summaryrefslogtreecommitdiff
path: root/spec/ruby/library/stringio/shared/eof.rb
AgeCommit message (Collapse)Author
2017-09-20Move spec/rubyspec to spec/ruby for consistencyeregon
* Other ruby implementations use the spec/ruby directory. [Misc #13792] [ruby-core:82287] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
d class='rem' style='width: 0.0%;'/> -rw-r--r--.document7
-rw-r--r--.gdbinit10
-rw-r--r--.git-blame-ignore-revs23
-rw-r--r--.github/dependabot.yml6
-rw-r--r--.github/workflows/baseruby.yml61
-rw-r--r--.github/workflows/bundled_gems.yml166
-rw-r--r--.github/workflows/check_dependencies.yml45
-rw-r--r--.github/workflows/check_misc.yml20
-rw-r--r--.github/workflows/codeql-analysis.yml52
-rw-r--r--.github/workflows/compilers.yml343
-rw-r--r--.github/workflows/macos.yml86
-rw-r--r--.github/workflows/mingw.yml166
-rw-r--r--.github/workflows/mjit-bindgen.yml104
-rw-r--r--.github/workflows/mjit.yml80
-rw-r--r--.github/workflows/publish.yml18
-rw-r--r--.github/workflows/scorecards.yml72
-rw-r--r--.github/workflows/spec_guards.yml51
-rw-r--r--.github/workflows/ubuntu.yml121
-rw-r--r--.github/workflows/wasm.yml146
-rw-r--r--.github/workflows/windows.yml163
-rw-r--r--.github/workflows/yjit-ubuntu.yml170
-rw-r--r--.gitignore24
-rw-r--r--.indent.pro32
-rw-r--r--.rdoc_options4
-rw-r--r--.travis.yml228
-rw-r--r--CONTRIBUTING.md6
-rw-r--r--LEGAL90
-rw-r--r--NEWS.md888
-rw-r--r--README.ja.md5
-rw-r--r--README.md145
-rw-r--r--addr2line.c498
-rw-r--r--array.c3395
-rw-r--r--array.rb10
-rw-r--r--ast.c114
-rw-r--r--ast.rb110
-rwxr-xr-xautogen.sh10
-rwxr-xr-xbasictest/test.rb3
-rw-r--r--benchmark/README.md8
-rw-r--r--benchmark/array_sample.yml4
-rw-r--r--benchmark/array_sort_int.yml15
-rw-r--r--benchmark/attr_accessor.yml29
-rw-r--r--benchmark/buffer_each.yml27
-rw-r--r--benchmark/buffer_get.yml25
-rw-r--r--benchmark/cgi_escape_html.yml37
-rw-r--r--benchmark/constant_invalidation.rb22
-rw-r--r--benchmark/enum_minmax.yml25
-rw-r--r--benchmark/enum_sort.yml15
-rw-r--r--benchmark/erb_escape_html.yml31
-rw-r--r--benchmark/hash_aref_array.rb5
-rw-r--r--benchmark/io_write.rb22
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit.rb10
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit_exec.rb237
-rw-r--r--benchmark/marshal_dump_load_integer.yml22
-rw-r--r--benchmark/masgn.yml26
-rw-r--r--benchmark/mjit_exec_jt2jt.yml6
-rw-r--r--benchmark/mjit_exec_vm2jt.yml6
-rw-r--r--benchmark/mjit_exec_vm2vm.yml6
-rw-r--r--benchmark/module_eqq.yml27
-rw-r--r--benchmark/numeric_methods.yml16
-rw-r--r--benchmark/range_min.yml2
-rw-r--r--benchmark/so_nbody.rb58
-rw-r--r--benchmark/string_concat.yml45
-rw-r--r--benchmark/time_at.yml7
-rw-r--r--benchmark/time_new.yml4
-rw-r--r--benchmark/time_now.yml3
-rw-r--r--benchmark/time_parse.yml10
-rw-r--r--benchmark/vm_const.yml6
-rw-r--r--benchmark/vm_dstr_ary.rb6
-rw-r--r--benchmark/vm_dstr_bool.rb7
-rw-r--r--benchmark/vm_dstr_class_module.rb10
-rw-r--r--benchmark/vm_dstr_digit.rb7
-rw-r--r--benchmark/vm_dstr_int.rb5
-rw-r--r--benchmark/vm_dstr_nil.rb6
-rw-r--r--benchmark/vm_dstr_obj.rb6
-rw-r--r--benchmark/vm_dstr_obj_def.rb8
-rw-r--r--benchmark/vm_dstr_str.rb6
-rw-r--r--benchmark/vm_dstr_sym.rb6
-rw-r--r--benchmark/vm_freezeobj.yml6
-rw-r--r--benchmark/vm_ivar_embedded_obj_init.yml14
-rw-r--r--benchmark/vm_ivar_extended_obj_init.yml (renamed from benchmark/vm_ivar_init.yml)8
-rw-r--r--benchmark/vm_ivar_generic_get.yml17
-rw-r--r--benchmark/vm_ivar_generic_set.yml14
-rw-r--r--benchmark/vm_ivar_get.yml37
-rw-r--r--benchmark/vm_ivar_get_unintialized.yml12
-rw-r--r--benchmark/vm_ivar_lazy_set.yml12
-rw-r--r--benchmark/vm_ivar_of_class.yml12
-rw-r--r--benchmark/vm_ivar_of_class_set.yml11
-rw-r--r--benchmark/vm_ivar_set_on_instance.yml35
-rw-r--r--benchmark/vm_ivar_set_subclass.yml9
-rw-r--r--benchmark/vm_lvar_cond_set.yml8
-rw-r--r--bignum.c1244
-rwxr-xr-xbin/gem19
-rwxr-xr-xbootstraptest/runner.rb823
-rw-r--r--bootstraptest/test_attr.rb16
-rw-r--r--bootstraptest/test_autoload.rb30
-rw-r--r--bootstraptest/test_constant_cache.rb187
-rw-r--r--bootstraptest/test_eval.rb31
-rw-r--r--bootstraptest/test_insns.rb1
-rw-r--r--bootstraptest/test_io.rb5
-rw-r--r--bootstraptest/test_jump.rb4
-rw-r--r--bootstraptest/test_literal.rb7
-rw-r--r--bootstraptest/test_method.rb2
-rw-r--r--bootstraptest/test_ractor.rb233
-rw-r--r--bootstraptest/test_syntax.rb2
-rw-r--r--bootstraptest/test_thread.rb8
-rw-r--r--bootstraptest/test_yjit.rb3530
-rw-r--r--bootstraptest/test_yjit_30k_ifelse.rb241023
-rw-r--r--bootstraptest/test_yjit_30k_methods.rb121018
-rw-r--r--bootstraptest/test_yjit_rust_port.rb422
-rw-r--r--builtin.h80
-rw-r--r--ccan/build_assert/build_assert.h12
-rw-r--r--ccan/check_type/check_type.h28
-rw-r--r--ccan/container_of/container_of.h52
-rw-r--r--ccan/list/list.h587
-rw-r--r--ccan/str/str.h9
-rw-r--r--class.c1357
-rw-r--r--common.mk3307
-rw-r--r--compar.c41
-rw-r--r--compile.c9275
-rw-r--r--complex.c857
-rw-r--r--configure.ac932
-rw-r--r--cont.c1042
-rw-r--r--coroutine/amd64/Context.h25
-rw-r--r--coroutine/arm64/Context.h25
-rw-r--r--coroutine/asyncify/Context.c10
-rw-r--r--coroutine/asyncify/Context.h93
-rw-r--r--coroutine/ppc/Context.S90
-rw-r--r--coroutine/ppc/Context.h58
-rw-r--r--coroutine/ppc64/Context.S89
-rw-r--r--coroutine/ppc64/Context.h57
-rw-r--r--coroutine/universal/Context.S6
-rw-r--r--coroutine/universal/Context.h6
-rw-r--r--cygwin/GNUmakefile.in38
-rw-r--r--darray.h179
-rw-r--r--debug.c378
-rw-r--r--debug_counter.c36
-rw-r--r--debug_counter.h47
-rw-r--r--defs/gmake.mk222
-rw-r--r--defs/id.def8
-rw-r--r--defs/keywords2
-rw-r--r--defs/lex.c.src2
-rw-r--r--dir.c1790
-rw-r--r--dir.rb118
-rw-r--r--dln.c456
-rw-r--r--dln_find.c246
-rw-r--r--dmyenc.c2
-rw-r--r--doc/.document7
-rw-r--r--doc/ChangeLog-0.60_to_1.110
-rw-r--r--doc/ChangeLog-1.9.330
-rw-r--r--doc/ChangeLog-2.0.08
-rw-r--r--doc/ChangeLog-2.3.015
-rw-r--r--doc/ChangeLog-2.4.04
-rw-r--r--doc/ChangeLog-YARV48
-rw-r--r--doc/NEWS/NEWS-1.8.7 (renamed from doc/NEWS-1.8.7)0
-rw-r--r--doc/NEWS/NEWS-1.9.1 (renamed from doc/NEWS-1.9.1)0
-rw-r--r--doc/NEWS/NEWS-1.9.2 (renamed from doc/NEWS-1.9.2)0
-rw-r--r--doc/NEWS/NEWS-1.9.3 (renamed from doc/NEWS-1.9.3)0
-rw-r--r--doc/NEWS/NEWS-2.0.0 (renamed from doc/NEWS-2.0.0)2
-rw-r--r--doc/NEWS/NEWS-2.1.0 (renamed from doc/NEWS-2.1.0)0
-rw-r--r--doc/NEWS/NEWS-2.2.0 (renamed from doc/NEWS-2.2.0)0
-rw-r--r--doc/NEWS/NEWS-2.3.0 (renamed from doc/NEWS-2.3.0)0
-rw-r--r--doc/NEWS/NEWS-2.4.0 (renamed from doc/NEWS-2.4.0)0
-rw-r--r--doc/NEWS/NEWS-2.5.0 (renamed from doc/NEWS-2.5.0)2
-rw-r--r--doc/NEWS/NEWS-2.6.0 (renamed from doc/NEWS-2.6.0)0
-rw-r--r--doc/NEWS/NEWS-2.7.0 (renamed from doc/NEWS-2.7.0)10
-rw-r--r--doc/NEWS/NEWS-3.0.0.md (renamed from doc/NEWS-3.0.0.md)14
-rw-r--r--doc/NEWS/NEWS-3.1.0.md660
-rw-r--r--doc/bsearch.rdoc120
-rw-r--r--doc/case_mapping.rdoc116
-rw-r--r--doc/character_selectors.rdoc97
-rw-r--r--doc/command_injection.rdoc29
-rw-r--r--doc/contributing.md12
-rw-r--r--doc/contributing.rdoc428
-rw-r--r--doc/contributing/building_ruby.md172
-rw-r--r--doc/contributing/documentation_guide.md435
-rw-r--r--doc/contributing/making_changes_to_ruby.md28
-rw-r--r--doc/contributing/making_changes_to_stdlibs.md49
-rw-r--r--doc/contributing/reporting_issues.md91
-rw-r--r--doc/contributing/testing_ruby.md138
-rw-r--r--doc/date/calendars.rdoc62
-rw-r--r--doc/documentation_guide.rdoc281
-rw-r--r--doc/encodings.rdoc479
-rw-r--r--doc/examples/files.rdoc26
-rw-r--r--doc/extension.ja.rdoc65
-rw-r--r--doc/extension.rdoc114
-rw-r--r--doc/fiber.md26
-rw-r--r--doc/format_specifications.rdoc348
-rw-r--r--doc/implicit_conversion.rdoc23
-rw-r--r--doc/irb/irb.rd.ja11
-rw-r--r--doc/maintainers.rdoc31
-rw-r--r--doc/make_cheatsheet.md124
-rw-r--r--doc/marshal.rdoc2
-rw-r--r--doc/matchdata/begin.rdoc30
-rw-r--r--doc/matchdata/end.rdoc30
-rw-r--r--doc/matchdata/offset.rdoc31
-rw-r--r--doc/math/math.rdoc117
-rw-r--r--doc/memory_view.md6
-rw-r--r--doc/mjit/mjit.md39
-rw-r--r--doc/net-http/examples.rdoc31
-rw-r--r--doc/net-http/included_getters.rdoc3
-rw-r--r--doc/optparse/.document1
-rw-r--r--doc/optparse/creates_option.rdoc4
-rw-r--r--doc/optparse/option_params.rdoc6
-rw-r--r--doc/optparse/tutorial.rdoc4
-rw-r--r--doc/packed_data.rdoc590
-rw-r--r--doc/ractor.md45
-rw-r--r--doc/rdoc/markup_reference.rb1257
-rw-r--r--doc/regexp.rdoc63
-rw-r--r--doc/standard_library.rdoc5
-rw-r--r--doc/strftime_formatting.rdoc527
-rw-r--r--doc/string/b.rdoc14
-rw-r--r--doc/string/bytes.rdoc6
-rw-r--r--doc/string/bytesize.rdoc11
-rw-r--r--doc/string/center.rdoc16
-rw-r--r--doc/string/chars.rdoc5
-rw-r--r--doc/string/chomp.rdoc29
-rw-r--r--doc/string/chop.rdoc16
-rw-r--r--doc/string/codepoints.rdoc6
-rw-r--r--doc/string/delete_prefix.rdoc8
-rw-r--r--doc/string/delete_suffix.rdoc8
-rw-r--r--doc/string/each_byte.rdoc17
-rw-r--r--doc/string/each_char.rdoc17
-rw-r--r--doc/string/each_codepoint.rdoc18
-rw-r--r--doc/string/each_grapheme_cluster.rdoc12
-rw-r--r--doc/string/each_line.rdoc60
-rw-r--r--doc/string/end_with_p.rdoc11
-rw-r--r--doc/string/force_encoding.rdoc20
-rw-r--r--doc/string/grapheme_clusters.rdoc6
-rw-r--r--doc/string/index.rdoc38
-rw-r--r--doc/string/length.rdoc13
-rw-r--r--doc/string/ljust.rdoc16
-rw-r--r--doc/string/new.rdoc51
-rw-r--r--doc/string/ord.rdoc6
-rw-r--r--doc/string/partition.rdoc24
-rw-r--r--doc/string/rjust.rdoc16
-rw-r--r--doc/string/rpartition.rdoc24
-rw-r--r--doc/string/scrub.rdoc25
-rw-r--r--doc/string/split.rdoc86
-rw-r--r--doc/string/start_with_p.rdoc18
-rw-r--r--doc/string/sum.rdoc11
-rw-r--r--doc/symbol/casecmp.rdoc27
-rw-r--r--doc/symbol/casecmp_p.rdoc26
-rw-r--r--doc/syntax/assignment.rdoc6
-rw-r--r--doc/syntax/calling_methods.rdoc18
-rw-r--r--doc/syntax/comments.rdoc6
-rw-r--r--doc/syntax/control_expressions.rdoc26
-rw-r--r--doc/syntax/literals.rdoc281
-rw-r--r--doc/syntax/methods.rdoc23
-rw-r--r--doc/syntax/modules_and_classes.rdoc4
-rw-r--r--doc/syntax/pattern_matching.rdoc8
-rw-r--r--doc/syntax/precedence.rdoc2
-rw-r--r--doc/time/in.rdoc7
-rw-r--r--doc/time/mon-min.rdoc8
-rw-r--r--doc/time/msec.rdoc2
-rw-r--r--doc/time/nsec.rdoc2
-rw-r--r--doc/time/sec.rdoc2
-rw-r--r--doc/time/sec_i.rdoc1
-rw-r--r--doc/time/usec.rdoc2
-rw-r--r--doc/time/year.rdoc1
-rw-r--r--doc/time/zone_and_in.rdoc8
-rw-r--r--doc/timezones.rdoc108
-rw-r--r--doc/transcode.rdoc52
-rw-r--r--doc/yjit/yjit.md417
-rw-r--r--doc/yjit/yjit_hacking.md75
-rw-r--r--enc/Makefile.in4
-rw-r--r--enc/ascii.c6
-rw-r--r--enc/cesu_8.c23
-rw-r--r--enc/depend5901
-rw-r--r--enc/encdb.c2
-rw-r--r--enc/encinit.c.erb1
-rw-r--r--enc/jis/props.h.blt4
-rw-r--r--enc/jis/props.kwd2
-rw-r--r--enc/jis/props.src2
-rwxr-xr-xenc/make_encmake.rb2
-rw-r--r--enc/trans/newline.trans20
-rw-r--r--enc/trans/transdb.c2
-rw-r--r--enc/unicode/15.0.0/casefold.h (renamed from enc/unicode/13.0.0/casefold.h)6053
-rw-r--r--enc/unicode/15.0.0/name2ctype.h (renamed from enc/unicode/13.0.0/name2ctype.h)7239
-rw-r--r--enc/utf_16_32.h2
-rw-r--r--encindex.h6
-rw-r--r--encoding.c788
-rw-r--r--enum.c2477
-rw-r--r--enumerator.c993
-rw-r--r--error.c1135
-rw-r--r--eval.c1210
-rw-r--r--eval_error.c565
-rw-r--r--eval_intern.h47
-rw-r--r--eval_jump.c38
-rw-r--r--ext/-test-/RUBY_ALIGNOF/depend2
-rw-r--r--ext/-test-/abi/abi.c11
-rw-r--r--ext/-test-/abi/extconf.rb4
-rw-r--r--ext/-test-/arith_seq/beg_len_step/beg_len_step.c19
-rw-r--r--ext/-test-/arith_seq/beg_len_step/depend161
-rw-r--r--ext/-test-/arith_seq/beg_len_step/extconf.rb2
-rw-r--r--ext/-test-/arith_seq/extract/depend26
-rw-r--r--ext/-test-/array/concat/depend162
-rw-r--r--ext/-test-/array/concat/extconf.rb2
-rw-r--r--ext/-test-/array/concat/to_ary_concat.c38
-rw-r--r--ext/-test-/array/resize/depend26
-rw-r--r--ext/-test-/auto_ext.rb1
-rw-r--r--ext/-test-/bignum/depend194
-rw-r--r--ext/-test-/bug-14834/depend28
-rw-r--r--ext/-test-/bug-3571/depend26
-rw-r--r--ext/-test-/bug-5832/depend26
-rw-r--r--ext/-test-/bug_reporter/depend26
-rw-r--r--ext/-test-/class/depend52
-rw-r--r--ext/-test-/cxxanyargs/depend12
-rw-r--r--ext/-test-/debug/depend82
-rw-r--r--ext/-test-/debug/inspector.c14
-rw-r--r--ext/-test-/debug/profile_frames.c27
-rw-r--r--ext/-test-/dln/empty/depend159
-rw-r--r--ext/-test-/dln/empty/empty.c2
-rw-r--r--ext/-test-/econv/append.c15
-rw-r--r--ext/-test-/econv/extconf.rb3
-rw-r--r--ext/-test-/econv/init.c11
-rw-r--r--ext/-test-/enumerator_kw/depend26
-rw-r--r--ext/-test-/enumerator_kw/enumerator_kw.c3
-rw-r--r--ext/-test-/eval/eval.c13
-rw-r--r--ext/-test-/eval/extconf.rb2
-rw-r--r--ext/-test-/exception/depend115
-rw-r--r--ext/-test-/fatal/depend26
-rw-r--r--ext/-test-/file/depend100
-rw-r--r--ext/-test-/file/fs.c16
-rw-r--r--ext/-test-/float/depend52
-rw-r--r--ext/-test-/funcall/depend26
-rw-r--r--ext/-test-/funcall/funcall.c12
-rw-r--r--ext/-test-/gvl/call_without_gvl/call_without_gvl.c2
-rw-r--r--ext/-test-/gvl/call_without_gvl/depend26
-rw-r--r--ext/-test-/hash/depend52
-rw-r--r--ext/-test-/integer/depend81
-rw-r--r--ext/-test-/iseq_load/depend26
-rw-r--r--ext/-test-/iter/depend78
-rw-r--r--ext/-test-/load/dot.dot/depend159
-rw-r--r--ext/-test-/load/dot.dot/dot.dot.c2
-rw-r--r--ext/-test-/load/protect/depend26
-rw-r--r--ext/-test-/marshal/compat/depend26
-rw-r--r--ext/-test-/marshal/internal_ivar/depend26
-rw-r--r--ext/-test-/marshal/internal_ivar/internal_ivar.c5
-rw-r--r--ext/-test-/marshal/usr/depend26
-rw-r--r--ext/-test-/memory_status/depend2
-rw-r--r--ext/-test-/memory_status/memory_status.c12
-rw-r--r--ext/-test-/memory_view/depend2
-rw-r--r--ext/-test-/method/depend52
-rw-r--r--ext/-test-/notimplement/depend26
-rw-r--r--ext/-test-/num2int/depend26
-rw-r--r--ext/-test-/num2int/num2int.c26
-rw-r--r--ext/-test-/path_to_class/depend26
-rw-r--r--ext/-test-/popen_deadlock/depend27
-rw-r--r--ext/-test-/postponed_job/depend28
-rw-r--r--ext/-test-/postponed_job/postponed_job.c31
-rw-r--r--ext/-test-/printf/depend37
-rw-r--r--ext/-test-/printf/printf.c64
-rw-r--r--ext/-test-/proc/depend78
-rw-r--r--ext/-test-/proc/super.c2
-rw-r--r--ext/-test-/random/bad_version.c135
-rw-r--r--ext/-test-/random/depend168
-rw-r--r--ext/-test-/random/loop.c1
-rw-r--r--ext/-test-/rational/depend30
-rw-r--r--ext/-test-/rb_call_super_kw/depend26
-rw-r--r--ext/-test-/rb_call_super_kw/rb_call_super_kw.c3
-rw-r--r--ext/-test-/recursion/depend26
-rw-r--r--ext/-test-/regexp/depend52
-rw-r--r--ext/-test-/scan_args/depend26
-rw-r--r--ext/-test-/st/foreach/depend26
-rw-r--r--ext/-test-/st/foreach/foreach.c100
-rw-r--r--ext/-test-/st/numhash/depend26
-rw-r--r--ext/-test-/st/numhash/numhash.c16
-rw-r--r--ext/-test-/st/update/depend26
-rw-r--r--ext/-test-/st/update/update.c12
-rw-r--r--ext/-test-/string/capacity.c9
-rw-r--r--ext/-test-/string/coderange.c8
-rw-r--r--ext/-test-/string/cstr.c26
-rw-r--r--ext/-test-/string/depend116
-rw-r--r--ext/-test-/string/fstring.c4
-rw-r--r--ext/-test-/string/qsort.c14
-rw-r--r--ext/-test-/string/set_len.c10
-rw-r--r--ext/-test-/struct/depend104
-rw-r--r--ext/-test-/struct/member.c2
-rw-r--r--ext/-test-/symbol/depend52
-rw-r--r--ext/-test-/symbol/type.c6
-rw-r--r--ext/-test-/thread/instrumentation/depend164
-rw-r--r--ext/-test-/thread/instrumentation/extconf.rb2
-rw-r--r--ext/-test-/thread/instrumentation/instrumentation.c141
-rw-r--r--ext/-test-/thread_fd/depend26
-rw-r--r--ext/-test-/time/depend79
-rw-r--r--ext/-test-/tracepoint/depend56
-rw-r--r--ext/-test-/tracepoint/gc_hook.c26
-rw-r--r--ext/-test-/tracepoint/tracepoint.c54
-rw-r--r--ext/-test-/typeddata/depend26
-rw-r--r--ext/-test-/typeddata/typeddata.c2
-rw-r--r--ext/-test-/vm/at_exit.c12
-rw-r--r--ext/-test-/vm/depend26
-rw-r--r--ext/-test-/wait/depend174
-rw-r--r--ext/-test-/win32/console/attribute.c18
-rw-r--r--ext/-test-/win32/fd_setsize/fd_setsize.c10
-rw-r--r--ext/bigdecimal/bigdecimal.c2280
-rw-r--r--ext/bigdecimal/bigdecimal.gemspec14
-rw-r--r--ext/bigdecimal/bigdecimal.h48
-rw-r--r--ext/bigdecimal/depend4
-rw-r--r--ext/bigdecimal/extconf.rb9
-rw-r--r--ext/bigdecimal/lib/bigdecimal/jacobian.rb6
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb6
-rw-r--r--ext/bigdecimal/missing.h51
-rw-r--r--ext/cgi/escape/depend37
-rw-r--r--ext/cgi/escape/escape.c363
-rw-r--r--ext/continuation/depend26
-rw-r--r--ext/coverage/coverage.c307
-rw-r--r--ext/coverage/depend6
-rw-r--r--ext/date/date.gemspec31
-rw-r--r--ext/date/date_core.c2218
-rw-r--r--ext/date/date_parse.c131
-rw-r--r--ext/date/date_strftime.c2
-rw-r--r--ext/date/date_strptime.c105
-rw-r--r--ext/date/depend137
-rw-r--r--ext/date/extconf.rb7
-rw-r--r--ext/date/lib/date.rb5
-rw-r--r--ext/date/prereq.mk7
-rw-r--r--ext/date/zonetab.h18
-rw-r--r--ext/date/zonetab.list2
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c2
-rw-r--r--ext/digest/bubblebabble/depend26
-rw-r--r--ext/digest/depend26
-rw-r--r--ext/digest/digest.c12
-rw-r--r--ext/digest/digest.gemspec45
-rw-r--r--ext/digest/digest.h2
-rw-r--r--ext/digest/digest_conf.rb2
-rw-r--r--ext/digest/extconf.rb2
-rw-r--r--ext/digest/lib/digest.rb18
-rw-r--r--ext/digest/lib/digest/loader.rb3
-rw-r--r--ext/digest/lib/digest/version.rb5
-rw-r--r--ext/digest/md5/depend5
-rw-r--r--ext/digest/md5/md5.c2
-rw-r--r--ext/digest/rmd160/depend4
-rw-r--r--ext/digest/sha1/depend5
-rw-r--r--ext/digest/sha2/depend5
-rw-r--r--ext/digest/sha2/lib/sha2.rb2
-rw-r--r--ext/digest/sha2/lib/sha2/loader.rb3
-rw-r--r--ext/digest/sha2/sha2.c2
-rw-r--r--ext/digest/sha2/sha2init.c2
-rw-r--r--ext/erb/escape/escape.c95
-rw-r--r--ext/erb/escape/extconf.rb7
-rw-r--r--ext/etc/depend11
-rw-r--r--ext/etc/etc.c133
-rw-r--r--ext/etc/etc.gemspec13
-rw-r--r--ext/etc/extconf.rb6
-rwxr-xr-xext/extmk.rb137
-rw-r--r--ext/fcntl/depend26
-rw-r--r--ext/fcntl/fcntl.c17
-rw-r--r--ext/fcntl/fcntl.gemspec2
-rw-r--r--ext/fiddle/closure.c135
-rw-r--r--ext/fiddle/conversions.c20
-rw-r--r--ext/fiddle/depend34
-rw-r--r--ext/fiddle/extconf.rb28
-rw-r--r--ext/fiddle/extlibs13
-rw-r--r--ext/fiddle/fiddle.c214
-rw-r--r--ext/fiddle/fiddle.gemspec7
-rw-r--r--ext/fiddle/fiddle.h21
-rw-r--r--ext/fiddle/handle.c59
-rw-r--r--ext/fiddle/lib/fiddle.rb35
-rw-r--r--ext/fiddle/lib/fiddle/closure.rb25
-rw-r--r--ext/fiddle/lib/fiddle/cparser.rb18
-rw-r--r--ext/fiddle/lib/fiddle/pack.rb35
-rw-r--r--ext/fiddle/lib/fiddle/struct.rb60
-rw-r--r--ext/fiddle/lib/fiddle/version.rb2
-rw-r--r--ext/io/console/console.c50
-rw-r--r--ext/io/console/depend13
-rw-r--r--ext/io/console/io-console.gemspec4
-rw-r--r--ext/io/console/win32_vk.inc327
-rw-r--r--ext/io/console/win32_vk.list2
-rw-r--r--ext/io/nonblock/depend37
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec16
-rw-r--r--ext/io/nonblock/nonblock.c67
-rw-r--r--ext/io/wait/depend38
-rw-r--r--ext/io/wait/extconf.rb31
-rw-r--r--ext/io/wait/io-wait.gemspec23
-rw-r--r--ext/io/wait/wait.c278
-rw-r--r--ext/json/VERSION2
-rw-r--r--ext/json/generator/depend37
-rw-r--r--ext/json/generator/generator.c4
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/depend37
-rw-r--r--ext/json/parser/extconf.rb4
-rw-r--r--ext/json/parser/parser.c23
-rw-r--r--ext/json/parser/parser.rl23
-rw-r--r--ext/monitor/depend26
-rw-r--r--ext/nkf/depend37
-rw-r--r--ext/nkf/nkf-utf8/nkf.c14
-rw-r--r--ext/nkf/nkf.c90
-rw-r--r--ext/nkf/nkf.gemspec2
-rw-r--r--ext/objspace/depend54
-rw-r--r--ext/objspace/lib/objspace.rb97
-rw-r--r--ext/objspace/object_tracing.c170
-rw-r--r--ext/objspace/objspace.c424
-rw-r--r--ext/objspace/objspace_dump.c280
-rw-r--r--ext/openssl/History.md260
-rw-r--r--ext/openssl/depend385
-rw-r--r--ext/openssl/extconf.rb97
-rw-r--r--ext/openssl/lib/openssl/buffering.rb12
-rw-r--r--ext/openssl/lib/openssl/pkey.rb70
-rw-r--r--ext/openssl/lib/openssl/ssl.rb17
-rw-r--r--ext/openssl/lib/openssl/version.rb2
-rw-r--r--ext/openssl/lib/openssl/x509.rb18
-rw-r--r--ext/openssl/openssl.gemspec4
-rw-r--r--ext/openssl/openssl_missing.c3
-rw-r--r--ext/openssl/openssl_missing.h29
-rw-r--r--ext/openssl/ossl.c69
-rw-r--r--ext/openssl/ossl.h31
-rw-r--r--ext/openssl/ossl_asn1.c39
-rw-r--r--ext/openssl/ossl_bn.c222
-rw-r--r--ext/openssl/ossl_cipher.c11
-rw-r--r--ext/openssl/ossl_config.c2
-rw-r--r--ext/openssl/ossl_digest.c14
-rw-r--r--ext/openssl/ossl_engine.c3
-rw-r--r--ext/openssl/ossl_hmac.c16
-rw-r--r--ext/openssl/ossl_kdf.c6
-rw-r--r--ext/openssl/ossl_ocsp.c6
-rw-r--r--ext/openssl/ossl_pkcs12.c24
-rw-r--r--ext/openssl/ossl_pkey.c162
-rw-r--r--ext/openssl/ossl_pkey.h34
-rw-r--r--ext/openssl/ossl_pkey_dh.c96
-rw-r--r--ext/openssl/ossl_pkey_dsa.c111
-rw-r--r--ext/openssl/ossl_pkey_ec.c192
-rw-r--r--ext/openssl/ossl_pkey_rsa.c112
-rw-r--r--ext/openssl/ossl_ssl.c619
-rw-r--r--ext/openssl/ossl_ssl_session.c4
-rw-r--r--ext/openssl/ossl_ts.c44
-rw-r--r--ext/openssl/ossl_x509cert.c6
-rw-r--r--ext/openssl/ossl_x509crl.c6
-rw-r--r--ext/openssl/ossl_x509name.c11
-rw-r--r--ext/openssl/ossl_x509req.c6
-rw-r--r--ext/openssl/ossl_x509revoked.c6
-rw-r--r--ext/openssl/ossl_x509store.c51
-rw-r--r--ext/openssl/ruby_missing.h24
-rw-r--r--ext/pathname/depend37
-rw-r--r--ext/pathname/lib/pathname.rb17
-rw-r--r--ext/pathname/pathname.c20
-rw-r--r--ext/pathname/pathname.gemspec4
-rw-r--r--ext/psych/.gitignore1
-rw-r--r--ext/psych/depend114
-rw-r--r--ext/psych/extconf.rb70
-rw-r--r--ext/psych/lib/psych.rb50
-rw-r--r--ext/psych/lib/psych/class_loader.rb4
-rw-r--r--ext/psych/lib/psych/core_ext.rb2
-rw-r--r--ext/psych/lib/psych/exception.rb14
-rw-r--r--ext/psych/lib/psych/handlers/document_stream.rb2
-rw-r--r--ext/psych/lib/psych/handlers/recorder.rb2
-rw-r--r--ext/psych/lib/psych/json/stream.rb4
-rw-r--r--ext/psych/lib/psych/json/tree_builder.rb2
-rw-r--r--ext/psych/lib/psych/nodes.rb14
-rw-r--r--ext/psych/lib/psych/nodes/node.rb8
-rw-r--r--ext/psych/lib/psych/parser.rb13
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb38
-rw-r--r--ext/psych/lib/psych/syntax_error.rb2
-rw-r--r--ext/psych/lib/psych/tree_builder.rb2
-rw-r--r--ext/psych/lib/psych/versions.rb4
-rw-r--r--ext/psych/lib/psych/visitors.rb12
-rw-r--r--ext/psych/lib/psych/visitors/json_tree.rb2
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb18
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb24
-rw-r--r--ext/psych/psych.gemspec5
-rw-r--r--ext/psych/psych_parser.c52
-rw-r--r--ext/psych/yaml/api.c1393
-rw-r--r--ext/psych/yaml/config.h80
-rw-r--r--ext/psych/yaml/dumper.c394
-rw-r--r--ext/psych/yaml/emitter.c2358
-rw-r--r--ext/psych/yaml/loader.c544
-rw-r--r--ext/psych/yaml/parser.c1375
-rw-r--r--ext/psych/yaml/reader.c469
-rw-r--r--ext/psych/yaml/scanner.c3598
-rw-r--r--ext/psych/yaml/writer.c141
-rw-r--r--ext/psych/yaml/yaml.h1985
-rw-r--r--ext/psych/yaml/yaml_private.h688
-rw-r--r--ext/pty/depend40
-rw-r--r--ext/pty/extconf.rb6
-rw-r--r--ext/pty/lib/expect.rb16
-rw-r--r--ext/pty/pty.c160
-rw-r--r--ext/racc/cparse/cparse.c4
-rw-r--r--ext/racc/cparse/depend26
-rw-r--r--ext/rbconfig/sizeof/depend52
-rw-r--r--ext/readline/depend11
-rw-r--r--ext/readline/readline-ext.gemspec6
-rw-r--r--ext/readline/readline.c5
-rw-r--r--ext/ripper/depend20
-rw-r--r--ext/ripper/eventids2.c19
-rw-r--r--ext/ripper/extconf.rb3
-rw-r--r--ext/ripper/lib/ripper/lexer.rb91
-rw-r--r--ext/ripper/tools/preproc.rb2
-rw-r--r--ext/socket/addrinfo.h36
-rw-r--r--ext/socket/ancdata.c274
-rw-r--r--ext/socket/basicsocket.c78
-rw-r--r--ext/socket/constants.c6
-rw-r--r--ext/socket/depend180
-rw-r--r--ext/socket/extconf.rb30
-rw-r--r--ext/socket/getaddrinfo.c898
-rw-r--r--ext/socket/getnameinfo.c226
-rw-r--r--ext/socket/ifaddr.c9
-rw-r--r--ext/socket/init.c156
-rw-r--r--ext/socket/ipsocket.c190
-rw-r--r--ext/socket/lib/socket.rb9
-rw-r--r--ext/socket/mkconstants.rb40
-rw-r--r--ext/socket/option.c98
-rw-r--r--ext/socket/raddrinfo.c278
-rw-r--r--ext/socket/rubysocket.h24
-rw-r--r--ext/socket/socket.c461
-rw-r--r--ext/socket/sockssocket.c4
-rw-r--r--ext/socket/tcpserver.c2
-rw-r--r--ext/socket/tcpsocket.c18
-rw-r--r--ext/socket/udpsocket.c30
-rw-r--r--ext/socket/unixserver.c8
-rw-r--r--ext/socket/unixsocket.c148
-rw-r--r--ext/stringio/depend37
-rw-r--r--ext/stringio/stringio.c378
-rw-r--r--ext/stringio/stringio.gemspec17
-rw-r--r--ext/strscan/depend37
-rw-r--r--ext/strscan/extconf.rb11
-rw-r--r--ext/strscan/strscan.c178
-rw-r--r--ext/strscan/strscan.gemspec23
-rw-r--r--ext/syslog/depend26
-rw-r--r--ext/syslog/syslog.c22
-rw-r--r--ext/syslog/syslog.gemspec2
-rw-r--r--ext/win32/lib/win32/registry.rb13
-rw-r--r--ext/win32/resolv/resolv.c18
-rw-r--r--ext/win32ole/win32ole.c170
-rw-r--r--ext/win32ole/win32ole.gemspec3
-rw-r--r--ext/win32ole/win32ole_event.c21
-rw-r--r--ext/win32ole/win32ole_method.c5
-rw-r--r--ext/win32ole/win32ole_param.c3
-rw-r--r--ext/win32ole/win32ole_record.c3
-rw-r--r--ext/win32ole/win32ole_type.c3
-rw-r--r--ext/win32ole/win32ole_typelib.c19
-rw-r--r--ext/win32ole/win32ole_variable.c4
-rw-r--r--ext/win32ole/win32ole_variant.c3
-rw-r--r--ext/zlib/depend37
-rw-r--r--ext/zlib/extconf.rb2
-rw-r--r--ext/zlib/extlibs8
-rw-r--r--ext/zlib/win32/zlib-1.2.11-mswin.patch95
-rw-r--r--ext/zlib/zlib.c167
-rw-r--r--file.c3454
-rw-r--r--gc.c8184
-rw-r--r--gc.h39
-rw-r--r--gc.rb267
-rw-r--r--gem_prelude.rb11
-rw-r--r--gems/bundled_gems29
-rw-r--r--gems/lib/core_assertions.rb1
-rw-r--r--gems/lib/envutil.rb1
-rw-r--r--gems/lib/rake/extensiontask.rb12
-rw-r--r--goruby.c32
-rw-r--r--hash.c2026
-rw-r--r--hrtime.h59
-rw-r--r--id_table.c161
-rw-r--r--id_table.h9
-rw-r--r--include/ruby.h1
-rw-r--r--include/ruby/assert.h4
-rw-r--r--include/ruby/atomic.h990
-rw-r--r--include/ruby/backward.h53
-rw-r--r--include/ruby/backward/2/assume.h27
-rw-r--r--include/ruby/backward/2/attributes.h3
-rw-r--r--include/ruby/backward/2/bool.h5
-rw-r--r--include/ruby/backward/2/gcc_version_since.h5
-rw-r--r--include/ruby/backward/2/inttypes.h3
-rw-r--r--include/ruby/backward/2/limits.h5
-rw-r--r--include/ruby/backward/2/long_long.h12
-rw-r--r--include/ruby/backward/2/r_cast.h5
-rw-r--r--include/ruby/backward/2/rmodule.h3
-rw-r--r--include/ruby/backward/2/stdalign.h6
-rw-r--r--include/ruby/backward/2/stdarg.h24
-rw-r--r--include/ruby/backward/cxxanyargs.hpp63
-rw-r--r--include/ruby/debug.h580
-rw-r--r--include/ruby/defines.h11
-rw-r--r--include/ruby/encoding.h410
-rw-r--r--include/ruby/fiber/scheduler.h335
-rw-r--r--include/ruby/internal/abi.h58
-rw-r--r--include/ruby/internal/anyargs.h45
-rw-r--r--include/ruby/internal/arithmetic.h5
-rw-r--r--include/ruby/internal/arithmetic/char.h31
-rw-r--r--include/ruby/internal/arithmetic/double.h49
-rw-r--r--include/ruby/internal/arithmetic/fixnum.h32
-rw-r--r--include/ruby/internal/arithmetic/gid_t.h5
-rw-r--r--include/ruby/internal/arithmetic/int.h129
-rw-r--r--include/ruby/internal/arithmetic/intptr_t.h38
-rw-r--r--include/ruby/internal/arithmetic/long.h160
-rw-r--r--include/ruby/internal/arithmetic/long_long.h85
-rw-r--r--include/ruby/internal/arithmetic/mode_t.h5
-rw-r--r--include/ruby/internal/arithmetic/off_t.h5
-rw-r--r--include/ruby/internal/arithmetic/pid_t.h5
-rw-r--r--include/ruby/internal/arithmetic/short.h85
-rw-r--r--include/ruby/internal/arithmetic/size_t.h24
-rw-r--r--include/ruby/internal/arithmetic/st_data_t.h24
-rw-r--r--include/ruby/internal/arithmetic/uid_t.h5
-rw-r--r--include/ruby/internal/assume.h7
-rw-r--r--include/ruby/internal/attr/alloc_size.h2
-rw-r--r--include/ruby/internal/attr/artificial.h2
-rw-r--r--include/ruby/internal/attr/cold.h2
-rw-r--r--include/ruby/internal/attr/const.h2
-rw-r--r--include/ruby/internal/attr/constexpr.h2
-rw-r--r--include/ruby/internal/attr/deprecated.h10
-rw-r--r--include/ruby/internal/attr/diagnose_if.h2
-rw-r--r--include/ruby/internal/attr/enum_extensibility.h2
-rw-r--r--include/ruby/internal/attr/error.h2
-rw-r--r--include/ruby/internal/attr/flag_enum.h2
-rw-r--r--include/ruby/internal/attr/forceinline.h2
-rw-r--r--include/ruby/internal/attr/format.h2
-rw-r--r--include/ruby/internal/attr/maybe_unused.h2
-rw-r--r--include/ruby/internal/attr/noalias.h15
-rw-r--r--include/ruby/internal/attr/nodiscard.h4
-rw-r--r--include/ruby/internal/attr/noexcept.h2
-rw-r--r--include/ruby/internal/attr/noinline.h2
-rw-r--r--include/ruby/internal/attr/nonnull.h4
-rw-r--r--include/ruby/internal/attr/nonstring.h32
-rw-r--r--include/ruby/internal/attr/noreturn.h2
-rw-r--r--include/ruby/internal/attr/pure.h2
-rw-r--r--include/ruby/internal/attr/restrict.h2
-rw-r--r--include/ruby/internal/attr/returns_nonnull.h2
-rw-r--r--include/ruby/internal/attr/warning.h2
-rw-r--r--include/ruby/internal/attr/weakref.h2
-rw-r--r--include/ruby/internal/cast.h5
-rw-r--r--include/ruby/internal/compiler_is.h2
-rw-r--r--include/ruby/internal/compiler_is/apple.h5
-rw-r--r--include/ruby/internal/compiler_is/clang.h5
-rw-r--r--include/ruby/internal/compiler_is/gcc.h5
-rw-r--r--include/ruby/internal/compiler_is/intel.h5
-rw-r--r--include/ruby/internal/compiler_is/msvc.h5
-rw-r--r--include/ruby/internal/compiler_is/sunpro.h5
-rw-r--r--include/ruby/internal/compiler_since.h2
-rw-r--r--include/ruby/internal/config.h9
-rw-r--r--include/ruby/internal/constant_p.h3
-rw-r--r--include/ruby/internal/core.h2
-rw-r--r--include/ruby/internal/core/rarray.h345
-rw-r--r--include/ruby/internal/core/rbasic.h88
-rw-r--r--include/ruby/internal/core/rbignum.h33
-rw-r--r--include/ruby/internal/core/rclass.h62
-rw-r--r--include/ruby/internal/core/rdata.h225
-rw-r--r--include/ruby/internal/core/rfile.h17
-rw-r--r--include/ruby/internal/core/rhash.h112
-rw-r--r--include/ruby/internal/core/rmatch.h85
-rw-r--r--include/ruby/internal/core/robject.h124
-rw-r--r--include/ruby/internal/core/rregexp.h88
-rw-r--r--include/ruby/internal/core/rstring.h409
-rw-r--r--include/ruby/internal/core/rstruct.h58
-rw-r--r--include/ruby/internal/core/rtypeddata.h428
-rw-r--r--include/ruby/internal/ctype.h382
-rw-r--r--include/ruby/internal/dllexport.h28
-rw-r--r--include/ruby/internal/dosish.h28
-rw-r--r--include/ruby/internal/encoding/coderange.h202
-rw-r--r--include/ruby/internal/encoding/ctype.h258
-rw-r--r--include/ruby/internal/encoding/encoding.h1060
-rw-r--r--include/ruby/internal/encoding/pathname.h184
-rw-r--r--include/ruby/internal/encoding/re.h46
-rw-r--r--include/ruby/internal/encoding/sprintf.h78
-rw-r--r--include/ruby/internal/encoding/string.h346
-rw-r--r--include/ruby/internal/encoding/symbol.h100
-rw-r--r--include/ruby/internal/encoding/transcode.h562
-rw-r--r--include/ruby/internal/error.h568
-rw-r--r--include/ruby/internal/eval.h382
-rw-r--r--include/ruby/internal/event.h157
-rw-r--r--include/ruby/internal/fl_type.h658
-rw-r--r--include/ruby/internal/gc.h15
-rw-r--r--include/ruby/internal/glob.h88
-rw-r--r--include/ruby/internal/globals.h226
-rw-r--r--include/ruby/internal/has/attribute.h2
-rw-r--r--include/ruby/internal/has/builtin.h10
-rw-r--r--include/ruby/internal/has/c_attribute.h2
-rw-r--r--include/ruby/internal/has/cpp_attribute.h2
-rw-r--r--include/ruby/internal/has/declspec_attribute.h2
-rw-r--r--include/ruby/internal/has/extension.h2
-rw-r--r--include/ruby/internal/has/feature.h2
-rw-r--r--include/ruby/internal/has/warning.h2
-rw-r--r--include/ruby/internal/intern/array.h659
-rw-r--r--include/ruby/internal/intern/bignum.h815
-rw-r--r--include/ruby/internal/intern/class.h385
-rw-r--r--include/ruby/internal/intern/compar.h34
-rw-r--r--include/ruby/internal/intern/complex.h203
-rw-r--r--include/ruby/internal/intern/cont.h244
-rw-r--r--include/ruby/internal/intern/dir.h11
-rw-r--r--include/ruby/internal/intern/enum.h44
-rw-r--r--include/ruby/internal/intern/enumerator.h201
-rw-r--r--include/ruby/internal/intern/error.h249
-rw-r--r--include/ruby/internal/intern/eval.h183
-rw-r--r--include/ruby/internal/intern/file.h191
-rw-r--r--include/ruby/internal/intern/gc.h375
-rw-r--r--include/ruby/internal/intern/hash.h304
-rw-r--r--include/ruby/internal/intern/io.h635
-rw-r--r--include/ruby/internal/intern/load.h194
-rw-r--r--include/ruby/internal/intern/marshal.h83
-rw-r--r--include/ruby/internal/intern/numeric.h188
-rw-r--r--include/ruby/internal/intern/object.h499
-rw-r--r--include/ruby/internal/intern/parse.h155
-rw-r--r--include/ruby/internal/intern/proc.h336
-rw-r--r--include/ruby/internal/intern/process.h239
-rw-r--r--include/ruby/internal/intern/random.h74
-rw-r--r--include/ruby/internal/intern/range.h60
-rw-r--r--include/ruby/internal/intern/rational.h138
-rw-r--r--include/ruby/internal/intern/re.h227
-rw-r--r--include/ruby/internal/intern/ruby.h46
-rw-r--r--include/ruby/internal/intern/select.h38
-rw-r--r--include/ruby/internal/intern/select/largesize.h141
-rw-r--r--include/ruby/internal/intern/select/posix.h70
-rw-r--r--include/ruby/internal/intern/select/win32.h153
-rw-r--r--include/ruby/internal/intern/signal.h121
-rw-r--r--include/ruby/internal/intern/sprintf.h132
-rw-r--r--include/ruby/internal/intern/string.h1655
-rw-r--r--include/ruby/internal/intern/struct.h184
-rw-r--r--include/ruby/internal/intern/thread.h452
-rw-r--r--include/ruby/internal/intern/time.h122
-rw-r--r--include/ruby/internal/intern/variable.h630
-rw-r--r--include/ruby/internal/intern/vm.h403
-rw-r--r--include/ruby/internal/interpreter.h235
-rw-r--r--include/ruby/internal/iterator.h475
-rw-r--r--include/ruby/internal/memory.h433
-rw-r--r--include/ruby/internal/method.h180
-rw-r--r--include/ruby/internal/module.h154
-rw-r--r--include/ruby/internal/newobj.h152
-rw-r--r--include/ruby/internal/rgengc.h286
-rw-r--r--include/ruby/internal/scan_args.h157
-rw-r--r--include/ruby/internal/special_consts.h228
-rw-r--r--include/ruby/internal/static_assert.h2
-rw-r--r--include/ruby/internal/stdalign.h8
-rw-r--r--include/ruby/internal/stdbool.h4
-rw-r--r--include/ruby/internal/symbol.h256
-rw-r--r--include/ruby/internal/value.h71
-rw-r--r--include/ruby/internal/value_type.h171
-rw-r--r--include/ruby/internal/variable.h301
-rw-r--r--include/ruby/internal/warning_push.h41
-rw-r--r--include/ruby/internal/xmalloc.h110
-rw-r--r--include/ruby/io.h916
-rw-r--r--include/ruby/io/buffer.h92
-rw-r--r--include/ruby/memory_view.h202
-rw-r--r--include/ruby/missing.h156
-rw-r--r--include/ruby/onigmo.h15
-rw-r--r--include/ruby/ractor.h210
-rw-r--r--include/ruby/random.h281
-rw-r--r--include/ruby/re.h129
-rw-r--r--include/ruby/regex.h1
-rw-r--r--include/ruby/ruby.h216
-rw-r--r--include/ruby/st.h2
-rw-r--r--include/ruby/subst.h1
-rw-r--r--include/ruby/thread.h201
-rw-r--r--include/ruby/thread_native.h147
-rw-r--r--include/ruby/util.h195
-rw-r--r--include/ruby/version.h109
-rw-r--r--include/ruby/vm.h19
-rw-r--r--include/ruby/win32.h70
-rw-r--r--inits.c11
-rw-r--r--insns.def230
-rw-r--r--internal.h16
-rw-r--r--internal/array.h60
-rw-r--r--internal/basic_operators.h64
-rw-r--r--internal/bignum.h1
-rw-r--r--internal/bits.h1
-rw-r--r--internal/class.h83
-rw-r--r--internal/cmdlineopt.h61
-rw-r--r--internal/compar.h33
-rw-r--r--internal/compile.h2
-rw-r--r--internal/compilers.h1
-rw-r--r--internal/complex.h1
-rw-r--r--internal/cont.h11
-rw-r--r--internal/dir.h1
-rw-r--r--internal/enc.h1
-rw-r--r--internal/encoding.h5
-rw-r--r--internal/enum.h1
-rw-r--r--internal/enumerator.h1
-rw-r--r--internal/error.h37
-rw-r--r--internal/eval.h2
-rw-r--r--internal/file.h1
-rw-r--r--internal/fixnum.h3
-rw-r--r--internal/gc.h50
-rw-r--r--internal/hash.h5
-rw-r--r--internal/imemo.h8
-rw-r--r--internal/inits.h1
-rw-r--r--internal/io.h5
-rw-r--r--internal/load.h1
-rw-r--r--internal/loadpath.h1
-rw-r--r--internal/math.h1
-rw-r--r--internal/missing.h1
-rw-r--r--internal/numeric.h25
-rw-r--r--internal/object.h25
-rw-r--r--internal/parse.h5
-rw-r--r--internal/proc.h1
-rw-r--r--internal/process.h5
-rw-r--r--internal/ractor.h6
-rw-r--r--internal/random.h1
-rw-r--r--internal/range.h1
-rw-r--r--internal/rational.h1
-rw-r--r--internal/re.h1
-rw-r--r--internal/sanitizers.h1
-rw-r--r--internal/serial.h1
-rw-r--r--internal/signal.h1
-rw-r--r--internal/static_assert.h1
-rw-r--r--internal/string.h11
-rw-r--r--internal/struct.h1
-rw-r--r--internal/symbol.h3
-rw-r--r--internal/thread.h4
-rw-r--r--internal/time.h6
-rw-r--r--internal/transcode.h1
-rw-r--r--internal/util.h4
-rw-r--r--internal/variable.h16
-rw-r--r--internal/vm.h9
-rw-r--r--internal/warnings.h1
-rw-r--r--io.c9716
-rw-r--r--io_buffer.c3515
-rw-r--r--iseq.c2301
-rw-r--r--iseq.h110
-rw-r--r--kernel.rb6
-rw-r--r--lex.c.blt2
-rw-r--r--lib/.document26
-rw-r--r--lib/English.gemspec4
-rw-r--r--lib/abbrev.gemspec2
-rw-r--r--lib/base64.gemspec2
-rw-r--r--lib/base64.rb6
-rw-r--r--lib/benchmark/version.rb3
-rw-r--r--lib/bundler.rb160
-rw-r--r--lib/bundler/.document1
-rw-r--r--lib/bundler/build_metadata.rb2
-rw-r--r--lib/bundler/bundler.gemspec18
-rw-r--r--lib/bundler/cli.rb101
-rw-r--r--lib/bundler/cli/add.rb2
-rw-r--r--lib/bundler/cli/binstubs.rb8
-rw-r--r--lib/bundler/cli/check.rb2
-rw-r--r--lib/bundler/cli/common.rb6
-rw-r--r--lib/bundler/cli/config.rb11
-rw-r--r--lib/bundler/cli/console.rb4
-rw-r--r--lib/bundler/cli/doctor.rb13
-rw-r--r--lib/bundler/cli/exec.rb7
-rw-r--r--lib/bundler/cli/gem.rb121
-rw-r--r--lib/bundler/cli/info.rb35
-rw-r--r--lib/bundler/cli/init.rb8
-rw-r--r--lib/bundler/cli/install.rb62
-rw-r--r--lib/bundler/cli/issue.rb7
-rw-r--r--lib/bundler/cli/list.rb8
-rw-r--r--lib/bundler/cli/lock.rb13
-rw-r--r--lib/bundler/cli/open.rb10
-rw-r--r--lib/bundler/cli/outdated.rb21
-rw-r--r--lib/bundler/cli/platform.rb14
-rw-r--r--lib/bundler/cli/remove.rb3
-rw-r--r--lib/bundler/cli/show.rb2
-rw-r--r--lib/bundler/cli/update.rb12
-rw-r--r--lib/bundler/cli/viz.rb2
-rw-r--r--lib/bundler/compact_index_client.rb6
-rw-r--r--lib/bundler/compact_index_client/cache.rb11
-rw-r--r--lib/bundler/compact_index_client/updater.rb97
-rw-r--r--lib/bundler/constants.rb2
-rw-r--r--lib/bundler/current_ruby.rb24
-rw-r--r--lib/bundler/definition.rb634
-rw-r--r--lib/bundler/dep_proxy.rb55
-rw-r--r--lib/bundler/dependency.rb89
-rw-r--r--lib/bundler/digest.rb71
-rw-r--r--lib/bundler/dsl.rb79
-rw-r--r--lib/bundler/endpoint_specification.rb28
-rw-r--r--lib/bundler/env.rb6
-rw-r--r--lib/bundler/environment_preserver.rb10
-rw-r--r--lib/bundler/errors.rb44
-rw-r--r--lib/bundler/feature_flag.rb2
-rw-r--r--lib/bundler/fetcher.rb58
-rw-r--r--lib/bundler/fetcher/base.rb14
-rw-r--r--lib/bundler/fetcher/compact_index.rb34
-rw-r--r--lib/bundler/fetcher/dependency.rb8
-rw-r--r--lib/bundler/fetcher/downloader.rb9
-rw-r--r--lib/bundler/fetcher/index.rb29
-rw-r--r--lib/bundler/force_platform.rb18
-rw-r--r--lib/bundler/friendly_errors.rb63
-rw-r--r--lib/bundler/gem_helper.rb32
-rw-r--r--lib/bundler/gem_helpers.rb11
-rw-r--r--lib/bundler/gem_version_promoter.rb151
-rw-r--r--lib/bundler/gemdeps.rb29
-rw-r--r--lib/bundler/graph.rb6
-rw-r--r--lib/bundler/index.rb64
-rw-r--r--lib/bundler/injector.rb22
-rw-r--r--lib/bundler/inline.rb30
-rw-r--r--lib/bundler/installer.rb67
-rw-r--r--lib/bundler/installer/gem_installer.rb18
-rw-r--r--lib/bundler/installer/parallel_installer.rb38
-rw-r--r--lib/bundler/installer/standalone.rb68
-rw-r--r--lib/bundler/lazy_specification.rb127
-rw-r--r--lib/bundler/lockfile_generator.rb6
-rw-r--r--lib/bundler/lockfile_parser.rb56
-rw-r--r--lib/bundler/man/bundle-add.126
-rw-r--r--lib/bundler/man/bundle-add.1.ronn20
-rw-r--r--lib/bundler/man/bundle-binstubs.12
-rw-r--r--lib/bundler/man/bundle-cache.112
-rw-r--r--lib/bundler/man/bundle-cache.1.ronn11
-rw-r--r--lib/bundler/man/bundle-check.12
-rw-r--r--lib/bundler/man/bundle-clean.14
-rw-r--r--lib/bundler/man/bundle-clean.1.ronn2
-rw-r--r--lib/bundler/man/bundle-config.150
-rw-r--r--lib/bundler/man/bundle-config.1.ronn51
-rw-r--r--lib/bundler/man/bundle-console.153
-rw-r--r--lib/bundler/man/bundle-console.1.ronn44
-rw-r--r--lib/bundler/man/bundle-doctor.12
-rw-r--r--lib/bundler/man/bundle-exec.112
-rw-r--r--lib/bundler/man/bundle-exec.1.ronn12
-rw-r--r--lib/bundler/man/bundle-gem.164
-rw-r--r--lib/bundler/man/bundle-gem.1.ronn10
-rw-r--r--lib/bundler/man/bundle-help.113
-rw-r--r--lib/bundler/man/bundle-help.1.ronn12
-rw-r--r--lib/bundler/man/bundle-info.16
-rw-r--r--lib/bundler/man/bundle-info.1.ronn6
-rw-r--r--lib/bundler/man/bundle-init.16
-rw-r--r--lib/bundler/man/bundle-init.1.ronn2
-rw-r--r--lib/bundler/man/bundle-inject.17
-rw-r--r--lib/bundler/man/bundle-inject.1.ronn4
-rw-r--r--lib/bundler/man/bundle-install.137
-rw-r--r--lib/bundler/man/bundle-install.1.ronn39
-rw-r--r--lib/bundler/man/bundle-list.12
-rw-r--r--lib/bundler/man/bundle-lock.12
-rw-r--r--lib/bundler/man/bundle-open.124
-rw-r--r--lib/bundler/man/bundle-open.1.ronn10
-rw-r--r--lib/bundler/man/bundle-outdated.133
-rw-r--r--lib/bundler/man/bundle-outdated.1.ronn32
-rw-r--r--lib/bundler/man/bundle-platform.122
-rw-r--r--lib/bundler/man/bundle-platform.1.ronn21
-rw-r--r--lib/bundler/man/bundle-plugin.181
-rw-r--r--lib/bundler/man/bundle-plugin.1.ronn59
-rw-r--r--lib/bundler/man/bundle-pristine.12
-rw-r--r--lib/bundler/man/bundle-remove.12
-rw-r--r--lib/bundler/man/bundle-show.12
-rw-r--r--lib/bundler/man/bundle-update.14
-rw-r--r--lib/bundler/man/bundle-update.1.ronn3
-rw-r--r--lib/bundler/man/bundle-version.135
-rw-r--r--lib/bundler/man/bundle-version.1.ronn24
-rw-r--r--lib/bundler/man/bundle-viz.15
-rw-r--r--lib/bundler/man/bundle-viz.1.ronn2
-rw-r--r--lib/bundler/man/bundle.125
-rw-r--r--lib/bundler/man/bundle.1.ronn19
-rw-r--r--lib/bundler/man/gemfile.5210
-rw-r--r--lib/bundler/man/gemfile.5.ronn194
-rw-r--r--lib/bundler/man/index.txt4
-rw-r--r--lib/bundler/match_metadata.rb13
-rw-r--r--lib/bundler/match_platform.rb1
-rw-r--r--lib/bundler/match_remote_metadata.rb29
-rw-r--r--lib/bundler/mirror.rb12
-rw-r--r--lib/bundler/plugin.rb33
-rw-r--r--lib/bundler/plugin/api/source.rb13
-rw-r--r--lib/bundler/plugin/index.rb10
-rw-r--r--lib/bundler/plugin/installer.rb11
-rw-r--r--lib/bundler/plugin/installer/git.rb4
-rw-r--r--lib/bundler/plugin/installer/rubygems.rb8
-rw-r--r--lib/bundler/process_lock.rb2
-rw-r--r--lib/bundler/psyched_yaml.rb22
-rw-r--r--lib/bundler/remote_specification.rb12
-rw-r--r--lib/bundler/resolver.rb653
-rw-r--r--lib/bundler/resolver/base.rb107
-rw-r--r--lib/bundler/resolver/candidate.rb94
-rw-r--r--lib/bundler/resolver/incompatibility.rb15
-rw-r--r--lib/bundler/resolver/package.rb72
-rw-r--r--lib/bundler/resolver/root.rb25
-rw-r--r--lib/bundler/resolver/spec_group.rb114
-rw-r--r--lib/bundler/ruby_dsl.rb8
-rw-r--r--lib/bundler/ruby_version.rb29
-rw-r--r--lib/bundler/rubygems_ext.rb179
-rw-r--r--lib/bundler/rubygems_gem_installer.rb60
-rw-r--r--lib/bundler/rubygems_integration.rb158
-rw-r--r--lib/bundler/runtime.rb34
-rw-r--r--lib/bundler/safe_marshal.rb31
-rw-r--r--lib/bundler/self_manager.rb168
-rw-r--r--lib/bundler/settings.rb33
-rw-r--r--lib/bundler/setup.rb7
-rw-r--r--lib/bundler/shared_helpers.rb33
-rw-r--r--lib/bundler/source.rb13
-rw-r--r--lib/bundler/source/git.rb123
-rw-r--r--lib/bundler/source/git/git_proxy.rb323
-rw-r--r--lib/bundler/source/metadata.rb7
-rw-r--r--lib/bundler/source/path.rb14
-rw-r--r--lib/bundler/source/path/installer.rb23
-rw-r--r--lib/bundler/source/rubygems.rb320
-rw-r--r--lib/bundler/source/rubygems_aggregate.rb4
-rw-r--r--lib/bundler/source_list.rb57
-rw-r--r--lib/bundler/source_map.rb17
-rw-r--r--lib/bundler/spec_set.rb132
-rw-r--r--lib/bundler/stub_specification.rb8
-rw-r--r--lib/bundler/templates/Executable8
-rw-r--r--lib/bundler/templates/Executable.bundler17
-rw-r--r--lib/bundler/templates/Executable.standalone8
-rw-r--r--lib/bundler/templates/Gemfile2
-rw-r--r--lib/bundler/templates/gems.rb8
-rw-r--r--lib/bundler/templates/newgem/Cargo.toml.tt7
-rw-r--r--lib/bundler/templates/newgem/Gemfile.tt3
-rw-r--r--lib/bundler/templates/newgem/README.md.tt18
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt13
-rw-r--r--lib/bundler/templates/newgem/bin/console.tt4
-rw-r--r--lib/bundler/templates/newgem/circleci/config.yml.tt12
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt15
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt10
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt6
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt5
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/newgem.c.tt2
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt12
-rw-r--r--lib/bundler/templates/newgem/github/workflows/main.yml.tt27
-rw-r--r--lib/bundler/templates/newgem/gitignore.tt3
-rw-r--r--lib/bundler/templates/newgem/gitlab-ci.yml.tt17
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt15
-rw-r--r--lib/bundler/templates/newgem/sig/newgem.rbs.tt8
-rw-r--r--lib/bundler/templates/newgem/standard.yml.tt3
-rw-r--r--lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/travis.yml.tt6
-rw-r--r--lib/bundler/ui/rg_proxy.rb2
-rw-r--r--lib/bundler/ui/shell.rb49
-rw-r--r--lib/bundler/ui/silent.rb26
-rw-r--r--lib/bundler/uri_normalizer.rb23
-rw-r--r--lib/bundler/vendor/.document1
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool.rb4
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb6
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb1
-rw-r--r--lib/bundler/vendor/fileutils/lib/fileutils.rb1760
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo.rb11
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb57
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb88
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb255
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb36
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb66
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb62
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb63
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb61
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb126
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb46
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb36
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb164
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/errors.rb143
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb6
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb112
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb67
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb839
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb46
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/state.rb58
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb2
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub.rb31
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb20
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb189
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb182
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb150
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb43
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb121
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb45
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb19
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb60
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb105
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb3
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb129
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb411
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb248
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb178
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb8
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb12
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb3
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb13
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb20
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb28
-rw-r--r--lib/bundler/vendor/thor/lib/thor/util.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb2
-rw-r--r--lib/bundler/vendor/tmpdir/lib/tmpdir.rb154
-rw-r--r--lib/bundler/vendor/tsort/lib/tsort.rb452
-rw-r--r--lib/bundler/vendor/uri/lib/uri.rb5
-rw-r--r--lib/bundler/vendor/uri/lib/uri/common.rb80
-rw-r--r--lib/bundler/vendor/uri/lib/uri/file.rb8
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ftp.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/generic.rb34
-rw-r--r--lib/bundler/vendor/uri/lib/uri/http.rb42
-rw-r--r--lib/bundler/vendor/uri/lib/uri/https.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ldap.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ldaps.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/mailto.rb4
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb24
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb17
-rw-r--r--lib/bundler/vendor/uri/lib/uri/version.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ws.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/wss.rb3
-rw-r--r--lib/bundler/vendored_persistent.rb34
-rw-r--r--lib/bundler/vendored_pub_grub.rb (renamed from lib/bundler/vendored_molinillo.rb)2
-rw-r--r--lib/bundler/vendored_tsort.rb (renamed from lib/bundler/vendored_tmpdir.rb)2
-rw-r--r--lib/bundler/version.rb6
-rw-r--r--lib/bundler/version_ranges.rb122
-rw-r--r--lib/bundler/worker.rb12
-rw-r--r--lib/cgi.rb4
-rw-r--r--lib/cgi/cgi.gemspec19
-rw-r--r--lib/cgi/cookie.rb50
-rw-r--r--lib/cgi/core.rb45
-rw-r--r--lib/cgi/session.rb58
-rw-r--r--lib/cgi/session/pstore.rb16
-rw-r--r--lib/cgi/util.rb64
-rw-r--r--lib/csv.rb548
-rw-r--r--lib/csv/csv.gemspec2
-rw-r--r--lib/csv/fields_converter.rb13
-rw-r--r--lib/csv/input_record_separator.rb18
-rw-r--r--lib/csv/parser.rb345
-rw-r--r--lib/csv/row.rb231
-rw-r--r--lib/csv/table.rb626
-rw-r--r--lib/csv/version.rb2
-rw-r--r--lib/csv/writer.rb13
-rw-r--r--lib/debug.gemspec22
-rw-r--r--lib/debug.rb1106
-rw-r--r--lib/delegate.rb4
-rw-r--r--lib/delegate/delegate.gemspec2
-rw-r--r--lib/did_you_mean.rb59
-rw-r--r--lib/did_you_mean/core_ext/name_error.rb57
-rw-r--r--lib/did_you_mean/formatter.rb44
-rw-r--r--lib/did_you_mean/formatters/plain_formatter.rb35
-rw-r--r--lib/did_you_mean/formatters/verbose_formatter.rb49
-rw-r--r--lib/did_you_mean/spell_checker.rb18
-rw-r--r--lib/did_you_mean/spell_checkers/method_name_checker.rb10
-rw-r--r--lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb5
-rw-r--r--lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb20
-rw-r--r--lib/did_you_mean/spell_checkers/require_path_checker.rb5
-rw-r--r--lib/did_you_mean/verbose.rb6
-rw-r--r--lib/did_you_mean/version.rb2
-rw-r--r--lib/drb/drb.gemspec4
-rw-r--r--lib/drb/drb.rb11
-rw-r--r--lib/drb/extserv.rb4
-rw-r--r--lib/drb/extservm.rb6
-rw-r--r--lib/drb/version.rb2
-rw-r--r--lib/erb.gemspec13
-rw-r--r--lib/erb.rb579
-rw-r--r--lib/erb/compiler.rb471
-rw-r--r--lib/erb/def_method.rb46
-rw-r--r--lib/erb/util.rb62
-rw-r--r--lib/erb/version.rb2
-rw-r--r--lib/error_highlight/base.rb67
-rw-r--r--lib/error_highlight/core_ext.rb69
-rw-r--r--lib/error_highlight/formatter.rb8
-rw-r--r--lib/error_highlight/version.rb2
-rw-r--r--lib/fileutils.rb1715
-rw-r--r--lib/find.gemspec2
-rw-r--r--lib/forwardable.rb4
-rw-r--r--lib/forwardable/impl.rb3
-rw-r--r--lib/getoptlong.rb573
-rw-r--r--lib/ipaddr.gemspec18
-rw-r--r--lib/ipaddr.rb143
-rw-r--r--lib/irb.rb154
-rw-r--r--lib/irb/cmd/backtrace.rb21
-rw-r--r--lib/irb/cmd/break.rb21
-rw-r--r--lib/irb/cmd/catch.rb21
-rw-r--r--lib/irb/cmd/chws.rb12
-rw-r--r--lib/irb/cmd/continue.rb17
-rw-r--r--lib/irb/cmd/debug.rb136
-rw-r--r--lib/irb/cmd/delete.rb17
-rw-r--r--lib/irb/cmd/edit.rb61
-rw-r--r--lib/irb/cmd/finish.rb17
-rw-r--r--lib/irb/cmd/fork.rb7
-rw-r--r--lib/irb/cmd/help.rb23
-rw-r--r--lib/irb/cmd/info.rb36
-rw-r--r--lib/irb/cmd/irb_info.rb37
-rw-r--r--lib/irb/cmd/load.rb39
-rw-r--r--lib/irb/cmd/ls.rb19
-rw-r--r--lib/irb/cmd/measure.rb9
-rw-r--r--lib/irb/cmd/next.rb17
-rw-r--r--lib/irb/cmd/nop.rb30
-rw-r--r--lib/irb/cmd/pushws.rb15
-rw-r--r--lib/irb/cmd/show_cmds.rb39
-rw-r--r--lib/irb/cmd/show_source.rb112
-rw-r--r--lib/irb/cmd/step.rb17
-rw-r--r--lib/irb/cmd/subirb.rb44
-rw-r--r--lib/irb/cmd/whereami.rb9
-rw-r--r--lib/irb/color.rb78
-rw-r--r--lib/irb/color_printer.rb5
-rw-r--r--lib/irb/completion.rb172
-rw-r--r--lib/irb/context.rb120
-rw-r--r--lib/irb/ext/multi-irb.rb1
-rw-r--r--lib/irb/ext/save-history.rb10
-rw-r--r--lib/irb/extend-command.rb171
-rw-r--r--lib/irb/init.rb55
-rw-r--r--lib/irb/input-method.rb128
-rw-r--r--lib/irb/inspector.rb14
-rw-r--r--lib/irb/irb.gemspec8
-rw-r--r--lib/irb/lc/error.rb11
-rw-r--r--lib/irb/lc/help-message93
-rw-r--r--lib/irb/lc/ja/encoding_aliases.rb6
-rw-r--r--lib/irb/lc/ja/error.rb11
-rw-r--r--lib/irb/lc/ja/help-message14
-rw-r--r--lib/irb/ruby-lex.rb293
-rw-r--r--lib/irb/version.rb4
-rw-r--r--lib/irb/workspace.rb22
-rw-r--r--lib/logger.rb773
-rw-r--r--lib/logger/errors.rb2
-rw-r--r--lib/logger/formatter.rb8
-rw-r--r--lib/logger/log_device.rb8
-rw-r--r--lib/logger/logger.gemspec3
-rw-r--r--lib/logger/version.rb2
-rw-r--r--lib/mkmf.rb218
-rw-r--r--lib/mutex_m.rb3
-rw-r--r--lib/net/http.rb2121
-rw-r--r--lib/net/http/backward.rb40
-rw-r--r--lib/net/http/exceptions.rb55
-rw-r--r--lib/net/http/generic_request.rb113
-rw-r--r--lib/net/http/header.rb791
-rw-r--r--lib/net/http/net-http.gemspec15
-rw-r--r--lib/net/http/proxy_delta.rb2
-rw-r--r--lib/net/http/request.rb79
-rw-r--r--lib/net/http/requests.rb352
-rw-r--r--lib/net/http/response.rb367
-rw-r--r--lib/net/http/responses.rb1313
-rw-r--r--lib/net/http/status.rb13
-rw-r--r--lib/net/https.rb2
-rw-r--r--lib/net/net-protocol.gemspec9
-rw-r--r--lib/net/protocol.rb75
-rw-r--r--lib/open-uri.gemspec7
-rw-r--r--lib/open-uri.rb37
-rw-r--r--lib/open3.rb6
-rw-r--r--lib/open3/open3.gemspec (renamed from lib/open3.gemspec)4
-rw-r--r--lib/open3/version.rb3
-rw-r--r--lib/optparse.rb124
-rw-r--r--lib/optparse/ac.rb2
-rw-r--r--lib/optparse/date.rb2
-rw-r--r--lib/optparse/kwargs.rb2
-rw-r--r--lib/optparse/optparse.gemspec1
-rw-r--r--lib/optparse/shellwords.rb2
-rw-r--r--lib/optparse/time.rb2
-rw-r--r--lib/optparse/uri.rb2
-rw-r--r--lib/ostruct.rb53
-rw-r--r--lib/ostruct/ostruct.gemspec2
-rw-r--r--lib/pp.gemspec2
-rw-r--r--lib/pp.rb104
-rw-r--r--lib/prettyprint.gemspec2
-rw-r--r--lib/pstore.rb578
-rw-r--r--lib/racc/grammar.rb6
-rw-r--r--lib/racc/grammarfileparser.rb4
-rw-r--r--lib/racc/info.rb2
-rw-r--r--lib/racc/parser-text.rb2
-rw-r--r--lib/racc/parser.rb2
-rw-r--r--lib/racc/racc.gemspec2
-rw-r--r--lib/racc/statetransitiontable.rb2
-rw-r--r--lib/random/formatter.rb245
-rw-r--r--lib/rdoc.rb92
-rw-r--r--lib/rdoc/Gemfile13
-rw-r--r--lib/rdoc/Rakefile107
-rw-r--r--lib/rdoc/any_method.rb9
-rw-r--r--lib/rdoc/code_objects.rb3
-rw-r--r--lib/rdoc/context.rb4
-rw-r--r--lib/rdoc/context/section.rb2
-rw-r--r--lib/rdoc/cross_reference.rb64
-rw-r--r--lib/rdoc/generator.rb10
-rw-r--r--lib/rdoc/generator/darkfish.rb4
-rw-r--r--lib/rdoc/generator/markup.rb2
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml24
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml30
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml24
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml29
-rw-r--r--lib/rdoc/generator/template/darkfish/class.rhtml42
-rw-r--r--lib/rdoc/generator/template/darkfish/css/rdoc.css25
-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttfbin71200 -> 138268 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttfbin71692 -> 138680 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/index.rhtml2
-rw-r--r--lib/rdoc/generator/template/darkfish/js/darkfish.js2
-rw-r--r--lib/rdoc/generator/template/darkfish/js/search.js2
-rw-r--r--lib/rdoc/generator/template/darkfish/table_of_contents.rhtml4
-rw-r--r--lib/rdoc/i18n.rb2
-rw-r--r--lib/rdoc/known_classes.rb9
-rw-r--r--lib/rdoc/markdown.rb551
-rw-r--r--lib/rdoc/markdown/literals.rb107
-rw-r--r--lib/rdoc/markup.rb702
-rw-r--r--lib/rdoc/markup/attribute_manager.rb64
-rw-r--r--lib/rdoc/markup/parser.rb18
-rw-r--r--lib/rdoc/markup/pre_process.rb2
-rw-r--r--lib/rdoc/markup/to_html.rb32
-rw-r--r--lib/rdoc/markup/to_label.rb2
-rw-r--r--lib/rdoc/markup/to_rdoc.rb23
-rw-r--r--lib/rdoc/method_attr.rb2
-rw-r--r--lib/rdoc/normal_class.rb2
-rw-r--r--lib/rdoc/normal_module.rb2
-rw-r--r--lib/rdoc/options.rb82
-rw-r--r--lib/rdoc/parser.rb21
-rw-r--r--lib/rdoc/parser/c.rb220
-rw-r--r--lib/rdoc/parser/ruby.rb35
-rw-r--r--lib/rdoc/rd.rb7
-rw-r--r--lib/rdoc/rd/block_parser.rb22
-rw-r--r--lib/rdoc/rd/inline_parser.rb2
-rw-r--r--lib/rdoc/rdoc.gemspec18
-rw-r--r--lib/rdoc/rdoc.rb53
-rw-r--r--lib/rdoc/ri.rb9
-rw-r--r--lib/rdoc/ri/driver.rb89
-rw-r--r--lib/rdoc/rubygems_hook.rb2
-rw-r--r--lib/rdoc/servlet.rb2
-rw-r--r--lib/rdoc/single_class.rb5
-rw-r--r--lib/rdoc/stats.rb7
-rw-r--r--lib/rdoc/store.rb45
-rw-r--r--lib/rdoc/task.rb6
-rw-r--r--lib/rdoc/text.rb16
-rw-r--r--lib/rdoc/version.rb4
-rw-r--r--lib/readline.gemspec2
-rw-r--r--lib/readline.rb1
-rw-r--r--lib/reline.rb197
-rw-r--r--lib/reline/ansi.rb86
-rw-r--r--lib/reline/config.rb47
-rw-r--r--lib/reline/general_io.rb10
-rw-r--r--lib/reline/key_actor/emacs.rb2
-rw-r--r--lib/reline/key_stroke.rb78
-rw-r--r--lib/reline/line_editor.rb716
-rw-r--r--lib/reline/reline.gemspec10
-rw-r--r--lib/reline/terminfo.rb62
-rw-r--r--lib/reline/unicode.rb45
-rw-r--r--lib/reline/version.rb2
-rw-r--r--lib/reline/windows.rb202
-rw-r--r--lib/resolv-replace.gemspec2
-rw-r--r--lib/resolv.gemspec2
-rw-r--r--lib/resolv.rb10
-rw-r--r--lib/rinda/rinda.gemspec2
-rw-r--r--lib/ruby_vm/mjit/c_pointer.rb329
-rw-r--r--lib/ruby_vm/mjit/c_type.rb91
-rw-r--r--lib/ruby_vm/mjit/compiler.rb952
-rw-r--r--lib/ruby_vm/mjit/hooks.rb32
-rw-r--r--lib/rubygems.rb290
-rw-r--r--lib/rubygems/available_set.rb7
-rw-r--r--lib/rubygems/basic_specification.rb25
-rw-r--r--lib/rubygems/bundler_version_finder.rb62
-rw-r--r--lib/rubygems/command.rb87
-rw-r--r--lib/rubygems/command_manager.rb50
-rw-r--r--lib/rubygems/commands/build_command.rb20
-rw-r--r--lib/rubygems/commands/cert_command.rb92
-rw-r--r--lib/rubygems/commands/check_command.rb41
-rw-r--r--lib/rubygems/commands/cleanup_command.rb47
-rw-r--r--lib/rubygems/commands/contents_command.rb27
-rw-r--r--lib/rubygems/commands/dependency_command.rb81
-rw-r--r--lib/rubygems/commands/environment_command.rb18
-rw-r--r--lib/rubygems/commands/exec_command.rb249
-rw-r--r--lib/rubygems/commands/fetch_command.rb46
-rw-r--r--lib/rubygems/commands/generate_index_command.rb35
-rw-r--r--lib/rubygems/commands/help_command.rb13
-rw-r--r--lib/rubygems/commands/info_command.rb6
-rw-r--r--lib/rubygems/commands/install_command.rb54
-rw-r--r--lib/rubygems/commands/list_command.rb9
-rw-r--r--lib/rubygems/commands/lock_command.rb9
-rw-r--r--lib/rubygems/commands/mirror_command.rb7
-rw-r--r--lib/rubygems/commands/open_command.rb19
-rw-r--r--lib/rubygems/commands/outdated_command.rb11
-rw-r--r--lib/rubygems/commands/owner_command.rb36
-rw-r--r--lib/rubygems/commands/pristine_command.rb114
-rw-r--r--lib/rubygems/commands/push_command.rb33
-rw-r--r--lib/rubygems/commands/query_command.rb19
-rw-r--r--lib/rubygems/commands/rdoc_command.rb52
-rw-r--r--lib/rubygems/commands/search_command.rb9
-rw-r--r--lib/rubygems/commands/server_command.rb92
-rw-r--r--lib/rubygems/commands/setup_command.rb350
-rw-r--r--lib/rubygems/commands/signin_command.rb19
-rw-r--r--lib/rubygems/commands/signout_command.rb15
-rw-r--r--lib/rubygems/commands/sources_command.rb45
-rw-r--r--lib/rubygems/commands/specification_command.rb37
-rw-r--r--lib/rubygems/commands/stale_command.rb5
-rw-r--r--lib/rubygems/commands/uninstall_command.rb84
-rw-r--r--lib/rubygems/commands/unpack_command.rb27
-rw-r--r--lib/rubygems/commands/update_command.rb125
-rw-r--r--lib/rubygems/commands/which_command.rb15
-rw-r--r--lib/rubygems/commands/yank_command.rb23
-rw-r--r--lib/rubygems/compatibility.rb6
-rw-r--r--lib/rubygems/config_file.rb84
-rw-r--r--lib/rubygems/core_ext/kernel_gem.rb7
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb224
-rw-r--r--lib/rubygems/core_ext/kernel_warn.rb70
-rw-r--r--lib/rubygems/core_ext/tcpsocket_init.rb4
-rw-r--r--lib/rubygems/defaults.rb71
-rw-r--r--lib/rubygems/dependency.rb38
-rw-r--r--lib/rubygems/dependency_installer.rb75
-rw-r--r--lib/rubygems/dependency_list.rb15
-rw-r--r--lib/rubygems/deprecate.rb5
-rw-r--r--lib/rubygems/doctor.rb43
-rw-r--r--lib/rubygems/errors.rb11
-rw-r--r--lib/rubygems/exceptions.rb33
-rw-r--r--lib/rubygems/ext.rb14
-rw-r--r--lib/rubygems/ext/build_error.rb3
-rw-r--r--lib/rubygems/ext/builder.rb71
-rw-r--r--lib/rubygems/ext/cargo_builder.rb360
-rw-r--r--lib/rubygems/ext/cargo_builder/link_flag_converter.rb27
-rw-r--r--lib/rubygems/ext/cmake_builder.rb4
-rw-r--r--lib/rubygems/ext/configure_builder.rb3
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb97
-rw-r--r--lib/rubygems/ext/rake_builder.rb12
-rw-r--r--lib/rubygems/gem_runner.rb29
-rw-r--r--lib/rubygems/gemcutter_utilities.rb137
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener.rb105
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb163
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_poller.rb78
-rw-r--r--lib/rubygems/indexer.rb59
-rw-r--r--lib/rubygems/install_default_message.rb5
-rw-r--r--lib/rubygems/install_message.rb5
-rw-r--r--lib/rubygems/install_update_options.rb121
-rw-r--r--lib/rubygems/installer.rb249
-rw-r--r--lib/rubygems/installer_uninstaller_utils.rb4
-rw-r--r--lib/rubygems/local_remote_options.rb47
-rw-r--r--lib/rubygems/mock_gem_ui.rb5
-rw-r--r--lib/rubygems/name_tuple.rb14
-rw-r--r--lib/rubygems/optparse.rb3
-rw-r--r--lib/rubygems/optparse/.document1
-rw-r--r--lib/rubygems/optparse/lib/optionparser.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse.rb2308
-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.rb191
-rw-r--r--lib/rubygems/package/digest_io.rb1
-rw-r--r--lib/rubygems/package/file_source.rb5
-rw-r--r--lib/rubygems/package/io_source.rb1
-rw-r--r--lib/rubygems/package/old.rb19
-rw-r--r--lib/rubygems/package/source.rb1
-rw-r--r--lib/rubygems/package/tar_header.rb125
-rw-r--r--lib/rubygems/package/tar_reader.rb31
-rw-r--r--lib/rubygems/package/tar_reader/entry.rb100
-rw-r--r--lib/rubygems/package/tar_writer.rb15
-rw-r--r--lib/rubygems/package_task.rb9
-rw-r--r--lib/rubygems/path_support.rb8
-rw-r--r--lib/rubygems/platform.rb157
-rw-r--r--lib/rubygems/psych_additions.rb10
-rw-r--r--lib/rubygems/psych_tree.rb3
-rw-r--r--lib/rubygems/query_utils.rb100
-rw-r--r--lib/rubygems/rdoc.rb5
-rw-r--r--lib/rubygems/remote_fetcher.rb70
-rw-r--r--lib/rubygems/request.rb47
-rw-r--r--lib/rubygems/request/connection_pools.rb8
-rw-r--r--lib/rubygems/request/http_pool.rb3
-rw-r--r--lib/rubygems/request/https_pool.rb1
-rw-r--r--lib/rubygems/request_set.rb43
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb246
-rw-r--r--lib/rubygems/request_set/lockfile.rb19
-rw-r--r--lib/rubygems/request_set/lockfile/parser.rb55
-rw-r--r--lib/rubygems/request_set/lockfile/tokenizer.rb8
-rw-r--r--lib/rubygems/requirement.rb31
-rw-r--r--lib/rubygems/resolver.rb81
-rw-r--r--lib/rubygems/resolver/activation_request.rb7
-rw-r--r--lib/rubygems/resolver/api_set.rb9
-rw-r--r--lib/rubygems/resolver/api_specification.rb13
-rw-r--r--lib/rubygems/resolver/best_set.rb11
-rw-r--r--lib/rubygems/resolver/composed_set.rb1
-rw-r--r--lib/rubygems/resolver/conflict.rb21
-rw-r--r--lib/rubygems/resolver/current_set.rb1
-rw-r--r--lib/rubygems/resolver/dependency_request.rb5
-rw-r--r--lib/rubygems/resolver/git_set.rb5
-rw-r--r--lib/rubygems/resolver/git_specification.rb13
-rw-r--r--lib/rubygems/resolver/index_set.rb7
-rw-r--r--lib/rubygems/resolver/index_specification.rb12
-rw-r--r--lib/rubygems/resolver/installed_specification.rb9
-rw-r--r--lib/rubygems/resolver/installer_set.rb58
-rw-r--r--lib/rubygems/resolver/local_specification.rb5
-rw-r--r--lib/rubygems/resolver/lock_set.rb9
-rw-r--r--lib/rubygems/resolver/lock_specification.rb9
-rw-r--r--lib/rubygems/resolver/molinillo.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb6
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb58
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb2
-rw-r--r--lib/rubygems/resolver/requirement_list.rb1
-rw-r--r--lib/rubygems/resolver/set.rb2
-rw-r--r--lib/rubygems/resolver/source_set.rb2
-rw-r--r--lib/rubygems/resolver/spec_specification.rb1
-rw-r--r--lib/rubygems/resolver/specification.rb3
-rw-r--r--lib/rubygems/resolver/stats.rb3
-rw-r--r--lib/rubygems/resolver/vendor_set.rb3
-rw-r--r--lib/rubygems/resolver/vendor_specification.rb7
-rw-r--r--lib/rubygems/s3_uri_signer.rb21
-rw-r--r--lib/rubygems/safe_yaml.rb22
-rw-r--r--lib/rubygems/security.rb113
-rw-r--r--lib/rubygems/security/policies.rb95
-rw-r--r--lib/rubygems/security/policy.rb43
-rw-r--r--lib/rubygems/security/signer.rb20
-rw-r--r--lib/rubygems/security/trust_dir.rb9
-rw-r--r--lib/rubygems/security_option.rb15
-rw-r--r--lib/rubygems/server.rb882
-rw-r--r--lib/rubygems/shellwords.rb3
-rw-r--r--lib/rubygems/source.rb57
-rw-r--r--lib/rubygems/source/git.rb51
-rw-r--r--lib/rubygems/source/installed.rb3
-rw-r--r--lib/rubygems/source/local.rb5
-rw-r--r--lib/rubygems/source/lock.rb1
-rw-r--r--lib/rubygems/source/specific_file.rb3
-rw-r--r--lib/rubygems/source/vendor.rb1
-rw-r--r--lib/rubygems/source_list.rb14
-rw-r--r--lib/rubygems/spec_fetcher.rb75
-rw-r--r--lib/rubygems/specification.rb496
-rw-r--r--lib/rubygems/specification_policy.rb83
-rw-r--r--lib/rubygems/stub_specification.rb55
-rw-r--r--lib/rubygems/text.rb4
-rw-r--r--lib/rubygems/tsort.rb3
-rw-r--r--lib/rubygems/tsort/.document1
-rw-r--r--lib/rubygems/tsort/lib/tsort.rb452
-rw-r--r--lib/rubygems/uninstaller.rb51
-rw-r--r--lib/rubygems/update_suggestion.rb69
-rw-r--r--lib/rubygems/uri.rb126
-rw-r--r--lib/rubygems/uri_formatter.rb2
-rw-r--r--lib/rubygems/uri_parser.rb42
-rw-r--r--lib/rubygems/user_interaction.rb76
-rw-r--r--lib/rubygems/util.rb29
-rw-r--r--lib/rubygems/util/licenses.rb7
-rw-r--r--lib/rubygems/util/list.rb1
-rw-r--r--lib/rubygems/validator.rb13
-rw-r--r--lib/rubygems/version.rb45
-rw-r--r--lib/rubygems/version_option.rb11
-rw-r--r--lib/securerandom.gemspec4
-rw-r--r--lib/securerandom.rb244
-rw-r--r--lib/set.rb99
-rw-r--r--lib/set/set.gemspec2
-rw-r--r--lib/syntax_suggest.rb3
-rw-r--r--lib/syntax_suggest/api.rb201
-rw-r--r--lib/syntax_suggest/around_block_scan.rb232
-rw-r--r--lib/syntax_suggest/block_expand.rb165
-rw-r--r--lib/syntax_suggest/capture/before_after_keyword_ends.rb85
-rw-r--r--lib/syntax_suggest/capture/falling_indent_lines.rb71
-rw-r--r--lib/syntax_suggest/capture_code_context.rb245
-rw-r--r--lib/syntax_suggest/clean_document.rb306
-rw-r--r--lib/syntax_suggest/cli.rb130
-rw-r--r--lib/syntax_suggest/code_block.rb100
-rw-r--r--lib/syntax_suggest/code_frontier.rb178
-rw-r--r--lib/syntax_suggest/code_line.rb237
-rw-r--r--lib/syntax_suggest/code_search.rb139
-rw-r--r--lib/syntax_suggest/core_ext.rb114
-rw-r--r--lib/syntax_suggest/display_code_with_line_numbers.rb70
-rw-r--r--lib/syntax_suggest/display_invalid_blocks.rb83
-rw-r--r--lib/syntax_suggest/explain_syntax.rb103
-rw-r--r--lib/syntax_suggest/left_right_lex_count.rb168
-rw-r--r--lib/syntax_suggest/lex_all.rb55
-rw-r--r--lib/syntax_suggest/lex_value.rb70
-rw-r--r--lib/syntax_suggest/parse_blocks_from_indent_line.rb60
-rw-r--r--lib/syntax_suggest/pathname_from_message.rb59
-rw-r--r--lib/syntax_suggest/priority_engulf_queue.rb63
-rw-r--r--lib/syntax_suggest/priority_queue.rb105
-rw-r--r--lib/syntax_suggest/ripper_errors.rb36
-rw-r--r--lib/syntax_suggest/scan_history.rb134
-rw-r--r--lib/syntax_suggest/syntax_suggest.gemspec32
-rw-r--r--lib/syntax_suggest/unvisited_lines.rb36
-rw-r--r--lib/syntax_suggest/version.rb5
-rw-r--r--lib/tempfile.gemspec4
-rw-r--r--lib/tempfile.rb151
-rw-r--r--lib/time.gemspec2
-rw-r--r--lib/time.rb6
-rw-r--r--lib/timeout.rb144
-rw-r--r--lib/timeout/timeout.gemspec8
-rw-r--r--lib/tmpdir.gemspec4
-rw-r--r--lib/tmpdir.rb28
-rw-r--r--lib/tsort.gemspec2
-rw-r--r--lib/tsort.rb20
-rw-r--r--lib/un.gemspec5
-rw-r--r--lib/un.rb47
-rw-r--r--lib/unicode_normalize/normalize.rb2
-rw-r--r--lib/unicode_normalize/tables.rb194
-rw-r--r--lib/uri.rb1
-rw-r--r--lib/uri/common.rb54
-rw-r--r--lib/uri/file.rb6
-rw-r--r--lib/uri/generic.rb29
-rw-r--r--lib/uri/http.rb39
-rw-r--r--lib/uri/mailto.rb2
-rw-r--r--lib/uri/rfc2396_parser.rb4
-rw-r--r--lib/uri/rfc3986_parser.rb7
-rw-r--r--lib/uri/version.rb2
-rw-r--r--lib/weakref.rb5
-rw-r--r--lib/yaml.rb14
-rw-r--r--lib/yaml/yaml.gemspec2
-rwxr-xr-xlibexec/bundle36
-rwxr-xr-xlibexec/bundler2
-rwxr-xr-xlibexec/erb12
-rwxr-xr-xlibexec/rdoc1
-rwxr-xr-xlibexec/syntax_suggest7
-rw-r--r--load.c1071
-rw-r--r--localeinit.c12
-rw-r--r--main.c27
-rw-r--r--man/irb.149
-rw-r--r--man/ruby.140
-rw-r--r--marshal.c1919
-rw-r--r--marshal.rb40
-rw-r--r--math.c664
-rw-r--r--memory_view.c25
-rw-r--r--method.h32
-rw-r--r--mini_builtin.c2
-rwxr-xr-xmisc/lldb_cruby.py98
-rw-r--r--misc/lldb_disasm.py29
-rw-r--r--misc/lldb_rb/commands/command_template.py30
-rw-r--r--misc/lldb_rb/commands/heap_page_command.py26
-rw-r--r--misc/lldb_rb/commands/rclass_ext_command.py14
-rw-r--r--misc/lldb_rb/constants.py4
-rw-r--r--misc/lldb_rb/rb_base_command.py69
-rw-r--r--misc/lldb_yjit.py47
-rw-r--r--missing/dtoa.c3
-rw-r--r--missing/erf.c15
-rw-r--r--missing/finite.c9
-rw-r--r--missing/flock.c9
-rw-r--r--missing/isinf.c69
-rw-r--r--missing/isnan.c32
-rw-r--r--missing/langinfo.c2
-rw-r--r--missing/signbit.c19
-rw-r--r--missing/tgamma.c15
-rw-r--r--mjit.c1814
-rw-r--r--mjit.h130
-rw-r--r--mjit.rb37
-rw-r--r--mjit_c.c43
-rw-r--r--mjit_c.h97
-rw-r--r--mjit_c.rb807
-rw-r--r--mjit_compile.c589
-rw-r--r--mjit_worker.c1515
-rw-r--r--node.c1492
-rw-r--r--node.h79
-rw-r--r--numeric.c4660
-rw-r--r--numeric.rb134
-rw-r--r--object.c2263
-rw-r--r--pack.c2349
-rw-r--r--pack.rb280
-rw-r--r--parse.y1707
-rw-r--r--prelude.rb9
-rw-r--r--probes_helper.h14
-rw-r--r--proc.c1154
-rw-r--r--process.c2266
-rw-r--r--ractor.c235
-rw-r--r--ractor.rb14
-rw-r--r--ractor_core.h123
-rw-r--r--random.c652
-rw-r--r--range.c1935
-rw-r--r--rational.c834
-rw-r--r--re.c2934
-rw-r--r--regcomp.c21
-rw-r--r--regenc.c15
-rw-r--r--regenc.h15
-rw-r--r--regerror.c4
-rw-r--r--regexec.c833
-rw-r--r--regint.h63
-rw-r--r--regparse.c19
-rw-r--r--ruby-runner.c56
-rw-r--r--ruby.c2323
-rw-r--r--ruby_assert.h1
-rw-r--r--rubystub.c29
-rw-r--r--sample/coverage.rb2
-rw-r--r--sample/drb/README.ja.rdoc2
-rw-r--r--sample/drb/README.rdoc4
-rw-r--r--sample/exyacc.rb2
-rw-r--r--sample/from.rb2
-rw-r--r--sample/getoptlong/abbrev.rb9
-rw-r--r--sample/getoptlong/aliases.rb8
-rw-r--r--sample/getoptlong/argv.rb12
-rw-r--r--sample/getoptlong/each.rb12
-rw-r--r--sample/getoptlong/fibonacci.rb62
-rw-r--r--sample/getoptlong/permute.rb12
-rw-r--r--sample/getoptlong/require_order.rb13
-rw-r--r--sample/getoptlong/return_in_order.rb13
-rw-r--r--sample/getoptlong/simple.rb7
-rw-r--r--sample/getoptlong/types.rb10
-rwxr-xr-xsample/mine.rb8
-rw-r--r--sample/mpart.rb44
-rw-r--r--sample/trick2015/kinaba/entry.rb4
-rw-r--r--sample/trick2018/02-mame/entry.rb4
-rw-r--r--sample/trick2022/01-tompng/Gemfile2
-rw-r--r--sample/trick2022/01-tompng/Gemfile.lock13
-rw-r--r--sample/trick2022/01-tompng/authors.markdown3
-rw-r--r--sample/trick2022/01-tompng/entry.rb40
-rw-r--r--sample/trick2022/01-tompng/remarks.markdown51
-rw-r--r--sample/trick2022/02-tompng/authors.markdown3
-rw-r--r--sample/trick2022/02-tompng/entry.rb32
-rw-r--r--sample/trick2022/02-tompng/remarks.markdown32
-rw-r--r--sample/trick2022/03-mame/authors.markdown3
-rw-r--r--sample/trick2022/03-mame/entry.rb27
-rw-r--r--sample/trick2022/03-mame/remarks.markdown96
-rw-r--r--sample/trick2022/03-mame/test.txt13
-rw-r--r--sample/trick2022/README.md14
-rw-r--r--sample/uumerge.rb2
-rw-r--r--scheduler.c476
-rw-r--r--shape.c825
-rw-r--r--shape.h232
-rw-r--r--signal.c513
-rw-r--r--siphash.c90
-rw-r--r--sparc.c4
-rw-r--r--spec/README.md34
-rw-r--r--spec/bundler/bundler/bundler_spec.rb227
-rw-r--r--spec/bundler/bundler/cli_spec.rb66
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb10
-rw-r--r--spec/bundler/bundler/definition_spec.rb54
-rw-r--r--spec/bundler/bundler/dep_proxy_spec.rb32
-rw-r--r--spec/bundler/bundler/dependency_spec.rb157
-rw-r--r--spec/bundler/bundler/digest_spec.rb24
-rw-r--r--spec/bundler/bundler/dsl_spec.rb53
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb48
-rw-r--r--spec/bundler/bundler/env_spec.rb22
-rw-r--r--spec/bundler/bundler/fetcher/dependency_spec.rb18
-rw-r--r--spec/bundler/bundler/fetcher/downloader_spec.rb30
-rw-r--r--spec/bundler/bundler/fetcher/index_spec.rb23
-rw-r--r--spec/bundler/bundler/fetcher_spec.rb34
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb14
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb22
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb246
-rw-r--r--spec/bundler/bundler/installer/gem_installer_spec.rb18
-rw-r--r--spec/bundler/bundler/installer/parallel_installer_spec.rb38
-rw-r--r--spec/bundler/bundler/plugin/index_spec.rb10
-rw-r--r--spec/bundler/bundler/plugin/installer_spec.rb2
-rw-r--r--spec/bundler/bundler/plugin_spec.rb29
-rw-r--r--spec/bundler/bundler/psyched_yaml_spec.rb9
-rw-r--r--spec/bundler/bundler/remote_specification_spec.rb2
-rw-r--r--spec/bundler/bundler/resolver/candidate_spec.rb21
-rw-r--r--spec/bundler/bundler/ruby_dsl_spec.rb27
-rw-r--r--spec/bundler/bundler/ruby_version_spec.rb46
-rw-r--r--spec/bundler/bundler/rubygems_integration_spec.rb34
-rw-r--r--spec/bundler/bundler/settings_spec.rb2
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb11
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb69
-rw-r--r--spec/bundler/bundler/source/git_spec.rb45
-rw-r--r--spec/bundler/bundler/source_spec.rb38
-rw-r--r--spec/bundler/bundler/vendored_persistent_spec.rb77
-rw-r--r--spec/bundler/bundler/version_ranges_spec.rb40
-rw-r--r--spec/bundler/cache/gems_spec.rb36
-rw-r--r--spec/bundler/cache/git_spec.rb77
-rw-r--r--spec/bundler/commands/add_spec.rb58
-rw-r--r--spec/bundler/commands/binstubs_spec.rb85
-rw-r--r--spec/bundler/commands/cache_spec.rb18
-rw-r--r--spec/bundler/commands/check_spec.rb133
-rw-r--r--spec/bundler/commands/clean_spec.rb24
-rw-r--r--spec/bundler/commands/config_spec.rb118
-rw-r--r--spec/bundler/commands/doctor_spec.rb18
-rw-r--r--spec/bundler/commands/exec_spec.rb92
-rw-r--r--spec/bundler/commands/fund_spec.rb16
-rw-r--r--spec/bundler/commands/help_spec.rb4
-rw-r--r--spec/bundler/commands/info_spec.rb66
-rw-r--r--spec/bundler/commands/init_spec.rb38
-rw-r--r--spec/bundler/commands/inject_spec.rb4
-rw-r--r--spec/bundler/commands/install_spec.rb386
-rw-r--r--spec/bundler/commands/lock_spec.rb757
-rw-r--r--spec/bundler/commands/newgem_spec.rb282
-rw-r--r--spec/bundler/commands/open_spec.rb60
-rw-r--r--spec/bundler/commands/outdated_spec.rb224
-rw-r--r--spec/bundler/commands/platform_spec.rb (renamed from spec/bundler/other/platform_spec.rb)107
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb1
-rw-r--r--spec/bundler/commands/pristine_spec.rb4
-rw-r--r--spec/bundler/commands/remove_spec.rb93
-rw-r--r--spec/bundler/commands/show_spec.rb6
-rw-r--r--spec/bundler/commands/update_spec.rb579
-rw-r--r--spec/bundler/commands/viz_spec.rb6
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb5
-rw-r--r--spec/bundler/install/binstubs_spec.rb4
-rw-r--r--spec/bundler/install/bundler_spec.rb83
-rw-r--r--spec/bundler/install/deploy_spec.rb148
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb118
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb222
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb179
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb13
-rw-r--r--spec/bundler/install/gemfile/install_if_spec.rb2
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb189
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb198
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb40
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb288
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb758
-rw-r--r--spec/bundler/install/gemfile_spec.rb2
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb61
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb53
-rw-r--r--spec/bundler/install/gems/flex_spec.rb126
-rw-r--r--spec/bundler/install/gems/fund_spec.rb43
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb6
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb331
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb165
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb205
-rw-r--r--spec/bundler/install/gemspecs_spec.rb7
-rw-r--r--spec/bundler/install/git_spec.rb80
-rw-r--r--spec/bundler/install/global_cache_spec.rb22
-rw-r--r--spec/bundler/install/path_spec.rb2
-rw-r--r--spec/bundler/install/process_lock_spec.rb22
-rw-r--r--spec/bundler/install/yanked_spec.rb168
-rw-r--r--spec/bundler/lock/git_spec.rb127
-rw-r--r--spec/bundler/lock/lockfile_spec.rb428
-rw-r--r--spec/bundler/other/ext_spec.rb4
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb113
-rw-r--r--spec/bundler/plugins/command_spec.rb6
-rw-r--r--spec/bundler/plugins/install_spec.rb51
-rw-r--r--spec/bundler/plugins/source/example_spec.rb18
-rw-r--r--spec/bundler/quality_es_spec.rb4
-rw-r--r--spec/bundler/quality_spec.rb55
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb10
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb372
-rw-r--r--spec/bundler/realworld/ffi_spec.rb57
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock2
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb10
-rw-r--r--spec/bundler/realworld/git_spec.rb11
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb45
-rw-r--r--spec/bundler/realworld/parallel_spec.rb2
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb19
-rw-r--r--spec/bundler/resolver/basic_spec.rb74
-rw-r--r--spec/bundler/resolver/platform_spec.rb161
-rw-r--r--spec/bundler/runtime/gem_tasks_spec.rb6
-rw-r--r--spec/bundler/runtime/inline_spec.rb222
-rw-r--r--spec/bundler/runtime/platform_spec.rb170
-rw-r--r--spec/bundler/runtime/require_spec.rb2
-rw-r--r--spec/bundler/runtime/self_management_spec.rb126
-rw-r--r--spec/bundler/runtime/setup_spec.rb280
-rw-r--r--spec/bundler/spec_helper.rb38
-rw-r--r--spec/bundler/support/api_request_limit_hax.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index.rb118
-rw-r--r--spec/bundler/support/artifice/compact_index_api_missing.rb13
-rw-r--r--spec/bundler/support/artifice/compact_index_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_checksum_mismatch.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_concurrent_download.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_creds_diff_host.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_extra.rb35
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api.rb50
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api_missing.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_missing.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_forbidden.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_host_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_no_gem.rb6
-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.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_precompiled_before.rb25
-rw-r--r--spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_rate_limited.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_redirects.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_wrong_dependencies.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint.rb113
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb7
-rw-r--r--spec/bundler/support/artifice/endpoint_api_forbidden.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_api_missing.rb18
-rw-r--r--spec/bundler/support/artifice/endpoint_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_creds_diff_host.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_extra.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_api.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_missing.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_fallback.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_host_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail.rb11
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_mirror_source.rb4
-rw-r--r--spec/bundler/support/artifice/endpoint_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_timeout.rb6
-rw-r--r--spec/bundler/support/artifice/fail.rb11
-rw-r--r--spec/bundler/support/artifice/helpers/artifice.rb30
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index.rb118
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_extra.rb33
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_extra_api.rb48
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint.rb112
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_extra.rb29
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_fallback.rb15
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb9
-rw-r--r--spec/bundler/support/artifice/helpers/rack_request.rb100
-rw-r--r--spec/bundler/support/artifice/used_cassettes.txt20908
-rw-r--r--spec/bundler/support/artifice/vcr.rb35
-rw-r--r--spec/bundler/support/artifice/windows.rb7
-rw-r--r--spec/bundler/support/builders.rb71
-rw-r--r--spec/bundler/support/bundle.rb2
-rw-r--r--spec/bundler/support/filters.rb11
-rw-r--r--spec/bundler/support/hax.rb46
-rw-r--r--spec/bundler/support/helpers.rb99
-rw-r--r--spec/bundler/support/indexes.rb39
-rw-r--r--spec/bundler/support/matchers.rb28
-rw-r--r--spec/bundler/support/path.rb40
-rw-r--r--spec/bundler/support/platforms.rb40
-rw-r--r--spec/bundler/support/rubygems_ext.rb33
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb14
-rw-r--r--spec/bundler/support/sudo.rb18
-rw-r--r--spec/bundler/update/gems/fund_spec.rb16
-rw-r--r--spec/bundler/update/git_spec.rb58
-rw-r--r--spec/default.mspec22
-rwxr-xr-xspec/mspec/bin/mspec2
-rwxr-xr-xspec/mspec/lib/mspec/commands/mkspec.rb16
-rwxr-xr-xspec/mspec/lib/mspec/commands/mspec.rb6
-rw-r--r--spec/mspec/lib/mspec/expectations/expectations.rb4
-rw-r--r--spec/mspec/lib/mspec/guards/platform.rb4
-rw-r--r--spec/mspec/lib/mspec/guards/superuser.rb10
-rw-r--r--spec/mspec/lib/mspec/guards/version.rb28
-rw-r--r--spec/mspec/lib/mspec/helpers/datetime.rb1
-rw-r--r--spec/mspec/lib/mspec/helpers/numeric.rb4
-rw-r--r--spec/mspec/lib/mspec/helpers/ruby_exe.rb23
-rw-r--r--spec/mspec/lib/mspec/matchers/base.rb30
-rw-r--r--spec/mspec/lib/mspec/matchers/output.rb8
-rw-r--r--spec/mspec/lib/mspec/matchers/raise_error.rb6
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb3
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb37
-rw-r--r--spec/mspec/lib/mspec/runner/context.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/exception.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/base.rb26
-rw-r--r--spec/mspec/lib/mspec/runner/mspec.rb8
-rw-r--r--spec/mspec/lib/mspec/runner/shared.rb8
-rw-r--r--spec/mspec/lib/mspec/utils/name_map.rb7
-rw-r--r--spec/mspec/lib/mspec/utils/options.rb15
-rw-r--r--spec/mspec/lib/mspec/utils/script.rb16
-rw-r--r--spec/mspec/lib/mspec/utils/warnings.rb2
-rw-r--r--spec/mspec/spec/commands/mkspec_spec.rb2
-rw-r--r--spec/mspec/spec/helpers/numeric_spec.rb10
-rw-r--r--spec/mspec/spec/helpers/ruby_exe_spec.rb14
-rw-r--r--spec/mspec/spec/utils/script_spec.rb5
-rw-r--r--spec/mspec/tool/remove_old_guards.rb12
-rw-r--r--spec/mspec/tool/sync/sync-rubyspec.rb11
-rwxr-xr-xspec/mspec/tool/tag_from_output.rb33
-rw-r--r--spec/ruby/.mspec.constants3
-rw-r--r--spec/ruby/.rubocop.yml55
-rw-r--r--spec/ruby/.rubocop_todo.yml11
-rw-r--r--spec/ruby/CONTRIBUTING.md21
-rw-r--r--spec/ruby/README.md22
-rw-r--r--spec/ruby/command_line/backtrace_limit_spec.rb48
-rw-r--r--spec/ruby/command_line/dash_upper_w_spec.rb42
-rw-r--r--spec/ruby/command_line/dash_v_spec.rb3
-rw-r--r--spec/ruby/command_line/dash_w_spec.rb4
-rw-r--r--spec/ruby/command_line/feature_spec.rb4
-rw-r--r--spec/ruby/command_line/fixtures/backtrace.rb35
-rw-r--r--spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb2
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb30
-rw-r--r--spec/ruby/core/array/clear_spec.rb20
-rw-r--r--spec/ruby/core/array/compact_spec.rb30
-rw-r--r--spec/ruby/core/array/concat_spec.rb58
-rw-r--r--spec/ruby/core/array/deconstruct_spec.rb10
-rw-r--r--spec/ruby/core/array/delete_at_spec.rb22
-rw-r--r--spec/ruby/core/array/delete_if_spec.rb16
-rw-r--r--spec/ruby/core/array/delete_spec.rb22
-rw-r--r--spec/ruby/core/array/each_spec.rb35
-rw-r--r--spec/ruby/core/array/element_set_spec.rb76
-rw-r--r--spec/ruby/core/array/fill_spec.rb14
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb62
-rw-r--r--spec/ruby/core/array/flatten_spec.rb10
-rw-r--r--spec/ruby/core/array/intersect_spec.rb17
-rw-r--r--spec/ruby/core/array/intersection_spec.rb16
-rw-r--r--spec/ruby/core/array/keep_if_spec.rb1
-rw-r--r--spec/ruby/core/array/multiply_spec.rb40
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb11
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb7
-rw-r--r--spec/ruby/core/array/pack/c_spec.rb14
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb5
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/p_spec.rb24
-rw-r--r--spec/ruby/core/array/pack/shared/basic.rb52
-rw-r--r--spec/ruby/core/array/pack/shared/float.rb74
-rw-r--r--spec/ruby/core/array/pack/shared/integer.rb96
-rw-r--r--spec/ruby/core/array/pack/shared/numeric_basic.rb10
-rw-r--r--spec/ruby/core/array/pack/shared/taint.rb33
-rw-r--r--spec/ruby/core/array/pack/shared/unicode.rb14
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/w_spec.rb14
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb1
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb10
-rw-r--r--spec/ruby/core/array/plus_spec.rb16
-rw-r--r--spec/ruby/core/array/pop_spec.rb52
-rw-r--r--spec/ruby/core/array/sample_spec.rb26
-rw-r--r--spec/ruby/core/array/shared/clone.rb24
-rw-r--r--spec/ruby/core/array/shared/collect.rb31
-rw-r--r--spec/ruby/core/array/shared/inspect.rb26
-rw-r--r--spec/ruby/core/array/shared/join.rb85
-rw-r--r--spec/ruby/core/array/shared/slice.rb371
-rw-r--r--spec/ruby/core/array/shared/unshift.rb18
-rw-r--r--spec/ruby/core/array/shift_spec.rb16
-rw-r--r--spec/ruby/core/array/slice_spec.rb18
-rw-r--r--spec/ruby/core/array/sum_spec.rb29
-rw-r--r--spec/ruby/core/array/uniq_spec.rb76
-rw-r--r--spec/ruby/core/array/values_at_spec.rb9
-rw-r--r--spec/ruby/core/array/zip_spec.rb6
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb68
-rw-r--r--spec/ruby/core/binding/eval_spec.rb16
-rw-r--r--spec/ruby/core/builtin_constants/builtin_constants_spec.rb18
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb31
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb60
-rw-r--r--spec/ruby/core/comparable/clamp_spec.rb78
-rw-r--r--spec/ruby/core/complex/comparision_spec.rb27
-rw-r--r--spec/ruby/core/complex/comparison_spec.rb25
-rw-r--r--spec/ruby/core/complex/polar_spec.rb16
-rw-r--r--spec/ruby/core/conditionvariable/broadcast_spec.rb (renamed from spec/ruby/library/conditionvariable/broadcast_spec.rb)0
-rw-r--r--spec/ruby/core/conditionvariable/marshal_dump_spec.rb (renamed from spec/ruby/library/conditionvariable/marshal_dump_spec.rb)0
-rw-r--r--spec/ruby/core/conditionvariable/signal_spec.rb (renamed from spec/ruby/library/conditionvariable/signal_spec.rb)0
-rw-r--r--spec/ruby/core/conditionvariable/wait_spec.rb (renamed from spec/ruby/library/conditionvariable/wait_spec.rb)0
-rw-r--r--spec/ruby/core/data/constants_spec.rb14
-rw-r--r--spec/ruby/core/dir/children_spec.rb8
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb7
-rw-r--r--spec/ruby/core/dir/entries_spec.rb7
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb22
-rw-r--r--spec/ruby/core/dir/foreach_spec.rb12
-rw-r--r--spec/ruby/core/dir/glob_spec.rb29
-rw-r--r--spec/ruby/core/dir/home_spec.rb45
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb18
-rw-r--r--spec/ruby/core/dir/read_spec.rb33
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb9
-rw-r--r--spec/ruby/core/dir/shared/glob.rb59
-rw-r--r--spec/ruby/core/encoding/compatible_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb13
-rw-r--r--spec/ruby/core/encoding/default_external_spec.rb8
-rw-r--r--spec/ruby/core/encoding/list_spec.rb6
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb108
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/any_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/compact_spec.rb11
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/filter_map_spec.rb34
-rw-r--r--spec/ruby/core/enumerable/grep_spec.rb18
-rw-r--r--spec/ruby/core/enumerable/grep_v_spec.rb18
-rw-r--r--spec/ruby/core/enumerable/group_by_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/shared/collect.rb14
-rw-r--r--spec/ruby/core/enumerable/shared/entries.rb10
-rw-r--r--spec/ruby/core/enumerable/shared/inject.rb10
-rw-r--r--spec/ruby/core/enumerable/sum_spec.rb26
-rw-r--r--spec/ruby/core/enumerable/tally_spec.rb50
-rw-r--r--spec/ruby/core/enumerable/uniq_spec.rb76
-rw-r--r--spec/ruby/core/enumerable/zip_spec.rb5
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb7
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb7
-rw-r--r--spec/ruby/core/enumerator/lazy/compact_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/lazy/eager_spec.rb38
-rw-r--r--spec/ruby/core/enumerator/lazy/filter_map_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/lazy_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/lazy/with_index_spec.rb44
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/produce_spec.rb48
-rw-r--r--spec/ruby/core/enumerator/yielder/to_proc_spec.rb20
-rw-r--r--spec/ruby/core/env/merge_spec.rb6
-rw-r--r--spec/ruby/core/env/shared/update.rb38
-rw-r--r--spec/ruby/core/env/shift_spec.rb37
-rw-r--r--spec/ruby/core/exception/errno_spec.rb9
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb28
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb40
-rw-r--r--spec/ruby/core/exception/interrupt_spec.rb9
-rw-r--r--spec/ruby/core/exception/signal_exception_spec.rb6
-rw-r--r--spec/ruby/core/exception/system_exit_spec.rb42
-rw-r--r--spec/ruby/core/false/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/false/to_s_spec.rb12
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb79
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb148
-rw-r--r--spec/ruby/core/fiber/shared/blocking.rb41
-rw-r--r--spec/ruby/core/fiber/storage_spec.rb117
-rw-r--r--spec/ruby/core/file/absolute_path_spec.rb74
-rw-r--r--spec/ruby/core/file/atime_spec.rb6
-rw-r--r--spec/ruby/core/file/ctime_spec.rb4
-rw-r--r--spec/ruby/core/file/extname_spec.rb4
-rw-r--r--spec/ruby/core/file/mtime_spec.rb20
-rw-r--r--spec/ruby/core/file/open_spec.rb8
-rw-r--r--spec/ruby/core/file/shared/fnmatch.rb16
-rw-r--r--spec/ruby/core/file/shared/path.rb14
-rw-r--r--spec/ruby/core/file/utime_spec.rb45
-rw-r--r--spec/ruby/core/float/coerce_spec.rb4
-rw-r--r--spec/ruby/core/float/comparison_spec.rb53
-rw-r--r--spec/ruby/core/float/divide_spec.rb4
-rw-r--r--spec/ruby/core/float/divmod_spec.rb4
-rw-r--r--spec/ruby/core/float/gt_spec.rb21
-rw-r--r--spec/ruby/core/float/gte_spec.rb21
-rw-r--r--spec/ruby/core/float/lt_spec.rb21
-rw-r--r--spec/ruby/core/float/lte_spec.rb21
-rw-r--r--spec/ruby/core/float/minus_spec.rb2
-rw-r--r--spec/ruby/core/float/multiply_spec.rb2
-rw-r--r--spec/ruby/core/float/plus_spec.rb2
-rw-r--r--spec/ruby/core/float/round_spec.rb64
-rw-r--r--spec/ruby/core/float/shared/equal.rb21
-rw-r--r--spec/ruby/core/float/shared/to_i.rb4
-rw-r--r--spec/ruby/core/gc/auto_compact_spec.rb26
-rw-r--r--spec/ruby/core/gc/measure_total_time_spec.rb19
-rw-r--r--spec/ruby/core/gc/stat_spec.rb18
-rw-r--r--spec/ruby/core/gc/total_time_spec.rb15
-rw-r--r--spec/ruby/core/hash/constructor_spec.rb27
-rw-r--r--spec/ruby/core/hash/deconstruct_keys_spec.rb32
-rw-r--r--spec/ruby/core/hash/hash_spec.rb9
-rw-r--r--spec/ruby/core/hash/reject_spec.rb7
-rw-r--r--spec/ruby/core/hash/ruby2_keywords_hash_spec.rb96
-rw-r--r--spec/ruby/core/hash/shared/eql.rb84
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb17
-rw-r--r--spec/ruby/core/hash/shift_spec.rb42
-rw-r--r--spec/ruby/core/hash/to_a_spec.rb10
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb32
-rw-r--r--spec/ruby/core/integer/bit_and_spec.rb14
-rw-r--r--spec/ruby/core/integer/bit_or_spec.rb33
-rw-r--r--spec/ruby/core/integer/bit_xor_spec.rb35
-rw-r--r--spec/ruby/core/integer/chr_spec.rb65
-rw-r--r--spec/ruby/core/integer/complement_spec.rb6
-rw-r--r--spec/ruby/core/integer/constants_spec.rb36
-rw-r--r--spec/ruby/core/integer/div_spec.rb10
-rw-r--r--spec/ruby/core/integer/divide_spec.rb12
-rw-r--r--spec/ruby/core/integer/divmod_spec.rb12
-rw-r--r--spec/ruby/core/integer/element_reference_spec.rb122
-rw-r--r--spec/ruby/core/integer/fdiv_spec.rb51
-rw-r--r--spec/ruby/core/integer/left_shift_spec.rb57
-rw-r--r--spec/ruby/core/integer/minus_spec.rb6
-rw-r--r--spec/ruby/core/integer/multiply_spec.rb6
-rw-r--r--spec/ruby/core/integer/plus_spec.rb23
-rw-r--r--spec/ruby/core/integer/remainder_spec.rb2
-rw-r--r--spec/ruby/core/integer/right_shift_spec.rb61
-rw-r--r--spec/ruby/core/integer/shared/abs.rb4
-rw-r--r--spec/ruby/core/integer/shared/exponent.rb11
-rw-r--r--spec/ruby/core/integer/shared/modulo.rb10
-rw-r--r--spec/ruby/core/integer/to_f_spec.rb6
-rw-r--r--spec/ruby/core/integer/to_s_spec.rb6
-rw-r--r--spec/ruby/core/integer/uminus_spec.rb8
-rw-r--r--spec/ruby/core/integer/zero_spec.rb21
-rw-r--r--spec/ruby/core/io/advise_spec.rb14
-rw-r--r--spec/ruby/core/io/close_spec.rb6
-rw-r--r--spec/ruby/core/io/external_encoding_spec.rb8
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb26
-rw-r--r--spec/ruby/core/io/flush_spec.rb2
-rw-r--r--spec/ruby/core/io/gets_spec.rb52
-rw-r--r--spec/ruby/core/io/internal_encoding_spec.rb8
-rw-r--r--spec/ruby/core/io/lineno_spec.rb9
-rw-r--r--spec/ruby/core/io/new_spec.rb2
-rw-r--r--spec/ruby/core/io/nonblock_spec.rb70
-rw-r--r--spec/ruby/core/io/open_spec.rb4
-rw-r--r--spec/ruby/core/io/path_spec.rb14
-rw-r--r--spec/ruby/core/io/pipe_spec.rb11
-rw-r--r--spec/ruby/core/io/print_spec.rb25
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb49
-rw-r--r--spec/ruby/core/io/read_spec.rb25
-rw-r--r--spec/ruby/core/io/readchar_spec.rb66
-rw-r--r--spec/ruby/core/io/readline_spec.rb35
-rw-r--r--spec/ruby/core/io/readlines_spec.rb26
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb17
-rw-r--r--spec/ruby/core/io/rewind_spec.rb15
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb273
-rw-r--r--spec/ruby/core/io/set_encoding_spec.rb49
-rw-r--r--spec/ruby/core/io/shared/each.rb84
-rw-r--r--spec/ruby/core/io/shared/new.rb2
-rw-r--r--spec/ruby/core/io/shared/pos.rb8
-rw-r--r--spec/ruby/core/io/shared/readlines.rb142
-rw-r--r--spec/ruby/core/io/shared/write.rb12
-rw-r--r--spec/ruby/core/io/sysread_spec.rb31
-rw-r--r--spec/ruby/core/io/sysseek_spec.rb2
-rw-r--r--spec/ruby/core/io/syswrite_spec.rb10
-rw-r--r--spec/ruby/core/io/ungetbyte_spec.rb18
-rw-r--r--spec/ruby/core/io/ungetc_spec.rb2
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb10
-rw-r--r--spec/ruby/core/io/write_spec.rb34
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb89
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb10
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb10
-rw-r--r--spec/ruby/core/kernel/clone_spec.rb131
-rw-r--r--spec/ruby/core/kernel/define_singleton_method_spec.rb15
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb10
-rw-r--r--spec/ruby/core/kernel/fixtures/Complex.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/classes.rb15
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_core_method.rb2
-rw-r--r--spec/ruby/core/kernel/initialize_clone_spec.rb28
-rw-r--r--spec/ruby/core/kernel/initialize_dup_spec.rb20
-rw-r--r--spec/ruby/core/kernel/inspect_spec.rb10
-rw-r--r--spec/ruby/core/kernel/instance_variable_get_spec.rb6
-rw-r--r--spec/ruby/core/kernel/instance_variable_set_spec.rb12
-rw-r--r--spec/ruby/core/kernel/instance_variables_spec.rb11
-rw-r--r--spec/ruby/core/kernel/lambda_spec.rb12
-rw-r--r--spec/ruby/core/kernel/match_spec.rb34
-rw-r--r--spec/ruby/core/kernel/method_spec.rb24
-rw-r--r--spec/ruby/core/kernel/nil_spec.rb10
-rw-r--r--spec/ruby/core/kernel/open_spec.rb14
-rw-r--r--spec/ruby/core/kernel/p_spec.rb6
-rw-r--r--spec/ruby/core/kernel/print_spec.rb12
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb10
-rw-r--r--spec/ruby/core/kernel/rand_spec.rb4
-rw-r--r--spec/ruby/core/kernel/remove_instance_variable_spec.rb13
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/dup_clone.rb24
-rw-r--r--spec/ruby/core/kernel/shared/load.rb45
-rw-r--r--spec/ruby/core/kernel/shared/require.rb36
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb107
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb33
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb2
-rw-r--r--spec/ruby/core/kernel/srand_spec.rb16
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb45
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb12
-rw-r--r--spec/ruby/core/kernel/to_s_spec.rb10
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb25
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb25
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb25
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb28
-rw-r--r--spec/ruby/core/kernel/warn_spec.rb64
-rw-r--r--spec/ruby/core/main/fixtures/using.rb1
-rw-r--r--spec/ruby/core/main/fixtures/using_in_main.rb5
-rw-r--r--spec/ruby/core/main/fixtures/using_in_method.rb5
-rw-r--r--spec/ruby/core/main/private_spec.rb12
-rw-r--r--spec/ruby/core/main/public_spec.rb13
-rw-r--r--spec/ruby/core/main/ruby2_keywords_spec.rb10
-rw-r--r--spec/ruby/core/main/using_spec.rb20
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb71
-rw-r--r--spec/ruby/core/marshal/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/marshal/shared/load.rb315
-rw-r--r--spec/ruby/core/matchdata/allocate_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/captures_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb29
-rw-r--r--spec/ruby/core/matchdata/fixtures/classes.rb3
-rw-r--r--spec/ruby/core/matchdata/match_length_spec.rb34
-rw-r--r--spec/ruby/core/matchdata/match_spec.rb34
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb26
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb26
-rw-r--r--spec/ruby/core/matchdata/to_a_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/to_s_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/values_at_spec.rb73
-rw-r--r--spec/ruby/core/math/ldexp_spec.rb6
-rw-r--r--spec/ruby/core/math/log2_spec.rb2
-rw-r--r--spec/ruby/core/math/sqrt_spec.rb4
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb30
-rw-r--r--spec/ruby/core/method/owner_spec.rb6
-rw-r--r--spec/ruby/core/method/parameters_spec.rb15
-rw-r--r--spec/ruby/core/method/private_spec.rb21
-rw-r--r--spec/ruby/core/method/protected_spec.rb21
-rw-r--r--spec/ruby/core/method/public_spec.rb21
-rw-r--r--spec/ruby/core/method/shared/to_s.rb32
-rw-r--r--spec/ruby/core/method/super_method_spec.rb21
-rw-r--r--spec/ruby/core/method/unbind_spec.rb12
-rw-r--r--spec/ruby/core/module/allocate_spec.rb14
-rw-r--r--spec/ruby/core/module/append_features_spec.rb14
-rw-r--r--spec/ruby/core/module/autoload_spec.rb146
-rw-r--r--spec/ruby/core/module/class_variables_spec.rb8
-rw-r--r--spec/ruby/core/module/const_added_spec.rb125
-rw-r--r--spec/ruby/core/module/const_defined_spec.rb7
-rw-r--r--spec/ruby/core/module/const_get_spec.rb14
-rw-r--r--spec/ruby/core/module/const_set_spec.rb3
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb333
-rw-r--r--spec/ruby/core/module/constants_spec.rb6
-rw-r--r--spec/ruby/core/module/define_method_spec.rb94
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb23
-rw-r--r--spec/ruby/core/module/extend_object_spec.rb14
-rw-r--r--spec/ruby/core/module/fixtures/classes.rb13
-rw-r--r--spec/ruby/core/module/include_spec.rb25
-rw-r--r--spec/ruby/core/module/included_modules_spec.rb2
-rw-r--r--spec/ruby/core/module/instance_method_spec.rb42
-rw-r--r--spec/ruby/core/module/module_function_spec.rb40
-rw-r--r--spec/ruby/core/module/name_spec.rb26
-rw-r--r--spec/ruby/core/module/prepend_features_spec.rb14
-rw-r--r--spec/ruby/core/module/prepend_spec.rb14
-rw-r--r--spec/ruby/core/module/private_class_method_spec.rb12
-rw-r--r--spec/ruby/core/module/private_spec.rb24
-rw-r--r--spec/ruby/core/module/protected_spec.rb24
-rw-r--r--spec/ruby/core/module/public_class_method_spec.rb16
-rw-r--r--spec/ruby/core/module/public_spec.rb25
-rw-r--r--spec/ruby/core/module/refine_spec.rb574
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb343
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb21
-rw-r--r--spec/ruby/core/nil/match_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_s_spec.rb12
-rw-r--r--spec/ruby/core/numeric/clone_spec.rb7
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb11
-rw-r--r--spec/ruby/core/numeric/shared/step.rb1
-rw-r--r--spec/ruby/core/numeric/step_spec.rb2
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb22
-rw-r--r--spec/ruby/core/objectspace/garbage_collect_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/weakmap/element_set_spec.rb53
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/include.rb16
-rw-r--r--spec/ruby/core/proc/block_pass_spec.rb22
-rw-r--r--spec/ruby/core/proc/compose_spec.rb8
-rw-r--r--spec/ruby/core/proc/eql_spec.rb2
-rw-r--r--spec/ruby/core/proc/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/proc/new_spec.rb39
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb27
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb104
-rw-r--r--spec/ruby/core/proc/shared/compose.rb51
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb10
-rw-r--r--spec/ruby/core/process/_fork_spec.rb24
-rw-r--r--spec/ruby/core/process/clock_gettime_spec.rb101
-rw-r--r--spec/ruby/core/process/constants_spec.rb1
-rw-r--r--spec/ruby/core/process/daemon_spec.rb3
-rw-r--r--spec/ruby/core/process/detach_spec.rb29
-rw-r--r--spec/ruby/core/process/egid_spec.rb41
-rw-r--r--spec/ruby/core/process/euid_spec.rb12
-rw-r--r--spec/ruby/core/process/spawn_spec.rb50
-rw-r--r--spec/ruby/core/process/status/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/process/status/exited_spec.rb2
-rw-r--r--spec/ruby/core/process/status/exitstatus_spec.rb2
-rw-r--r--spec/ruby/core/process/status/signaled_spec.rb2
-rw-r--r--spec/ruby/core/process/status/success_spec.rb2
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb4
-rw-r--r--spec/ruby/core/process/status/to_i_spec.rb2
-rw-r--r--spec/ruby/core/process/times_spec.rb14
-rw-r--r--spec/ruby/core/process/wait2_spec.rb9
-rw-r--r--spec/ruby/core/queue/initialize_spec.rb13
-rw-r--r--spec/ruby/core/random/bytes_spec.rb2
-rw-r--r--spec/ruby/core/random/default_spec.rb51
-rw-r--r--spec/ruby/core/random/rand_spec.rb5
-rw-r--r--spec/ruby/core/random/raw_seed_spec.rb6
-rw-r--r--spec/ruby/core/random/shared/urandom.rb23
-rw-r--r--spec/ruby/core/random/urandom_spec.rb25
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb196
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb10
-rw-r--r--spec/ruby/core/range/clone_spec.rb26
-rw-r--r--spec/ruby/core/range/count_spec.rb16
-rw-r--r--spec/ruby/core/range/dup_spec.rb10
-rw-r--r--spec/ruby/core/range/each_spec.rb30
-rw-r--r--spec/ruby/core/range/equal_value_spec.rb6
-rw-r--r--spec/ruby/core/range/first_spec.rb6
-rw-r--r--spec/ruby/core/range/frozen_spec.rb27
-rw-r--r--spec/ruby/core/range/inspect_spec.rb28
-rw-r--r--spec/ruby/core/range/last_spec.rb6
-rw-r--r--spec/ruby/core/range/max_spec.rb12
-rw-r--r--spec/ruby/core/range/min_spec.rb6
-rw-r--r--spec/ruby/core/range/minmax_spec.rb124
-rw-r--r--spec/ruby/core/range/new_spec.rb32
-rw-r--r--spec/ruby/core/range/shared/cover.rb56
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb8
-rw-r--r--spec/ruby/core/range/size_spec.rb25
-rw-r--r--spec/ruby/core/range/step_spec.rb22
-rw-r--r--spec/ruby/core/range/to_a_spec.rb6
-rw-r--r--spec/ruby/core/range/to_s_spec.rb22
-rw-r--r--spec/ruby/core/rational/minus_spec.rb48
-rw-r--r--spec/ruby/core/rational/rational_spec.rb4
-rw-r--r--spec/ruby/core/refinement/append_features_spec.rb21
-rw-r--r--spec/ruby/core/refinement/extend_object_spec.rb21
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb34
-rw-r--r--spec/ruby/core/refinement/include_spec.rb27
-rw-r--r--spec/ruby/core/refinement/prepend_features_spec.rb21
-rw-r--r--spec/ruby/core/refinement/prepend_spec.rb27
-rw-r--r--spec/ruby/core/regexp/compile_spec.rb4
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb2
-rw-r--r--spec/ruby/core/regexp/new_spec.rb14
-rw-r--r--spec/ruby/core/regexp/shared/new.rb192
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb10
-rw-r--r--spec/ruby/core/regexp/source_spec.rb22
-rw-r--r--spec/ruby/core/regexp/timeout_spec.rb35
-rw-r--r--spec/ruby/core/signal/trap_spec.rb16
-rw-r--r--spec/ruby/core/string/allocate_spec.rb2
-rw-r--r--spec/ruby/core/string/append_spec.rb5
-rw-r--r--spec/ruby/core/string/b_spec.rb9
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb16
-rw-r--r--spec/ruby/core/string/bytesize_spec.rb2
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb6
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb16
-rw-r--r--spec/ruby/core/string/center_spec.rb18
-rw-r--r--spec/ruby/core/string/chars_spec.rb7
-rw-r--r--spec/ruby/core/string/chomp_spec.rb62
-rw-r--r--spec/ruby/core/string/chop_spec.rb16
-rw-r--r--spec/ruby/core/string/clone_spec.rb4
-rw-r--r--spec/ruby/core/string/comparison_spec.rb4
-rw-r--r--spec/ruby/core/string/crypt_spec.rb30
-rw-r--r--spec/ruby/core/string/dedup_spec.rb8
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb11
-rw-r--r--spec/ruby/core/string/delete_spec.rb13
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb11
-rw-r--r--spec/ruby/core/string/downcase_spec.rb16
-rw-r--r--spec/ruby/core/string/dump_spec.rb22
-rw-r--r--spec/ruby/core/string/dup_spec.rb13
-rw-r--r--spec/ruby/core/string/each_grapheme_cluster_spec.rb8
-rw-r--r--spec/ruby/core/string/element_set_spec.rb34
-rw-r--r--spec/ruby/core/string/encode_spec.rb50
-rw-r--r--spec/ruby/core/string/encoding_spec.rb1
-rw-r--r--spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb2
-rw-r--r--spec/ruby/core/string/fixtures/to_c.rb5
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb2
-rw-r--r--spec/ruby/core/string/gsub_spec.rb173
-rw-r--r--spec/ruby/core/string/include_spec.rb14
-rw-r--r--spec/ruby/core/string/index_spec.rb8
-rw-r--r--spec/ruby/core/string/insert_spec.rb21
-rw-r--r--spec/ruby/core/string/inspect_spec.rb32
-rw-r--r--spec/ruby/core/string/lines_spec.rb1
-rw-r--r--spec/ruby/core/string/ljust_spec.rb18
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb53
-rw-r--r--spec/ruby/core/string/modulo_spec.rb62
-rw-r--r--spec/ruby/core/string/ord_spec.rb5
-rw-r--r--spec/ruby/core/string/partition_spec.rb25
-rw-r--r--spec/ruby/core/string/plus_spec.rb13
-rw-r--r--spec/ruby/core/string/prepend_spec.rb10
-rw-r--r--spec/ruby/core/string/reverse_spec.rb37
-rw-r--r--spec/ruby/core/string/rindex_spec.rb23
-rw-r--r--spec/ruby/core/string/rjust_spec.rb18
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb25
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb57
-rw-r--r--spec/ruby/core/string/scan_spec.rb54
-rw-r--r--spec/ruby/core/string/scrub_spec.rb51
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb6
-rw-r--r--spec/ruby/core/string/shared/chars.rb14
-rw-r--r--spec/ruby/core/string/shared/concat.rb12
-rw-r--r--spec/ruby/core/string/shared/dedup.rb57
-rw-r--r--spec/ruby/core/string/shared/each_line.rb14
-rw-r--r--spec/ruby/core/string/shared/eql.rb6
-rw-r--r--spec/ruby/core/string/shared/length.rb26
-rw-r--r--spec/ruby/core/string/shared/partition.rb51
-rw-r--r--spec/ruby/core/string/shared/replace.rb30
-rw-r--r--spec/ruby/core/string/shared/slice.rb155
-rw-r--r--spec/ruby/core/string/shared/strip.rb24
-rw-r--r--spec/ruby/core/string/shared/succ.rb8
-rw-r--r--spec/ruby/core/string/shared/to_s.rb7
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb9
-rw-r--r--spec/ruby/core/string/slice_spec.rb85
-rw-r--r--spec/ruby/core/string/split_spec.rb165
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb15
-rw-r--r--spec/ruby/core/string/start_with_spec.rb10
-rw-r--r--spec/ruby/core/string/strip_spec.rb21
-rw-r--r--spec/ruby/core/string/sub_spec.rb136
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb11
-rw-r--r--spec/ruby/core/string/to_c_spec.rb108
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb13
-rw-r--r--spec/ruby/core/string/tr_spec.rb13
-rw-r--r--spec/ruby/core/string/uminus_spec.rb47
-rw-r--r--spec/ruby/core/string/undump_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb34
-rw-r--r--spec/ruby/core/string/unpack/c_spec.rb14
-rw-r--r--spec/ruby/core/string/unpack/h_spec.rb28
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb5
-rw-r--r--spec/ruby/core/string/unpack/p_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack/shared/basic.rb8
-rw-r--r--spec/ruby/core/string/unpack/shared/float.rb60
-rw-r--r--spec/ruby/core/string/unpack/shared/integer.rb88
-rw-r--r--spec/ruby/core/string/unpack/shared/taint.rb81
-rw-r--r--spec/ruby/core/string/unpack/shared/unicode.rb14
-rw-r--r--spec/ruby/core/string/unpack/w_spec.rb14
-rw-r--r--spec/ruby/core/string/unpack/z_spec.rb5
-rw-r--r--spec/ruby/core/string/unpack1_spec.rb26
-rw-r--r--spec/ruby/core/string/unpack_spec.rb34
-rw-r--r--spec/ruby/core/string/upcase_spec.rb16
-rw-r--r--spec/ruby/core/string/valid_encoding/utf_8_spec.rb214
-rw-r--r--spec/ruby/core/string/valid_encoding_spec.rb8
-rw-r--r--spec/ruby/core/struct/deconstruct_keys_spec.rb146
-rw-r--r--spec/ruby/core/struct/deconstruct_spec.rb12
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb8
-rw-r--r--spec/ruby/core/struct/keyword_init_spec.rb21
-rw-r--r--spec/ruby/core/struct/new_spec.rb16
-rw-r--r--spec/ruby/core/struct/values_at_spec.rb55
-rw-r--r--spec/ruby/core/symbol/end_with_spec.rb6
-rw-r--r--spec/ruby/core/symbol/shared/id2name.rb7
-rw-r--r--spec/ruby/core/symbol/shared/slice.rb20
-rw-r--r--spec/ruby/core/symbol/start_with_spec.rb6
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb31
-rw-r--r--spec/ruby/core/thread/backtrace/limit_spec.rb15
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb9
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb11
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb1
-rw-r--r--spec/ruby/core/thread/backtrace_locations_spec.rb10
-rw-r--r--spec/ruby/core/thread/ignore_deadlock_spec.rb21
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb17
-rw-r--r--spec/ruby/core/thread/raise_spec.rb24
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb51
-rw-r--r--spec/ruby/core/thread/shared/exit.rb22
-rw-r--r--spec/ruby/core/thread/shared/to_s.rb4
-rw-r--r--spec/ruby/core/time/at_spec.rb21
-rw-r--r--spec/ruby/core/time/ceil_spec.rb64
-rw-r--r--spec/ruby/core/time/floor_spec.rb52
-rw-r--r--spec/ruby/core/time/inspect_spec.rb44
-rw-r--r--spec/ruby/core/time/localtime_spec.rb16
-rw-r--r--spec/ruby/core/time/new_spec.rb145
-rw-r--r--spec/ruby/core/time/now_spec.rb45
-rw-r--r--spec/ruby/core/time/shared/gmtime.rb4
-rw-r--r--spec/ruby/core/time/shared/local.rb11
-rw-r--r--spec/ruby/core/time/shared/time_params.rb11
-rw-r--r--spec/ruby/core/time/strftime_spec.rb41
-rw-r--r--spec/ruby/core/time/utc_spec.rb41
-rw-r--r--spec/ruby/core/time/zone_spec.rb20
-rw-r--r--spec/ruby/core/tracepoint/allow_reentry_spec.rb32
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb55
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb21
-rw-r--r--spec/ruby/core/true/to_s_spec.rb12
-rw-r--r--spec/ruby/core/unboundmethod/bind_call_spec.rb74
-rw-r--r--spec/ruby/core/unboundmethod/equal_value_spec.rb76
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb16
-rw-r--r--spec/ruby/core/unboundmethod/hash_spec.rb7
-rw-r--r--spec/ruby/core/unboundmethod/owner_spec.rb7
-rw-r--r--spec/ruby/core/unboundmethod/private_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/protected_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/public_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/shared/to_s.rb16
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb23
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb16
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb44
-rw-r--r--spec/ruby/core/warning/warn_spec.rb3
-rw-r--r--spec/ruby/fixtures/class.rb4
-rw-r--r--spec/ruby/fixtures/code/a/load_fixture.dylib1
-rw-r--r--spec/ruby/fixtures/code/c/load_fixture.rb1
-rw-r--r--spec/ruby/fixtures/code/concurrent_require_fixture.rb4
-rw-r--r--spec/ruby/fixtures/code/load_fixture.dylib1
-rw-r--r--spec/ruby/fixtures/code/load_fixture.ext.dylib1
-rw-r--r--spec/ruby/fixtures/code/load_wrap_fixture.rb (renamed from spec/ruby/fixtures/code/wrap_fixture.rb)3
-rw-r--r--spec/ruby/fixtures/constants.rb21
-rw-r--r--spec/ruby/language/alias_spec.rb13
-rw-r--r--spec/ruby/language/block_spec.rb182
-rw-r--r--spec/ruby/language/case_spec.rb13
-rw-r--r--spec/ruby/language/class_spec.rb13
-rw-r--r--spec/ruby/language/class_variable_spec.rb32
-rw-r--r--spec/ruby/language/comment_spec.rb16
-rw-r--r--spec/ruby/language/constants_spec.rb48
-rw-r--r--spec/ruby/language/def_spec.rb33
-rw-r--r--spec/ruby/language/defined_spec.rb67
-rw-r--r--spec/ruby/language/delegation_spec.rb61
-rw-r--r--spec/ruby/language/file_spec.rb12
-rw-r--r--spec/ruby/language/fixtures/defined.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb2
-rw-r--r--spec/ruby/language/hash_spec.rb54
-rw-r--r--spec/ruby/language/heredoc_spec.rb18
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb397
-rw-r--r--spec/ruby/language/lambda_spec.rb64
-rw-r--r--spec/ruby/language/method_spec.rb467
-rw-r--r--spec/ruby/language/module_spec.rb15
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb174
-rw-r--r--spec/ruby/language/numbers_spec.rb2
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb38
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb2020
-rw-r--r--spec/ruby/language/precedence_spec.rb78
-rw-r--r--spec/ruby/language/predefined_spec.rb514
-rw-r--r--spec/ruby/language/proc_spec.rb27
-rw-r--r--spec/ruby/language/range_spec.rb16
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb5
-rw-r--r--spec/ruby/language/regexp/encoding_spec.rb17
-rw-r--r--spec/ruby/language/regexp/escapes_spec.rb84
-rw-r--r--spec/ruby/language/regexp/grouping_spec.rb28
-rw-r--r--spec/ruby/language/regexp_spec.rb23
-rw-r--r--spec/ruby/language/rescue_spec.rb22
-rw-r--r--spec/ruby/language/return_spec.rb61
-rw-r--r--spec/ruby/language/safe_spec.rb104
-rw-r--r--spec/ruby/language/send_spec.rb18
-rw-r--r--spec/ruby/language/singleton_class_spec.rb17
-rw-r--r--spec/ruby/language/string_spec.rb22
-rw-r--r--spec/ruby/language/variables_spec.rb66
-rw-r--r--spec/ruby/language/yield_spec.rb38
-rw-r--r--spec/ruby/library/base64/decode64_spec.rb4
-rw-r--r--spec/ruby/library/bigdecimal/exponent_spec.rb11
-rw-r--r--spec/ruby/library/bigdecimal/round_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/to_r_spec.rb12
-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/cmath/math/acos_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/acosh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/asin_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/asinh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/atan2_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/atan_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/atanh_spec.rb20
-rw-r--r--spec/ruby/library/cmath/math/cos_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/cosh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/exp_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/cmath/math/log10_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/log_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/shared/acos.rb41
-rw-r--r--spec/ruby/library/cmath/math/shared/acosh.rb37
-rw-r--r--spec/ruby/library/cmath/math/shared/asin.rb47
-rw-r--r--spec/ruby/library/cmath/math/shared/asinh.rb32
-rw-r--r--spec/ruby/library/cmath/math/shared/atan.rb32
-rw-r--r--spec/ruby/library/cmath/math/shared/atan2.rb34
-rw-r--r--spec/ruby/library/cmath/math/shared/atanh.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/cos.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/cosh.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/exp.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/log.rb39
-rw-r--r--spec/ruby/library/cmath/math/shared/log10.rb41
-rw-r--r--spec/ruby/library/cmath/math/shared/sin.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/sinh.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/sqrt.rb34
-rw-r--r--spec/ruby/library/cmath/math/shared/tan.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/tanh.rb32
-rw-r--r--spec/ruby/library/cmath/math/sin_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/sinh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/sqrt_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/tan_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/tanh_spec.rb18
-rw-r--r--spec/ruby/library/coverage/result_spec.rb77
-rw-r--r--spec/ruby/library/coverage/running_spec.rb20
-rw-r--r--spec/ruby/library/coverage/start_spec.rb8
-rw-r--r--spec/ruby/library/date/civil_spec.rb7
-rw-r--r--spec/ruby/library/date/iso8601_spec.rb9
-rw-r--r--spec/ruby/library/date/parse_spec.rb2
-rw-r--r--spec/ruby/library/date/shared/valid_jd.rb20
-rw-r--r--spec/ruby/library/date/strftime_spec.rb15
-rw-r--r--spec/ruby/library/datetime/strftime_spec.rb15
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/taint_spec.rb17
-rw-r--r--spec/ruby/library/delegate/delegator/trust_spec.rb16
-rw-r--r--spec/ruby/library/delegate/delegator/untaint_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/untrust_spec.rb17
-rw-r--r--spec/ruby/library/erb/new_spec.rb16
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb12
-rw-r--r--spec/ruby/library/fiddle/handle/initialize_spec.rb10
-rw-r--r--spec/ruby/library/io-wait/wait_readable_spec.rb27
-rw-r--r--spec/ruby/library/io-wait/wait_writable_spec.rb20
-rw-r--r--spec/ruby/library/ipaddr/new_spec.rb41
-rw-r--r--spec/ruby/library/logger/device/close_spec.rb4
-rw-r--r--spec/ruby/library/logger/device/write_spec.rb4
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb4
-rw-r--r--spec/ruby/library/net/http/http/fixtures/http_server.rb27
-rw-r--r--spec/ruby/library/objectspace/fixtures/trace.rb5
-rw-r--r--spec/ruby/library/objectspace/memsize_of_all_spec.rb7
-rw-r--r--spec/ruby/library/objectspace/trace_object_allocations_spec.rb18
-rw-r--r--spec/ruby/library/objectspace/trace_spec.rb15
-rw-r--r--spec/ruby/library/openssl/x509/name/verify_spec.rb78
-rw-r--r--spec/ruby/library/openstruct/method_missing_spec.rb8
-rw-r--r--spec/ruby/library/pathname/birthtime_spec.rb16
-rw-r--r--spec/ruby/library/pathname/glob_spec.rb53
-rw-r--r--spec/ruby/library/pathname/new_spec.rb7
-rw-r--r--spec/ruby/library/pathname/pathname_spec.rb19
-rw-r--r--spec/ruby/library/pp/pp_spec.rb7
-rw-r--r--spec/ruby/library/rbconfig/rbconfig_spec.rb13
-rw-r--r--spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb25
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb25
-rw-r--r--spec/ruby/library/readline/history/delete_at_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/each_spec.rb8
-rw-r--r--spec/ruby/library/readline/history/element_reference_spec.rb7
-rw-r--r--spec/ruby/library/readline/history/pop_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/shift_spec.rb9
-rw-r--r--spec/ruby/library/readline/readline_spec.rb7
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb18
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_text_spec.rb4
-rw-r--r--spec/ruby/library/rexml/element/has_text_spec.rb2
-rw-r--r--spec/ruby/library/rexml/node/parent_spec.rb2
-rw-r--r--spec/ruby/library/rexml/shared/elements_to_a.rb2
-rw-r--r--spec/ruby/library/scanf/io/block_scanf_spec.rb10
-rw-r--r--spec/ruby/library/scanf/io/fixtures/date.txt4
-rw-r--r--spec/ruby/library/scanf/io/fixtures/helloworld.txt1
-rw-r--r--spec/ruby/library/scanf/io/scanf_spec.rb38
-rw-r--r--spec/ruby/library/scanf/io/shared/block_scanf.rb28
-rw-r--r--spec/ruby/library/scanf/string/block_scanf_spec.rb10
-rw-r--r--spec/ruby/library/scanf/string/scanf_spec.rb56
-rw-r--r--spec/ruby/library/scanf/string/shared/block_scanf.rb25
-rw-r--r--spec/ruby/library/set/comparison_spec.rb29
-rw-r--r--spec/ruby/library/set/initialize_clone_spec.rb18
-rw-r--r--spec/ruby/library/set/join_spec.rb31
-rw-r--r--spec/ruby/library/set/pretty_print_spec.rb20
-rw-r--r--spec/ruby/library/set/sortedset/sortedset_spec.rb22
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/local_address_spec.rb10
-rw-r--r--spec/ruby/library/socket/basicsocket/remote_address_spec.rb10
-rw-r--r--spec/ruby/library/socket/shared/address.rb249
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb7
-rw-r--r--spec/ruby/library/socket/socket/bind_spec.rb4
-rw-r--r--spec/ruby/library/socket/tcpsocket/initialize_spec.rb5
-rw-r--r--spec/ruby/library/socket/tcpsocket/new_spec.rb5
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb23
-rw-r--r--spec/ruby/library/stringio/append_spec.rb7
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb4
-rw-r--r--spec/ruby/library/stringio/each_spec.rb8
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb4
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb85
-rw-r--r--spec/ruby/library/stringio/new_spec.rb8
-rw-r--r--spec/ruby/library/stringio/open_spec.rb12
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb27
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb15
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb14
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb11
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb20
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb18
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb17
-rw-r--r--spec/ruby/library/stringio/shared/each.rb58
-rw-r--r--spec/ruby/library/stringio/shared/read.rb6
-rw-r--r--spec/ruby/library/stringio/shared/write.rb40
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb12
-rw-r--r--spec/ruby/library/stringio/ungetbyte_spec.rb38
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb9
-rw-r--r--spec/ruby/library/stringscanner/check_until_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/exist_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/matched_size_spec.rb21
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb44
-rw-r--r--spec/ruby/library/stringscanner/scan_until_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/search_full_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range.rb13
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range_matched.rb11
-rw-r--r--spec/ruby/library/stringscanner/shared/matched_size.rb21
-rw-r--r--spec/ruby/library/stringscanner/shared/peek.rb10
-rw-r--r--spec/ruby/library/stringscanner/size_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/skip_until_spec.rb6
-rw-r--r--spec/ruby/library/time/to_datetime_spec.rb18
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb12
-rw-r--r--spec/ruby/library/zlib/crc_table_spec.rb143
-rw-r--r--spec/ruby/library/zlib/deflate/deflate_spec.rb5
-rw-r--r--spec/ruby/library/zlib/inflate/inflate_spec.rb7
-rw-r--r--spec/ruby/optional/capi/binding_spec.rb21
-rw-r--r--spec/ruby/optional/capi/class_spec.rb70
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb73
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c37
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c33
-rw-r--r--spec/ruby/optional/capi/ext/fiber_spec.c11
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c35
-rw-r--r--spec/ruby/optional/capi/ext/globals_spec.c34
-rw-r--r--spec/ruby/optional/capi/ext/integer_spec.c2
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c43
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c32
-rw-r--r--spec/ruby/optional/capi/ext/module_spec.c56
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c49
-rw-r--r--spec/ruby/optional/capi/ext/proc_spec.c59
-rw-r--r--spec/ruby/optional/capi/ext/rbasic_spec.c28
-rw-r--r--spec/ruby/optional/capi/ext/regexp_spec.c7
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h34
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c95
-rw-r--r--spec/ruby/optional/capi/ext/symbol_spec.c11
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c38
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c21
-rw-r--r--spec/ruby/optional/capi/fiber_spec.rb38
-rw-r--r--spec/ruby/optional/capi/fixtures/class.rb13
-rw-r--r--spec/ruby/optional/capi/fixtures/object.rb29
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb30
-rw-r--r--spec/ruby/optional/capi/globals_spec.rb54
-rw-r--r--spec/ruby/optional/capi/io_spec.rb15
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb94
-rw-r--r--spec/ruby/optional/capi/module_spec.rb30
-rw-r--r--spec/ruby/optional/capi/object_spec.rb141
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb55
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb21
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb16
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb56
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb13
-rw-r--r--spec/ruby/optional/capi/string_spec.rb262
-rw-r--r--spec/ruby/optional/capi/symbol_spec.rb8
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb10
-rw-r--r--spec/ruby/optional/capi/util_spec.rb24
-rw-r--r--spec/ruby/security/cve_2010_1330_spec.rb2
-rw-r--r--spec/ruby/security/cve_2013_4164_spec.rb4
-rw-r--r--spec/ruby/security/cve_2014_8080_spec.rb1
-rw-r--r--spec/ruby/security/cve_2018_16396_spec.rb18
-rw-r--r--spec/ruby/security/cve_2018_8778_spec.rb2
-rw-r--r--spec/ruby/security/cve_2019_8325_spec.rb58
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb25
-rw-r--r--spec/ruby/shared/file/executable.rb35
-rw-r--r--spec/ruby/shared/file/executable_real.rb35
-rw-r--r--spec/ruby/shared/file/readable.rb16
-rw-r--r--spec/ruby/shared/file/readable_real.rb16
-rw-r--r--spec/ruby/shared/file/writable.rb16
-rw-r--r--spec/ruby/shared/file/writable_real.rb16
-rw-r--r--spec/ruby/shared/kernel/complex.rb133
-rw-r--r--spec/ruby/shared/kernel/raise.rb34
-rw-r--r--spec/ruby/shared/process/exit.rb6
-rw-r--r--spec/ruby/shared/queue/deque.rb62
-rw-r--r--spec/ruby/shared/rational/Rational.rb48
-rw-r--r--spec/ruby/shared/rational/divmod.rb6
-rw-r--r--spec/ruby/shared/rational/exponent.rb8
-rw-r--r--spec/ruby/shared/rational/minus.rb48
-rw-r--r--spec/ruby/shared/rational/to_f.rb6
-rw-r--r--spec/ruby/shared/sizedqueue/enque.rb63
-rw-r--r--spec/ruby/shared/sizedqueue/new.rb9
-rw-r--r--spec/ruby/shared/string/end_with.rb9
-rw-r--r--spec/ruby/shared/string/start_with.rb4
-rw-r--r--spec/ruby/shared/string/times.rb12
-rw-r--r--spec/ruby/spec_helper.rb10
-rw-r--r--spec/syntax_suggest/fixtures/derailed_require_tree.rb.txt74
-rwxr-xr-xspec/syntax_suggest/fixtures/rexe.rb.txt569
-rw-r--r--spec/syntax_suggest/fixtures/routes.rb.txt121
-rw-r--r--spec/syntax_suggest/fixtures/ruby_buildpack.rb.txt1344
-rw-r--r--spec/syntax_suggest/fixtures/syntax_tree.rb.txt9234
-rw-r--r--spec/syntax_suggest/fixtures/this_project_extra_def.rb.txt64
-rw-r--r--spec/syntax_suggest/fixtures/webmock.rb.txt35
-rw-r--r--spec/syntax_suggest/integration/exe_cli_spec.rb27
-rw-r--r--spec/syntax_suggest/integration/ruby_command_line_spec.rb193
-rw-r--r--spec/syntax_suggest/integration/syntax_suggest_spec.rb239
-rw-r--r--spec/syntax_suggest/spec_helper.rb104
-rw-r--r--spec/syntax_suggest/unit/api_spec.rb108
-rw-r--r--spec/syntax_suggest/unit/around_block_scan_spec.rb165
-rw-r--r--spec/syntax_suggest/unit/block_expand_spec.rb230
-rw-r--r--spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb47
-rw-r--r--spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb44
-rw-r--r--spec/syntax_suggest/unit/capture_code_context_spec.rb229
-rw-r--r--spec/syntax_suggest/unit/clean_document_spec.rb260
-rw-r--r--spec/syntax_suggest/unit/cli_spec.rb224
-rw-r--r--spec/syntax_suggest/unit/code_block_spec.rb77
-rw-r--r--spec/syntax_suggest/unit/code_frontier_spec.rb135
-rw-r--r--spec/syntax_suggest/unit/code_line_spec.rb165
-rw-r--r--spec/syntax_suggest/unit/code_search_spec.rb505
-rw-r--r--spec/syntax_suggest/unit/core_ext_spec.rb34
-rw-r--r--spec/syntax_suggest/unit/display_invalid_blocks_spec.rb174
-rw-r--r--spec/syntax_suggest/unit/explain_syntax_spec.rb255
-rw-r--r--spec/syntax_suggest/unit/lex_all_spec.rb29
-rw-r--r--spec/syntax_suggest/unit/pathname_from_message_spec.rb56
-rw-r--r--spec/syntax_suggest/unit/priority_queue_spec.rb95
-rw-r--r--spec/syntax_suggest/unit/scan_history_spec.rb114
-rw-r--r--sprintf.c1368
-rw-r--r--st.c717
-rw-r--r--strftime.c11
-rw-r--r--string.c9295
-rw-r--r--string.rb552
-rw-r--r--struct.c1760
-rw-r--r--symbol.c463
-rw-r--r--symbol.h20
-rw-r--r--symbol.rb15
-rw-r--r--template/Doxyfile.tmpl2543
-rw-r--r--template/GNUmakefile.in17
-rw-r--r--template/Makefile.in118
-rw-r--r--template/extinit.c.tmpl2
-rw-r--r--template/exts.mk.tmpl9
-rw-r--r--template/fake.rb.in39
-rw-r--r--template/id.c.tmpl5
-rw-r--r--template/id.h.tmpl10
-rw-r--r--template/prelude.c.tmpl110
-rw-r--r--template/ruby.pc.in16
-rw-r--r--test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb52
-rw-r--r--test/-ext-/array/test_to_ary_concat.rb20
-rw-r--r--test/-ext-/bignum/test_big2str.rb38
-rw-r--r--test/-ext-/bignum/test_bigzero.rb20
-rw-r--r--test/-ext-/bignum/test_div.rb38
-rw-r--r--test/-ext-/bignum/test_mul.rb260
-rw-r--r--test/-ext-/bignum/test_pack.rb653
-rw-r--r--test/-ext-/bignum/test_str2big.rb52
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb15
-rw-r--r--test/-ext-/debug/test_profile_frames.rb24
-rw-r--r--test/-ext-/econv/test_append.rb23
-rw-r--r--test/-ext-/eval/test_eval.rb12
-rw-r--r--test/-ext-/float/test_nextafter.rb4
-rw-r--r--test/-ext-/funcall/test_funcall.rb11
-rw-r--r--test/-ext-/funcall/test_passing_block.rb5
-rw-r--r--test/-ext-/gvl/test_ubf_async_safe.rb2
-rw-r--r--test/-ext-/iseq_load/test_iseq_load.rb6
-rw-r--r--test/-ext-/postponed_job/test_postponed_job.rb7
-rw-r--r--test/-ext-/string/test_capacity.rb42
-rw-r--r--test/-ext-/string/test_cstr.rb6
-rw-r--r--test/-ext-/string/test_fstring.rb22
-rw-r--r--test/-ext-/string/test_rb_str_dup.rb6
-rw-r--r--test/-ext-/string/test_set_len.rb39
-rw-r--r--test/-ext-/symbol/test_type.rb14
-rw-r--r--test/-ext-/test_abi.rb47
-rw-r--r--test/-ext-/test_random.rb26
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb91
-rw-r--r--test/-ext-/thread_fd/test_thread_fd_close.rb1
-rw-r--r--test/-ext-/wait/test_wait.rb16
-rw-r--r--test/bigdecimal/helper.rb11
-rw-r--r--test/bigdecimal/test_bigdecimal.rb203
-rw-r--r--test/bigdecimal/test_bigdecimal_util.rb15
-rw-r--r--test/bigdecimal/test_ractor.rb2
-rw-r--r--test/cgi/test_cgi_cookie.rb90
-rw-r--r--test/cgi/test_cgi_header.rb8
-rw-r--r--test/cgi/test_cgi_util.rb85
-rw-r--r--test/coverage/autostart.rb2
-rw-r--r--test/coverage/main.rb1
-rw-r--r--test/coverage/test_coverage.rb217
-rw-r--r--test/csv/interface/test_read.rb48
-rw-r--r--test/csv/interface/test_read_write.rb9
-rw-r--r--test/csv/interface/test_write.rb43
-rw-r--r--test/csv/parse/test_convert.rb57
-rw-r--r--test/csv/parse/test_general.rb86
-rw-r--r--test/csv/parse/test_header.rb9
-rw-r--r--test/csv/parse/test_inputs_scanner.rb63
-rw-r--r--test/csv/parse/test_invalid.rb13
-rw-r--r--test/csv/parse/test_liberal_parsing.rb11
-rw-r--r--test/csv/parse/test_read.rb27
-rw-r--r--test/csv/parse/test_strip.rb29
-rw-r--r--test/csv/test_data_converters.rb84
-rw-r--r--test/csv/test_encodings.rb31
-rw-r--r--test/csv/test_patterns.rb27
-rw-r--r--test/csv/test_table.rb75
-rw-r--r--test/date/test_date.rb29
-rw-r--r--test/date/test_date_conv.rb17
-rw-r--r--test/date/test_date_parse.rb85
-rw-r--r--test/date/test_date_ractor.rb2
-rw-r--r--test/date/test_date_strftime.rb4
-rw-r--r--test/date/test_date_strptime.rb9
-rw-r--r--test/did_you_mean/core_ext/test_name_error_extension.rb23
-rw-r--r--test/did_you_mean/helper.rb14
-rw-r--r--test/did_you_mean/spell_checking/test_key_name_check.rb14
-rw-r--r--test/did_you_mean/spell_checking/test_method_name_check.rb38
-rw-r--r--test/did_you_mean/spell_checking/test_pattern_key_name_check.rb20
-rw-r--r--test/did_you_mean/spell_checking/test_require_path_check.rb6
-rw-r--r--test/did_you_mean/spell_checking/test_variable_name_check.rb36
-rw-r--r--test/did_you_mean/test_ractor_compatibility.rb117
-rw-r--r--test/did_you_mean/test_spell_checker.rb1
-rw-r--r--test/did_you_mean/test_verbose_formatter.rb23
-rw-r--r--test/did_you_mean/tree_spell/test_change_word.rb2
-rw-r--r--test/digest/test_digest_extend.rb13
-rw-r--r--test/digest/test_ractor.rb6
-rw-r--r--test/drb/drbtest.rb8
-rw-r--r--test/drb/test_drb.rb5
-rw-r--r--test/drb/test_drbssl.rb8
-rw-r--r--test/dtrace/helper.rb2
-rw-r--r--test/erb/test_erb.rb30
-rw-r--r--test/erb/test_erb_command.rb18
-rw-r--r--test/error_highlight/test_error_highlight.rb135
-rw-r--r--test/excludes/TestArray.rb1
-rw-r--r--test/excludes/TestGem.rb4
-rw-r--r--test/excludes/TestThread.rb12
-rw-r--r--test/excludes/TestThreadQueue.rb9
-rw-r--r--test/fiber/autoload.rb3
-rw-r--r--test/fiber/scheduler.rb129
-rw-r--r--test/fiber/test_address_resolve.rb2
-rw-r--r--test/fiber/test_enumerator.rb16
-rw-r--r--test/fiber/test_io.rb150
-rw-r--r--test/fiber/test_io_buffer.rb158
-rw-r--r--test/fiber/test_mutex.rb22
-rw-r--r--test/fiber/test_process.rb36
-rw-r--r--test/fiber/test_queue.rb54
-rw-r--r--test/fiber/test_ractor.rb2
-rw-r--r--test/fiber/test_scheduler.rb120
-rw-r--r--test/fiber/test_storage.rb115
-rw-r--r--test/fiber/test_thread.rb22
-rw-r--r--test/fiddle/helper.rb30
-rw-r--r--test/fiddle/test_c_struct_builder.rb33
-rw-r--r--test/fiddle/test_closure.rb111
-rw-r--r--test/fiddle/test_cparser.rb2
-rw-r--r--test/fiddle/test_fiddle.rb41
-rw-r--r--test/fiddle/test_func.rb57
-rw-r--r--test/fiddle/test_function.rb64
-rw-r--r--test/fiddle/test_handle.rb18
-rw-r--r--test/fiddle/test_import.rb23
-rw-r--r--test/fiddle/test_memory_view.rb8
-rw-r--r--test/fiddle/test_pack.rb37
-rw-r--r--test/fiddle/test_pointer.rb24
-rw-r--r--test/fileutils/clobber.rb5
-rw-r--r--test/fileutils/test_dryrun.rb2
-rw-r--r--test/fileutils/test_fileutils.rb93
-rw-r--r--test/fileutils/test_nowrite.rb2
-rw-r--r--test/fileutils/test_verbose.rb2
-rw-r--r--test/fileutils/visibility_tests.rb5
-rw-r--r--test/io/console/test_io_console.rb42
-rw-r--r--test/io/nonblock/test_flush.rb2
-rw-r--r--test/io/wait/test_io_wait.rb36
-rw-r--r--test/io/wait/test_io_wait_uncommon.rb5
-rw-r--r--test/io/wait/test_ractor.rb7
-rw-r--r--test/irb/helper.rb76
-rw-r--r--test/irb/test_cmd.rb855
-rw-r--r--test/irb/test_color.rb86
-rw-r--r--test/irb/test_color_printer.rb7
-rw-r--r--test/irb/test_completion.rb354
-rw-r--r--test/irb/test_context.rb386
-rw-r--r--test/irb/test_debug_cmd.rb303
-rw-r--r--test/irb/test_history.rb68
-rw-r--r--test/irb/test_init.rb82
-rw-r--r--test/irb/test_input_method.rb79
-rw-r--r--test/irb/test_option.rb4
-rw-r--r--test/irb/test_raise_no_backtrace_exception.rb12
-rw-r--r--test/irb/test_ruby_lex.rb199
-rw-r--r--test/irb/test_workspace.rb26
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb92
-rw-r--r--test/json/json_addition_test.rb2
-rw-r--r--test/json/json_parser_test.rb5
-rw-r--r--test/lib/jit_support.rb49
-rw-r--r--test/logger/helper.rb13
-rw-r--r--test/logger/test_formatter.rb35
-rw-r--r--test/logger/test_logdevice.rb5
-rw-r--r--test/logger/test_logger.rb8
-rw-r--r--test/logger/test_logperiod.rb2
-rw-r--r--test/logger/test_severity.rb2
-rw-r--r--test/mkmf/base.rb226
-rw-r--r--test/mkmf/test_config.rb16
-rw-r--r--test/mkmf/test_constant.rb60
-rw-r--r--test/mkmf/test_convertible.rb48
-rw-r--r--test/mkmf/test_egrep_cpp.rb14
-rw-r--r--test/mkmf/test_find_executable.rb82
-rw-r--r--test/mkmf/test_flags.rb92
-rw-r--r--test/mkmf/test_framework.rb70
-rw-r--r--test/mkmf/test_have_func.rb18
-rw-r--r--test/mkmf/test_have_library.rb84
-rw-r--r--test/mkmf/test_have_macro.rb46
-rw-r--r--test/mkmf/test_have_var.rb17
-rw-r--r--test/mkmf/test_install.rb38
-rw-r--r--test/mkmf/test_libs.rb156
-rw-r--r--test/mkmf/test_mkmf.rb14
-rw-r--r--test/mkmf/test_pkg_config.rb66
-rw-r--r--test/mkmf/test_signedness.rb38
-rw-r--r--test/mkmf/test_sizeof.rb74
-rw-r--r--test/net/fixtures/Makefile6
-rw-r--r--test/net/fixtures/cacert.pem44
-rw-r--r--test/net/fixtures/server.crt99
-rw-r--r--test/net/fixtures/server.key55
-rw-r--r--test/net/http/test_http.rb140
-rw-r--r--test/net/http/test_http_request.rb5
-rw-r--r--test/net/http/test_httpheader.rb27
-rw-r--r--test/net/http/test_httpresponse.rb289
-rw-r--r--test/net/http/test_https.rb20
-rw-r--r--test/net/http/test_https_proxy.rb2
-rw-r--r--test/net/protocol/test_protocol.rb37
-rw-r--r--test/objspace/test_objspace.rb242
-rw-r--r--test/objspace/test_ractor.rb17
-rw-r--r--test/open-uri/test_open-uri.rb11
-rw-r--r--test/open-uri/test_ssl.rb19
-rw-r--r--test/openssl/fixtures/pkey/p256_too_large.pem5
-rw-r--r--test/openssl/fixtures/pkey/p384_invalid.pem6
-rw-r--r--test/openssl/test_asn1.rb24
-rw-r--r--test/openssl/test_bn.rb35
-rw-r--r--test/openssl/test_cipher.rb19
-rw-r--r--test/openssl/test_config.rb16
-rw-r--r--test/openssl/test_digest.rb2
-rw-r--r--test/openssl/test_hmac.rb8
-rw-r--r--test/openssl/test_ns_spki.rb2
-rw-r--r--test/openssl/test_ocsp.rb2
-rw-r--r--test/openssl/test_pair.rb5
-rw-r--r--test/openssl/test_pkcs12.rb297
-rw-r--r--test/openssl/test_pkey.rb32
-rw-r--r--test/openssl/test_pkey_dh.rb64
-rw-r--r--test/openssl/test_pkey_dsa.rb46
-rw-r--r--test/openssl/test_pkey_ec.rb132
-rw-r--r--test/openssl/test_pkey_rsa.rb147
-rw-r--r--test/openssl/test_ssl.rb476
-rw-r--r--test/openssl/test_ssl_session.rb10
-rw-r--r--test/openssl/test_ts.rb18
-rw-r--r--test/openssl/test_x509cert.rb4
-rw-r--r--test/openssl/test_x509crl.rb20
-rw-r--r--test/openssl/test_x509req.rb30
-rw-r--r--test/openssl/utils.rb49
-rw-r--r--test/optparse/test_acceptable.rb2
-rw-r--r--test/optparse/test_autoconf.rb4
-rw-r--r--test/optparse/test_bash_completion.rb4
-rw-r--r--test/optparse/test_cclass.rb2
-rw-r--r--test/optparse/test_did_you_mean.rb22
-rw-r--r--test/optparse/test_getopts.rb4
-rw-r--r--test/optparse/test_kwargs.rb4
-rw-r--r--test/optparse/test_load.rb141
-rw-r--r--test/optparse/test_noarg.rb6
-rw-r--r--test/optparse/test_optarg.rb2
-rw-r--r--test/optparse/test_optparse.rb15
-rw-r--r--test/optparse/test_placearg.rb8
-rw-r--r--test/optparse/test_reqarg.rb10
-rw-r--r--test/optparse/test_summary.rb25
-rw-r--r--test/optparse/test_zsh_completion.rb4
-rw-r--r--test/ostruct/test_ostruct.rb19
-rw-r--r--test/pathname/test_pathname.rb61
-rw-r--r--test/pathname/test_ractor.rb2
-rw-r--r--test/psych/helper.rb6
-rw-r--r--test/psych/test_array.rb16
-rw-r--r--test/psych/test_coder.rb6
-rw-r--r--test/psych/test_date_time.rb20
-rw-r--r--test/psych/test_encoding.rb7
-rw-r--r--test/psych/test_hash.rb64
-rw-r--r--test/psych/test_merge_keys.rb2
-rw-r--r--test/psych/test_numeric.rb11
-rw-r--r--test/psych/test_object.rb13
-rw-r--r--test/psych/test_parser.rb8
-rw-r--r--test/psych/test_safe_load.rb31
-rw-r--r--test/psych/test_scalar_scanner.rb74
-rw-r--r--test/psych/test_string.rb13
-rw-r--r--test/psych/test_yaml.rb2
-rw-r--r--test/racc/assets/mof.y6
-rw-r--r--test/racc/case.rb (renamed from test/racc/helper.rb)12
-rw-r--r--test/racc/regress/mof6
-rw-r--r--test/racc/test_chk_y.rb2
-rw-r--r--test/racc/test_grammar_file_parser.rb2
-rw-r--r--test/racc/test_racc_command.rb2
-rw-r--r--test/racc/test_scan_y.rb2
-rw-r--r--test/rdoc/helper.rb6
-rw-r--r--test/rdoc/support/test_case.rb23
-rw-r--r--test/rdoc/test_rdoc_alias.rb3
-rw-r--r--test/rdoc/test_rdoc_any_method.rb64
-rw-r--r--test/rdoc/test_rdoc_class_module.rb11
-rw-r--r--test/rdoc/test_rdoc_code_object.rb2
-rw-r--r--test/rdoc/test_rdoc_constant.rb2
-rw-r--r--test/rdoc/test_rdoc_context.rb4
-rw-r--r--test/rdoc/test_rdoc_cross_reference.rb58
-rw-r--r--test/rdoc/test_rdoc_extend.rb11
-rw-r--r--test/rdoc/test_rdoc_generator_darkfish.rb116
-rw-r--r--test/rdoc/test_rdoc_generator_json_index.rb16
-rw-r--r--test/rdoc/test_rdoc_include.rb14
-rw-r--r--test/rdoc/test_rdoc_markdown.rb27
-rw-r--r--test/rdoc/test_rdoc_markdown_test.rb4
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb2
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb103
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb9
-rw-r--r--test/rdoc/test_rdoc_method_attr.rb3
-rw-r--r--test/rdoc/test_rdoc_normal_class.rb7
-rw-r--r--test/rdoc/test_rdoc_normal_module.rb3
-rw-r--r--test/rdoc/test_rdoc_options.rb134
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb266
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb23
-rw-r--r--test/rdoc/test_rdoc_rd_block_parser.rb21
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb101
-rw-r--r--test/rdoc/test_rdoc_require.rb3
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb51
-rw-r--r--test/rdoc/test_rdoc_rubygems_hook.rb10
-rw-r--r--test/rdoc/test_rdoc_servlet.rb4
-rw-r--r--test/rdoc/test_rdoc_store.rb11
-rw-r--r--test/rdoc/test_rdoc_task.rb1
-rw-r--r--test/rdoc/test_rdoc_text.rb10
-rw-r--r--test/rdoc/test_rdoc_top_level.rb7
-rw-r--r--test/rdoc/xref_data.rb17
-rw-r--r--test/rdoc/xref_test_case.rb8
-rw-r--r--test/readline/test_readline.rb62
-rw-r--r--test/reline/helper.rb13
-rw-r--r--test/reline/test_config.rb41
-rw-r--r--test/reline/test_key_actor_emacs.rb82
-rw-r--r--test/reline/test_key_actor_vi.rb66
-rw-r--r--test/reline/test_key_stroke.rb32
-rw-r--r--test/reline/test_reline.rb159
-rw-r--r--test/reline/test_reline_key.rb53
-rw-r--r--test/reline/test_terminfo.rb37
-rw-r--r--test/reline/test_unicode.rb5
-rw-r--r--test/reline/test_within_pipe.rb2
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl141
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb6
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb598
-rw-r--r--test/resolv/test_addr.rb4
-rw-r--r--test/resolv/test_dns.rb15
-rw-r--r--test/rinda/test_rinda.rb98
-rw-r--r--test/ripper/test_lexer.rb86
-rw-r--r--test/ripper/test_parser_events.rb55
-rw-r--r--test/ripper/test_ripper.rb31
-rw-r--r--test/ripper/test_scanner_events.rb48
-rw-r--r--test/ripper/test_sexp.rb14
-rw-r--r--test/ruby/enc/test_case_comprehensive.rb2
-rw-r--r--test/ruby/enc/test_cesu8.rb4
-rw-r--r--test/ruby/enc/test_emoji_breaks.rb208
-rw-r--r--test/ruby/enc/test_grapheme_breaks.rb117
-rw-r--r--test/ruby/enc/test_regex_casefold.rb2
-rw-r--r--test/ruby/test_alias.rb39
-rw-r--r--test/ruby/test_argf.rb16
-rw-r--r--test/ruby/test_arity.rb44
-rw-r--r--test/ruby/test_array.rb162
-rw-r--r--test/ruby/test_assignment.rb118
-rw-r--r--test/ruby/test_ast.rb638
-rw-r--r--test/ruby/test_autoload.rb131
-rw-r--r--test/ruby/test_backtrace.rb29
-rw-r--r--test/ruby/test_bignum.rb13
-rw-r--r--test/ruby/test_call.rb7
-rw-r--r--test/ruby/test_class.rb88
-rw-r--r--test/ruby/test_clone.rb53
-rw-r--r--test/ruby/test_complex.rb119
-rw-r--r--test/ruby/test_complex2.rb2
-rw-r--r--test/ruby/test_complexrational.rb4
-rw-r--r--test/ruby/test_data.rb249
-rw-r--r--test/ruby/test_default_gems.rb2
-rw-r--r--test/ruby/test_dir.rb81
-rw-r--r--test/ruby/test_dup.rb110
-rw-r--r--test/ruby/test_encoding.rb21
-rw-r--r--test/ruby/test_enum.rb25
-rw-r--r--test/ruby/test_enumerator.rb119
-rw-r--r--test/ruby/test_env.rb910
-rw-r--r--test/ruby/test_eval.rb70
-rw-r--r--test/ruby/test_exception.rb167
-rw-r--r--test/ruby/test_fiber.rb17
-rw-r--r--test/ruby/test_file.rb54
-rw-r--r--test/ruby/test_file_exhaustive.rb104
-rw-r--r--test/ruby/test_float.rb35
-rw-r--r--test/ruby/test_frozen.rb30
-rw-r--r--test/ruby/test_gc.rb151
-rw-r--r--test/ruby/test_gc_compact.rb335
-rw-r--r--test/ruby/test_hash.rb147
-rw-r--r--test/ruby/test_inlinecache.rb2
-rw-r--r--test/ruby/test_integer.rb75
-rw-r--r--test/ruby/test_io.rb255
-rw-r--r--test/ruby/test_io_buffer.rb562
-rw-r--r--test/ruby/test_io_m17n.rb10
-rw-r--r--test/ruby/test_io_timeout.rb58
-rw-r--r--test/ruby/test_iseq.rb205
-rw-r--r--test/ruby/test_jit_debug.rb17
-rw-r--r--test/ruby/test_keyword.rb280
-rw-r--r--test/ruby/test_lazy_enumerator.rb20
-rw-r--r--test/ruby/test_literal.rb37
-rw-r--r--test/ruby/test_m17n.rb61
-rw-r--r--test/ruby/test_marshal.rb136
-rw-r--r--test/ruby/test_method.rb224
-rw-r--r--test/ruby/test_mjit.rb (renamed from test/ruby/test_jit.rb)410
-rw-r--r--test/ruby/test_mjit_debug.rb17
-rw-r--r--test/ruby/test_module.rb289
-rw-r--r--test/ruby/test_numeric.rb3
-rw-r--r--test/ruby/test_object.rb31
-rw-r--r--test/ruby/test_objectspace.rb7
-rw-r--r--test/ruby/test_optimization.rb104
-rw-r--r--test/ruby/test_pack.rb94
-rw-r--r--test/ruby/test_parse.rb86
-rw-r--r--test/ruby/test_pattern_matching.rb204
-rw-r--r--test/ruby/test_proc.rb172
-rw-r--r--test/ruby/test_process.rb320
-rw-r--r--test/ruby/test_rand.rb14
-rw-r--r--test/ruby/test_random_formatter.rb123
-rw-r--r--test/ruby/test_range.rb108
-rw-r--r--test/ruby/test_rational.rb2
-rw-r--r--test/ruby/test_refinement.rb301
-rw-r--r--test/ruby/test_regexp.rb491
-rw-r--r--test/ruby/test_require.rb180
-rw-r--r--test/ruby/test_require_lib.rb2
-rw-r--r--test/ruby/test_rubyoptions.rb115
-rw-r--r--test/ruby/test_rubyvm.rb57
-rw-r--r--test/ruby/test_rubyvm_jit.rb91
-rw-r--r--test/ruby/test_rubyvm_mjit.rb105
-rw-r--r--test/ruby/test_settracefunc.rb561
-rw-r--r--test/ruby/test_shapes.rb441
-rw-r--r--test/ruby/test_signal.rb5
-rw-r--r--test/ruby/test_sprintf.rb40
-rw-r--r--test/ruby/test_string.rb839
-rw-r--r--test/ruby/test_struct.rb61
-rw-r--r--test/ruby/test_super.rb66
-rw-r--r--test/ruby/test_symbol.rb13
-rw-r--r--test/ruby/test_syntax.rb236
-rw-r--r--test/ruby/test_thread.rb119
-rw-r--r--test/ruby/test_thread_cv.rb3
-rw-r--r--test/ruby/test_thread_queue.rb59
-rw-r--r--test/ruby/test_time.rb174
-rw-r--r--test/ruby/test_time_tz.rb38
-rw-r--r--test/ruby/test_transcode.rb14
-rw-r--r--test/ruby/test_undef.rb16
-rw-r--r--test/ruby/test_variable.rb25
-rw-r--r--test/ruby/test_vm_dump.rb4
-rw-r--r--test/ruby/test_weakmap.rb57
-rw-r--r--test/ruby/test_yjit.rb1333
-rw-r--r--test/ruby/test_yjit_exit_locations.rb110
-rw-r--r--test/rubygems/alternate_cert.pem28
-rw-r--r--test/rubygems/alternate_cert_32.pem30
-rw-r--r--test/rubygems/alternate_key.pem50
-rw-r--r--test/rubygems/bad_rake.rb1
-rw-r--r--test/rubygems/bogussources.rb9
-rw-r--r--test/rubygems/bundler_test_gem.rb421
-rw-r--r--test/rubygems/child_cert.pem31
-rw-r--r--test/rubygems/child_cert_32.pem31
-rw-r--r--test/rubygems/child_key.pem50
-rw-r--r--test/rubygems/data/excon-0.7.7.gemspec.rzbin0 -> 388 bytes-rw-r--r--test/rubygems/data/null-type.gemspec.rzbin504 -> 0 bytes-rw-r--r--test/rubygems/data/pry-0.4.7.gemspec.rzbin0 -> 433 bytes-rw-r--r--test/rubygems/encrypted_private_key.pem52
-rw-r--r--test/rubygems/expired_cert.pem30
-rw-r--r--test/rubygems/fake_certlib/openssl.rb1
-rw-r--r--test/rubygems/future_cert.pem30
-rw-r--r--test/rubygems/future_cert_32.pem30
-rw-r--r--test/rubygems/good_rake.rb1
-rw-r--r--test/rubygems/grandchild_cert.pem31
-rw-r--r--test/rubygems/grandchild_cert_32.pem31
-rw-r--r--test/rubygems/grandchild_key.pem50
-rw-r--r--test/rubygems/helper.rb472
-rw-r--r--test/rubygems/installer_test_case.rb27
-rw-r--r--test/rubygems/invalid_issuer_cert.pem32
-rw-r--r--test/rubygems/invalid_issuer_cert_32.pem32
-rw-r--r--test/rubygems/invalid_key.pem50
-rw-r--r--test/rubygems/invalid_signer_cert.pem30
-rw-r--r--test/rubygems/invalid_signer_cert_32.pem30
-rw-r--r--test/rubygems/invalidchild_cert.pem31
-rw-r--r--test/rubygems/invalidchild_cert_32.pem31
-rw-r--r--test/rubygems/invalidchild_key.pem50
-rw-r--r--test/rubygems/multifactor_auth_utilities.rb111
-rw-r--r--test/rubygems/package/tar_test_case.rb70
-rw-r--r--test/rubygems/packages/Bluebie-legs-0.6.2.gembin0 -> 14336 bytes-rw-r--r--test/rubygems/plugin/exception/rubygems_plugin.rb3
-rw-r--r--test/rubygems/plugin/load/rubygems_plugin.rb1
-rw-r--r--test/rubygems/plugin/standarderror/rubygems_plugin.rb3
-rw-r--r--test/rubygems/private_ec_key.pem9
-rw-r--r--test/rubygems/private_key.pem50
-rw-r--r--test/rubygems/public_cert.pem32
-rw-r--r--test/rubygems/public_cert_32.pem30
-rw-r--r--test/rubygems/public_key.pem14
-rw-r--r--test/rubygems/rubygems/commands/crash_command.rb1
-rw-r--r--test/rubygems/rubygems_plugin.rb5
-rw-r--r--test/rubygems/simple_gem.rb3
-rw-r--r--test/rubygems/specifications/bar-0.0.2.gemspec2
-rw-r--r--test/rubygems/specifications/rubyforge-0.0.1.gemspec10
-rw-r--r--test/rubygems/test_bundled_ca.rb25
-rw-r--r--test/rubygems/test_config.rb9
-rw-r--r--test/rubygems/test_deprecate.rb9
-rw-r--r--test/rubygems/test_exit.rb12
-rw-r--r--test/rubygems/test_gem.rb1250
-rw-r--r--test/rubygems/test_gem_available_set.rb43
-rw-r--r--test/rubygems/test_gem_bundler_version_finder.rb75
-rw-r--r--test/rubygems/test_gem_command.rb91
-rw-r--r--test/rubygems/test_gem_command_manager.rb144
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb137
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb262
-rw-r--r--test/rubygems/test_gem_commands_check_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_cleanup_command.rb81
-rw-r--r--test/rubygems/test_gem_commands_contents_command.rb57
-rw-r--r--test/rubygems/test_gem_commands_dependency_command.rb73
-rw-r--r--test/rubygems/test_gem_commands_environment_command.rb53
-rw-r--r--test/rubygems/test_gem_commands_exec_command.rb853
-rw-r--r--test/rubygems/test_gem_commands_fetch_command.rb186
-rw-r--r--test/rubygems/test_gem_commands_generate_index_command.rb15
-rw-r--r--test/rubygems/test_gem_commands_help_command.rb27
-rw-r--r--test/rubygems/test_gem_commands_info_command.rb31
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb356
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb21
-rw-r--r--test/rubygems/test_gem_commands_mirror.rb5
-rw-r--r--test/rubygems/test_gem_commands_open_command.rb11
-rw-r--r--test/rubygems/test_gem_commands_outdated_command.rb19
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb277
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb236
-rw-r--r--test/rubygems/test_gem_commands_push_command.rb256
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb147
-rw-r--r--test/rubygems/test_gem_commands_search_command.rb5
-rw-r--r--test/rubygems/test_gem_commands_server_command.rb55
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb265
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb181
-rw-r--r--test/rubygems/test_gem_commands_signout_command.rb6
-rw-r--r--test/rubygems/test_gem_commands_sources_command.rb100
-rw-r--r--test/rubygems/test_gem_commands_specification_command.rb65
-rw-r--r--test/rubygems/test_gem_commands_stale_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb182
-rw-r--r--test/rubygems/test_gem_commands_unpack_command.rb63
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb290
-rw-r--r--test/rubygems/test_gem_commands_which_command.rb13
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb207
-rw-r--r--test/rubygems/test_gem_config_file.rb175
-rw-r--r--test/rubygems/test_gem_dependency.rb159
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb365
-rw-r--r--test/rubygems/test_gem_dependency_list.rb95
-rw-r--r--test/rubygems/test_gem_dependency_resolution_error.rb9
-rw-r--r--test/rubygems/test_gem_doctor.rb53
-rw-r--r--test/rubygems/test_gem_ext_builder.rb123
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder.rb167
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore1
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock233
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs27
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb3
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore1
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock247
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs51
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb34
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_unit.rb60
-rw-r--r--test/rubygems/test_gem_ext_cmake_builder.rb35
-rw-r--r--test/rubygems/test_gem_ext_configure_builder.rb27
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb103
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb31
-rw-r--r--test/rubygems/test_gem_gem_runner.rb24
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb252
-rw-r--r--test/rubygems/test_gem_impossible_dependencies_error.rb9
-rw-r--r--test/rubygems/test_gem_indexer.rb158
-rw-r--r--test/rubygems/test_gem_install_update_options.rb37
-rw-r--r--test/rubygems/test_gem_installer.rb893
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb21
-rw-r--r--test/rubygems/test_gem_name_tuple.rb9
-rw-r--r--test/rubygems/test_gem_package.rb529
-rw-r--r--test/rubygems/test_gem_package_old.rb27
-rw-r--r--test/rubygems/test_gem_package_tar_header.rb95
-rw-r--r--test/rubygems/test_gem_package_tar_reader.rb64
-rw-r--r--test/rubygems/test_gem_package_tar_reader_entry.rb178
-rw-r--r--test/rubygems/test_gem_package_tar_writer.rb153
-rw-r--r--test/rubygems/test_gem_package_task.rb37
-rw-r--r--test/rubygems/test_gem_path_support.rb35
-rw-r--r--test/rubygems/test_gem_platform.rb549
-rw-r--r--test/rubygems/test_gem_rdoc.rb29
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb346
-rw-r--r--test/rubygems/test_gem_request.rb176
-rw-r--r--test/rubygems/test_gem_request_connection_pools.rb59
-rw-r--r--test/rubygems/test_gem_request_set.rb201
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb421
-rw-r--r--test/rubygems/test_gem_request_set_lockfile.rb173
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_parser.rb117
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_tokenizer.rb125
-rw-r--r--test/rubygems/test_gem_requirement.rb89
-rw-r--r--test/rubygems/test_gem_resolver.rb280
-rw-r--r--test/rubygems/test_gem_resolver_activation_request.rb13
-rw-r--r--test/rubygems/test_gem_resolver_api_set.rb67
-rw-r--r--test/rubygems/test_gem_resolver_api_specification.rb95
-rw-r--r--test/rubygems/test_gem_resolver_best_set.rb45
-rw-r--r--test/rubygems/test_gem_resolver_composed_set.rb3
-rw-r--r--test/rubygems/test_gem_resolver_conflict.rb25
-rw-r--r--test/rubygems/test_gem_resolver_dependency_request.rb31
-rw-r--r--test/rubygems/test_gem_resolver_git_set.rb43
-rw-r--r--test/rubygems/test_gem_resolver_git_specification.rb43
-rw-r--r--test/rubygems/test_gem_resolver_index_set.rb25
-rw-r--r--test/rubygems/test_gem_resolver_index_specification.rb33
-rw-r--r--test/rubygems/test_gem_resolver_installed_specification.rb11
-rw-r--r--test/rubygems/test_gem_resolver_installer_set.rb127
-rw-r--r--test/rubygems/test_gem_resolver_local_specification.rb15
-rw-r--r--test/rubygems/test_gem_resolver_lock_set.rb25
-rw-r--r--test/rubygems/test_gem_resolver_lock_specification.rb35
-rw-r--r--test/rubygems/test_gem_resolver_requirement_list.rb3
-rw-r--r--test/rubygems/test_gem_resolver_specification.rb17
-rw-r--r--test/rubygems/test_gem_resolver_vendor_set.rb13
-rw-r--r--test/rubygems/test_gem_resolver_vendor_specification.rb21
-rw-r--r--test/rubygems/test_gem_security.rb161
-rw-r--r--test/rubygems/test_gem_security_policy.rb144
-rw-r--r--test/rubygems/test_gem_security_signer.rb69
-rw-r--r--test/rubygems/test_gem_security_trust_dir.rb13
-rw-r--r--test/rubygems/test_gem_server.rb608
-rw-r--r--test/rubygems/test_gem_silent_ui.rb71
-rw-r--r--test/rubygems/test_gem_source.rb89
-rw-r--r--test/rubygems/test_gem_source_fetch_problem.rb23
-rw-r--r--test/rubygems/test_gem_source_git.rb132
-rw-r--r--test/rubygems/test_gem_source_installed.rb33
-rw-r--r--test/rubygems/test_gem_source_list.rb11
-rw-r--r--test/rubygems/test_gem_source_local.rb29
-rw-r--r--test/rubygems/test_gem_source_lock.rb63
-rw-r--r--test/rubygems/test_gem_source_specific_file.rb35
-rw-r--r--test/rubygems/test_gem_source_subpath_problem.rb15
-rw-r--r--test/rubygems/test_gem_source_vendor.rb27
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb145
-rw-r--r--test/rubygems/test_gem_specification.rb1510
-rw-r--r--test/rubygems/test_gem_stream_ui.rb75
-rw-r--r--test/rubygems/test_gem_stub_specification.rb81
-rw-r--r--test/rubygems/test_gem_text.rb3
-rw-r--r--test/rubygems/test_gem_uninstaller.rb235
-rw-r--r--test/rubygems/test_gem_unsatisfiable_dependency_error.rb7
-rw-r--r--test/rubygems/test_gem_update_suggestion.rb209
-rw-r--r--test/rubygems/test_gem_uri.rb41
-rw-r--r--test/rubygems/test_gem_uri_formatter.rb29
-rw-r--r--test/rubygems/test_gem_util.rb47
-rw-r--r--test/rubygems/test_gem_validator.rb16
-rw-r--r--test/rubygems/test_gem_version.rb44
-rw-r--r--test/rubygems/test_gem_version_option.rb31
-rw-r--r--test/rubygems/test_kernel.rb105
-rw-r--r--test/rubygems/test_project_sanity.rb37
-rw-r--r--test/rubygems/test_remote_fetch_error.rb15
-rw-r--r--test/rubygems/test_require.rb307
-rw-r--r--test/rubygems/test_rubygems.rb76
-rw-r--r--test/rubygems/test_webauthn_listener.rb143
-rw-r--r--test/rubygems/test_webauthn_listener_response.rb93
-rw-r--r--test/rubygems/test_webauthn_poller.rb124
-rw-r--r--test/rubygems/utilities.rb140
-rw-r--r--test/rubygems/wrong_key_cert.pem30
-rw-r--r--test/rubygems/wrong_key_cert_32.pem30
-rw-r--r--test/runner.rb14
-rw-r--r--test/socket/test_addrinfo.rb8
-rw-r--r--test/socket/test_basicsocket.rb4
-rw-r--r--test/socket/test_nonblock.rb12
-rw-r--r--test/socket/test_socket.rb14
-rw-r--r--test/socket/test_sockopt.rb2
-rw-r--r--test/socket/test_tcp.rb2
-rw-r--r--test/socket/test_udp.rb2
-rw-r--r--test/socket/test_unix.rb147
-rw-r--r--test/stringio/test_stringio.rb75
-rw-r--r--test/strscan/test_ractor.rb2
-rw-r--r--test/strscan/test_stringscanner.rb63
-rw-r--r--test/test_extlibs.rb2
-rw-r--r--test/test_find.rb16
-rw-r--r--test/test_getoptlong.rb163
-rw-r--r--test/test_ipaddr.rb86
-rw-r--r--test/test_open3.rb13
-rw-r--r--test/test_pp.rb21
-rw-r--r--test/test_pstore.rb32
-rw-r--r--test/test_pty.rb30
-rw-r--r--test/test_rbconfig.rb9
-rw-r--r--test/test_securerandom.rb121
-rw-r--r--test/test_set.rb39
-rw-r--r--test/test_time.rb9
-rw-r--r--test/test_timeout.rb57
-rw-r--r--test/test_tmpdir.rb20
-rw-r--r--test/test_trick.rb23
-rw-r--r--test/uri/test_common.rb103
-rw-r--r--test/uri/test_generic.rb27
-rw-r--r--test/uri/test_http.rb31
-rw-r--r--test/uri/test_ldap.rb6
-rw-r--r--test/uri/test_parser.rb38
-rw-r--r--test/uri/test_wss.rb71
-rw-r--r--test/win32ole/test_err_in_callback.rb2
-rw-r--r--test/win32ole/test_win32ole.rb2
-rw-r--r--test/win32ole/test_win32ole_event.rb5
-rw-r--r--test/win32ole/test_win32ole_method_event.rb2
-rw-r--r--test/win32ole/test_win32ole_param_event.rb2
-rw-r--r--test/win32ole/test_win32ole_record.rb2
-rw-r--r--test/win32ole/test_win32ole_type_event.rb2
-rw-r--r--test/win32ole/test_win32ole_variable.rb4
-rw-r--r--test/win32ole/test_win32ole_variant.rb2
-rw-r--r--test/win32ole/test_win32ole_variant_outarg.rb2
-rw-r--r--test/win32ole/test_word.rb2
-rw-r--r--test/yaml/test_store.rb2
-rw-r--r--test/zlib/test_zlib.rb34
-rw-r--r--thread.c1700
-rw-r--r--thread_none.c284
-rw-r--r--thread_none.h20
-rw-r--r--thread_pthread.c976
-rw-r--r--thread_pthread.h92
-rw-r--r--thread_sync.c437
-rw-r--r--thread_sync.rb68
-rw-r--r--thread_win32.c403
-rw-r--r--thread_win32.h24
-rw-r--r--time.c2284
-rw-r--r--timev.h11
-rw-r--r--timev.rb341
-rw-r--r--tool/annocheck/Dockerfile4
-rw-r--r--tool/annocheck/Dockerfile-copy7
-rw-r--r--tool/bundler/dev_gems.rb19
-rw-r--r--tool/bundler/dev_gems.rb.lock57
-rw-r--r--tool/bundler/rubocop_gems.rb1
-rw-r--r--tool/bundler/rubocop_gems.rb.lock71
-rw-r--r--tool/bundler/standard_gems.rb1
-rw-r--r--tool/bundler/standard_gems.rb.lock83
-rw-r--r--tool/bundler/test_gems.rb2
-rw-r--r--tool/bundler/test_gems.rb.lock16
-rwxr-xr-xtool/checksum.rb4
-rwxr-xr-xtool/disable_ipv6.sh9
-rw-r--r--tool/downloader.rb112
-rwxr-xr-x[-rw-r--r--]tool/enc-case-folding.rb (renamed from enc/unicode/case-folding.rb)10
-rw-r--r--tool/enc-emoji-citrus-gen.rb4
-rwxr-xr-xtool/enc-unicode.rb31
-rwxr-xr-xtool/expand-config.rb14
-rwxr-xr-xtool/extlibs.rb176
-rw-r--r--tool/fake.rb13
-rwxr-xr-xtool/fetch-bundled_gems.rb6
-rwxr-xr-xtool/file2lastrev.rb91
-rwxr-xr-xtool/format-release21
-rw-r--r--tool/gem-unpack.rb19
-rwxr-xr-xtool/gen-mailmap.rb4
-rw-r--r--tool/generic_erb.rb44
-rw-r--r--tool/gperf.sed1
-rwxr-xr-xtool/id2token.rb11
-rw-r--r--tool/lib/bundled_gem.rb68
-rw-r--r--tool/lib/colorize.rb4
-rw-r--r--tool/lib/core_assertions.rb213
-rw-r--r--tool/lib/envutil.rb25
-rw-r--r--tool/lib/leakchecker.rb34
-rw-r--r--tool/lib/memory_status.rb1
-rw-r--r--tool/lib/minitest/README.txt457
-rw-r--r--tool/lib/minitest/unit.rb1479
-rw-r--r--tool/lib/output.rb57
-rw-r--r--tool/lib/profile_test_all.rb2
-rw-r--r--tool/lib/test/unit.rb773
-rw-r--r--tool/lib/test/unit/assertions.rb564
-rw-r--r--tool/lib/test/unit/parallel.rb45
-rw-r--r--tool/lib/test/unit/testcase.rb282
-rw-r--r--tool/lib/vcs.rb179
-rw-r--r--tool/lib/vpath.rb7
-rw-r--r--tool/lib/webrick/httpserver.rb1
-rw-r--r--tool/lib/webrick/httputils.rb2
-rwxr-xr-xtool/ln_sr.rb131
-rw-r--r--tool/m4/ruby_default_arch.m41
-rw-r--r--tool/m4/ruby_define_if.m410
-rw-r--r--tool/m4/ruby_prog_makedirs.m49
-rw-r--r--tool/m4/ruby_replace_funcs.m44
-rw-r--r--tool/m4/ruby_replace_type.m412
-rw-r--r--tool/m4/ruby_require_funcs.m413
-rw-r--r--tool/m4/ruby_thread.m480
-rw-r--r--tool/m4/ruby_try_cflags.m47
-rw-r--r--tool/m4/ruby_universal_arch.m432
-rw-r--r--tool/m4/ruby_wasm_tools.m424
-rwxr-xr-xtool/make-snapshot44
-rw-r--r--tool/make_hgraph.rb7
-rwxr-xr-xtool/merger.rb189
-rwxr-xr-xtool/mjit/bindgen.rb435
-rw-r--r--tool/mk_builtin_loader.rb72
-rwxr-xr-xtool/mkconfig.rb17
-rwxr-xr-xtool/mkrunnable.rb20
-rwxr-xr-xtool/outdate-bundled-gems.rb135
-rwxr-xr-xtool/pure_parser.rb24
-rwxr-xr-xtool/rbinstall.rb291
-rw-r--r--tool/rbs_skip_tests11
-rwxr-xr-xtool/redmine-backporter.rb158
-rwxr-xr-xtool/releng/gen-mail.rb13
-rw-r--r--tool/ruby_vm/controllers/application_controller.rb5
-rw-r--r--tool/ruby_vm/helpers/dumper.rb7
-rw-r--r--tool/ruby_vm/models/typemap.rb1
-rw-r--r--tool/ruby_vm/scripts/insns2vm.rb12
-rw-r--r--tool/ruby_vm/views/_insn_entry.erb2
-rw-r--r--tool/ruby_vm/views/_insn_len_info.erb23
-rw-r--r--tool/ruby_vm/views/_insn_name_info.erb30
-rw-r--r--tool/ruby_vm/views/_insn_operand_info.erb29
-rw-r--r--tool/ruby_vm/views/_insn_type_chars.erb19
-rw-r--r--tool/ruby_vm/views/_mjit_compile_getinlinecache.erb31
-rw-r--r--tool/ruby_vm/views/_mjit_compile_insn.erb92
-rw-r--r--tool/ruby_vm/views/_mjit_compile_insn_body.erb129
-rw-r--r--tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb29
-rw-r--r--tool/ruby_vm/views/_mjit_compile_ivar.erb101
-rw-r--r--tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb38
-rw-r--r--tool/ruby_vm/views/_mjit_compile_send.erb119
-rw-r--r--tool/ruby_vm/views/_trace_instruction.erb7
-rw-r--r--tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb40
-rw-r--r--tool/ruby_vm/views/mjit_compile.inc.erb110
-rw-r--r--tool/ruby_vm/views/mjit_sp_inc.inc.erb17
-rw-r--r--tool/ruby_vm/views/optinsn.inc.erb4
-rwxr-xr-xtool/runruby.rb20
-rwxr-xr-xtool/strip-rdoc.rb30
-rwxr-xr-x[-rw-r--r--]tool/sync_default_gems.rb1200
-rwxr-xr-xtool/test-annocheck.sh33
-rw-r--r--tool/test-bundled-gems.rb72
-rwxr-xr-xtool/test/test_sync_default_gems.rb76
-rw-r--r--tool/test/testunit/metametameta.rb (renamed from tool/test/minitest/metametameta.rb)16
-rw-r--r--tool/test/testunit/test4test_hideskip.rb8
-rw-r--r--tool/test/testunit/test4test_sorting.rb2
-rw-r--r--tool/test/testunit/test_assertion.rb26
-rw-r--r--tool/test/testunit/test_hideskip.rb6
-rw-r--r--tool/test/testunit/test_minitest_unit.rb (renamed from tool/test/minitest/test_minitest_unit.rb)565
-rw-r--r--tool/test/testunit/test_parallel.rb33
-rw-r--r--tool/test/testunit/test_redefinition.rb13
-rw-r--r--tool/test/testunit/test_sorting.rb57
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_hungup.rb15
-rw-r--r--tool/test/webrick/test_filehandler.rb4
-rw-r--r--tool/test/webrick/test_httprequest.rb2
-rw-r--r--tool/test/webrick/test_httpserver.rb2
-rw-r--r--tool/test/webrick/test_server.rb2
-rw-r--r--tool/test/webrick/utils.rb2
-rw-r--r--tool/transcode-tblgen.rb2
-rw-r--r--tool/transform_mjit_header.rb15
-rw-r--r--tool/update-NEWS-refs.rb37
-rwxr-xr-xtool/update-bundled_gems.rb7
-rwxr-xr-xtool/update-deps7
-rwxr-xr-xtool/wasm-clangw9
-rw-r--r--trace_point.rb86
-rw-r--r--transcode.c677
-rw-r--r--transcode_data.h32
-rw-r--r--transient_heap.c12
-rw-r--r--util.c179
-rw-r--r--variable.c2562
-rw-r--r--variable.h11
-rw-r--r--version.c67
-rw-r--r--version.h64
-rw-r--r--vm.c2111
-rw-r--r--vm_args.c639
-rw-r--r--vm_backtrace.c618
-rw-r--r--vm_callinfo.h137
-rw-r--r--vm_core.h556
-rw-r--r--vm_debug.h46
-rw-r--r--vm_dump.c1055
-rw-r--r--vm_eval.c882
-rw-r--r--vm_exec.c28
-rw-r--r--vm_exec.h25
-rw-r--r--vm_insnhelper.c3451
-rw-r--r--vm_insnhelper.h26
-rw-r--r--vm_method.c1251
-rw-r--r--vm_sync.c16
-rw-r--r--vm_trace.c672
-rw-r--r--vsnprintf.c13
-rw-r--r--wasm/GNUmakefile.in32
-rw-r--r--wasm/README.md70
-rw-r--r--wasm/asyncify.h23
-rw-r--r--wasm/fiber.c83
-rw-r--r--wasm/fiber.h43
-rw-r--r--wasm/machine.c62
-rw-r--r--wasm/machine.h25
-rw-r--r--wasm/machine_core.S25
-rw-r--r--wasm/missing.c199
-rw-r--r--wasm/runtime.c47
-rw-r--r--wasm/setjmp.c204
-rw-r--r--wasm/setjmp.h95
-rw-r--r--wasm/setjmp_core.S27
-rw-r--r--wasm/tests/fiber_test.c66
-rw-r--r--wasm/tests/machine_test.c115
-rw-r--r--wasm/tests/setjmp_test.c108
-rwxr-xr-xwasm/wasm-opt36
-rw-r--r--win32/Makefile.sub238
-rwxr-xr-xwin32/configure.bat51
-rw-r--r--win32/dir.h2
-rw-r--r--win32/file.c593
-rw-r--r--win32/file.h38
-rwxr-xr-xwin32/ifchange.bat1
-rwxr-xr-xwin32/mkexports.rb4
-rwxr-xr-xwin32/resource.rb2
-rw-r--r--win32/setup.mak83
-rw-r--r--win32/win32.c5993
-rw-r--r--win32/winmain.c4
-rw-r--r--yjit.c1109
-rw-r--r--yjit.h70
-rw-r--r--yjit.rb356
-rw-r--r--yjit/.gitignore2
-rw-r--r--yjit/Cargo.lock49
-rw-r--r--yjit/Cargo.toml47
-rw-r--r--yjit/bindgen/Cargo.lock311
-rw-r--r--yjit/bindgen/Cargo.toml10
-rw-r--r--yjit/bindgen/src/main.rs430
-rw-r--r--yjit/not_gmake.mk14
-rw-r--r--yjit/src/asm/arm64/README.md16
-rw-r--r--yjit/src/asm/arm64/arg/bitmask_imm.rs255
-rw-r--r--yjit/src/asm/arm64/arg/condition.rs52
-rw-r--r--yjit/src/asm/arm64/arg/inst_offset.rs47
-rw-r--r--yjit/src/asm/arm64/arg/mod.rs18
-rw-r--r--yjit/src/asm/arm64/arg/sf.rs19
-rw-r--r--yjit/src/asm/arm64/arg/shifted_imm.rs81
-rw-r--r--yjit/src/asm/arm64/arg/sys_reg.rs6
-rw-r--r--yjit/src/asm/arm64/arg/truncate.rs66
-rw-r--r--yjit/src/asm/arm64/inst/atomic.rs86
-rw-r--r--yjit/src/asm/arm64/inst/branch.rs100
-rw-r--r--yjit/src/asm/arm64/inst/branch_cond.rs78
-rw-r--r--yjit/src/asm/arm64/inst/breakpoint.rs55
-rw-r--r--yjit/src/asm/arm64/inst/call.rs104
-rw-r--r--yjit/src/asm/arm64/inst/conditional.rs73
-rw-r--r--yjit/src/asm/arm64/inst/data_imm.rs143
-rw-r--r--yjit/src/asm/arm64/inst/data_reg.rs192
-rw-r--r--yjit/src/asm/arm64/inst/halfword_imm.rs179
-rw-r--r--yjit/src/asm/arm64/inst/load_literal.rs89
-rw-r--r--yjit/src/asm/arm64/inst/load_register.rs108
-rw-r--r--yjit/src/asm/arm64/inst/load_store.rs249
-rw-r--r--yjit/src/asm/arm64/inst/load_store_exclusive.rs109
-rw-r--r--yjit/src/asm/arm64/inst/logical_imm.rs154
-rw-r--r--yjit/src/asm/arm64/inst/logical_reg.rs207
-rw-r--r--yjit/src/asm/arm64/inst/mod.rs50
-rw-r--r--yjit/src/asm/arm64/inst/mov.rs155
-rw-r--r--yjit/src/asm/arm64/inst/nop.rs44
-rw-r--r--yjit/src/asm/arm64/inst/pc_rel.rs107
-rw-r--r--yjit/src/asm/arm64/inst/reg_pair.rs212
-rw-r--r--yjit/src/asm/arm64/inst/sbfm.rs103
-rw-r--r--yjit/src/asm/arm64/inst/shift_imm.rs147
-rw-r--r--yjit/src/asm/arm64/inst/sys_reg.rs86
-rw-r--r--yjit/src/asm/arm64/inst/test_bit.rs133
-rw-r--r--yjit/src/asm/arm64/mod.rs1580
-rw-r--r--yjit/src/asm/arm64/opnd.rs195
-rw-r--r--yjit/src/asm/mod.rs792
-rw-r--r--yjit/src/asm/x86_64/mod.rs1415
-rw-r--r--yjit/src/asm/x86_64/tests.rs449
-rw-r--r--yjit/src/backend/arm64/mod.rs1491
-rw-r--r--yjit/src/backend/ir.rs1576
-rw-r--r--yjit/src/backend/mod.rs8
-rw-r--r--yjit/src/backend/tests.rs331
-rw-r--r--yjit/src/backend/x86_64/mod.rs895
-rw-r--r--yjit/src/codegen.rs7721
-rw-r--r--yjit/src/core.rs2400
-rw-r--r--yjit/src/cruby.rs715
-rw-r--r--yjit/src/cruby_bindings.inc.rs1310
-rw-r--r--yjit/src/disasm.rs269
-rw-r--r--yjit/src/invariants.rs567
-rw-r--r--yjit/src/lib.rs18
-rw-r--r--yjit/src/options.rs174
-rw-r--r--yjit/src/stats.rs640
-rw-r--r--yjit/src/utils.rs274
-rw-r--r--yjit/src/virtualmem.rs443
-rw-r--r--yjit/src/yjit.rs136
-rw-r--r--yjit/yjit.mk69
3736 files changed, 690083 insertions, 143354 deletions
diff --git a/appveyor.yml b/.appveyor.yml
index 0c984b964a..05ff204541 100644
--- a/appveyor.yml
+++ b/.appveyor.yml
@@ -6,24 +6,34 @@ init:
- git config --global core.autocrlf false
- git config --global core.eol lf
- git config --global advice.detachedHead 0
+shallow_clone: true
clone_depth: 10
platform:
- x64
+skip_commits:
+ message: /\[DOC\]/
+ files:
+ - doc/*
+ - '**/*.md'
+ - '**/*.rdoc'
+ - '**/.document'
+ - '**/*.[1-8]'
+ - '**/*.ronn'
environment:
ruby_version: "24-%Platform%"
- zlib_version: "1.2.11"
matrix:
+ # Test only the oldest supported version because AppVeyor is unstable, its concurrency
+ # is limited, and compatibility issues that happen only in newer versions are rare.
+ # You may test some other stuff on GitHub Actions instead.
- build: vs
- vs: 120
- ssl: OpenSSL
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
- GEMS_FOR_TEST: ""
- - build: vs
- vs: 140
+ vs: 120 # Visual Studio 2013
ssl: OpenSSL-v111
+ # The worker image name. This is NOT the Visual Studio version we're using here.
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GEMS_FOR_TEST: ""
- RELINE_TEST_ENCODING: "Windows-31J"
+ RELINE_TEST_ENCODING: "UTF-8"
+cache:
+ - c:\Tools\vcpkg\installed\
for:
-
matrix:
@@ -35,6 +45,12 @@ for:
- SET BITS=%Platform:x86=32%
- SET BITS=%BITS:x=%
- SET OPENSSL_DIR=C:\%ssl%-Win%BITS%
+ - cd C:\Tools\vcpkg
+ - git pull -q
+ - .\bootstrap-vcpkg.bat
+ - ps: Start-FileDownload 'https://github.com/microsoft/vcpkg-tool/releases/download/2023-08-09/vcpkg.exe' -FileName 'C:\Tools\vcpkg\vcpkg.exe'
+ - cd %APPVEYOR_BUILD_FOLDER%
+ - vcpkg --triplet %Platform%-windows install --x-use-aria2 libffi libyaml readline zlib
- CALL SET vcvars=%%^VS%VS%COMNTOOLS^%%..\..\VC\vcvarsall.bat
- SET vcvars
- '"%vcvars%" %Platform:x64=amd64%'
@@ -54,16 +70,20 @@ for:
- mkdir \usr\local\bin
- mkdir \usr\local\include
- mkdir \usr\local\lib
- - SET ZLIB_ZIP=.downloaded-cache\zlib%zlib_version:.=%.zip
- - if not exist %ZLIB_ZIP% curl -fsSL -o %ZLIB_ZIP% --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip
- - 7z x -aos -o%APPVEYOR_BUILD_FOLDER%\ext\zlib %ZLIB_ZIP%
- for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I
+ - for %%I in (c:\Tools\vcpkg\installed\%Platform%-windows\bin\*.dll) do (
+ if not %%~nI == readline mklink \usr\local\bin\%%~nxI %%I
+ )
- attrib +r /s /d
- mkdir %Platform%-mswin_%vs%
build_script:
+ - set HAVE_GIT=no
- cd %APPVEYOR_BUILD_FOLDER%
- cd %Platform%-mswin_%vs%
- - ..\win32\configure.bat --without-ext=+,dbm,gdbm,readline --with-opt-dir=/usr/local --with-openssl-dir=%OPENSSL_DIR:\=/%
+ - >-
+ ..\win32\configure.bat
+ --with-opt-dir="/usr/local;c:/Tools/vcpkg/installed/%Platform%-windows"
+ --with-openssl-dir=%OPENSSL_DIR:\=/%
- nmake -l
- nmake install-nodoc
- \usr\bin\ruby -v -e "p :locale => Encoding.find('locale'), :filesystem => Encoding.find('filesystem')"
@@ -73,9 +93,26 @@ for:
- set /a JOBS=%NUMBER_OF_PROCESSORS%
- nmake -l "TESTOPTS=-v -q" btest
- nmake -l "TESTOPTS=-v -q" test-basic
- - nmake -l "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor -j%JOBS% --exclude readline --exclude win32ole --exclude test_bignum --exclude test_syntax --exclude test_open-uri --exclude test_bundled_ca" test-all
+ - >-
+ nmake -l "TESTOPTS=--timeout-scale=3.0
+ --excludes=../test/excludes/_appveyor -j%JOBS%
+ --exclude win32ole
+ --exclude test_bignum
+ --exclude test_syntax
+ --exclude test_open-uri
+ --exclude test_bundled_ca
+ " test-all
# separately execute tests without -j which may crash worker with -j.
- - nmake -l "TESTOPTS=-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
+ "TESTOPTS=--timeout-scale=3.0 --excludes=../test/excludes/_appveyor"
+ TESTS="
+ ../test/win32ole
+ ../test/ruby/test_bignum.rb
+ ../test/ruby/test_syntax.rb
+ ../test/open-uri/test_open-uri.rb
+ ../test/rubygems/test_bundled_ca.rb
+ " test-all
- nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows
notifications:
- provider: Webhook
@@ -86,7 +123,7 @@ notifications:
{{^isPullRequest}}
{
"ci": "AppVeyor CI",
- "env": "Visual Studio 2013 / 2015",
+ "env": "Visual Studio 2013",
"url": "{{buildUrl}}",
"commit": "{{commitId}}",
"branch": "{{branch}}"
diff --git a/.document b/.document
index 2c68af227d..3a6b0c238c 100644
--- a/.document
+++ b/.document
@@ -17,13 +17,19 @@ dir.rb
gc.rb
io.rb
kernel.rb
+marshal.rb
+mjit.rb
numeric.rb
nilclass.rb
pack.rb
ractor.rb
+string.rb
+symbol.rb
timev.rb
+thread_sync.rb
trace_point.rb
warning.rb
+yjit.rb
# the lib/ directory (which has its own .document file)
lib
@@ -39,7 +45,6 @@ README.ja.md
COPYING
COPYING.ja
-CONTRIBUTING.md
LEGAL
diff --git a/.gdbinit b/.gdbinit
index 8979e8b47c..34d044caf6 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -544,13 +544,13 @@ end
define rp_class
printf "(struct RClass *) %p", (void*)$arg0
- if ((struct RClass *)($arg0))->ptr.origin_ != $arg0
- printf " -> %p", ((struct RClass *)($arg0))->ptr.origin_
+ if RCLASS_ORIGIN((struct RClass *)($arg0)) != $arg0
+ printf " -> %p", RCLASS_ORIGIN((struct RClass *)($arg0))
end
printf "\n"
rb_classname $arg0
print/x *(struct RClass *)($arg0)
- print *((struct RClass *)($arg0))->ptr
+ print *RCLASS_EXT((struct RClass *)($arg0))
end
document rp_class
Print the content of a Class/Module.
@@ -979,8 +979,8 @@ end
define rb_ps_vm
print $ps_vm = (rb_vm_t*)$arg0
- set $ps_thread_ln = $ps_vm->living_threads.n.next
- set $ps_thread_ln_last = $ps_vm->living_threads.n.prev
+ set $ps_thread_ln = $ps_vm->ractor.main_ractor.threads.set.n.next
+ set $ps_thread_ln_last = $ps_vm->ractor.main_ractor.threads.set.n.prev
while 1
set $ps_thread_th = (rb_thread_t *)$ps_thread_ln
set $ps_thread = (VALUE)($ps_thread_th->self)
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000..6c5eac5a0f
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,23 @@
+# This is a file used by GitHub to ignore the following commits on `git blame`.
+#
+# You can also do the same thing in your local repository with:
+# $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
+
+# Expand tabs
+5b21e94bebed90180d8ff63dad03b8b948361089
+
+# Enable Style/StringLiterals cop for RubyGems/Bundler
+d7ffd3fea402239b16833cc434404a7af82d44f3
+
+# [ruby/digest] Revert tab-expansion in external files
+48b09aae7ec5632209229dcc294dd0d75a93a17f
+8a65cf3b61c60e4cb886f59a73ff6db44364bfa9
+39dc9f9093901d40d2998653948d5da38b18ee2c
+
+# [ruby/io-nonblock] Revert tab expansion
+f28287d34c03f472ffe90ea262bdde9affd4b965
+0d842fecb4f75ab3b1d4097ebdb8e88f51558041
+4ba2c66761d6a293abdfba409241d31063cefd62
+
+# Make benchmark indentation consistent
+fc4acf8cae82e5196186d3278d831f2438479d91
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..bc63aca35b
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: 'github-actions'
+ directory: '/'
+ schedule:
+ interval: 'monthly'
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
index 532d4a998d..ebaafe3bf0 100644
--- a/.github/workflows/baseruby.yml
+++ b/.github/workflows/baseruby.yml
@@ -1,11 +1,40 @@
name: BASERUBY Check
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
jobs:
baseruby:
name: BASERUBY
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
strategy:
matrix:
ruby:
@@ -14,23 +43,29 @@ jobs:
# - ruby-2.4
# - ruby-2.5
# - ruby-2.6
- - ruby-2.7
+# - ruby-2.7
+ - ruby-3.0
+ - ruby-3.1
steps:
- - uses: actions/checkout@v2
- - uses: ruby/setup-ruby@v1
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: .downloaded-cache
+ key: downloaded-cache
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
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: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - run: sudo apt-get install build-essential autoconf bison libyaml-dev
- run: ./autogen.sh
- run: ./configure --disable-install-doc
- - run: $make common-srcs
- - run: $make incs
- - run: $make all
- - run: $make test
- - uses: k0kubun/action-slack@v2.0.0
+ - run: make common-srcs
+ - run: make incs
+ - run: make all
+ - run: make test
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -38,7 +73,7 @@ jobs:
"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]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml
new file mode 100644
index 0000000000..070c0fa1dd
--- /dev/null
+++ b/.github/workflows/bundled_gems.yml
@@ -0,0 +1,166 @@
+name: bundled_gems
+
+on:
+ push:
+ branches: [ "master" ]
+ paths:
+ - '.github/workflows/bundled_gems.yml'
+ - 'gems/bundled_gems'
+ pull_request:
+ branches: [ "master" ]
+ paths:
+ - '.github/workflows/bundled_gems.yml'
+ - 'gems/bundled_gems'
+ merge_group:
+ branches: [ "master" ]
+ paths:
+ - '.github/workflows/bundled_gems.yml'
+ - 'gems/bundled_gems'
+ schedule:
+ - cron: '45 6 * * *'
+ workflow_dispatch:
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
+jobs:
+ update:
+ permissions:
+ contents: write # for Git to git push
+ if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }}
+ name: update ${{ github.workflow }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+
+ - name: Set ENV
+ run: |
+ echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ echo "TODAY=$(date +%F)" >> $GITHUB_ENV
+
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: .downloaded-cache
+ key: downloaded-cache-${{ github.sha }}
+ restore-keys: |
+ downloaded-cache
+
+ - name: Download previous gems list
+ run: |
+ data=bundled_gems.json
+ mkdir -p .downloaded-cache
+ ln -s .downloaded-cache/$data .
+ curl -O -R -z ./$data https://stdgems.org/$data
+
+ - name: Update bundled gems list
+ run: |
+ ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems
+
+ - name: Maintain updated gems list in NEWS
+ run: |
+ #!ruby
+ require 'json'
+ news = File.read("NEWS.md")
+ prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1]
+ prevs = [prev, prev.sub(/\.\d+\z/, '')]
+ %W[bundled].each do |type|
+ last = JSON.parse(File.read("#{type}_gems.json"))['gems'].filter_map do |g|
+ v = g['versions'].values_at(*prevs).compact.first
+ g = g['gem']
+ g = 'RubyGems' if g == 'rubygems'
+ [g, v] if v
+ end.to_h
+ changed = File.foreach("gems/#{type}_gems").filter_map do |l|
+ next if l.start_with?("#")
+ g, v = l.split(" ", 3)
+ [g, v] unless last[g] == v
+ end
+ changed, added = changed.partition {|g, _| last[g]}
+ news.sub!(/^\*( +)The following #{type} gems? are updated\.\n+\K(?: \1\*( +).*\n)*/) do
+ mark = "#{$1} *#{$2}"
+ changed.map {|g, v|"#{mark}#{g} #{v}\n"}.join("")
+ end or next
+ news.sub!(/^\*( +)The following default gems are now bundled gems\.\n+\K(?: \1\*( +).*\n)*/) do
+ mark = "#{$1} *#{$2}"
+ added.map {|g, v|"#{mark}#{g} #{v}\n"}.join("")
+ end or next unless added.empty?
+ File.write("NEWS.md", news)
+ end
+ shell: ruby {0}
+
+ - name: Check diffs
+ id: diff
+ run: |
+ git add -- NEWS.md
+ git diff --no-ext-diff --ignore-submodules --quiet -- gems/bundled_gems
+ continue-on-error: true
+
+ - name: Install libraries
+ run: |
+ set -x
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby
+ if: ${{ steps.diff.outcome == 'failure' }}
+
+ - name: Build
+ run: |
+ ./autogen.sh
+ ./configure -C --disable-install-doc
+ make
+ if: ${{ steps.diff.outcome == 'failure' }}
+
+ - name: Prepare bundled gems
+ run: |
+ make -s prepare-gems
+ if: ${{ steps.diff.outcome == 'failure' }}
+
+ - name: Test bundled gems
+ run: |
+ make -s test-bundled-gems
+ git add -- gems/bundled_gems
+ timeout-minutes: 30
+ env:
+ RUBY_TESTOPTS: "-q --tty=no"
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
+ if: ${{ steps.diff.outcome == 'failure' }}
+
+ - name: Show diffs
+ id: show
+ run: |
+ git diff --cached --color --no-ext-diff --ignore-submodules --exit-code --
+ continue-on-error: true
+
+ - name: Commit
+ run: |
+ git pull --ff-only origin ${GITHUB_REF#refs/heads/}
+ message="Update bundled gems list at "
+ if [ ${{ steps.diff.outcome }} = success ]; then
+ git commit --message="${message}${GITHUB_SHA:0:30} [ci skip]"
+ else
+ git commit --message="${message}${TODAY}"
+ fi
+ git push origin ${GITHUB_REF#refs/heads/}
+ env:
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ if: ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && steps.show.outcome == 'failure' }}
+
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / update",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ 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_dependencies.yml b/.github/workflows/check_dependencies.yml
index 645da4000b..79b2916feb 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -1,12 +1,42 @@
name: Check Dependencies
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
jobs:
update-deps:
strategy:
matrix:
- os: [ubuntu-20.04, macos-latest]
+ os: [ubuntu-22.04]
fail-fast: true
runs-on: ${{ matrix.os }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- name: Install libraries
run: |
@@ -16,21 +46,24 @@ jobs:
if: ${{ contains(matrix.os, 'ubuntu') }}
- name: Install libraries
run: |
- brew upgrade
brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline
if: ${{ contains(matrix.os, 'macos') }}
- name: git config
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: .downloaded-cache
+ key: downloaded-cache
- run: ./autogen.sh
- name: Run configure
run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g'
- run: make all golf
- run: ruby tool/update-deps --fix
- run: git diff --no-ext-diff --ignore-submodules --exit-code
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -38,7 +71,7 @@ jobs:
"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]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
deleted file mode 100644
index c116011d86..0000000000
--- a/.github/workflows/check_misc.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-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 trailing spaces
- run: |
- ! git grep -n '[ ]$' '*.rb' '*.[chy]'
- - 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
index 19ad77d393..8dba76fbe2 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,16 +1,45 @@
name: "Code scanning - action"
on:
- push:
- pull_request:
+ # push:
+ # paths-ignore:
+ # - 'doc/**'
+ # - '**/man'
+ # - '**.md'
+ # - '**.rdoc'
+ # - '**/.document'
+ # pull_request:
+ # paths-ignore:
+ # - 'doc/**'
+ # - '**/man'
+ # - '**.md'
+ # - '**.rdoc'
+ # - '**/.document'
schedule:
- - cron: '0 12 * * 4'
+ - cron: '0 12 * * *'
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
jobs:
CodeQL-Build:
# CodeQL runs on ubuntu-latest and windows-latest
+ permissions:
+ actions: read # for github/codeql-action/init to get workflow details
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/autobuild to send a status report
runs-on: ubuntu-latest
+ # CodeQL fails to run pull requests from dependabot due to missing write access to upload results.
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') && github.event.head_commit.pusher.name != 'dependabot[bot]' }}
+
+ env:
+ enable_install_doc: no
steps:
- name: Install libraries
@@ -20,18 +49,27 @@ jobs:
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: .downloaded-cache
+ key: downloaded-cache
- name: Remove an obsolete rubygems vendored file
run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37
with:
config-file: ./.github/codeql/codeql-config.yml
+ trap-caching: false
+
+ - name: Set ENV
+ run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37
diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
index a5c1e72db2..caf12cc0f4 100644
--- a/.github/workflows/compilers.yml
+++ b/.github/workflows/compilers.yml
@@ -1,17 +1,39 @@
name: Compilations
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.rdoc'
+ - '**/.document'
-# Github actions does not support YAML anchors. This creative use of
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+# GitHub actions does not support YAML anchors. This creative use of
# environment variables (plus the "echo $GITHUB_ENV" hack) is to reroute that
# restriction.
env:
- default_cc: clang-14
+ default_cc: clang-15
append_cc: ''
- crosshost: ''
# -O1 is faster than -O3 in our tests... Majority of time are consumed trying
- # to optimize binaries. Also Github Actions run on relatively modern CPUs
+ # to optimize binaries. Also GitHub Actions run on relatively modern CPUs
# compared to, say, GCC 4 or Clang 3. We don't specify `-march=native`
# because compilers tend not understand what the CPU is.
optflags: '-O1'
@@ -41,169 +63,206 @@ env:
--color=always
--tty=no
+permissions:
+ contents: read
+
jobs:
compile:
strategy:
fail-fast: false
matrix:
+ env:
+ - {}
entry:
- - { key: default_cc, name: gcc-11, value: gcc-11, container: gcc-11 }
- - { key: default_cc, name: gcc-10, value: gcc-10, container: gcc-10 }
- - { key: default_cc, name: gcc-9, value: gcc-9, container: gcc-9 }
- - { key: default_cc, name: gcc-8, value: gcc-8, container: gcc-8 }
- - { key: default_cc, name: gcc-7, value: gcc-7, container: gcc-7 }
- - { key: default_cc, name: gcc-6, value: gcc-6, container: gcc-6 }
- - { key: default_cc, name: gcc-5, value: gcc-5, container: gcc-5 }
- - { key: default_cc, name: gcc-4.8, value: gcc-4.8, container: gcc-4.8 }
- - key: default_cc
- name: 'gcc-11 LTO'
- value: 'gcc-11 -O2 -flto=auto -ffat-lto-objects'
- container: gcc-11
+ - { name: gcc-12, env: { default_cc: gcc-12 } }
+ - { name: gcc-11, env: { default_cc: gcc-11 } }
+ - { name: gcc-10, env: { default_cc: gcc-10 } }
+ - { name: gcc-9, env: { default_cc: gcc-9 } }
+ - { name: gcc-8, env: { default_cc: gcc-8 } }
+ - { name: gcc-7, env: { default_cc: gcc-7 } }
+ - name: 'gcc-13 LTO'
+ container: gcc-13
+ env:
+ default_cc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch'
+ optflags: '-O2'
+ shared: disable
# check: true
- - { key: default_cc, name: clang-14, value: clang-14, container: clang-14 }
- - { key: default_cc, name: clang-13, value: clang-13, container: clang-13 }
- - { key: default_cc, name: clang-12, value: clang-12, container: clang-12 }
- - { key: default_cc, name: clang-11, value: clang-11, container: clang-11 }
- - { key: default_cc, name: clang-10, value: clang-10, container: clang-10 }
- - { key: default_cc, name: clang-9, value: clang-9, container: clang-9 }
- - { key: default_cc, name: clang-8, value: clang-8, container: clang-8 }
- - { key: default_cc, name: clang-7, value: clang-7, container: clang-7 }
- - { key: default_cc, name: clang-6.0, value: clang-6.0, container: clang-6.0 }
- - { key: default_cc, name: clang-5.0, value: clang-5.0, container: clang-5.0 }
- - { key: default_cc, name: clang-4.0, value: clang-4.0, container: clang-4.0 }
- - { key: default_cc, name: clang-3.9, value: clang-3.9, container: clang-3.9 }
- - key: default_cc
- name: 'clang-14 LTO'
- value: 'clang-14 -O2 -flto=auto'
- container: clang-14
+ - { name: clang-16, env: { default_cc: clang-16 } }
+ - { name: clang-15, env: { default_cc: clang-15 } }
+ - { name: clang-14, env: { default_cc: clang-14 } }
+ - { name: clang-13, env: { default_cc: clang-13 } }
+ - { name: clang-12, env: { default_cc: clang-12 } }
+ - { name: clang-11, env: { default_cc: clang-11 } }
+ - { name: clang-10, env: { default_cc: clang-10 } }
+ # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o.
+ - { name: clang-9, env: { default_cc: clang-9, append_configure: '--disable-yjit' } }
+ - { name: clang-8, env: { default_cc: clang-8, append_configure: '--disable-yjit' } }
+ - { name: clang-7, env: { default_cc: clang-7, append_configure: '--disable-yjit' } }
+ - { name: clang-6.0, env: { default_cc: clang-6.0, append_configure: '--disable-yjit' } }
+ - name: 'clang-16 LTO'
+ container: clang-16
+ env:
+ default_cc: 'clang-16 -flto=auto'
+ optflags: '-O2'
+ shared: disable
# check: true
- - { key: crosshost, name: aarch64-linux-gnu, value: aarch64-linux-gnu, container: crossbuild-essential-arm64 }
-# - { key: crosshost, name: arm-linux-gnueabi, value: arm-linux-gnueabi }
-# - { key: crosshost, name: arm-linux-gnueabihf, value: arm-linux-gnueabihf }
-# - { key: crosshost, name: i686-w64-mingw32, value: i686-w64-mingw32 }
-# - { key: crosshost, name: powerpc-linux-gnu, value: powerpc-linux-gnu }
- - { key: crosshost, name: powerpc64le-linux-gnu, value: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el }
- - { key: crosshost, name: s390x-linux-gnu, value: s390x-linux-gnu, container: crossbuild-essential-s390x }
- - { key: crosshost, name: x86_64-w64-mingw32, value: x86_64-w64-mingw32, container: mingw-w64 }
-
- - { key: append_cc, name: c99, value: '-std=c99 -Werror=pedantic -pedantic-errors' }
-# - { key: append_cc, name: c11, value: '-std=c11 -Werror=pedantic -pedantic-errors' }
-# - { key: append_cc, name: c17, value: '-std=c17 -Werror=pedantic -pedantic-errors' }
- - { key: append_cc, name: c2x, value: '-std=c2x -Werror=pedantic -pedantic-errors' }
- - { key: CXXFLAGS, name: c++98, value: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-# - { key: CXXFLAGS, name: c++11, value: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-# - { key: CXXFLAGS, name: c++14, value: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-# - { key: CXXFLAGS, name: c++17, value: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
- - { key: CXXFLAGS, name: c++2a, value: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-
- - { key: optflags, name: '-O0', value: '-O0 -march=x86-64 -mtune=generic' }
-# - { key: optflags, name: '-O3', value: '-O3 -march=x86-64 -mtune=generic', check: true }
-
- - { key: append_configure, name: gmp, value: '--with-gmp' }
- - { key: append_configure, name: jemalloc, value: '--with-jemalloc' }
- - { key: append_configure, name: valgrind, value: '--with-valgrind' }
- - { key: append_configure, name: 'coroutine=ucontext', value: '--with-coroutine=ucontext' }
- - { key: append_configure, name: 'coroutine=pthread', value: '--with-coroutine=pthread' }
- - { key: append_configure, name: disable-jit-support, value: '--disable-jit-support' }
- - { key: append_configure, name: disable-dln, value: '--disable-dln' }
- - { key: append_configure, name: disable-rubygems, value: '--disable-rubygems' }
-
- - { key: cppflags, name: OPT_THREADED_CODE=1, value: '-DOPT_THREADED_CODE=1' }
- - { key: cppflags, name: OPT_THREADED_CODE=2, value: '-DOPT_THREADED_CODE=2' }
- - { key: cppflags, name: OPT_THREADED_CODE=3, value: '-DOPT_THREADED_CODE=3' }
-
- - { key: cppflags, name: NDEBUG, value: '-DNDEBUG' }
- - { key: cppflags, name: RUBY_DEBUG, value: '-DRUBY_DEBUG' }
-# - { key: cppflags, name: ARRAY_DEBUG, value: '-DARRAY_DEBUG' }
-# - { key: cppflags, name: BIGNUM_DEBUG, value: '-DBIGNUM_DEBUG' }
-# - { key: cppflags, name: CCAN_LIST_DEBUG, value: '-DCCAN_LIST_DEBUG' }
-# - { key: cppflags, name: CPDEBUG=-1, value: '-DCPDEBUG=-1' }
-# - { key: cppflags, name: ENC_DEBUG, value: '-DENC_DEBUG' }
-# - { key: cppflags, name: GC_DEBUG, value: '-DGC_DEBUG' }
-# - { key: cppflags, name: HASH_DEBUG, value: '-DHASH_DEBUG' }
-# - { key: cppflags, name: ID_TABLE_DEBUG, value: '-DID_TABLE_DEBUG' }
-# - { key: cppflags, name: RGENGC_DEBUG=-1, value: '-DRGENGC_DEBUG=-1' }
-# - { key: cppflags, name: SYMBOL_DEBUG, value: '-DSYMBOL_DEBUG' }
-# - { key: cppflags, name: THREAD_DEBUG=-1, value: '-DTHREAD_DEBUG=-1' }
-
-# - { key: cppflags, name: RGENGC_CHECK_MODE, value: '-DRGENGC_CHECK_MODE' }
-# - { key: cppflags, name: TRANSIENT_HEAP_CHECK_MODE, value: '-DTRANSIENT_HEAP_CHECK_MODE' }
-# - { key: cppflags, name: VM_CHECK_MODE, value: '-DVM_CHECK_MODE' }
-
- - { key: cppflags, name: USE_EMBED_CI=0, value: '-DUSE_EMBED_CI=0' }
- - { key: cppflags, name: USE_FLONUM=0, value: '-DUSE_FLONUM=0' }
-# - { key: cppflags, name: USE_GC_MALLOC_OBJ_INFO_DETAILS, value: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' }
- - { key: cppflags, name: USE_LAZY_LOAD, value: '-DUSE_LAZY_LOAD' }
-# - { key: cppflags, name: USE_RINCGC=0, value: '-DUSE_RINCGC=0' }
-# - { key: cppflags, name: USE_SYMBOL_GC=0, value: '-DUSE_SYMBOL_GC=0' }
-# - { key: cppflags, name: USE_THREAD_CACHE=0, value: '-DUSE_THREAD_CACHE=0' }
-# - { key: cppflags, name: USE_TRANSIENT_HEAP=0, value: '-DUSE_TRANSIENT_HEAP=0' }
-# - { key: cppflags, name: USE_RUBY_DEBUG_LOG=1, value: '-DUSE_RUBY_DEBUG_LOG=1' }
-
- - { key: cppflags, name: DEBUG_FIND_TIME_NUMGUESS, value: '-DDEBUG_FIND_TIME_NUMGUESS' }
- - { key: cppflags, name: DEBUG_INTEGER_PACK, value: '-DDEBUG_INTEGER_PACK' }
-# - { key: cppflags, name: ENABLE_PATH_CHECK, value: '-DENABLE_PATH_CHECK' }
-
- - { key: cppflags, name: GC_DEBUG_STRESS_TO_CLASS, value: '-DGC_DEBUG_STRESS_TO_CLASS' }
-# - { key: cppflags, name: GC_ENABLE_LAZY_SWEEP=0, value: '-DGC_ENABLE_LAZY_SWEEP=0' }
-# - { key: cppflags, name: GC_PROFILE_DETAIL_MEMOTY, value: '-DGC_PROFILE_DETAIL_MEMOTY' }
-# - { key: cppflags, name: GC_PROFILE_MORE_DETAIL, value: '-DGC_PROFILE_MORE_DETAIL' }
-
-# - { key: cppflags, name: CALC_EXACT_MALLOC_SIZE, value: '-DCALC_EXACT_MALLOC_SIZE' }
-# - { key: cppflags, name: MALLOC_ALLOCATED_SIZE_CHECK, value: '-DMALLOC_ALLOCATED_SIZE_CHECK' }
-
-# - { key: cppflags, name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, value: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' }
-
-# - { key: cppflags, name: RGENGC_ESTIMATE_OLDMALLOC, value: '-DRGENGC_ESTIMATE_OLDMALLOC' }
-# - { key: cppflags, name: RGENGC_FORCE_MAJOR_GC, value: '-DRGENGC_FORCE_MAJOR_GC' }
-# - { key: cppflags, name: RGENGC_OBJ_INFO, value: '-DRGENGC_OBJ_INFO' }
-# - { key: cppflags, name: RGENGC_OLD_NEWOBJ_CHECK, value: '-DRGENGC_OLD_NEWOBJ_CHECK' }
-# - { key: cppflags, name: RGENGC_PROFILE, value: '-DRGENGC_PROFILE' }
-
-# - { key: cppflags, name: VM_DEBUG_BP_CHECK, value: '-DVM_DEBUG_BP_CHECK' }
-# - { key: cppflags, name: VM_DEBUG_VERIFY_METHOD_CACHE, value: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }
-
- - { key: cppflags, name: MJIT_FORCE_ENABLE, value: '-DMJIT_FORCE_ENABLE' }
+# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 }
+# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi }
+# - { name: arm-linux-gnueabihf, crosshost: arm-linux-gnueabihf }
+# - { name: i686-w64-mingw32, crosshost: i686-w64-mingw32 }
+# - { name: powerpc-linux-gnu, crosshost: powerpc-linux-gnu }
+# - { name: powerpc64le-linux-gnu, crosshost: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el }
+# - { name: s390x-linux-gnu, crosshost: s390x-linux-gnu, container: crossbuild-essential-s390x }
+# - { name: x86_64-w64-mingw32, crosshost: x86_64-w64-mingw32, container: mingw-w64 }
+
+ # -Wno-strict-prototypes is necessary with current clang-15 since
+ # older autoconf generate functions without prototype and -pedantic
+ # now implies strict-prototypes. Disabling the error but leaving the
+ # warning generates a lot of noise from use of ANYARGS in
+ # rb_define_method() and friends.
+ # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94
+ - { name: c99, env: { append_cc: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+# - { name: c11, env: { append_cc: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+# - { name: c17, env: { append_cc: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+ - { name: c2x, env: { append_cc: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+ - { name: c++98, env: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+# - { name: c++11, env: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+# - { name: c++14, env: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+# - { name: c++17, env: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+ - { name: c++2a, env: { CXXFLAGS: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+
+ - { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } }
+# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true }
+
+ - { name: gmp, env: { append_configure: '--with-gmp' } }
+ - { name: jemalloc, env: { append_configure: '--with-jemalloc' } }
+ - { name: valgrind, env: { append_configure: '--with-valgrind' } }
+ - { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } }
+ - { name: 'coroutine=pthread', env: { append_configure: '--with-coroutine=pthread' } }
+ - { name: disable-jit-support, env: { append_configure: '--disable-jit-support' } }
+ - { name: disable-dln, env: { append_configure: '--disable-dln' } }
+ - { name: enable-mkmf-verbose, env: { append_configure: '--enable-mkmf-verbose' } }
+ - { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } }
+ - { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } }
+
+ - { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } }
+ - { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } }
+ - { name: OPT_THREADED_CODE=3, env: { cppflags: '-DOPT_THREADED_CODE=3' } }
+
+ - { name: NDEBUG, env: { cppflags: '-DNDEBUG' } }
+ - { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } }
+# - { name: ARRAY_DEBUG, env: { cppflags: '-DARRAY_DEBUG' } }
+# - { name: BIGNUM_DEBUG, env: { cppflags: '-DBIGNUM_DEBUG' } }
+# - { name: CCAN_LIST_DEBUG, env: { cppflags: '-DCCAN_LIST_DEBUG' } }
+# - { name: CPDEBUG=-1, env: { cppflags: '-DCPDEBUG=-1' } }
+# - { name: ENC_DEBUG, env: { cppflags: '-DENC_DEBUG' } }
+# - { name: GC_DEBUG, env: { cppflags: '-DGC_DEBUG' } }
+# - { name: HASH_DEBUG, env: { cppflags: '-DHASH_DEBUG' } }
+# - { name: ID_TABLE_DEBUG, env: { cppflags: '-DID_TABLE_DEBUG' } }
+# - { name: RGENGC_DEBUG=-1, env: { cppflags: '-DRGENGC_DEBUG=-1' } }
+# - { name: SYMBOL_DEBUG, env: { cppflags: '-DSYMBOL_DEBUG' } }
+
+# - { name: RGENGC_CHECK_MODE, env: { cppflags: '-DRGENGC_CHECK_MODE' } }
+# - { name: TRANSIENT_HEAP_CHECK_MODE, env: { cppflags: '-DTRANSIENT_HEAP_CHECK_MODE' } }
+# - { name: VM_CHECK_MODE, env: { cppflags: '-DVM_CHECK_MODE' } }
+
+ - { name: USE_EMBED_CI=0, env: { cppflags: '-DUSE_EMBED_CI=0' } }
+ - name: USE_FLONUM=0,
+ env:
+ cppflags: '-DUSE_FLONUM=0'
+ # yjit requires FLONUM for the pointer tagging scheme
+ append_configure: '--disable-yjit'
+# - { name: USE_GC_MALLOC_OBJ_INFO_DETAILS, env: { cppflags: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } }
+ - { name: USE_LAZY_LOAD, env: { cppflags: '-DUSE_LAZY_LOAD' } }
+# - { name: USE_RINCGC=0, env: { cppflags: '-DUSE_RINCGC=0' } }
+# - { name: USE_SYMBOL_GC=0, env: { cppflags: '-DUSE_SYMBOL_GC=0' } }
+# - { name: USE_THREAD_CACHE=0, env: { cppflags: '-DUSE_THREAD_CACHE=0' } }
+# - { name: USE_TRANSIENT_HEAP=0, env: { cppflags: '-DUSE_TRANSIENT_HEAP=0' } }
+# - { name: USE_RUBY_DEBUG_LOG=1, env: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } }
+ - { name: USE_RVARGC=0, env: { cppflags: '-DUSE_RVARGC=0' } }
+# - { name: USE_RVARGC=1, env: { cppflags: '-DUSE_RVARGC=1' } }
+# - { name: USE_DEBUG_COUNTER, env: { cppflags: '-DUSE_DEBUG_COUNTER=1', RUBY_DEBUG_COUNTER_DISABLE: '1' } }
+
+ - { name: DEBUG_FIND_TIME_NUMGUESS, env: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } }
+ - { name: DEBUG_INTEGER_PACK, env: { cppflags: '-DDEBUG_INTEGER_PACK' } }
+# - { name: ENABLE_PATH_CHECK, env: { cppflags: '-DENABLE_PATH_CHECK' } }
+
+ - { name: GC_DEBUG_STRESS_TO_CLASS, env: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } }
+# - { name: GC_ENABLE_LAZY_SWEEP=0, env: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } }
+# - { name: GC_PROFILE_DETAIL_MEMOTY, env: { cppflags: '-DGC_PROFILE_DETAIL_MEMOTY' } }
+# - { name: GC_PROFILE_MORE_DETAIL, env: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } }
+
+# - { name: CALC_EXACT_MALLOC_SIZE, env: { cppflags: '-DCALC_EXACT_MALLOC_SIZE' } }
+# - { name: MALLOC_ALLOCATED_SIZE_CHECK, env: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } }
+
+# - { name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, env: { cppflags: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } }
+
+# - { name: RGENGC_ESTIMATE_OLDMALLOC, env: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } }
+# - { name: RGENGC_FORCE_MAJOR_GC, env: { cppflags: '-DRGENGC_FORCE_MAJOR_GC' } }
+# - { name: RGENGC_OBJ_INFO, env: { cppflags: '-DRGENGC_OBJ_INFO' } }
+# - { name: RGENGC_OLD_NEWOBJ_CHECK, env: { cppflags: '-DRGENGC_OLD_NEWOBJ_CHECK' } }
+# - { name: RGENGC_PROFILE, env: { cppflags: '-DRGENGC_PROFILE' } }
+
+# - { name: VM_DEBUG_BP_CHECK, env: { cppflags: '-DVM_DEBUG_BP_CHECK' } }
+# - { name: VM_DEBUG_VERIFY_METHOD_CACHE, env: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } }
+
+ - { name: MJIT_FORCE_ENABLE, env: { cppflags: '-DMJIT_FORCE_ENABLE' } }
+ - { name: YJIT_FORCE_ENABLE, env: { cppflags: '-DYJIT_FORCE_ENABLE' } }
name: ${{ matrix.entry.name }}
runs-on: ubuntu-latest
- container: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || 'clang-14' }}
+ container:
+ image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-15' }}
+ options: --user root
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ env: ${{ matrix.entry.env || matrix.env }}
steps:
+ - run: id
+ working-directory:
- 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
+ echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
- run: ./autogen.sh
working-directory: src
- name: Run configure
- run: ../src/configure -C ${default_configure} ${append_configure} --with-gcc="${default_cc} ${append_cc}"
- if: ${{ matrix.entry.key != 'crosshost' }}
- - name: Run cross configure
- run: ../src/configure -C ${default_configure} ${append_configure} --host="${crosshost}"
- if: ${{ matrix.entry.key == 'crosshost' }}
- - run: $make extract-extlibs
- - run: $make incs
- - run: $make
- - run: $make leaked-globals
- - run: $make test
- - run: $make install
+ run: >
+ ../src/configure -C ${default_configure} ${append_configure}
+ --${{
+ matrix.entry.crosshost && 'host' || 'with-gcc'
+ }}=${{
+ matrix.entry.crosshost || '"${default_cc}${append_cc:+ $append_cc}"'
+ }}
+ --${{ matrix.entry.shared || 'enable' }}-shared
+ - run: make extract-extlibs
+ - run: make incs
+ - run: make showflags
+ - run: make
+ - run: make leaked-globals
+ - run: make test
+ - run: make install
if: ${{ matrix.entry.check }}
- - run: /usr/local/bin/gem install --no-doc timezone tzinfo
+ - run: make test-tool
if: ${{ matrix.entry.check }}
- - run: $make test-tool
+ - run: make test-all TESTS='-- ruby -ext-'
if: ${{ matrix.entry.check }}
- - run: $make test-all TESTS='-- ruby -ext-'
- if: ${{ matrix.entry.check }}
- - run: $make test-spec
+ - run: make test-spec
+ env:
+ CHECK_LEAKS: true
if: ${{ matrix.entry.check }}
+ - run: make test-annocheck
+ if: ${{ matrix.entry.check && endsWith(matrix.entry.name, 'annocheck') }}
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -211,7 +270,7 @@ jobs:
"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]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 0a2d7ea73b..d8dc58b119 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -1,14 +1,48 @@
name: macOS
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
jobs:
make:
- runs-on: macos-latest
strategy:
matrix:
- test_task: [ "check", "test-bundler-parallel" ] #, "test-bundled-gems" ] matrix tests has unknown issues
+ test_task: ["check"] # "test-bundler-parallel", "test-bundled-gems"
+ os:
+ - macos-13
+ - macos-14
+ - macos-15
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ runs-on: ${{ matrix.os }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
@@ -16,41 +50,59 @@ jobs:
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
- name: Install libraries
run: |
- brew upgrade
- brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline
+ brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline bison
working-directory: src
- name: Set ENV
run: |
- echo "JOBS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV
+ echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV
+ echo "PATH="/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin:$PATH"" >> $GITHUB_ENV
- 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 incs
- run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+ - run: make
+ - run: make leaked-globals
if: ${{ matrix.test_task == 'check' }}
- - run: make $JOBS -s ${{ matrix.test_task }}
- timeout-minutes: 60
+ - name: make ${{ matrix.test_task }}
+ run: |
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ timeout-minutes: 40
env:
RUBY_TESTOPTS: "-q --tty=no"
- TEST_BUNDLED_GEMS_ALLOW_FAILURES: "rexml"
- - uses: k0kubun/action-slack@v2.0.0
+ TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
+ PRECHECK_BUNDLED_GEMS: "no"
+ - name: make skipped tests
+ run: |
+ make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ env:
+ GNUMAKEFLAGS: ""
+ RUBY_TESTOPTS: "-v --tty=no"
+ TESTS: ${{ matrix.skipped_tests }}
+ PRECHECK_BUNDLED_GEMS: "no"
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ github.workflow }} / ${{ matrix.test_task }}",
+ "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
index 8f5a8e657f..0df917d3d8 100644
--- a/.github/workflows/mingw.yml
+++ b/.github/workflows/mingw.yml
@@ -1,27 +1,61 @@
name: MinGW
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
# Notes:
# Actions console encoding causes issues, see test-all & test-spec steps
#
jobs:
make:
- runs-on: windows-2019
+ runs-on: windows-2022
+ name: ${{ github.workflow }} (${{ matrix.msystem }})
env:
- MSYSTEM: MINGW64
- MSYSTEM_PREFIX: /mingw64
+ MSYSTEM: ${{ matrix.msystem }}
MSYS2_ARCH: x86_64
CHOST: "x86_64-w64-mingw32"
- CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong"
+ CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe"
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"
+ LDFLAGS: "-pipe"
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
+ include:
+ # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses.
+ - msystem: "UCRT64"
+ base_ruby: head
+ test_task: "check"
+ test-all-opts: "--name=!/TestObjSpace#test_reachable_objects_during_iteration/"
fail-fast: false
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
@@ -31,108 +65,109 @@ jobs:
git config --global core.eol lf
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
- name: Set up Ruby & MSYS2
- uses: MSP-Greg/setup-ruby-pkgs@v1
+ uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
with:
- ruby-version: 2.6
- mingw: _upgrade_ gmp libffi libyaml openssl ragel readline
- msys2: automake1.16 bison
+ ruby-version: ${{ matrix.base_ruby }}
+ - name: set env
+ run: |
+ echo "GNUMAKEFLAGS=-j$((2 * NUMBER_OF_PROCESSORS))" >> $GITHUB_ENV
+
- 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: misc setup, autoreconf
+ mv /c/Windows/System32/libcrypto-1_1-x64.dll /c/Windows/System32/libcrypto-1_1-x64.dll_
+ mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_
+ result=true
+ for e in gcc.exe ragel.exe make.exe bison.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do
+ echo '##['group']'$'\033[93m'$e$'\033[m'
+ where $e || result=false
+ echo '##['endgroup']'
+ done
+ $result
+
+ - name: version check
run: |
- mkdir install
- mkdir temp
- cd src
- sh -c "autoreconf -fi"
- working-directory:
+ # show version
+ result=true
+ for e in gcc ragel make bison "openssl version"; do
+ case "$e" in *" "*) ;; *) e="$e --version";; esac
+ echo '##['group']'$'\033[93m'$e$'\033[m'
+ $e || result=false
+ echo '##['endgroup']'
+ done
+ $result
- - name: configure
+ - name: autogen
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=/install $config_args"
- # Write-Host "-------------------------------------- config.log"
- # Get-Content ./config.log | foreach {Write-Output $_}
+ ./autogen.sh
+ working-directory: src
+
+ - name: configure
+ run: >
+ ../src/configure --disable-install-doc --prefix=/.
+ --build=$CHOST --host=$CHOST --target=$CHOST
- name: update
run: |
- $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS)
- make -j $jobs incs
+ make incs
- name: download gems
run: |
- $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS)
- make -j $jobs update-gems
+ make update-gems
- name: make all
- timeout-minutes: 40
+ timeout-minutes: 30
run: |
- $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS)
- make -j $jobs
+ make
- run: make leaked-globals
- 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-nodoc
+ make DESTDIR=../install install-nodoc
- name: test
timeout-minutes: 5
run: |
make test
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test'}}
- name: test-all
- timeout-minutes: 60
+ timeout-minutes: 45
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"
+ chcp.com 437
+ make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
+ env:
+ RUBY_TESTOPTS: >-
+ --retry --job-status=normal --show-skip --timeout-scale=1.5
+ ${{ matrix.test-all-opts }}
+ BUNDLER_VERSION:
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/')}}
- 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 --timeout 60
+ make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }}
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/')}}
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ github.workflow }} / ${{ matrix.test_task }}",
+ "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]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
@@ -141,3 +176,4 @@ jobs:
defaults:
run:
working-directory: build
+ shell: sh
diff --git a/.github/workflows/mjit-bindgen.yml b/.github/workflows/mjit-bindgen.yml
new file mode 100644
index 0000000000..26f8a1b2aa
--- /dev/null
+++ b/.github/workflows/mjit-bindgen.yml
@@ -0,0 +1,104 @@
+name: MJIT bindgen
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ include:
+ - task: mjit-bindgen
+ fail-fast: false
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: Set ENV
+ run: |
+ echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - 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 \
+ libclang1-14 \
+ bison autoconf
+ sudo apt-get install -q -y pkg-config || :
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
+ with:
+ ruby-version: '3.1'
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
+ - name: Fixed world writable dirs
+ run: |
+ chmod -v go-w $HOME $HOME/.config
+ sudo chmod -R go-w /usr/share
+ sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install --enable-yjit=dev_nodebug
+ - run: make incs
+ - run: make
+ - run: make install
+ - run: make ${{ matrix.task }}
+ - run: git diff --exit-code
+ working-directory: src
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ 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 63011e78d0..6f7181489a 100644
--- a/.github/workflows/mjit.yml
+++ b/.github/workflows/mjit.yml
@@ -1,16 +1,49 @@
name: MJIT
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '**.[1-8]'
+ - '**.ronn'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '**.[1-8]'
+ - '**.ronn'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
jobs:
make:
strategy:
matrix:
- test_task: [ "check" ] # to make job names consistent
- jit_opts: [ "--jit", "--jit-wait" ]
+ test_task: [check] # to make job names consistent
+ mjit_opts: [--mjit-wait]
fail-fast: false
runs-on: ubuntu-latest
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
env:
TESTOPTS: '-q --tty=no'
- RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --jit-debug=-ggdb3'
+ RUN_OPTS: '--disable-gems ${{ matrix.mjit_opts }} --mjit-debug=-ggdb3'
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
steps:
- run: mkdir build
@@ -24,9 +57,13 @@ jobs:
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
- name: Fixed world writable dirs
run: |
chmod -v go-w $HOME $HOME/.config
@@ -34,39 +71,38 @@ jobs:
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
+ echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- run: ./autogen.sh
working-directory: src
- name: Run configure
run: ../src/configure -C --disable-install-doc cppflags=-DVM_CHECK_MODE
- - run: make $JOBS incs
- - run: make $JOBS
- - run: sudo make $JOBS -s install
- - run: sudo apt-get install gdb # used by test / test-all failure
+ - run: make incs
+ - run: make
+ - run: sudo make -s install
- 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"
+ unset GNUMAKEFLAGS
+ make -s test RUN_OPTS="$RUN_OPTS"
timeout-minutes: 60
+ # - name: Run test-all
+ # run: |
+ # ulimit -c unlimited
+ # make -s test-all RUN_OPTS="$RUN_OPTS"
+ # timeout-minutes: 60
- name: Run test-spec
run: |
- ulimit -c unlimited
- make $JOBS -s test-spec RUN_OPTS="$RUN_OPTS"
+ unset GNUMAKEFLAGS
+ make -s test-spec RUN_OPTS="$RUN_OPTS"
timeout-minutes: 60
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.jit_opts }}",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.mjit_opts }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000000..5d4474d978
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,18 @@
+name: Start release workflow
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Build release package
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/actions/dispatches \
+ -d '{"event_type": "${{ github.ref }}"}'
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
new file mode 100644
index 0000000000..c12a95362d
--- /dev/null
+++ b/.github/workflows/scorecards.yml
@@ -0,0 +1,72 @@
+# This workflow uses actions that are not certified by GitHub. They are provided
+# by a third-party and are governed by separate terms of service, privacy
+# policy, and support documentation.
+
+name: Scorecards supply-chain security
+on:
+ # For Branch-Protection check. Only the default branch is supported. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+ branch_protection_rule:
+ # To guarantee Maintained check is occasionally updated. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+ schedule:
+ - cron: '22 4 * * 2'
+ push:
+ branches: [ "master" ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecards analysis
+ runs-on: ubuntu-latest
+ permissions:
+ # Needed to upload the results to code-scanning dashboard.
+ security-events: write
+ # Needed to publish results and get a badge (see publish_results below).
+ id-token: write
+ # Uncomment the permissions below if installing in a private repository.
+ # contents: read
+ # actions: read
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@ea651e62978af7915d09fe2e282747c798bf2dab # v2.4.1
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
+ # - you want to enable the Branch-Protection check on a *public* repository, or
+ # - you are installing Scorecards on a *private* repository
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
+ repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
+
+ # Public repositories:
+ # - Publish results to OpenSSF REST API for easy access by consumers
+ # - Allows the repository to include the Scorecard badge.
+ # - See https://github.com/ossf/scorecard-action#publishing-results.
+ # For private repositories:
+ # - `publish_results` will always be set to `false`, regardless
+ # of the value entered here.
+ publish_results: true
+
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+ # format to the repository Actions tab.
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ # Upload the results to GitHub's code scanning dashboard.
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.27
+ with:
+ sarif_file: results.sarif
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
index 61ebeb33c1..4521195a2b 100644
--- a/.github/workflows/spec_guards.yml
+++ b/.github/workflows/spec_guards.yml
@@ -1,29 +1,62 @@
name: Rubyspec Version Guards Check
-on: [push, pull_request]
+on:
+ push:
+ paths:
+ - 'spec/**'
+ - '!spec/*.md'
+ pull_request:
+ paths:
+ - 'spec/**'
+ - '!spec/*.md'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
jobs:
rubyspec:
name: Rubyspec
- runs-on: ubuntu-20.04
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
+ || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ )}}
+
strategy:
matrix:
# Specs from ruby/spec should still run on all supported Ruby versions.
# This also ensures the needed ruby_version_is guards are there, see spec/README.md.
ruby:
- - ruby-2.7
- - ruby-3.0
+ - ruby-3.1
+ - ruby-3.2
steps:
- - uses: actions/checkout@v2
- - uses: ruby/setup-ruby@v1
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
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
+ env:
+ CHECK_LEAKS: true
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -31,8 +64,8 @@ jobs:
"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]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
- if: ${{ failure() && github.event_name == 'push' }}
+ if: ${{ failure() }}
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index e148b76cbe..4fbca1170e 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -1,74 +1,141 @@
name: Ubuntu
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
jobs:
make:
strategy:
matrix:
- test_task: ["check", "test-bundler-parallel", "test-bundled-gems"]
- os:
- - ubuntu-20.04
-# - ubuntu-18.04
- configure: ["", "cppflags=-DRUBY_DEBUG"]
+ # main variables included in the job name
+ test_task: [check]
+ configure: [cppflags=-DRUBY_DEBUG] # default to use more assertions
+ arch: ['']
+ # specify all jobs with `include` to avoid testing duplicated things
include:
- - test_task: "test-all TESTS=--repeat-count=2"
- os: ubuntu-20.04
- configure: ""
+ - test_task: check
+ - test_task: check
+ arch: i686
+ configure: '' # test without -DRUBY_DEBUG as well
+ - test_task: check
+ configure: "--enable-shared --enable-load-relative"
+ - test_task: test-all TESTS=--repeat-count=2
+ - test_task: test-bundler-parallel
+ - test_task: test-bundled-gems
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
RUBY_DEBUG: ci
- runs-on: ${{ matrix.os }}
+ SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
+ - name: Set ENV
+ run: |
+ echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- name: Install libraries
+ env:
+ arch: ${{matrix.arch}}
run: |
set -x
+ arch=${arch:+:${arch/i[3-6]86/i386}}
+ ${arch:+sudo dpkg --add-architecture ${arch#:}}
sudo apt-get update -q || :
- sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby
+ sudo apt-get install --no-install-recommends -q -y \
+ ${arch:+cross}build-essential${arch/:/-} \
+ libssl-dev${arch} libyaml-dev${arch} libreadline6-dev${arch} \
+ zlib1g-dev${arch} libncurses5-dev${arch} libffi-dev${arch} \
+ bison autoconf ruby
+ sudo apt-get install -q -y pkg-config${arch} || :
- name: git config
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
- name: Fixed world writable dirs
run: |
chmod -v go-w $HOME $HOME/.config
sudo chmod -R go-w /usr/share
sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
- - name: Set ENV
- run: |
- echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- run: ./autogen.sh
working-directory: src
- name: Run configure
- run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
- - run: make $JOBS incs
- - run: make $JOBS
- - run: make leaked-globals
- if: ${{ matrix.test_task == 'check' }}
- - run: make prepare-gems
+ env:
+ arch: ${{matrix.arch}}
+ run: >-
+ $SETARCH ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
+ - run: $SETARCH make incs
+ - run: $SETARCH make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+ - run: $SETARCH make
+ - run: $SETARCH make leaked-globals
if: ${{ matrix.test_task == 'check' }}
- name: Create dummy files in build dir
run: |
- ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}'
+ $SETARCH ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}'
if: ${{ matrix.test_task == 'check' }}
- - run: make $JOBS -s ${{ matrix.test_task }}
- timeout-minutes: 30
+ - name: make ${{ matrix.test_task }}
+ run: |
+ $SETARCH make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ timeout-minutes: 40
env:
RUBY_TESTOPTS: "-q --tty=no"
+ TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
- - uses: k0kubun/action-slack@v2.0.0
+ PRECHECK_BUNDLED_GEMS: "no"
+ - name: make skipped tests
+ run: |
+ $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ env:
+ GNUMAKEFLAGS: ""
+ RUBY_TESTOPTS: "-v --tty=no"
+ TESTS: ${{ matrix.skipped_tests }}
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml
new file mode 100644
index 0000000000..27920b5821
--- /dev/null
+++ b/.github/workflows/wasm.yml
@@ -0,0 +1,146 @@
+name: WebAssembly
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ entry:
+# # wasmtime can't compile non-optimized Asyncified binary due to locals explosion
+# - { name: O0-debuginfo, optflags: "-O0", debugflags: "-g", wasmoptflags: "-O1" }
+# - { name: O1, optflags: "-O1", debugflags: "" , wasmoptflags: "-O1" }
+ - { name: O2, optflags: "-O2", debugflags: "" , wasmoptflags: "-O2" }
+# - { name: O3, optflags: "-O3", debugflags: "" , wasmoptflags: "-O3" }
+# # -O4 is equivalent to -O3 in clang, but it's different in wasm-opt
+# - { name: O4, optflags: "-O3", debugflags: "" , wasmoptflags: "-O4" }
+# - { name: Oz, optflags: "-Oz", debugflags: "" , wasmoptflags: "-Oz" }
+ fail-fast: false
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ WASI_SDK_VERSION_MAJOR: 14
+ WASI_SDK_VERSION_MINOR: 0
+ BINARYEN_VERSION: 109
+ WASMTIME_VERSION: v0.33.0
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ path: src
+ - name: Install libraries
+ run: |
+ set -ex
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y ruby bison make autoconf git wget
+
+ wasi_sdk_deb="wasi-sdk_${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}_amd64.deb"
+ wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}"
+ sudo dpkg -i "$wasi_sdk_deb"
+ rm -f "$wasi_sdk_deb"
+
+ mkdir build-sdk
+ pushd build-sdk
+
+ wasmtime_url="https://github.com/bytecodealliance/wasmtime/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-x86_64-linux.tar.xz"
+ wget -O - "$wasmtime_url" | tar xJf -
+ sudo ln -fs "$PWD/wasmtime-${WASMTIME_VERSION}-x86_64-linux/wasmtime" /usr/local/bin/wasmtime
+
+ binaryen_tarball="binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz"
+ binaryen_url="https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/${binaryen_tarball}"
+ wget -O - "$binaryen_url" | tar xfz -
+ sudo ln -fs "$PWD/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt" /usr/local/bin/wasm-opt
+ working-directory: src
+ - name: Set ENV
+ run: |
+ echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV
+ echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV
+ - run: ./autogen.sh
+ working-directory: src
+
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
+ - name: Download config.guess with wasi version
+ run: |
+ rm tool/config.guess tool/config.sub
+ ruby tool/downloader.rb -d tool -e gnu config.guess config.sub
+ working-directory: src
+
+ - name: Run configure
+ run: |
+ ../src/configure \
+ --host wasm32-unknown-wasi \
+ --with-static-linked-ext \
+ LDFLAGS=" \
+ -Xlinker --stack-first \
+ -Xlinker -z -Xlinker stack-size=16777216 \
+ " \
+ optflags="${{ matrix.entry.optflags }}" \
+ debugflags="${{ matrix.entry.debugflags }}" \
+ wasmoptflags="${{ matrix.entry.wasmoptflags }} ${{ matrix.entry.debugflags }}"
+
+ # miniruby may not be built when cross-compling
+ - run: make mini ruby
+ - name: Run basictest
+ run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb
+ working-directory: src
+ - name: Run bootstraptest (no thread)
+ run: |
+ NO_THREAD_TESTS="$(grep -L Thread -R ./bootstraptest | awk -F/ '{ print $NF }' | uniq | sed -n 's/test_\(.*\).rb/\1/p' | paste -s -d, -)"
+ ruby ./bootstraptest/runner.rb --ruby="$(which wasmtime) run $PWD/../build/ruby --mapdir /::./ -- " --verbose "--sets=$NO_THREAD_TESTS"
+ working-directory: src
+
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / ${{ matrix.name }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ 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/windows.yml b/.github/workflows/windows.yml
index 6adc4fcd4c..c2bd4881c2 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -1,94 +1,143 @@
name: Windows
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
jobs:
make:
strategy:
matrix:
- test_task: [check] # to make job names consistent
- os: [windows-2019]
- vs: [2019]
+ include:
+ - vs: 2022
+ vcvers: -vcvars_ver=14.2
fail-fast: false
- runs-on: ${{ matrix.os }}
+ runs-on: windows-${{ matrix.vs }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ name: VisualStudio ${{ matrix.vs }}
env:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
- VCVARS: C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat
PATCH: C:\msys64\usr\bin\patch.exe
+ OS_VER: windows-${{ matrix.vs }}
steps:
- run: md build
working-directory:
- - uses: actions/cache@v2
+ - uses: msys2/setup-msys2@61f9e5e925871ba6c9e3e8da24ede83ea27fa91f # v2.27.0
+ id: setup-msys2
with:
- path: C:\vcpkg\downloads
- key: ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-
- ${{ runner.os }}-vcpkg-download-
- - name: Install libraries with vcpkg
- run: |
- vcpkg --triplet x64-windows install readline zlib
- - uses: actions/cache@v2
+ update: true
+ install: bison patch
+ - name: patch path
+ shell: msys2 {0}
+ run: echo PATCH=$(cygpath -wa $(command -v patch)) >> $GITHUB_ENV
+ if: ${{ steps.setup-msys2.outcome == 'success' }}
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
- path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
- key: ${{ runner.os }}-chocolatey-${{ matrix.os }}-${{ github.sha }}
+ path: C:\vcpkg\installed
+ key: ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-${{ github.sha }}
restore-keys: |
- ${{ runner.os }}-chocolatey-${{ matrix.os }}-
- ${{ runner.os }}-chocolatey-
- - name: Install libraries with chocolatey
+ ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-
+ ${{ runner.os }}-vcpkg-installed-windows-
+ - name: Install libraries with vcpkg
run: |
- # Using Choco-Install for retries, but it doesn't detect failures properly
- # if you pass multiple package names in a single command.
- Choco-Install -PackageName openssl
- Choco-Install -PackageName winflexbison3
- shell: pwsh
+ iex "& {$(irm get.scoop.sh)} -RunAsAdmin"
+ Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
+ scoop install cmake@3.31.6
+ vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib
+ shell:
+ pwsh
- name: git config
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - name: Configure
- run: |
- call "%VCVARS%"
- ../src/win32/configure.bat --disable-install-doc --enable-bundled-libffi --with-opt-dir=C:/vcpkg/installed/x64-windows --with-openssl-dir="C:/Program Files/OpenSSL-Win64"
- - name: nmake
- run: |
- call "%VCVARS%"
- set YACC=win_bison
- echo on
- nmake incs
- nmake extract-extlibs
- nmake
- - name: nmake test
- timeout-minutes: 5
- run: |
- call "%VCVARS%"
- nmake test
- - name: nmake test-all
- timeout-minutes: 60
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
+ - name: setup env
+ # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
+ # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ # msys2/setup-msys2 installs MSYS2 to D:/a/_temp/msys64/usr/bin
run: |
- call "%VCVARS%"
- ::- %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
- ::- https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ set Path=D:/a/_temp/msys64/usr/bin;%Path%
+ if not "%VCVARS%" == "" goto :vcset
+ set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ :vcset
+ set | C:\msys64\usr\bin\sort > old.env
+ call %VCVARS% ${{ matrix.vcvers || ''}}
set TMP=%USERPROFILE%\AppData\Local\Temp
set TEMP=%USERPROFILE%\AppData\Local\Temp
- nmake test-all
- - name: nmake test-spec
- timeout-minutes: 10
+ set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul
+ set | C:\msys64\usr\bin\sort > new.env
+ C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV%
+ del *.env
+ - name: compiler version
+ run: cl
+ - name: link libraries
run: |
- call "%VCVARS%"
- nmake test-spec
- - uses: k0kubun/action-slack@v2.0.0
+ for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do (
+ if not %%~nI == readline mklink %%~nxI %%I
+ )
+ for %%I in (libcrypto-1_1-x64 libssl-1_1-x64) do (
+ ren c:\Windows\System32\%%I.dll %%I.dll_
+ )
+ - name: Configure
+ run: >-
+ ../src/win32/configure.bat --disable-install-doc
+ --with-opt-dir=C:/vcpkg/installed/x64-windows
+ - run: nmake incs
+ - run: nmake extract-extlibs
+ - run: nmake
+ env:
+ YACC: bison.exe
+ - run: nmake test
+ timeout-minutes: 5
+ - run: nmake test-spec
+ timeout-minutes: 10
+ - run: nmake test-all
+ env:
+ RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --job-status=normal
+ timeout-minutes: 60
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ matrix.os }} / ${{ matrix.test_task }}",
+ "env": "VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml
new file mode 100644
index 0000000000..0b7b9046e9
--- /dev/null
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -0,0 +1,170 @@
+name: YJIT Ubuntu
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ cargo:
+ name: Rust cargo test
+ # GitHub Action's image seems to already contain a Rust 1.58.0.
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ # For now we can't run cargo test --offline because it complains about the
+ # capstone dependency, even though the dependency is optional
+ #- run: cargo test --offline
+ - run: RUST_BACKTRACE=1 cargo test
+ working-directory: yjit
+ # Also compile and test with all features enabled
+ - run: RUST_BACKTRACE=1 cargo test --all-features
+ working-directory: yjit
+ # Check that we can build in release mode too
+ - run: cargo build --release
+ working-directory: yjit
+ make:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - test_task: 'yjit-bindgen'
+ hint: 'To fix: use patch in logs'
+ configure: '--with-gcc=clang-14 --enable-yjit=dev'
+ libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1'
+
+ - test_task: "check"
+ # YJIT should be automatically built in release mode on x86-64 Linux with rustc present
+ #configure: "--enable-yjit RUSTC='rustc +1.58.0'"
+ configure: "RUSTC='rustc +1.58.0'"
+ rust_version: "1.58.0"
+
+ - test_task: "check"
+ configure: "--enable-yjit=dev"
+
+ - test_task: "check"
+ configure: "--enable-yjit=dev"
+ yjit_opts: "--yjit-call-threshold=1 --yjit-verify-ctx"
+
+ - test_task: "test-all TESTS=--repeat-count=2"
+ configure: "--enable-yjit=dev"
+
+ - test_task: "test-bundled-gems"
+ configure: "--enable-yjit=dev"
+
+ - test_task: "yjit-bench"
+ configure: "--enable-yjit=dev"
+ yjit_bench_opts: "--yjit-stats"
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ RUN_OPTS: ${{ matrix.yjit_opts }}
+ YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
+ RUBY_DEBUG: ci
+ BUNDLE_JOBS: 8 # for yjit-bench
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: Install libraries
+ run: |
+ set -x
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: rustup install ${{ matrix.rust_version }} --profile minimal
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
+ - name: Fixed world writable dirs
+ run: |
+ chmod -v go-w $HOME $HOME/.config
+ sudo chmod -R go-w /usr/share
+ sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
+ - name: Set ENV
+ run: |
+ echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
+ - run: make incs
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+ - run: make -j
+ - run: make leaked-globals
+ if: ${{ matrix.test_task == 'check' }}
+ - name: Create dummy files in build dir
+ run: |
+ ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}'
+ if: ${{ matrix.test_task == 'check' }}
+ - name: Enable YJIT through ENV
+ run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ # Check that the binary was built with YJIT
+ - name: Check YJIT enabled
+ run: ./miniruby --yjit -v | grep "+YJIT"
+ - name: make ${{ matrix.test_task }}
+ run: make -s -j ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS"
+ timeout-minutes: 60
+ env:
+ RUBY_TESTOPTS: "-q --tty=no"
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
+ PRECHECK_BUNDLED_GEMS: "no"
+ LIBCLANG_PATH: ${{ matrix.libclang_path }}
+ continue-on-error: ${{ matrix.test_task == 'yjit-bench' }}
+ - name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison
+ run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}"
+ env:
+ BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
+ if: ${{ matrix.test_task == 'yjit-bench' && startsWith(github.event_name, 'pull') }}
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.configure }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ 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/.gitignore b/.gitignore
index 8d11d7278a..99d32a1825 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,9 +10,11 @@
*.dylib
*.elc
*.i
+*.ii
*.inc
*.log
*.o
+*.o.tmp
*.obj
*.old
*.orig
@@ -24,6 +26,7 @@
*.sav
*.sl
*.so
+*.so.*
*.swp
*.yarb
*~
@@ -126,6 +129,7 @@ lcov*.info
/ruby-runner
/ruby-runner.h
/ruby-man.rd.gz
+/rubyspec_temp
/run.gdb
/sizes.c
/static-ruby
@@ -143,6 +147,8 @@ lcov*.info
/bin/*.exe
/bin/*.dll
+/bin/goruby
+/bin/ruby
# /benchmark/
/benchmark/bm_require.data
@@ -182,6 +188,9 @@ lcov*.info
/ext/-test-/win32/dln/dlntest.exp
/ext/-test-/win32/dln/dlntest.lib
+# /ext/-test-/gems
+/ext/-test-/gems
+
# /ext/etc/
/ext/etc/constdefs.h
@@ -214,6 +223,9 @@ lcov*.info
/lib/ruby/[1-9]*.*
/lib/ruby/vendor_ruby
+# /misc/
+/misc/**/__pycache__
+
# /spec/bundler
/.rspec_status
@@ -225,6 +237,14 @@ lcov*.info
/win32/*.ico
# MJIT
-/rb_mjit_header.h
-/mjit_config.h
/include/ruby-*/*/rb_mjit_min_header-*.h
+/lib/ruby_vm/mjit/instruction.rb
+/mjit_config.h
+/rb_mjit_header.h
+
+# YJIT
+/yjit-bench
+/yjit_exit_locations.dump
+
+# /wasm/
+/wasm/tests/*.wasm
diff --git a/.indent.pro b/.indent.pro
new file mode 100644
index 0000000000..1d61cbcad1
--- /dev/null
+++ b/.indent.pro
@@ -0,0 +1,32 @@
+-bap
+-nbbb
+-nbc
+-br
+-brs
+-nbs
+-ncdb
+-nce
+-cdw
+-cli2
+-cbi2
+-ndj
+-ncs
+-nfc1
+-i4
+-l120
+-lp
+-npcs
+-psl
+-sc
+-sob
+-sbi4
+-nut
+-par
+
+-TID
+-TVALUE
+-Tst_data_t
+-Tst_index_t
+-Tst_table
+-Trb_data_type_t
+-TFILE
diff --git a/.rdoc_options b/.rdoc_options
new file mode 100644
index 0000000000..760507c7a2
--- /dev/null
+++ b/.rdoc_options
@@ -0,0 +1,4 @@
+---
+page_dir: doc
+main_page: README.md
+title: Documentation for Ruby development version
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c84cb1a6d7..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,228 +0,0 @@
-# -*- YAML -*-
-# Copyright (C) 2011 Urabe, Shyouhei. All rights reserved.
-#
-# This file is a part of the programming language Ruby. Permission is hereby
-# granted, to either redistribute or modify this file, provided that the
-# conditions mentioned in the file COPYING are met. Consult the file for
-# details.
-
-# We only manage non-amd64 free pipelines.
-# https://docs.travis-ci.com/user/billing-overview/
-
-language: c
-
-os: linux
-
-dist: focal
-
-git:
- quiet: true
-
-cache:
- ccache: true
- directories:
- - $HOME/config_2nd
- - $HOME/.downloaded-cache
-
-env:
- global:
- # Reset timestamps early
- - _=$(touch NEWS && find . -type f -exec touch -r NEWS {} +)
- - CONFIGURE_TTY=no
- - CCACHE_COMPILERCHECK=none
- - CCACHE_NOCOMPRESS=1
- - CCACHE_MAXSIZE=512Mi
- - NPROC="`nproc`"
- # JOBS and SETARCH are overridden when necessary; see below.
- - JOBS=-j$((1+${NPROC}))
- - SETARCH=
- - RUBY_PREFIX=/tmp/ruby-prefix
- - GEMS_FOR_TEST='timezone tzinfo'
- # The tests skipped in `make test-all`.
- - TEST_ALL_SKIPPED_TESTS=
- # Run the separated tests with allowing failures.
- - RUN_SEPARATED_TESTS=true
- # The tests executed separately by `make test-all`.
- - TEST_ALL_SEPARATED_TESTS=
- # https://github.com/travis-ci/travis-build/blob/e411371dda21430a60f61b8f3f57943d2fe4d344/lib/travis/build/bash/travis_apt_get_options.bash#L7
- - travis_apt_get_options='--allow-downgrades --allow-remove-essential --allow-change-held-packages'
- - travis_apt_get_options="-yq --no-install-suggests --no-install-recommends $travis_apt_get_options"
- # -O1 is faster than -O3 in our tests.
- - optflags=-O1
- # -g0 disables backtraces when SEGV. Do not set that.
- - debugflags=-ggdb3
-
-.org.ruby-lang.ci.matrix-definitions:
-
- - &gcc-10
- compiler: gcc-10
- before_install:
- - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - >-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
- ccache
- gcc-10
- g++-10
- libffi-dev
- libgdbm-dev
- libncurses-dev
- libncursesw5-dev
- libreadline-dev
- libssl-dev
- libyaml-dev
- openssl
- zlib1g-dev
-
- # --------
-
- - &arm64-linux
- name: arm64-linux
- arch: arm64
- <<: *gcc-10
-
- - &ppc64le-linux
- name: ppc64le-linux
- arch: ppc64le
- <<: *gcc-10
-
- - &s390x-linux
- name: s390x-linux
- arch: s390x
- <<: *gcc-10
-
- - &arm32-linux
- name: arm32-linux
- arch: arm64
- # https://packages.ubuntu.com/focal/crossbuild-essential-armhf
- compiler: arm-linux-gnueabihf-gcc
- env:
- - SETARCH='setarch linux32 --verbose --32bit'
- before_install:
- - sudo dpkg --add-architecture armhf
- - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - >-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
- ccache
- crossbuild-essential-armhf
- libc6:armhf
- libstdc++-10-dev:armhf
- libffi-dev:armhf
- libgdbm-dev:armhf
- libncurses-dev:armhf
- libncursesw5-dev:armhf
- libreadline-dev:armhf
- libssl-dev:armhf
- linux-libc-dev:armhf
- zlib1g-dev:armhf
-
-matrix:
- include:
- # Build every commit (Allowed Failures):
- - <<: *arm32-linux
- - <<: *arm64-linux
- - <<: *ppc64le-linux
- - <<: *s390x-linux
- allow_failures:
- # The "TestReadline#test_interrupt_in_other_thread" started failing on arm32
- # from https://www.travis-ci.com/github/ruby/ruby/jobs/529005145
- - name: arm32-linux
- # - name: arm64-linux
- # We see "Some worker was crashed." in about 40% of recent ppc64le-linux jobs
- # e.g. https://app.travis-ci.com/github/ruby/ruby/jobs/530959548
- - name: ppc64le-linux
- # - name: s390x-linux
- fast_finish: true
-
-before_script:
- - . tool/ci_functions.sh
- - |-
- if [ -n "${TEST_ALL_SKIPPED_TESTS}" ]; then
- TEST_ALL_OPTS="${TEST_ALL_OPTS} $(ci_to_excluded_test_opts "${TEST_ALL_SKIPPED_TESTS}")"
- if [ -z "${TEST_ALL_SEPARATED_TESTS}" ]; then
- TEST_ALL_SEPARATED_TESTS="${TEST_ALL_SKIPPED_TESTS}"
- fi
- fi
- - |-
- if [ -n "${TEST_ALL_SEPARATED_TESTS}" ]; then
- TEST_ALL_OPTS_SEPARATED="$(ci_to_included_test_opts "${TEST_ALL_SEPARATED_TESTS}")"
- fi
- - echo TEST_ALL_OPTS="${TEST_ALL_OPTS}" TEST_ALL_OPTS_SEPARATED="${TEST_ALL_OPTS_SEPARATED}"
- - rm -fr .ext autom4te.cache
- - |-
- [ -d ~/.downloaded-cache ] ||
- mkdir ~/.downloaded-cache
- - ln -s ~/.downloaded-cache
- - "> config.status"
- - "> .rbconfig.time"
- - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile
- - make -s $JOBS up
- - make -s $JOBS srcs
- - rm -f config.status Makefile rbconfig.rb .rbconfig.time
- - |-
- if [ -d ~/config_2nd ]; then
- cp -pr ~/config_2nd build
- else
- mkdir build
- fi
- - mkdir config_1st config_2nd
- - chmod -R a-w .
- - chmod -R u+w build config_1st config_2nd
- - cd build
- - |-
- case "$CC" in
- gcc*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-diagnostics-color";;
- clang*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-color-diagnostics";;
- esac
- - |-
- [ ! -f config.cache ] ||
- [ "$CC" = "`sed -n s/^ac_cv_prog_CC=//p config.cache`" ] ||
- (set -x; exec rm config.cache)
- - $SETARCH ../configure -C --disable-install-doc --prefix=$RUBY_PREFIX $CONFIG_FLAG
- - cp -pr config.cache config.status .ext/include ../config_1st
- - $SETARCH make reconfig
- - cp -pr config.cache config.status .ext/include ../config_2nd
- - (cd .. && exec diff -ru config_1st config_2nd)
- - chmod u+w ..
- - rm -rf ~/config_2nd
- - mv ../config_2nd ~
- - chmod u-w ..
- - $SETARCH make -s $JOBS
- - make -s install
- - |-
- [ -z "${GEMS_FOR_TEST}" ] ||
- $RUBY_PREFIX/bin/gem install --no-document $GEMS_FOR_TEST
- - echo "raise 'do not load ~/.irbrc in test'" > ~/.irbrc
-
-script:
- - $SETARCH make -s test -o showflags TESTOPTS="${TESTOPTS=$JOBS -q --tty=no}"
- - ../tool/travis_wait.sh $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -q --tty=no ${TEST_ALL_OPTS}" RUBYOPT="-w"
- # Run the failing tests separately returning ok status to check if it works,
- # visualize them.
- - |
- if [ "${RUN_SEPARATED_TESTS}" = true -a -n "${TEST_ALL_OPTS_SEPARATED}" ]; then
- $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -v --tty=no ${TEST_ALL_OPTS_SEPARATED}" RUBYOPT="-w" || :
- fi
- - $SETARCH make -s test-spec MSPECOPT=-ff # not using `-j` because sometimes `mspec -j` silently dies
- - $SETARCH make -s -o showflags leaked-globals
-
-# We enable Travis on the specific branches or forked repositories here.
-if: (repo = ruby/ruby AND (branch = master OR branch =~ /^ruby_\d_\d$/)) OR repo != ruby/ruby
-
-# We want to be notified when something happens.
-notifications:
- irc:
- channels:
- - "chat.freenode.net#ruby-core"
- on_success: change # [always|never|change] # default: always
- on_failure: always # [always|never|change] # default: always
- template:
- - "%{message} by @%{author}: See %{build_url}"
-
- webhooks:
- urls:
- - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk= # ruby-lang slack: ruby/simpler-alerts-bot (travis)
- on_success: never
- on_failure: always
-
- email:
- - jaruga@ruby-lang.org
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c112806acf..13df6087ca 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1 @@
-Please see the [official issue tracker], [doc/contributing.rdoc] and wiki [HowToContribute].
-
-[official issue tracker]: https://bugs.ruby-lang.org
-[doc/contributing.rdoc]: doc/contributing.rdoc
-[HowToContribute]: https://bugs.ruby-lang.org/projects/ruby/wiki/HowToContribute
+See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions.
diff --git a/LEGAL b/LEGAL
index ecd1e16050..0423d57ac9 100644
--- a/LEGAL
+++ b/LEGAL
@@ -343,6 +343,34 @@ mentioned below.
program. This Exception is an additional permission under section 7
of the GNU General Public License, version 3 ("GPLv3").
+[tool/lib/test/*]
+[tool/lib/core_assertions.rb]
+
+ Some of methods on these files are based on MiniTest 4. MiniTest 4 is
+ distributed under the MIT License.
+
+ >>>
+ Copyright (c) Ryan Davis, seattle.rb
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ 'Software'), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
[parse.c]
[parse.h]
@@ -440,7 +468,8 @@ mentioned below.
>>>
A C-program for MT19937, with initialization improved 2002/2/10.::
- Coded by Takuji Nishimura and Makoto Matsumoto.
+ 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.
@@ -532,10 +561,7 @@ mentioned below.
[missing/acosh.c]
[missing/alloca.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]
@@ -943,6 +969,51 @@ mentioned below.
{MIT License}[rdoc-label:label-MIT+License]
+[lib/bundler/vendor/thor]
+
+ Thor is under the following license.
+
+ >>>
+ Copyright (c) 2008 Yehuda Katz, Eric Hodel, et al.
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
+[lib/rubygems/resolver/molinillo]
+
+ molinillo is under the following license.
+
+ >>>
+ Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
+[lib/bundler/vendor/pub_grub]
+
+ pub_grub is under the following license.
+
+ >>>
+ Copyright (c) 2018 John Hawthorn
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
+[lib/bundler/vendor/connection_pool]
+
+ connection_pool is under the following license.
+
+ >>>
+ Copyright (c) 2011 Mike Perham
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
+[lib/bundler/vendor/net-http-persistent]
+
+ net-http-persistent is under the following license.
+
+ >>>
+ Copyright (c) Eric Hodel, Aaron Patterson
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
[lib/did_you_mean]
[lib/did_you_mean.rb]
[test/did_you_mean]
@@ -954,6 +1025,17 @@ mentioned below.
{MIT License}[rdoc-label:label-MIT+License]
+[lib/error_highlight]
+[lib/error_highlight.rb]
+[test/error_highlight]
+
+ error_highlight is under the following license.
+
+ >>>
+ Copyright (c) 2021 Yusuke Endoh
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
[benchmark/so_ackermann.rb]
[benchmark/so_array.rb]
[benchmark/so_binary_trees.rb]
diff --git a/NEWS.md b/NEWS.md
index 783f59ca2b..f6c3c6fc97 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,228 +1,820 @@
-# NEWS for Ruby 3.1.0
+# NEWS for Ruby 3.2.0
-This document is a list of user visible feature changes
-since the **3.0.0** release, except for bug fixes.
+This document is a list of user-visible feature changes
+since the **3.1.0** release, except for bug fixes.
Note that each entry is kept to a minimum, see links for details.
## Language changes
-* Pin operator now takes an expression. [[Feature #17411]]
+* Anonymous rest and keyword rest arguments can now be passed as
+ arguments, instead of just used in method parameters.
+ [[Feature #18351]]
```ruby
- Prime.each_cons(2).lazy.find_all{_1 in [n, ^(n + 2)]}.take(3).to_a
- #=> [[3, 5], [5, 7], [11, 13]]
+ def foo(*)
+ bar(*)
+ end
+ def baz(**)
+ quux(**)
+ end
```
-* Pin operator now supports instance, class, and global variables.
- [[Feature #17724]]
+* A proc that accepts a single positional argument and keywords will
+ no longer autosplat. [[Bug #18633]]
```ruby
- @n = 5
- Prime.each_cons(2).lazy.find{_1 in [n, ^@n]}
- #=> [3, 5]
+ proc{|a, **k| a}.call([1, 2])
+ # Ruby 3.1 and before
+ # => 1
+ # Ruby 3.2 and after
+ # => [1, 2]
```
-* One-line pattern matching is no longer experimental.
+* Constant assignment evaluation order for constants set on explicit
+ objects has been made consistent with single attribute assignment
+ evaluation order. With this code:
-* Multiple assignment evaluation order has been made consistent with
- single assignment evaluation order. With single assignment, Ruby
- uses a left-to-right evaluation order. With this code:
+ ```ruby
+ foo::BAR = baz
+ ```
+
+ `foo` is now called before `baz`. Similarly, for multiple assignments
+ to constants, left-to-right evaluation order is used. With this
+ code:
```ruby
- foo[0] = bar
+ foo1::BAR1, foo2::BAR2 = baz1, baz2
```
- The following evaluation order is used:
+ The following evaluation order is now used:
- 1. `foo`
- 2. `bar`
- 3. `[]=` called on the result of `foo`
+ 1. `foo1`
+ 2. `foo2`
+ 3. `baz1`
+ 4. `baz2`
- In Ruby before 3.1.0, multiple assignment did not follow this
- evaluation order. With this code:
+ [[Bug #15928]]
+
+* "Find pattern" is no longer experimental.
+ [[Feature #18585]]
+
+* Methods taking a rest parameter (like `*args`) and wishing to delegate keyword
+ arguments through `foo(*args)` must now be marked with `ruby2_keywords`
+ (if not already the case). In other words, all methods wishing to delegate
+ keyword arguments through `*args` must now be marked with `ruby2_keywords`,
+ with no exception. This will make it easier to transition to other ways of
+ delegation once a library can require Ruby 3+. Previously, the `ruby2_keywords`
+ flag was kept if the receiving method took `*args`, but this was a bug and an
+ inconsistency. A good technique to find the potentially-missing `ruby2_keywords`
+ is to run the test suite, for where it fails find the last method which must
+ receive keyword arguments, use `puts nil, caller, nil` there, and check each
+ method/block on the call chain which must delegate keywords is correctly marked
+ as `ruby2_keywords`. [[Bug #18625]] [[Bug #16466]]
```ruby
- foo[0], bar.baz = a, b
+ def target(**kw)
+ end
+
+ # Accidentally worked without ruby2_keywords in Ruby 2.7-3.1, ruby2_keywords
+ # needed in 3.2+. Just like (*args, **kwargs) or (...) would be needed on
+ # both #foo and #bar when migrating away from ruby2_keywords.
+ ruby2_keywords def bar(*args)
+ target(*args)
+ end
+
+ ruby2_keywords def foo(*args)
+ bar(*args)
+ end
+
+ foo(k: 1)
```
- Versions of Ruby before 3.1.0 would evaluate in the following
- order
+## Core classes updates
+
+Note: We're only listing outstanding class updates.
+
+* Fiber
+
+ * Introduce Fiber.[] and Fiber.[]= for inheritable fiber storage.
+ Introduce Fiber#storage and Fiber#storage= (experimental) for
+ getting and resetting the current storage. Introduce
+ `Fiber.new(storage:)` for setting the storage when creating a
+ fiber. [[Feature #19078]]
- 1. `a`
- 2. `b`
- 3. `foo`
- 4. `[]=` called on the result of `foo`
- 5. `bar`
- 6. `baz=` called on the result of `bar`
+ Existing Thread and Fiber local variables can be tricky to use.
+ Thread-local variables are shared between all fibers, making it
+ hard to isolate, while Fiber-local variables can be hard to
+ share. It is often desirable to define unit of execution
+ ("execution context") such that some state is shared between all
+ fibers and threads created in that context. This is what Fiber
+ storage provides.
- Starting in Ruby 3.1.0, evaluation order is now consistent with
- single assignment, with the left hand side being evaluated before
- the right hand side:
+ ```ruby
+ def log(message)
+ puts "#{Fiber[:request_id]}: #{message}"
+ end
- 1. `foo`
- 2. `bar`
- 3. `a`
- 4. `b`
- 5. `[]=` called on the result of `foo`
- 6. `baz=` called on the result of `bar`
+ def handle_requests
+ while request = read_request
+ Fiber.schedule do
+ Fiber[:request_id] = SecureRandom.uuid
- [[Bug #4443]]
+ request.messages.each do |message|
+ Fiber.schedule do
+ log("Handling #{message}") # Log includes inherited request_id.
+ end
+ end
+ end
+ end
+ end
+ ```
-## Command line options
+ You should generally consider Fiber storage for any state which
+ you want to be shared implicitly between all fibers and threads
+ created in a given context, e.g. a connection pool, a request
+ id, a logger level, environment variables, configuration, etc.
-## Core classes updates
+* Fiber::Scheduler
+
+ * Introduce `Fiber::Scheduler#io_select` for non-blocking IO.select.
+ [[Feature #19060]]
-Outstanding ones only.
+* IO
-* Array
+ * Introduce IO#timeout= and IO#timeout which can cause
+ IO::TimeoutError to be raised if a blocking operation exceeds the
+ specified timeout. [[Feature #18630]]
- * Array#intersect? is added. [[Feature #15198]]
+ ```ruby
+ STDIN.timeout = 1
+ STDIN.read # => Blocking operation timed out! (IO::TimeoutError)
+ ```
-* Enumerable
+ * Introduce `IO.new(..., path:)` and promote `File#path` to `IO#path`.
+ [[Feature #19036]]
- * Enumerable#compact is added. [[Feature #17312]]
+* Class
- * Enumerable#tally now accepts an optional hash to count. [[Feature #17744]]
+ * Class#attached_object, which returns the object for which
+ the receiver is the singleton class. Raises TypeError if the
+ receiver is not a singleton class.
+ [[Feature #12084]]
-* Enumerator::Lazy
+ ```ruby
+ class Foo; end
- * Enumerator::Lazy#compact is added. [[Feature #17312]]
+ Foo.singleton_class.attached_object #=> Foo
+ Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
+ Foo.attached_object #=> TypeError: `Foo' is not a singleton class
+ nil.singleton_class.attached_object #=> TypeError: `NilClass' is not a singleton class
+ ```
-* File
+* Data
- * File.dirname now accepts an optional argument for the level to
- strip path components. [[Feature #12194]]
+ * New core class to represent simple immutable value object. The class is
+ similar to Struct and partially shares an implementation, but has more
+ lean and strict API. [[Feature #16122]]
+
+ ```ruby
+ Measure = Data.define(:amount, :unit)
+ distance = Measure.new(100, 'km') #=> #<data Measure amount=100, unit="km">
+ weight = Measure.new(amount: 50, unit: 'kg') #=> #<data Measure amount=50, unit="kg">
+ weight.with(amount: 40) #=> #<data Measure amount=40, unit="kg">
+ weight.amount #=> 50
+ weight.amount = 40 #=> NoMethodError: undefined method `amount='
+ ```
+
+* Encoding
+
+ * Encoding#replicate has been deprecated and will be removed in 3.3. [[Feature #18949]]
+ * The dummy `Encoding::UTF_16` and `Encoding::UTF_32` encodings no longer
+ try to dynamically guess the endian based on a byte order mark.
+ Use `Encoding::UTF_16BE`/`UTF_16LE` and `Encoding::UTF_32BE`/`UTF_32LE` instead.
+ This change speeds up getting the encoding of a String. [[Feature #18949]]
+ * Limit maximum encoding set size by 256.
+ If exceeding maximum size, `EncodingError` will be raised. [[Feature #18949]]
+
+* Enumerator
+
+ * Enumerator.product has been added. Enumerator::Product is the implementation. [[Feature #18685]]
+
+* Exception
+
+ * Exception#detailed_message has been added.
+ The default error printer calls this method on the Exception object
+ instead of #message. [[Feature #18564]]
+
+* Hash
+
+ * Hash#shift now always returns nil if the hash is
+ empty, instead of returning the default value or
+ calling the default proc. [[Bug #16908]]
* Integer
- * Integer.try_convert is added. [[Feature #15211]]
+ * Integer#ceildiv has been added. [[Feature #18809]]
+
+* Kernel
+
+ * Kernel#binding raises RuntimeError if called from a non-Ruby frame
+ (such as a method defined in C). [[Bug #18487]]
+
+* MatchData
+
+ * MatchData#byteoffset has been added. [[Feature #13110]]
+ * MatchData#deconstruct has been added. [[Feature #18821]]
+ * MatchData#deconstruct_keys has been added. [[Feature #18821]]
* Module
- * Module#prepend now modifies the ancestor chain if the receiver
- already includes the argument. Module#prepend still does not
- modify the ancestor chain if the receiver has already prepended
- the argument. [[Bug #17423]]
+ * Module.used_refinements has been added. [[Feature #14332]]
+ * Module#refinements has been added. [[Feature #12737]]
+ * Module#const_added has been added. [[Feature #17881]]
+ * Module#undefined_instance_methods has been added. [[Feature #12655]]
-* Struct
+* Proc
- * Passing only keyword arguments to Struct#initialize is warned.
- You need to use a Hash literal to set a Hash to a first member.
- [[Feature #16806]]
+ * Proc#dup returns an instance of subclass. [[Bug #17545]]
+ * Proc#parameters now accepts lambda keyword. [[Feature #15357]]
- * StructClass#keyword_init? is added [[Feature #18008]]
+* Process
+ * Added `RLIMIT_NPTS` constant to FreeBSD platform
+
+* Regexp
+
+ * The cache-based optimization is introduced.
+ Many (but not all) Regexp matching is now in linear time, which
+ will prevent regular expression denial of service (ReDoS)
+ vulnerability. [[Feature #19104]]
+
+ * Regexp.linear_time? is introduced. [[Feature #19194]]
+
+ * Regexp.new now supports passing the regexp flags not only as an Integer,
+ but also as a String. Unknown flags raise ArgumentError.
+ Otherwise, anything other than `true`, `false`, `nil` or Integer will be warned.
+ [[Feature #18788]]
+
+ * Regexp.timeout= has been added. Also, Regexp.new new supports timeout keyword.
+ See [[Feature #17837]]
+
+* Refinement
+
+ * Refinement#refined_class has been added. [[Feature #12737]]
+
+* RubyVM::AbstractSyntaxTree
+
+ * Add `error_tolerant` option for `parse`, `parse_file` and `of`. [[Feature #19013]]
+ With this option
+
+ 1. SyntaxError is suppressed
+ 2. AST is returned for invalid input
+ 3. `end` is complemented when a parser reaches to the end of input but `end` is insufficient
+ 4. `end` is treated as keyword based on indent
+
+ ```ruby
+ # Without error_tolerant option
+ root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY)
+ def m
+ a = 10
+ if
+ end
+ RUBY
+ # => <internal:ast>:33:in `parse': syntax error, unexpected `end' (SyntaxError)
+
+ # With error_tolerant option
+ root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true)
+ def m
+ a = 10
+ if
+ end
+ RUBY
+ p root # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-4:3>
+
+ # `end` is treated as keyword based on indent
+ root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true)
+ module Z
+ class Foo
+ foo.
+ end
+
+ def bar
+ end
+ end
+ RUBY
+ p root.children[-1].children[-1].children[-1].children[-2..-1]
+ # => [#<RubyVM::AbstractSyntaxTree::Node:CLASS@2:2-4:5>, #<RubyVM::AbstractSyntaxTree::Node:DEFN@6:2-7:5>]
+ ```
+
+ * Add `keep_tokens` option for `parse`, `parse_file` and `of`. Add `#tokens` and `#all_tokens`
+ for RubyVM::AbstractSyntaxTree::Node [[Feature #19070]]
+
+ ```ruby
+ root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true)
+ root.tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ root.tokens.map{_1[2]}.join # => "x = 1 + 2"
+ ```
+
+* Set
+
+ * Set is now available as a built-in class without the need for `require "set"`. [[Feature #16989]]
+ It is currently autoloaded via the Set constant or a call to Enumerable#to_set.
+
+* String
+
+ * String#byteindex and String#byterindex have been added. [[Feature #13110]]
+ * Update Unicode to Version 15.0.0 and Emoji Version 15.0. [[Feature #18639]]
+ (also applies to Regexp)
+ * String#bytesplice has been added. [[Feature #18598]]
+ * String#dedup has been added as an alias to String#-@. [[Feature #18595]]
+
+* Struct
-* Queue
+ * A Struct class can also be initialized with keyword arguments
+ without `keyword_init: true` on Struct.new [[Feature #16806]]
- * Queue#initialize now accepts an Enumerable of initial values.
- [[Feature #17327]]
+ ```ruby
+ Post = Struct.new(:id, :name)
+ Post.new(1, "hello") #=> #<struct Post id=1, name="hello">
+ # From Ruby 3.2, the following code also works without keyword_init: true.
+ Post.new(id: 1, name: "hello") #=> #<struct Post id=1, name="hello">
+ ```
* Thread
- * Thread#native_thread_id is added. [[Feature #17853]]
+ * Thread.each_caller_location is added. [[Feature #16663]]
-* Thread::Backtrace
+* Thread::Queue
- * Thread::Backtrace.limit, which returns the value to limit backtrace
- length set by `--backtrace-limit` command line option, is added.
- [[Feature #17479]]
+ * Thread::Queue#pop(timeout: sec) is added. [[Feature #18774]]
-* $LOAD_PATH
+* Thread::SizedQueue
- * $LOAD_PATH.resolve_feature_path does not raise. [[Feature #16043]]
+ * Thread::SizedQueue#pop(timeout: sec) is added. [[Feature #18774]]
+ * Thread::SizedQueue#push(timeout: sec) is added. [[Feature #18944]]
-* Fiber Scheduler
+* Time
- * Add support for `Addrinfo.getaddrinfo` using `address_resolve` hook.
- [[Feature #17370]]
+ * Time#deconstruct_keys is added, allowing to use Time instances
+ in pattern-matching expressions [[Feature #19071]]
- * Introduce non-blocking `Timeout.timeout` using `timeout_after` hook.
- [[Feature #17470]]
+ * Time.new now can parse a string like generated by Time#inspect
+ and return a Time instance based on the given argument.
+ [[Feature #18033]]
- * IO hooks `io_wait`, `io_read`, `io_write`, receive the original IO object
- where possible. [[Bug #18003]]
+* SyntaxError
+ * SyntaxError#path has been added. [[Feature #19138]]
- * Make `Monitor` fiber-safe. [[Bug #17827]]
+* TracePoint
- * Replace copy coroutine with pthread implementation. [[Feature #18015]]
+ * TracePoint#binding now returns `nil` for `c_call`/`c_return` TracePoints.
+ [[Bug #18487]]
+ * TracePoint#enable `target_thread` keyword argument now defaults to the
+ current thread if a block is given and `target` and `target_line` keyword
+ arguments are not passed. [[Bug #16889]]
+
+* UnboundMethod
+
+ * `UnboundMethod#==` returns `true` if the actual method is same. For example,
+ `String.instance_method(:object_id) == Array.instance_method(:object_id)`
+ returns `true`. [[Feature #18798]]
+
+ * `UnboundMethod#inspect` does not show the receiver of `instance_method`.
+ For example `String.instance_method(:object_id).inspect` returns
+ `"#<UnboundMethod: Kernel#object_id()>"`
+ (was `"#<UnboundMethod: String(Kernel)#object_id()>"`).
+
+* GC
+
+ * Expose `need_major_gc` via `GC.latest_gc_info`. [GH-6791]
+
+* ObjectSpace
+
+ * `ObjectSpace.dump_all` dump shapes as well. [GH-6868]
## Stdlib updates
-Outstanding ones only.
+* Bundler
+
+ * Bundler now uses [PubGrub] resolver instead of [Molinillo] for performance improvement.
+ * Add --ext=rust support to bundle gem for creating simple gems with Rust extensions.
+ [[GH-rubygems-6149]]
+ * Make cloning git repos faster [[GH-rubygems-4475]]
+
+* RubyGems
+
+ * Add mswin support for cargo builder. [[GH-rubygems-6167]]
+
+* CGI
+
+ * `CGI.escapeURIComponent` and `CGI.unescapeURIComponent` are added.
+ [[Feature #18822]]
+
+* Coverage
+
+ * `Coverage.setup` now accepts `eval: true`. By this, `eval` and related methods are
+ able to generate code coverage. [[Feature #19008]]
+
+ * `Coverage.supported?(mode)` enables detection of what coverage modes are
+ supported. [[Feature #19026]]
+
+* Date
+
+ * Added `Date#deconstruct_keys` and `DateTime#deconstruct_keys` same as [[Feature #19071]]
+
+* ERB
+
+ * `ERB::Util.html_escape` is made faster than `CGI.escapeHTML`.
+ * It no longer allocates a String object when no character needs to be escaped.
+ * It skips calling `#to_s` method when an argument is already a String.
+ * `ERB::Escape.html_escape` is added as an alias to `ERB::Util.html_escape`,
+ which has not been monkey-patched by Rails.
+ * `ERB::Util.url_encode` is made faster using `CGI.escapeURIComponent`.
+ * `-S` option is removed from `erb` command.
+
+* FileUtils
+
+ * Add FileUtils.ln_sr method and `relative:` option to FileUtils.ln_s.
+ [[Feature #18925]]
+
+* IRB
+
+ * debug.gem integration commands have been added: `debug`, `break`, `catch`,
+ `next`, `delete`, `step`, `continue`, `finish`, `backtrace`, `info`
+ * They work even if you don't have `gem "debug"` in your Gemfile.
+ * See also: [What's new in Ruby 3.2's IRB?](https://st0012.dev/whats-new-in-ruby-3-2-irb)
+ * More Pry-like commands and features have been added.
+ * `edit` and `show_cmds` (like Pry's `help`) are added.
+ * `ls` takes `-g` or `-G` option to filter out outputs.
+ * `show_source` is aliased from `$` and accepts unquoted inputs.
+ * `whereami` is aliased from `@`.
+
+* Net::Protocol
+
+ * Improve `Net::BufferedIO` performance. [[GH-net-protocol-14]]
+
+* Pathname
+
+ * Added `Pathname#lutime`. [[GH-pathname-20]]
+
+* Socket
+
+ * Added the following constants for supported platforms.
+ * `SO_INCOMING_CPU`
+ * `SO_INCOMING_NAPI_ID`
+ * `SO_RTABLE`
+ * `SO_SETFIB`
+ * `SO_USER_COOKIE`
+ * `TCP_KEEPALIVE`
+ * `TCP_CONNECTION_INFO`
+
+* SyntaxSuggest
+
+ * The feature of `syntax_suggest` formerly `dead_end` is integrated in Ruby.
+ [[Feature #18159]]
+
+* UNIXSocket
+
+ * Add support for UNIXSocket on Windows. Emulate anonymous sockets. Add
+ support for File.socket? and File::Stat#socket? where possible.
+ [[Feature #19135]]
+
+* The following default gems are updated.
+
+ * RubyGems 3.4.1
+ * abbrev 0.1.1
+ * benchmark 0.2.1
+ * bigdecimal 3.1.3
+ * bundler 2.4.1
+ * cgi 0.3.6
+ * csv 3.2.6
+ * date 3.3.3
+ * delegate 0.3.0
+ * did_you_mean 1.6.3
+ * digest 3.1.1
+ * drb 2.1.1
+ * english 0.7.2
+ * erb 4.0.2
+ * error_highlight 0.5.1
+ * etc 1.4.2
+ * fcntl 1.0.2
+ * fiddle 1.1.1
+ * fileutils 1.7.0
+ * forwardable 1.3.3
+ * getoptlong 0.2.0
+ * io-console 0.6.0
+ * io-nonblock 0.2.0
+ * io-wait 0.3.0
+ * ipaddr 1.2.5
+ * irb 1.6.2
+ * json 2.6.3
+ * logger 1.5.3
+ * mutex_m 0.1.2
+ * net-http 0.4.0
+ * net-protocol 0.2.1
+ * nkf 0.1.2
+ * open-uri 0.3.0
+ * open3 0.1.2
+ * openssl 3.1.0
+ * optparse 0.3.1
+ * ostruct 0.5.5
+ * pathname 0.2.1
+ * pp 0.4.0
+ * pstore 0.1.2
+ * psych 5.0.1
+ * racc 1.6.2
+ * rdoc 6.5.0
+ * readline-ext 0.1.5
+ * reline 0.3.2
+ * resolv 0.2.2
+ * resolv-replace 0.1.1
+ * securerandom 0.2.2
+ * set 1.0.3
+ * stringio 3.0.4
+ * strscan 3.0.5
+ * syntax_suggest 1.0.2
+ * syslog 0.1.1
+ * tempfile 0.1.3
+ * time 0.2.1
+ * timeout 0.3.1
+ * tmpdir 0.1.3
+ * tsort 0.1.1
+ * un 0.2.1
+ * uri 0.12.0
+ * weakref 0.1.2
+ * win32ole 1.8.9
+ * yaml 0.2.1
+ * zlib 3.0.0
+
+* The following bundled gems are updated.
+
+ * minitest 5.16.3
+ * power_assert 2.0.3
+ * test-unit 3.5.7
+ * net-ftp 0.2.0
+ * net-imap 0.3.4
+ * net-pop 0.1.2
+ * net-smtp 0.3.3
+ * rbs 2.8.2
+ * typeprof 0.21.3
+ * debug 1.7.1
+
+See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems.
+
+## Supported platforms
+
+* WebAssembly/WASI is added. See [wasm/README.md] and [ruby.wasm] for more details. [[Feature #18462]]
## Compatibility issues
-Excluding feature bug fixes.
+* `String#to_c` currently treat a sequence of underscores as an end of Complex
+ string. [[Bug #19087]]
+
+* Now `ENV.clone` raises `TypeError` as well as `ENV.dup` [[Bug #17767]]
+
+### Removed constants
+
+The following deprecated constants are removed.
+
+* `Fixnum` and `Bignum` [[Feature #12005]]
+* `Random::DEFAULT` [[Feature #17351]]
+* `Struct::Group`
+* `Struct::Passwd`
+
+### Removed methods
+
+The following deprecated methods are removed.
+
+* `Dir.exists?` [[Feature #17391]]
+* `File.exists?` [[Feature #17391]]
+* `Kernel#=~` [[Feature #15231]]
+* `Kernel#taint`, `Kernel#untaint`, `Kernel#tainted?`
+ [[Feature #16131]]
+* `Kernel#trust`, `Kernel#untrust`, `Kernel#untrusted?`
+ [[Feature #16131]]
+* `Method#public?`, `Method#private?`, `Method#protected?`,
+ `UnboundMethod#public?`, `UnboundMethod#private?`, `UnboundMethod#protected?`
+ [[Bug #18729]] [[Bug #18751]] [[Bug #18435]]
+
+### Source code incompatibility of extension libraries
-* `rb_io_wait_readable`, `rb_io_wait_writable` and `rb_wait_for_single_fd` are
- deprecated in favour of `rb_io_maybe_wait_readable`,
- `rb_io_maybe_wait_writable` and `rb_io_maybe_wait` respectively.
- `rb_thread_wait_fd` and `rb_thread_fd_writable` are deprecated. [[Bug #18003]]
+* Extension libraries provide PRNG, subclasses of Random, need updates.
+ See [PRNG update] below for more information. [[Bug #19100]]
+
+### Error printer
+
+* Ruby no longer escapes control characters and backslashes in an
+ error message. [[Feature #18367]]
+
+### Constant lookup when defining a class/module
+
+* When defining a class/module directly under the Object class by class/module
+ statement, if there is already a class/module defined by `Module#include`
+ with the same name, the statement was handled as "open class" in Ruby 3.1 or before.
+ Since Ruby 3.2, a new class is defined instead. [[Feature #18832]]
## Stdlib compatibility issues
-* `ERB#initialize` warns `safe_level` and later arguments even without -w.
- [[Feature #14256]]
+* Psych no longer bundles libyaml sources.
+ And also Fiddle no longer bundles libffi sources.
+ Users need to install the libyaml/libffi library themselves via the package
+ manager like apt, yum, brew, etc.
+
+ Psych and fiddle supported the static build with specific version of libyaml
+ and libffi sources. You can build psych with libyaml-0.2.5 like this.
+
+ ```bash
+ $ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5
+ ```
+
+ And you can build fiddle with libffi-3.4.4 like this.
+
+ ```bash
+ $ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4
+ ```
+
+ [[Feature #18571]]
+
+* Check cookie name/path/domain characters in `CGI::Cookie`. [[CVE-2021-33621]]
+
+* `URI.parse` return empty string in host instead of nil. [[sec-156615]]
## C API updates
+### Updated C APIs
+
+The following APIs are updated.
+
+* PRNG update
+
+ `rb_random_interface_t` in ruby/random.h updated and versioned.
+ Extension libraries which use this interface and built for older
+ versions need to rebuild with adding `init_int32` function.
+
+### Added C APIs
+
+* `VALUE rb_hash_new_capa(long capa)` was added to created hashes with the desired capacity.
+* `rb_internal_thread_add_event_hook` and `rb_internal_thread_add_event_hook` were added to instrument threads scheduling.
+ The following events are available:
+ * `RUBY_INTERNAL_THREAD_EVENT_STARTED`
+ * `RUBY_INTERNAL_THREAD_EVENT_READY`
+ * `RUBY_INTERNAL_THREAD_EVENT_RESUMED`
+ * `RUBY_INTERNAL_THREAD_EVENT_SUSPENDED`
+ * `RUBY_INTERNAL_THREAD_EVENT_EXITED`
+* `rb_debug_inspector_current_depth` and `rb_debug_inspector_frame_depth` are added for debuggers.
+
+### Removed C APIs
+
+The following deprecated APIs are removed.
+
+* `rb_cData` variable.
+* "taintedness" and "trustedness" functions. [[Feature #16131]]
+
## Implementation improvements
-### JIT
-
-* The default `--jit-max-cache` is changed from 100 to 10000.
-
-* JIT-ed code is no longer cancelled when a TracePoint for class events
- is enabled.
-
-* The JIT compiler no longer skips compilation of methods longer than
- 1000 instructions.
-
-* `--jit-verbose` and `--jit-warning` output "JIT cancel" when JIT-ed
- code is disabled because TracePoint or GC.compact is used.
-
-* `RubyVM::MJIT` is renamed to `RubyVM::JIT`. [[Feature #17490]]
-
-## Static analysis
-
-### RBS
-
-### TypeProf
-
-## Miscellaneous changes
-
-* lib/objspace/trace.rb is added, which is a tool for tracing the object
- allocation. Just by requiring this file, tracing is started *immediately*.
- Just by `Kernel#p`, you can investigate where an object was created.
- Note that just requiring this file brings a large performance overhead.
- This is only for debugging purpose. Do not use this in production.
- [[Feature #17762]]
-
-* Now exceptions raised in finalizers will be printed to `STDERR`, unless
- `$VERBOSE` is `nil`. [[Feature #17798]]
-
-[Bug #4443]: https://bugs.ruby-lang.org/issues/4443
-[Feature #12194]: https://bugs.ruby-lang.org/issues/12194
-[Feature #14256]: https://bugs.ruby-lang.org/issues/14256
-[Feature #15198]: https://bugs.ruby-lang.org/issues/15198
-[Feature #15211]: https://bugs.ruby-lang.org/issues/15211
-[Feature #16043]: https://bugs.ruby-lang.org/issues/16043
-[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
-[Feature #17312]: https://bugs.ruby-lang.org/issues/17312
-[Feature #17327]: https://bugs.ruby-lang.org/issues/17327
-[Feature #17411]: https://bugs.ruby-lang.org/issues/17411
-[Bug #17423]: https://bugs.ruby-lang.org/issues/17423
-[Feature #17479]: https://bugs.ruby-lang.org/issues/17479
-[Feature #17490]: https://bugs.ruby-lang.org/issues/17490
-[Feature #17724]: https://bugs.ruby-lang.org/issues/17724
-[Feature #17744]: https://bugs.ruby-lang.org/issues/17744
-[Feature #17762]: https://bugs.ruby-lang.org/issues/17762
-[Feature #17798]: https://bugs.ruby-lang.org/issues/17798
-[Bug #18003]: https://bugs.ruby-lang.org/issues/18003
-[Feature #17370]: https://bugs.ruby-lang.org/issues/17370
-[Feature #17470]: https://bugs.ruby-lang.org/issues/17470
-[Feature #17853]: https://bugs.ruby-lang.org/issues/17853
-[Bug #17827]: https://bugs.ruby-lang.org/issues/17827
-[Feature #18008]: https://bugs.ruby-lang.org/issues/18008
-[Feature #18015]: https://bugs.ruby-lang.org/issues/18015
+* Fixed several race conditions in Kernel#autoload. [[Bug #18782]]
+* Cache invalidation for expressions referencing constants is now
+ more fine-grained. `RubyVM.stat(:global_constant_state)` was
+ removed because it was closely tied to the previous caching scheme
+ where setting any constant invalidates all caches in the system.
+ New keys, `:constant_cache_invalidations` and `:constant_cache_misses`,
+ were introduced to help with use cases for `:global_constant_state`.
+ [[Feature #18589]]
+* The cache-based optimization for Regexp matching is introduced.
+ [[Feature #19104]]
+* [Variable Width Allocation](https://shopify.engineering/ruby-variable-width-allocation)
+ is now enabled by default. [[Feature #18239]]
+* Added a new instance variable caching mechanism, called object shapes, which
+ improves inline cache hits for most objects and allows us to generate very
+ efficient JIT code. Objects whose instance variables are defined in a
+ consistent order will see the most performance benefits.
+ [[Feature #18776]]
+* Speed up marking instruction sequences by using a bitmap to find "markable"
+ objects. This change results in faster major collections.
+ [[Feature #18875]]
+
+## JIT
+
+### YJIT
+
+* YJIT is no longer experimental
+ * Has been tested on production workloads for over a year and proven to be quite stable.
+* YJIT now supports both x86-64 and arm64/aarch64 CPUs on Linux, MacOS, BSD and other UNIX platforms.
+ * This release brings support for Mac M1/M2, AWS Graviton and Raspberry Pi 4.
+* Building YJIT now requires Rust 1.58.0+. [[Feature #18481]]
+ * In order to ensure that CRuby is built with YJIT, please install `rustc` >= 1.58.0
+ before running `./configure`
+ * Please reach out to the YJIT team should you run into any issues.
+* Physical memory for JIT code is lazily allocated. Unlike Ruby 3.1,
+ the RSS of a Ruby process is minimized because virtual memory pages
+ allocated by `--yjit-exec-mem-size` will not be mapped to physical
+ memory pages until actually utilized by JIT code.
+* Introduce Code GC that frees all code pages when the memory consumption
+ by JIT code reaches `--yjit-exec-mem-size`.
+ * `RubyVM::YJIT.runtime_stats` returns Code GC metrics in addition to
+ existing `inline_code_size` and `outlined_code_size` keys:
+ `code_gc_count`, `live_page_count`, `freed_page_count`, and `freed_code_size`.
+* Most of the statistics produced by `RubyVM::YJIT.runtime_stats` are now available in release builds.
+ * Simply run ruby with `--yjit-stats` to compute and dump stats (incurs some run-time overhead).
+* YJIT is now optimized to take advantage of object shapes. [[Feature #18776]]
+* Take advantage of finer-grained constant invalidation to invalidate less code when defining new constants. [[Feature #18589]]
+* The default `--yjit-exec-mem-size` is changed to 64 (MiB).
+* The default `--yjit-call-threshold` is changed to 30.
+
+### MJIT
+
+* The MJIT compiler is re-implemented in Ruby as `ruby_vm/mjit/compiler`.
+* MJIT compiler is executed under a forked Ruby process instead of
+ doing it in a native thread called MJIT worker. [[Feature #18968]]
+ * As a result, Microsoft Visual Studio (MSWIN) is no longer supported.
+* MinGW is no longer supported. [[Feature #18824]]
+* Rename `--mjit-min-calls` to `--mjit-call-threshold`.
+* Change default `--mjit-max-cache` back from 10000 to 100.
+
+[Feature #12005]: https://bugs.ruby-lang.org/issues/12005
+[Feature #12084]: https://bugs.ruby-lang.org/issues/12084
+[Feature #12655]: https://bugs.ruby-lang.org/issues/12655
+[Feature #12737]: https://bugs.ruby-lang.org/issues/12737
+[Feature #13110]: https://bugs.ruby-lang.org/issues/13110
+[Feature #14332]: https://bugs.ruby-lang.org/issues/14332
+[Feature #15231]: https://bugs.ruby-lang.org/issues/15231
+[Feature #15357]: https://bugs.ruby-lang.org/issues/15357
+[Bug #15928]: https://bugs.ruby-lang.org/issues/15928
+[Feature #16122]: https://bugs.ruby-lang.org/issues/16122
+[Feature #16131]: https://bugs.ruby-lang.org/issues/16131
+[Bug #16466]: https://bugs.ruby-lang.org/issues/16466
+[Feature #16663]: https://bugs.ruby-lang.org/issues/16663
+[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
+[Bug #16889]: https://bugs.ruby-lang.org/issues/16889
+[Bug #16908]: https://bugs.ruby-lang.org/issues/16908
+[Feature #16989]: https://bugs.ruby-lang.org/issues/16989
+[Feature #17351]: https://bugs.ruby-lang.org/issues/17351
+[Feature #17391]: https://bugs.ruby-lang.org/issues/17391
+[Bug #17545]: https://bugs.ruby-lang.org/issues/17545
+[Bug #17767]: https://bugs.ruby-lang.org/issues/17767
+[Feature #17837]: https://bugs.ruby-lang.org/issues/17837
+[Feature #17881]: https://bugs.ruby-lang.org/issues/17881
+[Feature #18033]: https://bugs.ruby-lang.org/issues/18033
+[Feature #18159]: https://bugs.ruby-lang.org/issues/18159
+[Feature #18239]: https://bugs.ruby-lang.org/issues/18239#note-17
+[Feature #18351]: https://bugs.ruby-lang.org/issues/18351
+[Feature #18367]: https://bugs.ruby-lang.org/issues/18367
+[Bug #18435]: https://bugs.ruby-lang.org/issues/18435
+[Feature #18462]: https://bugs.ruby-lang.org/issues/18462
+[Feature #18481]: https://bugs.ruby-lang.org/issues/18481
+[Bug #18487]: https://bugs.ruby-lang.org/issues/18487
+[Feature #18564]: https://bugs.ruby-lang.org/issues/18564
+[Feature #18571]: https://bugs.ruby-lang.org/issues/18571
+[Feature #18585]: https://bugs.ruby-lang.org/issues/18585
+[Feature #18589]: https://bugs.ruby-lang.org/issues/18589
+[Feature #18595]: https://bugs.ruby-lang.org/issues/18595
+[Feature #18598]: https://bugs.ruby-lang.org/issues/18598
+[Bug #18625]: https://bugs.ruby-lang.org/issues/18625
+[Feature #18630]: https://bugs.ruby-lang.org/issues/18630
+[Bug #18633]: https://bugs.ruby-lang.org/issues/18633
+[Feature #18639]: https://bugs.ruby-lang.org/issues/18639
+[Feature #18685]: https://bugs.ruby-lang.org/issues/18685
+[Bug #18729]: https://bugs.ruby-lang.org/issues/18729
+[Bug #18751]: https://bugs.ruby-lang.org/issues/18751
+[Feature #18774]: https://bugs.ruby-lang.org/issues/18774
+[Feature #18776]: https://bugs.ruby-lang.org/issues/18776
+[Bug #18782]: https://bugs.ruby-lang.org/issues/18782
+[Feature #18788]: https://bugs.ruby-lang.org/issues/18788
+[Feature #18798]: https://bugs.ruby-lang.org/issues/18798
+[Feature #18809]: https://bugs.ruby-lang.org/issues/18809
+[Feature #18821]: https://bugs.ruby-lang.org/issues/18821
+[Feature #18822]: https://bugs.ruby-lang.org/issues/18822
+[Feature #18824]: https://bugs.ruby-lang.org/issues/18824
+[Feature #18832]: https://bugs.ruby-lang.org/issues/18832
+[Feature #18875]: https://bugs.ruby-lang.org/issues/18875
+[Feature #18925]: https://bugs.ruby-lang.org/issues/18925
+[Feature #18944]: https://bugs.ruby-lang.org/issues/18944
+[Feature #18949]: https://bugs.ruby-lang.org/issues/18949
+[Feature #18968]: https://bugs.ruby-lang.org/issues/18968
+[Feature #19008]: https://bugs.ruby-lang.org/issues/19008
+[Feature #19013]: https://bugs.ruby-lang.org/issues/19013
+[Feature #19026]: https://bugs.ruby-lang.org/issues/19026
+[Feature #19036]: https://bugs.ruby-lang.org/issues/19036
+[Feature #19060]: https://bugs.ruby-lang.org/issues/19060
+[Feature #19070]: https://bugs.ruby-lang.org/issues/19070
+[Feature #19071]: https://bugs.ruby-lang.org/issues/19071
+[Feature #19078]: https://bugs.ruby-lang.org/issues/19078
+[Bug #19087]: https://bugs.ruby-lang.org/issues/19087
+[Bug #19100]: https://bugs.ruby-lang.org/issues/19100
+[Feature #19104]: https://bugs.ruby-lang.org/issues/19104
+[Feature #19135]: https://bugs.ruby-lang.org/issues/19135
+[Feature #19138]: https://bugs.ruby-lang.org/issues/19138
+[Feature #19194]: https://bugs.ruby-lang.org/issues/19194
+[Molinillo]: https://github.com/CocoaPods/Molinillo
+[PubGrub]: https://github.com/jhawthorn/pub_grub
+[GH-net-protocol-14]: https://github.com/ruby/net-protocol/pull/14
+[GH-pathname-20]: https://github.com/ruby/pathname/pull/20
+[GH-6791]: https://github.com/ruby/ruby/pull/6791
+[GH-6868]: https://github.com/ruby/ruby/pull/6868
+[GH-rubygems-4475]: https://github.com/rubygems/rubygems/pull/4475
+[GH-rubygems-6149]: https://github.com/rubygems/rubygems/pull/6149
+[GH-rubygems-6167]: https://github.com/rubygems/rubygems/pull/6167
+[sec-156615]: https://hackerone.com/reports/156615
+[CVE-2021-33621]: https://www.ruby-lang.org/en/news/2022/11/22/http-response-splitting-in-cgi-cve-2021-33621/
+[wasm/README.md]: https://github.com/ruby/ruby/blob/master/wasm/README.md
+[ruby.wasm]: https://github.com/ruby/ruby.wasm
diff --git a/README.ja.md b/README.ja.md
index 4516c71459..93c0131690 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -1,10 +1,9 @@
-[![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)
-[![Actions Status: macOS](https://github.com/ruby/ruby/workflows/macOS/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"macOS")
[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
[![Actions Status: MJIT](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT")
[![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
+[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
+[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
# Rubyとは
diff --git a/README.md b/README.md
index 5d225fdfa1..c445448c71 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,11 @@
-[![Actions Status: macOS](https://github.com/ruby/ruby/workflows/macOS/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"macOS")
[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
[![Actions Status: MJIT](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT")
[![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
-[![Travis Status](https://www.travis-ci.com/ruby/ruby.svg?branch=master)](https://www.travis-ci.com/ruby/ruby)
+[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
-# What's Ruby
+# What is Ruby?
Ruby is an interpreted object-oriented programming language often
used for web development. It also offers many scripting features
@@ -15,28 +14,25 @@ It is simple, straightforward, and extensible.
## Features of Ruby
-* Simple Syntax
-* **Normal** Object-oriented Features (e.g. class, method calls)
-* **Advanced** Object-oriented Features (e.g. mix-in, singleton-method)
-* Operator Overloading
-* Exception Handling
-* Iterators and Closures
-* 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, etc.) cf.
- https://github.com/ruby/ruby/blob/master/doc/contributing.rdoc#label-Platform+Maintainers
+* Simple Syntax
+* **Normal** Object-oriented Features (e.g. class, method calls)
+* **Advanced** Object-oriented Features (e.g. mix-in, singleton-method)
+* Operator Overloading
+* Exception Handling
+* Iterators and Closures
+* 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, etc.) cf.
+ https://github.com/ruby/ruby/blob/master/doc/maintainers.rdoc#label-Platform+Maintainers
-
-## How to get Ruby
+## How to get Ruby with Git
For a complete list of ways to install Ruby, including using third-party tools
like rvm, see:
https://www.ruby-lang.org/en/downloads/
-### Git
-
The mirror of the Ruby source tree can be checked out with the following command:
$ git clone https://github.com/ruby/ruby.git
@@ -49,22 +45,19 @@ to see the list of branches:
You may also want to use https://git.ruby-lang.org/ruby.git (actual master of Ruby source)
if you are a committer.
-### Subversion
-
-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
-
-Try the following command to see the list of branches:
-
- $ svn ls https://svn.ruby-lang.org/repos/ruby/branches/
+## How to build
+see [Building Ruby](doc/contributing/building_ruby.md)
## Ruby home page
https://www.ruby-lang.org/
+## Documentation
+
+- [English](https://docs.ruby-lang.org/en/master/index.html)
+- [Japanese](https://docs.ruby-lang.org/ja/master/index.html)
+
## Mailing list
There is a mailing list to discuss Ruby. To subscribe to this list, please
@@ -76,108 +69,20 @@ in the mail body (not subject) to the address [ruby-talk-request@ruby-lang.org].
[ruby-talk-request@ruby-lang.org]: mailto:ruby-talk-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe
-## Requirements to build from repository
-
-1. GNU or BSD make
-2. C99 compiler
-3. autoconf 2.67 or higher
-4. automake 1.15 or higher
-5. bison 2.3 or higher
-6. Ruby 2.2 or higher
-
-When building from a released version, only a C99 compiler and GNU or BSD make
-is required.
-
-## How to compile and install
-
-1. If you want to use Microsoft Visual C++ to compile Ruby, read
- [win32/README.win32](win32/README.win32) instead of this document.
-
-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`.
-
- Some C compiler flags may be added by default depending on your
- environment. Specify `optflags=..` and `warnflags=..` as necessary to
- override them.
-
-4. Edit `include/ruby/defines.h` if you need. Usually this step will not be needed.
-
-5. Optional: Remove comment mark(`#`) before the module names from `ext/Setup`.
-
- This step is only necessary if you want to link modules statically.
-
- If you don't want to compile dynamic extensions (probably on architectures
- which do not allow dynamic loading), remove comment mark from the line
- "`#option nodynamic`" in `ext/Setup`.
-
- Usually this step will not be needed.
-
-6. Run `make`.
-
- * On Mac, set RUBY\_CODESIGN environment variable with a signing identity.
- It uses the identity to sign `ruby` binary. See also codesign(1).
-
-7. Optionally, run '`make check`' to check whether the compiled Ruby
- interpreter works well. If you see the message "`check succeeded`", your
- Ruby works as it should (hopefully).
-
-8. Run '`make install`'.
-
- This command will create the following directories and install files into
- them.
-
- * `${DESTDIR}${prefix}/bin`
- * `${DESTDIR}${prefix}/include/ruby-${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/include/ruby-${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib`
- * `${DESTDIR}${prefix}/lib/ruby`
- * `${DESTDIR}${prefix}/lib/ruby/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/lib/ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib/ruby/site_ruby`
- * `${DESTDIR}${prefix}/lib/ruby/site_ruby/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/lib/ruby/site_ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib/ruby/vendor_ruby`
- * `${DESTDIR}${prefix}/lib/ruby/vendor_ruby/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/lib/ruby/vendor_ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib/ruby/gems/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/share/man/man1`
- * `${DESTDIR}${prefix}/share/ri/${MAJOR}.${MINOR}.${TEENY}/system`
-
-
- If Ruby's API version is '*x.y.z*', the `${MAJOR}` is '*x*', the
- `${MINOR}` is '*y*', and the `${TEENY}` is '*z*'.
-
- **NOTE**: teeny of the API version may be different from one of Ruby's
- program version
-
- You may have to be a super user to install Ruby.
-
-If you fail to compile Ruby, please send the detailed error report with the
-error log and machine/OS type, to help others.
-
-Some extension libraries may not get compiled because of lack of necessary
-external libraries and/or headers, then you will need to run '`make distclean-ext`'
-to remove old configuration after installing them in such case.
-
## Copying
-See the file [COPYING](COPYING).
+See the file [COPYING](rdoc-ref:COPYING).
## Feedback
-Questions about the Ruby language can be asked on the [Ruby-Talk] mailing list
+Questions about the Ruby language can be asked on the [Ruby-Talk](https://www.ruby-lang.org/en/community/mailing-lists) mailing list
or on websites like https://stackoverflow.com.
-Bugs should be reported at https://bugs.ruby-lang.org. Read [HowToReport] for more information.
-
-[Ruby-Talk]: https://www.ruby-lang.org/en/community/mailing-lists
-[HowToReport]: https://bugs.ruby-lang.org/projects/ruby/wiki/HowToReport
+Bugs should be reported at https://bugs.ruby-lang.org. Read ["Reporting Issues"](https://docs.ruby-lang.org/en/master/contributing/reporting_issues_md.html) for more information.
## Contributing
-See the file [CONTRIBUTING.md](CONTRIBUTING.md)
+See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions.
## The Author
diff --git a/addr2line.c b/addr2line.c
index 92c6da5e3b..e5f25293e2 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -159,12 +159,15 @@ typedef struct obj_info {
struct dwarf_section debug_info;
struct dwarf_section debug_line;
struct dwarf_section debug_ranges;
+ struct dwarf_section debug_str_offsets;
+ struct dwarf_section debug_addr;
struct dwarf_section debug_rnglists;
struct dwarf_section debug_str;
+ struct dwarf_section debug_line_str;
struct obj_info *next;
} obj_info_t;
-#define DWARF_SECTION_COUNT 6
+#define DWARF_SECTION_COUNT 9
static struct dwarf_section *
obj_dwarf_section_at(obj_info_t *obj, int n)
@@ -174,8 +177,11 @@ obj_dwarf_section_at(obj_info_t *obj, int n)
&obj->debug_info,
&obj->debug_line,
&obj->debug_ranges,
+ &obj->debug_str_offsets,
+ &obj->debug_addr,
&obj->debug_rnglists,
- &obj->debug_str
+ &obj->debug_str,
+ &obj->debug_line_str
};
if (n < 0 || DWARF_SECTION_COUNT <= n) {
abort();
@@ -248,39 +254,51 @@ get_nth_dirname(unsigned long dir, const char *p)
return p;
}
+static const char *parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t *obj, const char **out_path, uint64_t *out_directory_index);
+
static void
-fill_filename(int file, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj)
+fill_filename(int file, uint8_t format, uint16_t version, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj)
{
int i;
const char *p = filenames;
const char *filename;
unsigned long dir;
- for (i = 1; i <= file; i++) {
- filename = p;
- if (!*p) {
- /* Need to output binary file name? */
- kprintf("Unexpected file number %d in %s at %tx\n",
- file, binary_filename, filenames - obj->mapped);
- return;
- }
- while (*p) p++;
- p++;
- dir = uleb128(&p);
- /* last modified. */
- uleb128(&p);
- /* size of the file. */
- uleb128(&p);
-
- if (i == file) {
- line->filename = filename;
- line->dirname = get_nth_dirname(dir, include_directories);
- }
+ if (version >= 5) {
+ const char *path;
+ uint64_t directory_index = -1;
+ parse_ver5_debug_line_header(filenames, file, format, obj, &path, &directory_index);
+ line->filename = path;
+ parse_ver5_debug_line_header(include_directories, (int)directory_index, format, obj, &path, NULL);
+ line->dirname = path;
+ }
+ else {
+ for (i = 1; i <= file; i++) {
+ filename = p;
+ if (!*p) {
+ /* Need to output binary file name? */
+ kprintf("Unexpected file number %d in %s at %tx\n",
+ file, binary_filename, filenames - obj->mapped);
+ return;
+ }
+ while (*p) p++;
+ p++;
+ dir = uleb128(&p);
+ /* last modified. */
+ uleb128(&p);
+ /* size of the file. */
+ uleb128(&p);
+
+ if (i == file) {
+ line->filename = filename;
+ line->dirname = get_nth_dirname(dir, include_directories);
+ }
+ }
}
}
static void
fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
- const char *include_directories, const char *filenames,
+ uint8_t format, uint16_t version, const char *include_directories, const char *filenames,
obj_info_t *obj, line_info_t *lines, int offset)
{
int i;
@@ -290,7 +308,7 @@ fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
/* We assume one line code doesn't result >100 bytes of native code.
We may want more reliable way eventually... */
if (addr < a && a < addr + 100) {
- fill_filename(file, include_directories, filenames, &lines[i], obj);
+ fill_filename(file, format, version, include_directories, filenames, &lines[i], obj);
lines[i].line = line;
}
}
@@ -315,7 +333,7 @@ struct LineNumberProgramHeader {
};
static int
-parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
+parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgramHeader *header)
{
const char *p = *pp;
header->unit_length = *(uint32_t *)p;
@@ -332,7 +350,13 @@ parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
header->version = *(uint16_t *)p;
p += sizeof(uint16_t);
- if (header->version > 4) return -1;
+ if (header->version > 5) return -1;
+
+ if (header->version >= 5) {
+ /* address_size = *(uint8_t *)p++; */
+ /* segment_selector_size = *(uint8_t *)p++; */
+ p += 2;
+ }
header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
p += header->format;
@@ -353,20 +377,27 @@ parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
/* header->standard_opcode_lengths = (uint8_t *)p - 1; */
p += header->opcode_base - 1;
- header->include_directories = p;
+ if (header->version >= 5) {
+ header->include_directories = p;
+ p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL);
+ header->filenames = p;
+ }
+ else {
+ header->include_directories = p;
- /* temporary measure for compress-debug-sections */
- if (p >= header->cu_end) return -1;
+ /* temporary measure for compress-debug-sections */
+ if (p >= header->cu_end) return -1;
- /* skip include directories */
- while (*p) {
- p = memchr(p, '\0', header->cu_end - p);
- if (!p) return -1;
- p++;
- }
- p++;
+ /* skip include directories */
+ while (*p) {
+ p = memchr(p, '\0', header->cu_end - p);
+ if (!p) return -1;
+ p++;
+ }
+ p++;
- header->filenames = p;
+ header->filenames = p;
+ }
*pp = header->cu_start;
@@ -392,13 +423,15 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
/* int epilogue_begin = 0; */
/* unsigned int isa = 0; */
- if (parse_debug_line_header(&p, &header))
+ if (parse_debug_line_header(obj, &p, &header))
return -1;
is_stmt = header.default_is_stmt;
#define FILL_LINE() \
do { \
fill_line(num_traces, traces, addr, file, line, \
+ header.format, \
+ header.version, \
header.include_directories, \
header.filenames, \
obj, lines, offset); \
@@ -827,16 +860,23 @@ enum {
VAL_cstr = 1,
VAL_data = 2,
VAL_uint = 3,
- VAL_int = 4
+ VAL_int = 4,
+ VAL_addr = 5
};
# define ABBREV_TABLE_SIZE 256
typedef struct {
obj_info_t *obj;
const char *file;
+ uint8_t current_version;
const char *current_cu;
uint64_t current_low_pc;
+ uint64_t current_str_offsets_base;
+ uint64_t current_addr_base;
+ uint64_t current_rnglists_base;
const char *debug_line_cu_end;
+ uint8_t debug_line_format;
+ uint16_t debug_line_version;
const char *debug_line_files;
const char *debug_line_directories;
const char *p;
@@ -861,6 +901,7 @@ typedef struct {
const char *ptr;
uint64_t uint64;
int64_t int64;
+ uint64_t addr_idx;
} as;
uint64_t off;
uint64_t at;
@@ -869,8 +910,11 @@ typedef struct {
int type;
} DebugInfoValue;
-/* TODO: Big Endian */
+#if defined(WORDS_BIGENDIAN)
+#define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
+#else
#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
+#endif
static uint16_t
get_uint16(const uint8_t *p)
@@ -973,6 +1017,9 @@ debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
reader->pend = obj->debug_info.ptr + obj->debug_info.size;
reader->debug_line_cu_end = obj->debug_line.ptr;
reader->current_low_pc = 0;
+ reader->current_str_offsets_base = 0;
+ reader->current_addr_base = 0;
+ reader->current_rnglists_base = 0;
}
static void
@@ -1017,10 +1064,12 @@ di_read_debug_line_cu(DebugInfoReader *reader)
struct LineNumberProgramHeader header;
p = (const char *)reader->debug_line_cu_end;
- if (parse_debug_line_header(&p, &header))
+ if (parse_debug_line_header(reader->obj, &p, &header))
return -1;
reader->debug_line_cu_end = (char *)header.cu_end;
+ reader->debug_line_format = header.format;
+ reader->debug_line_version = header.version;
reader->debug_line_directories = (char *)header.include_directories;
reader->debug_line_files = (char *)header.filenames;
@@ -1028,6 +1077,13 @@ di_read_debug_line_cu(DebugInfoReader *reader)
}
static void
+set_addr_idx_value(DebugInfoValue *v, uint64_t n)
+{
+ v->as.addr_idx = n;
+ v->type = VAL_addr;
+}
+
+static void
set_uint_value(DebugInfoValue *v, uint64_t n)
{
v->as.uint64 = n;
@@ -1074,19 +1130,39 @@ get_cstr_value(DebugInfoValue *v)
}
}
+static const char *
+resolve_strx(DebugInfoReader *reader, uint64_t idx)
+{
+ const char *p = reader->obj->debug_str_offsets.ptr + reader->current_str_offsets_base;
+ uint64_t off;
+ if (reader->format == 4) {
+ off = ((uint32_t *)p)[idx];
+ }
+ else {
+ off = ((uint64_t *)p)[idx];
+ }
+ return reader->obj->debug_str.ptr + off;
+}
+
+static void
+debug_info_reader_read_addr_value(DebugInfoReader *reader, DebugInfoValue *v)
+{
+ if (reader->address_size == 4) {
+ set_uint_value(v, read_uint32(&reader->p));
+ } else if (reader->address_size == 8) {
+ set_uint_value(v, read_uint64(&reader->p));
+ } else {
+ fprintf(stderr,"unknown address_size:%d", reader->address_size);
+ abort();
+ }
+}
+
static void
debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v)
{
switch (form) {
case DW_FORM_addr:
- if (reader->address_size == 4) {
- set_uint_value(v, read_uint32(&reader->p));
- } else if (reader->address_size == 8) {
- set_uint_value(v, read_uint64(&reader->p));
- } else {
- fprintf(stderr,"unknown address_size:%d", reader->address_size);
- abort();
- }
+ debug_info_reader_read_addr_value(reader, v);
break;
case DW_FORM_block2:
v->size = read_uint16(&reader->p);
@@ -1138,13 +1214,19 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
set_uint_value(v, read_uleb128(reader));
break;
case DW_FORM_ref_addr:
- if (reader->format == 4) {
- set_uint_value(v, read_uint32(&reader->p));
- } else if (reader->format == 8) {
- set_uint_value(v, read_uint64(&reader->p));
+ if (reader->current_version <= 2) {
+ // DWARF Version 2 specifies that references have
+ // the same size as an address on the target system
+ debug_info_reader_read_addr_value(reader, v);
} else {
- fprintf(stderr,"unknown format:%d", reader->format);
- abort();
+ if (reader->format == 4) {
+ set_uint_value(v, read_uint32(&reader->p));
+ } else if (reader->format == 8) {
+ set_uint_value(v, read_uint64(&reader->p));
+ } else {
+ fprintf(stderr,"unknown format:%d", reader->format);
+ abort();
+ }
}
break;
case DW_FORM_ref1:
@@ -1186,11 +1268,10 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
set_uint_value(v, 1);
break;
case DW_FORM_strx:
- set_uint_value(v, uleb128(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, uleb128(&reader->p)));
break;
case DW_FORM_addrx:
- /* TODO: read .debug_addr */
- set_uint_value(v, uleb128(&reader->p));
+ set_addr_idx_value(v, uleb128(&reader->p));
break;
case DW_FORM_ref_sup4:
set_uint_value(v, read_uint32(&reader->p));
@@ -1205,8 +1286,7 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
reader->p += v->size;
break;
case DW_FORM_line_strp:
- set_uint_value(v, read_uint(reader));
- /* *p = reader->file + reader->line->sh_offset + ret; */
+ set_cstrp_value(v, reader->obj->debug_line_str.ptr, read_uint(reader));
break;
case DW_FORM_ref_sig8:
set_uint_value(v, read_uint64(&reader->p));
@@ -1224,28 +1304,28 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
set_uint_value(v, read_uint64(&reader->p));
break;
case DW_FORM_strx1:
- set_uint_value(v, read_uint8(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint8(&reader->p)));
break;
case DW_FORM_strx2:
- set_uint_value(v, read_uint16(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint16(&reader->p)));
break;
case DW_FORM_strx3:
- set_uint_value(v, read_uint24(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint24(&reader->p)));
break;
case DW_FORM_strx4:
- set_uint_value(v, read_uint32(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint32(&reader->p)));
break;
case DW_FORM_addrx1:
- set_uint_value(v, read_uint8(&reader->p));
+ set_addr_idx_value(v, read_uint8(&reader->p));
break;
case DW_FORM_addrx2:
- set_uint_value(v, read_uint16(&reader->p));
+ set_addr_idx_value(v, read_uint16(&reader->p));
break;
case DW_FORM_addrx3:
- set_uint_value(v, read_uint24(&reader->p));
+ set_addr_idx_value(v, read_uint24(&reader->p));
break;
case DW_FORM_addrx4:
- set_uint_value(v, read_uint32(&reader->p));
+ set_addr_idx_value(v, read_uint32(&reader->p));
break;
case 0:
goto fail;
@@ -1292,7 +1372,7 @@ hexdump0(const unsigned char *p, size_t n)
for (i=0; i < n; i++){
switch (i & 15) {
case 0:
- fprintf(stderr, "%02zd: %02X ", i/16, p[i]);
+ fprintf(stderr, "%02" PRIdSIZE ": %02X ", i/16, p[i]);
break;
case 15:
fprintf(stderr, "%02X\n", p[i]);
@@ -1313,16 +1393,16 @@ div_inspect(DebugInfoValue *v)
{
switch (v->type) {
case VAL_uint:
- fprintf(stderr,"%d: type:%d size:%zx v:%"PRIx64"\n",__LINE__,v->type,v->size,v->as.uint64);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:%"PRIx64"\n",__LINE__,v->type,v->size,v->as.uint64);
break;
case VAL_int:
- fprintf(stderr,"%d: type:%d size:%zx v:%"PRId64"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:%"PRId64"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
break;
case VAL_cstr:
- fprintf(stderr,"%d: type:%d size:%zx v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
break;
case VAL_data:
- fprintf(stderr,"%d: type:%d size:%zx v:\n",__LINE__,v->type,v->size);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:\n",__LINE__,v->type,v->size);
hexdump(v->as.ptr, 16);
break;
}
@@ -1373,6 +1453,76 @@ di_skip_records(DebugInfoReader *reader)
}
}
+typedef struct addr_header {
+ const char *ptr;
+ uint64_t unit_length;
+ uint8_t format;
+ uint8_t address_size;
+ /* uint8_t segment_selector_size; */
+} addr_header_t;
+
+static void
+addr_header_init(obj_info_t *obj, addr_header_t *header) {
+ const char *p = obj->debug_addr.ptr;
+
+ header->ptr = p;
+
+ if (!p) return;
+
+ header->unit_length = *(uint32_t *)p;
+ p += sizeof(uint32_t);
+
+ header->format = 4;
+ if (header->unit_length == 0xffffffff) {
+ header->unit_length = *(uint64_t *)p;
+ p += sizeof(uint64_t);
+ header->format = 8;
+ }
+
+ p += 2; /* version */
+ header->address_size = *p++;
+ p++; /* segment_selector_size */
+}
+
+static uint64_t
+read_addr(addr_header_t *header, uint64_t addr_base, uint64_t idx) {
+ if (header->address_size == 4) {
+ return ((uint32_t*)(header->ptr + addr_base))[idx];
+ }
+ else {
+ return ((uint64_t*)(header->ptr + addr_base))[idx];
+ }
+}
+
+typedef struct rnglists_header {
+ uint64_t unit_length;
+ uint8_t format;
+ uint8_t address_size;
+ uint32_t offset_entry_count;
+} rnglists_header_t;
+
+static void
+rnglists_header_init(obj_info_t *obj, rnglists_header_t *header) {
+ const char *p = obj->debug_rnglists.ptr;
+
+ if (!p) return;
+
+ header->unit_length = *(uint32_t *)p;
+ p += sizeof(uint32_t);
+
+ header->format = 4;
+ if (header->unit_length == 0xffffffff) {
+ header->unit_length = *(uint64_t *)p;
+ p += sizeof(uint64_t);
+ header->format = 8;
+ }
+
+ p += 2; /* version */
+ header->address_size = *p++;
+ p++; /* segment_selector_size */
+ header->offset_entry_count = *(uint32_t *)p;
+}
+
typedef struct {
uint64_t low_pc;
uint64_t high_pc;
@@ -1383,24 +1533,31 @@ typedef struct {
} ranges_t;
static void
-ranges_set(ranges_t *ptr, DebugInfoValue *v)
+ranges_set(ranges_t *ptr, DebugInfoValue *v, addr_header_t *addr_header, uint64_t addr_base)
{
+ uint64_t n = 0;
+ if (v->type == VAL_uint) {
+ n = v->as.uint64;
+ }
+ else if (v->type == VAL_addr) {
+ n = read_addr(addr_header, addr_base, v->as.addr_idx);
+ }
switch (v->at) {
case DW_AT_low_pc:
- ptr->low_pc = v->as.uint64;
+ ptr->low_pc = n;
ptr->low_pc_set = true;
break;
case DW_AT_high_pc:
if (v->form == DW_FORM_addr) {
- ptr->high_pc = v->as.uint64;
+ ptr->high_pc = n;
}
else {
- ptr->high_pc = ptr->low_pc + v->as.uint64;
+ ptr->high_pc = ptr->low_pc + n;
}
ptr->high_pc_set = true;
break;
case DW_AT_ranges:
- ptr->ranges = v->as.uint64;
+ ptr->ranges = n;
ptr->ranges_set = true;
break;
}
@@ -1410,10 +1567,10 @@ static uint64_t
read_dw_form_addr(DebugInfoReader *reader, const char **ptr)
{
const char *p = *ptr;
- *ptr = p + reader->format;
- if (reader->format == 4) {
+ *ptr = p + reader->address_size;
+ if (reader->address_size == 4) {
return read_uint32(&p);
- } else if (reader->format == 8) {
+ } else if (reader->address_size == 8) {
return read_uint64(&p);
} else {
fprintf(stderr,"unknown address_size:%d", reader->address_size);
@@ -1422,7 +1579,7 @@ read_dw_form_addr(DebugInfoReader *reader, const char **ptr)
}
static uintptr_t
-ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
+ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header)
{
if (ptr->high_pc_set) {
if (ptr->ranges_set || !ptr->low_pc_set) {
@@ -1436,16 +1593,30 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
/* TODO: support base address selection entry */
const char *p;
uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
- if (reader->obj->debug_rnglists.ptr) {
- p = reader->obj->debug_rnglists.ptr + ptr->ranges;
+ bool base_valid = true;
+ if (reader->current_version >= 5) {
+ if (rnglists_header->offset_entry_count == 0) {
+ // DW_FORM_sec_offset
+ p = reader->obj->debug_rnglists.ptr + ptr->ranges + reader->current_rnglists_base;
+ }
+ else {
+ // DW_FORM_rnglistx
+ const char *offset_array = reader->obj->debug_rnglists.ptr + reader->current_rnglists_base;
+ if (rnglists_header->format == 4) {
+ p = offset_array + ((uint32_t *)offset_array)[ptr->ranges];
+ }
+ else {
+ p = offset_array + ((uint64_t *)offset_array)[ptr->ranges];
+ }
+ }
for (;;) {
uint8_t rle = read_uint8(&p);
- uintptr_t base_address = 0;
- uintptr_t from, to;
+ uintptr_t from = 0, to = 0;
if (rle == DW_RLE_end_of_list) break;
switch (rle) {
case DW_RLE_base_addressx:
uleb128(&p);
+ base_valid = false; /* not supported yet */
break;
case DW_RLE_startx_endx:
uleb128(&p);
@@ -1456,24 +1627,26 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
uleb128(&p);
break;
case DW_RLE_offset_pair:
- from = base_address + uleb128(&p);
- to = base_address + uleb128(&p);
- if (base + from <= addr && addr < base + to) {
- return from;
- }
+ if (!base_valid) break;
+ from = (uintptr_t)base + uleb128(&p);
+ to = (uintptr_t)base + uleb128(&p);
break;
case DW_RLE_base_address:
- base_address = (uintptr_t)read_dw_form_addr(reader, &p);
+ base = read_dw_form_addr(reader, &p);
+ base_valid = true;
break;
case DW_RLE_start_end:
- read_dw_form_addr(reader, &p);
- read_dw_form_addr(reader, &p);
+ from = (uintptr_t)read_dw_form_addr(reader, &p);
+ to = (uintptr_t)read_dw_form_addr(reader, &p);
break;
case DW_RLE_start_length:
- read_dw_form_addr(reader, &p);
- uleb128(&p);
+ from = (uintptr_t)read_dw_form_addr(reader, &p);
+ to = from + uleb128(&p);
break;
}
+ if (from <= addr && addr < to) {
+ return from;
+ }
}
return false;
}
@@ -1487,7 +1660,7 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
base = to;
}
else if (base + from <= addr && addr < base + to) {
- return from;
+ return (uintptr_t)base + from;
}
}
}
@@ -1545,6 +1718,7 @@ di_read_cu(DebugInfoReader *reader)
}
reader->cu_end = reader->p + unit_length;
version = read_uint16(&reader->p);
+ reader->current_version = version;
if (version > 5) {
return -1;
}
@@ -1577,16 +1751,45 @@ di_read_cu(DebugInfoReader *reader)
break;
}
+ reader->current_str_offsets_base = 0;
+ reader->current_addr_base = 0;
+ reader->current_rnglists_base = 0;
+
+ DebugInfoValue low_pc = {{}};
/* enumerate abbrev */
for (;;) {
DebugInfoValue v = {{}};
if (!di_read_record(reader, &v)) break;
switch (v.at) {
case DW_AT_low_pc:
- reader->current_low_pc = v.as.uint64;
+ // clang may output DW_AT_addr_base after DW_AT_low_pc.
+ // We need to resolve the DW_FORM_addr* after DW_AT_addr_base is parsed.
+ low_pc = v;
+ break;
+ case DW_AT_str_offsets_base:
+ reader->current_str_offsets_base = v.as.uint64;
+ break;
+ case DW_AT_addr_base:
+ reader->current_addr_base = v.as.uint64;
+ break;
+ case DW_AT_rnglists_base:
+ reader->current_rnglists_base = v.as.uint64;
break;
}
}
+ // Resolve the DW_FORM_addr of DW_AT_low_pc
+ switch (low_pc.type) {
+ case VAL_uint:
+ reader->current_low_pc = low_pc.as.uint64;
+ break;
+ case VAL_addr:
+ {
+ addr_header_t header;
+ addr_header_init(reader->obj, &header);
+ reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx);
+ }
+ break;
+ }
} while (0);
#endif
return 0;
@@ -1640,6 +1843,13 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o
static void
debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
line_info_t *lines, int offset) {
+
+ addr_header_t addr_header = {};
+ addr_header_init(reader->obj, &addr_header);
+
+ rnglists_header_t rnglists_header = {};
+ rnglists_header_init(reader->obj, &rnglists_header);
+
while (reader->p < reader->cu_end) {
DIE die;
ranges_t ranges = {};
@@ -1666,7 +1876,7 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
line.sname = get_cstr_value(&v);
break;
case DW_AT_call_file:
- fill_filename((int)v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
+ fill_filename((int)v.as.uint64, reader->debug_line_format, reader->debug_line_version, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
break;
case DW_AT_call_line:
line.line = (int)v.as.uint64;
@@ -1674,7 +1884,7 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
case DW_AT_low_pc:
case DW_AT_high_pc:
case DW_AT_ranges:
- ranges_set(&ranges, &v);
+ ranges_set(&ranges, &v, &addr_header, reader->current_addr_base);
break;
case DW_AT_declaration:
goto skip_die;
@@ -1691,9 +1901,9 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
for (int i=offset; i < num_traces; i++) {
uintptr_t addr = (uintptr_t)traces[i];
uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
- uintptr_t saddr = ranges_include(reader, &ranges, offset);
+ uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header);
if (saddr) {
- /* fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
+ /* fprintf(stdout, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
if (lines[i].sname) {
line_info_t *lp = malloc(sizeof(line_info_t));
memcpy(lp, &lines[i], sizeof(line_info_t));
@@ -1712,6 +1922,54 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
}
}
+// This function parses the following attributes of Line Number Program Header in DWARF 5:
+//
+// * directory_entry_format_count
+// * directory_entry_format
+// * directories_count
+// * directories
+//
+// or
+//
+// * file_name_entry_format_count
+// * file_name_entry_format
+// * file_names_count
+// * file_names
+//
+// It records DW_LNCT_path and DW_LNCT_directory_index at the index "idx".
+static const char *
+parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t *obj, const char **out_path, uint64_t *out_directory_index) {
+ int i, j;
+ int entry_format_count = *(uint8_t *)p++;
+ const char *entry_format = p;
+
+ /* skip the part of entry_format */
+ for (i = 0; i < entry_format_count * 2; i++) uleb128(&p);
+
+ int entry_count = (int)uleb128(&p);
+
+ DebugInfoReader reader;
+ debug_info_reader_init(&reader, obj);
+ reader.format = format;
+ reader.p = p;
+ for (j = 0; j < entry_count; j++) {
+ const char *format = entry_format;
+ for (i = 0; i < entry_format_count; i++) {
+ DebugInfoValue v = {{}};
+ unsigned long dw_lnct = uleb128(&format);
+ unsigned long dw_form = uleb128(&format);
+ debug_info_reader_read_value(&reader, dw_form, &v);
+ if (dw_lnct == 1 /* DW_LNCT_path */ && v.type == VAL_cstr && out_path)
+ *out_path = v.as.ptr + v.off;
+ if (dw_lnct == 2 /* DW_LNCT_directory_index */ && v.type == VAL_uint && out_directory_index)
+ *out_directory_index = v.as.uint64;
+ }
+ if (j == idx) return 0;
+ }
+
+ return reader.p;
+}
+
#ifdef USE_ELF
static unsigned long
uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
@@ -1840,8 +2098,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
".debug_info",
".debug_line",
".debug_ranges",
+ ".debug_str_offsets",
+ ".debug_addr",
".debug_rnglists",
- ".debug_str"
+ ".debug_str",
+ ".debug_line_str"
};
for (j=0; j < DWARF_SECTION_COUNT; j++) {
@@ -2097,8 +2358,11 @@ found_mach_header:
"__debug_info",
"__debug_line",
"__debug_ranges",
+ "__debug_str_offsets",
+ "__debug_addr",
"__debug_rnglists",
- "__debug_str"
+ "__debug_str",
+ "__debug_line_str",
};
struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd;
if (strcmp(scmd->segname, "__TEXT") == 0) {
@@ -2135,7 +2399,7 @@ found_mach_header:
char *strtab = file + cmd->stroff, *sname = 0;
uint32_t j;
uintptr_t saddr = 0;
- /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, p); */
+ /* kprintf("[%2d]: %x/symtab %p\n", i, cmd->cmd, (void *)p); */
for (j = 0; j < cmd->nsyms; j++) {
uintptr_t symsize, d;
struct LP(nlist) *e = &nl[j];
@@ -2187,7 +2451,7 @@ fail:
#endif
#define HAVE_MAIN_EXE_PATH
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__DragonFly__)
# include <sys/sysctl.h>
#endif
/* ssize_t main_exe_path(void)
@@ -2210,7 +2474,7 @@ main_exe_path(void)
binary_filename[len] = 0;
return len;
}
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
static ssize_t
main_exe_path(void)
{
@@ -2254,9 +2518,12 @@ print_line0(line_info_t *line, void *address)
else if (!line->path) {
kprintf("[0x%"PRIxPTR"]\n", addr);
}
- else if (!line->saddr || !line->sname) {
+ else if (!line->sname) {
kprintf("%s(0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, addr-line->base_addr, addr);
}
+ else if (!line->saddr) {
+ kprintf("%s(%s) [0x%"PRIxPTR"]\n", line->path, line->sname, addr);
+ }
else if (line->line <= 0) {
kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, line->sname,
d, addr);
@@ -2293,6 +2560,7 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces)
obj_info_t *obj = NULL;
/* 2 is NULL + main executable */
void **dladdr_fbases = (void **)calloc(num_traces+2, sizeof(void *));
+
#ifdef HAVE_MAIN_EXE_PATH
char *main_path = NULL; /* used on printing backtrace */
ssize_t len;
@@ -2323,8 +2591,8 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces)
/* if the binary is strip-ed, this may effect */
for (p=dladdr_fbases; *p; p++) {
if (*p == info.dli_fbase) {
- lines[i].path = info.dli_fname;
- lines[i].sname = info.dli_sname;
+ if (info.dli_fname) lines[i].path = info.dli_fname;
+ if (info.dli_sname) lines[i].sname = info.dli_sname;
goto next_line;
}
}
@@ -2334,9 +2602,11 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces)
obj->base_addr = (uintptr_t)info.dli_fbase;
path = info.dli_fname;
obj->path = path;
- lines[i].path = path;
- lines[i].sname = info.dli_sname;
- lines[i].saddr = (uintptr_t)info.dli_saddr;
+ if (path) lines[i].path = path;
+ if (info.dli_sname) {
+ lines[i].sname = info.dli_sname;
+ lines[i].saddr = (uintptr_t)info.dli_saddr;
+ }
strlcpy(binary_filename, path, PATH_MAX);
if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (uintptr_t)-1)
break;
diff --git a/array.c b/array.c
index bd323cd6b0..b76e9a64a3 100644
--- a/array.c
+++ b/array.c
@@ -39,6 +39,37 @@
VALUE rb_cArray;
+/* Flags of RArray
+ *
+ * 1: RARRAY_EMBED_FLAG
+ * The array is embedded (its contents follow the header, rather than
+ * being on a separately allocated buffer).
+ * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
+ * The array is shared. The buffer this array points to is owned by
+ * another array (the shared root).
+ * if USE_RVARGC
+ * 3-9: RARRAY_EMBED_LEN
+ * The length of the array when RARRAY_EMBED_FLAG is set.
+ * else
+ * 3-4: RARRAY_EMBED_LEN
+ * The length of the array when RARRAY_EMBED_FLAG is set.
+ * endif
+ * 12: RARRAY_SHARED_ROOT_FLAG
+ * The array is a shared root that does reference counting. The buffer
+ * this array points to is owned by this array but may be pointed to
+ * by other arrays.
+ * Note: Frozen arrays may be a shared root without this flag being
+ * set. Frozen arrays do not have reference counting because
+ * they cannot be modified. Not updating the reference count
+ * improves copy-on-write performance. Their reference count is
+ * assumed to be infinity.
+ * 13: RARRAY_TRANSIENT_FLAG
+ * The buffer of the array is allocated on the transient heap.
+ * 14: RARRAY_PTR_IN_USE_FLAG
+ * The buffer of the array is in use. This is only used during
+ * debugging.
+ */
+
/* for OPTIMIZED_CMP: */
#define id_cmp idCmp
@@ -53,23 +84,6 @@ 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)
-{
- return !FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG);
-}
-
-#define ARY_SHARED_P(ary) \
- (assert(should_be_T_ARRAY((VALUE)(ary))), \
- assert(should_not_be_shared_and_embedded((VALUE)ary)), \
- FL_TEST_RAW((ary),ELTS_SHARED)!=0)
-
-#define ARY_EMBED_P(ary) \
- (assert(should_be_T_ARRAY((VALUE)(ary))), \
- assert(should_not_be_shared_and_embedded((VALUE)ary)), \
- FL_TEST_RAW((ary), RARRAY_EMBED_FLAG) != 0)
-
#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
#define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
@@ -79,11 +93,11 @@ should_not_be_shared_and_embedded(VALUE ary)
#define ARY_EMBED_LEN(a) \
(assert(ARY_EMBED_P(a)), \
(long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
- (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
+ (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
#define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
#define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
- !FL_TEST_RAW((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
+ !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
#define FL_SET_EMBED(a) do { \
assert(!ARY_SHARED_P(a)); \
@@ -95,9 +109,9 @@ should_not_be_shared_and_embedded(VALUE ary)
#define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
#define FL_SET_SHARED(ary) do { \
assert(!ARY_EMBED_P(ary)); \
- FL_SET((ary), ELTS_SHARED); \
+ FL_SET((ary), RARRAY_SHARED_FLAG); \
} while (0)
-#define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
+#define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
#define ARY_SET_PTR(ary, p) do { \
assert(!ARY_EMBED_P(ary)); \
@@ -107,7 +121,6 @@ should_not_be_shared_and_embedded(VALUE ary)
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = (n); \
assert(ARY_EMBED_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
} while (0)
@@ -139,7 +152,7 @@ should_not_be_shared_and_embedded(VALUE ary)
} \
} while (0)
-#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
+#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
#define ARY_SET_CAPA(ary, n) do { \
assert(!ARY_EMBED_P(ary)); \
@@ -148,26 +161,25 @@ should_not_be_shared_and_embedded(VALUE ary)
RARRAY(ary)->as.heap.aux.capa = (n); \
} while (0)
-#define ARY_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
#define ARY_SET_SHARED(ary, value) do { \
const VALUE _ary_ = (ary); \
const VALUE _value_ = (value); \
assert(!ARY_EMBED_P(_ary_)); \
assert(ARY_SHARED_P(_ary_)); \
- assert(ARY_SHARED_ROOT_P(_value_)); \
+ assert(!OBJ_FROZEN(_ary_)); \
+ assert(ARY_SHARED_ROOT_P(_value_) || OBJ_FROZEN(_value_)); \
RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
} while (0)
-#define RARRAY_SHARED_ROOT_FLAG FL_USER5
-#define ARY_SHARED_ROOT_P(ary) (assert(should_be_T_ARRAY((VALUE)(ary))), \
- FL_TEST_RAW((ary), RARRAY_SHARED_ROOT_FLAG))
-#define ARY_SHARED_ROOT_REFCNT(ary) \
- (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
-#define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
+
+#define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
assert(ARY_SHARED_ROOT_P(ary)); \
+ assert(!OBJ_FROZEN(ary)); \
+ assert((value) >= 0); \
RARRAY(ary)->as.heap.aux.capa = (value); \
} while (0)
#define FL_SET_SHARED_ROOT(ary) do { \
+ assert(!OBJ_FROZEN(ary)); \
assert(!ARY_EMBED_P(ary)); \
assert(!RARRAY_TRANSIENT_P(ary)); \
FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
@@ -183,6 +195,65 @@ ARY_SET(VALUE a, long i, VALUE v)
}
#undef RARRAY_ASET
+static long
+ary_embed_capa(VALUE ary)
+{
+#if USE_RVARGC
+ size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
+ assert(size % sizeof(VALUE) == 0);
+ return size / sizeof(VALUE);
+#else
+ return RARRAY_EMBED_LEN_MAX;
+#endif
+}
+
+static size_t
+ary_embed_size(long capa)
+{
+ return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
+}
+
+static bool
+ary_embeddable_p(long capa)
+{
+#if USE_RVARGC
+ return rb_gc_size_allocatable_p(ary_embed_size(capa));
+#else
+ return capa <= RARRAY_EMBED_LEN_MAX;
+#endif
+}
+
+bool
+rb_ary_embeddable_p(VALUE ary)
+{
+ /* An array cannot be turned embeddable when the array is:
+ * - Shared root: other objects may point to the buffer of this array
+ * so we cannot make it embedded.
+ * - Frozen: this array may also be a shared root without the shared root
+ * flag.
+ * - Shared: we don't want to re-embed an array that points to a shared
+ * root (to save memory).
+ */
+ return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
+}
+
+size_t
+rb_ary_size_as_embedded(VALUE ary)
+{
+ size_t real_size;
+
+ if (ARY_EMBED_P(ary)) {
+ real_size = ary_embed_size(ARY_EMBED_LEN(ary));
+ }
+ else if (rb_ary_embeddable_p(ary)) {
+ real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
+ }
+ else {
+ real_size = sizeof(struct RArray);
+ }
+ return real_size;
+}
+
#if ARRAY_DEBUG
#define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
@@ -192,19 +263,19 @@ ary_verify_(VALUE ary, const char *file, int line)
{
assert(RB_TYPE_P(ary, T_ARRAY));
- if (FL_TEST(ary, ELTS_SHARED)) {
- VALUE root = RARRAY(ary)->as.heap.aux.shared_root;
+ if (ARY_SHARED_P(ary)) {
+ VALUE root = ARY_SHARED_ROOT(ary);
const VALUE *ptr = ARY_HEAP_PTR(ary);
const VALUE *root_ptr = RARRAY_CONST_PTR_TRANSIENT(root);
long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
- assert(FL_TEST(root, RARRAY_SHARED_ROOT_FLAG));
+ assert(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
ary_verify(root);
}
else if (ARY_EMBED_P(ary)) {
assert(!RARRAY_TRANSIENT_P(ary));
assert(!ARY_SHARED_P(ary));
- assert(RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX);
+ assert(RARRAY_LEN(ary) <= ary_embed_capa(ary));
}
else {
#if 1
@@ -260,7 +331,7 @@ void
rb_mem_clear(VALUE *mem, long size)
{
while (size--) {
- *mem++ = Qnil;
+ *mem++ = Qnil;
}
}
@@ -268,7 +339,7 @@ static void
ary_mem_clear(VALUE ary, long beg, long size)
{
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- rb_mem_clear(ptr + beg, size);
+ rb_mem_clear(ptr + beg, size);
});
}
@@ -276,7 +347,7 @@ static inline void
memfill(register VALUE *mem, register long size, register VALUE val)
{
while (size--) {
- *mem++ = val;
+ *mem++ = val;
}
}
@@ -284,8 +355,8 @@ static void
ary_memfill(VALUE ary, long beg, long size, VALUE val)
{
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- memfill(ptr + beg, size, val);
- RB_OBJ_WRITTEN(ary, Qundef, val);
+ memfill(ptr + beg, size, val);
+ RB_OBJ_WRITTEN(ary, Qundef, val);
});
}
@@ -390,14 +461,11 @@ static inline void
rb_ary_transient_heap_evacuate_(VALUE ary, int transient, int promote)
{
if (transient) {
+ assert(!ARY_SHARED_ROOT_P(ary));
+
VALUE *new_ptr;
const VALUE *old_ptr = ARY_HEAP_PTR(ary);
long capa = ARY_HEAP_CAPA(ary);
- long len = ARY_HEAP_LEN(ary);
-
- if (ARY_SHARED_ROOT_P(ary)) {
- capa = len;
- }
assert(ARY_OWNS_HEAP_P(ary));
assert(RARRAY_TRANSIENT_P(ary));
@@ -439,6 +507,27 @@ rb_ary_detransient(VALUE ary)
}
#endif
+void
+rb_ary_make_embedded(VALUE ary)
+{
+ assert(rb_ary_embeddable_p(ary));
+ if (!ARY_EMBED_P(ary)) {
+ const VALUE *buf = ARY_HEAP_PTR(ary);
+ long len = ARY_HEAP_LEN(ary);
+ bool was_transient = RARRAY_TRANSIENT_P(ary);
+
+ // FL_SET_EMBED also unsets the transient flag
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, len);
+
+ MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
+
+ if (!was_transient) {
+ ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
+ }
+ }
+}
+
static void
ary_resize_capa(VALUE ary, long capacity)
{
@@ -446,7 +535,7 @@ ary_resize_capa(VALUE ary, long capacity)
assert(!OBJ_FROZEN(ary));
assert(!ARY_SHARED_P(ary));
- if (capacity > RARRAY_EMBED_LEN_MAX) {
+ if (capacity > ary_embed_capa(ary)) {
size_t new_capa = capacity;
if (ARY_EMBED_P(ary)) {
long len = ARY_EMBED_LEN(ary);
@@ -498,10 +587,10 @@ ary_double_capa(VALUE ary, long min)
long new_capa = ARY_CAPA(ary) / 2;
if (new_capa < ARY_DEFAULT_SIZE) {
- new_capa = ARY_DEFAULT_SIZE;
+ new_capa = ARY_DEFAULT_SIZE;
}
if (new_capa >= ARY_MAX_SIZE - min) {
- new_capa = (ARY_MAX_SIZE - min) / 2;
+ new_capa = (ARY_MAX_SIZE - min) / 2;
}
new_capa += min;
ary_resize_capa(ary, new_capa);
@@ -512,39 +601,40 @@ ary_double_capa(VALUE ary, long min)
static void
rb_ary_decrement_share(VALUE shared_root)
{
- if (shared_root) {
- long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1;
- if (num == 0) {
- rb_ary_free(shared_root);
- rb_gc_force_recycle(shared_root);
- }
- else if (num > 0) {
- ARY_SET_SHARED_ROOT_REFCNT(shared_root, num);
- }
+ if (!OBJ_FROZEN(shared_root)) {
+ long num = ARY_SHARED_ROOT_REFCNT(shared_root);
+ ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
}
}
static void
rb_ary_unshare(VALUE ary)
{
- VALUE shared_root = RARRAY(ary)->as.heap.aux.shared_root;
+ VALUE shared_root = ARY_SHARED_ROOT(ary);
rb_ary_decrement_share(shared_root);
FL_UNSET_SHARED(ary);
}
-static inline void
-rb_ary_unshare_safe(VALUE ary)
+static void
+rb_ary_reset(VALUE ary)
{
- if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
+ if (ARY_OWNS_HEAP_P(ary)) {
+ ary_heap_free(ary);
}
+ else if (ARY_SHARED_P(ary)) {
+ rb_ary_unshare(ary);
+ }
+
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, 0);
}
static VALUE
rb_ary_increment_share(VALUE shared_root)
{
- long num = ARY_SHARED_ROOT_REFCNT(shared_root);
- if (num >= 0) {
+ if (!OBJ_FROZEN(shared_root)) {
+ long num = ARY_SHARED_ROOT_REFCNT(shared_root);
+ assert(num >= 0);
ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
}
return shared_root;
@@ -575,7 +665,7 @@ rb_ary_cancel_sharing(VALUE ary)
ary_verify(shared_root);
- if (len <= RARRAY_EMBED_LEN_MAX) {
+ if (len <= ary_embed_capa(ary)) {
const VALUE *ptr = ARY_HEAP_PTR(ary);
FL_UNSET_SHARED(ary);
FL_SET_EMBED(ary);
@@ -622,40 +712,40 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
long capa;
if (old_len > ARY_MAX_SIZE - add_len) {
- rb_raise(rb_eIndexError, "index %ld too big", new_len);
+ rb_raise(rb_eIndexError, "index %ld too big", new_len);
}
if (ARY_SHARED_P(ary)) {
- if (new_len > RARRAY_EMBED_LEN_MAX) {
+ if (new_len > ary_embed_capa(ary)) {
VALUE shared_root = ARY_SHARED_ROOT(ary);
if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
- rb_ary_modify_check(ary);
+ rb_ary_modify_check(ary);
ary_verify(ary);
ary_verify(shared_root);
return shared_root;
- }
- else {
- /* if array is shared, then it is likely it participate in push/shift pattern */
- rb_ary_modify(ary);
- capa = ARY_CAPA(ary);
- if (new_len > capa - (capa >> 6)) {
- ary_double_capa(ary, new_len);
- }
+ }
+ else {
+ /* if array is shared, then it is likely it participate in push/shift pattern */
+ rb_ary_modify(ary);
+ capa = ARY_CAPA(ary);
+ if (new_len > capa - (capa >> 6)) {
+ ary_double_capa(ary, new_len);
+ }
ary_verify(ary);
- return ary;
- }
- }
- }
+ return ary;
+ }
+ }
+ }
ary_verify(ary);
rb_ary_modify(ary);
}
else {
- rb_ary_modify_check(ary);
+ rb_ary_modify_check(ary);
}
capa = ARY_CAPA(ary);
if (new_len > capa) {
- ary_double_capa(ary, new_len);
+ ary_double_capa(ary, new_len);
}
ary_verify(ary);
@@ -667,6 +757,7 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
* array.freeze -> self
*
* Freezes +self+; returns +self+:
+ *
* a = []
* a.frozen? # => false
* a.freeze
@@ -692,18 +783,25 @@ VALUE
rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
{
if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
- !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
- RARRAY(ary1)->as.heap.aux.shared_root == RARRAY(ary2)->as.heap.aux.shared_root &&
- RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
- return Qtrue;
+ !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
+ ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
+ ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
+ return Qtrue;
}
return Qfalse;
}
static VALUE
-ary_alloc(VALUE klass)
+ary_alloc_embed(VALUE klass, long capa)
{
- NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
+ size_t size = ary_embed_size(capa);
+ assert(rb_gc_size_allocatable_p(size));
+#if !USE_RVARGC
+ assert(size <= sizeof(struct RArray));
+#endif
+ RVARGC_NEWOBJ_OF(ary, struct RArray, klass,
+ T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ size);
/* Created array is:
* FL_SET_EMBED((VALUE)ary);
* ARY_SET_EMBED_LEN((VALUE)ary, 0);
@@ -712,10 +810,19 @@ ary_alloc(VALUE klass)
}
static VALUE
+ary_alloc_heap(VALUE klass)
+{
+ RVARGC_NEWOBJ_OF(ary, struct RArray, klass,
+ T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ sizeof(struct RArray));
+ return (VALUE)ary;
+}
+
+static VALUE
empty_ary_alloc(VALUE klass)
{
RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
- return ary_alloc(klass);
+ return ary_alloc_embed(klass, 0);
}
static VALUE
@@ -724,20 +831,24 @@ ary_new(VALUE klass, long capa)
VALUE ary,*ptr;
if (capa < 0) {
- rb_raise(rb_eArgError, "negative array size (or size too big)");
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
}
if (capa > ARY_MAX_SIZE) {
- rb_raise(rb_eArgError, "array size too big");
+ rb_raise(rb_eArgError, "array size too big");
}
RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
- ary = ary_alloc(klass);
- if (capa > RARRAY_EMBED_LEN_MAX) {
+ if (ary_embeddable_p(capa)) {
+ ary = ary_alloc_embed(klass, capa);
+ }
+ else {
+ ary = ary_alloc_heap(klass);
+ ARY_SET_CAPA(ary, capa);
+ assert(!ARY_EMBED_P(ary));
+
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);
}
@@ -753,7 +864,7 @@ rb_ary_new_capa(long capa)
VALUE
rb_ary_new(void)
{
- return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
+ return rb_ary_new_capa(0);
}
VALUE
@@ -767,7 +878,7 @@ VALUE
va_start(ar, n);
for (i=0; i<n; i++) {
- ARY_SET(ary, i, va_arg(ar, VALUE));
+ ARY_SET(ary, i, va_arg(ar, VALUE));
}
va_end(ar);
@@ -782,8 +893,8 @@ rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
ary = ary_new(klass, n);
if (n > 0 && elts) {
- ary_memcpy(ary, 0, n, elts);
- ARY_SET_LEN(ary, n);
+ ary_memcpy(ary, 0, n, elts);
+ ARY_SET_LEN(ary, n);
}
return ary;
@@ -796,9 +907,16 @@ rb_ary_new_from_values(long n, const VALUE *elts)
}
static VALUE
-ec_ary_alloc(rb_execution_context_t *ec, VALUE klass)
+ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
{
- RB_EC_NEWOBJ_OF(ec, ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
+ size_t size = ary_embed_size(capa);
+ assert(rb_gc_size_allocatable_p(size));
+#if !USE_RVARGC
+ assert(size <= sizeof(struct RArray));
+#endif
+ RB_RVARGC_EC_NEWOBJ_OF(ec, ary, struct RArray, klass,
+ T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ size);
/* Created array is:
* FL_SET_EMBED((VALUE)ary);
* ARY_SET_EMBED_LEN((VALUE)ary, 0);
@@ -807,26 +925,38 @@ ec_ary_alloc(rb_execution_context_t *ec, VALUE klass)
}
static VALUE
+ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
+{
+ RB_RVARGC_EC_NEWOBJ_OF(ec, ary, struct RArray, klass,
+ T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ sizeof(struct RArray));
+ 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)");
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
}
if (capa > ARY_MAX_SIZE) {
- rb_raise(rb_eArgError, "array size too big");
+ rb_raise(rb_eArgError, "array size too big");
}
RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
- ary = ec_ary_alloc(ec, klass);
+ if (ary_embeddable_p(capa)) {
+ ary = ec_ary_alloc_embed(ec, klass, capa);
+ }
+ else {
+ ary = ec_ary_alloc_heap(ec, klass);
+ ARY_SET_CAPA(ary, capa);
+ assert(!ARY_EMBED_P(ary));
- 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);
}
@@ -840,15 +970,15 @@ rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
ary = ec_ary_new(ec, rb_cArray, n);
if (n > 0 && elts) {
- ary_memcpy(ary, 0, n, elts);
- ARY_SET_LEN(ary, n);
+ ary_memcpy(ary, 0, n, elts);
+ ARY_SET_LEN(ary, n);
}
return ary;
}
VALUE
-rb_ary_tmp_new(long capa)
+rb_ary_hidden_new(long capa)
{
VALUE ary = ary_new(0, capa);
rb_ary_transient_heap_evacuate(ary, TRUE);
@@ -856,12 +986,11 @@ rb_ary_tmp_new(long capa)
}
VALUE
-rb_ary_tmp_new_fill(long capa)
+rb_ary_hidden_new_fill(long capa)
{
- VALUE ary = ary_new(0, capa);
+ VALUE ary = rb_ary_hidden_new(capa);
ary_memfill(ary, 0, capa, Qnil);
ARY_SET_LEN(ary, capa);
- rb_ary_transient_heap_evacuate(ary, TRUE);
return ary;
}
@@ -899,64 +1028,69 @@ RUBY_FUNC_EXPORTED size_t
rb_ary_memsize(VALUE ary)
{
if (ARY_OWNS_HEAP_P(ary)) {
- return ARY_CAPA(ary) * sizeof(VALUE);
+ return ARY_CAPA(ary) * sizeof(VALUE);
}
else {
- return 0;
+ return 0;
}
}
-static inline void
-ary_discard(VALUE ary)
-{
- rb_ary_free(ary);
- RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
- RBASIC(ary)->flags &= ~(RARRAY_EMBED_LEN_MASK | RARRAY_TRANSIENT_FLAG);
-}
-
static VALUE
ary_make_shared(VALUE ary)
{
- assert(!ARY_EMBED_P(ary));
+ assert(USE_RVARGC || !ARY_EMBED_P(ary));
ary_verify(ary);
if (ARY_SHARED_P(ary)) {
return ARY_SHARED_ROOT(ary);
}
else if (ARY_SHARED_ROOT_P(ary)) {
- return ary;
+ return ary;
}
else if (OBJ_FROZEN(ary)) {
- rb_ary_transient_heap_evacuate(ary, TRUE);
- ary_shrink_capa(ary);
- FL_SET_SHARED_ROOT(ary);
- ARY_SET_SHARED_ROOT_REFCNT(ary, 1);
- return ary;
+ if (!ARY_EMBED_P(ary)) {
+ rb_ary_transient_heap_evacuate(ary, TRUE);
+ ary_shrink_capa(ary);
+ }
+ return ary;
}
else {
- 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(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);
+
+ long capa = ARY_CAPA(ary);
+ long len = RARRAY_LEN(ary);
+
+ /* Shared roots cannot be embedded because the reference count
+ * (refcnt) is stored in as.heap.aux.capa. */
+ VALUE shared = ary_alloc_heap(0);
+ FL_SET_SHARED_ROOT(shared);
+
+ if (ARY_EMBED_P(ary)) {
+ /* Cannot use ary_heap_alloc because we don't want to allocate
+ * on the transient heap. */
+ VALUE *ptr = ALLOC_N(VALUE, capa);
+ ARY_SET_PTR(shared, ptr);
+ ary_memcpy(shared, 0, len, RARRAY_PTR(ary));
+
+ FL_UNSET_EMBED(ary);
+ ARY_SET_HEAP_LEN(ary, len);
+ ARY_SET_PTR(ary, ptr);
+ }
+ else {
+ ARY_SET_PTR(shared, RARRAY_PTR(ary));
+ }
+
+ ARY_SET_LEN(shared, capa);
+ ary_mem_clear(shared, len, capa - len);
+ ARY_SET_SHARED_ROOT_REFCNT(shared, 1);
+ FL_SET_SHARED(ary);
RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
- ARY_SET_SHARED(ary, vshared);
- OBJ_FREEZE(vshared);
+ ARY_SET_SHARED(ary, shared);
- ary_verify(vshared);
+ ary_verify(shared);
ary_verify(ary);
- return vshared;
+ return shared;
}
}
@@ -965,8 +1099,10 @@ ary_make_substitution(VALUE ary)
{
long len = RARRAY_LEN(ary);
- if (len <= RARRAY_EMBED_LEN_MAX) {
- VALUE subst = rb_ary_new2(len);
+ if (ary_embeddable_p(len)) {
+ VALUE subst = rb_ary_new_capa(len);
+ assert(ARY_EMBED_P(subst));
+
ary_memcpy(subst, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary));
ARY_SET_EMBED_LEN(subst, len);
return subst;
@@ -1027,6 +1163,30 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
return rb_check_array_type(ary);
}
+/* :nodoc: */
+static VALUE
+rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ary;
+
+ if (klass == rb_cArray) {
+ long size = 0;
+ if (argc > 0 && FIXNUM_P(argv[0])) {
+ size = FIX2LONG(argv[0]);
+ if (size < 0) size = 0;
+ }
+
+ ary = ary_new(klass, size);
+
+ rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
+ }
+ else {
+ ary = rb_class_new_instance_pass_kw(argc, argv, klass);
+ }
+
+ return ary;
+}
+
/*
* call-seq:
* Array.new -> new_empty_array
@@ -1041,6 +1201,7 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
*
* 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]
@@ -1048,12 +1209,14 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
* 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']
*
@@ -1061,6 +1224,7 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
* 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"]
*
@@ -1079,51 +1243,48 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary);
if (argc == 0) {
- if (ARY_OWNS_HEAP_P(ary) && ARY_HEAP_PTR(ary) != NULL) {
- ary_heap_free(ary);
- }
- rb_ary_unshare_safe(ary);
- FL_SET_EMBED(ary);
- ARY_SET_EMBED_LEN(ary, 0);
- if (rb_block_given_p()) {
- rb_warning("given block not used");
- }
- return ary;
+ rb_ary_reset(ary);
+ assert(ARY_EMBED_P(ary));
+ assert(ARY_EMBED_LEN(ary) == 0);
+ if (rb_block_given_p()) {
+ rb_warning("given block not used");
+ }
+ return ary;
}
rb_scan_args(argc, argv, "02", &size, &val);
if (argc == 1 && !FIXNUM_P(size)) {
- val = rb_check_array_type(size);
- if (!NIL_P(val)) {
- rb_ary_replace(ary, val);
- return ary;
- }
+ val = rb_check_array_type(size);
+ if (!NIL_P(val)) {
+ rb_ary_replace(ary, val);
+ return ary;
+ }
}
len = NUM2LONG(size);
/* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
if (len < 0) {
- rb_raise(rb_eArgError, "negative array size");
+ rb_raise(rb_eArgError, "negative array size");
}
if (len > ARY_MAX_SIZE) {
- rb_raise(rb_eArgError, "array size too big");
+ rb_raise(rb_eArgError, "array size too big");
}
/* recheck after argument conversion */
rb_ary_modify(ary);
ary_resize_capa(ary, len);
if (rb_block_given_p()) {
- long i;
+ long i;
- if (argc == 2) {
- rb_warn("block supersedes default value argument");
- }
- for (i=0; i<len; i++) {
- rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
- ARY_SET_LEN(ary, i + 1);
- }
+ if (argc == 2) {
+ rb_warn("block supersedes default value argument");
+ }
+ for (i=0; i<len; i++) {
+ rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
+ ARY_SET_LEN(ary, i + 1);
+ }
}
else {
- ary_memfill(ary, 0, len, val);
- ARY_SET_LEN(ary, len);
+ ary_memfill(ary, 0, len, val);
+ ARY_SET_LEN(ary, len);
}
return ary;
}
@@ -1154,26 +1315,26 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
long len = RARRAY_LEN(ary);
if (idx < 0) {
- idx += len;
- if (idx < 0) {
- rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
- idx - len, -len);
- }
+ idx += len;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
+ idx - len, -len);
+ }
}
else if (idx >= ARY_MAX_SIZE) {
- rb_raise(rb_eIndexError, "index %ld too big", idx);
+ rb_raise(rb_eIndexError, "index %ld too big", idx);
}
rb_ary_modify(ary);
if (idx >= ARY_CAPA(ary)) {
- ary_double_capa(ary, idx);
+ ary_double_capa(ary, idx);
}
if (idx > len) {
- ary_mem_clear(ary, len, idx - len + 1);
+ ary_mem_clear(ary, len, idx - len + 1);
}
if (idx >= len) {
- ARY_SET_LEN(ary, idx + 1);
+ ARY_SET_LEN(ary, idx + 1);
}
ARY_SET(ary, idx, val);
}
@@ -1185,17 +1346,20 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
assert(len >= 0);
assert(offset+len <= RARRAY_LEN(ary));
- if (len <= RARRAY_EMBED_LEN_MAX) {
- VALUE result = ary_alloc(klass);
+ const size_t rarray_embed_capa_max = (sizeof(struct RArray) - offsetof(struct RArray, as.ary)) / sizeof(VALUE);
+
+ if ((size_t)len <= rarray_embed_capa_max && ary_embeddable_p(len)) {
+ VALUE result = ary_alloc_embed(klass, len);
ary_memcpy(result, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary) + offset);
ARY_SET_EMBED_LEN(result, len);
return result;
}
else {
- VALUE shared, result = ary_alloc(klass);
- FL_UNSET_EMBED(result);
+ VALUE shared = ary_make_shared(ary);
+
+ VALUE result = ary_alloc_heap(klass);
+ assert(!ARY_EMBED_P(result));
- shared = ary_make_shared(ary);
ARY_SET_PTR(result, RARRAY_CONST_PTR_TRANSIENT(ary));
ARY_SET_LEN(result, RARRAY_LEN(ary));
rb_ary_set_shared(result, shared);
@@ -1220,21 +1384,25 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
const VALUE *values = RARRAY_CONST_PTR_TRANSIENT(ary);
const long orig_len = len;
- if ((step > 0 && step >= len) || (step < 0 && (step < -len))) {
+ if (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;
}
+ else if (step < 0 && step < -len) {
+ step = -len;
+ }
long ustep = (step < 0) ? -step : step;
- len = (len + ustep - 1) / ustep;
+ len = roomof(len, ustep);
long i;
long j = offset + ((step > 0) ? 0 : (orig_len - 1));
+
VALUE result = ary_new(klass, len);
- if (len <= RARRAY_EMBED_LEN_MAX) {
+ if (ARY_EMBED_P(result)) {
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
for (i = 0; i < len; ++i) {
RB_OBJ_WRITE(result, ptr+i, values[j]);
@@ -1283,13 +1451,13 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
n = NUM2LONG(argv[0]);
len = RARRAY_LEN(ary);
if (n > len) {
- n = len;
+ n = len;
}
else if (n < 0) {
- rb_raise(rb_eArgError, "negative array size");
+ rb_raise(rb_eArgError, "negative array size");
}
if (last) {
- offset = len - n;
+ offset = len - n;
}
return ary_make_partial(ary, rb_cArray, offset, n);
}
@@ -1299,13 +1467,16 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
* array << object -> self
*
* 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
@@ -1314,7 +1485,7 @@ rb_ary_push(VALUE ary, VALUE item)
long idx = RARRAY_LEN((ary_verify(ary), ary));
VALUE target_ary = ary_ensure_room_for_push(ary, 1);
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- RB_OBJ_WRITE(target_ary, &ptr[idx], item);
+ RB_OBJ_WRITE(target_ary, &ptr[idx], item);
});
ARY_SET_LEN(ary, idx + 1);
ary_verify(ary);
@@ -1338,15 +1509,17 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len)
* 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.
+ * Array#append is an alias for Array#push.
*
* Related: #pop, #shift, #unshift.
*/
@@ -1365,10 +1538,10 @@ rb_ary_pop(VALUE ary)
n = RARRAY_LEN(ary);
if (n == 0) return Qnil;
if (ARY_OWNS_HEAP_P(ary) &&
- n * 3 < ARY_CAPA(ary) &&
- ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
+ n * 3 < ARY_CAPA(ary) &&
+ ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
{
- ary_resize_capa(ary, n * 2);
+ ary_resize_capa(ary, n * 2);
}
--n;
ARY_SET_LEN(ary, n);
@@ -1385,6 +1558,7 @@ rb_ary_pop(VALUE ary)
*
* 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"]
@@ -1392,12 +1566,14 @@ rb_ary_pop(VALUE ary)
* Returns +nil+ if the array is empty.
*
* When a non-negative \Integer argument +n+ is given and is in range,
+ *
* removes and returns the last +n+ elements in a new \Array:
* a = [:foo, 'bar', 2]
* a.pop(2) # => ["bar", 2]
*
* If +n+ is positive and out of range,
* removes and returns all elements:
+ *
* a = [:foo, 'bar', 2]
* a.pop(50) # => [:foo, "bar", 2]
*
@@ -1410,7 +1586,7 @@ rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
VALUE result;
if (argc == 0) {
- return rb_ary_pop(ary);
+ return rb_ary_pop(ary);
}
rb_ary_modify_check(ary);
@@ -1426,30 +1602,14 @@ rb_ary_shift(VALUE ary)
VALUE top;
long len = RARRAY_LEN(ary);
- rb_ary_modify_check(ary);
- if (len == 0) return Qnil;
- top = RARRAY_AREF(ary, 0);
- if (!ARY_SHARED_P(ary)) {
- if (len < ARY_DEFAULT_SIZE) {
- RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr, ptr+1, VALUE, len-1);
- }); /* WB: no new reference */
- ARY_INCREASE_LEN(ary, -1);
- ary_verify(ary);
- return top;
- }
- assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
-
- ARY_SET(ary, 0, Qnil);
- ary_make_shared(ary);
- }
- else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
- RARRAY_PTR_USE_TRANSIENT(ary, ptr, ptr[0] = Qnil);
+ if (len == 0) {
+ rb_ary_modify_check(ary);
+ return Qnil;
}
- ARY_INCREASE_PTR(ary, 1); /* shift ptr */
- ARY_INCREASE_LEN(ary, -1);
- ary_verify(ary);
+ top = RARRAY_AREF(ary, 0);
+
+ rb_ary_behead(ary, 1);
return top;
}
@@ -1462,6 +1622,7 @@ rb_ary_shift(VALUE ary)
* Removes and returns leading elements.
*
* When no argument is given, removes and returns the first element:
+ *
* a = [:foo, 'bar', 2]
* a.shift # => :foo
* a # => ['bar', 2]
@@ -1470,12 +1631,14 @@ rb_ary_shift(VALUE ary)
*
* When positive \Integer argument +n+ is given, removes the first +n+ elements;
* returns those elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.shift(2) # => [:foo, 'bar']
* a # => [2]
*
* If +n+ is as large as or larger than <tt>self.length</tt>,
* removes all elements; returns those elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.shift(3) # => [:foo, 'bar', 2]
*
@@ -1491,7 +1654,7 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
long n;
if (argc == 0) {
- return rb_ary_shift(ary);
+ return rb_ary_shift(ary);
}
rb_ary_modify_check(ary);
@@ -1502,48 +1665,37 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
return result;
}
-static VALUE
-behead_shared(VALUE ary, long n)
-{
- 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);
- 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) {
+
+ rb_ary_modify_check(ary);
+
+ if (!ARY_SHARED_P(ary)) {
+ if (ARY_EMBED_P(ary) || 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 */
+ ARY_INCREASE_LEN(ary, -n);
+ ary_verify(ary);
+ return ary;
+ }
+
+ ary_mem_clear(ary, 0, n);
ary_make_shared(ary);
- return behead_shared(ary, n);
}
- else {
- return behead_transient(ary, n);
+ else 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
@@ -1574,28 +1726,28 @@ ary_modify_for_unshift(VALUE ary, int argc)
rb_ary_modify(ary);
capa = ARY_CAPA(ary);
if (capa - (capa >> 6) <= new_len) {
- ary_double_capa(ary, new_len);
+ ary_double_capa(ary, new_len);
}
/* use shared array for big "queues" */
- if (new_len > ARY_DEFAULT_SIZE * 4) {
+ if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
ary_verify(ary);
/* make a room for unshifted items */
- capa = ARY_CAPA(ary);
- ary_make_shared(ary);
+ capa = ARY_CAPA(ary);
+ ary_make_shared(ary);
head = sharedp = RARRAY_CONST_PTR_TRANSIENT(ary);
return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
}
else {
- /* sliding items */
+ /* sliding items */
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr + argc, ptr, VALUE, len);
- });
+ MEMMOVE(ptr + argc, ptr, VALUE, len);
+ });
ary_verify(ary);
- return ary;
+ return ary;
}
}
@@ -1636,6 +1788,7 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
* array.unshift(*objects) -> self
*
* Prepends the given +objects+ to +self+:
+ *
* a = [:foo, 'bar', 2]
* a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
*
@@ -1651,8 +1804,8 @@ rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
VALUE target_ary;
if (argc == 0) {
- rb_ary_modify_check(ary);
- return ary;
+ rb_ary_modify_check(ary);
+ return ary;
}
target_ary = ary_ensure_room_for_unshift(ary, argc);
@@ -1674,7 +1827,7 @@ rb_ary_elt(VALUE ary, long offset)
long len = RARRAY_LEN(ary);
if (len == 0) return Qnil;
if (offset < 0 || len <= offset) {
- return Qnil;
+ return Qnil;
}
return RARRAY_AREF(ary, offset);
}
@@ -1695,7 +1848,7 @@ rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
if (beg < 0 || len < 0) return Qnil;
if (alen < len || alen < beg + len) {
- len = alen - beg;
+ len = alen - beg;
}
klass = rb_cArray;
if (len == 0) return ary_new(klass, 0);
@@ -1729,12 +1882,14 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* 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"
@@ -1743,12 +1898,14 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
*
* 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]
@@ -1762,6 +1919,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* 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]
@@ -1769,31 +1927,36 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* 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
+ * 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)
@@ -1802,6 +1965,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
*
* 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]
@@ -1814,7 +1978,7 @@ rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
rb_check_arity(argc, 1, 2);
if (argc == 2) {
- return rb_ary_aref2(ary, argv[0], argv[1]);
+ return rb_ary_aref2(ary, argv[0], argv[1]);
}
return rb_ary_aref1(ary, argv[0]);
}
@@ -1825,7 +1989,7 @@ rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
long beg = NUM2LONG(b);
long len = NUM2LONG(e);
if (beg < 0) {
- beg += RARRAY_LEN(ary);
+ beg += RARRAY_LEN(ary);
}
return rb_ary_subseq(ary, beg, len);
}
@@ -1837,7 +2001,7 @@ rb_ary_aref1(VALUE ary, VALUE arg)
/* special case - speeding up */
if (FIXNUM_P(arg)) {
- return rb_ary_entry(ary, FIX2LONG(arg));
+ return rb_ary_entry(ary, FIX2LONG(arg));
}
/* check if idx is Range or ArithmeticSequence */
switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
@@ -1860,6 +2024,7 @@ rb_ary_aref1(VALUE ary, VALUE arg)
* a = [:foo, 'bar', 2]
* a.at(0) # => :foo
* a.at(2) # => 2
+ *
*/
VALUE
@@ -1876,6 +2041,7 @@ rb_ary_at(VALUE ary, VALUE pos)
* 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]
@@ -1884,14 +2050,17 @@ rb_ary_at(VALUE ary, VALUE pos)
*
* 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"]
*
* 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) # []
*
@@ -1901,11 +2070,11 @@ static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
- if (RARRAY_LEN(ary) == 0) return Qnil;
- return RARRAY_AREF(ary, 0);
+ if (RARRAY_LEN(ary) == 0) return Qnil;
+ return RARRAY_AREF(ary, 0);
}
else {
- return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
+ return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
}
}
@@ -1917,22 +2086,26 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
* 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]
*
* If +self+ is empty, returns +nil+.
*
- * When non-negative \Innteger argument +n+ is given,
+ * When non-negative \Integer argument +n+ is given,
* returns the last +n+ elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.last(2) # => ["bar", 2]
*
* If <tt>n >= array.size</tt>, returns all elements:
+ *
* 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) # []
*
@@ -1943,12 +2116,12 @@ VALUE
rb_ary_last(int argc, const VALUE *argv, VALUE ary)
{
if (argc == 0) {
- long len = RARRAY_LEN(ary);
- if (len == 0) return Qnil;
- return RARRAY_AREF(ary, len-1);
+ long len = RARRAY_LEN(ary);
+ if (len == 0) return Qnil;
+ return RARRAY_AREF(ary, len-1);
}
else {
- return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
+ return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
}
}
@@ -1962,10 +2135,12 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
*
* 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"
@@ -1973,6 +2148,7 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
* 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"
*
@@ -1983,6 +2159,7 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
* a = [:foo, 'bar', 2]
* a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
* a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
+ *
*/
static VALUE
@@ -1995,20 +2172,20 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
rb_scan_args(argc, argv, "11", &pos, &ifnone);
block_given = rb_block_given_p();
if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
+ rb_warn("block supersedes default value argument");
}
idx = NUM2LONG(pos);
if (idx < 0) {
- idx += RARRAY_LEN(ary);
+ idx += RARRAY_LEN(ary);
}
if (idx < 0 || RARRAY_LEN(ary) <= idx) {
- if (block_given) return rb_yield(pos);
- if (argc == 1) {
- rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
- idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
- }
- return ifnone;
+ if (block_given) return rb_yield(pos);
+ if (argc == 1) {
+ rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
+ idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
+ }
+ return ifnone;
}
return RARRAY_AREF(ary, idx);
}
@@ -2024,6 +2201,7 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
* 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
*
@@ -2032,12 +2210,14 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
* 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
*
* Returns +nil+ if the block never returns a truthy value.
*
* When neither an argument nor a block is given, returns a new Enumerator:
+ *
* a = [:foo, 'bar', 2]
* e = a.index
* e # => #<Enumerator: [:foo, "bar", 2]:index>
@@ -2055,23 +2235,23 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
long i;
if (argc == 0) {
- RETURN_ENUMERATOR(ary, 0, 0);
- for (i=0; i<RARRAY_LEN(ary); i++) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
- return LONG2NUM(i);
- }
- }
- return Qnil;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
+ return LONG2NUM(i);
+ }
+ }
+ return Qnil;
}
rb_check_arity(argc, 0, 1);
val = argv[0];
if (rb_block_given_p())
- rb_warn("given block not used");
+ rb_warn("given block not used");
for (i=0; i<RARRAY_LEN(ary); i++) {
- VALUE e = RARRAY_AREF(ary, i);
- if (rb_equal(e, val)) {
- return LONG2NUM(i);
- }
+ VALUE e = RARRAY_AREF(ary, i);
+ if (rb_equal(e, val)) {
+ return LONG2NUM(i);
+ }
}
return Qnil;
}
@@ -2085,6 +2265,7 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
* Returns the index of the last element for which <tt>object == element</tt>.
*
* When argument +object+ is given but no block, returns the index of the last such element found:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a.rindex('bar') # => 3
*
@@ -2092,6 +2273,7 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
*
* 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
*
@@ -2114,25 +2296,25 @@ rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
long i = RARRAY_LEN(ary), len;
if (argc == 0) {
- RETURN_ENUMERATOR(ary, 0, 0);
- while (i--) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
- return LONG2NUM(i);
- if (i > (len = RARRAY_LEN(ary))) {
- i = len;
- }
- }
- return Qnil;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ while (i--) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
+ return LONG2NUM(i);
+ if (i > (len = RARRAY_LEN(ary))) {
+ i = len;
+ }
+ }
+ return Qnil;
}
rb_check_arity(argc, 0, 1);
val = argv[0];
if (rb_block_given_p())
- rb_warn("given block not used");
+ rb_warn("given block not used");
while (i--) {
- VALUE e = RARRAY_AREF(ary, i);
- if (rb_equal(e, val)) {
- return LONG2NUM(i);
- }
+ VALUE e = RARRAY_AREF(ary, i);
+ if (rb_equal(e, val)) {
+ return LONG2NUM(i);
+ }
if (i > RARRAY_LEN(ary)) {
break;
}
@@ -2158,54 +2340,54 @@ rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
olen = RARRAY_LEN(ary);
if (beg < 0) {
- beg += olen;
- if (beg < 0) {
- rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
- beg - olen, -olen);
- }
+ beg += olen;
+ if (beg < 0) {
+ rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
+ beg - olen, -olen);
+ }
}
if (olen < len || olen < beg + len) {
- len = olen - beg;
+ len = olen - beg;
}
{
const VALUE *optr = RARRAY_CONST_PTR_TRANSIENT(ary);
- rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
+ rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
}
if (beg >= olen) {
- VALUE target_ary;
- if (beg > ARY_MAX_SIZE - rlen) {
- rb_raise(rb_eIndexError, "index %ld too big", beg);
- }
- target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
- len = beg + rlen;
- ary_mem_clear(ary, olen, beg - olen);
- if (rlen > 0) {
+ VALUE target_ary;
+ if (beg > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", beg);
+ }
+ target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
+ len = beg + rlen;
+ ary_mem_clear(ary, olen, beg - olen);
+ if (rlen > 0) {
if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
- ary_memcpy0(ary, beg, rlen, rptr, target_ary);
- }
- ARY_SET_LEN(ary, len);
+ ary_memcpy0(ary, beg, rlen, rptr, target_ary);
+ }
+ ARY_SET_LEN(ary, len);
}
else {
- long alen;
-
- if (olen - len > ARY_MAX_SIZE - rlen) {
- rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
- }
- rb_ary_modify(ary);
- alen = olen + rlen - len;
- if (alen >= ARY_CAPA(ary)) {
- ary_double_capa(ary, alen);
- }
-
- if (len != rlen) {
+ long alen;
+
+ if (olen - len > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
+ }
+ rb_ary_modify(ary);
+ alen = olen + rlen - len;
+ if (alen >= ARY_CAPA(ary)) {
+ ary_double_capa(ary, alen);
+ }
+
+ if (len != rlen) {
RARRAY_PTR_USE_TRANSIENT(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len)));
- ARY_SET_LEN(ary, alen);
- }
- if (rlen > 0) {
+ ARY_SET_LEN(ary, alen);
+ }
+ if (rlen > 0) {
if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
/* give up wb-protected ary */
RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
@@ -2215,7 +2397,7 @@ rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
*/
RARRAY_PTR_USE_TRANSIENT(ary, ptr,
MEMMOVE(ptr + beg, rptr, VALUE, rlen));
- }
+ }
}
}
@@ -2226,22 +2408,14 @@ rb_ary_set_len(VALUE ary, long len)
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- rb_raise(rb_eRuntimeError, "can't set length of shared ");
+ rb_raise(rb_eRuntimeError, "can't set length of shared ");
}
if (len > (capa = (long)ARY_CAPA(ary))) {
- rb_bug("probable buffer overflow: %ld for %ld", len, capa);
+ rb_bug("probable buffer overflow: %ld for %ld", len, capa);
}
ARY_SET_LEN(ary, len);
}
-/*!
- * expands or shrinks \a ary to \a len elements.
- * expanded region will be filled with Qnil.
- * \param ary an array
- * \param len new size
- * \return \a ary
- * \post the size of \a ary is \a len.
- */
VALUE
rb_ary_resize(VALUE ary, long len)
{
@@ -2251,31 +2425,37 @@ rb_ary_resize(VALUE ary, long len)
olen = RARRAY_LEN(ary);
if (len == olen) return ary;
if (len > ARY_MAX_SIZE) {
- rb_raise(rb_eIndexError, "index %ld too big", len);
+ rb_raise(rb_eIndexError, "index %ld too big", len);
}
if (len > olen) {
- if (len >= ARY_CAPA(ary)) {
- ary_double_capa(ary, len);
- }
- ary_mem_clear(ary, olen, len - olen);
- ARY_SET_LEN(ary, len);
+ if (len >= ARY_CAPA(ary)) {
+ ary_double_capa(ary, len);
+ }
+ ary_mem_clear(ary, olen, len - olen);
+ ARY_SET_LEN(ary, len);
}
else if (ARY_EMBED_P(ary)) {
ARY_SET_EMBED_LEN(ary, len);
}
- else if (len <= RARRAY_EMBED_LEN_MAX) {
- VALUE tmp[RARRAY_EMBED_LEN_MAX];
- MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
- ary_discard(ary);
- MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len); /* WB: no new reference */
+ else if (len <= ary_embed_capa(ary)) {
+ const VALUE *ptr = ARY_HEAP_PTR(ary);
+ long ptr_capa = ARY_HEAP_SIZE(ary);
+ bool is_malloc_ptr = !ARY_SHARED_P(ary) && !RARRAY_TRANSIENT_P(ary);
+
+ FL_UNSET(ary, RARRAY_TRANSIENT_FLAG);
+ FL_SET_EMBED(ary);
+
+ MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
ARY_SET_EMBED_LEN(ary, len);
+
+ if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
}
else {
- if (olen > len + ARY_DEFAULT_SIZE) {
+ if (olen > len + ARY_DEFAULT_SIZE) {
size_t new_capa = ary_heap_realloc(ary, len);
ARY_SET_CAPA(ary, new_capa);
- }
- ARY_SET_HEAP_LEN(ary, len);
+ }
+ ARY_SET_HEAP_LEN(ary, len);
}
ary_verify(ary);
return ary;
@@ -2308,16 +2488,19 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* 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"]
@@ -2325,11 +2508,13 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* 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"]
@@ -2337,17 +2522,20 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* 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"]
@@ -2355,29 +2543,34 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* 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"]
@@ -2391,9 +2584,11 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
*
* 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
@@ -2404,16 +2599,16 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
rb_check_arity(argc, 2, 3);
rb_ary_modify_check(ary);
if (argc == 3) {
- beg = NUM2LONG(argv[0]);
- len = NUM2LONG(argv[1]);
+ beg = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[1]);
return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
}
if (FIXNUM_P(argv[0])) {
- offset = FIX2LONG(argv[0]);
+ offset = FIX2LONG(argv[0]);
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 */
+ /* check if idx is Range */
return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
}
@@ -2430,15 +2625,18 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
*
* 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)
@@ -2447,9 +2645,11 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -2462,15 +2662,15 @@ rb_ary_insert(int argc, VALUE *argv, VALUE ary)
pos = NUM2LONG(argv[0]);
if (argc == 1) return ary;
if (pos == -1) {
- pos = RARRAY_LEN(ary);
+ pos = RARRAY_LEN(ary);
}
else if (pos < 0) {
- long minpos = -RARRAY_LEN(ary) - 1;
- if (pos < minpos) {
- rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
- pos, minpos);
- }
- pos++;
+ long minpos = -RARRAY_LEN(ary) - 1;
+ if (pos < minpos) {
+ rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
+ pos, minpos);
+ }
+ pos++;
}
rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
return ary;
@@ -2494,29 +2694,35 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
*
* 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}" }
*
* Output:
+ *
* Symbol foo
* String bar
* Integer 2
*
* Allows the array to be modified during iteration:
+ *
* a = [:foo, 'bar', 2]
* a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
*
* Output:
+ *
* foo
* bar
*
* 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}" }
*
* Output:
+ *
* Symbol foo
* String bar
* Integer 2
@@ -2531,7 +2737,7 @@ rb_ary_each(VALUE ary)
ary_verify(ary);
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
- rb_yield(RARRAY_AREF(ary, i));
+ rb_yield(RARRAY_AREF(ary, i));
}
return ary;
}
@@ -2545,29 +2751,35 @@ rb_ary_each(VALUE ary)
*
* 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]}" }
*
* Output:
+ *
* 0 foo
* 1 bar
* 2 2
*
* Allows the array to be modified during iteration:
+ *
* a = [:foo, 'bar', 2]
* a.each_index {|index| puts index; a.clear if index > 0 }
*
* Output:
+ *
* 0
* 1
*
* 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]}"}
*
* Output:
+ *
* 0 foo
* 1 bar
* 2 2
@@ -2582,7 +2794,7 @@ rb_ary_each_index(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
- rb_yield(LONG2NUM(i));
+ rb_yield(LONG2NUM(i));
}
return ary;
}
@@ -2596,28 +2808,35 @@ rb_ary_each_index(VALUE ary)
*
* 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
@@ -2633,12 +2852,12 @@ rb_ary_reverse_each(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
len = RARRAY_LEN(ary);
while (len--) {
- long nlen;
- rb_yield(RARRAY_AREF(ary, len));
- nlen = RARRAY_LEN(ary);
- if (nlen < len) {
- len = nlen;
- }
+ long nlen;
+ rb_yield(RARRAY_AREF(ary, len));
+ nlen = RARRAY_LEN(ary);
+ if (nlen < len) {
+ len = nlen;
+ }
}
return ary;
}
@@ -2704,10 +2923,10 @@ recursive_join(VALUE obj, VALUE argp, int recur)
int *first = (int *)arg[3];
if (recur) {
- rb_raise(rb_eArgError, "recursive array join");
+ rb_raise(rb_eArgError, "recursive array join");
}
else {
- ary_join_1(obj, ary, sep, 0, result, first);
+ ary_join_1(obj, ary, sep, 0, result, first);
}
return Qnil;
}
@@ -2720,11 +2939,11 @@ 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);
+ 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);
+ if (i > 0 && !NIL_P(sep))
+ rb_str_buf_append(result, sep);
+ rb_str_buf_append(result, val);
}
return i;
}
@@ -2763,16 +2982,16 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
VALUE val, tmp;
for (; i<RARRAY_LEN(ary); i++) {
- if (i > 0 && !NIL_P(sep))
- rb_str_buf_append(result, sep);
+ if (i > 0 && !NIL_P(sep))
+ rb_str_buf_append(result, sep);
- val = RARRAY_AREF(ary, i);
- if (RB_TYPE_P(val, T_STRING)) {
+ val = RARRAY_AREF(ary, i);
+ if (RB_TYPE_P(val, T_STRING)) {
ary_join_1_str(result, val, first);
- }
- else if (RB_TYPE_P(val, T_ARRAY)) {
+ }
+ else if (RB_TYPE_P(val, T_ARRAY)) {
ary_join_1_ary(val, ary, sep, result, val, first);
- }
+ }
else if (!NIL_P(tmp = rb_check_string_type(val))) {
ary_join_1_str(result, tmp, first);
}
@@ -2781,7 +3000,7 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
}
else {
ary_join_1_str(result, rb_obj_as_string(val), first);
- }
+ }
}
}
@@ -2794,26 +3013,26 @@ rb_ary_join(VALUE ary, VALUE sep)
if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
if (!NIL_P(sep)) {
- StringValue(sep);
- len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
+ StringValue(sep);
+ len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
}
for (i=0; i<RARRAY_LEN(ary); i++) {
- val = RARRAY_AREF(ary, i);
- tmp = rb_check_string_type(val);
+ val = RARRAY_AREF(ary, i);
+ tmp = rb_check_string_type(val);
- if (NIL_P(tmp) || tmp != val) {
- int first;
+ if (NIL_P(tmp) || tmp != val) {
+ int first;
long n = RARRAY_LEN(ary);
if (i > n) i = n;
result = rb_str_buf_new(len + (n-i)*10);
- rb_enc_associate(result, rb_usascii_encoding());
+ rb_enc_associate(result, rb_usascii_encoding());
i = ary_join_0(ary, sep, i, result);
- first = i == 0;
- ary_join_1(ary, ary, sep, i, result, &first);
- return result;
- }
+ first = i == 0;
+ ary_join_1(ary, ary, sep, i, result, &first);
+ return result;
+ }
- len += RSTRING_LEN(tmp);
+ len += RSTRING_LEN(tmp);
}
result = rb_str_new(0, len);
@@ -2830,22 +3049,27 @@ rb_ary_join(VALUE ary, VALUE sep)
* array.join(separator = $,) -> new_string
*
* Returns the new \String formed by joining the array elements after conversion.
- * For each element +element+
+ * 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)
@@ -2871,10 +3095,10 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
if (recur) return rb_usascii_str_new_cstr("[...]");
str = rb_str_buf_new2("[");
for (i=0; i<RARRAY_LEN(ary); i++) {
- s = rb_inspect(RARRAY_AREF(ary, i));
- if (i > 0) rb_str_buf_cat2(str, ", ");
- else rb_enc_copy(str, s);
- rb_str_buf_append(str, s);
+ s = rb_inspect(RARRAY_AREF(ary, i));
+ if (i > 0) rb_str_buf_cat2(str, ", ");
+ else rb_enc_copy(str, s);
+ rb_str_buf_append(str, s);
}
rb_str_buf_cat2(str, "]");
return str;
@@ -2886,6 +3110,7 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
*
* Returns the new \String formed by calling method <tt>#inspect</tt>
* on each array element:
+ *
* a = [:foo, 'bar', 2]
* a.inspect # => "[:foo, \"bar\", 2]"
*
@@ -2910,10 +3135,12 @@ rb_ary_to_s(VALUE ary)
* 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
@@ -2921,15 +3148,16 @@ rb_ary_to_s(VALUE ary)
* a1 = a.to_a
* a1 # => ["foo", "bar", "two"]
* a1.class # => Array # Not MyArray
+ *
*/
static VALUE
rb_ary_to_a(VALUE ary)
{
if (rb_obj_class(ary) != rb_cArray) {
- VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
- rb_ary_replace(dup, ary);
- return dup;
+ VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
+ rb_ary_replace(dup, ary);
+ return dup;
}
return ary;
}
@@ -2944,16 +3172,19 @@ rb_ary_to_a(VALUE ary)
* 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
@@ -2964,18 +3195,18 @@ rb_ary_to_h(VALUE ary)
int block_given = rb_block_given_p();
for (i=0; i<RARRAY_LEN(ary); i++) {
- const VALUE e = rb_ary_elt(ary, i);
- const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
- const VALUE key_value_pair = rb_check_array_type(elt);
- if (NIL_P(key_value_pair)) {
- rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
- rb_obj_class(elt), i);
- }
- if (RARRAY_LEN(key_value_pair) != 2) {
- rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
- i, RARRAY_LEN(key_value_pair));
- }
- rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
+ const VALUE e = rb_ary_elt(ary, i);
+ const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
+ const VALUE key_value_pair = rb_check_array_type(elt);
+ if (NIL_P(key_value_pair)) {
+ rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
+ rb_obj_class(elt), i);
+ }
+ if (RARRAY_LEN(key_value_pair) != 2) {
+ rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
+ i, RARRAY_LEN(key_value_pair));
+ }
+ rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
}
return hash;
}
@@ -2997,9 +3228,9 @@ static void
ary_reverse(VALUE *p1, VALUE *p2)
{
while (p1 < p2) {
- VALUE tmp = *p1;
- *p1++ = *p2;
- *p2-- = tmp;
+ VALUE tmp = *p1;
+ *p1++ = *p2;
+ *p2-- = tmp;
}
}
@@ -3014,7 +3245,7 @@ rb_ary_reverse(VALUE ary)
RARRAY_PTR_USE_TRANSIENT(ary, p1, {
p2 = p1 + len - 1; /* points last item */
ary_reverse(p1, p2);
- }); /* WB: no new reference */
+ }); /* WB: no new reference */
}
return ary;
}
@@ -3024,8 +3255,10 @@ rb_ary_reverse(VALUE ary)
* array.reverse! -> self
*
* Reverses +self+ in place:
+ *
* a = ['foo', 'bar', 'two']
* a.reverse! # => ["two", "bar", "foo"]
+ *
*/
static VALUE
@@ -3038,10 +3271,12 @@ rb_ary_reverse_bang(VALUE ary)
* call-seq:
* array.reverse -> new_array
*
- * Returns a new \Array with the elements of +self+ in reverse order.
+ * 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
@@ -3053,7 +3288,7 @@ rb_ary_reverse_m(VALUE ary)
if (len > 0) {
const VALUE *p1 = RARRAY_CONST_PTR_TRANSIENT(ary);
VALUE *p2 = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(dup) + len - 1;
- do *p2-- = *p1++; while (--len > 0);
+ do *p2-- = *p1++; while (--len > 0);
}
ARY_SET_LEN(dup, RARRAY_LEN(ary));
return dup;
@@ -3109,35 +3344,42 @@ rb_ary_rotate(VALUE ary, long cnt)
* 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
@@ -3158,36 +3400,43 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -3201,11 +3450,11 @@ rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
len = RARRAY_LEN(ary);
rotated = rb_ary_new2(len);
if (len > 0) {
- cnt = rotate_count(cnt, len);
+ cnt = rotate_count(cnt, len);
ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
- len -= cnt;
- ary_memcpy(rotated, 0, len, ptr + cnt);
- ary_memcpy(rotated, len, cnt, ptr);
+ len -= cnt;
+ ary_memcpy(rotated, 0, len, ptr + cnt);
+ ary_memcpy(rotated, len, cnt, ptr);
}
ARY_SET_LEN(rotated, RARRAY_LEN(ary));
return rotated;
@@ -3214,14 +3463,13 @@ rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
struct ary_sort_data {
VALUE ary;
VALUE receiver;
- struct cmp_opt_data cmp_opt;
};
static VALUE
sort_reentered(VALUE ary)
{
if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort reentered");
+ rb_raise(rb_eRuntimeError, "sort reentered");
}
return Qnil;
}
@@ -3260,16 +3508,16 @@ 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, Integer)) {
- if ((long)a > (long)b) return 1;
- if ((long)a < (long)b) return -1;
- return 0;
+ if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
+ if ((long)a > (long)b) return 1;
+ if ((long)a < (long)b) return -1;
+ return 0;
}
- if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, String)) {
- return rb_str_cmp(a, b);
+ if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
+ return rb_str_cmp(a, b);
}
- if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(data->cmp_opt, Float)) {
- return rb_float_cmp(a, b);
+ if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
+ return rb_float_cmp(a, b);
}
retval = rb_funcallv(a, id_cmp, 1, &b);
@@ -3288,6 +3536,7 @@ sort_2(const void *ap, const void *bp, void *dummy)
*
* With no block, compares elements using operator <tt><=></tt>
* (see Comparable):
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a.sort!
@@ -3295,11 +3544,13 @@ sort_2(const void *ap, const void *bp, void *dummy)
*
* 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 }
@@ -3309,10 +3560,12 @@ sort_2(const void *ap, const void *bp, void *dummy)
*
* 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
@@ -3321,25 +3574,23 @@ rb_ary_sort_bang(VALUE ary)
rb_ary_modify(ary);
assert(!ARY_SHARED_P(ary));
if (RARRAY_LEN(ary) > 1) {
- VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
- struct ary_sort_data data;
- long len = RARRAY_LEN(ary);
- RBASIC_CLEAR_CLASS(tmp);
- data.ary = tmp;
+ VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
+ struct ary_sort_data data;
+ long len = RARRAY_LEN(ary);
+ RBASIC_CLEAR_CLASS(tmp);
+ data.ary = tmp;
data.receiver = ary;
- data.cmp_opt.opt_methods = 0;
- data.cmp_opt.opt_inited = 0;
- RARRAY_PTR_USE(tmp, ptr, {
+ RARRAY_PTR_USE(tmp, ptr, {
ruby_qsort(ptr, len, sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2, &data);
- }); /* WB: no new reference */
- rb_ary_modify(ary);
+ }); /* WB: no new reference */
+ rb_ary_modify(ary);
if (ARY_EMBED_P(tmp)) {
if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
+ FL_SET_EMBED(ary);
}
- ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
+ ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
}
else {
@@ -3385,6 +3636,7 @@ rb_ary_sort_bang(VALUE ary)
*
* With no block, compares elements using operator <tt><=></tt>
* (see Comparable):
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a1 = a.sort
@@ -3392,11 +3644,13 @@ rb_ary_sort_bang(VALUE ary)
*
* 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 }
@@ -3406,6 +3660,7 @@ rb_ary_sort_bang(VALUE ary)
*
* 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 }
@@ -3430,89 +3685,8 @@ static VALUE rb_ary_bsearch_index(VALUE ary);
* 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 <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>
+ * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
*/
static VALUE
@@ -3521,7 +3695,7 @@ rb_ary_bsearch(VALUE ary)
VALUE index_result = rb_ary_bsearch_index(ary);
if (FIXNUM_P(index_result)) {
- return rb_ary_entry(ary, FIX2LONG(index_result));
+ return rb_ary_entry(ary, FIX2LONG(index_result));
}
return index_result;
}
@@ -3544,39 +3718,39 @@ rb_ary_bsearch_index(VALUE ary)
RETURN_ENUMERATOR(ary, 0, 0);
while (low < high) {
- mid = low + ((high - low) / 2);
- val = rb_ary_entry(ary, mid);
- v = rb_yield(val);
- if (FIXNUM_P(v)) {
- if (v == INT2FIX(0)) return INT2FIX(mid);
- smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
- }
- else if (v == Qtrue) {
- satisfied = 1;
- smaller = 1;
- }
- else if (v == Qfalse || v == Qnil) {
- smaller = 0;
- }
- else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
- const VALUE zero = INT2FIX(0);
- switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
- case 0: return INT2FIX(mid);
- case 1: smaller = 1; break;
- case -1: smaller = 0;
- }
- }
- else {
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
- " (must be numeric, true, false or nil)",
- rb_obj_class(v));
- }
- if (smaller) {
- high = mid;
- }
- else {
- low = mid + 1;
- }
+ mid = low + ((high - low) / 2);
+ val = rb_ary_entry(ary, mid);
+ v = rb_yield(val);
+ if (FIXNUM_P(v)) {
+ if (v == INT2FIX(0)) return INT2FIX(mid);
+ smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
+ }
+ else if (v == Qtrue) {
+ satisfied = 1;
+ smaller = 1;
+ }
+ else if (!RTEST(v)) {
+ smaller = 0;
+ }
+ else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
+ const VALUE zero = INT2FIX(0);
+ switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
+ case 0: return INT2FIX(mid);
+ case 1: smaller = 0; break;
+ case -1: smaller = 1;
+ }
+ }
+ else {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
+ " (must be numeric, true, false or nil)",
+ rb_obj_class(v));
+ }
+ if (smaller) {
+ high = mid;
+ }
+ else {
+ low = mid + 1;
+ }
}
if (!satisfied) return Qnil;
return INT2FIX(low);
@@ -3603,6 +3777,7 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
* For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
*
* This example sorts strings based on their sizes:
+ *
* a = ['aaaa', 'bbb', 'cc', 'd']
* a.sort_by! {|element| element.size }
* a # => ["d", "cc", "bbb", "aaaa"]
@@ -3611,6 +3786,7 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
*
* a = ['aaaa', 'bbb', 'cc', 'd']
* a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
+ *
*/
static VALUE
@@ -3633,6 +3809,7 @@ rb_ary_sort_by_bang(VALUE ary)
*
* 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]
@@ -3667,10 +3844,12 @@ rb_ary_collect(VALUE ary)
*
* 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]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.map!
* a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
@@ -3686,7 +3865,7 @@ rb_ary_collect_bang(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
+ rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
}
return ary;
}
@@ -3698,21 +3877,21 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func
long beg, len, i, j;
for (i=0; i<argc; i++) {
- if (FIXNUM_P(argv[i])) {
- rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
- continue;
- }
- /* check if idx is Range */
- if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
- long end = olen < beg+len ? olen : beg+len;
- for (j = beg; j < end; j++) {
- rb_ary_push(result, (*func)(obj, j));
- }
- if (beg + len > j)
- rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
- continue;
- }
- rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
+ if (FIXNUM_P(argv[i])) {
+ rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
+ continue;
+ }
+ /* check if idx is Range */
+ if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
+ long end = olen < beg+len ? olen : beg+len;
+ for (j = beg; j < end; j++) {
+ rb_ary_push(result, (*func)(obj, j));
+ }
+ if (beg + len > j)
+ rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
+ continue;
+ }
+ rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
}
return result;
}
@@ -3722,25 +3901,25 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
{
long beg, len;
if (FIXNUM_P(idx)) {
- beg = FIX2LONG(idx);
+ beg = FIX2LONG(idx);
}
/* check if idx is Range */
else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
- if (len > 0) {
+ if (len > 0) {
const VALUE *const src = RARRAY_CONST_PTR_TRANSIENT(ary);
- const long end = beg + len;
- const long prevlen = RARRAY_LEN(result);
- if (beg < olen) {
- rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
- }
- if (end > olen) {
- rb_ary_store(result, prevlen + len - 1, Qnil);
- }
- }
- return result;
+ const long end = beg + len;
+ const long prevlen = RARRAY_LEN(result);
+ if (beg < olen) {
+ rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
+ }
+ if (end > olen) {
+ rb_ary_store(result, prevlen + len - 1, Qnil);
+ }
+ }
+ return result;
}
else {
- beg = NUM2LONG(idx);
+ beg = NUM2LONG(idx);
}
return rb_ary_push(result, rb_ary_entry(ary, beg));
}
@@ -3753,32 +3932,39 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
* of +self+ at the given \Integer or \Range +indexes+.
*
* For each positive +index+, returns the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, 2) # => [:foo, 2]
* a.values_at(0..1) # => [:foo, "bar"]
*
* The given +indexes+ may be in any order, and may repeat:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
* a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
*
* Assigns +nil+ for an +index+ that is too large:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
*
* Returns a new empty \Array if no arguments given.
*
* For each negative +index+, counts backward from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(-1, -3) # => [2, :foo]
*
* Assigns +nil+ for an +index+ that is too small:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
*
* The given +indexes+ may have a mixture of signs:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
+ *
*/
static VALUE
@@ -3787,7 +3973,7 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
long i, olen = RARRAY_LEN(ary);
VALUE result = rb_ary_new_capa(argc);
for (i = 0; i < argc; ++i) {
- append_values_at_single(result, ary, olen, argv[i]);
+ append_values_at_single(result, ary, olen, argv[i]);
}
RB_GC_GUARD(ary);
return result;
@@ -3802,11 +3988,13 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
* 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]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
*
@@ -3822,9 +4010,9 @@ rb_ary_select(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
result = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
- rb_ary_push(result, rb_ary_elt(ary, i));
- }
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
+ rb_ary_push(result, rb_ary_elt(ary, i));
+ }
}
return result;
}
@@ -3842,12 +4030,12 @@ select_bang_i(VALUE a)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
- VALUE v = RARRAY_AREF(ary, i1);
- if (!RTEST(rb_yield(v))) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, v);
- }
- arg->len[1] = ++i2;
+ VALUE v = RARRAY_AREF(ary, i1);
+ if (!RTEST(rb_yield(v))) continue;
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, v);
+ }
+ arg->len[1] = ++i2;
}
return (i1 == i2) ? Qnil : ary;
}
@@ -3861,15 +4049,15 @@ select_bang_ensure(VALUE a)
long i1 = arg->len[0], i2 = arg->len[1];
if (i2 < len && i2 < i1) {
- long tail = 0;
+ long tail = 0;
rb_ary_modify(ary);
- if (i1 < len) {
- tail = len - i1;
+ if (i1 < len) {
+ tail = len - i1;
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
- });
- }
- ARY_SET_LEN(ary, i2 + tail);
+ MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
+ });
+ }
+ ARY_SET_LEN(ary, i2 + tail);
}
return ary;
}
@@ -3883,12 +4071,14 @@ select_bang_ensure(VALUE a)
* removes from +self+ those elements for which the block returns +false+ or +nil+.
*
* Returns +self+ if any elements were removed:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
*
* Returns +nil+ if no elements were removed.
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
*
@@ -3915,12 +4105,15 @@ rb_ary_select_bang(VALUE ary)
*
* 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]
*
* 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
@@ -3936,11 +4129,11 @@ ary_resize_smaller(VALUE ary, long len)
{
rb_ary_modify(ary);
if (RARRAY_LEN(ary) > len) {
- ARY_SET_LEN(ary, len);
- if (len * 2 < ARY_CAPA(ary) &&
- ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
- ary_resize_capa(ary, len * 2);
- }
+ ARY_SET_LEN(ary, len);
+ if (len * 2 < ARY_CAPA(ary) &&
+ ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
+ ary_resize_capa(ary, len * 2);
+ }
}
}
@@ -3949,11 +4142,12 @@ ary_resize_smaller(VALUE ary, long len)
* array.delete(obj) -> deleted_object
* array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
*
- * Removes zero or more elements from +self+; returns +self+.
+ * Removes zero or more elements from +self+.
*
* When no block is given,
* removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
* returns the last deleted element:
+ *
* s1 = 'bar'; s2 = 'bar'
* a = [:foo, s1, 2, s2]
* a.delete('bar') # => "bar"
@@ -3966,14 +4160,17 @@ ary_resize_smaller(VALUE ary, long len)
*
* 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
@@ -3983,22 +4180,22 @@ rb_ary_delete(VALUE ary, VALUE item)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
- VALUE e = RARRAY_AREF(ary, i1);
+ VALUE e = RARRAY_AREF(ary, i1);
- if (rb_equal(e, item)) {
- v = e;
- continue;
- }
- if (i1 != i2) {
- rb_ary_store(ary, i2, e);
- }
- i2++;
+ if (rb_equal(e, item)) {
+ v = e;
+ continue;
+ }
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, e);
+ }
+ i2++;
}
if (RARRAY_LEN(ary) == i2) {
- if (rb_block_given_p()) {
- return rb_yield(item);
- }
- return Qnil;
+ if (rb_block_given_p()) {
+ return rb_yield(item);
+ }
+ return Qnil;
}
ary_resize_smaller(ary, i2);
@@ -4013,18 +4210,18 @@ rb_ary_delete_same(VALUE ary, VALUE item)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
- VALUE e = RARRAY_AREF(ary, i1);
+ VALUE e = RARRAY_AREF(ary, i1);
- if (e == item) {
- continue;
- }
- if (i1 != i2) {
- rb_ary_store(ary, i2, e);
- }
- i2++;
+ if (e == item) {
+ continue;
+ }
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, e);
+ }
+ i2++;
}
if (RARRAY_LEN(ary) == i2) {
- return;
+ return;
}
ary_resize_smaller(ary, i2);
@@ -4038,8 +4235,8 @@ rb_ary_delete_at(VALUE ary, long pos)
if (pos >= len) return Qnil;
if (pos < 0) {
- pos += len;
- if (pos < 0) return Qnil;
+ pos += len;
+ if (pos < 0) return Qnil;
}
rb_ary_modify(ary);
@@ -4059,6 +4256,7 @@ rb_ary_delete_at(VALUE ary, long pos)
* Deletes an element from +self+, per the given \Integer +index+.
*
* When +index+ is non-negative, deletes the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a.delete_at(1) # => "bar"
* a # => [:foo, 2]
@@ -4066,6 +4264,7 @@ rb_ary_delete_at(VALUE ary, long pos)
* 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]
@@ -4096,7 +4295,7 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
else if (orig_len < pos) {
return Qnil;
}
- else if (orig_len < pos + len) {
+ if (orig_len < pos + len) {
len = orig_len - pos;
}
if (len == 0) {
@@ -4119,11 +4318,13 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* 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"]
@@ -4132,13 +4333,15 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* 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:
+ * 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]
@@ -4150,8 +4353,9 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* 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.slice!(1..2) # => ["bar", 2]
* a # => [:foo]
*
* If <tt>range.start == a.size</tt>, returns a new empty \Array.
@@ -4159,15 +4363,18 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
* 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
@@ -4181,23 +4388,23 @@ rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
arg1 = argv[0];
if (argc == 2) {
- pos = NUM2LONG(argv[0]);
- len = NUM2LONG(argv[1]);
+ pos = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[1]);
return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
}
if (!FIXNUM_P(arg1)) {
- switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
- case Qtrue:
- /* valid range */
+ switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
+ case Qtrue:
+ /* valid range */
return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
- case Qnil:
- /* invalid range */
- return Qnil;
- default:
- /* not a range */
- break;
- }
+ case Qnil:
+ /* invalid range */
+ return Qnil;
+ default:
+ /* not a range */
+ break;
+ }
}
return rb_ary_delete_at(ary, NUM2LONG(arg1));
@@ -4209,11 +4416,11 @@ ary_reject(VALUE orig, VALUE result)
long i;
for (i = 0; i < RARRAY_LEN(orig); i++) {
- VALUE v = RARRAY_AREF(orig, i);
+ VALUE v = RARRAY_AREF(orig, i);
if (!RTEST(rb_yield(v))) {
- rb_ary_push(result, v);
- }
+ rb_ary_push(result, v);
+ }
}
return result;
}
@@ -4226,12 +4433,12 @@ reject_bang_i(VALUE a)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
- VALUE v = RARRAY_AREF(ary, i1);
- if (RTEST(rb_yield(v))) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, v);
- }
- arg->len[1] = ++i2;
+ VALUE v = RARRAY_AREF(ary, i1);
+ if (RTEST(rb_yield(v))) continue;
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, v);
+ }
+ arg->len[1] = ++i2;
}
return (i1 == i2) ? Qnil : ary;
}
@@ -4254,14 +4461,17 @@ ary_reject_bang(VALUE ary)
* Removes each element for which the block returns a truthy value.
*
* Returns +self+ if any elements removed:
+ *
* a = [:foo, 'bar', 2, 'bat']
* a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
*
* Returns +nil+ if no elements removed.
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
+ *
*/
static VALUE
@@ -4279,13 +4489,16 @@ rb_ary_reject_bang(VALUE ary)
*
* 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
@@ -4306,13 +4519,16 @@ rb_ary_reject(VALUE ary)
*
* 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]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
- */
+ *
+3 */
static VALUE
rb_ary_delete_if(VALUE ary)
@@ -4343,9 +4559,9 @@ take_items(VALUE obj, long n)
if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
result = rb_ary_new2(n);
args[0] = result; args[1] = (VALUE)n;
- if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
- rb_obj_class(obj));
+ if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
+ rb_obj_class(obj));
return result;
}
@@ -4360,10 +4576,12 @@ take_items(VALUE obj, long n)
*
* 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]
@@ -4372,6 +4590,7 @@ take_items(VALUE obj, long n)
*
* 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]
@@ -4380,23 +4599,27 @@ take_items(VALUE obj, long n)
*
* 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
+ * 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
@@ -4407,51 +4630,51 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
VALUE result = Qnil;
for (i=0; i<argc; i++) {
- argv[i] = take_items(argv[i], len);
+ argv[i] = take_items(argv[i], len);
}
if (rb_block_given_p()) {
- int arity = rb_block_arity();
-
- if (arity > 1) {
- VALUE work, *tmp;
-
- tmp = ALLOCV_N(VALUE, work, argc+1);
-
- for (i=0; i<RARRAY_LEN(ary); i++) {
- tmp[0] = RARRAY_AREF(ary, i);
- for (j=0; j<argc; j++) {
- tmp[j+1] = rb_ary_elt(argv[j], i);
- }
- rb_yield_values2(argc+1, tmp);
- }
-
- if (work) ALLOCV_END(work);
- }
- else {
- for (i=0; i<RARRAY_LEN(ary); i++) {
- VALUE tmp = rb_ary_new2(argc+1);
-
- rb_ary_push(tmp, RARRAY_AREF(ary, i));
- for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_elt(argv[j], i));
- }
- rb_yield(tmp);
- }
- }
+ int arity = rb_block_arity();
+
+ if (arity > 1) {
+ VALUE work, *tmp;
+
+ tmp = ALLOCV_N(VALUE, work, argc+1);
+
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ tmp[0] = RARRAY_AREF(ary, i);
+ for (j=0; j<argc; j++) {
+ tmp[j+1] = rb_ary_elt(argv[j], i);
+ }
+ rb_yield_values2(argc+1, tmp);
+ }
+
+ if (work) ALLOCV_END(work);
+ }
+ else {
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ VALUE tmp = rb_ary_new2(argc+1);
+
+ rb_ary_push(tmp, RARRAY_AREF(ary, i));
+ for (j=0; j<argc; j++) {
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
+ }
+ rb_yield(tmp);
+ }
+ }
}
else {
- result = rb_ary_new_capa(len);
+ result = rb_ary_new_capa(len);
- for (i=0; i<len; i++) {
- VALUE tmp = rb_ary_new_capa(argc+1);
+ for (i=0; i<len; i++) {
+ VALUE tmp = rb_ary_new_capa(argc+1);
- rb_ary_push(tmp, RARRAY_AREF(ary, i));
- for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_elt(argv[j], i));
- }
- rb_ary_push(result, tmp);
- }
+ rb_ary_push(tmp, RARRAY_AREF(ary, i));
+ for (j=0; j<argc; j++) {
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
+ }
+ rb_ary_push(result, tmp);
+ }
}
return result;
@@ -4463,8 +4686,10 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -4476,21 +4701,21 @@ rb_ary_transpose(VALUE ary)
alen = RARRAY_LEN(ary);
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
- tmp = to_ary(rb_ary_elt(ary, i));
- if (elen < 0) { /* first element */
- elen = RARRAY_LEN(tmp);
- result = rb_ary_new2(elen);
- for (j=0; j<elen; j++) {
- rb_ary_store(result, j, rb_ary_new2(alen));
- }
- }
- else if (elen != RARRAY_LEN(tmp)) {
- rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
- RARRAY_LEN(tmp), elen);
- }
- for (j=0; j<elen; j++) {
- rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
- }
+ tmp = to_ary(rb_ary_elt(ary, i));
+ if (elen < 0) { /* first element */
+ elen = RARRAY_LEN(tmp);
+ result = rb_ary_new2(elen);
+ for (j=0; j<elen; j++) {
+ rb_ary_store(result, j, rb_ary_new2(alen));
+ }
+ }
+ else if (elen != RARRAY_LEN(tmp)) {
+ rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
+ RARRAY_LEN(tmp), elen);
+ }
+ for (j=0; j<elen; j++) {
+ rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
+ }
}
return result;
}
@@ -4500,8 +4725,10 @@ rb_ary_transpose(VALUE ary)
* array.replace(other_array) -> self
*
* 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
@@ -4511,31 +4738,35 @@ rb_ary_replace(VALUE copy, VALUE orig)
orig = to_ary(orig);
if (copy == orig) return copy;
- if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
- VALUE shared_root = 0;
+ rb_ary_reset(copy);
- if (ARY_OWNS_HEAP_P(copy)) {
- ary_heap_free(copy);
- }
- else if (ARY_SHARED_P(copy)) {
- shared_root = ARY_SHARED_ROOT(copy);
- FL_UNSET_SHARED(copy);
- }
- FL_SET_EMBED(copy);
+ /* orig has enough space to embed the contents of orig. */
+ if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
+ assert(ARY_EMBED_P(copy));
ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR_TRANSIENT(orig));
- if (shared_root) {
- rb_ary_decrement_share(shared_root);
- }
- ARY_SET_LEN(copy, RARRAY_LEN(orig));
+ ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
+ }
+#if USE_RVARGC
+ /* orig is embedded but copy does not have enough space to embed the
+ * contents of orig. */
+ else if (ARY_EMBED_P(orig)) {
+ long len = ARY_EMBED_LEN(orig);
+ VALUE *ptr = ary_heap_alloc(copy, len);
+
+ FL_UNSET_EMBED(copy);
+ ARY_SET_PTR(copy, ptr);
+ ARY_SET_LEN(copy, len);
+ ARY_SET_CAPA(copy, len);
+
+ // No allocation and exception expected that could leave `copy` in a
+ // bad state from the edits above.
+ ary_memcpy(copy, 0, len, RARRAY_CONST_PTR_TRANSIENT(orig));
}
+#endif
+ /* Otherwise, orig is on heap and copy does not have enough space to embed
+ * the contents of orig. */
else {
VALUE shared_root = ary_make_shared(orig);
- if (ARY_OWNS_HEAP_P(copy)) {
- ary_heap_free(copy);
- }
- else {
- rb_ary_unshare_safe(copy);
- }
FL_UNSET_EMBED(copy);
ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
@@ -4550,8 +4781,10 @@ rb_ary_replace(VALUE copy, VALUE orig)
* array.clear -> self
*
* Removes all elements from +self+:
+ *
* a = [:foo, 'bar', 2]
* a.clear # => []
+ *
*/
VALUE
@@ -4559,11 +4792,11 @@ rb_ary_clear(VALUE ary)
{
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- if (!ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
+ if (!ARY_EMBED_P(ary)) {
+ rb_ary_unshare(ary);
+ FL_SET_EMBED(ary);
ARY_SET_EMBED_LEN(ary, 0);
- }
+ }
}
else {
ARY_SET_LEN(ary, 0);
@@ -4589,6 +4822,7 @@ rb_ary_clear(VALUE ary)
* 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]
@@ -4598,20 +4832,24 @@ rb_ary_clear(VALUE ary)
*
* 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']
@@ -4621,20 +4859,24 @@ rb_ary_clear(VALUE ary)
* 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"]
@@ -4644,14 +4886,17 @@ rb_ary_clear(VALUE ary)
*
* 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']
@@ -4659,6 +4904,7 @@ rb_ary_clear(VALUE ary)
*
* 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']
@@ -4666,29 +4912,34 @@ rb_ary_clear(VALUE ary)
*
* 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:
+ * 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']
@@ -4699,20 +4950,24 @@ rb_ary_clear(VALUE ary)
* 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"]
@@ -4723,14 +4978,17 @@ rb_ary_clear(VALUE ary)
*
* 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']
@@ -4738,10 +4996,12 @@ rb_ary_clear(VALUE ary)
*
* 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
@@ -4751,59 +5011,59 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
long beg = 0, end = 0, len = 0;
if (rb_block_given_p()) {
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- argc += 1; /* hackish */
+ rb_scan_args(argc, argv, "02", &arg1, &arg2);
+ argc += 1; /* hackish */
}
else {
- rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
+ rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
}
switch (argc) {
case 1:
- beg = 0;
- len = RARRAY_LEN(ary);
- break;
+ beg = 0;
+ len = RARRAY_LEN(ary);
+ break;
case 2:
- if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
- break;
- }
- /* fall through */
+ if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
+ break;
+ }
+ /* fall through */
case 3:
- beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
- if (beg < 0) {
- beg = RARRAY_LEN(ary) + beg;
- if (beg < 0) beg = 0;
- }
- len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
- break;
+ beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
+ if (beg < 0) {
+ beg = RARRAY_LEN(ary) + beg;
+ if (beg < 0) beg = 0;
+ }
+ len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
+ break;
}
rb_ary_modify(ary);
if (len < 0) {
return ary;
}
if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
- rb_raise(rb_eArgError, "argument too big");
+ rb_raise(rb_eArgError, "argument too big");
}
end = beg + len;
if (RARRAY_LEN(ary) < end) {
- if (end >= ARY_CAPA(ary)) {
- ary_resize_capa(ary, end);
- }
- ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
- ARY_SET_LEN(ary, end);
+ if (end >= ARY_CAPA(ary)) {
+ ary_resize_capa(ary, end);
+ }
+ ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
+ ARY_SET_LEN(ary, end);
}
- if (item == Qundef) {
- VALUE v;
- long i;
+ if (UNDEF_P(item)) {
+ VALUE v;
+ long i;
- for (i=beg; i<end; i++) {
- v = rb_yield(LONG2NUM(i));
- if (i>=RARRAY_LEN(ary)) break;
- ARY_SET(ary, i, v);
- }
+ for (i=beg; i<end; i++) {
+ v = rb_yield(LONG2NUM(i));
+ if (i>=RARRAY_LEN(ary)) break;
+ ARY_SET(ary, i, v);
+ }
}
else {
- ary_memfill(ary, beg, len, item);
+ ary_memfill(ary, beg, len, item);
}
return ary;
}
@@ -4814,6 +5074,7 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
*
* 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]
*
@@ -4845,6 +5106,7 @@ 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;
}
@@ -4853,6 +5115,7 @@ ary_append(VALUE x, VALUE y)
* array.concat(*other_arrays) -> self
*
* 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]
*/
@@ -4863,15 +5126,15 @@ rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
rb_ary_modify_check(ary);
if (argc == 1) {
- rb_ary_concat(ary, argv[0]);
+ rb_ary_concat(ary, argv[0]);
}
else if (argc > 1) {
- int i;
- VALUE args = rb_ary_tmp_new(argc);
- for (i = 0; i < argc; i++) {
- rb_ary_concat(args, argv[i]);
- }
- ary_append(ary, args);
+ int i;
+ VALUE args = rb_ary_hidden_new(argc);
+ for (i = 0; i < argc; i++) {
+ rb_ary_concat(args, argv[i]);
+ }
+ ary_append(ary, args);
}
ary_verify(ary);
@@ -4891,12 +5154,15 @@ rb_ary_concat(VALUE x, VALUE y)
*
* When non-negative argument \Integer +n+ is given,
* returns a new \Array built by concatenating the +n+ copies of +self+:
+ *
* a = ['x', 'y']
* a * 3 # => ["x", "y", "x", "y", "x", "y"]
*
* When \String argument +string_separator+ is given,
* equivalent to <tt>array.join(string_separator)</tt>:
+ *
* [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
+ *
*/
static VALUE
@@ -4908,19 +5174,19 @@ rb_ary_times(VALUE ary, VALUE times)
tmp = rb_check_string_type(times);
if (!NIL_P(tmp)) {
- return rb_ary_join(ary, tmp);
+ return rb_ary_join(ary, tmp);
}
len = NUM2LONG(times);
if (len == 0) {
ary2 = ary_new(rb_cArray, 0);
- goto out;
+ goto out;
}
if (len < 0) {
- rb_raise(rb_eArgError, "negative argument");
+ rb_raise(rb_eArgError, "negative argument");
}
if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
- rb_raise(rb_eArgError, "argument too big");
+ rb_raise(rb_eArgError, "argument too big");
}
len *= RARRAY_LEN(ary);
@@ -4930,8 +5196,8 @@ rb_ary_times(VALUE ary, VALUE times)
ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
t = RARRAY_LEN(ary);
if (0 < t) {
- ary_memcpy(ary2, 0, t, ptr);
- while (t <= len/2) {
+ ary_memcpy(ary2, 0, t, ptr);
+ while (t <= len/2) {
ary_memcpy(ary2, t, t, RARRAY_CONST_PTR_TRANSIENT(ary2));
t *= 2;
}
@@ -4949,6 +5215,7 @@ rb_ary_times(VALUE ary, VALUE times)
*
* 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]
*
@@ -4964,10 +5231,10 @@ rb_ary_assoc(VALUE ary, VALUE key)
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- v = rb_check_array_type(RARRAY_AREF(ary, i));
- if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
- rb_equal(RARRAY_AREF(v, 0), key))
- return v;
+ v = rb_check_array_type(RARRAY_AREF(ary, i));
+ if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
+ rb_equal(RARRAY_AREF(v, 0), key))
+ return v;
}
return Qnil;
}
@@ -4978,6 +5245,7 @@ rb_ary_assoc(VALUE ary, VALUE key)
*
* 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]
*
@@ -4993,11 +5261,11 @@ rb_ary_rassoc(VALUE ary, VALUE value)
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- v = RARRAY_AREF(ary, i);
- if (RB_TYPE_P(v, T_ARRAY) &&
- RARRAY_LEN(v) > 1 &&
- rb_equal(RARRAY_AREF(v, 1), value))
- return v;
+ v = RARRAY_AREF(ary, i);
+ if (RB_TYPE_P(v, T_ARRAY) &&
+ RARRAY_LEN(v) > 1 &&
+ rb_equal(RARRAY_AREF(v, 1), value))
+ return v;
}
return Qnil;
}
@@ -5016,22 +5284,22 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
len1 = RARRAY_LEN(ary1);
for (i = 0; i < len1; i++) {
- if (*p1 != *p2) {
- if (rb_equal(*p1, *p2)) {
- len1 = RARRAY_LEN(ary1);
- if (len1 != RARRAY_LEN(ary2))
- return Qfalse;
- if (len1 < i)
- return Qtrue;
+ if (*p1 != *p2) {
+ if (rb_equal(*p1, *p2)) {
+ len1 = RARRAY_LEN(ary1);
+ if (len1 != RARRAY_LEN(ary2))
+ return Qfalse;
+ if (len1 < i)
+ return Qtrue;
p1 = RARRAY_CONST_PTR(ary1) + i;
p2 = RARRAY_CONST_PTR(ary2) + i;
- }
- else {
- return Qfalse;
- }
- }
- p1++;
- p2++;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ p1++;
+ p2++;
}
return Qtrue;
}
@@ -5042,6 +5310,7 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
*
* 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
@@ -5058,10 +5327,10 @@ rb_ary_equal(VALUE ary1, VALUE ary2)
{
if (ary1 == ary2) return Qtrue;
if (!RB_TYPE_P(ary2, T_ARRAY)) {
- if (!rb_respond_to(ary2, idTo_ary)) {
- return Qfalse;
- }
- return rb_equal(ary2, ary1);
+ if (!rb_respond_to(ary2, idTo_ary)) {
+ return Qfalse;
+ }
+ return rb_equal(ary2, ary1);
}
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
if (RARRAY_CONST_PTR_TRANSIENT(ary1) == RARRAY_CONST_PTR_TRANSIENT(ary2)) return Qtrue;
@@ -5075,8 +5344,8 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
if (recur) return Qtrue; /* Subtle! */
for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
+ if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ return Qfalse;
}
return Qtrue;
}
@@ -5087,13 +5356,14 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
*
* 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
*
* Otherwise, returns +false+.
*
- * This method is different from method {Array#==}[#method-i-3D-3D],
+ * This method is different from method Array#==,
* which compares using method <tt>Object#==</tt>.
*/
@@ -5114,8 +5384,10 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
* Returns the integer hash value for +self+.
*
* 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
@@ -5128,8 +5400,8 @@ rb_ary_hash(VALUE ary)
h = rb_hash_start(RARRAY_LEN(ary));
h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
for (i=0; i<RARRAY_LEN(ary); i++) {
- n = rb_hash(RARRAY_AREF(ary, i));
- h = rb_hash_uint(h, NUM2LONG(n));
+ n = rb_hash(RARRAY_AREF(ary, i));
+ h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return ST2FIX(h);
@@ -5141,6 +5413,7 @@ rb_ary_hash(VALUE ary)
*
* 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
*/
@@ -5152,10 +5425,10 @@ rb_ary_includes(VALUE ary, VALUE item)
VALUE e;
for (i=0; i<RARRAY_LEN(ary); i++) {
- e = RARRAY_AREF(ary, i);
- if (rb_equal(e, item)) {
- return Qtrue;
- }
+ e = RARRAY_AREF(ary, i);
+ if (rb_equal(e, item)) {
+ return Qtrue;
+ }
}
return Qfalse;
}
@@ -5167,10 +5440,10 @@ rb_ary_includes_by_eql(VALUE ary, VALUE item)
VALUE e;
for (i=0; i<RARRAY_LEN(ary); i++) {
- e = RARRAY_AREF(ary, i);
- if (rb_eql(item, e)) {
- return Qtrue;
- }
+ e = RARRAY_AREF(ary, i);
+ if (rb_eql(item, e)) {
+ return Qtrue;
+ }
}
return Qfalse;
}
@@ -5183,14 +5456,14 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur)
if (recur) return Qundef; /* Subtle! */
len = RARRAY_LEN(ary1);
if (len > RARRAY_LEN(ary2)) {
- len = RARRAY_LEN(ary2);
+ len = RARRAY_LEN(ary2);
}
for (i=0; i<len; i++) {
- VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
- VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
- if (v != INT2FIX(0)) {
- return v;
- }
+ VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
+ VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
+ if (v != INT2FIX(0)) {
+ return v;
+ }
}
return Qundef;
}
@@ -5203,18 +5476,27 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur)
* For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
*
* Returns -1 if any result is -1:
+ *
* [0, 1, 2] <=> [0, 1, 3] # => -1
*
* 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
@@ -5227,7 +5509,7 @@ rb_ary_cmp(VALUE ary1, VALUE ary2)
if (NIL_P(ary2)) return Qnil;
if (ary1 == ary2) return INT2FIX(0);
v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
- if (v != Qundef) return v;
+ if (!UNDEF_P(v)) return v;
len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
if (len == 0) return INT2FIX(0);
if (len > 0) return INT2FIX(1);
@@ -5240,8 +5522,8 @@ ary_add_hash(VALUE hash, VALUE ary)
long i;
for (i=0; i<RARRAY_LEN(ary); i++) {
- VALUE elt = RARRAY_AREF(ary, i);
- rb_hash_add_new_element(hash, elt, elt);
+ VALUE elt = RARRAY_AREF(ary, i);
+ rb_hash_add_new_element(hash, elt, elt);
}
return hash;
}
@@ -5269,8 +5551,8 @@ ary_add_hash_by(VALUE hash, VALUE ary)
long i;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
- rb_hash_add_new_element(hash, k, v);
+ VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
+ rb_hash_add_new_element(hash, k, v);
}
return hash;
}
@@ -5288,7 +5570,7 @@ ary_recycle_hash(VALUE hash)
assert(RBASIC_CLASS(hash) == 0);
if (RHASH_ST_TABLE_P(hash)) {
st_table *tbl = RHASH_ST_TABLE(hash);
- st_free_table(tbl);
+ st_free_table(tbl);
RHASH_ST_CLEAR(hash);
}
}
@@ -5301,6 +5583,7 @@ ary_recycle_hash(VALUE hash)
* 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]
@@ -5308,7 +5591,7 @@ ary_recycle_hash(VALUE hash)
* Related: Array#difference.
*/
-static VALUE
+VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
VALUE ary3;
@@ -5320,18 +5603,18 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
ary3 = rb_ary_new();
if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
- for (i=0; i<RARRAY_LEN(ary1); i++) {
- VALUE elt = rb_ary_elt(ary1, i);
- if (rb_ary_includes_by_eql(ary2, elt)) continue;
- rb_ary_push(ary3, elt);
- }
- return ary3;
+ for (i=0; i<RARRAY_LEN(ary1); i++) {
+ VALUE elt = rb_ary_elt(ary1, i);
+ if (rb_ary_includes_by_eql(ary2, elt)) continue;
+ rb_ary_push(ary3, elt);
+ }
+ return ary3;
}
hash = ary_make_hash(ary2);
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
- rb_ary_push(ary3, rb_ary_elt(ary1, i));
+ rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
ary_recycle_hash(hash);
return ary3;
@@ -5344,6 +5627,7 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
* 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]
@@ -5396,10 +5680,12 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
*
* 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]
*
* Preserves order from +array+:
+ *
* [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
*
* Related: Array#intersection.
@@ -5418,23 +5704,23 @@ rb_ary_and(VALUE ary1, VALUE ary2)
if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
- for (i=0; i<RARRAY_LEN(ary1); i++) {
- v = RARRAY_AREF(ary1, i);
- if (!rb_ary_includes_by_eql(ary2, v)) continue;
- if (rb_ary_includes_by_eql(ary3, v)) continue;
- rb_ary_push(ary3, v);
- }
- return ary3;
+ for (i=0; i<RARRAY_LEN(ary1); i++) {
+ v = RARRAY_AREF(ary1, i);
+ if (!rb_ary_includes_by_eql(ary2, v)) continue;
+ if (rb_ary_includes_by_eql(ary3, v)) continue;
+ rb_ary_push(ary3, v);
+ }
+ return ary3;
}
hash = ary_make_hash(ary2);
for (i=0; i<RARRAY_LEN(ary1); i++) {
- v = RARRAY_AREF(ary1, i);
- vv = (st_data_t)v;
+ v = RARRAY_AREF(ary1, i);
+ vv = (st_data_t)v;
if (rb_hash_stlike_delete(hash, &vv, 0)) {
- rb_ary_push(ary3, v);
- }
+ rb_ary_push(ary3, v);
+ }
}
ary_recycle_hash(hash);
@@ -5448,10 +5734,12 @@ rb_ary_and(VALUE ary1, VALUE ary2)
* 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]
*
* Preserves order from +self+:
+ *
* [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
*
* Returns a copy of +self+ if no arguments given.
@@ -5510,6 +5798,7 @@ rb_ary_union_hash(VALUE hash, VALUE ary2)
* 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]
@@ -5524,10 +5813,10 @@ rb_ary_or(VALUE ary1, VALUE ary2)
ary2 = to_ary(ary2);
if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
- ary3 = rb_ary_new();
+ ary3 = rb_ary_new();
rb_ary_union(ary3, ary1);
rb_ary_union(ary3, ary2);
- return ary3;
+ return ary3;
}
hash = ary_make_hash(ary1);
@@ -5544,6 +5833,7 @@ rb_ary_or(VALUE ary1, VALUE ary2)
*
* 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]
@@ -5588,13 +5878,14 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
* ary.intersect?(other_ary) -> true or false
*
* Returns +true+ if the array and +other_ary+ have at least one element in
- * common, otherwise returns +false+.
+ * common, otherwise returns +false+:
*
* a = [ 1, 2, 3 ]
* b = [ 3, 4, 5 ]
* c = [ 5, 6, 7 ]
* a.intersect?(b) #=> true
* a.intersect?(c) #=> false
+ *
*/
static VALUE
@@ -5735,6 +6026,7 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
* 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+.
*
@@ -5743,10 +6035,12 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* With no argument and no block, returns the element in +self+
* having the maximum value per method <tt><=></tt>:
+ *
* [0, 1, 2].max # => 2
*
* 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, 0]
*
@@ -5754,16 +6048,18 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* 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"
*
* 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)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE result = Qundef, v;
VALUE num;
long i;
@@ -5773,23 +6069,23 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary)
const long n = RARRAY_LEN(ary);
if (rb_block_given_p()) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
- result = v;
- }
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_AREF(ary, i);
+ if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
+ result = v;
+ }
+ }
}
else if (n > 0) {
result = RARRAY_AREF(ary, 0);
if (n > 1) {
- if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
+ if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
return ary_max_opt_fixnum(ary, 1, result);
}
- else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
+ else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
return ary_max_opt_string(ary, 1, result);
}
- else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
+ else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
return ary_max_opt_float(ary, 1, result);
}
else {
@@ -5797,7 +6093,7 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary)
}
}
}
- if (result == Qundef) return Qnil;
+ if (UNDEF_P(result)) return Qnil;
return result;
}
@@ -5898,6 +6194,7 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
* 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+.
*
@@ -5906,10 +6203,12 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* With no argument and no block, returns the element in +self+
* having the minimum value per method <tt><=></tt>:
+ *
* [0, 1, 2].min # => 0
*
* With \Integer argument +n+ and no block, returns a new \Array with at most +n+ elements,
* in ascending order per method <tt><=></tt>:
+ *
* [0, 1, 2, 3].min(3) # => [0, 1, 2]
* [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
*
@@ -5917,17 +6216,18 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* 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]
+ *
+ * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
+ *
*/
static VALUE
rb_ary_min(int argc, VALUE *argv, VALUE ary)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE result = Qundef, v;
VALUE num;
long i;
@@ -5937,23 +6237,23 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
const long n = RARRAY_LEN(ary);
if (rb_block_given_p()) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
- result = v;
- }
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_AREF(ary, i);
+ if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
+ result = v;
+ }
+ }
}
else if (n > 0) {
result = RARRAY_AREF(ary, 0);
if (n > 1) {
- if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
+ if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
return ary_min_opt_fixnum(ary, 1, result);
}
- else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
+ else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
return ary_min_opt_string(ary, 1, result);
}
- else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
+ else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
return ary_min_opt_float(ary, 1, result);
}
else {
@@ -5961,7 +6261,7 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
}
}
}
- if (result == Qundef) return Qnil;
+ if (UNDEF_P(result)) return Qnil;
return result;
}
@@ -5977,13 +6277,16 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
* 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)
@@ -6013,6 +6316,7 @@ push_value(st_data_t key, st_data_t val, st_data_t ary)
* to compare.
*
* Returns +self+ if any elements removed:
+ *
* a = [0, 0, 1, 1, 2, 2]
* a.uniq! # => [0, 1, 2]
*
@@ -6023,6 +6327,7 @@ push_value(st_data_t key, st_data_t val, st_data_t ary)
* elements for which the block returns duplicate values.
*
* Returns +self+ if any elements removed:
+ *
* a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
* a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
*
@@ -6038,19 +6343,19 @@ rb_ary_uniq_bang(VALUE ary)
if (RARRAY_LEN(ary) <= 1)
return Qnil;
if (rb_block_given_p())
- hash = ary_make_hash_by(ary);
+ hash = ary_make_hash_by(ary);
else
- hash = ary_make_hash(ary);
+ hash = ary_make_hash(ary);
hash_size = RHASH_SIZE(hash);
if (RARRAY_LEN(ary) == hash_size) {
- return Qnil;
+ return Qnil;
}
rb_ary_modify_check(ary);
ARY_SET_LEN(ary, 0);
if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
+ rb_ary_unshare(ary);
+ FL_SET_EMBED(ary);
}
ary_resize_capa(ary, hash_size);
rb_hash_foreach(hash, push_value, ary);
@@ -6068,15 +6373,18 @@ rb_ary_uniq_bang(VALUE ary)
* the first occurrence always being retained.
*
* With no block given, identifies and omits duplicates using method <tt>eql?</tt>
- * to compare.
+ * 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
@@ -6089,12 +6397,12 @@ rb_ary_uniq(VALUE ary)
uniq = rb_ary_dup(ary);
}
else if (rb_block_given_p()) {
- hash = ary_make_hash_by(ary);
- uniq = rb_hash_values(hash);
+ hash = ary_make_hash_by(ary);
+ uniq = rb_hash_values(hash);
}
else {
- hash = ary_make_hash(ary);
- uniq = rb_hash_values(hash);
+ hash = ary_make_hash(ary);
+ uniq = rb_hash_values(hash);
}
if (hash) {
ary_recycle_hash(hash);
@@ -6123,12 +6431,12 @@ rb_ary_compact_bang(VALUE ary)
end = p + RARRAY_LEN(ary);
while (t < end) {
- if (NIL_P(*t)) t++;
- else *p++ = *t++;
+ if (NIL_P(*t)) t++;
+ else *p++ = *t++;
}
n = p - RARRAY_CONST_PTR_TRANSIENT(ary);
if (RARRAY_LEN(ary) == n) {
- return Qnil;
+ return Qnil;
}
ary_resize_smaller(ary, n);
@@ -6140,6 +6448,7 @@ rb_ary_compact_bang(VALUE ary)
* array.compact -> new_array
*
* Returns a new \Array containing all non-+nil+ elements from +self+:
+ *
* a = [nil, 0, nil, 1, nil, 2, nil]
* a.compact # => [0, 1, 2]
*/
@@ -6161,19 +6470,22 @@ rb_ary_compact(VALUE ary)
* Returns a count of specified elements.
*
* With no argument and no block, returns the count of all elements:
+ *
* [0, 1, 2].count # => 3
* [].count # => 0
*
* With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
+ *
* [0, 1, 2, 0.0].count(0) # => 2
* [0, 1, 2].count(3) # => 0
*
* 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>==</tt> to +obj+:
+ * and returns the count of elements <tt>==</tt> to +obj+.
*/
static VALUE
@@ -6182,25 +6494,25 @@ rb_ary_count(int argc, VALUE *argv, VALUE ary)
long i, n = 0;
if (rb_check_arity(argc, 0, 1) == 0) {
- VALUE v;
+ VALUE v;
- if (!rb_block_given_p())
- return LONG2NUM(RARRAY_LEN(ary));
+ if (!rb_block_given_p())
+ return LONG2NUM(RARRAY_LEN(ary));
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (RTEST(rb_yield(v))) n++;
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_AREF(ary, i);
+ if (RTEST(rb_yield(v))) n++;
+ }
}
else {
VALUE obj = argv[0];
- if (rb_block_given_p()) {
- rb_warn("given block not used");
- }
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
- }
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
+ }
}
return LONG2NUM(n);
@@ -6234,64 +6546,64 @@ flatten(VALUE ary, int level)
rb_ary_push(stack, LONG2NUM(i + 1));
if (level < 0) {
- vmemo = rb_hash_new();
- RBASIC_CLEAR_CLASS(vmemo);
- memo = st_init_numtable();
- rb_hash_st_table_set(vmemo, memo);
- st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
- st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
+ vmemo = rb_hash_new();
+ RBASIC_CLEAR_CLASS(vmemo);
+ memo = st_init_numtable();
+ rb_hash_st_table_set(vmemo, memo);
+ st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
+ st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
}
ary = tmp;
i = 0;
while (1) {
- while (i < RARRAY_LEN(ary)) {
- elt = RARRAY_AREF(ary, i++);
- if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
- rb_ary_push(result, elt);
- continue;
- }
- tmp = rb_check_array_type(elt);
- if (RBASIC(result)->klass) {
- if (memo) {
- RB_GC_GUARD(vmemo);
- st_clear(memo);
- }
- rb_raise(rb_eRuntimeError, "flatten reentered");
- }
- if (NIL_P(tmp)) {
- rb_ary_push(result, elt);
- }
- else {
- if (memo) {
- id = (st_data_t)tmp;
- if (st_is_member(memo, id)) {
- st_clear(memo);
- rb_raise(rb_eArgError, "tried to flatten recursive array");
- }
- st_insert(memo, id, (st_data_t)Qtrue);
- }
- rb_ary_push(stack, ary);
- rb_ary_push(stack, LONG2NUM(i));
- ary = tmp;
- i = 0;
- }
- }
- if (RARRAY_LEN(stack) == 0) {
- break;
- }
- if (memo) {
- id = (st_data_t)ary;
- st_delete(memo, &id, 0);
- }
- tmp = rb_ary_pop(stack);
- i = NUM2LONG(tmp);
- ary = rb_ary_pop(stack);
+ while (i < RARRAY_LEN(ary)) {
+ elt = RARRAY_AREF(ary, i++);
+ if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
+ rb_ary_push(result, elt);
+ continue;
+ }
+ tmp = rb_check_array_type(elt);
+ if (RBASIC(result)->klass) {
+ if (memo) {
+ RB_GC_GUARD(vmemo);
+ st_clear(memo);
+ }
+ rb_raise(rb_eRuntimeError, "flatten reentered");
+ }
+ if (NIL_P(tmp)) {
+ rb_ary_push(result, elt);
+ }
+ else {
+ if (memo) {
+ id = (st_data_t)tmp;
+ if (st_is_member(memo, id)) {
+ st_clear(memo);
+ rb_raise(rb_eArgError, "tried to flatten recursive array");
+ }
+ st_insert(memo, id, (st_data_t)Qtrue);
+ }
+ rb_ary_push(stack, ary);
+ rb_ary_push(stack, LONG2NUM(i));
+ ary = tmp;
+ i = 0;
+ }
+ }
+ if (RARRAY_LEN(stack) == 0) {
+ break;
+ }
+ if (memo) {
+ id = (st_data_t)ary;
+ st_delete(memo, &id, 0);
+ }
+ tmp = rb_ary_pop(stack);
+ i = NUM2LONG(tmp);
+ ary = rb_ary_pop(stack);
}
if (memo) {
- st_clear(memo);
+ st_clear(memo);
}
RBASIC_SET_CLASS(result, rb_cArray);
@@ -6307,6 +6619,7 @@ flatten(VALUE ary, int level)
* 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 ]
@@ -6316,6 +6629,7 @@ flatten(VALUE ary, int level)
* [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
@@ -6324,6 +6638,7 @@ flatten(VALUE ary, int level)
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
* [0, 1, 2].flatten!(-1) # => nil
+ *
*/
static VALUE
@@ -6339,7 +6654,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
result = flatten(ary, level);
if (result == ary) {
- return Qnil;
+ return Qnil;
}
if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
rb_ary_replace(ary, result);
@@ -6358,6 +6673,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* - 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 ]
@@ -6368,6 +6684,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* 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]
@@ -6376,6 +6693,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* 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
@@ -6407,16 +6725,16 @@ rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
rb_ary_modify(ary);
i = len = RARRAY_LEN(ary);
RARRAY_PTR_USE(ary, ptr, {
- while (i) {
- long j = RAND_UPTO(i);
- VALUE tmp;
+ while (i) {
+ long j = RAND_UPTO(i);
+ VALUE tmp;
if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR_TRANSIENT(ary)) {
rb_raise(rb_eRuntimeError, "modified during shuffle");
- }
- tmp = ptr[--i];
- ptr[i] = ptr[j];
- ptr[j] = tmp;
- }
+ }
+ tmp = ptr[--i];
+ ptr[i] = ptr[j];
+ ptr[j] = tmp;
+ }
}); /* WB: no new reference */
return ary;
}
@@ -6430,7 +6748,7 @@ rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
}
static VALUE
-rb_ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
+ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
{
VALUE result;
long n, len, i, j, k, idx[10];
@@ -6439,120 +6757,120 @@ rb_ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VA
len = RARRAY_LEN(ary);
if (!to_array) {
- if (len < 2)
- i = 0;
- else
- i = RAND_UPTO(len);
+ if (len < 2)
+ i = 0;
+ else
+ i = RAND_UPTO(len);
- return rb_ary_elt(ary, i);
+ return rb_ary_elt(ary, i);
}
n = NUM2LONG(nv);
if (n < 0) rb_raise(rb_eArgError, "negative sample number");
if (n > len) n = len;
if (n <= numberof(idx)) {
- for (i = 0; i < n; ++i) {
- rnds[i] = RAND_UPTO(len - i);
- }
+ for (i = 0; i < n; ++i) {
+ rnds[i] = RAND_UPTO(len - i);
+ }
}
k = len;
len = RARRAY_LEN(ary);
if (len < k && n <= numberof(idx)) {
- for (i = 0; i < n; ++i) {
- if (rnds[i] >= len) return rb_ary_new_capa(0);
- }
+ for (i = 0; i < n; ++i) {
+ if (rnds[i] >= len) return rb_ary_new_capa(0);
+ }
}
if (n > len) n = len;
switch (n) {
case 0:
- return rb_ary_new_capa(0);
+ return rb_ary_new_capa(0);
case 1:
- i = rnds[0];
- return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
+ i = rnds[0];
+ return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
case 2:
- i = rnds[0];
- j = rnds[1];
- if (j >= i) j++;
- return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
+ i = rnds[0];
+ j = rnds[1];
+ if (j >= i) j++;
+ return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
case 3:
- i = rnds[0];
- j = rnds[1];
- k = rnds[2];
- {
- long l = j, g = i;
- if (j >= i) l = i, g = ++j;
- if (k >= l && (++k >= g)) ++k;
- }
- return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
+ i = rnds[0];
+ j = rnds[1];
+ k = rnds[2];
+ {
+ long l = j, g = i;
+ if (j >= i) l = i, g = ++j;
+ if (k >= l && (++k >= g)) ++k;
+ }
+ return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
}
memo_threshold =
- len < 2560 ? len / 128 :
- len < 5120 ? len / 64 :
- len < 10240 ? len / 32 :
- len / 16;
+ len < 2560 ? len / 128 :
+ len < 5120 ? len / 64 :
+ len < 10240 ? len / 32 :
+ len / 16;
if (n <= numberof(idx)) {
- long sorted[numberof(idx)];
- sorted[0] = idx[0] = rnds[0];
- for (i=1; i<n; i++) {
- k = rnds[i];
- for (j = 0; j < i; ++j) {
- if (k < sorted[j]) break;
- ++k;
- }
- memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
- sorted[j] = idx[i] = k;
- }
- result = rb_ary_new_capa(n);
+ long sorted[numberof(idx)];
+ sorted[0] = idx[0] = rnds[0];
+ for (i=1; i<n; i++) {
+ k = rnds[i];
+ for (j = 0; j < i; ++j) {
+ if (k < sorted[j]) break;
+ ++k;
+ }
+ memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
+ sorted[j] = idx[i] = k;
+ }
+ result = rb_ary_new_capa(n);
RARRAY_PTR_USE_TRANSIENT(result, ptr_result, {
- for (i=0; i<n; i++) {
- ptr_result[i] = RARRAY_AREF(ary, idx[i]);
- }
- });
+ for (i=0; i<n; i++) {
+ ptr_result[i] = RARRAY_AREF(ary, idx[i]);
+ }
+ });
}
else if (n <= memo_threshold / 2) {
- long max_idx = 0;
+ long max_idx = 0;
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
- VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
- st_table *memo = st_init_numtable_with_size(n);
- DATA_PTR(vmemo) = memo;
- result = rb_ary_new_capa(n);
- RARRAY_PTR_USE(result, ptr_result, {
- for (i=0; i<n; i++) {
- long r = RAND_UPTO(len-i) + i;
- ptr_result[i] = r;
- if (r > max_idx) max_idx = r;
- }
- len = RARRAY_LEN(ary);
- if (len <= max_idx) n = 0;
- else if (n > len) n = len;
+ VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
+ st_table *memo = st_init_numtable_with_size(n);
+ DATA_PTR(vmemo) = memo;
+ result = rb_ary_new_capa(n);
+ RARRAY_PTR_USE(result, ptr_result, {
+ for (i=0; i<n; i++) {
+ long r = RAND_UPTO(len-i) + i;
+ ptr_result[i] = r;
+ if (r > max_idx) max_idx = r;
+ }
+ len = RARRAY_LEN(ary);
+ if (len <= max_idx) n = 0;
+ else if (n > len) n = len;
RARRAY_PTR_USE_TRANSIENT(ary, ptr_ary, {
- for (i=0; i<n; i++) {
- long j2 = j = ptr_result[i];
- long i2 = i;
- st_data_t value;
- if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
- if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
- st_insert(memo, (st_data_t)j, (st_data_t)i2);
- ptr_result[i] = ptr_ary[j2];
- }
- });
- });
- DATA_PTR(vmemo) = 0;
- st_free_table(memo);
+ for (i=0; i<n; i++) {
+ long j2 = j = ptr_result[i];
+ long i2 = i;
+ st_data_t value;
+ if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
+ if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
+ st_insert(memo, (st_data_t)j, (st_data_t)i2);
+ ptr_result[i] = ptr_ary[j2];
+ }
+ });
+ });
+ DATA_PTR(vmemo) = 0;
+ st_free_table(memo);
}
else {
- result = rb_ary_dup(ary);
- RBASIC_CLEAR_CLASS(result);
- RB_GC_GUARD(ary);
- RARRAY_PTR_USE(result, ptr_result, {
- for (i=0; i<n; i++) {
- j = RAND_UPTO(len-i) + i;
- nv = ptr_result[j];
- ptr_result[j] = ptr_result[i];
- ptr_result[i] = nv;
- }
- });
- RBASIC_SET_CLASS_RAW(result, rb_cArray);
+ result = rb_ary_dup(ary);
+ RBASIC_CLEAR_CLASS(result);
+ RB_GC_GUARD(ary);
+ RARRAY_PTR_USE(result, ptr_result, {
+ for (i=0; i<n; i++) {
+ j = RAND_UPTO(len-i) + i;
+ nv = ptr_result[j];
+ ptr_result[j] = ptr_result[i];
+ ptr_result[i] = nv;
+ }
+ });
+ RBASIC_SET_CLASS_RAW(result, rb_cArray);
}
ARY_SET_LEN(result, n);
@@ -6560,15 +6878,21 @@ rb_ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VA
}
static VALUE
+ary_sample0(rb_execution_context_t *ec, VALUE ary)
+{
+ return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
+}
+
+static VALUE
rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
{
long mul;
VALUE n = Qnil;
if (args && (RARRAY_LEN(args) > 0)) {
- n = RARRAY_AREF(args, 0);
+ n = RARRAY_AREF(args, 0);
}
if (RARRAY_LEN(self) == 0) return INT2FIX(0);
- if (n == Qnil) return DBL2NUM(HUGE_VAL);
+ if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
mul = NUM2LONG(n);
if (mul <= 0) return INT2FIX(0);
n = LONG2FIX(mul);
@@ -6585,15 +6909,18 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
* 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 }
@@ -6603,6 +6930,7 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
* [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)
@@ -6628,9 +6956,6 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
return Qnil;
}
-#define tmpary(n) rb_ary_tmp_new(n)
-#define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
-
/*
* Build a ruby array of the corresponding values and yield it to the
* associated block.
@@ -6666,32 +6991,32 @@ permute0(const long n, const long r, long *const p, char *const used, const VALU
long i = 0, index = 0;
for (;;) {
- const char *const unused = memchr(&used[i], 0, n-i);
- if (!unused) {
- if (!index) break;
- i = p[--index]; /* pop index */
- used[i++] = 0; /* index unused */
- }
- else {
- i = unused - used;
- p[index] = i;
- used[i] = 1; /* mark index used */
- ++index;
- if (index < r-1) { /* if not done yet */
- p[index] = i = 0;
- continue;
- }
- for (i = 0; i < n; ++i) {
- if (used[i]) continue;
- p[index] = i;
- if (!yield_indexed_values(values, r, p)) {
- rb_raise(rb_eRuntimeError, "permute reentered");
- }
- }
- i = p[--index]; /* pop index */
- used[i] = 0; /* index unused */
- p[index] = ++i;
- }
+ const char *const unused = memchr(&used[i], 0, n-i);
+ if (!unused) {
+ if (!index) break;
+ i = p[--index]; /* pop index */
+ used[i++] = 0; /* index unused */
+ }
+ else {
+ i = unused - used;
+ p[index] = i;
+ used[i] = 1; /* mark index used */
+ ++index;
+ if (index < r-1) { /* if not done yet */
+ p[index] = i = 0;
+ continue;
+ }
+ for (i = 0; i < n; ++i) {
+ if (used[i]) continue;
+ p[index] = i;
+ if (!yield_indexed_values(values, r, p)) {
+ rb_raise(rb_eRuntimeError, "permute reentered");
+ }
+ }
+ i = p[--index]; /* pop index */
+ used[i] = 0; /* index unused */
+ p[index] = ++i;
+ }
}
}
@@ -6704,14 +7029,14 @@ descending_factorial(long from, long how_many)
{
VALUE cnt;
if (how_many > 0) {
- cnt = LONG2FIX(from);
- while (--how_many > 0) {
- long v = --from;
- cnt = rb_int_mul(cnt, LONG2FIX(v));
- }
+ cnt = LONG2FIX(from);
+ while (--how_many > 0) {
+ long v = --from;
+ cnt = rb_int_mul(cnt, LONG2FIX(v));
+ }
}
else {
- cnt = LONG2FIX(how_many == 0);
+ cnt = LONG2FIX(how_many == 0);
}
return cnt;
}
@@ -6722,18 +7047,18 @@ binomial_coefficient(long comb, long size)
VALUE r;
long i;
if (comb > size-comb) {
- comb = size-comb;
+ comb = size-comb;
}
if (comb < 0) {
- return LONG2FIX(0);
+ return LONG2FIX(0);
}
else if (comb == 0) {
- return LONG2FIX(1);
+ return LONG2FIX(1);
}
r = LONG2FIX(size);
for (i = 1; i < comb; ++i) {
- r = rb_int_mul(r, LONG2FIX(size - i));
- r = rb_int_idiv(r, LONG2FIX(i + 1));
+ r = rb_int_mul(r, LONG2FIX(size - i));
+ r = rb_int_idiv(r, LONG2FIX(i + 1));
}
return r;
}
@@ -6761,19 +7086,26 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* 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]
@@ -6782,22 +7114,29 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* [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]
@@ -6806,9 +7145,11 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* [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
@@ -6823,28 +7164,28 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
r = NUM2LONG(argv[0]); /* Permutation size from argument */
if (r < 0 || n < r) {
- /* no permutations: yield nothing */
+ /* no permutations: yield nothing */
}
else if (r == 0) { /* exactly one permutation: the zero-length array */
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (r == 1) { /* this is a special, easy case */
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else { /* this is the general case */
- volatile VALUE t0;
- long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
- char *used = (char*)(p + r);
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC_CLEAR_CLASS(ary0);
+ volatile VALUE t0;
+ long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
+ char *used = (char*)(p + r);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ RBASIC_CLEAR_CLASS(ary0);
- MEMZERO(used, char, n); /* initialize array */
+ MEMZERO(used, char, n); /* initialize array */
- permute0(n, r, p, used, ary0); /* compute and yield permutations */
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ permute0(n, r, p, used, ary0); /* compute and yield permutations */
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -6857,16 +7198,16 @@ combinate0(const long len, const long n, long *const stack, const VALUE values)
MEMZERO(stack+1, long, n);
stack[0] = -1;
for (;;) {
- for (lev++; lev < n; lev++) {
- stack[lev+1] = stack[lev]+1;
- }
- if (!yield_indexed_values(values, n, stack+1)) {
- rb_raise(rb_eRuntimeError, "combination reentered");
- }
- do {
- if (lev == 0) return;
- stack[lev--]++;
- } while (stack[lev+1]+n == len+lev+1);
+ for (lev++; lev < n; lev++) {
+ stack[lev+1] = stack[lev]+1;
+ }
+ if (!yield_indexed_values(values, n, stack+1)) {
+ rb_raise(rb_eRuntimeError, "combination reentered");
+ }
+ do {
+ if (lev == 0) return;
+ stack[lev--]++;
+ } while (stack[lev+1]+n == len+lev+1);
}
}
@@ -6891,34 +7232,46 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
* 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
@@ -6930,25 +7283,25 @@ rb_ary_combination(VALUE ary, VALUE num)
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
len = RARRAY_LEN(ary);
if (n < 0 || len < n) {
- /* yield nothing */
+ /* yield nothing */
}
else if (n == 0) {
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (n == 1) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else {
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- volatile VALUE t0;
- long *stack = ALLOCV_N(long, t0, n+1);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ volatile VALUE t0;
+ long *stack = ALLOCV_N(long, t0, n+1);
- RBASIC_CLEAR_CLASS(ary0);
- combinate0(len, n, stack, ary0);
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ RBASIC_CLEAR_CLASS(ary0);
+ combinate0(len, n, stack, ary0);
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -6972,19 +7325,19 @@ rpermute0(const long n, const long r, long *const p, const VALUE values)
p[index] = i;
for (;;) {
- if (++index < r-1) {
- p[index] = i = 0;
- continue;
- }
- for (i = 0; i < n; ++i) {
- p[index] = i;
- if (!yield_indexed_values(values, r, p)) {
- rb_raise(rb_eRuntimeError, "repeated permute reentered");
- }
- }
- do {
- if (index <= 0) return;
- } while ((i = ++p[--index]) >= n);
+ if (++index < r-1) {
+ p[index] = i = 0;
+ continue;
+ }
+ for (i = 0; i < n; ++i) {
+ p[index] = i;
+ if (!yield_indexed_values(values, r, p)) {
+ rb_raise(rb_eRuntimeError, "repeated permute reentered");
+ }
+ }
+ do {
+ if (index <= 0) return;
+ } while ((i = ++p[--index]) >= n);
}
}
@@ -6995,10 +7348,10 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
long k = NUM2LONG(RARRAY_AREF(args, 0));
if (k < 0) {
- return LONG2FIX(0);
+ return LONG2FIX(0);
}
if (n <= 0) {
- return LONG2FIX(!k);
+ return LONG2FIX(!k);
}
return rb_int_positive_pow(n, (unsigned long)k);
}
@@ -7017,16 +7370,22 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* 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]
@@ -7040,14 +7399,17 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* 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 # => [[]]
@@ -7057,6 +7419,7 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* 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)
@@ -7068,25 +7431,25 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
r = NUM2LONG(num); /* Permutation size from argument */
if (r < 0) {
- /* no permutations: yield nothing */
+ /* no permutations: yield nothing */
}
else if (r == 0) { /* exactly one permutation: the zero-length array */
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (r == 1) { /* this is a special, easy case */
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else { /* this is the general case */
- volatile VALUE t0;
- long *p = ALLOCV_N(long, t0, r);
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC_CLEAR_CLASS(ary0);
+ volatile VALUE t0;
+ long *p = ALLOCV_N(long, t0, r);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ RBASIC_CLEAR_CLASS(ary0);
- rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -7098,19 +7461,19 @@ rcombinate0(const long n, const long r, long *const p, const long rest, const VA
p[index] = i;
for (;;) {
- if (++index < r-1) {
- p[index] = i;
- continue;
- }
- for (; i < n; ++i) {
- p[index] = i;
- if (!yield_indexed_values(values, r, p)) {
- rb_raise(rb_eRuntimeError, "repeated combination reentered");
- }
- }
- do {
- if (index <= 0) return;
- } while ((i = ++p[--index]) >= n);
+ if (++index < r-1) {
+ p[index] = i;
+ continue;
+ }
+ for (; i < n; ++i) {
+ p[index] = i;
+ if (!yield_indexed_values(values, r, p)) {
+ rb_raise(rb_eRuntimeError, "repeated combination reentered");
+ }
+ }
+ do {
+ if (index <= 0) return;
+ } while ((i = ++p[--index]) >= n);
}
}
@@ -7120,7 +7483,7 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
long n = RARRAY_LEN(ary);
long k = NUM2LONG(RARRAY_AREF(args, 0));
if (k == 0) {
- return LONG2FIX(1);
+ return LONG2FIX(1);
}
return binomial_coefficient(k, n + k - 1);
}
@@ -7139,16 +7502,22 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* 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]
@@ -7159,14 +7528,17 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* 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 # => [[]]
@@ -7176,6 +7548,7 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* 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
@@ -7187,28 +7560,28 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
len = RARRAY_LEN(ary);
if (n < 0) {
- /* yield nothing */
+ /* yield nothing */
}
else if (n == 0) {
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (n == 1) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else if (len == 0) {
- /* yield nothing */
+ /* yield nothing */
}
else {
- volatile VALUE t0;
- long *p = ALLOCV_N(long, t0, n);
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC_CLEAR_CLASS(ary0);
+ volatile VALUE t0;
+ long *p = ALLOCV_N(long, t0, n);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ RBASIC_CLEAR_CLASS(ary0);
- rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -7219,12 +7592,14 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* 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+.
+ * 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]
@@ -7239,11 +7614,15 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
*
* 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]
@@ -7252,21 +7631,26 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* [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
rb_ary_product(int argc, VALUE *argv, VALUE ary)
{
int n = argc+1; /* How many arrays we're operating on */
- volatile VALUE t0 = tmpary(n);
+ volatile VALUE t0 = rb_ary_hidden_new(n);
volatile VALUE t1 = Qundef;
VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
@@ -7287,64 +7671,64 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
/* Otherwise, allocate and fill in an array of results */
if (rb_block_given_p()) {
- /* Make defensive copies of arrays; exit if any is empty */
- for (i = 0; i < n; i++) {
- if (RARRAY_LEN(arrays[i]) == 0) goto done;
- arrays[i] = ary_make_shared_copy(arrays[i]);
- }
+ /* Make defensive copies of arrays; exit if any is empty */
+ for (i = 0; i < n; i++) {
+ if (RARRAY_LEN(arrays[i]) == 0) goto done;
+ arrays[i] = ary_make_shared_copy(arrays[i]);
+ }
}
else {
- /* Compute the length of the result array; return [] if any is empty */
- for (i = 0; i < n; i++) {
- long k = RARRAY_LEN(arrays[i]);
- if (k == 0) {
- result = rb_ary_new2(0);
- goto done;
- }
+ /* Compute the length of the result array; return [] if any is empty */
+ for (i = 0; i < n; i++) {
+ long k = RARRAY_LEN(arrays[i]);
+ if (k == 0) {
+ result = rb_ary_new2(0);
+ goto done;
+ }
if (MUL_OVERFLOW_LONG_P(resultlen, k))
- rb_raise(rb_eRangeError, "too big to product");
- resultlen *= k;
- }
- result = rb_ary_new2(resultlen);
+ rb_raise(rb_eRangeError, "too big to product");
+ resultlen *= k;
+ }
+ result = rb_ary_new2(resultlen);
}
for (;;) {
- int m;
- /* fill in one subarray */
- VALUE subarray = rb_ary_new2(n);
- for (j = 0; j < n; j++) {
- rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
- }
-
- /* put it on the result array */
- if (NIL_P(result)) {
- FL_SET(t0, FL_USER5);
- rb_yield(subarray);
- if (! FL_TEST(t0, FL_USER5)) {
- rb_raise(rb_eRuntimeError, "product reentered");
- }
- else {
- FL_UNSET(t0, FL_USER5);
- }
- }
- else {
- rb_ary_push(result, subarray);
- }
-
- /*
- * Increment the last counter. If it overflows, reset to 0
- * and increment the one before it.
- */
- m = n-1;
- counters[m]++;
- while (counters[m] == RARRAY_LEN(arrays[m])) {
- counters[m] = 0;
- /* If the first counter overflows, we are done */
- if (--m < 0) goto done;
- counters[m]++;
- }
+ int m;
+ /* fill in one subarray */
+ VALUE subarray = rb_ary_new2(n);
+ for (j = 0; j < n; j++) {
+ rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
+ }
+
+ /* put it on the result array */
+ if (NIL_P(result)) {
+ FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
+ rb_yield(subarray);
+ if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
+ rb_raise(rb_eRuntimeError, "product reentered");
+ }
+ else {
+ FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
+ }
+ }
+ else {
+ rb_ary_push(result, subarray);
+ }
+
+ /*
+ * Increment the last counter. If it overflows, reset to 0
+ * and increment the one before it.
+ */
+ m = n-1;
+ counters[m]++;
+ while (counters[m] == RARRAY_LEN(arrays[m])) {
+ counters[m] = 0;
+ /* If the first counter overflows, we are done */
+ if (--m < 0) goto done;
+ counters[m]++;
+ }
}
+
done:
- tmpary_discard(t0);
ALLOCV_END(t1);
return NIL_P(result) ? ary : result;
@@ -7359,11 +7743,13 @@ done:
* 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
@@ -7371,7 +7757,7 @@ rb_ary_take(VALUE obj, VALUE n)
{
long len = NUM2LONG(n);
if (len < 0) {
- rb_raise(rb_eArgError, "attempt to take negative size");
+ rb_raise(rb_eArgError, "attempt to take negative size");
}
return rb_ary_subseq(obj, 0, len);
}
@@ -7386,14 +7772,17 @@ rb_ary_take(VALUE obj, VALUE n)
*
* 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:
+ * 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
@@ -7403,7 +7792,7 @@ rb_ary_take_while(VALUE ary)
RETURN_ENUMERATOR(ary, 0, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
+ if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
}
return rb_ary_take(ary, LONG2FIX(i));
}
@@ -7417,10 +7806,12 @@ rb_ary_take_while(VALUE ary)
* 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
@@ -7429,11 +7820,11 @@ rb_ary_drop(VALUE ary, VALUE n)
VALUE result;
long pos = NUM2LONG(n);
if (pos < 0) {
- rb_raise(rb_eArgError, "attempt to drop negative size");
+ rb_raise(rb_eArgError, "attempt to drop negative size");
}
result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
- if (result == Qnil) result = rb_ary_new();
+ if (NIL_P(result)) result = rb_ary_new();
return result;
}
@@ -7447,12 +7838,15 @@ rb_ary_drop(VALUE ary, VALUE n)
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
- * returns a new Array _omitting_ those elements for which the block returned a truthy value:
+ * returns a new \Array _omitting_ those elements for which the block returned a truthy value:
+ *
* 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
@@ -7462,7 +7856,7 @@ rb_ary_drop_while(VALUE ary)
RETURN_ENUMERATOR(ary, 0, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
+ if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
}
return rb_ary_drop(ary, LONG2FIX(i));
}
@@ -7477,17 +7871,20 @@ rb_ary_drop_while(VALUE ary)
*
* 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
@@ -7508,9 +7905,9 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
if (rb_block_given_p()) {
rb_warn("given block not used");
}
- for (i = 0; i < RARRAY_LEN(ary); ++i) {
- if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
- }
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
+ }
}
else if (!rb_block_given_p()) {
for (i = 0; i < len; ++i) {
@@ -7518,9 +7915,9 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
}
}
else {
- for (i = 0; i < RARRAY_LEN(ary); ++i) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
- }
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
+ }
}
return Qfalse;
}
@@ -7535,16 +7932,19 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -7592,16 +7992,19 @@ rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -7649,6 +8052,7 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -7656,12 +8060,14 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
*
* 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
@@ -7717,14 +8123,16 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
* 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].
+ * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
*
* Examples:
+ *
* a = [:foo, [:bar, :baz, [:bat, :bam]]]
* a.dig(1) # => [:bar, :baz, [:bat, :bam]]
* a.dig(1, 2) # => [:bat, :bam]
* a.dig(1, 2, 0) # => :bat
* a.dig(1, 2, 3) # => nil
+ *
*/
static VALUE
@@ -7742,7 +8150,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) {
+ if (!UNDEF_P(r)) {
v = rb_rational_plus(r, v);
}
else if (!n && z) {
@@ -7757,31 +8165,38 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
* 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
@@ -7811,10 +8226,10 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
n = 0;
}
}
- else if (RB_TYPE_P(e, T_BIGNUM))
+ else if (RB_BIGNUM_TYPE_P(e))
v = rb_big_plus(e, v);
else if (RB_TYPE_P(e, T_RATIONAL)) {
- if (r == Qundef)
+ if (UNDEF_P(r))
r = e;
else
r = rb_rational_plus(r, e);
@@ -7848,7 +8263,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
x = RFLOAT_VALUE(e);
else if (FIXNUM_P(e))
x = FIX2LONG(e);
- else if (RB_TYPE_P(e, T_BIGNUM))
+ else if (RB_BIGNUM_TYPE_P(e))
x = rb_big2dbl(e);
else if (RB_TYPE_P(e, T_RATIONAL))
x = rb_num2dbl(e);
@@ -7901,75 +8316,128 @@ rb_ary_deconstruct(VALUE ary)
}
/*
- * An \Array is an ordered, integer-indexed collection of objects,
- * called _elements_. Any object may be an \Array element.
+ * An \Array is an ordered, integer-indexed collection of objects, called _elements_.
+ * Any object (even another array) may be an array element,
+ * and an array can contain objects of different types.
*
* == \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.
* - ...
*
- * A non-negative index is <i>in range</i> if it is smaller than
+ * A non-negative index is <i>in range</i> if and only if it is smaller than
* the size of the array. For a 3-element array:
+ *
* - 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
+ * A negative index is <i>in range</i> if and only 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.
*
+ * Although the effective index into an array is always an integer,
+ * some methods (both within and outside of class \Array)
+ * accept one or more non-integer arguments that are
+ * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
+ *
+ *
* == Creating Arrays
*
- * A new array can be created by using the literal constructor
- * <code>[]</code>. Arrays can contain different types of objects. For
- * example, the array below contains an Integer, a String and a Float:
+ * You can create an \Array object explicitly with:
+ *
+ * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
+ *
+ * [1, 'one', :one, [2, 'two', :two]]
+ *
+ * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
+ *
+ * %w[foo bar baz] # => ["foo", "bar", "baz"]
+ * %w[1 % *] # => ["1", "%", "*"]
+ *
+ * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
*
- * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
+ * %i[foo bar baz] # => [:foo, :bar, :baz]
+ * %i[1 % *] # => [:"1", :%, :*]
*
- * An array can also be created by explicitly calling Array.new with zero, one
- * (the initial size of the Array) or two arguments (the initial size and a
- * default object).
+ * - \Method Kernel#Array:
*
- * ary = Array.new #=> []
- * Array.new(3) #=> [nil, nil, nil]
- * Array.new(3, true) #=> [true, true, true]
+ * Array(["a", "b"]) # => ["a", "b"]
+ * Array(1..5) # => [1, 2, 3, 4, 5]
+ * Array(key: :value) # => [[:key, :value]]
+ * Array(nil) # => []
+ * Array(1) # => [1]
+ * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
*
- * Note that the second argument populates the array with references to the
- * same object. Therefore, it is only recommended in cases when you need to
- * instantiate arrays with natively immutable objects such as Symbols,
- * numbers, true or false.
+ * - \Method Array.new:
*
- * To create an array with separate objects a block can be passed instead.
- * This method is safe to use with mutable objects such as hashes, strings or
- * other arrays:
+ * Array.new # => []
+ * Array.new(3) # => [nil, nil, nil]
+ * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
+ * Array.new(3, true) # => [true, true, true]
*
- * Array.new(4) {Hash.new} #=> [{}, {}, {}, {}]
- * Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
+ * Note that the last example above populates the array
+ * with references to the same object.
+ * This is recommended only in cases where that object is a natively immutable object
+ * such as a symbol, a numeric, +nil+, +true+, or +false+.
*
- * This is also a quick way to build up multi-dimensional arrays:
+ * Another way to create an array with various objects, using a block;
+ * this usage is safe for mutable objects such as hashes, strings or
+ * other arrays:
*
- * empty_table = Array.new(3) {Array.new(3)}
- * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
+ * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
*
- * An array can also be created by using the Array() method, provided by
- * Kernel, which tries to call #to_ary, then #to_a on its argument.
+ * Here is a way to create a multi-dimensional array:
*
- * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
+ * Array.new(3) {Array.new(3)}
+ * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
+ *
+ * A number of Ruby methods, both in the core and in the standard library,
+ * provide instance method +to_a+, which converts an object to an array.
+ *
+ * - ARGF#to_a
+ * - Array#to_a
+ * - Enumerable#to_a
+ * - Hash#to_a
+ * - MatchData#to_a
+ * - NilClass#to_a
+ * - OptionParser#to_a
+ * - Range#to_a
+ * - Set#to_a
+ * - Struct#to_a
+ * - Time#to_a
+ * - Benchmark::Tms#to_a
+ * - CSV::Table#to_a
+ * - Enumerator::Lazy#to_a
+ * - Gem::List#to_a
+ * - Gem::NameTuple#to_a
+ * - Gem::Platform#to_a
+ * - Gem::RequestSet::Lockfile::Tokenizer#to_a
+ * - Gem::SourceList#to_a
+ * - OpenSSL::X509::Extension#to_a
+ * - OpenSSL::X509::Name#to_a
+ * - Racc::ISet#to_a
+ * - Rinda::RingFinger#to_a
+ * - Ripper::Lexer::Elem#to_a
+ * - RubyVM::InstructionSequence#to_a
+ * - YAML::DBM#to_a
*
* == Example Usage
*
* In addition to the methods it mixes in through the Enumerable module, the
- * Array class has proprietary methods for accessing, searching and otherwise
+ * \Array class has proprietary methods for accessing, searching and otherwise
* manipulating arrays.
*
* Some of the more common ones are illustrated below.
@@ -8017,7 +8485,7 @@ rb_ary_deconstruct(VALUE ary)
*
* arr.drop(3) #=> [4, 5, 6]
*
- * == Obtaining Information about an Array
+ * == Obtaining Information about an \Array
*
* Arrays keep track of their own length at all times. To query an array
* about the number of elements it contains, use #length, #count or #size.
@@ -8055,7 +8523,7 @@ rb_ary_deconstruct(VALUE ary)
* arr.insert(3, 'orange', 'pear', 'grapefruit')
* #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
*
- * == Removing Items from an Array
+ * == Removing Items from an \Array
*
* The method #pop removes the last element in an array and returns it:
*
@@ -8097,9 +8565,9 @@ rb_ary_deconstruct(VALUE ary)
*
* == Iterating over Arrays
*
- * Like all classes that include the Enumerable module, Array has an each
+ * Like all classes that include the Enumerable module, \Array has an each
* method, which defines what elements should be iterated over and how. In
- * case of Array's #each, all elements in the Array instance are yielded to
+ * case of Array's #each, all elements in the \Array instance are yielded to
* the supplied block in sequence.
*
* Note that this operation leaves the array unchanged.
@@ -8125,7 +8593,8 @@ rb_ary_deconstruct(VALUE ary)
* arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
* arr #=> [1, 4, 9, 16, 25]
*
- * == Selecting Items from an Array
+ *
+ * == Selecting Items from an \Array
*
* Elements can be selected from an array according to criteria defined in a
* block. The selection can happen in a destructive or a non-destructive
@@ -8160,181 +8629,184 @@ rb_ary_deconstruct(VALUE ary)
*
* First, what's elsewhere. \Class \Array:
*
- * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
- * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
* Here, class \Array provides methods that are useful for:
*
- * - {Creating an Array}[#class-Array-label-Methods+for+Creating+an+Array]
- * - {Querying}[#class-Array-label-Methods+for+Querying]
- * - {Comparing}[#class-Array-label-Methods+for+Comparing]
- * - {Fetching}[#class-Array-label-Methods+for+Fetching]
- * - {Assigning}[#class-Array-label-Methods+for+Assigning]
- * - {Deleting}[#class-Array-label-Methods+for+Deleting]
- * - {Combining}[#class-Array-label-Methods+for+Combining]
- * - {Iterating}[#class-Array-label-Methods+for+Iterating]
- * - {Converting}[#class-Array-label-Methods+for+Converting]
- * - {And more....}[#class-Array-label-Other+Methods]
+ * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
+ * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
+ * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
+ * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
+ * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
+ * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
+ * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
+ * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
+ * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
+ * - {And more....}[rdoc-ref:Array@Other+Methods]
*
- * === Methods for Creating an Array
+ * === Methods for Creating an \Array
*
- * ::[]:: Returns a new array populated with given objects.
- * ::new:: Returns a new array.
- * ::try_convert:: Returns a new array created from a given object.
+ * - ::[]: Returns a new array populated with given objects.
+ * - ::new: Returns a new array.
+ * - ::try_convert: Returns a new array created from a given object.
*
* === Methods for Querying
*
- * #length, #size:: Returns the count of elements.
- * #include?:: Returns whether any element <tt>==</tt> a given object.
- * #empty?:: Returns whether there are no elements.
- * #all?:: Returns whether all elements meet a given criterion.
- * #any?:: Returns whether any element meets a given criterion.
- * #none?:: Returns whether no element <tt>==</tt> a given object.
- * #one?:: Returns whether exactly one element <tt>==</tt> a given object.
- * #count:: Returns the count of elements that meet a given criterion.
- * #find_index, #index:: Returns the index of the first element that meets a given criterion.
- * #rindex:: Returns the index of the last element that meets a given criterion.
- * #hash:: Returns the integer hash code.
+ * - #length, #size: Returns the count of elements.
+ * - #include?: Returns whether any element <tt>==</tt> a given object.
+ * - #empty?: Returns whether there are no elements.
+ * - #all?: Returns whether all elements meet a given criterion.
+ * - #any?: Returns whether any element meets a given criterion.
+ * - #none?: Returns whether no element <tt>==</tt> a given object.
+ * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
+ * - #count: Returns the count of elements that meet a given criterion.
+ * - #find_index, #index: Returns the index of the first element that meets a given criterion.
+ * - #rindex: Returns the index of the last element that meets a given criterion.
+ * - #hash: Returns the integer hash code.
*
* === Methods for Comparing
- * {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1
- * as +self+ is less than, equal to, or greater than a given object.
- * {#==}[#method-i-3D-3D]:: Returns whether each element in +self+ is <tt>==</tt> to the
- * corresponding element in a given object.
- * #eql?:: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
- * element in a given object.
+ *
+ * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or
+ * greater than a given object.
+ * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
+ * in a given object.
+ * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
+ * element in a given object.
* === Methods for Fetching
*
* These methods do not modify +self+.
*
- * #[]:: Returns one or more elements.
- * #fetch:: Returns the element at a given offset.
- * #first:: Returns one or more leading elements.
- * #last:: Returns one or more trailing elements.
- * #max:: Returns one or more maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #max:: Returns one or more minimum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #minmax:: Returns the minimum-valued and maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #assoc:: Returns the first element that is an array
- * whose first element <tt>==</tt> a given object.
- * #rassoc:: Returns the first element that is an array
- * whose second element <tt>==</tt> a given object.
- * #at:: Returns the element at a given offset.
- * #values_at:: Returns the elements at given offsets.
- * #dig:: Returns the object in nested objects
- * that is specified by a given index and additional arguments.
- * #drop:: Returns trailing elements as determined by a given index.
- * #take:: Returns leading elements as determined by a given index.
- * #drop_while:: Returns trailing elements as determined by a given block.
- * #take_while:: Returns leading elements as determined by a given block.
- * #slice:: Returns consecutive elements as determined by a given argument.
- * #sort:: Returns all elements in an order determined by <tt><=></tt> or a given block.
- * #reverse:: Returns all elements in reverse order.
- * #compact:: Returns an array containing all non-+nil+ elements.
- * #select, #filter:: Returns an array containing elements selected by a given block.
- * #uniq:: Returns an array containing non-duplicate elements.
- * #rotate:: Returns all elements with some rotated from one end to the other.
- * #bsearch:: Returns an element selected via a binary search
- * as determined by a given block.
- * #bsearch_index:: Returns the index of an element selected via a binary search
- * as determined by a given block.
- * #sample:: Returns one or more random elements.
- * #shuffle:: Returns elements in a random order.
+ * - #[]: Returns one or more elements.
+ * - #fetch: Returns the element at a given offset.
+ * - #first: Returns one or more leading elements.
+ * - #last: Returns one or more trailing elements.
+ * - #max: Returns one or more maximum-valued elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #min: Returns one or more minimum-valued elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #minmax: Returns the minimum-valued and maximum-valued elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #assoc: Returns the first element that is an array
+ * whose first element <tt>==</tt> a given object.
+ * - #rassoc: Returns the first element that is an array
+ * whose second element <tt>==</tt> a given object.
+ * - #at: Returns the element at a given offset.
+ * - #values_at: Returns the elements at given offsets.
+ * - #dig: Returns the object in nested objects
+ * that is specified by a given index and additional arguments.
+ * - #drop: Returns trailing elements as determined by a given index.
+ * - #take: Returns leading elements as determined by a given index.
+ * - #drop_while: Returns trailing elements as determined by a given block.
+ * - #take_while: Returns leading elements as determined by a given block.
+ * - #slice: Returns consecutive elements as determined by a given argument.
+ * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
+ * - #reverse: Returns all elements in reverse order.
+ * - #compact: Returns an array containing all non-+nil+ elements.
+ * - #select, #filter: Returns an array containing elements selected by a given block.
+ * - #uniq: Returns an array containing non-duplicate elements.
+ * - #rotate: Returns all elements with some rotated from one end to the other.
+ * - #bsearch: Returns an element selected via a binary search
+ * as determined by a given block.
+ * - #bsearch_index: Returns the index of an element selected via a binary search
+ * as determined by a given block.
+ * - #sample: Returns one or more random elements.
+ * - #shuffle: Returns elements in a random order.
*
* === Methods for Assigning
*
* These methods add, replace, or reorder elements in +self+.
*
- * #[]=:: Assigns specified elements with a given object.
- * #push, #append, #<<:: Appends trailing elements.
- * #unshift, #prepend:: Prepends leading elements.
- * #insert:: Inserts given objects at a given offset; does not replace elements.
- * #concat:: Appends all elements from given arrays.
- * #fill:: Replaces specified elements with specified objects.
- * #replace:: Replaces the content of +self+ with the content of a given array.
- * #reverse!:: Replaces +self+ with its elements reversed.
- * #rotate!:: Replaces +self+ with its elements rotated.
- * #shuffle!:: Replaces +self+ with its elements in random order.
- * #sort!:: Replaces +self+ with its elements sorted,
- * as determined by <tt><=></tt> or a given block.
- * #sort_by!:: Replaces +self+ with its elements sorted, as determined by a given block.
+ * - #[]=: Assigns specified elements with a given object.
+ * - #push, #append, #<<: Appends trailing elements.
+ * - #unshift, #prepend: Prepends leading elements.
+ * - #insert: Inserts given objects at a given offset; does not replace elements.
+ * - #concat: Appends all elements from given arrays.
+ * - #fill: Replaces specified elements with specified objects.
+ * - #replace: Replaces the content of +self+ with the content of a given array.
+ * - #reverse!: Replaces +self+ with its elements reversed.
+ * - #rotate!: Replaces +self+ with its elements rotated.
+ * - #shuffle!: Replaces +self+ with its elements in random order.
+ * - #sort!: Replaces +self+ with its elements sorted,
+ * as determined by <tt><=></tt> or a given block.
+ * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
*
* === Methods for Deleting
*
* Each of these methods removes elements from +self+:
*
- * #pop:: Removes and returns the last element.
- * #shift:: Removes and returns the first element.
- * #compact!:: Removes all non-+nil+ elements.
- * #delete:: Removes elements equal to a given object.
- * #delete_at:: Removes the element at a given offset.
- * #delete_if:: Removes elements specified by a given block.
- * #keep_if:: Removes elements not specified by a given block.
- * #reject!:: Removes elements specified by a given block.
- * #select!, #filter!:: Removes elements not specified by a given block.
- * #slice!:: Removes and returns a sequence of elements.
- * #uniq!:: Removes duplicates.
+ * - #pop: Removes and returns the last element.
+ * - #shift: Removes and returns the first element.
+ * - #compact!: Removes all +nil+ elements.
+ * - #delete: Removes elements equal to a given object.
+ * - #delete_at: Removes the element at a given offset.
+ * - #delete_if: Removes elements specified by a given block.
+ * - #keep_if: Removes elements not specified by a given block.
+ * - #reject!: Removes elements specified by a given block.
+ * - #select!, #filter!: Removes elements not specified by a given block.
+ * - #slice!: Removes and returns a sequence of elements.
+ * - #uniq!: Removes duplicates.
*
* === Methods for Combining
*
- * {#&}[#method-i-26]:: Returns an array containing elements found both in +self+ and a given array.
- * #intersection:: Returns an array containing elements found both in +self+
- * and in each given array.
- * #+:: Returns an array containing all elements of +self+ followed by all elements of a given array.
- * #-:: Returns an array containiing all elements of +self+ that are not found in a given array.
- * {#|}[#method-i-7C]:: Returns an array containing all elements of +self+ and all elements of a given array,
- * duplicates removed.
- * #union:: Returns an array containing all elements of +self+ and all elements of given arrays,
- * duplicates removed.
- * #difference:: Returns an array containing all elements of +self+ that are not found
- * in any of the given arrays..
- * #product:: Returns or yields all combinations of elements from +self+ and given arrays.
+ * - #&: Returns an array containing elements found both in +self+ and a given array.
+ * - #intersection: Returns an array containing elements found both in +self+
+ * and in each given array.
+ * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
+ * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
+ * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
+ * duplicates removed.
+ * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
+ * duplicates removed.
+ * - #difference: Returns an array containing all elements of +self+ that are not found
+ * in any of the given arrays..
+ * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
*
* === Methods for Iterating
*
- * #each:: Passes each element to a given block.
- * #reverse_each:: Passes each element, in reverse order, to a given block.
- * #each_index:: Passes each element index to a given block.
- * #cycle:: Calls a given block with each element, then does so again,
- * for a specified number of times, or forever.
- * #combination:: Calls a given block with combinations of elements of +self+;
- * a combination does not use the same element more than once.
- * #permutation:: Calls a given block with permutations of elements of +self+;
- * a permutation does not use the same element more than once.
- * #repeated_combination:: Calls a given block with combinations of elements of +self+;
- * a combination may use the same element more than once.
- * #repeated_permutation:: Calls a given block with permutations of elements of +self+;
- * a permutation may use the same element more than once.
+ * - #each: Passes each element to a given block.
+ * - #reverse_each: Passes each element, in reverse order, to a given block.
+ * - #each_index: Passes each element index to a given block.
+ * - #cycle: Calls a given block with each element, then does so again,
+ * for a specified number of times, or forever.
+ * - #combination: Calls a given block with combinations of elements of +self+;
+ * a combination does not use the same element more than once.
+ * - #permutation: Calls a given block with permutations of elements of +self+;
+ * a permutation does not use the same element more than once.
+ * - #repeated_combination: Calls a given block with combinations of elements of +self+;
+ * a combination may use the same element more than once.
+ * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
+ * a permutation may use the same element more than once.
*
* === Methods for Converting
*
- * #map, #collect:: Returns an array containing the block return-value for each element.
- * #map!, #collect!:: Replaces each element with a block return-value.
- * #flatten:: Returns an array that is a recursive flattening of +self+.
- * #flatten!:: Replaces each nested array in +self+ with the elements from that array.
- * #inspect, #to_s:: Returns a new String containing the elements.
- * #join:: Returns a newsString containing the elements joined by the field separator.
- * #to_a:: Returns +self+ or a new array containing all elements.
- * #to_ary:: Returns +self+.
- * #to_h:: Returns a new hash formed from the elements.
- * #transpose:: Transposes +self+, which must be an array of arrays.
- * #zip:: Returns a new array of arrays containing +self+ and given arrays;
- * follow the link for details.
+ * - #map, #collect: Returns an array containing the block return-value for each element.
+ * - #map!, #collect!: Replaces each element with a block return-value.
+ * - #flatten: Returns an array that is a recursive flattening of +self+.
+ * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
+ * - #inspect, #to_s: Returns a new String containing the elements.
+ * - #join: Returns a newsString containing the elements joined by the field separator.
+ * - #to_a: Returns +self+ or a new array containing all elements.
+ * - #to_ary: Returns +self+.
+ * - #to_h: Returns a new hash formed from the elements.
+ * - #transpose: Transposes +self+, which must be an array of arrays.
+ * - #zip: Returns a new array of arrays containing +self+ and given arrays;
+ * follow the link for details.
*
* === Other Methods
*
- * #*:: Returns one of the following:
- * - With integer argument +n+, a new array that is the concatenation
- * of +n+ copies of +self+.
- * - With string argument +field_separator+, a new string that is equivalent to
- * <tt>join(field_separator)</tt>.
- * #abbrev:: Returns a hash of unambiguous abbreviations for elements.
- * #pack:: Packs the the elements into a binary sequence.
- * #sum:: Returns a sum of elements according to either <tt>+</tt> or a given block.
+ * - #*: Returns one of the following:
+ *
+ * - With integer argument +n+, a new array that is the concatenation
+ * of +n+ copies of +self+.
+ * - With string argument +field_separator+, a new string that is equivalent to
+ * <tt>join(field_separator)</tt>.
+ *
+ * - #abbrev: Returns a hash of unambiguous abbreviations for elements.
+ * - #pack: Packs the elements into a binary sequence.
+ * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
*/
void
@@ -8344,6 +8816,7 @@ Init_Array(void)
rb_include_module(rb_cArray, rb_mEnumerable);
rb_define_alloc_func(rb_cArray, empty_ary_alloc);
+ rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
diff --git a/array.rb b/array.rb
index a43a3b27b1..b9fa9844e6 100644
--- a/array.rb
+++ b/array.rb
@@ -49,6 +49,8 @@ class Array
# But +self+ may contain duplicates:
# a = [1, 1, 1, 2, 2, 3]
# a.sample(a.size * 2) # => [1, 1, 3, 2, 1, 2]
+ # The argument +n+ must be a non-negative numeric value.
+ # The order of the result array is unrelated to the order of +self+.
# Returns a new empty \Array if +self+ is empty.
#
# The optional +random+ argument will be used as the random number generator:
@@ -56,6 +58,12 @@ class Array
# 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)
+ if Primitive.mandatory_only?
+ # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
+ Primitive.ary_sample0
+ else
+ # Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) }
+ Primitive.ary_sample(random, n, ary)
+ end
end
end
diff --git a/ast.c b/ast.c
index 20c4588cd7..adb7287ed3 100644
--- a/ast.c
+++ b/ast.c
@@ -64,8 +64,8 @@ ast_new_internal(rb_ast_t *ast, const NODE *node)
return obj;
}
-static VALUE rb_ast_parse_str(VALUE str, VALUE save_script_lines);
-static VALUE rb_ast_parse_file(VALUE path, VALUE save_script_lines);
+static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
+static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
static VALUE
ast_parse_new(void)
@@ -85,31 +85,33 @@ ast_parse_done(rb_ast_t *ast)
}
static VALUE
-ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE save_script_lines)
+ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- return rb_ast_parse_str(str, save_script_lines);
+ return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
}
static VALUE
-rb_ast_parse_str(VALUE str, VALUE save_script_lines)
+rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
rb_ast_t *ast = 0;
StringValue(str);
VALUE vparser = ast_parse_new();
- if (RTEST(save_script_lines)) rb_parser_save_script_lines(vparser);
+ if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
ast = rb_parser_compile_string_path(vparser, Qnil, str, 1);
return ast_parse_done(ast);
}
static VALUE
-ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE save_script_lines)
+ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- return rb_ast_parse_file(path, save_script_lines);
+ return rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
}
static VALUE
-rb_ast_parse_file(VALUE path, VALUE save_script_lines)
+rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
VALUE f;
rb_ast_t *ast = 0;
@@ -119,7 +121,9 @@ rb_ast_parse_file(VALUE path, VALUE save_script_lines)
f = rb_file_open_str(path, "r");
rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
VALUE vparser = ast_parse_new();
- if (RTEST(save_script_lines)) rb_parser_save_script_lines(vparser);
+ if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
ast = rb_parser_compile_file_path(vparser, Qnil, f, 1);
rb_io_close(f);
return ast_parse_done(ast);
@@ -139,13 +143,15 @@ lex_array(VALUE array, int index)
}
static VALUE
-rb_ast_parse_array(VALUE array, VALUE save_script_lines)
+rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
rb_ast_t *ast = 0;
array = rb_check_array_type(array);
VALUE vparser = ast_parse_new();
- if (RTEST(save_script_lines)) rb_parser_save_script_lines(vparser);
+ if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1);
return ast_parse_done(ast);
}
@@ -193,17 +199,35 @@ script_lines(VALUE path)
}
static VALUE
-ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE save_script_lines)
+node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
{
- VALUE path, node, lines;
+ int node_id;
+
+ if (!rb_frame_info_p(location)) {
+ rb_raise(rb_eTypeError, "Thread::Backtrace::Location object expected");
+ }
+
+ node_id = rb_get_node_id_from_frame_info(location);
+ if (node_id == -1) {
+ return Qnil;
+ }
+
+ return INT2NUM(node_id);
+}
+
+static VALUE
+ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
+{
+ VALUE node, lines = Qnil;
+ const rb_iseq_t *iseq;
int node_id;
if (rb_frame_info_p(body)) {
- rb_frame_info_get(body, &path, &node_id);
- if (NIL_P(path)) return Qnil;
+ iseq = rb_get_iseq_from_frame_info(body);
+ node_id = rb_get_node_id_from_frame_info(body);
}
else {
- const rb_iseq_t *iseq = NULL;
+ iseq = NULL;
if (rb_obj_is_proc(body)) {
iseq = vm_proc_iseq(body);
@@ -213,21 +237,31 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE save_script
else {
iseq = rb_method_iseq(body);
}
- if (rb_iseq_from_eval_p(iseq)) {
- rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
+ if (iseq) {
+ node_id = ISEQ_BODY(iseq)->location.node_id;
}
- path = rb_iseq_path(iseq);
- node_id = iseq->body->location.node_id;
}
- if (!NIL_P(lines = script_lines(path))) {
- node = rb_ast_parse_array(lines, save_script_lines);
+ if (!iseq) {
+ return Qnil;
}
- else if (RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0) {
- node = rb_ast_parse_str(rb_e_script, save_script_lines);
+ lines = ISEQ_BODY(iseq)->variable.script_lines;
+
+ VALUE path = rb_iseq_path(iseq);
+ int e_option = RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0;
+
+ if (NIL_P(lines) && rb_iseq_from_eval_p(iseq) && !e_option) {
+ rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
+ }
+
+ if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) {
+ node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens);
+ }
+ else if (e_option) {
+ node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens);
}
else {
- node = rb_ast_parse_file(path, save_script_lines);
+ node = rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
}
return node_find(node, node_id);
@@ -294,7 +328,7 @@ dump_block(rb_ast_t *ast, const NODE *node)
do {
rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
} while (node->nd_next &&
- nd_type(node->nd_next) == NODE_BLOCK &&
+ nd_type_p(node->nd_next, NODE_BLOCK) &&
(node = node->nd_next, 1));
if (node->nd_next) {
rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
@@ -309,7 +343,7 @@ dump_array(rb_ast_t *ast, const NODE *node)
VALUE ary = rb_ary_new();
rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
- while (node->nd_next && nd_type(node->nd_next) == NODE_LIST) {
+ while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
node = node->nd_next;
rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
}
@@ -366,7 +400,7 @@ node_children(rb_ast_t *ast, const NODE *node)
case NODE_WHILE:
case NODE_UNTIL:
return rb_ary_push(rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body),
- (node->nd_state ? Qtrue : Qfalse));
+ RBOOL(node->nd_state));
case NODE_ITER:
case NODE_FOR:
return rb_ary_new_from_node_args(ast, 2, node->nd_iter, node->nd_body);
@@ -395,7 +429,7 @@ node_children(rb_ast_t *ast, const NODE *node)
while (1) {
rb_ary_push(ary, NEW_CHILD(ast, node->nd_1st));
- if (!node->nd_2nd || nd_type(node->nd_2nd) != (int)type)
+ if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
break;
node = node->nd_2nd;
}
@@ -413,7 +447,6 @@ node_children(rb_ast_t *ast, const NODE *node)
}
case NODE_LASGN:
case NODE_DASGN:
- case NODE_DASGN_CURR:
case NODE_IASGN:
case NODE_CVASGN:
case NODE_GASGN:
@@ -433,7 +466,7 @@ node_children(rb_ast_t *ast, const NODE *node)
NEW_CHILD(ast, node->nd_args->nd_body));
case NODE_OP_ASGN2:
return rb_ary_new_from_args(5, NEW_CHILD(ast, node->nd_recv),
- node->nd_next->nd_aid ? Qtrue : Qfalse,
+ RBOOL(node->nd_next->nd_aid),
ID2SYM(node->nd_next->nd_vid),
ID2SYM(node->nd_next->nd_mid),
NEW_CHILD(ast, node->nd_value));
@@ -596,11 +629,11 @@ node_children(rb_ast_t *ast, const NODE *node)
}
case NODE_SCOPE:
{
- ID *tbl = node->nd_tbl;
- int i, size = tbl ? (int)*tbl++ : 0;
+ rb_ast_id_table_t *tbl = node->nd_tbl;
+ int i, size = tbl ? tbl->size : 0;
VALUE locals = rb_ary_new_capa(size);
for (i = 0; i < size; i++) {
- rb_ary_push(locals, var_name(tbl[i]));
+ rb_ary_push(locals, var_name(tbl->ids[i]));
}
return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, node->nd_args), NEW_CHILD(ast, node->nd_body));
}
@@ -635,6 +668,8 @@ node_children(rb_ast_t *ast, const NODE *node)
NEW_CHILD(ast, node->nd_pkwargs),
kwrest);
}
+ case NODE_ERROR:
+ return rb_ary_new_from_node_args(ast, 0);
case NODE_ARGS_AUX:
case NODE_LAST:
break;
@@ -689,6 +724,15 @@ ast_node_last_column(rb_execution_context_t *ec, VALUE self)
}
static VALUE
+ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTNodeData *data;
+ TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
+
+ return rb_ast_tokens(data->ast);
+}
+
+static VALUE
ast_node_inspect(rb_execution_context_t *ec, VALUE self)
{
VALUE str;
diff --git a/ast.rb b/ast.rb
index 34dd3f1d49..f3f72c747f 100644
--- a/ast.rb
+++ b/ast.rb
@@ -20,21 +20,47 @@
module RubyVM::AbstractSyntaxTree
# call-seq:
- # RubyVM::AbstractSyntaxTree.parse(string) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.parse(string, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
#
# Parses the given _string_ into an abstract syntax tree,
# returning the root node of that tree.
#
- # SyntaxError is raised if the given _string_ is invalid syntax.
- #
# RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-1:9>
- def self.parse string, save_script_lines: false
- Primitive.ast_s_parse string, save_script_lines
+ #
+ # If <tt>keep_script_lines: true</tt> option is provided, the text of the parsed
+ # source is associated with nodes and is available via Node#script_lines.
+ #
+ # If <tt>keep_tokens: true</tt> option is provided, Node#tokens are populated.
+ #
+ # SyntaxError is raised if the given _string_ is invalid syntax. To overwrite this
+ # behavior, <tt>error_tolerant: true</tt> can be provided. In this case, the parser
+ # will produce a tree where expressions with syntax errors would be represented by
+ # Node with <tt>type=:ERROR</tt>.
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1; p(x; y=2")
+ # # <internal:ast>:33:in `parse': syntax error, unexpected ';', expecting ')' (SyntaxError)
+ # # x = 1; p(x; y=2
+ # # ^
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1; p(x; y=2", error_tolerant: true)
+ # # (SCOPE@1:0-1:15
+ # # tbl: [:x, :y]
+ # # args: nil
+ # # body: (BLOCK@1:0-1:15 (LASGN@1:0-1:5 :x (LIT@1:4-1:5 1)) (ERROR@1:7-1:11) (LASGN@1:12-1:15 :y (LIT@1:14-1:15 2))))
+ # root.children.last.children
+ # # [(LASGN@1:0-1:5 :x (LIT@1:4-1:5 1)),
+ # # (ERROR@1:7-1:11),
+ # # (LASGN@1:12-1:15 :y (LIT@1:14-1:15 2))]
+ #
+ # Note that parsing continues even after the errored expresion.
+ #
+ def self.parse string, keep_script_lines: false, error_tolerant: false, keep_tokens: false
+ Primitive.ast_s_parse string, keep_script_lines, error_tolerant, keep_tokens
end
# call-seq:
- # RubyVM::AbstractSyntaxTree.parse_file(pathname) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.parse_file(pathname, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
#
# Reads the file from _pathname_, then parses it like ::parse,
# returning the root node of the abstract syntax tree.
@@ -44,13 +70,15 @@ module RubyVM::AbstractSyntaxTree
#
# RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb")
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-31:3>
- def self.parse_file pathname, save_script_lines: false
- Primitive.ast_s_parse_file pathname, save_script_lines
+ #
+ # See ::parse for explanation of keyword argument meaning and usage.
+ def self.parse_file pathname, keep_script_lines: false, error_tolerant: false, keep_tokens: false
+ Primitive.ast_s_parse_file pathname, keep_script_lines, error_tolerant, keep_tokens
end
# call-seq:
- # RubyVM::AbstractSyntaxTree.of(proc) -> RubyVM::AbstractSyntaxTree::Node
- # RubyVM::AbstractSyntaxTree.of(method) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.of(proc, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.of(method, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
#
# Returns AST nodes of the given _proc_ or _method_.
#
@@ -63,8 +91,25 @@ module RubyVM::AbstractSyntaxTree
#
# RubyVM::AbstractSyntaxTree.of(method(:hello))
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-3:3>
- def self.of body, save_script_lines: false
- Primitive.ast_s_of body, save_script_lines
+ #
+ # See ::parse for explanation of keyword argument meaning and usage.
+ def self.of body, keep_script_lines: false, error_tolerant: false, keep_tokens: false
+ Primitive.ast_s_of body, keep_script_lines, error_tolerant, keep_tokens
+ end
+
+ # call-seq:
+ # RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(backtrace_location) -> integer
+ #
+ # Returns the node id for the given backtrace location.
+ #
+ # begin
+ # raise
+ # rescue => e
+ # loc = e.backtrace_locations.first
+ # RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
+ # end # => 0
+ def self.node_id_for_backtrace_location backtrace_location
+ Primitive.node_id_for_backtrace_location backtrace_location
end
# RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in
@@ -122,6 +167,47 @@ module RubyVM::AbstractSyntaxTree
end
# call-seq:
+ # node.tokens -> array
+ #
+ # Returns tokens corresponding to the location of the node.
+ # Returns +nil+ if +keep_tokens+ is not enabled when #parse method is called.
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true)
+ # root.tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ # root.tokens.map{_1[2]}.join # => "x = 1 + 2"
+ #
+ # Token is an array of:
+ #
+ # - id
+ # - token type
+ # - source code text
+ # - location [ first_lineno, first_column, last_lineno, last_column ]
+ def tokens
+ return nil unless all_tokens
+
+ all_tokens.each_with_object([]) do |token, a|
+ loc = token.last
+ if ([first_lineno, first_column] <=> [loc[0], loc[1]]) <= 0 &&
+ ([last_lineno, last_column] <=> [loc[2], loc[3]]) >= 0
+ a << token
+ end
+ end
+ end
+
+ # call-seq:
+ # node.all_tokens -> array
+ #
+ # Returns all tokens for the input script regardless the receiver node.
+ # Returns +nil+ if +keep_tokens+ is not enabled when #parse method is called.
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true)
+ # root.all_tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ # root.children[-1].all_tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ def all_tokens
+ Primitive.ast_node_all_tokens
+ end
+
+ # call-seq:
# node.children -> array
#
# Returns AST nodes under this one. Each kind of node
diff --git a/autogen.sh b/autogen.sh
index 44a1922cb0..f8cdf3c0c1 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -6,4 +6,12 @@ case "$0" in
*) srcdir="";;
esac
-exec ${AUTORECONF:-autoreconf} --install --symlink "$@" ${srcdir:+"$srcdir"}
+symlink='--install --symlink'
+case " $* " in
+ *" -i "*|*" --install "*)
+ # reset to copy missing standard auxiliary files, instead of symlinks
+ symlink=
+ ;;
+esac
+
+exec ${AUTORECONF:-autoreconf} ${symlink} "$@" ${srcdir:+"$srcdir"}
diff --git a/basictest/test.rb b/basictest/test.rb
index 52008b78db..95875b52a6 100755
--- a/basictest/test.rb
+++ b/basictest/test.rb
@@ -1960,6 +1960,8 @@ test_ok(p1.call == 5)
test_ok(i7 == nil)
end
+# WASI doesn't support spawning a new process for now.
+unless /wasi/ =~ RUBY_PLATFORM
test_check "system"
test_ok(`echo foobar` == "foobar\n")
test_ok(`./miniruby -e 'print "foobar"'` == 'foobar')
@@ -2010,6 +2012,7 @@ test_ok(done)
File.unlink script_tmp or `/bin/rm -f "#{script_tmp}"`
File.unlink "#{script_tmp}.bak" or `/bin/rm -f "#{script_tmp}.bak"`
+end # not /wasi/ =~ RUBY_PLATFORM
test_check "const"
TEST1 = 1
diff --git a/benchmark/README.md b/benchmark/README.md
index c222164be3..e11381cad9 100644
--- a/benchmark/README.md
+++ b/benchmark/README.md
@@ -28,16 +28,18 @@ See also:
```console
Usage: benchmark-driver [options] RUBY|YAML...
- -r, --runner TYPE Specify runner type: ips, time, memory, once (default: ips)
- -o, --output TYPE Specify output type: compare, simple, markdown, record (default: compare)
+ -r, --runner TYPE Specify runner type: ips, time, memory, once, block (default: ips)
+ -o, --output TYPE Specify output type: compare, simple, markdown, record, all (default: compare)
-e, --executables EXECS Ruby executables (e1::path1 arg1; e2::path2 arg2;...)
--rbenv VERSIONS Ruby executables in rbenv (x.x.x arg1;y.y.y arg2;...)
--repeat-count NUM Try benchmark NUM times and use the fastest result or the worst memory usage
--repeat-result TYPE Yield "best", "average" or "worst" result with --repeat-count (default: best)
+ --alternate Alternate executables instead of running the same executable in a row with --repeat-count
--bundler Install and use gems specified in Gemfile
--filter REGEXP Filter out benchmarks with given regexp
--run-duration SECONDS Warmup estimates loop_count to run for this duration (default: 3)
- -v, --verbose Verbose mode. Multiple -v options increase visibility (max: 2)
+ --timeout SECONDS Timeout ruby command execution with timeout(1)
+ -v, --verbose Verbose mode. Multiple -v options increase visilibity (max: 2)
```
## make benchmark
diff --git a/benchmark/array_sample.yml b/benchmark/array_sample.yml
new file mode 100644
index 0000000000..1cd2b34794
--- /dev/null
+++ b/benchmark/array_sample.yml
@@ -0,0 +1,4 @@
+prelude: ary = (1..10_000).to_a
+benchmark:
+ - ary.sample
+ - ary.sample(2)
diff --git a/benchmark/array_sort_int.yml b/benchmark/array_sort_int.yml
new file mode 100644
index 0000000000..7b9027ebf7
--- /dev/null
+++ b/benchmark/array_sort_int.yml
@@ -0,0 +1,15 @@
+prelude: |
+ ary2 = 2.times.to_a.shuffle
+ ary10 = 10.times.to_a.shuffle
+ ary100 = 100.times.to_a.shuffle
+ ary1000 = 1000.times.to_a.shuffle
+ ary10000 = 10000.times.to_a.shuffle
+
+benchmark:
+ ary2.sort: ary2.sort
+ ary10.sort: ary10.sort
+ ary100.sort: ary100.sort
+ ary1000.sort: ary1000.sort
+ ary10000.sort: ary10000.sort
+
+loop_count: 10000
diff --git a/benchmark/attr_accessor.yml b/benchmark/attr_accessor.yml
new file mode 100644
index 0000000000..82134cdf9b
--- /dev/null
+++ b/benchmark/attr_accessor.yml
@@ -0,0 +1,29 @@
+prelude: |
+ class C
+ attr_accessor :x
+ def initialize
+ @x = nil
+ end
+ class_eval <<-END
+ def ar
+ #{'x;'*256}
+ end
+ def aw
+ #{'self.x = nil;'*256}
+ end
+ def arm
+ m = method(:x)
+ #{'m.call;'*256}
+ end
+ def awm
+ m = method(:x=)
+ #{'m.call(nil);'*256}
+ end
+ END
+ end
+ obj = C.new
+benchmark:
+ attr_reader: "obj.ar"
+ attr_writer: "obj.aw"
+ attr_reader_method: "obj.arm"
+ attr_writer_method: "obj.awm"
diff --git a/benchmark/buffer_each.yml b/benchmark/buffer_each.yml
new file mode 100644
index 0000000000..417941104e
--- /dev/null
+++ b/benchmark/buffer_each.yml
@@ -0,0 +1,27 @@
+prelude: |
+ # frozen_string_literal: true
+ Warning[:experimental] = false
+ string = "The quick brown fox jumped over the lazy dog."
+ array = string.bytes
+ buffer = IO::Buffer.for(string)
+benchmark:
+ string.each_byte: |
+ upcased = String.new
+ string.each_byte do |byte|
+ upcased << (byte ^ 32)
+ end
+ array.each: |
+ upcased = String.new
+ array.each do |byte|
+ upcased << (byte ^ 32)
+ end
+ buffer.each: |
+ upcased = String.new
+ buffer.each(:U8) do |offset, byte|
+ upcased << (byte ^ 32)
+ end
+ buffer.each_byte: |
+ upcased = String.new
+ buffer.each_byte do |byte|
+ upcased << (byte ^ 32)
+ end
diff --git a/benchmark/buffer_get.yml b/benchmark/buffer_get.yml
new file mode 100644
index 0000000000..9e1f99d64e
--- /dev/null
+++ b/benchmark/buffer_get.yml
@@ -0,0 +1,25 @@
+prelude: |
+ # frozen_string_literal: true
+ Warning[:experimental] = false
+ string = "The quick brown fox jumped over the lazy dog."
+ buffer = IO::Buffer.for(string)
+ format = [:U32, :U32, :U32, :U32]
+benchmark:
+ string.unpack1: |
+ [
+ string.unpack1("N"),
+ string.unpack1("N", offset: 4),
+ string.unpack1("N", offset: 8),
+ string.unpack1("N", offset: 12),
+ ]
+ buffer.get_value: |
+ [
+ buffer.get_value(:U32, 0),
+ buffer.get_value(:U32, 4),
+ buffer.get_value(:U32, 8),
+ buffer.get_value(:U32, 12),
+ ]
+ buffer.get_values: |
+ buffer.get_values(format, 0)
+ string.unpack: |
+ string.unpack("NNNN")
diff --git a/benchmark/cgi_escape_html.yml b/benchmark/cgi_escape_html.yml
index af6abd08ac..655be9d7d8 100644
--- a/benchmark/cgi_escape_html.yml
+++ b/benchmark/cgi_escape_html.yml
@@ -1,32 +1,23 @@
-prelude: require 'cgi/escape'
+prelude: |
+ # frozen_string_literal: true
+ require 'cgi/escape'
benchmark:
- - name: escape_html_blank
- prelude: str = ""
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("")
loop_count: 20000000
- - name: escape_html_short_none
- prelude: str = "abcde"
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("abcde")
loop_count: 20000000
- - name: escape_html_short_one
- prelude: str = "abcd<"
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("abcd<")
loop_count: 20000000
- - name: escape_html_short_all
- prelude: str = "'&\"<>"
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("'&\"<>")
loop_count: 5000000
- - name: escape_html_long_none
- prelude: str = "abcde" * 300
- script: CGI.escapeHTML(str)
+ - prelude: long_no_escape = "abcde" * 300
+ script: CGI.escapeHTML(long_no_escape)
loop_count: 1000000
- - name: escape_html_long_all
- prelude: str = "'&\"<>" * 10
- script: CGI.escapeHTML(str)
+ - prelude: long_all_escape = "'&\"<>" * 10
+ script: CGI.escapeHTML(long_all_escape)
loop_count: 1000000
- - name: escape_html_real
- prelude: | # http://example.com/
- str = <<~HTML
+ - prelude: | # http://example.com/
+ example_html = <<~HTML
<body>
<div>
<h1>Example Domain</h1>
@@ -36,5 +27,5 @@ benchmark:
</div>
</body>
HTML
- script: CGI.escapeHTML(str)
+ script: CGI.escapeHTML(example_html)
loop_count: 1000000
diff --git a/benchmark/constant_invalidation.rb b/benchmark/constant_invalidation.rb
new file mode 100644
index 0000000000..a95ec6f37e
--- /dev/null
+++ b/benchmark/constant_invalidation.rb
@@ -0,0 +1,22 @@
+$VERBOSE = nil
+
+CONSTANT1 = 1
+CONSTANT2 = 1
+CONSTANT3 = 1
+CONSTANT4 = 1
+CONSTANT5 = 1
+
+def constants
+ [CONSTANT1, CONSTANT2, CONSTANT3, CONSTANT4, CONSTANT5]
+end
+
+500_000.times do
+ constants
+
+ # With previous behavior, this would cause all of the constant caches
+ # associated with the constant lookups listed above to invalidate, meaning
+ # they would all have to be fetched again. With current behavior, it only
+ # invalidates when a name matches, so the following constant set shouldn't
+ # impact the constant lookups listed above.
+ INVALIDATE = true
+end
diff --git a/benchmark/enum_minmax.yml b/benchmark/enum_minmax.yml
new file mode 100644
index 0000000000..9d01731abb
--- /dev/null
+++ b/benchmark/enum_minmax.yml
@@ -0,0 +1,25 @@
+prelude: |
+ set2 = 2.times.to_a.shuffle.to_set
+ set10 = 10.times.to_a.shuffle.to_set
+ set100 = 100.times.to_a.shuffle.to_set
+ set1000 = 1000.times.to_a.shuffle.to_set
+ set10000 = 10000.times.to_a.shuffle.to_set
+
+benchmark:
+ set2.min: set2.min
+ set10.min: set10.min
+ set100.min: set100.min
+ set1000.min: set1000.min
+ set10000.min: set10000.min
+ set2.max: set2.max
+ set10.max: set10.max
+ set100.max: set100.max
+ set1000.max: set1000.max
+ set10000.max: set10000.max
+ set2.minmax: set2.minmax
+ set10.minmax: set10.minmax
+ set100.minmax: set100.minmax
+ set1000.minmax: set1000.minmax
+ set10000.minmax: set10000.minmax
+
+loop_count: 10000
diff --git a/benchmark/enum_sort.yml b/benchmark/enum_sort.yml
new file mode 100644
index 0000000000..6f26e748c6
--- /dev/null
+++ b/benchmark/enum_sort.yml
@@ -0,0 +1,15 @@
+prelude: |
+ set2 = 2.times.to_a.shuffle.to_set
+ set10 = 10.times.to_a.shuffle.to_set
+ set100 = 100.times.to_a.shuffle.to_set
+ set1000 = 1000.times.to_a.shuffle.to_set
+ set10000 = 10000.times.to_a.shuffle.to_set
+
+benchmark:
+ set2.sort_by: set2.sort_by { 0 }
+ set10.sort_by: set10.sort_by { 0 }
+ set100.sort_by: set100.sort_by { 0 }
+ set1000.sort_by: set1000.sort_by { 0 }
+ set10000.sort_by: set10000.sort_by { 0 }
+
+loop_count: 10000
diff --git a/benchmark/erb_escape_html.yml b/benchmark/erb_escape_html.yml
new file mode 100644
index 0000000000..ca28d756e7
--- /dev/null
+++ b/benchmark/erb_escape_html.yml
@@ -0,0 +1,31 @@
+prelude: |
+ # frozen_string_literal: true
+ require 'erb'
+benchmark:
+ - script: ERB::Util.html_escape("")
+ loop_count: 20000000
+ - script: ERB::Util.html_escape("abcde")
+ loop_count: 20000000
+ - script: ERB::Util.html_escape("abcd<")
+ loop_count: 20000000
+ - script: ERB::Util.html_escape("'&\"<>")
+ loop_count: 5000000
+ - prelude: long_no_escape = "abcde" * 300
+ script: ERB::Util.html_escape(long_no_escape)
+ loop_count: 1000000
+ - prelude: long_all_escape = "'&\"<>" * 10
+ script: ERB::Util.html_escape(long_all_escape)
+ loop_count: 1000000
+ - prelude: | # http://example.com/
+ example_html = <<~HTML
+ <body>
+ <div>
+ <h1>Example Domain</h1>
+ <p>This domain is established to be used for illustrative examples in documents. You may use this
+ domain in examples without prior coordination or asking for permission.</p>
+ <p><a href="http://www.iana.org/domains/example">More information...</a></p>
+ </div>
+ </body>
+ HTML
+ script: ERB::Util.html_escape(example_html)
+ loop_count: 1000000
diff --git a/benchmark/hash_aref_array.rb b/benchmark/hash_aref_array.rb
new file mode 100644
index 0000000000..ac7a683d95
--- /dev/null
+++ b/benchmark/hash_aref_array.rb
@@ -0,0 +1,5 @@
+h = {}
+arrays = (0..99).each_slice(10).to_a
+#STDERR.puts arrays.inspect
+arrays.each { |s| h[s] = s }
+200_000.times { arrays.each { |s| h[s] } }
diff --git a/benchmark/io_write.rb b/benchmark/io_write.rb
new file mode 100644
index 0000000000..cdb409948b
--- /dev/null
+++ b/benchmark/io_write.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+
+require 'benchmark'
+
+i, o = IO.pipe
+o.sync = true
+
+DOT = ".".freeze
+
+chunks = 100_000.times.collect{DOT}
+
+thread = Thread.new do
+ while i.read(1024)
+ end
+end
+
+100.times do
+ o.write(*chunks)
+end
+
+o.close
+thread.join
diff --git a/benchmark/lib/benchmark_driver/runner/mjit.rb b/benchmark/lib/benchmark_driver/runner/mjit.rb
index abefa463b3..3a58a620de 100644
--- a/benchmark/lib/benchmark_driver/runner/mjit.rb
+++ b/benchmark/lib/benchmark_driver/runner/mjit.rb
@@ -14,17 +14,17 @@ class BenchmarkDriver::Runner::Mjit < BenchmarkDriver::Runner::Ips
jobs.map do |job|
job = job.dup
job.prelude = "#{job.prelude}\n#{<<~EOS}"
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
__bmdv_ruby_i = 0
- while __bmdv_ruby_i < 10000 # jit_min_calls
+ while __bmdv_ruby_i < 10000 # MJIT call threshold
#{job.script}
__bmdv_ruby_i += 1
end
- RubyVM::JIT.pause # compile
+ RubyVM::MJIT.pause # compile
#{job.script}
- RubyVM::JIT.resume; RubyVM::JIT.pause # recompile
+ RubyVM::MJIT.resume; RubyVM::MJIT.pause # recompile
#{job.script}
- RubyVM::JIT.resume; RubyVM::JIT.pause # recompile 2
+ RubyVM::MJIT.resume; RubyVM::MJIT.pause # recompile 2
end
EOS
job
diff --git a/benchmark/lib/benchmark_driver/runner/mjit_exec.rb b/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
deleted file mode 100644
index 46e662bc7c..0000000000
--- a/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
+++ /dev/null
@@ -1,237 +0,0 @@
-require 'benchmark_driver/struct'
-require 'benchmark_driver/metric'
-require 'erb'
-
-# A special runner dedicated for measuring mjit_exec overhead.
-class BenchmarkDriver::Runner::MjitExec
- METRIC = BenchmarkDriver::Metric.new(name: 'Iteration per second', unit: 'i/s')
-
- # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job"
- Job = ::BenchmarkDriver::Struct.new(
- :name, # @param [String] name - This is mandatory for all runner
- :metrics, # @param [Array<BenchmarkDriver::Metric>]
- :num_methods, # @param [Integer] num_methods - The number of methods to be defined
- :loop_count, # @param [Integer] loop_count
- :from_jit, # @param [TrueClass,FalseClass] from_jit - Whether the mjit_exec() is from JIT or not
- :to_jit, # @param [TrueClass,FalseClass] to_jit - Whether the mjit_exec() is to JIT or not
- )
- # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
- class << JobParser = Module.new
- # @param [Array,String] num_methods
- # @param [Integer] loop_count
- # @param [TrueClass,FalseClass] from_jit
- # @param [TrueClass,FalseClass] to_jit
- def parse(num_methods:, loop_count:, from_jit:, to_jit:)
- if num_methods.is_a?(String)
- num_methods = eval(num_methods)
- end
-
- num_methods.map do |num|
- if num_methods.size > 1
- suffix = "[#{'%4d' % num}]"
- else
- suffix = "_#{num}"
- end
- Job.new(
- name: "mjit_exec_#{from_jit ? 'JT' : 'VM'}2#{to_jit ? 'JT' : 'VM'}#{suffix}",
- metrics: [METRIC],
- num_methods: num,
- loop_count: loop_count,
- from_jit: from_jit,
- to_jit: to_jit,
- )
- end
- end
- end
-
- # @param [BenchmarkDriver::Config::RunnerConfig] config
- # @param [BenchmarkDriver::Output] output
- # @param [BenchmarkDriver::Context] contexts
- def initialize(config:, output:, contexts:)
- @config = config
- @output = output
- @contexts = contexts
- end
-
- # This method is dynamically called by `BenchmarkDriver::JobRunner.run`
- # @param [Array<BenchmarkDriver::Runner::Peak::Job>] jobs
- def run(jobs)
- @output.with_benchmark do
- jobs.each do |job|
- @output.with_job(name: job.name) do
- @contexts.each do |context|
- result = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: true, rest_on_average: :average) do
- run_benchmark(job, context: context)
- end
- value, duration = result.value
- @output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do
- @output.report(values: { METRIC => value }, duration: duration, loop_count: job.loop_count)
- end
- end
- end
- end
- end
- end
-
- private
-
- # @param [BenchmarkDriver::Runner::Ips::Job] job - loop_count is not nil
- # @param [BenchmarkDriver::Context] context
- # @return [BenchmarkDriver::Metrics]
- def run_benchmark(job, context:)
- if job.from_jit
- if job.to_jit
- benchmark = BenchmarkJT2JT.new(num_methods: job.num_methods, loop_count: job.loop_count)
- else
- raise NotImplementedError, "JT2VM is not implemented yet"
- end
- else
- if job.to_jit
- benchmark = BenchmarkVM2JT.new(num_methods: job.num_methods, loop_count: job.loop_count)
- else
- benchmark = BenchmarkVM2VM.new(num_methods: job.num_methods, loop_count: job.loop_count)
- end
- end
-
- duration = Tempfile.open(['benchmark_driver-result', '.txt']) do |f|
- with_script(benchmark.render(result: f.path)) do |path|
- opt = []
- if context.executable.command.any? { |c| c.start_with?('--jit') }
- opt << '--jit-min-calls=2'
- end
- IO.popen([*context.executable.command, '--disable-gems', *opt, path], &:read)
- if $?.success?
- Float(f.read)
- else
- BenchmarkDriver::Result::ERROR
- end
- end
- end
-
- [job.loop_count.to_f / duration, duration]
- end
-
- def with_script(script)
- if @config.verbose >= 2
- sep = '-' * 30
- $stdout.puts "\n\n#{sep}[Script begin]#{sep}\n#{script}#{sep}[Script end]#{sep}\n\n"
- end
-
- Tempfile.open(['benchmark_driver-', '.rb']) do |f|
- f.puts script
- f.close
- return yield(f.path)
- end
- end
-
- # @param [Integer] num_methods
- # @param [Integer] loop_count
- BenchmarkVM2VM = ::BenchmarkDriver::Struct.new(:num_methods, :loop_count) do
- # @param [String] result - A file to write result
- def render(result:)
- ERB.new(<<~EOS, trim_mode: '%').result(binding)
- % num_methods.times do |i|
- def a<%= i %>
- nil
- end
- % end
- RubyVM::JIT.pause if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
-
- def vm
- t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- i = 0
- while i < <%= loop_count / 1000 %>
- % 1000.times do |i|
- a<%= i % num_methods %>
- % end
- i += 1
- end
- % (loop_count % 1000).times do |i|
- a<%= i % num_methods %>
- % end
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - t
- end
-
- vm # warmup call cache
- File.write(<%= result.dump %>, vm)
- EOS
- end
- end
- private_constant :BenchmarkVM2VM
-
- # @param [Integer] num_methods
- # @param [Integer] loop_count
- BenchmarkVM2JT = ::BenchmarkDriver::Struct.new(:num_methods, :loop_count) do
- # @param [String] result - A file to write result
- def render(result:)
- ERB.new(<<~EOS, trim_mode: '%').result(binding)
- % num_methods.times do |i|
- def a<%= i %>
- nil
- end
- a<%= i %>
- a<%= i %> # --jit-min-calls=2
- % end
- RubyVM::JIT.pause if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
-
- def vm
- t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- i = 0
- while i < <%= loop_count / 1000 %>
- % 1000.times do |i|
- a<%= i % num_methods %>
- % end
- i += 1
- end
- % (loop_count % 1000).times do |i|
- a<%= i % num_methods %>
- % end
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - t
- end
-
- vm # warmup call cache
- File.write(<%= result.dump %>, vm)
- EOS
- end
- end
- private_constant :BenchmarkVM2JT
-
- # @param [Integer] num_methods
- # @param [Integer] loop_count
- BenchmarkJT2JT = ::BenchmarkDriver::Struct.new(:num_methods, :loop_count) do
- # @param [String] result - A file to write result
- def render(result:)
- ERB.new(<<~EOS, trim_mode: '%').result(binding)
- % num_methods.times do |i|
- def a<%= i %>
- nil
- end
- % end
-
- # You may need to:
- # * Increase `JIT_ISEQ_SIZE_THRESHOLD` to 10000000 in mjit.h
- # * Always return false in `inlinable_iseq_p()` of mjit_compile.c
- def jit
- t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- i = 0
- while i < <%= loop_count / 1000 %>
- % 1000.times do |i|
- a<%= i % num_methods %>
- % end
- i += 1
- end
- % (loop_count % 1000).times do |i|
- a<%= i % num_methods %>
- % end
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - t
- end
-
- jit
- jit
- RubyVM::JIT.pause if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
- File.write(<%= result.dump %>, jit)
- EOS
- end
- end
- private_constant :BenchmarkJT2JT
-end
diff --git a/benchmark/marshal_dump_load_integer.yml b/benchmark/marshal_dump_load_integer.yml
new file mode 100644
index 0000000000..78ebf823d2
--- /dev/null
+++ b/benchmark/marshal_dump_load_integer.yml
@@ -0,0 +1,22 @@
+prelude: |
+ smallint_array = 1000.times.map { |x| x }
+ bigint32_array = 1000.times.map { |x| x + 2**32 }
+ bigint64_array = 1000.times.map { |x| x + 2**64 }
+
+ smallint_dump = Marshal.dump(smallint_array)
+ bigint32_dump = Marshal.dump(bigint32_array)
+ bigint64_dump = Marshal.dump(bigint64_array)
+benchmark:
+ marshal_dump_integer_small: |
+ Marshal.dump(smallint_array)
+ marshal_dump_integer_over_32_bit: |
+ Marshal.dump(bigint32_array)
+ marshal_dump_integer_over_64_bit: |
+ Marshal.dump(bigint64_array)
+ marshal_load_integer_small: |
+ Marshal.load(smallint_dump)
+ marshal_load_integer_over_32_bit: |
+ Marshal.load(bigint32_dump)
+ marshal_load_integer_over_64_bit: |
+ Marshal.load(bigint64_dump)
+loop_count: 4000
diff --git a/benchmark/masgn.yml b/benchmark/masgn.yml
index 4be9333e23..31cb8ee4a3 100644
--- a/benchmark/masgn.yml
+++ b/benchmark/masgn.yml
@@ -1,7 +1,7 @@
prelude: |
a = [nil] * 3
b = Class.new{attr_writer :a, :b, :c}.new
- c, d, e, f = nil, nil, nil, nil
+ c = d = e = f = g = h = i = nil
benchmark:
array2_2: "c = (a[0], a[1] = 1, 2)"
array2_3: "c = (a[0], a[1] = 1, 2, 3)"
@@ -27,3 +27,27 @@ benchmark:
lvar2_3p: "(d, e = 1, 2, 3; nil)"
lvar3_2p: "(d, e, f = 1, 2; nil)"
lvar3_3p: "(d, e, f = 1, 2, 3; nil)"
+ array2_2lv: "c = (a[0], a[1] = g, h)"
+ array2_ilv: "c = (a[0], a[1] = g, h, i)"
+ arrayi_2lv: "c = (a[0], a[1], a[2] = g, h)"
+ arrayi_ilv: "c = (a[0], a[1], a[2] = g, h, i)"
+ attr2_2lv: "c = (b.a, b.b = g, h)"
+ attr2_ilv: "c = (b.a, b.b = g, h, i)"
+ attri_2lv: "c = (b.a, b.b, b.c = g, h)"
+ attri_ilv: "c = (b.a, b.b, b.c = g, h, i)"
+ lvar2_2lv: "c = (d, e = g, h)"
+ lvar2_ilv: "c = (d, e = g, h, i)"
+ lvari_2lv: "c = (d, e, f = g, h)"
+ lvari_ilv: "c = (d, e, f = g, h, i)"
+ array2_2plv: "(a[0], a[1] = g, h; nil)"
+ array2_iplv: "(a[0], a[1] = g, h, i; nil)"
+ arrayi_2plv: "(a[0], a[1], a[2] = g, h; nil)"
+ arrayi_iplv: "(a[0], a[1], a[2] = g, h, i; nil)"
+ attr2_2plv: "(b.a, b.b = g, h; nil)"
+ attr2_iplv: "(b.a, b.b = g, h, i; nil)"
+ attri_2plv: "(b.a, b.b, b.c = g, h; nil)"
+ attri_iplv: "(b.a, b.b, b.c = g, h, i; nil)"
+ lvar2_2plv: "(d, e = g, h; nil)"
+ lvar2_iplv: "(d, e = g, h, i; nil)"
+ lvari_2plv: "(d, e, f = g, h; nil)"
+ lvari_iplv: "(d, e, f = g, h, i; nil)"
diff --git a/benchmark/mjit_exec_jt2jt.yml b/benchmark/mjit_exec_jt2jt.yml
deleted file mode 100644
index 6c303c7a44..0000000000
--- a/benchmark/mjit_exec_jt2jt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-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
-from_jit: true
-to_jit: true
diff --git a/benchmark/mjit_exec_vm2jt.yml b/benchmark/mjit_exec_vm2jt.yml
deleted file mode 100644
index 764883f070..0000000000
--- a/benchmark/mjit_exec_vm2jt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-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
-from_jit: false
-to_jit: true
diff --git a/benchmark/mjit_exec_vm2vm.yml b/benchmark/mjit_exec_vm2vm.yml
deleted file mode 100644
index 030aa76c1c..0000000000
--- a/benchmark/mjit_exec_vm2vm.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-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
-from_jit: false
-to_jit: false
diff --git a/benchmark/module_eqq.yml b/benchmark/module_eqq.yml
new file mode 100644
index 0000000000..a561fb86dc
--- /dev/null
+++ b/benchmark/module_eqq.yml
@@ -0,0 +1,27 @@
+prelude: |
+ class SimpleClass; end
+ class MediumClass
+ 10.times { include Module.new }
+ end
+ class LargeClass
+ 100.times { include Module.new }
+ end
+ class HugeClass
+ 300.times { include Module.new }
+ end
+ SimpleObj = SimpleClass.new
+ MediumObj = MediumClass.new
+ LargeObj = LargeClass.new
+ HugeObj = HugeClass.new
+benchmark:
+ simple_class_eqq_simple_obj: |
+ SimpleClass === SimpleObj
+ medium_class_eqq_simple_obj: |
+ MediumClass === SimpleObj
+ simple_class_eqq_medium_obj: |
+ SimpleClass === MediumObj
+ simple_class_eqq_large_obj: |
+ SimpleClass === LargeObj
+ simple_class_eqq_huge_obj: |
+ SimpleClass === HugeObj
+loop_count: 20000000
diff --git a/benchmark/numeric_methods.yml b/benchmark/numeric_methods.yml
index 433c2268a3..1384902935 100644
--- a/benchmark/numeric_methods.yml
+++ b/benchmark/numeric_methods.yml
@@ -10,4 +10,20 @@ benchmark:
int.finite?
infinite?: |
int.infinite?
+ integer_real: |
+ int.real
+ float_real: |
+ flo.real
+ integr_imag: |
+ int.imag
+ float_imag: |
+ flo.imag
+ integer_conj: |
+ int.conj
+ float_conj: |
+ flo.conj
+ integer_numerator: |
+ int.numerator
+ integer_denominator: |
+ int.denominator
loop_count: 20000000
diff --git a/benchmark/range_min.yml b/benchmark/range_min.yml
new file mode 100644
index 0000000000..9e60dd7308
--- /dev/null
+++ b/benchmark/range_min.yml
@@ -0,0 +1,2 @@
+benchmark:
+ - (1..10).min
diff --git a/benchmark/so_nbody.rb b/benchmark/so_nbody.rb
index d6c5bb9e61..9884fc4edc 100644
--- a/benchmark/so_nbody.rb
+++ b/benchmark/so_nbody.rb
@@ -12,38 +12,38 @@ def _puts *args
end
class Planet
- attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass
+ attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass
- def initialize(x, y, z, vx, vy, vz, mass)
- @x, @y, @z = x, y, z
- @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
- @mass = mass * SOLAR_MASS
- end
-
- def move_from_i(bodies, nbodies, dt, i)
- while i < nbodies
- b2 = bodies[i]
- dx = @x - b2.x
- dy = @y - b2.y
- dz = @z - b2.z
-
- distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
- mag = dt / (distance * distance * distance)
- b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
-
- @vx -= dx * b2_mass_mag
- @vy -= dy * b2_mass_mag
- @vz -= dz * b2_mass_mag
- b2.vx += dx * b_mass_mag
- b2.vy += dy * b_mass_mag
- b2.vz += dz * b_mass_mag
- i += 1
+ def initialize(x, y, z, vx, vy, vz, mass)
+ @x, @y, @z = x, y, z
+ @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
+ @mass = mass * SOLAR_MASS
end
- @x += dt * @vx
- @y += dt * @vy
- @z += dt * @vz
- end
+ def move_from_i(bodies, nbodies, dt, i)
+ while i < nbodies
+ b2 = bodies[i]
+ dx = @x - b2.x
+ dy = @y - b2.y
+ dz = @z - b2.z
+
+ distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
+ mag = dt / (distance * distance * distance)
+ b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
+
+ @vx -= dx * b2_mass_mag
+ @vy -= dy * b2_mass_mag
+ @vz -= dz * b2_mass_mag
+ b2.vx += dx * b_mass_mag
+ b2.vy += dy * b_mass_mag
+ b2.vz += dz * b_mass_mag
+ i += 1
+ end
+
+ @x += dt * @vx
+ @y += dt * @vy
+ @z += dt * @vz
+ end
end
def energy(bodies)
diff --git a/benchmark/string_concat.yml b/benchmark/string_concat.yml
new file mode 100644
index 0000000000..e65c00cca9
--- /dev/null
+++ b/benchmark/string_concat.yml
@@ -0,0 +1,45 @@
+prelude: |
+ CHUNK = "a" * 64
+ UCHUNK = "é" * 32
+ GC.disable # GC causes a lot of variance
+benchmark:
+ binary_concat_7bit: |
+ buffer = String.new(capacity: 4096, encoding: Encoding::BINARY)
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ utf8_concat_7bit: |
+ buffer = String.new(capacity: 4096, encoding: Encoding::UTF_8)
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ utf8_concat_UTF8: |
+ buffer = String.new(capacity: 4096, encoding: Encoding::UTF_8)
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ interpolation: |
+ buffer = "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}"
diff --git a/benchmark/time_at.yml b/benchmark/time_at.yml
new file mode 100644
index 0000000000..3247efbe77
--- /dev/null
+++ b/benchmark/time_at.yml
@@ -0,0 +1,7 @@
+prelude: |
+ # frozen_string_literal: true
+benchmark:
+ - 'Time.at(0)'
+ - 'Time.at(0, 500)'
+ - 'Time.at(0, in: "+09:00")'
+ - 'Time.at(0, 500, in: "+09:00")'
diff --git a/benchmark/time_new.yml b/benchmark/time_new.yml
new file mode 100644
index 0000000000..5947dd3a41
--- /dev/null
+++ b/benchmark/time_new.yml
@@ -0,0 +1,4 @@
+benchmark:
+ - 'Time.new(2021)'
+ - 'Time.new(2021, 8, 22)'
+ - 'Time.new(2021, 8, 22, in: "+09:00")'
diff --git a/benchmark/time_now.yml b/benchmark/time_now.yml
new file mode 100644
index 0000000000..f6d6a31489
--- /dev/null
+++ b/benchmark/time_now.yml
@@ -0,0 +1,3 @@
+benchmark:
+ - 'Time.now'
+ - 'Time.now(in: "+09:00")'
diff --git a/benchmark/time_parse.yml b/benchmark/time_parse.yml
new file mode 100644
index 0000000000..6060b58bc6
--- /dev/null
+++ b/benchmark/time_parse.yml
@@ -0,0 +1,10 @@
+prelude: |
+ require 'time'
+ inspect = "2021-08-23 09:57:02 +0900"
+ iso8601 = "2021-08-23T09:57:02+09:00"
+benchmark:
+ - Time.iso8601(iso8601)
+ - Time.parse(iso8601)
+ - Time.parse(inspect)
+ - Time.new(iso8601) rescue Time.iso8601(iso8601)
+ - Time.new(inspect) rescue Time.parse(inspect)
diff --git a/benchmark/vm_const.yml b/benchmark/vm_const.yml
index 6064d4eed0..8939ca0cd3 100644
--- a/benchmark/vm_const.yml
+++ b/benchmark/vm_const.yml
@@ -1,7 +1,13 @@
prelude: |
Const = 1
+ A = B = C = D = E = F = G = H = I = J = K = L = M = N = O = P = Q = R = S = T = U = V = W = X = Y = Z = 1
+ def foo
+ A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P; Q; R; S; T; U; V; W; X; Y; Z
+ end
benchmark:
vm_const: |
j = Const
k = Const
+ vm_const_many: |
+ foo
loop_count: 30000000
diff --git a/benchmark/vm_dstr_ary.rb b/benchmark/vm_dstr_ary.rb
new file mode 100644
index 0000000000..1d3aa3b97b
--- /dev/null
+++ b/benchmark/vm_dstr_ary.rb
@@ -0,0 +1,6 @@
+i = 0
+x = y = []
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_bool.rb b/benchmark/vm_dstr_bool.rb
new file mode 100644
index 0000000000..631ca54755
--- /dev/null
+++ b/benchmark/vm_dstr_bool.rb
@@ -0,0 +1,7 @@
+i = 0
+x = true
+y = false
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_class_module.rb b/benchmark/vm_dstr_class_module.rb
new file mode 100644
index 0000000000..becf0861c7
--- /dev/null
+++ b/benchmark/vm_dstr_class_module.rb
@@ -0,0 +1,10 @@
+i = 0
+class A; end unless defined?(A)
+module B; end unless defined?(B)
+x = A
+y = B
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
+
diff --git a/benchmark/vm_dstr_digit.rb b/benchmark/vm_dstr_digit.rb
new file mode 100644
index 0000000000..caaa395192
--- /dev/null
+++ b/benchmark/vm_dstr_digit.rb
@@ -0,0 +1,7 @@
+i = 0
+x = 0
+y = 9
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_int.rb b/benchmark/vm_dstr_int.rb
new file mode 100644
index 0000000000..ed380d7595
--- /dev/null
+++ b/benchmark/vm_dstr_int.rb
@@ -0,0 +1,5 @@
+i = 0
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{i}bar#{i}baz"
+end
diff --git a/benchmark/vm_dstr_nil.rb b/benchmark/vm_dstr_nil.rb
new file mode 100644
index 0000000000..ec4f5d6c67
--- /dev/null
+++ b/benchmark/vm_dstr_nil.rb
@@ -0,0 +1,6 @@
+i = 0
+x = y = nil
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_obj.rb b/benchmark/vm_dstr_obj.rb
new file mode 100644
index 0000000000..fb78637ead
--- /dev/null
+++ b/benchmark/vm_dstr_obj.rb
@@ -0,0 +1,6 @@
+i = 0
+x = y = Object.new
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_obj_def.rb b/benchmark/vm_dstr_obj_def.rb
new file mode 100644
index 0000000000..99ff7b98fb
--- /dev/null
+++ b/benchmark/vm_dstr_obj_def.rb
@@ -0,0 +1,8 @@
+i = 0
+o = Object.new
+def o.to_s; -""; end
+x = y = o
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_str.rb b/benchmark/vm_dstr_str.rb
new file mode 100644
index 0000000000..45fc107892
--- /dev/null
+++ b/benchmark/vm_dstr_str.rb
@@ -0,0 +1,6 @@
+i = 0
+x = y = ""
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_dstr_sym.rb b/benchmark/vm_dstr_sym.rb
new file mode 100644
index 0000000000..484b8f8150
--- /dev/null
+++ b/benchmark/vm_dstr_sym.rb
@@ -0,0 +1,6 @@
+i = 0
+x = y = :z
+while i<6_000_000 # benchmark loop 2
+ i += 1
+ str = "foo#{x}bar#{y}baz"
+end
diff --git a/benchmark/vm_freezeobj.yml b/benchmark/vm_freezeobj.yml
new file mode 100644
index 0000000000..69a795a354
--- /dev/null
+++ b/benchmark/vm_freezeobj.yml
@@ -0,0 +1,6 @@
+prelude: |
+ objs = 100000.times.map { Object.new }
+benchmark:
+ vm_freeze_obj: |
+ objs.map(&:freeze)
+loop_count: 600
diff --git a/benchmark/vm_ivar_embedded_obj_init.yml b/benchmark/vm_ivar_embedded_obj_init.yml
new file mode 100644
index 0000000000..74fe20a630
--- /dev/null
+++ b/benchmark/vm_ivar_embedded_obj_init.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C
+ def set_ivars
+ @a = nil
+ @b = nil
+ @c = nil
+ end
+ end
+
+ c = C.new
+benchmark:
+ vm_ivar_embedded_obj_init: |
+ c.set_ivars
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_init.yml b/benchmark/vm_ivar_extended_obj_init.yml
index c6f1633907..f054bab282 100644
--- a/benchmark/vm_ivar_init.yml
+++ b/benchmark/vm_ivar_extended_obj_init.yml
@@ -1,6 +1,6 @@
prelude: |
class C
- def initialize
+ def set_ivars
@a = nil
@b = nil
@c = nil
@@ -8,7 +8,9 @@ prelude: |
@e = nil
end
end
+
+ c = C.new
benchmark:
- vm_ivar_init: |
- C.new
+ vm_ivar_extended_obj_init: |
+ c.set_ivars
loop_count: 30000000
diff --git a/benchmark/vm_ivar_generic_get.yml b/benchmark/vm_ivar_generic_get.yml
new file mode 100644
index 0000000000..dae2d37671
--- /dev/null
+++ b/benchmark/vm_ivar_generic_get.yml
@@ -0,0 +1,17 @@
+prelude: |
+ class C < Array
+ attr_reader :a, :b, :c
+ def initialize
+ @a = nil
+ @b = nil
+ @c = nil
+ end
+ end
+
+ c = C.new
+benchmark:
+ vm_ivar_generic_get: |
+ c.a
+ c.b
+ c.c
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_generic_set.yml b/benchmark/vm_ivar_generic_set.yml
new file mode 100644
index 0000000000..102a6577fb
--- /dev/null
+++ b/benchmark/vm_ivar_generic_set.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C < Array
+ def set_ivars
+ @a = nil
+ @b = nil
+ @c = nil
+ end
+ end
+
+ c = C.new
+benchmark:
+ vm_ivar_generic_set: |
+ c.set_ivars
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_get.yml b/benchmark/vm_ivar_get.yml
new file mode 100644
index 0000000000..9174af6965
--- /dev/null
+++ b/benchmark/vm_ivar_get.yml
@@ -0,0 +1,37 @@
+prelude: |
+ class Example
+ def initialize
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
+ @levar = 1
+ end
+
+ def get_value_loop
+ sum = 0
+
+ i = 0
+ while i < 1000000
+ # 10 times to de-emphasize loop overhead
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ i += 1
+ end
+
+ return sum
+ end
+ end
+
+ obj = Example.new
+benchmark:
+ vm_ivar_get: |
+ obj.get_value_loop
+loop_count: 100
diff --git a/benchmark/vm_ivar_get_unintialized.yml b/benchmark/vm_ivar_get_unintialized.yml
new file mode 100644
index 0000000000..a1ccfb06ce
--- /dev/null
+++ b/benchmark/vm_ivar_get_unintialized.yml
@@ -0,0 +1,12 @@
+prelude: |
+ class Example
+ def read
+ @uninitialized
+ end
+ end
+
+ obj = Example.new
+benchmark:
+ vm_ivar_get_uninitialized: |
+ obj.read
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_lazy_set.yml b/benchmark/vm_ivar_lazy_set.yml
new file mode 100644
index 0000000000..7372ffcfbc
--- /dev/null
+++ b/benchmark/vm_ivar_lazy_set.yml
@@ -0,0 +1,12 @@
+prelude: |
+ class Example
+ def lazy_set
+ @uninitialized ||= 123
+ end
+ end
+
+ objs = 10000000.times.map { Example.new }
+benchmark:
+ vm_ivar_lazy_set: |
+ objs.each(&:lazy_set)
+loop_count: 1
diff --git a/benchmark/vm_ivar_of_class.yml b/benchmark/vm_ivar_of_class.yml
new file mode 100644
index 0000000000..172e28b2fd
--- /dev/null
+++ b/benchmark/vm_ivar_of_class.yml
@@ -0,0 +1,12 @@
+prelude: |
+ class C
+ @a = 1
+ def self.a
+ _a = @a; _a = @a; _a = @a; _a = @a; _a = @a;
+ _a = @a; _a = @a; _a = @a; _a = @a; _a = @a;
+ end
+ end
+benchmark:
+ vm_ivar_of_class: |
+ a = C.a
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_of_class_set.yml b/benchmark/vm_ivar_of_class_set.yml
new file mode 100644
index 0000000000..2ea5199423
--- /dev/null
+++ b/benchmark/vm_ivar_of_class_set.yml
@@ -0,0 +1,11 @@
+prelude: |
+ class C
+ @a = 1
+ def self.a o
+ @a = o; @a = o; @a = o; @a = o; @a = o; @a = o;
+ end
+ end
+benchmark:
+ vm_ivar_of_class_set: |
+ a = C.a(nil)
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_set_on_instance.yml b/benchmark/vm_ivar_set_on_instance.yml
new file mode 100644
index 0000000000..91857b7742
--- /dev/null
+++ b/benchmark/vm_ivar_set_on_instance.yml
@@ -0,0 +1,35 @@
+prelude: |
+ class TheClass
+ def initialize
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
+ @levar = 1
+ end
+
+ def set_value_loop
+ # 1M
+ i = 0
+ while i < 1000000
+ # 10 times to de-emphasize loop overhead
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ i += 1
+ end
+ end
+ end
+
+ obj = TheClass.new
+
+benchmark:
+ vm_ivar_set_on_instance: |
+ obj.set_value_loop
+loop_count: 100
diff --git a/benchmark/vm_ivar_set_subclass.yml b/benchmark/vm_ivar_set_subclass.yml
index 2653d36ded..bc8bf5bf6b 100644
--- a/benchmark/vm_ivar_set_subclass.yml
+++ b/benchmark/vm_ivar_set_subclass.yml
@@ -1,6 +1,6 @@
prelude: |
class A
- def initialize
+ def set_ivars
@a = nil
@b = nil
@c = nil
@@ -10,8 +10,11 @@ prelude: |
end
class B < A; end
class C < A; end
+
+ b = B.new
+ c = C.new
benchmark:
vm_ivar_init_subclass: |
- B.new
- C.new
+ b.set_ivars
+ c.set_ivars
loop_count: 3000000
diff --git a/benchmark/vm_lvar_cond_set.yml b/benchmark/vm_lvar_cond_set.yml
new file mode 100644
index 0000000000..1845f9d12e
--- /dev/null
+++ b/benchmark/vm_lvar_cond_set.yml
@@ -0,0 +1,8 @@
+benchmark:
+ vm_lvar_cond_set: |
+ a ||= 1
+ b ||= 1
+ c ||= 1
+ d ||= 1
+ nil
+loop_count: 30000000
diff --git a/bignum.c b/bignum.c
index da5df41f97..cb2c3b6f07 100644
--- a/bignum.c
+++ b/bignum.c
@@ -23,8 +23,14 @@
# include <ieeefp.h>
#endif
+#if !defined(USE_GMP)
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
-# define USE_GMP
+# define USE_GMP 1
+#else
+# define USE_GMP 0
+#endif
+#endif
+#if USE_GMP
# include <gmp.h>
#endif
@@ -36,15 +42,12 @@
#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)
-
const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#ifndef SIZEOF_BDIGIT_DBL
@@ -102,8 +105,8 @@ STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
#endif
#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
- (BDIGITS(x)[0] == 0 && \
- (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
+ (BDIGITS(x)[0] == 0 && \
+ (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
(size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
@@ -148,7 +151,7 @@ STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
#define GMP_DIV_DIGITS 20
#define GMP_BIG2STR_DIGITS 20
#define GMP_STR2BIG_DIGITS 20
-#ifdef USE_GMP
+#if USE_GMP
# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
#else
# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
@@ -416,9 +419,9 @@ bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
assert(0 <= shift && shift < BITSPERDIG);
for (i=0; i<n; i++) {
- num = num | (BDIGIT_DBL)*xds++ << shift;
- *zds++ = BIGLO(num);
- num = BIGDN(num);
+ num = num | (BDIGIT_DBL)*xds++ << shift;
+ *zds++ = BIGLO(num);
+ num = BIGDN(num);
}
return BIGLO(num);
}
@@ -434,9 +437,9 @@ bary_small_rshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift, BDIGIT hi
num = BIGUP(higher_bdigit);
for (i = 0; i < n; i++) {
BDIGIT x = xds[n - i - 1];
- num = (num | x) >> shift;
+ num = (num | x) >> shift;
zds[n - i - 1] = BIGLO(num);
- num = BIGUP(x);
+ num = BIGUP(x);
}
}
@@ -446,7 +449,7 @@ bary_zero_p(const BDIGIT *xds, size_t xn)
if (xn == 0)
return 1;
do {
- if (xds[--xn]) return 0;
+ if (xds[--xn]) return 0;
} while (xn);
return 1;
}
@@ -463,7 +466,6 @@ static int
bary_2comp(BDIGIT *ds, size_t n)
{
size_t i;
- i = 0;
for (i = 0; i < n; i++) {
if (ds[i] != 0) {
goto non_zero;
@@ -975,7 +977,7 @@ integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails,
{
/* nlp_bits stands for number of leading padding bits */
size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
- size_t num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG;
+ size_t num_bdigits = roomof(num_bits, BITSPERDIG);
*nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
return num_bdigits;
}
@@ -985,7 +987,7 @@ integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nail
{
/* BITSPERDIG = SIZEOF_BDIGIT * CHAR_BIT */
/* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
- /* num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG */
+ /* num_bdigits = roomof(num_bits, BITSPERDIG) */
/* num_bits = CHAR_BIT * (wordsize * numwords) - nails * numwords = CHAR_BIT * num_bytes1 - nails * numwords */
size_t num_bytes1 = wordsize * numwords;
@@ -1348,9 +1350,9 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
num = borrow ? -1 : 0;
for (i = 0; i < sn; i++) {
- num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
if (yn <= xn) {
for (; i < xn; i++) {
@@ -1369,7 +1371,7 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
}
if (num == 0) goto num_is_zero;
for (; i < zn; i++) {
- zds[i] = BDIGMAX;
+ zds[i] = BDIGMAX;
}
return 1;
@@ -1377,10 +1379,10 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
if (xds == zds && xn == zn)
return 0;
for (; i < xn; i++) {
- zds[i] = xds[i];
+ zds[i] = xds[i];
}
for (; i < zn; i++) {
- zds[i] = 0;
+ zds[i] = 0;
}
return 0;
}
@@ -1407,27 +1409,27 @@ bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
assert(yn <= zn);
if (xn > yn) {
- const BDIGIT *tds;
- tds = xds; xds = yds; yds = tds;
- i = xn; xn = yn; yn = i;
+ const BDIGIT *tds;
+ tds = xds; xds = yds; yds = tds;
+ i = xn; xn = yn; yn = i;
}
num = carry ? 1 : 0;
for (i = 0; i < xn; i++) {
- num += (BDIGIT_DBL)xds[i] + yds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += (BDIGIT_DBL)xds[i] + yds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
for (; i < yn; i++) {
if (num == 0) goto num_is_zero;
- num += yds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += yds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
for (; i < zn; i++) {
if (num == 0) goto num_is_zero;
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
return num != 0;
@@ -1435,10 +1437,10 @@ bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
if (yds == zds && yn == zn)
return 0;
for (; i < yn; i++) {
- zds[i] = yds[i];
+ zds[i] = yds[i];
}
for (; i < zn; i++) {
- zds[i] = 0;
+ zds[i] = 0;
}
return 0;
}
@@ -1577,7 +1579,7 @@ rb_big_mul_normal(VALUE x, VALUE y)
/* efficient squaring (2 times faster than normal multiplication)
* ref: Handbook of Applied Cryptography, Algorithm 14.16
- * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * https://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
*/
static void
bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
@@ -1595,30 +1597,30 @@ bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
return;
for (i = 0; i < xn-1; i++) {
- v = (BDIGIT_DBL)xds[i];
- if (!v)
+ v = (BDIGIT_DBL)xds[i];
+ if (!v)
continue;
- c = (BDIGIT_DBL)zds[i + i] + v * v;
- zds[i + i] = BIGLO(c);
- c = BIGDN(c);
- v *= 2;
+ c = (BDIGIT_DBL)zds[i + i] + v * v;
+ zds[i + i] = BIGLO(c);
+ c = BIGDN(c);
+ v *= 2;
vl = BIGLO(v);
vh = (int)BIGDN(v);
- for (j = i + 1; j < xn; j++) {
- w = (BDIGIT_DBL)xds[j];
- c += (BDIGIT_DBL)zds[i + j] + vl * w;
- zds[i + j] = BIGLO(c);
- c = BIGDN(c);
- if (vh)
+ for (j = i + 1; j < xn; j++) {
+ w = (BDIGIT_DBL)xds[j];
+ c += (BDIGIT_DBL)zds[i + j] + vl * w;
+ zds[i + j] = BIGLO(c);
+ c = BIGDN(c);
+ if (vh)
c += w;
- }
- if (c) {
- c += (BDIGIT_DBL)zds[i + xn];
- zds[i + xn] = BIGLO(c);
- c = BIGDN(c);
+ }
+ if (c) {
+ c += (BDIGIT_DBL)zds[i + xn];
+ zds[i + xn] = BIGLO(c);
+ c = BIGDN(c);
if (c)
zds[i + xn + 1] += (BDIGIT)c;
- }
+ }
}
/* i == xn-1 */
@@ -1643,13 +1645,21 @@ rb_big_sq_fast(VALUE x)
return z;
}
+static inline size_t
+max_size(size_t a, size_t b)
+{
+ return (a > b ? a : b);
+}
+
/* balancing multiplication by slicing larger argument */
static void
-bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn, mulfunc_t *mulfunc)
+bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
+ const BDIGIT *const xds, const size_t xn,
+ const BDIGIT *const yds, const size_t yn,
+ BDIGIT *wds, size_t wn, mulfunc_t *const mulfunc)
{
VALUE work = 0;
- size_t yn0 = yn;
- size_t r, n;
+ size_t n;
assert(xn + yn <= zn);
assert(xn <= yn);
@@ -1657,14 +1667,26 @@ bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t
BDIGITS_ZERO(zds, xn);
+ if (wn < xn) {
+ /* The condition when a new buffer is needed:
+ * 1. (2(xn+r) > zn-(yn-r)) => (2xn+r > zn-yn), at the last
+ * iteration (or r == 0)
+ * 2. (2(xn+xn) > zn-(yn-r-xn)) => (3xn-r > zn-yn), at the
+ * previous iteration.
+ */
+ const size_t r = yn % xn;
+ if (2*xn + yn + max_size(xn-r, r) > zn) {
+ wn = xn;
+ wds = ALLOCV_N(BDIGIT, work, wn);
+ }
+ }
+
n = 0;
- while (yn > 0) {
- BDIGIT *tds;
- size_t tn;
- r = xn > yn ? yn : xn;
- tn = xn + r;
+ while (yn > n) {
+ const size_t r = (xn > (yn - n) ? (yn - n) : xn);
+ const size_t tn = (xn + r);
if (2 * (xn + r) <= zn - n) {
- tds = zds + n + xn + r;
+ BDIGIT *const tds = zds + n + xn + r;
mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
BDIGITS_ZERO(zds + n + xn, r);
bary_add(zds + n, tn,
@@ -1672,21 +1694,25 @@ bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t
tds, tn);
}
else {
+ BDIGIT *const tds = zds + n;
if (wn < xn) {
+ /* xn is invariant, only once here */
+#if 0
wn = xn;
wds = ALLOCV_N(BDIGIT, work, wn);
+#else
+ rb_bug("wds is not enough: %" PRIdSIZE " for %" PRIdSIZE, wn, xn);
+#endif
}
- tds = zds + n;
MEMCPY(wds, zds + n, BDIGIT, xn);
mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
bary_add(zds + n, tn,
zds + n, tn,
wds, xn);
}
- yn -= r;
- n += r;
+ n += r;
}
- BDIGITS_ZERO(zds+xn+yn0, zn - (xn+yn0));
+ BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
if (work)
ALLOCV_END(work);
@@ -2076,21 +2102,21 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI
v3n = u3n; v3ds = u3ds; v3p = u3p;
}
else {
- /* v1 <- y0 + y2 */
+ /* v1 <- y0 + y2 */
bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
v1p = 1;
- /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
+ /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
v2p = 1;
if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
bary_2comp(v2ds, v2n);
v2p = 0;
}
- /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
+ /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
- /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
+ /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
v3p = 1;
if (v2p) {
bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
@@ -2283,7 +2309,7 @@ rb_big_mul_toom3(VALUE x, VALUE y)
return z;
}
-#ifdef USE_GMP
+#if USE_GMP
static inline void
bdigits_to_mpz(mpz_t mp, const BDIGIT *digits, size_t len)
{
@@ -2421,8 +2447,8 @@ bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp,
if (xn > yn) {
const BDIGIT *tds;
size_t tn;
- tds = xds; xds = yds; yds = tds;
- tn = xn; xn = yn; yn = tn;
+ tds = xds; xds = yds; yds = tds;
+ tn = xn; xn = yn; yn = tn;
}
assert(xn <= yn);
@@ -2548,7 +2574,7 @@ bary_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds
}
}
-#ifdef USE_GMP
+#if USE_GMP
bary_mul_gmp(zds, zn, xds, xn, yds, yn);
#else
bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
@@ -2572,26 +2598,26 @@ bigdivrem1(void *ptr)
BDIGIT q;
do {
- if (bds->stop) {
- bds->zn = zn;
- return 0;
+ if (bds->stop) {
+ bds->zn = zn;
+ return 0;
}
- if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
- else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
- if (q) {
+ if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
+ else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
+ if (q) {
num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
q,
yds, yn);
- while (num) { /* "add back" required */
- q--;
+ while (num) { /* "add back" required */
+ q--;
num = bary_add(zds+zn-(yn+1), yn,
zds+zn-(yn+1), yn,
yds, yn);
num--;
- }
- }
+ }
+ }
zn--;
- zds[zn] = q;
+ zds[zn] = q;
} while (zn > yn);
return 0;
}
@@ -2660,16 +2686,16 @@ bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
bds.zn = zn - ynzero;
if (bds.zn > 10000 || bds.yn > 10000) {
retry:
- bds.stop = Qfalse;
+ bds.stop = Qfalse;
rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE);
- if (bds.stop == Qtrue) {
- /* execute trap handler, but exception was not raised. */
- goto retry;
- }
+ if (bds.stop == Qtrue) {
+ /* execute trap handler, but exception was not raised. */
+ goto retry;
+ }
}
else {
- bigdivrem1(&bds);
+ bigdivrem1(&bds);
}
}
@@ -2768,7 +2794,7 @@ rb_big_divrem_normal(VALUE x, VALUE y)
return rb_assoc_new(q, r);
}
-#ifdef USE_GMP
+#if USE_GMP
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)
{
@@ -2852,7 +2878,7 @@ rb_big_divrem_gmp(VALUE x, VALUE y)
static void
bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
-#ifdef USE_GMP
+#if USE_GMP
if (GMP_DIV_DIGITS < xn) {
bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
return;
@@ -2927,7 +2953,7 @@ int
rb_cmpint(VALUE val, VALUE a, VALUE b)
{
if (NIL_P(val)) {
- rb_cmperr(a, b);
+ rb_cmperr(a, b);
}
if (FIXNUM_P(val)) {
long l = FIX2LONG(val);
@@ -2936,9 +2962,9 @@ rb_cmpint(VALUE val, VALUE a, VALUE b)
return 0;
}
if (RB_BIGNUM_TYPE_P(val)) {
- if (BIGZEROP(val)) return 0;
- if (BIGNUM_SIGN(val)) return 1;
- return -1;
+ if (BIGZEROP(val)) return 0;
+ if (BIGNUM_SIGN(val)) return 1;
+ return -1;
}
if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
@@ -2948,8 +2974,8 @@ rb_cmpint(VALUE val, VALUE a, VALUE b)
#define BIGNUM_SET_LEN(b,l) \
(BIGNUM_EMBED_P(b) ? \
(void)(RBASIC(b)->flags = \
- (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
- ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
+ (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
+ ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
(void)(RBIGNUM(b)->as.heap.len = (l)))
static void
@@ -2957,33 +2983,33 @@ rb_big_realloc(VALUE big, size_t len)
{
BDIGIT *ds;
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;
+ 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;
FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG);
- }
+ }
}
else {
- if (len <= BIGNUM_EMBED_LEN_MAX) {
- ds = RBIGNUM(big)->as.heap.digits;
+ if (len <= BIGNUM_EMBED_LEN_MAX) {
+ ds = RBIGNUM(big)->as.heap.digits;
FL_SET_RAW(big, BIGNUM_EMBED_FLAG);
- BIGNUM_SET_LEN(big, len);
+ BIGNUM_SET_LEN(big, len);
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
- if (ds) {
- MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
- xfree(ds);
- }
- }
- else {
- if (BIGNUM_LEN(big) == 0) {
- RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
- }
- else {
- REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
- }
- }
+ if (ds) {
+ MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
+ xfree(ds);
+ }
+ }
+ else {
+ if (BIGNUM_LEN(big) == 0) {
+ RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
+ }
+ else {
+ REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
+ }
+ }
}
}
@@ -3069,7 +3095,7 @@ abs2twocomp(VALUE *xp, long *n_ret)
MEMCPY(BDIGITS(z), ds, BDIGIT, n);
bary_2comp(BDIGITS(z), n);
hibits = BDIGMAX;
- *xp = z;
+ *xp = z;
}
*n_ret = n;
return hibits;
@@ -3093,7 +3119,7 @@ bigtrunc(VALUE x)
if (len == 0) return x;
while (--len && !ds[len]);
if (BIGNUM_LEN(x) > len+1) {
- rb_big_resize(x, len+1);
+ rb_big_resize(x, len+1);
}
return x;
}
@@ -3146,7 +3172,7 @@ static VALUE
bignorm(VALUE x)
{
if (RB_BIGNUM_TYPE_P(x)) {
- x = bigfixize(x);
+ x = bigfixize(x);
}
return x;
}
@@ -3168,8 +3194,8 @@ rb_uint2big(uintptr_t n)
digits[0] = n;
#else
for (i = 0; i < bdigit_roomof(SIZEOF_VALUE); i++) {
- digits[i] = BIGLO(n);
- n = BIGDN(n);
+ digits[i] = BIGLO(n);
+ n = BIGDN(n);
}
#endif
@@ -3188,14 +3214,14 @@ rb_int2big(intptr_t n)
if (n < 0) {
u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
- neg = 1;
+ neg = 1;
}
else {
u = n;
}
big = rb_uint2big(u);
if (neg) {
- BIGNUM_SET_NEGATIVE_SIGN(big);
+ BIGNUM_SET_NEGATIVE_SIGN(big);
}
return big;
}
@@ -3354,7 +3380,7 @@ absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_num
if (sign == 2) {
#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
- *nlz_bits_ret = 0;
+ *nlz_bits_ret = 0;
#endif
return (size_t)-1;
}
@@ -3674,7 +3700,7 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na
}
else if (num_bdigits == numberof(fixbuf)) {
val = bignew((long)num_bdigits+1, 0);
- MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
+ MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
BDIGITS(val)[num_bdigits++] = 1;
}
else {
@@ -3686,9 +3712,9 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na
BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
if (u == 0)
return LONG2FIX(0);
- if (0 < sign && POSFIXABLE(u))
+ if (0 < sign && POSFIXABLE(u))
return LONG2FIX((long)u);
- if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
+ if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u))
return LONG2FIX((long)-(BDIGIT_DBL_SIGNED)u);
val = bignew((long)num_bdigits, 0 <= sign);
@@ -3740,41 +3766,41 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size
int c;
if (!len) {
- *num_digits_p = 0;
- *len_p = 0;
- return TRUE;
+ *num_digits_p = 0;
+ *len_p = 0;
+ return TRUE;
}
if (badcheck && *str == '_') return FALSE;
while ((c = *str++) != 0) {
- if (c == '_') {
- if (nondigit) {
+ if (c == '_') {
+ if (nondigit) {
if (badcheck) return FALSE;
- break;
- }
- nondigit = (char) c;
- }
- else if ((c = conv_digit(c)) < 0 || c >= base) {
- break;
- }
- else {
- nondigit = 0;
- num_digits++;
- digits_end = str;
- }
- if (len > 0 && !--len) break;
+ break;
+ }
+ nondigit = (char) c;
+ }
+ else if ((c = conv_digit(c)) < 0 || c >= base) {
+ break;
+ }
+ else {
+ nondigit = 0;
+ num_digits++;
+ digits_end = str;
+ }
+ if (len > 0 && !--len) break;
}
if (badcheck && nondigit) return FALSE;
if (badcheck && len) {
- str--;
- while (*str && ISSPACE(*str)) {
- str++;
- if (len > 0 && !--len) break;
- }
- if (len && *str) {
- return FALSE;
- }
+ str--;
+ while (*str && ISSPACE(*str)) {
+ str++;
+ if (len > 0 && !--len) break;
+ }
+ if (len && *str) {
+ return FALSE;
+ }
}
*num_digits_p = num_digits;
*len_p = digits_end - digits_start;
@@ -3949,7 +3975,7 @@ str2big_karatsuba(
return z;
}
-#ifdef USE_GMP
+#if USE_GMP
static VALUE
str2big_gmp(
int sign,
@@ -4016,8 +4042,8 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
char *end;
VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
if (NIL_P(ret)) {
- if (badcheck) rb_invalid_str(str, "Integer()");
- ret = INT2FIX(0);
+ if (badcheck) rb_invalid_str(str, "Integer()");
+ ret = INT2FIX(0);
}
return ret;
}
@@ -4041,7 +4067,7 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
VALUE
rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
- int base, int flags)
+ int base, int flags)
{
const char *const s = str;
char sign = 1;
@@ -4058,82 +4084,82 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
const int badcheck = !endp;
#define ADV(n) do {\
- if (len > 0 && len <= (n)) goto bad; \
- str += (n); \
- len -= (n); \
+ if (len > 0 && len <= (n)) goto bad; \
+ str += (n); \
+ len -= (n); \
} while (0)
#define ASSERT_LEN() do {\
- assert(len != 0); \
- if (len0 >= 0) assert(s + len0 == str + len); \
+ assert(len != 0); \
+ if (len0 >= 0) assert(s + len0 == str + len); \
} while (0)
if (!str) {
goto bad;
}
if (len && (flags & RB_INT_PARSE_SIGN)) {
- while (ISSPACE(*str)) ADV(1);
+ while (ISSPACE(*str)) ADV(1);
- if (str[0] == '+') {
- ADV(1);
- }
- else if (str[0] == '-') {
- ADV(1);
- sign = 0;
- }
- ASSERT_LEN();
+ if (str[0] == '+') {
+ ADV(1);
+ }
+ else if (str[0] == '-') {
+ ADV(1);
+ sign = 0;
+ }
+ ASSERT_LEN();
}
if (base <= 0) {
- if (str[0] == '0' && len > 1) {
- switch (str[1]) {
- case 'x': case 'X':
- base = 16;
- ADV(2);
- break;
- case 'b': case 'B':
- base = 2;
- ADV(2);
- break;
- case 'o': case 'O':
- base = 8;
- ADV(2);
- break;
- case 'd': case 'D':
- base = 10;
- ADV(2);
- break;
- default:
- base = 8;
- }
- }
- else if (base < -1) {
- base = -base;
- }
- else {
- base = 10;
- }
+ if (str[0] == '0' && len > 1) {
+ switch (str[1]) {
+ case 'x': case 'X':
+ base = 16;
+ ADV(2);
+ break;
+ case 'b': case 'B':
+ base = 2;
+ ADV(2);
+ break;
+ case 'o': case 'O':
+ base = 8;
+ ADV(2);
+ break;
+ case 'd': case 'D':
+ base = 10;
+ ADV(2);
+ break;
+ default:
+ base = 8;
+ }
+ }
+ else if (base < -1) {
+ base = -base;
+ }
+ else {
+ base = 10;
+ }
}
else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
- /* no prefix */
+ /* no prefix */
}
else if (base == 2) {
- if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
+ ADV(2);
+ }
}
else if (base == 8) {
- if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
+ ADV(2);
+ }
}
else if (base == 10) {
- if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
+ ADV(2);
+ }
}
else if (base == 16) {
- if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
+ ADV(2);
+ }
}
if (!valid_radix_p(base)) {
invalid_radix(base);
@@ -4141,80 +4167,79 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
if (!len) goto bad;
num_digits = str - s;
if (*str == '0' && len != 1) { /* squeeze preceding 0s */
- int us = 0;
- const char *end = len < 0 ? NULL : str + len;
- ++num_digits;
- while ((c = *++str) == '0' ||
- ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
- if (c == '_') {
- if (++us >= 2)
- break;
- }
- else {
- ++num_digits;
- us = 0;
- }
- if (str == end) break;
- }
- if (!c || ISSPACE(c)) --str;
- if (end) len = end - str;
- ASSERT_LEN();
+ int us = 0;
+ const char *end = len < 0 ? NULL : str + len;
+ ++num_digits;
+ while ((c = *++str) == '0' ||
+ ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
+ if (c == '_') {
+ if (++us >= 2)
+ break;
+ }
+ else {
+ ++num_digits;
+ us = 0;
+ }
+ if (str == end) break;
+ }
+ if (!c || ISSPACE(c)) --str;
+ if (end) len = end - str;
}
c = *str;
c = conv_digit(c);
if (c < 0 || c >= base) {
- if (!badcheck && num_digits) z = INT2FIX(0);
- goto bad;
+ if (!badcheck && num_digits) z = INT2FIX(0);
+ goto bad;
}
if (ndigits) *ndigits = num_digits;
val = ruby_scan_digits(str, len, base, &num_digits, &ov);
if (!ov) {
- const char *end = &str[num_digits];
- if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
- goto bigparse;
- if (endp) *endp = (char *)end;
- if (ndigits) *ndigits += num_digits;
- if (badcheck) {
- if (num_digits == 0) return Qnil; /* no number */
- while (len < 0 ? *end : end < str + len) {
- if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
- end++;
- }
- }
-
- if (POSFIXABLE(val)) {
- if (sign) return LONG2FIX(val);
- else {
- long result = -(long)val;
- return LONG2FIX(result);
- }
- }
- else {
- VALUE big = rb_uint2big(val);
- BIGNUM_SET_SIGN(big, sign);
- return bignorm(big);
- }
+ const char *end = &str[num_digits];
+ if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
+ goto bigparse;
+ if (endp) *endp = (char *)end;
+ if (ndigits) *ndigits += num_digits;
+ if (badcheck) {
+ if (num_digits == 0) return Qnil; /* no number */
+ while (len < 0 ? *end : end < str + len) {
+ if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
+ end++;
+ }
+ }
+
+ if (POSFIXABLE(val)) {
+ if (sign) return LONG2FIX(val);
+ else {
+ long result = -(long)val;
+ return LONG2FIX(result);
+ }
+ }
+ else {
+ VALUE big = rb_uint2big(val);
+ BIGNUM_SET_SIGN(big, sign);
+ return bignorm(big);
+ }
}
bigparse:
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- goto bad;
+ goto bad;
if (endp) *endp = (char *)(str + len);
if (ndigits) *ndigits += num_digits;
digits_end = digits_start + len;
if (POW2_P(base)) {
z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
- bit_length(base-1));
+ bit_length(base-1));
}
else {
int digits_per_bdigits_dbl;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
-#ifdef USE_GMP
+#if USE_GMP
if (GMP_STR2BIG_DIGITS < num_bdigits) {
z = str2big_gmp(sign, digits_start, digits_end, num_digits,
num_bdigits, base);
@@ -4243,7 +4268,7 @@ static VALUE
rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
{
return rb_int_parse_cstr(str, len, endp, NULL, base,
- RB_INT_PARSE_DEFAULT);
+ RB_INT_PARSE_DEFAULT);
}
VALUE
@@ -4292,14 +4317,14 @@ rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
s = str = StringValueCStr(arg);
len = RSTRING_LEN(arg);
if (*str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
@@ -4331,14 +4356,14 @@ rb_str2big_normal(VALUE arg, int base, int badcheck)
s = str = StringValuePtr(arg);
len = RSTRING_LEN(arg);
if (len > 0 && *str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
@@ -4373,14 +4398,14 @@ rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
s = str = StringValuePtr(arg);
len = RSTRING_LEN(arg);
if (len > 0 && *str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
@@ -4394,7 +4419,7 @@ rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
return bignorm(z);
}
-#ifdef USE_GMP
+#if USE_GMP
VALUE
rb_str2big_gmp(VALUE arg, int base, int badcheck)
{
@@ -4416,14 +4441,14 @@ rb_str2big_gmp(VALUE arg, int base, int badcheck)
s = str = StringValuePtr(arg);
len = RSTRING_LEN(arg);
if (len > 0 && *str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
@@ -4450,8 +4475,8 @@ rb_ull2big(unsigned LONG_LONG n)
digits[0] = n;
#else
for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
- digits[i] = BIGLO(n);
- n = BIGDN(n);
+ digits[i] = BIGLO(n);
+ n = BIGDN(n);
}
#endif
@@ -4470,14 +4495,14 @@ rb_ll2big(LONG_LONG n)
if (n < 0) {
u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
- neg = 1;
+ neg = 1;
}
else {
u = n;
}
big = rb_ull2big(u);
if (neg) {
- BIGNUM_SET_NEGATIVE_SIGN(big);
+ BIGNUM_SET_NEGATIVE_SIGN(big);
}
return big;
}
@@ -4507,7 +4532,7 @@ rb_uint128t2big(uint128_t n)
BDIGIT *digits = BDIGITS(big);
for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
- digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
+ digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
}
i = bdigit_roomof(SIZEOF_INT128_T);
@@ -4525,14 +4550,14 @@ rb_int128t2big(int128_t n)
if (n < 0) {
u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
- neg = 1;
+ neg = 1;
}
else {
u = n;
}
big = rb_uint128t2big(u);
if (neg) {
- BIGNUM_SET_NEGATIVE_SIGN(big);
+ BIGNUM_SET_NEGATIVE_SIGN(big);
}
return big;
}
@@ -4561,11 +4586,14 @@ big_shift3(VALUE x, int lshift_p, size_t shift_numdigits, int shift_numbits)
if (lshift_p) {
if (LONG_MAX < shift_numdigits) {
- rb_raise(rb_eArgError, "too big number");
+ too_big:
+ rb_raise(rb_eRangeError, "shift width too big");
}
s1 = shift_numdigits;
s2 = shift_numbits;
+ if ((size_t)s1 != shift_numdigits) goto too_big;
xn = BIGNUM_LEN(x);
+ if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1) goto too_big;
z = bignew(xn+s1+1, BIGNUM_SIGN(x));
zds = BDIGITS(z);
BDIGITS_ZERO(zds, s1);
@@ -4695,7 +4723,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
rb_obj_hide(power);
base36_power_cache[base - 2][power_level] = power;
base36_numdigits_cache[base - 2][power_level] = numdigits;
- rb_gc_register_mark_object(power);
+ rb_gc_register_mark_object(power);
}
if (numdigits_ret)
*numdigits_ret = base36_numdigits_cache[base - 2][power_level];
@@ -4746,7 +4774,7 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
} while (num);
len = sizeof(buf) - j;
big2str_alloc(b2s, len + taillen);
- MEMCPY(b2s->ptr, buf + j, char, len);
+ MEMCPY(b2s->ptr, buf + j, char, len);
}
else {
p = b2s->ptr;
@@ -4763,7 +4791,7 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
static void
big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
- int power_level, size_t taillen)
+ int power_level, size_t taillen)
{
VALUE b;
size_t half_numdigits, lower_numdigits;
@@ -4793,17 +4821,17 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
*/
if (xn == 0 || bary_zero_p(xds, xn)) {
- if (b2s->ptr) {
+ if (b2s->ptr) {
/* When x is zero, power_cache_get_power(base, power_level) should be cached already. */
power_cache_get_power(b2s->base, power_level, &len);
- memset(b2s->ptr, '0', len);
+ memset(b2s->ptr, '0', len);
b2s->ptr += len;
- }
+ }
return;
}
if (power_level == 0) {
- big2str_2bdigits(b2s, xds, xn, taillen);
+ big2str_2bdigits(b2s, xds, xn, taillen);
return;
}
@@ -4831,7 +4859,7 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
memset(b2s->ptr, '0', len);
b2s->ptr += len;
}
- big2str_2bdigits(b2s, xds, xn, taillen);
+ big2str_2bdigits(b2s, xds, xn, taillen);
}
else {
BDIGIT *qds, *rds;
@@ -4935,11 +4963,11 @@ big2str_generic(VALUE x, int base)
BARY_TRUNC(xds, xn);
if (xn == 0) {
- return rb_usascii_str_new2("0");
+ return rb_usascii_str_new2("0");
}
if (!valid_radix_p(base))
- invalid_radix(base);
+ invalid_radix(base);
if (xn >= LONG_MAX/BITSPERDIG) {
rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
@@ -4976,7 +5004,7 @@ big2str_generic(VALUE x, int base)
b2s_data.ptr = NULL;
if (power_level == 0) {
- big2str_2bdigits(&b2s_data, xds, xn, 0);
+ big2str_2bdigits(&b2s_data, xds, xn, 0);
}
else {
VALUE tmpw = 0;
@@ -4985,7 +5013,7 @@ big2str_generic(VALUE x, int base)
wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
wds = ALLOCV_N(BDIGIT, tmpw, xn + wn);
MEMCPY(wds, xds, BDIGIT, xn);
- big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
+ big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
if (tmpw)
ALLOCV_END(tmpw);
}
@@ -5004,7 +5032,7 @@ rb_big2str_generic(VALUE x, int base)
return big2str_generic(x, base);
}
-#ifdef USE_GMP
+#if USE_GMP
static VALUE
big2str_gmp(VALUE x, int base)
{
@@ -5051,7 +5079,7 @@ rb_big2str1(VALUE x, int base)
size_t xn;
if (FIXNUM_P(x)) {
- return rb_fix2str(x, base);
+ return rb_fix2str(x, base);
}
bigtrunc(x);
@@ -5060,11 +5088,11 @@ rb_big2str1(VALUE x, int base)
BARY_TRUNC(xds, xn);
if (xn == 0) {
- return rb_usascii_str_new2("0");
+ return rb_usascii_str_new2("0");
}
if (!valid_radix_p(base))
- invalid_radix(base);
+ invalid_radix(base);
if (xn >= LONG_MAX/BITSPERDIG) {
rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
@@ -5075,7 +5103,7 @@ rb_big2str1(VALUE x, int base)
return big2str_base_poweroftwo(x, base);
}
-#ifdef USE_GMP
+#if USE_GMP
if (GMP_BIG2STR_DIGITS < xn) {
return big2str_gmp(x, base);
}
@@ -5111,7 +5139,7 @@ big2ulong(VALUE x, const char *type)
#else
num = 0;
for (i = 0; i < len; i++) {
- num <<= BITSPERDIG;
+ num <<= BITSPERDIG;
num += (unsigned long)ds[len - i - 1]; /* overflow is already checked */
}
#endif
@@ -5164,13 +5192,13 @@ big2ull(VALUE x, const char *type)
if (len == 0)
return 0;
if (BIGSIZE(x) > SIZEOF_LONG_LONG)
- rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
+ rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
num = (unsigned LONG_LONG)ds[0];
#else
num = 0;
for (i = 0; i < len; i++) {
- num = BIGUP(num);
+ num = BIGUP(num);
num += ds[len - i - 1];
}
#endif
@@ -5220,23 +5248,23 @@ dbl2big(double d)
double u = (d < 0)?-d:d;
if (isinf(d)) {
- rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
+ rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
}
if (isnan(d)) {
- rb_raise(rb_eFloatDomainError, "NaN");
+ rb_raise(rb_eFloatDomainError, "NaN");
}
while (1.0 <= u) {
- u /= (double)(BIGRAD);
- i++;
+ u /= (double)(BIGRAD);
+ i++;
}
z = bignew(i, d>=0);
digits = BDIGITS(z);
while (i--) {
- u *= BIGRAD;
- c = (BDIGIT)u;
- u -= c;
- digits[i] = c;
+ u *= BIGRAD;
+ c = (BDIGIT)u;
+ u -= c;
+ digits[i] = c;
}
return z;
@@ -5256,28 +5284,28 @@ big2dbl(VALUE x)
BDIGIT *ds = BDIGITS(x), dl;
if (i) {
- bits = i * BITSPERDIG - nlz(ds[i-1]);
- if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
- d = HUGE_VAL;
- }
- else {
- if (bits > DBL_MANT_DIG+1)
- lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
- else
- bits = 0;
- while (--i > lo) {
- d = ds[i] + BIGRAD*d;
- }
- dl = ds[i];
- if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
- int carry = (dl & ~(BDIGMAX << bits)) != 0;
- if (!carry) {
- while (i-- > 0) {
- carry = ds[i] != 0;
- if (carry) break;
- }
- }
- if (carry) {
+ bits = i * BITSPERDIG - nlz(ds[i-1]);
+ if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
+ d = HUGE_VAL;
+ }
+ else {
+ if (bits > DBL_MANT_DIG+1)
+ lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
+ else
+ bits = 0;
+ while (--i > lo) {
+ d = ds[i] + BIGRAD*d;
+ }
+ dl = ds[i];
+ if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
+ int carry = (dl & ~(BDIGMAX << bits)) != 0;
+ if (!carry) {
+ while (i-- > 0) {
+ carry = ds[i] != 0;
+ if (carry) break;
+ }
+ }
+ if (carry) {
BDIGIT mask = BDIGMAX;
BDIGIT bit = 1;
mask <<= bits;
@@ -5285,19 +5313,19 @@ big2dbl(VALUE x)
dl &= mask;
dl += bit;
dl = BIGLO(dl);
- if (!dl) d += 1;
- }
- }
- d = dl + BIGRAD*d;
- if (lo) {
- if (lo > INT_MAX / BITSPERDIG)
- d = HUGE_VAL;
- else if (lo < INT_MIN / BITSPERDIG)
- d = 0.0;
- else
- d = ldexp(d, (int)(lo * BITSPERDIG));
- }
- }
+ if (!dl) d += 1;
+ }
+ }
+ d = dl + BIGRAD*d;
+ if (lo) {
+ if (lo > INT_MAX / BITSPERDIG)
+ d = HUGE_VAL;
+ else if (lo < INT_MIN / BITSPERDIG)
+ d = 0.0;
+ else
+ d = ldexp(d, (int)(lo * BITSPERDIG));
+ }
+ }
}
if (BIGNUM_NEGATIVE_P(x)) d = -d;
return d;
@@ -5309,11 +5337,11 @@ rb_big2dbl(VALUE x)
double d = big2dbl(x);
if (isinf(d)) {
- rb_warning("Bignum out of Float range");
- if (d < 0.0)
- d = -HUGE_VAL;
- else
- d = HUGE_VAL;
+ rb_warning("Integer out of Float range");
+ if (d < 0.0)
+ d = -HUGE_VAL;
+ else
+ d = HUGE_VAL;
}
return d;
}
@@ -5383,7 +5411,7 @@ rb_integer_float_eq(VALUE x, VALUE y)
double yd = RFLOAT_VALUE(y);
double yi, yf;
- if (isnan(yd) || isinf(yd))
+ if (!isfinite(yd))
return Qfalse;
yf = modf(yd, &yi);
if (yf != 0)
@@ -5391,18 +5419,14 @@ rb_integer_float_eq(VALUE x, VALUE y)
if (FIXNUM_P(x)) {
#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
double xd = (double)FIX2LONG(x);
- if (xd != yd)
- return Qfalse;
- return Qtrue;
+ return RBOOL(xd == yd);
#else
long xn, yn;
if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
return Qfalse;
xn = FIX2LONG(x);
yn = (long)yi;
- if (xn != yn)
- return Qfalse;
- return Qtrue;
+ return RBOOL(xn == yn);
#endif
}
y = rb_dbl2big(yi);
@@ -5414,26 +5438,26 @@ VALUE
rb_big_cmp(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- x = bigfixize(x);
+ x = bigfixize(x);
if (FIXNUM_P(x)) {
- /* SIGNED_VALUE and Fixnum have same sign-bits, same
- * order */
- SIGNED_VALUE sx = (SIGNED_VALUE)x, sy = (SIGNED_VALUE)y;
- if (sx < sy) return INT2FIX(-1);
- return INT2FIX(sx > sy);
+ /* SIGNED_VALUE and Fixnum have same sign-bits, same
+ * order */
+ SIGNED_VALUE sx = (SIGNED_VALUE)x, sy = (SIGNED_VALUE)y;
+ if (sx < sy) return INT2FIX(-1);
+ return INT2FIX(sx > sy);
}
}
else if (RB_BIGNUM_TYPE_P(y)) {
- if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
- int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
- return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
- }
+ if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
+ int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
+ return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
+ }
}
else if (RB_FLOAT_TYPE_P(y)) {
return rb_integer_float_cmp(x, y);
}
else {
- return rb_num_coerce_cmp(x, y, idCmp);
+ return rb_num_coerce_cmp(x, y, idCmp);
}
return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
}
@@ -5452,30 +5476,30 @@ big_op(VALUE x, VALUE y, enum big_op_t op)
int n;
if (RB_INTEGER_TYPE_P(y)) {
- rel = rb_big_cmp(x, y);
+ rel = rb_big_cmp(x, y);
}
else if (RB_FLOAT_TYPE_P(y)) {
rel = rb_integer_float_cmp(x, y);
}
else {
- ID id = 0;
- switch (op) {
- case big_op_gt: id = '>'; break;
- case big_op_ge: id = idGE; break;
- case big_op_lt: id = '<'; break;
- case big_op_le: id = idLE; break;
- }
- return rb_num_coerce_relop(x, y, id);
+ ID id = 0;
+ switch (op) {
+ case big_op_gt: id = '>'; break;
+ case big_op_ge: id = idGE; break;
+ case big_op_lt: id = '<'; break;
+ case big_op_le: id = idLE; break;
+ }
+ return rb_num_coerce_relop(x, y, id);
}
if (NIL_P(rel)) return Qfalse;
n = FIX2INT(rel);
switch (op) {
- case big_op_gt: return n > 0 ? Qtrue : Qfalse;
- case big_op_ge: return n >= 0 ? Qtrue : Qfalse;
- case big_op_lt: return n < 0 ? Qtrue : Qfalse;
- case big_op_le: return n <= 0 ? Qtrue : Qfalse;
+ case big_op_gt: return RBOOL(n > 0);
+ case big_op_ge: return RBOOL(n >= 0);
+ case big_op_lt: return RBOOL(n < 0);
+ case big_op_le: return RBOOL(n <= 0);
}
return Qundef;
}
@@ -5519,7 +5543,7 @@ VALUE
rb_big_eq(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- return bignorm(x) == y ? Qtrue : Qfalse;
+ return RBOOL(bignorm(x) == y);
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
@@ -5527,12 +5551,11 @@ rb_big_eq(VALUE x, VALUE y)
return rb_integer_float_eq(x, y);
}
else {
- return rb_equal(y, x);
+ return rb_equal(y, x);
}
if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
- if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
- return Qtrue;
+ return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
}
VALUE
@@ -5541,8 +5564,7 @@ rb_big_eql(VALUE x, VALUE y)
if (!RB_BIGNUM_TYPE_P(y)) return Qfalse;
if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
- if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
- return Qtrue;
+ return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
}
VALUE
@@ -5636,10 +5658,10 @@ bigsub_int(VALUE x, long y0)
assert(xn == zn);
num = (BDIGIT_DBL_SIGNED)xds[0] - y;
if (xn == 1 && num < 0) {
- BIGNUM_NEGATE(z);
- zds[0] = (BDIGIT)-num;
- RB_GC_GUARD(x);
- return bignorm(z);
+ BIGNUM_NEGATE(z);
+ zds[0] = (BDIGIT)-num;
+ RB_GC_GUARD(x);
+ return bignorm(z);
}
zds[0] = BIGLO(num);
num = BIGDN(num);
@@ -5651,10 +5673,10 @@ bigsub_int(VALUE x, long y0)
num = 0;
for (i=0; i < xn; i++) {
if (y == 0) goto y_is_zero_x;
- num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
- zds[i] = BIGLO(num);
- num = BIGDN(num);
- y = BIGDN(y);
+ num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
+ y = BIGDN(y);
}
for (; i < zn; i++) {
if (y == 0) goto y_is_zero_z;
@@ -5669,9 +5691,9 @@ bigsub_int(VALUE x, long y0)
for (; i < xn; i++) {
y_is_zero_x:
if (num == 0) goto num_is_zero_x;
- num += xds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += xds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
#if SIZEOF_BDIGIT < SIZEOF_LONG
for (; i < zn; i++) {
@@ -5685,7 +5707,7 @@ bigsub_int(VALUE x, long y0)
for (; i < xn; i++) {
num_is_zero_x:
- zds[i] = xds[i];
+ zds[i] = xds[i];
}
#if SIZEOF_BDIGIT < SIZEOF_LONG
for (; i < zn; i++) {
@@ -5699,7 +5721,7 @@ bigsub_int(VALUE x, long y0)
assert(num == 0 || num == -1);
if (num < 0) {
get2comp(z);
- BIGNUM_NEGATE(z);
+ BIGNUM_NEGATE(z);
}
RB_GC_GUARD(x);
return bignorm(z);
@@ -5742,17 +5764,17 @@ bigadd_int(VALUE x, long y)
num = 0;
for (i=0; i < xn; i++) {
if (y == 0) goto y_is_zero_x;
- num += (BDIGIT_DBL)xds[i] + BIGLO(y);
- zds[i] = BIGLO(num);
- num = BIGDN(num);
- y = BIGDN(y);
+ num += (BDIGIT_DBL)xds[i] + BIGLO(y);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
+ y = BIGDN(y);
}
for (; i < zn; i++) {
if (y == 0) goto y_is_zero_z;
- num += BIGLO(y);
- zds[i] = BIGLO(num);
- num = BIGDN(num);
- y = BIGDN(y);
+ num += BIGLO(y);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
+ y = BIGDN(y);
}
goto finish;
@@ -5761,25 +5783,25 @@ bigadd_int(VALUE x, long y)
for (;i < xn; i++) {
y_is_zero_x:
if (num == 0) goto num_is_zero_x;
- num += (BDIGIT_DBL)xds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += (BDIGIT_DBL)xds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
for (; i < zn; i++) {
y_is_zero_z:
if (num == 0) goto num_is_zero_z;
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
goto finish;
for (;i < xn; i++) {
num_is_zero_x:
- zds[i] = xds[i];
+ zds[i] = xds[i];
}
for (; i < zn; i++) {
num_is_zero_z:
- zds[i] = 0;
+ zds[i] = 0;
}
goto finish;
@@ -5796,15 +5818,15 @@ bigadd(VALUE x, VALUE y, int sign)
sign = (sign == BIGNUM_SIGN(y));
if (BIGNUM_SIGN(x) != sign) {
- if (sign) return bigsub(y, x);
- return bigsub(x, y);
+ if (sign) return bigsub(y, x);
+ return bigsub(x, y);
}
if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
- len = BIGNUM_LEN(x) + 1;
+ len = BIGNUM_LEN(x) + 1;
}
else {
- len = BIGNUM_LEN(y) + 1;
+ len = BIGNUM_LEN(y) + 1;
}
z = bignew(len, sign);
@@ -5821,26 +5843,26 @@ rb_big_plus(VALUE x, VALUE y)
long n;
if (FIXNUM_P(y)) {
- n = FIX2LONG(y);
- if ((n > 0) != BIGNUM_SIGN(x)) {
- if (n < 0) {
- n = -n;
- }
- return bigsub_int(x, n);
- }
- if (n < 0) {
- n = -n;
- }
- return bigadd_int(x, n);
+ n = FIX2LONG(y);
+ if ((n > 0) != BIGNUM_SIGN(x)) {
+ if (n < 0) {
+ n = -n;
+ }
+ return bigsub_int(x, n);
+ }
+ if (n < 0) {
+ n = -n;
+ }
+ return bigadd_int(x, n);
}
else if (RB_BIGNUM_TYPE_P(y)) {
- return bignorm(bigadd(x, y, 1));
+ return bignorm(bigadd(x, y, 1));
}
else if (RB_FLOAT_TYPE_P(y)) {
- return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
+ return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '+');
+ return rb_num_coerce_bin(x, y, '+');
}
}
@@ -5850,26 +5872,26 @@ rb_big_minus(VALUE x, VALUE y)
long n;
if (FIXNUM_P(y)) {
- n = FIX2LONG(y);
- if ((n > 0) != BIGNUM_SIGN(x)) {
- if (n < 0) {
- n = -n;
- }
- return bigadd_int(x, n);
- }
- if (n < 0) {
- n = -n;
- }
- return bigsub_int(x, n);
+ n = FIX2LONG(y);
+ if ((n > 0) != BIGNUM_SIGN(x)) {
+ if (n < 0) {
+ n = -n;
+ }
+ return bigadd_int(x, n);
+ }
+ if (n < 0) {
+ n = -n;
+ }
+ return bigsub_int(x, n);
}
else if (RB_BIGNUM_TYPE_P(y)) {
- return bignorm(bigadd(x, y, 0));
+ return bignorm(bigadd(x, y, 0));
}
else if (RB_FLOAT_TYPE_P(y)) {
- return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
+ return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '-');
+ return rb_num_coerce_bin(x, y, '-');
}
}
@@ -5928,15 +5950,15 @@ VALUE
rb_big_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
+ y = rb_int2big(FIX2LONG(y));
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
else if (RB_FLOAT_TYPE_P(y)) {
- return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
+ return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '*');
+ return rb_num_coerce_bin(x, y, '*');
}
return bignorm(bigmul0(x, y));
@@ -5963,21 +5985,21 @@ bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
BARY_TRUNC(xds, xn);
if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
- if (divp) *divp = rb_int2big(0);
- if (modp) *modp = x;
- return Qnil;
+ if (divp) *divp = rb_int2big(0);
+ if (modp) *modp = x;
+ return Qnil;
}
if (yn == 1) {
- dd = yds[0];
- z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
- zds = BDIGITS(z);
+ dd = yds[0];
+ z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
+ zds = BDIGITS(z);
dd = bigdivrem_single(zds, xds, xn, dd);
- if (modp) {
- *modp = rb_uint2big((uintptr_t)dd);
- BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
- }
- if (divp) *divp = z;
- return Qnil;
+ if (modp) {
+ *modp = rb_uint2big((uintptr_t)dd);
+ BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
+ }
+ if (divp) *divp = z;
+ return Qnil;
}
if (xn == 2 && yn == 2) {
BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
@@ -6042,11 +6064,11 @@ bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
bigdivrem(x, y, divp, &mod);
if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
- if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
- if (modp) *modp = bigadd(mod, y, 1);
+ if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
+ if (modp) *modp = bigadd(mod, y, 1);
}
else if (modp) {
- *modp = mod;
+ *modp = mod;
}
}
@@ -6057,25 +6079,25 @@ rb_big_divide(VALUE x, VALUE y, ID op)
VALUE z;
if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
+ y = rb_int2big(FIX2LONG(y));
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
else if (RB_FLOAT_TYPE_P(y)) {
- if (op == '/') {
+ if (op == '/') {
double dx = rb_big2dbl(x);
return rb_flo_div_flo(DBL2NUM(dx), y);
- }
- else {
+ }
+ else {
VALUE v;
- double dy = RFLOAT_VALUE(y);
- if (dy == 0.0) rb_num_zerodiv();
+ double dy = RFLOAT_VALUE(y);
+ if (dy == 0.0) rb_num_zerodiv();
v = rb_big_divide(x, y, '/');
return rb_dbl2big(RFLOAT_VALUE(v));
- }
+ }
}
else {
- return rb_num_coerce_bin(x, y, op);
+ return rb_num_coerce_bin(x, y, op);
}
bigdivmod(x, y, &z, 0);
@@ -6100,10 +6122,10 @@ rb_big_modulo(VALUE x, VALUE y)
VALUE z;
if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
+ y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
- return rb_num_coerce_bin(x, y, '%');
+ return rb_num_coerce_bin(x, y, '%');
}
bigdivmod(x, y, 0, &z);
@@ -6116,10 +6138,10 @@ rb_big_remainder(VALUE x, VALUE y)
VALUE z;
if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
+ y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
- return rb_num_coerce_bin(x, y, rb_intern("remainder"));
+ return rb_num_coerce_bin(x, y, rb_intern("remainder"));
}
bigdivrem(x, y, 0, &z);
@@ -6132,7 +6154,7 @@ rb_big_divmod(VALUE x, VALUE y)
VALUE div, mod;
if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
+ y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
return rb_num_coerce_bin(x, y, idDivmod);
@@ -6146,9 +6168,9 @@ static VALUE
big_shift(VALUE x, long n)
{
if (n < 0)
- return big_lshift(x, 1+(unsigned long)(-(n+1)));
+ return big_lshift(x, 1+(unsigned long)(-(n+1)));
else if (n > 0)
- return big_rshift(x, (unsigned long)n);
+ return big_rshift(x, (unsigned long)n);
return x;
}
@@ -6172,9 +6194,9 @@ big_fdiv(VALUE x, VALUE y, long ey)
l = ex - ey;
#if SIZEOF_LONG > SIZEOF_INT
{
- /* Visual C++ can't be here */
- if (l > INT_MAX) return HUGE_VAL;
- if (l < INT_MIN) return 0.0;
+ /* Visual C++ can't be here */
+ if (l > INT_MAX) return HUGE_VAL;
+ if (l < INT_MIN) return 0.0;
}
#endif
return ldexp(big2dbl(z), (int)l);
@@ -6208,19 +6230,19 @@ rb_big_fdiv_double(VALUE x, VALUE y)
dx = big2dbl(x);
if (FIXNUM_P(y)) {
- dy = (double)FIX2LONG(y);
- if (isinf(dx))
- return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
+ dy = (double)FIX2LONG(y);
+ if (isinf(dx))
+ return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
}
else if (RB_BIGNUM_TYPE_P(y)) {
- return big_fdiv_int(x, y);
+ return big_fdiv_int(x, y);
}
else if (RB_FLOAT_TYPE_P(y)) {
- dy = RFLOAT_VALUE(y);
- if (isnan(dy))
- return dy;
- if (isinf(dx))
- return big_fdiv_float(x, y);
+ dy = RFLOAT_VALUE(y);
+ if (isnan(dy))
+ return dy;
+ if (isinf(dx))
+ return big_fdiv_float(x, y);
}
else {
return NUM2DBL(rb_num_coerce_bin(x, y, idFdiv));
@@ -6245,20 +6267,20 @@ rb_big_pow(VALUE x, VALUE y)
if (y == INT2FIX(0)) return INT2FIX(1);
if (y == INT2FIX(1)) return x;
if (RB_FLOAT_TYPE_P(y)) {
- d = RFLOAT_VALUE(y);
- if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
+ d = RFLOAT_VALUE(y);
+ if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
- }
+ }
}
else if (RB_BIGNUM_TYPE_P(y)) {
- y = bignorm(y);
- if (FIXNUM_P(y))
- goto again;
- rb_warn("in a**b, b may be too big");
- d = rb_big2dbl(y);
+ y = bignorm(y);
+ if (FIXNUM_P(y))
+ goto again;
+ rb_warn("in a**b, b may be too big");
+ d = rb_big2dbl(y);
}
else if (FIXNUM_P(y)) {
- yy = FIX2LONG(y);
+ yy = FIX2LONG(y);
if (yy < 0) {
x = rb_big_pow(x, LONG2NUM(-yy));
@@ -6267,31 +6289,31 @@ rb_big_pow(VALUE x, VALUE y)
else
return DBL2NUM(1.0 / NUM2DBL(x));
}
- else {
- VALUE z = 0;
- SIGNED_VALUE mask;
+ else {
+ VALUE z = 0;
+ SIGNED_VALUE mask;
const size_t xbits = rb_absint_numwords(x, 1, NULL);
- const size_t BIGLEN_LIMIT = 32*1024*1024;
+ const size_t BIGLEN_LIMIT = 32*1024*1024;
- if (xbits == (size_t)-1 ||
+ if (xbits == (size_t)-1 ||
(xbits > BIGLEN_LIMIT) ||
(xbits * yy > BIGLEN_LIMIT)) {
- rb_warn("in a**b, b may be too big");
- d = (double)yy;
- }
- else {
- for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
- if (z) z = bigsq(z);
- if (yy & mask) {
- z = z ? bigtrunc(bigmul0(z, x)) : x;
- }
- }
- return bignorm(z);
- }
- }
+ rb_warn("in a**b, b may be too big");
+ d = (double)yy;
+ }
+ else {
+ for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
+ if (z) z = bigsq(z);
+ if (yy & mask) {
+ z = z ? bigtrunc(bigmul0(z, x)) : x;
+ }
+ }
+ return bignorm(z);
+ }
+ }
}
else {
- return rb_num_coerce_bin(x, y, idPow);
+ return rb_num_coerce_bin(x, y, idPow);
}
return DBL2NUM(pow(rb_big2dbl(x), d));
}
@@ -6311,8 +6333,8 @@ bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
xds = BDIGITS(x);
#if SIZEOF_BDIGIT >= SIZEOF_LONG
if (!hibitsy) {
- y &= xds[0];
- return LONG2NUM(y);
+ y &= xds[0];
+ return LONG2NUM(y);
}
#endif
@@ -6341,10 +6363,10 @@ bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
}
#endif
for (;i < xn; i++) {
- zds[i] = xds[i] & hibitsy;
+ zds[i] = xds[i] & hibitsy;
}
for (;i < zn; i++) {
- zds[i] = hibitsx & hibitsy;
+ zds[i] = hibitsx & hibitsy;
}
twocomp2abs_bang(z, hibitsx && hibitsy);
RB_GC_GUARD(x);
@@ -6364,12 +6386,12 @@ rb_big_and(VALUE x, VALUE y)
long tmpn;
if (!RB_INTEGER_TYPE_P(y)) {
- return rb_num_coerce_bit(x, y, '&');
+ return rb_num_coerce_bit(x, y, '&');
}
hibitsx = abs2twocomp(&x, &xn);
if (FIXNUM_P(y)) {
- return bigand_int(x, xn, hibitsx, FIX2LONG(y));
+ return bigand_int(x, xn, hibitsx, FIX2LONG(y));
}
hibitsy = abs2twocomp(&y, &yn);
if (xn > yn) {
@@ -6391,10 +6413,10 @@ rb_big_and(VALUE x, VALUE y)
zds = BDIGITS(z);
for (i=0; i<n1; i++) {
- zds[i] = ds1[i] & ds2[i];
+ zds[i] = ds1[i] & ds2[i];
}
for (; i<n2; i++) {
- zds[i] = hibits1 & ds2[i];
+ zds[i] = hibits1 & ds2[i];
}
twocomp2abs_bang(z, hibits1 && hibits2);
RB_GC_GUARD(x);
@@ -6483,12 +6505,12 @@ rb_big_or(VALUE x, VALUE y)
long tmpn;
if (!RB_INTEGER_TYPE_P(y)) {
- return rb_num_coerce_bit(x, y, '|');
+ return rb_num_coerce_bit(x, y, '|');
}
hibitsx = abs2twocomp(&x, &xn);
if (FIXNUM_P(y)) {
- return bigor_int(x, xn, hibitsx, FIX2LONG(y));
+ return bigor_int(x, xn, hibitsx, FIX2LONG(y));
}
hibitsy = abs2twocomp(&y, &yn);
if (xn > yn) {
@@ -6510,10 +6532,10 @@ rb_big_or(VALUE x, VALUE y)
zds = BDIGITS(z);
for (i=0; i<n1; i++) {
- zds[i] = ds1[i] | ds2[i];
+ zds[i] = ds1[i] | ds2[i];
}
for (; i<n2; i++) {
- zds[i] = hibits1 | ds2[i];
+ zds[i] = hibits1 | ds2[i];
}
twocomp2abs_bang(z, hibits1 || hibits2);
RB_GC_GUARD(x);
@@ -6577,12 +6599,12 @@ rb_big_xor(VALUE x, VALUE y)
long tmpn;
if (!RB_INTEGER_TYPE_P(y)) {
- return rb_num_coerce_bit(x, y, '^');
+ return rb_num_coerce_bit(x, y, '^');
}
hibitsx = abs2twocomp(&x, &xn);
if (FIXNUM_P(y)) {
- return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
+ return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
}
hibitsy = abs2twocomp(&y, &yn);
if (xn > yn) {
@@ -6601,10 +6623,10 @@ rb_big_xor(VALUE x, VALUE y)
zds = BDIGITS(z);
for (i=0; i<n1; i++) {
- zds[i] = ds1[i] ^ ds2[i];
+ zds[i] = ds1[i] ^ ds2[i];
}
for (; i<n2; i++) {
- zds[i] = hibitsx ^ ds2[i];
+ zds[i] = hibitsx ^ ds2[i];
}
twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
RB_GC_GUARD(x);
@@ -6620,25 +6642,25 @@ rb_big_lshift(VALUE x, VALUE y)
int shift_numbits;
for (;;) {
- if (FIXNUM_P(y)) {
- long l = FIX2LONG(y);
+ if (FIXNUM_P(y)) {
+ long l = FIX2LONG(y);
unsigned long shift;
- if (0 <= l) {
- lshift_p = 1;
+ if (0 <= l) {
+ lshift_p = 1;
shift = l;
}
else {
- lshift_p = 0;
- shift = 1+(unsigned long)(-(l+1));
- }
+ lshift_p = 0;
+ shift = 1+(unsigned long)(-(l+1));
+ }
shift_numbits = (int)(shift & (BITSPERDIG-1));
shift_numdigits = shift >> bit_length(BITSPERDIG-1);
return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
- }
- else if (RB_BIGNUM_TYPE_P(y)) {
+ }
+ else if (RB_BIGNUM_TYPE_P(y)) {
return bignorm(big_shift2(x, 1, y));
- }
- y = rb_to_int(y);
+ }
+ y = rb_to_int(y);
}
}
@@ -6650,8 +6672,8 @@ rb_big_rshift(VALUE x, VALUE y)
int shift_numbits;
for (;;) {
- if (FIXNUM_P(y)) {
- long l = FIX2LONG(y);
+ if (FIXNUM_P(y)) {
+ long l = FIX2LONG(y);
unsigned long shift;
if (0 <= l) {
lshift_p = 0;
@@ -6659,16 +6681,16 @@ rb_big_rshift(VALUE x, VALUE y)
}
else {
lshift_p = 1;
- shift = 1+(unsigned long)(-(l+1));
- }
+ shift = 1+(unsigned long)(-(l+1));
+ }
shift_numbits = (int)(shift & (BITSPERDIG-1));
shift_numdigits = shift >> bit_length(BITSPERDIG-1);
return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
- }
- else if (RB_BIGNUM_TYPE_P(y)) {
+ }
+ else if (RB_BIGNUM_TYPE_P(y)) {
return bignorm(big_shift2(x, 0, y));
- }
- y = rb_to_int(y);
+ }
+ y = rb_to_int(y);
}
}
@@ -6682,22 +6704,22 @@ rb_big_aref(VALUE x, VALUE y)
BDIGIT bit;
if (RB_BIGNUM_TYPE_P(y)) {
- if (BIGNUM_NEGATIVE_P(y))
- return INT2FIX(0);
- bigtrunc(y);
- if (BIGSIZE(y) > sizeof(size_t)) {
- return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
- }
+ if (BIGNUM_NEGATIVE_P(y))
+ return INT2FIX(0);
+ bigtrunc(y);
+ if (BIGSIZE(y) > sizeof(size_t)) {
+ return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
+ }
#if SIZEOF_SIZE_T <= SIZEOF_LONG
- shift = big2ulong(y, "long");
+ shift = big2ulong(y, "long");
#else
- shift = big2ull(y, "long long");
+ shift = big2ull(y, "long long");
#endif
}
else {
- l = NUM2LONG(y);
- if (l < 0) return INT2FIX(0);
- shift = (size_t)l;
+ l = NUM2LONG(y);
+ if (l < 0) return INT2FIX(0);
+ shift = (size_t)l;
}
s1 = shift/BITSPERDIG;
s2 = shift%BITSPERDIG;
@@ -6728,14 +6750,15 @@ rb_big_hash(VALUE x)
/*
* call-seq:
- * big.coerce(numeric) -> array
+ * int.coerce(numeric) -> array
*
- * Returns an array with both a +numeric+ and a +big+ represented as Bignum
- * objects.
+ * Returns an array with both a +numeric+ and a +int+ represented as
+ * Integer objects or Float objects.
*
- * This is achieved by converting +numeric+ to a Bignum.
+ * This is achieved by converting +numeric+ to an Integer or a Float.
*
- * A TypeError is raised if the +numeric+ is not a Fixnum or Bignum type.
+ * A TypeError is raised if the +numeric+ is not an Integer or a Float
+ * type.
*
* (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904]
*/
@@ -6757,8 +6780,8 @@ VALUE
rb_big_abs(VALUE x)
{
if (BIGNUM_NEGATIVE_P(x)) {
- x = rb_big_clone(x);
- BIGNUM_SET_POSITIVE_SIGN(x);
+ x = rb_big_clone(x);
+ BIGNUM_SET_POSITIVE_SIGN(x);
}
return x;
}
@@ -6825,17 +6848,14 @@ rb_big_bit_length(VALUE big)
VALUE
rb_big_odd_p(VALUE num)
{
- if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
- return Qtrue;
- }
- return Qfalse;
+ return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
}
VALUE
rb_big_even_p(VALUE num)
{
if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
- return Qfalse;
+ return Qfalse;
}
return Qtrue;
}
@@ -6866,21 +6886,21 @@ estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len)
double f;
if (rshift > 0) {
- lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift);
- d >>= rshift;
+ lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift);
+ d >>= rshift;
}
else if (rshift < 0) {
- d <<= -rshift;
- d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift);
+ d <<= -rshift;
+ d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift);
}
f = sqrt(BDIGIT_DBL_TO_DOUBLE(d));
d = (BDIGIT_DBL)ceil(f);
if (BDIGIT_DBL_TO_DOUBLE(d) == f) {
- if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig)))
- ++d;
+ if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig)))
+ ++d;
}
else {
- lowbits = 1;
+ lowbits = 1;
}
rshift /= 2;
rshift += (2-(len&1))*BITSPERDIG/2;
@@ -6912,37 +6932,35 @@ rb_big_isqrt(VALUE n)
BDIGIT *xds;
if (len <= 2) {
- BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
+ BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
#if SIZEOF_BDIGIT > SIZEOF_LONG
- return ULL2NUM(sq);
+ return ULL2NUM(sq);
#else
- return ULONG2NUM(sq);
+ return ULONG2NUM(sq);
#endif
}
else if ((xds = estimate_initial_sqrt(&x, xn, nds, len)) != 0) {
- size_t tn = xn + BIGDIVREM_EXTRA_WORDS;
- VALUE t = bignew_1(0, tn, 1);
- BDIGIT *tds = BDIGITS(t);
- tn = BIGNUM_LEN(t);
-
- /* t = n/x */
- while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn),
- bary_cmp(tds, tn, xds, xn) < 0) {
- int carry;
- BARY_TRUNC(tds, tn);
- /* x = (x+t)/2 */
- carry = bary_add(xds, xn, xds, xn, tds, tn);
- bary_small_rshift(xds, xds, xn, 1, carry);
- tn = BIGNUM_LEN(t);
- }
- rb_big_realloc(t, 0);
- rb_gc_force_recycle(t);
+ size_t tn = xn + BIGDIVREM_EXTRA_WORDS;
+ VALUE t = bignew_1(0, tn, 1);
+ BDIGIT *tds = BDIGITS(t);
+ tn = BIGNUM_LEN(t);
+
+ /* t = n/x */
+ while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn),
+ bary_cmp(tds, tn, xds, xn) < 0) {
+ int carry;
+ BARY_TRUNC(tds, tn);
+ /* x = (x+t)/2 */
+ carry = bary_add(xds, xn, xds, xn, tds, tn);
+ bary_small_rshift(xds, xds, xn, 1, carry);
+ tn = BIGNUM_LEN(t);
+ }
}
RBASIC_SET_CLASS_RAW(x, rb_cInteger);
return x;
}
-#ifdef USE_GMP
+#if USE_GMP
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)
{
@@ -6968,7 +6986,7 @@ bary_powm_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT
static VALUE
int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
{
-#ifdef USE_GMP
+#if USE_GMP
VALUE z;
size_t xn, yn, mn, zn;
@@ -7144,7 +7162,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);
+ if (bignorm(m) == INT2FIX(1)) return INT2FIX(0);
return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
}
}
@@ -7172,13 +7190,9 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
void
Init_Bignum(void)
{
- /* An obsolete class, use Integer */
- rb_define_const(rb_cObject, "Bignum", rb_cInteger);
- rb_deprecate_constant(rb_cObject, "Bignum");
-
rb_define_method(rb_cInteger, "coerce", rb_int_coerce, 1);
-#ifdef USE_GMP
+#if USE_GMP
/* The version of loaded GMP. */
rb_define_const(rb_cInteger, "GMP_VERSION", rb_sprintf("GMP %s", gmp_version));
#endif
diff --git a/bin/gem b/bin/gem
index a4ec754abb..1c16ea7ddd 100755
--- a/bin/gem
+++ b/bin/gem
@@ -5,21 +5,6 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/gem_runner'
-require 'rubygems/exceptions'
-
-required_version = Gem::Requirement.new ">= 1.8.7"
-
-unless required_version.satisfied_by? Gem.ruby_version then
- abort "Expected Ruby Version #{required_version}, is #{Gem.ruby_version}"
-end
-
-args = ARGV.clone
-
-begin
- Gem::GemRunner.new.run args
-rescue Gem::SystemExitException => e
- exit e.exit_code
-end
+require "rubygems/gem_runner"
+Gem::GemRunner.new.run ARGV.clone
diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb
index 11d5a6c17e..f9b3e919b8 100755
--- a/bootstraptest/runner.rb
+++ b/bootstraptest/runner.rb
@@ -8,6 +8,8 @@
# Never use Ruby extensions in this file.
# Maintain Ruby 1.8 compatibility for now
+$start_time = Time.now
+
begin
require 'fileutils'
require 'tmpdir'
@@ -58,24 +60,114 @@ if !Dir.respond_to?(:mktmpdir)
end
end
+# Configuration
+bt = Struct.new(:ruby,
+ :verbose,
+ :color,
+ :tty,
+ :quiet,
+ :wn,
+ :progress,
+ :progress_bs,
+ :passed,
+ :failed,
+ :reset,
+ :columns,
+ :window_width,
+ :width,
+ :indent,
+ :platform,
+ )
+BT = Class.new(bt) do
+ def indent=(n)
+ super
+ if (self.columns ||= 0) < n
+ $stderr.print(' ' * (n - self.columns))
+ end
+ self.columns = indent
+ end
+
+ def putc(c)
+ unless self.quiet
+ if self.window_width == nil
+ unless w = ENV["COLUMNS"] and (w = w.to_i) > 0
+ w = 80
+ end
+ w -= 1
+ self.window_width = w
+ end
+ if self.window_width and self.columns >= self.window_width
+ $stderr.print "\n", " " * (self.indent ||= 0)
+ self.columns = indent
+ end
+ $stderr.print c
+ $stderr.flush
+ self.columns += 1
+ end
+ end
+
+ def wn=(wn)
+ unless wn == 1
+ if /(?:\A|\s)--jobserver-(?:auth|fds)=(?:(\d+),(\d+)|fifo:((?:\\.|\S)+))/ =~ ENV.delete("MAKEFLAGS")
+ begin
+ if fifo = $3
+ fifo.gsub!(/\\(?=.)/, '')
+ r = File.open(fifo, IO::RDONLY|IO::NONBLOCK|IO::BINARY)
+ w = File.open(fifo, IO::WRONLY|IO::NONBLOCK|IO::BINARY)
+ else
+ r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
+ w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
+ end
+ rescue => e
+ r.close if r
+ else
+ r.close_on_exec = true
+ w.close_on_exec = true
+ tokens = r.read_nonblock(wn > 0 ? wn : 1024, exception: false)
+ r.close
+ if String === tokens
+ tokens.freeze
+ auth = w
+ w = nil
+ at_exit {auth << tokens; auth.close}
+ wn = tokens.size + 1
+ else
+ w.close
+ wn = 1
+ end
+ end
+ end
+ if wn <= 0
+ require 'etc'
+ wn = [Etc.nprocessors / 2, 1].max
+ end
+ end
+ super wn
+ end
+end.new
+
+BT_STATE = Struct.new(:count, :error).new
+
def main
- @ruby = File.expand_path('miniruby')
- @verbose = false
+ BT.ruby = File.expand_path('miniruby')
+ BT.verbose = false
$VERBOSE = false
$stress = false
- @color = nil
- @tty = nil
- @quiet = false
+ BT.color = nil
+ BT.tty = nil
+ BT.quiet = false
+ # BT.wn = 1
dir = nil
quiet = false
tests = nil
ARGV.delete_if {|arg|
case arg
when /\A--ruby=(.*)/
- @ruby = $1
- @ruby.gsub!(/^([^ ]*)/){File.expand_path($1)}
- @ruby.gsub!(/(\s+-I\s*)((?!(?:\.\/)*-(?:\s|\z))\S+)/){$1+File.expand_path($2)}
- @ruby.gsub!(/(\s+-r\s*)(\.\.?\/\S+)/){$1+File.expand_path($2)}
+ ruby = $1
+ ruby.gsub!(/^([^ ]*)/){File.expand_path($1)}
+ ruby.gsub!(/(\s+-I\s*)((?!(?:\.\/)*-(?:\s|\z))\S+)/){$1+File.expand_path($2)}
+ ruby.gsub!(/(\s+-r\s*)(\.\.?\/\S+)/){$1+File.expand_path($2)}
+ BT.ruby = ruby
true
when /\A--sets=(.*)/
tests = Dir.glob("#{File.dirname($0)}/test_{#{$1}}*.rb").sort
@@ -88,18 +180,23 @@ def main
$stress = true
when /\A--color(?:=(?:always|(auto)|(never)|(.*)))?\z/
warn "unknown --color argument: #$3" if $3
- @color = $1 ? nil : !$2
+ BT.color = color = $1 ? nil : !$2
true
when /\A--tty(=(?:yes|(no)|(.*)))?\z/
warn "unknown --tty argument: #$3" if $3
- @tty = !$1 || !$2
+ BT.tty = !$1 || !$2
true
when /\A(-q|--q(uiet))\z/
quiet = true
- @quiet = true
+ BT.quiet = true
+ true
+ when /\A-j(\d+)?/
+ BT.wn = $1.to_i
true
when /\A(-v|--v(erbose))\z/
- @verbose = true
+ BT.verbose = true
+ BT.quiet = false
+ true
when /\A(-h|--h(elp)?)\z/
puts(<<-End)
Usage: #{File.basename($0, '.*')} --ruby=PATH [--sets=NAME,NAME,...]
@@ -121,22 +218,23 @@ End
end
}
if tests and not ARGV.empty?
- $stderr.puts "--tests and arguments are exclusive"
- exit false
+ abort "--sets and arguments are exclusive"
end
tests ||= ARGV
tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty?
pathes = tests.map {|path| File.expand_path(path) }
- @progress = %w[- \\ | /]
- @progress_bs = "\b" * @progress[0].size
- @tty = $stderr.tty? if @tty.nil?
- case @color
+ BT.progress = %w[- \\ | /]
+ BT.progress_bs = "\b" * BT.progress[0].size
+ BT.tty = $stderr.tty? if BT.tty.nil?
+ BT.wn ||= /-j(\d+)?/ =~ (ENV["MAKEFLAGS"] || ENV["MFLAGS"]) ? $1.to_i : 1
+
+ case BT.color
when nil
- @color = @tty && /dumb/ !~ ENV["TERM"]
+ BT.color = BT.tty && /dumb/ !~ ENV["TERM"]
end
- @tty &&= !@verbose
- if @color
+ BT.tty &&= !BT.verbose
+ if BT.color
# dircolors-like style
colors = (colors = ENV['TEST_COLORS']) ? Hash[colors.scan(/(\w+)=([^:\n]*)/)] : {}
begin
@@ -145,14 +243,16 @@ End
end
rescue
end
- @passed = "\e[;#{colors["pass"] || "32"}m"
- @failed = "\e[;#{colors["fail"] || "31"}m"
- @reset = "\e[m"
+ BT.passed = "\e[;#{colors["pass"] || "32"}m"
+ BT.failed = "\e[;#{colors["fail"] || "31"}m"
+ BT.reset = "\e[m"
else
- @passed = @failed = @reset = ""
+ BT.passed = BT.failed = BT.reset = ""
end
+ target_version = `#{BT.ruby} -v`.chomp
+ BT.platform = target_version[/\[(.*)\]\z/, 1]
unless quiet
- puts Time.now
+ puts $start_time
if defined?(RUBY_DESCRIPTION)
puts "Driver is #{RUBY_DESCRIPTION}"
elsif defined?(RUBY_PATCHLEVEL)
@@ -160,272 +260,469 @@ End
else
puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
end
- puts "Target is #{`#{@ruby} -v`.chomp}"
+ puts "Target is #{target_version}"
puts
$stdout.flush
end
- in_temporary_working_directory(dir) {
+ in_temporary_working_directory(dir) do
exec_test pathes
- }
+ end
end
def erase(e = true)
- if e and @columns > 0 and @tty and !@verbose
+ if e and BT.columns > 0 and BT.tty and !BT.verbose
"\e[1K\r"
else
""
end
end
-def exec_test(pathes)
- @count = 0
- @error = 0
- @errbuf = []
- @location = nil
- @columns = 0
- @width = pathes.map {|path| File.basename(path).size}.max + 2
+def load_test pathes
pathes.each do |path|
- @basename = File.basename(path)
- $stderr.printf("%s%-*s ", erase(@quiet), @width, @basename)
- $stderr.flush
- @columns = @width + 1
- $stderr.puts if @verbose
- count = @count
- error = @error
load File.expand_path(path)
- if @tty
- if @error == error
- msg = "PASS #{@count-count}"
- @columns += msg.size - 1
- $stderr.print "#{@progress_bs}#{@passed}#{msg}#{@reset}"
+ end
+end
+
+def concurrent_exec_test
+ aq = Queue.new
+ rq = Queue.new
+
+ ts = BT.wn.times.map do
+ Thread.new do
+ while as = aq.pop
+ as.call
+ rq << as
+ end
+ ensure
+ rq << nil
+ end
+ end
+
+ Assertion.all.to_a.shuffle.each do |path, assertions|
+ assertions.each do |as|
+ aq << as
+ end
+ end
+
+ BT.indent = 1
+ aq.close
+ i = 1
+ term_wn = 0
+ begin
+ while BT.wn != term_wn
+ if r = rq.pop
+ case
+ when BT.quiet
+ when BT.tty
+ $stderr.print "#{BT.progress_bs}#{BT.progress[(i+=1) % BT.progress.size]}"
+ else
+ BT.putc '.'
+ end
else
- msg = "FAIL #{@error-error}/#{@count-count}"
- $stderr.print "#{@progress_bs}#{@failed}#{msg}#{@reset}"
- @columns = 0
+ term_wn += 1
+ end
+ end
+ ensure
+ ts.each(&:kill)
+ ts.each(&:join)
+ end
+end
+
+def exec_test(pathes)
+ # setup
+ load_test pathes
+ BT_STATE.count = 0
+ BT_STATE.error = 0
+ BT.columns = 0
+ BT.width = pathes.map {|path| File.basename(path).size}.max + 2
+
+ # execute tests
+ if BT.wn > 1
+ concurrent_exec_test
+ else
+ prev_basename = nil
+ Assertion.all.each do |basename, assertions|
+ if !BT.quiet && basename != prev_basename
+ prev_basename = basename
+ $stderr.printf("%s%-*s ", erase(BT.quiet), BT.width, basename)
+ $stderr.flush
+ end
+ BT.columns = BT.width + 1
+ $stderr.puts if BT.verbose
+ count = BT_STATE.count
+ error = BT_STATE.error
+
+ assertions.each do |assertion|
+ BT_STATE.count += 1
+ assertion.call
+ end
+
+ if BT.tty
+ if BT_STATE.error == error
+ msg = "PASS #{BT_STATE.count-count}"
+ BT.columns += msg.size - 1
+ $stderr.print "#{BT.progress_bs}#{BT.passed}#{msg}#{BT.reset}" unless BT.quiet
+ else
+ msg = "FAIL #{BT_STATE.error-error}/#{BT_STATE.count-count}"
+ $stderr.print "#{BT.progress_bs}#{BT.failed}#{msg}#{BT.reset}"
+ BT.columns = 0
+ end
end
+ $stderr.puts if !BT.quiet and (BT.tty or BT_STATE.error == error)
end
- $stderr.puts unless @quiet and @tty and @error == error
end
- $stderr.print(erase) if @quiet
- @errbuf.each do |msg|
+
+ # show results
+ unless BT.quiet
+ $stderr.puts(erase)
+
+ sec = Time.now - $start_time
+ $stderr.puts "Finished in #{'%.2f' % sec} sec\n\n" if Assertion.count > 0
+ end
+
+ Assertion.errbuf.each do |msg|
$stderr.puts msg
end
- if @error == 0
- if @count == 0
- $stderr.puts "No tests, no problem"
+
+ out = BT.quiet ? $stdout : $stderr
+
+ if BT_STATE.error == 0
+ if Assertion.count == 0
+ out.puts "No tests, no problem" unless BT.quiet
else
- $stderr.puts "#{@passed}PASS#{@reset} all #{@count} tests"
+ out.puts "#{BT.passed}PASS#{BT.reset} all #{Assertion.count} tests"
end
- exit true
+ true
else
- $stderr.puts "#{@failed}FAIL#{@reset} #{@error}/#{@count} tests failed"
- exit false
+ $stderr.puts "#{BT.failed}FAIL#{BT.reset} #{BT_STATE.error}/#{BT_STATE.count} tests failed"
+ false
end
end
-def show_progress(message = '')
- if @verbose
- $stderr.print "\##{@count} #{@location} "
- elsif @tty
- $stderr.print "#{@progress_bs}#{@progress[@count % @progress.size]}"
- end
- t = Time.now if @verbose
- faildesc, errout = with_stderr {yield}
- t = Time.now - t if @verbose
- if !faildesc
- if @tty
- $stderr.print "#{@progress_bs}#{@progress[@count % @progress.size]}"
- elsif @verbose
- $stderr.printf(". %.3f\n", t)
- else
- $stderr.print '.'
+def target_platform
+ BT.platform or RUBY_PLATFORM
+end
+
+class Assertion < Struct.new(:src, :path, :lineno, :proc)
+ @count = 0
+ @all = Hash.new{|h, k| h[k] = []}
+ @errbuf = []
+
+ class << self
+ attr_reader :count, :errbuf
+
+ def all
+ @all
end
- else
- $stderr.print "#{@failed}F"
- $stderr.printf(" %.3f", t) if @verbose
- $stderr.print @reset
- $stderr.puts if @verbose
- error faildesc, message
- unless errout.empty?
- $stderr.print "#{@failed}stderr output is not empty#{@reset}\n", adjust_indent(errout)
+
+ def add as
+ @all[as.path] << as
+ as.id = (@count += 1)
+ end
+ end
+
+ attr_accessor :id
+ attr_reader :err, :category
+
+ def initialize(*args)
+ super
+ self.class.add self
+ @category = self.path.match(/test_(.+)\.rb/)[1]
+ end
+
+ def call
+ self.proc.call self
+ end
+
+ def assert_check(message = '', opt = '', **argh)
+ show_progress(message) {
+ result = get_result_string(opt, **argh)
+ yield(result)
+ }
+ end
+
+ def with_stderr
+ out = err = nil
+ r, w = IO.pipe
+ @err = w
+ err_reader = Thread.new{ r.read }
+
+ begin
+ out = yield
+ ensure
+ w.close
+ err = err_reader.value
+ r.close rescue nil
end
- if @tty and !@verbose
- $stderr.printf("%-*s%s", @width, @basename, @progress[@count % @progress.size])
+
+ return out, err
+ end
+
+ def show_error(msg, additional_message)
+ msg = "#{BT.failed}\##{self.id} #{self.path}:#{self.lineno}#{BT.reset}: #{msg} #{additional_message}"
+ if BT.tty
+ $stderr.puts "#{erase}#{msg}"
+ else
+ Assertion.errbuf << msg
end
+ BT_STATE.error += 1
end
-rescue Interrupt
- $stderr.puts "\##{@count} #{@location}"
- raise
-rescue Exception => err
- $stderr.print 'E'
- $stderr.puts if @verbose
- error err.message, message
-ensure
- begin
- check_coredump
- rescue CoreDumpError => err
+
+
+ def show_progress(message = '')
+ if BT.quiet || BT.wn > 1
+ # do nothing
+ elsif BT.verbose
+ $stderr.print "\##{@id} #{self.path}:#{self.lineno} "
+ elsif BT.tty
+ $stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}"
+ end
+
+ t = Time.now if BT.verbose
+ faildesc, errout = with_stderr {yield}
+ t = Time.now - t if BT.verbose
+
+ if !faildesc
+ # success
+ if BT.quiet || BT.wn > 1
+ # do nothing
+ elsif BT.tty
+ $stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}"
+ elsif BT.verbose
+ $stderr.printf(". %.3f\n", t)
+ else
+ BT.putc '.'
+ end
+ else
+ $stderr.print "#{BT.failed}F"
+ $stderr.printf(" %.3f", t) if BT.verbose
+ $stderr.print BT.reset
+ $stderr.puts if BT.verbose
+ show_error faildesc, message
+ unless errout.empty?
+ $stderr.print "#{BT.failed}stderr output is not empty#{BT.reset}\n", adjust_indent(errout)
+ end
+
+ if BT.tty and !BT.verbose and BT.wn == 1
+ $stderr.printf("%-*s%s", BT.width, path, BT.progress[BT_STATE.count % BT.progress.size])
+ end
+ end
+ rescue Interrupt
+ $stderr.puts "\##{@id} #{path}:#{lineno}"
+ raise
+ rescue Exception => err
$stderr.print 'E'
- $stderr.puts if @verbose
- error err.message, message
+ $stderr.puts if BT.verbose
+ show_error err.message, message
+ ensure
+ begin
+ check_coredump
+ rescue CoreDumpError => err
+ $stderr.print 'E'
+ $stderr.puts if BT.verbose
+ show_error err.message, message
+ cleanup_coredump
+ end
end
-end
-def show_limit(testsrc, opt = '', **argh)
- result = get_result_string(testsrc, opt, **argh)
- if @tty and @verbose
- $stderr.puts ".{#@reset}\n#{erase}#{result}"
- else
- @errbuf.push result
+ def get_result_string(opt = '', **argh)
+ if BT.ruby
+ filename = make_srcfile(**argh)
+ begin
+ kw = self.err ? {err: self.err} : {}
+ out = IO.popen("#{BT.ruby} -W0 #{opt} #{filename}", **kw)
+ pid = out.pid
+ out.read.tap{ Process.waitpid(pid); out.close }
+ ensure
+ raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"]
+
+ begin
+ Process.kill :KILL, pid
+ rescue Errno::ESRCH
+ # OK
+ end
+ end
+ else
+ eval(src).to_s
+ end
+ end
+
+ def make_srcfile(frozen_string_literal: nil)
+ filename = "bootstraptest.#{self.path}_#{self.lineno}_#{self.id}.rb"
+ File.open(filename, 'w') {|f|
+ f.puts "#frozen_string_literal:true" if frozen_string_literal
+ f.puts "GC.stress = true" if $stress
+ f.puts "print(begin; #{self.src}; end)"
+ }
+ filename
end
end
-def assert_check(testsrc, message = '', opt = '', **argh)
- show_progress(message) {
- result = get_result_string(testsrc, opt, **argh)
- yield(result)
- }
+def add_assertion src, pr
+ loc = caller_locations(2, 1).first
+ lineno = loc.lineno
+ path = File.basename(loc.path)
+
+ Assertion.new(src, path, lineno, pr)
end
def assert_equal(expected, testsrc, message = '', opt = '', **argh)
- newtest
- assert_check(testsrc, message, opt, **argh) {|result|
- if expected == result
- nil
- else
- desc = "#{result.inspect} (expected #{expected.inspect})"
- pretty(testsrc, desc, result)
- end
- }
+ add_assertion testsrc, -> as do
+ as.assert_check(message, opt, **argh) {|result|
+ if expected == result
+ nil
+ else
+ desc = "#{result.inspect} (expected #{expected.inspect})"
+ pretty(testsrc, desc, result)
+ end
+ }
+ end
end
def assert_match(expected_pattern, testsrc, message = '')
- newtest
- assert_check(testsrc, message) {|result|
- if expected_pattern =~ result
- nil
- else
- desc = "#{expected_pattern.inspect} expected to be =~\n#{result.inspect}"
- pretty(testsrc, desc, result)
- end
- }
+ add_assertion testsrc, -> as do
+ as.assert_check(message) {|result|
+ if expected_pattern =~ result
+ nil
+ else
+ desc = "#{expected_pattern.inspect} expected to be =~\n#{result.inspect}"
+ pretty(testsrc, desc, result)
+ end
+ }
+ end
end
def assert_not_match(unexpected_pattern, testsrc, message = '')
- newtest
- assert_check(testsrc, message) {|result|
- if unexpected_pattern !~ result
- nil
- else
- desc = "#{unexpected_pattern.inspect} expected to be !~\n#{result.inspect}"
- pretty(testsrc, desc, result)
- end
- }
+ add_assertion testsrc, -> as do
+ as.assert_check(message) {|result|
+ if unexpected_pattern !~ result
+ nil
+ else
+ desc = "#{unexpected_pattern.inspect} expected to be !~\n#{result.inspect}"
+ pretty(testsrc, desc, result)
+ end
+ }
+ end
end
def assert_valid_syntax(testsrc, message = '')
- newtest
- assert_check(testsrc, message, '-c') {|result|
- result if /Syntax OK/ !~ result
- }
+ add_assertion testsrc, -> as do
+ as.assert_check(message, '-c') {|result|
+ result if /Syntax OK/ !~ result
+ }
+ end
end
def assert_normal_exit(testsrc, *rest, timeout: nil, **opt)
- newtest
- message, ignore_signals = rest
- message ||= ''
- show_progress(message) {
- faildesc = nil
- filename = make_srcfile(testsrc)
- old_stderr = $stderr.dup
- timeout_signaled = false
- begin
- $stderr.reopen("assert_normal_exit.log", "w")
- io = IO.popen("#{@ruby} -W0 #{filename}")
- pid = io.pid
- th = Thread.new {
- io.read
- io.close
- $?
- }
- if !th.join(timeout)
- Process.kill :KILL, pid
- timeout_signaled = true
- end
- status = th.value
- ensure
- $stderr.reopen(old_stderr)
- old_stderr.close
- end
- if status && status.signaled?
- signo = status.termsig
- signame = Signal.list.invert[signo]
- unless ignore_signals and ignore_signals.include?(signame)
- sigdesc = "signal #{signo}"
- if signame
- sigdesc = "SIG#{signame} (#{sigdesc})"
- end
- if timeout_signaled
- sigdesc << " (timeout)"
+ add_assertion testsrc, -> as do
+ message, ignore_signals = rest
+ message ||= ''
+ as.show_progress(message) {
+ faildesc = nil
+ filename = as.make_srcfile
+ timeout_signaled = false
+ logfile = "assert_normal_exit.#{as.path}.#{as.lineno}.log"
+
+ begin
+ err = open(logfile, "w")
+ io = IO.popen("#{BT.ruby} -W0 #{filename}", err: err)
+ pid = io.pid
+ th = Thread.new {
+ io.read
+ io.close
+ $?
+ }
+ if !th.join(timeout)
+ Process.kill :KILL, pid
+ timeout_signaled = true
end
- faildesc = pretty(testsrc, "killed by #{sigdesc}", nil)
- stderr_log = File.read("assert_normal_exit.log")
- if !stderr_log.empty?
- faildesc << "\n" if /\n\z/ !~ faildesc
- stderr_log << "\n" if /\n\z/ !~ stderr_log
- stderr_log.gsub!(/^.*\n/) { '| ' + $& }
- faildesc << stderr_log
+ status = th.value
+ ensure
+ err.close
+ end
+ if status && status.signaled?
+ signo = status.termsig
+ signame = Signal.list.invert[signo]
+ unless ignore_signals and ignore_signals.include?(signame)
+ sigdesc = "signal #{signo}"
+ if signame
+ sigdesc = "SIG#{signame} (#{sigdesc})"
+ end
+ if timeout_signaled
+ sigdesc << " (timeout)"
+ end
+ faildesc = pretty(testsrc, "killed by #{sigdesc}", nil)
+ stderr_log = File.read(logfile)
+ if !stderr_log.empty?
+ faildesc << "\n" if /\n\z/ !~ faildesc
+ stderr_log << "\n" if /\n\z/ !~ stderr_log
+ stderr_log.gsub!(/^.*\n/) { '| ' + $& }
+ faildesc << stderr_log
+ end
end
end
- end
- faildesc
- }
+ faildesc
+ }
+ end
end
def assert_finish(timeout_seconds, testsrc, message = '')
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # for --jit-wait
- timeout_seconds *= 3
- end
- newtest
- show_progress(message) {
- faildesc = nil
- filename = make_srcfile(testsrc)
- io = IO.popen("#{@ruby} -W0 #{filename}")
- pid = io.pid
- waited = false
- tlimit = Time.now + timeout_seconds
- diff = timeout_seconds
- while diff > 0
- if Process.waitpid pid, Process::WNOHANG
- waited = true
- break
- end
- if io.respond_to?(:read_nonblock)
- if IO.select([io], nil, nil, diff)
- begin
- io.read_nonblock(1024)
- rescue Errno::EAGAIN, IO::WaitReadable, EOFError
- break
- end while true
+ add_assertion testsrc, -> as do
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
+ timeout_seconds *= 3
+ end
+
+ as.show_progress(message) {
+ faildesc = nil
+ filename = as.make_srcfile
+ io = IO.popen("#{BT.ruby} -W0 #{filename}", err: as.err)
+ pid = io.pid
+ waited = false
+ tlimit = Time.now + timeout_seconds
+ diff = timeout_seconds
+ while diff > 0
+ if Process.waitpid pid, Process::WNOHANG
+ waited = true
+ break
end
- else
- sleep 0.1
+ if io.respond_to?(:read_nonblock)
+ if IO.select([io], nil, nil, diff)
+ begin
+ io.read_nonblock(1024)
+ rescue Errno::EAGAIN, IO::WaitReadable, EOFError
+ break
+ end while true
+ end
+ else
+ sleep 0.1
+ end
+ diff = tlimit - Time.now
end
- diff = tlimit - Time.now
- end
- if !waited
- Process.kill(:KILL, pid)
- Process.waitpid pid
- faildesc = pretty(testsrc, "not finished in #{timeout_seconds} seconds", nil)
- end
- io.close
- faildesc
- }
+ if !waited
+ Process.kill(:KILL, pid)
+ Process.waitpid pid
+ faildesc = pretty(testsrc, "not finished in #{timeout_seconds} seconds", nil)
+ end
+ io.close
+ faildesc
+ }
+ end
end
def flunk(message = '')
- newtest
- show_progress('') { message }
+ add_assertion '', -> as do
+ as.show_progress('') { message }
+ end
+end
+
+def show_limit(testsrc, opt = '', **argh)
+ return if BT.quiet
+
+ add_assertion testsrc, -> as do
+ result = as.get_result_string(opt, **argh)
+ Assertion.errbuf << result
+ end
end
def pretty(src, desc, result)
@@ -443,66 +740,6 @@ def untabify(str)
str.gsub(/^\t+/) {' ' * (8 * $&.size) }
end
-def make_srcfile(src, frozen_string_literal: nil)
- filename = 'bootstraptest.tmp.rb'
- File.open(filename, 'w') {|f|
- f.puts "#frozen_string_literal:true" if frozen_string_literal
- f.puts "GC.stress = true" if $stress
- f.puts "print(begin; #{src}; end)"
- }
- filename
-end
-
-def get_result_string(src, opt = '', **argh)
- if @ruby
- filename = make_srcfile(src, **argh)
- begin
- `#{@ruby} -W0 #{opt} #{filename}`
- ensure
- raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"]
- end
- else
- eval(src).to_s
- end
-end
-
-def with_stderr
- out = err = nil
- begin
- r, w = IO.pipe
- stderr = $stderr.dup
- $stderr.reopen(w)
- w.close
- reader = Thread.start {r.read}
- begin
- out = yield
- ensure
- $stderr.reopen(stderr)
- err = reader.value
- end
- ensure
- w.close rescue nil
- r.close rescue nil
- end
- return out, err
-end
-
-def newtest
- @location = File.basename(caller(2).first)
- @count += 1
- cleanup_coredump
-end
-
-def error(msg, additional_message)
- msg = "#{@failed}\##{@count} #{@location}#{@reset}: #{msg} #{additional_message}"
- if @tty
- $stderr.puts "#{erase}#{msg}"
- else
- @errbuf.push msg
- end
- @error += 1
-end
-
def in_temporary_working_directory(dir)
if dir
Dir.mkdir dir
@@ -530,21 +767,21 @@ def cleanup_coredump
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']
+ cmd = ['gdb', BT.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
+ FileUtils.rm_f BT.ruby+'.stackdump' if BT.ruby
end
class CoreDumpError < StandardError; end
def check_coredump
if File.file?('core') or not Dir.glob('core.*').empty? or
- (@ruby and File.exist?(@ruby+'.stackdump'))
+ (BT.ruby and File.exist?(BT.ruby+'.stackdump'))
raise CoreDumpError, "core dumped"
end
end
-main
+exit main
diff --git a/bootstraptest/test_attr.rb b/bootstraptest/test_attr.rb
index 721a847145..3cb9d3eb39 100644
--- a/bootstraptest/test_attr.rb
+++ b/bootstraptest/test_attr.rb
@@ -34,3 +34,19 @@ assert_equal %{ok}, %{
print "ok"
end
}, '[ruby-core:15120]'
+
+assert_equal %{ok}, %{
+ class Big
+ attr_reader :foo
+ def initialize
+ @foo = "ok"
+ end
+ end
+
+ obj = Big.new
+ 100.times do |i|
+ obj.instance_variable_set(:"@ivar_\#{i}", i)
+ end
+
+ Big.new.foo
+}
diff --git a/bootstraptest/test_autoload.rb b/bootstraptest/test_autoload.rb
index a9f8e6dacd..9e0850bc52 100644
--- a/bootstraptest/test_autoload.rb
+++ b/bootstraptest/test_autoload.rb
@@ -1,7 +1,7 @@
assert_equal 'ok', %q{
- File.unlink('zzz.rb') if File.file?('zzz.rb')
+ File.unlink('zzz1.rb') if File.file?('zzz1.rb')
instance_eval do
- autoload :ZZZ, './zzz.rb'
+ autoload :ZZZ, './zzz1.rb'
begin
ZZZ
rescue LoadError
@@ -11,9 +11,9 @@ assert_equal 'ok', %q{
}, '[ruby-dev:43816]'
assert_equal 'ok', %q{
- open('zzz.rb', 'w') {|f| f.puts '' }
+ open('zzz2.rb', 'w') {|f| f.puts '' }
instance_eval do
- autoload :ZZZ, './zzz.rb'
+ autoload :ZZZ, './zzz2.rb'
begin
ZZZ
rescue NameError
@@ -23,29 +23,29 @@ assert_equal 'ok', %q{
}, '[ruby-dev:43816]'
assert_equal 'ok', %q{
- open('zzz.rb', 'w') {|f| f.puts 'class ZZZ; def self.ok;:ok;end;end'}
+ open('zzz3.rb', 'w') {|f| f.puts 'class ZZZ; def self.ok;:ok;end;end'}
instance_eval do
- autoload :ZZZ, './zzz.rb'
+ autoload :ZZZ, './zzz3.rb'
ZZZ.ok
end
}, '[ruby-dev:43816]'
assert_equal 'ok', %q{
- open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
- autoload :ZZZ, "./zzz.rb"
+ open("zzz4.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
+ autoload :ZZZ, "./zzz4.rb"
ZZZ.ok
}
assert_equal 'ok', %q{
- open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
- autoload :ZZZ, "./zzz.rb"
- require "./zzz.rb"
+ open("zzz5.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
+ autoload :ZZZ, "./zzz5.rb"
+ require "./zzz5.rb"
ZZZ.ok
}
assert_equal 'okok', %q{
- open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
- autoload :ZZZ, "./zzz.rb"
+ open("zzz6.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
+ autoload :ZZZ, "./zzz6.rb"
t1 = Thread.new {ZZZ.ok}
t2 = Thread.new {ZZZ.ok}
[t1.value, t2.value].join
@@ -60,9 +60,9 @@ assert_finish 5, %q{
}, '[ruby-core:21696]'
assert_equal 'A::C', %q{
- open("zzz.rb", "w") {}
+ open("zzz7.rb", "w") {}
class A
- autoload :C, "./zzz"
+ autoload :C, "./zzz7"
class C
end
C
diff --git a/bootstraptest/test_constant_cache.rb b/bootstraptest/test_constant_cache.rb
new file mode 100644
index 0000000000..1fa83256ed
--- /dev/null
+++ b/bootstraptest/test_constant_cache.rb
@@ -0,0 +1,187 @@
+# Constant lookup is cached.
+assert_equal '1', %q{
+ CONST = 1
+
+ def const
+ CONST
+ end
+
+ const
+ const
+}
+
+# Invalidate when a constant is set.
+assert_equal '2', %q{
+ CONST = 1
+
+ def const
+ CONST
+ end
+
+ const
+
+ CONST = 2
+
+ const
+}
+
+# Invalidate when a constant of the same name is set.
+assert_equal '1', %q{
+ CONST = 1
+
+ def const
+ CONST
+ end
+
+ const
+
+ class Container
+ CONST = 2
+ end
+
+ const
+}
+
+# Invalidate when a constant is removed.
+assert_equal 'missing', %q{
+ class Container
+ CONST = 1
+
+ def const
+ CONST
+ end
+
+ def self.const_missing(name)
+ 'missing'
+ end
+
+ new.const
+ remove_const :CONST
+ end
+
+ Container.new.const
+}
+
+# Invalidate when a constant's visibility changes.
+assert_equal 'missing', %q{
+ class Container
+ CONST = 1
+
+ def self.const_missing(name)
+ 'missing'
+ end
+ end
+
+ def const
+ Container::CONST
+ end
+
+ const
+
+ Container.private_constant :CONST
+
+ const
+}
+
+# Invalidate when a constant's visibility changes even if the call to the
+# visibility change method fails.
+assert_equal 'missing', %q{
+ class Container
+ CONST1 = 1
+
+ def self.const_missing(name)
+ 'missing'
+ end
+ end
+
+ def const1
+ Container::CONST1
+ end
+
+ const1
+
+ begin
+ Container.private_constant :CONST1, :CONST2
+ rescue NameError
+ end
+
+ const1
+}
+
+# Invalidate when a module is included.
+assert_equal 'INCLUDE', %q{
+ module Include
+ CONST = :INCLUDE
+ end
+
+ class Parent
+ CONST = :PARENT
+ end
+
+ class Child < Parent
+ def const
+ CONST
+ end
+
+ new.const
+
+ include Include
+ end
+
+ Child.new.const
+}
+
+# Invalidate when const_missing is hit.
+assert_equal '2', %q{
+ module Container
+ Foo = 1
+ Bar = 2
+
+ class << self
+ attr_accessor :count
+
+ def const_missing(name)
+ @count += 1
+ @count == 1 ? Foo : Bar
+ end
+ end
+
+ @count = 0
+ end
+
+ def const
+ Container::Baz
+ end
+
+ const
+ const
+}
+
+# Invalidate when the iseq gets cleaned up.
+assert_equal '2', %q{
+ CONSTANT = 1
+
+ iseq = RubyVM::InstructionSequence.compile(<<~RUBY)
+ CONSTANT
+ RUBY
+
+ iseq.eval
+ iseq = nil
+
+ GC.start
+ CONSTANT = 2
+}
+
+# Invalidate when the iseq gets cleaned up even if it was never in the cache.
+assert_equal '2', %q{
+ CONSTANT = 1
+
+ iseq = RubyVM::InstructionSequence.compile(<<~RUBY)
+ CONSTANT
+ RUBY
+
+ iseq = nil
+
+ GC.start
+ CONSTANT = 2
+}
diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
index 5d2593c306..a9f389c673 100644
--- a/bootstraptest/test_eval.rb
+++ b/bootstraptest/test_eval.rb
@@ -116,6 +116,33 @@ assert_equal %q{1}, %q{
Const
}
}
+assert_equal %q{1}, %q{
+ class TrueClass
+ Const = 1
+ end
+ true.instance_eval %{
+ Const
+ }
+}
+assert_equal %q{[:Const]}, %q{
+ mod = Module.new
+ mod.instance_eval %{
+ Const = 1
+ }
+ raise if defined?(Module::Const)
+ mod.singleton_class.constants
+}
+assert_equal %q{can't define singleton}, %q{
+ begin
+ 123.instance_eval %{
+ Const = 1
+ }
+ "bad"
+ rescue TypeError => e
+ raise "bad" if defined?(Integer::Const)
+ e.message
+ end
+}
assert_equal %q{top}, %q{
Const = :top
class C
@@ -191,7 +218,7 @@ assert_equal %q{[10, main]}, %q{
%w[break next redo].each do |keyword|
assert_match %r"Can't escape from eval with #{keyword}\b", %{
- STDERR.reopen(STDOUT)
+ $stderr = STDOUT
begin
eval "0 rescue #{keyword}"
rescue SyntaxError => e
@@ -201,7 +228,7 @@ assert_equal %q{[10, main]}, %q{
end
assert_normal_exit %q{
- STDERR.reopen(STDOUT)
+ $stderr = STDOUT
class Foo
def self.add_method
class_eval("def some-bad-name; puts 'hello' unless @some_variable.some_function(''); end")
diff --git a/bootstraptest/test_insns.rb b/bootstraptest/test_insns.rb
index 31fdc29d02..91fba9b011 100644
--- a/bootstraptest/test_insns.rb
+++ b/bootstraptest/test_insns.rb
@@ -120,6 +120,7 @@ tests = [
[ 'dup', %q{ x = y = true; x }, ],
[ 'dupn', %q{ Object::X ||= true }, ],
[ 'reverse', %q{ q, (w, e), r = 1, [2, 3], 4; e == 3 }, ],
+ [ 'swap', %q{ !!defined?([[]]) }, ],
[ 'swap', <<-'},', ], # {
x = [[false, true]]
for i, j in x # here
diff --git a/bootstraptest/test_io.rb b/bootstraptest/test_io.rb
index 89c00d0b88..666e5a011b 100644
--- a/bootstraptest/test_io.rb
+++ b/bootstraptest/test_io.rb
@@ -1,3 +1,4 @@
+/freebsd/ =~ RUBY_PLATFORM or
assert_finish 5, %q{
r, w = IO.pipe
t1 = Thread.new { r.sysread(1) }
@@ -30,7 +31,8 @@ assert_finish 10, %q{
end
}, '[ruby-dev:32566]'
-assert_finish 1, %q{
+/freebsd/ =~ RUBY_PLATFORM or
+assert_finish 5, %q{
r, w = IO.pipe
Thread.new {
w << "ab"
@@ -83,6 +85,7 @@ assert_normal_exit %q{
ARGF.set_encoding "foo"
}
+/freebsd/ =~ RUBY_PLATFORM or
10.times do
assert_normal_exit %q{
at_exit { p :foo }
diff --git a/bootstraptest/test_jump.rb b/bootstraptest/test_jump.rb
index 18a2737ea3..d07c47a56d 100644
--- a/bootstraptest/test_jump.rb
+++ b/bootstraptest/test_jump.rb
@@ -147,7 +147,7 @@ assert_equal %q{131}, %q{
}
}
assert_match %r{Invalid retry}, %q{
-STDERR.reopen(STDOUT)
+$stderr = STDOUT
begin
eval %q{
1.times{
@@ -297,7 +297,7 @@ assert_equal "true", %q{
}, '[ruby-core:21379]'
assert_match %r{Invalid yield}, %q{
-STDERR.reopen(STDOUT)
+$stderr = STDOUT
begin
eval %q{
class Object
diff --git a/bootstraptest/test_literal.rb b/bootstraptest/test_literal.rb
index 9b3c10d519..a0d4ee08c6 100644
--- a/bootstraptest/test_literal.rb
+++ b/bootstraptest/test_literal.rb
@@ -65,8 +65,11 @@ assert_equal ':a3c', ':"a#{1+2}c".inspect'
assert_equal 'Symbol', ':"a#{1+2}c".class'
# xstring
-assert_equal "foo\n", %q(`echo foo`)
-assert_equal "foo\n", %q(s = "foo"; `echo #{s}`)
+# WASI doesn't support spawning a new process for now.
+if /wasi/ !~ target_platform
+ assert_equal "foo\n", %q(`echo foo`)
+ assert_equal "foo\n", %q(s = "foo"; `echo #{s}`)
+end
# regexp
assert_equal '', '//.source'
diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb
index 3462aa9434..04c9eb2d11 100644
--- a/bootstraptest/test_method.rb
+++ b/bootstraptest/test_method.rb
@@ -22,7 +22,7 @@ assert_match /\Awrong number of arguments \(.*\b0\b.* 1\)\z/, %q{
}
# default argument
-assert_equal '1', 'def m(x=1) x end; m()'
+assert_equal '1', 'def m(x=1) x end; m();'
assert_equal '1', 'def m(x=7) x end; m(1)'
assert_equal '1', 'def m(a,x=1) x end; m(7)'
assert_equal '1', 'def m(a,x=7) x end; m(7,1)'
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 28c9e6d90c..67e66b03ee 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -187,6 +187,41 @@ assert_equal '[:ok, :ok, :ok]', %q{
}.map(&:take)
}
+# Ractor.make_shareable issue for locals in proc [Bug #18023]
+assert_equal '[:a, :b, :c, :d, :e]', %q{
+ v1, v2, v3, v4, v5 = :a, :b, :c, :d, :e
+ closure = Ractor.current.instance_eval{ Proc.new { [v1, v2, v3, v4, v5] } }
+
+ Ractor.make_shareable(closure).call
+}
+
+# Ractor.make_shareable issue for locals in proc [Bug #18023]
+assert_equal '[:a, :b, :c, :d, :e, :f, :g]', %q{
+ a = :a
+ closure = Ractor.current.instance_eval do
+ -> {
+ b, c, d = :b, :c, :d
+ -> {
+ e, f, g = :e, :f, :g
+ -> { [a, b, c, d, e, f, g] }
+ }.call
+ }.call
+ end
+
+ Ractor.make_shareable(closure).call
+}
+
+# Now autoload in non-main Ractor is not supported
+assert_equal 'ok', %q{
+ autoload :Foo, 'foo.rb'
+ r = Ractor.new do
+ p Foo
+ rescue Ractor::UnsafeError
+ :ok
+ end
+ r.take
+}
+
###
###
# Ractor still has several memory corruption so skip huge number of tests
@@ -248,8 +283,9 @@ assert_equal 30.times.map { 'ok' }.to_s, %q{
30.times.map{|i|
test i
}
-} unless ENV['RUN_OPTS'] =~ /--jit-min-calls=5/ || # This always fails with --jit-wait --jit-min-calls=5
- (ENV.key?('TRAVIS') && ENV['TRAVIS_CPU_ARCH'] == 'arm64') # https://bugs.ruby-lang.org/issues/17878
+} unless ENV['RUN_OPTS'] =~ /--mjit-call-threshold=5/ || # This always fails with --mjit-wait --mjit-call-threshold=5
+ (ENV.key?('TRAVIS') && ENV['TRAVIS_CPU_ARCH'] == 'arm64') || # https://bugs.ruby-lang.org/issues/17878
+ true # too flaky everywhere http://ci.rvm.jp/results/trunk@ruby-sp1/4321096
# Exception for empty select
assert_match /specify at least one ractor/, %q{
@@ -466,7 +502,7 @@ assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{
rs.delete r
n
}.sort
-}
+} unless /mswin/ =~ RUBY_PLATFORM # randomly hangs on mswin https://github.com/ruby/ruby/actions/runs/3753871445/jobs/6377551069#step:20:131
# Ractor.select also support multiple take, receive and yield
assert_equal '[true, true, true]', %q{
@@ -906,7 +942,7 @@ assert_equal 'ArgumentError', %q{
}
# 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{
+assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", %q{
class C
@iv = 'str'
end
@@ -1000,6 +1036,53 @@ assert_equal '11', %q{
}.join
}
+# and instance variables of classes/modules are accessible if they refer shareable objects
+assert_equal '333', %q{
+ class C
+ @int = 1
+ @str = '-1000'.dup
+ @fstr = '100'.freeze
+
+ def self.int = @int
+ def self.str = @str
+ def self.fstr = @fstr
+ end
+
+ module M
+ @int = 2
+ @str = '-2000'.dup
+ @fstr = '200'.freeze
+
+ def self.int = @int
+ def self.str = @str
+ def self.fstr = @fstr
+ end
+
+ a = Ractor.new{ C.int }.take
+ b = Ractor.new do
+ C.str.to_i
+ rescue Ractor::IsolationError
+ 10
+ end.take
+ c = Ractor.new do
+ C.fstr.to_i
+ end.take
+
+ d = Ractor.new{ M.int }.take
+ e = Ractor.new do
+ M.str.to_i
+ rescue Ractor::IsolationError
+ 20
+ end.take
+ f = Ractor.new do
+ M.fstr.to_i
+ end.take
+
+
+ # 1 + 10 + 100 + 2 + 20 + 200
+ a + b + c + d + e + f
+}
+
# cvar in shareable-objects are not allowed to access from non-main Ractor
assert_equal 'can not access class variables from non-main Ractors', %q{
class C
@@ -1019,6 +1102,28 @@ assert_equal 'can not access class variables from non-main Ractors', %q{
end
}
+# also cached cvar in shareable-objects are not allowed to access from non-main Ractor
+assert_equal 'can not access class variables from non-main Ractors', %q{
+ class C
+ @@cv = 'str'
+ def self.cv
+ @@cv
+ end
+ end
+
+ C.cv # cache
+
+ r = Ractor.new do
+ C.cv
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
# Getting non-shareable objects via constants by other Ractors is not allowed
assert_equal 'can not access non-shareable objects in constant C::CONST by non-main Ractor.', %q{
class C
@@ -1061,7 +1166,7 @@ assert_equal 'can not set constants with non-shareable objects by non-main Racto
}
# define_method is not allowed
-assert_equal "defined in a different Ractor", %q{
+assert_equal "defined with an un-shareable Proc in a different Ractor", %q{
str = "foo"
define_method(:buggy){|i| str << "#{i}"}
begin
@@ -1207,9 +1312,13 @@ assert_equal 'true', %q{
# Ractor.make_shareable(a_proc) makes a proc shareable.
assert_equal 'true', %q{
a = [1, [2, 3], {a: "4"}]
- pr = Proc.new do
- a
+
+ pr = Ractor.current.instance_eval do
+ Proc.new do
+ a
+ end
end
+
Ractor.make_shareable(a) # referred value should be shareable
Ractor.make_shareable(pr)
Ractor.shareable?(pr)
@@ -1257,10 +1366,12 @@ assert_equal '1', %q{
# 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
+ pr = Ractor.current.instance_eval do
+ Proc.new do
+ c = b # assign to a is okay because c is block local variable
+ # reading b is okay
+ a = b # assign to a is not allowed #=> Ractor::Error
+ end
end
begin
@@ -1362,7 +1473,7 @@ assert_equal "#{N}#{N}", %Q{
}
# enc_table
-assert_equal "#{N/10}", %Q{
+assert_equal "100", %Q{
Ractor.new do
loop do
Encoding.find("test-enc-#{rand(5_000)}").inspect
@@ -1371,7 +1482,7 @@ assert_equal "#{N/10}", %Q{
end
src = Encoding.find("UTF-8")
- #{N/10}.times{|i|
+ 100.times{|i|
src.replicate("test-enc-\#{i}")
}
}
@@ -1418,4 +1529,100 @@ assert_equal "ok", %q{
'ok'
}
+# Can yield back values while GC is sweeping [Bug #18117]
+assert_equal "ok", %q{
+ workers = (0...8).map do
+ Ractor.new do
+ loop do
+ 10_000.times.map { Object.new }
+ Ractor.yield Time.now
+ end
+ end
+ end
+
+ 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) }
+ "ok"
+}
+
+assert_equal "ok", %q{
+ def foo(*); ->{ super }; end
+ begin
+ Ractor.make_shareable(foo)
+ rescue Ractor::IsolationError
+ "ok"
+ end
+}
+
+assert_equal "ok", %q{
+ def foo(**); ->{ super }; end
+ begin
+ Ractor.make_shareable(foo)
+ rescue Ractor::IsolationError
+ "ok"
+ end
+}
+
+assert_equal "ok", %q{
+ def foo(...); ->{ super }; end
+ begin
+ Ractor.make_shareable(foo)
+ rescue Ractor::IsolationError
+ "ok"
+ end
+}
+
+assert_equal "ok", %q{
+ def foo((x), (y)); ->{ super }; end
+ begin
+ Ractor.make_shareable(foo([], []))
+ rescue Ractor::IsolationError
+ "ok"
+ end
+}
+
+assert_equal "ok", %q{
+ module M
+ def foo
+ @foo
+ end
+ end
+
+ class A
+ include M
+
+ def initialize
+ 100.times { |i| instance_variable_set(:"@var_#{i}", "bad: #{i}") }
+ @foo = 2
+ end
+ end
+
+ class B
+ include M
+
+ def initialize
+ @foo = 1
+ end
+ end
+
+ Ractor.new do
+ b = B.new
+ 100_000.times do
+ raise unless b.foo == 1
+ end
+ end
+
+ a = A.new
+ 100_000.times do
+ raise unless a.foo == 2
+ end
+
+ "ok"
+}
+
+assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{
+ Warning[:experimental] = $VERBOSE = true
+ STDERR.reopen(STDOUT)
+ eval("Ractor.new{}.take", nil, "test_ractor.rb", 1)
+}
+
end # if !ENV['GITHUB_WORKFLOW']
diff --git a/bootstraptest/test_syntax.rb b/bootstraptest/test_syntax.rb
index fa27bf2aeb..948e2d7809 100644
--- a/bootstraptest/test_syntax.rb
+++ b/bootstraptest/test_syntax.rb
@@ -628,7 +628,7 @@ assert_equal '2', %q{
}
assert_match /invalid multibyte char/, %q{
- STDERR.reopen(STDOUT)
+ $stderr = STDOUT
eval("\"\xf0".force_encoding("utf-8"))
}, '[ruby-dev:32429]'
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb
index 38a55ff229..5361828403 100644
--- a/bootstraptest/test_thread.rb
+++ b/bootstraptest/test_thread.rb
@@ -243,7 +243,7 @@ assert_equal 'true', %{
}
assert_equal 'ok', %{
- open("zzz.rb", "w") do |f|
+ open("zzz_t1.rb", "w") do |f|
f.puts <<-END
begin
Thread.new { fork { GC.start } }.join
@@ -254,7 +254,7 @@ assert_equal 'ok', %{
end
END
end
- require "./zzz.rb"
+ require "./zzz_t1.rb"
$result
}
@@ -408,7 +408,7 @@ assert_equal 'ok', %q{
}
assert_equal 'ok', %{
- open("zzz.rb", "w") do |f|
+ open("zzz_t2.rb", "w") do |f|
f.puts <<-'end;' # do
begin
m = Thread::Mutex.new
@@ -432,7 +432,7 @@ assert_equal 'ok', %{
end
end;
end
- require "./zzz.rb"
+ require "./zzz_t2.rb"
$result
}
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
new file mode 100644
index 0000000000..5c655b8f25
--- /dev/null
+++ b/bootstraptest/test_yjit.rb
@@ -0,0 +1,3530 @@
+# Regression test for yielding with autosplat to block with
+# optional parameters. https://github.com/Shopify/yjit/issues/313
+assert_equal '[:a, :b, :a, :b]', %q{
+ def yielder(arg) = yield(arg) + yield(arg)
+
+ yielder([:a, :b]) do |c = :c, d = :d|
+ [c, d]
+ end
+}
+
+# Regression test for GC mishap while doing shape transition
+assert_equal '[:ok]', %q{
+ # [Bug #19601]
+ class RegressionTest
+ def initialize
+ @a = @b = @fourth_ivar_does_shape_transition = nil
+ end
+
+ def extender
+ @first_extended_ivar = [:ok]
+ end
+ end
+
+ GC.stress = true
+
+ # Used to crash due to GC run in rb_ensure_iv_list_size()
+ # not marking the newly allocated [:ok].
+ RegressionTest.new.extender.itself
+}
+
+assert_equal 'true', %q{
+ # regression test for tracking type of locals for too long
+ def local_setting_cmp(five)
+ victim = 5
+ five.define_singleton_method(:respond_to?) do |_, _|
+ victim = nil
+ end
+
+ # +1 makes YJIT track that victim is a number and
+ # defined? calls respond_to? from above indirectly
+ unless (victim + 1) && defined?(five.something)
+ # Would return wrong result if we still think `five` is a number
+ victim.nil?
+ end
+ end
+
+ local_setting_cmp(Object.new)
+ local_setting_cmp(Object.new)
+}
+
+assert_equal '18374962167983112447', %q{
+ # regression test for incorrectly discarding 32 bits of a pointer when it
+ # comes to default values.
+ def large_literal_default(n: 0xff00_fabcafe0_00ff)
+ n
+ end
+
+ def call_graph_root
+ large_literal_default
+ end
+
+ call_graph_root
+ call_graph_root
+}
+
+assert_normal_exit %q{
+ # regression test for a leak caught by an assert on --yjit-call-threshold=2
+ Foo = 1
+
+ eval("def foo = [#{(['Foo,']*256).join}]")
+
+ foo
+ foo
+
+ Object.send(:remove_const, :Foo)
+}
+
+assert_normal_exit %q{
+ # Test to ensure send on overriden c functions
+ # doesn't corrupt the stack
+ class Bar
+ def bar(x)
+ x
+ end
+ end
+
+ class Foo
+ def bar
+ Bar.new
+ end
+ end
+
+ foo = Foo.new
+ # before this change, this line would error
+ # because "s" would still be on the stack
+ # String.to_s is the overridden method here
+ p foo.bar.bar("s".__send__(:to_s))
+}
+
+
+assert_equal '[nil, nil, nil, nil, nil, nil]', %q{
+ [NilClass, TrueClass, FalseClass, Integer, Float, Symbol].each do |klass|
+ klass.class_eval("def foo = @foo")
+ end
+
+ [nil, true, false, 0xFABCAFE, 0.42, :cake].map do |instance|
+ instance.foo
+ instance.foo
+ end
+}
+
+assert_equal '0', %q{
+ # This is a regression test for incomplete invalidation from
+ # opt_setinlinecache. This test might be brittle, so
+ # feel free to remove it in the future if it's too annoying.
+ # This test assumes --yjit-call-threshold=2.
+ module M
+ Foo = 1
+ def foo
+ Foo
+ end
+
+ def pin_self_type_then_foo
+ _ = @foo
+ foo
+ end
+
+ def only_ints
+ 1 + self
+ foo
+ end
+ end
+
+ class Integer
+ include M
+ end
+
+ class Sub
+ include M
+ end
+
+ foo_method = M.instance_method(:foo)
+
+ dbg = ->(message) do
+ return # comment this out to get printouts
+
+ $stderr.puts RubyVM::YJIT.disasm(foo_method)
+ $stderr.puts message
+ end
+
+ 2.times { 42.only_ints }
+
+ dbg["There should be two versions of getinlineache"]
+
+ module M
+ remove_const(:Foo)
+ end
+
+ dbg["There should be no getinlinecaches"]
+
+ 2.times do
+ 42.only_ints
+ rescue NameError => err
+ _ = "caught name error #{err}"
+ end
+
+ dbg["There should be one version of getinlineache"]
+
+ 2.times do
+ Sub.new.pin_self_type_then_foo
+ rescue NameError
+ _ = 'second specialization'
+ end
+
+ dbg["There should be two versions of getinlineache"]
+
+ module M
+ Foo = 1
+ end
+
+ dbg["There should still be two versions of getinlineache"]
+
+ 42.only_ints
+
+ dbg["There should be no getinlinecaches"]
+
+ # Find name of the first VM instruction in M#foo.
+ insns = RubyVM::InstructionSequence.of(foo_method).to_a
+ if defined?(RubyVM::YJIT.blocks_for) && (insns.last.find { Array === _1 }&.first == :opt_getinlinecache)
+ RubyVM::YJIT.blocks_for(RubyVM::InstructionSequence.of(foo_method))
+ .filter { _1.iseq_start_index == 0 }.count
+ else
+ 0 # skip the test
+ end
+}
+
+# Check that frozen objects are respected
+assert_equal 'great', %q{
+ class Foo
+ attr_accessor :bar
+ def initialize
+ @bar = 1
+ freeze
+ end
+ end
+
+ foo = Foo.new
+
+ 5.times do
+ begin
+ foo.bar = 2
+ rescue FrozenError
+ end
+ end
+
+ foo.bar == 1 ? "great" : "NG"
+}
+
+# Check that global variable set works
+assert_equal 'string', %q{
+ def foo
+ $foo = "string"
+ end
+
+ foo
+}
+
+# Check that exceptions work when setting global variables
+assert_equal 'rescued', %q{
+ def set_var
+ $var = 100
+ rescue
+ :rescued
+ end
+
+ set_var
+ trace_var(:$var) { raise }
+ set_var
+}
+
+# Check that global variables work
+assert_equal 'string', %q{
+ $foo = "string"
+
+ def foo
+ $foo
+ end
+
+ foo
+}
+
+# Check that exceptions work when getting global variable
+assert_equal 'rescued', %q{
+ Warning[:deprecated] = true
+
+ module Warning
+ def warn(message)
+ raise
+ end
+ end
+
+ def get_var
+ $=
+ rescue
+ :rescued
+ end
+
+ $VERBOSE = true
+ get_var
+ get_var
+}
+
+# Check that global tracepoints work
+assert_equal 'true', %q{
+ def foo
+ 1
+ end
+
+ foo
+ foo
+ foo
+
+ called = false
+
+ tp = TracePoint.new(:return) { |event|
+ if event.method_id == :foo
+ called = true
+ end
+ }
+ tp.enable
+ foo
+ tp.disable
+ called
+}
+
+# Check that local tracepoints work
+assert_equal 'true', %q{
+ def foo
+ 1
+ end
+
+ foo
+ foo
+ foo
+
+ called = false
+
+ tp = TracePoint.new(:return) { |_| called = true }
+ tp.enable(target: method(:foo))
+ foo
+ tp.disable
+ called
+}
+
+# Make sure that optional param methods return the correct value
+assert_equal '1', %q{
+ def m(ary = [])
+ yield(ary)
+ end
+
+ # Warm the JIT with a 0 param call
+ 2.times { m { } }
+ m(1) { |v| v }
+}
+
+# Test for topn
+assert_equal 'array', %q{
+ def threequals(a)
+ case a
+ when Array
+ "array"
+ when Hash
+ "hash"
+ else
+ "unknown"
+ end
+ end
+
+ threequals([])
+ threequals([])
+ threequals([])
+}
+
+# Test for opt_mod
+assert_equal '2', %q{
+ def mod(a, b)
+ a % b
+ end
+
+ mod(7, 5)
+ mod(7, 5)
+}
+
+# Test for opt_mult
+assert_equal '12', %q{
+ def mult(a, b)
+ a * b
+ end
+
+ mult(6, 2)
+ mult(6, 2)
+}
+
+# Test for opt_div
+assert_equal '3', %q{
+ def div(a, b)
+ a / b
+ end
+
+ div(6, 2)
+ div(6, 2)
+}
+
+# BOP redefined methods work when JIT compiled
+assert_equal 'false', %q{
+ def less_than x
+ x < 10
+ end
+
+ class Integer
+ def < x
+ false
+ end
+ end
+
+ less_than 2
+ less_than 2
+ less_than 2
+}
+
+# BOP redefinition works on Integer#<
+assert_equal 'false', %q{
+ def less_than x
+ x < 10
+ end
+
+ less_than 2
+ less_than 2
+
+ class Integer
+ def < x
+ false
+ end
+ end
+
+ less_than 2
+}
+
+# Putobject, less-than operator, fixnums
+assert_equal '2', %q{
+ def check_index(index)
+ if 0x40000000 < index
+ raise "wat? #{index}"
+ end
+ index
+ end
+ check_index 2
+ check_index 2
+}
+
+# foo leaves a temp on the stack before the call
+assert_equal '6', %q{
+ def bar
+ return 5
+ end
+
+ def foo
+ return 1 + bar
+ end
+
+ foo()
+ retval = foo()
+}
+
+# Method with one arguments
+# foo leaves a temp on the stack before the call
+assert_equal '7', %q{
+ def bar(a)
+ return a + 1
+ end
+
+ def foo
+ return 1 + bar(5)
+ end
+
+ foo()
+ retval = foo()
+}
+
+# Method with two arguments
+# foo leaves a temp on the stack before the call
+assert_equal '0', %q{
+ def bar(a, b)
+ return a - b
+ end
+
+ def foo
+ return 1 + bar(1, 2)
+ end
+
+ foo()
+ retval = foo()
+}
+
+# Passing argument types to callees
+assert_equal '8.5', %q{
+ def foo(x, y)
+ x + y
+ end
+
+ def bar
+ foo(7, 1.5)
+ end
+
+ bar
+ bar
+}
+
+# Recursive Ruby-to-Ruby calls
+assert_equal '21', %q{
+ def fib(n)
+ if n < 2
+ return n
+ end
+
+ return fib(n-1) + fib(n-2)
+ end
+
+ r = fib(8)
+}
+
+# Ruby-to-Ruby call and C call
+assert_normal_exit %q{
+ def bar
+ puts('hi!')
+ end
+
+ def foo
+ bar
+ end
+
+ foo()
+ foo()
+}
+
+# Method aliasing
+assert_equal '42', %q{
+ class Foo
+ def method_a
+ 42
+ end
+
+ alias method_b method_a
+
+ def method_a
+ :somethingelse
+ end
+ end
+
+ @obj = Foo.new
+
+ def test
+ @obj.method_b
+ end
+
+ test
+ test
+}
+
+# Method aliasing with method from parent class
+assert_equal '777', %q{
+ class A
+ def method_a
+ 777
+ end
+ end
+
+ class B < A
+ alias method_b method_a
+ end
+
+ @obj = B.new
+
+ def test
+ @obj.method_b
+ end
+
+ test
+ test
+}
+
+# The hash method is a C function and uses the self argument
+assert_equal 'true', %q{
+ def lehashself
+ hash
+ end
+
+ a = lehashself
+ b = lehashself
+ a == b
+}
+
+# Method redefinition (code invalidation) test
+assert_equal '1', %q{
+ def ret1
+ return 1
+ end
+
+ klass = Class.new do
+ def alias_then_hash(klass, method_to_redefine)
+ # Redefine the method to be ret1
+ klass.alias_method(method_to_redefine, :ret1)
+ hash
+ end
+ end
+
+ instance = klass.new
+
+ i = 0
+ while i < 12
+ if i < 11
+ # Redefine the bar method
+ instance.alias_then_hash(klass, :bar)
+ else
+ # Redefine the hash method to be ret1
+ retval = instance.alias_then_hash(klass, :hash)
+ end
+ i += 1
+ end
+
+ retval
+}
+
+# Code invalidation and opt_getinlinecache
+assert_normal_exit %q{
+ class Foo; end
+
+ # Uses the class constant Foo
+ def use_constant(arg)
+ [Foo.new, arg]
+ end
+
+ def propagate_type
+ i = Array.new
+ i.itself # make it remember that i is on-heap
+ use_constant(i)
+ end
+
+ propagate_type
+ propagate_type
+ use_constant(Foo.new)
+ class Jo; end # bump global constant state
+ use_constant(3)
+}
+
+# Method redefinition (code invalidation) and GC
+assert_equal '7', %q{
+ def bar()
+ return 5
+ end
+
+ def foo()
+ bar()
+ end
+
+ foo()
+ foo()
+
+ def bar()
+ return 7
+ end
+
+ 4.times { GC.start }
+
+ foo()
+ foo()
+}
+
+# Method redefinition with two block versions
+assert_equal '7', %q{
+ def bar()
+ return 5
+ end
+
+ def foo(n)
+ return ((n < 5)? 5:false), bar()
+ end
+
+ foo(4)
+ foo(4)
+ foo(10)
+ foo(10)
+
+ def bar()
+ return 7
+ end
+
+ 4.times { GC.start }
+
+ foo(4)
+ foo(4)[1]
+}
+
+# Method redefinition while the method is on the stack
+assert_equal '[777, 1]', %q{
+ def foo
+ redef()
+ 777
+ end
+
+ def redef
+ # Redefine the global foo
+ eval("def foo; 1; end", TOPLEVEL_BINDING)
+
+ # Collect dead code
+ GC.stress = true
+ GC.start
+
+ # But we will return to the original foo,
+ # which remains alive because it's on the stack
+ end
+
+ # Must produce [777, 1]
+ [foo, foo]
+}
+
+# Test for GC safety. Don't invalidate dead iseqs.
+assert_normal_exit %q{
+ Class.new do
+ def foo
+ itself
+ end
+
+ new.foo
+ new.foo
+ new.foo
+ new.foo
+ end
+
+ 4.times { GC.start }
+ def itself
+ self
+ end
+}
+
+# test setinstancevariable on extended objects
+assert_equal '1', %q{
+ class Extended
+ attr_reader :one
+
+ def write_many
+ @a = 1
+ @b = 2
+ @c = 3
+ @d = 4
+ @one = 1
+ end
+ end
+
+ foo = Extended.new
+ foo.write_many
+ foo.write_many
+ foo.write_many
+}
+
+# test setinstancevariable on embedded objects
+assert_equal '1', %q{
+ class Embedded
+ attr_reader :one
+
+ def write_one
+ @one = 1
+ end
+ end
+
+ foo = Embedded.new
+ foo.write_one
+ foo.write_one
+ foo.write_one
+}
+
+# test setinstancevariable after extension
+assert_equal '[10, 11, 12, 13, 1]', %q{
+ class WillExtend
+ attr_reader :one
+
+ def make_extended
+ @foo1 = 10
+ @foo2 = 11
+ @foo3 = 12
+ @foo4 = 13
+ end
+
+ def write_one
+ @one = 1
+ end
+
+ def read_all
+ [@foo1, @foo2, @foo3, @foo4, @one]
+ end
+ end
+
+ foo = WillExtend.new
+ foo.write_one
+ foo.write_one
+ foo.make_extended
+ foo.write_one
+ foo.read_all
+}
+
+# test setinstancevariable on frozen object
+assert_equal 'object was not modified', %q{
+ class WillFreeze
+ def write
+ @ivar = 1
+ end
+ end
+
+ wf = WillFreeze.new
+ wf.write
+ wf.write
+ wf.freeze
+
+ begin
+ wf.write
+ rescue FrozenError
+ "object was not modified"
+ end
+}
+
+# Test getinstancevariable and inline caches
+assert_equal '6', %q{
+ class Foo
+ def initialize
+ @x1 = 1
+ @x2 = 1
+ @x2 = 1
+ @x3 = 1
+ @x4 = 3
+ end
+
+ def bar
+ x = 1
+ @x4 + @x4
+ end
+ end
+
+ f = Foo.new
+ f.bar
+ f.bar
+}
+
+# Test that getinstancevariable codegen checks for extended table size
+assert_equal "nil\n", %q{
+ class A
+ def read
+ @ins1000
+ end
+ end
+
+ ins = A.new
+ other = A.new
+ 10.times { other.instance_variable_set(:"@otr#{_1}", 'value') }
+ 1001.times { ins.instance_variable_set(:"@ins#{_1}", 'value') }
+
+ ins.read
+ ins.read
+ ins.read
+
+ p other.read
+}
+
+# Test that opt_aref checks the class of the receiver
+assert_equal 'special', %q{
+ def foo(array)
+ array[30]
+ end
+
+ foo([])
+ foo([])
+
+ special = []
+ def special.[](idx)
+ 'special'
+ end
+
+ foo(special)
+}
+
+# Test that object references in generated code get marked and moved
+assert_equal "good", %q{
+ def bar
+ "good"
+ end
+
+ def foo
+ bar
+ end
+
+ foo
+ foo
+
+ begin
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+ rescue NotImplementedError
+ # in case compaction isn't supported
+ end
+
+ foo
+}
+
+# Test polymorphic getinstancevariable. T_OBJECT -> T_STRING
+assert_equal 'ok', %q{
+ @hello = @h1 = @h2 = @h3 = @h4 = 'ok'
+ str = ""
+ str.instance_variable_set(:@hello, 'ok')
+
+ public def get
+ @hello
+ end
+
+ get
+ get
+ str.get
+ str.get
+}
+
+# Test polymorphic getinstancevariable, two different classes
+assert_equal 'ok', %q{
+ class Embedded
+ def initialize
+ @ivar = 0
+ end
+
+ def get
+ @ivar
+ end
+ end
+
+ class Extended < Embedded
+ def initialize
+ @v1 = @v2 = @v3 = @v4 = @ivar = 'ok'
+ end
+ end
+
+ embed = Embedded.new
+ extend = Extended.new
+
+ embed.get
+ embed.get
+ extend.get
+ extend.get
+}
+
+# Test megamorphic getinstancevariable
+assert_equal 'ok', %q{
+ parent = Class.new do
+ def initialize
+ @hello = @h1 = @h2 = @h3 = @h4 = 'ok'
+ end
+
+ def get
+ @hello
+ end
+ end
+
+ subclasses = 300.times.map { Class.new(parent) }
+ subclasses.each { _1.new.get }
+ parent.new.get
+}
+
+# Test polymorphic opt_aref. array -> hash
+assert_equal '[42, :key]', %q{
+ def index(obj, idx)
+ obj[idx]
+ end
+
+ index([], 0) # get over compilation threshold
+
+ [
+ index([42], 0),
+ index({0=>:key}, 0),
+ ]
+}
+
+# Test polymorphic opt_aref. hash -> array -> custom class
+assert_equal '[nil, nil, :custom]', %q{
+ def index(obj, idx)
+ obj[idx]
+ end
+
+ custom = Object.new
+ def custom.[](_idx)
+ :custom
+ end
+
+ index({}, 0) # get over compilation threshold
+
+ [
+ index({}, 0),
+ index([], 0),
+ index(custom, 0)
+ ]
+}
+
+# Test polymorphic opt_aref. array -> custom class
+assert_equal '[42, :custom]', %q{
+ def index(obj, idx)
+ obj[idx]
+ end
+
+ custom = Object.new
+ def custom.[](_idx)
+ :custom
+ end
+
+ index([], 0) # get over compilation threshold
+
+ [
+ index([42], 0),
+ index(custom, 0)
+ ]
+}
+
+# Test custom hash method with opt_aref
+assert_equal '[nil, :ok]', %q{
+ def index(obj, idx)
+ obj[idx]
+ end
+
+ custom = Object.new
+ def custom.hash
+ 42
+ end
+
+ h = {custom => :ok}
+
+ [
+ index(h, 0),
+ index(h, custom)
+ ]
+}
+
+# Test default value block for Hash with opt_aref
+assert_equal '[42, :default]', %q{
+ def index(obj, idx)
+ obj[idx]
+ end
+
+ h = Hash.new { :default }
+ h[0] = 42
+
+ [
+ index(h, 0),
+ index(h, 1)
+ ]
+}
+
+# A regression test for making sure cfp->sp is proper when
+# hitting stubs. See :stub-sp-flush:
+assert_equal 'ok', %q{
+ class D
+ def foo
+ Object.new
+ end
+ end
+
+ GC.stress = true
+ 10.times do
+ D.new.foo
+ # ^
+ # This hits a stub with sp_offset > 0
+ end
+
+ :ok
+}
+
+# Test polymorphic callsite, cfunc -> iseq
+assert_equal '[Cfunc, Iseq]', %q{
+ public def call_itself
+ itself # the polymorphic callsite
+ end
+
+ class Cfunc; end
+
+ class Iseq
+ def itself
+ self
+ end
+ end
+
+ call_itself # cross threshold
+
+ [Cfunc.call_itself, Iseq.call_itself]
+}
+
+# Test polymorphic callsite, iseq -> cfunc
+assert_equal '[Iseq, Cfunc]', %q{
+ public def call_itself
+ itself # the polymorphic callsite
+ end
+
+ class Cfunc; end
+
+ class Iseq
+ def itself
+ self
+ end
+ end
+
+ call_itself # cross threshold
+
+ [Iseq.call_itself, Cfunc.call_itself]
+}
+
+# attr_reader method
+assert_equal '[100, 299]', %q{
+ class A
+ attr_reader :foo
+
+ def initialize
+ @foo = 100
+ end
+
+ # Make it extended
+ def fill!
+ @bar = @jojo = @as = @sdfsdf = @foo = 299
+ end
+ end
+
+ def bar(ins)
+ ins.foo
+ end
+
+ ins = A.new
+ oth = A.new
+ oth.fill!
+
+ bar(ins)
+ bar(oth)
+
+ [bar(ins), bar(oth)]
+}
+
+# get ivar on object, then on hash
+assert_equal '[42, 100]', %q{
+ class Hash
+ attr_accessor :foo
+ end
+
+ class A
+ attr_reader :foo
+
+ def initialize
+ @foo = 42
+ end
+ end
+
+ def use(val)
+ val.foo
+ end
+
+
+ h = {}
+ h.foo = 100
+ obj = A.new
+
+ use(obj)
+ [use(obj), use(h)]
+}
+
+# get ivar on String
+assert_equal '[nil, nil, 42, 42]', %q{
+ # @foo to exercise the getinstancevariable instruction
+ public def get_foo
+ @foo
+ end
+
+ get_foo
+ get_foo # compile it for the top level object
+
+ class String
+ attr_reader :foo
+ end
+
+ def run
+ str = String.new
+
+ getter = str.foo
+ insn = str.get_foo
+
+ str.instance_variable_set(:@foo, 42)
+
+ [getter, insn, str.foo, str.get_foo]
+ end
+
+ run
+ run
+}
+
+# splatting an empty array on a getter
+assert_equal '42', %q{
+ @foo = 42
+ module Kernel
+ attr_reader :foo
+ end
+
+ def run
+ foo(*[])
+ end
+
+ run
+ run
+}
+
+# splatting an empty array on a specialized method
+assert_equal 'ok', %q{
+ def run
+ "ok".to_s(*[])
+ end
+
+ run
+ run
+}
+
+# splatting an single element array on a specialized method
+assert_equal '[1]', %q{
+ def run
+ [].<<(*[1])
+ end
+
+ run
+ run
+}
+
+# specialized method with wrong args
+assert_equal 'ok', %q{
+ def run(x)
+ "bad".to_s(123) if x
+ rescue
+ :ok
+ end
+
+ run(false)
+ run(true)
+}
+
+# getinstancevariable on Symbol
+assert_equal '[nil, nil]', %q{
+ # @foo to exercise the getinstancevariable instruction
+ public def get_foo
+ @foo
+ end
+
+ dyn_sym = ("a" + "b").to_sym
+ sym = :static
+
+ # compile get_foo
+ dyn_sym.get_foo
+ dyn_sym.get_foo
+
+ [dyn_sym.get_foo, sym.get_foo]
+}
+
+# attr_reader on Symbol
+assert_equal '[nil, nil]', %q{
+ class Symbol
+ attr_reader :foo
+ end
+
+ public def get_foo
+ foo
+ end
+
+ dyn_sym = ("a" + "b").to_sym
+ sym = :static
+
+ # compile get_foo
+ dyn_sym.get_foo
+ dyn_sym.get_foo
+
+ [dyn_sym.get_foo, sym.get_foo]
+}
+
+# passing too few arguments to method with optional parameters
+assert_equal 'raised', %q{
+ def opt(a, b = 0)
+ end
+
+ def use
+ opt
+ end
+
+ use rescue nil
+ begin
+ use
+ :ng
+ rescue ArgumentError
+ :raised
+ end
+}
+
+# passing too many arguments to method with optional parameters
+assert_equal 'raised', %q{
+ def opt(a, b = 0)
+ end
+
+ def use
+ opt(1, 2, 3, 4)
+ end
+
+ use rescue nil
+ begin
+ use
+ :ng
+ rescue ArgumentError
+ :raised
+ end
+}
+
+# test calling Ruby method with a block
+assert_equal '[1, 2, 42]', %q{
+ def thing(a, b)
+ [a, b, yield]
+ end
+
+ def use
+ thing(1,2) { 42 }
+ end
+
+ use
+ use
+}
+
+# test calling C method with a block
+assert_equal '[42, 42]', %q{
+ def use(array, initial)
+ array.reduce(initial) { |a, b| a + b }
+ end
+
+ use([], 0)
+ [use([2, 2], 38), use([14, 14, 14], 0)]
+}
+
+# test calling block param
+assert_equal '[1, 2, 42]', %q{
+ def foo(&block)
+ block.call
+ end
+
+ [foo {1}, foo {2}, foo {42}]
+}
+
+# test calling without block param
+assert_equal '[1, false, 2, false]', %q{
+ def bar
+ block_given? && yield
+ end
+
+ def foo(&block)
+ bar(&block)
+ end
+
+ [foo { 1 }, foo, foo { 2 }, foo]
+}
+
+# test calling block param failing
+assert_equal '42', %q{
+ def foo(&block)
+ block.call
+ end
+
+ foo {} # warmup
+
+ begin
+ foo
+ rescue NoMethodError => e
+ 42 if nil == e.receiver
+ end
+}
+
+# test calling method taking block param
+assert_equal '[Proc, 1, 2, 3, Proc]', %q{
+ def three(a, b, c, &block)
+ [a, b, c, block.class]
+ end
+
+ def zero(&block)
+ block.class
+ end
+
+ def use_three
+ three(1, 2, 3) {}
+ end
+
+ def use_zero
+ zero {}
+ end
+
+ use_three
+ use_zero
+
+ [use_zero] + use_three
+}
+
+# test building empty array
+assert_equal '[]', %q{
+ def build_arr
+ []
+ end
+
+ build_arr
+ build_arr
+}
+
+# test building array of one element
+assert_equal '[5]', %q{
+ def build_arr(val)
+ [val]
+ end
+
+ build_arr(5)
+ build_arr(5)
+}
+
+# test building array of several element
+assert_equal '[5, 5, 5, 5, 5]', %q{
+ def build_arr(val)
+ [val, val, val, val, val]
+ end
+
+ build_arr(5)
+ build_arr(5)
+}
+
+# test building empty hash
+assert_equal '{}', %q{
+ def build_hash
+ {}
+ end
+
+ build_hash
+ build_hash
+}
+
+# test building hash with values
+assert_equal '{:foo=>:bar}', %q{
+ def build_hash(val)
+ { foo: val }
+ end
+
+ build_hash(:bar)
+ build_hash(:bar)
+}
+
+# test string interpolation with known types
+assert_equal 'foobar', %q{
+ def make_str
+ foo = -"foo"
+ bar = -"bar"
+ "#{foo}#{bar}"
+ end
+
+ make_str
+ make_str
+}
+
+# test string interpolation with unknown types
+assert_equal 'foobar', %q{
+ def make_str(foo, bar)
+ "#{foo}#{bar}"
+ end
+
+ make_str("foo", "bar")
+ make_str("foo", "bar")
+}
+
+# test string interpolation with known non-strings
+assert_equal 'foo123', %q{
+ def make_str
+ foo = -"foo"
+ bar = 123
+ "#{foo}#{bar}"
+ end
+
+ make_str
+ make_str
+}
+
+# test string interpolation with unknown non-strings
+assert_equal 'foo123', %q{
+ def make_str(foo, bar)
+ "#{foo}#{bar}"
+ end
+
+ make_str("foo", 123)
+ make_str("foo", 123)
+}
+
+# test that invalidation of String#to_s doesn't crash
+assert_equal 'meh', %q{
+ def inval_method
+ "".to_s
+ end
+
+ inval_method
+
+ class String
+ def to_s
+ "meh"
+ end
+ end
+
+ inval_method
+}
+
+# test that overriding to_s on a String subclass works consistently
+assert_equal 'meh', %q{
+ class MyString < String
+ def to_s
+ "meh"
+ end
+ end
+
+ def test_to_s(obj)
+ obj.to_s
+ end
+
+ OBJ = MyString.new
+
+ # Should return '' both times
+ test_to_s("")
+ test_to_s("")
+
+ # Can return '' if YJIT optimises String#to_s too aggressively
+ test_to_s(OBJ)
+ test_to_s(OBJ)
+}
+
+# test string interpolation with overridden to_s
+assert_equal 'foo', %q{
+ class String
+ def to_s
+ "bad"
+ end
+ end
+
+ def make_str(foo)
+ "#{foo}"
+ end
+
+ make_str("foo")
+ make_str("foo")
+}
+
+# Test that String unary plus returns the same object ID for an unfrozen string.
+assert_equal 'true', %q{
+ def jittable_method
+ str = "bar"
+
+ old_obj_id = str.object_id
+ uplus_str = +str
+
+ uplus_str.object_id == old_obj_id
+ end
+ jittable_method
+}
+
+# Test that String unary plus returns a different unfrozen string when given a frozen string
+assert_equal 'false', %q{
+ # Logic needs to be inside an ISEQ, such as a method, for YJIT to compile it
+ def jittable_method
+ frozen_str = "foo".freeze
+
+ old_obj_id = frozen_str.object_id
+ uplus_str = +frozen_str
+
+ uplus_str.object_id == old_obj_id || uplus_str.frozen?
+ end
+
+ jittable_method
+}
+
+# String-subclass objects should behave as expected inside string-interpolation via concatstrings
+assert_equal 'monkeys / monkeys, yo!', %q{
+ class MyString < String
+ # This is a terrible idea in production code, but we'd like YJIT to match CRuby
+ def to_s
+ super + ", yo!"
+ end
+ end
+
+ def jittable_method
+ m = MyString.new('monkeys')
+ "#{m} / #{m.to_s}"
+ end
+
+ jittable_method
+}
+
+# String-subclass objects should behave as expected for string equality
+assert_equal 'false', %q{
+ class MyString < String
+ # This is a terrible idea in production code, but we'd like YJIT to match CRuby
+ def ==(b)
+ "#{self}_" == b
+ end
+ end
+
+ def jittable_method
+ ma = MyString.new("a")
+
+ # Check equality with string-subclass receiver
+ ma == "a" || ma != "a_" ||
+ # Check equality with string receiver
+ "a_" == ma || "a" != ma ||
+ # Check equality between string subclasses
+ ma != MyString.new("a_") ||
+ # Make sure "string always equals itself" check isn't used with overridden equality
+ ma == ma
+ end
+ jittable_method
+}
+
+# Test to_s duplicates a string subclass object but not a string
+assert_equal 'false', %q{
+ class MyString < String; end
+
+ def jittable_method
+ a = "a"
+ ma = MyString.new("a")
+
+ a.object_id != a.to_s.object_id ||
+ ma.object_id == ma.to_s.object_id
+ end
+ jittable_method
+}
+
+# Test freeze on string subclass
+assert_equal 'true', %q{
+ class MyString < String; end
+
+ def jittable_method
+ fma = MyString.new("a").freeze
+
+ # Freezing a string subclass should not duplicate it
+ fma.object_id == fma.freeze.object_id
+ end
+ jittable_method
+}
+
+# Test unary minus on string subclass
+assert_equal 'true', %q{
+ class MyString < String; end
+
+ def jittable_method
+ ma = MyString.new("a")
+ fma = MyString.new("a").freeze
+
+ # Unary minus on frozen string subclass should not duplicate it
+ fma.object_id == (-fma).object_id &&
+ # Unary minus on unfrozen string subclass should duplicate it
+ ma.object_id != (-ma).object_id
+ end
+ jittable_method
+}
+
+# Test unary plus on string subclass
+assert_equal 'true', %q{
+ class MyString < String; end
+
+ def jittable_method
+ fma = MyString.new("a").freeze
+
+ # Unary plus on frozen string subclass should not duplicate it
+ fma.object_id != (+fma).object_id
+ end
+ jittable_method
+}
+
+# Test << operator on string subclass
+assert_equal 'abab', %q{
+ class MyString < String; end
+
+ def jittable_method
+ a = -"a"
+ mb = MyString.new("b")
+
+ buf = String.new
+ mbuf = MyString.new
+
+ buf << a << mb
+ mbuf << a << mb
+
+ buf + mbuf
+ end
+ jittable_method
+}
+
+# test invokebuiltin as used in struct assignment
+assert_equal '123', %q{
+ def foo(obj)
+ obj.foo = 123
+ end
+
+ struct = Struct.new(:foo)
+ obj = struct.new
+ foo(obj)
+ foo(obj)
+}
+
+# test invokebuiltin_delegate as used inside Dir.open
+assert_equal '.', %q{
+ def foo(path)
+ Dir.open(path).path
+ end
+
+ foo(".")
+ foo(".")
+}
+
+# test invokebuiltin_delegate_leave in method called from jit
+assert_normal_exit %q{
+ def foo(obj)
+ obj.clone
+ end
+
+ foo(Object.new)
+ foo(Object.new)
+}
+
+# test invokebuiltin_delegate_leave in method called from cfunc
+assert_normal_exit %q{
+ def foo(obj)
+ [obj].map(&:clone)
+ end
+
+ foo(Object.new)
+ foo(Object.new)
+}
+
+# defining TrueClass#!
+assert_equal '[false, false, :ok]', %q{
+ def foo(obj)
+ !obj
+ end
+
+ x = foo(true)
+ y = foo(true)
+
+ class TrueClass
+ def !
+ :ok
+ end
+ end
+
+ z = foo(true)
+
+ [x, y, z]
+}
+
+# defining FalseClass#!
+assert_equal '[true, true, :ok]', %q{
+ def foo(obj)
+ !obj
+ end
+
+ x = foo(false)
+ y = foo(false)
+
+ class FalseClass
+ def !
+ :ok
+ end
+ end
+
+ z = foo(false)
+
+ [x, y, z]
+}
+
+# defining NilClass#!
+assert_equal '[true, true, :ok]', %q{
+ def foo(obj)
+ !obj
+ end
+
+ x = foo(nil)
+ y = foo(nil)
+
+ class NilClass
+ def !
+ :ok
+ end
+ end
+
+ z = foo(nil)
+
+ [x, y, z]
+}
+
+# polymorphic opt_not
+assert_equal '[true, true, false, false, false, false, false]', %q{
+ def foo(obj)
+ !obj
+ end
+
+ foo(0)
+ [foo(nil), foo(false), foo(true), foo([]), foo(0), foo(4.2), foo(:sym)]
+}
+
+# getlocal with 2 levels
+assert_equal '7', %q{
+ def foo(foo, bar)
+ while foo > 0
+ while bar > 0
+ return foo + bar
+ end
+ end
+ end
+
+ foo(5,2)
+ foo(5,2)
+}
+
+# test pattern matching
+assert_equal '[:ok, :ok]', %q{
+ class C
+ def destructure_keys
+ {}
+ end
+ end
+
+ pattern_match = ->(i) do
+ case i
+ in a: 0
+ :ng
+ else
+ :ok
+ end
+ end
+
+ [{}, C.new].map(&pattern_match)
+}
+
+# Call to object with singleton
+assert_equal '123', %q{
+ obj = Object.new
+ def obj.foo
+ 123
+ end
+
+ def foo(obj)
+ obj.foo()
+ end
+
+ foo(obj)
+ foo(obj)
+}
+
+# Call method on an object that has a non-material
+# singleton class.
+# TODO: assert that it takes no side exits? This
+# test case revealed that we were taking exits unnecessarily.
+assert_normal_exit %q{
+ def foo(obj)
+ obj.itself
+ end
+
+ o = Object.new.singleton_class
+ foo(o)
+ foo(o)
+}
+
+# Call to singleton class
+assert_equal '123', %q{
+ class Foo
+ def self.foo
+ 123
+ end
+ end
+
+ def foo(obj)
+ obj.foo()
+ end
+
+ foo(Foo)
+ foo(Foo)
+}
+
+# invokesuper edge case
+assert_equal '[:A, [:A, :B]]', %q{
+ class B
+ def foo = :B
+ end
+
+ class A < B
+ def foo = [:A, super()]
+ end
+
+ A.new.foo
+ A.new.foo # compile A#foo
+
+ class C < A
+ define_method(:bar, A.instance_method(:foo))
+ end
+
+ C.new.bar
+}
+
+# Same invokesuper bytecode, multiple destinations
+assert_equal '[:Forward, :SecondTerminus]', %q{
+ module Terminus
+ def foo = :Terminus
+ end
+
+ module SecondTerminus
+ def foo = :SecondTerminus
+ end
+
+
+ module Forward
+ def foo = [:Forward, super]
+ end
+
+ class B
+ include SecondTerminus
+ end
+
+ class A < B
+ include Terminus
+ include Forward
+ end
+
+ A.new.foo
+ A.new.foo # compile
+
+ class B
+ include Forward
+ alias bar foo
+ end
+
+ # A.ancestors.take(5) == [A, Forward, Terminus, B, Forward, SecondTerminus]
+
+ A.new.bar
+}
+
+# invokesuper calling into itself
+assert_equal '[:B, [:B, :m]]', %q{
+ module M
+ def foo = :m
+ end
+
+ class B
+ include M
+ def foo = [:B, super]
+ end
+
+ ins = B.new
+ ins.singleton_class # materialize the singleton class
+ ins.foo
+ ins.foo # compile
+
+ ins.singleton_class.define_method(:bar, B.instance_method(:foo))
+ ins.bar
+}
+
+# invokesuper changed ancestor
+assert_equal '[:A, [:M, :B]]', %q{
+ class B
+ def foo
+ :B
+ end
+ end
+
+ class A < B
+ def foo
+ [:A, super]
+ end
+ end
+
+ module M
+ def foo
+ [:M, super]
+ end
+ end
+
+ ins = A.new
+ ins.foo
+ ins.foo
+ A.include(M)
+ ins.foo
+}
+
+# invokesuper changed ancestor via prepend
+assert_equal '[:A, [:M, :B]]', %q{
+ class B
+ def foo
+ :B
+ end
+ end
+
+ class A < B
+ def foo
+ [:A, super]
+ end
+ end
+
+ module M
+ def foo
+ [:M, super]
+ end
+ end
+
+ ins = A.new
+ ins.foo
+ ins.foo
+ B.prepend(M)
+ ins.foo
+}
+
+# invokesuper replaced method
+assert_equal '[:A, :Btwo]', %q{
+ class B
+ def foo
+ :B
+ end
+ end
+
+ class A < B
+ def foo
+ [:A, super]
+ end
+ end
+
+ ins = A.new
+ ins.foo
+ ins.foo
+ class B
+ def foo
+ :Btwo
+ end
+ end
+ ins.foo
+}
+
+# Call to fixnum
+assert_equal '[true, false]', %q{
+ def is_odd(obj)
+ obj.odd?
+ end
+
+ is_odd(1)
+ is_odd(1)
+
+ [is_odd(123), is_odd(456)]
+}
+
+# Call to bignum
+assert_equal '[true, false]', %q{
+ def is_odd(obj)
+ obj.odd?
+ end
+
+ bignum = 99999999999999999999
+ is_odd(bignum)
+ is_odd(bignum)
+
+ [is_odd(bignum), is_odd(bignum+1)]
+}
+
+# Call to fixnum and bignum
+assert_equal '[true, false, true, false]', %q{
+ def is_odd(obj)
+ obj.odd?
+ end
+
+ bignum = 99999999999999999999
+ is_odd(bignum)
+ is_odd(bignum)
+ is_odd(123)
+ is_odd(123)
+
+ [is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)]
+}
+
+# Call to static and dynamic symbol
+assert_equal 'bar', %q{
+ def to_string(obj)
+ obj.to_s
+ end
+
+ to_string(:foo)
+ to_string(:foo)
+ to_string((-"bar").to_sym)
+ to_string((-"bar").to_sym)
+}
+
+# Call to flonum and heap float
+assert_equal '[nil, nil, nil, 1]', %q{
+ def is_inf(obj)
+ obj.infinite?
+ end
+
+ is_inf(0.0)
+ is_inf(0.0)
+ is_inf(1e256)
+ is_inf(1e256)
+
+ [
+ is_inf(0.0),
+ is_inf(1.0),
+ is_inf(1e256),
+ is_inf(1.0/0.0)
+ ]
+}
+
+assert_equal '[1, 2, 3, 4, 5]', %q{
+ def splatarray
+ [*(1..5)]
+ end
+
+ splatarray
+ splatarray
+}
+
+assert_equal '[1, 1, 2, 1, 2, 3]', %q{
+ def expandarray
+ arr = [1, 2, 3]
+
+ a, = arr
+ b, c, = arr
+ d, e, f = arr
+
+ [a, b, c, d, e, f]
+ end
+
+ expandarray
+ expandarray
+}
+
+assert_equal '[1, 1]', %q{
+ def expandarray_useless_splat
+ arr = (1..10).to_a
+
+ a, * = arr
+ b, (*) = arr
+
+ [a, b]
+ end
+
+ expandarray_useless_splat
+ expandarray_useless_splat
+}
+
+assert_equal '[:not_heap, nil, nil]', %q{
+ def expandarray_not_heap
+ a, b, c = :not_heap
+ [a, b, c]
+ end
+
+ expandarray_not_heap
+ expandarray_not_heap
+}
+
+assert_equal '[:not_array, nil, nil]', %q{
+ def expandarray_not_array(obj)
+ a, b, c = obj
+ [a, b, c]
+ end
+
+ obj = Object.new
+ def obj.to_ary
+ [:not_array]
+ end
+
+ expandarray_not_array(obj)
+ expandarray_not_array(obj)
+}
+
+assert_equal '[1, 2, nil]', %q{
+ def expandarray_rhs_too_small
+ a, b, c = [1, 2]
+ [a, b, c]
+ end
+
+ expandarray_rhs_too_small
+ expandarray_rhs_too_small
+}
+
+assert_equal '[1, [2]]', %q{
+ def expandarray_splat
+ a, *b = [1, 2]
+ [a, b]
+ end
+
+ expandarray_splat
+ expandarray_splat
+}
+
+assert_equal '2', %q{
+ def expandarray_postarg
+ *, a = [1, 2]
+ a
+ end
+
+ expandarray_postarg
+ expandarray_postarg
+}
+
+assert_equal '10', %q{
+ obj = Object.new
+ val = nil
+ obj.define_singleton_method(:to_ary) { val = 10; [] }
+
+ def expandarray_always_call_to_ary(object)
+ * = object
+ end
+
+ expandarray_always_call_to_ary(obj)
+ expandarray_always_call_to_ary(obj)
+
+ val
+}
+
+# regression test of local type change
+assert_equal '1.1', %q{
+def bar(baz, quux)
+ if baz.integer?
+ baz, quux = quux, nil
+ end
+ baz.to_s
+end
+
+bar(123, 1.1)
+bar(123, 1.1)
+}
+
+# test enabling a line TracePoint in a C method call
+assert_equal '[[:line, true]]', %q{
+ events = []
+ events.instance_variable_set(
+ :@tp,
+ TracePoint.new(:line) { |tp| events << [tp.event, tp.lineno] if tp.path == __FILE__ }
+ )
+ def events.to_str
+ @tp.enable; ''
+ end
+
+ # Stay in generated code while enabling tracing
+ def events.compiled(obj)
+ String(obj)
+ @tp.disable; __LINE__
+ end
+
+ line = events.compiled(events)
+ events[0][-1] = (events[0][-1] == line)
+
+ events
+}
+
+# test enabling a c_return TracePoint in a C method call
+assert_equal '[[:c_return, :String, :string_alias, "events_to_str"]]', %q{
+ events = []
+ events.instance_variable_set(:@tp, TracePoint.new(:c_return) { |tp| events << [tp.event, tp.method_id, tp.callee_id, tp.return_value] })
+ def events.to_str
+ @tp.enable; 'events_to_str'
+ end
+
+ # Stay in generated code while enabling tracing
+ alias string_alias String
+ def events.compiled(obj)
+ string_alias(obj)
+ @tp.disable
+ end
+
+ events.compiled(events)
+
+ events
+} unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # MJIT calls extra Ruby methods
+
+# test enabling a TracePoint that targets a particular line in a C method call
+assert_equal '[true]', %q{
+ events = []
+ events.instance_variable_set(:@tp, TracePoint.new(:line) { |tp| events << tp.lineno })
+ def events.to_str
+ @tp.enable(target: method(:compiled))
+ ''
+ end
+
+ # Stay in generated code while enabling tracing
+ def events.compiled(obj)
+ String(obj)
+ __LINE__
+ end
+
+ line = events.compiled(events)
+ events[0] = (events[0] == line)
+
+ events
+}
+
+# test enabling tracing in the middle of splatarray
+assert_equal '[true]', %q{
+ events = []
+ obj = Object.new
+ obj.instance_variable_set(:@tp, TracePoint.new(:line) { |tp| events << tp.lineno })
+ def obj.to_a
+ @tp.enable(target: method(:compiled))
+ []
+ end
+
+ # Enable tracing in the middle of the splatarray instruction
+ def obj.compiled(obj)
+ * = *obj
+ __LINE__
+ end
+
+ obj.compiled([])
+ line = obj.compiled(obj)
+ events[0] = (events[0] == line)
+
+ events
+}
+
+# test enabling tracing in the middle of opt_aref. Different since the codegen
+# for it ends in a jump.
+assert_equal '[true]', %q{
+ def lookup(hash, tp)
+ hash[42]
+ tp.disable; __LINE__
+ end
+
+ lines = []
+ tp = TracePoint.new(:line) { lines << _1.lineno if _1.path == __FILE__ }
+
+ lookup(:foo, tp)
+ lookup({}, tp)
+
+ enable_tracing_on_missing = Hash.new { tp.enable }
+
+ expected_line = lookup(enable_tracing_on_missing, tp)
+
+ lines[0] = true if lines[0] == expected_line
+
+ lines
+}
+
+# test enabling c_call tracing before compiling
+assert_equal '[[:c_call, :itself]]', %q{
+ def shouldnt_compile
+ itself
+ end
+
+ events = []
+ tp = TracePoint.new(:c_call) { |tp| events << [tp.event, tp.method_id] }
+
+ # assume first call compiles
+ tp.enable { shouldnt_compile }
+
+ events
+} unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # MJIT calls extra Ruby methods
+
+# test enabling c_return tracing before compiling
+assert_equal '[[:c_return, :itself, main]]', %q{
+ def shouldnt_compile
+ itself
+ end
+
+ events = []
+ tp = TracePoint.new(:c_return) { |tp| events << [tp.event, tp.method_id, tp.return_value] }
+
+ # assume first call compiles
+ tp.enable { shouldnt_compile }
+
+ events
+} unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # MJIT calls extra Ruby methods
+
+# test c_call invalidation
+assert_equal '[[:c_call, :itself]]', %q{
+ # enable the event once to make sure invalidation
+ # happens the second time we enable it
+ TracePoint.new(:c_call) {}.enable{}
+
+ def compiled
+ itself
+ end
+
+ # assume first call compiles
+ compiled
+
+ events = []
+ tp = TracePoint.new(:c_call) { |tp| events << [tp.event, tp.method_id] }
+ tp.enable { compiled }
+
+ events
+}
+
+# test enabling tracing for a suspended fiber
+assert_equal '[[:return, 42]]', %q{
+ def traced_method
+ Fiber.yield
+ 42
+ end
+
+ events = []
+ tp = TracePoint.new(:return) { events << [_1.event, _1.return_value] }
+ # assume first call compiles
+ fiber = Fiber.new { traced_method }
+ fiber.resume
+ tp.enable(target: method(:traced_method))
+ fiber.resume
+
+ events
+}
+
+# test compiling on non-tracing ractor then running on a tracing one
+assert_equal '[:itself]', %q{
+ def traced_method
+ itself
+ end
+
+ tracing_ractor = Ractor.new do
+ # 1: start tracing
+ events = []
+ tp = TracePoint.new(:c_call) { events << _1.method_id }
+ tp.enable
+ Ractor.yield(nil)
+
+ # 3: run compiled method on tracing ractor
+ Ractor.yield(nil)
+ traced_method
+
+ events
+ ensure
+ tp&.disable
+ end
+
+ tracing_ractor.take
+
+ # 2: compile on non tracing ractor
+ traced_method
+
+ tracing_ractor.take
+ tracing_ractor.take
+}
+
+# Try to hit a lazy branch stub while another ractor enables tracing
+assert_equal '42', %q{
+ def compiled(arg)
+ if arg
+ arg + 1
+ else
+ itself
+ itself
+ end
+ end
+
+ ractor = Ractor.new do
+ compiled(false)
+ Ractor.yield(nil)
+ compiled(41)
+ end
+
+ tp = TracePoint.new(:line) { itself }
+ ractor.take
+ tp.enable
+
+ ractor.take
+}
+
+# Test equality with changing types
+assert_equal '[true, false, false, false]', %q{
+ def eq(a, b)
+ a == b
+ end
+
+ [
+ eq("foo", "foo"),
+ eq("foo", "bar"),
+ eq(:foo, "bar"),
+ eq("foo", :bar)
+ ]
+}
+
+# Redefined String eq
+assert_equal 'true', %q{
+ class String
+ def ==(other)
+ true
+ end
+ end
+
+ def eq(a, b)
+ a == b
+ end
+
+ eq("foo", "bar")
+ eq("foo", "bar")
+}
+
+# Redefined Integer eq
+assert_equal 'true', %q{
+ class Integer
+ def ==(other)
+ true
+ end
+ end
+
+ def eq(a, b)
+ a == b
+ end
+
+ eq(1, 2)
+ eq(1, 2)
+}
+
+# aset on array with invalid key
+assert_normal_exit %q{
+ def foo(arr)
+ arr[:foo] = 123
+ end
+
+ foo([1]) rescue nil
+ foo([1]) rescue nil
+}
+
+# test ractor exception on when setting ivar
+assert_equal '42', %q{
+ class A
+ def self.foo
+ _foo = 1
+ _bar = 2
+ begin
+ @bar = _foo + _bar
+ rescue Ractor::IsolationError
+ 42
+ end
+ end
+ end
+
+ A.foo
+ A.foo
+
+ Ractor.new { A.foo }.take
+}
+
+assert_equal '["plain", "special", "sub", "plain"]', %q{
+ def foo(arg)
+ arg.to_s
+ end
+
+ class Sub < String
+ end
+
+ special = String.new("special")
+ special.singleton_class
+
+ [
+ foo("plain"),
+ foo(special),
+ foo(Sub.new("sub")),
+ foo("plain")
+ ]
+}
+
+assert_equal '["sub", "sub"]', %q{
+ def foo(arg)
+ arg.to_s
+ end
+
+ class Sub < String
+ def to_s
+ super
+ end
+ end
+
+ sub = Sub.new("sub")
+
+ [foo(sub), foo(sub)]
+}
+
+assert_equal '[1]', %q{
+ def kwargs(value:)
+ value
+ end
+
+ 5.times.map { kwargs(value: 1) }.uniq
+}
+
+assert_equal '[:ok]', %q{
+ def kwargs(value:)
+ value
+ end
+
+ 5.times.map { kwargs() rescue :ok }.uniq
+}
+
+assert_equal '[:ok]', %q{
+ def kwargs(a:, b: nil)
+ value
+ end
+
+ 5.times.map { kwargs(b: 123) rescue :ok }.uniq
+}
+
+assert_equal '[[1, 2]]', %q{
+ def kwargs(left:, right:)
+ [left, right]
+ end
+
+ 5.times.flat_map do
+ [
+ kwargs(left: 1, right: 2),
+ kwargs(right: 2, left: 1)
+ ]
+ end.uniq
+}
+
+assert_equal '[[1, 2]]', %q{
+ def kwargs(lead, kwarg:)
+ [lead, kwarg]
+ end
+
+ 5.times.map { kwargs(1, kwarg: 2) }.uniq
+}
+
+# optional and keyword args
+assert_equal '[[1, 2, 3]]', %q{
+ def opt_and_kwargs(a, b=2, c: nil)
+ [a,b,c]
+ end
+
+ 5.times.map { opt_and_kwargs(1, c: 3) }.uniq
+}
+
+assert_equal '[[1, 2, 3]]', %q{
+ def opt_and_kwargs(a, b=nil, c: nil)
+ [a,b,c]
+ end
+
+ 5.times.map { opt_and_kwargs(1, 2, c: 3) }.uniq
+}
+
+# Bug #18453
+assert_equal '[[1, nil, 2]]', %q{
+ def opt_and_kwargs(a = {}, b: nil, c: nil)
+ [a, b, c]
+ end
+
+ 5.times.map { opt_and_kwargs(1, c: 2) }.uniq
+}
+
+assert_equal '[[{}, nil, 1]]', %q{
+ def opt_and_kwargs(a = {}, b: nil, c: nil)
+ [a, b, c]
+ end
+
+ 5.times.map { opt_and_kwargs(c: 1) }.uniq
+}
+
+# leading and keyword arguments are swapped into the right order
+assert_equal '[[1, 2, 3, 4, 5, 6]]', %q{
+ def kwargs(five, six, a:, b:, c:, d:)
+ [a, b, c, d, five, six]
+ end
+
+ 5.times.flat_map do
+ [
+ kwargs(5, 6, a: 1, b: 2, c: 3, d: 4),
+ kwargs(5, 6, a: 1, b: 2, d: 4, c: 3),
+ kwargs(5, 6, a: 1, c: 3, b: 2, d: 4),
+ kwargs(5, 6, a: 1, c: 3, d: 4, b: 2),
+ kwargs(5, 6, a: 1, d: 4, b: 2, c: 3),
+ kwargs(5, 6, a: 1, d: 4, c: 3, b: 2),
+ kwargs(5, 6, b: 2, a: 1, c: 3, d: 4),
+ kwargs(5, 6, b: 2, a: 1, d: 4, c: 3),
+ kwargs(5, 6, b: 2, c: 3, a: 1, d: 4),
+ kwargs(5, 6, b: 2, c: 3, d: 4, a: 1),
+ kwargs(5, 6, b: 2, d: 4, a: 1, c: 3),
+ kwargs(5, 6, b: 2, d: 4, c: 3, a: 1),
+ kwargs(5, 6, c: 3, a: 1, b: 2, d: 4),
+ kwargs(5, 6, c: 3, a: 1, d: 4, b: 2),
+ kwargs(5, 6, c: 3, b: 2, a: 1, d: 4),
+ kwargs(5, 6, c: 3, b: 2, d: 4, a: 1),
+ kwargs(5, 6, c: 3, d: 4, a: 1, b: 2),
+ kwargs(5, 6, c: 3, d: 4, b: 2, a: 1),
+ kwargs(5, 6, d: 4, a: 1, b: 2, c: 3),
+ kwargs(5, 6, d: 4, a: 1, c: 3, b: 2),
+ kwargs(5, 6, d: 4, b: 2, a: 1, c: 3),
+ kwargs(5, 6, d: 4, b: 2, c: 3, a: 1),
+ kwargs(5, 6, d: 4, c: 3, a: 1, b: 2),
+ kwargs(5, 6, d: 4, c: 3, b: 2, a: 1)
+ ]
+ end.uniq
+}
+
+# implicit hashes get skipped and don't break compilation
+assert_equal '[[:key]]', %q{
+ def implicit(hash)
+ hash.keys
+ end
+
+ 5.times.map { implicit(key: :value) }.uniq
+}
+
+# default values on keywords don't mess up argument order
+assert_equal '[2]', %q{
+ def default_value
+ 1
+ end
+
+ def default_expression(value: default_value)
+ value
+ end
+
+ 5.times.map { default_expression(value: 2) }.uniq
+}
+
+# constant default values on keywords
+assert_equal '[3]', %q{
+ def default_expression(value: 3)
+ value
+ end
+
+ 5.times.map { default_expression }.uniq
+}
+
+# non-constant default values on keywords
+assert_equal '[3]', %q{
+ def default_value
+ 3
+ end
+
+ def default_expression(value: default_value)
+ value
+ end
+
+ 5.times.map { default_expression }.uniq
+}
+
+# reordered optional kwargs
+assert_equal '[[100, 1]]', %q{
+ def foo(capacity: 100, max: nil)
+ [capacity, max]
+ end
+
+ 5.times.map { foo(max: 1) }.uniq
+}
+
+# invalid lead param
+assert_equal 'ok', %q{
+ def bar(baz: 2)
+ baz
+ end
+
+ def foo
+ bar(1, baz: 123)
+ end
+
+ begin
+ foo
+ foo
+ rescue ArgumentError => e
+ print "ok"
+ end
+}
+
+# reordered required kwargs
+assert_equal '[[1, 2, 3, 4]]', %q{
+ def foo(default1: 1, required1:, default2: 3, required2:)
+ [default1, required1, default2, required2]
+ end
+
+ 5.times.map { foo(required1: 2, required2: 4) }.uniq
+}
+
+# reordered default expression kwargs
+assert_equal '[[:one, :two, 3]]', %q{
+ def foo(arg1: (1+0), arg2: (2+0), arg3: (3+0))
+ [arg1, arg2, arg3]
+ end
+
+ 5.times.map { foo(arg2: :two, arg1: :one) }.uniq
+}
+
+# complex kwargs
+assert_equal '[[1, 2, 3, 4]]', %q{
+ def foo(required:, specified: 999, simple_default: 3, complex_default: "4".to_i)
+ [required, specified, simple_default, complex_default]
+ end
+
+ 5.times.map { foo(specified: 2, required: 1) }.uniq
+}
+
+# cfunc kwargs
+assert_equal '{:foo=>123}', %q{
+ def foo(bar)
+ bar.store(:value, foo: 123)
+ bar[:value]
+ end
+
+ foo({})
+ foo({})
+}
+
+# cfunc kwargs
+assert_equal '{:foo=>123}', %q{
+ def foo(bar)
+ bar.replace(foo: 123)
+ end
+
+ foo({})
+ foo({})
+}
+
+# cfunc kwargs
+assert_equal '{:foo=>123, :bar=>456}', %q{
+ def foo(bar)
+ bar.replace(foo: 123, bar: 456)
+ end
+
+ foo({})
+ foo({})
+}
+
+# variadic cfunc kwargs
+assert_equal '{:foo=>123}', %q{
+ def foo(bar)
+ bar.merge(foo: 123)
+ end
+
+ foo({})
+ foo({})
+}
+
+# optimized cfunc kwargs
+assert_equal 'false', %q{
+ def foo
+ :foo.eql?(foo: :foo)
+ end
+
+ foo
+ foo
+}
+
+# attr_reader on frozen object
+assert_equal 'false', %q{
+ class Foo
+ attr_reader :exception
+
+ def failed?
+ !exception.nil?
+ end
+ end
+
+ foo = Foo.new.freeze
+ foo.failed?
+ foo.failed?
+}
+
+# regression test for doing kwarg shuffle before checking for interrupts
+assert_equal 'ok', %q{
+ def new_media_drop(attributes:, product_drop:, context:, sources:)
+ nil.nomethod rescue nil # force YJIT to bail to side exit
+
+ [attributes, product_drop, context, sources]
+ end
+
+ def load_medias(product_drop: nil, raw_medias:, context:)
+ raw_medias.map do |raw_media|
+ case new_media_drop(context: context, attributes: raw_media, product_drop: product_drop, sources: [])
+ in [Hash, ProductDrop, Context, Array]
+ else
+ raise "bad shuffle"
+ end
+ end
+ end
+
+ class Context; end
+
+ class ProductDrop
+ attr_reader :title
+ def initialize(title)
+ @title = title
+ end
+ end
+
+ # Make a thread so we have thread switching interrupts
+ th = Thread.new do
+ while true; end
+ end
+ 1_000.times do |i|
+ load_medias(product_drop: ProductDrop.new("foo"), raw_medias: [{}, {}], context: Context.new)
+ end
+ th.kill.join
+
+ :ok
+}
+
+# regression test for tracing attr_accessor methods.
+assert_equal "true", %q{
+ c = Class.new do
+ attr_accessor :x
+ alias y x
+ alias y= x=
+ end
+ obj = c.new
+
+ ar_meth = obj.method(:x)
+ aw_meth = obj.method(:x=)
+ aar_meth = obj.method(:y)
+ aaw_meth = obj.method(:y=)
+ events = []
+ trace = TracePoint.new(:c_call, :c_return){|tp|
+ next if tp.path != __FILE__
+ next if tp.method_id == :call
+ case tp.event
+ when :c_call
+ events << [tp.event, tp.method_id, tp.callee_id]
+ when :c_return
+ events << [tp.event, tp.method_id, tp.callee_id, tp.return_value]
+ end
+ }
+ test_proc = proc do
+ obj.x = 1
+ obj.x
+ obj.y = 2
+ obj.y
+ aw_meth.call(1)
+ ar_meth.call
+ aaw_meth.call(2)
+ aar_meth.call
+ end
+ test_proc.call # populate call caches
+ trace.enable(&test_proc)
+ expected = [
+ [:c_call, :x=, :x=],
+ [:c_return, :x=, :x=, 1],
+ [:c_call, :x, :x],
+ [:c_return, :x, :x, 1],
+ [:c_call, :x=, :y=],
+ [:c_return, :x=, :y=, 2],
+ [:c_call, :x, :y],
+ [:c_return, :x, :y, 2],
+ ] * 2
+
+ expected == events
+}
+
+# duphash
+assert_equal '{:foo=>123}', %q{
+ def foo
+ {foo: 123}
+ end
+
+ foo
+ foo
+}
+
+# newhash
+assert_equal '{:foo=>2}', %q{
+ def foo
+ {foo: 1+1}
+ end
+
+ foo
+ foo
+}
+
+# block invalidation edge case
+assert_equal 'undef', %q{
+ class A
+ def foo(arg)
+ arg.times { A.remove_method(:bar) }
+ self
+ end
+
+ def bar
+ 4
+ end
+
+ def use(arg)
+ # two consecutive sends. When bar is removed, the return address
+ # for calling it is already on foo's control frame
+ foo(arg).bar
+ rescue NoMethodError
+ :undef
+ end
+ end
+
+ A.new.use 0
+ A.new.use 0
+ A.new.use 1
+}
+
+# block invalidation edge case
+assert_equal 'ok', %q{
+ class A
+ Good = :ng
+ def foo(arg)
+ arg.times { A.const_set(:Good, :ok) }
+ self
+ end
+
+ def id(arg)
+ arg
+ end
+
+ def use(arg)
+ # send followed by an opt_getinlinecache.
+ # The return address remains on the control frame
+ # when opt_getinlinecache is invalidated.
+ foo(arg).id(Good)
+ end
+ end
+
+ A.new.use 0
+ A.new.use 0
+ A.new.use 1
+}
+
+assert_equal 'ok', %q{
+ # test hitting a branch stub when out of memory
+ def nimai(jita)
+ if jita
+ :ng
+ else
+ :ok
+ end
+ end
+
+ nimai(true)
+ nimai(true)
+
+ RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT)
+
+ nimai(false)
+}
+
+assert_equal 'new', %q{
+ # test block invalidation while out of memory
+ def foo
+ :old
+ end
+
+ def test
+ foo
+ end
+
+ def bar
+ :bar
+ end
+
+
+ test
+ test
+
+ RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT)
+
+ # Old simulat_omm! leaves one byte of space and this fills it up
+ bar
+ bar
+
+ def foo
+ :new
+ end
+
+ test
+}
+
+assert_equal 'ok', %q{
+ # Try to compile new method while OOM
+ def foo
+ :ok
+ end
+
+ RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT)
+
+ foo
+ foo
+}
+
+# struct aref embedded
+assert_equal '2', %q{
+ def foo(s)
+ s.foo
+ end
+
+ S = Struct.new(:foo)
+ foo(S.new(1))
+ foo(S.new(2))
+}
+
+# struct aref non-embedded
+assert_equal '4', %q{
+ def foo(s)
+ s.d
+ end
+
+ S = Struct.new(:a, :b, :c, :d, :e)
+ foo(S.new(1,2,3,4,5))
+ foo(S.new(1,2,3,4,5))
+}
+
+# struct aset embedded
+assert_equal '123', %q{
+ def foo(s)
+ s.foo = 123
+ end
+
+ s = Struct.new(:foo).new
+ foo(s)
+ s = Struct.new(:foo).new
+ foo(s)
+ s.foo
+}
+
+# struct aset non-embedded
+assert_equal '[1, 2, 3, 4, 5]', %q{
+ def foo(s)
+ s.a = 1
+ s.b = 2
+ s.c = 3
+ s.d = 4
+ s.e = 5
+ end
+
+ S = Struct.new(:a, :b, :c, :d, :e)
+ s = S.new
+ foo(s)
+ s = S.new
+ foo(s)
+ [s.a, s.b, s.c, s.d, s.e]
+}
+
+# struct aref too many args
+assert_equal 'ok', %q{
+ def foo(s)
+ s.foo(:bad)
+ end
+
+ s = Struct.new(:foo).new
+ foo(s) rescue :ok
+ foo(s) rescue :ok
+}
+
+# struct aset too many args
+assert_equal 'ok', %q{
+ def foo(s)
+ s.set_foo(123, :bad)
+ end
+
+ s = Struct.new(:foo) do
+ alias :set_foo :foo=
+ end
+ foo(s) rescue :ok
+ foo(s) rescue :ok
+}
+
+# File.join is a cfunc accepting variable arguments as a Ruby array (argc = -2)
+assert_equal 'foo/bar', %q{
+ def foo
+ File.join("foo", "bar")
+ end
+
+ foo
+ foo
+}
+
+# File.join is a cfunc accepting variable arguments as a Ruby array (argc = -2)
+assert_equal '', %q{
+ def foo
+ File.join()
+ end
+
+ foo
+ foo
+}
+
+# Make sure we're correctly reading RStruct's as.ary union for embedded RStructs
+assert_equal '3,12', %q{
+ pt_struct = Struct.new(:x, :y)
+ p = pt_struct.new(3, 12)
+ def pt_inspect(pt)
+ "#{pt.x},#{pt.y}"
+ end
+
+ # Make sure pt_inspect is JITted
+ 10.times { pt_inspect(p) }
+
+ # Make sure it's returning '3,12' instead of e.g. '3,false'
+ pt_inspect(p)
+}
+
+# Regression test for deadlock between branch_stub_hit and ractor_receive_if
+assert_equal '10', %q{
+ r = Ractor.new Ractor.current do |main|
+ main << 1
+ main << 2
+ main << 3
+ main << 4
+ main << 5
+ main << 6
+ main << 7
+ main << 8
+ main << 9
+ main << 10
+ end
+
+ a = []
+ a << Ractor.receive_if{|msg| msg == 10}
+ a << Ractor.receive_if{|msg| msg == 9}
+ a << Ractor.receive_if{|msg| msg == 8}
+ a << Ractor.receive_if{|msg| msg == 7}
+ a << Ractor.receive_if{|msg| msg == 6}
+ a << Ractor.receive_if{|msg| msg == 5}
+ a << Ractor.receive_if{|msg| msg == 4}
+ a << Ractor.receive_if{|msg| msg == 3}
+ a << Ractor.receive_if{|msg| msg == 2}
+ a << Ractor.receive_if{|msg| msg == 1}
+
+ a.length
+}
+
+# checktype
+assert_equal 'false', %q{
+ def function()
+ [1, 2] in [Integer, String]
+ end
+ function()
+}
+
+# opt_send_without_block (VM_METHOD_TYPE_ATTRSET)
+assert_equal 'foo', %q{
+ class Foo
+ attr_writer :foo
+
+ def foo()
+ self.foo = "foo"
+ end
+ end
+ foo = Foo.new
+ foo.foo
+}
+
+# anytostring, intern
+assert_equal 'true', %q{
+ def foo()
+ :"#{true}"
+ end
+ foo()
+}
+
+# toregexp, objtostring
+assert_equal '/true/', %q{
+ def foo()
+ /#{true}/
+ end
+ foo().inspect
+}
+
+# concatstrings, objtostring
+assert_equal '9001', %q{
+ def foo()
+ "#{9001}"
+ end
+ foo()
+}
+
+# opt_send_without_block (VM_METHOD_TYPE_CFUNC)
+assert_equal 'nil', %q{
+ def foo
+ nil.inspect # argc: 0
+ end
+ foo
+}
+assert_equal '4', %q{
+ def foo
+ 2.pow(2) # argc: 1
+ end
+ foo
+}
+assert_equal 'aba', %q{
+ def foo
+ "abc".tr("c", "a") # argc: 2
+ end
+ foo
+}
+assert_equal 'true', %q{
+ def foo
+ respond_to?(:inspect) # argc: -1
+ end
+ foo
+}
+assert_equal '["a", "b"]', %q{
+ def foo
+ "a\nb".lines(chomp: true) # kwargs
+ end
+ foo
+}
+
+# invokebuiltin
+assert_equal '123', %q{
+ def foo(obj)
+ obj.foo = 123
+ end
+
+ struct = Struct.new(:foo)
+ obj = struct.new
+ foo(obj)
+}
+
+# invokebuiltin_delegate
+assert_equal '.', %q{
+ def foo(path)
+ Dir.open(path).path
+ end
+ foo(".")
+}
+
+# opt_invokebuiltin_delegate_leave
+assert_equal '[0]', %q{"\x00".unpack("c")}
+
+# opt_send_without_block (VM_METHOD_TYPE_ISEQ)
+assert_equal '1', %q{
+ def foo = 1
+ def bar = foo
+ bar
+}
+assert_equal '[1, 2, 3]', %q{
+ def foo(a, b) = [1, a, b]
+ def bar = foo(2, 3)
+ bar
+}
+assert_equal '[1, 2, 3, 4, 5, 6]', %q{
+ def foo(a, b, c:, d:, e: 0, f: 6) = [a, b, c, d, e, f]
+ def bar = foo(1, 2, c: 3, d: 4, e: 5)
+ bar
+}
+assert_equal '[1, 2, 3, 4]', %q{
+ def foo(a, b = 2) = [a, b]
+ def bar = foo(1) + foo(3, 4)
+ bar
+}
+
+assert_equal '1', %q{
+ def foo(a) = a
+ def bar = foo(1) { 2 }
+ bar
+}
+assert_equal '[1, 2]', %q{
+ def foo(a, &block) = [a, block.call]
+ def bar = foo(1) { 2 }
+ bar
+}
+
+# opt_send_without_block (VM_METHOD_TYPE_IVAR)
+assert_equal 'foo', %q{
+ class Foo
+ attr_reader :foo
+
+ def initialize
+ @foo = "foo"
+ end
+ end
+ Foo.new.foo
+}
+
+# opt_send_without_block (VM_METHOD_TYPE_OPTIMIZED)
+assert_equal 'foo', %q{
+ Foo = Struct.new(:bar)
+ Foo.new("bar").bar = "foo"
+}
+assert_equal 'foo', %q{
+ Foo = Struct.new(:bar)
+ Foo.new("foo").bar
+}
+
+# getblockparamproxy
+assert_equal 'foo', %q{
+ def foo(&block)
+ block.call
+ end
+ foo { "foo" }
+}
+
+# getblockparam
+assert_equal 'foo', %q{
+ def foo(&block)
+ block
+ end
+ foo { "foo" }.call
+}
+
+assert_equal '[1, 2]', %q{
+ def foo
+ x = [2]
+ [1, *x]
+ end
+
+ foo
+ foo
+}
+
+# respond_to? with changing symbol
+assert_equal 'false', %q{
+ def foo(name)
+ :sym.respond_to?(name)
+ end
+ foo(:to_s)
+ foo(:to_s)
+ foo(:not_exist)
+}
+
+# respond_to? with method being defined
+assert_equal 'true', %q{
+ def foo
+ :sym.respond_to?(:not_yet_defined)
+ end
+ foo
+ foo
+ module Kernel
+ def not_yet_defined = true
+ end
+ foo
+}
+
+# respond_to? with undef method
+assert_equal 'false', %q{
+ module Kernel
+ def to_be_removed = true
+ end
+ def foo
+ :sym.respond_to?(:to_be_removed)
+ end
+ foo
+ foo
+ class Object
+ undef_method :to_be_removed
+ end
+ foo
+}
+
+# respond_to? with respond_to_missing?
+assert_equal 'true', %q{
+ class Foo
+ end
+ def foo(x)
+ x.respond_to?(:bar)
+ end
+ foo(Foo.new)
+ foo(Foo.new)
+ class Foo
+ def respond_to_missing?(*) = true
+ end
+ foo(Foo.new)
+}
+
+# bmethod
+assert_equal '[1, 2, 3]', %q{
+ one = 1
+ define_method(:foo) do
+ one
+ end
+
+ 3.times.map { |i| foo + i }
+}
+
+# return inside bmethod
+assert_equal 'ok', %q{
+ define_method(:foo) do
+ 1.tap { return :ok }
+ end
+
+ foo
+}
+
+# bmethod optional and keywords
+assert_equal '[[1, nil, 2]]', %q{
+ define_method(:opt_and_kwargs) do |a = {}, b: nil, c: nil|
+ [a, b, c]
+ end
+
+ 5.times.map { opt_and_kwargs(1, c: 2) }.uniq
+}
+
+# bmethod with forwarded block
+assert_equal '2', %q{
+ define_method(:foo) do |&block|
+ block.call
+ end
+
+ def bar(&block)
+ foo(&block)
+ end
+
+ bar { 1 }
+ bar { 2 }
+}
+
+# bmethod with forwarded block and arguments
+assert_equal '5', %q{
+ define_method(:foo) do |n, &block|
+ n + block.call
+ end
+
+ def bar(n, &block)
+ foo(n, &block)
+ end
+
+ bar(0) { 1 }
+ bar(3) { 2 }
+}
+
+# bmethod with forwarded unwanted block
+assert_equal '1', %q{
+ one = 1
+ define_method(:foo) do
+ one
+ end
+
+ def bar(&block)
+ foo(&block)
+ end
+
+ bar { }
+ bar { }
+}
+
+# test for return stub lifetime issue
+assert_equal '1', %q{
+ def foo(n)
+ if n == 2
+ return 1.times { Object.define_method(:foo) {} }
+ end
+
+ foo(n + 1)
+ end
+
+ foo(1)
+}
+
+# case-when with redefined ===
+assert_equal 'ok', %q{
+ class Symbol
+ def ===(a)
+ true
+ end
+ end
+
+ def cw(arg)
+ case arg
+ when :b
+ :ok
+ when 4
+ :ng
+ end
+ end
+
+ cw(4)
+}
+
+assert_normal_exit %{
+ class Bug20997
+ def foo(&) = self.class.name(&)
+
+ new.foo
+ end
+}
diff --git a/bootstraptest/test_yjit_30k_ifelse.rb b/bootstraptest/test_yjit_30k_ifelse.rb
new file mode 100644
index 0000000000..c3afa95e4d
--- /dev/null
+++ b/bootstraptest/test_yjit_30k_ifelse.rb
@@ -0,0 +1,241023 @@
+# This is a torture test for the JIT.
+# There are 30K tiny methods with if-else statements in a 30-deep call hierarchy.
+assert_equal '100000', %q{
+
+def fun_l0_n0(x)
+ if (x < 1)
+ fun_l1_n310(x)
+ else
+ fun_l1_n485(x)
+ end
+end
+
+def fun_l0_n1(x)
+ if (x < 1)
+ fun_l1_n930(x)
+ else
+ fun_l1_n418(x)
+ end
+end
+
+def fun_l0_n2(x)
+ if (x < 1)
+ fun_l1_n549(x)
+ else
+ fun_l1_n44(x)
+ end
+end
+
+def fun_l0_n3(x)
+ if (x < 1)
+ fun_l1_n394(x)
+ else
+ fun_l1_n447(x)
+ end
+end
+
+def fun_l0_n4(x)
+ if (x < 1)
+ fun_l1_n683(x)
+ else
+ fun_l1_n547(x)
+ end
+end
+
+def fun_l0_n5(x)
+ if (x < 1)
+ fun_l1_n320(x)
+ else
+ fun_l1_n896(x)
+ end
+end
+
+def fun_l0_n6(x)
+ if (x < 1)
+ fun_l1_n649(x)
+ else
+ fun_l1_n243(x)
+ end
+end
+
+def fun_l0_n7(x)
+ if (x < 1)
+ fun_l1_n100(x)
+ else
+ fun_l1_n243(x)
+ end
+end
+
+def fun_l0_n8(x)
+ if (x < 1)
+ fun_l1_n839(x)
+ else
+ fun_l1_n720(x)
+ end
+end
+
+def fun_l0_n9(x)
+ if (x < 1)
+ fun_l1_n177(x)
+ else
+ fun_l1_n555(x)
+ end
+end
+
+def fun_l0_n10(x)
+ if (x < 1)
+ fun_l1_n814(x)
+ else
+ fun_l1_n900(x)
+ end
+end
+
+def fun_l0_n11(x)
+ if (x < 1)
+ fun_l1_n585(x)
+ else
+ fun_l1_n901(x)
+ end
+end
+
+def fun_l0_n12(x)
+ if (x < 1)
+ fun_l1_n952(x)
+ else
+ fun_l1_n270(x)
+ end
+end
+
+def fun_l0_n13(x)
+ if (x < 1)
+ fun_l1_n172(x)
+ else
+ fun_l1_n209(x)
+ end
+end
+
+def fun_l0_n14(x)
+ if (x < 1)
+ fun_l1_n514(x)
+ else
+ fun_l1_n414(x)
+ end
+end
+
+def fun_l0_n15(x)
+ if (x < 1)
+ fun_l1_n190(x)
+ else
+ fun_l1_n100(x)
+ end
+end
+
+def fun_l0_n16(x)
+ if (x < 1)
+ fun_l1_n696(x)
+ else
+ fun_l1_n997(x)
+ end
+end
+
+def fun_l0_n17(x)
+ if (x < 1)
+ fun_l1_n568(x)
+ else
+ fun_l1_n820(x)
+ end
+end
+
+def fun_l0_n18(x)
+ if (x < 1)
+ fun_l1_n837(x)
+ else
+ fun_l1_n588(x)
+ end
+end
+
+def fun_l0_n19(x)
+ if (x < 1)
+ fun_l1_n206(x)
+ else
+ fun_l1_n126(x)
+ end
+end
+
+def fun_l0_n20(x)
+ if (x < 1)
+ fun_l1_n317(x)
+ else
+ fun_l1_n722(x)
+ end
+end
+
+def fun_l0_n21(x)
+ if (x < 1)
+ fun_l1_n614(x)
+ else
+ fun_l1_n372(x)
+ end
+end
+
+def fun_l0_n22(x)
+ if (x < 1)
+ fun_l1_n530(x)
+ else
+ fun_l1_n862(x)
+ end
+end
+
+def fun_l0_n23(x)
+ if (x < 1)
+ fun_l1_n889(x)
+ else
+ fun_l1_n271(x)
+ end
+end
+
+def fun_l0_n24(x)
+ if (x < 1)
+ fun_l1_n996(x)
+ else
+ fun_l1_n717(x)
+ end
+end
+
+def fun_l0_n25(x)
+ if (x < 1)
+ fun_l1_n726(x)
+ else
+ fun_l1_n939(x)
+ end
+end
+
+def fun_l0_n26(x)
+ if (x < 1)
+ fun_l1_n316(x)
+ else
+ fun_l1_n293(x)
+ end
+end
+
+def fun_l0_n27(x)
+ if (x < 1)
+ fun_l1_n90(x)
+ else
+ fun_l1_n596(x)
+ end
+end
+
+def fun_l0_n28(x)
+ if (x < 1)
+ fun_l1_n743(x)
+ else
+ fun_l1_n782(x)
+ end
+end
+
+def fun_l0_n29(x)
+ if (x < 1)
+ fun_l1_n896(x)
+ else
+ fun_l1_n247(x)
+ end
+end
+
+def fun_l0_n30(x)
+ if (x < 1)
+ fun_l1_n2(x)
+ else
+ fun_l1_n377(x)
+ end
+end
+
+def fun_l0_n31(x)
+ if (x < 1)
+ fun_l1_n380(x)
+ else
+ fun_l1_n655(x)
+ end
+end
+
+def fun_l0_n32(x)
+ if (x < 1)
+ fun_l1_n572(x)
+ else
+ fun_l1_n778(x)
+ end
+end
+
+def fun_l0_n33(x)
+ if (x < 1)
+ fun_l1_n485(x)
+ else
+ fun_l1_n282(x)
+ end
+end
+
+def fun_l0_n34(x)
+ if (x < 1)
+ fun_l1_n703(x)
+ else
+ fun_l1_n179(x)
+ end
+end
+
+def fun_l0_n35(x)
+ if (x < 1)
+ fun_l1_n281(x)
+ else
+ fun_l1_n572(x)
+ end
+end
+
+def fun_l0_n36(x)
+ if (x < 1)
+ fun_l1_n48(x)
+ else
+ fun_l1_n286(x)
+ end
+end
+
+def fun_l0_n37(x)
+ if (x < 1)
+ fun_l1_n539(x)
+ else
+ fun_l1_n86(x)
+ end
+end
+
+def fun_l0_n38(x)
+ if (x < 1)
+ fun_l1_n918(x)
+ else
+ fun_l1_n778(x)
+ end
+end
+
+def fun_l0_n39(x)
+ if (x < 1)
+ fun_l1_n832(x)
+ else
+ fun_l1_n94(x)
+ end
+end
+
+def fun_l0_n40(x)
+ if (x < 1)
+ fun_l1_n213(x)
+ else
+ fun_l1_n580(x)
+ end
+end
+
+def fun_l0_n41(x)
+ if (x < 1)
+ fun_l1_n413(x)
+ else
+ fun_l1_n793(x)
+ end
+end
+
+def fun_l0_n42(x)
+ if (x < 1)
+ fun_l1_n451(x)
+ else
+ fun_l1_n779(x)
+ end
+end
+
+def fun_l0_n43(x)
+ if (x < 1)
+ fun_l1_n118(x)
+ else
+ fun_l1_n778(x)
+ end
+end
+
+def fun_l0_n44(x)
+ if (x < 1)
+ fun_l1_n162(x)
+ else
+ fun_l1_n901(x)
+ end
+end
+
+def fun_l0_n45(x)
+ if (x < 1)
+ fun_l1_n157(x)
+ else
+ fun_l1_n280(x)
+ end
+end
+
+def fun_l0_n46(x)
+ if (x < 1)
+ fun_l1_n748(x)
+ else
+ fun_l1_n881(x)
+ end
+end
+
+def fun_l0_n47(x)
+ if (x < 1)
+ fun_l1_n529(x)
+ else
+ fun_l1_n732(x)
+ end
+end
+
+def fun_l0_n48(x)
+ if (x < 1)
+ fun_l1_n417(x)
+ else
+ fun_l1_n483(x)
+ end
+end
+
+def fun_l0_n49(x)
+ if (x < 1)
+ fun_l1_n743(x)
+ else
+ fun_l1_n525(x)
+ end
+end
+
+def fun_l0_n50(x)
+ if (x < 1)
+ fun_l1_n14(x)
+ else
+ fun_l1_n309(x)
+ end
+end
+
+def fun_l0_n51(x)
+ if (x < 1)
+ fun_l1_n436(x)
+ else
+ fun_l1_n304(x)
+ end
+end
+
+def fun_l0_n52(x)
+ if (x < 1)
+ fun_l1_n623(x)
+ else
+ fun_l1_n590(x)
+ end
+end
+
+def fun_l0_n53(x)
+ if (x < 1)
+ fun_l1_n696(x)
+ else
+ fun_l1_n53(x)
+ end
+end
+
+def fun_l0_n54(x)
+ if (x < 1)
+ fun_l1_n807(x)
+ else
+ fun_l1_n523(x)
+ end
+end
+
+def fun_l0_n55(x)
+ if (x < 1)
+ fun_l1_n607(x)
+ else
+ fun_l1_n609(x)
+ end
+end
+
+def fun_l0_n56(x)
+ if (x < 1)
+ fun_l1_n721(x)
+ else
+ fun_l1_n994(x)
+ end
+end
+
+def fun_l0_n57(x)
+ if (x < 1)
+ fun_l1_n472(x)
+ else
+ fun_l1_n818(x)
+ end
+end
+
+def fun_l0_n58(x)
+ if (x < 1)
+ fun_l1_n30(x)
+ else
+ fun_l1_n954(x)
+ end
+end
+
+def fun_l0_n59(x)
+ if (x < 1)
+ fun_l1_n223(x)
+ else
+ fun_l1_n148(x)
+ end
+end
+
+def fun_l0_n60(x)
+ if (x < 1)
+ fun_l1_n761(x)
+ else
+ fun_l1_n40(x)
+ end
+end
+
+def fun_l0_n61(x)
+ if (x < 1)
+ fun_l1_n57(x)
+ else
+ fun_l1_n858(x)
+ end
+end
+
+def fun_l0_n62(x)
+ if (x < 1)
+ fun_l1_n114(x)
+ else
+ fun_l1_n767(x)
+ end
+end
+
+def fun_l0_n63(x)
+ if (x < 1)
+ fun_l1_n287(x)
+ else
+ fun_l1_n752(x)
+ end
+end
+
+def fun_l0_n64(x)
+ if (x < 1)
+ fun_l1_n16(x)
+ else
+ fun_l1_n229(x)
+ end
+end
+
+def fun_l0_n65(x)
+ if (x < 1)
+ fun_l1_n230(x)
+ else
+ fun_l1_n954(x)
+ end
+end
+
+def fun_l0_n66(x)
+ if (x < 1)
+ fun_l1_n98(x)
+ else
+ fun_l1_n320(x)
+ end
+end
+
+def fun_l0_n67(x)
+ if (x < 1)
+ fun_l1_n878(x)
+ else
+ fun_l1_n985(x)
+ end
+end
+
+def fun_l0_n68(x)
+ if (x < 1)
+ fun_l1_n32(x)
+ else
+ fun_l1_n648(x)
+ end
+end
+
+def fun_l0_n69(x)
+ if (x < 1)
+ fun_l1_n453(x)
+ else
+ fun_l1_n466(x)
+ end
+end
+
+def fun_l0_n70(x)
+ if (x < 1)
+ fun_l1_n787(x)
+ else
+ fun_l1_n802(x)
+ end
+end
+
+def fun_l0_n71(x)
+ if (x < 1)
+ fun_l1_n656(x)
+ else
+ fun_l1_n347(x)
+ end
+end
+
+def fun_l0_n72(x)
+ if (x < 1)
+ fun_l1_n358(x)
+ else
+ fun_l1_n336(x)
+ end
+end
+
+def fun_l0_n73(x)
+ if (x < 1)
+ fun_l1_n291(x)
+ else
+ fun_l1_n536(x)
+ end
+end
+
+def fun_l0_n74(x)
+ if (x < 1)
+ fun_l1_n795(x)
+ else
+ fun_l1_n606(x)
+ end
+end
+
+def fun_l0_n75(x)
+ if (x < 1)
+ fun_l1_n21(x)
+ else
+ fun_l1_n720(x)
+ end
+end
+
+def fun_l0_n76(x)
+ if (x < 1)
+ fun_l1_n513(x)
+ else
+ fun_l1_n300(x)
+ end
+end
+
+def fun_l0_n77(x)
+ if (x < 1)
+ fun_l1_n358(x)
+ else
+ fun_l1_n332(x)
+ end
+end
+
+def fun_l0_n78(x)
+ if (x < 1)
+ fun_l1_n712(x)
+ else
+ fun_l1_n906(x)
+ end
+end
+
+def fun_l0_n79(x)
+ if (x < 1)
+ fun_l1_n555(x)
+ else
+ fun_l1_n850(x)
+ end
+end
+
+def fun_l0_n80(x)
+ if (x < 1)
+ fun_l1_n320(x)
+ else
+ fun_l1_n892(x)
+ end
+end
+
+def fun_l0_n81(x)
+ if (x < 1)
+ fun_l1_n191(x)
+ else
+ fun_l1_n187(x)
+ end
+end
+
+def fun_l0_n82(x)
+ if (x < 1)
+ fun_l1_n457(x)
+ else
+ fun_l1_n718(x)
+ end
+end
+
+def fun_l0_n83(x)
+ if (x < 1)
+ fun_l1_n314(x)
+ else
+ fun_l1_n697(x)
+ end
+end
+
+def fun_l0_n84(x)
+ if (x < 1)
+ fun_l1_n459(x)
+ else
+ fun_l1_n500(x)
+ end
+end
+
+def fun_l0_n85(x)
+ if (x < 1)
+ fun_l1_n912(x)
+ else
+ fun_l1_n992(x)
+ end
+end
+
+def fun_l0_n86(x)
+ if (x < 1)
+ fun_l1_n523(x)
+ else
+ fun_l1_n201(x)
+ end
+end
+
+def fun_l0_n87(x)
+ if (x < 1)
+ fun_l1_n30(x)
+ else
+ fun_l1_n829(x)
+ end
+end
+
+def fun_l0_n88(x)
+ if (x < 1)
+ fun_l1_n223(x)
+ else
+ fun_l1_n799(x)
+ end
+end
+
+def fun_l0_n89(x)
+ if (x < 1)
+ fun_l1_n289(x)
+ else
+ fun_l1_n289(x)
+ end
+end
+
+def fun_l0_n90(x)
+ if (x < 1)
+ fun_l1_n961(x)
+ else
+ fun_l1_n694(x)
+ end
+end
+
+def fun_l0_n91(x)
+ if (x < 1)
+ fun_l1_n423(x)
+ else
+ fun_l1_n848(x)
+ end
+end
+
+def fun_l0_n92(x)
+ if (x < 1)
+ fun_l1_n612(x)
+ else
+ fun_l1_n358(x)
+ end
+end
+
+def fun_l0_n93(x)
+ if (x < 1)
+ fun_l1_n148(x)
+ else
+ fun_l1_n312(x)
+ end
+end
+
+def fun_l0_n94(x)
+ if (x < 1)
+ fun_l1_n771(x)
+ else
+ fun_l1_n205(x)
+ end
+end
+
+def fun_l0_n95(x)
+ if (x < 1)
+ fun_l1_n573(x)
+ else
+ fun_l1_n692(x)
+ end
+end
+
+def fun_l0_n96(x)
+ if (x < 1)
+ fun_l1_n66(x)
+ else
+ fun_l1_n936(x)
+ end
+end
+
+def fun_l0_n97(x)
+ if (x < 1)
+ fun_l1_n429(x)
+ else
+ fun_l1_n949(x)
+ end
+end
+
+def fun_l0_n98(x)
+ if (x < 1)
+ fun_l1_n737(x)
+ else
+ fun_l1_n338(x)
+ end
+end
+
+def fun_l0_n99(x)
+ if (x < 1)
+ fun_l1_n335(x)
+ else
+ fun_l1_n739(x)
+ end
+end
+
+def fun_l0_n100(x)
+ if (x < 1)
+ fun_l1_n989(x)
+ else
+ fun_l1_n735(x)
+ end
+end
+
+def fun_l0_n101(x)
+ if (x < 1)
+ fun_l1_n559(x)
+ else
+ fun_l1_n478(x)
+ end
+end
+
+def fun_l0_n102(x)
+ if (x < 1)
+ fun_l1_n261(x)
+ else
+ fun_l1_n162(x)
+ end
+end
+
+def fun_l0_n103(x)
+ if (x < 1)
+ fun_l1_n400(x)
+ else
+ fun_l1_n156(x)
+ end
+end
+
+def fun_l0_n104(x)
+ if (x < 1)
+ fun_l1_n747(x)
+ else
+ fun_l1_n361(x)
+ end
+end
+
+def fun_l0_n105(x)
+ if (x < 1)
+ fun_l1_n717(x)
+ else
+ fun_l1_n522(x)
+ end
+end
+
+def fun_l0_n106(x)
+ if (x < 1)
+ fun_l1_n513(x)
+ else
+ fun_l1_n150(x)
+ end
+end
+
+def fun_l0_n107(x)
+ if (x < 1)
+ fun_l1_n710(x)
+ else
+ fun_l1_n602(x)
+ end
+end
+
+def fun_l0_n108(x)
+ if (x < 1)
+ fun_l1_n866(x)
+ else
+ fun_l1_n111(x)
+ end
+end
+
+def fun_l0_n109(x)
+ if (x < 1)
+ fun_l1_n725(x)
+ else
+ fun_l1_n448(x)
+ end
+end
+
+def fun_l0_n110(x)
+ if (x < 1)
+ fun_l1_n703(x)
+ else
+ fun_l1_n127(x)
+ end
+end
+
+def fun_l0_n111(x)
+ if (x < 1)
+ fun_l1_n420(x)
+ else
+ fun_l1_n666(x)
+ end
+end
+
+def fun_l0_n112(x)
+ if (x < 1)
+ fun_l1_n647(x)
+ else
+ fun_l1_n567(x)
+ end
+end
+
+def fun_l0_n113(x)
+ if (x < 1)
+ fun_l1_n543(x)
+ else
+ fun_l1_n992(x)
+ end
+end
+
+def fun_l0_n114(x)
+ if (x < 1)
+ fun_l1_n12(x)
+ else
+ fun_l1_n470(x)
+ end
+end
+
+def fun_l0_n115(x)
+ if (x < 1)
+ fun_l1_n25(x)
+ else
+ fun_l1_n917(x)
+ end
+end
+
+def fun_l0_n116(x)
+ if (x < 1)
+ fun_l1_n201(x)
+ else
+ fun_l1_n110(x)
+ end
+end
+
+def fun_l0_n117(x)
+ if (x < 1)
+ fun_l1_n222(x)
+ else
+ fun_l1_n747(x)
+ end
+end
+
+def fun_l0_n118(x)
+ if (x < 1)
+ fun_l1_n990(x)
+ else
+ fun_l1_n794(x)
+ end
+end
+
+def fun_l0_n119(x)
+ if (x < 1)
+ fun_l1_n712(x)
+ else
+ fun_l1_n5(x)
+ end
+end
+
+def fun_l0_n120(x)
+ if (x < 1)
+ fun_l1_n28(x)
+ else
+ fun_l1_n89(x)
+ end
+end
+
+def fun_l0_n121(x)
+ if (x < 1)
+ fun_l1_n341(x)
+ else
+ fun_l1_n983(x)
+ end
+end
+
+def fun_l0_n122(x)
+ if (x < 1)
+ fun_l1_n123(x)
+ else
+ fun_l1_n452(x)
+ end
+end
+
+def fun_l0_n123(x)
+ if (x < 1)
+ fun_l1_n514(x)
+ else
+ fun_l1_n949(x)
+ end
+end
+
+def fun_l0_n124(x)
+ if (x < 1)
+ fun_l1_n280(x)
+ else
+ fun_l1_n281(x)
+ end
+end
+
+def fun_l0_n125(x)
+ if (x < 1)
+ fun_l1_n512(x)
+ else
+ fun_l1_n772(x)
+ end
+end
+
+def fun_l0_n126(x)
+ if (x < 1)
+ fun_l1_n911(x)
+ else
+ fun_l1_n693(x)
+ end
+end
+
+def fun_l0_n127(x)
+ if (x < 1)
+ fun_l1_n633(x)
+ else
+ fun_l1_n574(x)
+ end
+end
+
+def fun_l0_n128(x)
+ if (x < 1)
+ fun_l1_n318(x)
+ else
+ fun_l1_n266(x)
+ end
+end
+
+def fun_l0_n129(x)
+ if (x < 1)
+ fun_l1_n677(x)
+ else
+ fun_l1_n10(x)
+ end
+end
+
+def fun_l0_n130(x)
+ if (x < 1)
+ fun_l1_n994(x)
+ else
+ fun_l1_n48(x)
+ end
+end
+
+def fun_l0_n131(x)
+ if (x < 1)
+ fun_l1_n335(x)
+ else
+ fun_l1_n473(x)
+ end
+end
+
+def fun_l0_n132(x)
+ if (x < 1)
+ fun_l1_n641(x)
+ else
+ fun_l1_n48(x)
+ end
+end
+
+def fun_l0_n133(x)
+ if (x < 1)
+ fun_l1_n914(x)
+ else
+ fun_l1_n818(x)
+ end
+end
+
+def fun_l0_n134(x)
+ if (x < 1)
+ fun_l1_n479(x)
+ else
+ fun_l1_n761(x)
+ end
+end
+
+def fun_l0_n135(x)
+ if (x < 1)
+ fun_l1_n186(x)
+ else
+ fun_l1_n692(x)
+ end
+end
+
+def fun_l0_n136(x)
+ if (x < 1)
+ fun_l1_n325(x)
+ else
+ fun_l1_n279(x)
+ end
+end
+
+def fun_l0_n137(x)
+ if (x < 1)
+ fun_l1_n493(x)
+ else
+ fun_l1_n293(x)
+ end
+end
+
+def fun_l0_n138(x)
+ if (x < 1)
+ fun_l1_n788(x)
+ else
+ fun_l1_n364(x)
+ end
+end
+
+def fun_l0_n139(x)
+ if (x < 1)
+ fun_l1_n565(x)
+ else
+ fun_l1_n63(x)
+ end
+end
+
+def fun_l0_n140(x)
+ if (x < 1)
+ fun_l1_n128(x)
+ else
+ fun_l1_n299(x)
+ end
+end
+
+def fun_l0_n141(x)
+ if (x < 1)
+ fun_l1_n782(x)
+ else
+ fun_l1_n195(x)
+ end
+end
+
+def fun_l0_n142(x)
+ if (x < 1)
+ fun_l1_n696(x)
+ else
+ fun_l1_n117(x)
+ end
+end
+
+def fun_l0_n143(x)
+ if (x < 1)
+ fun_l1_n263(x)
+ else
+ fun_l1_n683(x)
+ end
+end
+
+def fun_l0_n144(x)
+ if (x < 1)
+ fun_l1_n633(x)
+ else
+ fun_l1_n92(x)
+ end
+end
+
+def fun_l0_n145(x)
+ if (x < 1)
+ fun_l1_n626(x)
+ else
+ fun_l1_n201(x)
+ end
+end
+
+def fun_l0_n146(x)
+ if (x < 1)
+ fun_l1_n296(x)
+ else
+ fun_l1_n425(x)
+ end
+end
+
+def fun_l0_n147(x)
+ if (x < 1)
+ fun_l1_n395(x)
+ else
+ fun_l1_n750(x)
+ end
+end
+
+def fun_l0_n148(x)
+ if (x < 1)
+ fun_l1_n164(x)
+ else
+ fun_l1_n580(x)
+ end
+end
+
+def fun_l0_n149(x)
+ if (x < 1)
+ fun_l1_n904(x)
+ else
+ fun_l1_n264(x)
+ end
+end
+
+def fun_l0_n150(x)
+ if (x < 1)
+ fun_l1_n383(x)
+ else
+ fun_l1_n558(x)
+ end
+end
+
+def fun_l0_n151(x)
+ if (x < 1)
+ fun_l1_n522(x)
+ else
+ fun_l1_n735(x)
+ end
+end
+
+def fun_l0_n152(x)
+ if (x < 1)
+ fun_l1_n496(x)
+ else
+ fun_l1_n562(x)
+ end
+end
+
+def fun_l0_n153(x)
+ if (x < 1)
+ fun_l1_n374(x)
+ else
+ fun_l1_n561(x)
+ end
+end
+
+def fun_l0_n154(x)
+ if (x < 1)
+ fun_l1_n314(x)
+ else
+ fun_l1_n368(x)
+ end
+end
+
+def fun_l0_n155(x)
+ if (x < 1)
+ fun_l1_n456(x)
+ else
+ fun_l1_n189(x)
+ end
+end
+
+def fun_l0_n156(x)
+ if (x < 1)
+ fun_l1_n46(x)
+ else
+ fun_l1_n620(x)
+ end
+end
+
+def fun_l0_n157(x)
+ if (x < 1)
+ fun_l1_n259(x)
+ else
+ fun_l1_n742(x)
+ end
+end
+
+def fun_l0_n158(x)
+ if (x < 1)
+ fun_l1_n881(x)
+ else
+ fun_l1_n786(x)
+ end
+end
+
+def fun_l0_n159(x)
+ if (x < 1)
+ fun_l1_n607(x)
+ else
+ fun_l1_n177(x)
+ end
+end
+
+def fun_l0_n160(x)
+ if (x < 1)
+ fun_l1_n824(x)
+ else
+ fun_l1_n415(x)
+ end
+end
+
+def fun_l0_n161(x)
+ if (x < 1)
+ fun_l1_n443(x)
+ else
+ fun_l1_n787(x)
+ end
+end
+
+def fun_l0_n162(x)
+ if (x < 1)
+ fun_l1_n124(x)
+ else
+ fun_l1_n529(x)
+ end
+end
+
+def fun_l0_n163(x)
+ if (x < 1)
+ fun_l1_n696(x)
+ else
+ fun_l1_n96(x)
+ end
+end
+
+def fun_l0_n164(x)
+ if (x < 1)
+ fun_l1_n775(x)
+ else
+ fun_l1_n549(x)
+ end
+end
+
+def fun_l0_n165(x)
+ if (x < 1)
+ fun_l1_n860(x)
+ else
+ fun_l1_n212(x)
+ end
+end
+
+def fun_l0_n166(x)
+ if (x < 1)
+ fun_l1_n378(x)
+ else
+ fun_l1_n904(x)
+ end
+end
+
+def fun_l0_n167(x)
+ if (x < 1)
+ fun_l1_n15(x)
+ else
+ fun_l1_n640(x)
+ end
+end
+
+def fun_l0_n168(x)
+ if (x < 1)
+ fun_l1_n771(x)
+ else
+ fun_l1_n861(x)
+ end
+end
+
+def fun_l0_n169(x)
+ if (x < 1)
+ fun_l1_n468(x)
+ else
+ fun_l1_n586(x)
+ end
+end
+
+def fun_l0_n170(x)
+ if (x < 1)
+ fun_l1_n477(x)
+ else
+ fun_l1_n674(x)
+ end
+end
+
+def fun_l0_n171(x)
+ if (x < 1)
+ fun_l1_n509(x)
+ else
+ fun_l1_n64(x)
+ end
+end
+
+def fun_l0_n172(x)
+ if (x < 1)
+ fun_l1_n612(x)
+ else
+ fun_l1_n828(x)
+ end
+end
+
+def fun_l0_n173(x)
+ if (x < 1)
+ fun_l1_n440(x)
+ else
+ fun_l1_n204(x)
+ end
+end
+
+def fun_l0_n174(x)
+ if (x < 1)
+ fun_l1_n259(x)
+ else
+ fun_l1_n947(x)
+ end
+end
+
+def fun_l0_n175(x)
+ if (x < 1)
+ fun_l1_n402(x)
+ else
+ fun_l1_n588(x)
+ end
+end
+
+def fun_l0_n176(x)
+ if (x < 1)
+ fun_l1_n245(x)
+ else
+ fun_l1_n540(x)
+ end
+end
+
+def fun_l0_n177(x)
+ if (x < 1)
+ fun_l1_n869(x)
+ else
+ fun_l1_n249(x)
+ end
+end
+
+def fun_l0_n178(x)
+ if (x < 1)
+ fun_l1_n830(x)
+ else
+ fun_l1_n210(x)
+ end
+end
+
+def fun_l0_n179(x)
+ if (x < 1)
+ fun_l1_n692(x)
+ else
+ fun_l1_n222(x)
+ end
+end
+
+def fun_l0_n180(x)
+ if (x < 1)
+ fun_l1_n220(x)
+ else
+ fun_l1_n281(x)
+ end
+end
+
+def fun_l0_n181(x)
+ if (x < 1)
+ fun_l1_n523(x)
+ else
+ fun_l1_n618(x)
+ end
+end
+
+def fun_l0_n182(x)
+ if (x < 1)
+ fun_l1_n44(x)
+ else
+ fun_l1_n422(x)
+ end
+end
+
+def fun_l0_n183(x)
+ if (x < 1)
+ fun_l1_n944(x)
+ else
+ fun_l1_n230(x)
+ end
+end
+
+def fun_l0_n184(x)
+ if (x < 1)
+ fun_l1_n678(x)
+ else
+ fun_l1_n121(x)
+ end
+end
+
+def fun_l0_n185(x)
+ if (x < 1)
+ fun_l1_n73(x)
+ else
+ fun_l1_n398(x)
+ end
+end
+
+def fun_l0_n186(x)
+ if (x < 1)
+ fun_l1_n121(x)
+ else
+ fun_l1_n689(x)
+ end
+end
+
+def fun_l0_n187(x)
+ if (x < 1)
+ fun_l1_n946(x)
+ else
+ fun_l1_n613(x)
+ end
+end
+
+def fun_l0_n188(x)
+ if (x < 1)
+ fun_l1_n987(x)
+ else
+ fun_l1_n785(x)
+ end
+end
+
+def fun_l0_n189(x)
+ if (x < 1)
+ fun_l1_n181(x)
+ else
+ fun_l1_n644(x)
+ end
+end
+
+def fun_l0_n190(x)
+ if (x < 1)
+ fun_l1_n623(x)
+ else
+ fun_l1_n679(x)
+ end
+end
+
+def fun_l0_n191(x)
+ if (x < 1)
+ fun_l1_n784(x)
+ else
+ fun_l1_n274(x)
+ end
+end
+
+def fun_l0_n192(x)
+ if (x < 1)
+ fun_l1_n71(x)
+ else
+ fun_l1_n773(x)
+ end
+end
+
+def fun_l0_n193(x)
+ if (x < 1)
+ fun_l1_n516(x)
+ else
+ fun_l1_n496(x)
+ end
+end
+
+def fun_l0_n194(x)
+ if (x < 1)
+ fun_l1_n608(x)
+ else
+ fun_l1_n460(x)
+ end
+end
+
+def fun_l0_n195(x)
+ if (x < 1)
+ fun_l1_n25(x)
+ else
+ fun_l1_n437(x)
+ end
+end
+
+def fun_l0_n196(x)
+ if (x < 1)
+ fun_l1_n410(x)
+ else
+ fun_l1_n674(x)
+ end
+end
+
+def fun_l0_n197(x)
+ if (x < 1)
+ fun_l1_n949(x)
+ else
+ fun_l1_n708(x)
+ end
+end
+
+def fun_l0_n198(x)
+ if (x < 1)
+ fun_l1_n714(x)
+ else
+ fun_l1_n119(x)
+ end
+end
+
+def fun_l0_n199(x)
+ if (x < 1)
+ fun_l1_n41(x)
+ else
+ fun_l1_n865(x)
+ end
+end
+
+def fun_l0_n200(x)
+ if (x < 1)
+ fun_l1_n383(x)
+ else
+ fun_l1_n90(x)
+ end
+end
+
+def fun_l0_n201(x)
+ if (x < 1)
+ fun_l1_n581(x)
+ else
+ fun_l1_n273(x)
+ end
+end
+
+def fun_l0_n202(x)
+ if (x < 1)
+ fun_l1_n350(x)
+ else
+ fun_l1_n425(x)
+ end
+end
+
+def fun_l0_n203(x)
+ if (x < 1)
+ fun_l1_n259(x)
+ else
+ fun_l1_n922(x)
+ end
+end
+
+def fun_l0_n204(x)
+ if (x < 1)
+ fun_l1_n448(x)
+ else
+ fun_l1_n741(x)
+ end
+end
+
+def fun_l0_n205(x)
+ if (x < 1)
+ fun_l1_n86(x)
+ else
+ fun_l1_n618(x)
+ end
+end
+
+def fun_l0_n206(x)
+ if (x < 1)
+ fun_l1_n412(x)
+ else
+ fun_l1_n646(x)
+ end
+end
+
+def fun_l0_n207(x)
+ if (x < 1)
+ fun_l1_n196(x)
+ else
+ fun_l1_n496(x)
+ end
+end
+
+def fun_l0_n208(x)
+ if (x < 1)
+ fun_l1_n777(x)
+ else
+ fun_l1_n150(x)
+ end
+end
+
+def fun_l0_n209(x)
+ if (x < 1)
+ fun_l1_n20(x)
+ else
+ fun_l1_n718(x)
+ end
+end
+
+def fun_l0_n210(x)
+ if (x < 1)
+ fun_l1_n934(x)
+ else
+ fun_l1_n416(x)
+ end
+end
+
+def fun_l0_n211(x)
+ if (x < 1)
+ fun_l1_n803(x)
+ else
+ fun_l1_n636(x)
+ end
+end
+
+def fun_l0_n212(x)
+ if (x < 1)
+ fun_l1_n93(x)
+ else
+ fun_l1_n791(x)
+ end
+end
+
+def fun_l0_n213(x)
+ if (x < 1)
+ fun_l1_n76(x)
+ else
+ fun_l1_n172(x)
+ end
+end
+
+def fun_l0_n214(x)
+ if (x < 1)
+ fun_l1_n103(x)
+ else
+ fun_l1_n381(x)
+ end
+end
+
+def fun_l0_n215(x)
+ if (x < 1)
+ fun_l1_n433(x)
+ else
+ fun_l1_n349(x)
+ end
+end
+
+def fun_l0_n216(x)
+ if (x < 1)
+ fun_l1_n154(x)
+ else
+ fun_l1_n740(x)
+ end
+end
+
+def fun_l0_n217(x)
+ if (x < 1)
+ fun_l1_n927(x)
+ else
+ fun_l1_n886(x)
+ end
+end
+
+def fun_l0_n218(x)
+ if (x < 1)
+ fun_l1_n804(x)
+ else
+ fun_l1_n6(x)
+ end
+end
+
+def fun_l0_n219(x)
+ if (x < 1)
+ fun_l1_n921(x)
+ else
+ fun_l1_n121(x)
+ end
+end
+
+def fun_l0_n220(x)
+ if (x < 1)
+ fun_l1_n732(x)
+ else
+ fun_l1_n224(x)
+ end
+end
+
+def fun_l0_n221(x)
+ if (x < 1)
+ fun_l1_n818(x)
+ else
+ fun_l1_n105(x)
+ end
+end
+
+def fun_l0_n222(x)
+ if (x < 1)
+ fun_l1_n162(x)
+ else
+ fun_l1_n700(x)
+ end
+end
+
+def fun_l0_n223(x)
+ if (x < 1)
+ fun_l1_n57(x)
+ else
+ fun_l1_n734(x)
+ end
+end
+
+def fun_l0_n224(x)
+ if (x < 1)
+ fun_l1_n283(x)
+ else
+ fun_l1_n87(x)
+ end
+end
+
+def fun_l0_n225(x)
+ if (x < 1)
+ fun_l1_n623(x)
+ else
+ fun_l1_n363(x)
+ end
+end
+
+def fun_l0_n226(x)
+ if (x < 1)
+ fun_l1_n962(x)
+ else
+ fun_l1_n660(x)
+ end
+end
+
+def fun_l0_n227(x)
+ if (x < 1)
+ fun_l1_n255(x)
+ else
+ fun_l1_n536(x)
+ end
+end
+
+def fun_l0_n228(x)
+ if (x < 1)
+ fun_l1_n377(x)
+ else
+ fun_l1_n249(x)
+ end
+end
+
+def fun_l0_n229(x)
+ if (x < 1)
+ fun_l1_n527(x)
+ else
+ fun_l1_n691(x)
+ end
+end
+
+def fun_l0_n230(x)
+ if (x < 1)
+ fun_l1_n781(x)
+ else
+ fun_l1_n494(x)
+ end
+end
+
+def fun_l0_n231(x)
+ if (x < 1)
+ fun_l1_n889(x)
+ else
+ fun_l1_n967(x)
+ end
+end
+
+def fun_l0_n232(x)
+ if (x < 1)
+ fun_l1_n509(x)
+ else
+ fun_l1_n910(x)
+ end
+end
+
+def fun_l0_n233(x)
+ if (x < 1)
+ fun_l1_n354(x)
+ else
+ fun_l1_n5(x)
+ end
+end
+
+def fun_l0_n234(x)
+ if (x < 1)
+ fun_l1_n423(x)
+ else
+ fun_l1_n788(x)
+ end
+end
+
+def fun_l0_n235(x)
+ if (x < 1)
+ fun_l1_n632(x)
+ else
+ fun_l1_n705(x)
+ end
+end
+
+def fun_l0_n236(x)
+ if (x < 1)
+ fun_l1_n955(x)
+ else
+ fun_l1_n908(x)
+ end
+end
+
+def fun_l0_n237(x)
+ if (x < 1)
+ fun_l1_n329(x)
+ else
+ fun_l1_n2(x)
+ end
+end
+
+def fun_l0_n238(x)
+ if (x < 1)
+ fun_l1_n767(x)
+ else
+ fun_l1_n766(x)
+ end
+end
+
+def fun_l0_n239(x)
+ if (x < 1)
+ fun_l1_n304(x)
+ else
+ fun_l1_n507(x)
+ end
+end
+
+def fun_l0_n240(x)
+ if (x < 1)
+ fun_l1_n845(x)
+ else
+ fun_l1_n777(x)
+ end
+end
+
+def fun_l0_n241(x)
+ if (x < 1)
+ fun_l1_n69(x)
+ else
+ fun_l1_n260(x)
+ end
+end
+
+def fun_l0_n242(x)
+ if (x < 1)
+ fun_l1_n194(x)
+ else
+ fun_l1_n412(x)
+ end
+end
+
+def fun_l0_n243(x)
+ if (x < 1)
+ fun_l1_n974(x)
+ else
+ fun_l1_n922(x)
+ end
+end
+
+def fun_l0_n244(x)
+ if (x < 1)
+ fun_l1_n532(x)
+ else
+ fun_l1_n530(x)
+ end
+end
+
+def fun_l0_n245(x)
+ if (x < 1)
+ fun_l1_n554(x)
+ else
+ fun_l1_n656(x)
+ end
+end
+
+def fun_l0_n246(x)
+ if (x < 1)
+ fun_l1_n253(x)
+ else
+ fun_l1_n235(x)
+ end
+end
+
+def fun_l0_n247(x)
+ if (x < 1)
+ fun_l1_n754(x)
+ else
+ fun_l1_n775(x)
+ end
+end
+
+def fun_l0_n248(x)
+ if (x < 1)
+ fun_l1_n89(x)
+ else
+ fun_l1_n129(x)
+ end
+end
+
+def fun_l0_n249(x)
+ if (x < 1)
+ fun_l1_n284(x)
+ else
+ fun_l1_n642(x)
+ end
+end
+
+def fun_l0_n250(x)
+ if (x < 1)
+ fun_l1_n67(x)
+ else
+ fun_l1_n867(x)
+ end
+end
+
+def fun_l0_n251(x)
+ if (x < 1)
+ fun_l1_n926(x)
+ else
+ fun_l1_n442(x)
+ end
+end
+
+def fun_l0_n252(x)
+ if (x < 1)
+ fun_l1_n196(x)
+ else
+ fun_l1_n583(x)
+ end
+end
+
+def fun_l0_n253(x)
+ if (x < 1)
+ fun_l1_n966(x)
+ else
+ fun_l1_n810(x)
+ end
+end
+
+def fun_l0_n254(x)
+ if (x < 1)
+ fun_l1_n984(x)
+ else
+ fun_l1_n752(x)
+ end
+end
+
+def fun_l0_n255(x)
+ if (x < 1)
+ fun_l1_n941(x)
+ else
+ fun_l1_n744(x)
+ end
+end
+
+def fun_l0_n256(x)
+ if (x < 1)
+ fun_l1_n785(x)
+ else
+ fun_l1_n610(x)
+ end
+end
+
+def fun_l0_n257(x)
+ if (x < 1)
+ fun_l1_n622(x)
+ else
+ fun_l1_n730(x)
+ end
+end
+
+def fun_l0_n258(x)
+ if (x < 1)
+ fun_l1_n453(x)
+ else
+ fun_l1_n641(x)
+ end
+end
+
+def fun_l0_n259(x)
+ if (x < 1)
+ fun_l1_n407(x)
+ else
+ fun_l1_n818(x)
+ end
+end
+
+def fun_l0_n260(x)
+ if (x < 1)
+ fun_l1_n252(x)
+ else
+ fun_l1_n205(x)
+ end
+end
+
+def fun_l0_n261(x)
+ if (x < 1)
+ fun_l1_n940(x)
+ else
+ fun_l1_n678(x)
+ end
+end
+
+def fun_l0_n262(x)
+ if (x < 1)
+ fun_l1_n350(x)
+ else
+ fun_l1_n496(x)
+ end
+end
+
+def fun_l0_n263(x)
+ if (x < 1)
+ fun_l1_n688(x)
+ else
+ fun_l1_n193(x)
+ end
+end
+
+def fun_l0_n264(x)
+ if (x < 1)
+ fun_l1_n366(x)
+ else
+ fun_l1_n790(x)
+ end
+end
+
+def fun_l0_n265(x)
+ if (x < 1)
+ fun_l1_n592(x)
+ else
+ fun_l1_n93(x)
+ end
+end
+
+def fun_l0_n266(x)
+ if (x < 1)
+ fun_l1_n189(x)
+ else
+ fun_l1_n467(x)
+ end
+end
+
+def fun_l0_n267(x)
+ if (x < 1)
+ fun_l1_n813(x)
+ else
+ fun_l1_n7(x)
+ end
+end
+
+def fun_l0_n268(x)
+ if (x < 1)
+ fun_l1_n516(x)
+ else
+ fun_l1_n271(x)
+ end
+end
+
+def fun_l0_n269(x)
+ if (x < 1)
+ fun_l1_n0(x)
+ else
+ fun_l1_n121(x)
+ end
+end
+
+def fun_l0_n270(x)
+ if (x < 1)
+ fun_l1_n634(x)
+ else
+ fun_l1_n726(x)
+ end
+end
+
+def fun_l0_n271(x)
+ if (x < 1)
+ fun_l1_n192(x)
+ else
+ fun_l1_n468(x)
+ end
+end
+
+def fun_l0_n272(x)
+ if (x < 1)
+ fun_l1_n278(x)
+ else
+ fun_l1_n355(x)
+ end
+end
+
+def fun_l0_n273(x)
+ if (x < 1)
+ fun_l1_n354(x)
+ else
+ fun_l1_n87(x)
+ end
+end
+
+def fun_l0_n274(x)
+ if (x < 1)
+ fun_l1_n643(x)
+ else
+ fun_l1_n806(x)
+ end
+end
+
+def fun_l0_n275(x)
+ if (x < 1)
+ fun_l1_n389(x)
+ else
+ fun_l1_n559(x)
+ end
+end
+
+def fun_l0_n276(x)
+ if (x < 1)
+ fun_l1_n283(x)
+ else
+ fun_l1_n539(x)
+ end
+end
+
+def fun_l0_n277(x)
+ if (x < 1)
+ fun_l1_n0(x)
+ else
+ fun_l1_n351(x)
+ end
+end
+
+def fun_l0_n278(x)
+ if (x < 1)
+ fun_l1_n813(x)
+ else
+ fun_l1_n513(x)
+ end
+end
+
+def fun_l0_n279(x)
+ if (x < 1)
+ fun_l1_n501(x)
+ else
+ fun_l1_n967(x)
+ end
+end
+
+def fun_l0_n280(x)
+ if (x < 1)
+ fun_l1_n727(x)
+ else
+ fun_l1_n232(x)
+ end
+end
+
+def fun_l0_n281(x)
+ if (x < 1)
+ fun_l1_n946(x)
+ else
+ fun_l1_n693(x)
+ end
+end
+
+def fun_l0_n282(x)
+ if (x < 1)
+ fun_l1_n260(x)
+ else
+ fun_l1_n525(x)
+ end
+end
+
+def fun_l0_n283(x)
+ if (x < 1)
+ fun_l1_n957(x)
+ else
+ fun_l1_n817(x)
+ end
+end
+
+def fun_l0_n284(x)
+ if (x < 1)
+ fun_l1_n91(x)
+ else
+ fun_l1_n735(x)
+ end
+end
+
+def fun_l0_n285(x)
+ if (x < 1)
+ fun_l1_n71(x)
+ else
+ fun_l1_n24(x)
+ end
+end
+
+def fun_l0_n286(x)
+ if (x < 1)
+ fun_l1_n594(x)
+ else
+ fun_l1_n747(x)
+ end
+end
+
+def fun_l0_n287(x)
+ if (x < 1)
+ fun_l1_n869(x)
+ else
+ fun_l1_n414(x)
+ end
+end
+
+def fun_l0_n288(x)
+ if (x < 1)
+ fun_l1_n182(x)
+ else
+ fun_l1_n835(x)
+ end
+end
+
+def fun_l0_n289(x)
+ if (x < 1)
+ fun_l1_n188(x)
+ else
+ fun_l1_n949(x)
+ end
+end
+
+def fun_l0_n290(x)
+ if (x < 1)
+ fun_l1_n35(x)
+ else
+ fun_l1_n259(x)
+ end
+end
+
+def fun_l0_n291(x)
+ if (x < 1)
+ fun_l1_n593(x)
+ else
+ fun_l1_n810(x)
+ end
+end
+
+def fun_l0_n292(x)
+ if (x < 1)
+ fun_l1_n680(x)
+ else
+ fun_l1_n564(x)
+ end
+end
+
+def fun_l0_n293(x)
+ if (x < 1)
+ fun_l1_n57(x)
+ else
+ fun_l1_n91(x)
+ end
+end
+
+def fun_l0_n294(x)
+ if (x < 1)
+ fun_l1_n945(x)
+ else
+ fun_l1_n807(x)
+ end
+end
+
+def fun_l0_n295(x)
+ if (x < 1)
+ fun_l1_n442(x)
+ else
+ fun_l1_n123(x)
+ end
+end
+
+def fun_l0_n296(x)
+ if (x < 1)
+ fun_l1_n536(x)
+ else
+ fun_l1_n987(x)
+ end
+end
+
+def fun_l0_n297(x)
+ if (x < 1)
+ fun_l1_n519(x)
+ else
+ fun_l1_n657(x)
+ end
+end
+
+def fun_l0_n298(x)
+ if (x < 1)
+ fun_l1_n204(x)
+ else
+ fun_l1_n437(x)
+ end
+end
+
+def fun_l0_n299(x)
+ if (x < 1)
+ fun_l1_n289(x)
+ else
+ fun_l1_n385(x)
+ end
+end
+
+def fun_l0_n300(x)
+ if (x < 1)
+ fun_l1_n629(x)
+ else
+ fun_l1_n803(x)
+ end
+end
+
+def fun_l0_n301(x)
+ if (x < 1)
+ fun_l1_n576(x)
+ else
+ fun_l1_n921(x)
+ end
+end
+
+def fun_l0_n302(x)
+ if (x < 1)
+ fun_l1_n466(x)
+ else
+ fun_l1_n475(x)
+ end
+end
+
+def fun_l0_n303(x)
+ if (x < 1)
+ fun_l1_n658(x)
+ else
+ fun_l1_n333(x)
+ end
+end
+
+def fun_l0_n304(x)
+ if (x < 1)
+ fun_l1_n728(x)
+ else
+ fun_l1_n749(x)
+ end
+end
+
+def fun_l0_n305(x)
+ if (x < 1)
+ fun_l1_n68(x)
+ else
+ fun_l1_n552(x)
+ end
+end
+
+def fun_l0_n306(x)
+ if (x < 1)
+ fun_l1_n633(x)
+ else
+ fun_l1_n958(x)
+ end
+end
+
+def fun_l0_n307(x)
+ if (x < 1)
+ fun_l1_n79(x)
+ else
+ fun_l1_n386(x)
+ end
+end
+
+def fun_l0_n308(x)
+ if (x < 1)
+ fun_l1_n831(x)
+ else
+ fun_l1_n176(x)
+ end
+end
+
+def fun_l0_n309(x)
+ if (x < 1)
+ fun_l1_n770(x)
+ else
+ fun_l1_n334(x)
+ end
+end
+
+def fun_l0_n310(x)
+ if (x < 1)
+ fun_l1_n21(x)
+ else
+ fun_l1_n643(x)
+ end
+end
+
+def fun_l0_n311(x)
+ if (x < 1)
+ fun_l1_n673(x)
+ else
+ fun_l1_n298(x)
+ end
+end
+
+def fun_l0_n312(x)
+ if (x < 1)
+ fun_l1_n753(x)
+ else
+ fun_l1_n817(x)
+ end
+end
+
+def fun_l0_n313(x)
+ if (x < 1)
+ fun_l1_n299(x)
+ else
+ fun_l1_n350(x)
+ end
+end
+
+def fun_l0_n314(x)
+ if (x < 1)
+ fun_l1_n190(x)
+ else
+ fun_l1_n519(x)
+ end
+end
+
+def fun_l0_n315(x)
+ if (x < 1)
+ fun_l1_n934(x)
+ else
+ fun_l1_n416(x)
+ end
+end
+
+def fun_l0_n316(x)
+ if (x < 1)
+ fun_l1_n695(x)
+ else
+ fun_l1_n377(x)
+ end
+end
+
+def fun_l0_n317(x)
+ if (x < 1)
+ fun_l1_n194(x)
+ else
+ fun_l1_n747(x)
+ end
+end
+
+def fun_l0_n318(x)
+ if (x < 1)
+ fun_l1_n145(x)
+ else
+ fun_l1_n761(x)
+ end
+end
+
+def fun_l0_n319(x)
+ if (x < 1)
+ fun_l1_n223(x)
+ else
+ fun_l1_n237(x)
+ end
+end
+
+def fun_l0_n320(x)
+ if (x < 1)
+ fun_l1_n907(x)
+ else
+ fun_l1_n653(x)
+ end
+end
+
+def fun_l0_n321(x)
+ if (x < 1)
+ fun_l1_n216(x)
+ else
+ fun_l1_n67(x)
+ end
+end
+
+def fun_l0_n322(x)
+ if (x < 1)
+ fun_l1_n658(x)
+ else
+ fun_l1_n948(x)
+ end
+end
+
+def fun_l0_n323(x)
+ if (x < 1)
+ fun_l1_n358(x)
+ else
+ fun_l1_n926(x)
+ end
+end
+
+def fun_l0_n324(x)
+ if (x < 1)
+ fun_l1_n533(x)
+ else
+ fun_l1_n252(x)
+ end
+end
+
+def fun_l0_n325(x)
+ if (x < 1)
+ fun_l1_n284(x)
+ else
+ fun_l1_n670(x)
+ end
+end
+
+def fun_l0_n326(x)
+ if (x < 1)
+ fun_l1_n327(x)
+ else
+ fun_l1_n298(x)
+ end
+end
+
+def fun_l0_n327(x)
+ if (x < 1)
+ fun_l1_n837(x)
+ else
+ fun_l1_n890(x)
+ end
+end
+
+def fun_l0_n328(x)
+ if (x < 1)
+ fun_l1_n941(x)
+ else
+ fun_l1_n794(x)
+ end
+end
+
+def fun_l0_n329(x)
+ if (x < 1)
+ fun_l1_n859(x)
+ else
+ fun_l1_n970(x)
+ end
+end
+
+def fun_l0_n330(x)
+ if (x < 1)
+ fun_l1_n282(x)
+ else
+ fun_l1_n569(x)
+ end
+end
+
+def fun_l0_n331(x)
+ if (x < 1)
+ fun_l1_n33(x)
+ else
+ fun_l1_n525(x)
+ end
+end
+
+def fun_l0_n332(x)
+ if (x < 1)
+ fun_l1_n847(x)
+ else
+ fun_l1_n540(x)
+ end
+end
+
+def fun_l0_n333(x)
+ if (x < 1)
+ fun_l1_n485(x)
+ else
+ fun_l1_n756(x)
+ end
+end
+
+def fun_l0_n334(x)
+ if (x < 1)
+ fun_l1_n396(x)
+ else
+ fun_l1_n781(x)
+ end
+end
+
+def fun_l0_n335(x)
+ if (x < 1)
+ fun_l1_n225(x)
+ else
+ fun_l1_n417(x)
+ end
+end
+
+def fun_l0_n336(x)
+ if (x < 1)
+ fun_l1_n906(x)
+ else
+ fun_l1_n301(x)
+ end
+end
+
+def fun_l0_n337(x)
+ if (x < 1)
+ fun_l1_n863(x)
+ else
+ fun_l1_n409(x)
+ end
+end
+
+def fun_l0_n338(x)
+ if (x < 1)
+ fun_l1_n103(x)
+ else
+ fun_l1_n460(x)
+ end
+end
+
+def fun_l0_n339(x)
+ if (x < 1)
+ fun_l1_n787(x)
+ else
+ fun_l1_n434(x)
+ end
+end
+
+def fun_l0_n340(x)
+ if (x < 1)
+ fun_l1_n308(x)
+ else
+ fun_l1_n875(x)
+ end
+end
+
+def fun_l0_n341(x)
+ if (x < 1)
+ fun_l1_n146(x)
+ else
+ fun_l1_n566(x)
+ end
+end
+
+def fun_l0_n342(x)
+ if (x < 1)
+ fun_l1_n837(x)
+ else
+ fun_l1_n770(x)
+ end
+end
+
+def fun_l0_n343(x)
+ if (x < 1)
+ fun_l1_n668(x)
+ else
+ fun_l1_n60(x)
+ end
+end
+
+def fun_l0_n344(x)
+ if (x < 1)
+ fun_l1_n305(x)
+ else
+ fun_l1_n388(x)
+ end
+end
+
+def fun_l0_n345(x)
+ if (x < 1)
+ fun_l1_n796(x)
+ else
+ fun_l1_n920(x)
+ end
+end
+
+def fun_l0_n346(x)
+ if (x < 1)
+ fun_l1_n257(x)
+ else
+ fun_l1_n229(x)
+ end
+end
+
+def fun_l0_n347(x)
+ if (x < 1)
+ fun_l1_n740(x)
+ else
+ fun_l1_n372(x)
+ end
+end
+
+def fun_l0_n348(x)
+ if (x < 1)
+ fun_l1_n698(x)
+ else
+ fun_l1_n63(x)
+ end
+end
+
+def fun_l0_n349(x)
+ if (x < 1)
+ fun_l1_n4(x)
+ else
+ fun_l1_n119(x)
+ end
+end
+
+def fun_l0_n350(x)
+ if (x < 1)
+ fun_l1_n186(x)
+ else
+ fun_l1_n352(x)
+ end
+end
+
+def fun_l0_n351(x)
+ if (x < 1)
+ fun_l1_n619(x)
+ else
+ fun_l1_n583(x)
+ end
+end
+
+def fun_l0_n352(x)
+ if (x < 1)
+ fun_l1_n2(x)
+ else
+ fun_l1_n275(x)
+ end
+end
+
+def fun_l0_n353(x)
+ if (x < 1)
+ fun_l1_n843(x)
+ else
+ fun_l1_n986(x)
+ end
+end
+
+def fun_l0_n354(x)
+ if (x < 1)
+ fun_l1_n865(x)
+ else
+ fun_l1_n64(x)
+ end
+end
+
+def fun_l0_n355(x)
+ if (x < 1)
+ fun_l1_n732(x)
+ else
+ fun_l1_n332(x)
+ end
+end
+
+def fun_l0_n356(x)
+ if (x < 1)
+ fun_l1_n642(x)
+ else
+ fun_l1_n559(x)
+ end
+end
+
+def fun_l0_n357(x)
+ if (x < 1)
+ fun_l1_n385(x)
+ else
+ fun_l1_n532(x)
+ end
+end
+
+def fun_l0_n358(x)
+ if (x < 1)
+ fun_l1_n672(x)
+ else
+ fun_l1_n721(x)
+ end
+end
+
+def fun_l0_n359(x)
+ if (x < 1)
+ fun_l1_n663(x)
+ else
+ fun_l1_n590(x)
+ end
+end
+
+def fun_l0_n360(x)
+ if (x < 1)
+ fun_l1_n240(x)
+ else
+ fun_l1_n743(x)
+ end
+end
+
+def fun_l0_n361(x)
+ if (x < 1)
+ fun_l1_n301(x)
+ else
+ fun_l1_n943(x)
+ end
+end
+
+def fun_l0_n362(x)
+ if (x < 1)
+ fun_l1_n108(x)
+ else
+ fun_l1_n975(x)
+ end
+end
+
+def fun_l0_n363(x)
+ if (x < 1)
+ fun_l1_n554(x)
+ else
+ fun_l1_n135(x)
+ end
+end
+
+def fun_l0_n364(x)
+ if (x < 1)
+ fun_l1_n360(x)
+ else
+ fun_l1_n821(x)
+ end
+end
+
+def fun_l0_n365(x)
+ if (x < 1)
+ fun_l1_n992(x)
+ else
+ fun_l1_n158(x)
+ end
+end
+
+def fun_l0_n366(x)
+ if (x < 1)
+ fun_l1_n439(x)
+ else
+ fun_l1_n506(x)
+ end
+end
+
+def fun_l0_n367(x)
+ if (x < 1)
+ fun_l1_n229(x)
+ else
+ fun_l1_n714(x)
+ end
+end
+
+def fun_l0_n368(x)
+ if (x < 1)
+ fun_l1_n459(x)
+ else
+ fun_l1_n874(x)
+ end
+end
+
+def fun_l0_n369(x)
+ if (x < 1)
+ fun_l1_n799(x)
+ else
+ fun_l1_n406(x)
+ end
+end
+
+def fun_l0_n370(x)
+ if (x < 1)
+ fun_l1_n791(x)
+ else
+ fun_l1_n669(x)
+ end
+end
+
+def fun_l0_n371(x)
+ if (x < 1)
+ fun_l1_n99(x)
+ else
+ fun_l1_n344(x)
+ end
+end
+
+def fun_l0_n372(x)
+ if (x < 1)
+ fun_l1_n585(x)
+ else
+ fun_l1_n388(x)
+ end
+end
+
+def fun_l0_n373(x)
+ if (x < 1)
+ fun_l1_n35(x)
+ else
+ fun_l1_n369(x)
+ end
+end
+
+def fun_l0_n374(x)
+ if (x < 1)
+ fun_l1_n41(x)
+ else
+ fun_l1_n378(x)
+ end
+end
+
+def fun_l0_n375(x)
+ if (x < 1)
+ fun_l1_n372(x)
+ else
+ fun_l1_n406(x)
+ end
+end
+
+def fun_l0_n376(x)
+ if (x < 1)
+ fun_l1_n247(x)
+ else
+ fun_l1_n563(x)
+ end
+end
+
+def fun_l0_n377(x)
+ if (x < 1)
+ fun_l1_n998(x)
+ else
+ fun_l1_n302(x)
+ end
+end
+
+def fun_l0_n378(x)
+ if (x < 1)
+ fun_l1_n955(x)
+ else
+ fun_l1_n333(x)
+ end
+end
+
+def fun_l0_n379(x)
+ if (x < 1)
+ fun_l1_n554(x)
+ else
+ fun_l1_n863(x)
+ end
+end
+
+def fun_l0_n380(x)
+ if (x < 1)
+ fun_l1_n248(x)
+ else
+ fun_l1_n297(x)
+ end
+end
+
+def fun_l0_n381(x)
+ if (x < 1)
+ fun_l1_n85(x)
+ else
+ fun_l1_n726(x)
+ end
+end
+
+def fun_l0_n382(x)
+ if (x < 1)
+ fun_l1_n75(x)
+ else
+ fun_l1_n990(x)
+ end
+end
+
+def fun_l0_n383(x)
+ if (x < 1)
+ fun_l1_n353(x)
+ else
+ fun_l1_n218(x)
+ end
+end
+
+def fun_l0_n384(x)
+ if (x < 1)
+ fun_l1_n103(x)
+ else
+ fun_l1_n192(x)
+ end
+end
+
+def fun_l0_n385(x)
+ if (x < 1)
+ fun_l1_n659(x)
+ else
+ fun_l1_n996(x)
+ end
+end
+
+def fun_l0_n386(x)
+ if (x < 1)
+ fun_l1_n528(x)
+ else
+ fun_l1_n654(x)
+ end
+end
+
+def fun_l0_n387(x)
+ if (x < 1)
+ fun_l1_n857(x)
+ else
+ fun_l1_n638(x)
+ end
+end
+
+def fun_l0_n388(x)
+ if (x < 1)
+ fun_l1_n311(x)
+ else
+ fun_l1_n877(x)
+ end
+end
+
+def fun_l0_n389(x)
+ if (x < 1)
+ fun_l1_n406(x)
+ else
+ fun_l1_n191(x)
+ end
+end
+
+def fun_l0_n390(x)
+ if (x < 1)
+ fun_l1_n464(x)
+ else
+ fun_l1_n684(x)
+ end
+end
+
+def fun_l0_n391(x)
+ if (x < 1)
+ fun_l1_n878(x)
+ else
+ fun_l1_n635(x)
+ end
+end
+
+def fun_l0_n392(x)
+ if (x < 1)
+ fun_l1_n863(x)
+ else
+ fun_l1_n486(x)
+ end
+end
+
+def fun_l0_n393(x)
+ if (x < 1)
+ fun_l1_n587(x)
+ else
+ fun_l1_n387(x)
+ end
+end
+
+def fun_l0_n394(x)
+ if (x < 1)
+ fun_l1_n553(x)
+ else
+ fun_l1_n789(x)
+ end
+end
+
+def fun_l0_n395(x)
+ if (x < 1)
+ fun_l1_n420(x)
+ else
+ fun_l1_n148(x)
+ end
+end
+
+def fun_l0_n396(x)
+ if (x < 1)
+ fun_l1_n802(x)
+ else
+ fun_l1_n845(x)
+ end
+end
+
+def fun_l0_n397(x)
+ if (x < 1)
+ fun_l1_n749(x)
+ else
+ fun_l1_n742(x)
+ end
+end
+
+def fun_l0_n398(x)
+ if (x < 1)
+ fun_l1_n929(x)
+ else
+ fun_l1_n458(x)
+ end
+end
+
+def fun_l0_n399(x)
+ if (x < 1)
+ fun_l1_n908(x)
+ else
+ fun_l1_n188(x)
+ end
+end
+
+def fun_l0_n400(x)
+ if (x < 1)
+ fun_l1_n932(x)
+ else
+ fun_l1_n854(x)
+ end
+end
+
+def fun_l0_n401(x)
+ if (x < 1)
+ fun_l1_n29(x)
+ else
+ fun_l1_n666(x)
+ end
+end
+
+def fun_l0_n402(x)
+ if (x < 1)
+ fun_l1_n877(x)
+ else
+ fun_l1_n518(x)
+ end
+end
+
+def fun_l0_n403(x)
+ if (x < 1)
+ fun_l1_n639(x)
+ else
+ fun_l1_n618(x)
+ end
+end
+
+def fun_l0_n404(x)
+ if (x < 1)
+ fun_l1_n177(x)
+ else
+ fun_l1_n487(x)
+ end
+end
+
+def fun_l0_n405(x)
+ if (x < 1)
+ fun_l1_n536(x)
+ else
+ fun_l1_n860(x)
+ end
+end
+
+def fun_l0_n406(x)
+ if (x < 1)
+ fun_l1_n626(x)
+ else
+ fun_l1_n894(x)
+ end
+end
+
+def fun_l0_n407(x)
+ if (x < 1)
+ fun_l1_n533(x)
+ else
+ fun_l1_n367(x)
+ end
+end
+
+def fun_l0_n408(x)
+ if (x < 1)
+ fun_l1_n146(x)
+ else
+ fun_l1_n546(x)
+ end
+end
+
+def fun_l0_n409(x)
+ if (x < 1)
+ fun_l1_n872(x)
+ else
+ fun_l1_n387(x)
+ end
+end
+
+def fun_l0_n410(x)
+ if (x < 1)
+ fun_l1_n726(x)
+ else
+ fun_l1_n973(x)
+ end
+end
+
+def fun_l0_n411(x)
+ if (x < 1)
+ fun_l1_n168(x)
+ else
+ fun_l1_n783(x)
+ end
+end
+
+def fun_l0_n412(x)
+ if (x < 1)
+ fun_l1_n895(x)
+ else
+ fun_l1_n901(x)
+ end
+end
+
+def fun_l0_n413(x)
+ if (x < 1)
+ fun_l1_n235(x)
+ else
+ fun_l1_n593(x)
+ end
+end
+
+def fun_l0_n414(x)
+ if (x < 1)
+ fun_l1_n328(x)
+ else
+ fun_l1_n693(x)
+ end
+end
+
+def fun_l0_n415(x)
+ if (x < 1)
+ fun_l1_n882(x)
+ else
+ fun_l1_n290(x)
+ end
+end
+
+def fun_l0_n416(x)
+ if (x < 1)
+ fun_l1_n433(x)
+ else
+ fun_l1_n220(x)
+ end
+end
+
+def fun_l0_n417(x)
+ if (x < 1)
+ fun_l1_n966(x)
+ else
+ fun_l1_n74(x)
+ end
+end
+
+def fun_l0_n418(x)
+ if (x < 1)
+ fun_l1_n750(x)
+ else
+ fun_l1_n547(x)
+ end
+end
+
+def fun_l0_n419(x)
+ if (x < 1)
+ fun_l1_n94(x)
+ else
+ fun_l1_n794(x)
+ end
+end
+
+def fun_l0_n420(x)
+ if (x < 1)
+ fun_l1_n68(x)
+ else
+ fun_l1_n970(x)
+ end
+end
+
+def fun_l0_n421(x)
+ if (x < 1)
+ fun_l1_n663(x)
+ else
+ fun_l1_n388(x)
+ end
+end
+
+def fun_l0_n422(x)
+ if (x < 1)
+ fun_l1_n686(x)
+ else
+ fun_l1_n67(x)
+ end
+end
+
+def fun_l0_n423(x)
+ if (x < 1)
+ fun_l1_n210(x)
+ else
+ fun_l1_n64(x)
+ end
+end
+
+def fun_l0_n424(x)
+ if (x < 1)
+ fun_l1_n375(x)
+ else
+ fun_l1_n205(x)
+ end
+end
+
+def fun_l0_n425(x)
+ if (x < 1)
+ fun_l1_n832(x)
+ else
+ fun_l1_n325(x)
+ end
+end
+
+def fun_l0_n426(x)
+ if (x < 1)
+ fun_l1_n819(x)
+ else
+ fun_l1_n601(x)
+ end
+end
+
+def fun_l0_n427(x)
+ if (x < 1)
+ fun_l1_n588(x)
+ else
+ fun_l1_n875(x)
+ end
+end
+
+def fun_l0_n428(x)
+ if (x < 1)
+ fun_l1_n682(x)
+ else
+ fun_l1_n523(x)
+ end
+end
+
+def fun_l0_n429(x)
+ if (x < 1)
+ fun_l1_n972(x)
+ else
+ fun_l1_n891(x)
+ end
+end
+
+def fun_l0_n430(x)
+ if (x < 1)
+ fun_l1_n90(x)
+ else
+ fun_l1_n655(x)
+ end
+end
+
+def fun_l0_n431(x)
+ if (x < 1)
+ fun_l1_n393(x)
+ else
+ fun_l1_n454(x)
+ end
+end
+
+def fun_l0_n432(x)
+ if (x < 1)
+ fun_l1_n435(x)
+ else
+ fun_l1_n860(x)
+ end
+end
+
+def fun_l0_n433(x)
+ if (x < 1)
+ fun_l1_n516(x)
+ else
+ fun_l1_n246(x)
+ end
+end
+
+def fun_l0_n434(x)
+ if (x < 1)
+ fun_l1_n216(x)
+ else
+ fun_l1_n78(x)
+ end
+end
+
+def fun_l0_n435(x)
+ if (x < 1)
+ fun_l1_n357(x)
+ else
+ fun_l1_n61(x)
+ end
+end
+
+def fun_l0_n436(x)
+ if (x < 1)
+ fun_l1_n289(x)
+ else
+ fun_l1_n507(x)
+ end
+end
+
+def fun_l0_n437(x)
+ if (x < 1)
+ fun_l1_n182(x)
+ else
+ fun_l1_n289(x)
+ end
+end
+
+def fun_l0_n438(x)
+ if (x < 1)
+ fun_l1_n69(x)
+ else
+ fun_l1_n549(x)
+ end
+end
+
+def fun_l0_n439(x)
+ if (x < 1)
+ fun_l1_n275(x)
+ else
+ fun_l1_n723(x)
+ end
+end
+
+def fun_l0_n440(x)
+ if (x < 1)
+ fun_l1_n469(x)
+ else
+ fun_l1_n243(x)
+ end
+end
+
+def fun_l0_n441(x)
+ if (x < 1)
+ fun_l1_n595(x)
+ else
+ fun_l1_n624(x)
+ end
+end
+
+def fun_l0_n442(x)
+ if (x < 1)
+ fun_l1_n655(x)
+ else
+ fun_l1_n896(x)
+ end
+end
+
+def fun_l0_n443(x)
+ if (x < 1)
+ fun_l1_n926(x)
+ else
+ fun_l1_n503(x)
+ end
+end
+
+def fun_l0_n444(x)
+ if (x < 1)
+ fun_l1_n875(x)
+ else
+ fun_l1_n110(x)
+ end
+end
+
+def fun_l0_n445(x)
+ if (x < 1)
+ fun_l1_n832(x)
+ else
+ fun_l1_n154(x)
+ end
+end
+
+def fun_l0_n446(x)
+ if (x < 1)
+ fun_l1_n538(x)
+ else
+ fun_l1_n75(x)
+ end
+end
+
+def fun_l0_n447(x)
+ if (x < 1)
+ fun_l1_n183(x)
+ else
+ fun_l1_n718(x)
+ end
+end
+
+def fun_l0_n448(x)
+ if (x < 1)
+ fun_l1_n680(x)
+ else
+ fun_l1_n93(x)
+ end
+end
+
+def fun_l0_n449(x)
+ if (x < 1)
+ fun_l1_n147(x)
+ else
+ fun_l1_n924(x)
+ end
+end
+
+def fun_l0_n450(x)
+ if (x < 1)
+ fun_l1_n702(x)
+ else
+ fun_l1_n830(x)
+ end
+end
+
+def fun_l0_n451(x)
+ if (x < 1)
+ fun_l1_n750(x)
+ else
+ fun_l1_n447(x)
+ end
+end
+
+def fun_l0_n452(x)
+ if (x < 1)
+ fun_l1_n520(x)
+ else
+ fun_l1_n69(x)
+ end
+end
+
+def fun_l0_n453(x)
+ if (x < 1)
+ fun_l1_n132(x)
+ else
+ fun_l1_n877(x)
+ end
+end
+
+def fun_l0_n454(x)
+ if (x < 1)
+ fun_l1_n247(x)
+ else
+ fun_l1_n69(x)
+ end
+end
+
+def fun_l0_n455(x)
+ if (x < 1)
+ fun_l1_n180(x)
+ else
+ fun_l1_n645(x)
+ end
+end
+
+def fun_l0_n456(x)
+ if (x < 1)
+ fun_l1_n658(x)
+ else
+ fun_l1_n487(x)
+ end
+end
+
+def fun_l0_n457(x)
+ if (x < 1)
+ fun_l1_n276(x)
+ else
+ fun_l1_n528(x)
+ end
+end
+
+def fun_l0_n458(x)
+ if (x < 1)
+ fun_l1_n30(x)
+ else
+ fun_l1_n456(x)
+ end
+end
+
+def fun_l0_n459(x)
+ if (x < 1)
+ fun_l1_n986(x)
+ else
+ fun_l1_n552(x)
+ end
+end
+
+def fun_l0_n460(x)
+ if (x < 1)
+ fun_l1_n874(x)
+ else
+ fun_l1_n396(x)
+ end
+end
+
+def fun_l0_n461(x)
+ if (x < 1)
+ fun_l1_n524(x)
+ else
+ fun_l1_n335(x)
+ end
+end
+
+def fun_l0_n462(x)
+ if (x < 1)
+ fun_l1_n471(x)
+ else
+ fun_l1_n578(x)
+ end
+end
+
+def fun_l0_n463(x)
+ if (x < 1)
+ fun_l1_n173(x)
+ else
+ fun_l1_n456(x)
+ end
+end
+
+def fun_l0_n464(x)
+ if (x < 1)
+ fun_l1_n872(x)
+ else
+ fun_l1_n745(x)
+ end
+end
+
+def fun_l0_n465(x)
+ if (x < 1)
+ fun_l1_n387(x)
+ else
+ fun_l1_n776(x)
+ end
+end
+
+def fun_l0_n466(x)
+ if (x < 1)
+ fun_l1_n119(x)
+ else
+ fun_l1_n428(x)
+ end
+end
+
+def fun_l0_n467(x)
+ if (x < 1)
+ fun_l1_n416(x)
+ else
+ fun_l1_n738(x)
+ end
+end
+
+def fun_l0_n468(x)
+ if (x < 1)
+ fun_l1_n762(x)
+ else
+ fun_l1_n694(x)
+ end
+end
+
+def fun_l0_n469(x)
+ if (x < 1)
+ fun_l1_n27(x)
+ else
+ fun_l1_n562(x)
+ end
+end
+
+def fun_l0_n470(x)
+ if (x < 1)
+ fun_l1_n12(x)
+ else
+ fun_l1_n812(x)
+ end
+end
+
+def fun_l0_n471(x)
+ if (x < 1)
+ fun_l1_n865(x)
+ else
+ fun_l1_n94(x)
+ end
+end
+
+def fun_l0_n472(x)
+ if (x < 1)
+ fun_l1_n346(x)
+ else
+ fun_l1_n39(x)
+ end
+end
+
+def fun_l0_n473(x)
+ if (x < 1)
+ fun_l1_n309(x)
+ else
+ fun_l1_n158(x)
+ end
+end
+
+def fun_l0_n474(x)
+ if (x < 1)
+ fun_l1_n828(x)
+ else
+ fun_l1_n229(x)
+ end
+end
+
+def fun_l0_n475(x)
+ if (x < 1)
+ fun_l1_n554(x)
+ else
+ fun_l1_n121(x)
+ end
+end
+
+def fun_l0_n476(x)
+ if (x < 1)
+ fun_l1_n818(x)
+ else
+ fun_l1_n390(x)
+ end
+end
+
+def fun_l0_n477(x)
+ if (x < 1)
+ fun_l1_n88(x)
+ else
+ fun_l1_n73(x)
+ end
+end
+
+def fun_l0_n478(x)
+ if (x < 1)
+ fun_l1_n709(x)
+ else
+ fun_l1_n680(x)
+ end
+end
+
+def fun_l0_n479(x)
+ if (x < 1)
+ fun_l1_n271(x)
+ else
+ fun_l1_n439(x)
+ end
+end
+
+def fun_l0_n480(x)
+ if (x < 1)
+ fun_l1_n493(x)
+ else
+ fun_l1_n562(x)
+ end
+end
+
+def fun_l0_n481(x)
+ if (x < 1)
+ fun_l1_n642(x)
+ else
+ fun_l1_n221(x)
+ end
+end
+
+def fun_l0_n482(x)
+ if (x < 1)
+ fun_l1_n838(x)
+ else
+ fun_l1_n345(x)
+ end
+end
+
+def fun_l0_n483(x)
+ if (x < 1)
+ fun_l1_n411(x)
+ else
+ fun_l1_n266(x)
+ end
+end
+
+def fun_l0_n484(x)
+ if (x < 1)
+ fun_l1_n916(x)
+ else
+ fun_l1_n791(x)
+ end
+end
+
+def fun_l0_n485(x)
+ if (x < 1)
+ fun_l1_n392(x)
+ else
+ fun_l1_n68(x)
+ end
+end
+
+def fun_l0_n486(x)
+ if (x < 1)
+ fun_l1_n834(x)
+ else
+ fun_l1_n783(x)
+ end
+end
+
+def fun_l0_n487(x)
+ if (x < 1)
+ fun_l1_n398(x)
+ else
+ fun_l1_n627(x)
+ end
+end
+
+def fun_l0_n488(x)
+ if (x < 1)
+ fun_l1_n904(x)
+ else
+ fun_l1_n167(x)
+ end
+end
+
+def fun_l0_n489(x)
+ if (x < 1)
+ fun_l1_n54(x)
+ else
+ fun_l1_n28(x)
+ end
+end
+
+def fun_l0_n490(x)
+ if (x < 1)
+ fun_l1_n24(x)
+ else
+ fun_l1_n9(x)
+ end
+end
+
+def fun_l0_n491(x)
+ if (x < 1)
+ fun_l1_n497(x)
+ else
+ fun_l1_n297(x)
+ end
+end
+
+def fun_l0_n492(x)
+ if (x < 1)
+ fun_l1_n951(x)
+ else
+ fun_l1_n534(x)
+ end
+end
+
+def fun_l0_n493(x)
+ if (x < 1)
+ fun_l1_n213(x)
+ else
+ fun_l1_n808(x)
+ end
+end
+
+def fun_l0_n494(x)
+ if (x < 1)
+ fun_l1_n904(x)
+ else
+ fun_l1_n94(x)
+ end
+end
+
+def fun_l0_n495(x)
+ if (x < 1)
+ fun_l1_n799(x)
+ else
+ fun_l1_n817(x)
+ end
+end
+
+def fun_l0_n496(x)
+ if (x < 1)
+ fun_l1_n45(x)
+ else
+ fun_l1_n860(x)
+ end
+end
+
+def fun_l0_n497(x)
+ if (x < 1)
+ fun_l1_n482(x)
+ else
+ fun_l1_n783(x)
+ end
+end
+
+def fun_l0_n498(x)
+ if (x < 1)
+ fun_l1_n78(x)
+ else
+ fun_l1_n785(x)
+ end
+end
+
+def fun_l0_n499(x)
+ if (x < 1)
+ fun_l1_n174(x)
+ else
+ fun_l1_n87(x)
+ end
+end
+
+def fun_l0_n500(x)
+ if (x < 1)
+ fun_l1_n608(x)
+ else
+ fun_l1_n7(x)
+ end
+end
+
+def fun_l0_n501(x)
+ if (x < 1)
+ fun_l1_n157(x)
+ else
+ fun_l1_n718(x)
+ end
+end
+
+def fun_l0_n502(x)
+ if (x < 1)
+ fun_l1_n823(x)
+ else
+ fun_l1_n549(x)
+ end
+end
+
+def fun_l0_n503(x)
+ if (x < 1)
+ fun_l1_n13(x)
+ else
+ fun_l1_n502(x)
+ end
+end
+
+def fun_l0_n504(x)
+ if (x < 1)
+ fun_l1_n119(x)
+ else
+ fun_l1_n191(x)
+ end
+end
+
+def fun_l0_n505(x)
+ if (x < 1)
+ fun_l1_n503(x)
+ else
+ fun_l1_n974(x)
+ end
+end
+
+def fun_l0_n506(x)
+ if (x < 1)
+ fun_l1_n893(x)
+ else
+ fun_l1_n582(x)
+ end
+end
+
+def fun_l0_n507(x)
+ if (x < 1)
+ fun_l1_n403(x)
+ else
+ fun_l1_n228(x)
+ end
+end
+
+def fun_l0_n508(x)
+ if (x < 1)
+ fun_l1_n640(x)
+ else
+ fun_l1_n362(x)
+ end
+end
+
+def fun_l0_n509(x)
+ if (x < 1)
+ fun_l1_n629(x)
+ else
+ fun_l1_n824(x)
+ end
+end
+
+def fun_l0_n510(x)
+ if (x < 1)
+ fun_l1_n84(x)
+ else
+ fun_l1_n330(x)
+ end
+end
+
+def fun_l0_n511(x)
+ if (x < 1)
+ fun_l1_n91(x)
+ else
+ fun_l1_n523(x)
+ end
+end
+
+def fun_l0_n512(x)
+ if (x < 1)
+ fun_l1_n696(x)
+ else
+ fun_l1_n126(x)
+ end
+end
+
+def fun_l0_n513(x)
+ if (x < 1)
+ fun_l1_n905(x)
+ else
+ fun_l1_n496(x)
+ end
+end
+
+def fun_l0_n514(x)
+ if (x < 1)
+ fun_l1_n766(x)
+ else
+ fun_l1_n523(x)
+ end
+end
+
+def fun_l0_n515(x)
+ if (x < 1)
+ fun_l1_n798(x)
+ else
+ fun_l1_n698(x)
+ end
+end
+
+def fun_l0_n516(x)
+ if (x < 1)
+ fun_l1_n124(x)
+ else
+ fun_l1_n356(x)
+ end
+end
+
+def fun_l0_n517(x)
+ if (x < 1)
+ fun_l1_n289(x)
+ else
+ fun_l1_n782(x)
+ end
+end
+
+def fun_l0_n518(x)
+ if (x < 1)
+ fun_l1_n483(x)
+ else
+ fun_l1_n586(x)
+ end
+end
+
+def fun_l0_n519(x)
+ if (x < 1)
+ fun_l1_n878(x)
+ else
+ fun_l1_n37(x)
+ end
+end
+
+def fun_l0_n520(x)
+ if (x < 1)
+ fun_l1_n48(x)
+ else
+ fun_l1_n216(x)
+ end
+end
+
+def fun_l0_n521(x)
+ if (x < 1)
+ fun_l1_n805(x)
+ else
+ fun_l1_n846(x)
+ end
+end
+
+def fun_l0_n522(x)
+ if (x < 1)
+ fun_l1_n422(x)
+ else
+ fun_l1_n190(x)
+ end
+end
+
+def fun_l0_n523(x)
+ if (x < 1)
+ fun_l1_n168(x)
+ else
+ fun_l1_n272(x)
+ end
+end
+
+def fun_l0_n524(x)
+ if (x < 1)
+ fun_l1_n766(x)
+ else
+ fun_l1_n125(x)
+ end
+end
+
+def fun_l0_n525(x)
+ if (x < 1)
+ fun_l1_n56(x)
+ else
+ fun_l1_n224(x)
+ end
+end
+
+def fun_l0_n526(x)
+ if (x < 1)
+ fun_l1_n540(x)
+ else
+ fun_l1_n303(x)
+ end
+end
+
+def fun_l0_n527(x)
+ if (x < 1)
+ fun_l1_n846(x)
+ else
+ fun_l1_n955(x)
+ end
+end
+
+def fun_l0_n528(x)
+ if (x < 1)
+ fun_l1_n571(x)
+ else
+ fun_l1_n640(x)
+ end
+end
+
+def fun_l0_n529(x)
+ if (x < 1)
+ fun_l1_n650(x)
+ else
+ fun_l1_n107(x)
+ end
+end
+
+def fun_l0_n530(x)
+ if (x < 1)
+ fun_l1_n240(x)
+ else
+ fun_l1_n139(x)
+ end
+end
+
+def fun_l0_n531(x)
+ if (x < 1)
+ fun_l1_n975(x)
+ else
+ fun_l1_n970(x)
+ end
+end
+
+def fun_l0_n532(x)
+ if (x < 1)
+ fun_l1_n753(x)
+ else
+ fun_l1_n147(x)
+ end
+end
+
+def fun_l0_n533(x)
+ if (x < 1)
+ fun_l1_n269(x)
+ else
+ fun_l1_n292(x)
+ end
+end
+
+def fun_l0_n534(x)
+ if (x < 1)
+ fun_l1_n791(x)
+ else
+ fun_l1_n69(x)
+ end
+end
+
+def fun_l0_n535(x)
+ if (x < 1)
+ fun_l1_n469(x)
+ else
+ fun_l1_n58(x)
+ end
+end
+
+def fun_l0_n536(x)
+ if (x < 1)
+ fun_l1_n526(x)
+ else
+ fun_l1_n265(x)
+ end
+end
+
+def fun_l0_n537(x)
+ if (x < 1)
+ fun_l1_n681(x)
+ else
+ fun_l1_n646(x)
+ end
+end
+
+def fun_l0_n538(x)
+ if (x < 1)
+ fun_l1_n377(x)
+ else
+ fun_l1_n969(x)
+ end
+end
+
+def fun_l0_n539(x)
+ if (x < 1)
+ fun_l1_n935(x)
+ else
+ fun_l1_n556(x)
+ end
+end
+
+def fun_l0_n540(x)
+ if (x < 1)
+ fun_l1_n498(x)
+ else
+ fun_l1_n439(x)
+ end
+end
+
+def fun_l0_n541(x)
+ if (x < 1)
+ fun_l1_n451(x)
+ else
+ fun_l1_n35(x)
+ end
+end
+
+def fun_l0_n542(x)
+ if (x < 1)
+ fun_l1_n32(x)
+ else
+ fun_l1_n795(x)
+ end
+end
+
+def fun_l0_n543(x)
+ if (x < 1)
+ fun_l1_n732(x)
+ else
+ fun_l1_n530(x)
+ end
+end
+
+def fun_l0_n544(x)
+ if (x < 1)
+ fun_l1_n176(x)
+ else
+ fun_l1_n735(x)
+ end
+end
+
+def fun_l0_n545(x)
+ if (x < 1)
+ fun_l1_n34(x)
+ else
+ fun_l1_n989(x)
+ end
+end
+
+def fun_l0_n546(x)
+ if (x < 1)
+ fun_l1_n534(x)
+ else
+ fun_l1_n705(x)
+ end
+end
+
+def fun_l0_n547(x)
+ if (x < 1)
+ fun_l1_n997(x)
+ else
+ fun_l1_n883(x)
+ end
+end
+
+def fun_l0_n548(x)
+ if (x < 1)
+ fun_l1_n379(x)
+ else
+ fun_l1_n33(x)
+ end
+end
+
+def fun_l0_n549(x)
+ if (x < 1)
+ fun_l1_n454(x)
+ else
+ fun_l1_n516(x)
+ end
+end
+
+def fun_l0_n550(x)
+ if (x < 1)
+ fun_l1_n678(x)
+ else
+ fun_l1_n652(x)
+ end
+end
+
+def fun_l0_n551(x)
+ if (x < 1)
+ fun_l1_n13(x)
+ else
+ fun_l1_n864(x)
+ end
+end
+
+def fun_l0_n552(x)
+ if (x < 1)
+ fun_l1_n178(x)
+ else
+ fun_l1_n996(x)
+ end
+end
+
+def fun_l0_n553(x)
+ if (x < 1)
+ fun_l1_n865(x)
+ else
+ fun_l1_n703(x)
+ end
+end
+
+def fun_l0_n554(x)
+ if (x < 1)
+ fun_l1_n306(x)
+ else
+ fun_l1_n24(x)
+ end
+end
+
+def fun_l0_n555(x)
+ if (x < 1)
+ fun_l1_n110(x)
+ else
+ fun_l1_n123(x)
+ end
+end
+
+def fun_l0_n556(x)
+ if (x < 1)
+ fun_l1_n367(x)
+ else
+ fun_l1_n117(x)
+ end
+end
+
+def fun_l0_n557(x)
+ if (x < 1)
+ fun_l1_n967(x)
+ else
+ fun_l1_n662(x)
+ end
+end
+
+def fun_l0_n558(x)
+ if (x < 1)
+ fun_l1_n68(x)
+ else
+ fun_l1_n47(x)
+ end
+end
+
+def fun_l0_n559(x)
+ if (x < 1)
+ fun_l1_n154(x)
+ else
+ fun_l1_n344(x)
+ end
+end
+
+def fun_l0_n560(x)
+ if (x < 1)
+ fun_l1_n835(x)
+ else
+ fun_l1_n577(x)
+ end
+end
+
+def fun_l0_n561(x)
+ if (x < 1)
+ fun_l1_n393(x)
+ else
+ fun_l1_n419(x)
+ end
+end
+
+def fun_l0_n562(x)
+ if (x < 1)
+ fun_l1_n632(x)
+ else
+ fun_l1_n630(x)
+ end
+end
+
+def fun_l0_n563(x)
+ if (x < 1)
+ fun_l1_n9(x)
+ else
+ fun_l1_n109(x)
+ end
+end
+
+def fun_l0_n564(x)
+ if (x < 1)
+ fun_l1_n65(x)
+ else
+ fun_l1_n123(x)
+ end
+end
+
+def fun_l0_n565(x)
+ if (x < 1)
+ fun_l1_n156(x)
+ else
+ fun_l1_n921(x)
+ end
+end
+
+def fun_l0_n566(x)
+ if (x < 1)
+ fun_l1_n88(x)
+ else
+ fun_l1_n743(x)
+ end
+end
+
+def fun_l0_n567(x)
+ if (x < 1)
+ fun_l1_n92(x)
+ else
+ fun_l1_n27(x)
+ end
+end
+
+def fun_l0_n568(x)
+ if (x < 1)
+ fun_l1_n462(x)
+ else
+ fun_l1_n988(x)
+ end
+end
+
+def fun_l0_n569(x)
+ if (x < 1)
+ fun_l1_n241(x)
+ else
+ fun_l1_n199(x)
+ end
+end
+
+def fun_l0_n570(x)
+ if (x < 1)
+ fun_l1_n429(x)
+ else
+ fun_l1_n530(x)
+ end
+end
+
+def fun_l0_n571(x)
+ if (x < 1)
+ fun_l1_n412(x)
+ else
+ fun_l1_n530(x)
+ end
+end
+
+def fun_l0_n572(x)
+ if (x < 1)
+ fun_l1_n100(x)
+ else
+ fun_l1_n270(x)
+ end
+end
+
+def fun_l0_n573(x)
+ if (x < 1)
+ fun_l1_n326(x)
+ else
+ fun_l1_n191(x)
+ end
+end
+
+def fun_l0_n574(x)
+ if (x < 1)
+ fun_l1_n151(x)
+ else
+ fun_l1_n354(x)
+ end
+end
+
+def fun_l0_n575(x)
+ if (x < 1)
+ fun_l1_n322(x)
+ else
+ fun_l1_n534(x)
+ end
+end
+
+def fun_l0_n576(x)
+ if (x < 1)
+ fun_l1_n995(x)
+ else
+ fun_l1_n658(x)
+ end
+end
+
+def fun_l0_n577(x)
+ if (x < 1)
+ fun_l1_n193(x)
+ else
+ fun_l1_n444(x)
+ end
+end
+
+def fun_l0_n578(x)
+ if (x < 1)
+ fun_l1_n527(x)
+ else
+ fun_l1_n517(x)
+ end
+end
+
+def fun_l0_n579(x)
+ if (x < 1)
+ fun_l1_n885(x)
+ else
+ fun_l1_n218(x)
+ end
+end
+
+def fun_l0_n580(x)
+ if (x < 1)
+ fun_l1_n789(x)
+ else
+ fun_l1_n711(x)
+ end
+end
+
+def fun_l0_n581(x)
+ if (x < 1)
+ fun_l1_n848(x)
+ else
+ fun_l1_n321(x)
+ end
+end
+
+def fun_l0_n582(x)
+ if (x < 1)
+ fun_l1_n389(x)
+ else
+ fun_l1_n360(x)
+ end
+end
+
+def fun_l0_n583(x)
+ if (x < 1)
+ fun_l1_n319(x)
+ else
+ fun_l1_n972(x)
+ end
+end
+
+def fun_l0_n584(x)
+ if (x < 1)
+ fun_l1_n421(x)
+ else
+ fun_l1_n659(x)
+ end
+end
+
+def fun_l0_n585(x)
+ if (x < 1)
+ fun_l1_n462(x)
+ else
+ fun_l1_n302(x)
+ end
+end
+
+def fun_l0_n586(x)
+ if (x < 1)
+ fun_l1_n122(x)
+ else
+ fun_l1_n50(x)
+ end
+end
+
+def fun_l0_n587(x)
+ if (x < 1)
+ fun_l1_n795(x)
+ else
+ fun_l1_n622(x)
+ end
+end
+
+def fun_l0_n588(x)
+ if (x < 1)
+ fun_l1_n719(x)
+ else
+ fun_l1_n390(x)
+ end
+end
+
+def fun_l0_n589(x)
+ if (x < 1)
+ fun_l1_n916(x)
+ else
+ fun_l1_n925(x)
+ end
+end
+
+def fun_l0_n590(x)
+ if (x < 1)
+ fun_l1_n541(x)
+ else
+ fun_l1_n139(x)
+ end
+end
+
+def fun_l0_n591(x)
+ if (x < 1)
+ fun_l1_n610(x)
+ else
+ fun_l1_n509(x)
+ end
+end
+
+def fun_l0_n592(x)
+ if (x < 1)
+ fun_l1_n217(x)
+ else
+ fun_l1_n452(x)
+ end
+end
+
+def fun_l0_n593(x)
+ if (x < 1)
+ fun_l1_n456(x)
+ else
+ fun_l1_n888(x)
+ end
+end
+
+def fun_l0_n594(x)
+ if (x < 1)
+ fun_l1_n987(x)
+ else
+ fun_l1_n462(x)
+ end
+end
+
+def fun_l0_n595(x)
+ if (x < 1)
+ fun_l1_n571(x)
+ else
+ fun_l1_n429(x)
+ end
+end
+
+def fun_l0_n596(x)
+ if (x < 1)
+ fun_l1_n751(x)
+ else
+ fun_l1_n773(x)
+ end
+end
+
+def fun_l0_n597(x)
+ if (x < 1)
+ fun_l1_n181(x)
+ else
+ fun_l1_n340(x)
+ end
+end
+
+def fun_l0_n598(x)
+ if (x < 1)
+ fun_l1_n6(x)
+ else
+ fun_l1_n39(x)
+ end
+end
+
+def fun_l0_n599(x)
+ if (x < 1)
+ fun_l1_n814(x)
+ else
+ fun_l1_n320(x)
+ end
+end
+
+def fun_l0_n600(x)
+ if (x < 1)
+ fun_l1_n931(x)
+ else
+ fun_l1_n535(x)
+ end
+end
+
+def fun_l0_n601(x)
+ if (x < 1)
+ fun_l1_n99(x)
+ else
+ fun_l1_n154(x)
+ end
+end
+
+def fun_l0_n602(x)
+ if (x < 1)
+ fun_l1_n981(x)
+ else
+ fun_l1_n817(x)
+ end
+end
+
+def fun_l0_n603(x)
+ if (x < 1)
+ fun_l1_n975(x)
+ else
+ fun_l1_n364(x)
+ end
+end
+
+def fun_l0_n604(x)
+ if (x < 1)
+ fun_l1_n112(x)
+ else
+ fun_l1_n226(x)
+ end
+end
+
+def fun_l0_n605(x)
+ if (x < 1)
+ fun_l1_n995(x)
+ else
+ fun_l1_n95(x)
+ end
+end
+
+def fun_l0_n606(x)
+ if (x < 1)
+ fun_l1_n930(x)
+ else
+ fun_l1_n77(x)
+ end
+end
+
+def fun_l0_n607(x)
+ if (x < 1)
+ fun_l1_n899(x)
+ else
+ fun_l1_n957(x)
+ end
+end
+
+def fun_l0_n608(x)
+ if (x < 1)
+ fun_l1_n844(x)
+ else
+ fun_l1_n119(x)
+ end
+end
+
+def fun_l0_n609(x)
+ if (x < 1)
+ fun_l1_n861(x)
+ else
+ fun_l1_n74(x)
+ end
+end
+
+def fun_l0_n610(x)
+ if (x < 1)
+ fun_l1_n521(x)
+ else
+ fun_l1_n46(x)
+ end
+end
+
+def fun_l0_n611(x)
+ if (x < 1)
+ fun_l1_n258(x)
+ else
+ fun_l1_n208(x)
+ end
+end
+
+def fun_l0_n612(x)
+ if (x < 1)
+ fun_l1_n620(x)
+ else
+ fun_l1_n427(x)
+ end
+end
+
+def fun_l0_n613(x)
+ if (x < 1)
+ fun_l1_n583(x)
+ else
+ fun_l1_n400(x)
+ end
+end
+
+def fun_l0_n614(x)
+ if (x < 1)
+ fun_l1_n933(x)
+ else
+ fun_l1_n810(x)
+ end
+end
+
+def fun_l0_n615(x)
+ if (x < 1)
+ fun_l1_n154(x)
+ else
+ fun_l1_n879(x)
+ end
+end
+
+def fun_l0_n616(x)
+ if (x < 1)
+ fun_l1_n715(x)
+ else
+ fun_l1_n862(x)
+ end
+end
+
+def fun_l0_n617(x)
+ if (x < 1)
+ fun_l1_n178(x)
+ else
+ fun_l1_n285(x)
+ end
+end
+
+def fun_l0_n618(x)
+ if (x < 1)
+ fun_l1_n458(x)
+ else
+ fun_l1_n217(x)
+ end
+end
+
+def fun_l0_n619(x)
+ if (x < 1)
+ fun_l1_n655(x)
+ else
+ fun_l1_n405(x)
+ end
+end
+
+def fun_l0_n620(x)
+ if (x < 1)
+ fun_l1_n470(x)
+ else
+ fun_l1_n306(x)
+ end
+end
+
+def fun_l0_n621(x)
+ if (x < 1)
+ fun_l1_n755(x)
+ else
+ fun_l1_n425(x)
+ end
+end
+
+def fun_l0_n622(x)
+ if (x < 1)
+ fun_l1_n426(x)
+ else
+ fun_l1_n737(x)
+ end
+end
+
+def fun_l0_n623(x)
+ if (x < 1)
+ fun_l1_n79(x)
+ else
+ fun_l1_n55(x)
+ end
+end
+
+def fun_l0_n624(x)
+ if (x < 1)
+ fun_l1_n437(x)
+ else
+ fun_l1_n79(x)
+ end
+end
+
+def fun_l0_n625(x)
+ if (x < 1)
+ fun_l1_n691(x)
+ else
+ fun_l1_n198(x)
+ end
+end
+
+def fun_l0_n626(x)
+ if (x < 1)
+ fun_l1_n703(x)
+ else
+ fun_l1_n585(x)
+ end
+end
+
+def fun_l0_n627(x)
+ if (x < 1)
+ fun_l1_n966(x)
+ else
+ fun_l1_n425(x)
+ end
+end
+
+def fun_l0_n628(x)
+ if (x < 1)
+ fun_l1_n516(x)
+ else
+ fun_l1_n744(x)
+ end
+end
+
+def fun_l0_n629(x)
+ if (x < 1)
+ fun_l1_n40(x)
+ else
+ fun_l1_n942(x)
+ end
+end
+
+def fun_l0_n630(x)
+ if (x < 1)
+ fun_l1_n528(x)
+ else
+ fun_l1_n440(x)
+ end
+end
+
+def fun_l0_n631(x)
+ if (x < 1)
+ fun_l1_n139(x)
+ else
+ fun_l1_n403(x)
+ end
+end
+
+def fun_l0_n632(x)
+ if (x < 1)
+ fun_l1_n421(x)
+ else
+ fun_l1_n510(x)
+ end
+end
+
+def fun_l0_n633(x)
+ if (x < 1)
+ fun_l1_n718(x)
+ else
+ fun_l1_n388(x)
+ end
+end
+
+def fun_l0_n634(x)
+ if (x < 1)
+ fun_l1_n67(x)
+ else
+ fun_l1_n342(x)
+ end
+end
+
+def fun_l0_n635(x)
+ if (x < 1)
+ fun_l1_n943(x)
+ else
+ fun_l1_n941(x)
+ end
+end
+
+def fun_l0_n636(x)
+ if (x < 1)
+ fun_l1_n170(x)
+ else
+ fun_l1_n527(x)
+ end
+end
+
+def fun_l0_n637(x)
+ if (x < 1)
+ fun_l1_n336(x)
+ else
+ fun_l1_n496(x)
+ end
+end
+
+def fun_l0_n638(x)
+ if (x < 1)
+ fun_l1_n730(x)
+ else
+ fun_l1_n10(x)
+ end
+end
+
+def fun_l0_n639(x)
+ if (x < 1)
+ fun_l1_n939(x)
+ else
+ fun_l1_n940(x)
+ end
+end
+
+def fun_l0_n640(x)
+ if (x < 1)
+ fun_l1_n73(x)
+ else
+ fun_l1_n439(x)
+ end
+end
+
+def fun_l0_n641(x)
+ if (x < 1)
+ fun_l1_n460(x)
+ else
+ fun_l1_n828(x)
+ end
+end
+
+def fun_l0_n642(x)
+ if (x < 1)
+ fun_l1_n90(x)
+ else
+ fun_l1_n113(x)
+ end
+end
+
+def fun_l0_n643(x)
+ if (x < 1)
+ fun_l1_n972(x)
+ else
+ fun_l1_n15(x)
+ end
+end
+
+def fun_l0_n644(x)
+ if (x < 1)
+ fun_l1_n417(x)
+ else
+ fun_l1_n228(x)
+ end
+end
+
+def fun_l0_n645(x)
+ if (x < 1)
+ fun_l1_n876(x)
+ else
+ fun_l1_n152(x)
+ end
+end
+
+def fun_l0_n646(x)
+ if (x < 1)
+ fun_l1_n404(x)
+ else
+ fun_l1_n147(x)
+ end
+end
+
+def fun_l0_n647(x)
+ if (x < 1)
+ fun_l1_n802(x)
+ else
+ fun_l1_n824(x)
+ end
+end
+
+def fun_l0_n648(x)
+ if (x < 1)
+ fun_l1_n771(x)
+ else
+ fun_l1_n421(x)
+ end
+end
+
+def fun_l0_n649(x)
+ if (x < 1)
+ fun_l1_n807(x)
+ else
+ fun_l1_n955(x)
+ end
+end
+
+def fun_l0_n650(x)
+ if (x < 1)
+ fun_l1_n221(x)
+ else
+ fun_l1_n367(x)
+ end
+end
+
+def fun_l0_n651(x)
+ if (x < 1)
+ fun_l1_n955(x)
+ else
+ fun_l1_n401(x)
+ end
+end
+
+def fun_l0_n652(x)
+ if (x < 1)
+ fun_l1_n203(x)
+ else
+ fun_l1_n909(x)
+ end
+end
+
+def fun_l0_n653(x)
+ if (x < 1)
+ fun_l1_n154(x)
+ else
+ fun_l1_n535(x)
+ end
+end
+
+def fun_l0_n654(x)
+ if (x < 1)
+ fun_l1_n420(x)
+ else
+ fun_l1_n393(x)
+ end
+end
+
+def fun_l0_n655(x)
+ if (x < 1)
+ fun_l1_n232(x)
+ else
+ fun_l1_n981(x)
+ end
+end
+
+def fun_l0_n656(x)
+ if (x < 1)
+ fun_l1_n873(x)
+ else
+ fun_l1_n510(x)
+ end
+end
+
+def fun_l0_n657(x)
+ if (x < 1)
+ fun_l1_n919(x)
+ else
+ fun_l1_n706(x)
+ end
+end
+
+def fun_l0_n658(x)
+ if (x < 1)
+ fun_l1_n429(x)
+ else
+ fun_l1_n112(x)
+ end
+end
+
+def fun_l0_n659(x)
+ if (x < 1)
+ fun_l1_n547(x)
+ else
+ fun_l1_n712(x)
+ end
+end
+
+def fun_l0_n660(x)
+ if (x < 1)
+ fun_l1_n498(x)
+ else
+ fun_l1_n695(x)
+ end
+end
+
+def fun_l0_n661(x)
+ if (x < 1)
+ fun_l1_n801(x)
+ else
+ fun_l1_n659(x)
+ end
+end
+
+def fun_l0_n662(x)
+ if (x < 1)
+ fun_l1_n796(x)
+ else
+ fun_l1_n229(x)
+ end
+end
+
+def fun_l0_n663(x)
+ if (x < 1)
+ fun_l1_n11(x)
+ else
+ fun_l1_n620(x)
+ end
+end
+
+def fun_l0_n664(x)
+ if (x < 1)
+ fun_l1_n652(x)
+ else
+ fun_l1_n416(x)
+ end
+end
+
+def fun_l0_n665(x)
+ if (x < 1)
+ fun_l1_n655(x)
+ else
+ fun_l1_n331(x)
+ end
+end
+
+def fun_l0_n666(x)
+ if (x < 1)
+ fun_l1_n846(x)
+ else
+ fun_l1_n1(x)
+ end
+end
+
+def fun_l0_n667(x)
+ if (x < 1)
+ fun_l1_n55(x)
+ else
+ fun_l1_n32(x)
+ end
+end
+
+def fun_l0_n668(x)
+ if (x < 1)
+ fun_l1_n241(x)
+ else
+ fun_l1_n627(x)
+ end
+end
+
+def fun_l0_n669(x)
+ if (x < 1)
+ fun_l1_n234(x)
+ else
+ fun_l1_n996(x)
+ end
+end
+
+def fun_l0_n670(x)
+ if (x < 1)
+ fun_l1_n235(x)
+ else
+ fun_l1_n761(x)
+ end
+end
+
+def fun_l0_n671(x)
+ if (x < 1)
+ fun_l1_n990(x)
+ else
+ fun_l1_n236(x)
+ end
+end
+
+def fun_l0_n672(x)
+ if (x < 1)
+ fun_l1_n970(x)
+ else
+ fun_l1_n595(x)
+ end
+end
+
+def fun_l0_n673(x)
+ if (x < 1)
+ fun_l1_n294(x)
+ else
+ fun_l1_n440(x)
+ end
+end
+
+def fun_l0_n674(x)
+ if (x < 1)
+ fun_l1_n597(x)
+ else
+ fun_l1_n956(x)
+ end
+end
+
+def fun_l0_n675(x)
+ if (x < 1)
+ fun_l1_n942(x)
+ else
+ fun_l1_n352(x)
+ end
+end
+
+def fun_l0_n676(x)
+ if (x < 1)
+ fun_l1_n309(x)
+ else
+ fun_l1_n294(x)
+ end
+end
+
+def fun_l0_n677(x)
+ if (x < 1)
+ fun_l1_n752(x)
+ else
+ fun_l1_n447(x)
+ end
+end
+
+def fun_l0_n678(x)
+ if (x < 1)
+ fun_l1_n890(x)
+ else
+ fun_l1_n497(x)
+ end
+end
+
+def fun_l0_n679(x)
+ if (x < 1)
+ fun_l1_n808(x)
+ else
+ fun_l1_n881(x)
+ end
+end
+
+def fun_l0_n680(x)
+ if (x < 1)
+ fun_l1_n966(x)
+ else
+ fun_l1_n460(x)
+ end
+end
+
+def fun_l0_n681(x)
+ if (x < 1)
+ fun_l1_n104(x)
+ else
+ fun_l1_n262(x)
+ end
+end
+
+def fun_l0_n682(x)
+ if (x < 1)
+ fun_l1_n425(x)
+ else
+ fun_l1_n177(x)
+ end
+end
+
+def fun_l0_n683(x)
+ if (x < 1)
+ fun_l1_n15(x)
+ else
+ fun_l1_n458(x)
+ end
+end
+
+def fun_l0_n684(x)
+ if (x < 1)
+ fun_l1_n760(x)
+ else
+ fun_l1_n997(x)
+ end
+end
+
+def fun_l0_n685(x)
+ if (x < 1)
+ fun_l1_n496(x)
+ else
+ fun_l1_n223(x)
+ end
+end
+
+def fun_l0_n686(x)
+ if (x < 1)
+ fun_l1_n363(x)
+ else
+ fun_l1_n543(x)
+ end
+end
+
+def fun_l0_n687(x)
+ if (x < 1)
+ fun_l1_n758(x)
+ else
+ fun_l1_n473(x)
+ end
+end
+
+def fun_l0_n688(x)
+ if (x < 1)
+ fun_l1_n854(x)
+ else
+ fun_l1_n999(x)
+ end
+end
+
+def fun_l0_n689(x)
+ if (x < 1)
+ fun_l1_n336(x)
+ else
+ fun_l1_n388(x)
+ end
+end
+
+def fun_l0_n690(x)
+ if (x < 1)
+ fun_l1_n930(x)
+ else
+ fun_l1_n478(x)
+ end
+end
+
+def fun_l0_n691(x)
+ if (x < 1)
+ fun_l1_n423(x)
+ else
+ fun_l1_n83(x)
+ end
+end
+
+def fun_l0_n692(x)
+ if (x < 1)
+ fun_l1_n797(x)
+ else
+ fun_l1_n427(x)
+ end
+end
+
+def fun_l0_n693(x)
+ if (x < 1)
+ fun_l1_n907(x)
+ else
+ fun_l1_n1(x)
+ end
+end
+
+def fun_l0_n694(x)
+ if (x < 1)
+ fun_l1_n601(x)
+ else
+ fun_l1_n809(x)
+ end
+end
+
+def fun_l0_n695(x)
+ if (x < 1)
+ fun_l1_n252(x)
+ else
+ fun_l1_n233(x)
+ end
+end
+
+def fun_l0_n696(x)
+ if (x < 1)
+ fun_l1_n36(x)
+ else
+ fun_l1_n796(x)
+ end
+end
+
+def fun_l0_n697(x)
+ if (x < 1)
+ fun_l1_n893(x)
+ else
+ fun_l1_n926(x)
+ end
+end
+
+def fun_l0_n698(x)
+ if (x < 1)
+ fun_l1_n511(x)
+ else
+ fun_l1_n88(x)
+ end
+end
+
+def fun_l0_n699(x)
+ if (x < 1)
+ fun_l1_n573(x)
+ else
+ fun_l1_n718(x)
+ end
+end
+
+def fun_l0_n700(x)
+ if (x < 1)
+ fun_l1_n475(x)
+ else
+ fun_l1_n539(x)
+ end
+end
+
+def fun_l0_n701(x)
+ if (x < 1)
+ fun_l1_n238(x)
+ else
+ fun_l1_n253(x)
+ end
+end
+
+def fun_l0_n702(x)
+ if (x < 1)
+ fun_l1_n731(x)
+ else
+ fun_l1_n225(x)
+ end
+end
+
+def fun_l0_n703(x)
+ if (x < 1)
+ fun_l1_n594(x)
+ else
+ fun_l1_n16(x)
+ end
+end
+
+def fun_l0_n704(x)
+ if (x < 1)
+ fun_l1_n732(x)
+ else
+ fun_l1_n354(x)
+ end
+end
+
+def fun_l0_n705(x)
+ if (x < 1)
+ fun_l1_n812(x)
+ else
+ fun_l1_n218(x)
+ end
+end
+
+def fun_l0_n706(x)
+ if (x < 1)
+ fun_l1_n731(x)
+ else
+ fun_l1_n343(x)
+ end
+end
+
+def fun_l0_n707(x)
+ if (x < 1)
+ fun_l1_n134(x)
+ else
+ fun_l1_n752(x)
+ end
+end
+
+def fun_l0_n708(x)
+ if (x < 1)
+ fun_l1_n899(x)
+ else
+ fun_l1_n854(x)
+ end
+end
+
+def fun_l0_n709(x)
+ if (x < 1)
+ fun_l1_n120(x)
+ else
+ fun_l1_n193(x)
+ end
+end
+
+def fun_l0_n710(x)
+ if (x < 1)
+ fun_l1_n22(x)
+ else
+ fun_l1_n254(x)
+ end
+end
+
+def fun_l0_n711(x)
+ if (x < 1)
+ fun_l1_n527(x)
+ else
+ fun_l1_n921(x)
+ end
+end
+
+def fun_l0_n712(x)
+ if (x < 1)
+ fun_l1_n820(x)
+ else
+ fun_l1_n96(x)
+ end
+end
+
+def fun_l0_n713(x)
+ if (x < 1)
+ fun_l1_n145(x)
+ else
+ fun_l1_n226(x)
+ end
+end
+
+def fun_l0_n714(x)
+ if (x < 1)
+ fun_l1_n643(x)
+ else
+ fun_l1_n407(x)
+ end
+end
+
+def fun_l0_n715(x)
+ if (x < 1)
+ fun_l1_n349(x)
+ else
+ fun_l1_n450(x)
+ end
+end
+
+def fun_l0_n716(x)
+ if (x < 1)
+ fun_l1_n954(x)
+ else
+ fun_l1_n707(x)
+ end
+end
+
+def fun_l0_n717(x)
+ if (x < 1)
+ fun_l1_n723(x)
+ else
+ fun_l1_n762(x)
+ end
+end
+
+def fun_l0_n718(x)
+ if (x < 1)
+ fun_l1_n299(x)
+ else
+ fun_l1_n332(x)
+ end
+end
+
+def fun_l0_n719(x)
+ if (x < 1)
+ fun_l1_n493(x)
+ else
+ fun_l1_n521(x)
+ end
+end
+
+def fun_l0_n720(x)
+ if (x < 1)
+ fun_l1_n39(x)
+ else
+ fun_l1_n17(x)
+ end
+end
+
+def fun_l0_n721(x)
+ if (x < 1)
+ fun_l1_n297(x)
+ else
+ fun_l1_n800(x)
+ end
+end
+
+def fun_l0_n722(x)
+ if (x < 1)
+ fun_l1_n758(x)
+ else
+ fun_l1_n135(x)
+ end
+end
+
+def fun_l0_n723(x)
+ if (x < 1)
+ fun_l1_n471(x)
+ else
+ fun_l1_n351(x)
+ end
+end
+
+def fun_l0_n724(x)
+ if (x < 1)
+ fun_l1_n381(x)
+ else
+ fun_l1_n281(x)
+ end
+end
+
+def fun_l0_n725(x)
+ if (x < 1)
+ fun_l1_n624(x)
+ else
+ fun_l1_n162(x)
+ end
+end
+
+def fun_l0_n726(x)
+ if (x < 1)
+ fun_l1_n143(x)
+ else
+ fun_l1_n417(x)
+ end
+end
+
+def fun_l0_n727(x)
+ if (x < 1)
+ fun_l1_n623(x)
+ else
+ fun_l1_n19(x)
+ end
+end
+
+def fun_l0_n728(x)
+ if (x < 1)
+ fun_l1_n687(x)
+ else
+ fun_l1_n574(x)
+ end
+end
+
+def fun_l0_n729(x)
+ if (x < 1)
+ fun_l1_n225(x)
+ else
+ fun_l1_n871(x)
+ end
+end
+
+def fun_l0_n730(x)
+ if (x < 1)
+ fun_l1_n830(x)
+ else
+ fun_l1_n273(x)
+ end
+end
+
+def fun_l0_n731(x)
+ if (x < 1)
+ fun_l1_n95(x)
+ else
+ fun_l1_n864(x)
+ end
+end
+
+def fun_l0_n732(x)
+ if (x < 1)
+ fun_l1_n902(x)
+ else
+ fun_l1_n522(x)
+ end
+end
+
+def fun_l0_n733(x)
+ if (x < 1)
+ fun_l1_n564(x)
+ else
+ fun_l1_n55(x)
+ end
+end
+
+def fun_l0_n734(x)
+ if (x < 1)
+ fun_l1_n481(x)
+ else
+ fun_l1_n880(x)
+ end
+end
+
+def fun_l0_n735(x)
+ if (x < 1)
+ fun_l1_n87(x)
+ else
+ fun_l1_n693(x)
+ end
+end
+
+def fun_l0_n736(x)
+ if (x < 1)
+ fun_l1_n72(x)
+ else
+ fun_l1_n396(x)
+ end
+end
+
+def fun_l0_n737(x)
+ if (x < 1)
+ fun_l1_n920(x)
+ else
+ fun_l1_n852(x)
+ end
+end
+
+def fun_l0_n738(x)
+ if (x < 1)
+ fun_l1_n342(x)
+ else
+ fun_l1_n959(x)
+ end
+end
+
+def fun_l0_n739(x)
+ if (x < 1)
+ fun_l1_n682(x)
+ else
+ fun_l1_n714(x)
+ end
+end
+
+def fun_l0_n740(x)
+ if (x < 1)
+ fun_l1_n264(x)
+ else
+ fun_l1_n325(x)
+ end
+end
+
+def fun_l0_n741(x)
+ if (x < 1)
+ fun_l1_n621(x)
+ else
+ fun_l1_n339(x)
+ end
+end
+
+def fun_l0_n742(x)
+ if (x < 1)
+ fun_l1_n46(x)
+ else
+ fun_l1_n766(x)
+ end
+end
+
+def fun_l0_n743(x)
+ if (x < 1)
+ fun_l1_n333(x)
+ else
+ fun_l1_n353(x)
+ end
+end
+
+def fun_l0_n744(x)
+ if (x < 1)
+ fun_l1_n930(x)
+ else
+ fun_l1_n964(x)
+ end
+end
+
+def fun_l0_n745(x)
+ if (x < 1)
+ fun_l1_n785(x)
+ else
+ fun_l1_n114(x)
+ end
+end
+
+def fun_l0_n746(x)
+ if (x < 1)
+ fun_l1_n402(x)
+ else
+ fun_l1_n803(x)
+ end
+end
+
+def fun_l0_n747(x)
+ if (x < 1)
+ fun_l1_n878(x)
+ else
+ fun_l1_n870(x)
+ end
+end
+
+def fun_l0_n748(x)
+ if (x < 1)
+ fun_l1_n683(x)
+ else
+ fun_l1_n287(x)
+ end
+end
+
+def fun_l0_n749(x)
+ if (x < 1)
+ fun_l1_n816(x)
+ else
+ fun_l1_n849(x)
+ end
+end
+
+def fun_l0_n750(x)
+ if (x < 1)
+ fun_l1_n523(x)
+ else
+ fun_l1_n555(x)
+ end
+end
+
+def fun_l0_n751(x)
+ if (x < 1)
+ fun_l1_n270(x)
+ else
+ fun_l1_n660(x)
+ end
+end
+
+def fun_l0_n752(x)
+ if (x < 1)
+ fun_l1_n786(x)
+ else
+ fun_l1_n749(x)
+ end
+end
+
+def fun_l0_n753(x)
+ if (x < 1)
+ fun_l1_n567(x)
+ else
+ fun_l1_n325(x)
+ end
+end
+
+def fun_l0_n754(x)
+ if (x < 1)
+ fun_l1_n502(x)
+ else
+ fun_l1_n610(x)
+ end
+end
+
+def fun_l0_n755(x)
+ if (x < 1)
+ fun_l1_n336(x)
+ else
+ fun_l1_n354(x)
+ end
+end
+
+def fun_l0_n756(x)
+ if (x < 1)
+ fun_l1_n435(x)
+ else
+ fun_l1_n484(x)
+ end
+end
+
+def fun_l0_n757(x)
+ if (x < 1)
+ fun_l1_n849(x)
+ else
+ fun_l1_n42(x)
+ end
+end
+
+def fun_l0_n758(x)
+ if (x < 1)
+ fun_l1_n294(x)
+ else
+ fun_l1_n483(x)
+ end
+end
+
+def fun_l0_n759(x)
+ if (x < 1)
+ fun_l1_n14(x)
+ else
+ fun_l1_n9(x)
+ end
+end
+
+def fun_l0_n760(x)
+ if (x < 1)
+ fun_l1_n860(x)
+ else
+ fun_l1_n645(x)
+ end
+end
+
+def fun_l0_n761(x)
+ if (x < 1)
+ fun_l1_n577(x)
+ else
+ fun_l1_n0(x)
+ end
+end
+
+def fun_l0_n762(x)
+ if (x < 1)
+ fun_l1_n28(x)
+ else
+ fun_l1_n834(x)
+ end
+end
+
+def fun_l0_n763(x)
+ if (x < 1)
+ fun_l1_n147(x)
+ else
+ fun_l1_n177(x)
+ end
+end
+
+def fun_l0_n764(x)
+ if (x < 1)
+ fun_l1_n429(x)
+ else
+ fun_l1_n646(x)
+ end
+end
+
+def fun_l0_n765(x)
+ if (x < 1)
+ fun_l1_n474(x)
+ else
+ fun_l1_n22(x)
+ end
+end
+
+def fun_l0_n766(x)
+ if (x < 1)
+ fun_l1_n264(x)
+ else
+ fun_l1_n549(x)
+ end
+end
+
+def fun_l0_n767(x)
+ if (x < 1)
+ fun_l1_n351(x)
+ else
+ fun_l1_n813(x)
+ end
+end
+
+def fun_l0_n768(x)
+ if (x < 1)
+ fun_l1_n798(x)
+ else
+ fun_l1_n684(x)
+ end
+end
+
+def fun_l0_n769(x)
+ if (x < 1)
+ fun_l1_n202(x)
+ else
+ fun_l1_n982(x)
+ end
+end
+
+def fun_l0_n770(x)
+ if (x < 1)
+ fun_l1_n611(x)
+ else
+ fun_l1_n52(x)
+ end
+end
+
+def fun_l0_n771(x)
+ if (x < 1)
+ fun_l1_n754(x)
+ else
+ fun_l1_n7(x)
+ end
+end
+
+def fun_l0_n772(x)
+ if (x < 1)
+ fun_l1_n98(x)
+ else
+ fun_l1_n149(x)
+ end
+end
+
+def fun_l0_n773(x)
+ if (x < 1)
+ fun_l1_n358(x)
+ else
+ fun_l1_n603(x)
+ end
+end
+
+def fun_l0_n774(x)
+ if (x < 1)
+ fun_l1_n604(x)
+ else
+ fun_l1_n318(x)
+ end
+end
+
+def fun_l0_n775(x)
+ if (x < 1)
+ fun_l1_n831(x)
+ else
+ fun_l1_n635(x)
+ end
+end
+
+def fun_l0_n776(x)
+ if (x < 1)
+ fun_l1_n738(x)
+ else
+ fun_l1_n563(x)
+ end
+end
+
+def fun_l0_n777(x)
+ if (x < 1)
+ fun_l1_n570(x)
+ else
+ fun_l1_n671(x)
+ end
+end
+
+def fun_l0_n778(x)
+ if (x < 1)
+ fun_l1_n945(x)
+ else
+ fun_l1_n840(x)
+ end
+end
+
+def fun_l0_n779(x)
+ if (x < 1)
+ fun_l1_n116(x)
+ else
+ fun_l1_n942(x)
+ end
+end
+
+def fun_l0_n780(x)
+ if (x < 1)
+ fun_l1_n835(x)
+ else
+ fun_l1_n244(x)
+ end
+end
+
+def fun_l0_n781(x)
+ if (x < 1)
+ fun_l1_n427(x)
+ else
+ fun_l1_n556(x)
+ end
+end
+
+def fun_l0_n782(x)
+ if (x < 1)
+ fun_l1_n280(x)
+ else
+ fun_l1_n926(x)
+ end
+end
+
+def fun_l0_n783(x)
+ if (x < 1)
+ fun_l1_n674(x)
+ else
+ fun_l1_n560(x)
+ end
+end
+
+def fun_l0_n784(x)
+ if (x < 1)
+ fun_l1_n978(x)
+ else
+ fun_l1_n139(x)
+ end
+end
+
+def fun_l0_n785(x)
+ if (x < 1)
+ fun_l1_n928(x)
+ else
+ fun_l1_n11(x)
+ end
+end
+
+def fun_l0_n786(x)
+ if (x < 1)
+ fun_l1_n829(x)
+ else
+ fun_l1_n239(x)
+ end
+end
+
+def fun_l0_n787(x)
+ if (x < 1)
+ fun_l1_n732(x)
+ else
+ fun_l1_n829(x)
+ end
+end
+
+def fun_l0_n788(x)
+ if (x < 1)
+ fun_l1_n968(x)
+ else
+ fun_l1_n596(x)
+ end
+end
+
+def fun_l0_n789(x)
+ if (x < 1)
+ fun_l1_n214(x)
+ else
+ fun_l1_n158(x)
+ end
+end
+
+def fun_l0_n790(x)
+ if (x < 1)
+ fun_l1_n566(x)
+ else
+ fun_l1_n390(x)
+ end
+end
+
+def fun_l0_n791(x)
+ if (x < 1)
+ fun_l1_n936(x)
+ else
+ fun_l1_n31(x)
+ end
+end
+
+def fun_l0_n792(x)
+ if (x < 1)
+ fun_l1_n291(x)
+ else
+ fun_l1_n835(x)
+ end
+end
+
+def fun_l0_n793(x)
+ if (x < 1)
+ fun_l1_n300(x)
+ else
+ fun_l1_n658(x)
+ end
+end
+
+def fun_l0_n794(x)
+ if (x < 1)
+ fun_l1_n609(x)
+ else
+ fun_l1_n156(x)
+ end
+end
+
+def fun_l0_n795(x)
+ if (x < 1)
+ fun_l1_n419(x)
+ else
+ fun_l1_n534(x)
+ end
+end
+
+def fun_l0_n796(x)
+ if (x < 1)
+ fun_l1_n401(x)
+ else
+ fun_l1_n281(x)
+ end
+end
+
+def fun_l0_n797(x)
+ if (x < 1)
+ fun_l1_n538(x)
+ else
+ fun_l1_n905(x)
+ end
+end
+
+def fun_l0_n798(x)
+ if (x < 1)
+ fun_l1_n427(x)
+ else
+ fun_l1_n978(x)
+ end
+end
+
+def fun_l0_n799(x)
+ if (x < 1)
+ fun_l1_n851(x)
+ else
+ fun_l1_n57(x)
+ end
+end
+
+def fun_l0_n800(x)
+ if (x < 1)
+ fun_l1_n836(x)
+ else
+ fun_l1_n306(x)
+ end
+end
+
+def fun_l0_n801(x)
+ if (x < 1)
+ fun_l1_n414(x)
+ else
+ fun_l1_n679(x)
+ end
+end
+
+def fun_l0_n802(x)
+ if (x < 1)
+ fun_l1_n645(x)
+ else
+ fun_l1_n115(x)
+ end
+end
+
+def fun_l0_n803(x)
+ if (x < 1)
+ fun_l1_n884(x)
+ else
+ fun_l1_n801(x)
+ end
+end
+
+def fun_l0_n804(x)
+ if (x < 1)
+ fun_l1_n713(x)
+ else
+ fun_l1_n974(x)
+ end
+end
+
+def fun_l0_n805(x)
+ if (x < 1)
+ fun_l1_n301(x)
+ else
+ fun_l1_n589(x)
+ end
+end
+
+def fun_l0_n806(x)
+ if (x < 1)
+ fun_l1_n912(x)
+ else
+ fun_l1_n766(x)
+ end
+end
+
+def fun_l0_n807(x)
+ if (x < 1)
+ fun_l1_n656(x)
+ else
+ fun_l1_n765(x)
+ end
+end
+
+def fun_l0_n808(x)
+ if (x < 1)
+ fun_l1_n517(x)
+ else
+ fun_l1_n964(x)
+ end
+end
+
+def fun_l0_n809(x)
+ if (x < 1)
+ fun_l1_n878(x)
+ else
+ fun_l1_n69(x)
+ end
+end
+
+def fun_l0_n810(x)
+ if (x < 1)
+ fun_l1_n527(x)
+ else
+ fun_l1_n841(x)
+ end
+end
+
+def fun_l0_n811(x)
+ if (x < 1)
+ fun_l1_n564(x)
+ else
+ fun_l1_n541(x)
+ end
+end
+
+def fun_l0_n812(x)
+ if (x < 1)
+ fun_l1_n754(x)
+ else
+ fun_l1_n681(x)
+ end
+end
+
+def fun_l0_n813(x)
+ if (x < 1)
+ fun_l1_n21(x)
+ else
+ fun_l1_n561(x)
+ end
+end
+
+def fun_l0_n814(x)
+ if (x < 1)
+ fun_l1_n547(x)
+ else
+ fun_l1_n631(x)
+ end
+end
+
+def fun_l0_n815(x)
+ if (x < 1)
+ fun_l1_n956(x)
+ else
+ fun_l1_n889(x)
+ end
+end
+
+def fun_l0_n816(x)
+ if (x < 1)
+ fun_l1_n817(x)
+ else
+ fun_l1_n957(x)
+ end
+end
+
+def fun_l0_n817(x)
+ if (x < 1)
+ fun_l1_n622(x)
+ else
+ fun_l1_n827(x)
+ end
+end
+
+def fun_l0_n818(x)
+ if (x < 1)
+ fun_l1_n7(x)
+ else
+ fun_l1_n208(x)
+ end
+end
+
+def fun_l0_n819(x)
+ if (x < 1)
+ fun_l1_n411(x)
+ else
+ fun_l1_n742(x)
+ end
+end
+
+def fun_l0_n820(x)
+ if (x < 1)
+ fun_l1_n676(x)
+ else
+ fun_l1_n144(x)
+ end
+end
+
+def fun_l0_n821(x)
+ if (x < 1)
+ fun_l1_n489(x)
+ else
+ fun_l1_n963(x)
+ end
+end
+
+def fun_l0_n822(x)
+ if (x < 1)
+ fun_l1_n645(x)
+ else
+ fun_l1_n953(x)
+ end
+end
+
+def fun_l0_n823(x)
+ if (x < 1)
+ fun_l1_n974(x)
+ else
+ fun_l1_n75(x)
+ end
+end
+
+def fun_l0_n824(x)
+ if (x < 1)
+ fun_l1_n295(x)
+ else
+ fun_l1_n249(x)
+ end
+end
+
+def fun_l0_n825(x)
+ if (x < 1)
+ fun_l1_n141(x)
+ else
+ fun_l1_n633(x)
+ end
+end
+
+def fun_l0_n826(x)
+ if (x < 1)
+ fun_l1_n317(x)
+ else
+ fun_l1_n152(x)
+ end
+end
+
+def fun_l0_n827(x)
+ if (x < 1)
+ fun_l1_n570(x)
+ else
+ fun_l1_n377(x)
+ end
+end
+
+def fun_l0_n828(x)
+ if (x < 1)
+ fun_l1_n392(x)
+ else
+ fun_l1_n477(x)
+ end
+end
+
+def fun_l0_n829(x)
+ if (x < 1)
+ fun_l1_n277(x)
+ else
+ fun_l1_n276(x)
+ end
+end
+
+def fun_l0_n830(x)
+ if (x < 1)
+ fun_l1_n579(x)
+ else
+ fun_l1_n648(x)
+ end
+end
+
+def fun_l0_n831(x)
+ if (x < 1)
+ fun_l1_n8(x)
+ else
+ fun_l1_n25(x)
+ end
+end
+
+def fun_l0_n832(x)
+ if (x < 1)
+ fun_l1_n724(x)
+ else
+ fun_l1_n617(x)
+ end
+end
+
+def fun_l0_n833(x)
+ if (x < 1)
+ fun_l1_n771(x)
+ else
+ fun_l1_n619(x)
+ end
+end
+
+def fun_l0_n834(x)
+ if (x < 1)
+ fun_l1_n23(x)
+ else
+ fun_l1_n127(x)
+ end
+end
+
+def fun_l0_n835(x)
+ if (x < 1)
+ fun_l1_n322(x)
+ else
+ fun_l1_n327(x)
+ end
+end
+
+def fun_l0_n836(x)
+ if (x < 1)
+ fun_l1_n7(x)
+ else
+ fun_l1_n600(x)
+ end
+end
+
+def fun_l0_n837(x)
+ if (x < 1)
+ fun_l1_n796(x)
+ else
+ fun_l1_n782(x)
+ end
+end
+
+def fun_l0_n838(x)
+ if (x < 1)
+ fun_l1_n937(x)
+ else
+ fun_l1_n899(x)
+ end
+end
+
+def fun_l0_n839(x)
+ if (x < 1)
+ fun_l1_n16(x)
+ else
+ fun_l1_n349(x)
+ end
+end
+
+def fun_l0_n840(x)
+ if (x < 1)
+ fun_l1_n622(x)
+ else
+ fun_l1_n960(x)
+ end
+end
+
+def fun_l0_n841(x)
+ if (x < 1)
+ fun_l1_n295(x)
+ else
+ fun_l1_n176(x)
+ end
+end
+
+def fun_l0_n842(x)
+ if (x < 1)
+ fun_l1_n302(x)
+ else
+ fun_l1_n639(x)
+ end
+end
+
+def fun_l0_n843(x)
+ if (x < 1)
+ fun_l1_n342(x)
+ else
+ fun_l1_n373(x)
+ end
+end
+
+def fun_l0_n844(x)
+ if (x < 1)
+ fun_l1_n5(x)
+ else
+ fun_l1_n787(x)
+ end
+end
+
+def fun_l0_n845(x)
+ if (x < 1)
+ fun_l1_n89(x)
+ else
+ fun_l1_n951(x)
+ end
+end
+
+def fun_l0_n846(x)
+ if (x < 1)
+ fun_l1_n954(x)
+ else
+ fun_l1_n982(x)
+ end
+end
+
+def fun_l0_n847(x)
+ if (x < 1)
+ fun_l1_n971(x)
+ else
+ fun_l1_n917(x)
+ end
+end
+
+def fun_l0_n848(x)
+ if (x < 1)
+ fun_l1_n845(x)
+ else
+ fun_l1_n343(x)
+ end
+end
+
+def fun_l0_n849(x)
+ if (x < 1)
+ fun_l1_n684(x)
+ else
+ fun_l1_n683(x)
+ end
+end
+
+def fun_l0_n850(x)
+ if (x < 1)
+ fun_l1_n670(x)
+ else
+ fun_l1_n256(x)
+ end
+end
+
+def fun_l0_n851(x)
+ if (x < 1)
+ fun_l1_n405(x)
+ else
+ fun_l1_n123(x)
+ end
+end
+
+def fun_l0_n852(x)
+ if (x < 1)
+ fun_l1_n809(x)
+ else
+ fun_l1_n691(x)
+ end
+end
+
+def fun_l0_n853(x)
+ if (x < 1)
+ fun_l1_n937(x)
+ else
+ fun_l1_n92(x)
+ end
+end
+
+def fun_l0_n854(x)
+ if (x < 1)
+ fun_l1_n735(x)
+ else
+ fun_l1_n948(x)
+ end
+end
+
+def fun_l0_n855(x)
+ if (x < 1)
+ fun_l1_n684(x)
+ else
+ fun_l1_n566(x)
+ end
+end
+
+def fun_l0_n856(x)
+ if (x < 1)
+ fun_l1_n508(x)
+ else
+ fun_l1_n35(x)
+ end
+end
+
+def fun_l0_n857(x)
+ if (x < 1)
+ fun_l1_n865(x)
+ else
+ fun_l1_n930(x)
+ end
+end
+
+def fun_l0_n858(x)
+ if (x < 1)
+ fun_l1_n937(x)
+ else
+ fun_l1_n241(x)
+ end
+end
+
+def fun_l0_n859(x)
+ if (x < 1)
+ fun_l1_n938(x)
+ else
+ fun_l1_n108(x)
+ end
+end
+
+def fun_l0_n860(x)
+ if (x < 1)
+ fun_l1_n491(x)
+ else
+ fun_l1_n119(x)
+ end
+end
+
+def fun_l0_n861(x)
+ if (x < 1)
+ fun_l1_n991(x)
+ else
+ fun_l1_n198(x)
+ end
+end
+
+def fun_l0_n862(x)
+ if (x < 1)
+ fun_l1_n846(x)
+ else
+ fun_l1_n513(x)
+ end
+end
+
+def fun_l0_n863(x)
+ if (x < 1)
+ fun_l1_n279(x)
+ else
+ fun_l1_n229(x)
+ end
+end
+
+def fun_l0_n864(x)
+ if (x < 1)
+ fun_l1_n52(x)
+ else
+ fun_l1_n765(x)
+ end
+end
+
+def fun_l0_n865(x)
+ if (x < 1)
+ fun_l1_n35(x)
+ else
+ fun_l1_n572(x)
+ end
+end
+
+def fun_l0_n866(x)
+ if (x < 1)
+ fun_l1_n4(x)
+ else
+ fun_l1_n645(x)
+ end
+end
+
+def fun_l0_n867(x)
+ if (x < 1)
+ fun_l1_n112(x)
+ else
+ fun_l1_n758(x)
+ end
+end
+
+def fun_l0_n868(x)
+ if (x < 1)
+ fun_l1_n924(x)
+ else
+ fun_l1_n251(x)
+ end
+end
+
+def fun_l0_n869(x)
+ if (x < 1)
+ fun_l1_n558(x)
+ else
+ fun_l1_n818(x)
+ end
+end
+
+def fun_l0_n870(x)
+ if (x < 1)
+ fun_l1_n804(x)
+ else
+ fun_l1_n746(x)
+ end
+end
+
+def fun_l0_n871(x)
+ if (x < 1)
+ fun_l1_n111(x)
+ else
+ fun_l1_n407(x)
+ end
+end
+
+def fun_l0_n872(x)
+ if (x < 1)
+ fun_l1_n973(x)
+ else
+ fun_l1_n384(x)
+ end
+end
+
+def fun_l0_n873(x)
+ if (x < 1)
+ fun_l1_n102(x)
+ else
+ fun_l1_n199(x)
+ end
+end
+
+def fun_l0_n874(x)
+ if (x < 1)
+ fun_l1_n735(x)
+ else
+ fun_l1_n903(x)
+ end
+end
+
+def fun_l0_n875(x)
+ if (x < 1)
+ fun_l1_n95(x)
+ else
+ fun_l1_n720(x)
+ end
+end
+
+def fun_l0_n876(x)
+ if (x < 1)
+ fun_l1_n864(x)
+ else
+ fun_l1_n970(x)
+ end
+end
+
+def fun_l0_n877(x)
+ if (x < 1)
+ fun_l1_n729(x)
+ else
+ fun_l1_n207(x)
+ end
+end
+
+def fun_l0_n878(x)
+ if (x < 1)
+ fun_l1_n104(x)
+ else
+ fun_l1_n209(x)
+ end
+end
+
+def fun_l0_n879(x)
+ if (x < 1)
+ fun_l1_n566(x)
+ else
+ fun_l1_n918(x)
+ end
+end
+
+def fun_l0_n880(x)
+ if (x < 1)
+ fun_l1_n457(x)
+ else
+ fun_l1_n104(x)
+ end
+end
+
+def fun_l0_n881(x)
+ if (x < 1)
+ fun_l1_n745(x)
+ else
+ fun_l1_n476(x)
+ end
+end
+
+def fun_l0_n882(x)
+ if (x < 1)
+ fun_l1_n346(x)
+ else
+ fun_l1_n642(x)
+ end
+end
+
+def fun_l0_n883(x)
+ if (x < 1)
+ fun_l1_n78(x)
+ else
+ fun_l1_n210(x)
+ end
+end
+
+def fun_l0_n884(x)
+ if (x < 1)
+ fun_l1_n864(x)
+ else
+ fun_l1_n439(x)
+ end
+end
+
+def fun_l0_n885(x)
+ if (x < 1)
+ fun_l1_n0(x)
+ else
+ fun_l1_n414(x)
+ end
+end
+
+def fun_l0_n886(x)
+ if (x < 1)
+ fun_l1_n217(x)
+ else
+ fun_l1_n444(x)
+ end
+end
+
+def fun_l0_n887(x)
+ if (x < 1)
+ fun_l1_n193(x)
+ else
+ fun_l1_n788(x)
+ end
+end
+
+def fun_l0_n888(x)
+ if (x < 1)
+ fun_l1_n30(x)
+ else
+ fun_l1_n793(x)
+ end
+end
+
+def fun_l0_n889(x)
+ if (x < 1)
+ fun_l1_n222(x)
+ else
+ fun_l1_n936(x)
+ end
+end
+
+def fun_l0_n890(x)
+ if (x < 1)
+ fun_l1_n758(x)
+ else
+ fun_l1_n52(x)
+ end
+end
+
+def fun_l0_n891(x)
+ if (x < 1)
+ fun_l1_n796(x)
+ else
+ fun_l1_n424(x)
+ end
+end
+
+def fun_l0_n892(x)
+ if (x < 1)
+ fun_l1_n627(x)
+ else
+ fun_l1_n284(x)
+ end
+end
+
+def fun_l0_n893(x)
+ if (x < 1)
+ fun_l1_n42(x)
+ else
+ fun_l1_n193(x)
+ end
+end
+
+def fun_l0_n894(x)
+ if (x < 1)
+ fun_l1_n90(x)
+ else
+ fun_l1_n158(x)
+ end
+end
+
+def fun_l0_n895(x)
+ if (x < 1)
+ fun_l1_n878(x)
+ else
+ fun_l1_n396(x)
+ end
+end
+
+def fun_l0_n896(x)
+ if (x < 1)
+ fun_l1_n665(x)
+ else
+ fun_l1_n731(x)
+ end
+end
+
+def fun_l0_n897(x)
+ if (x < 1)
+ fun_l1_n618(x)
+ else
+ fun_l1_n152(x)
+ end
+end
+
+def fun_l0_n898(x)
+ if (x < 1)
+ fun_l1_n64(x)
+ else
+ fun_l1_n697(x)
+ end
+end
+
+def fun_l0_n899(x)
+ if (x < 1)
+ fun_l1_n354(x)
+ else
+ fun_l1_n657(x)
+ end
+end
+
+def fun_l0_n900(x)
+ if (x < 1)
+ fun_l1_n79(x)
+ else
+ fun_l1_n794(x)
+ end
+end
+
+def fun_l0_n901(x)
+ if (x < 1)
+ fun_l1_n623(x)
+ else
+ fun_l1_n392(x)
+ end
+end
+
+def fun_l0_n902(x)
+ if (x < 1)
+ fun_l1_n529(x)
+ else
+ fun_l1_n708(x)
+ end
+end
+
+def fun_l0_n903(x)
+ if (x < 1)
+ fun_l1_n900(x)
+ else
+ fun_l1_n830(x)
+ end
+end
+
+def fun_l0_n904(x)
+ if (x < 1)
+ fun_l1_n424(x)
+ else
+ fun_l1_n564(x)
+ end
+end
+
+def fun_l0_n905(x)
+ if (x < 1)
+ fun_l1_n557(x)
+ else
+ fun_l1_n612(x)
+ end
+end
+
+def fun_l0_n906(x)
+ if (x < 1)
+ fun_l1_n725(x)
+ else
+ fun_l1_n166(x)
+ end
+end
+
+def fun_l0_n907(x)
+ if (x < 1)
+ fun_l1_n534(x)
+ else
+ fun_l1_n159(x)
+ end
+end
+
+def fun_l0_n908(x)
+ if (x < 1)
+ fun_l1_n50(x)
+ else
+ fun_l1_n201(x)
+ end
+end
+
+def fun_l0_n909(x)
+ if (x < 1)
+ fun_l1_n568(x)
+ else
+ fun_l1_n276(x)
+ end
+end
+
+def fun_l0_n910(x)
+ if (x < 1)
+ fun_l1_n0(x)
+ else
+ fun_l1_n324(x)
+ end
+end
+
+def fun_l0_n911(x)
+ if (x < 1)
+ fun_l1_n926(x)
+ else
+ fun_l1_n524(x)
+ end
+end
+
+def fun_l0_n912(x)
+ if (x < 1)
+ fun_l1_n498(x)
+ else
+ fun_l1_n650(x)
+ end
+end
+
+def fun_l0_n913(x)
+ if (x < 1)
+ fun_l1_n593(x)
+ else
+ fun_l1_n860(x)
+ end
+end
+
+def fun_l0_n914(x)
+ if (x < 1)
+ fun_l1_n726(x)
+ else
+ fun_l1_n440(x)
+ end
+end
+
+def fun_l0_n915(x)
+ if (x < 1)
+ fun_l1_n422(x)
+ else
+ fun_l1_n627(x)
+ end
+end
+
+def fun_l0_n916(x)
+ if (x < 1)
+ fun_l1_n346(x)
+ else
+ fun_l1_n932(x)
+ end
+end
+
+def fun_l0_n917(x)
+ if (x < 1)
+ fun_l1_n403(x)
+ else
+ fun_l1_n58(x)
+ end
+end
+
+def fun_l0_n918(x)
+ if (x < 1)
+ fun_l1_n989(x)
+ else
+ fun_l1_n579(x)
+ end
+end
+
+def fun_l0_n919(x)
+ if (x < 1)
+ fun_l1_n933(x)
+ else
+ fun_l1_n434(x)
+ end
+end
+
+def fun_l0_n920(x)
+ if (x < 1)
+ fun_l1_n899(x)
+ else
+ fun_l1_n377(x)
+ end
+end
+
+def fun_l0_n921(x)
+ if (x < 1)
+ fun_l1_n17(x)
+ else
+ fun_l1_n637(x)
+ end
+end
+
+def fun_l0_n922(x)
+ if (x < 1)
+ fun_l1_n551(x)
+ else
+ fun_l1_n693(x)
+ end
+end
+
+def fun_l0_n923(x)
+ if (x < 1)
+ fun_l1_n861(x)
+ else
+ fun_l1_n248(x)
+ end
+end
+
+def fun_l0_n924(x)
+ if (x < 1)
+ fun_l1_n171(x)
+ else
+ fun_l1_n75(x)
+ end
+end
+
+def fun_l0_n925(x)
+ if (x < 1)
+ fun_l1_n233(x)
+ else
+ fun_l1_n444(x)
+ end
+end
+
+def fun_l0_n926(x)
+ if (x < 1)
+ fun_l1_n310(x)
+ else
+ fun_l1_n941(x)
+ end
+end
+
+def fun_l0_n927(x)
+ if (x < 1)
+ fun_l1_n363(x)
+ else
+ fun_l1_n567(x)
+ end
+end
+
+def fun_l0_n928(x)
+ if (x < 1)
+ fun_l1_n632(x)
+ else
+ fun_l1_n840(x)
+ end
+end
+
+def fun_l0_n929(x)
+ if (x < 1)
+ fun_l1_n368(x)
+ else
+ fun_l1_n713(x)
+ end
+end
+
+def fun_l0_n930(x)
+ if (x < 1)
+ fun_l1_n37(x)
+ else
+ fun_l1_n355(x)
+ end
+end
+
+def fun_l0_n931(x)
+ if (x < 1)
+ fun_l1_n907(x)
+ else
+ fun_l1_n784(x)
+ end
+end
+
+def fun_l0_n932(x)
+ if (x < 1)
+ fun_l1_n591(x)
+ else
+ fun_l1_n844(x)
+ end
+end
+
+def fun_l0_n933(x)
+ if (x < 1)
+ fun_l1_n996(x)
+ else
+ fun_l1_n943(x)
+ end
+end
+
+def fun_l0_n934(x)
+ if (x < 1)
+ fun_l1_n631(x)
+ else
+ fun_l1_n643(x)
+ end
+end
+
+def fun_l0_n935(x)
+ if (x < 1)
+ fun_l1_n875(x)
+ else
+ fun_l1_n89(x)
+ end
+end
+
+def fun_l0_n936(x)
+ if (x < 1)
+ fun_l1_n842(x)
+ else
+ fun_l1_n595(x)
+ end
+end
+
+def fun_l0_n937(x)
+ if (x < 1)
+ fun_l1_n921(x)
+ else
+ fun_l1_n271(x)
+ end
+end
+
+def fun_l0_n938(x)
+ if (x < 1)
+ fun_l1_n222(x)
+ else
+ fun_l1_n170(x)
+ end
+end
+
+def fun_l0_n939(x)
+ if (x < 1)
+ fun_l1_n567(x)
+ else
+ fun_l1_n463(x)
+ end
+end
+
+def fun_l0_n940(x)
+ if (x < 1)
+ fun_l1_n456(x)
+ else
+ fun_l1_n192(x)
+ end
+end
+
+def fun_l0_n941(x)
+ if (x < 1)
+ fun_l1_n32(x)
+ else
+ fun_l1_n951(x)
+ end
+end
+
+def fun_l0_n942(x)
+ if (x < 1)
+ fun_l1_n14(x)
+ else
+ fun_l1_n135(x)
+ end
+end
+
+def fun_l0_n943(x)
+ if (x < 1)
+ fun_l1_n15(x)
+ else
+ fun_l1_n234(x)
+ end
+end
+
+def fun_l0_n944(x)
+ if (x < 1)
+ fun_l1_n119(x)
+ else
+ fun_l1_n33(x)
+ end
+end
+
+def fun_l0_n945(x)
+ if (x < 1)
+ fun_l1_n859(x)
+ else
+ fun_l1_n497(x)
+ end
+end
+
+def fun_l0_n946(x)
+ if (x < 1)
+ fun_l1_n178(x)
+ else
+ fun_l1_n369(x)
+ end
+end
+
+def fun_l0_n947(x)
+ if (x < 1)
+ fun_l1_n64(x)
+ else
+ fun_l1_n356(x)
+ end
+end
+
+def fun_l0_n948(x)
+ if (x < 1)
+ fun_l1_n279(x)
+ else
+ fun_l1_n244(x)
+ end
+end
+
+def fun_l0_n949(x)
+ if (x < 1)
+ fun_l1_n728(x)
+ else
+ fun_l1_n548(x)
+ end
+end
+
+def fun_l0_n950(x)
+ if (x < 1)
+ fun_l1_n3(x)
+ else
+ fun_l1_n698(x)
+ end
+end
+
+def fun_l0_n951(x)
+ if (x < 1)
+ fun_l1_n665(x)
+ else
+ fun_l1_n198(x)
+ end
+end
+
+def fun_l0_n952(x)
+ if (x < 1)
+ fun_l1_n812(x)
+ else
+ fun_l1_n964(x)
+ end
+end
+
+def fun_l0_n953(x)
+ if (x < 1)
+ fun_l1_n851(x)
+ else
+ fun_l1_n877(x)
+ end
+end
+
+def fun_l0_n954(x)
+ if (x < 1)
+ fun_l1_n415(x)
+ else
+ fun_l1_n379(x)
+ end
+end
+
+def fun_l0_n955(x)
+ if (x < 1)
+ fun_l1_n806(x)
+ else
+ fun_l1_n919(x)
+ end
+end
+
+def fun_l0_n956(x)
+ if (x < 1)
+ fun_l1_n207(x)
+ else
+ fun_l1_n798(x)
+ end
+end
+
+def fun_l0_n957(x)
+ if (x < 1)
+ fun_l1_n269(x)
+ else
+ fun_l1_n416(x)
+ end
+end
+
+def fun_l0_n958(x)
+ if (x < 1)
+ fun_l1_n654(x)
+ else
+ fun_l1_n236(x)
+ end
+end
+
+def fun_l0_n959(x)
+ if (x < 1)
+ fun_l1_n392(x)
+ else
+ fun_l1_n623(x)
+ end
+end
+
+def fun_l0_n960(x)
+ if (x < 1)
+ fun_l1_n889(x)
+ else
+ fun_l1_n279(x)
+ end
+end
+
+def fun_l0_n961(x)
+ if (x < 1)
+ fun_l1_n476(x)
+ else
+ fun_l1_n201(x)
+ end
+end
+
+def fun_l0_n962(x)
+ if (x < 1)
+ fun_l1_n799(x)
+ else
+ fun_l1_n570(x)
+ end
+end
+
+def fun_l0_n963(x)
+ if (x < 1)
+ fun_l1_n802(x)
+ else
+ fun_l1_n114(x)
+ end
+end
+
+def fun_l0_n964(x)
+ if (x < 1)
+ fun_l1_n197(x)
+ else
+ fun_l1_n422(x)
+ end
+end
+
+def fun_l0_n965(x)
+ if (x < 1)
+ fun_l1_n37(x)
+ else
+ fun_l1_n691(x)
+ end
+end
+
+def fun_l0_n966(x)
+ if (x < 1)
+ fun_l1_n775(x)
+ else
+ fun_l1_n854(x)
+ end
+end
+
+def fun_l0_n967(x)
+ if (x < 1)
+ fun_l1_n373(x)
+ else
+ fun_l1_n306(x)
+ end
+end
+
+def fun_l0_n968(x)
+ if (x < 1)
+ fun_l1_n154(x)
+ else
+ fun_l1_n122(x)
+ end
+end
+
+def fun_l0_n969(x)
+ if (x < 1)
+ fun_l1_n497(x)
+ else
+ fun_l1_n456(x)
+ end
+end
+
+def fun_l0_n970(x)
+ if (x < 1)
+ fun_l1_n621(x)
+ else
+ fun_l1_n931(x)
+ end
+end
+
+def fun_l0_n971(x)
+ if (x < 1)
+ fun_l1_n963(x)
+ else
+ fun_l1_n613(x)
+ end
+end
+
+def fun_l0_n972(x)
+ if (x < 1)
+ fun_l1_n613(x)
+ else
+ fun_l1_n508(x)
+ end
+end
+
+def fun_l0_n973(x)
+ if (x < 1)
+ fun_l1_n466(x)
+ else
+ fun_l1_n929(x)
+ end
+end
+
+def fun_l0_n974(x)
+ if (x < 1)
+ fun_l1_n247(x)
+ else
+ fun_l1_n610(x)
+ end
+end
+
+def fun_l0_n975(x)
+ if (x < 1)
+ fun_l1_n674(x)
+ else
+ fun_l1_n609(x)
+ end
+end
+
+def fun_l0_n976(x)
+ if (x < 1)
+ fun_l1_n963(x)
+ else
+ fun_l1_n601(x)
+ end
+end
+
+def fun_l0_n977(x)
+ if (x < 1)
+ fun_l1_n728(x)
+ else
+ fun_l1_n242(x)
+ end
+end
+
+def fun_l0_n978(x)
+ if (x < 1)
+ fun_l1_n515(x)
+ else
+ fun_l1_n113(x)
+ end
+end
+
+def fun_l0_n979(x)
+ if (x < 1)
+ fun_l1_n734(x)
+ else
+ fun_l1_n271(x)
+ end
+end
+
+def fun_l0_n980(x)
+ if (x < 1)
+ fun_l1_n837(x)
+ else
+ fun_l1_n733(x)
+ end
+end
+
+def fun_l0_n981(x)
+ if (x < 1)
+ fun_l1_n326(x)
+ else
+ fun_l1_n213(x)
+ end
+end
+
+def fun_l0_n982(x)
+ if (x < 1)
+ fun_l1_n733(x)
+ else
+ fun_l1_n198(x)
+ end
+end
+
+def fun_l0_n983(x)
+ if (x < 1)
+ fun_l1_n989(x)
+ else
+ fun_l1_n700(x)
+ end
+end
+
+def fun_l0_n984(x)
+ if (x < 1)
+ fun_l1_n266(x)
+ else
+ fun_l1_n348(x)
+ end
+end
+
+def fun_l0_n985(x)
+ if (x < 1)
+ fun_l1_n931(x)
+ else
+ fun_l1_n646(x)
+ end
+end
+
+def fun_l0_n986(x)
+ if (x < 1)
+ fun_l1_n435(x)
+ else
+ fun_l1_n747(x)
+ end
+end
+
+def fun_l0_n987(x)
+ if (x < 1)
+ fun_l1_n474(x)
+ else
+ fun_l1_n638(x)
+ end
+end
+
+def fun_l0_n988(x)
+ if (x < 1)
+ fun_l1_n615(x)
+ else
+ fun_l1_n283(x)
+ end
+end
+
+def fun_l0_n989(x)
+ if (x < 1)
+ fun_l1_n410(x)
+ else
+ fun_l1_n289(x)
+ end
+end
+
+def fun_l0_n990(x)
+ if (x < 1)
+ fun_l1_n633(x)
+ else
+ fun_l1_n77(x)
+ end
+end
+
+def fun_l0_n991(x)
+ if (x < 1)
+ fun_l1_n153(x)
+ else
+ fun_l1_n255(x)
+ end
+end
+
+def fun_l0_n992(x)
+ if (x < 1)
+ fun_l1_n447(x)
+ else
+ fun_l1_n239(x)
+ end
+end
+
+def fun_l0_n993(x)
+ if (x < 1)
+ fun_l1_n837(x)
+ else
+ fun_l1_n582(x)
+ end
+end
+
+def fun_l0_n994(x)
+ if (x < 1)
+ fun_l1_n385(x)
+ else
+ fun_l1_n939(x)
+ end
+end
+
+def fun_l0_n995(x)
+ if (x < 1)
+ fun_l1_n236(x)
+ else
+ fun_l1_n497(x)
+ end
+end
+
+def fun_l0_n996(x)
+ if (x < 1)
+ fun_l1_n63(x)
+ else
+ fun_l1_n721(x)
+ end
+end
+
+def fun_l0_n997(x)
+ if (x < 1)
+ fun_l1_n457(x)
+ else
+ fun_l1_n376(x)
+ end
+end
+
+def fun_l0_n998(x)
+ if (x < 1)
+ fun_l1_n362(x)
+ else
+ fun_l1_n478(x)
+ end
+end
+
+def fun_l0_n999(x)
+ if (x < 1)
+ fun_l1_n554(x)
+ else
+ fun_l1_n422(x)
+ end
+end
+
+def fun_l1_n0(x)
+ if (x < 1)
+ fun_l2_n498(x)
+ else
+ fun_l2_n461(x)
+ end
+end
+
+def fun_l1_n1(x)
+ if (x < 1)
+ fun_l2_n424(x)
+ else
+ fun_l2_n137(x)
+ end
+end
+
+def fun_l1_n2(x)
+ if (x < 1)
+ fun_l2_n325(x)
+ else
+ fun_l2_n95(x)
+ end
+end
+
+def fun_l1_n3(x)
+ if (x < 1)
+ fun_l2_n917(x)
+ else
+ fun_l2_n469(x)
+ end
+end
+
+def fun_l1_n4(x)
+ if (x < 1)
+ fun_l2_n730(x)
+ else
+ fun_l2_n147(x)
+ end
+end
+
+def fun_l1_n5(x)
+ if (x < 1)
+ fun_l2_n796(x)
+ else
+ fun_l2_n907(x)
+ end
+end
+
+def fun_l1_n6(x)
+ if (x < 1)
+ fun_l2_n555(x)
+ else
+ fun_l2_n309(x)
+ end
+end
+
+def fun_l1_n7(x)
+ if (x < 1)
+ fun_l2_n475(x)
+ else
+ fun_l2_n193(x)
+ end
+end
+
+def fun_l1_n8(x)
+ if (x < 1)
+ fun_l2_n317(x)
+ else
+ fun_l2_n284(x)
+ end
+end
+
+def fun_l1_n9(x)
+ if (x < 1)
+ fun_l2_n297(x)
+ else
+ fun_l2_n370(x)
+ end
+end
+
+def fun_l1_n10(x)
+ if (x < 1)
+ fun_l2_n66(x)
+ else
+ fun_l2_n959(x)
+ end
+end
+
+def fun_l1_n11(x)
+ if (x < 1)
+ fun_l2_n833(x)
+ else
+ fun_l2_n250(x)
+ end
+end
+
+def fun_l1_n12(x)
+ if (x < 1)
+ fun_l2_n640(x)
+ else
+ fun_l2_n588(x)
+ end
+end
+
+def fun_l1_n13(x)
+ if (x < 1)
+ fun_l2_n91(x)
+ else
+ fun_l2_n294(x)
+ end
+end
+
+def fun_l1_n14(x)
+ if (x < 1)
+ fun_l2_n166(x)
+ else
+ fun_l2_n943(x)
+ end
+end
+
+def fun_l1_n15(x)
+ if (x < 1)
+ fun_l2_n352(x)
+ else
+ fun_l2_n363(x)
+ end
+end
+
+def fun_l1_n16(x)
+ if (x < 1)
+ fun_l2_n84(x)
+ else
+ fun_l2_n278(x)
+ end
+end
+
+def fun_l1_n17(x)
+ if (x < 1)
+ fun_l2_n308(x)
+ else
+ fun_l2_n341(x)
+ end
+end
+
+def fun_l1_n18(x)
+ if (x < 1)
+ fun_l2_n713(x)
+ else
+ fun_l2_n575(x)
+ end
+end
+
+def fun_l1_n19(x)
+ if (x < 1)
+ fun_l2_n81(x)
+ else
+ fun_l2_n301(x)
+ end
+end
+
+def fun_l1_n20(x)
+ if (x < 1)
+ fun_l2_n516(x)
+ else
+ fun_l2_n164(x)
+ end
+end
+
+def fun_l1_n21(x)
+ if (x < 1)
+ fun_l2_n900(x)
+ else
+ fun_l2_n963(x)
+ end
+end
+
+def fun_l1_n22(x)
+ if (x < 1)
+ fun_l2_n472(x)
+ else
+ fun_l2_n288(x)
+ end
+end
+
+def fun_l1_n23(x)
+ if (x < 1)
+ fun_l2_n587(x)
+ else
+ fun_l2_n515(x)
+ end
+end
+
+def fun_l1_n24(x)
+ if (x < 1)
+ fun_l2_n506(x)
+ else
+ fun_l2_n711(x)
+ end
+end
+
+def fun_l1_n25(x)
+ if (x < 1)
+ fun_l2_n935(x)
+ else
+ fun_l2_n177(x)
+ end
+end
+
+def fun_l1_n26(x)
+ if (x < 1)
+ fun_l2_n485(x)
+ else
+ fun_l2_n368(x)
+ end
+end
+
+def fun_l1_n27(x)
+ if (x < 1)
+ fun_l2_n984(x)
+ else
+ fun_l2_n290(x)
+ end
+end
+
+def fun_l1_n28(x)
+ if (x < 1)
+ fun_l2_n36(x)
+ else
+ fun_l2_n837(x)
+ end
+end
+
+def fun_l1_n29(x)
+ if (x < 1)
+ fun_l2_n752(x)
+ else
+ fun_l2_n311(x)
+ end
+end
+
+def fun_l1_n30(x)
+ if (x < 1)
+ fun_l2_n215(x)
+ else
+ fun_l2_n376(x)
+ end
+end
+
+def fun_l1_n31(x)
+ if (x < 1)
+ fun_l2_n533(x)
+ else
+ fun_l2_n92(x)
+ end
+end
+
+def fun_l1_n32(x)
+ if (x < 1)
+ fun_l2_n386(x)
+ else
+ fun_l2_n283(x)
+ end
+end
+
+def fun_l1_n33(x)
+ if (x < 1)
+ fun_l2_n268(x)
+ else
+ fun_l2_n256(x)
+ end
+end
+
+def fun_l1_n34(x)
+ if (x < 1)
+ fun_l2_n348(x)
+ else
+ fun_l2_n464(x)
+ end
+end
+
+def fun_l1_n35(x)
+ if (x < 1)
+ fun_l2_n25(x)
+ else
+ fun_l2_n33(x)
+ end
+end
+
+def fun_l1_n36(x)
+ if (x < 1)
+ fun_l2_n387(x)
+ else
+ fun_l2_n341(x)
+ end
+end
+
+def fun_l1_n37(x)
+ if (x < 1)
+ fun_l2_n580(x)
+ else
+ fun_l2_n476(x)
+ end
+end
+
+def fun_l1_n38(x)
+ if (x < 1)
+ fun_l2_n33(x)
+ else
+ fun_l2_n33(x)
+ end
+end
+
+def fun_l1_n39(x)
+ if (x < 1)
+ fun_l2_n861(x)
+ else
+ fun_l2_n52(x)
+ end
+end
+
+def fun_l1_n40(x)
+ if (x < 1)
+ fun_l2_n740(x)
+ else
+ fun_l2_n943(x)
+ end
+end
+
+def fun_l1_n41(x)
+ if (x < 1)
+ fun_l2_n956(x)
+ else
+ fun_l2_n159(x)
+ end
+end
+
+def fun_l1_n42(x)
+ if (x < 1)
+ fun_l2_n445(x)
+ else
+ fun_l2_n775(x)
+ end
+end
+
+def fun_l1_n43(x)
+ if (x < 1)
+ fun_l2_n667(x)
+ else
+ fun_l2_n282(x)
+ end
+end
+
+def fun_l1_n44(x)
+ if (x < 1)
+ fun_l2_n185(x)
+ else
+ fun_l2_n210(x)
+ end
+end
+
+def fun_l1_n45(x)
+ if (x < 1)
+ fun_l2_n490(x)
+ else
+ fun_l2_n21(x)
+ end
+end
+
+def fun_l1_n46(x)
+ if (x < 1)
+ fun_l2_n751(x)
+ else
+ fun_l2_n639(x)
+ end
+end
+
+def fun_l1_n47(x)
+ if (x < 1)
+ fun_l2_n431(x)
+ else
+ fun_l2_n917(x)
+ end
+end
+
+def fun_l1_n48(x)
+ if (x < 1)
+ fun_l2_n187(x)
+ else
+ fun_l2_n170(x)
+ end
+end
+
+def fun_l1_n49(x)
+ if (x < 1)
+ fun_l2_n780(x)
+ else
+ fun_l2_n77(x)
+ end
+end
+
+def fun_l1_n50(x)
+ if (x < 1)
+ fun_l2_n546(x)
+ else
+ fun_l2_n759(x)
+ end
+end
+
+def fun_l1_n51(x)
+ if (x < 1)
+ fun_l2_n453(x)
+ else
+ fun_l2_n951(x)
+ end
+end
+
+def fun_l1_n52(x)
+ if (x < 1)
+ fun_l2_n989(x)
+ else
+ fun_l2_n716(x)
+ end
+end
+
+def fun_l1_n53(x)
+ if (x < 1)
+ fun_l2_n652(x)
+ else
+ fun_l2_n36(x)
+ end
+end
+
+def fun_l1_n54(x)
+ if (x < 1)
+ fun_l2_n187(x)
+ else
+ fun_l2_n760(x)
+ end
+end
+
+def fun_l1_n55(x)
+ if (x < 1)
+ fun_l2_n706(x)
+ else
+ fun_l2_n927(x)
+ end
+end
+
+def fun_l1_n56(x)
+ if (x < 1)
+ fun_l2_n666(x)
+ else
+ fun_l2_n295(x)
+ end
+end
+
+def fun_l1_n57(x)
+ if (x < 1)
+ fun_l2_n424(x)
+ else
+ fun_l2_n447(x)
+ end
+end
+
+def fun_l1_n58(x)
+ if (x < 1)
+ fun_l2_n408(x)
+ else
+ fun_l2_n337(x)
+ end
+end
+
+def fun_l1_n59(x)
+ if (x < 1)
+ fun_l2_n567(x)
+ else
+ fun_l2_n765(x)
+ end
+end
+
+def fun_l1_n60(x)
+ if (x < 1)
+ fun_l2_n241(x)
+ else
+ fun_l2_n701(x)
+ end
+end
+
+def fun_l1_n61(x)
+ if (x < 1)
+ fun_l2_n831(x)
+ else
+ fun_l2_n382(x)
+ end
+end
+
+def fun_l1_n62(x)
+ if (x < 1)
+ fun_l2_n634(x)
+ else
+ fun_l2_n908(x)
+ end
+end
+
+def fun_l1_n63(x)
+ if (x < 1)
+ fun_l2_n696(x)
+ else
+ fun_l2_n48(x)
+ end
+end
+
+def fun_l1_n64(x)
+ if (x < 1)
+ fun_l2_n528(x)
+ else
+ fun_l2_n110(x)
+ end
+end
+
+def fun_l1_n65(x)
+ if (x < 1)
+ fun_l2_n767(x)
+ else
+ fun_l2_n973(x)
+ end
+end
+
+def fun_l1_n66(x)
+ if (x < 1)
+ fun_l2_n963(x)
+ else
+ fun_l2_n673(x)
+ end
+end
+
+def fun_l1_n67(x)
+ if (x < 1)
+ fun_l2_n927(x)
+ else
+ fun_l2_n309(x)
+ end
+end
+
+def fun_l1_n68(x)
+ if (x < 1)
+ fun_l2_n851(x)
+ else
+ fun_l2_n160(x)
+ end
+end
+
+def fun_l1_n69(x)
+ if (x < 1)
+ fun_l2_n575(x)
+ else
+ fun_l2_n800(x)
+ end
+end
+
+def fun_l1_n70(x)
+ if (x < 1)
+ fun_l2_n396(x)
+ else
+ fun_l2_n382(x)
+ end
+end
+
+def fun_l1_n71(x)
+ if (x < 1)
+ fun_l2_n508(x)
+ else
+ fun_l2_n763(x)
+ end
+end
+
+def fun_l1_n72(x)
+ if (x < 1)
+ fun_l2_n360(x)
+ else
+ fun_l2_n848(x)
+ end
+end
+
+def fun_l1_n73(x)
+ if (x < 1)
+ fun_l2_n878(x)
+ else
+ fun_l2_n83(x)
+ end
+end
+
+def fun_l1_n74(x)
+ if (x < 1)
+ fun_l2_n573(x)
+ else
+ fun_l2_n284(x)
+ end
+end
+
+def fun_l1_n75(x)
+ if (x < 1)
+ fun_l2_n999(x)
+ else
+ fun_l2_n954(x)
+ end
+end
+
+def fun_l1_n76(x)
+ if (x < 1)
+ fun_l2_n182(x)
+ else
+ fun_l2_n997(x)
+ end
+end
+
+def fun_l1_n77(x)
+ if (x < 1)
+ fun_l2_n802(x)
+ else
+ fun_l2_n409(x)
+ end
+end
+
+def fun_l1_n78(x)
+ if (x < 1)
+ fun_l2_n163(x)
+ else
+ fun_l2_n417(x)
+ end
+end
+
+def fun_l1_n79(x)
+ if (x < 1)
+ fun_l2_n328(x)
+ else
+ fun_l2_n688(x)
+ end
+end
+
+def fun_l1_n80(x)
+ if (x < 1)
+ fun_l2_n699(x)
+ else
+ fun_l2_n356(x)
+ end
+end
+
+def fun_l1_n81(x)
+ if (x < 1)
+ fun_l2_n44(x)
+ else
+ fun_l2_n302(x)
+ end
+end
+
+def fun_l1_n82(x)
+ if (x < 1)
+ fun_l2_n597(x)
+ else
+ fun_l2_n892(x)
+ end
+end
+
+def fun_l1_n83(x)
+ if (x < 1)
+ fun_l2_n494(x)
+ else
+ fun_l2_n547(x)
+ end
+end
+
+def fun_l1_n84(x)
+ if (x < 1)
+ fun_l2_n631(x)
+ else
+ fun_l2_n922(x)
+ end
+end
+
+def fun_l1_n85(x)
+ if (x < 1)
+ fun_l2_n797(x)
+ else
+ fun_l2_n874(x)
+ end
+end
+
+def fun_l1_n86(x)
+ if (x < 1)
+ fun_l2_n209(x)
+ else
+ fun_l2_n365(x)
+ end
+end
+
+def fun_l1_n87(x)
+ if (x < 1)
+ fun_l2_n516(x)
+ else
+ fun_l2_n371(x)
+ end
+end
+
+def fun_l1_n88(x)
+ if (x < 1)
+ fun_l2_n654(x)
+ else
+ fun_l2_n88(x)
+ end
+end
+
+def fun_l1_n89(x)
+ if (x < 1)
+ fun_l2_n70(x)
+ else
+ fun_l2_n521(x)
+ end
+end
+
+def fun_l1_n90(x)
+ if (x < 1)
+ fun_l2_n666(x)
+ else
+ fun_l2_n749(x)
+ end
+end
+
+def fun_l1_n91(x)
+ if (x < 1)
+ fun_l2_n504(x)
+ else
+ fun_l2_n339(x)
+ end
+end
+
+def fun_l1_n92(x)
+ if (x < 1)
+ fun_l2_n734(x)
+ else
+ fun_l2_n277(x)
+ end
+end
+
+def fun_l1_n93(x)
+ if (x < 1)
+ fun_l2_n300(x)
+ else
+ fun_l2_n826(x)
+ end
+end
+
+def fun_l1_n94(x)
+ if (x < 1)
+ fun_l2_n733(x)
+ else
+ fun_l2_n560(x)
+ end
+end
+
+def fun_l1_n95(x)
+ if (x < 1)
+ fun_l2_n834(x)
+ else
+ fun_l2_n644(x)
+ end
+end
+
+def fun_l1_n96(x)
+ if (x < 1)
+ fun_l2_n183(x)
+ else
+ fun_l2_n238(x)
+ end
+end
+
+def fun_l1_n97(x)
+ if (x < 1)
+ fun_l2_n372(x)
+ else
+ fun_l2_n753(x)
+ end
+end
+
+def fun_l1_n98(x)
+ if (x < 1)
+ fun_l2_n208(x)
+ else
+ fun_l2_n543(x)
+ end
+end
+
+def fun_l1_n99(x)
+ if (x < 1)
+ fun_l2_n38(x)
+ else
+ fun_l2_n974(x)
+ end
+end
+
+def fun_l1_n100(x)
+ if (x < 1)
+ fun_l2_n620(x)
+ else
+ fun_l2_n503(x)
+ end
+end
+
+def fun_l1_n101(x)
+ if (x < 1)
+ fun_l2_n248(x)
+ else
+ fun_l2_n189(x)
+ end
+end
+
+def fun_l1_n102(x)
+ if (x < 1)
+ fun_l2_n489(x)
+ else
+ fun_l2_n390(x)
+ end
+end
+
+def fun_l1_n103(x)
+ if (x < 1)
+ fun_l2_n452(x)
+ else
+ fun_l2_n22(x)
+ end
+end
+
+def fun_l1_n104(x)
+ if (x < 1)
+ fun_l2_n542(x)
+ else
+ fun_l2_n135(x)
+ end
+end
+
+def fun_l1_n105(x)
+ if (x < 1)
+ fun_l2_n988(x)
+ else
+ fun_l2_n118(x)
+ end
+end
+
+def fun_l1_n106(x)
+ if (x < 1)
+ fun_l2_n817(x)
+ else
+ fun_l2_n534(x)
+ end
+end
+
+def fun_l1_n107(x)
+ if (x < 1)
+ fun_l2_n812(x)
+ else
+ fun_l2_n206(x)
+ end
+end
+
+def fun_l1_n108(x)
+ if (x < 1)
+ fun_l2_n514(x)
+ else
+ fun_l2_n300(x)
+ end
+end
+
+def fun_l1_n109(x)
+ if (x < 1)
+ fun_l2_n482(x)
+ else
+ fun_l2_n376(x)
+ end
+end
+
+def fun_l1_n110(x)
+ if (x < 1)
+ fun_l2_n571(x)
+ else
+ fun_l2_n758(x)
+ end
+end
+
+def fun_l1_n111(x)
+ if (x < 1)
+ fun_l2_n971(x)
+ else
+ fun_l2_n811(x)
+ end
+end
+
+def fun_l1_n112(x)
+ if (x < 1)
+ fun_l2_n23(x)
+ else
+ fun_l2_n844(x)
+ end
+end
+
+def fun_l1_n113(x)
+ if (x < 1)
+ fun_l2_n865(x)
+ else
+ fun_l2_n149(x)
+ end
+end
+
+def fun_l1_n114(x)
+ if (x < 1)
+ fun_l2_n930(x)
+ else
+ fun_l2_n327(x)
+ end
+end
+
+def fun_l1_n115(x)
+ if (x < 1)
+ fun_l2_n67(x)
+ else
+ fun_l2_n442(x)
+ end
+end
+
+def fun_l1_n116(x)
+ if (x < 1)
+ fun_l2_n278(x)
+ else
+ fun_l2_n653(x)
+ end
+end
+
+def fun_l1_n117(x)
+ if (x < 1)
+ fun_l2_n457(x)
+ else
+ fun_l2_n179(x)
+ end
+end
+
+def fun_l1_n118(x)
+ if (x < 1)
+ fun_l2_n384(x)
+ else
+ fun_l2_n594(x)
+ end
+end
+
+def fun_l1_n119(x)
+ if (x < 1)
+ fun_l2_n361(x)
+ else
+ fun_l2_n770(x)
+ end
+end
+
+def fun_l1_n120(x)
+ if (x < 1)
+ fun_l2_n24(x)
+ else
+ fun_l2_n269(x)
+ end
+end
+
+def fun_l1_n121(x)
+ if (x < 1)
+ fun_l2_n57(x)
+ else
+ fun_l2_n2(x)
+ end
+end
+
+def fun_l1_n122(x)
+ if (x < 1)
+ fun_l2_n421(x)
+ else
+ fun_l2_n339(x)
+ end
+end
+
+def fun_l1_n123(x)
+ if (x < 1)
+ fun_l2_n623(x)
+ else
+ fun_l2_n985(x)
+ end
+end
+
+def fun_l1_n124(x)
+ if (x < 1)
+ fun_l2_n609(x)
+ else
+ fun_l2_n530(x)
+ end
+end
+
+def fun_l1_n125(x)
+ if (x < 1)
+ fun_l2_n565(x)
+ else
+ fun_l2_n155(x)
+ end
+end
+
+def fun_l1_n126(x)
+ if (x < 1)
+ fun_l2_n135(x)
+ else
+ fun_l2_n971(x)
+ end
+end
+
+def fun_l1_n127(x)
+ if (x < 1)
+ fun_l2_n691(x)
+ else
+ fun_l2_n503(x)
+ end
+end
+
+def fun_l1_n128(x)
+ if (x < 1)
+ fun_l2_n555(x)
+ else
+ fun_l2_n67(x)
+ end
+end
+
+def fun_l1_n129(x)
+ if (x < 1)
+ fun_l2_n95(x)
+ else
+ fun_l2_n192(x)
+ end
+end
+
+def fun_l1_n130(x)
+ if (x < 1)
+ fun_l2_n432(x)
+ else
+ fun_l2_n771(x)
+ end
+end
+
+def fun_l1_n131(x)
+ if (x < 1)
+ fun_l2_n993(x)
+ else
+ fun_l2_n539(x)
+ end
+end
+
+def fun_l1_n132(x)
+ if (x < 1)
+ fun_l2_n809(x)
+ else
+ fun_l2_n902(x)
+ end
+end
+
+def fun_l1_n133(x)
+ if (x < 1)
+ fun_l2_n95(x)
+ else
+ fun_l2_n928(x)
+ end
+end
+
+def fun_l1_n134(x)
+ if (x < 1)
+ fun_l2_n781(x)
+ else
+ fun_l2_n832(x)
+ end
+end
+
+def fun_l1_n135(x)
+ if (x < 1)
+ fun_l2_n231(x)
+ else
+ fun_l2_n392(x)
+ end
+end
+
+def fun_l1_n136(x)
+ if (x < 1)
+ fun_l2_n102(x)
+ else
+ fun_l2_n449(x)
+ end
+end
+
+def fun_l1_n137(x)
+ if (x < 1)
+ fun_l2_n196(x)
+ else
+ fun_l2_n909(x)
+ end
+end
+
+def fun_l1_n138(x)
+ if (x < 1)
+ fun_l2_n449(x)
+ else
+ fun_l2_n190(x)
+ end
+end
+
+def fun_l1_n139(x)
+ if (x < 1)
+ fun_l2_n638(x)
+ else
+ fun_l2_n149(x)
+ end
+end
+
+def fun_l1_n140(x)
+ if (x < 1)
+ fun_l2_n523(x)
+ else
+ fun_l2_n297(x)
+ end
+end
+
+def fun_l1_n141(x)
+ if (x < 1)
+ fun_l2_n476(x)
+ else
+ fun_l2_n161(x)
+ end
+end
+
+def fun_l1_n142(x)
+ if (x < 1)
+ fun_l2_n893(x)
+ else
+ fun_l2_n686(x)
+ end
+end
+
+def fun_l1_n143(x)
+ if (x < 1)
+ fun_l2_n958(x)
+ else
+ fun_l2_n899(x)
+ end
+end
+
+def fun_l1_n144(x)
+ if (x < 1)
+ fun_l2_n104(x)
+ else
+ fun_l2_n912(x)
+ end
+end
+
+def fun_l1_n145(x)
+ if (x < 1)
+ fun_l2_n332(x)
+ else
+ fun_l2_n579(x)
+ end
+end
+
+def fun_l1_n146(x)
+ if (x < 1)
+ fun_l2_n40(x)
+ else
+ fun_l2_n468(x)
+ end
+end
+
+def fun_l1_n147(x)
+ if (x < 1)
+ fun_l2_n771(x)
+ else
+ fun_l2_n314(x)
+ end
+end
+
+def fun_l1_n148(x)
+ if (x < 1)
+ fun_l2_n340(x)
+ else
+ fun_l2_n203(x)
+ end
+end
+
+def fun_l1_n149(x)
+ if (x < 1)
+ fun_l2_n952(x)
+ else
+ fun_l2_n265(x)
+ end
+end
+
+def fun_l1_n150(x)
+ if (x < 1)
+ fun_l2_n11(x)
+ else
+ fun_l2_n303(x)
+ end
+end
+
+def fun_l1_n151(x)
+ if (x < 1)
+ fun_l2_n394(x)
+ else
+ fun_l2_n317(x)
+ end
+end
+
+def fun_l1_n152(x)
+ if (x < 1)
+ fun_l2_n140(x)
+ else
+ fun_l2_n906(x)
+ end
+end
+
+def fun_l1_n153(x)
+ if (x < 1)
+ fun_l2_n75(x)
+ else
+ fun_l2_n485(x)
+ end
+end
+
+def fun_l1_n154(x)
+ if (x < 1)
+ fun_l2_n842(x)
+ else
+ fun_l2_n370(x)
+ end
+end
+
+def fun_l1_n155(x)
+ if (x < 1)
+ fun_l2_n346(x)
+ else
+ fun_l2_n833(x)
+ end
+end
+
+def fun_l1_n156(x)
+ if (x < 1)
+ fun_l2_n433(x)
+ else
+ fun_l2_n373(x)
+ end
+end
+
+def fun_l1_n157(x)
+ if (x < 1)
+ fun_l2_n978(x)
+ else
+ fun_l2_n99(x)
+ end
+end
+
+def fun_l1_n158(x)
+ if (x < 1)
+ fun_l2_n540(x)
+ else
+ fun_l2_n987(x)
+ end
+end
+
+def fun_l1_n159(x)
+ if (x < 1)
+ fun_l2_n785(x)
+ else
+ fun_l2_n478(x)
+ end
+end
+
+def fun_l1_n160(x)
+ if (x < 1)
+ fun_l2_n282(x)
+ else
+ fun_l2_n222(x)
+ end
+end
+
+def fun_l1_n161(x)
+ if (x < 1)
+ fun_l2_n29(x)
+ else
+ fun_l2_n946(x)
+ end
+end
+
+def fun_l1_n162(x)
+ if (x < 1)
+ fun_l2_n314(x)
+ else
+ fun_l2_n758(x)
+ end
+end
+
+def fun_l1_n163(x)
+ if (x < 1)
+ fun_l2_n861(x)
+ else
+ fun_l2_n799(x)
+ end
+end
+
+def fun_l1_n164(x)
+ if (x < 1)
+ fun_l2_n403(x)
+ else
+ fun_l2_n413(x)
+ end
+end
+
+def fun_l1_n165(x)
+ if (x < 1)
+ fun_l2_n160(x)
+ else
+ fun_l2_n794(x)
+ end
+end
+
+def fun_l1_n166(x)
+ if (x < 1)
+ fun_l2_n114(x)
+ else
+ fun_l2_n238(x)
+ end
+end
+
+def fun_l1_n167(x)
+ if (x < 1)
+ fun_l2_n806(x)
+ else
+ fun_l2_n233(x)
+ end
+end
+
+def fun_l1_n168(x)
+ if (x < 1)
+ fun_l2_n871(x)
+ else
+ fun_l2_n53(x)
+ end
+end
+
+def fun_l1_n169(x)
+ if (x < 1)
+ fun_l2_n644(x)
+ else
+ fun_l2_n503(x)
+ end
+end
+
+def fun_l1_n170(x)
+ if (x < 1)
+ fun_l2_n172(x)
+ else
+ fun_l2_n289(x)
+ end
+end
+
+def fun_l1_n171(x)
+ if (x < 1)
+ fun_l2_n920(x)
+ else
+ fun_l2_n851(x)
+ end
+end
+
+def fun_l1_n172(x)
+ if (x < 1)
+ fun_l2_n552(x)
+ else
+ fun_l2_n822(x)
+ end
+end
+
+def fun_l1_n173(x)
+ if (x < 1)
+ fun_l2_n747(x)
+ else
+ fun_l2_n265(x)
+ end
+end
+
+def fun_l1_n174(x)
+ if (x < 1)
+ fun_l2_n287(x)
+ else
+ fun_l2_n762(x)
+ end
+end
+
+def fun_l1_n175(x)
+ if (x < 1)
+ fun_l2_n627(x)
+ else
+ fun_l2_n951(x)
+ end
+end
+
+def fun_l1_n176(x)
+ if (x < 1)
+ fun_l2_n459(x)
+ else
+ fun_l2_n962(x)
+ end
+end
+
+def fun_l1_n177(x)
+ if (x < 1)
+ fun_l2_n214(x)
+ else
+ fun_l2_n145(x)
+ end
+end
+
+def fun_l1_n178(x)
+ if (x < 1)
+ fun_l2_n620(x)
+ else
+ fun_l2_n995(x)
+ end
+end
+
+def fun_l1_n179(x)
+ if (x < 1)
+ fun_l2_n136(x)
+ else
+ fun_l2_n283(x)
+ end
+end
+
+def fun_l1_n180(x)
+ if (x < 1)
+ fun_l2_n377(x)
+ else
+ fun_l2_n672(x)
+ end
+end
+
+def fun_l1_n181(x)
+ if (x < 1)
+ fun_l2_n218(x)
+ else
+ fun_l2_n434(x)
+ end
+end
+
+def fun_l1_n182(x)
+ if (x < 1)
+ fun_l2_n522(x)
+ else
+ fun_l2_n525(x)
+ end
+end
+
+def fun_l1_n183(x)
+ if (x < 1)
+ fun_l2_n648(x)
+ else
+ fun_l2_n725(x)
+ end
+end
+
+def fun_l1_n184(x)
+ if (x < 1)
+ fun_l2_n579(x)
+ else
+ fun_l2_n974(x)
+ end
+end
+
+def fun_l1_n185(x)
+ if (x < 1)
+ fun_l2_n10(x)
+ else
+ fun_l2_n514(x)
+ end
+end
+
+def fun_l1_n186(x)
+ if (x < 1)
+ fun_l2_n829(x)
+ else
+ fun_l2_n754(x)
+ end
+end
+
+def fun_l1_n187(x)
+ if (x < 1)
+ fun_l2_n380(x)
+ else
+ fun_l2_n401(x)
+ end
+end
+
+def fun_l1_n188(x)
+ if (x < 1)
+ fun_l2_n839(x)
+ else
+ fun_l2_n453(x)
+ end
+end
+
+def fun_l1_n189(x)
+ if (x < 1)
+ fun_l2_n553(x)
+ else
+ fun_l2_n553(x)
+ end
+end
+
+def fun_l1_n190(x)
+ if (x < 1)
+ fun_l2_n972(x)
+ else
+ fun_l2_n187(x)
+ end
+end
+
+def fun_l1_n191(x)
+ if (x < 1)
+ fun_l2_n275(x)
+ else
+ fun_l2_n11(x)
+ end
+end
+
+def fun_l1_n192(x)
+ if (x < 1)
+ fun_l2_n1(x)
+ else
+ fun_l2_n927(x)
+ end
+end
+
+def fun_l1_n193(x)
+ if (x < 1)
+ fun_l2_n569(x)
+ else
+ fun_l2_n557(x)
+ end
+end
+
+def fun_l1_n194(x)
+ if (x < 1)
+ fun_l2_n380(x)
+ else
+ fun_l2_n187(x)
+ end
+end
+
+def fun_l1_n195(x)
+ if (x < 1)
+ fun_l2_n297(x)
+ else
+ fun_l2_n813(x)
+ end
+end
+
+def fun_l1_n196(x)
+ if (x < 1)
+ fun_l2_n565(x)
+ else
+ fun_l2_n514(x)
+ end
+end
+
+def fun_l1_n197(x)
+ if (x < 1)
+ fun_l2_n473(x)
+ else
+ fun_l2_n64(x)
+ end
+end
+
+def fun_l1_n198(x)
+ if (x < 1)
+ fun_l2_n182(x)
+ else
+ fun_l2_n363(x)
+ end
+end
+
+def fun_l1_n199(x)
+ if (x < 1)
+ fun_l2_n660(x)
+ else
+ fun_l2_n506(x)
+ end
+end
+
+def fun_l1_n200(x)
+ if (x < 1)
+ fun_l2_n834(x)
+ else
+ fun_l2_n348(x)
+ end
+end
+
+def fun_l1_n201(x)
+ if (x < 1)
+ fun_l2_n403(x)
+ else
+ fun_l2_n432(x)
+ end
+end
+
+def fun_l1_n202(x)
+ if (x < 1)
+ fun_l2_n115(x)
+ else
+ fun_l2_n145(x)
+ end
+end
+
+def fun_l1_n203(x)
+ if (x < 1)
+ fun_l2_n637(x)
+ else
+ fun_l2_n4(x)
+ end
+end
+
+def fun_l1_n204(x)
+ if (x < 1)
+ fun_l2_n951(x)
+ else
+ fun_l2_n753(x)
+ end
+end
+
+def fun_l1_n205(x)
+ if (x < 1)
+ fun_l2_n703(x)
+ else
+ fun_l2_n563(x)
+ end
+end
+
+def fun_l1_n206(x)
+ if (x < 1)
+ fun_l2_n614(x)
+ else
+ fun_l2_n563(x)
+ end
+end
+
+def fun_l1_n207(x)
+ if (x < 1)
+ fun_l2_n210(x)
+ else
+ fun_l2_n139(x)
+ end
+end
+
+def fun_l1_n208(x)
+ if (x < 1)
+ fun_l2_n471(x)
+ else
+ fun_l2_n346(x)
+ end
+end
+
+def fun_l1_n209(x)
+ if (x < 1)
+ fun_l2_n922(x)
+ else
+ fun_l2_n54(x)
+ end
+end
+
+def fun_l1_n210(x)
+ if (x < 1)
+ fun_l2_n494(x)
+ else
+ fun_l2_n41(x)
+ end
+end
+
+def fun_l1_n211(x)
+ if (x < 1)
+ fun_l2_n87(x)
+ else
+ fun_l2_n190(x)
+ end
+end
+
+def fun_l1_n212(x)
+ if (x < 1)
+ fun_l2_n458(x)
+ else
+ fun_l2_n885(x)
+ end
+end
+
+def fun_l1_n213(x)
+ if (x < 1)
+ fun_l2_n48(x)
+ else
+ fun_l2_n225(x)
+ end
+end
+
+def fun_l1_n214(x)
+ if (x < 1)
+ fun_l2_n706(x)
+ else
+ fun_l2_n694(x)
+ end
+end
+
+def fun_l1_n215(x)
+ if (x < 1)
+ fun_l2_n116(x)
+ else
+ fun_l2_n233(x)
+ end
+end
+
+def fun_l1_n216(x)
+ if (x < 1)
+ fun_l2_n279(x)
+ else
+ fun_l2_n857(x)
+ end
+end
+
+def fun_l1_n217(x)
+ if (x < 1)
+ fun_l2_n643(x)
+ else
+ fun_l2_n289(x)
+ end
+end
+
+def fun_l1_n218(x)
+ if (x < 1)
+ fun_l2_n535(x)
+ else
+ fun_l2_n833(x)
+ end
+end
+
+def fun_l1_n219(x)
+ if (x < 1)
+ fun_l2_n478(x)
+ else
+ fun_l2_n793(x)
+ end
+end
+
+def fun_l1_n220(x)
+ if (x < 1)
+ fun_l2_n57(x)
+ else
+ fun_l2_n64(x)
+ end
+end
+
+def fun_l1_n221(x)
+ if (x < 1)
+ fun_l2_n36(x)
+ else
+ fun_l2_n74(x)
+ end
+end
+
+def fun_l1_n222(x)
+ if (x < 1)
+ fun_l2_n438(x)
+ else
+ fun_l2_n616(x)
+ end
+end
+
+def fun_l1_n223(x)
+ if (x < 1)
+ fun_l2_n900(x)
+ else
+ fun_l2_n744(x)
+ end
+end
+
+def fun_l1_n224(x)
+ if (x < 1)
+ fun_l2_n780(x)
+ else
+ fun_l2_n213(x)
+ end
+end
+
+def fun_l1_n225(x)
+ if (x < 1)
+ fun_l2_n916(x)
+ else
+ fun_l2_n471(x)
+ end
+end
+
+def fun_l1_n226(x)
+ if (x < 1)
+ fun_l2_n236(x)
+ else
+ fun_l2_n980(x)
+ end
+end
+
+def fun_l1_n227(x)
+ if (x < 1)
+ fun_l2_n28(x)
+ else
+ fun_l2_n291(x)
+ end
+end
+
+def fun_l1_n228(x)
+ if (x < 1)
+ fun_l2_n35(x)
+ else
+ fun_l2_n353(x)
+ end
+end
+
+def fun_l1_n229(x)
+ if (x < 1)
+ fun_l2_n404(x)
+ else
+ fun_l2_n254(x)
+ end
+end
+
+def fun_l1_n230(x)
+ if (x < 1)
+ fun_l2_n641(x)
+ else
+ fun_l2_n464(x)
+ end
+end
+
+def fun_l1_n231(x)
+ if (x < 1)
+ fun_l2_n592(x)
+ else
+ fun_l2_n646(x)
+ end
+end
+
+def fun_l1_n232(x)
+ if (x < 1)
+ fun_l2_n162(x)
+ else
+ fun_l2_n215(x)
+ end
+end
+
+def fun_l1_n233(x)
+ if (x < 1)
+ fun_l2_n219(x)
+ else
+ fun_l2_n772(x)
+ end
+end
+
+def fun_l1_n234(x)
+ if (x < 1)
+ fun_l2_n304(x)
+ else
+ fun_l2_n963(x)
+ end
+end
+
+def fun_l1_n235(x)
+ if (x < 1)
+ fun_l2_n610(x)
+ else
+ fun_l2_n716(x)
+ end
+end
+
+def fun_l1_n236(x)
+ if (x < 1)
+ fun_l2_n151(x)
+ else
+ fun_l2_n498(x)
+ end
+end
+
+def fun_l1_n237(x)
+ if (x < 1)
+ fun_l2_n288(x)
+ else
+ fun_l2_n261(x)
+ end
+end
+
+def fun_l1_n238(x)
+ if (x < 1)
+ fun_l2_n139(x)
+ else
+ fun_l2_n18(x)
+ end
+end
+
+def fun_l1_n239(x)
+ if (x < 1)
+ fun_l2_n559(x)
+ else
+ fun_l2_n148(x)
+ end
+end
+
+def fun_l1_n240(x)
+ if (x < 1)
+ fun_l2_n520(x)
+ else
+ fun_l2_n250(x)
+ end
+end
+
+def fun_l1_n241(x)
+ if (x < 1)
+ fun_l2_n42(x)
+ else
+ fun_l2_n196(x)
+ end
+end
+
+def fun_l1_n242(x)
+ if (x < 1)
+ fun_l2_n16(x)
+ else
+ fun_l2_n540(x)
+ end
+end
+
+def fun_l1_n243(x)
+ if (x < 1)
+ fun_l2_n539(x)
+ else
+ fun_l2_n890(x)
+ end
+end
+
+def fun_l1_n244(x)
+ if (x < 1)
+ fun_l2_n559(x)
+ else
+ fun_l2_n423(x)
+ end
+end
+
+def fun_l1_n245(x)
+ if (x < 1)
+ fun_l2_n110(x)
+ else
+ fun_l2_n711(x)
+ end
+end
+
+def fun_l1_n246(x)
+ if (x < 1)
+ fun_l2_n151(x)
+ else
+ fun_l2_n407(x)
+ end
+end
+
+def fun_l1_n247(x)
+ if (x < 1)
+ fun_l2_n118(x)
+ else
+ fun_l2_n209(x)
+ end
+end
+
+def fun_l1_n248(x)
+ if (x < 1)
+ fun_l2_n764(x)
+ else
+ fun_l2_n932(x)
+ end
+end
+
+def fun_l1_n249(x)
+ if (x < 1)
+ fun_l2_n991(x)
+ else
+ fun_l2_n828(x)
+ end
+end
+
+def fun_l1_n250(x)
+ if (x < 1)
+ fun_l2_n354(x)
+ else
+ fun_l2_n53(x)
+ end
+end
+
+def fun_l1_n251(x)
+ if (x < 1)
+ fun_l2_n63(x)
+ else
+ fun_l2_n292(x)
+ end
+end
+
+def fun_l1_n252(x)
+ if (x < 1)
+ fun_l2_n874(x)
+ else
+ fun_l2_n544(x)
+ end
+end
+
+def fun_l1_n253(x)
+ if (x < 1)
+ fun_l2_n336(x)
+ else
+ fun_l2_n57(x)
+ end
+end
+
+def fun_l1_n254(x)
+ if (x < 1)
+ fun_l2_n302(x)
+ else
+ fun_l2_n90(x)
+ end
+end
+
+def fun_l1_n255(x)
+ if (x < 1)
+ fun_l2_n122(x)
+ else
+ fun_l2_n888(x)
+ end
+end
+
+def fun_l1_n256(x)
+ if (x < 1)
+ fun_l2_n326(x)
+ else
+ fun_l2_n616(x)
+ end
+end
+
+def fun_l1_n257(x)
+ if (x < 1)
+ fun_l2_n77(x)
+ else
+ fun_l2_n622(x)
+ end
+end
+
+def fun_l1_n258(x)
+ if (x < 1)
+ fun_l2_n785(x)
+ else
+ fun_l2_n229(x)
+ end
+end
+
+def fun_l1_n259(x)
+ if (x < 1)
+ fun_l2_n504(x)
+ else
+ fun_l2_n766(x)
+ end
+end
+
+def fun_l1_n260(x)
+ if (x < 1)
+ fun_l2_n857(x)
+ else
+ fun_l2_n823(x)
+ end
+end
+
+def fun_l1_n261(x)
+ if (x < 1)
+ fun_l2_n72(x)
+ else
+ fun_l2_n875(x)
+ end
+end
+
+def fun_l1_n262(x)
+ if (x < 1)
+ fun_l2_n215(x)
+ else
+ fun_l2_n549(x)
+ end
+end
+
+def fun_l1_n263(x)
+ if (x < 1)
+ fun_l2_n232(x)
+ else
+ fun_l2_n96(x)
+ end
+end
+
+def fun_l1_n264(x)
+ if (x < 1)
+ fun_l2_n183(x)
+ else
+ fun_l2_n351(x)
+ end
+end
+
+def fun_l1_n265(x)
+ if (x < 1)
+ fun_l2_n906(x)
+ else
+ fun_l2_n154(x)
+ end
+end
+
+def fun_l1_n266(x)
+ if (x < 1)
+ fun_l2_n234(x)
+ else
+ fun_l2_n547(x)
+ end
+end
+
+def fun_l1_n267(x)
+ if (x < 1)
+ fun_l2_n882(x)
+ else
+ fun_l2_n802(x)
+ end
+end
+
+def fun_l1_n268(x)
+ if (x < 1)
+ fun_l2_n844(x)
+ else
+ fun_l2_n430(x)
+ end
+end
+
+def fun_l1_n269(x)
+ if (x < 1)
+ fun_l2_n781(x)
+ else
+ fun_l2_n738(x)
+ end
+end
+
+def fun_l1_n270(x)
+ if (x < 1)
+ fun_l2_n88(x)
+ else
+ fun_l2_n439(x)
+ end
+end
+
+def fun_l1_n271(x)
+ if (x < 1)
+ fun_l2_n334(x)
+ else
+ fun_l2_n508(x)
+ end
+end
+
+def fun_l1_n272(x)
+ if (x < 1)
+ fun_l2_n871(x)
+ else
+ fun_l2_n562(x)
+ end
+end
+
+def fun_l1_n273(x)
+ if (x < 1)
+ fun_l2_n328(x)
+ else
+ fun_l2_n356(x)
+ end
+end
+
+def fun_l1_n274(x)
+ if (x < 1)
+ fun_l2_n654(x)
+ else
+ fun_l2_n511(x)
+ end
+end
+
+def fun_l1_n275(x)
+ if (x < 1)
+ fun_l2_n309(x)
+ else
+ fun_l2_n840(x)
+ end
+end
+
+def fun_l1_n276(x)
+ if (x < 1)
+ fun_l2_n729(x)
+ else
+ fun_l2_n72(x)
+ end
+end
+
+def fun_l1_n277(x)
+ if (x < 1)
+ fun_l2_n993(x)
+ else
+ fun_l2_n858(x)
+ end
+end
+
+def fun_l1_n278(x)
+ if (x < 1)
+ fun_l2_n664(x)
+ else
+ fun_l2_n50(x)
+ end
+end
+
+def fun_l1_n279(x)
+ if (x < 1)
+ fun_l2_n225(x)
+ else
+ fun_l2_n403(x)
+ end
+end
+
+def fun_l1_n280(x)
+ if (x < 1)
+ fun_l2_n780(x)
+ else
+ fun_l2_n396(x)
+ end
+end
+
+def fun_l1_n281(x)
+ if (x < 1)
+ fun_l2_n114(x)
+ else
+ fun_l2_n114(x)
+ end
+end
+
+def fun_l1_n282(x)
+ if (x < 1)
+ fun_l2_n568(x)
+ else
+ fun_l2_n610(x)
+ end
+end
+
+def fun_l1_n283(x)
+ if (x < 1)
+ fun_l2_n539(x)
+ else
+ fun_l2_n990(x)
+ end
+end
+
+def fun_l1_n284(x)
+ if (x < 1)
+ fun_l2_n773(x)
+ else
+ fun_l2_n622(x)
+ end
+end
+
+def fun_l1_n285(x)
+ if (x < 1)
+ fun_l2_n695(x)
+ else
+ fun_l2_n101(x)
+ end
+end
+
+def fun_l1_n286(x)
+ if (x < 1)
+ fun_l2_n239(x)
+ else
+ fun_l2_n242(x)
+ end
+end
+
+def fun_l1_n287(x)
+ if (x < 1)
+ fun_l2_n191(x)
+ else
+ fun_l2_n839(x)
+ end
+end
+
+def fun_l1_n288(x)
+ if (x < 1)
+ fun_l2_n246(x)
+ else
+ fun_l2_n179(x)
+ end
+end
+
+def fun_l1_n289(x)
+ if (x < 1)
+ fun_l2_n300(x)
+ else
+ fun_l2_n975(x)
+ end
+end
+
+def fun_l1_n290(x)
+ if (x < 1)
+ fun_l2_n436(x)
+ else
+ fun_l2_n14(x)
+ end
+end
+
+def fun_l1_n291(x)
+ if (x < 1)
+ fun_l2_n33(x)
+ else
+ fun_l2_n303(x)
+ end
+end
+
+def fun_l1_n292(x)
+ if (x < 1)
+ fun_l2_n462(x)
+ else
+ fun_l2_n399(x)
+ end
+end
+
+def fun_l1_n293(x)
+ if (x < 1)
+ fun_l2_n782(x)
+ else
+ fun_l2_n521(x)
+ end
+end
+
+def fun_l1_n294(x)
+ if (x < 1)
+ fun_l2_n995(x)
+ else
+ fun_l2_n944(x)
+ end
+end
+
+def fun_l1_n295(x)
+ if (x < 1)
+ fun_l2_n700(x)
+ else
+ fun_l2_n250(x)
+ end
+end
+
+def fun_l1_n296(x)
+ if (x < 1)
+ fun_l2_n866(x)
+ else
+ fun_l2_n566(x)
+ end
+end
+
+def fun_l1_n297(x)
+ if (x < 1)
+ fun_l2_n373(x)
+ else
+ fun_l2_n881(x)
+ end
+end
+
+def fun_l1_n298(x)
+ if (x < 1)
+ fun_l2_n382(x)
+ else
+ fun_l2_n729(x)
+ end
+end
+
+def fun_l1_n299(x)
+ if (x < 1)
+ fun_l2_n878(x)
+ else
+ fun_l2_n192(x)
+ end
+end
+
+def fun_l1_n300(x)
+ if (x < 1)
+ fun_l2_n65(x)
+ else
+ fun_l2_n434(x)
+ end
+end
+
+def fun_l1_n301(x)
+ if (x < 1)
+ fun_l2_n513(x)
+ else
+ fun_l2_n617(x)
+ end
+end
+
+def fun_l1_n302(x)
+ if (x < 1)
+ fun_l2_n972(x)
+ else
+ fun_l2_n482(x)
+ end
+end
+
+def fun_l1_n303(x)
+ if (x < 1)
+ fun_l2_n533(x)
+ else
+ fun_l2_n774(x)
+ end
+end
+
+def fun_l1_n304(x)
+ if (x < 1)
+ fun_l2_n439(x)
+ else
+ fun_l2_n351(x)
+ end
+end
+
+def fun_l1_n305(x)
+ if (x < 1)
+ fun_l2_n181(x)
+ else
+ fun_l2_n74(x)
+ end
+end
+
+def fun_l1_n306(x)
+ if (x < 1)
+ fun_l2_n117(x)
+ else
+ fun_l2_n962(x)
+ end
+end
+
+def fun_l1_n307(x)
+ if (x < 1)
+ fun_l2_n499(x)
+ else
+ fun_l2_n183(x)
+ end
+end
+
+def fun_l1_n308(x)
+ if (x < 1)
+ fun_l2_n358(x)
+ else
+ fun_l2_n226(x)
+ end
+end
+
+def fun_l1_n309(x)
+ if (x < 1)
+ fun_l2_n227(x)
+ else
+ fun_l2_n425(x)
+ end
+end
+
+def fun_l1_n310(x)
+ if (x < 1)
+ fun_l2_n724(x)
+ else
+ fun_l2_n278(x)
+ end
+end
+
+def fun_l1_n311(x)
+ if (x < 1)
+ fun_l2_n784(x)
+ else
+ fun_l2_n888(x)
+ end
+end
+
+def fun_l1_n312(x)
+ if (x < 1)
+ fun_l2_n952(x)
+ else
+ fun_l2_n849(x)
+ end
+end
+
+def fun_l1_n313(x)
+ if (x < 1)
+ fun_l2_n921(x)
+ else
+ fun_l2_n31(x)
+ end
+end
+
+def fun_l1_n314(x)
+ if (x < 1)
+ fun_l2_n469(x)
+ else
+ fun_l2_n856(x)
+ end
+end
+
+def fun_l1_n315(x)
+ if (x < 1)
+ fun_l2_n89(x)
+ else
+ fun_l2_n949(x)
+ end
+end
+
+def fun_l1_n316(x)
+ if (x < 1)
+ fun_l2_n216(x)
+ else
+ fun_l2_n410(x)
+ end
+end
+
+def fun_l1_n317(x)
+ if (x < 1)
+ fun_l2_n591(x)
+ else
+ fun_l2_n203(x)
+ end
+end
+
+def fun_l1_n318(x)
+ if (x < 1)
+ fun_l2_n19(x)
+ else
+ fun_l2_n461(x)
+ end
+end
+
+def fun_l1_n319(x)
+ if (x < 1)
+ fun_l2_n875(x)
+ else
+ fun_l2_n996(x)
+ end
+end
+
+def fun_l1_n320(x)
+ if (x < 1)
+ fun_l2_n696(x)
+ else
+ fun_l2_n987(x)
+ end
+end
+
+def fun_l1_n321(x)
+ if (x < 1)
+ fun_l2_n708(x)
+ else
+ fun_l2_n150(x)
+ end
+end
+
+def fun_l1_n322(x)
+ if (x < 1)
+ fun_l2_n324(x)
+ else
+ fun_l2_n814(x)
+ end
+end
+
+def fun_l1_n323(x)
+ if (x < 1)
+ fun_l2_n427(x)
+ else
+ fun_l2_n472(x)
+ end
+end
+
+def fun_l1_n324(x)
+ if (x < 1)
+ fun_l2_n847(x)
+ else
+ fun_l2_n482(x)
+ end
+end
+
+def fun_l1_n325(x)
+ if (x < 1)
+ fun_l2_n335(x)
+ else
+ fun_l2_n854(x)
+ end
+end
+
+def fun_l1_n326(x)
+ if (x < 1)
+ fun_l2_n635(x)
+ else
+ fun_l2_n276(x)
+ end
+end
+
+def fun_l1_n327(x)
+ if (x < 1)
+ fun_l2_n539(x)
+ else
+ fun_l2_n885(x)
+ end
+end
+
+def fun_l1_n328(x)
+ if (x < 1)
+ fun_l2_n979(x)
+ else
+ fun_l2_n558(x)
+ end
+end
+
+def fun_l1_n329(x)
+ if (x < 1)
+ fun_l2_n35(x)
+ else
+ fun_l2_n696(x)
+ end
+end
+
+def fun_l1_n330(x)
+ if (x < 1)
+ fun_l2_n483(x)
+ else
+ fun_l2_n218(x)
+ end
+end
+
+def fun_l1_n331(x)
+ if (x < 1)
+ fun_l2_n3(x)
+ else
+ fun_l2_n324(x)
+ end
+end
+
+def fun_l1_n332(x)
+ if (x < 1)
+ fun_l2_n396(x)
+ else
+ fun_l2_n718(x)
+ end
+end
+
+def fun_l1_n333(x)
+ if (x < 1)
+ fun_l2_n973(x)
+ else
+ fun_l2_n663(x)
+ end
+end
+
+def fun_l1_n334(x)
+ if (x < 1)
+ fun_l2_n441(x)
+ else
+ fun_l2_n468(x)
+ end
+end
+
+def fun_l1_n335(x)
+ if (x < 1)
+ fun_l2_n511(x)
+ else
+ fun_l2_n455(x)
+ end
+end
+
+def fun_l1_n336(x)
+ if (x < 1)
+ fun_l2_n732(x)
+ else
+ fun_l2_n14(x)
+ end
+end
+
+def fun_l1_n337(x)
+ if (x < 1)
+ fun_l2_n484(x)
+ else
+ fun_l2_n482(x)
+ end
+end
+
+def fun_l1_n338(x)
+ if (x < 1)
+ fun_l2_n604(x)
+ else
+ fun_l2_n683(x)
+ end
+end
+
+def fun_l1_n339(x)
+ if (x < 1)
+ fun_l2_n334(x)
+ else
+ fun_l2_n710(x)
+ end
+end
+
+def fun_l1_n340(x)
+ if (x < 1)
+ fun_l2_n233(x)
+ else
+ fun_l2_n394(x)
+ end
+end
+
+def fun_l1_n341(x)
+ if (x < 1)
+ fun_l2_n948(x)
+ else
+ fun_l2_n473(x)
+ end
+end
+
+def fun_l1_n342(x)
+ if (x < 1)
+ fun_l2_n858(x)
+ else
+ fun_l2_n466(x)
+ end
+end
+
+def fun_l1_n343(x)
+ if (x < 1)
+ fun_l2_n647(x)
+ else
+ fun_l2_n604(x)
+ end
+end
+
+def fun_l1_n344(x)
+ if (x < 1)
+ fun_l2_n872(x)
+ else
+ fun_l2_n965(x)
+ end
+end
+
+def fun_l1_n345(x)
+ if (x < 1)
+ fun_l2_n845(x)
+ else
+ fun_l2_n701(x)
+ end
+end
+
+def fun_l1_n346(x)
+ if (x < 1)
+ fun_l2_n75(x)
+ else
+ fun_l2_n332(x)
+ end
+end
+
+def fun_l1_n347(x)
+ if (x < 1)
+ fun_l2_n873(x)
+ else
+ fun_l2_n575(x)
+ end
+end
+
+def fun_l1_n348(x)
+ if (x < 1)
+ fun_l2_n303(x)
+ else
+ fun_l2_n445(x)
+ end
+end
+
+def fun_l1_n349(x)
+ if (x < 1)
+ fun_l2_n45(x)
+ else
+ fun_l2_n312(x)
+ end
+end
+
+def fun_l1_n350(x)
+ if (x < 1)
+ fun_l2_n751(x)
+ else
+ fun_l2_n316(x)
+ end
+end
+
+def fun_l1_n351(x)
+ if (x < 1)
+ fun_l2_n781(x)
+ else
+ fun_l2_n165(x)
+ end
+end
+
+def fun_l1_n352(x)
+ if (x < 1)
+ fun_l2_n120(x)
+ else
+ fun_l2_n595(x)
+ end
+end
+
+def fun_l1_n353(x)
+ if (x < 1)
+ fun_l2_n221(x)
+ else
+ fun_l2_n827(x)
+ end
+end
+
+def fun_l1_n354(x)
+ if (x < 1)
+ fun_l2_n290(x)
+ else
+ fun_l2_n27(x)
+ end
+end
+
+def fun_l1_n355(x)
+ if (x < 1)
+ fun_l2_n377(x)
+ else
+ fun_l2_n28(x)
+ end
+end
+
+def fun_l1_n356(x)
+ if (x < 1)
+ fun_l2_n474(x)
+ else
+ fun_l2_n811(x)
+ end
+end
+
+def fun_l1_n357(x)
+ if (x < 1)
+ fun_l2_n90(x)
+ else
+ fun_l2_n559(x)
+ end
+end
+
+def fun_l1_n358(x)
+ if (x < 1)
+ fun_l2_n66(x)
+ else
+ fun_l2_n234(x)
+ end
+end
+
+def fun_l1_n359(x)
+ if (x < 1)
+ fun_l2_n526(x)
+ else
+ fun_l2_n674(x)
+ end
+end
+
+def fun_l1_n360(x)
+ if (x < 1)
+ fun_l2_n449(x)
+ else
+ fun_l2_n364(x)
+ end
+end
+
+def fun_l1_n361(x)
+ if (x < 1)
+ fun_l2_n790(x)
+ else
+ fun_l2_n835(x)
+ end
+end
+
+def fun_l1_n362(x)
+ if (x < 1)
+ fun_l2_n335(x)
+ else
+ fun_l2_n22(x)
+ end
+end
+
+def fun_l1_n363(x)
+ if (x < 1)
+ fun_l2_n982(x)
+ else
+ fun_l2_n449(x)
+ end
+end
+
+def fun_l1_n364(x)
+ if (x < 1)
+ fun_l2_n980(x)
+ else
+ fun_l2_n861(x)
+ end
+end
+
+def fun_l1_n365(x)
+ if (x < 1)
+ fun_l2_n673(x)
+ else
+ fun_l2_n267(x)
+ end
+end
+
+def fun_l1_n366(x)
+ if (x < 1)
+ fun_l2_n862(x)
+ else
+ fun_l2_n559(x)
+ end
+end
+
+def fun_l1_n367(x)
+ if (x < 1)
+ fun_l2_n637(x)
+ else
+ fun_l2_n275(x)
+ end
+end
+
+def fun_l1_n368(x)
+ if (x < 1)
+ fun_l2_n370(x)
+ else
+ fun_l2_n763(x)
+ end
+end
+
+def fun_l1_n369(x)
+ if (x < 1)
+ fun_l2_n680(x)
+ else
+ fun_l2_n476(x)
+ end
+end
+
+def fun_l1_n370(x)
+ if (x < 1)
+ fun_l2_n799(x)
+ else
+ fun_l2_n724(x)
+ end
+end
+
+def fun_l1_n371(x)
+ if (x < 1)
+ fun_l2_n331(x)
+ else
+ fun_l2_n927(x)
+ end
+end
+
+def fun_l1_n372(x)
+ if (x < 1)
+ fun_l2_n875(x)
+ else
+ fun_l2_n350(x)
+ end
+end
+
+def fun_l1_n373(x)
+ if (x < 1)
+ fun_l2_n734(x)
+ else
+ fun_l2_n172(x)
+ end
+end
+
+def fun_l1_n374(x)
+ if (x < 1)
+ fun_l2_n657(x)
+ else
+ fun_l2_n765(x)
+ end
+end
+
+def fun_l1_n375(x)
+ if (x < 1)
+ fun_l2_n950(x)
+ else
+ fun_l2_n85(x)
+ end
+end
+
+def fun_l1_n376(x)
+ if (x < 1)
+ fun_l2_n276(x)
+ else
+ fun_l2_n892(x)
+ end
+end
+
+def fun_l1_n377(x)
+ if (x < 1)
+ fun_l2_n430(x)
+ else
+ fun_l2_n173(x)
+ end
+end
+
+def fun_l1_n378(x)
+ if (x < 1)
+ fun_l2_n376(x)
+ else
+ fun_l2_n876(x)
+ end
+end
+
+def fun_l1_n379(x)
+ if (x < 1)
+ fun_l2_n981(x)
+ else
+ fun_l2_n314(x)
+ end
+end
+
+def fun_l1_n380(x)
+ if (x < 1)
+ fun_l2_n680(x)
+ else
+ fun_l2_n600(x)
+ end
+end
+
+def fun_l1_n381(x)
+ if (x < 1)
+ fun_l2_n54(x)
+ else
+ fun_l2_n158(x)
+ end
+end
+
+def fun_l1_n382(x)
+ if (x < 1)
+ fun_l2_n692(x)
+ else
+ fun_l2_n673(x)
+ end
+end
+
+def fun_l1_n383(x)
+ if (x < 1)
+ fun_l2_n393(x)
+ else
+ fun_l2_n723(x)
+ end
+end
+
+def fun_l1_n384(x)
+ if (x < 1)
+ fun_l2_n899(x)
+ else
+ fun_l2_n940(x)
+ end
+end
+
+def fun_l1_n385(x)
+ if (x < 1)
+ fun_l2_n473(x)
+ else
+ fun_l2_n846(x)
+ end
+end
+
+def fun_l1_n386(x)
+ if (x < 1)
+ fun_l2_n291(x)
+ else
+ fun_l2_n864(x)
+ end
+end
+
+def fun_l1_n387(x)
+ if (x < 1)
+ fun_l2_n174(x)
+ else
+ fun_l2_n466(x)
+ end
+end
+
+def fun_l1_n388(x)
+ if (x < 1)
+ fun_l2_n883(x)
+ else
+ fun_l2_n613(x)
+ end
+end
+
+def fun_l1_n389(x)
+ if (x < 1)
+ fun_l2_n808(x)
+ else
+ fun_l2_n169(x)
+ end
+end
+
+def fun_l1_n390(x)
+ if (x < 1)
+ fun_l2_n94(x)
+ else
+ fun_l2_n93(x)
+ end
+end
+
+def fun_l1_n391(x)
+ if (x < 1)
+ fun_l2_n874(x)
+ else
+ fun_l2_n400(x)
+ end
+end
+
+def fun_l1_n392(x)
+ if (x < 1)
+ fun_l2_n473(x)
+ else
+ fun_l2_n239(x)
+ end
+end
+
+def fun_l1_n393(x)
+ if (x < 1)
+ fun_l2_n64(x)
+ else
+ fun_l2_n760(x)
+ end
+end
+
+def fun_l1_n394(x)
+ if (x < 1)
+ fun_l2_n947(x)
+ else
+ fun_l2_n354(x)
+ end
+end
+
+def fun_l1_n395(x)
+ if (x < 1)
+ fun_l2_n833(x)
+ else
+ fun_l2_n563(x)
+ end
+end
+
+def fun_l1_n396(x)
+ if (x < 1)
+ fun_l2_n429(x)
+ else
+ fun_l2_n280(x)
+ end
+end
+
+def fun_l1_n397(x)
+ if (x < 1)
+ fun_l2_n132(x)
+ else
+ fun_l2_n486(x)
+ end
+end
+
+def fun_l1_n398(x)
+ if (x < 1)
+ fun_l2_n28(x)
+ else
+ fun_l2_n135(x)
+ end
+end
+
+def fun_l1_n399(x)
+ if (x < 1)
+ fun_l2_n804(x)
+ else
+ fun_l2_n406(x)
+ end
+end
+
+def fun_l1_n400(x)
+ if (x < 1)
+ fun_l2_n661(x)
+ else
+ fun_l2_n216(x)
+ end
+end
+
+def fun_l1_n401(x)
+ if (x < 1)
+ fun_l2_n681(x)
+ else
+ fun_l2_n849(x)
+ end
+end
+
+def fun_l1_n402(x)
+ if (x < 1)
+ fun_l2_n13(x)
+ else
+ fun_l2_n205(x)
+ end
+end
+
+def fun_l1_n403(x)
+ if (x < 1)
+ fun_l2_n911(x)
+ else
+ fun_l2_n63(x)
+ end
+end
+
+def fun_l1_n404(x)
+ if (x < 1)
+ fun_l2_n518(x)
+ else
+ fun_l2_n845(x)
+ end
+end
+
+def fun_l1_n405(x)
+ if (x < 1)
+ fun_l2_n699(x)
+ else
+ fun_l2_n963(x)
+ end
+end
+
+def fun_l1_n406(x)
+ if (x < 1)
+ fun_l2_n373(x)
+ else
+ fun_l2_n485(x)
+ end
+end
+
+def fun_l1_n407(x)
+ if (x < 1)
+ fun_l2_n402(x)
+ else
+ fun_l2_n582(x)
+ end
+end
+
+def fun_l1_n408(x)
+ if (x < 1)
+ fun_l2_n802(x)
+ else
+ fun_l2_n420(x)
+ end
+end
+
+def fun_l1_n409(x)
+ if (x < 1)
+ fun_l2_n728(x)
+ else
+ fun_l2_n50(x)
+ end
+end
+
+def fun_l1_n410(x)
+ if (x < 1)
+ fun_l2_n189(x)
+ else
+ fun_l2_n588(x)
+ end
+end
+
+def fun_l1_n411(x)
+ if (x < 1)
+ fun_l2_n51(x)
+ else
+ fun_l2_n23(x)
+ end
+end
+
+def fun_l1_n412(x)
+ if (x < 1)
+ fun_l2_n548(x)
+ else
+ fun_l2_n200(x)
+ end
+end
+
+def fun_l1_n413(x)
+ if (x < 1)
+ fun_l2_n763(x)
+ else
+ fun_l2_n581(x)
+ end
+end
+
+def fun_l1_n414(x)
+ if (x < 1)
+ fun_l2_n650(x)
+ else
+ fun_l2_n535(x)
+ end
+end
+
+def fun_l1_n415(x)
+ if (x < 1)
+ fun_l2_n500(x)
+ else
+ fun_l2_n579(x)
+ end
+end
+
+def fun_l1_n416(x)
+ if (x < 1)
+ fun_l2_n573(x)
+ else
+ fun_l2_n154(x)
+ end
+end
+
+def fun_l1_n417(x)
+ if (x < 1)
+ fun_l2_n685(x)
+ else
+ fun_l2_n14(x)
+ end
+end
+
+def fun_l1_n418(x)
+ if (x < 1)
+ fun_l2_n849(x)
+ else
+ fun_l2_n91(x)
+ end
+end
+
+def fun_l1_n419(x)
+ if (x < 1)
+ fun_l2_n629(x)
+ else
+ fun_l2_n698(x)
+ end
+end
+
+def fun_l1_n420(x)
+ if (x < 1)
+ fun_l2_n273(x)
+ else
+ fun_l2_n303(x)
+ end
+end
+
+def fun_l1_n421(x)
+ if (x < 1)
+ fun_l2_n8(x)
+ else
+ fun_l2_n476(x)
+ end
+end
+
+def fun_l1_n422(x)
+ if (x < 1)
+ fun_l2_n294(x)
+ else
+ fun_l2_n338(x)
+ end
+end
+
+def fun_l1_n423(x)
+ if (x < 1)
+ fun_l2_n408(x)
+ else
+ fun_l2_n187(x)
+ end
+end
+
+def fun_l1_n424(x)
+ if (x < 1)
+ fun_l2_n349(x)
+ else
+ fun_l2_n896(x)
+ end
+end
+
+def fun_l1_n425(x)
+ if (x < 1)
+ fun_l2_n950(x)
+ else
+ fun_l2_n186(x)
+ end
+end
+
+def fun_l1_n426(x)
+ if (x < 1)
+ fun_l2_n817(x)
+ else
+ fun_l2_n605(x)
+ end
+end
+
+def fun_l1_n427(x)
+ if (x < 1)
+ fun_l2_n317(x)
+ else
+ fun_l2_n31(x)
+ end
+end
+
+def fun_l1_n428(x)
+ if (x < 1)
+ fun_l2_n804(x)
+ else
+ fun_l2_n547(x)
+ end
+end
+
+def fun_l1_n429(x)
+ if (x < 1)
+ fun_l2_n730(x)
+ else
+ fun_l2_n711(x)
+ end
+end
+
+def fun_l1_n430(x)
+ if (x < 1)
+ fun_l2_n822(x)
+ else
+ fun_l2_n749(x)
+ end
+end
+
+def fun_l1_n431(x)
+ if (x < 1)
+ fun_l2_n412(x)
+ else
+ fun_l2_n366(x)
+ end
+end
+
+def fun_l1_n432(x)
+ if (x < 1)
+ fun_l2_n462(x)
+ else
+ fun_l2_n601(x)
+ end
+end
+
+def fun_l1_n433(x)
+ if (x < 1)
+ fun_l2_n971(x)
+ else
+ fun_l2_n878(x)
+ end
+end
+
+def fun_l1_n434(x)
+ if (x < 1)
+ fun_l2_n551(x)
+ else
+ fun_l2_n172(x)
+ end
+end
+
+def fun_l1_n435(x)
+ if (x < 1)
+ fun_l2_n914(x)
+ else
+ fun_l2_n640(x)
+ end
+end
+
+def fun_l1_n436(x)
+ if (x < 1)
+ fun_l2_n957(x)
+ else
+ fun_l2_n846(x)
+ end
+end
+
+def fun_l1_n437(x)
+ if (x < 1)
+ fun_l2_n622(x)
+ else
+ fun_l2_n995(x)
+ end
+end
+
+def fun_l1_n438(x)
+ if (x < 1)
+ fun_l2_n830(x)
+ else
+ fun_l2_n537(x)
+ end
+end
+
+def fun_l1_n439(x)
+ if (x < 1)
+ fun_l2_n415(x)
+ else
+ fun_l2_n863(x)
+ end
+end
+
+def fun_l1_n440(x)
+ if (x < 1)
+ fun_l2_n637(x)
+ else
+ fun_l2_n354(x)
+ end
+end
+
+def fun_l1_n441(x)
+ if (x < 1)
+ fun_l2_n525(x)
+ else
+ fun_l2_n656(x)
+ end
+end
+
+def fun_l1_n442(x)
+ if (x < 1)
+ fun_l2_n284(x)
+ else
+ fun_l2_n722(x)
+ end
+end
+
+def fun_l1_n443(x)
+ if (x < 1)
+ fun_l2_n485(x)
+ else
+ fun_l2_n794(x)
+ end
+end
+
+def fun_l1_n444(x)
+ if (x < 1)
+ fun_l2_n268(x)
+ else
+ fun_l2_n443(x)
+ end
+end
+
+def fun_l1_n445(x)
+ if (x < 1)
+ fun_l2_n743(x)
+ else
+ fun_l2_n723(x)
+ end
+end
+
+def fun_l1_n446(x)
+ if (x < 1)
+ fun_l2_n651(x)
+ else
+ fun_l2_n544(x)
+ end
+end
+
+def fun_l1_n447(x)
+ if (x < 1)
+ fun_l2_n936(x)
+ else
+ fun_l2_n50(x)
+ end
+end
+
+def fun_l1_n448(x)
+ if (x < 1)
+ fun_l2_n473(x)
+ else
+ fun_l2_n749(x)
+ end
+end
+
+def fun_l1_n449(x)
+ if (x < 1)
+ fun_l2_n218(x)
+ else
+ fun_l2_n266(x)
+ end
+end
+
+def fun_l1_n450(x)
+ if (x < 1)
+ fun_l2_n686(x)
+ else
+ fun_l2_n629(x)
+ end
+end
+
+def fun_l1_n451(x)
+ if (x < 1)
+ fun_l2_n648(x)
+ else
+ fun_l2_n322(x)
+ end
+end
+
+def fun_l1_n452(x)
+ if (x < 1)
+ fun_l2_n380(x)
+ else
+ fun_l2_n720(x)
+ end
+end
+
+def fun_l1_n453(x)
+ if (x < 1)
+ fun_l2_n53(x)
+ else
+ fun_l2_n830(x)
+ end
+end
+
+def fun_l1_n454(x)
+ if (x < 1)
+ fun_l2_n315(x)
+ else
+ fun_l2_n742(x)
+ end
+end
+
+def fun_l1_n455(x)
+ if (x < 1)
+ fun_l2_n902(x)
+ else
+ fun_l2_n111(x)
+ end
+end
+
+def fun_l1_n456(x)
+ if (x < 1)
+ fun_l2_n924(x)
+ else
+ fun_l2_n109(x)
+ end
+end
+
+def fun_l1_n457(x)
+ if (x < 1)
+ fun_l2_n249(x)
+ else
+ fun_l2_n865(x)
+ end
+end
+
+def fun_l1_n458(x)
+ if (x < 1)
+ fun_l2_n650(x)
+ else
+ fun_l2_n960(x)
+ end
+end
+
+def fun_l1_n459(x)
+ if (x < 1)
+ fun_l2_n273(x)
+ else
+ fun_l2_n544(x)
+ end
+end
+
+def fun_l1_n460(x)
+ if (x < 1)
+ fun_l2_n120(x)
+ else
+ fun_l2_n322(x)
+ end
+end
+
+def fun_l1_n461(x)
+ if (x < 1)
+ fun_l2_n366(x)
+ else
+ fun_l2_n534(x)
+ end
+end
+
+def fun_l1_n462(x)
+ if (x < 1)
+ fun_l2_n380(x)
+ else
+ fun_l2_n25(x)
+ end
+end
+
+def fun_l1_n463(x)
+ if (x < 1)
+ fun_l2_n333(x)
+ else
+ fun_l2_n303(x)
+ end
+end
+
+def fun_l1_n464(x)
+ if (x < 1)
+ fun_l2_n16(x)
+ else
+ fun_l2_n239(x)
+ end
+end
+
+def fun_l1_n465(x)
+ if (x < 1)
+ fun_l2_n539(x)
+ else
+ fun_l2_n988(x)
+ end
+end
+
+def fun_l1_n466(x)
+ if (x < 1)
+ fun_l2_n580(x)
+ else
+ fun_l2_n86(x)
+ end
+end
+
+def fun_l1_n467(x)
+ if (x < 1)
+ fun_l2_n406(x)
+ else
+ fun_l2_n706(x)
+ end
+end
+
+def fun_l1_n468(x)
+ if (x < 1)
+ fun_l2_n858(x)
+ else
+ fun_l2_n393(x)
+ end
+end
+
+def fun_l1_n469(x)
+ if (x < 1)
+ fun_l2_n64(x)
+ else
+ fun_l2_n482(x)
+ end
+end
+
+def fun_l1_n470(x)
+ if (x < 1)
+ fun_l2_n654(x)
+ else
+ fun_l2_n833(x)
+ end
+end
+
+def fun_l1_n471(x)
+ if (x < 1)
+ fun_l2_n161(x)
+ else
+ fun_l2_n91(x)
+ end
+end
+
+def fun_l1_n472(x)
+ if (x < 1)
+ fun_l2_n98(x)
+ else
+ fun_l2_n661(x)
+ end
+end
+
+def fun_l1_n473(x)
+ if (x < 1)
+ fun_l2_n574(x)
+ else
+ fun_l2_n133(x)
+ end
+end
+
+def fun_l1_n474(x)
+ if (x < 1)
+ fun_l2_n109(x)
+ else
+ fun_l2_n702(x)
+ end
+end
+
+def fun_l1_n475(x)
+ if (x < 1)
+ fun_l2_n808(x)
+ else
+ fun_l2_n584(x)
+ end
+end
+
+def fun_l1_n476(x)
+ if (x < 1)
+ fun_l2_n495(x)
+ else
+ fun_l2_n708(x)
+ end
+end
+
+def fun_l1_n477(x)
+ if (x < 1)
+ fun_l2_n649(x)
+ else
+ fun_l2_n290(x)
+ end
+end
+
+def fun_l1_n478(x)
+ if (x < 1)
+ fun_l2_n718(x)
+ else
+ fun_l2_n998(x)
+ end
+end
+
+def fun_l1_n479(x)
+ if (x < 1)
+ fun_l2_n557(x)
+ else
+ fun_l2_n359(x)
+ end
+end
+
+def fun_l1_n480(x)
+ if (x < 1)
+ fun_l2_n958(x)
+ else
+ fun_l2_n86(x)
+ end
+end
+
+def fun_l1_n481(x)
+ if (x < 1)
+ fun_l2_n245(x)
+ else
+ fun_l2_n124(x)
+ end
+end
+
+def fun_l1_n482(x)
+ if (x < 1)
+ fun_l2_n510(x)
+ else
+ fun_l2_n170(x)
+ end
+end
+
+def fun_l1_n483(x)
+ if (x < 1)
+ fun_l2_n550(x)
+ else
+ fun_l2_n9(x)
+ end
+end
+
+def fun_l1_n484(x)
+ if (x < 1)
+ fun_l2_n82(x)
+ else
+ fun_l2_n351(x)
+ end
+end
+
+def fun_l1_n485(x)
+ if (x < 1)
+ fun_l2_n760(x)
+ else
+ fun_l2_n560(x)
+ end
+end
+
+def fun_l1_n486(x)
+ if (x < 1)
+ fun_l2_n550(x)
+ else
+ fun_l2_n881(x)
+ end
+end
+
+def fun_l1_n487(x)
+ if (x < 1)
+ fun_l2_n62(x)
+ else
+ fun_l2_n213(x)
+ end
+end
+
+def fun_l1_n488(x)
+ if (x < 1)
+ fun_l2_n336(x)
+ else
+ fun_l2_n855(x)
+ end
+end
+
+def fun_l1_n489(x)
+ if (x < 1)
+ fun_l2_n172(x)
+ else
+ fun_l2_n479(x)
+ end
+end
+
+def fun_l1_n490(x)
+ if (x < 1)
+ fun_l2_n821(x)
+ else
+ fun_l2_n767(x)
+ end
+end
+
+def fun_l1_n491(x)
+ if (x < 1)
+ fun_l2_n388(x)
+ else
+ fun_l2_n307(x)
+ end
+end
+
+def fun_l1_n492(x)
+ if (x < 1)
+ fun_l2_n158(x)
+ else
+ fun_l2_n725(x)
+ end
+end
+
+def fun_l1_n493(x)
+ if (x < 1)
+ fun_l2_n681(x)
+ else
+ fun_l2_n767(x)
+ end
+end
+
+def fun_l1_n494(x)
+ if (x < 1)
+ fun_l2_n799(x)
+ else
+ fun_l2_n458(x)
+ end
+end
+
+def fun_l1_n495(x)
+ if (x < 1)
+ fun_l2_n379(x)
+ else
+ fun_l2_n152(x)
+ end
+end
+
+def fun_l1_n496(x)
+ if (x < 1)
+ fun_l2_n996(x)
+ else
+ fun_l2_n296(x)
+ end
+end
+
+def fun_l1_n497(x)
+ if (x < 1)
+ fun_l2_n752(x)
+ else
+ fun_l2_n481(x)
+ end
+end
+
+def fun_l1_n498(x)
+ if (x < 1)
+ fun_l2_n887(x)
+ else
+ fun_l2_n343(x)
+ end
+end
+
+def fun_l1_n499(x)
+ if (x < 1)
+ fun_l2_n481(x)
+ else
+ fun_l2_n368(x)
+ end
+end
+
+def fun_l1_n500(x)
+ if (x < 1)
+ fun_l2_n738(x)
+ else
+ fun_l2_n349(x)
+ end
+end
+
+def fun_l1_n501(x)
+ if (x < 1)
+ fun_l2_n104(x)
+ else
+ fun_l2_n841(x)
+ end
+end
+
+def fun_l1_n502(x)
+ if (x < 1)
+ fun_l2_n549(x)
+ else
+ fun_l2_n684(x)
+ end
+end
+
+def fun_l1_n503(x)
+ if (x < 1)
+ fun_l2_n726(x)
+ else
+ fun_l2_n41(x)
+ end
+end
+
+def fun_l1_n504(x)
+ if (x < 1)
+ fun_l2_n637(x)
+ else
+ fun_l2_n830(x)
+ end
+end
+
+def fun_l1_n505(x)
+ if (x < 1)
+ fun_l2_n38(x)
+ else
+ fun_l2_n815(x)
+ end
+end
+
+def fun_l1_n506(x)
+ if (x < 1)
+ fun_l2_n284(x)
+ else
+ fun_l2_n599(x)
+ end
+end
+
+def fun_l1_n507(x)
+ if (x < 1)
+ fun_l2_n665(x)
+ else
+ fun_l2_n763(x)
+ end
+end
+
+def fun_l1_n508(x)
+ if (x < 1)
+ fun_l2_n755(x)
+ else
+ fun_l2_n51(x)
+ end
+end
+
+def fun_l1_n509(x)
+ if (x < 1)
+ fun_l2_n860(x)
+ else
+ fun_l2_n273(x)
+ end
+end
+
+def fun_l1_n510(x)
+ if (x < 1)
+ fun_l2_n967(x)
+ else
+ fun_l2_n141(x)
+ end
+end
+
+def fun_l1_n511(x)
+ if (x < 1)
+ fun_l2_n637(x)
+ else
+ fun_l2_n953(x)
+ end
+end
+
+def fun_l1_n512(x)
+ if (x < 1)
+ fun_l2_n784(x)
+ else
+ fun_l2_n941(x)
+ end
+end
+
+def fun_l1_n513(x)
+ if (x < 1)
+ fun_l2_n499(x)
+ else
+ fun_l2_n189(x)
+ end
+end
+
+def fun_l1_n514(x)
+ if (x < 1)
+ fun_l2_n207(x)
+ else
+ fun_l2_n187(x)
+ end
+end
+
+def fun_l1_n515(x)
+ if (x < 1)
+ fun_l2_n174(x)
+ else
+ fun_l2_n316(x)
+ end
+end
+
+def fun_l1_n516(x)
+ if (x < 1)
+ fun_l2_n884(x)
+ else
+ fun_l2_n72(x)
+ end
+end
+
+def fun_l1_n517(x)
+ if (x < 1)
+ fun_l2_n878(x)
+ else
+ fun_l2_n423(x)
+ end
+end
+
+def fun_l1_n518(x)
+ if (x < 1)
+ fun_l2_n452(x)
+ else
+ fun_l2_n733(x)
+ end
+end
+
+def fun_l1_n519(x)
+ if (x < 1)
+ fun_l2_n586(x)
+ else
+ fun_l2_n987(x)
+ end
+end
+
+def fun_l1_n520(x)
+ if (x < 1)
+ fun_l2_n638(x)
+ else
+ fun_l2_n276(x)
+ end
+end
+
+def fun_l1_n521(x)
+ if (x < 1)
+ fun_l2_n186(x)
+ else
+ fun_l2_n498(x)
+ end
+end
+
+def fun_l1_n522(x)
+ if (x < 1)
+ fun_l2_n816(x)
+ else
+ fun_l2_n687(x)
+ end
+end
+
+def fun_l1_n523(x)
+ if (x < 1)
+ fun_l2_n572(x)
+ else
+ fun_l2_n878(x)
+ end
+end
+
+def fun_l1_n524(x)
+ if (x < 1)
+ fun_l2_n528(x)
+ else
+ fun_l2_n188(x)
+ end
+end
+
+def fun_l1_n525(x)
+ if (x < 1)
+ fun_l2_n719(x)
+ else
+ fun_l2_n146(x)
+ end
+end
+
+def fun_l1_n526(x)
+ if (x < 1)
+ fun_l2_n730(x)
+ else
+ fun_l2_n209(x)
+ end
+end
+
+def fun_l1_n527(x)
+ if (x < 1)
+ fun_l2_n998(x)
+ else
+ fun_l2_n544(x)
+ end
+end
+
+def fun_l1_n528(x)
+ if (x < 1)
+ fun_l2_n288(x)
+ else
+ fun_l2_n682(x)
+ end
+end
+
+def fun_l1_n529(x)
+ if (x < 1)
+ fun_l2_n808(x)
+ else
+ fun_l2_n651(x)
+ end
+end
+
+def fun_l1_n530(x)
+ if (x < 1)
+ fun_l2_n674(x)
+ else
+ fun_l2_n643(x)
+ end
+end
+
+def fun_l1_n531(x)
+ if (x < 1)
+ fun_l2_n42(x)
+ else
+ fun_l2_n457(x)
+ end
+end
+
+def fun_l1_n532(x)
+ if (x < 1)
+ fun_l2_n188(x)
+ else
+ fun_l2_n218(x)
+ end
+end
+
+def fun_l1_n533(x)
+ if (x < 1)
+ fun_l2_n529(x)
+ else
+ fun_l2_n541(x)
+ end
+end
+
+def fun_l1_n534(x)
+ if (x < 1)
+ fun_l2_n820(x)
+ else
+ fun_l2_n426(x)
+ end
+end
+
+def fun_l1_n535(x)
+ if (x < 1)
+ fun_l2_n730(x)
+ else
+ fun_l2_n36(x)
+ end
+end
+
+def fun_l1_n536(x)
+ if (x < 1)
+ fun_l2_n187(x)
+ else
+ fun_l2_n96(x)
+ end
+end
+
+def fun_l1_n537(x)
+ if (x < 1)
+ fun_l2_n1(x)
+ else
+ fun_l2_n905(x)
+ end
+end
+
+def fun_l1_n538(x)
+ if (x < 1)
+ fun_l2_n252(x)
+ else
+ fun_l2_n597(x)
+ end
+end
+
+def fun_l1_n539(x)
+ if (x < 1)
+ fun_l2_n959(x)
+ else
+ fun_l2_n26(x)
+ end
+end
+
+def fun_l1_n540(x)
+ if (x < 1)
+ fun_l2_n959(x)
+ else
+ fun_l2_n266(x)
+ end
+end
+
+def fun_l1_n541(x)
+ if (x < 1)
+ fun_l2_n902(x)
+ else
+ fun_l2_n957(x)
+ end
+end
+
+def fun_l1_n542(x)
+ if (x < 1)
+ fun_l2_n244(x)
+ else
+ fun_l2_n407(x)
+ end
+end
+
+def fun_l1_n543(x)
+ if (x < 1)
+ fun_l2_n319(x)
+ else
+ fun_l2_n19(x)
+ end
+end
+
+def fun_l1_n544(x)
+ if (x < 1)
+ fun_l2_n251(x)
+ else
+ fun_l2_n92(x)
+ end
+end
+
+def fun_l1_n545(x)
+ if (x < 1)
+ fun_l2_n482(x)
+ else
+ fun_l2_n177(x)
+ end
+end
+
+def fun_l1_n546(x)
+ if (x < 1)
+ fun_l2_n338(x)
+ else
+ fun_l2_n152(x)
+ end
+end
+
+def fun_l1_n547(x)
+ if (x < 1)
+ fun_l2_n902(x)
+ else
+ fun_l2_n243(x)
+ end
+end
+
+def fun_l1_n548(x)
+ if (x < 1)
+ fun_l2_n943(x)
+ else
+ fun_l2_n930(x)
+ end
+end
+
+def fun_l1_n549(x)
+ if (x < 1)
+ fun_l2_n775(x)
+ else
+ fun_l2_n338(x)
+ end
+end
+
+def fun_l1_n550(x)
+ if (x < 1)
+ fun_l2_n286(x)
+ else
+ fun_l2_n347(x)
+ end
+end
+
+def fun_l1_n551(x)
+ if (x < 1)
+ fun_l2_n611(x)
+ else
+ fun_l2_n108(x)
+ end
+end
+
+def fun_l1_n552(x)
+ if (x < 1)
+ fun_l2_n515(x)
+ else
+ fun_l2_n478(x)
+ end
+end
+
+def fun_l1_n553(x)
+ if (x < 1)
+ fun_l2_n68(x)
+ else
+ fun_l2_n943(x)
+ end
+end
+
+def fun_l1_n554(x)
+ if (x < 1)
+ fun_l2_n16(x)
+ else
+ fun_l2_n280(x)
+ end
+end
+
+def fun_l1_n555(x)
+ if (x < 1)
+ fun_l2_n421(x)
+ else
+ fun_l2_n412(x)
+ end
+end
+
+def fun_l1_n556(x)
+ if (x < 1)
+ fun_l2_n653(x)
+ else
+ fun_l2_n527(x)
+ end
+end
+
+def fun_l1_n557(x)
+ if (x < 1)
+ fun_l2_n181(x)
+ else
+ fun_l2_n179(x)
+ end
+end
+
+def fun_l1_n558(x)
+ if (x < 1)
+ fun_l2_n270(x)
+ else
+ fun_l2_n367(x)
+ end
+end
+
+def fun_l1_n559(x)
+ if (x < 1)
+ fun_l2_n323(x)
+ else
+ fun_l2_n453(x)
+ end
+end
+
+def fun_l1_n560(x)
+ if (x < 1)
+ fun_l2_n699(x)
+ else
+ fun_l2_n904(x)
+ end
+end
+
+def fun_l1_n561(x)
+ if (x < 1)
+ fun_l2_n903(x)
+ else
+ fun_l2_n559(x)
+ end
+end
+
+def fun_l1_n562(x)
+ if (x < 1)
+ fun_l2_n573(x)
+ else
+ fun_l2_n880(x)
+ end
+end
+
+def fun_l1_n563(x)
+ if (x < 1)
+ fun_l2_n674(x)
+ else
+ fun_l2_n420(x)
+ end
+end
+
+def fun_l1_n564(x)
+ if (x < 1)
+ fun_l2_n76(x)
+ else
+ fun_l2_n702(x)
+ end
+end
+
+def fun_l1_n565(x)
+ if (x < 1)
+ fun_l2_n78(x)
+ else
+ fun_l2_n741(x)
+ end
+end
+
+def fun_l1_n566(x)
+ if (x < 1)
+ fun_l2_n542(x)
+ else
+ fun_l2_n762(x)
+ end
+end
+
+def fun_l1_n567(x)
+ if (x < 1)
+ fun_l2_n992(x)
+ else
+ fun_l2_n416(x)
+ end
+end
+
+def fun_l1_n568(x)
+ if (x < 1)
+ fun_l2_n510(x)
+ else
+ fun_l2_n68(x)
+ end
+end
+
+def fun_l1_n569(x)
+ if (x < 1)
+ fun_l2_n36(x)
+ else
+ fun_l2_n152(x)
+ end
+end
+
+def fun_l1_n570(x)
+ if (x < 1)
+ fun_l2_n243(x)
+ else
+ fun_l2_n421(x)
+ end
+end
+
+def fun_l1_n571(x)
+ if (x < 1)
+ fun_l2_n48(x)
+ else
+ fun_l2_n50(x)
+ end
+end
+
+def fun_l1_n572(x)
+ if (x < 1)
+ fun_l2_n647(x)
+ else
+ fun_l2_n614(x)
+ end
+end
+
+def fun_l1_n573(x)
+ if (x < 1)
+ fun_l2_n847(x)
+ else
+ fun_l2_n598(x)
+ end
+end
+
+def fun_l1_n574(x)
+ if (x < 1)
+ fun_l2_n462(x)
+ else
+ fun_l2_n492(x)
+ end
+end
+
+def fun_l1_n575(x)
+ if (x < 1)
+ fun_l2_n805(x)
+ else
+ fun_l2_n23(x)
+ end
+end
+
+def fun_l1_n576(x)
+ if (x < 1)
+ fun_l2_n660(x)
+ else
+ fun_l2_n271(x)
+ end
+end
+
+def fun_l1_n577(x)
+ if (x < 1)
+ fun_l2_n277(x)
+ else
+ fun_l2_n259(x)
+ end
+end
+
+def fun_l1_n578(x)
+ if (x < 1)
+ fun_l2_n645(x)
+ else
+ fun_l2_n638(x)
+ end
+end
+
+def fun_l1_n579(x)
+ if (x < 1)
+ fun_l2_n925(x)
+ else
+ fun_l2_n801(x)
+ end
+end
+
+def fun_l1_n580(x)
+ if (x < 1)
+ fun_l2_n52(x)
+ else
+ fun_l2_n703(x)
+ end
+end
+
+def fun_l1_n581(x)
+ if (x < 1)
+ fun_l2_n126(x)
+ else
+ fun_l2_n511(x)
+ end
+end
+
+def fun_l1_n582(x)
+ if (x < 1)
+ fun_l2_n663(x)
+ else
+ fun_l2_n158(x)
+ end
+end
+
+def fun_l1_n583(x)
+ if (x < 1)
+ fun_l2_n604(x)
+ else
+ fun_l2_n498(x)
+ end
+end
+
+def fun_l1_n584(x)
+ if (x < 1)
+ fun_l2_n889(x)
+ else
+ fun_l2_n197(x)
+ end
+end
+
+def fun_l1_n585(x)
+ if (x < 1)
+ fun_l2_n28(x)
+ else
+ fun_l2_n298(x)
+ end
+end
+
+def fun_l1_n586(x)
+ if (x < 1)
+ fun_l2_n165(x)
+ else
+ fun_l2_n340(x)
+ end
+end
+
+def fun_l1_n587(x)
+ if (x < 1)
+ fun_l2_n89(x)
+ else
+ fun_l2_n947(x)
+ end
+end
+
+def fun_l1_n588(x)
+ if (x < 1)
+ fun_l2_n151(x)
+ else
+ fun_l2_n163(x)
+ end
+end
+
+def fun_l1_n589(x)
+ if (x < 1)
+ fun_l2_n200(x)
+ else
+ fun_l2_n855(x)
+ end
+end
+
+def fun_l1_n590(x)
+ if (x < 1)
+ fun_l2_n749(x)
+ else
+ fun_l2_n232(x)
+ end
+end
+
+def fun_l1_n591(x)
+ if (x < 1)
+ fun_l2_n850(x)
+ else
+ fun_l2_n897(x)
+ end
+end
+
+def fun_l1_n592(x)
+ if (x < 1)
+ fun_l2_n287(x)
+ else
+ fun_l2_n266(x)
+ end
+end
+
+def fun_l1_n593(x)
+ if (x < 1)
+ fun_l2_n547(x)
+ else
+ fun_l2_n937(x)
+ end
+end
+
+def fun_l1_n594(x)
+ if (x < 1)
+ fun_l2_n517(x)
+ else
+ fun_l2_n602(x)
+ end
+end
+
+def fun_l1_n595(x)
+ if (x < 1)
+ fun_l2_n962(x)
+ else
+ fun_l2_n387(x)
+ end
+end
+
+def fun_l1_n596(x)
+ if (x < 1)
+ fun_l2_n959(x)
+ else
+ fun_l2_n885(x)
+ end
+end
+
+def fun_l1_n597(x)
+ if (x < 1)
+ fun_l2_n343(x)
+ else
+ fun_l2_n704(x)
+ end
+end
+
+def fun_l1_n598(x)
+ if (x < 1)
+ fun_l2_n256(x)
+ else
+ fun_l2_n213(x)
+ end
+end
+
+def fun_l1_n599(x)
+ if (x < 1)
+ fun_l2_n653(x)
+ else
+ fun_l2_n630(x)
+ end
+end
+
+def fun_l1_n600(x)
+ if (x < 1)
+ fun_l2_n587(x)
+ else
+ fun_l2_n899(x)
+ end
+end
+
+def fun_l1_n601(x)
+ if (x < 1)
+ fun_l2_n798(x)
+ else
+ fun_l2_n318(x)
+ end
+end
+
+def fun_l1_n602(x)
+ if (x < 1)
+ fun_l2_n286(x)
+ else
+ fun_l2_n586(x)
+ end
+end
+
+def fun_l1_n603(x)
+ if (x < 1)
+ fun_l2_n931(x)
+ else
+ fun_l2_n370(x)
+ end
+end
+
+def fun_l1_n604(x)
+ if (x < 1)
+ fun_l2_n311(x)
+ else
+ fun_l2_n476(x)
+ end
+end
+
+def fun_l1_n605(x)
+ if (x < 1)
+ fun_l2_n998(x)
+ else
+ fun_l2_n953(x)
+ end
+end
+
+def fun_l1_n606(x)
+ if (x < 1)
+ fun_l2_n782(x)
+ else
+ fun_l2_n225(x)
+ end
+end
+
+def fun_l1_n607(x)
+ if (x < 1)
+ fun_l2_n696(x)
+ else
+ fun_l2_n797(x)
+ end
+end
+
+def fun_l1_n608(x)
+ if (x < 1)
+ fun_l2_n344(x)
+ else
+ fun_l2_n247(x)
+ end
+end
+
+def fun_l1_n609(x)
+ if (x < 1)
+ fun_l2_n627(x)
+ else
+ fun_l2_n410(x)
+ end
+end
+
+def fun_l1_n610(x)
+ if (x < 1)
+ fun_l2_n431(x)
+ else
+ fun_l2_n56(x)
+ end
+end
+
+def fun_l1_n611(x)
+ if (x < 1)
+ fun_l2_n307(x)
+ else
+ fun_l2_n857(x)
+ end
+end
+
+def fun_l1_n612(x)
+ if (x < 1)
+ fun_l2_n411(x)
+ else
+ fun_l2_n59(x)
+ end
+end
+
+def fun_l1_n613(x)
+ if (x < 1)
+ fun_l2_n38(x)
+ else
+ fun_l2_n880(x)
+ end
+end
+
+def fun_l1_n614(x)
+ if (x < 1)
+ fun_l2_n945(x)
+ else
+ fun_l2_n723(x)
+ end
+end
+
+def fun_l1_n615(x)
+ if (x < 1)
+ fun_l2_n248(x)
+ else
+ fun_l2_n56(x)
+ end
+end
+
+def fun_l1_n616(x)
+ if (x < 1)
+ fun_l2_n453(x)
+ else
+ fun_l2_n4(x)
+ end
+end
+
+def fun_l1_n617(x)
+ if (x < 1)
+ fun_l2_n599(x)
+ else
+ fun_l2_n966(x)
+ end
+end
+
+def fun_l1_n618(x)
+ if (x < 1)
+ fun_l2_n896(x)
+ else
+ fun_l2_n666(x)
+ end
+end
+
+def fun_l1_n619(x)
+ if (x < 1)
+ fun_l2_n715(x)
+ else
+ fun_l2_n918(x)
+ end
+end
+
+def fun_l1_n620(x)
+ if (x < 1)
+ fun_l2_n663(x)
+ else
+ fun_l2_n144(x)
+ end
+end
+
+def fun_l1_n621(x)
+ if (x < 1)
+ fun_l2_n17(x)
+ else
+ fun_l2_n411(x)
+ end
+end
+
+def fun_l1_n622(x)
+ if (x < 1)
+ fun_l2_n851(x)
+ else
+ fun_l2_n858(x)
+ end
+end
+
+def fun_l1_n623(x)
+ if (x < 1)
+ fun_l2_n552(x)
+ else
+ fun_l2_n503(x)
+ end
+end
+
+def fun_l1_n624(x)
+ if (x < 1)
+ fun_l2_n822(x)
+ else
+ fun_l2_n239(x)
+ end
+end
+
+def fun_l1_n625(x)
+ if (x < 1)
+ fun_l2_n917(x)
+ else
+ fun_l2_n120(x)
+ end
+end
+
+def fun_l1_n626(x)
+ if (x < 1)
+ fun_l2_n640(x)
+ else
+ fun_l2_n603(x)
+ end
+end
+
+def fun_l1_n627(x)
+ if (x < 1)
+ fun_l2_n244(x)
+ else
+ fun_l2_n114(x)
+ end
+end
+
+def fun_l1_n628(x)
+ if (x < 1)
+ fun_l2_n374(x)
+ else
+ fun_l2_n295(x)
+ end
+end
+
+def fun_l1_n629(x)
+ if (x < 1)
+ fun_l2_n761(x)
+ else
+ fun_l2_n920(x)
+ end
+end
+
+def fun_l1_n630(x)
+ if (x < 1)
+ fun_l2_n314(x)
+ else
+ fun_l2_n571(x)
+ end
+end
+
+def fun_l1_n631(x)
+ if (x < 1)
+ fun_l2_n830(x)
+ else
+ fun_l2_n838(x)
+ end
+end
+
+def fun_l1_n632(x)
+ if (x < 1)
+ fun_l2_n523(x)
+ else
+ fun_l2_n453(x)
+ end
+end
+
+def fun_l1_n633(x)
+ if (x < 1)
+ fun_l2_n245(x)
+ else
+ fun_l2_n173(x)
+ end
+end
+
+def fun_l1_n634(x)
+ if (x < 1)
+ fun_l2_n939(x)
+ else
+ fun_l2_n774(x)
+ end
+end
+
+def fun_l1_n635(x)
+ if (x < 1)
+ fun_l2_n17(x)
+ else
+ fun_l2_n166(x)
+ end
+end
+
+def fun_l1_n636(x)
+ if (x < 1)
+ fun_l2_n443(x)
+ else
+ fun_l2_n297(x)
+ end
+end
+
+def fun_l1_n637(x)
+ if (x < 1)
+ fun_l2_n280(x)
+ else
+ fun_l2_n776(x)
+ end
+end
+
+def fun_l1_n638(x)
+ if (x < 1)
+ fun_l2_n761(x)
+ else
+ fun_l2_n866(x)
+ end
+end
+
+def fun_l1_n639(x)
+ if (x < 1)
+ fun_l2_n677(x)
+ else
+ fun_l2_n855(x)
+ end
+end
+
+def fun_l1_n640(x)
+ if (x < 1)
+ fun_l2_n252(x)
+ else
+ fun_l2_n766(x)
+ end
+end
+
+def fun_l1_n641(x)
+ if (x < 1)
+ fun_l2_n3(x)
+ else
+ fun_l2_n115(x)
+ end
+end
+
+def fun_l1_n642(x)
+ if (x < 1)
+ fun_l2_n495(x)
+ else
+ fun_l2_n340(x)
+ end
+end
+
+def fun_l1_n643(x)
+ if (x < 1)
+ fun_l2_n991(x)
+ else
+ fun_l2_n119(x)
+ end
+end
+
+def fun_l1_n644(x)
+ if (x < 1)
+ fun_l2_n379(x)
+ else
+ fun_l2_n519(x)
+ end
+end
+
+def fun_l1_n645(x)
+ if (x < 1)
+ fun_l2_n191(x)
+ else
+ fun_l2_n872(x)
+ end
+end
+
+def fun_l1_n646(x)
+ if (x < 1)
+ fun_l2_n979(x)
+ else
+ fun_l2_n980(x)
+ end
+end
+
+def fun_l1_n647(x)
+ if (x < 1)
+ fun_l2_n918(x)
+ else
+ fun_l2_n455(x)
+ end
+end
+
+def fun_l1_n648(x)
+ if (x < 1)
+ fun_l2_n966(x)
+ else
+ fun_l2_n529(x)
+ end
+end
+
+def fun_l1_n649(x)
+ if (x < 1)
+ fun_l2_n838(x)
+ else
+ fun_l2_n529(x)
+ end
+end
+
+def fun_l1_n650(x)
+ if (x < 1)
+ fun_l2_n542(x)
+ else
+ fun_l2_n42(x)
+ end
+end
+
+def fun_l1_n651(x)
+ if (x < 1)
+ fun_l2_n65(x)
+ else
+ fun_l2_n460(x)
+ end
+end
+
+def fun_l1_n652(x)
+ if (x < 1)
+ fun_l2_n479(x)
+ else
+ fun_l2_n251(x)
+ end
+end
+
+def fun_l1_n653(x)
+ if (x < 1)
+ fun_l2_n243(x)
+ else
+ fun_l2_n77(x)
+ end
+end
+
+def fun_l1_n654(x)
+ if (x < 1)
+ fun_l2_n392(x)
+ else
+ fun_l2_n940(x)
+ end
+end
+
+def fun_l1_n655(x)
+ if (x < 1)
+ fun_l2_n875(x)
+ else
+ fun_l2_n157(x)
+ end
+end
+
+def fun_l1_n656(x)
+ if (x < 1)
+ fun_l2_n279(x)
+ else
+ fun_l2_n237(x)
+ end
+end
+
+def fun_l1_n657(x)
+ if (x < 1)
+ fun_l2_n522(x)
+ else
+ fun_l2_n174(x)
+ end
+end
+
+def fun_l1_n658(x)
+ if (x < 1)
+ fun_l2_n669(x)
+ else
+ fun_l2_n399(x)
+ end
+end
+
+def fun_l1_n659(x)
+ if (x < 1)
+ fun_l2_n251(x)
+ else
+ fun_l2_n56(x)
+ end
+end
+
+def fun_l1_n660(x)
+ if (x < 1)
+ fun_l2_n563(x)
+ else
+ fun_l2_n731(x)
+ end
+end
+
+def fun_l1_n661(x)
+ if (x < 1)
+ fun_l2_n684(x)
+ else
+ fun_l2_n292(x)
+ end
+end
+
+def fun_l1_n662(x)
+ if (x < 1)
+ fun_l2_n952(x)
+ else
+ fun_l2_n1(x)
+ end
+end
+
+def fun_l1_n663(x)
+ if (x < 1)
+ fun_l2_n89(x)
+ else
+ fun_l2_n562(x)
+ end
+end
+
+def fun_l1_n664(x)
+ if (x < 1)
+ fun_l2_n480(x)
+ else
+ fun_l2_n488(x)
+ end
+end
+
+def fun_l1_n665(x)
+ if (x < 1)
+ fun_l2_n398(x)
+ else
+ fun_l2_n493(x)
+ end
+end
+
+def fun_l1_n666(x)
+ if (x < 1)
+ fun_l2_n778(x)
+ else
+ fun_l2_n702(x)
+ end
+end
+
+def fun_l1_n667(x)
+ if (x < 1)
+ fun_l2_n332(x)
+ else
+ fun_l2_n441(x)
+ end
+end
+
+def fun_l1_n668(x)
+ if (x < 1)
+ fun_l2_n866(x)
+ else
+ fun_l2_n442(x)
+ end
+end
+
+def fun_l1_n669(x)
+ if (x < 1)
+ fun_l2_n533(x)
+ else
+ fun_l2_n970(x)
+ end
+end
+
+def fun_l1_n670(x)
+ if (x < 1)
+ fun_l2_n926(x)
+ else
+ fun_l2_n883(x)
+ end
+end
+
+def fun_l1_n671(x)
+ if (x < 1)
+ fun_l2_n204(x)
+ else
+ fun_l2_n769(x)
+ end
+end
+
+def fun_l1_n672(x)
+ if (x < 1)
+ fun_l2_n663(x)
+ else
+ fun_l2_n367(x)
+ end
+end
+
+def fun_l1_n673(x)
+ if (x < 1)
+ fun_l2_n978(x)
+ else
+ fun_l2_n750(x)
+ end
+end
+
+def fun_l1_n674(x)
+ if (x < 1)
+ fun_l2_n296(x)
+ else
+ fun_l2_n608(x)
+ end
+end
+
+def fun_l1_n675(x)
+ if (x < 1)
+ fun_l2_n35(x)
+ else
+ fun_l2_n200(x)
+ end
+end
+
+def fun_l1_n676(x)
+ if (x < 1)
+ fun_l2_n618(x)
+ else
+ fun_l2_n286(x)
+ end
+end
+
+def fun_l1_n677(x)
+ if (x < 1)
+ fun_l2_n98(x)
+ else
+ fun_l2_n264(x)
+ end
+end
+
+def fun_l1_n678(x)
+ if (x < 1)
+ fun_l2_n967(x)
+ else
+ fun_l2_n884(x)
+ end
+end
+
+def fun_l1_n679(x)
+ if (x < 1)
+ fun_l2_n351(x)
+ else
+ fun_l2_n854(x)
+ end
+end
+
+def fun_l1_n680(x)
+ if (x < 1)
+ fun_l2_n397(x)
+ else
+ fun_l2_n56(x)
+ end
+end
+
+def fun_l1_n681(x)
+ if (x < 1)
+ fun_l2_n232(x)
+ else
+ fun_l2_n400(x)
+ end
+end
+
+def fun_l1_n682(x)
+ if (x < 1)
+ fun_l2_n321(x)
+ else
+ fun_l2_n500(x)
+ end
+end
+
+def fun_l1_n683(x)
+ if (x < 1)
+ fun_l2_n315(x)
+ else
+ fun_l2_n509(x)
+ end
+end
+
+def fun_l1_n684(x)
+ if (x < 1)
+ fun_l2_n854(x)
+ else
+ fun_l2_n921(x)
+ end
+end
+
+def fun_l1_n685(x)
+ if (x < 1)
+ fun_l2_n823(x)
+ else
+ fun_l2_n995(x)
+ end
+end
+
+def fun_l1_n686(x)
+ if (x < 1)
+ fun_l2_n42(x)
+ else
+ fun_l2_n92(x)
+ end
+end
+
+def fun_l1_n687(x)
+ if (x < 1)
+ fun_l2_n74(x)
+ else
+ fun_l2_n577(x)
+ end
+end
+
+def fun_l1_n688(x)
+ if (x < 1)
+ fun_l2_n47(x)
+ else
+ fun_l2_n664(x)
+ end
+end
+
+def fun_l1_n689(x)
+ if (x < 1)
+ fun_l2_n709(x)
+ else
+ fun_l2_n92(x)
+ end
+end
+
+def fun_l1_n690(x)
+ if (x < 1)
+ fun_l2_n875(x)
+ else
+ fun_l2_n893(x)
+ end
+end
+
+def fun_l1_n691(x)
+ if (x < 1)
+ fun_l2_n934(x)
+ else
+ fun_l2_n339(x)
+ end
+end
+
+def fun_l1_n692(x)
+ if (x < 1)
+ fun_l2_n194(x)
+ else
+ fun_l2_n915(x)
+ end
+end
+
+def fun_l1_n693(x)
+ if (x < 1)
+ fun_l2_n352(x)
+ else
+ fun_l2_n212(x)
+ end
+end
+
+def fun_l1_n694(x)
+ if (x < 1)
+ fun_l2_n554(x)
+ else
+ fun_l2_n461(x)
+ end
+end
+
+def fun_l1_n695(x)
+ if (x < 1)
+ fun_l2_n372(x)
+ else
+ fun_l2_n652(x)
+ end
+end
+
+def fun_l1_n696(x)
+ if (x < 1)
+ fun_l2_n778(x)
+ else
+ fun_l2_n350(x)
+ end
+end
+
+def fun_l1_n697(x)
+ if (x < 1)
+ fun_l2_n656(x)
+ else
+ fun_l2_n467(x)
+ end
+end
+
+def fun_l1_n698(x)
+ if (x < 1)
+ fun_l2_n799(x)
+ else
+ fun_l2_n983(x)
+ end
+end
+
+def fun_l1_n699(x)
+ if (x < 1)
+ fun_l2_n917(x)
+ else
+ fun_l2_n801(x)
+ end
+end
+
+def fun_l1_n700(x)
+ if (x < 1)
+ fun_l2_n276(x)
+ else
+ fun_l2_n778(x)
+ end
+end
+
+def fun_l1_n701(x)
+ if (x < 1)
+ fun_l2_n562(x)
+ else
+ fun_l2_n558(x)
+ end
+end
+
+def fun_l1_n702(x)
+ if (x < 1)
+ fun_l2_n600(x)
+ else
+ fun_l2_n120(x)
+ end
+end
+
+def fun_l1_n703(x)
+ if (x < 1)
+ fun_l2_n346(x)
+ else
+ fun_l2_n975(x)
+ end
+end
+
+def fun_l1_n704(x)
+ if (x < 1)
+ fun_l2_n139(x)
+ else
+ fun_l2_n241(x)
+ end
+end
+
+def fun_l1_n705(x)
+ if (x < 1)
+ fun_l2_n728(x)
+ else
+ fun_l2_n62(x)
+ end
+end
+
+def fun_l1_n706(x)
+ if (x < 1)
+ fun_l2_n719(x)
+ else
+ fun_l2_n955(x)
+ end
+end
+
+def fun_l1_n707(x)
+ if (x < 1)
+ fun_l2_n752(x)
+ else
+ fun_l2_n122(x)
+ end
+end
+
+def fun_l1_n708(x)
+ if (x < 1)
+ fun_l2_n456(x)
+ else
+ fun_l2_n128(x)
+ end
+end
+
+def fun_l1_n709(x)
+ if (x < 1)
+ fun_l2_n4(x)
+ else
+ fun_l2_n399(x)
+ end
+end
+
+def fun_l1_n710(x)
+ if (x < 1)
+ fun_l2_n20(x)
+ else
+ fun_l2_n746(x)
+ end
+end
+
+def fun_l1_n711(x)
+ if (x < 1)
+ fun_l2_n978(x)
+ else
+ fun_l2_n886(x)
+ end
+end
+
+def fun_l1_n712(x)
+ if (x < 1)
+ fun_l2_n417(x)
+ else
+ fun_l2_n337(x)
+ end
+end
+
+def fun_l1_n713(x)
+ if (x < 1)
+ fun_l2_n394(x)
+ else
+ fun_l2_n713(x)
+ end
+end
+
+def fun_l1_n714(x)
+ if (x < 1)
+ fun_l2_n433(x)
+ else
+ fun_l2_n985(x)
+ end
+end
+
+def fun_l1_n715(x)
+ if (x < 1)
+ fun_l2_n937(x)
+ else
+ fun_l2_n709(x)
+ end
+end
+
+def fun_l1_n716(x)
+ if (x < 1)
+ fun_l2_n963(x)
+ else
+ fun_l2_n842(x)
+ end
+end
+
+def fun_l1_n717(x)
+ if (x < 1)
+ fun_l2_n671(x)
+ else
+ fun_l2_n954(x)
+ end
+end
+
+def fun_l1_n718(x)
+ if (x < 1)
+ fun_l2_n948(x)
+ else
+ fun_l2_n128(x)
+ end
+end
+
+def fun_l1_n719(x)
+ if (x < 1)
+ fun_l2_n682(x)
+ else
+ fun_l2_n973(x)
+ end
+end
+
+def fun_l1_n720(x)
+ if (x < 1)
+ fun_l2_n336(x)
+ else
+ fun_l2_n643(x)
+ end
+end
+
+def fun_l1_n721(x)
+ if (x < 1)
+ fun_l2_n224(x)
+ else
+ fun_l2_n96(x)
+ end
+end
+
+def fun_l1_n722(x)
+ if (x < 1)
+ fun_l2_n907(x)
+ else
+ fun_l2_n776(x)
+ end
+end
+
+def fun_l1_n723(x)
+ if (x < 1)
+ fun_l2_n93(x)
+ else
+ fun_l2_n410(x)
+ end
+end
+
+def fun_l1_n724(x)
+ if (x < 1)
+ fun_l2_n282(x)
+ else
+ fun_l2_n134(x)
+ end
+end
+
+def fun_l1_n725(x)
+ if (x < 1)
+ fun_l2_n938(x)
+ else
+ fun_l2_n603(x)
+ end
+end
+
+def fun_l1_n726(x)
+ if (x < 1)
+ fun_l2_n574(x)
+ else
+ fun_l2_n976(x)
+ end
+end
+
+def fun_l1_n727(x)
+ if (x < 1)
+ fun_l2_n428(x)
+ else
+ fun_l2_n658(x)
+ end
+end
+
+def fun_l1_n728(x)
+ if (x < 1)
+ fun_l2_n828(x)
+ else
+ fun_l2_n226(x)
+ end
+end
+
+def fun_l1_n729(x)
+ if (x < 1)
+ fun_l2_n663(x)
+ else
+ fun_l2_n292(x)
+ end
+end
+
+def fun_l1_n730(x)
+ if (x < 1)
+ fun_l2_n802(x)
+ else
+ fun_l2_n853(x)
+ end
+end
+
+def fun_l1_n731(x)
+ if (x < 1)
+ fun_l2_n142(x)
+ else
+ fun_l2_n339(x)
+ end
+end
+
+def fun_l1_n732(x)
+ if (x < 1)
+ fun_l2_n211(x)
+ else
+ fun_l2_n35(x)
+ end
+end
+
+def fun_l1_n733(x)
+ if (x < 1)
+ fun_l2_n660(x)
+ else
+ fun_l2_n179(x)
+ end
+end
+
+def fun_l1_n734(x)
+ if (x < 1)
+ fun_l2_n174(x)
+ else
+ fun_l2_n224(x)
+ end
+end
+
+def fun_l1_n735(x)
+ if (x < 1)
+ fun_l2_n490(x)
+ else
+ fun_l2_n564(x)
+ end
+end
+
+def fun_l1_n736(x)
+ if (x < 1)
+ fun_l2_n597(x)
+ else
+ fun_l2_n153(x)
+ end
+end
+
+def fun_l1_n737(x)
+ if (x < 1)
+ fun_l2_n633(x)
+ else
+ fun_l2_n358(x)
+ end
+end
+
+def fun_l1_n738(x)
+ if (x < 1)
+ fun_l2_n0(x)
+ else
+ fun_l2_n858(x)
+ end
+end
+
+def fun_l1_n739(x)
+ if (x < 1)
+ fun_l2_n335(x)
+ else
+ fun_l2_n531(x)
+ end
+end
+
+def fun_l1_n740(x)
+ if (x < 1)
+ fun_l2_n736(x)
+ else
+ fun_l2_n653(x)
+ end
+end
+
+def fun_l1_n741(x)
+ if (x < 1)
+ fun_l2_n280(x)
+ else
+ fun_l2_n684(x)
+ end
+end
+
+def fun_l1_n742(x)
+ if (x < 1)
+ fun_l2_n976(x)
+ else
+ fun_l2_n987(x)
+ end
+end
+
+def fun_l1_n743(x)
+ if (x < 1)
+ fun_l2_n519(x)
+ else
+ fun_l2_n633(x)
+ end
+end
+
+def fun_l1_n744(x)
+ if (x < 1)
+ fun_l2_n314(x)
+ else
+ fun_l2_n579(x)
+ end
+end
+
+def fun_l1_n745(x)
+ if (x < 1)
+ fun_l2_n365(x)
+ else
+ fun_l2_n972(x)
+ end
+end
+
+def fun_l1_n746(x)
+ if (x < 1)
+ fun_l2_n902(x)
+ else
+ fun_l2_n715(x)
+ end
+end
+
+def fun_l1_n747(x)
+ if (x < 1)
+ fun_l2_n363(x)
+ else
+ fun_l2_n407(x)
+ end
+end
+
+def fun_l1_n748(x)
+ if (x < 1)
+ fun_l2_n660(x)
+ else
+ fun_l2_n814(x)
+ end
+end
+
+def fun_l1_n749(x)
+ if (x < 1)
+ fun_l2_n415(x)
+ else
+ fun_l2_n162(x)
+ end
+end
+
+def fun_l1_n750(x)
+ if (x < 1)
+ fun_l2_n157(x)
+ else
+ fun_l2_n406(x)
+ end
+end
+
+def fun_l1_n751(x)
+ if (x < 1)
+ fun_l2_n388(x)
+ else
+ fun_l2_n212(x)
+ end
+end
+
+def fun_l1_n752(x)
+ if (x < 1)
+ fun_l2_n733(x)
+ else
+ fun_l2_n283(x)
+ end
+end
+
+def fun_l1_n753(x)
+ if (x < 1)
+ fun_l2_n960(x)
+ else
+ fun_l2_n20(x)
+ end
+end
+
+def fun_l1_n754(x)
+ if (x < 1)
+ fun_l2_n797(x)
+ else
+ fun_l2_n202(x)
+ end
+end
+
+def fun_l1_n755(x)
+ if (x < 1)
+ fun_l2_n113(x)
+ else
+ fun_l2_n953(x)
+ end
+end
+
+def fun_l1_n756(x)
+ if (x < 1)
+ fun_l2_n84(x)
+ else
+ fun_l2_n390(x)
+ end
+end
+
+def fun_l1_n757(x)
+ if (x < 1)
+ fun_l2_n355(x)
+ else
+ fun_l2_n761(x)
+ end
+end
+
+def fun_l1_n758(x)
+ if (x < 1)
+ fun_l2_n823(x)
+ else
+ fun_l2_n37(x)
+ end
+end
+
+def fun_l1_n759(x)
+ if (x < 1)
+ fun_l2_n428(x)
+ else
+ fun_l2_n130(x)
+ end
+end
+
+def fun_l1_n760(x)
+ if (x < 1)
+ fun_l2_n364(x)
+ else
+ fun_l2_n680(x)
+ end
+end
+
+def fun_l1_n761(x)
+ if (x < 1)
+ fun_l2_n718(x)
+ else
+ fun_l2_n885(x)
+ end
+end
+
+def fun_l1_n762(x)
+ if (x < 1)
+ fun_l2_n795(x)
+ else
+ fun_l2_n342(x)
+ end
+end
+
+def fun_l1_n763(x)
+ if (x < 1)
+ fun_l2_n561(x)
+ else
+ fun_l2_n593(x)
+ end
+end
+
+def fun_l1_n764(x)
+ if (x < 1)
+ fun_l2_n714(x)
+ else
+ fun_l2_n168(x)
+ end
+end
+
+def fun_l1_n765(x)
+ if (x < 1)
+ fun_l2_n377(x)
+ else
+ fun_l2_n109(x)
+ end
+end
+
+def fun_l1_n766(x)
+ if (x < 1)
+ fun_l2_n477(x)
+ else
+ fun_l2_n871(x)
+ end
+end
+
+def fun_l1_n767(x)
+ if (x < 1)
+ fun_l2_n596(x)
+ else
+ fun_l2_n81(x)
+ end
+end
+
+def fun_l1_n768(x)
+ if (x < 1)
+ fun_l2_n609(x)
+ else
+ fun_l2_n454(x)
+ end
+end
+
+def fun_l1_n769(x)
+ if (x < 1)
+ fun_l2_n308(x)
+ else
+ fun_l2_n890(x)
+ end
+end
+
+def fun_l1_n770(x)
+ if (x < 1)
+ fun_l2_n761(x)
+ else
+ fun_l2_n342(x)
+ end
+end
+
+def fun_l1_n771(x)
+ if (x < 1)
+ fun_l2_n44(x)
+ else
+ fun_l2_n1(x)
+ end
+end
+
+def fun_l1_n772(x)
+ if (x < 1)
+ fun_l2_n457(x)
+ else
+ fun_l2_n571(x)
+ end
+end
+
+def fun_l1_n773(x)
+ if (x < 1)
+ fun_l2_n88(x)
+ else
+ fun_l2_n622(x)
+ end
+end
+
+def fun_l1_n774(x)
+ if (x < 1)
+ fun_l2_n459(x)
+ else
+ fun_l2_n446(x)
+ end
+end
+
+def fun_l1_n775(x)
+ if (x < 1)
+ fun_l2_n400(x)
+ else
+ fun_l2_n918(x)
+ end
+end
+
+def fun_l1_n776(x)
+ if (x < 1)
+ fun_l2_n752(x)
+ else
+ fun_l2_n696(x)
+ end
+end
+
+def fun_l1_n777(x)
+ if (x < 1)
+ fun_l2_n968(x)
+ else
+ fun_l2_n988(x)
+ end
+end
+
+def fun_l1_n778(x)
+ if (x < 1)
+ fun_l2_n242(x)
+ else
+ fun_l2_n496(x)
+ end
+end
+
+def fun_l1_n779(x)
+ if (x < 1)
+ fun_l2_n106(x)
+ else
+ fun_l2_n637(x)
+ end
+end
+
+def fun_l1_n780(x)
+ if (x < 1)
+ fun_l2_n945(x)
+ else
+ fun_l2_n238(x)
+ end
+end
+
+def fun_l1_n781(x)
+ if (x < 1)
+ fun_l2_n269(x)
+ else
+ fun_l2_n582(x)
+ end
+end
+
+def fun_l1_n782(x)
+ if (x < 1)
+ fun_l2_n523(x)
+ else
+ fun_l2_n201(x)
+ end
+end
+
+def fun_l1_n783(x)
+ if (x < 1)
+ fun_l2_n326(x)
+ else
+ fun_l2_n744(x)
+ end
+end
+
+def fun_l1_n784(x)
+ if (x < 1)
+ fun_l2_n49(x)
+ else
+ fun_l2_n943(x)
+ end
+end
+
+def fun_l1_n785(x)
+ if (x < 1)
+ fun_l2_n975(x)
+ else
+ fun_l2_n560(x)
+ end
+end
+
+def fun_l1_n786(x)
+ if (x < 1)
+ fun_l2_n843(x)
+ else
+ fun_l2_n240(x)
+ end
+end
+
+def fun_l1_n787(x)
+ if (x < 1)
+ fun_l2_n179(x)
+ else
+ fun_l2_n423(x)
+ end
+end
+
+def fun_l1_n788(x)
+ if (x < 1)
+ fun_l2_n536(x)
+ else
+ fun_l2_n112(x)
+ end
+end
+
+def fun_l1_n789(x)
+ if (x < 1)
+ fun_l2_n418(x)
+ else
+ fun_l2_n443(x)
+ end
+end
+
+def fun_l1_n790(x)
+ if (x < 1)
+ fun_l2_n770(x)
+ else
+ fun_l2_n127(x)
+ end
+end
+
+def fun_l1_n791(x)
+ if (x < 1)
+ fun_l2_n425(x)
+ else
+ fun_l2_n364(x)
+ end
+end
+
+def fun_l1_n792(x)
+ if (x < 1)
+ fun_l2_n841(x)
+ else
+ fun_l2_n112(x)
+ end
+end
+
+def fun_l1_n793(x)
+ if (x < 1)
+ fun_l2_n64(x)
+ else
+ fun_l2_n294(x)
+ end
+end
+
+def fun_l1_n794(x)
+ if (x < 1)
+ fun_l2_n837(x)
+ else
+ fun_l2_n325(x)
+ end
+end
+
+def fun_l1_n795(x)
+ if (x < 1)
+ fun_l2_n522(x)
+ else
+ fun_l2_n307(x)
+ end
+end
+
+def fun_l1_n796(x)
+ if (x < 1)
+ fun_l2_n526(x)
+ else
+ fun_l2_n957(x)
+ end
+end
+
+def fun_l1_n797(x)
+ if (x < 1)
+ fun_l2_n71(x)
+ else
+ fun_l2_n871(x)
+ end
+end
+
+def fun_l1_n798(x)
+ if (x < 1)
+ fun_l2_n386(x)
+ else
+ fun_l2_n354(x)
+ end
+end
+
+def fun_l1_n799(x)
+ if (x < 1)
+ fun_l2_n669(x)
+ else
+ fun_l2_n237(x)
+ end
+end
+
+def fun_l1_n800(x)
+ if (x < 1)
+ fun_l2_n455(x)
+ else
+ fun_l2_n549(x)
+ end
+end
+
+def fun_l1_n801(x)
+ if (x < 1)
+ fun_l2_n708(x)
+ else
+ fun_l2_n611(x)
+ end
+end
+
+def fun_l1_n802(x)
+ if (x < 1)
+ fun_l2_n35(x)
+ else
+ fun_l2_n239(x)
+ end
+end
+
+def fun_l1_n803(x)
+ if (x < 1)
+ fun_l2_n890(x)
+ else
+ fun_l2_n27(x)
+ end
+end
+
+def fun_l1_n804(x)
+ if (x < 1)
+ fun_l2_n378(x)
+ else
+ fun_l2_n567(x)
+ end
+end
+
+def fun_l1_n805(x)
+ if (x < 1)
+ fun_l2_n672(x)
+ else
+ fun_l2_n320(x)
+ end
+end
+
+def fun_l1_n806(x)
+ if (x < 1)
+ fun_l2_n207(x)
+ else
+ fun_l2_n691(x)
+ end
+end
+
+def fun_l1_n807(x)
+ if (x < 1)
+ fun_l2_n180(x)
+ else
+ fun_l2_n912(x)
+ end
+end
+
+def fun_l1_n808(x)
+ if (x < 1)
+ fun_l2_n370(x)
+ else
+ fun_l2_n529(x)
+ end
+end
+
+def fun_l1_n809(x)
+ if (x < 1)
+ fun_l2_n436(x)
+ else
+ fun_l2_n465(x)
+ end
+end
+
+def fun_l1_n810(x)
+ if (x < 1)
+ fun_l2_n820(x)
+ else
+ fun_l2_n995(x)
+ end
+end
+
+def fun_l1_n811(x)
+ if (x < 1)
+ fun_l2_n821(x)
+ else
+ fun_l2_n898(x)
+ end
+end
+
+def fun_l1_n812(x)
+ if (x < 1)
+ fun_l2_n376(x)
+ else
+ fun_l2_n999(x)
+ end
+end
+
+def fun_l1_n813(x)
+ if (x < 1)
+ fun_l2_n643(x)
+ else
+ fun_l2_n478(x)
+ end
+end
+
+def fun_l1_n814(x)
+ if (x < 1)
+ fun_l2_n475(x)
+ else
+ fun_l2_n137(x)
+ end
+end
+
+def fun_l1_n815(x)
+ if (x < 1)
+ fun_l2_n117(x)
+ else
+ fun_l2_n685(x)
+ end
+end
+
+def fun_l1_n816(x)
+ if (x < 1)
+ fun_l2_n451(x)
+ else
+ fun_l2_n643(x)
+ end
+end
+
+def fun_l1_n817(x)
+ if (x < 1)
+ fun_l2_n22(x)
+ else
+ fun_l2_n939(x)
+ end
+end
+
+def fun_l1_n818(x)
+ if (x < 1)
+ fun_l2_n586(x)
+ else
+ fun_l2_n206(x)
+ end
+end
+
+def fun_l1_n819(x)
+ if (x < 1)
+ fun_l2_n443(x)
+ else
+ fun_l2_n661(x)
+ end
+end
+
+def fun_l1_n820(x)
+ if (x < 1)
+ fun_l2_n656(x)
+ else
+ fun_l2_n93(x)
+ end
+end
+
+def fun_l1_n821(x)
+ if (x < 1)
+ fun_l2_n794(x)
+ else
+ fun_l2_n354(x)
+ end
+end
+
+def fun_l1_n822(x)
+ if (x < 1)
+ fun_l2_n519(x)
+ else
+ fun_l2_n446(x)
+ end
+end
+
+def fun_l1_n823(x)
+ if (x < 1)
+ fun_l2_n0(x)
+ else
+ fun_l2_n233(x)
+ end
+end
+
+def fun_l1_n824(x)
+ if (x < 1)
+ fun_l2_n376(x)
+ else
+ fun_l2_n186(x)
+ end
+end
+
+def fun_l1_n825(x)
+ if (x < 1)
+ fun_l2_n292(x)
+ else
+ fun_l2_n303(x)
+ end
+end
+
+def fun_l1_n826(x)
+ if (x < 1)
+ fun_l2_n871(x)
+ else
+ fun_l2_n515(x)
+ end
+end
+
+def fun_l1_n827(x)
+ if (x < 1)
+ fun_l2_n227(x)
+ else
+ fun_l2_n232(x)
+ end
+end
+
+def fun_l1_n828(x)
+ if (x < 1)
+ fun_l2_n860(x)
+ else
+ fun_l2_n341(x)
+ end
+end
+
+def fun_l1_n829(x)
+ if (x < 1)
+ fun_l2_n140(x)
+ else
+ fun_l2_n304(x)
+ end
+end
+
+def fun_l1_n830(x)
+ if (x < 1)
+ fun_l2_n796(x)
+ else
+ fun_l2_n943(x)
+ end
+end
+
+def fun_l1_n831(x)
+ if (x < 1)
+ fun_l2_n71(x)
+ else
+ fun_l2_n8(x)
+ end
+end
+
+def fun_l1_n832(x)
+ if (x < 1)
+ fun_l2_n328(x)
+ else
+ fun_l2_n836(x)
+ end
+end
+
+def fun_l1_n833(x)
+ if (x < 1)
+ fun_l2_n322(x)
+ else
+ fun_l2_n653(x)
+ end
+end
+
+def fun_l1_n834(x)
+ if (x < 1)
+ fun_l2_n471(x)
+ else
+ fun_l2_n147(x)
+ end
+end
+
+def fun_l1_n835(x)
+ if (x < 1)
+ fun_l2_n601(x)
+ else
+ fun_l2_n249(x)
+ end
+end
+
+def fun_l1_n836(x)
+ if (x < 1)
+ fun_l2_n105(x)
+ else
+ fun_l2_n63(x)
+ end
+end
+
+def fun_l1_n837(x)
+ if (x < 1)
+ fun_l2_n773(x)
+ else
+ fun_l2_n597(x)
+ end
+end
+
+def fun_l1_n838(x)
+ if (x < 1)
+ fun_l2_n933(x)
+ else
+ fun_l2_n964(x)
+ end
+end
+
+def fun_l1_n839(x)
+ if (x < 1)
+ fun_l2_n123(x)
+ else
+ fun_l2_n533(x)
+ end
+end
+
+def fun_l1_n840(x)
+ if (x < 1)
+ fun_l2_n94(x)
+ else
+ fun_l2_n127(x)
+ end
+end
+
+def fun_l1_n841(x)
+ if (x < 1)
+ fun_l2_n981(x)
+ else
+ fun_l2_n819(x)
+ end
+end
+
+def fun_l1_n842(x)
+ if (x < 1)
+ fun_l2_n743(x)
+ else
+ fun_l2_n747(x)
+ end
+end
+
+def fun_l1_n843(x)
+ if (x < 1)
+ fun_l2_n735(x)
+ else
+ fun_l2_n110(x)
+ end
+end
+
+def fun_l1_n844(x)
+ if (x < 1)
+ fun_l2_n273(x)
+ else
+ fun_l2_n753(x)
+ end
+end
+
+def fun_l1_n845(x)
+ if (x < 1)
+ fun_l2_n316(x)
+ else
+ fun_l2_n391(x)
+ end
+end
+
+def fun_l1_n846(x)
+ if (x < 1)
+ fun_l2_n221(x)
+ else
+ fun_l2_n251(x)
+ end
+end
+
+def fun_l1_n847(x)
+ if (x < 1)
+ fun_l2_n795(x)
+ else
+ fun_l2_n513(x)
+ end
+end
+
+def fun_l1_n848(x)
+ if (x < 1)
+ fun_l2_n986(x)
+ else
+ fun_l2_n472(x)
+ end
+end
+
+def fun_l1_n849(x)
+ if (x < 1)
+ fun_l2_n863(x)
+ else
+ fun_l2_n759(x)
+ end
+end
+
+def fun_l1_n850(x)
+ if (x < 1)
+ fun_l2_n512(x)
+ else
+ fun_l2_n502(x)
+ end
+end
+
+def fun_l1_n851(x)
+ if (x < 1)
+ fun_l2_n561(x)
+ else
+ fun_l2_n697(x)
+ end
+end
+
+def fun_l1_n852(x)
+ if (x < 1)
+ fun_l2_n816(x)
+ else
+ fun_l2_n90(x)
+ end
+end
+
+def fun_l1_n853(x)
+ if (x < 1)
+ fun_l2_n656(x)
+ else
+ fun_l2_n174(x)
+ end
+end
+
+def fun_l1_n854(x)
+ if (x < 1)
+ fun_l2_n439(x)
+ else
+ fun_l2_n90(x)
+ end
+end
+
+def fun_l1_n855(x)
+ if (x < 1)
+ fun_l2_n15(x)
+ else
+ fun_l2_n402(x)
+ end
+end
+
+def fun_l1_n856(x)
+ if (x < 1)
+ fun_l2_n224(x)
+ else
+ fun_l2_n177(x)
+ end
+end
+
+def fun_l1_n857(x)
+ if (x < 1)
+ fun_l2_n675(x)
+ else
+ fun_l2_n113(x)
+ end
+end
+
+def fun_l1_n858(x)
+ if (x < 1)
+ fun_l2_n388(x)
+ else
+ fun_l2_n529(x)
+ end
+end
+
+def fun_l1_n859(x)
+ if (x < 1)
+ fun_l2_n628(x)
+ else
+ fun_l2_n93(x)
+ end
+end
+
+def fun_l1_n860(x)
+ if (x < 1)
+ fun_l2_n67(x)
+ else
+ fun_l2_n90(x)
+ end
+end
+
+def fun_l1_n861(x)
+ if (x < 1)
+ fun_l2_n637(x)
+ else
+ fun_l2_n68(x)
+ end
+end
+
+def fun_l1_n862(x)
+ if (x < 1)
+ fun_l2_n767(x)
+ else
+ fun_l2_n86(x)
+ end
+end
+
+def fun_l1_n863(x)
+ if (x < 1)
+ fun_l2_n50(x)
+ else
+ fun_l2_n777(x)
+ end
+end
+
+def fun_l1_n864(x)
+ if (x < 1)
+ fun_l2_n846(x)
+ else
+ fun_l2_n783(x)
+ end
+end
+
+def fun_l1_n865(x)
+ if (x < 1)
+ fun_l2_n756(x)
+ else
+ fun_l2_n703(x)
+ end
+end
+
+def fun_l1_n866(x)
+ if (x < 1)
+ fun_l2_n972(x)
+ else
+ fun_l2_n249(x)
+ end
+end
+
+def fun_l1_n867(x)
+ if (x < 1)
+ fun_l2_n636(x)
+ else
+ fun_l2_n841(x)
+ end
+end
+
+def fun_l1_n868(x)
+ if (x < 1)
+ fun_l2_n889(x)
+ else
+ fun_l2_n899(x)
+ end
+end
+
+def fun_l1_n869(x)
+ if (x < 1)
+ fun_l2_n55(x)
+ else
+ fun_l2_n45(x)
+ end
+end
+
+def fun_l1_n870(x)
+ if (x < 1)
+ fun_l2_n740(x)
+ else
+ fun_l2_n722(x)
+ end
+end
+
+def fun_l1_n871(x)
+ if (x < 1)
+ fun_l2_n865(x)
+ else
+ fun_l2_n695(x)
+ end
+end
+
+def fun_l1_n872(x)
+ if (x < 1)
+ fun_l2_n54(x)
+ else
+ fun_l2_n581(x)
+ end
+end
+
+def fun_l1_n873(x)
+ if (x < 1)
+ fun_l2_n328(x)
+ else
+ fun_l2_n861(x)
+ end
+end
+
+def fun_l1_n874(x)
+ if (x < 1)
+ fun_l2_n645(x)
+ else
+ fun_l2_n121(x)
+ end
+end
+
+def fun_l1_n875(x)
+ if (x < 1)
+ fun_l2_n71(x)
+ else
+ fun_l2_n329(x)
+ end
+end
+
+def fun_l1_n876(x)
+ if (x < 1)
+ fun_l2_n944(x)
+ else
+ fun_l2_n95(x)
+ end
+end
+
+def fun_l1_n877(x)
+ if (x < 1)
+ fun_l2_n270(x)
+ else
+ fun_l2_n801(x)
+ end
+end
+
+def fun_l1_n878(x)
+ if (x < 1)
+ fun_l2_n115(x)
+ else
+ fun_l2_n414(x)
+ end
+end
+
+def fun_l1_n879(x)
+ if (x < 1)
+ fun_l2_n154(x)
+ else
+ fun_l2_n605(x)
+ end
+end
+
+def fun_l1_n880(x)
+ if (x < 1)
+ fun_l2_n859(x)
+ else
+ fun_l2_n307(x)
+ end
+end
+
+def fun_l1_n881(x)
+ if (x < 1)
+ fun_l2_n443(x)
+ else
+ fun_l2_n267(x)
+ end
+end
+
+def fun_l1_n882(x)
+ if (x < 1)
+ fun_l2_n280(x)
+ else
+ fun_l2_n175(x)
+ end
+end
+
+def fun_l1_n883(x)
+ if (x < 1)
+ fun_l2_n176(x)
+ else
+ fun_l2_n286(x)
+ end
+end
+
+def fun_l1_n884(x)
+ if (x < 1)
+ fun_l2_n422(x)
+ else
+ fun_l2_n469(x)
+ end
+end
+
+def fun_l1_n885(x)
+ if (x < 1)
+ fun_l2_n532(x)
+ else
+ fun_l2_n795(x)
+ end
+end
+
+def fun_l1_n886(x)
+ if (x < 1)
+ fun_l2_n966(x)
+ else
+ fun_l2_n46(x)
+ end
+end
+
+def fun_l1_n887(x)
+ if (x < 1)
+ fun_l2_n446(x)
+ else
+ fun_l2_n944(x)
+ end
+end
+
+def fun_l1_n888(x)
+ if (x < 1)
+ fun_l2_n256(x)
+ else
+ fun_l2_n757(x)
+ end
+end
+
+def fun_l1_n889(x)
+ if (x < 1)
+ fun_l2_n566(x)
+ else
+ fun_l2_n992(x)
+ end
+end
+
+def fun_l1_n890(x)
+ if (x < 1)
+ fun_l2_n55(x)
+ else
+ fun_l2_n121(x)
+ end
+end
+
+def fun_l1_n891(x)
+ if (x < 1)
+ fun_l2_n597(x)
+ else
+ fun_l2_n257(x)
+ end
+end
+
+def fun_l1_n892(x)
+ if (x < 1)
+ fun_l2_n79(x)
+ else
+ fun_l2_n249(x)
+ end
+end
+
+def fun_l1_n893(x)
+ if (x < 1)
+ fun_l2_n436(x)
+ else
+ fun_l2_n738(x)
+ end
+end
+
+def fun_l1_n894(x)
+ if (x < 1)
+ fun_l2_n244(x)
+ else
+ fun_l2_n184(x)
+ end
+end
+
+def fun_l1_n895(x)
+ if (x < 1)
+ fun_l2_n342(x)
+ else
+ fun_l2_n794(x)
+ end
+end
+
+def fun_l1_n896(x)
+ if (x < 1)
+ fun_l2_n588(x)
+ else
+ fun_l2_n235(x)
+ end
+end
+
+def fun_l1_n897(x)
+ if (x < 1)
+ fun_l2_n443(x)
+ else
+ fun_l2_n462(x)
+ end
+end
+
+def fun_l1_n898(x)
+ if (x < 1)
+ fun_l2_n986(x)
+ else
+ fun_l2_n282(x)
+ end
+end
+
+def fun_l1_n899(x)
+ if (x < 1)
+ fun_l2_n61(x)
+ else
+ fun_l2_n516(x)
+ end
+end
+
+def fun_l1_n900(x)
+ if (x < 1)
+ fun_l2_n993(x)
+ else
+ fun_l2_n337(x)
+ end
+end
+
+def fun_l1_n901(x)
+ if (x < 1)
+ fun_l2_n398(x)
+ else
+ fun_l2_n425(x)
+ end
+end
+
+def fun_l1_n902(x)
+ if (x < 1)
+ fun_l2_n177(x)
+ else
+ fun_l2_n741(x)
+ end
+end
+
+def fun_l1_n903(x)
+ if (x < 1)
+ fun_l2_n597(x)
+ else
+ fun_l2_n331(x)
+ end
+end
+
+def fun_l1_n904(x)
+ if (x < 1)
+ fun_l2_n740(x)
+ else
+ fun_l2_n527(x)
+ end
+end
+
+def fun_l1_n905(x)
+ if (x < 1)
+ fun_l2_n138(x)
+ else
+ fun_l2_n248(x)
+ end
+end
+
+def fun_l1_n906(x)
+ if (x < 1)
+ fun_l2_n318(x)
+ else
+ fun_l2_n941(x)
+ end
+end
+
+def fun_l1_n907(x)
+ if (x < 1)
+ fun_l2_n493(x)
+ else
+ fun_l2_n376(x)
+ end
+end
+
+def fun_l1_n908(x)
+ if (x < 1)
+ fun_l2_n899(x)
+ else
+ fun_l2_n745(x)
+ end
+end
+
+def fun_l1_n909(x)
+ if (x < 1)
+ fun_l2_n963(x)
+ else
+ fun_l2_n384(x)
+ end
+end
+
+def fun_l1_n910(x)
+ if (x < 1)
+ fun_l2_n490(x)
+ else
+ fun_l2_n702(x)
+ end
+end
+
+def fun_l1_n911(x)
+ if (x < 1)
+ fun_l2_n712(x)
+ else
+ fun_l2_n810(x)
+ end
+end
+
+def fun_l1_n912(x)
+ if (x < 1)
+ fun_l2_n245(x)
+ else
+ fun_l2_n609(x)
+ end
+end
+
+def fun_l1_n913(x)
+ if (x < 1)
+ fun_l2_n997(x)
+ else
+ fun_l2_n241(x)
+ end
+end
+
+def fun_l1_n914(x)
+ if (x < 1)
+ fun_l2_n428(x)
+ else
+ fun_l2_n697(x)
+ end
+end
+
+def fun_l1_n915(x)
+ if (x < 1)
+ fun_l2_n257(x)
+ else
+ fun_l2_n626(x)
+ end
+end
+
+def fun_l1_n916(x)
+ if (x < 1)
+ fun_l2_n378(x)
+ else
+ fun_l2_n457(x)
+ end
+end
+
+def fun_l1_n917(x)
+ if (x < 1)
+ fun_l2_n378(x)
+ else
+ fun_l2_n958(x)
+ end
+end
+
+def fun_l1_n918(x)
+ if (x < 1)
+ fun_l2_n213(x)
+ else
+ fun_l2_n962(x)
+ end
+end
+
+def fun_l1_n919(x)
+ if (x < 1)
+ fun_l2_n466(x)
+ else
+ fun_l2_n461(x)
+ end
+end
+
+def fun_l1_n920(x)
+ if (x < 1)
+ fun_l2_n835(x)
+ else
+ fun_l2_n460(x)
+ end
+end
+
+def fun_l1_n921(x)
+ if (x < 1)
+ fun_l2_n642(x)
+ else
+ fun_l2_n680(x)
+ end
+end
+
+def fun_l1_n922(x)
+ if (x < 1)
+ fun_l2_n467(x)
+ else
+ fun_l2_n225(x)
+ end
+end
+
+def fun_l1_n923(x)
+ if (x < 1)
+ fun_l2_n752(x)
+ else
+ fun_l2_n462(x)
+ end
+end
+
+def fun_l1_n924(x)
+ if (x < 1)
+ fun_l2_n113(x)
+ else
+ fun_l2_n59(x)
+ end
+end
+
+def fun_l1_n925(x)
+ if (x < 1)
+ fun_l2_n329(x)
+ else
+ fun_l2_n994(x)
+ end
+end
+
+def fun_l1_n926(x)
+ if (x < 1)
+ fun_l2_n815(x)
+ else
+ fun_l2_n249(x)
+ end
+end
+
+def fun_l1_n927(x)
+ if (x < 1)
+ fun_l2_n216(x)
+ else
+ fun_l2_n591(x)
+ end
+end
+
+def fun_l1_n928(x)
+ if (x < 1)
+ fun_l2_n441(x)
+ else
+ fun_l2_n437(x)
+ end
+end
+
+def fun_l1_n929(x)
+ if (x < 1)
+ fun_l2_n433(x)
+ else
+ fun_l2_n185(x)
+ end
+end
+
+def fun_l1_n930(x)
+ if (x < 1)
+ fun_l2_n125(x)
+ else
+ fun_l2_n940(x)
+ end
+end
+
+def fun_l1_n931(x)
+ if (x < 1)
+ fun_l2_n203(x)
+ else
+ fun_l2_n292(x)
+ end
+end
+
+def fun_l1_n932(x)
+ if (x < 1)
+ fun_l2_n986(x)
+ else
+ fun_l2_n234(x)
+ end
+end
+
+def fun_l1_n933(x)
+ if (x < 1)
+ fun_l2_n735(x)
+ else
+ fun_l2_n20(x)
+ end
+end
+
+def fun_l1_n934(x)
+ if (x < 1)
+ fun_l2_n878(x)
+ else
+ fun_l2_n166(x)
+ end
+end
+
+def fun_l1_n935(x)
+ if (x < 1)
+ fun_l2_n123(x)
+ else
+ fun_l2_n52(x)
+ end
+end
+
+def fun_l1_n936(x)
+ if (x < 1)
+ fun_l2_n99(x)
+ else
+ fun_l2_n336(x)
+ end
+end
+
+def fun_l1_n937(x)
+ if (x < 1)
+ fun_l2_n731(x)
+ else
+ fun_l2_n363(x)
+ end
+end
+
+def fun_l1_n938(x)
+ if (x < 1)
+ fun_l2_n988(x)
+ else
+ fun_l2_n978(x)
+ end
+end
+
+def fun_l1_n939(x)
+ if (x < 1)
+ fun_l2_n592(x)
+ else
+ fun_l2_n932(x)
+ end
+end
+
+def fun_l1_n940(x)
+ if (x < 1)
+ fun_l2_n681(x)
+ else
+ fun_l2_n868(x)
+ end
+end
+
+def fun_l1_n941(x)
+ if (x < 1)
+ fun_l2_n863(x)
+ else
+ fun_l2_n457(x)
+ end
+end
+
+def fun_l1_n942(x)
+ if (x < 1)
+ fun_l2_n526(x)
+ else
+ fun_l2_n960(x)
+ end
+end
+
+def fun_l1_n943(x)
+ if (x < 1)
+ fun_l2_n859(x)
+ else
+ fun_l2_n478(x)
+ end
+end
+
+def fun_l1_n944(x)
+ if (x < 1)
+ fun_l2_n947(x)
+ else
+ fun_l2_n889(x)
+ end
+end
+
+def fun_l1_n945(x)
+ if (x < 1)
+ fun_l2_n845(x)
+ else
+ fun_l2_n211(x)
+ end
+end
+
+def fun_l1_n946(x)
+ if (x < 1)
+ fun_l2_n445(x)
+ else
+ fun_l2_n600(x)
+ end
+end
+
+def fun_l1_n947(x)
+ if (x < 1)
+ fun_l2_n932(x)
+ else
+ fun_l2_n534(x)
+ end
+end
+
+def fun_l1_n948(x)
+ if (x < 1)
+ fun_l2_n224(x)
+ else
+ fun_l2_n32(x)
+ end
+end
+
+def fun_l1_n949(x)
+ if (x < 1)
+ fun_l2_n63(x)
+ else
+ fun_l2_n121(x)
+ end
+end
+
+def fun_l1_n950(x)
+ if (x < 1)
+ fun_l2_n55(x)
+ else
+ fun_l2_n90(x)
+ end
+end
+
+def fun_l1_n951(x)
+ if (x < 1)
+ fun_l2_n880(x)
+ else
+ fun_l2_n936(x)
+ end
+end
+
+def fun_l1_n952(x)
+ if (x < 1)
+ fun_l2_n971(x)
+ else
+ fun_l2_n40(x)
+ end
+end
+
+def fun_l1_n953(x)
+ if (x < 1)
+ fun_l2_n880(x)
+ else
+ fun_l2_n200(x)
+ end
+end
+
+def fun_l1_n954(x)
+ if (x < 1)
+ fun_l2_n60(x)
+ else
+ fun_l2_n473(x)
+ end
+end
+
+def fun_l1_n955(x)
+ if (x < 1)
+ fun_l2_n855(x)
+ else
+ fun_l2_n601(x)
+ end
+end
+
+def fun_l1_n956(x)
+ if (x < 1)
+ fun_l2_n282(x)
+ else
+ fun_l2_n542(x)
+ end
+end
+
+def fun_l1_n957(x)
+ if (x < 1)
+ fun_l2_n116(x)
+ else
+ fun_l2_n584(x)
+ end
+end
+
+def fun_l1_n958(x)
+ if (x < 1)
+ fun_l2_n845(x)
+ else
+ fun_l2_n814(x)
+ end
+end
+
+def fun_l1_n959(x)
+ if (x < 1)
+ fun_l2_n443(x)
+ else
+ fun_l2_n239(x)
+ end
+end
+
+def fun_l1_n960(x)
+ if (x < 1)
+ fun_l2_n79(x)
+ else
+ fun_l2_n556(x)
+ end
+end
+
+def fun_l1_n961(x)
+ if (x < 1)
+ fun_l2_n664(x)
+ else
+ fun_l2_n282(x)
+ end
+end
+
+def fun_l1_n962(x)
+ if (x < 1)
+ fun_l2_n273(x)
+ else
+ fun_l2_n393(x)
+ end
+end
+
+def fun_l1_n963(x)
+ if (x < 1)
+ fun_l2_n120(x)
+ else
+ fun_l2_n506(x)
+ end
+end
+
+def fun_l1_n964(x)
+ if (x < 1)
+ fun_l2_n362(x)
+ else
+ fun_l2_n631(x)
+ end
+end
+
+def fun_l1_n965(x)
+ if (x < 1)
+ fun_l2_n219(x)
+ else
+ fun_l2_n260(x)
+ end
+end
+
+def fun_l1_n966(x)
+ if (x < 1)
+ fun_l2_n802(x)
+ else
+ fun_l2_n732(x)
+ end
+end
+
+def fun_l1_n967(x)
+ if (x < 1)
+ fun_l2_n761(x)
+ else
+ fun_l2_n580(x)
+ end
+end
+
+def fun_l1_n968(x)
+ if (x < 1)
+ fun_l2_n529(x)
+ else
+ fun_l2_n783(x)
+ end
+end
+
+def fun_l1_n969(x)
+ if (x < 1)
+ fun_l2_n138(x)
+ else
+ fun_l2_n434(x)
+ end
+end
+
+def fun_l1_n970(x)
+ if (x < 1)
+ fun_l2_n266(x)
+ else
+ fun_l2_n522(x)
+ end
+end
+
+def fun_l1_n971(x)
+ if (x < 1)
+ fun_l2_n352(x)
+ else
+ fun_l2_n51(x)
+ end
+end
+
+def fun_l1_n972(x)
+ if (x < 1)
+ fun_l2_n619(x)
+ else
+ fun_l2_n68(x)
+ end
+end
+
+def fun_l1_n973(x)
+ if (x < 1)
+ fun_l2_n510(x)
+ else
+ fun_l2_n74(x)
+ end
+end
+
+def fun_l1_n974(x)
+ if (x < 1)
+ fun_l2_n442(x)
+ else
+ fun_l2_n258(x)
+ end
+end
+
+def fun_l1_n975(x)
+ if (x < 1)
+ fun_l2_n106(x)
+ else
+ fun_l2_n364(x)
+ end
+end
+
+def fun_l1_n976(x)
+ if (x < 1)
+ fun_l2_n412(x)
+ else
+ fun_l2_n669(x)
+ end
+end
+
+def fun_l1_n977(x)
+ if (x < 1)
+ fun_l2_n394(x)
+ else
+ fun_l2_n435(x)
+ end
+end
+
+def fun_l1_n978(x)
+ if (x < 1)
+ fun_l2_n630(x)
+ else
+ fun_l2_n686(x)
+ end
+end
+
+def fun_l1_n979(x)
+ if (x < 1)
+ fun_l2_n683(x)
+ else
+ fun_l2_n99(x)
+ end
+end
+
+def fun_l1_n980(x)
+ if (x < 1)
+ fun_l2_n352(x)
+ else
+ fun_l2_n394(x)
+ end
+end
+
+def fun_l1_n981(x)
+ if (x < 1)
+ fun_l2_n856(x)
+ else
+ fun_l2_n11(x)
+ end
+end
+
+def fun_l1_n982(x)
+ if (x < 1)
+ fun_l2_n484(x)
+ else
+ fun_l2_n230(x)
+ end
+end
+
+def fun_l1_n983(x)
+ if (x < 1)
+ fun_l2_n609(x)
+ else
+ fun_l2_n882(x)
+ end
+end
+
+def fun_l1_n984(x)
+ if (x < 1)
+ fun_l2_n529(x)
+ else
+ fun_l2_n589(x)
+ end
+end
+
+def fun_l1_n985(x)
+ if (x < 1)
+ fun_l2_n545(x)
+ else
+ fun_l2_n139(x)
+ end
+end
+
+def fun_l1_n986(x)
+ if (x < 1)
+ fun_l2_n679(x)
+ else
+ fun_l2_n938(x)
+ end
+end
+
+def fun_l1_n987(x)
+ if (x < 1)
+ fun_l2_n803(x)
+ else
+ fun_l2_n454(x)
+ end
+end
+
+def fun_l1_n988(x)
+ if (x < 1)
+ fun_l2_n403(x)
+ else
+ fun_l2_n976(x)
+ end
+end
+
+def fun_l1_n989(x)
+ if (x < 1)
+ fun_l2_n364(x)
+ else
+ fun_l2_n96(x)
+ end
+end
+
+def fun_l1_n990(x)
+ if (x < 1)
+ fun_l2_n48(x)
+ else
+ fun_l2_n442(x)
+ end
+end
+
+def fun_l1_n991(x)
+ if (x < 1)
+ fun_l2_n842(x)
+ else
+ fun_l2_n810(x)
+ end
+end
+
+def fun_l1_n992(x)
+ if (x < 1)
+ fun_l2_n237(x)
+ else
+ fun_l2_n145(x)
+ end
+end
+
+def fun_l1_n993(x)
+ if (x < 1)
+ fun_l2_n279(x)
+ else
+ fun_l2_n783(x)
+ end
+end
+
+def fun_l1_n994(x)
+ if (x < 1)
+ fun_l2_n323(x)
+ else
+ fun_l2_n829(x)
+ end
+end
+
+def fun_l1_n995(x)
+ if (x < 1)
+ fun_l2_n904(x)
+ else
+ fun_l2_n738(x)
+ end
+end
+
+def fun_l1_n996(x)
+ if (x < 1)
+ fun_l2_n390(x)
+ else
+ fun_l2_n169(x)
+ end
+end
+
+def fun_l1_n997(x)
+ if (x < 1)
+ fun_l2_n583(x)
+ else
+ fun_l2_n993(x)
+ end
+end
+
+def fun_l1_n998(x)
+ if (x < 1)
+ fun_l2_n752(x)
+ else
+ fun_l2_n240(x)
+ end
+end
+
+def fun_l1_n999(x)
+ if (x < 1)
+ fun_l2_n489(x)
+ else
+ fun_l2_n175(x)
+ end
+end
+
+def fun_l2_n0(x)
+ if (x < 1)
+ fun_l3_n293(x)
+ else
+ fun_l3_n569(x)
+ end
+end
+
+def fun_l2_n1(x)
+ if (x < 1)
+ fun_l3_n310(x)
+ else
+ fun_l3_n785(x)
+ end
+end
+
+def fun_l2_n2(x)
+ if (x < 1)
+ fun_l3_n484(x)
+ else
+ fun_l3_n800(x)
+ end
+end
+
+def fun_l2_n3(x)
+ if (x < 1)
+ fun_l3_n353(x)
+ else
+ fun_l3_n871(x)
+ end
+end
+
+def fun_l2_n4(x)
+ if (x < 1)
+ fun_l3_n100(x)
+ else
+ fun_l3_n796(x)
+ end
+end
+
+def fun_l2_n5(x)
+ if (x < 1)
+ fun_l3_n547(x)
+ else
+ fun_l3_n663(x)
+ end
+end
+
+def fun_l2_n6(x)
+ if (x < 1)
+ fun_l3_n756(x)
+ else
+ fun_l3_n69(x)
+ end
+end
+
+def fun_l2_n7(x)
+ if (x < 1)
+ fun_l3_n393(x)
+ else
+ fun_l3_n333(x)
+ end
+end
+
+def fun_l2_n8(x)
+ if (x < 1)
+ fun_l3_n167(x)
+ else
+ fun_l3_n47(x)
+ end
+end
+
+def fun_l2_n9(x)
+ if (x < 1)
+ fun_l3_n969(x)
+ else
+ fun_l3_n772(x)
+ end
+end
+
+def fun_l2_n10(x)
+ if (x < 1)
+ fun_l3_n667(x)
+ else
+ fun_l3_n62(x)
+ end
+end
+
+def fun_l2_n11(x)
+ if (x < 1)
+ fun_l3_n671(x)
+ else
+ fun_l3_n303(x)
+ end
+end
+
+def fun_l2_n12(x)
+ if (x < 1)
+ fun_l3_n116(x)
+ else
+ fun_l3_n537(x)
+ end
+end
+
+def fun_l2_n13(x)
+ if (x < 1)
+ fun_l3_n363(x)
+ else
+ fun_l3_n426(x)
+ end
+end
+
+def fun_l2_n14(x)
+ if (x < 1)
+ fun_l3_n23(x)
+ else
+ fun_l3_n800(x)
+ end
+end
+
+def fun_l2_n15(x)
+ if (x < 1)
+ fun_l3_n344(x)
+ else
+ fun_l3_n590(x)
+ end
+end
+
+def fun_l2_n16(x)
+ if (x < 1)
+ fun_l3_n759(x)
+ else
+ fun_l3_n531(x)
+ end
+end
+
+def fun_l2_n17(x)
+ if (x < 1)
+ fun_l3_n902(x)
+ else
+ fun_l3_n948(x)
+ end
+end
+
+def fun_l2_n18(x)
+ if (x < 1)
+ fun_l3_n407(x)
+ else
+ fun_l3_n743(x)
+ end
+end
+
+def fun_l2_n19(x)
+ if (x < 1)
+ fun_l3_n360(x)
+ else
+ fun_l3_n953(x)
+ end
+end
+
+def fun_l2_n20(x)
+ if (x < 1)
+ fun_l3_n968(x)
+ else
+ fun_l3_n685(x)
+ end
+end
+
+def fun_l2_n21(x)
+ if (x < 1)
+ fun_l3_n964(x)
+ else
+ fun_l3_n210(x)
+ end
+end
+
+def fun_l2_n22(x)
+ if (x < 1)
+ fun_l3_n346(x)
+ else
+ fun_l3_n902(x)
+ end
+end
+
+def fun_l2_n23(x)
+ if (x < 1)
+ fun_l3_n154(x)
+ else
+ fun_l3_n52(x)
+ end
+end
+
+def fun_l2_n24(x)
+ if (x < 1)
+ fun_l3_n229(x)
+ else
+ fun_l3_n137(x)
+ end
+end
+
+def fun_l2_n25(x)
+ if (x < 1)
+ fun_l3_n390(x)
+ else
+ fun_l3_n445(x)
+ end
+end
+
+def fun_l2_n26(x)
+ if (x < 1)
+ fun_l3_n11(x)
+ else
+ fun_l3_n113(x)
+ end
+end
+
+def fun_l2_n27(x)
+ if (x < 1)
+ fun_l3_n756(x)
+ else
+ fun_l3_n935(x)
+ end
+end
+
+def fun_l2_n28(x)
+ if (x < 1)
+ fun_l3_n567(x)
+ else
+ fun_l3_n984(x)
+ end
+end
+
+def fun_l2_n29(x)
+ if (x < 1)
+ fun_l3_n982(x)
+ else
+ fun_l3_n335(x)
+ end
+end
+
+def fun_l2_n30(x)
+ if (x < 1)
+ fun_l3_n78(x)
+ else
+ fun_l3_n571(x)
+ end
+end
+
+def fun_l2_n31(x)
+ if (x < 1)
+ fun_l3_n93(x)
+ else
+ fun_l3_n455(x)
+ end
+end
+
+def fun_l2_n32(x)
+ if (x < 1)
+ fun_l3_n118(x)
+ else
+ fun_l3_n713(x)
+ end
+end
+
+def fun_l2_n33(x)
+ if (x < 1)
+ fun_l3_n561(x)
+ else
+ fun_l3_n0(x)
+ end
+end
+
+def fun_l2_n34(x)
+ if (x < 1)
+ fun_l3_n153(x)
+ else
+ fun_l3_n77(x)
+ end
+end
+
+def fun_l2_n35(x)
+ if (x < 1)
+ fun_l3_n815(x)
+ else
+ fun_l3_n642(x)
+ end
+end
+
+def fun_l2_n36(x)
+ if (x < 1)
+ fun_l3_n503(x)
+ else
+ fun_l3_n428(x)
+ end
+end
+
+def fun_l2_n37(x)
+ if (x < 1)
+ fun_l3_n780(x)
+ else
+ fun_l3_n301(x)
+ end
+end
+
+def fun_l2_n38(x)
+ if (x < 1)
+ fun_l3_n827(x)
+ else
+ fun_l3_n444(x)
+ end
+end
+
+def fun_l2_n39(x)
+ if (x < 1)
+ fun_l3_n808(x)
+ else
+ fun_l3_n76(x)
+ end
+end
+
+def fun_l2_n40(x)
+ if (x < 1)
+ fun_l3_n216(x)
+ else
+ fun_l3_n943(x)
+ end
+end
+
+def fun_l2_n41(x)
+ if (x < 1)
+ fun_l3_n237(x)
+ else
+ fun_l3_n935(x)
+ end
+end
+
+def fun_l2_n42(x)
+ if (x < 1)
+ fun_l3_n769(x)
+ else
+ fun_l3_n564(x)
+ end
+end
+
+def fun_l2_n43(x)
+ if (x < 1)
+ fun_l3_n108(x)
+ else
+ fun_l3_n180(x)
+ end
+end
+
+def fun_l2_n44(x)
+ if (x < 1)
+ fun_l3_n750(x)
+ else
+ fun_l3_n614(x)
+ end
+end
+
+def fun_l2_n45(x)
+ if (x < 1)
+ fun_l3_n497(x)
+ else
+ fun_l3_n584(x)
+ end
+end
+
+def fun_l2_n46(x)
+ if (x < 1)
+ fun_l3_n364(x)
+ else
+ fun_l3_n218(x)
+ end
+end
+
+def fun_l2_n47(x)
+ if (x < 1)
+ fun_l3_n938(x)
+ else
+ fun_l3_n707(x)
+ end
+end
+
+def fun_l2_n48(x)
+ if (x < 1)
+ fun_l3_n14(x)
+ else
+ fun_l3_n178(x)
+ end
+end
+
+def fun_l2_n49(x)
+ if (x < 1)
+ fun_l3_n923(x)
+ else
+ fun_l3_n493(x)
+ end
+end
+
+def fun_l2_n50(x)
+ if (x < 1)
+ fun_l3_n481(x)
+ else
+ fun_l3_n193(x)
+ end
+end
+
+def fun_l2_n51(x)
+ if (x < 1)
+ fun_l3_n876(x)
+ else
+ fun_l3_n59(x)
+ end
+end
+
+def fun_l2_n52(x)
+ if (x < 1)
+ fun_l3_n930(x)
+ else
+ fun_l3_n813(x)
+ end
+end
+
+def fun_l2_n53(x)
+ if (x < 1)
+ fun_l3_n369(x)
+ else
+ fun_l3_n972(x)
+ end
+end
+
+def fun_l2_n54(x)
+ if (x < 1)
+ fun_l3_n95(x)
+ else
+ fun_l3_n573(x)
+ end
+end
+
+def fun_l2_n55(x)
+ if (x < 1)
+ fun_l3_n148(x)
+ else
+ fun_l3_n369(x)
+ end
+end
+
+def fun_l2_n56(x)
+ if (x < 1)
+ fun_l3_n476(x)
+ else
+ fun_l3_n54(x)
+ end
+end
+
+def fun_l2_n57(x)
+ if (x < 1)
+ fun_l3_n672(x)
+ else
+ fun_l3_n592(x)
+ end
+end
+
+def fun_l2_n58(x)
+ if (x < 1)
+ fun_l3_n648(x)
+ else
+ fun_l3_n169(x)
+ end
+end
+
+def fun_l2_n59(x)
+ if (x < 1)
+ fun_l3_n844(x)
+ else
+ fun_l3_n422(x)
+ end
+end
+
+def fun_l2_n60(x)
+ if (x < 1)
+ fun_l3_n6(x)
+ else
+ fun_l3_n763(x)
+ end
+end
+
+def fun_l2_n61(x)
+ if (x < 1)
+ fun_l3_n35(x)
+ else
+ fun_l3_n316(x)
+ end
+end
+
+def fun_l2_n62(x)
+ if (x < 1)
+ fun_l3_n487(x)
+ else
+ fun_l3_n469(x)
+ end
+end
+
+def fun_l2_n63(x)
+ if (x < 1)
+ fun_l3_n272(x)
+ else
+ fun_l3_n909(x)
+ end
+end
+
+def fun_l2_n64(x)
+ if (x < 1)
+ fun_l3_n266(x)
+ else
+ fun_l3_n347(x)
+ end
+end
+
+def fun_l2_n65(x)
+ if (x < 1)
+ fun_l3_n696(x)
+ else
+ fun_l3_n499(x)
+ end
+end
+
+def fun_l2_n66(x)
+ if (x < 1)
+ fun_l3_n523(x)
+ else
+ fun_l3_n834(x)
+ end
+end
+
+def fun_l2_n67(x)
+ if (x < 1)
+ fun_l3_n966(x)
+ else
+ fun_l3_n454(x)
+ end
+end
+
+def fun_l2_n68(x)
+ if (x < 1)
+ fun_l3_n406(x)
+ else
+ fun_l3_n644(x)
+ end
+end
+
+def fun_l2_n69(x)
+ if (x < 1)
+ fun_l3_n616(x)
+ else
+ fun_l3_n90(x)
+ end
+end
+
+def fun_l2_n70(x)
+ if (x < 1)
+ fun_l3_n158(x)
+ else
+ fun_l3_n910(x)
+ end
+end
+
+def fun_l2_n71(x)
+ if (x < 1)
+ fun_l3_n391(x)
+ else
+ fun_l3_n761(x)
+ end
+end
+
+def fun_l2_n72(x)
+ if (x < 1)
+ fun_l3_n585(x)
+ else
+ fun_l3_n405(x)
+ end
+end
+
+def fun_l2_n73(x)
+ if (x < 1)
+ fun_l3_n227(x)
+ else
+ fun_l3_n583(x)
+ end
+end
+
+def fun_l2_n74(x)
+ if (x < 1)
+ fun_l3_n580(x)
+ else
+ fun_l3_n110(x)
+ end
+end
+
+def fun_l2_n75(x)
+ if (x < 1)
+ fun_l3_n393(x)
+ else
+ fun_l3_n643(x)
+ end
+end
+
+def fun_l2_n76(x)
+ if (x < 1)
+ fun_l3_n935(x)
+ else
+ fun_l3_n593(x)
+ end
+end
+
+def fun_l2_n77(x)
+ if (x < 1)
+ fun_l3_n239(x)
+ else
+ fun_l3_n704(x)
+ end
+end
+
+def fun_l2_n78(x)
+ if (x < 1)
+ fun_l3_n192(x)
+ else
+ fun_l3_n722(x)
+ end
+end
+
+def fun_l2_n79(x)
+ if (x < 1)
+ fun_l3_n119(x)
+ else
+ fun_l3_n426(x)
+ end
+end
+
+def fun_l2_n80(x)
+ if (x < 1)
+ fun_l3_n692(x)
+ else
+ fun_l3_n895(x)
+ end
+end
+
+def fun_l2_n81(x)
+ if (x < 1)
+ fun_l3_n246(x)
+ else
+ fun_l3_n340(x)
+ end
+end
+
+def fun_l2_n82(x)
+ if (x < 1)
+ fun_l3_n368(x)
+ else
+ fun_l3_n255(x)
+ end
+end
+
+def fun_l2_n83(x)
+ if (x < 1)
+ fun_l3_n942(x)
+ else
+ fun_l3_n595(x)
+ end
+end
+
+def fun_l2_n84(x)
+ if (x < 1)
+ fun_l3_n629(x)
+ else
+ fun_l3_n622(x)
+ end
+end
+
+def fun_l2_n85(x)
+ if (x < 1)
+ fun_l3_n415(x)
+ else
+ fun_l3_n615(x)
+ end
+end
+
+def fun_l2_n86(x)
+ if (x < 1)
+ fun_l3_n295(x)
+ else
+ fun_l3_n809(x)
+ end
+end
+
+def fun_l2_n87(x)
+ if (x < 1)
+ fun_l3_n957(x)
+ else
+ fun_l3_n452(x)
+ end
+end
+
+def fun_l2_n88(x)
+ if (x < 1)
+ fun_l3_n490(x)
+ else
+ fun_l3_n184(x)
+ end
+end
+
+def fun_l2_n89(x)
+ if (x < 1)
+ fun_l3_n483(x)
+ else
+ fun_l3_n963(x)
+ end
+end
+
+def fun_l2_n90(x)
+ if (x < 1)
+ fun_l3_n262(x)
+ else
+ fun_l3_n458(x)
+ end
+end
+
+def fun_l2_n91(x)
+ if (x < 1)
+ fun_l3_n277(x)
+ else
+ fun_l3_n30(x)
+ end
+end
+
+def fun_l2_n92(x)
+ if (x < 1)
+ fun_l3_n310(x)
+ else
+ fun_l3_n215(x)
+ end
+end
+
+def fun_l2_n93(x)
+ if (x < 1)
+ fun_l3_n660(x)
+ else
+ fun_l3_n798(x)
+ end
+end
+
+def fun_l2_n94(x)
+ if (x < 1)
+ fun_l3_n761(x)
+ else
+ fun_l3_n10(x)
+ end
+end
+
+def fun_l2_n95(x)
+ if (x < 1)
+ fun_l3_n4(x)
+ else
+ fun_l3_n65(x)
+ end
+end
+
+def fun_l2_n96(x)
+ if (x < 1)
+ fun_l3_n444(x)
+ else
+ fun_l3_n378(x)
+ end
+end
+
+def fun_l2_n97(x)
+ if (x < 1)
+ fun_l3_n119(x)
+ else
+ fun_l3_n96(x)
+ end
+end
+
+def fun_l2_n98(x)
+ if (x < 1)
+ fun_l3_n970(x)
+ else
+ fun_l3_n471(x)
+ end
+end
+
+def fun_l2_n99(x)
+ if (x < 1)
+ fun_l3_n544(x)
+ else
+ fun_l3_n1(x)
+ end
+end
+
+def fun_l2_n100(x)
+ if (x < 1)
+ fun_l3_n253(x)
+ else
+ fun_l3_n332(x)
+ end
+end
+
+def fun_l2_n101(x)
+ if (x < 1)
+ fun_l3_n69(x)
+ else
+ fun_l3_n946(x)
+ end
+end
+
+def fun_l2_n102(x)
+ if (x < 1)
+ fun_l3_n458(x)
+ else
+ fun_l3_n885(x)
+ end
+end
+
+def fun_l2_n103(x)
+ if (x < 1)
+ fun_l3_n732(x)
+ else
+ fun_l3_n601(x)
+ end
+end
+
+def fun_l2_n104(x)
+ if (x < 1)
+ fun_l3_n737(x)
+ else
+ fun_l3_n530(x)
+ end
+end
+
+def fun_l2_n105(x)
+ if (x < 1)
+ fun_l3_n125(x)
+ else
+ fun_l3_n561(x)
+ end
+end
+
+def fun_l2_n106(x)
+ if (x < 1)
+ fun_l3_n717(x)
+ else
+ fun_l3_n660(x)
+ end
+end
+
+def fun_l2_n107(x)
+ if (x < 1)
+ fun_l3_n863(x)
+ else
+ fun_l3_n211(x)
+ end
+end
+
+def fun_l2_n108(x)
+ if (x < 1)
+ fun_l3_n221(x)
+ else
+ fun_l3_n718(x)
+ end
+end
+
+def fun_l2_n109(x)
+ if (x < 1)
+ fun_l3_n100(x)
+ else
+ fun_l3_n673(x)
+ end
+end
+
+def fun_l2_n110(x)
+ if (x < 1)
+ fun_l3_n434(x)
+ else
+ fun_l3_n348(x)
+ end
+end
+
+def fun_l2_n111(x)
+ if (x < 1)
+ fun_l3_n923(x)
+ else
+ fun_l3_n413(x)
+ end
+end
+
+def fun_l2_n112(x)
+ if (x < 1)
+ fun_l3_n253(x)
+ else
+ fun_l3_n461(x)
+ end
+end
+
+def fun_l2_n113(x)
+ if (x < 1)
+ fun_l3_n946(x)
+ else
+ fun_l3_n406(x)
+ end
+end
+
+def fun_l2_n114(x)
+ if (x < 1)
+ fun_l3_n976(x)
+ else
+ fun_l3_n354(x)
+ end
+end
+
+def fun_l2_n115(x)
+ if (x < 1)
+ fun_l3_n205(x)
+ else
+ fun_l3_n798(x)
+ end
+end
+
+def fun_l2_n116(x)
+ if (x < 1)
+ fun_l3_n304(x)
+ else
+ fun_l3_n145(x)
+ end
+end
+
+def fun_l2_n117(x)
+ if (x < 1)
+ fun_l3_n917(x)
+ else
+ fun_l3_n276(x)
+ end
+end
+
+def fun_l2_n118(x)
+ if (x < 1)
+ fun_l3_n880(x)
+ else
+ fun_l3_n532(x)
+ end
+end
+
+def fun_l2_n119(x)
+ if (x < 1)
+ fun_l3_n39(x)
+ else
+ fun_l3_n549(x)
+ end
+end
+
+def fun_l2_n120(x)
+ if (x < 1)
+ fun_l3_n325(x)
+ else
+ fun_l3_n250(x)
+ end
+end
+
+def fun_l2_n121(x)
+ if (x < 1)
+ fun_l3_n953(x)
+ else
+ fun_l3_n259(x)
+ end
+end
+
+def fun_l2_n122(x)
+ if (x < 1)
+ fun_l3_n572(x)
+ else
+ fun_l3_n747(x)
+ end
+end
+
+def fun_l2_n123(x)
+ if (x < 1)
+ fun_l3_n639(x)
+ else
+ fun_l3_n810(x)
+ end
+end
+
+def fun_l2_n124(x)
+ if (x < 1)
+ fun_l3_n954(x)
+ else
+ fun_l3_n814(x)
+ end
+end
+
+def fun_l2_n125(x)
+ if (x < 1)
+ fun_l3_n932(x)
+ else
+ fun_l3_n275(x)
+ end
+end
+
+def fun_l2_n126(x)
+ if (x < 1)
+ fun_l3_n472(x)
+ else
+ fun_l3_n184(x)
+ end
+end
+
+def fun_l2_n127(x)
+ if (x < 1)
+ fun_l3_n725(x)
+ else
+ fun_l3_n497(x)
+ end
+end
+
+def fun_l2_n128(x)
+ if (x < 1)
+ fun_l3_n94(x)
+ else
+ fun_l3_n801(x)
+ end
+end
+
+def fun_l2_n129(x)
+ if (x < 1)
+ fun_l3_n476(x)
+ else
+ fun_l3_n936(x)
+ end
+end
+
+def fun_l2_n130(x)
+ if (x < 1)
+ fun_l3_n706(x)
+ else
+ fun_l3_n738(x)
+ end
+end
+
+def fun_l2_n131(x)
+ if (x < 1)
+ fun_l3_n535(x)
+ else
+ fun_l3_n401(x)
+ end
+end
+
+def fun_l2_n132(x)
+ if (x < 1)
+ fun_l3_n459(x)
+ else
+ fun_l3_n998(x)
+ end
+end
+
+def fun_l2_n133(x)
+ if (x < 1)
+ fun_l3_n158(x)
+ else
+ fun_l3_n288(x)
+ end
+end
+
+def fun_l2_n134(x)
+ if (x < 1)
+ fun_l3_n47(x)
+ else
+ fun_l3_n104(x)
+ end
+end
+
+def fun_l2_n135(x)
+ if (x < 1)
+ fun_l3_n154(x)
+ else
+ fun_l3_n239(x)
+ end
+end
+
+def fun_l2_n136(x)
+ if (x < 1)
+ fun_l3_n634(x)
+ else
+ fun_l3_n718(x)
+ end
+end
+
+def fun_l2_n137(x)
+ if (x < 1)
+ fun_l3_n867(x)
+ else
+ fun_l3_n578(x)
+ end
+end
+
+def fun_l2_n138(x)
+ if (x < 1)
+ fun_l3_n905(x)
+ else
+ fun_l3_n434(x)
+ end
+end
+
+def fun_l2_n139(x)
+ if (x < 1)
+ fun_l3_n596(x)
+ else
+ fun_l3_n516(x)
+ end
+end
+
+def fun_l2_n140(x)
+ if (x < 1)
+ fun_l3_n150(x)
+ else
+ fun_l3_n901(x)
+ end
+end
+
+def fun_l2_n141(x)
+ if (x < 1)
+ fun_l3_n792(x)
+ else
+ fun_l3_n50(x)
+ end
+end
+
+def fun_l2_n142(x)
+ if (x < 1)
+ fun_l3_n539(x)
+ else
+ fun_l3_n206(x)
+ end
+end
+
+def fun_l2_n143(x)
+ if (x < 1)
+ fun_l3_n690(x)
+ else
+ fun_l3_n788(x)
+ end
+end
+
+def fun_l2_n144(x)
+ if (x < 1)
+ fun_l3_n535(x)
+ else
+ fun_l3_n868(x)
+ end
+end
+
+def fun_l2_n145(x)
+ if (x < 1)
+ fun_l3_n869(x)
+ else
+ fun_l3_n865(x)
+ end
+end
+
+def fun_l2_n146(x)
+ if (x < 1)
+ fun_l3_n574(x)
+ else
+ fun_l3_n798(x)
+ end
+end
+
+def fun_l2_n147(x)
+ if (x < 1)
+ fun_l3_n876(x)
+ else
+ fun_l3_n658(x)
+ end
+end
+
+def fun_l2_n148(x)
+ if (x < 1)
+ fun_l3_n582(x)
+ else
+ fun_l3_n694(x)
+ end
+end
+
+def fun_l2_n149(x)
+ if (x < 1)
+ fun_l3_n137(x)
+ else
+ fun_l3_n187(x)
+ end
+end
+
+def fun_l2_n150(x)
+ if (x < 1)
+ fun_l3_n30(x)
+ else
+ fun_l3_n666(x)
+ end
+end
+
+def fun_l2_n151(x)
+ if (x < 1)
+ fun_l3_n264(x)
+ else
+ fun_l3_n236(x)
+ end
+end
+
+def fun_l2_n152(x)
+ if (x < 1)
+ fun_l3_n984(x)
+ else
+ fun_l3_n469(x)
+ end
+end
+
+def fun_l2_n153(x)
+ if (x < 1)
+ fun_l3_n152(x)
+ else
+ fun_l3_n578(x)
+ end
+end
+
+def fun_l2_n154(x)
+ if (x < 1)
+ fun_l3_n452(x)
+ else
+ fun_l3_n807(x)
+ end
+end
+
+def fun_l2_n155(x)
+ if (x < 1)
+ fun_l3_n82(x)
+ else
+ fun_l3_n589(x)
+ end
+end
+
+def fun_l2_n156(x)
+ if (x < 1)
+ fun_l3_n356(x)
+ else
+ fun_l3_n454(x)
+ end
+end
+
+def fun_l2_n157(x)
+ if (x < 1)
+ fun_l3_n814(x)
+ else
+ fun_l3_n376(x)
+ end
+end
+
+def fun_l2_n158(x)
+ if (x < 1)
+ fun_l3_n755(x)
+ else
+ fun_l3_n966(x)
+ end
+end
+
+def fun_l2_n159(x)
+ if (x < 1)
+ fun_l3_n167(x)
+ else
+ fun_l3_n571(x)
+ end
+end
+
+def fun_l2_n160(x)
+ if (x < 1)
+ fun_l3_n919(x)
+ else
+ fun_l3_n771(x)
+ end
+end
+
+def fun_l2_n161(x)
+ if (x < 1)
+ fun_l3_n147(x)
+ else
+ fun_l3_n936(x)
+ end
+end
+
+def fun_l2_n162(x)
+ if (x < 1)
+ fun_l3_n638(x)
+ else
+ fun_l3_n23(x)
+ end
+end
+
+def fun_l2_n163(x)
+ if (x < 1)
+ fun_l3_n349(x)
+ else
+ fun_l3_n46(x)
+ end
+end
+
+def fun_l2_n164(x)
+ if (x < 1)
+ fun_l3_n55(x)
+ else
+ fun_l3_n795(x)
+ end
+end
+
+def fun_l2_n165(x)
+ if (x < 1)
+ fun_l3_n131(x)
+ else
+ fun_l3_n233(x)
+ end
+end
+
+def fun_l2_n166(x)
+ if (x < 1)
+ fun_l3_n324(x)
+ else
+ fun_l3_n215(x)
+ end
+end
+
+def fun_l2_n167(x)
+ if (x < 1)
+ fun_l3_n244(x)
+ else
+ fun_l3_n641(x)
+ end
+end
+
+def fun_l2_n168(x)
+ if (x < 1)
+ fun_l3_n744(x)
+ else
+ fun_l3_n337(x)
+ end
+end
+
+def fun_l2_n169(x)
+ if (x < 1)
+ fun_l3_n760(x)
+ else
+ fun_l3_n82(x)
+ end
+end
+
+def fun_l2_n170(x)
+ if (x < 1)
+ fun_l3_n877(x)
+ else
+ fun_l3_n566(x)
+ end
+end
+
+def fun_l2_n171(x)
+ if (x < 1)
+ fun_l3_n211(x)
+ else
+ fun_l3_n101(x)
+ end
+end
+
+def fun_l2_n172(x)
+ if (x < 1)
+ fun_l3_n143(x)
+ else
+ fun_l3_n537(x)
+ end
+end
+
+def fun_l2_n173(x)
+ if (x < 1)
+ fun_l3_n210(x)
+ else
+ fun_l3_n150(x)
+ end
+end
+
+def fun_l2_n174(x)
+ if (x < 1)
+ fun_l3_n772(x)
+ else
+ fun_l3_n42(x)
+ end
+end
+
+def fun_l2_n175(x)
+ if (x < 1)
+ fun_l3_n482(x)
+ else
+ fun_l3_n606(x)
+ end
+end
+
+def fun_l2_n176(x)
+ if (x < 1)
+ fun_l3_n68(x)
+ else
+ fun_l3_n888(x)
+ end
+end
+
+def fun_l2_n177(x)
+ if (x < 1)
+ fun_l3_n313(x)
+ else
+ fun_l3_n947(x)
+ end
+end
+
+def fun_l2_n178(x)
+ if (x < 1)
+ fun_l3_n116(x)
+ else
+ fun_l3_n812(x)
+ end
+end
+
+def fun_l2_n179(x)
+ if (x < 1)
+ fun_l3_n741(x)
+ else
+ fun_l3_n994(x)
+ end
+end
+
+def fun_l2_n180(x)
+ if (x < 1)
+ fun_l3_n667(x)
+ else
+ fun_l3_n335(x)
+ end
+end
+
+def fun_l2_n181(x)
+ if (x < 1)
+ fun_l3_n994(x)
+ else
+ fun_l3_n502(x)
+ end
+end
+
+def fun_l2_n182(x)
+ if (x < 1)
+ fun_l3_n528(x)
+ else
+ fun_l3_n272(x)
+ end
+end
+
+def fun_l2_n183(x)
+ if (x < 1)
+ fun_l3_n649(x)
+ else
+ fun_l3_n200(x)
+ end
+end
+
+def fun_l2_n184(x)
+ if (x < 1)
+ fun_l3_n105(x)
+ else
+ fun_l3_n897(x)
+ end
+end
+
+def fun_l2_n185(x)
+ if (x < 1)
+ fun_l3_n980(x)
+ else
+ fun_l3_n651(x)
+ end
+end
+
+def fun_l2_n186(x)
+ if (x < 1)
+ fun_l3_n835(x)
+ else
+ fun_l3_n388(x)
+ end
+end
+
+def fun_l2_n187(x)
+ if (x < 1)
+ fun_l3_n769(x)
+ else
+ fun_l3_n162(x)
+ end
+end
+
+def fun_l2_n188(x)
+ if (x < 1)
+ fun_l3_n934(x)
+ else
+ fun_l3_n874(x)
+ end
+end
+
+def fun_l2_n189(x)
+ if (x < 1)
+ fun_l3_n407(x)
+ else
+ fun_l3_n180(x)
+ end
+end
+
+def fun_l2_n190(x)
+ if (x < 1)
+ fun_l3_n594(x)
+ else
+ fun_l3_n929(x)
+ end
+end
+
+def fun_l2_n191(x)
+ if (x < 1)
+ fun_l3_n303(x)
+ else
+ fun_l3_n528(x)
+ end
+end
+
+def fun_l2_n192(x)
+ if (x < 1)
+ fun_l3_n768(x)
+ else
+ fun_l3_n226(x)
+ end
+end
+
+def fun_l2_n193(x)
+ if (x < 1)
+ fun_l3_n618(x)
+ else
+ fun_l3_n821(x)
+ end
+end
+
+def fun_l2_n194(x)
+ if (x < 1)
+ fun_l3_n953(x)
+ else
+ fun_l3_n969(x)
+ end
+end
+
+def fun_l2_n195(x)
+ if (x < 1)
+ fun_l3_n574(x)
+ else
+ fun_l3_n344(x)
+ end
+end
+
+def fun_l2_n196(x)
+ if (x < 1)
+ fun_l3_n943(x)
+ else
+ fun_l3_n304(x)
+ end
+end
+
+def fun_l2_n197(x)
+ if (x < 1)
+ fun_l3_n276(x)
+ else
+ fun_l3_n502(x)
+ end
+end
+
+def fun_l2_n198(x)
+ if (x < 1)
+ fun_l3_n597(x)
+ else
+ fun_l3_n197(x)
+ end
+end
+
+def fun_l2_n199(x)
+ if (x < 1)
+ fun_l3_n517(x)
+ else
+ fun_l3_n34(x)
+ end
+end
+
+def fun_l2_n200(x)
+ if (x < 1)
+ fun_l3_n980(x)
+ else
+ fun_l3_n672(x)
+ end
+end
+
+def fun_l2_n201(x)
+ if (x < 1)
+ fun_l3_n510(x)
+ else
+ fun_l3_n804(x)
+ end
+end
+
+def fun_l2_n202(x)
+ if (x < 1)
+ fun_l3_n735(x)
+ else
+ fun_l3_n367(x)
+ end
+end
+
+def fun_l2_n203(x)
+ if (x < 1)
+ fun_l3_n546(x)
+ else
+ fun_l3_n502(x)
+ end
+end
+
+def fun_l2_n204(x)
+ if (x < 1)
+ fun_l3_n189(x)
+ else
+ fun_l3_n639(x)
+ end
+end
+
+def fun_l2_n205(x)
+ if (x < 1)
+ fun_l3_n396(x)
+ else
+ fun_l3_n862(x)
+ end
+end
+
+def fun_l2_n206(x)
+ if (x < 1)
+ fun_l3_n679(x)
+ else
+ fun_l3_n881(x)
+ end
+end
+
+def fun_l2_n207(x)
+ if (x < 1)
+ fun_l3_n342(x)
+ else
+ fun_l3_n522(x)
+ end
+end
+
+def fun_l2_n208(x)
+ if (x < 1)
+ fun_l3_n173(x)
+ else
+ fun_l3_n323(x)
+ end
+end
+
+def fun_l2_n209(x)
+ if (x < 1)
+ fun_l3_n693(x)
+ else
+ fun_l3_n160(x)
+ end
+end
+
+def fun_l2_n210(x)
+ if (x < 1)
+ fun_l3_n827(x)
+ else
+ fun_l3_n580(x)
+ end
+end
+
+def fun_l2_n211(x)
+ if (x < 1)
+ fun_l3_n213(x)
+ else
+ fun_l3_n100(x)
+ end
+end
+
+def fun_l2_n212(x)
+ if (x < 1)
+ fun_l3_n915(x)
+ else
+ fun_l3_n531(x)
+ end
+end
+
+def fun_l2_n213(x)
+ if (x < 1)
+ fun_l3_n260(x)
+ else
+ fun_l3_n279(x)
+ end
+end
+
+def fun_l2_n214(x)
+ if (x < 1)
+ fun_l3_n468(x)
+ else
+ fun_l3_n257(x)
+ end
+end
+
+def fun_l2_n215(x)
+ if (x < 1)
+ fun_l3_n990(x)
+ else
+ fun_l3_n740(x)
+ end
+end
+
+def fun_l2_n216(x)
+ if (x < 1)
+ fun_l3_n291(x)
+ else
+ fun_l3_n625(x)
+ end
+end
+
+def fun_l2_n217(x)
+ if (x < 1)
+ fun_l3_n493(x)
+ else
+ fun_l3_n726(x)
+ end
+end
+
+def fun_l2_n218(x)
+ if (x < 1)
+ fun_l3_n714(x)
+ else
+ fun_l3_n793(x)
+ end
+end
+
+def fun_l2_n219(x)
+ if (x < 1)
+ fun_l3_n683(x)
+ else
+ fun_l3_n715(x)
+ end
+end
+
+def fun_l2_n220(x)
+ if (x < 1)
+ fun_l3_n249(x)
+ else
+ fun_l3_n266(x)
+ end
+end
+
+def fun_l2_n221(x)
+ if (x < 1)
+ fun_l3_n324(x)
+ else
+ fun_l3_n22(x)
+ end
+end
+
+def fun_l2_n222(x)
+ if (x < 1)
+ fun_l3_n978(x)
+ else
+ fun_l3_n885(x)
+ end
+end
+
+def fun_l2_n223(x)
+ if (x < 1)
+ fun_l3_n821(x)
+ else
+ fun_l3_n412(x)
+ end
+end
+
+def fun_l2_n224(x)
+ if (x < 1)
+ fun_l3_n636(x)
+ else
+ fun_l3_n641(x)
+ end
+end
+
+def fun_l2_n225(x)
+ if (x < 1)
+ fun_l3_n971(x)
+ else
+ fun_l3_n288(x)
+ end
+end
+
+def fun_l2_n226(x)
+ if (x < 1)
+ fun_l3_n429(x)
+ else
+ fun_l3_n323(x)
+ end
+end
+
+def fun_l2_n227(x)
+ if (x < 1)
+ fun_l3_n909(x)
+ else
+ fun_l3_n267(x)
+ end
+end
+
+def fun_l2_n228(x)
+ if (x < 1)
+ fun_l3_n437(x)
+ else
+ fun_l3_n985(x)
+ end
+end
+
+def fun_l2_n229(x)
+ if (x < 1)
+ fun_l3_n131(x)
+ else
+ fun_l3_n298(x)
+ end
+end
+
+def fun_l2_n230(x)
+ if (x < 1)
+ fun_l3_n865(x)
+ else
+ fun_l3_n288(x)
+ end
+end
+
+def fun_l2_n231(x)
+ if (x < 1)
+ fun_l3_n772(x)
+ else
+ fun_l3_n531(x)
+ end
+end
+
+def fun_l2_n232(x)
+ if (x < 1)
+ fun_l3_n30(x)
+ else
+ fun_l3_n422(x)
+ end
+end
+
+def fun_l2_n233(x)
+ if (x < 1)
+ fun_l3_n82(x)
+ else
+ fun_l3_n32(x)
+ end
+end
+
+def fun_l2_n234(x)
+ if (x < 1)
+ fun_l3_n25(x)
+ else
+ fun_l3_n518(x)
+ end
+end
+
+def fun_l2_n235(x)
+ if (x < 1)
+ fun_l3_n313(x)
+ else
+ fun_l3_n179(x)
+ end
+end
+
+def fun_l2_n236(x)
+ if (x < 1)
+ fun_l3_n819(x)
+ else
+ fun_l3_n586(x)
+ end
+end
+
+def fun_l2_n237(x)
+ if (x < 1)
+ fun_l3_n398(x)
+ else
+ fun_l3_n921(x)
+ end
+end
+
+def fun_l2_n238(x)
+ if (x < 1)
+ fun_l3_n667(x)
+ else
+ fun_l3_n795(x)
+ end
+end
+
+def fun_l2_n239(x)
+ if (x < 1)
+ fun_l3_n862(x)
+ else
+ fun_l3_n222(x)
+ end
+end
+
+def fun_l2_n240(x)
+ if (x < 1)
+ fun_l3_n968(x)
+ else
+ fun_l3_n320(x)
+ end
+end
+
+def fun_l2_n241(x)
+ if (x < 1)
+ fun_l3_n559(x)
+ else
+ fun_l3_n50(x)
+ end
+end
+
+def fun_l2_n242(x)
+ if (x < 1)
+ fun_l3_n647(x)
+ else
+ fun_l3_n232(x)
+ end
+end
+
+def fun_l2_n243(x)
+ if (x < 1)
+ fun_l3_n425(x)
+ else
+ fun_l3_n815(x)
+ end
+end
+
+def fun_l2_n244(x)
+ if (x < 1)
+ fun_l3_n752(x)
+ else
+ fun_l3_n690(x)
+ end
+end
+
+def fun_l2_n245(x)
+ if (x < 1)
+ fun_l3_n382(x)
+ else
+ fun_l3_n817(x)
+ end
+end
+
+def fun_l2_n246(x)
+ if (x < 1)
+ fun_l3_n880(x)
+ else
+ fun_l3_n380(x)
+ end
+end
+
+def fun_l2_n247(x)
+ if (x < 1)
+ fun_l3_n444(x)
+ else
+ fun_l3_n75(x)
+ end
+end
+
+def fun_l2_n248(x)
+ if (x < 1)
+ fun_l3_n368(x)
+ else
+ fun_l3_n314(x)
+ end
+end
+
+def fun_l2_n249(x)
+ if (x < 1)
+ fun_l3_n131(x)
+ else
+ fun_l3_n398(x)
+ end
+end
+
+def fun_l2_n250(x)
+ if (x < 1)
+ fun_l3_n376(x)
+ else
+ fun_l3_n449(x)
+ end
+end
+
+def fun_l2_n251(x)
+ if (x < 1)
+ fun_l3_n404(x)
+ else
+ fun_l3_n301(x)
+ end
+end
+
+def fun_l2_n252(x)
+ if (x < 1)
+ fun_l3_n274(x)
+ else
+ fun_l3_n430(x)
+ end
+end
+
+def fun_l2_n253(x)
+ if (x < 1)
+ fun_l3_n734(x)
+ else
+ fun_l3_n255(x)
+ end
+end
+
+def fun_l2_n254(x)
+ if (x < 1)
+ fun_l3_n30(x)
+ else
+ fun_l3_n944(x)
+ end
+end
+
+def fun_l2_n255(x)
+ if (x < 1)
+ fun_l3_n978(x)
+ else
+ fun_l3_n898(x)
+ end
+end
+
+def fun_l2_n256(x)
+ if (x < 1)
+ fun_l3_n175(x)
+ else
+ fun_l3_n477(x)
+ end
+end
+
+def fun_l2_n257(x)
+ if (x < 1)
+ fun_l3_n84(x)
+ else
+ fun_l3_n772(x)
+ end
+end
+
+def fun_l2_n258(x)
+ if (x < 1)
+ fun_l3_n605(x)
+ else
+ fun_l3_n144(x)
+ end
+end
+
+def fun_l2_n259(x)
+ if (x < 1)
+ fun_l3_n51(x)
+ else
+ fun_l3_n542(x)
+ end
+end
+
+def fun_l2_n260(x)
+ if (x < 1)
+ fun_l3_n940(x)
+ else
+ fun_l3_n316(x)
+ end
+end
+
+def fun_l2_n261(x)
+ if (x < 1)
+ fun_l3_n702(x)
+ else
+ fun_l3_n197(x)
+ end
+end
+
+def fun_l2_n262(x)
+ if (x < 1)
+ fun_l3_n164(x)
+ else
+ fun_l3_n21(x)
+ end
+end
+
+def fun_l2_n263(x)
+ if (x < 1)
+ fun_l3_n432(x)
+ else
+ fun_l3_n496(x)
+ end
+end
+
+def fun_l2_n264(x)
+ if (x < 1)
+ fun_l3_n265(x)
+ else
+ fun_l3_n40(x)
+ end
+end
+
+def fun_l2_n265(x)
+ if (x < 1)
+ fun_l3_n951(x)
+ else
+ fun_l3_n723(x)
+ end
+end
+
+def fun_l2_n266(x)
+ if (x < 1)
+ fun_l3_n279(x)
+ else
+ fun_l3_n167(x)
+ end
+end
+
+def fun_l2_n267(x)
+ if (x < 1)
+ fun_l3_n51(x)
+ else
+ fun_l3_n283(x)
+ end
+end
+
+def fun_l2_n268(x)
+ if (x < 1)
+ fun_l3_n389(x)
+ else
+ fun_l3_n264(x)
+ end
+end
+
+def fun_l2_n269(x)
+ if (x < 1)
+ fun_l3_n68(x)
+ else
+ fun_l3_n484(x)
+ end
+end
+
+def fun_l2_n270(x)
+ if (x < 1)
+ fun_l3_n435(x)
+ else
+ fun_l3_n204(x)
+ end
+end
+
+def fun_l2_n271(x)
+ if (x < 1)
+ fun_l3_n717(x)
+ else
+ fun_l3_n763(x)
+ end
+end
+
+def fun_l2_n272(x)
+ if (x < 1)
+ fun_l3_n901(x)
+ else
+ fun_l3_n332(x)
+ end
+end
+
+def fun_l2_n273(x)
+ if (x < 1)
+ fun_l3_n358(x)
+ else
+ fun_l3_n608(x)
+ end
+end
+
+def fun_l2_n274(x)
+ if (x < 1)
+ fun_l3_n885(x)
+ else
+ fun_l3_n490(x)
+ end
+end
+
+def fun_l2_n275(x)
+ if (x < 1)
+ fun_l3_n82(x)
+ else
+ fun_l3_n87(x)
+ end
+end
+
+def fun_l2_n276(x)
+ if (x < 1)
+ fun_l3_n698(x)
+ else
+ fun_l3_n846(x)
+ end
+end
+
+def fun_l2_n277(x)
+ if (x < 1)
+ fun_l3_n690(x)
+ else
+ fun_l3_n457(x)
+ end
+end
+
+def fun_l2_n278(x)
+ if (x < 1)
+ fun_l3_n925(x)
+ else
+ fun_l3_n674(x)
+ end
+end
+
+def fun_l2_n279(x)
+ if (x < 1)
+ fun_l3_n797(x)
+ else
+ fun_l3_n315(x)
+ end
+end
+
+def fun_l2_n280(x)
+ if (x < 1)
+ fun_l3_n73(x)
+ else
+ fun_l3_n2(x)
+ end
+end
+
+def fun_l2_n281(x)
+ if (x < 1)
+ fun_l3_n301(x)
+ else
+ fun_l3_n315(x)
+ end
+end
+
+def fun_l2_n282(x)
+ if (x < 1)
+ fun_l3_n473(x)
+ else
+ fun_l3_n639(x)
+ end
+end
+
+def fun_l2_n283(x)
+ if (x < 1)
+ fun_l3_n812(x)
+ else
+ fun_l3_n241(x)
+ end
+end
+
+def fun_l2_n284(x)
+ if (x < 1)
+ fun_l3_n0(x)
+ else
+ fun_l3_n445(x)
+ end
+end
+
+def fun_l2_n285(x)
+ if (x < 1)
+ fun_l3_n587(x)
+ else
+ fun_l3_n806(x)
+ end
+end
+
+def fun_l2_n286(x)
+ if (x < 1)
+ fun_l3_n169(x)
+ else
+ fun_l3_n546(x)
+ end
+end
+
+def fun_l2_n287(x)
+ if (x < 1)
+ fun_l3_n623(x)
+ else
+ fun_l3_n677(x)
+ end
+end
+
+def fun_l2_n288(x)
+ if (x < 1)
+ fun_l3_n804(x)
+ else
+ fun_l3_n80(x)
+ end
+end
+
+def fun_l2_n289(x)
+ if (x < 1)
+ fun_l3_n812(x)
+ else
+ fun_l3_n197(x)
+ end
+end
+
+def fun_l2_n290(x)
+ if (x < 1)
+ fun_l3_n551(x)
+ else
+ fun_l3_n896(x)
+ end
+end
+
+def fun_l2_n291(x)
+ if (x < 1)
+ fun_l3_n686(x)
+ else
+ fun_l3_n884(x)
+ end
+end
+
+def fun_l2_n292(x)
+ if (x < 1)
+ fun_l3_n427(x)
+ else
+ fun_l3_n251(x)
+ end
+end
+
+def fun_l2_n293(x)
+ if (x < 1)
+ fun_l3_n375(x)
+ else
+ fun_l3_n309(x)
+ end
+end
+
+def fun_l2_n294(x)
+ if (x < 1)
+ fun_l3_n371(x)
+ else
+ fun_l3_n184(x)
+ end
+end
+
+def fun_l2_n295(x)
+ if (x < 1)
+ fun_l3_n332(x)
+ else
+ fun_l3_n250(x)
+ end
+end
+
+def fun_l2_n296(x)
+ if (x < 1)
+ fun_l3_n333(x)
+ else
+ fun_l3_n254(x)
+ end
+end
+
+def fun_l2_n297(x)
+ if (x < 1)
+ fun_l3_n24(x)
+ else
+ fun_l3_n528(x)
+ end
+end
+
+def fun_l2_n298(x)
+ if (x < 1)
+ fun_l3_n96(x)
+ else
+ fun_l3_n653(x)
+ end
+end
+
+def fun_l2_n299(x)
+ if (x < 1)
+ fun_l3_n920(x)
+ else
+ fun_l3_n475(x)
+ end
+end
+
+def fun_l2_n300(x)
+ if (x < 1)
+ fun_l3_n337(x)
+ else
+ fun_l3_n378(x)
+ end
+end
+
+def fun_l2_n301(x)
+ if (x < 1)
+ fun_l3_n778(x)
+ else
+ fun_l3_n216(x)
+ end
+end
+
+def fun_l2_n302(x)
+ if (x < 1)
+ fun_l3_n366(x)
+ else
+ fun_l3_n562(x)
+ end
+end
+
+def fun_l2_n303(x)
+ if (x < 1)
+ fun_l3_n656(x)
+ else
+ fun_l3_n779(x)
+ end
+end
+
+def fun_l2_n304(x)
+ if (x < 1)
+ fun_l3_n526(x)
+ else
+ fun_l3_n783(x)
+ end
+end
+
+def fun_l2_n305(x)
+ if (x < 1)
+ fun_l3_n500(x)
+ else
+ fun_l3_n744(x)
+ end
+end
+
+def fun_l2_n306(x)
+ if (x < 1)
+ fun_l3_n953(x)
+ else
+ fun_l3_n394(x)
+ end
+end
+
+def fun_l2_n307(x)
+ if (x < 1)
+ fun_l3_n385(x)
+ else
+ fun_l3_n937(x)
+ end
+end
+
+def fun_l2_n308(x)
+ if (x < 1)
+ fun_l3_n742(x)
+ else
+ fun_l3_n984(x)
+ end
+end
+
+def fun_l2_n309(x)
+ if (x < 1)
+ fun_l3_n388(x)
+ else
+ fun_l3_n704(x)
+ end
+end
+
+def fun_l2_n310(x)
+ if (x < 1)
+ fun_l3_n252(x)
+ else
+ fun_l3_n585(x)
+ end
+end
+
+def fun_l2_n311(x)
+ if (x < 1)
+ fun_l3_n121(x)
+ else
+ fun_l3_n815(x)
+ end
+end
+
+def fun_l2_n312(x)
+ if (x < 1)
+ fun_l3_n657(x)
+ else
+ fun_l3_n338(x)
+ end
+end
+
+def fun_l2_n313(x)
+ if (x < 1)
+ fun_l3_n115(x)
+ else
+ fun_l3_n748(x)
+ end
+end
+
+def fun_l2_n314(x)
+ if (x < 1)
+ fun_l3_n237(x)
+ else
+ fun_l3_n319(x)
+ end
+end
+
+def fun_l2_n315(x)
+ if (x < 1)
+ fun_l3_n684(x)
+ else
+ fun_l3_n428(x)
+ end
+end
+
+def fun_l2_n316(x)
+ if (x < 1)
+ fun_l3_n416(x)
+ else
+ fun_l3_n499(x)
+ end
+end
+
+def fun_l2_n317(x)
+ if (x < 1)
+ fun_l3_n305(x)
+ else
+ fun_l3_n888(x)
+ end
+end
+
+def fun_l2_n318(x)
+ if (x < 1)
+ fun_l3_n506(x)
+ else
+ fun_l3_n579(x)
+ end
+end
+
+def fun_l2_n319(x)
+ if (x < 1)
+ fun_l3_n324(x)
+ else
+ fun_l3_n459(x)
+ end
+end
+
+def fun_l2_n320(x)
+ if (x < 1)
+ fun_l3_n278(x)
+ else
+ fun_l3_n89(x)
+ end
+end
+
+def fun_l2_n321(x)
+ if (x < 1)
+ fun_l3_n319(x)
+ else
+ fun_l3_n903(x)
+ end
+end
+
+def fun_l2_n322(x)
+ if (x < 1)
+ fun_l3_n96(x)
+ else
+ fun_l3_n334(x)
+ end
+end
+
+def fun_l2_n323(x)
+ if (x < 1)
+ fun_l3_n913(x)
+ else
+ fun_l3_n309(x)
+ end
+end
+
+def fun_l2_n324(x)
+ if (x < 1)
+ fun_l3_n186(x)
+ else
+ fun_l3_n453(x)
+ end
+end
+
+def fun_l2_n325(x)
+ if (x < 1)
+ fun_l3_n223(x)
+ else
+ fun_l3_n761(x)
+ end
+end
+
+def fun_l2_n326(x)
+ if (x < 1)
+ fun_l3_n757(x)
+ else
+ fun_l3_n700(x)
+ end
+end
+
+def fun_l2_n327(x)
+ if (x < 1)
+ fun_l3_n316(x)
+ else
+ fun_l3_n3(x)
+ end
+end
+
+def fun_l2_n328(x)
+ if (x < 1)
+ fun_l3_n680(x)
+ else
+ fun_l3_n275(x)
+ end
+end
+
+def fun_l2_n329(x)
+ if (x < 1)
+ fun_l3_n731(x)
+ else
+ fun_l3_n971(x)
+ end
+end
+
+def fun_l2_n330(x)
+ if (x < 1)
+ fun_l3_n672(x)
+ else
+ fun_l3_n389(x)
+ end
+end
+
+def fun_l2_n331(x)
+ if (x < 1)
+ fun_l3_n947(x)
+ else
+ fun_l3_n778(x)
+ end
+end
+
+def fun_l2_n332(x)
+ if (x < 1)
+ fun_l3_n23(x)
+ else
+ fun_l3_n478(x)
+ end
+end
+
+def fun_l2_n333(x)
+ if (x < 1)
+ fun_l3_n778(x)
+ else
+ fun_l3_n894(x)
+ end
+end
+
+def fun_l2_n334(x)
+ if (x < 1)
+ fun_l3_n198(x)
+ else
+ fun_l3_n830(x)
+ end
+end
+
+def fun_l2_n335(x)
+ if (x < 1)
+ fun_l3_n874(x)
+ else
+ fun_l3_n861(x)
+ end
+end
+
+def fun_l2_n336(x)
+ if (x < 1)
+ fun_l3_n66(x)
+ else
+ fun_l3_n47(x)
+ end
+end
+
+def fun_l2_n337(x)
+ if (x < 1)
+ fun_l3_n65(x)
+ else
+ fun_l3_n849(x)
+ end
+end
+
+def fun_l2_n338(x)
+ if (x < 1)
+ fun_l3_n122(x)
+ else
+ fun_l3_n891(x)
+ end
+end
+
+def fun_l2_n339(x)
+ if (x < 1)
+ fun_l3_n377(x)
+ else
+ fun_l3_n862(x)
+ end
+end
+
+def fun_l2_n340(x)
+ if (x < 1)
+ fun_l3_n278(x)
+ else
+ fun_l3_n495(x)
+ end
+end
+
+def fun_l2_n341(x)
+ if (x < 1)
+ fun_l3_n396(x)
+ else
+ fun_l3_n842(x)
+ end
+end
+
+def fun_l2_n342(x)
+ if (x < 1)
+ fun_l3_n971(x)
+ else
+ fun_l3_n296(x)
+ end
+end
+
+def fun_l2_n343(x)
+ if (x < 1)
+ fun_l3_n137(x)
+ else
+ fun_l3_n815(x)
+ end
+end
+
+def fun_l2_n344(x)
+ if (x < 1)
+ fun_l3_n910(x)
+ else
+ fun_l3_n515(x)
+ end
+end
+
+def fun_l2_n345(x)
+ if (x < 1)
+ fun_l3_n415(x)
+ else
+ fun_l3_n766(x)
+ end
+end
+
+def fun_l2_n346(x)
+ if (x < 1)
+ fun_l3_n816(x)
+ else
+ fun_l3_n169(x)
+ end
+end
+
+def fun_l2_n347(x)
+ if (x < 1)
+ fun_l3_n223(x)
+ else
+ fun_l3_n776(x)
+ end
+end
+
+def fun_l2_n348(x)
+ if (x < 1)
+ fun_l3_n316(x)
+ else
+ fun_l3_n497(x)
+ end
+end
+
+def fun_l2_n349(x)
+ if (x < 1)
+ fun_l3_n116(x)
+ else
+ fun_l3_n536(x)
+ end
+end
+
+def fun_l2_n350(x)
+ if (x < 1)
+ fun_l3_n252(x)
+ else
+ fun_l3_n981(x)
+ end
+end
+
+def fun_l2_n351(x)
+ if (x < 1)
+ fun_l3_n783(x)
+ else
+ fun_l3_n596(x)
+ end
+end
+
+def fun_l2_n352(x)
+ if (x < 1)
+ fun_l3_n72(x)
+ else
+ fun_l3_n978(x)
+ end
+end
+
+def fun_l2_n353(x)
+ if (x < 1)
+ fun_l3_n910(x)
+ else
+ fun_l3_n493(x)
+ end
+end
+
+def fun_l2_n354(x)
+ if (x < 1)
+ fun_l3_n671(x)
+ else
+ fun_l3_n297(x)
+ end
+end
+
+def fun_l2_n355(x)
+ if (x < 1)
+ fun_l3_n820(x)
+ else
+ fun_l3_n456(x)
+ end
+end
+
+def fun_l2_n356(x)
+ if (x < 1)
+ fun_l3_n23(x)
+ else
+ fun_l3_n760(x)
+ end
+end
+
+def fun_l2_n357(x)
+ if (x < 1)
+ fun_l3_n676(x)
+ else
+ fun_l3_n531(x)
+ end
+end
+
+def fun_l2_n358(x)
+ if (x < 1)
+ fun_l3_n849(x)
+ else
+ fun_l3_n592(x)
+ end
+end
+
+def fun_l2_n359(x)
+ if (x < 1)
+ fun_l3_n492(x)
+ else
+ fun_l3_n845(x)
+ end
+end
+
+def fun_l2_n360(x)
+ if (x < 1)
+ fun_l3_n58(x)
+ else
+ fun_l3_n896(x)
+ end
+end
+
+def fun_l2_n361(x)
+ if (x < 1)
+ fun_l3_n427(x)
+ else
+ fun_l3_n434(x)
+ end
+end
+
+def fun_l2_n362(x)
+ if (x < 1)
+ fun_l3_n129(x)
+ else
+ fun_l3_n582(x)
+ end
+end
+
+def fun_l2_n363(x)
+ if (x < 1)
+ fun_l3_n901(x)
+ else
+ fun_l3_n405(x)
+ end
+end
+
+def fun_l2_n364(x)
+ if (x < 1)
+ fun_l3_n577(x)
+ else
+ fun_l3_n550(x)
+ end
+end
+
+def fun_l2_n365(x)
+ if (x < 1)
+ fun_l3_n717(x)
+ else
+ fun_l3_n660(x)
+ end
+end
+
+def fun_l2_n366(x)
+ if (x < 1)
+ fun_l3_n605(x)
+ else
+ fun_l3_n755(x)
+ end
+end
+
+def fun_l2_n367(x)
+ if (x < 1)
+ fun_l3_n875(x)
+ else
+ fun_l3_n784(x)
+ end
+end
+
+def fun_l2_n368(x)
+ if (x < 1)
+ fun_l3_n914(x)
+ else
+ fun_l3_n351(x)
+ end
+end
+
+def fun_l2_n369(x)
+ if (x < 1)
+ fun_l3_n684(x)
+ else
+ fun_l3_n932(x)
+ end
+end
+
+def fun_l2_n370(x)
+ if (x < 1)
+ fun_l3_n796(x)
+ else
+ fun_l3_n920(x)
+ end
+end
+
+def fun_l2_n371(x)
+ if (x < 1)
+ fun_l3_n456(x)
+ else
+ fun_l3_n188(x)
+ end
+end
+
+def fun_l2_n372(x)
+ if (x < 1)
+ fun_l3_n891(x)
+ else
+ fun_l3_n905(x)
+ end
+end
+
+def fun_l2_n373(x)
+ if (x < 1)
+ fun_l3_n906(x)
+ else
+ fun_l3_n993(x)
+ end
+end
+
+def fun_l2_n374(x)
+ if (x < 1)
+ fun_l3_n811(x)
+ else
+ fun_l3_n629(x)
+ end
+end
+
+def fun_l2_n375(x)
+ if (x < 1)
+ fun_l3_n5(x)
+ else
+ fun_l3_n304(x)
+ end
+end
+
+def fun_l2_n376(x)
+ if (x < 1)
+ fun_l3_n240(x)
+ else
+ fun_l3_n859(x)
+ end
+end
+
+def fun_l2_n377(x)
+ if (x < 1)
+ fun_l3_n346(x)
+ else
+ fun_l3_n196(x)
+ end
+end
+
+def fun_l2_n378(x)
+ if (x < 1)
+ fun_l3_n918(x)
+ else
+ fun_l3_n371(x)
+ end
+end
+
+def fun_l2_n379(x)
+ if (x < 1)
+ fun_l3_n112(x)
+ else
+ fun_l3_n269(x)
+ end
+end
+
+def fun_l2_n380(x)
+ if (x < 1)
+ fun_l3_n46(x)
+ else
+ fun_l3_n397(x)
+ end
+end
+
+def fun_l2_n381(x)
+ if (x < 1)
+ fun_l3_n977(x)
+ else
+ fun_l3_n647(x)
+ end
+end
+
+def fun_l2_n382(x)
+ if (x < 1)
+ fun_l3_n788(x)
+ else
+ fun_l3_n418(x)
+ end
+end
+
+def fun_l2_n383(x)
+ if (x < 1)
+ fun_l3_n395(x)
+ else
+ fun_l3_n268(x)
+ end
+end
+
+def fun_l2_n384(x)
+ if (x < 1)
+ fun_l3_n39(x)
+ else
+ fun_l3_n950(x)
+ end
+end
+
+def fun_l2_n385(x)
+ if (x < 1)
+ fun_l3_n301(x)
+ else
+ fun_l3_n241(x)
+ end
+end
+
+def fun_l2_n386(x)
+ if (x < 1)
+ fun_l3_n936(x)
+ else
+ fun_l3_n416(x)
+ end
+end
+
+def fun_l2_n387(x)
+ if (x < 1)
+ fun_l3_n750(x)
+ else
+ fun_l3_n152(x)
+ end
+end
+
+def fun_l2_n388(x)
+ if (x < 1)
+ fun_l3_n210(x)
+ else
+ fun_l3_n824(x)
+ end
+end
+
+def fun_l2_n389(x)
+ if (x < 1)
+ fun_l3_n3(x)
+ else
+ fun_l3_n872(x)
+ end
+end
+
+def fun_l2_n390(x)
+ if (x < 1)
+ fun_l3_n944(x)
+ else
+ fun_l3_n49(x)
+ end
+end
+
+def fun_l2_n391(x)
+ if (x < 1)
+ fun_l3_n645(x)
+ else
+ fun_l3_n604(x)
+ end
+end
+
+def fun_l2_n392(x)
+ if (x < 1)
+ fun_l3_n539(x)
+ else
+ fun_l3_n374(x)
+ end
+end
+
+def fun_l2_n393(x)
+ if (x < 1)
+ fun_l3_n728(x)
+ else
+ fun_l3_n620(x)
+ end
+end
+
+def fun_l2_n394(x)
+ if (x < 1)
+ fun_l3_n538(x)
+ else
+ fun_l3_n233(x)
+ end
+end
+
+def fun_l2_n395(x)
+ if (x < 1)
+ fun_l3_n977(x)
+ else
+ fun_l3_n351(x)
+ end
+end
+
+def fun_l2_n396(x)
+ if (x < 1)
+ fun_l3_n54(x)
+ else
+ fun_l3_n958(x)
+ end
+end
+
+def fun_l2_n397(x)
+ if (x < 1)
+ fun_l3_n237(x)
+ else
+ fun_l3_n54(x)
+ end
+end
+
+def fun_l2_n398(x)
+ if (x < 1)
+ fun_l3_n846(x)
+ else
+ fun_l3_n234(x)
+ end
+end
+
+def fun_l2_n399(x)
+ if (x < 1)
+ fun_l3_n934(x)
+ else
+ fun_l3_n128(x)
+ end
+end
+
+def fun_l2_n400(x)
+ if (x < 1)
+ fun_l3_n15(x)
+ else
+ fun_l3_n288(x)
+ end
+end
+
+def fun_l2_n401(x)
+ if (x < 1)
+ fun_l3_n944(x)
+ else
+ fun_l3_n455(x)
+ end
+end
+
+def fun_l2_n402(x)
+ if (x < 1)
+ fun_l3_n962(x)
+ else
+ fun_l3_n785(x)
+ end
+end
+
+def fun_l2_n403(x)
+ if (x < 1)
+ fun_l3_n408(x)
+ else
+ fun_l3_n689(x)
+ end
+end
+
+def fun_l2_n404(x)
+ if (x < 1)
+ fun_l3_n722(x)
+ else
+ fun_l3_n704(x)
+ end
+end
+
+def fun_l2_n405(x)
+ if (x < 1)
+ fun_l3_n410(x)
+ else
+ fun_l3_n543(x)
+ end
+end
+
+def fun_l2_n406(x)
+ if (x < 1)
+ fun_l3_n953(x)
+ else
+ fun_l3_n351(x)
+ end
+end
+
+def fun_l2_n407(x)
+ if (x < 1)
+ fun_l3_n426(x)
+ else
+ fun_l3_n467(x)
+ end
+end
+
+def fun_l2_n408(x)
+ if (x < 1)
+ fun_l3_n204(x)
+ else
+ fun_l3_n163(x)
+ end
+end
+
+def fun_l2_n409(x)
+ if (x < 1)
+ fun_l3_n418(x)
+ else
+ fun_l3_n896(x)
+ end
+end
+
+def fun_l2_n410(x)
+ if (x < 1)
+ fun_l3_n915(x)
+ else
+ fun_l3_n800(x)
+ end
+end
+
+def fun_l2_n411(x)
+ if (x < 1)
+ fun_l3_n580(x)
+ else
+ fun_l3_n507(x)
+ end
+end
+
+def fun_l2_n412(x)
+ if (x < 1)
+ fun_l3_n672(x)
+ else
+ fun_l3_n938(x)
+ end
+end
+
+def fun_l2_n413(x)
+ if (x < 1)
+ fun_l3_n112(x)
+ else
+ fun_l3_n927(x)
+ end
+end
+
+def fun_l2_n414(x)
+ if (x < 1)
+ fun_l3_n801(x)
+ else
+ fun_l3_n604(x)
+ end
+end
+
+def fun_l2_n415(x)
+ if (x < 1)
+ fun_l3_n773(x)
+ else
+ fun_l3_n951(x)
+ end
+end
+
+def fun_l2_n416(x)
+ if (x < 1)
+ fun_l3_n335(x)
+ else
+ fun_l3_n157(x)
+ end
+end
+
+def fun_l2_n417(x)
+ if (x < 1)
+ fun_l3_n480(x)
+ else
+ fun_l3_n106(x)
+ end
+end
+
+def fun_l2_n418(x)
+ if (x < 1)
+ fun_l3_n523(x)
+ else
+ fun_l3_n969(x)
+ end
+end
+
+def fun_l2_n419(x)
+ if (x < 1)
+ fun_l3_n371(x)
+ else
+ fun_l3_n698(x)
+ end
+end
+
+def fun_l2_n420(x)
+ if (x < 1)
+ fun_l3_n102(x)
+ else
+ fun_l3_n47(x)
+ end
+end
+
+def fun_l2_n421(x)
+ if (x < 1)
+ fun_l3_n64(x)
+ else
+ fun_l3_n574(x)
+ end
+end
+
+def fun_l2_n422(x)
+ if (x < 1)
+ fun_l3_n208(x)
+ else
+ fun_l3_n904(x)
+ end
+end
+
+def fun_l2_n423(x)
+ if (x < 1)
+ fun_l3_n715(x)
+ else
+ fun_l3_n414(x)
+ end
+end
+
+def fun_l2_n424(x)
+ if (x < 1)
+ fun_l3_n455(x)
+ else
+ fun_l3_n219(x)
+ end
+end
+
+def fun_l2_n425(x)
+ if (x < 1)
+ fun_l3_n210(x)
+ else
+ fun_l3_n160(x)
+ end
+end
+
+def fun_l2_n426(x)
+ if (x < 1)
+ fun_l3_n729(x)
+ else
+ fun_l3_n512(x)
+ end
+end
+
+def fun_l2_n427(x)
+ if (x < 1)
+ fun_l3_n159(x)
+ else
+ fun_l3_n482(x)
+ end
+end
+
+def fun_l2_n428(x)
+ if (x < 1)
+ fun_l3_n182(x)
+ else
+ fun_l3_n687(x)
+ end
+end
+
+def fun_l2_n429(x)
+ if (x < 1)
+ fun_l3_n690(x)
+ else
+ fun_l3_n856(x)
+ end
+end
+
+def fun_l2_n430(x)
+ if (x < 1)
+ fun_l3_n494(x)
+ else
+ fun_l3_n365(x)
+ end
+end
+
+def fun_l2_n431(x)
+ if (x < 1)
+ fun_l3_n346(x)
+ else
+ fun_l3_n82(x)
+ end
+end
+
+def fun_l2_n432(x)
+ if (x < 1)
+ fun_l3_n311(x)
+ else
+ fun_l3_n412(x)
+ end
+end
+
+def fun_l2_n433(x)
+ if (x < 1)
+ fun_l3_n824(x)
+ else
+ fun_l3_n494(x)
+ end
+end
+
+def fun_l2_n434(x)
+ if (x < 1)
+ fun_l3_n471(x)
+ else
+ fun_l3_n174(x)
+ end
+end
+
+def fun_l2_n435(x)
+ if (x < 1)
+ fun_l3_n10(x)
+ else
+ fun_l3_n319(x)
+ end
+end
+
+def fun_l2_n436(x)
+ if (x < 1)
+ fun_l3_n223(x)
+ else
+ fun_l3_n518(x)
+ end
+end
+
+def fun_l2_n437(x)
+ if (x < 1)
+ fun_l3_n497(x)
+ else
+ fun_l3_n685(x)
+ end
+end
+
+def fun_l2_n438(x)
+ if (x < 1)
+ fun_l3_n639(x)
+ else
+ fun_l3_n695(x)
+ end
+end
+
+def fun_l2_n439(x)
+ if (x < 1)
+ fun_l3_n898(x)
+ else
+ fun_l3_n114(x)
+ end
+end
+
+def fun_l2_n440(x)
+ if (x < 1)
+ fun_l3_n12(x)
+ else
+ fun_l3_n344(x)
+ end
+end
+
+def fun_l2_n441(x)
+ if (x < 1)
+ fun_l3_n556(x)
+ else
+ fun_l3_n684(x)
+ end
+end
+
+def fun_l2_n442(x)
+ if (x < 1)
+ fun_l3_n403(x)
+ else
+ fun_l3_n528(x)
+ end
+end
+
+def fun_l2_n443(x)
+ if (x < 1)
+ fun_l3_n514(x)
+ else
+ fun_l3_n943(x)
+ end
+end
+
+def fun_l2_n444(x)
+ if (x < 1)
+ fun_l3_n218(x)
+ else
+ fun_l3_n94(x)
+ end
+end
+
+def fun_l2_n445(x)
+ if (x < 1)
+ fun_l3_n0(x)
+ else
+ fun_l3_n731(x)
+ end
+end
+
+def fun_l2_n446(x)
+ if (x < 1)
+ fun_l3_n468(x)
+ else
+ fun_l3_n197(x)
+ end
+end
+
+def fun_l2_n447(x)
+ if (x < 1)
+ fun_l3_n79(x)
+ else
+ fun_l3_n900(x)
+ end
+end
+
+def fun_l2_n448(x)
+ if (x < 1)
+ fun_l3_n706(x)
+ else
+ fun_l3_n250(x)
+ end
+end
+
+def fun_l2_n449(x)
+ if (x < 1)
+ fun_l3_n607(x)
+ else
+ fun_l3_n514(x)
+ end
+end
+
+def fun_l2_n450(x)
+ if (x < 1)
+ fun_l3_n855(x)
+ else
+ fun_l3_n223(x)
+ end
+end
+
+def fun_l2_n451(x)
+ if (x < 1)
+ fun_l3_n824(x)
+ else
+ fun_l3_n426(x)
+ end
+end
+
+def fun_l2_n452(x)
+ if (x < 1)
+ fun_l3_n137(x)
+ else
+ fun_l3_n555(x)
+ end
+end
+
+def fun_l2_n453(x)
+ if (x < 1)
+ fun_l3_n553(x)
+ else
+ fun_l3_n130(x)
+ end
+end
+
+def fun_l2_n454(x)
+ if (x < 1)
+ fun_l3_n350(x)
+ else
+ fun_l3_n545(x)
+ end
+end
+
+def fun_l2_n455(x)
+ if (x < 1)
+ fun_l3_n181(x)
+ else
+ fun_l3_n950(x)
+ end
+end
+
+def fun_l2_n456(x)
+ if (x < 1)
+ fun_l3_n581(x)
+ else
+ fun_l3_n957(x)
+ end
+end
+
+def fun_l2_n457(x)
+ if (x < 1)
+ fun_l3_n688(x)
+ else
+ fun_l3_n560(x)
+ end
+end
+
+def fun_l2_n458(x)
+ if (x < 1)
+ fun_l3_n655(x)
+ else
+ fun_l3_n323(x)
+ end
+end
+
+def fun_l2_n459(x)
+ if (x < 1)
+ fun_l3_n92(x)
+ else
+ fun_l3_n796(x)
+ end
+end
+
+def fun_l2_n460(x)
+ if (x < 1)
+ fun_l3_n68(x)
+ else
+ fun_l3_n152(x)
+ end
+end
+
+def fun_l2_n461(x)
+ if (x < 1)
+ fun_l3_n153(x)
+ else
+ fun_l3_n929(x)
+ end
+end
+
+def fun_l2_n462(x)
+ if (x < 1)
+ fun_l3_n401(x)
+ else
+ fun_l3_n248(x)
+ end
+end
+
+def fun_l2_n463(x)
+ if (x < 1)
+ fun_l3_n4(x)
+ else
+ fun_l3_n906(x)
+ end
+end
+
+def fun_l2_n464(x)
+ if (x < 1)
+ fun_l3_n313(x)
+ else
+ fun_l3_n911(x)
+ end
+end
+
+def fun_l2_n465(x)
+ if (x < 1)
+ fun_l3_n490(x)
+ else
+ fun_l3_n430(x)
+ end
+end
+
+def fun_l2_n466(x)
+ if (x < 1)
+ fun_l3_n537(x)
+ else
+ fun_l3_n470(x)
+ end
+end
+
+def fun_l2_n467(x)
+ if (x < 1)
+ fun_l3_n666(x)
+ else
+ fun_l3_n695(x)
+ end
+end
+
+def fun_l2_n468(x)
+ if (x < 1)
+ fun_l3_n126(x)
+ else
+ fun_l3_n201(x)
+ end
+end
+
+def fun_l2_n469(x)
+ if (x < 1)
+ fun_l3_n111(x)
+ else
+ fun_l3_n741(x)
+ end
+end
+
+def fun_l2_n470(x)
+ if (x < 1)
+ fun_l3_n391(x)
+ else
+ fun_l3_n83(x)
+ end
+end
+
+def fun_l2_n471(x)
+ if (x < 1)
+ fun_l3_n619(x)
+ else
+ fun_l3_n425(x)
+ end
+end
+
+def fun_l2_n472(x)
+ if (x < 1)
+ fun_l3_n637(x)
+ else
+ fun_l3_n865(x)
+ end
+end
+
+def fun_l2_n473(x)
+ if (x < 1)
+ fun_l3_n182(x)
+ else
+ fun_l3_n350(x)
+ end
+end
+
+def fun_l2_n474(x)
+ if (x < 1)
+ fun_l3_n752(x)
+ else
+ fun_l3_n815(x)
+ end
+end
+
+def fun_l2_n475(x)
+ if (x < 1)
+ fun_l3_n184(x)
+ else
+ fun_l3_n683(x)
+ end
+end
+
+def fun_l2_n476(x)
+ if (x < 1)
+ fun_l3_n324(x)
+ else
+ fun_l3_n232(x)
+ end
+end
+
+def fun_l2_n477(x)
+ if (x < 1)
+ fun_l3_n588(x)
+ else
+ fun_l3_n586(x)
+ end
+end
+
+def fun_l2_n478(x)
+ if (x < 1)
+ fun_l3_n320(x)
+ else
+ fun_l3_n599(x)
+ end
+end
+
+def fun_l2_n479(x)
+ if (x < 1)
+ fun_l3_n999(x)
+ else
+ fun_l3_n678(x)
+ end
+end
+
+def fun_l2_n480(x)
+ if (x < 1)
+ fun_l3_n523(x)
+ else
+ fun_l3_n637(x)
+ end
+end
+
+def fun_l2_n481(x)
+ if (x < 1)
+ fun_l3_n291(x)
+ else
+ fun_l3_n347(x)
+ end
+end
+
+def fun_l2_n482(x)
+ if (x < 1)
+ fun_l3_n873(x)
+ else
+ fun_l3_n435(x)
+ end
+end
+
+def fun_l2_n483(x)
+ if (x < 1)
+ fun_l3_n718(x)
+ else
+ fun_l3_n903(x)
+ end
+end
+
+def fun_l2_n484(x)
+ if (x < 1)
+ fun_l3_n188(x)
+ else
+ fun_l3_n751(x)
+ end
+end
+
+def fun_l2_n485(x)
+ if (x < 1)
+ fun_l3_n501(x)
+ else
+ fun_l3_n235(x)
+ end
+end
+
+def fun_l2_n486(x)
+ if (x < 1)
+ fun_l3_n578(x)
+ else
+ fun_l3_n224(x)
+ end
+end
+
+def fun_l2_n487(x)
+ if (x < 1)
+ fun_l3_n757(x)
+ else
+ fun_l3_n145(x)
+ end
+end
+
+def fun_l2_n488(x)
+ if (x < 1)
+ fun_l3_n17(x)
+ else
+ fun_l3_n727(x)
+ end
+end
+
+def fun_l2_n489(x)
+ if (x < 1)
+ fun_l3_n699(x)
+ else
+ fun_l3_n102(x)
+ end
+end
+
+def fun_l2_n490(x)
+ if (x < 1)
+ fun_l3_n518(x)
+ else
+ fun_l3_n15(x)
+ end
+end
+
+def fun_l2_n491(x)
+ if (x < 1)
+ fun_l3_n889(x)
+ else
+ fun_l3_n798(x)
+ end
+end
+
+def fun_l2_n492(x)
+ if (x < 1)
+ fun_l3_n715(x)
+ else
+ fun_l3_n27(x)
+ end
+end
+
+def fun_l2_n493(x)
+ if (x < 1)
+ fun_l3_n237(x)
+ else
+ fun_l3_n130(x)
+ end
+end
+
+def fun_l2_n494(x)
+ if (x < 1)
+ fun_l3_n99(x)
+ else
+ fun_l3_n223(x)
+ end
+end
+
+def fun_l2_n495(x)
+ if (x < 1)
+ fun_l3_n65(x)
+ else
+ fun_l3_n811(x)
+ end
+end
+
+def fun_l2_n496(x)
+ if (x < 1)
+ fun_l3_n457(x)
+ else
+ fun_l3_n527(x)
+ end
+end
+
+def fun_l2_n497(x)
+ if (x < 1)
+ fun_l3_n312(x)
+ else
+ fun_l3_n902(x)
+ end
+end
+
+def fun_l2_n498(x)
+ if (x < 1)
+ fun_l3_n63(x)
+ else
+ fun_l3_n948(x)
+ end
+end
+
+def fun_l2_n499(x)
+ if (x < 1)
+ fun_l3_n652(x)
+ else
+ fun_l3_n752(x)
+ end
+end
+
+def fun_l2_n500(x)
+ if (x < 1)
+ fun_l3_n583(x)
+ else
+ fun_l3_n427(x)
+ end
+end
+
+def fun_l2_n501(x)
+ if (x < 1)
+ fun_l3_n536(x)
+ else
+ fun_l3_n671(x)
+ end
+end
+
+def fun_l2_n502(x)
+ if (x < 1)
+ fun_l3_n122(x)
+ else
+ fun_l3_n170(x)
+ end
+end
+
+def fun_l2_n503(x)
+ if (x < 1)
+ fun_l3_n280(x)
+ else
+ fun_l3_n390(x)
+ end
+end
+
+def fun_l2_n504(x)
+ if (x < 1)
+ fun_l3_n427(x)
+ else
+ fun_l3_n267(x)
+ end
+end
+
+def fun_l2_n505(x)
+ if (x < 1)
+ fun_l3_n241(x)
+ else
+ fun_l3_n345(x)
+ end
+end
+
+def fun_l2_n506(x)
+ if (x < 1)
+ fun_l3_n960(x)
+ else
+ fun_l3_n537(x)
+ end
+end
+
+def fun_l2_n507(x)
+ if (x < 1)
+ fun_l3_n947(x)
+ else
+ fun_l3_n3(x)
+ end
+end
+
+def fun_l2_n508(x)
+ if (x < 1)
+ fun_l3_n974(x)
+ else
+ fun_l3_n597(x)
+ end
+end
+
+def fun_l2_n509(x)
+ if (x < 1)
+ fun_l3_n978(x)
+ else
+ fun_l3_n70(x)
+ end
+end
+
+def fun_l2_n510(x)
+ if (x < 1)
+ fun_l3_n855(x)
+ else
+ fun_l3_n259(x)
+ end
+end
+
+def fun_l2_n511(x)
+ if (x < 1)
+ fun_l3_n987(x)
+ else
+ fun_l3_n182(x)
+ end
+end
+
+def fun_l2_n512(x)
+ if (x < 1)
+ fun_l3_n787(x)
+ else
+ fun_l3_n656(x)
+ end
+end
+
+def fun_l2_n513(x)
+ if (x < 1)
+ fun_l3_n348(x)
+ else
+ fun_l3_n242(x)
+ end
+end
+
+def fun_l2_n514(x)
+ if (x < 1)
+ fun_l3_n530(x)
+ else
+ fun_l3_n718(x)
+ end
+end
+
+def fun_l2_n515(x)
+ if (x < 1)
+ fun_l3_n840(x)
+ else
+ fun_l3_n302(x)
+ end
+end
+
+def fun_l2_n516(x)
+ if (x < 1)
+ fun_l3_n678(x)
+ else
+ fun_l3_n732(x)
+ end
+end
+
+def fun_l2_n517(x)
+ if (x < 1)
+ fun_l3_n160(x)
+ else
+ fun_l3_n344(x)
+ end
+end
+
+def fun_l2_n518(x)
+ if (x < 1)
+ fun_l3_n518(x)
+ else
+ fun_l3_n830(x)
+ end
+end
+
+def fun_l2_n519(x)
+ if (x < 1)
+ fun_l3_n595(x)
+ else
+ fun_l3_n95(x)
+ end
+end
+
+def fun_l2_n520(x)
+ if (x < 1)
+ fun_l3_n939(x)
+ else
+ fun_l3_n954(x)
+ end
+end
+
+def fun_l2_n521(x)
+ if (x < 1)
+ fun_l3_n931(x)
+ else
+ fun_l3_n686(x)
+ end
+end
+
+def fun_l2_n522(x)
+ if (x < 1)
+ fun_l3_n117(x)
+ else
+ fun_l3_n501(x)
+ end
+end
+
+def fun_l2_n523(x)
+ if (x < 1)
+ fun_l3_n727(x)
+ else
+ fun_l3_n712(x)
+ end
+end
+
+def fun_l2_n524(x)
+ if (x < 1)
+ fun_l3_n152(x)
+ else
+ fun_l3_n453(x)
+ end
+end
+
+def fun_l2_n525(x)
+ if (x < 1)
+ fun_l3_n375(x)
+ else
+ fun_l3_n186(x)
+ end
+end
+
+def fun_l2_n526(x)
+ if (x < 1)
+ fun_l3_n835(x)
+ else
+ fun_l3_n465(x)
+ end
+end
+
+def fun_l2_n527(x)
+ if (x < 1)
+ fun_l3_n411(x)
+ else
+ fun_l3_n208(x)
+ end
+end
+
+def fun_l2_n528(x)
+ if (x < 1)
+ fun_l3_n696(x)
+ else
+ fun_l3_n537(x)
+ end
+end
+
+def fun_l2_n529(x)
+ if (x < 1)
+ fun_l3_n606(x)
+ else
+ fun_l3_n682(x)
+ end
+end
+
+def fun_l2_n530(x)
+ if (x < 1)
+ fun_l3_n920(x)
+ else
+ fun_l3_n592(x)
+ end
+end
+
+def fun_l2_n531(x)
+ if (x < 1)
+ fun_l3_n201(x)
+ else
+ fun_l3_n27(x)
+ end
+end
+
+def fun_l2_n532(x)
+ if (x < 1)
+ fun_l3_n643(x)
+ else
+ fun_l3_n642(x)
+ end
+end
+
+def fun_l2_n533(x)
+ if (x < 1)
+ fun_l3_n92(x)
+ else
+ fun_l3_n576(x)
+ end
+end
+
+def fun_l2_n534(x)
+ if (x < 1)
+ fun_l3_n135(x)
+ else
+ fun_l3_n738(x)
+ end
+end
+
+def fun_l2_n535(x)
+ if (x < 1)
+ fun_l3_n706(x)
+ else
+ fun_l3_n810(x)
+ end
+end
+
+def fun_l2_n536(x)
+ if (x < 1)
+ fun_l3_n922(x)
+ else
+ fun_l3_n456(x)
+ end
+end
+
+def fun_l2_n537(x)
+ if (x < 1)
+ fun_l3_n511(x)
+ else
+ fun_l3_n279(x)
+ end
+end
+
+def fun_l2_n538(x)
+ if (x < 1)
+ fun_l3_n541(x)
+ else
+ fun_l3_n826(x)
+ end
+end
+
+def fun_l2_n539(x)
+ if (x < 1)
+ fun_l3_n7(x)
+ else
+ fun_l3_n362(x)
+ end
+end
+
+def fun_l2_n540(x)
+ if (x < 1)
+ fun_l3_n132(x)
+ else
+ fun_l3_n819(x)
+ end
+end
+
+def fun_l2_n541(x)
+ if (x < 1)
+ fun_l3_n600(x)
+ else
+ fun_l3_n155(x)
+ end
+end
+
+def fun_l2_n542(x)
+ if (x < 1)
+ fun_l3_n930(x)
+ else
+ fun_l3_n827(x)
+ end
+end
+
+def fun_l2_n543(x)
+ if (x < 1)
+ fun_l3_n974(x)
+ else
+ fun_l3_n957(x)
+ end
+end
+
+def fun_l2_n544(x)
+ if (x < 1)
+ fun_l3_n912(x)
+ else
+ fun_l3_n503(x)
+ end
+end
+
+def fun_l2_n545(x)
+ if (x < 1)
+ fun_l3_n605(x)
+ else
+ fun_l3_n966(x)
+ end
+end
+
+def fun_l2_n546(x)
+ if (x < 1)
+ fun_l3_n523(x)
+ else
+ fun_l3_n105(x)
+ end
+end
+
+def fun_l2_n547(x)
+ if (x < 1)
+ fun_l3_n352(x)
+ else
+ fun_l3_n762(x)
+ end
+end
+
+def fun_l2_n548(x)
+ if (x < 1)
+ fun_l3_n65(x)
+ else
+ fun_l3_n714(x)
+ end
+end
+
+def fun_l2_n549(x)
+ if (x < 1)
+ fun_l3_n665(x)
+ else
+ fun_l3_n799(x)
+ end
+end
+
+def fun_l2_n550(x)
+ if (x < 1)
+ fun_l3_n624(x)
+ else
+ fun_l3_n131(x)
+ end
+end
+
+def fun_l2_n551(x)
+ if (x < 1)
+ fun_l3_n53(x)
+ else
+ fun_l3_n377(x)
+ end
+end
+
+def fun_l2_n552(x)
+ if (x < 1)
+ fun_l3_n377(x)
+ else
+ fun_l3_n532(x)
+ end
+end
+
+def fun_l2_n553(x)
+ if (x < 1)
+ fun_l3_n302(x)
+ else
+ fun_l3_n593(x)
+ end
+end
+
+def fun_l2_n554(x)
+ if (x < 1)
+ fun_l3_n573(x)
+ else
+ fun_l3_n727(x)
+ end
+end
+
+def fun_l2_n555(x)
+ if (x < 1)
+ fun_l3_n575(x)
+ else
+ fun_l3_n838(x)
+ end
+end
+
+def fun_l2_n556(x)
+ if (x < 1)
+ fun_l3_n92(x)
+ else
+ fun_l3_n137(x)
+ end
+end
+
+def fun_l2_n557(x)
+ if (x < 1)
+ fun_l3_n921(x)
+ else
+ fun_l3_n683(x)
+ end
+end
+
+def fun_l2_n558(x)
+ if (x < 1)
+ fun_l3_n987(x)
+ else
+ fun_l3_n646(x)
+ end
+end
+
+def fun_l2_n559(x)
+ if (x < 1)
+ fun_l3_n574(x)
+ else
+ fun_l3_n493(x)
+ end
+end
+
+def fun_l2_n560(x)
+ if (x < 1)
+ fun_l3_n950(x)
+ else
+ fun_l3_n139(x)
+ end
+end
+
+def fun_l2_n561(x)
+ if (x < 1)
+ fun_l3_n276(x)
+ else
+ fun_l3_n491(x)
+ end
+end
+
+def fun_l2_n562(x)
+ if (x < 1)
+ fun_l3_n226(x)
+ else
+ fun_l3_n840(x)
+ end
+end
+
+def fun_l2_n563(x)
+ if (x < 1)
+ fun_l3_n473(x)
+ else
+ fun_l3_n907(x)
+ end
+end
+
+def fun_l2_n564(x)
+ if (x < 1)
+ fun_l3_n695(x)
+ else
+ fun_l3_n951(x)
+ end
+end
+
+def fun_l2_n565(x)
+ if (x < 1)
+ fun_l3_n415(x)
+ else
+ fun_l3_n12(x)
+ end
+end
+
+def fun_l2_n566(x)
+ if (x < 1)
+ fun_l3_n32(x)
+ else
+ fun_l3_n759(x)
+ end
+end
+
+def fun_l2_n567(x)
+ if (x < 1)
+ fun_l3_n876(x)
+ else
+ fun_l3_n297(x)
+ end
+end
+
+def fun_l2_n568(x)
+ if (x < 1)
+ fun_l3_n520(x)
+ else
+ fun_l3_n713(x)
+ end
+end
+
+def fun_l2_n569(x)
+ if (x < 1)
+ fun_l3_n819(x)
+ else
+ fun_l3_n505(x)
+ end
+end
+
+def fun_l2_n570(x)
+ if (x < 1)
+ fun_l3_n661(x)
+ else
+ fun_l3_n447(x)
+ end
+end
+
+def fun_l2_n571(x)
+ if (x < 1)
+ fun_l3_n538(x)
+ else
+ fun_l3_n532(x)
+ end
+end
+
+def fun_l2_n572(x)
+ if (x < 1)
+ fun_l3_n584(x)
+ else
+ fun_l3_n304(x)
+ end
+end
+
+def fun_l2_n573(x)
+ if (x < 1)
+ fun_l3_n76(x)
+ else
+ fun_l3_n512(x)
+ end
+end
+
+def fun_l2_n574(x)
+ if (x < 1)
+ fun_l3_n22(x)
+ else
+ fun_l3_n328(x)
+ end
+end
+
+def fun_l2_n575(x)
+ if (x < 1)
+ fun_l3_n397(x)
+ else
+ fun_l3_n640(x)
+ end
+end
+
+def fun_l2_n576(x)
+ if (x < 1)
+ fun_l3_n227(x)
+ else
+ fun_l3_n236(x)
+ end
+end
+
+def fun_l2_n577(x)
+ if (x < 1)
+ fun_l3_n743(x)
+ else
+ fun_l3_n974(x)
+ end
+end
+
+def fun_l2_n578(x)
+ if (x < 1)
+ fun_l3_n970(x)
+ else
+ fun_l3_n229(x)
+ end
+end
+
+def fun_l2_n579(x)
+ if (x < 1)
+ fun_l3_n401(x)
+ else
+ fun_l3_n672(x)
+ end
+end
+
+def fun_l2_n580(x)
+ if (x < 1)
+ fun_l3_n837(x)
+ else
+ fun_l3_n804(x)
+ end
+end
+
+def fun_l2_n581(x)
+ if (x < 1)
+ fun_l3_n526(x)
+ else
+ fun_l3_n763(x)
+ end
+end
+
+def fun_l2_n582(x)
+ if (x < 1)
+ fun_l3_n2(x)
+ else
+ fun_l3_n692(x)
+ end
+end
+
+def fun_l2_n583(x)
+ if (x < 1)
+ fun_l3_n561(x)
+ else
+ fun_l3_n394(x)
+ end
+end
+
+def fun_l2_n584(x)
+ if (x < 1)
+ fun_l3_n60(x)
+ else
+ fun_l3_n682(x)
+ end
+end
+
+def fun_l2_n585(x)
+ if (x < 1)
+ fun_l3_n646(x)
+ else
+ fun_l3_n776(x)
+ end
+end
+
+def fun_l2_n586(x)
+ if (x < 1)
+ fun_l3_n466(x)
+ else
+ fun_l3_n91(x)
+ end
+end
+
+def fun_l2_n587(x)
+ if (x < 1)
+ fun_l3_n294(x)
+ else
+ fun_l3_n813(x)
+ end
+end
+
+def fun_l2_n588(x)
+ if (x < 1)
+ fun_l3_n958(x)
+ else
+ fun_l3_n64(x)
+ end
+end
+
+def fun_l2_n589(x)
+ if (x < 1)
+ fun_l3_n703(x)
+ else
+ fun_l3_n937(x)
+ end
+end
+
+def fun_l2_n590(x)
+ if (x < 1)
+ fun_l3_n1(x)
+ else
+ fun_l3_n970(x)
+ end
+end
+
+def fun_l2_n591(x)
+ if (x < 1)
+ fun_l3_n566(x)
+ else
+ fun_l3_n750(x)
+ end
+end
+
+def fun_l2_n592(x)
+ if (x < 1)
+ fun_l3_n905(x)
+ else
+ fun_l3_n840(x)
+ end
+end
+
+def fun_l2_n593(x)
+ if (x < 1)
+ fun_l3_n23(x)
+ else
+ fun_l3_n862(x)
+ end
+end
+
+def fun_l2_n594(x)
+ if (x < 1)
+ fun_l3_n739(x)
+ else
+ fun_l3_n4(x)
+ end
+end
+
+def fun_l2_n595(x)
+ if (x < 1)
+ fun_l3_n818(x)
+ else
+ fun_l3_n117(x)
+ end
+end
+
+def fun_l2_n596(x)
+ if (x < 1)
+ fun_l3_n891(x)
+ else
+ fun_l3_n599(x)
+ end
+end
+
+def fun_l2_n597(x)
+ if (x < 1)
+ fun_l3_n731(x)
+ else
+ fun_l3_n960(x)
+ end
+end
+
+def fun_l2_n598(x)
+ if (x < 1)
+ fun_l3_n323(x)
+ else
+ fun_l3_n811(x)
+ end
+end
+
+def fun_l2_n599(x)
+ if (x < 1)
+ fun_l3_n299(x)
+ else
+ fun_l3_n188(x)
+ end
+end
+
+def fun_l2_n600(x)
+ if (x < 1)
+ fun_l3_n129(x)
+ else
+ fun_l3_n730(x)
+ end
+end
+
+def fun_l2_n601(x)
+ if (x < 1)
+ fun_l3_n412(x)
+ else
+ fun_l3_n353(x)
+ end
+end
+
+def fun_l2_n602(x)
+ if (x < 1)
+ fun_l3_n658(x)
+ else
+ fun_l3_n774(x)
+ end
+end
+
+def fun_l2_n603(x)
+ if (x < 1)
+ fun_l3_n378(x)
+ else
+ fun_l3_n722(x)
+ end
+end
+
+def fun_l2_n604(x)
+ if (x < 1)
+ fun_l3_n482(x)
+ else
+ fun_l3_n949(x)
+ end
+end
+
+def fun_l2_n605(x)
+ if (x < 1)
+ fun_l3_n996(x)
+ else
+ fun_l3_n169(x)
+ end
+end
+
+def fun_l2_n606(x)
+ if (x < 1)
+ fun_l3_n653(x)
+ else
+ fun_l3_n966(x)
+ end
+end
+
+def fun_l2_n607(x)
+ if (x < 1)
+ fun_l3_n179(x)
+ else
+ fun_l3_n113(x)
+ end
+end
+
+def fun_l2_n608(x)
+ if (x < 1)
+ fun_l3_n157(x)
+ else
+ fun_l3_n692(x)
+ end
+end
+
+def fun_l2_n609(x)
+ if (x < 1)
+ fun_l3_n648(x)
+ else
+ fun_l3_n318(x)
+ end
+end
+
+def fun_l2_n610(x)
+ if (x < 1)
+ fun_l3_n979(x)
+ else
+ fun_l3_n642(x)
+ end
+end
+
+def fun_l2_n611(x)
+ if (x < 1)
+ fun_l3_n909(x)
+ else
+ fun_l3_n986(x)
+ end
+end
+
+def fun_l2_n612(x)
+ if (x < 1)
+ fun_l3_n387(x)
+ else
+ fun_l3_n586(x)
+ end
+end
+
+def fun_l2_n613(x)
+ if (x < 1)
+ fun_l3_n99(x)
+ else
+ fun_l3_n690(x)
+ end
+end
+
+def fun_l2_n614(x)
+ if (x < 1)
+ fun_l3_n485(x)
+ else
+ fun_l3_n733(x)
+ end
+end
+
+def fun_l2_n615(x)
+ if (x < 1)
+ fun_l3_n735(x)
+ else
+ fun_l3_n827(x)
+ end
+end
+
+def fun_l2_n616(x)
+ if (x < 1)
+ fun_l3_n496(x)
+ else
+ fun_l3_n912(x)
+ end
+end
+
+def fun_l2_n617(x)
+ if (x < 1)
+ fun_l3_n363(x)
+ else
+ fun_l3_n845(x)
+ end
+end
+
+def fun_l2_n618(x)
+ if (x < 1)
+ fun_l3_n891(x)
+ else
+ fun_l3_n964(x)
+ end
+end
+
+def fun_l2_n619(x)
+ if (x < 1)
+ fun_l3_n266(x)
+ else
+ fun_l3_n189(x)
+ end
+end
+
+def fun_l2_n620(x)
+ if (x < 1)
+ fun_l3_n906(x)
+ else
+ fun_l3_n218(x)
+ end
+end
+
+def fun_l2_n621(x)
+ if (x < 1)
+ fun_l3_n145(x)
+ else
+ fun_l3_n279(x)
+ end
+end
+
+def fun_l2_n622(x)
+ if (x < 1)
+ fun_l3_n797(x)
+ else
+ fun_l3_n328(x)
+ end
+end
+
+def fun_l2_n623(x)
+ if (x < 1)
+ fun_l3_n910(x)
+ else
+ fun_l3_n250(x)
+ end
+end
+
+def fun_l2_n624(x)
+ if (x < 1)
+ fun_l3_n111(x)
+ else
+ fun_l3_n884(x)
+ end
+end
+
+def fun_l2_n625(x)
+ if (x < 1)
+ fun_l3_n852(x)
+ else
+ fun_l3_n985(x)
+ end
+end
+
+def fun_l2_n626(x)
+ if (x < 1)
+ fun_l3_n163(x)
+ else
+ fun_l3_n885(x)
+ end
+end
+
+def fun_l2_n627(x)
+ if (x < 1)
+ fun_l3_n338(x)
+ else
+ fun_l3_n562(x)
+ end
+end
+
+def fun_l2_n628(x)
+ if (x < 1)
+ fun_l3_n300(x)
+ else
+ fun_l3_n245(x)
+ end
+end
+
+def fun_l2_n629(x)
+ if (x < 1)
+ fun_l3_n747(x)
+ else
+ fun_l3_n123(x)
+ end
+end
+
+def fun_l2_n630(x)
+ if (x < 1)
+ fun_l3_n42(x)
+ else
+ fun_l3_n46(x)
+ end
+end
+
+def fun_l2_n631(x)
+ if (x < 1)
+ fun_l3_n256(x)
+ else
+ fun_l3_n960(x)
+ end
+end
+
+def fun_l2_n632(x)
+ if (x < 1)
+ fun_l3_n679(x)
+ else
+ fun_l3_n393(x)
+ end
+end
+
+def fun_l2_n633(x)
+ if (x < 1)
+ fun_l3_n286(x)
+ else
+ fun_l3_n147(x)
+ end
+end
+
+def fun_l2_n634(x)
+ if (x < 1)
+ fun_l3_n62(x)
+ else
+ fun_l3_n994(x)
+ end
+end
+
+def fun_l2_n635(x)
+ if (x < 1)
+ fun_l3_n479(x)
+ else
+ fun_l3_n502(x)
+ end
+end
+
+def fun_l2_n636(x)
+ if (x < 1)
+ fun_l3_n504(x)
+ else
+ fun_l3_n557(x)
+ end
+end
+
+def fun_l2_n637(x)
+ if (x < 1)
+ fun_l3_n716(x)
+ else
+ fun_l3_n763(x)
+ end
+end
+
+def fun_l2_n638(x)
+ if (x < 1)
+ fun_l3_n972(x)
+ else
+ fun_l3_n391(x)
+ end
+end
+
+def fun_l2_n639(x)
+ if (x < 1)
+ fun_l3_n842(x)
+ else
+ fun_l3_n740(x)
+ end
+end
+
+def fun_l2_n640(x)
+ if (x < 1)
+ fun_l3_n854(x)
+ else
+ fun_l3_n52(x)
+ end
+end
+
+def fun_l2_n641(x)
+ if (x < 1)
+ fun_l3_n321(x)
+ else
+ fun_l3_n109(x)
+ end
+end
+
+def fun_l2_n642(x)
+ if (x < 1)
+ fun_l3_n868(x)
+ else
+ fun_l3_n926(x)
+ end
+end
+
+def fun_l2_n643(x)
+ if (x < 1)
+ fun_l3_n864(x)
+ else
+ fun_l3_n98(x)
+ end
+end
+
+def fun_l2_n644(x)
+ if (x < 1)
+ fun_l3_n373(x)
+ else
+ fun_l3_n105(x)
+ end
+end
+
+def fun_l2_n645(x)
+ if (x < 1)
+ fun_l3_n293(x)
+ else
+ fun_l3_n846(x)
+ end
+end
+
+def fun_l2_n646(x)
+ if (x < 1)
+ fun_l3_n24(x)
+ else
+ fun_l3_n83(x)
+ end
+end
+
+def fun_l2_n647(x)
+ if (x < 1)
+ fun_l3_n431(x)
+ else
+ fun_l3_n772(x)
+ end
+end
+
+def fun_l2_n648(x)
+ if (x < 1)
+ fun_l3_n667(x)
+ else
+ fun_l3_n108(x)
+ end
+end
+
+def fun_l2_n649(x)
+ if (x < 1)
+ fun_l3_n93(x)
+ else
+ fun_l3_n394(x)
+ end
+end
+
+def fun_l2_n650(x)
+ if (x < 1)
+ fun_l3_n176(x)
+ else
+ fun_l3_n315(x)
+ end
+end
+
+def fun_l2_n651(x)
+ if (x < 1)
+ fun_l3_n684(x)
+ else
+ fun_l3_n635(x)
+ end
+end
+
+def fun_l2_n652(x)
+ if (x < 1)
+ fun_l3_n554(x)
+ else
+ fun_l3_n88(x)
+ end
+end
+
+def fun_l2_n653(x)
+ if (x < 1)
+ fun_l3_n165(x)
+ else
+ fun_l3_n962(x)
+ end
+end
+
+def fun_l2_n654(x)
+ if (x < 1)
+ fun_l3_n631(x)
+ else
+ fun_l3_n80(x)
+ end
+end
+
+def fun_l2_n655(x)
+ if (x < 1)
+ fun_l3_n529(x)
+ else
+ fun_l3_n711(x)
+ end
+end
+
+def fun_l2_n656(x)
+ if (x < 1)
+ fun_l3_n809(x)
+ else
+ fun_l3_n44(x)
+ end
+end
+
+def fun_l2_n657(x)
+ if (x < 1)
+ fun_l3_n226(x)
+ else
+ fun_l3_n939(x)
+ end
+end
+
+def fun_l2_n658(x)
+ if (x < 1)
+ fun_l3_n355(x)
+ else
+ fun_l3_n750(x)
+ end
+end
+
+def fun_l2_n659(x)
+ if (x < 1)
+ fun_l3_n111(x)
+ else
+ fun_l3_n883(x)
+ end
+end
+
+def fun_l2_n660(x)
+ if (x < 1)
+ fun_l3_n22(x)
+ else
+ fun_l3_n544(x)
+ end
+end
+
+def fun_l2_n661(x)
+ if (x < 1)
+ fun_l3_n334(x)
+ else
+ fun_l3_n58(x)
+ end
+end
+
+def fun_l2_n662(x)
+ if (x < 1)
+ fun_l3_n690(x)
+ else
+ fun_l3_n647(x)
+ end
+end
+
+def fun_l2_n663(x)
+ if (x < 1)
+ fun_l3_n886(x)
+ else
+ fun_l3_n142(x)
+ end
+end
+
+def fun_l2_n664(x)
+ if (x < 1)
+ fun_l3_n713(x)
+ else
+ fun_l3_n710(x)
+ end
+end
+
+def fun_l2_n665(x)
+ if (x < 1)
+ fun_l3_n657(x)
+ else
+ fun_l3_n24(x)
+ end
+end
+
+def fun_l2_n666(x)
+ if (x < 1)
+ fun_l3_n993(x)
+ else
+ fun_l3_n741(x)
+ end
+end
+
+def fun_l2_n667(x)
+ if (x < 1)
+ fun_l3_n265(x)
+ else
+ fun_l3_n143(x)
+ end
+end
+
+def fun_l2_n668(x)
+ if (x < 1)
+ fun_l3_n725(x)
+ else
+ fun_l3_n272(x)
+ end
+end
+
+def fun_l2_n669(x)
+ if (x < 1)
+ fun_l3_n171(x)
+ else
+ fun_l3_n95(x)
+ end
+end
+
+def fun_l2_n670(x)
+ if (x < 1)
+ fun_l3_n409(x)
+ else
+ fun_l3_n774(x)
+ end
+end
+
+def fun_l2_n671(x)
+ if (x < 1)
+ fun_l3_n566(x)
+ else
+ fun_l3_n251(x)
+ end
+end
+
+def fun_l2_n672(x)
+ if (x < 1)
+ fun_l3_n914(x)
+ else
+ fun_l3_n716(x)
+ end
+end
+
+def fun_l2_n673(x)
+ if (x < 1)
+ fun_l3_n889(x)
+ else
+ fun_l3_n339(x)
+ end
+end
+
+def fun_l2_n674(x)
+ if (x < 1)
+ fun_l3_n808(x)
+ else
+ fun_l3_n858(x)
+ end
+end
+
+def fun_l2_n675(x)
+ if (x < 1)
+ fun_l3_n895(x)
+ else
+ fun_l3_n180(x)
+ end
+end
+
+def fun_l2_n676(x)
+ if (x < 1)
+ fun_l3_n674(x)
+ else
+ fun_l3_n183(x)
+ end
+end
+
+def fun_l2_n677(x)
+ if (x < 1)
+ fun_l3_n934(x)
+ else
+ fun_l3_n292(x)
+ end
+end
+
+def fun_l2_n678(x)
+ if (x < 1)
+ fun_l3_n302(x)
+ else
+ fun_l3_n511(x)
+ end
+end
+
+def fun_l2_n679(x)
+ if (x < 1)
+ fun_l3_n847(x)
+ else
+ fun_l3_n70(x)
+ end
+end
+
+def fun_l2_n680(x)
+ if (x < 1)
+ fun_l3_n200(x)
+ else
+ fun_l3_n436(x)
+ end
+end
+
+def fun_l2_n681(x)
+ if (x < 1)
+ fun_l3_n44(x)
+ else
+ fun_l3_n145(x)
+ end
+end
+
+def fun_l2_n682(x)
+ if (x < 1)
+ fun_l3_n929(x)
+ else
+ fun_l3_n605(x)
+ end
+end
+
+def fun_l2_n683(x)
+ if (x < 1)
+ fun_l3_n990(x)
+ else
+ fun_l3_n641(x)
+ end
+end
+
+def fun_l2_n684(x)
+ if (x < 1)
+ fun_l3_n679(x)
+ else
+ fun_l3_n976(x)
+ end
+end
+
+def fun_l2_n685(x)
+ if (x < 1)
+ fun_l3_n405(x)
+ else
+ fun_l3_n658(x)
+ end
+end
+
+def fun_l2_n686(x)
+ if (x < 1)
+ fun_l3_n685(x)
+ else
+ fun_l3_n379(x)
+ end
+end
+
+def fun_l2_n687(x)
+ if (x < 1)
+ fun_l3_n279(x)
+ else
+ fun_l3_n415(x)
+ end
+end
+
+def fun_l2_n688(x)
+ if (x < 1)
+ fun_l3_n234(x)
+ else
+ fun_l3_n634(x)
+ end
+end
+
+def fun_l2_n689(x)
+ if (x < 1)
+ fun_l3_n119(x)
+ else
+ fun_l3_n234(x)
+ end
+end
+
+def fun_l2_n690(x)
+ if (x < 1)
+ fun_l3_n213(x)
+ else
+ fun_l3_n102(x)
+ end
+end
+
+def fun_l2_n691(x)
+ if (x < 1)
+ fun_l3_n744(x)
+ else
+ fun_l3_n31(x)
+ end
+end
+
+def fun_l2_n692(x)
+ if (x < 1)
+ fun_l3_n29(x)
+ else
+ fun_l3_n238(x)
+ end
+end
+
+def fun_l2_n693(x)
+ if (x < 1)
+ fun_l3_n323(x)
+ else
+ fun_l3_n388(x)
+ end
+end
+
+def fun_l2_n694(x)
+ if (x < 1)
+ fun_l3_n70(x)
+ else
+ fun_l3_n356(x)
+ end
+end
+
+def fun_l2_n695(x)
+ if (x < 1)
+ fun_l3_n589(x)
+ else
+ fun_l3_n949(x)
+ end
+end
+
+def fun_l2_n696(x)
+ if (x < 1)
+ fun_l3_n328(x)
+ else
+ fun_l3_n472(x)
+ end
+end
+
+def fun_l2_n697(x)
+ if (x < 1)
+ fun_l3_n705(x)
+ else
+ fun_l3_n709(x)
+ end
+end
+
+def fun_l2_n698(x)
+ if (x < 1)
+ fun_l3_n817(x)
+ else
+ fun_l3_n927(x)
+ end
+end
+
+def fun_l2_n699(x)
+ if (x < 1)
+ fun_l3_n916(x)
+ else
+ fun_l3_n66(x)
+ end
+end
+
+def fun_l2_n700(x)
+ if (x < 1)
+ fun_l3_n461(x)
+ else
+ fun_l3_n648(x)
+ end
+end
+
+def fun_l2_n701(x)
+ if (x < 1)
+ fun_l3_n71(x)
+ else
+ fun_l3_n218(x)
+ end
+end
+
+def fun_l2_n702(x)
+ if (x < 1)
+ fun_l3_n490(x)
+ else
+ fun_l3_n706(x)
+ end
+end
+
+def fun_l2_n703(x)
+ if (x < 1)
+ fun_l3_n480(x)
+ else
+ fun_l3_n665(x)
+ end
+end
+
+def fun_l2_n704(x)
+ if (x < 1)
+ fun_l3_n965(x)
+ else
+ fun_l3_n394(x)
+ end
+end
+
+def fun_l2_n705(x)
+ if (x < 1)
+ fun_l3_n65(x)
+ else
+ fun_l3_n761(x)
+ end
+end
+
+def fun_l2_n706(x)
+ if (x < 1)
+ fun_l3_n690(x)
+ else
+ fun_l3_n50(x)
+ end
+end
+
+def fun_l2_n707(x)
+ if (x < 1)
+ fun_l3_n665(x)
+ else
+ fun_l3_n589(x)
+ end
+end
+
+def fun_l2_n708(x)
+ if (x < 1)
+ fun_l3_n331(x)
+ else
+ fun_l3_n299(x)
+ end
+end
+
+def fun_l2_n709(x)
+ if (x < 1)
+ fun_l3_n656(x)
+ else
+ fun_l3_n966(x)
+ end
+end
+
+def fun_l2_n710(x)
+ if (x < 1)
+ fun_l3_n610(x)
+ else
+ fun_l3_n767(x)
+ end
+end
+
+def fun_l2_n711(x)
+ if (x < 1)
+ fun_l3_n281(x)
+ else
+ fun_l3_n942(x)
+ end
+end
+
+def fun_l2_n712(x)
+ if (x < 1)
+ fun_l3_n474(x)
+ else
+ fun_l3_n373(x)
+ end
+end
+
+def fun_l2_n713(x)
+ if (x < 1)
+ fun_l3_n668(x)
+ else
+ fun_l3_n881(x)
+ end
+end
+
+def fun_l2_n714(x)
+ if (x < 1)
+ fun_l3_n112(x)
+ else
+ fun_l3_n914(x)
+ end
+end
+
+def fun_l2_n715(x)
+ if (x < 1)
+ fun_l3_n276(x)
+ else
+ fun_l3_n946(x)
+ end
+end
+
+def fun_l2_n716(x)
+ if (x < 1)
+ fun_l3_n340(x)
+ else
+ fun_l3_n474(x)
+ end
+end
+
+def fun_l2_n717(x)
+ if (x < 1)
+ fun_l3_n179(x)
+ else
+ fun_l3_n740(x)
+ end
+end
+
+def fun_l2_n718(x)
+ if (x < 1)
+ fun_l3_n830(x)
+ else
+ fun_l3_n139(x)
+ end
+end
+
+def fun_l2_n719(x)
+ if (x < 1)
+ fun_l3_n945(x)
+ else
+ fun_l3_n98(x)
+ end
+end
+
+def fun_l2_n720(x)
+ if (x < 1)
+ fun_l3_n912(x)
+ else
+ fun_l3_n457(x)
+ end
+end
+
+def fun_l2_n721(x)
+ if (x < 1)
+ fun_l3_n4(x)
+ else
+ fun_l3_n798(x)
+ end
+end
+
+def fun_l2_n722(x)
+ if (x < 1)
+ fun_l3_n438(x)
+ else
+ fun_l3_n677(x)
+ end
+end
+
+def fun_l2_n723(x)
+ if (x < 1)
+ fun_l3_n447(x)
+ else
+ fun_l3_n418(x)
+ end
+end
+
+def fun_l2_n724(x)
+ if (x < 1)
+ fun_l3_n936(x)
+ else
+ fun_l3_n572(x)
+ end
+end
+
+def fun_l2_n725(x)
+ if (x < 1)
+ fun_l3_n856(x)
+ else
+ fun_l3_n429(x)
+ end
+end
+
+def fun_l2_n726(x)
+ if (x < 1)
+ fun_l3_n747(x)
+ else
+ fun_l3_n823(x)
+ end
+end
+
+def fun_l2_n727(x)
+ if (x < 1)
+ fun_l3_n908(x)
+ else
+ fun_l3_n446(x)
+ end
+end
+
+def fun_l2_n728(x)
+ if (x < 1)
+ fun_l3_n170(x)
+ else
+ fun_l3_n546(x)
+ end
+end
+
+def fun_l2_n729(x)
+ if (x < 1)
+ fun_l3_n45(x)
+ else
+ fun_l3_n76(x)
+ end
+end
+
+def fun_l2_n730(x)
+ if (x < 1)
+ fun_l3_n688(x)
+ else
+ fun_l3_n826(x)
+ end
+end
+
+def fun_l2_n731(x)
+ if (x < 1)
+ fun_l3_n805(x)
+ else
+ fun_l3_n88(x)
+ end
+end
+
+def fun_l2_n732(x)
+ if (x < 1)
+ fun_l3_n191(x)
+ else
+ fun_l3_n395(x)
+ end
+end
+
+def fun_l2_n733(x)
+ if (x < 1)
+ fun_l3_n161(x)
+ else
+ fun_l3_n600(x)
+ end
+end
+
+def fun_l2_n734(x)
+ if (x < 1)
+ fun_l3_n586(x)
+ else
+ fun_l3_n770(x)
+ end
+end
+
+def fun_l2_n735(x)
+ if (x < 1)
+ fun_l3_n139(x)
+ else
+ fun_l3_n108(x)
+ end
+end
+
+def fun_l2_n736(x)
+ if (x < 1)
+ fun_l3_n719(x)
+ else
+ fun_l3_n210(x)
+ end
+end
+
+def fun_l2_n737(x)
+ if (x < 1)
+ fun_l3_n327(x)
+ else
+ fun_l3_n138(x)
+ end
+end
+
+def fun_l2_n738(x)
+ if (x < 1)
+ fun_l3_n755(x)
+ else
+ fun_l3_n785(x)
+ end
+end
+
+def fun_l2_n739(x)
+ if (x < 1)
+ fun_l3_n499(x)
+ else
+ fun_l3_n998(x)
+ end
+end
+
+def fun_l2_n740(x)
+ if (x < 1)
+ fun_l3_n303(x)
+ else
+ fun_l3_n646(x)
+ end
+end
+
+def fun_l2_n741(x)
+ if (x < 1)
+ fun_l3_n385(x)
+ else
+ fun_l3_n202(x)
+ end
+end
+
+def fun_l2_n742(x)
+ if (x < 1)
+ fun_l3_n290(x)
+ else
+ fun_l3_n617(x)
+ end
+end
+
+def fun_l2_n743(x)
+ if (x < 1)
+ fun_l3_n735(x)
+ else
+ fun_l3_n322(x)
+ end
+end
+
+def fun_l2_n744(x)
+ if (x < 1)
+ fun_l3_n541(x)
+ else
+ fun_l3_n841(x)
+ end
+end
+
+def fun_l2_n745(x)
+ if (x < 1)
+ fun_l3_n124(x)
+ else
+ fun_l3_n927(x)
+ end
+end
+
+def fun_l2_n746(x)
+ if (x < 1)
+ fun_l3_n909(x)
+ else
+ fun_l3_n981(x)
+ end
+end
+
+def fun_l2_n747(x)
+ if (x < 1)
+ fun_l3_n535(x)
+ else
+ fun_l3_n154(x)
+ end
+end
+
+def fun_l2_n748(x)
+ if (x < 1)
+ fun_l3_n804(x)
+ else
+ fun_l3_n837(x)
+ end
+end
+
+def fun_l2_n749(x)
+ if (x < 1)
+ fun_l3_n787(x)
+ else
+ fun_l3_n890(x)
+ end
+end
+
+def fun_l2_n750(x)
+ if (x < 1)
+ fun_l3_n273(x)
+ else
+ fun_l3_n539(x)
+ end
+end
+
+def fun_l2_n751(x)
+ if (x < 1)
+ fun_l3_n397(x)
+ else
+ fun_l3_n630(x)
+ end
+end
+
+def fun_l2_n752(x)
+ if (x < 1)
+ fun_l3_n757(x)
+ else
+ fun_l3_n294(x)
+ end
+end
+
+def fun_l2_n753(x)
+ if (x < 1)
+ fun_l3_n731(x)
+ else
+ fun_l3_n121(x)
+ end
+end
+
+def fun_l2_n754(x)
+ if (x < 1)
+ fun_l3_n391(x)
+ else
+ fun_l3_n640(x)
+ end
+end
+
+def fun_l2_n755(x)
+ if (x < 1)
+ fun_l3_n441(x)
+ else
+ fun_l3_n731(x)
+ end
+end
+
+def fun_l2_n756(x)
+ if (x < 1)
+ fun_l3_n947(x)
+ else
+ fun_l3_n175(x)
+ end
+end
+
+def fun_l2_n757(x)
+ if (x < 1)
+ fun_l3_n294(x)
+ else
+ fun_l3_n732(x)
+ end
+end
+
+def fun_l2_n758(x)
+ if (x < 1)
+ fun_l3_n862(x)
+ else
+ fun_l3_n490(x)
+ end
+end
+
+def fun_l2_n759(x)
+ if (x < 1)
+ fun_l3_n959(x)
+ else
+ fun_l3_n58(x)
+ end
+end
+
+def fun_l2_n760(x)
+ if (x < 1)
+ fun_l3_n245(x)
+ else
+ fun_l3_n201(x)
+ end
+end
+
+def fun_l2_n761(x)
+ if (x < 1)
+ fun_l3_n174(x)
+ else
+ fun_l3_n763(x)
+ end
+end
+
+def fun_l2_n762(x)
+ if (x < 1)
+ fun_l3_n276(x)
+ else
+ fun_l3_n624(x)
+ end
+end
+
+def fun_l2_n763(x)
+ if (x < 1)
+ fun_l3_n130(x)
+ else
+ fun_l3_n452(x)
+ end
+end
+
+def fun_l2_n764(x)
+ if (x < 1)
+ fun_l3_n476(x)
+ else
+ fun_l3_n519(x)
+ end
+end
+
+def fun_l2_n765(x)
+ if (x < 1)
+ fun_l3_n911(x)
+ else
+ fun_l3_n28(x)
+ end
+end
+
+def fun_l2_n766(x)
+ if (x < 1)
+ fun_l3_n290(x)
+ else
+ fun_l3_n528(x)
+ end
+end
+
+def fun_l2_n767(x)
+ if (x < 1)
+ fun_l3_n89(x)
+ else
+ fun_l3_n284(x)
+ end
+end
+
+def fun_l2_n768(x)
+ if (x < 1)
+ fun_l3_n307(x)
+ else
+ fun_l3_n832(x)
+ end
+end
+
+def fun_l2_n769(x)
+ if (x < 1)
+ fun_l3_n204(x)
+ else
+ fun_l3_n358(x)
+ end
+end
+
+def fun_l2_n770(x)
+ if (x < 1)
+ fun_l3_n380(x)
+ else
+ fun_l3_n938(x)
+ end
+end
+
+def fun_l2_n771(x)
+ if (x < 1)
+ fun_l3_n245(x)
+ else
+ fun_l3_n156(x)
+ end
+end
+
+def fun_l2_n772(x)
+ if (x < 1)
+ fun_l3_n77(x)
+ else
+ fun_l3_n842(x)
+ end
+end
+
+def fun_l2_n773(x)
+ if (x < 1)
+ fun_l3_n972(x)
+ else
+ fun_l3_n143(x)
+ end
+end
+
+def fun_l2_n774(x)
+ if (x < 1)
+ fun_l3_n308(x)
+ else
+ fun_l3_n713(x)
+ end
+end
+
+def fun_l2_n775(x)
+ if (x < 1)
+ fun_l3_n714(x)
+ else
+ fun_l3_n329(x)
+ end
+end
+
+def fun_l2_n776(x)
+ if (x < 1)
+ fun_l3_n805(x)
+ else
+ fun_l3_n141(x)
+ end
+end
+
+def fun_l2_n777(x)
+ if (x < 1)
+ fun_l3_n155(x)
+ else
+ fun_l3_n873(x)
+ end
+end
+
+def fun_l2_n778(x)
+ if (x < 1)
+ fun_l3_n551(x)
+ else
+ fun_l3_n293(x)
+ end
+end
+
+def fun_l2_n779(x)
+ if (x < 1)
+ fun_l3_n857(x)
+ else
+ fun_l3_n551(x)
+ end
+end
+
+def fun_l2_n780(x)
+ if (x < 1)
+ fun_l3_n30(x)
+ else
+ fun_l3_n230(x)
+ end
+end
+
+def fun_l2_n781(x)
+ if (x < 1)
+ fun_l3_n958(x)
+ else
+ fun_l3_n463(x)
+ end
+end
+
+def fun_l2_n782(x)
+ if (x < 1)
+ fun_l3_n89(x)
+ else
+ fun_l3_n514(x)
+ end
+end
+
+def fun_l2_n783(x)
+ if (x < 1)
+ fun_l3_n290(x)
+ else
+ fun_l3_n394(x)
+ end
+end
+
+def fun_l2_n784(x)
+ if (x < 1)
+ fun_l3_n582(x)
+ else
+ fun_l3_n927(x)
+ end
+end
+
+def fun_l2_n785(x)
+ if (x < 1)
+ fun_l3_n739(x)
+ else
+ fun_l3_n822(x)
+ end
+end
+
+def fun_l2_n786(x)
+ if (x < 1)
+ fun_l3_n1(x)
+ else
+ fun_l3_n162(x)
+ end
+end
+
+def fun_l2_n787(x)
+ if (x < 1)
+ fun_l3_n88(x)
+ else
+ fun_l3_n800(x)
+ end
+end
+
+def fun_l2_n788(x)
+ if (x < 1)
+ fun_l3_n592(x)
+ else
+ fun_l3_n235(x)
+ end
+end
+
+def fun_l2_n789(x)
+ if (x < 1)
+ fun_l3_n337(x)
+ else
+ fun_l3_n204(x)
+ end
+end
+
+def fun_l2_n790(x)
+ if (x < 1)
+ fun_l3_n481(x)
+ else
+ fun_l3_n361(x)
+ end
+end
+
+def fun_l2_n791(x)
+ if (x < 1)
+ fun_l3_n441(x)
+ else
+ fun_l3_n883(x)
+ end
+end
+
+def fun_l2_n792(x)
+ if (x < 1)
+ fun_l3_n424(x)
+ else
+ fun_l3_n387(x)
+ end
+end
+
+def fun_l2_n793(x)
+ if (x < 1)
+ fun_l3_n961(x)
+ else
+ fun_l3_n710(x)
+ end
+end
+
+def fun_l2_n794(x)
+ if (x < 1)
+ fun_l3_n653(x)
+ else
+ fun_l3_n869(x)
+ end
+end
+
+def fun_l2_n795(x)
+ if (x < 1)
+ fun_l3_n466(x)
+ else
+ fun_l3_n195(x)
+ end
+end
+
+def fun_l2_n796(x)
+ if (x < 1)
+ fun_l3_n30(x)
+ else
+ fun_l3_n137(x)
+ end
+end
+
+def fun_l2_n797(x)
+ if (x < 1)
+ fun_l3_n974(x)
+ else
+ fun_l3_n911(x)
+ end
+end
+
+def fun_l2_n798(x)
+ if (x < 1)
+ fun_l3_n500(x)
+ else
+ fun_l3_n607(x)
+ end
+end
+
+def fun_l2_n799(x)
+ if (x < 1)
+ fun_l3_n964(x)
+ else
+ fun_l3_n425(x)
+ end
+end
+
+def fun_l2_n800(x)
+ if (x < 1)
+ fun_l3_n381(x)
+ else
+ fun_l3_n618(x)
+ end
+end
+
+def fun_l2_n801(x)
+ if (x < 1)
+ fun_l3_n803(x)
+ else
+ fun_l3_n697(x)
+ end
+end
+
+def fun_l2_n802(x)
+ if (x < 1)
+ fun_l3_n372(x)
+ else
+ fun_l3_n331(x)
+ end
+end
+
+def fun_l2_n803(x)
+ if (x < 1)
+ fun_l3_n450(x)
+ else
+ fun_l3_n707(x)
+ end
+end
+
+def fun_l2_n804(x)
+ if (x < 1)
+ fun_l3_n760(x)
+ else
+ fun_l3_n800(x)
+ end
+end
+
+def fun_l2_n805(x)
+ if (x < 1)
+ fun_l3_n695(x)
+ else
+ fun_l3_n426(x)
+ end
+end
+
+def fun_l2_n806(x)
+ if (x < 1)
+ fun_l3_n312(x)
+ else
+ fun_l3_n517(x)
+ end
+end
+
+def fun_l2_n807(x)
+ if (x < 1)
+ fun_l3_n794(x)
+ else
+ fun_l3_n37(x)
+ end
+end
+
+def fun_l2_n808(x)
+ if (x < 1)
+ fun_l3_n591(x)
+ else
+ fun_l3_n933(x)
+ end
+end
+
+def fun_l2_n809(x)
+ if (x < 1)
+ fun_l3_n974(x)
+ else
+ fun_l3_n69(x)
+ end
+end
+
+def fun_l2_n810(x)
+ if (x < 1)
+ fun_l3_n263(x)
+ else
+ fun_l3_n628(x)
+ end
+end
+
+def fun_l2_n811(x)
+ if (x < 1)
+ fun_l3_n647(x)
+ else
+ fun_l3_n133(x)
+ end
+end
+
+def fun_l2_n812(x)
+ if (x < 1)
+ fun_l3_n396(x)
+ else
+ fun_l3_n872(x)
+ end
+end
+
+def fun_l2_n813(x)
+ if (x < 1)
+ fun_l3_n716(x)
+ else
+ fun_l3_n254(x)
+ end
+end
+
+def fun_l2_n814(x)
+ if (x < 1)
+ fun_l3_n181(x)
+ else
+ fun_l3_n786(x)
+ end
+end
+
+def fun_l2_n815(x)
+ if (x < 1)
+ fun_l3_n163(x)
+ else
+ fun_l3_n175(x)
+ end
+end
+
+def fun_l2_n816(x)
+ if (x < 1)
+ fun_l3_n835(x)
+ else
+ fun_l3_n713(x)
+ end
+end
+
+def fun_l2_n817(x)
+ if (x < 1)
+ fun_l3_n54(x)
+ else
+ fun_l3_n280(x)
+ end
+end
+
+def fun_l2_n818(x)
+ if (x < 1)
+ fun_l3_n261(x)
+ else
+ fun_l3_n958(x)
+ end
+end
+
+def fun_l2_n819(x)
+ if (x < 1)
+ fun_l3_n821(x)
+ else
+ fun_l3_n418(x)
+ end
+end
+
+def fun_l2_n820(x)
+ if (x < 1)
+ fun_l3_n541(x)
+ else
+ fun_l3_n547(x)
+ end
+end
+
+def fun_l2_n821(x)
+ if (x < 1)
+ fun_l3_n726(x)
+ else
+ fun_l3_n386(x)
+ end
+end
+
+def fun_l2_n822(x)
+ if (x < 1)
+ fun_l3_n369(x)
+ else
+ fun_l3_n781(x)
+ end
+end
+
+def fun_l2_n823(x)
+ if (x < 1)
+ fun_l3_n392(x)
+ else
+ fun_l3_n357(x)
+ end
+end
+
+def fun_l2_n824(x)
+ if (x < 1)
+ fun_l3_n167(x)
+ else
+ fun_l3_n764(x)
+ end
+end
+
+def fun_l2_n825(x)
+ if (x < 1)
+ fun_l3_n339(x)
+ else
+ fun_l3_n853(x)
+ end
+end
+
+def fun_l2_n826(x)
+ if (x < 1)
+ fun_l3_n613(x)
+ else
+ fun_l3_n767(x)
+ end
+end
+
+def fun_l2_n827(x)
+ if (x < 1)
+ fun_l3_n31(x)
+ else
+ fun_l3_n35(x)
+ end
+end
+
+def fun_l2_n828(x)
+ if (x < 1)
+ fun_l3_n838(x)
+ else
+ fun_l3_n939(x)
+ end
+end
+
+def fun_l2_n829(x)
+ if (x < 1)
+ fun_l3_n344(x)
+ else
+ fun_l3_n568(x)
+ end
+end
+
+def fun_l2_n830(x)
+ if (x < 1)
+ fun_l3_n892(x)
+ else
+ fun_l3_n564(x)
+ end
+end
+
+def fun_l2_n831(x)
+ if (x < 1)
+ fun_l3_n520(x)
+ else
+ fun_l3_n897(x)
+ end
+end
+
+def fun_l2_n832(x)
+ if (x < 1)
+ fun_l3_n986(x)
+ else
+ fun_l3_n523(x)
+ end
+end
+
+def fun_l2_n833(x)
+ if (x < 1)
+ fun_l3_n649(x)
+ else
+ fun_l3_n776(x)
+ end
+end
+
+def fun_l2_n834(x)
+ if (x < 1)
+ fun_l3_n613(x)
+ else
+ fun_l3_n170(x)
+ end
+end
+
+def fun_l2_n835(x)
+ if (x < 1)
+ fun_l3_n657(x)
+ else
+ fun_l3_n790(x)
+ end
+end
+
+def fun_l2_n836(x)
+ if (x < 1)
+ fun_l3_n976(x)
+ else
+ fun_l3_n785(x)
+ end
+end
+
+def fun_l2_n837(x)
+ if (x < 1)
+ fun_l3_n746(x)
+ else
+ fun_l3_n448(x)
+ end
+end
+
+def fun_l2_n838(x)
+ if (x < 1)
+ fun_l3_n911(x)
+ else
+ fun_l3_n978(x)
+ end
+end
+
+def fun_l2_n839(x)
+ if (x < 1)
+ fun_l3_n917(x)
+ else
+ fun_l3_n484(x)
+ end
+end
+
+def fun_l2_n840(x)
+ if (x < 1)
+ fun_l3_n930(x)
+ else
+ fun_l3_n617(x)
+ end
+end
+
+def fun_l2_n841(x)
+ if (x < 1)
+ fun_l3_n753(x)
+ else
+ fun_l3_n587(x)
+ end
+end
+
+def fun_l2_n842(x)
+ if (x < 1)
+ fun_l3_n21(x)
+ else
+ fun_l3_n256(x)
+ end
+end
+
+def fun_l2_n843(x)
+ if (x < 1)
+ fun_l3_n697(x)
+ else
+ fun_l3_n828(x)
+ end
+end
+
+def fun_l2_n844(x)
+ if (x < 1)
+ fun_l3_n59(x)
+ else
+ fun_l3_n855(x)
+ end
+end
+
+def fun_l2_n845(x)
+ if (x < 1)
+ fun_l3_n637(x)
+ else
+ fun_l3_n667(x)
+ end
+end
+
+def fun_l2_n846(x)
+ if (x < 1)
+ fun_l3_n229(x)
+ else
+ fun_l3_n379(x)
+ end
+end
+
+def fun_l2_n847(x)
+ if (x < 1)
+ fun_l3_n908(x)
+ else
+ fun_l3_n53(x)
+ end
+end
+
+def fun_l2_n848(x)
+ if (x < 1)
+ fun_l3_n72(x)
+ else
+ fun_l3_n882(x)
+ end
+end
+
+def fun_l2_n849(x)
+ if (x < 1)
+ fun_l3_n890(x)
+ else
+ fun_l3_n153(x)
+ end
+end
+
+def fun_l2_n850(x)
+ if (x < 1)
+ fun_l3_n301(x)
+ else
+ fun_l3_n404(x)
+ end
+end
+
+def fun_l2_n851(x)
+ if (x < 1)
+ fun_l3_n451(x)
+ else
+ fun_l3_n365(x)
+ end
+end
+
+def fun_l2_n852(x)
+ if (x < 1)
+ fun_l3_n591(x)
+ else
+ fun_l3_n974(x)
+ end
+end
+
+def fun_l2_n853(x)
+ if (x < 1)
+ fun_l3_n534(x)
+ else
+ fun_l3_n649(x)
+ end
+end
+
+def fun_l2_n854(x)
+ if (x < 1)
+ fun_l3_n438(x)
+ else
+ fun_l3_n853(x)
+ end
+end
+
+def fun_l2_n855(x)
+ if (x < 1)
+ fun_l3_n181(x)
+ else
+ fun_l3_n888(x)
+ end
+end
+
+def fun_l2_n856(x)
+ if (x < 1)
+ fun_l3_n856(x)
+ else
+ fun_l3_n139(x)
+ end
+end
+
+def fun_l2_n857(x)
+ if (x < 1)
+ fun_l3_n664(x)
+ else
+ fun_l3_n659(x)
+ end
+end
+
+def fun_l2_n858(x)
+ if (x < 1)
+ fun_l3_n838(x)
+ else
+ fun_l3_n157(x)
+ end
+end
+
+def fun_l2_n859(x)
+ if (x < 1)
+ fun_l3_n542(x)
+ else
+ fun_l3_n512(x)
+ end
+end
+
+def fun_l2_n860(x)
+ if (x < 1)
+ fun_l3_n213(x)
+ else
+ fun_l3_n954(x)
+ end
+end
+
+def fun_l2_n861(x)
+ if (x < 1)
+ fun_l3_n580(x)
+ else
+ fun_l3_n525(x)
+ end
+end
+
+def fun_l2_n862(x)
+ if (x < 1)
+ fun_l3_n649(x)
+ else
+ fun_l3_n376(x)
+ end
+end
+
+def fun_l2_n863(x)
+ if (x < 1)
+ fun_l3_n846(x)
+ else
+ fun_l3_n643(x)
+ end
+end
+
+def fun_l2_n864(x)
+ if (x < 1)
+ fun_l3_n899(x)
+ else
+ fun_l3_n667(x)
+ end
+end
+
+def fun_l2_n865(x)
+ if (x < 1)
+ fun_l3_n326(x)
+ else
+ fun_l3_n664(x)
+ end
+end
+
+def fun_l2_n866(x)
+ if (x < 1)
+ fun_l3_n155(x)
+ else
+ fun_l3_n369(x)
+ end
+end
+
+def fun_l2_n867(x)
+ if (x < 1)
+ fun_l3_n583(x)
+ else
+ fun_l3_n12(x)
+ end
+end
+
+def fun_l2_n868(x)
+ if (x < 1)
+ fun_l3_n637(x)
+ else
+ fun_l3_n711(x)
+ end
+end
+
+def fun_l2_n869(x)
+ if (x < 1)
+ fun_l3_n120(x)
+ else
+ fun_l3_n449(x)
+ end
+end
+
+def fun_l2_n870(x)
+ if (x < 1)
+ fun_l3_n459(x)
+ else
+ fun_l3_n83(x)
+ end
+end
+
+def fun_l2_n871(x)
+ if (x < 1)
+ fun_l3_n298(x)
+ else
+ fun_l3_n6(x)
+ end
+end
+
+def fun_l2_n872(x)
+ if (x < 1)
+ fun_l3_n640(x)
+ else
+ fun_l3_n319(x)
+ end
+end
+
+def fun_l2_n873(x)
+ if (x < 1)
+ fun_l3_n777(x)
+ else
+ fun_l3_n903(x)
+ end
+end
+
+def fun_l2_n874(x)
+ if (x < 1)
+ fun_l3_n16(x)
+ else
+ fun_l3_n50(x)
+ end
+end
+
+def fun_l2_n875(x)
+ if (x < 1)
+ fun_l3_n732(x)
+ else
+ fun_l3_n711(x)
+ end
+end
+
+def fun_l2_n876(x)
+ if (x < 1)
+ fun_l3_n958(x)
+ else
+ fun_l3_n949(x)
+ end
+end
+
+def fun_l2_n877(x)
+ if (x < 1)
+ fun_l3_n992(x)
+ else
+ fun_l3_n592(x)
+ end
+end
+
+def fun_l2_n878(x)
+ if (x < 1)
+ fun_l3_n283(x)
+ else
+ fun_l3_n178(x)
+ end
+end
+
+def fun_l2_n879(x)
+ if (x < 1)
+ fun_l3_n179(x)
+ else
+ fun_l3_n963(x)
+ end
+end
+
+def fun_l2_n880(x)
+ if (x < 1)
+ fun_l3_n345(x)
+ else
+ fun_l3_n585(x)
+ end
+end
+
+def fun_l2_n881(x)
+ if (x < 1)
+ fun_l3_n859(x)
+ else
+ fun_l3_n204(x)
+ end
+end
+
+def fun_l2_n882(x)
+ if (x < 1)
+ fun_l3_n718(x)
+ else
+ fun_l3_n354(x)
+ end
+end
+
+def fun_l2_n883(x)
+ if (x < 1)
+ fun_l3_n58(x)
+ else
+ fun_l3_n34(x)
+ end
+end
+
+def fun_l2_n884(x)
+ if (x < 1)
+ fun_l3_n442(x)
+ else
+ fun_l3_n853(x)
+ end
+end
+
+def fun_l2_n885(x)
+ if (x < 1)
+ fun_l3_n37(x)
+ else
+ fun_l3_n665(x)
+ end
+end
+
+def fun_l2_n886(x)
+ if (x < 1)
+ fun_l3_n468(x)
+ else
+ fun_l3_n283(x)
+ end
+end
+
+def fun_l2_n887(x)
+ if (x < 1)
+ fun_l3_n674(x)
+ else
+ fun_l3_n940(x)
+ end
+end
+
+def fun_l2_n888(x)
+ if (x < 1)
+ fun_l3_n556(x)
+ else
+ fun_l3_n191(x)
+ end
+end
+
+def fun_l2_n889(x)
+ if (x < 1)
+ fun_l3_n451(x)
+ else
+ fun_l3_n33(x)
+ end
+end
+
+def fun_l2_n890(x)
+ if (x < 1)
+ fun_l3_n724(x)
+ else
+ fun_l3_n355(x)
+ end
+end
+
+def fun_l2_n891(x)
+ if (x < 1)
+ fun_l3_n811(x)
+ else
+ fun_l3_n969(x)
+ end
+end
+
+def fun_l2_n892(x)
+ if (x < 1)
+ fun_l3_n122(x)
+ else
+ fun_l3_n956(x)
+ end
+end
+
+def fun_l2_n893(x)
+ if (x < 1)
+ fun_l3_n416(x)
+ else
+ fun_l3_n373(x)
+ end
+end
+
+def fun_l2_n894(x)
+ if (x < 1)
+ fun_l3_n990(x)
+ else
+ fun_l3_n148(x)
+ end
+end
+
+def fun_l2_n895(x)
+ if (x < 1)
+ fun_l3_n52(x)
+ else
+ fun_l3_n605(x)
+ end
+end
+
+def fun_l2_n896(x)
+ if (x < 1)
+ fun_l3_n523(x)
+ else
+ fun_l3_n929(x)
+ end
+end
+
+def fun_l2_n897(x)
+ if (x < 1)
+ fun_l3_n631(x)
+ else
+ fun_l3_n167(x)
+ end
+end
+
+def fun_l2_n898(x)
+ if (x < 1)
+ fun_l3_n366(x)
+ else
+ fun_l3_n666(x)
+ end
+end
+
+def fun_l2_n899(x)
+ if (x < 1)
+ fun_l3_n758(x)
+ else
+ fun_l3_n441(x)
+ end
+end
+
+def fun_l2_n900(x)
+ if (x < 1)
+ fun_l3_n561(x)
+ else
+ fun_l3_n766(x)
+ end
+end
+
+def fun_l2_n901(x)
+ if (x < 1)
+ fun_l3_n323(x)
+ else
+ fun_l3_n348(x)
+ end
+end
+
+def fun_l2_n902(x)
+ if (x < 1)
+ fun_l3_n455(x)
+ else
+ fun_l3_n78(x)
+ end
+end
+
+def fun_l2_n903(x)
+ if (x < 1)
+ fun_l3_n373(x)
+ else
+ fun_l3_n646(x)
+ end
+end
+
+def fun_l2_n904(x)
+ if (x < 1)
+ fun_l3_n595(x)
+ else
+ fun_l3_n742(x)
+ end
+end
+
+def fun_l2_n905(x)
+ if (x < 1)
+ fun_l3_n102(x)
+ else
+ fun_l3_n140(x)
+ end
+end
+
+def fun_l2_n906(x)
+ if (x < 1)
+ fun_l3_n458(x)
+ else
+ fun_l3_n528(x)
+ end
+end
+
+def fun_l2_n907(x)
+ if (x < 1)
+ fun_l3_n970(x)
+ else
+ fun_l3_n841(x)
+ end
+end
+
+def fun_l2_n908(x)
+ if (x < 1)
+ fun_l3_n97(x)
+ else
+ fun_l3_n250(x)
+ end
+end
+
+def fun_l2_n909(x)
+ if (x < 1)
+ fun_l3_n381(x)
+ else
+ fun_l3_n44(x)
+ end
+end
+
+def fun_l2_n910(x)
+ if (x < 1)
+ fun_l3_n812(x)
+ else
+ fun_l3_n225(x)
+ end
+end
+
+def fun_l2_n911(x)
+ if (x < 1)
+ fun_l3_n849(x)
+ else
+ fun_l3_n683(x)
+ end
+end
+
+def fun_l2_n912(x)
+ if (x < 1)
+ fun_l3_n958(x)
+ else
+ fun_l3_n590(x)
+ end
+end
+
+def fun_l2_n913(x)
+ if (x < 1)
+ fun_l3_n858(x)
+ else
+ fun_l3_n140(x)
+ end
+end
+
+def fun_l2_n914(x)
+ if (x < 1)
+ fun_l3_n997(x)
+ else
+ fun_l3_n959(x)
+ end
+end
+
+def fun_l2_n915(x)
+ if (x < 1)
+ fun_l3_n184(x)
+ else
+ fun_l3_n910(x)
+ end
+end
+
+def fun_l2_n916(x)
+ if (x < 1)
+ fun_l3_n369(x)
+ else
+ fun_l3_n180(x)
+ end
+end
+
+def fun_l2_n917(x)
+ if (x < 1)
+ fun_l3_n537(x)
+ else
+ fun_l3_n927(x)
+ end
+end
+
+def fun_l2_n918(x)
+ if (x < 1)
+ fun_l3_n739(x)
+ else
+ fun_l3_n222(x)
+ end
+end
+
+def fun_l2_n919(x)
+ if (x < 1)
+ fun_l3_n640(x)
+ else
+ fun_l3_n406(x)
+ end
+end
+
+def fun_l2_n920(x)
+ if (x < 1)
+ fun_l3_n371(x)
+ else
+ fun_l3_n976(x)
+ end
+end
+
+def fun_l2_n921(x)
+ if (x < 1)
+ fun_l3_n262(x)
+ else
+ fun_l3_n532(x)
+ end
+end
+
+def fun_l2_n922(x)
+ if (x < 1)
+ fun_l3_n772(x)
+ else
+ fun_l3_n368(x)
+ end
+end
+
+def fun_l2_n923(x)
+ if (x < 1)
+ fun_l3_n935(x)
+ else
+ fun_l3_n109(x)
+ end
+end
+
+def fun_l2_n924(x)
+ if (x < 1)
+ fun_l3_n982(x)
+ else
+ fun_l3_n643(x)
+ end
+end
+
+def fun_l2_n925(x)
+ if (x < 1)
+ fun_l3_n849(x)
+ else
+ fun_l3_n266(x)
+ end
+end
+
+def fun_l2_n926(x)
+ if (x < 1)
+ fun_l3_n977(x)
+ else
+ fun_l3_n803(x)
+ end
+end
+
+def fun_l2_n927(x)
+ if (x < 1)
+ fun_l3_n706(x)
+ else
+ fun_l3_n441(x)
+ end
+end
+
+def fun_l2_n928(x)
+ if (x < 1)
+ fun_l3_n781(x)
+ else
+ fun_l3_n374(x)
+ end
+end
+
+def fun_l2_n929(x)
+ if (x < 1)
+ fun_l3_n122(x)
+ else
+ fun_l3_n851(x)
+ end
+end
+
+def fun_l2_n930(x)
+ if (x < 1)
+ fun_l3_n821(x)
+ else
+ fun_l3_n904(x)
+ end
+end
+
+def fun_l2_n931(x)
+ if (x < 1)
+ fun_l3_n379(x)
+ else
+ fun_l3_n211(x)
+ end
+end
+
+def fun_l2_n932(x)
+ if (x < 1)
+ fun_l3_n572(x)
+ else
+ fun_l3_n169(x)
+ end
+end
+
+def fun_l2_n933(x)
+ if (x < 1)
+ fun_l3_n620(x)
+ else
+ fun_l3_n703(x)
+ end
+end
+
+def fun_l2_n934(x)
+ if (x < 1)
+ fun_l3_n238(x)
+ else
+ fun_l3_n220(x)
+ end
+end
+
+def fun_l2_n935(x)
+ if (x < 1)
+ fun_l3_n652(x)
+ else
+ fun_l3_n822(x)
+ end
+end
+
+def fun_l2_n936(x)
+ if (x < 1)
+ fun_l3_n818(x)
+ else
+ fun_l3_n384(x)
+ end
+end
+
+def fun_l2_n937(x)
+ if (x < 1)
+ fun_l3_n560(x)
+ else
+ fun_l3_n875(x)
+ end
+end
+
+def fun_l2_n938(x)
+ if (x < 1)
+ fun_l3_n417(x)
+ else
+ fun_l3_n900(x)
+ end
+end
+
+def fun_l2_n939(x)
+ if (x < 1)
+ fun_l3_n740(x)
+ else
+ fun_l3_n431(x)
+ end
+end
+
+def fun_l2_n940(x)
+ if (x < 1)
+ fun_l3_n1(x)
+ else
+ fun_l3_n147(x)
+ end
+end
+
+def fun_l2_n941(x)
+ if (x < 1)
+ fun_l3_n64(x)
+ else
+ fun_l3_n317(x)
+ end
+end
+
+def fun_l2_n942(x)
+ if (x < 1)
+ fun_l3_n347(x)
+ else
+ fun_l3_n778(x)
+ end
+end
+
+def fun_l2_n943(x)
+ if (x < 1)
+ fun_l3_n819(x)
+ else
+ fun_l3_n446(x)
+ end
+end
+
+def fun_l2_n944(x)
+ if (x < 1)
+ fun_l3_n492(x)
+ else
+ fun_l3_n381(x)
+ end
+end
+
+def fun_l2_n945(x)
+ if (x < 1)
+ fun_l3_n594(x)
+ else
+ fun_l3_n413(x)
+ end
+end
+
+def fun_l2_n946(x)
+ if (x < 1)
+ fun_l3_n580(x)
+ else
+ fun_l3_n838(x)
+ end
+end
+
+def fun_l2_n947(x)
+ if (x < 1)
+ fun_l3_n880(x)
+ else
+ fun_l3_n768(x)
+ end
+end
+
+def fun_l2_n948(x)
+ if (x < 1)
+ fun_l3_n9(x)
+ else
+ fun_l3_n888(x)
+ end
+end
+
+def fun_l2_n949(x)
+ if (x < 1)
+ fun_l3_n365(x)
+ else
+ fun_l3_n322(x)
+ end
+end
+
+def fun_l2_n950(x)
+ if (x < 1)
+ fun_l3_n283(x)
+ else
+ fun_l3_n921(x)
+ end
+end
+
+def fun_l2_n951(x)
+ if (x < 1)
+ fun_l3_n740(x)
+ else
+ fun_l3_n336(x)
+ end
+end
+
+def fun_l2_n952(x)
+ if (x < 1)
+ fun_l3_n827(x)
+ else
+ fun_l3_n683(x)
+ end
+end
+
+def fun_l2_n953(x)
+ if (x < 1)
+ fun_l3_n289(x)
+ else
+ fun_l3_n915(x)
+ end
+end
+
+def fun_l2_n954(x)
+ if (x < 1)
+ fun_l3_n234(x)
+ else
+ fun_l3_n198(x)
+ end
+end
+
+def fun_l2_n955(x)
+ if (x < 1)
+ fun_l3_n364(x)
+ else
+ fun_l3_n152(x)
+ end
+end
+
+def fun_l2_n956(x)
+ if (x < 1)
+ fun_l3_n370(x)
+ else
+ fun_l3_n786(x)
+ end
+end
+
+def fun_l2_n957(x)
+ if (x < 1)
+ fun_l3_n672(x)
+ else
+ fun_l3_n375(x)
+ end
+end
+
+def fun_l2_n958(x)
+ if (x < 1)
+ fun_l3_n423(x)
+ else
+ fun_l3_n448(x)
+ end
+end
+
+def fun_l2_n959(x)
+ if (x < 1)
+ fun_l3_n887(x)
+ else
+ fun_l3_n33(x)
+ end
+end
+
+def fun_l2_n960(x)
+ if (x < 1)
+ fun_l3_n280(x)
+ else
+ fun_l3_n334(x)
+ end
+end
+
+def fun_l2_n961(x)
+ if (x < 1)
+ fun_l3_n535(x)
+ else
+ fun_l3_n524(x)
+ end
+end
+
+def fun_l2_n962(x)
+ if (x < 1)
+ fun_l3_n689(x)
+ else
+ fun_l3_n426(x)
+ end
+end
+
+def fun_l2_n963(x)
+ if (x < 1)
+ fun_l3_n235(x)
+ else
+ fun_l3_n286(x)
+ end
+end
+
+def fun_l2_n964(x)
+ if (x < 1)
+ fun_l3_n116(x)
+ else
+ fun_l3_n308(x)
+ end
+end
+
+def fun_l2_n965(x)
+ if (x < 1)
+ fun_l3_n174(x)
+ else
+ fun_l3_n823(x)
+ end
+end
+
+def fun_l2_n966(x)
+ if (x < 1)
+ fun_l3_n792(x)
+ else
+ fun_l3_n29(x)
+ end
+end
+
+def fun_l2_n967(x)
+ if (x < 1)
+ fun_l3_n755(x)
+ else
+ fun_l3_n689(x)
+ end
+end
+
+def fun_l2_n968(x)
+ if (x < 1)
+ fun_l3_n167(x)
+ else
+ fun_l3_n287(x)
+ end
+end
+
+def fun_l2_n969(x)
+ if (x < 1)
+ fun_l3_n836(x)
+ else
+ fun_l3_n892(x)
+ end
+end
+
+def fun_l2_n970(x)
+ if (x < 1)
+ fun_l3_n201(x)
+ else
+ fun_l3_n677(x)
+ end
+end
+
+def fun_l2_n971(x)
+ if (x < 1)
+ fun_l3_n990(x)
+ else
+ fun_l3_n251(x)
+ end
+end
+
+def fun_l2_n972(x)
+ if (x < 1)
+ fun_l3_n500(x)
+ else
+ fun_l3_n686(x)
+ end
+end
+
+def fun_l2_n973(x)
+ if (x < 1)
+ fun_l3_n969(x)
+ else
+ fun_l3_n819(x)
+ end
+end
+
+def fun_l2_n974(x)
+ if (x < 1)
+ fun_l3_n87(x)
+ else
+ fun_l3_n120(x)
+ end
+end
+
+def fun_l2_n975(x)
+ if (x < 1)
+ fun_l3_n701(x)
+ else
+ fun_l3_n569(x)
+ end
+end
+
+def fun_l2_n976(x)
+ if (x < 1)
+ fun_l3_n128(x)
+ else
+ fun_l3_n310(x)
+ end
+end
+
+def fun_l2_n977(x)
+ if (x < 1)
+ fun_l3_n690(x)
+ else
+ fun_l3_n5(x)
+ end
+end
+
+def fun_l2_n978(x)
+ if (x < 1)
+ fun_l3_n432(x)
+ else
+ fun_l3_n964(x)
+ end
+end
+
+def fun_l2_n979(x)
+ if (x < 1)
+ fun_l3_n198(x)
+ else
+ fun_l3_n161(x)
+ end
+end
+
+def fun_l2_n980(x)
+ if (x < 1)
+ fun_l3_n415(x)
+ else
+ fun_l3_n768(x)
+ end
+end
+
+def fun_l2_n981(x)
+ if (x < 1)
+ fun_l3_n635(x)
+ else
+ fun_l3_n569(x)
+ end
+end
+
+def fun_l2_n982(x)
+ if (x < 1)
+ fun_l3_n326(x)
+ else
+ fun_l3_n338(x)
+ end
+end
+
+def fun_l2_n983(x)
+ if (x < 1)
+ fun_l3_n243(x)
+ else
+ fun_l3_n48(x)
+ end
+end
+
+def fun_l2_n984(x)
+ if (x < 1)
+ fun_l3_n204(x)
+ else
+ fun_l3_n141(x)
+ end
+end
+
+def fun_l2_n985(x)
+ if (x < 1)
+ fun_l3_n805(x)
+ else
+ fun_l3_n577(x)
+ end
+end
+
+def fun_l2_n986(x)
+ if (x < 1)
+ fun_l3_n237(x)
+ else
+ fun_l3_n833(x)
+ end
+end
+
+def fun_l2_n987(x)
+ if (x < 1)
+ fun_l3_n643(x)
+ else
+ fun_l3_n629(x)
+ end
+end
+
+def fun_l2_n988(x)
+ if (x < 1)
+ fun_l3_n911(x)
+ else
+ fun_l3_n712(x)
+ end
+end
+
+def fun_l2_n989(x)
+ if (x < 1)
+ fun_l3_n936(x)
+ else
+ fun_l3_n300(x)
+ end
+end
+
+def fun_l2_n990(x)
+ if (x < 1)
+ fun_l3_n561(x)
+ else
+ fun_l3_n281(x)
+ end
+end
+
+def fun_l2_n991(x)
+ if (x < 1)
+ fun_l3_n226(x)
+ else
+ fun_l3_n203(x)
+ end
+end
+
+def fun_l2_n992(x)
+ if (x < 1)
+ fun_l3_n727(x)
+ else
+ fun_l3_n437(x)
+ end
+end
+
+def fun_l2_n993(x)
+ if (x < 1)
+ fun_l3_n608(x)
+ else
+ fun_l3_n169(x)
+ end
+end
+
+def fun_l2_n994(x)
+ if (x < 1)
+ fun_l3_n30(x)
+ else
+ fun_l3_n980(x)
+ end
+end
+
+def fun_l2_n995(x)
+ if (x < 1)
+ fun_l3_n652(x)
+ else
+ fun_l3_n122(x)
+ end
+end
+
+def fun_l2_n996(x)
+ if (x < 1)
+ fun_l3_n334(x)
+ else
+ fun_l3_n668(x)
+ end
+end
+
+def fun_l2_n997(x)
+ if (x < 1)
+ fun_l3_n241(x)
+ else
+ fun_l3_n515(x)
+ end
+end
+
+def fun_l2_n998(x)
+ if (x < 1)
+ fun_l3_n665(x)
+ else
+ fun_l3_n54(x)
+ end
+end
+
+def fun_l2_n999(x)
+ if (x < 1)
+ fun_l3_n568(x)
+ else
+ fun_l3_n652(x)
+ end
+end
+
+def fun_l3_n0(x)
+ if (x < 1)
+ fun_l4_n169(x)
+ else
+ fun_l4_n923(x)
+ end
+end
+
+def fun_l3_n1(x)
+ if (x < 1)
+ fun_l4_n214(x)
+ else
+ fun_l4_n506(x)
+ end
+end
+
+def fun_l3_n2(x)
+ if (x < 1)
+ fun_l4_n513(x)
+ else
+ fun_l4_n409(x)
+ end
+end
+
+def fun_l3_n3(x)
+ if (x < 1)
+ fun_l4_n133(x)
+ else
+ fun_l4_n293(x)
+ end
+end
+
+def fun_l3_n4(x)
+ if (x < 1)
+ fun_l4_n550(x)
+ else
+ fun_l4_n95(x)
+ end
+end
+
+def fun_l3_n5(x)
+ if (x < 1)
+ fun_l4_n13(x)
+ else
+ fun_l4_n508(x)
+ end
+end
+
+def fun_l3_n6(x)
+ if (x < 1)
+ fun_l4_n607(x)
+ else
+ fun_l4_n140(x)
+ end
+end
+
+def fun_l3_n7(x)
+ if (x < 1)
+ fun_l4_n65(x)
+ else
+ fun_l4_n90(x)
+ end
+end
+
+def fun_l3_n8(x)
+ if (x < 1)
+ fun_l4_n516(x)
+ else
+ fun_l4_n445(x)
+ end
+end
+
+def fun_l3_n9(x)
+ if (x < 1)
+ fun_l4_n713(x)
+ else
+ fun_l4_n487(x)
+ end
+end
+
+def fun_l3_n10(x)
+ if (x < 1)
+ fun_l4_n16(x)
+ else
+ fun_l4_n547(x)
+ end
+end
+
+def fun_l3_n11(x)
+ if (x < 1)
+ fun_l4_n561(x)
+ else
+ fun_l4_n530(x)
+ end
+end
+
+def fun_l3_n12(x)
+ if (x < 1)
+ fun_l4_n866(x)
+ else
+ fun_l4_n187(x)
+ end
+end
+
+def fun_l3_n13(x)
+ if (x < 1)
+ fun_l4_n8(x)
+ else
+ fun_l4_n458(x)
+ end
+end
+
+def fun_l3_n14(x)
+ if (x < 1)
+ fun_l4_n627(x)
+ else
+ fun_l4_n122(x)
+ end
+end
+
+def fun_l3_n15(x)
+ if (x < 1)
+ fun_l4_n988(x)
+ else
+ fun_l4_n4(x)
+ end
+end
+
+def fun_l3_n16(x)
+ if (x < 1)
+ fun_l4_n654(x)
+ else
+ fun_l4_n863(x)
+ end
+end
+
+def fun_l3_n17(x)
+ if (x < 1)
+ fun_l4_n112(x)
+ else
+ fun_l4_n223(x)
+ end
+end
+
+def fun_l3_n18(x)
+ if (x < 1)
+ fun_l4_n808(x)
+ else
+ fun_l4_n161(x)
+ end
+end
+
+def fun_l3_n19(x)
+ if (x < 1)
+ fun_l4_n265(x)
+ else
+ fun_l4_n860(x)
+ end
+end
+
+def fun_l3_n20(x)
+ if (x < 1)
+ fun_l4_n60(x)
+ else
+ fun_l4_n943(x)
+ end
+end
+
+def fun_l3_n21(x)
+ if (x < 1)
+ fun_l4_n707(x)
+ else
+ fun_l4_n990(x)
+ end
+end
+
+def fun_l3_n22(x)
+ if (x < 1)
+ fun_l4_n774(x)
+ else
+ fun_l4_n686(x)
+ end
+end
+
+def fun_l3_n23(x)
+ if (x < 1)
+ fun_l4_n552(x)
+ else
+ fun_l4_n935(x)
+ end
+end
+
+def fun_l3_n24(x)
+ if (x < 1)
+ fun_l4_n752(x)
+ else
+ fun_l4_n279(x)
+ end
+end
+
+def fun_l3_n25(x)
+ if (x < 1)
+ fun_l4_n325(x)
+ else
+ fun_l4_n440(x)
+ end
+end
+
+def fun_l3_n26(x)
+ if (x < 1)
+ fun_l4_n330(x)
+ else
+ fun_l4_n233(x)
+ end
+end
+
+def fun_l3_n27(x)
+ if (x < 1)
+ fun_l4_n112(x)
+ else
+ fun_l4_n399(x)
+ end
+end
+
+def fun_l3_n28(x)
+ if (x < 1)
+ fun_l4_n420(x)
+ else
+ fun_l4_n570(x)
+ end
+end
+
+def fun_l3_n29(x)
+ if (x < 1)
+ fun_l4_n515(x)
+ else
+ fun_l4_n485(x)
+ end
+end
+
+def fun_l3_n30(x)
+ if (x < 1)
+ fun_l4_n694(x)
+ else
+ fun_l4_n279(x)
+ end
+end
+
+def fun_l3_n31(x)
+ if (x < 1)
+ fun_l4_n683(x)
+ else
+ fun_l4_n396(x)
+ end
+end
+
+def fun_l3_n32(x)
+ if (x < 1)
+ fun_l4_n997(x)
+ else
+ fun_l4_n978(x)
+ end
+end
+
+def fun_l3_n33(x)
+ if (x < 1)
+ fun_l4_n260(x)
+ else
+ fun_l4_n895(x)
+ end
+end
+
+def fun_l3_n34(x)
+ if (x < 1)
+ fun_l4_n510(x)
+ else
+ fun_l4_n147(x)
+ end
+end
+
+def fun_l3_n35(x)
+ if (x < 1)
+ fun_l4_n415(x)
+ else
+ fun_l4_n590(x)
+ end
+end
+
+def fun_l3_n36(x)
+ if (x < 1)
+ fun_l4_n164(x)
+ else
+ fun_l4_n990(x)
+ end
+end
+
+def fun_l3_n37(x)
+ if (x < 1)
+ fun_l4_n744(x)
+ else
+ fun_l4_n981(x)
+ end
+end
+
+def fun_l3_n38(x)
+ if (x < 1)
+ fun_l4_n243(x)
+ else
+ fun_l4_n385(x)
+ end
+end
+
+def fun_l3_n39(x)
+ if (x < 1)
+ fun_l4_n874(x)
+ else
+ fun_l4_n941(x)
+ end
+end
+
+def fun_l3_n40(x)
+ if (x < 1)
+ fun_l4_n39(x)
+ else
+ fun_l4_n115(x)
+ end
+end
+
+def fun_l3_n41(x)
+ if (x < 1)
+ fun_l4_n829(x)
+ else
+ fun_l4_n991(x)
+ end
+end
+
+def fun_l3_n42(x)
+ if (x < 1)
+ fun_l4_n234(x)
+ else
+ fun_l4_n359(x)
+ end
+end
+
+def fun_l3_n43(x)
+ if (x < 1)
+ fun_l4_n481(x)
+ else
+ fun_l4_n368(x)
+ end
+end
+
+def fun_l3_n44(x)
+ if (x < 1)
+ fun_l4_n969(x)
+ else
+ fun_l4_n716(x)
+ end
+end
+
+def fun_l3_n45(x)
+ if (x < 1)
+ fun_l4_n858(x)
+ else
+ fun_l4_n446(x)
+ end
+end
+
+def fun_l3_n46(x)
+ if (x < 1)
+ fun_l4_n786(x)
+ else
+ fun_l4_n418(x)
+ end
+end
+
+def fun_l3_n47(x)
+ if (x < 1)
+ fun_l4_n261(x)
+ else
+ fun_l4_n346(x)
+ end
+end
+
+def fun_l3_n48(x)
+ if (x < 1)
+ fun_l4_n422(x)
+ else
+ fun_l4_n710(x)
+ end
+end
+
+def fun_l3_n49(x)
+ if (x < 1)
+ fun_l4_n533(x)
+ else
+ fun_l4_n599(x)
+ end
+end
+
+def fun_l3_n50(x)
+ if (x < 1)
+ fun_l4_n922(x)
+ else
+ fun_l4_n90(x)
+ end
+end
+
+def fun_l3_n51(x)
+ if (x < 1)
+ fun_l4_n718(x)
+ else
+ fun_l4_n854(x)
+ end
+end
+
+def fun_l3_n52(x)
+ if (x < 1)
+ fun_l4_n993(x)
+ else
+ fun_l4_n996(x)
+ end
+end
+
+def fun_l3_n53(x)
+ if (x < 1)
+ fun_l4_n628(x)
+ else
+ fun_l4_n589(x)
+ end
+end
+
+def fun_l3_n54(x)
+ if (x < 1)
+ fun_l4_n735(x)
+ else
+ fun_l4_n258(x)
+ end
+end
+
+def fun_l3_n55(x)
+ if (x < 1)
+ fun_l4_n794(x)
+ else
+ fun_l4_n559(x)
+ end
+end
+
+def fun_l3_n56(x)
+ if (x < 1)
+ fun_l4_n771(x)
+ else
+ fun_l4_n812(x)
+ end
+end
+
+def fun_l3_n57(x)
+ if (x < 1)
+ fun_l4_n106(x)
+ else
+ fun_l4_n144(x)
+ end
+end
+
+def fun_l3_n58(x)
+ if (x < 1)
+ fun_l4_n2(x)
+ else
+ fun_l4_n49(x)
+ end
+end
+
+def fun_l3_n59(x)
+ if (x < 1)
+ fun_l4_n540(x)
+ else
+ fun_l4_n164(x)
+ end
+end
+
+def fun_l3_n60(x)
+ if (x < 1)
+ fun_l4_n638(x)
+ else
+ fun_l4_n984(x)
+ end
+end
+
+def fun_l3_n61(x)
+ if (x < 1)
+ fun_l4_n144(x)
+ else
+ fun_l4_n236(x)
+ end
+end
+
+def fun_l3_n62(x)
+ if (x < 1)
+ fun_l4_n345(x)
+ else
+ fun_l4_n65(x)
+ end
+end
+
+def fun_l3_n63(x)
+ if (x < 1)
+ fun_l4_n112(x)
+ else
+ fun_l4_n216(x)
+ end
+end
+
+def fun_l3_n64(x)
+ if (x < 1)
+ fun_l4_n213(x)
+ else
+ fun_l4_n370(x)
+ end
+end
+
+def fun_l3_n65(x)
+ if (x < 1)
+ fun_l4_n845(x)
+ else
+ fun_l4_n672(x)
+ end
+end
+
+def fun_l3_n66(x)
+ if (x < 1)
+ fun_l4_n951(x)
+ else
+ fun_l4_n415(x)
+ end
+end
+
+def fun_l3_n67(x)
+ if (x < 1)
+ fun_l4_n997(x)
+ else
+ fun_l4_n760(x)
+ end
+end
+
+def fun_l3_n68(x)
+ if (x < 1)
+ fun_l4_n595(x)
+ else
+ fun_l4_n517(x)
+ end
+end
+
+def fun_l3_n69(x)
+ if (x < 1)
+ fun_l4_n776(x)
+ else
+ fun_l4_n550(x)
+ end
+end
+
+def fun_l3_n70(x)
+ if (x < 1)
+ fun_l4_n360(x)
+ else
+ fun_l4_n836(x)
+ end
+end
+
+def fun_l3_n71(x)
+ if (x < 1)
+ fun_l4_n214(x)
+ else
+ fun_l4_n532(x)
+ end
+end
+
+def fun_l3_n72(x)
+ if (x < 1)
+ fun_l4_n138(x)
+ else
+ fun_l4_n881(x)
+ end
+end
+
+def fun_l3_n73(x)
+ if (x < 1)
+ fun_l4_n793(x)
+ else
+ fun_l4_n866(x)
+ end
+end
+
+def fun_l3_n74(x)
+ if (x < 1)
+ fun_l4_n883(x)
+ else
+ fun_l4_n730(x)
+ end
+end
+
+def fun_l3_n75(x)
+ if (x < 1)
+ fun_l4_n525(x)
+ else
+ fun_l4_n188(x)
+ end
+end
+
+def fun_l3_n76(x)
+ if (x < 1)
+ fun_l4_n528(x)
+ else
+ fun_l4_n723(x)
+ end
+end
+
+def fun_l3_n77(x)
+ if (x < 1)
+ fun_l4_n954(x)
+ else
+ fun_l4_n581(x)
+ end
+end
+
+def fun_l3_n78(x)
+ if (x < 1)
+ fun_l4_n614(x)
+ else
+ fun_l4_n941(x)
+ end
+end
+
+def fun_l3_n79(x)
+ if (x < 1)
+ fun_l4_n396(x)
+ else
+ fun_l4_n539(x)
+ end
+end
+
+def fun_l3_n80(x)
+ if (x < 1)
+ fun_l4_n1(x)
+ else
+ fun_l4_n708(x)
+ end
+end
+
+def fun_l3_n81(x)
+ if (x < 1)
+ fun_l4_n626(x)
+ else
+ fun_l4_n418(x)
+ end
+end
+
+def fun_l3_n82(x)
+ if (x < 1)
+ fun_l4_n5(x)
+ else
+ fun_l4_n108(x)
+ end
+end
+
+def fun_l3_n83(x)
+ if (x < 1)
+ fun_l4_n683(x)
+ else
+ fun_l4_n679(x)
+ end
+end
+
+def fun_l3_n84(x)
+ if (x < 1)
+ fun_l4_n613(x)
+ else
+ fun_l4_n596(x)
+ end
+end
+
+def fun_l3_n85(x)
+ if (x < 1)
+ fun_l4_n490(x)
+ else
+ fun_l4_n178(x)
+ end
+end
+
+def fun_l3_n86(x)
+ if (x < 1)
+ fun_l4_n286(x)
+ else
+ fun_l4_n724(x)
+ end
+end
+
+def fun_l3_n87(x)
+ if (x < 1)
+ fun_l4_n989(x)
+ else
+ fun_l4_n711(x)
+ end
+end
+
+def fun_l3_n88(x)
+ if (x < 1)
+ fun_l4_n422(x)
+ else
+ fun_l4_n259(x)
+ end
+end
+
+def fun_l3_n89(x)
+ if (x < 1)
+ fun_l4_n938(x)
+ else
+ fun_l4_n123(x)
+ end
+end
+
+def fun_l3_n90(x)
+ if (x < 1)
+ fun_l4_n589(x)
+ else
+ fun_l4_n231(x)
+ end
+end
+
+def fun_l3_n91(x)
+ if (x < 1)
+ fun_l4_n484(x)
+ else
+ fun_l4_n439(x)
+ end
+end
+
+def fun_l3_n92(x)
+ if (x < 1)
+ fun_l4_n469(x)
+ else
+ fun_l4_n737(x)
+ end
+end
+
+def fun_l3_n93(x)
+ if (x < 1)
+ fun_l4_n93(x)
+ else
+ fun_l4_n907(x)
+ end
+end
+
+def fun_l3_n94(x)
+ if (x < 1)
+ fun_l4_n468(x)
+ else
+ fun_l4_n219(x)
+ end
+end
+
+def fun_l3_n95(x)
+ if (x < 1)
+ fun_l4_n409(x)
+ else
+ fun_l4_n921(x)
+ end
+end
+
+def fun_l3_n96(x)
+ if (x < 1)
+ fun_l4_n952(x)
+ else
+ fun_l4_n167(x)
+ end
+end
+
+def fun_l3_n97(x)
+ if (x < 1)
+ fun_l4_n177(x)
+ else
+ fun_l4_n462(x)
+ end
+end
+
+def fun_l3_n98(x)
+ if (x < 1)
+ fun_l4_n351(x)
+ else
+ fun_l4_n89(x)
+ end
+end
+
+def fun_l3_n99(x)
+ if (x < 1)
+ fun_l4_n869(x)
+ else
+ fun_l4_n502(x)
+ end
+end
+
+def fun_l3_n100(x)
+ if (x < 1)
+ fun_l4_n985(x)
+ else
+ fun_l4_n297(x)
+ end
+end
+
+def fun_l3_n101(x)
+ if (x < 1)
+ fun_l4_n48(x)
+ else
+ fun_l4_n895(x)
+ end
+end
+
+def fun_l3_n102(x)
+ if (x < 1)
+ fun_l4_n92(x)
+ else
+ fun_l4_n36(x)
+ end
+end
+
+def fun_l3_n103(x)
+ if (x < 1)
+ fun_l4_n610(x)
+ else
+ fun_l4_n616(x)
+ end
+end
+
+def fun_l3_n104(x)
+ if (x < 1)
+ fun_l4_n472(x)
+ else
+ fun_l4_n689(x)
+ end
+end
+
+def fun_l3_n105(x)
+ if (x < 1)
+ fun_l4_n75(x)
+ else
+ fun_l4_n161(x)
+ end
+end
+
+def fun_l3_n106(x)
+ if (x < 1)
+ fun_l4_n300(x)
+ else
+ fun_l4_n767(x)
+ end
+end
+
+def fun_l3_n107(x)
+ if (x < 1)
+ fun_l4_n707(x)
+ else
+ fun_l4_n229(x)
+ end
+end
+
+def fun_l3_n108(x)
+ if (x < 1)
+ fun_l4_n761(x)
+ else
+ fun_l4_n97(x)
+ end
+end
+
+def fun_l3_n109(x)
+ if (x < 1)
+ fun_l4_n734(x)
+ else
+ fun_l4_n290(x)
+ end
+end
+
+def fun_l3_n110(x)
+ if (x < 1)
+ fun_l4_n819(x)
+ else
+ fun_l4_n567(x)
+ end
+end
+
+def fun_l3_n111(x)
+ if (x < 1)
+ fun_l4_n904(x)
+ else
+ fun_l4_n322(x)
+ end
+end
+
+def fun_l3_n112(x)
+ if (x < 1)
+ fun_l4_n907(x)
+ else
+ fun_l4_n667(x)
+ end
+end
+
+def fun_l3_n113(x)
+ if (x < 1)
+ fun_l4_n473(x)
+ else
+ fun_l4_n620(x)
+ end
+end
+
+def fun_l3_n114(x)
+ if (x < 1)
+ fun_l4_n278(x)
+ else
+ fun_l4_n998(x)
+ end
+end
+
+def fun_l3_n115(x)
+ if (x < 1)
+ fun_l4_n185(x)
+ else
+ fun_l4_n962(x)
+ end
+end
+
+def fun_l3_n116(x)
+ if (x < 1)
+ fun_l4_n989(x)
+ else
+ fun_l4_n993(x)
+ end
+end
+
+def fun_l3_n117(x)
+ if (x < 1)
+ fun_l4_n140(x)
+ else
+ fun_l4_n456(x)
+ end
+end
+
+def fun_l3_n118(x)
+ if (x < 1)
+ fun_l4_n920(x)
+ else
+ fun_l4_n701(x)
+ end
+end
+
+def fun_l3_n119(x)
+ if (x < 1)
+ fun_l4_n263(x)
+ else
+ fun_l4_n837(x)
+ end
+end
+
+def fun_l3_n120(x)
+ if (x < 1)
+ fun_l4_n54(x)
+ else
+ fun_l4_n964(x)
+ end
+end
+
+def fun_l3_n121(x)
+ if (x < 1)
+ fun_l4_n540(x)
+ else
+ fun_l4_n543(x)
+ end
+end
+
+def fun_l3_n122(x)
+ if (x < 1)
+ fun_l4_n51(x)
+ else
+ fun_l4_n453(x)
+ end
+end
+
+def fun_l3_n123(x)
+ if (x < 1)
+ fun_l4_n726(x)
+ else
+ fun_l4_n785(x)
+ end
+end
+
+def fun_l3_n124(x)
+ if (x < 1)
+ fun_l4_n932(x)
+ else
+ fun_l4_n583(x)
+ end
+end
+
+def fun_l3_n125(x)
+ if (x < 1)
+ fun_l4_n471(x)
+ else
+ fun_l4_n518(x)
+ end
+end
+
+def fun_l3_n126(x)
+ if (x < 1)
+ fun_l4_n351(x)
+ else
+ fun_l4_n825(x)
+ end
+end
+
+def fun_l3_n127(x)
+ if (x < 1)
+ fun_l4_n759(x)
+ else
+ fun_l4_n203(x)
+ end
+end
+
+def fun_l3_n128(x)
+ if (x < 1)
+ fun_l4_n336(x)
+ else
+ fun_l4_n861(x)
+ end
+end
+
+def fun_l3_n129(x)
+ if (x < 1)
+ fun_l4_n573(x)
+ else
+ fun_l4_n568(x)
+ end
+end
+
+def fun_l3_n130(x)
+ if (x < 1)
+ fun_l4_n788(x)
+ else
+ fun_l4_n259(x)
+ end
+end
+
+def fun_l3_n131(x)
+ if (x < 1)
+ fun_l4_n392(x)
+ else
+ fun_l4_n932(x)
+ end
+end
+
+def fun_l3_n132(x)
+ if (x < 1)
+ fun_l4_n919(x)
+ else
+ fun_l4_n650(x)
+ end
+end
+
+def fun_l3_n133(x)
+ if (x < 1)
+ fun_l4_n895(x)
+ else
+ fun_l4_n983(x)
+ end
+end
+
+def fun_l3_n134(x)
+ if (x < 1)
+ fun_l4_n389(x)
+ else
+ fun_l4_n358(x)
+ end
+end
+
+def fun_l3_n135(x)
+ if (x < 1)
+ fun_l4_n732(x)
+ else
+ fun_l4_n747(x)
+ end
+end
+
+def fun_l3_n136(x)
+ if (x < 1)
+ fun_l4_n756(x)
+ else
+ fun_l4_n592(x)
+ end
+end
+
+def fun_l3_n137(x)
+ if (x < 1)
+ fun_l4_n581(x)
+ else
+ fun_l4_n24(x)
+ end
+end
+
+def fun_l3_n138(x)
+ if (x < 1)
+ fun_l4_n932(x)
+ else
+ fun_l4_n599(x)
+ end
+end
+
+def fun_l3_n139(x)
+ if (x < 1)
+ fun_l4_n955(x)
+ else
+ fun_l4_n148(x)
+ end
+end
+
+def fun_l3_n140(x)
+ if (x < 1)
+ fun_l4_n332(x)
+ else
+ fun_l4_n677(x)
+ end
+end
+
+def fun_l3_n141(x)
+ if (x < 1)
+ fun_l4_n152(x)
+ else
+ fun_l4_n696(x)
+ end
+end
+
+def fun_l3_n142(x)
+ if (x < 1)
+ fun_l4_n295(x)
+ else
+ fun_l4_n205(x)
+ end
+end
+
+def fun_l3_n143(x)
+ if (x < 1)
+ fun_l4_n543(x)
+ else
+ fun_l4_n951(x)
+ end
+end
+
+def fun_l3_n144(x)
+ if (x < 1)
+ fun_l4_n656(x)
+ else
+ fun_l4_n494(x)
+ end
+end
+
+def fun_l3_n145(x)
+ if (x < 1)
+ fun_l4_n729(x)
+ else
+ fun_l4_n749(x)
+ end
+end
+
+def fun_l3_n146(x)
+ if (x < 1)
+ fun_l4_n197(x)
+ else
+ fun_l4_n3(x)
+ end
+end
+
+def fun_l3_n147(x)
+ if (x < 1)
+ fun_l4_n519(x)
+ else
+ fun_l4_n36(x)
+ end
+end
+
+def fun_l3_n148(x)
+ if (x < 1)
+ fun_l4_n100(x)
+ else
+ fun_l4_n463(x)
+ end
+end
+
+def fun_l3_n149(x)
+ if (x < 1)
+ fun_l4_n890(x)
+ else
+ fun_l4_n947(x)
+ end
+end
+
+def fun_l3_n150(x)
+ if (x < 1)
+ fun_l4_n512(x)
+ else
+ fun_l4_n982(x)
+ end
+end
+
+def fun_l3_n151(x)
+ if (x < 1)
+ fun_l4_n750(x)
+ else
+ fun_l4_n781(x)
+ end
+end
+
+def fun_l3_n152(x)
+ if (x < 1)
+ fun_l4_n193(x)
+ else
+ fun_l4_n530(x)
+ end
+end
+
+def fun_l3_n153(x)
+ if (x < 1)
+ fun_l4_n189(x)
+ else
+ fun_l4_n209(x)
+ end
+end
+
+def fun_l3_n154(x)
+ if (x < 1)
+ fun_l4_n343(x)
+ else
+ fun_l4_n44(x)
+ end
+end
+
+def fun_l3_n155(x)
+ if (x < 1)
+ fun_l4_n536(x)
+ else
+ fun_l4_n228(x)
+ end
+end
+
+def fun_l3_n156(x)
+ if (x < 1)
+ fun_l4_n475(x)
+ else
+ fun_l4_n790(x)
+ end
+end
+
+def fun_l3_n157(x)
+ if (x < 1)
+ fun_l4_n954(x)
+ else
+ fun_l4_n242(x)
+ end
+end
+
+def fun_l3_n158(x)
+ if (x < 1)
+ fun_l4_n19(x)
+ else
+ fun_l4_n735(x)
+ end
+end
+
+def fun_l3_n159(x)
+ if (x < 1)
+ fun_l4_n900(x)
+ else
+ fun_l4_n456(x)
+ end
+end
+
+def fun_l3_n160(x)
+ if (x < 1)
+ fun_l4_n193(x)
+ else
+ fun_l4_n606(x)
+ end
+end
+
+def fun_l3_n161(x)
+ if (x < 1)
+ fun_l4_n684(x)
+ else
+ fun_l4_n622(x)
+ end
+end
+
+def fun_l3_n162(x)
+ if (x < 1)
+ fun_l4_n260(x)
+ else
+ fun_l4_n582(x)
+ end
+end
+
+def fun_l3_n163(x)
+ if (x < 1)
+ fun_l4_n713(x)
+ else
+ fun_l4_n601(x)
+ end
+end
+
+def fun_l3_n164(x)
+ if (x < 1)
+ fun_l4_n819(x)
+ else
+ fun_l4_n642(x)
+ end
+end
+
+def fun_l3_n165(x)
+ if (x < 1)
+ fun_l4_n45(x)
+ else
+ fun_l4_n777(x)
+ end
+end
+
+def fun_l3_n166(x)
+ if (x < 1)
+ fun_l4_n256(x)
+ else
+ fun_l4_n92(x)
+ end
+end
+
+def fun_l3_n167(x)
+ if (x < 1)
+ fun_l4_n975(x)
+ else
+ fun_l4_n962(x)
+ end
+end
+
+def fun_l3_n168(x)
+ if (x < 1)
+ fun_l4_n579(x)
+ else
+ fun_l4_n208(x)
+ end
+end
+
+def fun_l3_n169(x)
+ if (x < 1)
+ fun_l4_n133(x)
+ else
+ fun_l4_n636(x)
+ end
+end
+
+def fun_l3_n170(x)
+ if (x < 1)
+ fun_l4_n863(x)
+ else
+ fun_l4_n168(x)
+ end
+end
+
+def fun_l3_n171(x)
+ if (x < 1)
+ fun_l4_n396(x)
+ else
+ fun_l4_n654(x)
+ end
+end
+
+def fun_l3_n172(x)
+ if (x < 1)
+ fun_l4_n963(x)
+ else
+ fun_l4_n420(x)
+ end
+end
+
+def fun_l3_n173(x)
+ if (x < 1)
+ fun_l4_n487(x)
+ else
+ fun_l4_n573(x)
+ end
+end
+
+def fun_l3_n174(x)
+ if (x < 1)
+ fun_l4_n847(x)
+ else
+ fun_l4_n476(x)
+ end
+end
+
+def fun_l3_n175(x)
+ if (x < 1)
+ fun_l4_n712(x)
+ else
+ fun_l4_n522(x)
+ end
+end
+
+def fun_l3_n176(x)
+ if (x < 1)
+ fun_l4_n292(x)
+ else
+ fun_l4_n717(x)
+ end
+end
+
+def fun_l3_n177(x)
+ if (x < 1)
+ fun_l4_n945(x)
+ else
+ fun_l4_n146(x)
+ end
+end
+
+def fun_l3_n178(x)
+ if (x < 1)
+ fun_l4_n163(x)
+ else
+ fun_l4_n28(x)
+ end
+end
+
+def fun_l3_n179(x)
+ if (x < 1)
+ fun_l4_n738(x)
+ else
+ fun_l4_n502(x)
+ end
+end
+
+def fun_l3_n180(x)
+ if (x < 1)
+ fun_l4_n8(x)
+ else
+ fun_l4_n56(x)
+ end
+end
+
+def fun_l3_n181(x)
+ if (x < 1)
+ fun_l4_n58(x)
+ else
+ fun_l4_n155(x)
+ end
+end
+
+def fun_l3_n182(x)
+ if (x < 1)
+ fun_l4_n298(x)
+ else
+ fun_l4_n580(x)
+ end
+end
+
+def fun_l3_n183(x)
+ if (x < 1)
+ fun_l4_n860(x)
+ else
+ fun_l4_n176(x)
+ end
+end
+
+def fun_l3_n184(x)
+ if (x < 1)
+ fun_l4_n108(x)
+ else
+ fun_l4_n986(x)
+ end
+end
+
+def fun_l3_n185(x)
+ if (x < 1)
+ fun_l4_n366(x)
+ else
+ fun_l4_n110(x)
+ end
+end
+
+def fun_l3_n186(x)
+ if (x < 1)
+ fun_l4_n177(x)
+ else
+ fun_l4_n158(x)
+ end
+end
+
+def fun_l3_n187(x)
+ if (x < 1)
+ fun_l4_n212(x)
+ else
+ fun_l4_n803(x)
+ end
+end
+
+def fun_l3_n188(x)
+ if (x < 1)
+ fun_l4_n946(x)
+ else
+ fun_l4_n281(x)
+ end
+end
+
+def fun_l3_n189(x)
+ if (x < 1)
+ fun_l4_n610(x)
+ else
+ fun_l4_n691(x)
+ end
+end
+
+def fun_l3_n190(x)
+ if (x < 1)
+ fun_l4_n784(x)
+ else
+ fun_l4_n300(x)
+ end
+end
+
+def fun_l3_n191(x)
+ if (x < 1)
+ fun_l4_n272(x)
+ else
+ fun_l4_n809(x)
+ end
+end
+
+def fun_l3_n192(x)
+ if (x < 1)
+ fun_l4_n812(x)
+ else
+ fun_l4_n633(x)
+ end
+end
+
+def fun_l3_n193(x)
+ if (x < 1)
+ fun_l4_n880(x)
+ else
+ fun_l4_n267(x)
+ end
+end
+
+def fun_l3_n194(x)
+ if (x < 1)
+ fun_l4_n454(x)
+ else
+ fun_l4_n567(x)
+ end
+end
+
+def fun_l3_n195(x)
+ if (x < 1)
+ fun_l4_n919(x)
+ else
+ fun_l4_n184(x)
+ end
+end
+
+def fun_l3_n196(x)
+ if (x < 1)
+ fun_l4_n294(x)
+ else
+ fun_l4_n150(x)
+ end
+end
+
+def fun_l3_n197(x)
+ if (x < 1)
+ fun_l4_n543(x)
+ else
+ fun_l4_n319(x)
+ end
+end
+
+def fun_l3_n198(x)
+ if (x < 1)
+ fun_l4_n91(x)
+ else
+ fun_l4_n378(x)
+ end
+end
+
+def fun_l3_n199(x)
+ if (x < 1)
+ fun_l4_n590(x)
+ else
+ fun_l4_n195(x)
+ end
+end
+
+def fun_l3_n200(x)
+ if (x < 1)
+ fun_l4_n532(x)
+ else
+ fun_l4_n346(x)
+ end
+end
+
+def fun_l3_n201(x)
+ if (x < 1)
+ fun_l4_n340(x)
+ else
+ fun_l4_n129(x)
+ end
+end
+
+def fun_l3_n202(x)
+ if (x < 1)
+ fun_l4_n193(x)
+ else
+ fun_l4_n676(x)
+ end
+end
+
+def fun_l3_n203(x)
+ if (x < 1)
+ fun_l4_n210(x)
+ else
+ fun_l4_n982(x)
+ end
+end
+
+def fun_l3_n204(x)
+ if (x < 1)
+ fun_l4_n247(x)
+ else
+ fun_l4_n550(x)
+ end
+end
+
+def fun_l3_n205(x)
+ if (x < 1)
+ fun_l4_n727(x)
+ else
+ fun_l4_n737(x)
+ end
+end
+
+def fun_l3_n206(x)
+ if (x < 1)
+ fun_l4_n111(x)
+ else
+ fun_l4_n952(x)
+ end
+end
+
+def fun_l3_n207(x)
+ if (x < 1)
+ fun_l4_n996(x)
+ else
+ fun_l4_n865(x)
+ end
+end
+
+def fun_l3_n208(x)
+ if (x < 1)
+ fun_l4_n945(x)
+ else
+ fun_l4_n488(x)
+ end
+end
+
+def fun_l3_n209(x)
+ if (x < 1)
+ fun_l4_n697(x)
+ else
+ fun_l4_n366(x)
+ end
+end
+
+def fun_l3_n210(x)
+ if (x < 1)
+ fun_l4_n180(x)
+ else
+ fun_l4_n995(x)
+ end
+end
+
+def fun_l3_n211(x)
+ if (x < 1)
+ fun_l4_n972(x)
+ else
+ fun_l4_n783(x)
+ end
+end
+
+def fun_l3_n212(x)
+ if (x < 1)
+ fun_l4_n58(x)
+ else
+ fun_l4_n430(x)
+ end
+end
+
+def fun_l3_n213(x)
+ if (x < 1)
+ fun_l4_n904(x)
+ else
+ fun_l4_n703(x)
+ end
+end
+
+def fun_l3_n214(x)
+ if (x < 1)
+ fun_l4_n882(x)
+ else
+ fun_l4_n648(x)
+ end
+end
+
+def fun_l3_n215(x)
+ if (x < 1)
+ fun_l4_n800(x)
+ else
+ fun_l4_n680(x)
+ end
+end
+
+def fun_l3_n216(x)
+ if (x < 1)
+ fun_l4_n205(x)
+ else
+ fun_l4_n185(x)
+ end
+end
+
+def fun_l3_n217(x)
+ if (x < 1)
+ fun_l4_n242(x)
+ else
+ fun_l4_n834(x)
+ end
+end
+
+def fun_l3_n218(x)
+ if (x < 1)
+ fun_l4_n551(x)
+ else
+ fun_l4_n399(x)
+ end
+end
+
+def fun_l3_n219(x)
+ if (x < 1)
+ fun_l4_n820(x)
+ else
+ fun_l4_n403(x)
+ end
+end
+
+def fun_l3_n220(x)
+ if (x < 1)
+ fun_l4_n874(x)
+ else
+ fun_l4_n584(x)
+ end
+end
+
+def fun_l3_n221(x)
+ if (x < 1)
+ fun_l4_n845(x)
+ else
+ fun_l4_n56(x)
+ end
+end
+
+def fun_l3_n222(x)
+ if (x < 1)
+ fun_l4_n947(x)
+ else
+ fun_l4_n299(x)
+ end
+end
+
+def fun_l3_n223(x)
+ if (x < 1)
+ fun_l4_n533(x)
+ else
+ fun_l4_n184(x)
+ end
+end
+
+def fun_l3_n224(x)
+ if (x < 1)
+ fun_l4_n760(x)
+ else
+ fun_l4_n507(x)
+ end
+end
+
+def fun_l3_n225(x)
+ if (x < 1)
+ fun_l4_n47(x)
+ else
+ fun_l4_n712(x)
+ end
+end
+
+def fun_l3_n226(x)
+ if (x < 1)
+ fun_l4_n470(x)
+ else
+ fun_l4_n760(x)
+ end
+end
+
+def fun_l3_n227(x)
+ if (x < 1)
+ fun_l4_n932(x)
+ else
+ fun_l4_n292(x)
+ end
+end
+
+def fun_l3_n228(x)
+ if (x < 1)
+ fun_l4_n44(x)
+ else
+ fun_l4_n855(x)
+ end
+end
+
+def fun_l3_n229(x)
+ if (x < 1)
+ fun_l4_n385(x)
+ else
+ fun_l4_n284(x)
+ end
+end
+
+def fun_l3_n230(x)
+ if (x < 1)
+ fun_l4_n272(x)
+ else
+ fun_l4_n407(x)
+ end
+end
+
+def fun_l3_n231(x)
+ if (x < 1)
+ fun_l4_n820(x)
+ else
+ fun_l4_n375(x)
+ end
+end
+
+def fun_l3_n232(x)
+ if (x < 1)
+ fun_l4_n165(x)
+ else
+ fun_l4_n38(x)
+ end
+end
+
+def fun_l3_n233(x)
+ if (x < 1)
+ fun_l4_n772(x)
+ else
+ fun_l4_n179(x)
+ end
+end
+
+def fun_l3_n234(x)
+ if (x < 1)
+ fun_l4_n980(x)
+ else
+ fun_l4_n678(x)
+ end
+end
+
+def fun_l3_n235(x)
+ if (x < 1)
+ fun_l4_n279(x)
+ else
+ fun_l4_n834(x)
+ end
+end
+
+def fun_l3_n236(x)
+ if (x < 1)
+ fun_l4_n227(x)
+ else
+ fun_l4_n11(x)
+ end
+end
+
+def fun_l3_n237(x)
+ if (x < 1)
+ fun_l4_n724(x)
+ else
+ fun_l4_n659(x)
+ end
+end
+
+def fun_l3_n238(x)
+ if (x < 1)
+ fun_l4_n569(x)
+ else
+ fun_l4_n693(x)
+ end
+end
+
+def fun_l3_n239(x)
+ if (x < 1)
+ fun_l4_n933(x)
+ else
+ fun_l4_n897(x)
+ end
+end
+
+def fun_l3_n240(x)
+ if (x < 1)
+ fun_l4_n215(x)
+ else
+ fun_l4_n784(x)
+ end
+end
+
+def fun_l3_n241(x)
+ if (x < 1)
+ fun_l4_n964(x)
+ else
+ fun_l4_n430(x)
+ end
+end
+
+def fun_l3_n242(x)
+ if (x < 1)
+ fun_l4_n91(x)
+ else
+ fun_l4_n190(x)
+ end
+end
+
+def fun_l3_n243(x)
+ if (x < 1)
+ fun_l4_n375(x)
+ else
+ fun_l4_n638(x)
+ end
+end
+
+def fun_l3_n244(x)
+ if (x < 1)
+ fun_l4_n381(x)
+ else
+ fun_l4_n324(x)
+ end
+end
+
+def fun_l3_n245(x)
+ if (x < 1)
+ fun_l4_n983(x)
+ else
+ fun_l4_n248(x)
+ end
+end
+
+def fun_l3_n246(x)
+ if (x < 1)
+ fun_l4_n336(x)
+ else
+ fun_l4_n647(x)
+ end
+end
+
+def fun_l3_n247(x)
+ if (x < 1)
+ fun_l4_n64(x)
+ else
+ fun_l4_n957(x)
+ end
+end
+
+def fun_l3_n248(x)
+ if (x < 1)
+ fun_l4_n313(x)
+ else
+ fun_l4_n662(x)
+ end
+end
+
+def fun_l3_n249(x)
+ if (x < 1)
+ fun_l4_n528(x)
+ else
+ fun_l4_n448(x)
+ end
+end
+
+def fun_l3_n250(x)
+ if (x < 1)
+ fun_l4_n9(x)
+ else
+ fun_l4_n424(x)
+ end
+end
+
+def fun_l3_n251(x)
+ if (x < 1)
+ fun_l4_n290(x)
+ else
+ fun_l4_n416(x)
+ end
+end
+
+def fun_l3_n252(x)
+ if (x < 1)
+ fun_l4_n159(x)
+ else
+ fun_l4_n780(x)
+ end
+end
+
+def fun_l3_n253(x)
+ if (x < 1)
+ fun_l4_n863(x)
+ else
+ fun_l4_n192(x)
+ end
+end
+
+def fun_l3_n254(x)
+ if (x < 1)
+ fun_l4_n658(x)
+ else
+ fun_l4_n816(x)
+ end
+end
+
+def fun_l3_n255(x)
+ if (x < 1)
+ fun_l4_n686(x)
+ else
+ fun_l4_n586(x)
+ end
+end
+
+def fun_l3_n256(x)
+ if (x < 1)
+ fun_l4_n110(x)
+ else
+ fun_l4_n290(x)
+ end
+end
+
+def fun_l3_n257(x)
+ if (x < 1)
+ fun_l4_n355(x)
+ else
+ fun_l4_n862(x)
+ end
+end
+
+def fun_l3_n258(x)
+ if (x < 1)
+ fun_l4_n63(x)
+ else
+ fun_l4_n205(x)
+ end
+end
+
+def fun_l3_n259(x)
+ if (x < 1)
+ fun_l4_n766(x)
+ else
+ fun_l4_n130(x)
+ end
+end
+
+def fun_l3_n260(x)
+ if (x < 1)
+ fun_l4_n670(x)
+ else
+ fun_l4_n313(x)
+ end
+end
+
+def fun_l3_n261(x)
+ if (x < 1)
+ fun_l4_n738(x)
+ else
+ fun_l4_n796(x)
+ end
+end
+
+def fun_l3_n262(x)
+ if (x < 1)
+ fun_l4_n925(x)
+ else
+ fun_l4_n267(x)
+ end
+end
+
+def fun_l3_n263(x)
+ if (x < 1)
+ fun_l4_n515(x)
+ else
+ fun_l4_n298(x)
+ end
+end
+
+def fun_l3_n264(x)
+ if (x < 1)
+ fun_l4_n883(x)
+ else
+ fun_l4_n809(x)
+ end
+end
+
+def fun_l3_n265(x)
+ if (x < 1)
+ fun_l4_n138(x)
+ else
+ fun_l4_n665(x)
+ end
+end
+
+def fun_l3_n266(x)
+ if (x < 1)
+ fun_l4_n141(x)
+ else
+ fun_l4_n641(x)
+ end
+end
+
+def fun_l3_n267(x)
+ if (x < 1)
+ fun_l4_n936(x)
+ else
+ fun_l4_n233(x)
+ end
+end
+
+def fun_l3_n268(x)
+ if (x < 1)
+ fun_l4_n28(x)
+ else
+ fun_l4_n351(x)
+ end
+end
+
+def fun_l3_n269(x)
+ if (x < 1)
+ fun_l4_n62(x)
+ else
+ fun_l4_n17(x)
+ end
+end
+
+def fun_l3_n270(x)
+ if (x < 1)
+ fun_l4_n489(x)
+ else
+ fun_l4_n408(x)
+ end
+end
+
+def fun_l3_n271(x)
+ if (x < 1)
+ fun_l4_n276(x)
+ else
+ fun_l4_n799(x)
+ end
+end
+
+def fun_l3_n272(x)
+ if (x < 1)
+ fun_l4_n103(x)
+ else
+ fun_l4_n804(x)
+ end
+end
+
+def fun_l3_n273(x)
+ if (x < 1)
+ fun_l4_n850(x)
+ else
+ fun_l4_n388(x)
+ end
+end
+
+def fun_l3_n274(x)
+ if (x < 1)
+ fun_l4_n651(x)
+ else
+ fun_l4_n484(x)
+ end
+end
+
+def fun_l3_n275(x)
+ if (x < 1)
+ fun_l4_n693(x)
+ else
+ fun_l4_n20(x)
+ end
+end
+
+def fun_l3_n276(x)
+ if (x < 1)
+ fun_l4_n897(x)
+ else
+ fun_l4_n328(x)
+ end
+end
+
+def fun_l3_n277(x)
+ if (x < 1)
+ fun_l4_n632(x)
+ else
+ fun_l4_n120(x)
+ end
+end
+
+def fun_l3_n278(x)
+ if (x < 1)
+ fun_l4_n919(x)
+ else
+ fun_l4_n921(x)
+ end
+end
+
+def fun_l3_n279(x)
+ if (x < 1)
+ fun_l4_n461(x)
+ else
+ fun_l4_n219(x)
+ end
+end
+
+def fun_l3_n280(x)
+ if (x < 1)
+ fun_l4_n867(x)
+ else
+ fun_l4_n682(x)
+ end
+end
+
+def fun_l3_n281(x)
+ if (x < 1)
+ fun_l4_n233(x)
+ else
+ fun_l4_n589(x)
+ end
+end
+
+def fun_l3_n282(x)
+ if (x < 1)
+ fun_l4_n516(x)
+ else
+ fun_l4_n970(x)
+ end
+end
+
+def fun_l3_n283(x)
+ if (x < 1)
+ fun_l4_n300(x)
+ else
+ fun_l4_n934(x)
+ end
+end
+
+def fun_l3_n284(x)
+ if (x < 1)
+ fun_l4_n736(x)
+ else
+ fun_l4_n516(x)
+ end
+end
+
+def fun_l3_n285(x)
+ if (x < 1)
+ fun_l4_n401(x)
+ else
+ fun_l4_n539(x)
+ end
+end
+
+def fun_l3_n286(x)
+ if (x < 1)
+ fun_l4_n342(x)
+ else
+ fun_l4_n142(x)
+ end
+end
+
+def fun_l3_n287(x)
+ if (x < 1)
+ fun_l4_n44(x)
+ else
+ fun_l4_n311(x)
+ end
+end
+
+def fun_l3_n288(x)
+ if (x < 1)
+ fun_l4_n698(x)
+ else
+ fun_l4_n407(x)
+ end
+end
+
+def fun_l3_n289(x)
+ if (x < 1)
+ fun_l4_n714(x)
+ else
+ fun_l4_n324(x)
+ end
+end
+
+def fun_l3_n290(x)
+ if (x < 1)
+ fun_l4_n862(x)
+ else
+ fun_l4_n807(x)
+ end
+end
+
+def fun_l3_n291(x)
+ if (x < 1)
+ fun_l4_n446(x)
+ else
+ fun_l4_n378(x)
+ end
+end
+
+def fun_l3_n292(x)
+ if (x < 1)
+ fun_l4_n418(x)
+ else
+ fun_l4_n194(x)
+ end
+end
+
+def fun_l3_n293(x)
+ if (x < 1)
+ fun_l4_n336(x)
+ else
+ fun_l4_n895(x)
+ end
+end
+
+def fun_l3_n294(x)
+ if (x < 1)
+ fun_l4_n928(x)
+ else
+ fun_l4_n154(x)
+ end
+end
+
+def fun_l3_n295(x)
+ if (x < 1)
+ fun_l4_n764(x)
+ else
+ fun_l4_n335(x)
+ end
+end
+
+def fun_l3_n296(x)
+ if (x < 1)
+ fun_l4_n840(x)
+ else
+ fun_l4_n513(x)
+ end
+end
+
+def fun_l3_n297(x)
+ if (x < 1)
+ fun_l4_n520(x)
+ else
+ fun_l4_n838(x)
+ end
+end
+
+def fun_l3_n298(x)
+ if (x < 1)
+ fun_l4_n831(x)
+ else
+ fun_l4_n344(x)
+ end
+end
+
+def fun_l3_n299(x)
+ if (x < 1)
+ fun_l4_n110(x)
+ else
+ fun_l4_n19(x)
+ end
+end
+
+def fun_l3_n300(x)
+ if (x < 1)
+ fun_l4_n272(x)
+ else
+ fun_l4_n952(x)
+ end
+end
+
+def fun_l3_n301(x)
+ if (x < 1)
+ fun_l4_n659(x)
+ else
+ fun_l4_n439(x)
+ end
+end
+
+def fun_l3_n302(x)
+ if (x < 1)
+ fun_l4_n787(x)
+ else
+ fun_l4_n189(x)
+ end
+end
+
+def fun_l3_n303(x)
+ if (x < 1)
+ fun_l4_n549(x)
+ else
+ fun_l4_n594(x)
+ end
+end
+
+def fun_l3_n304(x)
+ if (x < 1)
+ fun_l4_n255(x)
+ else
+ fun_l4_n822(x)
+ end
+end
+
+def fun_l3_n305(x)
+ if (x < 1)
+ fun_l4_n312(x)
+ else
+ fun_l4_n935(x)
+ end
+end
+
+def fun_l3_n306(x)
+ if (x < 1)
+ fun_l4_n831(x)
+ else
+ fun_l4_n299(x)
+ end
+end
+
+def fun_l3_n307(x)
+ if (x < 1)
+ fun_l4_n154(x)
+ else
+ fun_l4_n520(x)
+ end
+end
+
+def fun_l3_n308(x)
+ if (x < 1)
+ fun_l4_n768(x)
+ else
+ fun_l4_n676(x)
+ end
+end
+
+def fun_l3_n309(x)
+ if (x < 1)
+ fun_l4_n816(x)
+ else
+ fun_l4_n447(x)
+ end
+end
+
+def fun_l3_n310(x)
+ if (x < 1)
+ fun_l4_n689(x)
+ else
+ fun_l4_n244(x)
+ end
+end
+
+def fun_l3_n311(x)
+ if (x < 1)
+ fun_l4_n389(x)
+ else
+ fun_l4_n326(x)
+ end
+end
+
+def fun_l3_n312(x)
+ if (x < 1)
+ fun_l4_n125(x)
+ else
+ fun_l4_n502(x)
+ end
+end
+
+def fun_l3_n313(x)
+ if (x < 1)
+ fun_l4_n327(x)
+ else
+ fun_l4_n123(x)
+ end
+end
+
+def fun_l3_n314(x)
+ if (x < 1)
+ fun_l4_n558(x)
+ else
+ fun_l4_n940(x)
+ end
+end
+
+def fun_l3_n315(x)
+ if (x < 1)
+ fun_l4_n652(x)
+ else
+ fun_l4_n10(x)
+ end
+end
+
+def fun_l3_n316(x)
+ if (x < 1)
+ fun_l4_n483(x)
+ else
+ fun_l4_n315(x)
+ end
+end
+
+def fun_l3_n317(x)
+ if (x < 1)
+ fun_l4_n567(x)
+ else
+ fun_l4_n540(x)
+ end
+end
+
+def fun_l3_n318(x)
+ if (x < 1)
+ fun_l4_n449(x)
+ else
+ fun_l4_n760(x)
+ end
+end
+
+def fun_l3_n319(x)
+ if (x < 1)
+ fun_l4_n111(x)
+ else
+ fun_l4_n173(x)
+ end
+end
+
+def fun_l3_n320(x)
+ if (x < 1)
+ fun_l4_n373(x)
+ else
+ fun_l4_n615(x)
+ end
+end
+
+def fun_l3_n321(x)
+ if (x < 1)
+ fun_l4_n570(x)
+ else
+ fun_l4_n27(x)
+ end
+end
+
+def fun_l3_n322(x)
+ if (x < 1)
+ fun_l4_n235(x)
+ else
+ fun_l4_n695(x)
+ end
+end
+
+def fun_l3_n323(x)
+ if (x < 1)
+ fun_l4_n788(x)
+ else
+ fun_l4_n57(x)
+ end
+end
+
+def fun_l3_n324(x)
+ if (x < 1)
+ fun_l4_n7(x)
+ else
+ fun_l4_n75(x)
+ end
+end
+
+def fun_l3_n325(x)
+ if (x < 1)
+ fun_l4_n502(x)
+ else
+ fun_l4_n459(x)
+ end
+end
+
+def fun_l3_n326(x)
+ if (x < 1)
+ fun_l4_n572(x)
+ else
+ fun_l4_n324(x)
+ end
+end
+
+def fun_l3_n327(x)
+ if (x < 1)
+ fun_l4_n860(x)
+ else
+ fun_l4_n250(x)
+ end
+end
+
+def fun_l3_n328(x)
+ if (x < 1)
+ fun_l4_n242(x)
+ else
+ fun_l4_n667(x)
+ end
+end
+
+def fun_l3_n329(x)
+ if (x < 1)
+ fun_l4_n589(x)
+ else
+ fun_l4_n236(x)
+ end
+end
+
+def fun_l3_n330(x)
+ if (x < 1)
+ fun_l4_n100(x)
+ else
+ fun_l4_n476(x)
+ end
+end
+
+def fun_l3_n331(x)
+ if (x < 1)
+ fun_l4_n779(x)
+ else
+ fun_l4_n667(x)
+ end
+end
+
+def fun_l3_n332(x)
+ if (x < 1)
+ fun_l4_n277(x)
+ else
+ fun_l4_n441(x)
+ end
+end
+
+def fun_l3_n333(x)
+ if (x < 1)
+ fun_l4_n379(x)
+ else
+ fun_l4_n331(x)
+ end
+end
+
+def fun_l3_n334(x)
+ if (x < 1)
+ fun_l4_n802(x)
+ else
+ fun_l4_n588(x)
+ end
+end
+
+def fun_l3_n335(x)
+ if (x < 1)
+ fun_l4_n385(x)
+ else
+ fun_l4_n918(x)
+ end
+end
+
+def fun_l3_n336(x)
+ if (x < 1)
+ fun_l4_n532(x)
+ else
+ fun_l4_n254(x)
+ end
+end
+
+def fun_l3_n337(x)
+ if (x < 1)
+ fun_l4_n920(x)
+ else
+ fun_l4_n134(x)
+ end
+end
+
+def fun_l3_n338(x)
+ if (x < 1)
+ fun_l4_n803(x)
+ else
+ fun_l4_n746(x)
+ end
+end
+
+def fun_l3_n339(x)
+ if (x < 1)
+ fun_l4_n924(x)
+ else
+ fun_l4_n878(x)
+ end
+end
+
+def fun_l3_n340(x)
+ if (x < 1)
+ fun_l4_n166(x)
+ else
+ fun_l4_n776(x)
+ end
+end
+
+def fun_l3_n341(x)
+ if (x < 1)
+ fun_l4_n240(x)
+ else
+ fun_l4_n898(x)
+ end
+end
+
+def fun_l3_n342(x)
+ if (x < 1)
+ fun_l4_n810(x)
+ else
+ fun_l4_n423(x)
+ end
+end
+
+def fun_l3_n343(x)
+ if (x < 1)
+ fun_l4_n209(x)
+ else
+ fun_l4_n514(x)
+ end
+end
+
+def fun_l3_n344(x)
+ if (x < 1)
+ fun_l4_n505(x)
+ else
+ fun_l4_n321(x)
+ end
+end
+
+def fun_l3_n345(x)
+ if (x < 1)
+ fun_l4_n88(x)
+ else
+ fun_l4_n39(x)
+ end
+end
+
+def fun_l3_n346(x)
+ if (x < 1)
+ fun_l4_n848(x)
+ else
+ fun_l4_n357(x)
+ end
+end
+
+def fun_l3_n347(x)
+ if (x < 1)
+ fun_l4_n450(x)
+ else
+ fun_l4_n704(x)
+ end
+end
+
+def fun_l3_n348(x)
+ if (x < 1)
+ fun_l4_n881(x)
+ else
+ fun_l4_n916(x)
+ end
+end
+
+def fun_l3_n349(x)
+ if (x < 1)
+ fun_l4_n16(x)
+ else
+ fun_l4_n996(x)
+ end
+end
+
+def fun_l3_n350(x)
+ if (x < 1)
+ fun_l4_n839(x)
+ else
+ fun_l4_n697(x)
+ end
+end
+
+def fun_l3_n351(x)
+ if (x < 1)
+ fun_l4_n177(x)
+ else
+ fun_l4_n859(x)
+ end
+end
+
+def fun_l3_n352(x)
+ if (x < 1)
+ fun_l4_n684(x)
+ else
+ fun_l4_n778(x)
+ end
+end
+
+def fun_l3_n353(x)
+ if (x < 1)
+ fun_l4_n604(x)
+ else
+ fun_l4_n280(x)
+ end
+end
+
+def fun_l3_n354(x)
+ if (x < 1)
+ fun_l4_n366(x)
+ else
+ fun_l4_n576(x)
+ end
+end
+
+def fun_l3_n355(x)
+ if (x < 1)
+ fun_l4_n584(x)
+ else
+ fun_l4_n228(x)
+ end
+end
+
+def fun_l3_n356(x)
+ if (x < 1)
+ fun_l4_n844(x)
+ else
+ fun_l4_n799(x)
+ end
+end
+
+def fun_l3_n357(x)
+ if (x < 1)
+ fun_l4_n489(x)
+ else
+ fun_l4_n905(x)
+ end
+end
+
+def fun_l3_n358(x)
+ if (x < 1)
+ fun_l4_n781(x)
+ else
+ fun_l4_n565(x)
+ end
+end
+
+def fun_l3_n359(x)
+ if (x < 1)
+ fun_l4_n110(x)
+ else
+ fun_l4_n326(x)
+ end
+end
+
+def fun_l3_n360(x)
+ if (x < 1)
+ fun_l4_n915(x)
+ else
+ fun_l4_n489(x)
+ end
+end
+
+def fun_l3_n361(x)
+ if (x < 1)
+ fun_l4_n110(x)
+ else
+ fun_l4_n733(x)
+ end
+end
+
+def fun_l3_n362(x)
+ if (x < 1)
+ fun_l4_n93(x)
+ else
+ fun_l4_n549(x)
+ end
+end
+
+def fun_l3_n363(x)
+ if (x < 1)
+ fun_l4_n270(x)
+ else
+ fun_l4_n883(x)
+ end
+end
+
+def fun_l3_n364(x)
+ if (x < 1)
+ fun_l4_n512(x)
+ else
+ fun_l4_n555(x)
+ end
+end
+
+def fun_l3_n365(x)
+ if (x < 1)
+ fun_l4_n800(x)
+ else
+ fun_l4_n672(x)
+ end
+end
+
+def fun_l3_n366(x)
+ if (x < 1)
+ fun_l4_n535(x)
+ else
+ fun_l4_n320(x)
+ end
+end
+
+def fun_l3_n367(x)
+ if (x < 1)
+ fun_l4_n883(x)
+ else
+ fun_l4_n365(x)
+ end
+end
+
+def fun_l3_n368(x)
+ if (x < 1)
+ fun_l4_n306(x)
+ else
+ fun_l4_n614(x)
+ end
+end
+
+def fun_l3_n369(x)
+ if (x < 1)
+ fun_l4_n914(x)
+ else
+ fun_l4_n20(x)
+ end
+end
+
+def fun_l3_n370(x)
+ if (x < 1)
+ fun_l4_n230(x)
+ else
+ fun_l4_n585(x)
+ end
+end
+
+def fun_l3_n371(x)
+ if (x < 1)
+ fun_l4_n544(x)
+ else
+ fun_l4_n752(x)
+ end
+end
+
+def fun_l3_n372(x)
+ if (x < 1)
+ fun_l4_n984(x)
+ else
+ fun_l4_n738(x)
+ end
+end
+
+def fun_l3_n373(x)
+ if (x < 1)
+ fun_l4_n478(x)
+ else
+ fun_l4_n618(x)
+ end
+end
+
+def fun_l3_n374(x)
+ if (x < 1)
+ fun_l4_n941(x)
+ else
+ fun_l4_n746(x)
+ end
+end
+
+def fun_l3_n375(x)
+ if (x < 1)
+ fun_l4_n121(x)
+ else
+ fun_l4_n798(x)
+ end
+end
+
+def fun_l3_n376(x)
+ if (x < 1)
+ fun_l4_n851(x)
+ else
+ fun_l4_n681(x)
+ end
+end
+
+def fun_l3_n377(x)
+ if (x < 1)
+ fun_l4_n502(x)
+ else
+ fun_l4_n538(x)
+ end
+end
+
+def fun_l3_n378(x)
+ if (x < 1)
+ fun_l4_n432(x)
+ else
+ fun_l4_n226(x)
+ end
+end
+
+def fun_l3_n379(x)
+ if (x < 1)
+ fun_l4_n734(x)
+ else
+ fun_l4_n684(x)
+ end
+end
+
+def fun_l3_n380(x)
+ if (x < 1)
+ fun_l4_n912(x)
+ else
+ fun_l4_n116(x)
+ end
+end
+
+def fun_l3_n381(x)
+ if (x < 1)
+ fun_l4_n291(x)
+ else
+ fun_l4_n464(x)
+ end
+end
+
+def fun_l3_n382(x)
+ if (x < 1)
+ fun_l4_n285(x)
+ else
+ fun_l4_n943(x)
+ end
+end
+
+def fun_l3_n383(x)
+ if (x < 1)
+ fun_l4_n738(x)
+ else
+ fun_l4_n532(x)
+ end
+end
+
+def fun_l3_n384(x)
+ if (x < 1)
+ fun_l4_n503(x)
+ else
+ fun_l4_n724(x)
+ end
+end
+
+def fun_l3_n385(x)
+ if (x < 1)
+ fun_l4_n208(x)
+ else
+ fun_l4_n683(x)
+ end
+end
+
+def fun_l3_n386(x)
+ if (x < 1)
+ fun_l4_n673(x)
+ else
+ fun_l4_n230(x)
+ end
+end
+
+def fun_l3_n387(x)
+ if (x < 1)
+ fun_l4_n921(x)
+ else
+ fun_l4_n800(x)
+ end
+end
+
+def fun_l3_n388(x)
+ if (x < 1)
+ fun_l4_n461(x)
+ else
+ fun_l4_n369(x)
+ end
+end
+
+def fun_l3_n389(x)
+ if (x < 1)
+ fun_l4_n86(x)
+ else
+ fun_l4_n403(x)
+ end
+end
+
+def fun_l3_n390(x)
+ if (x < 1)
+ fun_l4_n883(x)
+ else
+ fun_l4_n92(x)
+ end
+end
+
+def fun_l3_n391(x)
+ if (x < 1)
+ fun_l4_n562(x)
+ else
+ fun_l4_n826(x)
+ end
+end
+
+def fun_l3_n392(x)
+ if (x < 1)
+ fun_l4_n459(x)
+ else
+ fun_l4_n821(x)
+ end
+end
+
+def fun_l3_n393(x)
+ if (x < 1)
+ fun_l4_n774(x)
+ else
+ fun_l4_n376(x)
+ end
+end
+
+def fun_l3_n394(x)
+ if (x < 1)
+ fun_l4_n114(x)
+ else
+ fun_l4_n451(x)
+ end
+end
+
+def fun_l3_n395(x)
+ if (x < 1)
+ fun_l4_n689(x)
+ else
+ fun_l4_n13(x)
+ end
+end
+
+def fun_l3_n396(x)
+ if (x < 1)
+ fun_l4_n929(x)
+ else
+ fun_l4_n777(x)
+ end
+end
+
+def fun_l3_n397(x)
+ if (x < 1)
+ fun_l4_n634(x)
+ else
+ fun_l4_n329(x)
+ end
+end
+
+def fun_l3_n398(x)
+ if (x < 1)
+ fun_l4_n972(x)
+ else
+ fun_l4_n572(x)
+ end
+end
+
+def fun_l3_n399(x)
+ if (x < 1)
+ fun_l4_n231(x)
+ else
+ fun_l4_n14(x)
+ end
+end
+
+def fun_l3_n400(x)
+ if (x < 1)
+ fun_l4_n357(x)
+ else
+ fun_l4_n881(x)
+ end
+end
+
+def fun_l3_n401(x)
+ if (x < 1)
+ fun_l4_n283(x)
+ else
+ fun_l4_n614(x)
+ end
+end
+
+def fun_l3_n402(x)
+ if (x < 1)
+ fun_l4_n634(x)
+ else
+ fun_l4_n653(x)
+ end
+end
+
+def fun_l3_n403(x)
+ if (x < 1)
+ fun_l4_n660(x)
+ else
+ fun_l4_n127(x)
+ end
+end
+
+def fun_l3_n404(x)
+ if (x < 1)
+ fun_l4_n523(x)
+ else
+ fun_l4_n467(x)
+ end
+end
+
+def fun_l3_n405(x)
+ if (x < 1)
+ fun_l4_n593(x)
+ else
+ fun_l4_n78(x)
+ end
+end
+
+def fun_l3_n406(x)
+ if (x < 1)
+ fun_l4_n514(x)
+ else
+ fun_l4_n783(x)
+ end
+end
+
+def fun_l3_n407(x)
+ if (x < 1)
+ fun_l4_n460(x)
+ else
+ fun_l4_n137(x)
+ end
+end
+
+def fun_l3_n408(x)
+ if (x < 1)
+ fun_l4_n3(x)
+ else
+ fun_l4_n224(x)
+ end
+end
+
+def fun_l3_n409(x)
+ if (x < 1)
+ fun_l4_n11(x)
+ else
+ fun_l4_n531(x)
+ end
+end
+
+def fun_l3_n410(x)
+ if (x < 1)
+ fun_l4_n94(x)
+ else
+ fun_l4_n717(x)
+ end
+end
+
+def fun_l3_n411(x)
+ if (x < 1)
+ fun_l4_n729(x)
+ else
+ fun_l4_n526(x)
+ end
+end
+
+def fun_l3_n412(x)
+ if (x < 1)
+ fun_l4_n86(x)
+ else
+ fun_l4_n26(x)
+ end
+end
+
+def fun_l3_n413(x)
+ if (x < 1)
+ fun_l4_n249(x)
+ else
+ fun_l4_n572(x)
+ end
+end
+
+def fun_l3_n414(x)
+ if (x < 1)
+ fun_l4_n578(x)
+ else
+ fun_l4_n512(x)
+ end
+end
+
+def fun_l3_n415(x)
+ if (x < 1)
+ fun_l4_n176(x)
+ else
+ fun_l4_n414(x)
+ end
+end
+
+def fun_l3_n416(x)
+ if (x < 1)
+ fun_l4_n757(x)
+ else
+ fun_l4_n385(x)
+ end
+end
+
+def fun_l3_n417(x)
+ if (x < 1)
+ fun_l4_n249(x)
+ else
+ fun_l4_n180(x)
+ end
+end
+
+def fun_l3_n418(x)
+ if (x < 1)
+ fun_l4_n193(x)
+ else
+ fun_l4_n294(x)
+ end
+end
+
+def fun_l3_n419(x)
+ if (x < 1)
+ fun_l4_n441(x)
+ else
+ fun_l4_n932(x)
+ end
+end
+
+def fun_l3_n420(x)
+ if (x < 1)
+ fun_l4_n492(x)
+ else
+ fun_l4_n239(x)
+ end
+end
+
+def fun_l3_n421(x)
+ if (x < 1)
+ fun_l4_n49(x)
+ else
+ fun_l4_n738(x)
+ end
+end
+
+def fun_l3_n422(x)
+ if (x < 1)
+ fun_l4_n546(x)
+ else
+ fun_l4_n285(x)
+ end
+end
+
+def fun_l3_n423(x)
+ if (x < 1)
+ fun_l4_n687(x)
+ else
+ fun_l4_n973(x)
+ end
+end
+
+def fun_l3_n424(x)
+ if (x < 1)
+ fun_l4_n876(x)
+ else
+ fun_l4_n591(x)
+ end
+end
+
+def fun_l3_n425(x)
+ if (x < 1)
+ fun_l4_n626(x)
+ else
+ fun_l4_n739(x)
+ end
+end
+
+def fun_l3_n426(x)
+ if (x < 1)
+ fun_l4_n439(x)
+ else
+ fun_l4_n709(x)
+ end
+end
+
+def fun_l3_n427(x)
+ if (x < 1)
+ fun_l4_n710(x)
+ else
+ fun_l4_n305(x)
+ end
+end
+
+def fun_l3_n428(x)
+ if (x < 1)
+ fun_l4_n61(x)
+ else
+ fun_l4_n520(x)
+ end
+end
+
+def fun_l3_n429(x)
+ if (x < 1)
+ fun_l4_n172(x)
+ else
+ fun_l4_n12(x)
+ end
+end
+
+def fun_l3_n430(x)
+ if (x < 1)
+ fun_l4_n432(x)
+ else
+ fun_l4_n174(x)
+ end
+end
+
+def fun_l3_n431(x)
+ if (x < 1)
+ fun_l4_n194(x)
+ else
+ fun_l4_n673(x)
+ end
+end
+
+def fun_l3_n432(x)
+ if (x < 1)
+ fun_l4_n952(x)
+ else
+ fun_l4_n798(x)
+ end
+end
+
+def fun_l3_n433(x)
+ if (x < 1)
+ fun_l4_n915(x)
+ else
+ fun_l4_n263(x)
+ end
+end
+
+def fun_l3_n434(x)
+ if (x < 1)
+ fun_l4_n735(x)
+ else
+ fun_l4_n882(x)
+ end
+end
+
+def fun_l3_n435(x)
+ if (x < 1)
+ fun_l4_n499(x)
+ else
+ fun_l4_n947(x)
+ end
+end
+
+def fun_l3_n436(x)
+ if (x < 1)
+ fun_l4_n744(x)
+ else
+ fun_l4_n187(x)
+ end
+end
+
+def fun_l3_n437(x)
+ if (x < 1)
+ fun_l4_n244(x)
+ else
+ fun_l4_n366(x)
+ end
+end
+
+def fun_l3_n438(x)
+ if (x < 1)
+ fun_l4_n228(x)
+ else
+ fun_l4_n866(x)
+ end
+end
+
+def fun_l3_n439(x)
+ if (x < 1)
+ fun_l4_n617(x)
+ else
+ fun_l4_n924(x)
+ end
+end
+
+def fun_l3_n440(x)
+ if (x < 1)
+ fun_l4_n302(x)
+ else
+ fun_l4_n691(x)
+ end
+end
+
+def fun_l3_n441(x)
+ if (x < 1)
+ fun_l4_n559(x)
+ else
+ fun_l4_n758(x)
+ end
+end
+
+def fun_l3_n442(x)
+ if (x < 1)
+ fun_l4_n412(x)
+ else
+ fun_l4_n544(x)
+ end
+end
+
+def fun_l3_n443(x)
+ if (x < 1)
+ fun_l4_n130(x)
+ else
+ fun_l4_n764(x)
+ end
+end
+
+def fun_l3_n444(x)
+ if (x < 1)
+ fun_l4_n135(x)
+ else
+ fun_l4_n65(x)
+ end
+end
+
+def fun_l3_n445(x)
+ if (x < 1)
+ fun_l4_n224(x)
+ else
+ fun_l4_n148(x)
+ end
+end
+
+def fun_l3_n446(x)
+ if (x < 1)
+ fun_l4_n238(x)
+ else
+ fun_l4_n808(x)
+ end
+end
+
+def fun_l3_n447(x)
+ if (x < 1)
+ fun_l4_n832(x)
+ else
+ fun_l4_n460(x)
+ end
+end
+
+def fun_l3_n448(x)
+ if (x < 1)
+ fun_l4_n897(x)
+ else
+ fun_l4_n817(x)
+ end
+end
+
+def fun_l3_n449(x)
+ if (x < 1)
+ fun_l4_n587(x)
+ else
+ fun_l4_n926(x)
+ end
+end
+
+def fun_l3_n450(x)
+ if (x < 1)
+ fun_l4_n575(x)
+ else
+ fun_l4_n274(x)
+ end
+end
+
+def fun_l3_n451(x)
+ if (x < 1)
+ fun_l4_n42(x)
+ else
+ fun_l4_n714(x)
+ end
+end
+
+def fun_l3_n452(x)
+ if (x < 1)
+ fun_l4_n101(x)
+ else
+ fun_l4_n470(x)
+ end
+end
+
+def fun_l3_n453(x)
+ if (x < 1)
+ fun_l4_n906(x)
+ else
+ fun_l4_n724(x)
+ end
+end
+
+def fun_l3_n454(x)
+ if (x < 1)
+ fun_l4_n682(x)
+ else
+ fun_l4_n709(x)
+ end
+end
+
+def fun_l3_n455(x)
+ if (x < 1)
+ fun_l4_n929(x)
+ else
+ fun_l4_n274(x)
+ end
+end
+
+def fun_l3_n456(x)
+ if (x < 1)
+ fun_l4_n10(x)
+ else
+ fun_l4_n101(x)
+ end
+end
+
+def fun_l3_n457(x)
+ if (x < 1)
+ fun_l4_n825(x)
+ else
+ fun_l4_n632(x)
+ end
+end
+
+def fun_l3_n458(x)
+ if (x < 1)
+ fun_l4_n2(x)
+ else
+ fun_l4_n723(x)
+ end
+end
+
+def fun_l3_n459(x)
+ if (x < 1)
+ fun_l4_n998(x)
+ else
+ fun_l4_n546(x)
+ end
+end
+
+def fun_l3_n460(x)
+ if (x < 1)
+ fun_l4_n483(x)
+ else
+ fun_l4_n445(x)
+ end
+end
+
+def fun_l3_n461(x)
+ if (x < 1)
+ fun_l4_n896(x)
+ else
+ fun_l4_n993(x)
+ end
+end
+
+def fun_l3_n462(x)
+ if (x < 1)
+ fun_l4_n710(x)
+ else
+ fun_l4_n529(x)
+ end
+end
+
+def fun_l3_n463(x)
+ if (x < 1)
+ fun_l4_n913(x)
+ else
+ fun_l4_n65(x)
+ end
+end
+
+def fun_l3_n464(x)
+ if (x < 1)
+ fun_l4_n712(x)
+ else
+ fun_l4_n412(x)
+ end
+end
+
+def fun_l3_n465(x)
+ if (x < 1)
+ fun_l4_n296(x)
+ else
+ fun_l4_n37(x)
+ end
+end
+
+def fun_l3_n466(x)
+ if (x < 1)
+ fun_l4_n241(x)
+ else
+ fun_l4_n649(x)
+ end
+end
+
+def fun_l3_n467(x)
+ if (x < 1)
+ fun_l4_n296(x)
+ else
+ fun_l4_n80(x)
+ end
+end
+
+def fun_l3_n468(x)
+ if (x < 1)
+ fun_l4_n270(x)
+ else
+ fun_l4_n192(x)
+ end
+end
+
+def fun_l3_n469(x)
+ if (x < 1)
+ fun_l4_n655(x)
+ else
+ fun_l4_n605(x)
+ end
+end
+
+def fun_l3_n470(x)
+ if (x < 1)
+ fun_l4_n180(x)
+ else
+ fun_l4_n807(x)
+ end
+end
+
+def fun_l3_n471(x)
+ if (x < 1)
+ fun_l4_n915(x)
+ else
+ fun_l4_n902(x)
+ end
+end
+
+def fun_l3_n472(x)
+ if (x < 1)
+ fun_l4_n527(x)
+ else
+ fun_l4_n638(x)
+ end
+end
+
+def fun_l3_n473(x)
+ if (x < 1)
+ fun_l4_n775(x)
+ else
+ fun_l4_n572(x)
+ end
+end
+
+def fun_l3_n474(x)
+ if (x < 1)
+ fun_l4_n856(x)
+ else
+ fun_l4_n182(x)
+ end
+end
+
+def fun_l3_n475(x)
+ if (x < 1)
+ fun_l4_n434(x)
+ else
+ fun_l4_n232(x)
+ end
+end
+
+def fun_l3_n476(x)
+ if (x < 1)
+ fun_l4_n208(x)
+ else
+ fun_l4_n37(x)
+ end
+end
+
+def fun_l3_n477(x)
+ if (x < 1)
+ fun_l4_n146(x)
+ else
+ fun_l4_n764(x)
+ end
+end
+
+def fun_l3_n478(x)
+ if (x < 1)
+ fun_l4_n806(x)
+ else
+ fun_l4_n148(x)
+ end
+end
+
+def fun_l3_n479(x)
+ if (x < 1)
+ fun_l4_n46(x)
+ else
+ fun_l4_n488(x)
+ end
+end
+
+def fun_l3_n480(x)
+ if (x < 1)
+ fun_l4_n637(x)
+ else
+ fun_l4_n48(x)
+ end
+end
+
+def fun_l3_n481(x)
+ if (x < 1)
+ fun_l4_n496(x)
+ else
+ fun_l4_n891(x)
+ end
+end
+
+def fun_l3_n482(x)
+ if (x < 1)
+ fun_l4_n282(x)
+ else
+ fun_l4_n736(x)
+ end
+end
+
+def fun_l3_n483(x)
+ if (x < 1)
+ fun_l4_n377(x)
+ else
+ fun_l4_n603(x)
+ end
+end
+
+def fun_l3_n484(x)
+ if (x < 1)
+ fun_l4_n689(x)
+ else
+ fun_l4_n201(x)
+ end
+end
+
+def fun_l3_n485(x)
+ if (x < 1)
+ fun_l4_n495(x)
+ else
+ fun_l4_n721(x)
+ end
+end
+
+def fun_l3_n486(x)
+ if (x < 1)
+ fun_l4_n128(x)
+ else
+ fun_l4_n400(x)
+ end
+end
+
+def fun_l3_n487(x)
+ if (x < 1)
+ fun_l4_n993(x)
+ else
+ fun_l4_n53(x)
+ end
+end
+
+def fun_l3_n488(x)
+ if (x < 1)
+ fun_l4_n913(x)
+ else
+ fun_l4_n814(x)
+ end
+end
+
+def fun_l3_n489(x)
+ if (x < 1)
+ fun_l4_n816(x)
+ else
+ fun_l4_n196(x)
+ end
+end
+
+def fun_l3_n490(x)
+ if (x < 1)
+ fun_l4_n754(x)
+ else
+ fun_l4_n451(x)
+ end
+end
+
+def fun_l3_n491(x)
+ if (x < 1)
+ fun_l4_n57(x)
+ else
+ fun_l4_n597(x)
+ end
+end
+
+def fun_l3_n492(x)
+ if (x < 1)
+ fun_l4_n539(x)
+ else
+ fun_l4_n893(x)
+ end
+end
+
+def fun_l3_n493(x)
+ if (x < 1)
+ fun_l4_n542(x)
+ else
+ fun_l4_n956(x)
+ end
+end
+
+def fun_l3_n494(x)
+ if (x < 1)
+ fun_l4_n479(x)
+ else
+ fun_l4_n448(x)
+ end
+end
+
+def fun_l3_n495(x)
+ if (x < 1)
+ fun_l4_n263(x)
+ else
+ fun_l4_n912(x)
+ end
+end
+
+def fun_l3_n496(x)
+ if (x < 1)
+ fun_l4_n463(x)
+ else
+ fun_l4_n112(x)
+ end
+end
+
+def fun_l3_n497(x)
+ if (x < 1)
+ fun_l4_n806(x)
+ else
+ fun_l4_n486(x)
+ end
+end
+
+def fun_l3_n498(x)
+ if (x < 1)
+ fun_l4_n155(x)
+ else
+ fun_l4_n298(x)
+ end
+end
+
+def fun_l3_n499(x)
+ if (x < 1)
+ fun_l4_n538(x)
+ else
+ fun_l4_n908(x)
+ end
+end
+
+def fun_l3_n500(x)
+ if (x < 1)
+ fun_l4_n769(x)
+ else
+ fun_l4_n681(x)
+ end
+end
+
+def fun_l3_n501(x)
+ if (x < 1)
+ fun_l4_n544(x)
+ else
+ fun_l4_n749(x)
+ end
+end
+
+def fun_l3_n502(x)
+ if (x < 1)
+ fun_l4_n505(x)
+ else
+ fun_l4_n66(x)
+ end
+end
+
+def fun_l3_n503(x)
+ if (x < 1)
+ fun_l4_n900(x)
+ else
+ fun_l4_n917(x)
+ end
+end
+
+def fun_l3_n504(x)
+ if (x < 1)
+ fun_l4_n982(x)
+ else
+ fun_l4_n707(x)
+ end
+end
+
+def fun_l3_n505(x)
+ if (x < 1)
+ fun_l4_n102(x)
+ else
+ fun_l4_n564(x)
+ end
+end
+
+def fun_l3_n506(x)
+ if (x < 1)
+ fun_l4_n332(x)
+ else
+ fun_l4_n367(x)
+ end
+end
+
+def fun_l3_n507(x)
+ if (x < 1)
+ fun_l4_n969(x)
+ else
+ fun_l4_n354(x)
+ end
+end
+
+def fun_l3_n508(x)
+ if (x < 1)
+ fun_l4_n405(x)
+ else
+ fun_l4_n485(x)
+ end
+end
+
+def fun_l3_n509(x)
+ if (x < 1)
+ fun_l4_n477(x)
+ else
+ fun_l4_n629(x)
+ end
+end
+
+def fun_l3_n510(x)
+ if (x < 1)
+ fun_l4_n753(x)
+ else
+ fun_l4_n78(x)
+ end
+end
+
+def fun_l3_n511(x)
+ if (x < 1)
+ fun_l4_n221(x)
+ else
+ fun_l4_n637(x)
+ end
+end
+
+def fun_l3_n512(x)
+ if (x < 1)
+ fun_l4_n540(x)
+ else
+ fun_l4_n267(x)
+ end
+end
+
+def fun_l3_n513(x)
+ if (x < 1)
+ fun_l4_n750(x)
+ else
+ fun_l4_n626(x)
+ end
+end
+
+def fun_l3_n514(x)
+ if (x < 1)
+ fun_l4_n160(x)
+ else
+ fun_l4_n32(x)
+ end
+end
+
+def fun_l3_n515(x)
+ if (x < 1)
+ fun_l4_n914(x)
+ else
+ fun_l4_n967(x)
+ end
+end
+
+def fun_l3_n516(x)
+ if (x < 1)
+ fun_l4_n380(x)
+ else
+ fun_l4_n83(x)
+ end
+end
+
+def fun_l3_n517(x)
+ if (x < 1)
+ fun_l4_n175(x)
+ else
+ fun_l4_n830(x)
+ end
+end
+
+def fun_l3_n518(x)
+ if (x < 1)
+ fun_l4_n579(x)
+ else
+ fun_l4_n773(x)
+ end
+end
+
+def fun_l3_n519(x)
+ if (x < 1)
+ fun_l4_n707(x)
+ else
+ fun_l4_n690(x)
+ end
+end
+
+def fun_l3_n520(x)
+ if (x < 1)
+ fun_l4_n587(x)
+ else
+ fun_l4_n754(x)
+ end
+end
+
+def fun_l3_n521(x)
+ if (x < 1)
+ fun_l4_n922(x)
+ else
+ fun_l4_n156(x)
+ end
+end
+
+def fun_l3_n522(x)
+ if (x < 1)
+ fun_l4_n299(x)
+ else
+ fun_l4_n937(x)
+ end
+end
+
+def fun_l3_n523(x)
+ if (x < 1)
+ fun_l4_n996(x)
+ else
+ fun_l4_n786(x)
+ end
+end
+
+def fun_l3_n524(x)
+ if (x < 1)
+ fun_l4_n988(x)
+ else
+ fun_l4_n930(x)
+ end
+end
+
+def fun_l3_n525(x)
+ if (x < 1)
+ fun_l4_n475(x)
+ else
+ fun_l4_n43(x)
+ end
+end
+
+def fun_l3_n526(x)
+ if (x < 1)
+ fun_l4_n367(x)
+ else
+ fun_l4_n167(x)
+ end
+end
+
+def fun_l3_n527(x)
+ if (x < 1)
+ fun_l4_n31(x)
+ else
+ fun_l4_n394(x)
+ end
+end
+
+def fun_l3_n528(x)
+ if (x < 1)
+ fun_l4_n92(x)
+ else
+ fun_l4_n304(x)
+ end
+end
+
+def fun_l3_n529(x)
+ if (x < 1)
+ fun_l4_n369(x)
+ else
+ fun_l4_n458(x)
+ end
+end
+
+def fun_l3_n530(x)
+ if (x < 1)
+ fun_l4_n475(x)
+ else
+ fun_l4_n8(x)
+ end
+end
+
+def fun_l3_n531(x)
+ if (x < 1)
+ fun_l4_n678(x)
+ else
+ fun_l4_n970(x)
+ end
+end
+
+def fun_l3_n532(x)
+ if (x < 1)
+ fun_l4_n349(x)
+ else
+ fun_l4_n853(x)
+ end
+end
+
+def fun_l3_n533(x)
+ if (x < 1)
+ fun_l4_n918(x)
+ else
+ fun_l4_n820(x)
+ end
+end
+
+def fun_l3_n534(x)
+ if (x < 1)
+ fun_l4_n369(x)
+ else
+ fun_l4_n445(x)
+ end
+end
+
+def fun_l3_n535(x)
+ if (x < 1)
+ fun_l4_n437(x)
+ else
+ fun_l4_n930(x)
+ end
+end
+
+def fun_l3_n536(x)
+ if (x < 1)
+ fun_l4_n143(x)
+ else
+ fun_l4_n986(x)
+ end
+end
+
+def fun_l3_n537(x)
+ if (x < 1)
+ fun_l4_n603(x)
+ else
+ fun_l4_n818(x)
+ end
+end
+
+def fun_l3_n538(x)
+ if (x < 1)
+ fun_l4_n14(x)
+ else
+ fun_l4_n994(x)
+ end
+end
+
+def fun_l3_n539(x)
+ if (x < 1)
+ fun_l4_n650(x)
+ else
+ fun_l4_n115(x)
+ end
+end
+
+def fun_l3_n540(x)
+ if (x < 1)
+ fun_l4_n74(x)
+ else
+ fun_l4_n559(x)
+ end
+end
+
+def fun_l3_n541(x)
+ if (x < 1)
+ fun_l4_n601(x)
+ else
+ fun_l4_n756(x)
+ end
+end
+
+def fun_l3_n542(x)
+ if (x < 1)
+ fun_l4_n733(x)
+ else
+ fun_l4_n274(x)
+ end
+end
+
+def fun_l3_n543(x)
+ if (x < 1)
+ fun_l4_n819(x)
+ else
+ fun_l4_n97(x)
+ end
+end
+
+def fun_l3_n544(x)
+ if (x < 1)
+ fun_l4_n949(x)
+ else
+ fun_l4_n868(x)
+ end
+end
+
+def fun_l3_n545(x)
+ if (x < 1)
+ fun_l4_n346(x)
+ else
+ fun_l4_n0(x)
+ end
+end
+
+def fun_l3_n546(x)
+ if (x < 1)
+ fun_l4_n820(x)
+ else
+ fun_l4_n188(x)
+ end
+end
+
+def fun_l3_n547(x)
+ if (x < 1)
+ fun_l4_n403(x)
+ else
+ fun_l4_n670(x)
+ end
+end
+
+def fun_l3_n548(x)
+ if (x < 1)
+ fun_l4_n449(x)
+ else
+ fun_l4_n96(x)
+ end
+end
+
+def fun_l3_n549(x)
+ if (x < 1)
+ fun_l4_n585(x)
+ else
+ fun_l4_n388(x)
+ end
+end
+
+def fun_l3_n550(x)
+ if (x < 1)
+ fun_l4_n963(x)
+ else
+ fun_l4_n979(x)
+ end
+end
+
+def fun_l3_n551(x)
+ if (x < 1)
+ fun_l4_n892(x)
+ else
+ fun_l4_n583(x)
+ end
+end
+
+def fun_l3_n552(x)
+ if (x < 1)
+ fun_l4_n846(x)
+ else
+ fun_l4_n508(x)
+ end
+end
+
+def fun_l3_n553(x)
+ if (x < 1)
+ fun_l4_n160(x)
+ else
+ fun_l4_n428(x)
+ end
+end
+
+def fun_l3_n554(x)
+ if (x < 1)
+ fun_l4_n538(x)
+ else
+ fun_l4_n641(x)
+ end
+end
+
+def fun_l3_n555(x)
+ if (x < 1)
+ fun_l4_n523(x)
+ else
+ fun_l4_n697(x)
+ end
+end
+
+def fun_l3_n556(x)
+ if (x < 1)
+ fun_l4_n212(x)
+ else
+ fun_l4_n0(x)
+ end
+end
+
+def fun_l3_n557(x)
+ if (x < 1)
+ fun_l4_n255(x)
+ else
+ fun_l4_n860(x)
+ end
+end
+
+def fun_l3_n558(x)
+ if (x < 1)
+ fun_l4_n807(x)
+ else
+ fun_l4_n865(x)
+ end
+end
+
+def fun_l3_n559(x)
+ if (x < 1)
+ fun_l4_n735(x)
+ else
+ fun_l4_n352(x)
+ end
+end
+
+def fun_l3_n560(x)
+ if (x < 1)
+ fun_l4_n327(x)
+ else
+ fun_l4_n739(x)
+ end
+end
+
+def fun_l3_n561(x)
+ if (x < 1)
+ fun_l4_n637(x)
+ else
+ fun_l4_n628(x)
+ end
+end
+
+def fun_l3_n562(x)
+ if (x < 1)
+ fun_l4_n281(x)
+ else
+ fun_l4_n394(x)
+ end
+end
+
+def fun_l3_n563(x)
+ if (x < 1)
+ fun_l4_n440(x)
+ else
+ fun_l4_n179(x)
+ end
+end
+
+def fun_l3_n564(x)
+ if (x < 1)
+ fun_l4_n893(x)
+ else
+ fun_l4_n396(x)
+ end
+end
+
+def fun_l3_n565(x)
+ if (x < 1)
+ fun_l4_n94(x)
+ else
+ fun_l4_n134(x)
+ end
+end
+
+def fun_l3_n566(x)
+ if (x < 1)
+ fun_l4_n968(x)
+ else
+ fun_l4_n444(x)
+ end
+end
+
+def fun_l3_n567(x)
+ if (x < 1)
+ fun_l4_n85(x)
+ else
+ fun_l4_n281(x)
+ end
+end
+
+def fun_l3_n568(x)
+ if (x < 1)
+ fun_l4_n164(x)
+ else
+ fun_l4_n229(x)
+ end
+end
+
+def fun_l3_n569(x)
+ if (x < 1)
+ fun_l4_n594(x)
+ else
+ fun_l4_n756(x)
+ end
+end
+
+def fun_l3_n570(x)
+ if (x < 1)
+ fun_l4_n77(x)
+ else
+ fun_l4_n370(x)
+ end
+end
+
+def fun_l3_n571(x)
+ if (x < 1)
+ fun_l4_n724(x)
+ else
+ fun_l4_n965(x)
+ end
+end
+
+def fun_l3_n572(x)
+ if (x < 1)
+ fun_l4_n394(x)
+ else
+ fun_l4_n595(x)
+ end
+end
+
+def fun_l3_n573(x)
+ if (x < 1)
+ fun_l4_n54(x)
+ else
+ fun_l4_n41(x)
+ end
+end
+
+def fun_l3_n574(x)
+ if (x < 1)
+ fun_l4_n951(x)
+ else
+ fun_l4_n414(x)
+ end
+end
+
+def fun_l3_n575(x)
+ if (x < 1)
+ fun_l4_n297(x)
+ else
+ fun_l4_n126(x)
+ end
+end
+
+def fun_l3_n576(x)
+ if (x < 1)
+ fun_l4_n538(x)
+ else
+ fun_l4_n276(x)
+ end
+end
+
+def fun_l3_n577(x)
+ if (x < 1)
+ fun_l4_n882(x)
+ else
+ fun_l4_n152(x)
+ end
+end
+
+def fun_l3_n578(x)
+ if (x < 1)
+ fun_l4_n950(x)
+ else
+ fun_l4_n822(x)
+ end
+end
+
+def fun_l3_n579(x)
+ if (x < 1)
+ fun_l4_n484(x)
+ else
+ fun_l4_n99(x)
+ end
+end
+
+def fun_l3_n580(x)
+ if (x < 1)
+ fun_l4_n160(x)
+ else
+ fun_l4_n98(x)
+ end
+end
+
+def fun_l3_n581(x)
+ if (x < 1)
+ fun_l4_n10(x)
+ else
+ fun_l4_n537(x)
+ end
+end
+
+def fun_l3_n582(x)
+ if (x < 1)
+ fun_l4_n419(x)
+ else
+ fun_l4_n285(x)
+ end
+end
+
+def fun_l3_n583(x)
+ if (x < 1)
+ fun_l4_n330(x)
+ else
+ fun_l4_n732(x)
+ end
+end
+
+def fun_l3_n584(x)
+ if (x < 1)
+ fun_l4_n64(x)
+ else
+ fun_l4_n461(x)
+ end
+end
+
+def fun_l3_n585(x)
+ if (x < 1)
+ fun_l4_n326(x)
+ else
+ fun_l4_n134(x)
+ end
+end
+
+def fun_l3_n586(x)
+ if (x < 1)
+ fun_l4_n423(x)
+ else
+ fun_l4_n945(x)
+ end
+end
+
+def fun_l3_n587(x)
+ if (x < 1)
+ fun_l4_n192(x)
+ else
+ fun_l4_n459(x)
+ end
+end
+
+def fun_l3_n588(x)
+ if (x < 1)
+ fun_l4_n292(x)
+ else
+ fun_l4_n697(x)
+ end
+end
+
+def fun_l3_n589(x)
+ if (x < 1)
+ fun_l4_n612(x)
+ else
+ fun_l4_n902(x)
+ end
+end
+
+def fun_l3_n590(x)
+ if (x < 1)
+ fun_l4_n842(x)
+ else
+ fun_l4_n300(x)
+ end
+end
+
+def fun_l3_n591(x)
+ if (x < 1)
+ fun_l4_n265(x)
+ else
+ fun_l4_n906(x)
+ end
+end
+
+def fun_l3_n592(x)
+ if (x < 1)
+ fun_l4_n82(x)
+ else
+ fun_l4_n417(x)
+ end
+end
+
+def fun_l3_n593(x)
+ if (x < 1)
+ fun_l4_n896(x)
+ else
+ fun_l4_n794(x)
+ end
+end
+
+def fun_l3_n594(x)
+ if (x < 1)
+ fun_l4_n760(x)
+ else
+ fun_l4_n83(x)
+ end
+end
+
+def fun_l3_n595(x)
+ if (x < 1)
+ fun_l4_n750(x)
+ else
+ fun_l4_n778(x)
+ end
+end
+
+def fun_l3_n596(x)
+ if (x < 1)
+ fun_l4_n655(x)
+ else
+ fun_l4_n8(x)
+ end
+end
+
+def fun_l3_n597(x)
+ if (x < 1)
+ fun_l4_n810(x)
+ else
+ fun_l4_n824(x)
+ end
+end
+
+def fun_l3_n598(x)
+ if (x < 1)
+ fun_l4_n904(x)
+ else
+ fun_l4_n921(x)
+ end
+end
+
+def fun_l3_n599(x)
+ if (x < 1)
+ fun_l4_n16(x)
+ else
+ fun_l4_n96(x)
+ end
+end
+
+def fun_l3_n600(x)
+ if (x < 1)
+ fun_l4_n879(x)
+ else
+ fun_l4_n757(x)
+ end
+end
+
+def fun_l3_n601(x)
+ if (x < 1)
+ fun_l4_n840(x)
+ else
+ fun_l4_n62(x)
+ end
+end
+
+def fun_l3_n602(x)
+ if (x < 1)
+ fun_l4_n547(x)
+ else
+ fun_l4_n45(x)
+ end
+end
+
+def fun_l3_n603(x)
+ if (x < 1)
+ fun_l4_n978(x)
+ else
+ fun_l4_n646(x)
+ end
+end
+
+def fun_l3_n604(x)
+ if (x < 1)
+ fun_l4_n100(x)
+ else
+ fun_l4_n654(x)
+ end
+end
+
+def fun_l3_n605(x)
+ if (x < 1)
+ fun_l4_n257(x)
+ else
+ fun_l4_n465(x)
+ end
+end
+
+def fun_l3_n606(x)
+ if (x < 1)
+ fun_l4_n427(x)
+ else
+ fun_l4_n489(x)
+ end
+end
+
+def fun_l3_n607(x)
+ if (x < 1)
+ fun_l4_n465(x)
+ else
+ fun_l4_n48(x)
+ end
+end
+
+def fun_l3_n608(x)
+ if (x < 1)
+ fun_l4_n571(x)
+ else
+ fun_l4_n332(x)
+ end
+end
+
+def fun_l3_n609(x)
+ if (x < 1)
+ fun_l4_n813(x)
+ else
+ fun_l4_n462(x)
+ end
+end
+
+def fun_l3_n610(x)
+ if (x < 1)
+ fun_l4_n931(x)
+ else
+ fun_l4_n913(x)
+ end
+end
+
+def fun_l3_n611(x)
+ if (x < 1)
+ fun_l4_n20(x)
+ else
+ fun_l4_n933(x)
+ end
+end
+
+def fun_l3_n612(x)
+ if (x < 1)
+ fun_l4_n913(x)
+ else
+ fun_l4_n787(x)
+ end
+end
+
+def fun_l3_n613(x)
+ if (x < 1)
+ fun_l4_n523(x)
+ else
+ fun_l4_n735(x)
+ end
+end
+
+def fun_l3_n614(x)
+ if (x < 1)
+ fun_l4_n315(x)
+ else
+ fun_l4_n913(x)
+ end
+end
+
+def fun_l3_n615(x)
+ if (x < 1)
+ fun_l4_n308(x)
+ else
+ fun_l4_n865(x)
+ end
+end
+
+def fun_l3_n616(x)
+ if (x < 1)
+ fun_l4_n847(x)
+ else
+ fun_l4_n506(x)
+ end
+end
+
+def fun_l3_n617(x)
+ if (x < 1)
+ fun_l4_n387(x)
+ else
+ fun_l4_n551(x)
+ end
+end
+
+def fun_l3_n618(x)
+ if (x < 1)
+ fun_l4_n276(x)
+ else
+ fun_l4_n991(x)
+ end
+end
+
+def fun_l3_n619(x)
+ if (x < 1)
+ fun_l4_n524(x)
+ else
+ fun_l4_n202(x)
+ end
+end
+
+def fun_l3_n620(x)
+ if (x < 1)
+ fun_l4_n836(x)
+ else
+ fun_l4_n548(x)
+ end
+end
+
+def fun_l3_n621(x)
+ if (x < 1)
+ fun_l4_n76(x)
+ else
+ fun_l4_n5(x)
+ end
+end
+
+def fun_l3_n622(x)
+ if (x < 1)
+ fun_l4_n223(x)
+ else
+ fun_l4_n438(x)
+ end
+end
+
+def fun_l3_n623(x)
+ if (x < 1)
+ fun_l4_n31(x)
+ else
+ fun_l4_n590(x)
+ end
+end
+
+def fun_l3_n624(x)
+ if (x < 1)
+ fun_l4_n609(x)
+ else
+ fun_l4_n513(x)
+ end
+end
+
+def fun_l3_n625(x)
+ if (x < 1)
+ fun_l4_n966(x)
+ else
+ fun_l4_n278(x)
+ end
+end
+
+def fun_l3_n626(x)
+ if (x < 1)
+ fun_l4_n82(x)
+ else
+ fun_l4_n100(x)
+ end
+end
+
+def fun_l3_n627(x)
+ if (x < 1)
+ fun_l4_n312(x)
+ else
+ fun_l4_n746(x)
+ end
+end
+
+def fun_l3_n628(x)
+ if (x < 1)
+ fun_l4_n682(x)
+ else
+ fun_l4_n791(x)
+ end
+end
+
+def fun_l3_n629(x)
+ if (x < 1)
+ fun_l4_n166(x)
+ else
+ fun_l4_n678(x)
+ end
+end
+
+def fun_l3_n630(x)
+ if (x < 1)
+ fun_l4_n507(x)
+ else
+ fun_l4_n778(x)
+ end
+end
+
+def fun_l3_n631(x)
+ if (x < 1)
+ fun_l4_n97(x)
+ else
+ fun_l4_n13(x)
+ end
+end
+
+def fun_l3_n632(x)
+ if (x < 1)
+ fun_l4_n976(x)
+ else
+ fun_l4_n794(x)
+ end
+end
+
+def fun_l3_n633(x)
+ if (x < 1)
+ fun_l4_n994(x)
+ else
+ fun_l4_n743(x)
+ end
+end
+
+def fun_l3_n634(x)
+ if (x < 1)
+ fun_l4_n212(x)
+ else
+ fun_l4_n754(x)
+ end
+end
+
+def fun_l3_n635(x)
+ if (x < 1)
+ fun_l4_n602(x)
+ else
+ fun_l4_n997(x)
+ end
+end
+
+def fun_l3_n636(x)
+ if (x < 1)
+ fun_l4_n282(x)
+ else
+ fun_l4_n133(x)
+ end
+end
+
+def fun_l3_n637(x)
+ if (x < 1)
+ fun_l4_n413(x)
+ else
+ fun_l4_n952(x)
+ end
+end
+
+def fun_l3_n638(x)
+ if (x < 1)
+ fun_l4_n843(x)
+ else
+ fun_l4_n783(x)
+ end
+end
+
+def fun_l3_n639(x)
+ if (x < 1)
+ fun_l4_n946(x)
+ else
+ fun_l4_n833(x)
+ end
+end
+
+def fun_l3_n640(x)
+ if (x < 1)
+ fun_l4_n384(x)
+ else
+ fun_l4_n444(x)
+ end
+end
+
+def fun_l3_n641(x)
+ if (x < 1)
+ fun_l4_n699(x)
+ else
+ fun_l4_n26(x)
+ end
+end
+
+def fun_l3_n642(x)
+ if (x < 1)
+ fun_l4_n96(x)
+ else
+ fun_l4_n623(x)
+ end
+end
+
+def fun_l3_n643(x)
+ if (x < 1)
+ fun_l4_n928(x)
+ else
+ fun_l4_n8(x)
+ end
+end
+
+def fun_l3_n644(x)
+ if (x < 1)
+ fun_l4_n804(x)
+ else
+ fun_l4_n618(x)
+ end
+end
+
+def fun_l3_n645(x)
+ if (x < 1)
+ fun_l4_n513(x)
+ else
+ fun_l4_n214(x)
+ end
+end
+
+def fun_l3_n646(x)
+ if (x < 1)
+ fun_l4_n605(x)
+ else
+ fun_l4_n920(x)
+ end
+end
+
+def fun_l3_n647(x)
+ if (x < 1)
+ fun_l4_n774(x)
+ else
+ fun_l4_n297(x)
+ end
+end
+
+def fun_l3_n648(x)
+ if (x < 1)
+ fun_l4_n871(x)
+ else
+ fun_l4_n75(x)
+ end
+end
+
+def fun_l3_n649(x)
+ if (x < 1)
+ fun_l4_n196(x)
+ else
+ fun_l4_n277(x)
+ end
+end
+
+def fun_l3_n650(x)
+ if (x < 1)
+ fun_l4_n25(x)
+ else
+ fun_l4_n681(x)
+ end
+end
+
+def fun_l3_n651(x)
+ if (x < 1)
+ fun_l4_n603(x)
+ else
+ fun_l4_n46(x)
+ end
+end
+
+def fun_l3_n652(x)
+ if (x < 1)
+ fun_l4_n623(x)
+ else
+ fun_l4_n604(x)
+ end
+end
+
+def fun_l3_n653(x)
+ if (x < 1)
+ fun_l4_n854(x)
+ else
+ fun_l4_n955(x)
+ end
+end
+
+def fun_l3_n654(x)
+ if (x < 1)
+ fun_l4_n667(x)
+ else
+ fun_l4_n988(x)
+ end
+end
+
+def fun_l3_n655(x)
+ if (x < 1)
+ fun_l4_n263(x)
+ else
+ fun_l4_n831(x)
+ end
+end
+
+def fun_l3_n656(x)
+ if (x < 1)
+ fun_l4_n591(x)
+ else
+ fun_l4_n593(x)
+ end
+end
+
+def fun_l3_n657(x)
+ if (x < 1)
+ fun_l4_n308(x)
+ else
+ fun_l4_n547(x)
+ end
+end
+
+def fun_l3_n658(x)
+ if (x < 1)
+ fun_l4_n780(x)
+ else
+ fun_l4_n174(x)
+ end
+end
+
+def fun_l3_n659(x)
+ if (x < 1)
+ fun_l4_n54(x)
+ else
+ fun_l4_n681(x)
+ end
+end
+
+def fun_l3_n660(x)
+ if (x < 1)
+ fun_l4_n279(x)
+ else
+ fun_l4_n282(x)
+ end
+end
+
+def fun_l3_n661(x)
+ if (x < 1)
+ fun_l4_n953(x)
+ else
+ fun_l4_n832(x)
+ end
+end
+
+def fun_l3_n662(x)
+ if (x < 1)
+ fun_l4_n525(x)
+ else
+ fun_l4_n850(x)
+ end
+end
+
+def fun_l3_n663(x)
+ if (x < 1)
+ fun_l4_n606(x)
+ else
+ fun_l4_n167(x)
+ end
+end
+
+def fun_l3_n664(x)
+ if (x < 1)
+ fun_l4_n941(x)
+ else
+ fun_l4_n591(x)
+ end
+end
+
+def fun_l3_n665(x)
+ if (x < 1)
+ fun_l4_n781(x)
+ else
+ fun_l4_n162(x)
+ end
+end
+
+def fun_l3_n666(x)
+ if (x < 1)
+ fun_l4_n848(x)
+ else
+ fun_l4_n133(x)
+ end
+end
+
+def fun_l3_n667(x)
+ if (x < 1)
+ fun_l4_n341(x)
+ else
+ fun_l4_n212(x)
+ end
+end
+
+def fun_l3_n668(x)
+ if (x < 1)
+ fun_l4_n320(x)
+ else
+ fun_l4_n131(x)
+ end
+end
+
+def fun_l3_n669(x)
+ if (x < 1)
+ fun_l4_n18(x)
+ else
+ fun_l4_n385(x)
+ end
+end
+
+def fun_l3_n670(x)
+ if (x < 1)
+ fun_l4_n917(x)
+ else
+ fun_l4_n988(x)
+ end
+end
+
+def fun_l3_n671(x)
+ if (x < 1)
+ fun_l4_n50(x)
+ else
+ fun_l4_n27(x)
+ end
+end
+
+def fun_l3_n672(x)
+ if (x < 1)
+ fun_l4_n277(x)
+ else
+ fun_l4_n238(x)
+ end
+end
+
+def fun_l3_n673(x)
+ if (x < 1)
+ fun_l4_n303(x)
+ else
+ fun_l4_n643(x)
+ end
+end
+
+def fun_l3_n674(x)
+ if (x < 1)
+ fun_l4_n794(x)
+ else
+ fun_l4_n906(x)
+ end
+end
+
+def fun_l3_n675(x)
+ if (x < 1)
+ fun_l4_n688(x)
+ else
+ fun_l4_n312(x)
+ end
+end
+
+def fun_l3_n676(x)
+ if (x < 1)
+ fun_l4_n833(x)
+ else
+ fun_l4_n900(x)
+ end
+end
+
+def fun_l3_n677(x)
+ if (x < 1)
+ fun_l4_n649(x)
+ else
+ fun_l4_n822(x)
+ end
+end
+
+def fun_l3_n678(x)
+ if (x < 1)
+ fun_l4_n958(x)
+ else
+ fun_l4_n939(x)
+ end
+end
+
+def fun_l3_n679(x)
+ if (x < 1)
+ fun_l4_n949(x)
+ else
+ fun_l4_n887(x)
+ end
+end
+
+def fun_l3_n680(x)
+ if (x < 1)
+ fun_l4_n630(x)
+ else
+ fun_l4_n508(x)
+ end
+end
+
+def fun_l3_n681(x)
+ if (x < 1)
+ fun_l4_n553(x)
+ else
+ fun_l4_n940(x)
+ end
+end
+
+def fun_l3_n682(x)
+ if (x < 1)
+ fun_l4_n180(x)
+ else
+ fun_l4_n950(x)
+ end
+end
+
+def fun_l3_n683(x)
+ if (x < 1)
+ fun_l4_n898(x)
+ else
+ fun_l4_n374(x)
+ end
+end
+
+def fun_l3_n684(x)
+ if (x < 1)
+ fun_l4_n802(x)
+ else
+ fun_l4_n527(x)
+ end
+end
+
+def fun_l3_n685(x)
+ if (x < 1)
+ fun_l4_n751(x)
+ else
+ fun_l4_n967(x)
+ end
+end
+
+def fun_l3_n686(x)
+ if (x < 1)
+ fun_l4_n235(x)
+ else
+ fun_l4_n559(x)
+ end
+end
+
+def fun_l3_n687(x)
+ if (x < 1)
+ fun_l4_n694(x)
+ else
+ fun_l4_n819(x)
+ end
+end
+
+def fun_l3_n688(x)
+ if (x < 1)
+ fun_l4_n167(x)
+ else
+ fun_l4_n91(x)
+ end
+end
+
+def fun_l3_n689(x)
+ if (x < 1)
+ fun_l4_n692(x)
+ else
+ fun_l4_n422(x)
+ end
+end
+
+def fun_l3_n690(x)
+ if (x < 1)
+ fun_l4_n344(x)
+ else
+ fun_l4_n738(x)
+ end
+end
+
+def fun_l3_n691(x)
+ if (x < 1)
+ fun_l4_n394(x)
+ else
+ fun_l4_n603(x)
+ end
+end
+
+def fun_l3_n692(x)
+ if (x < 1)
+ fun_l4_n909(x)
+ else
+ fun_l4_n528(x)
+ end
+end
+
+def fun_l3_n693(x)
+ if (x < 1)
+ fun_l4_n180(x)
+ else
+ fun_l4_n22(x)
+ end
+end
+
+def fun_l3_n694(x)
+ if (x < 1)
+ fun_l4_n6(x)
+ else
+ fun_l4_n777(x)
+ end
+end
+
+def fun_l3_n695(x)
+ if (x < 1)
+ fun_l4_n327(x)
+ else
+ fun_l4_n948(x)
+ end
+end
+
+def fun_l3_n696(x)
+ if (x < 1)
+ fun_l4_n748(x)
+ else
+ fun_l4_n706(x)
+ end
+end
+
+def fun_l3_n697(x)
+ if (x < 1)
+ fun_l4_n720(x)
+ else
+ fun_l4_n693(x)
+ end
+end
+
+def fun_l3_n698(x)
+ if (x < 1)
+ fun_l4_n282(x)
+ else
+ fun_l4_n755(x)
+ end
+end
+
+def fun_l3_n699(x)
+ if (x < 1)
+ fun_l4_n975(x)
+ else
+ fun_l4_n415(x)
+ end
+end
+
+def fun_l3_n700(x)
+ if (x < 1)
+ fun_l4_n684(x)
+ else
+ fun_l4_n738(x)
+ end
+end
+
+def fun_l3_n701(x)
+ if (x < 1)
+ fun_l4_n58(x)
+ else
+ fun_l4_n892(x)
+ end
+end
+
+def fun_l3_n702(x)
+ if (x < 1)
+ fun_l4_n366(x)
+ else
+ fun_l4_n189(x)
+ end
+end
+
+def fun_l3_n703(x)
+ if (x < 1)
+ fun_l4_n422(x)
+ else
+ fun_l4_n535(x)
+ end
+end
+
+def fun_l3_n704(x)
+ if (x < 1)
+ fun_l4_n886(x)
+ else
+ fun_l4_n223(x)
+ end
+end
+
+def fun_l3_n705(x)
+ if (x < 1)
+ fun_l4_n57(x)
+ else
+ fun_l4_n62(x)
+ end
+end
+
+def fun_l3_n706(x)
+ if (x < 1)
+ fun_l4_n629(x)
+ else
+ fun_l4_n479(x)
+ end
+end
+
+def fun_l3_n707(x)
+ if (x < 1)
+ fun_l4_n477(x)
+ else
+ fun_l4_n302(x)
+ end
+end
+
+def fun_l3_n708(x)
+ if (x < 1)
+ fun_l4_n790(x)
+ else
+ fun_l4_n262(x)
+ end
+end
+
+def fun_l3_n709(x)
+ if (x < 1)
+ fun_l4_n772(x)
+ else
+ fun_l4_n995(x)
+ end
+end
+
+def fun_l3_n710(x)
+ if (x < 1)
+ fun_l4_n549(x)
+ else
+ fun_l4_n651(x)
+ end
+end
+
+def fun_l3_n711(x)
+ if (x < 1)
+ fun_l4_n77(x)
+ else
+ fun_l4_n555(x)
+ end
+end
+
+def fun_l3_n712(x)
+ if (x < 1)
+ fun_l4_n515(x)
+ else
+ fun_l4_n734(x)
+ end
+end
+
+def fun_l3_n713(x)
+ if (x < 1)
+ fun_l4_n778(x)
+ else
+ fun_l4_n884(x)
+ end
+end
+
+def fun_l3_n714(x)
+ if (x < 1)
+ fun_l4_n235(x)
+ else
+ fun_l4_n637(x)
+ end
+end
+
+def fun_l3_n715(x)
+ if (x < 1)
+ fun_l4_n516(x)
+ else
+ fun_l4_n249(x)
+ end
+end
+
+def fun_l3_n716(x)
+ if (x < 1)
+ fun_l4_n44(x)
+ else
+ fun_l4_n307(x)
+ end
+end
+
+def fun_l3_n717(x)
+ if (x < 1)
+ fun_l4_n482(x)
+ else
+ fun_l4_n4(x)
+ end
+end
+
+def fun_l3_n718(x)
+ if (x < 1)
+ fun_l4_n195(x)
+ else
+ fun_l4_n410(x)
+ end
+end
+
+def fun_l3_n719(x)
+ if (x < 1)
+ fun_l4_n862(x)
+ else
+ fun_l4_n91(x)
+ end
+end
+
+def fun_l3_n720(x)
+ if (x < 1)
+ fun_l4_n591(x)
+ else
+ fun_l4_n391(x)
+ end
+end
+
+def fun_l3_n721(x)
+ if (x < 1)
+ fun_l4_n776(x)
+ else
+ fun_l4_n129(x)
+ end
+end
+
+def fun_l3_n722(x)
+ if (x < 1)
+ fun_l4_n857(x)
+ else
+ fun_l4_n160(x)
+ end
+end
+
+def fun_l3_n723(x)
+ if (x < 1)
+ fun_l4_n772(x)
+ else
+ fun_l4_n567(x)
+ end
+end
+
+def fun_l3_n724(x)
+ if (x < 1)
+ fun_l4_n582(x)
+ else
+ fun_l4_n100(x)
+ end
+end
+
+def fun_l3_n725(x)
+ if (x < 1)
+ fun_l4_n962(x)
+ else
+ fun_l4_n846(x)
+ end
+end
+
+def fun_l3_n726(x)
+ if (x < 1)
+ fun_l4_n892(x)
+ else
+ fun_l4_n334(x)
+ end
+end
+
+def fun_l3_n727(x)
+ if (x < 1)
+ fun_l4_n17(x)
+ else
+ fun_l4_n690(x)
+ end
+end
+
+def fun_l3_n728(x)
+ if (x < 1)
+ fun_l4_n453(x)
+ else
+ fun_l4_n234(x)
+ end
+end
+
+def fun_l3_n729(x)
+ if (x < 1)
+ fun_l4_n562(x)
+ else
+ fun_l4_n139(x)
+ end
+end
+
+def fun_l3_n730(x)
+ if (x < 1)
+ fun_l4_n87(x)
+ else
+ fun_l4_n513(x)
+ end
+end
+
+def fun_l3_n731(x)
+ if (x < 1)
+ fun_l4_n565(x)
+ else
+ fun_l4_n289(x)
+ end
+end
+
+def fun_l3_n732(x)
+ if (x < 1)
+ fun_l4_n821(x)
+ else
+ fun_l4_n290(x)
+ end
+end
+
+def fun_l3_n733(x)
+ if (x < 1)
+ fun_l4_n464(x)
+ else
+ fun_l4_n929(x)
+ end
+end
+
+def fun_l3_n734(x)
+ if (x < 1)
+ fun_l4_n617(x)
+ else
+ fun_l4_n230(x)
+ end
+end
+
+def fun_l3_n735(x)
+ if (x < 1)
+ fun_l4_n942(x)
+ else
+ fun_l4_n770(x)
+ end
+end
+
+def fun_l3_n736(x)
+ if (x < 1)
+ fun_l4_n826(x)
+ else
+ fun_l4_n414(x)
+ end
+end
+
+def fun_l3_n737(x)
+ if (x < 1)
+ fun_l4_n47(x)
+ else
+ fun_l4_n357(x)
+ end
+end
+
+def fun_l3_n738(x)
+ if (x < 1)
+ fun_l4_n582(x)
+ else
+ fun_l4_n652(x)
+ end
+end
+
+def fun_l3_n739(x)
+ if (x < 1)
+ fun_l4_n641(x)
+ else
+ fun_l4_n479(x)
+ end
+end
+
+def fun_l3_n740(x)
+ if (x < 1)
+ fun_l4_n11(x)
+ else
+ fun_l4_n965(x)
+ end
+end
+
+def fun_l3_n741(x)
+ if (x < 1)
+ fun_l4_n402(x)
+ else
+ fun_l4_n512(x)
+ end
+end
+
+def fun_l3_n742(x)
+ if (x < 1)
+ fun_l4_n300(x)
+ else
+ fun_l4_n942(x)
+ end
+end
+
+def fun_l3_n743(x)
+ if (x < 1)
+ fun_l4_n770(x)
+ else
+ fun_l4_n690(x)
+ end
+end
+
+def fun_l3_n744(x)
+ if (x < 1)
+ fun_l4_n575(x)
+ else
+ fun_l4_n158(x)
+ end
+end
+
+def fun_l3_n745(x)
+ if (x < 1)
+ fun_l4_n760(x)
+ else
+ fun_l4_n552(x)
+ end
+end
+
+def fun_l3_n746(x)
+ if (x < 1)
+ fun_l4_n887(x)
+ else
+ fun_l4_n319(x)
+ end
+end
+
+def fun_l3_n747(x)
+ if (x < 1)
+ fun_l4_n967(x)
+ else
+ fun_l4_n561(x)
+ end
+end
+
+def fun_l3_n748(x)
+ if (x < 1)
+ fun_l4_n4(x)
+ else
+ fun_l4_n766(x)
+ end
+end
+
+def fun_l3_n749(x)
+ if (x < 1)
+ fun_l4_n993(x)
+ else
+ fun_l4_n991(x)
+ end
+end
+
+def fun_l3_n750(x)
+ if (x < 1)
+ fun_l4_n890(x)
+ else
+ fun_l4_n663(x)
+ end
+end
+
+def fun_l3_n751(x)
+ if (x < 1)
+ fun_l4_n267(x)
+ else
+ fun_l4_n449(x)
+ end
+end
+
+def fun_l3_n752(x)
+ if (x < 1)
+ fun_l4_n540(x)
+ else
+ fun_l4_n226(x)
+ end
+end
+
+def fun_l3_n753(x)
+ if (x < 1)
+ fun_l4_n893(x)
+ else
+ fun_l4_n116(x)
+ end
+end
+
+def fun_l3_n754(x)
+ if (x < 1)
+ fun_l4_n570(x)
+ else
+ fun_l4_n192(x)
+ end
+end
+
+def fun_l3_n755(x)
+ if (x < 1)
+ fun_l4_n712(x)
+ else
+ fun_l4_n81(x)
+ end
+end
+
+def fun_l3_n756(x)
+ if (x < 1)
+ fun_l4_n833(x)
+ else
+ fun_l4_n24(x)
+ end
+end
+
+def fun_l3_n757(x)
+ if (x < 1)
+ fun_l4_n740(x)
+ else
+ fun_l4_n803(x)
+ end
+end
+
+def fun_l3_n758(x)
+ if (x < 1)
+ fun_l4_n552(x)
+ else
+ fun_l4_n551(x)
+ end
+end
+
+def fun_l3_n759(x)
+ if (x < 1)
+ fun_l4_n570(x)
+ else
+ fun_l4_n677(x)
+ end
+end
+
+def fun_l3_n760(x)
+ if (x < 1)
+ fun_l4_n243(x)
+ else
+ fun_l4_n677(x)
+ end
+end
+
+def fun_l3_n761(x)
+ if (x < 1)
+ fun_l4_n65(x)
+ else
+ fun_l4_n660(x)
+ end
+end
+
+def fun_l3_n762(x)
+ if (x < 1)
+ fun_l4_n989(x)
+ else
+ fun_l4_n761(x)
+ end
+end
+
+def fun_l3_n763(x)
+ if (x < 1)
+ fun_l4_n971(x)
+ else
+ fun_l4_n280(x)
+ end
+end
+
+def fun_l3_n764(x)
+ if (x < 1)
+ fun_l4_n441(x)
+ else
+ fun_l4_n506(x)
+ end
+end
+
+def fun_l3_n765(x)
+ if (x < 1)
+ fun_l4_n577(x)
+ else
+ fun_l4_n586(x)
+ end
+end
+
+def fun_l3_n766(x)
+ if (x < 1)
+ fun_l4_n385(x)
+ else
+ fun_l4_n60(x)
+ end
+end
+
+def fun_l3_n767(x)
+ if (x < 1)
+ fun_l4_n380(x)
+ else
+ fun_l4_n32(x)
+ end
+end
+
+def fun_l3_n768(x)
+ if (x < 1)
+ fun_l4_n797(x)
+ else
+ fun_l4_n437(x)
+ end
+end
+
+def fun_l3_n769(x)
+ if (x < 1)
+ fun_l4_n615(x)
+ else
+ fun_l4_n369(x)
+ end
+end
+
+def fun_l3_n770(x)
+ if (x < 1)
+ fun_l4_n779(x)
+ else
+ fun_l4_n194(x)
+ end
+end
+
+def fun_l3_n771(x)
+ if (x < 1)
+ fun_l4_n287(x)
+ else
+ fun_l4_n819(x)
+ end
+end
+
+def fun_l3_n772(x)
+ if (x < 1)
+ fun_l4_n405(x)
+ else
+ fun_l4_n738(x)
+ end
+end
+
+def fun_l3_n773(x)
+ if (x < 1)
+ fun_l4_n706(x)
+ else
+ fun_l4_n174(x)
+ end
+end
+
+def fun_l3_n774(x)
+ if (x < 1)
+ fun_l4_n690(x)
+ else
+ fun_l4_n841(x)
+ end
+end
+
+def fun_l3_n775(x)
+ if (x < 1)
+ fun_l4_n256(x)
+ else
+ fun_l4_n179(x)
+ end
+end
+
+def fun_l3_n776(x)
+ if (x < 1)
+ fun_l4_n342(x)
+ else
+ fun_l4_n359(x)
+ end
+end
+
+def fun_l3_n777(x)
+ if (x < 1)
+ fun_l4_n371(x)
+ else
+ fun_l4_n680(x)
+ end
+end
+
+def fun_l3_n778(x)
+ if (x < 1)
+ fun_l4_n996(x)
+ else
+ fun_l4_n343(x)
+ end
+end
+
+def fun_l3_n779(x)
+ if (x < 1)
+ fun_l4_n96(x)
+ else
+ fun_l4_n893(x)
+ end
+end
+
+def fun_l3_n780(x)
+ if (x < 1)
+ fun_l4_n706(x)
+ else
+ fun_l4_n140(x)
+ end
+end
+
+def fun_l3_n781(x)
+ if (x < 1)
+ fun_l4_n349(x)
+ else
+ fun_l4_n317(x)
+ end
+end
+
+def fun_l3_n782(x)
+ if (x < 1)
+ fun_l4_n491(x)
+ else
+ fun_l4_n616(x)
+ end
+end
+
+def fun_l3_n783(x)
+ if (x < 1)
+ fun_l4_n227(x)
+ else
+ fun_l4_n356(x)
+ end
+end
+
+def fun_l3_n784(x)
+ if (x < 1)
+ fun_l4_n387(x)
+ else
+ fun_l4_n532(x)
+ end
+end
+
+def fun_l3_n785(x)
+ if (x < 1)
+ fun_l4_n648(x)
+ else
+ fun_l4_n34(x)
+ end
+end
+
+def fun_l3_n786(x)
+ if (x < 1)
+ fun_l4_n562(x)
+ else
+ fun_l4_n476(x)
+ end
+end
+
+def fun_l3_n787(x)
+ if (x < 1)
+ fun_l4_n162(x)
+ else
+ fun_l4_n384(x)
+ end
+end
+
+def fun_l3_n788(x)
+ if (x < 1)
+ fun_l4_n221(x)
+ else
+ fun_l4_n617(x)
+ end
+end
+
+def fun_l3_n789(x)
+ if (x < 1)
+ fun_l4_n670(x)
+ else
+ fun_l4_n350(x)
+ end
+end
+
+def fun_l3_n790(x)
+ if (x < 1)
+ fun_l4_n202(x)
+ else
+ fun_l4_n112(x)
+ end
+end
+
+def fun_l3_n791(x)
+ if (x < 1)
+ fun_l4_n390(x)
+ else
+ fun_l4_n868(x)
+ end
+end
+
+def fun_l3_n792(x)
+ if (x < 1)
+ fun_l4_n746(x)
+ else
+ fun_l4_n833(x)
+ end
+end
+
+def fun_l3_n793(x)
+ if (x < 1)
+ fun_l4_n471(x)
+ else
+ fun_l4_n60(x)
+ end
+end
+
+def fun_l3_n794(x)
+ if (x < 1)
+ fun_l4_n583(x)
+ else
+ fun_l4_n470(x)
+ end
+end
+
+def fun_l3_n795(x)
+ if (x < 1)
+ fun_l4_n567(x)
+ else
+ fun_l4_n218(x)
+ end
+end
+
+def fun_l3_n796(x)
+ if (x < 1)
+ fun_l4_n140(x)
+ else
+ fun_l4_n690(x)
+ end
+end
+
+def fun_l3_n797(x)
+ if (x < 1)
+ fun_l4_n190(x)
+ else
+ fun_l4_n437(x)
+ end
+end
+
+def fun_l3_n798(x)
+ if (x < 1)
+ fun_l4_n684(x)
+ else
+ fun_l4_n843(x)
+ end
+end
+
+def fun_l3_n799(x)
+ if (x < 1)
+ fun_l4_n825(x)
+ else
+ fun_l4_n354(x)
+ end
+end
+
+def fun_l3_n800(x)
+ if (x < 1)
+ fun_l4_n711(x)
+ else
+ fun_l4_n606(x)
+ end
+end
+
+def fun_l3_n801(x)
+ if (x < 1)
+ fun_l4_n756(x)
+ else
+ fun_l4_n464(x)
+ end
+end
+
+def fun_l3_n802(x)
+ if (x < 1)
+ fun_l4_n143(x)
+ else
+ fun_l4_n962(x)
+ end
+end
+
+def fun_l3_n803(x)
+ if (x < 1)
+ fun_l4_n223(x)
+ else
+ fun_l4_n293(x)
+ end
+end
+
+def fun_l3_n804(x)
+ if (x < 1)
+ fun_l4_n832(x)
+ else
+ fun_l4_n632(x)
+ end
+end
+
+def fun_l3_n805(x)
+ if (x < 1)
+ fun_l4_n649(x)
+ else
+ fun_l4_n259(x)
+ end
+end
+
+def fun_l3_n806(x)
+ if (x < 1)
+ fun_l4_n617(x)
+ else
+ fun_l4_n993(x)
+ end
+end
+
+def fun_l3_n807(x)
+ if (x < 1)
+ fun_l4_n257(x)
+ else
+ fun_l4_n712(x)
+ end
+end
+
+def fun_l3_n808(x)
+ if (x < 1)
+ fun_l4_n632(x)
+ else
+ fun_l4_n563(x)
+ end
+end
+
+def fun_l3_n809(x)
+ if (x < 1)
+ fun_l4_n154(x)
+ else
+ fun_l4_n561(x)
+ end
+end
+
+def fun_l3_n810(x)
+ if (x < 1)
+ fun_l4_n411(x)
+ else
+ fun_l4_n42(x)
+ end
+end
+
+def fun_l3_n811(x)
+ if (x < 1)
+ fun_l4_n560(x)
+ else
+ fun_l4_n531(x)
+ end
+end
+
+def fun_l3_n812(x)
+ if (x < 1)
+ fun_l4_n759(x)
+ else
+ fun_l4_n588(x)
+ end
+end
+
+def fun_l3_n813(x)
+ if (x < 1)
+ fun_l4_n311(x)
+ else
+ fun_l4_n813(x)
+ end
+end
+
+def fun_l3_n814(x)
+ if (x < 1)
+ fun_l4_n521(x)
+ else
+ fun_l4_n877(x)
+ end
+end
+
+def fun_l3_n815(x)
+ if (x < 1)
+ fun_l4_n578(x)
+ else
+ fun_l4_n37(x)
+ end
+end
+
+def fun_l3_n816(x)
+ if (x < 1)
+ fun_l4_n337(x)
+ else
+ fun_l4_n562(x)
+ end
+end
+
+def fun_l3_n817(x)
+ if (x < 1)
+ fun_l4_n523(x)
+ else
+ fun_l4_n445(x)
+ end
+end
+
+def fun_l3_n818(x)
+ if (x < 1)
+ fun_l4_n256(x)
+ else
+ fun_l4_n551(x)
+ end
+end
+
+def fun_l3_n819(x)
+ if (x < 1)
+ fun_l4_n718(x)
+ else
+ fun_l4_n463(x)
+ end
+end
+
+def fun_l3_n820(x)
+ if (x < 1)
+ fun_l4_n780(x)
+ else
+ fun_l4_n103(x)
+ end
+end
+
+def fun_l3_n821(x)
+ if (x < 1)
+ fun_l4_n729(x)
+ else
+ fun_l4_n331(x)
+ end
+end
+
+def fun_l3_n822(x)
+ if (x < 1)
+ fun_l4_n84(x)
+ else
+ fun_l4_n176(x)
+ end
+end
+
+def fun_l3_n823(x)
+ if (x < 1)
+ fun_l4_n231(x)
+ else
+ fun_l4_n681(x)
+ end
+end
+
+def fun_l3_n824(x)
+ if (x < 1)
+ fun_l4_n675(x)
+ else
+ fun_l4_n837(x)
+ end
+end
+
+def fun_l3_n825(x)
+ if (x < 1)
+ fun_l4_n140(x)
+ else
+ fun_l4_n932(x)
+ end
+end
+
+def fun_l3_n826(x)
+ if (x < 1)
+ fun_l4_n268(x)
+ else
+ fun_l4_n908(x)
+ end
+end
+
+def fun_l3_n827(x)
+ if (x < 1)
+ fun_l4_n959(x)
+ else
+ fun_l4_n643(x)
+ end
+end
+
+def fun_l3_n828(x)
+ if (x < 1)
+ fun_l4_n290(x)
+ else
+ fun_l4_n718(x)
+ end
+end
+
+def fun_l3_n829(x)
+ if (x < 1)
+ fun_l4_n430(x)
+ else
+ fun_l4_n114(x)
+ end
+end
+
+def fun_l3_n830(x)
+ if (x < 1)
+ fun_l4_n817(x)
+ else
+ fun_l4_n296(x)
+ end
+end
+
+def fun_l3_n831(x)
+ if (x < 1)
+ fun_l4_n586(x)
+ else
+ fun_l4_n345(x)
+ end
+end
+
+def fun_l3_n832(x)
+ if (x < 1)
+ fun_l4_n321(x)
+ else
+ fun_l4_n805(x)
+ end
+end
+
+def fun_l3_n833(x)
+ if (x < 1)
+ fun_l4_n57(x)
+ else
+ fun_l4_n373(x)
+ end
+end
+
+def fun_l3_n834(x)
+ if (x < 1)
+ fun_l4_n344(x)
+ else
+ fun_l4_n654(x)
+ end
+end
+
+def fun_l3_n835(x)
+ if (x < 1)
+ fun_l4_n761(x)
+ else
+ fun_l4_n295(x)
+ end
+end
+
+def fun_l3_n836(x)
+ if (x < 1)
+ fun_l4_n169(x)
+ else
+ fun_l4_n184(x)
+ end
+end
+
+def fun_l3_n837(x)
+ if (x < 1)
+ fun_l4_n482(x)
+ else
+ fun_l4_n127(x)
+ end
+end
+
+def fun_l3_n838(x)
+ if (x < 1)
+ fun_l4_n260(x)
+ else
+ fun_l4_n662(x)
+ end
+end
+
+def fun_l3_n839(x)
+ if (x < 1)
+ fun_l4_n548(x)
+ else
+ fun_l4_n197(x)
+ end
+end
+
+def fun_l3_n840(x)
+ if (x < 1)
+ fun_l4_n96(x)
+ else
+ fun_l4_n17(x)
+ end
+end
+
+def fun_l3_n841(x)
+ if (x < 1)
+ fun_l4_n946(x)
+ else
+ fun_l4_n447(x)
+ end
+end
+
+def fun_l3_n842(x)
+ if (x < 1)
+ fun_l4_n66(x)
+ else
+ fun_l4_n110(x)
+ end
+end
+
+def fun_l3_n843(x)
+ if (x < 1)
+ fun_l4_n574(x)
+ else
+ fun_l4_n887(x)
+ end
+end
+
+def fun_l3_n844(x)
+ if (x < 1)
+ fun_l4_n912(x)
+ else
+ fun_l4_n465(x)
+ end
+end
+
+def fun_l3_n845(x)
+ if (x < 1)
+ fun_l4_n401(x)
+ else
+ fun_l4_n903(x)
+ end
+end
+
+def fun_l3_n846(x)
+ if (x < 1)
+ fun_l4_n929(x)
+ else
+ fun_l4_n238(x)
+ end
+end
+
+def fun_l3_n847(x)
+ if (x < 1)
+ fun_l4_n579(x)
+ else
+ fun_l4_n924(x)
+ end
+end
+
+def fun_l3_n848(x)
+ if (x < 1)
+ fun_l4_n697(x)
+ else
+ fun_l4_n157(x)
+ end
+end
+
+def fun_l3_n849(x)
+ if (x < 1)
+ fun_l4_n608(x)
+ else
+ fun_l4_n426(x)
+ end
+end
+
+def fun_l3_n850(x)
+ if (x < 1)
+ fun_l4_n710(x)
+ else
+ fun_l4_n360(x)
+ end
+end
+
+def fun_l3_n851(x)
+ if (x < 1)
+ fun_l4_n558(x)
+ else
+ fun_l4_n152(x)
+ end
+end
+
+def fun_l3_n852(x)
+ if (x < 1)
+ fun_l4_n276(x)
+ else
+ fun_l4_n895(x)
+ end
+end
+
+def fun_l3_n853(x)
+ if (x < 1)
+ fun_l4_n945(x)
+ else
+ fun_l4_n251(x)
+ end
+end
+
+def fun_l3_n854(x)
+ if (x < 1)
+ fun_l4_n131(x)
+ else
+ fun_l4_n677(x)
+ end
+end
+
+def fun_l3_n855(x)
+ if (x < 1)
+ fun_l4_n493(x)
+ else
+ fun_l4_n631(x)
+ end
+end
+
+def fun_l3_n856(x)
+ if (x < 1)
+ fun_l4_n608(x)
+ else
+ fun_l4_n556(x)
+ end
+end
+
+def fun_l3_n857(x)
+ if (x < 1)
+ fun_l4_n808(x)
+ else
+ fun_l4_n672(x)
+ end
+end
+
+def fun_l3_n858(x)
+ if (x < 1)
+ fun_l4_n407(x)
+ else
+ fun_l4_n648(x)
+ end
+end
+
+def fun_l3_n859(x)
+ if (x < 1)
+ fun_l4_n217(x)
+ else
+ fun_l4_n763(x)
+ end
+end
+
+def fun_l3_n860(x)
+ if (x < 1)
+ fun_l4_n941(x)
+ else
+ fun_l4_n159(x)
+ end
+end
+
+def fun_l3_n861(x)
+ if (x < 1)
+ fun_l4_n364(x)
+ else
+ fun_l4_n241(x)
+ end
+end
+
+def fun_l3_n862(x)
+ if (x < 1)
+ fun_l4_n915(x)
+ else
+ fun_l4_n729(x)
+ end
+end
+
+def fun_l3_n863(x)
+ if (x < 1)
+ fun_l4_n137(x)
+ else
+ fun_l4_n317(x)
+ end
+end
+
+def fun_l3_n864(x)
+ if (x < 1)
+ fun_l4_n818(x)
+ else
+ fun_l4_n782(x)
+ end
+end
+
+def fun_l3_n865(x)
+ if (x < 1)
+ fun_l4_n577(x)
+ else
+ fun_l4_n418(x)
+ end
+end
+
+def fun_l3_n866(x)
+ if (x < 1)
+ fun_l4_n882(x)
+ else
+ fun_l4_n7(x)
+ end
+end
+
+def fun_l3_n867(x)
+ if (x < 1)
+ fun_l4_n238(x)
+ else
+ fun_l4_n944(x)
+ end
+end
+
+def fun_l3_n868(x)
+ if (x < 1)
+ fun_l4_n105(x)
+ else
+ fun_l4_n465(x)
+ end
+end
+
+def fun_l3_n869(x)
+ if (x < 1)
+ fun_l4_n841(x)
+ else
+ fun_l4_n262(x)
+ end
+end
+
+def fun_l3_n870(x)
+ if (x < 1)
+ fun_l4_n32(x)
+ else
+ fun_l4_n992(x)
+ end
+end
+
+def fun_l3_n871(x)
+ if (x < 1)
+ fun_l4_n431(x)
+ else
+ fun_l4_n391(x)
+ end
+end
+
+def fun_l3_n872(x)
+ if (x < 1)
+ fun_l4_n829(x)
+ else
+ fun_l4_n879(x)
+ end
+end
+
+def fun_l3_n873(x)
+ if (x < 1)
+ fun_l4_n617(x)
+ else
+ fun_l4_n657(x)
+ end
+end
+
+def fun_l3_n874(x)
+ if (x < 1)
+ fun_l4_n529(x)
+ else
+ fun_l4_n717(x)
+ end
+end
+
+def fun_l3_n875(x)
+ if (x < 1)
+ fun_l4_n928(x)
+ else
+ fun_l4_n476(x)
+ end
+end
+
+def fun_l3_n876(x)
+ if (x < 1)
+ fun_l4_n388(x)
+ else
+ fun_l4_n949(x)
+ end
+end
+
+def fun_l3_n877(x)
+ if (x < 1)
+ fun_l4_n826(x)
+ else
+ fun_l4_n560(x)
+ end
+end
+
+def fun_l3_n878(x)
+ if (x < 1)
+ fun_l4_n863(x)
+ else
+ fun_l4_n122(x)
+ end
+end
+
+def fun_l3_n879(x)
+ if (x < 1)
+ fun_l4_n964(x)
+ else
+ fun_l4_n793(x)
+ end
+end
+
+def fun_l3_n880(x)
+ if (x < 1)
+ fun_l4_n141(x)
+ else
+ fun_l4_n132(x)
+ end
+end
+
+def fun_l3_n881(x)
+ if (x < 1)
+ fun_l4_n735(x)
+ else
+ fun_l4_n592(x)
+ end
+end
+
+def fun_l3_n882(x)
+ if (x < 1)
+ fun_l4_n585(x)
+ else
+ fun_l4_n341(x)
+ end
+end
+
+def fun_l3_n883(x)
+ if (x < 1)
+ fun_l4_n843(x)
+ else
+ fun_l4_n692(x)
+ end
+end
+
+def fun_l3_n884(x)
+ if (x < 1)
+ fun_l4_n360(x)
+ else
+ fun_l4_n833(x)
+ end
+end
+
+def fun_l3_n885(x)
+ if (x < 1)
+ fun_l4_n31(x)
+ else
+ fun_l4_n62(x)
+ end
+end
+
+def fun_l3_n886(x)
+ if (x < 1)
+ fun_l4_n756(x)
+ else
+ fun_l4_n699(x)
+ end
+end
+
+def fun_l3_n887(x)
+ if (x < 1)
+ fun_l4_n71(x)
+ else
+ fun_l4_n256(x)
+ end
+end
+
+def fun_l3_n888(x)
+ if (x < 1)
+ fun_l4_n406(x)
+ else
+ fun_l4_n493(x)
+ end
+end
+
+def fun_l3_n889(x)
+ if (x < 1)
+ fun_l4_n489(x)
+ else
+ fun_l4_n874(x)
+ end
+end
+
+def fun_l3_n890(x)
+ if (x < 1)
+ fun_l4_n365(x)
+ else
+ fun_l4_n910(x)
+ end
+end
+
+def fun_l3_n891(x)
+ if (x < 1)
+ fun_l4_n262(x)
+ else
+ fun_l4_n665(x)
+ end
+end
+
+def fun_l3_n892(x)
+ if (x < 1)
+ fun_l4_n274(x)
+ else
+ fun_l4_n849(x)
+ end
+end
+
+def fun_l3_n893(x)
+ if (x < 1)
+ fun_l4_n880(x)
+ else
+ fun_l4_n739(x)
+ end
+end
+
+def fun_l3_n894(x)
+ if (x < 1)
+ fun_l4_n504(x)
+ else
+ fun_l4_n128(x)
+ end
+end
+
+def fun_l3_n895(x)
+ if (x < 1)
+ fun_l4_n555(x)
+ else
+ fun_l4_n281(x)
+ end
+end
+
+def fun_l3_n896(x)
+ if (x < 1)
+ fun_l4_n270(x)
+ else
+ fun_l4_n225(x)
+ end
+end
+
+def fun_l3_n897(x)
+ if (x < 1)
+ fun_l4_n38(x)
+ else
+ fun_l4_n26(x)
+ end
+end
+
+def fun_l3_n898(x)
+ if (x < 1)
+ fun_l4_n944(x)
+ else
+ fun_l4_n217(x)
+ end
+end
+
+def fun_l3_n899(x)
+ if (x < 1)
+ fun_l4_n967(x)
+ else
+ fun_l4_n853(x)
+ end
+end
+
+def fun_l3_n900(x)
+ if (x < 1)
+ fun_l4_n686(x)
+ else
+ fun_l4_n760(x)
+ end
+end
+
+def fun_l3_n901(x)
+ if (x < 1)
+ fun_l4_n698(x)
+ else
+ fun_l4_n842(x)
+ end
+end
+
+def fun_l3_n902(x)
+ if (x < 1)
+ fun_l4_n344(x)
+ else
+ fun_l4_n701(x)
+ end
+end
+
+def fun_l3_n903(x)
+ if (x < 1)
+ fun_l4_n756(x)
+ else
+ fun_l4_n321(x)
+ end
+end
+
+def fun_l3_n904(x)
+ if (x < 1)
+ fun_l4_n504(x)
+ else
+ fun_l4_n228(x)
+ end
+end
+
+def fun_l3_n905(x)
+ if (x < 1)
+ fun_l4_n135(x)
+ else
+ fun_l4_n57(x)
+ end
+end
+
+def fun_l3_n906(x)
+ if (x < 1)
+ fun_l4_n279(x)
+ else
+ fun_l4_n912(x)
+ end
+end
+
+def fun_l3_n907(x)
+ if (x < 1)
+ fun_l4_n962(x)
+ else
+ fun_l4_n418(x)
+ end
+end
+
+def fun_l3_n908(x)
+ if (x < 1)
+ fun_l4_n972(x)
+ else
+ fun_l4_n14(x)
+ end
+end
+
+def fun_l3_n909(x)
+ if (x < 1)
+ fun_l4_n231(x)
+ else
+ fun_l4_n763(x)
+ end
+end
+
+def fun_l3_n910(x)
+ if (x < 1)
+ fun_l4_n859(x)
+ else
+ fun_l4_n243(x)
+ end
+end
+
+def fun_l3_n911(x)
+ if (x < 1)
+ fun_l4_n153(x)
+ else
+ fun_l4_n136(x)
+ end
+end
+
+def fun_l3_n912(x)
+ if (x < 1)
+ fun_l4_n325(x)
+ else
+ fun_l4_n113(x)
+ end
+end
+
+def fun_l3_n913(x)
+ if (x < 1)
+ fun_l4_n625(x)
+ else
+ fun_l4_n179(x)
+ end
+end
+
+def fun_l3_n914(x)
+ if (x < 1)
+ fun_l4_n54(x)
+ else
+ fun_l4_n88(x)
+ end
+end
+
+def fun_l3_n915(x)
+ if (x < 1)
+ fun_l4_n332(x)
+ else
+ fun_l4_n3(x)
+ end
+end
+
+def fun_l3_n916(x)
+ if (x < 1)
+ fun_l4_n748(x)
+ else
+ fun_l4_n21(x)
+ end
+end
+
+def fun_l3_n917(x)
+ if (x < 1)
+ fun_l4_n132(x)
+ else
+ fun_l4_n132(x)
+ end
+end
+
+def fun_l3_n918(x)
+ if (x < 1)
+ fun_l4_n295(x)
+ else
+ fun_l4_n429(x)
+ end
+end
+
+def fun_l3_n919(x)
+ if (x < 1)
+ fun_l4_n105(x)
+ else
+ fun_l4_n984(x)
+ end
+end
+
+def fun_l3_n920(x)
+ if (x < 1)
+ fun_l4_n319(x)
+ else
+ fun_l4_n304(x)
+ end
+end
+
+def fun_l3_n921(x)
+ if (x < 1)
+ fun_l4_n756(x)
+ else
+ fun_l4_n639(x)
+ end
+end
+
+def fun_l3_n922(x)
+ if (x < 1)
+ fun_l4_n678(x)
+ else
+ fun_l4_n209(x)
+ end
+end
+
+def fun_l3_n923(x)
+ if (x < 1)
+ fun_l4_n755(x)
+ else
+ fun_l4_n941(x)
+ end
+end
+
+def fun_l3_n924(x)
+ if (x < 1)
+ fun_l4_n311(x)
+ else
+ fun_l4_n272(x)
+ end
+end
+
+def fun_l3_n925(x)
+ if (x < 1)
+ fun_l4_n543(x)
+ else
+ fun_l4_n896(x)
+ end
+end
+
+def fun_l3_n926(x)
+ if (x < 1)
+ fun_l4_n994(x)
+ else
+ fun_l4_n671(x)
+ end
+end
+
+def fun_l3_n927(x)
+ if (x < 1)
+ fun_l4_n125(x)
+ else
+ fun_l4_n852(x)
+ end
+end
+
+def fun_l3_n928(x)
+ if (x < 1)
+ fun_l4_n483(x)
+ else
+ fun_l4_n350(x)
+ end
+end
+
+def fun_l3_n929(x)
+ if (x < 1)
+ fun_l4_n622(x)
+ else
+ fun_l4_n511(x)
+ end
+end
+
+def fun_l3_n930(x)
+ if (x < 1)
+ fun_l4_n134(x)
+ else
+ fun_l4_n288(x)
+ end
+end
+
+def fun_l3_n931(x)
+ if (x < 1)
+ fun_l4_n278(x)
+ else
+ fun_l4_n800(x)
+ end
+end
+
+def fun_l3_n932(x)
+ if (x < 1)
+ fun_l4_n139(x)
+ else
+ fun_l4_n966(x)
+ end
+end
+
+def fun_l3_n933(x)
+ if (x < 1)
+ fun_l4_n275(x)
+ else
+ fun_l4_n506(x)
+ end
+end
+
+def fun_l3_n934(x)
+ if (x < 1)
+ fun_l4_n503(x)
+ else
+ fun_l4_n204(x)
+ end
+end
+
+def fun_l3_n935(x)
+ if (x < 1)
+ fun_l4_n993(x)
+ else
+ fun_l4_n126(x)
+ end
+end
+
+def fun_l3_n936(x)
+ if (x < 1)
+ fun_l4_n704(x)
+ else
+ fun_l4_n462(x)
+ end
+end
+
+def fun_l3_n937(x)
+ if (x < 1)
+ fun_l4_n922(x)
+ else
+ fun_l4_n722(x)
+ end
+end
+
+def fun_l3_n938(x)
+ if (x < 1)
+ fun_l4_n937(x)
+ else
+ fun_l4_n195(x)
+ end
+end
+
+def fun_l3_n939(x)
+ if (x < 1)
+ fun_l4_n661(x)
+ else
+ fun_l4_n265(x)
+ end
+end
+
+def fun_l3_n940(x)
+ if (x < 1)
+ fun_l4_n423(x)
+ else
+ fun_l4_n230(x)
+ end
+end
+
+def fun_l3_n941(x)
+ if (x < 1)
+ fun_l4_n698(x)
+ else
+ fun_l4_n226(x)
+ end
+end
+
+def fun_l3_n942(x)
+ if (x < 1)
+ fun_l4_n501(x)
+ else
+ fun_l4_n816(x)
+ end
+end
+
+def fun_l3_n943(x)
+ if (x < 1)
+ fun_l4_n650(x)
+ else
+ fun_l4_n925(x)
+ end
+end
+
+def fun_l3_n944(x)
+ if (x < 1)
+ fun_l4_n829(x)
+ else
+ fun_l4_n647(x)
+ end
+end
+
+def fun_l3_n945(x)
+ if (x < 1)
+ fun_l4_n401(x)
+ else
+ fun_l4_n791(x)
+ end
+end
+
+def fun_l3_n946(x)
+ if (x < 1)
+ fun_l4_n551(x)
+ else
+ fun_l4_n104(x)
+ end
+end
+
+def fun_l3_n947(x)
+ if (x < 1)
+ fun_l4_n927(x)
+ else
+ fun_l4_n213(x)
+ end
+end
+
+def fun_l3_n948(x)
+ if (x < 1)
+ fun_l4_n912(x)
+ else
+ fun_l4_n609(x)
+ end
+end
+
+def fun_l3_n949(x)
+ if (x < 1)
+ fun_l4_n302(x)
+ else
+ fun_l4_n157(x)
+ end
+end
+
+def fun_l3_n950(x)
+ if (x < 1)
+ fun_l4_n955(x)
+ else
+ fun_l4_n492(x)
+ end
+end
+
+def fun_l3_n951(x)
+ if (x < 1)
+ fun_l4_n486(x)
+ else
+ fun_l4_n412(x)
+ end
+end
+
+def fun_l3_n952(x)
+ if (x < 1)
+ fun_l4_n850(x)
+ else
+ fun_l4_n885(x)
+ end
+end
+
+def fun_l3_n953(x)
+ if (x < 1)
+ fun_l4_n84(x)
+ else
+ fun_l4_n622(x)
+ end
+end
+
+def fun_l3_n954(x)
+ if (x < 1)
+ fun_l4_n235(x)
+ else
+ fun_l4_n67(x)
+ end
+end
+
+def fun_l3_n955(x)
+ if (x < 1)
+ fun_l4_n347(x)
+ else
+ fun_l4_n757(x)
+ end
+end
+
+def fun_l3_n956(x)
+ if (x < 1)
+ fun_l4_n825(x)
+ else
+ fun_l4_n10(x)
+ end
+end
+
+def fun_l3_n957(x)
+ if (x < 1)
+ fun_l4_n393(x)
+ else
+ fun_l4_n482(x)
+ end
+end
+
+def fun_l3_n958(x)
+ if (x < 1)
+ fun_l4_n0(x)
+ else
+ fun_l4_n556(x)
+ end
+end
+
+def fun_l3_n959(x)
+ if (x < 1)
+ fun_l4_n806(x)
+ else
+ fun_l4_n783(x)
+ end
+end
+
+def fun_l3_n960(x)
+ if (x < 1)
+ fun_l4_n964(x)
+ else
+ fun_l4_n843(x)
+ end
+end
+
+def fun_l3_n961(x)
+ if (x < 1)
+ fun_l4_n508(x)
+ else
+ fun_l4_n874(x)
+ end
+end
+
+def fun_l3_n962(x)
+ if (x < 1)
+ fun_l4_n15(x)
+ else
+ fun_l4_n197(x)
+ end
+end
+
+def fun_l3_n963(x)
+ if (x < 1)
+ fun_l4_n989(x)
+ else
+ fun_l4_n380(x)
+ end
+end
+
+def fun_l3_n964(x)
+ if (x < 1)
+ fun_l4_n315(x)
+ else
+ fun_l4_n196(x)
+ end
+end
+
+def fun_l3_n965(x)
+ if (x < 1)
+ fun_l4_n510(x)
+ else
+ fun_l4_n275(x)
+ end
+end
+
+def fun_l3_n966(x)
+ if (x < 1)
+ fun_l4_n725(x)
+ else
+ fun_l4_n94(x)
+ end
+end
+
+def fun_l3_n967(x)
+ if (x < 1)
+ fun_l4_n733(x)
+ else
+ fun_l4_n577(x)
+ end
+end
+
+def fun_l3_n968(x)
+ if (x < 1)
+ fun_l4_n280(x)
+ else
+ fun_l4_n702(x)
+ end
+end
+
+def fun_l3_n969(x)
+ if (x < 1)
+ fun_l4_n41(x)
+ else
+ fun_l4_n343(x)
+ end
+end
+
+def fun_l3_n970(x)
+ if (x < 1)
+ fun_l4_n102(x)
+ else
+ fun_l4_n785(x)
+ end
+end
+
+def fun_l3_n971(x)
+ if (x < 1)
+ fun_l4_n460(x)
+ else
+ fun_l4_n388(x)
+ end
+end
+
+def fun_l3_n972(x)
+ if (x < 1)
+ fun_l4_n31(x)
+ else
+ fun_l4_n421(x)
+ end
+end
+
+def fun_l3_n973(x)
+ if (x < 1)
+ fun_l4_n587(x)
+ else
+ fun_l4_n401(x)
+ end
+end
+
+def fun_l3_n974(x)
+ if (x < 1)
+ fun_l4_n593(x)
+ else
+ fun_l4_n418(x)
+ end
+end
+
+def fun_l3_n975(x)
+ if (x < 1)
+ fun_l4_n12(x)
+ else
+ fun_l4_n929(x)
+ end
+end
+
+def fun_l3_n976(x)
+ if (x < 1)
+ fun_l4_n516(x)
+ else
+ fun_l4_n402(x)
+ end
+end
+
+def fun_l3_n977(x)
+ if (x < 1)
+ fun_l4_n590(x)
+ else
+ fun_l4_n876(x)
+ end
+end
+
+def fun_l3_n978(x)
+ if (x < 1)
+ fun_l4_n505(x)
+ else
+ fun_l4_n94(x)
+ end
+end
+
+def fun_l3_n979(x)
+ if (x < 1)
+ fun_l4_n625(x)
+ else
+ fun_l4_n344(x)
+ end
+end
+
+def fun_l3_n980(x)
+ if (x < 1)
+ fun_l4_n128(x)
+ else
+ fun_l4_n454(x)
+ end
+end
+
+def fun_l3_n981(x)
+ if (x < 1)
+ fun_l4_n937(x)
+ else
+ fun_l4_n277(x)
+ end
+end
+
+def fun_l3_n982(x)
+ if (x < 1)
+ fun_l4_n237(x)
+ else
+ fun_l4_n113(x)
+ end
+end
+
+def fun_l3_n983(x)
+ if (x < 1)
+ fun_l4_n668(x)
+ else
+ fun_l4_n668(x)
+ end
+end
+
+def fun_l3_n984(x)
+ if (x < 1)
+ fun_l4_n783(x)
+ else
+ fun_l4_n771(x)
+ end
+end
+
+def fun_l3_n985(x)
+ if (x < 1)
+ fun_l4_n135(x)
+ else
+ fun_l4_n967(x)
+ end
+end
+
+def fun_l3_n986(x)
+ if (x < 1)
+ fun_l4_n29(x)
+ else
+ fun_l4_n313(x)
+ end
+end
+
+def fun_l3_n987(x)
+ if (x < 1)
+ fun_l4_n765(x)
+ else
+ fun_l4_n885(x)
+ end
+end
+
+def fun_l3_n988(x)
+ if (x < 1)
+ fun_l4_n242(x)
+ else
+ fun_l4_n622(x)
+ end
+end
+
+def fun_l3_n989(x)
+ if (x < 1)
+ fun_l4_n916(x)
+ else
+ fun_l4_n518(x)
+ end
+end
+
+def fun_l3_n990(x)
+ if (x < 1)
+ fun_l4_n523(x)
+ else
+ fun_l4_n468(x)
+ end
+end
+
+def fun_l3_n991(x)
+ if (x < 1)
+ fun_l4_n904(x)
+ else
+ fun_l4_n601(x)
+ end
+end
+
+def fun_l3_n992(x)
+ if (x < 1)
+ fun_l4_n437(x)
+ else
+ fun_l4_n77(x)
+ end
+end
+
+def fun_l3_n993(x)
+ if (x < 1)
+ fun_l4_n957(x)
+ else
+ fun_l4_n619(x)
+ end
+end
+
+def fun_l3_n994(x)
+ if (x < 1)
+ fun_l4_n540(x)
+ else
+ fun_l4_n108(x)
+ end
+end
+
+def fun_l3_n995(x)
+ if (x < 1)
+ fun_l4_n8(x)
+ else
+ fun_l4_n428(x)
+ end
+end
+
+def fun_l3_n996(x)
+ if (x < 1)
+ fun_l4_n53(x)
+ else
+ fun_l4_n278(x)
+ end
+end
+
+def fun_l3_n997(x)
+ if (x < 1)
+ fun_l4_n930(x)
+ else
+ fun_l4_n671(x)
+ end
+end
+
+def fun_l3_n998(x)
+ if (x < 1)
+ fun_l4_n574(x)
+ else
+ fun_l4_n879(x)
+ end
+end
+
+def fun_l3_n999(x)
+ if (x < 1)
+ fun_l4_n316(x)
+ else
+ fun_l4_n93(x)
+ end
+end
+
+def fun_l4_n0(x)
+ if (x < 1)
+ fun_l5_n524(x)
+ else
+ fun_l5_n284(x)
+ end
+end
+
+def fun_l4_n1(x)
+ if (x < 1)
+ fun_l5_n845(x)
+ else
+ fun_l5_n863(x)
+ end
+end
+
+def fun_l4_n2(x)
+ if (x < 1)
+ fun_l5_n258(x)
+ else
+ fun_l5_n860(x)
+ end
+end
+
+def fun_l4_n3(x)
+ if (x < 1)
+ fun_l5_n253(x)
+ else
+ fun_l5_n763(x)
+ end
+end
+
+def fun_l4_n4(x)
+ if (x < 1)
+ fun_l5_n833(x)
+ else
+ fun_l5_n807(x)
+ end
+end
+
+def fun_l4_n5(x)
+ if (x < 1)
+ fun_l5_n890(x)
+ else
+ fun_l5_n669(x)
+ end
+end
+
+def fun_l4_n6(x)
+ if (x < 1)
+ fun_l5_n396(x)
+ else
+ fun_l5_n388(x)
+ end
+end
+
+def fun_l4_n7(x)
+ if (x < 1)
+ fun_l5_n926(x)
+ else
+ fun_l5_n661(x)
+ end
+end
+
+def fun_l4_n8(x)
+ if (x < 1)
+ fun_l5_n990(x)
+ else
+ fun_l5_n765(x)
+ end
+end
+
+def fun_l4_n9(x)
+ if (x < 1)
+ fun_l5_n978(x)
+ else
+ fun_l5_n342(x)
+ end
+end
+
+def fun_l4_n10(x)
+ if (x < 1)
+ fun_l5_n500(x)
+ else
+ fun_l5_n758(x)
+ end
+end
+
+def fun_l4_n11(x)
+ if (x < 1)
+ fun_l5_n10(x)
+ else
+ fun_l5_n796(x)
+ end
+end
+
+def fun_l4_n12(x)
+ if (x < 1)
+ fun_l5_n173(x)
+ else
+ fun_l5_n87(x)
+ end
+end
+
+def fun_l4_n13(x)
+ if (x < 1)
+ fun_l5_n852(x)
+ else
+ fun_l5_n93(x)
+ end
+end
+
+def fun_l4_n14(x)
+ if (x < 1)
+ fun_l5_n526(x)
+ else
+ fun_l5_n144(x)
+ end
+end
+
+def fun_l4_n15(x)
+ if (x < 1)
+ fun_l5_n398(x)
+ else
+ fun_l5_n632(x)
+ end
+end
+
+def fun_l4_n16(x)
+ if (x < 1)
+ fun_l5_n774(x)
+ else
+ fun_l5_n716(x)
+ end
+end
+
+def fun_l4_n17(x)
+ if (x < 1)
+ fun_l5_n412(x)
+ else
+ fun_l5_n95(x)
+ end
+end
+
+def fun_l4_n18(x)
+ if (x < 1)
+ fun_l5_n446(x)
+ else
+ fun_l5_n885(x)
+ end
+end
+
+def fun_l4_n19(x)
+ if (x < 1)
+ fun_l5_n420(x)
+ else
+ fun_l5_n420(x)
+ end
+end
+
+def fun_l4_n20(x)
+ if (x < 1)
+ fun_l5_n274(x)
+ else
+ fun_l5_n813(x)
+ end
+end
+
+def fun_l4_n21(x)
+ if (x < 1)
+ fun_l5_n174(x)
+ else
+ fun_l5_n781(x)
+ end
+end
+
+def fun_l4_n22(x)
+ if (x < 1)
+ fun_l5_n903(x)
+ else
+ fun_l5_n224(x)
+ end
+end
+
+def fun_l4_n23(x)
+ if (x < 1)
+ fun_l5_n317(x)
+ else
+ fun_l5_n900(x)
+ end
+end
+
+def fun_l4_n24(x)
+ if (x < 1)
+ fun_l5_n600(x)
+ else
+ fun_l5_n515(x)
+ end
+end
+
+def fun_l4_n25(x)
+ if (x < 1)
+ fun_l5_n151(x)
+ else
+ fun_l5_n790(x)
+ end
+end
+
+def fun_l4_n26(x)
+ if (x < 1)
+ fun_l5_n256(x)
+ else
+ fun_l5_n449(x)
+ end
+end
+
+def fun_l4_n27(x)
+ if (x < 1)
+ fun_l5_n985(x)
+ else
+ fun_l5_n763(x)
+ end
+end
+
+def fun_l4_n28(x)
+ if (x < 1)
+ fun_l5_n961(x)
+ else
+ fun_l5_n86(x)
+ end
+end
+
+def fun_l4_n29(x)
+ if (x < 1)
+ fun_l5_n359(x)
+ else
+ fun_l5_n894(x)
+ end
+end
+
+def fun_l4_n30(x)
+ if (x < 1)
+ fun_l5_n426(x)
+ else
+ fun_l5_n983(x)
+ end
+end
+
+def fun_l4_n31(x)
+ if (x < 1)
+ fun_l5_n996(x)
+ else
+ fun_l5_n343(x)
+ end
+end
+
+def fun_l4_n32(x)
+ if (x < 1)
+ fun_l5_n300(x)
+ else
+ fun_l5_n719(x)
+ end
+end
+
+def fun_l4_n33(x)
+ if (x < 1)
+ fun_l5_n755(x)
+ else
+ fun_l5_n623(x)
+ end
+end
+
+def fun_l4_n34(x)
+ if (x < 1)
+ fun_l5_n681(x)
+ else
+ fun_l5_n410(x)
+ end
+end
+
+def fun_l4_n35(x)
+ if (x < 1)
+ fun_l5_n356(x)
+ else
+ fun_l5_n351(x)
+ end
+end
+
+def fun_l4_n36(x)
+ if (x < 1)
+ fun_l5_n463(x)
+ else
+ fun_l5_n402(x)
+ end
+end
+
+def fun_l4_n37(x)
+ if (x < 1)
+ fun_l5_n250(x)
+ else
+ fun_l5_n681(x)
+ end
+end
+
+def fun_l4_n38(x)
+ if (x < 1)
+ fun_l5_n573(x)
+ else
+ fun_l5_n622(x)
+ end
+end
+
+def fun_l4_n39(x)
+ if (x < 1)
+ fun_l5_n545(x)
+ else
+ fun_l5_n210(x)
+ end
+end
+
+def fun_l4_n40(x)
+ if (x < 1)
+ fun_l5_n264(x)
+ else
+ fun_l5_n239(x)
+ end
+end
+
+def fun_l4_n41(x)
+ if (x < 1)
+ fun_l5_n635(x)
+ else
+ fun_l5_n224(x)
+ end
+end
+
+def fun_l4_n42(x)
+ if (x < 1)
+ fun_l5_n806(x)
+ else
+ fun_l5_n125(x)
+ end
+end
+
+def fun_l4_n43(x)
+ if (x < 1)
+ fun_l5_n480(x)
+ else
+ fun_l5_n625(x)
+ end
+end
+
+def fun_l4_n44(x)
+ if (x < 1)
+ fun_l5_n644(x)
+ else
+ fun_l5_n465(x)
+ end
+end
+
+def fun_l4_n45(x)
+ if (x < 1)
+ fun_l5_n999(x)
+ else
+ fun_l5_n759(x)
+ end
+end
+
+def fun_l4_n46(x)
+ if (x < 1)
+ fun_l5_n866(x)
+ else
+ fun_l5_n536(x)
+ end
+end
+
+def fun_l4_n47(x)
+ if (x < 1)
+ fun_l5_n328(x)
+ else
+ fun_l5_n533(x)
+ end
+end
+
+def fun_l4_n48(x)
+ if (x < 1)
+ fun_l5_n902(x)
+ else
+ fun_l5_n919(x)
+ end
+end
+
+def fun_l4_n49(x)
+ if (x < 1)
+ fun_l5_n197(x)
+ else
+ fun_l5_n262(x)
+ end
+end
+
+def fun_l4_n50(x)
+ if (x < 1)
+ fun_l5_n172(x)
+ else
+ fun_l5_n731(x)
+ end
+end
+
+def fun_l4_n51(x)
+ if (x < 1)
+ fun_l5_n502(x)
+ else
+ fun_l5_n149(x)
+ end
+end
+
+def fun_l4_n52(x)
+ if (x < 1)
+ fun_l5_n69(x)
+ else
+ fun_l5_n536(x)
+ end
+end
+
+def fun_l4_n53(x)
+ if (x < 1)
+ fun_l5_n932(x)
+ else
+ fun_l5_n482(x)
+ end
+end
+
+def fun_l4_n54(x)
+ if (x < 1)
+ fun_l5_n982(x)
+ else
+ fun_l5_n207(x)
+ end
+end
+
+def fun_l4_n55(x)
+ if (x < 1)
+ fun_l5_n949(x)
+ else
+ fun_l5_n9(x)
+ end
+end
+
+def fun_l4_n56(x)
+ if (x < 1)
+ fun_l5_n672(x)
+ else
+ fun_l5_n924(x)
+ end
+end
+
+def fun_l4_n57(x)
+ if (x < 1)
+ fun_l5_n757(x)
+ else
+ fun_l5_n609(x)
+ end
+end
+
+def fun_l4_n58(x)
+ if (x < 1)
+ fun_l5_n251(x)
+ else
+ fun_l5_n471(x)
+ end
+end
+
+def fun_l4_n59(x)
+ if (x < 1)
+ fun_l5_n878(x)
+ else
+ fun_l5_n626(x)
+ end
+end
+
+def fun_l4_n60(x)
+ if (x < 1)
+ fun_l5_n859(x)
+ else
+ fun_l5_n646(x)
+ end
+end
+
+def fun_l4_n61(x)
+ if (x < 1)
+ fun_l5_n417(x)
+ else
+ fun_l5_n587(x)
+ end
+end
+
+def fun_l4_n62(x)
+ if (x < 1)
+ fun_l5_n164(x)
+ else
+ fun_l5_n861(x)
+ end
+end
+
+def fun_l4_n63(x)
+ if (x < 1)
+ fun_l5_n591(x)
+ else
+ fun_l5_n79(x)
+ end
+end
+
+def fun_l4_n64(x)
+ if (x < 1)
+ fun_l5_n269(x)
+ else
+ fun_l5_n336(x)
+ end
+end
+
+def fun_l4_n65(x)
+ if (x < 1)
+ fun_l5_n420(x)
+ else
+ fun_l5_n557(x)
+ end
+end
+
+def fun_l4_n66(x)
+ if (x < 1)
+ fun_l5_n61(x)
+ else
+ fun_l5_n690(x)
+ end
+end
+
+def fun_l4_n67(x)
+ if (x < 1)
+ fun_l5_n939(x)
+ else
+ fun_l5_n139(x)
+ end
+end
+
+def fun_l4_n68(x)
+ if (x < 1)
+ fun_l5_n430(x)
+ else
+ fun_l5_n625(x)
+ end
+end
+
+def fun_l4_n69(x)
+ if (x < 1)
+ fun_l5_n532(x)
+ else
+ fun_l5_n909(x)
+ end
+end
+
+def fun_l4_n70(x)
+ if (x < 1)
+ fun_l5_n937(x)
+ else
+ fun_l5_n886(x)
+ end
+end
+
+def fun_l4_n71(x)
+ if (x < 1)
+ fun_l5_n554(x)
+ else
+ fun_l5_n898(x)
+ end
+end
+
+def fun_l4_n72(x)
+ if (x < 1)
+ fun_l5_n390(x)
+ else
+ fun_l5_n690(x)
+ end
+end
+
+def fun_l4_n73(x)
+ if (x < 1)
+ fun_l5_n980(x)
+ else
+ fun_l5_n248(x)
+ end
+end
+
+def fun_l4_n74(x)
+ if (x < 1)
+ fun_l5_n438(x)
+ else
+ fun_l5_n247(x)
+ end
+end
+
+def fun_l4_n75(x)
+ if (x < 1)
+ fun_l5_n798(x)
+ else
+ fun_l5_n399(x)
+ end
+end
+
+def fun_l4_n76(x)
+ if (x < 1)
+ fun_l5_n419(x)
+ else
+ fun_l5_n754(x)
+ end
+end
+
+def fun_l4_n77(x)
+ if (x < 1)
+ fun_l5_n875(x)
+ else
+ fun_l5_n18(x)
+ end
+end
+
+def fun_l4_n78(x)
+ if (x < 1)
+ fun_l5_n695(x)
+ else
+ fun_l5_n336(x)
+ end
+end
+
+def fun_l4_n79(x)
+ if (x < 1)
+ fun_l5_n185(x)
+ else
+ fun_l5_n627(x)
+ end
+end
+
+def fun_l4_n80(x)
+ if (x < 1)
+ fun_l5_n359(x)
+ else
+ fun_l5_n465(x)
+ end
+end
+
+def fun_l4_n81(x)
+ if (x < 1)
+ fun_l5_n284(x)
+ else
+ fun_l5_n232(x)
+ end
+end
+
+def fun_l4_n82(x)
+ if (x < 1)
+ fun_l5_n947(x)
+ else
+ fun_l5_n748(x)
+ end
+end
+
+def fun_l4_n83(x)
+ if (x < 1)
+ fun_l5_n254(x)
+ else
+ fun_l5_n836(x)
+ end
+end
+
+def fun_l4_n84(x)
+ if (x < 1)
+ fun_l5_n181(x)
+ else
+ fun_l5_n789(x)
+ end
+end
+
+def fun_l4_n85(x)
+ if (x < 1)
+ fun_l5_n682(x)
+ else
+ fun_l5_n547(x)
+ end
+end
+
+def fun_l4_n86(x)
+ if (x < 1)
+ fun_l5_n35(x)
+ else
+ fun_l5_n157(x)
+ end
+end
+
+def fun_l4_n87(x)
+ if (x < 1)
+ fun_l5_n981(x)
+ else
+ fun_l5_n724(x)
+ end
+end
+
+def fun_l4_n88(x)
+ if (x < 1)
+ fun_l5_n35(x)
+ else
+ fun_l5_n914(x)
+ end
+end
+
+def fun_l4_n89(x)
+ if (x < 1)
+ fun_l5_n844(x)
+ else
+ fun_l5_n668(x)
+ end
+end
+
+def fun_l4_n90(x)
+ if (x < 1)
+ fun_l5_n615(x)
+ else
+ fun_l5_n415(x)
+ end
+end
+
+def fun_l4_n91(x)
+ if (x < 1)
+ fun_l5_n141(x)
+ else
+ fun_l5_n538(x)
+ end
+end
+
+def fun_l4_n92(x)
+ if (x < 1)
+ fun_l5_n563(x)
+ else
+ fun_l5_n60(x)
+ end
+end
+
+def fun_l4_n93(x)
+ if (x < 1)
+ fun_l5_n967(x)
+ else
+ fun_l5_n549(x)
+ end
+end
+
+def fun_l4_n94(x)
+ if (x < 1)
+ fun_l5_n992(x)
+ else
+ fun_l5_n34(x)
+ end
+end
+
+def fun_l4_n95(x)
+ if (x < 1)
+ fun_l5_n187(x)
+ else
+ fun_l5_n980(x)
+ end
+end
+
+def fun_l4_n96(x)
+ if (x < 1)
+ fun_l5_n543(x)
+ else
+ fun_l5_n318(x)
+ end
+end
+
+def fun_l4_n97(x)
+ if (x < 1)
+ fun_l5_n253(x)
+ else
+ fun_l5_n709(x)
+ end
+end
+
+def fun_l4_n98(x)
+ if (x < 1)
+ fun_l5_n233(x)
+ else
+ fun_l5_n963(x)
+ end
+end
+
+def fun_l4_n99(x)
+ if (x < 1)
+ fun_l5_n944(x)
+ else
+ fun_l5_n688(x)
+ end
+end
+
+def fun_l4_n100(x)
+ if (x < 1)
+ fun_l5_n422(x)
+ else
+ fun_l5_n805(x)
+ end
+end
+
+def fun_l4_n101(x)
+ if (x < 1)
+ fun_l5_n125(x)
+ else
+ fun_l5_n729(x)
+ end
+end
+
+def fun_l4_n102(x)
+ if (x < 1)
+ fun_l5_n339(x)
+ else
+ fun_l5_n394(x)
+ end
+end
+
+def fun_l4_n103(x)
+ if (x < 1)
+ fun_l5_n149(x)
+ else
+ fun_l5_n839(x)
+ end
+end
+
+def fun_l4_n104(x)
+ if (x < 1)
+ fun_l5_n750(x)
+ else
+ fun_l5_n514(x)
+ end
+end
+
+def fun_l4_n105(x)
+ if (x < 1)
+ fun_l5_n726(x)
+ else
+ fun_l5_n251(x)
+ end
+end
+
+def fun_l4_n106(x)
+ if (x < 1)
+ fun_l5_n810(x)
+ else
+ fun_l5_n46(x)
+ end
+end
+
+def fun_l4_n107(x)
+ if (x < 1)
+ fun_l5_n702(x)
+ else
+ fun_l5_n224(x)
+ end
+end
+
+def fun_l4_n108(x)
+ if (x < 1)
+ fun_l5_n604(x)
+ else
+ fun_l5_n24(x)
+ end
+end
+
+def fun_l4_n109(x)
+ if (x < 1)
+ fun_l5_n511(x)
+ else
+ fun_l5_n529(x)
+ end
+end
+
+def fun_l4_n110(x)
+ if (x < 1)
+ fun_l5_n193(x)
+ else
+ fun_l5_n210(x)
+ end
+end
+
+def fun_l4_n111(x)
+ if (x < 1)
+ fun_l5_n599(x)
+ else
+ fun_l5_n85(x)
+ end
+end
+
+def fun_l4_n112(x)
+ if (x < 1)
+ fun_l5_n910(x)
+ else
+ fun_l5_n292(x)
+ end
+end
+
+def fun_l4_n113(x)
+ if (x < 1)
+ fun_l5_n851(x)
+ else
+ fun_l5_n269(x)
+ end
+end
+
+def fun_l4_n114(x)
+ if (x < 1)
+ fun_l5_n739(x)
+ else
+ fun_l5_n439(x)
+ end
+end
+
+def fun_l4_n115(x)
+ if (x < 1)
+ fun_l5_n580(x)
+ else
+ fun_l5_n656(x)
+ end
+end
+
+def fun_l4_n116(x)
+ if (x < 1)
+ fun_l5_n992(x)
+ else
+ fun_l5_n703(x)
+ end
+end
+
+def fun_l4_n117(x)
+ if (x < 1)
+ fun_l5_n549(x)
+ else
+ fun_l5_n300(x)
+ end
+end
+
+def fun_l4_n118(x)
+ if (x < 1)
+ fun_l5_n785(x)
+ else
+ fun_l5_n596(x)
+ end
+end
+
+def fun_l4_n119(x)
+ if (x < 1)
+ fun_l5_n236(x)
+ else
+ fun_l5_n84(x)
+ end
+end
+
+def fun_l4_n120(x)
+ if (x < 1)
+ fun_l5_n78(x)
+ else
+ fun_l5_n610(x)
+ end
+end
+
+def fun_l4_n121(x)
+ if (x < 1)
+ fun_l5_n591(x)
+ else
+ fun_l5_n557(x)
+ end
+end
+
+def fun_l4_n122(x)
+ if (x < 1)
+ fun_l5_n927(x)
+ else
+ fun_l5_n40(x)
+ end
+end
+
+def fun_l4_n123(x)
+ if (x < 1)
+ fun_l5_n620(x)
+ else
+ fun_l5_n173(x)
+ end
+end
+
+def fun_l4_n124(x)
+ if (x < 1)
+ fun_l5_n558(x)
+ else
+ fun_l5_n330(x)
+ end
+end
+
+def fun_l4_n125(x)
+ if (x < 1)
+ fun_l5_n535(x)
+ else
+ fun_l5_n636(x)
+ end
+end
+
+def fun_l4_n126(x)
+ if (x < 1)
+ fun_l5_n401(x)
+ else
+ fun_l5_n747(x)
+ end
+end
+
+def fun_l4_n127(x)
+ if (x < 1)
+ fun_l5_n172(x)
+ else
+ fun_l5_n124(x)
+ end
+end
+
+def fun_l4_n128(x)
+ if (x < 1)
+ fun_l5_n449(x)
+ else
+ fun_l5_n619(x)
+ end
+end
+
+def fun_l4_n129(x)
+ if (x < 1)
+ fun_l5_n564(x)
+ else
+ fun_l5_n306(x)
+ end
+end
+
+def fun_l4_n130(x)
+ if (x < 1)
+ fun_l5_n196(x)
+ else
+ fun_l5_n170(x)
+ end
+end
+
+def fun_l4_n131(x)
+ if (x < 1)
+ fun_l5_n383(x)
+ else
+ fun_l5_n87(x)
+ end
+end
+
+def fun_l4_n132(x)
+ if (x < 1)
+ fun_l5_n568(x)
+ else
+ fun_l5_n54(x)
+ end
+end
+
+def fun_l4_n133(x)
+ if (x < 1)
+ fun_l5_n780(x)
+ else
+ fun_l5_n184(x)
+ end
+end
+
+def fun_l4_n134(x)
+ if (x < 1)
+ fun_l5_n880(x)
+ else
+ fun_l5_n38(x)
+ end
+end
+
+def fun_l4_n135(x)
+ if (x < 1)
+ fun_l5_n819(x)
+ else
+ fun_l5_n440(x)
+ end
+end
+
+def fun_l4_n136(x)
+ if (x < 1)
+ fun_l5_n301(x)
+ else
+ fun_l5_n676(x)
+ end
+end
+
+def fun_l4_n137(x)
+ if (x < 1)
+ fun_l5_n69(x)
+ else
+ fun_l5_n333(x)
+ end
+end
+
+def fun_l4_n138(x)
+ if (x < 1)
+ fun_l5_n303(x)
+ else
+ fun_l5_n69(x)
+ end
+end
+
+def fun_l4_n139(x)
+ if (x < 1)
+ fun_l5_n939(x)
+ else
+ fun_l5_n103(x)
+ end
+end
+
+def fun_l4_n140(x)
+ if (x < 1)
+ fun_l5_n517(x)
+ else
+ fun_l5_n24(x)
+ end
+end
+
+def fun_l4_n141(x)
+ if (x < 1)
+ fun_l5_n923(x)
+ else
+ fun_l5_n968(x)
+ end
+end
+
+def fun_l4_n142(x)
+ if (x < 1)
+ fun_l5_n196(x)
+ else
+ fun_l5_n841(x)
+ end
+end
+
+def fun_l4_n143(x)
+ if (x < 1)
+ fun_l5_n726(x)
+ else
+ fun_l5_n715(x)
+ end
+end
+
+def fun_l4_n144(x)
+ if (x < 1)
+ fun_l5_n434(x)
+ else
+ fun_l5_n771(x)
+ end
+end
+
+def fun_l4_n145(x)
+ if (x < 1)
+ fun_l5_n211(x)
+ else
+ fun_l5_n963(x)
+ end
+end
+
+def fun_l4_n146(x)
+ if (x < 1)
+ fun_l5_n534(x)
+ else
+ fun_l5_n5(x)
+ end
+end
+
+def fun_l4_n147(x)
+ if (x < 1)
+ fun_l5_n409(x)
+ else
+ fun_l5_n298(x)
+ end
+end
+
+def fun_l4_n148(x)
+ if (x < 1)
+ fun_l5_n447(x)
+ else
+ fun_l5_n474(x)
+ end
+end
+
+def fun_l4_n149(x)
+ if (x < 1)
+ fun_l5_n181(x)
+ else
+ fun_l5_n87(x)
+ end
+end
+
+def fun_l4_n150(x)
+ if (x < 1)
+ fun_l5_n871(x)
+ else
+ fun_l5_n201(x)
+ end
+end
+
+def fun_l4_n151(x)
+ if (x < 1)
+ fun_l5_n539(x)
+ else
+ fun_l5_n855(x)
+ end
+end
+
+def fun_l4_n152(x)
+ if (x < 1)
+ fun_l5_n387(x)
+ else
+ fun_l5_n730(x)
+ end
+end
+
+def fun_l4_n153(x)
+ if (x < 1)
+ fun_l5_n785(x)
+ else
+ fun_l5_n774(x)
+ end
+end
+
+def fun_l4_n154(x)
+ if (x < 1)
+ fun_l5_n924(x)
+ else
+ fun_l5_n414(x)
+ end
+end
+
+def fun_l4_n155(x)
+ if (x < 1)
+ fun_l5_n110(x)
+ else
+ fun_l5_n669(x)
+ end
+end
+
+def fun_l4_n156(x)
+ if (x < 1)
+ fun_l5_n551(x)
+ else
+ fun_l5_n456(x)
+ end
+end
+
+def fun_l4_n157(x)
+ if (x < 1)
+ fun_l5_n872(x)
+ else
+ fun_l5_n397(x)
+ end
+end
+
+def fun_l4_n158(x)
+ if (x < 1)
+ fun_l5_n208(x)
+ else
+ fun_l5_n464(x)
+ end
+end
+
+def fun_l4_n159(x)
+ if (x < 1)
+ fun_l5_n236(x)
+ else
+ fun_l5_n532(x)
+ end
+end
+
+def fun_l4_n160(x)
+ if (x < 1)
+ fun_l5_n820(x)
+ else
+ fun_l5_n146(x)
+ end
+end
+
+def fun_l4_n161(x)
+ if (x < 1)
+ fun_l5_n154(x)
+ else
+ fun_l5_n388(x)
+ end
+end
+
+def fun_l4_n162(x)
+ if (x < 1)
+ fun_l5_n456(x)
+ else
+ fun_l5_n309(x)
+ end
+end
+
+def fun_l4_n163(x)
+ if (x < 1)
+ fun_l5_n201(x)
+ else
+ fun_l5_n728(x)
+ end
+end
+
+def fun_l4_n164(x)
+ if (x < 1)
+ fun_l5_n806(x)
+ else
+ fun_l5_n156(x)
+ end
+end
+
+def fun_l4_n165(x)
+ if (x < 1)
+ fun_l5_n984(x)
+ else
+ fun_l5_n996(x)
+ end
+end
+
+def fun_l4_n166(x)
+ if (x < 1)
+ fun_l5_n253(x)
+ else
+ fun_l5_n527(x)
+ end
+end
+
+def fun_l4_n167(x)
+ if (x < 1)
+ fun_l5_n513(x)
+ else
+ fun_l5_n145(x)
+ end
+end
+
+def fun_l4_n168(x)
+ if (x < 1)
+ fun_l5_n694(x)
+ else
+ fun_l5_n841(x)
+ end
+end
+
+def fun_l4_n169(x)
+ if (x < 1)
+ fun_l5_n463(x)
+ else
+ fun_l5_n193(x)
+ end
+end
+
+def fun_l4_n170(x)
+ if (x < 1)
+ fun_l5_n638(x)
+ else
+ fun_l5_n252(x)
+ end
+end
+
+def fun_l4_n171(x)
+ if (x < 1)
+ fun_l5_n166(x)
+ else
+ fun_l5_n134(x)
+ end
+end
+
+def fun_l4_n172(x)
+ if (x < 1)
+ fun_l5_n172(x)
+ else
+ fun_l5_n179(x)
+ end
+end
+
+def fun_l4_n173(x)
+ if (x < 1)
+ fun_l5_n218(x)
+ else
+ fun_l5_n124(x)
+ end
+end
+
+def fun_l4_n174(x)
+ if (x < 1)
+ fun_l5_n370(x)
+ else
+ fun_l5_n742(x)
+ end
+end
+
+def fun_l4_n175(x)
+ if (x < 1)
+ fun_l5_n593(x)
+ else
+ fun_l5_n542(x)
+ end
+end
+
+def fun_l4_n176(x)
+ if (x < 1)
+ fun_l5_n438(x)
+ else
+ fun_l5_n606(x)
+ end
+end
+
+def fun_l4_n177(x)
+ if (x < 1)
+ fun_l5_n316(x)
+ else
+ fun_l5_n92(x)
+ end
+end
+
+def fun_l4_n178(x)
+ if (x < 1)
+ fun_l5_n222(x)
+ else
+ fun_l5_n461(x)
+ end
+end
+
+def fun_l4_n179(x)
+ if (x < 1)
+ fun_l5_n244(x)
+ else
+ fun_l5_n536(x)
+ end
+end
+
+def fun_l4_n180(x)
+ if (x < 1)
+ fun_l5_n120(x)
+ else
+ fun_l5_n905(x)
+ end
+end
+
+def fun_l4_n181(x)
+ if (x < 1)
+ fun_l5_n601(x)
+ else
+ fun_l5_n62(x)
+ end
+end
+
+def fun_l4_n182(x)
+ if (x < 1)
+ fun_l5_n701(x)
+ else
+ fun_l5_n25(x)
+ end
+end
+
+def fun_l4_n183(x)
+ if (x < 1)
+ fun_l5_n361(x)
+ else
+ fun_l5_n433(x)
+ end
+end
+
+def fun_l4_n184(x)
+ if (x < 1)
+ fun_l5_n29(x)
+ else
+ fun_l5_n302(x)
+ end
+end
+
+def fun_l4_n185(x)
+ if (x < 1)
+ fun_l5_n697(x)
+ else
+ fun_l5_n849(x)
+ end
+end
+
+def fun_l4_n186(x)
+ if (x < 1)
+ fun_l5_n76(x)
+ else
+ fun_l5_n402(x)
+ end
+end
+
+def fun_l4_n187(x)
+ if (x < 1)
+ fun_l5_n38(x)
+ else
+ fun_l5_n818(x)
+ end
+end
+
+def fun_l4_n188(x)
+ if (x < 1)
+ fun_l5_n730(x)
+ else
+ fun_l5_n456(x)
+ end
+end
+
+def fun_l4_n189(x)
+ if (x < 1)
+ fun_l5_n828(x)
+ else
+ fun_l5_n796(x)
+ end
+end
+
+def fun_l4_n190(x)
+ if (x < 1)
+ fun_l5_n86(x)
+ else
+ fun_l5_n976(x)
+ end
+end
+
+def fun_l4_n191(x)
+ if (x < 1)
+ fun_l5_n267(x)
+ else
+ fun_l5_n497(x)
+ end
+end
+
+def fun_l4_n192(x)
+ if (x < 1)
+ fun_l5_n534(x)
+ else
+ fun_l5_n449(x)
+ end
+end
+
+def fun_l4_n193(x)
+ if (x < 1)
+ fun_l5_n97(x)
+ else
+ fun_l5_n595(x)
+ end
+end
+
+def fun_l4_n194(x)
+ if (x < 1)
+ fun_l5_n821(x)
+ else
+ fun_l5_n823(x)
+ end
+end
+
+def fun_l4_n195(x)
+ if (x < 1)
+ fun_l5_n936(x)
+ else
+ fun_l5_n490(x)
+ end
+end
+
+def fun_l4_n196(x)
+ if (x < 1)
+ fun_l5_n579(x)
+ else
+ fun_l5_n684(x)
+ end
+end
+
+def fun_l4_n197(x)
+ if (x < 1)
+ fun_l5_n742(x)
+ else
+ fun_l5_n874(x)
+ end
+end
+
+def fun_l4_n198(x)
+ if (x < 1)
+ fun_l5_n904(x)
+ else
+ fun_l5_n394(x)
+ end
+end
+
+def fun_l4_n199(x)
+ if (x < 1)
+ fun_l5_n229(x)
+ else
+ fun_l5_n406(x)
+ end
+end
+
+def fun_l4_n200(x)
+ if (x < 1)
+ fun_l5_n332(x)
+ else
+ fun_l5_n803(x)
+ end
+end
+
+def fun_l4_n201(x)
+ if (x < 1)
+ fun_l5_n635(x)
+ else
+ fun_l5_n294(x)
+ end
+end
+
+def fun_l4_n202(x)
+ if (x < 1)
+ fun_l5_n397(x)
+ else
+ fun_l5_n924(x)
+ end
+end
+
+def fun_l4_n203(x)
+ if (x < 1)
+ fun_l5_n199(x)
+ else
+ fun_l5_n751(x)
+ end
+end
+
+def fun_l4_n204(x)
+ if (x < 1)
+ fun_l5_n570(x)
+ else
+ fun_l5_n70(x)
+ end
+end
+
+def fun_l4_n205(x)
+ if (x < 1)
+ fun_l5_n344(x)
+ else
+ fun_l5_n713(x)
+ end
+end
+
+def fun_l4_n206(x)
+ if (x < 1)
+ fun_l5_n568(x)
+ else
+ fun_l5_n40(x)
+ end
+end
+
+def fun_l4_n207(x)
+ if (x < 1)
+ fun_l5_n460(x)
+ else
+ fun_l5_n311(x)
+ end
+end
+
+def fun_l4_n208(x)
+ if (x < 1)
+ fun_l5_n995(x)
+ else
+ fun_l5_n147(x)
+ end
+end
+
+def fun_l4_n209(x)
+ if (x < 1)
+ fun_l5_n295(x)
+ else
+ fun_l5_n752(x)
+ end
+end
+
+def fun_l4_n210(x)
+ if (x < 1)
+ fun_l5_n644(x)
+ else
+ fun_l5_n555(x)
+ end
+end
+
+def fun_l4_n211(x)
+ if (x < 1)
+ fun_l5_n196(x)
+ else
+ fun_l5_n418(x)
+ end
+end
+
+def fun_l4_n212(x)
+ if (x < 1)
+ fun_l5_n761(x)
+ else
+ fun_l5_n66(x)
+ end
+end
+
+def fun_l4_n213(x)
+ if (x < 1)
+ fun_l5_n906(x)
+ else
+ fun_l5_n521(x)
+ end
+end
+
+def fun_l4_n214(x)
+ if (x < 1)
+ fun_l5_n97(x)
+ else
+ fun_l5_n431(x)
+ end
+end
+
+def fun_l4_n215(x)
+ if (x < 1)
+ fun_l5_n450(x)
+ else
+ fun_l5_n58(x)
+ end
+end
+
+def fun_l4_n216(x)
+ if (x < 1)
+ fun_l5_n576(x)
+ else
+ fun_l5_n675(x)
+ end
+end
+
+def fun_l4_n217(x)
+ if (x < 1)
+ fun_l5_n764(x)
+ else
+ fun_l5_n653(x)
+ end
+end
+
+def fun_l4_n218(x)
+ if (x < 1)
+ fun_l5_n591(x)
+ else
+ fun_l5_n398(x)
+ end
+end
+
+def fun_l4_n219(x)
+ if (x < 1)
+ fun_l5_n94(x)
+ else
+ fun_l5_n411(x)
+ end
+end
+
+def fun_l4_n220(x)
+ if (x < 1)
+ fun_l5_n13(x)
+ else
+ fun_l5_n117(x)
+ end
+end
+
+def fun_l4_n221(x)
+ if (x < 1)
+ fun_l5_n872(x)
+ else
+ fun_l5_n799(x)
+ end
+end
+
+def fun_l4_n222(x)
+ if (x < 1)
+ fun_l5_n692(x)
+ else
+ fun_l5_n99(x)
+ end
+end
+
+def fun_l4_n223(x)
+ if (x < 1)
+ fun_l5_n861(x)
+ else
+ fun_l5_n999(x)
+ end
+end
+
+def fun_l4_n224(x)
+ if (x < 1)
+ fun_l5_n547(x)
+ else
+ fun_l5_n955(x)
+ end
+end
+
+def fun_l4_n225(x)
+ if (x < 1)
+ fun_l5_n305(x)
+ else
+ fun_l5_n894(x)
+ end
+end
+
+def fun_l4_n226(x)
+ if (x < 1)
+ fun_l5_n128(x)
+ else
+ fun_l5_n662(x)
+ end
+end
+
+def fun_l4_n227(x)
+ if (x < 1)
+ fun_l5_n858(x)
+ else
+ fun_l5_n323(x)
+ end
+end
+
+def fun_l4_n228(x)
+ if (x < 1)
+ fun_l5_n923(x)
+ else
+ fun_l5_n206(x)
+ end
+end
+
+def fun_l4_n229(x)
+ if (x < 1)
+ fun_l5_n486(x)
+ else
+ fun_l5_n603(x)
+ end
+end
+
+def fun_l4_n230(x)
+ if (x < 1)
+ fun_l5_n116(x)
+ else
+ fun_l5_n887(x)
+ end
+end
+
+def fun_l4_n231(x)
+ if (x < 1)
+ fun_l5_n791(x)
+ else
+ fun_l5_n762(x)
+ end
+end
+
+def fun_l4_n232(x)
+ if (x < 1)
+ fun_l5_n511(x)
+ else
+ fun_l5_n890(x)
+ end
+end
+
+def fun_l4_n233(x)
+ if (x < 1)
+ fun_l5_n600(x)
+ else
+ fun_l5_n777(x)
+ end
+end
+
+def fun_l4_n234(x)
+ if (x < 1)
+ fun_l5_n458(x)
+ else
+ fun_l5_n379(x)
+ end
+end
+
+def fun_l4_n235(x)
+ if (x < 1)
+ fun_l5_n907(x)
+ else
+ fun_l5_n463(x)
+ end
+end
+
+def fun_l4_n236(x)
+ if (x < 1)
+ fun_l5_n177(x)
+ else
+ fun_l5_n732(x)
+ end
+end
+
+def fun_l4_n237(x)
+ if (x < 1)
+ fun_l5_n761(x)
+ else
+ fun_l5_n936(x)
+ end
+end
+
+def fun_l4_n238(x)
+ if (x < 1)
+ fun_l5_n757(x)
+ else
+ fun_l5_n733(x)
+ end
+end
+
+def fun_l4_n239(x)
+ if (x < 1)
+ fun_l5_n844(x)
+ else
+ fun_l5_n527(x)
+ end
+end
+
+def fun_l4_n240(x)
+ if (x < 1)
+ fun_l5_n594(x)
+ else
+ fun_l5_n620(x)
+ end
+end
+
+def fun_l4_n241(x)
+ if (x < 1)
+ fun_l5_n722(x)
+ else
+ fun_l5_n779(x)
+ end
+end
+
+def fun_l4_n242(x)
+ if (x < 1)
+ fun_l5_n663(x)
+ else
+ fun_l5_n237(x)
+ end
+end
+
+def fun_l4_n243(x)
+ if (x < 1)
+ fun_l5_n256(x)
+ else
+ fun_l5_n366(x)
+ end
+end
+
+def fun_l4_n244(x)
+ if (x < 1)
+ fun_l5_n614(x)
+ else
+ fun_l5_n895(x)
+ end
+end
+
+def fun_l4_n245(x)
+ if (x < 1)
+ fun_l5_n459(x)
+ else
+ fun_l5_n193(x)
+ end
+end
+
+def fun_l4_n246(x)
+ if (x < 1)
+ fun_l5_n780(x)
+ else
+ fun_l5_n175(x)
+ end
+end
+
+def fun_l4_n247(x)
+ if (x < 1)
+ fun_l5_n186(x)
+ else
+ fun_l5_n488(x)
+ end
+end
+
+def fun_l4_n248(x)
+ if (x < 1)
+ fun_l5_n156(x)
+ else
+ fun_l5_n807(x)
+ end
+end
+
+def fun_l4_n249(x)
+ if (x < 1)
+ fun_l5_n862(x)
+ else
+ fun_l5_n537(x)
+ end
+end
+
+def fun_l4_n250(x)
+ if (x < 1)
+ fun_l5_n880(x)
+ else
+ fun_l5_n528(x)
+ end
+end
+
+def fun_l4_n251(x)
+ if (x < 1)
+ fun_l5_n163(x)
+ else
+ fun_l5_n94(x)
+ end
+end
+
+def fun_l4_n252(x)
+ if (x < 1)
+ fun_l5_n937(x)
+ else
+ fun_l5_n582(x)
+ end
+end
+
+def fun_l4_n253(x)
+ if (x < 1)
+ fun_l5_n368(x)
+ else
+ fun_l5_n584(x)
+ end
+end
+
+def fun_l4_n254(x)
+ if (x < 1)
+ fun_l5_n566(x)
+ else
+ fun_l5_n449(x)
+ end
+end
+
+def fun_l4_n255(x)
+ if (x < 1)
+ fun_l5_n876(x)
+ else
+ fun_l5_n0(x)
+ end
+end
+
+def fun_l4_n256(x)
+ if (x < 1)
+ fun_l5_n842(x)
+ else
+ fun_l5_n469(x)
+ end
+end
+
+def fun_l4_n257(x)
+ if (x < 1)
+ fun_l5_n85(x)
+ else
+ fun_l5_n961(x)
+ end
+end
+
+def fun_l4_n258(x)
+ if (x < 1)
+ fun_l5_n120(x)
+ else
+ fun_l5_n893(x)
+ end
+end
+
+def fun_l4_n259(x)
+ if (x < 1)
+ fun_l5_n243(x)
+ else
+ fun_l5_n630(x)
+ end
+end
+
+def fun_l4_n260(x)
+ if (x < 1)
+ fun_l5_n710(x)
+ else
+ fun_l5_n715(x)
+ end
+end
+
+def fun_l4_n261(x)
+ if (x < 1)
+ fun_l5_n423(x)
+ else
+ fun_l5_n910(x)
+ end
+end
+
+def fun_l4_n262(x)
+ if (x < 1)
+ fun_l5_n505(x)
+ else
+ fun_l5_n532(x)
+ end
+end
+
+def fun_l4_n263(x)
+ if (x < 1)
+ fun_l5_n775(x)
+ else
+ fun_l5_n236(x)
+ end
+end
+
+def fun_l4_n264(x)
+ if (x < 1)
+ fun_l5_n140(x)
+ else
+ fun_l5_n295(x)
+ end
+end
+
+def fun_l4_n265(x)
+ if (x < 1)
+ fun_l5_n554(x)
+ else
+ fun_l5_n88(x)
+ end
+end
+
+def fun_l4_n266(x)
+ if (x < 1)
+ fun_l5_n831(x)
+ else
+ fun_l5_n307(x)
+ end
+end
+
+def fun_l4_n267(x)
+ if (x < 1)
+ fun_l5_n303(x)
+ else
+ fun_l5_n960(x)
+ end
+end
+
+def fun_l4_n268(x)
+ if (x < 1)
+ fun_l5_n322(x)
+ else
+ fun_l5_n264(x)
+ end
+end
+
+def fun_l4_n269(x)
+ if (x < 1)
+ fun_l5_n823(x)
+ else
+ fun_l5_n374(x)
+ end
+end
+
+def fun_l4_n270(x)
+ if (x < 1)
+ fun_l5_n76(x)
+ else
+ fun_l5_n918(x)
+ end
+end
+
+def fun_l4_n271(x)
+ if (x < 1)
+ fun_l5_n591(x)
+ else
+ fun_l5_n45(x)
+ end
+end
+
+def fun_l4_n272(x)
+ if (x < 1)
+ fun_l5_n686(x)
+ else
+ fun_l5_n836(x)
+ end
+end
+
+def fun_l4_n273(x)
+ if (x < 1)
+ fun_l5_n13(x)
+ else
+ fun_l5_n676(x)
+ end
+end
+
+def fun_l4_n274(x)
+ if (x < 1)
+ fun_l5_n120(x)
+ else
+ fun_l5_n180(x)
+ end
+end
+
+def fun_l4_n275(x)
+ if (x < 1)
+ fun_l5_n901(x)
+ else
+ fun_l5_n101(x)
+ end
+end
+
+def fun_l4_n276(x)
+ if (x < 1)
+ fun_l5_n289(x)
+ else
+ fun_l5_n238(x)
+ end
+end
+
+def fun_l4_n277(x)
+ if (x < 1)
+ fun_l5_n513(x)
+ else
+ fun_l5_n887(x)
+ end
+end
+
+def fun_l4_n278(x)
+ if (x < 1)
+ fun_l5_n799(x)
+ else
+ fun_l5_n763(x)
+ end
+end
+
+def fun_l4_n279(x)
+ if (x < 1)
+ fun_l5_n628(x)
+ else
+ fun_l5_n373(x)
+ end
+end
+
+def fun_l4_n280(x)
+ if (x < 1)
+ fun_l5_n661(x)
+ else
+ fun_l5_n826(x)
+ end
+end
+
+def fun_l4_n281(x)
+ if (x < 1)
+ fun_l5_n35(x)
+ else
+ fun_l5_n409(x)
+ end
+end
+
+def fun_l4_n282(x)
+ if (x < 1)
+ fun_l5_n721(x)
+ else
+ fun_l5_n719(x)
+ end
+end
+
+def fun_l4_n283(x)
+ if (x < 1)
+ fun_l5_n729(x)
+ else
+ fun_l5_n901(x)
+ end
+end
+
+def fun_l4_n284(x)
+ if (x < 1)
+ fun_l5_n17(x)
+ else
+ fun_l5_n482(x)
+ end
+end
+
+def fun_l4_n285(x)
+ if (x < 1)
+ fun_l5_n166(x)
+ else
+ fun_l5_n53(x)
+ end
+end
+
+def fun_l4_n286(x)
+ if (x < 1)
+ fun_l5_n873(x)
+ else
+ fun_l5_n383(x)
+ end
+end
+
+def fun_l4_n287(x)
+ if (x < 1)
+ fun_l5_n269(x)
+ else
+ fun_l5_n49(x)
+ end
+end
+
+def fun_l4_n288(x)
+ if (x < 1)
+ fun_l5_n292(x)
+ else
+ fun_l5_n353(x)
+ end
+end
+
+def fun_l4_n289(x)
+ if (x < 1)
+ fun_l5_n651(x)
+ else
+ fun_l5_n606(x)
+ end
+end
+
+def fun_l4_n290(x)
+ if (x < 1)
+ fun_l5_n287(x)
+ else
+ fun_l5_n444(x)
+ end
+end
+
+def fun_l4_n291(x)
+ if (x < 1)
+ fun_l5_n181(x)
+ else
+ fun_l5_n195(x)
+ end
+end
+
+def fun_l4_n292(x)
+ if (x < 1)
+ fun_l5_n20(x)
+ else
+ fun_l5_n58(x)
+ end
+end
+
+def fun_l4_n293(x)
+ if (x < 1)
+ fun_l5_n185(x)
+ else
+ fun_l5_n759(x)
+ end
+end
+
+def fun_l4_n294(x)
+ if (x < 1)
+ fun_l5_n938(x)
+ else
+ fun_l5_n849(x)
+ end
+end
+
+def fun_l4_n295(x)
+ if (x < 1)
+ fun_l5_n187(x)
+ else
+ fun_l5_n469(x)
+ end
+end
+
+def fun_l4_n296(x)
+ if (x < 1)
+ fun_l5_n516(x)
+ else
+ fun_l5_n314(x)
+ end
+end
+
+def fun_l4_n297(x)
+ if (x < 1)
+ fun_l5_n585(x)
+ else
+ fun_l5_n344(x)
+ end
+end
+
+def fun_l4_n298(x)
+ if (x < 1)
+ fun_l5_n637(x)
+ else
+ fun_l5_n103(x)
+ end
+end
+
+def fun_l4_n299(x)
+ if (x < 1)
+ fun_l5_n185(x)
+ else
+ fun_l5_n593(x)
+ end
+end
+
+def fun_l4_n300(x)
+ if (x < 1)
+ fun_l5_n773(x)
+ else
+ fun_l5_n758(x)
+ end
+end
+
+def fun_l4_n301(x)
+ if (x < 1)
+ fun_l5_n444(x)
+ else
+ fun_l5_n945(x)
+ end
+end
+
+def fun_l4_n302(x)
+ if (x < 1)
+ fun_l5_n728(x)
+ else
+ fun_l5_n484(x)
+ end
+end
+
+def fun_l4_n303(x)
+ if (x < 1)
+ fun_l5_n412(x)
+ else
+ fun_l5_n106(x)
+ end
+end
+
+def fun_l4_n304(x)
+ if (x < 1)
+ fun_l5_n399(x)
+ else
+ fun_l5_n234(x)
+ end
+end
+
+def fun_l4_n305(x)
+ if (x < 1)
+ fun_l5_n886(x)
+ else
+ fun_l5_n406(x)
+ end
+end
+
+def fun_l4_n306(x)
+ if (x < 1)
+ fun_l5_n535(x)
+ else
+ fun_l5_n338(x)
+ end
+end
+
+def fun_l4_n307(x)
+ if (x < 1)
+ fun_l5_n898(x)
+ else
+ fun_l5_n859(x)
+ end
+end
+
+def fun_l4_n308(x)
+ if (x < 1)
+ fun_l5_n25(x)
+ else
+ fun_l5_n476(x)
+ end
+end
+
+def fun_l4_n309(x)
+ if (x < 1)
+ fun_l5_n451(x)
+ else
+ fun_l5_n665(x)
+ end
+end
+
+def fun_l4_n310(x)
+ if (x < 1)
+ fun_l5_n937(x)
+ else
+ fun_l5_n555(x)
+ end
+end
+
+def fun_l4_n311(x)
+ if (x < 1)
+ fun_l5_n982(x)
+ else
+ fun_l5_n89(x)
+ end
+end
+
+def fun_l4_n312(x)
+ if (x < 1)
+ fun_l5_n32(x)
+ else
+ fun_l5_n908(x)
+ end
+end
+
+def fun_l4_n313(x)
+ if (x < 1)
+ fun_l5_n963(x)
+ else
+ fun_l5_n267(x)
+ end
+end
+
+def fun_l4_n314(x)
+ if (x < 1)
+ fun_l5_n3(x)
+ else
+ fun_l5_n60(x)
+ end
+end
+
+def fun_l4_n315(x)
+ if (x < 1)
+ fun_l5_n763(x)
+ else
+ fun_l5_n488(x)
+ end
+end
+
+def fun_l4_n316(x)
+ if (x < 1)
+ fun_l5_n696(x)
+ else
+ fun_l5_n663(x)
+ end
+end
+
+def fun_l4_n317(x)
+ if (x < 1)
+ fun_l5_n851(x)
+ else
+ fun_l5_n487(x)
+ end
+end
+
+def fun_l4_n318(x)
+ if (x < 1)
+ fun_l5_n327(x)
+ else
+ fun_l5_n433(x)
+ end
+end
+
+def fun_l4_n319(x)
+ if (x < 1)
+ fun_l5_n242(x)
+ else
+ fun_l5_n471(x)
+ end
+end
+
+def fun_l4_n320(x)
+ if (x < 1)
+ fun_l5_n786(x)
+ else
+ fun_l5_n622(x)
+ end
+end
+
+def fun_l4_n321(x)
+ if (x < 1)
+ fun_l5_n94(x)
+ else
+ fun_l5_n934(x)
+ end
+end
+
+def fun_l4_n322(x)
+ if (x < 1)
+ fun_l5_n665(x)
+ else
+ fun_l5_n386(x)
+ end
+end
+
+def fun_l4_n323(x)
+ if (x < 1)
+ fun_l5_n96(x)
+ else
+ fun_l5_n466(x)
+ end
+end
+
+def fun_l4_n324(x)
+ if (x < 1)
+ fun_l5_n394(x)
+ else
+ fun_l5_n595(x)
+ end
+end
+
+def fun_l4_n325(x)
+ if (x < 1)
+ fun_l5_n544(x)
+ else
+ fun_l5_n688(x)
+ end
+end
+
+def fun_l4_n326(x)
+ if (x < 1)
+ fun_l5_n295(x)
+ else
+ fun_l5_n206(x)
+ end
+end
+
+def fun_l4_n327(x)
+ if (x < 1)
+ fun_l5_n128(x)
+ else
+ fun_l5_n607(x)
+ end
+end
+
+def fun_l4_n328(x)
+ if (x < 1)
+ fun_l5_n987(x)
+ else
+ fun_l5_n109(x)
+ end
+end
+
+def fun_l4_n329(x)
+ if (x < 1)
+ fun_l5_n842(x)
+ else
+ fun_l5_n217(x)
+ end
+end
+
+def fun_l4_n330(x)
+ if (x < 1)
+ fun_l5_n92(x)
+ else
+ fun_l5_n774(x)
+ end
+end
+
+def fun_l4_n331(x)
+ if (x < 1)
+ fun_l5_n761(x)
+ else
+ fun_l5_n34(x)
+ end
+end
+
+def fun_l4_n332(x)
+ if (x < 1)
+ fun_l5_n867(x)
+ else
+ fun_l5_n645(x)
+ end
+end
+
+def fun_l4_n333(x)
+ if (x < 1)
+ fun_l5_n273(x)
+ else
+ fun_l5_n592(x)
+ end
+end
+
+def fun_l4_n334(x)
+ if (x < 1)
+ fun_l5_n29(x)
+ else
+ fun_l5_n985(x)
+ end
+end
+
+def fun_l4_n335(x)
+ if (x < 1)
+ fun_l5_n430(x)
+ else
+ fun_l5_n346(x)
+ end
+end
+
+def fun_l4_n336(x)
+ if (x < 1)
+ fun_l5_n367(x)
+ else
+ fun_l5_n686(x)
+ end
+end
+
+def fun_l4_n337(x)
+ if (x < 1)
+ fun_l5_n868(x)
+ else
+ fun_l5_n5(x)
+ end
+end
+
+def fun_l4_n338(x)
+ if (x < 1)
+ fun_l5_n998(x)
+ else
+ fun_l5_n64(x)
+ end
+end
+
+def fun_l4_n339(x)
+ if (x < 1)
+ fun_l5_n594(x)
+ else
+ fun_l5_n311(x)
+ end
+end
+
+def fun_l4_n340(x)
+ if (x < 1)
+ fun_l5_n547(x)
+ else
+ fun_l5_n573(x)
+ end
+end
+
+def fun_l4_n341(x)
+ if (x < 1)
+ fun_l5_n590(x)
+ else
+ fun_l5_n923(x)
+ end
+end
+
+def fun_l4_n342(x)
+ if (x < 1)
+ fun_l5_n538(x)
+ else
+ fun_l5_n118(x)
+ end
+end
+
+def fun_l4_n343(x)
+ if (x < 1)
+ fun_l5_n322(x)
+ else
+ fun_l5_n970(x)
+ end
+end
+
+def fun_l4_n344(x)
+ if (x < 1)
+ fun_l5_n809(x)
+ else
+ fun_l5_n958(x)
+ end
+end
+
+def fun_l4_n345(x)
+ if (x < 1)
+ fun_l5_n613(x)
+ else
+ fun_l5_n199(x)
+ end
+end
+
+def fun_l4_n346(x)
+ if (x < 1)
+ fun_l5_n298(x)
+ else
+ fun_l5_n273(x)
+ end
+end
+
+def fun_l4_n347(x)
+ if (x < 1)
+ fun_l5_n560(x)
+ else
+ fun_l5_n803(x)
+ end
+end
+
+def fun_l4_n348(x)
+ if (x < 1)
+ fun_l5_n672(x)
+ else
+ fun_l5_n952(x)
+ end
+end
+
+def fun_l4_n349(x)
+ if (x < 1)
+ fun_l5_n58(x)
+ else
+ fun_l5_n267(x)
+ end
+end
+
+def fun_l4_n350(x)
+ if (x < 1)
+ fun_l5_n933(x)
+ else
+ fun_l5_n773(x)
+ end
+end
+
+def fun_l4_n351(x)
+ if (x < 1)
+ fun_l5_n574(x)
+ else
+ fun_l5_n692(x)
+ end
+end
+
+def fun_l4_n352(x)
+ if (x < 1)
+ fun_l5_n537(x)
+ else
+ fun_l5_n312(x)
+ end
+end
+
+def fun_l4_n353(x)
+ if (x < 1)
+ fun_l5_n696(x)
+ else
+ fun_l5_n739(x)
+ end
+end
+
+def fun_l4_n354(x)
+ if (x < 1)
+ fun_l5_n871(x)
+ else
+ fun_l5_n86(x)
+ end
+end
+
+def fun_l4_n355(x)
+ if (x < 1)
+ fun_l5_n3(x)
+ else
+ fun_l5_n950(x)
+ end
+end
+
+def fun_l4_n356(x)
+ if (x < 1)
+ fun_l5_n560(x)
+ else
+ fun_l5_n45(x)
+ end
+end
+
+def fun_l4_n357(x)
+ if (x < 1)
+ fun_l5_n666(x)
+ else
+ fun_l5_n874(x)
+ end
+end
+
+def fun_l4_n358(x)
+ if (x < 1)
+ fun_l5_n457(x)
+ else
+ fun_l5_n7(x)
+ end
+end
+
+def fun_l4_n359(x)
+ if (x < 1)
+ fun_l5_n674(x)
+ else
+ fun_l5_n985(x)
+ end
+end
+
+def fun_l4_n360(x)
+ if (x < 1)
+ fun_l5_n960(x)
+ else
+ fun_l5_n228(x)
+ end
+end
+
+def fun_l4_n361(x)
+ if (x < 1)
+ fun_l5_n597(x)
+ else
+ fun_l5_n487(x)
+ end
+end
+
+def fun_l4_n362(x)
+ if (x < 1)
+ fun_l5_n145(x)
+ else
+ fun_l5_n278(x)
+ end
+end
+
+def fun_l4_n363(x)
+ if (x < 1)
+ fun_l5_n949(x)
+ else
+ fun_l5_n353(x)
+ end
+end
+
+def fun_l4_n364(x)
+ if (x < 1)
+ fun_l5_n604(x)
+ else
+ fun_l5_n250(x)
+ end
+end
+
+def fun_l4_n365(x)
+ if (x < 1)
+ fun_l5_n347(x)
+ else
+ fun_l5_n964(x)
+ end
+end
+
+def fun_l4_n366(x)
+ if (x < 1)
+ fun_l5_n331(x)
+ else
+ fun_l5_n657(x)
+ end
+end
+
+def fun_l4_n367(x)
+ if (x < 1)
+ fun_l5_n74(x)
+ else
+ fun_l5_n504(x)
+ end
+end
+
+def fun_l4_n368(x)
+ if (x < 1)
+ fun_l5_n9(x)
+ else
+ fun_l5_n993(x)
+ end
+end
+
+def fun_l4_n369(x)
+ if (x < 1)
+ fun_l5_n492(x)
+ else
+ fun_l5_n155(x)
+ end
+end
+
+def fun_l4_n370(x)
+ if (x < 1)
+ fun_l5_n848(x)
+ else
+ fun_l5_n178(x)
+ end
+end
+
+def fun_l4_n371(x)
+ if (x < 1)
+ fun_l5_n395(x)
+ else
+ fun_l5_n837(x)
+ end
+end
+
+def fun_l4_n372(x)
+ if (x < 1)
+ fun_l5_n834(x)
+ else
+ fun_l5_n719(x)
+ end
+end
+
+def fun_l4_n373(x)
+ if (x < 1)
+ fun_l5_n422(x)
+ else
+ fun_l5_n776(x)
+ end
+end
+
+def fun_l4_n374(x)
+ if (x < 1)
+ fun_l5_n293(x)
+ else
+ fun_l5_n385(x)
+ end
+end
+
+def fun_l4_n375(x)
+ if (x < 1)
+ fun_l5_n487(x)
+ else
+ fun_l5_n61(x)
+ end
+end
+
+def fun_l4_n376(x)
+ if (x < 1)
+ fun_l5_n493(x)
+ else
+ fun_l5_n629(x)
+ end
+end
+
+def fun_l4_n377(x)
+ if (x < 1)
+ fun_l5_n429(x)
+ else
+ fun_l5_n157(x)
+ end
+end
+
+def fun_l4_n378(x)
+ if (x < 1)
+ fun_l5_n145(x)
+ else
+ fun_l5_n988(x)
+ end
+end
+
+def fun_l4_n379(x)
+ if (x < 1)
+ fun_l5_n430(x)
+ else
+ fun_l5_n246(x)
+ end
+end
+
+def fun_l4_n380(x)
+ if (x < 1)
+ fun_l5_n320(x)
+ else
+ fun_l5_n284(x)
+ end
+end
+
+def fun_l4_n381(x)
+ if (x < 1)
+ fun_l5_n278(x)
+ else
+ fun_l5_n163(x)
+ end
+end
+
+def fun_l4_n382(x)
+ if (x < 1)
+ fun_l5_n999(x)
+ else
+ fun_l5_n907(x)
+ end
+end
+
+def fun_l4_n383(x)
+ if (x < 1)
+ fun_l5_n979(x)
+ else
+ fun_l5_n370(x)
+ end
+end
+
+def fun_l4_n384(x)
+ if (x < 1)
+ fun_l5_n58(x)
+ else
+ fun_l5_n60(x)
+ end
+end
+
+def fun_l4_n385(x)
+ if (x < 1)
+ fun_l5_n558(x)
+ else
+ fun_l5_n524(x)
+ end
+end
+
+def fun_l4_n386(x)
+ if (x < 1)
+ fun_l5_n438(x)
+ else
+ fun_l5_n799(x)
+ end
+end
+
+def fun_l4_n387(x)
+ if (x < 1)
+ fun_l5_n696(x)
+ else
+ fun_l5_n463(x)
+ end
+end
+
+def fun_l4_n388(x)
+ if (x < 1)
+ fun_l5_n376(x)
+ else
+ fun_l5_n943(x)
+ end
+end
+
+def fun_l4_n389(x)
+ if (x < 1)
+ fun_l5_n21(x)
+ else
+ fun_l5_n663(x)
+ end
+end
+
+def fun_l4_n390(x)
+ if (x < 1)
+ fun_l5_n8(x)
+ else
+ fun_l5_n348(x)
+ end
+end
+
+def fun_l4_n391(x)
+ if (x < 1)
+ fun_l5_n908(x)
+ else
+ fun_l5_n695(x)
+ end
+end
+
+def fun_l4_n392(x)
+ if (x < 1)
+ fun_l5_n97(x)
+ else
+ fun_l5_n466(x)
+ end
+end
+
+def fun_l4_n393(x)
+ if (x < 1)
+ fun_l5_n480(x)
+ else
+ fun_l5_n972(x)
+ end
+end
+
+def fun_l4_n394(x)
+ if (x < 1)
+ fun_l5_n85(x)
+ else
+ fun_l5_n849(x)
+ end
+end
+
+def fun_l4_n395(x)
+ if (x < 1)
+ fun_l5_n897(x)
+ else
+ fun_l5_n13(x)
+ end
+end
+
+def fun_l4_n396(x)
+ if (x < 1)
+ fun_l5_n628(x)
+ else
+ fun_l5_n743(x)
+ end
+end
+
+def fun_l4_n397(x)
+ if (x < 1)
+ fun_l5_n29(x)
+ else
+ fun_l5_n185(x)
+ end
+end
+
+def fun_l4_n398(x)
+ if (x < 1)
+ fun_l5_n464(x)
+ else
+ fun_l5_n742(x)
+ end
+end
+
+def fun_l4_n399(x)
+ if (x < 1)
+ fun_l5_n348(x)
+ else
+ fun_l5_n70(x)
+ end
+end
+
+def fun_l4_n400(x)
+ if (x < 1)
+ fun_l5_n397(x)
+ else
+ fun_l5_n132(x)
+ end
+end
+
+def fun_l4_n401(x)
+ if (x < 1)
+ fun_l5_n433(x)
+ else
+ fun_l5_n77(x)
+ end
+end
+
+def fun_l4_n402(x)
+ if (x < 1)
+ fun_l5_n24(x)
+ else
+ fun_l5_n160(x)
+ end
+end
+
+def fun_l4_n403(x)
+ if (x < 1)
+ fun_l5_n738(x)
+ else
+ fun_l5_n174(x)
+ end
+end
+
+def fun_l4_n404(x)
+ if (x < 1)
+ fun_l5_n585(x)
+ else
+ fun_l5_n670(x)
+ end
+end
+
+def fun_l4_n405(x)
+ if (x < 1)
+ fun_l5_n320(x)
+ else
+ fun_l5_n245(x)
+ end
+end
+
+def fun_l4_n406(x)
+ if (x < 1)
+ fun_l5_n357(x)
+ else
+ fun_l5_n742(x)
+ end
+end
+
+def fun_l4_n407(x)
+ if (x < 1)
+ fun_l5_n16(x)
+ else
+ fun_l5_n227(x)
+ end
+end
+
+def fun_l4_n408(x)
+ if (x < 1)
+ fun_l5_n360(x)
+ else
+ fun_l5_n18(x)
+ end
+end
+
+def fun_l4_n409(x)
+ if (x < 1)
+ fun_l5_n210(x)
+ else
+ fun_l5_n253(x)
+ end
+end
+
+def fun_l4_n410(x)
+ if (x < 1)
+ fun_l5_n915(x)
+ else
+ fun_l5_n605(x)
+ end
+end
+
+def fun_l4_n411(x)
+ if (x < 1)
+ fun_l5_n511(x)
+ else
+ fun_l5_n118(x)
+ end
+end
+
+def fun_l4_n412(x)
+ if (x < 1)
+ fun_l5_n680(x)
+ else
+ fun_l5_n445(x)
+ end
+end
+
+def fun_l4_n413(x)
+ if (x < 1)
+ fun_l5_n722(x)
+ else
+ fun_l5_n440(x)
+ end
+end
+
+def fun_l4_n414(x)
+ if (x < 1)
+ fun_l5_n382(x)
+ else
+ fun_l5_n380(x)
+ end
+end
+
+def fun_l4_n415(x)
+ if (x < 1)
+ fun_l5_n548(x)
+ else
+ fun_l5_n462(x)
+ end
+end
+
+def fun_l4_n416(x)
+ if (x < 1)
+ fun_l5_n12(x)
+ else
+ fun_l5_n952(x)
+ end
+end
+
+def fun_l4_n417(x)
+ if (x < 1)
+ fun_l5_n814(x)
+ else
+ fun_l5_n720(x)
+ end
+end
+
+def fun_l4_n418(x)
+ if (x < 1)
+ fun_l5_n804(x)
+ else
+ fun_l5_n243(x)
+ end
+end
+
+def fun_l4_n419(x)
+ if (x < 1)
+ fun_l5_n654(x)
+ else
+ fun_l5_n950(x)
+ end
+end
+
+def fun_l4_n420(x)
+ if (x < 1)
+ fun_l5_n998(x)
+ else
+ fun_l5_n937(x)
+ end
+end
+
+def fun_l4_n421(x)
+ if (x < 1)
+ fun_l5_n476(x)
+ else
+ fun_l5_n245(x)
+ end
+end
+
+def fun_l4_n422(x)
+ if (x < 1)
+ fun_l5_n778(x)
+ else
+ fun_l5_n950(x)
+ end
+end
+
+def fun_l4_n423(x)
+ if (x < 1)
+ fun_l5_n255(x)
+ else
+ fun_l5_n438(x)
+ end
+end
+
+def fun_l4_n424(x)
+ if (x < 1)
+ fun_l5_n906(x)
+ else
+ fun_l5_n329(x)
+ end
+end
+
+def fun_l4_n425(x)
+ if (x < 1)
+ fun_l5_n644(x)
+ else
+ fun_l5_n512(x)
+ end
+end
+
+def fun_l4_n426(x)
+ if (x < 1)
+ fun_l5_n558(x)
+ else
+ fun_l5_n925(x)
+ end
+end
+
+def fun_l4_n427(x)
+ if (x < 1)
+ fun_l5_n745(x)
+ else
+ fun_l5_n168(x)
+ end
+end
+
+def fun_l4_n428(x)
+ if (x < 1)
+ fun_l5_n682(x)
+ else
+ fun_l5_n298(x)
+ end
+end
+
+def fun_l4_n429(x)
+ if (x < 1)
+ fun_l5_n211(x)
+ else
+ fun_l5_n608(x)
+ end
+end
+
+def fun_l4_n430(x)
+ if (x < 1)
+ fun_l5_n100(x)
+ else
+ fun_l5_n287(x)
+ end
+end
+
+def fun_l4_n431(x)
+ if (x < 1)
+ fun_l5_n513(x)
+ else
+ fun_l5_n764(x)
+ end
+end
+
+def fun_l4_n432(x)
+ if (x < 1)
+ fun_l5_n925(x)
+ else
+ fun_l5_n857(x)
+ end
+end
+
+def fun_l4_n433(x)
+ if (x < 1)
+ fun_l5_n279(x)
+ else
+ fun_l5_n429(x)
+ end
+end
+
+def fun_l4_n434(x)
+ if (x < 1)
+ fun_l5_n376(x)
+ else
+ fun_l5_n811(x)
+ end
+end
+
+def fun_l4_n435(x)
+ if (x < 1)
+ fun_l5_n893(x)
+ else
+ fun_l5_n136(x)
+ end
+end
+
+def fun_l4_n436(x)
+ if (x < 1)
+ fun_l5_n283(x)
+ else
+ fun_l5_n508(x)
+ end
+end
+
+def fun_l4_n437(x)
+ if (x < 1)
+ fun_l5_n478(x)
+ else
+ fun_l5_n589(x)
+ end
+end
+
+def fun_l4_n438(x)
+ if (x < 1)
+ fun_l5_n460(x)
+ else
+ fun_l5_n589(x)
+ end
+end
+
+def fun_l4_n439(x)
+ if (x < 1)
+ fun_l5_n745(x)
+ else
+ fun_l5_n5(x)
+ end
+end
+
+def fun_l4_n440(x)
+ if (x < 1)
+ fun_l5_n601(x)
+ else
+ fun_l5_n322(x)
+ end
+end
+
+def fun_l4_n441(x)
+ if (x < 1)
+ fun_l5_n703(x)
+ else
+ fun_l5_n322(x)
+ end
+end
+
+def fun_l4_n442(x)
+ if (x < 1)
+ fun_l5_n810(x)
+ else
+ fun_l5_n363(x)
+ end
+end
+
+def fun_l4_n443(x)
+ if (x < 1)
+ fun_l5_n62(x)
+ else
+ fun_l5_n995(x)
+ end
+end
+
+def fun_l4_n444(x)
+ if (x < 1)
+ fun_l5_n196(x)
+ else
+ fun_l5_n156(x)
+ end
+end
+
+def fun_l4_n445(x)
+ if (x < 1)
+ fun_l5_n456(x)
+ else
+ fun_l5_n820(x)
+ end
+end
+
+def fun_l4_n446(x)
+ if (x < 1)
+ fun_l5_n592(x)
+ else
+ fun_l5_n214(x)
+ end
+end
+
+def fun_l4_n447(x)
+ if (x < 1)
+ fun_l5_n44(x)
+ else
+ fun_l5_n769(x)
+ end
+end
+
+def fun_l4_n448(x)
+ if (x < 1)
+ fun_l5_n694(x)
+ else
+ fun_l5_n909(x)
+ end
+end
+
+def fun_l4_n449(x)
+ if (x < 1)
+ fun_l5_n297(x)
+ else
+ fun_l5_n134(x)
+ end
+end
+
+def fun_l4_n450(x)
+ if (x < 1)
+ fun_l5_n878(x)
+ else
+ fun_l5_n475(x)
+ end
+end
+
+def fun_l4_n451(x)
+ if (x < 1)
+ fun_l5_n338(x)
+ else
+ fun_l5_n700(x)
+ end
+end
+
+def fun_l4_n452(x)
+ if (x < 1)
+ fun_l5_n813(x)
+ else
+ fun_l5_n41(x)
+ end
+end
+
+def fun_l4_n453(x)
+ if (x < 1)
+ fun_l5_n176(x)
+ else
+ fun_l5_n758(x)
+ end
+end
+
+def fun_l4_n454(x)
+ if (x < 1)
+ fun_l5_n60(x)
+ else
+ fun_l5_n608(x)
+ end
+end
+
+def fun_l4_n455(x)
+ if (x < 1)
+ fun_l5_n550(x)
+ else
+ fun_l5_n607(x)
+ end
+end
+
+def fun_l4_n456(x)
+ if (x < 1)
+ fun_l5_n535(x)
+ else
+ fun_l5_n478(x)
+ end
+end
+
+def fun_l4_n457(x)
+ if (x < 1)
+ fun_l5_n768(x)
+ else
+ fun_l5_n613(x)
+ end
+end
+
+def fun_l4_n458(x)
+ if (x < 1)
+ fun_l5_n686(x)
+ else
+ fun_l5_n208(x)
+ end
+end
+
+def fun_l4_n459(x)
+ if (x < 1)
+ fun_l5_n167(x)
+ else
+ fun_l5_n875(x)
+ end
+end
+
+def fun_l4_n460(x)
+ if (x < 1)
+ fun_l5_n202(x)
+ else
+ fun_l5_n440(x)
+ end
+end
+
+def fun_l4_n461(x)
+ if (x < 1)
+ fun_l5_n64(x)
+ else
+ fun_l5_n845(x)
+ end
+end
+
+def fun_l4_n462(x)
+ if (x < 1)
+ fun_l5_n914(x)
+ else
+ fun_l5_n699(x)
+ end
+end
+
+def fun_l4_n463(x)
+ if (x < 1)
+ fun_l5_n204(x)
+ else
+ fun_l5_n723(x)
+ end
+end
+
+def fun_l4_n464(x)
+ if (x < 1)
+ fun_l5_n549(x)
+ else
+ fun_l5_n375(x)
+ end
+end
+
+def fun_l4_n465(x)
+ if (x < 1)
+ fun_l5_n610(x)
+ else
+ fun_l5_n596(x)
+ end
+end
+
+def fun_l4_n466(x)
+ if (x < 1)
+ fun_l5_n571(x)
+ else
+ fun_l5_n618(x)
+ end
+end
+
+def fun_l4_n467(x)
+ if (x < 1)
+ fun_l5_n428(x)
+ else
+ fun_l5_n315(x)
+ end
+end
+
+def fun_l4_n468(x)
+ if (x < 1)
+ fun_l5_n19(x)
+ else
+ fun_l5_n301(x)
+ end
+end
+
+def fun_l4_n469(x)
+ if (x < 1)
+ fun_l5_n38(x)
+ else
+ fun_l5_n895(x)
+ end
+end
+
+def fun_l4_n470(x)
+ if (x < 1)
+ fun_l5_n815(x)
+ else
+ fun_l5_n303(x)
+ end
+end
+
+def fun_l4_n471(x)
+ if (x < 1)
+ fun_l5_n876(x)
+ else
+ fun_l5_n221(x)
+ end
+end
+
+def fun_l4_n472(x)
+ if (x < 1)
+ fun_l5_n199(x)
+ else
+ fun_l5_n354(x)
+ end
+end
+
+def fun_l4_n473(x)
+ if (x < 1)
+ fun_l5_n56(x)
+ else
+ fun_l5_n197(x)
+ end
+end
+
+def fun_l4_n474(x)
+ if (x < 1)
+ fun_l5_n573(x)
+ else
+ fun_l5_n616(x)
+ end
+end
+
+def fun_l4_n475(x)
+ if (x < 1)
+ fun_l5_n313(x)
+ else
+ fun_l5_n209(x)
+ end
+end
+
+def fun_l4_n476(x)
+ if (x < 1)
+ fun_l5_n229(x)
+ else
+ fun_l5_n51(x)
+ end
+end
+
+def fun_l4_n477(x)
+ if (x < 1)
+ fun_l5_n768(x)
+ else
+ fun_l5_n368(x)
+ end
+end
+
+def fun_l4_n478(x)
+ if (x < 1)
+ fun_l5_n80(x)
+ else
+ fun_l5_n411(x)
+ end
+end
+
+def fun_l4_n479(x)
+ if (x < 1)
+ fun_l5_n221(x)
+ else
+ fun_l5_n266(x)
+ end
+end
+
+def fun_l4_n480(x)
+ if (x < 1)
+ fun_l5_n463(x)
+ else
+ fun_l5_n71(x)
+ end
+end
+
+def fun_l4_n481(x)
+ if (x < 1)
+ fun_l5_n446(x)
+ else
+ fun_l5_n610(x)
+ end
+end
+
+def fun_l4_n482(x)
+ if (x < 1)
+ fun_l5_n402(x)
+ else
+ fun_l5_n449(x)
+ end
+end
+
+def fun_l4_n483(x)
+ if (x < 1)
+ fun_l5_n497(x)
+ else
+ fun_l5_n521(x)
+ end
+end
+
+def fun_l4_n484(x)
+ if (x < 1)
+ fun_l5_n895(x)
+ else
+ fun_l5_n361(x)
+ end
+end
+
+def fun_l4_n485(x)
+ if (x < 1)
+ fun_l5_n254(x)
+ else
+ fun_l5_n366(x)
+ end
+end
+
+def fun_l4_n486(x)
+ if (x < 1)
+ fun_l5_n179(x)
+ else
+ fun_l5_n154(x)
+ end
+end
+
+def fun_l4_n487(x)
+ if (x < 1)
+ fun_l5_n905(x)
+ else
+ fun_l5_n30(x)
+ end
+end
+
+def fun_l4_n488(x)
+ if (x < 1)
+ fun_l5_n989(x)
+ else
+ fun_l5_n640(x)
+ end
+end
+
+def fun_l4_n489(x)
+ if (x < 1)
+ fun_l5_n664(x)
+ else
+ fun_l5_n87(x)
+ end
+end
+
+def fun_l4_n490(x)
+ if (x < 1)
+ fun_l5_n518(x)
+ else
+ fun_l5_n986(x)
+ end
+end
+
+def fun_l4_n491(x)
+ if (x < 1)
+ fun_l5_n443(x)
+ else
+ fun_l5_n532(x)
+ end
+end
+
+def fun_l4_n492(x)
+ if (x < 1)
+ fun_l5_n349(x)
+ else
+ fun_l5_n373(x)
+ end
+end
+
+def fun_l4_n493(x)
+ if (x < 1)
+ fun_l5_n208(x)
+ else
+ fun_l5_n404(x)
+ end
+end
+
+def fun_l4_n494(x)
+ if (x < 1)
+ fun_l5_n12(x)
+ else
+ fun_l5_n608(x)
+ end
+end
+
+def fun_l4_n495(x)
+ if (x < 1)
+ fun_l5_n12(x)
+ else
+ fun_l5_n42(x)
+ end
+end
+
+def fun_l4_n496(x)
+ if (x < 1)
+ fun_l5_n442(x)
+ else
+ fun_l5_n809(x)
+ end
+end
+
+def fun_l4_n497(x)
+ if (x < 1)
+ fun_l5_n266(x)
+ else
+ fun_l5_n259(x)
+ end
+end
+
+def fun_l4_n498(x)
+ if (x < 1)
+ fun_l5_n342(x)
+ else
+ fun_l5_n275(x)
+ end
+end
+
+def fun_l4_n499(x)
+ if (x < 1)
+ fun_l5_n806(x)
+ else
+ fun_l5_n797(x)
+ end
+end
+
+def fun_l4_n500(x)
+ if (x < 1)
+ fun_l5_n646(x)
+ else
+ fun_l5_n426(x)
+ end
+end
+
+def fun_l4_n501(x)
+ if (x < 1)
+ fun_l5_n593(x)
+ else
+ fun_l5_n860(x)
+ end
+end
+
+def fun_l4_n502(x)
+ if (x < 1)
+ fun_l5_n355(x)
+ else
+ fun_l5_n411(x)
+ end
+end
+
+def fun_l4_n503(x)
+ if (x < 1)
+ fun_l5_n602(x)
+ else
+ fun_l5_n26(x)
+ end
+end
+
+def fun_l4_n504(x)
+ if (x < 1)
+ fun_l5_n875(x)
+ else
+ fun_l5_n716(x)
+ end
+end
+
+def fun_l4_n505(x)
+ if (x < 1)
+ fun_l5_n248(x)
+ else
+ fun_l5_n388(x)
+ end
+end
+
+def fun_l4_n506(x)
+ if (x < 1)
+ fun_l5_n273(x)
+ else
+ fun_l5_n11(x)
+ end
+end
+
+def fun_l4_n507(x)
+ if (x < 1)
+ fun_l5_n291(x)
+ else
+ fun_l5_n464(x)
+ end
+end
+
+def fun_l4_n508(x)
+ if (x < 1)
+ fun_l5_n309(x)
+ else
+ fun_l5_n198(x)
+ end
+end
+
+def fun_l4_n509(x)
+ if (x < 1)
+ fun_l5_n85(x)
+ else
+ fun_l5_n375(x)
+ end
+end
+
+def fun_l4_n510(x)
+ if (x < 1)
+ fun_l5_n993(x)
+ else
+ fun_l5_n311(x)
+ end
+end
+
+def fun_l4_n511(x)
+ if (x < 1)
+ fun_l5_n824(x)
+ else
+ fun_l5_n936(x)
+ end
+end
+
+def fun_l4_n512(x)
+ if (x < 1)
+ fun_l5_n897(x)
+ else
+ fun_l5_n995(x)
+ end
+end
+
+def fun_l4_n513(x)
+ if (x < 1)
+ fun_l5_n443(x)
+ else
+ fun_l5_n511(x)
+ end
+end
+
+def fun_l4_n514(x)
+ if (x < 1)
+ fun_l5_n965(x)
+ else
+ fun_l5_n506(x)
+ end
+end
+
+def fun_l4_n515(x)
+ if (x < 1)
+ fun_l5_n480(x)
+ else
+ fun_l5_n464(x)
+ end
+end
+
+def fun_l4_n516(x)
+ if (x < 1)
+ fun_l5_n396(x)
+ else
+ fun_l5_n355(x)
+ end
+end
+
+def fun_l4_n517(x)
+ if (x < 1)
+ fun_l5_n782(x)
+ else
+ fun_l5_n624(x)
+ end
+end
+
+def fun_l4_n518(x)
+ if (x < 1)
+ fun_l5_n460(x)
+ else
+ fun_l5_n920(x)
+ end
+end
+
+def fun_l4_n519(x)
+ if (x < 1)
+ fun_l5_n258(x)
+ else
+ fun_l5_n296(x)
+ end
+end
+
+def fun_l4_n520(x)
+ if (x < 1)
+ fun_l5_n344(x)
+ else
+ fun_l5_n180(x)
+ end
+end
+
+def fun_l4_n521(x)
+ if (x < 1)
+ fun_l5_n489(x)
+ else
+ fun_l5_n818(x)
+ end
+end
+
+def fun_l4_n522(x)
+ if (x < 1)
+ fun_l5_n246(x)
+ else
+ fun_l5_n25(x)
+ end
+end
+
+def fun_l4_n523(x)
+ if (x < 1)
+ fun_l5_n165(x)
+ else
+ fun_l5_n835(x)
+ end
+end
+
+def fun_l4_n524(x)
+ if (x < 1)
+ fun_l5_n836(x)
+ else
+ fun_l5_n838(x)
+ end
+end
+
+def fun_l4_n525(x)
+ if (x < 1)
+ fun_l5_n781(x)
+ else
+ fun_l5_n183(x)
+ end
+end
+
+def fun_l4_n526(x)
+ if (x < 1)
+ fun_l5_n335(x)
+ else
+ fun_l5_n809(x)
+ end
+end
+
+def fun_l4_n527(x)
+ if (x < 1)
+ fun_l5_n748(x)
+ else
+ fun_l5_n674(x)
+ end
+end
+
+def fun_l4_n528(x)
+ if (x < 1)
+ fun_l5_n612(x)
+ else
+ fun_l5_n933(x)
+ end
+end
+
+def fun_l4_n529(x)
+ if (x < 1)
+ fun_l5_n781(x)
+ else
+ fun_l5_n174(x)
+ end
+end
+
+def fun_l4_n530(x)
+ if (x < 1)
+ fun_l5_n299(x)
+ else
+ fun_l5_n677(x)
+ end
+end
+
+def fun_l4_n531(x)
+ if (x < 1)
+ fun_l5_n455(x)
+ else
+ fun_l5_n211(x)
+ end
+end
+
+def fun_l4_n532(x)
+ if (x < 1)
+ fun_l5_n981(x)
+ else
+ fun_l5_n605(x)
+ end
+end
+
+def fun_l4_n533(x)
+ if (x < 1)
+ fun_l5_n299(x)
+ else
+ fun_l5_n30(x)
+ end
+end
+
+def fun_l4_n534(x)
+ if (x < 1)
+ fun_l5_n642(x)
+ else
+ fun_l5_n652(x)
+ end
+end
+
+def fun_l4_n535(x)
+ if (x < 1)
+ fun_l5_n904(x)
+ else
+ fun_l5_n133(x)
+ end
+end
+
+def fun_l4_n536(x)
+ if (x < 1)
+ fun_l5_n253(x)
+ else
+ fun_l5_n330(x)
+ end
+end
+
+def fun_l4_n537(x)
+ if (x < 1)
+ fun_l5_n357(x)
+ else
+ fun_l5_n533(x)
+ end
+end
+
+def fun_l4_n538(x)
+ if (x < 1)
+ fun_l5_n484(x)
+ else
+ fun_l5_n438(x)
+ end
+end
+
+def fun_l4_n539(x)
+ if (x < 1)
+ fun_l5_n200(x)
+ else
+ fun_l5_n235(x)
+ end
+end
+
+def fun_l4_n540(x)
+ if (x < 1)
+ fun_l5_n929(x)
+ else
+ fun_l5_n875(x)
+ end
+end
+
+def fun_l4_n541(x)
+ if (x < 1)
+ fun_l5_n237(x)
+ else
+ fun_l5_n688(x)
+ end
+end
+
+def fun_l4_n542(x)
+ if (x < 1)
+ fun_l5_n723(x)
+ else
+ fun_l5_n308(x)
+ end
+end
+
+def fun_l4_n543(x)
+ if (x < 1)
+ fun_l5_n591(x)
+ else
+ fun_l5_n93(x)
+ end
+end
+
+def fun_l4_n544(x)
+ if (x < 1)
+ fun_l5_n258(x)
+ else
+ fun_l5_n205(x)
+ end
+end
+
+def fun_l4_n545(x)
+ if (x < 1)
+ fun_l5_n910(x)
+ else
+ fun_l5_n529(x)
+ end
+end
+
+def fun_l4_n546(x)
+ if (x < 1)
+ fun_l5_n255(x)
+ else
+ fun_l5_n262(x)
+ end
+end
+
+def fun_l4_n547(x)
+ if (x < 1)
+ fun_l5_n674(x)
+ else
+ fun_l5_n813(x)
+ end
+end
+
+def fun_l4_n548(x)
+ if (x < 1)
+ fun_l5_n9(x)
+ else
+ fun_l5_n709(x)
+ end
+end
+
+def fun_l4_n549(x)
+ if (x < 1)
+ fun_l5_n146(x)
+ else
+ fun_l5_n801(x)
+ end
+end
+
+def fun_l4_n550(x)
+ if (x < 1)
+ fun_l5_n593(x)
+ else
+ fun_l5_n428(x)
+ end
+end
+
+def fun_l4_n551(x)
+ if (x < 1)
+ fun_l5_n953(x)
+ else
+ fun_l5_n238(x)
+ end
+end
+
+def fun_l4_n552(x)
+ if (x < 1)
+ fun_l5_n900(x)
+ else
+ fun_l5_n246(x)
+ end
+end
+
+def fun_l4_n553(x)
+ if (x < 1)
+ fun_l5_n400(x)
+ else
+ fun_l5_n150(x)
+ end
+end
+
+def fun_l4_n554(x)
+ if (x < 1)
+ fun_l5_n697(x)
+ else
+ fun_l5_n681(x)
+ end
+end
+
+def fun_l4_n555(x)
+ if (x < 1)
+ fun_l5_n487(x)
+ else
+ fun_l5_n784(x)
+ end
+end
+
+def fun_l4_n556(x)
+ if (x < 1)
+ fun_l5_n485(x)
+ else
+ fun_l5_n984(x)
+ end
+end
+
+def fun_l4_n557(x)
+ if (x < 1)
+ fun_l5_n774(x)
+ else
+ fun_l5_n864(x)
+ end
+end
+
+def fun_l4_n558(x)
+ if (x < 1)
+ fun_l5_n823(x)
+ else
+ fun_l5_n527(x)
+ end
+end
+
+def fun_l4_n559(x)
+ if (x < 1)
+ fun_l5_n204(x)
+ else
+ fun_l5_n114(x)
+ end
+end
+
+def fun_l4_n560(x)
+ if (x < 1)
+ fun_l5_n835(x)
+ else
+ fun_l5_n930(x)
+ end
+end
+
+def fun_l4_n561(x)
+ if (x < 1)
+ fun_l5_n481(x)
+ else
+ fun_l5_n471(x)
+ end
+end
+
+def fun_l4_n562(x)
+ if (x < 1)
+ fun_l5_n459(x)
+ else
+ fun_l5_n526(x)
+ end
+end
+
+def fun_l4_n563(x)
+ if (x < 1)
+ fun_l5_n148(x)
+ else
+ fun_l5_n473(x)
+ end
+end
+
+def fun_l4_n564(x)
+ if (x < 1)
+ fun_l5_n448(x)
+ else
+ fun_l5_n389(x)
+ end
+end
+
+def fun_l4_n565(x)
+ if (x < 1)
+ fun_l5_n600(x)
+ else
+ fun_l5_n405(x)
+ end
+end
+
+def fun_l4_n566(x)
+ if (x < 1)
+ fun_l5_n67(x)
+ else
+ fun_l5_n145(x)
+ end
+end
+
+def fun_l4_n567(x)
+ if (x < 1)
+ fun_l5_n63(x)
+ else
+ fun_l5_n206(x)
+ end
+end
+
+def fun_l4_n568(x)
+ if (x < 1)
+ fun_l5_n463(x)
+ else
+ fun_l5_n288(x)
+ end
+end
+
+def fun_l4_n569(x)
+ if (x < 1)
+ fun_l5_n143(x)
+ else
+ fun_l5_n879(x)
+ end
+end
+
+def fun_l4_n570(x)
+ if (x < 1)
+ fun_l5_n552(x)
+ else
+ fun_l5_n517(x)
+ end
+end
+
+def fun_l4_n571(x)
+ if (x < 1)
+ fun_l5_n527(x)
+ else
+ fun_l5_n680(x)
+ end
+end
+
+def fun_l4_n572(x)
+ if (x < 1)
+ fun_l5_n853(x)
+ else
+ fun_l5_n97(x)
+ end
+end
+
+def fun_l4_n573(x)
+ if (x < 1)
+ fun_l5_n277(x)
+ else
+ fun_l5_n329(x)
+ end
+end
+
+def fun_l4_n574(x)
+ if (x < 1)
+ fun_l5_n952(x)
+ else
+ fun_l5_n515(x)
+ end
+end
+
+def fun_l4_n575(x)
+ if (x < 1)
+ fun_l5_n64(x)
+ else
+ fun_l5_n576(x)
+ end
+end
+
+def fun_l4_n576(x)
+ if (x < 1)
+ fun_l5_n57(x)
+ else
+ fun_l5_n499(x)
+ end
+end
+
+def fun_l4_n577(x)
+ if (x < 1)
+ fun_l5_n10(x)
+ else
+ fun_l5_n208(x)
+ end
+end
+
+def fun_l4_n578(x)
+ if (x < 1)
+ fun_l5_n361(x)
+ else
+ fun_l5_n447(x)
+ end
+end
+
+def fun_l4_n579(x)
+ if (x < 1)
+ fun_l5_n788(x)
+ else
+ fun_l5_n299(x)
+ end
+end
+
+def fun_l4_n580(x)
+ if (x < 1)
+ fun_l5_n973(x)
+ else
+ fun_l5_n753(x)
+ end
+end
+
+def fun_l4_n581(x)
+ if (x < 1)
+ fun_l5_n862(x)
+ else
+ fun_l5_n110(x)
+ end
+end
+
+def fun_l4_n582(x)
+ if (x < 1)
+ fun_l5_n760(x)
+ else
+ fun_l5_n256(x)
+ end
+end
+
+def fun_l4_n583(x)
+ if (x < 1)
+ fun_l5_n8(x)
+ else
+ fun_l5_n922(x)
+ end
+end
+
+def fun_l4_n584(x)
+ if (x < 1)
+ fun_l5_n100(x)
+ else
+ fun_l5_n230(x)
+ end
+end
+
+def fun_l4_n585(x)
+ if (x < 1)
+ fun_l5_n183(x)
+ else
+ fun_l5_n350(x)
+ end
+end
+
+def fun_l4_n586(x)
+ if (x < 1)
+ fun_l5_n294(x)
+ else
+ fun_l5_n673(x)
+ end
+end
+
+def fun_l4_n587(x)
+ if (x < 1)
+ fun_l5_n51(x)
+ else
+ fun_l5_n718(x)
+ end
+end
+
+def fun_l4_n588(x)
+ if (x < 1)
+ fun_l5_n257(x)
+ else
+ fun_l5_n111(x)
+ end
+end
+
+def fun_l4_n589(x)
+ if (x < 1)
+ fun_l5_n727(x)
+ else
+ fun_l5_n585(x)
+ end
+end
+
+def fun_l4_n590(x)
+ if (x < 1)
+ fun_l5_n205(x)
+ else
+ fun_l5_n308(x)
+ end
+end
+
+def fun_l4_n591(x)
+ if (x < 1)
+ fun_l5_n618(x)
+ else
+ fun_l5_n970(x)
+ end
+end
+
+def fun_l4_n592(x)
+ if (x < 1)
+ fun_l5_n631(x)
+ else
+ fun_l5_n513(x)
+ end
+end
+
+def fun_l4_n593(x)
+ if (x < 1)
+ fun_l5_n270(x)
+ else
+ fun_l5_n737(x)
+ end
+end
+
+def fun_l4_n594(x)
+ if (x < 1)
+ fun_l5_n464(x)
+ else
+ fun_l5_n217(x)
+ end
+end
+
+def fun_l4_n595(x)
+ if (x < 1)
+ fun_l5_n650(x)
+ else
+ fun_l5_n616(x)
+ end
+end
+
+def fun_l4_n596(x)
+ if (x < 1)
+ fun_l5_n542(x)
+ else
+ fun_l5_n613(x)
+ end
+end
+
+def fun_l4_n597(x)
+ if (x < 1)
+ fun_l5_n312(x)
+ else
+ fun_l5_n7(x)
+ end
+end
+
+def fun_l4_n598(x)
+ if (x < 1)
+ fun_l5_n164(x)
+ else
+ fun_l5_n592(x)
+ end
+end
+
+def fun_l4_n599(x)
+ if (x < 1)
+ fun_l5_n326(x)
+ else
+ fun_l5_n894(x)
+ end
+end
+
+def fun_l4_n600(x)
+ if (x < 1)
+ fun_l5_n243(x)
+ else
+ fun_l5_n233(x)
+ end
+end
+
+def fun_l4_n601(x)
+ if (x < 1)
+ fun_l5_n600(x)
+ else
+ fun_l5_n7(x)
+ end
+end
+
+def fun_l4_n602(x)
+ if (x < 1)
+ fun_l5_n334(x)
+ else
+ fun_l5_n282(x)
+ end
+end
+
+def fun_l4_n603(x)
+ if (x < 1)
+ fun_l5_n202(x)
+ else
+ fun_l5_n252(x)
+ end
+end
+
+def fun_l4_n604(x)
+ if (x < 1)
+ fun_l5_n173(x)
+ else
+ fun_l5_n685(x)
+ end
+end
+
+def fun_l4_n605(x)
+ if (x < 1)
+ fun_l5_n953(x)
+ else
+ fun_l5_n416(x)
+ end
+end
+
+def fun_l4_n606(x)
+ if (x < 1)
+ fun_l5_n775(x)
+ else
+ fun_l5_n372(x)
+ end
+end
+
+def fun_l4_n607(x)
+ if (x < 1)
+ fun_l5_n723(x)
+ else
+ fun_l5_n894(x)
+ end
+end
+
+def fun_l4_n608(x)
+ if (x < 1)
+ fun_l5_n690(x)
+ else
+ fun_l5_n26(x)
+ end
+end
+
+def fun_l4_n609(x)
+ if (x < 1)
+ fun_l5_n555(x)
+ else
+ fun_l5_n717(x)
+ end
+end
+
+def fun_l4_n610(x)
+ if (x < 1)
+ fun_l5_n597(x)
+ else
+ fun_l5_n106(x)
+ end
+end
+
+def fun_l4_n611(x)
+ if (x < 1)
+ fun_l5_n405(x)
+ else
+ fun_l5_n588(x)
+ end
+end
+
+def fun_l4_n612(x)
+ if (x < 1)
+ fun_l5_n41(x)
+ else
+ fun_l5_n558(x)
+ end
+end
+
+def fun_l4_n613(x)
+ if (x < 1)
+ fun_l5_n875(x)
+ else
+ fun_l5_n492(x)
+ end
+end
+
+def fun_l4_n614(x)
+ if (x < 1)
+ fun_l5_n605(x)
+ else
+ fun_l5_n461(x)
+ end
+end
+
+def fun_l4_n615(x)
+ if (x < 1)
+ fun_l5_n726(x)
+ else
+ fun_l5_n534(x)
+ end
+end
+
+def fun_l4_n616(x)
+ if (x < 1)
+ fun_l5_n919(x)
+ else
+ fun_l5_n404(x)
+ end
+end
+
+def fun_l4_n617(x)
+ if (x < 1)
+ fun_l5_n383(x)
+ else
+ fun_l5_n324(x)
+ end
+end
+
+def fun_l4_n618(x)
+ if (x < 1)
+ fun_l5_n286(x)
+ else
+ fun_l5_n157(x)
+ end
+end
+
+def fun_l4_n619(x)
+ if (x < 1)
+ fun_l5_n713(x)
+ else
+ fun_l5_n388(x)
+ end
+end
+
+def fun_l4_n620(x)
+ if (x < 1)
+ fun_l5_n773(x)
+ else
+ fun_l5_n790(x)
+ end
+end
+
+def fun_l4_n621(x)
+ if (x < 1)
+ fun_l5_n797(x)
+ else
+ fun_l5_n720(x)
+ end
+end
+
+def fun_l4_n622(x)
+ if (x < 1)
+ fun_l5_n799(x)
+ else
+ fun_l5_n423(x)
+ end
+end
+
+def fun_l4_n623(x)
+ if (x < 1)
+ fun_l5_n390(x)
+ else
+ fun_l5_n941(x)
+ end
+end
+
+def fun_l4_n624(x)
+ if (x < 1)
+ fun_l5_n584(x)
+ else
+ fun_l5_n191(x)
+ end
+end
+
+def fun_l4_n625(x)
+ if (x < 1)
+ fun_l5_n243(x)
+ else
+ fun_l5_n208(x)
+ end
+end
+
+def fun_l4_n626(x)
+ if (x < 1)
+ fun_l5_n136(x)
+ else
+ fun_l5_n791(x)
+ end
+end
+
+def fun_l4_n627(x)
+ if (x < 1)
+ fun_l5_n684(x)
+ else
+ fun_l5_n341(x)
+ end
+end
+
+def fun_l4_n628(x)
+ if (x < 1)
+ fun_l5_n876(x)
+ else
+ fun_l5_n27(x)
+ end
+end
+
+def fun_l4_n629(x)
+ if (x < 1)
+ fun_l5_n18(x)
+ else
+ fun_l5_n867(x)
+ end
+end
+
+def fun_l4_n630(x)
+ if (x < 1)
+ fun_l5_n4(x)
+ else
+ fun_l5_n871(x)
+ end
+end
+
+def fun_l4_n631(x)
+ if (x < 1)
+ fun_l5_n578(x)
+ else
+ fun_l5_n988(x)
+ end
+end
+
+def fun_l4_n632(x)
+ if (x < 1)
+ fun_l5_n388(x)
+ else
+ fun_l5_n258(x)
+ end
+end
+
+def fun_l4_n633(x)
+ if (x < 1)
+ fun_l5_n680(x)
+ else
+ fun_l5_n814(x)
+ end
+end
+
+def fun_l4_n634(x)
+ if (x < 1)
+ fun_l5_n857(x)
+ else
+ fun_l5_n595(x)
+ end
+end
+
+def fun_l4_n635(x)
+ if (x < 1)
+ fun_l5_n547(x)
+ else
+ fun_l5_n725(x)
+ end
+end
+
+def fun_l4_n636(x)
+ if (x < 1)
+ fun_l5_n644(x)
+ else
+ fun_l5_n485(x)
+ end
+end
+
+def fun_l4_n637(x)
+ if (x < 1)
+ fun_l5_n528(x)
+ else
+ fun_l5_n653(x)
+ end
+end
+
+def fun_l4_n638(x)
+ if (x < 1)
+ fun_l5_n924(x)
+ else
+ fun_l5_n956(x)
+ end
+end
+
+def fun_l4_n639(x)
+ if (x < 1)
+ fun_l5_n654(x)
+ else
+ fun_l5_n979(x)
+ end
+end
+
+def fun_l4_n640(x)
+ if (x < 1)
+ fun_l5_n287(x)
+ else
+ fun_l5_n778(x)
+ end
+end
+
+def fun_l4_n641(x)
+ if (x < 1)
+ fun_l5_n197(x)
+ else
+ fun_l5_n682(x)
+ end
+end
+
+def fun_l4_n642(x)
+ if (x < 1)
+ fun_l5_n559(x)
+ else
+ fun_l5_n812(x)
+ end
+end
+
+def fun_l4_n643(x)
+ if (x < 1)
+ fun_l5_n970(x)
+ else
+ fun_l5_n43(x)
+ end
+end
+
+def fun_l4_n644(x)
+ if (x < 1)
+ fun_l5_n222(x)
+ else
+ fun_l5_n741(x)
+ end
+end
+
+def fun_l4_n645(x)
+ if (x < 1)
+ fun_l5_n788(x)
+ else
+ fun_l5_n72(x)
+ end
+end
+
+def fun_l4_n646(x)
+ if (x < 1)
+ fun_l5_n877(x)
+ else
+ fun_l5_n371(x)
+ end
+end
+
+def fun_l4_n647(x)
+ if (x < 1)
+ fun_l5_n710(x)
+ else
+ fun_l5_n783(x)
+ end
+end
+
+def fun_l4_n648(x)
+ if (x < 1)
+ fun_l5_n957(x)
+ else
+ fun_l5_n801(x)
+ end
+end
+
+def fun_l4_n649(x)
+ if (x < 1)
+ fun_l5_n127(x)
+ else
+ fun_l5_n664(x)
+ end
+end
+
+def fun_l4_n650(x)
+ if (x < 1)
+ fun_l5_n176(x)
+ else
+ fun_l5_n511(x)
+ end
+end
+
+def fun_l4_n651(x)
+ if (x < 1)
+ fun_l5_n830(x)
+ else
+ fun_l5_n107(x)
+ end
+end
+
+def fun_l4_n652(x)
+ if (x < 1)
+ fun_l5_n207(x)
+ else
+ fun_l5_n894(x)
+ end
+end
+
+def fun_l4_n653(x)
+ if (x < 1)
+ fun_l5_n611(x)
+ else
+ fun_l5_n443(x)
+ end
+end
+
+def fun_l4_n654(x)
+ if (x < 1)
+ fun_l5_n953(x)
+ else
+ fun_l5_n214(x)
+ end
+end
+
+def fun_l4_n655(x)
+ if (x < 1)
+ fun_l5_n109(x)
+ else
+ fun_l5_n706(x)
+ end
+end
+
+def fun_l4_n656(x)
+ if (x < 1)
+ fun_l5_n312(x)
+ else
+ fun_l5_n914(x)
+ end
+end
+
+def fun_l4_n657(x)
+ if (x < 1)
+ fun_l5_n774(x)
+ else
+ fun_l5_n530(x)
+ end
+end
+
+def fun_l4_n658(x)
+ if (x < 1)
+ fun_l5_n79(x)
+ else
+ fun_l5_n303(x)
+ end
+end
+
+def fun_l4_n659(x)
+ if (x < 1)
+ fun_l5_n718(x)
+ else
+ fun_l5_n196(x)
+ end
+end
+
+def fun_l4_n660(x)
+ if (x < 1)
+ fun_l5_n196(x)
+ else
+ fun_l5_n661(x)
+ end
+end
+
+def fun_l4_n661(x)
+ if (x < 1)
+ fun_l5_n654(x)
+ else
+ fun_l5_n17(x)
+ end
+end
+
+def fun_l4_n662(x)
+ if (x < 1)
+ fun_l5_n413(x)
+ else
+ fun_l5_n214(x)
+ end
+end
+
+def fun_l4_n663(x)
+ if (x < 1)
+ fun_l5_n491(x)
+ else
+ fun_l5_n927(x)
+ end
+end
+
+def fun_l4_n664(x)
+ if (x < 1)
+ fun_l5_n671(x)
+ else
+ fun_l5_n611(x)
+ end
+end
+
+def fun_l4_n665(x)
+ if (x < 1)
+ fun_l5_n153(x)
+ else
+ fun_l5_n127(x)
+ end
+end
+
+def fun_l4_n666(x)
+ if (x < 1)
+ fun_l5_n661(x)
+ else
+ fun_l5_n590(x)
+ end
+end
+
+def fun_l4_n667(x)
+ if (x < 1)
+ fun_l5_n539(x)
+ else
+ fun_l5_n692(x)
+ end
+end
+
+def fun_l4_n668(x)
+ if (x < 1)
+ fun_l5_n390(x)
+ else
+ fun_l5_n423(x)
+ end
+end
+
+def fun_l4_n669(x)
+ if (x < 1)
+ fun_l5_n615(x)
+ else
+ fun_l5_n449(x)
+ end
+end
+
+def fun_l4_n670(x)
+ if (x < 1)
+ fun_l5_n49(x)
+ else
+ fun_l5_n632(x)
+ end
+end
+
+def fun_l4_n671(x)
+ if (x < 1)
+ fun_l5_n891(x)
+ else
+ fun_l5_n915(x)
+ end
+end
+
+def fun_l4_n672(x)
+ if (x < 1)
+ fun_l5_n257(x)
+ else
+ fun_l5_n719(x)
+ end
+end
+
+def fun_l4_n673(x)
+ if (x < 1)
+ fun_l5_n620(x)
+ else
+ fun_l5_n473(x)
+ end
+end
+
+def fun_l4_n674(x)
+ if (x < 1)
+ fun_l5_n422(x)
+ else
+ fun_l5_n776(x)
+ end
+end
+
+def fun_l4_n675(x)
+ if (x < 1)
+ fun_l5_n973(x)
+ else
+ fun_l5_n32(x)
+ end
+end
+
+def fun_l4_n676(x)
+ if (x < 1)
+ fun_l5_n434(x)
+ else
+ fun_l5_n85(x)
+ end
+end
+
+def fun_l4_n677(x)
+ if (x < 1)
+ fun_l5_n430(x)
+ else
+ fun_l5_n702(x)
+ end
+end
+
+def fun_l4_n678(x)
+ if (x < 1)
+ fun_l5_n698(x)
+ else
+ fun_l5_n482(x)
+ end
+end
+
+def fun_l4_n679(x)
+ if (x < 1)
+ fun_l5_n365(x)
+ else
+ fun_l5_n83(x)
+ end
+end
+
+def fun_l4_n680(x)
+ if (x < 1)
+ fun_l5_n397(x)
+ else
+ fun_l5_n356(x)
+ end
+end
+
+def fun_l4_n681(x)
+ if (x < 1)
+ fun_l5_n48(x)
+ else
+ fun_l5_n458(x)
+ end
+end
+
+def fun_l4_n682(x)
+ if (x < 1)
+ fun_l5_n205(x)
+ else
+ fun_l5_n693(x)
+ end
+end
+
+def fun_l4_n683(x)
+ if (x < 1)
+ fun_l5_n971(x)
+ else
+ fun_l5_n656(x)
+ end
+end
+
+def fun_l4_n684(x)
+ if (x < 1)
+ fun_l5_n147(x)
+ else
+ fun_l5_n314(x)
+ end
+end
+
+def fun_l4_n685(x)
+ if (x < 1)
+ fun_l5_n347(x)
+ else
+ fun_l5_n281(x)
+ end
+end
+
+def fun_l4_n686(x)
+ if (x < 1)
+ fun_l5_n259(x)
+ else
+ fun_l5_n395(x)
+ end
+end
+
+def fun_l4_n687(x)
+ if (x < 1)
+ fun_l5_n899(x)
+ else
+ fun_l5_n319(x)
+ end
+end
+
+def fun_l4_n688(x)
+ if (x < 1)
+ fun_l5_n293(x)
+ else
+ fun_l5_n831(x)
+ end
+end
+
+def fun_l4_n689(x)
+ if (x < 1)
+ fun_l5_n88(x)
+ else
+ fun_l5_n938(x)
+ end
+end
+
+def fun_l4_n690(x)
+ if (x < 1)
+ fun_l5_n72(x)
+ else
+ fun_l5_n172(x)
+ end
+end
+
+def fun_l4_n691(x)
+ if (x < 1)
+ fun_l5_n330(x)
+ else
+ fun_l5_n70(x)
+ end
+end
+
+def fun_l4_n692(x)
+ if (x < 1)
+ fun_l5_n901(x)
+ else
+ fun_l5_n984(x)
+ end
+end
+
+def fun_l4_n693(x)
+ if (x < 1)
+ fun_l5_n528(x)
+ else
+ fun_l5_n659(x)
+ end
+end
+
+def fun_l4_n694(x)
+ if (x < 1)
+ fun_l5_n522(x)
+ else
+ fun_l5_n219(x)
+ end
+end
+
+def fun_l4_n695(x)
+ if (x < 1)
+ fun_l5_n568(x)
+ else
+ fun_l5_n997(x)
+ end
+end
+
+def fun_l4_n696(x)
+ if (x < 1)
+ fun_l5_n248(x)
+ else
+ fun_l5_n508(x)
+ end
+end
+
+def fun_l4_n697(x)
+ if (x < 1)
+ fun_l5_n71(x)
+ else
+ fun_l5_n590(x)
+ end
+end
+
+def fun_l4_n698(x)
+ if (x < 1)
+ fun_l5_n398(x)
+ else
+ fun_l5_n125(x)
+ end
+end
+
+def fun_l4_n699(x)
+ if (x < 1)
+ fun_l5_n405(x)
+ else
+ fun_l5_n129(x)
+ end
+end
+
+def fun_l4_n700(x)
+ if (x < 1)
+ fun_l5_n818(x)
+ else
+ fun_l5_n792(x)
+ end
+end
+
+def fun_l4_n701(x)
+ if (x < 1)
+ fun_l5_n530(x)
+ else
+ fun_l5_n849(x)
+ end
+end
+
+def fun_l4_n702(x)
+ if (x < 1)
+ fun_l5_n640(x)
+ else
+ fun_l5_n558(x)
+ end
+end
+
+def fun_l4_n703(x)
+ if (x < 1)
+ fun_l5_n717(x)
+ else
+ fun_l5_n113(x)
+ end
+end
+
+def fun_l4_n704(x)
+ if (x < 1)
+ fun_l5_n139(x)
+ else
+ fun_l5_n743(x)
+ end
+end
+
+def fun_l4_n705(x)
+ if (x < 1)
+ fun_l5_n720(x)
+ else
+ fun_l5_n713(x)
+ end
+end
+
+def fun_l4_n706(x)
+ if (x < 1)
+ fun_l5_n774(x)
+ else
+ fun_l5_n90(x)
+ end
+end
+
+def fun_l4_n707(x)
+ if (x < 1)
+ fun_l5_n579(x)
+ else
+ fun_l5_n692(x)
+ end
+end
+
+def fun_l4_n708(x)
+ if (x < 1)
+ fun_l5_n448(x)
+ else
+ fun_l5_n146(x)
+ end
+end
+
+def fun_l4_n709(x)
+ if (x < 1)
+ fun_l5_n249(x)
+ else
+ fun_l5_n163(x)
+ end
+end
+
+def fun_l4_n710(x)
+ if (x < 1)
+ fun_l5_n694(x)
+ else
+ fun_l5_n532(x)
+ end
+end
+
+def fun_l4_n711(x)
+ if (x < 1)
+ fun_l5_n739(x)
+ else
+ fun_l5_n424(x)
+ end
+end
+
+def fun_l4_n712(x)
+ if (x < 1)
+ fun_l5_n700(x)
+ else
+ fun_l5_n761(x)
+ end
+end
+
+def fun_l4_n713(x)
+ if (x < 1)
+ fun_l5_n403(x)
+ else
+ fun_l5_n941(x)
+ end
+end
+
+def fun_l4_n714(x)
+ if (x < 1)
+ fun_l5_n724(x)
+ else
+ fun_l5_n863(x)
+ end
+end
+
+def fun_l4_n715(x)
+ if (x < 1)
+ fun_l5_n392(x)
+ else
+ fun_l5_n617(x)
+ end
+end
+
+def fun_l4_n716(x)
+ if (x < 1)
+ fun_l5_n76(x)
+ else
+ fun_l5_n896(x)
+ end
+end
+
+def fun_l4_n717(x)
+ if (x < 1)
+ fun_l5_n355(x)
+ else
+ fun_l5_n533(x)
+ end
+end
+
+def fun_l4_n718(x)
+ if (x < 1)
+ fun_l5_n225(x)
+ else
+ fun_l5_n273(x)
+ end
+end
+
+def fun_l4_n719(x)
+ if (x < 1)
+ fun_l5_n828(x)
+ else
+ fun_l5_n163(x)
+ end
+end
+
+def fun_l4_n720(x)
+ if (x < 1)
+ fun_l5_n309(x)
+ else
+ fun_l5_n702(x)
+ end
+end
+
+def fun_l4_n721(x)
+ if (x < 1)
+ fun_l5_n959(x)
+ else
+ fun_l5_n370(x)
+ end
+end
+
+def fun_l4_n722(x)
+ if (x < 1)
+ fun_l5_n640(x)
+ else
+ fun_l5_n96(x)
+ end
+end
+
+def fun_l4_n723(x)
+ if (x < 1)
+ fun_l5_n590(x)
+ else
+ fun_l5_n332(x)
+ end
+end
+
+def fun_l4_n724(x)
+ if (x < 1)
+ fun_l5_n14(x)
+ else
+ fun_l5_n161(x)
+ end
+end
+
+def fun_l4_n725(x)
+ if (x < 1)
+ fun_l5_n871(x)
+ else
+ fun_l5_n643(x)
+ end
+end
+
+def fun_l4_n726(x)
+ if (x < 1)
+ fun_l5_n885(x)
+ else
+ fun_l5_n142(x)
+ end
+end
+
+def fun_l4_n727(x)
+ if (x < 1)
+ fun_l5_n994(x)
+ else
+ fun_l5_n823(x)
+ end
+end
+
+def fun_l4_n728(x)
+ if (x < 1)
+ fun_l5_n825(x)
+ else
+ fun_l5_n315(x)
+ end
+end
+
+def fun_l4_n729(x)
+ if (x < 1)
+ fun_l5_n312(x)
+ else
+ fun_l5_n28(x)
+ end
+end
+
+def fun_l4_n730(x)
+ if (x < 1)
+ fun_l5_n545(x)
+ else
+ fun_l5_n87(x)
+ end
+end
+
+def fun_l4_n731(x)
+ if (x < 1)
+ fun_l5_n604(x)
+ else
+ fun_l5_n999(x)
+ end
+end
+
+def fun_l4_n732(x)
+ if (x < 1)
+ fun_l5_n21(x)
+ else
+ fun_l5_n170(x)
+ end
+end
+
+def fun_l4_n733(x)
+ if (x < 1)
+ fun_l5_n662(x)
+ else
+ fun_l5_n407(x)
+ end
+end
+
+def fun_l4_n734(x)
+ if (x < 1)
+ fun_l5_n808(x)
+ else
+ fun_l5_n653(x)
+ end
+end
+
+def fun_l4_n735(x)
+ if (x < 1)
+ fun_l5_n665(x)
+ else
+ fun_l5_n925(x)
+ end
+end
+
+def fun_l4_n736(x)
+ if (x < 1)
+ fun_l5_n186(x)
+ else
+ fun_l5_n817(x)
+ end
+end
+
+def fun_l4_n737(x)
+ if (x < 1)
+ fun_l5_n360(x)
+ else
+ fun_l5_n527(x)
+ end
+end
+
+def fun_l4_n738(x)
+ if (x < 1)
+ fun_l5_n278(x)
+ else
+ fun_l5_n759(x)
+ end
+end
+
+def fun_l4_n739(x)
+ if (x < 1)
+ fun_l5_n710(x)
+ else
+ fun_l5_n909(x)
+ end
+end
+
+def fun_l4_n740(x)
+ if (x < 1)
+ fun_l5_n770(x)
+ else
+ fun_l5_n382(x)
+ end
+end
+
+def fun_l4_n741(x)
+ if (x < 1)
+ fun_l5_n969(x)
+ else
+ fun_l5_n583(x)
+ end
+end
+
+def fun_l4_n742(x)
+ if (x < 1)
+ fun_l5_n653(x)
+ else
+ fun_l5_n258(x)
+ end
+end
+
+def fun_l4_n743(x)
+ if (x < 1)
+ fun_l5_n966(x)
+ else
+ fun_l5_n705(x)
+ end
+end
+
+def fun_l4_n744(x)
+ if (x < 1)
+ fun_l5_n454(x)
+ else
+ fun_l5_n748(x)
+ end
+end
+
+def fun_l4_n745(x)
+ if (x < 1)
+ fun_l5_n595(x)
+ else
+ fun_l5_n865(x)
+ end
+end
+
+def fun_l4_n746(x)
+ if (x < 1)
+ fun_l5_n593(x)
+ else
+ fun_l5_n615(x)
+ end
+end
+
+def fun_l4_n747(x)
+ if (x < 1)
+ fun_l5_n638(x)
+ else
+ fun_l5_n651(x)
+ end
+end
+
+def fun_l4_n748(x)
+ if (x < 1)
+ fun_l5_n331(x)
+ else
+ fun_l5_n847(x)
+ end
+end
+
+def fun_l4_n749(x)
+ if (x < 1)
+ fun_l5_n59(x)
+ else
+ fun_l5_n805(x)
+ end
+end
+
+def fun_l4_n750(x)
+ if (x < 1)
+ fun_l5_n269(x)
+ else
+ fun_l5_n904(x)
+ end
+end
+
+def fun_l4_n751(x)
+ if (x < 1)
+ fun_l5_n292(x)
+ else
+ fun_l5_n459(x)
+ end
+end
+
+def fun_l4_n752(x)
+ if (x < 1)
+ fun_l5_n581(x)
+ else
+ fun_l5_n353(x)
+ end
+end
+
+def fun_l4_n753(x)
+ if (x < 1)
+ fun_l5_n785(x)
+ else
+ fun_l5_n745(x)
+ end
+end
+
+def fun_l4_n754(x)
+ if (x < 1)
+ fun_l5_n317(x)
+ else
+ fun_l5_n604(x)
+ end
+end
+
+def fun_l4_n755(x)
+ if (x < 1)
+ fun_l5_n208(x)
+ else
+ fun_l5_n318(x)
+ end
+end
+
+def fun_l4_n756(x)
+ if (x < 1)
+ fun_l5_n986(x)
+ else
+ fun_l5_n83(x)
+ end
+end
+
+def fun_l4_n757(x)
+ if (x < 1)
+ fun_l5_n946(x)
+ else
+ fun_l5_n314(x)
+ end
+end
+
+def fun_l4_n758(x)
+ if (x < 1)
+ fun_l5_n571(x)
+ else
+ fun_l5_n919(x)
+ end
+end
+
+def fun_l4_n759(x)
+ if (x < 1)
+ fun_l5_n129(x)
+ else
+ fun_l5_n191(x)
+ end
+end
+
+def fun_l4_n760(x)
+ if (x < 1)
+ fun_l5_n838(x)
+ else
+ fun_l5_n29(x)
+ end
+end
+
+def fun_l4_n761(x)
+ if (x < 1)
+ fun_l5_n250(x)
+ else
+ fun_l5_n892(x)
+ end
+end
+
+def fun_l4_n762(x)
+ if (x < 1)
+ fun_l5_n588(x)
+ else
+ fun_l5_n59(x)
+ end
+end
+
+def fun_l4_n763(x)
+ if (x < 1)
+ fun_l5_n831(x)
+ else
+ fun_l5_n668(x)
+ end
+end
+
+def fun_l4_n764(x)
+ if (x < 1)
+ fun_l5_n337(x)
+ else
+ fun_l5_n514(x)
+ end
+end
+
+def fun_l4_n765(x)
+ if (x < 1)
+ fun_l5_n56(x)
+ else
+ fun_l5_n718(x)
+ end
+end
+
+def fun_l4_n766(x)
+ if (x < 1)
+ fun_l5_n189(x)
+ else
+ fun_l5_n103(x)
+ end
+end
+
+def fun_l4_n767(x)
+ if (x < 1)
+ fun_l5_n395(x)
+ else
+ fun_l5_n313(x)
+ end
+end
+
+def fun_l4_n768(x)
+ if (x < 1)
+ fun_l5_n388(x)
+ else
+ fun_l5_n757(x)
+ end
+end
+
+def fun_l4_n769(x)
+ if (x < 1)
+ fun_l5_n933(x)
+ else
+ fun_l5_n979(x)
+ end
+end
+
+def fun_l4_n770(x)
+ if (x < 1)
+ fun_l5_n765(x)
+ else
+ fun_l5_n472(x)
+ end
+end
+
+def fun_l4_n771(x)
+ if (x < 1)
+ fun_l5_n381(x)
+ else
+ fun_l5_n527(x)
+ end
+end
+
+def fun_l4_n772(x)
+ if (x < 1)
+ fun_l5_n314(x)
+ else
+ fun_l5_n990(x)
+ end
+end
+
+def fun_l4_n773(x)
+ if (x < 1)
+ fun_l5_n457(x)
+ else
+ fun_l5_n413(x)
+ end
+end
+
+def fun_l4_n774(x)
+ if (x < 1)
+ fun_l5_n245(x)
+ else
+ fun_l5_n85(x)
+ end
+end
+
+def fun_l4_n775(x)
+ if (x < 1)
+ fun_l5_n432(x)
+ else
+ fun_l5_n987(x)
+ end
+end
+
+def fun_l4_n776(x)
+ if (x < 1)
+ fun_l5_n588(x)
+ else
+ fun_l5_n352(x)
+ end
+end
+
+def fun_l4_n777(x)
+ if (x < 1)
+ fun_l5_n414(x)
+ else
+ fun_l5_n586(x)
+ end
+end
+
+def fun_l4_n778(x)
+ if (x < 1)
+ fun_l5_n290(x)
+ else
+ fun_l5_n776(x)
+ end
+end
+
+def fun_l4_n779(x)
+ if (x < 1)
+ fun_l5_n324(x)
+ else
+ fun_l5_n918(x)
+ end
+end
+
+def fun_l4_n780(x)
+ if (x < 1)
+ fun_l5_n928(x)
+ else
+ fun_l5_n107(x)
+ end
+end
+
+def fun_l4_n781(x)
+ if (x < 1)
+ fun_l5_n244(x)
+ else
+ fun_l5_n434(x)
+ end
+end
+
+def fun_l4_n782(x)
+ if (x < 1)
+ fun_l5_n828(x)
+ else
+ fun_l5_n141(x)
+ end
+end
+
+def fun_l4_n783(x)
+ if (x < 1)
+ fun_l5_n634(x)
+ else
+ fun_l5_n206(x)
+ end
+end
+
+def fun_l4_n784(x)
+ if (x < 1)
+ fun_l5_n387(x)
+ else
+ fun_l5_n57(x)
+ end
+end
+
+def fun_l4_n785(x)
+ if (x < 1)
+ fun_l5_n731(x)
+ else
+ fun_l5_n670(x)
+ end
+end
+
+def fun_l4_n786(x)
+ if (x < 1)
+ fun_l5_n173(x)
+ else
+ fun_l5_n657(x)
+ end
+end
+
+def fun_l4_n787(x)
+ if (x < 1)
+ fun_l5_n661(x)
+ else
+ fun_l5_n286(x)
+ end
+end
+
+def fun_l4_n788(x)
+ if (x < 1)
+ fun_l5_n364(x)
+ else
+ fun_l5_n520(x)
+ end
+end
+
+def fun_l4_n789(x)
+ if (x < 1)
+ fun_l5_n545(x)
+ else
+ fun_l5_n417(x)
+ end
+end
+
+def fun_l4_n790(x)
+ if (x < 1)
+ fun_l5_n270(x)
+ else
+ fun_l5_n550(x)
+ end
+end
+
+def fun_l4_n791(x)
+ if (x < 1)
+ fun_l5_n873(x)
+ else
+ fun_l5_n321(x)
+ end
+end
+
+def fun_l4_n792(x)
+ if (x < 1)
+ fun_l5_n243(x)
+ else
+ fun_l5_n406(x)
+ end
+end
+
+def fun_l4_n793(x)
+ if (x < 1)
+ fun_l5_n229(x)
+ else
+ fun_l5_n400(x)
+ end
+end
+
+def fun_l4_n794(x)
+ if (x < 1)
+ fun_l5_n670(x)
+ else
+ fun_l5_n535(x)
+ end
+end
+
+def fun_l4_n795(x)
+ if (x < 1)
+ fun_l5_n911(x)
+ else
+ fun_l5_n786(x)
+ end
+end
+
+def fun_l4_n796(x)
+ if (x < 1)
+ fun_l5_n247(x)
+ else
+ fun_l5_n775(x)
+ end
+end
+
+def fun_l4_n797(x)
+ if (x < 1)
+ fun_l5_n944(x)
+ else
+ fun_l5_n14(x)
+ end
+end
+
+def fun_l4_n798(x)
+ if (x < 1)
+ fun_l5_n57(x)
+ else
+ fun_l5_n644(x)
+ end
+end
+
+def fun_l4_n799(x)
+ if (x < 1)
+ fun_l5_n583(x)
+ else
+ fun_l5_n599(x)
+ end
+end
+
+def fun_l4_n800(x)
+ if (x < 1)
+ fun_l5_n685(x)
+ else
+ fun_l5_n366(x)
+ end
+end
+
+def fun_l4_n801(x)
+ if (x < 1)
+ fun_l5_n671(x)
+ else
+ fun_l5_n386(x)
+ end
+end
+
+def fun_l4_n802(x)
+ if (x < 1)
+ fun_l5_n19(x)
+ else
+ fun_l5_n403(x)
+ end
+end
+
+def fun_l4_n803(x)
+ if (x < 1)
+ fun_l5_n952(x)
+ else
+ fun_l5_n237(x)
+ end
+end
+
+def fun_l4_n804(x)
+ if (x < 1)
+ fun_l5_n929(x)
+ else
+ fun_l5_n737(x)
+ end
+end
+
+def fun_l4_n805(x)
+ if (x < 1)
+ fun_l5_n197(x)
+ else
+ fun_l5_n322(x)
+ end
+end
+
+def fun_l4_n806(x)
+ if (x < 1)
+ fun_l5_n966(x)
+ else
+ fun_l5_n531(x)
+ end
+end
+
+def fun_l4_n807(x)
+ if (x < 1)
+ fun_l5_n928(x)
+ else
+ fun_l5_n802(x)
+ end
+end
+
+def fun_l4_n808(x)
+ if (x < 1)
+ fun_l5_n34(x)
+ else
+ fun_l5_n107(x)
+ end
+end
+
+def fun_l4_n809(x)
+ if (x < 1)
+ fun_l5_n615(x)
+ else
+ fun_l5_n628(x)
+ end
+end
+
+def fun_l4_n810(x)
+ if (x < 1)
+ fun_l5_n187(x)
+ else
+ fun_l5_n424(x)
+ end
+end
+
+def fun_l4_n811(x)
+ if (x < 1)
+ fun_l5_n189(x)
+ else
+ fun_l5_n639(x)
+ end
+end
+
+def fun_l4_n812(x)
+ if (x < 1)
+ fun_l5_n177(x)
+ else
+ fun_l5_n580(x)
+ end
+end
+
+def fun_l4_n813(x)
+ if (x < 1)
+ fun_l5_n699(x)
+ else
+ fun_l5_n595(x)
+ end
+end
+
+def fun_l4_n814(x)
+ if (x < 1)
+ fun_l5_n44(x)
+ else
+ fun_l5_n966(x)
+ end
+end
+
+def fun_l4_n815(x)
+ if (x < 1)
+ fun_l5_n883(x)
+ else
+ fun_l5_n580(x)
+ end
+end
+
+def fun_l4_n816(x)
+ if (x < 1)
+ fun_l5_n306(x)
+ else
+ fun_l5_n564(x)
+ end
+end
+
+def fun_l4_n817(x)
+ if (x < 1)
+ fun_l5_n337(x)
+ else
+ fun_l5_n912(x)
+ end
+end
+
+def fun_l4_n818(x)
+ if (x < 1)
+ fun_l5_n36(x)
+ else
+ fun_l5_n164(x)
+ end
+end
+
+def fun_l4_n819(x)
+ if (x < 1)
+ fun_l5_n987(x)
+ else
+ fun_l5_n38(x)
+ end
+end
+
+def fun_l4_n820(x)
+ if (x < 1)
+ fun_l5_n656(x)
+ else
+ fun_l5_n647(x)
+ end
+end
+
+def fun_l4_n821(x)
+ if (x < 1)
+ fun_l5_n364(x)
+ else
+ fun_l5_n838(x)
+ end
+end
+
+def fun_l4_n822(x)
+ if (x < 1)
+ fun_l5_n301(x)
+ else
+ fun_l5_n850(x)
+ end
+end
+
+def fun_l4_n823(x)
+ if (x < 1)
+ fun_l5_n191(x)
+ else
+ fun_l5_n812(x)
+ end
+end
+
+def fun_l4_n824(x)
+ if (x < 1)
+ fun_l5_n148(x)
+ else
+ fun_l5_n332(x)
+ end
+end
+
+def fun_l4_n825(x)
+ if (x < 1)
+ fun_l5_n315(x)
+ else
+ fun_l5_n763(x)
+ end
+end
+
+def fun_l4_n826(x)
+ if (x < 1)
+ fun_l5_n612(x)
+ else
+ fun_l5_n993(x)
+ end
+end
+
+def fun_l4_n827(x)
+ if (x < 1)
+ fun_l5_n229(x)
+ else
+ fun_l5_n388(x)
+ end
+end
+
+def fun_l4_n828(x)
+ if (x < 1)
+ fun_l5_n131(x)
+ else
+ fun_l5_n283(x)
+ end
+end
+
+def fun_l4_n829(x)
+ if (x < 1)
+ fun_l5_n59(x)
+ else
+ fun_l5_n280(x)
+ end
+end
+
+def fun_l4_n830(x)
+ if (x < 1)
+ fun_l5_n993(x)
+ else
+ fun_l5_n160(x)
+ end
+end
+
+def fun_l4_n831(x)
+ if (x < 1)
+ fun_l5_n394(x)
+ else
+ fun_l5_n528(x)
+ end
+end
+
+def fun_l4_n832(x)
+ if (x < 1)
+ fun_l5_n376(x)
+ else
+ fun_l5_n201(x)
+ end
+end
+
+def fun_l4_n833(x)
+ if (x < 1)
+ fun_l5_n890(x)
+ else
+ fun_l5_n867(x)
+ end
+end
+
+def fun_l4_n834(x)
+ if (x < 1)
+ fun_l5_n320(x)
+ else
+ fun_l5_n237(x)
+ end
+end
+
+def fun_l4_n835(x)
+ if (x < 1)
+ fun_l5_n771(x)
+ else
+ fun_l5_n83(x)
+ end
+end
+
+def fun_l4_n836(x)
+ if (x < 1)
+ fun_l5_n751(x)
+ else
+ fun_l5_n2(x)
+ end
+end
+
+def fun_l4_n837(x)
+ if (x < 1)
+ fun_l5_n825(x)
+ else
+ fun_l5_n930(x)
+ end
+end
+
+def fun_l4_n838(x)
+ if (x < 1)
+ fun_l5_n968(x)
+ else
+ fun_l5_n136(x)
+ end
+end
+
+def fun_l4_n839(x)
+ if (x < 1)
+ fun_l5_n529(x)
+ else
+ fun_l5_n626(x)
+ end
+end
+
+def fun_l4_n840(x)
+ if (x < 1)
+ fun_l5_n228(x)
+ else
+ fun_l5_n915(x)
+ end
+end
+
+def fun_l4_n841(x)
+ if (x < 1)
+ fun_l5_n270(x)
+ else
+ fun_l5_n813(x)
+ end
+end
+
+def fun_l4_n842(x)
+ if (x < 1)
+ fun_l5_n392(x)
+ else
+ fun_l5_n60(x)
+ end
+end
+
+def fun_l4_n843(x)
+ if (x < 1)
+ fun_l5_n470(x)
+ else
+ fun_l5_n699(x)
+ end
+end
+
+def fun_l4_n844(x)
+ if (x < 1)
+ fun_l5_n68(x)
+ else
+ fun_l5_n163(x)
+ end
+end
+
+def fun_l4_n845(x)
+ if (x < 1)
+ fun_l5_n469(x)
+ else
+ fun_l5_n472(x)
+ end
+end
+
+def fun_l4_n846(x)
+ if (x < 1)
+ fun_l5_n640(x)
+ else
+ fun_l5_n311(x)
+ end
+end
+
+def fun_l4_n847(x)
+ if (x < 1)
+ fun_l5_n968(x)
+ else
+ fun_l5_n414(x)
+ end
+end
+
+def fun_l4_n848(x)
+ if (x < 1)
+ fun_l5_n111(x)
+ else
+ fun_l5_n340(x)
+ end
+end
+
+def fun_l4_n849(x)
+ if (x < 1)
+ fun_l5_n906(x)
+ else
+ fun_l5_n278(x)
+ end
+end
+
+def fun_l4_n850(x)
+ if (x < 1)
+ fun_l5_n353(x)
+ else
+ fun_l5_n590(x)
+ end
+end
+
+def fun_l4_n851(x)
+ if (x < 1)
+ fun_l5_n218(x)
+ else
+ fun_l5_n341(x)
+ end
+end
+
+def fun_l4_n852(x)
+ if (x < 1)
+ fun_l5_n527(x)
+ else
+ fun_l5_n273(x)
+ end
+end
+
+def fun_l4_n853(x)
+ if (x < 1)
+ fun_l5_n589(x)
+ else
+ fun_l5_n417(x)
+ end
+end
+
+def fun_l4_n854(x)
+ if (x < 1)
+ fun_l5_n411(x)
+ else
+ fun_l5_n848(x)
+ end
+end
+
+def fun_l4_n855(x)
+ if (x < 1)
+ fun_l5_n607(x)
+ else
+ fun_l5_n65(x)
+ end
+end
+
+def fun_l4_n856(x)
+ if (x < 1)
+ fun_l5_n240(x)
+ else
+ fun_l5_n24(x)
+ end
+end
+
+def fun_l4_n857(x)
+ if (x < 1)
+ fun_l5_n165(x)
+ else
+ fun_l5_n362(x)
+ end
+end
+
+def fun_l4_n858(x)
+ if (x < 1)
+ fun_l5_n559(x)
+ else
+ fun_l5_n253(x)
+ end
+end
+
+def fun_l4_n859(x)
+ if (x < 1)
+ fun_l5_n834(x)
+ else
+ fun_l5_n217(x)
+ end
+end
+
+def fun_l4_n860(x)
+ if (x < 1)
+ fun_l5_n891(x)
+ else
+ fun_l5_n369(x)
+ end
+end
+
+def fun_l4_n861(x)
+ if (x < 1)
+ fun_l5_n676(x)
+ else
+ fun_l5_n614(x)
+ end
+end
+
+def fun_l4_n862(x)
+ if (x < 1)
+ fun_l5_n527(x)
+ else
+ fun_l5_n318(x)
+ end
+end
+
+def fun_l4_n863(x)
+ if (x < 1)
+ fun_l5_n991(x)
+ else
+ fun_l5_n997(x)
+ end
+end
+
+def fun_l4_n864(x)
+ if (x < 1)
+ fun_l5_n842(x)
+ else
+ fun_l5_n370(x)
+ end
+end
+
+def fun_l4_n865(x)
+ if (x < 1)
+ fun_l5_n623(x)
+ else
+ fun_l5_n741(x)
+ end
+end
+
+def fun_l4_n866(x)
+ if (x < 1)
+ fun_l5_n58(x)
+ else
+ fun_l5_n953(x)
+ end
+end
+
+def fun_l4_n867(x)
+ if (x < 1)
+ fun_l5_n269(x)
+ else
+ fun_l5_n341(x)
+ end
+end
+
+def fun_l4_n868(x)
+ if (x < 1)
+ fun_l5_n814(x)
+ else
+ fun_l5_n849(x)
+ end
+end
+
+def fun_l4_n869(x)
+ if (x < 1)
+ fun_l5_n163(x)
+ else
+ fun_l5_n246(x)
+ end
+end
+
+def fun_l4_n870(x)
+ if (x < 1)
+ fun_l5_n739(x)
+ else
+ fun_l5_n524(x)
+ end
+end
+
+def fun_l4_n871(x)
+ if (x < 1)
+ fun_l5_n589(x)
+ else
+ fun_l5_n592(x)
+ end
+end
+
+def fun_l4_n872(x)
+ if (x < 1)
+ fun_l5_n922(x)
+ else
+ fun_l5_n401(x)
+ end
+end
+
+def fun_l4_n873(x)
+ if (x < 1)
+ fun_l5_n600(x)
+ else
+ fun_l5_n184(x)
+ end
+end
+
+def fun_l4_n874(x)
+ if (x < 1)
+ fun_l5_n424(x)
+ else
+ fun_l5_n627(x)
+ end
+end
+
+def fun_l4_n875(x)
+ if (x < 1)
+ fun_l5_n48(x)
+ else
+ fun_l5_n127(x)
+ end
+end
+
+def fun_l4_n876(x)
+ if (x < 1)
+ fun_l5_n687(x)
+ else
+ fun_l5_n451(x)
+ end
+end
+
+def fun_l4_n877(x)
+ if (x < 1)
+ fun_l5_n849(x)
+ else
+ fun_l5_n480(x)
+ end
+end
+
+def fun_l4_n878(x)
+ if (x < 1)
+ fun_l5_n801(x)
+ else
+ fun_l5_n60(x)
+ end
+end
+
+def fun_l4_n879(x)
+ if (x < 1)
+ fun_l5_n964(x)
+ else
+ fun_l5_n790(x)
+ end
+end
+
+def fun_l4_n880(x)
+ if (x < 1)
+ fun_l5_n483(x)
+ else
+ fun_l5_n817(x)
+ end
+end
+
+def fun_l4_n881(x)
+ if (x < 1)
+ fun_l5_n91(x)
+ else
+ fun_l5_n776(x)
+ end
+end
+
+def fun_l4_n882(x)
+ if (x < 1)
+ fun_l5_n8(x)
+ else
+ fun_l5_n726(x)
+ end
+end
+
+def fun_l4_n883(x)
+ if (x < 1)
+ fun_l5_n63(x)
+ else
+ fun_l5_n570(x)
+ end
+end
+
+def fun_l4_n884(x)
+ if (x < 1)
+ fun_l5_n691(x)
+ else
+ fun_l5_n117(x)
+ end
+end
+
+def fun_l4_n885(x)
+ if (x < 1)
+ fun_l5_n262(x)
+ else
+ fun_l5_n38(x)
+ end
+end
+
+def fun_l4_n886(x)
+ if (x < 1)
+ fun_l5_n678(x)
+ else
+ fun_l5_n108(x)
+ end
+end
+
+def fun_l4_n887(x)
+ if (x < 1)
+ fun_l5_n775(x)
+ else
+ fun_l5_n751(x)
+ end
+end
+
+def fun_l4_n888(x)
+ if (x < 1)
+ fun_l5_n917(x)
+ else
+ fun_l5_n769(x)
+ end
+end
+
+def fun_l4_n889(x)
+ if (x < 1)
+ fun_l5_n191(x)
+ else
+ fun_l5_n662(x)
+ end
+end
+
+def fun_l4_n890(x)
+ if (x < 1)
+ fun_l5_n34(x)
+ else
+ fun_l5_n806(x)
+ end
+end
+
+def fun_l4_n891(x)
+ if (x < 1)
+ fun_l5_n705(x)
+ else
+ fun_l5_n198(x)
+ end
+end
+
+def fun_l4_n892(x)
+ if (x < 1)
+ fun_l5_n647(x)
+ else
+ fun_l5_n0(x)
+ end
+end
+
+def fun_l4_n893(x)
+ if (x < 1)
+ fun_l5_n336(x)
+ else
+ fun_l5_n795(x)
+ end
+end
+
+def fun_l4_n894(x)
+ if (x < 1)
+ fun_l5_n984(x)
+ else
+ fun_l5_n751(x)
+ end
+end
+
+def fun_l4_n895(x)
+ if (x < 1)
+ fun_l5_n373(x)
+ else
+ fun_l5_n12(x)
+ end
+end
+
+def fun_l4_n896(x)
+ if (x < 1)
+ fun_l5_n672(x)
+ else
+ fun_l5_n17(x)
+ end
+end
+
+def fun_l4_n897(x)
+ if (x < 1)
+ fun_l5_n67(x)
+ else
+ fun_l5_n183(x)
+ end
+end
+
+def fun_l4_n898(x)
+ if (x < 1)
+ fun_l5_n557(x)
+ else
+ fun_l5_n43(x)
+ end
+end
+
+def fun_l4_n899(x)
+ if (x < 1)
+ fun_l5_n210(x)
+ else
+ fun_l5_n904(x)
+ end
+end
+
+def fun_l4_n900(x)
+ if (x < 1)
+ fun_l5_n665(x)
+ else
+ fun_l5_n173(x)
+ end
+end
+
+def fun_l4_n901(x)
+ if (x < 1)
+ fun_l5_n268(x)
+ else
+ fun_l5_n907(x)
+ end
+end
+
+def fun_l4_n902(x)
+ if (x < 1)
+ fun_l5_n19(x)
+ else
+ fun_l5_n145(x)
+ end
+end
+
+def fun_l4_n903(x)
+ if (x < 1)
+ fun_l5_n158(x)
+ else
+ fun_l5_n261(x)
+ end
+end
+
+def fun_l4_n904(x)
+ if (x < 1)
+ fun_l5_n677(x)
+ else
+ fun_l5_n880(x)
+ end
+end
+
+def fun_l4_n905(x)
+ if (x < 1)
+ fun_l5_n262(x)
+ else
+ fun_l5_n790(x)
+ end
+end
+
+def fun_l4_n906(x)
+ if (x < 1)
+ fun_l5_n775(x)
+ else
+ fun_l5_n785(x)
+ end
+end
+
+def fun_l4_n907(x)
+ if (x < 1)
+ fun_l5_n629(x)
+ else
+ fun_l5_n312(x)
+ end
+end
+
+def fun_l4_n908(x)
+ if (x < 1)
+ fun_l5_n84(x)
+ else
+ fun_l5_n605(x)
+ end
+end
+
+def fun_l4_n909(x)
+ if (x < 1)
+ fun_l5_n346(x)
+ else
+ fun_l5_n245(x)
+ end
+end
+
+def fun_l4_n910(x)
+ if (x < 1)
+ fun_l5_n768(x)
+ else
+ fun_l5_n47(x)
+ end
+end
+
+def fun_l4_n911(x)
+ if (x < 1)
+ fun_l5_n48(x)
+ else
+ fun_l5_n406(x)
+ end
+end
+
+def fun_l4_n912(x)
+ if (x < 1)
+ fun_l5_n493(x)
+ else
+ fun_l5_n608(x)
+ end
+end
+
+def fun_l4_n913(x)
+ if (x < 1)
+ fun_l5_n456(x)
+ else
+ fun_l5_n176(x)
+ end
+end
+
+def fun_l4_n914(x)
+ if (x < 1)
+ fun_l5_n201(x)
+ else
+ fun_l5_n233(x)
+ end
+end
+
+def fun_l4_n915(x)
+ if (x < 1)
+ fun_l5_n910(x)
+ else
+ fun_l5_n790(x)
+ end
+end
+
+def fun_l4_n916(x)
+ if (x < 1)
+ fun_l5_n734(x)
+ else
+ fun_l5_n685(x)
+ end
+end
+
+def fun_l4_n917(x)
+ if (x < 1)
+ fun_l5_n132(x)
+ else
+ fun_l5_n112(x)
+ end
+end
+
+def fun_l4_n918(x)
+ if (x < 1)
+ fun_l5_n897(x)
+ else
+ fun_l5_n196(x)
+ end
+end
+
+def fun_l4_n919(x)
+ if (x < 1)
+ fun_l5_n395(x)
+ else
+ fun_l5_n186(x)
+ end
+end
+
+def fun_l4_n920(x)
+ if (x < 1)
+ fun_l5_n19(x)
+ else
+ fun_l5_n810(x)
+ end
+end
+
+def fun_l4_n921(x)
+ if (x < 1)
+ fun_l5_n546(x)
+ else
+ fun_l5_n34(x)
+ end
+end
+
+def fun_l4_n922(x)
+ if (x < 1)
+ fun_l5_n863(x)
+ else
+ fun_l5_n928(x)
+ end
+end
+
+def fun_l4_n923(x)
+ if (x < 1)
+ fun_l5_n485(x)
+ else
+ fun_l5_n182(x)
+ end
+end
+
+def fun_l4_n924(x)
+ if (x < 1)
+ fun_l5_n303(x)
+ else
+ fun_l5_n17(x)
+ end
+end
+
+def fun_l4_n925(x)
+ if (x < 1)
+ fun_l5_n78(x)
+ else
+ fun_l5_n816(x)
+ end
+end
+
+def fun_l4_n926(x)
+ if (x < 1)
+ fun_l5_n797(x)
+ else
+ fun_l5_n761(x)
+ end
+end
+
+def fun_l4_n927(x)
+ if (x < 1)
+ fun_l5_n975(x)
+ else
+ fun_l5_n220(x)
+ end
+end
+
+def fun_l4_n928(x)
+ if (x < 1)
+ fun_l5_n213(x)
+ else
+ fun_l5_n815(x)
+ end
+end
+
+def fun_l4_n929(x)
+ if (x < 1)
+ fun_l5_n280(x)
+ else
+ fun_l5_n551(x)
+ end
+end
+
+def fun_l4_n930(x)
+ if (x < 1)
+ fun_l5_n631(x)
+ else
+ fun_l5_n629(x)
+ end
+end
+
+def fun_l4_n931(x)
+ if (x < 1)
+ fun_l5_n60(x)
+ else
+ fun_l5_n332(x)
+ end
+end
+
+def fun_l4_n932(x)
+ if (x < 1)
+ fun_l5_n336(x)
+ else
+ fun_l5_n733(x)
+ end
+end
+
+def fun_l4_n933(x)
+ if (x < 1)
+ fun_l5_n94(x)
+ else
+ fun_l5_n48(x)
+ end
+end
+
+def fun_l4_n934(x)
+ if (x < 1)
+ fun_l5_n527(x)
+ else
+ fun_l5_n108(x)
+ end
+end
+
+def fun_l4_n935(x)
+ if (x < 1)
+ fun_l5_n994(x)
+ else
+ fun_l5_n95(x)
+ end
+end
+
+def fun_l4_n936(x)
+ if (x < 1)
+ fun_l5_n631(x)
+ else
+ fun_l5_n310(x)
+ end
+end
+
+def fun_l4_n937(x)
+ if (x < 1)
+ fun_l5_n851(x)
+ else
+ fun_l5_n380(x)
+ end
+end
+
+def fun_l4_n938(x)
+ if (x < 1)
+ fun_l5_n256(x)
+ else
+ fun_l5_n231(x)
+ end
+end
+
+def fun_l4_n939(x)
+ if (x < 1)
+ fun_l5_n686(x)
+ else
+ fun_l5_n557(x)
+ end
+end
+
+def fun_l4_n940(x)
+ if (x < 1)
+ fun_l5_n311(x)
+ else
+ fun_l5_n611(x)
+ end
+end
+
+def fun_l4_n941(x)
+ if (x < 1)
+ fun_l5_n770(x)
+ else
+ fun_l5_n306(x)
+ end
+end
+
+def fun_l4_n942(x)
+ if (x < 1)
+ fun_l5_n649(x)
+ else
+ fun_l5_n60(x)
+ end
+end
+
+def fun_l4_n943(x)
+ if (x < 1)
+ fun_l5_n935(x)
+ else
+ fun_l5_n991(x)
+ end
+end
+
+def fun_l4_n944(x)
+ if (x < 1)
+ fun_l5_n851(x)
+ else
+ fun_l5_n131(x)
+ end
+end
+
+def fun_l4_n945(x)
+ if (x < 1)
+ fun_l5_n422(x)
+ else
+ fun_l5_n309(x)
+ end
+end
+
+def fun_l4_n946(x)
+ if (x < 1)
+ fun_l5_n906(x)
+ else
+ fun_l5_n798(x)
+ end
+end
+
+def fun_l4_n947(x)
+ if (x < 1)
+ fun_l5_n817(x)
+ else
+ fun_l5_n122(x)
+ end
+end
+
+def fun_l4_n948(x)
+ if (x < 1)
+ fun_l5_n233(x)
+ else
+ fun_l5_n600(x)
+ end
+end
+
+def fun_l4_n949(x)
+ if (x < 1)
+ fun_l5_n908(x)
+ else
+ fun_l5_n332(x)
+ end
+end
+
+def fun_l4_n950(x)
+ if (x < 1)
+ fun_l5_n71(x)
+ else
+ fun_l5_n893(x)
+ end
+end
+
+def fun_l4_n951(x)
+ if (x < 1)
+ fun_l5_n281(x)
+ else
+ fun_l5_n281(x)
+ end
+end
+
+def fun_l4_n952(x)
+ if (x < 1)
+ fun_l5_n312(x)
+ else
+ fun_l5_n164(x)
+ end
+end
+
+def fun_l4_n953(x)
+ if (x < 1)
+ fun_l5_n292(x)
+ else
+ fun_l5_n993(x)
+ end
+end
+
+def fun_l4_n954(x)
+ if (x < 1)
+ fun_l5_n271(x)
+ else
+ fun_l5_n635(x)
+ end
+end
+
+def fun_l4_n955(x)
+ if (x < 1)
+ fun_l5_n10(x)
+ else
+ fun_l5_n202(x)
+ end
+end
+
+def fun_l4_n956(x)
+ if (x < 1)
+ fun_l5_n574(x)
+ else
+ fun_l5_n29(x)
+ end
+end
+
+def fun_l4_n957(x)
+ if (x < 1)
+ fun_l5_n154(x)
+ else
+ fun_l5_n96(x)
+ end
+end
+
+def fun_l4_n958(x)
+ if (x < 1)
+ fun_l5_n287(x)
+ else
+ fun_l5_n509(x)
+ end
+end
+
+def fun_l4_n959(x)
+ if (x < 1)
+ fun_l5_n400(x)
+ else
+ fun_l5_n195(x)
+ end
+end
+
+def fun_l4_n960(x)
+ if (x < 1)
+ fun_l5_n94(x)
+ else
+ fun_l5_n165(x)
+ end
+end
+
+def fun_l4_n961(x)
+ if (x < 1)
+ fun_l5_n276(x)
+ else
+ fun_l5_n935(x)
+ end
+end
+
+def fun_l4_n962(x)
+ if (x < 1)
+ fun_l5_n504(x)
+ else
+ fun_l5_n480(x)
+ end
+end
+
+def fun_l4_n963(x)
+ if (x < 1)
+ fun_l5_n152(x)
+ else
+ fun_l5_n397(x)
+ end
+end
+
+def fun_l4_n964(x)
+ if (x < 1)
+ fun_l5_n303(x)
+ else
+ fun_l5_n481(x)
+ end
+end
+
+def fun_l4_n965(x)
+ if (x < 1)
+ fun_l5_n882(x)
+ else
+ fun_l5_n116(x)
+ end
+end
+
+def fun_l4_n966(x)
+ if (x < 1)
+ fun_l5_n329(x)
+ else
+ fun_l5_n484(x)
+ end
+end
+
+def fun_l4_n967(x)
+ if (x < 1)
+ fun_l5_n369(x)
+ else
+ fun_l5_n680(x)
+ end
+end
+
+def fun_l4_n968(x)
+ if (x < 1)
+ fun_l5_n30(x)
+ else
+ fun_l5_n653(x)
+ end
+end
+
+def fun_l4_n969(x)
+ if (x < 1)
+ fun_l5_n292(x)
+ else
+ fun_l5_n793(x)
+ end
+end
+
+def fun_l4_n970(x)
+ if (x < 1)
+ fun_l5_n796(x)
+ else
+ fun_l5_n387(x)
+ end
+end
+
+def fun_l4_n971(x)
+ if (x < 1)
+ fun_l5_n735(x)
+ else
+ fun_l5_n985(x)
+ end
+end
+
+def fun_l4_n972(x)
+ if (x < 1)
+ fun_l5_n925(x)
+ else
+ fun_l5_n689(x)
+ end
+end
+
+def fun_l4_n973(x)
+ if (x < 1)
+ fun_l5_n154(x)
+ else
+ fun_l5_n998(x)
+ end
+end
+
+def fun_l4_n974(x)
+ if (x < 1)
+ fun_l5_n708(x)
+ else
+ fun_l5_n253(x)
+ end
+end
+
+def fun_l4_n975(x)
+ if (x < 1)
+ fun_l5_n716(x)
+ else
+ fun_l5_n958(x)
+ end
+end
+
+def fun_l4_n976(x)
+ if (x < 1)
+ fun_l5_n488(x)
+ else
+ fun_l5_n299(x)
+ end
+end
+
+def fun_l4_n977(x)
+ if (x < 1)
+ fun_l5_n872(x)
+ else
+ fun_l5_n276(x)
+ end
+end
+
+def fun_l4_n978(x)
+ if (x < 1)
+ fun_l5_n219(x)
+ else
+ fun_l5_n76(x)
+ end
+end
+
+def fun_l4_n979(x)
+ if (x < 1)
+ fun_l5_n937(x)
+ else
+ fun_l5_n988(x)
+ end
+end
+
+def fun_l4_n980(x)
+ if (x < 1)
+ fun_l5_n681(x)
+ else
+ fun_l5_n264(x)
+ end
+end
+
+def fun_l4_n981(x)
+ if (x < 1)
+ fun_l5_n630(x)
+ else
+ fun_l5_n18(x)
+ end
+end
+
+def fun_l4_n982(x)
+ if (x < 1)
+ fun_l5_n910(x)
+ else
+ fun_l5_n97(x)
+ end
+end
+
+def fun_l4_n983(x)
+ if (x < 1)
+ fun_l5_n551(x)
+ else
+ fun_l5_n429(x)
+ end
+end
+
+def fun_l4_n984(x)
+ if (x < 1)
+ fun_l5_n304(x)
+ else
+ fun_l5_n192(x)
+ end
+end
+
+def fun_l4_n985(x)
+ if (x < 1)
+ fun_l5_n696(x)
+ else
+ fun_l5_n124(x)
+ end
+end
+
+def fun_l4_n986(x)
+ if (x < 1)
+ fun_l5_n603(x)
+ else
+ fun_l5_n967(x)
+ end
+end
+
+def fun_l4_n987(x)
+ if (x < 1)
+ fun_l5_n317(x)
+ else
+ fun_l5_n785(x)
+ end
+end
+
+def fun_l4_n988(x)
+ if (x < 1)
+ fun_l5_n762(x)
+ else
+ fun_l5_n999(x)
+ end
+end
+
+def fun_l4_n989(x)
+ if (x < 1)
+ fun_l5_n61(x)
+ else
+ fun_l5_n474(x)
+ end
+end
+
+def fun_l4_n990(x)
+ if (x < 1)
+ fun_l5_n465(x)
+ else
+ fun_l5_n878(x)
+ end
+end
+
+def fun_l4_n991(x)
+ if (x < 1)
+ fun_l5_n907(x)
+ else
+ fun_l5_n259(x)
+ end
+end
+
+def fun_l4_n992(x)
+ if (x < 1)
+ fun_l5_n594(x)
+ else
+ fun_l5_n378(x)
+ end
+end
+
+def fun_l4_n993(x)
+ if (x < 1)
+ fun_l5_n202(x)
+ else
+ fun_l5_n490(x)
+ end
+end
+
+def fun_l4_n994(x)
+ if (x < 1)
+ fun_l5_n105(x)
+ else
+ fun_l5_n675(x)
+ end
+end
+
+def fun_l4_n995(x)
+ if (x < 1)
+ fun_l5_n99(x)
+ else
+ fun_l5_n21(x)
+ end
+end
+
+def fun_l4_n996(x)
+ if (x < 1)
+ fun_l5_n831(x)
+ else
+ fun_l5_n692(x)
+ end
+end
+
+def fun_l4_n997(x)
+ if (x < 1)
+ fun_l5_n186(x)
+ else
+ fun_l5_n427(x)
+ end
+end
+
+def fun_l4_n998(x)
+ if (x < 1)
+ fun_l5_n597(x)
+ else
+ fun_l5_n978(x)
+ end
+end
+
+def fun_l4_n999(x)
+ if (x < 1)
+ fun_l5_n537(x)
+ else
+ fun_l5_n952(x)
+ end
+end
+
+def fun_l5_n0(x)
+ if (x < 1)
+ fun_l6_n104(x)
+ else
+ fun_l6_n249(x)
+ end
+end
+
+def fun_l5_n1(x)
+ if (x < 1)
+ fun_l6_n260(x)
+ else
+ fun_l6_n782(x)
+ end
+end
+
+def fun_l5_n2(x)
+ if (x < 1)
+ fun_l6_n974(x)
+ else
+ fun_l6_n301(x)
+ end
+end
+
+def fun_l5_n3(x)
+ if (x < 1)
+ fun_l6_n883(x)
+ else
+ fun_l6_n149(x)
+ end
+end
+
+def fun_l5_n4(x)
+ if (x < 1)
+ fun_l6_n134(x)
+ else
+ fun_l6_n111(x)
+ end
+end
+
+def fun_l5_n5(x)
+ if (x < 1)
+ fun_l6_n573(x)
+ else
+ fun_l6_n273(x)
+ end
+end
+
+def fun_l5_n6(x)
+ if (x < 1)
+ fun_l6_n221(x)
+ else
+ fun_l6_n843(x)
+ end
+end
+
+def fun_l5_n7(x)
+ if (x < 1)
+ fun_l6_n572(x)
+ else
+ fun_l6_n435(x)
+ end
+end
+
+def fun_l5_n8(x)
+ if (x < 1)
+ fun_l6_n43(x)
+ else
+ fun_l6_n598(x)
+ end
+end
+
+def fun_l5_n9(x)
+ if (x < 1)
+ fun_l6_n352(x)
+ else
+ fun_l6_n894(x)
+ end
+end
+
+def fun_l5_n10(x)
+ if (x < 1)
+ fun_l6_n161(x)
+ else
+ fun_l6_n654(x)
+ end
+end
+
+def fun_l5_n11(x)
+ if (x < 1)
+ fun_l6_n432(x)
+ else
+ fun_l6_n825(x)
+ end
+end
+
+def fun_l5_n12(x)
+ if (x < 1)
+ fun_l6_n863(x)
+ else
+ fun_l6_n940(x)
+ end
+end
+
+def fun_l5_n13(x)
+ if (x < 1)
+ fun_l6_n478(x)
+ else
+ fun_l6_n193(x)
+ end
+end
+
+def fun_l5_n14(x)
+ if (x < 1)
+ fun_l6_n327(x)
+ else
+ fun_l6_n808(x)
+ end
+end
+
+def fun_l5_n15(x)
+ if (x < 1)
+ fun_l6_n86(x)
+ else
+ fun_l6_n951(x)
+ end
+end
+
+def fun_l5_n16(x)
+ if (x < 1)
+ fun_l6_n492(x)
+ else
+ fun_l6_n704(x)
+ end
+end
+
+def fun_l5_n17(x)
+ if (x < 1)
+ fun_l6_n196(x)
+ else
+ fun_l6_n970(x)
+ end
+end
+
+def fun_l5_n18(x)
+ if (x < 1)
+ fun_l6_n325(x)
+ else
+ fun_l6_n30(x)
+ end
+end
+
+def fun_l5_n19(x)
+ if (x < 1)
+ fun_l6_n559(x)
+ else
+ fun_l6_n269(x)
+ end
+end
+
+def fun_l5_n20(x)
+ if (x < 1)
+ fun_l6_n716(x)
+ else
+ fun_l6_n783(x)
+ end
+end
+
+def fun_l5_n21(x)
+ if (x < 1)
+ fun_l6_n978(x)
+ else
+ fun_l6_n306(x)
+ end
+end
+
+def fun_l5_n22(x)
+ if (x < 1)
+ fun_l6_n220(x)
+ else
+ fun_l6_n823(x)
+ end
+end
+
+def fun_l5_n23(x)
+ if (x < 1)
+ fun_l6_n675(x)
+ else
+ fun_l6_n684(x)
+ end
+end
+
+def fun_l5_n24(x)
+ if (x < 1)
+ fun_l6_n851(x)
+ else
+ fun_l6_n450(x)
+ end
+end
+
+def fun_l5_n25(x)
+ if (x < 1)
+ fun_l6_n745(x)
+ else
+ fun_l6_n370(x)
+ end
+end
+
+def fun_l5_n26(x)
+ if (x < 1)
+ fun_l6_n431(x)
+ else
+ fun_l6_n130(x)
+ end
+end
+
+def fun_l5_n27(x)
+ if (x < 1)
+ fun_l6_n105(x)
+ else
+ fun_l6_n205(x)
+ end
+end
+
+def fun_l5_n28(x)
+ if (x < 1)
+ fun_l6_n718(x)
+ else
+ fun_l6_n742(x)
+ end
+end
+
+def fun_l5_n29(x)
+ if (x < 1)
+ fun_l6_n977(x)
+ else
+ fun_l6_n63(x)
+ end
+end
+
+def fun_l5_n30(x)
+ if (x < 1)
+ fun_l6_n902(x)
+ else
+ fun_l6_n471(x)
+ end
+end
+
+def fun_l5_n31(x)
+ if (x < 1)
+ fun_l6_n76(x)
+ else
+ fun_l6_n960(x)
+ end
+end
+
+def fun_l5_n32(x)
+ if (x < 1)
+ fun_l6_n75(x)
+ else
+ fun_l6_n640(x)
+ end
+end
+
+def fun_l5_n33(x)
+ if (x < 1)
+ fun_l6_n631(x)
+ else
+ fun_l6_n769(x)
+ end
+end
+
+def fun_l5_n34(x)
+ if (x < 1)
+ fun_l6_n201(x)
+ else
+ fun_l6_n771(x)
+ end
+end
+
+def fun_l5_n35(x)
+ if (x < 1)
+ fun_l6_n734(x)
+ else
+ fun_l6_n370(x)
+ end
+end
+
+def fun_l5_n36(x)
+ if (x < 1)
+ fun_l6_n490(x)
+ else
+ fun_l6_n994(x)
+ end
+end
+
+def fun_l5_n37(x)
+ if (x < 1)
+ fun_l6_n566(x)
+ else
+ fun_l6_n392(x)
+ end
+end
+
+def fun_l5_n38(x)
+ if (x < 1)
+ fun_l6_n120(x)
+ else
+ fun_l6_n774(x)
+ end
+end
+
+def fun_l5_n39(x)
+ if (x < 1)
+ fun_l6_n402(x)
+ else
+ fun_l6_n572(x)
+ end
+end
+
+def fun_l5_n40(x)
+ if (x < 1)
+ fun_l6_n911(x)
+ else
+ fun_l6_n968(x)
+ end
+end
+
+def fun_l5_n41(x)
+ if (x < 1)
+ fun_l6_n200(x)
+ else
+ fun_l6_n656(x)
+ end
+end
+
+def fun_l5_n42(x)
+ if (x < 1)
+ fun_l6_n59(x)
+ else
+ fun_l6_n426(x)
+ end
+end
+
+def fun_l5_n43(x)
+ if (x < 1)
+ fun_l6_n650(x)
+ else
+ fun_l6_n932(x)
+ end
+end
+
+def fun_l5_n44(x)
+ if (x < 1)
+ fun_l6_n365(x)
+ else
+ fun_l6_n755(x)
+ end
+end
+
+def fun_l5_n45(x)
+ if (x < 1)
+ fun_l6_n738(x)
+ else
+ fun_l6_n432(x)
+ end
+end
+
+def fun_l5_n46(x)
+ if (x < 1)
+ fun_l6_n82(x)
+ else
+ fun_l6_n484(x)
+ end
+end
+
+def fun_l5_n47(x)
+ if (x < 1)
+ fun_l6_n64(x)
+ else
+ fun_l6_n610(x)
+ end
+end
+
+def fun_l5_n48(x)
+ if (x < 1)
+ fun_l6_n875(x)
+ else
+ fun_l6_n464(x)
+ end
+end
+
+def fun_l5_n49(x)
+ if (x < 1)
+ fun_l6_n798(x)
+ else
+ fun_l6_n57(x)
+ end
+end
+
+def fun_l5_n50(x)
+ if (x < 1)
+ fun_l6_n76(x)
+ else
+ fun_l6_n462(x)
+ end
+end
+
+def fun_l5_n51(x)
+ if (x < 1)
+ fun_l6_n225(x)
+ else
+ fun_l6_n526(x)
+ end
+end
+
+def fun_l5_n52(x)
+ if (x < 1)
+ fun_l6_n388(x)
+ else
+ fun_l6_n167(x)
+ end
+end
+
+def fun_l5_n53(x)
+ if (x < 1)
+ fun_l6_n270(x)
+ else
+ fun_l6_n821(x)
+ end
+end
+
+def fun_l5_n54(x)
+ if (x < 1)
+ fun_l6_n790(x)
+ else
+ fun_l6_n95(x)
+ end
+end
+
+def fun_l5_n55(x)
+ if (x < 1)
+ fun_l6_n38(x)
+ else
+ fun_l6_n32(x)
+ end
+end
+
+def fun_l5_n56(x)
+ if (x < 1)
+ fun_l6_n400(x)
+ else
+ fun_l6_n513(x)
+ end
+end
+
+def fun_l5_n57(x)
+ if (x < 1)
+ fun_l6_n251(x)
+ else
+ fun_l6_n16(x)
+ end
+end
+
+def fun_l5_n58(x)
+ if (x < 1)
+ fun_l6_n303(x)
+ else
+ fun_l6_n858(x)
+ end
+end
+
+def fun_l5_n59(x)
+ if (x < 1)
+ fun_l6_n173(x)
+ else
+ fun_l6_n38(x)
+ end
+end
+
+def fun_l5_n60(x)
+ if (x < 1)
+ fun_l6_n466(x)
+ else
+ fun_l6_n64(x)
+ end
+end
+
+def fun_l5_n61(x)
+ if (x < 1)
+ fun_l6_n687(x)
+ else
+ fun_l6_n208(x)
+ end
+end
+
+def fun_l5_n62(x)
+ if (x < 1)
+ fun_l6_n891(x)
+ else
+ fun_l6_n789(x)
+ end
+end
+
+def fun_l5_n63(x)
+ if (x < 1)
+ fun_l6_n664(x)
+ else
+ fun_l6_n133(x)
+ end
+end
+
+def fun_l5_n64(x)
+ if (x < 1)
+ fun_l6_n121(x)
+ else
+ fun_l6_n989(x)
+ end
+end
+
+def fun_l5_n65(x)
+ if (x < 1)
+ fun_l6_n411(x)
+ else
+ fun_l6_n264(x)
+ end
+end
+
+def fun_l5_n66(x)
+ if (x < 1)
+ fun_l6_n528(x)
+ else
+ fun_l6_n662(x)
+ end
+end
+
+def fun_l5_n67(x)
+ if (x < 1)
+ fun_l6_n824(x)
+ else
+ fun_l6_n410(x)
+ end
+end
+
+def fun_l5_n68(x)
+ if (x < 1)
+ fun_l6_n29(x)
+ else
+ fun_l6_n946(x)
+ end
+end
+
+def fun_l5_n69(x)
+ if (x < 1)
+ fun_l6_n566(x)
+ else
+ fun_l6_n797(x)
+ end
+end
+
+def fun_l5_n70(x)
+ if (x < 1)
+ fun_l6_n816(x)
+ else
+ fun_l6_n112(x)
+ end
+end
+
+def fun_l5_n71(x)
+ if (x < 1)
+ fun_l6_n920(x)
+ else
+ fun_l6_n44(x)
+ end
+end
+
+def fun_l5_n72(x)
+ if (x < 1)
+ fun_l6_n725(x)
+ else
+ fun_l6_n113(x)
+ end
+end
+
+def fun_l5_n73(x)
+ if (x < 1)
+ fun_l6_n406(x)
+ else
+ fun_l6_n555(x)
+ end
+end
+
+def fun_l5_n74(x)
+ if (x < 1)
+ fun_l6_n527(x)
+ else
+ fun_l6_n991(x)
+ end
+end
+
+def fun_l5_n75(x)
+ if (x < 1)
+ fun_l6_n46(x)
+ else
+ fun_l6_n440(x)
+ end
+end
+
+def fun_l5_n76(x)
+ if (x < 1)
+ fun_l6_n242(x)
+ else
+ fun_l6_n488(x)
+ end
+end
+
+def fun_l5_n77(x)
+ if (x < 1)
+ fun_l6_n211(x)
+ else
+ fun_l6_n760(x)
+ end
+end
+
+def fun_l5_n78(x)
+ if (x < 1)
+ fun_l6_n821(x)
+ else
+ fun_l6_n653(x)
+ end
+end
+
+def fun_l5_n79(x)
+ if (x < 1)
+ fun_l6_n559(x)
+ else
+ fun_l6_n425(x)
+ end
+end
+
+def fun_l5_n80(x)
+ if (x < 1)
+ fun_l6_n792(x)
+ else
+ fun_l6_n813(x)
+ end
+end
+
+def fun_l5_n81(x)
+ if (x < 1)
+ fun_l6_n463(x)
+ else
+ fun_l6_n454(x)
+ end
+end
+
+def fun_l5_n82(x)
+ if (x < 1)
+ fun_l6_n731(x)
+ else
+ fun_l6_n718(x)
+ end
+end
+
+def fun_l5_n83(x)
+ if (x < 1)
+ fun_l6_n377(x)
+ else
+ fun_l6_n137(x)
+ end
+end
+
+def fun_l5_n84(x)
+ if (x < 1)
+ fun_l6_n829(x)
+ else
+ fun_l6_n77(x)
+ end
+end
+
+def fun_l5_n85(x)
+ if (x < 1)
+ fun_l6_n714(x)
+ else
+ fun_l6_n682(x)
+ end
+end
+
+def fun_l5_n86(x)
+ if (x < 1)
+ fun_l6_n47(x)
+ else
+ fun_l6_n527(x)
+ end
+end
+
+def fun_l5_n87(x)
+ if (x < 1)
+ fun_l6_n976(x)
+ else
+ fun_l6_n18(x)
+ end
+end
+
+def fun_l5_n88(x)
+ if (x < 1)
+ fun_l6_n710(x)
+ else
+ fun_l6_n998(x)
+ end
+end
+
+def fun_l5_n89(x)
+ if (x < 1)
+ fun_l6_n222(x)
+ else
+ fun_l6_n97(x)
+ end
+end
+
+def fun_l5_n90(x)
+ if (x < 1)
+ fun_l6_n862(x)
+ else
+ fun_l6_n627(x)
+ end
+end
+
+def fun_l5_n91(x)
+ if (x < 1)
+ fun_l6_n642(x)
+ else
+ fun_l6_n720(x)
+ end
+end
+
+def fun_l5_n92(x)
+ if (x < 1)
+ fun_l6_n444(x)
+ else
+ fun_l6_n506(x)
+ end
+end
+
+def fun_l5_n93(x)
+ if (x < 1)
+ fun_l6_n776(x)
+ else
+ fun_l6_n879(x)
+ end
+end
+
+def fun_l5_n94(x)
+ if (x < 1)
+ fun_l6_n629(x)
+ else
+ fun_l6_n322(x)
+ end
+end
+
+def fun_l5_n95(x)
+ if (x < 1)
+ fun_l6_n119(x)
+ else
+ fun_l6_n134(x)
+ end
+end
+
+def fun_l5_n96(x)
+ if (x < 1)
+ fun_l6_n385(x)
+ else
+ fun_l6_n343(x)
+ end
+end
+
+def fun_l5_n97(x)
+ if (x < 1)
+ fun_l6_n110(x)
+ else
+ fun_l6_n323(x)
+ end
+end
+
+def fun_l5_n98(x)
+ if (x < 1)
+ fun_l6_n547(x)
+ else
+ fun_l6_n762(x)
+ end
+end
+
+def fun_l5_n99(x)
+ if (x < 1)
+ fun_l6_n811(x)
+ else
+ fun_l6_n404(x)
+ end
+end
+
+def fun_l5_n100(x)
+ if (x < 1)
+ fun_l6_n893(x)
+ else
+ fun_l6_n120(x)
+ end
+end
+
+def fun_l5_n101(x)
+ if (x < 1)
+ fun_l6_n755(x)
+ else
+ fun_l6_n611(x)
+ end
+end
+
+def fun_l5_n102(x)
+ if (x < 1)
+ fun_l6_n65(x)
+ else
+ fun_l6_n897(x)
+ end
+end
+
+def fun_l5_n103(x)
+ if (x < 1)
+ fun_l6_n629(x)
+ else
+ fun_l6_n214(x)
+ end
+end
+
+def fun_l5_n104(x)
+ if (x < 1)
+ fun_l6_n211(x)
+ else
+ fun_l6_n179(x)
+ end
+end
+
+def fun_l5_n105(x)
+ if (x < 1)
+ fun_l6_n650(x)
+ else
+ fun_l6_n348(x)
+ end
+end
+
+def fun_l5_n106(x)
+ if (x < 1)
+ fun_l6_n966(x)
+ else
+ fun_l6_n654(x)
+ end
+end
+
+def fun_l5_n107(x)
+ if (x < 1)
+ fun_l6_n596(x)
+ else
+ fun_l6_n668(x)
+ end
+end
+
+def fun_l5_n108(x)
+ if (x < 1)
+ fun_l6_n392(x)
+ else
+ fun_l6_n629(x)
+ end
+end
+
+def fun_l5_n109(x)
+ if (x < 1)
+ fun_l6_n96(x)
+ else
+ fun_l6_n578(x)
+ end
+end
+
+def fun_l5_n110(x)
+ if (x < 1)
+ fun_l6_n88(x)
+ else
+ fun_l6_n214(x)
+ end
+end
+
+def fun_l5_n111(x)
+ if (x < 1)
+ fun_l6_n622(x)
+ else
+ fun_l6_n180(x)
+ end
+end
+
+def fun_l5_n112(x)
+ if (x < 1)
+ fun_l6_n100(x)
+ else
+ fun_l6_n373(x)
+ end
+end
+
+def fun_l5_n113(x)
+ if (x < 1)
+ fun_l6_n464(x)
+ else
+ fun_l6_n30(x)
+ end
+end
+
+def fun_l5_n114(x)
+ if (x < 1)
+ fun_l6_n703(x)
+ else
+ fun_l6_n116(x)
+ end
+end
+
+def fun_l5_n115(x)
+ if (x < 1)
+ fun_l6_n63(x)
+ else
+ fun_l6_n260(x)
+ end
+end
+
+def fun_l5_n116(x)
+ if (x < 1)
+ fun_l6_n935(x)
+ else
+ fun_l6_n951(x)
+ end
+end
+
+def fun_l5_n117(x)
+ if (x < 1)
+ fun_l6_n415(x)
+ else
+ fun_l6_n734(x)
+ end
+end
+
+def fun_l5_n118(x)
+ if (x < 1)
+ fun_l6_n873(x)
+ else
+ fun_l6_n163(x)
+ end
+end
+
+def fun_l5_n119(x)
+ if (x < 1)
+ fun_l6_n134(x)
+ else
+ fun_l6_n586(x)
+ end
+end
+
+def fun_l5_n120(x)
+ if (x < 1)
+ fun_l6_n793(x)
+ else
+ fun_l6_n197(x)
+ end
+end
+
+def fun_l5_n121(x)
+ if (x < 1)
+ fun_l6_n585(x)
+ else
+ fun_l6_n793(x)
+ end
+end
+
+def fun_l5_n122(x)
+ if (x < 1)
+ fun_l6_n10(x)
+ else
+ fun_l6_n12(x)
+ end
+end
+
+def fun_l5_n123(x)
+ if (x < 1)
+ fun_l6_n786(x)
+ else
+ fun_l6_n386(x)
+ end
+end
+
+def fun_l5_n124(x)
+ if (x < 1)
+ fun_l6_n891(x)
+ else
+ fun_l6_n903(x)
+ end
+end
+
+def fun_l5_n125(x)
+ if (x < 1)
+ fun_l6_n389(x)
+ else
+ fun_l6_n154(x)
+ end
+end
+
+def fun_l5_n126(x)
+ if (x < 1)
+ fun_l6_n214(x)
+ else
+ fun_l6_n754(x)
+ end
+end
+
+def fun_l5_n127(x)
+ if (x < 1)
+ fun_l6_n646(x)
+ else
+ fun_l6_n661(x)
+ end
+end
+
+def fun_l5_n128(x)
+ if (x < 1)
+ fun_l6_n662(x)
+ else
+ fun_l6_n527(x)
+ end
+end
+
+def fun_l5_n129(x)
+ if (x < 1)
+ fun_l6_n329(x)
+ else
+ fun_l6_n310(x)
+ end
+end
+
+def fun_l5_n130(x)
+ if (x < 1)
+ fun_l6_n352(x)
+ else
+ fun_l6_n820(x)
+ end
+end
+
+def fun_l5_n131(x)
+ if (x < 1)
+ fun_l6_n551(x)
+ else
+ fun_l6_n454(x)
+ end
+end
+
+def fun_l5_n132(x)
+ if (x < 1)
+ fun_l6_n586(x)
+ else
+ fun_l6_n340(x)
+ end
+end
+
+def fun_l5_n133(x)
+ if (x < 1)
+ fun_l6_n111(x)
+ else
+ fun_l6_n188(x)
+ end
+end
+
+def fun_l5_n134(x)
+ if (x < 1)
+ fun_l6_n261(x)
+ else
+ fun_l6_n464(x)
+ end
+end
+
+def fun_l5_n135(x)
+ if (x < 1)
+ fun_l6_n540(x)
+ else
+ fun_l6_n854(x)
+ end
+end
+
+def fun_l5_n136(x)
+ if (x < 1)
+ fun_l6_n120(x)
+ else
+ fun_l6_n230(x)
+ end
+end
+
+def fun_l5_n137(x)
+ if (x < 1)
+ fun_l6_n837(x)
+ else
+ fun_l6_n606(x)
+ end
+end
+
+def fun_l5_n138(x)
+ if (x < 1)
+ fun_l6_n663(x)
+ else
+ fun_l6_n195(x)
+ end
+end
+
+def fun_l5_n139(x)
+ if (x < 1)
+ fun_l6_n572(x)
+ else
+ fun_l6_n768(x)
+ end
+end
+
+def fun_l5_n140(x)
+ if (x < 1)
+ fun_l6_n747(x)
+ else
+ fun_l6_n304(x)
+ end
+end
+
+def fun_l5_n141(x)
+ if (x < 1)
+ fun_l6_n927(x)
+ else
+ fun_l6_n122(x)
+ end
+end
+
+def fun_l5_n142(x)
+ if (x < 1)
+ fun_l6_n311(x)
+ else
+ fun_l6_n920(x)
+ end
+end
+
+def fun_l5_n143(x)
+ if (x < 1)
+ fun_l6_n887(x)
+ else
+ fun_l6_n598(x)
+ end
+end
+
+def fun_l5_n144(x)
+ if (x < 1)
+ fun_l6_n289(x)
+ else
+ fun_l6_n894(x)
+ end
+end
+
+def fun_l5_n145(x)
+ if (x < 1)
+ fun_l6_n333(x)
+ else
+ fun_l6_n385(x)
+ end
+end
+
+def fun_l5_n146(x)
+ if (x < 1)
+ fun_l6_n926(x)
+ else
+ fun_l6_n310(x)
+ end
+end
+
+def fun_l5_n147(x)
+ if (x < 1)
+ fun_l6_n754(x)
+ else
+ fun_l6_n354(x)
+ end
+end
+
+def fun_l5_n148(x)
+ if (x < 1)
+ fun_l6_n800(x)
+ else
+ fun_l6_n634(x)
+ end
+end
+
+def fun_l5_n149(x)
+ if (x < 1)
+ fun_l6_n5(x)
+ else
+ fun_l6_n67(x)
+ end
+end
+
+def fun_l5_n150(x)
+ if (x < 1)
+ fun_l6_n766(x)
+ else
+ fun_l6_n237(x)
+ end
+end
+
+def fun_l5_n151(x)
+ if (x < 1)
+ fun_l6_n277(x)
+ else
+ fun_l6_n692(x)
+ end
+end
+
+def fun_l5_n152(x)
+ if (x < 1)
+ fun_l6_n328(x)
+ else
+ fun_l6_n216(x)
+ end
+end
+
+def fun_l5_n153(x)
+ if (x < 1)
+ fun_l6_n328(x)
+ else
+ fun_l6_n165(x)
+ end
+end
+
+def fun_l5_n154(x)
+ if (x < 1)
+ fun_l6_n884(x)
+ else
+ fun_l6_n811(x)
+ end
+end
+
+def fun_l5_n155(x)
+ if (x < 1)
+ fun_l6_n376(x)
+ else
+ fun_l6_n188(x)
+ end
+end
+
+def fun_l5_n156(x)
+ if (x < 1)
+ fun_l6_n276(x)
+ else
+ fun_l6_n19(x)
+ end
+end
+
+def fun_l5_n157(x)
+ if (x < 1)
+ fun_l6_n443(x)
+ else
+ fun_l6_n815(x)
+ end
+end
+
+def fun_l5_n158(x)
+ if (x < 1)
+ fun_l6_n610(x)
+ else
+ fun_l6_n341(x)
+ end
+end
+
+def fun_l5_n159(x)
+ if (x < 1)
+ fun_l6_n147(x)
+ else
+ fun_l6_n289(x)
+ end
+end
+
+def fun_l5_n160(x)
+ if (x < 1)
+ fun_l6_n258(x)
+ else
+ fun_l6_n683(x)
+ end
+end
+
+def fun_l5_n161(x)
+ if (x < 1)
+ fun_l6_n544(x)
+ else
+ fun_l6_n621(x)
+ end
+end
+
+def fun_l5_n162(x)
+ if (x < 1)
+ fun_l6_n119(x)
+ else
+ fun_l6_n336(x)
+ end
+end
+
+def fun_l5_n163(x)
+ if (x < 1)
+ fun_l6_n297(x)
+ else
+ fun_l6_n915(x)
+ end
+end
+
+def fun_l5_n164(x)
+ if (x < 1)
+ fun_l6_n782(x)
+ else
+ fun_l6_n499(x)
+ end
+end
+
+def fun_l5_n165(x)
+ if (x < 1)
+ fun_l6_n660(x)
+ else
+ fun_l6_n227(x)
+ end
+end
+
+def fun_l5_n166(x)
+ if (x < 1)
+ fun_l6_n820(x)
+ else
+ fun_l6_n822(x)
+ end
+end
+
+def fun_l5_n167(x)
+ if (x < 1)
+ fun_l6_n878(x)
+ else
+ fun_l6_n642(x)
+ end
+end
+
+def fun_l5_n168(x)
+ if (x < 1)
+ fun_l6_n123(x)
+ else
+ fun_l6_n451(x)
+ end
+end
+
+def fun_l5_n169(x)
+ if (x < 1)
+ fun_l6_n741(x)
+ else
+ fun_l6_n35(x)
+ end
+end
+
+def fun_l5_n170(x)
+ if (x < 1)
+ fun_l6_n522(x)
+ else
+ fun_l6_n546(x)
+ end
+end
+
+def fun_l5_n171(x)
+ if (x < 1)
+ fun_l6_n555(x)
+ else
+ fun_l6_n667(x)
+ end
+end
+
+def fun_l5_n172(x)
+ if (x < 1)
+ fun_l6_n760(x)
+ else
+ fun_l6_n292(x)
+ end
+end
+
+def fun_l5_n173(x)
+ if (x < 1)
+ fun_l6_n375(x)
+ else
+ fun_l6_n907(x)
+ end
+end
+
+def fun_l5_n174(x)
+ if (x < 1)
+ fun_l6_n382(x)
+ else
+ fun_l6_n693(x)
+ end
+end
+
+def fun_l5_n175(x)
+ if (x < 1)
+ fun_l6_n728(x)
+ else
+ fun_l6_n378(x)
+ end
+end
+
+def fun_l5_n176(x)
+ if (x < 1)
+ fun_l6_n79(x)
+ else
+ fun_l6_n402(x)
+ end
+end
+
+def fun_l5_n177(x)
+ if (x < 1)
+ fun_l6_n444(x)
+ else
+ fun_l6_n500(x)
+ end
+end
+
+def fun_l5_n178(x)
+ if (x < 1)
+ fun_l6_n535(x)
+ else
+ fun_l6_n754(x)
+ end
+end
+
+def fun_l5_n179(x)
+ if (x < 1)
+ fun_l6_n831(x)
+ else
+ fun_l6_n206(x)
+ end
+end
+
+def fun_l5_n180(x)
+ if (x < 1)
+ fun_l6_n878(x)
+ else
+ fun_l6_n715(x)
+ end
+end
+
+def fun_l5_n181(x)
+ if (x < 1)
+ fun_l6_n433(x)
+ else
+ fun_l6_n955(x)
+ end
+end
+
+def fun_l5_n182(x)
+ if (x < 1)
+ fun_l6_n611(x)
+ else
+ fun_l6_n258(x)
+ end
+end
+
+def fun_l5_n183(x)
+ if (x < 1)
+ fun_l6_n618(x)
+ else
+ fun_l6_n29(x)
+ end
+end
+
+def fun_l5_n184(x)
+ if (x < 1)
+ fun_l6_n838(x)
+ else
+ fun_l6_n918(x)
+ end
+end
+
+def fun_l5_n185(x)
+ if (x < 1)
+ fun_l6_n307(x)
+ else
+ fun_l6_n811(x)
+ end
+end
+
+def fun_l5_n186(x)
+ if (x < 1)
+ fun_l6_n564(x)
+ else
+ fun_l6_n73(x)
+ end
+end
+
+def fun_l5_n187(x)
+ if (x < 1)
+ fun_l6_n871(x)
+ else
+ fun_l6_n669(x)
+ end
+end
+
+def fun_l5_n188(x)
+ if (x < 1)
+ fun_l6_n546(x)
+ else
+ fun_l6_n41(x)
+ end
+end
+
+def fun_l5_n189(x)
+ if (x < 1)
+ fun_l6_n312(x)
+ else
+ fun_l6_n998(x)
+ end
+end
+
+def fun_l5_n190(x)
+ if (x < 1)
+ fun_l6_n519(x)
+ else
+ fun_l6_n275(x)
+ end
+end
+
+def fun_l5_n191(x)
+ if (x < 1)
+ fun_l6_n525(x)
+ else
+ fun_l6_n228(x)
+ end
+end
+
+def fun_l5_n192(x)
+ if (x < 1)
+ fun_l6_n115(x)
+ else
+ fun_l6_n790(x)
+ end
+end
+
+def fun_l5_n193(x)
+ if (x < 1)
+ fun_l6_n976(x)
+ else
+ fun_l6_n219(x)
+ end
+end
+
+def fun_l5_n194(x)
+ if (x < 1)
+ fun_l6_n785(x)
+ else
+ fun_l6_n834(x)
+ end
+end
+
+def fun_l5_n195(x)
+ if (x < 1)
+ fun_l6_n238(x)
+ else
+ fun_l6_n471(x)
+ end
+end
+
+def fun_l5_n196(x)
+ if (x < 1)
+ fun_l6_n275(x)
+ else
+ fun_l6_n218(x)
+ end
+end
+
+def fun_l5_n197(x)
+ if (x < 1)
+ fun_l6_n590(x)
+ else
+ fun_l6_n458(x)
+ end
+end
+
+def fun_l5_n198(x)
+ if (x < 1)
+ fun_l6_n498(x)
+ else
+ fun_l6_n906(x)
+ end
+end
+
+def fun_l5_n199(x)
+ if (x < 1)
+ fun_l6_n547(x)
+ else
+ fun_l6_n885(x)
+ end
+end
+
+def fun_l5_n200(x)
+ if (x < 1)
+ fun_l6_n631(x)
+ else
+ fun_l6_n0(x)
+ end
+end
+
+def fun_l5_n201(x)
+ if (x < 1)
+ fun_l6_n31(x)
+ else
+ fun_l6_n729(x)
+ end
+end
+
+def fun_l5_n202(x)
+ if (x < 1)
+ fun_l6_n303(x)
+ else
+ fun_l6_n847(x)
+ end
+end
+
+def fun_l5_n203(x)
+ if (x < 1)
+ fun_l6_n912(x)
+ else
+ fun_l6_n346(x)
+ end
+end
+
+def fun_l5_n204(x)
+ if (x < 1)
+ fun_l6_n153(x)
+ else
+ fun_l6_n831(x)
+ end
+end
+
+def fun_l5_n205(x)
+ if (x < 1)
+ fun_l6_n424(x)
+ else
+ fun_l6_n836(x)
+ end
+end
+
+def fun_l5_n206(x)
+ if (x < 1)
+ fun_l6_n214(x)
+ else
+ fun_l6_n207(x)
+ end
+end
+
+def fun_l5_n207(x)
+ if (x < 1)
+ fun_l6_n362(x)
+ else
+ fun_l6_n241(x)
+ end
+end
+
+def fun_l5_n208(x)
+ if (x < 1)
+ fun_l6_n796(x)
+ else
+ fun_l6_n763(x)
+ end
+end
+
+def fun_l5_n209(x)
+ if (x < 1)
+ fun_l6_n523(x)
+ else
+ fun_l6_n998(x)
+ end
+end
+
+def fun_l5_n210(x)
+ if (x < 1)
+ fun_l6_n326(x)
+ else
+ fun_l6_n755(x)
+ end
+end
+
+def fun_l5_n211(x)
+ if (x < 1)
+ fun_l6_n345(x)
+ else
+ fun_l6_n747(x)
+ end
+end
+
+def fun_l5_n212(x)
+ if (x < 1)
+ fun_l6_n631(x)
+ else
+ fun_l6_n576(x)
+ end
+end
+
+def fun_l5_n213(x)
+ if (x < 1)
+ fun_l6_n713(x)
+ else
+ fun_l6_n678(x)
+ end
+end
+
+def fun_l5_n214(x)
+ if (x < 1)
+ fun_l6_n470(x)
+ else
+ fun_l6_n877(x)
+ end
+end
+
+def fun_l5_n215(x)
+ if (x < 1)
+ fun_l6_n78(x)
+ else
+ fun_l6_n315(x)
+ end
+end
+
+def fun_l5_n216(x)
+ if (x < 1)
+ fun_l6_n281(x)
+ else
+ fun_l6_n872(x)
+ end
+end
+
+def fun_l5_n217(x)
+ if (x < 1)
+ fun_l6_n200(x)
+ else
+ fun_l6_n323(x)
+ end
+end
+
+def fun_l5_n218(x)
+ if (x < 1)
+ fun_l6_n483(x)
+ else
+ fun_l6_n938(x)
+ end
+end
+
+def fun_l5_n219(x)
+ if (x < 1)
+ fun_l6_n102(x)
+ else
+ fun_l6_n690(x)
+ end
+end
+
+def fun_l5_n220(x)
+ if (x < 1)
+ fun_l6_n740(x)
+ else
+ fun_l6_n684(x)
+ end
+end
+
+def fun_l5_n221(x)
+ if (x < 1)
+ fun_l6_n366(x)
+ else
+ fun_l6_n138(x)
+ end
+end
+
+def fun_l5_n222(x)
+ if (x < 1)
+ fun_l6_n306(x)
+ else
+ fun_l6_n874(x)
+ end
+end
+
+def fun_l5_n223(x)
+ if (x < 1)
+ fun_l6_n828(x)
+ else
+ fun_l6_n839(x)
+ end
+end
+
+def fun_l5_n224(x)
+ if (x < 1)
+ fun_l6_n739(x)
+ else
+ fun_l6_n569(x)
+ end
+end
+
+def fun_l5_n225(x)
+ if (x < 1)
+ fun_l6_n332(x)
+ else
+ fun_l6_n49(x)
+ end
+end
+
+def fun_l5_n226(x)
+ if (x < 1)
+ fun_l6_n783(x)
+ else
+ fun_l6_n20(x)
+ end
+end
+
+def fun_l5_n227(x)
+ if (x < 1)
+ fun_l6_n774(x)
+ else
+ fun_l6_n346(x)
+ end
+end
+
+def fun_l5_n228(x)
+ if (x < 1)
+ fun_l6_n637(x)
+ else
+ fun_l6_n302(x)
+ end
+end
+
+def fun_l5_n229(x)
+ if (x < 1)
+ fun_l6_n10(x)
+ else
+ fun_l6_n697(x)
+ end
+end
+
+def fun_l5_n230(x)
+ if (x < 1)
+ fun_l6_n804(x)
+ else
+ fun_l6_n141(x)
+ end
+end
+
+def fun_l5_n231(x)
+ if (x < 1)
+ fun_l6_n232(x)
+ else
+ fun_l6_n88(x)
+ end
+end
+
+def fun_l5_n232(x)
+ if (x < 1)
+ fun_l6_n248(x)
+ else
+ fun_l6_n862(x)
+ end
+end
+
+def fun_l5_n233(x)
+ if (x < 1)
+ fun_l6_n287(x)
+ else
+ fun_l6_n315(x)
+ end
+end
+
+def fun_l5_n234(x)
+ if (x < 1)
+ fun_l6_n543(x)
+ else
+ fun_l6_n182(x)
+ end
+end
+
+def fun_l5_n235(x)
+ if (x < 1)
+ fun_l6_n162(x)
+ else
+ fun_l6_n710(x)
+ end
+end
+
+def fun_l5_n236(x)
+ if (x < 1)
+ fun_l6_n879(x)
+ else
+ fun_l6_n262(x)
+ end
+end
+
+def fun_l5_n237(x)
+ if (x < 1)
+ fun_l6_n706(x)
+ else
+ fun_l6_n112(x)
+ end
+end
+
+def fun_l5_n238(x)
+ if (x < 1)
+ fun_l6_n578(x)
+ else
+ fun_l6_n792(x)
+ end
+end
+
+def fun_l5_n239(x)
+ if (x < 1)
+ fun_l6_n685(x)
+ else
+ fun_l6_n441(x)
+ end
+end
+
+def fun_l5_n240(x)
+ if (x < 1)
+ fun_l6_n706(x)
+ else
+ fun_l6_n737(x)
+ end
+end
+
+def fun_l5_n241(x)
+ if (x < 1)
+ fun_l6_n360(x)
+ else
+ fun_l6_n751(x)
+ end
+end
+
+def fun_l5_n242(x)
+ if (x < 1)
+ fun_l6_n823(x)
+ else
+ fun_l6_n888(x)
+ end
+end
+
+def fun_l5_n243(x)
+ if (x < 1)
+ fun_l6_n743(x)
+ else
+ fun_l6_n705(x)
+ end
+end
+
+def fun_l5_n244(x)
+ if (x < 1)
+ fun_l6_n340(x)
+ else
+ fun_l6_n541(x)
+ end
+end
+
+def fun_l5_n245(x)
+ if (x < 1)
+ fun_l6_n324(x)
+ else
+ fun_l6_n121(x)
+ end
+end
+
+def fun_l5_n246(x)
+ if (x < 1)
+ fun_l6_n241(x)
+ else
+ fun_l6_n584(x)
+ end
+end
+
+def fun_l5_n247(x)
+ if (x < 1)
+ fun_l6_n468(x)
+ else
+ fun_l6_n673(x)
+ end
+end
+
+def fun_l5_n248(x)
+ if (x < 1)
+ fun_l6_n595(x)
+ else
+ fun_l6_n537(x)
+ end
+end
+
+def fun_l5_n249(x)
+ if (x < 1)
+ fun_l6_n166(x)
+ else
+ fun_l6_n766(x)
+ end
+end
+
+def fun_l5_n250(x)
+ if (x < 1)
+ fun_l6_n322(x)
+ else
+ fun_l6_n904(x)
+ end
+end
+
+def fun_l5_n251(x)
+ if (x < 1)
+ fun_l6_n273(x)
+ else
+ fun_l6_n353(x)
+ end
+end
+
+def fun_l5_n252(x)
+ if (x < 1)
+ fun_l6_n990(x)
+ else
+ fun_l6_n360(x)
+ end
+end
+
+def fun_l5_n253(x)
+ if (x < 1)
+ fun_l6_n552(x)
+ else
+ fun_l6_n649(x)
+ end
+end
+
+def fun_l5_n254(x)
+ if (x < 1)
+ fun_l6_n917(x)
+ else
+ fun_l6_n803(x)
+ end
+end
+
+def fun_l5_n255(x)
+ if (x < 1)
+ fun_l6_n763(x)
+ else
+ fun_l6_n464(x)
+ end
+end
+
+def fun_l5_n256(x)
+ if (x < 1)
+ fun_l6_n577(x)
+ else
+ fun_l6_n70(x)
+ end
+end
+
+def fun_l5_n257(x)
+ if (x < 1)
+ fun_l6_n618(x)
+ else
+ fun_l6_n943(x)
+ end
+end
+
+def fun_l5_n258(x)
+ if (x < 1)
+ fun_l6_n683(x)
+ else
+ fun_l6_n761(x)
+ end
+end
+
+def fun_l5_n259(x)
+ if (x < 1)
+ fun_l6_n284(x)
+ else
+ fun_l6_n223(x)
+ end
+end
+
+def fun_l5_n260(x)
+ if (x < 1)
+ fun_l6_n189(x)
+ else
+ fun_l6_n455(x)
+ end
+end
+
+def fun_l5_n261(x)
+ if (x < 1)
+ fun_l6_n632(x)
+ else
+ fun_l6_n245(x)
+ end
+end
+
+def fun_l5_n262(x)
+ if (x < 1)
+ fun_l6_n940(x)
+ else
+ fun_l6_n38(x)
+ end
+end
+
+def fun_l5_n263(x)
+ if (x < 1)
+ fun_l6_n289(x)
+ else
+ fun_l6_n356(x)
+ end
+end
+
+def fun_l5_n264(x)
+ if (x < 1)
+ fun_l6_n268(x)
+ else
+ fun_l6_n412(x)
+ end
+end
+
+def fun_l5_n265(x)
+ if (x < 1)
+ fun_l6_n370(x)
+ else
+ fun_l6_n858(x)
+ end
+end
+
+def fun_l5_n266(x)
+ if (x < 1)
+ fun_l6_n523(x)
+ else
+ fun_l6_n809(x)
+ end
+end
+
+def fun_l5_n267(x)
+ if (x < 1)
+ fun_l6_n469(x)
+ else
+ fun_l6_n260(x)
+ end
+end
+
+def fun_l5_n268(x)
+ if (x < 1)
+ fun_l6_n442(x)
+ else
+ fun_l6_n738(x)
+ end
+end
+
+def fun_l5_n269(x)
+ if (x < 1)
+ fun_l6_n663(x)
+ else
+ fun_l6_n109(x)
+ end
+end
+
+def fun_l5_n270(x)
+ if (x < 1)
+ fun_l6_n302(x)
+ else
+ fun_l6_n664(x)
+ end
+end
+
+def fun_l5_n271(x)
+ if (x < 1)
+ fun_l6_n201(x)
+ else
+ fun_l6_n251(x)
+ end
+end
+
+def fun_l5_n272(x)
+ if (x < 1)
+ fun_l6_n776(x)
+ else
+ fun_l6_n903(x)
+ end
+end
+
+def fun_l5_n273(x)
+ if (x < 1)
+ fun_l6_n683(x)
+ else
+ fun_l6_n233(x)
+ end
+end
+
+def fun_l5_n274(x)
+ if (x < 1)
+ fun_l6_n530(x)
+ else
+ fun_l6_n487(x)
+ end
+end
+
+def fun_l5_n275(x)
+ if (x < 1)
+ fun_l6_n848(x)
+ else
+ fun_l6_n99(x)
+ end
+end
+
+def fun_l5_n276(x)
+ if (x < 1)
+ fun_l6_n126(x)
+ else
+ fun_l6_n914(x)
+ end
+end
+
+def fun_l5_n277(x)
+ if (x < 1)
+ fun_l6_n304(x)
+ else
+ fun_l6_n198(x)
+ end
+end
+
+def fun_l5_n278(x)
+ if (x < 1)
+ fun_l6_n47(x)
+ else
+ fun_l6_n179(x)
+ end
+end
+
+def fun_l5_n279(x)
+ if (x < 1)
+ fun_l6_n846(x)
+ else
+ fun_l6_n301(x)
+ end
+end
+
+def fun_l5_n280(x)
+ if (x < 1)
+ fun_l6_n576(x)
+ else
+ fun_l6_n561(x)
+ end
+end
+
+def fun_l5_n281(x)
+ if (x < 1)
+ fun_l6_n307(x)
+ else
+ fun_l6_n545(x)
+ end
+end
+
+def fun_l5_n282(x)
+ if (x < 1)
+ fun_l6_n434(x)
+ else
+ fun_l6_n669(x)
+ end
+end
+
+def fun_l5_n283(x)
+ if (x < 1)
+ fun_l6_n606(x)
+ else
+ fun_l6_n147(x)
+ end
+end
+
+def fun_l5_n284(x)
+ if (x < 1)
+ fun_l6_n212(x)
+ else
+ fun_l6_n504(x)
+ end
+end
+
+def fun_l5_n285(x)
+ if (x < 1)
+ fun_l6_n193(x)
+ else
+ fun_l6_n165(x)
+ end
+end
+
+def fun_l5_n286(x)
+ if (x < 1)
+ fun_l6_n569(x)
+ else
+ fun_l6_n100(x)
+ end
+end
+
+def fun_l5_n287(x)
+ if (x < 1)
+ fun_l6_n59(x)
+ else
+ fun_l6_n998(x)
+ end
+end
+
+def fun_l5_n288(x)
+ if (x < 1)
+ fun_l6_n544(x)
+ else
+ fun_l6_n923(x)
+ end
+end
+
+def fun_l5_n289(x)
+ if (x < 1)
+ fun_l6_n317(x)
+ else
+ fun_l6_n255(x)
+ end
+end
+
+def fun_l5_n290(x)
+ if (x < 1)
+ fun_l6_n476(x)
+ else
+ fun_l6_n789(x)
+ end
+end
+
+def fun_l5_n291(x)
+ if (x < 1)
+ fun_l6_n324(x)
+ else
+ fun_l6_n162(x)
+ end
+end
+
+def fun_l5_n292(x)
+ if (x < 1)
+ fun_l6_n704(x)
+ else
+ fun_l6_n454(x)
+ end
+end
+
+def fun_l5_n293(x)
+ if (x < 1)
+ fun_l6_n994(x)
+ else
+ fun_l6_n637(x)
+ end
+end
+
+def fun_l5_n294(x)
+ if (x < 1)
+ fun_l6_n801(x)
+ else
+ fun_l6_n913(x)
+ end
+end
+
+def fun_l5_n295(x)
+ if (x < 1)
+ fun_l6_n579(x)
+ else
+ fun_l6_n795(x)
+ end
+end
+
+def fun_l5_n296(x)
+ if (x < 1)
+ fun_l6_n689(x)
+ else
+ fun_l6_n546(x)
+ end
+end
+
+def fun_l5_n297(x)
+ if (x < 1)
+ fun_l6_n971(x)
+ else
+ fun_l6_n493(x)
+ end
+end
+
+def fun_l5_n298(x)
+ if (x < 1)
+ fun_l6_n67(x)
+ else
+ fun_l6_n372(x)
+ end
+end
+
+def fun_l5_n299(x)
+ if (x < 1)
+ fun_l6_n654(x)
+ else
+ fun_l6_n921(x)
+ end
+end
+
+def fun_l5_n300(x)
+ if (x < 1)
+ fun_l6_n402(x)
+ else
+ fun_l6_n437(x)
+ end
+end
+
+def fun_l5_n301(x)
+ if (x < 1)
+ fun_l6_n448(x)
+ else
+ fun_l6_n177(x)
+ end
+end
+
+def fun_l5_n302(x)
+ if (x < 1)
+ fun_l6_n308(x)
+ else
+ fun_l6_n869(x)
+ end
+end
+
+def fun_l5_n303(x)
+ if (x < 1)
+ fun_l6_n825(x)
+ else
+ fun_l6_n848(x)
+ end
+end
+
+def fun_l5_n304(x)
+ if (x < 1)
+ fun_l6_n735(x)
+ else
+ fun_l6_n653(x)
+ end
+end
+
+def fun_l5_n305(x)
+ if (x < 1)
+ fun_l6_n393(x)
+ else
+ fun_l6_n113(x)
+ end
+end
+
+def fun_l5_n306(x)
+ if (x < 1)
+ fun_l6_n821(x)
+ else
+ fun_l6_n827(x)
+ end
+end
+
+def fun_l5_n307(x)
+ if (x < 1)
+ fun_l6_n734(x)
+ else
+ fun_l6_n498(x)
+ end
+end
+
+def fun_l5_n308(x)
+ if (x < 1)
+ fun_l6_n833(x)
+ else
+ fun_l6_n302(x)
+ end
+end
+
+def fun_l5_n309(x)
+ if (x < 1)
+ fun_l6_n596(x)
+ else
+ fun_l6_n544(x)
+ end
+end
+
+def fun_l5_n310(x)
+ if (x < 1)
+ fun_l6_n61(x)
+ else
+ fun_l6_n823(x)
+ end
+end
+
+def fun_l5_n311(x)
+ if (x < 1)
+ fun_l6_n596(x)
+ else
+ fun_l6_n98(x)
+ end
+end
+
+def fun_l5_n312(x)
+ if (x < 1)
+ fun_l6_n78(x)
+ else
+ fun_l6_n186(x)
+ end
+end
+
+def fun_l5_n313(x)
+ if (x < 1)
+ fun_l6_n286(x)
+ else
+ fun_l6_n230(x)
+ end
+end
+
+def fun_l5_n314(x)
+ if (x < 1)
+ fun_l6_n613(x)
+ else
+ fun_l6_n412(x)
+ end
+end
+
+def fun_l5_n315(x)
+ if (x < 1)
+ fun_l6_n0(x)
+ else
+ fun_l6_n579(x)
+ end
+end
+
+def fun_l5_n316(x)
+ if (x < 1)
+ fun_l6_n991(x)
+ else
+ fun_l6_n379(x)
+ end
+end
+
+def fun_l5_n317(x)
+ if (x < 1)
+ fun_l6_n825(x)
+ else
+ fun_l6_n964(x)
+ end
+end
+
+def fun_l5_n318(x)
+ if (x < 1)
+ fun_l6_n707(x)
+ else
+ fun_l6_n664(x)
+ end
+end
+
+def fun_l5_n319(x)
+ if (x < 1)
+ fun_l6_n326(x)
+ else
+ fun_l6_n26(x)
+ end
+end
+
+def fun_l5_n320(x)
+ if (x < 1)
+ fun_l6_n684(x)
+ else
+ fun_l6_n333(x)
+ end
+end
+
+def fun_l5_n321(x)
+ if (x < 1)
+ fun_l6_n165(x)
+ else
+ fun_l6_n586(x)
+ end
+end
+
+def fun_l5_n322(x)
+ if (x < 1)
+ fun_l6_n28(x)
+ else
+ fun_l6_n53(x)
+ end
+end
+
+def fun_l5_n323(x)
+ if (x < 1)
+ fun_l6_n693(x)
+ else
+ fun_l6_n84(x)
+ end
+end
+
+def fun_l5_n324(x)
+ if (x < 1)
+ fun_l6_n500(x)
+ else
+ fun_l6_n445(x)
+ end
+end
+
+def fun_l5_n325(x)
+ if (x < 1)
+ fun_l6_n189(x)
+ else
+ fun_l6_n756(x)
+ end
+end
+
+def fun_l5_n326(x)
+ if (x < 1)
+ fun_l6_n147(x)
+ else
+ fun_l6_n709(x)
+ end
+end
+
+def fun_l5_n327(x)
+ if (x < 1)
+ fun_l6_n893(x)
+ else
+ fun_l6_n851(x)
+ end
+end
+
+def fun_l5_n328(x)
+ if (x < 1)
+ fun_l6_n685(x)
+ else
+ fun_l6_n399(x)
+ end
+end
+
+def fun_l5_n329(x)
+ if (x < 1)
+ fun_l6_n281(x)
+ else
+ fun_l6_n284(x)
+ end
+end
+
+def fun_l5_n330(x)
+ if (x < 1)
+ fun_l6_n579(x)
+ else
+ fun_l6_n671(x)
+ end
+end
+
+def fun_l5_n331(x)
+ if (x < 1)
+ fun_l6_n176(x)
+ else
+ fun_l6_n829(x)
+ end
+end
+
+def fun_l5_n332(x)
+ if (x < 1)
+ fun_l6_n209(x)
+ else
+ fun_l6_n91(x)
+ end
+end
+
+def fun_l5_n333(x)
+ if (x < 1)
+ fun_l6_n302(x)
+ else
+ fun_l6_n360(x)
+ end
+end
+
+def fun_l5_n334(x)
+ if (x < 1)
+ fun_l6_n701(x)
+ else
+ fun_l6_n438(x)
+ end
+end
+
+def fun_l5_n335(x)
+ if (x < 1)
+ fun_l6_n923(x)
+ else
+ fun_l6_n613(x)
+ end
+end
+
+def fun_l5_n336(x)
+ if (x < 1)
+ fun_l6_n490(x)
+ else
+ fun_l6_n405(x)
+ end
+end
+
+def fun_l5_n337(x)
+ if (x < 1)
+ fun_l6_n187(x)
+ else
+ fun_l6_n953(x)
+ end
+end
+
+def fun_l5_n338(x)
+ if (x < 1)
+ fun_l6_n396(x)
+ else
+ fun_l6_n917(x)
+ end
+end
+
+def fun_l5_n339(x)
+ if (x < 1)
+ fun_l6_n822(x)
+ else
+ fun_l6_n939(x)
+ end
+end
+
+def fun_l5_n340(x)
+ if (x < 1)
+ fun_l6_n665(x)
+ else
+ fun_l6_n890(x)
+ end
+end
+
+def fun_l5_n341(x)
+ if (x < 1)
+ fun_l6_n125(x)
+ else
+ fun_l6_n817(x)
+ end
+end
+
+def fun_l5_n342(x)
+ if (x < 1)
+ fun_l6_n825(x)
+ else
+ fun_l6_n853(x)
+ end
+end
+
+def fun_l5_n343(x)
+ if (x < 1)
+ fun_l6_n724(x)
+ else
+ fun_l6_n633(x)
+ end
+end
+
+def fun_l5_n344(x)
+ if (x < 1)
+ fun_l6_n901(x)
+ else
+ fun_l6_n26(x)
+ end
+end
+
+def fun_l5_n345(x)
+ if (x < 1)
+ fun_l6_n406(x)
+ else
+ fun_l6_n664(x)
+ end
+end
+
+def fun_l5_n346(x)
+ if (x < 1)
+ fun_l6_n720(x)
+ else
+ fun_l6_n856(x)
+ end
+end
+
+def fun_l5_n347(x)
+ if (x < 1)
+ fun_l6_n617(x)
+ else
+ fun_l6_n116(x)
+ end
+end
+
+def fun_l5_n348(x)
+ if (x < 1)
+ fun_l6_n560(x)
+ else
+ fun_l6_n24(x)
+ end
+end
+
+def fun_l5_n349(x)
+ if (x < 1)
+ fun_l6_n758(x)
+ else
+ fun_l6_n297(x)
+ end
+end
+
+def fun_l5_n350(x)
+ if (x < 1)
+ fun_l6_n583(x)
+ else
+ fun_l6_n673(x)
+ end
+end
+
+def fun_l5_n351(x)
+ if (x < 1)
+ fun_l6_n990(x)
+ else
+ fun_l6_n512(x)
+ end
+end
+
+def fun_l5_n352(x)
+ if (x < 1)
+ fun_l6_n250(x)
+ else
+ fun_l6_n819(x)
+ end
+end
+
+def fun_l5_n353(x)
+ if (x < 1)
+ fun_l6_n186(x)
+ else
+ fun_l6_n787(x)
+ end
+end
+
+def fun_l5_n354(x)
+ if (x < 1)
+ fun_l6_n217(x)
+ else
+ fun_l6_n231(x)
+ end
+end
+
+def fun_l5_n355(x)
+ if (x < 1)
+ fun_l6_n827(x)
+ else
+ fun_l6_n439(x)
+ end
+end
+
+def fun_l5_n356(x)
+ if (x < 1)
+ fun_l6_n456(x)
+ else
+ fun_l6_n352(x)
+ end
+end
+
+def fun_l5_n357(x)
+ if (x < 1)
+ fun_l6_n306(x)
+ else
+ fun_l6_n236(x)
+ end
+end
+
+def fun_l5_n358(x)
+ if (x < 1)
+ fun_l6_n515(x)
+ else
+ fun_l6_n100(x)
+ end
+end
+
+def fun_l5_n359(x)
+ if (x < 1)
+ fun_l6_n28(x)
+ else
+ fun_l6_n820(x)
+ end
+end
+
+def fun_l5_n360(x)
+ if (x < 1)
+ fun_l6_n683(x)
+ else
+ fun_l6_n547(x)
+ end
+end
+
+def fun_l5_n361(x)
+ if (x < 1)
+ fun_l6_n573(x)
+ else
+ fun_l6_n699(x)
+ end
+end
+
+def fun_l5_n362(x)
+ if (x < 1)
+ fun_l6_n807(x)
+ else
+ fun_l6_n548(x)
+ end
+end
+
+def fun_l5_n363(x)
+ if (x < 1)
+ fun_l6_n712(x)
+ else
+ fun_l6_n323(x)
+ end
+end
+
+def fun_l5_n364(x)
+ if (x < 1)
+ fun_l6_n457(x)
+ else
+ fun_l6_n447(x)
+ end
+end
+
+def fun_l5_n365(x)
+ if (x < 1)
+ fun_l6_n684(x)
+ else
+ fun_l6_n782(x)
+ end
+end
+
+def fun_l5_n366(x)
+ if (x < 1)
+ fun_l6_n217(x)
+ else
+ fun_l6_n344(x)
+ end
+end
+
+def fun_l5_n367(x)
+ if (x < 1)
+ fun_l6_n670(x)
+ else
+ fun_l6_n311(x)
+ end
+end
+
+def fun_l5_n368(x)
+ if (x < 1)
+ fun_l6_n224(x)
+ else
+ fun_l6_n198(x)
+ end
+end
+
+def fun_l5_n369(x)
+ if (x < 1)
+ fun_l6_n517(x)
+ else
+ fun_l6_n186(x)
+ end
+end
+
+def fun_l5_n370(x)
+ if (x < 1)
+ fun_l6_n511(x)
+ else
+ fun_l6_n27(x)
+ end
+end
+
+def fun_l5_n371(x)
+ if (x < 1)
+ fun_l6_n485(x)
+ else
+ fun_l6_n288(x)
+ end
+end
+
+def fun_l5_n372(x)
+ if (x < 1)
+ fun_l6_n931(x)
+ else
+ fun_l6_n473(x)
+ end
+end
+
+def fun_l5_n373(x)
+ if (x < 1)
+ fun_l6_n381(x)
+ else
+ fun_l6_n650(x)
+ end
+end
+
+def fun_l5_n374(x)
+ if (x < 1)
+ fun_l6_n132(x)
+ else
+ fun_l6_n243(x)
+ end
+end
+
+def fun_l5_n375(x)
+ if (x < 1)
+ fun_l6_n900(x)
+ else
+ fun_l6_n322(x)
+ end
+end
+
+def fun_l5_n376(x)
+ if (x < 1)
+ fun_l6_n787(x)
+ else
+ fun_l6_n588(x)
+ end
+end
+
+def fun_l5_n377(x)
+ if (x < 1)
+ fun_l6_n233(x)
+ else
+ fun_l6_n358(x)
+ end
+end
+
+def fun_l5_n378(x)
+ if (x < 1)
+ fun_l6_n601(x)
+ else
+ fun_l6_n40(x)
+ end
+end
+
+def fun_l5_n379(x)
+ if (x < 1)
+ fun_l6_n682(x)
+ else
+ fun_l6_n63(x)
+ end
+end
+
+def fun_l5_n380(x)
+ if (x < 1)
+ fun_l6_n279(x)
+ else
+ fun_l6_n393(x)
+ end
+end
+
+def fun_l5_n381(x)
+ if (x < 1)
+ fun_l6_n83(x)
+ else
+ fun_l6_n538(x)
+ end
+end
+
+def fun_l5_n382(x)
+ if (x < 1)
+ fun_l6_n956(x)
+ else
+ fun_l6_n194(x)
+ end
+end
+
+def fun_l5_n383(x)
+ if (x < 1)
+ fun_l6_n55(x)
+ else
+ fun_l6_n140(x)
+ end
+end
+
+def fun_l5_n384(x)
+ if (x < 1)
+ fun_l6_n165(x)
+ else
+ fun_l6_n784(x)
+ end
+end
+
+def fun_l5_n385(x)
+ if (x < 1)
+ fun_l6_n582(x)
+ else
+ fun_l6_n97(x)
+ end
+end
+
+def fun_l5_n386(x)
+ if (x < 1)
+ fun_l6_n362(x)
+ else
+ fun_l6_n935(x)
+ end
+end
+
+def fun_l5_n387(x)
+ if (x < 1)
+ fun_l6_n496(x)
+ else
+ fun_l6_n512(x)
+ end
+end
+
+def fun_l5_n388(x)
+ if (x < 1)
+ fun_l6_n793(x)
+ else
+ fun_l6_n746(x)
+ end
+end
+
+def fun_l5_n389(x)
+ if (x < 1)
+ fun_l6_n172(x)
+ else
+ fun_l6_n731(x)
+ end
+end
+
+def fun_l5_n390(x)
+ if (x < 1)
+ fun_l6_n895(x)
+ else
+ fun_l6_n694(x)
+ end
+end
+
+def fun_l5_n391(x)
+ if (x < 1)
+ fun_l6_n336(x)
+ else
+ fun_l6_n551(x)
+ end
+end
+
+def fun_l5_n392(x)
+ if (x < 1)
+ fun_l6_n453(x)
+ else
+ fun_l6_n83(x)
+ end
+end
+
+def fun_l5_n393(x)
+ if (x < 1)
+ fun_l6_n571(x)
+ else
+ fun_l6_n293(x)
+ end
+end
+
+def fun_l5_n394(x)
+ if (x < 1)
+ fun_l6_n872(x)
+ else
+ fun_l6_n519(x)
+ end
+end
+
+def fun_l5_n395(x)
+ if (x < 1)
+ fun_l6_n912(x)
+ else
+ fun_l6_n955(x)
+ end
+end
+
+def fun_l5_n396(x)
+ if (x < 1)
+ fun_l6_n961(x)
+ else
+ fun_l6_n367(x)
+ end
+end
+
+def fun_l5_n397(x)
+ if (x < 1)
+ fun_l6_n255(x)
+ else
+ fun_l6_n639(x)
+ end
+end
+
+def fun_l5_n398(x)
+ if (x < 1)
+ fun_l6_n970(x)
+ else
+ fun_l6_n465(x)
+ end
+end
+
+def fun_l5_n399(x)
+ if (x < 1)
+ fun_l6_n625(x)
+ else
+ fun_l6_n387(x)
+ end
+end
+
+def fun_l5_n400(x)
+ if (x < 1)
+ fun_l6_n537(x)
+ else
+ fun_l6_n336(x)
+ end
+end
+
+def fun_l5_n401(x)
+ if (x < 1)
+ fun_l6_n61(x)
+ else
+ fun_l6_n0(x)
+ end
+end
+
+def fun_l5_n402(x)
+ if (x < 1)
+ fun_l6_n358(x)
+ else
+ fun_l6_n715(x)
+ end
+end
+
+def fun_l5_n403(x)
+ if (x < 1)
+ fun_l6_n864(x)
+ else
+ fun_l6_n729(x)
+ end
+end
+
+def fun_l5_n404(x)
+ if (x < 1)
+ fun_l6_n393(x)
+ else
+ fun_l6_n962(x)
+ end
+end
+
+def fun_l5_n405(x)
+ if (x < 1)
+ fun_l6_n995(x)
+ else
+ fun_l6_n835(x)
+ end
+end
+
+def fun_l5_n406(x)
+ if (x < 1)
+ fun_l6_n605(x)
+ else
+ fun_l6_n732(x)
+ end
+end
+
+def fun_l5_n407(x)
+ if (x < 1)
+ fun_l6_n132(x)
+ else
+ fun_l6_n112(x)
+ end
+end
+
+def fun_l5_n408(x)
+ if (x < 1)
+ fun_l6_n311(x)
+ else
+ fun_l6_n972(x)
+ end
+end
+
+def fun_l5_n409(x)
+ if (x < 1)
+ fun_l6_n460(x)
+ else
+ fun_l6_n750(x)
+ end
+end
+
+def fun_l5_n410(x)
+ if (x < 1)
+ fun_l6_n237(x)
+ else
+ fun_l6_n463(x)
+ end
+end
+
+def fun_l5_n411(x)
+ if (x < 1)
+ fun_l6_n251(x)
+ else
+ fun_l6_n944(x)
+ end
+end
+
+def fun_l5_n412(x)
+ if (x < 1)
+ fun_l6_n123(x)
+ else
+ fun_l6_n369(x)
+ end
+end
+
+def fun_l5_n413(x)
+ if (x < 1)
+ fun_l6_n371(x)
+ else
+ fun_l6_n589(x)
+ end
+end
+
+def fun_l5_n414(x)
+ if (x < 1)
+ fun_l6_n232(x)
+ else
+ fun_l6_n354(x)
+ end
+end
+
+def fun_l5_n415(x)
+ if (x < 1)
+ fun_l6_n580(x)
+ else
+ fun_l6_n330(x)
+ end
+end
+
+def fun_l5_n416(x)
+ if (x < 1)
+ fun_l6_n483(x)
+ else
+ fun_l6_n446(x)
+ end
+end
+
+def fun_l5_n417(x)
+ if (x < 1)
+ fun_l6_n834(x)
+ else
+ fun_l6_n284(x)
+ end
+end
+
+def fun_l5_n418(x)
+ if (x < 1)
+ fun_l6_n864(x)
+ else
+ fun_l6_n825(x)
+ end
+end
+
+def fun_l5_n419(x)
+ if (x < 1)
+ fun_l6_n406(x)
+ else
+ fun_l6_n680(x)
+ end
+end
+
+def fun_l5_n420(x)
+ if (x < 1)
+ fun_l6_n101(x)
+ else
+ fun_l6_n4(x)
+ end
+end
+
+def fun_l5_n421(x)
+ if (x < 1)
+ fun_l6_n628(x)
+ else
+ fun_l6_n303(x)
+ end
+end
+
+def fun_l5_n422(x)
+ if (x < 1)
+ fun_l6_n521(x)
+ else
+ fun_l6_n547(x)
+ end
+end
+
+def fun_l5_n423(x)
+ if (x < 1)
+ fun_l6_n589(x)
+ else
+ fun_l6_n134(x)
+ end
+end
+
+def fun_l5_n424(x)
+ if (x < 1)
+ fun_l6_n161(x)
+ else
+ fun_l6_n347(x)
+ end
+end
+
+def fun_l5_n425(x)
+ if (x < 1)
+ fun_l6_n59(x)
+ else
+ fun_l6_n988(x)
+ end
+end
+
+def fun_l5_n426(x)
+ if (x < 1)
+ fun_l6_n388(x)
+ else
+ fun_l6_n182(x)
+ end
+end
+
+def fun_l5_n427(x)
+ if (x < 1)
+ fun_l6_n500(x)
+ else
+ fun_l6_n536(x)
+ end
+end
+
+def fun_l5_n428(x)
+ if (x < 1)
+ fun_l6_n792(x)
+ else
+ fun_l6_n253(x)
+ end
+end
+
+def fun_l5_n429(x)
+ if (x < 1)
+ fun_l6_n774(x)
+ else
+ fun_l6_n997(x)
+ end
+end
+
+def fun_l5_n430(x)
+ if (x < 1)
+ fun_l6_n876(x)
+ else
+ fun_l6_n798(x)
+ end
+end
+
+def fun_l5_n431(x)
+ if (x < 1)
+ fun_l6_n606(x)
+ else
+ fun_l6_n403(x)
+ end
+end
+
+def fun_l5_n432(x)
+ if (x < 1)
+ fun_l6_n920(x)
+ else
+ fun_l6_n827(x)
+ end
+end
+
+def fun_l5_n433(x)
+ if (x < 1)
+ fun_l6_n887(x)
+ else
+ fun_l6_n149(x)
+ end
+end
+
+def fun_l5_n434(x)
+ if (x < 1)
+ fun_l6_n413(x)
+ else
+ fun_l6_n44(x)
+ end
+end
+
+def fun_l5_n435(x)
+ if (x < 1)
+ fun_l6_n474(x)
+ else
+ fun_l6_n107(x)
+ end
+end
+
+def fun_l5_n436(x)
+ if (x < 1)
+ fun_l6_n807(x)
+ else
+ fun_l6_n636(x)
+ end
+end
+
+def fun_l5_n437(x)
+ if (x < 1)
+ fun_l6_n616(x)
+ else
+ fun_l6_n615(x)
+ end
+end
+
+def fun_l5_n438(x)
+ if (x < 1)
+ fun_l6_n384(x)
+ else
+ fun_l6_n535(x)
+ end
+end
+
+def fun_l5_n439(x)
+ if (x < 1)
+ fun_l6_n326(x)
+ else
+ fun_l6_n929(x)
+ end
+end
+
+def fun_l5_n440(x)
+ if (x < 1)
+ fun_l6_n852(x)
+ else
+ fun_l6_n597(x)
+ end
+end
+
+def fun_l5_n441(x)
+ if (x < 1)
+ fun_l6_n246(x)
+ else
+ fun_l6_n991(x)
+ end
+end
+
+def fun_l5_n442(x)
+ if (x < 1)
+ fun_l6_n258(x)
+ else
+ fun_l6_n140(x)
+ end
+end
+
+def fun_l5_n443(x)
+ if (x < 1)
+ fun_l6_n815(x)
+ else
+ fun_l6_n600(x)
+ end
+end
+
+def fun_l5_n444(x)
+ if (x < 1)
+ fun_l6_n153(x)
+ else
+ fun_l6_n902(x)
+ end
+end
+
+def fun_l5_n445(x)
+ if (x < 1)
+ fun_l6_n289(x)
+ else
+ fun_l6_n240(x)
+ end
+end
+
+def fun_l5_n446(x)
+ if (x < 1)
+ fun_l6_n398(x)
+ else
+ fun_l6_n273(x)
+ end
+end
+
+def fun_l5_n447(x)
+ if (x < 1)
+ fun_l6_n537(x)
+ else
+ fun_l6_n8(x)
+ end
+end
+
+def fun_l5_n448(x)
+ if (x < 1)
+ fun_l6_n801(x)
+ else
+ fun_l6_n389(x)
+ end
+end
+
+def fun_l5_n449(x)
+ if (x < 1)
+ fun_l6_n363(x)
+ else
+ fun_l6_n17(x)
+ end
+end
+
+def fun_l5_n450(x)
+ if (x < 1)
+ fun_l6_n511(x)
+ else
+ fun_l6_n151(x)
+ end
+end
+
+def fun_l5_n451(x)
+ if (x < 1)
+ fun_l6_n640(x)
+ else
+ fun_l6_n785(x)
+ end
+end
+
+def fun_l5_n452(x)
+ if (x < 1)
+ fun_l6_n961(x)
+ else
+ fun_l6_n567(x)
+ end
+end
+
+def fun_l5_n453(x)
+ if (x < 1)
+ fun_l6_n608(x)
+ else
+ fun_l6_n910(x)
+ end
+end
+
+def fun_l5_n454(x)
+ if (x < 1)
+ fun_l6_n898(x)
+ else
+ fun_l6_n231(x)
+ end
+end
+
+def fun_l5_n455(x)
+ if (x < 1)
+ fun_l6_n205(x)
+ else
+ fun_l6_n162(x)
+ end
+end
+
+def fun_l5_n456(x)
+ if (x < 1)
+ fun_l6_n374(x)
+ else
+ fun_l6_n544(x)
+ end
+end
+
+def fun_l5_n457(x)
+ if (x < 1)
+ fun_l6_n514(x)
+ else
+ fun_l6_n522(x)
+ end
+end
+
+def fun_l5_n458(x)
+ if (x < 1)
+ fun_l6_n385(x)
+ else
+ fun_l6_n808(x)
+ end
+end
+
+def fun_l5_n459(x)
+ if (x < 1)
+ fun_l6_n525(x)
+ else
+ fun_l6_n144(x)
+ end
+end
+
+def fun_l5_n460(x)
+ if (x < 1)
+ fun_l6_n781(x)
+ else
+ fun_l6_n180(x)
+ end
+end
+
+def fun_l5_n461(x)
+ if (x < 1)
+ fun_l6_n681(x)
+ else
+ fun_l6_n273(x)
+ end
+end
+
+def fun_l5_n462(x)
+ if (x < 1)
+ fun_l6_n497(x)
+ else
+ fun_l6_n399(x)
+ end
+end
+
+def fun_l5_n463(x)
+ if (x < 1)
+ fun_l6_n261(x)
+ else
+ fun_l6_n311(x)
+ end
+end
+
+def fun_l5_n464(x)
+ if (x < 1)
+ fun_l6_n64(x)
+ else
+ fun_l6_n253(x)
+ end
+end
+
+def fun_l5_n465(x)
+ if (x < 1)
+ fun_l6_n388(x)
+ else
+ fun_l6_n300(x)
+ end
+end
+
+def fun_l5_n466(x)
+ if (x < 1)
+ fun_l6_n822(x)
+ else
+ fun_l6_n277(x)
+ end
+end
+
+def fun_l5_n467(x)
+ if (x < 1)
+ fun_l6_n909(x)
+ else
+ fun_l6_n605(x)
+ end
+end
+
+def fun_l5_n468(x)
+ if (x < 1)
+ fun_l6_n879(x)
+ else
+ fun_l6_n870(x)
+ end
+end
+
+def fun_l5_n469(x)
+ if (x < 1)
+ fun_l6_n351(x)
+ else
+ fun_l6_n917(x)
+ end
+end
+
+def fun_l5_n470(x)
+ if (x < 1)
+ fun_l6_n202(x)
+ else
+ fun_l6_n40(x)
+ end
+end
+
+def fun_l5_n471(x)
+ if (x < 1)
+ fun_l6_n782(x)
+ else
+ fun_l6_n839(x)
+ end
+end
+
+def fun_l5_n472(x)
+ if (x < 1)
+ fun_l6_n370(x)
+ else
+ fun_l6_n868(x)
+ end
+end
+
+def fun_l5_n473(x)
+ if (x < 1)
+ fun_l6_n556(x)
+ else
+ fun_l6_n722(x)
+ end
+end
+
+def fun_l5_n474(x)
+ if (x < 1)
+ fun_l6_n220(x)
+ else
+ fun_l6_n994(x)
+ end
+end
+
+def fun_l5_n475(x)
+ if (x < 1)
+ fun_l6_n266(x)
+ else
+ fun_l6_n872(x)
+ end
+end
+
+def fun_l5_n476(x)
+ if (x < 1)
+ fun_l6_n720(x)
+ else
+ fun_l6_n412(x)
+ end
+end
+
+def fun_l5_n477(x)
+ if (x < 1)
+ fun_l6_n284(x)
+ else
+ fun_l6_n90(x)
+ end
+end
+
+def fun_l5_n478(x)
+ if (x < 1)
+ fun_l6_n716(x)
+ else
+ fun_l6_n125(x)
+ end
+end
+
+def fun_l5_n479(x)
+ if (x < 1)
+ fun_l6_n136(x)
+ else
+ fun_l6_n232(x)
+ end
+end
+
+def fun_l5_n480(x)
+ if (x < 1)
+ fun_l6_n627(x)
+ else
+ fun_l6_n641(x)
+ end
+end
+
+def fun_l5_n481(x)
+ if (x < 1)
+ fun_l6_n411(x)
+ else
+ fun_l6_n943(x)
+ end
+end
+
+def fun_l5_n482(x)
+ if (x < 1)
+ fun_l6_n86(x)
+ else
+ fun_l6_n839(x)
+ end
+end
+
+def fun_l5_n483(x)
+ if (x < 1)
+ fun_l6_n988(x)
+ else
+ fun_l6_n329(x)
+ end
+end
+
+def fun_l5_n484(x)
+ if (x < 1)
+ fun_l6_n595(x)
+ else
+ fun_l6_n499(x)
+ end
+end
+
+def fun_l5_n485(x)
+ if (x < 1)
+ fun_l6_n912(x)
+ else
+ fun_l6_n267(x)
+ end
+end
+
+def fun_l5_n486(x)
+ if (x < 1)
+ fun_l6_n334(x)
+ else
+ fun_l6_n459(x)
+ end
+end
+
+def fun_l5_n487(x)
+ if (x < 1)
+ fun_l6_n771(x)
+ else
+ fun_l6_n458(x)
+ end
+end
+
+def fun_l5_n488(x)
+ if (x < 1)
+ fun_l6_n609(x)
+ else
+ fun_l6_n280(x)
+ end
+end
+
+def fun_l5_n489(x)
+ if (x < 1)
+ fun_l6_n564(x)
+ else
+ fun_l6_n564(x)
+ end
+end
+
+def fun_l5_n490(x)
+ if (x < 1)
+ fun_l6_n271(x)
+ else
+ fun_l6_n904(x)
+ end
+end
+
+def fun_l5_n491(x)
+ if (x < 1)
+ fun_l6_n338(x)
+ else
+ fun_l6_n694(x)
+ end
+end
+
+def fun_l5_n492(x)
+ if (x < 1)
+ fun_l6_n596(x)
+ else
+ fun_l6_n191(x)
+ end
+end
+
+def fun_l5_n493(x)
+ if (x < 1)
+ fun_l6_n369(x)
+ else
+ fun_l6_n513(x)
+ end
+end
+
+def fun_l5_n494(x)
+ if (x < 1)
+ fun_l6_n972(x)
+ else
+ fun_l6_n945(x)
+ end
+end
+
+def fun_l5_n495(x)
+ if (x < 1)
+ fun_l6_n747(x)
+ else
+ fun_l6_n96(x)
+ end
+end
+
+def fun_l5_n496(x)
+ if (x < 1)
+ fun_l6_n220(x)
+ else
+ fun_l6_n665(x)
+ end
+end
+
+def fun_l5_n497(x)
+ if (x < 1)
+ fun_l6_n793(x)
+ else
+ fun_l6_n468(x)
+ end
+end
+
+def fun_l5_n498(x)
+ if (x < 1)
+ fun_l6_n227(x)
+ else
+ fun_l6_n576(x)
+ end
+end
+
+def fun_l5_n499(x)
+ if (x < 1)
+ fun_l6_n356(x)
+ else
+ fun_l6_n614(x)
+ end
+end
+
+def fun_l5_n500(x)
+ if (x < 1)
+ fun_l6_n256(x)
+ else
+ fun_l6_n237(x)
+ end
+end
+
+def fun_l5_n501(x)
+ if (x < 1)
+ fun_l6_n503(x)
+ else
+ fun_l6_n159(x)
+ end
+end
+
+def fun_l5_n502(x)
+ if (x < 1)
+ fun_l6_n523(x)
+ else
+ fun_l6_n547(x)
+ end
+end
+
+def fun_l5_n503(x)
+ if (x < 1)
+ fun_l6_n778(x)
+ else
+ fun_l6_n600(x)
+ end
+end
+
+def fun_l5_n504(x)
+ if (x < 1)
+ fun_l6_n654(x)
+ else
+ fun_l6_n950(x)
+ end
+end
+
+def fun_l5_n505(x)
+ if (x < 1)
+ fun_l6_n105(x)
+ else
+ fun_l6_n881(x)
+ end
+end
+
+def fun_l5_n506(x)
+ if (x < 1)
+ fun_l6_n956(x)
+ else
+ fun_l6_n71(x)
+ end
+end
+
+def fun_l5_n507(x)
+ if (x < 1)
+ fun_l6_n33(x)
+ else
+ fun_l6_n431(x)
+ end
+end
+
+def fun_l5_n508(x)
+ if (x < 1)
+ fun_l6_n587(x)
+ else
+ fun_l6_n1(x)
+ end
+end
+
+def fun_l5_n509(x)
+ if (x < 1)
+ fun_l6_n258(x)
+ else
+ fun_l6_n547(x)
+ end
+end
+
+def fun_l5_n510(x)
+ if (x < 1)
+ fun_l6_n816(x)
+ else
+ fun_l6_n558(x)
+ end
+end
+
+def fun_l5_n511(x)
+ if (x < 1)
+ fun_l6_n61(x)
+ else
+ fun_l6_n10(x)
+ end
+end
+
+def fun_l5_n512(x)
+ if (x < 1)
+ fun_l6_n674(x)
+ else
+ fun_l6_n466(x)
+ end
+end
+
+def fun_l5_n513(x)
+ if (x < 1)
+ fun_l6_n580(x)
+ else
+ fun_l6_n398(x)
+ end
+end
+
+def fun_l5_n514(x)
+ if (x < 1)
+ fun_l6_n495(x)
+ else
+ fun_l6_n407(x)
+ end
+end
+
+def fun_l5_n515(x)
+ if (x < 1)
+ fun_l6_n639(x)
+ else
+ fun_l6_n214(x)
+ end
+end
+
+def fun_l5_n516(x)
+ if (x < 1)
+ fun_l6_n15(x)
+ else
+ fun_l6_n716(x)
+ end
+end
+
+def fun_l5_n517(x)
+ if (x < 1)
+ fun_l6_n645(x)
+ else
+ fun_l6_n645(x)
+ end
+end
+
+def fun_l5_n518(x)
+ if (x < 1)
+ fun_l6_n615(x)
+ else
+ fun_l6_n44(x)
+ end
+end
+
+def fun_l5_n519(x)
+ if (x < 1)
+ fun_l6_n399(x)
+ else
+ fun_l6_n663(x)
+ end
+end
+
+def fun_l5_n520(x)
+ if (x < 1)
+ fun_l6_n85(x)
+ else
+ fun_l6_n870(x)
+ end
+end
+
+def fun_l5_n521(x)
+ if (x < 1)
+ fun_l6_n14(x)
+ else
+ fun_l6_n965(x)
+ end
+end
+
+def fun_l5_n522(x)
+ if (x < 1)
+ fun_l6_n24(x)
+ else
+ fun_l6_n581(x)
+ end
+end
+
+def fun_l5_n523(x)
+ if (x < 1)
+ fun_l6_n501(x)
+ else
+ fun_l6_n913(x)
+ end
+end
+
+def fun_l5_n524(x)
+ if (x < 1)
+ fun_l6_n772(x)
+ else
+ fun_l6_n999(x)
+ end
+end
+
+def fun_l5_n525(x)
+ if (x < 1)
+ fun_l6_n847(x)
+ else
+ fun_l6_n422(x)
+ end
+end
+
+def fun_l5_n526(x)
+ if (x < 1)
+ fun_l6_n377(x)
+ else
+ fun_l6_n986(x)
+ end
+end
+
+def fun_l5_n527(x)
+ if (x < 1)
+ fun_l6_n548(x)
+ else
+ fun_l6_n40(x)
+ end
+end
+
+def fun_l5_n528(x)
+ if (x < 1)
+ fun_l6_n392(x)
+ else
+ fun_l6_n577(x)
+ end
+end
+
+def fun_l5_n529(x)
+ if (x < 1)
+ fun_l6_n101(x)
+ else
+ fun_l6_n26(x)
+ end
+end
+
+def fun_l5_n530(x)
+ if (x < 1)
+ fun_l6_n800(x)
+ else
+ fun_l6_n958(x)
+ end
+end
+
+def fun_l5_n531(x)
+ if (x < 1)
+ fun_l6_n72(x)
+ else
+ fun_l6_n887(x)
+ end
+end
+
+def fun_l5_n532(x)
+ if (x < 1)
+ fun_l6_n467(x)
+ else
+ fun_l6_n740(x)
+ end
+end
+
+def fun_l5_n533(x)
+ if (x < 1)
+ fun_l6_n264(x)
+ else
+ fun_l6_n683(x)
+ end
+end
+
+def fun_l5_n534(x)
+ if (x < 1)
+ fun_l6_n953(x)
+ else
+ fun_l6_n560(x)
+ end
+end
+
+def fun_l5_n535(x)
+ if (x < 1)
+ fun_l6_n854(x)
+ else
+ fun_l6_n59(x)
+ end
+end
+
+def fun_l5_n536(x)
+ if (x < 1)
+ fun_l6_n940(x)
+ else
+ fun_l6_n832(x)
+ end
+end
+
+def fun_l5_n537(x)
+ if (x < 1)
+ fun_l6_n297(x)
+ else
+ fun_l6_n18(x)
+ end
+end
+
+def fun_l5_n538(x)
+ if (x < 1)
+ fun_l6_n188(x)
+ else
+ fun_l6_n537(x)
+ end
+end
+
+def fun_l5_n539(x)
+ if (x < 1)
+ fun_l6_n992(x)
+ else
+ fun_l6_n825(x)
+ end
+end
+
+def fun_l5_n540(x)
+ if (x < 1)
+ fun_l6_n691(x)
+ else
+ fun_l6_n850(x)
+ end
+end
+
+def fun_l5_n541(x)
+ if (x < 1)
+ fun_l6_n858(x)
+ else
+ fun_l6_n948(x)
+ end
+end
+
+def fun_l5_n542(x)
+ if (x < 1)
+ fun_l6_n923(x)
+ else
+ fun_l6_n112(x)
+ end
+end
+
+def fun_l5_n543(x)
+ if (x < 1)
+ fun_l6_n419(x)
+ else
+ fun_l6_n4(x)
+ end
+end
+
+def fun_l5_n544(x)
+ if (x < 1)
+ fun_l6_n766(x)
+ else
+ fun_l6_n147(x)
+ end
+end
+
+def fun_l5_n545(x)
+ if (x < 1)
+ fun_l6_n327(x)
+ else
+ fun_l6_n327(x)
+ end
+end
+
+def fun_l5_n546(x)
+ if (x < 1)
+ fun_l6_n94(x)
+ else
+ fun_l6_n662(x)
+ end
+end
+
+def fun_l5_n547(x)
+ if (x < 1)
+ fun_l6_n764(x)
+ else
+ fun_l6_n521(x)
+ end
+end
+
+def fun_l5_n548(x)
+ if (x < 1)
+ fun_l6_n509(x)
+ else
+ fun_l6_n231(x)
+ end
+end
+
+def fun_l5_n549(x)
+ if (x < 1)
+ fun_l6_n370(x)
+ else
+ fun_l6_n599(x)
+ end
+end
+
+def fun_l5_n550(x)
+ if (x < 1)
+ fun_l6_n710(x)
+ else
+ fun_l6_n104(x)
+ end
+end
+
+def fun_l5_n551(x)
+ if (x < 1)
+ fun_l6_n677(x)
+ else
+ fun_l6_n184(x)
+ end
+end
+
+def fun_l5_n552(x)
+ if (x < 1)
+ fun_l6_n700(x)
+ else
+ fun_l6_n299(x)
+ end
+end
+
+def fun_l5_n553(x)
+ if (x < 1)
+ fun_l6_n688(x)
+ else
+ fun_l6_n934(x)
+ end
+end
+
+def fun_l5_n554(x)
+ if (x < 1)
+ fun_l6_n771(x)
+ else
+ fun_l6_n989(x)
+ end
+end
+
+def fun_l5_n555(x)
+ if (x < 1)
+ fun_l6_n164(x)
+ else
+ fun_l6_n197(x)
+ end
+end
+
+def fun_l5_n556(x)
+ if (x < 1)
+ fun_l6_n901(x)
+ else
+ fun_l6_n235(x)
+ end
+end
+
+def fun_l5_n557(x)
+ if (x < 1)
+ fun_l6_n990(x)
+ else
+ fun_l6_n490(x)
+ end
+end
+
+def fun_l5_n558(x)
+ if (x < 1)
+ fun_l6_n476(x)
+ else
+ fun_l6_n612(x)
+ end
+end
+
+def fun_l5_n559(x)
+ if (x < 1)
+ fun_l6_n761(x)
+ else
+ fun_l6_n3(x)
+ end
+end
+
+def fun_l5_n560(x)
+ if (x < 1)
+ fun_l6_n461(x)
+ else
+ fun_l6_n832(x)
+ end
+end
+
+def fun_l5_n561(x)
+ if (x < 1)
+ fun_l6_n206(x)
+ else
+ fun_l6_n815(x)
+ end
+end
+
+def fun_l5_n562(x)
+ if (x < 1)
+ fun_l6_n180(x)
+ else
+ fun_l6_n640(x)
+ end
+end
+
+def fun_l5_n563(x)
+ if (x < 1)
+ fun_l6_n612(x)
+ else
+ fun_l6_n900(x)
+ end
+end
+
+def fun_l5_n564(x)
+ if (x < 1)
+ fun_l6_n31(x)
+ else
+ fun_l6_n290(x)
+ end
+end
+
+def fun_l5_n565(x)
+ if (x < 1)
+ fun_l6_n322(x)
+ else
+ fun_l6_n136(x)
+ end
+end
+
+def fun_l5_n566(x)
+ if (x < 1)
+ fun_l6_n657(x)
+ else
+ fun_l6_n649(x)
+ end
+end
+
+def fun_l5_n567(x)
+ if (x < 1)
+ fun_l6_n683(x)
+ else
+ fun_l6_n903(x)
+ end
+end
+
+def fun_l5_n568(x)
+ if (x < 1)
+ fun_l6_n391(x)
+ else
+ fun_l6_n117(x)
+ end
+end
+
+def fun_l5_n569(x)
+ if (x < 1)
+ fun_l6_n868(x)
+ else
+ fun_l6_n644(x)
+ end
+end
+
+def fun_l5_n570(x)
+ if (x < 1)
+ fun_l6_n493(x)
+ else
+ fun_l6_n638(x)
+ end
+end
+
+def fun_l5_n571(x)
+ if (x < 1)
+ fun_l6_n207(x)
+ else
+ fun_l6_n650(x)
+ end
+end
+
+def fun_l5_n572(x)
+ if (x < 1)
+ fun_l6_n575(x)
+ else
+ fun_l6_n421(x)
+ end
+end
+
+def fun_l5_n573(x)
+ if (x < 1)
+ fun_l6_n757(x)
+ else
+ fun_l6_n515(x)
+ end
+end
+
+def fun_l5_n574(x)
+ if (x < 1)
+ fun_l6_n619(x)
+ else
+ fun_l6_n39(x)
+ end
+end
+
+def fun_l5_n575(x)
+ if (x < 1)
+ fun_l6_n91(x)
+ else
+ fun_l6_n79(x)
+ end
+end
+
+def fun_l5_n576(x)
+ if (x < 1)
+ fun_l6_n492(x)
+ else
+ fun_l6_n938(x)
+ end
+end
+
+def fun_l5_n577(x)
+ if (x < 1)
+ fun_l6_n181(x)
+ else
+ fun_l6_n98(x)
+ end
+end
+
+def fun_l5_n578(x)
+ if (x < 1)
+ fun_l6_n823(x)
+ else
+ fun_l6_n528(x)
+ end
+end
+
+def fun_l5_n579(x)
+ if (x < 1)
+ fun_l6_n218(x)
+ else
+ fun_l6_n613(x)
+ end
+end
+
+def fun_l5_n580(x)
+ if (x < 1)
+ fun_l6_n81(x)
+ else
+ fun_l6_n318(x)
+ end
+end
+
+def fun_l5_n581(x)
+ if (x < 1)
+ fun_l6_n953(x)
+ else
+ fun_l6_n162(x)
+ end
+end
+
+def fun_l5_n582(x)
+ if (x < 1)
+ fun_l6_n225(x)
+ else
+ fun_l6_n441(x)
+ end
+end
+
+def fun_l5_n583(x)
+ if (x < 1)
+ fun_l6_n862(x)
+ else
+ fun_l6_n939(x)
+ end
+end
+
+def fun_l5_n584(x)
+ if (x < 1)
+ fun_l6_n401(x)
+ else
+ fun_l6_n149(x)
+ end
+end
+
+def fun_l5_n585(x)
+ if (x < 1)
+ fun_l6_n94(x)
+ else
+ fun_l6_n320(x)
+ end
+end
+
+def fun_l5_n586(x)
+ if (x < 1)
+ fun_l6_n609(x)
+ else
+ fun_l6_n524(x)
+ end
+end
+
+def fun_l5_n587(x)
+ if (x < 1)
+ fun_l6_n412(x)
+ else
+ fun_l6_n350(x)
+ end
+end
+
+def fun_l5_n588(x)
+ if (x < 1)
+ fun_l6_n874(x)
+ else
+ fun_l6_n217(x)
+ end
+end
+
+def fun_l5_n589(x)
+ if (x < 1)
+ fun_l6_n989(x)
+ else
+ fun_l6_n62(x)
+ end
+end
+
+def fun_l5_n590(x)
+ if (x < 1)
+ fun_l6_n91(x)
+ else
+ fun_l6_n360(x)
+ end
+end
+
+def fun_l5_n591(x)
+ if (x < 1)
+ fun_l6_n392(x)
+ else
+ fun_l6_n530(x)
+ end
+end
+
+def fun_l5_n592(x)
+ if (x < 1)
+ fun_l6_n635(x)
+ else
+ fun_l6_n268(x)
+ end
+end
+
+def fun_l5_n593(x)
+ if (x < 1)
+ fun_l6_n747(x)
+ else
+ fun_l6_n345(x)
+ end
+end
+
+def fun_l5_n594(x)
+ if (x < 1)
+ fun_l6_n450(x)
+ else
+ fun_l6_n165(x)
+ end
+end
+
+def fun_l5_n595(x)
+ if (x < 1)
+ fun_l6_n960(x)
+ else
+ fun_l6_n256(x)
+ end
+end
+
+def fun_l5_n596(x)
+ if (x < 1)
+ fun_l6_n724(x)
+ else
+ fun_l6_n506(x)
+ end
+end
+
+def fun_l5_n597(x)
+ if (x < 1)
+ fun_l6_n809(x)
+ else
+ fun_l6_n180(x)
+ end
+end
+
+def fun_l5_n598(x)
+ if (x < 1)
+ fun_l6_n799(x)
+ else
+ fun_l6_n59(x)
+ end
+end
+
+def fun_l5_n599(x)
+ if (x < 1)
+ fun_l6_n412(x)
+ else
+ fun_l6_n868(x)
+ end
+end
+
+def fun_l5_n600(x)
+ if (x < 1)
+ fun_l6_n459(x)
+ else
+ fun_l6_n537(x)
+ end
+end
+
+def fun_l5_n601(x)
+ if (x < 1)
+ fun_l6_n321(x)
+ else
+ fun_l6_n39(x)
+ end
+end
+
+def fun_l5_n602(x)
+ if (x < 1)
+ fun_l6_n561(x)
+ else
+ fun_l6_n413(x)
+ end
+end
+
+def fun_l5_n603(x)
+ if (x < 1)
+ fun_l6_n173(x)
+ else
+ fun_l6_n324(x)
+ end
+end
+
+def fun_l5_n604(x)
+ if (x < 1)
+ fun_l6_n583(x)
+ else
+ fun_l6_n763(x)
+ end
+end
+
+def fun_l5_n605(x)
+ if (x < 1)
+ fun_l6_n200(x)
+ else
+ fun_l6_n996(x)
+ end
+end
+
+def fun_l5_n606(x)
+ if (x < 1)
+ fun_l6_n465(x)
+ else
+ fun_l6_n777(x)
+ end
+end
+
+def fun_l5_n607(x)
+ if (x < 1)
+ fun_l6_n744(x)
+ else
+ fun_l6_n917(x)
+ end
+end
+
+def fun_l5_n608(x)
+ if (x < 1)
+ fun_l6_n825(x)
+ else
+ fun_l6_n751(x)
+ end
+end
+
+def fun_l5_n609(x)
+ if (x < 1)
+ fun_l6_n357(x)
+ else
+ fun_l6_n889(x)
+ end
+end
+
+def fun_l5_n610(x)
+ if (x < 1)
+ fun_l6_n534(x)
+ else
+ fun_l6_n628(x)
+ end
+end
+
+def fun_l5_n611(x)
+ if (x < 1)
+ fun_l6_n242(x)
+ else
+ fun_l6_n57(x)
+ end
+end
+
+def fun_l5_n612(x)
+ if (x < 1)
+ fun_l6_n426(x)
+ else
+ fun_l6_n295(x)
+ end
+end
+
+def fun_l5_n613(x)
+ if (x < 1)
+ fun_l6_n218(x)
+ else
+ fun_l6_n194(x)
+ end
+end
+
+def fun_l5_n614(x)
+ if (x < 1)
+ fun_l6_n618(x)
+ else
+ fun_l6_n757(x)
+ end
+end
+
+def fun_l5_n615(x)
+ if (x < 1)
+ fun_l6_n708(x)
+ else
+ fun_l6_n187(x)
+ end
+end
+
+def fun_l5_n616(x)
+ if (x < 1)
+ fun_l6_n824(x)
+ else
+ fun_l6_n384(x)
+ end
+end
+
+def fun_l5_n617(x)
+ if (x < 1)
+ fun_l6_n149(x)
+ else
+ fun_l6_n741(x)
+ end
+end
+
+def fun_l5_n618(x)
+ if (x < 1)
+ fun_l6_n889(x)
+ else
+ fun_l6_n768(x)
+ end
+end
+
+def fun_l5_n619(x)
+ if (x < 1)
+ fun_l6_n144(x)
+ else
+ fun_l6_n746(x)
+ end
+end
+
+def fun_l5_n620(x)
+ if (x < 1)
+ fun_l6_n338(x)
+ else
+ fun_l6_n757(x)
+ end
+end
+
+def fun_l5_n621(x)
+ if (x < 1)
+ fun_l6_n623(x)
+ else
+ fun_l6_n432(x)
+ end
+end
+
+def fun_l5_n622(x)
+ if (x < 1)
+ fun_l6_n139(x)
+ else
+ fun_l6_n162(x)
+ end
+end
+
+def fun_l5_n623(x)
+ if (x < 1)
+ fun_l6_n371(x)
+ else
+ fun_l6_n297(x)
+ end
+end
+
+def fun_l5_n624(x)
+ if (x < 1)
+ fun_l6_n166(x)
+ else
+ fun_l6_n172(x)
+ end
+end
+
+def fun_l5_n625(x)
+ if (x < 1)
+ fun_l6_n506(x)
+ else
+ fun_l6_n7(x)
+ end
+end
+
+def fun_l5_n626(x)
+ if (x < 1)
+ fun_l6_n334(x)
+ else
+ fun_l6_n631(x)
+ end
+end
+
+def fun_l5_n627(x)
+ if (x < 1)
+ fun_l6_n209(x)
+ else
+ fun_l6_n316(x)
+ end
+end
+
+def fun_l5_n628(x)
+ if (x < 1)
+ fun_l6_n461(x)
+ else
+ fun_l6_n34(x)
+ end
+end
+
+def fun_l5_n629(x)
+ if (x < 1)
+ fun_l6_n6(x)
+ else
+ fun_l6_n818(x)
+ end
+end
+
+def fun_l5_n630(x)
+ if (x < 1)
+ fun_l6_n265(x)
+ else
+ fun_l6_n111(x)
+ end
+end
+
+def fun_l5_n631(x)
+ if (x < 1)
+ fun_l6_n493(x)
+ else
+ fun_l6_n64(x)
+ end
+end
+
+def fun_l5_n632(x)
+ if (x < 1)
+ fun_l6_n513(x)
+ else
+ fun_l6_n890(x)
+ end
+end
+
+def fun_l5_n633(x)
+ if (x < 1)
+ fun_l6_n295(x)
+ else
+ fun_l6_n295(x)
+ end
+end
+
+def fun_l5_n634(x)
+ if (x < 1)
+ fun_l6_n158(x)
+ else
+ fun_l6_n971(x)
+ end
+end
+
+def fun_l5_n635(x)
+ if (x < 1)
+ fun_l6_n171(x)
+ else
+ fun_l6_n337(x)
+ end
+end
+
+def fun_l5_n636(x)
+ if (x < 1)
+ fun_l6_n943(x)
+ else
+ fun_l6_n502(x)
+ end
+end
+
+def fun_l5_n637(x)
+ if (x < 1)
+ fun_l6_n339(x)
+ else
+ fun_l6_n638(x)
+ end
+end
+
+def fun_l5_n638(x)
+ if (x < 1)
+ fun_l6_n155(x)
+ else
+ fun_l6_n393(x)
+ end
+end
+
+def fun_l5_n639(x)
+ if (x < 1)
+ fun_l6_n29(x)
+ else
+ fun_l6_n506(x)
+ end
+end
+
+def fun_l5_n640(x)
+ if (x < 1)
+ fun_l6_n677(x)
+ else
+ fun_l6_n606(x)
+ end
+end
+
+def fun_l5_n641(x)
+ if (x < 1)
+ fun_l6_n306(x)
+ else
+ fun_l6_n571(x)
+ end
+end
+
+def fun_l5_n642(x)
+ if (x < 1)
+ fun_l6_n490(x)
+ else
+ fun_l6_n281(x)
+ end
+end
+
+def fun_l5_n643(x)
+ if (x < 1)
+ fun_l6_n392(x)
+ else
+ fun_l6_n686(x)
+ end
+end
+
+def fun_l5_n644(x)
+ if (x < 1)
+ fun_l6_n257(x)
+ else
+ fun_l6_n358(x)
+ end
+end
+
+def fun_l5_n645(x)
+ if (x < 1)
+ fun_l6_n949(x)
+ else
+ fun_l6_n15(x)
+ end
+end
+
+def fun_l5_n646(x)
+ if (x < 1)
+ fun_l6_n866(x)
+ else
+ fun_l6_n657(x)
+ end
+end
+
+def fun_l5_n647(x)
+ if (x < 1)
+ fun_l6_n624(x)
+ else
+ fun_l6_n390(x)
+ end
+end
+
+def fun_l5_n648(x)
+ if (x < 1)
+ fun_l6_n394(x)
+ else
+ fun_l6_n951(x)
+ end
+end
+
+def fun_l5_n649(x)
+ if (x < 1)
+ fun_l6_n99(x)
+ else
+ fun_l6_n160(x)
+ end
+end
+
+def fun_l5_n650(x)
+ if (x < 1)
+ fun_l6_n84(x)
+ else
+ fun_l6_n111(x)
+ end
+end
+
+def fun_l5_n651(x)
+ if (x < 1)
+ fun_l6_n635(x)
+ else
+ fun_l6_n507(x)
+ end
+end
+
+def fun_l5_n652(x)
+ if (x < 1)
+ fun_l6_n674(x)
+ else
+ fun_l6_n501(x)
+ end
+end
+
+def fun_l5_n653(x)
+ if (x < 1)
+ fun_l6_n171(x)
+ else
+ fun_l6_n645(x)
+ end
+end
+
+def fun_l5_n654(x)
+ if (x < 1)
+ fun_l6_n327(x)
+ else
+ fun_l6_n152(x)
+ end
+end
+
+def fun_l5_n655(x)
+ if (x < 1)
+ fun_l6_n210(x)
+ else
+ fun_l6_n441(x)
+ end
+end
+
+def fun_l5_n656(x)
+ if (x < 1)
+ fun_l6_n691(x)
+ else
+ fun_l6_n813(x)
+ end
+end
+
+def fun_l5_n657(x)
+ if (x < 1)
+ fun_l6_n671(x)
+ else
+ fun_l6_n683(x)
+ end
+end
+
+def fun_l5_n658(x)
+ if (x < 1)
+ fun_l6_n939(x)
+ else
+ fun_l6_n580(x)
+ end
+end
+
+def fun_l5_n659(x)
+ if (x < 1)
+ fun_l6_n152(x)
+ else
+ fun_l6_n159(x)
+ end
+end
+
+def fun_l5_n660(x)
+ if (x < 1)
+ fun_l6_n50(x)
+ else
+ fun_l6_n911(x)
+ end
+end
+
+def fun_l5_n661(x)
+ if (x < 1)
+ fun_l6_n700(x)
+ else
+ fun_l6_n972(x)
+ end
+end
+
+def fun_l5_n662(x)
+ if (x < 1)
+ fun_l6_n22(x)
+ else
+ fun_l6_n82(x)
+ end
+end
+
+def fun_l5_n663(x)
+ if (x < 1)
+ fun_l6_n51(x)
+ else
+ fun_l6_n827(x)
+ end
+end
+
+def fun_l5_n664(x)
+ if (x < 1)
+ fun_l6_n997(x)
+ else
+ fun_l6_n289(x)
+ end
+end
+
+def fun_l5_n665(x)
+ if (x < 1)
+ fun_l6_n666(x)
+ else
+ fun_l6_n775(x)
+ end
+end
+
+def fun_l5_n666(x)
+ if (x < 1)
+ fun_l6_n373(x)
+ else
+ fun_l6_n175(x)
+ end
+end
+
+def fun_l5_n667(x)
+ if (x < 1)
+ fun_l6_n551(x)
+ else
+ fun_l6_n772(x)
+ end
+end
+
+def fun_l5_n668(x)
+ if (x < 1)
+ fun_l6_n107(x)
+ else
+ fun_l6_n197(x)
+ end
+end
+
+def fun_l5_n669(x)
+ if (x < 1)
+ fun_l6_n244(x)
+ else
+ fun_l6_n968(x)
+ end
+end
+
+def fun_l5_n670(x)
+ if (x < 1)
+ fun_l6_n798(x)
+ else
+ fun_l6_n30(x)
+ end
+end
+
+def fun_l5_n671(x)
+ if (x < 1)
+ fun_l6_n48(x)
+ else
+ fun_l6_n186(x)
+ end
+end
+
+def fun_l5_n672(x)
+ if (x < 1)
+ fun_l6_n373(x)
+ else
+ fun_l6_n937(x)
+ end
+end
+
+def fun_l5_n673(x)
+ if (x < 1)
+ fun_l6_n759(x)
+ else
+ fun_l6_n92(x)
+ end
+end
+
+def fun_l5_n674(x)
+ if (x < 1)
+ fun_l6_n380(x)
+ else
+ fun_l6_n772(x)
+ end
+end
+
+def fun_l5_n675(x)
+ if (x < 1)
+ fun_l6_n916(x)
+ else
+ fun_l6_n329(x)
+ end
+end
+
+def fun_l5_n676(x)
+ if (x < 1)
+ fun_l6_n110(x)
+ else
+ fun_l6_n951(x)
+ end
+end
+
+def fun_l5_n677(x)
+ if (x < 1)
+ fun_l6_n363(x)
+ else
+ fun_l6_n35(x)
+ end
+end
+
+def fun_l5_n678(x)
+ if (x < 1)
+ fun_l6_n484(x)
+ else
+ fun_l6_n492(x)
+ end
+end
+
+def fun_l5_n679(x)
+ if (x < 1)
+ fun_l6_n801(x)
+ else
+ fun_l6_n279(x)
+ end
+end
+
+def fun_l5_n680(x)
+ if (x < 1)
+ fun_l6_n499(x)
+ else
+ fun_l6_n561(x)
+ end
+end
+
+def fun_l5_n681(x)
+ if (x < 1)
+ fun_l6_n800(x)
+ else
+ fun_l6_n890(x)
+ end
+end
+
+def fun_l5_n682(x)
+ if (x < 1)
+ fun_l6_n191(x)
+ else
+ fun_l6_n686(x)
+ end
+end
+
+def fun_l5_n683(x)
+ if (x < 1)
+ fun_l6_n318(x)
+ else
+ fun_l6_n683(x)
+ end
+end
+
+def fun_l5_n684(x)
+ if (x < 1)
+ fun_l6_n500(x)
+ else
+ fun_l6_n914(x)
+ end
+end
+
+def fun_l5_n685(x)
+ if (x < 1)
+ fun_l6_n24(x)
+ else
+ fun_l6_n945(x)
+ end
+end
+
+def fun_l5_n686(x)
+ if (x < 1)
+ fun_l6_n602(x)
+ else
+ fun_l6_n291(x)
+ end
+end
+
+def fun_l5_n687(x)
+ if (x < 1)
+ fun_l6_n999(x)
+ else
+ fun_l6_n86(x)
+ end
+end
+
+def fun_l5_n688(x)
+ if (x < 1)
+ fun_l6_n106(x)
+ else
+ fun_l6_n754(x)
+ end
+end
+
+def fun_l5_n689(x)
+ if (x < 1)
+ fun_l6_n452(x)
+ else
+ fun_l6_n229(x)
+ end
+end
+
+def fun_l5_n690(x)
+ if (x < 1)
+ fun_l6_n672(x)
+ else
+ fun_l6_n587(x)
+ end
+end
+
+def fun_l5_n691(x)
+ if (x < 1)
+ fun_l6_n532(x)
+ else
+ fun_l6_n56(x)
+ end
+end
+
+def fun_l5_n692(x)
+ if (x < 1)
+ fun_l6_n606(x)
+ else
+ fun_l6_n552(x)
+ end
+end
+
+def fun_l5_n693(x)
+ if (x < 1)
+ fun_l6_n742(x)
+ else
+ fun_l6_n862(x)
+ end
+end
+
+def fun_l5_n694(x)
+ if (x < 1)
+ fun_l6_n964(x)
+ else
+ fun_l6_n475(x)
+ end
+end
+
+def fun_l5_n695(x)
+ if (x < 1)
+ fun_l6_n179(x)
+ else
+ fun_l6_n947(x)
+ end
+end
+
+def fun_l5_n696(x)
+ if (x < 1)
+ fun_l6_n563(x)
+ else
+ fun_l6_n329(x)
+ end
+end
+
+def fun_l5_n697(x)
+ if (x < 1)
+ fun_l6_n786(x)
+ else
+ fun_l6_n502(x)
+ end
+end
+
+def fun_l5_n698(x)
+ if (x < 1)
+ fun_l6_n178(x)
+ else
+ fun_l6_n757(x)
+ end
+end
+
+def fun_l5_n699(x)
+ if (x < 1)
+ fun_l6_n248(x)
+ else
+ fun_l6_n288(x)
+ end
+end
+
+def fun_l5_n700(x)
+ if (x < 1)
+ fun_l6_n262(x)
+ else
+ fun_l6_n650(x)
+ end
+end
+
+def fun_l5_n701(x)
+ if (x < 1)
+ fun_l6_n90(x)
+ else
+ fun_l6_n964(x)
+ end
+end
+
+def fun_l5_n702(x)
+ if (x < 1)
+ fun_l6_n864(x)
+ else
+ fun_l6_n743(x)
+ end
+end
+
+def fun_l5_n703(x)
+ if (x < 1)
+ fun_l6_n816(x)
+ else
+ fun_l6_n364(x)
+ end
+end
+
+def fun_l5_n704(x)
+ if (x < 1)
+ fun_l6_n590(x)
+ else
+ fun_l6_n434(x)
+ end
+end
+
+def fun_l5_n705(x)
+ if (x < 1)
+ fun_l6_n875(x)
+ else
+ fun_l6_n539(x)
+ end
+end
+
+def fun_l5_n706(x)
+ if (x < 1)
+ fun_l6_n964(x)
+ else
+ fun_l6_n564(x)
+ end
+end
+
+def fun_l5_n707(x)
+ if (x < 1)
+ fun_l6_n315(x)
+ else
+ fun_l6_n460(x)
+ end
+end
+
+def fun_l5_n708(x)
+ if (x < 1)
+ fun_l6_n139(x)
+ else
+ fun_l6_n210(x)
+ end
+end
+
+def fun_l5_n709(x)
+ if (x < 1)
+ fun_l6_n593(x)
+ else
+ fun_l6_n933(x)
+ end
+end
+
+def fun_l5_n710(x)
+ if (x < 1)
+ fun_l6_n37(x)
+ else
+ fun_l6_n459(x)
+ end
+end
+
+def fun_l5_n711(x)
+ if (x < 1)
+ fun_l6_n768(x)
+ else
+ fun_l6_n256(x)
+ end
+end
+
+def fun_l5_n712(x)
+ if (x < 1)
+ fun_l6_n506(x)
+ else
+ fun_l6_n936(x)
+ end
+end
+
+def fun_l5_n713(x)
+ if (x < 1)
+ fun_l6_n971(x)
+ else
+ fun_l6_n575(x)
+ end
+end
+
+def fun_l5_n714(x)
+ if (x < 1)
+ fun_l6_n498(x)
+ else
+ fun_l6_n932(x)
+ end
+end
+
+def fun_l5_n715(x)
+ if (x < 1)
+ fun_l6_n362(x)
+ else
+ fun_l6_n949(x)
+ end
+end
+
+def fun_l5_n716(x)
+ if (x < 1)
+ fun_l6_n706(x)
+ else
+ fun_l6_n788(x)
+ end
+end
+
+def fun_l5_n717(x)
+ if (x < 1)
+ fun_l6_n405(x)
+ else
+ fun_l6_n803(x)
+ end
+end
+
+def fun_l5_n718(x)
+ if (x < 1)
+ fun_l6_n166(x)
+ else
+ fun_l6_n917(x)
+ end
+end
+
+def fun_l5_n719(x)
+ if (x < 1)
+ fun_l6_n899(x)
+ else
+ fun_l6_n836(x)
+ end
+end
+
+def fun_l5_n720(x)
+ if (x < 1)
+ fun_l6_n805(x)
+ else
+ fun_l6_n159(x)
+ end
+end
+
+def fun_l5_n721(x)
+ if (x < 1)
+ fun_l6_n960(x)
+ else
+ fun_l6_n113(x)
+ end
+end
+
+def fun_l5_n722(x)
+ if (x < 1)
+ fun_l6_n807(x)
+ else
+ fun_l6_n533(x)
+ end
+end
+
+def fun_l5_n723(x)
+ if (x < 1)
+ fun_l6_n480(x)
+ else
+ fun_l6_n907(x)
+ end
+end
+
+def fun_l5_n724(x)
+ if (x < 1)
+ fun_l6_n951(x)
+ else
+ fun_l6_n793(x)
+ end
+end
+
+def fun_l5_n725(x)
+ if (x < 1)
+ fun_l6_n951(x)
+ else
+ fun_l6_n771(x)
+ end
+end
+
+def fun_l5_n726(x)
+ if (x < 1)
+ fun_l6_n435(x)
+ else
+ fun_l6_n336(x)
+ end
+end
+
+def fun_l5_n727(x)
+ if (x < 1)
+ fun_l6_n222(x)
+ else
+ fun_l6_n393(x)
+ end
+end
+
+def fun_l5_n728(x)
+ if (x < 1)
+ fun_l6_n988(x)
+ else
+ fun_l6_n402(x)
+ end
+end
+
+def fun_l5_n729(x)
+ if (x < 1)
+ fun_l6_n9(x)
+ else
+ fun_l6_n46(x)
+ end
+end
+
+def fun_l5_n730(x)
+ if (x < 1)
+ fun_l6_n722(x)
+ else
+ fun_l6_n112(x)
+ end
+end
+
+def fun_l5_n731(x)
+ if (x < 1)
+ fun_l6_n543(x)
+ else
+ fun_l6_n813(x)
+ end
+end
+
+def fun_l5_n732(x)
+ if (x < 1)
+ fun_l6_n337(x)
+ else
+ fun_l6_n245(x)
+ end
+end
+
+def fun_l5_n733(x)
+ if (x < 1)
+ fun_l6_n84(x)
+ else
+ fun_l6_n335(x)
+ end
+end
+
+def fun_l5_n734(x)
+ if (x < 1)
+ fun_l6_n697(x)
+ else
+ fun_l6_n498(x)
+ end
+end
+
+def fun_l5_n735(x)
+ if (x < 1)
+ fun_l6_n2(x)
+ else
+ fun_l6_n895(x)
+ end
+end
+
+def fun_l5_n736(x)
+ if (x < 1)
+ fun_l6_n619(x)
+ else
+ fun_l6_n163(x)
+ end
+end
+
+def fun_l5_n737(x)
+ if (x < 1)
+ fun_l6_n237(x)
+ else
+ fun_l6_n6(x)
+ end
+end
+
+def fun_l5_n738(x)
+ if (x < 1)
+ fun_l6_n259(x)
+ else
+ fun_l6_n95(x)
+ end
+end
+
+def fun_l5_n739(x)
+ if (x < 1)
+ fun_l6_n98(x)
+ else
+ fun_l6_n331(x)
+ end
+end
+
+def fun_l5_n740(x)
+ if (x < 1)
+ fun_l6_n489(x)
+ else
+ fun_l6_n305(x)
+ end
+end
+
+def fun_l5_n741(x)
+ if (x < 1)
+ fun_l6_n493(x)
+ else
+ fun_l6_n525(x)
+ end
+end
+
+def fun_l5_n742(x)
+ if (x < 1)
+ fun_l6_n269(x)
+ else
+ fun_l6_n742(x)
+ end
+end
+
+def fun_l5_n743(x)
+ if (x < 1)
+ fun_l6_n194(x)
+ else
+ fun_l6_n254(x)
+ end
+end
+
+def fun_l5_n744(x)
+ if (x < 1)
+ fun_l6_n247(x)
+ else
+ fun_l6_n909(x)
+ end
+end
+
+def fun_l5_n745(x)
+ if (x < 1)
+ fun_l6_n388(x)
+ else
+ fun_l6_n657(x)
+ end
+end
+
+def fun_l5_n746(x)
+ if (x < 1)
+ fun_l6_n27(x)
+ else
+ fun_l6_n286(x)
+ end
+end
+
+def fun_l5_n747(x)
+ if (x < 1)
+ fun_l6_n659(x)
+ else
+ fun_l6_n895(x)
+ end
+end
+
+def fun_l5_n748(x)
+ if (x < 1)
+ fun_l6_n538(x)
+ else
+ fun_l6_n667(x)
+ end
+end
+
+def fun_l5_n749(x)
+ if (x < 1)
+ fun_l6_n208(x)
+ else
+ fun_l6_n493(x)
+ end
+end
+
+def fun_l5_n750(x)
+ if (x < 1)
+ fun_l6_n326(x)
+ else
+ fun_l6_n570(x)
+ end
+end
+
+def fun_l5_n751(x)
+ if (x < 1)
+ fun_l6_n437(x)
+ else
+ fun_l6_n716(x)
+ end
+end
+
+def fun_l5_n752(x)
+ if (x < 1)
+ fun_l6_n957(x)
+ else
+ fun_l6_n231(x)
+ end
+end
+
+def fun_l5_n753(x)
+ if (x < 1)
+ fun_l6_n846(x)
+ else
+ fun_l6_n900(x)
+ end
+end
+
+def fun_l5_n754(x)
+ if (x < 1)
+ fun_l6_n81(x)
+ else
+ fun_l6_n464(x)
+ end
+end
+
+def fun_l5_n755(x)
+ if (x < 1)
+ fun_l6_n735(x)
+ else
+ fun_l6_n232(x)
+ end
+end
+
+def fun_l5_n756(x)
+ if (x < 1)
+ fun_l6_n577(x)
+ else
+ fun_l6_n804(x)
+ end
+end
+
+def fun_l5_n757(x)
+ if (x < 1)
+ fun_l6_n363(x)
+ else
+ fun_l6_n155(x)
+ end
+end
+
+def fun_l5_n758(x)
+ if (x < 1)
+ fun_l6_n534(x)
+ else
+ fun_l6_n827(x)
+ end
+end
+
+def fun_l5_n759(x)
+ if (x < 1)
+ fun_l6_n711(x)
+ else
+ fun_l6_n53(x)
+ end
+end
+
+def fun_l5_n760(x)
+ if (x < 1)
+ fun_l6_n80(x)
+ else
+ fun_l6_n734(x)
+ end
+end
+
+def fun_l5_n761(x)
+ if (x < 1)
+ fun_l6_n811(x)
+ else
+ fun_l6_n691(x)
+ end
+end
+
+def fun_l5_n762(x)
+ if (x < 1)
+ fun_l6_n847(x)
+ else
+ fun_l6_n570(x)
+ end
+end
+
+def fun_l5_n763(x)
+ if (x < 1)
+ fun_l6_n30(x)
+ else
+ fun_l6_n283(x)
+ end
+end
+
+def fun_l5_n764(x)
+ if (x < 1)
+ fun_l6_n270(x)
+ else
+ fun_l6_n965(x)
+ end
+end
+
+def fun_l5_n765(x)
+ if (x < 1)
+ fun_l6_n936(x)
+ else
+ fun_l6_n772(x)
+ end
+end
+
+def fun_l5_n766(x)
+ if (x < 1)
+ fun_l6_n181(x)
+ else
+ fun_l6_n682(x)
+ end
+end
+
+def fun_l5_n767(x)
+ if (x < 1)
+ fun_l6_n327(x)
+ else
+ fun_l6_n5(x)
+ end
+end
+
+def fun_l5_n768(x)
+ if (x < 1)
+ fun_l6_n296(x)
+ else
+ fun_l6_n940(x)
+ end
+end
+
+def fun_l5_n769(x)
+ if (x < 1)
+ fun_l6_n543(x)
+ else
+ fun_l6_n871(x)
+ end
+end
+
+def fun_l5_n770(x)
+ if (x < 1)
+ fun_l6_n670(x)
+ else
+ fun_l6_n128(x)
+ end
+end
+
+def fun_l5_n771(x)
+ if (x < 1)
+ fun_l6_n184(x)
+ else
+ fun_l6_n794(x)
+ end
+end
+
+def fun_l5_n772(x)
+ if (x < 1)
+ fun_l6_n571(x)
+ else
+ fun_l6_n337(x)
+ end
+end
+
+def fun_l5_n773(x)
+ if (x < 1)
+ fun_l6_n674(x)
+ else
+ fun_l6_n712(x)
+ end
+end
+
+def fun_l5_n774(x)
+ if (x < 1)
+ fun_l6_n572(x)
+ else
+ fun_l6_n944(x)
+ end
+end
+
+def fun_l5_n775(x)
+ if (x < 1)
+ fun_l6_n122(x)
+ else
+ fun_l6_n897(x)
+ end
+end
+
+def fun_l5_n776(x)
+ if (x < 1)
+ fun_l6_n461(x)
+ else
+ fun_l6_n202(x)
+ end
+end
+
+def fun_l5_n777(x)
+ if (x < 1)
+ fun_l6_n99(x)
+ else
+ fun_l6_n256(x)
+ end
+end
+
+def fun_l5_n778(x)
+ if (x < 1)
+ fun_l6_n547(x)
+ else
+ fun_l6_n138(x)
+ end
+end
+
+def fun_l5_n779(x)
+ if (x < 1)
+ fun_l6_n56(x)
+ else
+ fun_l6_n682(x)
+ end
+end
+
+def fun_l5_n780(x)
+ if (x < 1)
+ fun_l6_n10(x)
+ else
+ fun_l6_n238(x)
+ end
+end
+
+def fun_l5_n781(x)
+ if (x < 1)
+ fun_l6_n577(x)
+ else
+ fun_l6_n590(x)
+ end
+end
+
+def fun_l5_n782(x)
+ if (x < 1)
+ fun_l6_n415(x)
+ else
+ fun_l6_n522(x)
+ end
+end
+
+def fun_l5_n783(x)
+ if (x < 1)
+ fun_l6_n255(x)
+ else
+ fun_l6_n182(x)
+ end
+end
+
+def fun_l5_n784(x)
+ if (x < 1)
+ fun_l6_n755(x)
+ else
+ fun_l6_n644(x)
+ end
+end
+
+def fun_l5_n785(x)
+ if (x < 1)
+ fun_l6_n39(x)
+ else
+ fun_l6_n296(x)
+ end
+end
+
+def fun_l5_n786(x)
+ if (x < 1)
+ fun_l6_n17(x)
+ else
+ fun_l6_n811(x)
+ end
+end
+
+def fun_l5_n787(x)
+ if (x < 1)
+ fun_l6_n814(x)
+ else
+ fun_l6_n989(x)
+ end
+end
+
+def fun_l5_n788(x)
+ if (x < 1)
+ fun_l6_n791(x)
+ else
+ fun_l6_n688(x)
+ end
+end
+
+def fun_l5_n789(x)
+ if (x < 1)
+ fun_l6_n415(x)
+ else
+ fun_l6_n218(x)
+ end
+end
+
+def fun_l5_n790(x)
+ if (x < 1)
+ fun_l6_n227(x)
+ else
+ fun_l6_n391(x)
+ end
+end
+
+def fun_l5_n791(x)
+ if (x < 1)
+ fun_l6_n232(x)
+ else
+ fun_l6_n644(x)
+ end
+end
+
+def fun_l5_n792(x)
+ if (x < 1)
+ fun_l6_n325(x)
+ else
+ fun_l6_n740(x)
+ end
+end
+
+def fun_l5_n793(x)
+ if (x < 1)
+ fun_l6_n926(x)
+ else
+ fun_l6_n133(x)
+ end
+end
+
+def fun_l5_n794(x)
+ if (x < 1)
+ fun_l6_n114(x)
+ else
+ fun_l6_n76(x)
+ end
+end
+
+def fun_l5_n795(x)
+ if (x < 1)
+ fun_l6_n332(x)
+ else
+ fun_l6_n198(x)
+ end
+end
+
+def fun_l5_n796(x)
+ if (x < 1)
+ fun_l6_n584(x)
+ else
+ fun_l6_n298(x)
+ end
+end
+
+def fun_l5_n797(x)
+ if (x < 1)
+ fun_l6_n966(x)
+ else
+ fun_l6_n956(x)
+ end
+end
+
+def fun_l5_n798(x)
+ if (x < 1)
+ fun_l6_n604(x)
+ else
+ fun_l6_n311(x)
+ end
+end
+
+def fun_l5_n799(x)
+ if (x < 1)
+ fun_l6_n444(x)
+ else
+ fun_l6_n934(x)
+ end
+end
+
+def fun_l5_n800(x)
+ if (x < 1)
+ fun_l6_n805(x)
+ else
+ fun_l6_n83(x)
+ end
+end
+
+def fun_l5_n801(x)
+ if (x < 1)
+ fun_l6_n996(x)
+ else
+ fun_l6_n282(x)
+ end
+end
+
+def fun_l5_n802(x)
+ if (x < 1)
+ fun_l6_n759(x)
+ else
+ fun_l6_n681(x)
+ end
+end
+
+def fun_l5_n803(x)
+ if (x < 1)
+ fun_l6_n480(x)
+ else
+ fun_l6_n536(x)
+ end
+end
+
+def fun_l5_n804(x)
+ if (x < 1)
+ fun_l6_n536(x)
+ else
+ fun_l6_n64(x)
+ end
+end
+
+def fun_l5_n805(x)
+ if (x < 1)
+ fun_l6_n992(x)
+ else
+ fun_l6_n116(x)
+ end
+end
+
+def fun_l5_n806(x)
+ if (x < 1)
+ fun_l6_n446(x)
+ else
+ fun_l6_n553(x)
+ end
+end
+
+def fun_l5_n807(x)
+ if (x < 1)
+ fun_l6_n822(x)
+ else
+ fun_l6_n80(x)
+ end
+end
+
+def fun_l5_n808(x)
+ if (x < 1)
+ fun_l6_n912(x)
+ else
+ fun_l6_n525(x)
+ end
+end
+
+def fun_l5_n809(x)
+ if (x < 1)
+ fun_l6_n824(x)
+ else
+ fun_l6_n356(x)
+ end
+end
+
+def fun_l5_n810(x)
+ if (x < 1)
+ fun_l6_n144(x)
+ else
+ fun_l6_n193(x)
+ end
+end
+
+def fun_l5_n811(x)
+ if (x < 1)
+ fun_l6_n27(x)
+ else
+ fun_l6_n810(x)
+ end
+end
+
+def fun_l5_n812(x)
+ if (x < 1)
+ fun_l6_n244(x)
+ else
+ fun_l6_n696(x)
+ end
+end
+
+def fun_l5_n813(x)
+ if (x < 1)
+ fun_l6_n408(x)
+ else
+ fun_l6_n46(x)
+ end
+end
+
+def fun_l5_n814(x)
+ if (x < 1)
+ fun_l6_n496(x)
+ else
+ fun_l6_n149(x)
+ end
+end
+
+def fun_l5_n815(x)
+ if (x < 1)
+ fun_l6_n100(x)
+ else
+ fun_l6_n765(x)
+ end
+end
+
+def fun_l5_n816(x)
+ if (x < 1)
+ fun_l6_n731(x)
+ else
+ fun_l6_n953(x)
+ end
+end
+
+def fun_l5_n817(x)
+ if (x < 1)
+ fun_l6_n997(x)
+ else
+ fun_l6_n849(x)
+ end
+end
+
+def fun_l5_n818(x)
+ if (x < 1)
+ fun_l6_n570(x)
+ else
+ fun_l6_n918(x)
+ end
+end
+
+def fun_l5_n819(x)
+ if (x < 1)
+ fun_l6_n473(x)
+ else
+ fun_l6_n955(x)
+ end
+end
+
+def fun_l5_n820(x)
+ if (x < 1)
+ fun_l6_n691(x)
+ else
+ fun_l6_n271(x)
+ end
+end
+
+def fun_l5_n821(x)
+ if (x < 1)
+ fun_l6_n935(x)
+ else
+ fun_l6_n386(x)
+ end
+end
+
+def fun_l5_n822(x)
+ if (x < 1)
+ fun_l6_n210(x)
+ else
+ fun_l6_n871(x)
+ end
+end
+
+def fun_l5_n823(x)
+ if (x < 1)
+ fun_l6_n907(x)
+ else
+ fun_l6_n596(x)
+ end
+end
+
+def fun_l5_n824(x)
+ if (x < 1)
+ fun_l6_n701(x)
+ else
+ fun_l6_n541(x)
+ end
+end
+
+def fun_l5_n825(x)
+ if (x < 1)
+ fun_l6_n477(x)
+ else
+ fun_l6_n207(x)
+ end
+end
+
+def fun_l5_n826(x)
+ if (x < 1)
+ fun_l6_n95(x)
+ else
+ fun_l6_n26(x)
+ end
+end
+
+def fun_l5_n827(x)
+ if (x < 1)
+ fun_l6_n908(x)
+ else
+ fun_l6_n369(x)
+ end
+end
+
+def fun_l5_n828(x)
+ if (x < 1)
+ fun_l6_n213(x)
+ else
+ fun_l6_n607(x)
+ end
+end
+
+def fun_l5_n829(x)
+ if (x < 1)
+ fun_l6_n763(x)
+ else
+ fun_l6_n753(x)
+ end
+end
+
+def fun_l5_n830(x)
+ if (x < 1)
+ fun_l6_n24(x)
+ else
+ fun_l6_n157(x)
+ end
+end
+
+def fun_l5_n831(x)
+ if (x < 1)
+ fun_l6_n262(x)
+ else
+ fun_l6_n826(x)
+ end
+end
+
+def fun_l5_n832(x)
+ if (x < 1)
+ fun_l6_n743(x)
+ else
+ fun_l6_n37(x)
+ end
+end
+
+def fun_l5_n833(x)
+ if (x < 1)
+ fun_l6_n532(x)
+ else
+ fun_l6_n31(x)
+ end
+end
+
+def fun_l5_n834(x)
+ if (x < 1)
+ fun_l6_n309(x)
+ else
+ fun_l6_n454(x)
+ end
+end
+
+def fun_l5_n835(x)
+ if (x < 1)
+ fun_l6_n917(x)
+ else
+ fun_l6_n721(x)
+ end
+end
+
+def fun_l5_n836(x)
+ if (x < 1)
+ fun_l6_n376(x)
+ else
+ fun_l6_n758(x)
+ end
+end
+
+def fun_l5_n837(x)
+ if (x < 1)
+ fun_l6_n558(x)
+ else
+ fun_l6_n474(x)
+ end
+end
+
+def fun_l5_n838(x)
+ if (x < 1)
+ fun_l6_n436(x)
+ else
+ fun_l6_n675(x)
+ end
+end
+
+def fun_l5_n839(x)
+ if (x < 1)
+ fun_l6_n720(x)
+ else
+ fun_l6_n12(x)
+ end
+end
+
+def fun_l5_n840(x)
+ if (x < 1)
+ fun_l6_n957(x)
+ else
+ fun_l6_n200(x)
+ end
+end
+
+def fun_l5_n841(x)
+ if (x < 1)
+ fun_l6_n180(x)
+ else
+ fun_l6_n644(x)
+ end
+end
+
+def fun_l5_n842(x)
+ if (x < 1)
+ fun_l6_n510(x)
+ else
+ fun_l6_n73(x)
+ end
+end
+
+def fun_l5_n843(x)
+ if (x < 1)
+ fun_l6_n812(x)
+ else
+ fun_l6_n954(x)
+ end
+end
+
+def fun_l5_n844(x)
+ if (x < 1)
+ fun_l6_n566(x)
+ else
+ fun_l6_n866(x)
+ end
+end
+
+def fun_l5_n845(x)
+ if (x < 1)
+ fun_l6_n641(x)
+ else
+ fun_l6_n11(x)
+ end
+end
+
+def fun_l5_n846(x)
+ if (x < 1)
+ fun_l6_n607(x)
+ else
+ fun_l6_n884(x)
+ end
+end
+
+def fun_l5_n847(x)
+ if (x < 1)
+ fun_l6_n479(x)
+ else
+ fun_l6_n564(x)
+ end
+end
+
+def fun_l5_n848(x)
+ if (x < 1)
+ fun_l6_n365(x)
+ else
+ fun_l6_n285(x)
+ end
+end
+
+def fun_l5_n849(x)
+ if (x < 1)
+ fun_l6_n296(x)
+ else
+ fun_l6_n708(x)
+ end
+end
+
+def fun_l5_n850(x)
+ if (x < 1)
+ fun_l6_n429(x)
+ else
+ fun_l6_n758(x)
+ end
+end
+
+def fun_l5_n851(x)
+ if (x < 1)
+ fun_l6_n881(x)
+ else
+ fun_l6_n848(x)
+ end
+end
+
+def fun_l5_n852(x)
+ if (x < 1)
+ fun_l6_n257(x)
+ else
+ fun_l6_n51(x)
+ end
+end
+
+def fun_l5_n853(x)
+ if (x < 1)
+ fun_l6_n441(x)
+ else
+ fun_l6_n445(x)
+ end
+end
+
+def fun_l5_n854(x)
+ if (x < 1)
+ fun_l6_n80(x)
+ else
+ fun_l6_n767(x)
+ end
+end
+
+def fun_l5_n855(x)
+ if (x < 1)
+ fun_l6_n196(x)
+ else
+ fun_l6_n41(x)
+ end
+end
+
+def fun_l5_n856(x)
+ if (x < 1)
+ fun_l6_n548(x)
+ else
+ fun_l6_n860(x)
+ end
+end
+
+def fun_l5_n857(x)
+ if (x < 1)
+ fun_l6_n380(x)
+ else
+ fun_l6_n601(x)
+ end
+end
+
+def fun_l5_n858(x)
+ if (x < 1)
+ fun_l6_n272(x)
+ else
+ fun_l6_n376(x)
+ end
+end
+
+def fun_l5_n859(x)
+ if (x < 1)
+ fun_l6_n179(x)
+ else
+ fun_l6_n978(x)
+ end
+end
+
+def fun_l5_n860(x)
+ if (x < 1)
+ fun_l6_n52(x)
+ else
+ fun_l6_n827(x)
+ end
+end
+
+def fun_l5_n861(x)
+ if (x < 1)
+ fun_l6_n611(x)
+ else
+ fun_l6_n929(x)
+ end
+end
+
+def fun_l5_n862(x)
+ if (x < 1)
+ fun_l6_n179(x)
+ else
+ fun_l6_n171(x)
+ end
+end
+
+def fun_l5_n863(x)
+ if (x < 1)
+ fun_l6_n611(x)
+ else
+ fun_l6_n663(x)
+ end
+end
+
+def fun_l5_n864(x)
+ if (x < 1)
+ fun_l6_n539(x)
+ else
+ fun_l6_n356(x)
+ end
+end
+
+def fun_l5_n865(x)
+ if (x < 1)
+ fun_l6_n401(x)
+ else
+ fun_l6_n302(x)
+ end
+end
+
+def fun_l5_n866(x)
+ if (x < 1)
+ fun_l6_n94(x)
+ else
+ fun_l6_n761(x)
+ end
+end
+
+def fun_l5_n867(x)
+ if (x < 1)
+ fun_l6_n818(x)
+ else
+ fun_l6_n500(x)
+ end
+end
+
+def fun_l5_n868(x)
+ if (x < 1)
+ fun_l6_n956(x)
+ else
+ fun_l6_n661(x)
+ end
+end
+
+def fun_l5_n869(x)
+ if (x < 1)
+ fun_l6_n628(x)
+ else
+ fun_l6_n765(x)
+ end
+end
+
+def fun_l5_n870(x)
+ if (x < 1)
+ fun_l6_n654(x)
+ else
+ fun_l6_n181(x)
+ end
+end
+
+def fun_l5_n871(x)
+ if (x < 1)
+ fun_l6_n70(x)
+ else
+ fun_l6_n157(x)
+ end
+end
+
+def fun_l5_n872(x)
+ if (x < 1)
+ fun_l6_n133(x)
+ else
+ fun_l6_n806(x)
+ end
+end
+
+def fun_l5_n873(x)
+ if (x < 1)
+ fun_l6_n100(x)
+ else
+ fun_l6_n479(x)
+ end
+end
+
+def fun_l5_n874(x)
+ if (x < 1)
+ fun_l6_n401(x)
+ else
+ fun_l6_n567(x)
+ end
+end
+
+def fun_l5_n875(x)
+ if (x < 1)
+ fun_l6_n399(x)
+ else
+ fun_l6_n369(x)
+ end
+end
+
+def fun_l5_n876(x)
+ if (x < 1)
+ fun_l6_n412(x)
+ else
+ fun_l6_n763(x)
+ end
+end
+
+def fun_l5_n877(x)
+ if (x < 1)
+ fun_l6_n498(x)
+ else
+ fun_l6_n192(x)
+ end
+end
+
+def fun_l5_n878(x)
+ if (x < 1)
+ fun_l6_n798(x)
+ else
+ fun_l6_n473(x)
+ end
+end
+
+def fun_l5_n879(x)
+ if (x < 1)
+ fun_l6_n166(x)
+ else
+ fun_l6_n301(x)
+ end
+end
+
+def fun_l5_n880(x)
+ if (x < 1)
+ fun_l6_n616(x)
+ else
+ fun_l6_n28(x)
+ end
+end
+
+def fun_l5_n881(x)
+ if (x < 1)
+ fun_l6_n315(x)
+ else
+ fun_l6_n92(x)
+ end
+end
+
+def fun_l5_n882(x)
+ if (x < 1)
+ fun_l6_n548(x)
+ else
+ fun_l6_n41(x)
+ end
+end
+
+def fun_l5_n883(x)
+ if (x < 1)
+ fun_l6_n279(x)
+ else
+ fun_l6_n72(x)
+ end
+end
+
+def fun_l5_n884(x)
+ if (x < 1)
+ fun_l6_n206(x)
+ else
+ fun_l6_n384(x)
+ end
+end
+
+def fun_l5_n885(x)
+ if (x < 1)
+ fun_l6_n191(x)
+ else
+ fun_l6_n84(x)
+ end
+end
+
+def fun_l5_n886(x)
+ if (x < 1)
+ fun_l6_n960(x)
+ else
+ fun_l6_n495(x)
+ end
+end
+
+def fun_l5_n887(x)
+ if (x < 1)
+ fun_l6_n459(x)
+ else
+ fun_l6_n757(x)
+ end
+end
+
+def fun_l5_n888(x)
+ if (x < 1)
+ fun_l6_n634(x)
+ else
+ fun_l6_n463(x)
+ end
+end
+
+def fun_l5_n889(x)
+ if (x < 1)
+ fun_l6_n611(x)
+ else
+ fun_l6_n469(x)
+ end
+end
+
+def fun_l5_n890(x)
+ if (x < 1)
+ fun_l6_n787(x)
+ else
+ fun_l6_n707(x)
+ end
+end
+
+def fun_l5_n891(x)
+ if (x < 1)
+ fun_l6_n201(x)
+ else
+ fun_l6_n223(x)
+ end
+end
+
+def fun_l5_n892(x)
+ if (x < 1)
+ fun_l6_n214(x)
+ else
+ fun_l6_n303(x)
+ end
+end
+
+def fun_l5_n893(x)
+ if (x < 1)
+ fun_l6_n85(x)
+ else
+ fun_l6_n802(x)
+ end
+end
+
+def fun_l5_n894(x)
+ if (x < 1)
+ fun_l6_n816(x)
+ else
+ fun_l6_n325(x)
+ end
+end
+
+def fun_l5_n895(x)
+ if (x < 1)
+ fun_l6_n491(x)
+ else
+ fun_l6_n907(x)
+ end
+end
+
+def fun_l5_n896(x)
+ if (x < 1)
+ fun_l6_n809(x)
+ else
+ fun_l6_n364(x)
+ end
+end
+
+def fun_l5_n897(x)
+ if (x < 1)
+ fun_l6_n739(x)
+ else
+ fun_l6_n192(x)
+ end
+end
+
+def fun_l5_n898(x)
+ if (x < 1)
+ fun_l6_n461(x)
+ else
+ fun_l6_n594(x)
+ end
+end
+
+def fun_l5_n899(x)
+ if (x < 1)
+ fun_l6_n256(x)
+ else
+ fun_l6_n521(x)
+ end
+end
+
+def fun_l5_n900(x)
+ if (x < 1)
+ fun_l6_n6(x)
+ else
+ fun_l6_n127(x)
+ end
+end
+
+def fun_l5_n901(x)
+ if (x < 1)
+ fun_l6_n655(x)
+ else
+ fun_l6_n426(x)
+ end
+end
+
+def fun_l5_n902(x)
+ if (x < 1)
+ fun_l6_n936(x)
+ else
+ fun_l6_n275(x)
+ end
+end
+
+def fun_l5_n903(x)
+ if (x < 1)
+ fun_l6_n738(x)
+ else
+ fun_l6_n654(x)
+ end
+end
+
+def fun_l5_n904(x)
+ if (x < 1)
+ fun_l6_n583(x)
+ else
+ fun_l6_n600(x)
+ end
+end
+
+def fun_l5_n905(x)
+ if (x < 1)
+ fun_l6_n228(x)
+ else
+ fun_l6_n591(x)
+ end
+end
+
+def fun_l5_n906(x)
+ if (x < 1)
+ fun_l6_n292(x)
+ else
+ fun_l6_n55(x)
+ end
+end
+
+def fun_l5_n907(x)
+ if (x < 1)
+ fun_l6_n457(x)
+ else
+ fun_l6_n513(x)
+ end
+end
+
+def fun_l5_n908(x)
+ if (x < 1)
+ fun_l6_n542(x)
+ else
+ fun_l6_n593(x)
+ end
+end
+
+def fun_l5_n909(x)
+ if (x < 1)
+ fun_l6_n478(x)
+ else
+ fun_l6_n782(x)
+ end
+end
+
+def fun_l5_n910(x)
+ if (x < 1)
+ fun_l6_n780(x)
+ else
+ fun_l6_n275(x)
+ end
+end
+
+def fun_l5_n911(x)
+ if (x < 1)
+ fun_l6_n631(x)
+ else
+ fun_l6_n811(x)
+ end
+end
+
+def fun_l5_n912(x)
+ if (x < 1)
+ fun_l6_n17(x)
+ else
+ fun_l6_n837(x)
+ end
+end
+
+def fun_l5_n913(x)
+ if (x < 1)
+ fun_l6_n607(x)
+ else
+ fun_l6_n159(x)
+ end
+end
+
+def fun_l5_n914(x)
+ if (x < 1)
+ fun_l6_n23(x)
+ else
+ fun_l6_n70(x)
+ end
+end
+
+def fun_l5_n915(x)
+ if (x < 1)
+ fun_l6_n778(x)
+ else
+ fun_l6_n643(x)
+ end
+end
+
+def fun_l5_n916(x)
+ if (x < 1)
+ fun_l6_n707(x)
+ else
+ fun_l6_n121(x)
+ end
+end
+
+def fun_l5_n917(x)
+ if (x < 1)
+ fun_l6_n816(x)
+ else
+ fun_l6_n67(x)
+ end
+end
+
+def fun_l5_n918(x)
+ if (x < 1)
+ fun_l6_n963(x)
+ else
+ fun_l6_n520(x)
+ end
+end
+
+def fun_l5_n919(x)
+ if (x < 1)
+ fun_l6_n251(x)
+ else
+ fun_l6_n111(x)
+ end
+end
+
+def fun_l5_n920(x)
+ if (x < 1)
+ fun_l6_n198(x)
+ else
+ fun_l6_n872(x)
+ end
+end
+
+def fun_l5_n921(x)
+ if (x < 1)
+ fun_l6_n364(x)
+ else
+ fun_l6_n369(x)
+ end
+end
+
+def fun_l5_n922(x)
+ if (x < 1)
+ fun_l6_n7(x)
+ else
+ fun_l6_n314(x)
+ end
+end
+
+def fun_l5_n923(x)
+ if (x < 1)
+ fun_l6_n578(x)
+ else
+ fun_l6_n502(x)
+ end
+end
+
+def fun_l5_n924(x)
+ if (x < 1)
+ fun_l6_n450(x)
+ else
+ fun_l6_n680(x)
+ end
+end
+
+def fun_l5_n925(x)
+ if (x < 1)
+ fun_l6_n469(x)
+ else
+ fun_l6_n973(x)
+ end
+end
+
+def fun_l5_n926(x)
+ if (x < 1)
+ fun_l6_n114(x)
+ else
+ fun_l6_n862(x)
+ end
+end
+
+def fun_l5_n927(x)
+ if (x < 1)
+ fun_l6_n786(x)
+ else
+ fun_l6_n861(x)
+ end
+end
+
+def fun_l5_n928(x)
+ if (x < 1)
+ fun_l6_n40(x)
+ else
+ fun_l6_n665(x)
+ end
+end
+
+def fun_l5_n929(x)
+ if (x < 1)
+ fun_l6_n997(x)
+ else
+ fun_l6_n137(x)
+ end
+end
+
+def fun_l5_n930(x)
+ if (x < 1)
+ fun_l6_n547(x)
+ else
+ fun_l6_n547(x)
+ end
+end
+
+def fun_l5_n931(x)
+ if (x < 1)
+ fun_l6_n310(x)
+ else
+ fun_l6_n986(x)
+ end
+end
+
+def fun_l5_n932(x)
+ if (x < 1)
+ fun_l6_n339(x)
+ else
+ fun_l6_n18(x)
+ end
+end
+
+def fun_l5_n933(x)
+ if (x < 1)
+ fun_l6_n825(x)
+ else
+ fun_l6_n418(x)
+ end
+end
+
+def fun_l5_n934(x)
+ if (x < 1)
+ fun_l6_n509(x)
+ else
+ fun_l6_n589(x)
+ end
+end
+
+def fun_l5_n935(x)
+ if (x < 1)
+ fun_l6_n936(x)
+ else
+ fun_l6_n113(x)
+ end
+end
+
+def fun_l5_n936(x)
+ if (x < 1)
+ fun_l6_n530(x)
+ else
+ fun_l6_n841(x)
+ end
+end
+
+def fun_l5_n937(x)
+ if (x < 1)
+ fun_l6_n431(x)
+ else
+ fun_l6_n531(x)
+ end
+end
+
+def fun_l5_n938(x)
+ if (x < 1)
+ fun_l6_n791(x)
+ else
+ fun_l6_n41(x)
+ end
+end
+
+def fun_l5_n939(x)
+ if (x < 1)
+ fun_l6_n873(x)
+ else
+ fun_l6_n336(x)
+ end
+end
+
+def fun_l5_n940(x)
+ if (x < 1)
+ fun_l6_n925(x)
+ else
+ fun_l6_n746(x)
+ end
+end
+
+def fun_l5_n941(x)
+ if (x < 1)
+ fun_l6_n995(x)
+ else
+ fun_l6_n29(x)
+ end
+end
+
+def fun_l5_n942(x)
+ if (x < 1)
+ fun_l6_n984(x)
+ else
+ fun_l6_n455(x)
+ end
+end
+
+def fun_l5_n943(x)
+ if (x < 1)
+ fun_l6_n660(x)
+ else
+ fun_l6_n934(x)
+ end
+end
+
+def fun_l5_n944(x)
+ if (x < 1)
+ fun_l6_n625(x)
+ else
+ fun_l6_n523(x)
+ end
+end
+
+def fun_l5_n945(x)
+ if (x < 1)
+ fun_l6_n407(x)
+ else
+ fun_l6_n766(x)
+ end
+end
+
+def fun_l5_n946(x)
+ if (x < 1)
+ fun_l6_n80(x)
+ else
+ fun_l6_n75(x)
+ end
+end
+
+def fun_l5_n947(x)
+ if (x < 1)
+ fun_l6_n465(x)
+ else
+ fun_l6_n57(x)
+ end
+end
+
+def fun_l5_n948(x)
+ if (x < 1)
+ fun_l6_n750(x)
+ else
+ fun_l6_n278(x)
+ end
+end
+
+def fun_l5_n949(x)
+ if (x < 1)
+ fun_l6_n917(x)
+ else
+ fun_l6_n472(x)
+ end
+end
+
+def fun_l5_n950(x)
+ if (x < 1)
+ fun_l6_n917(x)
+ else
+ fun_l6_n71(x)
+ end
+end
+
+def fun_l5_n951(x)
+ if (x < 1)
+ fun_l6_n420(x)
+ else
+ fun_l6_n132(x)
+ end
+end
+
+def fun_l5_n952(x)
+ if (x < 1)
+ fun_l6_n112(x)
+ else
+ fun_l6_n396(x)
+ end
+end
+
+def fun_l5_n953(x)
+ if (x < 1)
+ fun_l6_n705(x)
+ else
+ fun_l6_n978(x)
+ end
+end
+
+def fun_l5_n954(x)
+ if (x < 1)
+ fun_l6_n761(x)
+ else
+ fun_l6_n136(x)
+ end
+end
+
+def fun_l5_n955(x)
+ if (x < 1)
+ fun_l6_n518(x)
+ else
+ fun_l6_n687(x)
+ end
+end
+
+def fun_l5_n956(x)
+ if (x < 1)
+ fun_l6_n308(x)
+ else
+ fun_l6_n34(x)
+ end
+end
+
+def fun_l5_n957(x)
+ if (x < 1)
+ fun_l6_n904(x)
+ else
+ fun_l6_n129(x)
+ end
+end
+
+def fun_l5_n958(x)
+ if (x < 1)
+ fun_l6_n271(x)
+ else
+ fun_l6_n444(x)
+ end
+end
+
+def fun_l5_n959(x)
+ if (x < 1)
+ fun_l6_n690(x)
+ else
+ fun_l6_n118(x)
+ end
+end
+
+def fun_l5_n960(x)
+ if (x < 1)
+ fun_l6_n509(x)
+ else
+ fun_l6_n957(x)
+ end
+end
+
+def fun_l5_n961(x)
+ if (x < 1)
+ fun_l6_n889(x)
+ else
+ fun_l6_n26(x)
+ end
+end
+
+def fun_l5_n962(x)
+ if (x < 1)
+ fun_l6_n802(x)
+ else
+ fun_l6_n364(x)
+ end
+end
+
+def fun_l5_n963(x)
+ if (x < 1)
+ fun_l6_n368(x)
+ else
+ fun_l6_n580(x)
+ end
+end
+
+def fun_l5_n964(x)
+ if (x < 1)
+ fun_l6_n879(x)
+ else
+ fun_l6_n925(x)
+ end
+end
+
+def fun_l5_n965(x)
+ if (x < 1)
+ fun_l6_n114(x)
+ else
+ fun_l6_n882(x)
+ end
+end
+
+def fun_l5_n966(x)
+ if (x < 1)
+ fun_l6_n9(x)
+ else
+ fun_l6_n5(x)
+ end
+end
+
+def fun_l5_n967(x)
+ if (x < 1)
+ fun_l6_n536(x)
+ else
+ fun_l6_n251(x)
+ end
+end
+
+def fun_l5_n968(x)
+ if (x < 1)
+ fun_l6_n804(x)
+ else
+ fun_l6_n179(x)
+ end
+end
+
+def fun_l5_n969(x)
+ if (x < 1)
+ fun_l6_n469(x)
+ else
+ fun_l6_n235(x)
+ end
+end
+
+def fun_l5_n970(x)
+ if (x < 1)
+ fun_l6_n328(x)
+ else
+ fun_l6_n763(x)
+ end
+end
+
+def fun_l5_n971(x)
+ if (x < 1)
+ fun_l6_n342(x)
+ else
+ fun_l6_n126(x)
+ end
+end
+
+def fun_l5_n972(x)
+ if (x < 1)
+ fun_l6_n901(x)
+ else
+ fun_l6_n674(x)
+ end
+end
+
+def fun_l5_n973(x)
+ if (x < 1)
+ fun_l6_n853(x)
+ else
+ fun_l6_n714(x)
+ end
+end
+
+def fun_l5_n974(x)
+ if (x < 1)
+ fun_l6_n670(x)
+ else
+ fun_l6_n905(x)
+ end
+end
+
+def fun_l5_n975(x)
+ if (x < 1)
+ fun_l6_n873(x)
+ else
+ fun_l6_n193(x)
+ end
+end
+
+def fun_l5_n976(x)
+ if (x < 1)
+ fun_l6_n603(x)
+ else
+ fun_l6_n186(x)
+ end
+end
+
+def fun_l5_n977(x)
+ if (x < 1)
+ fun_l6_n474(x)
+ else
+ fun_l6_n108(x)
+ end
+end
+
+def fun_l5_n978(x)
+ if (x < 1)
+ fun_l6_n347(x)
+ else
+ fun_l6_n872(x)
+ end
+end
+
+def fun_l5_n979(x)
+ if (x < 1)
+ fun_l6_n593(x)
+ else
+ fun_l6_n575(x)
+ end
+end
+
+def fun_l5_n980(x)
+ if (x < 1)
+ fun_l6_n692(x)
+ else
+ fun_l6_n262(x)
+ end
+end
+
+def fun_l5_n981(x)
+ if (x < 1)
+ fun_l6_n226(x)
+ else
+ fun_l6_n600(x)
+ end
+end
+
+def fun_l5_n982(x)
+ if (x < 1)
+ fun_l6_n357(x)
+ else
+ fun_l6_n165(x)
+ end
+end
+
+def fun_l5_n983(x)
+ if (x < 1)
+ fun_l6_n784(x)
+ else
+ fun_l6_n584(x)
+ end
+end
+
+def fun_l5_n984(x)
+ if (x < 1)
+ fun_l6_n339(x)
+ else
+ fun_l6_n754(x)
+ end
+end
+
+def fun_l5_n985(x)
+ if (x < 1)
+ fun_l6_n536(x)
+ else
+ fun_l6_n663(x)
+ end
+end
+
+def fun_l5_n986(x)
+ if (x < 1)
+ fun_l6_n239(x)
+ else
+ fun_l6_n723(x)
+ end
+end
+
+def fun_l5_n987(x)
+ if (x < 1)
+ fun_l6_n928(x)
+ else
+ fun_l6_n403(x)
+ end
+end
+
+def fun_l5_n988(x)
+ if (x < 1)
+ fun_l6_n328(x)
+ else
+ fun_l6_n551(x)
+ end
+end
+
+def fun_l5_n989(x)
+ if (x < 1)
+ fun_l6_n847(x)
+ else
+ fun_l6_n475(x)
+ end
+end
+
+def fun_l5_n990(x)
+ if (x < 1)
+ fun_l6_n405(x)
+ else
+ fun_l6_n39(x)
+ end
+end
+
+def fun_l5_n991(x)
+ if (x < 1)
+ fun_l6_n705(x)
+ else
+ fun_l6_n281(x)
+ end
+end
+
+def fun_l5_n992(x)
+ if (x < 1)
+ fun_l6_n59(x)
+ else
+ fun_l6_n465(x)
+ end
+end
+
+def fun_l5_n993(x)
+ if (x < 1)
+ fun_l6_n828(x)
+ else
+ fun_l6_n705(x)
+ end
+end
+
+def fun_l5_n994(x)
+ if (x < 1)
+ fun_l6_n687(x)
+ else
+ fun_l6_n451(x)
+ end
+end
+
+def fun_l5_n995(x)
+ if (x < 1)
+ fun_l6_n600(x)
+ else
+ fun_l6_n9(x)
+ end
+end
+
+def fun_l5_n996(x)
+ if (x < 1)
+ fun_l6_n205(x)
+ else
+ fun_l6_n242(x)
+ end
+end
+
+def fun_l5_n997(x)
+ if (x < 1)
+ fun_l6_n438(x)
+ else
+ fun_l6_n108(x)
+ end
+end
+
+def fun_l5_n998(x)
+ if (x < 1)
+ fun_l6_n164(x)
+ else
+ fun_l6_n302(x)
+ end
+end
+
+def fun_l5_n999(x)
+ if (x < 1)
+ fun_l6_n533(x)
+ else
+ fun_l6_n685(x)
+ end
+end
+
+def fun_l6_n0(x)
+ if (x < 1)
+ fun_l7_n74(x)
+ else
+ fun_l7_n45(x)
+ end
+end
+
+def fun_l6_n1(x)
+ if (x < 1)
+ fun_l7_n685(x)
+ else
+ fun_l7_n163(x)
+ end
+end
+
+def fun_l6_n2(x)
+ if (x < 1)
+ fun_l7_n325(x)
+ else
+ fun_l7_n365(x)
+ end
+end
+
+def fun_l6_n3(x)
+ if (x < 1)
+ fun_l7_n855(x)
+ else
+ fun_l7_n359(x)
+ end
+end
+
+def fun_l6_n4(x)
+ if (x < 1)
+ fun_l7_n939(x)
+ else
+ fun_l7_n690(x)
+ end
+end
+
+def fun_l6_n5(x)
+ if (x < 1)
+ fun_l7_n689(x)
+ else
+ fun_l7_n681(x)
+ end
+end
+
+def fun_l6_n6(x)
+ if (x < 1)
+ fun_l7_n226(x)
+ else
+ fun_l7_n307(x)
+ end
+end
+
+def fun_l6_n7(x)
+ if (x < 1)
+ fun_l7_n779(x)
+ else
+ fun_l7_n765(x)
+ end
+end
+
+def fun_l6_n8(x)
+ if (x < 1)
+ fun_l7_n85(x)
+ else
+ fun_l7_n967(x)
+ end
+end
+
+def fun_l6_n9(x)
+ if (x < 1)
+ fun_l7_n539(x)
+ else
+ fun_l7_n5(x)
+ end
+end
+
+def fun_l6_n10(x)
+ if (x < 1)
+ fun_l7_n503(x)
+ else
+ fun_l7_n163(x)
+ end
+end
+
+def fun_l6_n11(x)
+ if (x < 1)
+ fun_l7_n24(x)
+ else
+ fun_l7_n374(x)
+ end
+end
+
+def fun_l6_n12(x)
+ if (x < 1)
+ fun_l7_n633(x)
+ else
+ fun_l7_n395(x)
+ end
+end
+
+def fun_l6_n13(x)
+ if (x < 1)
+ fun_l7_n250(x)
+ else
+ fun_l7_n7(x)
+ end
+end
+
+def fun_l6_n14(x)
+ if (x < 1)
+ fun_l7_n22(x)
+ else
+ fun_l7_n560(x)
+ end
+end
+
+def fun_l6_n15(x)
+ if (x < 1)
+ fun_l7_n209(x)
+ else
+ fun_l7_n323(x)
+ end
+end
+
+def fun_l6_n16(x)
+ if (x < 1)
+ fun_l7_n770(x)
+ else
+ fun_l7_n155(x)
+ end
+end
+
+def fun_l6_n17(x)
+ if (x < 1)
+ fun_l7_n976(x)
+ else
+ fun_l7_n712(x)
+ end
+end
+
+def fun_l6_n18(x)
+ if (x < 1)
+ fun_l7_n762(x)
+ else
+ fun_l7_n307(x)
+ end
+end
+
+def fun_l6_n19(x)
+ if (x < 1)
+ fun_l7_n911(x)
+ else
+ fun_l7_n788(x)
+ end
+end
+
+def fun_l6_n20(x)
+ if (x < 1)
+ fun_l7_n40(x)
+ else
+ fun_l7_n269(x)
+ end
+end
+
+def fun_l6_n21(x)
+ if (x < 1)
+ fun_l7_n707(x)
+ else
+ fun_l7_n861(x)
+ end
+end
+
+def fun_l6_n22(x)
+ if (x < 1)
+ fun_l7_n591(x)
+ else
+ fun_l7_n557(x)
+ end
+end
+
+def fun_l6_n23(x)
+ if (x < 1)
+ fun_l7_n890(x)
+ else
+ fun_l7_n142(x)
+ end
+end
+
+def fun_l6_n24(x)
+ if (x < 1)
+ fun_l7_n563(x)
+ else
+ fun_l7_n509(x)
+ end
+end
+
+def fun_l6_n25(x)
+ if (x < 1)
+ fun_l7_n630(x)
+ else
+ fun_l7_n784(x)
+ end
+end
+
+def fun_l6_n26(x)
+ if (x < 1)
+ fun_l7_n30(x)
+ else
+ fun_l7_n826(x)
+ end
+end
+
+def fun_l6_n27(x)
+ if (x < 1)
+ fun_l7_n223(x)
+ else
+ fun_l7_n800(x)
+ end
+end
+
+def fun_l6_n28(x)
+ if (x < 1)
+ fun_l7_n51(x)
+ else
+ fun_l7_n963(x)
+ end
+end
+
+def fun_l6_n29(x)
+ if (x < 1)
+ fun_l7_n603(x)
+ else
+ fun_l7_n988(x)
+ end
+end
+
+def fun_l6_n30(x)
+ if (x < 1)
+ fun_l7_n258(x)
+ else
+ fun_l7_n512(x)
+ end
+end
+
+def fun_l6_n31(x)
+ if (x < 1)
+ fun_l7_n649(x)
+ else
+ fun_l7_n772(x)
+ end
+end
+
+def fun_l6_n32(x)
+ if (x < 1)
+ fun_l7_n999(x)
+ else
+ fun_l7_n592(x)
+ end
+end
+
+def fun_l6_n33(x)
+ if (x < 1)
+ fun_l7_n371(x)
+ else
+ fun_l7_n801(x)
+ end
+end
+
+def fun_l6_n34(x)
+ if (x < 1)
+ fun_l7_n905(x)
+ else
+ fun_l7_n701(x)
+ end
+end
+
+def fun_l6_n35(x)
+ if (x < 1)
+ fun_l7_n142(x)
+ else
+ fun_l7_n933(x)
+ end
+end
+
+def fun_l6_n36(x)
+ if (x < 1)
+ fun_l7_n987(x)
+ else
+ fun_l7_n305(x)
+ end
+end
+
+def fun_l6_n37(x)
+ if (x < 1)
+ fun_l7_n360(x)
+ else
+ fun_l7_n266(x)
+ end
+end
+
+def fun_l6_n38(x)
+ if (x < 1)
+ fun_l7_n799(x)
+ else
+ fun_l7_n938(x)
+ end
+end
+
+def fun_l6_n39(x)
+ if (x < 1)
+ fun_l7_n921(x)
+ else
+ fun_l7_n739(x)
+ end
+end
+
+def fun_l6_n40(x)
+ if (x < 1)
+ fun_l7_n553(x)
+ else
+ fun_l7_n236(x)
+ end
+end
+
+def fun_l6_n41(x)
+ if (x < 1)
+ fun_l7_n592(x)
+ else
+ fun_l7_n335(x)
+ end
+end
+
+def fun_l6_n42(x)
+ if (x < 1)
+ fun_l7_n33(x)
+ else
+ fun_l7_n521(x)
+ end
+end
+
+def fun_l6_n43(x)
+ if (x < 1)
+ fun_l7_n278(x)
+ else
+ fun_l7_n866(x)
+ end
+end
+
+def fun_l6_n44(x)
+ if (x < 1)
+ fun_l7_n808(x)
+ else
+ fun_l7_n394(x)
+ end
+end
+
+def fun_l6_n45(x)
+ if (x < 1)
+ fun_l7_n556(x)
+ else
+ fun_l7_n462(x)
+ end
+end
+
+def fun_l6_n46(x)
+ if (x < 1)
+ fun_l7_n72(x)
+ else
+ fun_l7_n558(x)
+ end
+end
+
+def fun_l6_n47(x)
+ if (x < 1)
+ fun_l7_n583(x)
+ else
+ fun_l7_n472(x)
+ end
+end
+
+def fun_l6_n48(x)
+ if (x < 1)
+ fun_l7_n577(x)
+ else
+ fun_l7_n264(x)
+ end
+end
+
+def fun_l6_n49(x)
+ if (x < 1)
+ fun_l7_n167(x)
+ else
+ fun_l7_n570(x)
+ end
+end
+
+def fun_l6_n50(x)
+ if (x < 1)
+ fun_l7_n707(x)
+ else
+ fun_l7_n127(x)
+ end
+end
+
+def fun_l6_n51(x)
+ if (x < 1)
+ fun_l7_n151(x)
+ else
+ fun_l7_n82(x)
+ end
+end
+
+def fun_l6_n52(x)
+ if (x < 1)
+ fun_l7_n729(x)
+ else
+ fun_l7_n785(x)
+ end
+end
+
+def fun_l6_n53(x)
+ if (x < 1)
+ fun_l7_n236(x)
+ else
+ fun_l7_n84(x)
+ end
+end
+
+def fun_l6_n54(x)
+ if (x < 1)
+ fun_l7_n573(x)
+ else
+ fun_l7_n92(x)
+ end
+end
+
+def fun_l6_n55(x)
+ if (x < 1)
+ fun_l7_n601(x)
+ else
+ fun_l7_n531(x)
+ end
+end
+
+def fun_l6_n56(x)
+ if (x < 1)
+ fun_l7_n623(x)
+ else
+ fun_l7_n522(x)
+ end
+end
+
+def fun_l6_n57(x)
+ if (x < 1)
+ fun_l7_n707(x)
+ else
+ fun_l7_n830(x)
+ end
+end
+
+def fun_l6_n58(x)
+ if (x < 1)
+ fun_l7_n240(x)
+ else
+ fun_l7_n868(x)
+ end
+end
+
+def fun_l6_n59(x)
+ if (x < 1)
+ fun_l7_n233(x)
+ else
+ fun_l7_n595(x)
+ end
+end
+
+def fun_l6_n60(x)
+ if (x < 1)
+ fun_l7_n384(x)
+ else
+ fun_l7_n605(x)
+ end
+end
+
+def fun_l6_n61(x)
+ if (x < 1)
+ fun_l7_n721(x)
+ else
+ fun_l7_n509(x)
+ end
+end
+
+def fun_l6_n62(x)
+ if (x < 1)
+ fun_l7_n741(x)
+ else
+ fun_l7_n934(x)
+ end
+end
+
+def fun_l6_n63(x)
+ if (x < 1)
+ fun_l7_n724(x)
+ else
+ fun_l7_n963(x)
+ end
+end
+
+def fun_l6_n64(x)
+ if (x < 1)
+ fun_l7_n144(x)
+ else
+ fun_l7_n417(x)
+ end
+end
+
+def fun_l6_n65(x)
+ if (x < 1)
+ fun_l7_n618(x)
+ else
+ fun_l7_n19(x)
+ end
+end
+
+def fun_l6_n66(x)
+ if (x < 1)
+ fun_l7_n128(x)
+ else
+ fun_l7_n257(x)
+ end
+end
+
+def fun_l6_n67(x)
+ if (x < 1)
+ fun_l7_n623(x)
+ else
+ fun_l7_n182(x)
+ end
+end
+
+def fun_l6_n68(x)
+ if (x < 1)
+ fun_l7_n256(x)
+ else
+ fun_l7_n692(x)
+ end
+end
+
+def fun_l6_n69(x)
+ if (x < 1)
+ fun_l7_n360(x)
+ else
+ fun_l7_n34(x)
+ end
+end
+
+def fun_l6_n70(x)
+ if (x < 1)
+ fun_l7_n690(x)
+ else
+ fun_l7_n813(x)
+ end
+end
+
+def fun_l6_n71(x)
+ if (x < 1)
+ fun_l7_n533(x)
+ else
+ fun_l7_n94(x)
+ end
+end
+
+def fun_l6_n72(x)
+ if (x < 1)
+ fun_l7_n245(x)
+ else
+ fun_l7_n548(x)
+ end
+end
+
+def fun_l6_n73(x)
+ if (x < 1)
+ fun_l7_n919(x)
+ else
+ fun_l7_n295(x)
+ end
+end
+
+def fun_l6_n74(x)
+ if (x < 1)
+ fun_l7_n925(x)
+ else
+ fun_l7_n965(x)
+ end
+end
+
+def fun_l6_n75(x)
+ if (x < 1)
+ fun_l7_n825(x)
+ else
+ fun_l7_n79(x)
+ end
+end
+
+def fun_l6_n76(x)
+ if (x < 1)
+ fun_l7_n812(x)
+ else
+ fun_l7_n96(x)
+ end
+end
+
+def fun_l6_n77(x)
+ if (x < 1)
+ fun_l7_n688(x)
+ else
+ fun_l7_n424(x)
+ end
+end
+
+def fun_l6_n78(x)
+ if (x < 1)
+ fun_l7_n171(x)
+ else
+ fun_l7_n728(x)
+ end
+end
+
+def fun_l6_n79(x)
+ if (x < 1)
+ fun_l7_n786(x)
+ else
+ fun_l7_n135(x)
+ end
+end
+
+def fun_l6_n80(x)
+ if (x < 1)
+ fun_l7_n622(x)
+ else
+ fun_l7_n3(x)
+ end
+end
+
+def fun_l6_n81(x)
+ if (x < 1)
+ fun_l7_n386(x)
+ else
+ fun_l7_n946(x)
+ end
+end
+
+def fun_l6_n82(x)
+ if (x < 1)
+ fun_l7_n192(x)
+ else
+ fun_l7_n253(x)
+ end
+end
+
+def fun_l6_n83(x)
+ if (x < 1)
+ fun_l7_n534(x)
+ else
+ fun_l7_n4(x)
+ end
+end
+
+def fun_l6_n84(x)
+ if (x < 1)
+ fun_l7_n198(x)
+ else
+ fun_l7_n455(x)
+ end
+end
+
+def fun_l6_n85(x)
+ if (x < 1)
+ fun_l7_n471(x)
+ else
+ fun_l7_n26(x)
+ end
+end
+
+def fun_l6_n86(x)
+ if (x < 1)
+ fun_l7_n147(x)
+ else
+ fun_l7_n893(x)
+ end
+end
+
+def fun_l6_n87(x)
+ if (x < 1)
+ fun_l7_n424(x)
+ else
+ fun_l7_n713(x)
+ end
+end
+
+def fun_l6_n88(x)
+ if (x < 1)
+ fun_l7_n867(x)
+ else
+ fun_l7_n561(x)
+ end
+end
+
+def fun_l6_n89(x)
+ if (x < 1)
+ fun_l7_n64(x)
+ else
+ fun_l7_n662(x)
+ end
+end
+
+def fun_l6_n90(x)
+ if (x < 1)
+ fun_l7_n849(x)
+ else
+ fun_l7_n105(x)
+ end
+end
+
+def fun_l6_n91(x)
+ if (x < 1)
+ fun_l7_n564(x)
+ else
+ fun_l7_n758(x)
+ end
+end
+
+def fun_l6_n92(x)
+ if (x < 1)
+ fun_l7_n433(x)
+ else
+ fun_l7_n713(x)
+ end
+end
+
+def fun_l6_n93(x)
+ if (x < 1)
+ fun_l7_n283(x)
+ else
+ fun_l7_n577(x)
+ end
+end
+
+def fun_l6_n94(x)
+ if (x < 1)
+ fun_l7_n951(x)
+ else
+ fun_l7_n48(x)
+ end
+end
+
+def fun_l6_n95(x)
+ if (x < 1)
+ fun_l7_n966(x)
+ else
+ fun_l7_n789(x)
+ end
+end
+
+def fun_l6_n96(x)
+ if (x < 1)
+ fun_l7_n954(x)
+ else
+ fun_l7_n431(x)
+ end
+end
+
+def fun_l6_n97(x)
+ if (x < 1)
+ fun_l7_n720(x)
+ else
+ fun_l7_n847(x)
+ end
+end
+
+def fun_l6_n98(x)
+ if (x < 1)
+ fun_l7_n517(x)
+ else
+ fun_l7_n378(x)
+ end
+end
+
+def fun_l6_n99(x)
+ if (x < 1)
+ fun_l7_n951(x)
+ else
+ fun_l7_n688(x)
+ end
+end
+
+def fun_l6_n100(x)
+ if (x < 1)
+ fun_l7_n163(x)
+ else
+ fun_l7_n540(x)
+ end
+end
+
+def fun_l6_n101(x)
+ if (x < 1)
+ fun_l7_n423(x)
+ else
+ fun_l7_n10(x)
+ end
+end
+
+def fun_l6_n102(x)
+ if (x < 1)
+ fun_l7_n346(x)
+ else
+ fun_l7_n409(x)
+ end
+end
+
+def fun_l6_n103(x)
+ if (x < 1)
+ fun_l7_n686(x)
+ else
+ fun_l7_n432(x)
+ end
+end
+
+def fun_l6_n104(x)
+ if (x < 1)
+ fun_l7_n144(x)
+ else
+ fun_l7_n510(x)
+ end
+end
+
+def fun_l6_n105(x)
+ if (x < 1)
+ fun_l7_n568(x)
+ else
+ fun_l7_n756(x)
+ end
+end
+
+def fun_l6_n106(x)
+ if (x < 1)
+ fun_l7_n708(x)
+ else
+ fun_l7_n199(x)
+ end
+end
+
+def fun_l6_n107(x)
+ if (x < 1)
+ fun_l7_n823(x)
+ else
+ fun_l7_n969(x)
+ end
+end
+
+def fun_l6_n108(x)
+ if (x < 1)
+ fun_l7_n156(x)
+ else
+ fun_l7_n211(x)
+ end
+end
+
+def fun_l6_n109(x)
+ if (x < 1)
+ fun_l7_n527(x)
+ else
+ fun_l7_n791(x)
+ end
+end
+
+def fun_l6_n110(x)
+ if (x < 1)
+ fun_l7_n392(x)
+ else
+ fun_l7_n314(x)
+ end
+end
+
+def fun_l6_n111(x)
+ if (x < 1)
+ fun_l7_n355(x)
+ else
+ fun_l7_n222(x)
+ end
+end
+
+def fun_l6_n112(x)
+ if (x < 1)
+ fun_l7_n683(x)
+ else
+ fun_l7_n735(x)
+ end
+end
+
+def fun_l6_n113(x)
+ if (x < 1)
+ fun_l7_n38(x)
+ else
+ fun_l7_n874(x)
+ end
+end
+
+def fun_l6_n114(x)
+ if (x < 1)
+ fun_l7_n190(x)
+ else
+ fun_l7_n209(x)
+ end
+end
+
+def fun_l6_n115(x)
+ if (x < 1)
+ fun_l7_n544(x)
+ else
+ fun_l7_n267(x)
+ end
+end
+
+def fun_l6_n116(x)
+ if (x < 1)
+ fun_l7_n701(x)
+ else
+ fun_l7_n101(x)
+ end
+end
+
+def fun_l6_n117(x)
+ if (x < 1)
+ fun_l7_n283(x)
+ else
+ fun_l7_n979(x)
+ end
+end
+
+def fun_l6_n118(x)
+ if (x < 1)
+ fun_l7_n902(x)
+ else
+ fun_l7_n897(x)
+ end
+end
+
+def fun_l6_n119(x)
+ if (x < 1)
+ fun_l7_n115(x)
+ else
+ fun_l7_n660(x)
+ end
+end
+
+def fun_l6_n120(x)
+ if (x < 1)
+ fun_l7_n804(x)
+ else
+ fun_l7_n536(x)
+ end
+end
+
+def fun_l6_n121(x)
+ if (x < 1)
+ fun_l7_n278(x)
+ else
+ fun_l7_n666(x)
+ end
+end
+
+def fun_l6_n122(x)
+ if (x < 1)
+ fun_l7_n254(x)
+ else
+ fun_l7_n572(x)
+ end
+end
+
+def fun_l6_n123(x)
+ if (x < 1)
+ fun_l7_n474(x)
+ else
+ fun_l7_n912(x)
+ end
+end
+
+def fun_l6_n124(x)
+ if (x < 1)
+ fun_l7_n0(x)
+ else
+ fun_l7_n514(x)
+ end
+end
+
+def fun_l6_n125(x)
+ if (x < 1)
+ fun_l7_n916(x)
+ else
+ fun_l7_n633(x)
+ end
+end
+
+def fun_l6_n126(x)
+ if (x < 1)
+ fun_l7_n184(x)
+ else
+ fun_l7_n379(x)
+ end
+end
+
+def fun_l6_n127(x)
+ if (x < 1)
+ fun_l7_n316(x)
+ else
+ fun_l7_n422(x)
+ end
+end
+
+def fun_l6_n128(x)
+ if (x < 1)
+ fun_l7_n402(x)
+ else
+ fun_l7_n237(x)
+ end
+end
+
+def fun_l6_n129(x)
+ if (x < 1)
+ fun_l7_n303(x)
+ else
+ fun_l7_n61(x)
+ end
+end
+
+def fun_l6_n130(x)
+ if (x < 1)
+ fun_l7_n918(x)
+ else
+ fun_l7_n732(x)
+ end
+end
+
+def fun_l6_n131(x)
+ if (x < 1)
+ fun_l7_n74(x)
+ else
+ fun_l7_n472(x)
+ end
+end
+
+def fun_l6_n132(x)
+ if (x < 1)
+ fun_l7_n648(x)
+ else
+ fun_l7_n546(x)
+ end
+end
+
+def fun_l6_n133(x)
+ if (x < 1)
+ fun_l7_n388(x)
+ else
+ fun_l7_n359(x)
+ end
+end
+
+def fun_l6_n134(x)
+ if (x < 1)
+ fun_l7_n594(x)
+ else
+ fun_l7_n607(x)
+ end
+end
+
+def fun_l6_n135(x)
+ if (x < 1)
+ fun_l7_n642(x)
+ else
+ fun_l7_n188(x)
+ end
+end
+
+def fun_l6_n136(x)
+ if (x < 1)
+ fun_l7_n879(x)
+ else
+ fun_l7_n521(x)
+ end
+end
+
+def fun_l6_n137(x)
+ if (x < 1)
+ fun_l7_n362(x)
+ else
+ fun_l7_n564(x)
+ end
+end
+
+def fun_l6_n138(x)
+ if (x < 1)
+ fun_l7_n590(x)
+ else
+ fun_l7_n59(x)
+ end
+end
+
+def fun_l6_n139(x)
+ if (x < 1)
+ fun_l7_n464(x)
+ else
+ fun_l7_n563(x)
+ end
+end
+
+def fun_l6_n140(x)
+ if (x < 1)
+ fun_l7_n710(x)
+ else
+ fun_l7_n890(x)
+ end
+end
+
+def fun_l6_n141(x)
+ if (x < 1)
+ fun_l7_n63(x)
+ else
+ fun_l7_n470(x)
+ end
+end
+
+def fun_l6_n142(x)
+ if (x < 1)
+ fun_l7_n160(x)
+ else
+ fun_l7_n153(x)
+ end
+end
+
+def fun_l6_n143(x)
+ if (x < 1)
+ fun_l7_n908(x)
+ else
+ fun_l7_n286(x)
+ end
+end
+
+def fun_l6_n144(x)
+ if (x < 1)
+ fun_l7_n193(x)
+ else
+ fun_l7_n657(x)
+ end
+end
+
+def fun_l6_n145(x)
+ if (x < 1)
+ fun_l7_n885(x)
+ else
+ fun_l7_n981(x)
+ end
+end
+
+def fun_l6_n146(x)
+ if (x < 1)
+ fun_l7_n479(x)
+ else
+ fun_l7_n188(x)
+ end
+end
+
+def fun_l6_n147(x)
+ if (x < 1)
+ fun_l7_n378(x)
+ else
+ fun_l7_n299(x)
+ end
+end
+
+def fun_l6_n148(x)
+ if (x < 1)
+ fun_l7_n239(x)
+ else
+ fun_l7_n70(x)
+ end
+end
+
+def fun_l6_n149(x)
+ if (x < 1)
+ fun_l7_n864(x)
+ else
+ fun_l7_n131(x)
+ end
+end
+
+def fun_l6_n150(x)
+ if (x < 1)
+ fun_l7_n748(x)
+ else
+ fun_l7_n112(x)
+ end
+end
+
+def fun_l6_n151(x)
+ if (x < 1)
+ fun_l7_n466(x)
+ else
+ fun_l7_n672(x)
+ end
+end
+
+def fun_l6_n152(x)
+ if (x < 1)
+ fun_l7_n242(x)
+ else
+ fun_l7_n8(x)
+ end
+end
+
+def fun_l6_n153(x)
+ if (x < 1)
+ fun_l7_n408(x)
+ else
+ fun_l7_n538(x)
+ end
+end
+
+def fun_l6_n154(x)
+ if (x < 1)
+ fun_l7_n984(x)
+ else
+ fun_l7_n134(x)
+ end
+end
+
+def fun_l6_n155(x)
+ if (x < 1)
+ fun_l7_n384(x)
+ else
+ fun_l7_n62(x)
+ end
+end
+
+def fun_l6_n156(x)
+ if (x < 1)
+ fun_l7_n576(x)
+ else
+ fun_l7_n168(x)
+ end
+end
+
+def fun_l6_n157(x)
+ if (x < 1)
+ fun_l7_n371(x)
+ else
+ fun_l7_n470(x)
+ end
+end
+
+def fun_l6_n158(x)
+ if (x < 1)
+ fun_l7_n30(x)
+ else
+ fun_l7_n11(x)
+ end
+end
+
+def fun_l6_n159(x)
+ if (x < 1)
+ fun_l7_n45(x)
+ else
+ fun_l7_n191(x)
+ end
+end
+
+def fun_l6_n160(x)
+ if (x < 1)
+ fun_l7_n659(x)
+ else
+ fun_l7_n981(x)
+ end
+end
+
+def fun_l6_n161(x)
+ if (x < 1)
+ fun_l7_n586(x)
+ else
+ fun_l7_n617(x)
+ end
+end
+
+def fun_l6_n162(x)
+ if (x < 1)
+ fun_l7_n844(x)
+ else
+ fun_l7_n831(x)
+ end
+end
+
+def fun_l6_n163(x)
+ if (x < 1)
+ fun_l7_n14(x)
+ else
+ fun_l7_n631(x)
+ end
+end
+
+def fun_l6_n164(x)
+ if (x < 1)
+ fun_l7_n388(x)
+ else
+ fun_l7_n837(x)
+ end
+end
+
+def fun_l6_n165(x)
+ if (x < 1)
+ fun_l7_n825(x)
+ else
+ fun_l7_n902(x)
+ end
+end
+
+def fun_l6_n166(x)
+ if (x < 1)
+ fun_l7_n490(x)
+ else
+ fun_l7_n724(x)
+ end
+end
+
+def fun_l6_n167(x)
+ if (x < 1)
+ fun_l7_n612(x)
+ else
+ fun_l7_n792(x)
+ end
+end
+
+def fun_l6_n168(x)
+ if (x < 1)
+ fun_l7_n344(x)
+ else
+ fun_l7_n624(x)
+ end
+end
+
+def fun_l6_n169(x)
+ if (x < 1)
+ fun_l7_n255(x)
+ else
+ fun_l7_n456(x)
+ end
+end
+
+def fun_l6_n170(x)
+ if (x < 1)
+ fun_l7_n893(x)
+ else
+ fun_l7_n358(x)
+ end
+end
+
+def fun_l6_n171(x)
+ if (x < 1)
+ fun_l7_n926(x)
+ else
+ fun_l7_n988(x)
+ end
+end
+
+def fun_l6_n172(x)
+ if (x < 1)
+ fun_l7_n856(x)
+ else
+ fun_l7_n553(x)
+ end
+end
+
+def fun_l6_n173(x)
+ if (x < 1)
+ fun_l7_n694(x)
+ else
+ fun_l7_n918(x)
+ end
+end
+
+def fun_l6_n174(x)
+ if (x < 1)
+ fun_l7_n884(x)
+ else
+ fun_l7_n711(x)
+ end
+end
+
+def fun_l6_n175(x)
+ if (x < 1)
+ fun_l7_n884(x)
+ else
+ fun_l7_n28(x)
+ end
+end
+
+def fun_l6_n176(x)
+ if (x < 1)
+ fun_l7_n378(x)
+ else
+ fun_l7_n14(x)
+ end
+end
+
+def fun_l6_n177(x)
+ if (x < 1)
+ fun_l7_n844(x)
+ else
+ fun_l7_n549(x)
+ end
+end
+
+def fun_l6_n178(x)
+ if (x < 1)
+ fun_l7_n396(x)
+ else
+ fun_l7_n802(x)
+ end
+end
+
+def fun_l6_n179(x)
+ if (x < 1)
+ fun_l7_n407(x)
+ else
+ fun_l7_n612(x)
+ end
+end
+
+def fun_l6_n180(x)
+ if (x < 1)
+ fun_l7_n403(x)
+ else
+ fun_l7_n768(x)
+ end
+end
+
+def fun_l6_n181(x)
+ if (x < 1)
+ fun_l7_n412(x)
+ else
+ fun_l7_n301(x)
+ end
+end
+
+def fun_l6_n182(x)
+ if (x < 1)
+ fun_l7_n479(x)
+ else
+ fun_l7_n923(x)
+ end
+end
+
+def fun_l6_n183(x)
+ if (x < 1)
+ fun_l7_n664(x)
+ else
+ fun_l7_n451(x)
+ end
+end
+
+def fun_l6_n184(x)
+ if (x < 1)
+ fun_l7_n854(x)
+ else
+ fun_l7_n438(x)
+ end
+end
+
+def fun_l6_n185(x)
+ if (x < 1)
+ fun_l7_n994(x)
+ else
+ fun_l7_n726(x)
+ end
+end
+
+def fun_l6_n186(x)
+ if (x < 1)
+ fun_l7_n128(x)
+ else
+ fun_l7_n166(x)
+ end
+end
+
+def fun_l6_n187(x)
+ if (x < 1)
+ fun_l7_n515(x)
+ else
+ fun_l7_n21(x)
+ end
+end
+
+def fun_l6_n188(x)
+ if (x < 1)
+ fun_l7_n487(x)
+ else
+ fun_l7_n631(x)
+ end
+end
+
+def fun_l6_n189(x)
+ if (x < 1)
+ fun_l7_n16(x)
+ else
+ fun_l7_n579(x)
+ end
+end
+
+def fun_l6_n190(x)
+ if (x < 1)
+ fun_l7_n30(x)
+ else
+ fun_l7_n417(x)
+ end
+end
+
+def fun_l6_n191(x)
+ if (x < 1)
+ fun_l7_n737(x)
+ else
+ fun_l7_n436(x)
+ end
+end
+
+def fun_l6_n192(x)
+ if (x < 1)
+ fun_l7_n260(x)
+ else
+ fun_l7_n657(x)
+ end
+end
+
+def fun_l6_n193(x)
+ if (x < 1)
+ fun_l7_n722(x)
+ else
+ fun_l7_n489(x)
+ end
+end
+
+def fun_l6_n194(x)
+ if (x < 1)
+ fun_l7_n53(x)
+ else
+ fun_l7_n624(x)
+ end
+end
+
+def fun_l6_n195(x)
+ if (x < 1)
+ fun_l7_n91(x)
+ else
+ fun_l7_n597(x)
+ end
+end
+
+def fun_l6_n196(x)
+ if (x < 1)
+ fun_l7_n980(x)
+ else
+ fun_l7_n498(x)
+ end
+end
+
+def fun_l6_n197(x)
+ if (x < 1)
+ fun_l7_n918(x)
+ else
+ fun_l7_n328(x)
+ end
+end
+
+def fun_l6_n198(x)
+ if (x < 1)
+ fun_l7_n184(x)
+ else
+ fun_l7_n761(x)
+ end
+end
+
+def fun_l6_n199(x)
+ if (x < 1)
+ fun_l7_n692(x)
+ else
+ fun_l7_n610(x)
+ end
+end
+
+def fun_l6_n200(x)
+ if (x < 1)
+ fun_l7_n597(x)
+ else
+ fun_l7_n135(x)
+ end
+end
+
+def fun_l6_n201(x)
+ if (x < 1)
+ fun_l7_n973(x)
+ else
+ fun_l7_n453(x)
+ end
+end
+
+def fun_l6_n202(x)
+ if (x < 1)
+ fun_l7_n433(x)
+ else
+ fun_l7_n794(x)
+ end
+end
+
+def fun_l6_n203(x)
+ if (x < 1)
+ fun_l7_n294(x)
+ else
+ fun_l7_n271(x)
+ end
+end
+
+def fun_l6_n204(x)
+ if (x < 1)
+ fun_l7_n783(x)
+ else
+ fun_l7_n20(x)
+ end
+end
+
+def fun_l6_n205(x)
+ if (x < 1)
+ fun_l7_n941(x)
+ else
+ fun_l7_n517(x)
+ end
+end
+
+def fun_l6_n206(x)
+ if (x < 1)
+ fun_l7_n306(x)
+ else
+ fun_l7_n735(x)
+ end
+end
+
+def fun_l6_n207(x)
+ if (x < 1)
+ fun_l7_n63(x)
+ else
+ fun_l7_n313(x)
+ end
+end
+
+def fun_l6_n208(x)
+ if (x < 1)
+ fun_l7_n766(x)
+ else
+ fun_l7_n868(x)
+ end
+end
+
+def fun_l6_n209(x)
+ if (x < 1)
+ fun_l7_n780(x)
+ else
+ fun_l7_n422(x)
+ end
+end
+
+def fun_l6_n210(x)
+ if (x < 1)
+ fun_l7_n279(x)
+ else
+ fun_l7_n695(x)
+ end
+end
+
+def fun_l6_n211(x)
+ if (x < 1)
+ fun_l7_n981(x)
+ else
+ fun_l7_n946(x)
+ end
+end
+
+def fun_l6_n212(x)
+ if (x < 1)
+ fun_l7_n885(x)
+ else
+ fun_l7_n752(x)
+ end
+end
+
+def fun_l6_n213(x)
+ if (x < 1)
+ fun_l7_n238(x)
+ else
+ fun_l7_n322(x)
+ end
+end
+
+def fun_l6_n214(x)
+ if (x < 1)
+ fun_l7_n832(x)
+ else
+ fun_l7_n714(x)
+ end
+end
+
+def fun_l6_n215(x)
+ if (x < 1)
+ fun_l7_n369(x)
+ else
+ fun_l7_n793(x)
+ end
+end
+
+def fun_l6_n216(x)
+ if (x < 1)
+ fun_l7_n897(x)
+ else
+ fun_l7_n22(x)
+ end
+end
+
+def fun_l6_n217(x)
+ if (x < 1)
+ fun_l7_n94(x)
+ else
+ fun_l7_n93(x)
+ end
+end
+
+def fun_l6_n218(x)
+ if (x < 1)
+ fun_l7_n638(x)
+ else
+ fun_l7_n267(x)
+ end
+end
+
+def fun_l6_n219(x)
+ if (x < 1)
+ fun_l7_n254(x)
+ else
+ fun_l7_n162(x)
+ end
+end
+
+def fun_l6_n220(x)
+ if (x < 1)
+ fun_l7_n969(x)
+ else
+ fun_l7_n371(x)
+ end
+end
+
+def fun_l6_n221(x)
+ if (x < 1)
+ fun_l7_n692(x)
+ else
+ fun_l7_n421(x)
+ end
+end
+
+def fun_l6_n222(x)
+ if (x < 1)
+ fun_l7_n312(x)
+ else
+ fun_l7_n475(x)
+ end
+end
+
+def fun_l6_n223(x)
+ if (x < 1)
+ fun_l7_n566(x)
+ else
+ fun_l7_n497(x)
+ end
+end
+
+def fun_l6_n224(x)
+ if (x < 1)
+ fun_l7_n560(x)
+ else
+ fun_l7_n60(x)
+ end
+end
+
+def fun_l6_n225(x)
+ if (x < 1)
+ fun_l7_n484(x)
+ else
+ fun_l7_n602(x)
+ end
+end
+
+def fun_l6_n226(x)
+ if (x < 1)
+ fun_l7_n399(x)
+ else
+ fun_l7_n614(x)
+ end
+end
+
+def fun_l6_n227(x)
+ if (x < 1)
+ fun_l7_n344(x)
+ else
+ fun_l7_n701(x)
+ end
+end
+
+def fun_l6_n228(x)
+ if (x < 1)
+ fun_l7_n840(x)
+ else
+ fun_l7_n211(x)
+ end
+end
+
+def fun_l6_n229(x)
+ if (x < 1)
+ fun_l7_n423(x)
+ else
+ fun_l7_n51(x)
+ end
+end
+
+def fun_l6_n230(x)
+ if (x < 1)
+ fun_l7_n978(x)
+ else
+ fun_l7_n334(x)
+ end
+end
+
+def fun_l6_n231(x)
+ if (x < 1)
+ fun_l7_n136(x)
+ else
+ fun_l7_n296(x)
+ end
+end
+
+def fun_l6_n232(x)
+ if (x < 1)
+ fun_l7_n24(x)
+ else
+ fun_l7_n282(x)
+ end
+end
+
+def fun_l6_n233(x)
+ if (x < 1)
+ fun_l7_n803(x)
+ else
+ fun_l7_n623(x)
+ end
+end
+
+def fun_l6_n234(x)
+ if (x < 1)
+ fun_l7_n720(x)
+ else
+ fun_l7_n492(x)
+ end
+end
+
+def fun_l6_n235(x)
+ if (x < 1)
+ fun_l7_n627(x)
+ else
+ fun_l7_n260(x)
+ end
+end
+
+def fun_l6_n236(x)
+ if (x < 1)
+ fun_l7_n460(x)
+ else
+ fun_l7_n693(x)
+ end
+end
+
+def fun_l6_n237(x)
+ if (x < 1)
+ fun_l7_n635(x)
+ else
+ fun_l7_n745(x)
+ end
+end
+
+def fun_l6_n238(x)
+ if (x < 1)
+ fun_l7_n76(x)
+ else
+ fun_l7_n283(x)
+ end
+end
+
+def fun_l6_n239(x)
+ if (x < 1)
+ fun_l7_n183(x)
+ else
+ fun_l7_n515(x)
+ end
+end
+
+def fun_l6_n240(x)
+ if (x < 1)
+ fun_l7_n266(x)
+ else
+ fun_l7_n34(x)
+ end
+end
+
+def fun_l6_n241(x)
+ if (x < 1)
+ fun_l7_n480(x)
+ else
+ fun_l7_n868(x)
+ end
+end
+
+def fun_l6_n242(x)
+ if (x < 1)
+ fun_l7_n998(x)
+ else
+ fun_l7_n669(x)
+ end
+end
+
+def fun_l6_n243(x)
+ if (x < 1)
+ fun_l7_n414(x)
+ else
+ fun_l7_n161(x)
+ end
+end
+
+def fun_l6_n244(x)
+ if (x < 1)
+ fun_l7_n104(x)
+ else
+ fun_l7_n659(x)
+ end
+end
+
+def fun_l6_n245(x)
+ if (x < 1)
+ fun_l7_n881(x)
+ else
+ fun_l7_n229(x)
+ end
+end
+
+def fun_l6_n246(x)
+ if (x < 1)
+ fun_l7_n328(x)
+ else
+ fun_l7_n935(x)
+ end
+end
+
+def fun_l6_n247(x)
+ if (x < 1)
+ fun_l7_n433(x)
+ else
+ fun_l7_n565(x)
+ end
+end
+
+def fun_l6_n248(x)
+ if (x < 1)
+ fun_l7_n161(x)
+ else
+ fun_l7_n760(x)
+ end
+end
+
+def fun_l6_n249(x)
+ if (x < 1)
+ fun_l7_n115(x)
+ else
+ fun_l7_n594(x)
+ end
+end
+
+def fun_l6_n250(x)
+ if (x < 1)
+ fun_l7_n350(x)
+ else
+ fun_l7_n310(x)
+ end
+end
+
+def fun_l6_n251(x)
+ if (x < 1)
+ fun_l7_n920(x)
+ else
+ fun_l7_n51(x)
+ end
+end
+
+def fun_l6_n252(x)
+ if (x < 1)
+ fun_l7_n132(x)
+ else
+ fun_l7_n492(x)
+ end
+end
+
+def fun_l6_n253(x)
+ if (x < 1)
+ fun_l7_n618(x)
+ else
+ fun_l7_n325(x)
+ end
+end
+
+def fun_l6_n254(x)
+ if (x < 1)
+ fun_l7_n682(x)
+ else
+ fun_l7_n840(x)
+ end
+end
+
+def fun_l6_n255(x)
+ if (x < 1)
+ fun_l7_n462(x)
+ else
+ fun_l7_n780(x)
+ end
+end
+
+def fun_l6_n256(x)
+ if (x < 1)
+ fun_l7_n712(x)
+ else
+ fun_l7_n995(x)
+ end
+end
+
+def fun_l6_n257(x)
+ if (x < 1)
+ fun_l7_n111(x)
+ else
+ fun_l7_n121(x)
+ end
+end
+
+def fun_l6_n258(x)
+ if (x < 1)
+ fun_l7_n255(x)
+ else
+ fun_l7_n384(x)
+ end
+end
+
+def fun_l6_n259(x)
+ if (x < 1)
+ fun_l7_n610(x)
+ else
+ fun_l7_n555(x)
+ end
+end
+
+def fun_l6_n260(x)
+ if (x < 1)
+ fun_l7_n778(x)
+ else
+ fun_l7_n454(x)
+ end
+end
+
+def fun_l6_n261(x)
+ if (x < 1)
+ fun_l7_n376(x)
+ else
+ fun_l7_n892(x)
+ end
+end
+
+def fun_l6_n262(x)
+ if (x < 1)
+ fun_l7_n454(x)
+ else
+ fun_l7_n468(x)
+ end
+end
+
+def fun_l6_n263(x)
+ if (x < 1)
+ fun_l7_n708(x)
+ else
+ fun_l7_n368(x)
+ end
+end
+
+def fun_l6_n264(x)
+ if (x < 1)
+ fun_l7_n517(x)
+ else
+ fun_l7_n299(x)
+ end
+end
+
+def fun_l6_n265(x)
+ if (x < 1)
+ fun_l7_n987(x)
+ else
+ fun_l7_n318(x)
+ end
+end
+
+def fun_l6_n266(x)
+ if (x < 1)
+ fun_l7_n372(x)
+ else
+ fun_l7_n560(x)
+ end
+end
+
+def fun_l6_n267(x)
+ if (x < 1)
+ fun_l7_n493(x)
+ else
+ fun_l7_n288(x)
+ end
+end
+
+def fun_l6_n268(x)
+ if (x < 1)
+ fun_l7_n278(x)
+ else
+ fun_l7_n10(x)
+ end
+end
+
+def fun_l6_n269(x)
+ if (x < 1)
+ fun_l7_n417(x)
+ else
+ fun_l7_n703(x)
+ end
+end
+
+def fun_l6_n270(x)
+ if (x < 1)
+ fun_l7_n410(x)
+ else
+ fun_l7_n91(x)
+ end
+end
+
+def fun_l6_n271(x)
+ if (x < 1)
+ fun_l7_n281(x)
+ else
+ fun_l7_n447(x)
+ end
+end
+
+def fun_l6_n272(x)
+ if (x < 1)
+ fun_l7_n263(x)
+ else
+ fun_l7_n374(x)
+ end
+end
+
+def fun_l6_n273(x)
+ if (x < 1)
+ fun_l7_n622(x)
+ else
+ fun_l7_n310(x)
+ end
+end
+
+def fun_l6_n274(x)
+ if (x < 1)
+ fun_l7_n176(x)
+ else
+ fun_l7_n227(x)
+ end
+end
+
+def fun_l6_n275(x)
+ if (x < 1)
+ fun_l7_n848(x)
+ else
+ fun_l7_n416(x)
+ end
+end
+
+def fun_l6_n276(x)
+ if (x < 1)
+ fun_l7_n998(x)
+ else
+ fun_l7_n969(x)
+ end
+end
+
+def fun_l6_n277(x)
+ if (x < 1)
+ fun_l7_n356(x)
+ else
+ fun_l7_n722(x)
+ end
+end
+
+def fun_l6_n278(x)
+ if (x < 1)
+ fun_l7_n888(x)
+ else
+ fun_l7_n156(x)
+ end
+end
+
+def fun_l6_n279(x)
+ if (x < 1)
+ fun_l7_n779(x)
+ else
+ fun_l7_n123(x)
+ end
+end
+
+def fun_l6_n280(x)
+ if (x < 1)
+ fun_l7_n393(x)
+ else
+ fun_l7_n765(x)
+ end
+end
+
+def fun_l6_n281(x)
+ if (x < 1)
+ fun_l7_n257(x)
+ else
+ fun_l7_n277(x)
+ end
+end
+
+def fun_l6_n282(x)
+ if (x < 1)
+ fun_l7_n780(x)
+ else
+ fun_l7_n643(x)
+ end
+end
+
+def fun_l6_n283(x)
+ if (x < 1)
+ fun_l7_n63(x)
+ else
+ fun_l7_n449(x)
+ end
+end
+
+def fun_l6_n284(x)
+ if (x < 1)
+ fun_l7_n200(x)
+ else
+ fun_l7_n806(x)
+ end
+end
+
+def fun_l6_n285(x)
+ if (x < 1)
+ fun_l7_n575(x)
+ else
+ fun_l7_n409(x)
+ end
+end
+
+def fun_l6_n286(x)
+ if (x < 1)
+ fun_l7_n377(x)
+ else
+ fun_l7_n456(x)
+ end
+end
+
+def fun_l6_n287(x)
+ if (x < 1)
+ fun_l7_n519(x)
+ else
+ fun_l7_n473(x)
+ end
+end
+
+def fun_l6_n288(x)
+ if (x < 1)
+ fun_l7_n525(x)
+ else
+ fun_l7_n45(x)
+ end
+end
+
+def fun_l6_n289(x)
+ if (x < 1)
+ fun_l7_n678(x)
+ else
+ fun_l7_n910(x)
+ end
+end
+
+def fun_l6_n290(x)
+ if (x < 1)
+ fun_l7_n628(x)
+ else
+ fun_l7_n939(x)
+ end
+end
+
+def fun_l6_n291(x)
+ if (x < 1)
+ fun_l7_n967(x)
+ else
+ fun_l7_n927(x)
+ end
+end
+
+def fun_l6_n292(x)
+ if (x < 1)
+ fun_l7_n634(x)
+ else
+ fun_l7_n184(x)
+ end
+end
+
+def fun_l6_n293(x)
+ if (x < 1)
+ fun_l7_n857(x)
+ else
+ fun_l7_n625(x)
+ end
+end
+
+def fun_l6_n294(x)
+ if (x < 1)
+ fun_l7_n105(x)
+ else
+ fun_l7_n46(x)
+ end
+end
+
+def fun_l6_n295(x)
+ if (x < 1)
+ fun_l7_n642(x)
+ else
+ fun_l7_n566(x)
+ end
+end
+
+def fun_l6_n296(x)
+ if (x < 1)
+ fun_l7_n173(x)
+ else
+ fun_l7_n619(x)
+ end
+end
+
+def fun_l6_n297(x)
+ if (x < 1)
+ fun_l7_n257(x)
+ else
+ fun_l7_n485(x)
+ end
+end
+
+def fun_l6_n298(x)
+ if (x < 1)
+ fun_l7_n447(x)
+ else
+ fun_l7_n808(x)
+ end
+end
+
+def fun_l6_n299(x)
+ if (x < 1)
+ fun_l7_n838(x)
+ else
+ fun_l7_n856(x)
+ end
+end
+
+def fun_l6_n300(x)
+ if (x < 1)
+ fun_l7_n893(x)
+ else
+ fun_l7_n99(x)
+ end
+end
+
+def fun_l6_n301(x)
+ if (x < 1)
+ fun_l7_n180(x)
+ else
+ fun_l7_n126(x)
+ end
+end
+
+def fun_l6_n302(x)
+ if (x < 1)
+ fun_l7_n62(x)
+ else
+ fun_l7_n266(x)
+ end
+end
+
+def fun_l6_n303(x)
+ if (x < 1)
+ fun_l7_n709(x)
+ else
+ fun_l7_n196(x)
+ end
+end
+
+def fun_l6_n304(x)
+ if (x < 1)
+ fun_l7_n408(x)
+ else
+ fun_l7_n730(x)
+ end
+end
+
+def fun_l6_n305(x)
+ if (x < 1)
+ fun_l7_n736(x)
+ else
+ fun_l7_n673(x)
+ end
+end
+
+def fun_l6_n306(x)
+ if (x < 1)
+ fun_l7_n734(x)
+ else
+ fun_l7_n519(x)
+ end
+end
+
+def fun_l6_n307(x)
+ if (x < 1)
+ fun_l7_n629(x)
+ else
+ fun_l7_n670(x)
+ end
+end
+
+def fun_l6_n308(x)
+ if (x < 1)
+ fun_l7_n839(x)
+ else
+ fun_l7_n191(x)
+ end
+end
+
+def fun_l6_n309(x)
+ if (x < 1)
+ fun_l7_n123(x)
+ else
+ fun_l7_n553(x)
+ end
+end
+
+def fun_l6_n310(x)
+ if (x < 1)
+ fun_l7_n812(x)
+ else
+ fun_l7_n815(x)
+ end
+end
+
+def fun_l6_n311(x)
+ if (x < 1)
+ fun_l7_n860(x)
+ else
+ fun_l7_n519(x)
+ end
+end
+
+def fun_l6_n312(x)
+ if (x < 1)
+ fun_l7_n181(x)
+ else
+ fun_l7_n674(x)
+ end
+end
+
+def fun_l6_n313(x)
+ if (x < 1)
+ fun_l7_n654(x)
+ else
+ fun_l7_n500(x)
+ end
+end
+
+def fun_l6_n314(x)
+ if (x < 1)
+ fun_l7_n690(x)
+ else
+ fun_l7_n136(x)
+ end
+end
+
+def fun_l6_n315(x)
+ if (x < 1)
+ fun_l7_n944(x)
+ else
+ fun_l7_n956(x)
+ end
+end
+
+def fun_l6_n316(x)
+ if (x < 1)
+ fun_l7_n471(x)
+ else
+ fun_l7_n245(x)
+ end
+end
+
+def fun_l6_n317(x)
+ if (x < 1)
+ fun_l7_n520(x)
+ else
+ fun_l7_n919(x)
+ end
+end
+
+def fun_l6_n318(x)
+ if (x < 1)
+ fun_l7_n843(x)
+ else
+ fun_l7_n793(x)
+ end
+end
+
+def fun_l6_n319(x)
+ if (x < 1)
+ fun_l7_n765(x)
+ else
+ fun_l7_n363(x)
+ end
+end
+
+def fun_l6_n320(x)
+ if (x < 1)
+ fun_l7_n483(x)
+ else
+ fun_l7_n439(x)
+ end
+end
+
+def fun_l6_n321(x)
+ if (x < 1)
+ fun_l7_n232(x)
+ else
+ fun_l7_n921(x)
+ end
+end
+
+def fun_l6_n322(x)
+ if (x < 1)
+ fun_l7_n398(x)
+ else
+ fun_l7_n862(x)
+ end
+end
+
+def fun_l6_n323(x)
+ if (x < 1)
+ fun_l7_n550(x)
+ else
+ fun_l7_n84(x)
+ end
+end
+
+def fun_l6_n324(x)
+ if (x < 1)
+ fun_l7_n788(x)
+ else
+ fun_l7_n512(x)
+ end
+end
+
+def fun_l6_n325(x)
+ if (x < 1)
+ fun_l7_n512(x)
+ else
+ fun_l7_n303(x)
+ end
+end
+
+def fun_l6_n326(x)
+ if (x < 1)
+ fun_l7_n86(x)
+ else
+ fun_l7_n555(x)
+ end
+end
+
+def fun_l6_n327(x)
+ if (x < 1)
+ fun_l7_n857(x)
+ else
+ fun_l7_n751(x)
+ end
+end
+
+def fun_l6_n328(x)
+ if (x < 1)
+ fun_l7_n341(x)
+ else
+ fun_l7_n208(x)
+ end
+end
+
+def fun_l6_n329(x)
+ if (x < 1)
+ fun_l7_n707(x)
+ else
+ fun_l7_n371(x)
+ end
+end
+
+def fun_l6_n330(x)
+ if (x < 1)
+ fun_l7_n217(x)
+ else
+ fun_l7_n604(x)
+ end
+end
+
+def fun_l6_n331(x)
+ if (x < 1)
+ fun_l7_n607(x)
+ else
+ fun_l7_n471(x)
+ end
+end
+
+def fun_l6_n332(x)
+ if (x < 1)
+ fun_l7_n818(x)
+ else
+ fun_l7_n787(x)
+ end
+end
+
+def fun_l6_n333(x)
+ if (x < 1)
+ fun_l7_n28(x)
+ else
+ fun_l7_n220(x)
+ end
+end
+
+def fun_l6_n334(x)
+ if (x < 1)
+ fun_l7_n666(x)
+ else
+ fun_l7_n995(x)
+ end
+end
+
+def fun_l6_n335(x)
+ if (x < 1)
+ fun_l7_n3(x)
+ else
+ fun_l7_n970(x)
+ end
+end
+
+def fun_l6_n336(x)
+ if (x < 1)
+ fun_l7_n977(x)
+ else
+ fun_l7_n77(x)
+ end
+end
+
+def fun_l6_n337(x)
+ if (x < 1)
+ fun_l7_n54(x)
+ else
+ fun_l7_n814(x)
+ end
+end
+
+def fun_l6_n338(x)
+ if (x < 1)
+ fun_l7_n129(x)
+ else
+ fun_l7_n624(x)
+ end
+end
+
+def fun_l6_n339(x)
+ if (x < 1)
+ fun_l7_n866(x)
+ else
+ fun_l7_n821(x)
+ end
+end
+
+def fun_l6_n340(x)
+ if (x < 1)
+ fun_l7_n912(x)
+ else
+ fun_l7_n24(x)
+ end
+end
+
+def fun_l6_n341(x)
+ if (x < 1)
+ fun_l7_n684(x)
+ else
+ fun_l7_n610(x)
+ end
+end
+
+def fun_l6_n342(x)
+ if (x < 1)
+ fun_l7_n816(x)
+ else
+ fun_l7_n826(x)
+ end
+end
+
+def fun_l6_n343(x)
+ if (x < 1)
+ fun_l7_n479(x)
+ else
+ fun_l7_n444(x)
+ end
+end
+
+def fun_l6_n344(x)
+ if (x < 1)
+ fun_l7_n51(x)
+ else
+ fun_l7_n731(x)
+ end
+end
+
+def fun_l6_n345(x)
+ if (x < 1)
+ fun_l7_n690(x)
+ else
+ fun_l7_n631(x)
+ end
+end
+
+def fun_l6_n346(x)
+ if (x < 1)
+ fun_l7_n254(x)
+ else
+ fun_l7_n353(x)
+ end
+end
+
+def fun_l6_n347(x)
+ if (x < 1)
+ fun_l7_n905(x)
+ else
+ fun_l7_n422(x)
+ end
+end
+
+def fun_l6_n348(x)
+ if (x < 1)
+ fun_l7_n249(x)
+ else
+ fun_l7_n200(x)
+ end
+end
+
+def fun_l6_n349(x)
+ if (x < 1)
+ fun_l7_n11(x)
+ else
+ fun_l7_n550(x)
+ end
+end
+
+def fun_l6_n350(x)
+ if (x < 1)
+ fun_l7_n818(x)
+ else
+ fun_l7_n444(x)
+ end
+end
+
+def fun_l6_n351(x)
+ if (x < 1)
+ fun_l7_n422(x)
+ else
+ fun_l7_n242(x)
+ end
+end
+
+def fun_l6_n352(x)
+ if (x < 1)
+ fun_l7_n653(x)
+ else
+ fun_l7_n912(x)
+ end
+end
+
+def fun_l6_n353(x)
+ if (x < 1)
+ fun_l7_n605(x)
+ else
+ fun_l7_n129(x)
+ end
+end
+
+def fun_l6_n354(x)
+ if (x < 1)
+ fun_l7_n622(x)
+ else
+ fun_l7_n172(x)
+ end
+end
+
+def fun_l6_n355(x)
+ if (x < 1)
+ fun_l7_n568(x)
+ else
+ fun_l7_n26(x)
+ end
+end
+
+def fun_l6_n356(x)
+ if (x < 1)
+ fun_l7_n777(x)
+ else
+ fun_l7_n818(x)
+ end
+end
+
+def fun_l6_n357(x)
+ if (x < 1)
+ fun_l7_n807(x)
+ else
+ fun_l7_n642(x)
+ end
+end
+
+def fun_l6_n358(x)
+ if (x < 1)
+ fun_l7_n745(x)
+ else
+ fun_l7_n866(x)
+ end
+end
+
+def fun_l6_n359(x)
+ if (x < 1)
+ fun_l7_n603(x)
+ else
+ fun_l7_n42(x)
+ end
+end
+
+def fun_l6_n360(x)
+ if (x < 1)
+ fun_l7_n818(x)
+ else
+ fun_l7_n203(x)
+ end
+end
+
+def fun_l6_n361(x)
+ if (x < 1)
+ fun_l7_n451(x)
+ else
+ fun_l7_n719(x)
+ end
+end
+
+def fun_l6_n362(x)
+ if (x < 1)
+ fun_l7_n31(x)
+ else
+ fun_l7_n148(x)
+ end
+end
+
+def fun_l6_n363(x)
+ if (x < 1)
+ fun_l7_n148(x)
+ else
+ fun_l7_n292(x)
+ end
+end
+
+def fun_l6_n364(x)
+ if (x < 1)
+ fun_l7_n175(x)
+ else
+ fun_l7_n849(x)
+ end
+end
+
+def fun_l6_n365(x)
+ if (x < 1)
+ fun_l7_n414(x)
+ else
+ fun_l7_n57(x)
+ end
+end
+
+def fun_l6_n366(x)
+ if (x < 1)
+ fun_l7_n771(x)
+ else
+ fun_l7_n625(x)
+ end
+end
+
+def fun_l6_n367(x)
+ if (x < 1)
+ fun_l7_n232(x)
+ else
+ fun_l7_n108(x)
+ end
+end
+
+def fun_l6_n368(x)
+ if (x < 1)
+ fun_l7_n123(x)
+ else
+ fun_l7_n413(x)
+ end
+end
+
+def fun_l6_n369(x)
+ if (x < 1)
+ fun_l7_n587(x)
+ else
+ fun_l7_n876(x)
+ end
+end
+
+def fun_l6_n370(x)
+ if (x < 1)
+ fun_l7_n750(x)
+ else
+ fun_l7_n531(x)
+ end
+end
+
+def fun_l6_n371(x)
+ if (x < 1)
+ fun_l7_n55(x)
+ else
+ fun_l7_n859(x)
+ end
+end
+
+def fun_l6_n372(x)
+ if (x < 1)
+ fun_l7_n848(x)
+ else
+ fun_l7_n272(x)
+ end
+end
+
+def fun_l6_n373(x)
+ if (x < 1)
+ fun_l7_n480(x)
+ else
+ fun_l7_n976(x)
+ end
+end
+
+def fun_l6_n374(x)
+ if (x < 1)
+ fun_l7_n298(x)
+ else
+ fun_l7_n844(x)
+ end
+end
+
+def fun_l6_n375(x)
+ if (x < 1)
+ fun_l7_n564(x)
+ else
+ fun_l7_n960(x)
+ end
+end
+
+def fun_l6_n376(x)
+ if (x < 1)
+ fun_l7_n684(x)
+ else
+ fun_l7_n181(x)
+ end
+end
+
+def fun_l6_n377(x)
+ if (x < 1)
+ fun_l7_n153(x)
+ else
+ fun_l7_n21(x)
+ end
+end
+
+def fun_l6_n378(x)
+ if (x < 1)
+ fun_l7_n377(x)
+ else
+ fun_l7_n761(x)
+ end
+end
+
+def fun_l6_n379(x)
+ if (x < 1)
+ fun_l7_n737(x)
+ else
+ fun_l7_n605(x)
+ end
+end
+
+def fun_l6_n380(x)
+ if (x < 1)
+ fun_l7_n536(x)
+ else
+ fun_l7_n143(x)
+ end
+end
+
+def fun_l6_n381(x)
+ if (x < 1)
+ fun_l7_n314(x)
+ else
+ fun_l7_n999(x)
+ end
+end
+
+def fun_l6_n382(x)
+ if (x < 1)
+ fun_l7_n995(x)
+ else
+ fun_l7_n564(x)
+ end
+end
+
+def fun_l6_n383(x)
+ if (x < 1)
+ fun_l7_n772(x)
+ else
+ fun_l7_n520(x)
+ end
+end
+
+def fun_l6_n384(x)
+ if (x < 1)
+ fun_l7_n250(x)
+ else
+ fun_l7_n142(x)
+ end
+end
+
+def fun_l6_n385(x)
+ if (x < 1)
+ fun_l7_n993(x)
+ else
+ fun_l7_n987(x)
+ end
+end
+
+def fun_l6_n386(x)
+ if (x < 1)
+ fun_l7_n717(x)
+ else
+ fun_l7_n674(x)
+ end
+end
+
+def fun_l6_n387(x)
+ if (x < 1)
+ fun_l7_n585(x)
+ else
+ fun_l7_n102(x)
+ end
+end
+
+def fun_l6_n388(x)
+ if (x < 1)
+ fun_l7_n779(x)
+ else
+ fun_l7_n110(x)
+ end
+end
+
+def fun_l6_n389(x)
+ if (x < 1)
+ fun_l7_n815(x)
+ else
+ fun_l7_n194(x)
+ end
+end
+
+def fun_l6_n390(x)
+ if (x < 1)
+ fun_l7_n261(x)
+ else
+ fun_l7_n30(x)
+ end
+end
+
+def fun_l6_n391(x)
+ if (x < 1)
+ fun_l7_n746(x)
+ else
+ fun_l7_n207(x)
+ end
+end
+
+def fun_l6_n392(x)
+ if (x < 1)
+ fun_l7_n866(x)
+ else
+ fun_l7_n862(x)
+ end
+end
+
+def fun_l6_n393(x)
+ if (x < 1)
+ fun_l7_n47(x)
+ else
+ fun_l7_n692(x)
+ end
+end
+
+def fun_l6_n394(x)
+ if (x < 1)
+ fun_l7_n140(x)
+ else
+ fun_l7_n104(x)
+ end
+end
+
+def fun_l6_n395(x)
+ if (x < 1)
+ fun_l7_n170(x)
+ else
+ fun_l7_n93(x)
+ end
+end
+
+def fun_l6_n396(x)
+ if (x < 1)
+ fun_l7_n184(x)
+ else
+ fun_l7_n218(x)
+ end
+end
+
+def fun_l6_n397(x)
+ if (x < 1)
+ fun_l7_n268(x)
+ else
+ fun_l7_n278(x)
+ end
+end
+
+def fun_l6_n398(x)
+ if (x < 1)
+ fun_l7_n859(x)
+ else
+ fun_l7_n888(x)
+ end
+end
+
+def fun_l6_n399(x)
+ if (x < 1)
+ fun_l7_n540(x)
+ else
+ fun_l7_n218(x)
+ end
+end
+
+def fun_l6_n400(x)
+ if (x < 1)
+ fun_l7_n148(x)
+ else
+ fun_l7_n220(x)
+ end
+end
+
+def fun_l6_n401(x)
+ if (x < 1)
+ fun_l7_n169(x)
+ else
+ fun_l7_n310(x)
+ end
+end
+
+def fun_l6_n402(x)
+ if (x < 1)
+ fun_l7_n256(x)
+ else
+ fun_l7_n336(x)
+ end
+end
+
+def fun_l6_n403(x)
+ if (x < 1)
+ fun_l7_n257(x)
+ else
+ fun_l7_n536(x)
+ end
+end
+
+def fun_l6_n404(x)
+ if (x < 1)
+ fun_l7_n47(x)
+ else
+ fun_l7_n714(x)
+ end
+end
+
+def fun_l6_n405(x)
+ if (x < 1)
+ fun_l7_n913(x)
+ else
+ fun_l7_n705(x)
+ end
+end
+
+def fun_l6_n406(x)
+ if (x < 1)
+ fun_l7_n816(x)
+ else
+ fun_l7_n168(x)
+ end
+end
+
+def fun_l6_n407(x)
+ if (x < 1)
+ fun_l7_n506(x)
+ else
+ fun_l7_n772(x)
+ end
+end
+
+def fun_l6_n408(x)
+ if (x < 1)
+ fun_l7_n983(x)
+ else
+ fun_l7_n973(x)
+ end
+end
+
+def fun_l6_n409(x)
+ if (x < 1)
+ fun_l7_n752(x)
+ else
+ fun_l7_n543(x)
+ end
+end
+
+def fun_l6_n410(x)
+ if (x < 1)
+ fun_l7_n580(x)
+ else
+ fun_l7_n265(x)
+ end
+end
+
+def fun_l6_n411(x)
+ if (x < 1)
+ fun_l7_n744(x)
+ else
+ fun_l7_n736(x)
+ end
+end
+
+def fun_l6_n412(x)
+ if (x < 1)
+ fun_l7_n950(x)
+ else
+ fun_l7_n5(x)
+ end
+end
+
+def fun_l6_n413(x)
+ if (x < 1)
+ fun_l7_n734(x)
+ else
+ fun_l7_n151(x)
+ end
+end
+
+def fun_l6_n414(x)
+ if (x < 1)
+ fun_l7_n907(x)
+ else
+ fun_l7_n113(x)
+ end
+end
+
+def fun_l6_n415(x)
+ if (x < 1)
+ fun_l7_n621(x)
+ else
+ fun_l7_n272(x)
+ end
+end
+
+def fun_l6_n416(x)
+ if (x < 1)
+ fun_l7_n598(x)
+ else
+ fun_l7_n872(x)
+ end
+end
+
+def fun_l6_n417(x)
+ if (x < 1)
+ fun_l7_n811(x)
+ else
+ fun_l7_n734(x)
+ end
+end
+
+def fun_l6_n418(x)
+ if (x < 1)
+ fun_l7_n18(x)
+ else
+ fun_l7_n405(x)
+ end
+end
+
+def fun_l6_n419(x)
+ if (x < 1)
+ fun_l7_n89(x)
+ else
+ fun_l7_n153(x)
+ end
+end
+
+def fun_l6_n420(x)
+ if (x < 1)
+ fun_l7_n438(x)
+ else
+ fun_l7_n452(x)
+ end
+end
+
+def fun_l6_n421(x)
+ if (x < 1)
+ fun_l7_n601(x)
+ else
+ fun_l7_n777(x)
+ end
+end
+
+def fun_l6_n422(x)
+ if (x < 1)
+ fun_l7_n202(x)
+ else
+ fun_l7_n368(x)
+ end
+end
+
+def fun_l6_n423(x)
+ if (x < 1)
+ fun_l7_n636(x)
+ else
+ fun_l7_n137(x)
+ end
+end
+
+def fun_l6_n424(x)
+ if (x < 1)
+ fun_l7_n222(x)
+ else
+ fun_l7_n838(x)
+ end
+end
+
+def fun_l6_n425(x)
+ if (x < 1)
+ fun_l7_n388(x)
+ else
+ fun_l7_n175(x)
+ end
+end
+
+def fun_l6_n426(x)
+ if (x < 1)
+ fun_l7_n629(x)
+ else
+ fun_l7_n376(x)
+ end
+end
+
+def fun_l6_n427(x)
+ if (x < 1)
+ fun_l7_n293(x)
+ else
+ fun_l7_n517(x)
+ end
+end
+
+def fun_l6_n428(x)
+ if (x < 1)
+ fun_l7_n859(x)
+ else
+ fun_l7_n129(x)
+ end
+end
+
+def fun_l6_n429(x)
+ if (x < 1)
+ fun_l7_n854(x)
+ else
+ fun_l7_n647(x)
+ end
+end
+
+def fun_l6_n430(x)
+ if (x < 1)
+ fun_l7_n117(x)
+ else
+ fun_l7_n291(x)
+ end
+end
+
+def fun_l6_n431(x)
+ if (x < 1)
+ fun_l7_n505(x)
+ else
+ fun_l7_n938(x)
+ end
+end
+
+def fun_l6_n432(x)
+ if (x < 1)
+ fun_l7_n536(x)
+ else
+ fun_l7_n303(x)
+ end
+end
+
+def fun_l6_n433(x)
+ if (x < 1)
+ fun_l7_n443(x)
+ else
+ fun_l7_n945(x)
+ end
+end
+
+def fun_l6_n434(x)
+ if (x < 1)
+ fun_l7_n74(x)
+ else
+ fun_l7_n594(x)
+ end
+end
+
+def fun_l6_n435(x)
+ if (x < 1)
+ fun_l7_n273(x)
+ else
+ fun_l7_n704(x)
+ end
+end
+
+def fun_l6_n436(x)
+ if (x < 1)
+ fun_l7_n451(x)
+ else
+ fun_l7_n371(x)
+ end
+end
+
+def fun_l6_n437(x)
+ if (x < 1)
+ fun_l7_n628(x)
+ else
+ fun_l7_n963(x)
+ end
+end
+
+def fun_l6_n438(x)
+ if (x < 1)
+ fun_l7_n361(x)
+ else
+ fun_l7_n506(x)
+ end
+end
+
+def fun_l6_n439(x)
+ if (x < 1)
+ fun_l7_n8(x)
+ else
+ fun_l7_n721(x)
+ end
+end
+
+def fun_l6_n440(x)
+ if (x < 1)
+ fun_l7_n728(x)
+ else
+ fun_l7_n372(x)
+ end
+end
+
+def fun_l6_n441(x)
+ if (x < 1)
+ fun_l7_n988(x)
+ else
+ fun_l7_n323(x)
+ end
+end
+
+def fun_l6_n442(x)
+ if (x < 1)
+ fun_l7_n5(x)
+ else
+ fun_l7_n56(x)
+ end
+end
+
+def fun_l6_n443(x)
+ if (x < 1)
+ fun_l7_n553(x)
+ else
+ fun_l7_n776(x)
+ end
+end
+
+def fun_l6_n444(x)
+ if (x < 1)
+ fun_l7_n194(x)
+ else
+ fun_l7_n101(x)
+ end
+end
+
+def fun_l6_n445(x)
+ if (x < 1)
+ fun_l7_n613(x)
+ else
+ fun_l7_n977(x)
+ end
+end
+
+def fun_l6_n446(x)
+ if (x < 1)
+ fun_l7_n23(x)
+ else
+ fun_l7_n311(x)
+ end
+end
+
+def fun_l6_n447(x)
+ if (x < 1)
+ fun_l7_n686(x)
+ else
+ fun_l7_n8(x)
+ end
+end
+
+def fun_l6_n448(x)
+ if (x < 1)
+ fun_l7_n812(x)
+ else
+ fun_l7_n229(x)
+ end
+end
+
+def fun_l6_n449(x)
+ if (x < 1)
+ fun_l7_n222(x)
+ else
+ fun_l7_n620(x)
+ end
+end
+
+def fun_l6_n450(x)
+ if (x < 1)
+ fun_l7_n599(x)
+ else
+ fun_l7_n468(x)
+ end
+end
+
+def fun_l6_n451(x)
+ if (x < 1)
+ fun_l7_n347(x)
+ else
+ fun_l7_n504(x)
+ end
+end
+
+def fun_l6_n452(x)
+ if (x < 1)
+ fun_l7_n95(x)
+ else
+ fun_l7_n482(x)
+ end
+end
+
+def fun_l6_n453(x)
+ if (x < 1)
+ fun_l7_n217(x)
+ else
+ fun_l7_n419(x)
+ end
+end
+
+def fun_l6_n454(x)
+ if (x < 1)
+ fun_l7_n28(x)
+ else
+ fun_l7_n609(x)
+ end
+end
+
+def fun_l6_n455(x)
+ if (x < 1)
+ fun_l7_n932(x)
+ else
+ fun_l7_n744(x)
+ end
+end
+
+def fun_l6_n456(x)
+ if (x < 1)
+ fun_l7_n901(x)
+ else
+ fun_l7_n882(x)
+ end
+end
+
+def fun_l6_n457(x)
+ if (x < 1)
+ fun_l7_n368(x)
+ else
+ fun_l7_n441(x)
+ end
+end
+
+def fun_l6_n458(x)
+ if (x < 1)
+ fun_l7_n49(x)
+ else
+ fun_l7_n135(x)
+ end
+end
+
+def fun_l6_n459(x)
+ if (x < 1)
+ fun_l7_n228(x)
+ else
+ fun_l7_n899(x)
+ end
+end
+
+def fun_l6_n460(x)
+ if (x < 1)
+ fun_l7_n90(x)
+ else
+ fun_l7_n190(x)
+ end
+end
+
+def fun_l6_n461(x)
+ if (x < 1)
+ fun_l7_n892(x)
+ else
+ fun_l7_n670(x)
+ end
+end
+
+def fun_l6_n462(x)
+ if (x < 1)
+ fun_l7_n961(x)
+ else
+ fun_l7_n769(x)
+ end
+end
+
+def fun_l6_n463(x)
+ if (x < 1)
+ fun_l7_n828(x)
+ else
+ fun_l7_n219(x)
+ end
+end
+
+def fun_l6_n464(x)
+ if (x < 1)
+ fun_l7_n17(x)
+ else
+ fun_l7_n345(x)
+ end
+end
+
+def fun_l6_n465(x)
+ if (x < 1)
+ fun_l7_n412(x)
+ else
+ fun_l7_n498(x)
+ end
+end
+
+def fun_l6_n466(x)
+ if (x < 1)
+ fun_l7_n659(x)
+ else
+ fun_l7_n781(x)
+ end
+end
+
+def fun_l6_n467(x)
+ if (x < 1)
+ fun_l7_n528(x)
+ else
+ fun_l7_n138(x)
+ end
+end
+
+def fun_l6_n468(x)
+ if (x < 1)
+ fun_l7_n272(x)
+ else
+ fun_l7_n512(x)
+ end
+end
+
+def fun_l6_n469(x)
+ if (x < 1)
+ fun_l7_n458(x)
+ else
+ fun_l7_n430(x)
+ end
+end
+
+def fun_l6_n470(x)
+ if (x < 1)
+ fun_l7_n192(x)
+ else
+ fun_l7_n755(x)
+ end
+end
+
+def fun_l6_n471(x)
+ if (x < 1)
+ fun_l7_n188(x)
+ else
+ fun_l7_n827(x)
+ end
+end
+
+def fun_l6_n472(x)
+ if (x < 1)
+ fun_l7_n467(x)
+ else
+ fun_l7_n167(x)
+ end
+end
+
+def fun_l6_n473(x)
+ if (x < 1)
+ fun_l7_n648(x)
+ else
+ fun_l7_n823(x)
+ end
+end
+
+def fun_l6_n474(x)
+ if (x < 1)
+ fun_l7_n788(x)
+ else
+ fun_l7_n120(x)
+ end
+end
+
+def fun_l6_n475(x)
+ if (x < 1)
+ fun_l7_n199(x)
+ else
+ fun_l7_n25(x)
+ end
+end
+
+def fun_l6_n476(x)
+ if (x < 1)
+ fun_l7_n812(x)
+ else
+ fun_l7_n258(x)
+ end
+end
+
+def fun_l6_n477(x)
+ if (x < 1)
+ fun_l7_n525(x)
+ else
+ fun_l7_n140(x)
+ end
+end
+
+def fun_l6_n478(x)
+ if (x < 1)
+ fun_l7_n728(x)
+ else
+ fun_l7_n157(x)
+ end
+end
+
+def fun_l6_n479(x)
+ if (x < 1)
+ fun_l7_n527(x)
+ else
+ fun_l7_n172(x)
+ end
+end
+
+def fun_l6_n480(x)
+ if (x < 1)
+ fun_l7_n295(x)
+ else
+ fun_l7_n230(x)
+ end
+end
+
+def fun_l6_n481(x)
+ if (x < 1)
+ fun_l7_n619(x)
+ else
+ fun_l7_n495(x)
+ end
+end
+
+def fun_l6_n482(x)
+ if (x < 1)
+ fun_l7_n412(x)
+ else
+ fun_l7_n30(x)
+ end
+end
+
+def fun_l6_n483(x)
+ if (x < 1)
+ fun_l7_n236(x)
+ else
+ fun_l7_n842(x)
+ end
+end
+
+def fun_l6_n484(x)
+ if (x < 1)
+ fun_l7_n59(x)
+ else
+ fun_l7_n341(x)
+ end
+end
+
+def fun_l6_n485(x)
+ if (x < 1)
+ fun_l7_n841(x)
+ else
+ fun_l7_n67(x)
+ end
+end
+
+def fun_l6_n486(x)
+ if (x < 1)
+ fun_l7_n299(x)
+ else
+ fun_l7_n144(x)
+ end
+end
+
+def fun_l6_n487(x)
+ if (x < 1)
+ fun_l7_n672(x)
+ else
+ fun_l7_n682(x)
+ end
+end
+
+def fun_l6_n488(x)
+ if (x < 1)
+ fun_l7_n110(x)
+ else
+ fun_l7_n231(x)
+ end
+end
+
+def fun_l6_n489(x)
+ if (x < 1)
+ fun_l7_n984(x)
+ else
+ fun_l7_n583(x)
+ end
+end
+
+def fun_l6_n490(x)
+ if (x < 1)
+ fun_l7_n354(x)
+ else
+ fun_l7_n90(x)
+ end
+end
+
+def fun_l6_n491(x)
+ if (x < 1)
+ fun_l7_n541(x)
+ else
+ fun_l7_n583(x)
+ end
+end
+
+def fun_l6_n492(x)
+ if (x < 1)
+ fun_l7_n35(x)
+ else
+ fun_l7_n209(x)
+ end
+end
+
+def fun_l6_n493(x)
+ if (x < 1)
+ fun_l7_n547(x)
+ else
+ fun_l7_n982(x)
+ end
+end
+
+def fun_l6_n494(x)
+ if (x < 1)
+ fun_l7_n3(x)
+ else
+ fun_l7_n230(x)
+ end
+end
+
+def fun_l6_n495(x)
+ if (x < 1)
+ fun_l7_n777(x)
+ else
+ fun_l7_n140(x)
+ end
+end
+
+def fun_l6_n496(x)
+ if (x < 1)
+ fun_l7_n927(x)
+ else
+ fun_l7_n934(x)
+ end
+end
+
+def fun_l6_n497(x)
+ if (x < 1)
+ fun_l7_n201(x)
+ else
+ fun_l7_n342(x)
+ end
+end
+
+def fun_l6_n498(x)
+ if (x < 1)
+ fun_l7_n973(x)
+ else
+ fun_l7_n106(x)
+ end
+end
+
+def fun_l6_n499(x)
+ if (x < 1)
+ fun_l7_n373(x)
+ else
+ fun_l7_n558(x)
+ end
+end
+
+def fun_l6_n500(x)
+ if (x < 1)
+ fun_l7_n835(x)
+ else
+ fun_l7_n981(x)
+ end
+end
+
+def fun_l6_n501(x)
+ if (x < 1)
+ fun_l7_n135(x)
+ else
+ fun_l7_n997(x)
+ end
+end
+
+def fun_l6_n502(x)
+ if (x < 1)
+ fun_l7_n129(x)
+ else
+ fun_l7_n530(x)
+ end
+end
+
+def fun_l6_n503(x)
+ if (x < 1)
+ fun_l7_n924(x)
+ else
+ fun_l7_n611(x)
+ end
+end
+
+def fun_l6_n504(x)
+ if (x < 1)
+ fun_l7_n125(x)
+ else
+ fun_l7_n26(x)
+ end
+end
+
+def fun_l6_n505(x)
+ if (x < 1)
+ fun_l7_n592(x)
+ else
+ fun_l7_n50(x)
+ end
+end
+
+def fun_l6_n506(x)
+ if (x < 1)
+ fun_l7_n220(x)
+ else
+ fun_l7_n787(x)
+ end
+end
+
+def fun_l6_n507(x)
+ if (x < 1)
+ fun_l7_n908(x)
+ else
+ fun_l7_n15(x)
+ end
+end
+
+def fun_l6_n508(x)
+ if (x < 1)
+ fun_l7_n475(x)
+ else
+ fun_l7_n899(x)
+ end
+end
+
+def fun_l6_n509(x)
+ if (x < 1)
+ fun_l7_n704(x)
+ else
+ fun_l7_n559(x)
+ end
+end
+
+def fun_l6_n510(x)
+ if (x < 1)
+ fun_l7_n625(x)
+ else
+ fun_l7_n73(x)
+ end
+end
+
+def fun_l6_n511(x)
+ if (x < 1)
+ fun_l7_n234(x)
+ else
+ fun_l7_n166(x)
+ end
+end
+
+def fun_l6_n512(x)
+ if (x < 1)
+ fun_l7_n502(x)
+ else
+ fun_l7_n304(x)
+ end
+end
+
+def fun_l6_n513(x)
+ if (x < 1)
+ fun_l7_n686(x)
+ else
+ fun_l7_n643(x)
+ end
+end
+
+def fun_l6_n514(x)
+ if (x < 1)
+ fun_l7_n804(x)
+ else
+ fun_l7_n116(x)
+ end
+end
+
+def fun_l6_n515(x)
+ if (x < 1)
+ fun_l7_n365(x)
+ else
+ fun_l7_n102(x)
+ end
+end
+
+def fun_l6_n516(x)
+ if (x < 1)
+ fun_l7_n563(x)
+ else
+ fun_l7_n161(x)
+ end
+end
+
+def fun_l6_n517(x)
+ if (x < 1)
+ fun_l7_n695(x)
+ else
+ fun_l7_n936(x)
+ end
+end
+
+def fun_l6_n518(x)
+ if (x < 1)
+ fun_l7_n220(x)
+ else
+ fun_l7_n884(x)
+ end
+end
+
+def fun_l6_n519(x)
+ if (x < 1)
+ fun_l7_n602(x)
+ else
+ fun_l7_n144(x)
+ end
+end
+
+def fun_l6_n520(x)
+ if (x < 1)
+ fun_l7_n409(x)
+ else
+ fun_l7_n861(x)
+ end
+end
+
+def fun_l6_n521(x)
+ if (x < 1)
+ fun_l7_n258(x)
+ else
+ fun_l7_n768(x)
+ end
+end
+
+def fun_l6_n522(x)
+ if (x < 1)
+ fun_l7_n878(x)
+ else
+ fun_l7_n503(x)
+ end
+end
+
+def fun_l6_n523(x)
+ if (x < 1)
+ fun_l7_n570(x)
+ else
+ fun_l7_n675(x)
+ end
+end
+
+def fun_l6_n524(x)
+ if (x < 1)
+ fun_l7_n741(x)
+ else
+ fun_l7_n748(x)
+ end
+end
+
+def fun_l6_n525(x)
+ if (x < 1)
+ fun_l7_n729(x)
+ else
+ fun_l7_n272(x)
+ end
+end
+
+def fun_l6_n526(x)
+ if (x < 1)
+ fun_l7_n734(x)
+ else
+ fun_l7_n70(x)
+ end
+end
+
+def fun_l6_n527(x)
+ if (x < 1)
+ fun_l7_n235(x)
+ else
+ fun_l7_n606(x)
+ end
+end
+
+def fun_l6_n528(x)
+ if (x < 1)
+ fun_l7_n67(x)
+ else
+ fun_l7_n399(x)
+ end
+end
+
+def fun_l6_n529(x)
+ if (x < 1)
+ fun_l7_n706(x)
+ else
+ fun_l7_n150(x)
+ end
+end
+
+def fun_l6_n530(x)
+ if (x < 1)
+ fun_l7_n35(x)
+ else
+ fun_l7_n951(x)
+ end
+end
+
+def fun_l6_n531(x)
+ if (x < 1)
+ fun_l7_n517(x)
+ else
+ fun_l7_n329(x)
+ end
+end
+
+def fun_l6_n532(x)
+ if (x < 1)
+ fun_l7_n392(x)
+ else
+ fun_l7_n970(x)
+ end
+end
+
+def fun_l6_n533(x)
+ if (x < 1)
+ fun_l7_n466(x)
+ else
+ fun_l7_n260(x)
+ end
+end
+
+def fun_l6_n534(x)
+ if (x < 1)
+ fun_l7_n957(x)
+ else
+ fun_l7_n417(x)
+ end
+end
+
+def fun_l6_n535(x)
+ if (x < 1)
+ fun_l7_n184(x)
+ else
+ fun_l7_n188(x)
+ end
+end
+
+def fun_l6_n536(x)
+ if (x < 1)
+ fun_l7_n298(x)
+ else
+ fun_l7_n192(x)
+ end
+end
+
+def fun_l6_n537(x)
+ if (x < 1)
+ fun_l7_n28(x)
+ else
+ fun_l7_n309(x)
+ end
+end
+
+def fun_l6_n538(x)
+ if (x < 1)
+ fun_l7_n801(x)
+ else
+ fun_l7_n84(x)
+ end
+end
+
+def fun_l6_n539(x)
+ if (x < 1)
+ fun_l7_n894(x)
+ else
+ fun_l7_n973(x)
+ end
+end
+
+def fun_l6_n540(x)
+ if (x < 1)
+ fun_l7_n895(x)
+ else
+ fun_l7_n231(x)
+ end
+end
+
+def fun_l6_n541(x)
+ if (x < 1)
+ fun_l7_n728(x)
+ else
+ fun_l7_n28(x)
+ end
+end
+
+def fun_l6_n542(x)
+ if (x < 1)
+ fun_l7_n655(x)
+ else
+ fun_l7_n845(x)
+ end
+end
+
+def fun_l6_n543(x)
+ if (x < 1)
+ fun_l7_n952(x)
+ else
+ fun_l7_n484(x)
+ end
+end
+
+def fun_l6_n544(x)
+ if (x < 1)
+ fun_l7_n835(x)
+ else
+ fun_l7_n187(x)
+ end
+end
+
+def fun_l6_n545(x)
+ if (x < 1)
+ fun_l7_n748(x)
+ else
+ fun_l7_n460(x)
+ end
+end
+
+def fun_l6_n546(x)
+ if (x < 1)
+ fun_l7_n734(x)
+ else
+ fun_l7_n165(x)
+ end
+end
+
+def fun_l6_n547(x)
+ if (x < 1)
+ fun_l7_n499(x)
+ else
+ fun_l7_n133(x)
+ end
+end
+
+def fun_l6_n548(x)
+ if (x < 1)
+ fun_l7_n751(x)
+ else
+ fun_l7_n731(x)
+ end
+end
+
+def fun_l6_n549(x)
+ if (x < 1)
+ fun_l7_n269(x)
+ else
+ fun_l7_n690(x)
+ end
+end
+
+def fun_l6_n550(x)
+ if (x < 1)
+ fun_l7_n320(x)
+ else
+ fun_l7_n308(x)
+ end
+end
+
+def fun_l6_n551(x)
+ if (x < 1)
+ fun_l7_n182(x)
+ else
+ fun_l7_n144(x)
+ end
+end
+
+def fun_l6_n552(x)
+ if (x < 1)
+ fun_l7_n683(x)
+ else
+ fun_l7_n691(x)
+ end
+end
+
+def fun_l6_n553(x)
+ if (x < 1)
+ fun_l7_n502(x)
+ else
+ fun_l7_n520(x)
+ end
+end
+
+def fun_l6_n554(x)
+ if (x < 1)
+ fun_l7_n60(x)
+ else
+ fun_l7_n551(x)
+ end
+end
+
+def fun_l6_n555(x)
+ if (x < 1)
+ fun_l7_n185(x)
+ else
+ fun_l7_n87(x)
+ end
+end
+
+def fun_l6_n556(x)
+ if (x < 1)
+ fun_l7_n140(x)
+ else
+ fun_l7_n725(x)
+ end
+end
+
+def fun_l6_n557(x)
+ if (x < 1)
+ fun_l7_n76(x)
+ else
+ fun_l7_n501(x)
+ end
+end
+
+def fun_l6_n558(x)
+ if (x < 1)
+ fun_l7_n553(x)
+ else
+ fun_l7_n146(x)
+ end
+end
+
+def fun_l6_n559(x)
+ if (x < 1)
+ fun_l7_n535(x)
+ else
+ fun_l7_n17(x)
+ end
+end
+
+def fun_l6_n560(x)
+ if (x < 1)
+ fun_l7_n566(x)
+ else
+ fun_l7_n773(x)
+ end
+end
+
+def fun_l6_n561(x)
+ if (x < 1)
+ fun_l7_n358(x)
+ else
+ fun_l7_n951(x)
+ end
+end
+
+def fun_l6_n562(x)
+ if (x < 1)
+ fun_l7_n492(x)
+ else
+ fun_l7_n478(x)
+ end
+end
+
+def fun_l6_n563(x)
+ if (x < 1)
+ fun_l7_n796(x)
+ else
+ fun_l7_n906(x)
+ end
+end
+
+def fun_l6_n564(x)
+ if (x < 1)
+ fun_l7_n751(x)
+ else
+ fun_l7_n546(x)
+ end
+end
+
+def fun_l6_n565(x)
+ if (x < 1)
+ fun_l7_n179(x)
+ else
+ fun_l7_n49(x)
+ end
+end
+
+def fun_l6_n566(x)
+ if (x < 1)
+ fun_l7_n550(x)
+ else
+ fun_l7_n440(x)
+ end
+end
+
+def fun_l6_n567(x)
+ if (x < 1)
+ fun_l7_n715(x)
+ else
+ fun_l7_n862(x)
+ end
+end
+
+def fun_l6_n568(x)
+ if (x < 1)
+ fun_l7_n124(x)
+ else
+ fun_l7_n191(x)
+ end
+end
+
+def fun_l6_n569(x)
+ if (x < 1)
+ fun_l7_n709(x)
+ else
+ fun_l7_n704(x)
+ end
+end
+
+def fun_l6_n570(x)
+ if (x < 1)
+ fun_l7_n864(x)
+ else
+ fun_l7_n84(x)
+ end
+end
+
+def fun_l6_n571(x)
+ if (x < 1)
+ fun_l7_n302(x)
+ else
+ fun_l7_n424(x)
+ end
+end
+
+def fun_l6_n572(x)
+ if (x < 1)
+ fun_l7_n488(x)
+ else
+ fun_l7_n570(x)
+ end
+end
+
+def fun_l6_n573(x)
+ if (x < 1)
+ fun_l7_n590(x)
+ else
+ fun_l7_n560(x)
+ end
+end
+
+def fun_l6_n574(x)
+ if (x < 1)
+ fun_l7_n38(x)
+ else
+ fun_l7_n444(x)
+ end
+end
+
+def fun_l6_n575(x)
+ if (x < 1)
+ fun_l7_n401(x)
+ else
+ fun_l7_n359(x)
+ end
+end
+
+def fun_l6_n576(x)
+ if (x < 1)
+ fun_l7_n518(x)
+ else
+ fun_l7_n240(x)
+ end
+end
+
+def fun_l6_n577(x)
+ if (x < 1)
+ fun_l7_n247(x)
+ else
+ fun_l7_n540(x)
+ end
+end
+
+def fun_l6_n578(x)
+ if (x < 1)
+ fun_l7_n223(x)
+ else
+ fun_l7_n729(x)
+ end
+end
+
+def fun_l6_n579(x)
+ if (x < 1)
+ fun_l7_n524(x)
+ else
+ fun_l7_n684(x)
+ end
+end
+
+def fun_l6_n580(x)
+ if (x < 1)
+ fun_l7_n113(x)
+ else
+ fun_l7_n865(x)
+ end
+end
+
+def fun_l6_n581(x)
+ if (x < 1)
+ fun_l7_n920(x)
+ else
+ fun_l7_n238(x)
+ end
+end
+
+def fun_l6_n582(x)
+ if (x < 1)
+ fun_l7_n78(x)
+ else
+ fun_l7_n85(x)
+ end
+end
+
+def fun_l6_n583(x)
+ if (x < 1)
+ fun_l7_n713(x)
+ else
+ fun_l7_n110(x)
+ end
+end
+
+def fun_l6_n584(x)
+ if (x < 1)
+ fun_l7_n170(x)
+ else
+ fun_l7_n183(x)
+ end
+end
+
+def fun_l6_n585(x)
+ if (x < 1)
+ fun_l7_n100(x)
+ else
+ fun_l7_n215(x)
+ end
+end
+
+def fun_l6_n586(x)
+ if (x < 1)
+ fun_l7_n126(x)
+ else
+ fun_l7_n136(x)
+ end
+end
+
+def fun_l6_n587(x)
+ if (x < 1)
+ fun_l7_n592(x)
+ else
+ fun_l7_n502(x)
+ end
+end
+
+def fun_l6_n588(x)
+ if (x < 1)
+ fun_l7_n155(x)
+ else
+ fun_l7_n591(x)
+ end
+end
+
+def fun_l6_n589(x)
+ if (x < 1)
+ fun_l7_n840(x)
+ else
+ fun_l7_n91(x)
+ end
+end
+
+def fun_l6_n590(x)
+ if (x < 1)
+ fun_l7_n146(x)
+ else
+ fun_l7_n849(x)
+ end
+end
+
+def fun_l6_n591(x)
+ if (x < 1)
+ fun_l7_n161(x)
+ else
+ fun_l7_n884(x)
+ end
+end
+
+def fun_l6_n592(x)
+ if (x < 1)
+ fun_l7_n994(x)
+ else
+ fun_l7_n341(x)
+ end
+end
+
+def fun_l6_n593(x)
+ if (x < 1)
+ fun_l7_n974(x)
+ else
+ fun_l7_n355(x)
+ end
+end
+
+def fun_l6_n594(x)
+ if (x < 1)
+ fun_l7_n726(x)
+ else
+ fun_l7_n266(x)
+ end
+end
+
+def fun_l6_n595(x)
+ if (x < 1)
+ fun_l7_n142(x)
+ else
+ fun_l7_n154(x)
+ end
+end
+
+def fun_l6_n596(x)
+ if (x < 1)
+ fun_l7_n287(x)
+ else
+ fun_l7_n155(x)
+ end
+end
+
+def fun_l6_n597(x)
+ if (x < 1)
+ fun_l7_n594(x)
+ else
+ fun_l7_n424(x)
+ end
+end
+
+def fun_l6_n598(x)
+ if (x < 1)
+ fun_l7_n227(x)
+ else
+ fun_l7_n445(x)
+ end
+end
+
+def fun_l6_n599(x)
+ if (x < 1)
+ fun_l7_n660(x)
+ else
+ fun_l7_n464(x)
+ end
+end
+
+def fun_l6_n600(x)
+ if (x < 1)
+ fun_l7_n930(x)
+ else
+ fun_l7_n520(x)
+ end
+end
+
+def fun_l6_n601(x)
+ if (x < 1)
+ fun_l7_n714(x)
+ else
+ fun_l7_n984(x)
+ end
+end
+
+def fun_l6_n602(x)
+ if (x < 1)
+ fun_l7_n226(x)
+ else
+ fun_l7_n316(x)
+ end
+end
+
+def fun_l6_n603(x)
+ if (x < 1)
+ fun_l7_n104(x)
+ else
+ fun_l7_n563(x)
+ end
+end
+
+def fun_l6_n604(x)
+ if (x < 1)
+ fun_l7_n149(x)
+ else
+ fun_l7_n921(x)
+ end
+end
+
+def fun_l6_n605(x)
+ if (x < 1)
+ fun_l7_n195(x)
+ else
+ fun_l7_n696(x)
+ end
+end
+
+def fun_l6_n606(x)
+ if (x < 1)
+ fun_l7_n337(x)
+ else
+ fun_l7_n347(x)
+ end
+end
+
+def fun_l6_n607(x)
+ if (x < 1)
+ fun_l7_n657(x)
+ else
+ fun_l7_n67(x)
+ end
+end
+
+def fun_l6_n608(x)
+ if (x < 1)
+ fun_l7_n796(x)
+ else
+ fun_l7_n589(x)
+ end
+end
+
+def fun_l6_n609(x)
+ if (x < 1)
+ fun_l7_n230(x)
+ else
+ fun_l7_n769(x)
+ end
+end
+
+def fun_l6_n610(x)
+ if (x < 1)
+ fun_l7_n427(x)
+ else
+ fun_l7_n892(x)
+ end
+end
+
+def fun_l6_n611(x)
+ if (x < 1)
+ fun_l7_n741(x)
+ else
+ fun_l7_n567(x)
+ end
+end
+
+def fun_l6_n612(x)
+ if (x < 1)
+ fun_l7_n471(x)
+ else
+ fun_l7_n824(x)
+ end
+end
+
+def fun_l6_n613(x)
+ if (x < 1)
+ fun_l7_n522(x)
+ else
+ fun_l7_n694(x)
+ end
+end
+
+def fun_l6_n614(x)
+ if (x < 1)
+ fun_l7_n95(x)
+ else
+ fun_l7_n84(x)
+ end
+end
+
+def fun_l6_n615(x)
+ if (x < 1)
+ fun_l7_n632(x)
+ else
+ fun_l7_n590(x)
+ end
+end
+
+def fun_l6_n616(x)
+ if (x < 1)
+ fun_l7_n372(x)
+ else
+ fun_l7_n659(x)
+ end
+end
+
+def fun_l6_n617(x)
+ if (x < 1)
+ fun_l7_n547(x)
+ else
+ fun_l7_n321(x)
+ end
+end
+
+def fun_l6_n618(x)
+ if (x < 1)
+ fun_l7_n53(x)
+ else
+ fun_l7_n723(x)
+ end
+end
+
+def fun_l6_n619(x)
+ if (x < 1)
+ fun_l7_n653(x)
+ else
+ fun_l7_n740(x)
+ end
+end
+
+def fun_l6_n620(x)
+ if (x < 1)
+ fun_l7_n16(x)
+ else
+ fun_l7_n228(x)
+ end
+end
+
+def fun_l6_n621(x)
+ if (x < 1)
+ fun_l7_n655(x)
+ else
+ fun_l7_n701(x)
+ end
+end
+
+def fun_l6_n622(x)
+ if (x < 1)
+ fun_l7_n212(x)
+ else
+ fun_l7_n692(x)
+ end
+end
+
+def fun_l6_n623(x)
+ if (x < 1)
+ fun_l7_n959(x)
+ else
+ fun_l7_n327(x)
+ end
+end
+
+def fun_l6_n624(x)
+ if (x < 1)
+ fun_l7_n607(x)
+ else
+ fun_l7_n168(x)
+ end
+end
+
+def fun_l6_n625(x)
+ if (x < 1)
+ fun_l7_n229(x)
+ else
+ fun_l7_n584(x)
+ end
+end
+
+def fun_l6_n626(x)
+ if (x < 1)
+ fun_l7_n776(x)
+ else
+ fun_l7_n284(x)
+ end
+end
+
+def fun_l6_n627(x)
+ if (x < 1)
+ fun_l7_n770(x)
+ else
+ fun_l7_n169(x)
+ end
+end
+
+def fun_l6_n628(x)
+ if (x < 1)
+ fun_l7_n550(x)
+ else
+ fun_l7_n918(x)
+ end
+end
+
+def fun_l6_n629(x)
+ if (x < 1)
+ fun_l7_n450(x)
+ else
+ fun_l7_n654(x)
+ end
+end
+
+def fun_l6_n630(x)
+ if (x < 1)
+ fun_l7_n968(x)
+ else
+ fun_l7_n770(x)
+ end
+end
+
+def fun_l6_n631(x)
+ if (x < 1)
+ fun_l7_n118(x)
+ else
+ fun_l7_n411(x)
+ end
+end
+
+def fun_l6_n632(x)
+ if (x < 1)
+ fun_l7_n352(x)
+ else
+ fun_l7_n840(x)
+ end
+end
+
+def fun_l6_n633(x)
+ if (x < 1)
+ fun_l7_n588(x)
+ else
+ fun_l7_n810(x)
+ end
+end
+
+def fun_l6_n634(x)
+ if (x < 1)
+ fun_l7_n955(x)
+ else
+ fun_l7_n709(x)
+ end
+end
+
+def fun_l6_n635(x)
+ if (x < 1)
+ fun_l7_n137(x)
+ else
+ fun_l7_n239(x)
+ end
+end
+
+def fun_l6_n636(x)
+ if (x < 1)
+ fun_l7_n955(x)
+ else
+ fun_l7_n87(x)
+ end
+end
+
+def fun_l6_n637(x)
+ if (x < 1)
+ fun_l7_n479(x)
+ else
+ fun_l7_n91(x)
+ end
+end
+
+def fun_l6_n638(x)
+ if (x < 1)
+ fun_l7_n366(x)
+ else
+ fun_l7_n388(x)
+ end
+end
+
+def fun_l6_n639(x)
+ if (x < 1)
+ fun_l7_n90(x)
+ else
+ fun_l7_n971(x)
+ end
+end
+
+def fun_l6_n640(x)
+ if (x < 1)
+ fun_l7_n330(x)
+ else
+ fun_l7_n415(x)
+ end
+end
+
+def fun_l6_n641(x)
+ if (x < 1)
+ fun_l7_n233(x)
+ else
+ fun_l7_n653(x)
+ end
+end
+
+def fun_l6_n642(x)
+ if (x < 1)
+ fun_l7_n106(x)
+ else
+ fun_l7_n440(x)
+ end
+end
+
+def fun_l6_n643(x)
+ if (x < 1)
+ fun_l7_n156(x)
+ else
+ fun_l7_n818(x)
+ end
+end
+
+def fun_l6_n644(x)
+ if (x < 1)
+ fun_l7_n68(x)
+ else
+ fun_l7_n763(x)
+ end
+end
+
+def fun_l6_n645(x)
+ if (x < 1)
+ fun_l7_n858(x)
+ else
+ fun_l7_n465(x)
+ end
+end
+
+def fun_l6_n646(x)
+ if (x < 1)
+ fun_l7_n886(x)
+ else
+ fun_l7_n86(x)
+ end
+end
+
+def fun_l6_n647(x)
+ if (x < 1)
+ fun_l7_n689(x)
+ else
+ fun_l7_n964(x)
+ end
+end
+
+def fun_l6_n648(x)
+ if (x < 1)
+ fun_l7_n748(x)
+ else
+ fun_l7_n214(x)
+ end
+end
+
+def fun_l6_n649(x)
+ if (x < 1)
+ fun_l7_n830(x)
+ else
+ fun_l7_n567(x)
+ end
+end
+
+def fun_l6_n650(x)
+ if (x < 1)
+ fun_l7_n907(x)
+ else
+ fun_l7_n957(x)
+ end
+end
+
+def fun_l6_n651(x)
+ if (x < 1)
+ fun_l7_n242(x)
+ else
+ fun_l7_n239(x)
+ end
+end
+
+def fun_l6_n652(x)
+ if (x < 1)
+ fun_l7_n347(x)
+ else
+ fun_l7_n63(x)
+ end
+end
+
+def fun_l6_n653(x)
+ if (x < 1)
+ fun_l7_n480(x)
+ else
+ fun_l7_n441(x)
+ end
+end
+
+def fun_l6_n654(x)
+ if (x < 1)
+ fun_l7_n304(x)
+ else
+ fun_l7_n690(x)
+ end
+end
+
+def fun_l6_n655(x)
+ if (x < 1)
+ fun_l7_n511(x)
+ else
+ fun_l7_n710(x)
+ end
+end
+
+def fun_l6_n656(x)
+ if (x < 1)
+ fun_l7_n202(x)
+ else
+ fun_l7_n48(x)
+ end
+end
+
+def fun_l6_n657(x)
+ if (x < 1)
+ fun_l7_n232(x)
+ else
+ fun_l7_n919(x)
+ end
+end
+
+def fun_l6_n658(x)
+ if (x < 1)
+ fun_l7_n627(x)
+ else
+ fun_l7_n620(x)
+ end
+end
+
+def fun_l6_n659(x)
+ if (x < 1)
+ fun_l7_n716(x)
+ else
+ fun_l7_n116(x)
+ end
+end
+
+def fun_l6_n660(x)
+ if (x < 1)
+ fun_l7_n105(x)
+ else
+ fun_l7_n536(x)
+ end
+end
+
+def fun_l6_n661(x)
+ if (x < 1)
+ fun_l7_n376(x)
+ else
+ fun_l7_n965(x)
+ end
+end
+
+def fun_l6_n662(x)
+ if (x < 1)
+ fun_l7_n417(x)
+ else
+ fun_l7_n726(x)
+ end
+end
+
+def fun_l6_n663(x)
+ if (x < 1)
+ fun_l7_n567(x)
+ else
+ fun_l7_n948(x)
+ end
+end
+
+def fun_l6_n664(x)
+ if (x < 1)
+ fun_l7_n640(x)
+ else
+ fun_l7_n910(x)
+ end
+end
+
+def fun_l6_n665(x)
+ if (x < 1)
+ fun_l7_n874(x)
+ else
+ fun_l7_n314(x)
+ end
+end
+
+def fun_l6_n666(x)
+ if (x < 1)
+ fun_l7_n946(x)
+ else
+ fun_l7_n101(x)
+ end
+end
+
+def fun_l6_n667(x)
+ if (x < 1)
+ fun_l7_n960(x)
+ else
+ fun_l7_n199(x)
+ end
+end
+
+def fun_l6_n668(x)
+ if (x < 1)
+ fun_l7_n389(x)
+ else
+ fun_l7_n976(x)
+ end
+end
+
+def fun_l6_n669(x)
+ if (x < 1)
+ fun_l7_n31(x)
+ else
+ fun_l7_n903(x)
+ end
+end
+
+def fun_l6_n670(x)
+ if (x < 1)
+ fun_l7_n288(x)
+ else
+ fun_l7_n115(x)
+ end
+end
+
+def fun_l6_n671(x)
+ if (x < 1)
+ fun_l7_n418(x)
+ else
+ fun_l7_n249(x)
+ end
+end
+
+def fun_l6_n672(x)
+ if (x < 1)
+ fun_l7_n733(x)
+ else
+ fun_l7_n815(x)
+ end
+end
+
+def fun_l6_n673(x)
+ if (x < 1)
+ fun_l7_n227(x)
+ else
+ fun_l7_n23(x)
+ end
+end
+
+def fun_l6_n674(x)
+ if (x < 1)
+ fun_l7_n936(x)
+ else
+ fun_l7_n386(x)
+ end
+end
+
+def fun_l6_n675(x)
+ if (x < 1)
+ fun_l7_n638(x)
+ else
+ fun_l7_n39(x)
+ end
+end
+
+def fun_l6_n676(x)
+ if (x < 1)
+ fun_l7_n304(x)
+ else
+ fun_l7_n35(x)
+ end
+end
+
+def fun_l6_n677(x)
+ if (x < 1)
+ fun_l7_n676(x)
+ else
+ fun_l7_n443(x)
+ end
+end
+
+def fun_l6_n678(x)
+ if (x < 1)
+ fun_l7_n648(x)
+ else
+ fun_l7_n453(x)
+ end
+end
+
+def fun_l6_n679(x)
+ if (x < 1)
+ fun_l7_n15(x)
+ else
+ fun_l7_n220(x)
+ end
+end
+
+def fun_l6_n680(x)
+ if (x < 1)
+ fun_l7_n201(x)
+ else
+ fun_l7_n842(x)
+ end
+end
+
+def fun_l6_n681(x)
+ if (x < 1)
+ fun_l7_n67(x)
+ else
+ fun_l7_n73(x)
+ end
+end
+
+def fun_l6_n682(x)
+ if (x < 1)
+ fun_l7_n280(x)
+ else
+ fun_l7_n370(x)
+ end
+end
+
+def fun_l6_n683(x)
+ if (x < 1)
+ fun_l7_n822(x)
+ else
+ fun_l7_n27(x)
+ end
+end
+
+def fun_l6_n684(x)
+ if (x < 1)
+ fun_l7_n720(x)
+ else
+ fun_l7_n651(x)
+ end
+end
+
+def fun_l6_n685(x)
+ if (x < 1)
+ fun_l7_n414(x)
+ else
+ fun_l7_n257(x)
+ end
+end
+
+def fun_l6_n686(x)
+ if (x < 1)
+ fun_l7_n477(x)
+ else
+ fun_l7_n883(x)
+ end
+end
+
+def fun_l6_n687(x)
+ if (x < 1)
+ fun_l7_n467(x)
+ else
+ fun_l7_n739(x)
+ end
+end
+
+def fun_l6_n688(x)
+ if (x < 1)
+ fun_l7_n421(x)
+ else
+ fun_l7_n271(x)
+ end
+end
+
+def fun_l6_n689(x)
+ if (x < 1)
+ fun_l7_n444(x)
+ else
+ fun_l7_n601(x)
+ end
+end
+
+def fun_l6_n690(x)
+ if (x < 1)
+ fun_l7_n104(x)
+ else
+ fun_l7_n597(x)
+ end
+end
+
+def fun_l6_n691(x)
+ if (x < 1)
+ fun_l7_n273(x)
+ else
+ fun_l7_n79(x)
+ end
+end
+
+def fun_l6_n692(x)
+ if (x < 1)
+ fun_l7_n310(x)
+ else
+ fun_l7_n261(x)
+ end
+end
+
+def fun_l6_n693(x)
+ if (x < 1)
+ fun_l7_n190(x)
+ else
+ fun_l7_n330(x)
+ end
+end
+
+def fun_l6_n694(x)
+ if (x < 1)
+ fun_l7_n103(x)
+ else
+ fun_l7_n258(x)
+ end
+end
+
+def fun_l6_n695(x)
+ if (x < 1)
+ fun_l7_n524(x)
+ else
+ fun_l7_n988(x)
+ end
+end
+
+def fun_l6_n696(x)
+ if (x < 1)
+ fun_l7_n885(x)
+ else
+ fun_l7_n731(x)
+ end
+end
+
+def fun_l6_n697(x)
+ if (x < 1)
+ fun_l7_n212(x)
+ else
+ fun_l7_n98(x)
+ end
+end
+
+def fun_l6_n698(x)
+ if (x < 1)
+ fun_l7_n735(x)
+ else
+ fun_l7_n682(x)
+ end
+end
+
+def fun_l6_n699(x)
+ if (x < 1)
+ fun_l7_n610(x)
+ else
+ fun_l7_n512(x)
+ end
+end
+
+def fun_l6_n700(x)
+ if (x < 1)
+ fun_l7_n828(x)
+ else
+ fun_l7_n651(x)
+ end
+end
+
+def fun_l6_n701(x)
+ if (x < 1)
+ fun_l7_n269(x)
+ else
+ fun_l7_n192(x)
+ end
+end
+
+def fun_l6_n702(x)
+ if (x < 1)
+ fun_l7_n775(x)
+ else
+ fun_l7_n334(x)
+ end
+end
+
+def fun_l6_n703(x)
+ if (x < 1)
+ fun_l7_n880(x)
+ else
+ fun_l7_n396(x)
+ end
+end
+
+def fun_l6_n704(x)
+ if (x < 1)
+ fun_l7_n907(x)
+ else
+ fun_l7_n107(x)
+ end
+end
+
+def fun_l6_n705(x)
+ if (x < 1)
+ fun_l7_n425(x)
+ else
+ fun_l7_n555(x)
+ end
+end
+
+def fun_l6_n706(x)
+ if (x < 1)
+ fun_l7_n458(x)
+ else
+ fun_l7_n610(x)
+ end
+end
+
+def fun_l6_n707(x)
+ if (x < 1)
+ fun_l7_n527(x)
+ else
+ fun_l7_n69(x)
+ end
+end
+
+def fun_l6_n708(x)
+ if (x < 1)
+ fun_l7_n518(x)
+ else
+ fun_l7_n87(x)
+ end
+end
+
+def fun_l6_n709(x)
+ if (x < 1)
+ fun_l7_n441(x)
+ else
+ fun_l7_n533(x)
+ end
+end
+
+def fun_l6_n710(x)
+ if (x < 1)
+ fun_l7_n872(x)
+ else
+ fun_l7_n896(x)
+ end
+end
+
+def fun_l6_n711(x)
+ if (x < 1)
+ fun_l7_n388(x)
+ else
+ fun_l7_n476(x)
+ end
+end
+
+def fun_l6_n712(x)
+ if (x < 1)
+ fun_l7_n913(x)
+ else
+ fun_l7_n304(x)
+ end
+end
+
+def fun_l6_n713(x)
+ if (x < 1)
+ fun_l7_n203(x)
+ else
+ fun_l7_n457(x)
+ end
+end
+
+def fun_l6_n714(x)
+ if (x < 1)
+ fun_l7_n593(x)
+ else
+ fun_l7_n921(x)
+ end
+end
+
+def fun_l6_n715(x)
+ if (x < 1)
+ fun_l7_n452(x)
+ else
+ fun_l7_n68(x)
+ end
+end
+
+def fun_l6_n716(x)
+ if (x < 1)
+ fun_l7_n203(x)
+ else
+ fun_l7_n362(x)
+ end
+end
+
+def fun_l6_n717(x)
+ if (x < 1)
+ fun_l7_n455(x)
+ else
+ fun_l7_n199(x)
+ end
+end
+
+def fun_l6_n718(x)
+ if (x < 1)
+ fun_l7_n500(x)
+ else
+ fun_l7_n272(x)
+ end
+end
+
+def fun_l6_n719(x)
+ if (x < 1)
+ fun_l7_n970(x)
+ else
+ fun_l7_n572(x)
+ end
+end
+
+def fun_l6_n720(x)
+ if (x < 1)
+ fun_l7_n74(x)
+ else
+ fun_l7_n246(x)
+ end
+end
+
+def fun_l6_n721(x)
+ if (x < 1)
+ fun_l7_n943(x)
+ else
+ fun_l7_n640(x)
+ end
+end
+
+def fun_l6_n722(x)
+ if (x < 1)
+ fun_l7_n106(x)
+ else
+ fun_l7_n387(x)
+ end
+end
+
+def fun_l6_n723(x)
+ if (x < 1)
+ fun_l7_n474(x)
+ else
+ fun_l7_n530(x)
+ end
+end
+
+def fun_l6_n724(x)
+ if (x < 1)
+ fun_l7_n246(x)
+ else
+ fun_l7_n387(x)
+ end
+end
+
+def fun_l6_n725(x)
+ if (x < 1)
+ fun_l7_n572(x)
+ else
+ fun_l7_n874(x)
+ end
+end
+
+def fun_l6_n726(x)
+ if (x < 1)
+ fun_l7_n858(x)
+ else
+ fun_l7_n71(x)
+ end
+end
+
+def fun_l6_n727(x)
+ if (x < 1)
+ fun_l7_n615(x)
+ else
+ fun_l7_n14(x)
+ end
+end
+
+def fun_l6_n728(x)
+ if (x < 1)
+ fun_l7_n840(x)
+ else
+ fun_l7_n779(x)
+ end
+end
+
+def fun_l6_n729(x)
+ if (x < 1)
+ fun_l7_n811(x)
+ else
+ fun_l7_n981(x)
+ end
+end
+
+def fun_l6_n730(x)
+ if (x < 1)
+ fun_l7_n196(x)
+ else
+ fun_l7_n731(x)
+ end
+end
+
+def fun_l6_n731(x)
+ if (x < 1)
+ fun_l7_n202(x)
+ else
+ fun_l7_n781(x)
+ end
+end
+
+def fun_l6_n732(x)
+ if (x < 1)
+ fun_l7_n867(x)
+ else
+ fun_l7_n770(x)
+ end
+end
+
+def fun_l6_n733(x)
+ if (x < 1)
+ fun_l7_n90(x)
+ else
+ fun_l7_n937(x)
+ end
+end
+
+def fun_l6_n734(x)
+ if (x < 1)
+ fun_l7_n890(x)
+ else
+ fun_l7_n937(x)
+ end
+end
+
+def fun_l6_n735(x)
+ if (x < 1)
+ fun_l7_n967(x)
+ else
+ fun_l7_n235(x)
+ end
+end
+
+def fun_l6_n736(x)
+ if (x < 1)
+ fun_l7_n612(x)
+ else
+ fun_l7_n140(x)
+ end
+end
+
+def fun_l6_n737(x)
+ if (x < 1)
+ fun_l7_n156(x)
+ else
+ fun_l7_n600(x)
+ end
+end
+
+def fun_l6_n738(x)
+ if (x < 1)
+ fun_l7_n462(x)
+ else
+ fun_l7_n907(x)
+ end
+end
+
+def fun_l6_n739(x)
+ if (x < 1)
+ fun_l7_n226(x)
+ else
+ fun_l7_n83(x)
+ end
+end
+
+def fun_l6_n740(x)
+ if (x < 1)
+ fun_l7_n419(x)
+ else
+ fun_l7_n95(x)
+ end
+end
+
+def fun_l6_n741(x)
+ if (x < 1)
+ fun_l7_n358(x)
+ else
+ fun_l7_n701(x)
+ end
+end
+
+def fun_l6_n742(x)
+ if (x < 1)
+ fun_l7_n451(x)
+ else
+ fun_l7_n700(x)
+ end
+end
+
+def fun_l6_n743(x)
+ if (x < 1)
+ fun_l7_n561(x)
+ else
+ fun_l7_n383(x)
+ end
+end
+
+def fun_l6_n744(x)
+ if (x < 1)
+ fun_l7_n28(x)
+ else
+ fun_l7_n56(x)
+ end
+end
+
+def fun_l6_n745(x)
+ if (x < 1)
+ fun_l7_n127(x)
+ else
+ fun_l7_n113(x)
+ end
+end
+
+def fun_l6_n746(x)
+ if (x < 1)
+ fun_l7_n767(x)
+ else
+ fun_l7_n907(x)
+ end
+end
+
+def fun_l6_n747(x)
+ if (x < 1)
+ fun_l7_n174(x)
+ else
+ fun_l7_n955(x)
+ end
+end
+
+def fun_l6_n748(x)
+ if (x < 1)
+ fun_l7_n51(x)
+ else
+ fun_l7_n951(x)
+ end
+end
+
+def fun_l6_n749(x)
+ if (x < 1)
+ fun_l7_n172(x)
+ else
+ fun_l7_n847(x)
+ end
+end
+
+def fun_l6_n750(x)
+ if (x < 1)
+ fun_l7_n240(x)
+ else
+ fun_l7_n869(x)
+ end
+end
+
+def fun_l6_n751(x)
+ if (x < 1)
+ fun_l7_n435(x)
+ else
+ fun_l7_n747(x)
+ end
+end
+
+def fun_l6_n752(x)
+ if (x < 1)
+ fun_l7_n673(x)
+ else
+ fun_l7_n454(x)
+ end
+end
+
+def fun_l6_n753(x)
+ if (x < 1)
+ fun_l7_n98(x)
+ else
+ fun_l7_n66(x)
+ end
+end
+
+def fun_l6_n754(x)
+ if (x < 1)
+ fun_l7_n63(x)
+ else
+ fun_l7_n943(x)
+ end
+end
+
+def fun_l6_n755(x)
+ if (x < 1)
+ fun_l7_n863(x)
+ else
+ fun_l7_n155(x)
+ end
+end
+
+def fun_l6_n756(x)
+ if (x < 1)
+ fun_l7_n197(x)
+ else
+ fun_l7_n807(x)
+ end
+end
+
+def fun_l6_n757(x)
+ if (x < 1)
+ fun_l7_n992(x)
+ else
+ fun_l7_n615(x)
+ end
+end
+
+def fun_l6_n758(x)
+ if (x < 1)
+ fun_l7_n172(x)
+ else
+ fun_l7_n507(x)
+ end
+end
+
+def fun_l6_n759(x)
+ if (x < 1)
+ fun_l7_n756(x)
+ else
+ fun_l7_n599(x)
+ end
+end
+
+def fun_l6_n760(x)
+ if (x < 1)
+ fun_l7_n876(x)
+ else
+ fun_l7_n185(x)
+ end
+end
+
+def fun_l6_n761(x)
+ if (x < 1)
+ fun_l7_n522(x)
+ else
+ fun_l7_n301(x)
+ end
+end
+
+def fun_l6_n762(x)
+ if (x < 1)
+ fun_l7_n994(x)
+ else
+ fun_l7_n408(x)
+ end
+end
+
+def fun_l6_n763(x)
+ if (x < 1)
+ fun_l7_n201(x)
+ else
+ fun_l7_n304(x)
+ end
+end
+
+def fun_l6_n764(x)
+ if (x < 1)
+ fun_l7_n200(x)
+ else
+ fun_l7_n123(x)
+ end
+end
+
+def fun_l6_n765(x)
+ if (x < 1)
+ fun_l7_n156(x)
+ else
+ fun_l7_n117(x)
+ end
+end
+
+def fun_l6_n766(x)
+ if (x < 1)
+ fun_l7_n918(x)
+ else
+ fun_l7_n416(x)
+ end
+end
+
+def fun_l6_n767(x)
+ if (x < 1)
+ fun_l7_n538(x)
+ else
+ fun_l7_n335(x)
+ end
+end
+
+def fun_l6_n768(x)
+ if (x < 1)
+ fun_l7_n699(x)
+ else
+ fun_l7_n980(x)
+ end
+end
+
+def fun_l6_n769(x)
+ if (x < 1)
+ fun_l7_n903(x)
+ else
+ fun_l7_n195(x)
+ end
+end
+
+def fun_l6_n770(x)
+ if (x < 1)
+ fun_l7_n419(x)
+ else
+ fun_l7_n523(x)
+ end
+end
+
+def fun_l6_n771(x)
+ if (x < 1)
+ fun_l7_n221(x)
+ else
+ fun_l7_n39(x)
+ end
+end
+
+def fun_l6_n772(x)
+ if (x < 1)
+ fun_l7_n369(x)
+ else
+ fun_l7_n227(x)
+ end
+end
+
+def fun_l6_n773(x)
+ if (x < 1)
+ fun_l7_n861(x)
+ else
+ fun_l7_n252(x)
+ end
+end
+
+def fun_l6_n774(x)
+ if (x < 1)
+ fun_l7_n682(x)
+ else
+ fun_l7_n42(x)
+ end
+end
+
+def fun_l6_n775(x)
+ if (x < 1)
+ fun_l7_n777(x)
+ else
+ fun_l7_n594(x)
+ end
+end
+
+def fun_l6_n776(x)
+ if (x < 1)
+ fun_l7_n794(x)
+ else
+ fun_l7_n71(x)
+ end
+end
+
+def fun_l6_n777(x)
+ if (x < 1)
+ fun_l7_n669(x)
+ else
+ fun_l7_n66(x)
+ end
+end
+
+def fun_l6_n778(x)
+ if (x < 1)
+ fun_l7_n824(x)
+ else
+ fun_l7_n95(x)
+ end
+end
+
+def fun_l6_n779(x)
+ if (x < 1)
+ fun_l7_n833(x)
+ else
+ fun_l7_n504(x)
+ end
+end
+
+def fun_l6_n780(x)
+ if (x < 1)
+ fun_l7_n50(x)
+ else
+ fun_l7_n647(x)
+ end
+end
+
+def fun_l6_n781(x)
+ if (x < 1)
+ fun_l7_n139(x)
+ else
+ fun_l7_n214(x)
+ end
+end
+
+def fun_l6_n782(x)
+ if (x < 1)
+ fun_l7_n450(x)
+ else
+ fun_l7_n660(x)
+ end
+end
+
+def fun_l6_n783(x)
+ if (x < 1)
+ fun_l7_n164(x)
+ else
+ fun_l7_n576(x)
+ end
+end
+
+def fun_l6_n784(x)
+ if (x < 1)
+ fun_l7_n722(x)
+ else
+ fun_l7_n714(x)
+ end
+end
+
+def fun_l6_n785(x)
+ if (x < 1)
+ fun_l7_n90(x)
+ else
+ fun_l7_n556(x)
+ end
+end
+
+def fun_l6_n786(x)
+ if (x < 1)
+ fun_l7_n413(x)
+ else
+ fun_l7_n722(x)
+ end
+end
+
+def fun_l6_n787(x)
+ if (x < 1)
+ fun_l7_n141(x)
+ else
+ fun_l7_n90(x)
+ end
+end
+
+def fun_l6_n788(x)
+ if (x < 1)
+ fun_l7_n750(x)
+ else
+ fun_l7_n660(x)
+ end
+end
+
+def fun_l6_n789(x)
+ if (x < 1)
+ fun_l7_n581(x)
+ else
+ fun_l7_n368(x)
+ end
+end
+
+def fun_l6_n790(x)
+ if (x < 1)
+ fun_l7_n922(x)
+ else
+ fun_l7_n551(x)
+ end
+end
+
+def fun_l6_n791(x)
+ if (x < 1)
+ fun_l7_n842(x)
+ else
+ fun_l7_n336(x)
+ end
+end
+
+def fun_l6_n792(x)
+ if (x < 1)
+ fun_l7_n264(x)
+ else
+ fun_l7_n7(x)
+ end
+end
+
+def fun_l6_n793(x)
+ if (x < 1)
+ fun_l7_n902(x)
+ else
+ fun_l7_n184(x)
+ end
+end
+
+def fun_l6_n794(x)
+ if (x < 1)
+ fun_l7_n788(x)
+ else
+ fun_l7_n854(x)
+ end
+end
+
+def fun_l6_n795(x)
+ if (x < 1)
+ fun_l7_n375(x)
+ else
+ fun_l7_n601(x)
+ end
+end
+
+def fun_l6_n796(x)
+ if (x < 1)
+ fun_l7_n674(x)
+ else
+ fun_l7_n136(x)
+ end
+end
+
+def fun_l6_n797(x)
+ if (x < 1)
+ fun_l7_n836(x)
+ else
+ fun_l7_n90(x)
+ end
+end
+
+def fun_l6_n798(x)
+ if (x < 1)
+ fun_l7_n461(x)
+ else
+ fun_l7_n686(x)
+ end
+end
+
+def fun_l6_n799(x)
+ if (x < 1)
+ fun_l7_n308(x)
+ else
+ fun_l7_n179(x)
+ end
+end
+
+def fun_l6_n800(x)
+ if (x < 1)
+ fun_l7_n154(x)
+ else
+ fun_l7_n618(x)
+ end
+end
+
+def fun_l6_n801(x)
+ if (x < 1)
+ fun_l7_n242(x)
+ else
+ fun_l7_n16(x)
+ end
+end
+
+def fun_l6_n802(x)
+ if (x < 1)
+ fun_l7_n880(x)
+ else
+ fun_l7_n143(x)
+ end
+end
+
+def fun_l6_n803(x)
+ if (x < 1)
+ fun_l7_n577(x)
+ else
+ fun_l7_n414(x)
+ end
+end
+
+def fun_l6_n804(x)
+ if (x < 1)
+ fun_l7_n409(x)
+ else
+ fun_l7_n116(x)
+ end
+end
+
+def fun_l6_n805(x)
+ if (x < 1)
+ fun_l7_n259(x)
+ else
+ fun_l7_n820(x)
+ end
+end
+
+def fun_l6_n806(x)
+ if (x < 1)
+ fun_l7_n384(x)
+ else
+ fun_l7_n939(x)
+ end
+end
+
+def fun_l6_n807(x)
+ if (x < 1)
+ fun_l7_n138(x)
+ else
+ fun_l7_n652(x)
+ end
+end
+
+def fun_l6_n808(x)
+ if (x < 1)
+ fun_l7_n455(x)
+ else
+ fun_l7_n693(x)
+ end
+end
+
+def fun_l6_n809(x)
+ if (x < 1)
+ fun_l7_n892(x)
+ else
+ fun_l7_n638(x)
+ end
+end
+
+def fun_l6_n810(x)
+ if (x < 1)
+ fun_l7_n498(x)
+ else
+ fun_l7_n716(x)
+ end
+end
+
+def fun_l6_n811(x)
+ if (x < 1)
+ fun_l7_n713(x)
+ else
+ fun_l7_n9(x)
+ end
+end
+
+def fun_l6_n812(x)
+ if (x < 1)
+ fun_l7_n854(x)
+ else
+ fun_l7_n507(x)
+ end
+end
+
+def fun_l6_n813(x)
+ if (x < 1)
+ fun_l7_n385(x)
+ else
+ fun_l7_n323(x)
+ end
+end
+
+def fun_l6_n814(x)
+ if (x < 1)
+ fun_l7_n437(x)
+ else
+ fun_l7_n954(x)
+ end
+end
+
+def fun_l6_n815(x)
+ if (x < 1)
+ fun_l7_n471(x)
+ else
+ fun_l7_n245(x)
+ end
+end
+
+def fun_l6_n816(x)
+ if (x < 1)
+ fun_l7_n485(x)
+ else
+ fun_l7_n935(x)
+ end
+end
+
+def fun_l6_n817(x)
+ if (x < 1)
+ fun_l7_n319(x)
+ else
+ fun_l7_n566(x)
+ end
+end
+
+def fun_l6_n818(x)
+ if (x < 1)
+ fun_l7_n339(x)
+ else
+ fun_l7_n152(x)
+ end
+end
+
+def fun_l6_n819(x)
+ if (x < 1)
+ fun_l7_n21(x)
+ else
+ fun_l7_n452(x)
+ end
+end
+
+def fun_l6_n820(x)
+ if (x < 1)
+ fun_l7_n16(x)
+ else
+ fun_l7_n502(x)
+ end
+end
+
+def fun_l6_n821(x)
+ if (x < 1)
+ fun_l7_n813(x)
+ else
+ fun_l7_n520(x)
+ end
+end
+
+def fun_l6_n822(x)
+ if (x < 1)
+ fun_l7_n519(x)
+ else
+ fun_l7_n651(x)
+ end
+end
+
+def fun_l6_n823(x)
+ if (x < 1)
+ fun_l7_n890(x)
+ else
+ fun_l7_n227(x)
+ end
+end
+
+def fun_l6_n824(x)
+ if (x < 1)
+ fun_l7_n517(x)
+ else
+ fun_l7_n799(x)
+ end
+end
+
+def fun_l6_n825(x)
+ if (x < 1)
+ fun_l7_n404(x)
+ else
+ fun_l7_n442(x)
+ end
+end
+
+def fun_l6_n826(x)
+ if (x < 1)
+ fun_l7_n308(x)
+ else
+ fun_l7_n328(x)
+ end
+end
+
+def fun_l6_n827(x)
+ if (x < 1)
+ fun_l7_n953(x)
+ else
+ fun_l7_n950(x)
+ end
+end
+
+def fun_l6_n828(x)
+ if (x < 1)
+ fun_l7_n206(x)
+ else
+ fun_l7_n701(x)
+ end
+end
+
+def fun_l6_n829(x)
+ if (x < 1)
+ fun_l7_n499(x)
+ else
+ fun_l7_n972(x)
+ end
+end
+
+def fun_l6_n830(x)
+ if (x < 1)
+ fun_l7_n578(x)
+ else
+ fun_l7_n697(x)
+ end
+end
+
+def fun_l6_n831(x)
+ if (x < 1)
+ fun_l7_n116(x)
+ else
+ fun_l7_n747(x)
+ end
+end
+
+def fun_l6_n832(x)
+ if (x < 1)
+ fun_l7_n423(x)
+ else
+ fun_l7_n653(x)
+ end
+end
+
+def fun_l6_n833(x)
+ if (x < 1)
+ fun_l7_n524(x)
+ else
+ fun_l7_n423(x)
+ end
+end
+
+def fun_l6_n834(x)
+ if (x < 1)
+ fun_l7_n940(x)
+ else
+ fun_l7_n48(x)
+ end
+end
+
+def fun_l6_n835(x)
+ if (x < 1)
+ fun_l7_n336(x)
+ else
+ fun_l7_n584(x)
+ end
+end
+
+def fun_l6_n836(x)
+ if (x < 1)
+ fun_l7_n66(x)
+ else
+ fun_l7_n980(x)
+ end
+end
+
+def fun_l6_n837(x)
+ if (x < 1)
+ fun_l7_n176(x)
+ else
+ fun_l7_n845(x)
+ end
+end
+
+def fun_l6_n838(x)
+ if (x < 1)
+ fun_l7_n736(x)
+ else
+ fun_l7_n385(x)
+ end
+end
+
+def fun_l6_n839(x)
+ if (x < 1)
+ fun_l7_n948(x)
+ else
+ fun_l7_n258(x)
+ end
+end
+
+def fun_l6_n840(x)
+ if (x < 1)
+ fun_l7_n926(x)
+ else
+ fun_l7_n926(x)
+ end
+end
+
+def fun_l6_n841(x)
+ if (x < 1)
+ fun_l7_n334(x)
+ else
+ fun_l7_n134(x)
+ end
+end
+
+def fun_l6_n842(x)
+ if (x < 1)
+ fun_l7_n757(x)
+ else
+ fun_l7_n995(x)
+ end
+end
+
+def fun_l6_n843(x)
+ if (x < 1)
+ fun_l7_n75(x)
+ else
+ fun_l7_n6(x)
+ end
+end
+
+def fun_l6_n844(x)
+ if (x < 1)
+ fun_l7_n632(x)
+ else
+ fun_l7_n683(x)
+ end
+end
+
+def fun_l6_n845(x)
+ if (x < 1)
+ fun_l7_n788(x)
+ else
+ fun_l7_n153(x)
+ end
+end
+
+def fun_l6_n846(x)
+ if (x < 1)
+ fun_l7_n668(x)
+ else
+ fun_l7_n78(x)
+ end
+end
+
+def fun_l6_n847(x)
+ if (x < 1)
+ fun_l7_n509(x)
+ else
+ fun_l7_n210(x)
+ end
+end
+
+def fun_l6_n848(x)
+ if (x < 1)
+ fun_l7_n862(x)
+ else
+ fun_l7_n90(x)
+ end
+end
+
+def fun_l6_n849(x)
+ if (x < 1)
+ fun_l7_n837(x)
+ else
+ fun_l7_n37(x)
+ end
+end
+
+def fun_l6_n850(x)
+ if (x < 1)
+ fun_l7_n792(x)
+ else
+ fun_l7_n171(x)
+ end
+end
+
+def fun_l6_n851(x)
+ if (x < 1)
+ fun_l7_n869(x)
+ else
+ fun_l7_n217(x)
+ end
+end
+
+def fun_l6_n852(x)
+ if (x < 1)
+ fun_l7_n585(x)
+ else
+ fun_l7_n980(x)
+ end
+end
+
+def fun_l6_n853(x)
+ if (x < 1)
+ fun_l7_n752(x)
+ else
+ fun_l7_n214(x)
+ end
+end
+
+def fun_l6_n854(x)
+ if (x < 1)
+ fun_l7_n151(x)
+ else
+ fun_l7_n668(x)
+ end
+end
+
+def fun_l6_n855(x)
+ if (x < 1)
+ fun_l7_n145(x)
+ else
+ fun_l7_n99(x)
+ end
+end
+
+def fun_l6_n856(x)
+ if (x < 1)
+ fun_l7_n114(x)
+ else
+ fun_l7_n852(x)
+ end
+end
+
+def fun_l6_n857(x)
+ if (x < 1)
+ fun_l7_n571(x)
+ else
+ fun_l7_n6(x)
+ end
+end
+
+def fun_l6_n858(x)
+ if (x < 1)
+ fun_l7_n724(x)
+ else
+ fun_l7_n132(x)
+ end
+end
+
+def fun_l6_n859(x)
+ if (x < 1)
+ fun_l7_n146(x)
+ else
+ fun_l7_n627(x)
+ end
+end
+
+def fun_l6_n860(x)
+ if (x < 1)
+ fun_l7_n515(x)
+ else
+ fun_l7_n598(x)
+ end
+end
+
+def fun_l6_n861(x)
+ if (x < 1)
+ fun_l7_n49(x)
+ else
+ fun_l7_n781(x)
+ end
+end
+
+def fun_l6_n862(x)
+ if (x < 1)
+ fun_l7_n378(x)
+ else
+ fun_l7_n295(x)
+ end
+end
+
+def fun_l6_n863(x)
+ if (x < 1)
+ fun_l7_n122(x)
+ else
+ fun_l7_n738(x)
+ end
+end
+
+def fun_l6_n864(x)
+ if (x < 1)
+ fun_l7_n421(x)
+ else
+ fun_l7_n719(x)
+ end
+end
+
+def fun_l6_n865(x)
+ if (x < 1)
+ fun_l7_n965(x)
+ else
+ fun_l7_n963(x)
+ end
+end
+
+def fun_l6_n866(x)
+ if (x < 1)
+ fun_l7_n551(x)
+ else
+ fun_l7_n177(x)
+ end
+end
+
+def fun_l6_n867(x)
+ if (x < 1)
+ fun_l7_n136(x)
+ else
+ fun_l7_n289(x)
+ end
+end
+
+def fun_l6_n868(x)
+ if (x < 1)
+ fun_l7_n26(x)
+ else
+ fun_l7_n376(x)
+ end
+end
+
+def fun_l6_n869(x)
+ if (x < 1)
+ fun_l7_n888(x)
+ else
+ fun_l7_n948(x)
+ end
+end
+
+def fun_l6_n870(x)
+ if (x < 1)
+ fun_l7_n636(x)
+ else
+ fun_l7_n89(x)
+ end
+end
+
+def fun_l6_n871(x)
+ if (x < 1)
+ fun_l7_n953(x)
+ else
+ fun_l7_n634(x)
+ end
+end
+
+def fun_l6_n872(x)
+ if (x < 1)
+ fun_l7_n74(x)
+ else
+ fun_l7_n219(x)
+ end
+end
+
+def fun_l6_n873(x)
+ if (x < 1)
+ fun_l7_n317(x)
+ else
+ fun_l7_n863(x)
+ end
+end
+
+def fun_l6_n874(x)
+ if (x < 1)
+ fun_l7_n495(x)
+ else
+ fun_l7_n478(x)
+ end
+end
+
+def fun_l6_n875(x)
+ if (x < 1)
+ fun_l7_n908(x)
+ else
+ fun_l7_n634(x)
+ end
+end
+
+def fun_l6_n876(x)
+ if (x < 1)
+ fun_l7_n780(x)
+ else
+ fun_l7_n886(x)
+ end
+end
+
+def fun_l6_n877(x)
+ if (x < 1)
+ fun_l7_n768(x)
+ else
+ fun_l7_n820(x)
+ end
+end
+
+def fun_l6_n878(x)
+ if (x < 1)
+ fun_l7_n501(x)
+ else
+ fun_l7_n355(x)
+ end
+end
+
+def fun_l6_n879(x)
+ if (x < 1)
+ fun_l7_n412(x)
+ else
+ fun_l7_n701(x)
+ end
+end
+
+def fun_l6_n880(x)
+ if (x < 1)
+ fun_l7_n541(x)
+ else
+ fun_l7_n148(x)
+ end
+end
+
+def fun_l6_n881(x)
+ if (x < 1)
+ fun_l7_n460(x)
+ else
+ fun_l7_n579(x)
+ end
+end
+
+def fun_l6_n882(x)
+ if (x < 1)
+ fun_l7_n576(x)
+ else
+ fun_l7_n118(x)
+ end
+end
+
+def fun_l6_n883(x)
+ if (x < 1)
+ fun_l7_n218(x)
+ else
+ fun_l7_n197(x)
+ end
+end
+
+def fun_l6_n884(x)
+ if (x < 1)
+ fun_l7_n279(x)
+ else
+ fun_l7_n565(x)
+ end
+end
+
+def fun_l6_n885(x)
+ if (x < 1)
+ fun_l7_n934(x)
+ else
+ fun_l7_n46(x)
+ end
+end
+
+def fun_l6_n886(x)
+ if (x < 1)
+ fun_l7_n894(x)
+ else
+ fun_l7_n864(x)
+ end
+end
+
+def fun_l6_n887(x)
+ if (x < 1)
+ fun_l7_n45(x)
+ else
+ fun_l7_n151(x)
+ end
+end
+
+def fun_l6_n888(x)
+ if (x < 1)
+ fun_l7_n190(x)
+ else
+ fun_l7_n46(x)
+ end
+end
+
+def fun_l6_n889(x)
+ if (x < 1)
+ fun_l7_n56(x)
+ else
+ fun_l7_n451(x)
+ end
+end
+
+def fun_l6_n890(x)
+ if (x < 1)
+ fun_l7_n7(x)
+ else
+ fun_l7_n906(x)
+ end
+end
+
+def fun_l6_n891(x)
+ if (x < 1)
+ fun_l7_n507(x)
+ else
+ fun_l7_n121(x)
+ end
+end
+
+def fun_l6_n892(x)
+ if (x < 1)
+ fun_l7_n757(x)
+ else
+ fun_l7_n485(x)
+ end
+end
+
+def fun_l6_n893(x)
+ if (x < 1)
+ fun_l7_n242(x)
+ else
+ fun_l7_n366(x)
+ end
+end
+
+def fun_l6_n894(x)
+ if (x < 1)
+ fun_l7_n563(x)
+ else
+ fun_l7_n749(x)
+ end
+end
+
+def fun_l6_n895(x)
+ if (x < 1)
+ fun_l7_n976(x)
+ else
+ fun_l7_n907(x)
+ end
+end
+
+def fun_l6_n896(x)
+ if (x < 1)
+ fun_l7_n525(x)
+ else
+ fun_l7_n843(x)
+ end
+end
+
+def fun_l6_n897(x)
+ if (x < 1)
+ fun_l7_n255(x)
+ else
+ fun_l7_n133(x)
+ end
+end
+
+def fun_l6_n898(x)
+ if (x < 1)
+ fun_l7_n796(x)
+ else
+ fun_l7_n275(x)
+ end
+end
+
+def fun_l6_n899(x)
+ if (x < 1)
+ fun_l7_n985(x)
+ else
+ fun_l7_n485(x)
+ end
+end
+
+def fun_l6_n900(x)
+ if (x < 1)
+ fun_l7_n32(x)
+ else
+ fun_l7_n324(x)
+ end
+end
+
+def fun_l6_n901(x)
+ if (x < 1)
+ fun_l7_n334(x)
+ else
+ fun_l7_n618(x)
+ end
+end
+
+def fun_l6_n902(x)
+ if (x < 1)
+ fun_l7_n762(x)
+ else
+ fun_l7_n778(x)
+ end
+end
+
+def fun_l6_n903(x)
+ if (x < 1)
+ fun_l7_n343(x)
+ else
+ fun_l7_n349(x)
+ end
+end
+
+def fun_l6_n904(x)
+ if (x < 1)
+ fun_l7_n310(x)
+ else
+ fun_l7_n215(x)
+ end
+end
+
+def fun_l6_n905(x)
+ if (x < 1)
+ fun_l7_n162(x)
+ else
+ fun_l7_n405(x)
+ end
+end
+
+def fun_l6_n906(x)
+ if (x < 1)
+ fun_l7_n667(x)
+ else
+ fun_l7_n633(x)
+ end
+end
+
+def fun_l6_n907(x)
+ if (x < 1)
+ fun_l7_n652(x)
+ else
+ fun_l7_n771(x)
+ end
+end
+
+def fun_l6_n908(x)
+ if (x < 1)
+ fun_l7_n198(x)
+ else
+ fun_l7_n32(x)
+ end
+end
+
+def fun_l6_n909(x)
+ if (x < 1)
+ fun_l7_n577(x)
+ else
+ fun_l7_n116(x)
+ end
+end
+
+def fun_l6_n910(x)
+ if (x < 1)
+ fun_l7_n63(x)
+ else
+ fun_l7_n57(x)
+ end
+end
+
+def fun_l6_n911(x)
+ if (x < 1)
+ fun_l7_n908(x)
+ else
+ fun_l7_n556(x)
+ end
+end
+
+def fun_l6_n912(x)
+ if (x < 1)
+ fun_l7_n420(x)
+ else
+ fun_l7_n163(x)
+ end
+end
+
+def fun_l6_n913(x)
+ if (x < 1)
+ fun_l7_n795(x)
+ else
+ fun_l7_n225(x)
+ end
+end
+
+def fun_l6_n914(x)
+ if (x < 1)
+ fun_l7_n855(x)
+ else
+ fun_l7_n742(x)
+ end
+end
+
+def fun_l6_n915(x)
+ if (x < 1)
+ fun_l7_n386(x)
+ else
+ fun_l7_n314(x)
+ end
+end
+
+def fun_l6_n916(x)
+ if (x < 1)
+ fun_l7_n587(x)
+ else
+ fun_l7_n371(x)
+ end
+end
+
+def fun_l6_n917(x)
+ if (x < 1)
+ fun_l7_n570(x)
+ else
+ fun_l7_n735(x)
+ end
+end
+
+def fun_l6_n918(x)
+ if (x < 1)
+ fun_l7_n985(x)
+ else
+ fun_l7_n492(x)
+ end
+end
+
+def fun_l6_n919(x)
+ if (x < 1)
+ fun_l7_n991(x)
+ else
+ fun_l7_n454(x)
+ end
+end
+
+def fun_l6_n920(x)
+ if (x < 1)
+ fun_l7_n925(x)
+ else
+ fun_l7_n161(x)
+ end
+end
+
+def fun_l6_n921(x)
+ if (x < 1)
+ fun_l7_n398(x)
+ else
+ fun_l7_n621(x)
+ end
+end
+
+def fun_l6_n922(x)
+ if (x < 1)
+ fun_l7_n732(x)
+ else
+ fun_l7_n509(x)
+ end
+end
+
+def fun_l6_n923(x)
+ if (x < 1)
+ fun_l7_n879(x)
+ else
+ fun_l7_n219(x)
+ end
+end
+
+def fun_l6_n924(x)
+ if (x < 1)
+ fun_l7_n19(x)
+ else
+ fun_l7_n604(x)
+ end
+end
+
+def fun_l6_n925(x)
+ if (x < 1)
+ fun_l7_n474(x)
+ else
+ fun_l7_n439(x)
+ end
+end
+
+def fun_l6_n926(x)
+ if (x < 1)
+ fun_l7_n807(x)
+ else
+ fun_l7_n802(x)
+ end
+end
+
+def fun_l6_n927(x)
+ if (x < 1)
+ fun_l7_n146(x)
+ else
+ fun_l7_n966(x)
+ end
+end
+
+def fun_l6_n928(x)
+ if (x < 1)
+ fun_l7_n72(x)
+ else
+ fun_l7_n835(x)
+ end
+end
+
+def fun_l6_n929(x)
+ if (x < 1)
+ fun_l7_n389(x)
+ else
+ fun_l7_n951(x)
+ end
+end
+
+def fun_l6_n930(x)
+ if (x < 1)
+ fun_l7_n104(x)
+ else
+ fun_l7_n719(x)
+ end
+end
+
+def fun_l6_n931(x)
+ if (x < 1)
+ fun_l7_n250(x)
+ else
+ fun_l7_n13(x)
+ end
+end
+
+def fun_l6_n932(x)
+ if (x < 1)
+ fun_l7_n470(x)
+ else
+ fun_l7_n984(x)
+ end
+end
+
+def fun_l6_n933(x)
+ if (x < 1)
+ fun_l7_n485(x)
+ else
+ fun_l7_n750(x)
+ end
+end
+
+def fun_l6_n934(x)
+ if (x < 1)
+ fun_l7_n371(x)
+ else
+ fun_l7_n912(x)
+ end
+end
+
+def fun_l6_n935(x)
+ if (x < 1)
+ fun_l7_n686(x)
+ else
+ fun_l7_n523(x)
+ end
+end
+
+def fun_l6_n936(x)
+ if (x < 1)
+ fun_l7_n998(x)
+ else
+ fun_l7_n6(x)
+ end
+end
+
+def fun_l6_n937(x)
+ if (x < 1)
+ fun_l7_n753(x)
+ else
+ fun_l7_n781(x)
+ end
+end
+
+def fun_l6_n938(x)
+ if (x < 1)
+ fun_l7_n518(x)
+ else
+ fun_l7_n18(x)
+ end
+end
+
+def fun_l6_n939(x)
+ if (x < 1)
+ fun_l7_n771(x)
+ else
+ fun_l7_n1(x)
+ end
+end
+
+def fun_l6_n940(x)
+ if (x < 1)
+ fun_l7_n43(x)
+ else
+ fun_l7_n727(x)
+ end
+end
+
+def fun_l6_n941(x)
+ if (x < 1)
+ fun_l7_n282(x)
+ else
+ fun_l7_n676(x)
+ end
+end
+
+def fun_l6_n942(x)
+ if (x < 1)
+ fun_l7_n284(x)
+ else
+ fun_l7_n56(x)
+ end
+end
+
+def fun_l6_n943(x)
+ if (x < 1)
+ fun_l7_n304(x)
+ else
+ fun_l7_n287(x)
+ end
+end
+
+def fun_l6_n944(x)
+ if (x < 1)
+ fun_l7_n968(x)
+ else
+ fun_l7_n283(x)
+ end
+end
+
+def fun_l6_n945(x)
+ if (x < 1)
+ fun_l7_n892(x)
+ else
+ fun_l7_n413(x)
+ end
+end
+
+def fun_l6_n946(x)
+ if (x < 1)
+ fun_l7_n750(x)
+ else
+ fun_l7_n244(x)
+ end
+end
+
+def fun_l6_n947(x)
+ if (x < 1)
+ fun_l7_n599(x)
+ else
+ fun_l7_n238(x)
+ end
+end
+
+def fun_l6_n948(x)
+ if (x < 1)
+ fun_l7_n447(x)
+ else
+ fun_l7_n880(x)
+ end
+end
+
+def fun_l6_n949(x)
+ if (x < 1)
+ fun_l7_n242(x)
+ else
+ fun_l7_n210(x)
+ end
+end
+
+def fun_l6_n950(x)
+ if (x < 1)
+ fun_l7_n143(x)
+ else
+ fun_l7_n816(x)
+ end
+end
+
+def fun_l6_n951(x)
+ if (x < 1)
+ fun_l7_n125(x)
+ else
+ fun_l7_n909(x)
+ end
+end
+
+def fun_l6_n952(x)
+ if (x < 1)
+ fun_l7_n134(x)
+ else
+ fun_l7_n946(x)
+ end
+end
+
+def fun_l6_n953(x)
+ if (x < 1)
+ fun_l7_n858(x)
+ else
+ fun_l7_n927(x)
+ end
+end
+
+def fun_l6_n954(x)
+ if (x < 1)
+ fun_l7_n853(x)
+ else
+ fun_l7_n396(x)
+ end
+end
+
+def fun_l6_n955(x)
+ if (x < 1)
+ fun_l7_n725(x)
+ else
+ fun_l7_n42(x)
+ end
+end
+
+def fun_l6_n956(x)
+ if (x < 1)
+ fun_l7_n108(x)
+ else
+ fun_l7_n177(x)
+ end
+end
+
+def fun_l6_n957(x)
+ if (x < 1)
+ fun_l7_n742(x)
+ else
+ fun_l7_n482(x)
+ end
+end
+
+def fun_l6_n958(x)
+ if (x < 1)
+ fun_l7_n385(x)
+ else
+ fun_l7_n292(x)
+ end
+end
+
+def fun_l6_n959(x)
+ if (x < 1)
+ fun_l7_n325(x)
+ else
+ fun_l7_n27(x)
+ end
+end
+
+def fun_l6_n960(x)
+ if (x < 1)
+ fun_l7_n558(x)
+ else
+ fun_l7_n556(x)
+ end
+end
+
+def fun_l6_n961(x)
+ if (x < 1)
+ fun_l7_n472(x)
+ else
+ fun_l7_n322(x)
+ end
+end
+
+def fun_l6_n962(x)
+ if (x < 1)
+ fun_l7_n754(x)
+ else
+ fun_l7_n729(x)
+ end
+end
+
+def fun_l6_n963(x)
+ if (x < 1)
+ fun_l7_n35(x)
+ else
+ fun_l7_n232(x)
+ end
+end
+
+def fun_l6_n964(x)
+ if (x < 1)
+ fun_l7_n113(x)
+ else
+ fun_l7_n878(x)
+ end
+end
+
+def fun_l6_n965(x)
+ if (x < 1)
+ fun_l7_n982(x)
+ else
+ fun_l7_n404(x)
+ end
+end
+
+def fun_l6_n966(x)
+ if (x < 1)
+ fun_l7_n385(x)
+ else
+ fun_l7_n20(x)
+ end
+end
+
+def fun_l6_n967(x)
+ if (x < 1)
+ fun_l7_n394(x)
+ else
+ fun_l7_n873(x)
+ end
+end
+
+def fun_l6_n968(x)
+ if (x < 1)
+ fun_l7_n230(x)
+ else
+ fun_l7_n141(x)
+ end
+end
+
+def fun_l6_n969(x)
+ if (x < 1)
+ fun_l7_n742(x)
+ else
+ fun_l7_n75(x)
+ end
+end
+
+def fun_l6_n970(x)
+ if (x < 1)
+ fun_l7_n583(x)
+ else
+ fun_l7_n809(x)
+ end
+end
+
+def fun_l6_n971(x)
+ if (x < 1)
+ fun_l7_n535(x)
+ else
+ fun_l7_n151(x)
+ end
+end
+
+def fun_l6_n972(x)
+ if (x < 1)
+ fun_l7_n42(x)
+ else
+ fun_l7_n469(x)
+ end
+end
+
+def fun_l6_n973(x)
+ if (x < 1)
+ fun_l7_n964(x)
+ else
+ fun_l7_n759(x)
+ end
+end
+
+def fun_l6_n974(x)
+ if (x < 1)
+ fun_l7_n897(x)
+ else
+ fun_l7_n29(x)
+ end
+end
+
+def fun_l6_n975(x)
+ if (x < 1)
+ fun_l7_n331(x)
+ else
+ fun_l7_n972(x)
+ end
+end
+
+def fun_l6_n976(x)
+ if (x < 1)
+ fun_l7_n825(x)
+ else
+ fun_l7_n221(x)
+ end
+end
+
+def fun_l6_n977(x)
+ if (x < 1)
+ fun_l7_n207(x)
+ else
+ fun_l7_n520(x)
+ end
+end
+
+def fun_l6_n978(x)
+ if (x < 1)
+ fun_l7_n231(x)
+ else
+ fun_l7_n552(x)
+ end
+end
+
+def fun_l6_n979(x)
+ if (x < 1)
+ fun_l7_n621(x)
+ else
+ fun_l7_n766(x)
+ end
+end
+
+def fun_l6_n980(x)
+ if (x < 1)
+ fun_l7_n461(x)
+ else
+ fun_l7_n552(x)
+ end
+end
+
+def fun_l6_n981(x)
+ if (x < 1)
+ fun_l7_n891(x)
+ else
+ fun_l7_n710(x)
+ end
+end
+
+def fun_l6_n982(x)
+ if (x < 1)
+ fun_l7_n253(x)
+ else
+ fun_l7_n104(x)
+ end
+end
+
+def fun_l6_n983(x)
+ if (x < 1)
+ fun_l7_n726(x)
+ else
+ fun_l7_n903(x)
+ end
+end
+
+def fun_l6_n984(x)
+ if (x < 1)
+ fun_l7_n524(x)
+ else
+ fun_l7_n700(x)
+ end
+end
+
+def fun_l6_n985(x)
+ if (x < 1)
+ fun_l7_n234(x)
+ else
+ fun_l7_n454(x)
+ end
+end
+
+def fun_l6_n986(x)
+ if (x < 1)
+ fun_l7_n379(x)
+ else
+ fun_l7_n504(x)
+ end
+end
+
+def fun_l6_n987(x)
+ if (x < 1)
+ fun_l7_n194(x)
+ else
+ fun_l7_n962(x)
+ end
+end
+
+def fun_l6_n988(x)
+ if (x < 1)
+ fun_l7_n60(x)
+ else
+ fun_l7_n699(x)
+ end
+end
+
+def fun_l6_n989(x)
+ if (x < 1)
+ fun_l7_n692(x)
+ else
+ fun_l7_n28(x)
+ end
+end
+
+def fun_l6_n990(x)
+ if (x < 1)
+ fun_l7_n456(x)
+ else
+ fun_l7_n126(x)
+ end
+end
+
+def fun_l6_n991(x)
+ if (x < 1)
+ fun_l7_n104(x)
+ else
+ fun_l7_n156(x)
+ end
+end
+
+def fun_l6_n992(x)
+ if (x < 1)
+ fun_l7_n269(x)
+ else
+ fun_l7_n513(x)
+ end
+end
+
+def fun_l6_n993(x)
+ if (x < 1)
+ fun_l7_n20(x)
+ else
+ fun_l7_n754(x)
+ end
+end
+
+def fun_l6_n994(x)
+ if (x < 1)
+ fun_l7_n445(x)
+ else
+ fun_l7_n422(x)
+ end
+end
+
+def fun_l6_n995(x)
+ if (x < 1)
+ fun_l7_n320(x)
+ else
+ fun_l7_n398(x)
+ end
+end
+
+def fun_l6_n996(x)
+ if (x < 1)
+ fun_l7_n479(x)
+ else
+ fun_l7_n238(x)
+ end
+end
+
+def fun_l6_n997(x)
+ if (x < 1)
+ fun_l7_n254(x)
+ else
+ fun_l7_n692(x)
+ end
+end
+
+def fun_l6_n998(x)
+ if (x < 1)
+ fun_l7_n774(x)
+ else
+ fun_l7_n510(x)
+ end
+end
+
+def fun_l6_n999(x)
+ if (x < 1)
+ fun_l7_n158(x)
+ else
+ fun_l7_n929(x)
+ end
+end
+
+def fun_l7_n0(x)
+ if (x < 1)
+ fun_l8_n414(x)
+ else
+ fun_l8_n327(x)
+ end
+end
+
+def fun_l7_n1(x)
+ if (x < 1)
+ fun_l8_n446(x)
+ else
+ fun_l8_n611(x)
+ end
+end
+
+def fun_l7_n2(x)
+ if (x < 1)
+ fun_l8_n116(x)
+ else
+ fun_l8_n224(x)
+ end
+end
+
+def fun_l7_n3(x)
+ if (x < 1)
+ fun_l8_n809(x)
+ else
+ fun_l8_n962(x)
+ end
+end
+
+def fun_l7_n4(x)
+ if (x < 1)
+ fun_l8_n137(x)
+ else
+ fun_l8_n426(x)
+ end
+end
+
+def fun_l7_n5(x)
+ if (x < 1)
+ fun_l8_n686(x)
+ else
+ fun_l8_n600(x)
+ end
+end
+
+def fun_l7_n6(x)
+ if (x < 1)
+ fun_l8_n430(x)
+ else
+ fun_l8_n302(x)
+ end
+end
+
+def fun_l7_n7(x)
+ if (x < 1)
+ fun_l8_n865(x)
+ else
+ fun_l8_n60(x)
+ end
+end
+
+def fun_l7_n8(x)
+ if (x < 1)
+ fun_l8_n895(x)
+ else
+ fun_l8_n148(x)
+ end
+end
+
+def fun_l7_n9(x)
+ if (x < 1)
+ fun_l8_n740(x)
+ else
+ fun_l8_n982(x)
+ end
+end
+
+def fun_l7_n10(x)
+ if (x < 1)
+ fun_l8_n757(x)
+ else
+ fun_l8_n640(x)
+ end
+end
+
+def fun_l7_n11(x)
+ if (x < 1)
+ fun_l8_n744(x)
+ else
+ fun_l8_n256(x)
+ end
+end
+
+def fun_l7_n12(x)
+ if (x < 1)
+ fun_l8_n272(x)
+ else
+ fun_l8_n828(x)
+ end
+end
+
+def fun_l7_n13(x)
+ if (x < 1)
+ fun_l8_n395(x)
+ else
+ fun_l8_n932(x)
+ end
+end
+
+def fun_l7_n14(x)
+ if (x < 1)
+ fun_l8_n178(x)
+ else
+ fun_l8_n676(x)
+ end
+end
+
+def fun_l7_n15(x)
+ if (x < 1)
+ fun_l8_n40(x)
+ else
+ fun_l8_n548(x)
+ end
+end
+
+def fun_l7_n16(x)
+ if (x < 1)
+ fun_l8_n506(x)
+ else
+ fun_l8_n234(x)
+ end
+end
+
+def fun_l7_n17(x)
+ if (x < 1)
+ fun_l8_n239(x)
+ else
+ fun_l8_n56(x)
+ end
+end
+
+def fun_l7_n18(x)
+ if (x < 1)
+ fun_l8_n381(x)
+ else
+ fun_l8_n720(x)
+ end
+end
+
+def fun_l7_n19(x)
+ if (x < 1)
+ fun_l8_n781(x)
+ else
+ fun_l8_n605(x)
+ end
+end
+
+def fun_l7_n20(x)
+ if (x < 1)
+ fun_l8_n479(x)
+ else
+ fun_l8_n894(x)
+ end
+end
+
+def fun_l7_n21(x)
+ if (x < 1)
+ fun_l8_n437(x)
+ else
+ fun_l8_n123(x)
+ end
+end
+
+def fun_l7_n22(x)
+ if (x < 1)
+ fun_l8_n20(x)
+ else
+ fun_l8_n144(x)
+ end
+end
+
+def fun_l7_n23(x)
+ if (x < 1)
+ fun_l8_n684(x)
+ else
+ fun_l8_n866(x)
+ end
+end
+
+def fun_l7_n24(x)
+ if (x < 1)
+ fun_l8_n527(x)
+ else
+ fun_l8_n629(x)
+ end
+end
+
+def fun_l7_n25(x)
+ if (x < 1)
+ fun_l8_n399(x)
+ else
+ fun_l8_n52(x)
+ end
+end
+
+def fun_l7_n26(x)
+ if (x < 1)
+ fun_l8_n353(x)
+ else
+ fun_l8_n438(x)
+ end
+end
+
+def fun_l7_n27(x)
+ if (x < 1)
+ fun_l8_n916(x)
+ else
+ fun_l8_n488(x)
+ end
+end
+
+def fun_l7_n28(x)
+ if (x < 1)
+ fun_l8_n833(x)
+ else
+ fun_l8_n585(x)
+ end
+end
+
+def fun_l7_n29(x)
+ if (x < 1)
+ fun_l8_n38(x)
+ else
+ fun_l8_n785(x)
+ end
+end
+
+def fun_l7_n30(x)
+ if (x < 1)
+ fun_l8_n157(x)
+ else
+ fun_l8_n332(x)
+ end
+end
+
+def fun_l7_n31(x)
+ if (x < 1)
+ fun_l8_n467(x)
+ else
+ fun_l8_n442(x)
+ end
+end
+
+def fun_l7_n32(x)
+ if (x < 1)
+ fun_l8_n704(x)
+ else
+ fun_l8_n295(x)
+ end
+end
+
+def fun_l7_n33(x)
+ if (x < 1)
+ fun_l8_n829(x)
+ else
+ fun_l8_n307(x)
+ end
+end
+
+def fun_l7_n34(x)
+ if (x < 1)
+ fun_l8_n227(x)
+ else
+ fun_l8_n865(x)
+ end
+end
+
+def fun_l7_n35(x)
+ if (x < 1)
+ fun_l8_n930(x)
+ else
+ fun_l8_n129(x)
+ end
+end
+
+def fun_l7_n36(x)
+ if (x < 1)
+ fun_l8_n519(x)
+ else
+ fun_l8_n587(x)
+ end
+end
+
+def fun_l7_n37(x)
+ if (x < 1)
+ fun_l8_n132(x)
+ else
+ fun_l8_n547(x)
+ end
+end
+
+def fun_l7_n38(x)
+ if (x < 1)
+ fun_l8_n627(x)
+ else
+ fun_l8_n712(x)
+ end
+end
+
+def fun_l7_n39(x)
+ if (x < 1)
+ fun_l8_n752(x)
+ else
+ fun_l8_n357(x)
+ end
+end
+
+def fun_l7_n40(x)
+ if (x < 1)
+ fun_l8_n542(x)
+ else
+ fun_l8_n86(x)
+ end
+end
+
+def fun_l7_n41(x)
+ if (x < 1)
+ fun_l8_n89(x)
+ else
+ fun_l8_n492(x)
+ end
+end
+
+def fun_l7_n42(x)
+ if (x < 1)
+ fun_l8_n508(x)
+ else
+ fun_l8_n288(x)
+ end
+end
+
+def fun_l7_n43(x)
+ if (x < 1)
+ fun_l8_n627(x)
+ else
+ fun_l8_n632(x)
+ end
+end
+
+def fun_l7_n44(x)
+ if (x < 1)
+ fun_l8_n513(x)
+ else
+ fun_l8_n472(x)
+ end
+end
+
+def fun_l7_n45(x)
+ if (x < 1)
+ fun_l8_n599(x)
+ else
+ fun_l8_n581(x)
+ end
+end
+
+def fun_l7_n46(x)
+ if (x < 1)
+ fun_l8_n907(x)
+ else
+ fun_l8_n71(x)
+ end
+end
+
+def fun_l7_n47(x)
+ if (x < 1)
+ fun_l8_n609(x)
+ else
+ fun_l8_n601(x)
+ end
+end
+
+def fun_l7_n48(x)
+ if (x < 1)
+ fun_l8_n985(x)
+ else
+ fun_l8_n536(x)
+ end
+end
+
+def fun_l7_n49(x)
+ if (x < 1)
+ fun_l8_n220(x)
+ else
+ fun_l8_n6(x)
+ end
+end
+
+def fun_l7_n50(x)
+ if (x < 1)
+ fun_l8_n445(x)
+ else
+ fun_l8_n939(x)
+ end
+end
+
+def fun_l7_n51(x)
+ if (x < 1)
+ fun_l8_n973(x)
+ else
+ fun_l8_n600(x)
+ end
+end
+
+def fun_l7_n52(x)
+ if (x < 1)
+ fun_l8_n377(x)
+ else
+ fun_l8_n70(x)
+ end
+end
+
+def fun_l7_n53(x)
+ if (x < 1)
+ fun_l8_n745(x)
+ else
+ fun_l8_n237(x)
+ end
+end
+
+def fun_l7_n54(x)
+ if (x < 1)
+ fun_l8_n782(x)
+ else
+ fun_l8_n756(x)
+ end
+end
+
+def fun_l7_n55(x)
+ if (x < 1)
+ fun_l8_n438(x)
+ else
+ fun_l8_n892(x)
+ end
+end
+
+def fun_l7_n56(x)
+ if (x < 1)
+ fun_l8_n564(x)
+ else
+ fun_l8_n600(x)
+ end
+end
+
+def fun_l7_n57(x)
+ if (x < 1)
+ fun_l8_n480(x)
+ else
+ fun_l8_n832(x)
+ end
+end
+
+def fun_l7_n58(x)
+ if (x < 1)
+ fun_l8_n239(x)
+ else
+ fun_l8_n540(x)
+ end
+end
+
+def fun_l7_n59(x)
+ if (x < 1)
+ fun_l8_n904(x)
+ else
+ fun_l8_n334(x)
+ end
+end
+
+def fun_l7_n60(x)
+ if (x < 1)
+ fun_l8_n407(x)
+ else
+ fun_l8_n573(x)
+ end
+end
+
+def fun_l7_n61(x)
+ if (x < 1)
+ fun_l8_n705(x)
+ else
+ fun_l8_n202(x)
+ end
+end
+
+def fun_l7_n62(x)
+ if (x < 1)
+ fun_l8_n715(x)
+ else
+ fun_l8_n394(x)
+ end
+end
+
+def fun_l7_n63(x)
+ if (x < 1)
+ fun_l8_n935(x)
+ else
+ fun_l8_n855(x)
+ end
+end
+
+def fun_l7_n64(x)
+ if (x < 1)
+ fun_l8_n525(x)
+ else
+ fun_l8_n81(x)
+ end
+end
+
+def fun_l7_n65(x)
+ if (x < 1)
+ fun_l8_n692(x)
+ else
+ fun_l8_n372(x)
+ end
+end
+
+def fun_l7_n66(x)
+ if (x < 1)
+ fun_l8_n286(x)
+ else
+ fun_l8_n568(x)
+ end
+end
+
+def fun_l7_n67(x)
+ if (x < 1)
+ fun_l8_n829(x)
+ else
+ fun_l8_n89(x)
+ end
+end
+
+def fun_l7_n68(x)
+ if (x < 1)
+ fun_l8_n542(x)
+ else
+ fun_l8_n362(x)
+ end
+end
+
+def fun_l7_n69(x)
+ if (x < 1)
+ fun_l8_n673(x)
+ else
+ fun_l8_n302(x)
+ end
+end
+
+def fun_l7_n70(x)
+ if (x < 1)
+ fun_l8_n649(x)
+ else
+ fun_l8_n890(x)
+ end
+end
+
+def fun_l7_n71(x)
+ if (x < 1)
+ fun_l8_n639(x)
+ else
+ fun_l8_n304(x)
+ end
+end
+
+def fun_l7_n72(x)
+ if (x < 1)
+ fun_l8_n797(x)
+ else
+ fun_l8_n132(x)
+ end
+end
+
+def fun_l7_n73(x)
+ if (x < 1)
+ fun_l8_n301(x)
+ else
+ fun_l8_n328(x)
+ end
+end
+
+def fun_l7_n74(x)
+ if (x < 1)
+ fun_l8_n438(x)
+ else
+ fun_l8_n979(x)
+ end
+end
+
+def fun_l7_n75(x)
+ if (x < 1)
+ fun_l8_n679(x)
+ else
+ fun_l8_n621(x)
+ end
+end
+
+def fun_l7_n76(x)
+ if (x < 1)
+ fun_l8_n136(x)
+ else
+ fun_l8_n916(x)
+ end
+end
+
+def fun_l7_n77(x)
+ if (x < 1)
+ fun_l8_n39(x)
+ else
+ fun_l8_n945(x)
+ end
+end
+
+def fun_l7_n78(x)
+ if (x < 1)
+ fun_l8_n365(x)
+ else
+ fun_l8_n883(x)
+ end
+end
+
+def fun_l7_n79(x)
+ if (x < 1)
+ fun_l8_n514(x)
+ else
+ fun_l8_n989(x)
+ end
+end
+
+def fun_l7_n80(x)
+ if (x < 1)
+ fun_l8_n378(x)
+ else
+ fun_l8_n634(x)
+ end
+end
+
+def fun_l7_n81(x)
+ if (x < 1)
+ fun_l8_n200(x)
+ else
+ fun_l8_n73(x)
+ end
+end
+
+def fun_l7_n82(x)
+ if (x < 1)
+ fun_l8_n521(x)
+ else
+ fun_l8_n848(x)
+ end
+end
+
+def fun_l7_n83(x)
+ if (x < 1)
+ fun_l8_n184(x)
+ else
+ fun_l8_n350(x)
+ end
+end
+
+def fun_l7_n84(x)
+ if (x < 1)
+ fun_l8_n215(x)
+ else
+ fun_l8_n615(x)
+ end
+end
+
+def fun_l7_n85(x)
+ if (x < 1)
+ fun_l8_n556(x)
+ else
+ fun_l8_n723(x)
+ end
+end
+
+def fun_l7_n86(x)
+ if (x < 1)
+ fun_l8_n565(x)
+ else
+ fun_l8_n661(x)
+ end
+end
+
+def fun_l7_n87(x)
+ if (x < 1)
+ fun_l8_n22(x)
+ else
+ fun_l8_n623(x)
+ end
+end
+
+def fun_l7_n88(x)
+ if (x < 1)
+ fun_l8_n995(x)
+ else
+ fun_l8_n30(x)
+ end
+end
+
+def fun_l7_n89(x)
+ if (x < 1)
+ fun_l8_n912(x)
+ else
+ fun_l8_n332(x)
+ end
+end
+
+def fun_l7_n90(x)
+ if (x < 1)
+ fun_l8_n776(x)
+ else
+ fun_l8_n362(x)
+ end
+end
+
+def fun_l7_n91(x)
+ if (x < 1)
+ fun_l8_n720(x)
+ else
+ fun_l8_n512(x)
+ end
+end
+
+def fun_l7_n92(x)
+ if (x < 1)
+ fun_l8_n437(x)
+ else
+ fun_l8_n107(x)
+ end
+end
+
+def fun_l7_n93(x)
+ if (x < 1)
+ fun_l8_n143(x)
+ else
+ fun_l8_n493(x)
+ end
+end
+
+def fun_l7_n94(x)
+ if (x < 1)
+ fun_l8_n814(x)
+ else
+ fun_l8_n892(x)
+ end
+end
+
+def fun_l7_n95(x)
+ if (x < 1)
+ fun_l8_n117(x)
+ else
+ fun_l8_n18(x)
+ end
+end
+
+def fun_l7_n96(x)
+ if (x < 1)
+ fun_l8_n769(x)
+ else
+ fun_l8_n37(x)
+ end
+end
+
+def fun_l7_n97(x)
+ if (x < 1)
+ fun_l8_n213(x)
+ else
+ fun_l8_n5(x)
+ end
+end
+
+def fun_l7_n98(x)
+ if (x < 1)
+ fun_l8_n608(x)
+ else
+ fun_l8_n551(x)
+ end
+end
+
+def fun_l7_n99(x)
+ if (x < 1)
+ fun_l8_n130(x)
+ else
+ fun_l8_n879(x)
+ end
+end
+
+def fun_l7_n100(x)
+ if (x < 1)
+ fun_l8_n279(x)
+ else
+ fun_l8_n786(x)
+ end
+end
+
+def fun_l7_n101(x)
+ if (x < 1)
+ fun_l8_n254(x)
+ else
+ fun_l8_n904(x)
+ end
+end
+
+def fun_l7_n102(x)
+ if (x < 1)
+ fun_l8_n661(x)
+ else
+ fun_l8_n873(x)
+ end
+end
+
+def fun_l7_n103(x)
+ if (x < 1)
+ fun_l8_n360(x)
+ else
+ fun_l8_n793(x)
+ end
+end
+
+def fun_l7_n104(x)
+ if (x < 1)
+ fun_l8_n687(x)
+ else
+ fun_l8_n853(x)
+ end
+end
+
+def fun_l7_n105(x)
+ if (x < 1)
+ fun_l8_n168(x)
+ else
+ fun_l8_n280(x)
+ end
+end
+
+def fun_l7_n106(x)
+ if (x < 1)
+ fun_l8_n742(x)
+ else
+ fun_l8_n222(x)
+ end
+end
+
+def fun_l7_n107(x)
+ if (x < 1)
+ fun_l8_n470(x)
+ else
+ fun_l8_n633(x)
+ end
+end
+
+def fun_l7_n108(x)
+ if (x < 1)
+ fun_l8_n495(x)
+ else
+ fun_l8_n253(x)
+ end
+end
+
+def fun_l7_n109(x)
+ if (x < 1)
+ fun_l8_n369(x)
+ else
+ fun_l8_n108(x)
+ end
+end
+
+def fun_l7_n110(x)
+ if (x < 1)
+ fun_l8_n254(x)
+ else
+ fun_l8_n162(x)
+ end
+end
+
+def fun_l7_n111(x)
+ if (x < 1)
+ fun_l8_n835(x)
+ else
+ fun_l8_n295(x)
+ end
+end
+
+def fun_l7_n112(x)
+ if (x < 1)
+ fun_l8_n349(x)
+ else
+ fun_l8_n432(x)
+ end
+end
+
+def fun_l7_n113(x)
+ if (x < 1)
+ fun_l8_n237(x)
+ else
+ fun_l8_n484(x)
+ end
+end
+
+def fun_l7_n114(x)
+ if (x < 1)
+ fun_l8_n755(x)
+ else
+ fun_l8_n819(x)
+ end
+end
+
+def fun_l7_n115(x)
+ if (x < 1)
+ fun_l8_n542(x)
+ else
+ fun_l8_n587(x)
+ end
+end
+
+def fun_l7_n116(x)
+ if (x < 1)
+ fun_l8_n837(x)
+ else
+ fun_l8_n274(x)
+ end
+end
+
+def fun_l7_n117(x)
+ if (x < 1)
+ fun_l8_n742(x)
+ else
+ fun_l8_n104(x)
+ end
+end
+
+def fun_l7_n118(x)
+ if (x < 1)
+ fun_l8_n201(x)
+ else
+ fun_l8_n340(x)
+ end
+end
+
+def fun_l7_n119(x)
+ if (x < 1)
+ fun_l8_n349(x)
+ else
+ fun_l8_n213(x)
+ end
+end
+
+def fun_l7_n120(x)
+ if (x < 1)
+ fun_l8_n563(x)
+ else
+ fun_l8_n193(x)
+ end
+end
+
+def fun_l7_n121(x)
+ if (x < 1)
+ fun_l8_n738(x)
+ else
+ fun_l8_n600(x)
+ end
+end
+
+def fun_l7_n122(x)
+ if (x < 1)
+ fun_l8_n261(x)
+ else
+ fun_l8_n500(x)
+ end
+end
+
+def fun_l7_n123(x)
+ if (x < 1)
+ fun_l8_n870(x)
+ else
+ fun_l8_n423(x)
+ end
+end
+
+def fun_l7_n124(x)
+ if (x < 1)
+ fun_l8_n405(x)
+ else
+ fun_l8_n749(x)
+ end
+end
+
+def fun_l7_n125(x)
+ if (x < 1)
+ fun_l8_n848(x)
+ else
+ fun_l8_n106(x)
+ end
+end
+
+def fun_l7_n126(x)
+ if (x < 1)
+ fun_l8_n382(x)
+ else
+ fun_l8_n379(x)
+ end
+end
+
+def fun_l7_n127(x)
+ if (x < 1)
+ fun_l8_n232(x)
+ else
+ fun_l8_n913(x)
+ end
+end
+
+def fun_l7_n128(x)
+ if (x < 1)
+ fun_l8_n7(x)
+ else
+ fun_l8_n177(x)
+ end
+end
+
+def fun_l7_n129(x)
+ if (x < 1)
+ fun_l8_n86(x)
+ else
+ fun_l8_n670(x)
+ end
+end
+
+def fun_l7_n130(x)
+ if (x < 1)
+ fun_l8_n361(x)
+ else
+ fun_l8_n132(x)
+ end
+end
+
+def fun_l7_n131(x)
+ if (x < 1)
+ fun_l8_n125(x)
+ else
+ fun_l8_n925(x)
+ end
+end
+
+def fun_l7_n132(x)
+ if (x < 1)
+ fun_l8_n529(x)
+ else
+ fun_l8_n996(x)
+ end
+end
+
+def fun_l7_n133(x)
+ if (x < 1)
+ fun_l8_n283(x)
+ else
+ fun_l8_n112(x)
+ end
+end
+
+def fun_l7_n134(x)
+ if (x < 1)
+ fun_l8_n974(x)
+ else
+ fun_l8_n204(x)
+ end
+end
+
+def fun_l7_n135(x)
+ if (x < 1)
+ fun_l8_n903(x)
+ else
+ fun_l8_n196(x)
+ end
+end
+
+def fun_l7_n136(x)
+ if (x < 1)
+ fun_l8_n59(x)
+ else
+ fun_l8_n505(x)
+ end
+end
+
+def fun_l7_n137(x)
+ if (x < 1)
+ fun_l8_n530(x)
+ else
+ fun_l8_n31(x)
+ end
+end
+
+def fun_l7_n138(x)
+ if (x < 1)
+ fun_l8_n990(x)
+ else
+ fun_l8_n924(x)
+ end
+end
+
+def fun_l7_n139(x)
+ if (x < 1)
+ fun_l8_n202(x)
+ else
+ fun_l8_n980(x)
+ end
+end
+
+def fun_l7_n140(x)
+ if (x < 1)
+ fun_l8_n354(x)
+ else
+ fun_l8_n694(x)
+ end
+end
+
+def fun_l7_n141(x)
+ if (x < 1)
+ fun_l8_n306(x)
+ else
+ fun_l8_n307(x)
+ end
+end
+
+def fun_l7_n142(x)
+ if (x < 1)
+ fun_l8_n433(x)
+ else
+ fun_l8_n902(x)
+ end
+end
+
+def fun_l7_n143(x)
+ if (x < 1)
+ fun_l8_n522(x)
+ else
+ fun_l8_n904(x)
+ end
+end
+
+def fun_l7_n144(x)
+ if (x < 1)
+ fun_l8_n86(x)
+ else
+ fun_l8_n11(x)
+ end
+end
+
+def fun_l7_n145(x)
+ if (x < 1)
+ fun_l8_n147(x)
+ else
+ fun_l8_n21(x)
+ end
+end
+
+def fun_l7_n146(x)
+ if (x < 1)
+ fun_l8_n47(x)
+ else
+ fun_l8_n855(x)
+ end
+end
+
+def fun_l7_n147(x)
+ if (x < 1)
+ fun_l8_n306(x)
+ else
+ fun_l8_n309(x)
+ end
+end
+
+def fun_l7_n148(x)
+ if (x < 1)
+ fun_l8_n757(x)
+ else
+ fun_l8_n83(x)
+ end
+end
+
+def fun_l7_n149(x)
+ if (x < 1)
+ fun_l8_n377(x)
+ else
+ fun_l8_n124(x)
+ end
+end
+
+def fun_l7_n150(x)
+ if (x < 1)
+ fun_l8_n276(x)
+ else
+ fun_l8_n838(x)
+ end
+end
+
+def fun_l7_n151(x)
+ if (x < 1)
+ fun_l8_n148(x)
+ else
+ fun_l8_n653(x)
+ end
+end
+
+def fun_l7_n152(x)
+ if (x < 1)
+ fun_l8_n315(x)
+ else
+ fun_l8_n942(x)
+ end
+end
+
+def fun_l7_n153(x)
+ if (x < 1)
+ fun_l8_n794(x)
+ else
+ fun_l8_n680(x)
+ end
+end
+
+def fun_l7_n154(x)
+ if (x < 1)
+ fun_l8_n508(x)
+ else
+ fun_l8_n427(x)
+ end
+end
+
+def fun_l7_n155(x)
+ if (x < 1)
+ fun_l8_n249(x)
+ else
+ fun_l8_n615(x)
+ end
+end
+
+def fun_l7_n156(x)
+ if (x < 1)
+ fun_l8_n339(x)
+ else
+ fun_l8_n559(x)
+ end
+end
+
+def fun_l7_n157(x)
+ if (x < 1)
+ fun_l8_n772(x)
+ else
+ fun_l8_n128(x)
+ end
+end
+
+def fun_l7_n158(x)
+ if (x < 1)
+ fun_l8_n247(x)
+ else
+ fun_l8_n962(x)
+ end
+end
+
+def fun_l7_n159(x)
+ if (x < 1)
+ fun_l8_n648(x)
+ else
+ fun_l8_n338(x)
+ end
+end
+
+def fun_l7_n160(x)
+ if (x < 1)
+ fun_l8_n104(x)
+ else
+ fun_l8_n757(x)
+ end
+end
+
+def fun_l7_n161(x)
+ if (x < 1)
+ fun_l8_n74(x)
+ else
+ fun_l8_n288(x)
+ end
+end
+
+def fun_l7_n162(x)
+ if (x < 1)
+ fun_l8_n849(x)
+ else
+ fun_l8_n982(x)
+ end
+end
+
+def fun_l7_n163(x)
+ if (x < 1)
+ fun_l8_n433(x)
+ else
+ fun_l8_n442(x)
+ end
+end
+
+def fun_l7_n164(x)
+ if (x < 1)
+ fun_l8_n268(x)
+ else
+ fun_l8_n717(x)
+ end
+end
+
+def fun_l7_n165(x)
+ if (x < 1)
+ fun_l8_n185(x)
+ else
+ fun_l8_n628(x)
+ end
+end
+
+def fun_l7_n166(x)
+ if (x < 1)
+ fun_l8_n207(x)
+ else
+ fun_l8_n830(x)
+ end
+end
+
+def fun_l7_n167(x)
+ if (x < 1)
+ fun_l8_n334(x)
+ else
+ fun_l8_n20(x)
+ end
+end
+
+def fun_l7_n168(x)
+ if (x < 1)
+ fun_l8_n835(x)
+ else
+ fun_l8_n493(x)
+ end
+end
+
+def fun_l7_n169(x)
+ if (x < 1)
+ fun_l8_n559(x)
+ else
+ fun_l8_n561(x)
+ end
+end
+
+def fun_l7_n170(x)
+ if (x < 1)
+ fun_l8_n942(x)
+ else
+ fun_l8_n699(x)
+ end
+end
+
+def fun_l7_n171(x)
+ if (x < 1)
+ fun_l8_n833(x)
+ else
+ fun_l8_n928(x)
+ end
+end
+
+def fun_l7_n172(x)
+ if (x < 1)
+ fun_l8_n564(x)
+ else
+ fun_l8_n972(x)
+ end
+end
+
+def fun_l7_n173(x)
+ if (x < 1)
+ fun_l8_n509(x)
+ else
+ fun_l8_n125(x)
+ end
+end
+
+def fun_l7_n174(x)
+ if (x < 1)
+ fun_l8_n643(x)
+ else
+ fun_l8_n813(x)
+ end
+end
+
+def fun_l7_n175(x)
+ if (x < 1)
+ fun_l8_n763(x)
+ else
+ fun_l8_n22(x)
+ end
+end
+
+def fun_l7_n176(x)
+ if (x < 1)
+ fun_l8_n955(x)
+ else
+ fun_l8_n579(x)
+ end
+end
+
+def fun_l7_n177(x)
+ if (x < 1)
+ fun_l8_n577(x)
+ else
+ fun_l8_n675(x)
+ end
+end
+
+def fun_l7_n178(x)
+ if (x < 1)
+ fun_l8_n867(x)
+ else
+ fun_l8_n119(x)
+ end
+end
+
+def fun_l7_n179(x)
+ if (x < 1)
+ fun_l8_n357(x)
+ else
+ fun_l8_n543(x)
+ end
+end
+
+def fun_l7_n180(x)
+ if (x < 1)
+ fun_l8_n67(x)
+ else
+ fun_l8_n643(x)
+ end
+end
+
+def fun_l7_n181(x)
+ if (x < 1)
+ fun_l8_n377(x)
+ else
+ fun_l8_n931(x)
+ end
+end
+
+def fun_l7_n182(x)
+ if (x < 1)
+ fun_l8_n962(x)
+ else
+ fun_l8_n220(x)
+ end
+end
+
+def fun_l7_n183(x)
+ if (x < 1)
+ fun_l8_n568(x)
+ else
+ fun_l8_n702(x)
+ end
+end
+
+def fun_l7_n184(x)
+ if (x < 1)
+ fun_l8_n877(x)
+ else
+ fun_l8_n376(x)
+ end
+end
+
+def fun_l7_n185(x)
+ if (x < 1)
+ fun_l8_n171(x)
+ else
+ fun_l8_n981(x)
+ end
+end
+
+def fun_l7_n186(x)
+ if (x < 1)
+ fun_l8_n283(x)
+ else
+ fun_l8_n81(x)
+ end
+end
+
+def fun_l7_n187(x)
+ if (x < 1)
+ fun_l8_n318(x)
+ else
+ fun_l8_n7(x)
+ end
+end
+
+def fun_l7_n188(x)
+ if (x < 1)
+ fun_l8_n874(x)
+ else
+ fun_l8_n879(x)
+ end
+end
+
+def fun_l7_n189(x)
+ if (x < 1)
+ fun_l8_n944(x)
+ else
+ fun_l8_n881(x)
+ end
+end
+
+def fun_l7_n190(x)
+ if (x < 1)
+ fun_l8_n462(x)
+ else
+ fun_l8_n570(x)
+ end
+end
+
+def fun_l7_n191(x)
+ if (x < 1)
+ fun_l8_n815(x)
+ else
+ fun_l8_n957(x)
+ end
+end
+
+def fun_l7_n192(x)
+ if (x < 1)
+ fun_l8_n217(x)
+ else
+ fun_l8_n93(x)
+ end
+end
+
+def fun_l7_n193(x)
+ if (x < 1)
+ fun_l8_n708(x)
+ else
+ fun_l8_n323(x)
+ end
+end
+
+def fun_l7_n194(x)
+ if (x < 1)
+ fun_l8_n420(x)
+ else
+ fun_l8_n375(x)
+ end
+end
+
+def fun_l7_n195(x)
+ if (x < 1)
+ fun_l8_n307(x)
+ else
+ fun_l8_n427(x)
+ end
+end
+
+def fun_l7_n196(x)
+ if (x < 1)
+ fun_l8_n200(x)
+ else
+ fun_l8_n265(x)
+ end
+end
+
+def fun_l7_n197(x)
+ if (x < 1)
+ fun_l8_n547(x)
+ else
+ fun_l8_n687(x)
+ end
+end
+
+def fun_l7_n198(x)
+ if (x < 1)
+ fun_l8_n693(x)
+ else
+ fun_l8_n420(x)
+ end
+end
+
+def fun_l7_n199(x)
+ if (x < 1)
+ fun_l8_n297(x)
+ else
+ fun_l8_n702(x)
+ end
+end
+
+def fun_l7_n200(x)
+ if (x < 1)
+ fun_l8_n418(x)
+ else
+ fun_l8_n758(x)
+ end
+end
+
+def fun_l7_n201(x)
+ if (x < 1)
+ fun_l8_n204(x)
+ else
+ fun_l8_n572(x)
+ end
+end
+
+def fun_l7_n202(x)
+ if (x < 1)
+ fun_l8_n847(x)
+ else
+ fun_l8_n440(x)
+ end
+end
+
+def fun_l7_n203(x)
+ if (x < 1)
+ fun_l8_n692(x)
+ else
+ fun_l8_n595(x)
+ end
+end
+
+def fun_l7_n204(x)
+ if (x < 1)
+ fun_l8_n922(x)
+ else
+ fun_l8_n618(x)
+ end
+end
+
+def fun_l7_n205(x)
+ if (x < 1)
+ fun_l8_n431(x)
+ else
+ fun_l8_n135(x)
+ end
+end
+
+def fun_l7_n206(x)
+ if (x < 1)
+ fun_l8_n92(x)
+ else
+ fun_l8_n370(x)
+ end
+end
+
+def fun_l7_n207(x)
+ if (x < 1)
+ fun_l8_n141(x)
+ else
+ fun_l8_n845(x)
+ end
+end
+
+def fun_l7_n208(x)
+ if (x < 1)
+ fun_l8_n552(x)
+ else
+ fun_l8_n917(x)
+ end
+end
+
+def fun_l7_n209(x)
+ if (x < 1)
+ fun_l8_n341(x)
+ else
+ fun_l8_n794(x)
+ end
+end
+
+def fun_l7_n210(x)
+ if (x < 1)
+ fun_l8_n772(x)
+ else
+ fun_l8_n515(x)
+ end
+end
+
+def fun_l7_n211(x)
+ if (x < 1)
+ fun_l8_n37(x)
+ else
+ fun_l8_n635(x)
+ end
+end
+
+def fun_l7_n212(x)
+ if (x < 1)
+ fun_l8_n164(x)
+ else
+ fun_l8_n506(x)
+ end
+end
+
+def fun_l7_n213(x)
+ if (x < 1)
+ fun_l8_n621(x)
+ else
+ fun_l8_n722(x)
+ end
+end
+
+def fun_l7_n214(x)
+ if (x < 1)
+ fun_l8_n475(x)
+ else
+ fun_l8_n854(x)
+ end
+end
+
+def fun_l7_n215(x)
+ if (x < 1)
+ fun_l8_n275(x)
+ else
+ fun_l8_n884(x)
+ end
+end
+
+def fun_l7_n216(x)
+ if (x < 1)
+ fun_l8_n894(x)
+ else
+ fun_l8_n424(x)
+ end
+end
+
+def fun_l7_n217(x)
+ if (x < 1)
+ fun_l8_n32(x)
+ else
+ fun_l8_n698(x)
+ end
+end
+
+def fun_l7_n218(x)
+ if (x < 1)
+ fun_l8_n707(x)
+ else
+ fun_l8_n728(x)
+ end
+end
+
+def fun_l7_n219(x)
+ if (x < 1)
+ fun_l8_n294(x)
+ else
+ fun_l8_n583(x)
+ end
+end
+
+def fun_l7_n220(x)
+ if (x < 1)
+ fun_l8_n577(x)
+ else
+ fun_l8_n881(x)
+ end
+end
+
+def fun_l7_n221(x)
+ if (x < 1)
+ fun_l8_n925(x)
+ else
+ fun_l8_n177(x)
+ end
+end
+
+def fun_l7_n222(x)
+ if (x < 1)
+ fun_l8_n495(x)
+ else
+ fun_l8_n407(x)
+ end
+end
+
+def fun_l7_n223(x)
+ if (x < 1)
+ fun_l8_n11(x)
+ else
+ fun_l8_n753(x)
+ end
+end
+
+def fun_l7_n224(x)
+ if (x < 1)
+ fun_l8_n366(x)
+ else
+ fun_l8_n546(x)
+ end
+end
+
+def fun_l7_n225(x)
+ if (x < 1)
+ fun_l8_n644(x)
+ else
+ fun_l8_n728(x)
+ end
+end
+
+def fun_l7_n226(x)
+ if (x < 1)
+ fun_l8_n731(x)
+ else
+ fun_l8_n292(x)
+ end
+end
+
+def fun_l7_n227(x)
+ if (x < 1)
+ fun_l8_n653(x)
+ else
+ fun_l8_n521(x)
+ end
+end
+
+def fun_l7_n228(x)
+ if (x < 1)
+ fun_l8_n479(x)
+ else
+ fun_l8_n329(x)
+ end
+end
+
+def fun_l7_n229(x)
+ if (x < 1)
+ fun_l8_n151(x)
+ else
+ fun_l8_n620(x)
+ end
+end
+
+def fun_l7_n230(x)
+ if (x < 1)
+ fun_l8_n58(x)
+ else
+ fun_l8_n369(x)
+ end
+end
+
+def fun_l7_n231(x)
+ if (x < 1)
+ fun_l8_n301(x)
+ else
+ fun_l8_n869(x)
+ end
+end
+
+def fun_l7_n232(x)
+ if (x < 1)
+ fun_l8_n810(x)
+ else
+ fun_l8_n376(x)
+ end
+end
+
+def fun_l7_n233(x)
+ if (x < 1)
+ fun_l8_n19(x)
+ else
+ fun_l8_n278(x)
+ end
+end
+
+def fun_l7_n234(x)
+ if (x < 1)
+ fun_l8_n509(x)
+ else
+ fun_l8_n826(x)
+ end
+end
+
+def fun_l7_n235(x)
+ if (x < 1)
+ fun_l8_n302(x)
+ else
+ fun_l8_n62(x)
+ end
+end
+
+def fun_l7_n236(x)
+ if (x < 1)
+ fun_l8_n289(x)
+ else
+ fun_l8_n935(x)
+ end
+end
+
+def fun_l7_n237(x)
+ if (x < 1)
+ fun_l8_n217(x)
+ else
+ fun_l8_n652(x)
+ end
+end
+
+def fun_l7_n238(x)
+ if (x < 1)
+ fun_l8_n234(x)
+ else
+ fun_l8_n720(x)
+ end
+end
+
+def fun_l7_n239(x)
+ if (x < 1)
+ fun_l8_n158(x)
+ else
+ fun_l8_n409(x)
+ end
+end
+
+def fun_l7_n240(x)
+ if (x < 1)
+ fun_l8_n478(x)
+ else
+ fun_l8_n855(x)
+ end
+end
+
+def fun_l7_n241(x)
+ if (x < 1)
+ fun_l8_n115(x)
+ else
+ fun_l8_n406(x)
+ end
+end
+
+def fun_l7_n242(x)
+ if (x < 1)
+ fun_l8_n278(x)
+ else
+ fun_l8_n12(x)
+ end
+end
+
+def fun_l7_n243(x)
+ if (x < 1)
+ fun_l8_n273(x)
+ else
+ fun_l8_n243(x)
+ end
+end
+
+def fun_l7_n244(x)
+ if (x < 1)
+ fun_l8_n909(x)
+ else
+ fun_l8_n721(x)
+ end
+end
+
+def fun_l7_n245(x)
+ if (x < 1)
+ fun_l8_n415(x)
+ else
+ fun_l8_n530(x)
+ end
+end
+
+def fun_l7_n246(x)
+ if (x < 1)
+ fun_l8_n770(x)
+ else
+ fun_l8_n413(x)
+ end
+end
+
+def fun_l7_n247(x)
+ if (x < 1)
+ fun_l8_n228(x)
+ else
+ fun_l8_n668(x)
+ end
+end
+
+def fun_l7_n248(x)
+ if (x < 1)
+ fun_l8_n174(x)
+ else
+ fun_l8_n559(x)
+ end
+end
+
+def fun_l7_n249(x)
+ if (x < 1)
+ fun_l8_n740(x)
+ else
+ fun_l8_n314(x)
+ end
+end
+
+def fun_l7_n250(x)
+ if (x < 1)
+ fun_l8_n293(x)
+ else
+ fun_l8_n835(x)
+ end
+end
+
+def fun_l7_n251(x)
+ if (x < 1)
+ fun_l8_n584(x)
+ else
+ fun_l8_n755(x)
+ end
+end
+
+def fun_l7_n252(x)
+ if (x < 1)
+ fun_l8_n792(x)
+ else
+ fun_l8_n135(x)
+ end
+end
+
+def fun_l7_n253(x)
+ if (x < 1)
+ fun_l8_n116(x)
+ else
+ fun_l8_n82(x)
+ end
+end
+
+def fun_l7_n254(x)
+ if (x < 1)
+ fun_l8_n478(x)
+ else
+ fun_l8_n809(x)
+ end
+end
+
+def fun_l7_n255(x)
+ if (x < 1)
+ fun_l8_n924(x)
+ else
+ fun_l8_n708(x)
+ end
+end
+
+def fun_l7_n256(x)
+ if (x < 1)
+ fun_l8_n345(x)
+ else
+ fun_l8_n669(x)
+ end
+end
+
+def fun_l7_n257(x)
+ if (x < 1)
+ fun_l8_n300(x)
+ else
+ fun_l8_n166(x)
+ end
+end
+
+def fun_l7_n258(x)
+ if (x < 1)
+ fun_l8_n979(x)
+ else
+ fun_l8_n894(x)
+ end
+end
+
+def fun_l7_n259(x)
+ if (x < 1)
+ fun_l8_n765(x)
+ else
+ fun_l8_n838(x)
+ end
+end
+
+def fun_l7_n260(x)
+ if (x < 1)
+ fun_l8_n812(x)
+ else
+ fun_l8_n472(x)
+ end
+end
+
+def fun_l7_n261(x)
+ if (x < 1)
+ fun_l8_n220(x)
+ else
+ fun_l8_n106(x)
+ end
+end
+
+def fun_l7_n262(x)
+ if (x < 1)
+ fun_l8_n727(x)
+ else
+ fun_l8_n783(x)
+ end
+end
+
+def fun_l7_n263(x)
+ if (x < 1)
+ fun_l8_n560(x)
+ else
+ fun_l8_n781(x)
+ end
+end
+
+def fun_l7_n264(x)
+ if (x < 1)
+ fun_l8_n709(x)
+ else
+ fun_l8_n33(x)
+ end
+end
+
+def fun_l7_n265(x)
+ if (x < 1)
+ fun_l8_n904(x)
+ else
+ fun_l8_n64(x)
+ end
+end
+
+def fun_l7_n266(x)
+ if (x < 1)
+ fun_l8_n944(x)
+ else
+ fun_l8_n652(x)
+ end
+end
+
+def fun_l7_n267(x)
+ if (x < 1)
+ fun_l8_n154(x)
+ else
+ fun_l8_n103(x)
+ end
+end
+
+def fun_l7_n268(x)
+ if (x < 1)
+ fun_l8_n55(x)
+ else
+ fun_l8_n841(x)
+ end
+end
+
+def fun_l7_n269(x)
+ if (x < 1)
+ fun_l8_n914(x)
+ else
+ fun_l8_n108(x)
+ end
+end
+
+def fun_l7_n270(x)
+ if (x < 1)
+ fun_l8_n733(x)
+ else
+ fun_l8_n398(x)
+ end
+end
+
+def fun_l7_n271(x)
+ if (x < 1)
+ fun_l8_n145(x)
+ else
+ fun_l8_n735(x)
+ end
+end
+
+def fun_l7_n272(x)
+ if (x < 1)
+ fun_l8_n404(x)
+ else
+ fun_l8_n216(x)
+ end
+end
+
+def fun_l7_n273(x)
+ if (x < 1)
+ fun_l8_n380(x)
+ else
+ fun_l8_n798(x)
+ end
+end
+
+def fun_l7_n274(x)
+ if (x < 1)
+ fun_l8_n63(x)
+ else
+ fun_l8_n133(x)
+ end
+end
+
+def fun_l7_n275(x)
+ if (x < 1)
+ fun_l8_n878(x)
+ else
+ fun_l8_n284(x)
+ end
+end
+
+def fun_l7_n276(x)
+ if (x < 1)
+ fun_l8_n718(x)
+ else
+ fun_l8_n97(x)
+ end
+end
+
+def fun_l7_n277(x)
+ if (x < 1)
+ fun_l8_n509(x)
+ else
+ fun_l8_n695(x)
+ end
+end
+
+def fun_l7_n278(x)
+ if (x < 1)
+ fun_l8_n581(x)
+ else
+ fun_l8_n898(x)
+ end
+end
+
+def fun_l7_n279(x)
+ if (x < 1)
+ fun_l8_n247(x)
+ else
+ fun_l8_n526(x)
+ end
+end
+
+def fun_l7_n280(x)
+ if (x < 1)
+ fun_l8_n995(x)
+ else
+ fun_l8_n614(x)
+ end
+end
+
+def fun_l7_n281(x)
+ if (x < 1)
+ fun_l8_n301(x)
+ else
+ fun_l8_n178(x)
+ end
+end
+
+def fun_l7_n282(x)
+ if (x < 1)
+ fun_l8_n575(x)
+ else
+ fun_l8_n712(x)
+ end
+end
+
+def fun_l7_n283(x)
+ if (x < 1)
+ fun_l8_n261(x)
+ else
+ fun_l8_n740(x)
+ end
+end
+
+def fun_l7_n284(x)
+ if (x < 1)
+ fun_l8_n284(x)
+ else
+ fun_l8_n350(x)
+ end
+end
+
+def fun_l7_n285(x)
+ if (x < 1)
+ fun_l8_n521(x)
+ else
+ fun_l8_n305(x)
+ end
+end
+
+def fun_l7_n286(x)
+ if (x < 1)
+ fun_l8_n271(x)
+ else
+ fun_l8_n728(x)
+ end
+end
+
+def fun_l7_n287(x)
+ if (x < 1)
+ fun_l8_n292(x)
+ else
+ fun_l8_n799(x)
+ end
+end
+
+def fun_l7_n288(x)
+ if (x < 1)
+ fun_l8_n852(x)
+ else
+ fun_l8_n606(x)
+ end
+end
+
+def fun_l7_n289(x)
+ if (x < 1)
+ fun_l8_n177(x)
+ else
+ fun_l8_n649(x)
+ end
+end
+
+def fun_l7_n290(x)
+ if (x < 1)
+ fun_l8_n488(x)
+ else
+ fun_l8_n252(x)
+ end
+end
+
+def fun_l7_n291(x)
+ if (x < 1)
+ fun_l8_n815(x)
+ else
+ fun_l8_n690(x)
+ end
+end
+
+def fun_l7_n292(x)
+ if (x < 1)
+ fun_l8_n999(x)
+ else
+ fun_l8_n700(x)
+ end
+end
+
+def fun_l7_n293(x)
+ if (x < 1)
+ fun_l8_n9(x)
+ else
+ fun_l8_n194(x)
+ end
+end
+
+def fun_l7_n294(x)
+ if (x < 1)
+ fun_l8_n390(x)
+ else
+ fun_l8_n772(x)
+ end
+end
+
+def fun_l7_n295(x)
+ if (x < 1)
+ fun_l8_n487(x)
+ else
+ fun_l8_n587(x)
+ end
+end
+
+def fun_l7_n296(x)
+ if (x < 1)
+ fun_l8_n892(x)
+ else
+ fun_l8_n126(x)
+ end
+end
+
+def fun_l7_n297(x)
+ if (x < 1)
+ fun_l8_n199(x)
+ else
+ fun_l8_n312(x)
+ end
+end
+
+def fun_l7_n298(x)
+ if (x < 1)
+ fun_l8_n534(x)
+ else
+ fun_l8_n640(x)
+ end
+end
+
+def fun_l7_n299(x)
+ if (x < 1)
+ fun_l8_n344(x)
+ else
+ fun_l8_n58(x)
+ end
+end
+
+def fun_l7_n300(x)
+ if (x < 1)
+ fun_l8_n11(x)
+ else
+ fun_l8_n922(x)
+ end
+end
+
+def fun_l7_n301(x)
+ if (x < 1)
+ fun_l8_n848(x)
+ else
+ fun_l8_n432(x)
+ end
+end
+
+def fun_l7_n302(x)
+ if (x < 1)
+ fun_l8_n292(x)
+ else
+ fun_l8_n86(x)
+ end
+end
+
+def fun_l7_n303(x)
+ if (x < 1)
+ fun_l8_n239(x)
+ else
+ fun_l8_n296(x)
+ end
+end
+
+def fun_l7_n304(x)
+ if (x < 1)
+ fun_l8_n350(x)
+ else
+ fun_l8_n769(x)
+ end
+end
+
+def fun_l7_n305(x)
+ if (x < 1)
+ fun_l8_n959(x)
+ else
+ fun_l8_n292(x)
+ end
+end
+
+def fun_l7_n306(x)
+ if (x < 1)
+ fun_l8_n371(x)
+ else
+ fun_l8_n507(x)
+ end
+end
+
+def fun_l7_n307(x)
+ if (x < 1)
+ fun_l8_n910(x)
+ else
+ fun_l8_n542(x)
+ end
+end
+
+def fun_l7_n308(x)
+ if (x < 1)
+ fun_l8_n299(x)
+ else
+ fun_l8_n543(x)
+ end
+end
+
+def fun_l7_n309(x)
+ if (x < 1)
+ fun_l8_n145(x)
+ else
+ fun_l8_n393(x)
+ end
+end
+
+def fun_l7_n310(x)
+ if (x < 1)
+ fun_l8_n1(x)
+ else
+ fun_l8_n810(x)
+ end
+end
+
+def fun_l7_n311(x)
+ if (x < 1)
+ fun_l8_n866(x)
+ else
+ fun_l8_n519(x)
+ end
+end
+
+def fun_l7_n312(x)
+ if (x < 1)
+ fun_l8_n730(x)
+ else
+ fun_l8_n912(x)
+ end
+end
+
+def fun_l7_n313(x)
+ if (x < 1)
+ fun_l8_n128(x)
+ else
+ fun_l8_n3(x)
+ end
+end
+
+def fun_l7_n314(x)
+ if (x < 1)
+ fun_l8_n393(x)
+ else
+ fun_l8_n887(x)
+ end
+end
+
+def fun_l7_n315(x)
+ if (x < 1)
+ fun_l8_n165(x)
+ else
+ fun_l8_n540(x)
+ end
+end
+
+def fun_l7_n316(x)
+ if (x < 1)
+ fun_l8_n641(x)
+ else
+ fun_l8_n255(x)
+ end
+end
+
+def fun_l7_n317(x)
+ if (x < 1)
+ fun_l8_n265(x)
+ else
+ fun_l8_n754(x)
+ end
+end
+
+def fun_l7_n318(x)
+ if (x < 1)
+ fun_l8_n433(x)
+ else
+ fun_l8_n163(x)
+ end
+end
+
+def fun_l7_n319(x)
+ if (x < 1)
+ fun_l8_n409(x)
+ else
+ fun_l8_n110(x)
+ end
+end
+
+def fun_l7_n320(x)
+ if (x < 1)
+ fun_l8_n704(x)
+ else
+ fun_l8_n959(x)
+ end
+end
+
+def fun_l7_n321(x)
+ if (x < 1)
+ fun_l8_n334(x)
+ else
+ fun_l8_n280(x)
+ end
+end
+
+def fun_l7_n322(x)
+ if (x < 1)
+ fun_l8_n107(x)
+ else
+ fun_l8_n403(x)
+ end
+end
+
+def fun_l7_n323(x)
+ if (x < 1)
+ fun_l8_n108(x)
+ else
+ fun_l8_n426(x)
+ end
+end
+
+def fun_l7_n324(x)
+ if (x < 1)
+ fun_l8_n310(x)
+ else
+ fun_l8_n968(x)
+ end
+end
+
+def fun_l7_n325(x)
+ if (x < 1)
+ fun_l8_n600(x)
+ else
+ fun_l8_n850(x)
+ end
+end
+
+def fun_l7_n326(x)
+ if (x < 1)
+ fun_l8_n736(x)
+ else
+ fun_l8_n61(x)
+ end
+end
+
+def fun_l7_n327(x)
+ if (x < 1)
+ fun_l8_n86(x)
+ else
+ fun_l8_n948(x)
+ end
+end
+
+def fun_l7_n328(x)
+ if (x < 1)
+ fun_l8_n625(x)
+ else
+ fun_l8_n644(x)
+ end
+end
+
+def fun_l7_n329(x)
+ if (x < 1)
+ fun_l8_n507(x)
+ else
+ fun_l8_n624(x)
+ end
+end
+
+def fun_l7_n330(x)
+ if (x < 1)
+ fun_l8_n956(x)
+ else
+ fun_l8_n281(x)
+ end
+end
+
+def fun_l7_n331(x)
+ if (x < 1)
+ fun_l8_n72(x)
+ else
+ fun_l8_n695(x)
+ end
+end
+
+def fun_l7_n332(x)
+ if (x < 1)
+ fun_l8_n445(x)
+ else
+ fun_l8_n465(x)
+ end
+end
+
+def fun_l7_n333(x)
+ if (x < 1)
+ fun_l8_n438(x)
+ else
+ fun_l8_n698(x)
+ end
+end
+
+def fun_l7_n334(x)
+ if (x < 1)
+ fun_l8_n242(x)
+ else
+ fun_l8_n837(x)
+ end
+end
+
+def fun_l7_n335(x)
+ if (x < 1)
+ fun_l8_n299(x)
+ else
+ fun_l8_n312(x)
+ end
+end
+
+def fun_l7_n336(x)
+ if (x < 1)
+ fun_l8_n264(x)
+ else
+ fun_l8_n330(x)
+ end
+end
+
+def fun_l7_n337(x)
+ if (x < 1)
+ fun_l8_n251(x)
+ else
+ fun_l8_n459(x)
+ end
+end
+
+def fun_l7_n338(x)
+ if (x < 1)
+ fun_l8_n876(x)
+ else
+ fun_l8_n689(x)
+ end
+end
+
+def fun_l7_n339(x)
+ if (x < 1)
+ fun_l8_n547(x)
+ else
+ fun_l8_n745(x)
+ end
+end
+
+def fun_l7_n340(x)
+ if (x < 1)
+ fun_l8_n493(x)
+ else
+ fun_l8_n877(x)
+ end
+end
+
+def fun_l7_n341(x)
+ if (x < 1)
+ fun_l8_n143(x)
+ else
+ fun_l8_n429(x)
+ end
+end
+
+def fun_l7_n342(x)
+ if (x < 1)
+ fun_l8_n650(x)
+ else
+ fun_l8_n384(x)
+ end
+end
+
+def fun_l7_n343(x)
+ if (x < 1)
+ fun_l8_n897(x)
+ else
+ fun_l8_n980(x)
+ end
+end
+
+def fun_l7_n344(x)
+ if (x < 1)
+ fun_l8_n699(x)
+ else
+ fun_l8_n673(x)
+ end
+end
+
+def fun_l7_n345(x)
+ if (x < 1)
+ fun_l8_n25(x)
+ else
+ fun_l8_n342(x)
+ end
+end
+
+def fun_l7_n346(x)
+ if (x < 1)
+ fun_l8_n345(x)
+ else
+ fun_l8_n140(x)
+ end
+end
+
+def fun_l7_n347(x)
+ if (x < 1)
+ fun_l8_n661(x)
+ else
+ fun_l8_n153(x)
+ end
+end
+
+def fun_l7_n348(x)
+ if (x < 1)
+ fun_l8_n477(x)
+ else
+ fun_l8_n460(x)
+ end
+end
+
+def fun_l7_n349(x)
+ if (x < 1)
+ fun_l8_n641(x)
+ else
+ fun_l8_n941(x)
+ end
+end
+
+def fun_l7_n350(x)
+ if (x < 1)
+ fun_l8_n952(x)
+ else
+ fun_l8_n886(x)
+ end
+end
+
+def fun_l7_n351(x)
+ if (x < 1)
+ fun_l8_n338(x)
+ else
+ fun_l8_n655(x)
+ end
+end
+
+def fun_l7_n352(x)
+ if (x < 1)
+ fun_l8_n717(x)
+ else
+ fun_l8_n314(x)
+ end
+end
+
+def fun_l7_n353(x)
+ if (x < 1)
+ fun_l8_n645(x)
+ else
+ fun_l8_n464(x)
+ end
+end
+
+def fun_l7_n354(x)
+ if (x < 1)
+ fun_l8_n114(x)
+ else
+ fun_l8_n816(x)
+ end
+end
+
+def fun_l7_n355(x)
+ if (x < 1)
+ fun_l8_n18(x)
+ else
+ fun_l8_n173(x)
+ end
+end
+
+def fun_l7_n356(x)
+ if (x < 1)
+ fun_l8_n214(x)
+ else
+ fun_l8_n834(x)
+ end
+end
+
+def fun_l7_n357(x)
+ if (x < 1)
+ fun_l8_n6(x)
+ else
+ fun_l8_n161(x)
+ end
+end
+
+def fun_l7_n358(x)
+ if (x < 1)
+ fun_l8_n823(x)
+ else
+ fun_l8_n695(x)
+ end
+end
+
+def fun_l7_n359(x)
+ if (x < 1)
+ fun_l8_n86(x)
+ else
+ fun_l8_n174(x)
+ end
+end
+
+def fun_l7_n360(x)
+ if (x < 1)
+ fun_l8_n904(x)
+ else
+ fun_l8_n240(x)
+ end
+end
+
+def fun_l7_n361(x)
+ if (x < 1)
+ fun_l8_n857(x)
+ else
+ fun_l8_n494(x)
+ end
+end
+
+def fun_l7_n362(x)
+ if (x < 1)
+ fun_l8_n780(x)
+ else
+ fun_l8_n186(x)
+ end
+end
+
+def fun_l7_n363(x)
+ if (x < 1)
+ fun_l8_n575(x)
+ else
+ fun_l8_n510(x)
+ end
+end
+
+def fun_l7_n364(x)
+ if (x < 1)
+ fun_l8_n412(x)
+ else
+ fun_l8_n153(x)
+ end
+end
+
+def fun_l7_n365(x)
+ if (x < 1)
+ fun_l8_n840(x)
+ else
+ fun_l8_n199(x)
+ end
+end
+
+def fun_l7_n366(x)
+ if (x < 1)
+ fun_l8_n162(x)
+ else
+ fun_l8_n971(x)
+ end
+end
+
+def fun_l7_n367(x)
+ if (x < 1)
+ fun_l8_n200(x)
+ else
+ fun_l8_n128(x)
+ end
+end
+
+def fun_l7_n368(x)
+ if (x < 1)
+ fun_l8_n404(x)
+ else
+ fun_l8_n657(x)
+ end
+end
+
+def fun_l7_n369(x)
+ if (x < 1)
+ fun_l8_n631(x)
+ else
+ fun_l8_n714(x)
+ end
+end
+
+def fun_l7_n370(x)
+ if (x < 1)
+ fun_l8_n177(x)
+ else
+ fun_l8_n718(x)
+ end
+end
+
+def fun_l7_n371(x)
+ if (x < 1)
+ fun_l8_n284(x)
+ else
+ fun_l8_n474(x)
+ end
+end
+
+def fun_l7_n372(x)
+ if (x < 1)
+ fun_l8_n138(x)
+ else
+ fun_l8_n461(x)
+ end
+end
+
+def fun_l7_n373(x)
+ if (x < 1)
+ fun_l8_n78(x)
+ else
+ fun_l8_n750(x)
+ end
+end
+
+def fun_l7_n374(x)
+ if (x < 1)
+ fun_l8_n231(x)
+ else
+ fun_l8_n648(x)
+ end
+end
+
+def fun_l7_n375(x)
+ if (x < 1)
+ fun_l8_n238(x)
+ else
+ fun_l8_n644(x)
+ end
+end
+
+def fun_l7_n376(x)
+ if (x < 1)
+ fun_l8_n509(x)
+ else
+ fun_l8_n354(x)
+ end
+end
+
+def fun_l7_n377(x)
+ if (x < 1)
+ fun_l8_n332(x)
+ else
+ fun_l8_n739(x)
+ end
+end
+
+def fun_l7_n378(x)
+ if (x < 1)
+ fun_l8_n76(x)
+ else
+ fun_l8_n505(x)
+ end
+end
+
+def fun_l7_n379(x)
+ if (x < 1)
+ fun_l8_n781(x)
+ else
+ fun_l8_n918(x)
+ end
+end
+
+def fun_l7_n380(x)
+ if (x < 1)
+ fun_l8_n854(x)
+ else
+ fun_l8_n85(x)
+ end
+end
+
+def fun_l7_n381(x)
+ if (x < 1)
+ fun_l8_n67(x)
+ else
+ fun_l8_n690(x)
+ end
+end
+
+def fun_l7_n382(x)
+ if (x < 1)
+ fun_l8_n425(x)
+ else
+ fun_l8_n643(x)
+ end
+end
+
+def fun_l7_n383(x)
+ if (x < 1)
+ fun_l8_n210(x)
+ else
+ fun_l8_n533(x)
+ end
+end
+
+def fun_l7_n384(x)
+ if (x < 1)
+ fun_l8_n469(x)
+ else
+ fun_l8_n274(x)
+ end
+end
+
+def fun_l7_n385(x)
+ if (x < 1)
+ fun_l8_n398(x)
+ else
+ fun_l8_n583(x)
+ end
+end
+
+def fun_l7_n386(x)
+ if (x < 1)
+ fun_l8_n483(x)
+ else
+ fun_l8_n80(x)
+ end
+end
+
+def fun_l7_n387(x)
+ if (x < 1)
+ fun_l8_n557(x)
+ else
+ fun_l8_n165(x)
+ end
+end
+
+def fun_l7_n388(x)
+ if (x < 1)
+ fun_l8_n335(x)
+ else
+ fun_l8_n656(x)
+ end
+end
+
+def fun_l7_n389(x)
+ if (x < 1)
+ fun_l8_n810(x)
+ else
+ fun_l8_n586(x)
+ end
+end
+
+def fun_l7_n390(x)
+ if (x < 1)
+ fun_l8_n90(x)
+ else
+ fun_l8_n788(x)
+ end
+end
+
+def fun_l7_n391(x)
+ if (x < 1)
+ fun_l8_n709(x)
+ else
+ fun_l8_n948(x)
+ end
+end
+
+def fun_l7_n392(x)
+ if (x < 1)
+ fun_l8_n139(x)
+ else
+ fun_l8_n631(x)
+ end
+end
+
+def fun_l7_n393(x)
+ if (x < 1)
+ fun_l8_n341(x)
+ else
+ fun_l8_n506(x)
+ end
+end
+
+def fun_l7_n394(x)
+ if (x < 1)
+ fun_l8_n435(x)
+ else
+ fun_l8_n178(x)
+ end
+end
+
+def fun_l7_n395(x)
+ if (x < 1)
+ fun_l8_n186(x)
+ else
+ fun_l8_n58(x)
+ end
+end
+
+def fun_l7_n396(x)
+ if (x < 1)
+ fun_l8_n512(x)
+ else
+ fun_l8_n87(x)
+ end
+end
+
+def fun_l7_n397(x)
+ if (x < 1)
+ fun_l8_n763(x)
+ else
+ fun_l8_n220(x)
+ end
+end
+
+def fun_l7_n398(x)
+ if (x < 1)
+ fun_l8_n266(x)
+ else
+ fun_l8_n231(x)
+ end
+end
+
+def fun_l7_n399(x)
+ if (x < 1)
+ fun_l8_n308(x)
+ else
+ fun_l8_n512(x)
+ end
+end
+
+def fun_l7_n400(x)
+ if (x < 1)
+ fun_l8_n26(x)
+ else
+ fun_l8_n228(x)
+ end
+end
+
+def fun_l7_n401(x)
+ if (x < 1)
+ fun_l8_n143(x)
+ else
+ fun_l8_n826(x)
+ end
+end
+
+def fun_l7_n402(x)
+ if (x < 1)
+ fun_l8_n893(x)
+ else
+ fun_l8_n334(x)
+ end
+end
+
+def fun_l7_n403(x)
+ if (x < 1)
+ fun_l8_n9(x)
+ else
+ fun_l8_n867(x)
+ end
+end
+
+def fun_l7_n404(x)
+ if (x < 1)
+ fun_l8_n85(x)
+ else
+ fun_l8_n279(x)
+ end
+end
+
+def fun_l7_n405(x)
+ if (x < 1)
+ fun_l8_n30(x)
+ else
+ fun_l8_n85(x)
+ end
+end
+
+def fun_l7_n406(x)
+ if (x < 1)
+ fun_l8_n38(x)
+ else
+ fun_l8_n979(x)
+ end
+end
+
+def fun_l7_n407(x)
+ if (x < 1)
+ fun_l8_n630(x)
+ else
+ fun_l8_n262(x)
+ end
+end
+
+def fun_l7_n408(x)
+ if (x < 1)
+ fun_l8_n430(x)
+ else
+ fun_l8_n178(x)
+ end
+end
+
+def fun_l7_n409(x)
+ if (x < 1)
+ fun_l8_n131(x)
+ else
+ fun_l8_n66(x)
+ end
+end
+
+def fun_l7_n410(x)
+ if (x < 1)
+ fun_l8_n373(x)
+ else
+ fun_l8_n514(x)
+ end
+end
+
+def fun_l7_n411(x)
+ if (x < 1)
+ fun_l8_n334(x)
+ else
+ fun_l8_n591(x)
+ end
+end
+
+def fun_l7_n412(x)
+ if (x < 1)
+ fun_l8_n619(x)
+ else
+ fun_l8_n490(x)
+ end
+end
+
+def fun_l7_n413(x)
+ if (x < 1)
+ fun_l8_n318(x)
+ else
+ fun_l8_n456(x)
+ end
+end
+
+def fun_l7_n414(x)
+ if (x < 1)
+ fun_l8_n576(x)
+ else
+ fun_l8_n638(x)
+ end
+end
+
+def fun_l7_n415(x)
+ if (x < 1)
+ fun_l8_n407(x)
+ else
+ fun_l8_n44(x)
+ end
+end
+
+def fun_l7_n416(x)
+ if (x < 1)
+ fun_l8_n970(x)
+ else
+ fun_l8_n564(x)
+ end
+end
+
+def fun_l7_n417(x)
+ if (x < 1)
+ fun_l8_n163(x)
+ else
+ fun_l8_n533(x)
+ end
+end
+
+def fun_l7_n418(x)
+ if (x < 1)
+ fun_l8_n216(x)
+ else
+ fun_l8_n604(x)
+ end
+end
+
+def fun_l7_n419(x)
+ if (x < 1)
+ fun_l8_n505(x)
+ else
+ fun_l8_n620(x)
+ end
+end
+
+def fun_l7_n420(x)
+ if (x < 1)
+ fun_l8_n746(x)
+ else
+ fun_l8_n998(x)
+ end
+end
+
+def fun_l7_n421(x)
+ if (x < 1)
+ fun_l8_n266(x)
+ else
+ fun_l8_n762(x)
+ end
+end
+
+def fun_l7_n422(x)
+ if (x < 1)
+ fun_l8_n216(x)
+ else
+ fun_l8_n995(x)
+ end
+end
+
+def fun_l7_n423(x)
+ if (x < 1)
+ fun_l8_n824(x)
+ else
+ fun_l8_n349(x)
+ end
+end
+
+def fun_l7_n424(x)
+ if (x < 1)
+ fun_l8_n177(x)
+ else
+ fun_l8_n61(x)
+ end
+end
+
+def fun_l7_n425(x)
+ if (x < 1)
+ fun_l8_n286(x)
+ else
+ fun_l8_n213(x)
+ end
+end
+
+def fun_l7_n426(x)
+ if (x < 1)
+ fun_l8_n794(x)
+ else
+ fun_l8_n428(x)
+ end
+end
+
+def fun_l7_n427(x)
+ if (x < 1)
+ fun_l8_n404(x)
+ else
+ fun_l8_n202(x)
+ end
+end
+
+def fun_l7_n428(x)
+ if (x < 1)
+ fun_l8_n571(x)
+ else
+ fun_l8_n812(x)
+ end
+end
+
+def fun_l7_n429(x)
+ if (x < 1)
+ fun_l8_n165(x)
+ else
+ fun_l8_n277(x)
+ end
+end
+
+def fun_l7_n430(x)
+ if (x < 1)
+ fun_l8_n138(x)
+ else
+ fun_l8_n230(x)
+ end
+end
+
+def fun_l7_n431(x)
+ if (x < 1)
+ fun_l8_n832(x)
+ else
+ fun_l8_n78(x)
+ end
+end
+
+def fun_l7_n432(x)
+ if (x < 1)
+ fun_l8_n866(x)
+ else
+ fun_l8_n137(x)
+ end
+end
+
+def fun_l7_n433(x)
+ if (x < 1)
+ fun_l8_n92(x)
+ else
+ fun_l8_n638(x)
+ end
+end
+
+def fun_l7_n434(x)
+ if (x < 1)
+ fun_l8_n788(x)
+ else
+ fun_l8_n991(x)
+ end
+end
+
+def fun_l7_n435(x)
+ if (x < 1)
+ fun_l8_n584(x)
+ else
+ fun_l8_n783(x)
+ end
+end
+
+def fun_l7_n436(x)
+ if (x < 1)
+ fun_l8_n786(x)
+ else
+ fun_l8_n771(x)
+ end
+end
+
+def fun_l7_n437(x)
+ if (x < 1)
+ fun_l8_n650(x)
+ else
+ fun_l8_n684(x)
+ end
+end
+
+def fun_l7_n438(x)
+ if (x < 1)
+ fun_l8_n964(x)
+ else
+ fun_l8_n738(x)
+ end
+end
+
+def fun_l7_n439(x)
+ if (x < 1)
+ fun_l8_n356(x)
+ else
+ fun_l8_n979(x)
+ end
+end
+
+def fun_l7_n440(x)
+ if (x < 1)
+ fun_l8_n630(x)
+ else
+ fun_l8_n79(x)
+ end
+end
+
+def fun_l7_n441(x)
+ if (x < 1)
+ fun_l8_n326(x)
+ else
+ fun_l8_n667(x)
+ end
+end
+
+def fun_l7_n442(x)
+ if (x < 1)
+ fun_l8_n561(x)
+ else
+ fun_l8_n263(x)
+ end
+end
+
+def fun_l7_n443(x)
+ if (x < 1)
+ fun_l8_n62(x)
+ else
+ fun_l8_n528(x)
+ end
+end
+
+def fun_l7_n444(x)
+ if (x < 1)
+ fun_l8_n156(x)
+ else
+ fun_l8_n496(x)
+ end
+end
+
+def fun_l7_n445(x)
+ if (x < 1)
+ fun_l8_n971(x)
+ else
+ fun_l8_n853(x)
+ end
+end
+
+def fun_l7_n446(x)
+ if (x < 1)
+ fun_l8_n217(x)
+ else
+ fun_l8_n985(x)
+ end
+end
+
+def fun_l7_n447(x)
+ if (x < 1)
+ fun_l8_n569(x)
+ else
+ fun_l8_n320(x)
+ end
+end
+
+def fun_l7_n448(x)
+ if (x < 1)
+ fun_l8_n133(x)
+ else
+ fun_l8_n417(x)
+ end
+end
+
+def fun_l7_n449(x)
+ if (x < 1)
+ fun_l8_n369(x)
+ else
+ fun_l8_n25(x)
+ end
+end
+
+def fun_l7_n450(x)
+ if (x < 1)
+ fun_l8_n735(x)
+ else
+ fun_l8_n573(x)
+ end
+end
+
+def fun_l7_n451(x)
+ if (x < 1)
+ fun_l8_n764(x)
+ else
+ fun_l8_n247(x)
+ end
+end
+
+def fun_l7_n452(x)
+ if (x < 1)
+ fun_l8_n512(x)
+ else
+ fun_l8_n274(x)
+ end
+end
+
+def fun_l7_n453(x)
+ if (x < 1)
+ fun_l8_n388(x)
+ else
+ fun_l8_n438(x)
+ end
+end
+
+def fun_l7_n454(x)
+ if (x < 1)
+ fun_l8_n565(x)
+ else
+ fun_l8_n449(x)
+ end
+end
+
+def fun_l7_n455(x)
+ if (x < 1)
+ fun_l8_n771(x)
+ else
+ fun_l8_n827(x)
+ end
+end
+
+def fun_l7_n456(x)
+ if (x < 1)
+ fun_l8_n538(x)
+ else
+ fun_l8_n270(x)
+ end
+end
+
+def fun_l7_n457(x)
+ if (x < 1)
+ fun_l8_n288(x)
+ else
+ fun_l8_n325(x)
+ end
+end
+
+def fun_l7_n458(x)
+ if (x < 1)
+ fun_l8_n345(x)
+ else
+ fun_l8_n334(x)
+ end
+end
+
+def fun_l7_n459(x)
+ if (x < 1)
+ fun_l8_n696(x)
+ else
+ fun_l8_n440(x)
+ end
+end
+
+def fun_l7_n460(x)
+ if (x < 1)
+ fun_l8_n509(x)
+ else
+ fun_l8_n580(x)
+ end
+end
+
+def fun_l7_n461(x)
+ if (x < 1)
+ fun_l8_n254(x)
+ else
+ fun_l8_n162(x)
+ end
+end
+
+def fun_l7_n462(x)
+ if (x < 1)
+ fun_l8_n541(x)
+ else
+ fun_l8_n493(x)
+ end
+end
+
+def fun_l7_n463(x)
+ if (x < 1)
+ fun_l8_n371(x)
+ else
+ fun_l8_n302(x)
+ end
+end
+
+def fun_l7_n464(x)
+ if (x < 1)
+ fun_l8_n44(x)
+ else
+ fun_l8_n677(x)
+ end
+end
+
+def fun_l7_n465(x)
+ if (x < 1)
+ fun_l8_n312(x)
+ else
+ fun_l8_n716(x)
+ end
+end
+
+def fun_l7_n466(x)
+ if (x < 1)
+ fun_l8_n252(x)
+ else
+ fun_l8_n827(x)
+ end
+end
+
+def fun_l7_n467(x)
+ if (x < 1)
+ fun_l8_n871(x)
+ else
+ fun_l8_n962(x)
+ end
+end
+
+def fun_l7_n468(x)
+ if (x < 1)
+ fun_l8_n323(x)
+ else
+ fun_l8_n813(x)
+ end
+end
+
+def fun_l7_n469(x)
+ if (x < 1)
+ fun_l8_n100(x)
+ else
+ fun_l8_n905(x)
+ end
+end
+
+def fun_l7_n470(x)
+ if (x < 1)
+ fun_l8_n95(x)
+ else
+ fun_l8_n96(x)
+ end
+end
+
+def fun_l7_n471(x)
+ if (x < 1)
+ fun_l8_n398(x)
+ else
+ fun_l8_n40(x)
+ end
+end
+
+def fun_l7_n472(x)
+ if (x < 1)
+ fun_l8_n280(x)
+ else
+ fun_l8_n34(x)
+ end
+end
+
+def fun_l7_n473(x)
+ if (x < 1)
+ fun_l8_n262(x)
+ else
+ fun_l8_n399(x)
+ end
+end
+
+def fun_l7_n474(x)
+ if (x < 1)
+ fun_l8_n126(x)
+ else
+ fun_l8_n208(x)
+ end
+end
+
+def fun_l7_n475(x)
+ if (x < 1)
+ fun_l8_n371(x)
+ else
+ fun_l8_n697(x)
+ end
+end
+
+def fun_l7_n476(x)
+ if (x < 1)
+ fun_l8_n617(x)
+ else
+ fun_l8_n822(x)
+ end
+end
+
+def fun_l7_n477(x)
+ if (x < 1)
+ fun_l8_n24(x)
+ else
+ fun_l8_n300(x)
+ end
+end
+
+def fun_l7_n478(x)
+ if (x < 1)
+ fun_l8_n864(x)
+ else
+ fun_l8_n357(x)
+ end
+end
+
+def fun_l7_n479(x)
+ if (x < 1)
+ fun_l8_n231(x)
+ else
+ fun_l8_n892(x)
+ end
+end
+
+def fun_l7_n480(x)
+ if (x < 1)
+ fun_l8_n200(x)
+ else
+ fun_l8_n49(x)
+ end
+end
+
+def fun_l7_n481(x)
+ if (x < 1)
+ fun_l8_n43(x)
+ else
+ fun_l8_n86(x)
+ end
+end
+
+def fun_l7_n482(x)
+ if (x < 1)
+ fun_l8_n617(x)
+ else
+ fun_l8_n752(x)
+ end
+end
+
+def fun_l7_n483(x)
+ if (x < 1)
+ fun_l8_n65(x)
+ else
+ fun_l8_n796(x)
+ end
+end
+
+def fun_l7_n484(x)
+ if (x < 1)
+ fun_l8_n960(x)
+ else
+ fun_l8_n174(x)
+ end
+end
+
+def fun_l7_n485(x)
+ if (x < 1)
+ fun_l8_n383(x)
+ else
+ fun_l8_n50(x)
+ end
+end
+
+def fun_l7_n486(x)
+ if (x < 1)
+ fun_l8_n269(x)
+ else
+ fun_l8_n413(x)
+ end
+end
+
+def fun_l7_n487(x)
+ if (x < 1)
+ fun_l8_n762(x)
+ else
+ fun_l8_n368(x)
+ end
+end
+
+def fun_l7_n488(x)
+ if (x < 1)
+ fun_l8_n635(x)
+ else
+ fun_l8_n900(x)
+ end
+end
+
+def fun_l7_n489(x)
+ if (x < 1)
+ fun_l8_n707(x)
+ else
+ fun_l8_n376(x)
+ end
+end
+
+def fun_l7_n490(x)
+ if (x < 1)
+ fun_l8_n215(x)
+ else
+ fun_l8_n255(x)
+ end
+end
+
+def fun_l7_n491(x)
+ if (x < 1)
+ fun_l8_n730(x)
+ else
+ fun_l8_n489(x)
+ end
+end
+
+def fun_l7_n492(x)
+ if (x < 1)
+ fun_l8_n896(x)
+ else
+ fun_l8_n501(x)
+ end
+end
+
+def fun_l7_n493(x)
+ if (x < 1)
+ fun_l8_n359(x)
+ else
+ fun_l8_n876(x)
+ end
+end
+
+def fun_l7_n494(x)
+ if (x < 1)
+ fun_l8_n13(x)
+ else
+ fun_l8_n669(x)
+ end
+end
+
+def fun_l7_n495(x)
+ if (x < 1)
+ fun_l8_n442(x)
+ else
+ fun_l8_n975(x)
+ end
+end
+
+def fun_l7_n496(x)
+ if (x < 1)
+ fun_l8_n349(x)
+ else
+ fun_l8_n240(x)
+ end
+end
+
+def fun_l7_n497(x)
+ if (x < 1)
+ fun_l8_n174(x)
+ else
+ fun_l8_n416(x)
+ end
+end
+
+def fun_l7_n498(x)
+ if (x < 1)
+ fun_l8_n141(x)
+ else
+ fun_l8_n231(x)
+ end
+end
+
+def fun_l7_n499(x)
+ if (x < 1)
+ fun_l8_n868(x)
+ else
+ fun_l8_n370(x)
+ end
+end
+
+def fun_l7_n500(x)
+ if (x < 1)
+ fun_l8_n888(x)
+ else
+ fun_l8_n525(x)
+ end
+end
+
+def fun_l7_n501(x)
+ if (x < 1)
+ fun_l8_n418(x)
+ else
+ fun_l8_n402(x)
+ end
+end
+
+def fun_l7_n502(x)
+ if (x < 1)
+ fun_l8_n910(x)
+ else
+ fun_l8_n308(x)
+ end
+end
+
+def fun_l7_n503(x)
+ if (x < 1)
+ fun_l8_n435(x)
+ else
+ fun_l8_n106(x)
+ end
+end
+
+def fun_l7_n504(x)
+ if (x < 1)
+ fun_l8_n716(x)
+ else
+ fun_l8_n768(x)
+ end
+end
+
+def fun_l7_n505(x)
+ if (x < 1)
+ fun_l8_n690(x)
+ else
+ fun_l8_n382(x)
+ end
+end
+
+def fun_l7_n506(x)
+ if (x < 1)
+ fun_l8_n786(x)
+ else
+ fun_l8_n270(x)
+ end
+end
+
+def fun_l7_n507(x)
+ if (x < 1)
+ fun_l8_n317(x)
+ else
+ fun_l8_n802(x)
+ end
+end
+
+def fun_l7_n508(x)
+ if (x < 1)
+ fun_l8_n423(x)
+ else
+ fun_l8_n91(x)
+ end
+end
+
+def fun_l7_n509(x)
+ if (x < 1)
+ fun_l8_n853(x)
+ else
+ fun_l8_n434(x)
+ end
+end
+
+def fun_l7_n510(x)
+ if (x < 1)
+ fun_l8_n691(x)
+ else
+ fun_l8_n458(x)
+ end
+end
+
+def fun_l7_n511(x)
+ if (x < 1)
+ fun_l8_n806(x)
+ else
+ fun_l8_n989(x)
+ end
+end
+
+def fun_l7_n512(x)
+ if (x < 1)
+ fun_l8_n696(x)
+ else
+ fun_l8_n234(x)
+ end
+end
+
+def fun_l7_n513(x)
+ if (x < 1)
+ fun_l8_n370(x)
+ else
+ fun_l8_n440(x)
+ end
+end
+
+def fun_l7_n514(x)
+ if (x < 1)
+ fun_l8_n889(x)
+ else
+ fun_l8_n306(x)
+ end
+end
+
+def fun_l7_n515(x)
+ if (x < 1)
+ fun_l8_n147(x)
+ else
+ fun_l8_n527(x)
+ end
+end
+
+def fun_l7_n516(x)
+ if (x < 1)
+ fun_l8_n18(x)
+ else
+ fun_l8_n120(x)
+ end
+end
+
+def fun_l7_n517(x)
+ if (x < 1)
+ fun_l8_n93(x)
+ else
+ fun_l8_n861(x)
+ end
+end
+
+def fun_l7_n518(x)
+ if (x < 1)
+ fun_l8_n954(x)
+ else
+ fun_l8_n864(x)
+ end
+end
+
+def fun_l7_n519(x)
+ if (x < 1)
+ fun_l8_n886(x)
+ else
+ fun_l8_n227(x)
+ end
+end
+
+def fun_l7_n520(x)
+ if (x < 1)
+ fun_l8_n525(x)
+ else
+ fun_l8_n73(x)
+ end
+end
+
+def fun_l7_n521(x)
+ if (x < 1)
+ fun_l8_n550(x)
+ else
+ fun_l8_n638(x)
+ end
+end
+
+def fun_l7_n522(x)
+ if (x < 1)
+ fun_l8_n36(x)
+ else
+ fun_l8_n511(x)
+ end
+end
+
+def fun_l7_n523(x)
+ if (x < 1)
+ fun_l8_n346(x)
+ else
+ fun_l8_n257(x)
+ end
+end
+
+def fun_l7_n524(x)
+ if (x < 1)
+ fun_l8_n973(x)
+ else
+ fun_l8_n704(x)
+ end
+end
+
+def fun_l7_n525(x)
+ if (x < 1)
+ fun_l8_n21(x)
+ else
+ fun_l8_n354(x)
+ end
+end
+
+def fun_l7_n526(x)
+ if (x < 1)
+ fun_l8_n394(x)
+ else
+ fun_l8_n461(x)
+ end
+end
+
+def fun_l7_n527(x)
+ if (x < 1)
+ fun_l8_n444(x)
+ else
+ fun_l8_n333(x)
+ end
+end
+
+def fun_l7_n528(x)
+ if (x < 1)
+ fun_l8_n743(x)
+ else
+ fun_l8_n579(x)
+ end
+end
+
+def fun_l7_n529(x)
+ if (x < 1)
+ fun_l8_n135(x)
+ else
+ fun_l8_n69(x)
+ end
+end
+
+def fun_l7_n530(x)
+ if (x < 1)
+ fun_l8_n66(x)
+ else
+ fun_l8_n6(x)
+ end
+end
+
+def fun_l7_n531(x)
+ if (x < 1)
+ fun_l8_n84(x)
+ else
+ fun_l8_n392(x)
+ end
+end
+
+def fun_l7_n532(x)
+ if (x < 1)
+ fun_l8_n178(x)
+ else
+ fun_l8_n227(x)
+ end
+end
+
+def fun_l7_n533(x)
+ if (x < 1)
+ fun_l8_n695(x)
+ else
+ fun_l8_n696(x)
+ end
+end
+
+def fun_l7_n534(x)
+ if (x < 1)
+ fun_l8_n266(x)
+ else
+ fun_l8_n8(x)
+ end
+end
+
+def fun_l7_n535(x)
+ if (x < 1)
+ fun_l8_n806(x)
+ else
+ fun_l8_n878(x)
+ end
+end
+
+def fun_l7_n536(x)
+ if (x < 1)
+ fun_l8_n775(x)
+ else
+ fun_l8_n778(x)
+ end
+end
+
+def fun_l7_n537(x)
+ if (x < 1)
+ fun_l8_n133(x)
+ else
+ fun_l8_n552(x)
+ end
+end
+
+def fun_l7_n538(x)
+ if (x < 1)
+ fun_l8_n71(x)
+ else
+ fun_l8_n786(x)
+ end
+end
+
+def fun_l7_n539(x)
+ if (x < 1)
+ fun_l8_n679(x)
+ else
+ fun_l8_n407(x)
+ end
+end
+
+def fun_l7_n540(x)
+ if (x < 1)
+ fun_l8_n532(x)
+ else
+ fun_l8_n75(x)
+ end
+end
+
+def fun_l7_n541(x)
+ if (x < 1)
+ fun_l8_n367(x)
+ else
+ fun_l8_n505(x)
+ end
+end
+
+def fun_l7_n542(x)
+ if (x < 1)
+ fun_l8_n74(x)
+ else
+ fun_l8_n374(x)
+ end
+end
+
+def fun_l7_n543(x)
+ if (x < 1)
+ fun_l8_n207(x)
+ else
+ fun_l8_n874(x)
+ end
+end
+
+def fun_l7_n544(x)
+ if (x < 1)
+ fun_l8_n774(x)
+ else
+ fun_l8_n750(x)
+ end
+end
+
+def fun_l7_n545(x)
+ if (x < 1)
+ fun_l8_n503(x)
+ else
+ fun_l8_n933(x)
+ end
+end
+
+def fun_l7_n546(x)
+ if (x < 1)
+ fun_l8_n125(x)
+ else
+ fun_l8_n570(x)
+ end
+end
+
+def fun_l7_n547(x)
+ if (x < 1)
+ fun_l8_n743(x)
+ else
+ fun_l8_n506(x)
+ end
+end
+
+def fun_l7_n548(x)
+ if (x < 1)
+ fun_l8_n297(x)
+ else
+ fun_l8_n70(x)
+ end
+end
+
+def fun_l7_n549(x)
+ if (x < 1)
+ fun_l8_n692(x)
+ else
+ fun_l8_n652(x)
+ end
+end
+
+def fun_l7_n550(x)
+ if (x < 1)
+ fun_l8_n446(x)
+ else
+ fun_l8_n432(x)
+ end
+end
+
+def fun_l7_n551(x)
+ if (x < 1)
+ fun_l8_n947(x)
+ else
+ fun_l8_n429(x)
+ end
+end
+
+def fun_l7_n552(x)
+ if (x < 1)
+ fun_l8_n417(x)
+ else
+ fun_l8_n136(x)
+ end
+end
+
+def fun_l7_n553(x)
+ if (x < 1)
+ fun_l8_n236(x)
+ else
+ fun_l8_n291(x)
+ end
+end
+
+def fun_l7_n554(x)
+ if (x < 1)
+ fun_l8_n60(x)
+ else
+ fun_l8_n328(x)
+ end
+end
+
+def fun_l7_n555(x)
+ if (x < 1)
+ fun_l8_n97(x)
+ else
+ fun_l8_n461(x)
+ end
+end
+
+def fun_l7_n556(x)
+ if (x < 1)
+ fun_l8_n158(x)
+ else
+ fun_l8_n603(x)
+ end
+end
+
+def fun_l7_n557(x)
+ if (x < 1)
+ fun_l8_n328(x)
+ else
+ fun_l8_n725(x)
+ end
+end
+
+def fun_l7_n558(x)
+ if (x < 1)
+ fun_l8_n25(x)
+ else
+ fun_l8_n933(x)
+ end
+end
+
+def fun_l7_n559(x)
+ if (x < 1)
+ fun_l8_n352(x)
+ else
+ fun_l8_n552(x)
+ end
+end
+
+def fun_l7_n560(x)
+ if (x < 1)
+ fun_l8_n427(x)
+ else
+ fun_l8_n91(x)
+ end
+end
+
+def fun_l7_n561(x)
+ if (x < 1)
+ fun_l8_n293(x)
+ else
+ fun_l8_n749(x)
+ end
+end
+
+def fun_l7_n562(x)
+ if (x < 1)
+ fun_l8_n672(x)
+ else
+ fun_l8_n905(x)
+ end
+end
+
+def fun_l7_n563(x)
+ if (x < 1)
+ fun_l8_n201(x)
+ else
+ fun_l8_n668(x)
+ end
+end
+
+def fun_l7_n564(x)
+ if (x < 1)
+ fun_l8_n109(x)
+ else
+ fun_l8_n401(x)
+ end
+end
+
+def fun_l7_n565(x)
+ if (x < 1)
+ fun_l8_n678(x)
+ else
+ fun_l8_n890(x)
+ end
+end
+
+def fun_l7_n566(x)
+ if (x < 1)
+ fun_l8_n876(x)
+ else
+ fun_l8_n129(x)
+ end
+end
+
+def fun_l7_n567(x)
+ if (x < 1)
+ fun_l8_n908(x)
+ else
+ fun_l8_n979(x)
+ end
+end
+
+def fun_l7_n568(x)
+ if (x < 1)
+ fun_l8_n899(x)
+ else
+ fun_l8_n792(x)
+ end
+end
+
+def fun_l7_n569(x)
+ if (x < 1)
+ fun_l8_n742(x)
+ else
+ fun_l8_n441(x)
+ end
+end
+
+def fun_l7_n570(x)
+ if (x < 1)
+ fun_l8_n338(x)
+ else
+ fun_l8_n877(x)
+ end
+end
+
+def fun_l7_n571(x)
+ if (x < 1)
+ fun_l8_n684(x)
+ else
+ fun_l8_n167(x)
+ end
+end
+
+def fun_l7_n572(x)
+ if (x < 1)
+ fun_l8_n366(x)
+ else
+ fun_l8_n239(x)
+ end
+end
+
+def fun_l7_n573(x)
+ if (x < 1)
+ fun_l8_n925(x)
+ else
+ fun_l8_n648(x)
+ end
+end
+
+def fun_l7_n574(x)
+ if (x < 1)
+ fun_l8_n825(x)
+ else
+ fun_l8_n811(x)
+ end
+end
+
+def fun_l7_n575(x)
+ if (x < 1)
+ fun_l8_n348(x)
+ else
+ fun_l8_n994(x)
+ end
+end
+
+def fun_l7_n576(x)
+ if (x < 1)
+ fun_l8_n721(x)
+ else
+ fun_l8_n584(x)
+ end
+end
+
+def fun_l7_n577(x)
+ if (x < 1)
+ fun_l8_n827(x)
+ else
+ fun_l8_n968(x)
+ end
+end
+
+def fun_l7_n578(x)
+ if (x < 1)
+ fun_l8_n649(x)
+ else
+ fun_l8_n684(x)
+ end
+end
+
+def fun_l7_n579(x)
+ if (x < 1)
+ fun_l8_n43(x)
+ else
+ fun_l8_n183(x)
+ end
+end
+
+def fun_l7_n580(x)
+ if (x < 1)
+ fun_l8_n516(x)
+ else
+ fun_l8_n893(x)
+ end
+end
+
+def fun_l7_n581(x)
+ if (x < 1)
+ fun_l8_n334(x)
+ else
+ fun_l8_n677(x)
+ end
+end
+
+def fun_l7_n582(x)
+ if (x < 1)
+ fun_l8_n731(x)
+ else
+ fun_l8_n922(x)
+ end
+end
+
+def fun_l7_n583(x)
+ if (x < 1)
+ fun_l8_n653(x)
+ else
+ fun_l8_n403(x)
+ end
+end
+
+def fun_l7_n584(x)
+ if (x < 1)
+ fun_l8_n534(x)
+ else
+ fun_l8_n155(x)
+ end
+end
+
+def fun_l7_n585(x)
+ if (x < 1)
+ fun_l8_n1(x)
+ else
+ fun_l8_n903(x)
+ end
+end
+
+def fun_l7_n586(x)
+ if (x < 1)
+ fun_l8_n956(x)
+ else
+ fun_l8_n182(x)
+ end
+end
+
+def fun_l7_n587(x)
+ if (x < 1)
+ fun_l8_n590(x)
+ else
+ fun_l8_n707(x)
+ end
+end
+
+def fun_l7_n588(x)
+ if (x < 1)
+ fun_l8_n74(x)
+ else
+ fun_l8_n612(x)
+ end
+end
+
+def fun_l7_n589(x)
+ if (x < 1)
+ fun_l8_n17(x)
+ else
+ fun_l8_n193(x)
+ end
+end
+
+def fun_l7_n590(x)
+ if (x < 1)
+ fun_l8_n650(x)
+ else
+ fun_l8_n863(x)
+ end
+end
+
+def fun_l7_n591(x)
+ if (x < 1)
+ fun_l8_n974(x)
+ else
+ fun_l8_n932(x)
+ end
+end
+
+def fun_l7_n592(x)
+ if (x < 1)
+ fun_l8_n17(x)
+ else
+ fun_l8_n537(x)
+ end
+end
+
+def fun_l7_n593(x)
+ if (x < 1)
+ fun_l8_n118(x)
+ else
+ fun_l8_n588(x)
+ end
+end
+
+def fun_l7_n594(x)
+ if (x < 1)
+ fun_l8_n241(x)
+ else
+ fun_l8_n929(x)
+ end
+end
+
+def fun_l7_n595(x)
+ if (x < 1)
+ fun_l8_n667(x)
+ else
+ fun_l8_n251(x)
+ end
+end
+
+def fun_l7_n596(x)
+ if (x < 1)
+ fun_l8_n473(x)
+ else
+ fun_l8_n189(x)
+ end
+end
+
+def fun_l7_n597(x)
+ if (x < 1)
+ fun_l8_n687(x)
+ else
+ fun_l8_n666(x)
+ end
+end
+
+def fun_l7_n598(x)
+ if (x < 1)
+ fun_l8_n700(x)
+ else
+ fun_l8_n294(x)
+ end
+end
+
+def fun_l7_n599(x)
+ if (x < 1)
+ fun_l8_n144(x)
+ else
+ fun_l8_n656(x)
+ end
+end
+
+def fun_l7_n600(x)
+ if (x < 1)
+ fun_l8_n375(x)
+ else
+ fun_l8_n571(x)
+ end
+end
+
+def fun_l7_n601(x)
+ if (x < 1)
+ fun_l8_n506(x)
+ else
+ fun_l8_n212(x)
+ end
+end
+
+def fun_l7_n602(x)
+ if (x < 1)
+ fun_l8_n770(x)
+ else
+ fun_l8_n491(x)
+ end
+end
+
+def fun_l7_n603(x)
+ if (x < 1)
+ fun_l8_n325(x)
+ else
+ fun_l8_n660(x)
+ end
+end
+
+def fun_l7_n604(x)
+ if (x < 1)
+ fun_l8_n255(x)
+ else
+ fun_l8_n842(x)
+ end
+end
+
+def fun_l7_n605(x)
+ if (x < 1)
+ fun_l8_n149(x)
+ else
+ fun_l8_n648(x)
+ end
+end
+
+def fun_l7_n606(x)
+ if (x < 1)
+ fun_l8_n845(x)
+ else
+ fun_l8_n248(x)
+ end
+end
+
+def fun_l7_n607(x)
+ if (x < 1)
+ fun_l8_n484(x)
+ else
+ fun_l8_n333(x)
+ end
+end
+
+def fun_l7_n608(x)
+ if (x < 1)
+ fun_l8_n287(x)
+ else
+ fun_l8_n341(x)
+ end
+end
+
+def fun_l7_n609(x)
+ if (x < 1)
+ fun_l8_n873(x)
+ else
+ fun_l8_n113(x)
+ end
+end
+
+def fun_l7_n610(x)
+ if (x < 1)
+ fun_l8_n45(x)
+ else
+ fun_l8_n994(x)
+ end
+end
+
+def fun_l7_n611(x)
+ if (x < 1)
+ fun_l8_n427(x)
+ else
+ fun_l8_n359(x)
+ end
+end
+
+def fun_l7_n612(x)
+ if (x < 1)
+ fun_l8_n433(x)
+ else
+ fun_l8_n189(x)
+ end
+end
+
+def fun_l7_n613(x)
+ if (x < 1)
+ fun_l8_n25(x)
+ else
+ fun_l8_n564(x)
+ end
+end
+
+def fun_l7_n614(x)
+ if (x < 1)
+ fun_l8_n789(x)
+ else
+ fun_l8_n441(x)
+ end
+end
+
+def fun_l7_n615(x)
+ if (x < 1)
+ fun_l8_n353(x)
+ else
+ fun_l8_n217(x)
+ end
+end
+
+def fun_l7_n616(x)
+ if (x < 1)
+ fun_l8_n334(x)
+ else
+ fun_l8_n559(x)
+ end
+end
+
+def fun_l7_n617(x)
+ if (x < 1)
+ fun_l8_n709(x)
+ else
+ fun_l8_n764(x)
+ end
+end
+
+def fun_l7_n618(x)
+ if (x < 1)
+ fun_l8_n710(x)
+ else
+ fun_l8_n307(x)
+ end
+end
+
+def fun_l7_n619(x)
+ if (x < 1)
+ fun_l8_n246(x)
+ else
+ fun_l8_n88(x)
+ end
+end
+
+def fun_l7_n620(x)
+ if (x < 1)
+ fun_l8_n259(x)
+ else
+ fun_l8_n813(x)
+ end
+end
+
+def fun_l7_n621(x)
+ if (x < 1)
+ fun_l8_n250(x)
+ else
+ fun_l8_n566(x)
+ end
+end
+
+def fun_l7_n622(x)
+ if (x < 1)
+ fun_l8_n223(x)
+ else
+ fun_l8_n627(x)
+ end
+end
+
+def fun_l7_n623(x)
+ if (x < 1)
+ fun_l8_n345(x)
+ else
+ fun_l8_n604(x)
+ end
+end
+
+def fun_l7_n624(x)
+ if (x < 1)
+ fun_l8_n405(x)
+ else
+ fun_l8_n850(x)
+ end
+end
+
+def fun_l7_n625(x)
+ if (x < 1)
+ fun_l8_n278(x)
+ else
+ fun_l8_n643(x)
+ end
+end
+
+def fun_l7_n626(x)
+ if (x < 1)
+ fun_l8_n359(x)
+ else
+ fun_l8_n167(x)
+ end
+end
+
+def fun_l7_n627(x)
+ if (x < 1)
+ fun_l8_n589(x)
+ else
+ fun_l8_n656(x)
+ end
+end
+
+def fun_l7_n628(x)
+ if (x < 1)
+ fun_l8_n612(x)
+ else
+ fun_l8_n227(x)
+ end
+end
+
+def fun_l7_n629(x)
+ if (x < 1)
+ fun_l8_n845(x)
+ else
+ fun_l8_n469(x)
+ end
+end
+
+def fun_l7_n630(x)
+ if (x < 1)
+ fun_l8_n833(x)
+ else
+ fun_l8_n92(x)
+ end
+end
+
+def fun_l7_n631(x)
+ if (x < 1)
+ fun_l8_n411(x)
+ else
+ fun_l8_n815(x)
+ end
+end
+
+def fun_l7_n632(x)
+ if (x < 1)
+ fun_l8_n844(x)
+ else
+ fun_l8_n349(x)
+ end
+end
+
+def fun_l7_n633(x)
+ if (x < 1)
+ fun_l8_n333(x)
+ else
+ fun_l8_n468(x)
+ end
+end
+
+def fun_l7_n634(x)
+ if (x < 1)
+ fun_l8_n12(x)
+ else
+ fun_l8_n727(x)
+ end
+end
+
+def fun_l7_n635(x)
+ if (x < 1)
+ fun_l8_n65(x)
+ else
+ fun_l8_n729(x)
+ end
+end
+
+def fun_l7_n636(x)
+ if (x < 1)
+ fun_l8_n54(x)
+ else
+ fun_l8_n524(x)
+ end
+end
+
+def fun_l7_n637(x)
+ if (x < 1)
+ fun_l8_n547(x)
+ else
+ fun_l8_n220(x)
+ end
+end
+
+def fun_l7_n638(x)
+ if (x < 1)
+ fun_l8_n679(x)
+ else
+ fun_l8_n693(x)
+ end
+end
+
+def fun_l7_n639(x)
+ if (x < 1)
+ fun_l8_n428(x)
+ else
+ fun_l8_n938(x)
+ end
+end
+
+def fun_l7_n640(x)
+ if (x < 1)
+ fun_l8_n779(x)
+ else
+ fun_l8_n323(x)
+ end
+end
+
+def fun_l7_n641(x)
+ if (x < 1)
+ fun_l8_n254(x)
+ else
+ fun_l8_n443(x)
+ end
+end
+
+def fun_l7_n642(x)
+ if (x < 1)
+ fun_l8_n623(x)
+ else
+ fun_l8_n361(x)
+ end
+end
+
+def fun_l7_n643(x)
+ if (x < 1)
+ fun_l8_n524(x)
+ else
+ fun_l8_n19(x)
+ end
+end
+
+def fun_l7_n644(x)
+ if (x < 1)
+ fun_l8_n77(x)
+ else
+ fun_l8_n696(x)
+ end
+end
+
+def fun_l7_n645(x)
+ if (x < 1)
+ fun_l8_n468(x)
+ else
+ fun_l8_n819(x)
+ end
+end
+
+def fun_l7_n646(x)
+ if (x < 1)
+ fun_l8_n319(x)
+ else
+ fun_l8_n921(x)
+ end
+end
+
+def fun_l7_n647(x)
+ if (x < 1)
+ fun_l8_n681(x)
+ else
+ fun_l8_n925(x)
+ end
+end
+
+def fun_l7_n648(x)
+ if (x < 1)
+ fun_l8_n146(x)
+ else
+ fun_l8_n451(x)
+ end
+end
+
+def fun_l7_n649(x)
+ if (x < 1)
+ fun_l8_n871(x)
+ else
+ fun_l8_n707(x)
+ end
+end
+
+def fun_l7_n650(x)
+ if (x < 1)
+ fun_l8_n782(x)
+ else
+ fun_l8_n556(x)
+ end
+end
+
+def fun_l7_n651(x)
+ if (x < 1)
+ fun_l8_n721(x)
+ else
+ fun_l8_n80(x)
+ end
+end
+
+def fun_l7_n652(x)
+ if (x < 1)
+ fun_l8_n110(x)
+ else
+ fun_l8_n529(x)
+ end
+end
+
+def fun_l7_n653(x)
+ if (x < 1)
+ fun_l8_n107(x)
+ else
+ fun_l8_n876(x)
+ end
+end
+
+def fun_l7_n654(x)
+ if (x < 1)
+ fun_l8_n902(x)
+ else
+ fun_l8_n45(x)
+ end
+end
+
+def fun_l7_n655(x)
+ if (x < 1)
+ fun_l8_n714(x)
+ else
+ fun_l8_n939(x)
+ end
+end
+
+def fun_l7_n656(x)
+ if (x < 1)
+ fun_l8_n761(x)
+ else
+ fun_l8_n940(x)
+ end
+end
+
+def fun_l7_n657(x)
+ if (x < 1)
+ fun_l8_n165(x)
+ else
+ fun_l8_n779(x)
+ end
+end
+
+def fun_l7_n658(x)
+ if (x < 1)
+ fun_l8_n848(x)
+ else
+ fun_l8_n307(x)
+ end
+end
+
+def fun_l7_n659(x)
+ if (x < 1)
+ fun_l8_n414(x)
+ else
+ fun_l8_n855(x)
+ end
+end
+
+def fun_l7_n660(x)
+ if (x < 1)
+ fun_l8_n963(x)
+ else
+ fun_l8_n887(x)
+ end
+end
+
+def fun_l7_n661(x)
+ if (x < 1)
+ fun_l8_n71(x)
+ else
+ fun_l8_n249(x)
+ end
+end
+
+def fun_l7_n662(x)
+ if (x < 1)
+ fun_l8_n426(x)
+ else
+ fun_l8_n977(x)
+ end
+end
+
+def fun_l7_n663(x)
+ if (x < 1)
+ fun_l8_n924(x)
+ else
+ fun_l8_n606(x)
+ end
+end
+
+def fun_l7_n664(x)
+ if (x < 1)
+ fun_l8_n88(x)
+ else
+ fun_l8_n718(x)
+ end
+end
+
+def fun_l7_n665(x)
+ if (x < 1)
+ fun_l8_n611(x)
+ else
+ fun_l8_n898(x)
+ end
+end
+
+def fun_l7_n666(x)
+ if (x < 1)
+ fun_l8_n656(x)
+ else
+ fun_l8_n116(x)
+ end
+end
+
+def fun_l7_n667(x)
+ if (x < 1)
+ fun_l8_n196(x)
+ else
+ fun_l8_n688(x)
+ end
+end
+
+def fun_l7_n668(x)
+ if (x < 1)
+ fun_l8_n873(x)
+ else
+ fun_l8_n561(x)
+ end
+end
+
+def fun_l7_n669(x)
+ if (x < 1)
+ fun_l8_n947(x)
+ else
+ fun_l8_n64(x)
+ end
+end
+
+def fun_l7_n670(x)
+ if (x < 1)
+ fun_l8_n309(x)
+ else
+ fun_l8_n708(x)
+ end
+end
+
+def fun_l7_n671(x)
+ if (x < 1)
+ fun_l8_n699(x)
+ else
+ fun_l8_n218(x)
+ end
+end
+
+def fun_l7_n672(x)
+ if (x < 1)
+ fun_l8_n930(x)
+ else
+ fun_l8_n387(x)
+ end
+end
+
+def fun_l7_n673(x)
+ if (x < 1)
+ fun_l8_n598(x)
+ else
+ fun_l8_n245(x)
+ end
+end
+
+def fun_l7_n674(x)
+ if (x < 1)
+ fun_l8_n411(x)
+ else
+ fun_l8_n236(x)
+ end
+end
+
+def fun_l7_n675(x)
+ if (x < 1)
+ fun_l8_n193(x)
+ else
+ fun_l8_n61(x)
+ end
+end
+
+def fun_l7_n676(x)
+ if (x < 1)
+ fun_l8_n2(x)
+ else
+ fun_l8_n253(x)
+ end
+end
+
+def fun_l7_n677(x)
+ if (x < 1)
+ fun_l8_n839(x)
+ else
+ fun_l8_n919(x)
+ end
+end
+
+def fun_l7_n678(x)
+ if (x < 1)
+ fun_l8_n643(x)
+ else
+ fun_l8_n245(x)
+ end
+end
+
+def fun_l7_n679(x)
+ if (x < 1)
+ fun_l8_n625(x)
+ else
+ fun_l8_n690(x)
+ end
+end
+
+def fun_l7_n680(x)
+ if (x < 1)
+ fun_l8_n899(x)
+ else
+ fun_l8_n307(x)
+ end
+end
+
+def fun_l7_n681(x)
+ if (x < 1)
+ fun_l8_n894(x)
+ else
+ fun_l8_n92(x)
+ end
+end
+
+def fun_l7_n682(x)
+ if (x < 1)
+ fun_l8_n139(x)
+ else
+ fun_l8_n252(x)
+ end
+end
+
+def fun_l7_n683(x)
+ if (x < 1)
+ fun_l8_n978(x)
+ else
+ fun_l8_n84(x)
+ end
+end
+
+def fun_l7_n684(x)
+ if (x < 1)
+ fun_l8_n426(x)
+ else
+ fun_l8_n329(x)
+ end
+end
+
+def fun_l7_n685(x)
+ if (x < 1)
+ fun_l8_n241(x)
+ else
+ fun_l8_n780(x)
+ end
+end
+
+def fun_l7_n686(x)
+ if (x < 1)
+ fun_l8_n793(x)
+ else
+ fun_l8_n534(x)
+ end
+end
+
+def fun_l7_n687(x)
+ if (x < 1)
+ fun_l8_n409(x)
+ else
+ fun_l8_n152(x)
+ end
+end
+
+def fun_l7_n688(x)
+ if (x < 1)
+ fun_l8_n838(x)
+ else
+ fun_l8_n555(x)
+ end
+end
+
+def fun_l7_n689(x)
+ if (x < 1)
+ fun_l8_n634(x)
+ else
+ fun_l8_n27(x)
+ end
+end
+
+def fun_l7_n690(x)
+ if (x < 1)
+ fun_l8_n629(x)
+ else
+ fun_l8_n448(x)
+ end
+end
+
+def fun_l7_n691(x)
+ if (x < 1)
+ fun_l8_n487(x)
+ else
+ fun_l8_n293(x)
+ end
+end
+
+def fun_l7_n692(x)
+ if (x < 1)
+ fun_l8_n739(x)
+ else
+ fun_l8_n472(x)
+ end
+end
+
+def fun_l7_n693(x)
+ if (x < 1)
+ fun_l8_n619(x)
+ else
+ fun_l8_n642(x)
+ end
+end
+
+def fun_l7_n694(x)
+ if (x < 1)
+ fun_l8_n123(x)
+ else
+ fun_l8_n880(x)
+ end
+end
+
+def fun_l7_n695(x)
+ if (x < 1)
+ fun_l8_n695(x)
+ else
+ fun_l8_n364(x)
+ end
+end
+
+def fun_l7_n696(x)
+ if (x < 1)
+ fun_l8_n610(x)
+ else
+ fun_l8_n798(x)
+ end
+end
+
+def fun_l7_n697(x)
+ if (x < 1)
+ fun_l8_n396(x)
+ else
+ fun_l8_n704(x)
+ end
+end
+
+def fun_l7_n698(x)
+ if (x < 1)
+ fun_l8_n759(x)
+ else
+ fun_l8_n880(x)
+ end
+end
+
+def fun_l7_n699(x)
+ if (x < 1)
+ fun_l8_n885(x)
+ else
+ fun_l8_n139(x)
+ end
+end
+
+def fun_l7_n700(x)
+ if (x < 1)
+ fun_l8_n244(x)
+ else
+ fun_l8_n307(x)
+ end
+end
+
+def fun_l7_n701(x)
+ if (x < 1)
+ fun_l8_n698(x)
+ else
+ fun_l8_n949(x)
+ end
+end
+
+def fun_l7_n702(x)
+ if (x < 1)
+ fun_l8_n585(x)
+ else
+ fun_l8_n211(x)
+ end
+end
+
+def fun_l7_n703(x)
+ if (x < 1)
+ fun_l8_n834(x)
+ else
+ fun_l8_n111(x)
+ end
+end
+
+def fun_l7_n704(x)
+ if (x < 1)
+ fun_l8_n690(x)
+ else
+ fun_l8_n981(x)
+ end
+end
+
+def fun_l7_n705(x)
+ if (x < 1)
+ fun_l8_n377(x)
+ else
+ fun_l8_n392(x)
+ end
+end
+
+def fun_l7_n706(x)
+ if (x < 1)
+ fun_l8_n988(x)
+ else
+ fun_l8_n759(x)
+ end
+end
+
+def fun_l7_n707(x)
+ if (x < 1)
+ fun_l8_n917(x)
+ else
+ fun_l8_n326(x)
+ end
+end
+
+def fun_l7_n708(x)
+ if (x < 1)
+ fun_l8_n662(x)
+ else
+ fun_l8_n488(x)
+ end
+end
+
+def fun_l7_n709(x)
+ if (x < 1)
+ fun_l8_n530(x)
+ else
+ fun_l8_n663(x)
+ end
+end
+
+def fun_l7_n710(x)
+ if (x < 1)
+ fun_l8_n344(x)
+ else
+ fun_l8_n282(x)
+ end
+end
+
+def fun_l7_n711(x)
+ if (x < 1)
+ fun_l8_n908(x)
+ else
+ fun_l8_n405(x)
+ end
+end
+
+def fun_l7_n712(x)
+ if (x < 1)
+ fun_l8_n332(x)
+ else
+ fun_l8_n660(x)
+ end
+end
+
+def fun_l7_n713(x)
+ if (x < 1)
+ fun_l8_n37(x)
+ else
+ fun_l8_n689(x)
+ end
+end
+
+def fun_l7_n714(x)
+ if (x < 1)
+ fun_l8_n642(x)
+ else
+ fun_l8_n996(x)
+ end
+end
+
+def fun_l7_n715(x)
+ if (x < 1)
+ fun_l8_n322(x)
+ else
+ fun_l8_n609(x)
+ end
+end
+
+def fun_l7_n716(x)
+ if (x < 1)
+ fun_l8_n567(x)
+ else
+ fun_l8_n492(x)
+ end
+end
+
+def fun_l7_n717(x)
+ if (x < 1)
+ fun_l8_n934(x)
+ else
+ fun_l8_n353(x)
+ end
+end
+
+def fun_l7_n718(x)
+ if (x < 1)
+ fun_l8_n572(x)
+ else
+ fun_l8_n859(x)
+ end
+end
+
+def fun_l7_n719(x)
+ if (x < 1)
+ fun_l8_n777(x)
+ else
+ fun_l8_n810(x)
+ end
+end
+
+def fun_l7_n720(x)
+ if (x < 1)
+ fun_l8_n121(x)
+ else
+ fun_l8_n847(x)
+ end
+end
+
+def fun_l7_n721(x)
+ if (x < 1)
+ fun_l8_n177(x)
+ else
+ fun_l8_n484(x)
+ end
+end
+
+def fun_l7_n722(x)
+ if (x < 1)
+ fun_l8_n73(x)
+ else
+ fun_l8_n795(x)
+ end
+end
+
+def fun_l7_n723(x)
+ if (x < 1)
+ fun_l8_n950(x)
+ else
+ fun_l8_n382(x)
+ end
+end
+
+def fun_l7_n724(x)
+ if (x < 1)
+ fun_l8_n349(x)
+ else
+ fun_l8_n644(x)
+ end
+end
+
+def fun_l7_n725(x)
+ if (x < 1)
+ fun_l8_n480(x)
+ else
+ fun_l8_n262(x)
+ end
+end
+
+def fun_l7_n726(x)
+ if (x < 1)
+ fun_l8_n39(x)
+ else
+ fun_l8_n543(x)
+ end
+end
+
+def fun_l7_n727(x)
+ if (x < 1)
+ fun_l8_n934(x)
+ else
+ fun_l8_n440(x)
+ end
+end
+
+def fun_l7_n728(x)
+ if (x < 1)
+ fun_l8_n312(x)
+ else
+ fun_l8_n341(x)
+ end
+end
+
+def fun_l7_n729(x)
+ if (x < 1)
+ fun_l8_n284(x)
+ else
+ fun_l8_n884(x)
+ end
+end
+
+def fun_l7_n730(x)
+ if (x < 1)
+ fun_l8_n841(x)
+ else
+ fun_l8_n221(x)
+ end
+end
+
+def fun_l7_n731(x)
+ if (x < 1)
+ fun_l8_n719(x)
+ else
+ fun_l8_n907(x)
+ end
+end
+
+def fun_l7_n732(x)
+ if (x < 1)
+ fun_l8_n422(x)
+ else
+ fun_l8_n65(x)
+ end
+end
+
+def fun_l7_n733(x)
+ if (x < 1)
+ fun_l8_n324(x)
+ else
+ fun_l8_n811(x)
+ end
+end
+
+def fun_l7_n734(x)
+ if (x < 1)
+ fun_l8_n643(x)
+ else
+ fun_l8_n622(x)
+ end
+end
+
+def fun_l7_n735(x)
+ if (x < 1)
+ fun_l8_n20(x)
+ else
+ fun_l8_n205(x)
+ end
+end
+
+def fun_l7_n736(x)
+ if (x < 1)
+ fun_l8_n487(x)
+ else
+ fun_l8_n908(x)
+ end
+end
+
+def fun_l7_n737(x)
+ if (x < 1)
+ fun_l8_n576(x)
+ else
+ fun_l8_n789(x)
+ end
+end
+
+def fun_l7_n738(x)
+ if (x < 1)
+ fun_l8_n353(x)
+ else
+ fun_l8_n286(x)
+ end
+end
+
+def fun_l7_n739(x)
+ if (x < 1)
+ fun_l8_n614(x)
+ else
+ fun_l8_n121(x)
+ end
+end
+
+def fun_l7_n740(x)
+ if (x < 1)
+ fun_l8_n79(x)
+ else
+ fun_l8_n637(x)
+ end
+end
+
+def fun_l7_n741(x)
+ if (x < 1)
+ fun_l8_n808(x)
+ else
+ fun_l8_n461(x)
+ end
+end
+
+def fun_l7_n742(x)
+ if (x < 1)
+ fun_l8_n590(x)
+ else
+ fun_l8_n198(x)
+ end
+end
+
+def fun_l7_n743(x)
+ if (x < 1)
+ fun_l8_n498(x)
+ else
+ fun_l8_n379(x)
+ end
+end
+
+def fun_l7_n744(x)
+ if (x < 1)
+ fun_l8_n599(x)
+ else
+ fun_l8_n359(x)
+ end
+end
+
+def fun_l7_n745(x)
+ if (x < 1)
+ fun_l8_n898(x)
+ else
+ fun_l8_n520(x)
+ end
+end
+
+def fun_l7_n746(x)
+ if (x < 1)
+ fun_l8_n835(x)
+ else
+ fun_l8_n131(x)
+ end
+end
+
+def fun_l7_n747(x)
+ if (x < 1)
+ fun_l8_n648(x)
+ else
+ fun_l8_n248(x)
+ end
+end
+
+def fun_l7_n748(x)
+ if (x < 1)
+ fun_l8_n451(x)
+ else
+ fun_l8_n352(x)
+ end
+end
+
+def fun_l7_n749(x)
+ if (x < 1)
+ fun_l8_n69(x)
+ else
+ fun_l8_n974(x)
+ end
+end
+
+def fun_l7_n750(x)
+ if (x < 1)
+ fun_l8_n108(x)
+ else
+ fun_l8_n744(x)
+ end
+end
+
+def fun_l7_n751(x)
+ if (x < 1)
+ fun_l8_n171(x)
+ else
+ fun_l8_n305(x)
+ end
+end
+
+def fun_l7_n752(x)
+ if (x < 1)
+ fun_l8_n180(x)
+ else
+ fun_l8_n293(x)
+ end
+end
+
+def fun_l7_n753(x)
+ if (x < 1)
+ fun_l8_n555(x)
+ else
+ fun_l8_n882(x)
+ end
+end
+
+def fun_l7_n754(x)
+ if (x < 1)
+ fun_l8_n756(x)
+ else
+ fun_l8_n604(x)
+ end
+end
+
+def fun_l7_n755(x)
+ if (x < 1)
+ fun_l8_n782(x)
+ else
+ fun_l8_n708(x)
+ end
+end
+
+def fun_l7_n756(x)
+ if (x < 1)
+ fun_l8_n65(x)
+ else
+ fun_l8_n474(x)
+ end
+end
+
+def fun_l7_n757(x)
+ if (x < 1)
+ fun_l8_n43(x)
+ else
+ fun_l8_n892(x)
+ end
+end
+
+def fun_l7_n758(x)
+ if (x < 1)
+ fun_l8_n90(x)
+ else
+ fun_l8_n968(x)
+ end
+end
+
+def fun_l7_n759(x)
+ if (x < 1)
+ fun_l8_n599(x)
+ else
+ fun_l8_n505(x)
+ end
+end
+
+def fun_l7_n760(x)
+ if (x < 1)
+ fun_l8_n344(x)
+ else
+ fun_l8_n122(x)
+ end
+end
+
+def fun_l7_n761(x)
+ if (x < 1)
+ fun_l8_n289(x)
+ else
+ fun_l8_n867(x)
+ end
+end
+
+def fun_l7_n762(x)
+ if (x < 1)
+ fun_l8_n107(x)
+ else
+ fun_l8_n950(x)
+ end
+end
+
+def fun_l7_n763(x)
+ if (x < 1)
+ fun_l8_n405(x)
+ else
+ fun_l8_n178(x)
+ end
+end
+
+def fun_l7_n764(x)
+ if (x < 1)
+ fun_l8_n91(x)
+ else
+ fun_l8_n760(x)
+ end
+end
+
+def fun_l7_n765(x)
+ if (x < 1)
+ fun_l8_n268(x)
+ else
+ fun_l8_n451(x)
+ end
+end
+
+def fun_l7_n766(x)
+ if (x < 1)
+ fun_l8_n693(x)
+ else
+ fun_l8_n150(x)
+ end
+end
+
+def fun_l7_n767(x)
+ if (x < 1)
+ fun_l8_n622(x)
+ else
+ fun_l8_n114(x)
+ end
+end
+
+def fun_l7_n768(x)
+ if (x < 1)
+ fun_l8_n662(x)
+ else
+ fun_l8_n514(x)
+ end
+end
+
+def fun_l7_n769(x)
+ if (x < 1)
+ fun_l8_n440(x)
+ else
+ fun_l8_n537(x)
+ end
+end
+
+def fun_l7_n770(x)
+ if (x < 1)
+ fun_l8_n207(x)
+ else
+ fun_l8_n513(x)
+ end
+end
+
+def fun_l7_n771(x)
+ if (x < 1)
+ fun_l8_n394(x)
+ else
+ fun_l8_n857(x)
+ end
+end
+
+def fun_l7_n772(x)
+ if (x < 1)
+ fun_l8_n635(x)
+ else
+ fun_l8_n696(x)
+ end
+end
+
+def fun_l7_n773(x)
+ if (x < 1)
+ fun_l8_n687(x)
+ else
+ fun_l8_n926(x)
+ end
+end
+
+def fun_l7_n774(x)
+ if (x < 1)
+ fun_l8_n54(x)
+ else
+ fun_l8_n410(x)
+ end
+end
+
+def fun_l7_n775(x)
+ if (x < 1)
+ fun_l8_n825(x)
+ else
+ fun_l8_n339(x)
+ end
+end
+
+def fun_l7_n776(x)
+ if (x < 1)
+ fun_l8_n130(x)
+ else
+ fun_l8_n48(x)
+ end
+end
+
+def fun_l7_n777(x)
+ if (x < 1)
+ fun_l8_n627(x)
+ else
+ fun_l8_n191(x)
+ end
+end
+
+def fun_l7_n778(x)
+ if (x < 1)
+ fun_l8_n843(x)
+ else
+ fun_l8_n627(x)
+ end
+end
+
+def fun_l7_n779(x)
+ if (x < 1)
+ fun_l8_n950(x)
+ else
+ fun_l8_n247(x)
+ end
+end
+
+def fun_l7_n780(x)
+ if (x < 1)
+ fun_l8_n865(x)
+ else
+ fun_l8_n540(x)
+ end
+end
+
+def fun_l7_n781(x)
+ if (x < 1)
+ fun_l8_n440(x)
+ else
+ fun_l8_n326(x)
+ end
+end
+
+def fun_l7_n782(x)
+ if (x < 1)
+ fun_l8_n463(x)
+ else
+ fun_l8_n808(x)
+ end
+end
+
+def fun_l7_n783(x)
+ if (x < 1)
+ fun_l8_n44(x)
+ else
+ fun_l8_n888(x)
+ end
+end
+
+def fun_l7_n784(x)
+ if (x < 1)
+ fun_l8_n690(x)
+ else
+ fun_l8_n673(x)
+ end
+end
+
+def fun_l7_n785(x)
+ if (x < 1)
+ fun_l8_n641(x)
+ else
+ fun_l8_n367(x)
+ end
+end
+
+def fun_l7_n786(x)
+ if (x < 1)
+ fun_l8_n193(x)
+ else
+ fun_l8_n764(x)
+ end
+end
+
+def fun_l7_n787(x)
+ if (x < 1)
+ fun_l8_n604(x)
+ else
+ fun_l8_n527(x)
+ end
+end
+
+def fun_l7_n788(x)
+ if (x < 1)
+ fun_l8_n626(x)
+ else
+ fun_l8_n101(x)
+ end
+end
+
+def fun_l7_n789(x)
+ if (x < 1)
+ fun_l8_n152(x)
+ else
+ fun_l8_n9(x)
+ end
+end
+
+def fun_l7_n790(x)
+ if (x < 1)
+ fun_l8_n541(x)
+ else
+ fun_l8_n789(x)
+ end
+end
+
+def fun_l7_n791(x)
+ if (x < 1)
+ fun_l8_n706(x)
+ else
+ fun_l8_n577(x)
+ end
+end
+
+def fun_l7_n792(x)
+ if (x < 1)
+ fun_l8_n480(x)
+ else
+ fun_l8_n284(x)
+ end
+end
+
+def fun_l7_n793(x)
+ if (x < 1)
+ fun_l8_n157(x)
+ else
+ fun_l8_n620(x)
+ end
+end
+
+def fun_l7_n794(x)
+ if (x < 1)
+ fun_l8_n666(x)
+ else
+ fun_l8_n755(x)
+ end
+end
+
+def fun_l7_n795(x)
+ if (x < 1)
+ fun_l8_n487(x)
+ else
+ fun_l8_n20(x)
+ end
+end
+
+def fun_l7_n796(x)
+ if (x < 1)
+ fun_l8_n750(x)
+ else
+ fun_l8_n974(x)
+ end
+end
+
+def fun_l7_n797(x)
+ if (x < 1)
+ fun_l8_n812(x)
+ else
+ fun_l8_n915(x)
+ end
+end
+
+def fun_l7_n798(x)
+ if (x < 1)
+ fun_l8_n297(x)
+ else
+ fun_l8_n8(x)
+ end
+end
+
+def fun_l7_n799(x)
+ if (x < 1)
+ fun_l8_n385(x)
+ else
+ fun_l8_n920(x)
+ end
+end
+
+def fun_l7_n800(x)
+ if (x < 1)
+ fun_l8_n322(x)
+ else
+ fun_l8_n603(x)
+ end
+end
+
+def fun_l7_n801(x)
+ if (x < 1)
+ fun_l8_n825(x)
+ else
+ fun_l8_n702(x)
+ end
+end
+
+def fun_l7_n802(x)
+ if (x < 1)
+ fun_l8_n902(x)
+ else
+ fun_l8_n978(x)
+ end
+end
+
+def fun_l7_n803(x)
+ if (x < 1)
+ fun_l8_n921(x)
+ else
+ fun_l8_n61(x)
+ end
+end
+
+def fun_l7_n804(x)
+ if (x < 1)
+ fun_l8_n171(x)
+ else
+ fun_l8_n630(x)
+ end
+end
+
+def fun_l7_n805(x)
+ if (x < 1)
+ fun_l8_n469(x)
+ else
+ fun_l8_n265(x)
+ end
+end
+
+def fun_l7_n806(x)
+ if (x < 1)
+ fun_l8_n367(x)
+ else
+ fun_l8_n820(x)
+ end
+end
+
+def fun_l7_n807(x)
+ if (x < 1)
+ fun_l8_n242(x)
+ else
+ fun_l8_n707(x)
+ end
+end
+
+def fun_l7_n808(x)
+ if (x < 1)
+ fun_l8_n512(x)
+ else
+ fun_l8_n139(x)
+ end
+end
+
+def fun_l7_n809(x)
+ if (x < 1)
+ fun_l8_n17(x)
+ else
+ fun_l8_n615(x)
+ end
+end
+
+def fun_l7_n810(x)
+ if (x < 1)
+ fun_l8_n600(x)
+ else
+ fun_l8_n6(x)
+ end
+end
+
+def fun_l7_n811(x)
+ if (x < 1)
+ fun_l8_n342(x)
+ else
+ fun_l8_n194(x)
+ end
+end
+
+def fun_l7_n812(x)
+ if (x < 1)
+ fun_l8_n191(x)
+ else
+ fun_l8_n864(x)
+ end
+end
+
+def fun_l7_n813(x)
+ if (x < 1)
+ fun_l8_n577(x)
+ else
+ fun_l8_n113(x)
+ end
+end
+
+def fun_l7_n814(x)
+ if (x < 1)
+ fun_l8_n729(x)
+ else
+ fun_l8_n989(x)
+ end
+end
+
+def fun_l7_n815(x)
+ if (x < 1)
+ fun_l8_n707(x)
+ else
+ fun_l8_n846(x)
+ end
+end
+
+def fun_l7_n816(x)
+ if (x < 1)
+ fun_l8_n874(x)
+ else
+ fun_l8_n790(x)
+ end
+end
+
+def fun_l7_n817(x)
+ if (x < 1)
+ fun_l8_n968(x)
+ else
+ fun_l8_n215(x)
+ end
+end
+
+def fun_l7_n818(x)
+ if (x < 1)
+ fun_l8_n444(x)
+ else
+ fun_l8_n182(x)
+ end
+end
+
+def fun_l7_n819(x)
+ if (x < 1)
+ fun_l8_n103(x)
+ else
+ fun_l8_n134(x)
+ end
+end
+
+def fun_l7_n820(x)
+ if (x < 1)
+ fun_l8_n718(x)
+ else
+ fun_l8_n950(x)
+ end
+end
+
+def fun_l7_n821(x)
+ if (x < 1)
+ fun_l8_n439(x)
+ else
+ fun_l8_n68(x)
+ end
+end
+
+def fun_l7_n822(x)
+ if (x < 1)
+ fun_l8_n961(x)
+ else
+ fun_l8_n593(x)
+ end
+end
+
+def fun_l7_n823(x)
+ if (x < 1)
+ fun_l8_n212(x)
+ else
+ fun_l8_n346(x)
+ end
+end
+
+def fun_l7_n824(x)
+ if (x < 1)
+ fun_l8_n926(x)
+ else
+ fun_l8_n225(x)
+ end
+end
+
+def fun_l7_n825(x)
+ if (x < 1)
+ fun_l8_n880(x)
+ else
+ fun_l8_n527(x)
+ end
+end
+
+def fun_l7_n826(x)
+ if (x < 1)
+ fun_l8_n13(x)
+ else
+ fun_l8_n436(x)
+ end
+end
+
+def fun_l7_n827(x)
+ if (x < 1)
+ fun_l8_n19(x)
+ else
+ fun_l8_n201(x)
+ end
+end
+
+def fun_l7_n828(x)
+ if (x < 1)
+ fun_l8_n568(x)
+ else
+ fun_l8_n450(x)
+ end
+end
+
+def fun_l7_n829(x)
+ if (x < 1)
+ fun_l8_n543(x)
+ else
+ fun_l8_n606(x)
+ end
+end
+
+def fun_l7_n830(x)
+ if (x < 1)
+ fun_l8_n503(x)
+ else
+ fun_l8_n104(x)
+ end
+end
+
+def fun_l7_n831(x)
+ if (x < 1)
+ fun_l8_n185(x)
+ else
+ fun_l8_n1(x)
+ end
+end
+
+def fun_l7_n832(x)
+ if (x < 1)
+ fun_l8_n598(x)
+ else
+ fun_l8_n637(x)
+ end
+end
+
+def fun_l7_n833(x)
+ if (x < 1)
+ fun_l8_n936(x)
+ else
+ fun_l8_n554(x)
+ end
+end
+
+def fun_l7_n834(x)
+ if (x < 1)
+ fun_l8_n864(x)
+ else
+ fun_l8_n766(x)
+ end
+end
+
+def fun_l7_n835(x)
+ if (x < 1)
+ fun_l8_n11(x)
+ else
+ fun_l8_n472(x)
+ end
+end
+
+def fun_l7_n836(x)
+ if (x < 1)
+ fun_l8_n596(x)
+ else
+ fun_l8_n429(x)
+ end
+end
+
+def fun_l7_n837(x)
+ if (x < 1)
+ fun_l8_n643(x)
+ else
+ fun_l8_n61(x)
+ end
+end
+
+def fun_l7_n838(x)
+ if (x < 1)
+ fun_l8_n905(x)
+ else
+ fun_l8_n605(x)
+ end
+end
+
+def fun_l7_n839(x)
+ if (x < 1)
+ fun_l8_n371(x)
+ else
+ fun_l8_n44(x)
+ end
+end
+
+def fun_l7_n840(x)
+ if (x < 1)
+ fun_l8_n195(x)
+ else
+ fun_l8_n368(x)
+ end
+end
+
+def fun_l7_n841(x)
+ if (x < 1)
+ fun_l8_n432(x)
+ else
+ fun_l8_n368(x)
+ end
+end
+
+def fun_l7_n842(x)
+ if (x < 1)
+ fun_l8_n145(x)
+ else
+ fun_l8_n180(x)
+ end
+end
+
+def fun_l7_n843(x)
+ if (x < 1)
+ fun_l8_n124(x)
+ else
+ fun_l8_n358(x)
+ end
+end
+
+def fun_l7_n844(x)
+ if (x < 1)
+ fun_l8_n87(x)
+ else
+ fun_l8_n364(x)
+ end
+end
+
+def fun_l7_n845(x)
+ if (x < 1)
+ fun_l8_n133(x)
+ else
+ fun_l8_n849(x)
+ end
+end
+
+def fun_l7_n846(x)
+ if (x < 1)
+ fun_l8_n686(x)
+ else
+ fun_l8_n556(x)
+ end
+end
+
+def fun_l7_n847(x)
+ if (x < 1)
+ fun_l8_n732(x)
+ else
+ fun_l8_n536(x)
+ end
+end
+
+def fun_l7_n848(x)
+ if (x < 1)
+ fun_l8_n950(x)
+ else
+ fun_l8_n173(x)
+ end
+end
+
+def fun_l7_n849(x)
+ if (x < 1)
+ fun_l8_n694(x)
+ else
+ fun_l8_n747(x)
+ end
+end
+
+def fun_l7_n850(x)
+ if (x < 1)
+ fun_l8_n421(x)
+ else
+ fun_l8_n940(x)
+ end
+end
+
+def fun_l7_n851(x)
+ if (x < 1)
+ fun_l8_n359(x)
+ else
+ fun_l8_n239(x)
+ end
+end
+
+def fun_l7_n852(x)
+ if (x < 1)
+ fun_l8_n731(x)
+ else
+ fun_l8_n530(x)
+ end
+end
+
+def fun_l7_n853(x)
+ if (x < 1)
+ fun_l8_n887(x)
+ else
+ fun_l8_n548(x)
+ end
+end
+
+def fun_l7_n854(x)
+ if (x < 1)
+ fun_l8_n47(x)
+ else
+ fun_l8_n675(x)
+ end
+end
+
+def fun_l7_n855(x)
+ if (x < 1)
+ fun_l8_n534(x)
+ else
+ fun_l8_n34(x)
+ end
+end
+
+def fun_l7_n856(x)
+ if (x < 1)
+ fun_l8_n935(x)
+ else
+ fun_l8_n402(x)
+ end
+end
+
+def fun_l7_n857(x)
+ if (x < 1)
+ fun_l8_n873(x)
+ else
+ fun_l8_n864(x)
+ end
+end
+
+def fun_l7_n858(x)
+ if (x < 1)
+ fun_l8_n325(x)
+ else
+ fun_l8_n495(x)
+ end
+end
+
+def fun_l7_n859(x)
+ if (x < 1)
+ fun_l8_n758(x)
+ else
+ fun_l8_n63(x)
+ end
+end
+
+def fun_l7_n860(x)
+ if (x < 1)
+ fun_l8_n811(x)
+ else
+ fun_l8_n150(x)
+ end
+end
+
+def fun_l7_n861(x)
+ if (x < 1)
+ fun_l8_n666(x)
+ else
+ fun_l8_n282(x)
+ end
+end
+
+def fun_l7_n862(x)
+ if (x < 1)
+ fun_l8_n123(x)
+ else
+ fun_l8_n893(x)
+ end
+end
+
+def fun_l7_n863(x)
+ if (x < 1)
+ fun_l8_n681(x)
+ else
+ fun_l8_n640(x)
+ end
+end
+
+def fun_l7_n864(x)
+ if (x < 1)
+ fun_l8_n861(x)
+ else
+ fun_l8_n922(x)
+ end
+end
+
+def fun_l7_n865(x)
+ if (x < 1)
+ fun_l8_n8(x)
+ else
+ fun_l8_n14(x)
+ end
+end
+
+def fun_l7_n866(x)
+ if (x < 1)
+ fun_l8_n713(x)
+ else
+ fun_l8_n802(x)
+ end
+end
+
+def fun_l7_n867(x)
+ if (x < 1)
+ fun_l8_n654(x)
+ else
+ fun_l8_n540(x)
+ end
+end
+
+def fun_l7_n868(x)
+ if (x < 1)
+ fun_l8_n308(x)
+ else
+ fun_l8_n504(x)
+ end
+end
+
+def fun_l7_n869(x)
+ if (x < 1)
+ fun_l8_n67(x)
+ else
+ fun_l8_n592(x)
+ end
+end
+
+def fun_l7_n870(x)
+ if (x < 1)
+ fun_l8_n295(x)
+ else
+ fun_l8_n585(x)
+ end
+end
+
+def fun_l7_n871(x)
+ if (x < 1)
+ fun_l8_n121(x)
+ else
+ fun_l8_n797(x)
+ end
+end
+
+def fun_l7_n872(x)
+ if (x < 1)
+ fun_l8_n234(x)
+ else
+ fun_l8_n834(x)
+ end
+end
+
+def fun_l7_n873(x)
+ if (x < 1)
+ fun_l8_n287(x)
+ else
+ fun_l8_n731(x)
+ end
+end
+
+def fun_l7_n874(x)
+ if (x < 1)
+ fun_l8_n460(x)
+ else
+ fun_l8_n261(x)
+ end
+end
+
+def fun_l7_n875(x)
+ if (x < 1)
+ fun_l8_n211(x)
+ else
+ fun_l8_n199(x)
+ end
+end
+
+def fun_l7_n876(x)
+ if (x < 1)
+ fun_l8_n256(x)
+ else
+ fun_l8_n547(x)
+ end
+end
+
+def fun_l7_n877(x)
+ if (x < 1)
+ fun_l8_n560(x)
+ else
+ fun_l8_n202(x)
+ end
+end
+
+def fun_l7_n878(x)
+ if (x < 1)
+ fun_l8_n5(x)
+ else
+ fun_l8_n955(x)
+ end
+end
+
+def fun_l7_n879(x)
+ if (x < 1)
+ fun_l8_n908(x)
+ else
+ fun_l8_n677(x)
+ end
+end
+
+def fun_l7_n880(x)
+ if (x < 1)
+ fun_l8_n366(x)
+ else
+ fun_l8_n226(x)
+ end
+end
+
+def fun_l7_n881(x)
+ if (x < 1)
+ fun_l8_n970(x)
+ else
+ fun_l8_n939(x)
+ end
+end
+
+def fun_l7_n882(x)
+ if (x < 1)
+ fun_l8_n562(x)
+ else
+ fun_l8_n420(x)
+ end
+end
+
+def fun_l7_n883(x)
+ if (x < 1)
+ fun_l8_n377(x)
+ else
+ fun_l8_n35(x)
+ end
+end
+
+def fun_l7_n884(x)
+ if (x < 1)
+ fun_l8_n459(x)
+ else
+ fun_l8_n155(x)
+ end
+end
+
+def fun_l7_n885(x)
+ if (x < 1)
+ fun_l8_n257(x)
+ else
+ fun_l8_n704(x)
+ end
+end
+
+def fun_l7_n886(x)
+ if (x < 1)
+ fun_l8_n393(x)
+ else
+ fun_l8_n741(x)
+ end
+end
+
+def fun_l7_n887(x)
+ if (x < 1)
+ fun_l8_n333(x)
+ else
+ fun_l8_n225(x)
+ end
+end
+
+def fun_l7_n888(x)
+ if (x < 1)
+ fun_l8_n614(x)
+ else
+ fun_l8_n106(x)
+ end
+end
+
+def fun_l7_n889(x)
+ if (x < 1)
+ fun_l8_n229(x)
+ else
+ fun_l8_n519(x)
+ end
+end
+
+def fun_l7_n890(x)
+ if (x < 1)
+ fun_l8_n651(x)
+ else
+ fun_l8_n68(x)
+ end
+end
+
+def fun_l7_n891(x)
+ if (x < 1)
+ fun_l8_n987(x)
+ else
+ fun_l8_n905(x)
+ end
+end
+
+def fun_l7_n892(x)
+ if (x < 1)
+ fun_l8_n698(x)
+ else
+ fun_l8_n942(x)
+ end
+end
+
+def fun_l7_n893(x)
+ if (x < 1)
+ fun_l8_n559(x)
+ else
+ fun_l8_n613(x)
+ end
+end
+
+def fun_l7_n894(x)
+ if (x < 1)
+ fun_l8_n402(x)
+ else
+ fun_l8_n966(x)
+ end
+end
+
+def fun_l7_n895(x)
+ if (x < 1)
+ fun_l8_n475(x)
+ else
+ fun_l8_n158(x)
+ end
+end
+
+def fun_l7_n896(x)
+ if (x < 1)
+ fun_l8_n420(x)
+ else
+ fun_l8_n113(x)
+ end
+end
+
+def fun_l7_n897(x)
+ if (x < 1)
+ fun_l8_n366(x)
+ else
+ fun_l8_n272(x)
+ end
+end
+
+def fun_l7_n898(x)
+ if (x < 1)
+ fun_l8_n252(x)
+ else
+ fun_l8_n821(x)
+ end
+end
+
+def fun_l7_n899(x)
+ if (x < 1)
+ fun_l8_n736(x)
+ else
+ fun_l8_n174(x)
+ end
+end
+
+def fun_l7_n900(x)
+ if (x < 1)
+ fun_l8_n151(x)
+ else
+ fun_l8_n611(x)
+ end
+end
+
+def fun_l7_n901(x)
+ if (x < 1)
+ fun_l8_n3(x)
+ else
+ fun_l8_n221(x)
+ end
+end
+
+def fun_l7_n902(x)
+ if (x < 1)
+ fun_l8_n319(x)
+ else
+ fun_l8_n930(x)
+ end
+end
+
+def fun_l7_n903(x)
+ if (x < 1)
+ fun_l8_n619(x)
+ else
+ fun_l8_n491(x)
+ end
+end
+
+def fun_l7_n904(x)
+ if (x < 1)
+ fun_l8_n144(x)
+ else
+ fun_l8_n304(x)
+ end
+end
+
+def fun_l7_n905(x)
+ if (x < 1)
+ fun_l8_n721(x)
+ else
+ fun_l8_n996(x)
+ end
+end
+
+def fun_l7_n906(x)
+ if (x < 1)
+ fun_l8_n700(x)
+ else
+ fun_l8_n688(x)
+ end
+end
+
+def fun_l7_n907(x)
+ if (x < 1)
+ fun_l8_n202(x)
+ else
+ fun_l8_n668(x)
+ end
+end
+
+def fun_l7_n908(x)
+ if (x < 1)
+ fun_l8_n514(x)
+ else
+ fun_l8_n306(x)
+ end
+end
+
+def fun_l7_n909(x)
+ if (x < 1)
+ fun_l8_n592(x)
+ else
+ fun_l8_n43(x)
+ end
+end
+
+def fun_l7_n910(x)
+ if (x < 1)
+ fun_l8_n743(x)
+ else
+ fun_l8_n406(x)
+ end
+end
+
+def fun_l7_n911(x)
+ if (x < 1)
+ fun_l8_n801(x)
+ else
+ fun_l8_n91(x)
+ end
+end
+
+def fun_l7_n912(x)
+ if (x < 1)
+ fun_l8_n392(x)
+ else
+ fun_l8_n461(x)
+ end
+end
+
+def fun_l7_n913(x)
+ if (x < 1)
+ fun_l8_n175(x)
+ else
+ fun_l8_n578(x)
+ end
+end
+
+def fun_l7_n914(x)
+ if (x < 1)
+ fun_l8_n155(x)
+ else
+ fun_l8_n795(x)
+ end
+end
+
+def fun_l7_n915(x)
+ if (x < 1)
+ fun_l8_n394(x)
+ else
+ fun_l8_n89(x)
+ end
+end
+
+def fun_l7_n916(x)
+ if (x < 1)
+ fun_l8_n59(x)
+ else
+ fun_l8_n345(x)
+ end
+end
+
+def fun_l7_n917(x)
+ if (x < 1)
+ fun_l8_n450(x)
+ else
+ fun_l8_n136(x)
+ end
+end
+
+def fun_l7_n918(x)
+ if (x < 1)
+ fun_l8_n530(x)
+ else
+ fun_l8_n233(x)
+ end
+end
+
+def fun_l7_n919(x)
+ if (x < 1)
+ fun_l8_n632(x)
+ else
+ fun_l8_n631(x)
+ end
+end
+
+def fun_l7_n920(x)
+ if (x < 1)
+ fun_l8_n252(x)
+ else
+ fun_l8_n95(x)
+ end
+end
+
+def fun_l7_n921(x)
+ if (x < 1)
+ fun_l8_n980(x)
+ else
+ fun_l8_n819(x)
+ end
+end
+
+def fun_l7_n922(x)
+ if (x < 1)
+ fun_l8_n866(x)
+ else
+ fun_l8_n652(x)
+ end
+end
+
+def fun_l7_n923(x)
+ if (x < 1)
+ fun_l8_n239(x)
+ else
+ fun_l8_n83(x)
+ end
+end
+
+def fun_l7_n924(x)
+ if (x < 1)
+ fun_l8_n162(x)
+ else
+ fun_l8_n193(x)
+ end
+end
+
+def fun_l7_n925(x)
+ if (x < 1)
+ fun_l8_n78(x)
+ else
+ fun_l8_n546(x)
+ end
+end
+
+def fun_l7_n926(x)
+ if (x < 1)
+ fun_l8_n102(x)
+ else
+ fun_l8_n847(x)
+ end
+end
+
+def fun_l7_n927(x)
+ if (x < 1)
+ fun_l8_n84(x)
+ else
+ fun_l8_n257(x)
+ end
+end
+
+def fun_l7_n928(x)
+ if (x < 1)
+ fun_l8_n195(x)
+ else
+ fun_l8_n200(x)
+ end
+end
+
+def fun_l7_n929(x)
+ if (x < 1)
+ fun_l8_n245(x)
+ else
+ fun_l8_n926(x)
+ end
+end
+
+def fun_l7_n930(x)
+ if (x < 1)
+ fun_l8_n651(x)
+ else
+ fun_l8_n308(x)
+ end
+end
+
+def fun_l7_n931(x)
+ if (x < 1)
+ fun_l8_n312(x)
+ else
+ fun_l8_n901(x)
+ end
+end
+
+def fun_l7_n932(x)
+ if (x < 1)
+ fun_l8_n221(x)
+ else
+ fun_l8_n775(x)
+ end
+end
+
+def fun_l7_n933(x)
+ if (x < 1)
+ fun_l8_n397(x)
+ else
+ fun_l8_n973(x)
+ end
+end
+
+def fun_l7_n934(x)
+ if (x < 1)
+ fun_l8_n788(x)
+ else
+ fun_l8_n952(x)
+ end
+end
+
+def fun_l7_n935(x)
+ if (x < 1)
+ fun_l8_n965(x)
+ else
+ fun_l8_n861(x)
+ end
+end
+
+def fun_l7_n936(x)
+ if (x < 1)
+ fun_l8_n969(x)
+ else
+ fun_l8_n773(x)
+ end
+end
+
+def fun_l7_n937(x)
+ if (x < 1)
+ fun_l8_n742(x)
+ else
+ fun_l8_n237(x)
+ end
+end
+
+def fun_l7_n938(x)
+ if (x < 1)
+ fun_l8_n369(x)
+ else
+ fun_l8_n444(x)
+ end
+end
+
+def fun_l7_n939(x)
+ if (x < 1)
+ fun_l8_n863(x)
+ else
+ fun_l8_n515(x)
+ end
+end
+
+def fun_l7_n940(x)
+ if (x < 1)
+ fun_l8_n573(x)
+ else
+ fun_l8_n356(x)
+ end
+end
+
+def fun_l7_n941(x)
+ if (x < 1)
+ fun_l8_n188(x)
+ else
+ fun_l8_n171(x)
+ end
+end
+
+def fun_l7_n942(x)
+ if (x < 1)
+ fun_l8_n483(x)
+ else
+ fun_l8_n556(x)
+ end
+end
+
+def fun_l7_n943(x)
+ if (x < 1)
+ fun_l8_n935(x)
+ else
+ fun_l8_n723(x)
+ end
+end
+
+def fun_l7_n944(x)
+ if (x < 1)
+ fun_l8_n451(x)
+ else
+ fun_l8_n227(x)
+ end
+end
+
+def fun_l7_n945(x)
+ if (x < 1)
+ fun_l8_n651(x)
+ else
+ fun_l8_n891(x)
+ end
+end
+
+def fun_l7_n946(x)
+ if (x < 1)
+ fun_l8_n225(x)
+ else
+ fun_l8_n178(x)
+ end
+end
+
+def fun_l7_n947(x)
+ if (x < 1)
+ fun_l8_n704(x)
+ else
+ fun_l8_n456(x)
+ end
+end
+
+def fun_l7_n948(x)
+ if (x < 1)
+ fun_l8_n995(x)
+ else
+ fun_l8_n816(x)
+ end
+end
+
+def fun_l7_n949(x)
+ if (x < 1)
+ fun_l8_n287(x)
+ else
+ fun_l8_n140(x)
+ end
+end
+
+def fun_l7_n950(x)
+ if (x < 1)
+ fun_l8_n302(x)
+ else
+ fun_l8_n582(x)
+ end
+end
+
+def fun_l7_n951(x)
+ if (x < 1)
+ fun_l8_n58(x)
+ else
+ fun_l8_n759(x)
+ end
+end
+
+def fun_l7_n952(x)
+ if (x < 1)
+ fun_l8_n54(x)
+ else
+ fun_l8_n812(x)
+ end
+end
+
+def fun_l7_n953(x)
+ if (x < 1)
+ fun_l8_n263(x)
+ else
+ fun_l8_n801(x)
+ end
+end
+
+def fun_l7_n954(x)
+ if (x < 1)
+ fun_l8_n507(x)
+ else
+ fun_l8_n781(x)
+ end
+end
+
+def fun_l7_n955(x)
+ if (x < 1)
+ fun_l8_n328(x)
+ else
+ fun_l8_n886(x)
+ end
+end
+
+def fun_l7_n956(x)
+ if (x < 1)
+ fun_l8_n653(x)
+ else
+ fun_l8_n847(x)
+ end
+end
+
+def fun_l7_n957(x)
+ if (x < 1)
+ fun_l8_n594(x)
+ else
+ fun_l8_n9(x)
+ end
+end
+
+def fun_l7_n958(x)
+ if (x < 1)
+ fun_l8_n818(x)
+ else
+ fun_l8_n912(x)
+ end
+end
+
+def fun_l7_n959(x)
+ if (x < 1)
+ fun_l8_n941(x)
+ else
+ fun_l8_n394(x)
+ end
+end
+
+def fun_l7_n960(x)
+ if (x < 1)
+ fun_l8_n151(x)
+ else
+ fun_l8_n426(x)
+ end
+end
+
+def fun_l7_n961(x)
+ if (x < 1)
+ fun_l8_n276(x)
+ else
+ fun_l8_n458(x)
+ end
+end
+
+def fun_l7_n962(x)
+ if (x < 1)
+ fun_l8_n310(x)
+ else
+ fun_l8_n472(x)
+ end
+end
+
+def fun_l7_n963(x)
+ if (x < 1)
+ fun_l8_n103(x)
+ else
+ fun_l8_n995(x)
+ end
+end
+
+def fun_l7_n964(x)
+ if (x < 1)
+ fun_l8_n808(x)
+ else
+ fun_l8_n41(x)
+ end
+end
+
+def fun_l7_n965(x)
+ if (x < 1)
+ fun_l8_n840(x)
+ else
+ fun_l8_n143(x)
+ end
+end
+
+def fun_l7_n966(x)
+ if (x < 1)
+ fun_l8_n855(x)
+ else
+ fun_l8_n38(x)
+ end
+end
+
+def fun_l7_n967(x)
+ if (x < 1)
+ fun_l8_n316(x)
+ else
+ fun_l8_n86(x)
+ end
+end
+
+def fun_l7_n968(x)
+ if (x < 1)
+ fun_l8_n856(x)
+ else
+ fun_l8_n182(x)
+ end
+end
+
+def fun_l7_n969(x)
+ if (x < 1)
+ fun_l8_n436(x)
+ else
+ fun_l8_n460(x)
+ end
+end
+
+def fun_l7_n970(x)
+ if (x < 1)
+ fun_l8_n187(x)
+ else
+ fun_l8_n90(x)
+ end
+end
+
+def fun_l7_n971(x)
+ if (x < 1)
+ fun_l8_n689(x)
+ else
+ fun_l8_n921(x)
+ end
+end
+
+def fun_l7_n972(x)
+ if (x < 1)
+ fun_l8_n207(x)
+ else
+ fun_l8_n79(x)
+ end
+end
+
+def fun_l7_n973(x)
+ if (x < 1)
+ fun_l8_n137(x)
+ else
+ fun_l8_n17(x)
+ end
+end
+
+def fun_l7_n974(x)
+ if (x < 1)
+ fun_l8_n813(x)
+ else
+ fun_l8_n944(x)
+ end
+end
+
+def fun_l7_n975(x)
+ if (x < 1)
+ fun_l8_n589(x)
+ else
+ fun_l8_n416(x)
+ end
+end
+
+def fun_l7_n976(x)
+ if (x < 1)
+ fun_l8_n763(x)
+ else
+ fun_l8_n289(x)
+ end
+end
+
+def fun_l7_n977(x)
+ if (x < 1)
+ fun_l8_n118(x)
+ else
+ fun_l8_n998(x)
+ end
+end
+
+def fun_l7_n978(x)
+ if (x < 1)
+ fun_l8_n382(x)
+ else
+ fun_l8_n216(x)
+ end
+end
+
+def fun_l7_n979(x)
+ if (x < 1)
+ fun_l8_n304(x)
+ else
+ fun_l8_n586(x)
+ end
+end
+
+def fun_l7_n980(x)
+ if (x < 1)
+ fun_l8_n693(x)
+ else
+ fun_l8_n118(x)
+ end
+end
+
+def fun_l7_n981(x)
+ if (x < 1)
+ fun_l8_n669(x)
+ else
+ fun_l8_n796(x)
+ end
+end
+
+def fun_l7_n982(x)
+ if (x < 1)
+ fun_l8_n187(x)
+ else
+ fun_l8_n143(x)
+ end
+end
+
+def fun_l7_n983(x)
+ if (x < 1)
+ fun_l8_n848(x)
+ else
+ fun_l8_n172(x)
+ end
+end
+
+def fun_l7_n984(x)
+ if (x < 1)
+ fun_l8_n782(x)
+ else
+ fun_l8_n670(x)
+ end
+end
+
+def fun_l7_n985(x)
+ if (x < 1)
+ fun_l8_n275(x)
+ else
+ fun_l8_n520(x)
+ end
+end
+
+def fun_l7_n986(x)
+ if (x < 1)
+ fun_l8_n841(x)
+ else
+ fun_l8_n446(x)
+ end
+end
+
+def fun_l7_n987(x)
+ if (x < 1)
+ fun_l8_n712(x)
+ else
+ fun_l8_n976(x)
+ end
+end
+
+def fun_l7_n988(x)
+ if (x < 1)
+ fun_l8_n115(x)
+ else
+ fun_l8_n222(x)
+ end
+end
+
+def fun_l7_n989(x)
+ if (x < 1)
+ fun_l8_n23(x)
+ else
+ fun_l8_n665(x)
+ end
+end
+
+def fun_l7_n990(x)
+ if (x < 1)
+ fun_l8_n416(x)
+ else
+ fun_l8_n455(x)
+ end
+end
+
+def fun_l7_n991(x)
+ if (x < 1)
+ fun_l8_n556(x)
+ else
+ fun_l8_n971(x)
+ end
+end
+
+def fun_l7_n992(x)
+ if (x < 1)
+ fun_l8_n726(x)
+ else
+ fun_l8_n312(x)
+ end
+end
+
+def fun_l7_n993(x)
+ if (x < 1)
+ fun_l8_n354(x)
+ else
+ fun_l8_n860(x)
+ end
+end
+
+def fun_l7_n994(x)
+ if (x < 1)
+ fun_l8_n62(x)
+ else
+ fun_l8_n290(x)
+ end
+end
+
+def fun_l7_n995(x)
+ if (x < 1)
+ fun_l8_n695(x)
+ else
+ fun_l8_n881(x)
+ end
+end
+
+def fun_l7_n996(x)
+ if (x < 1)
+ fun_l8_n938(x)
+ else
+ fun_l8_n566(x)
+ end
+end
+
+def fun_l7_n997(x)
+ if (x < 1)
+ fun_l8_n379(x)
+ else
+ fun_l8_n731(x)
+ end
+end
+
+def fun_l7_n998(x)
+ if (x < 1)
+ fun_l8_n320(x)
+ else
+ fun_l8_n339(x)
+ end
+end
+
+def fun_l7_n999(x)
+ if (x < 1)
+ fun_l8_n219(x)
+ else
+ fun_l8_n320(x)
+ end
+end
+
+def fun_l8_n0(x)
+ if (x < 1)
+ fun_l9_n590(x)
+ else
+ fun_l9_n825(x)
+ end
+end
+
+def fun_l8_n1(x)
+ if (x < 1)
+ fun_l9_n301(x)
+ else
+ fun_l9_n457(x)
+ end
+end
+
+def fun_l8_n2(x)
+ if (x < 1)
+ fun_l9_n637(x)
+ else
+ fun_l9_n909(x)
+ end
+end
+
+def fun_l8_n3(x)
+ if (x < 1)
+ fun_l9_n485(x)
+ else
+ fun_l9_n603(x)
+ end
+end
+
+def fun_l8_n4(x)
+ if (x < 1)
+ fun_l9_n465(x)
+ else
+ fun_l9_n39(x)
+ end
+end
+
+def fun_l8_n5(x)
+ if (x < 1)
+ fun_l9_n861(x)
+ else
+ fun_l9_n153(x)
+ end
+end
+
+def fun_l8_n6(x)
+ if (x < 1)
+ fun_l9_n130(x)
+ else
+ fun_l9_n401(x)
+ end
+end
+
+def fun_l8_n7(x)
+ if (x < 1)
+ fun_l9_n726(x)
+ else
+ fun_l9_n248(x)
+ end
+end
+
+def fun_l8_n8(x)
+ if (x < 1)
+ fun_l9_n607(x)
+ else
+ fun_l9_n681(x)
+ end
+end
+
+def fun_l8_n9(x)
+ if (x < 1)
+ fun_l9_n862(x)
+ else
+ fun_l9_n8(x)
+ end
+end
+
+def fun_l8_n10(x)
+ if (x < 1)
+ fun_l9_n607(x)
+ else
+ fun_l9_n373(x)
+ end
+end
+
+def fun_l8_n11(x)
+ if (x < 1)
+ fun_l9_n692(x)
+ else
+ fun_l9_n31(x)
+ end
+end
+
+def fun_l8_n12(x)
+ if (x < 1)
+ fun_l9_n412(x)
+ else
+ fun_l9_n576(x)
+ end
+end
+
+def fun_l8_n13(x)
+ if (x < 1)
+ fun_l9_n582(x)
+ else
+ fun_l9_n281(x)
+ end
+end
+
+def fun_l8_n14(x)
+ if (x < 1)
+ fun_l9_n986(x)
+ else
+ fun_l9_n99(x)
+ end
+end
+
+def fun_l8_n15(x)
+ if (x < 1)
+ fun_l9_n807(x)
+ else
+ fun_l9_n807(x)
+ end
+end
+
+def fun_l8_n16(x)
+ if (x < 1)
+ fun_l9_n635(x)
+ else
+ fun_l9_n51(x)
+ end
+end
+
+def fun_l8_n17(x)
+ if (x < 1)
+ fun_l9_n193(x)
+ else
+ fun_l9_n673(x)
+ end
+end
+
+def fun_l8_n18(x)
+ if (x < 1)
+ fun_l9_n897(x)
+ else
+ fun_l9_n881(x)
+ end
+end
+
+def fun_l8_n19(x)
+ if (x < 1)
+ fun_l9_n288(x)
+ else
+ fun_l9_n337(x)
+ end
+end
+
+def fun_l8_n20(x)
+ if (x < 1)
+ fun_l9_n754(x)
+ else
+ fun_l9_n581(x)
+ end
+end
+
+def fun_l8_n21(x)
+ if (x < 1)
+ fun_l9_n265(x)
+ else
+ fun_l9_n205(x)
+ end
+end
+
+def fun_l8_n22(x)
+ if (x < 1)
+ fun_l9_n784(x)
+ else
+ fun_l9_n428(x)
+ end
+end
+
+def fun_l8_n23(x)
+ if (x < 1)
+ fun_l9_n821(x)
+ else
+ fun_l9_n930(x)
+ end
+end
+
+def fun_l8_n24(x)
+ if (x < 1)
+ fun_l9_n237(x)
+ else
+ fun_l9_n681(x)
+ end
+end
+
+def fun_l8_n25(x)
+ if (x < 1)
+ fun_l9_n32(x)
+ else
+ fun_l9_n405(x)
+ end
+end
+
+def fun_l8_n26(x)
+ if (x < 1)
+ fun_l9_n370(x)
+ else
+ fun_l9_n802(x)
+ end
+end
+
+def fun_l8_n27(x)
+ if (x < 1)
+ fun_l9_n4(x)
+ else
+ fun_l9_n288(x)
+ end
+end
+
+def fun_l8_n28(x)
+ if (x < 1)
+ fun_l9_n9(x)
+ else
+ fun_l9_n180(x)
+ end
+end
+
+def fun_l8_n29(x)
+ if (x < 1)
+ fun_l9_n585(x)
+ else
+ fun_l9_n396(x)
+ end
+end
+
+def fun_l8_n30(x)
+ if (x < 1)
+ fun_l9_n954(x)
+ else
+ fun_l9_n603(x)
+ end
+end
+
+def fun_l8_n31(x)
+ if (x < 1)
+ fun_l9_n808(x)
+ else
+ fun_l9_n770(x)
+ end
+end
+
+def fun_l8_n32(x)
+ if (x < 1)
+ fun_l9_n442(x)
+ else
+ fun_l9_n243(x)
+ end
+end
+
+def fun_l8_n33(x)
+ if (x < 1)
+ fun_l9_n139(x)
+ else
+ fun_l9_n93(x)
+ end
+end
+
+def fun_l8_n34(x)
+ if (x < 1)
+ fun_l9_n270(x)
+ else
+ fun_l9_n333(x)
+ end
+end
+
+def fun_l8_n35(x)
+ if (x < 1)
+ fun_l9_n542(x)
+ else
+ fun_l9_n38(x)
+ end
+end
+
+def fun_l8_n36(x)
+ if (x < 1)
+ fun_l9_n892(x)
+ else
+ fun_l9_n517(x)
+ end
+end
+
+def fun_l8_n37(x)
+ if (x < 1)
+ fun_l9_n599(x)
+ else
+ fun_l9_n692(x)
+ end
+end
+
+def fun_l8_n38(x)
+ if (x < 1)
+ fun_l9_n0(x)
+ else
+ fun_l9_n879(x)
+ end
+end
+
+def fun_l8_n39(x)
+ if (x < 1)
+ fun_l9_n835(x)
+ else
+ fun_l9_n134(x)
+ end
+end
+
+def fun_l8_n40(x)
+ if (x < 1)
+ fun_l9_n151(x)
+ else
+ fun_l9_n546(x)
+ end
+end
+
+def fun_l8_n41(x)
+ if (x < 1)
+ fun_l9_n214(x)
+ else
+ fun_l9_n652(x)
+ end
+end
+
+def fun_l8_n42(x)
+ if (x < 1)
+ fun_l9_n239(x)
+ else
+ fun_l9_n123(x)
+ end
+end
+
+def fun_l8_n43(x)
+ if (x < 1)
+ fun_l9_n763(x)
+ else
+ fun_l9_n953(x)
+ end
+end
+
+def fun_l8_n44(x)
+ if (x < 1)
+ fun_l9_n449(x)
+ else
+ fun_l9_n343(x)
+ end
+end
+
+def fun_l8_n45(x)
+ if (x < 1)
+ fun_l9_n727(x)
+ else
+ fun_l9_n47(x)
+ end
+end
+
+def fun_l8_n46(x)
+ if (x < 1)
+ fun_l9_n684(x)
+ else
+ fun_l9_n711(x)
+ end
+end
+
+def fun_l8_n47(x)
+ if (x < 1)
+ fun_l9_n895(x)
+ else
+ fun_l9_n864(x)
+ end
+end
+
+def fun_l8_n48(x)
+ if (x < 1)
+ fun_l9_n544(x)
+ else
+ fun_l9_n358(x)
+ end
+end
+
+def fun_l8_n49(x)
+ if (x < 1)
+ fun_l9_n829(x)
+ else
+ fun_l9_n411(x)
+ end
+end
+
+def fun_l8_n50(x)
+ if (x < 1)
+ fun_l9_n673(x)
+ else
+ fun_l9_n640(x)
+ end
+end
+
+def fun_l8_n51(x)
+ if (x < 1)
+ fun_l9_n9(x)
+ else
+ fun_l9_n690(x)
+ end
+end
+
+def fun_l8_n52(x)
+ if (x < 1)
+ fun_l9_n293(x)
+ else
+ fun_l9_n889(x)
+ end
+end
+
+def fun_l8_n53(x)
+ if (x < 1)
+ fun_l9_n141(x)
+ else
+ fun_l9_n554(x)
+ end
+end
+
+def fun_l8_n54(x)
+ if (x < 1)
+ fun_l9_n982(x)
+ else
+ fun_l9_n955(x)
+ end
+end
+
+def fun_l8_n55(x)
+ if (x < 1)
+ fun_l9_n382(x)
+ else
+ fun_l9_n897(x)
+ end
+end
+
+def fun_l8_n56(x)
+ if (x < 1)
+ fun_l9_n332(x)
+ else
+ fun_l9_n550(x)
+ end
+end
+
+def fun_l8_n57(x)
+ if (x < 1)
+ fun_l9_n46(x)
+ else
+ fun_l9_n569(x)
+ end
+end
+
+def fun_l8_n58(x)
+ if (x < 1)
+ fun_l9_n556(x)
+ else
+ fun_l9_n0(x)
+ end
+end
+
+def fun_l8_n59(x)
+ if (x < 1)
+ fun_l9_n931(x)
+ else
+ fun_l9_n995(x)
+ end
+end
+
+def fun_l8_n60(x)
+ if (x < 1)
+ fun_l9_n470(x)
+ else
+ fun_l9_n679(x)
+ end
+end
+
+def fun_l8_n61(x)
+ if (x < 1)
+ fun_l9_n269(x)
+ else
+ fun_l9_n742(x)
+ end
+end
+
+def fun_l8_n62(x)
+ if (x < 1)
+ fun_l9_n542(x)
+ else
+ fun_l9_n556(x)
+ end
+end
+
+def fun_l8_n63(x)
+ if (x < 1)
+ fun_l9_n713(x)
+ else
+ fun_l9_n249(x)
+ end
+end
+
+def fun_l8_n64(x)
+ if (x < 1)
+ fun_l9_n842(x)
+ else
+ fun_l9_n566(x)
+ end
+end
+
+def fun_l8_n65(x)
+ if (x < 1)
+ fun_l9_n708(x)
+ else
+ fun_l9_n3(x)
+ end
+end
+
+def fun_l8_n66(x)
+ if (x < 1)
+ fun_l9_n845(x)
+ else
+ fun_l9_n926(x)
+ end
+end
+
+def fun_l8_n67(x)
+ if (x < 1)
+ fun_l9_n823(x)
+ else
+ fun_l9_n326(x)
+ end
+end
+
+def fun_l8_n68(x)
+ if (x < 1)
+ fun_l9_n457(x)
+ else
+ fun_l9_n888(x)
+ end
+end
+
+def fun_l8_n69(x)
+ if (x < 1)
+ fun_l9_n454(x)
+ else
+ fun_l9_n601(x)
+ end
+end
+
+def fun_l8_n70(x)
+ if (x < 1)
+ fun_l9_n636(x)
+ else
+ fun_l9_n482(x)
+ end
+end
+
+def fun_l8_n71(x)
+ if (x < 1)
+ fun_l9_n778(x)
+ else
+ fun_l9_n678(x)
+ end
+end
+
+def fun_l8_n72(x)
+ if (x < 1)
+ fun_l9_n715(x)
+ else
+ fun_l9_n851(x)
+ end
+end
+
+def fun_l8_n73(x)
+ if (x < 1)
+ fun_l9_n330(x)
+ else
+ fun_l9_n84(x)
+ end
+end
+
+def fun_l8_n74(x)
+ if (x < 1)
+ fun_l9_n524(x)
+ else
+ fun_l9_n109(x)
+ end
+end
+
+def fun_l8_n75(x)
+ if (x < 1)
+ fun_l9_n610(x)
+ else
+ fun_l9_n723(x)
+ end
+end
+
+def fun_l8_n76(x)
+ if (x < 1)
+ fun_l9_n964(x)
+ else
+ fun_l9_n893(x)
+ end
+end
+
+def fun_l8_n77(x)
+ if (x < 1)
+ fun_l9_n653(x)
+ else
+ fun_l9_n451(x)
+ end
+end
+
+def fun_l8_n78(x)
+ if (x < 1)
+ fun_l9_n582(x)
+ else
+ fun_l9_n29(x)
+ end
+end
+
+def fun_l8_n79(x)
+ if (x < 1)
+ fun_l9_n219(x)
+ else
+ fun_l9_n25(x)
+ end
+end
+
+def fun_l8_n80(x)
+ if (x < 1)
+ fun_l9_n471(x)
+ else
+ fun_l9_n217(x)
+ end
+end
+
+def fun_l8_n81(x)
+ if (x < 1)
+ fun_l9_n339(x)
+ else
+ fun_l9_n365(x)
+ end
+end
+
+def fun_l8_n82(x)
+ if (x < 1)
+ fun_l9_n808(x)
+ else
+ fun_l9_n501(x)
+ end
+end
+
+def fun_l8_n83(x)
+ if (x < 1)
+ fun_l9_n23(x)
+ else
+ fun_l9_n252(x)
+ end
+end
+
+def fun_l8_n84(x)
+ if (x < 1)
+ fun_l9_n628(x)
+ else
+ fun_l9_n514(x)
+ end
+end
+
+def fun_l8_n85(x)
+ if (x < 1)
+ fun_l9_n22(x)
+ else
+ fun_l9_n465(x)
+ end
+end
+
+def fun_l8_n86(x)
+ if (x < 1)
+ fun_l9_n553(x)
+ else
+ fun_l9_n788(x)
+ end
+end
+
+def fun_l8_n87(x)
+ if (x < 1)
+ fun_l9_n852(x)
+ else
+ fun_l9_n945(x)
+ end
+end
+
+def fun_l8_n88(x)
+ if (x < 1)
+ fun_l9_n886(x)
+ else
+ fun_l9_n438(x)
+ end
+end
+
+def fun_l8_n89(x)
+ if (x < 1)
+ fun_l9_n821(x)
+ else
+ fun_l9_n697(x)
+ end
+end
+
+def fun_l8_n90(x)
+ if (x < 1)
+ fun_l9_n388(x)
+ else
+ fun_l9_n39(x)
+ end
+end
+
+def fun_l8_n91(x)
+ if (x < 1)
+ fun_l9_n135(x)
+ else
+ fun_l9_n736(x)
+ end
+end
+
+def fun_l8_n92(x)
+ if (x < 1)
+ fun_l9_n225(x)
+ else
+ fun_l9_n125(x)
+ end
+end
+
+def fun_l8_n93(x)
+ if (x < 1)
+ fun_l9_n201(x)
+ else
+ fun_l9_n320(x)
+ end
+end
+
+def fun_l8_n94(x)
+ if (x < 1)
+ fun_l9_n30(x)
+ else
+ fun_l9_n938(x)
+ end
+end
+
+def fun_l8_n95(x)
+ if (x < 1)
+ fun_l9_n987(x)
+ else
+ fun_l9_n141(x)
+ end
+end
+
+def fun_l8_n96(x)
+ if (x < 1)
+ fun_l9_n968(x)
+ else
+ fun_l9_n999(x)
+ end
+end
+
+def fun_l8_n97(x)
+ if (x < 1)
+ fun_l9_n852(x)
+ else
+ fun_l9_n927(x)
+ end
+end
+
+def fun_l8_n98(x)
+ if (x < 1)
+ fun_l9_n720(x)
+ else
+ fun_l9_n717(x)
+ end
+end
+
+def fun_l8_n99(x)
+ if (x < 1)
+ fun_l9_n907(x)
+ else
+ fun_l9_n8(x)
+ end
+end
+
+def fun_l8_n100(x)
+ if (x < 1)
+ fun_l9_n973(x)
+ else
+ fun_l9_n379(x)
+ end
+end
+
+def fun_l8_n101(x)
+ if (x < 1)
+ fun_l9_n370(x)
+ else
+ fun_l9_n530(x)
+ end
+end
+
+def fun_l8_n102(x)
+ if (x < 1)
+ fun_l9_n411(x)
+ else
+ fun_l9_n560(x)
+ end
+end
+
+def fun_l8_n103(x)
+ if (x < 1)
+ fun_l9_n54(x)
+ else
+ fun_l9_n813(x)
+ end
+end
+
+def fun_l8_n104(x)
+ if (x < 1)
+ fun_l9_n217(x)
+ else
+ fun_l9_n455(x)
+ end
+end
+
+def fun_l8_n105(x)
+ if (x < 1)
+ fun_l9_n667(x)
+ else
+ fun_l9_n92(x)
+ end
+end
+
+def fun_l8_n106(x)
+ if (x < 1)
+ fun_l9_n933(x)
+ else
+ fun_l9_n727(x)
+ end
+end
+
+def fun_l8_n107(x)
+ if (x < 1)
+ fun_l9_n578(x)
+ else
+ fun_l9_n350(x)
+ end
+end
+
+def fun_l8_n108(x)
+ if (x < 1)
+ fun_l9_n75(x)
+ else
+ fun_l9_n439(x)
+ end
+end
+
+def fun_l8_n109(x)
+ if (x < 1)
+ fun_l9_n21(x)
+ else
+ fun_l9_n112(x)
+ end
+end
+
+def fun_l8_n110(x)
+ if (x < 1)
+ fun_l9_n57(x)
+ else
+ fun_l9_n553(x)
+ end
+end
+
+def fun_l8_n111(x)
+ if (x < 1)
+ fun_l9_n347(x)
+ else
+ fun_l9_n285(x)
+ end
+end
+
+def fun_l8_n112(x)
+ if (x < 1)
+ fun_l9_n837(x)
+ else
+ fun_l9_n793(x)
+ end
+end
+
+def fun_l8_n113(x)
+ if (x < 1)
+ fun_l9_n517(x)
+ else
+ fun_l9_n668(x)
+ end
+end
+
+def fun_l8_n114(x)
+ if (x < 1)
+ fun_l9_n486(x)
+ else
+ fun_l9_n872(x)
+ end
+end
+
+def fun_l8_n115(x)
+ if (x < 1)
+ fun_l9_n454(x)
+ else
+ fun_l9_n507(x)
+ end
+end
+
+def fun_l8_n116(x)
+ if (x < 1)
+ fun_l9_n110(x)
+ else
+ fun_l9_n263(x)
+ end
+end
+
+def fun_l8_n117(x)
+ if (x < 1)
+ fun_l9_n878(x)
+ else
+ fun_l9_n21(x)
+ end
+end
+
+def fun_l8_n118(x)
+ if (x < 1)
+ fun_l9_n564(x)
+ else
+ fun_l9_n409(x)
+ end
+end
+
+def fun_l8_n119(x)
+ if (x < 1)
+ fun_l9_n511(x)
+ else
+ fun_l9_n800(x)
+ end
+end
+
+def fun_l8_n120(x)
+ if (x < 1)
+ fun_l9_n501(x)
+ else
+ fun_l9_n305(x)
+ end
+end
+
+def fun_l8_n121(x)
+ if (x < 1)
+ fun_l9_n630(x)
+ else
+ fun_l9_n319(x)
+ end
+end
+
+def fun_l8_n122(x)
+ if (x < 1)
+ fun_l9_n271(x)
+ else
+ fun_l9_n639(x)
+ end
+end
+
+def fun_l8_n123(x)
+ if (x < 1)
+ fun_l9_n812(x)
+ else
+ fun_l9_n735(x)
+ end
+end
+
+def fun_l8_n124(x)
+ if (x < 1)
+ fun_l9_n828(x)
+ else
+ fun_l9_n203(x)
+ end
+end
+
+def fun_l8_n125(x)
+ if (x < 1)
+ fun_l9_n228(x)
+ else
+ fun_l9_n536(x)
+ end
+end
+
+def fun_l8_n126(x)
+ if (x < 1)
+ fun_l9_n426(x)
+ else
+ fun_l9_n325(x)
+ end
+end
+
+def fun_l8_n127(x)
+ if (x < 1)
+ fun_l9_n19(x)
+ else
+ fun_l9_n324(x)
+ end
+end
+
+def fun_l8_n128(x)
+ if (x < 1)
+ fun_l9_n419(x)
+ else
+ fun_l9_n425(x)
+ end
+end
+
+def fun_l8_n129(x)
+ if (x < 1)
+ fun_l9_n384(x)
+ else
+ fun_l9_n550(x)
+ end
+end
+
+def fun_l8_n130(x)
+ if (x < 1)
+ fun_l9_n956(x)
+ else
+ fun_l9_n270(x)
+ end
+end
+
+def fun_l8_n131(x)
+ if (x < 1)
+ fun_l9_n20(x)
+ else
+ fun_l9_n949(x)
+ end
+end
+
+def fun_l8_n132(x)
+ if (x < 1)
+ fun_l9_n317(x)
+ else
+ fun_l9_n909(x)
+ end
+end
+
+def fun_l8_n133(x)
+ if (x < 1)
+ fun_l9_n131(x)
+ else
+ fun_l9_n108(x)
+ end
+end
+
+def fun_l8_n134(x)
+ if (x < 1)
+ fun_l9_n648(x)
+ else
+ fun_l9_n473(x)
+ end
+end
+
+def fun_l8_n135(x)
+ if (x < 1)
+ fun_l9_n837(x)
+ else
+ fun_l9_n89(x)
+ end
+end
+
+def fun_l8_n136(x)
+ if (x < 1)
+ fun_l9_n637(x)
+ else
+ fun_l9_n394(x)
+ end
+end
+
+def fun_l8_n137(x)
+ if (x < 1)
+ fun_l9_n608(x)
+ else
+ fun_l9_n283(x)
+ end
+end
+
+def fun_l8_n138(x)
+ if (x < 1)
+ fun_l9_n728(x)
+ else
+ fun_l9_n586(x)
+ end
+end
+
+def fun_l8_n139(x)
+ if (x < 1)
+ fun_l9_n689(x)
+ else
+ fun_l9_n700(x)
+ end
+end
+
+def fun_l8_n140(x)
+ if (x < 1)
+ fun_l9_n532(x)
+ else
+ fun_l9_n98(x)
+ end
+end
+
+def fun_l8_n141(x)
+ if (x < 1)
+ fun_l9_n696(x)
+ else
+ fun_l9_n951(x)
+ end
+end
+
+def fun_l8_n142(x)
+ if (x < 1)
+ fun_l9_n28(x)
+ else
+ fun_l9_n714(x)
+ end
+end
+
+def fun_l8_n143(x)
+ if (x < 1)
+ fun_l9_n438(x)
+ else
+ fun_l9_n934(x)
+ end
+end
+
+def fun_l8_n144(x)
+ if (x < 1)
+ fun_l9_n738(x)
+ else
+ fun_l9_n473(x)
+ end
+end
+
+def fun_l8_n145(x)
+ if (x < 1)
+ fun_l9_n201(x)
+ else
+ fun_l9_n634(x)
+ end
+end
+
+def fun_l8_n146(x)
+ if (x < 1)
+ fun_l9_n391(x)
+ else
+ fun_l9_n703(x)
+ end
+end
+
+def fun_l8_n147(x)
+ if (x < 1)
+ fun_l9_n740(x)
+ else
+ fun_l9_n265(x)
+ end
+end
+
+def fun_l8_n148(x)
+ if (x < 1)
+ fun_l9_n303(x)
+ else
+ fun_l9_n162(x)
+ end
+end
+
+def fun_l8_n149(x)
+ if (x < 1)
+ fun_l9_n518(x)
+ else
+ fun_l9_n899(x)
+ end
+end
+
+def fun_l8_n150(x)
+ if (x < 1)
+ fun_l9_n847(x)
+ else
+ fun_l9_n840(x)
+ end
+end
+
+def fun_l8_n151(x)
+ if (x < 1)
+ fun_l9_n567(x)
+ else
+ fun_l9_n29(x)
+ end
+end
+
+def fun_l8_n152(x)
+ if (x < 1)
+ fun_l9_n426(x)
+ else
+ fun_l9_n578(x)
+ end
+end
+
+def fun_l8_n153(x)
+ if (x < 1)
+ fun_l9_n617(x)
+ else
+ fun_l9_n703(x)
+ end
+end
+
+def fun_l8_n154(x)
+ if (x < 1)
+ fun_l9_n673(x)
+ else
+ fun_l9_n663(x)
+ end
+end
+
+def fun_l8_n155(x)
+ if (x < 1)
+ fun_l9_n456(x)
+ else
+ fun_l9_n406(x)
+ end
+end
+
+def fun_l8_n156(x)
+ if (x < 1)
+ fun_l9_n297(x)
+ else
+ fun_l9_n444(x)
+ end
+end
+
+def fun_l8_n157(x)
+ if (x < 1)
+ fun_l9_n300(x)
+ else
+ fun_l9_n179(x)
+ end
+end
+
+def fun_l8_n158(x)
+ if (x < 1)
+ fun_l9_n646(x)
+ else
+ fun_l9_n9(x)
+ end
+end
+
+def fun_l8_n159(x)
+ if (x < 1)
+ fun_l9_n133(x)
+ else
+ fun_l9_n228(x)
+ end
+end
+
+def fun_l8_n160(x)
+ if (x < 1)
+ fun_l9_n814(x)
+ else
+ fun_l9_n775(x)
+ end
+end
+
+def fun_l8_n161(x)
+ if (x < 1)
+ fun_l9_n748(x)
+ else
+ fun_l9_n849(x)
+ end
+end
+
+def fun_l8_n162(x)
+ if (x < 1)
+ fun_l9_n209(x)
+ else
+ fun_l9_n273(x)
+ end
+end
+
+def fun_l8_n163(x)
+ if (x < 1)
+ fun_l9_n116(x)
+ else
+ fun_l9_n669(x)
+ end
+end
+
+def fun_l8_n164(x)
+ if (x < 1)
+ fun_l9_n714(x)
+ else
+ fun_l9_n621(x)
+ end
+end
+
+def fun_l8_n165(x)
+ if (x < 1)
+ fun_l9_n619(x)
+ else
+ fun_l9_n365(x)
+ end
+end
+
+def fun_l8_n166(x)
+ if (x < 1)
+ fun_l9_n756(x)
+ else
+ fun_l9_n745(x)
+ end
+end
+
+def fun_l8_n167(x)
+ if (x < 1)
+ fun_l9_n12(x)
+ else
+ fun_l9_n633(x)
+ end
+end
+
+def fun_l8_n168(x)
+ if (x < 1)
+ fun_l9_n619(x)
+ else
+ fun_l9_n31(x)
+ end
+end
+
+def fun_l8_n169(x)
+ if (x < 1)
+ fun_l9_n685(x)
+ else
+ fun_l9_n107(x)
+ end
+end
+
+def fun_l8_n170(x)
+ if (x < 1)
+ fun_l9_n636(x)
+ else
+ fun_l9_n280(x)
+ end
+end
+
+def fun_l8_n171(x)
+ if (x < 1)
+ fun_l9_n254(x)
+ else
+ fun_l9_n742(x)
+ end
+end
+
+def fun_l8_n172(x)
+ if (x < 1)
+ fun_l9_n829(x)
+ else
+ fun_l9_n632(x)
+ end
+end
+
+def fun_l8_n173(x)
+ if (x < 1)
+ fun_l9_n341(x)
+ else
+ fun_l9_n186(x)
+ end
+end
+
+def fun_l8_n174(x)
+ if (x < 1)
+ fun_l9_n903(x)
+ else
+ fun_l9_n93(x)
+ end
+end
+
+def fun_l8_n175(x)
+ if (x < 1)
+ fun_l9_n416(x)
+ else
+ fun_l9_n318(x)
+ end
+end
+
+def fun_l8_n176(x)
+ if (x < 1)
+ fun_l9_n893(x)
+ else
+ fun_l9_n438(x)
+ end
+end
+
+def fun_l8_n177(x)
+ if (x < 1)
+ fun_l9_n551(x)
+ else
+ fun_l9_n312(x)
+ end
+end
+
+def fun_l8_n178(x)
+ if (x < 1)
+ fun_l9_n582(x)
+ else
+ fun_l9_n926(x)
+ end
+end
+
+def fun_l8_n179(x)
+ if (x < 1)
+ fun_l9_n547(x)
+ else
+ fun_l9_n804(x)
+ end
+end
+
+def fun_l8_n180(x)
+ if (x < 1)
+ fun_l9_n589(x)
+ else
+ fun_l9_n246(x)
+ end
+end
+
+def fun_l8_n181(x)
+ if (x < 1)
+ fun_l9_n67(x)
+ else
+ fun_l9_n345(x)
+ end
+end
+
+def fun_l8_n182(x)
+ if (x < 1)
+ fun_l9_n958(x)
+ else
+ fun_l9_n923(x)
+ end
+end
+
+def fun_l8_n183(x)
+ if (x < 1)
+ fun_l9_n418(x)
+ else
+ fun_l9_n532(x)
+ end
+end
+
+def fun_l8_n184(x)
+ if (x < 1)
+ fun_l9_n372(x)
+ else
+ fun_l9_n808(x)
+ end
+end
+
+def fun_l8_n185(x)
+ if (x < 1)
+ fun_l9_n849(x)
+ else
+ fun_l9_n755(x)
+ end
+end
+
+def fun_l8_n186(x)
+ if (x < 1)
+ fun_l9_n544(x)
+ else
+ fun_l9_n73(x)
+ end
+end
+
+def fun_l8_n187(x)
+ if (x < 1)
+ fun_l9_n729(x)
+ else
+ fun_l9_n295(x)
+ end
+end
+
+def fun_l8_n188(x)
+ if (x < 1)
+ fun_l9_n782(x)
+ else
+ fun_l9_n117(x)
+ end
+end
+
+def fun_l8_n189(x)
+ if (x < 1)
+ fun_l9_n947(x)
+ else
+ fun_l9_n93(x)
+ end
+end
+
+def fun_l8_n190(x)
+ if (x < 1)
+ fun_l9_n989(x)
+ else
+ fun_l9_n444(x)
+ end
+end
+
+def fun_l8_n191(x)
+ if (x < 1)
+ fun_l9_n394(x)
+ else
+ fun_l9_n741(x)
+ end
+end
+
+def fun_l8_n192(x)
+ if (x < 1)
+ fun_l9_n582(x)
+ else
+ fun_l9_n333(x)
+ end
+end
+
+def fun_l8_n193(x)
+ if (x < 1)
+ fun_l9_n73(x)
+ else
+ fun_l9_n227(x)
+ end
+end
+
+def fun_l8_n194(x)
+ if (x < 1)
+ fun_l9_n946(x)
+ else
+ fun_l9_n354(x)
+ end
+end
+
+def fun_l8_n195(x)
+ if (x < 1)
+ fun_l9_n383(x)
+ else
+ fun_l9_n863(x)
+ end
+end
+
+def fun_l8_n196(x)
+ if (x < 1)
+ fun_l9_n441(x)
+ else
+ fun_l9_n947(x)
+ end
+end
+
+def fun_l8_n197(x)
+ if (x < 1)
+ fun_l9_n506(x)
+ else
+ fun_l9_n45(x)
+ end
+end
+
+def fun_l8_n198(x)
+ if (x < 1)
+ fun_l9_n890(x)
+ else
+ fun_l9_n341(x)
+ end
+end
+
+def fun_l8_n199(x)
+ if (x < 1)
+ fun_l9_n75(x)
+ else
+ fun_l9_n56(x)
+ end
+end
+
+def fun_l8_n200(x)
+ if (x < 1)
+ fun_l9_n386(x)
+ else
+ fun_l9_n280(x)
+ end
+end
+
+def fun_l8_n201(x)
+ if (x < 1)
+ fun_l9_n364(x)
+ else
+ fun_l9_n424(x)
+ end
+end
+
+def fun_l8_n202(x)
+ if (x < 1)
+ fun_l9_n923(x)
+ else
+ fun_l9_n326(x)
+ end
+end
+
+def fun_l8_n203(x)
+ if (x < 1)
+ fun_l9_n692(x)
+ else
+ fun_l9_n502(x)
+ end
+end
+
+def fun_l8_n204(x)
+ if (x < 1)
+ fun_l9_n508(x)
+ else
+ fun_l9_n561(x)
+ end
+end
+
+def fun_l8_n205(x)
+ if (x < 1)
+ fun_l9_n496(x)
+ else
+ fun_l9_n949(x)
+ end
+end
+
+def fun_l8_n206(x)
+ if (x < 1)
+ fun_l9_n852(x)
+ else
+ fun_l9_n447(x)
+ end
+end
+
+def fun_l8_n207(x)
+ if (x < 1)
+ fun_l9_n757(x)
+ else
+ fun_l9_n782(x)
+ end
+end
+
+def fun_l8_n208(x)
+ if (x < 1)
+ fun_l9_n505(x)
+ else
+ fun_l9_n32(x)
+ end
+end
+
+def fun_l8_n209(x)
+ if (x < 1)
+ fun_l9_n591(x)
+ else
+ fun_l9_n967(x)
+ end
+end
+
+def fun_l8_n210(x)
+ if (x < 1)
+ fun_l9_n537(x)
+ else
+ fun_l9_n380(x)
+ end
+end
+
+def fun_l8_n211(x)
+ if (x < 1)
+ fun_l9_n19(x)
+ else
+ fun_l9_n362(x)
+ end
+end
+
+def fun_l8_n212(x)
+ if (x < 1)
+ fun_l9_n759(x)
+ else
+ fun_l9_n835(x)
+ end
+end
+
+def fun_l8_n213(x)
+ if (x < 1)
+ fun_l9_n518(x)
+ else
+ fun_l9_n294(x)
+ end
+end
+
+def fun_l8_n214(x)
+ if (x < 1)
+ fun_l9_n921(x)
+ else
+ fun_l9_n687(x)
+ end
+end
+
+def fun_l8_n215(x)
+ if (x < 1)
+ fun_l9_n114(x)
+ else
+ fun_l9_n130(x)
+ end
+end
+
+def fun_l8_n216(x)
+ if (x < 1)
+ fun_l9_n829(x)
+ else
+ fun_l9_n8(x)
+ end
+end
+
+def fun_l8_n217(x)
+ if (x < 1)
+ fun_l9_n875(x)
+ else
+ fun_l9_n392(x)
+ end
+end
+
+def fun_l8_n218(x)
+ if (x < 1)
+ fun_l9_n13(x)
+ else
+ fun_l9_n907(x)
+ end
+end
+
+def fun_l8_n219(x)
+ if (x < 1)
+ fun_l9_n457(x)
+ else
+ fun_l9_n77(x)
+ end
+end
+
+def fun_l8_n220(x)
+ if (x < 1)
+ fun_l9_n404(x)
+ else
+ fun_l9_n12(x)
+ end
+end
+
+def fun_l8_n221(x)
+ if (x < 1)
+ fun_l9_n244(x)
+ else
+ fun_l9_n231(x)
+ end
+end
+
+def fun_l8_n222(x)
+ if (x < 1)
+ fun_l9_n205(x)
+ else
+ fun_l9_n458(x)
+ end
+end
+
+def fun_l8_n223(x)
+ if (x < 1)
+ fun_l9_n570(x)
+ else
+ fun_l9_n44(x)
+ end
+end
+
+def fun_l8_n224(x)
+ if (x < 1)
+ fun_l9_n651(x)
+ else
+ fun_l9_n836(x)
+ end
+end
+
+def fun_l8_n225(x)
+ if (x < 1)
+ fun_l9_n518(x)
+ else
+ fun_l9_n845(x)
+ end
+end
+
+def fun_l8_n226(x)
+ if (x < 1)
+ fun_l9_n92(x)
+ else
+ fun_l9_n637(x)
+ end
+end
+
+def fun_l8_n227(x)
+ if (x < 1)
+ fun_l9_n990(x)
+ else
+ fun_l9_n926(x)
+ end
+end
+
+def fun_l8_n228(x)
+ if (x < 1)
+ fun_l9_n465(x)
+ else
+ fun_l9_n764(x)
+ end
+end
+
+def fun_l8_n229(x)
+ if (x < 1)
+ fun_l9_n7(x)
+ else
+ fun_l9_n981(x)
+ end
+end
+
+def fun_l8_n230(x)
+ if (x < 1)
+ fun_l9_n250(x)
+ else
+ fun_l9_n690(x)
+ end
+end
+
+def fun_l8_n231(x)
+ if (x < 1)
+ fun_l9_n101(x)
+ else
+ fun_l9_n342(x)
+ end
+end
+
+def fun_l8_n232(x)
+ if (x < 1)
+ fun_l9_n659(x)
+ else
+ fun_l9_n216(x)
+ end
+end
+
+def fun_l8_n233(x)
+ if (x < 1)
+ fun_l9_n129(x)
+ else
+ fun_l9_n439(x)
+ end
+end
+
+def fun_l8_n234(x)
+ if (x < 1)
+ fun_l9_n616(x)
+ else
+ fun_l9_n700(x)
+ end
+end
+
+def fun_l8_n235(x)
+ if (x < 1)
+ fun_l9_n850(x)
+ else
+ fun_l9_n254(x)
+ end
+end
+
+def fun_l8_n236(x)
+ if (x < 1)
+ fun_l9_n186(x)
+ else
+ fun_l9_n592(x)
+ end
+end
+
+def fun_l8_n237(x)
+ if (x < 1)
+ fun_l9_n895(x)
+ else
+ fun_l9_n752(x)
+ end
+end
+
+def fun_l8_n238(x)
+ if (x < 1)
+ fun_l9_n496(x)
+ else
+ fun_l9_n784(x)
+ end
+end
+
+def fun_l8_n239(x)
+ if (x < 1)
+ fun_l9_n579(x)
+ else
+ fun_l9_n144(x)
+ end
+end
+
+def fun_l8_n240(x)
+ if (x < 1)
+ fun_l9_n805(x)
+ else
+ fun_l9_n851(x)
+ end
+end
+
+def fun_l8_n241(x)
+ if (x < 1)
+ fun_l9_n756(x)
+ else
+ fun_l9_n332(x)
+ end
+end
+
+def fun_l8_n242(x)
+ if (x < 1)
+ fun_l9_n898(x)
+ else
+ fun_l9_n285(x)
+ end
+end
+
+def fun_l8_n243(x)
+ if (x < 1)
+ fun_l9_n729(x)
+ else
+ fun_l9_n149(x)
+ end
+end
+
+def fun_l8_n244(x)
+ if (x < 1)
+ fun_l9_n881(x)
+ else
+ fun_l9_n356(x)
+ end
+end
+
+def fun_l8_n245(x)
+ if (x < 1)
+ fun_l9_n351(x)
+ else
+ fun_l9_n805(x)
+ end
+end
+
+def fun_l8_n246(x)
+ if (x < 1)
+ fun_l9_n493(x)
+ else
+ fun_l9_n200(x)
+ end
+end
+
+def fun_l8_n247(x)
+ if (x < 1)
+ fun_l9_n706(x)
+ else
+ fun_l9_n917(x)
+ end
+end
+
+def fun_l8_n248(x)
+ if (x < 1)
+ fun_l9_n370(x)
+ else
+ fun_l9_n755(x)
+ end
+end
+
+def fun_l8_n249(x)
+ if (x < 1)
+ fun_l9_n859(x)
+ else
+ fun_l9_n496(x)
+ end
+end
+
+def fun_l8_n250(x)
+ if (x < 1)
+ fun_l9_n443(x)
+ else
+ fun_l9_n113(x)
+ end
+end
+
+def fun_l8_n251(x)
+ if (x < 1)
+ fun_l9_n631(x)
+ else
+ fun_l9_n195(x)
+ end
+end
+
+def fun_l8_n252(x)
+ if (x < 1)
+ fun_l9_n357(x)
+ else
+ fun_l9_n694(x)
+ end
+end
+
+def fun_l8_n253(x)
+ if (x < 1)
+ fun_l9_n387(x)
+ else
+ fun_l9_n820(x)
+ end
+end
+
+def fun_l8_n254(x)
+ if (x < 1)
+ fun_l9_n909(x)
+ else
+ fun_l9_n559(x)
+ end
+end
+
+def fun_l8_n255(x)
+ if (x < 1)
+ fun_l9_n474(x)
+ else
+ fun_l9_n864(x)
+ end
+end
+
+def fun_l8_n256(x)
+ if (x < 1)
+ fun_l9_n914(x)
+ else
+ fun_l9_n672(x)
+ end
+end
+
+def fun_l8_n257(x)
+ if (x < 1)
+ fun_l9_n915(x)
+ else
+ fun_l9_n177(x)
+ end
+end
+
+def fun_l8_n258(x)
+ if (x < 1)
+ fun_l9_n917(x)
+ else
+ fun_l9_n210(x)
+ end
+end
+
+def fun_l8_n259(x)
+ if (x < 1)
+ fun_l9_n851(x)
+ else
+ fun_l9_n342(x)
+ end
+end
+
+def fun_l8_n260(x)
+ if (x < 1)
+ fun_l9_n205(x)
+ else
+ fun_l9_n412(x)
+ end
+end
+
+def fun_l8_n261(x)
+ if (x < 1)
+ fun_l9_n110(x)
+ else
+ fun_l9_n62(x)
+ end
+end
+
+def fun_l8_n262(x)
+ if (x < 1)
+ fun_l9_n706(x)
+ else
+ fun_l9_n903(x)
+ end
+end
+
+def fun_l8_n263(x)
+ if (x < 1)
+ fun_l9_n403(x)
+ else
+ fun_l9_n994(x)
+ end
+end
+
+def fun_l8_n264(x)
+ if (x < 1)
+ fun_l9_n631(x)
+ else
+ fun_l9_n126(x)
+ end
+end
+
+def fun_l8_n265(x)
+ if (x < 1)
+ fun_l9_n216(x)
+ else
+ fun_l9_n573(x)
+ end
+end
+
+def fun_l8_n266(x)
+ if (x < 1)
+ fun_l9_n174(x)
+ else
+ fun_l9_n495(x)
+ end
+end
+
+def fun_l8_n267(x)
+ if (x < 1)
+ fun_l9_n802(x)
+ else
+ fun_l9_n881(x)
+ end
+end
+
+def fun_l8_n268(x)
+ if (x < 1)
+ fun_l9_n148(x)
+ else
+ fun_l9_n399(x)
+ end
+end
+
+def fun_l8_n269(x)
+ if (x < 1)
+ fun_l9_n675(x)
+ else
+ fun_l9_n596(x)
+ end
+end
+
+def fun_l8_n270(x)
+ if (x < 1)
+ fun_l9_n306(x)
+ else
+ fun_l9_n413(x)
+ end
+end
+
+def fun_l8_n271(x)
+ if (x < 1)
+ fun_l9_n205(x)
+ else
+ fun_l9_n569(x)
+ end
+end
+
+def fun_l8_n272(x)
+ if (x < 1)
+ fun_l9_n6(x)
+ else
+ fun_l9_n531(x)
+ end
+end
+
+def fun_l8_n273(x)
+ if (x < 1)
+ fun_l9_n516(x)
+ else
+ fun_l9_n172(x)
+ end
+end
+
+def fun_l8_n274(x)
+ if (x < 1)
+ fun_l9_n641(x)
+ else
+ fun_l9_n85(x)
+ end
+end
+
+def fun_l8_n275(x)
+ if (x < 1)
+ fun_l9_n258(x)
+ else
+ fun_l9_n773(x)
+ end
+end
+
+def fun_l8_n276(x)
+ if (x < 1)
+ fun_l9_n233(x)
+ else
+ fun_l9_n222(x)
+ end
+end
+
+def fun_l8_n277(x)
+ if (x < 1)
+ fun_l9_n615(x)
+ else
+ fun_l9_n598(x)
+ end
+end
+
+def fun_l8_n278(x)
+ if (x < 1)
+ fun_l9_n126(x)
+ else
+ fun_l9_n270(x)
+ end
+end
+
+def fun_l8_n279(x)
+ if (x < 1)
+ fun_l9_n186(x)
+ else
+ fun_l9_n78(x)
+ end
+end
+
+def fun_l8_n280(x)
+ if (x < 1)
+ fun_l9_n731(x)
+ else
+ fun_l9_n114(x)
+ end
+end
+
+def fun_l8_n281(x)
+ if (x < 1)
+ fun_l9_n513(x)
+ else
+ fun_l9_n69(x)
+ end
+end
+
+def fun_l8_n282(x)
+ if (x < 1)
+ fun_l9_n208(x)
+ else
+ fun_l9_n466(x)
+ end
+end
+
+def fun_l8_n283(x)
+ if (x < 1)
+ fun_l9_n958(x)
+ else
+ fun_l9_n86(x)
+ end
+end
+
+def fun_l8_n284(x)
+ if (x < 1)
+ fun_l9_n663(x)
+ else
+ fun_l9_n619(x)
+ end
+end
+
+def fun_l8_n285(x)
+ if (x < 1)
+ fun_l9_n698(x)
+ else
+ fun_l9_n97(x)
+ end
+end
+
+def fun_l8_n286(x)
+ if (x < 1)
+ fun_l9_n544(x)
+ else
+ fun_l9_n791(x)
+ end
+end
+
+def fun_l8_n287(x)
+ if (x < 1)
+ fun_l9_n51(x)
+ else
+ fun_l9_n415(x)
+ end
+end
+
+def fun_l8_n288(x)
+ if (x < 1)
+ fun_l9_n942(x)
+ else
+ fun_l9_n11(x)
+ end
+end
+
+def fun_l8_n289(x)
+ if (x < 1)
+ fun_l9_n386(x)
+ else
+ fun_l9_n507(x)
+ end
+end
+
+def fun_l8_n290(x)
+ if (x < 1)
+ fun_l9_n983(x)
+ else
+ fun_l9_n81(x)
+ end
+end
+
+def fun_l8_n291(x)
+ if (x < 1)
+ fun_l9_n403(x)
+ else
+ fun_l9_n628(x)
+ end
+end
+
+def fun_l8_n292(x)
+ if (x < 1)
+ fun_l9_n479(x)
+ else
+ fun_l9_n379(x)
+ end
+end
+
+def fun_l8_n293(x)
+ if (x < 1)
+ fun_l9_n284(x)
+ else
+ fun_l9_n109(x)
+ end
+end
+
+def fun_l8_n294(x)
+ if (x < 1)
+ fun_l9_n29(x)
+ else
+ fun_l9_n802(x)
+ end
+end
+
+def fun_l8_n295(x)
+ if (x < 1)
+ fun_l9_n579(x)
+ else
+ fun_l9_n371(x)
+ end
+end
+
+def fun_l8_n296(x)
+ if (x < 1)
+ fun_l9_n96(x)
+ else
+ fun_l9_n632(x)
+ end
+end
+
+def fun_l8_n297(x)
+ if (x < 1)
+ fun_l9_n442(x)
+ else
+ fun_l9_n396(x)
+ end
+end
+
+def fun_l8_n298(x)
+ if (x < 1)
+ fun_l9_n902(x)
+ else
+ fun_l9_n804(x)
+ end
+end
+
+def fun_l8_n299(x)
+ if (x < 1)
+ fun_l9_n561(x)
+ else
+ fun_l9_n952(x)
+ end
+end
+
+def fun_l8_n300(x)
+ if (x < 1)
+ fun_l9_n757(x)
+ else
+ fun_l9_n819(x)
+ end
+end
+
+def fun_l8_n301(x)
+ if (x < 1)
+ fun_l9_n97(x)
+ else
+ fun_l9_n892(x)
+ end
+end
+
+def fun_l8_n302(x)
+ if (x < 1)
+ fun_l9_n67(x)
+ else
+ fun_l9_n765(x)
+ end
+end
+
+def fun_l8_n303(x)
+ if (x < 1)
+ fun_l9_n166(x)
+ else
+ fun_l9_n769(x)
+ end
+end
+
+def fun_l8_n304(x)
+ if (x < 1)
+ fun_l9_n592(x)
+ else
+ fun_l9_n423(x)
+ end
+end
+
+def fun_l8_n305(x)
+ if (x < 1)
+ fun_l9_n354(x)
+ else
+ fun_l9_n953(x)
+ end
+end
+
+def fun_l8_n306(x)
+ if (x < 1)
+ fun_l9_n857(x)
+ else
+ fun_l9_n18(x)
+ end
+end
+
+def fun_l8_n307(x)
+ if (x < 1)
+ fun_l9_n445(x)
+ else
+ fun_l9_n796(x)
+ end
+end
+
+def fun_l8_n308(x)
+ if (x < 1)
+ fun_l9_n293(x)
+ else
+ fun_l9_n304(x)
+ end
+end
+
+def fun_l8_n309(x)
+ if (x < 1)
+ fun_l9_n859(x)
+ else
+ fun_l9_n282(x)
+ end
+end
+
+def fun_l8_n310(x)
+ if (x < 1)
+ fun_l9_n133(x)
+ else
+ fun_l9_n90(x)
+ end
+end
+
+def fun_l8_n311(x)
+ if (x < 1)
+ fun_l9_n997(x)
+ else
+ fun_l9_n201(x)
+ end
+end
+
+def fun_l8_n312(x)
+ if (x < 1)
+ fun_l9_n140(x)
+ else
+ fun_l9_n772(x)
+ end
+end
+
+def fun_l8_n313(x)
+ if (x < 1)
+ fun_l9_n761(x)
+ else
+ fun_l9_n980(x)
+ end
+end
+
+def fun_l8_n314(x)
+ if (x < 1)
+ fun_l9_n357(x)
+ else
+ fun_l9_n552(x)
+ end
+end
+
+def fun_l8_n315(x)
+ if (x < 1)
+ fun_l9_n312(x)
+ else
+ fun_l9_n412(x)
+ end
+end
+
+def fun_l8_n316(x)
+ if (x < 1)
+ fun_l9_n700(x)
+ else
+ fun_l9_n551(x)
+ end
+end
+
+def fun_l8_n317(x)
+ if (x < 1)
+ fun_l9_n623(x)
+ else
+ fun_l9_n219(x)
+ end
+end
+
+def fun_l8_n318(x)
+ if (x < 1)
+ fun_l9_n613(x)
+ else
+ fun_l9_n959(x)
+ end
+end
+
+def fun_l8_n319(x)
+ if (x < 1)
+ fun_l9_n978(x)
+ else
+ fun_l9_n596(x)
+ end
+end
+
+def fun_l8_n320(x)
+ if (x < 1)
+ fun_l9_n542(x)
+ else
+ fun_l9_n527(x)
+ end
+end
+
+def fun_l8_n321(x)
+ if (x < 1)
+ fun_l9_n877(x)
+ else
+ fun_l9_n108(x)
+ end
+end
+
+def fun_l8_n322(x)
+ if (x < 1)
+ fun_l9_n817(x)
+ else
+ fun_l9_n476(x)
+ end
+end
+
+def fun_l8_n323(x)
+ if (x < 1)
+ fun_l9_n765(x)
+ else
+ fun_l9_n672(x)
+ end
+end
+
+def fun_l8_n324(x)
+ if (x < 1)
+ fun_l9_n863(x)
+ else
+ fun_l9_n605(x)
+ end
+end
+
+def fun_l8_n325(x)
+ if (x < 1)
+ fun_l9_n566(x)
+ else
+ fun_l9_n592(x)
+ end
+end
+
+def fun_l8_n326(x)
+ if (x < 1)
+ fun_l9_n607(x)
+ else
+ fun_l9_n968(x)
+ end
+end
+
+def fun_l8_n327(x)
+ if (x < 1)
+ fun_l9_n36(x)
+ else
+ fun_l9_n380(x)
+ end
+end
+
+def fun_l8_n328(x)
+ if (x < 1)
+ fun_l9_n597(x)
+ else
+ fun_l9_n664(x)
+ end
+end
+
+def fun_l8_n329(x)
+ if (x < 1)
+ fun_l9_n195(x)
+ else
+ fun_l9_n268(x)
+ end
+end
+
+def fun_l8_n330(x)
+ if (x < 1)
+ fun_l9_n419(x)
+ else
+ fun_l9_n715(x)
+ end
+end
+
+def fun_l8_n331(x)
+ if (x < 1)
+ fun_l9_n451(x)
+ else
+ fun_l9_n518(x)
+ end
+end
+
+def fun_l8_n332(x)
+ if (x < 1)
+ fun_l9_n106(x)
+ else
+ fun_l9_n236(x)
+ end
+end
+
+def fun_l8_n333(x)
+ if (x < 1)
+ fun_l9_n611(x)
+ else
+ fun_l9_n825(x)
+ end
+end
+
+def fun_l8_n334(x)
+ if (x < 1)
+ fun_l9_n394(x)
+ else
+ fun_l9_n34(x)
+ end
+end
+
+def fun_l8_n335(x)
+ if (x < 1)
+ fun_l9_n63(x)
+ else
+ fun_l9_n58(x)
+ end
+end
+
+def fun_l8_n336(x)
+ if (x < 1)
+ fun_l9_n475(x)
+ else
+ fun_l9_n455(x)
+ end
+end
+
+def fun_l8_n337(x)
+ if (x < 1)
+ fun_l9_n836(x)
+ else
+ fun_l9_n318(x)
+ end
+end
+
+def fun_l8_n338(x)
+ if (x < 1)
+ fun_l9_n844(x)
+ else
+ fun_l9_n21(x)
+ end
+end
+
+def fun_l8_n339(x)
+ if (x < 1)
+ fun_l9_n628(x)
+ else
+ fun_l9_n721(x)
+ end
+end
+
+def fun_l8_n340(x)
+ if (x < 1)
+ fun_l9_n966(x)
+ else
+ fun_l9_n833(x)
+ end
+end
+
+def fun_l8_n341(x)
+ if (x < 1)
+ fun_l9_n267(x)
+ else
+ fun_l9_n28(x)
+ end
+end
+
+def fun_l8_n342(x)
+ if (x < 1)
+ fun_l9_n204(x)
+ else
+ fun_l9_n838(x)
+ end
+end
+
+def fun_l8_n343(x)
+ if (x < 1)
+ fun_l9_n151(x)
+ else
+ fun_l9_n382(x)
+ end
+end
+
+def fun_l8_n344(x)
+ if (x < 1)
+ fun_l9_n409(x)
+ else
+ fun_l9_n591(x)
+ end
+end
+
+def fun_l8_n345(x)
+ if (x < 1)
+ fun_l9_n680(x)
+ else
+ fun_l9_n912(x)
+ end
+end
+
+def fun_l8_n346(x)
+ if (x < 1)
+ fun_l9_n150(x)
+ else
+ fun_l9_n34(x)
+ end
+end
+
+def fun_l8_n347(x)
+ if (x < 1)
+ fun_l9_n538(x)
+ else
+ fun_l9_n441(x)
+ end
+end
+
+def fun_l8_n348(x)
+ if (x < 1)
+ fun_l9_n707(x)
+ else
+ fun_l9_n199(x)
+ end
+end
+
+def fun_l8_n349(x)
+ if (x < 1)
+ fun_l9_n245(x)
+ else
+ fun_l9_n809(x)
+ end
+end
+
+def fun_l8_n350(x)
+ if (x < 1)
+ fun_l9_n16(x)
+ else
+ fun_l9_n565(x)
+ end
+end
+
+def fun_l8_n351(x)
+ if (x < 1)
+ fun_l9_n857(x)
+ else
+ fun_l9_n37(x)
+ end
+end
+
+def fun_l8_n352(x)
+ if (x < 1)
+ fun_l9_n816(x)
+ else
+ fun_l9_n941(x)
+ end
+end
+
+def fun_l8_n353(x)
+ if (x < 1)
+ fun_l9_n605(x)
+ else
+ fun_l9_n476(x)
+ end
+end
+
+def fun_l8_n354(x)
+ if (x < 1)
+ fun_l9_n641(x)
+ else
+ fun_l9_n319(x)
+ end
+end
+
+def fun_l8_n355(x)
+ if (x < 1)
+ fun_l9_n133(x)
+ else
+ fun_l9_n676(x)
+ end
+end
+
+def fun_l8_n356(x)
+ if (x < 1)
+ fun_l9_n826(x)
+ else
+ fun_l9_n926(x)
+ end
+end
+
+def fun_l8_n357(x)
+ if (x < 1)
+ fun_l9_n17(x)
+ else
+ fun_l9_n486(x)
+ end
+end
+
+def fun_l8_n358(x)
+ if (x < 1)
+ fun_l9_n90(x)
+ else
+ fun_l9_n744(x)
+ end
+end
+
+def fun_l8_n359(x)
+ if (x < 1)
+ fun_l9_n745(x)
+ else
+ fun_l9_n158(x)
+ end
+end
+
+def fun_l8_n360(x)
+ if (x < 1)
+ fun_l9_n261(x)
+ else
+ fun_l9_n878(x)
+ end
+end
+
+def fun_l8_n361(x)
+ if (x < 1)
+ fun_l9_n832(x)
+ else
+ fun_l9_n905(x)
+ end
+end
+
+def fun_l8_n362(x)
+ if (x < 1)
+ fun_l9_n879(x)
+ else
+ fun_l9_n475(x)
+ end
+end
+
+def fun_l8_n363(x)
+ if (x < 1)
+ fun_l9_n586(x)
+ else
+ fun_l9_n272(x)
+ end
+end
+
+def fun_l8_n364(x)
+ if (x < 1)
+ fun_l9_n469(x)
+ else
+ fun_l9_n918(x)
+ end
+end
+
+def fun_l8_n365(x)
+ if (x < 1)
+ fun_l9_n568(x)
+ else
+ fun_l9_n777(x)
+ end
+end
+
+def fun_l8_n366(x)
+ if (x < 1)
+ fun_l9_n662(x)
+ else
+ fun_l9_n957(x)
+ end
+end
+
+def fun_l8_n367(x)
+ if (x < 1)
+ fun_l9_n26(x)
+ else
+ fun_l9_n593(x)
+ end
+end
+
+def fun_l8_n368(x)
+ if (x < 1)
+ fun_l9_n766(x)
+ else
+ fun_l9_n598(x)
+ end
+end
+
+def fun_l8_n369(x)
+ if (x < 1)
+ fun_l9_n362(x)
+ else
+ fun_l9_n491(x)
+ end
+end
+
+def fun_l8_n370(x)
+ if (x < 1)
+ fun_l9_n205(x)
+ else
+ fun_l9_n585(x)
+ end
+end
+
+def fun_l8_n371(x)
+ if (x < 1)
+ fun_l9_n301(x)
+ else
+ fun_l9_n796(x)
+ end
+end
+
+def fun_l8_n372(x)
+ if (x < 1)
+ fun_l9_n527(x)
+ else
+ fun_l9_n31(x)
+ end
+end
+
+def fun_l8_n373(x)
+ if (x < 1)
+ fun_l9_n461(x)
+ else
+ fun_l9_n42(x)
+ end
+end
+
+def fun_l8_n374(x)
+ if (x < 1)
+ fun_l9_n288(x)
+ else
+ fun_l9_n534(x)
+ end
+end
+
+def fun_l8_n375(x)
+ if (x < 1)
+ fun_l9_n558(x)
+ else
+ fun_l9_n403(x)
+ end
+end
+
+def fun_l8_n376(x)
+ if (x < 1)
+ fun_l9_n835(x)
+ else
+ fun_l9_n390(x)
+ end
+end
+
+def fun_l8_n377(x)
+ if (x < 1)
+ fun_l9_n658(x)
+ else
+ fun_l9_n768(x)
+ end
+end
+
+def fun_l8_n378(x)
+ if (x < 1)
+ fun_l9_n856(x)
+ else
+ fun_l9_n299(x)
+ end
+end
+
+def fun_l8_n379(x)
+ if (x < 1)
+ fun_l9_n196(x)
+ else
+ fun_l9_n540(x)
+ end
+end
+
+def fun_l8_n380(x)
+ if (x < 1)
+ fun_l9_n70(x)
+ else
+ fun_l9_n627(x)
+ end
+end
+
+def fun_l8_n381(x)
+ if (x < 1)
+ fun_l9_n28(x)
+ else
+ fun_l9_n377(x)
+ end
+end
+
+def fun_l8_n382(x)
+ if (x < 1)
+ fun_l9_n955(x)
+ else
+ fun_l9_n124(x)
+ end
+end
+
+def fun_l8_n383(x)
+ if (x < 1)
+ fun_l9_n16(x)
+ else
+ fun_l9_n783(x)
+ end
+end
+
+def fun_l8_n384(x)
+ if (x < 1)
+ fun_l9_n843(x)
+ else
+ fun_l9_n801(x)
+ end
+end
+
+def fun_l8_n385(x)
+ if (x < 1)
+ fun_l9_n876(x)
+ else
+ fun_l9_n152(x)
+ end
+end
+
+def fun_l8_n386(x)
+ if (x < 1)
+ fun_l9_n6(x)
+ else
+ fun_l9_n432(x)
+ end
+end
+
+def fun_l8_n387(x)
+ if (x < 1)
+ fun_l9_n636(x)
+ else
+ fun_l9_n325(x)
+ end
+end
+
+def fun_l8_n388(x)
+ if (x < 1)
+ fun_l9_n267(x)
+ else
+ fun_l9_n716(x)
+ end
+end
+
+def fun_l8_n389(x)
+ if (x < 1)
+ fun_l9_n898(x)
+ else
+ fun_l9_n776(x)
+ end
+end
+
+def fun_l8_n390(x)
+ if (x < 1)
+ fun_l9_n481(x)
+ else
+ fun_l9_n878(x)
+ end
+end
+
+def fun_l8_n391(x)
+ if (x < 1)
+ fun_l9_n398(x)
+ else
+ fun_l9_n159(x)
+ end
+end
+
+def fun_l8_n392(x)
+ if (x < 1)
+ fun_l9_n889(x)
+ else
+ fun_l9_n517(x)
+ end
+end
+
+def fun_l8_n393(x)
+ if (x < 1)
+ fun_l9_n460(x)
+ else
+ fun_l9_n440(x)
+ end
+end
+
+def fun_l8_n394(x)
+ if (x < 1)
+ fun_l9_n576(x)
+ else
+ fun_l9_n421(x)
+ end
+end
+
+def fun_l8_n395(x)
+ if (x < 1)
+ fun_l9_n310(x)
+ else
+ fun_l9_n646(x)
+ end
+end
+
+def fun_l8_n396(x)
+ if (x < 1)
+ fun_l9_n914(x)
+ else
+ fun_l9_n414(x)
+ end
+end
+
+def fun_l8_n397(x)
+ if (x < 1)
+ fun_l9_n330(x)
+ else
+ fun_l9_n520(x)
+ end
+end
+
+def fun_l8_n398(x)
+ if (x < 1)
+ fun_l9_n175(x)
+ else
+ fun_l9_n975(x)
+ end
+end
+
+def fun_l8_n399(x)
+ if (x < 1)
+ fun_l9_n443(x)
+ else
+ fun_l9_n964(x)
+ end
+end
+
+def fun_l8_n400(x)
+ if (x < 1)
+ fun_l9_n810(x)
+ else
+ fun_l9_n102(x)
+ end
+end
+
+def fun_l8_n401(x)
+ if (x < 1)
+ fun_l9_n352(x)
+ else
+ fun_l9_n295(x)
+ end
+end
+
+def fun_l8_n402(x)
+ if (x < 1)
+ fun_l9_n980(x)
+ else
+ fun_l9_n974(x)
+ end
+end
+
+def fun_l8_n403(x)
+ if (x < 1)
+ fun_l9_n169(x)
+ else
+ fun_l9_n877(x)
+ end
+end
+
+def fun_l8_n404(x)
+ if (x < 1)
+ fun_l9_n333(x)
+ else
+ fun_l9_n306(x)
+ end
+end
+
+def fun_l8_n405(x)
+ if (x < 1)
+ fun_l9_n183(x)
+ else
+ fun_l9_n704(x)
+ end
+end
+
+def fun_l8_n406(x)
+ if (x < 1)
+ fun_l9_n532(x)
+ else
+ fun_l9_n684(x)
+ end
+end
+
+def fun_l8_n407(x)
+ if (x < 1)
+ fun_l9_n526(x)
+ else
+ fun_l9_n287(x)
+ end
+end
+
+def fun_l8_n408(x)
+ if (x < 1)
+ fun_l9_n377(x)
+ else
+ fun_l9_n351(x)
+ end
+end
+
+def fun_l8_n409(x)
+ if (x < 1)
+ fun_l9_n770(x)
+ else
+ fun_l9_n738(x)
+ end
+end
+
+def fun_l8_n410(x)
+ if (x < 1)
+ fun_l9_n61(x)
+ else
+ fun_l9_n499(x)
+ end
+end
+
+def fun_l8_n411(x)
+ if (x < 1)
+ fun_l9_n156(x)
+ else
+ fun_l9_n247(x)
+ end
+end
+
+def fun_l8_n412(x)
+ if (x < 1)
+ fun_l9_n431(x)
+ else
+ fun_l9_n636(x)
+ end
+end
+
+def fun_l8_n413(x)
+ if (x < 1)
+ fun_l9_n540(x)
+ else
+ fun_l9_n329(x)
+ end
+end
+
+def fun_l8_n414(x)
+ if (x < 1)
+ fun_l9_n49(x)
+ else
+ fun_l9_n979(x)
+ end
+end
+
+def fun_l8_n415(x)
+ if (x < 1)
+ fun_l9_n94(x)
+ else
+ fun_l9_n487(x)
+ end
+end
+
+def fun_l8_n416(x)
+ if (x < 1)
+ fun_l9_n679(x)
+ else
+ fun_l9_n644(x)
+ end
+end
+
+def fun_l8_n417(x)
+ if (x < 1)
+ fun_l9_n907(x)
+ else
+ fun_l9_n324(x)
+ end
+end
+
+def fun_l8_n418(x)
+ if (x < 1)
+ fun_l9_n426(x)
+ else
+ fun_l9_n495(x)
+ end
+end
+
+def fun_l8_n419(x)
+ if (x < 1)
+ fun_l9_n273(x)
+ else
+ fun_l9_n838(x)
+ end
+end
+
+def fun_l8_n420(x)
+ if (x < 1)
+ fun_l9_n631(x)
+ else
+ fun_l9_n205(x)
+ end
+end
+
+def fun_l8_n421(x)
+ if (x < 1)
+ fun_l9_n484(x)
+ else
+ fun_l9_n80(x)
+ end
+end
+
+def fun_l8_n422(x)
+ if (x < 1)
+ fun_l9_n908(x)
+ else
+ fun_l9_n514(x)
+ end
+end
+
+def fun_l8_n423(x)
+ if (x < 1)
+ fun_l9_n265(x)
+ else
+ fun_l9_n190(x)
+ end
+end
+
+def fun_l8_n424(x)
+ if (x < 1)
+ fun_l9_n463(x)
+ else
+ fun_l9_n714(x)
+ end
+end
+
+def fun_l8_n425(x)
+ if (x < 1)
+ fun_l9_n780(x)
+ else
+ fun_l9_n444(x)
+ end
+end
+
+def fun_l8_n426(x)
+ if (x < 1)
+ fun_l9_n418(x)
+ else
+ fun_l9_n518(x)
+ end
+end
+
+def fun_l8_n427(x)
+ if (x < 1)
+ fun_l9_n912(x)
+ else
+ fun_l9_n27(x)
+ end
+end
+
+def fun_l8_n428(x)
+ if (x < 1)
+ fun_l9_n157(x)
+ else
+ fun_l9_n547(x)
+ end
+end
+
+def fun_l8_n429(x)
+ if (x < 1)
+ fun_l9_n760(x)
+ else
+ fun_l9_n466(x)
+ end
+end
+
+def fun_l8_n430(x)
+ if (x < 1)
+ fun_l9_n726(x)
+ else
+ fun_l9_n609(x)
+ end
+end
+
+def fun_l8_n431(x)
+ if (x < 1)
+ fun_l9_n206(x)
+ else
+ fun_l9_n65(x)
+ end
+end
+
+def fun_l8_n432(x)
+ if (x < 1)
+ fun_l9_n396(x)
+ else
+ fun_l9_n325(x)
+ end
+end
+
+def fun_l8_n433(x)
+ if (x < 1)
+ fun_l9_n100(x)
+ else
+ fun_l9_n519(x)
+ end
+end
+
+def fun_l8_n434(x)
+ if (x < 1)
+ fun_l9_n923(x)
+ else
+ fun_l9_n387(x)
+ end
+end
+
+def fun_l8_n435(x)
+ if (x < 1)
+ fun_l9_n334(x)
+ else
+ fun_l9_n866(x)
+ end
+end
+
+def fun_l8_n436(x)
+ if (x < 1)
+ fun_l9_n896(x)
+ else
+ fun_l9_n780(x)
+ end
+end
+
+def fun_l8_n437(x)
+ if (x < 1)
+ fun_l9_n328(x)
+ else
+ fun_l9_n776(x)
+ end
+end
+
+def fun_l8_n438(x)
+ if (x < 1)
+ fun_l9_n414(x)
+ else
+ fun_l9_n884(x)
+ end
+end
+
+def fun_l8_n439(x)
+ if (x < 1)
+ fun_l9_n528(x)
+ else
+ fun_l9_n419(x)
+ end
+end
+
+def fun_l8_n440(x)
+ if (x < 1)
+ fun_l9_n192(x)
+ else
+ fun_l9_n973(x)
+ end
+end
+
+def fun_l8_n441(x)
+ if (x < 1)
+ fun_l9_n679(x)
+ else
+ fun_l9_n135(x)
+ end
+end
+
+def fun_l8_n442(x)
+ if (x < 1)
+ fun_l9_n294(x)
+ else
+ fun_l9_n138(x)
+ end
+end
+
+def fun_l8_n443(x)
+ if (x < 1)
+ fun_l9_n784(x)
+ else
+ fun_l9_n940(x)
+ end
+end
+
+def fun_l8_n444(x)
+ if (x < 1)
+ fun_l9_n834(x)
+ else
+ fun_l9_n127(x)
+ end
+end
+
+def fun_l8_n445(x)
+ if (x < 1)
+ fun_l9_n217(x)
+ else
+ fun_l9_n788(x)
+ end
+end
+
+def fun_l8_n446(x)
+ if (x < 1)
+ fun_l9_n173(x)
+ else
+ fun_l9_n49(x)
+ end
+end
+
+def fun_l8_n447(x)
+ if (x < 1)
+ fun_l9_n493(x)
+ else
+ fun_l9_n384(x)
+ end
+end
+
+def fun_l8_n448(x)
+ if (x < 1)
+ fun_l9_n770(x)
+ else
+ fun_l9_n761(x)
+ end
+end
+
+def fun_l8_n449(x)
+ if (x < 1)
+ fun_l9_n633(x)
+ else
+ fun_l9_n555(x)
+ end
+end
+
+def fun_l8_n450(x)
+ if (x < 1)
+ fun_l9_n25(x)
+ else
+ fun_l9_n714(x)
+ end
+end
+
+def fun_l8_n451(x)
+ if (x < 1)
+ fun_l9_n960(x)
+ else
+ fun_l9_n371(x)
+ end
+end
+
+def fun_l8_n452(x)
+ if (x < 1)
+ fun_l9_n733(x)
+ else
+ fun_l9_n996(x)
+ end
+end
+
+def fun_l8_n453(x)
+ if (x < 1)
+ fun_l9_n628(x)
+ else
+ fun_l9_n512(x)
+ end
+end
+
+def fun_l8_n454(x)
+ if (x < 1)
+ fun_l9_n406(x)
+ else
+ fun_l9_n671(x)
+ end
+end
+
+def fun_l8_n455(x)
+ if (x < 1)
+ fun_l9_n47(x)
+ else
+ fun_l9_n102(x)
+ end
+end
+
+def fun_l8_n456(x)
+ if (x < 1)
+ fun_l9_n85(x)
+ else
+ fun_l9_n591(x)
+ end
+end
+
+def fun_l8_n457(x)
+ if (x < 1)
+ fun_l9_n234(x)
+ else
+ fun_l9_n209(x)
+ end
+end
+
+def fun_l8_n458(x)
+ if (x < 1)
+ fun_l9_n186(x)
+ else
+ fun_l9_n928(x)
+ end
+end
+
+def fun_l8_n459(x)
+ if (x < 1)
+ fun_l9_n36(x)
+ else
+ fun_l9_n783(x)
+ end
+end
+
+def fun_l8_n460(x)
+ if (x < 1)
+ fun_l9_n775(x)
+ else
+ fun_l9_n641(x)
+ end
+end
+
+def fun_l8_n461(x)
+ if (x < 1)
+ fun_l9_n426(x)
+ else
+ fun_l9_n740(x)
+ end
+end
+
+def fun_l8_n462(x)
+ if (x < 1)
+ fun_l9_n770(x)
+ else
+ fun_l9_n113(x)
+ end
+end
+
+def fun_l8_n463(x)
+ if (x < 1)
+ fun_l9_n94(x)
+ else
+ fun_l9_n574(x)
+ end
+end
+
+def fun_l8_n464(x)
+ if (x < 1)
+ fun_l9_n457(x)
+ else
+ fun_l9_n776(x)
+ end
+end
+
+def fun_l8_n465(x)
+ if (x < 1)
+ fun_l9_n252(x)
+ else
+ fun_l9_n182(x)
+ end
+end
+
+def fun_l8_n466(x)
+ if (x < 1)
+ fun_l9_n157(x)
+ else
+ fun_l9_n849(x)
+ end
+end
+
+def fun_l8_n467(x)
+ if (x < 1)
+ fun_l9_n393(x)
+ else
+ fun_l9_n437(x)
+ end
+end
+
+def fun_l8_n468(x)
+ if (x < 1)
+ fun_l9_n269(x)
+ else
+ fun_l9_n381(x)
+ end
+end
+
+def fun_l8_n469(x)
+ if (x < 1)
+ fun_l9_n97(x)
+ else
+ fun_l9_n184(x)
+ end
+end
+
+def fun_l8_n470(x)
+ if (x < 1)
+ fun_l9_n157(x)
+ else
+ fun_l9_n621(x)
+ end
+end
+
+def fun_l8_n471(x)
+ if (x < 1)
+ fun_l9_n627(x)
+ else
+ fun_l9_n793(x)
+ end
+end
+
+def fun_l8_n472(x)
+ if (x < 1)
+ fun_l9_n117(x)
+ else
+ fun_l9_n318(x)
+ end
+end
+
+def fun_l8_n473(x)
+ if (x < 1)
+ fun_l9_n238(x)
+ else
+ fun_l9_n559(x)
+ end
+end
+
+def fun_l8_n474(x)
+ if (x < 1)
+ fun_l9_n81(x)
+ else
+ fun_l9_n355(x)
+ end
+end
+
+def fun_l8_n475(x)
+ if (x < 1)
+ fun_l9_n889(x)
+ else
+ fun_l9_n940(x)
+ end
+end
+
+def fun_l8_n476(x)
+ if (x < 1)
+ fun_l9_n358(x)
+ else
+ fun_l9_n52(x)
+ end
+end
+
+def fun_l8_n477(x)
+ if (x < 1)
+ fun_l9_n144(x)
+ else
+ fun_l9_n575(x)
+ end
+end
+
+def fun_l8_n478(x)
+ if (x < 1)
+ fun_l9_n975(x)
+ else
+ fun_l9_n740(x)
+ end
+end
+
+def fun_l8_n479(x)
+ if (x < 1)
+ fun_l9_n552(x)
+ else
+ fun_l9_n169(x)
+ end
+end
+
+def fun_l8_n480(x)
+ if (x < 1)
+ fun_l9_n854(x)
+ else
+ fun_l9_n524(x)
+ end
+end
+
+def fun_l8_n481(x)
+ if (x < 1)
+ fun_l9_n461(x)
+ else
+ fun_l9_n65(x)
+ end
+end
+
+def fun_l8_n482(x)
+ if (x < 1)
+ fun_l9_n809(x)
+ else
+ fun_l9_n844(x)
+ end
+end
+
+def fun_l8_n483(x)
+ if (x < 1)
+ fun_l9_n741(x)
+ else
+ fun_l9_n327(x)
+ end
+end
+
+def fun_l8_n484(x)
+ if (x < 1)
+ fun_l9_n560(x)
+ else
+ fun_l9_n385(x)
+ end
+end
+
+def fun_l8_n485(x)
+ if (x < 1)
+ fun_l9_n798(x)
+ else
+ fun_l9_n154(x)
+ end
+end
+
+def fun_l8_n486(x)
+ if (x < 1)
+ fun_l9_n892(x)
+ else
+ fun_l9_n367(x)
+ end
+end
+
+def fun_l8_n487(x)
+ if (x < 1)
+ fun_l9_n423(x)
+ else
+ fun_l9_n723(x)
+ end
+end
+
+def fun_l8_n488(x)
+ if (x < 1)
+ fun_l9_n618(x)
+ else
+ fun_l9_n649(x)
+ end
+end
+
+def fun_l8_n489(x)
+ if (x < 1)
+ fun_l9_n261(x)
+ else
+ fun_l9_n495(x)
+ end
+end
+
+def fun_l8_n490(x)
+ if (x < 1)
+ fun_l9_n566(x)
+ else
+ fun_l9_n405(x)
+ end
+end
+
+def fun_l8_n491(x)
+ if (x < 1)
+ fun_l9_n718(x)
+ else
+ fun_l9_n674(x)
+ end
+end
+
+def fun_l8_n492(x)
+ if (x < 1)
+ fun_l9_n487(x)
+ else
+ fun_l9_n95(x)
+ end
+end
+
+def fun_l8_n493(x)
+ if (x < 1)
+ fun_l9_n473(x)
+ else
+ fun_l9_n722(x)
+ end
+end
+
+def fun_l8_n494(x)
+ if (x < 1)
+ fun_l9_n460(x)
+ else
+ fun_l9_n157(x)
+ end
+end
+
+def fun_l8_n495(x)
+ if (x < 1)
+ fun_l9_n812(x)
+ else
+ fun_l9_n807(x)
+ end
+end
+
+def fun_l8_n496(x)
+ if (x < 1)
+ fun_l9_n609(x)
+ else
+ fun_l9_n697(x)
+ end
+end
+
+def fun_l8_n497(x)
+ if (x < 1)
+ fun_l9_n894(x)
+ else
+ fun_l9_n580(x)
+ end
+end
+
+def fun_l8_n498(x)
+ if (x < 1)
+ fun_l9_n642(x)
+ else
+ fun_l9_n13(x)
+ end
+end
+
+def fun_l8_n499(x)
+ if (x < 1)
+ fun_l9_n961(x)
+ else
+ fun_l9_n669(x)
+ end
+end
+
+def fun_l8_n500(x)
+ if (x < 1)
+ fun_l9_n587(x)
+ else
+ fun_l9_n828(x)
+ end
+end
+
+def fun_l8_n501(x)
+ if (x < 1)
+ fun_l9_n30(x)
+ else
+ fun_l9_n966(x)
+ end
+end
+
+def fun_l8_n502(x)
+ if (x < 1)
+ fun_l9_n436(x)
+ else
+ fun_l9_n170(x)
+ end
+end
+
+def fun_l8_n503(x)
+ if (x < 1)
+ fun_l9_n20(x)
+ else
+ fun_l9_n927(x)
+ end
+end
+
+def fun_l8_n504(x)
+ if (x < 1)
+ fun_l9_n326(x)
+ else
+ fun_l9_n223(x)
+ end
+end
+
+def fun_l8_n505(x)
+ if (x < 1)
+ fun_l9_n911(x)
+ else
+ fun_l9_n746(x)
+ end
+end
+
+def fun_l8_n506(x)
+ if (x < 1)
+ fun_l9_n333(x)
+ else
+ fun_l9_n773(x)
+ end
+end
+
+def fun_l8_n507(x)
+ if (x < 1)
+ fun_l9_n514(x)
+ else
+ fun_l9_n882(x)
+ end
+end
+
+def fun_l8_n508(x)
+ if (x < 1)
+ fun_l9_n918(x)
+ else
+ fun_l9_n713(x)
+ end
+end
+
+def fun_l8_n509(x)
+ if (x < 1)
+ fun_l9_n694(x)
+ else
+ fun_l9_n950(x)
+ end
+end
+
+def fun_l8_n510(x)
+ if (x < 1)
+ fun_l9_n77(x)
+ else
+ fun_l9_n65(x)
+ end
+end
+
+def fun_l8_n511(x)
+ if (x < 1)
+ fun_l9_n506(x)
+ else
+ fun_l9_n144(x)
+ end
+end
+
+def fun_l8_n512(x)
+ if (x < 1)
+ fun_l9_n69(x)
+ else
+ fun_l9_n308(x)
+ end
+end
+
+def fun_l8_n513(x)
+ if (x < 1)
+ fun_l9_n377(x)
+ else
+ fun_l9_n531(x)
+ end
+end
+
+def fun_l8_n514(x)
+ if (x < 1)
+ fun_l9_n342(x)
+ else
+ fun_l9_n265(x)
+ end
+end
+
+def fun_l8_n515(x)
+ if (x < 1)
+ fun_l9_n453(x)
+ else
+ fun_l9_n227(x)
+ end
+end
+
+def fun_l8_n516(x)
+ if (x < 1)
+ fun_l9_n396(x)
+ else
+ fun_l9_n130(x)
+ end
+end
+
+def fun_l8_n517(x)
+ if (x < 1)
+ fun_l9_n715(x)
+ else
+ fun_l9_n953(x)
+ end
+end
+
+def fun_l8_n518(x)
+ if (x < 1)
+ fun_l9_n326(x)
+ else
+ fun_l9_n949(x)
+ end
+end
+
+def fun_l8_n519(x)
+ if (x < 1)
+ fun_l9_n535(x)
+ else
+ fun_l9_n41(x)
+ end
+end
+
+def fun_l8_n520(x)
+ if (x < 1)
+ fun_l9_n985(x)
+ else
+ fun_l9_n942(x)
+ end
+end
+
+def fun_l8_n521(x)
+ if (x < 1)
+ fun_l9_n347(x)
+ else
+ fun_l9_n263(x)
+ end
+end
+
+def fun_l8_n522(x)
+ if (x < 1)
+ fun_l9_n532(x)
+ else
+ fun_l9_n378(x)
+ end
+end
+
+def fun_l8_n523(x)
+ if (x < 1)
+ fun_l9_n362(x)
+ else
+ fun_l9_n630(x)
+ end
+end
+
+def fun_l8_n524(x)
+ if (x < 1)
+ fun_l9_n382(x)
+ else
+ fun_l9_n256(x)
+ end
+end
+
+def fun_l8_n525(x)
+ if (x < 1)
+ fun_l9_n444(x)
+ else
+ fun_l9_n756(x)
+ end
+end
+
+def fun_l8_n526(x)
+ if (x < 1)
+ fun_l9_n5(x)
+ else
+ fun_l9_n754(x)
+ end
+end
+
+def fun_l8_n527(x)
+ if (x < 1)
+ fun_l9_n157(x)
+ else
+ fun_l9_n279(x)
+ end
+end
+
+def fun_l8_n528(x)
+ if (x < 1)
+ fun_l9_n110(x)
+ else
+ fun_l9_n246(x)
+ end
+end
+
+def fun_l8_n529(x)
+ if (x < 1)
+ fun_l9_n312(x)
+ else
+ fun_l9_n890(x)
+ end
+end
+
+def fun_l8_n530(x)
+ if (x < 1)
+ fun_l9_n624(x)
+ else
+ fun_l9_n548(x)
+ end
+end
+
+def fun_l8_n531(x)
+ if (x < 1)
+ fun_l9_n615(x)
+ else
+ fun_l9_n948(x)
+ end
+end
+
+def fun_l8_n532(x)
+ if (x < 1)
+ fun_l9_n519(x)
+ else
+ fun_l9_n583(x)
+ end
+end
+
+def fun_l8_n533(x)
+ if (x < 1)
+ fun_l9_n292(x)
+ else
+ fun_l9_n827(x)
+ end
+end
+
+def fun_l8_n534(x)
+ if (x < 1)
+ fun_l9_n893(x)
+ else
+ fun_l9_n877(x)
+ end
+end
+
+def fun_l8_n535(x)
+ if (x < 1)
+ fun_l9_n873(x)
+ else
+ fun_l9_n399(x)
+ end
+end
+
+def fun_l8_n536(x)
+ if (x < 1)
+ fun_l9_n497(x)
+ else
+ fun_l9_n507(x)
+ end
+end
+
+def fun_l8_n537(x)
+ if (x < 1)
+ fun_l9_n404(x)
+ else
+ fun_l9_n815(x)
+ end
+end
+
+def fun_l8_n538(x)
+ if (x < 1)
+ fun_l9_n258(x)
+ else
+ fun_l9_n810(x)
+ end
+end
+
+def fun_l8_n539(x)
+ if (x < 1)
+ fun_l9_n907(x)
+ else
+ fun_l9_n720(x)
+ end
+end
+
+def fun_l8_n540(x)
+ if (x < 1)
+ fun_l9_n752(x)
+ else
+ fun_l9_n597(x)
+ end
+end
+
+def fun_l8_n541(x)
+ if (x < 1)
+ fun_l9_n802(x)
+ else
+ fun_l9_n45(x)
+ end
+end
+
+def fun_l8_n542(x)
+ if (x < 1)
+ fun_l9_n635(x)
+ else
+ fun_l9_n470(x)
+ end
+end
+
+def fun_l8_n543(x)
+ if (x < 1)
+ fun_l9_n353(x)
+ else
+ fun_l9_n238(x)
+ end
+end
+
+def fun_l8_n544(x)
+ if (x < 1)
+ fun_l9_n656(x)
+ else
+ fun_l9_n569(x)
+ end
+end
+
+def fun_l8_n545(x)
+ if (x < 1)
+ fun_l9_n494(x)
+ else
+ fun_l9_n566(x)
+ end
+end
+
+def fun_l8_n546(x)
+ if (x < 1)
+ fun_l9_n65(x)
+ else
+ fun_l9_n896(x)
+ end
+end
+
+def fun_l8_n547(x)
+ if (x < 1)
+ fun_l9_n995(x)
+ else
+ fun_l9_n727(x)
+ end
+end
+
+def fun_l8_n548(x)
+ if (x < 1)
+ fun_l9_n562(x)
+ else
+ fun_l9_n759(x)
+ end
+end
+
+def fun_l8_n549(x)
+ if (x < 1)
+ fun_l9_n210(x)
+ else
+ fun_l9_n734(x)
+ end
+end
+
+def fun_l8_n550(x)
+ if (x < 1)
+ fun_l9_n482(x)
+ else
+ fun_l9_n11(x)
+ end
+end
+
+def fun_l8_n551(x)
+ if (x < 1)
+ fun_l9_n86(x)
+ else
+ fun_l9_n867(x)
+ end
+end
+
+def fun_l8_n552(x)
+ if (x < 1)
+ fun_l9_n647(x)
+ else
+ fun_l9_n293(x)
+ end
+end
+
+def fun_l8_n553(x)
+ if (x < 1)
+ fun_l9_n98(x)
+ else
+ fun_l9_n868(x)
+ end
+end
+
+def fun_l8_n554(x)
+ if (x < 1)
+ fun_l9_n380(x)
+ else
+ fun_l9_n2(x)
+ end
+end
+
+def fun_l8_n555(x)
+ if (x < 1)
+ fun_l9_n274(x)
+ else
+ fun_l9_n489(x)
+ end
+end
+
+def fun_l8_n556(x)
+ if (x < 1)
+ fun_l9_n623(x)
+ else
+ fun_l9_n848(x)
+ end
+end
+
+def fun_l8_n557(x)
+ if (x < 1)
+ fun_l9_n642(x)
+ else
+ fun_l9_n890(x)
+ end
+end
+
+def fun_l8_n558(x)
+ if (x < 1)
+ fun_l9_n247(x)
+ else
+ fun_l9_n65(x)
+ end
+end
+
+def fun_l8_n559(x)
+ if (x < 1)
+ fun_l9_n896(x)
+ else
+ fun_l9_n937(x)
+ end
+end
+
+def fun_l8_n560(x)
+ if (x < 1)
+ fun_l9_n592(x)
+ else
+ fun_l9_n211(x)
+ end
+end
+
+def fun_l8_n561(x)
+ if (x < 1)
+ fun_l9_n205(x)
+ else
+ fun_l9_n971(x)
+ end
+end
+
+def fun_l8_n562(x)
+ if (x < 1)
+ fun_l9_n663(x)
+ else
+ fun_l9_n147(x)
+ end
+end
+
+def fun_l8_n563(x)
+ if (x < 1)
+ fun_l9_n722(x)
+ else
+ fun_l9_n649(x)
+ end
+end
+
+def fun_l8_n564(x)
+ if (x < 1)
+ fun_l9_n605(x)
+ else
+ fun_l9_n58(x)
+ end
+end
+
+def fun_l8_n565(x)
+ if (x < 1)
+ fun_l9_n914(x)
+ else
+ fun_l9_n617(x)
+ end
+end
+
+def fun_l8_n566(x)
+ if (x < 1)
+ fun_l9_n772(x)
+ else
+ fun_l9_n428(x)
+ end
+end
+
+def fun_l8_n567(x)
+ if (x < 1)
+ fun_l9_n870(x)
+ else
+ fun_l9_n672(x)
+ end
+end
+
+def fun_l8_n568(x)
+ if (x < 1)
+ fun_l9_n946(x)
+ else
+ fun_l9_n465(x)
+ end
+end
+
+def fun_l8_n569(x)
+ if (x < 1)
+ fun_l9_n507(x)
+ else
+ fun_l9_n346(x)
+ end
+end
+
+def fun_l8_n570(x)
+ if (x < 1)
+ fun_l9_n157(x)
+ else
+ fun_l9_n70(x)
+ end
+end
+
+def fun_l8_n571(x)
+ if (x < 1)
+ fun_l9_n549(x)
+ else
+ fun_l9_n831(x)
+ end
+end
+
+def fun_l8_n572(x)
+ if (x < 1)
+ fun_l9_n463(x)
+ else
+ fun_l9_n843(x)
+ end
+end
+
+def fun_l8_n573(x)
+ if (x < 1)
+ fun_l9_n676(x)
+ else
+ fun_l9_n651(x)
+ end
+end
+
+def fun_l8_n574(x)
+ if (x < 1)
+ fun_l9_n648(x)
+ else
+ fun_l9_n562(x)
+ end
+end
+
+def fun_l8_n575(x)
+ if (x < 1)
+ fun_l9_n771(x)
+ else
+ fun_l9_n549(x)
+ end
+end
+
+def fun_l8_n576(x)
+ if (x < 1)
+ fun_l9_n899(x)
+ else
+ fun_l9_n436(x)
+ end
+end
+
+def fun_l8_n577(x)
+ if (x < 1)
+ fun_l9_n110(x)
+ else
+ fun_l9_n708(x)
+ end
+end
+
+def fun_l8_n578(x)
+ if (x < 1)
+ fun_l9_n49(x)
+ else
+ fun_l9_n559(x)
+ end
+end
+
+def fun_l8_n579(x)
+ if (x < 1)
+ fun_l9_n937(x)
+ else
+ fun_l9_n962(x)
+ end
+end
+
+def fun_l8_n580(x)
+ if (x < 1)
+ fun_l9_n970(x)
+ else
+ fun_l9_n203(x)
+ end
+end
+
+def fun_l8_n581(x)
+ if (x < 1)
+ fun_l9_n901(x)
+ else
+ fun_l9_n666(x)
+ end
+end
+
+def fun_l8_n582(x)
+ if (x < 1)
+ fun_l9_n79(x)
+ else
+ fun_l9_n260(x)
+ end
+end
+
+def fun_l8_n583(x)
+ if (x < 1)
+ fun_l9_n167(x)
+ else
+ fun_l9_n512(x)
+ end
+end
+
+def fun_l8_n584(x)
+ if (x < 1)
+ fun_l9_n750(x)
+ else
+ fun_l9_n406(x)
+ end
+end
+
+def fun_l8_n585(x)
+ if (x < 1)
+ fun_l9_n118(x)
+ else
+ fun_l9_n525(x)
+ end
+end
+
+def fun_l8_n586(x)
+ if (x < 1)
+ fun_l9_n573(x)
+ else
+ fun_l9_n657(x)
+ end
+end
+
+def fun_l8_n587(x)
+ if (x < 1)
+ fun_l9_n228(x)
+ else
+ fun_l9_n903(x)
+ end
+end
+
+def fun_l8_n588(x)
+ if (x < 1)
+ fun_l9_n971(x)
+ else
+ fun_l9_n608(x)
+ end
+end
+
+def fun_l8_n589(x)
+ if (x < 1)
+ fun_l9_n334(x)
+ else
+ fun_l9_n704(x)
+ end
+end
+
+def fun_l8_n590(x)
+ if (x < 1)
+ fun_l9_n398(x)
+ else
+ fun_l9_n500(x)
+ end
+end
+
+def fun_l8_n591(x)
+ if (x < 1)
+ fun_l9_n196(x)
+ else
+ fun_l9_n616(x)
+ end
+end
+
+def fun_l8_n592(x)
+ if (x < 1)
+ fun_l9_n756(x)
+ else
+ fun_l9_n655(x)
+ end
+end
+
+def fun_l8_n593(x)
+ if (x < 1)
+ fun_l9_n864(x)
+ else
+ fun_l9_n697(x)
+ end
+end
+
+def fun_l8_n594(x)
+ if (x < 1)
+ fun_l9_n35(x)
+ else
+ fun_l9_n554(x)
+ end
+end
+
+def fun_l8_n595(x)
+ if (x < 1)
+ fun_l9_n480(x)
+ else
+ fun_l9_n688(x)
+ end
+end
+
+def fun_l8_n596(x)
+ if (x < 1)
+ fun_l9_n846(x)
+ else
+ fun_l9_n403(x)
+ end
+end
+
+def fun_l8_n597(x)
+ if (x < 1)
+ fun_l9_n522(x)
+ else
+ fun_l9_n532(x)
+ end
+end
+
+def fun_l8_n598(x)
+ if (x < 1)
+ fun_l9_n800(x)
+ else
+ fun_l9_n531(x)
+ end
+end
+
+def fun_l8_n599(x)
+ if (x < 1)
+ fun_l9_n64(x)
+ else
+ fun_l9_n876(x)
+ end
+end
+
+def fun_l8_n600(x)
+ if (x < 1)
+ fun_l9_n614(x)
+ else
+ fun_l9_n660(x)
+ end
+end
+
+def fun_l8_n601(x)
+ if (x < 1)
+ fun_l9_n119(x)
+ else
+ fun_l9_n998(x)
+ end
+end
+
+def fun_l8_n602(x)
+ if (x < 1)
+ fun_l9_n549(x)
+ else
+ fun_l9_n911(x)
+ end
+end
+
+def fun_l8_n603(x)
+ if (x < 1)
+ fun_l9_n659(x)
+ else
+ fun_l9_n664(x)
+ end
+end
+
+def fun_l8_n604(x)
+ if (x < 1)
+ fun_l9_n570(x)
+ else
+ fun_l9_n960(x)
+ end
+end
+
+def fun_l8_n605(x)
+ if (x < 1)
+ fun_l9_n82(x)
+ else
+ fun_l9_n658(x)
+ end
+end
+
+def fun_l8_n606(x)
+ if (x < 1)
+ fun_l9_n379(x)
+ else
+ fun_l9_n881(x)
+ end
+end
+
+def fun_l8_n607(x)
+ if (x < 1)
+ fun_l9_n104(x)
+ else
+ fun_l9_n869(x)
+ end
+end
+
+def fun_l8_n608(x)
+ if (x < 1)
+ fun_l9_n874(x)
+ else
+ fun_l9_n63(x)
+ end
+end
+
+def fun_l8_n609(x)
+ if (x < 1)
+ fun_l9_n921(x)
+ else
+ fun_l9_n667(x)
+ end
+end
+
+def fun_l8_n610(x)
+ if (x < 1)
+ fun_l9_n1(x)
+ else
+ fun_l9_n524(x)
+ end
+end
+
+def fun_l8_n611(x)
+ if (x < 1)
+ fun_l9_n523(x)
+ else
+ fun_l9_n230(x)
+ end
+end
+
+def fun_l8_n612(x)
+ if (x < 1)
+ fun_l9_n914(x)
+ else
+ fun_l9_n129(x)
+ end
+end
+
+def fun_l8_n613(x)
+ if (x < 1)
+ fun_l9_n591(x)
+ else
+ fun_l9_n551(x)
+ end
+end
+
+def fun_l8_n614(x)
+ if (x < 1)
+ fun_l9_n860(x)
+ else
+ fun_l9_n358(x)
+ end
+end
+
+def fun_l8_n615(x)
+ if (x < 1)
+ fun_l9_n387(x)
+ else
+ fun_l9_n425(x)
+ end
+end
+
+def fun_l8_n616(x)
+ if (x < 1)
+ fun_l9_n426(x)
+ else
+ fun_l9_n449(x)
+ end
+end
+
+def fun_l8_n617(x)
+ if (x < 1)
+ fun_l9_n627(x)
+ else
+ fun_l9_n399(x)
+ end
+end
+
+def fun_l8_n618(x)
+ if (x < 1)
+ fun_l9_n244(x)
+ else
+ fun_l9_n24(x)
+ end
+end
+
+def fun_l8_n619(x)
+ if (x < 1)
+ fun_l9_n574(x)
+ else
+ fun_l9_n640(x)
+ end
+end
+
+def fun_l8_n620(x)
+ if (x < 1)
+ fun_l9_n20(x)
+ else
+ fun_l9_n6(x)
+ end
+end
+
+def fun_l8_n621(x)
+ if (x < 1)
+ fun_l9_n148(x)
+ else
+ fun_l9_n718(x)
+ end
+end
+
+def fun_l8_n622(x)
+ if (x < 1)
+ fun_l9_n151(x)
+ else
+ fun_l9_n56(x)
+ end
+end
+
+def fun_l8_n623(x)
+ if (x < 1)
+ fun_l9_n672(x)
+ else
+ fun_l9_n93(x)
+ end
+end
+
+def fun_l8_n624(x)
+ if (x < 1)
+ fun_l9_n948(x)
+ else
+ fun_l9_n530(x)
+ end
+end
+
+def fun_l8_n625(x)
+ if (x < 1)
+ fun_l9_n0(x)
+ else
+ fun_l9_n334(x)
+ end
+end
+
+def fun_l8_n626(x)
+ if (x < 1)
+ fun_l9_n736(x)
+ else
+ fun_l9_n922(x)
+ end
+end
+
+def fun_l8_n627(x)
+ if (x < 1)
+ fun_l9_n291(x)
+ else
+ fun_l9_n953(x)
+ end
+end
+
+def fun_l8_n628(x)
+ if (x < 1)
+ fun_l9_n493(x)
+ else
+ fun_l9_n4(x)
+ end
+end
+
+def fun_l8_n629(x)
+ if (x < 1)
+ fun_l9_n890(x)
+ else
+ fun_l9_n297(x)
+ end
+end
+
+def fun_l8_n630(x)
+ if (x < 1)
+ fun_l9_n860(x)
+ else
+ fun_l9_n74(x)
+ end
+end
+
+def fun_l8_n631(x)
+ if (x < 1)
+ fun_l9_n400(x)
+ else
+ fun_l9_n584(x)
+ end
+end
+
+def fun_l8_n632(x)
+ if (x < 1)
+ fun_l9_n714(x)
+ else
+ fun_l9_n200(x)
+ end
+end
+
+def fun_l8_n633(x)
+ if (x < 1)
+ fun_l9_n433(x)
+ else
+ fun_l9_n489(x)
+ end
+end
+
+def fun_l8_n634(x)
+ if (x < 1)
+ fun_l9_n974(x)
+ else
+ fun_l9_n25(x)
+ end
+end
+
+def fun_l8_n635(x)
+ if (x < 1)
+ fun_l9_n739(x)
+ else
+ fun_l9_n695(x)
+ end
+end
+
+def fun_l8_n636(x)
+ if (x < 1)
+ fun_l9_n855(x)
+ else
+ fun_l9_n898(x)
+ end
+end
+
+def fun_l8_n637(x)
+ if (x < 1)
+ fun_l9_n868(x)
+ else
+ fun_l9_n825(x)
+ end
+end
+
+def fun_l8_n638(x)
+ if (x < 1)
+ fun_l9_n537(x)
+ else
+ fun_l9_n417(x)
+ end
+end
+
+def fun_l8_n639(x)
+ if (x < 1)
+ fun_l9_n975(x)
+ else
+ fun_l9_n484(x)
+ end
+end
+
+def fun_l8_n640(x)
+ if (x < 1)
+ fun_l9_n228(x)
+ else
+ fun_l9_n964(x)
+ end
+end
+
+def fun_l8_n641(x)
+ if (x < 1)
+ fun_l9_n743(x)
+ else
+ fun_l9_n986(x)
+ end
+end
+
+def fun_l8_n642(x)
+ if (x < 1)
+ fun_l9_n763(x)
+ else
+ fun_l9_n747(x)
+ end
+end
+
+def fun_l8_n643(x)
+ if (x < 1)
+ fun_l9_n77(x)
+ else
+ fun_l9_n149(x)
+ end
+end
+
+def fun_l8_n644(x)
+ if (x < 1)
+ fun_l9_n393(x)
+ else
+ fun_l9_n694(x)
+ end
+end
+
+def fun_l8_n645(x)
+ if (x < 1)
+ fun_l9_n196(x)
+ else
+ fun_l9_n211(x)
+ end
+end
+
+def fun_l8_n646(x)
+ if (x < 1)
+ fun_l9_n94(x)
+ else
+ fun_l9_n649(x)
+ end
+end
+
+def fun_l8_n647(x)
+ if (x < 1)
+ fun_l9_n669(x)
+ else
+ fun_l9_n12(x)
+ end
+end
+
+def fun_l8_n648(x)
+ if (x < 1)
+ fun_l9_n175(x)
+ else
+ fun_l9_n388(x)
+ end
+end
+
+def fun_l8_n649(x)
+ if (x < 1)
+ fun_l9_n122(x)
+ else
+ fun_l9_n736(x)
+ end
+end
+
+def fun_l8_n650(x)
+ if (x < 1)
+ fun_l9_n817(x)
+ else
+ fun_l9_n274(x)
+ end
+end
+
+def fun_l8_n651(x)
+ if (x < 1)
+ fun_l9_n919(x)
+ else
+ fun_l9_n538(x)
+ end
+end
+
+def fun_l8_n652(x)
+ if (x < 1)
+ fun_l9_n171(x)
+ else
+ fun_l9_n895(x)
+ end
+end
+
+def fun_l8_n653(x)
+ if (x < 1)
+ fun_l9_n417(x)
+ else
+ fun_l9_n618(x)
+ end
+end
+
+def fun_l8_n654(x)
+ if (x < 1)
+ fun_l9_n709(x)
+ else
+ fun_l9_n892(x)
+ end
+end
+
+def fun_l8_n655(x)
+ if (x < 1)
+ fun_l9_n906(x)
+ else
+ fun_l9_n602(x)
+ end
+end
+
+def fun_l8_n656(x)
+ if (x < 1)
+ fun_l9_n769(x)
+ else
+ fun_l9_n554(x)
+ end
+end
+
+def fun_l8_n657(x)
+ if (x < 1)
+ fun_l9_n468(x)
+ else
+ fun_l9_n320(x)
+ end
+end
+
+def fun_l8_n658(x)
+ if (x < 1)
+ fun_l9_n38(x)
+ else
+ fun_l9_n947(x)
+ end
+end
+
+def fun_l8_n659(x)
+ if (x < 1)
+ fun_l9_n635(x)
+ else
+ fun_l9_n327(x)
+ end
+end
+
+def fun_l8_n660(x)
+ if (x < 1)
+ fun_l9_n452(x)
+ else
+ fun_l9_n313(x)
+ end
+end
+
+def fun_l8_n661(x)
+ if (x < 1)
+ fun_l9_n568(x)
+ else
+ fun_l9_n383(x)
+ end
+end
+
+def fun_l8_n662(x)
+ if (x < 1)
+ fun_l9_n795(x)
+ else
+ fun_l9_n680(x)
+ end
+end
+
+def fun_l8_n663(x)
+ if (x < 1)
+ fun_l9_n152(x)
+ else
+ fun_l9_n846(x)
+ end
+end
+
+def fun_l8_n664(x)
+ if (x < 1)
+ fun_l9_n585(x)
+ else
+ fun_l9_n670(x)
+ end
+end
+
+def fun_l8_n665(x)
+ if (x < 1)
+ fun_l9_n133(x)
+ else
+ fun_l9_n799(x)
+ end
+end
+
+def fun_l8_n666(x)
+ if (x < 1)
+ fun_l9_n699(x)
+ else
+ fun_l9_n311(x)
+ end
+end
+
+def fun_l8_n667(x)
+ if (x < 1)
+ fun_l9_n558(x)
+ else
+ fun_l9_n669(x)
+ end
+end
+
+def fun_l8_n668(x)
+ if (x < 1)
+ fun_l9_n825(x)
+ else
+ fun_l9_n534(x)
+ end
+end
+
+def fun_l8_n669(x)
+ if (x < 1)
+ fun_l9_n143(x)
+ else
+ fun_l9_n21(x)
+ end
+end
+
+def fun_l8_n670(x)
+ if (x < 1)
+ fun_l9_n827(x)
+ else
+ fun_l9_n679(x)
+ end
+end
+
+def fun_l8_n671(x)
+ if (x < 1)
+ fun_l9_n704(x)
+ else
+ fun_l9_n922(x)
+ end
+end
+
+def fun_l8_n672(x)
+ if (x < 1)
+ fun_l9_n776(x)
+ else
+ fun_l9_n867(x)
+ end
+end
+
+def fun_l8_n673(x)
+ if (x < 1)
+ fun_l9_n871(x)
+ else
+ fun_l9_n315(x)
+ end
+end
+
+def fun_l8_n674(x)
+ if (x < 1)
+ fun_l9_n860(x)
+ else
+ fun_l9_n945(x)
+ end
+end
+
+def fun_l8_n675(x)
+ if (x < 1)
+ fun_l9_n890(x)
+ else
+ fun_l9_n629(x)
+ end
+end
+
+def fun_l8_n676(x)
+ if (x < 1)
+ fun_l9_n91(x)
+ else
+ fun_l9_n35(x)
+ end
+end
+
+def fun_l8_n677(x)
+ if (x < 1)
+ fun_l9_n825(x)
+ else
+ fun_l9_n922(x)
+ end
+end
+
+def fun_l8_n678(x)
+ if (x < 1)
+ fun_l9_n457(x)
+ else
+ fun_l9_n156(x)
+ end
+end
+
+def fun_l8_n679(x)
+ if (x < 1)
+ fun_l9_n455(x)
+ else
+ fun_l9_n809(x)
+ end
+end
+
+def fun_l8_n680(x)
+ if (x < 1)
+ fun_l9_n213(x)
+ else
+ fun_l9_n944(x)
+ end
+end
+
+def fun_l8_n681(x)
+ if (x < 1)
+ fun_l9_n760(x)
+ else
+ fun_l9_n137(x)
+ end
+end
+
+def fun_l8_n682(x)
+ if (x < 1)
+ fun_l9_n998(x)
+ else
+ fun_l9_n703(x)
+ end
+end
+
+def fun_l8_n683(x)
+ if (x < 1)
+ fun_l9_n988(x)
+ else
+ fun_l9_n952(x)
+ end
+end
+
+def fun_l8_n684(x)
+ if (x < 1)
+ fun_l9_n583(x)
+ else
+ fun_l9_n890(x)
+ end
+end
+
+def fun_l8_n685(x)
+ if (x < 1)
+ fun_l9_n879(x)
+ else
+ fun_l9_n978(x)
+ end
+end
+
+def fun_l8_n686(x)
+ if (x < 1)
+ fun_l9_n6(x)
+ else
+ fun_l9_n978(x)
+ end
+end
+
+def fun_l8_n687(x)
+ if (x < 1)
+ fun_l9_n67(x)
+ else
+ fun_l9_n149(x)
+ end
+end
+
+def fun_l8_n688(x)
+ if (x < 1)
+ fun_l9_n386(x)
+ else
+ fun_l9_n293(x)
+ end
+end
+
+def fun_l8_n689(x)
+ if (x < 1)
+ fun_l9_n493(x)
+ else
+ fun_l9_n140(x)
+ end
+end
+
+def fun_l8_n690(x)
+ if (x < 1)
+ fun_l9_n92(x)
+ else
+ fun_l9_n550(x)
+ end
+end
+
+def fun_l8_n691(x)
+ if (x < 1)
+ fun_l9_n456(x)
+ else
+ fun_l9_n976(x)
+ end
+end
+
+def fun_l8_n692(x)
+ if (x < 1)
+ fun_l9_n516(x)
+ else
+ fun_l9_n145(x)
+ end
+end
+
+def fun_l8_n693(x)
+ if (x < 1)
+ fun_l9_n757(x)
+ else
+ fun_l9_n647(x)
+ end
+end
+
+def fun_l8_n694(x)
+ if (x < 1)
+ fun_l9_n348(x)
+ else
+ fun_l9_n86(x)
+ end
+end
+
+def fun_l8_n695(x)
+ if (x < 1)
+ fun_l9_n546(x)
+ else
+ fun_l9_n320(x)
+ end
+end
+
+def fun_l8_n696(x)
+ if (x < 1)
+ fun_l9_n588(x)
+ else
+ fun_l9_n285(x)
+ end
+end
+
+def fun_l8_n697(x)
+ if (x < 1)
+ fun_l9_n635(x)
+ else
+ fun_l9_n710(x)
+ end
+end
+
+def fun_l8_n698(x)
+ if (x < 1)
+ fun_l9_n312(x)
+ else
+ fun_l9_n217(x)
+ end
+end
+
+def fun_l8_n699(x)
+ if (x < 1)
+ fun_l9_n714(x)
+ else
+ fun_l9_n723(x)
+ end
+end
+
+def fun_l8_n700(x)
+ if (x < 1)
+ fun_l9_n378(x)
+ else
+ fun_l9_n122(x)
+ end
+end
+
+def fun_l8_n701(x)
+ if (x < 1)
+ fun_l9_n696(x)
+ else
+ fun_l9_n577(x)
+ end
+end
+
+def fun_l8_n702(x)
+ if (x < 1)
+ fun_l9_n388(x)
+ else
+ fun_l9_n578(x)
+ end
+end
+
+def fun_l8_n703(x)
+ if (x < 1)
+ fun_l9_n502(x)
+ else
+ fun_l9_n410(x)
+ end
+end
+
+def fun_l8_n704(x)
+ if (x < 1)
+ fun_l9_n532(x)
+ else
+ fun_l9_n532(x)
+ end
+end
+
+def fun_l8_n705(x)
+ if (x < 1)
+ fun_l9_n662(x)
+ else
+ fun_l9_n361(x)
+ end
+end
+
+def fun_l8_n706(x)
+ if (x < 1)
+ fun_l9_n109(x)
+ else
+ fun_l9_n380(x)
+ end
+end
+
+def fun_l8_n707(x)
+ if (x < 1)
+ fun_l9_n653(x)
+ else
+ fun_l9_n566(x)
+ end
+end
+
+def fun_l8_n708(x)
+ if (x < 1)
+ fun_l9_n587(x)
+ else
+ fun_l9_n465(x)
+ end
+end
+
+def fun_l8_n709(x)
+ if (x < 1)
+ fun_l9_n523(x)
+ else
+ fun_l9_n274(x)
+ end
+end
+
+def fun_l8_n710(x)
+ if (x < 1)
+ fun_l9_n459(x)
+ else
+ fun_l9_n872(x)
+ end
+end
+
+def fun_l8_n711(x)
+ if (x < 1)
+ fun_l9_n71(x)
+ else
+ fun_l9_n135(x)
+ end
+end
+
+def fun_l8_n712(x)
+ if (x < 1)
+ fun_l9_n770(x)
+ else
+ fun_l9_n405(x)
+ end
+end
+
+def fun_l8_n713(x)
+ if (x < 1)
+ fun_l9_n233(x)
+ else
+ fun_l9_n232(x)
+ end
+end
+
+def fun_l8_n714(x)
+ if (x < 1)
+ fun_l9_n29(x)
+ else
+ fun_l9_n23(x)
+ end
+end
+
+def fun_l8_n715(x)
+ if (x < 1)
+ fun_l9_n44(x)
+ else
+ fun_l9_n185(x)
+ end
+end
+
+def fun_l8_n716(x)
+ if (x < 1)
+ fun_l9_n980(x)
+ else
+ fun_l9_n967(x)
+ end
+end
+
+def fun_l8_n717(x)
+ if (x < 1)
+ fun_l9_n323(x)
+ else
+ fun_l9_n636(x)
+ end
+end
+
+def fun_l8_n718(x)
+ if (x < 1)
+ fun_l9_n733(x)
+ else
+ fun_l9_n10(x)
+ end
+end
+
+def fun_l8_n719(x)
+ if (x < 1)
+ fun_l9_n100(x)
+ else
+ fun_l9_n123(x)
+ end
+end
+
+def fun_l8_n720(x)
+ if (x < 1)
+ fun_l9_n572(x)
+ else
+ fun_l9_n813(x)
+ end
+end
+
+def fun_l8_n721(x)
+ if (x < 1)
+ fun_l9_n634(x)
+ else
+ fun_l9_n152(x)
+ end
+end
+
+def fun_l8_n722(x)
+ if (x < 1)
+ fun_l9_n527(x)
+ else
+ fun_l9_n881(x)
+ end
+end
+
+def fun_l8_n723(x)
+ if (x < 1)
+ fun_l9_n202(x)
+ else
+ fun_l9_n294(x)
+ end
+end
+
+def fun_l8_n724(x)
+ if (x < 1)
+ fun_l9_n668(x)
+ else
+ fun_l9_n792(x)
+ end
+end
+
+def fun_l8_n725(x)
+ if (x < 1)
+ fun_l9_n309(x)
+ else
+ fun_l9_n612(x)
+ end
+end
+
+def fun_l8_n726(x)
+ if (x < 1)
+ fun_l9_n320(x)
+ else
+ fun_l9_n459(x)
+ end
+end
+
+def fun_l8_n727(x)
+ if (x < 1)
+ fun_l9_n355(x)
+ else
+ fun_l9_n321(x)
+ end
+end
+
+def fun_l8_n728(x)
+ if (x < 1)
+ fun_l9_n237(x)
+ else
+ fun_l9_n135(x)
+ end
+end
+
+def fun_l8_n729(x)
+ if (x < 1)
+ fun_l9_n980(x)
+ else
+ fun_l9_n209(x)
+ end
+end
+
+def fun_l8_n730(x)
+ if (x < 1)
+ fun_l9_n957(x)
+ else
+ fun_l9_n481(x)
+ end
+end
+
+def fun_l8_n731(x)
+ if (x < 1)
+ fun_l9_n594(x)
+ else
+ fun_l9_n396(x)
+ end
+end
+
+def fun_l8_n732(x)
+ if (x < 1)
+ fun_l9_n916(x)
+ else
+ fun_l9_n473(x)
+ end
+end
+
+def fun_l8_n733(x)
+ if (x < 1)
+ fun_l9_n376(x)
+ else
+ fun_l9_n231(x)
+ end
+end
+
+def fun_l8_n734(x)
+ if (x < 1)
+ fun_l9_n758(x)
+ else
+ fun_l9_n111(x)
+ end
+end
+
+def fun_l8_n735(x)
+ if (x < 1)
+ fun_l9_n131(x)
+ else
+ fun_l9_n586(x)
+ end
+end
+
+def fun_l8_n736(x)
+ if (x < 1)
+ fun_l9_n290(x)
+ else
+ fun_l9_n227(x)
+ end
+end
+
+def fun_l8_n737(x)
+ if (x < 1)
+ fun_l9_n784(x)
+ else
+ fun_l9_n869(x)
+ end
+end
+
+def fun_l8_n738(x)
+ if (x < 1)
+ fun_l9_n94(x)
+ else
+ fun_l9_n79(x)
+ end
+end
+
+def fun_l8_n739(x)
+ if (x < 1)
+ fun_l9_n489(x)
+ else
+ fun_l9_n347(x)
+ end
+end
+
+def fun_l8_n740(x)
+ if (x < 1)
+ fun_l9_n4(x)
+ else
+ fun_l9_n587(x)
+ end
+end
+
+def fun_l8_n741(x)
+ if (x < 1)
+ fun_l9_n949(x)
+ else
+ fun_l9_n196(x)
+ end
+end
+
+def fun_l8_n742(x)
+ if (x < 1)
+ fun_l9_n577(x)
+ else
+ fun_l9_n562(x)
+ end
+end
+
+def fun_l8_n743(x)
+ if (x < 1)
+ fun_l9_n656(x)
+ else
+ fun_l9_n685(x)
+ end
+end
+
+def fun_l8_n744(x)
+ if (x < 1)
+ fun_l9_n792(x)
+ else
+ fun_l9_n572(x)
+ end
+end
+
+def fun_l8_n745(x)
+ if (x < 1)
+ fun_l9_n318(x)
+ else
+ fun_l9_n335(x)
+ end
+end
+
+def fun_l8_n746(x)
+ if (x < 1)
+ fun_l9_n59(x)
+ else
+ fun_l9_n109(x)
+ end
+end
+
+def fun_l8_n747(x)
+ if (x < 1)
+ fun_l9_n276(x)
+ else
+ fun_l9_n567(x)
+ end
+end
+
+def fun_l8_n748(x)
+ if (x < 1)
+ fun_l9_n902(x)
+ else
+ fun_l9_n220(x)
+ end
+end
+
+def fun_l8_n749(x)
+ if (x < 1)
+ fun_l9_n208(x)
+ else
+ fun_l9_n108(x)
+ end
+end
+
+def fun_l8_n750(x)
+ if (x < 1)
+ fun_l9_n927(x)
+ else
+ fun_l9_n950(x)
+ end
+end
+
+def fun_l8_n751(x)
+ if (x < 1)
+ fun_l9_n371(x)
+ else
+ fun_l9_n72(x)
+ end
+end
+
+def fun_l8_n752(x)
+ if (x < 1)
+ fun_l9_n455(x)
+ else
+ fun_l9_n467(x)
+ end
+end
+
+def fun_l8_n753(x)
+ if (x < 1)
+ fun_l9_n344(x)
+ else
+ fun_l9_n82(x)
+ end
+end
+
+def fun_l8_n754(x)
+ if (x < 1)
+ fun_l9_n902(x)
+ else
+ fun_l9_n219(x)
+ end
+end
+
+def fun_l8_n755(x)
+ if (x < 1)
+ fun_l9_n101(x)
+ else
+ fun_l9_n523(x)
+ end
+end
+
+def fun_l8_n756(x)
+ if (x < 1)
+ fun_l9_n517(x)
+ else
+ fun_l9_n97(x)
+ end
+end
+
+def fun_l8_n757(x)
+ if (x < 1)
+ fun_l9_n571(x)
+ else
+ fun_l9_n650(x)
+ end
+end
+
+def fun_l8_n758(x)
+ if (x < 1)
+ fun_l9_n701(x)
+ else
+ fun_l9_n962(x)
+ end
+end
+
+def fun_l8_n759(x)
+ if (x < 1)
+ fun_l9_n589(x)
+ else
+ fun_l9_n808(x)
+ end
+end
+
+def fun_l8_n760(x)
+ if (x < 1)
+ fun_l9_n570(x)
+ else
+ fun_l9_n90(x)
+ end
+end
+
+def fun_l8_n761(x)
+ if (x < 1)
+ fun_l9_n792(x)
+ else
+ fun_l9_n673(x)
+ end
+end
+
+def fun_l8_n762(x)
+ if (x < 1)
+ fun_l9_n514(x)
+ else
+ fun_l9_n771(x)
+ end
+end
+
+def fun_l8_n763(x)
+ if (x < 1)
+ fun_l9_n404(x)
+ else
+ fun_l9_n264(x)
+ end
+end
+
+def fun_l8_n764(x)
+ if (x < 1)
+ fun_l9_n270(x)
+ else
+ fun_l9_n738(x)
+ end
+end
+
+def fun_l8_n765(x)
+ if (x < 1)
+ fun_l9_n915(x)
+ else
+ fun_l9_n901(x)
+ end
+end
+
+def fun_l8_n766(x)
+ if (x < 1)
+ fun_l9_n120(x)
+ else
+ fun_l9_n176(x)
+ end
+end
+
+def fun_l8_n767(x)
+ if (x < 1)
+ fun_l9_n470(x)
+ else
+ fun_l9_n837(x)
+ end
+end
+
+def fun_l8_n768(x)
+ if (x < 1)
+ fun_l9_n912(x)
+ else
+ fun_l9_n898(x)
+ end
+end
+
+def fun_l8_n769(x)
+ if (x < 1)
+ fun_l9_n76(x)
+ else
+ fun_l9_n350(x)
+ end
+end
+
+def fun_l8_n770(x)
+ if (x < 1)
+ fun_l9_n487(x)
+ else
+ fun_l9_n572(x)
+ end
+end
+
+def fun_l8_n771(x)
+ if (x < 1)
+ fun_l9_n823(x)
+ else
+ fun_l9_n815(x)
+ end
+end
+
+def fun_l8_n772(x)
+ if (x < 1)
+ fun_l9_n655(x)
+ else
+ fun_l9_n968(x)
+ end
+end
+
+def fun_l8_n773(x)
+ if (x < 1)
+ fun_l9_n824(x)
+ else
+ fun_l9_n741(x)
+ end
+end
+
+def fun_l8_n774(x)
+ if (x < 1)
+ fun_l9_n143(x)
+ else
+ fun_l9_n641(x)
+ end
+end
+
+def fun_l8_n775(x)
+ if (x < 1)
+ fun_l9_n985(x)
+ else
+ fun_l9_n592(x)
+ end
+end
+
+def fun_l8_n776(x)
+ if (x < 1)
+ fun_l9_n686(x)
+ else
+ fun_l9_n234(x)
+ end
+end
+
+def fun_l8_n777(x)
+ if (x < 1)
+ fun_l9_n540(x)
+ else
+ fun_l9_n794(x)
+ end
+end
+
+def fun_l8_n778(x)
+ if (x < 1)
+ fun_l9_n154(x)
+ else
+ fun_l9_n656(x)
+ end
+end
+
+def fun_l8_n779(x)
+ if (x < 1)
+ fun_l9_n836(x)
+ else
+ fun_l9_n756(x)
+ end
+end
+
+def fun_l8_n780(x)
+ if (x < 1)
+ fun_l9_n98(x)
+ else
+ fun_l9_n233(x)
+ end
+end
+
+def fun_l8_n781(x)
+ if (x < 1)
+ fun_l9_n584(x)
+ else
+ fun_l9_n398(x)
+ end
+end
+
+def fun_l8_n782(x)
+ if (x < 1)
+ fun_l9_n851(x)
+ else
+ fun_l9_n967(x)
+ end
+end
+
+def fun_l8_n783(x)
+ if (x < 1)
+ fun_l9_n868(x)
+ else
+ fun_l9_n57(x)
+ end
+end
+
+def fun_l8_n784(x)
+ if (x < 1)
+ fun_l9_n782(x)
+ else
+ fun_l9_n214(x)
+ end
+end
+
+def fun_l8_n785(x)
+ if (x < 1)
+ fun_l9_n79(x)
+ else
+ fun_l9_n489(x)
+ end
+end
+
+def fun_l8_n786(x)
+ if (x < 1)
+ fun_l9_n757(x)
+ else
+ fun_l9_n918(x)
+ end
+end
+
+def fun_l8_n787(x)
+ if (x < 1)
+ fun_l9_n985(x)
+ else
+ fun_l9_n781(x)
+ end
+end
+
+def fun_l8_n788(x)
+ if (x < 1)
+ fun_l9_n921(x)
+ else
+ fun_l9_n542(x)
+ end
+end
+
+def fun_l8_n789(x)
+ if (x < 1)
+ fun_l9_n982(x)
+ else
+ fun_l9_n834(x)
+ end
+end
+
+def fun_l8_n790(x)
+ if (x < 1)
+ fun_l9_n482(x)
+ else
+ fun_l9_n424(x)
+ end
+end
+
+def fun_l8_n791(x)
+ if (x < 1)
+ fun_l9_n289(x)
+ else
+ fun_l9_n487(x)
+ end
+end
+
+def fun_l8_n792(x)
+ if (x < 1)
+ fun_l9_n820(x)
+ else
+ fun_l9_n242(x)
+ end
+end
+
+def fun_l8_n793(x)
+ if (x < 1)
+ fun_l9_n110(x)
+ else
+ fun_l9_n356(x)
+ end
+end
+
+def fun_l8_n794(x)
+ if (x < 1)
+ fun_l9_n142(x)
+ else
+ fun_l9_n607(x)
+ end
+end
+
+def fun_l8_n795(x)
+ if (x < 1)
+ fun_l9_n21(x)
+ else
+ fun_l9_n14(x)
+ end
+end
+
+def fun_l8_n796(x)
+ if (x < 1)
+ fun_l9_n147(x)
+ else
+ fun_l9_n767(x)
+ end
+end
+
+def fun_l8_n797(x)
+ if (x < 1)
+ fun_l9_n427(x)
+ else
+ fun_l9_n854(x)
+ end
+end
+
+def fun_l8_n798(x)
+ if (x < 1)
+ fun_l9_n557(x)
+ else
+ fun_l9_n729(x)
+ end
+end
+
+def fun_l8_n799(x)
+ if (x < 1)
+ fun_l9_n150(x)
+ else
+ fun_l9_n180(x)
+ end
+end
+
+def fun_l8_n800(x)
+ if (x < 1)
+ fun_l9_n888(x)
+ else
+ fun_l9_n612(x)
+ end
+end
+
+def fun_l8_n801(x)
+ if (x < 1)
+ fun_l9_n631(x)
+ else
+ fun_l9_n370(x)
+ end
+end
+
+def fun_l8_n802(x)
+ if (x < 1)
+ fun_l9_n759(x)
+ else
+ fun_l9_n446(x)
+ end
+end
+
+def fun_l8_n803(x)
+ if (x < 1)
+ fun_l9_n182(x)
+ else
+ fun_l9_n705(x)
+ end
+end
+
+def fun_l8_n804(x)
+ if (x < 1)
+ fun_l9_n474(x)
+ else
+ fun_l9_n461(x)
+ end
+end
+
+def fun_l8_n805(x)
+ if (x < 1)
+ fun_l9_n897(x)
+ else
+ fun_l9_n935(x)
+ end
+end
+
+def fun_l8_n806(x)
+ if (x < 1)
+ fun_l9_n793(x)
+ else
+ fun_l9_n981(x)
+ end
+end
+
+def fun_l8_n807(x)
+ if (x < 1)
+ fun_l9_n124(x)
+ else
+ fun_l9_n528(x)
+ end
+end
+
+def fun_l8_n808(x)
+ if (x < 1)
+ fun_l9_n637(x)
+ else
+ fun_l9_n989(x)
+ end
+end
+
+def fun_l8_n809(x)
+ if (x < 1)
+ fun_l9_n388(x)
+ else
+ fun_l9_n196(x)
+ end
+end
+
+def fun_l8_n810(x)
+ if (x < 1)
+ fun_l9_n333(x)
+ else
+ fun_l9_n806(x)
+ end
+end
+
+def fun_l8_n811(x)
+ if (x < 1)
+ fun_l9_n541(x)
+ else
+ fun_l9_n6(x)
+ end
+end
+
+def fun_l8_n812(x)
+ if (x < 1)
+ fun_l9_n346(x)
+ else
+ fun_l9_n496(x)
+ end
+end
+
+def fun_l8_n813(x)
+ if (x < 1)
+ fun_l9_n374(x)
+ else
+ fun_l9_n739(x)
+ end
+end
+
+def fun_l8_n814(x)
+ if (x < 1)
+ fun_l9_n121(x)
+ else
+ fun_l9_n184(x)
+ end
+end
+
+def fun_l8_n815(x)
+ if (x < 1)
+ fun_l9_n460(x)
+ else
+ fun_l9_n759(x)
+ end
+end
+
+def fun_l8_n816(x)
+ if (x < 1)
+ fun_l9_n598(x)
+ else
+ fun_l9_n638(x)
+ end
+end
+
+def fun_l8_n817(x)
+ if (x < 1)
+ fun_l9_n986(x)
+ else
+ fun_l9_n658(x)
+ end
+end
+
+def fun_l8_n818(x)
+ if (x < 1)
+ fun_l9_n169(x)
+ else
+ fun_l9_n696(x)
+ end
+end
+
+def fun_l8_n819(x)
+ if (x < 1)
+ fun_l9_n885(x)
+ else
+ fun_l9_n74(x)
+ end
+end
+
+def fun_l8_n820(x)
+ if (x < 1)
+ fun_l9_n24(x)
+ else
+ fun_l9_n87(x)
+ end
+end
+
+def fun_l8_n821(x)
+ if (x < 1)
+ fun_l9_n59(x)
+ else
+ fun_l9_n843(x)
+ end
+end
+
+def fun_l8_n822(x)
+ if (x < 1)
+ fun_l9_n640(x)
+ else
+ fun_l9_n360(x)
+ end
+end
+
+def fun_l8_n823(x)
+ if (x < 1)
+ fun_l9_n355(x)
+ else
+ fun_l9_n28(x)
+ end
+end
+
+def fun_l8_n824(x)
+ if (x < 1)
+ fun_l9_n553(x)
+ else
+ fun_l9_n475(x)
+ end
+end
+
+def fun_l8_n825(x)
+ if (x < 1)
+ fun_l9_n757(x)
+ else
+ fun_l9_n790(x)
+ end
+end
+
+def fun_l8_n826(x)
+ if (x < 1)
+ fun_l9_n787(x)
+ else
+ fun_l9_n226(x)
+ end
+end
+
+def fun_l8_n827(x)
+ if (x < 1)
+ fun_l9_n622(x)
+ else
+ fun_l9_n711(x)
+ end
+end
+
+def fun_l8_n828(x)
+ if (x < 1)
+ fun_l9_n399(x)
+ else
+ fun_l9_n7(x)
+ end
+end
+
+def fun_l8_n829(x)
+ if (x < 1)
+ fun_l9_n589(x)
+ else
+ fun_l9_n276(x)
+ end
+end
+
+def fun_l8_n830(x)
+ if (x < 1)
+ fun_l9_n83(x)
+ else
+ fun_l9_n126(x)
+ end
+end
+
+def fun_l8_n831(x)
+ if (x < 1)
+ fun_l9_n576(x)
+ else
+ fun_l9_n855(x)
+ end
+end
+
+def fun_l8_n832(x)
+ if (x < 1)
+ fun_l9_n756(x)
+ else
+ fun_l9_n638(x)
+ end
+end
+
+def fun_l8_n833(x)
+ if (x < 1)
+ fun_l9_n388(x)
+ else
+ fun_l9_n154(x)
+ end
+end
+
+def fun_l8_n834(x)
+ if (x < 1)
+ fun_l9_n268(x)
+ else
+ fun_l9_n85(x)
+ end
+end
+
+def fun_l8_n835(x)
+ if (x < 1)
+ fun_l9_n32(x)
+ else
+ fun_l9_n678(x)
+ end
+end
+
+def fun_l8_n836(x)
+ if (x < 1)
+ fun_l9_n537(x)
+ else
+ fun_l9_n984(x)
+ end
+end
+
+def fun_l8_n837(x)
+ if (x < 1)
+ fun_l9_n798(x)
+ else
+ fun_l9_n221(x)
+ end
+end
+
+def fun_l8_n838(x)
+ if (x < 1)
+ fun_l9_n153(x)
+ else
+ fun_l9_n414(x)
+ end
+end
+
+def fun_l8_n839(x)
+ if (x < 1)
+ fun_l9_n904(x)
+ else
+ fun_l9_n847(x)
+ end
+end
+
+def fun_l8_n840(x)
+ if (x < 1)
+ fun_l9_n501(x)
+ else
+ fun_l9_n971(x)
+ end
+end
+
+def fun_l8_n841(x)
+ if (x < 1)
+ fun_l9_n94(x)
+ else
+ fun_l9_n719(x)
+ end
+end
+
+def fun_l8_n842(x)
+ if (x < 1)
+ fun_l9_n343(x)
+ else
+ fun_l9_n365(x)
+ end
+end
+
+def fun_l8_n843(x)
+ if (x < 1)
+ fun_l9_n541(x)
+ else
+ fun_l9_n800(x)
+ end
+end
+
+def fun_l8_n844(x)
+ if (x < 1)
+ fun_l9_n122(x)
+ else
+ fun_l9_n662(x)
+ end
+end
+
+def fun_l8_n845(x)
+ if (x < 1)
+ fun_l9_n312(x)
+ else
+ fun_l9_n688(x)
+ end
+end
+
+def fun_l8_n846(x)
+ if (x < 1)
+ fun_l9_n668(x)
+ else
+ fun_l9_n805(x)
+ end
+end
+
+def fun_l8_n847(x)
+ if (x < 1)
+ fun_l9_n785(x)
+ else
+ fun_l9_n917(x)
+ end
+end
+
+def fun_l8_n848(x)
+ if (x < 1)
+ fun_l9_n333(x)
+ else
+ fun_l9_n782(x)
+ end
+end
+
+def fun_l8_n849(x)
+ if (x < 1)
+ fun_l9_n402(x)
+ else
+ fun_l9_n398(x)
+ end
+end
+
+def fun_l8_n850(x)
+ if (x < 1)
+ fun_l9_n708(x)
+ else
+ fun_l9_n199(x)
+ end
+end
+
+def fun_l8_n851(x)
+ if (x < 1)
+ fun_l9_n950(x)
+ else
+ fun_l9_n308(x)
+ end
+end
+
+def fun_l8_n852(x)
+ if (x < 1)
+ fun_l9_n524(x)
+ else
+ fun_l9_n411(x)
+ end
+end
+
+def fun_l8_n853(x)
+ if (x < 1)
+ fun_l9_n467(x)
+ else
+ fun_l9_n807(x)
+ end
+end
+
+def fun_l8_n854(x)
+ if (x < 1)
+ fun_l9_n316(x)
+ else
+ fun_l9_n717(x)
+ end
+end
+
+def fun_l8_n855(x)
+ if (x < 1)
+ fun_l9_n955(x)
+ else
+ fun_l9_n631(x)
+ end
+end
+
+def fun_l8_n856(x)
+ if (x < 1)
+ fun_l9_n244(x)
+ else
+ fun_l9_n838(x)
+ end
+end
+
+def fun_l8_n857(x)
+ if (x < 1)
+ fun_l9_n574(x)
+ else
+ fun_l9_n720(x)
+ end
+end
+
+def fun_l8_n858(x)
+ if (x < 1)
+ fun_l9_n80(x)
+ else
+ fun_l9_n888(x)
+ end
+end
+
+def fun_l8_n859(x)
+ if (x < 1)
+ fun_l9_n675(x)
+ else
+ fun_l9_n71(x)
+ end
+end
+
+def fun_l8_n860(x)
+ if (x < 1)
+ fun_l9_n375(x)
+ else
+ fun_l9_n507(x)
+ end
+end
+
+def fun_l8_n861(x)
+ if (x < 1)
+ fun_l9_n450(x)
+ else
+ fun_l9_n705(x)
+ end
+end
+
+def fun_l8_n862(x)
+ if (x < 1)
+ fun_l9_n358(x)
+ else
+ fun_l9_n614(x)
+ end
+end
+
+def fun_l8_n863(x)
+ if (x < 1)
+ fun_l9_n690(x)
+ else
+ fun_l9_n73(x)
+ end
+end
+
+def fun_l8_n864(x)
+ if (x < 1)
+ fun_l9_n806(x)
+ else
+ fun_l9_n85(x)
+ end
+end
+
+def fun_l8_n865(x)
+ if (x < 1)
+ fun_l9_n251(x)
+ else
+ fun_l9_n657(x)
+ end
+end
+
+def fun_l8_n866(x)
+ if (x < 1)
+ fun_l9_n921(x)
+ else
+ fun_l9_n199(x)
+ end
+end
+
+def fun_l8_n867(x)
+ if (x < 1)
+ fun_l9_n265(x)
+ else
+ fun_l9_n937(x)
+ end
+end
+
+def fun_l8_n868(x)
+ if (x < 1)
+ fun_l9_n610(x)
+ else
+ fun_l9_n7(x)
+ end
+end
+
+def fun_l8_n869(x)
+ if (x < 1)
+ fun_l9_n703(x)
+ else
+ fun_l9_n74(x)
+ end
+end
+
+def fun_l8_n870(x)
+ if (x < 1)
+ fun_l9_n869(x)
+ else
+ fun_l9_n665(x)
+ end
+end
+
+def fun_l8_n871(x)
+ if (x < 1)
+ fun_l9_n808(x)
+ else
+ fun_l9_n686(x)
+ end
+end
+
+def fun_l8_n872(x)
+ if (x < 1)
+ fun_l9_n678(x)
+ else
+ fun_l9_n709(x)
+ end
+end
+
+def fun_l8_n873(x)
+ if (x < 1)
+ fun_l9_n557(x)
+ else
+ fun_l9_n63(x)
+ end
+end
+
+def fun_l8_n874(x)
+ if (x < 1)
+ fun_l9_n214(x)
+ else
+ fun_l9_n926(x)
+ end
+end
+
+def fun_l8_n875(x)
+ if (x < 1)
+ fun_l9_n218(x)
+ else
+ fun_l9_n810(x)
+ end
+end
+
+def fun_l8_n876(x)
+ if (x < 1)
+ fun_l9_n365(x)
+ else
+ fun_l9_n257(x)
+ end
+end
+
+def fun_l8_n877(x)
+ if (x < 1)
+ fun_l9_n51(x)
+ else
+ fun_l9_n68(x)
+ end
+end
+
+def fun_l8_n878(x)
+ if (x < 1)
+ fun_l9_n20(x)
+ else
+ fun_l9_n55(x)
+ end
+end
+
+def fun_l8_n879(x)
+ if (x < 1)
+ fun_l9_n686(x)
+ else
+ fun_l9_n226(x)
+ end
+end
+
+def fun_l8_n880(x)
+ if (x < 1)
+ fun_l9_n283(x)
+ else
+ fun_l9_n270(x)
+ end
+end
+
+def fun_l8_n881(x)
+ if (x < 1)
+ fun_l9_n811(x)
+ else
+ fun_l9_n820(x)
+ end
+end
+
+def fun_l8_n882(x)
+ if (x < 1)
+ fun_l9_n342(x)
+ else
+ fun_l9_n919(x)
+ end
+end
+
+def fun_l8_n883(x)
+ if (x < 1)
+ fun_l9_n515(x)
+ else
+ fun_l9_n24(x)
+ end
+end
+
+def fun_l8_n884(x)
+ if (x < 1)
+ fun_l9_n0(x)
+ else
+ fun_l9_n150(x)
+ end
+end
+
+def fun_l8_n885(x)
+ if (x < 1)
+ fun_l9_n481(x)
+ else
+ fun_l9_n65(x)
+ end
+end
+
+def fun_l8_n886(x)
+ if (x < 1)
+ fun_l9_n252(x)
+ else
+ fun_l9_n544(x)
+ end
+end
+
+def fun_l8_n887(x)
+ if (x < 1)
+ fun_l9_n635(x)
+ else
+ fun_l9_n402(x)
+ end
+end
+
+def fun_l8_n888(x)
+ if (x < 1)
+ fun_l9_n78(x)
+ else
+ fun_l9_n779(x)
+ end
+end
+
+def fun_l8_n889(x)
+ if (x < 1)
+ fun_l9_n249(x)
+ else
+ fun_l9_n331(x)
+ end
+end
+
+def fun_l8_n890(x)
+ if (x < 1)
+ fun_l9_n914(x)
+ else
+ fun_l9_n115(x)
+ end
+end
+
+def fun_l8_n891(x)
+ if (x < 1)
+ fun_l9_n832(x)
+ else
+ fun_l9_n34(x)
+ end
+end
+
+def fun_l8_n892(x)
+ if (x < 1)
+ fun_l9_n919(x)
+ else
+ fun_l9_n620(x)
+ end
+end
+
+def fun_l8_n893(x)
+ if (x < 1)
+ fun_l9_n360(x)
+ else
+ fun_l9_n189(x)
+ end
+end
+
+def fun_l8_n894(x)
+ if (x < 1)
+ fun_l9_n736(x)
+ else
+ fun_l9_n949(x)
+ end
+end
+
+def fun_l8_n895(x)
+ if (x < 1)
+ fun_l9_n56(x)
+ else
+ fun_l9_n826(x)
+ end
+end
+
+def fun_l8_n896(x)
+ if (x < 1)
+ fun_l9_n159(x)
+ else
+ fun_l9_n523(x)
+ end
+end
+
+def fun_l8_n897(x)
+ if (x < 1)
+ fun_l9_n630(x)
+ else
+ fun_l9_n601(x)
+ end
+end
+
+def fun_l8_n898(x)
+ if (x < 1)
+ fun_l9_n434(x)
+ else
+ fun_l9_n919(x)
+ end
+end
+
+def fun_l8_n899(x)
+ if (x < 1)
+ fun_l9_n872(x)
+ else
+ fun_l9_n652(x)
+ end
+end
+
+def fun_l8_n900(x)
+ if (x < 1)
+ fun_l9_n550(x)
+ else
+ fun_l9_n124(x)
+ end
+end
+
+def fun_l8_n901(x)
+ if (x < 1)
+ fun_l9_n56(x)
+ else
+ fun_l9_n422(x)
+ end
+end
+
+def fun_l8_n902(x)
+ if (x < 1)
+ fun_l9_n297(x)
+ else
+ fun_l9_n281(x)
+ end
+end
+
+def fun_l8_n903(x)
+ if (x < 1)
+ fun_l9_n764(x)
+ else
+ fun_l9_n942(x)
+ end
+end
+
+def fun_l8_n904(x)
+ if (x < 1)
+ fun_l9_n700(x)
+ else
+ fun_l9_n525(x)
+ end
+end
+
+def fun_l8_n905(x)
+ if (x < 1)
+ fun_l9_n370(x)
+ else
+ fun_l9_n871(x)
+ end
+end
+
+def fun_l8_n906(x)
+ if (x < 1)
+ fun_l9_n385(x)
+ else
+ fun_l9_n999(x)
+ end
+end
+
+def fun_l8_n907(x)
+ if (x < 1)
+ fun_l9_n63(x)
+ else
+ fun_l9_n137(x)
+ end
+end
+
+def fun_l8_n908(x)
+ if (x < 1)
+ fun_l9_n793(x)
+ else
+ fun_l9_n720(x)
+ end
+end
+
+def fun_l8_n909(x)
+ if (x < 1)
+ fun_l9_n141(x)
+ else
+ fun_l9_n838(x)
+ end
+end
+
+def fun_l8_n910(x)
+ if (x < 1)
+ fun_l9_n764(x)
+ else
+ fun_l9_n334(x)
+ end
+end
+
+def fun_l8_n911(x)
+ if (x < 1)
+ fun_l9_n429(x)
+ else
+ fun_l9_n309(x)
+ end
+end
+
+def fun_l8_n912(x)
+ if (x < 1)
+ fun_l9_n852(x)
+ else
+ fun_l9_n662(x)
+ end
+end
+
+def fun_l8_n913(x)
+ if (x < 1)
+ fun_l9_n467(x)
+ else
+ fun_l9_n817(x)
+ end
+end
+
+def fun_l8_n914(x)
+ if (x < 1)
+ fun_l9_n318(x)
+ else
+ fun_l9_n942(x)
+ end
+end
+
+def fun_l8_n915(x)
+ if (x < 1)
+ fun_l9_n442(x)
+ else
+ fun_l9_n987(x)
+ end
+end
+
+def fun_l8_n916(x)
+ if (x < 1)
+ fun_l9_n657(x)
+ else
+ fun_l9_n736(x)
+ end
+end
+
+def fun_l8_n917(x)
+ if (x < 1)
+ fun_l9_n839(x)
+ else
+ fun_l9_n897(x)
+ end
+end
+
+def fun_l8_n918(x)
+ if (x < 1)
+ fun_l9_n659(x)
+ else
+ fun_l9_n766(x)
+ end
+end
+
+def fun_l8_n919(x)
+ if (x < 1)
+ fun_l9_n523(x)
+ else
+ fun_l9_n54(x)
+ end
+end
+
+def fun_l8_n920(x)
+ if (x < 1)
+ fun_l9_n298(x)
+ else
+ fun_l9_n169(x)
+ end
+end
+
+def fun_l8_n921(x)
+ if (x < 1)
+ fun_l9_n752(x)
+ else
+ fun_l9_n281(x)
+ end
+end
+
+def fun_l8_n922(x)
+ if (x < 1)
+ fun_l9_n703(x)
+ else
+ fun_l9_n874(x)
+ end
+end
+
+def fun_l8_n923(x)
+ if (x < 1)
+ fun_l9_n218(x)
+ else
+ fun_l9_n880(x)
+ end
+end
+
+def fun_l8_n924(x)
+ if (x < 1)
+ fun_l9_n699(x)
+ else
+ fun_l9_n357(x)
+ end
+end
+
+def fun_l8_n925(x)
+ if (x < 1)
+ fun_l9_n279(x)
+ else
+ fun_l9_n300(x)
+ end
+end
+
+def fun_l8_n926(x)
+ if (x < 1)
+ fun_l9_n955(x)
+ else
+ fun_l9_n522(x)
+ end
+end
+
+def fun_l8_n927(x)
+ if (x < 1)
+ fun_l9_n943(x)
+ else
+ fun_l9_n597(x)
+ end
+end
+
+def fun_l8_n928(x)
+ if (x < 1)
+ fun_l9_n828(x)
+ else
+ fun_l9_n658(x)
+ end
+end
+
+def fun_l8_n929(x)
+ if (x < 1)
+ fun_l9_n160(x)
+ else
+ fun_l9_n536(x)
+ end
+end
+
+def fun_l8_n930(x)
+ if (x < 1)
+ fun_l9_n422(x)
+ else
+ fun_l9_n848(x)
+ end
+end
+
+def fun_l8_n931(x)
+ if (x < 1)
+ fun_l9_n66(x)
+ else
+ fun_l9_n298(x)
+ end
+end
+
+def fun_l8_n932(x)
+ if (x < 1)
+ fun_l9_n871(x)
+ else
+ fun_l9_n443(x)
+ end
+end
+
+def fun_l8_n933(x)
+ if (x < 1)
+ fun_l9_n876(x)
+ else
+ fun_l9_n459(x)
+ end
+end
+
+def fun_l8_n934(x)
+ if (x < 1)
+ fun_l9_n319(x)
+ else
+ fun_l9_n921(x)
+ end
+end
+
+def fun_l8_n935(x)
+ if (x < 1)
+ fun_l9_n741(x)
+ else
+ fun_l9_n659(x)
+ end
+end
+
+def fun_l8_n936(x)
+ if (x < 1)
+ fun_l9_n713(x)
+ else
+ fun_l9_n800(x)
+ end
+end
+
+def fun_l8_n937(x)
+ if (x < 1)
+ fun_l9_n945(x)
+ else
+ fun_l9_n548(x)
+ end
+end
+
+def fun_l8_n938(x)
+ if (x < 1)
+ fun_l9_n732(x)
+ else
+ fun_l9_n10(x)
+ end
+end
+
+def fun_l8_n939(x)
+ if (x < 1)
+ fun_l9_n5(x)
+ else
+ fun_l9_n864(x)
+ end
+end
+
+def fun_l8_n940(x)
+ if (x < 1)
+ fun_l9_n353(x)
+ else
+ fun_l9_n46(x)
+ end
+end
+
+def fun_l8_n941(x)
+ if (x < 1)
+ fun_l9_n622(x)
+ else
+ fun_l9_n430(x)
+ end
+end
+
+def fun_l8_n942(x)
+ if (x < 1)
+ fun_l9_n120(x)
+ else
+ fun_l9_n265(x)
+ end
+end
+
+def fun_l8_n943(x)
+ if (x < 1)
+ fun_l9_n272(x)
+ else
+ fun_l9_n290(x)
+ end
+end
+
+def fun_l8_n944(x)
+ if (x < 1)
+ fun_l9_n527(x)
+ else
+ fun_l9_n830(x)
+ end
+end
+
+def fun_l8_n945(x)
+ if (x < 1)
+ fun_l9_n202(x)
+ else
+ fun_l9_n597(x)
+ end
+end
+
+def fun_l8_n946(x)
+ if (x < 1)
+ fun_l9_n797(x)
+ else
+ fun_l9_n984(x)
+ end
+end
+
+def fun_l8_n947(x)
+ if (x < 1)
+ fun_l9_n3(x)
+ else
+ fun_l9_n173(x)
+ end
+end
+
+def fun_l8_n948(x)
+ if (x < 1)
+ fun_l9_n658(x)
+ else
+ fun_l9_n48(x)
+ end
+end
+
+def fun_l8_n949(x)
+ if (x < 1)
+ fun_l9_n302(x)
+ else
+ fun_l9_n549(x)
+ end
+end
+
+def fun_l8_n950(x)
+ if (x < 1)
+ fun_l9_n450(x)
+ else
+ fun_l9_n442(x)
+ end
+end
+
+def fun_l8_n951(x)
+ if (x < 1)
+ fun_l9_n32(x)
+ else
+ fun_l9_n287(x)
+ end
+end
+
+def fun_l8_n952(x)
+ if (x < 1)
+ fun_l9_n427(x)
+ else
+ fun_l9_n67(x)
+ end
+end
+
+def fun_l8_n953(x)
+ if (x < 1)
+ fun_l9_n153(x)
+ else
+ fun_l9_n748(x)
+ end
+end
+
+def fun_l8_n954(x)
+ if (x < 1)
+ fun_l9_n528(x)
+ else
+ fun_l9_n754(x)
+ end
+end
+
+def fun_l8_n955(x)
+ if (x < 1)
+ fun_l9_n722(x)
+ else
+ fun_l9_n982(x)
+ end
+end
+
+def fun_l8_n956(x)
+ if (x < 1)
+ fun_l9_n857(x)
+ else
+ fun_l9_n286(x)
+ end
+end
+
+def fun_l8_n957(x)
+ if (x < 1)
+ fun_l9_n579(x)
+ else
+ fun_l9_n830(x)
+ end
+end
+
+def fun_l8_n958(x)
+ if (x < 1)
+ fun_l9_n913(x)
+ else
+ fun_l9_n918(x)
+ end
+end
+
+def fun_l8_n959(x)
+ if (x < 1)
+ fun_l9_n575(x)
+ else
+ fun_l9_n441(x)
+ end
+end
+
+def fun_l8_n960(x)
+ if (x < 1)
+ fun_l9_n774(x)
+ else
+ fun_l9_n426(x)
+ end
+end
+
+def fun_l8_n961(x)
+ if (x < 1)
+ fun_l9_n415(x)
+ else
+ fun_l9_n720(x)
+ end
+end
+
+def fun_l8_n962(x)
+ if (x < 1)
+ fun_l9_n187(x)
+ else
+ fun_l9_n101(x)
+ end
+end
+
+def fun_l8_n963(x)
+ if (x < 1)
+ fun_l9_n146(x)
+ else
+ fun_l9_n911(x)
+ end
+end
+
+def fun_l8_n964(x)
+ if (x < 1)
+ fun_l9_n758(x)
+ else
+ fun_l9_n46(x)
+ end
+end
+
+def fun_l8_n965(x)
+ if (x < 1)
+ fun_l9_n316(x)
+ else
+ fun_l9_n874(x)
+ end
+end
+
+def fun_l8_n966(x)
+ if (x < 1)
+ fun_l9_n604(x)
+ else
+ fun_l9_n933(x)
+ end
+end
+
+def fun_l8_n967(x)
+ if (x < 1)
+ fun_l9_n185(x)
+ else
+ fun_l9_n729(x)
+ end
+end
+
+def fun_l8_n968(x)
+ if (x < 1)
+ fun_l9_n735(x)
+ else
+ fun_l9_n347(x)
+ end
+end
+
+def fun_l8_n969(x)
+ if (x < 1)
+ fun_l9_n796(x)
+ else
+ fun_l9_n163(x)
+ end
+end
+
+def fun_l8_n970(x)
+ if (x < 1)
+ fun_l9_n535(x)
+ else
+ fun_l9_n184(x)
+ end
+end
+
+def fun_l8_n971(x)
+ if (x < 1)
+ fun_l9_n919(x)
+ else
+ fun_l9_n838(x)
+ end
+end
+
+def fun_l8_n972(x)
+ if (x < 1)
+ fun_l9_n296(x)
+ else
+ fun_l9_n822(x)
+ end
+end
+
+def fun_l8_n973(x)
+ if (x < 1)
+ fun_l9_n503(x)
+ else
+ fun_l9_n979(x)
+ end
+end
+
+def fun_l8_n974(x)
+ if (x < 1)
+ fun_l9_n598(x)
+ else
+ fun_l9_n916(x)
+ end
+end
+
+def fun_l8_n975(x)
+ if (x < 1)
+ fun_l9_n119(x)
+ else
+ fun_l9_n138(x)
+ end
+end
+
+def fun_l8_n976(x)
+ if (x < 1)
+ fun_l9_n92(x)
+ else
+ fun_l9_n244(x)
+ end
+end
+
+def fun_l8_n977(x)
+ if (x < 1)
+ fun_l9_n250(x)
+ else
+ fun_l9_n496(x)
+ end
+end
+
+def fun_l8_n978(x)
+ if (x < 1)
+ fun_l9_n665(x)
+ else
+ fun_l9_n617(x)
+ end
+end
+
+def fun_l8_n979(x)
+ if (x < 1)
+ fun_l9_n212(x)
+ else
+ fun_l9_n63(x)
+ end
+end
+
+def fun_l8_n980(x)
+ if (x < 1)
+ fun_l9_n304(x)
+ else
+ fun_l9_n373(x)
+ end
+end
+
+def fun_l8_n981(x)
+ if (x < 1)
+ fun_l9_n70(x)
+ else
+ fun_l9_n194(x)
+ end
+end
+
+def fun_l8_n982(x)
+ if (x < 1)
+ fun_l9_n996(x)
+ else
+ fun_l9_n821(x)
+ end
+end
+
+def fun_l8_n983(x)
+ if (x < 1)
+ fun_l9_n109(x)
+ else
+ fun_l9_n926(x)
+ end
+end
+
+def fun_l8_n984(x)
+ if (x < 1)
+ fun_l9_n342(x)
+ else
+ fun_l9_n768(x)
+ end
+end
+
+def fun_l8_n985(x)
+ if (x < 1)
+ fun_l9_n12(x)
+ else
+ fun_l9_n55(x)
+ end
+end
+
+def fun_l8_n986(x)
+ if (x < 1)
+ fun_l9_n663(x)
+ else
+ fun_l9_n963(x)
+ end
+end
+
+def fun_l8_n987(x)
+ if (x < 1)
+ fun_l9_n108(x)
+ else
+ fun_l9_n139(x)
+ end
+end
+
+def fun_l8_n988(x)
+ if (x < 1)
+ fun_l9_n256(x)
+ else
+ fun_l9_n55(x)
+ end
+end
+
+def fun_l8_n989(x)
+ if (x < 1)
+ fun_l9_n261(x)
+ else
+ fun_l9_n962(x)
+ end
+end
+
+def fun_l8_n990(x)
+ if (x < 1)
+ fun_l9_n581(x)
+ else
+ fun_l9_n558(x)
+ end
+end
+
+def fun_l8_n991(x)
+ if (x < 1)
+ fun_l9_n379(x)
+ else
+ fun_l9_n179(x)
+ end
+end
+
+def fun_l8_n992(x)
+ if (x < 1)
+ fun_l9_n256(x)
+ else
+ fun_l9_n158(x)
+ end
+end
+
+def fun_l8_n993(x)
+ if (x < 1)
+ fun_l9_n75(x)
+ else
+ fun_l9_n669(x)
+ end
+end
+
+def fun_l8_n994(x)
+ if (x < 1)
+ fun_l9_n1(x)
+ else
+ fun_l9_n723(x)
+ end
+end
+
+def fun_l8_n995(x)
+ if (x < 1)
+ fun_l9_n52(x)
+ else
+ fun_l9_n706(x)
+ end
+end
+
+def fun_l8_n996(x)
+ if (x < 1)
+ fun_l9_n583(x)
+ else
+ fun_l9_n769(x)
+ end
+end
+
+def fun_l8_n997(x)
+ if (x < 1)
+ fun_l9_n91(x)
+ else
+ fun_l9_n86(x)
+ end
+end
+
+def fun_l8_n998(x)
+ if (x < 1)
+ fun_l9_n605(x)
+ else
+ fun_l9_n106(x)
+ end
+end
+
+def fun_l8_n999(x)
+ if (x < 1)
+ fun_l9_n634(x)
+ else
+ fun_l9_n110(x)
+ end
+end
+
+def fun_l9_n0(x)
+ if (x < 1)
+ fun_l10_n583(x)
+ else
+ fun_l10_n168(x)
+ end
+end
+
+def fun_l9_n1(x)
+ if (x < 1)
+ fun_l10_n523(x)
+ else
+ fun_l10_n486(x)
+ end
+end
+
+def fun_l9_n2(x)
+ if (x < 1)
+ fun_l10_n869(x)
+ else
+ fun_l10_n480(x)
+ end
+end
+
+def fun_l9_n3(x)
+ if (x < 1)
+ fun_l10_n227(x)
+ else
+ fun_l10_n798(x)
+ end
+end
+
+def fun_l9_n4(x)
+ if (x < 1)
+ fun_l10_n8(x)
+ else
+ fun_l10_n984(x)
+ end
+end
+
+def fun_l9_n5(x)
+ if (x < 1)
+ fun_l10_n757(x)
+ else
+ fun_l10_n791(x)
+ end
+end
+
+def fun_l9_n6(x)
+ if (x < 1)
+ fun_l10_n131(x)
+ else
+ fun_l10_n44(x)
+ end
+end
+
+def fun_l9_n7(x)
+ if (x < 1)
+ fun_l10_n292(x)
+ else
+ fun_l10_n793(x)
+ end
+end
+
+def fun_l9_n8(x)
+ if (x < 1)
+ fun_l10_n237(x)
+ else
+ fun_l10_n439(x)
+ end
+end
+
+def fun_l9_n9(x)
+ if (x < 1)
+ fun_l10_n99(x)
+ else
+ fun_l10_n914(x)
+ end
+end
+
+def fun_l9_n10(x)
+ if (x < 1)
+ fun_l10_n702(x)
+ else
+ fun_l10_n983(x)
+ end
+end
+
+def fun_l9_n11(x)
+ if (x < 1)
+ fun_l10_n843(x)
+ else
+ fun_l10_n774(x)
+ end
+end
+
+def fun_l9_n12(x)
+ if (x < 1)
+ fun_l10_n720(x)
+ else
+ fun_l10_n238(x)
+ end
+end
+
+def fun_l9_n13(x)
+ if (x < 1)
+ fun_l10_n339(x)
+ else
+ fun_l10_n613(x)
+ end
+end
+
+def fun_l9_n14(x)
+ if (x < 1)
+ fun_l10_n711(x)
+ else
+ fun_l10_n836(x)
+ end
+end
+
+def fun_l9_n15(x)
+ if (x < 1)
+ fun_l10_n542(x)
+ else
+ fun_l10_n90(x)
+ end
+end
+
+def fun_l9_n16(x)
+ if (x < 1)
+ fun_l10_n931(x)
+ else
+ fun_l10_n1(x)
+ end
+end
+
+def fun_l9_n17(x)
+ if (x < 1)
+ fun_l10_n568(x)
+ else
+ fun_l10_n397(x)
+ end
+end
+
+def fun_l9_n18(x)
+ if (x < 1)
+ fun_l10_n108(x)
+ else
+ fun_l10_n245(x)
+ end
+end
+
+def fun_l9_n19(x)
+ if (x < 1)
+ fun_l10_n413(x)
+ else
+ fun_l10_n644(x)
+ end
+end
+
+def fun_l9_n20(x)
+ if (x < 1)
+ fun_l10_n533(x)
+ else
+ fun_l10_n345(x)
+ end
+end
+
+def fun_l9_n21(x)
+ if (x < 1)
+ fun_l10_n84(x)
+ else
+ fun_l10_n821(x)
+ end
+end
+
+def fun_l9_n22(x)
+ if (x < 1)
+ fun_l10_n391(x)
+ else
+ fun_l10_n154(x)
+ end
+end
+
+def fun_l9_n23(x)
+ if (x < 1)
+ fun_l10_n591(x)
+ else
+ fun_l10_n443(x)
+ end
+end
+
+def fun_l9_n24(x)
+ if (x < 1)
+ fun_l10_n105(x)
+ else
+ fun_l10_n652(x)
+ end
+end
+
+def fun_l9_n25(x)
+ if (x < 1)
+ fun_l10_n495(x)
+ else
+ fun_l10_n185(x)
+ end
+end
+
+def fun_l9_n26(x)
+ if (x < 1)
+ fun_l10_n160(x)
+ else
+ fun_l10_n77(x)
+ end
+end
+
+def fun_l9_n27(x)
+ if (x < 1)
+ fun_l10_n307(x)
+ else
+ fun_l10_n813(x)
+ end
+end
+
+def fun_l9_n28(x)
+ if (x < 1)
+ fun_l10_n651(x)
+ else
+ fun_l10_n198(x)
+ end
+end
+
+def fun_l9_n29(x)
+ if (x < 1)
+ fun_l10_n689(x)
+ else
+ fun_l10_n995(x)
+ end
+end
+
+def fun_l9_n30(x)
+ if (x < 1)
+ fun_l10_n52(x)
+ else
+ fun_l10_n846(x)
+ end
+end
+
+def fun_l9_n31(x)
+ if (x < 1)
+ fun_l10_n151(x)
+ else
+ fun_l10_n758(x)
+ end
+end
+
+def fun_l9_n32(x)
+ if (x < 1)
+ fun_l10_n675(x)
+ else
+ fun_l10_n240(x)
+ end
+end
+
+def fun_l9_n33(x)
+ if (x < 1)
+ fun_l10_n660(x)
+ else
+ fun_l10_n826(x)
+ end
+end
+
+def fun_l9_n34(x)
+ if (x < 1)
+ fun_l10_n858(x)
+ else
+ fun_l10_n120(x)
+ end
+end
+
+def fun_l9_n35(x)
+ if (x < 1)
+ fun_l10_n28(x)
+ else
+ fun_l10_n870(x)
+ end
+end
+
+def fun_l9_n36(x)
+ if (x < 1)
+ fun_l10_n275(x)
+ else
+ fun_l10_n376(x)
+ end
+end
+
+def fun_l9_n37(x)
+ if (x < 1)
+ fun_l10_n852(x)
+ else
+ fun_l10_n413(x)
+ end
+end
+
+def fun_l9_n38(x)
+ if (x < 1)
+ fun_l10_n608(x)
+ else
+ fun_l10_n740(x)
+ end
+end
+
+def fun_l9_n39(x)
+ if (x < 1)
+ fun_l10_n856(x)
+ else
+ fun_l10_n543(x)
+ end
+end
+
+def fun_l9_n40(x)
+ if (x < 1)
+ fun_l10_n979(x)
+ else
+ fun_l10_n37(x)
+ end
+end
+
+def fun_l9_n41(x)
+ if (x < 1)
+ fun_l10_n752(x)
+ else
+ fun_l10_n94(x)
+ end
+end
+
+def fun_l9_n42(x)
+ if (x < 1)
+ fun_l10_n653(x)
+ else
+ fun_l10_n64(x)
+ end
+end
+
+def fun_l9_n43(x)
+ if (x < 1)
+ fun_l10_n860(x)
+ else
+ fun_l10_n658(x)
+ end
+end
+
+def fun_l9_n44(x)
+ if (x < 1)
+ fun_l10_n952(x)
+ else
+ fun_l10_n413(x)
+ end
+end
+
+def fun_l9_n45(x)
+ if (x < 1)
+ fun_l10_n70(x)
+ else
+ fun_l10_n297(x)
+ end
+end
+
+def fun_l9_n46(x)
+ if (x < 1)
+ fun_l10_n100(x)
+ else
+ fun_l10_n154(x)
+ end
+end
+
+def fun_l9_n47(x)
+ if (x < 1)
+ fun_l10_n746(x)
+ else
+ fun_l10_n937(x)
+ end
+end
+
+def fun_l9_n48(x)
+ if (x < 1)
+ fun_l10_n341(x)
+ else
+ fun_l10_n200(x)
+ end
+end
+
+def fun_l9_n49(x)
+ if (x < 1)
+ fun_l10_n317(x)
+ else
+ fun_l10_n607(x)
+ end
+end
+
+def fun_l9_n50(x)
+ if (x < 1)
+ fun_l10_n194(x)
+ else
+ fun_l10_n499(x)
+ end
+end
+
+def fun_l9_n51(x)
+ if (x < 1)
+ fun_l10_n936(x)
+ else
+ fun_l10_n387(x)
+ end
+end
+
+def fun_l9_n52(x)
+ if (x < 1)
+ fun_l10_n660(x)
+ else
+ fun_l10_n734(x)
+ end
+end
+
+def fun_l9_n53(x)
+ if (x < 1)
+ fun_l10_n523(x)
+ else
+ fun_l10_n532(x)
+ end
+end
+
+def fun_l9_n54(x)
+ if (x < 1)
+ fun_l10_n847(x)
+ else
+ fun_l10_n586(x)
+ end
+end
+
+def fun_l9_n55(x)
+ if (x < 1)
+ fun_l10_n378(x)
+ else
+ fun_l10_n226(x)
+ end
+end
+
+def fun_l9_n56(x)
+ if (x < 1)
+ fun_l10_n55(x)
+ else
+ fun_l10_n823(x)
+ end
+end
+
+def fun_l9_n57(x)
+ if (x < 1)
+ fun_l10_n931(x)
+ else
+ fun_l10_n268(x)
+ end
+end
+
+def fun_l9_n58(x)
+ if (x < 1)
+ fun_l10_n603(x)
+ else
+ fun_l10_n746(x)
+ end
+end
+
+def fun_l9_n59(x)
+ if (x < 1)
+ fun_l10_n174(x)
+ else
+ fun_l10_n196(x)
+ end
+end
+
+def fun_l9_n60(x)
+ if (x < 1)
+ fun_l10_n45(x)
+ else
+ fun_l10_n907(x)
+ end
+end
+
+def fun_l9_n61(x)
+ if (x < 1)
+ fun_l10_n282(x)
+ else
+ fun_l10_n478(x)
+ end
+end
+
+def fun_l9_n62(x)
+ if (x < 1)
+ fun_l10_n558(x)
+ else
+ fun_l10_n354(x)
+ end
+end
+
+def fun_l9_n63(x)
+ if (x < 1)
+ fun_l10_n729(x)
+ else
+ fun_l10_n275(x)
+ end
+end
+
+def fun_l9_n64(x)
+ if (x < 1)
+ fun_l10_n804(x)
+ else
+ fun_l10_n873(x)
+ end
+end
+
+def fun_l9_n65(x)
+ if (x < 1)
+ fun_l10_n901(x)
+ else
+ fun_l10_n684(x)
+ end
+end
+
+def fun_l9_n66(x)
+ if (x < 1)
+ fun_l10_n542(x)
+ else
+ fun_l10_n668(x)
+ end
+end
+
+def fun_l9_n67(x)
+ if (x < 1)
+ fun_l10_n112(x)
+ else
+ fun_l10_n48(x)
+ end
+end
+
+def fun_l9_n68(x)
+ if (x < 1)
+ fun_l10_n78(x)
+ else
+ fun_l10_n50(x)
+ end
+end
+
+def fun_l9_n69(x)
+ if (x < 1)
+ fun_l10_n595(x)
+ else
+ fun_l10_n163(x)
+ end
+end
+
+def fun_l9_n70(x)
+ if (x < 1)
+ fun_l10_n839(x)
+ else
+ fun_l10_n811(x)
+ end
+end
+
+def fun_l9_n71(x)
+ if (x < 1)
+ fun_l10_n704(x)
+ else
+ fun_l10_n81(x)
+ end
+end
+
+def fun_l9_n72(x)
+ if (x < 1)
+ fun_l10_n708(x)
+ else
+ fun_l10_n711(x)
+ end
+end
+
+def fun_l9_n73(x)
+ if (x < 1)
+ fun_l10_n948(x)
+ else
+ fun_l10_n397(x)
+ end
+end
+
+def fun_l9_n74(x)
+ if (x < 1)
+ fun_l10_n168(x)
+ else
+ fun_l10_n415(x)
+ end
+end
+
+def fun_l9_n75(x)
+ if (x < 1)
+ fun_l10_n191(x)
+ else
+ fun_l10_n547(x)
+ end
+end
+
+def fun_l9_n76(x)
+ if (x < 1)
+ fun_l10_n163(x)
+ else
+ fun_l10_n246(x)
+ end
+end
+
+def fun_l9_n77(x)
+ if (x < 1)
+ fun_l10_n948(x)
+ else
+ fun_l10_n80(x)
+ end
+end
+
+def fun_l9_n78(x)
+ if (x < 1)
+ fun_l10_n178(x)
+ else
+ fun_l10_n698(x)
+ end
+end
+
+def fun_l9_n79(x)
+ if (x < 1)
+ fun_l10_n150(x)
+ else
+ fun_l10_n545(x)
+ end
+end
+
+def fun_l9_n80(x)
+ if (x < 1)
+ fun_l10_n808(x)
+ else
+ fun_l10_n668(x)
+ end
+end
+
+def fun_l9_n81(x)
+ if (x < 1)
+ fun_l10_n597(x)
+ else
+ fun_l10_n908(x)
+ end
+end
+
+def fun_l9_n82(x)
+ if (x < 1)
+ fun_l10_n868(x)
+ else
+ fun_l10_n831(x)
+ end
+end
+
+def fun_l9_n83(x)
+ if (x < 1)
+ fun_l10_n432(x)
+ else
+ fun_l10_n281(x)
+ end
+end
+
+def fun_l9_n84(x)
+ if (x < 1)
+ fun_l10_n906(x)
+ else
+ fun_l10_n838(x)
+ end
+end
+
+def fun_l9_n85(x)
+ if (x < 1)
+ fun_l10_n828(x)
+ else
+ fun_l10_n876(x)
+ end
+end
+
+def fun_l9_n86(x)
+ if (x < 1)
+ fun_l10_n537(x)
+ else
+ fun_l10_n283(x)
+ end
+end
+
+def fun_l9_n87(x)
+ if (x < 1)
+ fun_l10_n108(x)
+ else
+ fun_l10_n157(x)
+ end
+end
+
+def fun_l9_n88(x)
+ if (x < 1)
+ fun_l10_n576(x)
+ else
+ fun_l10_n448(x)
+ end
+end
+
+def fun_l9_n89(x)
+ if (x < 1)
+ fun_l10_n633(x)
+ else
+ fun_l10_n43(x)
+ end
+end
+
+def fun_l9_n90(x)
+ if (x < 1)
+ fun_l10_n114(x)
+ else
+ fun_l10_n44(x)
+ end
+end
+
+def fun_l9_n91(x)
+ if (x < 1)
+ fun_l10_n656(x)
+ else
+ fun_l10_n586(x)
+ end
+end
+
+def fun_l9_n92(x)
+ if (x < 1)
+ fun_l10_n366(x)
+ else
+ fun_l10_n613(x)
+ end
+end
+
+def fun_l9_n93(x)
+ if (x < 1)
+ fun_l10_n174(x)
+ else
+ fun_l10_n250(x)
+ end
+end
+
+def fun_l9_n94(x)
+ if (x < 1)
+ fun_l10_n911(x)
+ else
+ fun_l10_n877(x)
+ end
+end
+
+def fun_l9_n95(x)
+ if (x < 1)
+ fun_l10_n940(x)
+ else
+ fun_l10_n334(x)
+ end
+end
+
+def fun_l9_n96(x)
+ if (x < 1)
+ fun_l10_n473(x)
+ else
+ fun_l10_n914(x)
+ end
+end
+
+def fun_l9_n97(x)
+ if (x < 1)
+ fun_l10_n550(x)
+ else
+ fun_l10_n80(x)
+ end
+end
+
+def fun_l9_n98(x)
+ if (x < 1)
+ fun_l10_n46(x)
+ else
+ fun_l10_n716(x)
+ end
+end
+
+def fun_l9_n99(x)
+ if (x < 1)
+ fun_l10_n294(x)
+ else
+ fun_l10_n615(x)
+ end
+end
+
+def fun_l9_n100(x)
+ if (x < 1)
+ fun_l10_n286(x)
+ else
+ fun_l10_n120(x)
+ end
+end
+
+def fun_l9_n101(x)
+ if (x < 1)
+ fun_l10_n674(x)
+ else
+ fun_l10_n498(x)
+ end
+end
+
+def fun_l9_n102(x)
+ if (x < 1)
+ fun_l10_n700(x)
+ else
+ fun_l10_n35(x)
+ end
+end
+
+def fun_l9_n103(x)
+ if (x < 1)
+ fun_l10_n225(x)
+ else
+ fun_l10_n206(x)
+ end
+end
+
+def fun_l9_n104(x)
+ if (x < 1)
+ fun_l10_n594(x)
+ else
+ fun_l10_n679(x)
+ end
+end
+
+def fun_l9_n105(x)
+ if (x < 1)
+ fun_l10_n148(x)
+ else
+ fun_l10_n449(x)
+ end
+end
+
+def fun_l9_n106(x)
+ if (x < 1)
+ fun_l10_n125(x)
+ else
+ fun_l10_n761(x)
+ end
+end
+
+def fun_l9_n107(x)
+ if (x < 1)
+ fun_l10_n642(x)
+ else
+ fun_l10_n988(x)
+ end
+end
+
+def fun_l9_n108(x)
+ if (x < 1)
+ fun_l10_n952(x)
+ else
+ fun_l10_n436(x)
+ end
+end
+
+def fun_l9_n109(x)
+ if (x < 1)
+ fun_l10_n955(x)
+ else
+ fun_l10_n380(x)
+ end
+end
+
+def fun_l9_n110(x)
+ if (x < 1)
+ fun_l10_n813(x)
+ else
+ fun_l10_n837(x)
+ end
+end
+
+def fun_l9_n111(x)
+ if (x < 1)
+ fun_l10_n471(x)
+ else
+ fun_l10_n69(x)
+ end
+end
+
+def fun_l9_n112(x)
+ if (x < 1)
+ fun_l10_n614(x)
+ else
+ fun_l10_n665(x)
+ end
+end
+
+def fun_l9_n113(x)
+ if (x < 1)
+ fun_l10_n485(x)
+ else
+ fun_l10_n276(x)
+ end
+end
+
+def fun_l9_n114(x)
+ if (x < 1)
+ fun_l10_n171(x)
+ else
+ fun_l10_n457(x)
+ end
+end
+
+def fun_l9_n115(x)
+ if (x < 1)
+ fun_l10_n106(x)
+ else
+ fun_l10_n555(x)
+ end
+end
+
+def fun_l9_n116(x)
+ if (x < 1)
+ fun_l10_n231(x)
+ else
+ fun_l10_n163(x)
+ end
+end
+
+def fun_l9_n117(x)
+ if (x < 1)
+ fun_l10_n569(x)
+ else
+ fun_l10_n345(x)
+ end
+end
+
+def fun_l9_n118(x)
+ if (x < 1)
+ fun_l10_n946(x)
+ else
+ fun_l10_n174(x)
+ end
+end
+
+def fun_l9_n119(x)
+ if (x < 1)
+ fun_l10_n716(x)
+ else
+ fun_l10_n882(x)
+ end
+end
+
+def fun_l9_n120(x)
+ if (x < 1)
+ fun_l10_n628(x)
+ else
+ fun_l10_n838(x)
+ end
+end
+
+def fun_l9_n121(x)
+ if (x < 1)
+ fun_l10_n699(x)
+ else
+ fun_l10_n384(x)
+ end
+end
+
+def fun_l9_n122(x)
+ if (x < 1)
+ fun_l10_n180(x)
+ else
+ fun_l10_n98(x)
+ end
+end
+
+def fun_l9_n123(x)
+ if (x < 1)
+ fun_l10_n177(x)
+ else
+ fun_l10_n635(x)
+ end
+end
+
+def fun_l9_n124(x)
+ if (x < 1)
+ fun_l10_n398(x)
+ else
+ fun_l10_n121(x)
+ end
+end
+
+def fun_l9_n125(x)
+ if (x < 1)
+ fun_l10_n866(x)
+ else
+ fun_l10_n595(x)
+ end
+end
+
+def fun_l9_n126(x)
+ if (x < 1)
+ fun_l10_n9(x)
+ else
+ fun_l10_n901(x)
+ end
+end
+
+def fun_l9_n127(x)
+ if (x < 1)
+ fun_l10_n579(x)
+ else
+ fun_l10_n640(x)
+ end
+end
+
+def fun_l9_n128(x)
+ if (x < 1)
+ fun_l10_n884(x)
+ else
+ fun_l10_n327(x)
+ end
+end
+
+def fun_l9_n129(x)
+ if (x < 1)
+ fun_l10_n553(x)
+ else
+ fun_l10_n73(x)
+ end
+end
+
+def fun_l9_n130(x)
+ if (x < 1)
+ fun_l10_n372(x)
+ else
+ fun_l10_n450(x)
+ end
+end
+
+def fun_l9_n131(x)
+ if (x < 1)
+ fun_l10_n748(x)
+ else
+ fun_l10_n534(x)
+ end
+end
+
+def fun_l9_n132(x)
+ if (x < 1)
+ fun_l10_n529(x)
+ else
+ fun_l10_n689(x)
+ end
+end
+
+def fun_l9_n133(x)
+ if (x < 1)
+ fun_l10_n24(x)
+ else
+ fun_l10_n677(x)
+ end
+end
+
+def fun_l9_n134(x)
+ if (x < 1)
+ fun_l10_n4(x)
+ else
+ fun_l10_n482(x)
+ end
+end
+
+def fun_l9_n135(x)
+ if (x < 1)
+ fun_l10_n314(x)
+ else
+ fun_l10_n509(x)
+ end
+end
+
+def fun_l9_n136(x)
+ if (x < 1)
+ fun_l10_n160(x)
+ else
+ fun_l10_n342(x)
+ end
+end
+
+def fun_l9_n137(x)
+ if (x < 1)
+ fun_l10_n289(x)
+ else
+ fun_l10_n910(x)
+ end
+end
+
+def fun_l9_n138(x)
+ if (x < 1)
+ fun_l10_n926(x)
+ else
+ fun_l10_n752(x)
+ end
+end
+
+def fun_l9_n139(x)
+ if (x < 1)
+ fun_l10_n303(x)
+ else
+ fun_l10_n399(x)
+ end
+end
+
+def fun_l9_n140(x)
+ if (x < 1)
+ fun_l10_n11(x)
+ else
+ fun_l10_n241(x)
+ end
+end
+
+def fun_l9_n141(x)
+ if (x < 1)
+ fun_l10_n528(x)
+ else
+ fun_l10_n727(x)
+ end
+end
+
+def fun_l9_n142(x)
+ if (x < 1)
+ fun_l10_n572(x)
+ else
+ fun_l10_n132(x)
+ end
+end
+
+def fun_l9_n143(x)
+ if (x < 1)
+ fun_l10_n858(x)
+ else
+ fun_l10_n712(x)
+ end
+end
+
+def fun_l9_n144(x)
+ if (x < 1)
+ fun_l10_n662(x)
+ else
+ fun_l10_n128(x)
+ end
+end
+
+def fun_l9_n145(x)
+ if (x < 1)
+ fun_l10_n668(x)
+ else
+ fun_l10_n483(x)
+ end
+end
+
+def fun_l9_n146(x)
+ if (x < 1)
+ fun_l10_n401(x)
+ else
+ fun_l10_n330(x)
+ end
+end
+
+def fun_l9_n147(x)
+ if (x < 1)
+ fun_l10_n103(x)
+ else
+ fun_l10_n859(x)
+ end
+end
+
+def fun_l9_n148(x)
+ if (x < 1)
+ fun_l10_n129(x)
+ else
+ fun_l10_n628(x)
+ end
+end
+
+def fun_l9_n149(x)
+ if (x < 1)
+ fun_l10_n898(x)
+ else
+ fun_l10_n984(x)
+ end
+end
+
+def fun_l9_n150(x)
+ if (x < 1)
+ fun_l10_n574(x)
+ else
+ fun_l10_n59(x)
+ end
+end
+
+def fun_l9_n151(x)
+ if (x < 1)
+ fun_l10_n759(x)
+ else
+ fun_l10_n782(x)
+ end
+end
+
+def fun_l9_n152(x)
+ if (x < 1)
+ fun_l10_n588(x)
+ else
+ fun_l10_n383(x)
+ end
+end
+
+def fun_l9_n153(x)
+ if (x < 1)
+ fun_l10_n889(x)
+ else
+ fun_l10_n628(x)
+ end
+end
+
+def fun_l9_n154(x)
+ if (x < 1)
+ fun_l10_n376(x)
+ else
+ fun_l10_n442(x)
+ end
+end
+
+def fun_l9_n155(x)
+ if (x < 1)
+ fun_l10_n497(x)
+ else
+ fun_l10_n269(x)
+ end
+end
+
+def fun_l9_n156(x)
+ if (x < 1)
+ fun_l10_n976(x)
+ else
+ fun_l10_n829(x)
+ end
+end
+
+def fun_l9_n157(x)
+ if (x < 1)
+ fun_l10_n366(x)
+ else
+ fun_l10_n416(x)
+ end
+end
+
+def fun_l9_n158(x)
+ if (x < 1)
+ fun_l10_n712(x)
+ else
+ fun_l10_n19(x)
+ end
+end
+
+def fun_l9_n159(x)
+ if (x < 1)
+ fun_l10_n151(x)
+ else
+ fun_l10_n129(x)
+ end
+end
+
+def fun_l9_n160(x)
+ if (x < 1)
+ fun_l10_n621(x)
+ else
+ fun_l10_n385(x)
+ end
+end
+
+def fun_l9_n161(x)
+ if (x < 1)
+ fun_l10_n626(x)
+ else
+ fun_l10_n686(x)
+ end
+end
+
+def fun_l9_n162(x)
+ if (x < 1)
+ fun_l10_n165(x)
+ else
+ fun_l10_n922(x)
+ end
+end
+
+def fun_l9_n163(x)
+ if (x < 1)
+ fun_l10_n670(x)
+ else
+ fun_l10_n889(x)
+ end
+end
+
+def fun_l9_n164(x)
+ if (x < 1)
+ fun_l10_n346(x)
+ else
+ fun_l10_n292(x)
+ end
+end
+
+def fun_l9_n165(x)
+ if (x < 1)
+ fun_l10_n812(x)
+ else
+ fun_l10_n799(x)
+ end
+end
+
+def fun_l9_n166(x)
+ if (x < 1)
+ fun_l10_n21(x)
+ else
+ fun_l10_n641(x)
+ end
+end
+
+def fun_l9_n167(x)
+ if (x < 1)
+ fun_l10_n268(x)
+ else
+ fun_l10_n943(x)
+ end
+end
+
+def fun_l9_n168(x)
+ if (x < 1)
+ fun_l10_n349(x)
+ else
+ fun_l10_n620(x)
+ end
+end
+
+def fun_l9_n169(x)
+ if (x < 1)
+ fun_l10_n894(x)
+ else
+ fun_l10_n625(x)
+ end
+end
+
+def fun_l9_n170(x)
+ if (x < 1)
+ fun_l10_n732(x)
+ else
+ fun_l10_n518(x)
+ end
+end
+
+def fun_l9_n171(x)
+ if (x < 1)
+ fun_l10_n272(x)
+ else
+ fun_l10_n148(x)
+ end
+end
+
+def fun_l9_n172(x)
+ if (x < 1)
+ fun_l10_n701(x)
+ else
+ fun_l10_n227(x)
+ end
+end
+
+def fun_l9_n173(x)
+ if (x < 1)
+ fun_l10_n833(x)
+ else
+ fun_l10_n853(x)
+ end
+end
+
+def fun_l9_n174(x)
+ if (x < 1)
+ fun_l10_n643(x)
+ else
+ fun_l10_n314(x)
+ end
+end
+
+def fun_l9_n175(x)
+ if (x < 1)
+ fun_l10_n217(x)
+ else
+ fun_l10_n64(x)
+ end
+end
+
+def fun_l9_n176(x)
+ if (x < 1)
+ fun_l10_n204(x)
+ else
+ fun_l10_n990(x)
+ end
+end
+
+def fun_l9_n177(x)
+ if (x < 1)
+ fun_l10_n130(x)
+ else
+ fun_l10_n829(x)
+ end
+end
+
+def fun_l9_n178(x)
+ if (x < 1)
+ fun_l10_n260(x)
+ else
+ fun_l10_n881(x)
+ end
+end
+
+def fun_l9_n179(x)
+ if (x < 1)
+ fun_l10_n728(x)
+ else
+ fun_l10_n491(x)
+ end
+end
+
+def fun_l9_n180(x)
+ if (x < 1)
+ fun_l10_n456(x)
+ else
+ fun_l10_n221(x)
+ end
+end
+
+def fun_l9_n181(x)
+ if (x < 1)
+ fun_l10_n634(x)
+ else
+ fun_l10_n166(x)
+ end
+end
+
+def fun_l9_n182(x)
+ if (x < 1)
+ fun_l10_n427(x)
+ else
+ fun_l10_n452(x)
+ end
+end
+
+def fun_l9_n183(x)
+ if (x < 1)
+ fun_l10_n754(x)
+ else
+ fun_l10_n54(x)
+ end
+end
+
+def fun_l9_n184(x)
+ if (x < 1)
+ fun_l10_n137(x)
+ else
+ fun_l10_n155(x)
+ end
+end
+
+def fun_l9_n185(x)
+ if (x < 1)
+ fun_l10_n611(x)
+ else
+ fun_l10_n573(x)
+ end
+end
+
+def fun_l9_n186(x)
+ if (x < 1)
+ fun_l10_n694(x)
+ else
+ fun_l10_n890(x)
+ end
+end
+
+def fun_l9_n187(x)
+ if (x < 1)
+ fun_l10_n533(x)
+ else
+ fun_l10_n102(x)
+ end
+end
+
+def fun_l9_n188(x)
+ if (x < 1)
+ fun_l10_n400(x)
+ else
+ fun_l10_n838(x)
+ end
+end
+
+def fun_l9_n189(x)
+ if (x < 1)
+ fun_l10_n783(x)
+ else
+ fun_l10_n620(x)
+ end
+end
+
+def fun_l9_n190(x)
+ if (x < 1)
+ fun_l10_n209(x)
+ else
+ fun_l10_n777(x)
+ end
+end
+
+def fun_l9_n191(x)
+ if (x < 1)
+ fun_l10_n760(x)
+ else
+ fun_l10_n299(x)
+ end
+end
+
+def fun_l9_n192(x)
+ if (x < 1)
+ fun_l10_n306(x)
+ else
+ fun_l10_n509(x)
+ end
+end
+
+def fun_l9_n193(x)
+ if (x < 1)
+ fun_l10_n842(x)
+ else
+ fun_l10_n0(x)
+ end
+end
+
+def fun_l9_n194(x)
+ if (x < 1)
+ fun_l10_n620(x)
+ else
+ fun_l10_n757(x)
+ end
+end
+
+def fun_l9_n195(x)
+ if (x < 1)
+ fun_l10_n944(x)
+ else
+ fun_l10_n257(x)
+ end
+end
+
+def fun_l9_n196(x)
+ if (x < 1)
+ fun_l10_n222(x)
+ else
+ fun_l10_n11(x)
+ end
+end
+
+def fun_l9_n197(x)
+ if (x < 1)
+ fun_l10_n419(x)
+ else
+ fun_l10_n704(x)
+ end
+end
+
+def fun_l9_n198(x)
+ if (x < 1)
+ fun_l10_n656(x)
+ else
+ fun_l10_n341(x)
+ end
+end
+
+def fun_l9_n199(x)
+ if (x < 1)
+ fun_l10_n129(x)
+ else
+ fun_l10_n815(x)
+ end
+end
+
+def fun_l9_n200(x)
+ if (x < 1)
+ fun_l10_n768(x)
+ else
+ fun_l10_n924(x)
+ end
+end
+
+def fun_l9_n201(x)
+ if (x < 1)
+ fun_l10_n439(x)
+ else
+ fun_l10_n361(x)
+ end
+end
+
+def fun_l9_n202(x)
+ if (x < 1)
+ fun_l10_n421(x)
+ else
+ fun_l10_n937(x)
+ end
+end
+
+def fun_l9_n203(x)
+ if (x < 1)
+ fun_l10_n323(x)
+ else
+ fun_l10_n262(x)
+ end
+end
+
+def fun_l9_n204(x)
+ if (x < 1)
+ fun_l10_n335(x)
+ else
+ fun_l10_n87(x)
+ end
+end
+
+def fun_l9_n205(x)
+ if (x < 1)
+ fun_l10_n973(x)
+ else
+ fun_l10_n262(x)
+ end
+end
+
+def fun_l9_n206(x)
+ if (x < 1)
+ fun_l10_n494(x)
+ else
+ fun_l10_n430(x)
+ end
+end
+
+def fun_l9_n207(x)
+ if (x < 1)
+ fun_l10_n482(x)
+ else
+ fun_l10_n828(x)
+ end
+end
+
+def fun_l9_n208(x)
+ if (x < 1)
+ fun_l10_n820(x)
+ else
+ fun_l10_n646(x)
+ end
+end
+
+def fun_l9_n209(x)
+ if (x < 1)
+ fun_l10_n669(x)
+ else
+ fun_l10_n176(x)
+ end
+end
+
+def fun_l9_n210(x)
+ if (x < 1)
+ fun_l10_n165(x)
+ else
+ fun_l10_n963(x)
+ end
+end
+
+def fun_l9_n211(x)
+ if (x < 1)
+ fun_l10_n772(x)
+ else
+ fun_l10_n49(x)
+ end
+end
+
+def fun_l9_n212(x)
+ if (x < 1)
+ fun_l10_n167(x)
+ else
+ fun_l10_n598(x)
+ end
+end
+
+def fun_l9_n213(x)
+ if (x < 1)
+ fun_l10_n552(x)
+ else
+ fun_l10_n374(x)
+ end
+end
+
+def fun_l9_n214(x)
+ if (x < 1)
+ fun_l10_n39(x)
+ else
+ fun_l10_n470(x)
+ end
+end
+
+def fun_l9_n215(x)
+ if (x < 1)
+ fun_l10_n489(x)
+ else
+ fun_l10_n812(x)
+ end
+end
+
+def fun_l9_n216(x)
+ if (x < 1)
+ fun_l10_n390(x)
+ else
+ fun_l10_n928(x)
+ end
+end
+
+def fun_l9_n217(x)
+ if (x < 1)
+ fun_l10_n909(x)
+ else
+ fun_l10_n876(x)
+ end
+end
+
+def fun_l9_n218(x)
+ if (x < 1)
+ fun_l10_n781(x)
+ else
+ fun_l10_n799(x)
+ end
+end
+
+def fun_l9_n219(x)
+ if (x < 1)
+ fun_l10_n958(x)
+ else
+ fun_l10_n697(x)
+ end
+end
+
+def fun_l9_n220(x)
+ if (x < 1)
+ fun_l10_n577(x)
+ else
+ fun_l10_n667(x)
+ end
+end
+
+def fun_l9_n221(x)
+ if (x < 1)
+ fun_l10_n206(x)
+ else
+ fun_l10_n573(x)
+ end
+end
+
+def fun_l9_n222(x)
+ if (x < 1)
+ fun_l10_n389(x)
+ else
+ fun_l10_n659(x)
+ end
+end
+
+def fun_l9_n223(x)
+ if (x < 1)
+ fun_l10_n951(x)
+ else
+ fun_l10_n572(x)
+ end
+end
+
+def fun_l9_n224(x)
+ if (x < 1)
+ fun_l10_n158(x)
+ else
+ fun_l10_n500(x)
+ end
+end
+
+def fun_l9_n225(x)
+ if (x < 1)
+ fun_l10_n681(x)
+ else
+ fun_l10_n983(x)
+ end
+end
+
+def fun_l9_n226(x)
+ if (x < 1)
+ fun_l10_n987(x)
+ else
+ fun_l10_n116(x)
+ end
+end
+
+def fun_l9_n227(x)
+ if (x < 1)
+ fun_l10_n347(x)
+ else
+ fun_l10_n606(x)
+ end
+end
+
+def fun_l9_n228(x)
+ if (x < 1)
+ fun_l10_n566(x)
+ else
+ fun_l10_n77(x)
+ end
+end
+
+def fun_l9_n229(x)
+ if (x < 1)
+ fun_l10_n879(x)
+ else
+ fun_l10_n66(x)
+ end
+end
+
+def fun_l9_n230(x)
+ if (x < 1)
+ fun_l10_n355(x)
+ else
+ fun_l10_n97(x)
+ end
+end
+
+def fun_l9_n231(x)
+ if (x < 1)
+ fun_l10_n938(x)
+ else
+ fun_l10_n5(x)
+ end
+end
+
+def fun_l9_n232(x)
+ if (x < 1)
+ fun_l10_n684(x)
+ else
+ fun_l10_n528(x)
+ end
+end
+
+def fun_l9_n233(x)
+ if (x < 1)
+ fun_l10_n500(x)
+ else
+ fun_l10_n246(x)
+ end
+end
+
+def fun_l9_n234(x)
+ if (x < 1)
+ fun_l10_n610(x)
+ else
+ fun_l10_n61(x)
+ end
+end
+
+def fun_l9_n235(x)
+ if (x < 1)
+ fun_l10_n199(x)
+ else
+ fun_l10_n838(x)
+ end
+end
+
+def fun_l9_n236(x)
+ if (x < 1)
+ fun_l10_n820(x)
+ else
+ fun_l10_n633(x)
+ end
+end
+
+def fun_l9_n237(x)
+ if (x < 1)
+ fun_l10_n216(x)
+ else
+ fun_l10_n546(x)
+ end
+end
+
+def fun_l9_n238(x)
+ if (x < 1)
+ fun_l10_n555(x)
+ else
+ fun_l10_n153(x)
+ end
+end
+
+def fun_l9_n239(x)
+ if (x < 1)
+ fun_l10_n236(x)
+ else
+ fun_l10_n231(x)
+ end
+end
+
+def fun_l9_n240(x)
+ if (x < 1)
+ fun_l10_n775(x)
+ else
+ fun_l10_n823(x)
+ end
+end
+
+def fun_l9_n241(x)
+ if (x < 1)
+ fun_l10_n275(x)
+ else
+ fun_l10_n519(x)
+ end
+end
+
+def fun_l9_n242(x)
+ if (x < 1)
+ fun_l10_n239(x)
+ else
+ fun_l10_n791(x)
+ end
+end
+
+def fun_l9_n243(x)
+ if (x < 1)
+ fun_l10_n639(x)
+ else
+ fun_l10_n972(x)
+ end
+end
+
+def fun_l9_n244(x)
+ if (x < 1)
+ fun_l10_n5(x)
+ else
+ fun_l10_n510(x)
+ end
+end
+
+def fun_l9_n245(x)
+ if (x < 1)
+ fun_l10_n256(x)
+ else
+ fun_l10_n298(x)
+ end
+end
+
+def fun_l9_n246(x)
+ if (x < 1)
+ fun_l10_n139(x)
+ else
+ fun_l10_n385(x)
+ end
+end
+
+def fun_l9_n247(x)
+ if (x < 1)
+ fun_l10_n4(x)
+ else
+ fun_l10_n323(x)
+ end
+end
+
+def fun_l9_n248(x)
+ if (x < 1)
+ fun_l10_n166(x)
+ else
+ fun_l10_n539(x)
+ end
+end
+
+def fun_l9_n249(x)
+ if (x < 1)
+ fun_l10_n374(x)
+ else
+ fun_l10_n351(x)
+ end
+end
+
+def fun_l9_n250(x)
+ if (x < 1)
+ fun_l10_n650(x)
+ else
+ fun_l10_n791(x)
+ end
+end
+
+def fun_l9_n251(x)
+ if (x < 1)
+ fun_l10_n799(x)
+ else
+ fun_l10_n990(x)
+ end
+end
+
+def fun_l9_n252(x)
+ if (x < 1)
+ fun_l10_n388(x)
+ else
+ fun_l10_n887(x)
+ end
+end
+
+def fun_l9_n253(x)
+ if (x < 1)
+ fun_l10_n564(x)
+ else
+ fun_l10_n997(x)
+ end
+end
+
+def fun_l9_n254(x)
+ if (x < 1)
+ fun_l10_n580(x)
+ else
+ fun_l10_n646(x)
+ end
+end
+
+def fun_l9_n255(x)
+ if (x < 1)
+ fun_l10_n0(x)
+ else
+ fun_l10_n480(x)
+ end
+end
+
+def fun_l9_n256(x)
+ if (x < 1)
+ fun_l10_n606(x)
+ else
+ fun_l10_n48(x)
+ end
+end
+
+def fun_l9_n257(x)
+ if (x < 1)
+ fun_l10_n601(x)
+ else
+ fun_l10_n657(x)
+ end
+end
+
+def fun_l9_n258(x)
+ if (x < 1)
+ fun_l10_n419(x)
+ else
+ fun_l10_n909(x)
+ end
+end
+
+def fun_l9_n259(x)
+ if (x < 1)
+ fun_l10_n194(x)
+ else
+ fun_l10_n961(x)
+ end
+end
+
+def fun_l9_n260(x)
+ if (x < 1)
+ fun_l10_n876(x)
+ else
+ fun_l10_n345(x)
+ end
+end
+
+def fun_l9_n261(x)
+ if (x < 1)
+ fun_l10_n643(x)
+ else
+ fun_l10_n905(x)
+ end
+end
+
+def fun_l9_n262(x)
+ if (x < 1)
+ fun_l10_n105(x)
+ else
+ fun_l10_n61(x)
+ end
+end
+
+def fun_l9_n263(x)
+ if (x < 1)
+ fun_l10_n610(x)
+ else
+ fun_l10_n527(x)
+ end
+end
+
+def fun_l9_n264(x)
+ if (x < 1)
+ fun_l10_n183(x)
+ else
+ fun_l10_n51(x)
+ end
+end
+
+def fun_l9_n265(x)
+ if (x < 1)
+ fun_l10_n800(x)
+ else
+ fun_l10_n103(x)
+ end
+end
+
+def fun_l9_n266(x)
+ if (x < 1)
+ fun_l10_n501(x)
+ else
+ fun_l10_n293(x)
+ end
+end
+
+def fun_l9_n267(x)
+ if (x < 1)
+ fun_l10_n207(x)
+ else
+ fun_l10_n162(x)
+ end
+end
+
+def fun_l9_n268(x)
+ if (x < 1)
+ fun_l10_n901(x)
+ else
+ fun_l10_n914(x)
+ end
+end
+
+def fun_l9_n269(x)
+ if (x < 1)
+ fun_l10_n711(x)
+ else
+ fun_l10_n227(x)
+ end
+end
+
+def fun_l9_n270(x)
+ if (x < 1)
+ fun_l10_n445(x)
+ else
+ fun_l10_n227(x)
+ end
+end
+
+def fun_l9_n271(x)
+ if (x < 1)
+ fun_l10_n585(x)
+ else
+ fun_l10_n371(x)
+ end
+end
+
+def fun_l9_n272(x)
+ if (x < 1)
+ fun_l10_n137(x)
+ else
+ fun_l10_n678(x)
+ end
+end
+
+def fun_l9_n273(x)
+ if (x < 1)
+ fun_l10_n284(x)
+ else
+ fun_l10_n801(x)
+ end
+end
+
+def fun_l9_n274(x)
+ if (x < 1)
+ fun_l10_n829(x)
+ else
+ fun_l10_n456(x)
+ end
+end
+
+def fun_l9_n275(x)
+ if (x < 1)
+ fun_l10_n663(x)
+ else
+ fun_l10_n529(x)
+ end
+end
+
+def fun_l9_n276(x)
+ if (x < 1)
+ fun_l10_n154(x)
+ else
+ fun_l10_n421(x)
+ end
+end
+
+def fun_l9_n277(x)
+ if (x < 1)
+ fun_l10_n778(x)
+ else
+ fun_l10_n325(x)
+ end
+end
+
+def fun_l9_n278(x)
+ if (x < 1)
+ fun_l10_n179(x)
+ else
+ fun_l10_n369(x)
+ end
+end
+
+def fun_l9_n279(x)
+ if (x < 1)
+ fun_l10_n800(x)
+ else
+ fun_l10_n488(x)
+ end
+end
+
+def fun_l9_n280(x)
+ if (x < 1)
+ fun_l10_n617(x)
+ else
+ fun_l10_n1(x)
+ end
+end
+
+def fun_l9_n281(x)
+ if (x < 1)
+ fun_l10_n951(x)
+ else
+ fun_l10_n763(x)
+ end
+end
+
+def fun_l9_n282(x)
+ if (x < 1)
+ fun_l10_n537(x)
+ else
+ fun_l10_n541(x)
+ end
+end
+
+def fun_l9_n283(x)
+ if (x < 1)
+ fun_l10_n664(x)
+ else
+ fun_l10_n854(x)
+ end
+end
+
+def fun_l9_n284(x)
+ if (x < 1)
+ fun_l10_n711(x)
+ else
+ fun_l10_n767(x)
+ end
+end
+
+def fun_l9_n285(x)
+ if (x < 1)
+ fun_l10_n211(x)
+ else
+ fun_l10_n733(x)
+ end
+end
+
+def fun_l9_n286(x)
+ if (x < 1)
+ fun_l10_n524(x)
+ else
+ fun_l10_n850(x)
+ end
+end
+
+def fun_l9_n287(x)
+ if (x < 1)
+ fun_l10_n270(x)
+ else
+ fun_l10_n798(x)
+ end
+end
+
+def fun_l9_n288(x)
+ if (x < 1)
+ fun_l10_n906(x)
+ else
+ fun_l10_n408(x)
+ end
+end
+
+def fun_l9_n289(x)
+ if (x < 1)
+ fun_l10_n873(x)
+ else
+ fun_l10_n298(x)
+ end
+end
+
+def fun_l9_n290(x)
+ if (x < 1)
+ fun_l10_n535(x)
+ else
+ fun_l10_n946(x)
+ end
+end
+
+def fun_l9_n291(x)
+ if (x < 1)
+ fun_l10_n290(x)
+ else
+ fun_l10_n631(x)
+ end
+end
+
+def fun_l9_n292(x)
+ if (x < 1)
+ fun_l10_n223(x)
+ else
+ fun_l10_n165(x)
+ end
+end
+
+def fun_l9_n293(x)
+ if (x < 1)
+ fun_l10_n768(x)
+ else
+ fun_l10_n512(x)
+ end
+end
+
+def fun_l9_n294(x)
+ if (x < 1)
+ fun_l10_n133(x)
+ else
+ fun_l10_n986(x)
+ end
+end
+
+def fun_l9_n295(x)
+ if (x < 1)
+ fun_l10_n657(x)
+ else
+ fun_l10_n914(x)
+ end
+end
+
+def fun_l9_n296(x)
+ if (x < 1)
+ fun_l10_n444(x)
+ else
+ fun_l10_n490(x)
+ end
+end
+
+def fun_l9_n297(x)
+ if (x < 1)
+ fun_l10_n478(x)
+ else
+ fun_l10_n979(x)
+ end
+end
+
+def fun_l9_n298(x)
+ if (x < 1)
+ fun_l10_n994(x)
+ else
+ fun_l10_n945(x)
+ end
+end
+
+def fun_l9_n299(x)
+ if (x < 1)
+ fun_l10_n865(x)
+ else
+ fun_l10_n206(x)
+ end
+end
+
+def fun_l9_n300(x)
+ if (x < 1)
+ fun_l10_n678(x)
+ else
+ fun_l10_n103(x)
+ end
+end
+
+def fun_l9_n301(x)
+ if (x < 1)
+ fun_l10_n115(x)
+ else
+ fun_l10_n742(x)
+ end
+end
+
+def fun_l9_n302(x)
+ if (x < 1)
+ fun_l10_n677(x)
+ else
+ fun_l10_n446(x)
+ end
+end
+
+def fun_l9_n303(x)
+ if (x < 1)
+ fun_l10_n144(x)
+ else
+ fun_l10_n856(x)
+ end
+end
+
+def fun_l9_n304(x)
+ if (x < 1)
+ fun_l10_n751(x)
+ else
+ fun_l10_n989(x)
+ end
+end
+
+def fun_l9_n305(x)
+ if (x < 1)
+ fun_l10_n200(x)
+ else
+ fun_l10_n97(x)
+ end
+end
+
+def fun_l9_n306(x)
+ if (x < 1)
+ fun_l10_n685(x)
+ else
+ fun_l10_n663(x)
+ end
+end
+
+def fun_l9_n307(x)
+ if (x < 1)
+ fun_l10_n831(x)
+ else
+ fun_l10_n770(x)
+ end
+end
+
+def fun_l9_n308(x)
+ if (x < 1)
+ fun_l10_n467(x)
+ else
+ fun_l10_n715(x)
+ end
+end
+
+def fun_l9_n309(x)
+ if (x < 1)
+ fun_l10_n676(x)
+ else
+ fun_l10_n885(x)
+ end
+end
+
+def fun_l9_n310(x)
+ if (x < 1)
+ fun_l10_n382(x)
+ else
+ fun_l10_n687(x)
+ end
+end
+
+def fun_l9_n311(x)
+ if (x < 1)
+ fun_l10_n489(x)
+ else
+ fun_l10_n810(x)
+ end
+end
+
+def fun_l9_n312(x)
+ if (x < 1)
+ fun_l10_n922(x)
+ else
+ fun_l10_n81(x)
+ end
+end
+
+def fun_l9_n313(x)
+ if (x < 1)
+ fun_l10_n788(x)
+ else
+ fun_l10_n519(x)
+ end
+end
+
+def fun_l9_n314(x)
+ if (x < 1)
+ fun_l10_n830(x)
+ else
+ fun_l10_n486(x)
+ end
+end
+
+def fun_l9_n315(x)
+ if (x < 1)
+ fun_l10_n848(x)
+ else
+ fun_l10_n250(x)
+ end
+end
+
+def fun_l9_n316(x)
+ if (x < 1)
+ fun_l10_n933(x)
+ else
+ fun_l10_n268(x)
+ end
+end
+
+def fun_l9_n317(x)
+ if (x < 1)
+ fun_l10_n659(x)
+ else
+ fun_l10_n91(x)
+ end
+end
+
+def fun_l9_n318(x)
+ if (x < 1)
+ fun_l10_n417(x)
+ else
+ fun_l10_n99(x)
+ end
+end
+
+def fun_l9_n319(x)
+ if (x < 1)
+ fun_l10_n781(x)
+ else
+ fun_l10_n770(x)
+ end
+end
+
+def fun_l9_n320(x)
+ if (x < 1)
+ fun_l10_n820(x)
+ else
+ fun_l10_n836(x)
+ end
+end
+
+def fun_l9_n321(x)
+ if (x < 1)
+ fun_l10_n865(x)
+ else
+ fun_l10_n232(x)
+ end
+end
+
+def fun_l9_n322(x)
+ if (x < 1)
+ fun_l10_n793(x)
+ else
+ fun_l10_n856(x)
+ end
+end
+
+def fun_l9_n323(x)
+ if (x < 1)
+ fun_l10_n91(x)
+ else
+ fun_l10_n356(x)
+ end
+end
+
+def fun_l9_n324(x)
+ if (x < 1)
+ fun_l10_n262(x)
+ else
+ fun_l10_n776(x)
+ end
+end
+
+def fun_l9_n325(x)
+ if (x < 1)
+ fun_l10_n733(x)
+ else
+ fun_l10_n866(x)
+ end
+end
+
+def fun_l9_n326(x)
+ if (x < 1)
+ fun_l10_n798(x)
+ else
+ fun_l10_n703(x)
+ end
+end
+
+def fun_l9_n327(x)
+ if (x < 1)
+ fun_l10_n478(x)
+ else
+ fun_l10_n181(x)
+ end
+end
+
+def fun_l9_n328(x)
+ if (x < 1)
+ fun_l10_n66(x)
+ else
+ fun_l10_n736(x)
+ end
+end
+
+def fun_l9_n329(x)
+ if (x < 1)
+ fun_l10_n388(x)
+ else
+ fun_l10_n122(x)
+ end
+end
+
+def fun_l9_n330(x)
+ if (x < 1)
+ fun_l10_n382(x)
+ else
+ fun_l10_n85(x)
+ end
+end
+
+def fun_l9_n331(x)
+ if (x < 1)
+ fun_l10_n987(x)
+ else
+ fun_l10_n769(x)
+ end
+end
+
+def fun_l9_n332(x)
+ if (x < 1)
+ fun_l10_n644(x)
+ else
+ fun_l10_n230(x)
+ end
+end
+
+def fun_l9_n333(x)
+ if (x < 1)
+ fun_l10_n604(x)
+ else
+ fun_l10_n157(x)
+ end
+end
+
+def fun_l9_n334(x)
+ if (x < 1)
+ fun_l10_n50(x)
+ else
+ fun_l10_n417(x)
+ end
+end
+
+def fun_l9_n335(x)
+ if (x < 1)
+ fun_l10_n37(x)
+ else
+ fun_l10_n564(x)
+ end
+end
+
+def fun_l9_n336(x)
+ if (x < 1)
+ fun_l10_n265(x)
+ else
+ fun_l10_n330(x)
+ end
+end
+
+def fun_l9_n337(x)
+ if (x < 1)
+ fun_l10_n816(x)
+ else
+ fun_l10_n723(x)
+ end
+end
+
+def fun_l9_n338(x)
+ if (x < 1)
+ fun_l10_n583(x)
+ else
+ fun_l10_n193(x)
+ end
+end
+
+def fun_l9_n339(x)
+ if (x < 1)
+ fun_l10_n552(x)
+ else
+ fun_l10_n710(x)
+ end
+end
+
+def fun_l9_n340(x)
+ if (x < 1)
+ fun_l10_n594(x)
+ else
+ fun_l10_n323(x)
+ end
+end
+
+def fun_l9_n341(x)
+ if (x < 1)
+ fun_l10_n727(x)
+ else
+ fun_l10_n305(x)
+ end
+end
+
+def fun_l9_n342(x)
+ if (x < 1)
+ fun_l10_n621(x)
+ else
+ fun_l10_n917(x)
+ end
+end
+
+def fun_l9_n343(x)
+ if (x < 1)
+ fun_l10_n634(x)
+ else
+ fun_l10_n36(x)
+ end
+end
+
+def fun_l9_n344(x)
+ if (x < 1)
+ fun_l10_n792(x)
+ else
+ fun_l10_n438(x)
+ end
+end
+
+def fun_l9_n345(x)
+ if (x < 1)
+ fun_l10_n399(x)
+ else
+ fun_l10_n577(x)
+ end
+end
+
+def fun_l9_n346(x)
+ if (x < 1)
+ fun_l10_n110(x)
+ else
+ fun_l10_n120(x)
+ end
+end
+
+def fun_l9_n347(x)
+ if (x < 1)
+ fun_l10_n521(x)
+ else
+ fun_l10_n111(x)
+ end
+end
+
+def fun_l9_n348(x)
+ if (x < 1)
+ fun_l10_n134(x)
+ else
+ fun_l10_n49(x)
+ end
+end
+
+def fun_l9_n349(x)
+ if (x < 1)
+ fun_l10_n353(x)
+ else
+ fun_l10_n156(x)
+ end
+end
+
+def fun_l9_n350(x)
+ if (x < 1)
+ fun_l10_n532(x)
+ else
+ fun_l10_n796(x)
+ end
+end
+
+def fun_l9_n351(x)
+ if (x < 1)
+ fun_l10_n896(x)
+ else
+ fun_l10_n176(x)
+ end
+end
+
+def fun_l9_n352(x)
+ if (x < 1)
+ fun_l10_n857(x)
+ else
+ fun_l10_n798(x)
+ end
+end
+
+def fun_l9_n353(x)
+ if (x < 1)
+ fun_l10_n676(x)
+ else
+ fun_l10_n870(x)
+ end
+end
+
+def fun_l9_n354(x)
+ if (x < 1)
+ fun_l10_n806(x)
+ else
+ fun_l10_n951(x)
+ end
+end
+
+def fun_l9_n355(x)
+ if (x < 1)
+ fun_l10_n841(x)
+ else
+ fun_l10_n918(x)
+ end
+end
+
+def fun_l9_n356(x)
+ if (x < 1)
+ fun_l10_n226(x)
+ else
+ fun_l10_n514(x)
+ end
+end
+
+def fun_l9_n357(x)
+ if (x < 1)
+ fun_l10_n289(x)
+ else
+ fun_l10_n911(x)
+ end
+end
+
+def fun_l9_n358(x)
+ if (x < 1)
+ fun_l10_n697(x)
+ else
+ fun_l10_n138(x)
+ end
+end
+
+def fun_l9_n359(x)
+ if (x < 1)
+ fun_l10_n432(x)
+ else
+ fun_l10_n88(x)
+ end
+end
+
+def fun_l9_n360(x)
+ if (x < 1)
+ fun_l10_n351(x)
+ else
+ fun_l10_n968(x)
+ end
+end
+
+def fun_l9_n361(x)
+ if (x < 1)
+ fun_l10_n782(x)
+ else
+ fun_l10_n506(x)
+ end
+end
+
+def fun_l9_n362(x)
+ if (x < 1)
+ fun_l10_n875(x)
+ else
+ fun_l10_n459(x)
+ end
+end
+
+def fun_l9_n363(x)
+ if (x < 1)
+ fun_l10_n2(x)
+ else
+ fun_l10_n468(x)
+ end
+end
+
+def fun_l9_n364(x)
+ if (x < 1)
+ fun_l10_n151(x)
+ else
+ fun_l10_n538(x)
+ end
+end
+
+def fun_l9_n365(x)
+ if (x < 1)
+ fun_l10_n203(x)
+ else
+ fun_l10_n890(x)
+ end
+end
+
+def fun_l9_n366(x)
+ if (x < 1)
+ fun_l10_n612(x)
+ else
+ fun_l10_n483(x)
+ end
+end
+
+def fun_l9_n367(x)
+ if (x < 1)
+ fun_l10_n465(x)
+ else
+ fun_l10_n724(x)
+ end
+end
+
+def fun_l9_n368(x)
+ if (x < 1)
+ fun_l10_n745(x)
+ else
+ fun_l10_n92(x)
+ end
+end
+
+def fun_l9_n369(x)
+ if (x < 1)
+ fun_l10_n312(x)
+ else
+ fun_l10_n754(x)
+ end
+end
+
+def fun_l9_n370(x)
+ if (x < 1)
+ fun_l10_n432(x)
+ else
+ fun_l10_n234(x)
+ end
+end
+
+def fun_l9_n371(x)
+ if (x < 1)
+ fun_l10_n629(x)
+ else
+ fun_l10_n751(x)
+ end
+end
+
+def fun_l9_n372(x)
+ if (x < 1)
+ fun_l10_n142(x)
+ else
+ fun_l10_n381(x)
+ end
+end
+
+def fun_l9_n373(x)
+ if (x < 1)
+ fun_l10_n490(x)
+ else
+ fun_l10_n405(x)
+ end
+end
+
+def fun_l9_n374(x)
+ if (x < 1)
+ fun_l10_n197(x)
+ else
+ fun_l10_n574(x)
+ end
+end
+
+def fun_l9_n375(x)
+ if (x < 1)
+ fun_l10_n808(x)
+ else
+ fun_l10_n753(x)
+ end
+end
+
+def fun_l9_n376(x)
+ if (x < 1)
+ fun_l10_n195(x)
+ else
+ fun_l10_n186(x)
+ end
+end
+
+def fun_l9_n377(x)
+ if (x < 1)
+ fun_l10_n172(x)
+ else
+ fun_l10_n233(x)
+ end
+end
+
+def fun_l9_n378(x)
+ if (x < 1)
+ fun_l10_n723(x)
+ else
+ fun_l10_n919(x)
+ end
+end
+
+def fun_l9_n379(x)
+ if (x < 1)
+ fun_l10_n937(x)
+ else
+ fun_l10_n149(x)
+ end
+end
+
+def fun_l9_n380(x)
+ if (x < 1)
+ fun_l10_n676(x)
+ else
+ fun_l10_n502(x)
+ end
+end
+
+def fun_l9_n381(x)
+ if (x < 1)
+ fun_l10_n756(x)
+ else
+ fun_l10_n346(x)
+ end
+end
+
+def fun_l9_n382(x)
+ if (x < 1)
+ fun_l10_n477(x)
+ else
+ fun_l10_n179(x)
+ end
+end
+
+def fun_l9_n383(x)
+ if (x < 1)
+ fun_l10_n729(x)
+ else
+ fun_l10_n862(x)
+ end
+end
+
+def fun_l9_n384(x)
+ if (x < 1)
+ fun_l10_n406(x)
+ else
+ fun_l10_n145(x)
+ end
+end
+
+def fun_l9_n385(x)
+ if (x < 1)
+ fun_l10_n239(x)
+ else
+ fun_l10_n169(x)
+ end
+end
+
+def fun_l9_n386(x)
+ if (x < 1)
+ fun_l10_n596(x)
+ else
+ fun_l10_n971(x)
+ end
+end
+
+def fun_l9_n387(x)
+ if (x < 1)
+ fun_l10_n466(x)
+ else
+ fun_l10_n488(x)
+ end
+end
+
+def fun_l9_n388(x)
+ if (x < 1)
+ fun_l10_n711(x)
+ else
+ fun_l10_n553(x)
+ end
+end
+
+def fun_l9_n389(x)
+ if (x < 1)
+ fun_l10_n776(x)
+ else
+ fun_l10_n227(x)
+ end
+end
+
+def fun_l9_n390(x)
+ if (x < 1)
+ fun_l10_n872(x)
+ else
+ fun_l10_n901(x)
+ end
+end
+
+def fun_l9_n391(x)
+ if (x < 1)
+ fun_l10_n579(x)
+ else
+ fun_l10_n906(x)
+ end
+end
+
+def fun_l9_n392(x)
+ if (x < 1)
+ fun_l10_n734(x)
+ else
+ fun_l10_n195(x)
+ end
+end
+
+def fun_l9_n393(x)
+ if (x < 1)
+ fun_l10_n691(x)
+ else
+ fun_l10_n68(x)
+ end
+end
+
+def fun_l9_n394(x)
+ if (x < 1)
+ fun_l10_n446(x)
+ else
+ fun_l10_n838(x)
+ end
+end
+
+def fun_l9_n395(x)
+ if (x < 1)
+ fun_l10_n708(x)
+ else
+ fun_l10_n319(x)
+ end
+end
+
+def fun_l9_n396(x)
+ if (x < 1)
+ fun_l10_n414(x)
+ else
+ fun_l10_n152(x)
+ end
+end
+
+def fun_l9_n397(x)
+ if (x < 1)
+ fun_l10_n637(x)
+ else
+ fun_l10_n662(x)
+ end
+end
+
+def fun_l9_n398(x)
+ if (x < 1)
+ fun_l10_n990(x)
+ else
+ fun_l10_n547(x)
+ end
+end
+
+def fun_l9_n399(x)
+ if (x < 1)
+ fun_l10_n43(x)
+ else
+ fun_l10_n845(x)
+ end
+end
+
+def fun_l9_n400(x)
+ if (x < 1)
+ fun_l10_n843(x)
+ else
+ fun_l10_n876(x)
+ end
+end
+
+def fun_l9_n401(x)
+ if (x < 1)
+ fun_l10_n925(x)
+ else
+ fun_l10_n221(x)
+ end
+end
+
+def fun_l9_n402(x)
+ if (x < 1)
+ fun_l10_n420(x)
+ else
+ fun_l10_n267(x)
+ end
+end
+
+def fun_l9_n403(x)
+ if (x < 1)
+ fun_l10_n78(x)
+ else
+ fun_l10_n316(x)
+ end
+end
+
+def fun_l9_n404(x)
+ if (x < 1)
+ fun_l10_n291(x)
+ else
+ fun_l10_n614(x)
+ end
+end
+
+def fun_l9_n405(x)
+ if (x < 1)
+ fun_l10_n956(x)
+ else
+ fun_l10_n550(x)
+ end
+end
+
+def fun_l9_n406(x)
+ if (x < 1)
+ fun_l10_n232(x)
+ else
+ fun_l10_n53(x)
+ end
+end
+
+def fun_l9_n407(x)
+ if (x < 1)
+ fun_l10_n171(x)
+ else
+ fun_l10_n51(x)
+ end
+end
+
+def fun_l9_n408(x)
+ if (x < 1)
+ fun_l10_n401(x)
+ else
+ fun_l10_n932(x)
+ end
+end
+
+def fun_l9_n409(x)
+ if (x < 1)
+ fun_l10_n863(x)
+ else
+ fun_l10_n951(x)
+ end
+end
+
+def fun_l9_n410(x)
+ if (x < 1)
+ fun_l10_n64(x)
+ else
+ fun_l10_n721(x)
+ end
+end
+
+def fun_l9_n411(x)
+ if (x < 1)
+ fun_l10_n539(x)
+ else
+ fun_l10_n951(x)
+ end
+end
+
+def fun_l9_n412(x)
+ if (x < 1)
+ fun_l10_n660(x)
+ else
+ fun_l10_n852(x)
+ end
+end
+
+def fun_l9_n413(x)
+ if (x < 1)
+ fun_l10_n777(x)
+ else
+ fun_l10_n366(x)
+ end
+end
+
+def fun_l9_n414(x)
+ if (x < 1)
+ fun_l10_n695(x)
+ else
+ fun_l10_n538(x)
+ end
+end
+
+def fun_l9_n415(x)
+ if (x < 1)
+ fun_l10_n208(x)
+ else
+ fun_l10_n892(x)
+ end
+end
+
+def fun_l9_n416(x)
+ if (x < 1)
+ fun_l10_n632(x)
+ else
+ fun_l10_n463(x)
+ end
+end
+
+def fun_l9_n417(x)
+ if (x < 1)
+ fun_l10_n238(x)
+ else
+ fun_l10_n55(x)
+ end
+end
+
+def fun_l9_n418(x)
+ if (x < 1)
+ fun_l10_n276(x)
+ else
+ fun_l10_n526(x)
+ end
+end
+
+def fun_l9_n419(x)
+ if (x < 1)
+ fun_l10_n625(x)
+ else
+ fun_l10_n806(x)
+ end
+end
+
+def fun_l9_n420(x)
+ if (x < 1)
+ fun_l10_n899(x)
+ else
+ fun_l10_n594(x)
+ end
+end
+
+def fun_l9_n421(x)
+ if (x < 1)
+ fun_l10_n725(x)
+ else
+ fun_l10_n461(x)
+ end
+end
+
+def fun_l9_n422(x)
+ if (x < 1)
+ fun_l10_n187(x)
+ else
+ fun_l10_n953(x)
+ end
+end
+
+def fun_l9_n423(x)
+ if (x < 1)
+ fun_l10_n698(x)
+ else
+ fun_l10_n751(x)
+ end
+end
+
+def fun_l9_n424(x)
+ if (x < 1)
+ fun_l10_n115(x)
+ else
+ fun_l10_n321(x)
+ end
+end
+
+def fun_l9_n425(x)
+ if (x < 1)
+ fun_l10_n775(x)
+ else
+ fun_l10_n100(x)
+ end
+end
+
+def fun_l9_n426(x)
+ if (x < 1)
+ fun_l10_n177(x)
+ else
+ fun_l10_n565(x)
+ end
+end
+
+def fun_l9_n427(x)
+ if (x < 1)
+ fun_l10_n568(x)
+ else
+ fun_l10_n234(x)
+ end
+end
+
+def fun_l9_n428(x)
+ if (x < 1)
+ fun_l10_n787(x)
+ else
+ fun_l10_n815(x)
+ end
+end
+
+def fun_l9_n429(x)
+ if (x < 1)
+ fun_l10_n580(x)
+ else
+ fun_l10_n990(x)
+ end
+end
+
+def fun_l9_n430(x)
+ if (x < 1)
+ fun_l10_n680(x)
+ else
+ fun_l10_n696(x)
+ end
+end
+
+def fun_l9_n431(x)
+ if (x < 1)
+ fun_l10_n650(x)
+ else
+ fun_l10_n776(x)
+ end
+end
+
+def fun_l9_n432(x)
+ if (x < 1)
+ fun_l10_n377(x)
+ else
+ fun_l10_n232(x)
+ end
+end
+
+def fun_l9_n433(x)
+ if (x < 1)
+ fun_l10_n621(x)
+ else
+ fun_l10_n948(x)
+ end
+end
+
+def fun_l9_n434(x)
+ if (x < 1)
+ fun_l10_n126(x)
+ else
+ fun_l10_n220(x)
+ end
+end
+
+def fun_l9_n435(x)
+ if (x < 1)
+ fun_l10_n395(x)
+ else
+ fun_l10_n732(x)
+ end
+end
+
+def fun_l9_n436(x)
+ if (x < 1)
+ fun_l10_n194(x)
+ else
+ fun_l10_n159(x)
+ end
+end
+
+def fun_l9_n437(x)
+ if (x < 1)
+ fun_l10_n123(x)
+ else
+ fun_l10_n40(x)
+ end
+end
+
+def fun_l9_n438(x)
+ if (x < 1)
+ fun_l10_n241(x)
+ else
+ fun_l10_n861(x)
+ end
+end
+
+def fun_l9_n439(x)
+ if (x < 1)
+ fun_l10_n333(x)
+ else
+ fun_l10_n950(x)
+ end
+end
+
+def fun_l9_n440(x)
+ if (x < 1)
+ fun_l10_n116(x)
+ else
+ fun_l10_n832(x)
+ end
+end
+
+def fun_l9_n441(x)
+ if (x < 1)
+ fun_l10_n598(x)
+ else
+ fun_l10_n68(x)
+ end
+end
+
+def fun_l9_n442(x)
+ if (x < 1)
+ fun_l10_n234(x)
+ else
+ fun_l10_n277(x)
+ end
+end
+
+def fun_l9_n443(x)
+ if (x < 1)
+ fun_l10_n943(x)
+ else
+ fun_l10_n895(x)
+ end
+end
+
+def fun_l9_n444(x)
+ if (x < 1)
+ fun_l10_n490(x)
+ else
+ fun_l10_n512(x)
+ end
+end
+
+def fun_l9_n445(x)
+ if (x < 1)
+ fun_l10_n54(x)
+ else
+ fun_l10_n74(x)
+ end
+end
+
+def fun_l9_n446(x)
+ if (x < 1)
+ fun_l10_n214(x)
+ else
+ fun_l10_n858(x)
+ end
+end
+
+def fun_l9_n447(x)
+ if (x < 1)
+ fun_l10_n274(x)
+ else
+ fun_l10_n255(x)
+ end
+end
+
+def fun_l9_n448(x)
+ if (x < 1)
+ fun_l10_n307(x)
+ else
+ fun_l10_n197(x)
+ end
+end
+
+def fun_l9_n449(x)
+ if (x < 1)
+ fun_l10_n152(x)
+ else
+ fun_l10_n543(x)
+ end
+end
+
+def fun_l9_n450(x)
+ if (x < 1)
+ fun_l10_n773(x)
+ else
+ fun_l10_n582(x)
+ end
+end
+
+def fun_l9_n451(x)
+ if (x < 1)
+ fun_l10_n757(x)
+ else
+ fun_l10_n298(x)
+ end
+end
+
+def fun_l9_n452(x)
+ if (x < 1)
+ fun_l10_n648(x)
+ else
+ fun_l10_n826(x)
+ end
+end
+
+def fun_l9_n453(x)
+ if (x < 1)
+ fun_l10_n209(x)
+ else
+ fun_l10_n767(x)
+ end
+end
+
+def fun_l9_n454(x)
+ if (x < 1)
+ fun_l10_n448(x)
+ else
+ fun_l10_n374(x)
+ end
+end
+
+def fun_l9_n455(x)
+ if (x < 1)
+ fun_l10_n975(x)
+ else
+ fun_l10_n45(x)
+ end
+end
+
+def fun_l9_n456(x)
+ if (x < 1)
+ fun_l10_n938(x)
+ else
+ fun_l10_n354(x)
+ end
+end
+
+def fun_l9_n457(x)
+ if (x < 1)
+ fun_l10_n723(x)
+ else
+ fun_l10_n511(x)
+ end
+end
+
+def fun_l9_n458(x)
+ if (x < 1)
+ fun_l10_n864(x)
+ else
+ fun_l10_n688(x)
+ end
+end
+
+def fun_l9_n459(x)
+ if (x < 1)
+ fun_l10_n283(x)
+ else
+ fun_l10_n776(x)
+ end
+end
+
+def fun_l9_n460(x)
+ if (x < 1)
+ fun_l10_n167(x)
+ else
+ fun_l10_n639(x)
+ end
+end
+
+def fun_l9_n461(x)
+ if (x < 1)
+ fun_l10_n493(x)
+ else
+ fun_l10_n538(x)
+ end
+end
+
+def fun_l9_n462(x)
+ if (x < 1)
+ fun_l10_n392(x)
+ else
+ fun_l10_n434(x)
+ end
+end
+
+def fun_l9_n463(x)
+ if (x < 1)
+ fun_l10_n958(x)
+ else
+ fun_l10_n305(x)
+ end
+end
+
+def fun_l9_n464(x)
+ if (x < 1)
+ fun_l10_n516(x)
+ else
+ fun_l10_n375(x)
+ end
+end
+
+def fun_l9_n465(x)
+ if (x < 1)
+ fun_l10_n371(x)
+ else
+ fun_l10_n596(x)
+ end
+end
+
+def fun_l9_n466(x)
+ if (x < 1)
+ fun_l10_n435(x)
+ else
+ fun_l10_n176(x)
+ end
+end
+
+def fun_l9_n467(x)
+ if (x < 1)
+ fun_l10_n391(x)
+ else
+ fun_l10_n83(x)
+ end
+end
+
+def fun_l9_n468(x)
+ if (x < 1)
+ fun_l10_n751(x)
+ else
+ fun_l10_n632(x)
+ end
+end
+
+def fun_l9_n469(x)
+ if (x < 1)
+ fun_l10_n14(x)
+ else
+ fun_l10_n530(x)
+ end
+end
+
+def fun_l9_n470(x)
+ if (x < 1)
+ fun_l10_n663(x)
+ else
+ fun_l10_n844(x)
+ end
+end
+
+def fun_l9_n471(x)
+ if (x < 1)
+ fun_l10_n82(x)
+ else
+ fun_l10_n493(x)
+ end
+end
+
+def fun_l9_n472(x)
+ if (x < 1)
+ fun_l10_n614(x)
+ else
+ fun_l10_n277(x)
+ end
+end
+
+def fun_l9_n473(x)
+ if (x < 1)
+ fun_l10_n492(x)
+ else
+ fun_l10_n492(x)
+ end
+end
+
+def fun_l9_n474(x)
+ if (x < 1)
+ fun_l10_n440(x)
+ else
+ fun_l10_n665(x)
+ end
+end
+
+def fun_l9_n475(x)
+ if (x < 1)
+ fun_l10_n284(x)
+ else
+ fun_l10_n513(x)
+ end
+end
+
+def fun_l9_n476(x)
+ if (x < 1)
+ fun_l10_n690(x)
+ else
+ fun_l10_n507(x)
+ end
+end
+
+def fun_l9_n477(x)
+ if (x < 1)
+ fun_l10_n281(x)
+ else
+ fun_l10_n519(x)
+ end
+end
+
+def fun_l9_n478(x)
+ if (x < 1)
+ fun_l10_n903(x)
+ else
+ fun_l10_n866(x)
+ end
+end
+
+def fun_l9_n479(x)
+ if (x < 1)
+ fun_l10_n880(x)
+ else
+ fun_l10_n310(x)
+ end
+end
+
+def fun_l9_n480(x)
+ if (x < 1)
+ fun_l10_n69(x)
+ else
+ fun_l10_n227(x)
+ end
+end
+
+def fun_l9_n481(x)
+ if (x < 1)
+ fun_l10_n316(x)
+ else
+ fun_l10_n692(x)
+ end
+end
+
+def fun_l9_n482(x)
+ if (x < 1)
+ fun_l10_n875(x)
+ else
+ fun_l10_n384(x)
+ end
+end
+
+def fun_l9_n483(x)
+ if (x < 1)
+ fun_l10_n496(x)
+ else
+ fun_l10_n81(x)
+ end
+end
+
+def fun_l9_n484(x)
+ if (x < 1)
+ fun_l10_n336(x)
+ else
+ fun_l10_n193(x)
+ end
+end
+
+def fun_l9_n485(x)
+ if (x < 1)
+ fun_l10_n541(x)
+ else
+ fun_l10_n465(x)
+ end
+end
+
+def fun_l9_n486(x)
+ if (x < 1)
+ fun_l10_n197(x)
+ else
+ fun_l10_n844(x)
+ end
+end
+
+def fun_l9_n487(x)
+ if (x < 1)
+ fun_l10_n652(x)
+ else
+ fun_l10_n736(x)
+ end
+end
+
+def fun_l9_n488(x)
+ if (x < 1)
+ fun_l10_n960(x)
+ else
+ fun_l10_n912(x)
+ end
+end
+
+def fun_l9_n489(x)
+ if (x < 1)
+ fun_l10_n238(x)
+ else
+ fun_l10_n64(x)
+ end
+end
+
+def fun_l9_n490(x)
+ if (x < 1)
+ fun_l10_n505(x)
+ else
+ fun_l10_n204(x)
+ end
+end
+
+def fun_l9_n491(x)
+ if (x < 1)
+ fun_l10_n960(x)
+ else
+ fun_l10_n198(x)
+ end
+end
+
+def fun_l9_n492(x)
+ if (x < 1)
+ fun_l10_n148(x)
+ else
+ fun_l10_n669(x)
+ end
+end
+
+def fun_l9_n493(x)
+ if (x < 1)
+ fun_l10_n860(x)
+ else
+ fun_l10_n676(x)
+ end
+end
+
+def fun_l9_n494(x)
+ if (x < 1)
+ fun_l10_n77(x)
+ else
+ fun_l10_n945(x)
+ end
+end
+
+def fun_l9_n495(x)
+ if (x < 1)
+ fun_l10_n151(x)
+ else
+ fun_l10_n588(x)
+ end
+end
+
+def fun_l9_n496(x)
+ if (x < 1)
+ fun_l10_n159(x)
+ else
+ fun_l10_n727(x)
+ end
+end
+
+def fun_l9_n497(x)
+ if (x < 1)
+ fun_l10_n803(x)
+ else
+ fun_l10_n292(x)
+ end
+end
+
+def fun_l9_n498(x)
+ if (x < 1)
+ fun_l10_n308(x)
+ else
+ fun_l10_n46(x)
+ end
+end
+
+def fun_l9_n499(x)
+ if (x < 1)
+ fun_l10_n511(x)
+ else
+ fun_l10_n766(x)
+ end
+end
+
+def fun_l9_n500(x)
+ if (x < 1)
+ fun_l10_n753(x)
+ else
+ fun_l10_n235(x)
+ end
+end
+
+def fun_l9_n501(x)
+ if (x < 1)
+ fun_l10_n776(x)
+ else
+ fun_l10_n779(x)
+ end
+end
+
+def fun_l9_n502(x)
+ if (x < 1)
+ fun_l10_n114(x)
+ else
+ fun_l10_n969(x)
+ end
+end
+
+def fun_l9_n503(x)
+ if (x < 1)
+ fun_l10_n511(x)
+ else
+ fun_l10_n678(x)
+ end
+end
+
+def fun_l9_n504(x)
+ if (x < 1)
+ fun_l10_n578(x)
+ else
+ fun_l10_n689(x)
+ end
+end
+
+def fun_l9_n505(x)
+ if (x < 1)
+ fun_l10_n434(x)
+ else
+ fun_l10_n0(x)
+ end
+end
+
+def fun_l9_n506(x)
+ if (x < 1)
+ fun_l10_n121(x)
+ else
+ fun_l10_n488(x)
+ end
+end
+
+def fun_l9_n507(x)
+ if (x < 1)
+ fun_l10_n865(x)
+ else
+ fun_l10_n540(x)
+ end
+end
+
+def fun_l9_n508(x)
+ if (x < 1)
+ fun_l10_n809(x)
+ else
+ fun_l10_n764(x)
+ end
+end
+
+def fun_l9_n509(x)
+ if (x < 1)
+ fun_l10_n463(x)
+ else
+ fun_l10_n141(x)
+ end
+end
+
+def fun_l9_n510(x)
+ if (x < 1)
+ fun_l10_n442(x)
+ else
+ fun_l10_n646(x)
+ end
+end
+
+def fun_l9_n511(x)
+ if (x < 1)
+ fun_l10_n971(x)
+ else
+ fun_l10_n57(x)
+ end
+end
+
+def fun_l9_n512(x)
+ if (x < 1)
+ fun_l10_n892(x)
+ else
+ fun_l10_n612(x)
+ end
+end
+
+def fun_l9_n513(x)
+ if (x < 1)
+ fun_l10_n864(x)
+ else
+ fun_l10_n438(x)
+ end
+end
+
+def fun_l9_n514(x)
+ if (x < 1)
+ fun_l10_n504(x)
+ else
+ fun_l10_n100(x)
+ end
+end
+
+def fun_l9_n515(x)
+ if (x < 1)
+ fun_l10_n881(x)
+ else
+ fun_l10_n621(x)
+ end
+end
+
+def fun_l9_n516(x)
+ if (x < 1)
+ fun_l10_n170(x)
+ else
+ fun_l10_n435(x)
+ end
+end
+
+def fun_l9_n517(x)
+ if (x < 1)
+ fun_l10_n712(x)
+ else
+ fun_l10_n537(x)
+ end
+end
+
+def fun_l9_n518(x)
+ if (x < 1)
+ fun_l10_n369(x)
+ else
+ fun_l10_n832(x)
+ end
+end
+
+def fun_l9_n519(x)
+ if (x < 1)
+ fun_l10_n654(x)
+ else
+ fun_l10_n364(x)
+ end
+end
+
+def fun_l9_n520(x)
+ if (x < 1)
+ fun_l10_n410(x)
+ else
+ fun_l10_n10(x)
+ end
+end
+
+def fun_l9_n521(x)
+ if (x < 1)
+ fun_l10_n814(x)
+ else
+ fun_l10_n569(x)
+ end
+end
+
+def fun_l9_n522(x)
+ if (x < 1)
+ fun_l10_n787(x)
+ else
+ fun_l10_n333(x)
+ end
+end
+
+def fun_l9_n523(x)
+ if (x < 1)
+ fun_l10_n336(x)
+ else
+ fun_l10_n720(x)
+ end
+end
+
+def fun_l9_n524(x)
+ if (x < 1)
+ fun_l10_n34(x)
+ else
+ fun_l10_n643(x)
+ end
+end
+
+def fun_l9_n525(x)
+ if (x < 1)
+ fun_l10_n147(x)
+ else
+ fun_l10_n62(x)
+ end
+end
+
+def fun_l9_n526(x)
+ if (x < 1)
+ fun_l10_n431(x)
+ else
+ fun_l10_n452(x)
+ end
+end
+
+def fun_l9_n527(x)
+ if (x < 1)
+ fun_l10_n374(x)
+ else
+ fun_l10_n831(x)
+ end
+end
+
+def fun_l9_n528(x)
+ if (x < 1)
+ fun_l10_n604(x)
+ else
+ fun_l10_n274(x)
+ end
+end
+
+def fun_l9_n529(x)
+ if (x < 1)
+ fun_l10_n470(x)
+ else
+ fun_l10_n764(x)
+ end
+end
+
+def fun_l9_n530(x)
+ if (x < 1)
+ fun_l10_n552(x)
+ else
+ fun_l10_n646(x)
+ end
+end
+
+def fun_l9_n531(x)
+ if (x < 1)
+ fun_l10_n427(x)
+ else
+ fun_l10_n464(x)
+ end
+end
+
+def fun_l9_n532(x)
+ if (x < 1)
+ fun_l10_n553(x)
+ else
+ fun_l10_n605(x)
+ end
+end
+
+def fun_l9_n533(x)
+ if (x < 1)
+ fun_l10_n59(x)
+ else
+ fun_l10_n794(x)
+ end
+end
+
+def fun_l9_n534(x)
+ if (x < 1)
+ fun_l10_n168(x)
+ else
+ fun_l10_n740(x)
+ end
+end
+
+def fun_l9_n535(x)
+ if (x < 1)
+ fun_l10_n227(x)
+ else
+ fun_l10_n651(x)
+ end
+end
+
+def fun_l9_n536(x)
+ if (x < 1)
+ fun_l10_n904(x)
+ else
+ fun_l10_n552(x)
+ end
+end
+
+def fun_l9_n537(x)
+ if (x < 1)
+ fun_l10_n389(x)
+ else
+ fun_l10_n397(x)
+ end
+end
+
+def fun_l9_n538(x)
+ if (x < 1)
+ fun_l10_n622(x)
+ else
+ fun_l10_n100(x)
+ end
+end
+
+def fun_l9_n539(x)
+ if (x < 1)
+ fun_l10_n117(x)
+ else
+ fun_l10_n715(x)
+ end
+end
+
+def fun_l9_n540(x)
+ if (x < 1)
+ fun_l10_n959(x)
+ else
+ fun_l10_n391(x)
+ end
+end
+
+def fun_l9_n541(x)
+ if (x < 1)
+ fun_l10_n733(x)
+ else
+ fun_l10_n393(x)
+ end
+end
+
+def fun_l9_n542(x)
+ if (x < 1)
+ fun_l10_n171(x)
+ else
+ fun_l10_n299(x)
+ end
+end
+
+def fun_l9_n543(x)
+ if (x < 1)
+ fun_l10_n655(x)
+ else
+ fun_l10_n285(x)
+ end
+end
+
+def fun_l9_n544(x)
+ if (x < 1)
+ fun_l10_n819(x)
+ else
+ fun_l10_n817(x)
+ end
+end
+
+def fun_l9_n545(x)
+ if (x < 1)
+ fun_l10_n938(x)
+ else
+ fun_l10_n54(x)
+ end
+end
+
+def fun_l9_n546(x)
+ if (x < 1)
+ fun_l10_n712(x)
+ else
+ fun_l10_n6(x)
+ end
+end
+
+def fun_l9_n547(x)
+ if (x < 1)
+ fun_l10_n203(x)
+ else
+ fun_l10_n626(x)
+ end
+end
+
+def fun_l9_n548(x)
+ if (x < 1)
+ fun_l10_n643(x)
+ else
+ fun_l10_n761(x)
+ end
+end
+
+def fun_l9_n549(x)
+ if (x < 1)
+ fun_l10_n450(x)
+ else
+ fun_l10_n673(x)
+ end
+end
+
+def fun_l9_n550(x)
+ if (x < 1)
+ fun_l10_n496(x)
+ else
+ fun_l10_n568(x)
+ end
+end
+
+def fun_l9_n551(x)
+ if (x < 1)
+ fun_l10_n30(x)
+ else
+ fun_l10_n518(x)
+ end
+end
+
+def fun_l9_n552(x)
+ if (x < 1)
+ fun_l10_n398(x)
+ else
+ fun_l10_n858(x)
+ end
+end
+
+def fun_l9_n553(x)
+ if (x < 1)
+ fun_l10_n253(x)
+ else
+ fun_l10_n831(x)
+ end
+end
+
+def fun_l9_n554(x)
+ if (x < 1)
+ fun_l10_n493(x)
+ else
+ fun_l10_n750(x)
+ end
+end
+
+def fun_l9_n555(x)
+ if (x < 1)
+ fun_l10_n111(x)
+ else
+ fun_l10_n279(x)
+ end
+end
+
+def fun_l9_n556(x)
+ if (x < 1)
+ fun_l10_n927(x)
+ else
+ fun_l10_n793(x)
+ end
+end
+
+def fun_l9_n557(x)
+ if (x < 1)
+ fun_l10_n530(x)
+ else
+ fun_l10_n182(x)
+ end
+end
+
+def fun_l9_n558(x)
+ if (x < 1)
+ fun_l10_n434(x)
+ else
+ fun_l10_n453(x)
+ end
+end
+
+def fun_l9_n559(x)
+ if (x < 1)
+ fun_l10_n480(x)
+ else
+ fun_l10_n590(x)
+ end
+end
+
+def fun_l9_n560(x)
+ if (x < 1)
+ fun_l10_n906(x)
+ else
+ fun_l10_n280(x)
+ end
+end
+
+def fun_l9_n561(x)
+ if (x < 1)
+ fun_l10_n107(x)
+ else
+ fun_l10_n716(x)
+ end
+end
+
+def fun_l9_n562(x)
+ if (x < 1)
+ fun_l10_n15(x)
+ else
+ fun_l10_n671(x)
+ end
+end
+
+def fun_l9_n563(x)
+ if (x < 1)
+ fun_l10_n544(x)
+ else
+ fun_l10_n571(x)
+ end
+end
+
+def fun_l9_n564(x)
+ if (x < 1)
+ fun_l10_n482(x)
+ else
+ fun_l10_n885(x)
+ end
+end
+
+def fun_l9_n565(x)
+ if (x < 1)
+ fun_l10_n465(x)
+ else
+ fun_l10_n916(x)
+ end
+end
+
+def fun_l9_n566(x)
+ if (x < 1)
+ fun_l10_n413(x)
+ else
+ fun_l10_n684(x)
+ end
+end
+
+def fun_l9_n567(x)
+ if (x < 1)
+ fun_l10_n413(x)
+ else
+ fun_l10_n577(x)
+ end
+end
+
+def fun_l9_n568(x)
+ if (x < 1)
+ fun_l10_n604(x)
+ else
+ fun_l10_n899(x)
+ end
+end
+
+def fun_l9_n569(x)
+ if (x < 1)
+ fun_l10_n138(x)
+ else
+ fun_l10_n164(x)
+ end
+end
+
+def fun_l9_n570(x)
+ if (x < 1)
+ fun_l10_n993(x)
+ else
+ fun_l10_n94(x)
+ end
+end
+
+def fun_l9_n571(x)
+ if (x < 1)
+ fun_l10_n602(x)
+ else
+ fun_l10_n989(x)
+ end
+end
+
+def fun_l9_n572(x)
+ if (x < 1)
+ fun_l10_n700(x)
+ else
+ fun_l10_n308(x)
+ end
+end
+
+def fun_l9_n573(x)
+ if (x < 1)
+ fun_l10_n773(x)
+ else
+ fun_l10_n945(x)
+ end
+end
+
+def fun_l9_n574(x)
+ if (x < 1)
+ fun_l10_n148(x)
+ else
+ fun_l10_n608(x)
+ end
+end
+
+def fun_l9_n575(x)
+ if (x < 1)
+ fun_l10_n439(x)
+ else
+ fun_l10_n908(x)
+ end
+end
+
+def fun_l9_n576(x)
+ if (x < 1)
+ fun_l10_n174(x)
+ else
+ fun_l10_n872(x)
+ end
+end
+
+def fun_l9_n577(x)
+ if (x < 1)
+ fun_l10_n291(x)
+ else
+ fun_l10_n265(x)
+ end
+end
+
+def fun_l9_n578(x)
+ if (x < 1)
+ fun_l10_n425(x)
+ else
+ fun_l10_n928(x)
+ end
+end
+
+def fun_l9_n579(x)
+ if (x < 1)
+ fun_l10_n674(x)
+ else
+ fun_l10_n666(x)
+ end
+end
+
+def fun_l9_n580(x)
+ if (x < 1)
+ fun_l10_n784(x)
+ else
+ fun_l10_n147(x)
+ end
+end
+
+def fun_l9_n581(x)
+ if (x < 1)
+ fun_l10_n550(x)
+ else
+ fun_l10_n119(x)
+ end
+end
+
+def fun_l9_n582(x)
+ if (x < 1)
+ fun_l10_n953(x)
+ else
+ fun_l10_n269(x)
+ end
+end
+
+def fun_l9_n583(x)
+ if (x < 1)
+ fun_l10_n575(x)
+ else
+ fun_l10_n79(x)
+ end
+end
+
+def fun_l9_n584(x)
+ if (x < 1)
+ fun_l10_n498(x)
+ else
+ fun_l10_n1(x)
+ end
+end
+
+def fun_l9_n585(x)
+ if (x < 1)
+ fun_l10_n728(x)
+ else
+ fun_l10_n92(x)
+ end
+end
+
+def fun_l9_n586(x)
+ if (x < 1)
+ fun_l10_n344(x)
+ else
+ fun_l10_n753(x)
+ end
+end
+
+def fun_l9_n587(x)
+ if (x < 1)
+ fun_l10_n911(x)
+ else
+ fun_l10_n327(x)
+ end
+end
+
+def fun_l9_n588(x)
+ if (x < 1)
+ fun_l10_n422(x)
+ else
+ fun_l10_n224(x)
+ end
+end
+
+def fun_l9_n589(x)
+ if (x < 1)
+ fun_l10_n311(x)
+ else
+ fun_l10_n457(x)
+ end
+end
+
+def fun_l9_n590(x)
+ if (x < 1)
+ fun_l10_n705(x)
+ else
+ fun_l10_n136(x)
+ end
+end
+
+def fun_l9_n591(x)
+ if (x < 1)
+ fun_l10_n338(x)
+ else
+ fun_l10_n14(x)
+ end
+end
+
+def fun_l9_n592(x)
+ if (x < 1)
+ fun_l10_n144(x)
+ else
+ fun_l10_n671(x)
+ end
+end
+
+def fun_l9_n593(x)
+ if (x < 1)
+ fun_l10_n402(x)
+ else
+ fun_l10_n218(x)
+ end
+end
+
+def fun_l9_n594(x)
+ if (x < 1)
+ fun_l10_n854(x)
+ else
+ fun_l10_n198(x)
+ end
+end
+
+def fun_l9_n595(x)
+ if (x < 1)
+ fun_l10_n932(x)
+ else
+ fun_l10_n181(x)
+ end
+end
+
+def fun_l9_n596(x)
+ if (x < 1)
+ fun_l10_n373(x)
+ else
+ fun_l10_n937(x)
+ end
+end
+
+def fun_l9_n597(x)
+ if (x < 1)
+ fun_l10_n181(x)
+ else
+ fun_l10_n925(x)
+ end
+end
+
+def fun_l9_n598(x)
+ if (x < 1)
+ fun_l10_n263(x)
+ else
+ fun_l10_n98(x)
+ end
+end
+
+def fun_l9_n599(x)
+ if (x < 1)
+ fun_l10_n736(x)
+ else
+ fun_l10_n951(x)
+ end
+end
+
+def fun_l9_n600(x)
+ if (x < 1)
+ fun_l10_n576(x)
+ else
+ fun_l10_n998(x)
+ end
+end
+
+def fun_l9_n601(x)
+ if (x < 1)
+ fun_l10_n577(x)
+ else
+ fun_l10_n559(x)
+ end
+end
+
+def fun_l9_n602(x)
+ if (x < 1)
+ fun_l10_n143(x)
+ else
+ fun_l10_n993(x)
+ end
+end
+
+def fun_l9_n603(x)
+ if (x < 1)
+ fun_l10_n35(x)
+ else
+ fun_l10_n132(x)
+ end
+end
+
+def fun_l9_n604(x)
+ if (x < 1)
+ fun_l10_n715(x)
+ else
+ fun_l10_n933(x)
+ end
+end
+
+def fun_l9_n605(x)
+ if (x < 1)
+ fun_l10_n570(x)
+ else
+ fun_l10_n455(x)
+ end
+end
+
+def fun_l9_n606(x)
+ if (x < 1)
+ fun_l10_n225(x)
+ else
+ fun_l10_n216(x)
+ end
+end
+
+def fun_l9_n607(x)
+ if (x < 1)
+ fun_l10_n431(x)
+ else
+ fun_l10_n285(x)
+ end
+end
+
+def fun_l9_n608(x)
+ if (x < 1)
+ fun_l10_n647(x)
+ else
+ fun_l10_n221(x)
+ end
+end
+
+def fun_l9_n609(x)
+ if (x < 1)
+ fun_l10_n348(x)
+ else
+ fun_l10_n849(x)
+ end
+end
+
+def fun_l9_n610(x)
+ if (x < 1)
+ fun_l10_n301(x)
+ else
+ fun_l10_n500(x)
+ end
+end
+
+def fun_l9_n611(x)
+ if (x < 1)
+ fun_l10_n152(x)
+ else
+ fun_l10_n1(x)
+ end
+end
+
+def fun_l9_n612(x)
+ if (x < 1)
+ fun_l10_n339(x)
+ else
+ fun_l10_n577(x)
+ end
+end
+
+def fun_l9_n613(x)
+ if (x < 1)
+ fun_l10_n427(x)
+ else
+ fun_l10_n779(x)
+ end
+end
+
+def fun_l9_n614(x)
+ if (x < 1)
+ fun_l10_n60(x)
+ else
+ fun_l10_n199(x)
+ end
+end
+
+def fun_l9_n615(x)
+ if (x < 1)
+ fun_l10_n616(x)
+ else
+ fun_l10_n33(x)
+ end
+end
+
+def fun_l9_n616(x)
+ if (x < 1)
+ fun_l10_n940(x)
+ else
+ fun_l10_n981(x)
+ end
+end
+
+def fun_l9_n617(x)
+ if (x < 1)
+ fun_l10_n594(x)
+ else
+ fun_l10_n321(x)
+ end
+end
+
+def fun_l9_n618(x)
+ if (x < 1)
+ fun_l10_n233(x)
+ else
+ fun_l10_n500(x)
+ end
+end
+
+def fun_l9_n619(x)
+ if (x < 1)
+ fun_l10_n169(x)
+ else
+ fun_l10_n883(x)
+ end
+end
+
+def fun_l9_n620(x)
+ if (x < 1)
+ fun_l10_n611(x)
+ else
+ fun_l10_n345(x)
+ end
+end
+
+def fun_l9_n621(x)
+ if (x < 1)
+ fun_l10_n155(x)
+ else
+ fun_l10_n547(x)
+ end
+end
+
+def fun_l9_n622(x)
+ if (x < 1)
+ fun_l10_n244(x)
+ else
+ fun_l10_n760(x)
+ end
+end
+
+def fun_l9_n623(x)
+ if (x < 1)
+ fun_l10_n893(x)
+ else
+ fun_l10_n13(x)
+ end
+end
+
+def fun_l9_n624(x)
+ if (x < 1)
+ fun_l10_n465(x)
+ else
+ fun_l10_n276(x)
+ end
+end
+
+def fun_l9_n625(x)
+ if (x < 1)
+ fun_l10_n196(x)
+ else
+ fun_l10_n920(x)
+ end
+end
+
+def fun_l9_n626(x)
+ if (x < 1)
+ fun_l10_n235(x)
+ else
+ fun_l10_n962(x)
+ end
+end
+
+def fun_l9_n627(x)
+ if (x < 1)
+ fun_l10_n361(x)
+ else
+ fun_l10_n162(x)
+ end
+end
+
+def fun_l9_n628(x)
+ if (x < 1)
+ fun_l10_n110(x)
+ else
+ fun_l10_n574(x)
+ end
+end
+
+def fun_l9_n629(x)
+ if (x < 1)
+ fun_l10_n861(x)
+ else
+ fun_l10_n839(x)
+ end
+end
+
+def fun_l9_n630(x)
+ if (x < 1)
+ fun_l10_n386(x)
+ else
+ fun_l10_n741(x)
+ end
+end
+
+def fun_l9_n631(x)
+ if (x < 1)
+ fun_l10_n426(x)
+ else
+ fun_l10_n430(x)
+ end
+end
+
+def fun_l9_n632(x)
+ if (x < 1)
+ fun_l10_n231(x)
+ else
+ fun_l10_n353(x)
+ end
+end
+
+def fun_l9_n633(x)
+ if (x < 1)
+ fun_l10_n945(x)
+ else
+ fun_l10_n199(x)
+ end
+end
+
+def fun_l9_n634(x)
+ if (x < 1)
+ fun_l10_n607(x)
+ else
+ fun_l10_n388(x)
+ end
+end
+
+def fun_l9_n635(x)
+ if (x < 1)
+ fun_l10_n214(x)
+ else
+ fun_l10_n135(x)
+ end
+end
+
+def fun_l9_n636(x)
+ if (x < 1)
+ fun_l10_n642(x)
+ else
+ fun_l10_n522(x)
+ end
+end
+
+def fun_l9_n637(x)
+ if (x < 1)
+ fun_l10_n605(x)
+ else
+ fun_l10_n336(x)
+ end
+end
+
+def fun_l9_n638(x)
+ if (x < 1)
+ fun_l10_n719(x)
+ else
+ fun_l10_n213(x)
+ end
+end
+
+def fun_l9_n639(x)
+ if (x < 1)
+ fun_l10_n202(x)
+ else
+ fun_l10_n767(x)
+ end
+end
+
+def fun_l9_n640(x)
+ if (x < 1)
+ fun_l10_n242(x)
+ else
+ fun_l10_n596(x)
+ end
+end
+
+def fun_l9_n641(x)
+ if (x < 1)
+ fun_l10_n851(x)
+ else
+ fun_l10_n216(x)
+ end
+end
+
+def fun_l9_n642(x)
+ if (x < 1)
+ fun_l10_n645(x)
+ else
+ fun_l10_n890(x)
+ end
+end
+
+def fun_l9_n643(x)
+ if (x < 1)
+ fun_l10_n241(x)
+ else
+ fun_l10_n350(x)
+ end
+end
+
+def fun_l9_n644(x)
+ if (x < 1)
+ fun_l10_n597(x)
+ else
+ fun_l10_n350(x)
+ end
+end
+
+def fun_l9_n645(x)
+ if (x < 1)
+ fun_l10_n170(x)
+ else
+ fun_l10_n962(x)
+ end
+end
+
+def fun_l9_n646(x)
+ if (x < 1)
+ fun_l10_n229(x)
+ else
+ fun_l10_n543(x)
+ end
+end
+
+def fun_l9_n647(x)
+ if (x < 1)
+ fun_l10_n473(x)
+ else
+ fun_l10_n942(x)
+ end
+end
+
+def fun_l9_n648(x)
+ if (x < 1)
+ fun_l10_n630(x)
+ else
+ fun_l10_n630(x)
+ end
+end
+
+def fun_l9_n649(x)
+ if (x < 1)
+ fun_l10_n183(x)
+ else
+ fun_l10_n313(x)
+ end
+end
+
+def fun_l9_n650(x)
+ if (x < 1)
+ fun_l10_n951(x)
+ else
+ fun_l10_n394(x)
+ end
+end
+
+def fun_l9_n651(x)
+ if (x < 1)
+ fun_l10_n107(x)
+ else
+ fun_l10_n849(x)
+ end
+end
+
+def fun_l9_n652(x)
+ if (x < 1)
+ fun_l10_n678(x)
+ else
+ fun_l10_n768(x)
+ end
+end
+
+def fun_l9_n653(x)
+ if (x < 1)
+ fun_l10_n534(x)
+ else
+ fun_l10_n410(x)
+ end
+end
+
+def fun_l9_n654(x)
+ if (x < 1)
+ fun_l10_n694(x)
+ else
+ fun_l10_n134(x)
+ end
+end
+
+def fun_l9_n655(x)
+ if (x < 1)
+ fun_l10_n751(x)
+ else
+ fun_l10_n923(x)
+ end
+end
+
+def fun_l9_n656(x)
+ if (x < 1)
+ fun_l10_n957(x)
+ else
+ fun_l10_n489(x)
+ end
+end
+
+def fun_l9_n657(x)
+ if (x < 1)
+ fun_l10_n612(x)
+ else
+ fun_l10_n577(x)
+ end
+end
+
+def fun_l9_n658(x)
+ if (x < 1)
+ fun_l10_n814(x)
+ else
+ fun_l10_n801(x)
+ end
+end
+
+def fun_l9_n659(x)
+ if (x < 1)
+ fun_l10_n297(x)
+ else
+ fun_l10_n344(x)
+ end
+end
+
+def fun_l9_n660(x)
+ if (x < 1)
+ fun_l10_n674(x)
+ else
+ fun_l10_n780(x)
+ end
+end
+
+def fun_l9_n661(x)
+ if (x < 1)
+ fun_l10_n302(x)
+ else
+ fun_l10_n184(x)
+ end
+end
+
+def fun_l9_n662(x)
+ if (x < 1)
+ fun_l10_n308(x)
+ else
+ fun_l10_n302(x)
+ end
+end
+
+def fun_l9_n663(x)
+ if (x < 1)
+ fun_l10_n825(x)
+ else
+ fun_l10_n866(x)
+ end
+end
+
+def fun_l9_n664(x)
+ if (x < 1)
+ fun_l10_n771(x)
+ else
+ fun_l10_n141(x)
+ end
+end
+
+def fun_l9_n665(x)
+ if (x < 1)
+ fun_l10_n369(x)
+ else
+ fun_l10_n63(x)
+ end
+end
+
+def fun_l9_n666(x)
+ if (x < 1)
+ fun_l10_n198(x)
+ else
+ fun_l10_n793(x)
+ end
+end
+
+def fun_l9_n667(x)
+ if (x < 1)
+ fun_l10_n800(x)
+ else
+ fun_l10_n748(x)
+ end
+end
+
+def fun_l9_n668(x)
+ if (x < 1)
+ fun_l10_n809(x)
+ else
+ fun_l10_n673(x)
+ end
+end
+
+def fun_l9_n669(x)
+ if (x < 1)
+ fun_l10_n438(x)
+ else
+ fun_l10_n301(x)
+ end
+end
+
+def fun_l9_n670(x)
+ if (x < 1)
+ fun_l10_n802(x)
+ else
+ fun_l10_n882(x)
+ end
+end
+
+def fun_l9_n671(x)
+ if (x < 1)
+ fun_l10_n690(x)
+ else
+ fun_l10_n524(x)
+ end
+end
+
+def fun_l9_n672(x)
+ if (x < 1)
+ fun_l10_n996(x)
+ else
+ fun_l10_n68(x)
+ end
+end
+
+def fun_l9_n673(x)
+ if (x < 1)
+ fun_l10_n773(x)
+ else
+ fun_l10_n26(x)
+ end
+end
+
+def fun_l9_n674(x)
+ if (x < 1)
+ fun_l10_n252(x)
+ else
+ fun_l10_n680(x)
+ end
+end
+
+def fun_l9_n675(x)
+ if (x < 1)
+ fun_l10_n466(x)
+ else
+ fun_l10_n885(x)
+ end
+end
+
+def fun_l9_n676(x)
+ if (x < 1)
+ fun_l10_n746(x)
+ else
+ fun_l10_n968(x)
+ end
+end
+
+def fun_l9_n677(x)
+ if (x < 1)
+ fun_l10_n827(x)
+ else
+ fun_l10_n69(x)
+ end
+end
+
+def fun_l9_n678(x)
+ if (x < 1)
+ fun_l10_n158(x)
+ else
+ fun_l10_n780(x)
+ end
+end
+
+def fun_l9_n679(x)
+ if (x < 1)
+ fun_l10_n267(x)
+ else
+ fun_l10_n907(x)
+ end
+end
+
+def fun_l9_n680(x)
+ if (x < 1)
+ fun_l10_n378(x)
+ else
+ fun_l10_n668(x)
+ end
+end
+
+def fun_l9_n681(x)
+ if (x < 1)
+ fun_l10_n481(x)
+ else
+ fun_l10_n421(x)
+ end
+end
+
+def fun_l9_n682(x)
+ if (x < 1)
+ fun_l10_n501(x)
+ else
+ fun_l10_n277(x)
+ end
+end
+
+def fun_l9_n683(x)
+ if (x < 1)
+ fun_l10_n533(x)
+ else
+ fun_l10_n604(x)
+ end
+end
+
+def fun_l9_n684(x)
+ if (x < 1)
+ fun_l10_n483(x)
+ else
+ fun_l10_n761(x)
+ end
+end
+
+def fun_l9_n685(x)
+ if (x < 1)
+ fun_l10_n41(x)
+ else
+ fun_l10_n374(x)
+ end
+end
+
+def fun_l9_n686(x)
+ if (x < 1)
+ fun_l10_n549(x)
+ else
+ fun_l10_n319(x)
+ end
+end
+
+def fun_l9_n687(x)
+ if (x < 1)
+ fun_l10_n246(x)
+ else
+ fun_l10_n854(x)
+ end
+end
+
+def fun_l9_n688(x)
+ if (x < 1)
+ fun_l10_n634(x)
+ else
+ fun_l10_n43(x)
+ end
+end
+
+def fun_l9_n689(x)
+ if (x < 1)
+ fun_l10_n994(x)
+ else
+ fun_l10_n549(x)
+ end
+end
+
+def fun_l9_n690(x)
+ if (x < 1)
+ fun_l10_n439(x)
+ else
+ fun_l10_n560(x)
+ end
+end
+
+def fun_l9_n691(x)
+ if (x < 1)
+ fun_l10_n227(x)
+ else
+ fun_l10_n877(x)
+ end
+end
+
+def fun_l9_n692(x)
+ if (x < 1)
+ fun_l10_n644(x)
+ else
+ fun_l10_n350(x)
+ end
+end
+
+def fun_l9_n693(x)
+ if (x < 1)
+ fun_l10_n543(x)
+ else
+ fun_l10_n638(x)
+ end
+end
+
+def fun_l9_n694(x)
+ if (x < 1)
+ fun_l10_n537(x)
+ else
+ fun_l10_n187(x)
+ end
+end
+
+def fun_l9_n695(x)
+ if (x < 1)
+ fun_l10_n1(x)
+ else
+ fun_l10_n540(x)
+ end
+end
+
+def fun_l9_n696(x)
+ if (x < 1)
+ fun_l10_n306(x)
+ else
+ fun_l10_n290(x)
+ end
+end
+
+def fun_l9_n697(x)
+ if (x < 1)
+ fun_l10_n140(x)
+ else
+ fun_l10_n72(x)
+ end
+end
+
+def fun_l9_n698(x)
+ if (x < 1)
+ fun_l10_n43(x)
+ else
+ fun_l10_n257(x)
+ end
+end
+
+def fun_l9_n699(x)
+ if (x < 1)
+ fun_l10_n91(x)
+ else
+ fun_l10_n816(x)
+ end
+end
+
+def fun_l9_n700(x)
+ if (x < 1)
+ fun_l10_n420(x)
+ else
+ fun_l10_n763(x)
+ end
+end
+
+def fun_l9_n701(x)
+ if (x < 1)
+ fun_l10_n429(x)
+ else
+ fun_l10_n28(x)
+ end
+end
+
+def fun_l9_n702(x)
+ if (x < 1)
+ fun_l10_n615(x)
+ else
+ fun_l10_n995(x)
+ end
+end
+
+def fun_l9_n703(x)
+ if (x < 1)
+ fun_l10_n776(x)
+ else
+ fun_l10_n85(x)
+ end
+end
+
+def fun_l9_n704(x)
+ if (x < 1)
+ fun_l10_n795(x)
+ else
+ fun_l10_n542(x)
+ end
+end
+
+def fun_l9_n705(x)
+ if (x < 1)
+ fun_l10_n114(x)
+ else
+ fun_l10_n166(x)
+ end
+end
+
+def fun_l9_n706(x)
+ if (x < 1)
+ fun_l10_n99(x)
+ else
+ fun_l10_n400(x)
+ end
+end
+
+def fun_l9_n707(x)
+ if (x < 1)
+ fun_l10_n292(x)
+ else
+ fun_l10_n801(x)
+ end
+end
+
+def fun_l9_n708(x)
+ if (x < 1)
+ fun_l10_n303(x)
+ else
+ fun_l10_n380(x)
+ end
+end
+
+def fun_l9_n709(x)
+ if (x < 1)
+ fun_l10_n369(x)
+ else
+ fun_l10_n938(x)
+ end
+end
+
+def fun_l9_n710(x)
+ if (x < 1)
+ fun_l10_n652(x)
+ else
+ fun_l10_n453(x)
+ end
+end
+
+def fun_l9_n711(x)
+ if (x < 1)
+ fun_l10_n770(x)
+ else
+ fun_l10_n32(x)
+ end
+end
+
+def fun_l9_n712(x)
+ if (x < 1)
+ fun_l10_n261(x)
+ else
+ fun_l10_n485(x)
+ end
+end
+
+def fun_l9_n713(x)
+ if (x < 1)
+ fun_l10_n935(x)
+ else
+ fun_l10_n39(x)
+ end
+end
+
+def fun_l9_n714(x)
+ if (x < 1)
+ fun_l10_n332(x)
+ else
+ fun_l10_n309(x)
+ end
+end
+
+def fun_l9_n715(x)
+ if (x < 1)
+ fun_l10_n824(x)
+ else
+ fun_l10_n614(x)
+ end
+end
+
+def fun_l9_n716(x)
+ if (x < 1)
+ fun_l10_n468(x)
+ else
+ fun_l10_n341(x)
+ end
+end
+
+def fun_l9_n717(x)
+ if (x < 1)
+ fun_l10_n425(x)
+ else
+ fun_l10_n67(x)
+ end
+end
+
+def fun_l9_n718(x)
+ if (x < 1)
+ fun_l10_n199(x)
+ else
+ fun_l10_n423(x)
+ end
+end
+
+def fun_l9_n719(x)
+ if (x < 1)
+ fun_l10_n294(x)
+ else
+ fun_l10_n484(x)
+ end
+end
+
+def fun_l9_n720(x)
+ if (x < 1)
+ fun_l10_n276(x)
+ else
+ fun_l10_n799(x)
+ end
+end
+
+def fun_l9_n721(x)
+ if (x < 1)
+ fun_l10_n98(x)
+ else
+ fun_l10_n278(x)
+ end
+end
+
+def fun_l9_n722(x)
+ if (x < 1)
+ fun_l10_n689(x)
+ else
+ fun_l10_n767(x)
+ end
+end
+
+def fun_l9_n723(x)
+ if (x < 1)
+ fun_l10_n786(x)
+ else
+ fun_l10_n409(x)
+ end
+end
+
+def fun_l9_n724(x)
+ if (x < 1)
+ fun_l10_n874(x)
+ else
+ fun_l10_n413(x)
+ end
+end
+
+def fun_l9_n725(x)
+ if (x < 1)
+ fun_l10_n806(x)
+ else
+ fun_l10_n529(x)
+ end
+end
+
+def fun_l9_n726(x)
+ if (x < 1)
+ fun_l10_n847(x)
+ else
+ fun_l10_n427(x)
+ end
+end
+
+def fun_l9_n727(x)
+ if (x < 1)
+ fun_l10_n285(x)
+ else
+ fun_l10_n878(x)
+ end
+end
+
+def fun_l9_n728(x)
+ if (x < 1)
+ fun_l10_n829(x)
+ else
+ fun_l10_n341(x)
+ end
+end
+
+def fun_l9_n729(x)
+ if (x < 1)
+ fun_l10_n797(x)
+ else
+ fun_l10_n865(x)
+ end
+end
+
+def fun_l9_n730(x)
+ if (x < 1)
+ fun_l10_n689(x)
+ else
+ fun_l10_n241(x)
+ end
+end
+
+def fun_l9_n731(x)
+ if (x < 1)
+ fun_l10_n764(x)
+ else
+ fun_l10_n451(x)
+ end
+end
+
+def fun_l9_n732(x)
+ if (x < 1)
+ fun_l10_n147(x)
+ else
+ fun_l10_n998(x)
+ end
+end
+
+def fun_l9_n733(x)
+ if (x < 1)
+ fun_l10_n192(x)
+ else
+ fun_l10_n293(x)
+ end
+end
+
+def fun_l9_n734(x)
+ if (x < 1)
+ fun_l10_n207(x)
+ else
+ fun_l10_n696(x)
+ end
+end
+
+def fun_l9_n735(x)
+ if (x < 1)
+ fun_l10_n457(x)
+ else
+ fun_l10_n93(x)
+ end
+end
+
+def fun_l9_n736(x)
+ if (x < 1)
+ fun_l10_n130(x)
+ else
+ fun_l10_n512(x)
+ end
+end
+
+def fun_l9_n737(x)
+ if (x < 1)
+ fun_l10_n86(x)
+ else
+ fun_l10_n409(x)
+ end
+end
+
+def fun_l9_n738(x)
+ if (x < 1)
+ fun_l10_n783(x)
+ else
+ fun_l10_n981(x)
+ end
+end
+
+def fun_l9_n739(x)
+ if (x < 1)
+ fun_l10_n927(x)
+ else
+ fun_l10_n831(x)
+ end
+end
+
+def fun_l9_n740(x)
+ if (x < 1)
+ fun_l10_n719(x)
+ else
+ fun_l10_n422(x)
+ end
+end
+
+def fun_l9_n741(x)
+ if (x < 1)
+ fun_l10_n287(x)
+ else
+ fun_l10_n139(x)
+ end
+end
+
+def fun_l9_n742(x)
+ if (x < 1)
+ fun_l10_n533(x)
+ else
+ fun_l10_n687(x)
+ end
+end
+
+def fun_l9_n743(x)
+ if (x < 1)
+ fun_l10_n550(x)
+ else
+ fun_l10_n972(x)
+ end
+end
+
+def fun_l9_n744(x)
+ if (x < 1)
+ fun_l10_n5(x)
+ else
+ fun_l10_n306(x)
+ end
+end
+
+def fun_l9_n745(x)
+ if (x < 1)
+ fun_l10_n755(x)
+ else
+ fun_l10_n849(x)
+ end
+end
+
+def fun_l9_n746(x)
+ if (x < 1)
+ fun_l10_n912(x)
+ else
+ fun_l10_n307(x)
+ end
+end
+
+def fun_l9_n747(x)
+ if (x < 1)
+ fun_l10_n181(x)
+ else
+ fun_l10_n476(x)
+ end
+end
+
+def fun_l9_n748(x)
+ if (x < 1)
+ fun_l10_n353(x)
+ else
+ fun_l10_n412(x)
+ end
+end
+
+def fun_l9_n749(x)
+ if (x < 1)
+ fun_l10_n187(x)
+ else
+ fun_l10_n591(x)
+ end
+end
+
+def fun_l9_n750(x)
+ if (x < 1)
+ fun_l10_n464(x)
+ else
+ fun_l10_n581(x)
+ end
+end
+
+def fun_l9_n751(x)
+ if (x < 1)
+ fun_l10_n1(x)
+ else
+ fun_l10_n557(x)
+ end
+end
+
+def fun_l9_n752(x)
+ if (x < 1)
+ fun_l10_n788(x)
+ else
+ fun_l10_n438(x)
+ end
+end
+
+def fun_l9_n753(x)
+ if (x < 1)
+ fun_l10_n535(x)
+ else
+ fun_l10_n13(x)
+ end
+end
+
+def fun_l9_n754(x)
+ if (x < 1)
+ fun_l10_n811(x)
+ else
+ fun_l10_n543(x)
+ end
+end
+
+def fun_l9_n755(x)
+ if (x < 1)
+ fun_l10_n328(x)
+ else
+ fun_l10_n44(x)
+ end
+end
+
+def fun_l9_n756(x)
+ if (x < 1)
+ fun_l10_n839(x)
+ else
+ fun_l10_n16(x)
+ end
+end
+
+def fun_l9_n757(x)
+ if (x < 1)
+ fun_l10_n778(x)
+ else
+ fun_l10_n865(x)
+ end
+end
+
+def fun_l9_n758(x)
+ if (x < 1)
+ fun_l10_n552(x)
+ else
+ fun_l10_n783(x)
+ end
+end
+
+def fun_l9_n759(x)
+ if (x < 1)
+ fun_l10_n293(x)
+ else
+ fun_l10_n140(x)
+ end
+end
+
+def fun_l9_n760(x)
+ if (x < 1)
+ fun_l10_n814(x)
+ else
+ fun_l10_n497(x)
+ end
+end
+
+def fun_l9_n761(x)
+ if (x < 1)
+ fun_l10_n922(x)
+ else
+ fun_l10_n986(x)
+ end
+end
+
+def fun_l9_n762(x)
+ if (x < 1)
+ fun_l10_n100(x)
+ else
+ fun_l10_n346(x)
+ end
+end
+
+def fun_l9_n763(x)
+ if (x < 1)
+ fun_l10_n738(x)
+ else
+ fun_l10_n223(x)
+ end
+end
+
+def fun_l9_n764(x)
+ if (x < 1)
+ fun_l10_n168(x)
+ else
+ fun_l10_n367(x)
+ end
+end
+
+def fun_l9_n765(x)
+ if (x < 1)
+ fun_l10_n929(x)
+ else
+ fun_l10_n684(x)
+ end
+end
+
+def fun_l9_n766(x)
+ if (x < 1)
+ fun_l10_n940(x)
+ else
+ fun_l10_n497(x)
+ end
+end
+
+def fun_l9_n767(x)
+ if (x < 1)
+ fun_l10_n198(x)
+ else
+ fun_l10_n386(x)
+ end
+end
+
+def fun_l9_n768(x)
+ if (x < 1)
+ fun_l10_n667(x)
+ else
+ fun_l10_n913(x)
+ end
+end
+
+def fun_l9_n769(x)
+ if (x < 1)
+ fun_l10_n210(x)
+ else
+ fun_l10_n233(x)
+ end
+end
+
+def fun_l9_n770(x)
+ if (x < 1)
+ fun_l10_n819(x)
+ else
+ fun_l10_n755(x)
+ end
+end
+
+def fun_l9_n771(x)
+ if (x < 1)
+ fun_l10_n519(x)
+ else
+ fun_l10_n554(x)
+ end
+end
+
+def fun_l9_n772(x)
+ if (x < 1)
+ fun_l10_n880(x)
+ else
+ fun_l10_n280(x)
+ end
+end
+
+def fun_l9_n773(x)
+ if (x < 1)
+ fun_l10_n368(x)
+ else
+ fun_l10_n97(x)
+ end
+end
+
+def fun_l9_n774(x)
+ if (x < 1)
+ fun_l10_n447(x)
+ else
+ fun_l10_n918(x)
+ end
+end
+
+def fun_l9_n775(x)
+ if (x < 1)
+ fun_l10_n222(x)
+ else
+ fun_l10_n35(x)
+ end
+end
+
+def fun_l9_n776(x)
+ if (x < 1)
+ fun_l10_n339(x)
+ else
+ fun_l10_n309(x)
+ end
+end
+
+def fun_l9_n777(x)
+ if (x < 1)
+ fun_l10_n948(x)
+ else
+ fun_l10_n967(x)
+ end
+end
+
+def fun_l9_n778(x)
+ if (x < 1)
+ fun_l10_n561(x)
+ else
+ fun_l10_n202(x)
+ end
+end
+
+def fun_l9_n779(x)
+ if (x < 1)
+ fun_l10_n863(x)
+ else
+ fun_l10_n356(x)
+ end
+end
+
+def fun_l9_n780(x)
+ if (x < 1)
+ fun_l10_n459(x)
+ else
+ fun_l10_n358(x)
+ end
+end
+
+def fun_l9_n781(x)
+ if (x < 1)
+ fun_l10_n543(x)
+ else
+ fun_l10_n229(x)
+ end
+end
+
+def fun_l9_n782(x)
+ if (x < 1)
+ fun_l10_n422(x)
+ else
+ fun_l10_n448(x)
+ end
+end
+
+def fun_l9_n783(x)
+ if (x < 1)
+ fun_l10_n222(x)
+ else
+ fun_l10_n63(x)
+ end
+end
+
+def fun_l9_n784(x)
+ if (x < 1)
+ fun_l10_n520(x)
+ else
+ fun_l10_n443(x)
+ end
+end
+
+def fun_l9_n785(x)
+ if (x < 1)
+ fun_l10_n894(x)
+ else
+ fun_l10_n379(x)
+ end
+end
+
+def fun_l9_n786(x)
+ if (x < 1)
+ fun_l10_n362(x)
+ else
+ fun_l10_n676(x)
+ end
+end
+
+def fun_l9_n787(x)
+ if (x < 1)
+ fun_l10_n545(x)
+ else
+ fun_l10_n263(x)
+ end
+end
+
+def fun_l9_n788(x)
+ if (x < 1)
+ fun_l10_n322(x)
+ else
+ fun_l10_n631(x)
+ end
+end
+
+def fun_l9_n789(x)
+ if (x < 1)
+ fun_l10_n916(x)
+ else
+ fun_l10_n877(x)
+ end
+end
+
+def fun_l9_n790(x)
+ if (x < 1)
+ fun_l10_n443(x)
+ else
+ fun_l10_n640(x)
+ end
+end
+
+def fun_l9_n791(x)
+ if (x < 1)
+ fun_l10_n202(x)
+ else
+ fun_l10_n686(x)
+ end
+end
+
+def fun_l9_n792(x)
+ if (x < 1)
+ fun_l10_n143(x)
+ else
+ fun_l10_n200(x)
+ end
+end
+
+def fun_l9_n793(x)
+ if (x < 1)
+ fun_l10_n939(x)
+ else
+ fun_l10_n374(x)
+ end
+end
+
+def fun_l9_n794(x)
+ if (x < 1)
+ fun_l10_n506(x)
+ else
+ fun_l10_n782(x)
+ end
+end
+
+def fun_l9_n795(x)
+ if (x < 1)
+ fun_l10_n619(x)
+ else
+ fun_l10_n439(x)
+ end
+end
+
+def fun_l9_n796(x)
+ if (x < 1)
+ fun_l10_n748(x)
+ else
+ fun_l10_n61(x)
+ end
+end
+
+def fun_l9_n797(x)
+ if (x < 1)
+ fun_l10_n217(x)
+ else
+ fun_l10_n816(x)
+ end
+end
+
+def fun_l9_n798(x)
+ if (x < 1)
+ fun_l10_n310(x)
+ else
+ fun_l10_n445(x)
+ end
+end
+
+def fun_l9_n799(x)
+ if (x < 1)
+ fun_l10_n262(x)
+ else
+ fun_l10_n776(x)
+ end
+end
+
+def fun_l9_n800(x)
+ if (x < 1)
+ fun_l10_n807(x)
+ else
+ fun_l10_n566(x)
+ end
+end
+
+def fun_l9_n801(x)
+ if (x < 1)
+ fun_l10_n466(x)
+ else
+ fun_l10_n287(x)
+ end
+end
+
+def fun_l9_n802(x)
+ if (x < 1)
+ fun_l10_n205(x)
+ else
+ fun_l10_n415(x)
+ end
+end
+
+def fun_l9_n803(x)
+ if (x < 1)
+ fun_l10_n618(x)
+ else
+ fun_l10_n87(x)
+ end
+end
+
+def fun_l9_n804(x)
+ if (x < 1)
+ fun_l10_n248(x)
+ else
+ fun_l10_n32(x)
+ end
+end
+
+def fun_l9_n805(x)
+ if (x < 1)
+ fun_l10_n537(x)
+ else
+ fun_l10_n844(x)
+ end
+end
+
+def fun_l9_n806(x)
+ if (x < 1)
+ fun_l10_n554(x)
+ else
+ fun_l10_n696(x)
+ end
+end
+
+def fun_l9_n807(x)
+ if (x < 1)
+ fun_l10_n774(x)
+ else
+ fun_l10_n486(x)
+ end
+end
+
+def fun_l9_n808(x)
+ if (x < 1)
+ fun_l10_n500(x)
+ else
+ fun_l10_n926(x)
+ end
+end
+
+def fun_l9_n809(x)
+ if (x < 1)
+ fun_l10_n601(x)
+ else
+ fun_l10_n696(x)
+ end
+end
+
+def fun_l9_n810(x)
+ if (x < 1)
+ fun_l10_n770(x)
+ else
+ fun_l10_n948(x)
+ end
+end
+
+def fun_l9_n811(x)
+ if (x < 1)
+ fun_l10_n658(x)
+ else
+ fun_l10_n840(x)
+ end
+end
+
+def fun_l9_n812(x)
+ if (x < 1)
+ fun_l10_n913(x)
+ else
+ fun_l10_n892(x)
+ end
+end
+
+def fun_l9_n813(x)
+ if (x < 1)
+ fun_l10_n440(x)
+ else
+ fun_l10_n204(x)
+ end
+end
+
+def fun_l9_n814(x)
+ if (x < 1)
+ fun_l10_n273(x)
+ else
+ fun_l10_n816(x)
+ end
+end
+
+def fun_l9_n815(x)
+ if (x < 1)
+ fun_l10_n190(x)
+ else
+ fun_l10_n735(x)
+ end
+end
+
+def fun_l9_n816(x)
+ if (x < 1)
+ fun_l10_n77(x)
+ else
+ fun_l10_n30(x)
+ end
+end
+
+def fun_l9_n817(x)
+ if (x < 1)
+ fun_l10_n697(x)
+ else
+ fun_l10_n985(x)
+ end
+end
+
+def fun_l9_n818(x)
+ if (x < 1)
+ fun_l10_n583(x)
+ else
+ fun_l10_n314(x)
+ end
+end
+
+def fun_l9_n819(x)
+ if (x < 1)
+ fun_l10_n149(x)
+ else
+ fun_l10_n556(x)
+ end
+end
+
+def fun_l9_n820(x)
+ if (x < 1)
+ fun_l10_n634(x)
+ else
+ fun_l10_n392(x)
+ end
+end
+
+def fun_l9_n821(x)
+ if (x < 1)
+ fun_l10_n401(x)
+ else
+ fun_l10_n217(x)
+ end
+end
+
+def fun_l9_n822(x)
+ if (x < 1)
+ fun_l10_n564(x)
+ else
+ fun_l10_n860(x)
+ end
+end
+
+def fun_l9_n823(x)
+ if (x < 1)
+ fun_l10_n901(x)
+ else
+ fun_l10_n836(x)
+ end
+end
+
+def fun_l9_n824(x)
+ if (x < 1)
+ fun_l10_n526(x)
+ else
+ fun_l10_n660(x)
+ end
+end
+
+def fun_l9_n825(x)
+ if (x < 1)
+ fun_l10_n245(x)
+ else
+ fun_l10_n914(x)
+ end
+end
+
+def fun_l9_n826(x)
+ if (x < 1)
+ fun_l10_n712(x)
+ else
+ fun_l10_n928(x)
+ end
+end
+
+def fun_l9_n827(x)
+ if (x < 1)
+ fun_l10_n596(x)
+ else
+ fun_l10_n803(x)
+ end
+end
+
+def fun_l9_n828(x)
+ if (x < 1)
+ fun_l10_n454(x)
+ else
+ fun_l10_n679(x)
+ end
+end
+
+def fun_l9_n829(x)
+ if (x < 1)
+ fun_l10_n104(x)
+ else
+ fun_l10_n137(x)
+ end
+end
+
+def fun_l9_n830(x)
+ if (x < 1)
+ fun_l10_n516(x)
+ else
+ fun_l10_n687(x)
+ end
+end
+
+def fun_l9_n831(x)
+ if (x < 1)
+ fun_l10_n720(x)
+ else
+ fun_l10_n770(x)
+ end
+end
+
+def fun_l9_n832(x)
+ if (x < 1)
+ fun_l10_n939(x)
+ else
+ fun_l10_n119(x)
+ end
+end
+
+def fun_l9_n833(x)
+ if (x < 1)
+ fun_l10_n515(x)
+ else
+ fun_l10_n71(x)
+ end
+end
+
+def fun_l9_n834(x)
+ if (x < 1)
+ fun_l10_n668(x)
+ else
+ fun_l10_n521(x)
+ end
+end
+
+def fun_l9_n835(x)
+ if (x < 1)
+ fun_l10_n405(x)
+ else
+ fun_l10_n69(x)
+ end
+end
+
+def fun_l9_n836(x)
+ if (x < 1)
+ fun_l10_n201(x)
+ else
+ fun_l10_n681(x)
+ end
+end
+
+def fun_l9_n837(x)
+ if (x < 1)
+ fun_l10_n161(x)
+ else
+ fun_l10_n258(x)
+ end
+end
+
+def fun_l9_n838(x)
+ if (x < 1)
+ fun_l10_n913(x)
+ else
+ fun_l10_n586(x)
+ end
+end
+
+def fun_l9_n839(x)
+ if (x < 1)
+ fun_l10_n566(x)
+ else
+ fun_l10_n543(x)
+ end
+end
+
+def fun_l9_n840(x)
+ if (x < 1)
+ fun_l10_n547(x)
+ else
+ fun_l10_n570(x)
+ end
+end
+
+def fun_l9_n841(x)
+ if (x < 1)
+ fun_l10_n888(x)
+ else
+ fun_l10_n843(x)
+ end
+end
+
+def fun_l9_n842(x)
+ if (x < 1)
+ fun_l10_n497(x)
+ else
+ fun_l10_n985(x)
+ end
+end
+
+def fun_l9_n843(x)
+ if (x < 1)
+ fun_l10_n754(x)
+ else
+ fun_l10_n390(x)
+ end
+end
+
+def fun_l9_n844(x)
+ if (x < 1)
+ fun_l10_n625(x)
+ else
+ fun_l10_n562(x)
+ end
+end
+
+def fun_l9_n845(x)
+ if (x < 1)
+ fun_l10_n858(x)
+ else
+ fun_l10_n553(x)
+ end
+end
+
+def fun_l9_n846(x)
+ if (x < 1)
+ fun_l10_n145(x)
+ else
+ fun_l10_n551(x)
+ end
+end
+
+def fun_l9_n847(x)
+ if (x < 1)
+ fun_l10_n916(x)
+ else
+ fun_l10_n851(x)
+ end
+end
+
+def fun_l9_n848(x)
+ if (x < 1)
+ fun_l10_n935(x)
+ else
+ fun_l10_n448(x)
+ end
+end
+
+def fun_l9_n849(x)
+ if (x < 1)
+ fun_l10_n664(x)
+ else
+ fun_l10_n832(x)
+ end
+end
+
+def fun_l9_n850(x)
+ if (x < 1)
+ fun_l10_n904(x)
+ else
+ fun_l10_n203(x)
+ end
+end
+
+def fun_l9_n851(x)
+ if (x < 1)
+ fun_l10_n863(x)
+ else
+ fun_l10_n491(x)
+ end
+end
+
+def fun_l9_n852(x)
+ if (x < 1)
+ fun_l10_n930(x)
+ else
+ fun_l10_n248(x)
+ end
+end
+
+def fun_l9_n853(x)
+ if (x < 1)
+ fun_l10_n637(x)
+ else
+ fun_l10_n716(x)
+ end
+end
+
+def fun_l9_n854(x)
+ if (x < 1)
+ fun_l10_n35(x)
+ else
+ fun_l10_n662(x)
+ end
+end
+
+def fun_l9_n855(x)
+ if (x < 1)
+ fun_l10_n57(x)
+ else
+ fun_l10_n392(x)
+ end
+end
+
+def fun_l9_n856(x)
+ if (x < 1)
+ fun_l10_n480(x)
+ else
+ fun_l10_n447(x)
+ end
+end
+
+def fun_l9_n857(x)
+ if (x < 1)
+ fun_l10_n134(x)
+ else
+ fun_l10_n842(x)
+ end
+end
+
+def fun_l9_n858(x)
+ if (x < 1)
+ fun_l10_n384(x)
+ else
+ fun_l10_n577(x)
+ end
+end
+
+def fun_l9_n859(x)
+ if (x < 1)
+ fun_l10_n718(x)
+ else
+ fun_l10_n571(x)
+ end
+end
+
+def fun_l9_n860(x)
+ if (x < 1)
+ fun_l10_n237(x)
+ else
+ fun_l10_n654(x)
+ end
+end
+
+def fun_l9_n861(x)
+ if (x < 1)
+ fun_l10_n807(x)
+ else
+ fun_l10_n409(x)
+ end
+end
+
+def fun_l9_n862(x)
+ if (x < 1)
+ fun_l10_n801(x)
+ else
+ fun_l10_n575(x)
+ end
+end
+
+def fun_l9_n863(x)
+ if (x < 1)
+ fun_l10_n500(x)
+ else
+ fun_l10_n133(x)
+ end
+end
+
+def fun_l9_n864(x)
+ if (x < 1)
+ fun_l10_n403(x)
+ else
+ fun_l10_n720(x)
+ end
+end
+
+def fun_l9_n865(x)
+ if (x < 1)
+ fun_l10_n648(x)
+ else
+ fun_l10_n677(x)
+ end
+end
+
+def fun_l9_n866(x)
+ if (x < 1)
+ fun_l10_n873(x)
+ else
+ fun_l10_n519(x)
+ end
+end
+
+def fun_l9_n867(x)
+ if (x < 1)
+ fun_l10_n459(x)
+ else
+ fun_l10_n331(x)
+ end
+end
+
+def fun_l9_n868(x)
+ if (x < 1)
+ fun_l10_n159(x)
+ else
+ fun_l10_n64(x)
+ end
+end
+
+def fun_l9_n869(x)
+ if (x < 1)
+ fun_l10_n155(x)
+ else
+ fun_l10_n41(x)
+ end
+end
+
+def fun_l9_n870(x)
+ if (x < 1)
+ fun_l10_n947(x)
+ else
+ fun_l10_n386(x)
+ end
+end
+
+def fun_l9_n871(x)
+ if (x < 1)
+ fun_l10_n868(x)
+ else
+ fun_l10_n794(x)
+ end
+end
+
+def fun_l9_n872(x)
+ if (x < 1)
+ fun_l10_n77(x)
+ else
+ fun_l10_n268(x)
+ end
+end
+
+def fun_l9_n873(x)
+ if (x < 1)
+ fun_l10_n119(x)
+ else
+ fun_l10_n819(x)
+ end
+end
+
+def fun_l9_n874(x)
+ if (x < 1)
+ fun_l10_n143(x)
+ else
+ fun_l10_n434(x)
+ end
+end
+
+def fun_l9_n875(x)
+ if (x < 1)
+ fun_l10_n238(x)
+ else
+ fun_l10_n489(x)
+ end
+end
+
+def fun_l9_n876(x)
+ if (x < 1)
+ fun_l10_n687(x)
+ else
+ fun_l10_n384(x)
+ end
+end
+
+def fun_l9_n877(x)
+ if (x < 1)
+ fun_l10_n27(x)
+ else
+ fun_l10_n138(x)
+ end
+end
+
+def fun_l9_n878(x)
+ if (x < 1)
+ fun_l10_n208(x)
+ else
+ fun_l10_n691(x)
+ end
+end
+
+def fun_l9_n879(x)
+ if (x < 1)
+ fun_l10_n793(x)
+ else
+ fun_l10_n165(x)
+ end
+end
+
+def fun_l9_n880(x)
+ if (x < 1)
+ fun_l10_n358(x)
+ else
+ fun_l10_n455(x)
+ end
+end
+
+def fun_l9_n881(x)
+ if (x < 1)
+ fun_l10_n558(x)
+ else
+ fun_l10_n184(x)
+ end
+end
+
+def fun_l9_n882(x)
+ if (x < 1)
+ fun_l10_n461(x)
+ else
+ fun_l10_n155(x)
+ end
+end
+
+def fun_l9_n883(x)
+ if (x < 1)
+ fun_l10_n503(x)
+ else
+ fun_l10_n225(x)
+ end
+end
+
+def fun_l9_n884(x)
+ if (x < 1)
+ fun_l10_n384(x)
+ else
+ fun_l10_n262(x)
+ end
+end
+
+def fun_l9_n885(x)
+ if (x < 1)
+ fun_l10_n565(x)
+ else
+ fun_l10_n633(x)
+ end
+end
+
+def fun_l9_n886(x)
+ if (x < 1)
+ fun_l10_n626(x)
+ else
+ fun_l10_n796(x)
+ end
+end
+
+def fun_l9_n887(x)
+ if (x < 1)
+ fun_l10_n424(x)
+ else
+ fun_l10_n458(x)
+ end
+end
+
+def fun_l9_n888(x)
+ if (x < 1)
+ fun_l10_n687(x)
+ else
+ fun_l10_n145(x)
+ end
+end
+
+def fun_l9_n889(x)
+ if (x < 1)
+ fun_l10_n787(x)
+ else
+ fun_l10_n225(x)
+ end
+end
+
+def fun_l9_n890(x)
+ if (x < 1)
+ fun_l10_n249(x)
+ else
+ fun_l10_n154(x)
+ end
+end
+
+def fun_l9_n891(x)
+ if (x < 1)
+ fun_l10_n38(x)
+ else
+ fun_l10_n635(x)
+ end
+end
+
+def fun_l9_n892(x)
+ if (x < 1)
+ fun_l10_n920(x)
+ else
+ fun_l10_n478(x)
+ end
+end
+
+def fun_l9_n893(x)
+ if (x < 1)
+ fun_l10_n13(x)
+ else
+ fun_l10_n174(x)
+ end
+end
+
+def fun_l9_n894(x)
+ if (x < 1)
+ fun_l10_n304(x)
+ else
+ fun_l10_n495(x)
+ end
+end
+
+def fun_l9_n895(x)
+ if (x < 1)
+ fun_l10_n226(x)
+ else
+ fun_l10_n420(x)
+ end
+end
+
+def fun_l9_n896(x)
+ if (x < 1)
+ fun_l10_n86(x)
+ else
+ fun_l10_n837(x)
+ end
+end
+
+def fun_l9_n897(x)
+ if (x < 1)
+ fun_l10_n927(x)
+ else
+ fun_l10_n344(x)
+ end
+end
+
+def fun_l9_n898(x)
+ if (x < 1)
+ fun_l10_n87(x)
+ else
+ fun_l10_n270(x)
+ end
+end
+
+def fun_l9_n899(x)
+ if (x < 1)
+ fun_l10_n549(x)
+ else
+ fun_l10_n349(x)
+ end
+end
+
+def fun_l9_n900(x)
+ if (x < 1)
+ fun_l10_n456(x)
+ else
+ fun_l10_n345(x)
+ end
+end
+
+def fun_l9_n901(x)
+ if (x < 1)
+ fun_l10_n154(x)
+ else
+ fun_l10_n764(x)
+ end
+end
+
+def fun_l9_n902(x)
+ if (x < 1)
+ fun_l10_n614(x)
+ else
+ fun_l10_n536(x)
+ end
+end
+
+def fun_l9_n903(x)
+ if (x < 1)
+ fun_l10_n108(x)
+ else
+ fun_l10_n197(x)
+ end
+end
+
+def fun_l9_n904(x)
+ if (x < 1)
+ fun_l10_n616(x)
+ else
+ fun_l10_n777(x)
+ end
+end
+
+def fun_l9_n905(x)
+ if (x < 1)
+ fun_l10_n515(x)
+ else
+ fun_l10_n830(x)
+ end
+end
+
+def fun_l9_n906(x)
+ if (x < 1)
+ fun_l10_n288(x)
+ else
+ fun_l10_n717(x)
+ end
+end
+
+def fun_l9_n907(x)
+ if (x < 1)
+ fun_l10_n704(x)
+ else
+ fun_l10_n962(x)
+ end
+end
+
+def fun_l9_n908(x)
+ if (x < 1)
+ fun_l10_n85(x)
+ else
+ fun_l10_n70(x)
+ end
+end
+
+def fun_l9_n909(x)
+ if (x < 1)
+ fun_l10_n806(x)
+ else
+ fun_l10_n97(x)
+ end
+end
+
+def fun_l9_n910(x)
+ if (x < 1)
+ fun_l10_n567(x)
+ else
+ fun_l10_n47(x)
+ end
+end
+
+def fun_l9_n911(x)
+ if (x < 1)
+ fun_l10_n919(x)
+ else
+ fun_l10_n879(x)
+ end
+end
+
+def fun_l9_n912(x)
+ if (x < 1)
+ fun_l10_n229(x)
+ else
+ fun_l10_n200(x)
+ end
+end
+
+def fun_l9_n913(x)
+ if (x < 1)
+ fun_l10_n502(x)
+ else
+ fun_l10_n820(x)
+ end
+end
+
+def fun_l9_n914(x)
+ if (x < 1)
+ fun_l10_n57(x)
+ else
+ fun_l10_n470(x)
+ end
+end
+
+def fun_l9_n915(x)
+ if (x < 1)
+ fun_l10_n909(x)
+ else
+ fun_l10_n845(x)
+ end
+end
+
+def fun_l9_n916(x)
+ if (x < 1)
+ fun_l10_n658(x)
+ else
+ fun_l10_n925(x)
+ end
+end
+
+def fun_l9_n917(x)
+ if (x < 1)
+ fun_l10_n886(x)
+ else
+ fun_l10_n285(x)
+ end
+end
+
+def fun_l9_n918(x)
+ if (x < 1)
+ fun_l10_n484(x)
+ else
+ fun_l10_n712(x)
+ end
+end
+
+def fun_l9_n919(x)
+ if (x < 1)
+ fun_l10_n299(x)
+ else
+ fun_l10_n144(x)
+ end
+end
+
+def fun_l9_n920(x)
+ if (x < 1)
+ fun_l10_n830(x)
+ else
+ fun_l10_n913(x)
+ end
+end
+
+def fun_l9_n921(x)
+ if (x < 1)
+ fun_l10_n306(x)
+ else
+ fun_l10_n242(x)
+ end
+end
+
+def fun_l9_n922(x)
+ if (x < 1)
+ fun_l10_n442(x)
+ else
+ fun_l10_n497(x)
+ end
+end
+
+def fun_l9_n923(x)
+ if (x < 1)
+ fun_l10_n22(x)
+ else
+ fun_l10_n376(x)
+ end
+end
+
+def fun_l9_n924(x)
+ if (x < 1)
+ fun_l10_n737(x)
+ else
+ fun_l10_n603(x)
+ end
+end
+
+def fun_l9_n925(x)
+ if (x < 1)
+ fun_l10_n300(x)
+ else
+ fun_l10_n974(x)
+ end
+end
+
+def fun_l9_n926(x)
+ if (x < 1)
+ fun_l10_n644(x)
+ else
+ fun_l10_n973(x)
+ end
+end
+
+def fun_l9_n927(x)
+ if (x < 1)
+ fun_l10_n413(x)
+ else
+ fun_l10_n353(x)
+ end
+end
+
+def fun_l9_n928(x)
+ if (x < 1)
+ fun_l10_n438(x)
+ else
+ fun_l10_n518(x)
+ end
+end
+
+def fun_l9_n929(x)
+ if (x < 1)
+ fun_l10_n30(x)
+ else
+ fun_l10_n207(x)
+ end
+end
+
+def fun_l9_n930(x)
+ if (x < 1)
+ fun_l10_n976(x)
+ else
+ fun_l10_n70(x)
+ end
+end
+
+def fun_l9_n931(x)
+ if (x < 1)
+ fun_l10_n5(x)
+ else
+ fun_l10_n37(x)
+ end
+end
+
+def fun_l9_n932(x)
+ if (x < 1)
+ fun_l10_n612(x)
+ else
+ fun_l10_n268(x)
+ end
+end
+
+def fun_l9_n933(x)
+ if (x < 1)
+ fun_l10_n81(x)
+ else
+ fun_l10_n373(x)
+ end
+end
+
+def fun_l9_n934(x)
+ if (x < 1)
+ fun_l10_n30(x)
+ else
+ fun_l10_n504(x)
+ end
+end
+
+def fun_l9_n935(x)
+ if (x < 1)
+ fun_l10_n131(x)
+ else
+ fun_l10_n617(x)
+ end
+end
+
+def fun_l9_n936(x)
+ if (x < 1)
+ fun_l10_n114(x)
+ else
+ fun_l10_n883(x)
+ end
+end
+
+def fun_l9_n937(x)
+ if (x < 1)
+ fun_l10_n859(x)
+ else
+ fun_l10_n788(x)
+ end
+end
+
+def fun_l9_n938(x)
+ if (x < 1)
+ fun_l10_n993(x)
+ else
+ fun_l10_n349(x)
+ end
+end
+
+def fun_l9_n939(x)
+ if (x < 1)
+ fun_l10_n775(x)
+ else
+ fun_l10_n195(x)
+ end
+end
+
+def fun_l9_n940(x)
+ if (x < 1)
+ fun_l10_n829(x)
+ else
+ fun_l10_n398(x)
+ end
+end
+
+def fun_l9_n941(x)
+ if (x < 1)
+ fun_l10_n906(x)
+ else
+ fun_l10_n529(x)
+ end
+end
+
+def fun_l9_n942(x)
+ if (x < 1)
+ fun_l10_n965(x)
+ else
+ fun_l10_n372(x)
+ end
+end
+
+def fun_l9_n943(x)
+ if (x < 1)
+ fun_l10_n953(x)
+ else
+ fun_l10_n397(x)
+ end
+end
+
+def fun_l9_n944(x)
+ if (x < 1)
+ fun_l10_n984(x)
+ else
+ fun_l10_n909(x)
+ end
+end
+
+def fun_l9_n945(x)
+ if (x < 1)
+ fun_l10_n649(x)
+ else
+ fun_l10_n304(x)
+ end
+end
+
+def fun_l9_n946(x)
+ if (x < 1)
+ fun_l10_n0(x)
+ else
+ fun_l10_n922(x)
+ end
+end
+
+def fun_l9_n947(x)
+ if (x < 1)
+ fun_l10_n460(x)
+ else
+ fun_l10_n215(x)
+ end
+end
+
+def fun_l9_n948(x)
+ if (x < 1)
+ fun_l10_n251(x)
+ else
+ fun_l10_n636(x)
+ end
+end
+
+def fun_l9_n949(x)
+ if (x < 1)
+ fun_l10_n14(x)
+ else
+ fun_l10_n494(x)
+ end
+end
+
+def fun_l9_n950(x)
+ if (x < 1)
+ fun_l10_n6(x)
+ else
+ fun_l10_n523(x)
+ end
+end
+
+def fun_l9_n951(x)
+ if (x < 1)
+ fun_l10_n705(x)
+ else
+ fun_l10_n689(x)
+ end
+end
+
+def fun_l9_n952(x)
+ if (x < 1)
+ fun_l10_n830(x)
+ else
+ fun_l10_n374(x)
+ end
+end
+
+def fun_l9_n953(x)
+ if (x < 1)
+ fun_l10_n451(x)
+ else
+ fun_l10_n87(x)
+ end
+end
+
+def fun_l9_n954(x)
+ if (x < 1)
+ fun_l10_n202(x)
+ else
+ fun_l10_n753(x)
+ end
+end
+
+def fun_l9_n955(x)
+ if (x < 1)
+ fun_l10_n384(x)
+ else
+ fun_l10_n216(x)
+ end
+end
+
+def fun_l9_n956(x)
+ if (x < 1)
+ fun_l10_n381(x)
+ else
+ fun_l10_n727(x)
+ end
+end
+
+def fun_l9_n957(x)
+ if (x < 1)
+ fun_l10_n876(x)
+ else
+ fun_l10_n760(x)
+ end
+end
+
+def fun_l9_n958(x)
+ if (x < 1)
+ fun_l10_n975(x)
+ else
+ fun_l10_n372(x)
+ end
+end
+
+def fun_l9_n959(x)
+ if (x < 1)
+ fun_l10_n714(x)
+ else
+ fun_l10_n680(x)
+ end
+end
+
+def fun_l9_n960(x)
+ if (x < 1)
+ fun_l10_n733(x)
+ else
+ fun_l10_n508(x)
+ end
+end
+
+def fun_l9_n961(x)
+ if (x < 1)
+ fun_l10_n319(x)
+ else
+ fun_l10_n90(x)
+ end
+end
+
+def fun_l9_n962(x)
+ if (x < 1)
+ fun_l10_n964(x)
+ else
+ fun_l10_n282(x)
+ end
+end
+
+def fun_l9_n963(x)
+ if (x < 1)
+ fun_l10_n179(x)
+ else
+ fun_l10_n324(x)
+ end
+end
+
+def fun_l9_n964(x)
+ if (x < 1)
+ fun_l10_n627(x)
+ else
+ fun_l10_n627(x)
+ end
+end
+
+def fun_l9_n965(x)
+ if (x < 1)
+ fun_l10_n7(x)
+ else
+ fun_l10_n375(x)
+ end
+end
+
+def fun_l9_n966(x)
+ if (x < 1)
+ fun_l10_n960(x)
+ else
+ fun_l10_n272(x)
+ end
+end
+
+def fun_l9_n967(x)
+ if (x < 1)
+ fun_l10_n869(x)
+ else
+ fun_l10_n737(x)
+ end
+end
+
+def fun_l9_n968(x)
+ if (x < 1)
+ fun_l10_n621(x)
+ else
+ fun_l10_n413(x)
+ end
+end
+
+def fun_l9_n969(x)
+ if (x < 1)
+ fun_l10_n258(x)
+ else
+ fun_l10_n105(x)
+ end
+end
+
+def fun_l9_n970(x)
+ if (x < 1)
+ fun_l10_n817(x)
+ else
+ fun_l10_n519(x)
+ end
+end
+
+def fun_l9_n971(x)
+ if (x < 1)
+ fun_l10_n462(x)
+ else
+ fun_l10_n335(x)
+ end
+end
+
+def fun_l9_n972(x)
+ if (x < 1)
+ fun_l10_n770(x)
+ else
+ fun_l10_n856(x)
+ end
+end
+
+def fun_l9_n973(x)
+ if (x < 1)
+ fun_l10_n607(x)
+ else
+ fun_l10_n142(x)
+ end
+end
+
+def fun_l9_n974(x)
+ if (x < 1)
+ fun_l10_n498(x)
+ else
+ fun_l10_n373(x)
+ end
+end
+
+def fun_l9_n975(x)
+ if (x < 1)
+ fun_l10_n239(x)
+ else
+ fun_l10_n895(x)
+ end
+end
+
+def fun_l9_n976(x)
+ if (x < 1)
+ fun_l10_n312(x)
+ else
+ fun_l10_n489(x)
+ end
+end
+
+def fun_l9_n977(x)
+ if (x < 1)
+ fun_l10_n595(x)
+ else
+ fun_l10_n674(x)
+ end
+end
+
+def fun_l9_n978(x)
+ if (x < 1)
+ fun_l10_n928(x)
+ else
+ fun_l10_n774(x)
+ end
+end
+
+def fun_l9_n979(x)
+ if (x < 1)
+ fun_l10_n964(x)
+ else
+ fun_l10_n860(x)
+ end
+end
+
+def fun_l9_n980(x)
+ if (x < 1)
+ fun_l10_n63(x)
+ else
+ fun_l10_n115(x)
+ end
+end
+
+def fun_l9_n981(x)
+ if (x < 1)
+ fun_l10_n930(x)
+ else
+ fun_l10_n559(x)
+ end
+end
+
+def fun_l9_n982(x)
+ if (x < 1)
+ fun_l10_n391(x)
+ else
+ fun_l10_n411(x)
+ end
+end
+
+def fun_l9_n983(x)
+ if (x < 1)
+ fun_l10_n71(x)
+ else
+ fun_l10_n632(x)
+ end
+end
+
+def fun_l9_n984(x)
+ if (x < 1)
+ fun_l10_n613(x)
+ else
+ fun_l10_n218(x)
+ end
+end
+
+def fun_l9_n985(x)
+ if (x < 1)
+ fun_l10_n263(x)
+ else
+ fun_l10_n858(x)
+ end
+end
+
+def fun_l9_n986(x)
+ if (x < 1)
+ fun_l10_n974(x)
+ else
+ fun_l10_n824(x)
+ end
+end
+
+def fun_l9_n987(x)
+ if (x < 1)
+ fun_l10_n636(x)
+ else
+ fun_l10_n55(x)
+ end
+end
+
+def fun_l9_n988(x)
+ if (x < 1)
+ fun_l10_n367(x)
+ else
+ fun_l10_n878(x)
+ end
+end
+
+def fun_l9_n989(x)
+ if (x < 1)
+ fun_l10_n316(x)
+ else
+ fun_l10_n800(x)
+ end
+end
+
+def fun_l9_n990(x)
+ if (x < 1)
+ fun_l10_n581(x)
+ else
+ fun_l10_n511(x)
+ end
+end
+
+def fun_l9_n991(x)
+ if (x < 1)
+ fun_l10_n667(x)
+ else
+ fun_l10_n566(x)
+ end
+end
+
+def fun_l9_n992(x)
+ if (x < 1)
+ fun_l10_n144(x)
+ else
+ fun_l10_n51(x)
+ end
+end
+
+def fun_l9_n993(x)
+ if (x < 1)
+ fun_l10_n652(x)
+ else
+ fun_l10_n436(x)
+ end
+end
+
+def fun_l9_n994(x)
+ if (x < 1)
+ fun_l10_n283(x)
+ else
+ fun_l10_n480(x)
+ end
+end
+
+def fun_l9_n995(x)
+ if (x < 1)
+ fun_l10_n908(x)
+ else
+ fun_l10_n86(x)
+ end
+end
+
+def fun_l9_n996(x)
+ if (x < 1)
+ fun_l10_n43(x)
+ else
+ fun_l10_n466(x)
+ end
+end
+
+def fun_l9_n997(x)
+ if (x < 1)
+ fun_l10_n968(x)
+ else
+ fun_l10_n97(x)
+ end
+end
+
+def fun_l9_n998(x)
+ if (x < 1)
+ fun_l10_n38(x)
+ else
+ fun_l10_n78(x)
+ end
+end
+
+def fun_l9_n999(x)
+ if (x < 1)
+ fun_l10_n947(x)
+ else
+ fun_l10_n322(x)
+ end
+end
+
+def fun_l10_n0(x)
+ if (x < 1)
+ fun_l11_n424(x)
+ else
+ fun_l11_n206(x)
+ end
+end
+
+def fun_l10_n1(x)
+ if (x < 1)
+ fun_l11_n263(x)
+ else
+ fun_l11_n886(x)
+ end
+end
+
+def fun_l10_n2(x)
+ if (x < 1)
+ fun_l11_n31(x)
+ else
+ fun_l11_n693(x)
+ end
+end
+
+def fun_l10_n3(x)
+ if (x < 1)
+ fun_l11_n924(x)
+ else
+ fun_l11_n585(x)
+ end
+end
+
+def fun_l10_n4(x)
+ if (x < 1)
+ fun_l11_n552(x)
+ else
+ fun_l11_n904(x)
+ end
+end
+
+def fun_l10_n5(x)
+ if (x < 1)
+ fun_l11_n912(x)
+ else
+ fun_l11_n127(x)
+ end
+end
+
+def fun_l10_n6(x)
+ if (x < 1)
+ fun_l11_n284(x)
+ else
+ fun_l11_n952(x)
+ end
+end
+
+def fun_l10_n7(x)
+ if (x < 1)
+ fun_l11_n294(x)
+ else
+ fun_l11_n527(x)
+ end
+end
+
+def fun_l10_n8(x)
+ if (x < 1)
+ fun_l11_n675(x)
+ else
+ fun_l11_n457(x)
+ end
+end
+
+def fun_l10_n9(x)
+ if (x < 1)
+ fun_l11_n908(x)
+ else
+ fun_l11_n963(x)
+ end
+end
+
+def fun_l10_n10(x)
+ if (x < 1)
+ fun_l11_n361(x)
+ else
+ fun_l11_n839(x)
+ end
+end
+
+def fun_l10_n11(x)
+ if (x < 1)
+ fun_l11_n402(x)
+ else
+ fun_l11_n228(x)
+ end
+end
+
+def fun_l10_n12(x)
+ if (x < 1)
+ fun_l11_n871(x)
+ else
+ fun_l11_n194(x)
+ end
+end
+
+def fun_l10_n13(x)
+ if (x < 1)
+ fun_l11_n255(x)
+ else
+ fun_l11_n816(x)
+ end
+end
+
+def fun_l10_n14(x)
+ if (x < 1)
+ fun_l11_n987(x)
+ else
+ fun_l11_n870(x)
+ end
+end
+
+def fun_l10_n15(x)
+ if (x < 1)
+ fun_l11_n538(x)
+ else
+ fun_l11_n837(x)
+ end
+end
+
+def fun_l10_n16(x)
+ if (x < 1)
+ fun_l11_n205(x)
+ else
+ fun_l11_n831(x)
+ end
+end
+
+def fun_l10_n17(x)
+ if (x < 1)
+ fun_l11_n737(x)
+ else
+ fun_l11_n242(x)
+ end
+end
+
+def fun_l10_n18(x)
+ if (x < 1)
+ fun_l11_n18(x)
+ else
+ fun_l11_n103(x)
+ end
+end
+
+def fun_l10_n19(x)
+ if (x < 1)
+ fun_l11_n928(x)
+ else
+ fun_l11_n300(x)
+ end
+end
+
+def fun_l10_n20(x)
+ if (x < 1)
+ fun_l11_n816(x)
+ else
+ fun_l11_n225(x)
+ end
+end
+
+def fun_l10_n21(x)
+ if (x < 1)
+ fun_l11_n52(x)
+ else
+ fun_l11_n901(x)
+ end
+end
+
+def fun_l10_n22(x)
+ if (x < 1)
+ fun_l11_n316(x)
+ else
+ fun_l11_n556(x)
+ end
+end
+
+def fun_l10_n23(x)
+ if (x < 1)
+ fun_l11_n103(x)
+ else
+ fun_l11_n223(x)
+ end
+end
+
+def fun_l10_n24(x)
+ if (x < 1)
+ fun_l11_n14(x)
+ else
+ fun_l11_n875(x)
+ end
+end
+
+def fun_l10_n25(x)
+ if (x < 1)
+ fun_l11_n359(x)
+ else
+ fun_l11_n504(x)
+ end
+end
+
+def fun_l10_n26(x)
+ if (x < 1)
+ fun_l11_n416(x)
+ else
+ fun_l11_n172(x)
+ end
+end
+
+def fun_l10_n27(x)
+ if (x < 1)
+ fun_l11_n142(x)
+ else
+ fun_l11_n238(x)
+ end
+end
+
+def fun_l10_n28(x)
+ if (x < 1)
+ fun_l11_n319(x)
+ else
+ fun_l11_n350(x)
+ end
+end
+
+def fun_l10_n29(x)
+ if (x < 1)
+ fun_l11_n53(x)
+ else
+ fun_l11_n162(x)
+ end
+end
+
+def fun_l10_n30(x)
+ if (x < 1)
+ fun_l11_n121(x)
+ else
+ fun_l11_n39(x)
+ end
+end
+
+def fun_l10_n31(x)
+ if (x < 1)
+ fun_l11_n447(x)
+ else
+ fun_l11_n259(x)
+ end
+end
+
+def fun_l10_n32(x)
+ if (x < 1)
+ fun_l11_n931(x)
+ else
+ fun_l11_n571(x)
+ end
+end
+
+def fun_l10_n33(x)
+ if (x < 1)
+ fun_l11_n705(x)
+ else
+ fun_l11_n544(x)
+ end
+end
+
+def fun_l10_n34(x)
+ if (x < 1)
+ fun_l11_n990(x)
+ else
+ fun_l11_n695(x)
+ end
+end
+
+def fun_l10_n35(x)
+ if (x < 1)
+ fun_l11_n197(x)
+ else
+ fun_l11_n391(x)
+ end
+end
+
+def fun_l10_n36(x)
+ if (x < 1)
+ fun_l11_n686(x)
+ else
+ fun_l11_n785(x)
+ end
+end
+
+def fun_l10_n37(x)
+ if (x < 1)
+ fun_l11_n466(x)
+ else
+ fun_l11_n783(x)
+ end
+end
+
+def fun_l10_n38(x)
+ if (x < 1)
+ fun_l11_n351(x)
+ else
+ fun_l11_n732(x)
+ end
+end
+
+def fun_l10_n39(x)
+ if (x < 1)
+ fun_l11_n22(x)
+ else
+ fun_l11_n995(x)
+ end
+end
+
+def fun_l10_n40(x)
+ if (x < 1)
+ fun_l11_n264(x)
+ else
+ fun_l11_n662(x)
+ end
+end
+
+def fun_l10_n41(x)
+ if (x < 1)
+ fun_l11_n91(x)
+ else
+ fun_l11_n673(x)
+ end
+end
+
+def fun_l10_n42(x)
+ if (x < 1)
+ fun_l11_n993(x)
+ else
+ fun_l11_n839(x)
+ end
+end
+
+def fun_l10_n43(x)
+ if (x < 1)
+ fun_l11_n158(x)
+ else
+ fun_l11_n774(x)
+ end
+end
+
+def fun_l10_n44(x)
+ if (x < 1)
+ fun_l11_n977(x)
+ else
+ fun_l11_n321(x)
+ end
+end
+
+def fun_l10_n45(x)
+ if (x < 1)
+ fun_l11_n121(x)
+ else
+ fun_l11_n184(x)
+ end
+end
+
+def fun_l10_n46(x)
+ if (x < 1)
+ fun_l11_n446(x)
+ else
+ fun_l11_n426(x)
+ end
+end
+
+def fun_l10_n47(x)
+ if (x < 1)
+ fun_l11_n524(x)
+ else
+ fun_l11_n123(x)
+ end
+end
+
+def fun_l10_n48(x)
+ if (x < 1)
+ fun_l11_n435(x)
+ else
+ fun_l11_n560(x)
+ end
+end
+
+def fun_l10_n49(x)
+ if (x < 1)
+ fun_l11_n94(x)
+ else
+ fun_l11_n731(x)
+ end
+end
+
+def fun_l10_n50(x)
+ if (x < 1)
+ fun_l11_n177(x)
+ else
+ fun_l11_n902(x)
+ end
+end
+
+def fun_l10_n51(x)
+ if (x < 1)
+ fun_l11_n648(x)
+ else
+ fun_l11_n807(x)
+ end
+end
+
+def fun_l10_n52(x)
+ if (x < 1)
+ fun_l11_n414(x)
+ else
+ fun_l11_n335(x)
+ end
+end
+
+def fun_l10_n53(x)
+ if (x < 1)
+ fun_l11_n754(x)
+ else
+ fun_l11_n789(x)
+ end
+end
+
+def fun_l10_n54(x)
+ if (x < 1)
+ fun_l11_n843(x)
+ else
+ fun_l11_n980(x)
+ end
+end
+
+def fun_l10_n55(x)
+ if (x < 1)
+ fun_l11_n706(x)
+ else
+ fun_l11_n160(x)
+ end
+end
+
+def fun_l10_n56(x)
+ if (x < 1)
+ fun_l11_n564(x)
+ else
+ fun_l11_n672(x)
+ end
+end
+
+def fun_l10_n57(x)
+ if (x < 1)
+ fun_l11_n158(x)
+ else
+ fun_l11_n154(x)
+ end
+end
+
+def fun_l10_n58(x)
+ if (x < 1)
+ fun_l11_n120(x)
+ else
+ fun_l11_n970(x)
+ end
+end
+
+def fun_l10_n59(x)
+ if (x < 1)
+ fun_l11_n561(x)
+ else
+ fun_l11_n872(x)
+ end
+end
+
+def fun_l10_n60(x)
+ if (x < 1)
+ fun_l11_n93(x)
+ else
+ fun_l11_n723(x)
+ end
+end
+
+def fun_l10_n61(x)
+ if (x < 1)
+ fun_l11_n921(x)
+ else
+ fun_l11_n578(x)
+ end
+end
+
+def fun_l10_n62(x)
+ if (x < 1)
+ fun_l11_n527(x)
+ else
+ fun_l11_n118(x)
+ end
+end
+
+def fun_l10_n63(x)
+ if (x < 1)
+ fun_l11_n225(x)
+ else
+ fun_l11_n937(x)
+ end
+end
+
+def fun_l10_n64(x)
+ if (x < 1)
+ fun_l11_n634(x)
+ else
+ fun_l11_n415(x)
+ end
+end
+
+def fun_l10_n65(x)
+ if (x < 1)
+ fun_l11_n718(x)
+ else
+ fun_l11_n958(x)
+ end
+end
+
+def fun_l10_n66(x)
+ if (x < 1)
+ fun_l11_n972(x)
+ else
+ fun_l11_n453(x)
+ end
+end
+
+def fun_l10_n67(x)
+ if (x < 1)
+ fun_l11_n85(x)
+ else
+ fun_l11_n934(x)
+ end
+end
+
+def fun_l10_n68(x)
+ if (x < 1)
+ fun_l11_n386(x)
+ else
+ fun_l11_n138(x)
+ end
+end
+
+def fun_l10_n69(x)
+ if (x < 1)
+ fun_l11_n312(x)
+ else
+ fun_l11_n62(x)
+ end
+end
+
+def fun_l10_n70(x)
+ if (x < 1)
+ fun_l11_n591(x)
+ else
+ fun_l11_n906(x)
+ end
+end
+
+def fun_l10_n71(x)
+ if (x < 1)
+ fun_l11_n571(x)
+ else
+ fun_l11_n429(x)
+ end
+end
+
+def fun_l10_n72(x)
+ if (x < 1)
+ fun_l11_n996(x)
+ else
+ fun_l11_n932(x)
+ end
+end
+
+def fun_l10_n73(x)
+ if (x < 1)
+ fun_l11_n691(x)
+ else
+ fun_l11_n116(x)
+ end
+end
+
+def fun_l10_n74(x)
+ if (x < 1)
+ fun_l11_n670(x)
+ else
+ fun_l11_n865(x)
+ end
+end
+
+def fun_l10_n75(x)
+ if (x < 1)
+ fun_l11_n568(x)
+ else
+ fun_l11_n164(x)
+ end
+end
+
+def fun_l10_n76(x)
+ if (x < 1)
+ fun_l11_n747(x)
+ else
+ fun_l11_n235(x)
+ end
+end
+
+def fun_l10_n77(x)
+ if (x < 1)
+ fun_l11_n402(x)
+ else
+ fun_l11_n670(x)
+ end
+end
+
+def fun_l10_n78(x)
+ if (x < 1)
+ fun_l11_n525(x)
+ else
+ fun_l11_n675(x)
+ end
+end
+
+def fun_l10_n79(x)
+ if (x < 1)
+ fun_l11_n6(x)
+ else
+ fun_l11_n238(x)
+ end
+end
+
+def fun_l10_n80(x)
+ if (x < 1)
+ fun_l11_n905(x)
+ else
+ fun_l11_n170(x)
+ end
+end
+
+def fun_l10_n81(x)
+ if (x < 1)
+ fun_l11_n610(x)
+ else
+ fun_l11_n527(x)
+ end
+end
+
+def fun_l10_n82(x)
+ if (x < 1)
+ fun_l11_n796(x)
+ else
+ fun_l11_n749(x)
+ end
+end
+
+def fun_l10_n83(x)
+ if (x < 1)
+ fun_l11_n634(x)
+ else
+ fun_l11_n49(x)
+ end
+end
+
+def fun_l10_n84(x)
+ if (x < 1)
+ fun_l11_n376(x)
+ else
+ fun_l11_n852(x)
+ end
+end
+
+def fun_l10_n85(x)
+ if (x < 1)
+ fun_l11_n593(x)
+ else
+ fun_l11_n752(x)
+ end
+end
+
+def fun_l10_n86(x)
+ if (x < 1)
+ fun_l11_n821(x)
+ else
+ fun_l11_n892(x)
+ end
+end
+
+def fun_l10_n87(x)
+ if (x < 1)
+ fun_l11_n950(x)
+ else
+ fun_l11_n309(x)
+ end
+end
+
+def fun_l10_n88(x)
+ if (x < 1)
+ fun_l11_n360(x)
+ else
+ fun_l11_n134(x)
+ end
+end
+
+def fun_l10_n89(x)
+ if (x < 1)
+ fun_l11_n935(x)
+ else
+ fun_l11_n241(x)
+ end
+end
+
+def fun_l10_n90(x)
+ if (x < 1)
+ fun_l11_n524(x)
+ else
+ fun_l11_n120(x)
+ end
+end
+
+def fun_l10_n91(x)
+ if (x < 1)
+ fun_l11_n25(x)
+ else
+ fun_l11_n357(x)
+ end
+end
+
+def fun_l10_n92(x)
+ if (x < 1)
+ fun_l11_n248(x)
+ else
+ fun_l11_n212(x)
+ end
+end
+
+def fun_l10_n93(x)
+ if (x < 1)
+ fun_l11_n860(x)
+ else
+ fun_l11_n733(x)
+ end
+end
+
+def fun_l10_n94(x)
+ if (x < 1)
+ fun_l11_n147(x)
+ else
+ fun_l11_n907(x)
+ end
+end
+
+def fun_l10_n95(x)
+ if (x < 1)
+ fun_l11_n758(x)
+ else
+ fun_l11_n62(x)
+ end
+end
+
+def fun_l10_n96(x)
+ if (x < 1)
+ fun_l11_n205(x)
+ else
+ fun_l11_n54(x)
+ end
+end
+
+def fun_l10_n97(x)
+ if (x < 1)
+ fun_l11_n8(x)
+ else
+ fun_l11_n813(x)
+ end
+end
+
+def fun_l10_n98(x)
+ if (x < 1)
+ fun_l11_n296(x)
+ else
+ fun_l11_n693(x)
+ end
+end
+
+def fun_l10_n99(x)
+ if (x < 1)
+ fun_l11_n181(x)
+ else
+ fun_l11_n709(x)
+ end
+end
+
+def fun_l10_n100(x)
+ if (x < 1)
+ fun_l11_n109(x)
+ else
+ fun_l11_n560(x)
+ end
+end
+
+def fun_l10_n101(x)
+ if (x < 1)
+ fun_l11_n290(x)
+ else
+ fun_l11_n693(x)
+ end
+end
+
+def fun_l10_n102(x)
+ if (x < 1)
+ fun_l11_n826(x)
+ else
+ fun_l11_n813(x)
+ end
+end
+
+def fun_l10_n103(x)
+ if (x < 1)
+ fun_l11_n3(x)
+ else
+ fun_l11_n787(x)
+ end
+end
+
+def fun_l10_n104(x)
+ if (x < 1)
+ fun_l11_n477(x)
+ else
+ fun_l11_n336(x)
+ end
+end
+
+def fun_l10_n105(x)
+ if (x < 1)
+ fun_l11_n131(x)
+ else
+ fun_l11_n500(x)
+ end
+end
+
+def fun_l10_n106(x)
+ if (x < 1)
+ fun_l11_n278(x)
+ else
+ fun_l11_n948(x)
+ end
+end
+
+def fun_l10_n107(x)
+ if (x < 1)
+ fun_l11_n950(x)
+ else
+ fun_l11_n848(x)
+ end
+end
+
+def fun_l10_n108(x)
+ if (x < 1)
+ fun_l11_n490(x)
+ else
+ fun_l11_n1(x)
+ end
+end
+
+def fun_l10_n109(x)
+ if (x < 1)
+ fun_l11_n297(x)
+ else
+ fun_l11_n902(x)
+ end
+end
+
+def fun_l10_n110(x)
+ if (x < 1)
+ fun_l11_n808(x)
+ else
+ fun_l11_n697(x)
+ end
+end
+
+def fun_l10_n111(x)
+ if (x < 1)
+ fun_l11_n330(x)
+ else
+ fun_l11_n424(x)
+ end
+end
+
+def fun_l10_n112(x)
+ if (x < 1)
+ fun_l11_n254(x)
+ else
+ fun_l11_n662(x)
+ end
+end
+
+def fun_l10_n113(x)
+ if (x < 1)
+ fun_l11_n811(x)
+ else
+ fun_l11_n196(x)
+ end
+end
+
+def fun_l10_n114(x)
+ if (x < 1)
+ fun_l11_n868(x)
+ else
+ fun_l11_n812(x)
+ end
+end
+
+def fun_l10_n115(x)
+ if (x < 1)
+ fun_l11_n308(x)
+ else
+ fun_l11_n184(x)
+ end
+end
+
+def fun_l10_n116(x)
+ if (x < 1)
+ fun_l11_n64(x)
+ else
+ fun_l11_n906(x)
+ end
+end
+
+def fun_l10_n117(x)
+ if (x < 1)
+ fun_l11_n339(x)
+ else
+ fun_l11_n338(x)
+ end
+end
+
+def fun_l10_n118(x)
+ if (x < 1)
+ fun_l11_n993(x)
+ else
+ fun_l11_n915(x)
+ end
+end
+
+def fun_l10_n119(x)
+ if (x < 1)
+ fun_l11_n729(x)
+ else
+ fun_l11_n472(x)
+ end
+end
+
+def fun_l10_n120(x)
+ if (x < 1)
+ fun_l11_n646(x)
+ else
+ fun_l11_n83(x)
+ end
+end
+
+def fun_l10_n121(x)
+ if (x < 1)
+ fun_l11_n294(x)
+ else
+ fun_l11_n208(x)
+ end
+end
+
+def fun_l10_n122(x)
+ if (x < 1)
+ fun_l11_n309(x)
+ else
+ fun_l11_n52(x)
+ end
+end
+
+def fun_l10_n123(x)
+ if (x < 1)
+ fun_l11_n5(x)
+ else
+ fun_l11_n124(x)
+ end
+end
+
+def fun_l10_n124(x)
+ if (x < 1)
+ fun_l11_n288(x)
+ else
+ fun_l11_n731(x)
+ end
+end
+
+def fun_l10_n125(x)
+ if (x < 1)
+ fun_l11_n835(x)
+ else
+ fun_l11_n381(x)
+ end
+end
+
+def fun_l10_n126(x)
+ if (x < 1)
+ fun_l11_n269(x)
+ else
+ fun_l11_n104(x)
+ end
+end
+
+def fun_l10_n127(x)
+ if (x < 1)
+ fun_l11_n377(x)
+ else
+ fun_l11_n650(x)
+ end
+end
+
+def fun_l10_n128(x)
+ if (x < 1)
+ fun_l11_n749(x)
+ else
+ fun_l11_n223(x)
+ end
+end
+
+def fun_l10_n129(x)
+ if (x < 1)
+ fun_l11_n493(x)
+ else
+ fun_l11_n834(x)
+ end
+end
+
+def fun_l10_n130(x)
+ if (x < 1)
+ fun_l11_n826(x)
+ else
+ fun_l11_n857(x)
+ end
+end
+
+def fun_l10_n131(x)
+ if (x < 1)
+ fun_l11_n19(x)
+ else
+ fun_l11_n932(x)
+ end
+end
+
+def fun_l10_n132(x)
+ if (x < 1)
+ fun_l11_n585(x)
+ else
+ fun_l11_n13(x)
+ end
+end
+
+def fun_l10_n133(x)
+ if (x < 1)
+ fun_l11_n91(x)
+ else
+ fun_l11_n748(x)
+ end
+end
+
+def fun_l10_n134(x)
+ if (x < 1)
+ fun_l11_n218(x)
+ else
+ fun_l11_n343(x)
+ end
+end
+
+def fun_l10_n135(x)
+ if (x < 1)
+ fun_l11_n386(x)
+ else
+ fun_l11_n655(x)
+ end
+end
+
+def fun_l10_n136(x)
+ if (x < 1)
+ fun_l11_n43(x)
+ else
+ fun_l11_n964(x)
+ end
+end
+
+def fun_l10_n137(x)
+ if (x < 1)
+ fun_l11_n50(x)
+ else
+ fun_l11_n836(x)
+ end
+end
+
+def fun_l10_n138(x)
+ if (x < 1)
+ fun_l11_n915(x)
+ else
+ fun_l11_n262(x)
+ end
+end
+
+def fun_l10_n139(x)
+ if (x < 1)
+ fun_l11_n187(x)
+ else
+ fun_l11_n321(x)
+ end
+end
+
+def fun_l10_n140(x)
+ if (x < 1)
+ fun_l11_n473(x)
+ else
+ fun_l11_n771(x)
+ end
+end
+
+def fun_l10_n141(x)
+ if (x < 1)
+ fun_l11_n125(x)
+ else
+ fun_l11_n118(x)
+ end
+end
+
+def fun_l10_n142(x)
+ if (x < 1)
+ fun_l11_n993(x)
+ else
+ fun_l11_n178(x)
+ end
+end
+
+def fun_l10_n143(x)
+ if (x < 1)
+ fun_l11_n223(x)
+ else
+ fun_l11_n509(x)
+ end
+end
+
+def fun_l10_n144(x)
+ if (x < 1)
+ fun_l11_n62(x)
+ else
+ fun_l11_n455(x)
+ end
+end
+
+def fun_l10_n145(x)
+ if (x < 1)
+ fun_l11_n155(x)
+ else
+ fun_l11_n486(x)
+ end
+end
+
+def fun_l10_n146(x)
+ if (x < 1)
+ fun_l11_n414(x)
+ else
+ fun_l11_n384(x)
+ end
+end
+
+def fun_l10_n147(x)
+ if (x < 1)
+ fun_l11_n840(x)
+ else
+ fun_l11_n287(x)
+ end
+end
+
+def fun_l10_n148(x)
+ if (x < 1)
+ fun_l11_n605(x)
+ else
+ fun_l11_n283(x)
+ end
+end
+
+def fun_l10_n149(x)
+ if (x < 1)
+ fun_l11_n101(x)
+ else
+ fun_l11_n710(x)
+ end
+end
+
+def fun_l10_n150(x)
+ if (x < 1)
+ fun_l11_n51(x)
+ else
+ fun_l11_n304(x)
+ end
+end
+
+def fun_l10_n151(x)
+ if (x < 1)
+ fun_l11_n501(x)
+ else
+ fun_l11_n789(x)
+ end
+end
+
+def fun_l10_n152(x)
+ if (x < 1)
+ fun_l11_n265(x)
+ else
+ fun_l11_n304(x)
+ end
+end
+
+def fun_l10_n153(x)
+ if (x < 1)
+ fun_l11_n500(x)
+ else
+ fun_l11_n32(x)
+ end
+end
+
+def fun_l10_n154(x)
+ if (x < 1)
+ fun_l11_n464(x)
+ else
+ fun_l11_n212(x)
+ end
+end
+
+def fun_l10_n155(x)
+ if (x < 1)
+ fun_l11_n729(x)
+ else
+ fun_l11_n805(x)
+ end
+end
+
+def fun_l10_n156(x)
+ if (x < 1)
+ fun_l11_n225(x)
+ else
+ fun_l11_n241(x)
+ end
+end
+
+def fun_l10_n157(x)
+ if (x < 1)
+ fun_l11_n600(x)
+ else
+ fun_l11_n424(x)
+ end
+end
+
+def fun_l10_n158(x)
+ if (x < 1)
+ fun_l11_n684(x)
+ else
+ fun_l11_n898(x)
+ end
+end
+
+def fun_l10_n159(x)
+ if (x < 1)
+ fun_l11_n354(x)
+ else
+ fun_l11_n909(x)
+ end
+end
+
+def fun_l10_n160(x)
+ if (x < 1)
+ fun_l11_n879(x)
+ else
+ fun_l11_n917(x)
+ end
+end
+
+def fun_l10_n161(x)
+ if (x < 1)
+ fun_l11_n547(x)
+ else
+ fun_l11_n333(x)
+ end
+end
+
+def fun_l10_n162(x)
+ if (x < 1)
+ fun_l11_n769(x)
+ else
+ fun_l11_n846(x)
+ end
+end
+
+def fun_l10_n163(x)
+ if (x < 1)
+ fun_l11_n292(x)
+ else
+ fun_l11_n526(x)
+ end
+end
+
+def fun_l10_n164(x)
+ if (x < 1)
+ fun_l11_n355(x)
+ else
+ fun_l11_n783(x)
+ end
+end
+
+def fun_l10_n165(x)
+ if (x < 1)
+ fun_l11_n413(x)
+ else
+ fun_l11_n570(x)
+ end
+end
+
+def fun_l10_n166(x)
+ if (x < 1)
+ fun_l11_n535(x)
+ else
+ fun_l11_n953(x)
+ end
+end
+
+def fun_l10_n167(x)
+ if (x < 1)
+ fun_l11_n661(x)
+ else
+ fun_l11_n178(x)
+ end
+end
+
+def fun_l10_n168(x)
+ if (x < 1)
+ fun_l11_n749(x)
+ else
+ fun_l11_n853(x)
+ end
+end
+
+def fun_l10_n169(x)
+ if (x < 1)
+ fun_l11_n208(x)
+ else
+ fun_l11_n378(x)
+ end
+end
+
+def fun_l10_n170(x)
+ if (x < 1)
+ fun_l11_n385(x)
+ else
+ fun_l11_n811(x)
+ end
+end
+
+def fun_l10_n171(x)
+ if (x < 1)
+ fun_l11_n960(x)
+ else
+ fun_l11_n631(x)
+ end
+end
+
+def fun_l10_n172(x)
+ if (x < 1)
+ fun_l11_n104(x)
+ else
+ fun_l11_n667(x)
+ end
+end
+
+def fun_l10_n173(x)
+ if (x < 1)
+ fun_l11_n532(x)
+ else
+ fun_l11_n169(x)
+ end
+end
+
+def fun_l10_n174(x)
+ if (x < 1)
+ fun_l11_n794(x)
+ else
+ fun_l11_n761(x)
+ end
+end
+
+def fun_l10_n175(x)
+ if (x < 1)
+ fun_l11_n306(x)
+ else
+ fun_l11_n369(x)
+ end
+end
+
+def fun_l10_n176(x)
+ if (x < 1)
+ fun_l11_n693(x)
+ else
+ fun_l11_n254(x)
+ end
+end
+
+def fun_l10_n177(x)
+ if (x < 1)
+ fun_l11_n927(x)
+ else
+ fun_l11_n194(x)
+ end
+end
+
+def fun_l10_n178(x)
+ if (x < 1)
+ fun_l11_n197(x)
+ else
+ fun_l11_n136(x)
+ end
+end
+
+def fun_l10_n179(x)
+ if (x < 1)
+ fun_l11_n482(x)
+ else
+ fun_l11_n182(x)
+ end
+end
+
+def fun_l10_n180(x)
+ if (x < 1)
+ fun_l11_n20(x)
+ else
+ fun_l11_n978(x)
+ end
+end
+
+def fun_l10_n181(x)
+ if (x < 1)
+ fun_l11_n101(x)
+ else
+ fun_l11_n92(x)
+ end
+end
+
+def fun_l10_n182(x)
+ if (x < 1)
+ fun_l11_n179(x)
+ else
+ fun_l11_n634(x)
+ end
+end
+
+def fun_l10_n183(x)
+ if (x < 1)
+ fun_l11_n221(x)
+ else
+ fun_l11_n275(x)
+ end
+end
+
+def fun_l10_n184(x)
+ if (x < 1)
+ fun_l11_n826(x)
+ else
+ fun_l11_n630(x)
+ end
+end
+
+def fun_l10_n185(x)
+ if (x < 1)
+ fun_l11_n706(x)
+ else
+ fun_l11_n30(x)
+ end
+end
+
+def fun_l10_n186(x)
+ if (x < 1)
+ fun_l11_n491(x)
+ else
+ fun_l11_n182(x)
+ end
+end
+
+def fun_l10_n187(x)
+ if (x < 1)
+ fun_l11_n404(x)
+ else
+ fun_l11_n812(x)
+ end
+end
+
+def fun_l10_n188(x)
+ if (x < 1)
+ fun_l11_n41(x)
+ else
+ fun_l11_n39(x)
+ end
+end
+
+def fun_l10_n189(x)
+ if (x < 1)
+ fun_l11_n620(x)
+ else
+ fun_l11_n659(x)
+ end
+end
+
+def fun_l10_n190(x)
+ if (x < 1)
+ fun_l11_n717(x)
+ else
+ fun_l11_n846(x)
+ end
+end
+
+def fun_l10_n191(x)
+ if (x < 1)
+ fun_l11_n328(x)
+ else
+ fun_l11_n223(x)
+ end
+end
+
+def fun_l10_n192(x)
+ if (x < 1)
+ fun_l11_n280(x)
+ else
+ fun_l11_n360(x)
+ end
+end
+
+def fun_l10_n193(x)
+ if (x < 1)
+ fun_l11_n798(x)
+ else
+ fun_l11_n303(x)
+ end
+end
+
+def fun_l10_n194(x)
+ if (x < 1)
+ fun_l11_n617(x)
+ else
+ fun_l11_n207(x)
+ end
+end
+
+def fun_l10_n195(x)
+ if (x < 1)
+ fun_l11_n918(x)
+ else
+ fun_l11_n398(x)
+ end
+end
+
+def fun_l10_n196(x)
+ if (x < 1)
+ fun_l11_n998(x)
+ else
+ fun_l11_n31(x)
+ end
+end
+
+def fun_l10_n197(x)
+ if (x < 1)
+ fun_l11_n740(x)
+ else
+ fun_l11_n220(x)
+ end
+end
+
+def fun_l10_n198(x)
+ if (x < 1)
+ fun_l11_n847(x)
+ else
+ fun_l11_n915(x)
+ end
+end
+
+def fun_l10_n199(x)
+ if (x < 1)
+ fun_l11_n946(x)
+ else
+ fun_l11_n300(x)
+ end
+end
+
+def fun_l10_n200(x)
+ if (x < 1)
+ fun_l11_n494(x)
+ else
+ fun_l11_n316(x)
+ end
+end
+
+def fun_l10_n201(x)
+ if (x < 1)
+ fun_l11_n871(x)
+ else
+ fun_l11_n310(x)
+ end
+end
+
+def fun_l10_n202(x)
+ if (x < 1)
+ fun_l11_n660(x)
+ else
+ fun_l11_n538(x)
+ end
+end
+
+def fun_l10_n203(x)
+ if (x < 1)
+ fun_l11_n478(x)
+ else
+ fun_l11_n618(x)
+ end
+end
+
+def fun_l10_n204(x)
+ if (x < 1)
+ fun_l11_n134(x)
+ else
+ fun_l11_n224(x)
+ end
+end
+
+def fun_l10_n205(x)
+ if (x < 1)
+ fun_l11_n128(x)
+ else
+ fun_l11_n279(x)
+ end
+end
+
+def fun_l10_n206(x)
+ if (x < 1)
+ fun_l11_n718(x)
+ else
+ fun_l11_n514(x)
+ end
+end
+
+def fun_l10_n207(x)
+ if (x < 1)
+ fun_l11_n466(x)
+ else
+ fun_l11_n979(x)
+ end
+end
+
+def fun_l10_n208(x)
+ if (x < 1)
+ fun_l11_n990(x)
+ else
+ fun_l11_n881(x)
+ end
+end
+
+def fun_l10_n209(x)
+ if (x < 1)
+ fun_l11_n860(x)
+ else
+ fun_l11_n995(x)
+ end
+end
+
+def fun_l10_n210(x)
+ if (x < 1)
+ fun_l11_n269(x)
+ else
+ fun_l11_n846(x)
+ end
+end
+
+def fun_l10_n211(x)
+ if (x < 1)
+ fun_l11_n155(x)
+ else
+ fun_l11_n97(x)
+ end
+end
+
+def fun_l10_n212(x)
+ if (x < 1)
+ fun_l11_n377(x)
+ else
+ fun_l11_n749(x)
+ end
+end
+
+def fun_l10_n213(x)
+ if (x < 1)
+ fun_l11_n647(x)
+ else
+ fun_l11_n276(x)
+ end
+end
+
+def fun_l10_n214(x)
+ if (x < 1)
+ fun_l11_n290(x)
+ else
+ fun_l11_n325(x)
+ end
+end
+
+def fun_l10_n215(x)
+ if (x < 1)
+ fun_l11_n445(x)
+ else
+ fun_l11_n538(x)
+ end
+end
+
+def fun_l10_n216(x)
+ if (x < 1)
+ fun_l11_n433(x)
+ else
+ fun_l11_n937(x)
+ end
+end
+
+def fun_l10_n217(x)
+ if (x < 1)
+ fun_l11_n288(x)
+ else
+ fun_l11_n897(x)
+ end
+end
+
+def fun_l10_n218(x)
+ if (x < 1)
+ fun_l11_n386(x)
+ else
+ fun_l11_n545(x)
+ end
+end
+
+def fun_l10_n219(x)
+ if (x < 1)
+ fun_l11_n678(x)
+ else
+ fun_l11_n433(x)
+ end
+end
+
+def fun_l10_n220(x)
+ if (x < 1)
+ fun_l11_n203(x)
+ else
+ fun_l11_n163(x)
+ end
+end
+
+def fun_l10_n221(x)
+ if (x < 1)
+ fun_l11_n134(x)
+ else
+ fun_l11_n545(x)
+ end
+end
+
+def fun_l10_n222(x)
+ if (x < 1)
+ fun_l11_n556(x)
+ else
+ fun_l11_n537(x)
+ end
+end
+
+def fun_l10_n223(x)
+ if (x < 1)
+ fun_l11_n743(x)
+ else
+ fun_l11_n88(x)
+ end
+end
+
+def fun_l10_n224(x)
+ if (x < 1)
+ fun_l11_n678(x)
+ else
+ fun_l11_n643(x)
+ end
+end
+
+def fun_l10_n225(x)
+ if (x < 1)
+ fun_l11_n13(x)
+ else
+ fun_l11_n219(x)
+ end
+end
+
+def fun_l10_n226(x)
+ if (x < 1)
+ fun_l11_n454(x)
+ else
+ fun_l11_n691(x)
+ end
+end
+
+def fun_l10_n227(x)
+ if (x < 1)
+ fun_l11_n117(x)
+ else
+ fun_l11_n433(x)
+ end
+end
+
+def fun_l10_n228(x)
+ if (x < 1)
+ fun_l11_n559(x)
+ else
+ fun_l11_n884(x)
+ end
+end
+
+def fun_l10_n229(x)
+ if (x < 1)
+ fun_l11_n58(x)
+ else
+ fun_l11_n620(x)
+ end
+end
+
+def fun_l10_n230(x)
+ if (x < 1)
+ fun_l11_n688(x)
+ else
+ fun_l11_n76(x)
+ end
+end
+
+def fun_l10_n231(x)
+ if (x < 1)
+ fun_l11_n726(x)
+ else
+ fun_l11_n644(x)
+ end
+end
+
+def fun_l10_n232(x)
+ if (x < 1)
+ fun_l11_n918(x)
+ else
+ fun_l11_n0(x)
+ end
+end
+
+def fun_l10_n233(x)
+ if (x < 1)
+ fun_l11_n761(x)
+ else
+ fun_l11_n487(x)
+ end
+end
+
+def fun_l10_n234(x)
+ if (x < 1)
+ fun_l11_n657(x)
+ else
+ fun_l11_n107(x)
+ end
+end
+
+def fun_l10_n235(x)
+ if (x < 1)
+ fun_l11_n897(x)
+ else
+ fun_l11_n881(x)
+ end
+end
+
+def fun_l10_n236(x)
+ if (x < 1)
+ fun_l11_n851(x)
+ else
+ fun_l11_n593(x)
+ end
+end
+
+def fun_l10_n237(x)
+ if (x < 1)
+ fun_l11_n319(x)
+ else
+ fun_l11_n983(x)
+ end
+end
+
+def fun_l10_n238(x)
+ if (x < 1)
+ fun_l11_n648(x)
+ else
+ fun_l11_n870(x)
+ end
+end
+
+def fun_l10_n239(x)
+ if (x < 1)
+ fun_l11_n195(x)
+ else
+ fun_l11_n378(x)
+ end
+end
+
+def fun_l10_n240(x)
+ if (x < 1)
+ fun_l11_n398(x)
+ else
+ fun_l11_n284(x)
+ end
+end
+
+def fun_l10_n241(x)
+ if (x < 1)
+ fun_l11_n118(x)
+ else
+ fun_l11_n417(x)
+ end
+end
+
+def fun_l10_n242(x)
+ if (x < 1)
+ fun_l11_n220(x)
+ else
+ fun_l11_n445(x)
+ end
+end
+
+def fun_l10_n243(x)
+ if (x < 1)
+ fun_l11_n783(x)
+ else
+ fun_l11_n989(x)
+ end
+end
+
+def fun_l10_n244(x)
+ if (x < 1)
+ fun_l11_n229(x)
+ else
+ fun_l11_n439(x)
+ end
+end
+
+def fun_l10_n245(x)
+ if (x < 1)
+ fun_l11_n78(x)
+ else
+ fun_l11_n272(x)
+ end
+end
+
+def fun_l10_n246(x)
+ if (x < 1)
+ fun_l11_n481(x)
+ else
+ fun_l11_n499(x)
+ end
+end
+
+def fun_l10_n247(x)
+ if (x < 1)
+ fun_l11_n213(x)
+ else
+ fun_l11_n471(x)
+ end
+end
+
+def fun_l10_n248(x)
+ if (x < 1)
+ fun_l11_n45(x)
+ else
+ fun_l11_n919(x)
+ end
+end
+
+def fun_l10_n249(x)
+ if (x < 1)
+ fun_l11_n13(x)
+ else
+ fun_l11_n526(x)
+ end
+end
+
+def fun_l10_n250(x)
+ if (x < 1)
+ fun_l11_n997(x)
+ else
+ fun_l11_n112(x)
+ end
+end
+
+def fun_l10_n251(x)
+ if (x < 1)
+ fun_l11_n662(x)
+ else
+ fun_l11_n950(x)
+ end
+end
+
+def fun_l10_n252(x)
+ if (x < 1)
+ fun_l11_n272(x)
+ else
+ fun_l11_n345(x)
+ end
+end
+
+def fun_l10_n253(x)
+ if (x < 1)
+ fun_l11_n28(x)
+ else
+ fun_l11_n24(x)
+ end
+end
+
+def fun_l10_n254(x)
+ if (x < 1)
+ fun_l11_n326(x)
+ else
+ fun_l11_n907(x)
+ end
+end
+
+def fun_l10_n255(x)
+ if (x < 1)
+ fun_l11_n612(x)
+ else
+ fun_l11_n790(x)
+ end
+end
+
+def fun_l10_n256(x)
+ if (x < 1)
+ fun_l11_n50(x)
+ else
+ fun_l11_n16(x)
+ end
+end
+
+def fun_l10_n257(x)
+ if (x < 1)
+ fun_l11_n350(x)
+ else
+ fun_l11_n151(x)
+ end
+end
+
+def fun_l10_n258(x)
+ if (x < 1)
+ fun_l11_n290(x)
+ else
+ fun_l11_n113(x)
+ end
+end
+
+def fun_l10_n259(x)
+ if (x < 1)
+ fun_l11_n751(x)
+ else
+ fun_l11_n16(x)
+ end
+end
+
+def fun_l10_n260(x)
+ if (x < 1)
+ fun_l11_n337(x)
+ else
+ fun_l11_n516(x)
+ end
+end
+
+def fun_l10_n261(x)
+ if (x < 1)
+ fun_l11_n530(x)
+ else
+ fun_l11_n19(x)
+ end
+end
+
+def fun_l10_n262(x)
+ if (x < 1)
+ fun_l11_n977(x)
+ else
+ fun_l11_n529(x)
+ end
+end
+
+def fun_l10_n263(x)
+ if (x < 1)
+ fun_l11_n769(x)
+ else
+ fun_l11_n723(x)
+ end
+end
+
+def fun_l10_n264(x)
+ if (x < 1)
+ fun_l11_n673(x)
+ else
+ fun_l11_n771(x)
+ end
+end
+
+def fun_l10_n265(x)
+ if (x < 1)
+ fun_l11_n28(x)
+ else
+ fun_l11_n427(x)
+ end
+end
+
+def fun_l10_n266(x)
+ if (x < 1)
+ fun_l11_n92(x)
+ else
+ fun_l11_n590(x)
+ end
+end
+
+def fun_l10_n267(x)
+ if (x < 1)
+ fun_l11_n762(x)
+ else
+ fun_l11_n352(x)
+ end
+end
+
+def fun_l10_n268(x)
+ if (x < 1)
+ fun_l11_n988(x)
+ else
+ fun_l11_n126(x)
+ end
+end
+
+def fun_l10_n269(x)
+ if (x < 1)
+ fun_l11_n92(x)
+ else
+ fun_l11_n455(x)
+ end
+end
+
+def fun_l10_n270(x)
+ if (x < 1)
+ fun_l11_n233(x)
+ else
+ fun_l11_n404(x)
+ end
+end
+
+def fun_l10_n271(x)
+ if (x < 1)
+ fun_l11_n122(x)
+ else
+ fun_l11_n245(x)
+ end
+end
+
+def fun_l10_n272(x)
+ if (x < 1)
+ fun_l11_n277(x)
+ else
+ fun_l11_n969(x)
+ end
+end
+
+def fun_l10_n273(x)
+ if (x < 1)
+ fun_l11_n848(x)
+ else
+ fun_l11_n56(x)
+ end
+end
+
+def fun_l10_n274(x)
+ if (x < 1)
+ fun_l11_n640(x)
+ else
+ fun_l11_n632(x)
+ end
+end
+
+def fun_l10_n275(x)
+ if (x < 1)
+ fun_l11_n38(x)
+ else
+ fun_l11_n816(x)
+ end
+end
+
+def fun_l10_n276(x)
+ if (x < 1)
+ fun_l11_n706(x)
+ else
+ fun_l11_n126(x)
+ end
+end
+
+def fun_l10_n277(x)
+ if (x < 1)
+ fun_l11_n710(x)
+ else
+ fun_l11_n128(x)
+ end
+end
+
+def fun_l10_n278(x)
+ if (x < 1)
+ fun_l11_n175(x)
+ else
+ fun_l11_n954(x)
+ end
+end
+
+def fun_l10_n279(x)
+ if (x < 1)
+ fun_l11_n379(x)
+ else
+ fun_l11_n58(x)
+ end
+end
+
+def fun_l10_n280(x)
+ if (x < 1)
+ fun_l11_n926(x)
+ else
+ fun_l11_n287(x)
+ end
+end
+
+def fun_l10_n281(x)
+ if (x < 1)
+ fun_l11_n981(x)
+ else
+ fun_l11_n921(x)
+ end
+end
+
+def fun_l10_n282(x)
+ if (x < 1)
+ fun_l11_n222(x)
+ else
+ fun_l11_n954(x)
+ end
+end
+
+def fun_l10_n283(x)
+ if (x < 1)
+ fun_l11_n295(x)
+ else
+ fun_l11_n575(x)
+ end
+end
+
+def fun_l10_n284(x)
+ if (x < 1)
+ fun_l11_n554(x)
+ else
+ fun_l11_n559(x)
+ end
+end
+
+def fun_l10_n285(x)
+ if (x < 1)
+ fun_l11_n476(x)
+ else
+ fun_l11_n487(x)
+ end
+end
+
+def fun_l10_n286(x)
+ if (x < 1)
+ fun_l11_n102(x)
+ else
+ fun_l11_n928(x)
+ end
+end
+
+def fun_l10_n287(x)
+ if (x < 1)
+ fun_l11_n949(x)
+ else
+ fun_l11_n900(x)
+ end
+end
+
+def fun_l10_n288(x)
+ if (x < 1)
+ fun_l11_n717(x)
+ else
+ fun_l11_n762(x)
+ end
+end
+
+def fun_l10_n289(x)
+ if (x < 1)
+ fun_l11_n304(x)
+ else
+ fun_l11_n572(x)
+ end
+end
+
+def fun_l10_n290(x)
+ if (x < 1)
+ fun_l11_n748(x)
+ else
+ fun_l11_n791(x)
+ end
+end
+
+def fun_l10_n291(x)
+ if (x < 1)
+ fun_l11_n557(x)
+ else
+ fun_l11_n79(x)
+ end
+end
+
+def fun_l10_n292(x)
+ if (x < 1)
+ fun_l11_n74(x)
+ else
+ fun_l11_n931(x)
+ end
+end
+
+def fun_l10_n293(x)
+ if (x < 1)
+ fun_l11_n31(x)
+ else
+ fun_l11_n791(x)
+ end
+end
+
+def fun_l10_n294(x)
+ if (x < 1)
+ fun_l11_n29(x)
+ else
+ fun_l11_n377(x)
+ end
+end
+
+def fun_l10_n295(x)
+ if (x < 1)
+ fun_l11_n509(x)
+ else
+ fun_l11_n900(x)
+ end
+end
+
+def fun_l10_n296(x)
+ if (x < 1)
+ fun_l11_n594(x)
+ else
+ fun_l11_n835(x)
+ end
+end
+
+def fun_l10_n297(x)
+ if (x < 1)
+ fun_l11_n943(x)
+ else
+ fun_l11_n621(x)
+ end
+end
+
+def fun_l10_n298(x)
+ if (x < 1)
+ fun_l11_n860(x)
+ else
+ fun_l11_n403(x)
+ end
+end
+
+def fun_l10_n299(x)
+ if (x < 1)
+ fun_l11_n676(x)
+ else
+ fun_l11_n478(x)
+ end
+end
+
+def fun_l10_n300(x)
+ if (x < 1)
+ fun_l11_n513(x)
+ else
+ fun_l11_n661(x)
+ end
+end
+
+def fun_l10_n301(x)
+ if (x < 1)
+ fun_l11_n513(x)
+ else
+ fun_l11_n30(x)
+ end
+end
+
+def fun_l10_n302(x)
+ if (x < 1)
+ fun_l11_n763(x)
+ else
+ fun_l11_n823(x)
+ end
+end
+
+def fun_l10_n303(x)
+ if (x < 1)
+ fun_l11_n469(x)
+ else
+ fun_l11_n250(x)
+ end
+end
+
+def fun_l10_n304(x)
+ if (x < 1)
+ fun_l11_n637(x)
+ else
+ fun_l11_n478(x)
+ end
+end
+
+def fun_l10_n305(x)
+ if (x < 1)
+ fun_l11_n825(x)
+ else
+ fun_l11_n258(x)
+ end
+end
+
+def fun_l10_n306(x)
+ if (x < 1)
+ fun_l11_n264(x)
+ else
+ fun_l11_n698(x)
+ end
+end
+
+def fun_l10_n307(x)
+ if (x < 1)
+ fun_l11_n426(x)
+ else
+ fun_l11_n490(x)
+ end
+end
+
+def fun_l10_n308(x)
+ if (x < 1)
+ fun_l11_n157(x)
+ else
+ fun_l11_n407(x)
+ end
+end
+
+def fun_l10_n309(x)
+ if (x < 1)
+ fun_l11_n68(x)
+ else
+ fun_l11_n424(x)
+ end
+end
+
+def fun_l10_n310(x)
+ if (x < 1)
+ fun_l11_n844(x)
+ else
+ fun_l11_n955(x)
+ end
+end
+
+def fun_l10_n311(x)
+ if (x < 1)
+ fun_l11_n316(x)
+ else
+ fun_l11_n27(x)
+ end
+end
+
+def fun_l10_n312(x)
+ if (x < 1)
+ fun_l11_n771(x)
+ else
+ fun_l11_n604(x)
+ end
+end
+
+def fun_l10_n313(x)
+ if (x < 1)
+ fun_l11_n436(x)
+ else
+ fun_l11_n714(x)
+ end
+end
+
+def fun_l10_n314(x)
+ if (x < 1)
+ fun_l11_n791(x)
+ else
+ fun_l11_n889(x)
+ end
+end
+
+def fun_l10_n315(x)
+ if (x < 1)
+ fun_l11_n621(x)
+ else
+ fun_l11_n694(x)
+ end
+end
+
+def fun_l10_n316(x)
+ if (x < 1)
+ fun_l11_n403(x)
+ else
+ fun_l11_n625(x)
+ end
+end
+
+def fun_l10_n317(x)
+ if (x < 1)
+ fun_l11_n532(x)
+ else
+ fun_l11_n920(x)
+ end
+end
+
+def fun_l10_n318(x)
+ if (x < 1)
+ fun_l11_n895(x)
+ else
+ fun_l11_n781(x)
+ end
+end
+
+def fun_l10_n319(x)
+ if (x < 1)
+ fun_l11_n109(x)
+ else
+ fun_l11_n254(x)
+ end
+end
+
+def fun_l10_n320(x)
+ if (x < 1)
+ fun_l11_n842(x)
+ else
+ fun_l11_n879(x)
+ end
+end
+
+def fun_l10_n321(x)
+ if (x < 1)
+ fun_l11_n655(x)
+ else
+ fun_l11_n518(x)
+ end
+end
+
+def fun_l10_n322(x)
+ if (x < 1)
+ fun_l11_n727(x)
+ else
+ fun_l11_n14(x)
+ end
+end
+
+def fun_l10_n323(x)
+ if (x < 1)
+ fun_l11_n808(x)
+ else
+ fun_l11_n128(x)
+ end
+end
+
+def fun_l10_n324(x)
+ if (x < 1)
+ fun_l11_n412(x)
+ else
+ fun_l11_n940(x)
+ end
+end
+
+def fun_l10_n325(x)
+ if (x < 1)
+ fun_l11_n944(x)
+ else
+ fun_l11_n915(x)
+ end
+end
+
+def fun_l10_n326(x)
+ if (x < 1)
+ fun_l11_n120(x)
+ else
+ fun_l11_n572(x)
+ end
+end
+
+def fun_l10_n327(x)
+ if (x < 1)
+ fun_l11_n444(x)
+ else
+ fun_l11_n793(x)
+ end
+end
+
+def fun_l10_n328(x)
+ if (x < 1)
+ fun_l11_n892(x)
+ else
+ fun_l11_n475(x)
+ end
+end
+
+def fun_l10_n329(x)
+ if (x < 1)
+ fun_l11_n919(x)
+ else
+ fun_l11_n183(x)
+ end
+end
+
+def fun_l10_n330(x)
+ if (x < 1)
+ fun_l11_n80(x)
+ else
+ fun_l11_n357(x)
+ end
+end
+
+def fun_l10_n331(x)
+ if (x < 1)
+ fun_l11_n340(x)
+ else
+ fun_l11_n349(x)
+ end
+end
+
+def fun_l10_n332(x)
+ if (x < 1)
+ fun_l11_n579(x)
+ else
+ fun_l11_n845(x)
+ end
+end
+
+def fun_l10_n333(x)
+ if (x < 1)
+ fun_l11_n169(x)
+ else
+ fun_l11_n583(x)
+ end
+end
+
+def fun_l10_n334(x)
+ if (x < 1)
+ fun_l11_n544(x)
+ else
+ fun_l11_n462(x)
+ end
+end
+
+def fun_l10_n335(x)
+ if (x < 1)
+ fun_l11_n51(x)
+ else
+ fun_l11_n635(x)
+ end
+end
+
+def fun_l10_n336(x)
+ if (x < 1)
+ fun_l11_n965(x)
+ else
+ fun_l11_n538(x)
+ end
+end
+
+def fun_l10_n337(x)
+ if (x < 1)
+ fun_l11_n930(x)
+ else
+ fun_l11_n169(x)
+ end
+end
+
+def fun_l10_n338(x)
+ if (x < 1)
+ fun_l11_n732(x)
+ else
+ fun_l11_n574(x)
+ end
+end
+
+def fun_l10_n339(x)
+ if (x < 1)
+ fun_l11_n51(x)
+ else
+ fun_l11_n141(x)
+ end
+end
+
+def fun_l10_n340(x)
+ if (x < 1)
+ fun_l11_n149(x)
+ else
+ fun_l11_n346(x)
+ end
+end
+
+def fun_l10_n341(x)
+ if (x < 1)
+ fun_l11_n163(x)
+ else
+ fun_l11_n224(x)
+ end
+end
+
+def fun_l10_n342(x)
+ if (x < 1)
+ fun_l11_n175(x)
+ else
+ fun_l11_n40(x)
+ end
+end
+
+def fun_l10_n343(x)
+ if (x < 1)
+ fun_l11_n156(x)
+ else
+ fun_l11_n639(x)
+ end
+end
+
+def fun_l10_n344(x)
+ if (x < 1)
+ fun_l11_n934(x)
+ else
+ fun_l11_n85(x)
+ end
+end
+
+def fun_l10_n345(x)
+ if (x < 1)
+ fun_l11_n182(x)
+ else
+ fun_l11_n190(x)
+ end
+end
+
+def fun_l10_n346(x)
+ if (x < 1)
+ fun_l11_n879(x)
+ else
+ fun_l11_n702(x)
+ end
+end
+
+def fun_l10_n347(x)
+ if (x < 1)
+ fun_l11_n540(x)
+ else
+ fun_l11_n689(x)
+ end
+end
+
+def fun_l10_n348(x)
+ if (x < 1)
+ fun_l11_n945(x)
+ else
+ fun_l11_n39(x)
+ end
+end
+
+def fun_l10_n349(x)
+ if (x < 1)
+ fun_l11_n683(x)
+ else
+ fun_l11_n688(x)
+ end
+end
+
+def fun_l10_n350(x)
+ if (x < 1)
+ fun_l11_n750(x)
+ else
+ fun_l11_n577(x)
+ end
+end
+
+def fun_l10_n351(x)
+ if (x < 1)
+ fun_l11_n74(x)
+ else
+ fun_l11_n672(x)
+ end
+end
+
+def fun_l10_n352(x)
+ if (x < 1)
+ fun_l11_n252(x)
+ else
+ fun_l11_n766(x)
+ end
+end
+
+def fun_l10_n353(x)
+ if (x < 1)
+ fun_l11_n702(x)
+ else
+ fun_l11_n516(x)
+ end
+end
+
+def fun_l10_n354(x)
+ if (x < 1)
+ fun_l11_n19(x)
+ else
+ fun_l11_n290(x)
+ end
+end
+
+def fun_l10_n355(x)
+ if (x < 1)
+ fun_l11_n70(x)
+ else
+ fun_l11_n553(x)
+ end
+end
+
+def fun_l10_n356(x)
+ if (x < 1)
+ fun_l11_n654(x)
+ else
+ fun_l11_n108(x)
+ end
+end
+
+def fun_l10_n357(x)
+ if (x < 1)
+ fun_l11_n820(x)
+ else
+ fun_l11_n320(x)
+ end
+end
+
+def fun_l10_n358(x)
+ if (x < 1)
+ fun_l11_n417(x)
+ else
+ fun_l11_n290(x)
+ end
+end
+
+def fun_l10_n359(x)
+ if (x < 1)
+ fun_l11_n832(x)
+ else
+ fun_l11_n647(x)
+ end
+end
+
+def fun_l10_n360(x)
+ if (x < 1)
+ fun_l11_n625(x)
+ else
+ fun_l11_n723(x)
+ end
+end
+
+def fun_l10_n361(x)
+ if (x < 1)
+ fun_l11_n257(x)
+ else
+ fun_l11_n991(x)
+ end
+end
+
+def fun_l10_n362(x)
+ if (x < 1)
+ fun_l11_n101(x)
+ else
+ fun_l11_n247(x)
+ end
+end
+
+def fun_l10_n363(x)
+ if (x < 1)
+ fun_l11_n484(x)
+ else
+ fun_l11_n953(x)
+ end
+end
+
+def fun_l10_n364(x)
+ if (x < 1)
+ fun_l11_n281(x)
+ else
+ fun_l11_n846(x)
+ end
+end
+
+def fun_l10_n365(x)
+ if (x < 1)
+ fun_l11_n425(x)
+ else
+ fun_l11_n772(x)
+ end
+end
+
+def fun_l10_n366(x)
+ if (x < 1)
+ fun_l11_n724(x)
+ else
+ fun_l11_n725(x)
+ end
+end
+
+def fun_l10_n367(x)
+ if (x < 1)
+ fun_l11_n943(x)
+ else
+ fun_l11_n360(x)
+ end
+end
+
+def fun_l10_n368(x)
+ if (x < 1)
+ fun_l11_n874(x)
+ else
+ fun_l11_n698(x)
+ end
+end
+
+def fun_l10_n369(x)
+ if (x < 1)
+ fun_l11_n419(x)
+ else
+ fun_l11_n672(x)
+ end
+end
+
+def fun_l10_n370(x)
+ if (x < 1)
+ fun_l11_n655(x)
+ else
+ fun_l11_n468(x)
+ end
+end
+
+def fun_l10_n371(x)
+ if (x < 1)
+ fun_l11_n577(x)
+ else
+ fun_l11_n402(x)
+ end
+end
+
+def fun_l10_n372(x)
+ if (x < 1)
+ fun_l11_n531(x)
+ else
+ fun_l11_n319(x)
+ end
+end
+
+def fun_l10_n373(x)
+ if (x < 1)
+ fun_l11_n972(x)
+ else
+ fun_l11_n901(x)
+ end
+end
+
+def fun_l10_n374(x)
+ if (x < 1)
+ fun_l11_n59(x)
+ else
+ fun_l11_n12(x)
+ end
+end
+
+def fun_l10_n375(x)
+ if (x < 1)
+ fun_l11_n409(x)
+ else
+ fun_l11_n214(x)
+ end
+end
+
+def fun_l10_n376(x)
+ if (x < 1)
+ fun_l11_n52(x)
+ else
+ fun_l11_n395(x)
+ end
+end
+
+def fun_l10_n377(x)
+ if (x < 1)
+ fun_l11_n594(x)
+ else
+ fun_l11_n434(x)
+ end
+end
+
+def fun_l10_n378(x)
+ if (x < 1)
+ fun_l11_n795(x)
+ else
+ fun_l11_n820(x)
+ end
+end
+
+def fun_l10_n379(x)
+ if (x < 1)
+ fun_l11_n962(x)
+ else
+ fun_l11_n111(x)
+ end
+end
+
+def fun_l10_n380(x)
+ if (x < 1)
+ fun_l11_n762(x)
+ else
+ fun_l11_n678(x)
+ end
+end
+
+def fun_l10_n381(x)
+ if (x < 1)
+ fun_l11_n324(x)
+ else
+ fun_l11_n478(x)
+ end
+end
+
+def fun_l10_n382(x)
+ if (x < 1)
+ fun_l11_n360(x)
+ else
+ fun_l11_n35(x)
+ end
+end
+
+def fun_l10_n383(x)
+ if (x < 1)
+ fun_l11_n710(x)
+ else
+ fun_l11_n898(x)
+ end
+end
+
+def fun_l10_n384(x)
+ if (x < 1)
+ fun_l11_n584(x)
+ else
+ fun_l11_n260(x)
+ end
+end
+
+def fun_l10_n385(x)
+ if (x < 1)
+ fun_l11_n514(x)
+ else
+ fun_l11_n649(x)
+ end
+end
+
+def fun_l10_n386(x)
+ if (x < 1)
+ fun_l11_n426(x)
+ else
+ fun_l11_n391(x)
+ end
+end
+
+def fun_l10_n387(x)
+ if (x < 1)
+ fun_l11_n713(x)
+ else
+ fun_l11_n734(x)
+ end
+end
+
+def fun_l10_n388(x)
+ if (x < 1)
+ fun_l11_n236(x)
+ else
+ fun_l11_n469(x)
+ end
+end
+
+def fun_l10_n389(x)
+ if (x < 1)
+ fun_l11_n267(x)
+ else
+ fun_l11_n965(x)
+ end
+end
+
+def fun_l10_n390(x)
+ if (x < 1)
+ fun_l11_n943(x)
+ else
+ fun_l11_n181(x)
+ end
+end
+
+def fun_l10_n391(x)
+ if (x < 1)
+ fun_l11_n869(x)
+ else
+ fun_l11_n348(x)
+ end
+end
+
+def fun_l10_n392(x)
+ if (x < 1)
+ fun_l11_n144(x)
+ else
+ fun_l11_n801(x)
+ end
+end
+
+def fun_l10_n393(x)
+ if (x < 1)
+ fun_l11_n907(x)
+ else
+ fun_l11_n609(x)
+ end
+end
+
+def fun_l10_n394(x)
+ if (x < 1)
+ fun_l11_n801(x)
+ else
+ fun_l11_n691(x)
+ end
+end
+
+def fun_l10_n395(x)
+ if (x < 1)
+ fun_l11_n629(x)
+ else
+ fun_l11_n924(x)
+ end
+end
+
+def fun_l10_n396(x)
+ if (x < 1)
+ fun_l11_n191(x)
+ else
+ fun_l11_n248(x)
+ end
+end
+
+def fun_l10_n397(x)
+ if (x < 1)
+ fun_l11_n339(x)
+ else
+ fun_l11_n805(x)
+ end
+end
+
+def fun_l10_n398(x)
+ if (x < 1)
+ fun_l11_n798(x)
+ else
+ fun_l11_n154(x)
+ end
+end
+
+def fun_l10_n399(x)
+ if (x < 1)
+ fun_l11_n847(x)
+ else
+ fun_l11_n14(x)
+ end
+end
+
+def fun_l10_n400(x)
+ if (x < 1)
+ fun_l11_n296(x)
+ else
+ fun_l11_n144(x)
+ end
+end
+
+def fun_l10_n401(x)
+ if (x < 1)
+ fun_l11_n853(x)
+ else
+ fun_l11_n156(x)
+ end
+end
+
+def fun_l10_n402(x)
+ if (x < 1)
+ fun_l11_n54(x)
+ else
+ fun_l11_n944(x)
+ end
+end
+
+def fun_l10_n403(x)
+ if (x < 1)
+ fun_l11_n617(x)
+ else
+ fun_l11_n324(x)
+ end
+end
+
+def fun_l10_n404(x)
+ if (x < 1)
+ fun_l11_n962(x)
+ else
+ fun_l11_n139(x)
+ end
+end
+
+def fun_l10_n405(x)
+ if (x < 1)
+ fun_l11_n466(x)
+ else
+ fun_l11_n388(x)
+ end
+end
+
+def fun_l10_n406(x)
+ if (x < 1)
+ fun_l11_n914(x)
+ else
+ fun_l11_n847(x)
+ end
+end
+
+def fun_l10_n407(x)
+ if (x < 1)
+ fun_l11_n741(x)
+ else
+ fun_l11_n757(x)
+ end
+end
+
+def fun_l10_n408(x)
+ if (x < 1)
+ fun_l11_n36(x)
+ else
+ fun_l11_n312(x)
+ end
+end
+
+def fun_l10_n409(x)
+ if (x < 1)
+ fun_l11_n203(x)
+ else
+ fun_l11_n523(x)
+ end
+end
+
+def fun_l10_n410(x)
+ if (x < 1)
+ fun_l11_n187(x)
+ else
+ fun_l11_n291(x)
+ end
+end
+
+def fun_l10_n411(x)
+ if (x < 1)
+ fun_l11_n13(x)
+ else
+ fun_l11_n107(x)
+ end
+end
+
+def fun_l10_n412(x)
+ if (x < 1)
+ fun_l11_n960(x)
+ else
+ fun_l11_n565(x)
+ end
+end
+
+def fun_l10_n413(x)
+ if (x < 1)
+ fun_l11_n549(x)
+ else
+ fun_l11_n885(x)
+ end
+end
+
+def fun_l10_n414(x)
+ if (x < 1)
+ fun_l11_n559(x)
+ else
+ fun_l11_n612(x)
+ end
+end
+
+def fun_l10_n415(x)
+ if (x < 1)
+ fun_l11_n18(x)
+ else
+ fun_l11_n167(x)
+ end
+end
+
+def fun_l10_n416(x)
+ if (x < 1)
+ fun_l11_n125(x)
+ else
+ fun_l11_n206(x)
+ end
+end
+
+def fun_l10_n417(x)
+ if (x < 1)
+ fun_l11_n980(x)
+ else
+ fun_l11_n497(x)
+ end
+end
+
+def fun_l10_n418(x)
+ if (x < 1)
+ fun_l11_n703(x)
+ else
+ fun_l11_n49(x)
+ end
+end
+
+def fun_l10_n419(x)
+ if (x < 1)
+ fun_l11_n690(x)
+ else
+ fun_l11_n63(x)
+ end
+end
+
+def fun_l10_n420(x)
+ if (x < 1)
+ fun_l11_n219(x)
+ else
+ fun_l11_n814(x)
+ end
+end
+
+def fun_l10_n421(x)
+ if (x < 1)
+ fun_l11_n864(x)
+ else
+ fun_l11_n963(x)
+ end
+end
+
+def fun_l10_n422(x)
+ if (x < 1)
+ fun_l11_n672(x)
+ else
+ fun_l11_n87(x)
+ end
+end
+
+def fun_l10_n423(x)
+ if (x < 1)
+ fun_l11_n41(x)
+ else
+ fun_l11_n461(x)
+ end
+end
+
+def fun_l10_n424(x)
+ if (x < 1)
+ fun_l11_n334(x)
+ else
+ fun_l11_n283(x)
+ end
+end
+
+def fun_l10_n425(x)
+ if (x < 1)
+ fun_l11_n369(x)
+ else
+ fun_l11_n269(x)
+ end
+end
+
+def fun_l10_n426(x)
+ if (x < 1)
+ fun_l11_n832(x)
+ else
+ fun_l11_n625(x)
+ end
+end
+
+def fun_l10_n427(x)
+ if (x < 1)
+ fun_l11_n272(x)
+ else
+ fun_l11_n634(x)
+ end
+end
+
+def fun_l10_n428(x)
+ if (x < 1)
+ fun_l11_n122(x)
+ else
+ fun_l11_n53(x)
+ end
+end
+
+def fun_l10_n429(x)
+ if (x < 1)
+ fun_l11_n895(x)
+ else
+ fun_l11_n292(x)
+ end
+end
+
+def fun_l10_n430(x)
+ if (x < 1)
+ fun_l11_n460(x)
+ else
+ fun_l11_n177(x)
+ end
+end
+
+def fun_l10_n431(x)
+ if (x < 1)
+ fun_l11_n238(x)
+ else
+ fun_l11_n938(x)
+ end
+end
+
+def fun_l10_n432(x)
+ if (x < 1)
+ fun_l11_n302(x)
+ else
+ fun_l11_n492(x)
+ end
+end
+
+def fun_l10_n433(x)
+ if (x < 1)
+ fun_l11_n307(x)
+ else
+ fun_l11_n876(x)
+ end
+end
+
+def fun_l10_n434(x)
+ if (x < 1)
+ fun_l11_n64(x)
+ else
+ fun_l11_n892(x)
+ end
+end
+
+def fun_l10_n435(x)
+ if (x < 1)
+ fun_l11_n940(x)
+ else
+ fun_l11_n718(x)
+ end
+end
+
+def fun_l10_n436(x)
+ if (x < 1)
+ fun_l11_n988(x)
+ else
+ fun_l11_n216(x)
+ end
+end
+
+def fun_l10_n437(x)
+ if (x < 1)
+ fun_l11_n282(x)
+ else
+ fun_l11_n168(x)
+ end
+end
+
+def fun_l10_n438(x)
+ if (x < 1)
+ fun_l11_n529(x)
+ else
+ fun_l11_n66(x)
+ end
+end
+
+def fun_l10_n439(x)
+ if (x < 1)
+ fun_l11_n286(x)
+ else
+ fun_l11_n134(x)
+ end
+end
+
+def fun_l10_n440(x)
+ if (x < 1)
+ fun_l11_n454(x)
+ else
+ fun_l11_n873(x)
+ end
+end
+
+def fun_l10_n441(x)
+ if (x < 1)
+ fun_l11_n871(x)
+ else
+ fun_l11_n13(x)
+ end
+end
+
+def fun_l10_n442(x)
+ if (x < 1)
+ fun_l11_n314(x)
+ else
+ fun_l11_n685(x)
+ end
+end
+
+def fun_l10_n443(x)
+ if (x < 1)
+ fun_l11_n752(x)
+ else
+ fun_l11_n162(x)
+ end
+end
+
+def fun_l10_n444(x)
+ if (x < 1)
+ fun_l11_n686(x)
+ else
+ fun_l11_n585(x)
+ end
+end
+
+def fun_l10_n445(x)
+ if (x < 1)
+ fun_l11_n42(x)
+ else
+ fun_l11_n932(x)
+ end
+end
+
+def fun_l10_n446(x)
+ if (x < 1)
+ fun_l11_n433(x)
+ else
+ fun_l11_n241(x)
+ end
+end
+
+def fun_l10_n447(x)
+ if (x < 1)
+ fun_l11_n99(x)
+ else
+ fun_l11_n563(x)
+ end
+end
+
+def fun_l10_n448(x)
+ if (x < 1)
+ fun_l11_n463(x)
+ else
+ fun_l11_n395(x)
+ end
+end
+
+def fun_l10_n449(x)
+ if (x < 1)
+ fun_l11_n393(x)
+ else
+ fun_l11_n151(x)
+ end
+end
+
+def fun_l10_n450(x)
+ if (x < 1)
+ fun_l11_n255(x)
+ else
+ fun_l11_n834(x)
+ end
+end
+
+def fun_l10_n451(x)
+ if (x < 1)
+ fun_l11_n195(x)
+ else
+ fun_l11_n0(x)
+ end
+end
+
+def fun_l10_n452(x)
+ if (x < 1)
+ fun_l11_n372(x)
+ else
+ fun_l11_n228(x)
+ end
+end
+
+def fun_l10_n453(x)
+ if (x < 1)
+ fun_l11_n526(x)
+ else
+ fun_l11_n54(x)
+ end
+end
+
+def fun_l10_n454(x)
+ if (x < 1)
+ fun_l11_n594(x)
+ else
+ fun_l11_n116(x)
+ end
+end
+
+def fun_l10_n455(x)
+ if (x < 1)
+ fun_l11_n25(x)
+ else
+ fun_l11_n930(x)
+ end
+end
+
+def fun_l10_n456(x)
+ if (x < 1)
+ fun_l11_n83(x)
+ else
+ fun_l11_n30(x)
+ end
+end
+
+def fun_l10_n457(x)
+ if (x < 1)
+ fun_l11_n644(x)
+ else
+ fun_l11_n837(x)
+ end
+end
+
+def fun_l10_n458(x)
+ if (x < 1)
+ fun_l11_n311(x)
+ else
+ fun_l11_n86(x)
+ end
+end
+
+def fun_l10_n459(x)
+ if (x < 1)
+ fun_l11_n139(x)
+ else
+ fun_l11_n735(x)
+ end
+end
+
+def fun_l10_n460(x)
+ if (x < 1)
+ fun_l11_n431(x)
+ else
+ fun_l11_n808(x)
+ end
+end
+
+def fun_l10_n461(x)
+ if (x < 1)
+ fun_l11_n488(x)
+ else
+ fun_l11_n439(x)
+ end
+end
+
+def fun_l10_n462(x)
+ if (x < 1)
+ fun_l11_n448(x)
+ else
+ fun_l11_n882(x)
+ end
+end
+
+def fun_l10_n463(x)
+ if (x < 1)
+ fun_l11_n362(x)
+ else
+ fun_l11_n875(x)
+ end
+end
+
+def fun_l10_n464(x)
+ if (x < 1)
+ fun_l11_n88(x)
+ else
+ fun_l11_n842(x)
+ end
+end
+
+def fun_l10_n465(x)
+ if (x < 1)
+ fun_l11_n651(x)
+ else
+ fun_l11_n368(x)
+ end
+end
+
+def fun_l10_n466(x)
+ if (x < 1)
+ fun_l11_n121(x)
+ else
+ fun_l11_n3(x)
+ end
+end
+
+def fun_l10_n467(x)
+ if (x < 1)
+ fun_l11_n654(x)
+ else
+ fun_l11_n260(x)
+ end
+end
+
+def fun_l10_n468(x)
+ if (x < 1)
+ fun_l11_n765(x)
+ else
+ fun_l11_n604(x)
+ end
+end
+
+def fun_l10_n469(x)
+ if (x < 1)
+ fun_l11_n881(x)
+ else
+ fun_l11_n567(x)
+ end
+end
+
+def fun_l10_n470(x)
+ if (x < 1)
+ fun_l11_n41(x)
+ else
+ fun_l11_n92(x)
+ end
+end
+
+def fun_l10_n471(x)
+ if (x < 1)
+ fun_l11_n905(x)
+ else
+ fun_l11_n731(x)
+ end
+end
+
+def fun_l10_n472(x)
+ if (x < 1)
+ fun_l11_n797(x)
+ else
+ fun_l11_n878(x)
+ end
+end
+
+def fun_l10_n473(x)
+ if (x < 1)
+ fun_l11_n487(x)
+ else
+ fun_l11_n951(x)
+ end
+end
+
+def fun_l10_n474(x)
+ if (x < 1)
+ fun_l11_n998(x)
+ else
+ fun_l11_n900(x)
+ end
+end
+
+def fun_l10_n475(x)
+ if (x < 1)
+ fun_l11_n451(x)
+ else
+ fun_l11_n780(x)
+ end
+end
+
+def fun_l10_n476(x)
+ if (x < 1)
+ fun_l11_n427(x)
+ else
+ fun_l11_n760(x)
+ end
+end
+
+def fun_l10_n477(x)
+ if (x < 1)
+ fun_l11_n758(x)
+ else
+ fun_l11_n177(x)
+ end
+end
+
+def fun_l10_n478(x)
+ if (x < 1)
+ fun_l11_n359(x)
+ else
+ fun_l11_n236(x)
+ end
+end
+
+def fun_l10_n479(x)
+ if (x < 1)
+ fun_l11_n70(x)
+ else
+ fun_l11_n49(x)
+ end
+end
+
+def fun_l10_n480(x)
+ if (x < 1)
+ fun_l11_n338(x)
+ else
+ fun_l11_n714(x)
+ end
+end
+
+def fun_l10_n481(x)
+ if (x < 1)
+ fun_l11_n6(x)
+ else
+ fun_l11_n194(x)
+ end
+end
+
+def fun_l10_n482(x)
+ if (x < 1)
+ fun_l11_n801(x)
+ else
+ fun_l11_n591(x)
+ end
+end
+
+def fun_l10_n483(x)
+ if (x < 1)
+ fun_l11_n362(x)
+ else
+ fun_l11_n687(x)
+ end
+end
+
+def fun_l10_n484(x)
+ if (x < 1)
+ fun_l11_n659(x)
+ else
+ fun_l11_n661(x)
+ end
+end
+
+def fun_l10_n485(x)
+ if (x < 1)
+ fun_l11_n903(x)
+ else
+ fun_l11_n419(x)
+ end
+end
+
+def fun_l10_n486(x)
+ if (x < 1)
+ fun_l11_n279(x)
+ else
+ fun_l11_n995(x)
+ end
+end
+
+def fun_l10_n487(x)
+ if (x < 1)
+ fun_l11_n529(x)
+ else
+ fun_l11_n373(x)
+ end
+end
+
+def fun_l10_n488(x)
+ if (x < 1)
+ fun_l11_n198(x)
+ else
+ fun_l11_n899(x)
+ end
+end
+
+def fun_l10_n489(x)
+ if (x < 1)
+ fun_l11_n174(x)
+ else
+ fun_l11_n485(x)
+ end
+end
+
+def fun_l10_n490(x)
+ if (x < 1)
+ fun_l11_n19(x)
+ else
+ fun_l11_n322(x)
+ end
+end
+
+def fun_l10_n491(x)
+ if (x < 1)
+ fun_l11_n0(x)
+ else
+ fun_l11_n855(x)
+ end
+end
+
+def fun_l10_n492(x)
+ if (x < 1)
+ fun_l11_n126(x)
+ else
+ fun_l11_n986(x)
+ end
+end
+
+def fun_l10_n493(x)
+ if (x < 1)
+ fun_l11_n263(x)
+ else
+ fun_l11_n374(x)
+ end
+end
+
+def fun_l10_n494(x)
+ if (x < 1)
+ fun_l11_n21(x)
+ else
+ fun_l11_n749(x)
+ end
+end
+
+def fun_l10_n495(x)
+ if (x < 1)
+ fun_l11_n618(x)
+ else
+ fun_l11_n955(x)
+ end
+end
+
+def fun_l10_n496(x)
+ if (x < 1)
+ fun_l11_n157(x)
+ else
+ fun_l11_n230(x)
+ end
+end
+
+def fun_l10_n497(x)
+ if (x < 1)
+ fun_l11_n387(x)
+ else
+ fun_l11_n841(x)
+ end
+end
+
+def fun_l10_n498(x)
+ if (x < 1)
+ fun_l11_n496(x)
+ else
+ fun_l11_n30(x)
+ end
+end
+
+def fun_l10_n499(x)
+ if (x < 1)
+ fun_l11_n581(x)
+ else
+ fun_l11_n821(x)
+ end
+end
+
+def fun_l10_n500(x)
+ if (x < 1)
+ fun_l11_n202(x)
+ else
+ fun_l11_n26(x)
+ end
+end
+
+def fun_l10_n501(x)
+ if (x < 1)
+ fun_l11_n273(x)
+ else
+ fun_l11_n294(x)
+ end
+end
+
+def fun_l10_n502(x)
+ if (x < 1)
+ fun_l11_n604(x)
+ else
+ fun_l11_n261(x)
+ end
+end
+
+def fun_l10_n503(x)
+ if (x < 1)
+ fun_l11_n632(x)
+ else
+ fun_l11_n340(x)
+ end
+end
+
+def fun_l10_n504(x)
+ if (x < 1)
+ fun_l11_n162(x)
+ else
+ fun_l11_n483(x)
+ end
+end
+
+def fun_l10_n505(x)
+ if (x < 1)
+ fun_l11_n824(x)
+ else
+ fun_l11_n747(x)
+ end
+end
+
+def fun_l10_n506(x)
+ if (x < 1)
+ fun_l11_n575(x)
+ else
+ fun_l11_n932(x)
+ end
+end
+
+def fun_l10_n507(x)
+ if (x < 1)
+ fun_l11_n645(x)
+ else
+ fun_l11_n486(x)
+ end
+end
+
+def fun_l10_n508(x)
+ if (x < 1)
+ fun_l11_n876(x)
+ else
+ fun_l11_n640(x)
+ end
+end
+
+def fun_l10_n509(x)
+ if (x < 1)
+ fun_l11_n280(x)
+ else
+ fun_l11_n116(x)
+ end
+end
+
+def fun_l10_n510(x)
+ if (x < 1)
+ fun_l11_n570(x)
+ else
+ fun_l11_n640(x)
+ end
+end
+
+def fun_l10_n511(x)
+ if (x < 1)
+ fun_l11_n576(x)
+ else
+ fun_l11_n124(x)
+ end
+end
+
+def fun_l10_n512(x)
+ if (x < 1)
+ fun_l11_n328(x)
+ else
+ fun_l11_n880(x)
+ end
+end
+
+def fun_l10_n513(x)
+ if (x < 1)
+ fun_l11_n185(x)
+ else
+ fun_l11_n977(x)
+ end
+end
+
+def fun_l10_n514(x)
+ if (x < 1)
+ fun_l11_n560(x)
+ else
+ fun_l11_n825(x)
+ end
+end
+
+def fun_l10_n515(x)
+ if (x < 1)
+ fun_l11_n28(x)
+ else
+ fun_l11_n908(x)
+ end
+end
+
+def fun_l10_n516(x)
+ if (x < 1)
+ fun_l11_n902(x)
+ else
+ fun_l11_n882(x)
+ end
+end
+
+def fun_l10_n517(x)
+ if (x < 1)
+ fun_l11_n429(x)
+ else
+ fun_l11_n824(x)
+ end
+end
+
+def fun_l10_n518(x)
+ if (x < 1)
+ fun_l11_n706(x)
+ else
+ fun_l11_n149(x)
+ end
+end
+
+def fun_l10_n519(x)
+ if (x < 1)
+ fun_l11_n837(x)
+ else
+ fun_l11_n573(x)
+ end
+end
+
+def fun_l10_n520(x)
+ if (x < 1)
+ fun_l11_n934(x)
+ else
+ fun_l11_n504(x)
+ end
+end
+
+def fun_l10_n521(x)
+ if (x < 1)
+ fun_l11_n254(x)
+ else
+ fun_l11_n551(x)
+ end
+end
+
+def fun_l10_n522(x)
+ if (x < 1)
+ fun_l11_n53(x)
+ else
+ fun_l11_n297(x)
+ end
+end
+
+def fun_l10_n523(x)
+ if (x < 1)
+ fun_l11_n648(x)
+ else
+ fun_l11_n695(x)
+ end
+end
+
+def fun_l10_n524(x)
+ if (x < 1)
+ fun_l11_n737(x)
+ else
+ fun_l11_n636(x)
+ end
+end
+
+def fun_l10_n525(x)
+ if (x < 1)
+ fun_l11_n249(x)
+ else
+ fun_l11_n757(x)
+ end
+end
+
+def fun_l10_n526(x)
+ if (x < 1)
+ fun_l11_n42(x)
+ else
+ fun_l11_n199(x)
+ end
+end
+
+def fun_l10_n527(x)
+ if (x < 1)
+ fun_l11_n783(x)
+ else
+ fun_l11_n856(x)
+ end
+end
+
+def fun_l10_n528(x)
+ if (x < 1)
+ fun_l11_n708(x)
+ else
+ fun_l11_n550(x)
+ end
+end
+
+def fun_l10_n529(x)
+ if (x < 1)
+ fun_l11_n749(x)
+ else
+ fun_l11_n56(x)
+ end
+end
+
+def fun_l10_n530(x)
+ if (x < 1)
+ fun_l11_n838(x)
+ else
+ fun_l11_n57(x)
+ end
+end
+
+def fun_l10_n531(x)
+ if (x < 1)
+ fun_l11_n293(x)
+ else
+ fun_l11_n938(x)
+ end
+end
+
+def fun_l10_n532(x)
+ if (x < 1)
+ fun_l11_n245(x)
+ else
+ fun_l11_n367(x)
+ end
+end
+
+def fun_l10_n533(x)
+ if (x < 1)
+ fun_l11_n255(x)
+ else
+ fun_l11_n234(x)
+ end
+end
+
+def fun_l10_n534(x)
+ if (x < 1)
+ fun_l11_n315(x)
+ else
+ fun_l11_n982(x)
+ end
+end
+
+def fun_l10_n535(x)
+ if (x < 1)
+ fun_l11_n841(x)
+ else
+ fun_l11_n112(x)
+ end
+end
+
+def fun_l10_n536(x)
+ if (x < 1)
+ fun_l11_n481(x)
+ else
+ fun_l11_n622(x)
+ end
+end
+
+def fun_l10_n537(x)
+ if (x < 1)
+ fun_l11_n666(x)
+ else
+ fun_l11_n775(x)
+ end
+end
+
+def fun_l10_n538(x)
+ if (x < 1)
+ fun_l11_n409(x)
+ else
+ fun_l11_n733(x)
+ end
+end
+
+def fun_l10_n539(x)
+ if (x < 1)
+ fun_l11_n633(x)
+ else
+ fun_l11_n122(x)
+ end
+end
+
+def fun_l10_n540(x)
+ if (x < 1)
+ fun_l11_n453(x)
+ else
+ fun_l11_n938(x)
+ end
+end
+
+def fun_l10_n541(x)
+ if (x < 1)
+ fun_l11_n55(x)
+ else
+ fun_l11_n344(x)
+ end
+end
+
+def fun_l10_n542(x)
+ if (x < 1)
+ fun_l11_n167(x)
+ else
+ fun_l11_n908(x)
+ end
+end
+
+def fun_l10_n543(x)
+ if (x < 1)
+ fun_l11_n318(x)
+ else
+ fun_l11_n893(x)
+ end
+end
+
+def fun_l10_n544(x)
+ if (x < 1)
+ fun_l11_n683(x)
+ else
+ fun_l11_n109(x)
+ end
+end
+
+def fun_l10_n545(x)
+ if (x < 1)
+ fun_l11_n728(x)
+ else
+ fun_l11_n432(x)
+ end
+end
+
+def fun_l10_n546(x)
+ if (x < 1)
+ fun_l11_n343(x)
+ else
+ fun_l11_n674(x)
+ end
+end
+
+def fun_l10_n547(x)
+ if (x < 1)
+ fun_l11_n374(x)
+ else
+ fun_l11_n293(x)
+ end
+end
+
+def fun_l10_n548(x)
+ if (x < 1)
+ fun_l11_n661(x)
+ else
+ fun_l11_n619(x)
+ end
+end
+
+def fun_l10_n549(x)
+ if (x < 1)
+ fun_l11_n984(x)
+ else
+ fun_l11_n261(x)
+ end
+end
+
+def fun_l10_n550(x)
+ if (x < 1)
+ fun_l11_n729(x)
+ else
+ fun_l11_n469(x)
+ end
+end
+
+def fun_l10_n551(x)
+ if (x < 1)
+ fun_l11_n829(x)
+ else
+ fun_l11_n30(x)
+ end
+end
+
+def fun_l10_n552(x)
+ if (x < 1)
+ fun_l11_n457(x)
+ else
+ fun_l11_n440(x)
+ end
+end
+
+def fun_l10_n553(x)
+ if (x < 1)
+ fun_l11_n128(x)
+ else
+ fun_l11_n790(x)
+ end
+end
+
+def fun_l10_n554(x)
+ if (x < 1)
+ fun_l11_n135(x)
+ else
+ fun_l11_n118(x)
+ end
+end
+
+def fun_l10_n555(x)
+ if (x < 1)
+ fun_l11_n558(x)
+ else
+ fun_l11_n415(x)
+ end
+end
+
+def fun_l10_n556(x)
+ if (x < 1)
+ fun_l11_n388(x)
+ else
+ fun_l11_n102(x)
+ end
+end
+
+def fun_l10_n557(x)
+ if (x < 1)
+ fun_l11_n575(x)
+ else
+ fun_l11_n877(x)
+ end
+end
+
+def fun_l10_n558(x)
+ if (x < 1)
+ fun_l11_n266(x)
+ else
+ fun_l11_n216(x)
+ end
+end
+
+def fun_l10_n559(x)
+ if (x < 1)
+ fun_l11_n681(x)
+ else
+ fun_l11_n259(x)
+ end
+end
+
+def fun_l10_n560(x)
+ if (x < 1)
+ fun_l11_n922(x)
+ else
+ fun_l11_n828(x)
+ end
+end
+
+def fun_l10_n561(x)
+ if (x < 1)
+ fun_l11_n135(x)
+ else
+ fun_l11_n971(x)
+ end
+end
+
+def fun_l10_n562(x)
+ if (x < 1)
+ fun_l11_n940(x)
+ else
+ fun_l11_n266(x)
+ end
+end
+
+def fun_l10_n563(x)
+ if (x < 1)
+ fun_l11_n291(x)
+ else
+ fun_l11_n587(x)
+ end
+end
+
+def fun_l10_n564(x)
+ if (x < 1)
+ fun_l11_n143(x)
+ else
+ fun_l11_n289(x)
+ end
+end
+
+def fun_l10_n565(x)
+ if (x < 1)
+ fun_l11_n947(x)
+ else
+ fun_l11_n462(x)
+ end
+end
+
+def fun_l10_n566(x)
+ if (x < 1)
+ fun_l11_n307(x)
+ else
+ fun_l11_n904(x)
+ end
+end
+
+def fun_l10_n567(x)
+ if (x < 1)
+ fun_l11_n945(x)
+ else
+ fun_l11_n814(x)
+ end
+end
+
+def fun_l10_n568(x)
+ if (x < 1)
+ fun_l11_n689(x)
+ else
+ fun_l11_n61(x)
+ end
+end
+
+def fun_l10_n569(x)
+ if (x < 1)
+ fun_l11_n446(x)
+ else
+ fun_l11_n305(x)
+ end
+end
+
+def fun_l10_n570(x)
+ if (x < 1)
+ fun_l11_n209(x)
+ else
+ fun_l11_n768(x)
+ end
+end
+
+def fun_l10_n571(x)
+ if (x < 1)
+ fun_l11_n904(x)
+ else
+ fun_l11_n736(x)
+ end
+end
+
+def fun_l10_n572(x)
+ if (x < 1)
+ fun_l11_n87(x)
+ else
+ fun_l11_n474(x)
+ end
+end
+
+def fun_l10_n573(x)
+ if (x < 1)
+ fun_l11_n886(x)
+ else
+ fun_l11_n75(x)
+ end
+end
+
+def fun_l10_n574(x)
+ if (x < 1)
+ fun_l11_n761(x)
+ else
+ fun_l11_n662(x)
+ end
+end
+
+def fun_l10_n575(x)
+ if (x < 1)
+ fun_l11_n255(x)
+ else
+ fun_l11_n321(x)
+ end
+end
+
+def fun_l10_n576(x)
+ if (x < 1)
+ fun_l11_n154(x)
+ else
+ fun_l11_n356(x)
+ end
+end
+
+def fun_l10_n577(x)
+ if (x < 1)
+ fun_l11_n802(x)
+ else
+ fun_l11_n912(x)
+ end
+end
+
+def fun_l10_n578(x)
+ if (x < 1)
+ fun_l11_n709(x)
+ else
+ fun_l11_n66(x)
+ end
+end
+
+def fun_l10_n579(x)
+ if (x < 1)
+ fun_l11_n994(x)
+ else
+ fun_l11_n424(x)
+ end
+end
+
+def fun_l10_n580(x)
+ if (x < 1)
+ fun_l11_n520(x)
+ else
+ fun_l11_n551(x)
+ end
+end
+
+def fun_l10_n581(x)
+ if (x < 1)
+ fun_l11_n386(x)
+ else
+ fun_l11_n615(x)
+ end
+end
+
+def fun_l10_n582(x)
+ if (x < 1)
+ fun_l11_n125(x)
+ else
+ fun_l11_n667(x)
+ end
+end
+
+def fun_l10_n583(x)
+ if (x < 1)
+ fun_l11_n829(x)
+ else
+ fun_l11_n802(x)
+ end
+end
+
+def fun_l10_n584(x)
+ if (x < 1)
+ fun_l11_n649(x)
+ else
+ fun_l11_n39(x)
+ end
+end
+
+def fun_l10_n585(x)
+ if (x < 1)
+ fun_l11_n454(x)
+ else
+ fun_l11_n541(x)
+ end
+end
+
+def fun_l10_n586(x)
+ if (x < 1)
+ fun_l11_n281(x)
+ else
+ fun_l11_n4(x)
+ end
+end
+
+def fun_l10_n587(x)
+ if (x < 1)
+ fun_l11_n382(x)
+ else
+ fun_l11_n656(x)
+ end
+end
+
+def fun_l10_n588(x)
+ if (x < 1)
+ fun_l11_n177(x)
+ else
+ fun_l11_n38(x)
+ end
+end
+
+def fun_l10_n589(x)
+ if (x < 1)
+ fun_l11_n555(x)
+ else
+ fun_l11_n557(x)
+ end
+end
+
+def fun_l10_n590(x)
+ if (x < 1)
+ fun_l11_n999(x)
+ else
+ fun_l11_n645(x)
+ end
+end
+
+def fun_l10_n591(x)
+ if (x < 1)
+ fun_l11_n714(x)
+ else
+ fun_l11_n872(x)
+ end
+end
+
+def fun_l10_n592(x)
+ if (x < 1)
+ fun_l11_n779(x)
+ else
+ fun_l11_n524(x)
+ end
+end
+
+def fun_l10_n593(x)
+ if (x < 1)
+ fun_l11_n557(x)
+ else
+ fun_l11_n906(x)
+ end
+end
+
+def fun_l10_n594(x)
+ if (x < 1)
+ fun_l11_n379(x)
+ else
+ fun_l11_n550(x)
+ end
+end
+
+def fun_l10_n595(x)
+ if (x < 1)
+ fun_l11_n138(x)
+ else
+ fun_l11_n785(x)
+ end
+end
+
+def fun_l10_n596(x)
+ if (x < 1)
+ fun_l11_n486(x)
+ else
+ fun_l11_n381(x)
+ end
+end
+
+def fun_l10_n597(x)
+ if (x < 1)
+ fun_l11_n374(x)
+ else
+ fun_l11_n477(x)
+ end
+end
+
+def fun_l10_n598(x)
+ if (x < 1)
+ fun_l11_n113(x)
+ else
+ fun_l11_n455(x)
+ end
+end
+
+def fun_l10_n599(x)
+ if (x < 1)
+ fun_l11_n31(x)
+ else
+ fun_l11_n983(x)
+ end
+end
+
+def fun_l10_n600(x)
+ if (x < 1)
+ fun_l11_n758(x)
+ else
+ fun_l11_n187(x)
+ end
+end
+
+def fun_l10_n601(x)
+ if (x < 1)
+ fun_l11_n198(x)
+ else
+ fun_l11_n436(x)
+ end
+end
+
+def fun_l10_n602(x)
+ if (x < 1)
+ fun_l11_n207(x)
+ else
+ fun_l11_n86(x)
+ end
+end
+
+def fun_l10_n603(x)
+ if (x < 1)
+ fun_l11_n827(x)
+ else
+ fun_l11_n267(x)
+ end
+end
+
+def fun_l10_n604(x)
+ if (x < 1)
+ fun_l11_n760(x)
+ else
+ fun_l11_n707(x)
+ end
+end
+
+def fun_l10_n605(x)
+ if (x < 1)
+ fun_l11_n791(x)
+ else
+ fun_l11_n249(x)
+ end
+end
+
+def fun_l10_n606(x)
+ if (x < 1)
+ fun_l11_n634(x)
+ else
+ fun_l11_n607(x)
+ end
+end
+
+def fun_l10_n607(x)
+ if (x < 1)
+ fun_l11_n605(x)
+ else
+ fun_l11_n698(x)
+ end
+end
+
+def fun_l10_n608(x)
+ if (x < 1)
+ fun_l11_n401(x)
+ else
+ fun_l11_n316(x)
+ end
+end
+
+def fun_l10_n609(x)
+ if (x < 1)
+ fun_l11_n928(x)
+ else
+ fun_l11_n313(x)
+ end
+end
+
+def fun_l10_n610(x)
+ if (x < 1)
+ fun_l11_n601(x)
+ else
+ fun_l11_n278(x)
+ end
+end
+
+def fun_l10_n611(x)
+ if (x < 1)
+ fun_l11_n554(x)
+ else
+ fun_l11_n584(x)
+ end
+end
+
+def fun_l10_n612(x)
+ if (x < 1)
+ fun_l11_n906(x)
+ else
+ fun_l11_n58(x)
+ end
+end
+
+def fun_l10_n613(x)
+ if (x < 1)
+ fun_l11_n85(x)
+ else
+ fun_l11_n631(x)
+ end
+end
+
+def fun_l10_n614(x)
+ if (x < 1)
+ fun_l11_n221(x)
+ else
+ fun_l11_n85(x)
+ end
+end
+
+def fun_l10_n615(x)
+ if (x < 1)
+ fun_l11_n88(x)
+ else
+ fun_l11_n367(x)
+ end
+end
+
+def fun_l10_n616(x)
+ if (x < 1)
+ fun_l11_n693(x)
+ else
+ fun_l11_n385(x)
+ end
+end
+
+def fun_l10_n617(x)
+ if (x < 1)
+ fun_l11_n18(x)
+ else
+ fun_l11_n526(x)
+ end
+end
+
+def fun_l10_n618(x)
+ if (x < 1)
+ fun_l11_n307(x)
+ else
+ fun_l11_n303(x)
+ end
+end
+
+def fun_l10_n619(x)
+ if (x < 1)
+ fun_l11_n972(x)
+ else
+ fun_l11_n246(x)
+ end
+end
+
+def fun_l10_n620(x)
+ if (x < 1)
+ fun_l11_n185(x)
+ else
+ fun_l11_n512(x)
+ end
+end
+
+def fun_l10_n621(x)
+ if (x < 1)
+ fun_l11_n87(x)
+ else
+ fun_l11_n131(x)
+ end
+end
+
+def fun_l10_n622(x)
+ if (x < 1)
+ fun_l11_n617(x)
+ else
+ fun_l11_n869(x)
+ end
+end
+
+def fun_l10_n623(x)
+ if (x < 1)
+ fun_l11_n514(x)
+ else
+ fun_l11_n824(x)
+ end
+end
+
+def fun_l10_n624(x)
+ if (x < 1)
+ fun_l11_n551(x)
+ else
+ fun_l11_n430(x)
+ end
+end
+
+def fun_l10_n625(x)
+ if (x < 1)
+ fun_l11_n266(x)
+ else
+ fun_l11_n826(x)
+ end
+end
+
+def fun_l10_n626(x)
+ if (x < 1)
+ fun_l11_n90(x)
+ else
+ fun_l11_n866(x)
+ end
+end
+
+def fun_l10_n627(x)
+ if (x < 1)
+ fun_l11_n34(x)
+ else
+ fun_l11_n694(x)
+ end
+end
+
+def fun_l10_n628(x)
+ if (x < 1)
+ fun_l11_n455(x)
+ else
+ fun_l11_n990(x)
+ end
+end
+
+def fun_l10_n629(x)
+ if (x < 1)
+ fun_l11_n573(x)
+ else
+ fun_l11_n874(x)
+ end
+end
+
+def fun_l10_n630(x)
+ if (x < 1)
+ fun_l11_n836(x)
+ else
+ fun_l11_n87(x)
+ end
+end
+
+def fun_l10_n631(x)
+ if (x < 1)
+ fun_l11_n234(x)
+ else
+ fun_l11_n389(x)
+ end
+end
+
+def fun_l10_n632(x)
+ if (x < 1)
+ fun_l11_n647(x)
+ else
+ fun_l11_n655(x)
+ end
+end
+
+def fun_l10_n633(x)
+ if (x < 1)
+ fun_l11_n649(x)
+ else
+ fun_l11_n426(x)
+ end
+end
+
+def fun_l10_n634(x)
+ if (x < 1)
+ fun_l11_n613(x)
+ else
+ fun_l11_n10(x)
+ end
+end
+
+def fun_l10_n635(x)
+ if (x < 1)
+ fun_l11_n315(x)
+ else
+ fun_l11_n419(x)
+ end
+end
+
+def fun_l10_n636(x)
+ if (x < 1)
+ fun_l11_n575(x)
+ else
+ fun_l11_n29(x)
+ end
+end
+
+def fun_l10_n637(x)
+ if (x < 1)
+ fun_l11_n75(x)
+ else
+ fun_l11_n710(x)
+ end
+end
+
+def fun_l10_n638(x)
+ if (x < 1)
+ fun_l11_n42(x)
+ else
+ fun_l11_n45(x)
+ end
+end
+
+def fun_l10_n639(x)
+ if (x < 1)
+ fun_l11_n629(x)
+ else
+ fun_l11_n850(x)
+ end
+end
+
+def fun_l10_n640(x)
+ if (x < 1)
+ fun_l11_n491(x)
+ else
+ fun_l11_n708(x)
+ end
+end
+
+def fun_l10_n641(x)
+ if (x < 1)
+ fun_l11_n673(x)
+ else
+ fun_l11_n722(x)
+ end
+end
+
+def fun_l10_n642(x)
+ if (x < 1)
+ fun_l11_n922(x)
+ else
+ fun_l11_n783(x)
+ end
+end
+
+def fun_l10_n643(x)
+ if (x < 1)
+ fun_l11_n855(x)
+ else
+ fun_l11_n145(x)
+ end
+end
+
+def fun_l10_n644(x)
+ if (x < 1)
+ fun_l11_n897(x)
+ else
+ fun_l11_n281(x)
+ end
+end
+
+def fun_l10_n645(x)
+ if (x < 1)
+ fun_l11_n148(x)
+ else
+ fun_l11_n786(x)
+ end
+end
+
+def fun_l10_n646(x)
+ if (x < 1)
+ fun_l11_n743(x)
+ else
+ fun_l11_n627(x)
+ end
+end
+
+def fun_l10_n647(x)
+ if (x < 1)
+ fun_l11_n343(x)
+ else
+ fun_l11_n234(x)
+ end
+end
+
+def fun_l10_n648(x)
+ if (x < 1)
+ fun_l11_n995(x)
+ else
+ fun_l11_n199(x)
+ end
+end
+
+def fun_l10_n649(x)
+ if (x < 1)
+ fun_l11_n155(x)
+ else
+ fun_l11_n384(x)
+ end
+end
+
+def fun_l10_n650(x)
+ if (x < 1)
+ fun_l11_n329(x)
+ else
+ fun_l11_n313(x)
+ end
+end
+
+def fun_l10_n651(x)
+ if (x < 1)
+ fun_l11_n254(x)
+ else
+ fun_l11_n763(x)
+ end
+end
+
+def fun_l10_n652(x)
+ if (x < 1)
+ fun_l11_n839(x)
+ else
+ fun_l11_n692(x)
+ end
+end
+
+def fun_l10_n653(x)
+ if (x < 1)
+ fun_l11_n388(x)
+ else
+ fun_l11_n187(x)
+ end
+end
+
+def fun_l10_n654(x)
+ if (x < 1)
+ fun_l11_n919(x)
+ else
+ fun_l11_n198(x)
+ end
+end
+
+def fun_l10_n655(x)
+ if (x < 1)
+ fun_l11_n313(x)
+ else
+ fun_l11_n686(x)
+ end
+end
+
+def fun_l10_n656(x)
+ if (x < 1)
+ fun_l11_n91(x)
+ else
+ fun_l11_n95(x)
+ end
+end
+
+def fun_l10_n657(x)
+ if (x < 1)
+ fun_l11_n801(x)
+ else
+ fun_l11_n700(x)
+ end
+end
+
+def fun_l10_n658(x)
+ if (x < 1)
+ fun_l11_n938(x)
+ else
+ fun_l11_n936(x)
+ end
+end
+
+def fun_l10_n659(x)
+ if (x < 1)
+ fun_l11_n78(x)
+ else
+ fun_l11_n611(x)
+ end
+end
+
+def fun_l10_n660(x)
+ if (x < 1)
+ fun_l11_n261(x)
+ else
+ fun_l11_n396(x)
+ end
+end
+
+def fun_l10_n661(x)
+ if (x < 1)
+ fun_l11_n154(x)
+ else
+ fun_l11_n132(x)
+ end
+end
+
+def fun_l10_n662(x)
+ if (x < 1)
+ fun_l11_n603(x)
+ else
+ fun_l11_n718(x)
+ end
+end
+
+def fun_l10_n663(x)
+ if (x < 1)
+ fun_l11_n512(x)
+ else
+ fun_l11_n158(x)
+ end
+end
+
+def fun_l10_n664(x)
+ if (x < 1)
+ fun_l11_n178(x)
+ else
+ fun_l11_n59(x)
+ end
+end
+
+def fun_l10_n665(x)
+ if (x < 1)
+ fun_l11_n703(x)
+ else
+ fun_l11_n54(x)
+ end
+end
+
+def fun_l10_n666(x)
+ if (x < 1)
+ fun_l11_n623(x)
+ else
+ fun_l11_n793(x)
+ end
+end
+
+def fun_l10_n667(x)
+ if (x < 1)
+ fun_l11_n350(x)
+ else
+ fun_l11_n244(x)
+ end
+end
+
+def fun_l10_n668(x)
+ if (x < 1)
+ fun_l11_n253(x)
+ else
+ fun_l11_n297(x)
+ end
+end
+
+def fun_l10_n669(x)
+ if (x < 1)
+ fun_l11_n137(x)
+ else
+ fun_l11_n76(x)
+ end
+end
+
+def fun_l10_n670(x)
+ if (x < 1)
+ fun_l11_n755(x)
+ else
+ fun_l11_n627(x)
+ end
+end
+
+def fun_l10_n671(x)
+ if (x < 1)
+ fun_l11_n393(x)
+ else
+ fun_l11_n394(x)
+ end
+end
+
+def fun_l10_n672(x)
+ if (x < 1)
+ fun_l11_n858(x)
+ else
+ fun_l11_n823(x)
+ end
+end
+
+def fun_l10_n673(x)
+ if (x < 1)
+ fun_l11_n202(x)
+ else
+ fun_l11_n800(x)
+ end
+end
+
+def fun_l10_n674(x)
+ if (x < 1)
+ fun_l11_n977(x)
+ else
+ fun_l11_n343(x)
+ end
+end
+
+def fun_l10_n675(x)
+ if (x < 1)
+ fun_l11_n352(x)
+ else
+ fun_l11_n690(x)
+ end
+end
+
+def fun_l10_n676(x)
+ if (x < 1)
+ fun_l11_n598(x)
+ else
+ fun_l11_n108(x)
+ end
+end
+
+def fun_l10_n677(x)
+ if (x < 1)
+ fun_l11_n126(x)
+ else
+ fun_l11_n226(x)
+ end
+end
+
+def fun_l10_n678(x)
+ if (x < 1)
+ fun_l11_n937(x)
+ else
+ fun_l11_n846(x)
+ end
+end
+
+def fun_l10_n679(x)
+ if (x < 1)
+ fun_l11_n231(x)
+ else
+ fun_l11_n264(x)
+ end
+end
+
+def fun_l10_n680(x)
+ if (x < 1)
+ fun_l11_n657(x)
+ else
+ fun_l11_n766(x)
+ end
+end
+
+def fun_l10_n681(x)
+ if (x < 1)
+ fun_l11_n444(x)
+ else
+ fun_l11_n405(x)
+ end
+end
+
+def fun_l10_n682(x)
+ if (x < 1)
+ fun_l11_n410(x)
+ else
+ fun_l11_n409(x)
+ end
+end
+
+def fun_l10_n683(x)
+ if (x < 1)
+ fun_l11_n690(x)
+ else
+ fun_l11_n673(x)
+ end
+end
+
+def fun_l10_n684(x)
+ if (x < 1)
+ fun_l11_n737(x)
+ else
+ fun_l11_n61(x)
+ end
+end
+
+def fun_l10_n685(x)
+ if (x < 1)
+ fun_l11_n54(x)
+ else
+ fun_l11_n387(x)
+ end
+end
+
+def fun_l10_n686(x)
+ if (x < 1)
+ fun_l11_n271(x)
+ else
+ fun_l11_n698(x)
+ end
+end
+
+def fun_l10_n687(x)
+ if (x < 1)
+ fun_l11_n988(x)
+ else
+ fun_l11_n816(x)
+ end
+end
+
+def fun_l10_n688(x)
+ if (x < 1)
+ fun_l11_n309(x)
+ else
+ fun_l11_n576(x)
+ end
+end
+
+def fun_l10_n689(x)
+ if (x < 1)
+ fun_l11_n390(x)
+ else
+ fun_l11_n35(x)
+ end
+end
+
+def fun_l10_n690(x)
+ if (x < 1)
+ fun_l11_n93(x)
+ else
+ fun_l11_n712(x)
+ end
+end
+
+def fun_l10_n691(x)
+ if (x < 1)
+ fun_l11_n285(x)
+ else
+ fun_l11_n467(x)
+ end
+end
+
+def fun_l10_n692(x)
+ if (x < 1)
+ fun_l11_n403(x)
+ else
+ fun_l11_n41(x)
+ end
+end
+
+def fun_l10_n693(x)
+ if (x < 1)
+ fun_l11_n228(x)
+ else
+ fun_l11_n689(x)
+ end
+end
+
+def fun_l10_n694(x)
+ if (x < 1)
+ fun_l11_n581(x)
+ else
+ fun_l11_n989(x)
+ end
+end
+
+def fun_l10_n695(x)
+ if (x < 1)
+ fun_l11_n451(x)
+ else
+ fun_l11_n618(x)
+ end
+end
+
+def fun_l10_n696(x)
+ if (x < 1)
+ fun_l11_n640(x)
+ else
+ fun_l11_n13(x)
+ end
+end
+
+def fun_l10_n697(x)
+ if (x < 1)
+ fun_l11_n968(x)
+ else
+ fun_l11_n903(x)
+ end
+end
+
+def fun_l10_n698(x)
+ if (x < 1)
+ fun_l11_n918(x)
+ else
+ fun_l11_n244(x)
+ end
+end
+
+def fun_l10_n699(x)
+ if (x < 1)
+ fun_l11_n17(x)
+ else
+ fun_l11_n17(x)
+ end
+end
+
+def fun_l10_n700(x)
+ if (x < 1)
+ fun_l11_n918(x)
+ else
+ fun_l11_n539(x)
+ end
+end
+
+def fun_l10_n701(x)
+ if (x < 1)
+ fun_l11_n924(x)
+ else
+ fun_l11_n103(x)
+ end
+end
+
+def fun_l10_n702(x)
+ if (x < 1)
+ fun_l11_n908(x)
+ else
+ fun_l11_n328(x)
+ end
+end
+
+def fun_l10_n703(x)
+ if (x < 1)
+ fun_l11_n393(x)
+ else
+ fun_l11_n386(x)
+ end
+end
+
+def fun_l10_n704(x)
+ if (x < 1)
+ fun_l11_n194(x)
+ else
+ fun_l11_n812(x)
+ end
+end
+
+def fun_l10_n705(x)
+ if (x < 1)
+ fun_l11_n382(x)
+ else
+ fun_l11_n276(x)
+ end
+end
+
+def fun_l10_n706(x)
+ if (x < 1)
+ fun_l11_n257(x)
+ else
+ fun_l11_n269(x)
+ end
+end
+
+def fun_l10_n707(x)
+ if (x < 1)
+ fun_l11_n940(x)
+ else
+ fun_l11_n593(x)
+ end
+end
+
+def fun_l10_n708(x)
+ if (x < 1)
+ fun_l11_n710(x)
+ else
+ fun_l11_n992(x)
+ end
+end
+
+def fun_l10_n709(x)
+ if (x < 1)
+ fun_l11_n244(x)
+ else
+ fun_l11_n500(x)
+ end
+end
+
+def fun_l10_n710(x)
+ if (x < 1)
+ fun_l11_n712(x)
+ else
+ fun_l11_n544(x)
+ end
+end
+
+def fun_l10_n711(x)
+ if (x < 1)
+ fun_l11_n701(x)
+ else
+ fun_l11_n104(x)
+ end
+end
+
+def fun_l10_n712(x)
+ if (x < 1)
+ fun_l11_n706(x)
+ else
+ fun_l11_n199(x)
+ end
+end
+
+def fun_l10_n713(x)
+ if (x < 1)
+ fun_l11_n189(x)
+ else
+ fun_l11_n840(x)
+ end
+end
+
+def fun_l10_n714(x)
+ if (x < 1)
+ fun_l11_n122(x)
+ else
+ fun_l11_n318(x)
+ end
+end
+
+def fun_l10_n715(x)
+ if (x < 1)
+ fun_l11_n915(x)
+ else
+ fun_l11_n964(x)
+ end
+end
+
+def fun_l10_n716(x)
+ if (x < 1)
+ fun_l11_n341(x)
+ else
+ fun_l11_n118(x)
+ end
+end
+
+def fun_l10_n717(x)
+ if (x < 1)
+ fun_l11_n846(x)
+ else
+ fun_l11_n235(x)
+ end
+end
+
+def fun_l10_n718(x)
+ if (x < 1)
+ fun_l11_n679(x)
+ else
+ fun_l11_n959(x)
+ end
+end
+
+def fun_l10_n719(x)
+ if (x < 1)
+ fun_l11_n121(x)
+ else
+ fun_l11_n708(x)
+ end
+end
+
+def fun_l10_n720(x)
+ if (x < 1)
+ fun_l11_n651(x)
+ else
+ fun_l11_n480(x)
+ end
+end
+
+def fun_l10_n721(x)
+ if (x < 1)
+ fun_l11_n773(x)
+ else
+ fun_l11_n568(x)
+ end
+end
+
+def fun_l10_n722(x)
+ if (x < 1)
+ fun_l11_n809(x)
+ else
+ fun_l11_n111(x)
+ end
+end
+
+def fun_l10_n723(x)
+ if (x < 1)
+ fun_l11_n586(x)
+ else
+ fun_l11_n553(x)
+ end
+end
+
+def fun_l10_n724(x)
+ if (x < 1)
+ fun_l11_n473(x)
+ else
+ fun_l11_n387(x)
+ end
+end
+
+def fun_l10_n725(x)
+ if (x < 1)
+ fun_l11_n584(x)
+ else
+ fun_l11_n224(x)
+ end
+end
+
+def fun_l10_n726(x)
+ if (x < 1)
+ fun_l11_n110(x)
+ else
+ fun_l11_n827(x)
+ end
+end
+
+def fun_l10_n727(x)
+ if (x < 1)
+ fun_l11_n753(x)
+ else
+ fun_l11_n745(x)
+ end
+end
+
+def fun_l10_n728(x)
+ if (x < 1)
+ fun_l11_n550(x)
+ else
+ fun_l11_n380(x)
+ end
+end
+
+def fun_l10_n729(x)
+ if (x < 1)
+ fun_l11_n844(x)
+ else
+ fun_l11_n401(x)
+ end
+end
+
+def fun_l10_n730(x)
+ if (x < 1)
+ fun_l11_n837(x)
+ else
+ fun_l11_n759(x)
+ end
+end
+
+def fun_l10_n731(x)
+ if (x < 1)
+ fun_l11_n850(x)
+ else
+ fun_l11_n953(x)
+ end
+end
+
+def fun_l10_n732(x)
+ if (x < 1)
+ fun_l11_n872(x)
+ else
+ fun_l11_n864(x)
+ end
+end
+
+def fun_l10_n733(x)
+ if (x < 1)
+ fun_l11_n894(x)
+ else
+ fun_l11_n943(x)
+ end
+end
+
+def fun_l10_n734(x)
+ if (x < 1)
+ fun_l11_n830(x)
+ else
+ fun_l11_n858(x)
+ end
+end
+
+def fun_l10_n735(x)
+ if (x < 1)
+ fun_l11_n661(x)
+ else
+ fun_l11_n366(x)
+ end
+end
+
+def fun_l10_n736(x)
+ if (x < 1)
+ fun_l11_n736(x)
+ else
+ fun_l11_n636(x)
+ end
+end
+
+def fun_l10_n737(x)
+ if (x < 1)
+ fun_l11_n316(x)
+ else
+ fun_l11_n977(x)
+ end
+end
+
+def fun_l10_n738(x)
+ if (x < 1)
+ fun_l11_n54(x)
+ else
+ fun_l11_n386(x)
+ end
+end
+
+def fun_l10_n739(x)
+ if (x < 1)
+ fun_l11_n985(x)
+ else
+ fun_l11_n274(x)
+ end
+end
+
+def fun_l10_n740(x)
+ if (x < 1)
+ fun_l11_n756(x)
+ else
+ fun_l11_n171(x)
+ end
+end
+
+def fun_l10_n741(x)
+ if (x < 1)
+ fun_l11_n457(x)
+ else
+ fun_l11_n251(x)
+ end
+end
+
+def fun_l10_n742(x)
+ if (x < 1)
+ fun_l11_n751(x)
+ else
+ fun_l11_n29(x)
+ end
+end
+
+def fun_l10_n743(x)
+ if (x < 1)
+ fun_l11_n6(x)
+ else
+ fun_l11_n892(x)
+ end
+end
+
+def fun_l10_n744(x)
+ if (x < 1)
+ fun_l11_n85(x)
+ else
+ fun_l11_n205(x)
+ end
+end
+
+def fun_l10_n745(x)
+ if (x < 1)
+ fun_l11_n887(x)
+ else
+ fun_l11_n734(x)
+ end
+end
+
+def fun_l10_n746(x)
+ if (x < 1)
+ fun_l11_n478(x)
+ else
+ fun_l11_n505(x)
+ end
+end
+
+def fun_l10_n747(x)
+ if (x < 1)
+ fun_l11_n760(x)
+ else
+ fun_l11_n286(x)
+ end
+end
+
+def fun_l10_n748(x)
+ if (x < 1)
+ fun_l11_n391(x)
+ else
+ fun_l11_n69(x)
+ end
+end
+
+def fun_l10_n749(x)
+ if (x < 1)
+ fun_l11_n780(x)
+ else
+ fun_l11_n28(x)
+ end
+end
+
+def fun_l10_n750(x)
+ if (x < 1)
+ fun_l11_n337(x)
+ else
+ fun_l11_n647(x)
+ end
+end
+
+def fun_l10_n751(x)
+ if (x < 1)
+ fun_l11_n92(x)
+ else
+ fun_l11_n121(x)
+ end
+end
+
+def fun_l10_n752(x)
+ if (x < 1)
+ fun_l11_n358(x)
+ else
+ fun_l11_n177(x)
+ end
+end
+
+def fun_l10_n753(x)
+ if (x < 1)
+ fun_l11_n642(x)
+ else
+ fun_l11_n426(x)
+ end
+end
+
+def fun_l10_n754(x)
+ if (x < 1)
+ fun_l11_n66(x)
+ else
+ fun_l11_n948(x)
+ end
+end
+
+def fun_l10_n755(x)
+ if (x < 1)
+ fun_l11_n45(x)
+ else
+ fun_l11_n795(x)
+ end
+end
+
+def fun_l10_n756(x)
+ if (x < 1)
+ fun_l11_n734(x)
+ else
+ fun_l11_n162(x)
+ end
+end
+
+def fun_l10_n757(x)
+ if (x < 1)
+ fun_l11_n689(x)
+ else
+ fun_l11_n31(x)
+ end
+end
+
+def fun_l10_n758(x)
+ if (x < 1)
+ fun_l11_n33(x)
+ else
+ fun_l11_n992(x)
+ end
+end
+
+def fun_l10_n759(x)
+ if (x < 1)
+ fun_l11_n210(x)
+ else
+ fun_l11_n330(x)
+ end
+end
+
+def fun_l10_n760(x)
+ if (x < 1)
+ fun_l11_n727(x)
+ else
+ fun_l11_n265(x)
+ end
+end
+
+def fun_l10_n761(x)
+ if (x < 1)
+ fun_l11_n710(x)
+ else
+ fun_l11_n706(x)
+ end
+end
+
+def fun_l10_n762(x)
+ if (x < 1)
+ fun_l11_n791(x)
+ else
+ fun_l11_n325(x)
+ end
+end
+
+def fun_l10_n763(x)
+ if (x < 1)
+ fun_l11_n350(x)
+ else
+ fun_l11_n443(x)
+ end
+end
+
+def fun_l10_n764(x)
+ if (x < 1)
+ fun_l11_n522(x)
+ else
+ fun_l11_n662(x)
+ end
+end
+
+def fun_l10_n765(x)
+ if (x < 1)
+ fun_l11_n786(x)
+ else
+ fun_l11_n969(x)
+ end
+end
+
+def fun_l10_n766(x)
+ if (x < 1)
+ fun_l11_n486(x)
+ else
+ fun_l11_n834(x)
+ end
+end
+
+def fun_l10_n767(x)
+ if (x < 1)
+ fun_l11_n84(x)
+ else
+ fun_l11_n989(x)
+ end
+end
+
+def fun_l10_n768(x)
+ if (x < 1)
+ fun_l11_n511(x)
+ else
+ fun_l11_n0(x)
+ end
+end
+
+def fun_l10_n769(x)
+ if (x < 1)
+ fun_l11_n459(x)
+ else
+ fun_l11_n243(x)
+ end
+end
+
+def fun_l10_n770(x)
+ if (x < 1)
+ fun_l11_n59(x)
+ else
+ fun_l11_n267(x)
+ end
+end
+
+def fun_l10_n771(x)
+ if (x < 1)
+ fun_l11_n435(x)
+ else
+ fun_l11_n132(x)
+ end
+end
+
+def fun_l10_n772(x)
+ if (x < 1)
+ fun_l11_n986(x)
+ else
+ fun_l11_n227(x)
+ end
+end
+
+def fun_l10_n773(x)
+ if (x < 1)
+ fun_l11_n931(x)
+ else
+ fun_l11_n215(x)
+ end
+end
+
+def fun_l10_n774(x)
+ if (x < 1)
+ fun_l11_n586(x)
+ else
+ fun_l11_n170(x)
+ end
+end
+
+def fun_l10_n775(x)
+ if (x < 1)
+ fun_l11_n334(x)
+ else
+ fun_l11_n780(x)
+ end
+end
+
+def fun_l10_n776(x)
+ if (x < 1)
+ fun_l11_n81(x)
+ else
+ fun_l11_n583(x)
+ end
+end
+
+def fun_l10_n777(x)
+ if (x < 1)
+ fun_l11_n118(x)
+ else
+ fun_l11_n451(x)
+ end
+end
+
+def fun_l10_n778(x)
+ if (x < 1)
+ fun_l11_n767(x)
+ else
+ fun_l11_n824(x)
+ end
+end
+
+def fun_l10_n779(x)
+ if (x < 1)
+ fun_l11_n270(x)
+ else
+ fun_l11_n725(x)
+ end
+end
+
+def fun_l10_n780(x)
+ if (x < 1)
+ fun_l11_n146(x)
+ else
+ fun_l11_n407(x)
+ end
+end
+
+def fun_l10_n781(x)
+ if (x < 1)
+ fun_l11_n103(x)
+ else
+ fun_l11_n523(x)
+ end
+end
+
+def fun_l10_n782(x)
+ if (x < 1)
+ fun_l11_n499(x)
+ else
+ fun_l11_n710(x)
+ end
+end
+
+def fun_l10_n783(x)
+ if (x < 1)
+ fun_l11_n971(x)
+ else
+ fun_l11_n426(x)
+ end
+end
+
+def fun_l10_n784(x)
+ if (x < 1)
+ fun_l11_n457(x)
+ else
+ fun_l11_n207(x)
+ end
+end
+
+def fun_l10_n785(x)
+ if (x < 1)
+ fun_l11_n307(x)
+ else
+ fun_l11_n19(x)
+ end
+end
+
+def fun_l10_n786(x)
+ if (x < 1)
+ fun_l11_n458(x)
+ else
+ fun_l11_n243(x)
+ end
+end
+
+def fun_l10_n787(x)
+ if (x < 1)
+ fun_l11_n488(x)
+ else
+ fun_l11_n694(x)
+ end
+end
+
+def fun_l10_n788(x)
+ if (x < 1)
+ fun_l11_n422(x)
+ else
+ fun_l11_n201(x)
+ end
+end
+
+def fun_l10_n789(x)
+ if (x < 1)
+ fun_l11_n45(x)
+ else
+ fun_l11_n993(x)
+ end
+end
+
+def fun_l10_n790(x)
+ if (x < 1)
+ fun_l11_n443(x)
+ else
+ fun_l11_n124(x)
+ end
+end
+
+def fun_l10_n791(x)
+ if (x < 1)
+ fun_l11_n875(x)
+ else
+ fun_l11_n605(x)
+ end
+end
+
+def fun_l10_n792(x)
+ if (x < 1)
+ fun_l11_n836(x)
+ else
+ fun_l11_n776(x)
+ end
+end
+
+def fun_l10_n793(x)
+ if (x < 1)
+ fun_l11_n58(x)
+ else
+ fun_l11_n847(x)
+ end
+end
+
+def fun_l10_n794(x)
+ if (x < 1)
+ fun_l11_n334(x)
+ else
+ fun_l11_n981(x)
+ end
+end
+
+def fun_l10_n795(x)
+ if (x < 1)
+ fun_l11_n187(x)
+ else
+ fun_l11_n599(x)
+ end
+end
+
+def fun_l10_n796(x)
+ if (x < 1)
+ fun_l11_n37(x)
+ else
+ fun_l11_n211(x)
+ end
+end
+
+def fun_l10_n797(x)
+ if (x < 1)
+ fun_l11_n770(x)
+ else
+ fun_l11_n688(x)
+ end
+end
+
+def fun_l10_n798(x)
+ if (x < 1)
+ fun_l11_n728(x)
+ else
+ fun_l11_n150(x)
+ end
+end
+
+def fun_l10_n799(x)
+ if (x < 1)
+ fun_l11_n175(x)
+ else
+ fun_l11_n762(x)
+ end
+end
+
+def fun_l10_n800(x)
+ if (x < 1)
+ fun_l11_n977(x)
+ else
+ fun_l11_n86(x)
+ end
+end
+
+def fun_l10_n801(x)
+ if (x < 1)
+ fun_l11_n669(x)
+ else
+ fun_l11_n120(x)
+ end
+end
+
+def fun_l10_n802(x)
+ if (x < 1)
+ fun_l11_n630(x)
+ else
+ fun_l11_n839(x)
+ end
+end
+
+def fun_l10_n803(x)
+ if (x < 1)
+ fun_l11_n505(x)
+ else
+ fun_l11_n461(x)
+ end
+end
+
+def fun_l10_n804(x)
+ if (x < 1)
+ fun_l11_n757(x)
+ else
+ fun_l11_n620(x)
+ end
+end
+
+def fun_l10_n805(x)
+ if (x < 1)
+ fun_l11_n379(x)
+ else
+ fun_l11_n468(x)
+ end
+end
+
+def fun_l10_n806(x)
+ if (x < 1)
+ fun_l11_n708(x)
+ else
+ fun_l11_n73(x)
+ end
+end
+
+def fun_l10_n807(x)
+ if (x < 1)
+ fun_l11_n340(x)
+ else
+ fun_l11_n671(x)
+ end
+end
+
+def fun_l10_n808(x)
+ if (x < 1)
+ fun_l11_n628(x)
+ else
+ fun_l11_n912(x)
+ end
+end
+
+def fun_l10_n809(x)
+ if (x < 1)
+ fun_l11_n455(x)
+ else
+ fun_l11_n20(x)
+ end
+end
+
+def fun_l10_n810(x)
+ if (x < 1)
+ fun_l11_n211(x)
+ else
+ fun_l11_n724(x)
+ end
+end
+
+def fun_l10_n811(x)
+ if (x < 1)
+ fun_l11_n982(x)
+ else
+ fun_l11_n876(x)
+ end
+end
+
+def fun_l10_n812(x)
+ if (x < 1)
+ fun_l11_n455(x)
+ else
+ fun_l11_n846(x)
+ end
+end
+
+def fun_l10_n813(x)
+ if (x < 1)
+ fun_l11_n317(x)
+ else
+ fun_l11_n909(x)
+ end
+end
+
+def fun_l10_n814(x)
+ if (x < 1)
+ fun_l11_n622(x)
+ else
+ fun_l11_n147(x)
+ end
+end
+
+def fun_l10_n815(x)
+ if (x < 1)
+ fun_l11_n174(x)
+ else
+ fun_l11_n660(x)
+ end
+end
+
+def fun_l10_n816(x)
+ if (x < 1)
+ fun_l11_n63(x)
+ else
+ fun_l11_n427(x)
+ end
+end
+
+def fun_l10_n817(x)
+ if (x < 1)
+ fun_l11_n944(x)
+ else
+ fun_l11_n40(x)
+ end
+end
+
+def fun_l10_n818(x)
+ if (x < 1)
+ fun_l11_n887(x)
+ else
+ fun_l11_n641(x)
+ end
+end
+
+def fun_l10_n819(x)
+ if (x < 1)
+ fun_l11_n237(x)
+ else
+ fun_l11_n568(x)
+ end
+end
+
+def fun_l10_n820(x)
+ if (x < 1)
+ fun_l11_n415(x)
+ else
+ fun_l11_n374(x)
+ end
+end
+
+def fun_l10_n821(x)
+ if (x < 1)
+ fun_l11_n183(x)
+ else
+ fun_l11_n38(x)
+ end
+end
+
+def fun_l10_n822(x)
+ if (x < 1)
+ fun_l11_n835(x)
+ else
+ fun_l11_n406(x)
+ end
+end
+
+def fun_l10_n823(x)
+ if (x < 1)
+ fun_l11_n233(x)
+ else
+ fun_l11_n118(x)
+ end
+end
+
+def fun_l10_n824(x)
+ if (x < 1)
+ fun_l11_n898(x)
+ else
+ fun_l11_n543(x)
+ end
+end
+
+def fun_l10_n825(x)
+ if (x < 1)
+ fun_l11_n971(x)
+ else
+ fun_l11_n750(x)
+ end
+end
+
+def fun_l10_n826(x)
+ if (x < 1)
+ fun_l11_n254(x)
+ else
+ fun_l11_n759(x)
+ end
+end
+
+def fun_l10_n827(x)
+ if (x < 1)
+ fun_l11_n953(x)
+ else
+ fun_l11_n187(x)
+ end
+end
+
+def fun_l10_n828(x)
+ if (x < 1)
+ fun_l11_n403(x)
+ else
+ fun_l11_n170(x)
+ end
+end
+
+def fun_l10_n829(x)
+ if (x < 1)
+ fun_l11_n251(x)
+ else
+ fun_l11_n506(x)
+ end
+end
+
+def fun_l10_n830(x)
+ if (x < 1)
+ fun_l11_n426(x)
+ else
+ fun_l11_n325(x)
+ end
+end
+
+def fun_l10_n831(x)
+ if (x < 1)
+ fun_l11_n958(x)
+ else
+ fun_l11_n4(x)
+ end
+end
+
+def fun_l10_n832(x)
+ if (x < 1)
+ fun_l11_n628(x)
+ else
+ fun_l11_n920(x)
+ end
+end
+
+def fun_l10_n833(x)
+ if (x < 1)
+ fun_l11_n241(x)
+ else
+ fun_l11_n459(x)
+ end
+end
+
+def fun_l10_n834(x)
+ if (x < 1)
+ fun_l11_n559(x)
+ else
+ fun_l11_n671(x)
+ end
+end
+
+def fun_l10_n835(x)
+ if (x < 1)
+ fun_l11_n980(x)
+ else
+ fun_l11_n295(x)
+ end
+end
+
+def fun_l10_n836(x)
+ if (x < 1)
+ fun_l11_n306(x)
+ else
+ fun_l11_n143(x)
+ end
+end
+
+def fun_l10_n837(x)
+ if (x < 1)
+ fun_l11_n176(x)
+ else
+ fun_l11_n341(x)
+ end
+end
+
+def fun_l10_n838(x)
+ if (x < 1)
+ fun_l11_n130(x)
+ else
+ fun_l11_n380(x)
+ end
+end
+
+def fun_l10_n839(x)
+ if (x < 1)
+ fun_l11_n630(x)
+ else
+ fun_l11_n216(x)
+ end
+end
+
+def fun_l10_n840(x)
+ if (x < 1)
+ fun_l11_n500(x)
+ else
+ fun_l11_n579(x)
+ end
+end
+
+def fun_l10_n841(x)
+ if (x < 1)
+ fun_l11_n312(x)
+ else
+ fun_l11_n656(x)
+ end
+end
+
+def fun_l10_n842(x)
+ if (x < 1)
+ fun_l11_n209(x)
+ else
+ fun_l11_n332(x)
+ end
+end
+
+def fun_l10_n843(x)
+ if (x < 1)
+ fun_l11_n555(x)
+ else
+ fun_l11_n179(x)
+ end
+end
+
+def fun_l10_n844(x)
+ if (x < 1)
+ fun_l11_n154(x)
+ else
+ fun_l11_n284(x)
+ end
+end
+
+def fun_l10_n845(x)
+ if (x < 1)
+ fun_l11_n912(x)
+ else
+ fun_l11_n543(x)
+ end
+end
+
+def fun_l10_n846(x)
+ if (x < 1)
+ fun_l11_n346(x)
+ else
+ fun_l11_n553(x)
+ end
+end
+
+def fun_l10_n847(x)
+ if (x < 1)
+ fun_l11_n117(x)
+ else
+ fun_l11_n738(x)
+ end
+end
+
+def fun_l10_n848(x)
+ if (x < 1)
+ fun_l11_n664(x)
+ else
+ fun_l11_n988(x)
+ end
+end
+
+def fun_l10_n849(x)
+ if (x < 1)
+ fun_l11_n298(x)
+ else
+ fun_l11_n753(x)
+ end
+end
+
+def fun_l10_n850(x)
+ if (x < 1)
+ fun_l11_n177(x)
+ else
+ fun_l11_n690(x)
+ end
+end
+
+def fun_l10_n851(x)
+ if (x < 1)
+ fun_l11_n259(x)
+ else
+ fun_l11_n713(x)
+ end
+end
+
+def fun_l10_n852(x)
+ if (x < 1)
+ fun_l11_n151(x)
+ else
+ fun_l11_n580(x)
+ end
+end
+
+def fun_l10_n853(x)
+ if (x < 1)
+ fun_l11_n274(x)
+ else
+ fun_l11_n703(x)
+ end
+end
+
+def fun_l10_n854(x)
+ if (x < 1)
+ fun_l11_n295(x)
+ else
+ fun_l11_n885(x)
+ end
+end
+
+def fun_l10_n855(x)
+ if (x < 1)
+ fun_l11_n513(x)
+ else
+ fun_l11_n963(x)
+ end
+end
+
+def fun_l10_n856(x)
+ if (x < 1)
+ fun_l11_n855(x)
+ else
+ fun_l11_n435(x)
+ end
+end
+
+def fun_l10_n857(x)
+ if (x < 1)
+ fun_l11_n573(x)
+ else
+ fun_l11_n489(x)
+ end
+end
+
+def fun_l10_n858(x)
+ if (x < 1)
+ fun_l11_n880(x)
+ else
+ fun_l11_n91(x)
+ end
+end
+
+def fun_l10_n859(x)
+ if (x < 1)
+ fun_l11_n993(x)
+ else
+ fun_l11_n358(x)
+ end
+end
+
+def fun_l10_n860(x)
+ if (x < 1)
+ fun_l11_n836(x)
+ else
+ fun_l11_n192(x)
+ end
+end
+
+def fun_l10_n861(x)
+ if (x < 1)
+ fun_l11_n493(x)
+ else
+ fun_l11_n564(x)
+ end
+end
+
+def fun_l10_n862(x)
+ if (x < 1)
+ fun_l11_n111(x)
+ else
+ fun_l11_n8(x)
+ end
+end
+
+def fun_l10_n863(x)
+ if (x < 1)
+ fun_l11_n596(x)
+ else
+ fun_l11_n129(x)
+ end
+end
+
+def fun_l10_n864(x)
+ if (x < 1)
+ fun_l11_n0(x)
+ else
+ fun_l11_n687(x)
+ end
+end
+
+def fun_l10_n865(x)
+ if (x < 1)
+ fun_l11_n543(x)
+ else
+ fun_l11_n866(x)
+ end
+end
+
+def fun_l10_n866(x)
+ if (x < 1)
+ fun_l11_n398(x)
+ else
+ fun_l11_n532(x)
+ end
+end
+
+def fun_l10_n867(x)
+ if (x < 1)
+ fun_l11_n15(x)
+ else
+ fun_l11_n991(x)
+ end
+end
+
+def fun_l10_n868(x)
+ if (x < 1)
+ fun_l11_n890(x)
+ else
+ fun_l11_n222(x)
+ end
+end
+
+def fun_l10_n869(x)
+ if (x < 1)
+ fun_l11_n206(x)
+ else
+ fun_l11_n983(x)
+ end
+end
+
+def fun_l10_n870(x)
+ if (x < 1)
+ fun_l11_n869(x)
+ else
+ fun_l11_n619(x)
+ end
+end
+
+def fun_l10_n871(x)
+ if (x < 1)
+ fun_l11_n417(x)
+ else
+ fun_l11_n18(x)
+ end
+end
+
+def fun_l10_n872(x)
+ if (x < 1)
+ fun_l11_n738(x)
+ else
+ fun_l11_n473(x)
+ end
+end
+
+def fun_l10_n873(x)
+ if (x < 1)
+ fun_l11_n773(x)
+ else
+ fun_l11_n128(x)
+ end
+end
+
+def fun_l10_n874(x)
+ if (x < 1)
+ fun_l11_n930(x)
+ else
+ fun_l11_n563(x)
+ end
+end
+
+def fun_l10_n875(x)
+ if (x < 1)
+ fun_l11_n868(x)
+ else
+ fun_l11_n356(x)
+ end
+end
+
+def fun_l10_n876(x)
+ if (x < 1)
+ fun_l11_n533(x)
+ else
+ fun_l11_n402(x)
+ end
+end
+
+def fun_l10_n877(x)
+ if (x < 1)
+ fun_l11_n959(x)
+ else
+ fun_l11_n921(x)
+ end
+end
+
+def fun_l10_n878(x)
+ if (x < 1)
+ fun_l11_n717(x)
+ else
+ fun_l11_n484(x)
+ end
+end
+
+def fun_l10_n879(x)
+ if (x < 1)
+ fun_l11_n583(x)
+ else
+ fun_l11_n801(x)
+ end
+end
+
+def fun_l10_n880(x)
+ if (x < 1)
+ fun_l11_n576(x)
+ else
+ fun_l11_n811(x)
+ end
+end
+
+def fun_l10_n881(x)
+ if (x < 1)
+ fun_l11_n382(x)
+ else
+ fun_l11_n585(x)
+ end
+end
+
+def fun_l10_n882(x)
+ if (x < 1)
+ fun_l11_n648(x)
+ else
+ fun_l11_n930(x)
+ end
+end
+
+def fun_l10_n883(x)
+ if (x < 1)
+ fun_l11_n246(x)
+ else
+ fun_l11_n636(x)
+ end
+end
+
+def fun_l10_n884(x)
+ if (x < 1)
+ fun_l11_n112(x)
+ else
+ fun_l11_n798(x)
+ end
+end
+
+def fun_l10_n885(x)
+ if (x < 1)
+ fun_l11_n517(x)
+ else
+ fun_l11_n633(x)
+ end
+end
+
+def fun_l10_n886(x)
+ if (x < 1)
+ fun_l11_n651(x)
+ else
+ fun_l11_n377(x)
+ end
+end
+
+def fun_l10_n887(x)
+ if (x < 1)
+ fun_l11_n652(x)
+ else
+ fun_l11_n419(x)
+ end
+end
+
+def fun_l10_n888(x)
+ if (x < 1)
+ fun_l11_n346(x)
+ else
+ fun_l11_n294(x)
+ end
+end
+
+def fun_l10_n889(x)
+ if (x < 1)
+ fun_l11_n809(x)
+ else
+ fun_l11_n844(x)
+ end
+end
+
+def fun_l10_n890(x)
+ if (x < 1)
+ fun_l11_n382(x)
+ else
+ fun_l11_n930(x)
+ end
+end
+
+def fun_l10_n891(x)
+ if (x < 1)
+ fun_l11_n900(x)
+ else
+ fun_l11_n293(x)
+ end
+end
+
+def fun_l10_n892(x)
+ if (x < 1)
+ fun_l11_n912(x)
+ else
+ fun_l11_n46(x)
+ end
+end
+
+def fun_l10_n893(x)
+ if (x < 1)
+ fun_l11_n429(x)
+ else
+ fun_l11_n174(x)
+ end
+end
+
+def fun_l10_n894(x)
+ if (x < 1)
+ fun_l11_n142(x)
+ else
+ fun_l11_n739(x)
+ end
+end
+
+def fun_l10_n895(x)
+ if (x < 1)
+ fun_l11_n300(x)
+ else
+ fun_l11_n546(x)
+ end
+end
+
+def fun_l10_n896(x)
+ if (x < 1)
+ fun_l11_n253(x)
+ else
+ fun_l11_n555(x)
+ end
+end
+
+def fun_l10_n897(x)
+ if (x < 1)
+ fun_l11_n29(x)
+ else
+ fun_l11_n913(x)
+ end
+end
+
+def fun_l10_n898(x)
+ if (x < 1)
+ fun_l11_n879(x)
+ else
+ fun_l11_n2(x)
+ end
+end
+
+def fun_l10_n899(x)
+ if (x < 1)
+ fun_l11_n191(x)
+ else
+ fun_l11_n418(x)
+ end
+end
+
+def fun_l10_n900(x)
+ if (x < 1)
+ fun_l11_n239(x)
+ else
+ fun_l11_n904(x)
+ end
+end
+
+def fun_l10_n901(x)
+ if (x < 1)
+ fun_l11_n962(x)
+ else
+ fun_l11_n978(x)
+ end
+end
+
+def fun_l10_n902(x)
+ if (x < 1)
+ fun_l11_n343(x)
+ else
+ fun_l11_n358(x)
+ end
+end
+
+def fun_l10_n903(x)
+ if (x < 1)
+ fun_l11_n334(x)
+ else
+ fun_l11_n806(x)
+ end
+end
+
+def fun_l10_n904(x)
+ if (x < 1)
+ fun_l11_n973(x)
+ else
+ fun_l11_n708(x)
+ end
+end
+
+def fun_l10_n905(x)
+ if (x < 1)
+ fun_l11_n990(x)
+ else
+ fun_l11_n211(x)
+ end
+end
+
+def fun_l10_n906(x)
+ if (x < 1)
+ fun_l11_n499(x)
+ else
+ fun_l11_n605(x)
+ end
+end
+
+def fun_l10_n907(x)
+ if (x < 1)
+ fun_l11_n335(x)
+ else
+ fun_l11_n855(x)
+ end
+end
+
+def fun_l10_n908(x)
+ if (x < 1)
+ fun_l11_n197(x)
+ else
+ fun_l11_n130(x)
+ end
+end
+
+def fun_l10_n909(x)
+ if (x < 1)
+ fun_l11_n462(x)
+ else
+ fun_l11_n838(x)
+ end
+end
+
+def fun_l10_n910(x)
+ if (x < 1)
+ fun_l11_n254(x)
+ else
+ fun_l11_n16(x)
+ end
+end
+
+def fun_l10_n911(x)
+ if (x < 1)
+ fun_l11_n321(x)
+ else
+ fun_l11_n158(x)
+ end
+end
+
+def fun_l10_n912(x)
+ if (x < 1)
+ fun_l11_n113(x)
+ else
+ fun_l11_n50(x)
+ end
+end
+
+def fun_l10_n913(x)
+ if (x < 1)
+ fun_l11_n492(x)
+ else
+ fun_l11_n502(x)
+ end
+end
+
+def fun_l10_n914(x)
+ if (x < 1)
+ fun_l11_n221(x)
+ else
+ fun_l11_n732(x)
+ end
+end
+
+def fun_l10_n915(x)
+ if (x < 1)
+ fun_l11_n853(x)
+ else
+ fun_l11_n625(x)
+ end
+end
+
+def fun_l10_n916(x)
+ if (x < 1)
+ fun_l11_n172(x)
+ else
+ fun_l11_n17(x)
+ end
+end
+
+def fun_l10_n917(x)
+ if (x < 1)
+ fun_l11_n438(x)
+ else
+ fun_l11_n480(x)
+ end
+end
+
+def fun_l10_n918(x)
+ if (x < 1)
+ fun_l11_n646(x)
+ else
+ fun_l11_n833(x)
+ end
+end
+
+def fun_l10_n919(x)
+ if (x < 1)
+ fun_l11_n628(x)
+ else
+ fun_l11_n40(x)
+ end
+end
+
+def fun_l10_n920(x)
+ if (x < 1)
+ fun_l11_n387(x)
+ else
+ fun_l11_n824(x)
+ end
+end
+
+def fun_l10_n921(x)
+ if (x < 1)
+ fun_l11_n641(x)
+ else
+ fun_l11_n669(x)
+ end
+end
+
+def fun_l10_n922(x)
+ if (x < 1)
+ fun_l11_n484(x)
+ else
+ fun_l11_n591(x)
+ end
+end
+
+def fun_l10_n923(x)
+ if (x < 1)
+ fun_l11_n610(x)
+ else
+ fun_l11_n132(x)
+ end
+end
+
+def fun_l10_n924(x)
+ if (x < 1)
+ fun_l11_n90(x)
+ else
+ fun_l11_n727(x)
+ end
+end
+
+def fun_l10_n925(x)
+ if (x < 1)
+ fun_l11_n44(x)
+ else
+ fun_l11_n412(x)
+ end
+end
+
+def fun_l10_n926(x)
+ if (x < 1)
+ fun_l11_n912(x)
+ else
+ fun_l11_n229(x)
+ end
+end
+
+def fun_l10_n927(x)
+ if (x < 1)
+ fun_l11_n647(x)
+ else
+ fun_l11_n13(x)
+ end
+end
+
+def fun_l10_n928(x)
+ if (x < 1)
+ fun_l11_n820(x)
+ else
+ fun_l11_n316(x)
+ end
+end
+
+def fun_l10_n929(x)
+ if (x < 1)
+ fun_l11_n850(x)
+ else
+ fun_l11_n868(x)
+ end
+end
+
+def fun_l10_n930(x)
+ if (x < 1)
+ fun_l11_n373(x)
+ else
+ fun_l11_n183(x)
+ end
+end
+
+def fun_l10_n931(x)
+ if (x < 1)
+ fun_l11_n217(x)
+ else
+ fun_l11_n230(x)
+ end
+end
+
+def fun_l10_n932(x)
+ if (x < 1)
+ fun_l11_n77(x)
+ else
+ fun_l11_n917(x)
+ end
+end
+
+def fun_l10_n933(x)
+ if (x < 1)
+ fun_l11_n264(x)
+ else
+ fun_l11_n992(x)
+ end
+end
+
+def fun_l10_n934(x)
+ if (x < 1)
+ fun_l11_n125(x)
+ else
+ fun_l11_n441(x)
+ end
+end
+
+def fun_l10_n935(x)
+ if (x < 1)
+ fun_l11_n586(x)
+ else
+ fun_l11_n946(x)
+ end
+end
+
+def fun_l10_n936(x)
+ if (x < 1)
+ fun_l11_n186(x)
+ else
+ fun_l11_n595(x)
+ end
+end
+
+def fun_l10_n937(x)
+ if (x < 1)
+ fun_l11_n210(x)
+ else
+ fun_l11_n186(x)
+ end
+end
+
+def fun_l10_n938(x)
+ if (x < 1)
+ fun_l11_n131(x)
+ else
+ fun_l11_n519(x)
+ end
+end
+
+def fun_l10_n939(x)
+ if (x < 1)
+ fun_l11_n863(x)
+ else
+ fun_l11_n486(x)
+ end
+end
+
+def fun_l10_n940(x)
+ if (x < 1)
+ fun_l11_n753(x)
+ else
+ fun_l11_n916(x)
+ end
+end
+
+def fun_l10_n941(x)
+ if (x < 1)
+ fun_l11_n8(x)
+ else
+ fun_l11_n153(x)
+ end
+end
+
+def fun_l10_n942(x)
+ if (x < 1)
+ fun_l11_n798(x)
+ else
+ fun_l11_n873(x)
+ end
+end
+
+def fun_l10_n943(x)
+ if (x < 1)
+ fun_l11_n862(x)
+ else
+ fun_l11_n293(x)
+ end
+end
+
+def fun_l10_n944(x)
+ if (x < 1)
+ fun_l11_n554(x)
+ else
+ fun_l11_n599(x)
+ end
+end
+
+def fun_l10_n945(x)
+ if (x < 1)
+ fun_l11_n134(x)
+ else
+ fun_l11_n535(x)
+ end
+end
+
+def fun_l10_n946(x)
+ if (x < 1)
+ fun_l11_n992(x)
+ else
+ fun_l11_n624(x)
+ end
+end
+
+def fun_l10_n947(x)
+ if (x < 1)
+ fun_l11_n436(x)
+ else
+ fun_l11_n153(x)
+ end
+end
+
+def fun_l10_n948(x)
+ if (x < 1)
+ fun_l11_n72(x)
+ else
+ fun_l11_n154(x)
+ end
+end
+
+def fun_l10_n949(x)
+ if (x < 1)
+ fun_l11_n61(x)
+ else
+ fun_l11_n612(x)
+ end
+end
+
+def fun_l10_n950(x)
+ if (x < 1)
+ fun_l11_n964(x)
+ else
+ fun_l11_n999(x)
+ end
+end
+
+def fun_l10_n951(x)
+ if (x < 1)
+ fun_l11_n689(x)
+ else
+ fun_l11_n165(x)
+ end
+end
+
+def fun_l10_n952(x)
+ if (x < 1)
+ fun_l11_n856(x)
+ else
+ fun_l11_n7(x)
+ end
+end
+
+def fun_l10_n953(x)
+ if (x < 1)
+ fun_l11_n421(x)
+ else
+ fun_l11_n416(x)
+ end
+end
+
+def fun_l10_n954(x)
+ if (x < 1)
+ fun_l11_n969(x)
+ else
+ fun_l11_n260(x)
+ end
+end
+
+def fun_l10_n955(x)
+ if (x < 1)
+ fun_l11_n716(x)
+ else
+ fun_l11_n364(x)
+ end
+end
+
+def fun_l10_n956(x)
+ if (x < 1)
+ fun_l11_n491(x)
+ else
+ fun_l11_n575(x)
+ end
+end
+
+def fun_l10_n957(x)
+ if (x < 1)
+ fun_l11_n522(x)
+ else
+ fun_l11_n430(x)
+ end
+end
+
+def fun_l10_n958(x)
+ if (x < 1)
+ fun_l11_n712(x)
+ else
+ fun_l11_n939(x)
+ end
+end
+
+def fun_l10_n959(x)
+ if (x < 1)
+ fun_l11_n230(x)
+ else
+ fun_l11_n819(x)
+ end
+end
+
+def fun_l10_n960(x)
+ if (x < 1)
+ fun_l11_n790(x)
+ else
+ fun_l11_n939(x)
+ end
+end
+
+def fun_l10_n961(x)
+ if (x < 1)
+ fun_l11_n844(x)
+ else
+ fun_l11_n847(x)
+ end
+end
+
+def fun_l10_n962(x)
+ if (x < 1)
+ fun_l11_n105(x)
+ else
+ fun_l11_n722(x)
+ end
+end
+
+def fun_l10_n963(x)
+ if (x < 1)
+ fun_l11_n166(x)
+ else
+ fun_l11_n990(x)
+ end
+end
+
+def fun_l10_n964(x)
+ if (x < 1)
+ fun_l11_n224(x)
+ else
+ fun_l11_n751(x)
+ end
+end
+
+def fun_l10_n965(x)
+ if (x < 1)
+ fun_l11_n809(x)
+ else
+ fun_l11_n739(x)
+ end
+end
+
+def fun_l10_n966(x)
+ if (x < 1)
+ fun_l11_n840(x)
+ else
+ fun_l11_n795(x)
+ end
+end
+
+def fun_l10_n967(x)
+ if (x < 1)
+ fun_l11_n791(x)
+ else
+ fun_l11_n926(x)
+ end
+end
+
+def fun_l10_n968(x)
+ if (x < 1)
+ fun_l11_n484(x)
+ else
+ fun_l11_n409(x)
+ end
+end
+
+def fun_l10_n969(x)
+ if (x < 1)
+ fun_l11_n22(x)
+ else
+ fun_l11_n284(x)
+ end
+end
+
+def fun_l10_n970(x)
+ if (x < 1)
+ fun_l11_n539(x)
+ else
+ fun_l11_n661(x)
+ end
+end
+
+def fun_l10_n971(x)
+ if (x < 1)
+ fun_l11_n453(x)
+ else
+ fun_l11_n619(x)
+ end
+end
+
+def fun_l10_n972(x)
+ if (x < 1)
+ fun_l11_n80(x)
+ else
+ fun_l11_n848(x)
+ end
+end
+
+def fun_l10_n973(x)
+ if (x < 1)
+ fun_l11_n599(x)
+ else
+ fun_l11_n147(x)
+ end
+end
+
+def fun_l10_n974(x)
+ if (x < 1)
+ fun_l11_n784(x)
+ else
+ fun_l11_n603(x)
+ end
+end
+
+def fun_l10_n975(x)
+ if (x < 1)
+ fun_l11_n166(x)
+ else
+ fun_l11_n12(x)
+ end
+end
+
+def fun_l10_n976(x)
+ if (x < 1)
+ fun_l11_n739(x)
+ else
+ fun_l11_n381(x)
+ end
+end
+
+def fun_l10_n977(x)
+ if (x < 1)
+ fun_l11_n45(x)
+ else
+ fun_l11_n67(x)
+ end
+end
+
+def fun_l10_n978(x)
+ if (x < 1)
+ fun_l11_n243(x)
+ else
+ fun_l11_n51(x)
+ end
+end
+
+def fun_l10_n979(x)
+ if (x < 1)
+ fun_l11_n964(x)
+ else
+ fun_l11_n949(x)
+ end
+end
+
+def fun_l10_n980(x)
+ if (x < 1)
+ fun_l11_n881(x)
+ else
+ fun_l11_n893(x)
+ end
+end
+
+def fun_l10_n981(x)
+ if (x < 1)
+ fun_l11_n808(x)
+ else
+ fun_l11_n205(x)
+ end
+end
+
+def fun_l10_n982(x)
+ if (x < 1)
+ fun_l11_n897(x)
+ else
+ fun_l11_n259(x)
+ end
+end
+
+def fun_l10_n983(x)
+ if (x < 1)
+ fun_l11_n671(x)
+ else
+ fun_l11_n115(x)
+ end
+end
+
+def fun_l10_n984(x)
+ if (x < 1)
+ fun_l11_n9(x)
+ else
+ fun_l11_n994(x)
+ end
+end
+
+def fun_l10_n985(x)
+ if (x < 1)
+ fun_l11_n663(x)
+ else
+ fun_l11_n979(x)
+ end
+end
+
+def fun_l10_n986(x)
+ if (x < 1)
+ fun_l11_n8(x)
+ else
+ fun_l11_n949(x)
+ end
+end
+
+def fun_l10_n987(x)
+ if (x < 1)
+ fun_l11_n230(x)
+ else
+ fun_l11_n822(x)
+ end
+end
+
+def fun_l10_n988(x)
+ if (x < 1)
+ fun_l11_n767(x)
+ else
+ fun_l11_n691(x)
+ end
+end
+
+def fun_l10_n989(x)
+ if (x < 1)
+ fun_l11_n524(x)
+ else
+ fun_l11_n514(x)
+ end
+end
+
+def fun_l10_n990(x)
+ if (x < 1)
+ fun_l11_n556(x)
+ else
+ fun_l11_n34(x)
+ end
+end
+
+def fun_l10_n991(x)
+ if (x < 1)
+ fun_l11_n516(x)
+ else
+ fun_l11_n817(x)
+ end
+end
+
+def fun_l10_n992(x)
+ if (x < 1)
+ fun_l11_n273(x)
+ else
+ fun_l11_n189(x)
+ end
+end
+
+def fun_l10_n993(x)
+ if (x < 1)
+ fun_l11_n726(x)
+ else
+ fun_l11_n260(x)
+ end
+end
+
+def fun_l10_n994(x)
+ if (x < 1)
+ fun_l11_n789(x)
+ else
+ fun_l11_n993(x)
+ end
+end
+
+def fun_l10_n995(x)
+ if (x < 1)
+ fun_l11_n187(x)
+ else
+ fun_l11_n291(x)
+ end
+end
+
+def fun_l10_n996(x)
+ if (x < 1)
+ fun_l11_n145(x)
+ else
+ fun_l11_n500(x)
+ end
+end
+
+def fun_l10_n997(x)
+ if (x < 1)
+ fun_l11_n437(x)
+ else
+ fun_l11_n925(x)
+ end
+end
+
+def fun_l10_n998(x)
+ if (x < 1)
+ fun_l11_n945(x)
+ else
+ fun_l11_n300(x)
+ end
+end
+
+def fun_l10_n999(x)
+ if (x < 1)
+ fun_l11_n703(x)
+ else
+ fun_l11_n542(x)
+ end
+end
+
+def fun_l11_n0(x)
+ if (x < 1)
+ fun_l12_n539(x)
+ else
+ fun_l12_n60(x)
+ end
+end
+
+def fun_l11_n1(x)
+ if (x < 1)
+ fun_l12_n659(x)
+ else
+ fun_l12_n739(x)
+ end
+end
+
+def fun_l11_n2(x)
+ if (x < 1)
+ fun_l12_n273(x)
+ else
+ fun_l12_n392(x)
+ end
+end
+
+def fun_l11_n3(x)
+ if (x < 1)
+ fun_l12_n394(x)
+ else
+ fun_l12_n989(x)
+ end
+end
+
+def fun_l11_n4(x)
+ if (x < 1)
+ fun_l12_n254(x)
+ else
+ fun_l12_n906(x)
+ end
+end
+
+def fun_l11_n5(x)
+ if (x < 1)
+ fun_l12_n229(x)
+ else
+ fun_l12_n345(x)
+ end
+end
+
+def fun_l11_n6(x)
+ if (x < 1)
+ fun_l12_n15(x)
+ else
+ fun_l12_n893(x)
+ end
+end
+
+def fun_l11_n7(x)
+ if (x < 1)
+ fun_l12_n185(x)
+ else
+ fun_l12_n187(x)
+ end
+end
+
+def fun_l11_n8(x)
+ if (x < 1)
+ fun_l12_n761(x)
+ else
+ fun_l12_n850(x)
+ end
+end
+
+def fun_l11_n9(x)
+ if (x < 1)
+ fun_l12_n644(x)
+ else
+ fun_l12_n274(x)
+ end
+end
+
+def fun_l11_n10(x)
+ if (x < 1)
+ fun_l12_n652(x)
+ else
+ fun_l12_n223(x)
+ end
+end
+
+def fun_l11_n11(x)
+ if (x < 1)
+ fun_l12_n905(x)
+ else
+ fun_l12_n215(x)
+ end
+end
+
+def fun_l11_n12(x)
+ if (x < 1)
+ fun_l12_n58(x)
+ else
+ fun_l12_n495(x)
+ end
+end
+
+def fun_l11_n13(x)
+ if (x < 1)
+ fun_l12_n529(x)
+ else
+ fun_l12_n477(x)
+ end
+end
+
+def fun_l11_n14(x)
+ if (x < 1)
+ fun_l12_n743(x)
+ else
+ fun_l12_n847(x)
+ end
+end
+
+def fun_l11_n15(x)
+ if (x < 1)
+ fun_l12_n558(x)
+ else
+ fun_l12_n252(x)
+ end
+end
+
+def fun_l11_n16(x)
+ if (x < 1)
+ fun_l12_n115(x)
+ else
+ fun_l12_n972(x)
+ end
+end
+
+def fun_l11_n17(x)
+ if (x < 1)
+ fun_l12_n374(x)
+ else
+ fun_l12_n637(x)
+ end
+end
+
+def fun_l11_n18(x)
+ if (x < 1)
+ fun_l12_n978(x)
+ else
+ fun_l12_n570(x)
+ end
+end
+
+def fun_l11_n19(x)
+ if (x < 1)
+ fun_l12_n264(x)
+ else
+ fun_l12_n743(x)
+ end
+end
+
+def fun_l11_n20(x)
+ if (x < 1)
+ fun_l12_n936(x)
+ else
+ fun_l12_n986(x)
+ end
+end
+
+def fun_l11_n21(x)
+ if (x < 1)
+ fun_l12_n107(x)
+ else
+ fun_l12_n167(x)
+ end
+end
+
+def fun_l11_n22(x)
+ if (x < 1)
+ fun_l12_n777(x)
+ else
+ fun_l12_n143(x)
+ end
+end
+
+def fun_l11_n23(x)
+ if (x < 1)
+ fun_l12_n510(x)
+ else
+ fun_l12_n236(x)
+ end
+end
+
+def fun_l11_n24(x)
+ if (x < 1)
+ fun_l12_n180(x)
+ else
+ fun_l12_n309(x)
+ end
+end
+
+def fun_l11_n25(x)
+ if (x < 1)
+ fun_l12_n850(x)
+ else
+ fun_l12_n374(x)
+ end
+end
+
+def fun_l11_n26(x)
+ if (x < 1)
+ fun_l12_n573(x)
+ else
+ fun_l12_n722(x)
+ end
+end
+
+def fun_l11_n27(x)
+ if (x < 1)
+ fun_l12_n800(x)
+ else
+ fun_l12_n981(x)
+ end
+end
+
+def fun_l11_n28(x)
+ if (x < 1)
+ fun_l12_n705(x)
+ else
+ fun_l12_n636(x)
+ end
+end
+
+def fun_l11_n29(x)
+ if (x < 1)
+ fun_l12_n618(x)
+ else
+ fun_l12_n429(x)
+ end
+end
+
+def fun_l11_n30(x)
+ if (x < 1)
+ fun_l12_n139(x)
+ else
+ fun_l12_n95(x)
+ end
+end
+
+def fun_l11_n31(x)
+ if (x < 1)
+ fun_l12_n861(x)
+ else
+ fun_l12_n797(x)
+ end
+end
+
+def fun_l11_n32(x)
+ if (x < 1)
+ fun_l12_n576(x)
+ else
+ fun_l12_n719(x)
+ end
+end
+
+def fun_l11_n33(x)
+ if (x < 1)
+ fun_l12_n236(x)
+ else
+ fun_l12_n429(x)
+ end
+end
+
+def fun_l11_n34(x)
+ if (x < 1)
+ fun_l12_n375(x)
+ else
+ fun_l12_n696(x)
+ end
+end
+
+def fun_l11_n35(x)
+ if (x < 1)
+ fun_l12_n291(x)
+ else
+ fun_l12_n799(x)
+ end
+end
+
+def fun_l11_n36(x)
+ if (x < 1)
+ fun_l12_n180(x)
+ else
+ fun_l12_n228(x)
+ end
+end
+
+def fun_l11_n37(x)
+ if (x < 1)
+ fun_l12_n455(x)
+ else
+ fun_l12_n983(x)
+ end
+end
+
+def fun_l11_n38(x)
+ if (x < 1)
+ fun_l12_n486(x)
+ else
+ fun_l12_n871(x)
+ end
+end
+
+def fun_l11_n39(x)
+ if (x < 1)
+ fun_l12_n945(x)
+ else
+ fun_l12_n47(x)
+ end
+end
+
+def fun_l11_n40(x)
+ if (x < 1)
+ fun_l12_n531(x)
+ else
+ fun_l12_n506(x)
+ end
+end
+
+def fun_l11_n41(x)
+ if (x < 1)
+ fun_l12_n248(x)
+ else
+ fun_l12_n142(x)
+ end
+end
+
+def fun_l11_n42(x)
+ if (x < 1)
+ fun_l12_n415(x)
+ else
+ fun_l12_n177(x)
+ end
+end
+
+def fun_l11_n43(x)
+ if (x < 1)
+ fun_l12_n560(x)
+ else
+ fun_l12_n63(x)
+ end
+end
+
+def fun_l11_n44(x)
+ if (x < 1)
+ fun_l12_n180(x)
+ else
+ fun_l12_n268(x)
+ end
+end
+
+def fun_l11_n45(x)
+ if (x < 1)
+ fun_l12_n814(x)
+ else
+ fun_l12_n967(x)
+ end
+end
+
+def fun_l11_n46(x)
+ if (x < 1)
+ fun_l12_n273(x)
+ else
+ fun_l12_n702(x)
+ end
+end
+
+def fun_l11_n47(x)
+ if (x < 1)
+ fun_l12_n626(x)
+ else
+ fun_l12_n615(x)
+ end
+end
+
+def fun_l11_n48(x)
+ if (x < 1)
+ fun_l12_n374(x)
+ else
+ fun_l12_n669(x)
+ end
+end
+
+def fun_l11_n49(x)
+ if (x < 1)
+ fun_l12_n681(x)
+ else
+ fun_l12_n48(x)
+ end
+end
+
+def fun_l11_n50(x)
+ if (x < 1)
+ fun_l12_n3(x)
+ else
+ fun_l12_n455(x)
+ end
+end
+
+def fun_l11_n51(x)
+ if (x < 1)
+ fun_l12_n461(x)
+ else
+ fun_l12_n350(x)
+ end
+end
+
+def fun_l11_n52(x)
+ if (x < 1)
+ fun_l12_n129(x)
+ else
+ fun_l12_n266(x)
+ end
+end
+
+def fun_l11_n53(x)
+ if (x < 1)
+ fun_l12_n802(x)
+ else
+ fun_l12_n863(x)
+ end
+end
+
+def fun_l11_n54(x)
+ if (x < 1)
+ fun_l12_n216(x)
+ else
+ fun_l12_n820(x)
+ end
+end
+
+def fun_l11_n55(x)
+ if (x < 1)
+ fun_l12_n626(x)
+ else
+ fun_l12_n476(x)
+ end
+end
+
+def fun_l11_n56(x)
+ if (x < 1)
+ fun_l12_n162(x)
+ else
+ fun_l12_n796(x)
+ end
+end
+
+def fun_l11_n57(x)
+ if (x < 1)
+ fun_l12_n45(x)
+ else
+ fun_l12_n893(x)
+ end
+end
+
+def fun_l11_n58(x)
+ if (x < 1)
+ fun_l12_n227(x)
+ else
+ fun_l12_n919(x)
+ end
+end
+
+def fun_l11_n59(x)
+ if (x < 1)
+ fun_l12_n300(x)
+ else
+ fun_l12_n360(x)
+ end
+end
+
+def fun_l11_n60(x)
+ if (x < 1)
+ fun_l12_n265(x)
+ else
+ fun_l12_n552(x)
+ end
+end
+
+def fun_l11_n61(x)
+ if (x < 1)
+ fun_l12_n927(x)
+ else
+ fun_l12_n486(x)
+ end
+end
+
+def fun_l11_n62(x)
+ if (x < 1)
+ fun_l12_n94(x)
+ else
+ fun_l12_n28(x)
+ end
+end
+
+def fun_l11_n63(x)
+ if (x < 1)
+ fun_l12_n295(x)
+ else
+ fun_l12_n967(x)
+ end
+end
+
+def fun_l11_n64(x)
+ if (x < 1)
+ fun_l12_n713(x)
+ else
+ fun_l12_n463(x)
+ end
+end
+
+def fun_l11_n65(x)
+ if (x < 1)
+ fun_l12_n454(x)
+ else
+ fun_l12_n616(x)
+ end
+end
+
+def fun_l11_n66(x)
+ if (x < 1)
+ fun_l12_n121(x)
+ else
+ fun_l12_n277(x)
+ end
+end
+
+def fun_l11_n67(x)
+ if (x < 1)
+ fun_l12_n524(x)
+ else
+ fun_l12_n242(x)
+ end
+end
+
+def fun_l11_n68(x)
+ if (x < 1)
+ fun_l12_n570(x)
+ else
+ fun_l12_n658(x)
+ end
+end
+
+def fun_l11_n69(x)
+ if (x < 1)
+ fun_l12_n343(x)
+ else
+ fun_l12_n826(x)
+ end
+end
+
+def fun_l11_n70(x)
+ if (x < 1)
+ fun_l12_n732(x)
+ else
+ fun_l12_n993(x)
+ end
+end
+
+def fun_l11_n71(x)
+ if (x < 1)
+ fun_l12_n380(x)
+ else
+ fun_l12_n486(x)
+ end
+end
+
+def fun_l11_n72(x)
+ if (x < 1)
+ fun_l12_n55(x)
+ else
+ fun_l12_n342(x)
+ end
+end
+
+def fun_l11_n73(x)
+ if (x < 1)
+ fun_l12_n789(x)
+ else
+ fun_l12_n646(x)
+ end
+end
+
+def fun_l11_n74(x)
+ if (x < 1)
+ fun_l12_n106(x)
+ else
+ fun_l12_n557(x)
+ end
+end
+
+def fun_l11_n75(x)
+ if (x < 1)
+ fun_l12_n368(x)
+ else
+ fun_l12_n5(x)
+ end
+end
+
+def fun_l11_n76(x)
+ if (x < 1)
+ fun_l12_n992(x)
+ else
+ fun_l12_n521(x)
+ end
+end
+
+def fun_l11_n77(x)
+ if (x < 1)
+ fun_l12_n754(x)
+ else
+ fun_l12_n259(x)
+ end
+end
+
+def fun_l11_n78(x)
+ if (x < 1)
+ fun_l12_n855(x)
+ else
+ fun_l12_n946(x)
+ end
+end
+
+def fun_l11_n79(x)
+ if (x < 1)
+ fun_l12_n727(x)
+ else
+ fun_l12_n422(x)
+ end
+end
+
+def fun_l11_n80(x)
+ if (x < 1)
+ fun_l12_n649(x)
+ else
+ fun_l12_n593(x)
+ end
+end
+
+def fun_l11_n81(x)
+ if (x < 1)
+ fun_l12_n206(x)
+ else
+ fun_l12_n222(x)
+ end
+end
+
+def fun_l11_n82(x)
+ if (x < 1)
+ fun_l12_n995(x)
+ else
+ fun_l12_n471(x)
+ end
+end
+
+def fun_l11_n83(x)
+ if (x < 1)
+ fun_l12_n926(x)
+ else
+ fun_l12_n165(x)
+ end
+end
+
+def fun_l11_n84(x)
+ if (x < 1)
+ fun_l12_n988(x)
+ else
+ fun_l12_n495(x)
+ end
+end
+
+def fun_l11_n85(x)
+ if (x < 1)
+ fun_l12_n839(x)
+ else
+ fun_l12_n565(x)
+ end
+end
+
+def fun_l11_n86(x)
+ if (x < 1)
+ fun_l12_n381(x)
+ else
+ fun_l12_n981(x)
+ end
+end
+
+def fun_l11_n87(x)
+ if (x < 1)
+ fun_l12_n64(x)
+ else
+ fun_l12_n616(x)
+ end
+end
+
+def fun_l11_n88(x)
+ if (x < 1)
+ fun_l12_n714(x)
+ else
+ fun_l12_n995(x)
+ end
+end
+
+def fun_l11_n89(x)
+ if (x < 1)
+ fun_l12_n796(x)
+ else
+ fun_l12_n534(x)
+ end
+end
+
+def fun_l11_n90(x)
+ if (x < 1)
+ fun_l12_n31(x)
+ else
+ fun_l12_n584(x)
+ end
+end
+
+def fun_l11_n91(x)
+ if (x < 1)
+ fun_l12_n741(x)
+ else
+ fun_l12_n356(x)
+ end
+end
+
+def fun_l11_n92(x)
+ if (x < 1)
+ fun_l12_n418(x)
+ else
+ fun_l12_n184(x)
+ end
+end
+
+def fun_l11_n93(x)
+ if (x < 1)
+ fun_l12_n427(x)
+ else
+ fun_l12_n136(x)
+ end
+end
+
+def fun_l11_n94(x)
+ if (x < 1)
+ fun_l12_n968(x)
+ else
+ fun_l12_n647(x)
+ end
+end
+
+def fun_l11_n95(x)
+ if (x < 1)
+ fun_l12_n641(x)
+ else
+ fun_l12_n675(x)
+ end
+end
+
+def fun_l11_n96(x)
+ if (x < 1)
+ fun_l12_n465(x)
+ else
+ fun_l12_n507(x)
+ end
+end
+
+def fun_l11_n97(x)
+ if (x < 1)
+ fun_l12_n910(x)
+ else
+ fun_l12_n718(x)
+ end
+end
+
+def fun_l11_n98(x)
+ if (x < 1)
+ fun_l12_n686(x)
+ else
+ fun_l12_n94(x)
+ end
+end
+
+def fun_l11_n99(x)
+ if (x < 1)
+ fun_l12_n94(x)
+ else
+ fun_l12_n632(x)
+ end
+end
+
+def fun_l11_n100(x)
+ if (x < 1)
+ fun_l12_n270(x)
+ else
+ fun_l12_n228(x)
+ end
+end
+
+def fun_l11_n101(x)
+ if (x < 1)
+ fun_l12_n569(x)
+ else
+ fun_l12_n492(x)
+ end
+end
+
+def fun_l11_n102(x)
+ if (x < 1)
+ fun_l12_n187(x)
+ else
+ fun_l12_n183(x)
+ end
+end
+
+def fun_l11_n103(x)
+ if (x < 1)
+ fun_l12_n894(x)
+ else
+ fun_l12_n655(x)
+ end
+end
+
+def fun_l11_n104(x)
+ if (x < 1)
+ fun_l12_n347(x)
+ else
+ fun_l12_n467(x)
+ end
+end
+
+def fun_l11_n105(x)
+ if (x < 1)
+ fun_l12_n198(x)
+ else
+ fun_l12_n838(x)
+ end
+end
+
+def fun_l11_n106(x)
+ if (x < 1)
+ fun_l12_n941(x)
+ else
+ fun_l12_n98(x)
+ end
+end
+
+def fun_l11_n107(x)
+ if (x < 1)
+ fun_l12_n406(x)
+ else
+ fun_l12_n773(x)
+ end
+end
+
+def fun_l11_n108(x)
+ if (x < 1)
+ fun_l12_n980(x)
+ else
+ fun_l12_n508(x)
+ end
+end
+
+def fun_l11_n109(x)
+ if (x < 1)
+ fun_l12_n286(x)
+ else
+ fun_l12_n928(x)
+ end
+end
+
+def fun_l11_n110(x)
+ if (x < 1)
+ fun_l12_n710(x)
+ else
+ fun_l12_n20(x)
+ end
+end
+
+def fun_l11_n111(x)
+ if (x < 1)
+ fun_l12_n358(x)
+ else
+ fun_l12_n549(x)
+ end
+end
+
+def fun_l11_n112(x)
+ if (x < 1)
+ fun_l12_n359(x)
+ else
+ fun_l12_n548(x)
+ end
+end
+
+def fun_l11_n113(x)
+ if (x < 1)
+ fun_l12_n665(x)
+ else
+ fun_l12_n802(x)
+ end
+end
+
+def fun_l11_n114(x)
+ if (x < 1)
+ fun_l12_n199(x)
+ else
+ fun_l12_n904(x)
+ end
+end
+
+def fun_l11_n115(x)
+ if (x < 1)
+ fun_l12_n995(x)
+ else
+ fun_l12_n319(x)
+ end
+end
+
+def fun_l11_n116(x)
+ if (x < 1)
+ fun_l12_n873(x)
+ else
+ fun_l12_n786(x)
+ end
+end
+
+def fun_l11_n117(x)
+ if (x < 1)
+ fun_l12_n147(x)
+ else
+ fun_l12_n542(x)
+ end
+end
+
+def fun_l11_n118(x)
+ if (x < 1)
+ fun_l12_n669(x)
+ else
+ fun_l12_n871(x)
+ end
+end
+
+def fun_l11_n119(x)
+ if (x < 1)
+ fun_l12_n552(x)
+ else
+ fun_l12_n998(x)
+ end
+end
+
+def fun_l11_n120(x)
+ if (x < 1)
+ fun_l12_n300(x)
+ else
+ fun_l12_n333(x)
+ end
+end
+
+def fun_l11_n121(x)
+ if (x < 1)
+ fun_l12_n846(x)
+ else
+ fun_l12_n133(x)
+ end
+end
+
+def fun_l11_n122(x)
+ if (x < 1)
+ fun_l12_n946(x)
+ else
+ fun_l12_n540(x)
+ end
+end
+
+def fun_l11_n123(x)
+ if (x < 1)
+ fun_l12_n71(x)
+ else
+ fun_l12_n264(x)
+ end
+end
+
+def fun_l11_n124(x)
+ if (x < 1)
+ fun_l12_n410(x)
+ else
+ fun_l12_n60(x)
+ end
+end
+
+def fun_l11_n125(x)
+ if (x < 1)
+ fun_l12_n62(x)
+ else
+ fun_l12_n211(x)
+ end
+end
+
+def fun_l11_n126(x)
+ if (x < 1)
+ fun_l12_n252(x)
+ else
+ fun_l12_n635(x)
+ end
+end
+
+def fun_l11_n127(x)
+ if (x < 1)
+ fun_l12_n444(x)
+ else
+ fun_l12_n735(x)
+ end
+end
+
+def fun_l11_n128(x)
+ if (x < 1)
+ fun_l12_n3(x)
+ else
+ fun_l12_n403(x)
+ end
+end
+
+def fun_l11_n129(x)
+ if (x < 1)
+ fun_l12_n121(x)
+ else
+ fun_l12_n882(x)
+ end
+end
+
+def fun_l11_n130(x)
+ if (x < 1)
+ fun_l12_n985(x)
+ else
+ fun_l12_n983(x)
+ end
+end
+
+def fun_l11_n131(x)
+ if (x < 1)
+ fun_l12_n413(x)
+ else
+ fun_l12_n117(x)
+ end
+end
+
+def fun_l11_n132(x)
+ if (x < 1)
+ fun_l12_n856(x)
+ else
+ fun_l12_n312(x)
+ end
+end
+
+def fun_l11_n133(x)
+ if (x < 1)
+ fun_l12_n249(x)
+ else
+ fun_l12_n870(x)
+ end
+end
+
+def fun_l11_n134(x)
+ if (x < 1)
+ fun_l12_n367(x)
+ else
+ fun_l12_n748(x)
+ end
+end
+
+def fun_l11_n135(x)
+ if (x < 1)
+ fun_l12_n670(x)
+ else
+ fun_l12_n464(x)
+ end
+end
+
+def fun_l11_n136(x)
+ if (x < 1)
+ fun_l12_n698(x)
+ else
+ fun_l12_n238(x)
+ end
+end
+
+def fun_l11_n137(x)
+ if (x < 1)
+ fun_l12_n856(x)
+ else
+ fun_l12_n660(x)
+ end
+end
+
+def fun_l11_n138(x)
+ if (x < 1)
+ fun_l12_n693(x)
+ else
+ fun_l12_n793(x)
+ end
+end
+
+def fun_l11_n139(x)
+ if (x < 1)
+ fun_l12_n959(x)
+ else
+ fun_l12_n377(x)
+ end
+end
+
+def fun_l11_n140(x)
+ if (x < 1)
+ fun_l12_n24(x)
+ else
+ fun_l12_n250(x)
+ end
+end
+
+def fun_l11_n141(x)
+ if (x < 1)
+ fun_l12_n270(x)
+ else
+ fun_l12_n720(x)
+ end
+end
+
+def fun_l11_n142(x)
+ if (x < 1)
+ fun_l12_n775(x)
+ else
+ fun_l12_n781(x)
+ end
+end
+
+def fun_l11_n143(x)
+ if (x < 1)
+ fun_l12_n266(x)
+ else
+ fun_l12_n608(x)
+ end
+end
+
+def fun_l11_n144(x)
+ if (x < 1)
+ fun_l12_n196(x)
+ else
+ fun_l12_n70(x)
+ end
+end
+
+def fun_l11_n145(x)
+ if (x < 1)
+ fun_l12_n100(x)
+ else
+ fun_l12_n846(x)
+ end
+end
+
+def fun_l11_n146(x)
+ if (x < 1)
+ fun_l12_n406(x)
+ else
+ fun_l12_n966(x)
+ end
+end
+
+def fun_l11_n147(x)
+ if (x < 1)
+ fun_l12_n816(x)
+ else
+ fun_l12_n54(x)
+ end
+end
+
+def fun_l11_n148(x)
+ if (x < 1)
+ fun_l12_n856(x)
+ else
+ fun_l12_n710(x)
+ end
+end
+
+def fun_l11_n149(x)
+ if (x < 1)
+ fun_l12_n597(x)
+ else
+ fun_l12_n596(x)
+ end
+end
+
+def fun_l11_n150(x)
+ if (x < 1)
+ fun_l12_n938(x)
+ else
+ fun_l12_n349(x)
+ end
+end
+
+def fun_l11_n151(x)
+ if (x < 1)
+ fun_l12_n987(x)
+ else
+ fun_l12_n231(x)
+ end
+end
+
+def fun_l11_n152(x)
+ if (x < 1)
+ fun_l12_n67(x)
+ else
+ fun_l12_n685(x)
+ end
+end
+
+def fun_l11_n153(x)
+ if (x < 1)
+ fun_l12_n786(x)
+ else
+ fun_l12_n71(x)
+ end
+end
+
+def fun_l11_n154(x)
+ if (x < 1)
+ fun_l12_n245(x)
+ else
+ fun_l12_n109(x)
+ end
+end
+
+def fun_l11_n155(x)
+ if (x < 1)
+ fun_l12_n665(x)
+ else
+ fun_l12_n565(x)
+ end
+end
+
+def fun_l11_n156(x)
+ if (x < 1)
+ fun_l12_n885(x)
+ else
+ fun_l12_n27(x)
+ end
+end
+
+def fun_l11_n157(x)
+ if (x < 1)
+ fun_l12_n704(x)
+ else
+ fun_l12_n140(x)
+ end
+end
+
+def fun_l11_n158(x)
+ if (x < 1)
+ fun_l12_n505(x)
+ else
+ fun_l12_n428(x)
+ end
+end
+
+def fun_l11_n159(x)
+ if (x < 1)
+ fun_l12_n646(x)
+ else
+ fun_l12_n250(x)
+ end
+end
+
+def fun_l11_n160(x)
+ if (x < 1)
+ fun_l12_n125(x)
+ else
+ fun_l12_n22(x)
+ end
+end
+
+def fun_l11_n161(x)
+ if (x < 1)
+ fun_l12_n49(x)
+ else
+ fun_l12_n852(x)
+ end
+end
+
+def fun_l11_n162(x)
+ if (x < 1)
+ fun_l12_n992(x)
+ else
+ fun_l12_n321(x)
+ end
+end
+
+def fun_l11_n163(x)
+ if (x < 1)
+ fun_l12_n457(x)
+ else
+ fun_l12_n162(x)
+ end
+end
+
+def fun_l11_n164(x)
+ if (x < 1)
+ fun_l12_n612(x)
+ else
+ fun_l12_n107(x)
+ end
+end
+
+def fun_l11_n165(x)
+ if (x < 1)
+ fun_l12_n786(x)
+ else
+ fun_l12_n338(x)
+ end
+end
+
+def fun_l11_n166(x)
+ if (x < 1)
+ fun_l12_n623(x)
+ else
+ fun_l12_n18(x)
+ end
+end
+
+def fun_l11_n167(x)
+ if (x < 1)
+ fun_l12_n605(x)
+ else
+ fun_l12_n963(x)
+ end
+end
+
+def fun_l11_n168(x)
+ if (x < 1)
+ fun_l12_n111(x)
+ else
+ fun_l12_n822(x)
+ end
+end
+
+def fun_l11_n169(x)
+ if (x < 1)
+ fun_l12_n502(x)
+ else
+ fun_l12_n291(x)
+ end
+end
+
+def fun_l11_n170(x)
+ if (x < 1)
+ fun_l12_n984(x)
+ else
+ fun_l12_n950(x)
+ end
+end
+
+def fun_l11_n171(x)
+ if (x < 1)
+ fun_l12_n915(x)
+ else
+ fun_l12_n81(x)
+ end
+end
+
+def fun_l11_n172(x)
+ if (x < 1)
+ fun_l12_n839(x)
+ else
+ fun_l12_n405(x)
+ end
+end
+
+def fun_l11_n173(x)
+ if (x < 1)
+ fun_l12_n331(x)
+ else
+ fun_l12_n906(x)
+ end
+end
+
+def fun_l11_n174(x)
+ if (x < 1)
+ fun_l12_n698(x)
+ else
+ fun_l12_n378(x)
+ end
+end
+
+def fun_l11_n175(x)
+ if (x < 1)
+ fun_l12_n648(x)
+ else
+ fun_l12_n824(x)
+ end
+end
+
+def fun_l11_n176(x)
+ if (x < 1)
+ fun_l12_n876(x)
+ else
+ fun_l12_n873(x)
+ end
+end
+
+def fun_l11_n177(x)
+ if (x < 1)
+ fun_l12_n932(x)
+ else
+ fun_l12_n797(x)
+ end
+end
+
+def fun_l11_n178(x)
+ if (x < 1)
+ fun_l12_n975(x)
+ else
+ fun_l12_n166(x)
+ end
+end
+
+def fun_l11_n179(x)
+ if (x < 1)
+ fun_l12_n66(x)
+ else
+ fun_l12_n624(x)
+ end
+end
+
+def fun_l11_n180(x)
+ if (x < 1)
+ fun_l12_n676(x)
+ else
+ fun_l12_n603(x)
+ end
+end
+
+def fun_l11_n181(x)
+ if (x < 1)
+ fun_l12_n80(x)
+ else
+ fun_l12_n504(x)
+ end
+end
+
+def fun_l11_n182(x)
+ if (x < 1)
+ fun_l12_n465(x)
+ else
+ fun_l12_n319(x)
+ end
+end
+
+def fun_l11_n183(x)
+ if (x < 1)
+ fun_l12_n493(x)
+ else
+ fun_l12_n412(x)
+ end
+end
+
+def fun_l11_n184(x)
+ if (x < 1)
+ fun_l12_n278(x)
+ else
+ fun_l12_n145(x)
+ end
+end
+
+def fun_l11_n185(x)
+ if (x < 1)
+ fun_l12_n328(x)
+ else
+ fun_l12_n777(x)
+ end
+end
+
+def fun_l11_n186(x)
+ if (x < 1)
+ fun_l12_n120(x)
+ else
+ fun_l12_n462(x)
+ end
+end
+
+def fun_l11_n187(x)
+ if (x < 1)
+ fun_l12_n755(x)
+ else
+ fun_l12_n260(x)
+ end
+end
+
+def fun_l11_n188(x)
+ if (x < 1)
+ fun_l12_n378(x)
+ else
+ fun_l12_n174(x)
+ end
+end
+
+def fun_l11_n189(x)
+ if (x < 1)
+ fun_l12_n100(x)
+ else
+ fun_l12_n234(x)
+ end
+end
+
+def fun_l11_n190(x)
+ if (x < 1)
+ fun_l12_n132(x)
+ else
+ fun_l12_n437(x)
+ end
+end
+
+def fun_l11_n191(x)
+ if (x < 1)
+ fun_l12_n399(x)
+ else
+ fun_l12_n989(x)
+ end
+end
+
+def fun_l11_n192(x)
+ if (x < 1)
+ fun_l12_n355(x)
+ else
+ fun_l12_n953(x)
+ end
+end
+
+def fun_l11_n193(x)
+ if (x < 1)
+ fun_l12_n139(x)
+ else
+ fun_l12_n138(x)
+ end
+end
+
+def fun_l11_n194(x)
+ if (x < 1)
+ fun_l12_n294(x)
+ else
+ fun_l12_n676(x)
+ end
+end
+
+def fun_l11_n195(x)
+ if (x < 1)
+ fun_l12_n581(x)
+ else
+ fun_l12_n549(x)
+ end
+end
+
+def fun_l11_n196(x)
+ if (x < 1)
+ fun_l12_n555(x)
+ else
+ fun_l12_n738(x)
+ end
+end
+
+def fun_l11_n197(x)
+ if (x < 1)
+ fun_l12_n170(x)
+ else
+ fun_l12_n476(x)
+ end
+end
+
+def fun_l11_n198(x)
+ if (x < 1)
+ fun_l12_n350(x)
+ else
+ fun_l12_n576(x)
+ end
+end
+
+def fun_l11_n199(x)
+ if (x < 1)
+ fun_l12_n647(x)
+ else
+ fun_l12_n94(x)
+ end
+end
+
+def fun_l11_n200(x)
+ if (x < 1)
+ fun_l12_n28(x)
+ else
+ fun_l12_n706(x)
+ end
+end
+
+def fun_l11_n201(x)
+ if (x < 1)
+ fun_l12_n189(x)
+ else
+ fun_l12_n366(x)
+ end
+end
+
+def fun_l11_n202(x)
+ if (x < 1)
+ fun_l12_n690(x)
+ else
+ fun_l12_n807(x)
+ end
+end
+
+def fun_l11_n203(x)
+ if (x < 1)
+ fun_l12_n402(x)
+ else
+ fun_l12_n685(x)
+ end
+end
+
+def fun_l11_n204(x)
+ if (x < 1)
+ fun_l12_n232(x)
+ else
+ fun_l12_n257(x)
+ end
+end
+
+def fun_l11_n205(x)
+ if (x < 1)
+ fun_l12_n108(x)
+ else
+ fun_l12_n888(x)
+ end
+end
+
+def fun_l11_n206(x)
+ if (x < 1)
+ fun_l12_n494(x)
+ else
+ fun_l12_n372(x)
+ end
+end
+
+def fun_l11_n207(x)
+ if (x < 1)
+ fun_l12_n607(x)
+ else
+ fun_l12_n336(x)
+ end
+end
+
+def fun_l11_n208(x)
+ if (x < 1)
+ fun_l12_n913(x)
+ else
+ fun_l12_n134(x)
+ end
+end
+
+def fun_l11_n209(x)
+ if (x < 1)
+ fun_l12_n996(x)
+ else
+ fun_l12_n918(x)
+ end
+end
+
+def fun_l11_n210(x)
+ if (x < 1)
+ fun_l12_n674(x)
+ else
+ fun_l12_n260(x)
+ end
+end
+
+def fun_l11_n211(x)
+ if (x < 1)
+ fun_l12_n344(x)
+ else
+ fun_l12_n219(x)
+ end
+end
+
+def fun_l11_n212(x)
+ if (x < 1)
+ fun_l12_n161(x)
+ else
+ fun_l12_n415(x)
+ end
+end
+
+def fun_l11_n213(x)
+ if (x < 1)
+ fun_l12_n65(x)
+ else
+ fun_l12_n777(x)
+ end
+end
+
+def fun_l11_n214(x)
+ if (x < 1)
+ fun_l12_n369(x)
+ else
+ fun_l12_n899(x)
+ end
+end
+
+def fun_l11_n215(x)
+ if (x < 1)
+ fun_l12_n310(x)
+ else
+ fun_l12_n118(x)
+ end
+end
+
+def fun_l11_n216(x)
+ if (x < 1)
+ fun_l12_n326(x)
+ else
+ fun_l12_n823(x)
+ end
+end
+
+def fun_l11_n217(x)
+ if (x < 1)
+ fun_l12_n981(x)
+ else
+ fun_l12_n824(x)
+ end
+end
+
+def fun_l11_n218(x)
+ if (x < 1)
+ fun_l12_n425(x)
+ else
+ fun_l12_n483(x)
+ end
+end
+
+def fun_l11_n219(x)
+ if (x < 1)
+ fun_l12_n931(x)
+ else
+ fun_l12_n366(x)
+ end
+end
+
+def fun_l11_n220(x)
+ if (x < 1)
+ fun_l12_n325(x)
+ else
+ fun_l12_n926(x)
+ end
+end
+
+def fun_l11_n221(x)
+ if (x < 1)
+ fun_l12_n924(x)
+ else
+ fun_l12_n764(x)
+ end
+end
+
+def fun_l11_n222(x)
+ if (x < 1)
+ fun_l12_n407(x)
+ else
+ fun_l12_n137(x)
+ end
+end
+
+def fun_l11_n223(x)
+ if (x < 1)
+ fun_l12_n584(x)
+ else
+ fun_l12_n294(x)
+ end
+end
+
+def fun_l11_n224(x)
+ if (x < 1)
+ fun_l12_n39(x)
+ else
+ fun_l12_n795(x)
+ end
+end
+
+def fun_l11_n225(x)
+ if (x < 1)
+ fun_l12_n37(x)
+ else
+ fun_l12_n738(x)
+ end
+end
+
+def fun_l11_n226(x)
+ if (x < 1)
+ fun_l12_n779(x)
+ else
+ fun_l12_n152(x)
+ end
+end
+
+def fun_l11_n227(x)
+ if (x < 1)
+ fun_l12_n116(x)
+ else
+ fun_l12_n589(x)
+ end
+end
+
+def fun_l11_n228(x)
+ if (x < 1)
+ fun_l12_n500(x)
+ else
+ fun_l12_n916(x)
+ end
+end
+
+def fun_l11_n229(x)
+ if (x < 1)
+ fun_l12_n443(x)
+ else
+ fun_l12_n126(x)
+ end
+end
+
+def fun_l11_n230(x)
+ if (x < 1)
+ fun_l12_n311(x)
+ else
+ fun_l12_n184(x)
+ end
+end
+
+def fun_l11_n231(x)
+ if (x < 1)
+ fun_l12_n604(x)
+ else
+ fun_l12_n171(x)
+ end
+end
+
+def fun_l11_n232(x)
+ if (x < 1)
+ fun_l12_n287(x)
+ else
+ fun_l12_n899(x)
+ end
+end
+
+def fun_l11_n233(x)
+ if (x < 1)
+ fun_l12_n834(x)
+ else
+ fun_l12_n435(x)
+ end
+end
+
+def fun_l11_n234(x)
+ if (x < 1)
+ fun_l12_n187(x)
+ else
+ fun_l12_n584(x)
+ end
+end
+
+def fun_l11_n235(x)
+ if (x < 1)
+ fun_l12_n711(x)
+ else
+ fun_l12_n542(x)
+ end
+end
+
+def fun_l11_n236(x)
+ if (x < 1)
+ fun_l12_n797(x)
+ else
+ fun_l12_n702(x)
+ end
+end
+
+def fun_l11_n237(x)
+ if (x < 1)
+ fun_l12_n645(x)
+ else
+ fun_l12_n691(x)
+ end
+end
+
+def fun_l11_n238(x)
+ if (x < 1)
+ fun_l12_n920(x)
+ else
+ fun_l12_n97(x)
+ end
+end
+
+def fun_l11_n239(x)
+ if (x < 1)
+ fun_l12_n491(x)
+ else
+ fun_l12_n172(x)
+ end
+end
+
+def fun_l11_n240(x)
+ if (x < 1)
+ fun_l12_n882(x)
+ else
+ fun_l12_n596(x)
+ end
+end
+
+def fun_l11_n241(x)
+ if (x < 1)
+ fun_l12_n178(x)
+ else
+ fun_l12_n671(x)
+ end
+end
+
+def fun_l11_n242(x)
+ if (x < 1)
+ fun_l12_n483(x)
+ else
+ fun_l12_n143(x)
+ end
+end
+
+def fun_l11_n243(x)
+ if (x < 1)
+ fun_l12_n677(x)
+ else
+ fun_l12_n542(x)
+ end
+end
+
+def fun_l11_n244(x)
+ if (x < 1)
+ fun_l12_n676(x)
+ else
+ fun_l12_n873(x)
+ end
+end
+
+def fun_l11_n245(x)
+ if (x < 1)
+ fun_l12_n393(x)
+ else
+ fun_l12_n532(x)
+ end
+end
+
+def fun_l11_n246(x)
+ if (x < 1)
+ fun_l12_n704(x)
+ else
+ fun_l12_n885(x)
+ end
+end
+
+def fun_l11_n247(x)
+ if (x < 1)
+ fun_l12_n668(x)
+ else
+ fun_l12_n305(x)
+ end
+end
+
+def fun_l11_n248(x)
+ if (x < 1)
+ fun_l12_n925(x)
+ else
+ fun_l12_n342(x)
+ end
+end
+
+def fun_l11_n249(x)
+ if (x < 1)
+ fun_l12_n487(x)
+ else
+ fun_l12_n517(x)
+ end
+end
+
+def fun_l11_n250(x)
+ if (x < 1)
+ fun_l12_n889(x)
+ else
+ fun_l12_n91(x)
+ end
+end
+
+def fun_l11_n251(x)
+ if (x < 1)
+ fun_l12_n908(x)
+ else
+ fun_l12_n645(x)
+ end
+end
+
+def fun_l11_n252(x)
+ if (x < 1)
+ fun_l12_n747(x)
+ else
+ fun_l12_n736(x)
+ end
+end
+
+def fun_l11_n253(x)
+ if (x < 1)
+ fun_l12_n749(x)
+ else
+ fun_l12_n264(x)
+ end
+end
+
+def fun_l11_n254(x)
+ if (x < 1)
+ fun_l12_n353(x)
+ else
+ fun_l12_n120(x)
+ end
+end
+
+def fun_l11_n255(x)
+ if (x < 1)
+ fun_l12_n231(x)
+ else
+ fun_l12_n211(x)
+ end
+end
+
+def fun_l11_n256(x)
+ if (x < 1)
+ fun_l12_n66(x)
+ else
+ fun_l12_n998(x)
+ end
+end
+
+def fun_l11_n257(x)
+ if (x < 1)
+ fun_l12_n818(x)
+ else
+ fun_l12_n37(x)
+ end
+end
+
+def fun_l11_n258(x)
+ if (x < 1)
+ fun_l12_n96(x)
+ else
+ fun_l12_n489(x)
+ end
+end
+
+def fun_l11_n259(x)
+ if (x < 1)
+ fun_l12_n86(x)
+ else
+ fun_l12_n432(x)
+ end
+end
+
+def fun_l11_n260(x)
+ if (x < 1)
+ fun_l12_n774(x)
+ else
+ fun_l12_n203(x)
+ end
+end
+
+def fun_l11_n261(x)
+ if (x < 1)
+ fun_l12_n935(x)
+ else
+ fun_l12_n29(x)
+ end
+end
+
+def fun_l11_n262(x)
+ if (x < 1)
+ fun_l12_n599(x)
+ else
+ fun_l12_n204(x)
+ end
+end
+
+def fun_l11_n263(x)
+ if (x < 1)
+ fun_l12_n63(x)
+ else
+ fun_l12_n866(x)
+ end
+end
+
+def fun_l11_n264(x)
+ if (x < 1)
+ fun_l12_n892(x)
+ else
+ fun_l12_n847(x)
+ end
+end
+
+def fun_l11_n265(x)
+ if (x < 1)
+ fun_l12_n695(x)
+ else
+ fun_l12_n881(x)
+ end
+end
+
+def fun_l11_n266(x)
+ if (x < 1)
+ fun_l12_n176(x)
+ else
+ fun_l12_n39(x)
+ end
+end
+
+def fun_l11_n267(x)
+ if (x < 1)
+ fun_l12_n448(x)
+ else
+ fun_l12_n744(x)
+ end
+end
+
+def fun_l11_n268(x)
+ if (x < 1)
+ fun_l12_n587(x)
+ else
+ fun_l12_n462(x)
+ end
+end
+
+def fun_l11_n269(x)
+ if (x < 1)
+ fun_l12_n670(x)
+ else
+ fun_l12_n797(x)
+ end
+end
+
+def fun_l11_n270(x)
+ if (x < 1)
+ fun_l12_n856(x)
+ else
+ fun_l12_n903(x)
+ end
+end
+
+def fun_l11_n271(x)
+ if (x < 1)
+ fun_l12_n914(x)
+ else
+ fun_l12_n459(x)
+ end
+end
+
+def fun_l11_n272(x)
+ if (x < 1)
+ fun_l12_n932(x)
+ else
+ fun_l12_n10(x)
+ end
+end
+
+def fun_l11_n273(x)
+ if (x < 1)
+ fun_l12_n554(x)
+ else
+ fun_l12_n528(x)
+ end
+end
+
+def fun_l11_n274(x)
+ if (x < 1)
+ fun_l12_n698(x)
+ else
+ fun_l12_n899(x)
+ end
+end
+
+def fun_l11_n275(x)
+ if (x < 1)
+ fun_l12_n907(x)
+ else
+ fun_l12_n945(x)
+ end
+end
+
+def fun_l11_n276(x)
+ if (x < 1)
+ fun_l12_n421(x)
+ else
+ fun_l12_n575(x)
+ end
+end
+
+def fun_l11_n277(x)
+ if (x < 1)
+ fun_l12_n757(x)
+ else
+ fun_l12_n808(x)
+ end
+end
+
+def fun_l11_n278(x)
+ if (x < 1)
+ fun_l12_n527(x)
+ else
+ fun_l12_n438(x)
+ end
+end
+
+def fun_l11_n279(x)
+ if (x < 1)
+ fun_l12_n263(x)
+ else
+ fun_l12_n842(x)
+ end
+end
+
+def fun_l11_n280(x)
+ if (x < 1)
+ fun_l12_n603(x)
+ else
+ fun_l12_n899(x)
+ end
+end
+
+def fun_l11_n281(x)
+ if (x < 1)
+ fun_l12_n486(x)
+ else
+ fun_l12_n380(x)
+ end
+end
+
+def fun_l11_n282(x)
+ if (x < 1)
+ fun_l12_n699(x)
+ else
+ fun_l12_n199(x)
+ end
+end
+
+def fun_l11_n283(x)
+ if (x < 1)
+ fun_l12_n422(x)
+ else
+ fun_l12_n258(x)
+ end
+end
+
+def fun_l11_n284(x)
+ if (x < 1)
+ fun_l12_n255(x)
+ else
+ fun_l12_n752(x)
+ end
+end
+
+def fun_l11_n285(x)
+ if (x < 1)
+ fun_l12_n506(x)
+ else
+ fun_l12_n801(x)
+ end
+end
+
+def fun_l11_n286(x)
+ if (x < 1)
+ fun_l12_n535(x)
+ else
+ fun_l12_n892(x)
+ end
+end
+
+def fun_l11_n287(x)
+ if (x < 1)
+ fun_l12_n547(x)
+ else
+ fun_l12_n74(x)
+ end
+end
+
+def fun_l11_n288(x)
+ if (x < 1)
+ fun_l12_n923(x)
+ else
+ fun_l12_n135(x)
+ end
+end
+
+def fun_l11_n289(x)
+ if (x < 1)
+ fun_l12_n78(x)
+ else
+ fun_l12_n704(x)
+ end
+end
+
+def fun_l11_n290(x)
+ if (x < 1)
+ fun_l12_n771(x)
+ else
+ fun_l12_n915(x)
+ end
+end
+
+def fun_l11_n291(x)
+ if (x < 1)
+ fun_l12_n184(x)
+ else
+ fun_l12_n188(x)
+ end
+end
+
+def fun_l11_n292(x)
+ if (x < 1)
+ fun_l12_n736(x)
+ else
+ fun_l12_n190(x)
+ end
+end
+
+def fun_l11_n293(x)
+ if (x < 1)
+ fun_l12_n301(x)
+ else
+ fun_l12_n745(x)
+ end
+end
+
+def fun_l11_n294(x)
+ if (x < 1)
+ fun_l12_n525(x)
+ else
+ fun_l12_n603(x)
+ end
+end
+
+def fun_l11_n295(x)
+ if (x < 1)
+ fun_l12_n339(x)
+ else
+ fun_l12_n996(x)
+ end
+end
+
+def fun_l11_n296(x)
+ if (x < 1)
+ fun_l12_n491(x)
+ else
+ fun_l12_n601(x)
+ end
+end
+
+def fun_l11_n297(x)
+ if (x < 1)
+ fun_l12_n449(x)
+ else
+ fun_l12_n361(x)
+ end
+end
+
+def fun_l11_n298(x)
+ if (x < 1)
+ fun_l12_n617(x)
+ else
+ fun_l12_n346(x)
+ end
+end
+
+def fun_l11_n299(x)
+ if (x < 1)
+ fun_l12_n578(x)
+ else
+ fun_l12_n147(x)
+ end
+end
+
+def fun_l11_n300(x)
+ if (x < 1)
+ fun_l12_n73(x)
+ else
+ fun_l12_n360(x)
+ end
+end
+
+def fun_l11_n301(x)
+ if (x < 1)
+ fun_l12_n398(x)
+ else
+ fun_l12_n749(x)
+ end
+end
+
+def fun_l11_n302(x)
+ if (x < 1)
+ fun_l12_n871(x)
+ else
+ fun_l12_n745(x)
+ end
+end
+
+def fun_l11_n303(x)
+ if (x < 1)
+ fun_l12_n669(x)
+ else
+ fun_l12_n196(x)
+ end
+end
+
+def fun_l11_n304(x)
+ if (x < 1)
+ fun_l12_n202(x)
+ else
+ fun_l12_n173(x)
+ end
+end
+
+def fun_l11_n305(x)
+ if (x < 1)
+ fun_l12_n975(x)
+ else
+ fun_l12_n859(x)
+ end
+end
+
+def fun_l11_n306(x)
+ if (x < 1)
+ fun_l12_n776(x)
+ else
+ fun_l12_n433(x)
+ end
+end
+
+def fun_l11_n307(x)
+ if (x < 1)
+ fun_l12_n760(x)
+ else
+ fun_l12_n4(x)
+ end
+end
+
+def fun_l11_n308(x)
+ if (x < 1)
+ fun_l12_n834(x)
+ else
+ fun_l12_n276(x)
+ end
+end
+
+def fun_l11_n309(x)
+ if (x < 1)
+ fun_l12_n162(x)
+ else
+ fun_l12_n741(x)
+ end
+end
+
+def fun_l11_n310(x)
+ if (x < 1)
+ fun_l12_n231(x)
+ else
+ fun_l12_n646(x)
+ end
+end
+
+def fun_l11_n311(x)
+ if (x < 1)
+ fun_l12_n90(x)
+ else
+ fun_l12_n46(x)
+ end
+end
+
+def fun_l11_n312(x)
+ if (x < 1)
+ fun_l12_n101(x)
+ else
+ fun_l12_n75(x)
+ end
+end
+
+def fun_l11_n313(x)
+ if (x < 1)
+ fun_l12_n415(x)
+ else
+ fun_l12_n535(x)
+ end
+end
+
+def fun_l11_n314(x)
+ if (x < 1)
+ fun_l12_n550(x)
+ else
+ fun_l12_n305(x)
+ end
+end
+
+def fun_l11_n315(x)
+ if (x < 1)
+ fun_l12_n971(x)
+ else
+ fun_l12_n700(x)
+ end
+end
+
+def fun_l11_n316(x)
+ if (x < 1)
+ fun_l12_n942(x)
+ else
+ fun_l12_n793(x)
+ end
+end
+
+def fun_l11_n317(x)
+ if (x < 1)
+ fun_l12_n771(x)
+ else
+ fun_l12_n383(x)
+ end
+end
+
+def fun_l11_n318(x)
+ if (x < 1)
+ fun_l12_n846(x)
+ else
+ fun_l12_n504(x)
+ end
+end
+
+def fun_l11_n319(x)
+ if (x < 1)
+ fun_l12_n28(x)
+ else
+ fun_l12_n174(x)
+ end
+end
+
+def fun_l11_n320(x)
+ if (x < 1)
+ fun_l12_n437(x)
+ else
+ fun_l12_n355(x)
+ end
+end
+
+def fun_l11_n321(x)
+ if (x < 1)
+ fun_l12_n954(x)
+ else
+ fun_l12_n78(x)
+ end
+end
+
+def fun_l11_n322(x)
+ if (x < 1)
+ fun_l12_n256(x)
+ else
+ fun_l12_n729(x)
+ end
+end
+
+def fun_l11_n323(x)
+ if (x < 1)
+ fun_l12_n41(x)
+ else
+ fun_l12_n88(x)
+ end
+end
+
+def fun_l11_n324(x)
+ if (x < 1)
+ fun_l12_n256(x)
+ else
+ fun_l12_n162(x)
+ end
+end
+
+def fun_l11_n325(x)
+ if (x < 1)
+ fun_l12_n143(x)
+ else
+ fun_l12_n506(x)
+ end
+end
+
+def fun_l11_n326(x)
+ if (x < 1)
+ fun_l12_n686(x)
+ else
+ fun_l12_n968(x)
+ end
+end
+
+def fun_l11_n327(x)
+ if (x < 1)
+ fun_l12_n235(x)
+ else
+ fun_l12_n246(x)
+ end
+end
+
+def fun_l11_n328(x)
+ if (x < 1)
+ fun_l12_n85(x)
+ else
+ fun_l12_n125(x)
+ end
+end
+
+def fun_l11_n329(x)
+ if (x < 1)
+ fun_l12_n877(x)
+ else
+ fun_l12_n193(x)
+ end
+end
+
+def fun_l11_n330(x)
+ if (x < 1)
+ fun_l12_n678(x)
+ else
+ fun_l12_n147(x)
+ end
+end
+
+def fun_l11_n331(x)
+ if (x < 1)
+ fun_l12_n402(x)
+ else
+ fun_l12_n747(x)
+ end
+end
+
+def fun_l11_n332(x)
+ if (x < 1)
+ fun_l12_n390(x)
+ else
+ fun_l12_n852(x)
+ end
+end
+
+def fun_l11_n333(x)
+ if (x < 1)
+ fun_l12_n299(x)
+ else
+ fun_l12_n122(x)
+ end
+end
+
+def fun_l11_n334(x)
+ if (x < 1)
+ fun_l12_n398(x)
+ else
+ fun_l12_n886(x)
+ end
+end
+
+def fun_l11_n335(x)
+ if (x < 1)
+ fun_l12_n128(x)
+ else
+ fun_l12_n729(x)
+ end
+end
+
+def fun_l11_n336(x)
+ if (x < 1)
+ fun_l12_n611(x)
+ else
+ fun_l12_n75(x)
+ end
+end
+
+def fun_l11_n337(x)
+ if (x < 1)
+ fun_l12_n327(x)
+ else
+ fun_l12_n442(x)
+ end
+end
+
+def fun_l11_n338(x)
+ if (x < 1)
+ fun_l12_n353(x)
+ else
+ fun_l12_n259(x)
+ end
+end
+
+def fun_l11_n339(x)
+ if (x < 1)
+ fun_l12_n173(x)
+ else
+ fun_l12_n846(x)
+ end
+end
+
+def fun_l11_n340(x)
+ if (x < 1)
+ fun_l12_n579(x)
+ else
+ fun_l12_n869(x)
+ end
+end
+
+def fun_l11_n341(x)
+ if (x < 1)
+ fun_l12_n336(x)
+ else
+ fun_l12_n364(x)
+ end
+end
+
+def fun_l11_n342(x)
+ if (x < 1)
+ fun_l12_n355(x)
+ else
+ fun_l12_n317(x)
+ end
+end
+
+def fun_l11_n343(x)
+ if (x < 1)
+ fun_l12_n560(x)
+ else
+ fun_l12_n202(x)
+ end
+end
+
+def fun_l11_n344(x)
+ if (x < 1)
+ fun_l12_n232(x)
+ else
+ fun_l12_n447(x)
+ end
+end
+
+def fun_l11_n345(x)
+ if (x < 1)
+ fun_l12_n712(x)
+ else
+ fun_l12_n205(x)
+ end
+end
+
+def fun_l11_n346(x)
+ if (x < 1)
+ fun_l12_n102(x)
+ else
+ fun_l12_n785(x)
+ end
+end
+
+def fun_l11_n347(x)
+ if (x < 1)
+ fun_l12_n545(x)
+ else
+ fun_l12_n186(x)
+ end
+end
+
+def fun_l11_n348(x)
+ if (x < 1)
+ fun_l12_n530(x)
+ else
+ fun_l12_n705(x)
+ end
+end
+
+def fun_l11_n349(x)
+ if (x < 1)
+ fun_l12_n428(x)
+ else
+ fun_l12_n295(x)
+ end
+end
+
+def fun_l11_n350(x)
+ if (x < 1)
+ fun_l12_n855(x)
+ else
+ fun_l12_n232(x)
+ end
+end
+
+def fun_l11_n351(x)
+ if (x < 1)
+ fun_l12_n759(x)
+ else
+ fun_l12_n13(x)
+ end
+end
+
+def fun_l11_n352(x)
+ if (x < 1)
+ fun_l12_n366(x)
+ else
+ fun_l12_n700(x)
+ end
+end
+
+def fun_l11_n353(x)
+ if (x < 1)
+ fun_l12_n814(x)
+ else
+ fun_l12_n101(x)
+ end
+end
+
+def fun_l11_n354(x)
+ if (x < 1)
+ fun_l12_n788(x)
+ else
+ fun_l12_n509(x)
+ end
+end
+
+def fun_l11_n355(x)
+ if (x < 1)
+ fun_l12_n619(x)
+ else
+ fun_l12_n531(x)
+ end
+end
+
+def fun_l11_n356(x)
+ if (x < 1)
+ fun_l12_n142(x)
+ else
+ fun_l12_n586(x)
+ end
+end
+
+def fun_l11_n357(x)
+ if (x < 1)
+ fun_l12_n772(x)
+ else
+ fun_l12_n714(x)
+ end
+end
+
+def fun_l11_n358(x)
+ if (x < 1)
+ fun_l12_n506(x)
+ else
+ fun_l12_n405(x)
+ end
+end
+
+def fun_l11_n359(x)
+ if (x < 1)
+ fun_l12_n991(x)
+ else
+ fun_l12_n141(x)
+ end
+end
+
+def fun_l11_n360(x)
+ if (x < 1)
+ fun_l12_n156(x)
+ else
+ fun_l12_n67(x)
+ end
+end
+
+def fun_l11_n361(x)
+ if (x < 1)
+ fun_l12_n525(x)
+ else
+ fun_l12_n293(x)
+ end
+end
+
+def fun_l11_n362(x)
+ if (x < 1)
+ fun_l12_n396(x)
+ else
+ fun_l12_n931(x)
+ end
+end
+
+def fun_l11_n363(x)
+ if (x < 1)
+ fun_l12_n153(x)
+ else
+ fun_l12_n831(x)
+ end
+end
+
+def fun_l11_n364(x)
+ if (x < 1)
+ fun_l12_n240(x)
+ else
+ fun_l12_n450(x)
+ end
+end
+
+def fun_l11_n365(x)
+ if (x < 1)
+ fun_l12_n514(x)
+ else
+ fun_l12_n312(x)
+ end
+end
+
+def fun_l11_n366(x)
+ if (x < 1)
+ fun_l12_n456(x)
+ else
+ fun_l12_n221(x)
+ end
+end
+
+def fun_l11_n367(x)
+ if (x < 1)
+ fun_l12_n920(x)
+ else
+ fun_l12_n699(x)
+ end
+end
+
+def fun_l11_n368(x)
+ if (x < 1)
+ fun_l12_n738(x)
+ else
+ fun_l12_n793(x)
+ end
+end
+
+def fun_l11_n369(x)
+ if (x < 1)
+ fun_l12_n13(x)
+ else
+ fun_l12_n812(x)
+ end
+end
+
+def fun_l11_n370(x)
+ if (x < 1)
+ fun_l12_n392(x)
+ else
+ fun_l12_n342(x)
+ end
+end
+
+def fun_l11_n371(x)
+ if (x < 1)
+ fun_l12_n470(x)
+ else
+ fun_l12_n623(x)
+ end
+end
+
+def fun_l11_n372(x)
+ if (x < 1)
+ fun_l12_n26(x)
+ else
+ fun_l12_n138(x)
+ end
+end
+
+def fun_l11_n373(x)
+ if (x < 1)
+ fun_l12_n70(x)
+ else
+ fun_l12_n682(x)
+ end
+end
+
+def fun_l11_n374(x)
+ if (x < 1)
+ fun_l12_n413(x)
+ else
+ fun_l12_n900(x)
+ end
+end
+
+def fun_l11_n375(x)
+ if (x < 1)
+ fun_l12_n328(x)
+ else
+ fun_l12_n848(x)
+ end
+end
+
+def fun_l11_n376(x)
+ if (x < 1)
+ fun_l12_n604(x)
+ else
+ fun_l12_n823(x)
+ end
+end
+
+def fun_l11_n377(x)
+ if (x < 1)
+ fun_l12_n469(x)
+ else
+ fun_l12_n868(x)
+ end
+end
+
+def fun_l11_n378(x)
+ if (x < 1)
+ fun_l12_n241(x)
+ else
+ fun_l12_n571(x)
+ end
+end
+
+def fun_l11_n379(x)
+ if (x < 1)
+ fun_l12_n669(x)
+ else
+ fun_l12_n75(x)
+ end
+end
+
+def fun_l11_n380(x)
+ if (x < 1)
+ fun_l12_n587(x)
+ else
+ fun_l12_n454(x)
+ end
+end
+
+def fun_l11_n381(x)
+ if (x < 1)
+ fun_l12_n210(x)
+ else
+ fun_l12_n512(x)
+ end
+end
+
+def fun_l11_n382(x)
+ if (x < 1)
+ fun_l12_n73(x)
+ else
+ fun_l12_n981(x)
+ end
+end
+
+def fun_l11_n383(x)
+ if (x < 1)
+ fun_l12_n59(x)
+ else
+ fun_l12_n274(x)
+ end
+end
+
+def fun_l11_n384(x)
+ if (x < 1)
+ fun_l12_n242(x)
+ else
+ fun_l12_n631(x)
+ end
+end
+
+def fun_l11_n385(x)
+ if (x < 1)
+ fun_l12_n933(x)
+ else
+ fun_l12_n678(x)
+ end
+end
+
+def fun_l11_n386(x)
+ if (x < 1)
+ fun_l12_n695(x)
+ else
+ fun_l12_n766(x)
+ end
+end
+
+def fun_l11_n387(x)
+ if (x < 1)
+ fun_l12_n49(x)
+ else
+ fun_l12_n459(x)
+ end
+end
+
+def fun_l11_n388(x)
+ if (x < 1)
+ fun_l12_n751(x)
+ else
+ fun_l12_n594(x)
+ end
+end
+
+def fun_l11_n389(x)
+ if (x < 1)
+ fun_l12_n149(x)
+ else
+ fun_l12_n290(x)
+ end
+end
+
+def fun_l11_n390(x)
+ if (x < 1)
+ fun_l12_n307(x)
+ else
+ fun_l12_n723(x)
+ end
+end
+
+def fun_l11_n391(x)
+ if (x < 1)
+ fun_l12_n606(x)
+ else
+ fun_l12_n97(x)
+ end
+end
+
+def fun_l11_n392(x)
+ if (x < 1)
+ fun_l12_n31(x)
+ else
+ fun_l12_n610(x)
+ end
+end
+
+def fun_l11_n393(x)
+ if (x < 1)
+ fun_l12_n798(x)
+ else
+ fun_l12_n940(x)
+ end
+end
+
+def fun_l11_n394(x)
+ if (x < 1)
+ fun_l12_n131(x)
+ else
+ fun_l12_n79(x)
+ end
+end
+
+def fun_l11_n395(x)
+ if (x < 1)
+ fun_l12_n230(x)
+ else
+ fun_l12_n72(x)
+ end
+end
+
+def fun_l11_n396(x)
+ if (x < 1)
+ fun_l12_n506(x)
+ else
+ fun_l12_n433(x)
+ end
+end
+
+def fun_l11_n397(x)
+ if (x < 1)
+ fun_l12_n410(x)
+ else
+ fun_l12_n648(x)
+ end
+end
+
+def fun_l11_n398(x)
+ if (x < 1)
+ fun_l12_n946(x)
+ else
+ fun_l12_n630(x)
+ end
+end
+
+def fun_l11_n399(x)
+ if (x < 1)
+ fun_l12_n394(x)
+ else
+ fun_l12_n220(x)
+ end
+end
+
+def fun_l11_n400(x)
+ if (x < 1)
+ fun_l12_n761(x)
+ else
+ fun_l12_n407(x)
+ end
+end
+
+def fun_l11_n401(x)
+ if (x < 1)
+ fun_l12_n386(x)
+ else
+ fun_l12_n411(x)
+ end
+end
+
+def fun_l11_n402(x)
+ if (x < 1)
+ fun_l12_n290(x)
+ else
+ fun_l12_n334(x)
+ end
+end
+
+def fun_l11_n403(x)
+ if (x < 1)
+ fun_l12_n600(x)
+ else
+ fun_l12_n282(x)
+ end
+end
+
+def fun_l11_n404(x)
+ if (x < 1)
+ fun_l12_n334(x)
+ else
+ fun_l12_n214(x)
+ end
+end
+
+def fun_l11_n405(x)
+ if (x < 1)
+ fun_l12_n103(x)
+ else
+ fun_l12_n188(x)
+ end
+end
+
+def fun_l11_n406(x)
+ if (x < 1)
+ fun_l12_n755(x)
+ else
+ fun_l12_n773(x)
+ end
+end
+
+def fun_l11_n407(x)
+ if (x < 1)
+ fun_l12_n269(x)
+ else
+ fun_l12_n579(x)
+ end
+end
+
+def fun_l11_n408(x)
+ if (x < 1)
+ fun_l12_n54(x)
+ else
+ fun_l12_n961(x)
+ end
+end
+
+def fun_l11_n409(x)
+ if (x < 1)
+ fun_l12_n699(x)
+ else
+ fun_l12_n117(x)
+ end
+end
+
+def fun_l11_n410(x)
+ if (x < 1)
+ fun_l12_n802(x)
+ else
+ fun_l12_n65(x)
+ end
+end
+
+def fun_l11_n411(x)
+ if (x < 1)
+ fun_l12_n776(x)
+ else
+ fun_l12_n676(x)
+ end
+end
+
+def fun_l11_n412(x)
+ if (x < 1)
+ fun_l12_n520(x)
+ else
+ fun_l12_n447(x)
+ end
+end
+
+def fun_l11_n413(x)
+ if (x < 1)
+ fun_l12_n856(x)
+ else
+ fun_l12_n285(x)
+ end
+end
+
+def fun_l11_n414(x)
+ if (x < 1)
+ fun_l12_n797(x)
+ else
+ fun_l12_n590(x)
+ end
+end
+
+def fun_l11_n415(x)
+ if (x < 1)
+ fun_l12_n128(x)
+ else
+ fun_l12_n677(x)
+ end
+end
+
+def fun_l11_n416(x)
+ if (x < 1)
+ fun_l12_n422(x)
+ else
+ fun_l12_n632(x)
+ end
+end
+
+def fun_l11_n417(x)
+ if (x < 1)
+ fun_l12_n159(x)
+ else
+ fun_l12_n722(x)
+ end
+end
+
+def fun_l11_n418(x)
+ if (x < 1)
+ fun_l12_n989(x)
+ else
+ fun_l12_n670(x)
+ end
+end
+
+def fun_l11_n419(x)
+ if (x < 1)
+ fun_l12_n952(x)
+ else
+ fun_l12_n65(x)
+ end
+end
+
+def fun_l11_n420(x)
+ if (x < 1)
+ fun_l12_n796(x)
+ else
+ fun_l12_n493(x)
+ end
+end
+
+def fun_l11_n421(x)
+ if (x < 1)
+ fun_l12_n897(x)
+ else
+ fun_l12_n729(x)
+ end
+end
+
+def fun_l11_n422(x)
+ if (x < 1)
+ fun_l12_n557(x)
+ else
+ fun_l12_n545(x)
+ end
+end
+
+def fun_l11_n423(x)
+ if (x < 1)
+ fun_l12_n716(x)
+ else
+ fun_l12_n746(x)
+ end
+end
+
+def fun_l11_n424(x)
+ if (x < 1)
+ fun_l12_n335(x)
+ else
+ fun_l12_n968(x)
+ end
+end
+
+def fun_l11_n425(x)
+ if (x < 1)
+ fun_l12_n891(x)
+ else
+ fun_l12_n115(x)
+ end
+end
+
+def fun_l11_n426(x)
+ if (x < 1)
+ fun_l12_n757(x)
+ else
+ fun_l12_n750(x)
+ end
+end
+
+def fun_l11_n427(x)
+ if (x < 1)
+ fun_l12_n391(x)
+ else
+ fun_l12_n729(x)
+ end
+end
+
+def fun_l11_n428(x)
+ if (x < 1)
+ fun_l12_n249(x)
+ else
+ fun_l12_n347(x)
+ end
+end
+
+def fun_l11_n429(x)
+ if (x < 1)
+ fun_l12_n234(x)
+ else
+ fun_l12_n154(x)
+ end
+end
+
+def fun_l11_n430(x)
+ if (x < 1)
+ fun_l12_n890(x)
+ else
+ fun_l12_n40(x)
+ end
+end
+
+def fun_l11_n431(x)
+ if (x < 1)
+ fun_l12_n804(x)
+ else
+ fun_l12_n90(x)
+ end
+end
+
+def fun_l11_n432(x)
+ if (x < 1)
+ fun_l12_n936(x)
+ else
+ fun_l12_n127(x)
+ end
+end
+
+def fun_l11_n433(x)
+ if (x < 1)
+ fun_l12_n551(x)
+ else
+ fun_l12_n404(x)
+ end
+end
+
+def fun_l11_n434(x)
+ if (x < 1)
+ fun_l12_n246(x)
+ else
+ fun_l12_n759(x)
+ end
+end
+
+def fun_l11_n435(x)
+ if (x < 1)
+ fun_l12_n708(x)
+ else
+ fun_l12_n735(x)
+ end
+end
+
+def fun_l11_n436(x)
+ if (x < 1)
+ fun_l12_n535(x)
+ else
+ fun_l12_n785(x)
+ end
+end
+
+def fun_l11_n437(x)
+ if (x < 1)
+ fun_l12_n322(x)
+ else
+ fun_l12_n629(x)
+ end
+end
+
+def fun_l11_n438(x)
+ if (x < 1)
+ fun_l12_n986(x)
+ else
+ fun_l12_n899(x)
+ end
+end
+
+def fun_l11_n439(x)
+ if (x < 1)
+ fun_l12_n147(x)
+ else
+ fun_l12_n582(x)
+ end
+end
+
+def fun_l11_n440(x)
+ if (x < 1)
+ fun_l12_n375(x)
+ else
+ fun_l12_n667(x)
+ end
+end
+
+def fun_l11_n441(x)
+ if (x < 1)
+ fun_l12_n467(x)
+ else
+ fun_l12_n994(x)
+ end
+end
+
+def fun_l11_n442(x)
+ if (x < 1)
+ fun_l12_n176(x)
+ else
+ fun_l12_n558(x)
+ end
+end
+
+def fun_l11_n443(x)
+ if (x < 1)
+ fun_l12_n452(x)
+ else
+ fun_l12_n37(x)
+ end
+end
+
+def fun_l11_n444(x)
+ if (x < 1)
+ fun_l12_n701(x)
+ else
+ fun_l12_n382(x)
+ end
+end
+
+def fun_l11_n445(x)
+ if (x < 1)
+ fun_l12_n881(x)
+ else
+ fun_l12_n896(x)
+ end
+end
+
+def fun_l11_n446(x)
+ if (x < 1)
+ fun_l12_n901(x)
+ else
+ fun_l12_n822(x)
+ end
+end
+
+def fun_l11_n447(x)
+ if (x < 1)
+ fun_l12_n6(x)
+ else
+ fun_l12_n648(x)
+ end
+end
+
+def fun_l11_n448(x)
+ if (x < 1)
+ fun_l12_n359(x)
+ else
+ fun_l12_n682(x)
+ end
+end
+
+def fun_l11_n449(x)
+ if (x < 1)
+ fun_l12_n675(x)
+ else
+ fun_l12_n379(x)
+ end
+end
+
+def fun_l11_n450(x)
+ if (x < 1)
+ fun_l12_n254(x)
+ else
+ fun_l12_n475(x)
+ end
+end
+
+def fun_l11_n451(x)
+ if (x < 1)
+ fun_l12_n951(x)
+ else
+ fun_l12_n947(x)
+ end
+end
+
+def fun_l11_n452(x)
+ if (x < 1)
+ fun_l12_n909(x)
+ else
+ fun_l12_n703(x)
+ end
+end
+
+def fun_l11_n453(x)
+ if (x < 1)
+ fun_l12_n555(x)
+ else
+ fun_l12_n862(x)
+ end
+end
+
+def fun_l11_n454(x)
+ if (x < 1)
+ fun_l12_n379(x)
+ else
+ fun_l12_n852(x)
+ end
+end
+
+def fun_l11_n455(x)
+ if (x < 1)
+ fun_l12_n85(x)
+ else
+ fun_l12_n219(x)
+ end
+end
+
+def fun_l11_n456(x)
+ if (x < 1)
+ fun_l12_n84(x)
+ else
+ fun_l12_n678(x)
+ end
+end
+
+def fun_l11_n457(x)
+ if (x < 1)
+ fun_l12_n663(x)
+ else
+ fun_l12_n637(x)
+ end
+end
+
+def fun_l11_n458(x)
+ if (x < 1)
+ fun_l12_n627(x)
+ else
+ fun_l12_n764(x)
+ end
+end
+
+def fun_l11_n459(x)
+ if (x < 1)
+ fun_l12_n3(x)
+ else
+ fun_l12_n419(x)
+ end
+end
+
+def fun_l11_n460(x)
+ if (x < 1)
+ fun_l12_n69(x)
+ else
+ fun_l12_n802(x)
+ end
+end
+
+def fun_l11_n461(x)
+ if (x < 1)
+ fun_l12_n708(x)
+ else
+ fun_l12_n304(x)
+ end
+end
+
+def fun_l11_n462(x)
+ if (x < 1)
+ fun_l12_n323(x)
+ else
+ fun_l12_n92(x)
+ end
+end
+
+def fun_l11_n463(x)
+ if (x < 1)
+ fun_l12_n987(x)
+ else
+ fun_l12_n434(x)
+ end
+end
+
+def fun_l11_n464(x)
+ if (x < 1)
+ fun_l12_n532(x)
+ else
+ fun_l12_n82(x)
+ end
+end
+
+def fun_l11_n465(x)
+ if (x < 1)
+ fun_l12_n664(x)
+ else
+ fun_l12_n982(x)
+ end
+end
+
+def fun_l11_n466(x)
+ if (x < 1)
+ fun_l12_n488(x)
+ else
+ fun_l12_n799(x)
+ end
+end
+
+def fun_l11_n467(x)
+ if (x < 1)
+ fun_l12_n882(x)
+ else
+ fun_l12_n948(x)
+ end
+end
+
+def fun_l11_n468(x)
+ if (x < 1)
+ fun_l12_n585(x)
+ else
+ fun_l12_n528(x)
+ end
+end
+
+def fun_l11_n469(x)
+ if (x < 1)
+ fun_l12_n318(x)
+ else
+ fun_l12_n233(x)
+ end
+end
+
+def fun_l11_n470(x)
+ if (x < 1)
+ fun_l12_n537(x)
+ else
+ fun_l12_n803(x)
+ end
+end
+
+def fun_l11_n471(x)
+ if (x < 1)
+ fun_l12_n391(x)
+ else
+ fun_l12_n298(x)
+ end
+end
+
+def fun_l11_n472(x)
+ if (x < 1)
+ fun_l12_n266(x)
+ else
+ fun_l12_n345(x)
+ end
+end
+
+def fun_l11_n473(x)
+ if (x < 1)
+ fun_l12_n355(x)
+ else
+ fun_l12_n713(x)
+ end
+end
+
+def fun_l11_n474(x)
+ if (x < 1)
+ fun_l12_n352(x)
+ else
+ fun_l12_n12(x)
+ end
+end
+
+def fun_l11_n475(x)
+ if (x < 1)
+ fun_l12_n23(x)
+ else
+ fun_l12_n715(x)
+ end
+end
+
+def fun_l11_n476(x)
+ if (x < 1)
+ fun_l12_n342(x)
+ else
+ fun_l12_n323(x)
+ end
+end
+
+def fun_l11_n477(x)
+ if (x < 1)
+ fun_l12_n563(x)
+ else
+ fun_l12_n905(x)
+ end
+end
+
+def fun_l11_n478(x)
+ if (x < 1)
+ fun_l12_n313(x)
+ else
+ fun_l12_n489(x)
+ end
+end
+
+def fun_l11_n479(x)
+ if (x < 1)
+ fun_l12_n75(x)
+ else
+ fun_l12_n291(x)
+ end
+end
+
+def fun_l11_n480(x)
+ if (x < 1)
+ fun_l12_n693(x)
+ else
+ fun_l12_n991(x)
+ end
+end
+
+def fun_l11_n481(x)
+ if (x < 1)
+ fun_l12_n246(x)
+ else
+ fun_l12_n664(x)
+ end
+end
+
+def fun_l11_n482(x)
+ if (x < 1)
+ fun_l12_n524(x)
+ else
+ fun_l12_n1(x)
+ end
+end
+
+def fun_l11_n483(x)
+ if (x < 1)
+ fun_l12_n712(x)
+ else
+ fun_l12_n289(x)
+ end
+end
+
+def fun_l11_n484(x)
+ if (x < 1)
+ fun_l12_n435(x)
+ else
+ fun_l12_n163(x)
+ end
+end
+
+def fun_l11_n485(x)
+ if (x < 1)
+ fun_l12_n338(x)
+ else
+ fun_l12_n883(x)
+ end
+end
+
+def fun_l11_n486(x)
+ if (x < 1)
+ fun_l12_n958(x)
+ else
+ fun_l12_n143(x)
+ end
+end
+
+def fun_l11_n487(x)
+ if (x < 1)
+ fun_l12_n22(x)
+ else
+ fun_l12_n674(x)
+ end
+end
+
+def fun_l11_n488(x)
+ if (x < 1)
+ fun_l12_n905(x)
+ else
+ fun_l12_n955(x)
+ end
+end
+
+def fun_l11_n489(x)
+ if (x < 1)
+ fun_l12_n590(x)
+ else
+ fun_l12_n623(x)
+ end
+end
+
+def fun_l11_n490(x)
+ if (x < 1)
+ fun_l12_n434(x)
+ else
+ fun_l12_n793(x)
+ end
+end
+
+def fun_l11_n491(x)
+ if (x < 1)
+ fun_l12_n274(x)
+ else
+ fun_l12_n879(x)
+ end
+end
+
+def fun_l11_n492(x)
+ if (x < 1)
+ fun_l12_n639(x)
+ else
+ fun_l12_n915(x)
+ end
+end
+
+def fun_l11_n493(x)
+ if (x < 1)
+ fun_l12_n547(x)
+ else
+ fun_l12_n87(x)
+ end
+end
+
+def fun_l11_n494(x)
+ if (x < 1)
+ fun_l12_n364(x)
+ else
+ fun_l12_n133(x)
+ end
+end
+
+def fun_l11_n495(x)
+ if (x < 1)
+ fun_l12_n568(x)
+ else
+ fun_l12_n449(x)
+ end
+end
+
+def fun_l11_n496(x)
+ if (x < 1)
+ fun_l12_n751(x)
+ else
+ fun_l12_n580(x)
+ end
+end
+
+def fun_l11_n497(x)
+ if (x < 1)
+ fun_l12_n864(x)
+ else
+ fun_l12_n505(x)
+ end
+end
+
+def fun_l11_n498(x)
+ if (x < 1)
+ fun_l12_n68(x)
+ else
+ fun_l12_n280(x)
+ end
+end
+
+def fun_l11_n499(x)
+ if (x < 1)
+ fun_l12_n821(x)
+ else
+ fun_l12_n816(x)
+ end
+end
+
+def fun_l11_n500(x)
+ if (x < 1)
+ fun_l12_n793(x)
+ else
+ fun_l12_n558(x)
+ end
+end
+
+def fun_l11_n501(x)
+ if (x < 1)
+ fun_l12_n460(x)
+ else
+ fun_l12_n358(x)
+ end
+end
+
+def fun_l11_n502(x)
+ if (x < 1)
+ fun_l12_n99(x)
+ else
+ fun_l12_n149(x)
+ end
+end
+
+def fun_l11_n503(x)
+ if (x < 1)
+ fun_l12_n599(x)
+ else
+ fun_l12_n257(x)
+ end
+end
+
+def fun_l11_n504(x)
+ if (x < 1)
+ fun_l12_n853(x)
+ else
+ fun_l12_n477(x)
+ end
+end
+
+def fun_l11_n505(x)
+ if (x < 1)
+ fun_l12_n845(x)
+ else
+ fun_l12_n776(x)
+ end
+end
+
+def fun_l11_n506(x)
+ if (x < 1)
+ fun_l12_n533(x)
+ else
+ fun_l12_n6(x)
+ end
+end
+
+def fun_l11_n507(x)
+ if (x < 1)
+ fun_l12_n700(x)
+ else
+ fun_l12_n47(x)
+ end
+end
+
+def fun_l11_n508(x)
+ if (x < 1)
+ fun_l12_n449(x)
+ else
+ fun_l12_n261(x)
+ end
+end
+
+def fun_l11_n509(x)
+ if (x < 1)
+ fun_l12_n773(x)
+ else
+ fun_l12_n583(x)
+ end
+end
+
+def fun_l11_n510(x)
+ if (x < 1)
+ fun_l12_n252(x)
+ else
+ fun_l12_n215(x)
+ end
+end
+
+def fun_l11_n511(x)
+ if (x < 1)
+ fun_l12_n280(x)
+ else
+ fun_l12_n589(x)
+ end
+end
+
+def fun_l11_n512(x)
+ if (x < 1)
+ fun_l12_n796(x)
+ else
+ fun_l12_n803(x)
+ end
+end
+
+def fun_l11_n513(x)
+ if (x < 1)
+ fun_l12_n450(x)
+ else
+ fun_l12_n606(x)
+ end
+end
+
+def fun_l11_n514(x)
+ if (x < 1)
+ fun_l12_n509(x)
+ else
+ fun_l12_n521(x)
+ end
+end
+
+def fun_l11_n515(x)
+ if (x < 1)
+ fun_l12_n658(x)
+ else
+ fun_l12_n912(x)
+ end
+end
+
+def fun_l11_n516(x)
+ if (x < 1)
+ fun_l12_n181(x)
+ else
+ fun_l12_n724(x)
+ end
+end
+
+def fun_l11_n517(x)
+ if (x < 1)
+ fun_l12_n167(x)
+ else
+ fun_l12_n996(x)
+ end
+end
+
+def fun_l11_n518(x)
+ if (x < 1)
+ fun_l12_n654(x)
+ else
+ fun_l12_n67(x)
+ end
+end
+
+def fun_l11_n519(x)
+ if (x < 1)
+ fun_l12_n192(x)
+ else
+ fun_l12_n110(x)
+ end
+end
+
+def fun_l11_n520(x)
+ if (x < 1)
+ fun_l12_n271(x)
+ else
+ fun_l12_n74(x)
+ end
+end
+
+def fun_l11_n521(x)
+ if (x < 1)
+ fun_l12_n324(x)
+ else
+ fun_l12_n224(x)
+ end
+end
+
+def fun_l11_n522(x)
+ if (x < 1)
+ fun_l12_n535(x)
+ else
+ fun_l12_n537(x)
+ end
+end
+
+def fun_l11_n523(x)
+ if (x < 1)
+ fun_l12_n103(x)
+ else
+ fun_l12_n942(x)
+ end
+end
+
+def fun_l11_n524(x)
+ if (x < 1)
+ fun_l12_n755(x)
+ else
+ fun_l12_n431(x)
+ end
+end
+
+def fun_l11_n525(x)
+ if (x < 1)
+ fun_l12_n243(x)
+ else
+ fun_l12_n131(x)
+ end
+end
+
+def fun_l11_n526(x)
+ if (x < 1)
+ fun_l12_n270(x)
+ else
+ fun_l12_n747(x)
+ end
+end
+
+def fun_l11_n527(x)
+ if (x < 1)
+ fun_l12_n566(x)
+ else
+ fun_l12_n284(x)
+ end
+end
+
+def fun_l11_n528(x)
+ if (x < 1)
+ fun_l12_n510(x)
+ else
+ fun_l12_n928(x)
+ end
+end
+
+def fun_l11_n529(x)
+ if (x < 1)
+ fun_l12_n354(x)
+ else
+ fun_l12_n1(x)
+ end
+end
+
+def fun_l11_n530(x)
+ if (x < 1)
+ fun_l12_n271(x)
+ else
+ fun_l12_n875(x)
+ end
+end
+
+def fun_l11_n531(x)
+ if (x < 1)
+ fun_l12_n871(x)
+ else
+ fun_l12_n441(x)
+ end
+end
+
+def fun_l11_n532(x)
+ if (x < 1)
+ fun_l12_n727(x)
+ else
+ fun_l12_n903(x)
+ end
+end
+
+def fun_l11_n533(x)
+ if (x < 1)
+ fun_l12_n843(x)
+ else
+ fun_l12_n202(x)
+ end
+end
+
+def fun_l11_n534(x)
+ if (x < 1)
+ fun_l12_n798(x)
+ else
+ fun_l12_n309(x)
+ end
+end
+
+def fun_l11_n535(x)
+ if (x < 1)
+ fun_l12_n397(x)
+ else
+ fun_l12_n377(x)
+ end
+end
+
+def fun_l11_n536(x)
+ if (x < 1)
+ fun_l12_n441(x)
+ else
+ fun_l12_n253(x)
+ end
+end
+
+def fun_l11_n537(x)
+ if (x < 1)
+ fun_l12_n861(x)
+ else
+ fun_l12_n84(x)
+ end
+end
+
+def fun_l11_n538(x)
+ if (x < 1)
+ fun_l12_n268(x)
+ else
+ fun_l12_n627(x)
+ end
+end
+
+def fun_l11_n539(x)
+ if (x < 1)
+ fun_l12_n923(x)
+ else
+ fun_l12_n650(x)
+ end
+end
+
+def fun_l11_n540(x)
+ if (x < 1)
+ fun_l12_n503(x)
+ else
+ fun_l12_n598(x)
+ end
+end
+
+def fun_l11_n541(x)
+ if (x < 1)
+ fun_l12_n355(x)
+ else
+ fun_l12_n201(x)
+ end
+end
+
+def fun_l11_n542(x)
+ if (x < 1)
+ fun_l12_n956(x)
+ else
+ fun_l12_n789(x)
+ end
+end
+
+def fun_l11_n543(x)
+ if (x < 1)
+ fun_l12_n438(x)
+ else
+ fun_l12_n47(x)
+ end
+end
+
+def fun_l11_n544(x)
+ if (x < 1)
+ fun_l12_n425(x)
+ else
+ fun_l12_n109(x)
+ end
+end
+
+def fun_l11_n545(x)
+ if (x < 1)
+ fun_l12_n540(x)
+ else
+ fun_l12_n360(x)
+ end
+end
+
+def fun_l11_n546(x)
+ if (x < 1)
+ fun_l12_n228(x)
+ else
+ fun_l12_n270(x)
+ end
+end
+
+def fun_l11_n547(x)
+ if (x < 1)
+ fun_l12_n528(x)
+ else
+ fun_l12_n423(x)
+ end
+end
+
+def fun_l11_n548(x)
+ if (x < 1)
+ fun_l12_n656(x)
+ else
+ fun_l12_n269(x)
+ end
+end
+
+def fun_l11_n549(x)
+ if (x < 1)
+ fun_l12_n541(x)
+ else
+ fun_l12_n488(x)
+ end
+end
+
+def fun_l11_n550(x)
+ if (x < 1)
+ fun_l12_n240(x)
+ else
+ fun_l12_n990(x)
+ end
+end
+
+def fun_l11_n551(x)
+ if (x < 1)
+ fun_l12_n279(x)
+ else
+ fun_l12_n61(x)
+ end
+end
+
+def fun_l11_n552(x)
+ if (x < 1)
+ fun_l12_n996(x)
+ else
+ fun_l12_n738(x)
+ end
+end
+
+def fun_l11_n553(x)
+ if (x < 1)
+ fun_l12_n334(x)
+ else
+ fun_l12_n117(x)
+ end
+end
+
+def fun_l11_n554(x)
+ if (x < 1)
+ fun_l12_n943(x)
+ else
+ fun_l12_n754(x)
+ end
+end
+
+def fun_l11_n555(x)
+ if (x < 1)
+ fun_l12_n256(x)
+ else
+ fun_l12_n961(x)
+ end
+end
+
+def fun_l11_n556(x)
+ if (x < 1)
+ fun_l12_n530(x)
+ else
+ fun_l12_n378(x)
+ end
+end
+
+def fun_l11_n557(x)
+ if (x < 1)
+ fun_l12_n681(x)
+ else
+ fun_l12_n153(x)
+ end
+end
+
+def fun_l11_n558(x)
+ if (x < 1)
+ fun_l12_n145(x)
+ else
+ fun_l12_n951(x)
+ end
+end
+
+def fun_l11_n559(x)
+ if (x < 1)
+ fun_l12_n107(x)
+ else
+ fun_l12_n341(x)
+ end
+end
+
+def fun_l11_n560(x)
+ if (x < 1)
+ fun_l12_n570(x)
+ else
+ fun_l12_n152(x)
+ end
+end
+
+def fun_l11_n561(x)
+ if (x < 1)
+ fun_l12_n351(x)
+ else
+ fun_l12_n664(x)
+ end
+end
+
+def fun_l11_n562(x)
+ if (x < 1)
+ fun_l12_n825(x)
+ else
+ fun_l12_n226(x)
+ end
+end
+
+def fun_l11_n563(x)
+ if (x < 1)
+ fun_l12_n898(x)
+ else
+ fun_l12_n553(x)
+ end
+end
+
+def fun_l11_n564(x)
+ if (x < 1)
+ fun_l12_n122(x)
+ else
+ fun_l12_n618(x)
+ end
+end
+
+def fun_l11_n565(x)
+ if (x < 1)
+ fun_l12_n185(x)
+ else
+ fun_l12_n51(x)
+ end
+end
+
+def fun_l11_n566(x)
+ if (x < 1)
+ fun_l12_n359(x)
+ else
+ fun_l12_n67(x)
+ end
+end
+
+def fun_l11_n567(x)
+ if (x < 1)
+ fun_l12_n471(x)
+ else
+ fun_l12_n28(x)
+ end
+end
+
+def fun_l11_n568(x)
+ if (x < 1)
+ fun_l12_n195(x)
+ else
+ fun_l12_n104(x)
+ end
+end
+
+def fun_l11_n569(x)
+ if (x < 1)
+ fun_l12_n556(x)
+ else
+ fun_l12_n242(x)
+ end
+end
+
+def fun_l11_n570(x)
+ if (x < 1)
+ fun_l12_n203(x)
+ else
+ fun_l12_n204(x)
+ end
+end
+
+def fun_l11_n571(x)
+ if (x < 1)
+ fun_l12_n217(x)
+ else
+ fun_l12_n392(x)
+ end
+end
+
+def fun_l11_n572(x)
+ if (x < 1)
+ fun_l12_n223(x)
+ else
+ fun_l12_n176(x)
+ end
+end
+
+def fun_l11_n573(x)
+ if (x < 1)
+ fun_l12_n184(x)
+ else
+ fun_l12_n19(x)
+ end
+end
+
+def fun_l11_n574(x)
+ if (x < 1)
+ fun_l12_n799(x)
+ else
+ fun_l12_n652(x)
+ end
+end
+
+def fun_l11_n575(x)
+ if (x < 1)
+ fun_l12_n311(x)
+ else
+ fun_l12_n332(x)
+ end
+end
+
+def fun_l11_n576(x)
+ if (x < 1)
+ fun_l12_n928(x)
+ else
+ fun_l12_n584(x)
+ end
+end
+
+def fun_l11_n577(x)
+ if (x < 1)
+ fun_l12_n796(x)
+ else
+ fun_l12_n931(x)
+ end
+end
+
+def fun_l11_n578(x)
+ if (x < 1)
+ fun_l12_n991(x)
+ else
+ fun_l12_n985(x)
+ end
+end
+
+def fun_l11_n579(x)
+ if (x < 1)
+ fun_l12_n246(x)
+ else
+ fun_l12_n253(x)
+ end
+end
+
+def fun_l11_n580(x)
+ if (x < 1)
+ fun_l12_n492(x)
+ else
+ fun_l12_n239(x)
+ end
+end
+
+def fun_l11_n581(x)
+ if (x < 1)
+ fun_l12_n428(x)
+ else
+ fun_l12_n351(x)
+ end
+end
+
+def fun_l11_n582(x)
+ if (x < 1)
+ fun_l12_n184(x)
+ else
+ fun_l12_n37(x)
+ end
+end
+
+def fun_l11_n583(x)
+ if (x < 1)
+ fun_l12_n809(x)
+ else
+ fun_l12_n527(x)
+ end
+end
+
+def fun_l11_n584(x)
+ if (x < 1)
+ fun_l12_n661(x)
+ else
+ fun_l12_n539(x)
+ end
+end
+
+def fun_l11_n585(x)
+ if (x < 1)
+ fun_l12_n696(x)
+ else
+ fun_l12_n190(x)
+ end
+end
+
+def fun_l11_n586(x)
+ if (x < 1)
+ fun_l12_n178(x)
+ else
+ fun_l12_n301(x)
+ end
+end
+
+def fun_l11_n587(x)
+ if (x < 1)
+ fun_l12_n316(x)
+ else
+ fun_l12_n731(x)
+ end
+end
+
+def fun_l11_n588(x)
+ if (x < 1)
+ fun_l12_n502(x)
+ else
+ fun_l12_n776(x)
+ end
+end
+
+def fun_l11_n589(x)
+ if (x < 1)
+ fun_l12_n273(x)
+ else
+ fun_l12_n268(x)
+ end
+end
+
+def fun_l11_n590(x)
+ if (x < 1)
+ fun_l12_n623(x)
+ else
+ fun_l12_n622(x)
+ end
+end
+
+def fun_l11_n591(x)
+ if (x < 1)
+ fun_l12_n359(x)
+ else
+ fun_l12_n694(x)
+ end
+end
+
+def fun_l11_n592(x)
+ if (x < 1)
+ fun_l12_n71(x)
+ else
+ fun_l12_n984(x)
+ end
+end
+
+def fun_l11_n593(x)
+ if (x < 1)
+ fun_l12_n790(x)
+ else
+ fun_l12_n547(x)
+ end
+end
+
+def fun_l11_n594(x)
+ if (x < 1)
+ fun_l12_n313(x)
+ else
+ fun_l12_n526(x)
+ end
+end
+
+def fun_l11_n595(x)
+ if (x < 1)
+ fun_l12_n239(x)
+ else
+ fun_l12_n821(x)
+ end
+end
+
+def fun_l11_n596(x)
+ if (x < 1)
+ fun_l12_n36(x)
+ else
+ fun_l12_n141(x)
+ end
+end
+
+def fun_l11_n597(x)
+ if (x < 1)
+ fun_l12_n450(x)
+ else
+ fun_l12_n65(x)
+ end
+end
+
+def fun_l11_n598(x)
+ if (x < 1)
+ fun_l12_n226(x)
+ else
+ fun_l12_n490(x)
+ end
+end
+
+def fun_l11_n599(x)
+ if (x < 1)
+ fun_l12_n716(x)
+ else
+ fun_l12_n7(x)
+ end
+end
+
+def fun_l11_n600(x)
+ if (x < 1)
+ fun_l12_n694(x)
+ else
+ fun_l12_n663(x)
+ end
+end
+
+def fun_l11_n601(x)
+ if (x < 1)
+ fun_l12_n690(x)
+ else
+ fun_l12_n256(x)
+ end
+end
+
+def fun_l11_n602(x)
+ if (x < 1)
+ fun_l12_n251(x)
+ else
+ fun_l12_n177(x)
+ end
+end
+
+def fun_l11_n603(x)
+ if (x < 1)
+ fun_l12_n659(x)
+ else
+ fun_l12_n732(x)
+ end
+end
+
+def fun_l11_n604(x)
+ if (x < 1)
+ fun_l12_n440(x)
+ else
+ fun_l12_n334(x)
+ end
+end
+
+def fun_l11_n605(x)
+ if (x < 1)
+ fun_l12_n396(x)
+ else
+ fun_l12_n931(x)
+ end
+end
+
+def fun_l11_n606(x)
+ if (x < 1)
+ fun_l12_n687(x)
+ else
+ fun_l12_n88(x)
+ end
+end
+
+def fun_l11_n607(x)
+ if (x < 1)
+ fun_l12_n647(x)
+ else
+ fun_l12_n799(x)
+ end
+end
+
+def fun_l11_n608(x)
+ if (x < 1)
+ fun_l12_n383(x)
+ else
+ fun_l12_n889(x)
+ end
+end
+
+def fun_l11_n609(x)
+ if (x < 1)
+ fun_l12_n174(x)
+ else
+ fun_l12_n121(x)
+ end
+end
+
+def fun_l11_n610(x)
+ if (x < 1)
+ fun_l12_n818(x)
+ else
+ fun_l12_n835(x)
+ end
+end
+
+def fun_l11_n611(x)
+ if (x < 1)
+ fun_l12_n684(x)
+ else
+ fun_l12_n625(x)
+ end
+end
+
+def fun_l11_n612(x)
+ if (x < 1)
+ fun_l12_n961(x)
+ else
+ fun_l12_n711(x)
+ end
+end
+
+def fun_l11_n613(x)
+ if (x < 1)
+ fun_l12_n15(x)
+ else
+ fun_l12_n542(x)
+ end
+end
+
+def fun_l11_n614(x)
+ if (x < 1)
+ fun_l12_n378(x)
+ else
+ fun_l12_n809(x)
+ end
+end
+
+def fun_l11_n615(x)
+ if (x < 1)
+ fun_l12_n970(x)
+ else
+ fun_l12_n283(x)
+ end
+end
+
+def fun_l11_n616(x)
+ if (x < 1)
+ fun_l12_n391(x)
+ else
+ fun_l12_n949(x)
+ end
+end
+
+def fun_l11_n617(x)
+ if (x < 1)
+ fun_l12_n135(x)
+ else
+ fun_l12_n29(x)
+ end
+end
+
+def fun_l11_n618(x)
+ if (x < 1)
+ fun_l12_n449(x)
+ else
+ fun_l12_n834(x)
+ end
+end
+
+def fun_l11_n619(x)
+ if (x < 1)
+ fun_l12_n555(x)
+ else
+ fun_l12_n464(x)
+ end
+end
+
+def fun_l11_n620(x)
+ if (x < 1)
+ fun_l12_n414(x)
+ else
+ fun_l12_n632(x)
+ end
+end
+
+def fun_l11_n621(x)
+ if (x < 1)
+ fun_l12_n964(x)
+ else
+ fun_l12_n311(x)
+ end
+end
+
+def fun_l11_n622(x)
+ if (x < 1)
+ fun_l12_n184(x)
+ else
+ fun_l12_n499(x)
+ end
+end
+
+def fun_l11_n623(x)
+ if (x < 1)
+ fun_l12_n441(x)
+ else
+ fun_l12_n124(x)
+ end
+end
+
+def fun_l11_n624(x)
+ if (x < 1)
+ fun_l12_n884(x)
+ else
+ fun_l12_n484(x)
+ end
+end
+
+def fun_l11_n625(x)
+ if (x < 1)
+ fun_l12_n878(x)
+ else
+ fun_l12_n646(x)
+ end
+end
+
+def fun_l11_n626(x)
+ if (x < 1)
+ fun_l12_n918(x)
+ else
+ fun_l12_n481(x)
+ end
+end
+
+def fun_l11_n627(x)
+ if (x < 1)
+ fun_l12_n162(x)
+ else
+ fun_l12_n197(x)
+ end
+end
+
+def fun_l11_n628(x)
+ if (x < 1)
+ fun_l12_n852(x)
+ else
+ fun_l12_n874(x)
+ end
+end
+
+def fun_l11_n629(x)
+ if (x < 1)
+ fun_l12_n654(x)
+ else
+ fun_l12_n709(x)
+ end
+end
+
+def fun_l11_n630(x)
+ if (x < 1)
+ fun_l12_n819(x)
+ else
+ fun_l12_n325(x)
+ end
+end
+
+def fun_l11_n631(x)
+ if (x < 1)
+ fun_l12_n776(x)
+ else
+ fun_l12_n621(x)
+ end
+end
+
+def fun_l11_n632(x)
+ if (x < 1)
+ fun_l12_n648(x)
+ else
+ fun_l12_n53(x)
+ end
+end
+
+def fun_l11_n633(x)
+ if (x < 1)
+ fun_l12_n182(x)
+ else
+ fun_l12_n267(x)
+ end
+end
+
+def fun_l11_n634(x)
+ if (x < 1)
+ fun_l12_n17(x)
+ else
+ fun_l12_n415(x)
+ end
+end
+
+def fun_l11_n635(x)
+ if (x < 1)
+ fun_l12_n123(x)
+ else
+ fun_l12_n862(x)
+ end
+end
+
+def fun_l11_n636(x)
+ if (x < 1)
+ fun_l12_n594(x)
+ else
+ fun_l12_n878(x)
+ end
+end
+
+def fun_l11_n637(x)
+ if (x < 1)
+ fun_l12_n913(x)
+ else
+ fun_l12_n245(x)
+ end
+end
+
+def fun_l11_n638(x)
+ if (x < 1)
+ fun_l12_n976(x)
+ else
+ fun_l12_n19(x)
+ end
+end
+
+def fun_l11_n639(x)
+ if (x < 1)
+ fun_l12_n490(x)
+ else
+ fun_l12_n999(x)
+ end
+end
+
+def fun_l11_n640(x)
+ if (x < 1)
+ fun_l12_n345(x)
+ else
+ fun_l12_n585(x)
+ end
+end
+
+def fun_l11_n641(x)
+ if (x < 1)
+ fun_l12_n245(x)
+ else
+ fun_l12_n566(x)
+ end
+end
+
+def fun_l11_n642(x)
+ if (x < 1)
+ fun_l12_n680(x)
+ else
+ fun_l12_n77(x)
+ end
+end
+
+def fun_l11_n643(x)
+ if (x < 1)
+ fun_l12_n330(x)
+ else
+ fun_l12_n268(x)
+ end
+end
+
+def fun_l11_n644(x)
+ if (x < 1)
+ fun_l12_n651(x)
+ else
+ fun_l12_n386(x)
+ end
+end
+
+def fun_l11_n645(x)
+ if (x < 1)
+ fun_l12_n276(x)
+ else
+ fun_l12_n471(x)
+ end
+end
+
+def fun_l11_n646(x)
+ if (x < 1)
+ fun_l12_n784(x)
+ else
+ fun_l12_n892(x)
+ end
+end
+
+def fun_l11_n647(x)
+ if (x < 1)
+ fun_l12_n963(x)
+ else
+ fun_l12_n864(x)
+ end
+end
+
+def fun_l11_n648(x)
+ if (x < 1)
+ fun_l12_n58(x)
+ else
+ fun_l12_n252(x)
+ end
+end
+
+def fun_l11_n649(x)
+ if (x < 1)
+ fun_l12_n321(x)
+ else
+ fun_l12_n593(x)
+ end
+end
+
+def fun_l11_n650(x)
+ if (x < 1)
+ fun_l12_n598(x)
+ else
+ fun_l12_n54(x)
+ end
+end
+
+def fun_l11_n651(x)
+ if (x < 1)
+ fun_l12_n201(x)
+ else
+ fun_l12_n760(x)
+ end
+end
+
+def fun_l11_n652(x)
+ if (x < 1)
+ fun_l12_n880(x)
+ else
+ fun_l12_n841(x)
+ end
+end
+
+def fun_l11_n653(x)
+ if (x < 1)
+ fun_l12_n61(x)
+ else
+ fun_l12_n403(x)
+ end
+end
+
+def fun_l11_n654(x)
+ if (x < 1)
+ fun_l12_n114(x)
+ else
+ fun_l12_n768(x)
+ end
+end
+
+def fun_l11_n655(x)
+ if (x < 1)
+ fun_l12_n511(x)
+ else
+ fun_l12_n521(x)
+ end
+end
+
+def fun_l11_n656(x)
+ if (x < 1)
+ fun_l12_n27(x)
+ else
+ fun_l12_n490(x)
+ end
+end
+
+def fun_l11_n657(x)
+ if (x < 1)
+ fun_l12_n217(x)
+ else
+ fun_l12_n547(x)
+ end
+end
+
+def fun_l11_n658(x)
+ if (x < 1)
+ fun_l12_n549(x)
+ else
+ fun_l12_n823(x)
+ end
+end
+
+def fun_l11_n659(x)
+ if (x < 1)
+ fun_l12_n327(x)
+ else
+ fun_l12_n529(x)
+ end
+end
+
+def fun_l11_n660(x)
+ if (x < 1)
+ fun_l12_n395(x)
+ else
+ fun_l12_n797(x)
+ end
+end
+
+def fun_l11_n661(x)
+ if (x < 1)
+ fun_l12_n867(x)
+ else
+ fun_l12_n142(x)
+ end
+end
+
+def fun_l11_n662(x)
+ if (x < 1)
+ fun_l12_n818(x)
+ else
+ fun_l12_n311(x)
+ end
+end
+
+def fun_l11_n663(x)
+ if (x < 1)
+ fun_l12_n628(x)
+ else
+ fun_l12_n798(x)
+ end
+end
+
+def fun_l11_n664(x)
+ if (x < 1)
+ fun_l12_n260(x)
+ else
+ fun_l12_n607(x)
+ end
+end
+
+def fun_l11_n665(x)
+ if (x < 1)
+ fun_l12_n911(x)
+ else
+ fun_l12_n487(x)
+ end
+end
+
+def fun_l11_n666(x)
+ if (x < 1)
+ fun_l12_n340(x)
+ else
+ fun_l12_n23(x)
+ end
+end
+
+def fun_l11_n667(x)
+ if (x < 1)
+ fun_l12_n744(x)
+ else
+ fun_l12_n874(x)
+ end
+end
+
+def fun_l11_n668(x)
+ if (x < 1)
+ fun_l12_n53(x)
+ else
+ fun_l12_n203(x)
+ end
+end
+
+def fun_l11_n669(x)
+ if (x < 1)
+ fun_l12_n775(x)
+ else
+ fun_l12_n963(x)
+ end
+end
+
+def fun_l11_n670(x)
+ if (x < 1)
+ fun_l12_n922(x)
+ else
+ fun_l12_n0(x)
+ end
+end
+
+def fun_l11_n671(x)
+ if (x < 1)
+ fun_l12_n23(x)
+ else
+ fun_l12_n798(x)
+ end
+end
+
+def fun_l11_n672(x)
+ if (x < 1)
+ fun_l12_n453(x)
+ else
+ fun_l12_n667(x)
+ end
+end
+
+def fun_l11_n673(x)
+ if (x < 1)
+ fun_l12_n991(x)
+ else
+ fun_l12_n350(x)
+ end
+end
+
+def fun_l11_n674(x)
+ if (x < 1)
+ fun_l12_n865(x)
+ else
+ fun_l12_n95(x)
+ end
+end
+
+def fun_l11_n675(x)
+ if (x < 1)
+ fun_l12_n404(x)
+ else
+ fun_l12_n714(x)
+ end
+end
+
+def fun_l11_n676(x)
+ if (x < 1)
+ fun_l12_n576(x)
+ else
+ fun_l12_n162(x)
+ end
+end
+
+def fun_l11_n677(x)
+ if (x < 1)
+ fun_l12_n530(x)
+ else
+ fun_l12_n453(x)
+ end
+end
+
+def fun_l11_n678(x)
+ if (x < 1)
+ fun_l12_n127(x)
+ else
+ fun_l12_n224(x)
+ end
+end
+
+def fun_l11_n679(x)
+ if (x < 1)
+ fun_l12_n658(x)
+ else
+ fun_l12_n11(x)
+ end
+end
+
+def fun_l11_n680(x)
+ if (x < 1)
+ fun_l12_n778(x)
+ else
+ fun_l12_n202(x)
+ end
+end
+
+def fun_l11_n681(x)
+ if (x < 1)
+ fun_l12_n745(x)
+ else
+ fun_l12_n690(x)
+ end
+end
+
+def fun_l11_n682(x)
+ if (x < 1)
+ fun_l12_n920(x)
+ else
+ fun_l12_n54(x)
+ end
+end
+
+def fun_l11_n683(x)
+ if (x < 1)
+ fun_l12_n726(x)
+ else
+ fun_l12_n466(x)
+ end
+end
+
+def fun_l11_n684(x)
+ if (x < 1)
+ fun_l12_n709(x)
+ else
+ fun_l12_n287(x)
+ end
+end
+
+def fun_l11_n685(x)
+ if (x < 1)
+ fun_l12_n304(x)
+ else
+ fun_l12_n617(x)
+ end
+end
+
+def fun_l11_n686(x)
+ if (x < 1)
+ fun_l12_n834(x)
+ else
+ fun_l12_n240(x)
+ end
+end
+
+def fun_l11_n687(x)
+ if (x < 1)
+ fun_l12_n406(x)
+ else
+ fun_l12_n588(x)
+ end
+end
+
+def fun_l11_n688(x)
+ if (x < 1)
+ fun_l12_n308(x)
+ else
+ fun_l12_n790(x)
+ end
+end
+
+def fun_l11_n689(x)
+ if (x < 1)
+ fun_l12_n969(x)
+ else
+ fun_l12_n249(x)
+ end
+end
+
+def fun_l11_n690(x)
+ if (x < 1)
+ fun_l12_n760(x)
+ else
+ fun_l12_n807(x)
+ end
+end
+
+def fun_l11_n691(x)
+ if (x < 1)
+ fun_l12_n417(x)
+ else
+ fun_l12_n645(x)
+ end
+end
+
+def fun_l11_n692(x)
+ if (x < 1)
+ fun_l12_n722(x)
+ else
+ fun_l12_n614(x)
+ end
+end
+
+def fun_l11_n693(x)
+ if (x < 1)
+ fun_l12_n19(x)
+ else
+ fun_l12_n497(x)
+ end
+end
+
+def fun_l11_n694(x)
+ if (x < 1)
+ fun_l12_n580(x)
+ else
+ fun_l12_n76(x)
+ end
+end
+
+def fun_l11_n695(x)
+ if (x < 1)
+ fun_l12_n527(x)
+ else
+ fun_l12_n819(x)
+ end
+end
+
+def fun_l11_n696(x)
+ if (x < 1)
+ fun_l12_n71(x)
+ else
+ fun_l12_n906(x)
+ end
+end
+
+def fun_l11_n697(x)
+ if (x < 1)
+ fun_l12_n95(x)
+ else
+ fun_l12_n743(x)
+ end
+end
+
+def fun_l11_n698(x)
+ if (x < 1)
+ fun_l12_n544(x)
+ else
+ fun_l12_n265(x)
+ end
+end
+
+def fun_l11_n699(x)
+ if (x < 1)
+ fun_l12_n833(x)
+ else
+ fun_l12_n210(x)
+ end
+end
+
+def fun_l11_n700(x)
+ if (x < 1)
+ fun_l12_n865(x)
+ else
+ fun_l12_n318(x)
+ end
+end
+
+def fun_l11_n701(x)
+ if (x < 1)
+ fun_l12_n88(x)
+ else
+ fun_l12_n120(x)
+ end
+end
+
+def fun_l11_n702(x)
+ if (x < 1)
+ fun_l12_n165(x)
+ else
+ fun_l12_n671(x)
+ end
+end
+
+def fun_l11_n703(x)
+ if (x < 1)
+ fun_l12_n607(x)
+ else
+ fun_l12_n730(x)
+ end
+end
+
+def fun_l11_n704(x)
+ if (x < 1)
+ fun_l12_n690(x)
+ else
+ fun_l12_n553(x)
+ end
+end
+
+def fun_l11_n705(x)
+ if (x < 1)
+ fun_l12_n826(x)
+ else
+ fun_l12_n665(x)
+ end
+end
+
+def fun_l11_n706(x)
+ if (x < 1)
+ fun_l12_n125(x)
+ else
+ fun_l12_n167(x)
+ end
+end
+
+def fun_l11_n707(x)
+ if (x < 1)
+ fun_l12_n961(x)
+ else
+ fun_l12_n73(x)
+ end
+end
+
+def fun_l11_n708(x)
+ if (x < 1)
+ fun_l12_n446(x)
+ else
+ fun_l12_n373(x)
+ end
+end
+
+def fun_l11_n709(x)
+ if (x < 1)
+ fun_l12_n199(x)
+ else
+ fun_l12_n803(x)
+ end
+end
+
+def fun_l11_n710(x)
+ if (x < 1)
+ fun_l12_n960(x)
+ else
+ fun_l12_n996(x)
+ end
+end
+
+def fun_l11_n711(x)
+ if (x < 1)
+ fun_l12_n602(x)
+ else
+ fun_l12_n896(x)
+ end
+end
+
+def fun_l11_n712(x)
+ if (x < 1)
+ fun_l12_n198(x)
+ else
+ fun_l12_n857(x)
+ end
+end
+
+def fun_l11_n713(x)
+ if (x < 1)
+ fun_l12_n19(x)
+ else
+ fun_l12_n938(x)
+ end
+end
+
+def fun_l11_n714(x)
+ if (x < 1)
+ fun_l12_n530(x)
+ else
+ fun_l12_n432(x)
+ end
+end
+
+def fun_l11_n715(x)
+ if (x < 1)
+ fun_l12_n99(x)
+ else
+ fun_l12_n382(x)
+ end
+end
+
+def fun_l11_n716(x)
+ if (x < 1)
+ fun_l12_n623(x)
+ else
+ fun_l12_n461(x)
+ end
+end
+
+def fun_l11_n717(x)
+ if (x < 1)
+ fun_l12_n658(x)
+ else
+ fun_l12_n432(x)
+ end
+end
+
+def fun_l11_n718(x)
+ if (x < 1)
+ fun_l12_n17(x)
+ else
+ fun_l12_n83(x)
+ end
+end
+
+def fun_l11_n719(x)
+ if (x < 1)
+ fun_l12_n439(x)
+ else
+ fun_l12_n747(x)
+ end
+end
+
+def fun_l11_n720(x)
+ if (x < 1)
+ fun_l12_n259(x)
+ else
+ fun_l12_n80(x)
+ end
+end
+
+def fun_l11_n721(x)
+ if (x < 1)
+ fun_l12_n749(x)
+ else
+ fun_l12_n108(x)
+ end
+end
+
+def fun_l11_n722(x)
+ if (x < 1)
+ fun_l12_n20(x)
+ else
+ fun_l12_n391(x)
+ end
+end
+
+def fun_l11_n723(x)
+ if (x < 1)
+ fun_l12_n181(x)
+ else
+ fun_l12_n204(x)
+ end
+end
+
+def fun_l11_n724(x)
+ if (x < 1)
+ fun_l12_n426(x)
+ else
+ fun_l12_n109(x)
+ end
+end
+
+def fun_l11_n725(x)
+ if (x < 1)
+ fun_l12_n436(x)
+ else
+ fun_l12_n754(x)
+ end
+end
+
+def fun_l11_n726(x)
+ if (x < 1)
+ fun_l12_n496(x)
+ else
+ fun_l12_n265(x)
+ end
+end
+
+def fun_l11_n727(x)
+ if (x < 1)
+ fun_l12_n58(x)
+ else
+ fun_l12_n982(x)
+ end
+end
+
+def fun_l11_n728(x)
+ if (x < 1)
+ fun_l12_n236(x)
+ else
+ fun_l12_n152(x)
+ end
+end
+
+def fun_l11_n729(x)
+ if (x < 1)
+ fun_l12_n818(x)
+ else
+ fun_l12_n95(x)
+ end
+end
+
+def fun_l11_n730(x)
+ if (x < 1)
+ fun_l12_n696(x)
+ else
+ fun_l12_n263(x)
+ end
+end
+
+def fun_l11_n731(x)
+ if (x < 1)
+ fun_l12_n539(x)
+ else
+ fun_l12_n774(x)
+ end
+end
+
+def fun_l11_n732(x)
+ if (x < 1)
+ fun_l12_n788(x)
+ else
+ fun_l12_n454(x)
+ end
+end
+
+def fun_l11_n733(x)
+ if (x < 1)
+ fun_l12_n131(x)
+ else
+ fun_l12_n877(x)
+ end
+end
+
+def fun_l11_n734(x)
+ if (x < 1)
+ fun_l12_n449(x)
+ else
+ fun_l12_n222(x)
+ end
+end
+
+def fun_l11_n735(x)
+ if (x < 1)
+ fun_l12_n71(x)
+ else
+ fun_l12_n467(x)
+ end
+end
+
+def fun_l11_n736(x)
+ if (x < 1)
+ fun_l12_n220(x)
+ else
+ fun_l12_n214(x)
+ end
+end
+
+def fun_l11_n737(x)
+ if (x < 1)
+ fun_l12_n537(x)
+ else
+ fun_l12_n173(x)
+ end
+end
+
+def fun_l11_n738(x)
+ if (x < 1)
+ fun_l12_n897(x)
+ else
+ fun_l12_n515(x)
+ end
+end
+
+def fun_l11_n739(x)
+ if (x < 1)
+ fun_l12_n724(x)
+ else
+ fun_l12_n48(x)
+ end
+end
+
+def fun_l11_n740(x)
+ if (x < 1)
+ fun_l12_n61(x)
+ else
+ fun_l12_n963(x)
+ end
+end
+
+def fun_l11_n741(x)
+ if (x < 1)
+ fun_l12_n40(x)
+ else
+ fun_l12_n553(x)
+ end
+end
+
+def fun_l11_n742(x)
+ if (x < 1)
+ fun_l12_n361(x)
+ else
+ fun_l12_n975(x)
+ end
+end
+
+def fun_l11_n743(x)
+ if (x < 1)
+ fun_l12_n306(x)
+ else
+ fun_l12_n982(x)
+ end
+end
+
+def fun_l11_n744(x)
+ if (x < 1)
+ fun_l12_n951(x)
+ else
+ fun_l12_n590(x)
+ end
+end
+
+def fun_l11_n745(x)
+ if (x < 1)
+ fun_l12_n224(x)
+ else
+ fun_l12_n409(x)
+ end
+end
+
+def fun_l11_n746(x)
+ if (x < 1)
+ fun_l12_n24(x)
+ else
+ fun_l12_n249(x)
+ end
+end
+
+def fun_l11_n747(x)
+ if (x < 1)
+ fun_l12_n533(x)
+ else
+ fun_l12_n543(x)
+ end
+end
+
+def fun_l11_n748(x)
+ if (x < 1)
+ fun_l12_n616(x)
+ else
+ fun_l12_n63(x)
+ end
+end
+
+def fun_l11_n749(x)
+ if (x < 1)
+ fun_l12_n365(x)
+ else
+ fun_l12_n335(x)
+ end
+end
+
+def fun_l11_n750(x)
+ if (x < 1)
+ fun_l12_n134(x)
+ else
+ fun_l12_n363(x)
+ end
+end
+
+def fun_l11_n751(x)
+ if (x < 1)
+ fun_l12_n413(x)
+ else
+ fun_l12_n582(x)
+ end
+end
+
+def fun_l11_n752(x)
+ if (x < 1)
+ fun_l12_n987(x)
+ else
+ fun_l12_n948(x)
+ end
+end
+
+def fun_l11_n753(x)
+ if (x < 1)
+ fun_l12_n696(x)
+ else
+ fun_l12_n374(x)
+ end
+end
+
+def fun_l11_n754(x)
+ if (x < 1)
+ fun_l12_n730(x)
+ else
+ fun_l12_n345(x)
+ end
+end
+
+def fun_l11_n755(x)
+ if (x < 1)
+ fun_l12_n857(x)
+ else
+ fun_l12_n441(x)
+ end
+end
+
+def fun_l11_n756(x)
+ if (x < 1)
+ fun_l12_n711(x)
+ else
+ fun_l12_n39(x)
+ end
+end
+
+def fun_l11_n757(x)
+ if (x < 1)
+ fun_l12_n946(x)
+ else
+ fun_l12_n657(x)
+ end
+end
+
+def fun_l11_n758(x)
+ if (x < 1)
+ fun_l12_n470(x)
+ else
+ fun_l12_n650(x)
+ end
+end
+
+def fun_l11_n759(x)
+ if (x < 1)
+ fun_l12_n119(x)
+ else
+ fun_l12_n479(x)
+ end
+end
+
+def fun_l11_n760(x)
+ if (x < 1)
+ fun_l12_n429(x)
+ else
+ fun_l12_n922(x)
+ end
+end
+
+def fun_l11_n761(x)
+ if (x < 1)
+ fun_l12_n13(x)
+ else
+ fun_l12_n134(x)
+ end
+end
+
+def fun_l11_n762(x)
+ if (x < 1)
+ fun_l12_n797(x)
+ else
+ fun_l12_n223(x)
+ end
+end
+
+def fun_l11_n763(x)
+ if (x < 1)
+ fun_l12_n945(x)
+ else
+ fun_l12_n197(x)
+ end
+end
+
+def fun_l11_n764(x)
+ if (x < 1)
+ fun_l12_n612(x)
+ else
+ fun_l12_n773(x)
+ end
+end
+
+def fun_l11_n765(x)
+ if (x < 1)
+ fun_l12_n478(x)
+ else
+ fun_l12_n972(x)
+ end
+end
+
+def fun_l11_n766(x)
+ if (x < 1)
+ fun_l12_n946(x)
+ else
+ fun_l12_n9(x)
+ end
+end
+
+def fun_l11_n767(x)
+ if (x < 1)
+ fun_l12_n247(x)
+ else
+ fun_l12_n730(x)
+ end
+end
+
+def fun_l11_n768(x)
+ if (x < 1)
+ fun_l12_n223(x)
+ else
+ fun_l12_n986(x)
+ end
+end
+
+def fun_l11_n769(x)
+ if (x < 1)
+ fun_l12_n676(x)
+ else
+ fun_l12_n527(x)
+ end
+end
+
+def fun_l11_n770(x)
+ if (x < 1)
+ fun_l12_n112(x)
+ else
+ fun_l12_n660(x)
+ end
+end
+
+def fun_l11_n771(x)
+ if (x < 1)
+ fun_l12_n457(x)
+ else
+ fun_l12_n733(x)
+ end
+end
+
+def fun_l11_n772(x)
+ if (x < 1)
+ fun_l12_n633(x)
+ else
+ fun_l12_n449(x)
+ end
+end
+
+def fun_l11_n773(x)
+ if (x < 1)
+ fun_l12_n910(x)
+ else
+ fun_l12_n329(x)
+ end
+end
+
+def fun_l11_n774(x)
+ if (x < 1)
+ fun_l12_n354(x)
+ else
+ fun_l12_n233(x)
+ end
+end
+
+def fun_l11_n775(x)
+ if (x < 1)
+ fun_l12_n887(x)
+ else
+ fun_l12_n100(x)
+ end
+end
+
+def fun_l11_n776(x)
+ if (x < 1)
+ fun_l12_n65(x)
+ else
+ fun_l12_n199(x)
+ end
+end
+
+def fun_l11_n777(x)
+ if (x < 1)
+ fun_l12_n978(x)
+ else
+ fun_l12_n364(x)
+ end
+end
+
+def fun_l11_n778(x)
+ if (x < 1)
+ fun_l12_n502(x)
+ else
+ fun_l12_n90(x)
+ end
+end
+
+def fun_l11_n779(x)
+ if (x < 1)
+ fun_l12_n37(x)
+ else
+ fun_l12_n668(x)
+ end
+end
+
+def fun_l11_n780(x)
+ if (x < 1)
+ fun_l12_n80(x)
+ else
+ fun_l12_n603(x)
+ end
+end
+
+def fun_l11_n781(x)
+ if (x < 1)
+ fun_l12_n435(x)
+ else
+ fun_l12_n583(x)
+ end
+end
+
+def fun_l11_n782(x)
+ if (x < 1)
+ fun_l12_n899(x)
+ else
+ fun_l12_n863(x)
+ end
+end
+
+def fun_l11_n783(x)
+ if (x < 1)
+ fun_l12_n414(x)
+ else
+ fun_l12_n96(x)
+ end
+end
+
+def fun_l11_n784(x)
+ if (x < 1)
+ fun_l12_n286(x)
+ else
+ fun_l12_n126(x)
+ end
+end
+
+def fun_l11_n785(x)
+ if (x < 1)
+ fun_l12_n444(x)
+ else
+ fun_l12_n344(x)
+ end
+end
+
+def fun_l11_n786(x)
+ if (x < 1)
+ fun_l12_n484(x)
+ else
+ fun_l12_n469(x)
+ end
+end
+
+def fun_l11_n787(x)
+ if (x < 1)
+ fun_l12_n686(x)
+ else
+ fun_l12_n728(x)
+ end
+end
+
+def fun_l11_n788(x)
+ if (x < 1)
+ fun_l12_n938(x)
+ else
+ fun_l12_n70(x)
+ end
+end
+
+def fun_l11_n789(x)
+ if (x < 1)
+ fun_l12_n958(x)
+ else
+ fun_l12_n633(x)
+ end
+end
+
+def fun_l11_n790(x)
+ if (x < 1)
+ fun_l12_n984(x)
+ else
+ fun_l12_n39(x)
+ end
+end
+
+def fun_l11_n791(x)
+ if (x < 1)
+ fun_l12_n877(x)
+ else
+ fun_l12_n721(x)
+ end
+end
+
+def fun_l11_n792(x)
+ if (x < 1)
+ fun_l12_n710(x)
+ else
+ fun_l12_n840(x)
+ end
+end
+
+def fun_l11_n793(x)
+ if (x < 1)
+ fun_l12_n955(x)
+ else
+ fun_l12_n774(x)
+ end
+end
+
+def fun_l11_n794(x)
+ if (x < 1)
+ fun_l12_n816(x)
+ else
+ fun_l12_n859(x)
+ end
+end
+
+def fun_l11_n795(x)
+ if (x < 1)
+ fun_l12_n722(x)
+ else
+ fun_l12_n700(x)
+ end
+end
+
+def fun_l11_n796(x)
+ if (x < 1)
+ fun_l12_n508(x)
+ else
+ fun_l12_n617(x)
+ end
+end
+
+def fun_l11_n797(x)
+ if (x < 1)
+ fun_l12_n382(x)
+ else
+ fun_l12_n1(x)
+ end
+end
+
+def fun_l11_n798(x)
+ if (x < 1)
+ fun_l12_n857(x)
+ else
+ fun_l12_n141(x)
+ end
+end
+
+def fun_l11_n799(x)
+ if (x < 1)
+ fun_l12_n711(x)
+ else
+ fun_l12_n842(x)
+ end
+end
+
+def fun_l11_n800(x)
+ if (x < 1)
+ fun_l12_n588(x)
+ else
+ fun_l12_n511(x)
+ end
+end
+
+def fun_l11_n801(x)
+ if (x < 1)
+ fun_l12_n114(x)
+ else
+ fun_l12_n516(x)
+ end
+end
+
+def fun_l11_n802(x)
+ if (x < 1)
+ fun_l12_n792(x)
+ else
+ fun_l12_n128(x)
+ end
+end
+
+def fun_l11_n803(x)
+ if (x < 1)
+ fun_l12_n833(x)
+ else
+ fun_l12_n444(x)
+ end
+end
+
+def fun_l11_n804(x)
+ if (x < 1)
+ fun_l12_n564(x)
+ else
+ fun_l12_n129(x)
+ end
+end
+
+def fun_l11_n805(x)
+ if (x < 1)
+ fun_l12_n234(x)
+ else
+ fun_l12_n429(x)
+ end
+end
+
+def fun_l11_n806(x)
+ if (x < 1)
+ fun_l12_n841(x)
+ else
+ fun_l12_n705(x)
+ end
+end
+
+def fun_l11_n807(x)
+ if (x < 1)
+ fun_l12_n72(x)
+ else
+ fun_l12_n87(x)
+ end
+end
+
+def fun_l11_n808(x)
+ if (x < 1)
+ fun_l12_n131(x)
+ else
+ fun_l12_n27(x)
+ end
+end
+
+def fun_l11_n809(x)
+ if (x < 1)
+ fun_l12_n136(x)
+ else
+ fun_l12_n84(x)
+ end
+end
+
+def fun_l11_n810(x)
+ if (x < 1)
+ fun_l12_n464(x)
+ else
+ fun_l12_n411(x)
+ end
+end
+
+def fun_l11_n811(x)
+ if (x < 1)
+ fun_l12_n939(x)
+ else
+ fun_l12_n584(x)
+ end
+end
+
+def fun_l11_n812(x)
+ if (x < 1)
+ fun_l12_n24(x)
+ else
+ fun_l12_n593(x)
+ end
+end
+
+def fun_l11_n813(x)
+ if (x < 1)
+ fun_l12_n980(x)
+ else
+ fun_l12_n318(x)
+ end
+end
+
+def fun_l11_n814(x)
+ if (x < 1)
+ fun_l12_n73(x)
+ else
+ fun_l12_n431(x)
+ end
+end
+
+def fun_l11_n815(x)
+ if (x < 1)
+ fun_l12_n938(x)
+ else
+ fun_l12_n794(x)
+ end
+end
+
+def fun_l11_n816(x)
+ if (x < 1)
+ fun_l12_n305(x)
+ else
+ fun_l12_n620(x)
+ end
+end
+
+def fun_l11_n817(x)
+ if (x < 1)
+ fun_l12_n881(x)
+ else
+ fun_l12_n636(x)
+ end
+end
+
+def fun_l11_n818(x)
+ if (x < 1)
+ fun_l12_n493(x)
+ else
+ fun_l12_n536(x)
+ end
+end
+
+def fun_l11_n819(x)
+ if (x < 1)
+ fun_l12_n32(x)
+ else
+ fun_l12_n69(x)
+ end
+end
+
+def fun_l11_n820(x)
+ if (x < 1)
+ fun_l12_n131(x)
+ else
+ fun_l12_n206(x)
+ end
+end
+
+def fun_l11_n821(x)
+ if (x < 1)
+ fun_l12_n130(x)
+ else
+ fun_l12_n63(x)
+ end
+end
+
+def fun_l11_n822(x)
+ if (x < 1)
+ fun_l12_n228(x)
+ else
+ fun_l12_n753(x)
+ end
+end
+
+def fun_l11_n823(x)
+ if (x < 1)
+ fun_l12_n171(x)
+ else
+ fun_l12_n605(x)
+ end
+end
+
+def fun_l11_n824(x)
+ if (x < 1)
+ fun_l12_n69(x)
+ else
+ fun_l12_n900(x)
+ end
+end
+
+def fun_l11_n825(x)
+ if (x < 1)
+ fun_l12_n802(x)
+ else
+ fun_l12_n682(x)
+ end
+end
+
+def fun_l11_n826(x)
+ if (x < 1)
+ fun_l12_n311(x)
+ else
+ fun_l12_n257(x)
+ end
+end
+
+def fun_l11_n827(x)
+ if (x < 1)
+ fun_l12_n994(x)
+ else
+ fun_l12_n162(x)
+ end
+end
+
+def fun_l11_n828(x)
+ if (x < 1)
+ fun_l12_n780(x)
+ else
+ fun_l12_n805(x)
+ end
+end
+
+def fun_l11_n829(x)
+ if (x < 1)
+ fun_l12_n744(x)
+ else
+ fun_l12_n55(x)
+ end
+end
+
+def fun_l11_n830(x)
+ if (x < 1)
+ fun_l12_n655(x)
+ else
+ fun_l12_n603(x)
+ end
+end
+
+def fun_l11_n831(x)
+ if (x < 1)
+ fun_l12_n245(x)
+ else
+ fun_l12_n196(x)
+ end
+end
+
+def fun_l11_n832(x)
+ if (x < 1)
+ fun_l12_n381(x)
+ else
+ fun_l12_n582(x)
+ end
+end
+
+def fun_l11_n833(x)
+ if (x < 1)
+ fun_l12_n185(x)
+ else
+ fun_l12_n339(x)
+ end
+end
+
+def fun_l11_n834(x)
+ if (x < 1)
+ fun_l12_n601(x)
+ else
+ fun_l12_n996(x)
+ end
+end
+
+def fun_l11_n835(x)
+ if (x < 1)
+ fun_l12_n934(x)
+ else
+ fun_l12_n460(x)
+ end
+end
+
+def fun_l11_n836(x)
+ if (x < 1)
+ fun_l12_n550(x)
+ else
+ fun_l12_n55(x)
+ end
+end
+
+def fun_l11_n837(x)
+ if (x < 1)
+ fun_l12_n183(x)
+ else
+ fun_l12_n880(x)
+ end
+end
+
+def fun_l11_n838(x)
+ if (x < 1)
+ fun_l12_n742(x)
+ else
+ fun_l12_n249(x)
+ end
+end
+
+def fun_l11_n839(x)
+ if (x < 1)
+ fun_l12_n979(x)
+ else
+ fun_l12_n100(x)
+ end
+end
+
+def fun_l11_n840(x)
+ if (x < 1)
+ fun_l12_n889(x)
+ else
+ fun_l12_n683(x)
+ end
+end
+
+def fun_l11_n841(x)
+ if (x < 1)
+ fun_l12_n964(x)
+ else
+ fun_l12_n0(x)
+ end
+end
+
+def fun_l11_n842(x)
+ if (x < 1)
+ fun_l12_n461(x)
+ else
+ fun_l12_n126(x)
+ end
+end
+
+def fun_l11_n843(x)
+ if (x < 1)
+ fun_l12_n839(x)
+ else
+ fun_l12_n554(x)
+ end
+end
+
+def fun_l11_n844(x)
+ if (x < 1)
+ fun_l12_n150(x)
+ else
+ fun_l12_n857(x)
+ end
+end
+
+def fun_l11_n845(x)
+ if (x < 1)
+ fun_l12_n114(x)
+ else
+ fun_l12_n72(x)
+ end
+end
+
+def fun_l11_n846(x)
+ if (x < 1)
+ fun_l12_n953(x)
+ else
+ fun_l12_n695(x)
+ end
+end
+
+def fun_l11_n847(x)
+ if (x < 1)
+ fun_l12_n16(x)
+ else
+ fun_l12_n216(x)
+ end
+end
+
+def fun_l11_n848(x)
+ if (x < 1)
+ fun_l12_n440(x)
+ else
+ fun_l12_n893(x)
+ end
+end
+
+def fun_l11_n849(x)
+ if (x < 1)
+ fun_l12_n176(x)
+ else
+ fun_l12_n932(x)
+ end
+end
+
+def fun_l11_n850(x)
+ if (x < 1)
+ fun_l12_n723(x)
+ else
+ fun_l12_n363(x)
+ end
+end
+
+def fun_l11_n851(x)
+ if (x < 1)
+ fun_l12_n779(x)
+ else
+ fun_l12_n774(x)
+ end
+end
+
+def fun_l11_n852(x)
+ if (x < 1)
+ fun_l12_n618(x)
+ else
+ fun_l12_n252(x)
+ end
+end
+
+def fun_l11_n853(x)
+ if (x < 1)
+ fun_l12_n298(x)
+ else
+ fun_l12_n563(x)
+ end
+end
+
+def fun_l11_n854(x)
+ if (x < 1)
+ fun_l12_n972(x)
+ else
+ fun_l12_n681(x)
+ end
+end
+
+def fun_l11_n855(x)
+ if (x < 1)
+ fun_l12_n412(x)
+ else
+ fun_l12_n932(x)
+ end
+end
+
+def fun_l11_n856(x)
+ if (x < 1)
+ fun_l12_n132(x)
+ else
+ fun_l12_n699(x)
+ end
+end
+
+def fun_l11_n857(x)
+ if (x < 1)
+ fun_l12_n208(x)
+ else
+ fun_l12_n602(x)
+ end
+end
+
+def fun_l11_n858(x)
+ if (x < 1)
+ fun_l12_n705(x)
+ else
+ fun_l12_n833(x)
+ end
+end
+
+def fun_l11_n859(x)
+ if (x < 1)
+ fun_l12_n408(x)
+ else
+ fun_l12_n570(x)
+ end
+end
+
+def fun_l11_n860(x)
+ if (x < 1)
+ fun_l12_n720(x)
+ else
+ fun_l12_n996(x)
+ end
+end
+
+def fun_l11_n861(x)
+ if (x < 1)
+ fun_l12_n926(x)
+ else
+ fun_l12_n490(x)
+ end
+end
+
+def fun_l11_n862(x)
+ if (x < 1)
+ fun_l12_n985(x)
+ else
+ fun_l12_n54(x)
+ end
+end
+
+def fun_l11_n863(x)
+ if (x < 1)
+ fun_l12_n214(x)
+ else
+ fun_l12_n729(x)
+ end
+end
+
+def fun_l11_n864(x)
+ if (x < 1)
+ fun_l12_n351(x)
+ else
+ fun_l12_n951(x)
+ end
+end
+
+def fun_l11_n865(x)
+ if (x < 1)
+ fun_l12_n514(x)
+ else
+ fun_l12_n468(x)
+ end
+end
+
+def fun_l11_n866(x)
+ if (x < 1)
+ fun_l12_n793(x)
+ else
+ fun_l12_n712(x)
+ end
+end
+
+def fun_l11_n867(x)
+ if (x < 1)
+ fun_l12_n697(x)
+ else
+ fun_l12_n824(x)
+ end
+end
+
+def fun_l11_n868(x)
+ if (x < 1)
+ fun_l12_n144(x)
+ else
+ fun_l12_n703(x)
+ end
+end
+
+def fun_l11_n869(x)
+ if (x < 1)
+ fun_l12_n552(x)
+ else
+ fun_l12_n612(x)
+ end
+end
+
+def fun_l11_n870(x)
+ if (x < 1)
+ fun_l12_n2(x)
+ else
+ fun_l12_n287(x)
+ end
+end
+
+def fun_l11_n871(x)
+ if (x < 1)
+ fun_l12_n604(x)
+ else
+ fun_l12_n260(x)
+ end
+end
+
+def fun_l11_n872(x)
+ if (x < 1)
+ fun_l12_n517(x)
+ else
+ fun_l12_n173(x)
+ end
+end
+
+def fun_l11_n873(x)
+ if (x < 1)
+ fun_l12_n640(x)
+ else
+ fun_l12_n196(x)
+ end
+end
+
+def fun_l11_n874(x)
+ if (x < 1)
+ fun_l12_n874(x)
+ else
+ fun_l12_n697(x)
+ end
+end
+
+def fun_l11_n875(x)
+ if (x < 1)
+ fun_l12_n180(x)
+ else
+ fun_l12_n652(x)
+ end
+end
+
+def fun_l11_n876(x)
+ if (x < 1)
+ fun_l12_n432(x)
+ else
+ fun_l12_n971(x)
+ end
+end
+
+def fun_l11_n877(x)
+ if (x < 1)
+ fun_l12_n111(x)
+ else
+ fun_l12_n919(x)
+ end
+end
+
+def fun_l11_n878(x)
+ if (x < 1)
+ fun_l12_n631(x)
+ else
+ fun_l12_n439(x)
+ end
+end
+
+def fun_l11_n879(x)
+ if (x < 1)
+ fun_l12_n39(x)
+ else
+ fun_l12_n372(x)
+ end
+end
+
+def fun_l11_n880(x)
+ if (x < 1)
+ fun_l12_n675(x)
+ else
+ fun_l12_n64(x)
+ end
+end
+
+def fun_l11_n881(x)
+ if (x < 1)
+ fun_l12_n831(x)
+ else
+ fun_l12_n705(x)
+ end
+end
+
+def fun_l11_n882(x)
+ if (x < 1)
+ fun_l12_n126(x)
+ else
+ fun_l12_n648(x)
+ end
+end
+
+def fun_l11_n883(x)
+ if (x < 1)
+ fun_l12_n768(x)
+ else
+ fun_l12_n483(x)
+ end
+end
+
+def fun_l11_n884(x)
+ if (x < 1)
+ fun_l12_n328(x)
+ else
+ fun_l12_n646(x)
+ end
+end
+
+def fun_l11_n885(x)
+ if (x < 1)
+ fun_l12_n890(x)
+ else
+ fun_l12_n544(x)
+ end
+end
+
+def fun_l11_n886(x)
+ if (x < 1)
+ fun_l12_n651(x)
+ else
+ fun_l12_n557(x)
+ end
+end
+
+def fun_l11_n887(x)
+ if (x < 1)
+ fun_l12_n479(x)
+ else
+ fun_l12_n594(x)
+ end
+end
+
+def fun_l11_n888(x)
+ if (x < 1)
+ fun_l12_n649(x)
+ else
+ fun_l12_n488(x)
+ end
+end
+
+def fun_l11_n889(x)
+ if (x < 1)
+ fun_l12_n347(x)
+ else
+ fun_l12_n42(x)
+ end
+end
+
+def fun_l11_n890(x)
+ if (x < 1)
+ fun_l12_n111(x)
+ else
+ fun_l12_n683(x)
+ end
+end
+
+def fun_l11_n891(x)
+ if (x < 1)
+ fun_l12_n965(x)
+ else
+ fun_l12_n275(x)
+ end
+end
+
+def fun_l11_n892(x)
+ if (x < 1)
+ fun_l12_n148(x)
+ else
+ fun_l12_n541(x)
+ end
+end
+
+def fun_l11_n893(x)
+ if (x < 1)
+ fun_l12_n633(x)
+ else
+ fun_l12_n358(x)
+ end
+end
+
+def fun_l11_n894(x)
+ if (x < 1)
+ fun_l12_n681(x)
+ else
+ fun_l12_n236(x)
+ end
+end
+
+def fun_l11_n895(x)
+ if (x < 1)
+ fun_l12_n292(x)
+ else
+ fun_l12_n417(x)
+ end
+end
+
+def fun_l11_n896(x)
+ if (x < 1)
+ fun_l12_n165(x)
+ else
+ fun_l12_n80(x)
+ end
+end
+
+def fun_l11_n897(x)
+ if (x < 1)
+ fun_l12_n132(x)
+ else
+ fun_l12_n659(x)
+ end
+end
+
+def fun_l11_n898(x)
+ if (x < 1)
+ fun_l12_n329(x)
+ else
+ fun_l12_n204(x)
+ end
+end
+
+def fun_l11_n899(x)
+ if (x < 1)
+ fun_l12_n339(x)
+ else
+ fun_l12_n632(x)
+ end
+end
+
+def fun_l11_n900(x)
+ if (x < 1)
+ fun_l12_n957(x)
+ else
+ fun_l12_n282(x)
+ end
+end
+
+def fun_l11_n901(x)
+ if (x < 1)
+ fun_l12_n709(x)
+ else
+ fun_l12_n155(x)
+ end
+end
+
+def fun_l11_n902(x)
+ if (x < 1)
+ fun_l12_n227(x)
+ else
+ fun_l12_n659(x)
+ end
+end
+
+def fun_l11_n903(x)
+ if (x < 1)
+ fun_l12_n224(x)
+ else
+ fun_l12_n23(x)
+ end
+end
+
+def fun_l11_n904(x)
+ if (x < 1)
+ fun_l12_n494(x)
+ else
+ fun_l12_n292(x)
+ end
+end
+
+def fun_l11_n905(x)
+ if (x < 1)
+ fun_l12_n309(x)
+ else
+ fun_l12_n949(x)
+ end
+end
+
+def fun_l11_n906(x)
+ if (x < 1)
+ fun_l12_n960(x)
+ else
+ fun_l12_n24(x)
+ end
+end
+
+def fun_l11_n907(x)
+ if (x < 1)
+ fun_l12_n98(x)
+ else
+ fun_l12_n674(x)
+ end
+end
+
+def fun_l11_n908(x)
+ if (x < 1)
+ fun_l12_n84(x)
+ else
+ fun_l12_n307(x)
+ end
+end
+
+def fun_l11_n909(x)
+ if (x < 1)
+ fun_l12_n786(x)
+ else
+ fun_l12_n311(x)
+ end
+end
+
+def fun_l11_n910(x)
+ if (x < 1)
+ fun_l12_n631(x)
+ else
+ fun_l12_n605(x)
+ end
+end
+
+def fun_l11_n911(x)
+ if (x < 1)
+ fun_l12_n352(x)
+ else
+ fun_l12_n750(x)
+ end
+end
+
+def fun_l11_n912(x)
+ if (x < 1)
+ fun_l12_n75(x)
+ else
+ fun_l12_n112(x)
+ end
+end
+
+def fun_l11_n913(x)
+ if (x < 1)
+ fun_l12_n404(x)
+ else
+ fun_l12_n995(x)
+ end
+end
+
+def fun_l11_n914(x)
+ if (x < 1)
+ fun_l12_n656(x)
+ else
+ fun_l12_n203(x)
+ end
+end
+
+def fun_l11_n915(x)
+ if (x < 1)
+ fun_l12_n625(x)
+ else
+ fun_l12_n32(x)
+ end
+end
+
+def fun_l11_n916(x)
+ if (x < 1)
+ fun_l12_n785(x)
+ else
+ fun_l12_n237(x)
+ end
+end
+
+def fun_l11_n917(x)
+ if (x < 1)
+ fun_l12_n643(x)
+ else
+ fun_l12_n364(x)
+ end
+end
+
+def fun_l11_n918(x)
+ if (x < 1)
+ fun_l12_n920(x)
+ else
+ fun_l12_n957(x)
+ end
+end
+
+def fun_l11_n919(x)
+ if (x < 1)
+ fun_l12_n336(x)
+ else
+ fun_l12_n726(x)
+ end
+end
+
+def fun_l11_n920(x)
+ if (x < 1)
+ fun_l12_n329(x)
+ else
+ fun_l12_n15(x)
+ end
+end
+
+def fun_l11_n921(x)
+ if (x < 1)
+ fun_l12_n911(x)
+ else
+ fun_l12_n824(x)
+ end
+end
+
+def fun_l11_n922(x)
+ if (x < 1)
+ fun_l12_n907(x)
+ else
+ fun_l12_n854(x)
+ end
+end
+
+def fun_l11_n923(x)
+ if (x < 1)
+ fun_l12_n779(x)
+ else
+ fun_l12_n549(x)
+ end
+end
+
+def fun_l11_n924(x)
+ if (x < 1)
+ fun_l12_n833(x)
+ else
+ fun_l12_n986(x)
+ end
+end
+
+def fun_l11_n925(x)
+ if (x < 1)
+ fun_l12_n450(x)
+ else
+ fun_l12_n783(x)
+ end
+end
+
+def fun_l11_n926(x)
+ if (x < 1)
+ fun_l12_n405(x)
+ else
+ fun_l12_n960(x)
+ end
+end
+
+def fun_l11_n927(x)
+ if (x < 1)
+ fun_l12_n603(x)
+ else
+ fun_l12_n892(x)
+ end
+end
+
+def fun_l11_n928(x)
+ if (x < 1)
+ fun_l12_n137(x)
+ else
+ fun_l12_n200(x)
+ end
+end
+
+def fun_l11_n929(x)
+ if (x < 1)
+ fun_l12_n161(x)
+ else
+ fun_l12_n754(x)
+ end
+end
+
+def fun_l11_n930(x)
+ if (x < 1)
+ fun_l12_n107(x)
+ else
+ fun_l12_n258(x)
+ end
+end
+
+def fun_l11_n931(x)
+ if (x < 1)
+ fun_l12_n794(x)
+ else
+ fun_l12_n812(x)
+ end
+end
+
+def fun_l11_n932(x)
+ if (x < 1)
+ fun_l12_n956(x)
+ else
+ fun_l12_n156(x)
+ end
+end
+
+def fun_l11_n933(x)
+ if (x < 1)
+ fun_l12_n676(x)
+ else
+ fun_l12_n496(x)
+ end
+end
+
+def fun_l11_n934(x)
+ if (x < 1)
+ fun_l12_n229(x)
+ else
+ fun_l12_n339(x)
+ end
+end
+
+def fun_l11_n935(x)
+ if (x < 1)
+ fun_l12_n353(x)
+ else
+ fun_l12_n430(x)
+ end
+end
+
+def fun_l11_n936(x)
+ if (x < 1)
+ fun_l12_n721(x)
+ else
+ fun_l12_n409(x)
+ end
+end
+
+def fun_l11_n937(x)
+ if (x < 1)
+ fun_l12_n151(x)
+ else
+ fun_l12_n60(x)
+ end
+end
+
+def fun_l11_n938(x)
+ if (x < 1)
+ fun_l12_n362(x)
+ else
+ fun_l12_n92(x)
+ end
+end
+
+def fun_l11_n939(x)
+ if (x < 1)
+ fun_l12_n315(x)
+ else
+ fun_l12_n905(x)
+ end
+end
+
+def fun_l11_n940(x)
+ if (x < 1)
+ fun_l12_n788(x)
+ else
+ fun_l12_n105(x)
+ end
+end
+
+def fun_l11_n941(x)
+ if (x < 1)
+ fun_l12_n124(x)
+ else
+ fun_l12_n496(x)
+ end
+end
+
+def fun_l11_n942(x)
+ if (x < 1)
+ fun_l12_n546(x)
+ else
+ fun_l12_n17(x)
+ end
+end
+
+def fun_l11_n943(x)
+ if (x < 1)
+ fun_l12_n594(x)
+ else
+ fun_l12_n55(x)
+ end
+end
+
+def fun_l11_n944(x)
+ if (x < 1)
+ fun_l12_n187(x)
+ else
+ fun_l12_n139(x)
+ end
+end
+
+def fun_l11_n945(x)
+ if (x < 1)
+ fun_l12_n117(x)
+ else
+ fun_l12_n382(x)
+ end
+end
+
+def fun_l11_n946(x)
+ if (x < 1)
+ fun_l12_n579(x)
+ else
+ fun_l12_n895(x)
+ end
+end
+
+def fun_l11_n947(x)
+ if (x < 1)
+ fun_l12_n541(x)
+ else
+ fun_l12_n497(x)
+ end
+end
+
+def fun_l11_n948(x)
+ if (x < 1)
+ fun_l12_n250(x)
+ else
+ fun_l12_n257(x)
+ end
+end
+
+def fun_l11_n949(x)
+ if (x < 1)
+ fun_l12_n553(x)
+ else
+ fun_l12_n663(x)
+ end
+end
+
+def fun_l11_n950(x)
+ if (x < 1)
+ fun_l12_n779(x)
+ else
+ fun_l12_n414(x)
+ end
+end
+
+def fun_l11_n951(x)
+ if (x < 1)
+ fun_l12_n748(x)
+ else
+ fun_l12_n525(x)
+ end
+end
+
+def fun_l11_n952(x)
+ if (x < 1)
+ fun_l12_n669(x)
+ else
+ fun_l12_n339(x)
+ end
+end
+
+def fun_l11_n953(x)
+ if (x < 1)
+ fun_l12_n665(x)
+ else
+ fun_l12_n996(x)
+ end
+end
+
+def fun_l11_n954(x)
+ if (x < 1)
+ fun_l12_n366(x)
+ else
+ fun_l12_n149(x)
+ end
+end
+
+def fun_l11_n955(x)
+ if (x < 1)
+ fun_l12_n549(x)
+ else
+ fun_l12_n414(x)
+ end
+end
+
+def fun_l11_n956(x)
+ if (x < 1)
+ fun_l12_n258(x)
+ else
+ fun_l12_n67(x)
+ end
+end
+
+def fun_l11_n957(x)
+ if (x < 1)
+ fun_l12_n439(x)
+ else
+ fun_l12_n83(x)
+ end
+end
+
+def fun_l11_n958(x)
+ if (x < 1)
+ fun_l12_n601(x)
+ else
+ fun_l12_n938(x)
+ end
+end
+
+def fun_l11_n959(x)
+ if (x < 1)
+ fun_l12_n953(x)
+ else
+ fun_l12_n973(x)
+ end
+end
+
+def fun_l11_n960(x)
+ if (x < 1)
+ fun_l12_n426(x)
+ else
+ fun_l12_n8(x)
+ end
+end
+
+def fun_l11_n961(x)
+ if (x < 1)
+ fun_l12_n719(x)
+ else
+ fun_l12_n657(x)
+ end
+end
+
+def fun_l11_n962(x)
+ if (x < 1)
+ fun_l12_n391(x)
+ else
+ fun_l12_n992(x)
+ end
+end
+
+def fun_l11_n963(x)
+ if (x < 1)
+ fun_l12_n141(x)
+ else
+ fun_l12_n468(x)
+ end
+end
+
+def fun_l11_n964(x)
+ if (x < 1)
+ fun_l12_n463(x)
+ else
+ fun_l12_n94(x)
+ end
+end
+
+def fun_l11_n965(x)
+ if (x < 1)
+ fun_l12_n765(x)
+ else
+ fun_l12_n168(x)
+ end
+end
+
+def fun_l11_n966(x)
+ if (x < 1)
+ fun_l12_n237(x)
+ else
+ fun_l12_n437(x)
+ end
+end
+
+def fun_l11_n967(x)
+ if (x < 1)
+ fun_l12_n741(x)
+ else
+ fun_l12_n331(x)
+ end
+end
+
+def fun_l11_n968(x)
+ if (x < 1)
+ fun_l12_n617(x)
+ else
+ fun_l12_n773(x)
+ end
+end
+
+def fun_l11_n969(x)
+ if (x < 1)
+ fun_l12_n880(x)
+ else
+ fun_l12_n727(x)
+ end
+end
+
+def fun_l11_n970(x)
+ if (x < 1)
+ fun_l12_n781(x)
+ else
+ fun_l12_n270(x)
+ end
+end
+
+def fun_l11_n971(x)
+ if (x < 1)
+ fun_l12_n511(x)
+ else
+ fun_l12_n183(x)
+ end
+end
+
+def fun_l11_n972(x)
+ if (x < 1)
+ fun_l12_n448(x)
+ else
+ fun_l12_n965(x)
+ end
+end
+
+def fun_l11_n973(x)
+ if (x < 1)
+ fun_l12_n816(x)
+ else
+ fun_l12_n974(x)
+ end
+end
+
+def fun_l11_n974(x)
+ if (x < 1)
+ fun_l12_n583(x)
+ else
+ fun_l12_n731(x)
+ end
+end
+
+def fun_l11_n975(x)
+ if (x < 1)
+ fun_l12_n42(x)
+ else
+ fun_l12_n463(x)
+ end
+end
+
+def fun_l11_n976(x)
+ if (x < 1)
+ fun_l12_n267(x)
+ else
+ fun_l12_n769(x)
+ end
+end
+
+def fun_l11_n977(x)
+ if (x < 1)
+ fun_l12_n993(x)
+ else
+ fun_l12_n391(x)
+ end
+end
+
+def fun_l11_n978(x)
+ if (x < 1)
+ fun_l12_n507(x)
+ else
+ fun_l12_n905(x)
+ end
+end
+
+def fun_l11_n979(x)
+ if (x < 1)
+ fun_l12_n486(x)
+ else
+ fun_l12_n562(x)
+ end
+end
+
+def fun_l11_n980(x)
+ if (x < 1)
+ fun_l12_n252(x)
+ else
+ fun_l12_n475(x)
+ end
+end
+
+def fun_l11_n981(x)
+ if (x < 1)
+ fun_l12_n979(x)
+ else
+ fun_l12_n70(x)
+ end
+end
+
+def fun_l11_n982(x)
+ if (x < 1)
+ fun_l12_n11(x)
+ else
+ fun_l12_n483(x)
+ end
+end
+
+def fun_l11_n983(x)
+ if (x < 1)
+ fun_l12_n208(x)
+ else
+ fun_l12_n315(x)
+ end
+end
+
+def fun_l11_n984(x)
+ if (x < 1)
+ fun_l12_n452(x)
+ else
+ fun_l12_n367(x)
+ end
+end
+
+def fun_l11_n985(x)
+ if (x < 1)
+ fun_l12_n937(x)
+ else
+ fun_l12_n33(x)
+ end
+end
+
+def fun_l11_n986(x)
+ if (x < 1)
+ fun_l12_n227(x)
+ else
+ fun_l12_n448(x)
+ end
+end
+
+def fun_l11_n987(x)
+ if (x < 1)
+ fun_l12_n928(x)
+ else
+ fun_l12_n693(x)
+ end
+end
+
+def fun_l11_n988(x)
+ if (x < 1)
+ fun_l12_n731(x)
+ else
+ fun_l12_n872(x)
+ end
+end
+
+def fun_l11_n989(x)
+ if (x < 1)
+ fun_l12_n355(x)
+ else
+ fun_l12_n0(x)
+ end
+end
+
+def fun_l11_n990(x)
+ if (x < 1)
+ fun_l12_n203(x)
+ else
+ fun_l12_n545(x)
+ end
+end
+
+def fun_l11_n991(x)
+ if (x < 1)
+ fun_l12_n237(x)
+ else
+ fun_l12_n186(x)
+ end
+end
+
+def fun_l11_n992(x)
+ if (x < 1)
+ fun_l12_n22(x)
+ else
+ fun_l12_n597(x)
+ end
+end
+
+def fun_l11_n993(x)
+ if (x < 1)
+ fun_l12_n711(x)
+ else
+ fun_l12_n677(x)
+ end
+end
+
+def fun_l11_n994(x)
+ if (x < 1)
+ fun_l12_n892(x)
+ else
+ fun_l12_n729(x)
+ end
+end
+
+def fun_l11_n995(x)
+ if (x < 1)
+ fun_l12_n51(x)
+ else
+ fun_l12_n279(x)
+ end
+end
+
+def fun_l11_n996(x)
+ if (x < 1)
+ fun_l12_n430(x)
+ else
+ fun_l12_n527(x)
+ end
+end
+
+def fun_l11_n997(x)
+ if (x < 1)
+ fun_l12_n153(x)
+ else
+ fun_l12_n366(x)
+ end
+end
+
+def fun_l11_n998(x)
+ if (x < 1)
+ fun_l12_n574(x)
+ else
+ fun_l12_n432(x)
+ end
+end
+
+def fun_l11_n999(x)
+ if (x < 1)
+ fun_l12_n100(x)
+ else
+ fun_l12_n943(x)
+ end
+end
+
+def fun_l12_n0(x)
+ if (x < 1)
+ fun_l13_n874(x)
+ else
+ fun_l13_n769(x)
+ end
+end
+
+def fun_l12_n1(x)
+ if (x < 1)
+ fun_l13_n354(x)
+ else
+ fun_l13_n103(x)
+ end
+end
+
+def fun_l12_n2(x)
+ if (x < 1)
+ fun_l13_n265(x)
+ else
+ fun_l13_n936(x)
+ end
+end
+
+def fun_l12_n3(x)
+ if (x < 1)
+ fun_l13_n683(x)
+ else
+ fun_l13_n607(x)
+ end
+end
+
+def fun_l12_n4(x)
+ if (x < 1)
+ fun_l13_n398(x)
+ else
+ fun_l13_n902(x)
+ end
+end
+
+def fun_l12_n5(x)
+ if (x < 1)
+ fun_l13_n694(x)
+ else
+ fun_l13_n392(x)
+ end
+end
+
+def fun_l12_n6(x)
+ if (x < 1)
+ fun_l13_n170(x)
+ else
+ fun_l13_n207(x)
+ end
+end
+
+def fun_l12_n7(x)
+ if (x < 1)
+ fun_l13_n978(x)
+ else
+ fun_l13_n368(x)
+ end
+end
+
+def fun_l12_n8(x)
+ if (x < 1)
+ fun_l13_n970(x)
+ else
+ fun_l13_n560(x)
+ end
+end
+
+def fun_l12_n9(x)
+ if (x < 1)
+ fun_l13_n56(x)
+ else
+ fun_l13_n697(x)
+ end
+end
+
+def fun_l12_n10(x)
+ if (x < 1)
+ fun_l13_n860(x)
+ else
+ fun_l13_n407(x)
+ end
+end
+
+def fun_l12_n11(x)
+ if (x < 1)
+ fun_l13_n581(x)
+ else
+ fun_l13_n582(x)
+ end
+end
+
+def fun_l12_n12(x)
+ if (x < 1)
+ fun_l13_n835(x)
+ else
+ fun_l13_n706(x)
+ end
+end
+
+def fun_l12_n13(x)
+ if (x < 1)
+ fun_l13_n862(x)
+ else
+ fun_l13_n89(x)
+ end
+end
+
+def fun_l12_n14(x)
+ if (x < 1)
+ fun_l13_n379(x)
+ else
+ fun_l13_n896(x)
+ end
+end
+
+def fun_l12_n15(x)
+ if (x < 1)
+ fun_l13_n175(x)
+ else
+ fun_l13_n113(x)
+ end
+end
+
+def fun_l12_n16(x)
+ if (x < 1)
+ fun_l13_n553(x)
+ else
+ fun_l13_n935(x)
+ end
+end
+
+def fun_l12_n17(x)
+ if (x < 1)
+ fun_l13_n171(x)
+ else
+ fun_l13_n264(x)
+ end
+end
+
+def fun_l12_n18(x)
+ if (x < 1)
+ fun_l13_n61(x)
+ else
+ fun_l13_n412(x)
+ end
+end
+
+def fun_l12_n19(x)
+ if (x < 1)
+ fun_l13_n213(x)
+ else
+ fun_l13_n422(x)
+ end
+end
+
+def fun_l12_n20(x)
+ if (x < 1)
+ fun_l13_n401(x)
+ else
+ fun_l13_n537(x)
+ end
+end
+
+def fun_l12_n21(x)
+ if (x < 1)
+ fun_l13_n207(x)
+ else
+ fun_l13_n495(x)
+ end
+end
+
+def fun_l12_n22(x)
+ if (x < 1)
+ fun_l13_n941(x)
+ else
+ fun_l13_n466(x)
+ end
+end
+
+def fun_l12_n23(x)
+ if (x < 1)
+ fun_l13_n195(x)
+ else
+ fun_l13_n984(x)
+ end
+end
+
+def fun_l12_n24(x)
+ if (x < 1)
+ fun_l13_n106(x)
+ else
+ fun_l13_n812(x)
+ end
+end
+
+def fun_l12_n25(x)
+ if (x < 1)
+ fun_l13_n979(x)
+ else
+ fun_l13_n902(x)
+ end
+end
+
+def fun_l12_n26(x)
+ if (x < 1)
+ fun_l13_n726(x)
+ else
+ fun_l13_n440(x)
+ end
+end
+
+def fun_l12_n27(x)
+ if (x < 1)
+ fun_l13_n229(x)
+ else
+ fun_l13_n995(x)
+ end
+end
+
+def fun_l12_n28(x)
+ if (x < 1)
+ fun_l13_n764(x)
+ else
+ fun_l13_n333(x)
+ end
+end
+
+def fun_l12_n29(x)
+ if (x < 1)
+ fun_l13_n971(x)
+ else
+ fun_l13_n59(x)
+ end
+end
+
+def fun_l12_n30(x)
+ if (x < 1)
+ fun_l13_n731(x)
+ else
+ fun_l13_n138(x)
+ end
+end
+
+def fun_l12_n31(x)
+ if (x < 1)
+ fun_l13_n591(x)
+ else
+ fun_l13_n473(x)
+ end
+end
+
+def fun_l12_n32(x)
+ if (x < 1)
+ fun_l13_n50(x)
+ else
+ fun_l13_n175(x)
+ end
+end
+
+def fun_l12_n33(x)
+ if (x < 1)
+ fun_l13_n26(x)
+ else
+ fun_l13_n867(x)
+ end
+end
+
+def fun_l12_n34(x)
+ if (x < 1)
+ fun_l13_n349(x)
+ else
+ fun_l13_n332(x)
+ end
+end
+
+def fun_l12_n35(x)
+ if (x < 1)
+ fun_l13_n180(x)
+ else
+ fun_l13_n591(x)
+ end
+end
+
+def fun_l12_n36(x)
+ if (x < 1)
+ fun_l13_n339(x)
+ else
+ fun_l13_n354(x)
+ end
+end
+
+def fun_l12_n37(x)
+ if (x < 1)
+ fun_l13_n289(x)
+ else
+ fun_l13_n101(x)
+ end
+end
+
+def fun_l12_n38(x)
+ if (x < 1)
+ fun_l13_n410(x)
+ else
+ fun_l13_n91(x)
+ end
+end
+
+def fun_l12_n39(x)
+ if (x < 1)
+ fun_l13_n617(x)
+ else
+ fun_l13_n716(x)
+ end
+end
+
+def fun_l12_n40(x)
+ if (x < 1)
+ fun_l13_n116(x)
+ else
+ fun_l13_n875(x)
+ end
+end
+
+def fun_l12_n41(x)
+ if (x < 1)
+ fun_l13_n162(x)
+ else
+ fun_l13_n844(x)
+ end
+end
+
+def fun_l12_n42(x)
+ if (x < 1)
+ fun_l13_n79(x)
+ else
+ fun_l13_n589(x)
+ end
+end
+
+def fun_l12_n43(x)
+ if (x < 1)
+ fun_l13_n835(x)
+ else
+ fun_l13_n21(x)
+ end
+end
+
+def fun_l12_n44(x)
+ if (x < 1)
+ fun_l13_n420(x)
+ else
+ fun_l13_n403(x)
+ end
+end
+
+def fun_l12_n45(x)
+ if (x < 1)
+ fun_l13_n203(x)
+ else
+ fun_l13_n890(x)
+ end
+end
+
+def fun_l12_n46(x)
+ if (x < 1)
+ fun_l13_n529(x)
+ else
+ fun_l13_n717(x)
+ end
+end
+
+def fun_l12_n47(x)
+ if (x < 1)
+ fun_l13_n766(x)
+ else
+ fun_l13_n635(x)
+ end
+end
+
+def fun_l12_n48(x)
+ if (x < 1)
+ fun_l13_n223(x)
+ else
+ fun_l13_n460(x)
+ end
+end
+
+def fun_l12_n49(x)
+ if (x < 1)
+ fun_l13_n799(x)
+ else
+ fun_l13_n397(x)
+ end
+end
+
+def fun_l12_n50(x)
+ if (x < 1)
+ fun_l13_n200(x)
+ else
+ fun_l13_n608(x)
+ end
+end
+
+def fun_l12_n51(x)
+ if (x < 1)
+ fun_l13_n212(x)
+ else
+ fun_l13_n612(x)
+ end
+end
+
+def fun_l12_n52(x)
+ if (x < 1)
+ fun_l13_n271(x)
+ else
+ fun_l13_n324(x)
+ end
+end
+
+def fun_l12_n53(x)
+ if (x < 1)
+ fun_l13_n639(x)
+ else
+ fun_l13_n603(x)
+ end
+end
+
+def fun_l12_n54(x)
+ if (x < 1)
+ fun_l13_n125(x)
+ else
+ fun_l13_n726(x)
+ end
+end
+
+def fun_l12_n55(x)
+ if (x < 1)
+ fun_l13_n266(x)
+ else
+ fun_l13_n552(x)
+ end
+end
+
+def fun_l12_n56(x)
+ if (x < 1)
+ fun_l13_n412(x)
+ else
+ fun_l13_n132(x)
+ end
+end
+
+def fun_l12_n57(x)
+ if (x < 1)
+ fun_l13_n235(x)
+ else
+ fun_l13_n892(x)
+ end
+end
+
+def fun_l12_n58(x)
+ if (x < 1)
+ fun_l13_n515(x)
+ else
+ fun_l13_n465(x)
+ end
+end
+
+def fun_l12_n59(x)
+ if (x < 1)
+ fun_l13_n38(x)
+ else
+ fun_l13_n757(x)
+ end
+end
+
+def fun_l12_n60(x)
+ if (x < 1)
+ fun_l13_n544(x)
+ else
+ fun_l13_n794(x)
+ end
+end
+
+def fun_l12_n61(x)
+ if (x < 1)
+ fun_l13_n622(x)
+ else
+ fun_l13_n340(x)
+ end
+end
+
+def fun_l12_n62(x)
+ if (x < 1)
+ fun_l13_n563(x)
+ else
+ fun_l13_n313(x)
+ end
+end
+
+def fun_l12_n63(x)
+ if (x < 1)
+ fun_l13_n936(x)
+ else
+ fun_l13_n38(x)
+ end
+end
+
+def fun_l12_n64(x)
+ if (x < 1)
+ fun_l13_n951(x)
+ else
+ fun_l13_n543(x)
+ end
+end
+
+def fun_l12_n65(x)
+ if (x < 1)
+ fun_l13_n577(x)
+ else
+ fun_l13_n190(x)
+ end
+end
+
+def fun_l12_n66(x)
+ if (x < 1)
+ fun_l13_n649(x)
+ else
+ fun_l13_n887(x)
+ end
+end
+
+def fun_l12_n67(x)
+ if (x < 1)
+ fun_l13_n218(x)
+ else
+ fun_l13_n200(x)
+ end
+end
+
+def fun_l12_n68(x)
+ if (x < 1)
+ fun_l13_n111(x)
+ else
+ fun_l13_n849(x)
+ end
+end
+
+def fun_l12_n69(x)
+ if (x < 1)
+ fun_l13_n431(x)
+ else
+ fun_l13_n816(x)
+ end
+end
+
+def fun_l12_n70(x)
+ if (x < 1)
+ fun_l13_n970(x)
+ else
+ fun_l13_n545(x)
+ end
+end
+
+def fun_l12_n71(x)
+ if (x < 1)
+ fun_l13_n3(x)
+ else
+ fun_l13_n751(x)
+ end
+end
+
+def fun_l12_n72(x)
+ if (x < 1)
+ fun_l13_n58(x)
+ else
+ fun_l13_n994(x)
+ end
+end
+
+def fun_l12_n73(x)
+ if (x < 1)
+ fun_l13_n397(x)
+ else
+ fun_l13_n783(x)
+ end
+end
+
+def fun_l12_n74(x)
+ if (x < 1)
+ fun_l13_n705(x)
+ else
+ fun_l13_n318(x)
+ end
+end
+
+def fun_l12_n75(x)
+ if (x < 1)
+ fun_l13_n406(x)
+ else
+ fun_l13_n880(x)
+ end
+end
+
+def fun_l12_n76(x)
+ if (x < 1)
+ fun_l13_n867(x)
+ else
+ fun_l13_n234(x)
+ end
+end
+
+def fun_l12_n77(x)
+ if (x < 1)
+ fun_l13_n447(x)
+ else
+ fun_l13_n617(x)
+ end
+end
+
+def fun_l12_n78(x)
+ if (x < 1)
+ fun_l13_n631(x)
+ else
+ fun_l13_n687(x)
+ end
+end
+
+def fun_l12_n79(x)
+ if (x < 1)
+ fun_l13_n735(x)
+ else
+ fun_l13_n512(x)
+ end
+end
+
+def fun_l12_n80(x)
+ if (x < 1)
+ fun_l13_n826(x)
+ else
+ fun_l13_n626(x)
+ end
+end
+
+def fun_l12_n81(x)
+ if (x < 1)
+ fun_l13_n959(x)
+ else
+ fun_l13_n357(x)
+ end
+end
+
+def fun_l12_n82(x)
+ if (x < 1)
+ fun_l13_n17(x)
+ else
+ fun_l13_n722(x)
+ end
+end
+
+def fun_l12_n83(x)
+ if (x < 1)
+ fun_l13_n702(x)
+ else
+ fun_l13_n441(x)
+ end
+end
+
+def fun_l12_n84(x)
+ if (x < 1)
+ fun_l13_n939(x)
+ else
+ fun_l13_n972(x)
+ end
+end
+
+def fun_l12_n85(x)
+ if (x < 1)
+ fun_l13_n747(x)
+ else
+ fun_l13_n481(x)
+ end
+end
+
+def fun_l12_n86(x)
+ if (x < 1)
+ fun_l13_n813(x)
+ else
+ fun_l13_n780(x)
+ end
+end
+
+def fun_l12_n87(x)
+ if (x < 1)
+ fun_l13_n87(x)
+ else
+ fun_l13_n19(x)
+ end
+end
+
+def fun_l12_n88(x)
+ if (x < 1)
+ fun_l13_n422(x)
+ else
+ fun_l13_n938(x)
+ end
+end
+
+def fun_l12_n89(x)
+ if (x < 1)
+ fun_l13_n575(x)
+ else
+ fun_l13_n150(x)
+ end
+end
+
+def fun_l12_n90(x)
+ if (x < 1)
+ fun_l13_n294(x)
+ else
+ fun_l13_n666(x)
+ end
+end
+
+def fun_l12_n91(x)
+ if (x < 1)
+ fun_l13_n216(x)
+ else
+ fun_l13_n315(x)
+ end
+end
+
+def fun_l12_n92(x)
+ if (x < 1)
+ fun_l13_n580(x)
+ else
+ fun_l13_n487(x)
+ end
+end
+
+def fun_l12_n93(x)
+ if (x < 1)
+ fun_l13_n500(x)
+ else
+ fun_l13_n2(x)
+ end
+end
+
+def fun_l12_n94(x)
+ if (x < 1)
+ fun_l13_n362(x)
+ else
+ fun_l13_n69(x)
+ end
+end
+
+def fun_l12_n95(x)
+ if (x < 1)
+ fun_l13_n50(x)
+ else
+ fun_l13_n549(x)
+ end
+end
+
+def fun_l12_n96(x)
+ if (x < 1)
+ fun_l13_n407(x)
+ else
+ fun_l13_n935(x)
+ end
+end
+
+def fun_l12_n97(x)
+ if (x < 1)
+ fun_l13_n715(x)
+ else
+ fun_l13_n70(x)
+ end
+end
+
+def fun_l12_n98(x)
+ if (x < 1)
+ fun_l13_n184(x)
+ else
+ fun_l13_n702(x)
+ end
+end
+
+def fun_l12_n99(x)
+ if (x < 1)
+ fun_l13_n612(x)
+ else
+ fun_l13_n972(x)
+ end
+end
+
+def fun_l12_n100(x)
+ if (x < 1)
+ fun_l13_n778(x)
+ else
+ fun_l13_n458(x)
+ end
+end
+
+def fun_l12_n101(x)
+ if (x < 1)
+ fun_l13_n387(x)
+ else
+ fun_l13_n783(x)
+ end
+end
+
+def fun_l12_n102(x)
+ if (x < 1)
+ fun_l13_n764(x)
+ else
+ fun_l13_n647(x)
+ end
+end
+
+def fun_l12_n103(x)
+ if (x < 1)
+ fun_l13_n310(x)
+ else
+ fun_l13_n46(x)
+ end
+end
+
+def fun_l12_n104(x)
+ if (x < 1)
+ fun_l13_n643(x)
+ else
+ fun_l13_n479(x)
+ end
+end
+
+def fun_l12_n105(x)
+ if (x < 1)
+ fun_l13_n909(x)
+ else
+ fun_l13_n10(x)
+ end
+end
+
+def fun_l12_n106(x)
+ if (x < 1)
+ fun_l13_n181(x)
+ else
+ fun_l13_n671(x)
+ end
+end
+
+def fun_l12_n107(x)
+ if (x < 1)
+ fun_l13_n592(x)
+ else
+ fun_l13_n421(x)
+ end
+end
+
+def fun_l12_n108(x)
+ if (x < 1)
+ fun_l13_n438(x)
+ else
+ fun_l13_n196(x)
+ end
+end
+
+def fun_l12_n109(x)
+ if (x < 1)
+ fun_l13_n605(x)
+ else
+ fun_l13_n529(x)
+ end
+end
+
+def fun_l12_n110(x)
+ if (x < 1)
+ fun_l13_n31(x)
+ else
+ fun_l13_n769(x)
+ end
+end
+
+def fun_l12_n111(x)
+ if (x < 1)
+ fun_l13_n790(x)
+ else
+ fun_l13_n773(x)
+ end
+end
+
+def fun_l12_n112(x)
+ if (x < 1)
+ fun_l13_n778(x)
+ else
+ fun_l13_n621(x)
+ end
+end
+
+def fun_l12_n113(x)
+ if (x < 1)
+ fun_l13_n892(x)
+ else
+ fun_l13_n413(x)
+ end
+end
+
+def fun_l12_n114(x)
+ if (x < 1)
+ fun_l13_n675(x)
+ else
+ fun_l13_n124(x)
+ end
+end
+
+def fun_l12_n115(x)
+ if (x < 1)
+ fun_l13_n366(x)
+ else
+ fun_l13_n884(x)
+ end
+end
+
+def fun_l12_n116(x)
+ if (x < 1)
+ fun_l13_n552(x)
+ else
+ fun_l13_n769(x)
+ end
+end
+
+def fun_l12_n117(x)
+ if (x < 1)
+ fun_l13_n11(x)
+ else
+ fun_l13_n46(x)
+ end
+end
+
+def fun_l12_n118(x)
+ if (x < 1)
+ fun_l13_n766(x)
+ else
+ fun_l13_n914(x)
+ end
+end
+
+def fun_l12_n119(x)
+ if (x < 1)
+ fun_l13_n980(x)
+ else
+ fun_l13_n956(x)
+ end
+end
+
+def fun_l12_n120(x)
+ if (x < 1)
+ fun_l13_n668(x)
+ else
+ fun_l13_n532(x)
+ end
+end
+
+def fun_l12_n121(x)
+ if (x < 1)
+ fun_l13_n864(x)
+ else
+ fun_l13_n489(x)
+ end
+end
+
+def fun_l12_n122(x)
+ if (x < 1)
+ fun_l13_n581(x)
+ else
+ fun_l13_n33(x)
+ end
+end
+
+def fun_l12_n123(x)
+ if (x < 1)
+ fun_l13_n188(x)
+ else
+ fun_l13_n652(x)
+ end
+end
+
+def fun_l12_n124(x)
+ if (x < 1)
+ fun_l13_n631(x)
+ else
+ fun_l13_n932(x)
+ end
+end
+
+def fun_l12_n125(x)
+ if (x < 1)
+ fun_l13_n646(x)
+ else
+ fun_l13_n525(x)
+ end
+end
+
+def fun_l12_n126(x)
+ if (x < 1)
+ fun_l13_n878(x)
+ else
+ fun_l13_n98(x)
+ end
+end
+
+def fun_l12_n127(x)
+ if (x < 1)
+ fun_l13_n120(x)
+ else
+ fun_l13_n950(x)
+ end
+end
+
+def fun_l12_n128(x)
+ if (x < 1)
+ fun_l13_n405(x)
+ else
+ fun_l13_n60(x)
+ end
+end
+
+def fun_l12_n129(x)
+ if (x < 1)
+ fun_l13_n635(x)
+ else
+ fun_l13_n992(x)
+ end
+end
+
+def fun_l12_n130(x)
+ if (x < 1)
+ fun_l13_n711(x)
+ else
+ fun_l13_n172(x)
+ end
+end
+
+def fun_l12_n131(x)
+ if (x < 1)
+ fun_l13_n2(x)
+ else
+ fun_l13_n328(x)
+ end
+end
+
+def fun_l12_n132(x)
+ if (x < 1)
+ fun_l13_n506(x)
+ else
+ fun_l13_n258(x)
+ end
+end
+
+def fun_l12_n133(x)
+ if (x < 1)
+ fun_l13_n737(x)
+ else
+ fun_l13_n552(x)
+ end
+end
+
+def fun_l12_n134(x)
+ if (x < 1)
+ fun_l13_n596(x)
+ else
+ fun_l13_n475(x)
+ end
+end
+
+def fun_l12_n135(x)
+ if (x < 1)
+ fun_l13_n751(x)
+ else
+ fun_l13_n610(x)
+ end
+end
+
+def fun_l12_n136(x)
+ if (x < 1)
+ fun_l13_n778(x)
+ else
+ fun_l13_n719(x)
+ end
+end
+
+def fun_l12_n137(x)
+ if (x < 1)
+ fun_l13_n779(x)
+ else
+ fun_l13_n204(x)
+ end
+end
+
+def fun_l12_n138(x)
+ if (x < 1)
+ fun_l13_n765(x)
+ else
+ fun_l13_n280(x)
+ end
+end
+
+def fun_l12_n139(x)
+ if (x < 1)
+ fun_l13_n896(x)
+ else
+ fun_l13_n558(x)
+ end
+end
+
+def fun_l12_n140(x)
+ if (x < 1)
+ fun_l13_n16(x)
+ else
+ fun_l13_n809(x)
+ end
+end
+
+def fun_l12_n141(x)
+ if (x < 1)
+ fun_l13_n182(x)
+ else
+ fun_l13_n960(x)
+ end
+end
+
+def fun_l12_n142(x)
+ if (x < 1)
+ fun_l13_n196(x)
+ else
+ fun_l13_n794(x)
+ end
+end
+
+def fun_l12_n143(x)
+ if (x < 1)
+ fun_l13_n993(x)
+ else
+ fun_l13_n426(x)
+ end
+end
+
+def fun_l12_n144(x)
+ if (x < 1)
+ fun_l13_n926(x)
+ else
+ fun_l13_n554(x)
+ end
+end
+
+def fun_l12_n145(x)
+ if (x < 1)
+ fun_l13_n839(x)
+ else
+ fun_l13_n987(x)
+ end
+end
+
+def fun_l12_n146(x)
+ if (x < 1)
+ fun_l13_n412(x)
+ else
+ fun_l13_n359(x)
+ end
+end
+
+def fun_l12_n147(x)
+ if (x < 1)
+ fun_l13_n147(x)
+ else
+ fun_l13_n640(x)
+ end
+end
+
+def fun_l12_n148(x)
+ if (x < 1)
+ fun_l13_n831(x)
+ else
+ fun_l13_n862(x)
+ end
+end
+
+def fun_l12_n149(x)
+ if (x < 1)
+ fun_l13_n161(x)
+ else
+ fun_l13_n396(x)
+ end
+end
+
+def fun_l12_n150(x)
+ if (x < 1)
+ fun_l13_n734(x)
+ else
+ fun_l13_n226(x)
+ end
+end
+
+def fun_l12_n151(x)
+ if (x < 1)
+ fun_l13_n390(x)
+ else
+ fun_l13_n396(x)
+ end
+end
+
+def fun_l12_n152(x)
+ if (x < 1)
+ fun_l13_n722(x)
+ else
+ fun_l13_n939(x)
+ end
+end
+
+def fun_l12_n153(x)
+ if (x < 1)
+ fun_l13_n554(x)
+ else
+ fun_l13_n461(x)
+ end
+end
+
+def fun_l12_n154(x)
+ if (x < 1)
+ fun_l13_n223(x)
+ else
+ fun_l13_n502(x)
+ end
+end
+
+def fun_l12_n155(x)
+ if (x < 1)
+ fun_l13_n526(x)
+ else
+ fun_l13_n949(x)
+ end
+end
+
+def fun_l12_n156(x)
+ if (x < 1)
+ fun_l13_n764(x)
+ else
+ fun_l13_n290(x)
+ end
+end
+
+def fun_l12_n157(x)
+ if (x < 1)
+ fun_l13_n904(x)
+ else
+ fun_l13_n562(x)
+ end
+end
+
+def fun_l12_n158(x)
+ if (x < 1)
+ fun_l13_n308(x)
+ else
+ fun_l13_n646(x)
+ end
+end
+
+def fun_l12_n159(x)
+ if (x < 1)
+ fun_l13_n417(x)
+ else
+ fun_l13_n576(x)
+ end
+end
+
+def fun_l12_n160(x)
+ if (x < 1)
+ fun_l13_n846(x)
+ else
+ fun_l13_n989(x)
+ end
+end
+
+def fun_l12_n161(x)
+ if (x < 1)
+ fun_l13_n59(x)
+ else
+ fun_l13_n877(x)
+ end
+end
+
+def fun_l12_n162(x)
+ if (x < 1)
+ fun_l13_n194(x)
+ else
+ fun_l13_n654(x)
+ end
+end
+
+def fun_l12_n163(x)
+ if (x < 1)
+ fun_l13_n350(x)
+ else
+ fun_l13_n412(x)
+ end
+end
+
+def fun_l12_n164(x)
+ if (x < 1)
+ fun_l13_n482(x)
+ else
+ fun_l13_n820(x)
+ end
+end
+
+def fun_l12_n165(x)
+ if (x < 1)
+ fun_l13_n251(x)
+ else
+ fun_l13_n421(x)
+ end
+end
+
+def fun_l12_n166(x)
+ if (x < 1)
+ fun_l13_n832(x)
+ else
+ fun_l13_n505(x)
+ end
+end
+
+def fun_l12_n167(x)
+ if (x < 1)
+ fun_l13_n316(x)
+ else
+ fun_l13_n355(x)
+ end
+end
+
+def fun_l12_n168(x)
+ if (x < 1)
+ fun_l13_n325(x)
+ else
+ fun_l13_n755(x)
+ end
+end
+
+def fun_l12_n169(x)
+ if (x < 1)
+ fun_l13_n536(x)
+ else
+ fun_l13_n753(x)
+ end
+end
+
+def fun_l12_n170(x)
+ if (x < 1)
+ fun_l13_n819(x)
+ else
+ fun_l13_n532(x)
+ end
+end
+
+def fun_l12_n171(x)
+ if (x < 1)
+ fun_l13_n633(x)
+ else
+ fun_l13_n96(x)
+ end
+end
+
+def fun_l12_n172(x)
+ if (x < 1)
+ fun_l13_n229(x)
+ else
+ fun_l13_n105(x)
+ end
+end
+
+def fun_l12_n173(x)
+ if (x < 1)
+ fun_l13_n796(x)
+ else
+ fun_l13_n466(x)
+ end
+end
+
+def fun_l12_n174(x)
+ if (x < 1)
+ fun_l13_n520(x)
+ else
+ fun_l13_n329(x)
+ end
+end
+
+def fun_l12_n175(x)
+ if (x < 1)
+ fun_l13_n358(x)
+ else
+ fun_l13_n201(x)
+ end
+end
+
+def fun_l12_n176(x)
+ if (x < 1)
+ fun_l13_n42(x)
+ else
+ fun_l13_n649(x)
+ end
+end
+
+def fun_l12_n177(x)
+ if (x < 1)
+ fun_l13_n933(x)
+ else
+ fun_l13_n719(x)
+ end
+end
+
+def fun_l12_n178(x)
+ if (x < 1)
+ fun_l13_n236(x)
+ else
+ fun_l13_n723(x)
+ end
+end
+
+def fun_l12_n179(x)
+ if (x < 1)
+ fun_l13_n992(x)
+ else
+ fun_l13_n436(x)
+ end
+end
+
+def fun_l12_n180(x)
+ if (x < 1)
+ fun_l13_n221(x)
+ else
+ fun_l13_n294(x)
+ end
+end
+
+def fun_l12_n181(x)
+ if (x < 1)
+ fun_l13_n580(x)
+ else
+ fun_l13_n939(x)
+ end
+end
+
+def fun_l12_n182(x)
+ if (x < 1)
+ fun_l13_n608(x)
+ else
+ fun_l13_n709(x)
+ end
+end
+
+def fun_l12_n183(x)
+ if (x < 1)
+ fun_l13_n644(x)
+ else
+ fun_l13_n717(x)
+ end
+end
+
+def fun_l12_n184(x)
+ if (x < 1)
+ fun_l13_n605(x)
+ else
+ fun_l13_n665(x)
+ end
+end
+
+def fun_l12_n185(x)
+ if (x < 1)
+ fun_l13_n729(x)
+ else
+ fun_l13_n876(x)
+ end
+end
+
+def fun_l12_n186(x)
+ if (x < 1)
+ fun_l13_n43(x)
+ else
+ fun_l13_n366(x)
+ end
+end
+
+def fun_l12_n187(x)
+ if (x < 1)
+ fun_l13_n401(x)
+ else
+ fun_l13_n610(x)
+ end
+end
+
+def fun_l12_n188(x)
+ if (x < 1)
+ fun_l13_n489(x)
+ else
+ fun_l13_n107(x)
+ end
+end
+
+def fun_l12_n189(x)
+ if (x < 1)
+ fun_l13_n859(x)
+ else
+ fun_l13_n355(x)
+ end
+end
+
+def fun_l12_n190(x)
+ if (x < 1)
+ fun_l13_n631(x)
+ else
+ fun_l13_n399(x)
+ end
+end
+
+def fun_l12_n191(x)
+ if (x < 1)
+ fun_l13_n332(x)
+ else
+ fun_l13_n333(x)
+ end
+end
+
+def fun_l12_n192(x)
+ if (x < 1)
+ fun_l13_n535(x)
+ else
+ fun_l13_n191(x)
+ end
+end
+
+def fun_l12_n193(x)
+ if (x < 1)
+ fun_l13_n157(x)
+ else
+ fun_l13_n927(x)
+ end
+end
+
+def fun_l12_n194(x)
+ if (x < 1)
+ fun_l13_n733(x)
+ else
+ fun_l13_n798(x)
+ end
+end
+
+def fun_l12_n195(x)
+ if (x < 1)
+ fun_l13_n31(x)
+ else
+ fun_l13_n703(x)
+ end
+end
+
+def fun_l12_n196(x)
+ if (x < 1)
+ fun_l13_n976(x)
+ else
+ fun_l13_n862(x)
+ end
+end
+
+def fun_l12_n197(x)
+ if (x < 1)
+ fun_l13_n267(x)
+ else
+ fun_l13_n803(x)
+ end
+end
+
+def fun_l12_n198(x)
+ if (x < 1)
+ fun_l13_n598(x)
+ else
+ fun_l13_n255(x)
+ end
+end
+
+def fun_l12_n199(x)
+ if (x < 1)
+ fun_l13_n566(x)
+ else
+ fun_l13_n668(x)
+ end
+end
+
+def fun_l12_n200(x)
+ if (x < 1)
+ fun_l13_n48(x)
+ else
+ fun_l13_n406(x)
+ end
+end
+
+def fun_l12_n201(x)
+ if (x < 1)
+ fun_l13_n971(x)
+ else
+ fun_l13_n225(x)
+ end
+end
+
+def fun_l12_n202(x)
+ if (x < 1)
+ fun_l13_n120(x)
+ else
+ fun_l13_n72(x)
+ end
+end
+
+def fun_l12_n203(x)
+ if (x < 1)
+ fun_l13_n333(x)
+ else
+ fun_l13_n381(x)
+ end
+end
+
+def fun_l12_n204(x)
+ if (x < 1)
+ fun_l13_n558(x)
+ else
+ fun_l13_n474(x)
+ end
+end
+
+def fun_l12_n205(x)
+ if (x < 1)
+ fun_l13_n796(x)
+ else
+ fun_l13_n420(x)
+ end
+end
+
+def fun_l12_n206(x)
+ if (x < 1)
+ fun_l13_n287(x)
+ else
+ fun_l13_n43(x)
+ end
+end
+
+def fun_l12_n207(x)
+ if (x < 1)
+ fun_l13_n778(x)
+ else
+ fun_l13_n560(x)
+ end
+end
+
+def fun_l12_n208(x)
+ if (x < 1)
+ fun_l13_n707(x)
+ else
+ fun_l13_n824(x)
+ end
+end
+
+def fun_l12_n209(x)
+ if (x < 1)
+ fun_l13_n788(x)
+ else
+ fun_l13_n625(x)
+ end
+end
+
+def fun_l12_n210(x)
+ if (x < 1)
+ fun_l13_n818(x)
+ else
+ fun_l13_n667(x)
+ end
+end
+
+def fun_l12_n211(x)
+ if (x < 1)
+ fun_l13_n710(x)
+ else
+ fun_l13_n508(x)
+ end
+end
+
+def fun_l12_n212(x)
+ if (x < 1)
+ fun_l13_n497(x)
+ else
+ fun_l13_n20(x)
+ end
+end
+
+def fun_l12_n213(x)
+ if (x < 1)
+ fun_l13_n648(x)
+ else
+ fun_l13_n33(x)
+ end
+end
+
+def fun_l12_n214(x)
+ if (x < 1)
+ fun_l13_n404(x)
+ else
+ fun_l13_n918(x)
+ end
+end
+
+def fun_l12_n215(x)
+ if (x < 1)
+ fun_l13_n595(x)
+ else
+ fun_l13_n440(x)
+ end
+end
+
+def fun_l12_n216(x)
+ if (x < 1)
+ fun_l13_n302(x)
+ else
+ fun_l13_n388(x)
+ end
+end
+
+def fun_l12_n217(x)
+ if (x < 1)
+ fun_l13_n301(x)
+ else
+ fun_l13_n416(x)
+ end
+end
+
+def fun_l12_n218(x)
+ if (x < 1)
+ fun_l13_n114(x)
+ else
+ fun_l13_n650(x)
+ end
+end
+
+def fun_l12_n219(x)
+ if (x < 1)
+ fun_l13_n221(x)
+ else
+ fun_l13_n539(x)
+ end
+end
+
+def fun_l12_n220(x)
+ if (x < 1)
+ fun_l13_n529(x)
+ else
+ fun_l13_n438(x)
+ end
+end
+
+def fun_l12_n221(x)
+ if (x < 1)
+ fun_l13_n528(x)
+ else
+ fun_l13_n284(x)
+ end
+end
+
+def fun_l12_n222(x)
+ if (x < 1)
+ fun_l13_n746(x)
+ else
+ fun_l13_n634(x)
+ end
+end
+
+def fun_l12_n223(x)
+ if (x < 1)
+ fun_l13_n726(x)
+ else
+ fun_l13_n142(x)
+ end
+end
+
+def fun_l12_n224(x)
+ if (x < 1)
+ fun_l13_n57(x)
+ else
+ fun_l13_n625(x)
+ end
+end
+
+def fun_l12_n225(x)
+ if (x < 1)
+ fun_l13_n739(x)
+ else
+ fun_l13_n667(x)
+ end
+end
+
+def fun_l12_n226(x)
+ if (x < 1)
+ fun_l13_n693(x)
+ else
+ fun_l13_n819(x)
+ end
+end
+
+def fun_l12_n227(x)
+ if (x < 1)
+ fun_l13_n316(x)
+ else
+ fun_l13_n866(x)
+ end
+end
+
+def fun_l12_n228(x)
+ if (x < 1)
+ fun_l13_n88(x)
+ else
+ fun_l13_n336(x)
+ end
+end
+
+def fun_l12_n229(x)
+ if (x < 1)
+ fun_l13_n387(x)
+ else
+ fun_l13_n226(x)
+ end
+end
+
+def fun_l12_n230(x)
+ if (x < 1)
+ fun_l13_n644(x)
+ else
+ fun_l13_n933(x)
+ end
+end
+
+def fun_l12_n231(x)
+ if (x < 1)
+ fun_l13_n952(x)
+ else
+ fun_l13_n747(x)
+ end
+end
+
+def fun_l12_n232(x)
+ if (x < 1)
+ fun_l13_n107(x)
+ else
+ fun_l13_n0(x)
+ end
+end
+
+def fun_l12_n233(x)
+ if (x < 1)
+ fun_l13_n589(x)
+ else
+ fun_l13_n712(x)
+ end
+end
+
+def fun_l12_n234(x)
+ if (x < 1)
+ fun_l13_n429(x)
+ else
+ fun_l13_n845(x)
+ end
+end
+
+def fun_l12_n235(x)
+ if (x < 1)
+ fun_l13_n733(x)
+ else
+ fun_l13_n203(x)
+ end
+end
+
+def fun_l12_n236(x)
+ if (x < 1)
+ fun_l13_n842(x)
+ else
+ fun_l13_n134(x)
+ end
+end
+
+def fun_l12_n237(x)
+ if (x < 1)
+ fun_l13_n114(x)
+ else
+ fun_l13_n794(x)
+ end
+end
+
+def fun_l12_n238(x)
+ if (x < 1)
+ fun_l13_n463(x)
+ else
+ fun_l13_n127(x)
+ end
+end
+
+def fun_l12_n239(x)
+ if (x < 1)
+ fun_l13_n443(x)
+ else
+ fun_l13_n13(x)
+ end
+end
+
+def fun_l12_n240(x)
+ if (x < 1)
+ fun_l13_n713(x)
+ else
+ fun_l13_n447(x)
+ end
+end
+
+def fun_l12_n241(x)
+ if (x < 1)
+ fun_l13_n404(x)
+ else
+ fun_l13_n796(x)
+ end
+end
+
+def fun_l12_n242(x)
+ if (x < 1)
+ fun_l13_n277(x)
+ else
+ fun_l13_n106(x)
+ end
+end
+
+def fun_l12_n243(x)
+ if (x < 1)
+ fun_l13_n584(x)
+ else
+ fun_l13_n262(x)
+ end
+end
+
+def fun_l12_n244(x)
+ if (x < 1)
+ fun_l13_n670(x)
+ else
+ fun_l13_n989(x)
+ end
+end
+
+def fun_l12_n245(x)
+ if (x < 1)
+ fun_l13_n588(x)
+ else
+ fun_l13_n513(x)
+ end
+end
+
+def fun_l12_n246(x)
+ if (x < 1)
+ fun_l13_n98(x)
+ else
+ fun_l13_n400(x)
+ end
+end
+
+def fun_l12_n247(x)
+ if (x < 1)
+ fun_l13_n119(x)
+ else
+ fun_l13_n321(x)
+ end
+end
+
+def fun_l12_n248(x)
+ if (x < 1)
+ fun_l13_n157(x)
+ else
+ fun_l13_n557(x)
+ end
+end
+
+def fun_l12_n249(x)
+ if (x < 1)
+ fun_l13_n243(x)
+ else
+ fun_l13_n596(x)
+ end
+end
+
+def fun_l12_n250(x)
+ if (x < 1)
+ fun_l13_n280(x)
+ else
+ fun_l13_n779(x)
+ end
+end
+
+def fun_l12_n251(x)
+ if (x < 1)
+ fun_l13_n437(x)
+ else
+ fun_l13_n829(x)
+ end
+end
+
+def fun_l12_n252(x)
+ if (x < 1)
+ fun_l13_n472(x)
+ else
+ fun_l13_n224(x)
+ end
+end
+
+def fun_l12_n253(x)
+ if (x < 1)
+ fun_l13_n151(x)
+ else
+ fun_l13_n168(x)
+ end
+end
+
+def fun_l12_n254(x)
+ if (x < 1)
+ fun_l13_n724(x)
+ else
+ fun_l13_n355(x)
+ end
+end
+
+def fun_l12_n255(x)
+ if (x < 1)
+ fun_l13_n27(x)
+ else
+ fun_l13_n776(x)
+ end
+end
+
+def fun_l12_n256(x)
+ if (x < 1)
+ fun_l13_n116(x)
+ else
+ fun_l13_n52(x)
+ end
+end
+
+def fun_l12_n257(x)
+ if (x < 1)
+ fun_l13_n201(x)
+ else
+ fun_l13_n982(x)
+ end
+end
+
+def fun_l12_n258(x)
+ if (x < 1)
+ fun_l13_n152(x)
+ else
+ fun_l13_n818(x)
+ end
+end
+
+def fun_l12_n259(x)
+ if (x < 1)
+ fun_l13_n859(x)
+ else
+ fun_l13_n555(x)
+ end
+end
+
+def fun_l12_n260(x)
+ if (x < 1)
+ fun_l13_n29(x)
+ else
+ fun_l13_n416(x)
+ end
+end
+
+def fun_l12_n261(x)
+ if (x < 1)
+ fun_l13_n811(x)
+ else
+ fun_l13_n827(x)
+ end
+end
+
+def fun_l12_n262(x)
+ if (x < 1)
+ fun_l13_n867(x)
+ else
+ fun_l13_n298(x)
+ end
+end
+
+def fun_l12_n263(x)
+ if (x < 1)
+ fun_l13_n464(x)
+ else
+ fun_l13_n420(x)
+ end
+end
+
+def fun_l12_n264(x)
+ if (x < 1)
+ fun_l13_n494(x)
+ else
+ fun_l13_n368(x)
+ end
+end
+
+def fun_l12_n265(x)
+ if (x < 1)
+ fun_l13_n959(x)
+ else
+ fun_l13_n425(x)
+ end
+end
+
+def fun_l12_n266(x)
+ if (x < 1)
+ fun_l13_n841(x)
+ else
+ fun_l13_n874(x)
+ end
+end
+
+def fun_l12_n267(x)
+ if (x < 1)
+ fun_l13_n885(x)
+ else
+ fun_l13_n631(x)
+ end
+end
+
+def fun_l12_n268(x)
+ if (x < 1)
+ fun_l13_n645(x)
+ else
+ fun_l13_n342(x)
+ end
+end
+
+def fun_l12_n269(x)
+ if (x < 1)
+ fun_l13_n4(x)
+ else
+ fun_l13_n81(x)
+ end
+end
+
+def fun_l12_n270(x)
+ if (x < 1)
+ fun_l13_n44(x)
+ else
+ fun_l13_n924(x)
+ end
+end
+
+def fun_l12_n271(x)
+ if (x < 1)
+ fun_l13_n955(x)
+ else
+ fun_l13_n834(x)
+ end
+end
+
+def fun_l12_n272(x)
+ if (x < 1)
+ fun_l13_n969(x)
+ else
+ fun_l13_n699(x)
+ end
+end
+
+def fun_l12_n273(x)
+ if (x < 1)
+ fun_l13_n590(x)
+ else
+ fun_l13_n608(x)
+ end
+end
+
+def fun_l12_n274(x)
+ if (x < 1)
+ fun_l13_n170(x)
+ else
+ fun_l13_n343(x)
+ end
+end
+
+def fun_l12_n275(x)
+ if (x < 1)
+ fun_l13_n317(x)
+ else
+ fun_l13_n998(x)
+ end
+end
+
+def fun_l12_n276(x)
+ if (x < 1)
+ fun_l13_n864(x)
+ else
+ fun_l13_n644(x)
+ end
+end
+
+def fun_l12_n277(x)
+ if (x < 1)
+ fun_l13_n42(x)
+ else
+ fun_l13_n663(x)
+ end
+end
+
+def fun_l12_n278(x)
+ if (x < 1)
+ fun_l13_n39(x)
+ else
+ fun_l13_n624(x)
+ end
+end
+
+def fun_l12_n279(x)
+ if (x < 1)
+ fun_l13_n578(x)
+ else
+ fun_l13_n592(x)
+ end
+end
+
+def fun_l12_n280(x)
+ if (x < 1)
+ fun_l13_n345(x)
+ else
+ fun_l13_n462(x)
+ end
+end
+
+def fun_l12_n281(x)
+ if (x < 1)
+ fun_l13_n741(x)
+ else
+ fun_l13_n93(x)
+ end
+end
+
+def fun_l12_n282(x)
+ if (x < 1)
+ fun_l13_n845(x)
+ else
+ fun_l13_n981(x)
+ end
+end
+
+def fun_l12_n283(x)
+ if (x < 1)
+ fun_l13_n479(x)
+ else
+ fun_l13_n823(x)
+ end
+end
+
+def fun_l12_n284(x)
+ if (x < 1)
+ fun_l13_n201(x)
+ else
+ fun_l13_n526(x)
+ end
+end
+
+def fun_l12_n285(x)
+ if (x < 1)
+ fun_l13_n890(x)
+ else
+ fun_l13_n237(x)
+ end
+end
+
+def fun_l12_n286(x)
+ if (x < 1)
+ fun_l13_n377(x)
+ else
+ fun_l13_n249(x)
+ end
+end
+
+def fun_l12_n287(x)
+ if (x < 1)
+ fun_l13_n147(x)
+ else
+ fun_l13_n306(x)
+ end
+end
+
+def fun_l12_n288(x)
+ if (x < 1)
+ fun_l13_n822(x)
+ else
+ fun_l13_n220(x)
+ end
+end
+
+def fun_l12_n289(x)
+ if (x < 1)
+ fun_l13_n106(x)
+ else
+ fun_l13_n648(x)
+ end
+end
+
+def fun_l12_n290(x)
+ if (x < 1)
+ fun_l13_n278(x)
+ else
+ fun_l13_n255(x)
+ end
+end
+
+def fun_l12_n291(x)
+ if (x < 1)
+ fun_l13_n994(x)
+ else
+ fun_l13_n36(x)
+ end
+end
+
+def fun_l12_n292(x)
+ if (x < 1)
+ fun_l13_n731(x)
+ else
+ fun_l13_n473(x)
+ end
+end
+
+def fun_l12_n293(x)
+ if (x < 1)
+ fun_l13_n321(x)
+ else
+ fun_l13_n518(x)
+ end
+end
+
+def fun_l12_n294(x)
+ if (x < 1)
+ fun_l13_n91(x)
+ else
+ fun_l13_n765(x)
+ end
+end
+
+def fun_l12_n295(x)
+ if (x < 1)
+ fun_l13_n39(x)
+ else
+ fun_l13_n639(x)
+ end
+end
+
+def fun_l12_n296(x)
+ if (x < 1)
+ fun_l13_n800(x)
+ else
+ fun_l13_n821(x)
+ end
+end
+
+def fun_l12_n297(x)
+ if (x < 1)
+ fun_l13_n553(x)
+ else
+ fun_l13_n898(x)
+ end
+end
+
+def fun_l12_n298(x)
+ if (x < 1)
+ fun_l13_n487(x)
+ else
+ fun_l13_n470(x)
+ end
+end
+
+def fun_l12_n299(x)
+ if (x < 1)
+ fun_l13_n743(x)
+ else
+ fun_l13_n684(x)
+ end
+end
+
+def fun_l12_n300(x)
+ if (x < 1)
+ fun_l13_n177(x)
+ else
+ fun_l13_n375(x)
+ end
+end
+
+def fun_l12_n301(x)
+ if (x < 1)
+ fun_l13_n714(x)
+ else
+ fun_l13_n922(x)
+ end
+end
+
+def fun_l12_n302(x)
+ if (x < 1)
+ fun_l13_n845(x)
+ else
+ fun_l13_n93(x)
+ end
+end
+
+def fun_l12_n303(x)
+ if (x < 1)
+ fun_l13_n806(x)
+ else
+ fun_l13_n706(x)
+ end
+end
+
+def fun_l12_n304(x)
+ if (x < 1)
+ fun_l13_n428(x)
+ else
+ fun_l13_n942(x)
+ end
+end
+
+def fun_l12_n305(x)
+ if (x < 1)
+ fun_l13_n170(x)
+ else
+ fun_l13_n634(x)
+ end
+end
+
+def fun_l12_n306(x)
+ if (x < 1)
+ fun_l13_n998(x)
+ else
+ fun_l13_n224(x)
+ end
+end
+
+def fun_l12_n307(x)
+ if (x < 1)
+ fun_l13_n15(x)
+ else
+ fun_l13_n753(x)
+ end
+end
+
+def fun_l12_n308(x)
+ if (x < 1)
+ fun_l13_n323(x)
+ else
+ fun_l13_n846(x)
+ end
+end
+
+def fun_l12_n309(x)
+ if (x < 1)
+ fun_l13_n779(x)
+ else
+ fun_l13_n330(x)
+ end
+end
+
+def fun_l12_n310(x)
+ if (x < 1)
+ fun_l13_n652(x)
+ else
+ fun_l13_n560(x)
+ end
+end
+
+def fun_l12_n311(x)
+ if (x < 1)
+ fun_l13_n54(x)
+ else
+ fun_l13_n144(x)
+ end
+end
+
+def fun_l12_n312(x)
+ if (x < 1)
+ fun_l13_n674(x)
+ else
+ fun_l13_n779(x)
+ end
+end
+
+def fun_l12_n313(x)
+ if (x < 1)
+ fun_l13_n975(x)
+ else
+ fun_l13_n109(x)
+ end
+end
+
+def fun_l12_n314(x)
+ if (x < 1)
+ fun_l13_n997(x)
+ else
+ fun_l13_n827(x)
+ end
+end
+
+def fun_l12_n315(x)
+ if (x < 1)
+ fun_l13_n822(x)
+ else
+ fun_l13_n349(x)
+ end
+end
+
+def fun_l12_n316(x)
+ if (x < 1)
+ fun_l13_n516(x)
+ else
+ fun_l13_n974(x)
+ end
+end
+
+def fun_l12_n317(x)
+ if (x < 1)
+ fun_l13_n538(x)
+ else
+ fun_l13_n786(x)
+ end
+end
+
+def fun_l12_n318(x)
+ if (x < 1)
+ fun_l13_n125(x)
+ else
+ fun_l13_n809(x)
+ end
+end
+
+def fun_l12_n319(x)
+ if (x < 1)
+ fun_l13_n642(x)
+ else
+ fun_l13_n188(x)
+ end
+end
+
+def fun_l12_n320(x)
+ if (x < 1)
+ fun_l13_n904(x)
+ else
+ fun_l13_n396(x)
+ end
+end
+
+def fun_l12_n321(x)
+ if (x < 1)
+ fun_l13_n278(x)
+ else
+ fun_l13_n752(x)
+ end
+end
+
+def fun_l12_n322(x)
+ if (x < 1)
+ fun_l13_n566(x)
+ else
+ fun_l13_n894(x)
+ end
+end
+
+def fun_l12_n323(x)
+ if (x < 1)
+ fun_l13_n357(x)
+ else
+ fun_l13_n742(x)
+ end
+end
+
+def fun_l12_n324(x)
+ if (x < 1)
+ fun_l13_n667(x)
+ else
+ fun_l13_n764(x)
+ end
+end
+
+def fun_l12_n325(x)
+ if (x < 1)
+ fun_l13_n333(x)
+ else
+ fun_l13_n445(x)
+ end
+end
+
+def fun_l12_n326(x)
+ if (x < 1)
+ fun_l13_n669(x)
+ else
+ fun_l13_n484(x)
+ end
+end
+
+def fun_l12_n327(x)
+ if (x < 1)
+ fun_l13_n662(x)
+ else
+ fun_l13_n610(x)
+ end
+end
+
+def fun_l12_n328(x)
+ if (x < 1)
+ fun_l13_n869(x)
+ else
+ fun_l13_n993(x)
+ end
+end
+
+def fun_l12_n329(x)
+ if (x < 1)
+ fun_l13_n305(x)
+ else
+ fun_l13_n45(x)
+ end
+end
+
+def fun_l12_n330(x)
+ if (x < 1)
+ fun_l13_n32(x)
+ else
+ fun_l13_n253(x)
+ end
+end
+
+def fun_l12_n331(x)
+ if (x < 1)
+ fun_l13_n45(x)
+ else
+ fun_l13_n327(x)
+ end
+end
+
+def fun_l12_n332(x)
+ if (x < 1)
+ fun_l13_n685(x)
+ else
+ fun_l13_n562(x)
+ end
+end
+
+def fun_l12_n333(x)
+ if (x < 1)
+ fun_l13_n274(x)
+ else
+ fun_l13_n461(x)
+ end
+end
+
+def fun_l12_n334(x)
+ if (x < 1)
+ fun_l13_n93(x)
+ else
+ fun_l13_n7(x)
+ end
+end
+
+def fun_l12_n335(x)
+ if (x < 1)
+ fun_l13_n742(x)
+ else
+ fun_l13_n259(x)
+ end
+end
+
+def fun_l12_n336(x)
+ if (x < 1)
+ fun_l13_n518(x)
+ else
+ fun_l13_n108(x)
+ end
+end
+
+def fun_l12_n337(x)
+ if (x < 1)
+ fun_l13_n439(x)
+ else
+ fun_l13_n21(x)
+ end
+end
+
+def fun_l12_n338(x)
+ if (x < 1)
+ fun_l13_n34(x)
+ else
+ fun_l13_n869(x)
+ end
+end
+
+def fun_l12_n339(x)
+ if (x < 1)
+ fun_l13_n995(x)
+ else
+ fun_l13_n810(x)
+ end
+end
+
+def fun_l12_n340(x)
+ if (x < 1)
+ fun_l13_n640(x)
+ else
+ fun_l13_n108(x)
+ end
+end
+
+def fun_l12_n341(x)
+ if (x < 1)
+ fun_l13_n332(x)
+ else
+ fun_l13_n174(x)
+ end
+end
+
+def fun_l12_n342(x)
+ if (x < 1)
+ fun_l13_n425(x)
+ else
+ fun_l13_n523(x)
+ end
+end
+
+def fun_l12_n343(x)
+ if (x < 1)
+ fun_l13_n886(x)
+ else
+ fun_l13_n9(x)
+ end
+end
+
+def fun_l12_n344(x)
+ if (x < 1)
+ fun_l13_n644(x)
+ else
+ fun_l13_n558(x)
+ end
+end
+
+def fun_l12_n345(x)
+ if (x < 1)
+ fun_l13_n40(x)
+ else
+ fun_l13_n569(x)
+ end
+end
+
+def fun_l12_n346(x)
+ if (x < 1)
+ fun_l13_n530(x)
+ else
+ fun_l13_n52(x)
+ end
+end
+
+def fun_l12_n347(x)
+ if (x < 1)
+ fun_l13_n624(x)
+ else
+ fun_l13_n525(x)
+ end
+end
+
+def fun_l12_n348(x)
+ if (x < 1)
+ fun_l13_n106(x)
+ else
+ fun_l13_n101(x)
+ end
+end
+
+def fun_l12_n349(x)
+ if (x < 1)
+ fun_l13_n164(x)
+ else
+ fun_l13_n675(x)
+ end
+end
+
+def fun_l12_n350(x)
+ if (x < 1)
+ fun_l13_n349(x)
+ else
+ fun_l13_n125(x)
+ end
+end
+
+def fun_l12_n351(x)
+ if (x < 1)
+ fun_l13_n536(x)
+ else
+ fun_l13_n949(x)
+ end
+end
+
+def fun_l12_n352(x)
+ if (x < 1)
+ fun_l13_n872(x)
+ else
+ fun_l13_n678(x)
+ end
+end
+
+def fun_l12_n353(x)
+ if (x < 1)
+ fun_l13_n566(x)
+ else
+ fun_l13_n576(x)
+ end
+end
+
+def fun_l12_n354(x)
+ if (x < 1)
+ fun_l13_n978(x)
+ else
+ fun_l13_n539(x)
+ end
+end
+
+def fun_l12_n355(x)
+ if (x < 1)
+ fun_l13_n929(x)
+ else
+ fun_l13_n301(x)
+ end
+end
+
+def fun_l12_n356(x)
+ if (x < 1)
+ fun_l13_n768(x)
+ else
+ fun_l13_n292(x)
+ end
+end
+
+def fun_l12_n357(x)
+ if (x < 1)
+ fun_l13_n873(x)
+ else
+ fun_l13_n201(x)
+ end
+end
+
+def fun_l12_n358(x)
+ if (x < 1)
+ fun_l13_n852(x)
+ else
+ fun_l13_n144(x)
+ end
+end
+
+def fun_l12_n359(x)
+ if (x < 1)
+ fun_l13_n220(x)
+ else
+ fun_l13_n318(x)
+ end
+end
+
+def fun_l12_n360(x)
+ if (x < 1)
+ fun_l13_n339(x)
+ else
+ fun_l13_n896(x)
+ end
+end
+
+def fun_l12_n361(x)
+ if (x < 1)
+ fun_l13_n896(x)
+ else
+ fun_l13_n611(x)
+ end
+end
+
+def fun_l12_n362(x)
+ if (x < 1)
+ fun_l13_n237(x)
+ else
+ fun_l13_n781(x)
+ end
+end
+
+def fun_l12_n363(x)
+ if (x < 1)
+ fun_l13_n994(x)
+ else
+ fun_l13_n306(x)
+ end
+end
+
+def fun_l12_n364(x)
+ if (x < 1)
+ fun_l13_n437(x)
+ else
+ fun_l13_n634(x)
+ end
+end
+
+def fun_l12_n365(x)
+ if (x < 1)
+ fun_l13_n367(x)
+ else
+ fun_l13_n798(x)
+ end
+end
+
+def fun_l12_n366(x)
+ if (x < 1)
+ fun_l13_n831(x)
+ else
+ fun_l13_n352(x)
+ end
+end
+
+def fun_l12_n367(x)
+ if (x < 1)
+ fun_l13_n554(x)
+ else
+ fun_l13_n999(x)
+ end
+end
+
+def fun_l12_n368(x)
+ if (x < 1)
+ fun_l13_n214(x)
+ else
+ fun_l13_n67(x)
+ end
+end
+
+def fun_l12_n369(x)
+ if (x < 1)
+ fun_l13_n628(x)
+ else
+ fun_l13_n637(x)
+ end
+end
+
+def fun_l12_n370(x)
+ if (x < 1)
+ fun_l13_n42(x)
+ else
+ fun_l13_n631(x)
+ end
+end
+
+def fun_l12_n371(x)
+ if (x < 1)
+ fun_l13_n53(x)
+ else
+ fun_l13_n226(x)
+ end
+end
+
+def fun_l12_n372(x)
+ if (x < 1)
+ fun_l13_n810(x)
+ else
+ fun_l13_n853(x)
+ end
+end
+
+def fun_l12_n373(x)
+ if (x < 1)
+ fun_l13_n257(x)
+ else
+ fun_l13_n480(x)
+ end
+end
+
+def fun_l12_n374(x)
+ if (x < 1)
+ fun_l13_n715(x)
+ else
+ fun_l13_n481(x)
+ end
+end
+
+def fun_l12_n375(x)
+ if (x < 1)
+ fun_l13_n499(x)
+ else
+ fun_l13_n694(x)
+ end
+end
+
+def fun_l12_n376(x)
+ if (x < 1)
+ fun_l13_n376(x)
+ else
+ fun_l13_n99(x)
+ end
+end
+
+def fun_l12_n377(x)
+ if (x < 1)
+ fun_l13_n672(x)
+ else
+ fun_l13_n421(x)
+ end
+end
+
+def fun_l12_n378(x)
+ if (x < 1)
+ fun_l13_n320(x)
+ else
+ fun_l13_n590(x)
+ end
+end
+
+def fun_l12_n379(x)
+ if (x < 1)
+ fun_l13_n678(x)
+ else
+ fun_l13_n727(x)
+ end
+end
+
+def fun_l12_n380(x)
+ if (x < 1)
+ fun_l13_n269(x)
+ else
+ fun_l13_n74(x)
+ end
+end
+
+def fun_l12_n381(x)
+ if (x < 1)
+ fun_l13_n838(x)
+ else
+ fun_l13_n105(x)
+ end
+end
+
+def fun_l12_n382(x)
+ if (x < 1)
+ fun_l13_n482(x)
+ else
+ fun_l13_n400(x)
+ end
+end
+
+def fun_l12_n383(x)
+ if (x < 1)
+ fun_l13_n376(x)
+ else
+ fun_l13_n829(x)
+ end
+end
+
+def fun_l12_n384(x)
+ if (x < 1)
+ fun_l13_n81(x)
+ else
+ fun_l13_n895(x)
+ end
+end
+
+def fun_l12_n385(x)
+ if (x < 1)
+ fun_l13_n718(x)
+ else
+ fun_l13_n641(x)
+ end
+end
+
+def fun_l12_n386(x)
+ if (x < 1)
+ fun_l13_n825(x)
+ else
+ fun_l13_n761(x)
+ end
+end
+
+def fun_l12_n387(x)
+ if (x < 1)
+ fun_l13_n930(x)
+ else
+ fun_l13_n204(x)
+ end
+end
+
+def fun_l12_n388(x)
+ if (x < 1)
+ fun_l13_n81(x)
+ else
+ fun_l13_n319(x)
+ end
+end
+
+def fun_l12_n389(x)
+ if (x < 1)
+ fun_l13_n40(x)
+ else
+ fun_l13_n57(x)
+ end
+end
+
+def fun_l12_n390(x)
+ if (x < 1)
+ fun_l13_n206(x)
+ else
+ fun_l13_n219(x)
+ end
+end
+
+def fun_l12_n391(x)
+ if (x < 1)
+ fun_l13_n538(x)
+ else
+ fun_l13_n239(x)
+ end
+end
+
+def fun_l12_n392(x)
+ if (x < 1)
+ fun_l13_n326(x)
+ else
+ fun_l13_n613(x)
+ end
+end
+
+def fun_l12_n393(x)
+ if (x < 1)
+ fun_l13_n860(x)
+ else
+ fun_l13_n712(x)
+ end
+end
+
+def fun_l12_n394(x)
+ if (x < 1)
+ fun_l13_n829(x)
+ else
+ fun_l13_n153(x)
+ end
+end
+
+def fun_l12_n395(x)
+ if (x < 1)
+ fun_l13_n734(x)
+ else
+ fun_l13_n926(x)
+ end
+end
+
+def fun_l12_n396(x)
+ if (x < 1)
+ fun_l13_n188(x)
+ else
+ fun_l13_n821(x)
+ end
+end
+
+def fun_l12_n397(x)
+ if (x < 1)
+ fun_l13_n161(x)
+ else
+ fun_l13_n284(x)
+ end
+end
+
+def fun_l12_n398(x)
+ if (x < 1)
+ fun_l13_n402(x)
+ else
+ fun_l13_n481(x)
+ end
+end
+
+def fun_l12_n399(x)
+ if (x < 1)
+ fun_l13_n469(x)
+ else
+ fun_l13_n348(x)
+ end
+end
+
+def fun_l12_n400(x)
+ if (x < 1)
+ fun_l13_n567(x)
+ else
+ fun_l13_n702(x)
+ end
+end
+
+def fun_l12_n401(x)
+ if (x < 1)
+ fun_l13_n787(x)
+ else
+ fun_l13_n5(x)
+ end
+end
+
+def fun_l12_n402(x)
+ if (x < 1)
+ fun_l13_n525(x)
+ else
+ fun_l13_n983(x)
+ end
+end
+
+def fun_l12_n403(x)
+ if (x < 1)
+ fun_l13_n185(x)
+ else
+ fun_l13_n315(x)
+ end
+end
+
+def fun_l12_n404(x)
+ if (x < 1)
+ fun_l13_n746(x)
+ else
+ fun_l13_n892(x)
+ end
+end
+
+def fun_l12_n405(x)
+ if (x < 1)
+ fun_l13_n990(x)
+ else
+ fun_l13_n868(x)
+ end
+end
+
+def fun_l12_n406(x)
+ if (x < 1)
+ fun_l13_n399(x)
+ else
+ fun_l13_n298(x)
+ end
+end
+
+def fun_l12_n407(x)
+ if (x < 1)
+ fun_l13_n283(x)
+ else
+ fun_l13_n87(x)
+ end
+end
+
+def fun_l12_n408(x)
+ if (x < 1)
+ fun_l13_n597(x)
+ else
+ fun_l13_n355(x)
+ end
+end
+
+def fun_l12_n409(x)
+ if (x < 1)
+ fun_l13_n517(x)
+ else
+ fun_l13_n700(x)
+ end
+end
+
+def fun_l12_n410(x)
+ if (x < 1)
+ fun_l13_n796(x)
+ else
+ fun_l13_n282(x)
+ end
+end
+
+def fun_l12_n411(x)
+ if (x < 1)
+ fun_l13_n876(x)
+ else
+ fun_l13_n562(x)
+ end
+end
+
+def fun_l12_n412(x)
+ if (x < 1)
+ fun_l13_n344(x)
+ else
+ fun_l13_n182(x)
+ end
+end
+
+def fun_l12_n413(x)
+ if (x < 1)
+ fun_l13_n879(x)
+ else
+ fun_l13_n443(x)
+ end
+end
+
+def fun_l12_n414(x)
+ if (x < 1)
+ fun_l13_n335(x)
+ else
+ fun_l13_n451(x)
+ end
+end
+
+def fun_l12_n415(x)
+ if (x < 1)
+ fun_l13_n112(x)
+ else
+ fun_l13_n391(x)
+ end
+end
+
+def fun_l12_n416(x)
+ if (x < 1)
+ fun_l13_n217(x)
+ else
+ fun_l13_n221(x)
+ end
+end
+
+def fun_l12_n417(x)
+ if (x < 1)
+ fun_l13_n113(x)
+ else
+ fun_l13_n563(x)
+ end
+end
+
+def fun_l12_n418(x)
+ if (x < 1)
+ fun_l13_n486(x)
+ else
+ fun_l13_n374(x)
+ end
+end
+
+def fun_l12_n419(x)
+ if (x < 1)
+ fun_l13_n970(x)
+ else
+ fun_l13_n393(x)
+ end
+end
+
+def fun_l12_n420(x)
+ if (x < 1)
+ fun_l13_n273(x)
+ else
+ fun_l13_n64(x)
+ end
+end
+
+def fun_l12_n421(x)
+ if (x < 1)
+ fun_l13_n69(x)
+ else
+ fun_l13_n158(x)
+ end
+end
+
+def fun_l12_n422(x)
+ if (x < 1)
+ fun_l13_n308(x)
+ else
+ fun_l13_n609(x)
+ end
+end
+
+def fun_l12_n423(x)
+ if (x < 1)
+ fun_l13_n964(x)
+ else
+ fun_l13_n36(x)
+ end
+end
+
+def fun_l12_n424(x)
+ if (x < 1)
+ fun_l13_n783(x)
+ else
+ fun_l13_n513(x)
+ end
+end
+
+def fun_l12_n425(x)
+ if (x < 1)
+ fun_l13_n792(x)
+ else
+ fun_l13_n960(x)
+ end
+end
+
+def fun_l12_n426(x)
+ if (x < 1)
+ fun_l13_n160(x)
+ else
+ fun_l13_n911(x)
+ end
+end
+
+def fun_l12_n427(x)
+ if (x < 1)
+ fun_l13_n374(x)
+ else
+ fun_l13_n672(x)
+ end
+end
+
+def fun_l12_n428(x)
+ if (x < 1)
+ fun_l13_n694(x)
+ else
+ fun_l13_n166(x)
+ end
+end
+
+def fun_l12_n429(x)
+ if (x < 1)
+ fun_l13_n807(x)
+ else
+ fun_l13_n929(x)
+ end
+end
+
+def fun_l12_n430(x)
+ if (x < 1)
+ fun_l13_n997(x)
+ else
+ fun_l13_n938(x)
+ end
+end
+
+def fun_l12_n431(x)
+ if (x < 1)
+ fun_l13_n934(x)
+ else
+ fun_l13_n365(x)
+ end
+end
+
+def fun_l12_n432(x)
+ if (x < 1)
+ fun_l13_n546(x)
+ else
+ fun_l13_n272(x)
+ end
+end
+
+def fun_l12_n433(x)
+ if (x < 1)
+ fun_l13_n176(x)
+ else
+ fun_l13_n629(x)
+ end
+end
+
+def fun_l12_n434(x)
+ if (x < 1)
+ fun_l13_n536(x)
+ else
+ fun_l13_n165(x)
+ end
+end
+
+def fun_l12_n435(x)
+ if (x < 1)
+ fun_l13_n915(x)
+ else
+ fun_l13_n823(x)
+ end
+end
+
+def fun_l12_n436(x)
+ if (x < 1)
+ fun_l13_n580(x)
+ else
+ fun_l13_n214(x)
+ end
+end
+
+def fun_l12_n437(x)
+ if (x < 1)
+ fun_l13_n353(x)
+ else
+ fun_l13_n626(x)
+ end
+end
+
+def fun_l12_n438(x)
+ if (x < 1)
+ fun_l13_n888(x)
+ else
+ fun_l13_n874(x)
+ end
+end
+
+def fun_l12_n439(x)
+ if (x < 1)
+ fun_l13_n670(x)
+ else
+ fun_l13_n279(x)
+ end
+end
+
+def fun_l12_n440(x)
+ if (x < 1)
+ fun_l13_n818(x)
+ else
+ fun_l13_n927(x)
+ end
+end
+
+def fun_l12_n441(x)
+ if (x < 1)
+ fun_l13_n686(x)
+ else
+ fun_l13_n32(x)
+ end
+end
+
+def fun_l12_n442(x)
+ if (x < 1)
+ fun_l13_n882(x)
+ else
+ fun_l13_n932(x)
+ end
+end
+
+def fun_l12_n443(x)
+ if (x < 1)
+ fun_l13_n677(x)
+ else
+ fun_l13_n267(x)
+ end
+end
+
+def fun_l12_n444(x)
+ if (x < 1)
+ fun_l13_n632(x)
+ else
+ fun_l13_n808(x)
+ end
+end
+
+def fun_l12_n445(x)
+ if (x < 1)
+ fun_l13_n159(x)
+ else
+ fun_l13_n251(x)
+ end
+end
+
+def fun_l12_n446(x)
+ if (x < 1)
+ fun_l13_n939(x)
+ else
+ fun_l13_n231(x)
+ end
+end
+
+def fun_l12_n447(x)
+ if (x < 1)
+ fun_l13_n971(x)
+ else
+ fun_l13_n103(x)
+ end
+end
+
+def fun_l12_n448(x)
+ if (x < 1)
+ fun_l13_n556(x)
+ else
+ fun_l13_n356(x)
+ end
+end
+
+def fun_l12_n449(x)
+ if (x < 1)
+ fun_l13_n999(x)
+ else
+ fun_l13_n722(x)
+ end
+end
+
+def fun_l12_n450(x)
+ if (x < 1)
+ fun_l13_n387(x)
+ else
+ fun_l13_n15(x)
+ end
+end
+
+def fun_l12_n451(x)
+ if (x < 1)
+ fun_l13_n736(x)
+ else
+ fun_l13_n869(x)
+ end
+end
+
+def fun_l12_n452(x)
+ if (x < 1)
+ fun_l13_n984(x)
+ else
+ fun_l13_n396(x)
+ end
+end
+
+def fun_l12_n453(x)
+ if (x < 1)
+ fun_l13_n375(x)
+ else
+ fun_l13_n275(x)
+ end
+end
+
+def fun_l12_n454(x)
+ if (x < 1)
+ fun_l13_n100(x)
+ else
+ fun_l13_n956(x)
+ end
+end
+
+def fun_l12_n455(x)
+ if (x < 1)
+ fun_l13_n575(x)
+ else
+ fun_l13_n22(x)
+ end
+end
+
+def fun_l12_n456(x)
+ if (x < 1)
+ fun_l13_n515(x)
+ else
+ fun_l13_n716(x)
+ end
+end
+
+def fun_l12_n457(x)
+ if (x < 1)
+ fun_l13_n953(x)
+ else
+ fun_l13_n823(x)
+ end
+end
+
+def fun_l12_n458(x)
+ if (x < 1)
+ fun_l13_n343(x)
+ else
+ fun_l13_n843(x)
+ end
+end
+
+def fun_l12_n459(x)
+ if (x < 1)
+ fun_l13_n209(x)
+ else
+ fun_l13_n464(x)
+ end
+end
+
+def fun_l12_n460(x)
+ if (x < 1)
+ fun_l13_n281(x)
+ else
+ fun_l13_n165(x)
+ end
+end
+
+def fun_l12_n461(x)
+ if (x < 1)
+ fun_l13_n416(x)
+ else
+ fun_l13_n896(x)
+ end
+end
+
+def fun_l12_n462(x)
+ if (x < 1)
+ fun_l13_n677(x)
+ else
+ fun_l13_n767(x)
+ end
+end
+
+def fun_l12_n463(x)
+ if (x < 1)
+ fun_l13_n271(x)
+ else
+ fun_l13_n515(x)
+ end
+end
+
+def fun_l12_n464(x)
+ if (x < 1)
+ fun_l13_n589(x)
+ else
+ fun_l13_n447(x)
+ end
+end
+
+def fun_l12_n465(x)
+ if (x < 1)
+ fun_l13_n316(x)
+ else
+ fun_l13_n309(x)
+ end
+end
+
+def fun_l12_n466(x)
+ if (x < 1)
+ fun_l13_n48(x)
+ else
+ fun_l13_n999(x)
+ end
+end
+
+def fun_l12_n467(x)
+ if (x < 1)
+ fun_l13_n334(x)
+ else
+ fun_l13_n138(x)
+ end
+end
+
+def fun_l12_n468(x)
+ if (x < 1)
+ fun_l13_n483(x)
+ else
+ fun_l13_n353(x)
+ end
+end
+
+def fun_l12_n469(x)
+ if (x < 1)
+ fun_l13_n893(x)
+ else
+ fun_l13_n114(x)
+ end
+end
+
+def fun_l12_n470(x)
+ if (x < 1)
+ fun_l13_n945(x)
+ else
+ fun_l13_n438(x)
+ end
+end
+
+def fun_l12_n471(x)
+ if (x < 1)
+ fun_l13_n546(x)
+ else
+ fun_l13_n181(x)
+ end
+end
+
+def fun_l12_n472(x)
+ if (x < 1)
+ fun_l13_n443(x)
+ else
+ fun_l13_n35(x)
+ end
+end
+
+def fun_l12_n473(x)
+ if (x < 1)
+ fun_l13_n611(x)
+ else
+ fun_l13_n106(x)
+ end
+end
+
+def fun_l12_n474(x)
+ if (x < 1)
+ fun_l13_n408(x)
+ else
+ fun_l13_n162(x)
+ end
+end
+
+def fun_l12_n475(x)
+ if (x < 1)
+ fun_l13_n104(x)
+ else
+ fun_l13_n173(x)
+ end
+end
+
+def fun_l12_n476(x)
+ if (x < 1)
+ fun_l13_n922(x)
+ else
+ fun_l13_n593(x)
+ end
+end
+
+def fun_l12_n477(x)
+ if (x < 1)
+ fun_l13_n650(x)
+ else
+ fun_l13_n659(x)
+ end
+end
+
+def fun_l12_n478(x)
+ if (x < 1)
+ fun_l13_n746(x)
+ else
+ fun_l13_n484(x)
+ end
+end
+
+def fun_l12_n479(x)
+ if (x < 1)
+ fun_l13_n366(x)
+ else
+ fun_l13_n318(x)
+ end
+end
+
+def fun_l12_n480(x)
+ if (x < 1)
+ fun_l13_n995(x)
+ else
+ fun_l13_n108(x)
+ end
+end
+
+def fun_l12_n481(x)
+ if (x < 1)
+ fun_l13_n61(x)
+ else
+ fun_l13_n426(x)
+ end
+end
+
+def fun_l12_n482(x)
+ if (x < 1)
+ fun_l13_n578(x)
+ else
+ fun_l13_n955(x)
+ end
+end
+
+def fun_l12_n483(x)
+ if (x < 1)
+ fun_l13_n650(x)
+ else
+ fun_l13_n588(x)
+ end
+end
+
+def fun_l12_n484(x)
+ if (x < 1)
+ fun_l13_n842(x)
+ else
+ fun_l13_n198(x)
+ end
+end
+
+def fun_l12_n485(x)
+ if (x < 1)
+ fun_l13_n439(x)
+ else
+ fun_l13_n372(x)
+ end
+end
+
+def fun_l12_n486(x)
+ if (x < 1)
+ fun_l13_n94(x)
+ else
+ fun_l13_n531(x)
+ end
+end
+
+def fun_l12_n487(x)
+ if (x < 1)
+ fun_l13_n743(x)
+ else
+ fun_l13_n955(x)
+ end
+end
+
+def fun_l12_n488(x)
+ if (x < 1)
+ fun_l13_n648(x)
+ else
+ fun_l13_n849(x)
+ end
+end
+
+def fun_l12_n489(x)
+ if (x < 1)
+ fun_l13_n371(x)
+ else
+ fun_l13_n972(x)
+ end
+end
+
+def fun_l12_n490(x)
+ if (x < 1)
+ fun_l13_n128(x)
+ else
+ fun_l13_n617(x)
+ end
+end
+
+def fun_l12_n491(x)
+ if (x < 1)
+ fun_l13_n22(x)
+ else
+ fun_l13_n201(x)
+ end
+end
+
+def fun_l12_n492(x)
+ if (x < 1)
+ fun_l13_n209(x)
+ else
+ fun_l13_n679(x)
+ end
+end
+
+def fun_l12_n493(x)
+ if (x < 1)
+ fun_l13_n415(x)
+ else
+ fun_l13_n765(x)
+ end
+end
+
+def fun_l12_n494(x)
+ if (x < 1)
+ fun_l13_n498(x)
+ else
+ fun_l13_n719(x)
+ end
+end
+
+def fun_l12_n495(x)
+ if (x < 1)
+ fun_l13_n492(x)
+ else
+ fun_l13_n161(x)
+ end
+end
+
+def fun_l12_n496(x)
+ if (x < 1)
+ fun_l13_n162(x)
+ else
+ fun_l13_n54(x)
+ end
+end
+
+def fun_l12_n497(x)
+ if (x < 1)
+ fun_l13_n743(x)
+ else
+ fun_l13_n834(x)
+ end
+end
+
+def fun_l12_n498(x)
+ if (x < 1)
+ fun_l13_n376(x)
+ else
+ fun_l13_n676(x)
+ end
+end
+
+def fun_l12_n499(x)
+ if (x < 1)
+ fun_l13_n626(x)
+ else
+ fun_l13_n357(x)
+ end
+end
+
+def fun_l12_n500(x)
+ if (x < 1)
+ fun_l13_n874(x)
+ else
+ fun_l13_n53(x)
+ end
+end
+
+def fun_l12_n501(x)
+ if (x < 1)
+ fun_l13_n146(x)
+ else
+ fun_l13_n732(x)
+ end
+end
+
+def fun_l12_n502(x)
+ if (x < 1)
+ fun_l13_n908(x)
+ else
+ fun_l13_n933(x)
+ end
+end
+
+def fun_l12_n503(x)
+ if (x < 1)
+ fun_l13_n758(x)
+ else
+ fun_l13_n289(x)
+ end
+end
+
+def fun_l12_n504(x)
+ if (x < 1)
+ fun_l13_n913(x)
+ else
+ fun_l13_n770(x)
+ end
+end
+
+def fun_l12_n505(x)
+ if (x < 1)
+ fun_l13_n305(x)
+ else
+ fun_l13_n990(x)
+ end
+end
+
+def fun_l12_n506(x)
+ if (x < 1)
+ fun_l13_n79(x)
+ else
+ fun_l13_n199(x)
+ end
+end
+
+def fun_l12_n507(x)
+ if (x < 1)
+ fun_l13_n430(x)
+ else
+ fun_l13_n394(x)
+ end
+end
+
+def fun_l12_n508(x)
+ if (x < 1)
+ fun_l13_n835(x)
+ else
+ fun_l13_n64(x)
+ end
+end
+
+def fun_l12_n509(x)
+ if (x < 1)
+ fun_l13_n661(x)
+ else
+ fun_l13_n301(x)
+ end
+end
+
+def fun_l12_n510(x)
+ if (x < 1)
+ fun_l13_n672(x)
+ else
+ fun_l13_n498(x)
+ end
+end
+
+def fun_l12_n511(x)
+ if (x < 1)
+ fun_l13_n540(x)
+ else
+ fun_l13_n57(x)
+ end
+end
+
+def fun_l12_n512(x)
+ if (x < 1)
+ fun_l13_n634(x)
+ else
+ fun_l13_n790(x)
+ end
+end
+
+def fun_l12_n513(x)
+ if (x < 1)
+ fun_l13_n998(x)
+ else
+ fun_l13_n3(x)
+ end
+end
+
+def fun_l12_n514(x)
+ if (x < 1)
+ fun_l13_n482(x)
+ else
+ fun_l13_n116(x)
+ end
+end
+
+def fun_l12_n515(x)
+ if (x < 1)
+ fun_l13_n967(x)
+ else
+ fun_l13_n17(x)
+ end
+end
+
+def fun_l12_n516(x)
+ if (x < 1)
+ fun_l13_n614(x)
+ else
+ fun_l13_n260(x)
+ end
+end
+
+def fun_l12_n517(x)
+ if (x < 1)
+ fun_l13_n273(x)
+ else
+ fun_l13_n982(x)
+ end
+end
+
+def fun_l12_n518(x)
+ if (x < 1)
+ fun_l13_n786(x)
+ else
+ fun_l13_n186(x)
+ end
+end
+
+def fun_l12_n519(x)
+ if (x < 1)
+ fun_l13_n990(x)
+ else
+ fun_l13_n223(x)
+ end
+end
+
+def fun_l12_n520(x)
+ if (x < 1)
+ fun_l13_n406(x)
+ else
+ fun_l13_n374(x)
+ end
+end
+
+def fun_l12_n521(x)
+ if (x < 1)
+ fun_l13_n548(x)
+ else
+ fun_l13_n160(x)
+ end
+end
+
+def fun_l12_n522(x)
+ if (x < 1)
+ fun_l13_n249(x)
+ else
+ fun_l13_n295(x)
+ end
+end
+
+def fun_l12_n523(x)
+ if (x < 1)
+ fun_l13_n434(x)
+ else
+ fun_l13_n73(x)
+ end
+end
+
+def fun_l12_n524(x)
+ if (x < 1)
+ fun_l13_n550(x)
+ else
+ fun_l13_n472(x)
+ end
+end
+
+def fun_l12_n525(x)
+ if (x < 1)
+ fun_l13_n720(x)
+ else
+ fun_l13_n979(x)
+ end
+end
+
+def fun_l12_n526(x)
+ if (x < 1)
+ fun_l13_n806(x)
+ else
+ fun_l13_n156(x)
+ end
+end
+
+def fun_l12_n527(x)
+ if (x < 1)
+ fun_l13_n689(x)
+ else
+ fun_l13_n781(x)
+ end
+end
+
+def fun_l12_n528(x)
+ if (x < 1)
+ fun_l13_n130(x)
+ else
+ fun_l13_n909(x)
+ end
+end
+
+def fun_l12_n529(x)
+ if (x < 1)
+ fun_l13_n762(x)
+ else
+ fun_l13_n301(x)
+ end
+end
+
+def fun_l12_n530(x)
+ if (x < 1)
+ fun_l13_n580(x)
+ else
+ fun_l13_n269(x)
+ end
+end
+
+def fun_l12_n531(x)
+ if (x < 1)
+ fun_l13_n427(x)
+ else
+ fun_l13_n279(x)
+ end
+end
+
+def fun_l12_n532(x)
+ if (x < 1)
+ fun_l13_n408(x)
+ else
+ fun_l13_n523(x)
+ end
+end
+
+def fun_l12_n533(x)
+ if (x < 1)
+ fun_l13_n358(x)
+ else
+ fun_l13_n386(x)
+ end
+end
+
+def fun_l12_n534(x)
+ if (x < 1)
+ fun_l13_n401(x)
+ else
+ fun_l13_n148(x)
+ end
+end
+
+def fun_l12_n535(x)
+ if (x < 1)
+ fun_l13_n588(x)
+ else
+ fun_l13_n607(x)
+ end
+end
+
+def fun_l12_n536(x)
+ if (x < 1)
+ fun_l13_n445(x)
+ else
+ fun_l13_n681(x)
+ end
+end
+
+def fun_l12_n537(x)
+ if (x < 1)
+ fun_l13_n16(x)
+ else
+ fun_l13_n931(x)
+ end
+end
+
+def fun_l12_n538(x)
+ if (x < 1)
+ fun_l13_n567(x)
+ else
+ fun_l13_n9(x)
+ end
+end
+
+def fun_l12_n539(x)
+ if (x < 1)
+ fun_l13_n584(x)
+ else
+ fun_l13_n46(x)
+ end
+end
+
+def fun_l12_n540(x)
+ if (x < 1)
+ fun_l13_n147(x)
+ else
+ fun_l13_n498(x)
+ end
+end
+
+def fun_l12_n541(x)
+ if (x < 1)
+ fun_l13_n727(x)
+ else
+ fun_l13_n152(x)
+ end
+end
+
+def fun_l12_n542(x)
+ if (x < 1)
+ fun_l13_n797(x)
+ else
+ fun_l13_n789(x)
+ end
+end
+
+def fun_l12_n543(x)
+ if (x < 1)
+ fun_l13_n711(x)
+ else
+ fun_l13_n939(x)
+ end
+end
+
+def fun_l12_n544(x)
+ if (x < 1)
+ fun_l13_n276(x)
+ else
+ fun_l13_n325(x)
+ end
+end
+
+def fun_l12_n545(x)
+ if (x < 1)
+ fun_l13_n800(x)
+ else
+ fun_l13_n974(x)
+ end
+end
+
+def fun_l12_n546(x)
+ if (x < 1)
+ fun_l13_n654(x)
+ else
+ fun_l13_n331(x)
+ end
+end
+
+def fun_l12_n547(x)
+ if (x < 1)
+ fun_l13_n179(x)
+ else
+ fun_l13_n395(x)
+ end
+end
+
+def fun_l12_n548(x)
+ if (x < 1)
+ fun_l13_n348(x)
+ else
+ fun_l13_n210(x)
+ end
+end
+
+def fun_l12_n549(x)
+ if (x < 1)
+ fun_l13_n669(x)
+ else
+ fun_l13_n459(x)
+ end
+end
+
+def fun_l12_n550(x)
+ if (x < 1)
+ fun_l13_n316(x)
+ else
+ fun_l13_n846(x)
+ end
+end
+
+def fun_l12_n551(x)
+ if (x < 1)
+ fun_l13_n262(x)
+ else
+ fun_l13_n430(x)
+ end
+end
+
+def fun_l12_n552(x)
+ if (x < 1)
+ fun_l13_n224(x)
+ else
+ fun_l13_n866(x)
+ end
+end
+
+def fun_l12_n553(x)
+ if (x < 1)
+ fun_l13_n551(x)
+ else
+ fun_l13_n30(x)
+ end
+end
+
+def fun_l12_n554(x)
+ if (x < 1)
+ fun_l13_n864(x)
+ else
+ fun_l13_n931(x)
+ end
+end
+
+def fun_l12_n555(x)
+ if (x < 1)
+ fun_l13_n427(x)
+ else
+ fun_l13_n138(x)
+ end
+end
+
+def fun_l12_n556(x)
+ if (x < 1)
+ fun_l13_n603(x)
+ else
+ fun_l13_n167(x)
+ end
+end
+
+def fun_l12_n557(x)
+ if (x < 1)
+ fun_l13_n858(x)
+ else
+ fun_l13_n123(x)
+ end
+end
+
+def fun_l12_n558(x)
+ if (x < 1)
+ fun_l13_n729(x)
+ else
+ fun_l13_n769(x)
+ end
+end
+
+def fun_l12_n559(x)
+ if (x < 1)
+ fun_l13_n529(x)
+ else
+ fun_l13_n114(x)
+ end
+end
+
+def fun_l12_n560(x)
+ if (x < 1)
+ fun_l13_n727(x)
+ else
+ fun_l13_n673(x)
+ end
+end
+
+def fun_l12_n561(x)
+ if (x < 1)
+ fun_l13_n742(x)
+ else
+ fun_l13_n981(x)
+ end
+end
+
+def fun_l12_n562(x)
+ if (x < 1)
+ fun_l13_n29(x)
+ else
+ fun_l13_n493(x)
+ end
+end
+
+def fun_l12_n563(x)
+ if (x < 1)
+ fun_l13_n207(x)
+ else
+ fun_l13_n361(x)
+ end
+end
+
+def fun_l12_n564(x)
+ if (x < 1)
+ fun_l13_n370(x)
+ else
+ fun_l13_n185(x)
+ end
+end
+
+def fun_l12_n565(x)
+ if (x < 1)
+ fun_l13_n755(x)
+ else
+ fun_l13_n28(x)
+ end
+end
+
+def fun_l12_n566(x)
+ if (x < 1)
+ fun_l13_n332(x)
+ else
+ fun_l13_n718(x)
+ end
+end
+
+def fun_l12_n567(x)
+ if (x < 1)
+ fun_l13_n329(x)
+ else
+ fun_l13_n623(x)
+ end
+end
+
+def fun_l12_n568(x)
+ if (x < 1)
+ fun_l13_n592(x)
+ else
+ fun_l13_n870(x)
+ end
+end
+
+def fun_l12_n569(x)
+ if (x < 1)
+ fun_l13_n539(x)
+ else
+ fun_l13_n68(x)
+ end
+end
+
+def fun_l12_n570(x)
+ if (x < 1)
+ fun_l13_n794(x)
+ else
+ fun_l13_n617(x)
+ end
+end
+
+def fun_l12_n571(x)
+ if (x < 1)
+ fun_l13_n801(x)
+ else
+ fun_l13_n610(x)
+ end
+end
+
+def fun_l12_n572(x)
+ if (x < 1)
+ fun_l13_n781(x)
+ else
+ fun_l13_n879(x)
+ end
+end
+
+def fun_l12_n573(x)
+ if (x < 1)
+ fun_l13_n519(x)
+ else
+ fun_l13_n748(x)
+ end
+end
+
+def fun_l12_n574(x)
+ if (x < 1)
+ fun_l13_n416(x)
+ else
+ fun_l13_n908(x)
+ end
+end
+
+def fun_l12_n575(x)
+ if (x < 1)
+ fun_l13_n288(x)
+ else
+ fun_l13_n925(x)
+ end
+end
+
+def fun_l12_n576(x)
+ if (x < 1)
+ fun_l13_n398(x)
+ else
+ fun_l13_n185(x)
+ end
+end
+
+def fun_l12_n577(x)
+ if (x < 1)
+ fun_l13_n742(x)
+ else
+ fun_l13_n768(x)
+ end
+end
+
+def fun_l12_n578(x)
+ if (x < 1)
+ fun_l13_n472(x)
+ else
+ fun_l13_n474(x)
+ end
+end
+
+def fun_l12_n579(x)
+ if (x < 1)
+ fun_l13_n229(x)
+ else
+ fun_l13_n479(x)
+ end
+end
+
+def fun_l12_n580(x)
+ if (x < 1)
+ fun_l13_n483(x)
+ else
+ fun_l13_n60(x)
+ end
+end
+
+def fun_l12_n581(x)
+ if (x < 1)
+ fun_l13_n971(x)
+ else
+ fun_l13_n958(x)
+ end
+end
+
+def fun_l12_n582(x)
+ if (x < 1)
+ fun_l13_n612(x)
+ else
+ fun_l13_n491(x)
+ end
+end
+
+def fun_l12_n583(x)
+ if (x < 1)
+ fun_l13_n320(x)
+ else
+ fun_l13_n356(x)
+ end
+end
+
+def fun_l12_n584(x)
+ if (x < 1)
+ fun_l13_n521(x)
+ else
+ fun_l13_n126(x)
+ end
+end
+
+def fun_l12_n585(x)
+ if (x < 1)
+ fun_l13_n778(x)
+ else
+ fun_l13_n503(x)
+ end
+end
+
+def fun_l12_n586(x)
+ if (x < 1)
+ fun_l13_n715(x)
+ else
+ fun_l13_n849(x)
+ end
+end
+
+def fun_l12_n587(x)
+ if (x < 1)
+ fun_l13_n192(x)
+ else
+ fun_l13_n278(x)
+ end
+end
+
+def fun_l12_n588(x)
+ if (x < 1)
+ fun_l13_n882(x)
+ else
+ fun_l13_n992(x)
+ end
+end
+
+def fun_l12_n589(x)
+ if (x < 1)
+ fun_l13_n693(x)
+ else
+ fun_l13_n734(x)
+ end
+end
+
+def fun_l12_n590(x)
+ if (x < 1)
+ fun_l13_n207(x)
+ else
+ fun_l13_n674(x)
+ end
+end
+
+def fun_l12_n591(x)
+ if (x < 1)
+ fun_l13_n409(x)
+ else
+ fun_l13_n937(x)
+ end
+end
+
+def fun_l12_n592(x)
+ if (x < 1)
+ fun_l13_n424(x)
+ else
+ fun_l13_n709(x)
+ end
+end
+
+def fun_l12_n593(x)
+ if (x < 1)
+ fun_l13_n530(x)
+ else
+ fun_l13_n50(x)
+ end
+end
+
+def fun_l12_n594(x)
+ if (x < 1)
+ fun_l13_n451(x)
+ else
+ fun_l13_n513(x)
+ end
+end
+
+def fun_l12_n595(x)
+ if (x < 1)
+ fun_l13_n522(x)
+ else
+ fun_l13_n414(x)
+ end
+end
+
+def fun_l12_n596(x)
+ if (x < 1)
+ fun_l13_n352(x)
+ else
+ fun_l13_n323(x)
+ end
+end
+
+def fun_l12_n597(x)
+ if (x < 1)
+ fun_l13_n342(x)
+ else
+ fun_l13_n362(x)
+ end
+end
+
+def fun_l12_n598(x)
+ if (x < 1)
+ fun_l13_n870(x)
+ else
+ fun_l13_n366(x)
+ end
+end
+
+def fun_l12_n599(x)
+ if (x < 1)
+ fun_l13_n562(x)
+ else
+ fun_l13_n455(x)
+ end
+end
+
+def fun_l12_n600(x)
+ if (x < 1)
+ fun_l13_n554(x)
+ else
+ fun_l13_n929(x)
+ end
+end
+
+def fun_l12_n601(x)
+ if (x < 1)
+ fun_l13_n498(x)
+ else
+ fun_l13_n287(x)
+ end
+end
+
+def fun_l12_n602(x)
+ if (x < 1)
+ fun_l13_n9(x)
+ else
+ fun_l13_n258(x)
+ end
+end
+
+def fun_l12_n603(x)
+ if (x < 1)
+ fun_l13_n976(x)
+ else
+ fun_l13_n604(x)
+ end
+end
+
+def fun_l12_n604(x)
+ if (x < 1)
+ fun_l13_n411(x)
+ else
+ fun_l13_n238(x)
+ end
+end
+
+def fun_l12_n605(x)
+ if (x < 1)
+ fun_l13_n80(x)
+ else
+ fun_l13_n665(x)
+ end
+end
+
+def fun_l12_n606(x)
+ if (x < 1)
+ fun_l13_n453(x)
+ else
+ fun_l13_n642(x)
+ end
+end
+
+def fun_l12_n607(x)
+ if (x < 1)
+ fun_l13_n247(x)
+ else
+ fun_l13_n651(x)
+ end
+end
+
+def fun_l12_n608(x)
+ if (x < 1)
+ fun_l13_n586(x)
+ else
+ fun_l13_n372(x)
+ end
+end
+
+def fun_l12_n609(x)
+ if (x < 1)
+ fun_l13_n623(x)
+ else
+ fun_l13_n380(x)
+ end
+end
+
+def fun_l12_n610(x)
+ if (x < 1)
+ fun_l13_n399(x)
+ else
+ fun_l13_n43(x)
+ end
+end
+
+def fun_l12_n611(x)
+ if (x < 1)
+ fun_l13_n191(x)
+ else
+ fun_l13_n211(x)
+ end
+end
+
+def fun_l12_n612(x)
+ if (x < 1)
+ fun_l13_n719(x)
+ else
+ fun_l13_n663(x)
+ end
+end
+
+def fun_l12_n613(x)
+ if (x < 1)
+ fun_l13_n849(x)
+ else
+ fun_l13_n39(x)
+ end
+end
+
+def fun_l12_n614(x)
+ if (x < 1)
+ fun_l13_n822(x)
+ else
+ fun_l13_n927(x)
+ end
+end
+
+def fun_l12_n615(x)
+ if (x < 1)
+ fun_l13_n358(x)
+ else
+ fun_l13_n364(x)
+ end
+end
+
+def fun_l12_n616(x)
+ if (x < 1)
+ fun_l13_n685(x)
+ else
+ fun_l13_n897(x)
+ end
+end
+
+def fun_l12_n617(x)
+ if (x < 1)
+ fun_l13_n243(x)
+ else
+ fun_l13_n138(x)
+ end
+end
+
+def fun_l12_n618(x)
+ if (x < 1)
+ fun_l13_n737(x)
+ else
+ fun_l13_n187(x)
+ end
+end
+
+def fun_l12_n619(x)
+ if (x < 1)
+ fun_l13_n56(x)
+ else
+ fun_l13_n684(x)
+ end
+end
+
+def fun_l12_n620(x)
+ if (x < 1)
+ fun_l13_n865(x)
+ else
+ fun_l13_n886(x)
+ end
+end
+
+def fun_l12_n621(x)
+ if (x < 1)
+ fun_l13_n749(x)
+ else
+ fun_l13_n554(x)
+ end
+end
+
+def fun_l12_n622(x)
+ if (x < 1)
+ fun_l13_n162(x)
+ else
+ fun_l13_n600(x)
+ end
+end
+
+def fun_l12_n623(x)
+ if (x < 1)
+ fun_l13_n763(x)
+ else
+ fun_l13_n227(x)
+ end
+end
+
+def fun_l12_n624(x)
+ if (x < 1)
+ fun_l13_n767(x)
+ else
+ fun_l13_n431(x)
+ end
+end
+
+def fun_l12_n625(x)
+ if (x < 1)
+ fun_l13_n347(x)
+ else
+ fun_l13_n214(x)
+ end
+end
+
+def fun_l12_n626(x)
+ if (x < 1)
+ fun_l13_n365(x)
+ else
+ fun_l13_n747(x)
+ end
+end
+
+def fun_l12_n627(x)
+ if (x < 1)
+ fun_l13_n783(x)
+ else
+ fun_l13_n597(x)
+ end
+end
+
+def fun_l12_n628(x)
+ if (x < 1)
+ fun_l13_n249(x)
+ else
+ fun_l13_n906(x)
+ end
+end
+
+def fun_l12_n629(x)
+ if (x < 1)
+ fun_l13_n803(x)
+ else
+ fun_l13_n855(x)
+ end
+end
+
+def fun_l12_n630(x)
+ if (x < 1)
+ fun_l13_n981(x)
+ else
+ fun_l13_n38(x)
+ end
+end
+
+def fun_l12_n631(x)
+ if (x < 1)
+ fun_l13_n437(x)
+ else
+ fun_l13_n158(x)
+ end
+end
+
+def fun_l12_n632(x)
+ if (x < 1)
+ fun_l13_n611(x)
+ else
+ fun_l13_n142(x)
+ end
+end
+
+def fun_l12_n633(x)
+ if (x < 1)
+ fun_l13_n880(x)
+ else
+ fun_l13_n172(x)
+ end
+end
+
+def fun_l12_n634(x)
+ if (x < 1)
+ fun_l13_n135(x)
+ else
+ fun_l13_n529(x)
+ end
+end
+
+def fun_l12_n635(x)
+ if (x < 1)
+ fun_l13_n694(x)
+ else
+ fun_l13_n949(x)
+ end
+end
+
+def fun_l12_n636(x)
+ if (x < 1)
+ fun_l13_n153(x)
+ else
+ fun_l13_n326(x)
+ end
+end
+
+def fun_l12_n637(x)
+ if (x < 1)
+ fun_l13_n318(x)
+ else
+ fun_l13_n372(x)
+ end
+end
+
+def fun_l12_n638(x)
+ if (x < 1)
+ fun_l13_n467(x)
+ else
+ fun_l13_n450(x)
+ end
+end
+
+def fun_l12_n639(x)
+ if (x < 1)
+ fun_l13_n397(x)
+ else
+ fun_l13_n138(x)
+ end
+end
+
+def fun_l12_n640(x)
+ if (x < 1)
+ fun_l13_n408(x)
+ else
+ fun_l13_n335(x)
+ end
+end
+
+def fun_l12_n641(x)
+ if (x < 1)
+ fun_l13_n342(x)
+ else
+ fun_l13_n856(x)
+ end
+end
+
+def fun_l12_n642(x)
+ if (x < 1)
+ fun_l13_n163(x)
+ else
+ fun_l13_n979(x)
+ end
+end
+
+def fun_l12_n643(x)
+ if (x < 1)
+ fun_l13_n509(x)
+ else
+ fun_l13_n153(x)
+ end
+end
+
+def fun_l12_n644(x)
+ if (x < 1)
+ fun_l13_n3(x)
+ else
+ fun_l13_n55(x)
+ end
+end
+
+def fun_l12_n645(x)
+ if (x < 1)
+ fun_l13_n730(x)
+ else
+ fun_l13_n52(x)
+ end
+end
+
+def fun_l12_n646(x)
+ if (x < 1)
+ fun_l13_n553(x)
+ else
+ fun_l13_n885(x)
+ end
+end
+
+def fun_l12_n647(x)
+ if (x < 1)
+ fun_l13_n866(x)
+ else
+ fun_l13_n684(x)
+ end
+end
+
+def fun_l12_n648(x)
+ if (x < 1)
+ fun_l13_n989(x)
+ else
+ fun_l13_n511(x)
+ end
+end
+
+def fun_l12_n649(x)
+ if (x < 1)
+ fun_l13_n527(x)
+ else
+ fun_l13_n166(x)
+ end
+end
+
+def fun_l12_n650(x)
+ if (x < 1)
+ fun_l13_n507(x)
+ else
+ fun_l13_n527(x)
+ end
+end
+
+def fun_l12_n651(x)
+ if (x < 1)
+ fun_l13_n174(x)
+ else
+ fun_l13_n881(x)
+ end
+end
+
+def fun_l12_n652(x)
+ if (x < 1)
+ fun_l13_n302(x)
+ else
+ fun_l13_n3(x)
+ end
+end
+
+def fun_l12_n653(x)
+ if (x < 1)
+ fun_l13_n971(x)
+ else
+ fun_l13_n601(x)
+ end
+end
+
+def fun_l12_n654(x)
+ if (x < 1)
+ fun_l13_n440(x)
+ else
+ fun_l13_n286(x)
+ end
+end
+
+def fun_l12_n655(x)
+ if (x < 1)
+ fun_l13_n208(x)
+ else
+ fun_l13_n275(x)
+ end
+end
+
+def fun_l12_n656(x)
+ if (x < 1)
+ fun_l13_n954(x)
+ else
+ fun_l13_n991(x)
+ end
+end
+
+def fun_l12_n657(x)
+ if (x < 1)
+ fun_l13_n212(x)
+ else
+ fun_l13_n640(x)
+ end
+end
+
+def fun_l12_n658(x)
+ if (x < 1)
+ fun_l13_n733(x)
+ else
+ fun_l13_n459(x)
+ end
+end
+
+def fun_l12_n659(x)
+ if (x < 1)
+ fun_l13_n767(x)
+ else
+ fun_l13_n581(x)
+ end
+end
+
+def fun_l12_n660(x)
+ if (x < 1)
+ fun_l13_n421(x)
+ else
+ fun_l13_n19(x)
+ end
+end
+
+def fun_l12_n661(x)
+ if (x < 1)
+ fun_l13_n500(x)
+ else
+ fun_l13_n464(x)
+ end
+end
+
+def fun_l12_n662(x)
+ if (x < 1)
+ fun_l13_n26(x)
+ else
+ fun_l13_n300(x)
+ end
+end
+
+def fun_l12_n663(x)
+ if (x < 1)
+ fun_l13_n160(x)
+ else
+ fun_l13_n112(x)
+ end
+end
+
+def fun_l12_n664(x)
+ if (x < 1)
+ fun_l13_n181(x)
+ else
+ fun_l13_n511(x)
+ end
+end
+
+def fun_l12_n665(x)
+ if (x < 1)
+ fun_l13_n573(x)
+ else
+ fun_l13_n283(x)
+ end
+end
+
+def fun_l12_n666(x)
+ if (x < 1)
+ fun_l13_n562(x)
+ else
+ fun_l13_n992(x)
+ end
+end
+
+def fun_l12_n667(x)
+ if (x < 1)
+ fun_l13_n426(x)
+ else
+ fun_l13_n921(x)
+ end
+end
+
+def fun_l12_n668(x)
+ if (x < 1)
+ fun_l13_n319(x)
+ else
+ fun_l13_n226(x)
+ end
+end
+
+def fun_l12_n669(x)
+ if (x < 1)
+ fun_l13_n832(x)
+ else
+ fun_l13_n690(x)
+ end
+end
+
+def fun_l12_n670(x)
+ if (x < 1)
+ fun_l13_n921(x)
+ else
+ fun_l13_n964(x)
+ end
+end
+
+def fun_l12_n671(x)
+ if (x < 1)
+ fun_l13_n823(x)
+ else
+ fun_l13_n903(x)
+ end
+end
+
+def fun_l12_n672(x)
+ if (x < 1)
+ fun_l13_n469(x)
+ else
+ fun_l13_n914(x)
+ end
+end
+
+def fun_l12_n673(x)
+ if (x < 1)
+ fun_l13_n478(x)
+ else
+ fun_l13_n481(x)
+ end
+end
+
+def fun_l12_n674(x)
+ if (x < 1)
+ fun_l13_n762(x)
+ else
+ fun_l13_n464(x)
+ end
+end
+
+def fun_l12_n675(x)
+ if (x < 1)
+ fun_l13_n930(x)
+ else
+ fun_l13_n587(x)
+ end
+end
+
+def fun_l12_n676(x)
+ if (x < 1)
+ fun_l13_n351(x)
+ else
+ fun_l13_n239(x)
+ end
+end
+
+def fun_l12_n677(x)
+ if (x < 1)
+ fun_l13_n989(x)
+ else
+ fun_l13_n424(x)
+ end
+end
+
+def fun_l12_n678(x)
+ if (x < 1)
+ fun_l13_n505(x)
+ else
+ fun_l13_n186(x)
+ end
+end
+
+def fun_l12_n679(x)
+ if (x < 1)
+ fun_l13_n665(x)
+ else
+ fun_l13_n536(x)
+ end
+end
+
+def fun_l12_n680(x)
+ if (x < 1)
+ fun_l13_n734(x)
+ else
+ fun_l13_n36(x)
+ end
+end
+
+def fun_l12_n681(x)
+ if (x < 1)
+ fun_l13_n380(x)
+ else
+ fun_l13_n340(x)
+ end
+end
+
+def fun_l12_n682(x)
+ if (x < 1)
+ fun_l13_n293(x)
+ else
+ fun_l13_n205(x)
+ end
+end
+
+def fun_l12_n683(x)
+ if (x < 1)
+ fun_l13_n412(x)
+ else
+ fun_l13_n13(x)
+ end
+end
+
+def fun_l12_n684(x)
+ if (x < 1)
+ fun_l13_n187(x)
+ else
+ fun_l13_n186(x)
+ end
+end
+
+def fun_l12_n685(x)
+ if (x < 1)
+ fun_l13_n299(x)
+ else
+ fun_l13_n875(x)
+ end
+end
+
+def fun_l12_n686(x)
+ if (x < 1)
+ fun_l13_n943(x)
+ else
+ fun_l13_n96(x)
+ end
+end
+
+def fun_l12_n687(x)
+ if (x < 1)
+ fun_l13_n736(x)
+ else
+ fun_l13_n377(x)
+ end
+end
+
+def fun_l12_n688(x)
+ if (x < 1)
+ fun_l13_n559(x)
+ else
+ fun_l13_n410(x)
+ end
+end
+
+def fun_l12_n689(x)
+ if (x < 1)
+ fun_l13_n538(x)
+ else
+ fun_l13_n521(x)
+ end
+end
+
+def fun_l12_n690(x)
+ if (x < 1)
+ fun_l13_n568(x)
+ else
+ fun_l13_n838(x)
+ end
+end
+
+def fun_l12_n691(x)
+ if (x < 1)
+ fun_l13_n556(x)
+ else
+ fun_l13_n42(x)
+ end
+end
+
+def fun_l12_n692(x)
+ if (x < 1)
+ fun_l13_n137(x)
+ else
+ fun_l13_n939(x)
+ end
+end
+
+def fun_l12_n693(x)
+ if (x < 1)
+ fun_l13_n974(x)
+ else
+ fun_l13_n308(x)
+ end
+end
+
+def fun_l12_n694(x)
+ if (x < 1)
+ fun_l13_n459(x)
+ else
+ fun_l13_n323(x)
+ end
+end
+
+def fun_l12_n695(x)
+ if (x < 1)
+ fun_l13_n829(x)
+ else
+ fun_l13_n909(x)
+ end
+end
+
+def fun_l12_n696(x)
+ if (x < 1)
+ fun_l13_n710(x)
+ else
+ fun_l13_n648(x)
+ end
+end
+
+def fun_l12_n697(x)
+ if (x < 1)
+ fun_l13_n27(x)
+ else
+ fun_l13_n500(x)
+ end
+end
+
+def fun_l12_n698(x)
+ if (x < 1)
+ fun_l13_n553(x)
+ else
+ fun_l13_n865(x)
+ end
+end
+
+def fun_l12_n699(x)
+ if (x < 1)
+ fun_l13_n126(x)
+ else
+ fun_l13_n789(x)
+ end
+end
+
+def fun_l12_n700(x)
+ if (x < 1)
+ fun_l13_n408(x)
+ else
+ fun_l13_n391(x)
+ end
+end
+
+def fun_l12_n701(x)
+ if (x < 1)
+ fun_l13_n469(x)
+ else
+ fun_l13_n48(x)
+ end
+end
+
+def fun_l12_n702(x)
+ if (x < 1)
+ fun_l13_n646(x)
+ else
+ fun_l13_n117(x)
+ end
+end
+
+def fun_l12_n703(x)
+ if (x < 1)
+ fun_l13_n461(x)
+ else
+ fun_l13_n114(x)
+ end
+end
+
+def fun_l12_n704(x)
+ if (x < 1)
+ fun_l13_n603(x)
+ else
+ fun_l13_n27(x)
+ end
+end
+
+def fun_l12_n705(x)
+ if (x < 1)
+ fun_l13_n842(x)
+ else
+ fun_l13_n792(x)
+ end
+end
+
+def fun_l12_n706(x)
+ if (x < 1)
+ fun_l13_n194(x)
+ else
+ fun_l13_n405(x)
+ end
+end
+
+def fun_l12_n707(x)
+ if (x < 1)
+ fun_l13_n975(x)
+ else
+ fun_l13_n933(x)
+ end
+end
+
+def fun_l12_n708(x)
+ if (x < 1)
+ fun_l13_n919(x)
+ else
+ fun_l13_n558(x)
+ end
+end
+
+def fun_l12_n709(x)
+ if (x < 1)
+ fun_l13_n293(x)
+ else
+ fun_l13_n868(x)
+ end
+end
+
+def fun_l12_n710(x)
+ if (x < 1)
+ fun_l13_n577(x)
+ else
+ fun_l13_n816(x)
+ end
+end
+
+def fun_l12_n711(x)
+ if (x < 1)
+ fun_l13_n625(x)
+ else
+ fun_l13_n319(x)
+ end
+end
+
+def fun_l12_n712(x)
+ if (x < 1)
+ fun_l13_n100(x)
+ else
+ fun_l13_n421(x)
+ end
+end
+
+def fun_l12_n713(x)
+ if (x < 1)
+ fun_l13_n120(x)
+ else
+ fun_l13_n727(x)
+ end
+end
+
+def fun_l12_n714(x)
+ if (x < 1)
+ fun_l13_n346(x)
+ else
+ fun_l13_n399(x)
+ end
+end
+
+def fun_l12_n715(x)
+ if (x < 1)
+ fun_l13_n64(x)
+ else
+ fun_l13_n895(x)
+ end
+end
+
+def fun_l12_n716(x)
+ if (x < 1)
+ fun_l13_n810(x)
+ else
+ fun_l13_n958(x)
+ end
+end
+
+def fun_l12_n717(x)
+ if (x < 1)
+ fun_l13_n24(x)
+ else
+ fun_l13_n851(x)
+ end
+end
+
+def fun_l12_n718(x)
+ if (x < 1)
+ fun_l13_n716(x)
+ else
+ fun_l13_n859(x)
+ end
+end
+
+def fun_l12_n719(x)
+ if (x < 1)
+ fun_l13_n556(x)
+ else
+ fun_l13_n999(x)
+ end
+end
+
+def fun_l12_n720(x)
+ if (x < 1)
+ fun_l13_n388(x)
+ else
+ fun_l13_n127(x)
+ end
+end
+
+def fun_l12_n721(x)
+ if (x < 1)
+ fun_l13_n447(x)
+ else
+ fun_l13_n880(x)
+ end
+end
+
+def fun_l12_n722(x)
+ if (x < 1)
+ fun_l13_n415(x)
+ else
+ fun_l13_n636(x)
+ end
+end
+
+def fun_l12_n723(x)
+ if (x < 1)
+ fun_l13_n315(x)
+ else
+ fun_l13_n766(x)
+ end
+end
+
+def fun_l12_n724(x)
+ if (x < 1)
+ fun_l13_n600(x)
+ else
+ fun_l13_n223(x)
+ end
+end
+
+def fun_l12_n725(x)
+ if (x < 1)
+ fun_l13_n773(x)
+ else
+ fun_l13_n523(x)
+ end
+end
+
+def fun_l12_n726(x)
+ if (x < 1)
+ fun_l13_n662(x)
+ else
+ fun_l13_n775(x)
+ end
+end
+
+def fun_l12_n727(x)
+ if (x < 1)
+ fun_l13_n553(x)
+ else
+ fun_l13_n247(x)
+ end
+end
+
+def fun_l12_n728(x)
+ if (x < 1)
+ fun_l13_n180(x)
+ else
+ fun_l13_n815(x)
+ end
+end
+
+def fun_l12_n729(x)
+ if (x < 1)
+ fun_l13_n786(x)
+ else
+ fun_l13_n729(x)
+ end
+end
+
+def fun_l12_n730(x)
+ if (x < 1)
+ fun_l13_n1(x)
+ else
+ fun_l13_n791(x)
+ end
+end
+
+def fun_l12_n731(x)
+ if (x < 1)
+ fun_l13_n216(x)
+ else
+ fun_l13_n682(x)
+ end
+end
+
+def fun_l12_n732(x)
+ if (x < 1)
+ fun_l13_n953(x)
+ else
+ fun_l13_n364(x)
+ end
+end
+
+def fun_l12_n733(x)
+ if (x < 1)
+ fun_l13_n164(x)
+ else
+ fun_l13_n277(x)
+ end
+end
+
+def fun_l12_n734(x)
+ if (x < 1)
+ fun_l13_n486(x)
+ else
+ fun_l13_n741(x)
+ end
+end
+
+def fun_l12_n735(x)
+ if (x < 1)
+ fun_l13_n310(x)
+ else
+ fun_l13_n940(x)
+ end
+end
+
+def fun_l12_n736(x)
+ if (x < 1)
+ fun_l13_n312(x)
+ else
+ fun_l13_n46(x)
+ end
+end
+
+def fun_l12_n737(x)
+ if (x < 1)
+ fun_l13_n473(x)
+ else
+ fun_l13_n728(x)
+ end
+end
+
+def fun_l12_n738(x)
+ if (x < 1)
+ fun_l13_n602(x)
+ else
+ fun_l13_n652(x)
+ end
+end
+
+def fun_l12_n739(x)
+ if (x < 1)
+ fun_l13_n397(x)
+ else
+ fun_l13_n855(x)
+ end
+end
+
+def fun_l12_n740(x)
+ if (x < 1)
+ fun_l13_n81(x)
+ else
+ fun_l13_n32(x)
+ end
+end
+
+def fun_l12_n741(x)
+ if (x < 1)
+ fun_l13_n822(x)
+ else
+ fun_l13_n231(x)
+ end
+end
+
+def fun_l12_n742(x)
+ if (x < 1)
+ fun_l13_n200(x)
+ else
+ fun_l13_n440(x)
+ end
+end
+
+def fun_l12_n743(x)
+ if (x < 1)
+ fun_l13_n415(x)
+ else
+ fun_l13_n631(x)
+ end
+end
+
+def fun_l12_n744(x)
+ if (x < 1)
+ fun_l13_n353(x)
+ else
+ fun_l13_n536(x)
+ end
+end
+
+def fun_l12_n745(x)
+ if (x < 1)
+ fun_l13_n986(x)
+ else
+ fun_l13_n384(x)
+ end
+end
+
+def fun_l12_n746(x)
+ if (x < 1)
+ fun_l13_n237(x)
+ else
+ fun_l13_n583(x)
+ end
+end
+
+def fun_l12_n747(x)
+ if (x < 1)
+ fun_l13_n518(x)
+ else
+ fun_l13_n717(x)
+ end
+end
+
+def fun_l12_n748(x)
+ if (x < 1)
+ fun_l13_n242(x)
+ else
+ fun_l13_n180(x)
+ end
+end
+
+def fun_l12_n749(x)
+ if (x < 1)
+ fun_l13_n369(x)
+ else
+ fun_l13_n249(x)
+ end
+end
+
+def fun_l12_n750(x)
+ if (x < 1)
+ fun_l13_n335(x)
+ else
+ fun_l13_n180(x)
+ end
+end
+
+def fun_l12_n751(x)
+ if (x < 1)
+ fun_l13_n952(x)
+ else
+ fun_l13_n506(x)
+ end
+end
+
+def fun_l12_n752(x)
+ if (x < 1)
+ fun_l13_n941(x)
+ else
+ fun_l13_n251(x)
+ end
+end
+
+def fun_l12_n753(x)
+ if (x < 1)
+ fun_l13_n21(x)
+ else
+ fun_l13_n536(x)
+ end
+end
+
+def fun_l12_n754(x)
+ if (x < 1)
+ fun_l13_n123(x)
+ else
+ fun_l13_n976(x)
+ end
+end
+
+def fun_l12_n755(x)
+ if (x < 1)
+ fun_l13_n229(x)
+ else
+ fun_l13_n535(x)
+ end
+end
+
+def fun_l12_n756(x)
+ if (x < 1)
+ fun_l13_n23(x)
+ else
+ fun_l13_n976(x)
+ end
+end
+
+def fun_l12_n757(x)
+ if (x < 1)
+ fun_l13_n755(x)
+ else
+ fun_l13_n677(x)
+ end
+end
+
+def fun_l12_n758(x)
+ if (x < 1)
+ fun_l13_n692(x)
+ else
+ fun_l13_n334(x)
+ end
+end
+
+def fun_l12_n759(x)
+ if (x < 1)
+ fun_l13_n380(x)
+ else
+ fun_l13_n903(x)
+ end
+end
+
+def fun_l12_n760(x)
+ if (x < 1)
+ fun_l13_n16(x)
+ else
+ fun_l13_n750(x)
+ end
+end
+
+def fun_l12_n761(x)
+ if (x < 1)
+ fun_l13_n186(x)
+ else
+ fun_l13_n639(x)
+ end
+end
+
+def fun_l12_n762(x)
+ if (x < 1)
+ fun_l13_n163(x)
+ else
+ fun_l13_n273(x)
+ end
+end
+
+def fun_l12_n763(x)
+ if (x < 1)
+ fun_l13_n791(x)
+ else
+ fun_l13_n55(x)
+ end
+end
+
+def fun_l12_n764(x)
+ if (x < 1)
+ fun_l13_n10(x)
+ else
+ fun_l13_n672(x)
+ end
+end
+
+def fun_l12_n765(x)
+ if (x < 1)
+ fun_l13_n382(x)
+ else
+ fun_l13_n284(x)
+ end
+end
+
+def fun_l12_n766(x)
+ if (x < 1)
+ fun_l13_n940(x)
+ else
+ fun_l13_n716(x)
+ end
+end
+
+def fun_l12_n767(x)
+ if (x < 1)
+ fun_l13_n414(x)
+ else
+ fun_l13_n997(x)
+ end
+end
+
+def fun_l12_n768(x)
+ if (x < 1)
+ fun_l13_n345(x)
+ else
+ fun_l13_n511(x)
+ end
+end
+
+def fun_l12_n769(x)
+ if (x < 1)
+ fun_l13_n915(x)
+ else
+ fun_l13_n907(x)
+ end
+end
+
+def fun_l12_n770(x)
+ if (x < 1)
+ fun_l13_n508(x)
+ else
+ fun_l13_n144(x)
+ end
+end
+
+def fun_l12_n771(x)
+ if (x < 1)
+ fun_l13_n764(x)
+ else
+ fun_l13_n211(x)
+ end
+end
+
+def fun_l12_n772(x)
+ if (x < 1)
+ fun_l13_n571(x)
+ else
+ fun_l13_n486(x)
+ end
+end
+
+def fun_l12_n773(x)
+ if (x < 1)
+ fun_l13_n503(x)
+ else
+ fun_l13_n561(x)
+ end
+end
+
+def fun_l12_n774(x)
+ if (x < 1)
+ fun_l13_n831(x)
+ else
+ fun_l13_n608(x)
+ end
+end
+
+def fun_l12_n775(x)
+ if (x < 1)
+ fun_l13_n254(x)
+ else
+ fun_l13_n626(x)
+ end
+end
+
+def fun_l12_n776(x)
+ if (x < 1)
+ fun_l13_n155(x)
+ else
+ fun_l13_n602(x)
+ end
+end
+
+def fun_l12_n777(x)
+ if (x < 1)
+ fun_l13_n331(x)
+ else
+ fun_l13_n837(x)
+ end
+end
+
+def fun_l12_n778(x)
+ if (x < 1)
+ fun_l13_n109(x)
+ else
+ fun_l13_n558(x)
+ end
+end
+
+def fun_l12_n779(x)
+ if (x < 1)
+ fun_l13_n557(x)
+ else
+ fun_l13_n784(x)
+ end
+end
+
+def fun_l12_n780(x)
+ if (x < 1)
+ fun_l13_n719(x)
+ else
+ fun_l13_n933(x)
+ end
+end
+
+def fun_l12_n781(x)
+ if (x < 1)
+ fun_l13_n63(x)
+ else
+ fun_l13_n776(x)
+ end
+end
+
+def fun_l12_n782(x)
+ if (x < 1)
+ fun_l13_n146(x)
+ else
+ fun_l13_n32(x)
+ end
+end
+
+def fun_l12_n783(x)
+ if (x < 1)
+ fun_l13_n452(x)
+ else
+ fun_l13_n621(x)
+ end
+end
+
+def fun_l12_n784(x)
+ if (x < 1)
+ fun_l13_n821(x)
+ else
+ fun_l13_n454(x)
+ end
+end
+
+def fun_l12_n785(x)
+ if (x < 1)
+ fun_l13_n943(x)
+ else
+ fun_l13_n835(x)
+ end
+end
+
+def fun_l12_n786(x)
+ if (x < 1)
+ fun_l13_n47(x)
+ else
+ fun_l13_n252(x)
+ end
+end
+
+def fun_l12_n787(x)
+ if (x < 1)
+ fun_l13_n759(x)
+ else
+ fun_l13_n820(x)
+ end
+end
+
+def fun_l12_n788(x)
+ if (x < 1)
+ fun_l13_n883(x)
+ else
+ fun_l13_n218(x)
+ end
+end
+
+def fun_l12_n789(x)
+ if (x < 1)
+ fun_l13_n10(x)
+ else
+ fun_l13_n765(x)
+ end
+end
+
+def fun_l12_n790(x)
+ if (x < 1)
+ fun_l13_n6(x)
+ else
+ fun_l13_n424(x)
+ end
+end
+
+def fun_l12_n791(x)
+ if (x < 1)
+ fun_l13_n645(x)
+ else
+ fun_l13_n598(x)
+ end
+end
+
+def fun_l12_n792(x)
+ if (x < 1)
+ fun_l13_n237(x)
+ else
+ fun_l13_n141(x)
+ end
+end
+
+def fun_l12_n793(x)
+ if (x < 1)
+ fun_l13_n793(x)
+ else
+ fun_l13_n109(x)
+ end
+end
+
+def fun_l12_n794(x)
+ if (x < 1)
+ fun_l13_n404(x)
+ else
+ fun_l13_n864(x)
+ end
+end
+
+def fun_l12_n795(x)
+ if (x < 1)
+ fun_l13_n511(x)
+ else
+ fun_l13_n620(x)
+ end
+end
+
+def fun_l12_n796(x)
+ if (x < 1)
+ fun_l13_n880(x)
+ else
+ fun_l13_n330(x)
+ end
+end
+
+def fun_l12_n797(x)
+ if (x < 1)
+ fun_l13_n637(x)
+ else
+ fun_l13_n13(x)
+ end
+end
+
+def fun_l12_n798(x)
+ if (x < 1)
+ fun_l13_n567(x)
+ else
+ fun_l13_n958(x)
+ end
+end
+
+def fun_l12_n799(x)
+ if (x < 1)
+ fun_l13_n715(x)
+ else
+ fun_l13_n983(x)
+ end
+end
+
+def fun_l12_n800(x)
+ if (x < 1)
+ fun_l13_n502(x)
+ else
+ fun_l13_n600(x)
+ end
+end
+
+def fun_l12_n801(x)
+ if (x < 1)
+ fun_l13_n645(x)
+ else
+ fun_l13_n713(x)
+ end
+end
+
+def fun_l12_n802(x)
+ if (x < 1)
+ fun_l13_n804(x)
+ else
+ fun_l13_n475(x)
+ end
+end
+
+def fun_l12_n803(x)
+ if (x < 1)
+ fun_l13_n286(x)
+ else
+ fun_l13_n135(x)
+ end
+end
+
+def fun_l12_n804(x)
+ if (x < 1)
+ fun_l13_n420(x)
+ else
+ fun_l13_n534(x)
+ end
+end
+
+def fun_l12_n805(x)
+ if (x < 1)
+ fun_l13_n345(x)
+ else
+ fun_l13_n833(x)
+ end
+end
+
+def fun_l12_n806(x)
+ if (x < 1)
+ fun_l13_n558(x)
+ else
+ fun_l13_n831(x)
+ end
+end
+
+def fun_l12_n807(x)
+ if (x < 1)
+ fun_l13_n82(x)
+ else
+ fun_l13_n56(x)
+ end
+end
+
+def fun_l12_n808(x)
+ if (x < 1)
+ fun_l13_n809(x)
+ else
+ fun_l13_n12(x)
+ end
+end
+
+def fun_l12_n809(x)
+ if (x < 1)
+ fun_l13_n450(x)
+ else
+ fun_l13_n326(x)
+ end
+end
+
+def fun_l12_n810(x)
+ if (x < 1)
+ fun_l13_n567(x)
+ else
+ fun_l13_n437(x)
+ end
+end
+
+def fun_l12_n811(x)
+ if (x < 1)
+ fun_l13_n880(x)
+ else
+ fun_l13_n785(x)
+ end
+end
+
+def fun_l12_n812(x)
+ if (x < 1)
+ fun_l13_n585(x)
+ else
+ fun_l13_n610(x)
+ end
+end
+
+def fun_l12_n813(x)
+ if (x < 1)
+ fun_l13_n41(x)
+ else
+ fun_l13_n911(x)
+ end
+end
+
+def fun_l12_n814(x)
+ if (x < 1)
+ fun_l13_n438(x)
+ else
+ fun_l13_n300(x)
+ end
+end
+
+def fun_l12_n815(x)
+ if (x < 1)
+ fun_l13_n363(x)
+ else
+ fun_l13_n357(x)
+ end
+end
+
+def fun_l12_n816(x)
+ if (x < 1)
+ fun_l13_n172(x)
+ else
+ fun_l13_n25(x)
+ end
+end
+
+def fun_l12_n817(x)
+ if (x < 1)
+ fun_l13_n593(x)
+ else
+ fun_l13_n853(x)
+ end
+end
+
+def fun_l12_n818(x)
+ if (x < 1)
+ fun_l13_n790(x)
+ else
+ fun_l13_n575(x)
+ end
+end
+
+def fun_l12_n819(x)
+ if (x < 1)
+ fun_l13_n795(x)
+ else
+ fun_l13_n877(x)
+ end
+end
+
+def fun_l12_n820(x)
+ if (x < 1)
+ fun_l13_n563(x)
+ else
+ fun_l13_n170(x)
+ end
+end
+
+def fun_l12_n821(x)
+ if (x < 1)
+ fun_l13_n405(x)
+ else
+ fun_l13_n985(x)
+ end
+end
+
+def fun_l12_n822(x)
+ if (x < 1)
+ fun_l13_n668(x)
+ else
+ fun_l13_n702(x)
+ end
+end
+
+def fun_l12_n823(x)
+ if (x < 1)
+ fun_l13_n210(x)
+ else
+ fun_l13_n450(x)
+ end
+end
+
+def fun_l12_n824(x)
+ if (x < 1)
+ fun_l13_n817(x)
+ else
+ fun_l13_n693(x)
+ end
+end
+
+def fun_l12_n825(x)
+ if (x < 1)
+ fun_l13_n909(x)
+ else
+ fun_l13_n857(x)
+ end
+end
+
+def fun_l12_n826(x)
+ if (x < 1)
+ fun_l13_n944(x)
+ else
+ fun_l13_n601(x)
+ end
+end
+
+def fun_l12_n827(x)
+ if (x < 1)
+ fun_l13_n152(x)
+ else
+ fun_l13_n187(x)
+ end
+end
+
+def fun_l12_n828(x)
+ if (x < 1)
+ fun_l13_n735(x)
+ else
+ fun_l13_n198(x)
+ end
+end
+
+def fun_l12_n829(x)
+ if (x < 1)
+ fun_l13_n892(x)
+ else
+ fun_l13_n362(x)
+ end
+end
+
+def fun_l12_n830(x)
+ if (x < 1)
+ fun_l13_n636(x)
+ else
+ fun_l13_n779(x)
+ end
+end
+
+def fun_l12_n831(x)
+ if (x < 1)
+ fun_l13_n597(x)
+ else
+ fun_l13_n186(x)
+ end
+end
+
+def fun_l12_n832(x)
+ if (x < 1)
+ fun_l13_n680(x)
+ else
+ fun_l13_n477(x)
+ end
+end
+
+def fun_l12_n833(x)
+ if (x < 1)
+ fun_l13_n334(x)
+ else
+ fun_l13_n508(x)
+ end
+end
+
+def fun_l12_n834(x)
+ if (x < 1)
+ fun_l13_n927(x)
+ else
+ fun_l13_n111(x)
+ end
+end
+
+def fun_l12_n835(x)
+ if (x < 1)
+ fun_l13_n424(x)
+ else
+ fun_l13_n326(x)
+ end
+end
+
+def fun_l12_n836(x)
+ if (x < 1)
+ fun_l13_n624(x)
+ else
+ fun_l13_n270(x)
+ end
+end
+
+def fun_l12_n837(x)
+ if (x < 1)
+ fun_l13_n458(x)
+ else
+ fun_l13_n736(x)
+ end
+end
+
+def fun_l12_n838(x)
+ if (x < 1)
+ fun_l13_n881(x)
+ else
+ fun_l13_n702(x)
+ end
+end
+
+def fun_l12_n839(x)
+ if (x < 1)
+ fun_l13_n778(x)
+ else
+ fun_l13_n374(x)
+ end
+end
+
+def fun_l12_n840(x)
+ if (x < 1)
+ fun_l13_n118(x)
+ else
+ fun_l13_n543(x)
+ end
+end
+
+def fun_l12_n841(x)
+ if (x < 1)
+ fun_l13_n270(x)
+ else
+ fun_l13_n810(x)
+ end
+end
+
+def fun_l12_n842(x)
+ if (x < 1)
+ fun_l13_n122(x)
+ else
+ fun_l13_n905(x)
+ end
+end
+
+def fun_l12_n843(x)
+ if (x < 1)
+ fun_l13_n154(x)
+ else
+ fun_l13_n636(x)
+ end
+end
+
+def fun_l12_n844(x)
+ if (x < 1)
+ fun_l13_n603(x)
+ else
+ fun_l13_n586(x)
+ end
+end
+
+def fun_l12_n845(x)
+ if (x < 1)
+ fun_l13_n264(x)
+ else
+ fun_l13_n492(x)
+ end
+end
+
+def fun_l12_n846(x)
+ if (x < 1)
+ fun_l13_n264(x)
+ else
+ fun_l13_n214(x)
+ end
+end
+
+def fun_l12_n847(x)
+ if (x < 1)
+ fun_l13_n337(x)
+ else
+ fun_l13_n339(x)
+ end
+end
+
+def fun_l12_n848(x)
+ if (x < 1)
+ fun_l13_n83(x)
+ else
+ fun_l13_n454(x)
+ end
+end
+
+def fun_l12_n849(x)
+ if (x < 1)
+ fun_l13_n129(x)
+ else
+ fun_l13_n30(x)
+ end
+end
+
+def fun_l12_n850(x)
+ if (x < 1)
+ fun_l13_n602(x)
+ else
+ fun_l13_n355(x)
+ end
+end
+
+def fun_l12_n851(x)
+ if (x < 1)
+ fun_l13_n650(x)
+ else
+ fun_l13_n715(x)
+ end
+end
+
+def fun_l12_n852(x)
+ if (x < 1)
+ fun_l13_n482(x)
+ else
+ fun_l13_n852(x)
+ end
+end
+
+def fun_l12_n853(x)
+ if (x < 1)
+ fun_l13_n946(x)
+ else
+ fun_l13_n393(x)
+ end
+end
+
+def fun_l12_n854(x)
+ if (x < 1)
+ fun_l13_n16(x)
+ else
+ fun_l13_n512(x)
+ end
+end
+
+def fun_l12_n855(x)
+ if (x < 1)
+ fun_l13_n469(x)
+ else
+ fun_l13_n567(x)
+ end
+end
+
+def fun_l12_n856(x)
+ if (x < 1)
+ fun_l13_n531(x)
+ else
+ fun_l13_n39(x)
+ end
+end
+
+def fun_l12_n857(x)
+ if (x < 1)
+ fun_l13_n673(x)
+ else
+ fun_l13_n670(x)
+ end
+end
+
+def fun_l12_n858(x)
+ if (x < 1)
+ fun_l13_n83(x)
+ else
+ fun_l13_n588(x)
+ end
+end
+
+def fun_l12_n859(x)
+ if (x < 1)
+ fun_l13_n247(x)
+ else
+ fun_l13_n460(x)
+ end
+end
+
+def fun_l12_n860(x)
+ if (x < 1)
+ fun_l13_n621(x)
+ else
+ fun_l13_n229(x)
+ end
+end
+
+def fun_l12_n861(x)
+ if (x < 1)
+ fun_l13_n121(x)
+ else
+ fun_l13_n147(x)
+ end
+end
+
+def fun_l12_n862(x)
+ if (x < 1)
+ fun_l13_n293(x)
+ else
+ fun_l13_n976(x)
+ end
+end
+
+def fun_l12_n863(x)
+ if (x < 1)
+ fun_l13_n64(x)
+ else
+ fun_l13_n569(x)
+ end
+end
+
+def fun_l12_n864(x)
+ if (x < 1)
+ fun_l13_n802(x)
+ else
+ fun_l13_n962(x)
+ end
+end
+
+def fun_l12_n865(x)
+ if (x < 1)
+ fun_l13_n406(x)
+ else
+ fun_l13_n571(x)
+ end
+end
+
+def fun_l12_n866(x)
+ if (x < 1)
+ fun_l13_n798(x)
+ else
+ fun_l13_n418(x)
+ end
+end
+
+def fun_l12_n867(x)
+ if (x < 1)
+ fun_l13_n725(x)
+ else
+ fun_l13_n716(x)
+ end
+end
+
+def fun_l12_n868(x)
+ if (x < 1)
+ fun_l13_n245(x)
+ else
+ fun_l13_n154(x)
+ end
+end
+
+def fun_l12_n869(x)
+ if (x < 1)
+ fun_l13_n954(x)
+ else
+ fun_l13_n242(x)
+ end
+end
+
+def fun_l12_n870(x)
+ if (x < 1)
+ fun_l13_n649(x)
+ else
+ fun_l13_n160(x)
+ end
+end
+
+def fun_l12_n871(x)
+ if (x < 1)
+ fun_l13_n700(x)
+ else
+ fun_l13_n863(x)
+ end
+end
+
+def fun_l12_n872(x)
+ if (x < 1)
+ fun_l13_n60(x)
+ else
+ fun_l13_n359(x)
+ end
+end
+
+def fun_l12_n873(x)
+ if (x < 1)
+ fun_l13_n820(x)
+ else
+ fun_l13_n247(x)
+ end
+end
+
+def fun_l12_n874(x)
+ if (x < 1)
+ fun_l13_n294(x)
+ else
+ fun_l13_n179(x)
+ end
+end
+
+def fun_l12_n875(x)
+ if (x < 1)
+ fun_l13_n599(x)
+ else
+ fun_l13_n309(x)
+ end
+end
+
+def fun_l12_n876(x)
+ if (x < 1)
+ fun_l13_n922(x)
+ else
+ fun_l13_n632(x)
+ end
+end
+
+def fun_l12_n877(x)
+ if (x < 1)
+ fun_l13_n921(x)
+ else
+ fun_l13_n200(x)
+ end
+end
+
+def fun_l12_n878(x)
+ if (x < 1)
+ fun_l13_n375(x)
+ else
+ fun_l13_n109(x)
+ end
+end
+
+def fun_l12_n879(x)
+ if (x < 1)
+ fun_l13_n771(x)
+ else
+ fun_l13_n758(x)
+ end
+end
+
+def fun_l12_n880(x)
+ if (x < 1)
+ fun_l13_n887(x)
+ else
+ fun_l13_n958(x)
+ end
+end
+
+def fun_l12_n881(x)
+ if (x < 1)
+ fun_l13_n668(x)
+ else
+ fun_l13_n508(x)
+ end
+end
+
+def fun_l12_n882(x)
+ if (x < 1)
+ fun_l13_n822(x)
+ else
+ fun_l13_n933(x)
+ end
+end
+
+def fun_l12_n883(x)
+ if (x < 1)
+ fun_l13_n328(x)
+ else
+ fun_l13_n152(x)
+ end
+end
+
+def fun_l12_n884(x)
+ if (x < 1)
+ fun_l13_n978(x)
+ else
+ fun_l13_n282(x)
+ end
+end
+
+def fun_l12_n885(x)
+ if (x < 1)
+ fun_l13_n91(x)
+ else
+ fun_l13_n592(x)
+ end
+end
+
+def fun_l12_n886(x)
+ if (x < 1)
+ fun_l13_n844(x)
+ else
+ fun_l13_n254(x)
+ end
+end
+
+def fun_l12_n887(x)
+ if (x < 1)
+ fun_l13_n49(x)
+ else
+ fun_l13_n430(x)
+ end
+end
+
+def fun_l12_n888(x)
+ if (x < 1)
+ fun_l13_n653(x)
+ else
+ fun_l13_n612(x)
+ end
+end
+
+def fun_l12_n889(x)
+ if (x < 1)
+ fun_l13_n352(x)
+ else
+ fun_l13_n228(x)
+ end
+end
+
+def fun_l12_n890(x)
+ if (x < 1)
+ fun_l13_n952(x)
+ else
+ fun_l13_n505(x)
+ end
+end
+
+def fun_l12_n891(x)
+ if (x < 1)
+ fun_l13_n381(x)
+ else
+ fun_l13_n799(x)
+ end
+end
+
+def fun_l12_n892(x)
+ if (x < 1)
+ fun_l13_n160(x)
+ else
+ fun_l13_n78(x)
+ end
+end
+
+def fun_l12_n893(x)
+ if (x < 1)
+ fun_l13_n554(x)
+ else
+ fun_l13_n383(x)
+ end
+end
+
+def fun_l12_n894(x)
+ if (x < 1)
+ fun_l13_n475(x)
+ else
+ fun_l13_n853(x)
+ end
+end
+
+def fun_l12_n895(x)
+ if (x < 1)
+ fun_l13_n588(x)
+ else
+ fun_l13_n452(x)
+ end
+end
+
+def fun_l12_n896(x)
+ if (x < 1)
+ fun_l13_n991(x)
+ else
+ fun_l13_n758(x)
+ end
+end
+
+def fun_l12_n897(x)
+ if (x < 1)
+ fun_l13_n808(x)
+ else
+ fun_l13_n742(x)
+ end
+end
+
+def fun_l12_n898(x)
+ if (x < 1)
+ fun_l13_n654(x)
+ else
+ fun_l13_n772(x)
+ end
+end
+
+def fun_l12_n899(x)
+ if (x < 1)
+ fun_l13_n365(x)
+ else
+ fun_l13_n3(x)
+ end
+end
+
+def fun_l12_n900(x)
+ if (x < 1)
+ fun_l13_n322(x)
+ else
+ fun_l13_n143(x)
+ end
+end
+
+def fun_l12_n901(x)
+ if (x < 1)
+ fun_l13_n833(x)
+ else
+ fun_l13_n19(x)
+ end
+end
+
+def fun_l12_n902(x)
+ if (x < 1)
+ fun_l13_n796(x)
+ else
+ fun_l13_n140(x)
+ end
+end
+
+def fun_l12_n903(x)
+ if (x < 1)
+ fun_l13_n866(x)
+ else
+ fun_l13_n227(x)
+ end
+end
+
+def fun_l12_n904(x)
+ if (x < 1)
+ fun_l13_n814(x)
+ else
+ fun_l13_n714(x)
+ end
+end
+
+def fun_l12_n905(x)
+ if (x < 1)
+ fun_l13_n841(x)
+ else
+ fun_l13_n802(x)
+ end
+end
+
+def fun_l12_n906(x)
+ if (x < 1)
+ fun_l13_n212(x)
+ else
+ fun_l13_n14(x)
+ end
+end
+
+def fun_l12_n907(x)
+ if (x < 1)
+ fun_l13_n35(x)
+ else
+ fun_l13_n952(x)
+ end
+end
+
+def fun_l12_n908(x)
+ if (x < 1)
+ fun_l13_n181(x)
+ else
+ fun_l13_n539(x)
+ end
+end
+
+def fun_l12_n909(x)
+ if (x < 1)
+ fun_l13_n770(x)
+ else
+ fun_l13_n80(x)
+ end
+end
+
+def fun_l12_n910(x)
+ if (x < 1)
+ fun_l13_n421(x)
+ else
+ fun_l13_n512(x)
+ end
+end
+
+def fun_l12_n911(x)
+ if (x < 1)
+ fun_l13_n710(x)
+ else
+ fun_l13_n666(x)
+ end
+end
+
+def fun_l12_n912(x)
+ if (x < 1)
+ fun_l13_n319(x)
+ else
+ fun_l13_n491(x)
+ end
+end
+
+def fun_l12_n913(x)
+ if (x < 1)
+ fun_l13_n924(x)
+ else
+ fun_l13_n198(x)
+ end
+end
+
+def fun_l12_n914(x)
+ if (x < 1)
+ fun_l13_n707(x)
+ else
+ fun_l13_n91(x)
+ end
+end
+
+def fun_l12_n915(x)
+ if (x < 1)
+ fun_l13_n29(x)
+ else
+ fun_l13_n134(x)
+ end
+end
+
+def fun_l12_n916(x)
+ if (x < 1)
+ fun_l13_n314(x)
+ else
+ fun_l13_n831(x)
+ end
+end
+
+def fun_l12_n917(x)
+ if (x < 1)
+ fun_l13_n986(x)
+ else
+ fun_l13_n732(x)
+ end
+end
+
+def fun_l12_n918(x)
+ if (x < 1)
+ fun_l13_n787(x)
+ else
+ fun_l13_n232(x)
+ end
+end
+
+def fun_l12_n919(x)
+ if (x < 1)
+ fun_l13_n452(x)
+ else
+ fun_l13_n386(x)
+ end
+end
+
+def fun_l12_n920(x)
+ if (x < 1)
+ fun_l13_n12(x)
+ else
+ fun_l13_n264(x)
+ end
+end
+
+def fun_l12_n921(x)
+ if (x < 1)
+ fun_l13_n734(x)
+ else
+ fun_l13_n885(x)
+ end
+end
+
+def fun_l12_n922(x)
+ if (x < 1)
+ fun_l13_n180(x)
+ else
+ fun_l13_n509(x)
+ end
+end
+
+def fun_l12_n923(x)
+ if (x < 1)
+ fun_l13_n783(x)
+ else
+ fun_l13_n212(x)
+ end
+end
+
+def fun_l12_n924(x)
+ if (x < 1)
+ fun_l13_n623(x)
+ else
+ fun_l13_n159(x)
+ end
+end
+
+def fun_l12_n925(x)
+ if (x < 1)
+ fun_l13_n361(x)
+ else
+ fun_l13_n47(x)
+ end
+end
+
+def fun_l12_n926(x)
+ if (x < 1)
+ fun_l13_n355(x)
+ else
+ fun_l13_n337(x)
+ end
+end
+
+def fun_l12_n927(x)
+ if (x < 1)
+ fun_l13_n892(x)
+ else
+ fun_l13_n814(x)
+ end
+end
+
+def fun_l12_n928(x)
+ if (x < 1)
+ fun_l13_n173(x)
+ else
+ fun_l13_n613(x)
+ end
+end
+
+def fun_l12_n929(x)
+ if (x < 1)
+ fun_l13_n140(x)
+ else
+ fun_l13_n782(x)
+ end
+end
+
+def fun_l12_n930(x)
+ if (x < 1)
+ fun_l13_n964(x)
+ else
+ fun_l13_n830(x)
+ end
+end
+
+def fun_l12_n931(x)
+ if (x < 1)
+ fun_l13_n110(x)
+ else
+ fun_l13_n767(x)
+ end
+end
+
+def fun_l12_n932(x)
+ if (x < 1)
+ fun_l13_n738(x)
+ else
+ fun_l13_n73(x)
+ end
+end
+
+def fun_l12_n933(x)
+ if (x < 1)
+ fun_l13_n92(x)
+ else
+ fun_l13_n113(x)
+ end
+end
+
+def fun_l12_n934(x)
+ if (x < 1)
+ fun_l13_n377(x)
+ else
+ fun_l13_n464(x)
+ end
+end
+
+def fun_l12_n935(x)
+ if (x < 1)
+ fun_l13_n544(x)
+ else
+ fun_l13_n808(x)
+ end
+end
+
+def fun_l12_n936(x)
+ if (x < 1)
+ fun_l13_n36(x)
+ else
+ fun_l13_n343(x)
+ end
+end
+
+def fun_l12_n937(x)
+ if (x < 1)
+ fun_l13_n745(x)
+ else
+ fun_l13_n342(x)
+ end
+end
+
+def fun_l12_n938(x)
+ if (x < 1)
+ fun_l13_n238(x)
+ else
+ fun_l13_n703(x)
+ end
+end
+
+def fun_l12_n939(x)
+ if (x < 1)
+ fun_l13_n229(x)
+ else
+ fun_l13_n118(x)
+ end
+end
+
+def fun_l12_n940(x)
+ if (x < 1)
+ fun_l13_n90(x)
+ else
+ fun_l13_n0(x)
+ end
+end
+
+def fun_l12_n941(x)
+ if (x < 1)
+ fun_l13_n586(x)
+ else
+ fun_l13_n99(x)
+ end
+end
+
+def fun_l12_n942(x)
+ if (x < 1)
+ fun_l13_n755(x)
+ else
+ fun_l13_n573(x)
+ end
+end
+
+def fun_l12_n943(x)
+ if (x < 1)
+ fun_l13_n74(x)
+ else
+ fun_l13_n805(x)
+ end
+end
+
+def fun_l12_n944(x)
+ if (x < 1)
+ fun_l13_n574(x)
+ else
+ fun_l13_n876(x)
+ end
+end
+
+def fun_l12_n945(x)
+ if (x < 1)
+ fun_l13_n0(x)
+ else
+ fun_l13_n478(x)
+ end
+end
+
+def fun_l12_n946(x)
+ if (x < 1)
+ fun_l13_n536(x)
+ else
+ fun_l13_n957(x)
+ end
+end
+
+def fun_l12_n947(x)
+ if (x < 1)
+ fun_l13_n644(x)
+ else
+ fun_l13_n285(x)
+ end
+end
+
+def fun_l12_n948(x)
+ if (x < 1)
+ fun_l13_n215(x)
+ else
+ fun_l13_n914(x)
+ end
+end
+
+def fun_l12_n949(x)
+ if (x < 1)
+ fun_l13_n265(x)
+ else
+ fun_l13_n262(x)
+ end
+end
+
+def fun_l12_n950(x)
+ if (x < 1)
+ fun_l13_n44(x)
+ else
+ fun_l13_n917(x)
+ end
+end
+
+def fun_l12_n951(x)
+ if (x < 1)
+ fun_l13_n222(x)
+ else
+ fun_l13_n53(x)
+ end
+end
+
+def fun_l12_n952(x)
+ if (x < 1)
+ fun_l13_n149(x)
+ else
+ fun_l13_n11(x)
+ end
+end
+
+def fun_l12_n953(x)
+ if (x < 1)
+ fun_l13_n827(x)
+ else
+ fun_l13_n737(x)
+ end
+end
+
+def fun_l12_n954(x)
+ if (x < 1)
+ fun_l13_n655(x)
+ else
+ fun_l13_n308(x)
+ end
+end
+
+def fun_l12_n955(x)
+ if (x < 1)
+ fun_l13_n108(x)
+ else
+ fun_l13_n940(x)
+ end
+end
+
+def fun_l12_n956(x)
+ if (x < 1)
+ fun_l13_n236(x)
+ else
+ fun_l13_n259(x)
+ end
+end
+
+def fun_l12_n957(x)
+ if (x < 1)
+ fun_l13_n886(x)
+ else
+ fun_l13_n955(x)
+ end
+end
+
+def fun_l12_n958(x)
+ if (x < 1)
+ fun_l13_n688(x)
+ else
+ fun_l13_n391(x)
+ end
+end
+
+def fun_l12_n959(x)
+ if (x < 1)
+ fun_l13_n521(x)
+ else
+ fun_l13_n395(x)
+ end
+end
+
+def fun_l12_n960(x)
+ if (x < 1)
+ fun_l13_n877(x)
+ else
+ fun_l13_n808(x)
+ end
+end
+
+def fun_l12_n961(x)
+ if (x < 1)
+ fun_l13_n29(x)
+ else
+ fun_l13_n422(x)
+ end
+end
+
+def fun_l12_n962(x)
+ if (x < 1)
+ fun_l13_n417(x)
+ else
+ fun_l13_n310(x)
+ end
+end
+
+def fun_l12_n963(x)
+ if (x < 1)
+ fun_l13_n987(x)
+ else
+ fun_l13_n462(x)
+ end
+end
+
+def fun_l12_n964(x)
+ if (x < 1)
+ fun_l13_n914(x)
+ else
+ fun_l13_n115(x)
+ end
+end
+
+def fun_l12_n965(x)
+ if (x < 1)
+ fun_l13_n895(x)
+ else
+ fun_l13_n504(x)
+ end
+end
+
+def fun_l12_n966(x)
+ if (x < 1)
+ fun_l13_n304(x)
+ else
+ fun_l13_n788(x)
+ end
+end
+
+def fun_l12_n967(x)
+ if (x < 1)
+ fun_l13_n354(x)
+ else
+ fun_l13_n592(x)
+ end
+end
+
+def fun_l12_n968(x)
+ if (x < 1)
+ fun_l13_n231(x)
+ else
+ fun_l13_n214(x)
+ end
+end
+
+def fun_l12_n969(x)
+ if (x < 1)
+ fun_l13_n435(x)
+ else
+ fun_l13_n779(x)
+ end
+end
+
+def fun_l12_n970(x)
+ if (x < 1)
+ fun_l13_n261(x)
+ else
+ fun_l13_n139(x)
+ end
+end
+
+def fun_l12_n971(x)
+ if (x < 1)
+ fun_l13_n320(x)
+ else
+ fun_l13_n749(x)
+ end
+end
+
+def fun_l12_n972(x)
+ if (x < 1)
+ fun_l13_n56(x)
+ else
+ fun_l13_n207(x)
+ end
+end
+
+def fun_l12_n973(x)
+ if (x < 1)
+ fun_l13_n238(x)
+ else
+ fun_l13_n637(x)
+ end
+end
+
+def fun_l12_n974(x)
+ if (x < 1)
+ fun_l13_n474(x)
+ else
+ fun_l13_n512(x)
+ end
+end
+
+def fun_l12_n975(x)
+ if (x < 1)
+ fun_l13_n552(x)
+ else
+ fun_l13_n355(x)
+ end
+end
+
+def fun_l12_n976(x)
+ if (x < 1)
+ fun_l13_n127(x)
+ else
+ fun_l13_n571(x)
+ end
+end
+
+def fun_l12_n977(x)
+ if (x < 1)
+ fun_l13_n261(x)
+ else
+ fun_l13_n845(x)
+ end
+end
+
+def fun_l12_n978(x)
+ if (x < 1)
+ fun_l13_n280(x)
+ else
+ fun_l13_n465(x)
+ end
+end
+
+def fun_l12_n979(x)
+ if (x < 1)
+ fun_l13_n249(x)
+ else
+ fun_l13_n66(x)
+ end
+end
+
+def fun_l12_n980(x)
+ if (x < 1)
+ fun_l13_n306(x)
+ else
+ fun_l13_n53(x)
+ end
+end
+
+def fun_l12_n981(x)
+ if (x < 1)
+ fun_l13_n827(x)
+ else
+ fun_l13_n395(x)
+ end
+end
+
+def fun_l12_n982(x)
+ if (x < 1)
+ fun_l13_n858(x)
+ else
+ fun_l13_n644(x)
+ end
+end
+
+def fun_l12_n983(x)
+ if (x < 1)
+ fun_l13_n50(x)
+ else
+ fun_l13_n671(x)
+ end
+end
+
+def fun_l12_n984(x)
+ if (x < 1)
+ fun_l13_n629(x)
+ else
+ fun_l13_n55(x)
+ end
+end
+
+def fun_l12_n985(x)
+ if (x < 1)
+ fun_l13_n73(x)
+ else
+ fun_l13_n958(x)
+ end
+end
+
+def fun_l12_n986(x)
+ if (x < 1)
+ fun_l13_n197(x)
+ else
+ fun_l13_n444(x)
+ end
+end
+
+def fun_l12_n987(x)
+ if (x < 1)
+ fun_l13_n108(x)
+ else
+ fun_l13_n898(x)
+ end
+end
+
+def fun_l12_n988(x)
+ if (x < 1)
+ fun_l13_n153(x)
+ else
+ fun_l13_n278(x)
+ end
+end
+
+def fun_l12_n989(x)
+ if (x < 1)
+ fun_l13_n764(x)
+ else
+ fun_l13_n712(x)
+ end
+end
+
+def fun_l12_n990(x)
+ if (x < 1)
+ fun_l13_n711(x)
+ else
+ fun_l13_n825(x)
+ end
+end
+
+def fun_l12_n991(x)
+ if (x < 1)
+ fun_l13_n767(x)
+ else
+ fun_l13_n169(x)
+ end
+end
+
+def fun_l12_n992(x)
+ if (x < 1)
+ fun_l13_n917(x)
+ else
+ fun_l13_n524(x)
+ end
+end
+
+def fun_l12_n993(x)
+ if (x < 1)
+ fun_l13_n589(x)
+ else
+ fun_l13_n695(x)
+ end
+end
+
+def fun_l12_n994(x)
+ if (x < 1)
+ fun_l13_n733(x)
+ else
+ fun_l13_n764(x)
+ end
+end
+
+def fun_l12_n995(x)
+ if (x < 1)
+ fun_l13_n86(x)
+ else
+ fun_l13_n547(x)
+ end
+end
+
+def fun_l12_n996(x)
+ if (x < 1)
+ fun_l13_n236(x)
+ else
+ fun_l13_n197(x)
+ end
+end
+
+def fun_l12_n997(x)
+ if (x < 1)
+ fun_l13_n592(x)
+ else
+ fun_l13_n313(x)
+ end
+end
+
+def fun_l12_n998(x)
+ if (x < 1)
+ fun_l13_n878(x)
+ else
+ fun_l13_n439(x)
+ end
+end
+
+def fun_l12_n999(x)
+ if (x < 1)
+ fun_l13_n904(x)
+ else
+ fun_l13_n651(x)
+ end
+end
+
+def fun_l13_n0(x)
+ if (x < 1)
+ fun_l14_n72(x)
+ else
+ fun_l14_n951(x)
+ end
+end
+
+def fun_l13_n1(x)
+ if (x < 1)
+ fun_l14_n950(x)
+ else
+ fun_l14_n170(x)
+ end
+end
+
+def fun_l13_n2(x)
+ if (x < 1)
+ fun_l14_n773(x)
+ else
+ fun_l14_n351(x)
+ end
+end
+
+def fun_l13_n3(x)
+ if (x < 1)
+ fun_l14_n814(x)
+ else
+ fun_l14_n304(x)
+ end
+end
+
+def fun_l13_n4(x)
+ if (x < 1)
+ fun_l14_n395(x)
+ else
+ fun_l14_n187(x)
+ end
+end
+
+def fun_l13_n5(x)
+ if (x < 1)
+ fun_l14_n60(x)
+ else
+ fun_l14_n165(x)
+ end
+end
+
+def fun_l13_n6(x)
+ if (x < 1)
+ fun_l14_n711(x)
+ else
+ fun_l14_n815(x)
+ end
+end
+
+def fun_l13_n7(x)
+ if (x < 1)
+ fun_l14_n396(x)
+ else
+ fun_l14_n614(x)
+ end
+end
+
+def fun_l13_n8(x)
+ if (x < 1)
+ fun_l14_n477(x)
+ else
+ fun_l14_n427(x)
+ end
+end
+
+def fun_l13_n9(x)
+ if (x < 1)
+ fun_l14_n803(x)
+ else
+ fun_l14_n655(x)
+ end
+end
+
+def fun_l13_n10(x)
+ if (x < 1)
+ fun_l14_n261(x)
+ else
+ fun_l14_n324(x)
+ end
+end
+
+def fun_l13_n11(x)
+ if (x < 1)
+ fun_l14_n485(x)
+ else
+ fun_l14_n302(x)
+ end
+end
+
+def fun_l13_n12(x)
+ if (x < 1)
+ fun_l14_n324(x)
+ else
+ fun_l14_n840(x)
+ end
+end
+
+def fun_l13_n13(x)
+ if (x < 1)
+ fun_l14_n811(x)
+ else
+ fun_l14_n357(x)
+ end
+end
+
+def fun_l13_n14(x)
+ if (x < 1)
+ fun_l14_n736(x)
+ else
+ fun_l14_n763(x)
+ end
+end
+
+def fun_l13_n15(x)
+ if (x < 1)
+ fun_l14_n572(x)
+ else
+ fun_l14_n557(x)
+ end
+end
+
+def fun_l13_n16(x)
+ if (x < 1)
+ fun_l14_n406(x)
+ else
+ fun_l14_n200(x)
+ end
+end
+
+def fun_l13_n17(x)
+ if (x < 1)
+ fun_l14_n500(x)
+ else
+ fun_l14_n480(x)
+ end
+end
+
+def fun_l13_n18(x)
+ if (x < 1)
+ fun_l14_n215(x)
+ else
+ fun_l14_n241(x)
+ end
+end
+
+def fun_l13_n19(x)
+ if (x < 1)
+ fun_l14_n341(x)
+ else
+ fun_l14_n142(x)
+ end
+end
+
+def fun_l13_n20(x)
+ if (x < 1)
+ fun_l14_n649(x)
+ else
+ fun_l14_n853(x)
+ end
+end
+
+def fun_l13_n21(x)
+ if (x < 1)
+ fun_l14_n153(x)
+ else
+ fun_l14_n295(x)
+ end
+end
+
+def fun_l13_n22(x)
+ if (x < 1)
+ fun_l14_n210(x)
+ else
+ fun_l14_n947(x)
+ end
+end
+
+def fun_l13_n23(x)
+ if (x < 1)
+ fun_l14_n764(x)
+ else
+ fun_l14_n810(x)
+ end
+end
+
+def fun_l13_n24(x)
+ if (x < 1)
+ fun_l14_n96(x)
+ else
+ fun_l14_n359(x)
+ end
+end
+
+def fun_l13_n25(x)
+ if (x < 1)
+ fun_l14_n542(x)
+ else
+ fun_l14_n506(x)
+ end
+end
+
+def fun_l13_n26(x)
+ if (x < 1)
+ fun_l14_n583(x)
+ else
+ fun_l14_n754(x)
+ end
+end
+
+def fun_l13_n27(x)
+ if (x < 1)
+ fun_l14_n881(x)
+ else
+ fun_l14_n693(x)
+ end
+end
+
+def fun_l13_n28(x)
+ if (x < 1)
+ fun_l14_n385(x)
+ else
+ fun_l14_n628(x)
+ end
+end
+
+def fun_l13_n29(x)
+ if (x < 1)
+ fun_l14_n429(x)
+ else
+ fun_l14_n370(x)
+ end
+end
+
+def fun_l13_n30(x)
+ if (x < 1)
+ fun_l14_n484(x)
+ else
+ fun_l14_n724(x)
+ end
+end
+
+def fun_l13_n31(x)
+ if (x < 1)
+ fun_l14_n328(x)
+ else
+ fun_l14_n857(x)
+ end
+end
+
+def fun_l13_n32(x)
+ if (x < 1)
+ fun_l14_n367(x)
+ else
+ fun_l14_n441(x)
+ end
+end
+
+def fun_l13_n33(x)
+ if (x < 1)
+ fun_l14_n322(x)
+ else
+ fun_l14_n390(x)
+ end
+end
+
+def fun_l13_n34(x)
+ if (x < 1)
+ fun_l14_n935(x)
+ else
+ fun_l14_n46(x)
+ end
+end
+
+def fun_l13_n35(x)
+ if (x < 1)
+ fun_l14_n274(x)
+ else
+ fun_l14_n536(x)
+ end
+end
+
+def fun_l13_n36(x)
+ if (x < 1)
+ fun_l14_n645(x)
+ else
+ fun_l14_n396(x)
+ end
+end
+
+def fun_l13_n37(x)
+ if (x < 1)
+ fun_l14_n905(x)
+ else
+ fun_l14_n19(x)
+ end
+end
+
+def fun_l13_n38(x)
+ if (x < 1)
+ fun_l14_n562(x)
+ else
+ fun_l14_n983(x)
+ end
+end
+
+def fun_l13_n39(x)
+ if (x < 1)
+ fun_l14_n846(x)
+ else
+ fun_l14_n140(x)
+ end
+end
+
+def fun_l13_n40(x)
+ if (x < 1)
+ fun_l14_n308(x)
+ else
+ fun_l14_n968(x)
+ end
+end
+
+def fun_l13_n41(x)
+ if (x < 1)
+ fun_l14_n299(x)
+ else
+ fun_l14_n364(x)
+ end
+end
+
+def fun_l13_n42(x)
+ if (x < 1)
+ fun_l14_n266(x)
+ else
+ fun_l14_n368(x)
+ end
+end
+
+def fun_l13_n43(x)
+ if (x < 1)
+ fun_l14_n216(x)
+ else
+ fun_l14_n894(x)
+ end
+end
+
+def fun_l13_n44(x)
+ if (x < 1)
+ fun_l14_n30(x)
+ else
+ fun_l14_n118(x)
+ end
+end
+
+def fun_l13_n45(x)
+ if (x < 1)
+ fun_l14_n66(x)
+ else
+ fun_l14_n677(x)
+ end
+end
+
+def fun_l13_n46(x)
+ if (x < 1)
+ fun_l14_n415(x)
+ else
+ fun_l14_n311(x)
+ end
+end
+
+def fun_l13_n47(x)
+ if (x < 1)
+ fun_l14_n63(x)
+ else
+ fun_l14_n410(x)
+ end
+end
+
+def fun_l13_n48(x)
+ if (x < 1)
+ fun_l14_n640(x)
+ else
+ fun_l14_n161(x)
+ end
+end
+
+def fun_l13_n49(x)
+ if (x < 1)
+ fun_l14_n546(x)
+ else
+ fun_l14_n655(x)
+ end
+end
+
+def fun_l13_n50(x)
+ if (x < 1)
+ fun_l14_n102(x)
+ else
+ fun_l14_n791(x)
+ end
+end
+
+def fun_l13_n51(x)
+ if (x < 1)
+ fun_l14_n333(x)
+ else
+ fun_l14_n641(x)
+ end
+end
+
+def fun_l13_n52(x)
+ if (x < 1)
+ fun_l14_n16(x)
+ else
+ fun_l14_n653(x)
+ end
+end
+
+def fun_l13_n53(x)
+ if (x < 1)
+ fun_l14_n842(x)
+ else
+ fun_l14_n780(x)
+ end
+end
+
+def fun_l13_n54(x)
+ if (x < 1)
+ fun_l14_n663(x)
+ else
+ fun_l14_n903(x)
+ end
+end
+
+def fun_l13_n55(x)
+ if (x < 1)
+ fun_l14_n745(x)
+ else
+ fun_l14_n925(x)
+ end
+end
+
+def fun_l13_n56(x)
+ if (x < 1)
+ fun_l14_n688(x)
+ else
+ fun_l14_n930(x)
+ end
+end
+
+def fun_l13_n57(x)
+ if (x < 1)
+ fun_l14_n58(x)
+ else
+ fun_l14_n864(x)
+ end
+end
+
+def fun_l13_n58(x)
+ if (x < 1)
+ fun_l14_n107(x)
+ else
+ fun_l14_n197(x)
+ end
+end
+
+def fun_l13_n59(x)
+ if (x < 1)
+ fun_l14_n334(x)
+ else
+ fun_l14_n147(x)
+ end
+end
+
+def fun_l13_n60(x)
+ if (x < 1)
+ fun_l14_n814(x)
+ else
+ fun_l14_n417(x)
+ end
+end
+
+def fun_l13_n61(x)
+ if (x < 1)
+ fun_l14_n696(x)
+ else
+ fun_l14_n973(x)
+ end
+end
+
+def fun_l13_n62(x)
+ if (x < 1)
+ fun_l14_n378(x)
+ else
+ fun_l14_n968(x)
+ end
+end
+
+def fun_l13_n63(x)
+ if (x < 1)
+ fun_l14_n107(x)
+ else
+ fun_l14_n100(x)
+ end
+end
+
+def fun_l13_n64(x)
+ if (x < 1)
+ fun_l14_n105(x)
+ else
+ fun_l14_n393(x)
+ end
+end
+
+def fun_l13_n65(x)
+ if (x < 1)
+ fun_l14_n833(x)
+ else
+ fun_l14_n424(x)
+ end
+end
+
+def fun_l13_n66(x)
+ if (x < 1)
+ fun_l14_n125(x)
+ else
+ fun_l14_n697(x)
+ end
+end
+
+def fun_l13_n67(x)
+ if (x < 1)
+ fun_l14_n684(x)
+ else
+ fun_l14_n458(x)
+ end
+end
+
+def fun_l13_n68(x)
+ if (x < 1)
+ fun_l14_n301(x)
+ else
+ fun_l14_n711(x)
+ end
+end
+
+def fun_l13_n69(x)
+ if (x < 1)
+ fun_l14_n131(x)
+ else
+ fun_l14_n552(x)
+ end
+end
+
+def fun_l13_n70(x)
+ if (x < 1)
+ fun_l14_n425(x)
+ else
+ fun_l14_n241(x)
+ end
+end
+
+def fun_l13_n71(x)
+ if (x < 1)
+ fun_l14_n531(x)
+ else
+ fun_l14_n364(x)
+ end
+end
+
+def fun_l13_n72(x)
+ if (x < 1)
+ fun_l14_n801(x)
+ else
+ fun_l14_n951(x)
+ end
+end
+
+def fun_l13_n73(x)
+ if (x < 1)
+ fun_l14_n415(x)
+ else
+ fun_l14_n294(x)
+ end
+end
+
+def fun_l13_n74(x)
+ if (x < 1)
+ fun_l14_n715(x)
+ else
+ fun_l14_n606(x)
+ end
+end
+
+def fun_l13_n75(x)
+ if (x < 1)
+ fun_l14_n932(x)
+ else
+ fun_l14_n928(x)
+ end
+end
+
+def fun_l13_n76(x)
+ if (x < 1)
+ fun_l14_n930(x)
+ else
+ fun_l14_n102(x)
+ end
+end
+
+def fun_l13_n77(x)
+ if (x < 1)
+ fun_l14_n293(x)
+ else
+ fun_l14_n301(x)
+ end
+end
+
+def fun_l13_n78(x)
+ if (x < 1)
+ fun_l14_n270(x)
+ else
+ fun_l14_n715(x)
+ end
+end
+
+def fun_l13_n79(x)
+ if (x < 1)
+ fun_l14_n862(x)
+ else
+ fun_l14_n589(x)
+ end
+end
+
+def fun_l13_n80(x)
+ if (x < 1)
+ fun_l14_n337(x)
+ else
+ fun_l14_n940(x)
+ end
+end
+
+def fun_l13_n81(x)
+ if (x < 1)
+ fun_l14_n394(x)
+ else
+ fun_l14_n902(x)
+ end
+end
+
+def fun_l13_n82(x)
+ if (x < 1)
+ fun_l14_n468(x)
+ else
+ fun_l14_n816(x)
+ end
+end
+
+def fun_l13_n83(x)
+ if (x < 1)
+ fun_l14_n517(x)
+ else
+ fun_l14_n633(x)
+ end
+end
+
+def fun_l13_n84(x)
+ if (x < 1)
+ fun_l14_n312(x)
+ else
+ fun_l14_n473(x)
+ end
+end
+
+def fun_l13_n85(x)
+ if (x < 1)
+ fun_l14_n377(x)
+ else
+ fun_l14_n616(x)
+ end
+end
+
+def fun_l13_n86(x)
+ if (x < 1)
+ fun_l14_n541(x)
+ else
+ fun_l14_n77(x)
+ end
+end
+
+def fun_l13_n87(x)
+ if (x < 1)
+ fun_l14_n66(x)
+ else
+ fun_l14_n162(x)
+ end
+end
+
+def fun_l13_n88(x)
+ if (x < 1)
+ fun_l14_n202(x)
+ else
+ fun_l14_n158(x)
+ end
+end
+
+def fun_l13_n89(x)
+ if (x < 1)
+ fun_l14_n549(x)
+ else
+ fun_l14_n947(x)
+ end
+end
+
+def fun_l13_n90(x)
+ if (x < 1)
+ fun_l14_n82(x)
+ else
+ fun_l14_n747(x)
+ end
+end
+
+def fun_l13_n91(x)
+ if (x < 1)
+ fun_l14_n374(x)
+ else
+ fun_l14_n738(x)
+ end
+end
+
+def fun_l13_n92(x)
+ if (x < 1)
+ fun_l14_n124(x)
+ else
+ fun_l14_n673(x)
+ end
+end
+
+def fun_l13_n93(x)
+ if (x < 1)
+ fun_l14_n405(x)
+ else
+ fun_l14_n562(x)
+ end
+end
+
+def fun_l13_n94(x)
+ if (x < 1)
+ fun_l14_n766(x)
+ else
+ fun_l14_n466(x)
+ end
+end
+
+def fun_l13_n95(x)
+ if (x < 1)
+ fun_l14_n908(x)
+ else
+ fun_l14_n208(x)
+ end
+end
+
+def fun_l13_n96(x)
+ if (x < 1)
+ fun_l14_n439(x)
+ else
+ fun_l14_n964(x)
+ end
+end
+
+def fun_l13_n97(x)
+ if (x < 1)
+ fun_l14_n529(x)
+ else
+ fun_l14_n374(x)
+ end
+end
+
+def fun_l13_n98(x)
+ if (x < 1)
+ fun_l14_n723(x)
+ else
+ fun_l14_n464(x)
+ end
+end
+
+def fun_l13_n99(x)
+ if (x < 1)
+ fun_l14_n849(x)
+ else
+ fun_l14_n951(x)
+ end
+end
+
+def fun_l13_n100(x)
+ if (x < 1)
+ fun_l14_n797(x)
+ else
+ fun_l14_n421(x)
+ end
+end
+
+def fun_l13_n101(x)
+ if (x < 1)
+ fun_l14_n989(x)
+ else
+ fun_l14_n392(x)
+ end
+end
+
+def fun_l13_n102(x)
+ if (x < 1)
+ fun_l14_n8(x)
+ else
+ fun_l14_n913(x)
+ end
+end
+
+def fun_l13_n103(x)
+ if (x < 1)
+ fun_l14_n498(x)
+ else
+ fun_l14_n248(x)
+ end
+end
+
+def fun_l13_n104(x)
+ if (x < 1)
+ fun_l14_n989(x)
+ else
+ fun_l14_n83(x)
+ end
+end
+
+def fun_l13_n105(x)
+ if (x < 1)
+ fun_l14_n943(x)
+ else
+ fun_l14_n358(x)
+ end
+end
+
+def fun_l13_n106(x)
+ if (x < 1)
+ fun_l14_n252(x)
+ else
+ fun_l14_n626(x)
+ end
+end
+
+def fun_l13_n107(x)
+ if (x < 1)
+ fun_l14_n495(x)
+ else
+ fun_l14_n627(x)
+ end
+end
+
+def fun_l13_n108(x)
+ if (x < 1)
+ fun_l14_n286(x)
+ else
+ fun_l14_n500(x)
+ end
+end
+
+def fun_l13_n109(x)
+ if (x < 1)
+ fun_l14_n927(x)
+ else
+ fun_l14_n627(x)
+ end
+end
+
+def fun_l13_n110(x)
+ if (x < 1)
+ fun_l14_n103(x)
+ else
+ fun_l14_n319(x)
+ end
+end
+
+def fun_l13_n111(x)
+ if (x < 1)
+ fun_l14_n730(x)
+ else
+ fun_l14_n960(x)
+ end
+end
+
+def fun_l13_n112(x)
+ if (x < 1)
+ fun_l14_n188(x)
+ else
+ fun_l14_n145(x)
+ end
+end
+
+def fun_l13_n113(x)
+ if (x < 1)
+ fun_l14_n361(x)
+ else
+ fun_l14_n707(x)
+ end
+end
+
+def fun_l13_n114(x)
+ if (x < 1)
+ fun_l14_n629(x)
+ else
+ fun_l14_n536(x)
+ end
+end
+
+def fun_l13_n115(x)
+ if (x < 1)
+ fun_l14_n276(x)
+ else
+ fun_l14_n244(x)
+ end
+end
+
+def fun_l13_n116(x)
+ if (x < 1)
+ fun_l14_n512(x)
+ else
+ fun_l14_n578(x)
+ end
+end
+
+def fun_l13_n117(x)
+ if (x < 1)
+ fun_l14_n448(x)
+ else
+ fun_l14_n437(x)
+ end
+end
+
+def fun_l13_n118(x)
+ if (x < 1)
+ fun_l14_n855(x)
+ else
+ fun_l14_n617(x)
+ end
+end
+
+def fun_l13_n119(x)
+ if (x < 1)
+ fun_l14_n467(x)
+ else
+ fun_l14_n594(x)
+ end
+end
+
+def fun_l13_n120(x)
+ if (x < 1)
+ fun_l14_n54(x)
+ else
+ fun_l14_n765(x)
+ end
+end
+
+def fun_l13_n121(x)
+ if (x < 1)
+ fun_l14_n700(x)
+ else
+ fun_l14_n189(x)
+ end
+end
+
+def fun_l13_n122(x)
+ if (x < 1)
+ fun_l14_n731(x)
+ else
+ fun_l14_n469(x)
+ end
+end
+
+def fun_l13_n123(x)
+ if (x < 1)
+ fun_l14_n6(x)
+ else
+ fun_l14_n451(x)
+ end
+end
+
+def fun_l13_n124(x)
+ if (x < 1)
+ fun_l14_n402(x)
+ else
+ fun_l14_n445(x)
+ end
+end
+
+def fun_l13_n125(x)
+ if (x < 1)
+ fun_l14_n412(x)
+ else
+ fun_l14_n551(x)
+ end
+end
+
+def fun_l13_n126(x)
+ if (x < 1)
+ fun_l14_n295(x)
+ else
+ fun_l14_n180(x)
+ end
+end
+
+def fun_l13_n127(x)
+ if (x < 1)
+ fun_l14_n873(x)
+ else
+ fun_l14_n209(x)
+ end
+end
+
+def fun_l13_n128(x)
+ if (x < 1)
+ fun_l14_n181(x)
+ else
+ fun_l14_n198(x)
+ end
+end
+
+def fun_l13_n129(x)
+ if (x < 1)
+ fun_l14_n817(x)
+ else
+ fun_l14_n894(x)
+ end
+end
+
+def fun_l13_n130(x)
+ if (x < 1)
+ fun_l14_n306(x)
+ else
+ fun_l14_n429(x)
+ end
+end
+
+def fun_l13_n131(x)
+ if (x < 1)
+ fun_l14_n573(x)
+ else
+ fun_l14_n120(x)
+ end
+end
+
+def fun_l13_n132(x)
+ if (x < 1)
+ fun_l14_n433(x)
+ else
+ fun_l14_n668(x)
+ end
+end
+
+def fun_l13_n133(x)
+ if (x < 1)
+ fun_l14_n653(x)
+ else
+ fun_l14_n934(x)
+ end
+end
+
+def fun_l13_n134(x)
+ if (x < 1)
+ fun_l14_n280(x)
+ else
+ fun_l14_n533(x)
+ end
+end
+
+def fun_l13_n135(x)
+ if (x < 1)
+ fun_l14_n471(x)
+ else
+ fun_l14_n612(x)
+ end
+end
+
+def fun_l13_n136(x)
+ if (x < 1)
+ fun_l14_n55(x)
+ else
+ fun_l14_n684(x)
+ end
+end
+
+def fun_l13_n137(x)
+ if (x < 1)
+ fun_l14_n458(x)
+ else
+ fun_l14_n107(x)
+ end
+end
+
+def fun_l13_n138(x)
+ if (x < 1)
+ fun_l14_n415(x)
+ else
+ fun_l14_n189(x)
+ end
+end
+
+def fun_l13_n139(x)
+ if (x < 1)
+ fun_l14_n877(x)
+ else
+ fun_l14_n862(x)
+ end
+end
+
+def fun_l13_n140(x)
+ if (x < 1)
+ fun_l14_n471(x)
+ else
+ fun_l14_n533(x)
+ end
+end
+
+def fun_l13_n141(x)
+ if (x < 1)
+ fun_l14_n817(x)
+ else
+ fun_l14_n121(x)
+ end
+end
+
+def fun_l13_n142(x)
+ if (x < 1)
+ fun_l14_n523(x)
+ else
+ fun_l14_n894(x)
+ end
+end
+
+def fun_l13_n143(x)
+ if (x < 1)
+ fun_l14_n893(x)
+ else
+ fun_l14_n187(x)
+ end
+end
+
+def fun_l13_n144(x)
+ if (x < 1)
+ fun_l14_n921(x)
+ else
+ fun_l14_n253(x)
+ end
+end
+
+def fun_l13_n145(x)
+ if (x < 1)
+ fun_l14_n0(x)
+ else
+ fun_l14_n608(x)
+ end
+end
+
+def fun_l13_n146(x)
+ if (x < 1)
+ fun_l14_n83(x)
+ else
+ fun_l14_n450(x)
+ end
+end
+
+def fun_l13_n147(x)
+ if (x < 1)
+ fun_l14_n689(x)
+ else
+ fun_l14_n19(x)
+ end
+end
+
+def fun_l13_n148(x)
+ if (x < 1)
+ fun_l14_n922(x)
+ else
+ fun_l14_n417(x)
+ end
+end
+
+def fun_l13_n149(x)
+ if (x < 1)
+ fun_l14_n449(x)
+ else
+ fun_l14_n273(x)
+ end
+end
+
+def fun_l13_n150(x)
+ if (x < 1)
+ fun_l14_n601(x)
+ else
+ fun_l14_n442(x)
+ end
+end
+
+def fun_l13_n151(x)
+ if (x < 1)
+ fun_l14_n96(x)
+ else
+ fun_l14_n552(x)
+ end
+end
+
+def fun_l13_n152(x)
+ if (x < 1)
+ fun_l14_n667(x)
+ else
+ fun_l14_n273(x)
+ end
+end
+
+def fun_l13_n153(x)
+ if (x < 1)
+ fun_l14_n445(x)
+ else
+ fun_l14_n81(x)
+ end
+end
+
+def fun_l13_n154(x)
+ if (x < 1)
+ fun_l14_n906(x)
+ else
+ fun_l14_n960(x)
+ end
+end
+
+def fun_l13_n155(x)
+ if (x < 1)
+ fun_l14_n781(x)
+ else
+ fun_l14_n763(x)
+ end
+end
+
+def fun_l13_n156(x)
+ if (x < 1)
+ fun_l14_n201(x)
+ else
+ fun_l14_n886(x)
+ end
+end
+
+def fun_l13_n157(x)
+ if (x < 1)
+ fun_l14_n926(x)
+ else
+ fun_l14_n852(x)
+ end
+end
+
+def fun_l13_n158(x)
+ if (x < 1)
+ fun_l14_n114(x)
+ else
+ fun_l14_n23(x)
+ end
+end
+
+def fun_l13_n159(x)
+ if (x < 1)
+ fun_l14_n967(x)
+ else
+ fun_l14_n885(x)
+ end
+end
+
+def fun_l13_n160(x)
+ if (x < 1)
+ fun_l14_n563(x)
+ else
+ fun_l14_n309(x)
+ end
+end
+
+def fun_l13_n161(x)
+ if (x < 1)
+ fun_l14_n26(x)
+ else
+ fun_l14_n232(x)
+ end
+end
+
+def fun_l13_n162(x)
+ if (x < 1)
+ fun_l14_n212(x)
+ else
+ fun_l14_n147(x)
+ end
+end
+
+def fun_l13_n163(x)
+ if (x < 1)
+ fun_l14_n841(x)
+ else
+ fun_l14_n636(x)
+ end
+end
+
+def fun_l13_n164(x)
+ if (x < 1)
+ fun_l14_n405(x)
+ else
+ fun_l14_n709(x)
+ end
+end
+
+def fun_l13_n165(x)
+ if (x < 1)
+ fun_l14_n803(x)
+ else
+ fun_l14_n398(x)
+ end
+end
+
+def fun_l13_n166(x)
+ if (x < 1)
+ fun_l14_n112(x)
+ else
+ fun_l14_n197(x)
+ end
+end
+
+def fun_l13_n167(x)
+ if (x < 1)
+ fun_l14_n414(x)
+ else
+ fun_l14_n509(x)
+ end
+end
+
+def fun_l13_n168(x)
+ if (x < 1)
+ fun_l14_n585(x)
+ else
+ fun_l14_n166(x)
+ end
+end
+
+def fun_l13_n169(x)
+ if (x < 1)
+ fun_l14_n653(x)
+ else
+ fun_l14_n581(x)
+ end
+end
+
+def fun_l13_n170(x)
+ if (x < 1)
+ fun_l14_n291(x)
+ else
+ fun_l14_n520(x)
+ end
+end
+
+def fun_l13_n171(x)
+ if (x < 1)
+ fun_l14_n920(x)
+ else
+ fun_l14_n599(x)
+ end
+end
+
+def fun_l13_n172(x)
+ if (x < 1)
+ fun_l14_n125(x)
+ else
+ fun_l14_n84(x)
+ end
+end
+
+def fun_l13_n173(x)
+ if (x < 1)
+ fun_l14_n635(x)
+ else
+ fun_l14_n224(x)
+ end
+end
+
+def fun_l13_n174(x)
+ if (x < 1)
+ fun_l14_n23(x)
+ else
+ fun_l14_n922(x)
+ end
+end
+
+def fun_l13_n175(x)
+ if (x < 1)
+ fun_l14_n736(x)
+ else
+ fun_l14_n685(x)
+ end
+end
+
+def fun_l13_n176(x)
+ if (x < 1)
+ fun_l14_n235(x)
+ else
+ fun_l14_n157(x)
+ end
+end
+
+def fun_l13_n177(x)
+ if (x < 1)
+ fun_l14_n284(x)
+ else
+ fun_l14_n601(x)
+ end
+end
+
+def fun_l13_n178(x)
+ if (x < 1)
+ fun_l14_n785(x)
+ else
+ fun_l14_n498(x)
+ end
+end
+
+def fun_l13_n179(x)
+ if (x < 1)
+ fun_l14_n416(x)
+ else
+ fun_l14_n624(x)
+ end
+end
+
+def fun_l13_n180(x)
+ if (x < 1)
+ fun_l14_n747(x)
+ else
+ fun_l14_n824(x)
+ end
+end
+
+def fun_l13_n181(x)
+ if (x < 1)
+ fun_l14_n658(x)
+ else
+ fun_l14_n814(x)
+ end
+end
+
+def fun_l13_n182(x)
+ if (x < 1)
+ fun_l14_n723(x)
+ else
+ fun_l14_n365(x)
+ end
+end
+
+def fun_l13_n183(x)
+ if (x < 1)
+ fun_l14_n772(x)
+ else
+ fun_l14_n831(x)
+ end
+end
+
+def fun_l13_n184(x)
+ if (x < 1)
+ fun_l14_n560(x)
+ else
+ fun_l14_n933(x)
+ end
+end
+
+def fun_l13_n185(x)
+ if (x < 1)
+ fun_l14_n550(x)
+ else
+ fun_l14_n716(x)
+ end
+end
+
+def fun_l13_n186(x)
+ if (x < 1)
+ fun_l14_n72(x)
+ else
+ fun_l14_n224(x)
+ end
+end
+
+def fun_l13_n187(x)
+ if (x < 1)
+ fun_l14_n910(x)
+ else
+ fun_l14_n31(x)
+ end
+end
+
+def fun_l13_n188(x)
+ if (x < 1)
+ fun_l14_n792(x)
+ else
+ fun_l14_n69(x)
+ end
+end
+
+def fun_l13_n189(x)
+ if (x < 1)
+ fun_l14_n42(x)
+ else
+ fun_l14_n942(x)
+ end
+end
+
+def fun_l13_n190(x)
+ if (x < 1)
+ fun_l14_n520(x)
+ else
+ fun_l14_n826(x)
+ end
+end
+
+def fun_l13_n191(x)
+ if (x < 1)
+ fun_l14_n723(x)
+ else
+ fun_l14_n5(x)
+ end
+end
+
+def fun_l13_n192(x)
+ if (x < 1)
+ fun_l14_n448(x)
+ else
+ fun_l14_n243(x)
+ end
+end
+
+def fun_l13_n193(x)
+ if (x < 1)
+ fun_l14_n722(x)
+ else
+ fun_l14_n450(x)
+ end
+end
+
+def fun_l13_n194(x)
+ if (x < 1)
+ fun_l14_n31(x)
+ else
+ fun_l14_n968(x)
+ end
+end
+
+def fun_l13_n195(x)
+ if (x < 1)
+ fun_l14_n381(x)
+ else
+ fun_l14_n964(x)
+ end
+end
+
+def fun_l13_n196(x)
+ if (x < 1)
+ fun_l14_n797(x)
+ else
+ fun_l14_n216(x)
+ end
+end
+
+def fun_l13_n197(x)
+ if (x < 1)
+ fun_l14_n351(x)
+ else
+ fun_l14_n439(x)
+ end
+end
+
+def fun_l13_n198(x)
+ if (x < 1)
+ fun_l14_n983(x)
+ else
+ fun_l14_n363(x)
+ end
+end
+
+def fun_l13_n199(x)
+ if (x < 1)
+ fun_l14_n939(x)
+ else
+ fun_l14_n806(x)
+ end
+end
+
+def fun_l13_n200(x)
+ if (x < 1)
+ fun_l14_n710(x)
+ else
+ fun_l14_n513(x)
+ end
+end
+
+def fun_l13_n201(x)
+ if (x < 1)
+ fun_l14_n431(x)
+ else
+ fun_l14_n81(x)
+ end
+end
+
+def fun_l13_n202(x)
+ if (x < 1)
+ fun_l14_n41(x)
+ else
+ fun_l14_n916(x)
+ end
+end
+
+def fun_l13_n203(x)
+ if (x < 1)
+ fun_l14_n368(x)
+ else
+ fun_l14_n626(x)
+ end
+end
+
+def fun_l13_n204(x)
+ if (x < 1)
+ fun_l14_n505(x)
+ else
+ fun_l14_n750(x)
+ end
+end
+
+def fun_l13_n205(x)
+ if (x < 1)
+ fun_l14_n263(x)
+ else
+ fun_l14_n636(x)
+ end
+end
+
+def fun_l13_n206(x)
+ if (x < 1)
+ fun_l14_n589(x)
+ else
+ fun_l14_n215(x)
+ end
+end
+
+def fun_l13_n207(x)
+ if (x < 1)
+ fun_l14_n435(x)
+ else
+ fun_l14_n69(x)
+ end
+end
+
+def fun_l13_n208(x)
+ if (x < 1)
+ fun_l14_n114(x)
+ else
+ fun_l14_n222(x)
+ end
+end
+
+def fun_l13_n209(x)
+ if (x < 1)
+ fun_l14_n784(x)
+ else
+ fun_l14_n337(x)
+ end
+end
+
+def fun_l13_n210(x)
+ if (x < 1)
+ fun_l14_n434(x)
+ else
+ fun_l14_n79(x)
+ end
+end
+
+def fun_l13_n211(x)
+ if (x < 1)
+ fun_l14_n152(x)
+ else
+ fun_l14_n428(x)
+ end
+end
+
+def fun_l13_n212(x)
+ if (x < 1)
+ fun_l14_n24(x)
+ else
+ fun_l14_n101(x)
+ end
+end
+
+def fun_l13_n213(x)
+ if (x < 1)
+ fun_l14_n880(x)
+ else
+ fun_l14_n672(x)
+ end
+end
+
+def fun_l13_n214(x)
+ if (x < 1)
+ fun_l14_n824(x)
+ else
+ fun_l14_n351(x)
+ end
+end
+
+def fun_l13_n215(x)
+ if (x < 1)
+ fun_l14_n657(x)
+ else
+ fun_l14_n822(x)
+ end
+end
+
+def fun_l13_n216(x)
+ if (x < 1)
+ fun_l14_n603(x)
+ else
+ fun_l14_n993(x)
+ end
+end
+
+def fun_l13_n217(x)
+ if (x < 1)
+ fun_l14_n593(x)
+ else
+ fun_l14_n808(x)
+ end
+end
+
+def fun_l13_n218(x)
+ if (x < 1)
+ fun_l14_n30(x)
+ else
+ fun_l14_n632(x)
+ end
+end
+
+def fun_l13_n219(x)
+ if (x < 1)
+ fun_l14_n175(x)
+ else
+ fun_l14_n124(x)
+ end
+end
+
+def fun_l13_n220(x)
+ if (x < 1)
+ fun_l14_n878(x)
+ else
+ fun_l14_n342(x)
+ end
+end
+
+def fun_l13_n221(x)
+ if (x < 1)
+ fun_l14_n857(x)
+ else
+ fun_l14_n204(x)
+ end
+end
+
+def fun_l13_n222(x)
+ if (x < 1)
+ fun_l14_n29(x)
+ else
+ fun_l14_n573(x)
+ end
+end
+
+def fun_l13_n223(x)
+ if (x < 1)
+ fun_l14_n329(x)
+ else
+ fun_l14_n35(x)
+ end
+end
+
+def fun_l13_n224(x)
+ if (x < 1)
+ fun_l14_n31(x)
+ else
+ fun_l14_n323(x)
+ end
+end
+
+def fun_l13_n225(x)
+ if (x < 1)
+ fun_l14_n921(x)
+ else
+ fun_l14_n161(x)
+ end
+end
+
+def fun_l13_n226(x)
+ if (x < 1)
+ fun_l14_n599(x)
+ else
+ fun_l14_n566(x)
+ end
+end
+
+def fun_l13_n227(x)
+ if (x < 1)
+ fun_l14_n994(x)
+ else
+ fun_l14_n549(x)
+ end
+end
+
+def fun_l13_n228(x)
+ if (x < 1)
+ fun_l14_n989(x)
+ else
+ fun_l14_n212(x)
+ end
+end
+
+def fun_l13_n229(x)
+ if (x < 1)
+ fun_l14_n22(x)
+ else
+ fun_l14_n656(x)
+ end
+end
+
+def fun_l13_n230(x)
+ if (x < 1)
+ fun_l14_n232(x)
+ else
+ fun_l14_n658(x)
+ end
+end
+
+def fun_l13_n231(x)
+ if (x < 1)
+ fun_l14_n522(x)
+ else
+ fun_l14_n596(x)
+ end
+end
+
+def fun_l13_n232(x)
+ if (x < 1)
+ fun_l14_n296(x)
+ else
+ fun_l14_n53(x)
+ end
+end
+
+def fun_l13_n233(x)
+ if (x < 1)
+ fun_l14_n958(x)
+ else
+ fun_l14_n818(x)
+ end
+end
+
+def fun_l13_n234(x)
+ if (x < 1)
+ fun_l14_n267(x)
+ else
+ fun_l14_n299(x)
+ end
+end
+
+def fun_l13_n235(x)
+ if (x < 1)
+ fun_l14_n776(x)
+ else
+ fun_l14_n99(x)
+ end
+end
+
+def fun_l13_n236(x)
+ if (x < 1)
+ fun_l14_n204(x)
+ else
+ fun_l14_n34(x)
+ end
+end
+
+def fun_l13_n237(x)
+ if (x < 1)
+ fun_l14_n704(x)
+ else
+ fun_l14_n808(x)
+ end
+end
+
+def fun_l13_n238(x)
+ if (x < 1)
+ fun_l14_n82(x)
+ else
+ fun_l14_n352(x)
+ end
+end
+
+def fun_l13_n239(x)
+ if (x < 1)
+ fun_l14_n382(x)
+ else
+ fun_l14_n447(x)
+ end
+end
+
+def fun_l13_n240(x)
+ if (x < 1)
+ fun_l14_n200(x)
+ else
+ fun_l14_n623(x)
+ end
+end
+
+def fun_l13_n241(x)
+ if (x < 1)
+ fun_l14_n563(x)
+ else
+ fun_l14_n259(x)
+ end
+end
+
+def fun_l13_n242(x)
+ if (x < 1)
+ fun_l14_n126(x)
+ else
+ fun_l14_n337(x)
+ end
+end
+
+def fun_l13_n243(x)
+ if (x < 1)
+ fun_l14_n287(x)
+ else
+ fun_l14_n441(x)
+ end
+end
+
+def fun_l13_n244(x)
+ if (x < 1)
+ fun_l14_n271(x)
+ else
+ fun_l14_n961(x)
+ end
+end
+
+def fun_l13_n245(x)
+ if (x < 1)
+ fun_l14_n677(x)
+ else
+ fun_l14_n310(x)
+ end
+end
+
+def fun_l13_n246(x)
+ if (x < 1)
+ fun_l14_n504(x)
+ else
+ fun_l14_n504(x)
+ end
+end
+
+def fun_l13_n247(x)
+ if (x < 1)
+ fun_l14_n61(x)
+ else
+ fun_l14_n560(x)
+ end
+end
+
+def fun_l13_n248(x)
+ if (x < 1)
+ fun_l14_n813(x)
+ else
+ fun_l14_n337(x)
+ end
+end
+
+def fun_l13_n249(x)
+ if (x < 1)
+ fun_l14_n89(x)
+ else
+ fun_l14_n733(x)
+ end
+end
+
+def fun_l13_n250(x)
+ if (x < 1)
+ fun_l14_n203(x)
+ else
+ fun_l14_n342(x)
+ end
+end
+
+def fun_l13_n251(x)
+ if (x < 1)
+ fun_l14_n605(x)
+ else
+ fun_l14_n767(x)
+ end
+end
+
+def fun_l13_n252(x)
+ if (x < 1)
+ fun_l14_n35(x)
+ else
+ fun_l14_n338(x)
+ end
+end
+
+def fun_l13_n253(x)
+ if (x < 1)
+ fun_l14_n894(x)
+ else
+ fun_l14_n905(x)
+ end
+end
+
+def fun_l13_n254(x)
+ if (x < 1)
+ fun_l14_n516(x)
+ else
+ fun_l14_n832(x)
+ end
+end
+
+def fun_l13_n255(x)
+ if (x < 1)
+ fun_l14_n106(x)
+ else
+ fun_l14_n672(x)
+ end
+end
+
+def fun_l13_n256(x)
+ if (x < 1)
+ fun_l14_n978(x)
+ else
+ fun_l14_n940(x)
+ end
+end
+
+def fun_l13_n257(x)
+ if (x < 1)
+ fun_l14_n808(x)
+ else
+ fun_l14_n906(x)
+ end
+end
+
+def fun_l13_n258(x)
+ if (x < 1)
+ fun_l14_n435(x)
+ else
+ fun_l14_n55(x)
+ end
+end
+
+def fun_l13_n259(x)
+ if (x < 1)
+ fun_l14_n981(x)
+ else
+ fun_l14_n550(x)
+ end
+end
+
+def fun_l13_n260(x)
+ if (x < 1)
+ fun_l14_n689(x)
+ else
+ fun_l14_n533(x)
+ end
+end
+
+def fun_l13_n261(x)
+ if (x < 1)
+ fun_l14_n995(x)
+ else
+ fun_l14_n174(x)
+ end
+end
+
+def fun_l13_n262(x)
+ if (x < 1)
+ fun_l14_n161(x)
+ else
+ fun_l14_n357(x)
+ end
+end
+
+def fun_l13_n263(x)
+ if (x < 1)
+ fun_l14_n248(x)
+ else
+ fun_l14_n509(x)
+ end
+end
+
+def fun_l13_n264(x)
+ if (x < 1)
+ fun_l14_n521(x)
+ else
+ fun_l14_n41(x)
+ end
+end
+
+def fun_l13_n265(x)
+ if (x < 1)
+ fun_l14_n771(x)
+ else
+ fun_l14_n387(x)
+ end
+end
+
+def fun_l13_n266(x)
+ if (x < 1)
+ fun_l14_n149(x)
+ else
+ fun_l14_n814(x)
+ end
+end
+
+def fun_l13_n267(x)
+ if (x < 1)
+ fun_l14_n958(x)
+ else
+ fun_l14_n172(x)
+ end
+end
+
+def fun_l13_n268(x)
+ if (x < 1)
+ fun_l14_n167(x)
+ else
+ fun_l14_n889(x)
+ end
+end
+
+def fun_l13_n269(x)
+ if (x < 1)
+ fun_l14_n321(x)
+ else
+ fun_l14_n152(x)
+ end
+end
+
+def fun_l13_n270(x)
+ if (x < 1)
+ fun_l14_n851(x)
+ else
+ fun_l14_n793(x)
+ end
+end
+
+def fun_l13_n271(x)
+ if (x < 1)
+ fun_l14_n306(x)
+ else
+ fun_l14_n843(x)
+ end
+end
+
+def fun_l13_n272(x)
+ if (x < 1)
+ fun_l14_n499(x)
+ else
+ fun_l14_n118(x)
+ end
+end
+
+def fun_l13_n273(x)
+ if (x < 1)
+ fun_l14_n958(x)
+ else
+ fun_l14_n597(x)
+ end
+end
+
+def fun_l13_n274(x)
+ if (x < 1)
+ fun_l14_n884(x)
+ else
+ fun_l14_n23(x)
+ end
+end
+
+def fun_l13_n275(x)
+ if (x < 1)
+ fun_l14_n203(x)
+ else
+ fun_l14_n796(x)
+ end
+end
+
+def fun_l13_n276(x)
+ if (x < 1)
+ fun_l14_n944(x)
+ else
+ fun_l14_n239(x)
+ end
+end
+
+def fun_l13_n277(x)
+ if (x < 1)
+ fun_l14_n511(x)
+ else
+ fun_l14_n464(x)
+ end
+end
+
+def fun_l13_n278(x)
+ if (x < 1)
+ fun_l14_n906(x)
+ else
+ fun_l14_n713(x)
+ end
+end
+
+def fun_l13_n279(x)
+ if (x < 1)
+ fun_l14_n872(x)
+ else
+ fun_l14_n77(x)
+ end
+end
+
+def fun_l13_n280(x)
+ if (x < 1)
+ fun_l14_n888(x)
+ else
+ fun_l14_n117(x)
+ end
+end
+
+def fun_l13_n281(x)
+ if (x < 1)
+ fun_l14_n298(x)
+ else
+ fun_l14_n695(x)
+ end
+end
+
+def fun_l13_n282(x)
+ if (x < 1)
+ fun_l14_n740(x)
+ else
+ fun_l14_n668(x)
+ end
+end
+
+def fun_l13_n283(x)
+ if (x < 1)
+ fun_l14_n438(x)
+ else
+ fun_l14_n322(x)
+ end
+end
+
+def fun_l13_n284(x)
+ if (x < 1)
+ fun_l14_n39(x)
+ else
+ fun_l14_n39(x)
+ end
+end
+
+def fun_l13_n285(x)
+ if (x < 1)
+ fun_l14_n271(x)
+ else
+ fun_l14_n984(x)
+ end
+end
+
+def fun_l13_n286(x)
+ if (x < 1)
+ fun_l14_n278(x)
+ else
+ fun_l14_n453(x)
+ end
+end
+
+def fun_l13_n287(x)
+ if (x < 1)
+ fun_l14_n303(x)
+ else
+ fun_l14_n812(x)
+ end
+end
+
+def fun_l13_n288(x)
+ if (x < 1)
+ fun_l14_n891(x)
+ else
+ fun_l14_n843(x)
+ end
+end
+
+def fun_l13_n289(x)
+ if (x < 1)
+ fun_l14_n672(x)
+ else
+ fun_l14_n543(x)
+ end
+end
+
+def fun_l13_n290(x)
+ if (x < 1)
+ fun_l14_n115(x)
+ else
+ fun_l14_n33(x)
+ end
+end
+
+def fun_l13_n291(x)
+ if (x < 1)
+ fun_l14_n467(x)
+ else
+ fun_l14_n427(x)
+ end
+end
+
+def fun_l13_n292(x)
+ if (x < 1)
+ fun_l14_n528(x)
+ else
+ fun_l14_n51(x)
+ end
+end
+
+def fun_l13_n293(x)
+ if (x < 1)
+ fun_l14_n50(x)
+ else
+ fun_l14_n917(x)
+ end
+end
+
+def fun_l13_n294(x)
+ if (x < 1)
+ fun_l14_n245(x)
+ else
+ fun_l14_n289(x)
+ end
+end
+
+def fun_l13_n295(x)
+ if (x < 1)
+ fun_l14_n108(x)
+ else
+ fun_l14_n772(x)
+ end
+end
+
+def fun_l13_n296(x)
+ if (x < 1)
+ fun_l14_n451(x)
+ else
+ fun_l14_n127(x)
+ end
+end
+
+def fun_l13_n297(x)
+ if (x < 1)
+ fun_l14_n374(x)
+ else
+ fun_l14_n20(x)
+ end
+end
+
+def fun_l13_n298(x)
+ if (x < 1)
+ fun_l14_n588(x)
+ else
+ fun_l14_n95(x)
+ end
+end
+
+def fun_l13_n299(x)
+ if (x < 1)
+ fun_l14_n33(x)
+ else
+ fun_l14_n146(x)
+ end
+end
+
+def fun_l13_n300(x)
+ if (x < 1)
+ fun_l14_n812(x)
+ else
+ fun_l14_n373(x)
+ end
+end
+
+def fun_l13_n301(x)
+ if (x < 1)
+ fun_l14_n39(x)
+ else
+ fun_l14_n228(x)
+ end
+end
+
+def fun_l13_n302(x)
+ if (x < 1)
+ fun_l14_n992(x)
+ else
+ fun_l14_n578(x)
+ end
+end
+
+def fun_l13_n303(x)
+ if (x < 1)
+ fun_l14_n106(x)
+ else
+ fun_l14_n413(x)
+ end
+end
+
+def fun_l13_n304(x)
+ if (x < 1)
+ fun_l14_n463(x)
+ else
+ fun_l14_n884(x)
+ end
+end
+
+def fun_l13_n305(x)
+ if (x < 1)
+ fun_l14_n754(x)
+ else
+ fun_l14_n114(x)
+ end
+end
+
+def fun_l13_n306(x)
+ if (x < 1)
+ fun_l14_n960(x)
+ else
+ fun_l14_n596(x)
+ end
+end
+
+def fun_l13_n307(x)
+ if (x < 1)
+ fun_l14_n858(x)
+ else
+ fun_l14_n488(x)
+ end
+end
+
+def fun_l13_n308(x)
+ if (x < 1)
+ fun_l14_n968(x)
+ else
+ fun_l14_n507(x)
+ end
+end
+
+def fun_l13_n309(x)
+ if (x < 1)
+ fun_l14_n956(x)
+ else
+ fun_l14_n125(x)
+ end
+end
+
+def fun_l13_n310(x)
+ if (x < 1)
+ fun_l14_n190(x)
+ else
+ fun_l14_n817(x)
+ end
+end
+
+def fun_l13_n311(x)
+ if (x < 1)
+ fun_l14_n574(x)
+ else
+ fun_l14_n447(x)
+ end
+end
+
+def fun_l13_n312(x)
+ if (x < 1)
+ fun_l14_n403(x)
+ else
+ fun_l14_n591(x)
+ end
+end
+
+def fun_l13_n313(x)
+ if (x < 1)
+ fun_l14_n499(x)
+ else
+ fun_l14_n458(x)
+ end
+end
+
+def fun_l13_n314(x)
+ if (x < 1)
+ fun_l14_n994(x)
+ else
+ fun_l14_n77(x)
+ end
+end
+
+def fun_l13_n315(x)
+ if (x < 1)
+ fun_l14_n421(x)
+ else
+ fun_l14_n810(x)
+ end
+end
+
+def fun_l13_n316(x)
+ if (x < 1)
+ fun_l14_n304(x)
+ else
+ fun_l14_n785(x)
+ end
+end
+
+def fun_l13_n317(x)
+ if (x < 1)
+ fun_l14_n624(x)
+ else
+ fun_l14_n399(x)
+ end
+end
+
+def fun_l13_n318(x)
+ if (x < 1)
+ fun_l14_n882(x)
+ else
+ fun_l14_n3(x)
+ end
+end
+
+def fun_l13_n319(x)
+ if (x < 1)
+ fun_l14_n267(x)
+ else
+ fun_l14_n955(x)
+ end
+end
+
+def fun_l13_n320(x)
+ if (x < 1)
+ fun_l14_n690(x)
+ else
+ fun_l14_n281(x)
+ end
+end
+
+def fun_l13_n321(x)
+ if (x < 1)
+ fun_l14_n453(x)
+ else
+ fun_l14_n969(x)
+ end
+end
+
+def fun_l13_n322(x)
+ if (x < 1)
+ fun_l14_n297(x)
+ else
+ fun_l14_n50(x)
+ end
+end
+
+def fun_l13_n323(x)
+ if (x < 1)
+ fun_l14_n342(x)
+ else
+ fun_l14_n618(x)
+ end
+end
+
+def fun_l13_n324(x)
+ if (x < 1)
+ fun_l14_n74(x)
+ else
+ fun_l14_n638(x)
+ end
+end
+
+def fun_l13_n325(x)
+ if (x < 1)
+ fun_l14_n218(x)
+ else
+ fun_l14_n169(x)
+ end
+end
+
+def fun_l13_n326(x)
+ if (x < 1)
+ fun_l14_n128(x)
+ else
+ fun_l14_n504(x)
+ end
+end
+
+def fun_l13_n327(x)
+ if (x < 1)
+ fun_l14_n612(x)
+ else
+ fun_l14_n62(x)
+ end
+end
+
+def fun_l13_n328(x)
+ if (x < 1)
+ fun_l14_n83(x)
+ else
+ fun_l14_n67(x)
+ end
+end
+
+def fun_l13_n329(x)
+ if (x < 1)
+ fun_l14_n515(x)
+ else
+ fun_l14_n15(x)
+ end
+end
+
+def fun_l13_n330(x)
+ if (x < 1)
+ fun_l14_n448(x)
+ else
+ fun_l14_n951(x)
+ end
+end
+
+def fun_l13_n331(x)
+ if (x < 1)
+ fun_l14_n804(x)
+ else
+ fun_l14_n315(x)
+ end
+end
+
+def fun_l13_n332(x)
+ if (x < 1)
+ fun_l14_n522(x)
+ else
+ fun_l14_n761(x)
+ end
+end
+
+def fun_l13_n333(x)
+ if (x < 1)
+ fun_l14_n421(x)
+ else
+ fun_l14_n542(x)
+ end
+end
+
+def fun_l13_n334(x)
+ if (x < 1)
+ fun_l14_n952(x)
+ else
+ fun_l14_n390(x)
+ end
+end
+
+def fun_l13_n335(x)
+ if (x < 1)
+ fun_l14_n324(x)
+ else
+ fun_l14_n60(x)
+ end
+end
+
+def fun_l13_n336(x)
+ if (x < 1)
+ fun_l14_n887(x)
+ else
+ fun_l14_n474(x)
+ end
+end
+
+def fun_l13_n337(x)
+ if (x < 1)
+ fun_l14_n355(x)
+ else
+ fun_l14_n840(x)
+ end
+end
+
+def fun_l13_n338(x)
+ if (x < 1)
+ fun_l14_n21(x)
+ else
+ fun_l14_n133(x)
+ end
+end
+
+def fun_l13_n339(x)
+ if (x < 1)
+ fun_l14_n12(x)
+ else
+ fun_l14_n30(x)
+ end
+end
+
+def fun_l13_n340(x)
+ if (x < 1)
+ fun_l14_n678(x)
+ else
+ fun_l14_n583(x)
+ end
+end
+
+def fun_l13_n341(x)
+ if (x < 1)
+ fun_l14_n289(x)
+ else
+ fun_l14_n490(x)
+ end
+end
+
+def fun_l13_n342(x)
+ if (x < 1)
+ fun_l14_n232(x)
+ else
+ fun_l14_n288(x)
+ end
+end
+
+def fun_l13_n343(x)
+ if (x < 1)
+ fun_l14_n744(x)
+ else
+ fun_l14_n963(x)
+ end
+end
+
+def fun_l13_n344(x)
+ if (x < 1)
+ fun_l14_n651(x)
+ else
+ fun_l14_n377(x)
+ end
+end
+
+def fun_l13_n345(x)
+ if (x < 1)
+ fun_l14_n13(x)
+ else
+ fun_l14_n749(x)
+ end
+end
+
+def fun_l13_n346(x)
+ if (x < 1)
+ fun_l14_n789(x)
+ else
+ fun_l14_n621(x)
+ end
+end
+
+def fun_l13_n347(x)
+ if (x < 1)
+ fun_l14_n346(x)
+ else
+ fun_l14_n663(x)
+ end
+end
+
+def fun_l13_n348(x)
+ if (x < 1)
+ fun_l14_n252(x)
+ else
+ fun_l14_n202(x)
+ end
+end
+
+def fun_l13_n349(x)
+ if (x < 1)
+ fun_l14_n919(x)
+ else
+ fun_l14_n997(x)
+ end
+end
+
+def fun_l13_n350(x)
+ if (x < 1)
+ fun_l14_n472(x)
+ else
+ fun_l14_n900(x)
+ end
+end
+
+def fun_l13_n351(x)
+ if (x < 1)
+ fun_l14_n954(x)
+ else
+ fun_l14_n606(x)
+ end
+end
+
+def fun_l13_n352(x)
+ if (x < 1)
+ fun_l14_n227(x)
+ else
+ fun_l14_n344(x)
+ end
+end
+
+def fun_l13_n353(x)
+ if (x < 1)
+ fun_l14_n110(x)
+ else
+ fun_l14_n266(x)
+ end
+end
+
+def fun_l13_n354(x)
+ if (x < 1)
+ fun_l14_n840(x)
+ else
+ fun_l14_n905(x)
+ end
+end
+
+def fun_l13_n355(x)
+ if (x < 1)
+ fun_l14_n950(x)
+ else
+ fun_l14_n307(x)
+ end
+end
+
+def fun_l13_n356(x)
+ if (x < 1)
+ fun_l14_n572(x)
+ else
+ fun_l14_n480(x)
+ end
+end
+
+def fun_l13_n357(x)
+ if (x < 1)
+ fun_l14_n122(x)
+ else
+ fun_l14_n408(x)
+ end
+end
+
+def fun_l13_n358(x)
+ if (x < 1)
+ fun_l14_n105(x)
+ else
+ fun_l14_n173(x)
+ end
+end
+
+def fun_l13_n359(x)
+ if (x < 1)
+ fun_l14_n358(x)
+ else
+ fun_l14_n336(x)
+ end
+end
+
+def fun_l13_n360(x)
+ if (x < 1)
+ fun_l14_n457(x)
+ else
+ fun_l14_n434(x)
+ end
+end
+
+def fun_l13_n361(x)
+ if (x < 1)
+ fun_l14_n679(x)
+ else
+ fun_l14_n771(x)
+ end
+end
+
+def fun_l13_n362(x)
+ if (x < 1)
+ fun_l14_n419(x)
+ else
+ fun_l14_n909(x)
+ end
+end
+
+def fun_l13_n363(x)
+ if (x < 1)
+ fun_l14_n672(x)
+ else
+ fun_l14_n132(x)
+ end
+end
+
+def fun_l13_n364(x)
+ if (x < 1)
+ fun_l14_n947(x)
+ else
+ fun_l14_n328(x)
+ end
+end
+
+def fun_l13_n365(x)
+ if (x < 1)
+ fun_l14_n959(x)
+ else
+ fun_l14_n122(x)
+ end
+end
+
+def fun_l13_n366(x)
+ if (x < 1)
+ fun_l14_n534(x)
+ else
+ fun_l14_n611(x)
+ end
+end
+
+def fun_l13_n367(x)
+ if (x < 1)
+ fun_l14_n349(x)
+ else
+ fun_l14_n149(x)
+ end
+end
+
+def fun_l13_n368(x)
+ if (x < 1)
+ fun_l14_n94(x)
+ else
+ fun_l14_n870(x)
+ end
+end
+
+def fun_l13_n369(x)
+ if (x < 1)
+ fun_l14_n774(x)
+ else
+ fun_l14_n696(x)
+ end
+end
+
+def fun_l13_n370(x)
+ if (x < 1)
+ fun_l14_n311(x)
+ else
+ fun_l14_n479(x)
+ end
+end
+
+def fun_l13_n371(x)
+ if (x < 1)
+ fun_l14_n650(x)
+ else
+ fun_l14_n66(x)
+ end
+end
+
+def fun_l13_n372(x)
+ if (x < 1)
+ fun_l14_n825(x)
+ else
+ fun_l14_n910(x)
+ end
+end
+
+def fun_l13_n373(x)
+ if (x < 1)
+ fun_l14_n454(x)
+ else
+ fun_l14_n492(x)
+ end
+end
+
+def fun_l13_n374(x)
+ if (x < 1)
+ fun_l14_n785(x)
+ else
+ fun_l14_n352(x)
+ end
+end
+
+def fun_l13_n375(x)
+ if (x < 1)
+ fun_l14_n124(x)
+ else
+ fun_l14_n664(x)
+ end
+end
+
+def fun_l13_n376(x)
+ if (x < 1)
+ fun_l14_n427(x)
+ else
+ fun_l14_n615(x)
+ end
+end
+
+def fun_l13_n377(x)
+ if (x < 1)
+ fun_l14_n926(x)
+ else
+ fun_l14_n307(x)
+ end
+end
+
+def fun_l13_n378(x)
+ if (x < 1)
+ fun_l14_n575(x)
+ else
+ fun_l14_n561(x)
+ end
+end
+
+def fun_l13_n379(x)
+ if (x < 1)
+ fun_l14_n497(x)
+ else
+ fun_l14_n690(x)
+ end
+end
+
+def fun_l13_n380(x)
+ if (x < 1)
+ fun_l14_n350(x)
+ else
+ fun_l14_n641(x)
+ end
+end
+
+def fun_l13_n381(x)
+ if (x < 1)
+ fun_l14_n292(x)
+ else
+ fun_l14_n739(x)
+ end
+end
+
+def fun_l13_n382(x)
+ if (x < 1)
+ fun_l14_n302(x)
+ else
+ fun_l14_n583(x)
+ end
+end
+
+def fun_l13_n383(x)
+ if (x < 1)
+ fun_l14_n36(x)
+ else
+ fun_l14_n603(x)
+ end
+end
+
+def fun_l13_n384(x)
+ if (x < 1)
+ fun_l14_n953(x)
+ else
+ fun_l14_n394(x)
+ end
+end
+
+def fun_l13_n385(x)
+ if (x < 1)
+ fun_l14_n107(x)
+ else
+ fun_l14_n149(x)
+ end
+end
+
+def fun_l13_n386(x)
+ if (x < 1)
+ fun_l14_n77(x)
+ else
+ fun_l14_n880(x)
+ end
+end
+
+def fun_l13_n387(x)
+ if (x < 1)
+ fun_l14_n670(x)
+ else
+ fun_l14_n649(x)
+ end
+end
+
+def fun_l13_n388(x)
+ if (x < 1)
+ fun_l14_n277(x)
+ else
+ fun_l14_n922(x)
+ end
+end
+
+def fun_l13_n389(x)
+ if (x < 1)
+ fun_l14_n981(x)
+ else
+ fun_l14_n427(x)
+ end
+end
+
+def fun_l13_n390(x)
+ if (x < 1)
+ fun_l14_n411(x)
+ else
+ fun_l14_n804(x)
+ end
+end
+
+def fun_l13_n391(x)
+ if (x < 1)
+ fun_l14_n52(x)
+ else
+ fun_l14_n770(x)
+ end
+end
+
+def fun_l13_n392(x)
+ if (x < 1)
+ fun_l14_n592(x)
+ else
+ fun_l14_n672(x)
+ end
+end
+
+def fun_l13_n393(x)
+ if (x < 1)
+ fun_l14_n274(x)
+ else
+ fun_l14_n778(x)
+ end
+end
+
+def fun_l13_n394(x)
+ if (x < 1)
+ fun_l14_n708(x)
+ else
+ fun_l14_n262(x)
+ end
+end
+
+def fun_l13_n395(x)
+ if (x < 1)
+ fun_l14_n449(x)
+ else
+ fun_l14_n273(x)
+ end
+end
+
+def fun_l13_n396(x)
+ if (x < 1)
+ fun_l14_n567(x)
+ else
+ fun_l14_n148(x)
+ end
+end
+
+def fun_l13_n397(x)
+ if (x < 1)
+ fun_l14_n127(x)
+ else
+ fun_l14_n309(x)
+ end
+end
+
+def fun_l13_n398(x)
+ if (x < 1)
+ fun_l14_n150(x)
+ else
+ fun_l14_n540(x)
+ end
+end
+
+def fun_l13_n399(x)
+ if (x < 1)
+ fun_l14_n791(x)
+ else
+ fun_l14_n517(x)
+ end
+end
+
+def fun_l13_n400(x)
+ if (x < 1)
+ fun_l14_n152(x)
+ else
+ fun_l14_n319(x)
+ end
+end
+
+def fun_l13_n401(x)
+ if (x < 1)
+ fun_l14_n911(x)
+ else
+ fun_l14_n544(x)
+ end
+end
+
+def fun_l13_n402(x)
+ if (x < 1)
+ fun_l14_n915(x)
+ else
+ fun_l14_n208(x)
+ end
+end
+
+def fun_l13_n403(x)
+ if (x < 1)
+ fun_l14_n452(x)
+ else
+ fun_l14_n62(x)
+ end
+end
+
+def fun_l13_n404(x)
+ if (x < 1)
+ fun_l14_n823(x)
+ else
+ fun_l14_n913(x)
+ end
+end
+
+def fun_l13_n405(x)
+ if (x < 1)
+ fun_l14_n808(x)
+ else
+ fun_l14_n49(x)
+ end
+end
+
+def fun_l13_n406(x)
+ if (x < 1)
+ fun_l14_n498(x)
+ else
+ fun_l14_n470(x)
+ end
+end
+
+def fun_l13_n407(x)
+ if (x < 1)
+ fun_l14_n314(x)
+ else
+ fun_l14_n248(x)
+ end
+end
+
+def fun_l13_n408(x)
+ if (x < 1)
+ fun_l14_n61(x)
+ else
+ fun_l14_n190(x)
+ end
+end
+
+def fun_l13_n409(x)
+ if (x < 1)
+ fun_l14_n126(x)
+ else
+ fun_l14_n505(x)
+ end
+end
+
+def fun_l13_n410(x)
+ if (x < 1)
+ fun_l14_n646(x)
+ else
+ fun_l14_n319(x)
+ end
+end
+
+def fun_l13_n411(x)
+ if (x < 1)
+ fun_l14_n741(x)
+ else
+ fun_l14_n979(x)
+ end
+end
+
+def fun_l13_n412(x)
+ if (x < 1)
+ fun_l14_n840(x)
+ else
+ fun_l14_n211(x)
+ end
+end
+
+def fun_l13_n413(x)
+ if (x < 1)
+ fun_l14_n217(x)
+ else
+ fun_l14_n98(x)
+ end
+end
+
+def fun_l13_n414(x)
+ if (x < 1)
+ fun_l14_n398(x)
+ else
+ fun_l14_n701(x)
+ end
+end
+
+def fun_l13_n415(x)
+ if (x < 1)
+ fun_l14_n470(x)
+ else
+ fun_l14_n394(x)
+ end
+end
+
+def fun_l13_n416(x)
+ if (x < 1)
+ fun_l14_n113(x)
+ else
+ fun_l14_n792(x)
+ end
+end
+
+def fun_l13_n417(x)
+ if (x < 1)
+ fun_l14_n969(x)
+ else
+ fun_l14_n99(x)
+ end
+end
+
+def fun_l13_n418(x)
+ if (x < 1)
+ fun_l14_n54(x)
+ else
+ fun_l14_n800(x)
+ end
+end
+
+def fun_l13_n419(x)
+ if (x < 1)
+ fun_l14_n763(x)
+ else
+ fun_l14_n510(x)
+ end
+end
+
+def fun_l13_n420(x)
+ if (x < 1)
+ fun_l14_n660(x)
+ else
+ fun_l14_n904(x)
+ end
+end
+
+def fun_l13_n421(x)
+ if (x < 1)
+ fun_l14_n345(x)
+ else
+ fun_l14_n200(x)
+ end
+end
+
+def fun_l13_n422(x)
+ if (x < 1)
+ fun_l14_n831(x)
+ else
+ fun_l14_n35(x)
+ end
+end
+
+def fun_l13_n423(x)
+ if (x < 1)
+ fun_l14_n644(x)
+ else
+ fun_l14_n963(x)
+ end
+end
+
+def fun_l13_n424(x)
+ if (x < 1)
+ fun_l14_n0(x)
+ else
+ fun_l14_n625(x)
+ end
+end
+
+def fun_l13_n425(x)
+ if (x < 1)
+ fun_l14_n186(x)
+ else
+ fun_l14_n409(x)
+ end
+end
+
+def fun_l13_n426(x)
+ if (x < 1)
+ fun_l14_n869(x)
+ else
+ fun_l14_n852(x)
+ end
+end
+
+def fun_l13_n427(x)
+ if (x < 1)
+ fun_l14_n322(x)
+ else
+ fun_l14_n160(x)
+ end
+end
+
+def fun_l13_n428(x)
+ if (x < 1)
+ fun_l14_n974(x)
+ else
+ fun_l14_n139(x)
+ end
+end
+
+def fun_l13_n429(x)
+ if (x < 1)
+ fun_l14_n570(x)
+ else
+ fun_l14_n10(x)
+ end
+end
+
+def fun_l13_n430(x)
+ if (x < 1)
+ fun_l14_n199(x)
+ else
+ fun_l14_n829(x)
+ end
+end
+
+def fun_l13_n431(x)
+ if (x < 1)
+ fun_l14_n700(x)
+ else
+ fun_l14_n362(x)
+ end
+end
+
+def fun_l13_n432(x)
+ if (x < 1)
+ fun_l14_n925(x)
+ else
+ fun_l14_n365(x)
+ end
+end
+
+def fun_l13_n433(x)
+ if (x < 1)
+ fun_l14_n837(x)
+ else
+ fun_l14_n119(x)
+ end
+end
+
+def fun_l13_n434(x)
+ if (x < 1)
+ fun_l14_n355(x)
+ else
+ fun_l14_n374(x)
+ end
+end
+
+def fun_l13_n435(x)
+ if (x < 1)
+ fun_l14_n126(x)
+ else
+ fun_l14_n568(x)
+ end
+end
+
+def fun_l13_n436(x)
+ if (x < 1)
+ fun_l14_n468(x)
+ else
+ fun_l14_n299(x)
+ end
+end
+
+def fun_l13_n437(x)
+ if (x < 1)
+ fun_l14_n667(x)
+ else
+ fun_l14_n795(x)
+ end
+end
+
+def fun_l13_n438(x)
+ if (x < 1)
+ fun_l14_n989(x)
+ else
+ fun_l14_n484(x)
+ end
+end
+
+def fun_l13_n439(x)
+ if (x < 1)
+ fun_l14_n109(x)
+ else
+ fun_l14_n534(x)
+ end
+end
+
+def fun_l13_n440(x)
+ if (x < 1)
+ fun_l14_n999(x)
+ else
+ fun_l14_n69(x)
+ end
+end
+
+def fun_l13_n441(x)
+ if (x < 1)
+ fun_l14_n616(x)
+ else
+ fun_l14_n794(x)
+ end
+end
+
+def fun_l13_n442(x)
+ if (x < 1)
+ fun_l14_n719(x)
+ else
+ fun_l14_n967(x)
+ end
+end
+
+def fun_l13_n443(x)
+ if (x < 1)
+ fun_l14_n279(x)
+ else
+ fun_l14_n240(x)
+ end
+end
+
+def fun_l13_n444(x)
+ if (x < 1)
+ fun_l14_n660(x)
+ else
+ fun_l14_n146(x)
+ end
+end
+
+def fun_l13_n445(x)
+ if (x < 1)
+ fun_l14_n164(x)
+ else
+ fun_l14_n903(x)
+ end
+end
+
+def fun_l13_n446(x)
+ if (x < 1)
+ fun_l14_n474(x)
+ else
+ fun_l14_n137(x)
+ end
+end
+
+def fun_l13_n447(x)
+ if (x < 1)
+ fun_l14_n198(x)
+ else
+ fun_l14_n66(x)
+ end
+end
+
+def fun_l13_n448(x)
+ if (x < 1)
+ fun_l14_n948(x)
+ else
+ fun_l14_n682(x)
+ end
+end
+
+def fun_l13_n449(x)
+ if (x < 1)
+ fun_l14_n545(x)
+ else
+ fun_l14_n928(x)
+ end
+end
+
+def fun_l13_n450(x)
+ if (x < 1)
+ fun_l14_n822(x)
+ else
+ fun_l14_n846(x)
+ end
+end
+
+def fun_l13_n451(x)
+ if (x < 1)
+ fun_l14_n514(x)
+ else
+ fun_l14_n54(x)
+ end
+end
+
+def fun_l13_n452(x)
+ if (x < 1)
+ fun_l14_n539(x)
+ else
+ fun_l14_n199(x)
+ end
+end
+
+def fun_l13_n453(x)
+ if (x < 1)
+ fun_l14_n917(x)
+ else
+ fun_l14_n173(x)
+ end
+end
+
+def fun_l13_n454(x)
+ if (x < 1)
+ fun_l14_n924(x)
+ else
+ fun_l14_n51(x)
+ end
+end
+
+def fun_l13_n455(x)
+ if (x < 1)
+ fun_l14_n675(x)
+ else
+ fun_l14_n139(x)
+ end
+end
+
+def fun_l13_n456(x)
+ if (x < 1)
+ fun_l14_n335(x)
+ else
+ fun_l14_n138(x)
+ end
+end
+
+def fun_l13_n457(x)
+ if (x < 1)
+ fun_l14_n112(x)
+ else
+ fun_l14_n707(x)
+ end
+end
+
+def fun_l13_n458(x)
+ if (x < 1)
+ fun_l14_n784(x)
+ else
+ fun_l14_n278(x)
+ end
+end
+
+def fun_l13_n459(x)
+ if (x < 1)
+ fun_l14_n165(x)
+ else
+ fun_l14_n985(x)
+ end
+end
+
+def fun_l13_n460(x)
+ if (x < 1)
+ fun_l14_n843(x)
+ else
+ fun_l14_n262(x)
+ end
+end
+
+def fun_l13_n461(x)
+ if (x < 1)
+ fun_l14_n492(x)
+ else
+ fun_l14_n21(x)
+ end
+end
+
+def fun_l13_n462(x)
+ if (x < 1)
+ fun_l14_n864(x)
+ else
+ fun_l14_n248(x)
+ end
+end
+
+def fun_l13_n463(x)
+ if (x < 1)
+ fun_l14_n940(x)
+ else
+ fun_l14_n713(x)
+ end
+end
+
+def fun_l13_n464(x)
+ if (x < 1)
+ fun_l14_n8(x)
+ else
+ fun_l14_n771(x)
+ end
+end
+
+def fun_l13_n465(x)
+ if (x < 1)
+ fun_l14_n83(x)
+ else
+ fun_l14_n663(x)
+ end
+end
+
+def fun_l13_n466(x)
+ if (x < 1)
+ fun_l14_n411(x)
+ else
+ fun_l14_n570(x)
+ end
+end
+
+def fun_l13_n467(x)
+ if (x < 1)
+ fun_l14_n464(x)
+ else
+ fun_l14_n497(x)
+ end
+end
+
+def fun_l13_n468(x)
+ if (x < 1)
+ fun_l14_n49(x)
+ else
+ fun_l14_n153(x)
+ end
+end
+
+def fun_l13_n469(x)
+ if (x < 1)
+ fun_l14_n33(x)
+ else
+ fun_l14_n562(x)
+ end
+end
+
+def fun_l13_n470(x)
+ if (x < 1)
+ fun_l14_n207(x)
+ else
+ fun_l14_n328(x)
+ end
+end
+
+def fun_l13_n471(x)
+ if (x < 1)
+ fun_l14_n356(x)
+ else
+ fun_l14_n834(x)
+ end
+end
+
+def fun_l13_n472(x)
+ if (x < 1)
+ fun_l14_n46(x)
+ else
+ fun_l14_n842(x)
+ end
+end
+
+def fun_l13_n473(x)
+ if (x < 1)
+ fun_l14_n14(x)
+ else
+ fun_l14_n488(x)
+ end
+end
+
+def fun_l13_n474(x)
+ if (x < 1)
+ fun_l14_n307(x)
+ else
+ fun_l14_n647(x)
+ end
+end
+
+def fun_l13_n475(x)
+ if (x < 1)
+ fun_l14_n474(x)
+ else
+ fun_l14_n369(x)
+ end
+end
+
+def fun_l13_n476(x)
+ if (x < 1)
+ fun_l14_n471(x)
+ else
+ fun_l14_n956(x)
+ end
+end
+
+def fun_l13_n477(x)
+ if (x < 1)
+ fun_l14_n368(x)
+ else
+ fun_l14_n478(x)
+ end
+end
+
+def fun_l13_n478(x)
+ if (x < 1)
+ fun_l14_n377(x)
+ else
+ fun_l14_n675(x)
+ end
+end
+
+def fun_l13_n479(x)
+ if (x < 1)
+ fun_l14_n370(x)
+ else
+ fun_l14_n819(x)
+ end
+end
+
+def fun_l13_n480(x)
+ if (x < 1)
+ fun_l14_n459(x)
+ else
+ fun_l14_n59(x)
+ end
+end
+
+def fun_l13_n481(x)
+ if (x < 1)
+ fun_l14_n200(x)
+ else
+ fun_l14_n681(x)
+ end
+end
+
+def fun_l13_n482(x)
+ if (x < 1)
+ fun_l14_n893(x)
+ else
+ fun_l14_n518(x)
+ end
+end
+
+def fun_l13_n483(x)
+ if (x < 1)
+ fun_l14_n130(x)
+ else
+ fun_l14_n902(x)
+ end
+end
+
+def fun_l13_n484(x)
+ if (x < 1)
+ fun_l14_n598(x)
+ else
+ fun_l14_n533(x)
+ end
+end
+
+def fun_l13_n485(x)
+ if (x < 1)
+ fun_l14_n254(x)
+ else
+ fun_l14_n294(x)
+ end
+end
+
+def fun_l13_n486(x)
+ if (x < 1)
+ fun_l14_n608(x)
+ else
+ fun_l14_n858(x)
+ end
+end
+
+def fun_l13_n487(x)
+ if (x < 1)
+ fun_l14_n82(x)
+ else
+ fun_l14_n379(x)
+ end
+end
+
+def fun_l13_n488(x)
+ if (x < 1)
+ fun_l14_n605(x)
+ else
+ fun_l14_n530(x)
+ end
+end
+
+def fun_l13_n489(x)
+ if (x < 1)
+ fun_l14_n572(x)
+ else
+ fun_l14_n199(x)
+ end
+end
+
+def fun_l13_n490(x)
+ if (x < 1)
+ fun_l14_n3(x)
+ else
+ fun_l14_n103(x)
+ end
+end
+
+def fun_l13_n491(x)
+ if (x < 1)
+ fun_l14_n922(x)
+ else
+ fun_l14_n372(x)
+ end
+end
+
+def fun_l13_n492(x)
+ if (x < 1)
+ fun_l14_n306(x)
+ else
+ fun_l14_n378(x)
+ end
+end
+
+def fun_l13_n493(x)
+ if (x < 1)
+ fun_l14_n980(x)
+ else
+ fun_l14_n617(x)
+ end
+end
+
+def fun_l13_n494(x)
+ if (x < 1)
+ fun_l14_n127(x)
+ else
+ fun_l14_n348(x)
+ end
+end
+
+def fun_l13_n495(x)
+ if (x < 1)
+ fun_l14_n631(x)
+ else
+ fun_l14_n281(x)
+ end
+end
+
+def fun_l13_n496(x)
+ if (x < 1)
+ fun_l14_n552(x)
+ else
+ fun_l14_n493(x)
+ end
+end
+
+def fun_l13_n497(x)
+ if (x < 1)
+ fun_l14_n342(x)
+ else
+ fun_l14_n931(x)
+ end
+end
+
+def fun_l13_n498(x)
+ if (x < 1)
+ fun_l14_n297(x)
+ else
+ fun_l14_n512(x)
+ end
+end
+
+def fun_l13_n499(x)
+ if (x < 1)
+ fun_l14_n950(x)
+ else
+ fun_l14_n952(x)
+ end
+end
+
+def fun_l13_n500(x)
+ if (x < 1)
+ fun_l14_n355(x)
+ else
+ fun_l14_n383(x)
+ end
+end
+
+def fun_l13_n501(x)
+ if (x < 1)
+ fun_l14_n278(x)
+ else
+ fun_l14_n442(x)
+ end
+end
+
+def fun_l13_n502(x)
+ if (x < 1)
+ fun_l14_n16(x)
+ else
+ fun_l14_n150(x)
+ end
+end
+
+def fun_l13_n503(x)
+ if (x < 1)
+ fun_l14_n399(x)
+ else
+ fun_l14_n989(x)
+ end
+end
+
+def fun_l13_n504(x)
+ if (x < 1)
+ fun_l14_n289(x)
+ else
+ fun_l14_n925(x)
+ end
+end
+
+def fun_l13_n505(x)
+ if (x < 1)
+ fun_l14_n743(x)
+ else
+ fun_l14_n784(x)
+ end
+end
+
+def fun_l13_n506(x)
+ if (x < 1)
+ fun_l14_n916(x)
+ else
+ fun_l14_n111(x)
+ end
+end
+
+def fun_l13_n507(x)
+ if (x < 1)
+ fun_l14_n912(x)
+ else
+ fun_l14_n448(x)
+ end
+end
+
+def fun_l13_n508(x)
+ if (x < 1)
+ fun_l14_n10(x)
+ else
+ fun_l14_n451(x)
+ end
+end
+
+def fun_l13_n509(x)
+ if (x < 1)
+ fun_l14_n15(x)
+ else
+ fun_l14_n697(x)
+ end
+end
+
+def fun_l13_n510(x)
+ if (x < 1)
+ fun_l14_n565(x)
+ else
+ fun_l14_n511(x)
+ end
+end
+
+def fun_l13_n511(x)
+ if (x < 1)
+ fun_l14_n843(x)
+ else
+ fun_l14_n272(x)
+ end
+end
+
+def fun_l13_n512(x)
+ if (x < 1)
+ fun_l14_n70(x)
+ else
+ fun_l14_n333(x)
+ end
+end
+
+def fun_l13_n513(x)
+ if (x < 1)
+ fun_l14_n100(x)
+ else
+ fun_l14_n399(x)
+ end
+end
+
+def fun_l13_n514(x)
+ if (x < 1)
+ fun_l14_n678(x)
+ else
+ fun_l14_n247(x)
+ end
+end
+
+def fun_l13_n515(x)
+ if (x < 1)
+ fun_l14_n823(x)
+ else
+ fun_l14_n371(x)
+ end
+end
+
+def fun_l13_n516(x)
+ if (x < 1)
+ fun_l14_n994(x)
+ else
+ fun_l14_n322(x)
+ end
+end
+
+def fun_l13_n517(x)
+ if (x < 1)
+ fun_l14_n399(x)
+ else
+ fun_l14_n567(x)
+ end
+end
+
+def fun_l13_n518(x)
+ if (x < 1)
+ fun_l14_n898(x)
+ else
+ fun_l14_n59(x)
+ end
+end
+
+def fun_l13_n519(x)
+ if (x < 1)
+ fun_l14_n33(x)
+ else
+ fun_l14_n640(x)
+ end
+end
+
+def fun_l13_n520(x)
+ if (x < 1)
+ fun_l14_n475(x)
+ else
+ fun_l14_n67(x)
+ end
+end
+
+def fun_l13_n521(x)
+ if (x < 1)
+ fun_l14_n896(x)
+ else
+ fun_l14_n312(x)
+ end
+end
+
+def fun_l13_n522(x)
+ if (x < 1)
+ fun_l14_n454(x)
+ else
+ fun_l14_n520(x)
+ end
+end
+
+def fun_l13_n523(x)
+ if (x < 1)
+ fun_l14_n334(x)
+ else
+ fun_l14_n879(x)
+ end
+end
+
+def fun_l13_n524(x)
+ if (x < 1)
+ fun_l14_n267(x)
+ else
+ fun_l14_n526(x)
+ end
+end
+
+def fun_l13_n525(x)
+ if (x < 1)
+ fun_l14_n552(x)
+ else
+ fun_l14_n103(x)
+ end
+end
+
+def fun_l13_n526(x)
+ if (x < 1)
+ fun_l14_n224(x)
+ else
+ fun_l14_n211(x)
+ end
+end
+
+def fun_l13_n527(x)
+ if (x < 1)
+ fun_l14_n113(x)
+ else
+ fun_l14_n193(x)
+ end
+end
+
+def fun_l13_n528(x)
+ if (x < 1)
+ fun_l14_n389(x)
+ else
+ fun_l14_n332(x)
+ end
+end
+
+def fun_l13_n529(x)
+ if (x < 1)
+ fun_l14_n881(x)
+ else
+ fun_l14_n655(x)
+ end
+end
+
+def fun_l13_n530(x)
+ if (x < 1)
+ fun_l14_n857(x)
+ else
+ fun_l14_n588(x)
+ end
+end
+
+def fun_l13_n531(x)
+ if (x < 1)
+ fun_l14_n70(x)
+ else
+ fun_l14_n232(x)
+ end
+end
+
+def fun_l13_n532(x)
+ if (x < 1)
+ fun_l14_n617(x)
+ else
+ fun_l14_n477(x)
+ end
+end
+
+def fun_l13_n533(x)
+ if (x < 1)
+ fun_l14_n655(x)
+ else
+ fun_l14_n801(x)
+ end
+end
+
+def fun_l13_n534(x)
+ if (x < 1)
+ fun_l14_n665(x)
+ else
+ fun_l14_n22(x)
+ end
+end
+
+def fun_l13_n535(x)
+ if (x < 1)
+ fun_l14_n314(x)
+ else
+ fun_l14_n924(x)
+ end
+end
+
+def fun_l13_n536(x)
+ if (x < 1)
+ fun_l14_n619(x)
+ else
+ fun_l14_n455(x)
+ end
+end
+
+def fun_l13_n537(x)
+ if (x < 1)
+ fun_l14_n183(x)
+ else
+ fun_l14_n767(x)
+ end
+end
+
+def fun_l13_n538(x)
+ if (x < 1)
+ fun_l14_n862(x)
+ else
+ fun_l14_n352(x)
+ end
+end
+
+def fun_l13_n539(x)
+ if (x < 1)
+ fun_l14_n540(x)
+ else
+ fun_l14_n813(x)
+ end
+end
+
+def fun_l13_n540(x)
+ if (x < 1)
+ fun_l14_n429(x)
+ else
+ fun_l14_n515(x)
+ end
+end
+
+def fun_l13_n541(x)
+ if (x < 1)
+ fun_l14_n294(x)
+ else
+ fun_l14_n341(x)
+ end
+end
+
+def fun_l13_n542(x)
+ if (x < 1)
+ fun_l14_n910(x)
+ else
+ fun_l14_n882(x)
+ end
+end
+
+def fun_l13_n543(x)
+ if (x < 1)
+ fun_l14_n971(x)
+ else
+ fun_l14_n19(x)
+ end
+end
+
+def fun_l13_n544(x)
+ if (x < 1)
+ fun_l14_n344(x)
+ else
+ fun_l14_n419(x)
+ end
+end
+
+def fun_l13_n545(x)
+ if (x < 1)
+ fun_l14_n410(x)
+ else
+ fun_l14_n996(x)
+ end
+end
+
+def fun_l13_n546(x)
+ if (x < 1)
+ fun_l14_n857(x)
+ else
+ fun_l14_n431(x)
+ end
+end
+
+def fun_l13_n547(x)
+ if (x < 1)
+ fun_l14_n548(x)
+ else
+ fun_l14_n934(x)
+ end
+end
+
+def fun_l13_n548(x)
+ if (x < 1)
+ fun_l14_n420(x)
+ else
+ fun_l14_n506(x)
+ end
+end
+
+def fun_l13_n549(x)
+ if (x < 1)
+ fun_l14_n992(x)
+ else
+ fun_l14_n213(x)
+ end
+end
+
+def fun_l13_n550(x)
+ if (x < 1)
+ fun_l14_n754(x)
+ else
+ fun_l14_n666(x)
+ end
+end
+
+def fun_l13_n551(x)
+ if (x < 1)
+ fun_l14_n412(x)
+ else
+ fun_l14_n908(x)
+ end
+end
+
+def fun_l13_n552(x)
+ if (x < 1)
+ fun_l14_n708(x)
+ else
+ fun_l14_n308(x)
+ end
+end
+
+def fun_l13_n553(x)
+ if (x < 1)
+ fun_l14_n797(x)
+ else
+ fun_l14_n622(x)
+ end
+end
+
+def fun_l13_n554(x)
+ if (x < 1)
+ fun_l14_n26(x)
+ else
+ fun_l14_n102(x)
+ end
+end
+
+def fun_l13_n555(x)
+ if (x < 1)
+ fun_l14_n614(x)
+ else
+ fun_l14_n110(x)
+ end
+end
+
+def fun_l13_n556(x)
+ if (x < 1)
+ fun_l14_n368(x)
+ else
+ fun_l14_n718(x)
+ end
+end
+
+def fun_l13_n557(x)
+ if (x < 1)
+ fun_l14_n782(x)
+ else
+ fun_l14_n659(x)
+ end
+end
+
+def fun_l13_n558(x)
+ if (x < 1)
+ fun_l14_n544(x)
+ else
+ fun_l14_n507(x)
+ end
+end
+
+def fun_l13_n559(x)
+ if (x < 1)
+ fun_l14_n39(x)
+ else
+ fun_l14_n97(x)
+ end
+end
+
+def fun_l13_n560(x)
+ if (x < 1)
+ fun_l14_n390(x)
+ else
+ fun_l14_n93(x)
+ end
+end
+
+def fun_l13_n561(x)
+ if (x < 1)
+ fun_l14_n28(x)
+ else
+ fun_l14_n267(x)
+ end
+end
+
+def fun_l13_n562(x)
+ if (x < 1)
+ fun_l14_n10(x)
+ else
+ fun_l14_n990(x)
+ end
+end
+
+def fun_l13_n563(x)
+ if (x < 1)
+ fun_l14_n428(x)
+ else
+ fun_l14_n878(x)
+ end
+end
+
+def fun_l13_n564(x)
+ if (x < 1)
+ fun_l14_n587(x)
+ else
+ fun_l14_n724(x)
+ end
+end
+
+def fun_l13_n565(x)
+ if (x < 1)
+ fun_l14_n524(x)
+ else
+ fun_l14_n87(x)
+ end
+end
+
+def fun_l13_n566(x)
+ if (x < 1)
+ fun_l14_n213(x)
+ else
+ fun_l14_n718(x)
+ end
+end
+
+def fun_l13_n567(x)
+ if (x < 1)
+ fun_l14_n821(x)
+ else
+ fun_l14_n478(x)
+ end
+end
+
+def fun_l13_n568(x)
+ if (x < 1)
+ fun_l14_n580(x)
+ else
+ fun_l14_n731(x)
+ end
+end
+
+def fun_l13_n569(x)
+ if (x < 1)
+ fun_l14_n673(x)
+ else
+ fun_l14_n780(x)
+ end
+end
+
+def fun_l13_n570(x)
+ if (x < 1)
+ fun_l14_n791(x)
+ else
+ fun_l14_n691(x)
+ end
+end
+
+def fun_l13_n571(x)
+ if (x < 1)
+ fun_l14_n192(x)
+ else
+ fun_l14_n712(x)
+ end
+end
+
+def fun_l13_n572(x)
+ if (x < 1)
+ fun_l14_n201(x)
+ else
+ fun_l14_n732(x)
+ end
+end
+
+def fun_l13_n573(x)
+ if (x < 1)
+ fun_l14_n180(x)
+ else
+ fun_l14_n260(x)
+ end
+end
+
+def fun_l13_n574(x)
+ if (x < 1)
+ fun_l14_n609(x)
+ else
+ fun_l14_n110(x)
+ end
+end
+
+def fun_l13_n575(x)
+ if (x < 1)
+ fun_l14_n993(x)
+ else
+ fun_l14_n510(x)
+ end
+end
+
+def fun_l13_n576(x)
+ if (x < 1)
+ fun_l14_n318(x)
+ else
+ fun_l14_n915(x)
+ end
+end
+
+def fun_l13_n577(x)
+ if (x < 1)
+ fun_l14_n635(x)
+ else
+ fun_l14_n21(x)
+ end
+end
+
+def fun_l13_n578(x)
+ if (x < 1)
+ fun_l14_n330(x)
+ else
+ fun_l14_n860(x)
+ end
+end
+
+def fun_l13_n579(x)
+ if (x < 1)
+ fun_l14_n24(x)
+ else
+ fun_l14_n87(x)
+ end
+end
+
+def fun_l13_n580(x)
+ if (x < 1)
+ fun_l14_n404(x)
+ else
+ fun_l14_n530(x)
+ end
+end
+
+def fun_l13_n581(x)
+ if (x < 1)
+ fun_l14_n831(x)
+ else
+ fun_l14_n384(x)
+ end
+end
+
+def fun_l13_n582(x)
+ if (x < 1)
+ fun_l14_n272(x)
+ else
+ fun_l14_n438(x)
+ end
+end
+
+def fun_l13_n583(x)
+ if (x < 1)
+ fun_l14_n297(x)
+ else
+ fun_l14_n414(x)
+ end
+end
+
+def fun_l13_n584(x)
+ if (x < 1)
+ fun_l14_n38(x)
+ else
+ fun_l14_n676(x)
+ end
+end
+
+def fun_l13_n585(x)
+ if (x < 1)
+ fun_l14_n104(x)
+ else
+ fun_l14_n566(x)
+ end
+end
+
+def fun_l13_n586(x)
+ if (x < 1)
+ fun_l14_n322(x)
+ else
+ fun_l14_n601(x)
+ end
+end
+
+def fun_l13_n587(x)
+ if (x < 1)
+ fun_l14_n20(x)
+ else
+ fun_l14_n242(x)
+ end
+end
+
+def fun_l13_n588(x)
+ if (x < 1)
+ fun_l14_n291(x)
+ else
+ fun_l14_n744(x)
+ end
+end
+
+def fun_l13_n589(x)
+ if (x < 1)
+ fun_l14_n702(x)
+ else
+ fun_l14_n456(x)
+ end
+end
+
+def fun_l13_n590(x)
+ if (x < 1)
+ fun_l14_n39(x)
+ else
+ fun_l14_n493(x)
+ end
+end
+
+def fun_l13_n591(x)
+ if (x < 1)
+ fun_l14_n51(x)
+ else
+ fun_l14_n193(x)
+ end
+end
+
+def fun_l13_n592(x)
+ if (x < 1)
+ fun_l14_n512(x)
+ else
+ fun_l14_n382(x)
+ end
+end
+
+def fun_l13_n593(x)
+ if (x < 1)
+ fun_l14_n550(x)
+ else
+ fun_l14_n711(x)
+ end
+end
+
+def fun_l13_n594(x)
+ if (x < 1)
+ fun_l14_n586(x)
+ else
+ fun_l14_n130(x)
+ end
+end
+
+def fun_l13_n595(x)
+ if (x < 1)
+ fun_l14_n348(x)
+ else
+ fun_l14_n214(x)
+ end
+end
+
+def fun_l13_n596(x)
+ if (x < 1)
+ fun_l14_n193(x)
+ else
+ fun_l14_n490(x)
+ end
+end
+
+def fun_l13_n597(x)
+ if (x < 1)
+ fun_l14_n736(x)
+ else
+ fun_l14_n824(x)
+ end
+end
+
+def fun_l13_n598(x)
+ if (x < 1)
+ fun_l14_n555(x)
+ else
+ fun_l14_n546(x)
+ end
+end
+
+def fun_l13_n599(x)
+ if (x < 1)
+ fun_l14_n244(x)
+ else
+ fun_l14_n903(x)
+ end
+end
+
+def fun_l13_n600(x)
+ if (x < 1)
+ fun_l14_n786(x)
+ else
+ fun_l14_n817(x)
+ end
+end
+
+def fun_l13_n601(x)
+ if (x < 1)
+ fun_l14_n991(x)
+ else
+ fun_l14_n691(x)
+ end
+end
+
+def fun_l13_n602(x)
+ if (x < 1)
+ fun_l14_n369(x)
+ else
+ fun_l14_n85(x)
+ end
+end
+
+def fun_l13_n603(x)
+ if (x < 1)
+ fun_l14_n232(x)
+ else
+ fun_l14_n287(x)
+ end
+end
+
+def fun_l13_n604(x)
+ if (x < 1)
+ fun_l14_n397(x)
+ else
+ fun_l14_n59(x)
+ end
+end
+
+def fun_l13_n605(x)
+ if (x < 1)
+ fun_l14_n394(x)
+ else
+ fun_l14_n297(x)
+ end
+end
+
+def fun_l13_n606(x)
+ if (x < 1)
+ fun_l14_n676(x)
+ else
+ fun_l14_n444(x)
+ end
+end
+
+def fun_l13_n607(x)
+ if (x < 1)
+ fun_l14_n894(x)
+ else
+ fun_l14_n147(x)
+ end
+end
+
+def fun_l13_n608(x)
+ if (x < 1)
+ fun_l14_n593(x)
+ else
+ fun_l14_n880(x)
+ end
+end
+
+def fun_l13_n609(x)
+ if (x < 1)
+ fun_l14_n306(x)
+ else
+ fun_l14_n610(x)
+ end
+end
+
+def fun_l13_n610(x)
+ if (x < 1)
+ fun_l14_n884(x)
+ else
+ fun_l14_n202(x)
+ end
+end
+
+def fun_l13_n611(x)
+ if (x < 1)
+ fun_l14_n763(x)
+ else
+ fun_l14_n592(x)
+ end
+end
+
+def fun_l13_n612(x)
+ if (x < 1)
+ fun_l14_n477(x)
+ else
+ fun_l14_n614(x)
+ end
+end
+
+def fun_l13_n613(x)
+ if (x < 1)
+ fun_l14_n372(x)
+ else
+ fun_l14_n330(x)
+ end
+end
+
+def fun_l13_n614(x)
+ if (x < 1)
+ fun_l14_n767(x)
+ else
+ fun_l14_n277(x)
+ end
+end
+
+def fun_l13_n615(x)
+ if (x < 1)
+ fun_l14_n530(x)
+ else
+ fun_l14_n24(x)
+ end
+end
+
+def fun_l13_n616(x)
+ if (x < 1)
+ fun_l14_n657(x)
+ else
+ fun_l14_n709(x)
+ end
+end
+
+def fun_l13_n617(x)
+ if (x < 1)
+ fun_l14_n559(x)
+ else
+ fun_l14_n125(x)
+ end
+end
+
+def fun_l13_n618(x)
+ if (x < 1)
+ fun_l14_n855(x)
+ else
+ fun_l14_n353(x)
+ end
+end
+
+def fun_l13_n619(x)
+ if (x < 1)
+ fun_l14_n635(x)
+ else
+ fun_l14_n907(x)
+ end
+end
+
+def fun_l13_n620(x)
+ if (x < 1)
+ fun_l14_n229(x)
+ else
+ fun_l14_n7(x)
+ end
+end
+
+def fun_l13_n621(x)
+ if (x < 1)
+ fun_l14_n568(x)
+ else
+ fun_l14_n393(x)
+ end
+end
+
+def fun_l13_n622(x)
+ if (x < 1)
+ fun_l14_n153(x)
+ else
+ fun_l14_n641(x)
+ end
+end
+
+def fun_l13_n623(x)
+ if (x < 1)
+ fun_l14_n249(x)
+ else
+ fun_l14_n139(x)
+ end
+end
+
+def fun_l13_n624(x)
+ if (x < 1)
+ fun_l14_n961(x)
+ else
+ fun_l14_n897(x)
+ end
+end
+
+def fun_l13_n625(x)
+ if (x < 1)
+ fun_l14_n535(x)
+ else
+ fun_l14_n252(x)
+ end
+end
+
+def fun_l13_n626(x)
+ if (x < 1)
+ fun_l14_n832(x)
+ else
+ fun_l14_n995(x)
+ end
+end
+
+def fun_l13_n627(x)
+ if (x < 1)
+ fun_l14_n896(x)
+ else
+ fun_l14_n173(x)
+ end
+end
+
+def fun_l13_n628(x)
+ if (x < 1)
+ fun_l14_n939(x)
+ else
+ fun_l14_n852(x)
+ end
+end
+
+def fun_l13_n629(x)
+ if (x < 1)
+ fun_l14_n424(x)
+ else
+ fun_l14_n161(x)
+ end
+end
+
+def fun_l13_n630(x)
+ if (x < 1)
+ fun_l14_n822(x)
+ else
+ fun_l14_n523(x)
+ end
+end
+
+def fun_l13_n631(x)
+ if (x < 1)
+ fun_l14_n697(x)
+ else
+ fun_l14_n939(x)
+ end
+end
+
+def fun_l13_n632(x)
+ if (x < 1)
+ fun_l14_n831(x)
+ else
+ fun_l14_n722(x)
+ end
+end
+
+def fun_l13_n633(x)
+ if (x < 1)
+ fun_l14_n837(x)
+ else
+ fun_l14_n994(x)
+ end
+end
+
+def fun_l13_n634(x)
+ if (x < 1)
+ fun_l14_n568(x)
+ else
+ fun_l14_n636(x)
+ end
+end
+
+def fun_l13_n635(x)
+ if (x < 1)
+ fun_l14_n573(x)
+ else
+ fun_l14_n156(x)
+ end
+end
+
+def fun_l13_n636(x)
+ if (x < 1)
+ fun_l14_n682(x)
+ else
+ fun_l14_n999(x)
+ end
+end
+
+def fun_l13_n637(x)
+ if (x < 1)
+ fun_l14_n648(x)
+ else
+ fun_l14_n567(x)
+ end
+end
+
+def fun_l13_n638(x)
+ if (x < 1)
+ fun_l14_n395(x)
+ else
+ fun_l14_n837(x)
+ end
+end
+
+def fun_l13_n639(x)
+ if (x < 1)
+ fun_l14_n294(x)
+ else
+ fun_l14_n508(x)
+ end
+end
+
+def fun_l13_n640(x)
+ if (x < 1)
+ fun_l14_n530(x)
+ else
+ fun_l14_n542(x)
+ end
+end
+
+def fun_l13_n641(x)
+ if (x < 1)
+ fun_l14_n227(x)
+ else
+ fun_l14_n939(x)
+ end
+end
+
+def fun_l13_n642(x)
+ if (x < 1)
+ fun_l14_n415(x)
+ else
+ fun_l14_n79(x)
+ end
+end
+
+def fun_l13_n643(x)
+ if (x < 1)
+ fun_l14_n354(x)
+ else
+ fun_l14_n606(x)
+ end
+end
+
+def fun_l13_n644(x)
+ if (x < 1)
+ fun_l14_n270(x)
+ else
+ fun_l14_n644(x)
+ end
+end
+
+def fun_l13_n645(x)
+ if (x < 1)
+ fun_l14_n345(x)
+ else
+ fun_l14_n299(x)
+ end
+end
+
+def fun_l13_n646(x)
+ if (x < 1)
+ fun_l14_n384(x)
+ else
+ fun_l14_n97(x)
+ end
+end
+
+def fun_l13_n647(x)
+ if (x < 1)
+ fun_l14_n86(x)
+ else
+ fun_l14_n103(x)
+ end
+end
+
+def fun_l13_n648(x)
+ if (x < 1)
+ fun_l14_n765(x)
+ else
+ fun_l14_n498(x)
+ end
+end
+
+def fun_l13_n649(x)
+ if (x < 1)
+ fun_l14_n135(x)
+ else
+ fun_l14_n993(x)
+ end
+end
+
+def fun_l13_n650(x)
+ if (x < 1)
+ fun_l14_n837(x)
+ else
+ fun_l14_n576(x)
+ end
+end
+
+def fun_l13_n651(x)
+ if (x < 1)
+ fun_l14_n75(x)
+ else
+ fun_l14_n351(x)
+ end
+end
+
+def fun_l13_n652(x)
+ if (x < 1)
+ fun_l14_n932(x)
+ else
+ fun_l14_n646(x)
+ end
+end
+
+def fun_l13_n653(x)
+ if (x < 1)
+ fun_l14_n908(x)
+ else
+ fun_l14_n384(x)
+ end
+end
+
+def fun_l13_n654(x)
+ if (x < 1)
+ fun_l14_n540(x)
+ else
+ fun_l14_n946(x)
+ end
+end
+
+def fun_l13_n655(x)
+ if (x < 1)
+ fun_l14_n686(x)
+ else
+ fun_l14_n926(x)
+ end
+end
+
+def fun_l13_n656(x)
+ if (x < 1)
+ fun_l14_n567(x)
+ else
+ fun_l14_n815(x)
+ end
+end
+
+def fun_l13_n657(x)
+ if (x < 1)
+ fun_l14_n101(x)
+ else
+ fun_l14_n960(x)
+ end
+end
+
+def fun_l13_n658(x)
+ if (x < 1)
+ fun_l14_n956(x)
+ else
+ fun_l14_n980(x)
+ end
+end
+
+def fun_l13_n659(x)
+ if (x < 1)
+ fun_l14_n196(x)
+ else
+ fun_l14_n632(x)
+ end
+end
+
+def fun_l13_n660(x)
+ if (x < 1)
+ fun_l14_n83(x)
+ else
+ fun_l14_n288(x)
+ end
+end
+
+def fun_l13_n661(x)
+ if (x < 1)
+ fun_l14_n907(x)
+ else
+ fun_l14_n719(x)
+ end
+end
+
+def fun_l13_n662(x)
+ if (x < 1)
+ fun_l14_n922(x)
+ else
+ fun_l14_n186(x)
+ end
+end
+
+def fun_l13_n663(x)
+ if (x < 1)
+ fun_l14_n439(x)
+ else
+ fun_l14_n890(x)
+ end
+end
+
+def fun_l13_n664(x)
+ if (x < 1)
+ fun_l14_n310(x)
+ else
+ fun_l14_n534(x)
+ end
+end
+
+def fun_l13_n665(x)
+ if (x < 1)
+ fun_l14_n584(x)
+ else
+ fun_l14_n322(x)
+ end
+end
+
+def fun_l13_n666(x)
+ if (x < 1)
+ fun_l14_n385(x)
+ else
+ fun_l14_n466(x)
+ end
+end
+
+def fun_l13_n667(x)
+ if (x < 1)
+ fun_l14_n387(x)
+ else
+ fun_l14_n284(x)
+ end
+end
+
+def fun_l13_n668(x)
+ if (x < 1)
+ fun_l14_n834(x)
+ else
+ fun_l14_n446(x)
+ end
+end
+
+def fun_l13_n669(x)
+ if (x < 1)
+ fun_l14_n839(x)
+ else
+ fun_l14_n820(x)
+ end
+end
+
+def fun_l13_n670(x)
+ if (x < 1)
+ fun_l14_n666(x)
+ else
+ fun_l14_n690(x)
+ end
+end
+
+def fun_l13_n671(x)
+ if (x < 1)
+ fun_l14_n640(x)
+ else
+ fun_l14_n83(x)
+ end
+end
+
+def fun_l13_n672(x)
+ if (x < 1)
+ fun_l14_n663(x)
+ else
+ fun_l14_n332(x)
+ end
+end
+
+def fun_l13_n673(x)
+ if (x < 1)
+ fun_l14_n776(x)
+ else
+ fun_l14_n818(x)
+ end
+end
+
+def fun_l13_n674(x)
+ if (x < 1)
+ fun_l14_n82(x)
+ else
+ fun_l14_n594(x)
+ end
+end
+
+def fun_l13_n675(x)
+ if (x < 1)
+ fun_l14_n491(x)
+ else
+ fun_l14_n0(x)
+ end
+end
+
+def fun_l13_n676(x)
+ if (x < 1)
+ fun_l14_n963(x)
+ else
+ fun_l14_n634(x)
+ end
+end
+
+def fun_l13_n677(x)
+ if (x < 1)
+ fun_l14_n716(x)
+ else
+ fun_l14_n99(x)
+ end
+end
+
+def fun_l13_n678(x)
+ if (x < 1)
+ fun_l14_n997(x)
+ else
+ fun_l14_n933(x)
+ end
+end
+
+def fun_l13_n679(x)
+ if (x < 1)
+ fun_l14_n171(x)
+ else
+ fun_l14_n356(x)
+ end
+end
+
+def fun_l13_n680(x)
+ if (x < 1)
+ fun_l14_n214(x)
+ else
+ fun_l14_n360(x)
+ end
+end
+
+def fun_l13_n681(x)
+ if (x < 1)
+ fun_l14_n758(x)
+ else
+ fun_l14_n185(x)
+ end
+end
+
+def fun_l13_n682(x)
+ if (x < 1)
+ fun_l14_n480(x)
+ else
+ fun_l14_n572(x)
+ end
+end
+
+def fun_l13_n683(x)
+ if (x < 1)
+ fun_l14_n595(x)
+ else
+ fun_l14_n534(x)
+ end
+end
+
+def fun_l13_n684(x)
+ if (x < 1)
+ fun_l14_n462(x)
+ else
+ fun_l14_n481(x)
+ end
+end
+
+def fun_l13_n685(x)
+ if (x < 1)
+ fun_l14_n946(x)
+ else
+ fun_l14_n726(x)
+ end
+end
+
+def fun_l13_n686(x)
+ if (x < 1)
+ fun_l14_n428(x)
+ else
+ fun_l14_n256(x)
+ end
+end
+
+def fun_l13_n687(x)
+ if (x < 1)
+ fun_l14_n562(x)
+ else
+ fun_l14_n290(x)
+ end
+end
+
+def fun_l13_n688(x)
+ if (x < 1)
+ fun_l14_n679(x)
+ else
+ fun_l14_n787(x)
+ end
+end
+
+def fun_l13_n689(x)
+ if (x < 1)
+ fun_l14_n972(x)
+ else
+ fun_l14_n809(x)
+ end
+end
+
+def fun_l13_n690(x)
+ if (x < 1)
+ fun_l14_n700(x)
+ else
+ fun_l14_n239(x)
+ end
+end
+
+def fun_l13_n691(x)
+ if (x < 1)
+ fun_l14_n525(x)
+ else
+ fun_l14_n251(x)
+ end
+end
+
+def fun_l13_n692(x)
+ if (x < 1)
+ fun_l14_n4(x)
+ else
+ fun_l14_n889(x)
+ end
+end
+
+def fun_l13_n693(x)
+ if (x < 1)
+ fun_l14_n362(x)
+ else
+ fun_l14_n495(x)
+ end
+end
+
+def fun_l13_n694(x)
+ if (x < 1)
+ fun_l14_n466(x)
+ else
+ fun_l14_n820(x)
+ end
+end
+
+def fun_l13_n695(x)
+ if (x < 1)
+ fun_l14_n244(x)
+ else
+ fun_l14_n233(x)
+ end
+end
+
+def fun_l13_n696(x)
+ if (x < 1)
+ fun_l14_n920(x)
+ else
+ fun_l14_n124(x)
+ end
+end
+
+def fun_l13_n697(x)
+ if (x < 1)
+ fun_l14_n926(x)
+ else
+ fun_l14_n417(x)
+ end
+end
+
+def fun_l13_n698(x)
+ if (x < 1)
+ fun_l14_n756(x)
+ else
+ fun_l14_n683(x)
+ end
+end
+
+def fun_l13_n699(x)
+ if (x < 1)
+ fun_l14_n487(x)
+ else
+ fun_l14_n191(x)
+ end
+end
+
+def fun_l13_n700(x)
+ if (x < 1)
+ fun_l14_n316(x)
+ else
+ fun_l14_n123(x)
+ end
+end
+
+def fun_l13_n701(x)
+ if (x < 1)
+ fun_l14_n851(x)
+ else
+ fun_l14_n695(x)
+ end
+end
+
+def fun_l13_n702(x)
+ if (x < 1)
+ fun_l14_n766(x)
+ else
+ fun_l14_n603(x)
+ end
+end
+
+def fun_l13_n703(x)
+ if (x < 1)
+ fun_l14_n689(x)
+ else
+ fun_l14_n524(x)
+ end
+end
+
+def fun_l13_n704(x)
+ if (x < 1)
+ fun_l14_n23(x)
+ else
+ fun_l14_n866(x)
+ end
+end
+
+def fun_l13_n705(x)
+ if (x < 1)
+ fun_l14_n62(x)
+ else
+ fun_l14_n926(x)
+ end
+end
+
+def fun_l13_n706(x)
+ if (x < 1)
+ fun_l14_n53(x)
+ else
+ fun_l14_n567(x)
+ end
+end
+
+def fun_l13_n707(x)
+ if (x < 1)
+ fun_l14_n756(x)
+ else
+ fun_l14_n595(x)
+ end
+end
+
+def fun_l13_n708(x)
+ if (x < 1)
+ fun_l14_n495(x)
+ else
+ fun_l14_n698(x)
+ end
+end
+
+def fun_l13_n709(x)
+ if (x < 1)
+ fun_l14_n511(x)
+ else
+ fun_l14_n131(x)
+ end
+end
+
+def fun_l13_n710(x)
+ if (x < 1)
+ fun_l14_n593(x)
+ else
+ fun_l14_n233(x)
+ end
+end
+
+def fun_l13_n711(x)
+ if (x < 1)
+ fun_l14_n846(x)
+ else
+ fun_l14_n166(x)
+ end
+end
+
+def fun_l13_n712(x)
+ if (x < 1)
+ fun_l14_n759(x)
+ else
+ fun_l14_n103(x)
+ end
+end
+
+def fun_l13_n713(x)
+ if (x < 1)
+ fun_l14_n364(x)
+ else
+ fun_l14_n805(x)
+ end
+end
+
+def fun_l13_n714(x)
+ if (x < 1)
+ fun_l14_n957(x)
+ else
+ fun_l14_n85(x)
+ end
+end
+
+def fun_l13_n715(x)
+ if (x < 1)
+ fun_l14_n877(x)
+ else
+ fun_l14_n111(x)
+ end
+end
+
+def fun_l13_n716(x)
+ if (x < 1)
+ fun_l14_n290(x)
+ else
+ fun_l14_n894(x)
+ end
+end
+
+def fun_l13_n717(x)
+ if (x < 1)
+ fun_l14_n354(x)
+ else
+ fun_l14_n646(x)
+ end
+end
+
+def fun_l13_n718(x)
+ if (x < 1)
+ fun_l14_n364(x)
+ else
+ fun_l14_n810(x)
+ end
+end
+
+def fun_l13_n719(x)
+ if (x < 1)
+ fun_l14_n392(x)
+ else
+ fun_l14_n537(x)
+ end
+end
+
+def fun_l13_n720(x)
+ if (x < 1)
+ fun_l14_n546(x)
+ else
+ fun_l14_n681(x)
+ end
+end
+
+def fun_l13_n721(x)
+ if (x < 1)
+ fun_l14_n153(x)
+ else
+ fun_l14_n925(x)
+ end
+end
+
+def fun_l13_n722(x)
+ if (x < 1)
+ fun_l14_n107(x)
+ else
+ fun_l14_n482(x)
+ end
+end
+
+def fun_l13_n723(x)
+ if (x < 1)
+ fun_l14_n981(x)
+ else
+ fun_l14_n364(x)
+ end
+end
+
+def fun_l13_n724(x)
+ if (x < 1)
+ fun_l14_n869(x)
+ else
+ fun_l14_n871(x)
+ end
+end
+
+def fun_l13_n725(x)
+ if (x < 1)
+ fun_l14_n693(x)
+ else
+ fun_l14_n690(x)
+ end
+end
+
+def fun_l13_n726(x)
+ if (x < 1)
+ fun_l14_n587(x)
+ else
+ fun_l14_n654(x)
+ end
+end
+
+def fun_l13_n727(x)
+ if (x < 1)
+ fun_l14_n150(x)
+ else
+ fun_l14_n904(x)
+ end
+end
+
+def fun_l13_n728(x)
+ if (x < 1)
+ fun_l14_n843(x)
+ else
+ fun_l14_n556(x)
+ end
+end
+
+def fun_l13_n729(x)
+ if (x < 1)
+ fun_l14_n726(x)
+ else
+ fun_l14_n114(x)
+ end
+end
+
+def fun_l13_n730(x)
+ if (x < 1)
+ fun_l14_n976(x)
+ else
+ fun_l14_n740(x)
+ end
+end
+
+def fun_l13_n731(x)
+ if (x < 1)
+ fun_l14_n709(x)
+ else
+ fun_l14_n293(x)
+ end
+end
+
+def fun_l13_n732(x)
+ if (x < 1)
+ fun_l14_n858(x)
+ else
+ fun_l14_n530(x)
+ end
+end
+
+def fun_l13_n733(x)
+ if (x < 1)
+ fun_l14_n789(x)
+ else
+ fun_l14_n475(x)
+ end
+end
+
+def fun_l13_n734(x)
+ if (x < 1)
+ fun_l14_n813(x)
+ else
+ fun_l14_n359(x)
+ end
+end
+
+def fun_l13_n735(x)
+ if (x < 1)
+ fun_l14_n209(x)
+ else
+ fun_l14_n29(x)
+ end
+end
+
+def fun_l13_n736(x)
+ if (x < 1)
+ fun_l14_n710(x)
+ else
+ fun_l14_n823(x)
+ end
+end
+
+def fun_l13_n737(x)
+ if (x < 1)
+ fun_l14_n434(x)
+ else
+ fun_l14_n864(x)
+ end
+end
+
+def fun_l13_n738(x)
+ if (x < 1)
+ fun_l14_n184(x)
+ else
+ fun_l14_n902(x)
+ end
+end
+
+def fun_l13_n739(x)
+ if (x < 1)
+ fun_l14_n206(x)
+ else
+ fun_l14_n65(x)
+ end
+end
+
+def fun_l13_n740(x)
+ if (x < 1)
+ fun_l14_n670(x)
+ else
+ fun_l14_n956(x)
+ end
+end
+
+def fun_l13_n741(x)
+ if (x < 1)
+ fun_l14_n91(x)
+ else
+ fun_l14_n341(x)
+ end
+end
+
+def fun_l13_n742(x)
+ if (x < 1)
+ fun_l14_n864(x)
+ else
+ fun_l14_n864(x)
+ end
+end
+
+def fun_l13_n743(x)
+ if (x < 1)
+ fun_l14_n426(x)
+ else
+ fun_l14_n302(x)
+ end
+end
+
+def fun_l13_n744(x)
+ if (x < 1)
+ fun_l14_n241(x)
+ else
+ fun_l14_n151(x)
+ end
+end
+
+def fun_l13_n745(x)
+ if (x < 1)
+ fun_l14_n161(x)
+ else
+ fun_l14_n715(x)
+ end
+end
+
+def fun_l13_n746(x)
+ if (x < 1)
+ fun_l14_n925(x)
+ else
+ fun_l14_n840(x)
+ end
+end
+
+def fun_l13_n747(x)
+ if (x < 1)
+ fun_l14_n864(x)
+ else
+ fun_l14_n610(x)
+ end
+end
+
+def fun_l13_n748(x)
+ if (x < 1)
+ fun_l14_n322(x)
+ else
+ fun_l14_n69(x)
+ end
+end
+
+def fun_l13_n749(x)
+ if (x < 1)
+ fun_l14_n847(x)
+ else
+ fun_l14_n3(x)
+ end
+end
+
+def fun_l13_n750(x)
+ if (x < 1)
+ fun_l14_n124(x)
+ else
+ fun_l14_n915(x)
+ end
+end
+
+def fun_l13_n751(x)
+ if (x < 1)
+ fun_l14_n163(x)
+ else
+ fun_l14_n136(x)
+ end
+end
+
+def fun_l13_n752(x)
+ if (x < 1)
+ fun_l14_n525(x)
+ else
+ fun_l14_n197(x)
+ end
+end
+
+def fun_l13_n753(x)
+ if (x < 1)
+ fun_l14_n109(x)
+ else
+ fun_l14_n208(x)
+ end
+end
+
+def fun_l13_n754(x)
+ if (x < 1)
+ fun_l14_n597(x)
+ else
+ fun_l14_n307(x)
+ end
+end
+
+def fun_l13_n755(x)
+ if (x < 1)
+ fun_l14_n36(x)
+ else
+ fun_l14_n948(x)
+ end
+end
+
+def fun_l13_n756(x)
+ if (x < 1)
+ fun_l14_n236(x)
+ else
+ fun_l14_n716(x)
+ end
+end
+
+def fun_l13_n757(x)
+ if (x < 1)
+ fun_l14_n326(x)
+ else
+ fun_l14_n870(x)
+ end
+end
+
+def fun_l13_n758(x)
+ if (x < 1)
+ fun_l14_n333(x)
+ else
+ fun_l14_n224(x)
+ end
+end
+
+def fun_l13_n759(x)
+ if (x < 1)
+ fun_l14_n141(x)
+ else
+ fun_l14_n232(x)
+ end
+end
+
+def fun_l13_n760(x)
+ if (x < 1)
+ fun_l14_n653(x)
+ else
+ fun_l14_n559(x)
+ end
+end
+
+def fun_l13_n761(x)
+ if (x < 1)
+ fun_l14_n305(x)
+ else
+ fun_l14_n296(x)
+ end
+end
+
+def fun_l13_n762(x)
+ if (x < 1)
+ fun_l14_n318(x)
+ else
+ fun_l14_n351(x)
+ end
+end
+
+def fun_l13_n763(x)
+ if (x < 1)
+ fun_l14_n685(x)
+ else
+ fun_l14_n643(x)
+ end
+end
+
+def fun_l13_n764(x)
+ if (x < 1)
+ fun_l14_n180(x)
+ else
+ fun_l14_n348(x)
+ end
+end
+
+def fun_l13_n765(x)
+ if (x < 1)
+ fun_l14_n72(x)
+ else
+ fun_l14_n99(x)
+ end
+end
+
+def fun_l13_n766(x)
+ if (x < 1)
+ fun_l14_n463(x)
+ else
+ fun_l14_n135(x)
+ end
+end
+
+def fun_l13_n767(x)
+ if (x < 1)
+ fun_l14_n461(x)
+ else
+ fun_l14_n989(x)
+ end
+end
+
+def fun_l13_n768(x)
+ if (x < 1)
+ fun_l14_n759(x)
+ else
+ fun_l14_n907(x)
+ end
+end
+
+def fun_l13_n769(x)
+ if (x < 1)
+ fun_l14_n330(x)
+ else
+ fun_l14_n268(x)
+ end
+end
+
+def fun_l13_n770(x)
+ if (x < 1)
+ fun_l14_n809(x)
+ else
+ fun_l14_n46(x)
+ end
+end
+
+def fun_l13_n771(x)
+ if (x < 1)
+ fun_l14_n396(x)
+ else
+ fun_l14_n114(x)
+ end
+end
+
+def fun_l13_n772(x)
+ if (x < 1)
+ fun_l14_n300(x)
+ else
+ fun_l14_n60(x)
+ end
+end
+
+def fun_l13_n773(x)
+ if (x < 1)
+ fun_l14_n938(x)
+ else
+ fun_l14_n112(x)
+ end
+end
+
+def fun_l13_n774(x)
+ if (x < 1)
+ fun_l14_n862(x)
+ else
+ fun_l14_n503(x)
+ end
+end
+
+def fun_l13_n775(x)
+ if (x < 1)
+ fun_l14_n305(x)
+ else
+ fun_l14_n11(x)
+ end
+end
+
+def fun_l13_n776(x)
+ if (x < 1)
+ fun_l14_n638(x)
+ else
+ fun_l14_n161(x)
+ end
+end
+
+def fun_l13_n777(x)
+ if (x < 1)
+ fun_l14_n2(x)
+ else
+ fun_l14_n176(x)
+ end
+end
+
+def fun_l13_n778(x)
+ if (x < 1)
+ fun_l14_n967(x)
+ else
+ fun_l14_n739(x)
+ end
+end
+
+def fun_l13_n779(x)
+ if (x < 1)
+ fun_l14_n961(x)
+ else
+ fun_l14_n609(x)
+ end
+end
+
+def fun_l13_n780(x)
+ if (x < 1)
+ fun_l14_n207(x)
+ else
+ fun_l14_n910(x)
+ end
+end
+
+def fun_l13_n781(x)
+ if (x < 1)
+ fun_l14_n370(x)
+ else
+ fun_l14_n163(x)
+ end
+end
+
+def fun_l13_n782(x)
+ if (x < 1)
+ fun_l14_n140(x)
+ else
+ fun_l14_n816(x)
+ end
+end
+
+def fun_l13_n783(x)
+ if (x < 1)
+ fun_l14_n351(x)
+ else
+ fun_l14_n406(x)
+ end
+end
+
+def fun_l13_n784(x)
+ if (x < 1)
+ fun_l14_n790(x)
+ else
+ fun_l14_n175(x)
+ end
+end
+
+def fun_l13_n785(x)
+ if (x < 1)
+ fun_l14_n644(x)
+ else
+ fun_l14_n713(x)
+ end
+end
+
+def fun_l13_n786(x)
+ if (x < 1)
+ fun_l14_n800(x)
+ else
+ fun_l14_n257(x)
+ end
+end
+
+def fun_l13_n787(x)
+ if (x < 1)
+ fun_l14_n248(x)
+ else
+ fun_l14_n709(x)
+ end
+end
+
+def fun_l13_n788(x)
+ if (x < 1)
+ fun_l14_n280(x)
+ else
+ fun_l14_n485(x)
+ end
+end
+
+def fun_l13_n789(x)
+ if (x < 1)
+ fun_l14_n900(x)
+ else
+ fun_l14_n675(x)
+ end
+end
+
+def fun_l13_n790(x)
+ if (x < 1)
+ fun_l14_n65(x)
+ else
+ fun_l14_n426(x)
+ end
+end
+
+def fun_l13_n791(x)
+ if (x < 1)
+ fun_l14_n410(x)
+ else
+ fun_l14_n484(x)
+ end
+end
+
+def fun_l13_n792(x)
+ if (x < 1)
+ fun_l14_n741(x)
+ else
+ fun_l14_n13(x)
+ end
+end
+
+def fun_l13_n793(x)
+ if (x < 1)
+ fun_l14_n550(x)
+ else
+ fun_l14_n884(x)
+ end
+end
+
+def fun_l13_n794(x)
+ if (x < 1)
+ fun_l14_n120(x)
+ else
+ fun_l14_n262(x)
+ end
+end
+
+def fun_l13_n795(x)
+ if (x < 1)
+ fun_l14_n537(x)
+ else
+ fun_l14_n980(x)
+ end
+end
+
+def fun_l13_n796(x)
+ if (x < 1)
+ fun_l14_n742(x)
+ else
+ fun_l14_n6(x)
+ end
+end
+
+def fun_l13_n797(x)
+ if (x < 1)
+ fun_l14_n986(x)
+ else
+ fun_l14_n434(x)
+ end
+end
+
+def fun_l13_n798(x)
+ if (x < 1)
+ fun_l14_n39(x)
+ else
+ fun_l14_n658(x)
+ end
+end
+
+def fun_l13_n799(x)
+ if (x < 1)
+ fun_l14_n838(x)
+ else
+ fun_l14_n810(x)
+ end
+end
+
+def fun_l13_n800(x)
+ if (x < 1)
+ fun_l14_n79(x)
+ else
+ fun_l14_n695(x)
+ end
+end
+
+def fun_l13_n801(x)
+ if (x < 1)
+ fun_l14_n99(x)
+ else
+ fun_l14_n26(x)
+ end
+end
+
+def fun_l13_n802(x)
+ if (x < 1)
+ fun_l14_n839(x)
+ else
+ fun_l14_n430(x)
+ end
+end
+
+def fun_l13_n803(x)
+ if (x < 1)
+ fun_l14_n410(x)
+ else
+ fun_l14_n403(x)
+ end
+end
+
+def fun_l13_n804(x)
+ if (x < 1)
+ fun_l14_n143(x)
+ else
+ fun_l14_n689(x)
+ end
+end
+
+def fun_l13_n805(x)
+ if (x < 1)
+ fun_l14_n695(x)
+ else
+ fun_l14_n721(x)
+ end
+end
+
+def fun_l13_n806(x)
+ if (x < 1)
+ fun_l14_n418(x)
+ else
+ fun_l14_n508(x)
+ end
+end
+
+def fun_l13_n807(x)
+ if (x < 1)
+ fun_l14_n569(x)
+ else
+ fun_l14_n86(x)
+ end
+end
+
+def fun_l13_n808(x)
+ if (x < 1)
+ fun_l14_n670(x)
+ else
+ fun_l14_n690(x)
+ end
+end
+
+def fun_l13_n809(x)
+ if (x < 1)
+ fun_l14_n283(x)
+ else
+ fun_l14_n630(x)
+ end
+end
+
+def fun_l13_n810(x)
+ if (x < 1)
+ fun_l14_n54(x)
+ else
+ fun_l14_n180(x)
+ end
+end
+
+def fun_l13_n811(x)
+ if (x < 1)
+ fun_l14_n669(x)
+ else
+ fun_l14_n131(x)
+ end
+end
+
+def fun_l13_n812(x)
+ if (x < 1)
+ fun_l14_n972(x)
+ else
+ fun_l14_n948(x)
+ end
+end
+
+def fun_l13_n813(x)
+ if (x < 1)
+ fun_l14_n585(x)
+ else
+ fun_l14_n244(x)
+ end
+end
+
+def fun_l13_n814(x)
+ if (x < 1)
+ fun_l14_n277(x)
+ else
+ fun_l14_n530(x)
+ end
+end
+
+def fun_l13_n815(x)
+ if (x < 1)
+ fun_l14_n908(x)
+ else
+ fun_l14_n380(x)
+ end
+end
+
+def fun_l13_n816(x)
+ if (x < 1)
+ fun_l14_n520(x)
+ else
+ fun_l14_n382(x)
+ end
+end
+
+def fun_l13_n817(x)
+ if (x < 1)
+ fun_l14_n40(x)
+ else
+ fun_l14_n757(x)
+ end
+end
+
+def fun_l13_n818(x)
+ if (x < 1)
+ fun_l14_n220(x)
+ else
+ fun_l14_n781(x)
+ end
+end
+
+def fun_l13_n819(x)
+ if (x < 1)
+ fun_l14_n507(x)
+ else
+ fun_l14_n602(x)
+ end
+end
+
+def fun_l13_n820(x)
+ if (x < 1)
+ fun_l14_n39(x)
+ else
+ fun_l14_n798(x)
+ end
+end
+
+def fun_l13_n821(x)
+ if (x < 1)
+ fun_l14_n412(x)
+ else
+ fun_l14_n58(x)
+ end
+end
+
+def fun_l13_n822(x)
+ if (x < 1)
+ fun_l14_n599(x)
+ else
+ fun_l14_n206(x)
+ end
+end
+
+def fun_l13_n823(x)
+ if (x < 1)
+ fun_l14_n294(x)
+ else
+ fun_l14_n711(x)
+ end
+end
+
+def fun_l13_n824(x)
+ if (x < 1)
+ fun_l14_n421(x)
+ else
+ fun_l14_n191(x)
+ end
+end
+
+def fun_l13_n825(x)
+ if (x < 1)
+ fun_l14_n598(x)
+ else
+ fun_l14_n547(x)
+ end
+end
+
+def fun_l13_n826(x)
+ if (x < 1)
+ fun_l14_n131(x)
+ else
+ fun_l14_n29(x)
+ end
+end
+
+def fun_l13_n827(x)
+ if (x < 1)
+ fun_l14_n19(x)
+ else
+ fun_l14_n213(x)
+ end
+end
+
+def fun_l13_n828(x)
+ if (x < 1)
+ fun_l14_n202(x)
+ else
+ fun_l14_n195(x)
+ end
+end
+
+def fun_l13_n829(x)
+ if (x < 1)
+ fun_l14_n133(x)
+ else
+ fun_l14_n949(x)
+ end
+end
+
+def fun_l13_n830(x)
+ if (x < 1)
+ fun_l14_n402(x)
+ else
+ fun_l14_n762(x)
+ end
+end
+
+def fun_l13_n831(x)
+ if (x < 1)
+ fun_l14_n233(x)
+ else
+ fun_l14_n984(x)
+ end
+end
+
+def fun_l13_n832(x)
+ if (x < 1)
+ fun_l14_n309(x)
+ else
+ fun_l14_n545(x)
+ end
+end
+
+def fun_l13_n833(x)
+ if (x < 1)
+ fun_l14_n160(x)
+ else
+ fun_l14_n434(x)
+ end
+end
+
+def fun_l13_n834(x)
+ if (x < 1)
+ fun_l14_n909(x)
+ else
+ fun_l14_n681(x)
+ end
+end
+
+def fun_l13_n835(x)
+ if (x < 1)
+ fun_l14_n747(x)
+ else
+ fun_l14_n813(x)
+ end
+end
+
+def fun_l13_n836(x)
+ if (x < 1)
+ fun_l14_n338(x)
+ else
+ fun_l14_n592(x)
+ end
+end
+
+def fun_l13_n837(x)
+ if (x < 1)
+ fun_l14_n707(x)
+ else
+ fun_l14_n587(x)
+ end
+end
+
+def fun_l13_n838(x)
+ if (x < 1)
+ fun_l14_n655(x)
+ else
+ fun_l14_n207(x)
+ end
+end
+
+def fun_l13_n839(x)
+ if (x < 1)
+ fun_l14_n231(x)
+ else
+ fun_l14_n459(x)
+ end
+end
+
+def fun_l13_n840(x)
+ if (x < 1)
+ fun_l14_n351(x)
+ else
+ fun_l14_n228(x)
+ end
+end
+
+def fun_l13_n841(x)
+ if (x < 1)
+ fun_l14_n205(x)
+ else
+ fun_l14_n628(x)
+ end
+end
+
+def fun_l13_n842(x)
+ if (x < 1)
+ fun_l14_n725(x)
+ else
+ fun_l14_n246(x)
+ end
+end
+
+def fun_l13_n843(x)
+ if (x < 1)
+ fun_l14_n297(x)
+ else
+ fun_l14_n891(x)
+ end
+end
+
+def fun_l13_n844(x)
+ if (x < 1)
+ fun_l14_n598(x)
+ else
+ fun_l14_n168(x)
+ end
+end
+
+def fun_l13_n845(x)
+ if (x < 1)
+ fun_l14_n101(x)
+ else
+ fun_l14_n681(x)
+ end
+end
+
+def fun_l13_n846(x)
+ if (x < 1)
+ fun_l14_n162(x)
+ else
+ fun_l14_n270(x)
+ end
+end
+
+def fun_l13_n847(x)
+ if (x < 1)
+ fun_l14_n84(x)
+ else
+ fun_l14_n957(x)
+ end
+end
+
+def fun_l13_n848(x)
+ if (x < 1)
+ fun_l14_n16(x)
+ else
+ fun_l14_n708(x)
+ end
+end
+
+def fun_l13_n849(x)
+ if (x < 1)
+ fun_l14_n636(x)
+ else
+ fun_l14_n518(x)
+ end
+end
+
+def fun_l13_n850(x)
+ if (x < 1)
+ fun_l14_n379(x)
+ else
+ fun_l14_n595(x)
+ end
+end
+
+def fun_l13_n851(x)
+ if (x < 1)
+ fun_l14_n258(x)
+ else
+ fun_l14_n757(x)
+ end
+end
+
+def fun_l13_n852(x)
+ if (x < 1)
+ fun_l14_n995(x)
+ else
+ fun_l14_n380(x)
+ end
+end
+
+def fun_l13_n853(x)
+ if (x < 1)
+ fun_l14_n505(x)
+ else
+ fun_l14_n934(x)
+ end
+end
+
+def fun_l13_n854(x)
+ if (x < 1)
+ fun_l14_n268(x)
+ else
+ fun_l14_n36(x)
+ end
+end
+
+def fun_l13_n855(x)
+ if (x < 1)
+ fun_l14_n795(x)
+ else
+ fun_l14_n905(x)
+ end
+end
+
+def fun_l13_n856(x)
+ if (x < 1)
+ fun_l14_n136(x)
+ else
+ fun_l14_n750(x)
+ end
+end
+
+def fun_l13_n857(x)
+ if (x < 1)
+ fun_l14_n120(x)
+ else
+ fun_l14_n156(x)
+ end
+end
+
+def fun_l13_n858(x)
+ if (x < 1)
+ fun_l14_n157(x)
+ else
+ fun_l14_n414(x)
+ end
+end
+
+def fun_l13_n859(x)
+ if (x < 1)
+ fun_l14_n926(x)
+ else
+ fun_l14_n718(x)
+ end
+end
+
+def fun_l13_n860(x)
+ if (x < 1)
+ fun_l14_n904(x)
+ else
+ fun_l14_n821(x)
+ end
+end
+
+def fun_l13_n861(x)
+ if (x < 1)
+ fun_l14_n887(x)
+ else
+ fun_l14_n407(x)
+ end
+end
+
+def fun_l13_n862(x)
+ if (x < 1)
+ fun_l14_n870(x)
+ else
+ fun_l14_n950(x)
+ end
+end
+
+def fun_l13_n863(x)
+ if (x < 1)
+ fun_l14_n267(x)
+ else
+ fun_l14_n712(x)
+ end
+end
+
+def fun_l13_n864(x)
+ if (x < 1)
+ fun_l14_n409(x)
+ else
+ fun_l14_n309(x)
+ end
+end
+
+def fun_l13_n865(x)
+ if (x < 1)
+ fun_l14_n345(x)
+ else
+ fun_l14_n110(x)
+ end
+end
+
+def fun_l13_n866(x)
+ if (x < 1)
+ fun_l14_n401(x)
+ else
+ fun_l14_n970(x)
+ end
+end
+
+def fun_l13_n867(x)
+ if (x < 1)
+ fun_l14_n814(x)
+ else
+ fun_l14_n260(x)
+ end
+end
+
+def fun_l13_n868(x)
+ if (x < 1)
+ fun_l14_n490(x)
+ else
+ fun_l14_n31(x)
+ end
+end
+
+def fun_l13_n869(x)
+ if (x < 1)
+ fun_l14_n214(x)
+ else
+ fun_l14_n425(x)
+ end
+end
+
+def fun_l13_n870(x)
+ if (x < 1)
+ fun_l14_n660(x)
+ else
+ fun_l14_n703(x)
+ end
+end
+
+def fun_l13_n871(x)
+ if (x < 1)
+ fun_l14_n650(x)
+ else
+ fun_l14_n257(x)
+ end
+end
+
+def fun_l13_n872(x)
+ if (x < 1)
+ fun_l14_n701(x)
+ else
+ fun_l14_n55(x)
+ end
+end
+
+def fun_l13_n873(x)
+ if (x < 1)
+ fun_l14_n225(x)
+ else
+ fun_l14_n701(x)
+ end
+end
+
+def fun_l13_n874(x)
+ if (x < 1)
+ fun_l14_n525(x)
+ else
+ fun_l14_n793(x)
+ end
+end
+
+def fun_l13_n875(x)
+ if (x < 1)
+ fun_l14_n87(x)
+ else
+ fun_l14_n807(x)
+ end
+end
+
+def fun_l13_n876(x)
+ if (x < 1)
+ fun_l14_n24(x)
+ else
+ fun_l14_n15(x)
+ end
+end
+
+def fun_l13_n877(x)
+ if (x < 1)
+ fun_l14_n120(x)
+ else
+ fun_l14_n551(x)
+ end
+end
+
+def fun_l13_n878(x)
+ if (x < 1)
+ fun_l14_n703(x)
+ else
+ fun_l14_n67(x)
+ end
+end
+
+def fun_l13_n879(x)
+ if (x < 1)
+ fun_l14_n496(x)
+ else
+ fun_l14_n197(x)
+ end
+end
+
+def fun_l13_n880(x)
+ if (x < 1)
+ fun_l14_n369(x)
+ else
+ fun_l14_n834(x)
+ end
+end
+
+def fun_l13_n881(x)
+ if (x < 1)
+ fun_l14_n892(x)
+ else
+ fun_l14_n210(x)
+ end
+end
+
+def fun_l13_n882(x)
+ if (x < 1)
+ fun_l14_n587(x)
+ else
+ fun_l14_n472(x)
+ end
+end
+
+def fun_l13_n883(x)
+ if (x < 1)
+ fun_l14_n1(x)
+ else
+ fun_l14_n778(x)
+ end
+end
+
+def fun_l13_n884(x)
+ if (x < 1)
+ fun_l14_n762(x)
+ else
+ fun_l14_n286(x)
+ end
+end
+
+def fun_l13_n885(x)
+ if (x < 1)
+ fun_l14_n36(x)
+ else
+ fun_l14_n326(x)
+ end
+end
+
+def fun_l13_n886(x)
+ if (x < 1)
+ fun_l14_n857(x)
+ else
+ fun_l14_n564(x)
+ end
+end
+
+def fun_l13_n887(x)
+ if (x < 1)
+ fun_l14_n461(x)
+ else
+ fun_l14_n415(x)
+ end
+end
+
+def fun_l13_n888(x)
+ if (x < 1)
+ fun_l14_n225(x)
+ else
+ fun_l14_n783(x)
+ end
+end
+
+def fun_l13_n889(x)
+ if (x < 1)
+ fun_l14_n10(x)
+ else
+ fun_l14_n114(x)
+ end
+end
+
+def fun_l13_n890(x)
+ if (x < 1)
+ fun_l14_n670(x)
+ else
+ fun_l14_n473(x)
+ end
+end
+
+def fun_l13_n891(x)
+ if (x < 1)
+ fun_l14_n777(x)
+ else
+ fun_l14_n98(x)
+ end
+end
+
+def fun_l13_n892(x)
+ if (x < 1)
+ fun_l14_n600(x)
+ else
+ fun_l14_n808(x)
+ end
+end
+
+def fun_l13_n893(x)
+ if (x < 1)
+ fun_l14_n605(x)
+ else
+ fun_l14_n687(x)
+ end
+end
+
+def fun_l13_n894(x)
+ if (x < 1)
+ fun_l14_n29(x)
+ else
+ fun_l14_n190(x)
+ end
+end
+
+def fun_l13_n895(x)
+ if (x < 1)
+ fun_l14_n26(x)
+ else
+ fun_l14_n887(x)
+ end
+end
+
+def fun_l13_n896(x)
+ if (x < 1)
+ fun_l14_n680(x)
+ else
+ fun_l14_n413(x)
+ end
+end
+
+def fun_l13_n897(x)
+ if (x < 1)
+ fun_l14_n634(x)
+ else
+ fun_l14_n184(x)
+ end
+end
+
+def fun_l13_n898(x)
+ if (x < 1)
+ fun_l14_n420(x)
+ else
+ fun_l14_n603(x)
+ end
+end
+
+def fun_l13_n899(x)
+ if (x < 1)
+ fun_l14_n702(x)
+ else
+ fun_l14_n54(x)
+ end
+end
+
+def fun_l13_n900(x)
+ if (x < 1)
+ fun_l14_n620(x)
+ else
+ fun_l14_n849(x)
+ end
+end
+
+def fun_l13_n901(x)
+ if (x < 1)
+ fun_l14_n848(x)
+ else
+ fun_l14_n384(x)
+ end
+end
+
+def fun_l13_n902(x)
+ if (x < 1)
+ fun_l14_n726(x)
+ else
+ fun_l14_n624(x)
+ end
+end
+
+def fun_l13_n903(x)
+ if (x < 1)
+ fun_l14_n663(x)
+ else
+ fun_l14_n395(x)
+ end
+end
+
+def fun_l13_n904(x)
+ if (x < 1)
+ fun_l14_n803(x)
+ else
+ fun_l14_n979(x)
+ end
+end
+
+def fun_l13_n905(x)
+ if (x < 1)
+ fun_l14_n487(x)
+ else
+ fun_l14_n530(x)
+ end
+end
+
+def fun_l13_n906(x)
+ if (x < 1)
+ fun_l14_n737(x)
+ else
+ fun_l14_n679(x)
+ end
+end
+
+def fun_l13_n907(x)
+ if (x < 1)
+ fun_l14_n815(x)
+ else
+ fun_l14_n84(x)
+ end
+end
+
+def fun_l13_n908(x)
+ if (x < 1)
+ fun_l14_n116(x)
+ else
+ fun_l14_n820(x)
+ end
+end
+
+def fun_l13_n909(x)
+ if (x < 1)
+ fun_l14_n353(x)
+ else
+ fun_l14_n949(x)
+ end
+end
+
+def fun_l13_n910(x)
+ if (x < 1)
+ fun_l14_n271(x)
+ else
+ fun_l14_n168(x)
+ end
+end
+
+def fun_l13_n911(x)
+ if (x < 1)
+ fun_l14_n54(x)
+ else
+ fun_l14_n236(x)
+ end
+end
+
+def fun_l13_n912(x)
+ if (x < 1)
+ fun_l14_n391(x)
+ else
+ fun_l14_n152(x)
+ end
+end
+
+def fun_l13_n913(x)
+ if (x < 1)
+ fun_l14_n450(x)
+ else
+ fun_l14_n521(x)
+ end
+end
+
+def fun_l13_n914(x)
+ if (x < 1)
+ fun_l14_n36(x)
+ else
+ fun_l14_n995(x)
+ end
+end
+
+def fun_l13_n915(x)
+ if (x < 1)
+ fun_l14_n177(x)
+ else
+ fun_l14_n358(x)
+ end
+end
+
+def fun_l13_n916(x)
+ if (x < 1)
+ fun_l14_n36(x)
+ else
+ fun_l14_n32(x)
+ end
+end
+
+def fun_l13_n917(x)
+ if (x < 1)
+ fun_l14_n970(x)
+ else
+ fun_l14_n957(x)
+ end
+end
+
+def fun_l13_n918(x)
+ if (x < 1)
+ fun_l14_n229(x)
+ else
+ fun_l14_n138(x)
+ end
+end
+
+def fun_l13_n919(x)
+ if (x < 1)
+ fun_l14_n439(x)
+ else
+ fun_l14_n641(x)
+ end
+end
+
+def fun_l13_n920(x)
+ if (x < 1)
+ fun_l14_n318(x)
+ else
+ fun_l14_n649(x)
+ end
+end
+
+def fun_l13_n921(x)
+ if (x < 1)
+ fun_l14_n455(x)
+ else
+ fun_l14_n312(x)
+ end
+end
+
+def fun_l13_n922(x)
+ if (x < 1)
+ fun_l14_n15(x)
+ else
+ fun_l14_n825(x)
+ end
+end
+
+def fun_l13_n923(x)
+ if (x < 1)
+ fun_l14_n546(x)
+ else
+ fun_l14_n629(x)
+ end
+end
+
+def fun_l13_n924(x)
+ if (x < 1)
+ fun_l14_n298(x)
+ else
+ fun_l14_n563(x)
+ end
+end
+
+def fun_l13_n925(x)
+ if (x < 1)
+ fun_l14_n312(x)
+ else
+ fun_l14_n736(x)
+ end
+end
+
+def fun_l13_n926(x)
+ if (x < 1)
+ fun_l14_n767(x)
+ else
+ fun_l14_n107(x)
+ end
+end
+
+def fun_l13_n927(x)
+ if (x < 1)
+ fun_l14_n966(x)
+ else
+ fun_l14_n765(x)
+ end
+end
+
+def fun_l13_n928(x)
+ if (x < 1)
+ fun_l14_n545(x)
+ else
+ fun_l14_n383(x)
+ end
+end
+
+def fun_l13_n929(x)
+ if (x < 1)
+ fun_l14_n389(x)
+ else
+ fun_l14_n48(x)
+ end
+end
+
+def fun_l13_n930(x)
+ if (x < 1)
+ fun_l14_n142(x)
+ else
+ fun_l14_n632(x)
+ end
+end
+
+def fun_l13_n931(x)
+ if (x < 1)
+ fun_l14_n146(x)
+ else
+ fun_l14_n275(x)
+ end
+end
+
+def fun_l13_n932(x)
+ if (x < 1)
+ fun_l14_n754(x)
+ else
+ fun_l14_n380(x)
+ end
+end
+
+def fun_l13_n933(x)
+ if (x < 1)
+ fun_l14_n561(x)
+ else
+ fun_l14_n677(x)
+ end
+end
+
+def fun_l13_n934(x)
+ if (x < 1)
+ fun_l14_n253(x)
+ else
+ fun_l14_n86(x)
+ end
+end
+
+def fun_l13_n935(x)
+ if (x < 1)
+ fun_l14_n528(x)
+ else
+ fun_l14_n177(x)
+ end
+end
+
+def fun_l13_n936(x)
+ if (x < 1)
+ fun_l14_n938(x)
+ else
+ fun_l14_n265(x)
+ end
+end
+
+def fun_l13_n937(x)
+ if (x < 1)
+ fun_l14_n763(x)
+ else
+ fun_l14_n662(x)
+ end
+end
+
+def fun_l13_n938(x)
+ if (x < 1)
+ fun_l14_n836(x)
+ else
+ fun_l14_n734(x)
+ end
+end
+
+def fun_l13_n939(x)
+ if (x < 1)
+ fun_l14_n127(x)
+ else
+ fun_l14_n111(x)
+ end
+end
+
+def fun_l13_n940(x)
+ if (x < 1)
+ fun_l14_n356(x)
+ else
+ fun_l14_n544(x)
+ end
+end
+
+def fun_l13_n941(x)
+ if (x < 1)
+ fun_l14_n525(x)
+ else
+ fun_l14_n762(x)
+ end
+end
+
+def fun_l13_n942(x)
+ if (x < 1)
+ fun_l14_n333(x)
+ else
+ fun_l14_n639(x)
+ end
+end
+
+def fun_l13_n943(x)
+ if (x < 1)
+ fun_l14_n452(x)
+ else
+ fun_l14_n944(x)
+ end
+end
+
+def fun_l13_n944(x)
+ if (x < 1)
+ fun_l14_n827(x)
+ else
+ fun_l14_n961(x)
+ end
+end
+
+def fun_l13_n945(x)
+ if (x < 1)
+ fun_l14_n991(x)
+ else
+ fun_l14_n431(x)
+ end
+end
+
+def fun_l13_n946(x)
+ if (x < 1)
+ fun_l14_n646(x)
+ else
+ fun_l14_n183(x)
+ end
+end
+
+def fun_l13_n947(x)
+ if (x < 1)
+ fun_l14_n107(x)
+ else
+ fun_l14_n273(x)
+ end
+end
+
+def fun_l13_n948(x)
+ if (x < 1)
+ fun_l14_n210(x)
+ else
+ fun_l14_n664(x)
+ end
+end
+
+def fun_l13_n949(x)
+ if (x < 1)
+ fun_l14_n542(x)
+ else
+ fun_l14_n462(x)
+ end
+end
+
+def fun_l13_n950(x)
+ if (x < 1)
+ fun_l14_n891(x)
+ else
+ fun_l14_n486(x)
+ end
+end
+
+def fun_l13_n951(x)
+ if (x < 1)
+ fun_l14_n527(x)
+ else
+ fun_l14_n721(x)
+ end
+end
+
+def fun_l13_n952(x)
+ if (x < 1)
+ fun_l14_n745(x)
+ else
+ fun_l14_n11(x)
+ end
+end
+
+def fun_l13_n953(x)
+ if (x < 1)
+ fun_l14_n427(x)
+ else
+ fun_l14_n521(x)
+ end
+end
+
+def fun_l13_n954(x)
+ if (x < 1)
+ fun_l14_n907(x)
+ else
+ fun_l14_n878(x)
+ end
+end
+
+def fun_l13_n955(x)
+ if (x < 1)
+ fun_l14_n818(x)
+ else
+ fun_l14_n722(x)
+ end
+end
+
+def fun_l13_n956(x)
+ if (x < 1)
+ fun_l14_n567(x)
+ else
+ fun_l14_n71(x)
+ end
+end
+
+def fun_l13_n957(x)
+ if (x < 1)
+ fun_l14_n203(x)
+ else
+ fun_l14_n221(x)
+ end
+end
+
+def fun_l13_n958(x)
+ if (x < 1)
+ fun_l14_n173(x)
+ else
+ fun_l14_n854(x)
+ end
+end
+
+def fun_l13_n959(x)
+ if (x < 1)
+ fun_l14_n201(x)
+ else
+ fun_l14_n930(x)
+ end
+end
+
+def fun_l13_n960(x)
+ if (x < 1)
+ fun_l14_n736(x)
+ else
+ fun_l14_n539(x)
+ end
+end
+
+def fun_l13_n961(x)
+ if (x < 1)
+ fun_l14_n459(x)
+ else
+ fun_l14_n771(x)
+ end
+end
+
+def fun_l13_n962(x)
+ if (x < 1)
+ fun_l14_n682(x)
+ else
+ fun_l14_n19(x)
+ end
+end
+
+def fun_l13_n963(x)
+ if (x < 1)
+ fun_l14_n897(x)
+ else
+ fun_l14_n650(x)
+ end
+end
+
+def fun_l13_n964(x)
+ if (x < 1)
+ fun_l14_n814(x)
+ else
+ fun_l14_n726(x)
+ end
+end
+
+def fun_l13_n965(x)
+ if (x < 1)
+ fun_l14_n31(x)
+ else
+ fun_l14_n211(x)
+ end
+end
+
+def fun_l13_n966(x)
+ if (x < 1)
+ fun_l14_n89(x)
+ else
+ fun_l14_n407(x)
+ end
+end
+
+def fun_l13_n967(x)
+ if (x < 1)
+ fun_l14_n772(x)
+ else
+ fun_l14_n7(x)
+ end
+end
+
+def fun_l13_n968(x)
+ if (x < 1)
+ fun_l14_n764(x)
+ else
+ fun_l14_n523(x)
+ end
+end
+
+def fun_l13_n969(x)
+ if (x < 1)
+ fun_l14_n680(x)
+ else
+ fun_l14_n674(x)
+ end
+end
+
+def fun_l13_n970(x)
+ if (x < 1)
+ fun_l14_n517(x)
+ else
+ fun_l14_n346(x)
+ end
+end
+
+def fun_l13_n971(x)
+ if (x < 1)
+ fun_l14_n136(x)
+ else
+ fun_l14_n921(x)
+ end
+end
+
+def fun_l13_n972(x)
+ if (x < 1)
+ fun_l14_n400(x)
+ else
+ fun_l14_n901(x)
+ end
+end
+
+def fun_l13_n973(x)
+ if (x < 1)
+ fun_l14_n62(x)
+ else
+ fun_l14_n784(x)
+ end
+end
+
+def fun_l13_n974(x)
+ if (x < 1)
+ fun_l14_n411(x)
+ else
+ fun_l14_n889(x)
+ end
+end
+
+def fun_l13_n975(x)
+ if (x < 1)
+ fun_l14_n291(x)
+ else
+ fun_l14_n198(x)
+ end
+end
+
+def fun_l13_n976(x)
+ if (x < 1)
+ fun_l14_n229(x)
+ else
+ fun_l14_n346(x)
+ end
+end
+
+def fun_l13_n977(x)
+ if (x < 1)
+ fun_l14_n769(x)
+ else
+ fun_l14_n381(x)
+ end
+end
+
+def fun_l13_n978(x)
+ if (x < 1)
+ fun_l14_n430(x)
+ else
+ fun_l14_n205(x)
+ end
+end
+
+def fun_l13_n979(x)
+ if (x < 1)
+ fun_l14_n170(x)
+ else
+ fun_l14_n927(x)
+ end
+end
+
+def fun_l13_n980(x)
+ if (x < 1)
+ fun_l14_n12(x)
+ else
+ fun_l14_n605(x)
+ end
+end
+
+def fun_l13_n981(x)
+ if (x < 1)
+ fun_l14_n613(x)
+ else
+ fun_l14_n912(x)
+ end
+end
+
+def fun_l13_n982(x)
+ if (x < 1)
+ fun_l14_n982(x)
+ else
+ fun_l14_n707(x)
+ end
+end
+
+def fun_l13_n983(x)
+ if (x < 1)
+ fun_l14_n230(x)
+ else
+ fun_l14_n239(x)
+ end
+end
+
+def fun_l13_n984(x)
+ if (x < 1)
+ fun_l14_n55(x)
+ else
+ fun_l14_n337(x)
+ end
+end
+
+def fun_l13_n985(x)
+ if (x < 1)
+ fun_l14_n853(x)
+ else
+ fun_l14_n425(x)
+ end
+end
+
+def fun_l13_n986(x)
+ if (x < 1)
+ fun_l14_n14(x)
+ else
+ fun_l14_n921(x)
+ end
+end
+
+def fun_l13_n987(x)
+ if (x < 1)
+ fun_l14_n166(x)
+ else
+ fun_l14_n948(x)
+ end
+end
+
+def fun_l13_n988(x)
+ if (x < 1)
+ fun_l14_n752(x)
+ else
+ fun_l14_n226(x)
+ end
+end
+
+def fun_l13_n989(x)
+ if (x < 1)
+ fun_l14_n730(x)
+ else
+ fun_l14_n671(x)
+ end
+end
+
+def fun_l13_n990(x)
+ if (x < 1)
+ fun_l14_n603(x)
+ else
+ fun_l14_n903(x)
+ end
+end
+
+def fun_l13_n991(x)
+ if (x < 1)
+ fun_l14_n598(x)
+ else
+ fun_l14_n842(x)
+ end
+end
+
+def fun_l13_n992(x)
+ if (x < 1)
+ fun_l14_n230(x)
+ else
+ fun_l14_n704(x)
+ end
+end
+
+def fun_l13_n993(x)
+ if (x < 1)
+ fun_l14_n897(x)
+ else
+ fun_l14_n190(x)
+ end
+end
+
+def fun_l13_n994(x)
+ if (x < 1)
+ fun_l14_n640(x)
+ else
+ fun_l14_n622(x)
+ end
+end
+
+def fun_l13_n995(x)
+ if (x < 1)
+ fun_l14_n988(x)
+ else
+ fun_l14_n471(x)
+ end
+end
+
+def fun_l13_n996(x)
+ if (x < 1)
+ fun_l14_n721(x)
+ else
+ fun_l14_n672(x)
+ end
+end
+
+def fun_l13_n997(x)
+ if (x < 1)
+ fun_l14_n425(x)
+ else
+ fun_l14_n885(x)
+ end
+end
+
+def fun_l13_n998(x)
+ if (x < 1)
+ fun_l14_n279(x)
+ else
+ fun_l14_n966(x)
+ end
+end
+
+def fun_l13_n999(x)
+ if (x < 1)
+ fun_l14_n610(x)
+ else
+ fun_l14_n319(x)
+ end
+end
+
+def fun_l14_n0(x)
+ if (x < 1)
+ fun_l15_n46(x)
+ else
+ fun_l15_n966(x)
+ end
+end
+
+def fun_l14_n1(x)
+ if (x < 1)
+ fun_l15_n360(x)
+ else
+ fun_l15_n637(x)
+ end
+end
+
+def fun_l14_n2(x)
+ if (x < 1)
+ fun_l15_n381(x)
+ else
+ fun_l15_n728(x)
+ end
+end
+
+def fun_l14_n3(x)
+ if (x < 1)
+ fun_l15_n189(x)
+ else
+ fun_l15_n826(x)
+ end
+end
+
+def fun_l14_n4(x)
+ if (x < 1)
+ fun_l15_n789(x)
+ else
+ fun_l15_n157(x)
+ end
+end
+
+def fun_l14_n5(x)
+ if (x < 1)
+ fun_l15_n132(x)
+ else
+ fun_l15_n703(x)
+ end
+end
+
+def fun_l14_n6(x)
+ if (x < 1)
+ fun_l15_n64(x)
+ else
+ fun_l15_n537(x)
+ end
+end
+
+def fun_l14_n7(x)
+ if (x < 1)
+ fun_l15_n423(x)
+ else
+ fun_l15_n162(x)
+ end
+end
+
+def fun_l14_n8(x)
+ if (x < 1)
+ fun_l15_n177(x)
+ else
+ fun_l15_n923(x)
+ end
+end
+
+def fun_l14_n9(x)
+ if (x < 1)
+ fun_l15_n508(x)
+ else
+ fun_l15_n135(x)
+ end
+end
+
+def fun_l14_n10(x)
+ if (x < 1)
+ fun_l15_n640(x)
+ else
+ fun_l15_n869(x)
+ end
+end
+
+def fun_l14_n11(x)
+ if (x < 1)
+ fun_l15_n592(x)
+ else
+ fun_l15_n519(x)
+ end
+end
+
+def fun_l14_n12(x)
+ if (x < 1)
+ fun_l15_n332(x)
+ else
+ fun_l15_n263(x)
+ end
+end
+
+def fun_l14_n13(x)
+ if (x < 1)
+ fun_l15_n644(x)
+ else
+ fun_l15_n21(x)
+ end
+end
+
+def fun_l14_n14(x)
+ if (x < 1)
+ fun_l15_n436(x)
+ else
+ fun_l15_n566(x)
+ end
+end
+
+def fun_l14_n15(x)
+ if (x < 1)
+ fun_l15_n160(x)
+ else
+ fun_l15_n291(x)
+ end
+end
+
+def fun_l14_n16(x)
+ if (x < 1)
+ fun_l15_n726(x)
+ else
+ fun_l15_n704(x)
+ end
+end
+
+def fun_l14_n17(x)
+ if (x < 1)
+ fun_l15_n237(x)
+ else
+ fun_l15_n962(x)
+ end
+end
+
+def fun_l14_n18(x)
+ if (x < 1)
+ fun_l15_n941(x)
+ else
+ fun_l15_n217(x)
+ end
+end
+
+def fun_l14_n19(x)
+ if (x < 1)
+ fun_l15_n904(x)
+ else
+ fun_l15_n36(x)
+ end
+end
+
+def fun_l14_n20(x)
+ if (x < 1)
+ fun_l15_n74(x)
+ else
+ fun_l15_n790(x)
+ end
+end
+
+def fun_l14_n21(x)
+ if (x < 1)
+ fun_l15_n694(x)
+ else
+ fun_l15_n298(x)
+ end
+end
+
+def fun_l14_n22(x)
+ if (x < 1)
+ fun_l15_n757(x)
+ else
+ fun_l15_n636(x)
+ end
+end
+
+def fun_l14_n23(x)
+ if (x < 1)
+ fun_l15_n989(x)
+ else
+ fun_l15_n508(x)
+ end
+end
+
+def fun_l14_n24(x)
+ if (x < 1)
+ fun_l15_n80(x)
+ else
+ fun_l15_n686(x)
+ end
+end
+
+def fun_l14_n25(x)
+ if (x < 1)
+ fun_l15_n365(x)
+ else
+ fun_l15_n922(x)
+ end
+end
+
+def fun_l14_n26(x)
+ if (x < 1)
+ fun_l15_n922(x)
+ else
+ fun_l15_n207(x)
+ end
+end
+
+def fun_l14_n27(x)
+ if (x < 1)
+ fun_l15_n406(x)
+ else
+ fun_l15_n481(x)
+ end
+end
+
+def fun_l14_n28(x)
+ if (x < 1)
+ fun_l15_n986(x)
+ else
+ fun_l15_n181(x)
+ end
+end
+
+def fun_l14_n29(x)
+ if (x < 1)
+ fun_l15_n958(x)
+ else
+ fun_l15_n804(x)
+ end
+end
+
+def fun_l14_n30(x)
+ if (x < 1)
+ fun_l15_n233(x)
+ else
+ fun_l15_n877(x)
+ end
+end
+
+def fun_l14_n31(x)
+ if (x < 1)
+ fun_l15_n648(x)
+ else
+ fun_l15_n547(x)
+ end
+end
+
+def fun_l14_n32(x)
+ if (x < 1)
+ fun_l15_n641(x)
+ else
+ fun_l15_n628(x)
+ end
+end
+
+def fun_l14_n33(x)
+ if (x < 1)
+ fun_l15_n351(x)
+ else
+ fun_l15_n280(x)
+ end
+end
+
+def fun_l14_n34(x)
+ if (x < 1)
+ fun_l15_n373(x)
+ else
+ fun_l15_n948(x)
+ end
+end
+
+def fun_l14_n35(x)
+ if (x < 1)
+ fun_l15_n761(x)
+ else
+ fun_l15_n384(x)
+ end
+end
+
+def fun_l14_n36(x)
+ if (x < 1)
+ fun_l15_n75(x)
+ else
+ fun_l15_n581(x)
+ end
+end
+
+def fun_l14_n37(x)
+ if (x < 1)
+ fun_l15_n962(x)
+ else
+ fun_l15_n723(x)
+ end
+end
+
+def fun_l14_n38(x)
+ if (x < 1)
+ fun_l15_n422(x)
+ else
+ fun_l15_n953(x)
+ end
+end
+
+def fun_l14_n39(x)
+ if (x < 1)
+ fun_l15_n123(x)
+ else
+ fun_l15_n989(x)
+ end
+end
+
+def fun_l14_n40(x)
+ if (x < 1)
+ fun_l15_n789(x)
+ else
+ fun_l15_n472(x)
+ end
+end
+
+def fun_l14_n41(x)
+ if (x < 1)
+ fun_l15_n261(x)
+ else
+ fun_l15_n997(x)
+ end
+end
+
+def fun_l14_n42(x)
+ if (x < 1)
+ fun_l15_n231(x)
+ else
+ fun_l15_n703(x)
+ end
+end
+
+def fun_l14_n43(x)
+ if (x < 1)
+ fun_l15_n520(x)
+ else
+ fun_l15_n252(x)
+ end
+end
+
+def fun_l14_n44(x)
+ if (x < 1)
+ fun_l15_n966(x)
+ else
+ fun_l15_n244(x)
+ end
+end
+
+def fun_l14_n45(x)
+ if (x < 1)
+ fun_l15_n192(x)
+ else
+ fun_l15_n280(x)
+ end
+end
+
+def fun_l14_n46(x)
+ if (x < 1)
+ fun_l15_n422(x)
+ else
+ fun_l15_n847(x)
+ end
+end
+
+def fun_l14_n47(x)
+ if (x < 1)
+ fun_l15_n228(x)
+ else
+ fun_l15_n564(x)
+ end
+end
+
+def fun_l14_n48(x)
+ if (x < 1)
+ fun_l15_n263(x)
+ else
+ fun_l15_n226(x)
+ end
+end
+
+def fun_l14_n49(x)
+ if (x < 1)
+ fun_l15_n440(x)
+ else
+ fun_l15_n592(x)
+ end
+end
+
+def fun_l14_n50(x)
+ if (x < 1)
+ fun_l15_n464(x)
+ else
+ fun_l15_n135(x)
+ end
+end
+
+def fun_l14_n51(x)
+ if (x < 1)
+ fun_l15_n903(x)
+ else
+ fun_l15_n821(x)
+ end
+end
+
+def fun_l14_n52(x)
+ if (x < 1)
+ fun_l15_n472(x)
+ else
+ fun_l15_n322(x)
+ end
+end
+
+def fun_l14_n53(x)
+ if (x < 1)
+ fun_l15_n107(x)
+ else
+ fun_l15_n497(x)
+ end
+end
+
+def fun_l14_n54(x)
+ if (x < 1)
+ fun_l15_n692(x)
+ else
+ fun_l15_n392(x)
+ end
+end
+
+def fun_l14_n55(x)
+ if (x < 1)
+ fun_l15_n694(x)
+ else
+ fun_l15_n995(x)
+ end
+end
+
+def fun_l14_n56(x)
+ if (x < 1)
+ fun_l15_n181(x)
+ else
+ fun_l15_n200(x)
+ end
+end
+
+def fun_l14_n57(x)
+ if (x < 1)
+ fun_l15_n721(x)
+ else
+ fun_l15_n849(x)
+ end
+end
+
+def fun_l14_n58(x)
+ if (x < 1)
+ fun_l15_n626(x)
+ else
+ fun_l15_n866(x)
+ end
+end
+
+def fun_l14_n59(x)
+ if (x < 1)
+ fun_l15_n689(x)
+ else
+ fun_l15_n387(x)
+ end
+end
+
+def fun_l14_n60(x)
+ if (x < 1)
+ fun_l15_n805(x)
+ else
+ fun_l15_n842(x)
+ end
+end
+
+def fun_l14_n61(x)
+ if (x < 1)
+ fun_l15_n457(x)
+ else
+ fun_l15_n472(x)
+ end
+end
+
+def fun_l14_n62(x)
+ if (x < 1)
+ fun_l15_n884(x)
+ else
+ fun_l15_n786(x)
+ end
+end
+
+def fun_l14_n63(x)
+ if (x < 1)
+ fun_l15_n509(x)
+ else
+ fun_l15_n106(x)
+ end
+end
+
+def fun_l14_n64(x)
+ if (x < 1)
+ fun_l15_n600(x)
+ else
+ fun_l15_n314(x)
+ end
+end
+
+def fun_l14_n65(x)
+ if (x < 1)
+ fun_l15_n761(x)
+ else
+ fun_l15_n362(x)
+ end
+end
+
+def fun_l14_n66(x)
+ if (x < 1)
+ fun_l15_n812(x)
+ else
+ fun_l15_n640(x)
+ end
+end
+
+def fun_l14_n67(x)
+ if (x < 1)
+ fun_l15_n862(x)
+ else
+ fun_l15_n627(x)
+ end
+end
+
+def fun_l14_n68(x)
+ if (x < 1)
+ fun_l15_n503(x)
+ else
+ fun_l15_n381(x)
+ end
+end
+
+def fun_l14_n69(x)
+ if (x < 1)
+ fun_l15_n482(x)
+ else
+ fun_l15_n851(x)
+ end
+end
+
+def fun_l14_n70(x)
+ if (x < 1)
+ fun_l15_n253(x)
+ else
+ fun_l15_n728(x)
+ end
+end
+
+def fun_l14_n71(x)
+ if (x < 1)
+ fun_l15_n195(x)
+ else
+ fun_l15_n537(x)
+ end
+end
+
+def fun_l14_n72(x)
+ if (x < 1)
+ fun_l15_n482(x)
+ else
+ fun_l15_n604(x)
+ end
+end
+
+def fun_l14_n73(x)
+ if (x < 1)
+ fun_l15_n373(x)
+ else
+ fun_l15_n502(x)
+ end
+end
+
+def fun_l14_n74(x)
+ if (x < 1)
+ fun_l15_n183(x)
+ else
+ fun_l15_n50(x)
+ end
+end
+
+def fun_l14_n75(x)
+ if (x < 1)
+ fun_l15_n397(x)
+ else
+ fun_l15_n467(x)
+ end
+end
+
+def fun_l14_n76(x)
+ if (x < 1)
+ fun_l15_n207(x)
+ else
+ fun_l15_n566(x)
+ end
+end
+
+def fun_l14_n77(x)
+ if (x < 1)
+ fun_l15_n416(x)
+ else
+ fun_l15_n846(x)
+ end
+end
+
+def fun_l14_n78(x)
+ if (x < 1)
+ fun_l15_n426(x)
+ else
+ fun_l15_n142(x)
+ end
+end
+
+def fun_l14_n79(x)
+ if (x < 1)
+ fun_l15_n234(x)
+ else
+ fun_l15_n5(x)
+ end
+end
+
+def fun_l14_n80(x)
+ if (x < 1)
+ fun_l15_n133(x)
+ else
+ fun_l15_n216(x)
+ end
+end
+
+def fun_l14_n81(x)
+ if (x < 1)
+ fun_l15_n23(x)
+ else
+ fun_l15_n126(x)
+ end
+end
+
+def fun_l14_n82(x)
+ if (x < 1)
+ fun_l15_n129(x)
+ else
+ fun_l15_n614(x)
+ end
+end
+
+def fun_l14_n83(x)
+ if (x < 1)
+ fun_l15_n560(x)
+ else
+ fun_l15_n559(x)
+ end
+end
+
+def fun_l14_n84(x)
+ if (x < 1)
+ fun_l15_n113(x)
+ else
+ fun_l15_n300(x)
+ end
+end
+
+def fun_l14_n85(x)
+ if (x < 1)
+ fun_l15_n584(x)
+ else
+ fun_l15_n249(x)
+ end
+end
+
+def fun_l14_n86(x)
+ if (x < 1)
+ fun_l15_n933(x)
+ else
+ fun_l15_n280(x)
+ end
+end
+
+def fun_l14_n87(x)
+ if (x < 1)
+ fun_l15_n528(x)
+ else
+ fun_l15_n350(x)
+ end
+end
+
+def fun_l14_n88(x)
+ if (x < 1)
+ fun_l15_n568(x)
+ else
+ fun_l15_n762(x)
+ end
+end
+
+def fun_l14_n89(x)
+ if (x < 1)
+ fun_l15_n190(x)
+ else
+ fun_l15_n858(x)
+ end
+end
+
+def fun_l14_n90(x)
+ if (x < 1)
+ fun_l15_n896(x)
+ else
+ fun_l15_n543(x)
+ end
+end
+
+def fun_l14_n91(x)
+ if (x < 1)
+ fun_l15_n937(x)
+ else
+ fun_l15_n593(x)
+ end
+end
+
+def fun_l14_n92(x)
+ if (x < 1)
+ fun_l15_n135(x)
+ else
+ fun_l15_n5(x)
+ end
+end
+
+def fun_l14_n93(x)
+ if (x < 1)
+ fun_l15_n351(x)
+ else
+ fun_l15_n779(x)
+ end
+end
+
+def fun_l14_n94(x)
+ if (x < 1)
+ fun_l15_n617(x)
+ else
+ fun_l15_n375(x)
+ end
+end
+
+def fun_l14_n95(x)
+ if (x < 1)
+ fun_l15_n111(x)
+ else
+ fun_l15_n870(x)
+ end
+end
+
+def fun_l14_n96(x)
+ if (x < 1)
+ fun_l15_n187(x)
+ else
+ fun_l15_n881(x)
+ end
+end
+
+def fun_l14_n97(x)
+ if (x < 1)
+ fun_l15_n150(x)
+ else
+ fun_l15_n98(x)
+ end
+end
+
+def fun_l14_n98(x)
+ if (x < 1)
+ fun_l15_n629(x)
+ else
+ fun_l15_n548(x)
+ end
+end
+
+def fun_l14_n99(x)
+ if (x < 1)
+ fun_l15_n37(x)
+ else
+ fun_l15_n383(x)
+ end
+end
+
+def fun_l14_n100(x)
+ if (x < 1)
+ fun_l15_n719(x)
+ else
+ fun_l15_n503(x)
+ end
+end
+
+def fun_l14_n101(x)
+ if (x < 1)
+ fun_l15_n415(x)
+ else
+ fun_l15_n650(x)
+ end
+end
+
+def fun_l14_n102(x)
+ if (x < 1)
+ fun_l15_n924(x)
+ else
+ fun_l15_n520(x)
+ end
+end
+
+def fun_l14_n103(x)
+ if (x < 1)
+ fun_l15_n194(x)
+ else
+ fun_l15_n613(x)
+ end
+end
+
+def fun_l14_n104(x)
+ if (x < 1)
+ fun_l15_n909(x)
+ else
+ fun_l15_n333(x)
+ end
+end
+
+def fun_l14_n105(x)
+ if (x < 1)
+ fun_l15_n586(x)
+ else
+ fun_l15_n2(x)
+ end
+end
+
+def fun_l14_n106(x)
+ if (x < 1)
+ fun_l15_n373(x)
+ else
+ fun_l15_n316(x)
+ end
+end
+
+def fun_l14_n107(x)
+ if (x < 1)
+ fun_l15_n737(x)
+ else
+ fun_l15_n469(x)
+ end
+end
+
+def fun_l14_n108(x)
+ if (x < 1)
+ fun_l15_n841(x)
+ else
+ fun_l15_n888(x)
+ end
+end
+
+def fun_l14_n109(x)
+ if (x < 1)
+ fun_l15_n165(x)
+ else
+ fun_l15_n108(x)
+ end
+end
+
+def fun_l14_n110(x)
+ if (x < 1)
+ fun_l15_n344(x)
+ else
+ fun_l15_n893(x)
+ end
+end
+
+def fun_l14_n111(x)
+ if (x < 1)
+ fun_l15_n424(x)
+ else
+ fun_l15_n702(x)
+ end
+end
+
+def fun_l14_n112(x)
+ if (x < 1)
+ fun_l15_n161(x)
+ else
+ fun_l15_n827(x)
+ end
+end
+
+def fun_l14_n113(x)
+ if (x < 1)
+ fun_l15_n982(x)
+ else
+ fun_l15_n172(x)
+ end
+end
+
+def fun_l14_n114(x)
+ if (x < 1)
+ fun_l15_n233(x)
+ else
+ fun_l15_n178(x)
+ end
+end
+
+def fun_l14_n115(x)
+ if (x < 1)
+ fun_l15_n130(x)
+ else
+ fun_l15_n266(x)
+ end
+end
+
+def fun_l14_n116(x)
+ if (x < 1)
+ fun_l15_n32(x)
+ else
+ fun_l15_n63(x)
+ end
+end
+
+def fun_l14_n117(x)
+ if (x < 1)
+ fun_l15_n117(x)
+ else
+ fun_l15_n659(x)
+ end
+end
+
+def fun_l14_n118(x)
+ if (x < 1)
+ fun_l15_n607(x)
+ else
+ fun_l15_n516(x)
+ end
+end
+
+def fun_l14_n119(x)
+ if (x < 1)
+ fun_l15_n30(x)
+ else
+ fun_l15_n130(x)
+ end
+end
+
+def fun_l14_n120(x)
+ if (x < 1)
+ fun_l15_n510(x)
+ else
+ fun_l15_n789(x)
+ end
+end
+
+def fun_l14_n121(x)
+ if (x < 1)
+ fun_l15_n906(x)
+ else
+ fun_l15_n700(x)
+ end
+end
+
+def fun_l14_n122(x)
+ if (x < 1)
+ fun_l15_n51(x)
+ else
+ fun_l15_n378(x)
+ end
+end
+
+def fun_l14_n123(x)
+ if (x < 1)
+ fun_l15_n243(x)
+ else
+ fun_l15_n896(x)
+ end
+end
+
+def fun_l14_n124(x)
+ if (x < 1)
+ fun_l15_n23(x)
+ else
+ fun_l15_n648(x)
+ end
+end
+
+def fun_l14_n125(x)
+ if (x < 1)
+ fun_l15_n290(x)
+ else
+ fun_l15_n604(x)
+ end
+end
+
+def fun_l14_n126(x)
+ if (x < 1)
+ fun_l15_n410(x)
+ else
+ fun_l15_n646(x)
+ end
+end
+
+def fun_l14_n127(x)
+ if (x < 1)
+ fun_l15_n162(x)
+ else
+ fun_l15_n43(x)
+ end
+end
+
+def fun_l14_n128(x)
+ if (x < 1)
+ fun_l15_n775(x)
+ else
+ fun_l15_n176(x)
+ end
+end
+
+def fun_l14_n129(x)
+ if (x < 1)
+ fun_l15_n642(x)
+ else
+ fun_l15_n709(x)
+ end
+end
+
+def fun_l14_n130(x)
+ if (x < 1)
+ fun_l15_n669(x)
+ else
+ fun_l15_n936(x)
+ end
+end
+
+def fun_l14_n131(x)
+ if (x < 1)
+ fun_l15_n301(x)
+ else
+ fun_l15_n578(x)
+ end
+end
+
+def fun_l14_n132(x)
+ if (x < 1)
+ fun_l15_n112(x)
+ else
+ fun_l15_n72(x)
+ end
+end
+
+def fun_l14_n133(x)
+ if (x < 1)
+ fun_l15_n293(x)
+ else
+ fun_l15_n516(x)
+ end
+end
+
+def fun_l14_n134(x)
+ if (x < 1)
+ fun_l15_n525(x)
+ else
+ fun_l15_n199(x)
+ end
+end
+
+def fun_l14_n135(x)
+ if (x < 1)
+ fun_l15_n168(x)
+ else
+ fun_l15_n430(x)
+ end
+end
+
+def fun_l14_n136(x)
+ if (x < 1)
+ fun_l15_n889(x)
+ else
+ fun_l15_n635(x)
+ end
+end
+
+def fun_l14_n137(x)
+ if (x < 1)
+ fun_l15_n348(x)
+ else
+ fun_l15_n445(x)
+ end
+end
+
+def fun_l14_n138(x)
+ if (x < 1)
+ fun_l15_n828(x)
+ else
+ fun_l15_n23(x)
+ end
+end
+
+def fun_l14_n139(x)
+ if (x < 1)
+ fun_l15_n621(x)
+ else
+ fun_l15_n25(x)
+ end
+end
+
+def fun_l14_n140(x)
+ if (x < 1)
+ fun_l15_n268(x)
+ else
+ fun_l15_n105(x)
+ end
+end
+
+def fun_l14_n141(x)
+ if (x < 1)
+ fun_l15_n296(x)
+ else
+ fun_l15_n856(x)
+ end
+end
+
+def fun_l14_n142(x)
+ if (x < 1)
+ fun_l15_n206(x)
+ else
+ fun_l15_n417(x)
+ end
+end
+
+def fun_l14_n143(x)
+ if (x < 1)
+ fun_l15_n203(x)
+ else
+ fun_l15_n240(x)
+ end
+end
+
+def fun_l14_n144(x)
+ if (x < 1)
+ fun_l15_n556(x)
+ else
+ fun_l15_n47(x)
+ end
+end
+
+def fun_l14_n145(x)
+ if (x < 1)
+ fun_l15_n340(x)
+ else
+ fun_l15_n511(x)
+ end
+end
+
+def fun_l14_n146(x)
+ if (x < 1)
+ fun_l15_n250(x)
+ else
+ fun_l15_n402(x)
+ end
+end
+
+def fun_l14_n147(x)
+ if (x < 1)
+ fun_l15_n4(x)
+ else
+ fun_l15_n26(x)
+ end
+end
+
+def fun_l14_n148(x)
+ if (x < 1)
+ fun_l15_n52(x)
+ else
+ fun_l15_n366(x)
+ end
+end
+
+def fun_l14_n149(x)
+ if (x < 1)
+ fun_l15_n163(x)
+ else
+ fun_l15_n884(x)
+ end
+end
+
+def fun_l14_n150(x)
+ if (x < 1)
+ fun_l15_n677(x)
+ else
+ fun_l15_n509(x)
+ end
+end
+
+def fun_l14_n151(x)
+ if (x < 1)
+ fun_l15_n949(x)
+ else
+ fun_l15_n393(x)
+ end
+end
+
+def fun_l14_n152(x)
+ if (x < 1)
+ fun_l15_n719(x)
+ else
+ fun_l15_n307(x)
+ end
+end
+
+def fun_l14_n153(x)
+ if (x < 1)
+ fun_l15_n12(x)
+ else
+ fun_l15_n985(x)
+ end
+end
+
+def fun_l14_n154(x)
+ if (x < 1)
+ fun_l15_n639(x)
+ else
+ fun_l15_n367(x)
+ end
+end
+
+def fun_l14_n155(x)
+ if (x < 1)
+ fun_l15_n401(x)
+ else
+ fun_l15_n431(x)
+ end
+end
+
+def fun_l14_n156(x)
+ if (x < 1)
+ fun_l15_n897(x)
+ else
+ fun_l15_n136(x)
+ end
+end
+
+def fun_l14_n157(x)
+ if (x < 1)
+ fun_l15_n792(x)
+ else
+ fun_l15_n865(x)
+ end
+end
+
+def fun_l14_n158(x)
+ if (x < 1)
+ fun_l15_n851(x)
+ else
+ fun_l15_n167(x)
+ end
+end
+
+def fun_l14_n159(x)
+ if (x < 1)
+ fun_l15_n643(x)
+ else
+ fun_l15_n458(x)
+ end
+end
+
+def fun_l14_n160(x)
+ if (x < 1)
+ fun_l15_n539(x)
+ else
+ fun_l15_n36(x)
+ end
+end
+
+def fun_l14_n161(x)
+ if (x < 1)
+ fun_l15_n91(x)
+ else
+ fun_l15_n130(x)
+ end
+end
+
+def fun_l14_n162(x)
+ if (x < 1)
+ fun_l15_n214(x)
+ else
+ fun_l15_n712(x)
+ end
+end
+
+def fun_l14_n163(x)
+ if (x < 1)
+ fun_l15_n47(x)
+ else
+ fun_l15_n799(x)
+ end
+end
+
+def fun_l14_n164(x)
+ if (x < 1)
+ fun_l15_n715(x)
+ else
+ fun_l15_n888(x)
+ end
+end
+
+def fun_l14_n165(x)
+ if (x < 1)
+ fun_l15_n904(x)
+ else
+ fun_l15_n484(x)
+ end
+end
+
+def fun_l14_n166(x)
+ if (x < 1)
+ fun_l15_n870(x)
+ else
+ fun_l15_n121(x)
+ end
+end
+
+def fun_l14_n167(x)
+ if (x < 1)
+ fun_l15_n960(x)
+ else
+ fun_l15_n33(x)
+ end
+end
+
+def fun_l14_n168(x)
+ if (x < 1)
+ fun_l15_n16(x)
+ else
+ fun_l15_n24(x)
+ end
+end
+
+def fun_l14_n169(x)
+ if (x < 1)
+ fun_l15_n913(x)
+ else
+ fun_l15_n793(x)
+ end
+end
+
+def fun_l14_n170(x)
+ if (x < 1)
+ fun_l15_n35(x)
+ else
+ fun_l15_n204(x)
+ end
+end
+
+def fun_l14_n171(x)
+ if (x < 1)
+ fun_l15_n526(x)
+ else
+ fun_l15_n92(x)
+ end
+end
+
+def fun_l14_n172(x)
+ if (x < 1)
+ fun_l15_n648(x)
+ else
+ fun_l15_n535(x)
+ end
+end
+
+def fun_l14_n173(x)
+ if (x < 1)
+ fun_l15_n415(x)
+ else
+ fun_l15_n610(x)
+ end
+end
+
+def fun_l14_n174(x)
+ if (x < 1)
+ fun_l15_n352(x)
+ else
+ fun_l15_n256(x)
+ end
+end
+
+def fun_l14_n175(x)
+ if (x < 1)
+ fun_l15_n692(x)
+ else
+ fun_l15_n686(x)
+ end
+end
+
+def fun_l14_n176(x)
+ if (x < 1)
+ fun_l15_n189(x)
+ else
+ fun_l15_n307(x)
+ end
+end
+
+def fun_l14_n177(x)
+ if (x < 1)
+ fun_l15_n725(x)
+ else
+ fun_l15_n714(x)
+ end
+end
+
+def fun_l14_n178(x)
+ if (x < 1)
+ fun_l15_n43(x)
+ else
+ fun_l15_n392(x)
+ end
+end
+
+def fun_l14_n179(x)
+ if (x < 1)
+ fun_l15_n890(x)
+ else
+ fun_l15_n887(x)
+ end
+end
+
+def fun_l14_n180(x)
+ if (x < 1)
+ fun_l15_n499(x)
+ else
+ fun_l15_n729(x)
+ end
+end
+
+def fun_l14_n181(x)
+ if (x < 1)
+ fun_l15_n714(x)
+ else
+ fun_l15_n417(x)
+ end
+end
+
+def fun_l14_n182(x)
+ if (x < 1)
+ fun_l15_n935(x)
+ else
+ fun_l15_n671(x)
+ end
+end
+
+def fun_l14_n183(x)
+ if (x < 1)
+ fun_l15_n123(x)
+ else
+ fun_l15_n349(x)
+ end
+end
+
+def fun_l14_n184(x)
+ if (x < 1)
+ fun_l15_n653(x)
+ else
+ fun_l15_n160(x)
+ end
+end
+
+def fun_l14_n185(x)
+ if (x < 1)
+ fun_l15_n43(x)
+ else
+ fun_l15_n965(x)
+ end
+end
+
+def fun_l14_n186(x)
+ if (x < 1)
+ fun_l15_n38(x)
+ else
+ fun_l15_n411(x)
+ end
+end
+
+def fun_l14_n187(x)
+ if (x < 1)
+ fun_l15_n788(x)
+ else
+ fun_l15_n297(x)
+ end
+end
+
+def fun_l14_n188(x)
+ if (x < 1)
+ fun_l15_n83(x)
+ else
+ fun_l15_n784(x)
+ end
+end
+
+def fun_l14_n189(x)
+ if (x < 1)
+ fun_l15_n403(x)
+ else
+ fun_l15_n469(x)
+ end
+end
+
+def fun_l14_n190(x)
+ if (x < 1)
+ fun_l15_n77(x)
+ else
+ fun_l15_n55(x)
+ end
+end
+
+def fun_l14_n191(x)
+ if (x < 1)
+ fun_l15_n835(x)
+ else
+ fun_l15_n462(x)
+ end
+end
+
+def fun_l14_n192(x)
+ if (x < 1)
+ fun_l15_n830(x)
+ else
+ fun_l15_n680(x)
+ end
+end
+
+def fun_l14_n193(x)
+ if (x < 1)
+ fun_l15_n750(x)
+ else
+ fun_l15_n580(x)
+ end
+end
+
+def fun_l14_n194(x)
+ if (x < 1)
+ fun_l15_n668(x)
+ else
+ fun_l15_n911(x)
+ end
+end
+
+def fun_l14_n195(x)
+ if (x < 1)
+ fun_l15_n90(x)
+ else
+ fun_l15_n232(x)
+ end
+end
+
+def fun_l14_n196(x)
+ if (x < 1)
+ fun_l15_n936(x)
+ else
+ fun_l15_n127(x)
+ end
+end
+
+def fun_l14_n197(x)
+ if (x < 1)
+ fun_l15_n566(x)
+ else
+ fun_l15_n687(x)
+ end
+end
+
+def fun_l14_n198(x)
+ if (x < 1)
+ fun_l15_n797(x)
+ else
+ fun_l15_n835(x)
+ end
+end
+
+def fun_l14_n199(x)
+ if (x < 1)
+ fun_l15_n96(x)
+ else
+ fun_l15_n917(x)
+ end
+end
+
+def fun_l14_n200(x)
+ if (x < 1)
+ fun_l15_n891(x)
+ else
+ fun_l15_n566(x)
+ end
+end
+
+def fun_l14_n201(x)
+ if (x < 1)
+ fun_l15_n697(x)
+ else
+ fun_l15_n218(x)
+ end
+end
+
+def fun_l14_n202(x)
+ if (x < 1)
+ fun_l15_n802(x)
+ else
+ fun_l15_n977(x)
+ end
+end
+
+def fun_l14_n203(x)
+ if (x < 1)
+ fun_l15_n38(x)
+ else
+ fun_l15_n992(x)
+ end
+end
+
+def fun_l14_n204(x)
+ if (x < 1)
+ fun_l15_n591(x)
+ else
+ fun_l15_n394(x)
+ end
+end
+
+def fun_l14_n205(x)
+ if (x < 1)
+ fun_l15_n552(x)
+ else
+ fun_l15_n522(x)
+ end
+end
+
+def fun_l14_n206(x)
+ if (x < 1)
+ fun_l15_n90(x)
+ else
+ fun_l15_n470(x)
+ end
+end
+
+def fun_l14_n207(x)
+ if (x < 1)
+ fun_l15_n92(x)
+ else
+ fun_l15_n148(x)
+ end
+end
+
+def fun_l14_n208(x)
+ if (x < 1)
+ fun_l15_n954(x)
+ else
+ fun_l15_n769(x)
+ end
+end
+
+def fun_l14_n209(x)
+ if (x < 1)
+ fun_l15_n32(x)
+ else
+ fun_l15_n211(x)
+ end
+end
+
+def fun_l14_n210(x)
+ if (x < 1)
+ fun_l15_n338(x)
+ else
+ fun_l15_n678(x)
+ end
+end
+
+def fun_l14_n211(x)
+ if (x < 1)
+ fun_l15_n113(x)
+ else
+ fun_l15_n605(x)
+ end
+end
+
+def fun_l14_n212(x)
+ if (x < 1)
+ fun_l15_n359(x)
+ else
+ fun_l15_n970(x)
+ end
+end
+
+def fun_l14_n213(x)
+ if (x < 1)
+ fun_l15_n437(x)
+ else
+ fun_l15_n279(x)
+ end
+end
+
+def fun_l14_n214(x)
+ if (x < 1)
+ fun_l15_n782(x)
+ else
+ fun_l15_n344(x)
+ end
+end
+
+def fun_l14_n215(x)
+ if (x < 1)
+ fun_l15_n501(x)
+ else
+ fun_l15_n19(x)
+ end
+end
+
+def fun_l14_n216(x)
+ if (x < 1)
+ fun_l15_n525(x)
+ else
+ fun_l15_n269(x)
+ end
+end
+
+def fun_l14_n217(x)
+ if (x < 1)
+ fun_l15_n35(x)
+ else
+ fun_l15_n786(x)
+ end
+end
+
+def fun_l14_n218(x)
+ if (x < 1)
+ fun_l15_n759(x)
+ else
+ fun_l15_n547(x)
+ end
+end
+
+def fun_l14_n219(x)
+ if (x < 1)
+ fun_l15_n260(x)
+ else
+ fun_l15_n155(x)
+ end
+end
+
+def fun_l14_n220(x)
+ if (x < 1)
+ fun_l15_n691(x)
+ else
+ fun_l15_n969(x)
+ end
+end
+
+def fun_l14_n221(x)
+ if (x < 1)
+ fun_l15_n632(x)
+ else
+ fun_l15_n803(x)
+ end
+end
+
+def fun_l14_n222(x)
+ if (x < 1)
+ fun_l15_n652(x)
+ else
+ fun_l15_n70(x)
+ end
+end
+
+def fun_l14_n223(x)
+ if (x < 1)
+ fun_l15_n710(x)
+ else
+ fun_l15_n873(x)
+ end
+end
+
+def fun_l14_n224(x)
+ if (x < 1)
+ fun_l15_n3(x)
+ else
+ fun_l15_n509(x)
+ end
+end
+
+def fun_l14_n225(x)
+ if (x < 1)
+ fun_l15_n37(x)
+ else
+ fun_l15_n814(x)
+ end
+end
+
+def fun_l14_n226(x)
+ if (x < 1)
+ fun_l15_n88(x)
+ else
+ fun_l15_n683(x)
+ end
+end
+
+def fun_l14_n227(x)
+ if (x < 1)
+ fun_l15_n898(x)
+ else
+ fun_l15_n996(x)
+ end
+end
+
+def fun_l14_n228(x)
+ if (x < 1)
+ fun_l15_n510(x)
+ else
+ fun_l15_n315(x)
+ end
+end
+
+def fun_l14_n229(x)
+ if (x < 1)
+ fun_l15_n509(x)
+ else
+ fun_l15_n75(x)
+ end
+end
+
+def fun_l14_n230(x)
+ if (x < 1)
+ fun_l15_n184(x)
+ else
+ fun_l15_n650(x)
+ end
+end
+
+def fun_l14_n231(x)
+ if (x < 1)
+ fun_l15_n227(x)
+ else
+ fun_l15_n607(x)
+ end
+end
+
+def fun_l14_n232(x)
+ if (x < 1)
+ fun_l15_n245(x)
+ else
+ fun_l15_n347(x)
+ end
+end
+
+def fun_l14_n233(x)
+ if (x < 1)
+ fun_l15_n728(x)
+ else
+ fun_l15_n457(x)
+ end
+end
+
+def fun_l14_n234(x)
+ if (x < 1)
+ fun_l15_n619(x)
+ else
+ fun_l15_n936(x)
+ end
+end
+
+def fun_l14_n235(x)
+ if (x < 1)
+ fun_l15_n855(x)
+ else
+ fun_l15_n774(x)
+ end
+end
+
+def fun_l14_n236(x)
+ if (x < 1)
+ fun_l15_n217(x)
+ else
+ fun_l15_n908(x)
+ end
+end
+
+def fun_l14_n237(x)
+ if (x < 1)
+ fun_l15_n537(x)
+ else
+ fun_l15_n441(x)
+ end
+end
+
+def fun_l14_n238(x)
+ if (x < 1)
+ fun_l15_n930(x)
+ else
+ fun_l15_n601(x)
+ end
+end
+
+def fun_l14_n239(x)
+ if (x < 1)
+ fun_l15_n976(x)
+ else
+ fun_l15_n903(x)
+ end
+end
+
+def fun_l14_n240(x)
+ if (x < 1)
+ fun_l15_n792(x)
+ else
+ fun_l15_n882(x)
+ end
+end
+
+def fun_l14_n241(x)
+ if (x < 1)
+ fun_l15_n662(x)
+ else
+ fun_l15_n197(x)
+ end
+end
+
+def fun_l14_n242(x)
+ if (x < 1)
+ fun_l15_n839(x)
+ else
+ fun_l15_n486(x)
+ end
+end
+
+def fun_l14_n243(x)
+ if (x < 1)
+ fun_l15_n122(x)
+ else
+ fun_l15_n165(x)
+ end
+end
+
+def fun_l14_n244(x)
+ if (x < 1)
+ fun_l15_n209(x)
+ else
+ fun_l15_n977(x)
+ end
+end
+
+def fun_l14_n245(x)
+ if (x < 1)
+ fun_l15_n231(x)
+ else
+ fun_l15_n318(x)
+ end
+end
+
+def fun_l14_n246(x)
+ if (x < 1)
+ fun_l15_n53(x)
+ else
+ fun_l15_n995(x)
+ end
+end
+
+def fun_l14_n247(x)
+ if (x < 1)
+ fun_l15_n276(x)
+ else
+ fun_l15_n458(x)
+ end
+end
+
+def fun_l14_n248(x)
+ if (x < 1)
+ fun_l15_n964(x)
+ else
+ fun_l15_n753(x)
+ end
+end
+
+def fun_l14_n249(x)
+ if (x < 1)
+ fun_l15_n964(x)
+ else
+ fun_l15_n783(x)
+ end
+end
+
+def fun_l14_n250(x)
+ if (x < 1)
+ fun_l15_n865(x)
+ else
+ fun_l15_n736(x)
+ end
+end
+
+def fun_l14_n251(x)
+ if (x < 1)
+ fun_l15_n861(x)
+ else
+ fun_l15_n414(x)
+ end
+end
+
+def fun_l14_n252(x)
+ if (x < 1)
+ fun_l15_n327(x)
+ else
+ fun_l15_n440(x)
+ end
+end
+
+def fun_l14_n253(x)
+ if (x < 1)
+ fun_l15_n800(x)
+ else
+ fun_l15_n186(x)
+ end
+end
+
+def fun_l14_n254(x)
+ if (x < 1)
+ fun_l15_n687(x)
+ else
+ fun_l15_n245(x)
+ end
+end
+
+def fun_l14_n255(x)
+ if (x < 1)
+ fun_l15_n421(x)
+ else
+ fun_l15_n421(x)
+ end
+end
+
+def fun_l14_n256(x)
+ if (x < 1)
+ fun_l15_n417(x)
+ else
+ fun_l15_n975(x)
+ end
+end
+
+def fun_l14_n257(x)
+ if (x < 1)
+ fun_l15_n835(x)
+ else
+ fun_l15_n697(x)
+ end
+end
+
+def fun_l14_n258(x)
+ if (x < 1)
+ fun_l15_n433(x)
+ else
+ fun_l15_n811(x)
+ end
+end
+
+def fun_l14_n259(x)
+ if (x < 1)
+ fun_l15_n473(x)
+ else
+ fun_l15_n747(x)
+ end
+end
+
+def fun_l14_n260(x)
+ if (x < 1)
+ fun_l15_n636(x)
+ else
+ fun_l15_n718(x)
+ end
+end
+
+def fun_l14_n261(x)
+ if (x < 1)
+ fun_l15_n472(x)
+ else
+ fun_l15_n971(x)
+ end
+end
+
+def fun_l14_n262(x)
+ if (x < 1)
+ fun_l15_n91(x)
+ else
+ fun_l15_n18(x)
+ end
+end
+
+def fun_l14_n263(x)
+ if (x < 1)
+ fun_l15_n582(x)
+ else
+ fun_l15_n629(x)
+ end
+end
+
+def fun_l14_n264(x)
+ if (x < 1)
+ fun_l15_n493(x)
+ else
+ fun_l15_n718(x)
+ end
+end
+
+def fun_l14_n265(x)
+ if (x < 1)
+ fun_l15_n857(x)
+ else
+ fun_l15_n134(x)
+ end
+end
+
+def fun_l14_n266(x)
+ if (x < 1)
+ fun_l15_n351(x)
+ else
+ fun_l15_n454(x)
+ end
+end
+
+def fun_l14_n267(x)
+ if (x < 1)
+ fun_l15_n578(x)
+ else
+ fun_l15_n453(x)
+ end
+end
+
+def fun_l14_n268(x)
+ if (x < 1)
+ fun_l15_n679(x)
+ else
+ fun_l15_n886(x)
+ end
+end
+
+def fun_l14_n269(x)
+ if (x < 1)
+ fun_l15_n446(x)
+ else
+ fun_l15_n7(x)
+ end
+end
+
+def fun_l14_n270(x)
+ if (x < 1)
+ fun_l15_n375(x)
+ else
+ fun_l15_n83(x)
+ end
+end
+
+def fun_l14_n271(x)
+ if (x < 1)
+ fun_l15_n688(x)
+ else
+ fun_l15_n863(x)
+ end
+end
+
+def fun_l14_n272(x)
+ if (x < 1)
+ fun_l15_n382(x)
+ else
+ fun_l15_n997(x)
+ end
+end
+
+def fun_l14_n273(x)
+ if (x < 1)
+ fun_l15_n281(x)
+ else
+ fun_l15_n909(x)
+ end
+end
+
+def fun_l14_n274(x)
+ if (x < 1)
+ fun_l15_n618(x)
+ else
+ fun_l15_n967(x)
+ end
+end
+
+def fun_l14_n275(x)
+ if (x < 1)
+ fun_l15_n651(x)
+ else
+ fun_l15_n826(x)
+ end
+end
+
+def fun_l14_n276(x)
+ if (x < 1)
+ fun_l15_n326(x)
+ else
+ fun_l15_n11(x)
+ end
+end
+
+def fun_l14_n277(x)
+ if (x < 1)
+ fun_l15_n193(x)
+ else
+ fun_l15_n719(x)
+ end
+end
+
+def fun_l14_n278(x)
+ if (x < 1)
+ fun_l15_n973(x)
+ else
+ fun_l15_n313(x)
+ end
+end
+
+def fun_l14_n279(x)
+ if (x < 1)
+ fun_l15_n33(x)
+ else
+ fun_l15_n526(x)
+ end
+end
+
+def fun_l14_n280(x)
+ if (x < 1)
+ fun_l15_n334(x)
+ else
+ fun_l15_n158(x)
+ end
+end
+
+def fun_l14_n281(x)
+ if (x < 1)
+ fun_l15_n627(x)
+ else
+ fun_l15_n346(x)
+ end
+end
+
+def fun_l14_n282(x)
+ if (x < 1)
+ fun_l15_n537(x)
+ else
+ fun_l15_n198(x)
+ end
+end
+
+def fun_l14_n283(x)
+ if (x < 1)
+ fun_l15_n779(x)
+ else
+ fun_l15_n0(x)
+ end
+end
+
+def fun_l14_n284(x)
+ if (x < 1)
+ fun_l15_n487(x)
+ else
+ fun_l15_n489(x)
+ end
+end
+
+def fun_l14_n285(x)
+ if (x < 1)
+ fun_l15_n793(x)
+ else
+ fun_l15_n803(x)
+ end
+end
+
+def fun_l14_n286(x)
+ if (x < 1)
+ fun_l15_n206(x)
+ else
+ fun_l15_n936(x)
+ end
+end
+
+def fun_l14_n287(x)
+ if (x < 1)
+ fun_l15_n223(x)
+ else
+ fun_l15_n278(x)
+ end
+end
+
+def fun_l14_n288(x)
+ if (x < 1)
+ fun_l15_n601(x)
+ else
+ fun_l15_n251(x)
+ end
+end
+
+def fun_l14_n289(x)
+ if (x < 1)
+ fun_l15_n144(x)
+ else
+ fun_l15_n420(x)
+ end
+end
+
+def fun_l14_n290(x)
+ if (x < 1)
+ fun_l15_n964(x)
+ else
+ fun_l15_n319(x)
+ end
+end
+
+def fun_l14_n291(x)
+ if (x < 1)
+ fun_l15_n385(x)
+ else
+ fun_l15_n498(x)
+ end
+end
+
+def fun_l14_n292(x)
+ if (x < 1)
+ fun_l15_n19(x)
+ else
+ fun_l15_n959(x)
+ end
+end
+
+def fun_l14_n293(x)
+ if (x < 1)
+ fun_l15_n77(x)
+ else
+ fun_l15_n849(x)
+ end
+end
+
+def fun_l14_n294(x)
+ if (x < 1)
+ fun_l15_n96(x)
+ else
+ fun_l15_n964(x)
+ end
+end
+
+def fun_l14_n295(x)
+ if (x < 1)
+ fun_l15_n374(x)
+ else
+ fun_l15_n337(x)
+ end
+end
+
+def fun_l14_n296(x)
+ if (x < 1)
+ fun_l15_n210(x)
+ else
+ fun_l15_n621(x)
+ end
+end
+
+def fun_l14_n297(x)
+ if (x < 1)
+ fun_l15_n992(x)
+ else
+ fun_l15_n90(x)
+ end
+end
+
+def fun_l14_n298(x)
+ if (x < 1)
+ fun_l15_n442(x)
+ else
+ fun_l15_n799(x)
+ end
+end
+
+def fun_l14_n299(x)
+ if (x < 1)
+ fun_l15_n133(x)
+ else
+ fun_l15_n21(x)
+ end
+end
+
+def fun_l14_n300(x)
+ if (x < 1)
+ fun_l15_n619(x)
+ else
+ fun_l15_n46(x)
+ end
+end
+
+def fun_l14_n301(x)
+ if (x < 1)
+ fun_l15_n359(x)
+ else
+ fun_l15_n386(x)
+ end
+end
+
+def fun_l14_n302(x)
+ if (x < 1)
+ fun_l15_n163(x)
+ else
+ fun_l15_n197(x)
+ end
+end
+
+def fun_l14_n303(x)
+ if (x < 1)
+ fun_l15_n382(x)
+ else
+ fun_l15_n693(x)
+ end
+end
+
+def fun_l14_n304(x)
+ if (x < 1)
+ fun_l15_n700(x)
+ else
+ fun_l15_n167(x)
+ end
+end
+
+def fun_l14_n305(x)
+ if (x < 1)
+ fun_l15_n124(x)
+ else
+ fun_l15_n448(x)
+ end
+end
+
+def fun_l14_n306(x)
+ if (x < 1)
+ fun_l15_n829(x)
+ else
+ fun_l15_n986(x)
+ end
+end
+
+def fun_l14_n307(x)
+ if (x < 1)
+ fun_l15_n39(x)
+ else
+ fun_l15_n557(x)
+ end
+end
+
+def fun_l14_n308(x)
+ if (x < 1)
+ fun_l15_n495(x)
+ else
+ fun_l15_n259(x)
+ end
+end
+
+def fun_l14_n309(x)
+ if (x < 1)
+ fun_l15_n462(x)
+ else
+ fun_l15_n121(x)
+ end
+end
+
+def fun_l14_n310(x)
+ if (x < 1)
+ fun_l15_n110(x)
+ else
+ fun_l15_n159(x)
+ end
+end
+
+def fun_l14_n311(x)
+ if (x < 1)
+ fun_l15_n144(x)
+ else
+ fun_l15_n969(x)
+ end
+end
+
+def fun_l14_n312(x)
+ if (x < 1)
+ fun_l15_n679(x)
+ else
+ fun_l15_n610(x)
+ end
+end
+
+def fun_l14_n313(x)
+ if (x < 1)
+ fun_l15_n332(x)
+ else
+ fun_l15_n759(x)
+ end
+end
+
+def fun_l14_n314(x)
+ if (x < 1)
+ fun_l15_n819(x)
+ else
+ fun_l15_n595(x)
+ end
+end
+
+def fun_l14_n315(x)
+ if (x < 1)
+ fun_l15_n180(x)
+ else
+ fun_l15_n555(x)
+ end
+end
+
+def fun_l14_n316(x)
+ if (x < 1)
+ fun_l15_n218(x)
+ else
+ fun_l15_n844(x)
+ end
+end
+
+def fun_l14_n317(x)
+ if (x < 1)
+ fun_l15_n486(x)
+ else
+ fun_l15_n666(x)
+ end
+end
+
+def fun_l14_n318(x)
+ if (x < 1)
+ fun_l15_n277(x)
+ else
+ fun_l15_n486(x)
+ end
+end
+
+def fun_l14_n319(x)
+ if (x < 1)
+ fun_l15_n874(x)
+ else
+ fun_l15_n802(x)
+ end
+end
+
+def fun_l14_n320(x)
+ if (x < 1)
+ fun_l15_n717(x)
+ else
+ fun_l15_n348(x)
+ end
+end
+
+def fun_l14_n321(x)
+ if (x < 1)
+ fun_l15_n701(x)
+ else
+ fun_l15_n897(x)
+ end
+end
+
+def fun_l14_n322(x)
+ if (x < 1)
+ fun_l15_n229(x)
+ else
+ fun_l15_n976(x)
+ end
+end
+
+def fun_l14_n323(x)
+ if (x < 1)
+ fun_l15_n288(x)
+ else
+ fun_l15_n801(x)
+ end
+end
+
+def fun_l14_n324(x)
+ if (x < 1)
+ fun_l15_n25(x)
+ else
+ fun_l15_n566(x)
+ end
+end
+
+def fun_l14_n325(x)
+ if (x < 1)
+ fun_l15_n489(x)
+ else
+ fun_l15_n165(x)
+ end
+end
+
+def fun_l14_n326(x)
+ if (x < 1)
+ fun_l15_n646(x)
+ else
+ fun_l15_n529(x)
+ end
+end
+
+def fun_l14_n327(x)
+ if (x < 1)
+ fun_l15_n126(x)
+ else
+ fun_l15_n247(x)
+ end
+end
+
+def fun_l14_n328(x)
+ if (x < 1)
+ fun_l15_n180(x)
+ else
+ fun_l15_n838(x)
+ end
+end
+
+def fun_l14_n329(x)
+ if (x < 1)
+ fun_l15_n827(x)
+ else
+ fun_l15_n251(x)
+ end
+end
+
+def fun_l14_n330(x)
+ if (x < 1)
+ fun_l15_n232(x)
+ else
+ fun_l15_n371(x)
+ end
+end
+
+def fun_l14_n331(x)
+ if (x < 1)
+ fun_l15_n742(x)
+ else
+ fun_l15_n365(x)
+ end
+end
+
+def fun_l14_n332(x)
+ if (x < 1)
+ fun_l15_n254(x)
+ else
+ fun_l15_n895(x)
+ end
+end
+
+def fun_l14_n333(x)
+ if (x < 1)
+ fun_l15_n267(x)
+ else
+ fun_l15_n716(x)
+ end
+end
+
+def fun_l14_n334(x)
+ if (x < 1)
+ fun_l15_n907(x)
+ else
+ fun_l15_n846(x)
+ end
+end
+
+def fun_l14_n335(x)
+ if (x < 1)
+ fun_l15_n432(x)
+ else
+ fun_l15_n207(x)
+ end
+end
+
+def fun_l14_n336(x)
+ if (x < 1)
+ fun_l15_n342(x)
+ else
+ fun_l15_n533(x)
+ end
+end
+
+def fun_l14_n337(x)
+ if (x < 1)
+ fun_l15_n155(x)
+ else
+ fun_l15_n626(x)
+ end
+end
+
+def fun_l14_n338(x)
+ if (x < 1)
+ fun_l15_n457(x)
+ else
+ fun_l15_n226(x)
+ end
+end
+
+def fun_l14_n339(x)
+ if (x < 1)
+ fun_l15_n621(x)
+ else
+ fun_l15_n685(x)
+ end
+end
+
+def fun_l14_n340(x)
+ if (x < 1)
+ fun_l15_n502(x)
+ else
+ fun_l15_n604(x)
+ end
+end
+
+def fun_l14_n341(x)
+ if (x < 1)
+ fun_l15_n578(x)
+ else
+ fun_l15_n250(x)
+ end
+end
+
+def fun_l14_n342(x)
+ if (x < 1)
+ fun_l15_n16(x)
+ else
+ fun_l15_n897(x)
+ end
+end
+
+def fun_l14_n343(x)
+ if (x < 1)
+ fun_l15_n173(x)
+ else
+ fun_l15_n441(x)
+ end
+end
+
+def fun_l14_n344(x)
+ if (x < 1)
+ fun_l15_n882(x)
+ else
+ fun_l15_n287(x)
+ end
+end
+
+def fun_l14_n345(x)
+ if (x < 1)
+ fun_l15_n549(x)
+ else
+ fun_l15_n559(x)
+ end
+end
+
+def fun_l14_n346(x)
+ if (x < 1)
+ fun_l15_n587(x)
+ else
+ fun_l15_n712(x)
+ end
+end
+
+def fun_l14_n347(x)
+ if (x < 1)
+ fun_l15_n2(x)
+ else
+ fun_l15_n279(x)
+ end
+end
+
+def fun_l14_n348(x)
+ if (x < 1)
+ fun_l15_n602(x)
+ else
+ fun_l15_n801(x)
+ end
+end
+
+def fun_l14_n349(x)
+ if (x < 1)
+ fun_l15_n114(x)
+ else
+ fun_l15_n181(x)
+ end
+end
+
+def fun_l14_n350(x)
+ if (x < 1)
+ fun_l15_n751(x)
+ else
+ fun_l15_n760(x)
+ end
+end
+
+def fun_l14_n351(x)
+ if (x < 1)
+ fun_l15_n570(x)
+ else
+ fun_l15_n168(x)
+ end
+end
+
+def fun_l14_n352(x)
+ if (x < 1)
+ fun_l15_n342(x)
+ else
+ fun_l15_n401(x)
+ end
+end
+
+def fun_l14_n353(x)
+ if (x < 1)
+ fun_l15_n775(x)
+ else
+ fun_l15_n175(x)
+ end
+end
+
+def fun_l14_n354(x)
+ if (x < 1)
+ fun_l15_n0(x)
+ else
+ fun_l15_n831(x)
+ end
+end
+
+def fun_l14_n355(x)
+ if (x < 1)
+ fun_l15_n127(x)
+ else
+ fun_l15_n751(x)
+ end
+end
+
+def fun_l14_n356(x)
+ if (x < 1)
+ fun_l15_n57(x)
+ else
+ fun_l15_n58(x)
+ end
+end
+
+def fun_l14_n357(x)
+ if (x < 1)
+ fun_l15_n696(x)
+ else
+ fun_l15_n694(x)
+ end
+end
+
+def fun_l14_n358(x)
+ if (x < 1)
+ fun_l15_n240(x)
+ else
+ fun_l15_n525(x)
+ end
+end
+
+def fun_l14_n359(x)
+ if (x < 1)
+ fun_l15_n552(x)
+ else
+ fun_l15_n126(x)
+ end
+end
+
+def fun_l14_n360(x)
+ if (x < 1)
+ fun_l15_n435(x)
+ else
+ fun_l15_n24(x)
+ end
+end
+
+def fun_l14_n361(x)
+ if (x < 1)
+ fun_l15_n366(x)
+ else
+ fun_l15_n397(x)
+ end
+end
+
+def fun_l14_n362(x)
+ if (x < 1)
+ fun_l15_n626(x)
+ else
+ fun_l15_n288(x)
+ end
+end
+
+def fun_l14_n363(x)
+ if (x < 1)
+ fun_l15_n474(x)
+ else
+ fun_l15_n205(x)
+ end
+end
+
+def fun_l14_n364(x)
+ if (x < 1)
+ fun_l15_n299(x)
+ else
+ fun_l15_n9(x)
+ end
+end
+
+def fun_l14_n365(x)
+ if (x < 1)
+ fun_l15_n115(x)
+ else
+ fun_l15_n126(x)
+ end
+end
+
+def fun_l14_n366(x)
+ if (x < 1)
+ fun_l15_n777(x)
+ else
+ fun_l15_n714(x)
+ end
+end
+
+def fun_l14_n367(x)
+ if (x < 1)
+ fun_l15_n697(x)
+ else
+ fun_l15_n663(x)
+ end
+end
+
+def fun_l14_n368(x)
+ if (x < 1)
+ fun_l15_n72(x)
+ else
+ fun_l15_n339(x)
+ end
+end
+
+def fun_l14_n369(x)
+ if (x < 1)
+ fun_l15_n703(x)
+ else
+ fun_l15_n901(x)
+ end
+end
+
+def fun_l14_n370(x)
+ if (x < 1)
+ fun_l15_n38(x)
+ else
+ fun_l15_n920(x)
+ end
+end
+
+def fun_l14_n371(x)
+ if (x < 1)
+ fun_l15_n97(x)
+ else
+ fun_l15_n418(x)
+ end
+end
+
+def fun_l14_n372(x)
+ if (x < 1)
+ fun_l15_n831(x)
+ else
+ fun_l15_n295(x)
+ end
+end
+
+def fun_l14_n373(x)
+ if (x < 1)
+ fun_l15_n849(x)
+ else
+ fun_l15_n818(x)
+ end
+end
+
+def fun_l14_n374(x)
+ if (x < 1)
+ fun_l15_n308(x)
+ else
+ fun_l15_n379(x)
+ end
+end
+
+def fun_l14_n375(x)
+ if (x < 1)
+ fun_l15_n552(x)
+ else
+ fun_l15_n109(x)
+ end
+end
+
+def fun_l14_n376(x)
+ if (x < 1)
+ fun_l15_n444(x)
+ else
+ fun_l15_n509(x)
+ end
+end
+
+def fun_l14_n377(x)
+ if (x < 1)
+ fun_l15_n498(x)
+ else
+ fun_l15_n363(x)
+ end
+end
+
+def fun_l14_n378(x)
+ if (x < 1)
+ fun_l15_n475(x)
+ else
+ fun_l15_n250(x)
+ end
+end
+
+def fun_l14_n379(x)
+ if (x < 1)
+ fun_l15_n635(x)
+ else
+ fun_l15_n550(x)
+ end
+end
+
+def fun_l14_n380(x)
+ if (x < 1)
+ fun_l15_n835(x)
+ else
+ fun_l15_n261(x)
+ end
+end
+
+def fun_l14_n381(x)
+ if (x < 1)
+ fun_l15_n903(x)
+ else
+ fun_l15_n492(x)
+ end
+end
+
+def fun_l14_n382(x)
+ if (x < 1)
+ fun_l15_n447(x)
+ else
+ fun_l15_n570(x)
+ end
+end
+
+def fun_l14_n383(x)
+ if (x < 1)
+ fun_l15_n785(x)
+ else
+ fun_l15_n711(x)
+ end
+end
+
+def fun_l14_n384(x)
+ if (x < 1)
+ fun_l15_n321(x)
+ else
+ fun_l15_n966(x)
+ end
+end
+
+def fun_l14_n385(x)
+ if (x < 1)
+ fun_l15_n786(x)
+ else
+ fun_l15_n667(x)
+ end
+end
+
+def fun_l14_n386(x)
+ if (x < 1)
+ fun_l15_n954(x)
+ else
+ fun_l15_n101(x)
+ end
+end
+
+def fun_l14_n387(x)
+ if (x < 1)
+ fun_l15_n868(x)
+ else
+ fun_l15_n1(x)
+ end
+end
+
+def fun_l14_n388(x)
+ if (x < 1)
+ fun_l15_n380(x)
+ else
+ fun_l15_n949(x)
+ end
+end
+
+def fun_l14_n389(x)
+ if (x < 1)
+ fun_l15_n456(x)
+ else
+ fun_l15_n122(x)
+ end
+end
+
+def fun_l14_n390(x)
+ if (x < 1)
+ fun_l15_n644(x)
+ else
+ fun_l15_n601(x)
+ end
+end
+
+def fun_l14_n391(x)
+ if (x < 1)
+ fun_l15_n523(x)
+ else
+ fun_l15_n754(x)
+ end
+end
+
+def fun_l14_n392(x)
+ if (x < 1)
+ fun_l15_n882(x)
+ else
+ fun_l15_n453(x)
+ end
+end
+
+def fun_l14_n393(x)
+ if (x < 1)
+ fun_l15_n249(x)
+ else
+ fun_l15_n773(x)
+ end
+end
+
+def fun_l14_n394(x)
+ if (x < 1)
+ fun_l15_n453(x)
+ else
+ fun_l15_n490(x)
+ end
+end
+
+def fun_l14_n395(x)
+ if (x < 1)
+ fun_l15_n699(x)
+ else
+ fun_l15_n95(x)
+ end
+end
+
+def fun_l14_n396(x)
+ if (x < 1)
+ fun_l15_n726(x)
+ else
+ fun_l15_n632(x)
+ end
+end
+
+def fun_l14_n397(x)
+ if (x < 1)
+ fun_l15_n139(x)
+ else
+ fun_l15_n682(x)
+ end
+end
+
+def fun_l14_n398(x)
+ if (x < 1)
+ fun_l15_n246(x)
+ else
+ fun_l15_n74(x)
+ end
+end
+
+def fun_l14_n399(x)
+ if (x < 1)
+ fun_l15_n334(x)
+ else
+ fun_l15_n504(x)
+ end
+end
+
+def fun_l14_n400(x)
+ if (x < 1)
+ fun_l15_n450(x)
+ else
+ fun_l15_n778(x)
+ end
+end
+
+def fun_l14_n401(x)
+ if (x < 1)
+ fun_l15_n428(x)
+ else
+ fun_l15_n101(x)
+ end
+end
+
+def fun_l14_n402(x)
+ if (x < 1)
+ fun_l15_n779(x)
+ else
+ fun_l15_n924(x)
+ end
+end
+
+def fun_l14_n403(x)
+ if (x < 1)
+ fun_l15_n957(x)
+ else
+ fun_l15_n83(x)
+ end
+end
+
+def fun_l14_n404(x)
+ if (x < 1)
+ fun_l15_n0(x)
+ else
+ fun_l15_n781(x)
+ end
+end
+
+def fun_l14_n405(x)
+ if (x < 1)
+ fun_l15_n100(x)
+ else
+ fun_l15_n21(x)
+ end
+end
+
+def fun_l14_n406(x)
+ if (x < 1)
+ fun_l15_n262(x)
+ else
+ fun_l15_n925(x)
+ end
+end
+
+def fun_l14_n407(x)
+ if (x < 1)
+ fun_l15_n935(x)
+ else
+ fun_l15_n193(x)
+ end
+end
+
+def fun_l14_n408(x)
+ if (x < 1)
+ fun_l15_n140(x)
+ else
+ fun_l15_n459(x)
+ end
+end
+
+def fun_l14_n409(x)
+ if (x < 1)
+ fun_l15_n484(x)
+ else
+ fun_l15_n584(x)
+ end
+end
+
+def fun_l14_n410(x)
+ if (x < 1)
+ fun_l15_n762(x)
+ else
+ fun_l15_n640(x)
+ end
+end
+
+def fun_l14_n411(x)
+ if (x < 1)
+ fun_l15_n347(x)
+ else
+ fun_l15_n395(x)
+ end
+end
+
+def fun_l14_n412(x)
+ if (x < 1)
+ fun_l15_n809(x)
+ else
+ fun_l15_n105(x)
+ end
+end
+
+def fun_l14_n413(x)
+ if (x < 1)
+ fun_l15_n929(x)
+ else
+ fun_l15_n265(x)
+ end
+end
+
+def fun_l14_n414(x)
+ if (x < 1)
+ fun_l15_n228(x)
+ else
+ fun_l15_n88(x)
+ end
+end
+
+def fun_l14_n415(x)
+ if (x < 1)
+ fun_l15_n650(x)
+ else
+ fun_l15_n785(x)
+ end
+end
+
+def fun_l14_n416(x)
+ if (x < 1)
+ fun_l15_n806(x)
+ else
+ fun_l15_n743(x)
+ end
+end
+
+def fun_l14_n417(x)
+ if (x < 1)
+ fun_l15_n417(x)
+ else
+ fun_l15_n454(x)
+ end
+end
+
+def fun_l14_n418(x)
+ if (x < 1)
+ fun_l15_n571(x)
+ else
+ fun_l15_n651(x)
+ end
+end
+
+def fun_l14_n419(x)
+ if (x < 1)
+ fun_l15_n341(x)
+ else
+ fun_l15_n242(x)
+ end
+end
+
+def fun_l14_n420(x)
+ if (x < 1)
+ fun_l15_n613(x)
+ else
+ fun_l15_n339(x)
+ end
+end
+
+def fun_l14_n421(x)
+ if (x < 1)
+ fun_l15_n657(x)
+ else
+ fun_l15_n759(x)
+ end
+end
+
+def fun_l14_n422(x)
+ if (x < 1)
+ fun_l15_n33(x)
+ else
+ fun_l15_n669(x)
+ end
+end
+
+def fun_l14_n423(x)
+ if (x < 1)
+ fun_l15_n628(x)
+ else
+ fun_l15_n963(x)
+ end
+end
+
+def fun_l14_n424(x)
+ if (x < 1)
+ fun_l15_n940(x)
+ else
+ fun_l15_n773(x)
+ end
+end
+
+def fun_l14_n425(x)
+ if (x < 1)
+ fun_l15_n489(x)
+ else
+ fun_l15_n625(x)
+ end
+end
+
+def fun_l14_n426(x)
+ if (x < 1)
+ fun_l15_n501(x)
+ else
+ fun_l15_n278(x)
+ end
+end
+
+def fun_l14_n427(x)
+ if (x < 1)
+ fun_l15_n620(x)
+ else
+ fun_l15_n426(x)
+ end
+end
+
+def fun_l14_n428(x)
+ if (x < 1)
+ fun_l15_n606(x)
+ else
+ fun_l15_n123(x)
+ end
+end
+
+def fun_l14_n429(x)
+ if (x < 1)
+ fun_l15_n622(x)
+ else
+ fun_l15_n873(x)
+ end
+end
+
+def fun_l14_n430(x)
+ if (x < 1)
+ fun_l15_n660(x)
+ else
+ fun_l15_n736(x)
+ end
+end
+
+def fun_l14_n431(x)
+ if (x < 1)
+ fun_l15_n927(x)
+ else
+ fun_l15_n893(x)
+ end
+end
+
+def fun_l14_n432(x)
+ if (x < 1)
+ fun_l15_n492(x)
+ else
+ fun_l15_n947(x)
+ end
+end
+
+def fun_l14_n433(x)
+ if (x < 1)
+ fun_l15_n164(x)
+ else
+ fun_l15_n853(x)
+ end
+end
+
+def fun_l14_n434(x)
+ if (x < 1)
+ fun_l15_n730(x)
+ else
+ fun_l15_n265(x)
+ end
+end
+
+def fun_l14_n435(x)
+ if (x < 1)
+ fun_l15_n548(x)
+ else
+ fun_l15_n272(x)
+ end
+end
+
+def fun_l14_n436(x)
+ if (x < 1)
+ fun_l15_n944(x)
+ else
+ fun_l15_n344(x)
+ end
+end
+
+def fun_l14_n437(x)
+ if (x < 1)
+ fun_l15_n931(x)
+ else
+ fun_l15_n376(x)
+ end
+end
+
+def fun_l14_n438(x)
+ if (x < 1)
+ fun_l15_n261(x)
+ else
+ fun_l15_n270(x)
+ end
+end
+
+def fun_l14_n439(x)
+ if (x < 1)
+ fun_l15_n705(x)
+ else
+ fun_l15_n700(x)
+ end
+end
+
+def fun_l14_n440(x)
+ if (x < 1)
+ fun_l15_n115(x)
+ else
+ fun_l15_n964(x)
+ end
+end
+
+def fun_l14_n441(x)
+ if (x < 1)
+ fun_l15_n396(x)
+ else
+ fun_l15_n780(x)
+ end
+end
+
+def fun_l14_n442(x)
+ if (x < 1)
+ fun_l15_n813(x)
+ else
+ fun_l15_n25(x)
+ end
+end
+
+def fun_l14_n443(x)
+ if (x < 1)
+ fun_l15_n405(x)
+ else
+ fun_l15_n264(x)
+ end
+end
+
+def fun_l14_n444(x)
+ if (x < 1)
+ fun_l15_n816(x)
+ else
+ fun_l15_n857(x)
+ end
+end
+
+def fun_l14_n445(x)
+ if (x < 1)
+ fun_l15_n191(x)
+ else
+ fun_l15_n886(x)
+ end
+end
+
+def fun_l14_n446(x)
+ if (x < 1)
+ fun_l15_n415(x)
+ else
+ fun_l15_n611(x)
+ end
+end
+
+def fun_l14_n447(x)
+ if (x < 1)
+ fun_l15_n473(x)
+ else
+ fun_l15_n701(x)
+ end
+end
+
+def fun_l14_n448(x)
+ if (x < 1)
+ fun_l15_n532(x)
+ else
+ fun_l15_n501(x)
+ end
+end
+
+def fun_l14_n449(x)
+ if (x < 1)
+ fun_l15_n731(x)
+ else
+ fun_l15_n631(x)
+ end
+end
+
+def fun_l14_n450(x)
+ if (x < 1)
+ fun_l15_n75(x)
+ else
+ fun_l15_n356(x)
+ end
+end
+
+def fun_l14_n451(x)
+ if (x < 1)
+ fun_l15_n614(x)
+ else
+ fun_l15_n600(x)
+ end
+end
+
+def fun_l14_n452(x)
+ if (x < 1)
+ fun_l15_n592(x)
+ else
+ fun_l15_n995(x)
+ end
+end
+
+def fun_l14_n453(x)
+ if (x < 1)
+ fun_l15_n712(x)
+ else
+ fun_l15_n815(x)
+ end
+end
+
+def fun_l14_n454(x)
+ if (x < 1)
+ fun_l15_n859(x)
+ else
+ fun_l15_n560(x)
+ end
+end
+
+def fun_l14_n455(x)
+ if (x < 1)
+ fun_l15_n665(x)
+ else
+ fun_l15_n408(x)
+ end
+end
+
+def fun_l14_n456(x)
+ if (x < 1)
+ fun_l15_n693(x)
+ else
+ fun_l15_n491(x)
+ end
+end
+
+def fun_l14_n457(x)
+ if (x < 1)
+ fun_l15_n29(x)
+ else
+ fun_l15_n515(x)
+ end
+end
+
+def fun_l14_n458(x)
+ if (x < 1)
+ fun_l15_n598(x)
+ else
+ fun_l15_n448(x)
+ end
+end
+
+def fun_l14_n459(x)
+ if (x < 1)
+ fun_l15_n937(x)
+ else
+ fun_l15_n199(x)
+ end
+end
+
+def fun_l14_n460(x)
+ if (x < 1)
+ fun_l15_n950(x)
+ else
+ fun_l15_n874(x)
+ end
+end
+
+def fun_l14_n461(x)
+ if (x < 1)
+ fun_l15_n38(x)
+ else
+ fun_l15_n650(x)
+ end
+end
+
+def fun_l14_n462(x)
+ if (x < 1)
+ fun_l15_n366(x)
+ else
+ fun_l15_n271(x)
+ end
+end
+
+def fun_l14_n463(x)
+ if (x < 1)
+ fun_l15_n21(x)
+ else
+ fun_l15_n690(x)
+ end
+end
+
+def fun_l14_n464(x)
+ if (x < 1)
+ fun_l15_n660(x)
+ else
+ fun_l15_n71(x)
+ end
+end
+
+def fun_l14_n465(x)
+ if (x < 1)
+ fun_l15_n889(x)
+ else
+ fun_l15_n324(x)
+ end
+end
+
+def fun_l14_n466(x)
+ if (x < 1)
+ fun_l15_n808(x)
+ else
+ fun_l15_n532(x)
+ end
+end
+
+def fun_l14_n467(x)
+ if (x < 1)
+ fun_l15_n72(x)
+ else
+ fun_l15_n52(x)
+ end
+end
+
+def fun_l14_n468(x)
+ if (x < 1)
+ fun_l15_n563(x)
+ else
+ fun_l15_n327(x)
+ end
+end
+
+def fun_l14_n469(x)
+ if (x < 1)
+ fun_l15_n570(x)
+ else
+ fun_l15_n794(x)
+ end
+end
+
+def fun_l14_n470(x)
+ if (x < 1)
+ fun_l15_n8(x)
+ else
+ fun_l15_n594(x)
+ end
+end
+
+def fun_l14_n471(x)
+ if (x < 1)
+ fun_l15_n859(x)
+ else
+ fun_l15_n519(x)
+ end
+end
+
+def fun_l14_n472(x)
+ if (x < 1)
+ fun_l15_n539(x)
+ else
+ fun_l15_n432(x)
+ end
+end
+
+def fun_l14_n473(x)
+ if (x < 1)
+ fun_l15_n795(x)
+ else
+ fun_l15_n916(x)
+ end
+end
+
+def fun_l14_n474(x)
+ if (x < 1)
+ fun_l15_n851(x)
+ else
+ fun_l15_n157(x)
+ end
+end
+
+def fun_l14_n475(x)
+ if (x < 1)
+ fun_l15_n274(x)
+ else
+ fun_l15_n678(x)
+ end
+end
+
+def fun_l14_n476(x)
+ if (x < 1)
+ fun_l15_n221(x)
+ else
+ fun_l15_n906(x)
+ end
+end
+
+def fun_l14_n477(x)
+ if (x < 1)
+ fun_l15_n116(x)
+ else
+ fun_l15_n778(x)
+ end
+end
+
+def fun_l14_n478(x)
+ if (x < 1)
+ fun_l15_n715(x)
+ else
+ fun_l15_n855(x)
+ end
+end
+
+def fun_l14_n479(x)
+ if (x < 1)
+ fun_l15_n705(x)
+ else
+ fun_l15_n935(x)
+ end
+end
+
+def fun_l14_n480(x)
+ if (x < 1)
+ fun_l15_n119(x)
+ else
+ fun_l15_n559(x)
+ end
+end
+
+def fun_l14_n481(x)
+ if (x < 1)
+ fun_l15_n996(x)
+ else
+ fun_l15_n768(x)
+ end
+end
+
+def fun_l14_n482(x)
+ if (x < 1)
+ fun_l15_n619(x)
+ else
+ fun_l15_n475(x)
+ end
+end
+
+def fun_l14_n483(x)
+ if (x < 1)
+ fun_l15_n189(x)
+ else
+ fun_l15_n398(x)
+ end
+end
+
+def fun_l14_n484(x)
+ if (x < 1)
+ fun_l15_n758(x)
+ else
+ fun_l15_n864(x)
+ end
+end
+
+def fun_l14_n485(x)
+ if (x < 1)
+ fun_l15_n508(x)
+ else
+ fun_l15_n393(x)
+ end
+end
+
+def fun_l14_n486(x)
+ if (x < 1)
+ fun_l15_n825(x)
+ else
+ fun_l15_n337(x)
+ end
+end
+
+def fun_l14_n487(x)
+ if (x < 1)
+ fun_l15_n449(x)
+ else
+ fun_l15_n389(x)
+ end
+end
+
+def fun_l14_n488(x)
+ if (x < 1)
+ fun_l15_n328(x)
+ else
+ fun_l15_n658(x)
+ end
+end
+
+def fun_l14_n489(x)
+ if (x < 1)
+ fun_l15_n138(x)
+ else
+ fun_l15_n938(x)
+ end
+end
+
+def fun_l14_n490(x)
+ if (x < 1)
+ fun_l15_n387(x)
+ else
+ fun_l15_n865(x)
+ end
+end
+
+def fun_l14_n491(x)
+ if (x < 1)
+ fun_l15_n621(x)
+ else
+ fun_l15_n516(x)
+ end
+end
+
+def fun_l14_n492(x)
+ if (x < 1)
+ fun_l15_n962(x)
+ else
+ fun_l15_n821(x)
+ end
+end
+
+def fun_l14_n493(x)
+ if (x < 1)
+ fun_l15_n544(x)
+ else
+ fun_l15_n625(x)
+ end
+end
+
+def fun_l14_n494(x)
+ if (x < 1)
+ fun_l15_n610(x)
+ else
+ fun_l15_n404(x)
+ end
+end
+
+def fun_l14_n495(x)
+ if (x < 1)
+ fun_l15_n329(x)
+ else
+ fun_l15_n537(x)
+ end
+end
+
+def fun_l14_n496(x)
+ if (x < 1)
+ fun_l15_n659(x)
+ else
+ fun_l15_n837(x)
+ end
+end
+
+def fun_l14_n497(x)
+ if (x < 1)
+ fun_l15_n974(x)
+ else
+ fun_l15_n55(x)
+ end
+end
+
+def fun_l14_n498(x)
+ if (x < 1)
+ fun_l15_n243(x)
+ else
+ fun_l15_n810(x)
+ end
+end
+
+def fun_l14_n499(x)
+ if (x < 1)
+ fun_l15_n260(x)
+ else
+ fun_l15_n412(x)
+ end
+end
+
+def fun_l14_n500(x)
+ if (x < 1)
+ fun_l15_n940(x)
+ else
+ fun_l15_n920(x)
+ end
+end
+
+def fun_l14_n501(x)
+ if (x < 1)
+ fun_l15_n829(x)
+ else
+ fun_l15_n877(x)
+ end
+end
+
+def fun_l14_n502(x)
+ if (x < 1)
+ fun_l15_n457(x)
+ else
+ fun_l15_n307(x)
+ end
+end
+
+def fun_l14_n503(x)
+ if (x < 1)
+ fun_l15_n301(x)
+ else
+ fun_l15_n812(x)
+ end
+end
+
+def fun_l14_n504(x)
+ if (x < 1)
+ fun_l15_n175(x)
+ else
+ fun_l15_n715(x)
+ end
+end
+
+def fun_l14_n505(x)
+ if (x < 1)
+ fun_l15_n897(x)
+ else
+ fun_l15_n103(x)
+ end
+end
+
+def fun_l14_n506(x)
+ if (x < 1)
+ fun_l15_n357(x)
+ else
+ fun_l15_n606(x)
+ end
+end
+
+def fun_l14_n507(x)
+ if (x < 1)
+ fun_l15_n974(x)
+ else
+ fun_l15_n389(x)
+ end
+end
+
+def fun_l14_n508(x)
+ if (x < 1)
+ fun_l15_n641(x)
+ else
+ fun_l15_n450(x)
+ end
+end
+
+def fun_l14_n509(x)
+ if (x < 1)
+ fun_l15_n4(x)
+ else
+ fun_l15_n533(x)
+ end
+end
+
+def fun_l14_n510(x)
+ if (x < 1)
+ fun_l15_n258(x)
+ else
+ fun_l15_n716(x)
+ end
+end
+
+def fun_l14_n511(x)
+ if (x < 1)
+ fun_l15_n919(x)
+ else
+ fun_l15_n881(x)
+ end
+end
+
+def fun_l14_n512(x)
+ if (x < 1)
+ fun_l15_n313(x)
+ else
+ fun_l15_n282(x)
+ end
+end
+
+def fun_l14_n513(x)
+ if (x < 1)
+ fun_l15_n116(x)
+ else
+ fun_l15_n861(x)
+ end
+end
+
+def fun_l14_n514(x)
+ if (x < 1)
+ fun_l15_n178(x)
+ else
+ fun_l15_n717(x)
+ end
+end
+
+def fun_l14_n515(x)
+ if (x < 1)
+ fun_l15_n896(x)
+ else
+ fun_l15_n583(x)
+ end
+end
+
+def fun_l14_n516(x)
+ if (x < 1)
+ fun_l15_n203(x)
+ else
+ fun_l15_n802(x)
+ end
+end
+
+def fun_l14_n517(x)
+ if (x < 1)
+ fun_l15_n810(x)
+ else
+ fun_l15_n34(x)
+ end
+end
+
+def fun_l14_n518(x)
+ if (x < 1)
+ fun_l15_n908(x)
+ else
+ fun_l15_n623(x)
+ end
+end
+
+def fun_l14_n519(x)
+ if (x < 1)
+ fun_l15_n954(x)
+ else
+ fun_l15_n411(x)
+ end
+end
+
+def fun_l14_n520(x)
+ if (x < 1)
+ fun_l15_n880(x)
+ else
+ fun_l15_n38(x)
+ end
+end
+
+def fun_l14_n521(x)
+ if (x < 1)
+ fun_l15_n954(x)
+ else
+ fun_l15_n917(x)
+ end
+end
+
+def fun_l14_n522(x)
+ if (x < 1)
+ fun_l15_n693(x)
+ else
+ fun_l15_n950(x)
+ end
+end
+
+def fun_l14_n523(x)
+ if (x < 1)
+ fun_l15_n654(x)
+ else
+ fun_l15_n27(x)
+ end
+end
+
+def fun_l14_n524(x)
+ if (x < 1)
+ fun_l15_n316(x)
+ else
+ fun_l15_n873(x)
+ end
+end
+
+def fun_l14_n525(x)
+ if (x < 1)
+ fun_l15_n554(x)
+ else
+ fun_l15_n656(x)
+ end
+end
+
+def fun_l14_n526(x)
+ if (x < 1)
+ fun_l15_n739(x)
+ else
+ fun_l15_n69(x)
+ end
+end
+
+def fun_l14_n527(x)
+ if (x < 1)
+ fun_l15_n851(x)
+ else
+ fun_l15_n366(x)
+ end
+end
+
+def fun_l14_n528(x)
+ if (x < 1)
+ fun_l15_n113(x)
+ else
+ fun_l15_n271(x)
+ end
+end
+
+def fun_l14_n529(x)
+ if (x < 1)
+ fun_l15_n652(x)
+ else
+ fun_l15_n831(x)
+ end
+end
+
+def fun_l14_n530(x)
+ if (x < 1)
+ fun_l15_n746(x)
+ else
+ fun_l15_n841(x)
+ end
+end
+
+def fun_l14_n531(x)
+ if (x < 1)
+ fun_l15_n758(x)
+ else
+ fun_l15_n893(x)
+ end
+end
+
+def fun_l14_n532(x)
+ if (x < 1)
+ fun_l15_n976(x)
+ else
+ fun_l15_n514(x)
+ end
+end
+
+def fun_l14_n533(x)
+ if (x < 1)
+ fun_l15_n375(x)
+ else
+ fun_l15_n84(x)
+ end
+end
+
+def fun_l14_n534(x)
+ if (x < 1)
+ fun_l15_n226(x)
+ else
+ fun_l15_n770(x)
+ end
+end
+
+def fun_l14_n535(x)
+ if (x < 1)
+ fun_l15_n106(x)
+ else
+ fun_l15_n230(x)
+ end
+end
+
+def fun_l14_n536(x)
+ if (x < 1)
+ fun_l15_n18(x)
+ else
+ fun_l15_n335(x)
+ end
+end
+
+def fun_l14_n537(x)
+ if (x < 1)
+ fun_l15_n755(x)
+ else
+ fun_l15_n16(x)
+ end
+end
+
+def fun_l14_n538(x)
+ if (x < 1)
+ fun_l15_n653(x)
+ else
+ fun_l15_n486(x)
+ end
+end
+
+def fun_l14_n539(x)
+ if (x < 1)
+ fun_l15_n665(x)
+ else
+ fun_l15_n768(x)
+ end
+end
+
+def fun_l14_n540(x)
+ if (x < 1)
+ fun_l15_n282(x)
+ else
+ fun_l15_n780(x)
+ end
+end
+
+def fun_l14_n541(x)
+ if (x < 1)
+ fun_l15_n633(x)
+ else
+ fun_l15_n240(x)
+ end
+end
+
+def fun_l14_n542(x)
+ if (x < 1)
+ fun_l15_n141(x)
+ else
+ fun_l15_n474(x)
+ end
+end
+
+def fun_l14_n543(x)
+ if (x < 1)
+ fun_l15_n80(x)
+ else
+ fun_l15_n708(x)
+ end
+end
+
+def fun_l14_n544(x)
+ if (x < 1)
+ fun_l15_n309(x)
+ else
+ fun_l15_n808(x)
+ end
+end
+
+def fun_l14_n545(x)
+ if (x < 1)
+ fun_l15_n744(x)
+ else
+ fun_l15_n51(x)
+ end
+end
+
+def fun_l14_n546(x)
+ if (x < 1)
+ fun_l15_n571(x)
+ else
+ fun_l15_n581(x)
+ end
+end
+
+def fun_l14_n547(x)
+ if (x < 1)
+ fun_l15_n272(x)
+ else
+ fun_l15_n867(x)
+ end
+end
+
+def fun_l14_n548(x)
+ if (x < 1)
+ fun_l15_n96(x)
+ else
+ fun_l15_n83(x)
+ end
+end
+
+def fun_l14_n549(x)
+ if (x < 1)
+ fun_l15_n828(x)
+ else
+ fun_l15_n109(x)
+ end
+end
+
+def fun_l14_n550(x)
+ if (x < 1)
+ fun_l15_n94(x)
+ else
+ fun_l15_n839(x)
+ end
+end
+
+def fun_l14_n551(x)
+ if (x < 1)
+ fun_l15_n704(x)
+ else
+ fun_l15_n88(x)
+ end
+end
+
+def fun_l14_n552(x)
+ if (x < 1)
+ fun_l15_n531(x)
+ else
+ fun_l15_n865(x)
+ end
+end
+
+def fun_l14_n553(x)
+ if (x < 1)
+ fun_l15_n506(x)
+ else
+ fun_l15_n16(x)
+ end
+end
+
+def fun_l14_n554(x)
+ if (x < 1)
+ fun_l15_n583(x)
+ else
+ fun_l15_n186(x)
+ end
+end
+
+def fun_l14_n555(x)
+ if (x < 1)
+ fun_l15_n673(x)
+ else
+ fun_l15_n560(x)
+ end
+end
+
+def fun_l14_n556(x)
+ if (x < 1)
+ fun_l15_n947(x)
+ else
+ fun_l15_n268(x)
+ end
+end
+
+def fun_l14_n557(x)
+ if (x < 1)
+ fun_l15_n88(x)
+ else
+ fun_l15_n43(x)
+ end
+end
+
+def fun_l14_n558(x)
+ if (x < 1)
+ fun_l15_n690(x)
+ else
+ fun_l15_n145(x)
+ end
+end
+
+def fun_l14_n559(x)
+ if (x < 1)
+ fun_l15_n24(x)
+ else
+ fun_l15_n631(x)
+ end
+end
+
+def fun_l14_n560(x)
+ if (x < 1)
+ fun_l15_n381(x)
+ else
+ fun_l15_n3(x)
+ end
+end
+
+def fun_l14_n561(x)
+ if (x < 1)
+ fun_l15_n954(x)
+ else
+ fun_l15_n816(x)
+ end
+end
+
+def fun_l14_n562(x)
+ if (x < 1)
+ fun_l15_n948(x)
+ else
+ fun_l15_n886(x)
+ end
+end
+
+def fun_l14_n563(x)
+ if (x < 1)
+ fun_l15_n749(x)
+ else
+ fun_l15_n558(x)
+ end
+end
+
+def fun_l14_n564(x)
+ if (x < 1)
+ fun_l15_n715(x)
+ else
+ fun_l15_n157(x)
+ end
+end
+
+def fun_l14_n565(x)
+ if (x < 1)
+ fun_l15_n674(x)
+ else
+ fun_l15_n643(x)
+ end
+end
+
+def fun_l14_n566(x)
+ if (x < 1)
+ fun_l15_n151(x)
+ else
+ fun_l15_n686(x)
+ end
+end
+
+def fun_l14_n567(x)
+ if (x < 1)
+ fun_l15_n362(x)
+ else
+ fun_l15_n37(x)
+ end
+end
+
+def fun_l14_n568(x)
+ if (x < 1)
+ fun_l15_n132(x)
+ else
+ fun_l15_n146(x)
+ end
+end
+
+def fun_l14_n569(x)
+ if (x < 1)
+ fun_l15_n32(x)
+ else
+ fun_l15_n203(x)
+ end
+end
+
+def fun_l14_n570(x)
+ if (x < 1)
+ fun_l15_n477(x)
+ else
+ fun_l15_n403(x)
+ end
+end
+
+def fun_l14_n571(x)
+ if (x < 1)
+ fun_l15_n976(x)
+ else
+ fun_l15_n632(x)
+ end
+end
+
+def fun_l14_n572(x)
+ if (x < 1)
+ fun_l15_n735(x)
+ else
+ fun_l15_n100(x)
+ end
+end
+
+def fun_l14_n573(x)
+ if (x < 1)
+ fun_l15_n186(x)
+ else
+ fun_l15_n83(x)
+ end
+end
+
+def fun_l14_n574(x)
+ if (x < 1)
+ fun_l15_n246(x)
+ else
+ fun_l15_n573(x)
+ end
+end
+
+def fun_l14_n575(x)
+ if (x < 1)
+ fun_l15_n316(x)
+ else
+ fun_l15_n618(x)
+ end
+end
+
+def fun_l14_n576(x)
+ if (x < 1)
+ fun_l15_n426(x)
+ else
+ fun_l15_n616(x)
+ end
+end
+
+def fun_l14_n577(x)
+ if (x < 1)
+ fun_l15_n810(x)
+ else
+ fun_l15_n817(x)
+ end
+end
+
+def fun_l14_n578(x)
+ if (x < 1)
+ fun_l15_n262(x)
+ else
+ fun_l15_n815(x)
+ end
+end
+
+def fun_l14_n579(x)
+ if (x < 1)
+ fun_l15_n851(x)
+ else
+ fun_l15_n524(x)
+ end
+end
+
+def fun_l14_n580(x)
+ if (x < 1)
+ fun_l15_n748(x)
+ else
+ fun_l15_n843(x)
+ end
+end
+
+def fun_l14_n581(x)
+ if (x < 1)
+ fun_l15_n284(x)
+ else
+ fun_l15_n108(x)
+ end
+end
+
+def fun_l14_n582(x)
+ if (x < 1)
+ fun_l15_n976(x)
+ else
+ fun_l15_n294(x)
+ end
+end
+
+def fun_l14_n583(x)
+ if (x < 1)
+ fun_l15_n609(x)
+ else
+ fun_l15_n866(x)
+ end
+end
+
+def fun_l14_n584(x)
+ if (x < 1)
+ fun_l15_n293(x)
+ else
+ fun_l15_n980(x)
+ end
+end
+
+def fun_l14_n585(x)
+ if (x < 1)
+ fun_l15_n548(x)
+ else
+ fun_l15_n319(x)
+ end
+end
+
+def fun_l14_n586(x)
+ if (x < 1)
+ fun_l15_n566(x)
+ else
+ fun_l15_n843(x)
+ end
+end
+
+def fun_l14_n587(x)
+ if (x < 1)
+ fun_l15_n963(x)
+ else
+ fun_l15_n120(x)
+ end
+end
+
+def fun_l14_n588(x)
+ if (x < 1)
+ fun_l15_n149(x)
+ else
+ fun_l15_n17(x)
+ end
+end
+
+def fun_l14_n589(x)
+ if (x < 1)
+ fun_l15_n11(x)
+ else
+ fun_l15_n396(x)
+ end
+end
+
+def fun_l14_n590(x)
+ if (x < 1)
+ fun_l15_n40(x)
+ else
+ fun_l15_n687(x)
+ end
+end
+
+def fun_l14_n591(x)
+ if (x < 1)
+ fun_l15_n617(x)
+ else
+ fun_l15_n564(x)
+ end
+end
+
+def fun_l14_n592(x)
+ if (x < 1)
+ fun_l15_n26(x)
+ else
+ fun_l15_n812(x)
+ end
+end
+
+def fun_l14_n593(x)
+ if (x < 1)
+ fun_l15_n890(x)
+ else
+ fun_l15_n403(x)
+ end
+end
+
+def fun_l14_n594(x)
+ if (x < 1)
+ fun_l15_n455(x)
+ else
+ fun_l15_n248(x)
+ end
+end
+
+def fun_l14_n595(x)
+ if (x < 1)
+ fun_l15_n880(x)
+ else
+ fun_l15_n488(x)
+ end
+end
+
+def fun_l14_n596(x)
+ if (x < 1)
+ fun_l15_n412(x)
+ else
+ fun_l15_n986(x)
+ end
+end
+
+def fun_l14_n597(x)
+ if (x < 1)
+ fun_l15_n487(x)
+ else
+ fun_l15_n75(x)
+ end
+end
+
+def fun_l14_n598(x)
+ if (x < 1)
+ fun_l15_n911(x)
+ else
+ fun_l15_n789(x)
+ end
+end
+
+def fun_l14_n599(x)
+ if (x < 1)
+ fun_l15_n856(x)
+ else
+ fun_l15_n773(x)
+ end
+end
+
+def fun_l14_n600(x)
+ if (x < 1)
+ fun_l15_n57(x)
+ else
+ fun_l15_n538(x)
+ end
+end
+
+def fun_l14_n601(x)
+ if (x < 1)
+ fun_l15_n828(x)
+ else
+ fun_l15_n165(x)
+ end
+end
+
+def fun_l14_n602(x)
+ if (x < 1)
+ fun_l15_n230(x)
+ else
+ fun_l15_n326(x)
+ end
+end
+
+def fun_l14_n603(x)
+ if (x < 1)
+ fun_l15_n463(x)
+ else
+ fun_l15_n906(x)
+ end
+end
+
+def fun_l14_n604(x)
+ if (x < 1)
+ fun_l15_n584(x)
+ else
+ fun_l15_n205(x)
+ end
+end
+
+def fun_l14_n605(x)
+ if (x < 1)
+ fun_l15_n243(x)
+ else
+ fun_l15_n0(x)
+ end
+end
+
+def fun_l14_n606(x)
+ if (x < 1)
+ fun_l15_n258(x)
+ else
+ fun_l15_n574(x)
+ end
+end
+
+def fun_l14_n607(x)
+ if (x < 1)
+ fun_l15_n821(x)
+ else
+ fun_l15_n786(x)
+ end
+end
+
+def fun_l14_n608(x)
+ if (x < 1)
+ fun_l15_n553(x)
+ else
+ fun_l15_n183(x)
+ end
+end
+
+def fun_l14_n609(x)
+ if (x < 1)
+ fun_l15_n853(x)
+ else
+ fun_l15_n600(x)
+ end
+end
+
+def fun_l14_n610(x)
+ if (x < 1)
+ fun_l15_n606(x)
+ else
+ fun_l15_n76(x)
+ end
+end
+
+def fun_l14_n611(x)
+ if (x < 1)
+ fun_l15_n488(x)
+ else
+ fun_l15_n313(x)
+ end
+end
+
+def fun_l14_n612(x)
+ if (x < 1)
+ fun_l15_n261(x)
+ else
+ fun_l15_n320(x)
+ end
+end
+
+def fun_l14_n613(x)
+ if (x < 1)
+ fun_l15_n410(x)
+ else
+ fun_l15_n225(x)
+ end
+end
+
+def fun_l14_n614(x)
+ if (x < 1)
+ fun_l15_n653(x)
+ else
+ fun_l15_n699(x)
+ end
+end
+
+def fun_l14_n615(x)
+ if (x < 1)
+ fun_l15_n917(x)
+ else
+ fun_l15_n199(x)
+ end
+end
+
+def fun_l14_n616(x)
+ if (x < 1)
+ fun_l15_n583(x)
+ else
+ fun_l15_n676(x)
+ end
+end
+
+def fun_l14_n617(x)
+ if (x < 1)
+ fun_l15_n708(x)
+ else
+ fun_l15_n323(x)
+ end
+end
+
+def fun_l14_n618(x)
+ if (x < 1)
+ fun_l15_n935(x)
+ else
+ fun_l15_n570(x)
+ end
+end
+
+def fun_l14_n619(x)
+ if (x < 1)
+ fun_l15_n440(x)
+ else
+ fun_l15_n765(x)
+ end
+end
+
+def fun_l14_n620(x)
+ if (x < 1)
+ fun_l15_n621(x)
+ else
+ fun_l15_n239(x)
+ end
+end
+
+def fun_l14_n621(x)
+ if (x < 1)
+ fun_l15_n498(x)
+ else
+ fun_l15_n586(x)
+ end
+end
+
+def fun_l14_n622(x)
+ if (x < 1)
+ fun_l15_n786(x)
+ else
+ fun_l15_n894(x)
+ end
+end
+
+def fun_l14_n623(x)
+ if (x < 1)
+ fun_l15_n637(x)
+ else
+ fun_l15_n502(x)
+ end
+end
+
+def fun_l14_n624(x)
+ if (x < 1)
+ fun_l15_n982(x)
+ else
+ fun_l15_n690(x)
+ end
+end
+
+def fun_l14_n625(x)
+ if (x < 1)
+ fun_l15_n696(x)
+ else
+ fun_l15_n407(x)
+ end
+end
+
+def fun_l14_n626(x)
+ if (x < 1)
+ fun_l15_n324(x)
+ else
+ fun_l15_n937(x)
+ end
+end
+
+def fun_l14_n627(x)
+ if (x < 1)
+ fun_l15_n223(x)
+ else
+ fun_l15_n538(x)
+ end
+end
+
+def fun_l14_n628(x)
+ if (x < 1)
+ fun_l15_n865(x)
+ else
+ fun_l15_n459(x)
+ end
+end
+
+def fun_l14_n629(x)
+ if (x < 1)
+ fun_l15_n990(x)
+ else
+ fun_l15_n602(x)
+ end
+end
+
+def fun_l14_n630(x)
+ if (x < 1)
+ fun_l15_n289(x)
+ else
+ fun_l15_n608(x)
+ end
+end
+
+def fun_l14_n631(x)
+ if (x < 1)
+ fun_l15_n802(x)
+ else
+ fun_l15_n254(x)
+ end
+end
+
+def fun_l14_n632(x)
+ if (x < 1)
+ fun_l15_n8(x)
+ else
+ fun_l15_n114(x)
+ end
+end
+
+def fun_l14_n633(x)
+ if (x < 1)
+ fun_l15_n91(x)
+ else
+ fun_l15_n130(x)
+ end
+end
+
+def fun_l14_n634(x)
+ if (x < 1)
+ fun_l15_n691(x)
+ else
+ fun_l15_n961(x)
+ end
+end
+
+def fun_l14_n635(x)
+ if (x < 1)
+ fun_l15_n590(x)
+ else
+ fun_l15_n739(x)
+ end
+end
+
+def fun_l14_n636(x)
+ if (x < 1)
+ fun_l15_n552(x)
+ else
+ fun_l15_n526(x)
+ end
+end
+
+def fun_l14_n637(x)
+ if (x < 1)
+ fun_l15_n741(x)
+ else
+ fun_l15_n506(x)
+ end
+end
+
+def fun_l14_n638(x)
+ if (x < 1)
+ fun_l15_n458(x)
+ else
+ fun_l15_n1(x)
+ end
+end
+
+def fun_l14_n639(x)
+ if (x < 1)
+ fun_l15_n933(x)
+ else
+ fun_l15_n500(x)
+ end
+end
+
+def fun_l14_n640(x)
+ if (x < 1)
+ fun_l15_n267(x)
+ else
+ fun_l15_n450(x)
+ end
+end
+
+def fun_l14_n641(x)
+ if (x < 1)
+ fun_l15_n51(x)
+ else
+ fun_l15_n591(x)
+ end
+end
+
+def fun_l14_n642(x)
+ if (x < 1)
+ fun_l15_n262(x)
+ else
+ fun_l15_n254(x)
+ end
+end
+
+def fun_l14_n643(x)
+ if (x < 1)
+ fun_l15_n320(x)
+ else
+ fun_l15_n610(x)
+ end
+end
+
+def fun_l14_n644(x)
+ if (x < 1)
+ fun_l15_n137(x)
+ else
+ fun_l15_n802(x)
+ end
+end
+
+def fun_l14_n645(x)
+ if (x < 1)
+ fun_l15_n365(x)
+ else
+ fun_l15_n779(x)
+ end
+end
+
+def fun_l14_n646(x)
+ if (x < 1)
+ fun_l15_n863(x)
+ else
+ fun_l15_n273(x)
+ end
+end
+
+def fun_l14_n647(x)
+ if (x < 1)
+ fun_l15_n334(x)
+ else
+ fun_l15_n519(x)
+ end
+end
+
+def fun_l14_n648(x)
+ if (x < 1)
+ fun_l15_n232(x)
+ else
+ fun_l15_n876(x)
+ end
+end
+
+def fun_l14_n649(x)
+ if (x < 1)
+ fun_l15_n850(x)
+ else
+ fun_l15_n51(x)
+ end
+end
+
+def fun_l14_n650(x)
+ if (x < 1)
+ fun_l15_n610(x)
+ else
+ fun_l15_n52(x)
+ end
+end
+
+def fun_l14_n651(x)
+ if (x < 1)
+ fun_l15_n701(x)
+ else
+ fun_l15_n143(x)
+ end
+end
+
+def fun_l14_n652(x)
+ if (x < 1)
+ fun_l15_n933(x)
+ else
+ fun_l15_n748(x)
+ end
+end
+
+def fun_l14_n653(x)
+ if (x < 1)
+ fun_l15_n280(x)
+ else
+ fun_l15_n632(x)
+ end
+end
+
+def fun_l14_n654(x)
+ if (x < 1)
+ fun_l15_n361(x)
+ else
+ fun_l15_n107(x)
+ end
+end
+
+def fun_l14_n655(x)
+ if (x < 1)
+ fun_l15_n743(x)
+ else
+ fun_l15_n899(x)
+ end
+end
+
+def fun_l14_n656(x)
+ if (x < 1)
+ fun_l15_n383(x)
+ else
+ fun_l15_n441(x)
+ end
+end
+
+def fun_l14_n657(x)
+ if (x < 1)
+ fun_l15_n244(x)
+ else
+ fun_l15_n349(x)
+ end
+end
+
+def fun_l14_n658(x)
+ if (x < 1)
+ fun_l15_n69(x)
+ else
+ fun_l15_n758(x)
+ end
+end
+
+def fun_l14_n659(x)
+ if (x < 1)
+ fun_l15_n570(x)
+ else
+ fun_l15_n760(x)
+ end
+end
+
+def fun_l14_n660(x)
+ if (x < 1)
+ fun_l15_n554(x)
+ else
+ fun_l15_n258(x)
+ end
+end
+
+def fun_l14_n661(x)
+ if (x < 1)
+ fun_l15_n417(x)
+ else
+ fun_l15_n934(x)
+ end
+end
+
+def fun_l14_n662(x)
+ if (x < 1)
+ fun_l15_n717(x)
+ else
+ fun_l15_n99(x)
+ end
+end
+
+def fun_l14_n663(x)
+ if (x < 1)
+ fun_l15_n882(x)
+ else
+ fun_l15_n515(x)
+ end
+end
+
+def fun_l14_n664(x)
+ if (x < 1)
+ fun_l15_n623(x)
+ else
+ fun_l15_n679(x)
+ end
+end
+
+def fun_l14_n665(x)
+ if (x < 1)
+ fun_l15_n974(x)
+ else
+ fun_l15_n127(x)
+ end
+end
+
+def fun_l14_n666(x)
+ if (x < 1)
+ fun_l15_n592(x)
+ else
+ fun_l15_n322(x)
+ end
+end
+
+def fun_l14_n667(x)
+ if (x < 1)
+ fun_l15_n698(x)
+ else
+ fun_l15_n670(x)
+ end
+end
+
+def fun_l14_n668(x)
+ if (x < 1)
+ fun_l15_n164(x)
+ else
+ fun_l15_n670(x)
+ end
+end
+
+def fun_l14_n669(x)
+ if (x < 1)
+ fun_l15_n837(x)
+ else
+ fun_l15_n113(x)
+ end
+end
+
+def fun_l14_n670(x)
+ if (x < 1)
+ fun_l15_n200(x)
+ else
+ fun_l15_n486(x)
+ end
+end
+
+def fun_l14_n671(x)
+ if (x < 1)
+ fun_l15_n593(x)
+ else
+ fun_l15_n822(x)
+ end
+end
+
+def fun_l14_n672(x)
+ if (x < 1)
+ fun_l15_n191(x)
+ else
+ fun_l15_n842(x)
+ end
+end
+
+def fun_l14_n673(x)
+ if (x < 1)
+ fun_l15_n391(x)
+ else
+ fun_l15_n119(x)
+ end
+end
+
+def fun_l14_n674(x)
+ if (x < 1)
+ fun_l15_n914(x)
+ else
+ fun_l15_n453(x)
+ end
+end
+
+def fun_l14_n675(x)
+ if (x < 1)
+ fun_l15_n73(x)
+ else
+ fun_l15_n366(x)
+ end
+end
+
+def fun_l14_n676(x)
+ if (x < 1)
+ fun_l15_n58(x)
+ else
+ fun_l15_n804(x)
+ end
+end
+
+def fun_l14_n677(x)
+ if (x < 1)
+ fun_l15_n905(x)
+ else
+ fun_l15_n969(x)
+ end
+end
+
+def fun_l14_n678(x)
+ if (x < 1)
+ fun_l15_n301(x)
+ else
+ fun_l15_n838(x)
+ end
+end
+
+def fun_l14_n679(x)
+ if (x < 1)
+ fun_l15_n14(x)
+ else
+ fun_l15_n567(x)
+ end
+end
+
+def fun_l14_n680(x)
+ if (x < 1)
+ fun_l15_n262(x)
+ else
+ fun_l15_n325(x)
+ end
+end
+
+def fun_l14_n681(x)
+ if (x < 1)
+ fun_l15_n985(x)
+ else
+ fun_l15_n181(x)
+ end
+end
+
+def fun_l14_n682(x)
+ if (x < 1)
+ fun_l15_n197(x)
+ else
+ fun_l15_n175(x)
+ end
+end
+
+def fun_l14_n683(x)
+ if (x < 1)
+ fun_l15_n714(x)
+ else
+ fun_l15_n276(x)
+ end
+end
+
+def fun_l14_n684(x)
+ if (x < 1)
+ fun_l15_n720(x)
+ else
+ fun_l15_n517(x)
+ end
+end
+
+def fun_l14_n685(x)
+ if (x < 1)
+ fun_l15_n351(x)
+ else
+ fun_l15_n917(x)
+ end
+end
+
+def fun_l14_n686(x)
+ if (x < 1)
+ fun_l15_n199(x)
+ else
+ fun_l15_n163(x)
+ end
+end
+
+def fun_l14_n687(x)
+ if (x < 1)
+ fun_l15_n769(x)
+ else
+ fun_l15_n205(x)
+ end
+end
+
+def fun_l14_n688(x)
+ if (x < 1)
+ fun_l15_n840(x)
+ else
+ fun_l15_n756(x)
+ end
+end
+
+def fun_l14_n689(x)
+ if (x < 1)
+ fun_l15_n306(x)
+ else
+ fun_l15_n273(x)
+ end
+end
+
+def fun_l14_n690(x)
+ if (x < 1)
+ fun_l15_n549(x)
+ else
+ fun_l15_n192(x)
+ end
+end
+
+def fun_l14_n691(x)
+ if (x < 1)
+ fun_l15_n167(x)
+ else
+ fun_l15_n403(x)
+ end
+end
+
+def fun_l14_n692(x)
+ if (x < 1)
+ fun_l15_n175(x)
+ else
+ fun_l15_n361(x)
+ end
+end
+
+def fun_l14_n693(x)
+ if (x < 1)
+ fun_l15_n208(x)
+ else
+ fun_l15_n582(x)
+ end
+end
+
+def fun_l14_n694(x)
+ if (x < 1)
+ fun_l15_n347(x)
+ else
+ fun_l15_n962(x)
+ end
+end
+
+def fun_l14_n695(x)
+ if (x < 1)
+ fun_l15_n381(x)
+ else
+ fun_l15_n865(x)
+ end
+end
+
+def fun_l14_n696(x)
+ if (x < 1)
+ fun_l15_n76(x)
+ else
+ fun_l15_n140(x)
+ end
+end
+
+def fun_l14_n697(x)
+ if (x < 1)
+ fun_l15_n801(x)
+ else
+ fun_l15_n267(x)
+ end
+end
+
+def fun_l14_n698(x)
+ if (x < 1)
+ fun_l15_n137(x)
+ else
+ fun_l15_n518(x)
+ end
+end
+
+def fun_l14_n699(x)
+ if (x < 1)
+ fun_l15_n56(x)
+ else
+ fun_l15_n758(x)
+ end
+end
+
+def fun_l14_n700(x)
+ if (x < 1)
+ fun_l15_n178(x)
+ else
+ fun_l15_n641(x)
+ end
+end
+
+def fun_l14_n701(x)
+ if (x < 1)
+ fun_l15_n815(x)
+ else
+ fun_l15_n692(x)
+ end
+end
+
+def fun_l14_n702(x)
+ if (x < 1)
+ fun_l15_n355(x)
+ else
+ fun_l15_n338(x)
+ end
+end
+
+def fun_l14_n703(x)
+ if (x < 1)
+ fun_l15_n894(x)
+ else
+ fun_l15_n843(x)
+ end
+end
+
+def fun_l14_n704(x)
+ if (x < 1)
+ fun_l15_n728(x)
+ else
+ fun_l15_n140(x)
+ end
+end
+
+def fun_l14_n705(x)
+ if (x < 1)
+ fun_l15_n304(x)
+ else
+ fun_l15_n237(x)
+ end
+end
+
+def fun_l14_n706(x)
+ if (x < 1)
+ fun_l15_n57(x)
+ else
+ fun_l15_n947(x)
+ end
+end
+
+def fun_l14_n707(x)
+ if (x < 1)
+ fun_l15_n90(x)
+ else
+ fun_l15_n831(x)
+ end
+end
+
+def fun_l14_n708(x)
+ if (x < 1)
+ fun_l15_n487(x)
+ else
+ fun_l15_n937(x)
+ end
+end
+
+def fun_l14_n709(x)
+ if (x < 1)
+ fun_l15_n898(x)
+ else
+ fun_l15_n151(x)
+ end
+end
+
+def fun_l14_n710(x)
+ if (x < 1)
+ fun_l15_n306(x)
+ else
+ fun_l15_n687(x)
+ end
+end
+
+def fun_l14_n711(x)
+ if (x < 1)
+ fun_l15_n151(x)
+ else
+ fun_l15_n239(x)
+ end
+end
+
+def fun_l14_n712(x)
+ if (x < 1)
+ fun_l15_n512(x)
+ else
+ fun_l15_n203(x)
+ end
+end
+
+def fun_l14_n713(x)
+ if (x < 1)
+ fun_l15_n611(x)
+ else
+ fun_l15_n474(x)
+ end
+end
+
+def fun_l14_n714(x)
+ if (x < 1)
+ fun_l15_n109(x)
+ else
+ fun_l15_n149(x)
+ end
+end
+
+def fun_l14_n715(x)
+ if (x < 1)
+ fun_l15_n187(x)
+ else
+ fun_l15_n563(x)
+ end
+end
+
+def fun_l14_n716(x)
+ if (x < 1)
+ fun_l15_n877(x)
+ else
+ fun_l15_n644(x)
+ end
+end
+
+def fun_l14_n717(x)
+ if (x < 1)
+ fun_l15_n960(x)
+ else
+ fun_l15_n471(x)
+ end
+end
+
+def fun_l14_n718(x)
+ if (x < 1)
+ fun_l15_n250(x)
+ else
+ fun_l15_n93(x)
+ end
+end
+
+def fun_l14_n719(x)
+ if (x < 1)
+ fun_l15_n177(x)
+ else
+ fun_l15_n14(x)
+ end
+end
+
+def fun_l14_n720(x)
+ if (x < 1)
+ fun_l15_n912(x)
+ else
+ fun_l15_n95(x)
+ end
+end
+
+def fun_l14_n721(x)
+ if (x < 1)
+ fun_l15_n776(x)
+ else
+ fun_l15_n256(x)
+ end
+end
+
+def fun_l14_n722(x)
+ if (x < 1)
+ fun_l15_n968(x)
+ else
+ fun_l15_n857(x)
+ end
+end
+
+def fun_l14_n723(x)
+ if (x < 1)
+ fun_l15_n402(x)
+ else
+ fun_l15_n60(x)
+ end
+end
+
+def fun_l14_n724(x)
+ if (x < 1)
+ fun_l15_n345(x)
+ else
+ fun_l15_n688(x)
+ end
+end
+
+def fun_l14_n725(x)
+ if (x < 1)
+ fun_l15_n72(x)
+ else
+ fun_l15_n943(x)
+ end
+end
+
+def fun_l14_n726(x)
+ if (x < 1)
+ fun_l15_n535(x)
+ else
+ fun_l15_n916(x)
+ end
+end
+
+def fun_l14_n727(x)
+ if (x < 1)
+ fun_l15_n717(x)
+ else
+ fun_l15_n354(x)
+ end
+end
+
+def fun_l14_n728(x)
+ if (x < 1)
+ fun_l15_n679(x)
+ else
+ fun_l15_n348(x)
+ end
+end
+
+def fun_l14_n729(x)
+ if (x < 1)
+ fun_l15_n187(x)
+ else
+ fun_l15_n910(x)
+ end
+end
+
+def fun_l14_n730(x)
+ if (x < 1)
+ fun_l15_n151(x)
+ else
+ fun_l15_n689(x)
+ end
+end
+
+def fun_l14_n731(x)
+ if (x < 1)
+ fun_l15_n653(x)
+ else
+ fun_l15_n380(x)
+ end
+end
+
+def fun_l14_n732(x)
+ if (x < 1)
+ fun_l15_n627(x)
+ else
+ fun_l15_n214(x)
+ end
+end
+
+def fun_l14_n733(x)
+ if (x < 1)
+ fun_l15_n53(x)
+ else
+ fun_l15_n882(x)
+ end
+end
+
+def fun_l14_n734(x)
+ if (x < 1)
+ fun_l15_n628(x)
+ else
+ fun_l15_n632(x)
+ end
+end
+
+def fun_l14_n735(x)
+ if (x < 1)
+ fun_l15_n415(x)
+ else
+ fun_l15_n719(x)
+ end
+end
+
+def fun_l14_n736(x)
+ if (x < 1)
+ fun_l15_n474(x)
+ else
+ fun_l15_n966(x)
+ end
+end
+
+def fun_l14_n737(x)
+ if (x < 1)
+ fun_l15_n140(x)
+ else
+ fun_l15_n79(x)
+ end
+end
+
+def fun_l14_n738(x)
+ if (x < 1)
+ fun_l15_n682(x)
+ else
+ fun_l15_n788(x)
+ end
+end
+
+def fun_l14_n739(x)
+ if (x < 1)
+ fun_l15_n62(x)
+ else
+ fun_l15_n289(x)
+ end
+end
+
+def fun_l14_n740(x)
+ if (x < 1)
+ fun_l15_n256(x)
+ else
+ fun_l15_n53(x)
+ end
+end
+
+def fun_l14_n741(x)
+ if (x < 1)
+ fun_l15_n571(x)
+ else
+ fun_l15_n912(x)
+ end
+end
+
+def fun_l14_n742(x)
+ if (x < 1)
+ fun_l15_n477(x)
+ else
+ fun_l15_n757(x)
+ end
+end
+
+def fun_l14_n743(x)
+ if (x < 1)
+ fun_l15_n914(x)
+ else
+ fun_l15_n216(x)
+ end
+end
+
+def fun_l14_n744(x)
+ if (x < 1)
+ fun_l15_n474(x)
+ else
+ fun_l15_n860(x)
+ end
+end
+
+def fun_l14_n745(x)
+ if (x < 1)
+ fun_l15_n303(x)
+ else
+ fun_l15_n417(x)
+ end
+end
+
+def fun_l14_n746(x)
+ if (x < 1)
+ fun_l15_n601(x)
+ else
+ fun_l15_n872(x)
+ end
+end
+
+def fun_l14_n747(x)
+ if (x < 1)
+ fun_l15_n70(x)
+ else
+ fun_l15_n245(x)
+ end
+end
+
+def fun_l14_n748(x)
+ if (x < 1)
+ fun_l15_n628(x)
+ else
+ fun_l15_n503(x)
+ end
+end
+
+def fun_l14_n749(x)
+ if (x < 1)
+ fun_l15_n965(x)
+ else
+ fun_l15_n89(x)
+ end
+end
+
+def fun_l14_n750(x)
+ if (x < 1)
+ fun_l15_n910(x)
+ else
+ fun_l15_n386(x)
+ end
+end
+
+def fun_l14_n751(x)
+ if (x < 1)
+ fun_l15_n444(x)
+ else
+ fun_l15_n765(x)
+ end
+end
+
+def fun_l14_n752(x)
+ if (x < 1)
+ fun_l15_n481(x)
+ else
+ fun_l15_n356(x)
+ end
+end
+
+def fun_l14_n753(x)
+ if (x < 1)
+ fun_l15_n45(x)
+ else
+ fun_l15_n644(x)
+ end
+end
+
+def fun_l14_n754(x)
+ if (x < 1)
+ fun_l15_n262(x)
+ else
+ fun_l15_n681(x)
+ end
+end
+
+def fun_l14_n755(x)
+ if (x < 1)
+ fun_l15_n984(x)
+ else
+ fun_l15_n488(x)
+ end
+end
+
+def fun_l14_n756(x)
+ if (x < 1)
+ fun_l15_n751(x)
+ else
+ fun_l15_n165(x)
+ end
+end
+
+def fun_l14_n757(x)
+ if (x < 1)
+ fun_l15_n716(x)
+ else
+ fun_l15_n483(x)
+ end
+end
+
+def fun_l14_n758(x)
+ if (x < 1)
+ fun_l15_n863(x)
+ else
+ fun_l15_n841(x)
+ end
+end
+
+def fun_l14_n759(x)
+ if (x < 1)
+ fun_l15_n654(x)
+ else
+ fun_l15_n782(x)
+ end
+end
+
+def fun_l14_n760(x)
+ if (x < 1)
+ fun_l15_n390(x)
+ else
+ fun_l15_n254(x)
+ end
+end
+
+def fun_l14_n761(x)
+ if (x < 1)
+ fun_l15_n888(x)
+ else
+ fun_l15_n739(x)
+ end
+end
+
+def fun_l14_n762(x)
+ if (x < 1)
+ fun_l15_n775(x)
+ else
+ fun_l15_n310(x)
+ end
+end
+
+def fun_l14_n763(x)
+ if (x < 1)
+ fun_l15_n713(x)
+ else
+ fun_l15_n246(x)
+ end
+end
+
+def fun_l14_n764(x)
+ if (x < 1)
+ fun_l15_n318(x)
+ else
+ fun_l15_n121(x)
+ end
+end
+
+def fun_l14_n765(x)
+ if (x < 1)
+ fun_l15_n424(x)
+ else
+ fun_l15_n538(x)
+ end
+end
+
+def fun_l14_n766(x)
+ if (x < 1)
+ fun_l15_n58(x)
+ else
+ fun_l15_n487(x)
+ end
+end
+
+def fun_l14_n767(x)
+ if (x < 1)
+ fun_l15_n48(x)
+ else
+ fun_l15_n776(x)
+ end
+end
+
+def fun_l14_n768(x)
+ if (x < 1)
+ fun_l15_n156(x)
+ else
+ fun_l15_n340(x)
+ end
+end
+
+def fun_l14_n769(x)
+ if (x < 1)
+ fun_l15_n66(x)
+ else
+ fun_l15_n655(x)
+ end
+end
+
+def fun_l14_n770(x)
+ if (x < 1)
+ fun_l15_n15(x)
+ else
+ fun_l15_n392(x)
+ end
+end
+
+def fun_l14_n771(x)
+ if (x < 1)
+ fun_l15_n331(x)
+ else
+ fun_l15_n114(x)
+ end
+end
+
+def fun_l14_n772(x)
+ if (x < 1)
+ fun_l15_n267(x)
+ else
+ fun_l15_n711(x)
+ end
+end
+
+def fun_l14_n773(x)
+ if (x < 1)
+ fun_l15_n567(x)
+ else
+ fun_l15_n869(x)
+ end
+end
+
+def fun_l14_n774(x)
+ if (x < 1)
+ fun_l15_n915(x)
+ else
+ fun_l15_n594(x)
+ end
+end
+
+def fun_l14_n775(x)
+ if (x < 1)
+ fun_l15_n139(x)
+ else
+ fun_l15_n285(x)
+ end
+end
+
+def fun_l14_n776(x)
+ if (x < 1)
+ fun_l15_n994(x)
+ else
+ fun_l15_n116(x)
+ end
+end
+
+def fun_l14_n777(x)
+ if (x < 1)
+ fun_l15_n999(x)
+ else
+ fun_l15_n356(x)
+ end
+end
+
+def fun_l14_n778(x)
+ if (x < 1)
+ fun_l15_n46(x)
+ else
+ fun_l15_n845(x)
+ end
+end
+
+def fun_l14_n779(x)
+ if (x < 1)
+ fun_l15_n313(x)
+ else
+ fun_l15_n785(x)
+ end
+end
+
+def fun_l14_n780(x)
+ if (x < 1)
+ fun_l15_n282(x)
+ else
+ fun_l15_n489(x)
+ end
+end
+
+def fun_l14_n781(x)
+ if (x < 1)
+ fun_l15_n101(x)
+ else
+ fun_l15_n928(x)
+ end
+end
+
+def fun_l14_n782(x)
+ if (x < 1)
+ fun_l15_n307(x)
+ else
+ fun_l15_n808(x)
+ end
+end
+
+def fun_l14_n783(x)
+ if (x < 1)
+ fun_l15_n475(x)
+ else
+ fun_l15_n347(x)
+ end
+end
+
+def fun_l14_n784(x)
+ if (x < 1)
+ fun_l15_n404(x)
+ else
+ fun_l15_n65(x)
+ end
+end
+
+def fun_l14_n785(x)
+ if (x < 1)
+ fun_l15_n61(x)
+ else
+ fun_l15_n145(x)
+ end
+end
+
+def fun_l14_n786(x)
+ if (x < 1)
+ fun_l15_n919(x)
+ else
+ fun_l15_n700(x)
+ end
+end
+
+def fun_l14_n787(x)
+ if (x < 1)
+ fun_l15_n333(x)
+ else
+ fun_l15_n702(x)
+ end
+end
+
+def fun_l14_n788(x)
+ if (x < 1)
+ fun_l15_n924(x)
+ else
+ fun_l15_n354(x)
+ end
+end
+
+def fun_l14_n789(x)
+ if (x < 1)
+ fun_l15_n171(x)
+ else
+ fun_l15_n643(x)
+ end
+end
+
+def fun_l14_n790(x)
+ if (x < 1)
+ fun_l15_n852(x)
+ else
+ fun_l15_n421(x)
+ end
+end
+
+def fun_l14_n791(x)
+ if (x < 1)
+ fun_l15_n706(x)
+ else
+ fun_l15_n260(x)
+ end
+end
+
+def fun_l14_n792(x)
+ if (x < 1)
+ fun_l15_n908(x)
+ else
+ fun_l15_n145(x)
+ end
+end
+
+def fun_l14_n793(x)
+ if (x < 1)
+ fun_l15_n802(x)
+ else
+ fun_l15_n365(x)
+ end
+end
+
+def fun_l14_n794(x)
+ if (x < 1)
+ fun_l15_n727(x)
+ else
+ fun_l15_n758(x)
+ end
+end
+
+def fun_l14_n795(x)
+ if (x < 1)
+ fun_l15_n463(x)
+ else
+ fun_l15_n58(x)
+ end
+end
+
+def fun_l14_n796(x)
+ if (x < 1)
+ fun_l15_n413(x)
+ else
+ fun_l15_n525(x)
+ end
+end
+
+def fun_l14_n797(x)
+ if (x < 1)
+ fun_l15_n970(x)
+ else
+ fun_l15_n480(x)
+ end
+end
+
+def fun_l14_n798(x)
+ if (x < 1)
+ fun_l15_n476(x)
+ else
+ fun_l15_n316(x)
+ end
+end
+
+def fun_l14_n799(x)
+ if (x < 1)
+ fun_l15_n578(x)
+ else
+ fun_l15_n586(x)
+ end
+end
+
+def fun_l14_n800(x)
+ if (x < 1)
+ fun_l15_n848(x)
+ else
+ fun_l15_n286(x)
+ end
+end
+
+def fun_l14_n801(x)
+ if (x < 1)
+ fun_l15_n745(x)
+ else
+ fun_l15_n144(x)
+ end
+end
+
+def fun_l14_n802(x)
+ if (x < 1)
+ fun_l15_n369(x)
+ else
+ fun_l15_n819(x)
+ end
+end
+
+def fun_l14_n803(x)
+ if (x < 1)
+ fun_l15_n498(x)
+ else
+ fun_l15_n206(x)
+ end
+end
+
+def fun_l14_n804(x)
+ if (x < 1)
+ fun_l15_n817(x)
+ else
+ fun_l15_n707(x)
+ end
+end
+
+def fun_l14_n805(x)
+ if (x < 1)
+ fun_l15_n935(x)
+ else
+ fun_l15_n43(x)
+ end
+end
+
+def fun_l14_n806(x)
+ if (x < 1)
+ fun_l15_n285(x)
+ else
+ fun_l15_n605(x)
+ end
+end
+
+def fun_l14_n807(x)
+ if (x < 1)
+ fun_l15_n392(x)
+ else
+ fun_l15_n672(x)
+ end
+end
+
+def fun_l14_n808(x)
+ if (x < 1)
+ fun_l15_n965(x)
+ else
+ fun_l15_n610(x)
+ end
+end
+
+def fun_l14_n809(x)
+ if (x < 1)
+ fun_l15_n266(x)
+ else
+ fun_l15_n233(x)
+ end
+end
+
+def fun_l14_n810(x)
+ if (x < 1)
+ fun_l15_n514(x)
+ else
+ fun_l15_n204(x)
+ end
+end
+
+def fun_l14_n811(x)
+ if (x < 1)
+ fun_l15_n973(x)
+ else
+ fun_l15_n768(x)
+ end
+end
+
+def fun_l14_n812(x)
+ if (x < 1)
+ fun_l15_n241(x)
+ else
+ fun_l15_n329(x)
+ end
+end
+
+def fun_l14_n813(x)
+ if (x < 1)
+ fun_l15_n150(x)
+ else
+ fun_l15_n264(x)
+ end
+end
+
+def fun_l14_n814(x)
+ if (x < 1)
+ fun_l15_n205(x)
+ else
+ fun_l15_n595(x)
+ end
+end
+
+def fun_l14_n815(x)
+ if (x < 1)
+ fun_l15_n452(x)
+ else
+ fun_l15_n288(x)
+ end
+end
+
+def fun_l14_n816(x)
+ if (x < 1)
+ fun_l15_n385(x)
+ else
+ fun_l15_n633(x)
+ end
+end
+
+def fun_l14_n817(x)
+ if (x < 1)
+ fun_l15_n290(x)
+ else
+ fun_l15_n656(x)
+ end
+end
+
+def fun_l14_n818(x)
+ if (x < 1)
+ fun_l15_n463(x)
+ else
+ fun_l15_n785(x)
+ end
+end
+
+def fun_l14_n819(x)
+ if (x < 1)
+ fun_l15_n183(x)
+ else
+ fun_l15_n787(x)
+ end
+end
+
+def fun_l14_n820(x)
+ if (x < 1)
+ fun_l15_n515(x)
+ else
+ fun_l15_n104(x)
+ end
+end
+
+def fun_l14_n821(x)
+ if (x < 1)
+ fun_l15_n848(x)
+ else
+ fun_l15_n745(x)
+ end
+end
+
+def fun_l14_n822(x)
+ if (x < 1)
+ fun_l15_n268(x)
+ else
+ fun_l15_n140(x)
+ end
+end
+
+def fun_l14_n823(x)
+ if (x < 1)
+ fun_l15_n607(x)
+ else
+ fun_l15_n785(x)
+ end
+end
+
+def fun_l14_n824(x)
+ if (x < 1)
+ fun_l15_n261(x)
+ else
+ fun_l15_n659(x)
+ end
+end
+
+def fun_l14_n825(x)
+ if (x < 1)
+ fun_l15_n628(x)
+ else
+ fun_l15_n427(x)
+ end
+end
+
+def fun_l14_n826(x)
+ if (x < 1)
+ fun_l15_n293(x)
+ else
+ fun_l15_n141(x)
+ end
+end
+
+def fun_l14_n827(x)
+ if (x < 1)
+ fun_l15_n112(x)
+ else
+ fun_l15_n135(x)
+ end
+end
+
+def fun_l14_n828(x)
+ if (x < 1)
+ fun_l15_n779(x)
+ else
+ fun_l15_n323(x)
+ end
+end
+
+def fun_l14_n829(x)
+ if (x < 1)
+ fun_l15_n295(x)
+ else
+ fun_l15_n753(x)
+ end
+end
+
+def fun_l14_n830(x)
+ if (x < 1)
+ fun_l15_n683(x)
+ else
+ fun_l15_n303(x)
+ end
+end
+
+def fun_l14_n831(x)
+ if (x < 1)
+ fun_l15_n522(x)
+ else
+ fun_l15_n983(x)
+ end
+end
+
+def fun_l14_n832(x)
+ if (x < 1)
+ fun_l15_n338(x)
+ else
+ fun_l15_n835(x)
+ end
+end
+
+def fun_l14_n833(x)
+ if (x < 1)
+ fun_l15_n888(x)
+ else
+ fun_l15_n95(x)
+ end
+end
+
+def fun_l14_n834(x)
+ if (x < 1)
+ fun_l15_n510(x)
+ else
+ fun_l15_n342(x)
+ end
+end
+
+def fun_l14_n835(x)
+ if (x < 1)
+ fun_l15_n168(x)
+ else
+ fun_l15_n864(x)
+ end
+end
+
+def fun_l14_n836(x)
+ if (x < 1)
+ fun_l15_n392(x)
+ else
+ fun_l15_n779(x)
+ end
+end
+
+def fun_l14_n837(x)
+ if (x < 1)
+ fun_l15_n176(x)
+ else
+ fun_l15_n354(x)
+ end
+end
+
+def fun_l14_n838(x)
+ if (x < 1)
+ fun_l15_n477(x)
+ else
+ fun_l15_n95(x)
+ end
+end
+
+def fun_l14_n839(x)
+ if (x < 1)
+ fun_l15_n223(x)
+ else
+ fun_l15_n213(x)
+ end
+end
+
+def fun_l14_n840(x)
+ if (x < 1)
+ fun_l15_n228(x)
+ else
+ fun_l15_n897(x)
+ end
+end
+
+def fun_l14_n841(x)
+ if (x < 1)
+ fun_l15_n551(x)
+ else
+ fun_l15_n649(x)
+ end
+end
+
+def fun_l14_n842(x)
+ if (x < 1)
+ fun_l15_n541(x)
+ else
+ fun_l15_n741(x)
+ end
+end
+
+def fun_l14_n843(x)
+ if (x < 1)
+ fun_l15_n464(x)
+ else
+ fun_l15_n403(x)
+ end
+end
+
+def fun_l14_n844(x)
+ if (x < 1)
+ fun_l15_n853(x)
+ else
+ fun_l15_n223(x)
+ end
+end
+
+def fun_l14_n845(x)
+ if (x < 1)
+ fun_l15_n443(x)
+ else
+ fun_l15_n441(x)
+ end
+end
+
+def fun_l14_n846(x)
+ if (x < 1)
+ fun_l15_n864(x)
+ else
+ fun_l15_n912(x)
+ end
+end
+
+def fun_l14_n847(x)
+ if (x < 1)
+ fun_l15_n631(x)
+ else
+ fun_l15_n764(x)
+ end
+end
+
+def fun_l14_n848(x)
+ if (x < 1)
+ fun_l15_n198(x)
+ else
+ fun_l15_n825(x)
+ end
+end
+
+def fun_l14_n849(x)
+ if (x < 1)
+ fun_l15_n525(x)
+ else
+ fun_l15_n31(x)
+ end
+end
+
+def fun_l14_n850(x)
+ if (x < 1)
+ fun_l15_n928(x)
+ else
+ fun_l15_n893(x)
+ end
+end
+
+def fun_l14_n851(x)
+ if (x < 1)
+ fun_l15_n499(x)
+ else
+ fun_l15_n297(x)
+ end
+end
+
+def fun_l14_n852(x)
+ if (x < 1)
+ fun_l15_n777(x)
+ else
+ fun_l15_n239(x)
+ end
+end
+
+def fun_l14_n853(x)
+ if (x < 1)
+ fun_l15_n120(x)
+ else
+ fun_l15_n134(x)
+ end
+end
+
+def fun_l14_n854(x)
+ if (x < 1)
+ fun_l15_n613(x)
+ else
+ fun_l15_n324(x)
+ end
+end
+
+def fun_l14_n855(x)
+ if (x < 1)
+ fun_l15_n22(x)
+ else
+ fun_l15_n192(x)
+ end
+end
+
+def fun_l14_n856(x)
+ if (x < 1)
+ fun_l15_n609(x)
+ else
+ fun_l15_n284(x)
+ end
+end
+
+def fun_l14_n857(x)
+ if (x < 1)
+ fun_l15_n130(x)
+ else
+ fun_l15_n256(x)
+ end
+end
+
+def fun_l14_n858(x)
+ if (x < 1)
+ fun_l15_n40(x)
+ else
+ fun_l15_n340(x)
+ end
+end
+
+def fun_l14_n859(x)
+ if (x < 1)
+ fun_l15_n644(x)
+ else
+ fun_l15_n522(x)
+ end
+end
+
+def fun_l14_n860(x)
+ if (x < 1)
+ fun_l15_n363(x)
+ else
+ fun_l15_n52(x)
+ end
+end
+
+def fun_l14_n861(x)
+ if (x < 1)
+ fun_l15_n166(x)
+ else
+ fun_l15_n452(x)
+ end
+end
+
+def fun_l14_n862(x)
+ if (x < 1)
+ fun_l15_n552(x)
+ else
+ fun_l15_n534(x)
+ end
+end
+
+def fun_l14_n863(x)
+ if (x < 1)
+ fun_l15_n489(x)
+ else
+ fun_l15_n181(x)
+ end
+end
+
+def fun_l14_n864(x)
+ if (x < 1)
+ fun_l15_n584(x)
+ else
+ fun_l15_n871(x)
+ end
+end
+
+def fun_l14_n865(x)
+ if (x < 1)
+ fun_l15_n868(x)
+ else
+ fun_l15_n807(x)
+ end
+end
+
+def fun_l14_n866(x)
+ if (x < 1)
+ fun_l15_n159(x)
+ else
+ fun_l15_n226(x)
+ end
+end
+
+def fun_l14_n867(x)
+ if (x < 1)
+ fun_l15_n440(x)
+ else
+ fun_l15_n318(x)
+ end
+end
+
+def fun_l14_n868(x)
+ if (x < 1)
+ fun_l15_n603(x)
+ else
+ fun_l15_n440(x)
+ end
+end
+
+def fun_l14_n869(x)
+ if (x < 1)
+ fun_l15_n478(x)
+ else
+ fun_l15_n896(x)
+ end
+end
+
+def fun_l14_n870(x)
+ if (x < 1)
+ fun_l15_n593(x)
+ else
+ fun_l15_n973(x)
+ end
+end
+
+def fun_l14_n871(x)
+ if (x < 1)
+ fun_l15_n767(x)
+ else
+ fun_l15_n828(x)
+ end
+end
+
+def fun_l14_n872(x)
+ if (x < 1)
+ fun_l15_n578(x)
+ else
+ fun_l15_n309(x)
+ end
+end
+
+def fun_l14_n873(x)
+ if (x < 1)
+ fun_l15_n959(x)
+ else
+ fun_l15_n263(x)
+ end
+end
+
+def fun_l14_n874(x)
+ if (x < 1)
+ fun_l15_n170(x)
+ else
+ fun_l15_n700(x)
+ end
+end
+
+def fun_l14_n875(x)
+ if (x < 1)
+ fun_l15_n800(x)
+ else
+ fun_l15_n703(x)
+ end
+end
+
+def fun_l14_n876(x)
+ if (x < 1)
+ fun_l15_n556(x)
+ else
+ fun_l15_n854(x)
+ end
+end
+
+def fun_l14_n877(x)
+ if (x < 1)
+ fun_l15_n472(x)
+ else
+ fun_l15_n893(x)
+ end
+end
+
+def fun_l14_n878(x)
+ if (x < 1)
+ fun_l15_n847(x)
+ else
+ fun_l15_n438(x)
+ end
+end
+
+def fun_l14_n879(x)
+ if (x < 1)
+ fun_l15_n401(x)
+ else
+ fun_l15_n59(x)
+ end
+end
+
+def fun_l14_n880(x)
+ if (x < 1)
+ fun_l15_n321(x)
+ else
+ fun_l15_n57(x)
+ end
+end
+
+def fun_l14_n881(x)
+ if (x < 1)
+ fun_l15_n664(x)
+ else
+ fun_l15_n448(x)
+ end
+end
+
+def fun_l14_n882(x)
+ if (x < 1)
+ fun_l15_n113(x)
+ else
+ fun_l15_n270(x)
+ end
+end
+
+def fun_l14_n883(x)
+ if (x < 1)
+ fun_l15_n596(x)
+ else
+ fun_l15_n354(x)
+ end
+end
+
+def fun_l14_n884(x)
+ if (x < 1)
+ fun_l15_n681(x)
+ else
+ fun_l15_n801(x)
+ end
+end
+
+def fun_l14_n885(x)
+ if (x < 1)
+ fun_l15_n802(x)
+ else
+ fun_l15_n327(x)
+ end
+end
+
+def fun_l14_n886(x)
+ if (x < 1)
+ fun_l15_n657(x)
+ else
+ fun_l15_n325(x)
+ end
+end
+
+def fun_l14_n887(x)
+ if (x < 1)
+ fun_l15_n108(x)
+ else
+ fun_l15_n11(x)
+ end
+end
+
+def fun_l14_n888(x)
+ if (x < 1)
+ fun_l15_n696(x)
+ else
+ fun_l15_n88(x)
+ end
+end
+
+def fun_l14_n889(x)
+ if (x < 1)
+ fun_l15_n220(x)
+ else
+ fun_l15_n282(x)
+ end
+end
+
+def fun_l14_n890(x)
+ if (x < 1)
+ fun_l15_n702(x)
+ else
+ fun_l15_n550(x)
+ end
+end
+
+def fun_l14_n891(x)
+ if (x < 1)
+ fun_l15_n67(x)
+ else
+ fun_l15_n763(x)
+ end
+end
+
+def fun_l14_n892(x)
+ if (x < 1)
+ fun_l15_n386(x)
+ else
+ fun_l15_n938(x)
+ end
+end
+
+def fun_l14_n893(x)
+ if (x < 1)
+ fun_l15_n193(x)
+ else
+ fun_l15_n110(x)
+ end
+end
+
+def fun_l14_n894(x)
+ if (x < 1)
+ fun_l15_n408(x)
+ else
+ fun_l15_n392(x)
+ end
+end
+
+def fun_l14_n895(x)
+ if (x < 1)
+ fun_l15_n488(x)
+ else
+ fun_l15_n445(x)
+ end
+end
+
+def fun_l14_n896(x)
+ if (x < 1)
+ fun_l15_n572(x)
+ else
+ fun_l15_n645(x)
+ end
+end
+
+def fun_l14_n897(x)
+ if (x < 1)
+ fun_l15_n432(x)
+ else
+ fun_l15_n288(x)
+ end
+end
+
+def fun_l14_n898(x)
+ if (x < 1)
+ fun_l15_n466(x)
+ else
+ fun_l15_n877(x)
+ end
+end
+
+def fun_l14_n899(x)
+ if (x < 1)
+ fun_l15_n981(x)
+ else
+ fun_l15_n546(x)
+ end
+end
+
+def fun_l14_n900(x)
+ if (x < 1)
+ fun_l15_n334(x)
+ else
+ fun_l15_n198(x)
+ end
+end
+
+def fun_l14_n901(x)
+ if (x < 1)
+ fun_l15_n447(x)
+ else
+ fun_l15_n881(x)
+ end
+end
+
+def fun_l14_n902(x)
+ if (x < 1)
+ fun_l15_n818(x)
+ else
+ fun_l15_n882(x)
+ end
+end
+
+def fun_l14_n903(x)
+ if (x < 1)
+ fun_l15_n86(x)
+ else
+ fun_l15_n864(x)
+ end
+end
+
+def fun_l14_n904(x)
+ if (x < 1)
+ fun_l15_n981(x)
+ else
+ fun_l15_n472(x)
+ end
+end
+
+def fun_l14_n905(x)
+ if (x < 1)
+ fun_l15_n684(x)
+ else
+ fun_l15_n314(x)
+ end
+end
+
+def fun_l14_n906(x)
+ if (x < 1)
+ fun_l15_n792(x)
+ else
+ fun_l15_n270(x)
+ end
+end
+
+def fun_l14_n907(x)
+ if (x < 1)
+ fun_l15_n958(x)
+ else
+ fun_l15_n293(x)
+ end
+end
+
+def fun_l14_n908(x)
+ if (x < 1)
+ fun_l15_n953(x)
+ else
+ fun_l15_n837(x)
+ end
+end
+
+def fun_l14_n909(x)
+ if (x < 1)
+ fun_l15_n448(x)
+ else
+ fun_l15_n985(x)
+ end
+end
+
+def fun_l14_n910(x)
+ if (x < 1)
+ fun_l15_n148(x)
+ else
+ fun_l15_n210(x)
+ end
+end
+
+def fun_l14_n911(x)
+ if (x < 1)
+ fun_l15_n51(x)
+ else
+ fun_l15_n714(x)
+ end
+end
+
+def fun_l14_n912(x)
+ if (x < 1)
+ fun_l15_n538(x)
+ else
+ fun_l15_n653(x)
+ end
+end
+
+def fun_l14_n913(x)
+ if (x < 1)
+ fun_l15_n374(x)
+ else
+ fun_l15_n836(x)
+ end
+end
+
+def fun_l14_n914(x)
+ if (x < 1)
+ fun_l15_n5(x)
+ else
+ fun_l15_n307(x)
+ end
+end
+
+def fun_l14_n915(x)
+ if (x < 1)
+ fun_l15_n670(x)
+ else
+ fun_l15_n961(x)
+ end
+end
+
+def fun_l14_n916(x)
+ if (x < 1)
+ fun_l15_n600(x)
+ else
+ fun_l15_n843(x)
+ end
+end
+
+def fun_l14_n917(x)
+ if (x < 1)
+ fun_l15_n235(x)
+ else
+ fun_l15_n542(x)
+ end
+end
+
+def fun_l14_n918(x)
+ if (x < 1)
+ fun_l15_n883(x)
+ else
+ fun_l15_n990(x)
+ end
+end
+
+def fun_l14_n919(x)
+ if (x < 1)
+ fun_l15_n988(x)
+ else
+ fun_l15_n678(x)
+ end
+end
+
+def fun_l14_n920(x)
+ if (x < 1)
+ fun_l15_n246(x)
+ else
+ fun_l15_n942(x)
+ end
+end
+
+def fun_l14_n921(x)
+ if (x < 1)
+ fun_l15_n316(x)
+ else
+ fun_l15_n503(x)
+ end
+end
+
+def fun_l14_n922(x)
+ if (x < 1)
+ fun_l15_n392(x)
+ else
+ fun_l15_n948(x)
+ end
+end
+
+def fun_l14_n923(x)
+ if (x < 1)
+ fun_l15_n79(x)
+ else
+ fun_l15_n375(x)
+ end
+end
+
+def fun_l14_n924(x)
+ if (x < 1)
+ fun_l15_n139(x)
+ else
+ fun_l15_n350(x)
+ end
+end
+
+def fun_l14_n925(x)
+ if (x < 1)
+ fun_l15_n132(x)
+ else
+ fun_l15_n27(x)
+ end
+end
+
+def fun_l14_n926(x)
+ if (x < 1)
+ fun_l15_n608(x)
+ else
+ fun_l15_n910(x)
+ end
+end
+
+def fun_l14_n927(x)
+ if (x < 1)
+ fun_l15_n447(x)
+ else
+ fun_l15_n361(x)
+ end
+end
+
+def fun_l14_n928(x)
+ if (x < 1)
+ fun_l15_n432(x)
+ else
+ fun_l15_n943(x)
+ end
+end
+
+def fun_l14_n929(x)
+ if (x < 1)
+ fun_l15_n726(x)
+ else
+ fun_l15_n19(x)
+ end
+end
+
+def fun_l14_n930(x)
+ if (x < 1)
+ fun_l15_n311(x)
+ else
+ fun_l15_n683(x)
+ end
+end
+
+def fun_l14_n931(x)
+ if (x < 1)
+ fun_l15_n988(x)
+ else
+ fun_l15_n731(x)
+ end
+end
+
+def fun_l14_n932(x)
+ if (x < 1)
+ fun_l15_n916(x)
+ else
+ fun_l15_n625(x)
+ end
+end
+
+def fun_l14_n933(x)
+ if (x < 1)
+ fun_l15_n723(x)
+ else
+ fun_l15_n954(x)
+ end
+end
+
+def fun_l14_n934(x)
+ if (x < 1)
+ fun_l15_n82(x)
+ else
+ fun_l15_n140(x)
+ end
+end
+
+def fun_l14_n935(x)
+ if (x < 1)
+ fun_l15_n11(x)
+ else
+ fun_l15_n407(x)
+ end
+end
+
+def fun_l14_n936(x)
+ if (x < 1)
+ fun_l15_n261(x)
+ else
+ fun_l15_n733(x)
+ end
+end
+
+def fun_l14_n937(x)
+ if (x < 1)
+ fun_l15_n37(x)
+ else
+ fun_l15_n617(x)
+ end
+end
+
+def fun_l14_n938(x)
+ if (x < 1)
+ fun_l15_n733(x)
+ else
+ fun_l15_n178(x)
+ end
+end
+
+def fun_l14_n939(x)
+ if (x < 1)
+ fun_l15_n989(x)
+ else
+ fun_l15_n917(x)
+ end
+end
+
+def fun_l14_n940(x)
+ if (x < 1)
+ fun_l15_n297(x)
+ else
+ fun_l15_n393(x)
+ end
+end
+
+def fun_l14_n941(x)
+ if (x < 1)
+ fun_l15_n167(x)
+ else
+ fun_l15_n498(x)
+ end
+end
+
+def fun_l14_n942(x)
+ if (x < 1)
+ fun_l15_n365(x)
+ else
+ fun_l15_n158(x)
+ end
+end
+
+def fun_l14_n943(x)
+ if (x < 1)
+ fun_l15_n340(x)
+ else
+ fun_l15_n813(x)
+ end
+end
+
+def fun_l14_n944(x)
+ if (x < 1)
+ fun_l15_n417(x)
+ else
+ fun_l15_n150(x)
+ end
+end
+
+def fun_l14_n945(x)
+ if (x < 1)
+ fun_l15_n477(x)
+ else
+ fun_l15_n639(x)
+ end
+end
+
+def fun_l14_n946(x)
+ if (x < 1)
+ fun_l15_n243(x)
+ else
+ fun_l15_n439(x)
+ end
+end
+
+def fun_l14_n947(x)
+ if (x < 1)
+ fun_l15_n149(x)
+ else
+ fun_l15_n881(x)
+ end
+end
+
+def fun_l14_n948(x)
+ if (x < 1)
+ fun_l15_n383(x)
+ else
+ fun_l15_n525(x)
+ end
+end
+
+def fun_l14_n949(x)
+ if (x < 1)
+ fun_l15_n482(x)
+ else
+ fun_l15_n625(x)
+ end
+end
+
+def fun_l14_n950(x)
+ if (x < 1)
+ fun_l15_n376(x)
+ else
+ fun_l15_n743(x)
+ end
+end
+
+def fun_l14_n951(x)
+ if (x < 1)
+ fun_l15_n53(x)
+ else
+ fun_l15_n734(x)
+ end
+end
+
+def fun_l14_n952(x)
+ if (x < 1)
+ fun_l15_n437(x)
+ else
+ fun_l15_n829(x)
+ end
+end
+
+def fun_l14_n953(x)
+ if (x < 1)
+ fun_l15_n673(x)
+ else
+ fun_l15_n540(x)
+ end
+end
+
+def fun_l14_n954(x)
+ if (x < 1)
+ fun_l15_n477(x)
+ else
+ fun_l15_n488(x)
+ end
+end
+
+def fun_l14_n955(x)
+ if (x < 1)
+ fun_l15_n876(x)
+ else
+ fun_l15_n710(x)
+ end
+end
+
+def fun_l14_n956(x)
+ if (x < 1)
+ fun_l15_n823(x)
+ else
+ fun_l15_n841(x)
+ end
+end
+
+def fun_l14_n957(x)
+ if (x < 1)
+ fun_l15_n948(x)
+ else
+ fun_l15_n378(x)
+ end
+end
+
+def fun_l14_n958(x)
+ if (x < 1)
+ fun_l15_n941(x)
+ else
+ fun_l15_n555(x)
+ end
+end
+
+def fun_l14_n959(x)
+ if (x < 1)
+ fun_l15_n204(x)
+ else
+ fun_l15_n792(x)
+ end
+end
+
+def fun_l14_n960(x)
+ if (x < 1)
+ fun_l15_n897(x)
+ else
+ fun_l15_n287(x)
+ end
+end
+
+def fun_l14_n961(x)
+ if (x < 1)
+ fun_l15_n771(x)
+ else
+ fun_l15_n409(x)
+ end
+end
+
+def fun_l14_n962(x)
+ if (x < 1)
+ fun_l15_n597(x)
+ else
+ fun_l15_n190(x)
+ end
+end
+
+def fun_l14_n963(x)
+ if (x < 1)
+ fun_l15_n573(x)
+ else
+ fun_l15_n982(x)
+ end
+end
+
+def fun_l14_n964(x)
+ if (x < 1)
+ fun_l15_n186(x)
+ else
+ fun_l15_n363(x)
+ end
+end
+
+def fun_l14_n965(x)
+ if (x < 1)
+ fun_l15_n694(x)
+ else
+ fun_l15_n319(x)
+ end
+end
+
+def fun_l14_n966(x)
+ if (x < 1)
+ fun_l15_n312(x)
+ else
+ fun_l15_n332(x)
+ end
+end
+
+def fun_l14_n967(x)
+ if (x < 1)
+ fun_l15_n754(x)
+ else
+ fun_l15_n965(x)
+ end
+end
+
+def fun_l14_n968(x)
+ if (x < 1)
+ fun_l15_n18(x)
+ else
+ fun_l15_n723(x)
+ end
+end
+
+def fun_l14_n969(x)
+ if (x < 1)
+ fun_l15_n111(x)
+ else
+ fun_l15_n447(x)
+ end
+end
+
+def fun_l14_n970(x)
+ if (x < 1)
+ fun_l15_n3(x)
+ else
+ fun_l15_n302(x)
+ end
+end
+
+def fun_l14_n971(x)
+ if (x < 1)
+ fun_l15_n121(x)
+ else
+ fun_l15_n764(x)
+ end
+end
+
+def fun_l14_n972(x)
+ if (x < 1)
+ fun_l15_n192(x)
+ else
+ fun_l15_n692(x)
+ end
+end
+
+def fun_l14_n973(x)
+ if (x < 1)
+ fun_l15_n596(x)
+ else
+ fun_l15_n514(x)
+ end
+end
+
+def fun_l14_n974(x)
+ if (x < 1)
+ fun_l15_n845(x)
+ else
+ fun_l15_n245(x)
+ end
+end
+
+def fun_l14_n975(x)
+ if (x < 1)
+ fun_l15_n566(x)
+ else
+ fun_l15_n58(x)
+ end
+end
+
+def fun_l14_n976(x)
+ if (x < 1)
+ fun_l15_n843(x)
+ else
+ fun_l15_n35(x)
+ end
+end
+
+def fun_l14_n977(x)
+ if (x < 1)
+ fun_l15_n995(x)
+ else
+ fun_l15_n723(x)
+ end
+end
+
+def fun_l14_n978(x)
+ if (x < 1)
+ fun_l15_n534(x)
+ else
+ fun_l15_n704(x)
+ end
+end
+
+def fun_l14_n979(x)
+ if (x < 1)
+ fun_l15_n533(x)
+ else
+ fun_l15_n492(x)
+ end
+end
+
+def fun_l14_n980(x)
+ if (x < 1)
+ fun_l15_n758(x)
+ else
+ fun_l15_n655(x)
+ end
+end
+
+def fun_l14_n981(x)
+ if (x < 1)
+ fun_l15_n94(x)
+ else
+ fun_l15_n246(x)
+ end
+end
+
+def fun_l14_n982(x)
+ if (x < 1)
+ fun_l15_n873(x)
+ else
+ fun_l15_n996(x)
+ end
+end
+
+def fun_l14_n983(x)
+ if (x < 1)
+ fun_l15_n681(x)
+ else
+ fun_l15_n522(x)
+ end
+end
+
+def fun_l14_n984(x)
+ if (x < 1)
+ fun_l15_n272(x)
+ else
+ fun_l15_n501(x)
+ end
+end
+
+def fun_l14_n985(x)
+ if (x < 1)
+ fun_l15_n345(x)
+ else
+ fun_l15_n61(x)
+ end
+end
+
+def fun_l14_n986(x)
+ if (x < 1)
+ fun_l15_n517(x)
+ else
+ fun_l15_n151(x)
+ end
+end
+
+def fun_l14_n987(x)
+ if (x < 1)
+ fun_l15_n792(x)
+ else
+ fun_l15_n969(x)
+ end
+end
+
+def fun_l14_n988(x)
+ if (x < 1)
+ fun_l15_n683(x)
+ else
+ fun_l15_n537(x)
+ end
+end
+
+def fun_l14_n989(x)
+ if (x < 1)
+ fun_l15_n310(x)
+ else
+ fun_l15_n367(x)
+ end
+end
+
+def fun_l14_n990(x)
+ if (x < 1)
+ fun_l15_n249(x)
+ else
+ fun_l15_n897(x)
+ end
+end
+
+def fun_l14_n991(x)
+ if (x < 1)
+ fun_l15_n389(x)
+ else
+ fun_l15_n176(x)
+ end
+end
+
+def fun_l14_n992(x)
+ if (x < 1)
+ fun_l15_n233(x)
+ else
+ fun_l15_n220(x)
+ end
+end
+
+def fun_l14_n993(x)
+ if (x < 1)
+ fun_l15_n161(x)
+ else
+ fun_l15_n642(x)
+ end
+end
+
+def fun_l14_n994(x)
+ if (x < 1)
+ fun_l15_n163(x)
+ else
+ fun_l15_n5(x)
+ end
+end
+
+def fun_l14_n995(x)
+ if (x < 1)
+ fun_l15_n678(x)
+ else
+ fun_l15_n108(x)
+ end
+end
+
+def fun_l14_n996(x)
+ if (x < 1)
+ fun_l15_n732(x)
+ else
+ fun_l15_n26(x)
+ end
+end
+
+def fun_l14_n997(x)
+ if (x < 1)
+ fun_l15_n805(x)
+ else
+ fun_l15_n726(x)
+ end
+end
+
+def fun_l14_n998(x)
+ if (x < 1)
+ fun_l15_n543(x)
+ else
+ fun_l15_n102(x)
+ end
+end
+
+def fun_l14_n999(x)
+ if (x < 1)
+ fun_l15_n358(x)
+ else
+ fun_l15_n986(x)
+ end
+end
+
+def fun_l15_n0(x)
+ if (x < 1)
+ fun_l16_n832(x)
+ else
+ fun_l16_n319(x)
+ end
+end
+
+def fun_l15_n1(x)
+ if (x < 1)
+ fun_l16_n920(x)
+ else
+ fun_l16_n27(x)
+ end
+end
+
+def fun_l15_n2(x)
+ if (x < 1)
+ fun_l16_n929(x)
+ else
+ fun_l16_n230(x)
+ end
+end
+
+def fun_l15_n3(x)
+ if (x < 1)
+ fun_l16_n135(x)
+ else
+ fun_l16_n427(x)
+ end
+end
+
+def fun_l15_n4(x)
+ if (x < 1)
+ fun_l16_n299(x)
+ else
+ fun_l16_n811(x)
+ end
+end
+
+def fun_l15_n5(x)
+ if (x < 1)
+ fun_l16_n821(x)
+ else
+ fun_l16_n717(x)
+ end
+end
+
+def fun_l15_n6(x)
+ if (x < 1)
+ fun_l16_n907(x)
+ else
+ fun_l16_n348(x)
+ end
+end
+
+def fun_l15_n7(x)
+ if (x < 1)
+ fun_l16_n708(x)
+ else
+ fun_l16_n180(x)
+ end
+end
+
+def fun_l15_n8(x)
+ if (x < 1)
+ fun_l16_n835(x)
+ else
+ fun_l16_n754(x)
+ end
+end
+
+def fun_l15_n9(x)
+ if (x < 1)
+ fun_l16_n25(x)
+ else
+ fun_l16_n607(x)
+ end
+end
+
+def fun_l15_n10(x)
+ if (x < 1)
+ fun_l16_n73(x)
+ else
+ fun_l16_n784(x)
+ end
+end
+
+def fun_l15_n11(x)
+ if (x < 1)
+ fun_l16_n413(x)
+ else
+ fun_l16_n914(x)
+ end
+end
+
+def fun_l15_n12(x)
+ if (x < 1)
+ fun_l16_n734(x)
+ else
+ fun_l16_n688(x)
+ end
+end
+
+def fun_l15_n13(x)
+ if (x < 1)
+ fun_l16_n658(x)
+ else
+ fun_l16_n491(x)
+ end
+end
+
+def fun_l15_n14(x)
+ if (x < 1)
+ fun_l16_n839(x)
+ else
+ fun_l16_n740(x)
+ end
+end
+
+def fun_l15_n15(x)
+ if (x < 1)
+ fun_l16_n378(x)
+ else
+ fun_l16_n800(x)
+ end
+end
+
+def fun_l15_n16(x)
+ if (x < 1)
+ fun_l16_n980(x)
+ else
+ fun_l16_n83(x)
+ end
+end
+
+def fun_l15_n17(x)
+ if (x < 1)
+ fun_l16_n338(x)
+ else
+ fun_l16_n871(x)
+ end
+end
+
+def fun_l15_n18(x)
+ if (x < 1)
+ fun_l16_n497(x)
+ else
+ fun_l16_n347(x)
+ end
+end
+
+def fun_l15_n19(x)
+ if (x < 1)
+ fun_l16_n483(x)
+ else
+ fun_l16_n913(x)
+ end
+end
+
+def fun_l15_n20(x)
+ if (x < 1)
+ fun_l16_n663(x)
+ else
+ fun_l16_n432(x)
+ end
+end
+
+def fun_l15_n21(x)
+ if (x < 1)
+ fun_l16_n787(x)
+ else
+ fun_l16_n248(x)
+ end
+end
+
+def fun_l15_n22(x)
+ if (x < 1)
+ fun_l16_n257(x)
+ else
+ fun_l16_n944(x)
+ end
+end
+
+def fun_l15_n23(x)
+ if (x < 1)
+ fun_l16_n11(x)
+ else
+ fun_l16_n343(x)
+ end
+end
+
+def fun_l15_n24(x)
+ if (x < 1)
+ fun_l16_n860(x)
+ else
+ fun_l16_n752(x)
+ end
+end
+
+def fun_l15_n25(x)
+ if (x < 1)
+ fun_l16_n766(x)
+ else
+ fun_l16_n719(x)
+ end
+end
+
+def fun_l15_n26(x)
+ if (x < 1)
+ fun_l16_n144(x)
+ else
+ fun_l16_n963(x)
+ end
+end
+
+def fun_l15_n27(x)
+ if (x < 1)
+ fun_l16_n659(x)
+ else
+ fun_l16_n916(x)
+ end
+end
+
+def fun_l15_n28(x)
+ if (x < 1)
+ fun_l16_n429(x)
+ else
+ fun_l16_n272(x)
+ end
+end
+
+def fun_l15_n29(x)
+ if (x < 1)
+ fun_l16_n54(x)
+ else
+ fun_l16_n794(x)
+ end
+end
+
+def fun_l15_n30(x)
+ if (x < 1)
+ fun_l16_n273(x)
+ else
+ fun_l16_n929(x)
+ end
+end
+
+def fun_l15_n31(x)
+ if (x < 1)
+ fun_l16_n868(x)
+ else
+ fun_l16_n967(x)
+ end
+end
+
+def fun_l15_n32(x)
+ if (x < 1)
+ fun_l16_n888(x)
+ else
+ fun_l16_n283(x)
+ end
+end
+
+def fun_l15_n33(x)
+ if (x < 1)
+ fun_l16_n6(x)
+ else
+ fun_l16_n677(x)
+ end
+end
+
+def fun_l15_n34(x)
+ if (x < 1)
+ fun_l16_n248(x)
+ else
+ fun_l16_n831(x)
+ end
+end
+
+def fun_l15_n35(x)
+ if (x < 1)
+ fun_l16_n832(x)
+ else
+ fun_l16_n634(x)
+ end
+end
+
+def fun_l15_n36(x)
+ if (x < 1)
+ fun_l16_n221(x)
+ else
+ fun_l16_n401(x)
+ end
+end
+
+def fun_l15_n37(x)
+ if (x < 1)
+ fun_l16_n403(x)
+ else
+ fun_l16_n29(x)
+ end
+end
+
+def fun_l15_n38(x)
+ if (x < 1)
+ fun_l16_n11(x)
+ else
+ fun_l16_n517(x)
+ end
+end
+
+def fun_l15_n39(x)
+ if (x < 1)
+ fun_l16_n234(x)
+ else
+ fun_l16_n231(x)
+ end
+end
+
+def fun_l15_n40(x)
+ if (x < 1)
+ fun_l16_n185(x)
+ else
+ fun_l16_n818(x)
+ end
+end
+
+def fun_l15_n41(x)
+ if (x < 1)
+ fun_l16_n169(x)
+ else
+ fun_l16_n239(x)
+ end
+end
+
+def fun_l15_n42(x)
+ if (x < 1)
+ fun_l16_n111(x)
+ else
+ fun_l16_n836(x)
+ end
+end
+
+def fun_l15_n43(x)
+ if (x < 1)
+ fun_l16_n832(x)
+ else
+ fun_l16_n714(x)
+ end
+end
+
+def fun_l15_n44(x)
+ if (x < 1)
+ fun_l16_n167(x)
+ else
+ fun_l16_n65(x)
+ end
+end
+
+def fun_l15_n45(x)
+ if (x < 1)
+ fun_l16_n801(x)
+ else
+ fun_l16_n456(x)
+ end
+end
+
+def fun_l15_n46(x)
+ if (x < 1)
+ fun_l16_n894(x)
+ else
+ fun_l16_n103(x)
+ end
+end
+
+def fun_l15_n47(x)
+ if (x < 1)
+ fun_l16_n156(x)
+ else
+ fun_l16_n228(x)
+ end
+end
+
+def fun_l15_n48(x)
+ if (x < 1)
+ fun_l16_n167(x)
+ else
+ fun_l16_n317(x)
+ end
+end
+
+def fun_l15_n49(x)
+ if (x < 1)
+ fun_l16_n864(x)
+ else
+ fun_l16_n425(x)
+ end
+end
+
+def fun_l15_n50(x)
+ if (x < 1)
+ fun_l16_n11(x)
+ else
+ fun_l16_n498(x)
+ end
+end
+
+def fun_l15_n51(x)
+ if (x < 1)
+ fun_l16_n209(x)
+ else
+ fun_l16_n399(x)
+ end
+end
+
+def fun_l15_n52(x)
+ if (x < 1)
+ fun_l16_n320(x)
+ else
+ fun_l16_n912(x)
+ end
+end
+
+def fun_l15_n53(x)
+ if (x < 1)
+ fun_l16_n135(x)
+ else
+ fun_l16_n349(x)
+ end
+end
+
+def fun_l15_n54(x)
+ if (x < 1)
+ fun_l16_n410(x)
+ else
+ fun_l16_n849(x)
+ end
+end
+
+def fun_l15_n55(x)
+ if (x < 1)
+ fun_l16_n989(x)
+ else
+ fun_l16_n700(x)
+ end
+end
+
+def fun_l15_n56(x)
+ if (x < 1)
+ fun_l16_n79(x)
+ else
+ fun_l16_n549(x)
+ end
+end
+
+def fun_l15_n57(x)
+ if (x < 1)
+ fun_l16_n396(x)
+ else
+ fun_l16_n182(x)
+ end
+end
+
+def fun_l15_n58(x)
+ if (x < 1)
+ fun_l16_n765(x)
+ else
+ fun_l16_n225(x)
+ end
+end
+
+def fun_l15_n59(x)
+ if (x < 1)
+ fun_l16_n124(x)
+ else
+ fun_l16_n694(x)
+ end
+end
+
+def fun_l15_n60(x)
+ if (x < 1)
+ fun_l16_n813(x)
+ else
+ fun_l16_n319(x)
+ end
+end
+
+def fun_l15_n61(x)
+ if (x < 1)
+ fun_l16_n568(x)
+ else
+ fun_l16_n581(x)
+ end
+end
+
+def fun_l15_n62(x)
+ if (x < 1)
+ fun_l16_n667(x)
+ else
+ fun_l16_n12(x)
+ end
+end
+
+def fun_l15_n63(x)
+ if (x < 1)
+ fun_l16_n176(x)
+ else
+ fun_l16_n136(x)
+ end
+end
+
+def fun_l15_n64(x)
+ if (x < 1)
+ fun_l16_n620(x)
+ else
+ fun_l16_n937(x)
+ end
+end
+
+def fun_l15_n65(x)
+ if (x < 1)
+ fun_l16_n130(x)
+ else
+ fun_l16_n503(x)
+ end
+end
+
+def fun_l15_n66(x)
+ if (x < 1)
+ fun_l16_n774(x)
+ else
+ fun_l16_n109(x)
+ end
+end
+
+def fun_l15_n67(x)
+ if (x < 1)
+ fun_l16_n817(x)
+ else
+ fun_l16_n497(x)
+ end
+end
+
+def fun_l15_n68(x)
+ if (x < 1)
+ fun_l16_n123(x)
+ else
+ fun_l16_n482(x)
+ end
+end
+
+def fun_l15_n69(x)
+ if (x < 1)
+ fun_l16_n173(x)
+ else
+ fun_l16_n22(x)
+ end
+end
+
+def fun_l15_n70(x)
+ if (x < 1)
+ fun_l16_n648(x)
+ else
+ fun_l16_n671(x)
+ end
+end
+
+def fun_l15_n71(x)
+ if (x < 1)
+ fun_l16_n831(x)
+ else
+ fun_l16_n126(x)
+ end
+end
+
+def fun_l15_n72(x)
+ if (x < 1)
+ fun_l16_n731(x)
+ else
+ fun_l16_n273(x)
+ end
+end
+
+def fun_l15_n73(x)
+ if (x < 1)
+ fun_l16_n695(x)
+ else
+ fun_l16_n772(x)
+ end
+end
+
+def fun_l15_n74(x)
+ if (x < 1)
+ fun_l16_n831(x)
+ else
+ fun_l16_n49(x)
+ end
+end
+
+def fun_l15_n75(x)
+ if (x < 1)
+ fun_l16_n501(x)
+ else
+ fun_l16_n4(x)
+ end
+end
+
+def fun_l15_n76(x)
+ if (x < 1)
+ fun_l16_n712(x)
+ else
+ fun_l16_n762(x)
+ end
+end
+
+def fun_l15_n77(x)
+ if (x < 1)
+ fun_l16_n585(x)
+ else
+ fun_l16_n398(x)
+ end
+end
+
+def fun_l15_n78(x)
+ if (x < 1)
+ fun_l16_n811(x)
+ else
+ fun_l16_n866(x)
+ end
+end
+
+def fun_l15_n79(x)
+ if (x < 1)
+ fun_l16_n69(x)
+ else
+ fun_l16_n502(x)
+ end
+end
+
+def fun_l15_n80(x)
+ if (x < 1)
+ fun_l16_n885(x)
+ else
+ fun_l16_n116(x)
+ end
+end
+
+def fun_l15_n81(x)
+ if (x < 1)
+ fun_l16_n30(x)
+ else
+ fun_l16_n1(x)
+ end
+end
+
+def fun_l15_n82(x)
+ if (x < 1)
+ fun_l16_n105(x)
+ else
+ fun_l16_n526(x)
+ end
+end
+
+def fun_l15_n83(x)
+ if (x < 1)
+ fun_l16_n760(x)
+ else
+ fun_l16_n206(x)
+ end
+end
+
+def fun_l15_n84(x)
+ if (x < 1)
+ fun_l16_n722(x)
+ else
+ fun_l16_n211(x)
+ end
+end
+
+def fun_l15_n85(x)
+ if (x < 1)
+ fun_l16_n145(x)
+ else
+ fun_l16_n222(x)
+ end
+end
+
+def fun_l15_n86(x)
+ if (x < 1)
+ fun_l16_n691(x)
+ else
+ fun_l16_n885(x)
+ end
+end
+
+def fun_l15_n87(x)
+ if (x < 1)
+ fun_l16_n2(x)
+ else
+ fun_l16_n180(x)
+ end
+end
+
+def fun_l15_n88(x)
+ if (x < 1)
+ fun_l16_n272(x)
+ else
+ fun_l16_n433(x)
+ end
+end
+
+def fun_l15_n89(x)
+ if (x < 1)
+ fun_l16_n31(x)
+ else
+ fun_l16_n854(x)
+ end
+end
+
+def fun_l15_n90(x)
+ if (x < 1)
+ fun_l16_n264(x)
+ else
+ fun_l16_n231(x)
+ end
+end
+
+def fun_l15_n91(x)
+ if (x < 1)
+ fun_l16_n637(x)
+ else
+ fun_l16_n96(x)
+ end
+end
+
+def fun_l15_n92(x)
+ if (x < 1)
+ fun_l16_n317(x)
+ else
+ fun_l16_n56(x)
+ end
+end
+
+def fun_l15_n93(x)
+ if (x < 1)
+ fun_l16_n523(x)
+ else
+ fun_l16_n948(x)
+ end
+end
+
+def fun_l15_n94(x)
+ if (x < 1)
+ fun_l16_n694(x)
+ else
+ fun_l16_n948(x)
+ end
+end
+
+def fun_l15_n95(x)
+ if (x < 1)
+ fun_l16_n708(x)
+ else
+ fun_l16_n581(x)
+ end
+end
+
+def fun_l15_n96(x)
+ if (x < 1)
+ fun_l16_n725(x)
+ else
+ fun_l16_n931(x)
+ end
+end
+
+def fun_l15_n97(x)
+ if (x < 1)
+ fun_l16_n432(x)
+ else
+ fun_l16_n367(x)
+ end
+end
+
+def fun_l15_n98(x)
+ if (x < 1)
+ fun_l16_n671(x)
+ else
+ fun_l16_n165(x)
+ end
+end
+
+def fun_l15_n99(x)
+ if (x < 1)
+ fun_l16_n617(x)
+ else
+ fun_l16_n498(x)
+ end
+end
+
+def fun_l15_n100(x)
+ if (x < 1)
+ fun_l16_n32(x)
+ else
+ fun_l16_n103(x)
+ end
+end
+
+def fun_l15_n101(x)
+ if (x < 1)
+ fun_l16_n619(x)
+ else
+ fun_l16_n556(x)
+ end
+end
+
+def fun_l15_n102(x)
+ if (x < 1)
+ fun_l16_n0(x)
+ else
+ fun_l16_n925(x)
+ end
+end
+
+def fun_l15_n103(x)
+ if (x < 1)
+ fun_l16_n484(x)
+ else
+ fun_l16_n889(x)
+ end
+end
+
+def fun_l15_n104(x)
+ if (x < 1)
+ fun_l16_n557(x)
+ else
+ fun_l16_n465(x)
+ end
+end
+
+def fun_l15_n105(x)
+ if (x < 1)
+ fun_l16_n486(x)
+ else
+ fun_l16_n720(x)
+ end
+end
+
+def fun_l15_n106(x)
+ if (x < 1)
+ fun_l16_n281(x)
+ else
+ fun_l16_n61(x)
+ end
+end
+
+def fun_l15_n107(x)
+ if (x < 1)
+ fun_l16_n861(x)
+ else
+ fun_l16_n944(x)
+ end
+end
+
+def fun_l15_n108(x)
+ if (x < 1)
+ fun_l16_n739(x)
+ else
+ fun_l16_n192(x)
+ end
+end
+
+def fun_l15_n109(x)
+ if (x < 1)
+ fun_l16_n327(x)
+ else
+ fun_l16_n423(x)
+ end
+end
+
+def fun_l15_n110(x)
+ if (x < 1)
+ fun_l16_n541(x)
+ else
+ fun_l16_n927(x)
+ end
+end
+
+def fun_l15_n111(x)
+ if (x < 1)
+ fun_l16_n86(x)
+ else
+ fun_l16_n170(x)
+ end
+end
+
+def fun_l15_n112(x)
+ if (x < 1)
+ fun_l16_n508(x)
+ else
+ fun_l16_n554(x)
+ end
+end
+
+def fun_l15_n113(x)
+ if (x < 1)
+ fun_l16_n326(x)
+ else
+ fun_l16_n289(x)
+ end
+end
+
+def fun_l15_n114(x)
+ if (x < 1)
+ fun_l16_n309(x)
+ else
+ fun_l16_n125(x)
+ end
+end
+
+def fun_l15_n115(x)
+ if (x < 1)
+ fun_l16_n936(x)
+ else
+ fun_l16_n64(x)
+ end
+end
+
+def fun_l15_n116(x)
+ if (x < 1)
+ fun_l16_n942(x)
+ else
+ fun_l16_n737(x)
+ end
+end
+
+def fun_l15_n117(x)
+ if (x < 1)
+ fun_l16_n717(x)
+ else
+ fun_l16_n701(x)
+ end
+end
+
+def fun_l15_n118(x)
+ if (x < 1)
+ fun_l16_n789(x)
+ else
+ fun_l16_n901(x)
+ end
+end
+
+def fun_l15_n119(x)
+ if (x < 1)
+ fun_l16_n49(x)
+ else
+ fun_l16_n610(x)
+ end
+end
+
+def fun_l15_n120(x)
+ if (x < 1)
+ fun_l16_n578(x)
+ else
+ fun_l16_n372(x)
+ end
+end
+
+def fun_l15_n121(x)
+ if (x < 1)
+ fun_l16_n262(x)
+ else
+ fun_l16_n441(x)
+ end
+end
+
+def fun_l15_n122(x)
+ if (x < 1)
+ fun_l16_n29(x)
+ else
+ fun_l16_n837(x)
+ end
+end
+
+def fun_l15_n123(x)
+ if (x < 1)
+ fun_l16_n796(x)
+ else
+ fun_l16_n771(x)
+ end
+end
+
+def fun_l15_n124(x)
+ if (x < 1)
+ fun_l16_n354(x)
+ else
+ fun_l16_n818(x)
+ end
+end
+
+def fun_l15_n125(x)
+ if (x < 1)
+ fun_l16_n971(x)
+ else
+ fun_l16_n305(x)
+ end
+end
+
+def fun_l15_n126(x)
+ if (x < 1)
+ fun_l16_n435(x)
+ else
+ fun_l16_n307(x)
+ end
+end
+
+def fun_l15_n127(x)
+ if (x < 1)
+ fun_l16_n809(x)
+ else
+ fun_l16_n884(x)
+ end
+end
+
+def fun_l15_n128(x)
+ if (x < 1)
+ fun_l16_n794(x)
+ else
+ fun_l16_n480(x)
+ end
+end
+
+def fun_l15_n129(x)
+ if (x < 1)
+ fun_l16_n797(x)
+ else
+ fun_l16_n193(x)
+ end
+end
+
+def fun_l15_n130(x)
+ if (x < 1)
+ fun_l16_n415(x)
+ else
+ fun_l16_n255(x)
+ end
+end
+
+def fun_l15_n131(x)
+ if (x < 1)
+ fun_l16_n736(x)
+ else
+ fun_l16_n904(x)
+ end
+end
+
+def fun_l15_n132(x)
+ if (x < 1)
+ fun_l16_n753(x)
+ else
+ fun_l16_n408(x)
+ end
+end
+
+def fun_l15_n133(x)
+ if (x < 1)
+ fun_l16_n61(x)
+ else
+ fun_l16_n231(x)
+ end
+end
+
+def fun_l15_n134(x)
+ if (x < 1)
+ fun_l16_n541(x)
+ else
+ fun_l16_n93(x)
+ end
+end
+
+def fun_l15_n135(x)
+ if (x < 1)
+ fun_l16_n617(x)
+ else
+ fun_l16_n765(x)
+ end
+end
+
+def fun_l15_n136(x)
+ if (x < 1)
+ fun_l16_n749(x)
+ else
+ fun_l16_n344(x)
+ end
+end
+
+def fun_l15_n137(x)
+ if (x < 1)
+ fun_l16_n431(x)
+ else
+ fun_l16_n354(x)
+ end
+end
+
+def fun_l15_n138(x)
+ if (x < 1)
+ fun_l16_n116(x)
+ else
+ fun_l16_n963(x)
+ end
+end
+
+def fun_l15_n139(x)
+ if (x < 1)
+ fun_l16_n500(x)
+ else
+ fun_l16_n380(x)
+ end
+end
+
+def fun_l15_n140(x)
+ if (x < 1)
+ fun_l16_n120(x)
+ else
+ fun_l16_n953(x)
+ end
+end
+
+def fun_l15_n141(x)
+ if (x < 1)
+ fun_l16_n287(x)
+ else
+ fun_l16_n154(x)
+ end
+end
+
+def fun_l15_n142(x)
+ if (x < 1)
+ fun_l16_n347(x)
+ else
+ fun_l16_n841(x)
+ end
+end
+
+def fun_l15_n143(x)
+ if (x < 1)
+ fun_l16_n562(x)
+ else
+ fun_l16_n674(x)
+ end
+end
+
+def fun_l15_n144(x)
+ if (x < 1)
+ fun_l16_n146(x)
+ else
+ fun_l16_n788(x)
+ end
+end
+
+def fun_l15_n145(x)
+ if (x < 1)
+ fun_l16_n463(x)
+ else
+ fun_l16_n590(x)
+ end
+end
+
+def fun_l15_n146(x)
+ if (x < 1)
+ fun_l16_n452(x)
+ else
+ fun_l16_n732(x)
+ end
+end
+
+def fun_l15_n147(x)
+ if (x < 1)
+ fun_l16_n840(x)
+ else
+ fun_l16_n254(x)
+ end
+end
+
+def fun_l15_n148(x)
+ if (x < 1)
+ fun_l16_n224(x)
+ else
+ fun_l16_n826(x)
+ end
+end
+
+def fun_l15_n149(x)
+ if (x < 1)
+ fun_l16_n40(x)
+ else
+ fun_l16_n267(x)
+ end
+end
+
+def fun_l15_n150(x)
+ if (x < 1)
+ fun_l16_n160(x)
+ else
+ fun_l16_n745(x)
+ end
+end
+
+def fun_l15_n151(x)
+ if (x < 1)
+ fun_l16_n926(x)
+ else
+ fun_l16_n567(x)
+ end
+end
+
+def fun_l15_n152(x)
+ if (x < 1)
+ fun_l16_n392(x)
+ else
+ fun_l16_n487(x)
+ end
+end
+
+def fun_l15_n153(x)
+ if (x < 1)
+ fun_l16_n603(x)
+ else
+ fun_l16_n549(x)
+ end
+end
+
+def fun_l15_n154(x)
+ if (x < 1)
+ fun_l16_n993(x)
+ else
+ fun_l16_n451(x)
+ end
+end
+
+def fun_l15_n155(x)
+ if (x < 1)
+ fun_l16_n358(x)
+ else
+ fun_l16_n52(x)
+ end
+end
+
+def fun_l15_n156(x)
+ if (x < 1)
+ fun_l16_n694(x)
+ else
+ fun_l16_n419(x)
+ end
+end
+
+def fun_l15_n157(x)
+ if (x < 1)
+ fun_l16_n138(x)
+ else
+ fun_l16_n127(x)
+ end
+end
+
+def fun_l15_n158(x)
+ if (x < 1)
+ fun_l16_n619(x)
+ else
+ fun_l16_n328(x)
+ end
+end
+
+def fun_l15_n159(x)
+ if (x < 1)
+ fun_l16_n281(x)
+ else
+ fun_l16_n503(x)
+ end
+end
+
+def fun_l15_n160(x)
+ if (x < 1)
+ fun_l16_n631(x)
+ else
+ fun_l16_n69(x)
+ end
+end
+
+def fun_l15_n161(x)
+ if (x < 1)
+ fun_l16_n41(x)
+ else
+ fun_l16_n734(x)
+ end
+end
+
+def fun_l15_n162(x)
+ if (x < 1)
+ fun_l16_n809(x)
+ else
+ fun_l16_n303(x)
+ end
+end
+
+def fun_l15_n163(x)
+ if (x < 1)
+ fun_l16_n851(x)
+ else
+ fun_l16_n420(x)
+ end
+end
+
+def fun_l15_n164(x)
+ if (x < 1)
+ fun_l16_n534(x)
+ else
+ fun_l16_n686(x)
+ end
+end
+
+def fun_l15_n165(x)
+ if (x < 1)
+ fun_l16_n639(x)
+ else
+ fun_l16_n155(x)
+ end
+end
+
+def fun_l15_n166(x)
+ if (x < 1)
+ fun_l16_n196(x)
+ else
+ fun_l16_n478(x)
+ end
+end
+
+def fun_l15_n167(x)
+ if (x < 1)
+ fun_l16_n926(x)
+ else
+ fun_l16_n506(x)
+ end
+end
+
+def fun_l15_n168(x)
+ if (x < 1)
+ fun_l16_n74(x)
+ else
+ fun_l16_n442(x)
+ end
+end
+
+def fun_l15_n169(x)
+ if (x < 1)
+ fun_l16_n122(x)
+ else
+ fun_l16_n150(x)
+ end
+end
+
+def fun_l15_n170(x)
+ if (x < 1)
+ fun_l16_n805(x)
+ else
+ fun_l16_n46(x)
+ end
+end
+
+def fun_l15_n171(x)
+ if (x < 1)
+ fun_l16_n741(x)
+ else
+ fun_l16_n88(x)
+ end
+end
+
+def fun_l15_n172(x)
+ if (x < 1)
+ fun_l16_n749(x)
+ else
+ fun_l16_n896(x)
+ end
+end
+
+def fun_l15_n173(x)
+ if (x < 1)
+ fun_l16_n310(x)
+ else
+ fun_l16_n517(x)
+ end
+end
+
+def fun_l15_n174(x)
+ if (x < 1)
+ fun_l16_n237(x)
+ else
+ fun_l16_n948(x)
+ end
+end
+
+def fun_l15_n175(x)
+ if (x < 1)
+ fun_l16_n402(x)
+ else
+ fun_l16_n332(x)
+ end
+end
+
+def fun_l15_n176(x)
+ if (x < 1)
+ fun_l16_n189(x)
+ else
+ fun_l16_n223(x)
+ end
+end
+
+def fun_l15_n177(x)
+ if (x < 1)
+ fun_l16_n1(x)
+ else
+ fun_l16_n577(x)
+ end
+end
+
+def fun_l15_n178(x)
+ if (x < 1)
+ fun_l16_n738(x)
+ else
+ fun_l16_n775(x)
+ end
+end
+
+def fun_l15_n179(x)
+ if (x < 1)
+ fun_l16_n80(x)
+ else
+ fun_l16_n652(x)
+ end
+end
+
+def fun_l15_n180(x)
+ if (x < 1)
+ fun_l16_n72(x)
+ else
+ fun_l16_n635(x)
+ end
+end
+
+def fun_l15_n181(x)
+ if (x < 1)
+ fun_l16_n721(x)
+ else
+ fun_l16_n661(x)
+ end
+end
+
+def fun_l15_n182(x)
+ if (x < 1)
+ fun_l16_n354(x)
+ else
+ fun_l16_n681(x)
+ end
+end
+
+def fun_l15_n183(x)
+ if (x < 1)
+ fun_l16_n689(x)
+ else
+ fun_l16_n775(x)
+ end
+end
+
+def fun_l15_n184(x)
+ if (x < 1)
+ fun_l16_n923(x)
+ else
+ fun_l16_n719(x)
+ end
+end
+
+def fun_l15_n185(x)
+ if (x < 1)
+ fun_l16_n33(x)
+ else
+ fun_l16_n98(x)
+ end
+end
+
+def fun_l15_n186(x)
+ if (x < 1)
+ fun_l16_n155(x)
+ else
+ fun_l16_n880(x)
+ end
+end
+
+def fun_l15_n187(x)
+ if (x < 1)
+ fun_l16_n625(x)
+ else
+ fun_l16_n314(x)
+ end
+end
+
+def fun_l15_n188(x)
+ if (x < 1)
+ fun_l16_n284(x)
+ else
+ fun_l16_n229(x)
+ end
+end
+
+def fun_l15_n189(x)
+ if (x < 1)
+ fun_l16_n471(x)
+ else
+ fun_l16_n740(x)
+ end
+end
+
+def fun_l15_n190(x)
+ if (x < 1)
+ fun_l16_n102(x)
+ else
+ fun_l16_n766(x)
+ end
+end
+
+def fun_l15_n191(x)
+ if (x < 1)
+ fun_l16_n812(x)
+ else
+ fun_l16_n94(x)
+ end
+end
+
+def fun_l15_n192(x)
+ if (x < 1)
+ fun_l16_n797(x)
+ else
+ fun_l16_n736(x)
+ end
+end
+
+def fun_l15_n193(x)
+ if (x < 1)
+ fun_l16_n976(x)
+ else
+ fun_l16_n4(x)
+ end
+end
+
+def fun_l15_n194(x)
+ if (x < 1)
+ fun_l16_n423(x)
+ else
+ fun_l16_n612(x)
+ end
+end
+
+def fun_l15_n195(x)
+ if (x < 1)
+ fun_l16_n510(x)
+ else
+ fun_l16_n237(x)
+ end
+end
+
+def fun_l15_n196(x)
+ if (x < 1)
+ fun_l16_n116(x)
+ else
+ fun_l16_n624(x)
+ end
+end
+
+def fun_l15_n197(x)
+ if (x < 1)
+ fun_l16_n515(x)
+ else
+ fun_l16_n979(x)
+ end
+end
+
+def fun_l15_n198(x)
+ if (x < 1)
+ fun_l16_n700(x)
+ else
+ fun_l16_n284(x)
+ end
+end
+
+def fun_l15_n199(x)
+ if (x < 1)
+ fun_l16_n226(x)
+ else
+ fun_l16_n32(x)
+ end
+end
+
+def fun_l15_n200(x)
+ if (x < 1)
+ fun_l16_n453(x)
+ else
+ fun_l16_n959(x)
+ end
+end
+
+def fun_l15_n201(x)
+ if (x < 1)
+ fun_l16_n132(x)
+ else
+ fun_l16_n323(x)
+ end
+end
+
+def fun_l15_n202(x)
+ if (x < 1)
+ fun_l16_n539(x)
+ else
+ fun_l16_n670(x)
+ end
+end
+
+def fun_l15_n203(x)
+ if (x < 1)
+ fun_l16_n786(x)
+ else
+ fun_l16_n633(x)
+ end
+end
+
+def fun_l15_n204(x)
+ if (x < 1)
+ fun_l16_n498(x)
+ else
+ fun_l16_n520(x)
+ end
+end
+
+def fun_l15_n205(x)
+ if (x < 1)
+ fun_l16_n423(x)
+ else
+ fun_l16_n573(x)
+ end
+end
+
+def fun_l15_n206(x)
+ if (x < 1)
+ fun_l16_n746(x)
+ else
+ fun_l16_n562(x)
+ end
+end
+
+def fun_l15_n207(x)
+ if (x < 1)
+ fun_l16_n500(x)
+ else
+ fun_l16_n951(x)
+ end
+end
+
+def fun_l15_n208(x)
+ if (x < 1)
+ fun_l16_n331(x)
+ else
+ fun_l16_n596(x)
+ end
+end
+
+def fun_l15_n209(x)
+ if (x < 1)
+ fun_l16_n1(x)
+ else
+ fun_l16_n69(x)
+ end
+end
+
+def fun_l15_n210(x)
+ if (x < 1)
+ fun_l16_n19(x)
+ else
+ fun_l16_n148(x)
+ end
+end
+
+def fun_l15_n211(x)
+ if (x < 1)
+ fun_l16_n770(x)
+ else
+ fun_l16_n216(x)
+ end
+end
+
+def fun_l15_n212(x)
+ if (x < 1)
+ fun_l16_n863(x)
+ else
+ fun_l16_n319(x)
+ end
+end
+
+def fun_l15_n213(x)
+ if (x < 1)
+ fun_l16_n675(x)
+ else
+ fun_l16_n797(x)
+ end
+end
+
+def fun_l15_n214(x)
+ if (x < 1)
+ fun_l16_n392(x)
+ else
+ fun_l16_n593(x)
+ end
+end
+
+def fun_l15_n215(x)
+ if (x < 1)
+ fun_l16_n120(x)
+ else
+ fun_l16_n232(x)
+ end
+end
+
+def fun_l15_n216(x)
+ if (x < 1)
+ fun_l16_n549(x)
+ else
+ fun_l16_n175(x)
+ end
+end
+
+def fun_l15_n217(x)
+ if (x < 1)
+ fun_l16_n784(x)
+ else
+ fun_l16_n8(x)
+ end
+end
+
+def fun_l15_n218(x)
+ if (x < 1)
+ fun_l16_n296(x)
+ else
+ fun_l16_n454(x)
+ end
+end
+
+def fun_l15_n219(x)
+ if (x < 1)
+ fun_l16_n585(x)
+ else
+ fun_l16_n628(x)
+ end
+end
+
+def fun_l15_n220(x)
+ if (x < 1)
+ fun_l16_n375(x)
+ else
+ fun_l16_n294(x)
+ end
+end
+
+def fun_l15_n221(x)
+ if (x < 1)
+ fun_l16_n69(x)
+ else
+ fun_l16_n771(x)
+ end
+end
+
+def fun_l15_n222(x)
+ if (x < 1)
+ fun_l16_n885(x)
+ else
+ fun_l16_n476(x)
+ end
+end
+
+def fun_l15_n223(x)
+ if (x < 1)
+ fun_l16_n929(x)
+ else
+ fun_l16_n850(x)
+ end
+end
+
+def fun_l15_n224(x)
+ if (x < 1)
+ fun_l16_n489(x)
+ else
+ fun_l16_n234(x)
+ end
+end
+
+def fun_l15_n225(x)
+ if (x < 1)
+ fun_l16_n478(x)
+ else
+ fun_l16_n744(x)
+ end
+end
+
+def fun_l15_n226(x)
+ if (x < 1)
+ fun_l16_n714(x)
+ else
+ fun_l16_n323(x)
+ end
+end
+
+def fun_l15_n227(x)
+ if (x < 1)
+ fun_l16_n146(x)
+ else
+ fun_l16_n937(x)
+ end
+end
+
+def fun_l15_n228(x)
+ if (x < 1)
+ fun_l16_n611(x)
+ else
+ fun_l16_n320(x)
+ end
+end
+
+def fun_l15_n229(x)
+ if (x < 1)
+ fun_l16_n184(x)
+ else
+ fun_l16_n129(x)
+ end
+end
+
+def fun_l15_n230(x)
+ if (x < 1)
+ fun_l16_n563(x)
+ else
+ fun_l16_n581(x)
+ end
+end
+
+def fun_l15_n231(x)
+ if (x < 1)
+ fun_l16_n585(x)
+ else
+ fun_l16_n63(x)
+ end
+end
+
+def fun_l15_n232(x)
+ if (x < 1)
+ fun_l16_n895(x)
+ else
+ fun_l16_n622(x)
+ end
+end
+
+def fun_l15_n233(x)
+ if (x < 1)
+ fun_l16_n998(x)
+ else
+ fun_l16_n95(x)
+ end
+end
+
+def fun_l15_n234(x)
+ if (x < 1)
+ fun_l16_n770(x)
+ else
+ fun_l16_n557(x)
+ end
+end
+
+def fun_l15_n235(x)
+ if (x < 1)
+ fun_l16_n418(x)
+ else
+ fun_l16_n382(x)
+ end
+end
+
+def fun_l15_n236(x)
+ if (x < 1)
+ fun_l16_n842(x)
+ else
+ fun_l16_n543(x)
+ end
+end
+
+def fun_l15_n237(x)
+ if (x < 1)
+ fun_l16_n677(x)
+ else
+ fun_l16_n108(x)
+ end
+end
+
+def fun_l15_n238(x)
+ if (x < 1)
+ fun_l16_n557(x)
+ else
+ fun_l16_n288(x)
+ end
+end
+
+def fun_l15_n239(x)
+ if (x < 1)
+ fun_l16_n467(x)
+ else
+ fun_l16_n661(x)
+ end
+end
+
+def fun_l15_n240(x)
+ if (x < 1)
+ fun_l16_n267(x)
+ else
+ fun_l16_n559(x)
+ end
+end
+
+def fun_l15_n241(x)
+ if (x < 1)
+ fun_l16_n655(x)
+ else
+ fun_l16_n990(x)
+ end
+end
+
+def fun_l15_n242(x)
+ if (x < 1)
+ fun_l16_n673(x)
+ else
+ fun_l16_n390(x)
+ end
+end
+
+def fun_l15_n243(x)
+ if (x < 1)
+ fun_l16_n691(x)
+ else
+ fun_l16_n901(x)
+ end
+end
+
+def fun_l15_n244(x)
+ if (x < 1)
+ fun_l16_n490(x)
+ else
+ fun_l16_n627(x)
+ end
+end
+
+def fun_l15_n245(x)
+ if (x < 1)
+ fun_l16_n293(x)
+ else
+ fun_l16_n569(x)
+ end
+end
+
+def fun_l15_n246(x)
+ if (x < 1)
+ fun_l16_n818(x)
+ else
+ fun_l16_n74(x)
+ end
+end
+
+def fun_l15_n247(x)
+ if (x < 1)
+ fun_l16_n141(x)
+ else
+ fun_l16_n743(x)
+ end
+end
+
+def fun_l15_n248(x)
+ if (x < 1)
+ fun_l16_n819(x)
+ else
+ fun_l16_n141(x)
+ end
+end
+
+def fun_l15_n249(x)
+ if (x < 1)
+ fun_l16_n423(x)
+ else
+ fun_l16_n53(x)
+ end
+end
+
+def fun_l15_n250(x)
+ if (x < 1)
+ fun_l16_n694(x)
+ else
+ fun_l16_n463(x)
+ end
+end
+
+def fun_l15_n251(x)
+ if (x < 1)
+ fun_l16_n828(x)
+ else
+ fun_l16_n739(x)
+ end
+end
+
+def fun_l15_n252(x)
+ if (x < 1)
+ fun_l16_n18(x)
+ else
+ fun_l16_n694(x)
+ end
+end
+
+def fun_l15_n253(x)
+ if (x < 1)
+ fun_l16_n668(x)
+ else
+ fun_l16_n501(x)
+ end
+end
+
+def fun_l15_n254(x)
+ if (x < 1)
+ fun_l16_n649(x)
+ else
+ fun_l16_n397(x)
+ end
+end
+
+def fun_l15_n255(x)
+ if (x < 1)
+ fun_l16_n376(x)
+ else
+ fun_l16_n375(x)
+ end
+end
+
+def fun_l15_n256(x)
+ if (x < 1)
+ fun_l16_n451(x)
+ else
+ fun_l16_n537(x)
+ end
+end
+
+def fun_l15_n257(x)
+ if (x < 1)
+ fun_l16_n360(x)
+ else
+ fun_l16_n330(x)
+ end
+end
+
+def fun_l15_n258(x)
+ if (x < 1)
+ fun_l16_n581(x)
+ else
+ fun_l16_n193(x)
+ end
+end
+
+def fun_l15_n259(x)
+ if (x < 1)
+ fun_l16_n738(x)
+ else
+ fun_l16_n662(x)
+ end
+end
+
+def fun_l15_n260(x)
+ if (x < 1)
+ fun_l16_n450(x)
+ else
+ fun_l16_n942(x)
+ end
+end
+
+def fun_l15_n261(x)
+ if (x < 1)
+ fun_l16_n23(x)
+ else
+ fun_l16_n534(x)
+ end
+end
+
+def fun_l15_n262(x)
+ if (x < 1)
+ fun_l16_n364(x)
+ else
+ fun_l16_n716(x)
+ end
+end
+
+def fun_l15_n263(x)
+ if (x < 1)
+ fun_l16_n528(x)
+ else
+ fun_l16_n185(x)
+ end
+end
+
+def fun_l15_n264(x)
+ if (x < 1)
+ fun_l16_n491(x)
+ else
+ fun_l16_n686(x)
+ end
+end
+
+def fun_l15_n265(x)
+ if (x < 1)
+ fun_l16_n242(x)
+ else
+ fun_l16_n986(x)
+ end
+end
+
+def fun_l15_n266(x)
+ if (x < 1)
+ fun_l16_n726(x)
+ else
+ fun_l16_n88(x)
+ end
+end
+
+def fun_l15_n267(x)
+ if (x < 1)
+ fun_l16_n611(x)
+ else
+ fun_l16_n11(x)
+ end
+end
+
+def fun_l15_n268(x)
+ if (x < 1)
+ fun_l16_n993(x)
+ else
+ fun_l16_n269(x)
+ end
+end
+
+def fun_l15_n269(x)
+ if (x < 1)
+ fun_l16_n296(x)
+ else
+ fun_l16_n8(x)
+ end
+end
+
+def fun_l15_n270(x)
+ if (x < 1)
+ fun_l16_n700(x)
+ else
+ fun_l16_n692(x)
+ end
+end
+
+def fun_l15_n271(x)
+ if (x < 1)
+ fun_l16_n902(x)
+ else
+ fun_l16_n548(x)
+ end
+end
+
+def fun_l15_n272(x)
+ if (x < 1)
+ fun_l16_n39(x)
+ else
+ fun_l16_n635(x)
+ end
+end
+
+def fun_l15_n273(x)
+ if (x < 1)
+ fun_l16_n520(x)
+ else
+ fun_l16_n49(x)
+ end
+end
+
+def fun_l15_n274(x)
+ if (x < 1)
+ fun_l16_n24(x)
+ else
+ fun_l16_n466(x)
+ end
+end
+
+def fun_l15_n275(x)
+ if (x < 1)
+ fun_l16_n144(x)
+ else
+ fun_l16_n555(x)
+ end
+end
+
+def fun_l15_n276(x)
+ if (x < 1)
+ fun_l16_n719(x)
+ else
+ fun_l16_n693(x)
+ end
+end
+
+def fun_l15_n277(x)
+ if (x < 1)
+ fun_l16_n687(x)
+ else
+ fun_l16_n987(x)
+ end
+end
+
+def fun_l15_n278(x)
+ if (x < 1)
+ fun_l16_n426(x)
+ else
+ fun_l16_n179(x)
+ end
+end
+
+def fun_l15_n279(x)
+ if (x < 1)
+ fun_l16_n659(x)
+ else
+ fun_l16_n36(x)
+ end
+end
+
+def fun_l15_n280(x)
+ if (x < 1)
+ fun_l16_n460(x)
+ else
+ fun_l16_n450(x)
+ end
+end
+
+def fun_l15_n281(x)
+ if (x < 1)
+ fun_l16_n42(x)
+ else
+ fun_l16_n230(x)
+ end
+end
+
+def fun_l15_n282(x)
+ if (x < 1)
+ fun_l16_n168(x)
+ else
+ fun_l16_n422(x)
+ end
+end
+
+def fun_l15_n283(x)
+ if (x < 1)
+ fun_l16_n305(x)
+ else
+ fun_l16_n554(x)
+ end
+end
+
+def fun_l15_n284(x)
+ if (x < 1)
+ fun_l16_n680(x)
+ else
+ fun_l16_n147(x)
+ end
+end
+
+def fun_l15_n285(x)
+ if (x < 1)
+ fun_l16_n632(x)
+ else
+ fun_l16_n767(x)
+ end
+end
+
+def fun_l15_n286(x)
+ if (x < 1)
+ fun_l16_n735(x)
+ else
+ fun_l16_n465(x)
+ end
+end
+
+def fun_l15_n287(x)
+ if (x < 1)
+ fun_l16_n17(x)
+ else
+ fun_l16_n638(x)
+ end
+end
+
+def fun_l15_n288(x)
+ if (x < 1)
+ fun_l16_n517(x)
+ else
+ fun_l16_n47(x)
+ end
+end
+
+def fun_l15_n289(x)
+ if (x < 1)
+ fun_l16_n101(x)
+ else
+ fun_l16_n882(x)
+ end
+end
+
+def fun_l15_n290(x)
+ if (x < 1)
+ fun_l16_n697(x)
+ else
+ fun_l16_n963(x)
+ end
+end
+
+def fun_l15_n291(x)
+ if (x < 1)
+ fun_l16_n468(x)
+ else
+ fun_l16_n340(x)
+ end
+end
+
+def fun_l15_n292(x)
+ if (x < 1)
+ fun_l16_n817(x)
+ else
+ fun_l16_n454(x)
+ end
+end
+
+def fun_l15_n293(x)
+ if (x < 1)
+ fun_l16_n885(x)
+ else
+ fun_l16_n733(x)
+ end
+end
+
+def fun_l15_n294(x)
+ if (x < 1)
+ fun_l16_n844(x)
+ else
+ fun_l16_n564(x)
+ end
+end
+
+def fun_l15_n295(x)
+ if (x < 1)
+ fun_l16_n667(x)
+ else
+ fun_l16_n286(x)
+ end
+end
+
+def fun_l15_n296(x)
+ if (x < 1)
+ fun_l16_n694(x)
+ else
+ fun_l16_n660(x)
+ end
+end
+
+def fun_l15_n297(x)
+ if (x < 1)
+ fun_l16_n839(x)
+ else
+ fun_l16_n274(x)
+ end
+end
+
+def fun_l15_n298(x)
+ if (x < 1)
+ fun_l16_n385(x)
+ else
+ fun_l16_n821(x)
+ end
+end
+
+def fun_l15_n299(x)
+ if (x < 1)
+ fun_l16_n137(x)
+ else
+ fun_l16_n548(x)
+ end
+end
+
+def fun_l15_n300(x)
+ if (x < 1)
+ fun_l16_n662(x)
+ else
+ fun_l16_n2(x)
+ end
+end
+
+def fun_l15_n301(x)
+ if (x < 1)
+ fun_l16_n998(x)
+ else
+ fun_l16_n186(x)
+ end
+end
+
+def fun_l15_n302(x)
+ if (x < 1)
+ fun_l16_n667(x)
+ else
+ fun_l16_n454(x)
+ end
+end
+
+def fun_l15_n303(x)
+ if (x < 1)
+ fun_l16_n765(x)
+ else
+ fun_l16_n519(x)
+ end
+end
+
+def fun_l15_n304(x)
+ if (x < 1)
+ fun_l16_n936(x)
+ else
+ fun_l16_n213(x)
+ end
+end
+
+def fun_l15_n305(x)
+ if (x < 1)
+ fun_l16_n695(x)
+ else
+ fun_l16_n545(x)
+ end
+end
+
+def fun_l15_n306(x)
+ if (x < 1)
+ fun_l16_n221(x)
+ else
+ fun_l16_n545(x)
+ end
+end
+
+def fun_l15_n307(x)
+ if (x < 1)
+ fun_l16_n555(x)
+ else
+ fun_l16_n570(x)
+ end
+end
+
+def fun_l15_n308(x)
+ if (x < 1)
+ fun_l16_n57(x)
+ else
+ fun_l16_n91(x)
+ end
+end
+
+def fun_l15_n309(x)
+ if (x < 1)
+ fun_l16_n37(x)
+ else
+ fun_l16_n516(x)
+ end
+end
+
+def fun_l15_n310(x)
+ if (x < 1)
+ fun_l16_n661(x)
+ else
+ fun_l16_n98(x)
+ end
+end
+
+def fun_l15_n311(x)
+ if (x < 1)
+ fun_l16_n119(x)
+ else
+ fun_l16_n613(x)
+ end
+end
+
+def fun_l15_n312(x)
+ if (x < 1)
+ fun_l16_n982(x)
+ else
+ fun_l16_n20(x)
+ end
+end
+
+def fun_l15_n313(x)
+ if (x < 1)
+ fun_l16_n241(x)
+ else
+ fun_l16_n555(x)
+ end
+end
+
+def fun_l15_n314(x)
+ if (x < 1)
+ fun_l16_n638(x)
+ else
+ fun_l16_n854(x)
+ end
+end
+
+def fun_l15_n315(x)
+ if (x < 1)
+ fun_l16_n580(x)
+ else
+ fun_l16_n39(x)
+ end
+end
+
+def fun_l15_n316(x)
+ if (x < 1)
+ fun_l16_n705(x)
+ else
+ fun_l16_n240(x)
+ end
+end
+
+def fun_l15_n317(x)
+ if (x < 1)
+ fun_l16_n395(x)
+ else
+ fun_l16_n114(x)
+ end
+end
+
+def fun_l15_n318(x)
+ if (x < 1)
+ fun_l16_n554(x)
+ else
+ fun_l16_n239(x)
+ end
+end
+
+def fun_l15_n319(x)
+ if (x < 1)
+ fun_l16_n108(x)
+ else
+ fun_l16_n537(x)
+ end
+end
+
+def fun_l15_n320(x)
+ if (x < 1)
+ fun_l16_n554(x)
+ else
+ fun_l16_n902(x)
+ end
+end
+
+def fun_l15_n321(x)
+ if (x < 1)
+ fun_l16_n665(x)
+ else
+ fun_l16_n369(x)
+ end
+end
+
+def fun_l15_n322(x)
+ if (x < 1)
+ fun_l16_n4(x)
+ else
+ fun_l16_n572(x)
+ end
+end
+
+def fun_l15_n323(x)
+ if (x < 1)
+ fun_l16_n579(x)
+ else
+ fun_l16_n182(x)
+ end
+end
+
+def fun_l15_n324(x)
+ if (x < 1)
+ fun_l16_n593(x)
+ else
+ fun_l16_n203(x)
+ end
+end
+
+def fun_l15_n325(x)
+ if (x < 1)
+ fun_l16_n678(x)
+ else
+ fun_l16_n0(x)
+ end
+end
+
+def fun_l15_n326(x)
+ if (x < 1)
+ fun_l16_n809(x)
+ else
+ fun_l16_n833(x)
+ end
+end
+
+def fun_l15_n327(x)
+ if (x < 1)
+ fun_l16_n618(x)
+ else
+ fun_l16_n381(x)
+ end
+end
+
+def fun_l15_n328(x)
+ if (x < 1)
+ fun_l16_n133(x)
+ else
+ fun_l16_n744(x)
+ end
+end
+
+def fun_l15_n329(x)
+ if (x < 1)
+ fun_l16_n488(x)
+ else
+ fun_l16_n88(x)
+ end
+end
+
+def fun_l15_n330(x)
+ if (x < 1)
+ fun_l16_n205(x)
+ else
+ fun_l16_n402(x)
+ end
+end
+
+def fun_l15_n331(x)
+ if (x < 1)
+ fun_l16_n515(x)
+ else
+ fun_l16_n145(x)
+ end
+end
+
+def fun_l15_n332(x)
+ if (x < 1)
+ fun_l16_n581(x)
+ else
+ fun_l16_n607(x)
+ end
+end
+
+def fun_l15_n333(x)
+ if (x < 1)
+ fun_l16_n356(x)
+ else
+ fun_l16_n155(x)
+ end
+end
+
+def fun_l15_n334(x)
+ if (x < 1)
+ fun_l16_n936(x)
+ else
+ fun_l16_n272(x)
+ end
+end
+
+def fun_l15_n335(x)
+ if (x < 1)
+ fun_l16_n714(x)
+ else
+ fun_l16_n245(x)
+ end
+end
+
+def fun_l15_n336(x)
+ if (x < 1)
+ fun_l16_n581(x)
+ else
+ fun_l16_n877(x)
+ end
+end
+
+def fun_l15_n337(x)
+ if (x < 1)
+ fun_l16_n558(x)
+ else
+ fun_l16_n944(x)
+ end
+end
+
+def fun_l15_n338(x)
+ if (x < 1)
+ fun_l16_n49(x)
+ else
+ fun_l16_n501(x)
+ end
+end
+
+def fun_l15_n339(x)
+ if (x < 1)
+ fun_l16_n68(x)
+ else
+ fun_l16_n448(x)
+ end
+end
+
+def fun_l15_n340(x)
+ if (x < 1)
+ fun_l16_n249(x)
+ else
+ fun_l16_n210(x)
+ end
+end
+
+def fun_l15_n341(x)
+ if (x < 1)
+ fun_l16_n720(x)
+ else
+ fun_l16_n977(x)
+ end
+end
+
+def fun_l15_n342(x)
+ if (x < 1)
+ fun_l16_n771(x)
+ else
+ fun_l16_n519(x)
+ end
+end
+
+def fun_l15_n343(x)
+ if (x < 1)
+ fun_l16_n995(x)
+ else
+ fun_l16_n759(x)
+ end
+end
+
+def fun_l15_n344(x)
+ if (x < 1)
+ fun_l16_n972(x)
+ else
+ fun_l16_n558(x)
+ end
+end
+
+def fun_l15_n345(x)
+ if (x < 1)
+ fun_l16_n184(x)
+ else
+ fun_l16_n774(x)
+ end
+end
+
+def fun_l15_n346(x)
+ if (x < 1)
+ fun_l16_n881(x)
+ else
+ fun_l16_n858(x)
+ end
+end
+
+def fun_l15_n347(x)
+ if (x < 1)
+ fun_l16_n921(x)
+ else
+ fun_l16_n640(x)
+ end
+end
+
+def fun_l15_n348(x)
+ if (x < 1)
+ fun_l16_n840(x)
+ else
+ fun_l16_n366(x)
+ end
+end
+
+def fun_l15_n349(x)
+ if (x < 1)
+ fun_l16_n835(x)
+ else
+ fun_l16_n701(x)
+ end
+end
+
+def fun_l15_n350(x)
+ if (x < 1)
+ fun_l16_n304(x)
+ else
+ fun_l16_n144(x)
+ end
+end
+
+def fun_l15_n351(x)
+ if (x < 1)
+ fun_l16_n867(x)
+ else
+ fun_l16_n247(x)
+ end
+end
+
+def fun_l15_n352(x)
+ if (x < 1)
+ fun_l16_n595(x)
+ else
+ fun_l16_n676(x)
+ end
+end
+
+def fun_l15_n353(x)
+ if (x < 1)
+ fun_l16_n125(x)
+ else
+ fun_l16_n99(x)
+ end
+end
+
+def fun_l15_n354(x)
+ if (x < 1)
+ fun_l16_n659(x)
+ else
+ fun_l16_n559(x)
+ end
+end
+
+def fun_l15_n355(x)
+ if (x < 1)
+ fun_l16_n405(x)
+ else
+ fun_l16_n182(x)
+ end
+end
+
+def fun_l15_n356(x)
+ if (x < 1)
+ fun_l16_n347(x)
+ else
+ fun_l16_n482(x)
+ end
+end
+
+def fun_l15_n357(x)
+ if (x < 1)
+ fun_l16_n742(x)
+ else
+ fun_l16_n531(x)
+ end
+end
+
+def fun_l15_n358(x)
+ if (x < 1)
+ fun_l16_n954(x)
+ else
+ fun_l16_n908(x)
+ end
+end
+
+def fun_l15_n359(x)
+ if (x < 1)
+ fun_l16_n670(x)
+ else
+ fun_l16_n401(x)
+ end
+end
+
+def fun_l15_n360(x)
+ if (x < 1)
+ fun_l16_n423(x)
+ else
+ fun_l16_n802(x)
+ end
+end
+
+def fun_l15_n361(x)
+ if (x < 1)
+ fun_l16_n12(x)
+ else
+ fun_l16_n985(x)
+ end
+end
+
+def fun_l15_n362(x)
+ if (x < 1)
+ fun_l16_n644(x)
+ else
+ fun_l16_n40(x)
+ end
+end
+
+def fun_l15_n363(x)
+ if (x < 1)
+ fun_l16_n491(x)
+ else
+ fun_l16_n255(x)
+ end
+end
+
+def fun_l15_n364(x)
+ if (x < 1)
+ fun_l16_n14(x)
+ else
+ fun_l16_n433(x)
+ end
+end
+
+def fun_l15_n365(x)
+ if (x < 1)
+ fun_l16_n652(x)
+ else
+ fun_l16_n418(x)
+ end
+end
+
+def fun_l15_n366(x)
+ if (x < 1)
+ fun_l16_n815(x)
+ else
+ fun_l16_n325(x)
+ end
+end
+
+def fun_l15_n367(x)
+ if (x < 1)
+ fun_l16_n623(x)
+ else
+ fun_l16_n34(x)
+ end
+end
+
+def fun_l15_n368(x)
+ if (x < 1)
+ fun_l16_n596(x)
+ else
+ fun_l16_n382(x)
+ end
+end
+
+def fun_l15_n369(x)
+ if (x < 1)
+ fun_l16_n144(x)
+ else
+ fun_l16_n18(x)
+ end
+end
+
+def fun_l15_n370(x)
+ if (x < 1)
+ fun_l16_n37(x)
+ else
+ fun_l16_n626(x)
+ end
+end
+
+def fun_l15_n371(x)
+ if (x < 1)
+ fun_l16_n275(x)
+ else
+ fun_l16_n343(x)
+ end
+end
+
+def fun_l15_n372(x)
+ if (x < 1)
+ fun_l16_n951(x)
+ else
+ fun_l16_n93(x)
+ end
+end
+
+def fun_l15_n373(x)
+ if (x < 1)
+ fun_l16_n893(x)
+ else
+ fun_l16_n137(x)
+ end
+end
+
+def fun_l15_n374(x)
+ if (x < 1)
+ fun_l16_n32(x)
+ else
+ fun_l16_n663(x)
+ end
+end
+
+def fun_l15_n375(x)
+ if (x < 1)
+ fun_l16_n888(x)
+ else
+ fun_l16_n708(x)
+ end
+end
+
+def fun_l15_n376(x)
+ if (x < 1)
+ fun_l16_n745(x)
+ else
+ fun_l16_n275(x)
+ end
+end
+
+def fun_l15_n377(x)
+ if (x < 1)
+ fun_l16_n957(x)
+ else
+ fun_l16_n766(x)
+ end
+end
+
+def fun_l15_n378(x)
+ if (x < 1)
+ fun_l16_n242(x)
+ else
+ fun_l16_n309(x)
+ end
+end
+
+def fun_l15_n379(x)
+ if (x < 1)
+ fun_l16_n855(x)
+ else
+ fun_l16_n289(x)
+ end
+end
+
+def fun_l15_n380(x)
+ if (x < 1)
+ fun_l16_n511(x)
+ else
+ fun_l16_n261(x)
+ end
+end
+
+def fun_l15_n381(x)
+ if (x < 1)
+ fun_l16_n867(x)
+ else
+ fun_l16_n169(x)
+ end
+end
+
+def fun_l15_n382(x)
+ if (x < 1)
+ fun_l16_n646(x)
+ else
+ fun_l16_n821(x)
+ end
+end
+
+def fun_l15_n383(x)
+ if (x < 1)
+ fun_l16_n181(x)
+ else
+ fun_l16_n798(x)
+ end
+end
+
+def fun_l15_n384(x)
+ if (x < 1)
+ fun_l16_n290(x)
+ else
+ fun_l16_n756(x)
+ end
+end
+
+def fun_l15_n385(x)
+ if (x < 1)
+ fun_l16_n896(x)
+ else
+ fun_l16_n14(x)
+ end
+end
+
+def fun_l15_n386(x)
+ if (x < 1)
+ fun_l16_n602(x)
+ else
+ fun_l16_n817(x)
+ end
+end
+
+def fun_l15_n387(x)
+ if (x < 1)
+ fun_l16_n908(x)
+ else
+ fun_l16_n773(x)
+ end
+end
+
+def fun_l15_n388(x)
+ if (x < 1)
+ fun_l16_n708(x)
+ else
+ fun_l16_n416(x)
+ end
+end
+
+def fun_l15_n389(x)
+ if (x < 1)
+ fun_l16_n42(x)
+ else
+ fun_l16_n325(x)
+ end
+end
+
+def fun_l15_n390(x)
+ if (x < 1)
+ fun_l16_n245(x)
+ else
+ fun_l16_n211(x)
+ end
+end
+
+def fun_l15_n391(x)
+ if (x < 1)
+ fun_l16_n674(x)
+ else
+ fun_l16_n854(x)
+ end
+end
+
+def fun_l15_n392(x)
+ if (x < 1)
+ fun_l16_n294(x)
+ else
+ fun_l16_n299(x)
+ end
+end
+
+def fun_l15_n393(x)
+ if (x < 1)
+ fun_l16_n873(x)
+ else
+ fun_l16_n17(x)
+ end
+end
+
+def fun_l15_n394(x)
+ if (x < 1)
+ fun_l16_n375(x)
+ else
+ fun_l16_n976(x)
+ end
+end
+
+def fun_l15_n395(x)
+ if (x < 1)
+ fun_l16_n753(x)
+ else
+ fun_l16_n362(x)
+ end
+end
+
+def fun_l15_n396(x)
+ if (x < 1)
+ fun_l16_n326(x)
+ else
+ fun_l16_n878(x)
+ end
+end
+
+def fun_l15_n397(x)
+ if (x < 1)
+ fun_l16_n118(x)
+ else
+ fun_l16_n552(x)
+ end
+end
+
+def fun_l15_n398(x)
+ if (x < 1)
+ fun_l16_n931(x)
+ else
+ fun_l16_n552(x)
+ end
+end
+
+def fun_l15_n399(x)
+ if (x < 1)
+ fun_l16_n125(x)
+ else
+ fun_l16_n817(x)
+ end
+end
+
+def fun_l15_n400(x)
+ if (x < 1)
+ fun_l16_n747(x)
+ else
+ fun_l16_n328(x)
+ end
+end
+
+def fun_l15_n401(x)
+ if (x < 1)
+ fun_l16_n204(x)
+ else
+ fun_l16_n644(x)
+ end
+end
+
+def fun_l15_n402(x)
+ if (x < 1)
+ fun_l16_n730(x)
+ else
+ fun_l16_n622(x)
+ end
+end
+
+def fun_l15_n403(x)
+ if (x < 1)
+ fun_l16_n718(x)
+ else
+ fun_l16_n616(x)
+ end
+end
+
+def fun_l15_n404(x)
+ if (x < 1)
+ fun_l16_n260(x)
+ else
+ fun_l16_n96(x)
+ end
+end
+
+def fun_l15_n405(x)
+ if (x < 1)
+ fun_l16_n123(x)
+ else
+ fun_l16_n377(x)
+ end
+end
+
+def fun_l15_n406(x)
+ if (x < 1)
+ fun_l16_n425(x)
+ else
+ fun_l16_n601(x)
+ end
+end
+
+def fun_l15_n407(x)
+ if (x < 1)
+ fun_l16_n842(x)
+ else
+ fun_l16_n936(x)
+ end
+end
+
+def fun_l15_n408(x)
+ if (x < 1)
+ fun_l16_n797(x)
+ else
+ fun_l16_n194(x)
+ end
+end
+
+def fun_l15_n409(x)
+ if (x < 1)
+ fun_l16_n930(x)
+ else
+ fun_l16_n976(x)
+ end
+end
+
+def fun_l15_n410(x)
+ if (x < 1)
+ fun_l16_n163(x)
+ else
+ fun_l16_n703(x)
+ end
+end
+
+def fun_l15_n411(x)
+ if (x < 1)
+ fun_l16_n109(x)
+ else
+ fun_l16_n276(x)
+ end
+end
+
+def fun_l15_n412(x)
+ if (x < 1)
+ fun_l16_n37(x)
+ else
+ fun_l16_n372(x)
+ end
+end
+
+def fun_l15_n413(x)
+ if (x < 1)
+ fun_l16_n995(x)
+ else
+ fun_l16_n762(x)
+ end
+end
+
+def fun_l15_n414(x)
+ if (x < 1)
+ fun_l16_n789(x)
+ else
+ fun_l16_n601(x)
+ end
+end
+
+def fun_l15_n415(x)
+ if (x < 1)
+ fun_l16_n699(x)
+ else
+ fun_l16_n853(x)
+ end
+end
+
+def fun_l15_n416(x)
+ if (x < 1)
+ fun_l16_n936(x)
+ else
+ fun_l16_n478(x)
+ end
+end
+
+def fun_l15_n417(x)
+ if (x < 1)
+ fun_l16_n50(x)
+ else
+ fun_l16_n67(x)
+ end
+end
+
+def fun_l15_n418(x)
+ if (x < 1)
+ fun_l16_n563(x)
+ else
+ fun_l16_n248(x)
+ end
+end
+
+def fun_l15_n419(x)
+ if (x < 1)
+ fun_l16_n238(x)
+ else
+ fun_l16_n188(x)
+ end
+end
+
+def fun_l15_n420(x)
+ if (x < 1)
+ fun_l16_n369(x)
+ else
+ fun_l16_n706(x)
+ end
+end
+
+def fun_l15_n421(x)
+ if (x < 1)
+ fun_l16_n641(x)
+ else
+ fun_l16_n869(x)
+ end
+end
+
+def fun_l15_n422(x)
+ if (x < 1)
+ fun_l16_n219(x)
+ else
+ fun_l16_n333(x)
+ end
+end
+
+def fun_l15_n423(x)
+ if (x < 1)
+ fun_l16_n156(x)
+ else
+ fun_l16_n22(x)
+ end
+end
+
+def fun_l15_n424(x)
+ if (x < 1)
+ fun_l16_n443(x)
+ else
+ fun_l16_n1(x)
+ end
+end
+
+def fun_l15_n425(x)
+ if (x < 1)
+ fun_l16_n892(x)
+ else
+ fun_l16_n937(x)
+ end
+end
+
+def fun_l15_n426(x)
+ if (x < 1)
+ fun_l16_n586(x)
+ else
+ fun_l16_n636(x)
+ end
+end
+
+def fun_l15_n427(x)
+ if (x < 1)
+ fun_l16_n519(x)
+ else
+ fun_l16_n269(x)
+ end
+end
+
+def fun_l15_n428(x)
+ if (x < 1)
+ fun_l16_n379(x)
+ else
+ fun_l16_n994(x)
+ end
+end
+
+def fun_l15_n429(x)
+ if (x < 1)
+ fun_l16_n588(x)
+ else
+ fun_l16_n532(x)
+ end
+end
+
+def fun_l15_n430(x)
+ if (x < 1)
+ fun_l16_n584(x)
+ else
+ fun_l16_n445(x)
+ end
+end
+
+def fun_l15_n431(x)
+ if (x < 1)
+ fun_l16_n63(x)
+ else
+ fun_l16_n678(x)
+ end
+end
+
+def fun_l15_n432(x)
+ if (x < 1)
+ fun_l16_n487(x)
+ else
+ fun_l16_n435(x)
+ end
+end
+
+def fun_l15_n433(x)
+ if (x < 1)
+ fun_l16_n673(x)
+ else
+ fun_l16_n220(x)
+ end
+end
+
+def fun_l15_n434(x)
+ if (x < 1)
+ fun_l16_n131(x)
+ else
+ fun_l16_n751(x)
+ end
+end
+
+def fun_l15_n435(x)
+ if (x < 1)
+ fun_l16_n557(x)
+ else
+ fun_l16_n340(x)
+ end
+end
+
+def fun_l15_n436(x)
+ if (x < 1)
+ fun_l16_n511(x)
+ else
+ fun_l16_n751(x)
+ end
+end
+
+def fun_l15_n437(x)
+ if (x < 1)
+ fun_l16_n983(x)
+ else
+ fun_l16_n632(x)
+ end
+end
+
+def fun_l15_n438(x)
+ if (x < 1)
+ fun_l16_n350(x)
+ else
+ fun_l16_n492(x)
+ end
+end
+
+def fun_l15_n439(x)
+ if (x < 1)
+ fun_l16_n994(x)
+ else
+ fun_l16_n76(x)
+ end
+end
+
+def fun_l15_n440(x)
+ if (x < 1)
+ fun_l16_n756(x)
+ else
+ fun_l16_n177(x)
+ end
+end
+
+def fun_l15_n441(x)
+ if (x < 1)
+ fun_l16_n619(x)
+ else
+ fun_l16_n473(x)
+ end
+end
+
+def fun_l15_n442(x)
+ if (x < 1)
+ fun_l16_n667(x)
+ else
+ fun_l16_n714(x)
+ end
+end
+
+def fun_l15_n443(x)
+ if (x < 1)
+ fun_l16_n790(x)
+ else
+ fun_l16_n848(x)
+ end
+end
+
+def fun_l15_n444(x)
+ if (x < 1)
+ fun_l16_n925(x)
+ else
+ fun_l16_n113(x)
+ end
+end
+
+def fun_l15_n445(x)
+ if (x < 1)
+ fun_l16_n990(x)
+ else
+ fun_l16_n566(x)
+ end
+end
+
+def fun_l15_n446(x)
+ if (x < 1)
+ fun_l16_n589(x)
+ else
+ fun_l16_n881(x)
+ end
+end
+
+def fun_l15_n447(x)
+ if (x < 1)
+ fun_l16_n961(x)
+ else
+ fun_l16_n786(x)
+ end
+end
+
+def fun_l15_n448(x)
+ if (x < 1)
+ fun_l16_n928(x)
+ else
+ fun_l16_n631(x)
+ end
+end
+
+def fun_l15_n449(x)
+ if (x < 1)
+ fun_l16_n317(x)
+ else
+ fun_l16_n980(x)
+ end
+end
+
+def fun_l15_n450(x)
+ if (x < 1)
+ fun_l16_n276(x)
+ else
+ fun_l16_n941(x)
+ end
+end
+
+def fun_l15_n451(x)
+ if (x < 1)
+ fun_l16_n552(x)
+ else
+ fun_l16_n545(x)
+ end
+end
+
+def fun_l15_n452(x)
+ if (x < 1)
+ fun_l16_n334(x)
+ else
+ fun_l16_n340(x)
+ end
+end
+
+def fun_l15_n453(x)
+ if (x < 1)
+ fun_l16_n800(x)
+ else
+ fun_l16_n548(x)
+ end
+end
+
+def fun_l15_n454(x)
+ if (x < 1)
+ fun_l16_n676(x)
+ else
+ fun_l16_n742(x)
+ end
+end
+
+def fun_l15_n455(x)
+ if (x < 1)
+ fun_l16_n722(x)
+ else
+ fun_l16_n446(x)
+ end
+end
+
+def fun_l15_n456(x)
+ if (x < 1)
+ fun_l16_n570(x)
+ else
+ fun_l16_n203(x)
+ end
+end
+
+def fun_l15_n457(x)
+ if (x < 1)
+ fun_l16_n425(x)
+ else
+ fun_l16_n401(x)
+ end
+end
+
+def fun_l15_n458(x)
+ if (x < 1)
+ fun_l16_n3(x)
+ else
+ fun_l16_n483(x)
+ end
+end
+
+def fun_l15_n459(x)
+ if (x < 1)
+ fun_l16_n450(x)
+ else
+ fun_l16_n468(x)
+ end
+end
+
+def fun_l15_n460(x)
+ if (x < 1)
+ fun_l16_n447(x)
+ else
+ fun_l16_n758(x)
+ end
+end
+
+def fun_l15_n461(x)
+ if (x < 1)
+ fun_l16_n531(x)
+ else
+ fun_l16_n268(x)
+ end
+end
+
+def fun_l15_n462(x)
+ if (x < 1)
+ fun_l16_n628(x)
+ else
+ fun_l16_n142(x)
+ end
+end
+
+def fun_l15_n463(x)
+ if (x < 1)
+ fun_l16_n823(x)
+ else
+ fun_l16_n97(x)
+ end
+end
+
+def fun_l15_n464(x)
+ if (x < 1)
+ fun_l16_n807(x)
+ else
+ fun_l16_n231(x)
+ end
+end
+
+def fun_l15_n465(x)
+ if (x < 1)
+ fun_l16_n113(x)
+ else
+ fun_l16_n438(x)
+ end
+end
+
+def fun_l15_n466(x)
+ if (x < 1)
+ fun_l16_n234(x)
+ else
+ fun_l16_n369(x)
+ end
+end
+
+def fun_l15_n467(x)
+ if (x < 1)
+ fun_l16_n242(x)
+ else
+ fun_l16_n121(x)
+ end
+end
+
+def fun_l15_n468(x)
+ if (x < 1)
+ fun_l16_n38(x)
+ else
+ fun_l16_n223(x)
+ end
+end
+
+def fun_l15_n469(x)
+ if (x < 1)
+ fun_l16_n618(x)
+ else
+ fun_l16_n550(x)
+ end
+end
+
+def fun_l15_n470(x)
+ if (x < 1)
+ fun_l16_n318(x)
+ else
+ fun_l16_n182(x)
+ end
+end
+
+def fun_l15_n471(x)
+ if (x < 1)
+ fun_l16_n782(x)
+ else
+ fun_l16_n876(x)
+ end
+end
+
+def fun_l15_n472(x)
+ if (x < 1)
+ fun_l16_n995(x)
+ else
+ fun_l16_n4(x)
+ end
+end
+
+def fun_l15_n473(x)
+ if (x < 1)
+ fun_l16_n425(x)
+ else
+ fun_l16_n891(x)
+ end
+end
+
+def fun_l15_n474(x)
+ if (x < 1)
+ fun_l16_n263(x)
+ else
+ fun_l16_n278(x)
+ end
+end
+
+def fun_l15_n475(x)
+ if (x < 1)
+ fun_l16_n116(x)
+ else
+ fun_l16_n62(x)
+ end
+end
+
+def fun_l15_n476(x)
+ if (x < 1)
+ fun_l16_n855(x)
+ else
+ fun_l16_n153(x)
+ end
+end
+
+def fun_l15_n477(x)
+ if (x < 1)
+ fun_l16_n979(x)
+ else
+ fun_l16_n957(x)
+ end
+end
+
+def fun_l15_n478(x)
+ if (x < 1)
+ fun_l16_n671(x)
+ else
+ fun_l16_n694(x)
+ end
+end
+
+def fun_l15_n479(x)
+ if (x < 1)
+ fun_l16_n479(x)
+ else
+ fun_l16_n400(x)
+ end
+end
+
+def fun_l15_n480(x)
+ if (x < 1)
+ fun_l16_n740(x)
+ else
+ fun_l16_n940(x)
+ end
+end
+
+def fun_l15_n481(x)
+ if (x < 1)
+ fun_l16_n270(x)
+ else
+ fun_l16_n802(x)
+ end
+end
+
+def fun_l15_n482(x)
+ if (x < 1)
+ fun_l16_n489(x)
+ else
+ fun_l16_n402(x)
+ end
+end
+
+def fun_l15_n483(x)
+ if (x < 1)
+ fun_l16_n505(x)
+ else
+ fun_l16_n97(x)
+ end
+end
+
+def fun_l15_n484(x)
+ if (x < 1)
+ fun_l16_n64(x)
+ else
+ fun_l16_n748(x)
+ end
+end
+
+def fun_l15_n485(x)
+ if (x < 1)
+ fun_l16_n7(x)
+ else
+ fun_l16_n627(x)
+ end
+end
+
+def fun_l15_n486(x)
+ if (x < 1)
+ fun_l16_n302(x)
+ else
+ fun_l16_n331(x)
+ end
+end
+
+def fun_l15_n487(x)
+ if (x < 1)
+ fun_l16_n771(x)
+ else
+ fun_l16_n895(x)
+ end
+end
+
+def fun_l15_n488(x)
+ if (x < 1)
+ fun_l16_n306(x)
+ else
+ fun_l16_n740(x)
+ end
+end
+
+def fun_l15_n489(x)
+ if (x < 1)
+ fun_l16_n722(x)
+ else
+ fun_l16_n848(x)
+ end
+end
+
+def fun_l15_n490(x)
+ if (x < 1)
+ fun_l16_n764(x)
+ else
+ fun_l16_n851(x)
+ end
+end
+
+def fun_l15_n491(x)
+ if (x < 1)
+ fun_l16_n357(x)
+ else
+ fun_l16_n117(x)
+ end
+end
+
+def fun_l15_n492(x)
+ if (x < 1)
+ fun_l16_n483(x)
+ else
+ fun_l16_n187(x)
+ end
+end
+
+def fun_l15_n493(x)
+ if (x < 1)
+ fun_l16_n695(x)
+ else
+ fun_l16_n727(x)
+ end
+end
+
+def fun_l15_n494(x)
+ if (x < 1)
+ fun_l16_n460(x)
+ else
+ fun_l16_n154(x)
+ end
+end
+
+def fun_l15_n495(x)
+ if (x < 1)
+ fun_l16_n130(x)
+ else
+ fun_l16_n999(x)
+ end
+end
+
+def fun_l15_n496(x)
+ if (x < 1)
+ fun_l16_n963(x)
+ else
+ fun_l16_n746(x)
+ end
+end
+
+def fun_l15_n497(x)
+ if (x < 1)
+ fun_l16_n630(x)
+ else
+ fun_l16_n852(x)
+ end
+end
+
+def fun_l15_n498(x)
+ if (x < 1)
+ fun_l16_n847(x)
+ else
+ fun_l16_n836(x)
+ end
+end
+
+def fun_l15_n499(x)
+ if (x < 1)
+ fun_l16_n100(x)
+ else
+ fun_l16_n40(x)
+ end
+end
+
+def fun_l15_n500(x)
+ if (x < 1)
+ fun_l16_n246(x)
+ else
+ fun_l16_n442(x)
+ end
+end
+
+def fun_l15_n501(x)
+ if (x < 1)
+ fun_l16_n355(x)
+ else
+ fun_l16_n405(x)
+ end
+end
+
+def fun_l15_n502(x)
+ if (x < 1)
+ fun_l16_n857(x)
+ else
+ fun_l16_n652(x)
+ end
+end
+
+def fun_l15_n503(x)
+ if (x < 1)
+ fun_l16_n612(x)
+ else
+ fun_l16_n779(x)
+ end
+end
+
+def fun_l15_n504(x)
+ if (x < 1)
+ fun_l16_n836(x)
+ else
+ fun_l16_n625(x)
+ end
+end
+
+def fun_l15_n505(x)
+ if (x < 1)
+ fun_l16_n872(x)
+ else
+ fun_l16_n905(x)
+ end
+end
+
+def fun_l15_n506(x)
+ if (x < 1)
+ fun_l16_n953(x)
+ else
+ fun_l16_n955(x)
+ end
+end
+
+def fun_l15_n507(x)
+ if (x < 1)
+ fun_l16_n678(x)
+ else
+ fun_l16_n663(x)
+ end
+end
+
+def fun_l15_n508(x)
+ if (x < 1)
+ fun_l16_n848(x)
+ else
+ fun_l16_n438(x)
+ end
+end
+
+def fun_l15_n509(x)
+ if (x < 1)
+ fun_l16_n558(x)
+ else
+ fun_l16_n430(x)
+ end
+end
+
+def fun_l15_n510(x)
+ if (x < 1)
+ fun_l16_n424(x)
+ else
+ fun_l16_n473(x)
+ end
+end
+
+def fun_l15_n511(x)
+ if (x < 1)
+ fun_l16_n897(x)
+ else
+ fun_l16_n359(x)
+ end
+end
+
+def fun_l15_n512(x)
+ if (x < 1)
+ fun_l16_n229(x)
+ else
+ fun_l16_n205(x)
+ end
+end
+
+def fun_l15_n513(x)
+ if (x < 1)
+ fun_l16_n553(x)
+ else
+ fun_l16_n438(x)
+ end
+end
+
+def fun_l15_n514(x)
+ if (x < 1)
+ fun_l16_n300(x)
+ else
+ fun_l16_n588(x)
+ end
+end
+
+def fun_l15_n515(x)
+ if (x < 1)
+ fun_l16_n819(x)
+ else
+ fun_l16_n467(x)
+ end
+end
+
+def fun_l15_n516(x)
+ if (x < 1)
+ fun_l16_n767(x)
+ else
+ fun_l16_n786(x)
+ end
+end
+
+def fun_l15_n517(x)
+ if (x < 1)
+ fun_l16_n50(x)
+ else
+ fun_l16_n309(x)
+ end
+end
+
+def fun_l15_n518(x)
+ if (x < 1)
+ fun_l16_n671(x)
+ else
+ fun_l16_n635(x)
+ end
+end
+
+def fun_l15_n519(x)
+ if (x < 1)
+ fun_l16_n935(x)
+ else
+ fun_l16_n497(x)
+ end
+end
+
+def fun_l15_n520(x)
+ if (x < 1)
+ fun_l16_n343(x)
+ else
+ fun_l16_n175(x)
+ end
+end
+
+def fun_l15_n521(x)
+ if (x < 1)
+ fun_l16_n212(x)
+ else
+ fun_l16_n987(x)
+ end
+end
+
+def fun_l15_n522(x)
+ if (x < 1)
+ fun_l16_n780(x)
+ else
+ fun_l16_n331(x)
+ end
+end
+
+def fun_l15_n523(x)
+ if (x < 1)
+ fun_l16_n452(x)
+ else
+ fun_l16_n393(x)
+ end
+end
+
+def fun_l15_n524(x)
+ if (x < 1)
+ fun_l16_n823(x)
+ else
+ fun_l16_n212(x)
+ end
+end
+
+def fun_l15_n525(x)
+ if (x < 1)
+ fun_l16_n516(x)
+ else
+ fun_l16_n906(x)
+ end
+end
+
+def fun_l15_n526(x)
+ if (x < 1)
+ fun_l16_n590(x)
+ else
+ fun_l16_n278(x)
+ end
+end
+
+def fun_l15_n527(x)
+ if (x < 1)
+ fun_l16_n392(x)
+ else
+ fun_l16_n714(x)
+ end
+end
+
+def fun_l15_n528(x)
+ if (x < 1)
+ fun_l16_n729(x)
+ else
+ fun_l16_n751(x)
+ end
+end
+
+def fun_l15_n529(x)
+ if (x < 1)
+ fun_l16_n863(x)
+ else
+ fun_l16_n478(x)
+ end
+end
+
+def fun_l15_n530(x)
+ if (x < 1)
+ fun_l16_n472(x)
+ else
+ fun_l16_n672(x)
+ end
+end
+
+def fun_l15_n531(x)
+ if (x < 1)
+ fun_l16_n811(x)
+ else
+ fun_l16_n201(x)
+ end
+end
+
+def fun_l15_n532(x)
+ if (x < 1)
+ fun_l16_n558(x)
+ else
+ fun_l16_n602(x)
+ end
+end
+
+def fun_l15_n533(x)
+ if (x < 1)
+ fun_l16_n788(x)
+ else
+ fun_l16_n175(x)
+ end
+end
+
+def fun_l15_n534(x)
+ if (x < 1)
+ fun_l16_n497(x)
+ else
+ fun_l16_n807(x)
+ end
+end
+
+def fun_l15_n535(x)
+ if (x < 1)
+ fun_l16_n712(x)
+ else
+ fun_l16_n870(x)
+ end
+end
+
+def fun_l15_n536(x)
+ if (x < 1)
+ fun_l16_n699(x)
+ else
+ fun_l16_n879(x)
+ end
+end
+
+def fun_l15_n537(x)
+ if (x < 1)
+ fun_l16_n215(x)
+ else
+ fun_l16_n807(x)
+ end
+end
+
+def fun_l15_n538(x)
+ if (x < 1)
+ fun_l16_n569(x)
+ else
+ fun_l16_n385(x)
+ end
+end
+
+def fun_l15_n539(x)
+ if (x < 1)
+ fun_l16_n807(x)
+ else
+ fun_l16_n699(x)
+ end
+end
+
+def fun_l15_n540(x)
+ if (x < 1)
+ fun_l16_n982(x)
+ else
+ fun_l16_n436(x)
+ end
+end
+
+def fun_l15_n541(x)
+ if (x < 1)
+ fun_l16_n852(x)
+ else
+ fun_l16_n800(x)
+ end
+end
+
+def fun_l15_n542(x)
+ if (x < 1)
+ fun_l16_n401(x)
+ else
+ fun_l16_n478(x)
+ end
+end
+
+def fun_l15_n543(x)
+ if (x < 1)
+ fun_l16_n373(x)
+ else
+ fun_l16_n465(x)
+ end
+end
+
+def fun_l15_n544(x)
+ if (x < 1)
+ fun_l16_n299(x)
+ else
+ fun_l16_n337(x)
+ end
+end
+
+def fun_l15_n545(x)
+ if (x < 1)
+ fun_l16_n931(x)
+ else
+ fun_l16_n68(x)
+ end
+end
+
+def fun_l15_n546(x)
+ if (x < 1)
+ fun_l16_n87(x)
+ else
+ fun_l16_n947(x)
+ end
+end
+
+def fun_l15_n547(x)
+ if (x < 1)
+ fun_l16_n287(x)
+ else
+ fun_l16_n530(x)
+ end
+end
+
+def fun_l15_n548(x)
+ if (x < 1)
+ fun_l16_n910(x)
+ else
+ fun_l16_n112(x)
+ end
+end
+
+def fun_l15_n549(x)
+ if (x < 1)
+ fun_l16_n878(x)
+ else
+ fun_l16_n737(x)
+ end
+end
+
+def fun_l15_n550(x)
+ if (x < 1)
+ fun_l16_n538(x)
+ else
+ fun_l16_n634(x)
+ end
+end
+
+def fun_l15_n551(x)
+ if (x < 1)
+ fun_l16_n109(x)
+ else
+ fun_l16_n493(x)
+ end
+end
+
+def fun_l15_n552(x)
+ if (x < 1)
+ fun_l16_n631(x)
+ else
+ fun_l16_n244(x)
+ end
+end
+
+def fun_l15_n553(x)
+ if (x < 1)
+ fun_l16_n107(x)
+ else
+ fun_l16_n718(x)
+ end
+end
+
+def fun_l15_n554(x)
+ if (x < 1)
+ fun_l16_n572(x)
+ else
+ fun_l16_n199(x)
+ end
+end
+
+def fun_l15_n555(x)
+ if (x < 1)
+ fun_l16_n109(x)
+ else
+ fun_l16_n705(x)
+ end
+end
+
+def fun_l15_n556(x)
+ if (x < 1)
+ fun_l16_n679(x)
+ else
+ fun_l16_n999(x)
+ end
+end
+
+def fun_l15_n557(x)
+ if (x < 1)
+ fun_l16_n714(x)
+ else
+ fun_l16_n121(x)
+ end
+end
+
+def fun_l15_n558(x)
+ if (x < 1)
+ fun_l16_n408(x)
+ else
+ fun_l16_n239(x)
+ end
+end
+
+def fun_l15_n559(x)
+ if (x < 1)
+ fun_l16_n861(x)
+ else
+ fun_l16_n83(x)
+ end
+end
+
+def fun_l15_n560(x)
+ if (x < 1)
+ fun_l16_n597(x)
+ else
+ fun_l16_n413(x)
+ end
+end
+
+def fun_l15_n561(x)
+ if (x < 1)
+ fun_l16_n485(x)
+ else
+ fun_l16_n42(x)
+ end
+end
+
+def fun_l15_n562(x)
+ if (x < 1)
+ fun_l16_n798(x)
+ else
+ fun_l16_n340(x)
+ end
+end
+
+def fun_l15_n563(x)
+ if (x < 1)
+ fun_l16_n50(x)
+ else
+ fun_l16_n858(x)
+ end
+end
+
+def fun_l15_n564(x)
+ if (x < 1)
+ fun_l16_n92(x)
+ else
+ fun_l16_n3(x)
+ end
+end
+
+def fun_l15_n565(x)
+ if (x < 1)
+ fun_l16_n311(x)
+ else
+ fun_l16_n953(x)
+ end
+end
+
+def fun_l15_n566(x)
+ if (x < 1)
+ fun_l16_n649(x)
+ else
+ fun_l16_n670(x)
+ end
+end
+
+def fun_l15_n567(x)
+ if (x < 1)
+ fun_l16_n598(x)
+ else
+ fun_l16_n268(x)
+ end
+end
+
+def fun_l15_n568(x)
+ if (x < 1)
+ fun_l16_n425(x)
+ else
+ fun_l16_n821(x)
+ end
+end
+
+def fun_l15_n569(x)
+ if (x < 1)
+ fun_l16_n447(x)
+ else
+ fun_l16_n940(x)
+ end
+end
+
+def fun_l15_n570(x)
+ if (x < 1)
+ fun_l16_n755(x)
+ else
+ fun_l16_n26(x)
+ end
+end
+
+def fun_l15_n571(x)
+ if (x < 1)
+ fun_l16_n157(x)
+ else
+ fun_l16_n582(x)
+ end
+end
+
+def fun_l15_n572(x)
+ if (x < 1)
+ fun_l16_n530(x)
+ else
+ fun_l16_n202(x)
+ end
+end
+
+def fun_l15_n573(x)
+ if (x < 1)
+ fun_l16_n95(x)
+ else
+ fun_l16_n137(x)
+ end
+end
+
+def fun_l15_n574(x)
+ if (x < 1)
+ fun_l16_n789(x)
+ else
+ fun_l16_n531(x)
+ end
+end
+
+def fun_l15_n575(x)
+ if (x < 1)
+ fun_l16_n677(x)
+ else
+ fun_l16_n686(x)
+ end
+end
+
+def fun_l15_n576(x)
+ if (x < 1)
+ fun_l16_n253(x)
+ else
+ fun_l16_n101(x)
+ end
+end
+
+def fun_l15_n577(x)
+ if (x < 1)
+ fun_l16_n579(x)
+ else
+ fun_l16_n250(x)
+ end
+end
+
+def fun_l15_n578(x)
+ if (x < 1)
+ fun_l16_n104(x)
+ else
+ fun_l16_n860(x)
+ end
+end
+
+def fun_l15_n579(x)
+ if (x < 1)
+ fun_l16_n415(x)
+ else
+ fun_l16_n480(x)
+ end
+end
+
+def fun_l15_n580(x)
+ if (x < 1)
+ fun_l16_n255(x)
+ else
+ fun_l16_n123(x)
+ end
+end
+
+def fun_l15_n581(x)
+ if (x < 1)
+ fun_l16_n40(x)
+ else
+ fun_l16_n36(x)
+ end
+end
+
+def fun_l15_n582(x)
+ if (x < 1)
+ fun_l16_n612(x)
+ else
+ fun_l16_n46(x)
+ end
+end
+
+def fun_l15_n583(x)
+ if (x < 1)
+ fun_l16_n328(x)
+ else
+ fun_l16_n638(x)
+ end
+end
+
+def fun_l15_n584(x)
+ if (x < 1)
+ fun_l16_n219(x)
+ else
+ fun_l16_n672(x)
+ end
+end
+
+def fun_l15_n585(x)
+ if (x < 1)
+ fun_l16_n67(x)
+ else
+ fun_l16_n584(x)
+ end
+end
+
+def fun_l15_n586(x)
+ if (x < 1)
+ fun_l16_n222(x)
+ else
+ fun_l16_n366(x)
+ end
+end
+
+def fun_l15_n587(x)
+ if (x < 1)
+ fun_l16_n194(x)
+ else
+ fun_l16_n54(x)
+ end
+end
+
+def fun_l15_n588(x)
+ if (x < 1)
+ fun_l16_n742(x)
+ else
+ fun_l16_n725(x)
+ end
+end
+
+def fun_l15_n589(x)
+ if (x < 1)
+ fun_l16_n557(x)
+ else
+ fun_l16_n688(x)
+ end
+end
+
+def fun_l15_n590(x)
+ if (x < 1)
+ fun_l16_n588(x)
+ else
+ fun_l16_n296(x)
+ end
+end
+
+def fun_l15_n591(x)
+ if (x < 1)
+ fun_l16_n756(x)
+ else
+ fun_l16_n619(x)
+ end
+end
+
+def fun_l15_n592(x)
+ if (x < 1)
+ fun_l16_n919(x)
+ else
+ fun_l16_n607(x)
+ end
+end
+
+def fun_l15_n593(x)
+ if (x < 1)
+ fun_l16_n168(x)
+ else
+ fun_l16_n425(x)
+ end
+end
+
+def fun_l15_n594(x)
+ if (x < 1)
+ fun_l16_n641(x)
+ else
+ fun_l16_n980(x)
+ end
+end
+
+def fun_l15_n595(x)
+ if (x < 1)
+ fun_l16_n132(x)
+ else
+ fun_l16_n120(x)
+ end
+end
+
+def fun_l15_n596(x)
+ if (x < 1)
+ fun_l16_n998(x)
+ else
+ fun_l16_n383(x)
+ end
+end
+
+def fun_l15_n597(x)
+ if (x < 1)
+ fun_l16_n987(x)
+ else
+ fun_l16_n685(x)
+ end
+end
+
+def fun_l15_n598(x)
+ if (x < 1)
+ fun_l16_n898(x)
+ else
+ fun_l16_n53(x)
+ end
+end
+
+def fun_l15_n599(x)
+ if (x < 1)
+ fun_l16_n589(x)
+ else
+ fun_l16_n25(x)
+ end
+end
+
+def fun_l15_n600(x)
+ if (x < 1)
+ fun_l16_n841(x)
+ else
+ fun_l16_n623(x)
+ end
+end
+
+def fun_l15_n601(x)
+ if (x < 1)
+ fun_l16_n63(x)
+ else
+ fun_l16_n515(x)
+ end
+end
+
+def fun_l15_n602(x)
+ if (x < 1)
+ fun_l16_n708(x)
+ else
+ fun_l16_n318(x)
+ end
+end
+
+def fun_l15_n603(x)
+ if (x < 1)
+ fun_l16_n679(x)
+ else
+ fun_l16_n31(x)
+ end
+end
+
+def fun_l15_n604(x)
+ if (x < 1)
+ fun_l16_n617(x)
+ else
+ fun_l16_n20(x)
+ end
+end
+
+def fun_l15_n605(x)
+ if (x < 1)
+ fun_l16_n635(x)
+ else
+ fun_l16_n990(x)
+ end
+end
+
+def fun_l15_n606(x)
+ if (x < 1)
+ fun_l16_n174(x)
+ else
+ fun_l16_n977(x)
+ end
+end
+
+def fun_l15_n607(x)
+ if (x < 1)
+ fun_l16_n449(x)
+ else
+ fun_l16_n658(x)
+ end
+end
+
+def fun_l15_n608(x)
+ if (x < 1)
+ fun_l16_n208(x)
+ else
+ fun_l16_n875(x)
+ end
+end
+
+def fun_l15_n609(x)
+ if (x < 1)
+ fun_l16_n665(x)
+ else
+ fun_l16_n431(x)
+ end
+end
+
+def fun_l15_n610(x)
+ if (x < 1)
+ fun_l16_n6(x)
+ else
+ fun_l16_n78(x)
+ end
+end
+
+def fun_l15_n611(x)
+ if (x < 1)
+ fun_l16_n335(x)
+ else
+ fun_l16_n558(x)
+ end
+end
+
+def fun_l15_n612(x)
+ if (x < 1)
+ fun_l16_n259(x)
+ else
+ fun_l16_n893(x)
+ end
+end
+
+def fun_l15_n613(x)
+ if (x < 1)
+ fun_l16_n511(x)
+ else
+ fun_l16_n519(x)
+ end
+end
+
+def fun_l15_n614(x)
+ if (x < 1)
+ fun_l16_n96(x)
+ else
+ fun_l16_n28(x)
+ end
+end
+
+def fun_l15_n615(x)
+ if (x < 1)
+ fun_l16_n166(x)
+ else
+ fun_l16_n417(x)
+ end
+end
+
+def fun_l15_n616(x)
+ if (x < 1)
+ fun_l16_n666(x)
+ else
+ fun_l16_n932(x)
+ end
+end
+
+def fun_l15_n617(x)
+ if (x < 1)
+ fun_l16_n745(x)
+ else
+ fun_l16_n967(x)
+ end
+end
+
+def fun_l15_n618(x)
+ if (x < 1)
+ fun_l16_n5(x)
+ else
+ fun_l16_n769(x)
+ end
+end
+
+def fun_l15_n619(x)
+ if (x < 1)
+ fun_l16_n108(x)
+ else
+ fun_l16_n658(x)
+ end
+end
+
+def fun_l15_n620(x)
+ if (x < 1)
+ fun_l16_n454(x)
+ else
+ fun_l16_n666(x)
+ end
+end
+
+def fun_l15_n621(x)
+ if (x < 1)
+ fun_l16_n756(x)
+ else
+ fun_l16_n580(x)
+ end
+end
+
+def fun_l15_n622(x)
+ if (x < 1)
+ fun_l16_n419(x)
+ else
+ fun_l16_n450(x)
+ end
+end
+
+def fun_l15_n623(x)
+ if (x < 1)
+ fun_l16_n793(x)
+ else
+ fun_l16_n268(x)
+ end
+end
+
+def fun_l15_n624(x)
+ if (x < 1)
+ fun_l16_n78(x)
+ else
+ fun_l16_n311(x)
+ end
+end
+
+def fun_l15_n625(x)
+ if (x < 1)
+ fun_l16_n35(x)
+ else
+ fun_l16_n378(x)
+ end
+end
+
+def fun_l15_n626(x)
+ if (x < 1)
+ fun_l16_n974(x)
+ else
+ fun_l16_n483(x)
+ end
+end
+
+def fun_l15_n627(x)
+ if (x < 1)
+ fun_l16_n67(x)
+ else
+ fun_l16_n497(x)
+ end
+end
+
+def fun_l15_n628(x)
+ if (x < 1)
+ fun_l16_n640(x)
+ else
+ fun_l16_n32(x)
+ end
+end
+
+def fun_l15_n629(x)
+ if (x < 1)
+ fun_l16_n297(x)
+ else
+ fun_l16_n63(x)
+ end
+end
+
+def fun_l15_n630(x)
+ if (x < 1)
+ fun_l16_n546(x)
+ else
+ fun_l16_n931(x)
+ end
+end
+
+def fun_l15_n631(x)
+ if (x < 1)
+ fun_l16_n688(x)
+ else
+ fun_l16_n542(x)
+ end
+end
+
+def fun_l15_n632(x)
+ if (x < 1)
+ fun_l16_n313(x)
+ else
+ fun_l16_n1(x)
+ end
+end
+
+def fun_l15_n633(x)
+ if (x < 1)
+ fun_l16_n743(x)
+ else
+ fun_l16_n382(x)
+ end
+end
+
+def fun_l15_n634(x)
+ if (x < 1)
+ fun_l16_n224(x)
+ else
+ fun_l16_n311(x)
+ end
+end
+
+def fun_l15_n635(x)
+ if (x < 1)
+ fun_l16_n926(x)
+ else
+ fun_l16_n329(x)
+ end
+end
+
+def fun_l15_n636(x)
+ if (x < 1)
+ fun_l16_n735(x)
+ else
+ fun_l16_n759(x)
+ end
+end
+
+def fun_l15_n637(x)
+ if (x < 1)
+ fun_l16_n699(x)
+ else
+ fun_l16_n27(x)
+ end
+end
+
+def fun_l15_n638(x)
+ if (x < 1)
+ fun_l16_n710(x)
+ else
+ fun_l16_n194(x)
+ end
+end
+
+def fun_l15_n639(x)
+ if (x < 1)
+ fun_l16_n245(x)
+ else
+ fun_l16_n950(x)
+ end
+end
+
+def fun_l15_n640(x)
+ if (x < 1)
+ fun_l16_n488(x)
+ else
+ fun_l16_n357(x)
+ end
+end
+
+def fun_l15_n641(x)
+ if (x < 1)
+ fun_l16_n331(x)
+ else
+ fun_l16_n962(x)
+ end
+end
+
+def fun_l15_n642(x)
+ if (x < 1)
+ fun_l16_n144(x)
+ else
+ fun_l16_n877(x)
+ end
+end
+
+def fun_l15_n643(x)
+ if (x < 1)
+ fun_l16_n605(x)
+ else
+ fun_l16_n733(x)
+ end
+end
+
+def fun_l15_n644(x)
+ if (x < 1)
+ fun_l16_n22(x)
+ else
+ fun_l16_n176(x)
+ end
+end
+
+def fun_l15_n645(x)
+ if (x < 1)
+ fun_l16_n934(x)
+ else
+ fun_l16_n351(x)
+ end
+end
+
+def fun_l15_n646(x)
+ if (x < 1)
+ fun_l16_n224(x)
+ else
+ fun_l16_n308(x)
+ end
+end
+
+def fun_l15_n647(x)
+ if (x < 1)
+ fun_l16_n374(x)
+ else
+ fun_l16_n612(x)
+ end
+end
+
+def fun_l15_n648(x)
+ if (x < 1)
+ fun_l16_n105(x)
+ else
+ fun_l16_n563(x)
+ end
+end
+
+def fun_l15_n649(x)
+ if (x < 1)
+ fun_l16_n955(x)
+ else
+ fun_l16_n63(x)
+ end
+end
+
+def fun_l15_n650(x)
+ if (x < 1)
+ fun_l16_n734(x)
+ else
+ fun_l16_n194(x)
+ end
+end
+
+def fun_l15_n651(x)
+ if (x < 1)
+ fun_l16_n237(x)
+ else
+ fun_l16_n425(x)
+ end
+end
+
+def fun_l15_n652(x)
+ if (x < 1)
+ fun_l16_n135(x)
+ else
+ fun_l16_n217(x)
+ end
+end
+
+def fun_l15_n653(x)
+ if (x < 1)
+ fun_l16_n565(x)
+ else
+ fun_l16_n437(x)
+ end
+end
+
+def fun_l15_n654(x)
+ if (x < 1)
+ fun_l16_n471(x)
+ else
+ fun_l16_n426(x)
+ end
+end
+
+def fun_l15_n655(x)
+ if (x < 1)
+ fun_l16_n570(x)
+ else
+ fun_l16_n64(x)
+ end
+end
+
+def fun_l15_n656(x)
+ if (x < 1)
+ fun_l16_n456(x)
+ else
+ fun_l16_n479(x)
+ end
+end
+
+def fun_l15_n657(x)
+ if (x < 1)
+ fun_l16_n446(x)
+ else
+ fun_l16_n362(x)
+ end
+end
+
+def fun_l15_n658(x)
+ if (x < 1)
+ fun_l16_n294(x)
+ else
+ fun_l16_n485(x)
+ end
+end
+
+def fun_l15_n659(x)
+ if (x < 1)
+ fun_l16_n96(x)
+ else
+ fun_l16_n60(x)
+ end
+end
+
+def fun_l15_n660(x)
+ if (x < 1)
+ fun_l16_n436(x)
+ else
+ fun_l16_n12(x)
+ end
+end
+
+def fun_l15_n661(x)
+ if (x < 1)
+ fun_l16_n5(x)
+ else
+ fun_l16_n452(x)
+ end
+end
+
+def fun_l15_n662(x)
+ if (x < 1)
+ fun_l16_n70(x)
+ else
+ fun_l16_n564(x)
+ end
+end
+
+def fun_l15_n663(x)
+ if (x < 1)
+ fun_l16_n92(x)
+ else
+ fun_l16_n333(x)
+ end
+end
+
+def fun_l15_n664(x)
+ if (x < 1)
+ fun_l16_n884(x)
+ else
+ fun_l16_n381(x)
+ end
+end
+
+def fun_l15_n665(x)
+ if (x < 1)
+ fun_l16_n816(x)
+ else
+ fun_l16_n243(x)
+ end
+end
+
+def fun_l15_n666(x)
+ if (x < 1)
+ fun_l16_n680(x)
+ else
+ fun_l16_n306(x)
+ end
+end
+
+def fun_l15_n667(x)
+ if (x < 1)
+ fun_l16_n470(x)
+ else
+ fun_l16_n559(x)
+ end
+end
+
+def fun_l15_n668(x)
+ if (x < 1)
+ fun_l16_n34(x)
+ else
+ fun_l16_n261(x)
+ end
+end
+
+def fun_l15_n669(x)
+ if (x < 1)
+ fun_l16_n644(x)
+ else
+ fun_l16_n389(x)
+ end
+end
+
+def fun_l15_n670(x)
+ if (x < 1)
+ fun_l16_n313(x)
+ else
+ fun_l16_n575(x)
+ end
+end
+
+def fun_l15_n671(x)
+ if (x < 1)
+ fun_l16_n241(x)
+ else
+ fun_l16_n304(x)
+ end
+end
+
+def fun_l15_n672(x)
+ if (x < 1)
+ fun_l16_n280(x)
+ else
+ fun_l16_n996(x)
+ end
+end
+
+def fun_l15_n673(x)
+ if (x < 1)
+ fun_l16_n723(x)
+ else
+ fun_l16_n42(x)
+ end
+end
+
+def fun_l15_n674(x)
+ if (x < 1)
+ fun_l16_n503(x)
+ else
+ fun_l16_n837(x)
+ end
+end
+
+def fun_l15_n675(x)
+ if (x < 1)
+ fun_l16_n105(x)
+ else
+ fun_l16_n815(x)
+ end
+end
+
+def fun_l15_n676(x)
+ if (x < 1)
+ fun_l16_n441(x)
+ else
+ fun_l16_n313(x)
+ end
+end
+
+def fun_l15_n677(x)
+ if (x < 1)
+ fun_l16_n277(x)
+ else
+ fun_l16_n653(x)
+ end
+end
+
+def fun_l15_n678(x)
+ if (x < 1)
+ fun_l16_n105(x)
+ else
+ fun_l16_n907(x)
+ end
+end
+
+def fun_l15_n679(x)
+ if (x < 1)
+ fun_l16_n549(x)
+ else
+ fun_l16_n956(x)
+ end
+end
+
+def fun_l15_n680(x)
+ if (x < 1)
+ fun_l16_n177(x)
+ else
+ fun_l16_n238(x)
+ end
+end
+
+def fun_l15_n681(x)
+ if (x < 1)
+ fun_l16_n931(x)
+ else
+ fun_l16_n278(x)
+ end
+end
+
+def fun_l15_n682(x)
+ if (x < 1)
+ fun_l16_n923(x)
+ else
+ fun_l16_n924(x)
+ end
+end
+
+def fun_l15_n683(x)
+ if (x < 1)
+ fun_l16_n926(x)
+ else
+ fun_l16_n76(x)
+ end
+end
+
+def fun_l15_n684(x)
+ if (x < 1)
+ fun_l16_n828(x)
+ else
+ fun_l16_n961(x)
+ end
+end
+
+def fun_l15_n685(x)
+ if (x < 1)
+ fun_l16_n298(x)
+ else
+ fun_l16_n95(x)
+ end
+end
+
+def fun_l15_n686(x)
+ if (x < 1)
+ fun_l16_n929(x)
+ else
+ fun_l16_n239(x)
+ end
+end
+
+def fun_l15_n687(x)
+ if (x < 1)
+ fun_l16_n488(x)
+ else
+ fun_l16_n543(x)
+ end
+end
+
+def fun_l15_n688(x)
+ if (x < 1)
+ fun_l16_n562(x)
+ else
+ fun_l16_n879(x)
+ end
+end
+
+def fun_l15_n689(x)
+ if (x < 1)
+ fun_l16_n348(x)
+ else
+ fun_l16_n458(x)
+ end
+end
+
+def fun_l15_n690(x)
+ if (x < 1)
+ fun_l16_n431(x)
+ else
+ fun_l16_n653(x)
+ end
+end
+
+def fun_l15_n691(x)
+ if (x < 1)
+ fun_l16_n173(x)
+ else
+ fun_l16_n600(x)
+ end
+end
+
+def fun_l15_n692(x)
+ if (x < 1)
+ fun_l16_n820(x)
+ else
+ fun_l16_n793(x)
+ end
+end
+
+def fun_l15_n693(x)
+ if (x < 1)
+ fun_l16_n611(x)
+ else
+ fun_l16_n308(x)
+ end
+end
+
+def fun_l15_n694(x)
+ if (x < 1)
+ fun_l16_n325(x)
+ else
+ fun_l16_n791(x)
+ end
+end
+
+def fun_l15_n695(x)
+ if (x < 1)
+ fun_l16_n890(x)
+ else
+ fun_l16_n98(x)
+ end
+end
+
+def fun_l15_n696(x)
+ if (x < 1)
+ fun_l16_n803(x)
+ else
+ fun_l16_n890(x)
+ end
+end
+
+def fun_l15_n697(x)
+ if (x < 1)
+ fun_l16_n182(x)
+ else
+ fun_l16_n229(x)
+ end
+end
+
+def fun_l15_n698(x)
+ if (x < 1)
+ fun_l16_n238(x)
+ else
+ fun_l16_n395(x)
+ end
+end
+
+def fun_l15_n699(x)
+ if (x < 1)
+ fun_l16_n349(x)
+ else
+ fun_l16_n903(x)
+ end
+end
+
+def fun_l15_n700(x)
+ if (x < 1)
+ fun_l16_n328(x)
+ else
+ fun_l16_n664(x)
+ end
+end
+
+def fun_l15_n701(x)
+ if (x < 1)
+ fun_l16_n924(x)
+ else
+ fun_l16_n415(x)
+ end
+end
+
+def fun_l15_n702(x)
+ if (x < 1)
+ fun_l16_n504(x)
+ else
+ fun_l16_n180(x)
+ end
+end
+
+def fun_l15_n703(x)
+ if (x < 1)
+ fun_l16_n754(x)
+ else
+ fun_l16_n580(x)
+ end
+end
+
+def fun_l15_n704(x)
+ if (x < 1)
+ fun_l16_n686(x)
+ else
+ fun_l16_n75(x)
+ end
+end
+
+def fun_l15_n705(x)
+ if (x < 1)
+ fun_l16_n295(x)
+ else
+ fun_l16_n789(x)
+ end
+end
+
+def fun_l15_n706(x)
+ if (x < 1)
+ fun_l16_n796(x)
+ else
+ fun_l16_n628(x)
+ end
+end
+
+def fun_l15_n707(x)
+ if (x < 1)
+ fun_l16_n603(x)
+ else
+ fun_l16_n864(x)
+ end
+end
+
+def fun_l15_n708(x)
+ if (x < 1)
+ fun_l16_n420(x)
+ else
+ fun_l16_n506(x)
+ end
+end
+
+def fun_l15_n709(x)
+ if (x < 1)
+ fun_l16_n417(x)
+ else
+ fun_l16_n677(x)
+ end
+end
+
+def fun_l15_n710(x)
+ if (x < 1)
+ fun_l16_n484(x)
+ else
+ fun_l16_n210(x)
+ end
+end
+
+def fun_l15_n711(x)
+ if (x < 1)
+ fun_l16_n127(x)
+ else
+ fun_l16_n423(x)
+ end
+end
+
+def fun_l15_n712(x)
+ if (x < 1)
+ fun_l16_n395(x)
+ else
+ fun_l16_n75(x)
+ end
+end
+
+def fun_l15_n713(x)
+ if (x < 1)
+ fun_l16_n388(x)
+ else
+ fun_l16_n261(x)
+ end
+end
+
+def fun_l15_n714(x)
+ if (x < 1)
+ fun_l16_n508(x)
+ else
+ fun_l16_n160(x)
+ end
+end
+
+def fun_l15_n715(x)
+ if (x < 1)
+ fun_l16_n468(x)
+ else
+ fun_l16_n784(x)
+ end
+end
+
+def fun_l15_n716(x)
+ if (x < 1)
+ fun_l16_n156(x)
+ else
+ fun_l16_n769(x)
+ end
+end
+
+def fun_l15_n717(x)
+ if (x < 1)
+ fun_l16_n219(x)
+ else
+ fun_l16_n618(x)
+ end
+end
+
+def fun_l15_n718(x)
+ if (x < 1)
+ fun_l16_n921(x)
+ else
+ fun_l16_n83(x)
+ end
+end
+
+def fun_l15_n719(x)
+ if (x < 1)
+ fun_l16_n262(x)
+ else
+ fun_l16_n170(x)
+ end
+end
+
+def fun_l15_n720(x)
+ if (x < 1)
+ fun_l16_n420(x)
+ else
+ fun_l16_n504(x)
+ end
+end
+
+def fun_l15_n721(x)
+ if (x < 1)
+ fun_l16_n485(x)
+ else
+ fun_l16_n782(x)
+ end
+end
+
+def fun_l15_n722(x)
+ if (x < 1)
+ fun_l16_n607(x)
+ else
+ fun_l16_n706(x)
+ end
+end
+
+def fun_l15_n723(x)
+ if (x < 1)
+ fun_l16_n116(x)
+ else
+ fun_l16_n73(x)
+ end
+end
+
+def fun_l15_n724(x)
+ if (x < 1)
+ fun_l16_n946(x)
+ else
+ fun_l16_n694(x)
+ end
+end
+
+def fun_l15_n725(x)
+ if (x < 1)
+ fun_l16_n73(x)
+ else
+ fun_l16_n223(x)
+ end
+end
+
+def fun_l15_n726(x)
+ if (x < 1)
+ fun_l16_n54(x)
+ else
+ fun_l16_n681(x)
+ end
+end
+
+def fun_l15_n727(x)
+ if (x < 1)
+ fun_l16_n474(x)
+ else
+ fun_l16_n339(x)
+ end
+end
+
+def fun_l15_n728(x)
+ if (x < 1)
+ fun_l16_n780(x)
+ else
+ fun_l16_n364(x)
+ end
+end
+
+def fun_l15_n729(x)
+ if (x < 1)
+ fun_l16_n537(x)
+ else
+ fun_l16_n1(x)
+ end
+end
+
+def fun_l15_n730(x)
+ if (x < 1)
+ fun_l16_n81(x)
+ else
+ fun_l16_n591(x)
+ end
+end
+
+def fun_l15_n731(x)
+ if (x < 1)
+ fun_l16_n631(x)
+ else
+ fun_l16_n626(x)
+ end
+end
+
+def fun_l15_n732(x)
+ if (x < 1)
+ fun_l16_n904(x)
+ else
+ fun_l16_n988(x)
+ end
+end
+
+def fun_l15_n733(x)
+ if (x < 1)
+ fun_l16_n933(x)
+ else
+ fun_l16_n761(x)
+ end
+end
+
+def fun_l15_n734(x)
+ if (x < 1)
+ fun_l16_n687(x)
+ else
+ fun_l16_n611(x)
+ end
+end
+
+def fun_l15_n735(x)
+ if (x < 1)
+ fun_l16_n197(x)
+ else
+ fun_l16_n210(x)
+ end
+end
+
+def fun_l15_n736(x)
+ if (x < 1)
+ fun_l16_n227(x)
+ else
+ fun_l16_n82(x)
+ end
+end
+
+def fun_l15_n737(x)
+ if (x < 1)
+ fun_l16_n981(x)
+ else
+ fun_l16_n18(x)
+ end
+end
+
+def fun_l15_n738(x)
+ if (x < 1)
+ fun_l16_n673(x)
+ else
+ fun_l16_n452(x)
+ end
+end
+
+def fun_l15_n739(x)
+ if (x < 1)
+ fun_l16_n225(x)
+ else
+ fun_l16_n555(x)
+ end
+end
+
+def fun_l15_n740(x)
+ if (x < 1)
+ fun_l16_n409(x)
+ else
+ fun_l16_n29(x)
+ end
+end
+
+def fun_l15_n741(x)
+ if (x < 1)
+ fun_l16_n550(x)
+ else
+ fun_l16_n880(x)
+ end
+end
+
+def fun_l15_n742(x)
+ if (x < 1)
+ fun_l16_n930(x)
+ else
+ fun_l16_n280(x)
+ end
+end
+
+def fun_l15_n743(x)
+ if (x < 1)
+ fun_l16_n622(x)
+ else
+ fun_l16_n438(x)
+ end
+end
+
+def fun_l15_n744(x)
+ if (x < 1)
+ fun_l16_n874(x)
+ else
+ fun_l16_n921(x)
+ end
+end
+
+def fun_l15_n745(x)
+ if (x < 1)
+ fun_l16_n337(x)
+ else
+ fun_l16_n879(x)
+ end
+end
+
+def fun_l15_n746(x)
+ if (x < 1)
+ fun_l16_n668(x)
+ else
+ fun_l16_n858(x)
+ end
+end
+
+def fun_l15_n747(x)
+ if (x < 1)
+ fun_l16_n588(x)
+ else
+ fun_l16_n433(x)
+ end
+end
+
+def fun_l15_n748(x)
+ if (x < 1)
+ fun_l16_n263(x)
+ else
+ fun_l16_n389(x)
+ end
+end
+
+def fun_l15_n749(x)
+ if (x < 1)
+ fun_l16_n79(x)
+ else
+ fun_l16_n218(x)
+ end
+end
+
+def fun_l15_n750(x)
+ if (x < 1)
+ fun_l16_n586(x)
+ else
+ fun_l16_n426(x)
+ end
+end
+
+def fun_l15_n751(x)
+ if (x < 1)
+ fun_l16_n29(x)
+ else
+ fun_l16_n183(x)
+ end
+end
+
+def fun_l15_n752(x)
+ if (x < 1)
+ fun_l16_n423(x)
+ else
+ fun_l16_n994(x)
+ end
+end
+
+def fun_l15_n753(x)
+ if (x < 1)
+ fun_l16_n176(x)
+ else
+ fun_l16_n425(x)
+ end
+end
+
+def fun_l15_n754(x)
+ if (x < 1)
+ fun_l16_n58(x)
+ else
+ fun_l16_n980(x)
+ end
+end
+
+def fun_l15_n755(x)
+ if (x < 1)
+ fun_l16_n333(x)
+ else
+ fun_l16_n949(x)
+ end
+end
+
+def fun_l15_n756(x)
+ if (x < 1)
+ fun_l16_n846(x)
+ else
+ fun_l16_n449(x)
+ end
+end
+
+def fun_l15_n757(x)
+ if (x < 1)
+ fun_l16_n341(x)
+ else
+ fun_l16_n200(x)
+ end
+end
+
+def fun_l15_n758(x)
+ if (x < 1)
+ fun_l16_n32(x)
+ else
+ fun_l16_n271(x)
+ end
+end
+
+def fun_l15_n759(x)
+ if (x < 1)
+ fun_l16_n654(x)
+ else
+ fun_l16_n978(x)
+ end
+end
+
+def fun_l15_n760(x)
+ if (x < 1)
+ fun_l16_n438(x)
+ else
+ fun_l16_n426(x)
+ end
+end
+
+def fun_l15_n761(x)
+ if (x < 1)
+ fun_l16_n218(x)
+ else
+ fun_l16_n393(x)
+ end
+end
+
+def fun_l15_n762(x)
+ if (x < 1)
+ fun_l16_n873(x)
+ else
+ fun_l16_n231(x)
+ end
+end
+
+def fun_l15_n763(x)
+ if (x < 1)
+ fun_l16_n957(x)
+ else
+ fun_l16_n801(x)
+ end
+end
+
+def fun_l15_n764(x)
+ if (x < 1)
+ fun_l16_n571(x)
+ else
+ fun_l16_n369(x)
+ end
+end
+
+def fun_l15_n765(x)
+ if (x < 1)
+ fun_l16_n806(x)
+ else
+ fun_l16_n527(x)
+ end
+end
+
+def fun_l15_n766(x)
+ if (x < 1)
+ fun_l16_n511(x)
+ else
+ fun_l16_n911(x)
+ end
+end
+
+def fun_l15_n767(x)
+ if (x < 1)
+ fun_l16_n589(x)
+ else
+ fun_l16_n468(x)
+ end
+end
+
+def fun_l15_n768(x)
+ if (x < 1)
+ fun_l16_n846(x)
+ else
+ fun_l16_n325(x)
+ end
+end
+
+def fun_l15_n769(x)
+ if (x < 1)
+ fun_l16_n350(x)
+ else
+ fun_l16_n268(x)
+ end
+end
+
+def fun_l15_n770(x)
+ if (x < 1)
+ fun_l16_n200(x)
+ else
+ fun_l16_n151(x)
+ end
+end
+
+def fun_l15_n771(x)
+ if (x < 1)
+ fun_l16_n246(x)
+ else
+ fun_l16_n442(x)
+ end
+end
+
+def fun_l15_n772(x)
+ if (x < 1)
+ fun_l16_n768(x)
+ else
+ fun_l16_n303(x)
+ end
+end
+
+def fun_l15_n773(x)
+ if (x < 1)
+ fun_l16_n414(x)
+ else
+ fun_l16_n857(x)
+ end
+end
+
+def fun_l15_n774(x)
+ if (x < 1)
+ fun_l16_n654(x)
+ else
+ fun_l16_n151(x)
+ end
+end
+
+def fun_l15_n775(x)
+ if (x < 1)
+ fun_l16_n283(x)
+ else
+ fun_l16_n565(x)
+ end
+end
+
+def fun_l15_n776(x)
+ if (x < 1)
+ fun_l16_n375(x)
+ else
+ fun_l16_n897(x)
+ end
+end
+
+def fun_l15_n777(x)
+ if (x < 1)
+ fun_l16_n711(x)
+ else
+ fun_l16_n487(x)
+ end
+end
+
+def fun_l15_n778(x)
+ if (x < 1)
+ fun_l16_n445(x)
+ else
+ fun_l16_n99(x)
+ end
+end
+
+def fun_l15_n779(x)
+ if (x < 1)
+ fun_l16_n320(x)
+ else
+ fun_l16_n614(x)
+ end
+end
+
+def fun_l15_n780(x)
+ if (x < 1)
+ fun_l16_n330(x)
+ else
+ fun_l16_n478(x)
+ end
+end
+
+def fun_l15_n781(x)
+ if (x < 1)
+ fun_l16_n680(x)
+ else
+ fun_l16_n882(x)
+ end
+end
+
+def fun_l15_n782(x)
+ if (x < 1)
+ fun_l16_n799(x)
+ else
+ fun_l16_n511(x)
+ end
+end
+
+def fun_l15_n783(x)
+ if (x < 1)
+ fun_l16_n630(x)
+ else
+ fun_l16_n946(x)
+ end
+end
+
+def fun_l15_n784(x)
+ if (x < 1)
+ fun_l16_n867(x)
+ else
+ fun_l16_n4(x)
+ end
+end
+
+def fun_l15_n785(x)
+ if (x < 1)
+ fun_l16_n154(x)
+ else
+ fun_l16_n400(x)
+ end
+end
+
+def fun_l15_n786(x)
+ if (x < 1)
+ fun_l16_n166(x)
+ else
+ fun_l16_n224(x)
+ end
+end
+
+def fun_l15_n787(x)
+ if (x < 1)
+ fun_l16_n120(x)
+ else
+ fun_l16_n518(x)
+ end
+end
+
+def fun_l15_n788(x)
+ if (x < 1)
+ fun_l16_n648(x)
+ else
+ fun_l16_n56(x)
+ end
+end
+
+def fun_l15_n789(x)
+ if (x < 1)
+ fun_l16_n965(x)
+ else
+ fun_l16_n760(x)
+ end
+end
+
+def fun_l15_n790(x)
+ if (x < 1)
+ fun_l16_n880(x)
+ else
+ fun_l16_n809(x)
+ end
+end
+
+def fun_l15_n791(x)
+ if (x < 1)
+ fun_l16_n836(x)
+ else
+ fun_l16_n61(x)
+ end
+end
+
+def fun_l15_n792(x)
+ if (x < 1)
+ fun_l16_n874(x)
+ else
+ fun_l16_n559(x)
+ end
+end
+
+def fun_l15_n793(x)
+ if (x < 1)
+ fun_l16_n896(x)
+ else
+ fun_l16_n72(x)
+ end
+end
+
+def fun_l15_n794(x)
+ if (x < 1)
+ fun_l16_n994(x)
+ else
+ fun_l16_n411(x)
+ end
+end
+
+def fun_l15_n795(x)
+ if (x < 1)
+ fun_l16_n289(x)
+ else
+ fun_l16_n151(x)
+ end
+end
+
+def fun_l15_n796(x)
+ if (x < 1)
+ fun_l16_n190(x)
+ else
+ fun_l16_n693(x)
+ end
+end
+
+def fun_l15_n797(x)
+ if (x < 1)
+ fun_l16_n320(x)
+ else
+ fun_l16_n955(x)
+ end
+end
+
+def fun_l15_n798(x)
+ if (x < 1)
+ fun_l16_n572(x)
+ else
+ fun_l16_n626(x)
+ end
+end
+
+def fun_l15_n799(x)
+ if (x < 1)
+ fun_l16_n35(x)
+ else
+ fun_l16_n838(x)
+ end
+end
+
+def fun_l15_n800(x)
+ if (x < 1)
+ fun_l16_n423(x)
+ else
+ fun_l16_n834(x)
+ end
+end
+
+def fun_l15_n801(x)
+ if (x < 1)
+ fun_l16_n964(x)
+ else
+ fun_l16_n824(x)
+ end
+end
+
+def fun_l15_n802(x)
+ if (x < 1)
+ fun_l16_n77(x)
+ else
+ fun_l16_n62(x)
+ end
+end
+
+def fun_l15_n803(x)
+ if (x < 1)
+ fun_l16_n226(x)
+ else
+ fun_l16_n373(x)
+ end
+end
+
+def fun_l15_n804(x)
+ if (x < 1)
+ fun_l16_n832(x)
+ else
+ fun_l16_n915(x)
+ end
+end
+
+def fun_l15_n805(x)
+ if (x < 1)
+ fun_l16_n421(x)
+ else
+ fun_l16_n621(x)
+ end
+end
+
+def fun_l15_n806(x)
+ if (x < 1)
+ fun_l16_n303(x)
+ else
+ fun_l16_n713(x)
+ end
+end
+
+def fun_l15_n807(x)
+ if (x < 1)
+ fun_l16_n393(x)
+ else
+ fun_l16_n698(x)
+ end
+end
+
+def fun_l15_n808(x)
+ if (x < 1)
+ fun_l16_n303(x)
+ else
+ fun_l16_n341(x)
+ end
+end
+
+def fun_l15_n809(x)
+ if (x < 1)
+ fun_l16_n116(x)
+ else
+ fun_l16_n976(x)
+ end
+end
+
+def fun_l15_n810(x)
+ if (x < 1)
+ fun_l16_n873(x)
+ else
+ fun_l16_n822(x)
+ end
+end
+
+def fun_l15_n811(x)
+ if (x < 1)
+ fun_l16_n358(x)
+ else
+ fun_l16_n334(x)
+ end
+end
+
+def fun_l15_n812(x)
+ if (x < 1)
+ fun_l16_n599(x)
+ else
+ fun_l16_n527(x)
+ end
+end
+
+def fun_l15_n813(x)
+ if (x < 1)
+ fun_l16_n842(x)
+ else
+ fun_l16_n791(x)
+ end
+end
+
+def fun_l15_n814(x)
+ if (x < 1)
+ fun_l16_n45(x)
+ else
+ fun_l16_n280(x)
+ end
+end
+
+def fun_l15_n815(x)
+ if (x < 1)
+ fun_l16_n187(x)
+ else
+ fun_l16_n151(x)
+ end
+end
+
+def fun_l15_n816(x)
+ if (x < 1)
+ fun_l16_n8(x)
+ else
+ fun_l16_n409(x)
+ end
+end
+
+def fun_l15_n817(x)
+ if (x < 1)
+ fun_l16_n670(x)
+ else
+ fun_l16_n569(x)
+ end
+end
+
+def fun_l15_n818(x)
+ if (x < 1)
+ fun_l16_n344(x)
+ else
+ fun_l16_n618(x)
+ end
+end
+
+def fun_l15_n819(x)
+ if (x < 1)
+ fun_l16_n659(x)
+ else
+ fun_l16_n321(x)
+ end
+end
+
+def fun_l15_n820(x)
+ if (x < 1)
+ fun_l16_n890(x)
+ else
+ fun_l16_n911(x)
+ end
+end
+
+def fun_l15_n821(x)
+ if (x < 1)
+ fun_l16_n360(x)
+ else
+ fun_l16_n742(x)
+ end
+end
+
+def fun_l15_n822(x)
+ if (x < 1)
+ fun_l16_n166(x)
+ else
+ fun_l16_n803(x)
+ end
+end
+
+def fun_l15_n823(x)
+ if (x < 1)
+ fun_l16_n765(x)
+ else
+ fun_l16_n958(x)
+ end
+end
+
+def fun_l15_n824(x)
+ if (x < 1)
+ fun_l16_n439(x)
+ else
+ fun_l16_n931(x)
+ end
+end
+
+def fun_l15_n825(x)
+ if (x < 1)
+ fun_l16_n740(x)
+ else
+ fun_l16_n901(x)
+ end
+end
+
+def fun_l15_n826(x)
+ if (x < 1)
+ fun_l16_n223(x)
+ else
+ fun_l16_n878(x)
+ end
+end
+
+def fun_l15_n827(x)
+ if (x < 1)
+ fun_l16_n969(x)
+ else
+ fun_l16_n553(x)
+ end
+end
+
+def fun_l15_n828(x)
+ if (x < 1)
+ fun_l16_n42(x)
+ else
+ fun_l16_n915(x)
+ end
+end
+
+def fun_l15_n829(x)
+ if (x < 1)
+ fun_l16_n386(x)
+ else
+ fun_l16_n430(x)
+ end
+end
+
+def fun_l15_n830(x)
+ if (x < 1)
+ fun_l16_n164(x)
+ else
+ fun_l16_n337(x)
+ end
+end
+
+def fun_l15_n831(x)
+ if (x < 1)
+ fun_l16_n465(x)
+ else
+ fun_l16_n898(x)
+ end
+end
+
+def fun_l15_n832(x)
+ if (x < 1)
+ fun_l16_n145(x)
+ else
+ fun_l16_n688(x)
+ end
+end
+
+def fun_l15_n833(x)
+ if (x < 1)
+ fun_l16_n238(x)
+ else
+ fun_l16_n624(x)
+ end
+end
+
+def fun_l15_n834(x)
+ if (x < 1)
+ fun_l16_n973(x)
+ else
+ fun_l16_n507(x)
+ end
+end
+
+def fun_l15_n835(x)
+ if (x < 1)
+ fun_l16_n24(x)
+ else
+ fun_l16_n607(x)
+ end
+end
+
+def fun_l15_n836(x)
+ if (x < 1)
+ fun_l16_n307(x)
+ else
+ fun_l16_n265(x)
+ end
+end
+
+def fun_l15_n837(x)
+ if (x < 1)
+ fun_l16_n91(x)
+ else
+ fun_l16_n543(x)
+ end
+end
+
+def fun_l15_n838(x)
+ if (x < 1)
+ fun_l16_n544(x)
+ else
+ fun_l16_n397(x)
+ end
+end
+
+def fun_l15_n839(x)
+ if (x < 1)
+ fun_l16_n121(x)
+ else
+ fun_l16_n503(x)
+ end
+end
+
+def fun_l15_n840(x)
+ if (x < 1)
+ fun_l16_n806(x)
+ else
+ fun_l16_n831(x)
+ end
+end
+
+def fun_l15_n841(x)
+ if (x < 1)
+ fun_l16_n629(x)
+ else
+ fun_l16_n553(x)
+ end
+end
+
+def fun_l15_n842(x)
+ if (x < 1)
+ fun_l16_n674(x)
+ else
+ fun_l16_n945(x)
+ end
+end
+
+def fun_l15_n843(x)
+ if (x < 1)
+ fun_l16_n409(x)
+ else
+ fun_l16_n469(x)
+ end
+end
+
+def fun_l15_n844(x)
+ if (x < 1)
+ fun_l16_n779(x)
+ else
+ fun_l16_n168(x)
+ end
+end
+
+def fun_l15_n845(x)
+ if (x < 1)
+ fun_l16_n258(x)
+ else
+ fun_l16_n501(x)
+ end
+end
+
+def fun_l15_n846(x)
+ if (x < 1)
+ fun_l16_n408(x)
+ else
+ fun_l16_n211(x)
+ end
+end
+
+def fun_l15_n847(x)
+ if (x < 1)
+ fun_l16_n844(x)
+ else
+ fun_l16_n458(x)
+ end
+end
+
+def fun_l15_n848(x)
+ if (x < 1)
+ fun_l16_n565(x)
+ else
+ fun_l16_n177(x)
+ end
+end
+
+def fun_l15_n849(x)
+ if (x < 1)
+ fun_l16_n111(x)
+ else
+ fun_l16_n995(x)
+ end
+end
+
+def fun_l15_n850(x)
+ if (x < 1)
+ fun_l16_n883(x)
+ else
+ fun_l16_n776(x)
+ end
+end
+
+def fun_l15_n851(x)
+ if (x < 1)
+ fun_l16_n821(x)
+ else
+ fun_l16_n352(x)
+ end
+end
+
+def fun_l15_n852(x)
+ if (x < 1)
+ fun_l16_n977(x)
+ else
+ fun_l16_n520(x)
+ end
+end
+
+def fun_l15_n853(x)
+ if (x < 1)
+ fun_l16_n602(x)
+ else
+ fun_l16_n88(x)
+ end
+end
+
+def fun_l15_n854(x)
+ if (x < 1)
+ fun_l16_n819(x)
+ else
+ fun_l16_n177(x)
+ end
+end
+
+def fun_l15_n855(x)
+ if (x < 1)
+ fun_l16_n878(x)
+ else
+ fun_l16_n648(x)
+ end
+end
+
+def fun_l15_n856(x)
+ if (x < 1)
+ fun_l16_n69(x)
+ else
+ fun_l16_n134(x)
+ end
+end
+
+def fun_l15_n857(x)
+ if (x < 1)
+ fun_l16_n728(x)
+ else
+ fun_l16_n282(x)
+ end
+end
+
+def fun_l15_n858(x)
+ if (x < 1)
+ fun_l16_n152(x)
+ else
+ fun_l16_n725(x)
+ end
+end
+
+def fun_l15_n859(x)
+ if (x < 1)
+ fun_l16_n140(x)
+ else
+ fun_l16_n12(x)
+ end
+end
+
+def fun_l15_n860(x)
+ if (x < 1)
+ fun_l16_n691(x)
+ else
+ fun_l16_n159(x)
+ end
+end
+
+def fun_l15_n861(x)
+ if (x < 1)
+ fun_l16_n366(x)
+ else
+ fun_l16_n97(x)
+ end
+end
+
+def fun_l15_n862(x)
+ if (x < 1)
+ fun_l16_n812(x)
+ else
+ fun_l16_n178(x)
+ end
+end
+
+def fun_l15_n863(x)
+ if (x < 1)
+ fun_l16_n491(x)
+ else
+ fun_l16_n167(x)
+ end
+end
+
+def fun_l15_n864(x)
+ if (x < 1)
+ fun_l16_n280(x)
+ else
+ fun_l16_n463(x)
+ end
+end
+
+def fun_l15_n865(x)
+ if (x < 1)
+ fun_l16_n405(x)
+ else
+ fun_l16_n108(x)
+ end
+end
+
+def fun_l15_n866(x)
+ if (x < 1)
+ fun_l16_n956(x)
+ else
+ fun_l16_n840(x)
+ end
+end
+
+def fun_l15_n867(x)
+ if (x < 1)
+ fun_l16_n866(x)
+ else
+ fun_l16_n291(x)
+ end
+end
+
+def fun_l15_n868(x)
+ if (x < 1)
+ fun_l16_n176(x)
+ else
+ fun_l16_n192(x)
+ end
+end
+
+def fun_l15_n869(x)
+ if (x < 1)
+ fun_l16_n833(x)
+ else
+ fun_l16_n503(x)
+ end
+end
+
+def fun_l15_n870(x)
+ if (x < 1)
+ fun_l16_n648(x)
+ else
+ fun_l16_n778(x)
+ end
+end
+
+def fun_l15_n871(x)
+ if (x < 1)
+ fun_l16_n237(x)
+ else
+ fun_l16_n206(x)
+ end
+end
+
+def fun_l15_n872(x)
+ if (x < 1)
+ fun_l16_n676(x)
+ else
+ fun_l16_n868(x)
+ end
+end
+
+def fun_l15_n873(x)
+ if (x < 1)
+ fun_l16_n547(x)
+ else
+ fun_l16_n731(x)
+ end
+end
+
+def fun_l15_n874(x)
+ if (x < 1)
+ fun_l16_n870(x)
+ else
+ fun_l16_n43(x)
+ end
+end
+
+def fun_l15_n875(x)
+ if (x < 1)
+ fun_l16_n246(x)
+ else
+ fun_l16_n654(x)
+ end
+end
+
+def fun_l15_n876(x)
+ if (x < 1)
+ fun_l16_n570(x)
+ else
+ fun_l16_n842(x)
+ end
+end
+
+def fun_l15_n877(x)
+ if (x < 1)
+ fun_l16_n272(x)
+ else
+ fun_l16_n784(x)
+ end
+end
+
+def fun_l15_n878(x)
+ if (x < 1)
+ fun_l16_n702(x)
+ else
+ fun_l16_n758(x)
+ end
+end
+
+def fun_l15_n879(x)
+ if (x < 1)
+ fun_l16_n691(x)
+ else
+ fun_l16_n303(x)
+ end
+end
+
+def fun_l15_n880(x)
+ if (x < 1)
+ fun_l16_n944(x)
+ else
+ fun_l16_n449(x)
+ end
+end
+
+def fun_l15_n881(x)
+ if (x < 1)
+ fun_l16_n741(x)
+ else
+ fun_l16_n254(x)
+ end
+end
+
+def fun_l15_n882(x)
+ if (x < 1)
+ fun_l16_n195(x)
+ else
+ fun_l16_n294(x)
+ end
+end
+
+def fun_l15_n883(x)
+ if (x < 1)
+ fun_l16_n776(x)
+ else
+ fun_l16_n147(x)
+ end
+end
+
+def fun_l15_n884(x)
+ if (x < 1)
+ fun_l16_n145(x)
+ else
+ fun_l16_n856(x)
+ end
+end
+
+def fun_l15_n885(x)
+ if (x < 1)
+ fun_l16_n671(x)
+ else
+ fun_l16_n429(x)
+ end
+end
+
+def fun_l15_n886(x)
+ if (x < 1)
+ fun_l16_n72(x)
+ else
+ fun_l16_n455(x)
+ end
+end
+
+def fun_l15_n887(x)
+ if (x < 1)
+ fun_l16_n775(x)
+ else
+ fun_l16_n43(x)
+ end
+end
+
+def fun_l15_n888(x)
+ if (x < 1)
+ fun_l16_n936(x)
+ else
+ fun_l16_n642(x)
+ end
+end
+
+def fun_l15_n889(x)
+ if (x < 1)
+ fun_l16_n794(x)
+ else
+ fun_l16_n277(x)
+ end
+end
+
+def fun_l15_n890(x)
+ if (x < 1)
+ fun_l16_n72(x)
+ else
+ fun_l16_n450(x)
+ end
+end
+
+def fun_l15_n891(x)
+ if (x < 1)
+ fun_l16_n417(x)
+ else
+ fun_l16_n5(x)
+ end
+end
+
+def fun_l15_n892(x)
+ if (x < 1)
+ fun_l16_n69(x)
+ else
+ fun_l16_n355(x)
+ end
+end
+
+def fun_l15_n893(x)
+ if (x < 1)
+ fun_l16_n352(x)
+ else
+ fun_l16_n635(x)
+ end
+end
+
+def fun_l15_n894(x)
+ if (x < 1)
+ fun_l16_n168(x)
+ else
+ fun_l16_n16(x)
+ end
+end
+
+def fun_l15_n895(x)
+ if (x < 1)
+ fun_l16_n922(x)
+ else
+ fun_l16_n440(x)
+ end
+end
+
+def fun_l15_n896(x)
+ if (x < 1)
+ fun_l16_n808(x)
+ else
+ fun_l16_n896(x)
+ end
+end
+
+def fun_l15_n897(x)
+ if (x < 1)
+ fun_l16_n736(x)
+ else
+ fun_l16_n596(x)
+ end
+end
+
+def fun_l15_n898(x)
+ if (x < 1)
+ fun_l16_n886(x)
+ else
+ fun_l16_n386(x)
+ end
+end
+
+def fun_l15_n899(x)
+ if (x < 1)
+ fun_l16_n374(x)
+ else
+ fun_l16_n746(x)
+ end
+end
+
+def fun_l15_n900(x)
+ if (x < 1)
+ fun_l16_n623(x)
+ else
+ fun_l16_n329(x)
+ end
+end
+
+def fun_l15_n901(x)
+ if (x < 1)
+ fun_l16_n313(x)
+ else
+ fun_l16_n102(x)
+ end
+end
+
+def fun_l15_n902(x)
+ if (x < 1)
+ fun_l16_n234(x)
+ else
+ fun_l16_n425(x)
+ end
+end
+
+def fun_l15_n903(x)
+ if (x < 1)
+ fun_l16_n836(x)
+ else
+ fun_l16_n492(x)
+ end
+end
+
+def fun_l15_n904(x)
+ if (x < 1)
+ fun_l16_n690(x)
+ else
+ fun_l16_n241(x)
+ end
+end
+
+def fun_l15_n905(x)
+ if (x < 1)
+ fun_l16_n129(x)
+ else
+ fun_l16_n57(x)
+ end
+end
+
+def fun_l15_n906(x)
+ if (x < 1)
+ fun_l16_n50(x)
+ else
+ fun_l16_n24(x)
+ end
+end
+
+def fun_l15_n907(x)
+ if (x < 1)
+ fun_l16_n609(x)
+ else
+ fun_l16_n4(x)
+ end
+end
+
+def fun_l15_n908(x)
+ if (x < 1)
+ fun_l16_n483(x)
+ else
+ fun_l16_n708(x)
+ end
+end
+
+def fun_l15_n909(x)
+ if (x < 1)
+ fun_l16_n656(x)
+ else
+ fun_l16_n234(x)
+ end
+end
+
+def fun_l15_n910(x)
+ if (x < 1)
+ fun_l16_n945(x)
+ else
+ fun_l16_n753(x)
+ end
+end
+
+def fun_l15_n911(x)
+ if (x < 1)
+ fun_l16_n152(x)
+ else
+ fun_l16_n739(x)
+ end
+end
+
+def fun_l15_n912(x)
+ if (x < 1)
+ fun_l16_n855(x)
+ else
+ fun_l16_n518(x)
+ end
+end
+
+def fun_l15_n913(x)
+ if (x < 1)
+ fun_l16_n295(x)
+ else
+ fun_l16_n719(x)
+ end
+end
+
+def fun_l15_n914(x)
+ if (x < 1)
+ fun_l16_n442(x)
+ else
+ fun_l16_n803(x)
+ end
+end
+
+def fun_l15_n915(x)
+ if (x < 1)
+ fun_l16_n672(x)
+ else
+ fun_l16_n935(x)
+ end
+end
+
+def fun_l15_n916(x)
+ if (x < 1)
+ fun_l16_n908(x)
+ else
+ fun_l16_n900(x)
+ end
+end
+
+def fun_l15_n917(x)
+ if (x < 1)
+ fun_l16_n853(x)
+ else
+ fun_l16_n896(x)
+ end
+end
+
+def fun_l15_n918(x)
+ if (x < 1)
+ fun_l16_n90(x)
+ else
+ fun_l16_n56(x)
+ end
+end
+
+def fun_l15_n919(x)
+ if (x < 1)
+ fun_l16_n944(x)
+ else
+ fun_l16_n763(x)
+ end
+end
+
+def fun_l15_n920(x)
+ if (x < 1)
+ fun_l16_n303(x)
+ else
+ fun_l16_n328(x)
+ end
+end
+
+def fun_l15_n921(x)
+ if (x < 1)
+ fun_l16_n599(x)
+ else
+ fun_l16_n648(x)
+ end
+end
+
+def fun_l15_n922(x)
+ if (x < 1)
+ fun_l16_n113(x)
+ else
+ fun_l16_n665(x)
+ end
+end
+
+def fun_l15_n923(x)
+ if (x < 1)
+ fun_l16_n97(x)
+ else
+ fun_l16_n757(x)
+ end
+end
+
+def fun_l15_n924(x)
+ if (x < 1)
+ fun_l16_n815(x)
+ else
+ fun_l16_n821(x)
+ end
+end
+
+def fun_l15_n925(x)
+ if (x < 1)
+ fun_l16_n146(x)
+ else
+ fun_l16_n970(x)
+ end
+end
+
+def fun_l15_n926(x)
+ if (x < 1)
+ fun_l16_n74(x)
+ else
+ fun_l16_n203(x)
+ end
+end
+
+def fun_l15_n927(x)
+ if (x < 1)
+ fun_l16_n573(x)
+ else
+ fun_l16_n763(x)
+ end
+end
+
+def fun_l15_n928(x)
+ if (x < 1)
+ fun_l16_n656(x)
+ else
+ fun_l16_n691(x)
+ end
+end
+
+def fun_l15_n929(x)
+ if (x < 1)
+ fun_l16_n240(x)
+ else
+ fun_l16_n536(x)
+ end
+end
+
+def fun_l15_n930(x)
+ if (x < 1)
+ fun_l16_n168(x)
+ else
+ fun_l16_n145(x)
+ end
+end
+
+def fun_l15_n931(x)
+ if (x < 1)
+ fun_l16_n502(x)
+ else
+ fun_l16_n603(x)
+ end
+end
+
+def fun_l15_n932(x)
+ if (x < 1)
+ fun_l16_n998(x)
+ else
+ fun_l16_n259(x)
+ end
+end
+
+def fun_l15_n933(x)
+ if (x < 1)
+ fun_l16_n633(x)
+ else
+ fun_l16_n66(x)
+ end
+end
+
+def fun_l15_n934(x)
+ if (x < 1)
+ fun_l16_n657(x)
+ else
+ fun_l16_n727(x)
+ end
+end
+
+def fun_l15_n935(x)
+ if (x < 1)
+ fun_l16_n641(x)
+ else
+ fun_l16_n975(x)
+ end
+end
+
+def fun_l15_n936(x)
+ if (x < 1)
+ fun_l16_n610(x)
+ else
+ fun_l16_n256(x)
+ end
+end
+
+def fun_l15_n937(x)
+ if (x < 1)
+ fun_l16_n760(x)
+ else
+ fun_l16_n304(x)
+ end
+end
+
+def fun_l15_n938(x)
+ if (x < 1)
+ fun_l16_n395(x)
+ else
+ fun_l16_n302(x)
+ end
+end
+
+def fun_l15_n939(x)
+ if (x < 1)
+ fun_l16_n810(x)
+ else
+ fun_l16_n549(x)
+ end
+end
+
+def fun_l15_n940(x)
+ if (x < 1)
+ fun_l16_n452(x)
+ else
+ fun_l16_n914(x)
+ end
+end
+
+def fun_l15_n941(x)
+ if (x < 1)
+ fun_l16_n472(x)
+ else
+ fun_l16_n328(x)
+ end
+end
+
+def fun_l15_n942(x)
+ if (x < 1)
+ fun_l16_n886(x)
+ else
+ fun_l16_n535(x)
+ end
+end
+
+def fun_l15_n943(x)
+ if (x < 1)
+ fun_l16_n162(x)
+ else
+ fun_l16_n449(x)
+ end
+end
+
+def fun_l15_n944(x)
+ if (x < 1)
+ fun_l16_n152(x)
+ else
+ fun_l16_n790(x)
+ end
+end
+
+def fun_l15_n945(x)
+ if (x < 1)
+ fun_l16_n228(x)
+ else
+ fun_l16_n391(x)
+ end
+end
+
+def fun_l15_n946(x)
+ if (x < 1)
+ fun_l16_n115(x)
+ else
+ fun_l16_n371(x)
+ end
+end
+
+def fun_l15_n947(x)
+ if (x < 1)
+ fun_l16_n359(x)
+ else
+ fun_l16_n928(x)
+ end
+end
+
+def fun_l15_n948(x)
+ if (x < 1)
+ fun_l16_n246(x)
+ else
+ fun_l16_n907(x)
+ end
+end
+
+def fun_l15_n949(x)
+ if (x < 1)
+ fun_l16_n448(x)
+ else
+ fun_l16_n845(x)
+ end
+end
+
+def fun_l15_n950(x)
+ if (x < 1)
+ fun_l16_n457(x)
+ else
+ fun_l16_n954(x)
+ end
+end
+
+def fun_l15_n951(x)
+ if (x < 1)
+ fun_l16_n627(x)
+ else
+ fun_l16_n684(x)
+ end
+end
+
+def fun_l15_n952(x)
+ if (x < 1)
+ fun_l16_n887(x)
+ else
+ fun_l16_n928(x)
+ end
+end
+
+def fun_l15_n953(x)
+ if (x < 1)
+ fun_l16_n782(x)
+ else
+ fun_l16_n619(x)
+ end
+end
+
+def fun_l15_n954(x)
+ if (x < 1)
+ fun_l16_n436(x)
+ else
+ fun_l16_n745(x)
+ end
+end
+
+def fun_l15_n955(x)
+ if (x < 1)
+ fun_l16_n9(x)
+ else
+ fun_l16_n604(x)
+ end
+end
+
+def fun_l15_n956(x)
+ if (x < 1)
+ fun_l16_n149(x)
+ else
+ fun_l16_n357(x)
+ end
+end
+
+def fun_l15_n957(x)
+ if (x < 1)
+ fun_l16_n664(x)
+ else
+ fun_l16_n371(x)
+ end
+end
+
+def fun_l15_n958(x)
+ if (x < 1)
+ fun_l16_n236(x)
+ else
+ fun_l16_n402(x)
+ end
+end
+
+def fun_l15_n959(x)
+ if (x < 1)
+ fun_l16_n681(x)
+ else
+ fun_l16_n410(x)
+ end
+end
+
+def fun_l15_n960(x)
+ if (x < 1)
+ fun_l16_n909(x)
+ else
+ fun_l16_n958(x)
+ end
+end
+
+def fun_l15_n961(x)
+ if (x < 1)
+ fun_l16_n400(x)
+ else
+ fun_l16_n497(x)
+ end
+end
+
+def fun_l15_n962(x)
+ if (x < 1)
+ fun_l16_n949(x)
+ else
+ fun_l16_n794(x)
+ end
+end
+
+def fun_l15_n963(x)
+ if (x < 1)
+ fun_l16_n774(x)
+ else
+ fun_l16_n770(x)
+ end
+end
+
+def fun_l15_n964(x)
+ if (x < 1)
+ fun_l16_n573(x)
+ else
+ fun_l16_n73(x)
+ end
+end
+
+def fun_l15_n965(x)
+ if (x < 1)
+ fun_l16_n33(x)
+ else
+ fun_l16_n978(x)
+ end
+end
+
+def fun_l15_n966(x)
+ if (x < 1)
+ fun_l16_n8(x)
+ else
+ fun_l16_n542(x)
+ end
+end
+
+def fun_l15_n967(x)
+ if (x < 1)
+ fun_l16_n780(x)
+ else
+ fun_l16_n96(x)
+ end
+end
+
+def fun_l15_n968(x)
+ if (x < 1)
+ fun_l16_n75(x)
+ else
+ fun_l16_n560(x)
+ end
+end
+
+def fun_l15_n969(x)
+ if (x < 1)
+ fun_l16_n950(x)
+ else
+ fun_l16_n610(x)
+ end
+end
+
+def fun_l15_n970(x)
+ if (x < 1)
+ fun_l16_n254(x)
+ else
+ fun_l16_n2(x)
+ end
+end
+
+def fun_l15_n971(x)
+ if (x < 1)
+ fun_l16_n793(x)
+ else
+ fun_l16_n89(x)
+ end
+end
+
+def fun_l15_n972(x)
+ if (x < 1)
+ fun_l16_n409(x)
+ else
+ fun_l16_n967(x)
+ end
+end
+
+def fun_l15_n973(x)
+ if (x < 1)
+ fun_l16_n356(x)
+ else
+ fun_l16_n421(x)
+ end
+end
+
+def fun_l15_n974(x)
+ if (x < 1)
+ fun_l16_n539(x)
+ else
+ fun_l16_n997(x)
+ end
+end
+
+def fun_l15_n975(x)
+ if (x < 1)
+ fun_l16_n772(x)
+ else
+ fun_l16_n304(x)
+ end
+end
+
+def fun_l15_n976(x)
+ if (x < 1)
+ fun_l16_n228(x)
+ else
+ fun_l16_n420(x)
+ end
+end
+
+def fun_l15_n977(x)
+ if (x < 1)
+ fun_l16_n508(x)
+ else
+ fun_l16_n352(x)
+ end
+end
+
+def fun_l15_n978(x)
+ if (x < 1)
+ fun_l16_n878(x)
+ else
+ fun_l16_n316(x)
+ end
+end
+
+def fun_l15_n979(x)
+ if (x < 1)
+ fun_l16_n279(x)
+ else
+ fun_l16_n325(x)
+ end
+end
+
+def fun_l15_n980(x)
+ if (x < 1)
+ fun_l16_n98(x)
+ else
+ fun_l16_n10(x)
+ end
+end
+
+def fun_l15_n981(x)
+ if (x < 1)
+ fun_l16_n320(x)
+ else
+ fun_l16_n578(x)
+ end
+end
+
+def fun_l15_n982(x)
+ if (x < 1)
+ fun_l16_n112(x)
+ else
+ fun_l16_n353(x)
+ end
+end
+
+def fun_l15_n983(x)
+ if (x < 1)
+ fun_l16_n579(x)
+ else
+ fun_l16_n946(x)
+ end
+end
+
+def fun_l15_n984(x)
+ if (x < 1)
+ fun_l16_n183(x)
+ else
+ fun_l16_n638(x)
+ end
+end
+
+def fun_l15_n985(x)
+ if (x < 1)
+ fun_l16_n500(x)
+ else
+ fun_l16_n11(x)
+ end
+end
+
+def fun_l15_n986(x)
+ if (x < 1)
+ fun_l16_n773(x)
+ else
+ fun_l16_n135(x)
+ end
+end
+
+def fun_l15_n987(x)
+ if (x < 1)
+ fun_l16_n997(x)
+ else
+ fun_l16_n645(x)
+ end
+end
+
+def fun_l15_n988(x)
+ if (x < 1)
+ fun_l16_n392(x)
+ else
+ fun_l16_n172(x)
+ end
+end
+
+def fun_l15_n989(x)
+ if (x < 1)
+ fun_l16_n150(x)
+ else
+ fun_l16_n163(x)
+ end
+end
+
+def fun_l15_n990(x)
+ if (x < 1)
+ fun_l16_n351(x)
+ else
+ fun_l16_n297(x)
+ end
+end
+
+def fun_l15_n991(x)
+ if (x < 1)
+ fun_l16_n676(x)
+ else
+ fun_l16_n31(x)
+ end
+end
+
+def fun_l15_n992(x)
+ if (x < 1)
+ fun_l16_n257(x)
+ else
+ fun_l16_n45(x)
+ end
+end
+
+def fun_l15_n993(x)
+ if (x < 1)
+ fun_l16_n971(x)
+ else
+ fun_l16_n60(x)
+ end
+end
+
+def fun_l15_n994(x)
+ if (x < 1)
+ fun_l16_n472(x)
+ else
+ fun_l16_n774(x)
+ end
+end
+
+def fun_l15_n995(x)
+ if (x < 1)
+ fun_l16_n559(x)
+ else
+ fun_l16_n605(x)
+ end
+end
+
+def fun_l15_n996(x)
+ if (x < 1)
+ fun_l16_n122(x)
+ else
+ fun_l16_n695(x)
+ end
+end
+
+def fun_l15_n997(x)
+ if (x < 1)
+ fun_l16_n118(x)
+ else
+ fun_l16_n613(x)
+ end
+end
+
+def fun_l15_n998(x)
+ if (x < 1)
+ fun_l16_n973(x)
+ else
+ fun_l16_n193(x)
+ end
+end
+
+def fun_l15_n999(x)
+ if (x < 1)
+ fun_l16_n652(x)
+ else
+ fun_l16_n658(x)
+ end
+end
+
+def fun_l16_n0(x)
+ if (x < 1)
+ fun_l17_n352(x)
+ else
+ fun_l17_n155(x)
+ end
+end
+
+def fun_l16_n1(x)
+ if (x < 1)
+ fun_l17_n786(x)
+ else
+ fun_l17_n961(x)
+ end
+end
+
+def fun_l16_n2(x)
+ if (x < 1)
+ fun_l17_n760(x)
+ else
+ fun_l17_n629(x)
+ end
+end
+
+def fun_l16_n3(x)
+ if (x < 1)
+ fun_l17_n788(x)
+ else
+ fun_l17_n70(x)
+ end
+end
+
+def fun_l16_n4(x)
+ if (x < 1)
+ fun_l17_n116(x)
+ else
+ fun_l17_n616(x)
+ end
+end
+
+def fun_l16_n5(x)
+ if (x < 1)
+ fun_l17_n470(x)
+ else
+ fun_l17_n859(x)
+ end
+end
+
+def fun_l16_n6(x)
+ if (x < 1)
+ fun_l17_n830(x)
+ else
+ fun_l17_n987(x)
+ end
+end
+
+def fun_l16_n7(x)
+ if (x < 1)
+ fun_l17_n339(x)
+ else
+ fun_l17_n284(x)
+ end
+end
+
+def fun_l16_n8(x)
+ if (x < 1)
+ fun_l17_n677(x)
+ else
+ fun_l17_n77(x)
+ end
+end
+
+def fun_l16_n9(x)
+ if (x < 1)
+ fun_l17_n7(x)
+ else
+ fun_l17_n159(x)
+ end
+end
+
+def fun_l16_n10(x)
+ if (x < 1)
+ fun_l17_n275(x)
+ else
+ fun_l17_n37(x)
+ end
+end
+
+def fun_l16_n11(x)
+ if (x < 1)
+ fun_l17_n406(x)
+ else
+ fun_l17_n588(x)
+ end
+end
+
+def fun_l16_n12(x)
+ if (x < 1)
+ fun_l17_n132(x)
+ else
+ fun_l17_n208(x)
+ end
+end
+
+def fun_l16_n13(x)
+ if (x < 1)
+ fun_l17_n87(x)
+ else
+ fun_l17_n850(x)
+ end
+end
+
+def fun_l16_n14(x)
+ if (x < 1)
+ fun_l17_n965(x)
+ else
+ fun_l17_n106(x)
+ end
+end
+
+def fun_l16_n15(x)
+ if (x < 1)
+ fun_l17_n176(x)
+ else
+ fun_l17_n966(x)
+ end
+end
+
+def fun_l16_n16(x)
+ if (x < 1)
+ fun_l17_n825(x)
+ else
+ fun_l17_n815(x)
+ end
+end
+
+def fun_l16_n17(x)
+ if (x < 1)
+ fun_l17_n939(x)
+ else
+ fun_l17_n591(x)
+ end
+end
+
+def fun_l16_n18(x)
+ if (x < 1)
+ fun_l17_n166(x)
+ else
+ fun_l17_n732(x)
+ end
+end
+
+def fun_l16_n19(x)
+ if (x < 1)
+ fun_l17_n471(x)
+ else
+ fun_l17_n175(x)
+ end
+end
+
+def fun_l16_n20(x)
+ if (x < 1)
+ fun_l17_n887(x)
+ else
+ fun_l17_n304(x)
+ end
+end
+
+def fun_l16_n21(x)
+ if (x < 1)
+ fun_l17_n545(x)
+ else
+ fun_l17_n221(x)
+ end
+end
+
+def fun_l16_n22(x)
+ if (x < 1)
+ fun_l17_n879(x)
+ else
+ fun_l17_n143(x)
+ end
+end
+
+def fun_l16_n23(x)
+ if (x < 1)
+ fun_l17_n732(x)
+ else
+ fun_l17_n902(x)
+ end
+end
+
+def fun_l16_n24(x)
+ if (x < 1)
+ fun_l17_n490(x)
+ else
+ fun_l17_n327(x)
+ end
+end
+
+def fun_l16_n25(x)
+ if (x < 1)
+ fun_l17_n588(x)
+ else
+ fun_l17_n658(x)
+ end
+end
+
+def fun_l16_n26(x)
+ if (x < 1)
+ fun_l17_n555(x)
+ else
+ fun_l17_n507(x)
+ end
+end
+
+def fun_l16_n27(x)
+ if (x < 1)
+ fun_l17_n228(x)
+ else
+ fun_l17_n808(x)
+ end
+end
+
+def fun_l16_n28(x)
+ if (x < 1)
+ fun_l17_n705(x)
+ else
+ fun_l17_n696(x)
+ end
+end
+
+def fun_l16_n29(x)
+ if (x < 1)
+ fun_l17_n711(x)
+ else
+ fun_l17_n913(x)
+ end
+end
+
+def fun_l16_n30(x)
+ if (x < 1)
+ fun_l17_n264(x)
+ else
+ fun_l17_n287(x)
+ end
+end
+
+def fun_l16_n31(x)
+ if (x < 1)
+ fun_l17_n624(x)
+ else
+ fun_l17_n358(x)
+ end
+end
+
+def fun_l16_n32(x)
+ if (x < 1)
+ fun_l17_n102(x)
+ else
+ fun_l17_n303(x)
+ end
+end
+
+def fun_l16_n33(x)
+ if (x < 1)
+ fun_l17_n613(x)
+ else
+ fun_l17_n921(x)
+ end
+end
+
+def fun_l16_n34(x)
+ if (x < 1)
+ fun_l17_n637(x)
+ else
+ fun_l17_n142(x)
+ end
+end
+
+def fun_l16_n35(x)
+ if (x < 1)
+ fun_l17_n8(x)
+ else
+ fun_l17_n752(x)
+ end
+end
+
+def fun_l16_n36(x)
+ if (x < 1)
+ fun_l17_n748(x)
+ else
+ fun_l17_n956(x)
+ end
+end
+
+def fun_l16_n37(x)
+ if (x < 1)
+ fun_l17_n985(x)
+ else
+ fun_l17_n133(x)
+ end
+end
+
+def fun_l16_n38(x)
+ if (x < 1)
+ fun_l17_n422(x)
+ else
+ fun_l17_n608(x)
+ end
+end
+
+def fun_l16_n39(x)
+ if (x < 1)
+ fun_l17_n455(x)
+ else
+ fun_l17_n247(x)
+ end
+end
+
+def fun_l16_n40(x)
+ if (x < 1)
+ fun_l17_n363(x)
+ else
+ fun_l17_n874(x)
+ end
+end
+
+def fun_l16_n41(x)
+ if (x < 1)
+ fun_l17_n299(x)
+ else
+ fun_l17_n971(x)
+ end
+end
+
+def fun_l16_n42(x)
+ if (x < 1)
+ fun_l17_n788(x)
+ else
+ fun_l17_n535(x)
+ end
+end
+
+def fun_l16_n43(x)
+ if (x < 1)
+ fun_l17_n282(x)
+ else
+ fun_l17_n468(x)
+ end
+end
+
+def fun_l16_n44(x)
+ if (x < 1)
+ fun_l17_n493(x)
+ else
+ fun_l17_n931(x)
+ end
+end
+
+def fun_l16_n45(x)
+ if (x < 1)
+ fun_l17_n750(x)
+ else
+ fun_l17_n725(x)
+ end
+end
+
+def fun_l16_n46(x)
+ if (x < 1)
+ fun_l17_n227(x)
+ else
+ fun_l17_n769(x)
+ end
+end
+
+def fun_l16_n47(x)
+ if (x < 1)
+ fun_l17_n348(x)
+ else
+ fun_l17_n83(x)
+ end
+end
+
+def fun_l16_n48(x)
+ if (x < 1)
+ fun_l17_n624(x)
+ else
+ fun_l17_n398(x)
+ end
+end
+
+def fun_l16_n49(x)
+ if (x < 1)
+ fun_l17_n645(x)
+ else
+ fun_l17_n645(x)
+ end
+end
+
+def fun_l16_n50(x)
+ if (x < 1)
+ fun_l17_n191(x)
+ else
+ fun_l17_n256(x)
+ end
+end
+
+def fun_l16_n51(x)
+ if (x < 1)
+ fun_l17_n947(x)
+ else
+ fun_l17_n188(x)
+ end
+end
+
+def fun_l16_n52(x)
+ if (x < 1)
+ fun_l17_n135(x)
+ else
+ fun_l17_n923(x)
+ end
+end
+
+def fun_l16_n53(x)
+ if (x < 1)
+ fun_l17_n867(x)
+ else
+ fun_l17_n520(x)
+ end
+end
+
+def fun_l16_n54(x)
+ if (x < 1)
+ fun_l17_n450(x)
+ else
+ fun_l17_n864(x)
+ end
+end
+
+def fun_l16_n55(x)
+ if (x < 1)
+ fun_l17_n116(x)
+ else
+ fun_l17_n370(x)
+ end
+end
+
+def fun_l16_n56(x)
+ if (x < 1)
+ fun_l17_n754(x)
+ else
+ fun_l17_n919(x)
+ end
+end
+
+def fun_l16_n57(x)
+ if (x < 1)
+ fun_l17_n360(x)
+ else
+ fun_l17_n513(x)
+ end
+end
+
+def fun_l16_n58(x)
+ if (x < 1)
+ fun_l17_n436(x)
+ else
+ fun_l17_n618(x)
+ end
+end
+
+def fun_l16_n59(x)
+ if (x < 1)
+ fun_l17_n795(x)
+ else
+ fun_l17_n851(x)
+ end
+end
+
+def fun_l16_n60(x)
+ if (x < 1)
+ fun_l17_n624(x)
+ else
+ fun_l17_n305(x)
+ end
+end
+
+def fun_l16_n61(x)
+ if (x < 1)
+ fun_l17_n520(x)
+ else
+ fun_l17_n360(x)
+ end
+end
+
+def fun_l16_n62(x)
+ if (x < 1)
+ fun_l17_n297(x)
+ else
+ fun_l17_n218(x)
+ end
+end
+
+def fun_l16_n63(x)
+ if (x < 1)
+ fun_l17_n116(x)
+ else
+ fun_l17_n888(x)
+ end
+end
+
+def fun_l16_n64(x)
+ if (x < 1)
+ fun_l17_n800(x)
+ else
+ fun_l17_n985(x)
+ end
+end
+
+def fun_l16_n65(x)
+ if (x < 1)
+ fun_l17_n875(x)
+ else
+ fun_l17_n821(x)
+ end
+end
+
+def fun_l16_n66(x)
+ if (x < 1)
+ fun_l17_n677(x)
+ else
+ fun_l17_n705(x)
+ end
+end
+
+def fun_l16_n67(x)
+ if (x < 1)
+ fun_l17_n643(x)
+ else
+ fun_l17_n240(x)
+ end
+end
+
+def fun_l16_n68(x)
+ if (x < 1)
+ fun_l17_n290(x)
+ else
+ fun_l17_n885(x)
+ end
+end
+
+def fun_l16_n69(x)
+ if (x < 1)
+ fun_l17_n987(x)
+ else
+ fun_l17_n611(x)
+ end
+end
+
+def fun_l16_n70(x)
+ if (x < 1)
+ fun_l17_n546(x)
+ else
+ fun_l17_n95(x)
+ end
+end
+
+def fun_l16_n71(x)
+ if (x < 1)
+ fun_l17_n301(x)
+ else
+ fun_l17_n260(x)
+ end
+end
+
+def fun_l16_n72(x)
+ if (x < 1)
+ fun_l17_n118(x)
+ else
+ fun_l17_n110(x)
+ end
+end
+
+def fun_l16_n73(x)
+ if (x < 1)
+ fun_l17_n254(x)
+ else
+ fun_l17_n602(x)
+ end
+end
+
+def fun_l16_n74(x)
+ if (x < 1)
+ fun_l17_n725(x)
+ else
+ fun_l17_n606(x)
+ end
+end
+
+def fun_l16_n75(x)
+ if (x < 1)
+ fun_l17_n114(x)
+ else
+ fun_l17_n336(x)
+ end
+end
+
+def fun_l16_n76(x)
+ if (x < 1)
+ fun_l17_n930(x)
+ else
+ fun_l17_n513(x)
+ end
+end
+
+def fun_l16_n77(x)
+ if (x < 1)
+ fun_l17_n217(x)
+ else
+ fun_l17_n158(x)
+ end
+end
+
+def fun_l16_n78(x)
+ if (x < 1)
+ fun_l17_n987(x)
+ else
+ fun_l17_n538(x)
+ end
+end
+
+def fun_l16_n79(x)
+ if (x < 1)
+ fun_l17_n467(x)
+ else
+ fun_l17_n675(x)
+ end
+end
+
+def fun_l16_n80(x)
+ if (x < 1)
+ fun_l17_n553(x)
+ else
+ fun_l17_n77(x)
+ end
+end
+
+def fun_l16_n81(x)
+ if (x < 1)
+ fun_l17_n643(x)
+ else
+ fun_l17_n156(x)
+ end
+end
+
+def fun_l16_n82(x)
+ if (x < 1)
+ fun_l17_n858(x)
+ else
+ fun_l17_n300(x)
+ end
+end
+
+def fun_l16_n83(x)
+ if (x < 1)
+ fun_l17_n136(x)
+ else
+ fun_l17_n637(x)
+ end
+end
+
+def fun_l16_n84(x)
+ if (x < 1)
+ fun_l17_n71(x)
+ else
+ fun_l17_n979(x)
+ end
+end
+
+def fun_l16_n85(x)
+ if (x < 1)
+ fun_l17_n135(x)
+ else
+ fun_l17_n893(x)
+ end
+end
+
+def fun_l16_n86(x)
+ if (x < 1)
+ fun_l17_n734(x)
+ else
+ fun_l17_n254(x)
+ end
+end
+
+def fun_l16_n87(x)
+ if (x < 1)
+ fun_l17_n809(x)
+ else
+ fun_l17_n475(x)
+ end
+end
+
+def fun_l16_n88(x)
+ if (x < 1)
+ fun_l17_n931(x)
+ else
+ fun_l17_n110(x)
+ end
+end
+
+def fun_l16_n89(x)
+ if (x < 1)
+ fun_l17_n957(x)
+ else
+ fun_l17_n489(x)
+ end
+end
+
+def fun_l16_n90(x)
+ if (x < 1)
+ fun_l17_n145(x)
+ else
+ fun_l17_n861(x)
+ end
+end
+
+def fun_l16_n91(x)
+ if (x < 1)
+ fun_l17_n276(x)
+ else
+ fun_l17_n967(x)
+ end
+end
+
+def fun_l16_n92(x)
+ if (x < 1)
+ fun_l17_n657(x)
+ else
+ fun_l17_n638(x)
+ end
+end
+
+def fun_l16_n93(x)
+ if (x < 1)
+ fun_l17_n714(x)
+ else
+ fun_l17_n52(x)
+ end
+end
+
+def fun_l16_n94(x)
+ if (x < 1)
+ fun_l17_n487(x)
+ else
+ fun_l17_n380(x)
+ end
+end
+
+def fun_l16_n95(x)
+ if (x < 1)
+ fun_l17_n58(x)
+ else
+ fun_l17_n67(x)
+ end
+end
+
+def fun_l16_n96(x)
+ if (x < 1)
+ fun_l17_n9(x)
+ else
+ fun_l17_n896(x)
+ end
+end
+
+def fun_l16_n97(x)
+ if (x < 1)
+ fun_l17_n723(x)
+ else
+ fun_l17_n16(x)
+ end
+end
+
+def fun_l16_n98(x)
+ if (x < 1)
+ fun_l17_n143(x)
+ else
+ fun_l17_n31(x)
+ end
+end
+
+def fun_l16_n99(x)
+ if (x < 1)
+ fun_l17_n33(x)
+ else
+ fun_l17_n615(x)
+ end
+end
+
+def fun_l16_n100(x)
+ if (x < 1)
+ fun_l17_n318(x)
+ else
+ fun_l17_n83(x)
+ end
+end
+
+def fun_l16_n101(x)
+ if (x < 1)
+ fun_l17_n694(x)
+ else
+ fun_l17_n851(x)
+ end
+end
+
+def fun_l16_n102(x)
+ if (x < 1)
+ fun_l17_n31(x)
+ else
+ fun_l17_n881(x)
+ end
+end
+
+def fun_l16_n103(x)
+ if (x < 1)
+ fun_l17_n739(x)
+ else
+ fun_l17_n680(x)
+ end
+end
+
+def fun_l16_n104(x)
+ if (x < 1)
+ fun_l17_n123(x)
+ else
+ fun_l17_n969(x)
+ end
+end
+
+def fun_l16_n105(x)
+ if (x < 1)
+ fun_l17_n526(x)
+ else
+ fun_l17_n529(x)
+ end
+end
+
+def fun_l16_n106(x)
+ if (x < 1)
+ fun_l17_n613(x)
+ else
+ fun_l17_n738(x)
+ end
+end
+
+def fun_l16_n107(x)
+ if (x < 1)
+ fun_l17_n48(x)
+ else
+ fun_l17_n107(x)
+ end
+end
+
+def fun_l16_n108(x)
+ if (x < 1)
+ fun_l17_n493(x)
+ else
+ fun_l17_n875(x)
+ end
+end
+
+def fun_l16_n109(x)
+ if (x < 1)
+ fun_l17_n101(x)
+ else
+ fun_l17_n295(x)
+ end
+end
+
+def fun_l16_n110(x)
+ if (x < 1)
+ fun_l17_n257(x)
+ else
+ fun_l17_n132(x)
+ end
+end
+
+def fun_l16_n111(x)
+ if (x < 1)
+ fun_l17_n702(x)
+ else
+ fun_l17_n635(x)
+ end
+end
+
+def fun_l16_n112(x)
+ if (x < 1)
+ fun_l17_n193(x)
+ else
+ fun_l17_n931(x)
+ end
+end
+
+def fun_l16_n113(x)
+ if (x < 1)
+ fun_l17_n973(x)
+ else
+ fun_l17_n708(x)
+ end
+end
+
+def fun_l16_n114(x)
+ if (x < 1)
+ fun_l17_n110(x)
+ else
+ fun_l17_n247(x)
+ end
+end
+
+def fun_l16_n115(x)
+ if (x < 1)
+ fun_l17_n769(x)
+ else
+ fun_l17_n872(x)
+ end
+end
+
+def fun_l16_n116(x)
+ if (x < 1)
+ fun_l17_n63(x)
+ else
+ fun_l17_n90(x)
+ end
+end
+
+def fun_l16_n117(x)
+ if (x < 1)
+ fun_l17_n392(x)
+ else
+ fun_l17_n3(x)
+ end
+end
+
+def fun_l16_n118(x)
+ if (x < 1)
+ fun_l17_n73(x)
+ else
+ fun_l17_n354(x)
+ end
+end
+
+def fun_l16_n119(x)
+ if (x < 1)
+ fun_l17_n173(x)
+ else
+ fun_l17_n573(x)
+ end
+end
+
+def fun_l16_n120(x)
+ if (x < 1)
+ fun_l17_n481(x)
+ else
+ fun_l17_n571(x)
+ end
+end
+
+def fun_l16_n121(x)
+ if (x < 1)
+ fun_l17_n838(x)
+ else
+ fun_l17_n736(x)
+ end
+end
+
+def fun_l16_n122(x)
+ if (x < 1)
+ fun_l17_n400(x)
+ else
+ fun_l17_n169(x)
+ end
+end
+
+def fun_l16_n123(x)
+ if (x < 1)
+ fun_l17_n806(x)
+ else
+ fun_l17_n954(x)
+ end
+end
+
+def fun_l16_n124(x)
+ if (x < 1)
+ fun_l17_n328(x)
+ else
+ fun_l17_n200(x)
+ end
+end
+
+def fun_l16_n125(x)
+ if (x < 1)
+ fun_l17_n388(x)
+ else
+ fun_l17_n875(x)
+ end
+end
+
+def fun_l16_n126(x)
+ if (x < 1)
+ fun_l17_n178(x)
+ else
+ fun_l17_n122(x)
+ end
+end
+
+def fun_l16_n127(x)
+ if (x < 1)
+ fun_l17_n974(x)
+ else
+ fun_l17_n490(x)
+ end
+end
+
+def fun_l16_n128(x)
+ if (x < 1)
+ fun_l17_n731(x)
+ else
+ fun_l17_n807(x)
+ end
+end
+
+def fun_l16_n129(x)
+ if (x < 1)
+ fun_l17_n939(x)
+ else
+ fun_l17_n532(x)
+ end
+end
+
+def fun_l16_n130(x)
+ if (x < 1)
+ fun_l17_n482(x)
+ else
+ fun_l17_n926(x)
+ end
+end
+
+def fun_l16_n131(x)
+ if (x < 1)
+ fun_l17_n884(x)
+ else
+ fun_l17_n179(x)
+ end
+end
+
+def fun_l16_n132(x)
+ if (x < 1)
+ fun_l17_n683(x)
+ else
+ fun_l17_n24(x)
+ end
+end
+
+def fun_l16_n133(x)
+ if (x < 1)
+ fun_l17_n968(x)
+ else
+ fun_l17_n536(x)
+ end
+end
+
+def fun_l16_n134(x)
+ if (x < 1)
+ fun_l17_n229(x)
+ else
+ fun_l17_n280(x)
+ end
+end
+
+def fun_l16_n135(x)
+ if (x < 1)
+ fun_l17_n47(x)
+ else
+ fun_l17_n12(x)
+ end
+end
+
+def fun_l16_n136(x)
+ if (x < 1)
+ fun_l17_n905(x)
+ else
+ fun_l17_n461(x)
+ end
+end
+
+def fun_l16_n137(x)
+ if (x < 1)
+ fun_l17_n992(x)
+ else
+ fun_l17_n294(x)
+ end
+end
+
+def fun_l16_n138(x)
+ if (x < 1)
+ fun_l17_n383(x)
+ else
+ fun_l17_n916(x)
+ end
+end
+
+def fun_l16_n139(x)
+ if (x < 1)
+ fun_l17_n116(x)
+ else
+ fun_l17_n96(x)
+ end
+end
+
+def fun_l16_n140(x)
+ if (x < 1)
+ fun_l17_n702(x)
+ else
+ fun_l17_n294(x)
+ end
+end
+
+def fun_l16_n141(x)
+ if (x < 1)
+ fun_l17_n528(x)
+ else
+ fun_l17_n650(x)
+ end
+end
+
+def fun_l16_n142(x)
+ if (x < 1)
+ fun_l17_n341(x)
+ else
+ fun_l17_n168(x)
+ end
+end
+
+def fun_l16_n143(x)
+ if (x < 1)
+ fun_l17_n85(x)
+ else
+ fun_l17_n384(x)
+ end
+end
+
+def fun_l16_n144(x)
+ if (x < 1)
+ fun_l17_n738(x)
+ else
+ fun_l17_n842(x)
+ end
+end
+
+def fun_l16_n145(x)
+ if (x < 1)
+ fun_l17_n359(x)
+ else
+ fun_l17_n691(x)
+ end
+end
+
+def fun_l16_n146(x)
+ if (x < 1)
+ fun_l17_n465(x)
+ else
+ fun_l17_n310(x)
+ end
+end
+
+def fun_l16_n147(x)
+ if (x < 1)
+ fun_l17_n610(x)
+ else
+ fun_l17_n133(x)
+ end
+end
+
+def fun_l16_n148(x)
+ if (x < 1)
+ fun_l17_n829(x)
+ else
+ fun_l17_n449(x)
+ end
+end
+
+def fun_l16_n149(x)
+ if (x < 1)
+ fun_l17_n319(x)
+ else
+ fun_l17_n875(x)
+ end
+end
+
+def fun_l16_n150(x)
+ if (x < 1)
+ fun_l17_n493(x)
+ else
+ fun_l17_n39(x)
+ end
+end
+
+def fun_l16_n151(x)
+ if (x < 1)
+ fun_l17_n801(x)
+ else
+ fun_l17_n294(x)
+ end
+end
+
+def fun_l16_n152(x)
+ if (x < 1)
+ fun_l17_n39(x)
+ else
+ fun_l17_n113(x)
+ end
+end
+
+def fun_l16_n153(x)
+ if (x < 1)
+ fun_l17_n299(x)
+ else
+ fun_l17_n560(x)
+ end
+end
+
+def fun_l16_n154(x)
+ if (x < 1)
+ fun_l17_n220(x)
+ else
+ fun_l17_n485(x)
+ end
+end
+
+def fun_l16_n155(x)
+ if (x < 1)
+ fun_l17_n219(x)
+ else
+ fun_l17_n210(x)
+ end
+end
+
+def fun_l16_n156(x)
+ if (x < 1)
+ fun_l17_n44(x)
+ else
+ fun_l17_n394(x)
+ end
+end
+
+def fun_l16_n157(x)
+ if (x < 1)
+ fun_l17_n858(x)
+ else
+ fun_l17_n9(x)
+ end
+end
+
+def fun_l16_n158(x)
+ if (x < 1)
+ fun_l17_n298(x)
+ else
+ fun_l17_n584(x)
+ end
+end
+
+def fun_l16_n159(x)
+ if (x < 1)
+ fun_l17_n627(x)
+ else
+ fun_l17_n991(x)
+ end
+end
+
+def fun_l16_n160(x)
+ if (x < 1)
+ fun_l17_n459(x)
+ else
+ fun_l17_n686(x)
+ end
+end
+
+def fun_l16_n161(x)
+ if (x < 1)
+ fun_l17_n694(x)
+ else
+ fun_l17_n503(x)
+ end
+end
+
+def fun_l16_n162(x)
+ if (x < 1)
+ fun_l17_n331(x)
+ else
+ fun_l17_n869(x)
+ end
+end
+
+def fun_l16_n163(x)
+ if (x < 1)
+ fun_l17_n958(x)
+ else
+ fun_l17_n102(x)
+ end
+end
+
+def fun_l16_n164(x)
+ if (x < 1)
+ fun_l17_n254(x)
+ else
+ fun_l17_n888(x)
+ end
+end
+
+def fun_l16_n165(x)
+ if (x < 1)
+ fun_l17_n639(x)
+ else
+ fun_l17_n342(x)
+ end
+end
+
+def fun_l16_n166(x)
+ if (x < 1)
+ fun_l17_n859(x)
+ else
+ fun_l17_n2(x)
+ end
+end
+
+def fun_l16_n167(x)
+ if (x < 1)
+ fun_l17_n504(x)
+ else
+ fun_l17_n726(x)
+ end
+end
+
+def fun_l16_n168(x)
+ if (x < 1)
+ fun_l17_n426(x)
+ else
+ fun_l17_n532(x)
+ end
+end
+
+def fun_l16_n169(x)
+ if (x < 1)
+ fun_l17_n919(x)
+ else
+ fun_l17_n515(x)
+ end
+end
+
+def fun_l16_n170(x)
+ if (x < 1)
+ fun_l17_n394(x)
+ else
+ fun_l17_n259(x)
+ end
+end
+
+def fun_l16_n171(x)
+ if (x < 1)
+ fun_l17_n920(x)
+ else
+ fun_l17_n502(x)
+ end
+end
+
+def fun_l16_n172(x)
+ if (x < 1)
+ fun_l17_n898(x)
+ else
+ fun_l17_n984(x)
+ end
+end
+
+def fun_l16_n173(x)
+ if (x < 1)
+ fun_l17_n869(x)
+ else
+ fun_l17_n470(x)
+ end
+end
+
+def fun_l16_n174(x)
+ if (x < 1)
+ fun_l17_n959(x)
+ else
+ fun_l17_n283(x)
+ end
+end
+
+def fun_l16_n175(x)
+ if (x < 1)
+ fun_l17_n1(x)
+ else
+ fun_l17_n68(x)
+ end
+end
+
+def fun_l16_n176(x)
+ if (x < 1)
+ fun_l17_n91(x)
+ else
+ fun_l17_n684(x)
+ end
+end
+
+def fun_l16_n177(x)
+ if (x < 1)
+ fun_l17_n803(x)
+ else
+ fun_l17_n335(x)
+ end
+end
+
+def fun_l16_n178(x)
+ if (x < 1)
+ fun_l17_n242(x)
+ else
+ fun_l17_n671(x)
+ end
+end
+
+def fun_l16_n179(x)
+ if (x < 1)
+ fun_l17_n944(x)
+ else
+ fun_l17_n136(x)
+ end
+end
+
+def fun_l16_n180(x)
+ if (x < 1)
+ fun_l17_n681(x)
+ else
+ fun_l17_n587(x)
+ end
+end
+
+def fun_l16_n181(x)
+ if (x < 1)
+ fun_l17_n564(x)
+ else
+ fun_l17_n965(x)
+ end
+end
+
+def fun_l16_n182(x)
+ if (x < 1)
+ fun_l17_n107(x)
+ else
+ fun_l17_n229(x)
+ end
+end
+
+def fun_l16_n183(x)
+ if (x < 1)
+ fun_l17_n467(x)
+ else
+ fun_l17_n155(x)
+ end
+end
+
+def fun_l16_n184(x)
+ if (x < 1)
+ fun_l17_n62(x)
+ else
+ fun_l17_n507(x)
+ end
+end
+
+def fun_l16_n185(x)
+ if (x < 1)
+ fun_l17_n632(x)
+ else
+ fun_l17_n792(x)
+ end
+end
+
+def fun_l16_n186(x)
+ if (x < 1)
+ fun_l17_n174(x)
+ else
+ fun_l17_n623(x)
+ end
+end
+
+def fun_l16_n187(x)
+ if (x < 1)
+ fun_l17_n733(x)
+ else
+ fun_l17_n640(x)
+ end
+end
+
+def fun_l16_n188(x)
+ if (x < 1)
+ fun_l17_n968(x)
+ else
+ fun_l17_n554(x)
+ end
+end
+
+def fun_l16_n189(x)
+ if (x < 1)
+ fun_l17_n363(x)
+ else
+ fun_l17_n381(x)
+ end
+end
+
+def fun_l16_n190(x)
+ if (x < 1)
+ fun_l17_n34(x)
+ else
+ fun_l17_n145(x)
+ end
+end
+
+def fun_l16_n191(x)
+ if (x < 1)
+ fun_l17_n407(x)
+ else
+ fun_l17_n567(x)
+ end
+end
+
+def fun_l16_n192(x)
+ if (x < 1)
+ fun_l17_n497(x)
+ else
+ fun_l17_n842(x)
+ end
+end
+
+def fun_l16_n193(x)
+ if (x < 1)
+ fun_l17_n935(x)
+ else
+ fun_l17_n394(x)
+ end
+end
+
+def fun_l16_n194(x)
+ if (x < 1)
+ fun_l17_n728(x)
+ else
+ fun_l17_n885(x)
+ end
+end
+
+def fun_l16_n195(x)
+ if (x < 1)
+ fun_l17_n974(x)
+ else
+ fun_l17_n678(x)
+ end
+end
+
+def fun_l16_n196(x)
+ if (x < 1)
+ fun_l17_n420(x)
+ else
+ fun_l17_n894(x)
+ end
+end
+
+def fun_l16_n197(x)
+ if (x < 1)
+ fun_l17_n651(x)
+ else
+ fun_l17_n569(x)
+ end
+end
+
+def fun_l16_n198(x)
+ if (x < 1)
+ fun_l17_n274(x)
+ else
+ fun_l17_n683(x)
+ end
+end
+
+def fun_l16_n199(x)
+ if (x < 1)
+ fun_l17_n624(x)
+ else
+ fun_l17_n343(x)
+ end
+end
+
+def fun_l16_n200(x)
+ if (x < 1)
+ fun_l17_n82(x)
+ else
+ fun_l17_n472(x)
+ end
+end
+
+def fun_l16_n201(x)
+ if (x < 1)
+ fun_l17_n519(x)
+ else
+ fun_l17_n54(x)
+ end
+end
+
+def fun_l16_n202(x)
+ if (x < 1)
+ fun_l17_n858(x)
+ else
+ fun_l17_n379(x)
+ end
+end
+
+def fun_l16_n203(x)
+ if (x < 1)
+ fun_l17_n515(x)
+ else
+ fun_l17_n59(x)
+ end
+end
+
+def fun_l16_n204(x)
+ if (x < 1)
+ fun_l17_n736(x)
+ else
+ fun_l17_n880(x)
+ end
+end
+
+def fun_l16_n205(x)
+ if (x < 1)
+ fun_l17_n724(x)
+ else
+ fun_l17_n890(x)
+ end
+end
+
+def fun_l16_n206(x)
+ if (x < 1)
+ fun_l17_n92(x)
+ else
+ fun_l17_n305(x)
+ end
+end
+
+def fun_l16_n207(x)
+ if (x < 1)
+ fun_l17_n123(x)
+ else
+ fun_l17_n455(x)
+ end
+end
+
+def fun_l16_n208(x)
+ if (x < 1)
+ fun_l17_n722(x)
+ else
+ fun_l17_n142(x)
+ end
+end
+
+def fun_l16_n209(x)
+ if (x < 1)
+ fun_l17_n250(x)
+ else
+ fun_l17_n810(x)
+ end
+end
+
+def fun_l16_n210(x)
+ if (x < 1)
+ fun_l17_n118(x)
+ else
+ fun_l17_n902(x)
+ end
+end
+
+def fun_l16_n211(x)
+ if (x < 1)
+ fun_l17_n8(x)
+ else
+ fun_l17_n874(x)
+ end
+end
+
+def fun_l16_n212(x)
+ if (x < 1)
+ fun_l17_n589(x)
+ else
+ fun_l17_n731(x)
+ end
+end
+
+def fun_l16_n213(x)
+ if (x < 1)
+ fun_l17_n786(x)
+ else
+ fun_l17_n249(x)
+ end
+end
+
+def fun_l16_n214(x)
+ if (x < 1)
+ fun_l17_n80(x)
+ else
+ fun_l17_n763(x)
+ end
+end
+
+def fun_l16_n215(x)
+ if (x < 1)
+ fun_l17_n733(x)
+ else
+ fun_l17_n657(x)
+ end
+end
+
+def fun_l16_n216(x)
+ if (x < 1)
+ fun_l17_n168(x)
+ else
+ fun_l17_n881(x)
+ end
+end
+
+def fun_l16_n217(x)
+ if (x < 1)
+ fun_l17_n568(x)
+ else
+ fun_l17_n698(x)
+ end
+end
+
+def fun_l16_n218(x)
+ if (x < 1)
+ fun_l17_n727(x)
+ else
+ fun_l17_n388(x)
+ end
+end
+
+def fun_l16_n219(x)
+ if (x < 1)
+ fun_l17_n443(x)
+ else
+ fun_l17_n600(x)
+ end
+end
+
+def fun_l16_n220(x)
+ if (x < 1)
+ fun_l17_n901(x)
+ else
+ fun_l17_n875(x)
+ end
+end
+
+def fun_l16_n221(x)
+ if (x < 1)
+ fun_l17_n374(x)
+ else
+ fun_l17_n819(x)
+ end
+end
+
+def fun_l16_n222(x)
+ if (x < 1)
+ fun_l17_n563(x)
+ else
+ fun_l17_n341(x)
+ end
+end
+
+def fun_l16_n223(x)
+ if (x < 1)
+ fun_l17_n404(x)
+ else
+ fun_l17_n201(x)
+ end
+end
+
+def fun_l16_n224(x)
+ if (x < 1)
+ fun_l17_n932(x)
+ else
+ fun_l17_n803(x)
+ end
+end
+
+def fun_l16_n225(x)
+ if (x < 1)
+ fun_l17_n970(x)
+ else
+ fun_l17_n717(x)
+ end
+end
+
+def fun_l16_n226(x)
+ if (x < 1)
+ fun_l17_n599(x)
+ else
+ fun_l17_n692(x)
+ end
+end
+
+def fun_l16_n227(x)
+ if (x < 1)
+ fun_l17_n351(x)
+ else
+ fun_l17_n177(x)
+ end
+end
+
+def fun_l16_n228(x)
+ if (x < 1)
+ fun_l17_n891(x)
+ else
+ fun_l17_n79(x)
+ end
+end
+
+def fun_l16_n229(x)
+ if (x < 1)
+ fun_l17_n143(x)
+ else
+ fun_l17_n702(x)
+ end
+end
+
+def fun_l16_n230(x)
+ if (x < 1)
+ fun_l17_n591(x)
+ else
+ fun_l17_n317(x)
+ end
+end
+
+def fun_l16_n231(x)
+ if (x < 1)
+ fun_l17_n727(x)
+ else
+ fun_l17_n881(x)
+ end
+end
+
+def fun_l16_n232(x)
+ if (x < 1)
+ fun_l17_n390(x)
+ else
+ fun_l17_n580(x)
+ end
+end
+
+def fun_l16_n233(x)
+ if (x < 1)
+ fun_l17_n530(x)
+ else
+ fun_l17_n102(x)
+ end
+end
+
+def fun_l16_n234(x)
+ if (x < 1)
+ fun_l17_n891(x)
+ else
+ fun_l17_n783(x)
+ end
+end
+
+def fun_l16_n235(x)
+ if (x < 1)
+ fun_l17_n91(x)
+ else
+ fun_l17_n142(x)
+ end
+end
+
+def fun_l16_n236(x)
+ if (x < 1)
+ fun_l17_n55(x)
+ else
+ fun_l17_n897(x)
+ end
+end
+
+def fun_l16_n237(x)
+ if (x < 1)
+ fun_l17_n471(x)
+ else
+ fun_l17_n24(x)
+ end
+end
+
+def fun_l16_n238(x)
+ if (x < 1)
+ fun_l17_n812(x)
+ else
+ fun_l17_n833(x)
+ end
+end
+
+def fun_l16_n239(x)
+ if (x < 1)
+ fun_l17_n879(x)
+ else
+ fun_l17_n560(x)
+ end
+end
+
+def fun_l16_n240(x)
+ if (x < 1)
+ fun_l17_n882(x)
+ else
+ fun_l17_n473(x)
+ end
+end
+
+def fun_l16_n241(x)
+ if (x < 1)
+ fun_l17_n30(x)
+ else
+ fun_l17_n299(x)
+ end
+end
+
+def fun_l16_n242(x)
+ if (x < 1)
+ fun_l17_n855(x)
+ else
+ fun_l17_n751(x)
+ end
+end
+
+def fun_l16_n243(x)
+ if (x < 1)
+ fun_l17_n184(x)
+ else
+ fun_l17_n997(x)
+ end
+end
+
+def fun_l16_n244(x)
+ if (x < 1)
+ fun_l17_n151(x)
+ else
+ fun_l17_n495(x)
+ end
+end
+
+def fun_l16_n245(x)
+ if (x < 1)
+ fun_l17_n181(x)
+ else
+ fun_l17_n360(x)
+ end
+end
+
+def fun_l16_n246(x)
+ if (x < 1)
+ fun_l17_n208(x)
+ else
+ fun_l17_n767(x)
+ end
+end
+
+def fun_l16_n247(x)
+ if (x < 1)
+ fun_l17_n969(x)
+ else
+ fun_l17_n15(x)
+ end
+end
+
+def fun_l16_n248(x)
+ if (x < 1)
+ fun_l17_n529(x)
+ else
+ fun_l17_n879(x)
+ end
+end
+
+def fun_l16_n249(x)
+ if (x < 1)
+ fun_l17_n729(x)
+ else
+ fun_l17_n355(x)
+ end
+end
+
+def fun_l16_n250(x)
+ if (x < 1)
+ fun_l17_n239(x)
+ else
+ fun_l17_n414(x)
+ end
+end
+
+def fun_l16_n251(x)
+ if (x < 1)
+ fun_l17_n257(x)
+ else
+ fun_l17_n362(x)
+ end
+end
+
+def fun_l16_n252(x)
+ if (x < 1)
+ fun_l17_n832(x)
+ else
+ fun_l17_n924(x)
+ end
+end
+
+def fun_l16_n253(x)
+ if (x < 1)
+ fun_l17_n907(x)
+ else
+ fun_l17_n548(x)
+ end
+end
+
+def fun_l16_n254(x)
+ if (x < 1)
+ fun_l17_n391(x)
+ else
+ fun_l17_n316(x)
+ end
+end
+
+def fun_l16_n255(x)
+ if (x < 1)
+ fun_l17_n163(x)
+ else
+ fun_l17_n164(x)
+ end
+end
+
+def fun_l16_n256(x)
+ if (x < 1)
+ fun_l17_n86(x)
+ else
+ fun_l17_n473(x)
+ end
+end
+
+def fun_l16_n257(x)
+ if (x < 1)
+ fun_l17_n519(x)
+ else
+ fun_l17_n556(x)
+ end
+end
+
+def fun_l16_n258(x)
+ if (x < 1)
+ fun_l17_n819(x)
+ else
+ fun_l17_n41(x)
+ end
+end
+
+def fun_l16_n259(x)
+ if (x < 1)
+ fun_l17_n330(x)
+ else
+ fun_l17_n334(x)
+ end
+end
+
+def fun_l16_n260(x)
+ if (x < 1)
+ fun_l17_n441(x)
+ else
+ fun_l17_n529(x)
+ end
+end
+
+def fun_l16_n261(x)
+ if (x < 1)
+ fun_l17_n116(x)
+ else
+ fun_l17_n597(x)
+ end
+end
+
+def fun_l16_n262(x)
+ if (x < 1)
+ fun_l17_n537(x)
+ else
+ fun_l17_n594(x)
+ end
+end
+
+def fun_l16_n263(x)
+ if (x < 1)
+ fun_l17_n511(x)
+ else
+ fun_l17_n56(x)
+ end
+end
+
+def fun_l16_n264(x)
+ if (x < 1)
+ fun_l17_n264(x)
+ else
+ fun_l17_n641(x)
+ end
+end
+
+def fun_l16_n265(x)
+ if (x < 1)
+ fun_l17_n806(x)
+ else
+ fun_l17_n432(x)
+ end
+end
+
+def fun_l16_n266(x)
+ if (x < 1)
+ fun_l17_n428(x)
+ else
+ fun_l17_n463(x)
+ end
+end
+
+def fun_l16_n267(x)
+ if (x < 1)
+ fun_l17_n39(x)
+ else
+ fun_l17_n362(x)
+ end
+end
+
+def fun_l16_n268(x)
+ if (x < 1)
+ fun_l17_n502(x)
+ else
+ fun_l17_n87(x)
+ end
+end
+
+def fun_l16_n269(x)
+ if (x < 1)
+ fun_l17_n143(x)
+ else
+ fun_l17_n92(x)
+ end
+end
+
+def fun_l16_n270(x)
+ if (x < 1)
+ fun_l17_n675(x)
+ else
+ fun_l17_n629(x)
+ end
+end
+
+def fun_l16_n271(x)
+ if (x < 1)
+ fun_l17_n33(x)
+ else
+ fun_l17_n158(x)
+ end
+end
+
+def fun_l16_n272(x)
+ if (x < 1)
+ fun_l17_n480(x)
+ else
+ fun_l17_n204(x)
+ end
+end
+
+def fun_l16_n273(x)
+ if (x < 1)
+ fun_l17_n81(x)
+ else
+ fun_l17_n855(x)
+ end
+end
+
+def fun_l16_n274(x)
+ if (x < 1)
+ fun_l17_n608(x)
+ else
+ fun_l17_n969(x)
+ end
+end
+
+def fun_l16_n275(x)
+ if (x < 1)
+ fun_l17_n606(x)
+ else
+ fun_l17_n292(x)
+ end
+end
+
+def fun_l16_n276(x)
+ if (x < 1)
+ fun_l17_n494(x)
+ else
+ fun_l17_n689(x)
+ end
+end
+
+def fun_l16_n277(x)
+ if (x < 1)
+ fun_l17_n3(x)
+ else
+ fun_l17_n207(x)
+ end
+end
+
+def fun_l16_n278(x)
+ if (x < 1)
+ fun_l17_n85(x)
+ else
+ fun_l17_n59(x)
+ end
+end
+
+def fun_l16_n279(x)
+ if (x < 1)
+ fun_l17_n363(x)
+ else
+ fun_l17_n651(x)
+ end
+end
+
+def fun_l16_n280(x)
+ if (x < 1)
+ fun_l17_n199(x)
+ else
+ fun_l17_n77(x)
+ end
+end
+
+def fun_l16_n281(x)
+ if (x < 1)
+ fun_l17_n83(x)
+ else
+ fun_l17_n865(x)
+ end
+end
+
+def fun_l16_n282(x)
+ if (x < 1)
+ fun_l17_n120(x)
+ else
+ fun_l17_n466(x)
+ end
+end
+
+def fun_l16_n283(x)
+ if (x < 1)
+ fun_l17_n667(x)
+ else
+ fun_l17_n867(x)
+ end
+end
+
+def fun_l16_n284(x)
+ if (x < 1)
+ fun_l17_n248(x)
+ else
+ fun_l17_n480(x)
+ end
+end
+
+def fun_l16_n285(x)
+ if (x < 1)
+ fun_l17_n766(x)
+ else
+ fun_l17_n609(x)
+ end
+end
+
+def fun_l16_n286(x)
+ if (x < 1)
+ fun_l17_n95(x)
+ else
+ fun_l17_n341(x)
+ end
+end
+
+def fun_l16_n287(x)
+ if (x < 1)
+ fun_l17_n234(x)
+ else
+ fun_l17_n552(x)
+ end
+end
+
+def fun_l16_n288(x)
+ if (x < 1)
+ fun_l17_n955(x)
+ else
+ fun_l17_n434(x)
+ end
+end
+
+def fun_l16_n289(x)
+ if (x < 1)
+ fun_l17_n954(x)
+ else
+ fun_l17_n554(x)
+ end
+end
+
+def fun_l16_n290(x)
+ if (x < 1)
+ fun_l17_n981(x)
+ else
+ fun_l17_n374(x)
+ end
+end
+
+def fun_l16_n291(x)
+ if (x < 1)
+ fun_l17_n153(x)
+ else
+ fun_l17_n849(x)
+ end
+end
+
+def fun_l16_n292(x)
+ if (x < 1)
+ fun_l17_n89(x)
+ else
+ fun_l17_n491(x)
+ end
+end
+
+def fun_l16_n293(x)
+ if (x < 1)
+ fun_l17_n908(x)
+ else
+ fun_l17_n75(x)
+ end
+end
+
+def fun_l16_n294(x)
+ if (x < 1)
+ fun_l17_n772(x)
+ else
+ fun_l17_n474(x)
+ end
+end
+
+def fun_l16_n295(x)
+ if (x < 1)
+ fun_l17_n577(x)
+ else
+ fun_l17_n470(x)
+ end
+end
+
+def fun_l16_n296(x)
+ if (x < 1)
+ fun_l17_n699(x)
+ else
+ fun_l17_n172(x)
+ end
+end
+
+def fun_l16_n297(x)
+ if (x < 1)
+ fun_l17_n408(x)
+ else
+ fun_l17_n314(x)
+ end
+end
+
+def fun_l16_n298(x)
+ if (x < 1)
+ fun_l17_n521(x)
+ else
+ fun_l17_n940(x)
+ end
+end
+
+def fun_l16_n299(x)
+ if (x < 1)
+ fun_l17_n804(x)
+ else
+ fun_l17_n503(x)
+ end
+end
+
+def fun_l16_n300(x)
+ if (x < 1)
+ fun_l17_n712(x)
+ else
+ fun_l17_n227(x)
+ end
+end
+
+def fun_l16_n301(x)
+ if (x < 1)
+ fun_l17_n700(x)
+ else
+ fun_l17_n102(x)
+ end
+end
+
+def fun_l16_n302(x)
+ if (x < 1)
+ fun_l17_n290(x)
+ else
+ fun_l17_n212(x)
+ end
+end
+
+def fun_l16_n303(x)
+ if (x < 1)
+ fun_l17_n525(x)
+ else
+ fun_l17_n273(x)
+ end
+end
+
+def fun_l16_n304(x)
+ if (x < 1)
+ fun_l17_n356(x)
+ else
+ fun_l17_n359(x)
+ end
+end
+
+def fun_l16_n305(x)
+ if (x < 1)
+ fun_l17_n84(x)
+ else
+ fun_l17_n207(x)
+ end
+end
+
+def fun_l16_n306(x)
+ if (x < 1)
+ fun_l17_n566(x)
+ else
+ fun_l17_n945(x)
+ end
+end
+
+def fun_l16_n307(x)
+ if (x < 1)
+ fun_l17_n692(x)
+ else
+ fun_l17_n326(x)
+ end
+end
+
+def fun_l16_n308(x)
+ if (x < 1)
+ fun_l17_n727(x)
+ else
+ fun_l17_n205(x)
+ end
+end
+
+def fun_l16_n309(x)
+ if (x < 1)
+ fun_l17_n568(x)
+ else
+ fun_l17_n386(x)
+ end
+end
+
+def fun_l16_n310(x)
+ if (x < 1)
+ fun_l17_n244(x)
+ else
+ fun_l17_n472(x)
+ end
+end
+
+def fun_l16_n311(x)
+ if (x < 1)
+ fun_l17_n956(x)
+ else
+ fun_l17_n546(x)
+ end
+end
+
+def fun_l16_n312(x)
+ if (x < 1)
+ fun_l17_n807(x)
+ else
+ fun_l17_n924(x)
+ end
+end
+
+def fun_l16_n313(x)
+ if (x < 1)
+ fun_l17_n931(x)
+ else
+ fun_l17_n962(x)
+ end
+end
+
+def fun_l16_n314(x)
+ if (x < 1)
+ fun_l17_n64(x)
+ else
+ fun_l17_n178(x)
+ end
+end
+
+def fun_l16_n315(x)
+ if (x < 1)
+ fun_l17_n460(x)
+ else
+ fun_l17_n438(x)
+ end
+end
+
+def fun_l16_n316(x)
+ if (x < 1)
+ fun_l17_n185(x)
+ else
+ fun_l17_n25(x)
+ end
+end
+
+def fun_l16_n317(x)
+ if (x < 1)
+ fun_l17_n732(x)
+ else
+ fun_l17_n460(x)
+ end
+end
+
+def fun_l16_n318(x)
+ if (x < 1)
+ fun_l17_n5(x)
+ else
+ fun_l17_n947(x)
+ end
+end
+
+def fun_l16_n319(x)
+ if (x < 1)
+ fun_l17_n682(x)
+ else
+ fun_l17_n644(x)
+ end
+end
+
+def fun_l16_n320(x)
+ if (x < 1)
+ fun_l17_n151(x)
+ else
+ fun_l17_n578(x)
+ end
+end
+
+def fun_l16_n321(x)
+ if (x < 1)
+ fun_l17_n219(x)
+ else
+ fun_l17_n4(x)
+ end
+end
+
+def fun_l16_n322(x)
+ if (x < 1)
+ fun_l17_n214(x)
+ else
+ fun_l17_n594(x)
+ end
+end
+
+def fun_l16_n323(x)
+ if (x < 1)
+ fun_l17_n970(x)
+ else
+ fun_l17_n275(x)
+ end
+end
+
+def fun_l16_n324(x)
+ if (x < 1)
+ fun_l17_n442(x)
+ else
+ fun_l17_n377(x)
+ end
+end
+
+def fun_l16_n325(x)
+ if (x < 1)
+ fun_l17_n783(x)
+ else
+ fun_l17_n731(x)
+ end
+end
+
+def fun_l16_n326(x)
+ if (x < 1)
+ fun_l17_n43(x)
+ else
+ fun_l17_n884(x)
+ end
+end
+
+def fun_l16_n327(x)
+ if (x < 1)
+ fun_l17_n857(x)
+ else
+ fun_l17_n593(x)
+ end
+end
+
+def fun_l16_n328(x)
+ if (x < 1)
+ fun_l17_n942(x)
+ else
+ fun_l17_n772(x)
+ end
+end
+
+def fun_l16_n329(x)
+ if (x < 1)
+ fun_l17_n309(x)
+ else
+ fun_l17_n508(x)
+ end
+end
+
+def fun_l16_n330(x)
+ if (x < 1)
+ fun_l17_n30(x)
+ else
+ fun_l17_n165(x)
+ end
+end
+
+def fun_l16_n331(x)
+ if (x < 1)
+ fun_l17_n981(x)
+ else
+ fun_l17_n355(x)
+ end
+end
+
+def fun_l16_n332(x)
+ if (x < 1)
+ fun_l17_n159(x)
+ else
+ fun_l17_n228(x)
+ end
+end
+
+def fun_l16_n333(x)
+ if (x < 1)
+ fun_l17_n499(x)
+ else
+ fun_l17_n565(x)
+ end
+end
+
+def fun_l16_n334(x)
+ if (x < 1)
+ fun_l17_n371(x)
+ else
+ fun_l17_n856(x)
+ end
+end
+
+def fun_l16_n335(x)
+ if (x < 1)
+ fun_l17_n717(x)
+ else
+ fun_l17_n229(x)
+ end
+end
+
+def fun_l16_n336(x)
+ if (x < 1)
+ fun_l17_n678(x)
+ else
+ fun_l17_n236(x)
+ end
+end
+
+def fun_l16_n337(x)
+ if (x < 1)
+ fun_l17_n472(x)
+ else
+ fun_l17_n566(x)
+ end
+end
+
+def fun_l16_n338(x)
+ if (x < 1)
+ fun_l17_n74(x)
+ else
+ fun_l17_n247(x)
+ end
+end
+
+def fun_l16_n339(x)
+ if (x < 1)
+ fun_l17_n379(x)
+ else
+ fun_l17_n443(x)
+ end
+end
+
+def fun_l16_n340(x)
+ if (x < 1)
+ fun_l17_n233(x)
+ else
+ fun_l17_n79(x)
+ end
+end
+
+def fun_l16_n341(x)
+ if (x < 1)
+ fun_l17_n136(x)
+ else
+ fun_l17_n900(x)
+ end
+end
+
+def fun_l16_n342(x)
+ if (x < 1)
+ fun_l17_n785(x)
+ else
+ fun_l17_n63(x)
+ end
+end
+
+def fun_l16_n343(x)
+ if (x < 1)
+ fun_l17_n429(x)
+ else
+ fun_l17_n111(x)
+ end
+end
+
+def fun_l16_n344(x)
+ if (x < 1)
+ fun_l17_n226(x)
+ else
+ fun_l17_n137(x)
+ end
+end
+
+def fun_l16_n345(x)
+ if (x < 1)
+ fun_l17_n428(x)
+ else
+ fun_l17_n674(x)
+ end
+end
+
+def fun_l16_n346(x)
+ if (x < 1)
+ fun_l17_n940(x)
+ else
+ fun_l17_n987(x)
+ end
+end
+
+def fun_l16_n347(x)
+ if (x < 1)
+ fun_l17_n579(x)
+ else
+ fun_l17_n220(x)
+ end
+end
+
+def fun_l16_n348(x)
+ if (x < 1)
+ fun_l17_n502(x)
+ else
+ fun_l17_n530(x)
+ end
+end
+
+def fun_l16_n349(x)
+ if (x < 1)
+ fun_l17_n334(x)
+ else
+ fun_l17_n955(x)
+ end
+end
+
+def fun_l16_n350(x)
+ if (x < 1)
+ fun_l17_n680(x)
+ else
+ fun_l17_n41(x)
+ end
+end
+
+def fun_l16_n351(x)
+ if (x < 1)
+ fun_l17_n821(x)
+ else
+ fun_l17_n750(x)
+ end
+end
+
+def fun_l16_n352(x)
+ if (x < 1)
+ fun_l17_n212(x)
+ else
+ fun_l17_n537(x)
+ end
+end
+
+def fun_l16_n353(x)
+ if (x < 1)
+ fun_l17_n555(x)
+ else
+ fun_l17_n834(x)
+ end
+end
+
+def fun_l16_n354(x)
+ if (x < 1)
+ fun_l17_n532(x)
+ else
+ fun_l17_n940(x)
+ end
+end
+
+def fun_l16_n355(x)
+ if (x < 1)
+ fun_l17_n771(x)
+ else
+ fun_l17_n915(x)
+ end
+end
+
+def fun_l16_n356(x)
+ if (x < 1)
+ fun_l17_n844(x)
+ else
+ fun_l17_n235(x)
+ end
+end
+
+def fun_l16_n357(x)
+ if (x < 1)
+ fun_l17_n604(x)
+ else
+ fun_l17_n241(x)
+ end
+end
+
+def fun_l16_n358(x)
+ if (x < 1)
+ fun_l17_n156(x)
+ else
+ fun_l17_n832(x)
+ end
+end
+
+def fun_l16_n359(x)
+ if (x < 1)
+ fun_l17_n335(x)
+ else
+ fun_l17_n115(x)
+ end
+end
+
+def fun_l16_n360(x)
+ if (x < 1)
+ fun_l17_n563(x)
+ else
+ fun_l17_n779(x)
+ end
+end
+
+def fun_l16_n361(x)
+ if (x < 1)
+ fun_l17_n280(x)
+ else
+ fun_l17_n946(x)
+ end
+end
+
+def fun_l16_n362(x)
+ if (x < 1)
+ fun_l17_n497(x)
+ else
+ fun_l17_n390(x)
+ end
+end
+
+def fun_l16_n363(x)
+ if (x < 1)
+ fun_l17_n59(x)
+ else
+ fun_l17_n178(x)
+ end
+end
+
+def fun_l16_n364(x)
+ if (x < 1)
+ fun_l17_n509(x)
+ else
+ fun_l17_n963(x)
+ end
+end
+
+def fun_l16_n365(x)
+ if (x < 1)
+ fun_l17_n670(x)
+ else
+ fun_l17_n455(x)
+ end
+end
+
+def fun_l16_n366(x)
+ if (x < 1)
+ fun_l17_n852(x)
+ else
+ fun_l17_n590(x)
+ end
+end
+
+def fun_l16_n367(x)
+ if (x < 1)
+ fun_l17_n714(x)
+ else
+ fun_l17_n98(x)
+ end
+end
+
+def fun_l16_n368(x)
+ if (x < 1)
+ fun_l17_n456(x)
+ else
+ fun_l17_n754(x)
+ end
+end
+
+def fun_l16_n369(x)
+ if (x < 1)
+ fun_l17_n809(x)
+ else
+ fun_l17_n38(x)
+ end
+end
+
+def fun_l16_n370(x)
+ if (x < 1)
+ fun_l17_n127(x)
+ else
+ fun_l17_n395(x)
+ end
+end
+
+def fun_l16_n371(x)
+ if (x < 1)
+ fun_l17_n700(x)
+ else
+ fun_l17_n175(x)
+ end
+end
+
+def fun_l16_n372(x)
+ if (x < 1)
+ fun_l17_n705(x)
+ else
+ fun_l17_n598(x)
+ end
+end
+
+def fun_l16_n373(x)
+ if (x < 1)
+ fun_l17_n808(x)
+ else
+ fun_l17_n253(x)
+ end
+end
+
+def fun_l16_n374(x)
+ if (x < 1)
+ fun_l17_n195(x)
+ else
+ fun_l17_n47(x)
+ end
+end
+
+def fun_l16_n375(x)
+ if (x < 1)
+ fun_l17_n124(x)
+ else
+ fun_l17_n438(x)
+ end
+end
+
+def fun_l16_n376(x)
+ if (x < 1)
+ fun_l17_n261(x)
+ else
+ fun_l17_n317(x)
+ end
+end
+
+def fun_l16_n377(x)
+ if (x < 1)
+ fun_l17_n702(x)
+ else
+ fun_l17_n67(x)
+ end
+end
+
+def fun_l16_n378(x)
+ if (x < 1)
+ fun_l17_n194(x)
+ else
+ fun_l17_n990(x)
+ end
+end
+
+def fun_l16_n379(x)
+ if (x < 1)
+ fun_l17_n574(x)
+ else
+ fun_l17_n379(x)
+ end
+end
+
+def fun_l16_n380(x)
+ if (x < 1)
+ fun_l17_n182(x)
+ else
+ fun_l17_n902(x)
+ end
+end
+
+def fun_l16_n381(x)
+ if (x < 1)
+ fun_l17_n963(x)
+ else
+ fun_l17_n627(x)
+ end
+end
+
+def fun_l16_n382(x)
+ if (x < 1)
+ fun_l17_n200(x)
+ else
+ fun_l17_n889(x)
+ end
+end
+
+def fun_l16_n383(x)
+ if (x < 1)
+ fun_l17_n14(x)
+ else
+ fun_l17_n422(x)
+ end
+end
+
+def fun_l16_n384(x)
+ if (x < 1)
+ fun_l17_n543(x)
+ else
+ fun_l17_n940(x)
+ end
+end
+
+def fun_l16_n385(x)
+ if (x < 1)
+ fun_l17_n762(x)
+ else
+ fun_l17_n493(x)
+ end
+end
+
+def fun_l16_n386(x)
+ if (x < 1)
+ fun_l17_n824(x)
+ else
+ fun_l17_n963(x)
+ end
+end
+
+def fun_l16_n387(x)
+ if (x < 1)
+ fun_l17_n298(x)
+ else
+ fun_l17_n831(x)
+ end
+end
+
+def fun_l16_n388(x)
+ if (x < 1)
+ fun_l17_n284(x)
+ else
+ fun_l17_n784(x)
+ end
+end
+
+def fun_l16_n389(x)
+ if (x < 1)
+ fun_l17_n461(x)
+ else
+ fun_l17_n684(x)
+ end
+end
+
+def fun_l16_n390(x)
+ if (x < 1)
+ fun_l17_n829(x)
+ else
+ fun_l17_n788(x)
+ end
+end
+
+def fun_l16_n391(x)
+ if (x < 1)
+ fun_l17_n263(x)
+ else
+ fun_l17_n21(x)
+ end
+end
+
+def fun_l16_n392(x)
+ if (x < 1)
+ fun_l17_n994(x)
+ else
+ fun_l17_n646(x)
+ end
+end
+
+def fun_l16_n393(x)
+ if (x < 1)
+ fun_l17_n438(x)
+ else
+ fun_l17_n84(x)
+ end
+end
+
+def fun_l16_n394(x)
+ if (x < 1)
+ fun_l17_n660(x)
+ else
+ fun_l17_n269(x)
+ end
+end
+
+def fun_l16_n395(x)
+ if (x < 1)
+ fun_l17_n939(x)
+ else
+ fun_l17_n676(x)
+ end
+end
+
+def fun_l16_n396(x)
+ if (x < 1)
+ fun_l17_n608(x)
+ else
+ fun_l17_n483(x)
+ end
+end
+
+def fun_l16_n397(x)
+ if (x < 1)
+ fun_l17_n504(x)
+ else
+ fun_l17_n499(x)
+ end
+end
+
+def fun_l16_n398(x)
+ if (x < 1)
+ fun_l17_n793(x)
+ else
+ fun_l17_n489(x)
+ end
+end
+
+def fun_l16_n399(x)
+ if (x < 1)
+ fun_l17_n28(x)
+ else
+ fun_l17_n158(x)
+ end
+end
+
+def fun_l16_n400(x)
+ if (x < 1)
+ fun_l17_n30(x)
+ else
+ fun_l17_n21(x)
+ end
+end
+
+def fun_l16_n401(x)
+ if (x < 1)
+ fun_l17_n532(x)
+ else
+ fun_l17_n730(x)
+ end
+end
+
+def fun_l16_n402(x)
+ if (x < 1)
+ fun_l17_n593(x)
+ else
+ fun_l17_n4(x)
+ end
+end
+
+def fun_l16_n403(x)
+ if (x < 1)
+ fun_l17_n881(x)
+ else
+ fun_l17_n956(x)
+ end
+end
+
+def fun_l16_n404(x)
+ if (x < 1)
+ fun_l17_n676(x)
+ else
+ fun_l17_n625(x)
+ end
+end
+
+def fun_l16_n405(x)
+ if (x < 1)
+ fun_l17_n192(x)
+ else
+ fun_l17_n301(x)
+ end
+end
+
+def fun_l16_n406(x)
+ if (x < 1)
+ fun_l17_n170(x)
+ else
+ fun_l17_n970(x)
+ end
+end
+
+def fun_l16_n407(x)
+ if (x < 1)
+ fun_l17_n268(x)
+ else
+ fun_l17_n765(x)
+ end
+end
+
+def fun_l16_n408(x)
+ if (x < 1)
+ fun_l17_n310(x)
+ else
+ fun_l17_n578(x)
+ end
+end
+
+def fun_l16_n409(x)
+ if (x < 1)
+ fun_l17_n301(x)
+ else
+ fun_l17_n870(x)
+ end
+end
+
+def fun_l16_n410(x)
+ if (x < 1)
+ fun_l17_n390(x)
+ else
+ fun_l17_n769(x)
+ end
+end
+
+def fun_l16_n411(x)
+ if (x < 1)
+ fun_l17_n973(x)
+ else
+ fun_l17_n545(x)
+ end
+end
+
+def fun_l16_n412(x)
+ if (x < 1)
+ fun_l17_n108(x)
+ else
+ fun_l17_n731(x)
+ end
+end
+
+def fun_l16_n413(x)
+ if (x < 1)
+ fun_l17_n842(x)
+ else
+ fun_l17_n106(x)
+ end
+end
+
+def fun_l16_n414(x)
+ if (x < 1)
+ fun_l17_n10(x)
+ else
+ fun_l17_n421(x)
+ end
+end
+
+def fun_l16_n415(x)
+ if (x < 1)
+ fun_l17_n765(x)
+ else
+ fun_l17_n584(x)
+ end
+end
+
+def fun_l16_n416(x)
+ if (x < 1)
+ fun_l17_n480(x)
+ else
+ fun_l17_n494(x)
+ end
+end
+
+def fun_l16_n417(x)
+ if (x < 1)
+ fun_l17_n977(x)
+ else
+ fun_l17_n66(x)
+ end
+end
+
+def fun_l16_n418(x)
+ if (x < 1)
+ fun_l17_n291(x)
+ else
+ fun_l17_n161(x)
+ end
+end
+
+def fun_l16_n419(x)
+ if (x < 1)
+ fun_l17_n400(x)
+ else
+ fun_l17_n99(x)
+ end
+end
+
+def fun_l16_n420(x)
+ if (x < 1)
+ fun_l17_n621(x)
+ else
+ fun_l17_n778(x)
+ end
+end
+
+def fun_l16_n421(x)
+ if (x < 1)
+ fun_l17_n286(x)
+ else
+ fun_l17_n784(x)
+ end
+end
+
+def fun_l16_n422(x)
+ if (x < 1)
+ fun_l17_n575(x)
+ else
+ fun_l17_n606(x)
+ end
+end
+
+def fun_l16_n423(x)
+ if (x < 1)
+ fun_l17_n459(x)
+ else
+ fun_l17_n198(x)
+ end
+end
+
+def fun_l16_n424(x)
+ if (x < 1)
+ fun_l17_n190(x)
+ else
+ fun_l17_n597(x)
+ end
+end
+
+def fun_l16_n425(x)
+ if (x < 1)
+ fun_l17_n365(x)
+ else
+ fun_l17_n73(x)
+ end
+end
+
+def fun_l16_n426(x)
+ if (x < 1)
+ fun_l17_n769(x)
+ else
+ fun_l17_n658(x)
+ end
+end
+
+def fun_l16_n427(x)
+ if (x < 1)
+ fun_l17_n980(x)
+ else
+ fun_l17_n594(x)
+ end
+end
+
+def fun_l16_n428(x)
+ if (x < 1)
+ fun_l17_n210(x)
+ else
+ fun_l17_n33(x)
+ end
+end
+
+def fun_l16_n429(x)
+ if (x < 1)
+ fun_l17_n585(x)
+ else
+ fun_l17_n997(x)
+ end
+end
+
+def fun_l16_n430(x)
+ if (x < 1)
+ fun_l17_n660(x)
+ else
+ fun_l17_n883(x)
+ end
+end
+
+def fun_l16_n431(x)
+ if (x < 1)
+ fun_l17_n613(x)
+ else
+ fun_l17_n7(x)
+ end
+end
+
+def fun_l16_n432(x)
+ if (x < 1)
+ fun_l17_n764(x)
+ else
+ fun_l17_n150(x)
+ end
+end
+
+def fun_l16_n433(x)
+ if (x < 1)
+ fun_l17_n582(x)
+ else
+ fun_l17_n197(x)
+ end
+end
+
+def fun_l16_n434(x)
+ if (x < 1)
+ fun_l17_n553(x)
+ else
+ fun_l17_n107(x)
+ end
+end
+
+def fun_l16_n435(x)
+ if (x < 1)
+ fun_l17_n975(x)
+ else
+ fun_l17_n865(x)
+ end
+end
+
+def fun_l16_n436(x)
+ if (x < 1)
+ fun_l17_n622(x)
+ else
+ fun_l17_n351(x)
+ end
+end
+
+def fun_l16_n437(x)
+ if (x < 1)
+ fun_l17_n681(x)
+ else
+ fun_l17_n472(x)
+ end
+end
+
+def fun_l16_n438(x)
+ if (x < 1)
+ fun_l17_n329(x)
+ else
+ fun_l17_n54(x)
+ end
+end
+
+def fun_l16_n439(x)
+ if (x < 1)
+ fun_l17_n340(x)
+ else
+ fun_l17_n567(x)
+ end
+end
+
+def fun_l16_n440(x)
+ if (x < 1)
+ fun_l17_n563(x)
+ else
+ fun_l17_n134(x)
+ end
+end
+
+def fun_l16_n441(x)
+ if (x < 1)
+ fun_l17_n194(x)
+ else
+ fun_l17_n986(x)
+ end
+end
+
+def fun_l16_n442(x)
+ if (x < 1)
+ fun_l17_n926(x)
+ else
+ fun_l17_n35(x)
+ end
+end
+
+def fun_l16_n443(x)
+ if (x < 1)
+ fun_l17_n771(x)
+ else
+ fun_l17_n383(x)
+ end
+end
+
+def fun_l16_n444(x)
+ if (x < 1)
+ fun_l17_n682(x)
+ else
+ fun_l17_n1(x)
+ end
+end
+
+def fun_l16_n445(x)
+ if (x < 1)
+ fun_l17_n633(x)
+ else
+ fun_l17_n757(x)
+ end
+end
+
+def fun_l16_n446(x)
+ if (x < 1)
+ fun_l17_n95(x)
+ else
+ fun_l17_n256(x)
+ end
+end
+
+def fun_l16_n447(x)
+ if (x < 1)
+ fun_l17_n183(x)
+ else
+ fun_l17_n214(x)
+ end
+end
+
+def fun_l16_n448(x)
+ if (x < 1)
+ fun_l17_n140(x)
+ else
+ fun_l17_n371(x)
+ end
+end
+
+def fun_l16_n449(x)
+ if (x < 1)
+ fun_l17_n188(x)
+ else
+ fun_l17_n898(x)
+ end
+end
+
+def fun_l16_n450(x)
+ if (x < 1)
+ fun_l17_n710(x)
+ else
+ fun_l17_n512(x)
+ end
+end
+
+def fun_l16_n451(x)
+ if (x < 1)
+ fun_l17_n796(x)
+ else
+ fun_l17_n56(x)
+ end
+end
+
+def fun_l16_n452(x)
+ if (x < 1)
+ fun_l17_n124(x)
+ else
+ fun_l17_n304(x)
+ end
+end
+
+def fun_l16_n453(x)
+ if (x < 1)
+ fun_l17_n150(x)
+ else
+ fun_l17_n503(x)
+ end
+end
+
+def fun_l16_n454(x)
+ if (x < 1)
+ fun_l17_n369(x)
+ else
+ fun_l17_n623(x)
+ end
+end
+
+def fun_l16_n455(x)
+ if (x < 1)
+ fun_l17_n514(x)
+ else
+ fun_l17_n672(x)
+ end
+end
+
+def fun_l16_n456(x)
+ if (x < 1)
+ fun_l17_n80(x)
+ else
+ fun_l17_n332(x)
+ end
+end
+
+def fun_l16_n457(x)
+ if (x < 1)
+ fun_l17_n80(x)
+ else
+ fun_l17_n32(x)
+ end
+end
+
+def fun_l16_n458(x)
+ if (x < 1)
+ fun_l17_n310(x)
+ else
+ fun_l17_n90(x)
+ end
+end
+
+def fun_l16_n459(x)
+ if (x < 1)
+ fun_l17_n730(x)
+ else
+ fun_l17_n170(x)
+ end
+end
+
+def fun_l16_n460(x)
+ if (x < 1)
+ fun_l17_n908(x)
+ else
+ fun_l17_n865(x)
+ end
+end
+
+def fun_l16_n461(x)
+ if (x < 1)
+ fun_l17_n399(x)
+ else
+ fun_l17_n536(x)
+ end
+end
+
+def fun_l16_n462(x)
+ if (x < 1)
+ fun_l17_n123(x)
+ else
+ fun_l17_n216(x)
+ end
+end
+
+def fun_l16_n463(x)
+ if (x < 1)
+ fun_l17_n577(x)
+ else
+ fun_l17_n757(x)
+ end
+end
+
+def fun_l16_n464(x)
+ if (x < 1)
+ fun_l17_n750(x)
+ else
+ fun_l17_n916(x)
+ end
+end
+
+def fun_l16_n465(x)
+ if (x < 1)
+ fun_l17_n621(x)
+ else
+ fun_l17_n386(x)
+ end
+end
+
+def fun_l16_n466(x)
+ if (x < 1)
+ fun_l17_n904(x)
+ else
+ fun_l17_n732(x)
+ end
+end
+
+def fun_l16_n467(x)
+ if (x < 1)
+ fun_l17_n625(x)
+ else
+ fun_l17_n1(x)
+ end
+end
+
+def fun_l16_n468(x)
+ if (x < 1)
+ fun_l17_n762(x)
+ else
+ fun_l17_n373(x)
+ end
+end
+
+def fun_l16_n469(x)
+ if (x < 1)
+ fun_l17_n816(x)
+ else
+ fun_l17_n490(x)
+ end
+end
+
+def fun_l16_n470(x)
+ if (x < 1)
+ fun_l17_n908(x)
+ else
+ fun_l17_n701(x)
+ end
+end
+
+def fun_l16_n471(x)
+ if (x < 1)
+ fun_l17_n690(x)
+ else
+ fun_l17_n374(x)
+ end
+end
+
+def fun_l16_n472(x)
+ if (x < 1)
+ fun_l17_n753(x)
+ else
+ fun_l17_n625(x)
+ end
+end
+
+def fun_l16_n473(x)
+ if (x < 1)
+ fun_l17_n602(x)
+ else
+ fun_l17_n947(x)
+ end
+end
+
+def fun_l16_n474(x)
+ if (x < 1)
+ fun_l17_n565(x)
+ else
+ fun_l17_n320(x)
+ end
+end
+
+def fun_l16_n475(x)
+ if (x < 1)
+ fun_l17_n990(x)
+ else
+ fun_l17_n431(x)
+ end
+end
+
+def fun_l16_n476(x)
+ if (x < 1)
+ fun_l17_n135(x)
+ else
+ fun_l17_n506(x)
+ end
+end
+
+def fun_l16_n477(x)
+ if (x < 1)
+ fun_l17_n57(x)
+ else
+ fun_l17_n944(x)
+ end
+end
+
+def fun_l16_n478(x)
+ if (x < 1)
+ fun_l17_n877(x)
+ else
+ fun_l17_n28(x)
+ end
+end
+
+def fun_l16_n479(x)
+ if (x < 1)
+ fun_l17_n132(x)
+ else
+ fun_l17_n280(x)
+ end
+end
+
+def fun_l16_n480(x)
+ if (x < 1)
+ fun_l17_n514(x)
+ else
+ fun_l17_n51(x)
+ end
+end
+
+def fun_l16_n481(x)
+ if (x < 1)
+ fun_l17_n55(x)
+ else
+ fun_l17_n366(x)
+ end
+end
+
+def fun_l16_n482(x)
+ if (x < 1)
+ fun_l17_n59(x)
+ else
+ fun_l17_n810(x)
+ end
+end
+
+def fun_l16_n483(x)
+ if (x < 1)
+ fun_l17_n965(x)
+ else
+ fun_l17_n55(x)
+ end
+end
+
+def fun_l16_n484(x)
+ if (x < 1)
+ fun_l17_n813(x)
+ else
+ fun_l17_n408(x)
+ end
+end
+
+def fun_l16_n485(x)
+ if (x < 1)
+ fun_l17_n190(x)
+ else
+ fun_l17_n126(x)
+ end
+end
+
+def fun_l16_n486(x)
+ if (x < 1)
+ fun_l17_n479(x)
+ else
+ fun_l17_n964(x)
+ end
+end
+
+def fun_l16_n487(x)
+ if (x < 1)
+ fun_l17_n267(x)
+ else
+ fun_l17_n867(x)
+ end
+end
+
+def fun_l16_n488(x)
+ if (x < 1)
+ fun_l17_n787(x)
+ else
+ fun_l17_n34(x)
+ end
+end
+
+def fun_l16_n489(x)
+ if (x < 1)
+ fun_l17_n223(x)
+ else
+ fun_l17_n568(x)
+ end
+end
+
+def fun_l16_n490(x)
+ if (x < 1)
+ fun_l17_n773(x)
+ else
+ fun_l17_n11(x)
+ end
+end
+
+def fun_l16_n491(x)
+ if (x < 1)
+ fun_l17_n906(x)
+ else
+ fun_l17_n146(x)
+ end
+end
+
+def fun_l16_n492(x)
+ if (x < 1)
+ fun_l17_n221(x)
+ else
+ fun_l17_n136(x)
+ end
+end
+
+def fun_l16_n493(x)
+ if (x < 1)
+ fun_l17_n40(x)
+ else
+ fun_l17_n599(x)
+ end
+end
+
+def fun_l16_n494(x)
+ if (x < 1)
+ fun_l17_n494(x)
+ else
+ fun_l17_n591(x)
+ end
+end
+
+def fun_l16_n495(x)
+ if (x < 1)
+ fun_l17_n237(x)
+ else
+ fun_l17_n149(x)
+ end
+end
+
+def fun_l16_n496(x)
+ if (x < 1)
+ fun_l17_n501(x)
+ else
+ fun_l17_n681(x)
+ end
+end
+
+def fun_l16_n497(x)
+ if (x < 1)
+ fun_l17_n141(x)
+ else
+ fun_l17_n226(x)
+ end
+end
+
+def fun_l16_n498(x)
+ if (x < 1)
+ fun_l17_n868(x)
+ else
+ fun_l17_n837(x)
+ end
+end
+
+def fun_l16_n499(x)
+ if (x < 1)
+ fun_l17_n921(x)
+ else
+ fun_l17_n806(x)
+ end
+end
+
+def fun_l16_n500(x)
+ if (x < 1)
+ fun_l17_n117(x)
+ else
+ fun_l17_n835(x)
+ end
+end
+
+def fun_l16_n501(x)
+ if (x < 1)
+ fun_l17_n872(x)
+ else
+ fun_l17_n567(x)
+ end
+end
+
+def fun_l16_n502(x)
+ if (x < 1)
+ fun_l17_n787(x)
+ else
+ fun_l17_n785(x)
+ end
+end
+
+def fun_l16_n503(x)
+ if (x < 1)
+ fun_l17_n827(x)
+ else
+ fun_l17_n388(x)
+ end
+end
+
+def fun_l16_n504(x)
+ if (x < 1)
+ fun_l17_n328(x)
+ else
+ fun_l17_n849(x)
+ end
+end
+
+def fun_l16_n505(x)
+ if (x < 1)
+ fun_l17_n348(x)
+ else
+ fun_l17_n580(x)
+ end
+end
+
+def fun_l16_n506(x)
+ if (x < 1)
+ fun_l17_n408(x)
+ else
+ fun_l17_n236(x)
+ end
+end
+
+def fun_l16_n507(x)
+ if (x < 1)
+ fun_l17_n959(x)
+ else
+ fun_l17_n739(x)
+ end
+end
+
+def fun_l16_n508(x)
+ if (x < 1)
+ fun_l17_n496(x)
+ else
+ fun_l17_n774(x)
+ end
+end
+
+def fun_l16_n509(x)
+ if (x < 1)
+ fun_l17_n639(x)
+ else
+ fun_l17_n147(x)
+ end
+end
+
+def fun_l16_n510(x)
+ if (x < 1)
+ fun_l17_n910(x)
+ else
+ fun_l17_n697(x)
+ end
+end
+
+def fun_l16_n511(x)
+ if (x < 1)
+ fun_l17_n239(x)
+ else
+ fun_l17_n691(x)
+ end
+end
+
+def fun_l16_n512(x)
+ if (x < 1)
+ fun_l17_n923(x)
+ else
+ fun_l17_n735(x)
+ end
+end
+
+def fun_l16_n513(x)
+ if (x < 1)
+ fun_l17_n911(x)
+ else
+ fun_l17_n372(x)
+ end
+end
+
+def fun_l16_n514(x)
+ if (x < 1)
+ fun_l17_n706(x)
+ else
+ fun_l17_n27(x)
+ end
+end
+
+def fun_l16_n515(x)
+ if (x < 1)
+ fun_l17_n788(x)
+ else
+ fun_l17_n670(x)
+ end
+end
+
+def fun_l16_n516(x)
+ if (x < 1)
+ fun_l17_n507(x)
+ else
+ fun_l17_n330(x)
+ end
+end
+
+def fun_l16_n517(x)
+ if (x < 1)
+ fun_l17_n398(x)
+ else
+ fun_l17_n997(x)
+ end
+end
+
+def fun_l16_n518(x)
+ if (x < 1)
+ fun_l17_n675(x)
+ else
+ fun_l17_n383(x)
+ end
+end
+
+def fun_l16_n519(x)
+ if (x < 1)
+ fun_l17_n193(x)
+ else
+ fun_l17_n611(x)
+ end
+end
+
+def fun_l16_n520(x)
+ if (x < 1)
+ fun_l17_n884(x)
+ else
+ fun_l17_n200(x)
+ end
+end
+
+def fun_l16_n521(x)
+ if (x < 1)
+ fun_l17_n574(x)
+ else
+ fun_l17_n192(x)
+ end
+end
+
+def fun_l16_n522(x)
+ if (x < 1)
+ fun_l17_n883(x)
+ else
+ fun_l17_n399(x)
+ end
+end
+
+def fun_l16_n523(x)
+ if (x < 1)
+ fun_l17_n516(x)
+ else
+ fun_l17_n592(x)
+ end
+end
+
+def fun_l16_n524(x)
+ if (x < 1)
+ fun_l17_n653(x)
+ else
+ fun_l17_n355(x)
+ end
+end
+
+def fun_l16_n525(x)
+ if (x < 1)
+ fun_l17_n872(x)
+ else
+ fun_l17_n714(x)
+ end
+end
+
+def fun_l16_n526(x)
+ if (x < 1)
+ fun_l17_n891(x)
+ else
+ fun_l17_n70(x)
+ end
+end
+
+def fun_l16_n527(x)
+ if (x < 1)
+ fun_l17_n46(x)
+ else
+ fun_l17_n591(x)
+ end
+end
+
+def fun_l16_n528(x)
+ if (x < 1)
+ fun_l17_n969(x)
+ else
+ fun_l17_n289(x)
+ end
+end
+
+def fun_l16_n529(x)
+ if (x < 1)
+ fun_l17_n713(x)
+ else
+ fun_l17_n775(x)
+ end
+end
+
+def fun_l16_n530(x)
+ if (x < 1)
+ fun_l17_n374(x)
+ else
+ fun_l17_n708(x)
+ end
+end
+
+def fun_l16_n531(x)
+ if (x < 1)
+ fun_l17_n996(x)
+ else
+ fun_l17_n764(x)
+ end
+end
+
+def fun_l16_n532(x)
+ if (x < 1)
+ fun_l17_n314(x)
+ else
+ fun_l17_n445(x)
+ end
+end
+
+def fun_l16_n533(x)
+ if (x < 1)
+ fun_l17_n951(x)
+ else
+ fun_l17_n912(x)
+ end
+end
+
+def fun_l16_n534(x)
+ if (x < 1)
+ fun_l17_n760(x)
+ else
+ fun_l17_n445(x)
+ end
+end
+
+def fun_l16_n535(x)
+ if (x < 1)
+ fun_l17_n310(x)
+ else
+ fun_l17_n16(x)
+ end
+end
+
+def fun_l16_n536(x)
+ if (x < 1)
+ fun_l17_n254(x)
+ else
+ fun_l17_n693(x)
+ end
+end
+
+def fun_l16_n537(x)
+ if (x < 1)
+ fun_l17_n631(x)
+ else
+ fun_l17_n934(x)
+ end
+end
+
+def fun_l16_n538(x)
+ if (x < 1)
+ fun_l17_n944(x)
+ else
+ fun_l17_n922(x)
+ end
+end
+
+def fun_l16_n539(x)
+ if (x < 1)
+ fun_l17_n263(x)
+ else
+ fun_l17_n796(x)
+ end
+end
+
+def fun_l16_n540(x)
+ if (x < 1)
+ fun_l17_n928(x)
+ else
+ fun_l17_n604(x)
+ end
+end
+
+def fun_l16_n541(x)
+ if (x < 1)
+ fun_l17_n678(x)
+ else
+ fun_l17_n880(x)
+ end
+end
+
+def fun_l16_n542(x)
+ if (x < 1)
+ fun_l17_n286(x)
+ else
+ fun_l17_n123(x)
+ end
+end
+
+def fun_l16_n543(x)
+ if (x < 1)
+ fun_l17_n604(x)
+ else
+ fun_l17_n57(x)
+ end
+end
+
+def fun_l16_n544(x)
+ if (x < 1)
+ fun_l17_n204(x)
+ else
+ fun_l17_n950(x)
+ end
+end
+
+def fun_l16_n545(x)
+ if (x < 1)
+ fun_l17_n60(x)
+ else
+ fun_l17_n667(x)
+ end
+end
+
+def fun_l16_n546(x)
+ if (x < 1)
+ fun_l17_n472(x)
+ else
+ fun_l17_n818(x)
+ end
+end
+
+def fun_l16_n547(x)
+ if (x < 1)
+ fun_l17_n515(x)
+ else
+ fun_l17_n180(x)
+ end
+end
+
+def fun_l16_n548(x)
+ if (x < 1)
+ fun_l17_n443(x)
+ else
+ fun_l17_n159(x)
+ end
+end
+
+def fun_l16_n549(x)
+ if (x < 1)
+ fun_l17_n820(x)
+ else
+ fun_l17_n468(x)
+ end
+end
+
+def fun_l16_n550(x)
+ if (x < 1)
+ fun_l17_n938(x)
+ else
+ fun_l17_n307(x)
+ end
+end
+
+def fun_l16_n551(x)
+ if (x < 1)
+ fun_l17_n350(x)
+ else
+ fun_l17_n177(x)
+ end
+end
+
+def fun_l16_n552(x)
+ if (x < 1)
+ fun_l17_n761(x)
+ else
+ fun_l17_n35(x)
+ end
+end
+
+def fun_l16_n553(x)
+ if (x < 1)
+ fun_l17_n189(x)
+ else
+ fun_l17_n991(x)
+ end
+end
+
+def fun_l16_n554(x)
+ if (x < 1)
+ fun_l17_n234(x)
+ else
+ fun_l17_n721(x)
+ end
+end
+
+def fun_l16_n555(x)
+ if (x < 1)
+ fun_l17_n42(x)
+ else
+ fun_l17_n273(x)
+ end
+end
+
+def fun_l16_n556(x)
+ if (x < 1)
+ fun_l17_n261(x)
+ else
+ fun_l17_n328(x)
+ end
+end
+
+def fun_l16_n557(x)
+ if (x < 1)
+ fun_l17_n28(x)
+ else
+ fun_l17_n403(x)
+ end
+end
+
+def fun_l16_n558(x)
+ if (x < 1)
+ fun_l17_n766(x)
+ else
+ fun_l17_n363(x)
+ end
+end
+
+def fun_l16_n559(x)
+ if (x < 1)
+ fun_l17_n35(x)
+ else
+ fun_l17_n648(x)
+ end
+end
+
+def fun_l16_n560(x)
+ if (x < 1)
+ fun_l17_n288(x)
+ else
+ fun_l17_n684(x)
+ end
+end
+
+def fun_l16_n561(x)
+ if (x < 1)
+ fun_l17_n529(x)
+ else
+ fun_l17_n908(x)
+ end
+end
+
+def fun_l16_n562(x)
+ if (x < 1)
+ fun_l17_n244(x)
+ else
+ fun_l17_n342(x)
+ end
+end
+
+def fun_l16_n563(x)
+ if (x < 1)
+ fun_l17_n535(x)
+ else
+ fun_l17_n750(x)
+ end
+end
+
+def fun_l16_n564(x)
+ if (x < 1)
+ fun_l17_n761(x)
+ else
+ fun_l17_n106(x)
+ end
+end
+
+def fun_l16_n565(x)
+ if (x < 1)
+ fun_l17_n236(x)
+ else
+ fun_l17_n95(x)
+ end
+end
+
+def fun_l16_n566(x)
+ if (x < 1)
+ fun_l17_n356(x)
+ else
+ fun_l17_n129(x)
+ end
+end
+
+def fun_l16_n567(x)
+ if (x < 1)
+ fun_l17_n297(x)
+ else
+ fun_l17_n247(x)
+ end
+end
+
+def fun_l16_n568(x)
+ if (x < 1)
+ fun_l17_n735(x)
+ else
+ fun_l17_n781(x)
+ end
+end
+
+def fun_l16_n569(x)
+ if (x < 1)
+ fun_l17_n650(x)
+ else
+ fun_l17_n377(x)
+ end
+end
+
+def fun_l16_n570(x)
+ if (x < 1)
+ fun_l17_n872(x)
+ else
+ fun_l17_n52(x)
+ end
+end
+
+def fun_l16_n571(x)
+ if (x < 1)
+ fun_l17_n970(x)
+ else
+ fun_l17_n719(x)
+ end
+end
+
+def fun_l16_n572(x)
+ if (x < 1)
+ fun_l17_n380(x)
+ else
+ fun_l17_n121(x)
+ end
+end
+
+def fun_l16_n573(x)
+ if (x < 1)
+ fun_l17_n190(x)
+ else
+ fun_l17_n675(x)
+ end
+end
+
+def fun_l16_n574(x)
+ if (x < 1)
+ fun_l17_n269(x)
+ else
+ fun_l17_n362(x)
+ end
+end
+
+def fun_l16_n575(x)
+ if (x < 1)
+ fun_l17_n480(x)
+ else
+ fun_l17_n228(x)
+ end
+end
+
+def fun_l16_n576(x)
+ if (x < 1)
+ fun_l17_n791(x)
+ else
+ fun_l17_n45(x)
+ end
+end
+
+def fun_l16_n577(x)
+ if (x < 1)
+ fun_l17_n403(x)
+ else
+ fun_l17_n887(x)
+ end
+end
+
+def fun_l16_n578(x)
+ if (x < 1)
+ fun_l17_n139(x)
+ else
+ fun_l17_n446(x)
+ end
+end
+
+def fun_l16_n579(x)
+ if (x < 1)
+ fun_l17_n472(x)
+ else
+ fun_l17_n869(x)
+ end
+end
+
+def fun_l16_n580(x)
+ if (x < 1)
+ fun_l17_n738(x)
+ else
+ fun_l17_n298(x)
+ end
+end
+
+def fun_l16_n581(x)
+ if (x < 1)
+ fun_l17_n822(x)
+ else
+ fun_l17_n859(x)
+ end
+end
+
+def fun_l16_n582(x)
+ if (x < 1)
+ fun_l17_n768(x)
+ else
+ fun_l17_n814(x)
+ end
+end
+
+def fun_l16_n583(x)
+ if (x < 1)
+ fun_l17_n892(x)
+ else
+ fun_l17_n821(x)
+ end
+end
+
+def fun_l16_n584(x)
+ if (x < 1)
+ fun_l17_n234(x)
+ else
+ fun_l17_n276(x)
+ end
+end
+
+def fun_l16_n585(x)
+ if (x < 1)
+ fun_l17_n162(x)
+ else
+ fun_l17_n873(x)
+ end
+end
+
+def fun_l16_n586(x)
+ if (x < 1)
+ fun_l17_n932(x)
+ else
+ fun_l17_n227(x)
+ end
+end
+
+def fun_l16_n587(x)
+ if (x < 1)
+ fun_l17_n105(x)
+ else
+ fun_l17_n620(x)
+ end
+end
+
+def fun_l16_n588(x)
+ if (x < 1)
+ fun_l17_n137(x)
+ else
+ fun_l17_n941(x)
+ end
+end
+
+def fun_l16_n589(x)
+ if (x < 1)
+ fun_l17_n936(x)
+ else
+ fun_l17_n877(x)
+ end
+end
+
+def fun_l16_n590(x)
+ if (x < 1)
+ fun_l17_n280(x)
+ else
+ fun_l17_n711(x)
+ end
+end
+
+def fun_l16_n591(x)
+ if (x < 1)
+ fun_l17_n968(x)
+ else
+ fun_l17_n695(x)
+ end
+end
+
+def fun_l16_n592(x)
+ if (x < 1)
+ fun_l17_n774(x)
+ else
+ fun_l17_n674(x)
+ end
+end
+
+def fun_l16_n593(x)
+ if (x < 1)
+ fun_l17_n421(x)
+ else
+ fun_l17_n516(x)
+ end
+end
+
+def fun_l16_n594(x)
+ if (x < 1)
+ fun_l17_n830(x)
+ else
+ fun_l17_n852(x)
+ end
+end
+
+def fun_l16_n595(x)
+ if (x < 1)
+ fun_l17_n659(x)
+ else
+ fun_l17_n114(x)
+ end
+end
+
+def fun_l16_n596(x)
+ if (x < 1)
+ fun_l17_n411(x)
+ else
+ fun_l17_n217(x)
+ end
+end
+
+def fun_l16_n597(x)
+ if (x < 1)
+ fun_l17_n506(x)
+ else
+ fun_l17_n721(x)
+ end
+end
+
+def fun_l16_n598(x)
+ if (x < 1)
+ fun_l17_n979(x)
+ else
+ fun_l17_n579(x)
+ end
+end
+
+def fun_l16_n599(x)
+ if (x < 1)
+ fun_l17_n423(x)
+ else
+ fun_l17_n765(x)
+ end
+end
+
+def fun_l16_n600(x)
+ if (x < 1)
+ fun_l17_n138(x)
+ else
+ fun_l17_n878(x)
+ end
+end
+
+def fun_l16_n601(x)
+ if (x < 1)
+ fun_l17_n616(x)
+ else
+ fun_l17_n531(x)
+ end
+end
+
+def fun_l16_n602(x)
+ if (x < 1)
+ fun_l17_n737(x)
+ else
+ fun_l17_n936(x)
+ end
+end
+
+def fun_l16_n603(x)
+ if (x < 1)
+ fun_l17_n106(x)
+ else
+ fun_l17_n147(x)
+ end
+end
+
+def fun_l16_n604(x)
+ if (x < 1)
+ fun_l17_n562(x)
+ else
+ fun_l17_n852(x)
+ end
+end
+
+def fun_l16_n605(x)
+ if (x < 1)
+ fun_l17_n473(x)
+ else
+ fun_l17_n771(x)
+ end
+end
+
+def fun_l16_n606(x)
+ if (x < 1)
+ fun_l17_n778(x)
+ else
+ fun_l17_n463(x)
+ end
+end
+
+def fun_l16_n607(x)
+ if (x < 1)
+ fun_l17_n35(x)
+ else
+ fun_l17_n341(x)
+ end
+end
+
+def fun_l16_n608(x)
+ if (x < 1)
+ fun_l17_n268(x)
+ else
+ fun_l17_n659(x)
+ end
+end
+
+def fun_l16_n609(x)
+ if (x < 1)
+ fun_l17_n734(x)
+ else
+ fun_l17_n174(x)
+ end
+end
+
+def fun_l16_n610(x)
+ if (x < 1)
+ fun_l17_n815(x)
+ else
+ fun_l17_n798(x)
+ end
+end
+
+def fun_l16_n611(x)
+ if (x < 1)
+ fun_l17_n251(x)
+ else
+ fun_l17_n694(x)
+ end
+end
+
+def fun_l16_n612(x)
+ if (x < 1)
+ fun_l17_n597(x)
+ else
+ fun_l17_n245(x)
+ end
+end
+
+def fun_l16_n613(x)
+ if (x < 1)
+ fun_l17_n990(x)
+ else
+ fun_l17_n58(x)
+ end
+end
+
+def fun_l16_n614(x)
+ if (x < 1)
+ fun_l17_n877(x)
+ else
+ fun_l17_n13(x)
+ end
+end
+
+def fun_l16_n615(x)
+ if (x < 1)
+ fun_l17_n7(x)
+ else
+ fun_l17_n787(x)
+ end
+end
+
+def fun_l16_n616(x)
+ if (x < 1)
+ fun_l17_n372(x)
+ else
+ fun_l17_n643(x)
+ end
+end
+
+def fun_l16_n617(x)
+ if (x < 1)
+ fun_l17_n592(x)
+ else
+ fun_l17_n508(x)
+ end
+end
+
+def fun_l16_n618(x)
+ if (x < 1)
+ fun_l17_n928(x)
+ else
+ fun_l17_n923(x)
+ end
+end
+
+def fun_l16_n619(x)
+ if (x < 1)
+ fun_l17_n407(x)
+ else
+ fun_l17_n885(x)
+ end
+end
+
+def fun_l16_n620(x)
+ if (x < 1)
+ fun_l17_n4(x)
+ else
+ fun_l17_n532(x)
+ end
+end
+
+def fun_l16_n621(x)
+ if (x < 1)
+ fun_l17_n791(x)
+ else
+ fun_l17_n141(x)
+ end
+end
+
+def fun_l16_n622(x)
+ if (x < 1)
+ fun_l17_n529(x)
+ else
+ fun_l17_n140(x)
+ end
+end
+
+def fun_l16_n623(x)
+ if (x < 1)
+ fun_l17_n713(x)
+ else
+ fun_l17_n867(x)
+ end
+end
+
+def fun_l16_n624(x)
+ if (x < 1)
+ fun_l17_n148(x)
+ else
+ fun_l17_n195(x)
+ end
+end
+
+def fun_l16_n625(x)
+ if (x < 1)
+ fun_l17_n287(x)
+ else
+ fun_l17_n662(x)
+ end
+end
+
+def fun_l16_n626(x)
+ if (x < 1)
+ fun_l17_n678(x)
+ else
+ fun_l17_n262(x)
+ end
+end
+
+def fun_l16_n627(x)
+ if (x < 1)
+ fun_l17_n217(x)
+ else
+ fun_l17_n612(x)
+ end
+end
+
+def fun_l16_n628(x)
+ if (x < 1)
+ fun_l17_n826(x)
+ else
+ fun_l17_n164(x)
+ end
+end
+
+def fun_l16_n629(x)
+ if (x < 1)
+ fun_l17_n360(x)
+ else
+ fun_l17_n221(x)
+ end
+end
+
+def fun_l16_n630(x)
+ if (x < 1)
+ fun_l17_n842(x)
+ else
+ fun_l17_n362(x)
+ end
+end
+
+def fun_l16_n631(x)
+ if (x < 1)
+ fun_l17_n53(x)
+ else
+ fun_l17_n216(x)
+ end
+end
+
+def fun_l16_n632(x)
+ if (x < 1)
+ fun_l17_n628(x)
+ else
+ fun_l17_n150(x)
+ end
+end
+
+def fun_l16_n633(x)
+ if (x < 1)
+ fun_l17_n206(x)
+ else
+ fun_l17_n789(x)
+ end
+end
+
+def fun_l16_n634(x)
+ if (x < 1)
+ fun_l17_n26(x)
+ else
+ fun_l17_n376(x)
+ end
+end
+
+def fun_l16_n635(x)
+ if (x < 1)
+ fun_l17_n614(x)
+ else
+ fun_l17_n109(x)
+ end
+end
+
+def fun_l16_n636(x)
+ if (x < 1)
+ fun_l17_n626(x)
+ else
+ fun_l17_n456(x)
+ end
+end
+
+def fun_l16_n637(x)
+ if (x < 1)
+ fun_l17_n836(x)
+ else
+ fun_l17_n602(x)
+ end
+end
+
+def fun_l16_n638(x)
+ if (x < 1)
+ fun_l17_n793(x)
+ else
+ fun_l17_n791(x)
+ end
+end
+
+def fun_l16_n639(x)
+ if (x < 1)
+ fun_l17_n689(x)
+ else
+ fun_l17_n714(x)
+ end
+end
+
+def fun_l16_n640(x)
+ if (x < 1)
+ fun_l17_n587(x)
+ else
+ fun_l17_n203(x)
+ end
+end
+
+def fun_l16_n641(x)
+ if (x < 1)
+ fun_l17_n686(x)
+ else
+ fun_l17_n297(x)
+ end
+end
+
+def fun_l16_n642(x)
+ if (x < 1)
+ fun_l17_n394(x)
+ else
+ fun_l17_n564(x)
+ end
+end
+
+def fun_l16_n643(x)
+ if (x < 1)
+ fun_l17_n669(x)
+ else
+ fun_l17_n250(x)
+ end
+end
+
+def fun_l16_n644(x)
+ if (x < 1)
+ fun_l17_n407(x)
+ else
+ fun_l17_n631(x)
+ end
+end
+
+def fun_l16_n645(x)
+ if (x < 1)
+ fun_l17_n928(x)
+ else
+ fun_l17_n856(x)
+ end
+end
+
+def fun_l16_n646(x)
+ if (x < 1)
+ fun_l17_n344(x)
+ else
+ fun_l17_n529(x)
+ end
+end
+
+def fun_l16_n647(x)
+ if (x < 1)
+ fun_l17_n540(x)
+ else
+ fun_l17_n468(x)
+ end
+end
+
+def fun_l16_n648(x)
+ if (x < 1)
+ fun_l17_n831(x)
+ else
+ fun_l17_n350(x)
+ end
+end
+
+def fun_l16_n649(x)
+ if (x < 1)
+ fun_l17_n154(x)
+ else
+ fun_l17_n587(x)
+ end
+end
+
+def fun_l16_n650(x)
+ if (x < 1)
+ fun_l17_n379(x)
+ else
+ fun_l17_n421(x)
+ end
+end
+
+def fun_l16_n651(x)
+ if (x < 1)
+ fun_l17_n839(x)
+ else
+ fun_l17_n782(x)
+ end
+end
+
+def fun_l16_n652(x)
+ if (x < 1)
+ fun_l17_n408(x)
+ else
+ fun_l17_n923(x)
+ end
+end
+
+def fun_l16_n653(x)
+ if (x < 1)
+ fun_l17_n51(x)
+ else
+ fun_l17_n317(x)
+ end
+end
+
+def fun_l16_n654(x)
+ if (x < 1)
+ fun_l17_n635(x)
+ else
+ fun_l17_n39(x)
+ end
+end
+
+def fun_l16_n655(x)
+ if (x < 1)
+ fun_l17_n921(x)
+ else
+ fun_l17_n641(x)
+ end
+end
+
+def fun_l16_n656(x)
+ if (x < 1)
+ fun_l17_n615(x)
+ else
+ fun_l17_n118(x)
+ end
+end
+
+def fun_l16_n657(x)
+ if (x < 1)
+ fun_l17_n673(x)
+ else
+ fun_l17_n842(x)
+ end
+end
+
+def fun_l16_n658(x)
+ if (x < 1)
+ fun_l17_n743(x)
+ else
+ fun_l17_n594(x)
+ end
+end
+
+def fun_l16_n659(x)
+ if (x < 1)
+ fun_l17_n85(x)
+ else
+ fun_l17_n787(x)
+ end
+end
+
+def fun_l16_n660(x)
+ if (x < 1)
+ fun_l17_n363(x)
+ else
+ fun_l17_n830(x)
+ end
+end
+
+def fun_l16_n661(x)
+ if (x < 1)
+ fun_l17_n897(x)
+ else
+ fun_l17_n989(x)
+ end
+end
+
+def fun_l16_n662(x)
+ if (x < 1)
+ fun_l17_n644(x)
+ else
+ fun_l17_n924(x)
+ end
+end
+
+def fun_l16_n663(x)
+ if (x < 1)
+ fun_l17_n812(x)
+ else
+ fun_l17_n159(x)
+ end
+end
+
+def fun_l16_n664(x)
+ if (x < 1)
+ fun_l17_n937(x)
+ else
+ fun_l17_n720(x)
+ end
+end
+
+def fun_l16_n665(x)
+ if (x < 1)
+ fun_l17_n732(x)
+ else
+ fun_l17_n516(x)
+ end
+end
+
+def fun_l16_n666(x)
+ if (x < 1)
+ fun_l17_n399(x)
+ else
+ fun_l17_n728(x)
+ end
+end
+
+def fun_l16_n667(x)
+ if (x < 1)
+ fun_l17_n673(x)
+ else
+ fun_l17_n735(x)
+ end
+end
+
+def fun_l16_n668(x)
+ if (x < 1)
+ fun_l17_n321(x)
+ else
+ fun_l17_n850(x)
+ end
+end
+
+def fun_l16_n669(x)
+ if (x < 1)
+ fun_l17_n873(x)
+ else
+ fun_l17_n701(x)
+ end
+end
+
+def fun_l16_n670(x)
+ if (x < 1)
+ fun_l17_n683(x)
+ else
+ fun_l17_n903(x)
+ end
+end
+
+def fun_l16_n671(x)
+ if (x < 1)
+ fun_l17_n440(x)
+ else
+ fun_l17_n178(x)
+ end
+end
+
+def fun_l16_n672(x)
+ if (x < 1)
+ fun_l17_n619(x)
+ else
+ fun_l17_n785(x)
+ end
+end
+
+def fun_l16_n673(x)
+ if (x < 1)
+ fun_l17_n185(x)
+ else
+ fun_l17_n794(x)
+ end
+end
+
+def fun_l16_n674(x)
+ if (x < 1)
+ fun_l17_n543(x)
+ else
+ fun_l17_n161(x)
+ end
+end
+
+def fun_l16_n675(x)
+ if (x < 1)
+ fun_l17_n898(x)
+ else
+ fun_l17_n590(x)
+ end
+end
+
+def fun_l16_n676(x)
+ if (x < 1)
+ fun_l17_n471(x)
+ else
+ fun_l17_n66(x)
+ end
+end
+
+def fun_l16_n677(x)
+ if (x < 1)
+ fun_l17_n764(x)
+ else
+ fun_l17_n163(x)
+ end
+end
+
+def fun_l16_n678(x)
+ if (x < 1)
+ fun_l17_n290(x)
+ else
+ fun_l17_n353(x)
+ end
+end
+
+def fun_l16_n679(x)
+ if (x < 1)
+ fun_l17_n851(x)
+ else
+ fun_l17_n7(x)
+ end
+end
+
+def fun_l16_n680(x)
+ if (x < 1)
+ fun_l17_n741(x)
+ else
+ fun_l17_n180(x)
+ end
+end
+
+def fun_l16_n681(x)
+ if (x < 1)
+ fun_l17_n887(x)
+ else
+ fun_l17_n258(x)
+ end
+end
+
+def fun_l16_n682(x)
+ if (x < 1)
+ fun_l17_n536(x)
+ else
+ fun_l17_n84(x)
+ end
+end
+
+def fun_l16_n683(x)
+ if (x < 1)
+ fun_l17_n447(x)
+ else
+ fun_l17_n455(x)
+ end
+end
+
+def fun_l16_n684(x)
+ if (x < 1)
+ fun_l17_n23(x)
+ else
+ fun_l17_n47(x)
+ end
+end
+
+def fun_l16_n685(x)
+ if (x < 1)
+ fun_l17_n983(x)
+ else
+ fun_l17_n470(x)
+ end
+end
+
+def fun_l16_n686(x)
+ if (x < 1)
+ fun_l17_n261(x)
+ else
+ fun_l17_n138(x)
+ end
+end
+
+def fun_l16_n687(x)
+ if (x < 1)
+ fun_l17_n791(x)
+ else
+ fun_l17_n474(x)
+ end
+end
+
+def fun_l16_n688(x)
+ if (x < 1)
+ fun_l17_n148(x)
+ else
+ fun_l17_n317(x)
+ end
+end
+
+def fun_l16_n689(x)
+ if (x < 1)
+ fun_l17_n107(x)
+ else
+ fun_l17_n529(x)
+ end
+end
+
+def fun_l16_n690(x)
+ if (x < 1)
+ fun_l17_n310(x)
+ else
+ fun_l17_n394(x)
+ end
+end
+
+def fun_l16_n691(x)
+ if (x < 1)
+ fun_l17_n193(x)
+ else
+ fun_l17_n348(x)
+ end
+end
+
+def fun_l16_n692(x)
+ if (x < 1)
+ fun_l17_n308(x)
+ else
+ fun_l17_n26(x)
+ end
+end
+
+def fun_l16_n693(x)
+ if (x < 1)
+ fun_l17_n502(x)
+ else
+ fun_l17_n517(x)
+ end
+end
+
+def fun_l16_n694(x)
+ if (x < 1)
+ fun_l17_n396(x)
+ else
+ fun_l17_n886(x)
+ end
+end
+
+def fun_l16_n695(x)
+ if (x < 1)
+ fun_l17_n179(x)
+ else
+ fun_l17_n35(x)
+ end
+end
+
+def fun_l16_n696(x)
+ if (x < 1)
+ fun_l17_n431(x)
+ else
+ fun_l17_n392(x)
+ end
+end
+
+def fun_l16_n697(x)
+ if (x < 1)
+ fun_l17_n778(x)
+ else
+ fun_l17_n766(x)
+ end
+end
+
+def fun_l16_n698(x)
+ if (x < 1)
+ fun_l17_n868(x)
+ else
+ fun_l17_n31(x)
+ end
+end
+
+def fun_l16_n699(x)
+ if (x < 1)
+ fun_l17_n277(x)
+ else
+ fun_l17_n649(x)
+ end
+end
+
+def fun_l16_n700(x)
+ if (x < 1)
+ fun_l17_n638(x)
+ else
+ fun_l17_n411(x)
+ end
+end
+
+def fun_l16_n701(x)
+ if (x < 1)
+ fun_l17_n730(x)
+ else
+ fun_l17_n188(x)
+ end
+end
+
+def fun_l16_n702(x)
+ if (x < 1)
+ fun_l17_n530(x)
+ else
+ fun_l17_n540(x)
+ end
+end
+
+def fun_l16_n703(x)
+ if (x < 1)
+ fun_l17_n691(x)
+ else
+ fun_l17_n550(x)
+ end
+end
+
+def fun_l16_n704(x)
+ if (x < 1)
+ fun_l17_n691(x)
+ else
+ fun_l17_n25(x)
+ end
+end
+
+def fun_l16_n705(x)
+ if (x < 1)
+ fun_l17_n744(x)
+ else
+ fun_l17_n333(x)
+ end
+end
+
+def fun_l16_n706(x)
+ if (x < 1)
+ fun_l17_n845(x)
+ else
+ fun_l17_n229(x)
+ end
+end
+
+def fun_l16_n707(x)
+ if (x < 1)
+ fun_l17_n784(x)
+ else
+ fun_l17_n123(x)
+ end
+end
+
+def fun_l16_n708(x)
+ if (x < 1)
+ fun_l17_n88(x)
+ else
+ fun_l17_n961(x)
+ end
+end
+
+def fun_l16_n709(x)
+ if (x < 1)
+ fun_l17_n310(x)
+ else
+ fun_l17_n943(x)
+ end
+end
+
+def fun_l16_n710(x)
+ if (x < 1)
+ fun_l17_n265(x)
+ else
+ fun_l17_n958(x)
+ end
+end
+
+def fun_l16_n711(x)
+ if (x < 1)
+ fun_l17_n483(x)
+ else
+ fun_l17_n577(x)
+ end
+end
+
+def fun_l16_n712(x)
+ if (x < 1)
+ fun_l17_n703(x)
+ else
+ fun_l17_n625(x)
+ end
+end
+
+def fun_l16_n713(x)
+ if (x < 1)
+ fun_l17_n301(x)
+ else
+ fun_l17_n17(x)
+ end
+end
+
+def fun_l16_n714(x)
+ if (x < 1)
+ fun_l17_n455(x)
+ else
+ fun_l17_n647(x)
+ end
+end
+
+def fun_l16_n715(x)
+ if (x < 1)
+ fun_l17_n628(x)
+ else
+ fun_l17_n748(x)
+ end
+end
+
+def fun_l16_n716(x)
+ if (x < 1)
+ fun_l17_n10(x)
+ else
+ fun_l17_n632(x)
+ end
+end
+
+def fun_l16_n717(x)
+ if (x < 1)
+ fun_l17_n82(x)
+ else
+ fun_l17_n888(x)
+ end
+end
+
+def fun_l16_n718(x)
+ if (x < 1)
+ fun_l17_n234(x)
+ else
+ fun_l17_n554(x)
+ end
+end
+
+def fun_l16_n719(x)
+ if (x < 1)
+ fun_l17_n811(x)
+ else
+ fun_l17_n46(x)
+ end
+end
+
+def fun_l16_n720(x)
+ if (x < 1)
+ fun_l17_n227(x)
+ else
+ fun_l17_n89(x)
+ end
+end
+
+def fun_l16_n721(x)
+ if (x < 1)
+ fun_l17_n780(x)
+ else
+ fun_l17_n941(x)
+ end
+end
+
+def fun_l16_n722(x)
+ if (x < 1)
+ fun_l17_n877(x)
+ else
+ fun_l17_n262(x)
+ end
+end
+
+def fun_l16_n723(x)
+ if (x < 1)
+ fun_l17_n649(x)
+ else
+ fun_l17_n477(x)
+ end
+end
+
+def fun_l16_n724(x)
+ if (x < 1)
+ fun_l17_n902(x)
+ else
+ fun_l17_n315(x)
+ end
+end
+
+def fun_l16_n725(x)
+ if (x < 1)
+ fun_l17_n985(x)
+ else
+ fun_l17_n232(x)
+ end
+end
+
+def fun_l16_n726(x)
+ if (x < 1)
+ fun_l17_n5(x)
+ else
+ fun_l17_n981(x)
+ end
+end
+
+def fun_l16_n727(x)
+ if (x < 1)
+ fun_l17_n730(x)
+ else
+ fun_l17_n780(x)
+ end
+end
+
+def fun_l16_n728(x)
+ if (x < 1)
+ fun_l17_n626(x)
+ else
+ fun_l17_n272(x)
+ end
+end
+
+def fun_l16_n729(x)
+ if (x < 1)
+ fun_l17_n380(x)
+ else
+ fun_l17_n289(x)
+ end
+end
+
+def fun_l16_n730(x)
+ if (x < 1)
+ fun_l17_n711(x)
+ else
+ fun_l17_n861(x)
+ end
+end
+
+def fun_l16_n731(x)
+ if (x < 1)
+ fun_l17_n351(x)
+ else
+ fun_l17_n948(x)
+ end
+end
+
+def fun_l16_n732(x)
+ if (x < 1)
+ fun_l17_n864(x)
+ else
+ fun_l17_n60(x)
+ end
+end
+
+def fun_l16_n733(x)
+ if (x < 1)
+ fun_l17_n974(x)
+ else
+ fun_l17_n475(x)
+ end
+end
+
+def fun_l16_n734(x)
+ if (x < 1)
+ fun_l17_n855(x)
+ else
+ fun_l17_n988(x)
+ end
+end
+
+def fun_l16_n735(x)
+ if (x < 1)
+ fun_l17_n740(x)
+ else
+ fun_l17_n559(x)
+ end
+end
+
+def fun_l16_n736(x)
+ if (x < 1)
+ fun_l17_n449(x)
+ else
+ fun_l17_n580(x)
+ end
+end
+
+def fun_l16_n737(x)
+ if (x < 1)
+ fun_l17_n313(x)
+ else
+ fun_l17_n462(x)
+ end
+end
+
+def fun_l16_n738(x)
+ if (x < 1)
+ fun_l17_n177(x)
+ else
+ fun_l17_n812(x)
+ end
+end
+
+def fun_l16_n739(x)
+ if (x < 1)
+ fun_l17_n518(x)
+ else
+ fun_l17_n453(x)
+ end
+end
+
+def fun_l16_n740(x)
+ if (x < 1)
+ fun_l17_n190(x)
+ else
+ fun_l17_n722(x)
+ end
+end
+
+def fun_l16_n741(x)
+ if (x < 1)
+ fun_l17_n509(x)
+ else
+ fun_l17_n203(x)
+ end
+end
+
+def fun_l16_n742(x)
+ if (x < 1)
+ fun_l17_n901(x)
+ else
+ fun_l17_n497(x)
+ end
+end
+
+def fun_l16_n743(x)
+ if (x < 1)
+ fun_l17_n19(x)
+ else
+ fun_l17_n789(x)
+ end
+end
+
+def fun_l16_n744(x)
+ if (x < 1)
+ fun_l17_n879(x)
+ else
+ fun_l17_n554(x)
+ end
+end
+
+def fun_l16_n745(x)
+ if (x < 1)
+ fun_l17_n106(x)
+ else
+ fun_l17_n255(x)
+ end
+end
+
+def fun_l16_n746(x)
+ if (x < 1)
+ fun_l17_n942(x)
+ else
+ fun_l17_n701(x)
+ end
+end
+
+def fun_l16_n747(x)
+ if (x < 1)
+ fun_l17_n738(x)
+ else
+ fun_l17_n459(x)
+ end
+end
+
+def fun_l16_n748(x)
+ if (x < 1)
+ fun_l17_n984(x)
+ else
+ fun_l17_n501(x)
+ end
+end
+
+def fun_l16_n749(x)
+ if (x < 1)
+ fun_l17_n399(x)
+ else
+ fun_l17_n165(x)
+ end
+end
+
+def fun_l16_n750(x)
+ if (x < 1)
+ fun_l17_n956(x)
+ else
+ fun_l17_n210(x)
+ end
+end
+
+def fun_l16_n751(x)
+ if (x < 1)
+ fun_l17_n549(x)
+ else
+ fun_l17_n406(x)
+ end
+end
+
+def fun_l16_n752(x)
+ if (x < 1)
+ fun_l17_n671(x)
+ else
+ fun_l17_n809(x)
+ end
+end
+
+def fun_l16_n753(x)
+ if (x < 1)
+ fun_l17_n807(x)
+ else
+ fun_l17_n544(x)
+ end
+end
+
+def fun_l16_n754(x)
+ if (x < 1)
+ fun_l17_n150(x)
+ else
+ fun_l17_n705(x)
+ end
+end
+
+def fun_l16_n755(x)
+ if (x < 1)
+ fun_l17_n822(x)
+ else
+ fun_l17_n627(x)
+ end
+end
+
+def fun_l16_n756(x)
+ if (x < 1)
+ fun_l17_n429(x)
+ else
+ fun_l17_n598(x)
+ end
+end
+
+def fun_l16_n757(x)
+ if (x < 1)
+ fun_l17_n327(x)
+ else
+ fun_l17_n391(x)
+ end
+end
+
+def fun_l16_n758(x)
+ if (x < 1)
+ fun_l17_n335(x)
+ else
+ fun_l17_n779(x)
+ end
+end
+
+def fun_l16_n759(x)
+ if (x < 1)
+ fun_l17_n149(x)
+ else
+ fun_l17_n637(x)
+ end
+end
+
+def fun_l16_n760(x)
+ if (x < 1)
+ fun_l17_n83(x)
+ else
+ fun_l17_n616(x)
+ end
+end
+
+def fun_l16_n761(x)
+ if (x < 1)
+ fun_l17_n997(x)
+ else
+ fun_l17_n189(x)
+ end
+end
+
+def fun_l16_n762(x)
+ if (x < 1)
+ fun_l17_n779(x)
+ else
+ fun_l17_n175(x)
+ end
+end
+
+def fun_l16_n763(x)
+ if (x < 1)
+ fun_l17_n73(x)
+ else
+ fun_l17_n473(x)
+ end
+end
+
+def fun_l16_n764(x)
+ if (x < 1)
+ fun_l17_n784(x)
+ else
+ fun_l17_n415(x)
+ end
+end
+
+def fun_l16_n765(x)
+ if (x < 1)
+ fun_l17_n809(x)
+ else
+ fun_l17_n263(x)
+ end
+end
+
+def fun_l16_n766(x)
+ if (x < 1)
+ fun_l17_n114(x)
+ else
+ fun_l17_n898(x)
+ end
+end
+
+def fun_l16_n767(x)
+ if (x < 1)
+ fun_l17_n983(x)
+ else
+ fun_l17_n114(x)
+ end
+end
+
+def fun_l16_n768(x)
+ if (x < 1)
+ fun_l17_n141(x)
+ else
+ fun_l17_n492(x)
+ end
+end
+
+def fun_l16_n769(x)
+ if (x < 1)
+ fun_l17_n216(x)
+ else
+ fun_l17_n610(x)
+ end
+end
+
+def fun_l16_n770(x)
+ if (x < 1)
+ fun_l17_n797(x)
+ else
+ fun_l17_n164(x)
+ end
+end
+
+def fun_l16_n771(x)
+ if (x < 1)
+ fun_l17_n434(x)
+ else
+ fun_l17_n876(x)
+ end
+end
+
+def fun_l16_n772(x)
+ if (x < 1)
+ fun_l17_n165(x)
+ else
+ fun_l17_n646(x)
+ end
+end
+
+def fun_l16_n773(x)
+ if (x < 1)
+ fun_l17_n359(x)
+ else
+ fun_l17_n754(x)
+ end
+end
+
+def fun_l16_n774(x)
+ if (x < 1)
+ fun_l17_n314(x)
+ else
+ fun_l17_n745(x)
+ end
+end
+
+def fun_l16_n775(x)
+ if (x < 1)
+ fun_l17_n35(x)
+ else
+ fun_l17_n673(x)
+ end
+end
+
+def fun_l16_n776(x)
+ if (x < 1)
+ fun_l17_n51(x)
+ else
+ fun_l17_n708(x)
+ end
+end
+
+def fun_l16_n777(x)
+ if (x < 1)
+ fun_l17_n451(x)
+ else
+ fun_l17_n30(x)
+ end
+end
+
+def fun_l16_n778(x)
+ if (x < 1)
+ fun_l17_n821(x)
+ else
+ fun_l17_n114(x)
+ end
+end
+
+def fun_l16_n779(x)
+ if (x < 1)
+ fun_l17_n727(x)
+ else
+ fun_l17_n71(x)
+ end
+end
+
+def fun_l16_n780(x)
+ if (x < 1)
+ fun_l17_n404(x)
+ else
+ fun_l17_n42(x)
+ end
+end
+
+def fun_l16_n781(x)
+ if (x < 1)
+ fun_l17_n926(x)
+ else
+ fun_l17_n53(x)
+ end
+end
+
+def fun_l16_n782(x)
+ if (x < 1)
+ fun_l17_n499(x)
+ else
+ fun_l17_n429(x)
+ end
+end
+
+def fun_l16_n783(x)
+ if (x < 1)
+ fun_l17_n887(x)
+ else
+ fun_l17_n912(x)
+ end
+end
+
+def fun_l16_n784(x)
+ if (x < 1)
+ fun_l17_n900(x)
+ else
+ fun_l17_n163(x)
+ end
+end
+
+def fun_l16_n785(x)
+ if (x < 1)
+ fun_l17_n589(x)
+ else
+ fun_l17_n271(x)
+ end
+end
+
+def fun_l16_n786(x)
+ if (x < 1)
+ fun_l17_n732(x)
+ else
+ fun_l17_n296(x)
+ end
+end
+
+def fun_l16_n787(x)
+ if (x < 1)
+ fun_l17_n711(x)
+ else
+ fun_l17_n777(x)
+ end
+end
+
+def fun_l16_n788(x)
+ if (x < 1)
+ fun_l17_n426(x)
+ else
+ fun_l17_n291(x)
+ end
+end
+
+def fun_l16_n789(x)
+ if (x < 1)
+ fun_l17_n833(x)
+ else
+ fun_l17_n958(x)
+ end
+end
+
+def fun_l16_n790(x)
+ if (x < 1)
+ fun_l17_n680(x)
+ else
+ fun_l17_n707(x)
+ end
+end
+
+def fun_l16_n791(x)
+ if (x < 1)
+ fun_l17_n668(x)
+ else
+ fun_l17_n727(x)
+ end
+end
+
+def fun_l16_n792(x)
+ if (x < 1)
+ fun_l17_n948(x)
+ else
+ fun_l17_n160(x)
+ end
+end
+
+def fun_l16_n793(x)
+ if (x < 1)
+ fun_l17_n847(x)
+ else
+ fun_l17_n643(x)
+ end
+end
+
+def fun_l16_n794(x)
+ if (x < 1)
+ fun_l17_n89(x)
+ else
+ fun_l17_n704(x)
+ end
+end
+
+def fun_l16_n795(x)
+ if (x < 1)
+ fun_l17_n52(x)
+ else
+ fun_l17_n307(x)
+ end
+end
+
+def fun_l16_n796(x)
+ if (x < 1)
+ fun_l17_n632(x)
+ else
+ fun_l17_n839(x)
+ end
+end
+
+def fun_l16_n797(x)
+ if (x < 1)
+ fun_l17_n343(x)
+ else
+ fun_l17_n969(x)
+ end
+end
+
+def fun_l16_n798(x)
+ if (x < 1)
+ fun_l17_n850(x)
+ else
+ fun_l17_n975(x)
+ end
+end
+
+def fun_l16_n799(x)
+ if (x < 1)
+ fun_l17_n119(x)
+ else
+ fun_l17_n303(x)
+ end
+end
+
+def fun_l16_n800(x)
+ if (x < 1)
+ fun_l17_n870(x)
+ else
+ fun_l17_n4(x)
+ end
+end
+
+def fun_l16_n801(x)
+ if (x < 1)
+ fun_l17_n223(x)
+ else
+ fun_l17_n618(x)
+ end
+end
+
+def fun_l16_n802(x)
+ if (x < 1)
+ fun_l17_n183(x)
+ else
+ fun_l17_n358(x)
+ end
+end
+
+def fun_l16_n803(x)
+ if (x < 1)
+ fun_l17_n152(x)
+ else
+ fun_l17_n76(x)
+ end
+end
+
+def fun_l16_n804(x)
+ if (x < 1)
+ fun_l17_n487(x)
+ else
+ fun_l17_n475(x)
+ end
+end
+
+def fun_l16_n805(x)
+ if (x < 1)
+ fun_l17_n900(x)
+ else
+ fun_l17_n786(x)
+ end
+end
+
+def fun_l16_n806(x)
+ if (x < 1)
+ fun_l17_n881(x)
+ else
+ fun_l17_n523(x)
+ end
+end
+
+def fun_l16_n807(x)
+ if (x < 1)
+ fun_l17_n686(x)
+ else
+ fun_l17_n5(x)
+ end
+end
+
+def fun_l16_n808(x)
+ if (x < 1)
+ fun_l17_n841(x)
+ else
+ fun_l17_n73(x)
+ end
+end
+
+def fun_l16_n809(x)
+ if (x < 1)
+ fun_l17_n737(x)
+ else
+ fun_l17_n590(x)
+ end
+end
+
+def fun_l16_n810(x)
+ if (x < 1)
+ fun_l17_n252(x)
+ else
+ fun_l17_n867(x)
+ end
+end
+
+def fun_l16_n811(x)
+ if (x < 1)
+ fun_l17_n333(x)
+ else
+ fun_l17_n418(x)
+ end
+end
+
+def fun_l16_n812(x)
+ if (x < 1)
+ fun_l17_n155(x)
+ else
+ fun_l17_n104(x)
+ end
+end
+
+def fun_l16_n813(x)
+ if (x < 1)
+ fun_l17_n933(x)
+ else
+ fun_l17_n344(x)
+ end
+end
+
+def fun_l16_n814(x)
+ if (x < 1)
+ fun_l17_n107(x)
+ else
+ fun_l17_n784(x)
+ end
+end
+
+def fun_l16_n815(x)
+ if (x < 1)
+ fun_l17_n355(x)
+ else
+ fun_l17_n184(x)
+ end
+end
+
+def fun_l16_n816(x)
+ if (x < 1)
+ fun_l17_n266(x)
+ else
+ fun_l17_n315(x)
+ end
+end
+
+def fun_l16_n817(x)
+ if (x < 1)
+ fun_l17_n821(x)
+ else
+ fun_l17_n534(x)
+ end
+end
+
+def fun_l16_n818(x)
+ if (x < 1)
+ fun_l17_n126(x)
+ else
+ fun_l17_n712(x)
+ end
+end
+
+def fun_l16_n819(x)
+ if (x < 1)
+ fun_l17_n309(x)
+ else
+ fun_l17_n39(x)
+ end
+end
+
+def fun_l16_n820(x)
+ if (x < 1)
+ fun_l17_n629(x)
+ else
+ fun_l17_n689(x)
+ end
+end
+
+def fun_l16_n821(x)
+ if (x < 1)
+ fun_l17_n35(x)
+ else
+ fun_l17_n250(x)
+ end
+end
+
+def fun_l16_n822(x)
+ if (x < 1)
+ fun_l17_n276(x)
+ else
+ fun_l17_n350(x)
+ end
+end
+
+def fun_l16_n823(x)
+ if (x < 1)
+ fun_l17_n775(x)
+ else
+ fun_l17_n542(x)
+ end
+end
+
+def fun_l16_n824(x)
+ if (x < 1)
+ fun_l17_n739(x)
+ else
+ fun_l17_n441(x)
+ end
+end
+
+def fun_l16_n825(x)
+ if (x < 1)
+ fun_l17_n86(x)
+ else
+ fun_l17_n360(x)
+ end
+end
+
+def fun_l16_n826(x)
+ if (x < 1)
+ fun_l17_n196(x)
+ else
+ fun_l17_n406(x)
+ end
+end
+
+def fun_l16_n827(x)
+ if (x < 1)
+ fun_l17_n612(x)
+ else
+ fun_l17_n471(x)
+ end
+end
+
+def fun_l16_n828(x)
+ if (x < 1)
+ fun_l17_n409(x)
+ else
+ fun_l17_n572(x)
+ end
+end
+
+def fun_l16_n829(x)
+ if (x < 1)
+ fun_l17_n347(x)
+ else
+ fun_l17_n450(x)
+ end
+end
+
+def fun_l16_n830(x)
+ if (x < 1)
+ fun_l17_n75(x)
+ else
+ fun_l17_n185(x)
+ end
+end
+
+def fun_l16_n831(x)
+ if (x < 1)
+ fun_l17_n904(x)
+ else
+ fun_l17_n894(x)
+ end
+end
+
+def fun_l16_n832(x)
+ if (x < 1)
+ fun_l17_n889(x)
+ else
+ fun_l17_n651(x)
+ end
+end
+
+def fun_l16_n833(x)
+ if (x < 1)
+ fun_l17_n670(x)
+ else
+ fun_l17_n216(x)
+ end
+end
+
+def fun_l16_n834(x)
+ if (x < 1)
+ fun_l17_n212(x)
+ else
+ fun_l17_n445(x)
+ end
+end
+
+def fun_l16_n835(x)
+ if (x < 1)
+ fun_l17_n453(x)
+ else
+ fun_l17_n187(x)
+ end
+end
+
+def fun_l16_n836(x)
+ if (x < 1)
+ fun_l17_n614(x)
+ else
+ fun_l17_n203(x)
+ end
+end
+
+def fun_l16_n837(x)
+ if (x < 1)
+ fun_l17_n177(x)
+ else
+ fun_l17_n721(x)
+ end
+end
+
+def fun_l16_n838(x)
+ if (x < 1)
+ fun_l17_n910(x)
+ else
+ fun_l17_n510(x)
+ end
+end
+
+def fun_l16_n839(x)
+ if (x < 1)
+ fun_l17_n880(x)
+ else
+ fun_l17_n365(x)
+ end
+end
+
+def fun_l16_n840(x)
+ if (x < 1)
+ fun_l17_n336(x)
+ else
+ fun_l17_n483(x)
+ end
+end
+
+def fun_l16_n841(x)
+ if (x < 1)
+ fun_l17_n83(x)
+ else
+ fun_l17_n947(x)
+ end
+end
+
+def fun_l16_n842(x)
+ if (x < 1)
+ fun_l17_n723(x)
+ else
+ fun_l17_n209(x)
+ end
+end
+
+def fun_l16_n843(x)
+ if (x < 1)
+ fun_l17_n432(x)
+ else
+ fun_l17_n664(x)
+ end
+end
+
+def fun_l16_n844(x)
+ if (x < 1)
+ fun_l17_n906(x)
+ else
+ fun_l17_n472(x)
+ end
+end
+
+def fun_l16_n845(x)
+ if (x < 1)
+ fun_l17_n147(x)
+ else
+ fun_l17_n623(x)
+ end
+end
+
+def fun_l16_n846(x)
+ if (x < 1)
+ fun_l17_n296(x)
+ else
+ fun_l17_n44(x)
+ end
+end
+
+def fun_l16_n847(x)
+ if (x < 1)
+ fun_l17_n498(x)
+ else
+ fun_l17_n764(x)
+ end
+end
+
+def fun_l16_n848(x)
+ if (x < 1)
+ fun_l17_n428(x)
+ else
+ fun_l17_n575(x)
+ end
+end
+
+def fun_l16_n849(x)
+ if (x < 1)
+ fun_l17_n311(x)
+ else
+ fun_l17_n975(x)
+ end
+end
+
+def fun_l16_n850(x)
+ if (x < 1)
+ fun_l17_n482(x)
+ else
+ fun_l17_n388(x)
+ end
+end
+
+def fun_l16_n851(x)
+ if (x < 1)
+ fun_l17_n174(x)
+ else
+ fun_l17_n190(x)
+ end
+end
+
+def fun_l16_n852(x)
+ if (x < 1)
+ fun_l17_n28(x)
+ else
+ fun_l17_n598(x)
+ end
+end
+
+def fun_l16_n853(x)
+ if (x < 1)
+ fun_l17_n142(x)
+ else
+ fun_l17_n340(x)
+ end
+end
+
+def fun_l16_n854(x)
+ if (x < 1)
+ fun_l17_n793(x)
+ else
+ fun_l17_n226(x)
+ end
+end
+
+def fun_l16_n855(x)
+ if (x < 1)
+ fun_l17_n268(x)
+ else
+ fun_l17_n201(x)
+ end
+end
+
+def fun_l16_n856(x)
+ if (x < 1)
+ fun_l17_n52(x)
+ else
+ fun_l17_n871(x)
+ end
+end
+
+def fun_l16_n857(x)
+ if (x < 1)
+ fun_l17_n30(x)
+ else
+ fun_l17_n673(x)
+ end
+end
+
+def fun_l16_n858(x)
+ if (x < 1)
+ fun_l17_n794(x)
+ else
+ fun_l17_n839(x)
+ end
+end
+
+def fun_l16_n859(x)
+ if (x < 1)
+ fun_l17_n162(x)
+ else
+ fun_l17_n655(x)
+ end
+end
+
+def fun_l16_n860(x)
+ if (x < 1)
+ fun_l17_n770(x)
+ else
+ fun_l17_n879(x)
+ end
+end
+
+def fun_l16_n861(x)
+ if (x < 1)
+ fun_l17_n93(x)
+ else
+ fun_l17_n338(x)
+ end
+end
+
+def fun_l16_n862(x)
+ if (x < 1)
+ fun_l17_n468(x)
+ else
+ fun_l17_n977(x)
+ end
+end
+
+def fun_l16_n863(x)
+ if (x < 1)
+ fun_l17_n627(x)
+ else
+ fun_l17_n296(x)
+ end
+end
+
+def fun_l16_n864(x)
+ if (x < 1)
+ fun_l17_n402(x)
+ else
+ fun_l17_n515(x)
+ end
+end
+
+def fun_l16_n865(x)
+ if (x < 1)
+ fun_l17_n793(x)
+ else
+ fun_l17_n62(x)
+ end
+end
+
+def fun_l16_n866(x)
+ if (x < 1)
+ fun_l17_n87(x)
+ else
+ fun_l17_n532(x)
+ end
+end
+
+def fun_l16_n867(x)
+ if (x < 1)
+ fun_l17_n766(x)
+ else
+ fun_l17_n162(x)
+ end
+end
+
+def fun_l16_n868(x)
+ if (x < 1)
+ fun_l17_n214(x)
+ else
+ fun_l17_n827(x)
+ end
+end
+
+def fun_l16_n869(x)
+ if (x < 1)
+ fun_l17_n879(x)
+ else
+ fun_l17_n285(x)
+ end
+end
+
+def fun_l16_n870(x)
+ if (x < 1)
+ fun_l17_n619(x)
+ else
+ fun_l17_n648(x)
+ end
+end
+
+def fun_l16_n871(x)
+ if (x < 1)
+ fun_l17_n150(x)
+ else
+ fun_l17_n458(x)
+ end
+end
+
+def fun_l16_n872(x)
+ if (x < 1)
+ fun_l17_n346(x)
+ else
+ fun_l17_n824(x)
+ end
+end
+
+def fun_l16_n873(x)
+ if (x < 1)
+ fun_l17_n839(x)
+ else
+ fun_l17_n188(x)
+ end
+end
+
+def fun_l16_n874(x)
+ if (x < 1)
+ fun_l17_n202(x)
+ else
+ fun_l17_n147(x)
+ end
+end
+
+def fun_l16_n875(x)
+ if (x < 1)
+ fun_l17_n779(x)
+ else
+ fun_l17_n217(x)
+ end
+end
+
+def fun_l16_n876(x)
+ if (x < 1)
+ fun_l17_n417(x)
+ else
+ fun_l17_n350(x)
+ end
+end
+
+def fun_l16_n877(x)
+ if (x < 1)
+ fun_l17_n971(x)
+ else
+ fun_l17_n825(x)
+ end
+end
+
+def fun_l16_n878(x)
+ if (x < 1)
+ fun_l17_n843(x)
+ else
+ fun_l17_n431(x)
+ end
+end
+
+def fun_l16_n879(x)
+ if (x < 1)
+ fun_l17_n560(x)
+ else
+ fun_l17_n421(x)
+ end
+end
+
+def fun_l16_n880(x)
+ if (x < 1)
+ fun_l17_n399(x)
+ else
+ fun_l17_n101(x)
+ end
+end
+
+def fun_l16_n881(x)
+ if (x < 1)
+ fun_l17_n458(x)
+ else
+ fun_l17_n805(x)
+ end
+end
+
+def fun_l16_n882(x)
+ if (x < 1)
+ fun_l17_n590(x)
+ else
+ fun_l17_n924(x)
+ end
+end
+
+def fun_l16_n883(x)
+ if (x < 1)
+ fun_l17_n753(x)
+ else
+ fun_l17_n128(x)
+ end
+end
+
+def fun_l16_n884(x)
+ if (x < 1)
+ fun_l17_n271(x)
+ else
+ fun_l17_n366(x)
+ end
+end
+
+def fun_l16_n885(x)
+ if (x < 1)
+ fun_l17_n251(x)
+ else
+ fun_l17_n581(x)
+ end
+end
+
+def fun_l16_n886(x)
+ if (x < 1)
+ fun_l17_n82(x)
+ else
+ fun_l17_n212(x)
+ end
+end
+
+def fun_l16_n887(x)
+ if (x < 1)
+ fun_l17_n254(x)
+ else
+ fun_l17_n476(x)
+ end
+end
+
+def fun_l16_n888(x)
+ if (x < 1)
+ fun_l17_n774(x)
+ else
+ fun_l17_n23(x)
+ end
+end
+
+def fun_l16_n889(x)
+ if (x < 1)
+ fun_l17_n258(x)
+ else
+ fun_l17_n931(x)
+ end
+end
+
+def fun_l16_n890(x)
+ if (x < 1)
+ fun_l17_n60(x)
+ else
+ fun_l17_n267(x)
+ end
+end
+
+def fun_l16_n891(x)
+ if (x < 1)
+ fun_l17_n465(x)
+ else
+ fun_l17_n298(x)
+ end
+end
+
+def fun_l16_n892(x)
+ if (x < 1)
+ fun_l17_n284(x)
+ else
+ fun_l17_n59(x)
+ end
+end
+
+def fun_l16_n893(x)
+ if (x < 1)
+ fun_l17_n485(x)
+ else
+ fun_l17_n19(x)
+ end
+end
+
+def fun_l16_n894(x)
+ if (x < 1)
+ fun_l17_n676(x)
+ else
+ fun_l17_n196(x)
+ end
+end
+
+def fun_l16_n895(x)
+ if (x < 1)
+ fun_l17_n894(x)
+ else
+ fun_l17_n667(x)
+ end
+end
+
+def fun_l16_n896(x)
+ if (x < 1)
+ fun_l17_n234(x)
+ else
+ fun_l17_n115(x)
+ end
+end
+
+def fun_l16_n897(x)
+ if (x < 1)
+ fun_l17_n161(x)
+ else
+ fun_l17_n47(x)
+ end
+end
+
+def fun_l16_n898(x)
+ if (x < 1)
+ fun_l17_n598(x)
+ else
+ fun_l17_n796(x)
+ end
+end
+
+def fun_l16_n899(x)
+ if (x < 1)
+ fun_l17_n191(x)
+ else
+ fun_l17_n36(x)
+ end
+end
+
+def fun_l16_n900(x)
+ if (x < 1)
+ fun_l17_n803(x)
+ else
+ fun_l17_n894(x)
+ end
+end
+
+def fun_l16_n901(x)
+ if (x < 1)
+ fun_l17_n225(x)
+ else
+ fun_l17_n608(x)
+ end
+end
+
+def fun_l16_n902(x)
+ if (x < 1)
+ fun_l17_n318(x)
+ else
+ fun_l17_n667(x)
+ end
+end
+
+def fun_l16_n903(x)
+ if (x < 1)
+ fun_l17_n815(x)
+ else
+ fun_l17_n645(x)
+ end
+end
+
+def fun_l16_n904(x)
+ if (x < 1)
+ fun_l17_n891(x)
+ else
+ fun_l17_n465(x)
+ end
+end
+
+def fun_l16_n905(x)
+ if (x < 1)
+ fun_l17_n789(x)
+ else
+ fun_l17_n573(x)
+ end
+end
+
+def fun_l16_n906(x)
+ if (x < 1)
+ fun_l17_n139(x)
+ else
+ fun_l17_n745(x)
+ end
+end
+
+def fun_l16_n907(x)
+ if (x < 1)
+ fun_l17_n632(x)
+ else
+ fun_l17_n625(x)
+ end
+end
+
+def fun_l16_n908(x)
+ if (x < 1)
+ fun_l17_n249(x)
+ else
+ fun_l17_n279(x)
+ end
+end
+
+def fun_l16_n909(x)
+ if (x < 1)
+ fun_l17_n357(x)
+ else
+ fun_l17_n477(x)
+ end
+end
+
+def fun_l16_n910(x)
+ if (x < 1)
+ fun_l17_n796(x)
+ else
+ fun_l17_n313(x)
+ end
+end
+
+def fun_l16_n911(x)
+ if (x < 1)
+ fun_l17_n917(x)
+ else
+ fun_l17_n775(x)
+ end
+end
+
+def fun_l16_n912(x)
+ if (x < 1)
+ fun_l17_n451(x)
+ else
+ fun_l17_n102(x)
+ end
+end
+
+def fun_l16_n913(x)
+ if (x < 1)
+ fun_l17_n782(x)
+ else
+ fun_l17_n998(x)
+ end
+end
+
+def fun_l16_n914(x)
+ if (x < 1)
+ fun_l17_n237(x)
+ else
+ fun_l17_n586(x)
+ end
+end
+
+def fun_l16_n915(x)
+ if (x < 1)
+ fun_l17_n399(x)
+ else
+ fun_l17_n676(x)
+ end
+end
+
+def fun_l16_n916(x)
+ if (x < 1)
+ fun_l17_n65(x)
+ else
+ fun_l17_n61(x)
+ end
+end
+
+def fun_l16_n917(x)
+ if (x < 1)
+ fun_l17_n861(x)
+ else
+ fun_l17_n72(x)
+ end
+end
+
+def fun_l16_n918(x)
+ if (x < 1)
+ fun_l17_n375(x)
+ else
+ fun_l17_n446(x)
+ end
+end
+
+def fun_l16_n919(x)
+ if (x < 1)
+ fun_l17_n776(x)
+ else
+ fun_l17_n302(x)
+ end
+end
+
+def fun_l16_n920(x)
+ if (x < 1)
+ fun_l17_n216(x)
+ else
+ fun_l17_n804(x)
+ end
+end
+
+def fun_l16_n921(x)
+ if (x < 1)
+ fun_l17_n667(x)
+ else
+ fun_l17_n593(x)
+ end
+end
+
+def fun_l16_n922(x)
+ if (x < 1)
+ fun_l17_n499(x)
+ else
+ fun_l17_n577(x)
+ end
+end
+
+def fun_l16_n923(x)
+ if (x < 1)
+ fun_l17_n41(x)
+ else
+ fun_l17_n316(x)
+ end
+end
+
+def fun_l16_n924(x)
+ if (x < 1)
+ fun_l17_n521(x)
+ else
+ fun_l17_n86(x)
+ end
+end
+
+def fun_l16_n925(x)
+ if (x < 1)
+ fun_l17_n695(x)
+ else
+ fun_l17_n662(x)
+ end
+end
+
+def fun_l16_n926(x)
+ if (x < 1)
+ fun_l17_n379(x)
+ else
+ fun_l17_n58(x)
+ end
+end
+
+def fun_l16_n927(x)
+ if (x < 1)
+ fun_l17_n820(x)
+ else
+ fun_l17_n801(x)
+ end
+end
+
+def fun_l16_n928(x)
+ if (x < 1)
+ fun_l17_n175(x)
+ else
+ fun_l17_n865(x)
+ end
+end
+
+def fun_l16_n929(x)
+ if (x < 1)
+ fun_l17_n903(x)
+ else
+ fun_l17_n644(x)
+ end
+end
+
+def fun_l16_n930(x)
+ if (x < 1)
+ fun_l17_n801(x)
+ else
+ fun_l17_n265(x)
+ end
+end
+
+def fun_l16_n931(x)
+ if (x < 1)
+ fun_l17_n292(x)
+ else
+ fun_l17_n897(x)
+ end
+end
+
+def fun_l16_n932(x)
+ if (x < 1)
+ fun_l17_n666(x)
+ else
+ fun_l17_n531(x)
+ end
+end
+
+def fun_l16_n933(x)
+ if (x < 1)
+ fun_l17_n929(x)
+ else
+ fun_l17_n205(x)
+ end
+end
+
+def fun_l16_n934(x)
+ if (x < 1)
+ fun_l17_n557(x)
+ else
+ fun_l17_n70(x)
+ end
+end
+
+def fun_l16_n935(x)
+ if (x < 1)
+ fun_l17_n831(x)
+ else
+ fun_l17_n194(x)
+ end
+end
+
+def fun_l16_n936(x)
+ if (x < 1)
+ fun_l17_n277(x)
+ else
+ fun_l17_n786(x)
+ end
+end
+
+def fun_l16_n937(x)
+ if (x < 1)
+ fun_l17_n464(x)
+ else
+ fun_l17_n482(x)
+ end
+end
+
+def fun_l16_n938(x)
+ if (x < 1)
+ fun_l17_n782(x)
+ else
+ fun_l17_n60(x)
+ end
+end
+
+def fun_l16_n939(x)
+ if (x < 1)
+ fun_l17_n780(x)
+ else
+ fun_l17_n786(x)
+ end
+end
+
+def fun_l16_n940(x)
+ if (x < 1)
+ fun_l17_n201(x)
+ else
+ fun_l17_n614(x)
+ end
+end
+
+def fun_l16_n941(x)
+ if (x < 1)
+ fun_l17_n318(x)
+ else
+ fun_l17_n210(x)
+ end
+end
+
+def fun_l16_n942(x)
+ if (x < 1)
+ fun_l17_n831(x)
+ else
+ fun_l17_n293(x)
+ end
+end
+
+def fun_l16_n943(x)
+ if (x < 1)
+ fun_l17_n368(x)
+ else
+ fun_l17_n292(x)
+ end
+end
+
+def fun_l16_n944(x)
+ if (x < 1)
+ fun_l17_n924(x)
+ else
+ fun_l17_n20(x)
+ end
+end
+
+def fun_l16_n945(x)
+ if (x < 1)
+ fun_l17_n340(x)
+ else
+ fun_l17_n268(x)
+ end
+end
+
+def fun_l16_n946(x)
+ if (x < 1)
+ fun_l17_n913(x)
+ else
+ fun_l17_n877(x)
+ end
+end
+
+def fun_l16_n947(x)
+ if (x < 1)
+ fun_l17_n577(x)
+ else
+ fun_l17_n973(x)
+ end
+end
+
+def fun_l16_n948(x)
+ if (x < 1)
+ fun_l17_n101(x)
+ else
+ fun_l17_n350(x)
+ end
+end
+
+def fun_l16_n949(x)
+ if (x < 1)
+ fun_l17_n1(x)
+ else
+ fun_l17_n683(x)
+ end
+end
+
+def fun_l16_n950(x)
+ if (x < 1)
+ fun_l17_n290(x)
+ else
+ fun_l17_n30(x)
+ end
+end
+
+def fun_l16_n951(x)
+ if (x < 1)
+ fun_l17_n965(x)
+ else
+ fun_l17_n165(x)
+ end
+end
+
+def fun_l16_n952(x)
+ if (x < 1)
+ fun_l17_n532(x)
+ else
+ fun_l17_n887(x)
+ end
+end
+
+def fun_l16_n953(x)
+ if (x < 1)
+ fun_l17_n73(x)
+ else
+ fun_l17_n82(x)
+ end
+end
+
+def fun_l16_n954(x)
+ if (x < 1)
+ fun_l17_n518(x)
+ else
+ fun_l17_n886(x)
+ end
+end
+
+def fun_l16_n955(x)
+ if (x < 1)
+ fun_l17_n990(x)
+ else
+ fun_l17_n213(x)
+ end
+end
+
+def fun_l16_n956(x)
+ if (x < 1)
+ fun_l17_n489(x)
+ else
+ fun_l17_n937(x)
+ end
+end
+
+def fun_l16_n957(x)
+ if (x < 1)
+ fun_l17_n657(x)
+ else
+ fun_l17_n25(x)
+ end
+end
+
+def fun_l16_n958(x)
+ if (x < 1)
+ fun_l17_n988(x)
+ else
+ fun_l17_n684(x)
+ end
+end
+
+def fun_l16_n959(x)
+ if (x < 1)
+ fun_l17_n142(x)
+ else
+ fun_l17_n291(x)
+ end
+end
+
+def fun_l16_n960(x)
+ if (x < 1)
+ fun_l17_n495(x)
+ else
+ fun_l17_n806(x)
+ end
+end
+
+def fun_l16_n961(x)
+ if (x < 1)
+ fun_l17_n92(x)
+ else
+ fun_l17_n137(x)
+ end
+end
+
+def fun_l16_n962(x)
+ if (x < 1)
+ fun_l17_n954(x)
+ else
+ fun_l17_n943(x)
+ end
+end
+
+def fun_l16_n963(x)
+ if (x < 1)
+ fun_l17_n761(x)
+ else
+ fun_l17_n839(x)
+ end
+end
+
+def fun_l16_n964(x)
+ if (x < 1)
+ fun_l17_n591(x)
+ else
+ fun_l17_n519(x)
+ end
+end
+
+def fun_l16_n965(x)
+ if (x < 1)
+ fun_l17_n548(x)
+ else
+ fun_l17_n190(x)
+ end
+end
+
+def fun_l16_n966(x)
+ if (x < 1)
+ fun_l17_n206(x)
+ else
+ fun_l17_n491(x)
+ end
+end
+
+def fun_l16_n967(x)
+ if (x < 1)
+ fun_l17_n895(x)
+ else
+ fun_l17_n404(x)
+ end
+end
+
+def fun_l16_n968(x)
+ if (x < 1)
+ fun_l17_n284(x)
+ else
+ fun_l17_n715(x)
+ end
+end
+
+def fun_l16_n969(x)
+ if (x < 1)
+ fun_l17_n507(x)
+ else
+ fun_l17_n623(x)
+ end
+end
+
+def fun_l16_n970(x)
+ if (x < 1)
+ fun_l17_n415(x)
+ else
+ fun_l17_n718(x)
+ end
+end
+
+def fun_l16_n971(x)
+ if (x < 1)
+ fun_l17_n72(x)
+ else
+ fun_l17_n938(x)
+ end
+end
+
+def fun_l16_n972(x)
+ if (x < 1)
+ fun_l17_n661(x)
+ else
+ fun_l17_n525(x)
+ end
+end
+
+def fun_l16_n973(x)
+ if (x < 1)
+ fun_l17_n314(x)
+ else
+ fun_l17_n195(x)
+ end
+end
+
+def fun_l16_n974(x)
+ if (x < 1)
+ fun_l17_n53(x)
+ else
+ fun_l17_n562(x)
+ end
+end
+
+def fun_l16_n975(x)
+ if (x < 1)
+ fun_l17_n381(x)
+ else
+ fun_l17_n241(x)
+ end
+end
+
+def fun_l16_n976(x)
+ if (x < 1)
+ fun_l17_n919(x)
+ else
+ fun_l17_n291(x)
+ end
+end
+
+def fun_l16_n977(x)
+ if (x < 1)
+ fun_l17_n455(x)
+ else
+ fun_l17_n773(x)
+ end
+end
+
+def fun_l16_n978(x)
+ if (x < 1)
+ fun_l17_n75(x)
+ else
+ fun_l17_n737(x)
+ end
+end
+
+def fun_l16_n979(x)
+ if (x < 1)
+ fun_l17_n68(x)
+ else
+ fun_l17_n339(x)
+ end
+end
+
+def fun_l16_n980(x)
+ if (x < 1)
+ fun_l17_n719(x)
+ else
+ fun_l17_n464(x)
+ end
+end
+
+def fun_l16_n981(x)
+ if (x < 1)
+ fun_l17_n681(x)
+ else
+ fun_l17_n611(x)
+ end
+end
+
+def fun_l16_n982(x)
+ if (x < 1)
+ fun_l17_n367(x)
+ else
+ fun_l17_n446(x)
+ end
+end
+
+def fun_l16_n983(x)
+ if (x < 1)
+ fun_l17_n493(x)
+ else
+ fun_l17_n958(x)
+ end
+end
+
+def fun_l16_n984(x)
+ if (x < 1)
+ fun_l17_n271(x)
+ else
+ fun_l17_n982(x)
+ end
+end
+
+def fun_l16_n985(x)
+ if (x < 1)
+ fun_l17_n136(x)
+ else
+ fun_l17_n446(x)
+ end
+end
+
+def fun_l16_n986(x)
+ if (x < 1)
+ fun_l17_n362(x)
+ else
+ fun_l17_n114(x)
+ end
+end
+
+def fun_l16_n987(x)
+ if (x < 1)
+ fun_l17_n234(x)
+ else
+ fun_l17_n236(x)
+ end
+end
+
+def fun_l16_n988(x)
+ if (x < 1)
+ fun_l17_n339(x)
+ else
+ fun_l17_n2(x)
+ end
+end
+
+def fun_l16_n989(x)
+ if (x < 1)
+ fun_l17_n66(x)
+ else
+ fun_l17_n378(x)
+ end
+end
+
+def fun_l16_n990(x)
+ if (x < 1)
+ fun_l17_n366(x)
+ else
+ fun_l17_n289(x)
+ end
+end
+
+def fun_l16_n991(x)
+ if (x < 1)
+ fun_l17_n977(x)
+ else
+ fun_l17_n520(x)
+ end
+end
+
+def fun_l16_n992(x)
+ if (x < 1)
+ fun_l17_n953(x)
+ else
+ fun_l17_n254(x)
+ end
+end
+
+def fun_l16_n993(x)
+ if (x < 1)
+ fun_l17_n569(x)
+ else
+ fun_l17_n63(x)
+ end
+end
+
+def fun_l16_n994(x)
+ if (x < 1)
+ fun_l17_n844(x)
+ else
+ fun_l17_n42(x)
+ end
+end
+
+def fun_l16_n995(x)
+ if (x < 1)
+ fun_l17_n184(x)
+ else
+ fun_l17_n371(x)
+ end
+end
+
+def fun_l16_n996(x)
+ if (x < 1)
+ fun_l17_n229(x)
+ else
+ fun_l17_n309(x)
+ end
+end
+
+def fun_l16_n997(x)
+ if (x < 1)
+ fun_l17_n468(x)
+ else
+ fun_l17_n653(x)
+ end
+end
+
+def fun_l16_n998(x)
+ if (x < 1)
+ fun_l17_n173(x)
+ else
+ fun_l17_n709(x)
+ end
+end
+
+def fun_l16_n999(x)
+ if (x < 1)
+ fun_l17_n625(x)
+ else
+ fun_l17_n831(x)
+ end
+end
+
+def fun_l17_n0(x)
+ if (x < 1)
+ fun_l18_n495(x)
+ else
+ fun_l18_n122(x)
+ end
+end
+
+def fun_l17_n1(x)
+ if (x < 1)
+ fun_l18_n99(x)
+ else
+ fun_l18_n84(x)
+ end
+end
+
+def fun_l17_n2(x)
+ if (x < 1)
+ fun_l18_n464(x)
+ else
+ fun_l18_n321(x)
+ end
+end
+
+def fun_l17_n3(x)
+ if (x < 1)
+ fun_l18_n391(x)
+ else
+ fun_l18_n122(x)
+ end
+end
+
+def fun_l17_n4(x)
+ if (x < 1)
+ fun_l18_n65(x)
+ else
+ fun_l18_n514(x)
+ end
+end
+
+def fun_l17_n5(x)
+ if (x < 1)
+ fun_l18_n972(x)
+ else
+ fun_l18_n802(x)
+ end
+end
+
+def fun_l17_n6(x)
+ if (x < 1)
+ fun_l18_n577(x)
+ else
+ fun_l18_n26(x)
+ end
+end
+
+def fun_l17_n7(x)
+ if (x < 1)
+ fun_l18_n988(x)
+ else
+ fun_l18_n403(x)
+ end
+end
+
+def fun_l17_n8(x)
+ if (x < 1)
+ fun_l18_n466(x)
+ else
+ fun_l18_n162(x)
+ end
+end
+
+def fun_l17_n9(x)
+ if (x < 1)
+ fun_l18_n30(x)
+ else
+ fun_l18_n438(x)
+ end
+end
+
+def fun_l17_n10(x)
+ if (x < 1)
+ fun_l18_n92(x)
+ else
+ fun_l18_n365(x)
+ end
+end
+
+def fun_l17_n11(x)
+ if (x < 1)
+ fun_l18_n230(x)
+ else
+ fun_l18_n466(x)
+ end
+end
+
+def fun_l17_n12(x)
+ if (x < 1)
+ fun_l18_n274(x)
+ else
+ fun_l18_n38(x)
+ end
+end
+
+def fun_l17_n13(x)
+ if (x < 1)
+ fun_l18_n84(x)
+ else
+ fun_l18_n951(x)
+ end
+end
+
+def fun_l17_n14(x)
+ if (x < 1)
+ fun_l18_n878(x)
+ else
+ fun_l18_n981(x)
+ end
+end
+
+def fun_l17_n15(x)
+ if (x < 1)
+ fun_l18_n592(x)
+ else
+ fun_l18_n917(x)
+ end
+end
+
+def fun_l17_n16(x)
+ if (x < 1)
+ fun_l18_n524(x)
+ else
+ fun_l18_n812(x)
+ end
+end
+
+def fun_l17_n17(x)
+ if (x < 1)
+ fun_l18_n267(x)
+ else
+ fun_l18_n335(x)
+ end
+end
+
+def fun_l17_n18(x)
+ if (x < 1)
+ fun_l18_n427(x)
+ else
+ fun_l18_n591(x)
+ end
+end
+
+def fun_l17_n19(x)
+ if (x < 1)
+ fun_l18_n520(x)
+ else
+ fun_l18_n240(x)
+ end
+end
+
+def fun_l17_n20(x)
+ if (x < 1)
+ fun_l18_n729(x)
+ else
+ fun_l18_n709(x)
+ end
+end
+
+def fun_l17_n21(x)
+ if (x < 1)
+ fun_l18_n100(x)
+ else
+ fun_l18_n192(x)
+ end
+end
+
+def fun_l17_n22(x)
+ if (x < 1)
+ fun_l18_n762(x)
+ else
+ fun_l18_n373(x)
+ end
+end
+
+def fun_l17_n23(x)
+ if (x < 1)
+ fun_l18_n485(x)
+ else
+ fun_l18_n736(x)
+ end
+end
+
+def fun_l17_n24(x)
+ if (x < 1)
+ fun_l18_n743(x)
+ else
+ fun_l18_n83(x)
+ end
+end
+
+def fun_l17_n25(x)
+ if (x < 1)
+ fun_l18_n750(x)
+ else
+ fun_l18_n545(x)
+ end
+end
+
+def fun_l17_n26(x)
+ if (x < 1)
+ fun_l18_n488(x)
+ else
+ fun_l18_n870(x)
+ end
+end
+
+def fun_l17_n27(x)
+ if (x < 1)
+ fun_l18_n0(x)
+ else
+ fun_l18_n675(x)
+ end
+end
+
+def fun_l17_n28(x)
+ if (x < 1)
+ fun_l18_n878(x)
+ else
+ fun_l18_n32(x)
+ end
+end
+
+def fun_l17_n29(x)
+ if (x < 1)
+ fun_l18_n906(x)
+ else
+ fun_l18_n376(x)
+ end
+end
+
+def fun_l17_n30(x)
+ if (x < 1)
+ fun_l18_n182(x)
+ else
+ fun_l18_n58(x)
+ end
+end
+
+def fun_l17_n31(x)
+ if (x < 1)
+ fun_l18_n117(x)
+ else
+ fun_l18_n592(x)
+ end
+end
+
+def fun_l17_n32(x)
+ if (x < 1)
+ fun_l18_n123(x)
+ else
+ fun_l18_n697(x)
+ end
+end
+
+def fun_l17_n33(x)
+ if (x < 1)
+ fun_l18_n672(x)
+ else
+ fun_l18_n645(x)
+ end
+end
+
+def fun_l17_n34(x)
+ if (x < 1)
+ fun_l18_n640(x)
+ else
+ fun_l18_n280(x)
+ end
+end
+
+def fun_l17_n35(x)
+ if (x < 1)
+ fun_l18_n851(x)
+ else
+ fun_l18_n723(x)
+ end
+end
+
+def fun_l17_n36(x)
+ if (x < 1)
+ fun_l18_n968(x)
+ else
+ fun_l18_n840(x)
+ end
+end
+
+def fun_l17_n37(x)
+ if (x < 1)
+ fun_l18_n153(x)
+ else
+ fun_l18_n979(x)
+ end
+end
+
+def fun_l17_n38(x)
+ if (x < 1)
+ fun_l18_n817(x)
+ else
+ fun_l18_n521(x)
+ end
+end
+
+def fun_l17_n39(x)
+ if (x < 1)
+ fun_l18_n742(x)
+ else
+ fun_l18_n576(x)
+ end
+end
+
+def fun_l17_n40(x)
+ if (x < 1)
+ fun_l18_n5(x)
+ else
+ fun_l18_n998(x)
+ end
+end
+
+def fun_l17_n41(x)
+ if (x < 1)
+ fun_l18_n442(x)
+ else
+ fun_l18_n157(x)
+ end
+end
+
+def fun_l17_n42(x)
+ if (x < 1)
+ fun_l18_n832(x)
+ else
+ fun_l18_n218(x)
+ end
+end
+
+def fun_l17_n43(x)
+ if (x < 1)
+ fun_l18_n298(x)
+ else
+ fun_l18_n132(x)
+ end
+end
+
+def fun_l17_n44(x)
+ if (x < 1)
+ fun_l18_n397(x)
+ else
+ fun_l18_n375(x)
+ end
+end
+
+def fun_l17_n45(x)
+ if (x < 1)
+ fun_l18_n974(x)
+ else
+ fun_l18_n19(x)
+ end
+end
+
+def fun_l17_n46(x)
+ if (x < 1)
+ fun_l18_n340(x)
+ else
+ fun_l18_n506(x)
+ end
+end
+
+def fun_l17_n47(x)
+ if (x < 1)
+ fun_l18_n943(x)
+ else
+ fun_l18_n585(x)
+ end
+end
+
+def fun_l17_n48(x)
+ if (x < 1)
+ fun_l18_n756(x)
+ else
+ fun_l18_n2(x)
+ end
+end
+
+def fun_l17_n49(x)
+ if (x < 1)
+ fun_l18_n229(x)
+ else
+ fun_l18_n313(x)
+ end
+end
+
+def fun_l17_n50(x)
+ if (x < 1)
+ fun_l18_n243(x)
+ else
+ fun_l18_n562(x)
+ end
+end
+
+def fun_l17_n51(x)
+ if (x < 1)
+ fun_l18_n231(x)
+ else
+ fun_l18_n381(x)
+ end
+end
+
+def fun_l17_n52(x)
+ if (x < 1)
+ fun_l18_n509(x)
+ else
+ fun_l18_n693(x)
+ end
+end
+
+def fun_l17_n53(x)
+ if (x < 1)
+ fun_l18_n877(x)
+ else
+ fun_l18_n620(x)
+ end
+end
+
+def fun_l17_n54(x)
+ if (x < 1)
+ fun_l18_n435(x)
+ else
+ fun_l18_n3(x)
+ end
+end
+
+def fun_l17_n55(x)
+ if (x < 1)
+ fun_l18_n929(x)
+ else
+ fun_l18_n640(x)
+ end
+end
+
+def fun_l17_n56(x)
+ if (x < 1)
+ fun_l18_n913(x)
+ else
+ fun_l18_n374(x)
+ end
+end
+
+def fun_l17_n57(x)
+ if (x < 1)
+ fun_l18_n174(x)
+ else
+ fun_l18_n588(x)
+ end
+end
+
+def fun_l17_n58(x)
+ if (x < 1)
+ fun_l18_n339(x)
+ else
+ fun_l18_n860(x)
+ end
+end
+
+def fun_l17_n59(x)
+ if (x < 1)
+ fun_l18_n649(x)
+ else
+ fun_l18_n986(x)
+ end
+end
+
+def fun_l17_n60(x)
+ if (x < 1)
+ fun_l18_n326(x)
+ else
+ fun_l18_n739(x)
+ end
+end
+
+def fun_l17_n61(x)
+ if (x < 1)
+ fun_l18_n692(x)
+ else
+ fun_l18_n673(x)
+ end
+end
+
+def fun_l17_n62(x)
+ if (x < 1)
+ fun_l18_n515(x)
+ else
+ fun_l18_n951(x)
+ end
+end
+
+def fun_l17_n63(x)
+ if (x < 1)
+ fun_l18_n502(x)
+ else
+ fun_l18_n781(x)
+ end
+end
+
+def fun_l17_n64(x)
+ if (x < 1)
+ fun_l18_n833(x)
+ else
+ fun_l18_n235(x)
+ end
+end
+
+def fun_l17_n65(x)
+ if (x < 1)
+ fun_l18_n483(x)
+ else
+ fun_l18_n207(x)
+ end
+end
+
+def fun_l17_n66(x)
+ if (x < 1)
+ fun_l18_n292(x)
+ else
+ fun_l18_n916(x)
+ end
+end
+
+def fun_l17_n67(x)
+ if (x < 1)
+ fun_l18_n677(x)
+ else
+ fun_l18_n937(x)
+ end
+end
+
+def fun_l17_n68(x)
+ if (x < 1)
+ fun_l18_n733(x)
+ else
+ fun_l18_n426(x)
+ end
+end
+
+def fun_l17_n69(x)
+ if (x < 1)
+ fun_l18_n186(x)
+ else
+ fun_l18_n146(x)
+ end
+end
+
+def fun_l17_n70(x)
+ if (x < 1)
+ fun_l18_n493(x)
+ else
+ fun_l18_n418(x)
+ end
+end
+
+def fun_l17_n71(x)
+ if (x < 1)
+ fun_l18_n732(x)
+ else
+ fun_l18_n584(x)
+ end
+end
+
+def fun_l17_n72(x)
+ if (x < 1)
+ fun_l18_n774(x)
+ else
+ fun_l18_n349(x)
+ end
+end
+
+def fun_l17_n73(x)
+ if (x < 1)
+ fun_l18_n833(x)
+ else
+ fun_l18_n142(x)
+ end
+end
+
+def fun_l17_n74(x)
+ if (x < 1)
+ fun_l18_n506(x)
+ else
+ fun_l18_n882(x)
+ end
+end
+
+def fun_l17_n75(x)
+ if (x < 1)
+ fun_l18_n856(x)
+ else
+ fun_l18_n906(x)
+ end
+end
+
+def fun_l17_n76(x)
+ if (x < 1)
+ fun_l18_n172(x)
+ else
+ fun_l18_n426(x)
+ end
+end
+
+def fun_l17_n77(x)
+ if (x < 1)
+ fun_l18_n357(x)
+ else
+ fun_l18_n508(x)
+ end
+end
+
+def fun_l17_n78(x)
+ if (x < 1)
+ fun_l18_n25(x)
+ else
+ fun_l18_n899(x)
+ end
+end
+
+def fun_l17_n79(x)
+ if (x < 1)
+ fun_l18_n639(x)
+ else
+ fun_l18_n644(x)
+ end
+end
+
+def fun_l17_n80(x)
+ if (x < 1)
+ fun_l18_n207(x)
+ else
+ fun_l18_n193(x)
+ end
+end
+
+def fun_l17_n81(x)
+ if (x < 1)
+ fun_l18_n200(x)
+ else
+ fun_l18_n766(x)
+ end
+end
+
+def fun_l17_n82(x)
+ if (x < 1)
+ fun_l18_n815(x)
+ else
+ fun_l18_n533(x)
+ end
+end
+
+def fun_l17_n83(x)
+ if (x < 1)
+ fun_l18_n740(x)
+ else
+ fun_l18_n507(x)
+ end
+end
+
+def fun_l17_n84(x)
+ if (x < 1)
+ fun_l18_n484(x)
+ else
+ fun_l18_n158(x)
+ end
+end
+
+def fun_l17_n85(x)
+ if (x < 1)
+ fun_l18_n924(x)
+ else
+ fun_l18_n963(x)
+ end
+end
+
+def fun_l17_n86(x)
+ if (x < 1)
+ fun_l18_n614(x)
+ else
+ fun_l18_n806(x)
+ end
+end
+
+def fun_l17_n87(x)
+ if (x < 1)
+ fun_l18_n553(x)
+ else
+ fun_l18_n510(x)
+ end
+end
+
+def fun_l17_n88(x)
+ if (x < 1)
+ fun_l18_n561(x)
+ else
+ fun_l18_n860(x)
+ end
+end
+
+def fun_l17_n89(x)
+ if (x < 1)
+ fun_l18_n757(x)
+ else
+ fun_l18_n248(x)
+ end
+end
+
+def fun_l17_n90(x)
+ if (x < 1)
+ fun_l18_n616(x)
+ else
+ fun_l18_n217(x)
+ end
+end
+
+def fun_l17_n91(x)
+ if (x < 1)
+ fun_l18_n997(x)
+ else
+ fun_l18_n861(x)
+ end
+end
+
+def fun_l17_n92(x)
+ if (x < 1)
+ fun_l18_n18(x)
+ else
+ fun_l18_n457(x)
+ end
+end
+
+def fun_l17_n93(x)
+ if (x < 1)
+ fun_l18_n264(x)
+ else
+ fun_l18_n213(x)
+ end
+end
+
+def fun_l17_n94(x)
+ if (x < 1)
+ fun_l18_n352(x)
+ else
+ fun_l18_n304(x)
+ end
+end
+
+def fun_l17_n95(x)
+ if (x < 1)
+ fun_l18_n975(x)
+ else
+ fun_l18_n868(x)
+ end
+end
+
+def fun_l17_n96(x)
+ if (x < 1)
+ fun_l18_n859(x)
+ else
+ fun_l18_n786(x)
+ end
+end
+
+def fun_l17_n97(x)
+ if (x < 1)
+ fun_l18_n610(x)
+ else
+ fun_l18_n423(x)
+ end
+end
+
+def fun_l17_n98(x)
+ if (x < 1)
+ fun_l18_n814(x)
+ else
+ fun_l18_n71(x)
+ end
+end
+
+def fun_l17_n99(x)
+ if (x < 1)
+ fun_l18_n897(x)
+ else
+ fun_l18_n412(x)
+ end
+end
+
+def fun_l17_n100(x)
+ if (x < 1)
+ fun_l18_n654(x)
+ else
+ fun_l18_n600(x)
+ end
+end
+
+def fun_l17_n101(x)
+ if (x < 1)
+ fun_l18_n185(x)
+ else
+ fun_l18_n188(x)
+ end
+end
+
+def fun_l17_n102(x)
+ if (x < 1)
+ fun_l18_n262(x)
+ else
+ fun_l18_n509(x)
+ end
+end
+
+def fun_l17_n103(x)
+ if (x < 1)
+ fun_l18_n115(x)
+ else
+ fun_l18_n497(x)
+ end
+end
+
+def fun_l17_n104(x)
+ if (x < 1)
+ fun_l18_n650(x)
+ else
+ fun_l18_n389(x)
+ end
+end
+
+def fun_l17_n105(x)
+ if (x < 1)
+ fun_l18_n939(x)
+ else
+ fun_l18_n842(x)
+ end
+end
+
+def fun_l17_n106(x)
+ if (x < 1)
+ fun_l18_n645(x)
+ else
+ fun_l18_n34(x)
+ end
+end
+
+def fun_l17_n107(x)
+ if (x < 1)
+ fun_l18_n510(x)
+ else
+ fun_l18_n313(x)
+ end
+end
+
+def fun_l17_n108(x)
+ if (x < 1)
+ fun_l18_n377(x)
+ else
+ fun_l18_n397(x)
+ end
+end
+
+def fun_l17_n109(x)
+ if (x < 1)
+ fun_l18_n884(x)
+ else
+ fun_l18_n380(x)
+ end
+end
+
+def fun_l17_n110(x)
+ if (x < 1)
+ fun_l18_n924(x)
+ else
+ fun_l18_n102(x)
+ end
+end
+
+def fun_l17_n111(x)
+ if (x < 1)
+ fun_l18_n856(x)
+ else
+ fun_l18_n646(x)
+ end
+end
+
+def fun_l17_n112(x)
+ if (x < 1)
+ fun_l18_n270(x)
+ else
+ fun_l18_n345(x)
+ end
+end
+
+def fun_l17_n113(x)
+ if (x < 1)
+ fun_l18_n211(x)
+ else
+ fun_l18_n672(x)
+ end
+end
+
+def fun_l17_n114(x)
+ if (x < 1)
+ fun_l18_n947(x)
+ else
+ fun_l18_n376(x)
+ end
+end
+
+def fun_l17_n115(x)
+ if (x < 1)
+ fun_l18_n219(x)
+ else
+ fun_l18_n927(x)
+ end
+end
+
+def fun_l17_n116(x)
+ if (x < 1)
+ fun_l18_n731(x)
+ else
+ fun_l18_n327(x)
+ end
+end
+
+def fun_l17_n117(x)
+ if (x < 1)
+ fun_l18_n512(x)
+ else
+ fun_l18_n658(x)
+ end
+end
+
+def fun_l17_n118(x)
+ if (x < 1)
+ fun_l18_n248(x)
+ else
+ fun_l18_n661(x)
+ end
+end
+
+def fun_l17_n119(x)
+ if (x < 1)
+ fun_l18_n18(x)
+ else
+ fun_l18_n56(x)
+ end
+end
+
+def fun_l17_n120(x)
+ if (x < 1)
+ fun_l18_n441(x)
+ else
+ fun_l18_n648(x)
+ end
+end
+
+def fun_l17_n121(x)
+ if (x < 1)
+ fun_l18_n122(x)
+ else
+ fun_l18_n717(x)
+ end
+end
+
+def fun_l17_n122(x)
+ if (x < 1)
+ fun_l18_n495(x)
+ else
+ fun_l18_n30(x)
+ end
+end
+
+def fun_l17_n123(x)
+ if (x < 1)
+ fun_l18_n418(x)
+ else
+ fun_l18_n686(x)
+ end
+end
+
+def fun_l17_n124(x)
+ if (x < 1)
+ fun_l18_n274(x)
+ else
+ fun_l18_n300(x)
+ end
+end
+
+def fun_l17_n125(x)
+ if (x < 1)
+ fun_l18_n677(x)
+ else
+ fun_l18_n662(x)
+ end
+end
+
+def fun_l17_n126(x)
+ if (x < 1)
+ fun_l18_n448(x)
+ else
+ fun_l18_n584(x)
+ end
+end
+
+def fun_l17_n127(x)
+ if (x < 1)
+ fun_l18_n316(x)
+ else
+ fun_l18_n507(x)
+ end
+end
+
+def fun_l17_n128(x)
+ if (x < 1)
+ fun_l18_n166(x)
+ else
+ fun_l18_n266(x)
+ end
+end
+
+def fun_l17_n129(x)
+ if (x < 1)
+ fun_l18_n890(x)
+ else
+ fun_l18_n581(x)
+ end
+end
+
+def fun_l17_n130(x)
+ if (x < 1)
+ fun_l18_n554(x)
+ else
+ fun_l18_n925(x)
+ end
+end
+
+def fun_l17_n131(x)
+ if (x < 1)
+ fun_l18_n607(x)
+ else
+ fun_l18_n43(x)
+ end
+end
+
+def fun_l17_n132(x)
+ if (x < 1)
+ fun_l18_n747(x)
+ else
+ fun_l18_n461(x)
+ end
+end
+
+def fun_l17_n133(x)
+ if (x < 1)
+ fun_l18_n399(x)
+ else
+ fun_l18_n436(x)
+ end
+end
+
+def fun_l17_n134(x)
+ if (x < 1)
+ fun_l18_n922(x)
+ else
+ fun_l18_n33(x)
+ end
+end
+
+def fun_l17_n135(x)
+ if (x < 1)
+ fun_l18_n719(x)
+ else
+ fun_l18_n70(x)
+ end
+end
+
+def fun_l17_n136(x)
+ if (x < 1)
+ fun_l18_n664(x)
+ else
+ fun_l18_n842(x)
+ end
+end
+
+def fun_l17_n137(x)
+ if (x < 1)
+ fun_l18_n626(x)
+ else
+ fun_l18_n328(x)
+ end
+end
+
+def fun_l17_n138(x)
+ if (x < 1)
+ fun_l18_n64(x)
+ else
+ fun_l18_n24(x)
+ end
+end
+
+def fun_l17_n139(x)
+ if (x < 1)
+ fun_l18_n198(x)
+ else
+ fun_l18_n658(x)
+ end
+end
+
+def fun_l17_n140(x)
+ if (x < 1)
+ fun_l18_n813(x)
+ else
+ fun_l18_n5(x)
+ end
+end
+
+def fun_l17_n141(x)
+ if (x < 1)
+ fun_l18_n8(x)
+ else
+ fun_l18_n115(x)
+ end
+end
+
+def fun_l17_n142(x)
+ if (x < 1)
+ fun_l18_n699(x)
+ else
+ fun_l18_n135(x)
+ end
+end
+
+def fun_l17_n143(x)
+ if (x < 1)
+ fun_l18_n595(x)
+ else
+ fun_l18_n607(x)
+ end
+end
+
+def fun_l17_n144(x)
+ if (x < 1)
+ fun_l18_n650(x)
+ else
+ fun_l18_n994(x)
+ end
+end
+
+def fun_l17_n145(x)
+ if (x < 1)
+ fun_l18_n14(x)
+ else
+ fun_l18_n798(x)
+ end
+end
+
+def fun_l17_n146(x)
+ if (x < 1)
+ fun_l18_n107(x)
+ else
+ fun_l18_n144(x)
+ end
+end
+
+def fun_l17_n147(x)
+ if (x < 1)
+ fun_l18_n923(x)
+ else
+ fun_l18_n482(x)
+ end
+end
+
+def fun_l17_n148(x)
+ if (x < 1)
+ fun_l18_n629(x)
+ else
+ fun_l18_n224(x)
+ end
+end
+
+def fun_l17_n149(x)
+ if (x < 1)
+ fun_l18_n363(x)
+ else
+ fun_l18_n958(x)
+ end
+end
+
+def fun_l17_n150(x)
+ if (x < 1)
+ fun_l18_n143(x)
+ else
+ fun_l18_n828(x)
+ end
+end
+
+def fun_l17_n151(x)
+ if (x < 1)
+ fun_l18_n615(x)
+ else
+ fun_l18_n561(x)
+ end
+end
+
+def fun_l17_n152(x)
+ if (x < 1)
+ fun_l18_n418(x)
+ else
+ fun_l18_n46(x)
+ end
+end
+
+def fun_l17_n153(x)
+ if (x < 1)
+ fun_l18_n331(x)
+ else
+ fun_l18_n736(x)
+ end
+end
+
+def fun_l17_n154(x)
+ if (x < 1)
+ fun_l18_n340(x)
+ else
+ fun_l18_n221(x)
+ end
+end
+
+def fun_l17_n155(x)
+ if (x < 1)
+ fun_l18_n488(x)
+ else
+ fun_l18_n995(x)
+ end
+end
+
+def fun_l17_n156(x)
+ if (x < 1)
+ fun_l18_n500(x)
+ else
+ fun_l18_n106(x)
+ end
+end
+
+def fun_l17_n157(x)
+ if (x < 1)
+ fun_l18_n76(x)
+ else
+ fun_l18_n147(x)
+ end
+end
+
+def fun_l17_n158(x)
+ if (x < 1)
+ fun_l18_n258(x)
+ else
+ fun_l18_n754(x)
+ end
+end
+
+def fun_l17_n159(x)
+ if (x < 1)
+ fun_l18_n174(x)
+ else
+ fun_l18_n676(x)
+ end
+end
+
+def fun_l17_n160(x)
+ if (x < 1)
+ fun_l18_n997(x)
+ else
+ fun_l18_n662(x)
+ end
+end
+
+def fun_l17_n161(x)
+ if (x < 1)
+ fun_l18_n614(x)
+ else
+ fun_l18_n425(x)
+ end
+end
+
+def fun_l17_n162(x)
+ if (x < 1)
+ fun_l18_n943(x)
+ else
+ fun_l18_n534(x)
+ end
+end
+
+def fun_l17_n163(x)
+ if (x < 1)
+ fun_l18_n577(x)
+ else
+ fun_l18_n670(x)
+ end
+end
+
+def fun_l17_n164(x)
+ if (x < 1)
+ fun_l18_n707(x)
+ else
+ fun_l18_n701(x)
+ end
+end
+
+def fun_l17_n165(x)
+ if (x < 1)
+ fun_l18_n316(x)
+ else
+ fun_l18_n981(x)
+ end
+end
+
+def fun_l17_n166(x)
+ if (x < 1)
+ fun_l18_n557(x)
+ else
+ fun_l18_n710(x)
+ end
+end
+
+def fun_l17_n167(x)
+ if (x < 1)
+ fun_l18_n763(x)
+ else
+ fun_l18_n900(x)
+ end
+end
+
+def fun_l17_n168(x)
+ if (x < 1)
+ fun_l18_n818(x)
+ else
+ fun_l18_n2(x)
+ end
+end
+
+def fun_l17_n169(x)
+ if (x < 1)
+ fun_l18_n68(x)
+ else
+ fun_l18_n894(x)
+ end
+end
+
+def fun_l17_n170(x)
+ if (x < 1)
+ fun_l18_n88(x)
+ else
+ fun_l18_n431(x)
+ end
+end
+
+def fun_l17_n171(x)
+ if (x < 1)
+ fun_l18_n530(x)
+ else
+ fun_l18_n714(x)
+ end
+end
+
+def fun_l17_n172(x)
+ if (x < 1)
+ fun_l18_n636(x)
+ else
+ fun_l18_n747(x)
+ end
+end
+
+def fun_l17_n173(x)
+ if (x < 1)
+ fun_l18_n481(x)
+ else
+ fun_l18_n804(x)
+ end
+end
+
+def fun_l17_n174(x)
+ if (x < 1)
+ fun_l18_n591(x)
+ else
+ fun_l18_n121(x)
+ end
+end
+
+def fun_l17_n175(x)
+ if (x < 1)
+ fun_l18_n320(x)
+ else
+ fun_l18_n881(x)
+ end
+end
+
+def fun_l17_n176(x)
+ if (x < 1)
+ fun_l18_n524(x)
+ else
+ fun_l18_n948(x)
+ end
+end
+
+def fun_l17_n177(x)
+ if (x < 1)
+ fun_l18_n540(x)
+ else
+ fun_l18_n508(x)
+ end
+end
+
+def fun_l17_n178(x)
+ if (x < 1)
+ fun_l18_n949(x)
+ else
+ fun_l18_n492(x)
+ end
+end
+
+def fun_l17_n179(x)
+ if (x < 1)
+ fun_l18_n548(x)
+ else
+ fun_l18_n534(x)
+ end
+end
+
+def fun_l17_n180(x)
+ if (x < 1)
+ fun_l18_n591(x)
+ else
+ fun_l18_n104(x)
+ end
+end
+
+def fun_l17_n181(x)
+ if (x < 1)
+ fun_l18_n727(x)
+ else
+ fun_l18_n144(x)
+ end
+end
+
+def fun_l17_n182(x)
+ if (x < 1)
+ fun_l18_n365(x)
+ else
+ fun_l18_n628(x)
+ end
+end
+
+def fun_l17_n183(x)
+ if (x < 1)
+ fun_l18_n32(x)
+ else
+ fun_l18_n752(x)
+ end
+end
+
+def fun_l17_n184(x)
+ if (x < 1)
+ fun_l18_n778(x)
+ else
+ fun_l18_n929(x)
+ end
+end
+
+def fun_l17_n185(x)
+ if (x < 1)
+ fun_l18_n797(x)
+ else
+ fun_l18_n525(x)
+ end
+end
+
+def fun_l17_n186(x)
+ if (x < 1)
+ fun_l18_n800(x)
+ else
+ fun_l18_n799(x)
+ end
+end
+
+def fun_l17_n187(x)
+ if (x < 1)
+ fun_l18_n974(x)
+ else
+ fun_l18_n982(x)
+ end
+end
+
+def fun_l17_n188(x)
+ if (x < 1)
+ fun_l18_n259(x)
+ else
+ fun_l18_n465(x)
+ end
+end
+
+def fun_l17_n189(x)
+ if (x < 1)
+ fun_l18_n905(x)
+ else
+ fun_l18_n477(x)
+ end
+end
+
+def fun_l17_n190(x)
+ if (x < 1)
+ fun_l18_n453(x)
+ else
+ fun_l18_n894(x)
+ end
+end
+
+def fun_l17_n191(x)
+ if (x < 1)
+ fun_l18_n461(x)
+ else
+ fun_l18_n251(x)
+ end
+end
+
+def fun_l17_n192(x)
+ if (x < 1)
+ fun_l18_n377(x)
+ else
+ fun_l18_n371(x)
+ end
+end
+
+def fun_l17_n193(x)
+ if (x < 1)
+ fun_l18_n252(x)
+ else
+ fun_l18_n493(x)
+ end
+end
+
+def fun_l17_n194(x)
+ if (x < 1)
+ fun_l18_n398(x)
+ else
+ fun_l18_n104(x)
+ end
+end
+
+def fun_l17_n195(x)
+ if (x < 1)
+ fun_l18_n791(x)
+ else
+ fun_l18_n4(x)
+ end
+end
+
+def fun_l17_n196(x)
+ if (x < 1)
+ fun_l18_n801(x)
+ else
+ fun_l18_n429(x)
+ end
+end
+
+def fun_l17_n197(x)
+ if (x < 1)
+ fun_l18_n106(x)
+ else
+ fun_l18_n622(x)
+ end
+end
+
+def fun_l17_n198(x)
+ if (x < 1)
+ fun_l18_n581(x)
+ else
+ fun_l18_n312(x)
+ end
+end
+
+def fun_l17_n199(x)
+ if (x < 1)
+ fun_l18_n142(x)
+ else
+ fun_l18_n296(x)
+ end
+end
+
+def fun_l17_n200(x)
+ if (x < 1)
+ fun_l18_n234(x)
+ else
+ fun_l18_n185(x)
+ end
+end
+
+def fun_l17_n201(x)
+ if (x < 1)
+ fun_l18_n486(x)
+ else
+ fun_l18_n857(x)
+ end
+end
+
+def fun_l17_n202(x)
+ if (x < 1)
+ fun_l18_n84(x)
+ else
+ fun_l18_n718(x)
+ end
+end
+
+def fun_l17_n203(x)
+ if (x < 1)
+ fun_l18_n830(x)
+ else
+ fun_l18_n618(x)
+ end
+end
+
+def fun_l17_n204(x)
+ if (x < 1)
+ fun_l18_n860(x)
+ else
+ fun_l18_n28(x)
+ end
+end
+
+def fun_l17_n205(x)
+ if (x < 1)
+ fun_l18_n244(x)
+ else
+ fun_l18_n575(x)
+ end
+end
+
+def fun_l17_n206(x)
+ if (x < 1)
+ fun_l18_n189(x)
+ else
+ fun_l18_n722(x)
+ end
+end
+
+def fun_l17_n207(x)
+ if (x < 1)
+ fun_l18_n164(x)
+ else
+ fun_l18_n197(x)
+ end
+end
+
+def fun_l17_n208(x)
+ if (x < 1)
+ fun_l18_n109(x)
+ else
+ fun_l18_n392(x)
+ end
+end
+
+def fun_l17_n209(x)
+ if (x < 1)
+ fun_l18_n629(x)
+ else
+ fun_l18_n290(x)
+ end
+end
+
+def fun_l17_n210(x)
+ if (x < 1)
+ fun_l18_n637(x)
+ else
+ fun_l18_n317(x)
+ end
+end
+
+def fun_l17_n211(x)
+ if (x < 1)
+ fun_l18_n148(x)
+ else
+ fun_l18_n702(x)
+ end
+end
+
+def fun_l17_n212(x)
+ if (x < 1)
+ fun_l18_n892(x)
+ else
+ fun_l18_n395(x)
+ end
+end
+
+def fun_l17_n213(x)
+ if (x < 1)
+ fun_l18_n457(x)
+ else
+ fun_l18_n859(x)
+ end
+end
+
+def fun_l17_n214(x)
+ if (x < 1)
+ fun_l18_n561(x)
+ else
+ fun_l18_n295(x)
+ end
+end
+
+def fun_l17_n215(x)
+ if (x < 1)
+ fun_l18_n459(x)
+ else
+ fun_l18_n407(x)
+ end
+end
+
+def fun_l17_n216(x)
+ if (x < 1)
+ fun_l18_n761(x)
+ else
+ fun_l18_n308(x)
+ end
+end
+
+def fun_l17_n217(x)
+ if (x < 1)
+ fun_l18_n350(x)
+ else
+ fun_l18_n680(x)
+ end
+end
+
+def fun_l17_n218(x)
+ if (x < 1)
+ fun_l18_n240(x)
+ else
+ fun_l18_n119(x)
+ end
+end
+
+def fun_l17_n219(x)
+ if (x < 1)
+ fun_l18_n538(x)
+ else
+ fun_l18_n732(x)
+ end
+end
+
+def fun_l17_n220(x)
+ if (x < 1)
+ fun_l18_n45(x)
+ else
+ fun_l18_n643(x)
+ end
+end
+
+def fun_l17_n221(x)
+ if (x < 1)
+ fun_l18_n258(x)
+ else
+ fun_l18_n690(x)
+ end
+end
+
+def fun_l17_n222(x)
+ if (x < 1)
+ fun_l18_n288(x)
+ else
+ fun_l18_n998(x)
+ end
+end
+
+def fun_l17_n223(x)
+ if (x < 1)
+ fun_l18_n591(x)
+ else
+ fun_l18_n278(x)
+ end
+end
+
+def fun_l17_n224(x)
+ if (x < 1)
+ fun_l18_n433(x)
+ else
+ fun_l18_n852(x)
+ end
+end
+
+def fun_l17_n225(x)
+ if (x < 1)
+ fun_l18_n51(x)
+ else
+ fun_l18_n837(x)
+ end
+end
+
+def fun_l17_n226(x)
+ if (x < 1)
+ fun_l18_n755(x)
+ else
+ fun_l18_n949(x)
+ end
+end
+
+def fun_l17_n227(x)
+ if (x < 1)
+ fun_l18_n566(x)
+ else
+ fun_l18_n754(x)
+ end
+end
+
+def fun_l17_n228(x)
+ if (x < 1)
+ fun_l18_n915(x)
+ else
+ fun_l18_n893(x)
+ end
+end
+
+def fun_l17_n229(x)
+ if (x < 1)
+ fun_l18_n990(x)
+ else
+ fun_l18_n208(x)
+ end
+end
+
+def fun_l17_n230(x)
+ if (x < 1)
+ fun_l18_n220(x)
+ else
+ fun_l18_n292(x)
+ end
+end
+
+def fun_l17_n231(x)
+ if (x < 1)
+ fun_l18_n39(x)
+ else
+ fun_l18_n211(x)
+ end
+end
+
+def fun_l17_n232(x)
+ if (x < 1)
+ fun_l18_n669(x)
+ else
+ fun_l18_n818(x)
+ end
+end
+
+def fun_l17_n233(x)
+ if (x < 1)
+ fun_l18_n804(x)
+ else
+ fun_l18_n400(x)
+ end
+end
+
+def fun_l17_n234(x)
+ if (x < 1)
+ fun_l18_n198(x)
+ else
+ fun_l18_n393(x)
+ end
+end
+
+def fun_l17_n235(x)
+ if (x < 1)
+ fun_l18_n154(x)
+ else
+ fun_l18_n980(x)
+ end
+end
+
+def fun_l17_n236(x)
+ if (x < 1)
+ fun_l18_n46(x)
+ else
+ fun_l18_n926(x)
+ end
+end
+
+def fun_l17_n237(x)
+ if (x < 1)
+ fun_l18_n158(x)
+ else
+ fun_l18_n364(x)
+ end
+end
+
+def fun_l17_n238(x)
+ if (x < 1)
+ fun_l18_n728(x)
+ else
+ fun_l18_n864(x)
+ end
+end
+
+def fun_l17_n239(x)
+ if (x < 1)
+ fun_l18_n793(x)
+ else
+ fun_l18_n985(x)
+ end
+end
+
+def fun_l17_n240(x)
+ if (x < 1)
+ fun_l18_n619(x)
+ else
+ fun_l18_n216(x)
+ end
+end
+
+def fun_l17_n241(x)
+ if (x < 1)
+ fun_l18_n338(x)
+ else
+ fun_l18_n289(x)
+ end
+end
+
+def fun_l17_n242(x)
+ if (x < 1)
+ fun_l18_n42(x)
+ else
+ fun_l18_n360(x)
+ end
+end
+
+def fun_l17_n243(x)
+ if (x < 1)
+ fun_l18_n883(x)
+ else
+ fun_l18_n243(x)
+ end
+end
+
+def fun_l17_n244(x)
+ if (x < 1)
+ fun_l18_n474(x)
+ else
+ fun_l18_n236(x)
+ end
+end
+
+def fun_l17_n245(x)
+ if (x < 1)
+ fun_l18_n694(x)
+ else
+ fun_l18_n579(x)
+ end
+end
+
+def fun_l17_n246(x)
+ if (x < 1)
+ fun_l18_n787(x)
+ else
+ fun_l18_n349(x)
+ end
+end
+
+def fun_l17_n247(x)
+ if (x < 1)
+ fun_l18_n140(x)
+ else
+ fun_l18_n894(x)
+ end
+end
+
+def fun_l17_n248(x)
+ if (x < 1)
+ fun_l18_n587(x)
+ else
+ fun_l18_n19(x)
+ end
+end
+
+def fun_l17_n249(x)
+ if (x < 1)
+ fun_l18_n7(x)
+ else
+ fun_l18_n352(x)
+ end
+end
+
+def fun_l17_n250(x)
+ if (x < 1)
+ fun_l18_n330(x)
+ else
+ fun_l18_n779(x)
+ end
+end
+
+def fun_l17_n251(x)
+ if (x < 1)
+ fun_l18_n655(x)
+ else
+ fun_l18_n45(x)
+ end
+end
+
+def fun_l17_n252(x)
+ if (x < 1)
+ fun_l18_n263(x)
+ else
+ fun_l18_n668(x)
+ end
+end
+
+def fun_l17_n253(x)
+ if (x < 1)
+ fun_l18_n799(x)
+ else
+ fun_l18_n141(x)
+ end
+end
+
+def fun_l17_n254(x)
+ if (x < 1)
+ fun_l18_n868(x)
+ else
+ fun_l18_n486(x)
+ end
+end
+
+def fun_l17_n255(x)
+ if (x < 1)
+ fun_l18_n238(x)
+ else
+ fun_l18_n298(x)
+ end
+end
+
+def fun_l17_n256(x)
+ if (x < 1)
+ fun_l18_n939(x)
+ else
+ fun_l18_n977(x)
+ end
+end
+
+def fun_l17_n257(x)
+ if (x < 1)
+ fun_l18_n999(x)
+ else
+ fun_l18_n241(x)
+ end
+end
+
+def fun_l17_n258(x)
+ if (x < 1)
+ fun_l18_n362(x)
+ else
+ fun_l18_n19(x)
+ end
+end
+
+def fun_l17_n259(x)
+ if (x < 1)
+ fun_l18_n166(x)
+ else
+ fun_l18_n550(x)
+ end
+end
+
+def fun_l17_n260(x)
+ if (x < 1)
+ fun_l18_n18(x)
+ else
+ fun_l18_n453(x)
+ end
+end
+
+def fun_l17_n261(x)
+ if (x < 1)
+ fun_l18_n590(x)
+ else
+ fun_l18_n217(x)
+ end
+end
+
+def fun_l17_n262(x)
+ if (x < 1)
+ fun_l18_n703(x)
+ else
+ fun_l18_n827(x)
+ end
+end
+
+def fun_l17_n263(x)
+ if (x < 1)
+ fun_l18_n911(x)
+ else
+ fun_l18_n869(x)
+ end
+end
+
+def fun_l17_n264(x)
+ if (x < 1)
+ fun_l18_n980(x)
+ else
+ fun_l18_n598(x)
+ end
+end
+
+def fun_l17_n265(x)
+ if (x < 1)
+ fun_l18_n751(x)
+ else
+ fun_l18_n298(x)
+ end
+end
+
+def fun_l17_n266(x)
+ if (x < 1)
+ fun_l18_n527(x)
+ else
+ fun_l18_n392(x)
+ end
+end
+
+def fun_l17_n267(x)
+ if (x < 1)
+ fun_l18_n257(x)
+ else
+ fun_l18_n731(x)
+ end
+end
+
+def fun_l17_n268(x)
+ if (x < 1)
+ fun_l18_n254(x)
+ else
+ fun_l18_n188(x)
+ end
+end
+
+def fun_l17_n269(x)
+ if (x < 1)
+ fun_l18_n145(x)
+ else
+ fun_l18_n987(x)
+ end
+end
+
+def fun_l17_n270(x)
+ if (x < 1)
+ fun_l18_n640(x)
+ else
+ fun_l18_n370(x)
+ end
+end
+
+def fun_l17_n271(x)
+ if (x < 1)
+ fun_l18_n767(x)
+ else
+ fun_l18_n246(x)
+ end
+end
+
+def fun_l17_n272(x)
+ if (x < 1)
+ fun_l18_n274(x)
+ else
+ fun_l18_n851(x)
+ end
+end
+
+def fun_l17_n273(x)
+ if (x < 1)
+ fun_l18_n12(x)
+ else
+ fun_l18_n48(x)
+ end
+end
+
+def fun_l17_n274(x)
+ if (x < 1)
+ fun_l18_n389(x)
+ else
+ fun_l18_n353(x)
+ end
+end
+
+def fun_l17_n275(x)
+ if (x < 1)
+ fun_l18_n966(x)
+ else
+ fun_l18_n248(x)
+ end
+end
+
+def fun_l17_n276(x)
+ if (x < 1)
+ fun_l18_n459(x)
+ else
+ fun_l18_n989(x)
+ end
+end
+
+def fun_l17_n277(x)
+ if (x < 1)
+ fun_l18_n416(x)
+ else
+ fun_l18_n976(x)
+ end
+end
+
+def fun_l17_n278(x)
+ if (x < 1)
+ fun_l18_n752(x)
+ else
+ fun_l18_n282(x)
+ end
+end
+
+def fun_l17_n279(x)
+ if (x < 1)
+ fun_l18_n774(x)
+ else
+ fun_l18_n478(x)
+ end
+end
+
+def fun_l17_n280(x)
+ if (x < 1)
+ fun_l18_n713(x)
+ else
+ fun_l18_n117(x)
+ end
+end
+
+def fun_l17_n281(x)
+ if (x < 1)
+ fun_l18_n365(x)
+ else
+ fun_l18_n932(x)
+ end
+end
+
+def fun_l17_n282(x)
+ if (x < 1)
+ fun_l18_n791(x)
+ else
+ fun_l18_n331(x)
+ end
+end
+
+def fun_l17_n283(x)
+ if (x < 1)
+ fun_l18_n955(x)
+ else
+ fun_l18_n847(x)
+ end
+end
+
+def fun_l17_n284(x)
+ if (x < 1)
+ fun_l18_n409(x)
+ else
+ fun_l18_n681(x)
+ end
+end
+
+def fun_l17_n285(x)
+ if (x < 1)
+ fun_l18_n185(x)
+ else
+ fun_l18_n651(x)
+ end
+end
+
+def fun_l17_n286(x)
+ if (x < 1)
+ fun_l18_n894(x)
+ else
+ fun_l18_n827(x)
+ end
+end
+
+def fun_l17_n287(x)
+ if (x < 1)
+ fun_l18_n788(x)
+ else
+ fun_l18_n794(x)
+ end
+end
+
+def fun_l17_n288(x)
+ if (x < 1)
+ fun_l18_n361(x)
+ else
+ fun_l18_n415(x)
+ end
+end
+
+def fun_l17_n289(x)
+ if (x < 1)
+ fun_l18_n357(x)
+ else
+ fun_l18_n375(x)
+ end
+end
+
+def fun_l17_n290(x)
+ if (x < 1)
+ fun_l18_n557(x)
+ else
+ fun_l18_n85(x)
+ end
+end
+
+def fun_l17_n291(x)
+ if (x < 1)
+ fun_l18_n490(x)
+ else
+ fun_l18_n260(x)
+ end
+end
+
+def fun_l17_n292(x)
+ if (x < 1)
+ fun_l18_n21(x)
+ else
+ fun_l18_n497(x)
+ end
+end
+
+def fun_l17_n293(x)
+ if (x < 1)
+ fun_l18_n716(x)
+ else
+ fun_l18_n94(x)
+ end
+end
+
+def fun_l17_n294(x)
+ if (x < 1)
+ fun_l18_n462(x)
+ else
+ fun_l18_n408(x)
+ end
+end
+
+def fun_l17_n295(x)
+ if (x < 1)
+ fun_l18_n87(x)
+ else
+ fun_l18_n732(x)
+ end
+end
+
+def fun_l17_n296(x)
+ if (x < 1)
+ fun_l18_n889(x)
+ else
+ fun_l18_n755(x)
+ end
+end
+
+def fun_l17_n297(x)
+ if (x < 1)
+ fun_l18_n539(x)
+ else
+ fun_l18_n130(x)
+ end
+end
+
+def fun_l17_n298(x)
+ if (x < 1)
+ fun_l18_n729(x)
+ else
+ fun_l18_n861(x)
+ end
+end
+
+def fun_l17_n299(x)
+ if (x < 1)
+ fun_l18_n605(x)
+ else
+ fun_l18_n408(x)
+ end
+end
+
+def fun_l17_n300(x)
+ if (x < 1)
+ fun_l18_n408(x)
+ else
+ fun_l18_n281(x)
+ end
+end
+
+def fun_l17_n301(x)
+ if (x < 1)
+ fun_l18_n793(x)
+ else
+ fun_l18_n188(x)
+ end
+end
+
+def fun_l17_n302(x)
+ if (x < 1)
+ fun_l18_n42(x)
+ else
+ fun_l18_n970(x)
+ end
+end
+
+def fun_l17_n303(x)
+ if (x < 1)
+ fun_l18_n904(x)
+ else
+ fun_l18_n630(x)
+ end
+end
+
+def fun_l17_n304(x)
+ if (x < 1)
+ fun_l18_n142(x)
+ else
+ fun_l18_n366(x)
+ end
+end
+
+def fun_l17_n305(x)
+ if (x < 1)
+ fun_l18_n242(x)
+ else
+ fun_l18_n111(x)
+ end
+end
+
+def fun_l17_n306(x)
+ if (x < 1)
+ fun_l18_n184(x)
+ else
+ fun_l18_n301(x)
+ end
+end
+
+def fun_l17_n307(x)
+ if (x < 1)
+ fun_l18_n297(x)
+ else
+ fun_l18_n722(x)
+ end
+end
+
+def fun_l17_n308(x)
+ if (x < 1)
+ fun_l18_n608(x)
+ else
+ fun_l18_n502(x)
+ end
+end
+
+def fun_l17_n309(x)
+ if (x < 1)
+ fun_l18_n513(x)
+ else
+ fun_l18_n828(x)
+ end
+end
+
+def fun_l17_n310(x)
+ if (x < 1)
+ fun_l18_n5(x)
+ else
+ fun_l18_n638(x)
+ end
+end
+
+def fun_l17_n311(x)
+ if (x < 1)
+ fun_l18_n404(x)
+ else
+ fun_l18_n510(x)
+ end
+end
+
+def fun_l17_n312(x)
+ if (x < 1)
+ fun_l18_n961(x)
+ else
+ fun_l18_n526(x)
+ end
+end
+
+def fun_l17_n313(x)
+ if (x < 1)
+ fun_l18_n795(x)
+ else
+ fun_l18_n24(x)
+ end
+end
+
+def fun_l17_n314(x)
+ if (x < 1)
+ fun_l18_n505(x)
+ else
+ fun_l18_n526(x)
+ end
+end
+
+def fun_l17_n315(x)
+ if (x < 1)
+ fun_l18_n458(x)
+ else
+ fun_l18_n767(x)
+ end
+end
+
+def fun_l17_n316(x)
+ if (x < 1)
+ fun_l18_n778(x)
+ else
+ fun_l18_n972(x)
+ end
+end
+
+def fun_l17_n317(x)
+ if (x < 1)
+ fun_l18_n734(x)
+ else
+ fun_l18_n289(x)
+ end
+end
+
+def fun_l17_n318(x)
+ if (x < 1)
+ fun_l18_n950(x)
+ else
+ fun_l18_n507(x)
+ end
+end
+
+def fun_l17_n319(x)
+ if (x < 1)
+ fun_l18_n597(x)
+ else
+ fun_l18_n697(x)
+ end
+end
+
+def fun_l17_n320(x)
+ if (x < 1)
+ fun_l18_n270(x)
+ else
+ fun_l18_n323(x)
+ end
+end
+
+def fun_l17_n321(x)
+ if (x < 1)
+ fun_l18_n558(x)
+ else
+ fun_l18_n357(x)
+ end
+end
+
+def fun_l17_n322(x)
+ if (x < 1)
+ fun_l18_n948(x)
+ else
+ fun_l18_n726(x)
+ end
+end
+
+def fun_l17_n323(x)
+ if (x < 1)
+ fun_l18_n787(x)
+ else
+ fun_l18_n89(x)
+ end
+end
+
+def fun_l17_n324(x)
+ if (x < 1)
+ fun_l18_n894(x)
+ else
+ fun_l18_n454(x)
+ end
+end
+
+def fun_l17_n325(x)
+ if (x < 1)
+ fun_l18_n173(x)
+ else
+ fun_l18_n815(x)
+ end
+end
+
+def fun_l17_n326(x)
+ if (x < 1)
+ fun_l18_n102(x)
+ else
+ fun_l18_n261(x)
+ end
+end
+
+def fun_l17_n327(x)
+ if (x < 1)
+ fun_l18_n83(x)
+ else
+ fun_l18_n732(x)
+ end
+end
+
+def fun_l17_n328(x)
+ if (x < 1)
+ fun_l18_n675(x)
+ else
+ fun_l18_n186(x)
+ end
+end
+
+def fun_l17_n329(x)
+ if (x < 1)
+ fun_l18_n783(x)
+ else
+ fun_l18_n481(x)
+ end
+end
+
+def fun_l17_n330(x)
+ if (x < 1)
+ fun_l18_n828(x)
+ else
+ fun_l18_n829(x)
+ end
+end
+
+def fun_l17_n331(x)
+ if (x < 1)
+ fun_l18_n195(x)
+ else
+ fun_l18_n264(x)
+ end
+end
+
+def fun_l17_n332(x)
+ if (x < 1)
+ fun_l18_n842(x)
+ else
+ fun_l18_n198(x)
+ end
+end
+
+def fun_l17_n333(x)
+ if (x < 1)
+ fun_l18_n549(x)
+ else
+ fun_l18_n208(x)
+ end
+end
+
+def fun_l17_n334(x)
+ if (x < 1)
+ fun_l18_n976(x)
+ else
+ fun_l18_n316(x)
+ end
+end
+
+def fun_l17_n335(x)
+ if (x < 1)
+ fun_l18_n401(x)
+ else
+ fun_l18_n105(x)
+ end
+end
+
+def fun_l17_n336(x)
+ if (x < 1)
+ fun_l18_n357(x)
+ else
+ fun_l18_n54(x)
+ end
+end
+
+def fun_l17_n337(x)
+ if (x < 1)
+ fun_l18_n685(x)
+ else
+ fun_l18_n140(x)
+ end
+end
+
+def fun_l17_n338(x)
+ if (x < 1)
+ fun_l18_n301(x)
+ else
+ fun_l18_n167(x)
+ end
+end
+
+def fun_l17_n339(x)
+ if (x < 1)
+ fun_l18_n398(x)
+ else
+ fun_l18_n643(x)
+ end
+end
+
+def fun_l17_n340(x)
+ if (x < 1)
+ fun_l18_n147(x)
+ else
+ fun_l18_n27(x)
+ end
+end
+
+def fun_l17_n341(x)
+ if (x < 1)
+ fun_l18_n813(x)
+ else
+ fun_l18_n935(x)
+ end
+end
+
+def fun_l17_n342(x)
+ if (x < 1)
+ fun_l18_n319(x)
+ else
+ fun_l18_n429(x)
+ end
+end
+
+def fun_l17_n343(x)
+ if (x < 1)
+ fun_l18_n957(x)
+ else
+ fun_l18_n961(x)
+ end
+end
+
+def fun_l17_n344(x)
+ if (x < 1)
+ fun_l18_n380(x)
+ else
+ fun_l18_n604(x)
+ end
+end
+
+def fun_l17_n345(x)
+ if (x < 1)
+ fun_l18_n321(x)
+ else
+ fun_l18_n473(x)
+ end
+end
+
+def fun_l17_n346(x)
+ if (x < 1)
+ fun_l18_n346(x)
+ else
+ fun_l18_n752(x)
+ end
+end
+
+def fun_l17_n347(x)
+ if (x < 1)
+ fun_l18_n645(x)
+ else
+ fun_l18_n511(x)
+ end
+end
+
+def fun_l17_n348(x)
+ if (x < 1)
+ fun_l18_n647(x)
+ else
+ fun_l18_n997(x)
+ end
+end
+
+def fun_l17_n349(x)
+ if (x < 1)
+ fun_l18_n291(x)
+ else
+ fun_l18_n580(x)
+ end
+end
+
+def fun_l17_n350(x)
+ if (x < 1)
+ fun_l18_n745(x)
+ else
+ fun_l18_n402(x)
+ end
+end
+
+def fun_l17_n351(x)
+ if (x < 1)
+ fun_l18_n533(x)
+ else
+ fun_l18_n117(x)
+ end
+end
+
+def fun_l17_n352(x)
+ if (x < 1)
+ fun_l18_n490(x)
+ else
+ fun_l18_n458(x)
+ end
+end
+
+def fun_l17_n353(x)
+ if (x < 1)
+ fun_l18_n526(x)
+ else
+ fun_l18_n311(x)
+ end
+end
+
+def fun_l17_n354(x)
+ if (x < 1)
+ fun_l18_n315(x)
+ else
+ fun_l18_n306(x)
+ end
+end
+
+def fun_l17_n355(x)
+ if (x < 1)
+ fun_l18_n349(x)
+ else
+ fun_l18_n975(x)
+ end
+end
+
+def fun_l17_n356(x)
+ if (x < 1)
+ fun_l18_n764(x)
+ else
+ fun_l18_n897(x)
+ end
+end
+
+def fun_l17_n357(x)
+ if (x < 1)
+ fun_l18_n308(x)
+ else
+ fun_l18_n662(x)
+ end
+end
+
+def fun_l17_n358(x)
+ if (x < 1)
+ fun_l18_n7(x)
+ else
+ fun_l18_n807(x)
+ end
+end
+
+def fun_l17_n359(x)
+ if (x < 1)
+ fun_l18_n896(x)
+ else
+ fun_l18_n277(x)
+ end
+end
+
+def fun_l17_n360(x)
+ if (x < 1)
+ fun_l18_n606(x)
+ else
+ fun_l18_n605(x)
+ end
+end
+
+def fun_l17_n361(x)
+ if (x < 1)
+ fun_l18_n971(x)
+ else
+ fun_l18_n59(x)
+ end
+end
+
+def fun_l17_n362(x)
+ if (x < 1)
+ fun_l18_n304(x)
+ else
+ fun_l18_n604(x)
+ end
+end
+
+def fun_l17_n363(x)
+ if (x < 1)
+ fun_l18_n607(x)
+ else
+ fun_l18_n758(x)
+ end
+end
+
+def fun_l17_n364(x)
+ if (x < 1)
+ fun_l18_n454(x)
+ else
+ fun_l18_n635(x)
+ end
+end
+
+def fun_l17_n365(x)
+ if (x < 1)
+ fun_l18_n287(x)
+ else
+ fun_l18_n979(x)
+ end
+end
+
+def fun_l17_n366(x)
+ if (x < 1)
+ fun_l18_n708(x)
+ else
+ fun_l18_n480(x)
+ end
+end
+
+def fun_l17_n367(x)
+ if (x < 1)
+ fun_l18_n925(x)
+ else
+ fun_l18_n96(x)
+ end
+end
+
+def fun_l17_n368(x)
+ if (x < 1)
+ fun_l18_n756(x)
+ else
+ fun_l18_n765(x)
+ end
+end
+
+def fun_l17_n369(x)
+ if (x < 1)
+ fun_l18_n134(x)
+ else
+ fun_l18_n320(x)
+ end
+end
+
+def fun_l17_n370(x)
+ if (x < 1)
+ fun_l18_n167(x)
+ else
+ fun_l18_n112(x)
+ end
+end
+
+def fun_l17_n371(x)
+ if (x < 1)
+ fun_l18_n393(x)
+ else
+ fun_l18_n701(x)
+ end
+end
+
+def fun_l17_n372(x)
+ if (x < 1)
+ fun_l18_n363(x)
+ else
+ fun_l18_n934(x)
+ end
+end
+
+def fun_l17_n373(x)
+ if (x < 1)
+ fun_l18_n431(x)
+ else
+ fun_l18_n343(x)
+ end
+end
+
+def fun_l17_n374(x)
+ if (x < 1)
+ fun_l18_n111(x)
+ else
+ fun_l18_n689(x)
+ end
+end
+
+def fun_l17_n375(x)
+ if (x < 1)
+ fun_l18_n609(x)
+ else
+ fun_l18_n814(x)
+ end
+end
+
+def fun_l17_n376(x)
+ if (x < 1)
+ fun_l18_n9(x)
+ else
+ fun_l18_n711(x)
+ end
+end
+
+def fun_l17_n377(x)
+ if (x < 1)
+ fun_l18_n270(x)
+ else
+ fun_l18_n455(x)
+ end
+end
+
+def fun_l17_n378(x)
+ if (x < 1)
+ fun_l18_n432(x)
+ else
+ fun_l18_n348(x)
+ end
+end
+
+def fun_l17_n379(x)
+ if (x < 1)
+ fun_l18_n646(x)
+ else
+ fun_l18_n934(x)
+ end
+end
+
+def fun_l17_n380(x)
+ if (x < 1)
+ fun_l18_n737(x)
+ else
+ fun_l18_n472(x)
+ end
+end
+
+def fun_l17_n381(x)
+ if (x < 1)
+ fun_l18_n163(x)
+ else
+ fun_l18_n533(x)
+ end
+end
+
+def fun_l17_n382(x)
+ if (x < 1)
+ fun_l18_n71(x)
+ else
+ fun_l18_n343(x)
+ end
+end
+
+def fun_l17_n383(x)
+ if (x < 1)
+ fun_l18_n52(x)
+ else
+ fun_l18_n0(x)
+ end
+end
+
+def fun_l17_n384(x)
+ if (x < 1)
+ fun_l18_n708(x)
+ else
+ fun_l18_n616(x)
+ end
+end
+
+def fun_l17_n385(x)
+ if (x < 1)
+ fun_l18_n525(x)
+ else
+ fun_l18_n818(x)
+ end
+end
+
+def fun_l17_n386(x)
+ if (x < 1)
+ fun_l18_n154(x)
+ else
+ fun_l18_n588(x)
+ end
+end
+
+def fun_l17_n387(x)
+ if (x < 1)
+ fun_l18_n295(x)
+ else
+ fun_l18_n462(x)
+ end
+end
+
+def fun_l17_n388(x)
+ if (x < 1)
+ fun_l18_n331(x)
+ else
+ fun_l18_n773(x)
+ end
+end
+
+def fun_l17_n389(x)
+ if (x < 1)
+ fun_l18_n221(x)
+ else
+ fun_l18_n168(x)
+ end
+end
+
+def fun_l17_n390(x)
+ if (x < 1)
+ fun_l18_n575(x)
+ else
+ fun_l18_n284(x)
+ end
+end
+
+def fun_l17_n391(x)
+ if (x < 1)
+ fun_l18_n936(x)
+ else
+ fun_l18_n71(x)
+ end
+end
+
+def fun_l17_n392(x)
+ if (x < 1)
+ fun_l18_n123(x)
+ else
+ fun_l18_n863(x)
+ end
+end
+
+def fun_l17_n393(x)
+ if (x < 1)
+ fun_l18_n664(x)
+ else
+ fun_l18_n189(x)
+ end
+end
+
+def fun_l17_n394(x)
+ if (x < 1)
+ fun_l18_n456(x)
+ else
+ fun_l18_n476(x)
+ end
+end
+
+def fun_l17_n395(x)
+ if (x < 1)
+ fun_l18_n557(x)
+ else
+ fun_l18_n877(x)
+ end
+end
+
+def fun_l17_n396(x)
+ if (x < 1)
+ fun_l18_n192(x)
+ else
+ fun_l18_n312(x)
+ end
+end
+
+def fun_l17_n397(x)
+ if (x < 1)
+ fun_l18_n87(x)
+ else
+ fun_l18_n56(x)
+ end
+end
+
+def fun_l17_n398(x)
+ if (x < 1)
+ fun_l18_n769(x)
+ else
+ fun_l18_n597(x)
+ end
+end
+
+def fun_l17_n399(x)
+ if (x < 1)
+ fun_l18_n534(x)
+ else
+ fun_l18_n366(x)
+ end
+end
+
+def fun_l17_n400(x)
+ if (x < 1)
+ fun_l18_n284(x)
+ else
+ fun_l18_n503(x)
+ end
+end
+
+def fun_l17_n401(x)
+ if (x < 1)
+ fun_l18_n655(x)
+ else
+ fun_l18_n242(x)
+ end
+end
+
+def fun_l17_n402(x)
+ if (x < 1)
+ fun_l18_n491(x)
+ else
+ fun_l18_n81(x)
+ end
+end
+
+def fun_l17_n403(x)
+ if (x < 1)
+ fun_l18_n861(x)
+ else
+ fun_l18_n372(x)
+ end
+end
+
+def fun_l17_n404(x)
+ if (x < 1)
+ fun_l18_n600(x)
+ else
+ fun_l18_n692(x)
+ end
+end
+
+def fun_l17_n405(x)
+ if (x < 1)
+ fun_l18_n336(x)
+ else
+ fun_l18_n778(x)
+ end
+end
+
+def fun_l17_n406(x)
+ if (x < 1)
+ fun_l18_n224(x)
+ else
+ fun_l18_n277(x)
+ end
+end
+
+def fun_l17_n407(x)
+ if (x < 1)
+ fun_l18_n630(x)
+ else
+ fun_l18_n861(x)
+ end
+end
+
+def fun_l17_n408(x)
+ if (x < 1)
+ fun_l18_n829(x)
+ else
+ fun_l18_n213(x)
+ end
+end
+
+def fun_l17_n409(x)
+ if (x < 1)
+ fun_l18_n325(x)
+ else
+ fun_l18_n599(x)
+ end
+end
+
+def fun_l17_n410(x)
+ if (x < 1)
+ fun_l18_n850(x)
+ else
+ fun_l18_n828(x)
+ end
+end
+
+def fun_l17_n411(x)
+ if (x < 1)
+ fun_l18_n557(x)
+ else
+ fun_l18_n757(x)
+ end
+end
+
+def fun_l17_n412(x)
+ if (x < 1)
+ fun_l18_n755(x)
+ else
+ fun_l18_n474(x)
+ end
+end
+
+def fun_l17_n413(x)
+ if (x < 1)
+ fun_l18_n945(x)
+ else
+ fun_l18_n113(x)
+ end
+end
+
+def fun_l17_n414(x)
+ if (x < 1)
+ fun_l18_n584(x)
+ else
+ fun_l18_n815(x)
+ end
+end
+
+def fun_l17_n415(x)
+ if (x < 1)
+ fun_l18_n136(x)
+ else
+ fun_l18_n997(x)
+ end
+end
+
+def fun_l17_n416(x)
+ if (x < 1)
+ fun_l18_n57(x)
+ else
+ fun_l18_n361(x)
+ end
+end
+
+def fun_l17_n417(x)
+ if (x < 1)
+ fun_l18_n3(x)
+ else
+ fun_l18_n882(x)
+ end
+end
+
+def fun_l17_n418(x)
+ if (x < 1)
+ fun_l18_n578(x)
+ else
+ fun_l18_n719(x)
+ end
+end
+
+def fun_l17_n419(x)
+ if (x < 1)
+ fun_l18_n426(x)
+ else
+ fun_l18_n958(x)
+ end
+end
+
+def fun_l17_n420(x)
+ if (x < 1)
+ fun_l18_n384(x)
+ else
+ fun_l18_n182(x)
+ end
+end
+
+def fun_l17_n421(x)
+ if (x < 1)
+ fun_l18_n458(x)
+ else
+ fun_l18_n314(x)
+ end
+end
+
+def fun_l17_n422(x)
+ if (x < 1)
+ fun_l18_n641(x)
+ else
+ fun_l18_n678(x)
+ end
+end
+
+def fun_l17_n423(x)
+ if (x < 1)
+ fun_l18_n790(x)
+ else
+ fun_l18_n830(x)
+ end
+end
+
+def fun_l17_n424(x)
+ if (x < 1)
+ fun_l18_n207(x)
+ else
+ fun_l18_n686(x)
+ end
+end
+
+def fun_l17_n425(x)
+ if (x < 1)
+ fun_l18_n847(x)
+ else
+ fun_l18_n387(x)
+ end
+end
+
+def fun_l17_n426(x)
+ if (x < 1)
+ fun_l18_n744(x)
+ else
+ fun_l18_n9(x)
+ end
+end
+
+def fun_l17_n427(x)
+ if (x < 1)
+ fun_l18_n446(x)
+ else
+ fun_l18_n533(x)
+ end
+end
+
+def fun_l17_n428(x)
+ if (x < 1)
+ fun_l18_n910(x)
+ else
+ fun_l18_n749(x)
+ end
+end
+
+def fun_l17_n429(x)
+ if (x < 1)
+ fun_l18_n918(x)
+ else
+ fun_l18_n260(x)
+ end
+end
+
+def fun_l17_n430(x)
+ if (x < 1)
+ fun_l18_n812(x)
+ else
+ fun_l18_n545(x)
+ end
+end
+
+def fun_l17_n431(x)
+ if (x < 1)
+ fun_l18_n191(x)
+ else
+ fun_l18_n260(x)
+ end
+end
+
+def fun_l17_n432(x)
+ if (x < 1)
+ fun_l18_n155(x)
+ else
+ fun_l18_n582(x)
+ end
+end
+
+def fun_l17_n433(x)
+ if (x < 1)
+ fun_l18_n374(x)
+ else
+ fun_l18_n991(x)
+ end
+end
+
+def fun_l17_n434(x)
+ if (x < 1)
+ fun_l18_n611(x)
+ else
+ fun_l18_n334(x)
+ end
+end
+
+def fun_l17_n435(x)
+ if (x < 1)
+ fun_l18_n876(x)
+ else
+ fun_l18_n386(x)
+ end
+end
+
+def fun_l17_n436(x)
+ if (x < 1)
+ fun_l18_n985(x)
+ else
+ fun_l18_n874(x)
+ end
+end
+
+def fun_l17_n437(x)
+ if (x < 1)
+ fun_l18_n715(x)
+ else
+ fun_l18_n52(x)
+ end
+end
+
+def fun_l17_n438(x)
+ if (x < 1)
+ fun_l18_n53(x)
+ else
+ fun_l18_n15(x)
+ end
+end
+
+def fun_l17_n439(x)
+ if (x < 1)
+ fun_l18_n689(x)
+ else
+ fun_l18_n498(x)
+ end
+end
+
+def fun_l17_n440(x)
+ if (x < 1)
+ fun_l18_n990(x)
+ else
+ fun_l18_n70(x)
+ end
+end
+
+def fun_l17_n441(x)
+ if (x < 1)
+ fun_l18_n369(x)
+ else
+ fun_l18_n327(x)
+ end
+end
+
+def fun_l17_n442(x)
+ if (x < 1)
+ fun_l18_n157(x)
+ else
+ fun_l18_n917(x)
+ end
+end
+
+def fun_l17_n443(x)
+ if (x < 1)
+ fun_l18_n822(x)
+ else
+ fun_l18_n472(x)
+ end
+end
+
+def fun_l17_n444(x)
+ if (x < 1)
+ fun_l18_n465(x)
+ else
+ fun_l18_n19(x)
+ end
+end
+
+def fun_l17_n445(x)
+ if (x < 1)
+ fun_l18_n543(x)
+ else
+ fun_l18_n499(x)
+ end
+end
+
+def fun_l17_n446(x)
+ if (x < 1)
+ fun_l18_n662(x)
+ else
+ fun_l18_n531(x)
+ end
+end
+
+def fun_l17_n447(x)
+ if (x < 1)
+ fun_l18_n452(x)
+ else
+ fun_l18_n150(x)
+ end
+end
+
+def fun_l17_n448(x)
+ if (x < 1)
+ fun_l18_n438(x)
+ else
+ fun_l18_n552(x)
+ end
+end
+
+def fun_l17_n449(x)
+ if (x < 1)
+ fun_l18_n23(x)
+ else
+ fun_l18_n89(x)
+ end
+end
+
+def fun_l17_n450(x)
+ if (x < 1)
+ fun_l18_n896(x)
+ else
+ fun_l18_n313(x)
+ end
+end
+
+def fun_l17_n451(x)
+ if (x < 1)
+ fun_l18_n221(x)
+ else
+ fun_l18_n622(x)
+ end
+end
+
+def fun_l17_n452(x)
+ if (x < 1)
+ fun_l18_n347(x)
+ else
+ fun_l18_n43(x)
+ end
+end
+
+def fun_l17_n453(x)
+ if (x < 1)
+ fun_l18_n695(x)
+ else
+ fun_l18_n5(x)
+ end
+end
+
+def fun_l17_n454(x)
+ if (x < 1)
+ fun_l18_n829(x)
+ else
+ fun_l18_n409(x)
+ end
+end
+
+def fun_l17_n455(x)
+ if (x < 1)
+ fun_l18_n398(x)
+ else
+ fun_l18_n906(x)
+ end
+end
+
+def fun_l17_n456(x)
+ if (x < 1)
+ fun_l18_n983(x)
+ else
+ fun_l18_n235(x)
+ end
+end
+
+def fun_l17_n457(x)
+ if (x < 1)
+ fun_l18_n542(x)
+ else
+ fun_l18_n819(x)
+ end
+end
+
+def fun_l17_n458(x)
+ if (x < 1)
+ fun_l18_n952(x)
+ else
+ fun_l18_n123(x)
+ end
+end
+
+def fun_l17_n459(x)
+ if (x < 1)
+ fun_l18_n249(x)
+ else
+ fun_l18_n525(x)
+ end
+end
+
+def fun_l17_n460(x)
+ if (x < 1)
+ fun_l18_n833(x)
+ else
+ fun_l18_n657(x)
+ end
+end
+
+def fun_l17_n461(x)
+ if (x < 1)
+ fun_l18_n847(x)
+ else
+ fun_l18_n396(x)
+ end
+end
+
+def fun_l17_n462(x)
+ if (x < 1)
+ fun_l18_n611(x)
+ else
+ fun_l18_n790(x)
+ end
+end
+
+def fun_l17_n463(x)
+ if (x < 1)
+ fun_l18_n944(x)
+ else
+ fun_l18_n655(x)
+ end
+end
+
+def fun_l17_n464(x)
+ if (x < 1)
+ fun_l18_n688(x)
+ else
+ fun_l18_n804(x)
+ end
+end
+
+def fun_l17_n465(x)
+ if (x < 1)
+ fun_l18_n29(x)
+ else
+ fun_l18_n324(x)
+ end
+end
+
+def fun_l17_n466(x)
+ if (x < 1)
+ fun_l18_n496(x)
+ else
+ fun_l18_n76(x)
+ end
+end
+
+def fun_l17_n467(x)
+ if (x < 1)
+ fun_l18_n317(x)
+ else
+ fun_l18_n241(x)
+ end
+end
+
+def fun_l17_n468(x)
+ if (x < 1)
+ fun_l18_n759(x)
+ else
+ fun_l18_n516(x)
+ end
+end
+
+def fun_l17_n469(x)
+ if (x < 1)
+ fun_l18_n430(x)
+ else
+ fun_l18_n355(x)
+ end
+end
+
+def fun_l17_n470(x)
+ if (x < 1)
+ fun_l18_n683(x)
+ else
+ fun_l18_n16(x)
+ end
+end
+
+def fun_l17_n471(x)
+ if (x < 1)
+ fun_l18_n46(x)
+ else
+ fun_l18_n216(x)
+ end
+end
+
+def fun_l17_n472(x)
+ if (x < 1)
+ fun_l18_n460(x)
+ else
+ fun_l18_n460(x)
+ end
+end
+
+def fun_l17_n473(x)
+ if (x < 1)
+ fun_l18_n120(x)
+ else
+ fun_l18_n189(x)
+ end
+end
+
+def fun_l17_n474(x)
+ if (x < 1)
+ fun_l18_n663(x)
+ else
+ fun_l18_n732(x)
+ end
+end
+
+def fun_l17_n475(x)
+ if (x < 1)
+ fun_l18_n441(x)
+ else
+ fun_l18_n460(x)
+ end
+end
+
+def fun_l17_n476(x)
+ if (x < 1)
+ fun_l18_n759(x)
+ else
+ fun_l18_n533(x)
+ end
+end
+
+def fun_l17_n477(x)
+ if (x < 1)
+ fun_l18_n105(x)
+ else
+ fun_l18_n671(x)
+ end
+end
+
+def fun_l17_n478(x)
+ if (x < 1)
+ fun_l18_n849(x)
+ else
+ fun_l18_n316(x)
+ end
+end
+
+def fun_l17_n479(x)
+ if (x < 1)
+ fun_l18_n482(x)
+ else
+ fun_l18_n502(x)
+ end
+end
+
+def fun_l17_n480(x)
+ if (x < 1)
+ fun_l18_n335(x)
+ else
+ fun_l18_n795(x)
+ end
+end
+
+def fun_l17_n481(x)
+ if (x < 1)
+ fun_l18_n168(x)
+ else
+ fun_l18_n799(x)
+ end
+end
+
+def fun_l17_n482(x)
+ if (x < 1)
+ fun_l18_n981(x)
+ else
+ fun_l18_n633(x)
+ end
+end
+
+def fun_l17_n483(x)
+ if (x < 1)
+ fun_l18_n873(x)
+ else
+ fun_l18_n723(x)
+ end
+end
+
+def fun_l17_n484(x)
+ if (x < 1)
+ fun_l18_n448(x)
+ else
+ fun_l18_n954(x)
+ end
+end
+
+def fun_l17_n485(x)
+ if (x < 1)
+ fun_l18_n421(x)
+ else
+ fun_l18_n802(x)
+ end
+end
+
+def fun_l17_n486(x)
+ if (x < 1)
+ fun_l18_n477(x)
+ else
+ fun_l18_n976(x)
+ end
+end
+
+def fun_l17_n487(x)
+ if (x < 1)
+ fun_l18_n53(x)
+ else
+ fun_l18_n298(x)
+ end
+end
+
+def fun_l17_n488(x)
+ if (x < 1)
+ fun_l18_n733(x)
+ else
+ fun_l18_n585(x)
+ end
+end
+
+def fun_l17_n489(x)
+ if (x < 1)
+ fun_l18_n684(x)
+ else
+ fun_l18_n537(x)
+ end
+end
+
+def fun_l17_n490(x)
+ if (x < 1)
+ fun_l18_n409(x)
+ else
+ fun_l18_n178(x)
+ end
+end
+
+def fun_l17_n491(x)
+ if (x < 1)
+ fun_l18_n335(x)
+ else
+ fun_l18_n255(x)
+ end
+end
+
+def fun_l17_n492(x)
+ if (x < 1)
+ fun_l18_n798(x)
+ else
+ fun_l18_n398(x)
+ end
+end
+
+def fun_l17_n493(x)
+ if (x < 1)
+ fun_l18_n112(x)
+ else
+ fun_l18_n83(x)
+ end
+end
+
+def fun_l17_n494(x)
+ if (x < 1)
+ fun_l18_n888(x)
+ else
+ fun_l18_n136(x)
+ end
+end
+
+def fun_l17_n495(x)
+ if (x < 1)
+ fun_l18_n726(x)
+ else
+ fun_l18_n678(x)
+ end
+end
+
+def fun_l17_n496(x)
+ if (x < 1)
+ fun_l18_n224(x)
+ else
+ fun_l18_n625(x)
+ end
+end
+
+def fun_l17_n497(x)
+ if (x < 1)
+ fun_l18_n772(x)
+ else
+ fun_l18_n14(x)
+ end
+end
+
+def fun_l17_n498(x)
+ if (x < 1)
+ fun_l18_n646(x)
+ else
+ fun_l18_n758(x)
+ end
+end
+
+def fun_l17_n499(x)
+ if (x < 1)
+ fun_l18_n961(x)
+ else
+ fun_l18_n570(x)
+ end
+end
+
+def fun_l17_n500(x)
+ if (x < 1)
+ fun_l18_n368(x)
+ else
+ fun_l18_n681(x)
+ end
+end
+
+def fun_l17_n501(x)
+ if (x < 1)
+ fun_l18_n768(x)
+ else
+ fun_l18_n747(x)
+ end
+end
+
+def fun_l17_n502(x)
+ if (x < 1)
+ fun_l18_n957(x)
+ else
+ fun_l18_n851(x)
+ end
+end
+
+def fun_l17_n503(x)
+ if (x < 1)
+ fun_l18_n669(x)
+ else
+ fun_l18_n939(x)
+ end
+end
+
+def fun_l17_n504(x)
+ if (x < 1)
+ fun_l18_n969(x)
+ else
+ fun_l18_n899(x)
+ end
+end
+
+def fun_l17_n505(x)
+ if (x < 1)
+ fun_l18_n756(x)
+ else
+ fun_l18_n29(x)
+ end
+end
+
+def fun_l17_n506(x)
+ if (x < 1)
+ fun_l18_n92(x)
+ else
+ fun_l18_n230(x)
+ end
+end
+
+def fun_l17_n507(x)
+ if (x < 1)
+ fun_l18_n670(x)
+ else
+ fun_l18_n744(x)
+ end
+end
+
+def fun_l17_n508(x)
+ if (x < 1)
+ fun_l18_n646(x)
+ else
+ fun_l18_n900(x)
+ end
+end
+
+def fun_l17_n509(x)
+ if (x < 1)
+ fun_l18_n480(x)
+ else
+ fun_l18_n6(x)
+ end
+end
+
+def fun_l17_n510(x)
+ if (x < 1)
+ fun_l18_n141(x)
+ else
+ fun_l18_n735(x)
+ end
+end
+
+def fun_l17_n511(x)
+ if (x < 1)
+ fun_l18_n622(x)
+ else
+ fun_l18_n617(x)
+ end
+end
+
+def fun_l17_n512(x)
+ if (x < 1)
+ fun_l18_n491(x)
+ else
+ fun_l18_n154(x)
+ end
+end
+
+def fun_l17_n513(x)
+ if (x < 1)
+ fun_l18_n931(x)
+ else
+ fun_l18_n730(x)
+ end
+end
+
+def fun_l17_n514(x)
+ if (x < 1)
+ fun_l18_n935(x)
+ else
+ fun_l18_n51(x)
+ end
+end
+
+def fun_l17_n515(x)
+ if (x < 1)
+ fun_l18_n751(x)
+ else
+ fun_l18_n786(x)
+ end
+end
+
+def fun_l17_n516(x)
+ if (x < 1)
+ fun_l18_n538(x)
+ else
+ fun_l18_n630(x)
+ end
+end
+
+def fun_l17_n517(x)
+ if (x < 1)
+ fun_l18_n832(x)
+ else
+ fun_l18_n932(x)
+ end
+end
+
+def fun_l17_n518(x)
+ if (x < 1)
+ fun_l18_n572(x)
+ else
+ fun_l18_n408(x)
+ end
+end
+
+def fun_l17_n519(x)
+ if (x < 1)
+ fun_l18_n961(x)
+ else
+ fun_l18_n820(x)
+ end
+end
+
+def fun_l17_n520(x)
+ if (x < 1)
+ fun_l18_n33(x)
+ else
+ fun_l18_n655(x)
+ end
+end
+
+def fun_l17_n521(x)
+ if (x < 1)
+ fun_l18_n940(x)
+ else
+ fun_l18_n436(x)
+ end
+end
+
+def fun_l17_n522(x)
+ if (x < 1)
+ fun_l18_n471(x)
+ else
+ fun_l18_n975(x)
+ end
+end
+
+def fun_l17_n523(x)
+ if (x < 1)
+ fun_l18_n752(x)
+ else
+ fun_l18_n640(x)
+ end
+end
+
+def fun_l17_n524(x)
+ if (x < 1)
+ fun_l18_n226(x)
+ else
+ fun_l18_n645(x)
+ end
+end
+
+def fun_l17_n525(x)
+ if (x < 1)
+ fun_l18_n986(x)
+ else
+ fun_l18_n858(x)
+ end
+end
+
+def fun_l17_n526(x)
+ if (x < 1)
+ fun_l18_n362(x)
+ else
+ fun_l18_n842(x)
+ end
+end
+
+def fun_l17_n527(x)
+ if (x < 1)
+ fun_l18_n273(x)
+ else
+ fun_l18_n510(x)
+ end
+end
+
+def fun_l17_n528(x)
+ if (x < 1)
+ fun_l18_n728(x)
+ else
+ fun_l18_n906(x)
+ end
+end
+
+def fun_l17_n529(x)
+ if (x < 1)
+ fun_l18_n225(x)
+ else
+ fun_l18_n988(x)
+ end
+end
+
+def fun_l17_n530(x)
+ if (x < 1)
+ fun_l18_n472(x)
+ else
+ fun_l18_n933(x)
+ end
+end
+
+def fun_l17_n531(x)
+ if (x < 1)
+ fun_l18_n105(x)
+ else
+ fun_l18_n501(x)
+ end
+end
+
+def fun_l17_n532(x)
+ if (x < 1)
+ fun_l18_n77(x)
+ else
+ fun_l18_n616(x)
+ end
+end
+
+def fun_l17_n533(x)
+ if (x < 1)
+ fun_l18_n404(x)
+ else
+ fun_l18_n86(x)
+ end
+end
+
+def fun_l17_n534(x)
+ if (x < 1)
+ fun_l18_n312(x)
+ else
+ fun_l18_n638(x)
+ end
+end
+
+def fun_l17_n535(x)
+ if (x < 1)
+ fun_l18_n908(x)
+ else
+ fun_l18_n697(x)
+ end
+end
+
+def fun_l17_n536(x)
+ if (x < 1)
+ fun_l18_n520(x)
+ else
+ fun_l18_n379(x)
+ end
+end
+
+def fun_l17_n537(x)
+ if (x < 1)
+ fun_l18_n15(x)
+ else
+ fun_l18_n97(x)
+ end
+end
+
+def fun_l17_n538(x)
+ if (x < 1)
+ fun_l18_n312(x)
+ else
+ fun_l18_n981(x)
+ end
+end
+
+def fun_l17_n539(x)
+ if (x < 1)
+ fun_l18_n901(x)
+ else
+ fun_l18_n579(x)
+ end
+end
+
+def fun_l17_n540(x)
+ if (x < 1)
+ fun_l18_n569(x)
+ else
+ fun_l18_n512(x)
+ end
+end
+
+def fun_l17_n541(x)
+ if (x < 1)
+ fun_l18_n319(x)
+ else
+ fun_l18_n388(x)
+ end
+end
+
+def fun_l17_n542(x)
+ if (x < 1)
+ fun_l18_n288(x)
+ else
+ fun_l18_n422(x)
+ end
+end
+
+def fun_l17_n543(x)
+ if (x < 1)
+ fun_l18_n873(x)
+ else
+ fun_l18_n614(x)
+ end
+end
+
+def fun_l17_n544(x)
+ if (x < 1)
+ fun_l18_n104(x)
+ else
+ fun_l18_n771(x)
+ end
+end
+
+def fun_l17_n545(x)
+ if (x < 1)
+ fun_l18_n204(x)
+ else
+ fun_l18_n452(x)
+ end
+end
+
+def fun_l17_n546(x)
+ if (x < 1)
+ fun_l18_n288(x)
+ else
+ fun_l18_n558(x)
+ end
+end
+
+def fun_l17_n547(x)
+ if (x < 1)
+ fun_l18_n265(x)
+ else
+ fun_l18_n768(x)
+ end
+end
+
+def fun_l17_n548(x)
+ if (x < 1)
+ fun_l18_n21(x)
+ else
+ fun_l18_n44(x)
+ end
+end
+
+def fun_l17_n549(x)
+ if (x < 1)
+ fun_l18_n72(x)
+ else
+ fun_l18_n321(x)
+ end
+end
+
+def fun_l17_n550(x)
+ if (x < 1)
+ fun_l18_n473(x)
+ else
+ fun_l18_n127(x)
+ end
+end
+
+def fun_l17_n551(x)
+ if (x < 1)
+ fun_l18_n188(x)
+ else
+ fun_l18_n782(x)
+ end
+end
+
+def fun_l17_n552(x)
+ if (x < 1)
+ fun_l18_n118(x)
+ else
+ fun_l18_n466(x)
+ end
+end
+
+def fun_l17_n553(x)
+ if (x < 1)
+ fun_l18_n279(x)
+ else
+ fun_l18_n605(x)
+ end
+end
+
+def fun_l17_n554(x)
+ if (x < 1)
+ fun_l18_n760(x)
+ else
+ fun_l18_n561(x)
+ end
+end
+
+def fun_l17_n555(x)
+ if (x < 1)
+ fun_l18_n873(x)
+ else
+ fun_l18_n846(x)
+ end
+end
+
+def fun_l17_n556(x)
+ if (x < 1)
+ fun_l18_n555(x)
+ else
+ fun_l18_n955(x)
+ end
+end
+
+def fun_l17_n557(x)
+ if (x < 1)
+ fun_l18_n757(x)
+ else
+ fun_l18_n171(x)
+ end
+end
+
+def fun_l17_n558(x)
+ if (x < 1)
+ fun_l18_n684(x)
+ else
+ fun_l18_n784(x)
+ end
+end
+
+def fun_l17_n559(x)
+ if (x < 1)
+ fun_l18_n457(x)
+ else
+ fun_l18_n798(x)
+ end
+end
+
+def fun_l17_n560(x)
+ if (x < 1)
+ fun_l18_n472(x)
+ else
+ fun_l18_n291(x)
+ end
+end
+
+def fun_l17_n561(x)
+ if (x < 1)
+ fun_l18_n870(x)
+ else
+ fun_l18_n395(x)
+ end
+end
+
+def fun_l17_n562(x)
+ if (x < 1)
+ fun_l18_n482(x)
+ else
+ fun_l18_n281(x)
+ end
+end
+
+def fun_l17_n563(x)
+ if (x < 1)
+ fun_l18_n761(x)
+ else
+ fun_l18_n362(x)
+ end
+end
+
+def fun_l17_n564(x)
+ if (x < 1)
+ fun_l18_n586(x)
+ else
+ fun_l18_n92(x)
+ end
+end
+
+def fun_l17_n565(x)
+ if (x < 1)
+ fun_l18_n620(x)
+ else
+ fun_l18_n356(x)
+ end
+end
+
+def fun_l17_n566(x)
+ if (x < 1)
+ fun_l18_n529(x)
+ else
+ fun_l18_n985(x)
+ end
+end
+
+def fun_l17_n567(x)
+ if (x < 1)
+ fun_l18_n351(x)
+ else
+ fun_l18_n77(x)
+ end
+end
+
+def fun_l17_n568(x)
+ if (x < 1)
+ fun_l18_n659(x)
+ else
+ fun_l18_n631(x)
+ end
+end
+
+def fun_l17_n569(x)
+ if (x < 1)
+ fun_l18_n630(x)
+ else
+ fun_l18_n466(x)
+ end
+end
+
+def fun_l17_n570(x)
+ if (x < 1)
+ fun_l18_n374(x)
+ else
+ fun_l18_n203(x)
+ end
+end
+
+def fun_l17_n571(x)
+ if (x < 1)
+ fun_l18_n479(x)
+ else
+ fun_l18_n977(x)
+ end
+end
+
+def fun_l17_n572(x)
+ if (x < 1)
+ fun_l18_n862(x)
+ else
+ fun_l18_n323(x)
+ end
+end
+
+def fun_l17_n573(x)
+ if (x < 1)
+ fun_l18_n148(x)
+ else
+ fun_l18_n848(x)
+ end
+end
+
+def fun_l17_n574(x)
+ if (x < 1)
+ fun_l18_n29(x)
+ else
+ fun_l18_n210(x)
+ end
+end
+
+def fun_l17_n575(x)
+ if (x < 1)
+ fun_l18_n39(x)
+ else
+ fun_l18_n874(x)
+ end
+end
+
+def fun_l17_n576(x)
+ if (x < 1)
+ fun_l18_n843(x)
+ else
+ fun_l18_n5(x)
+ end
+end
+
+def fun_l17_n577(x)
+ if (x < 1)
+ fun_l18_n284(x)
+ else
+ fun_l18_n242(x)
+ end
+end
+
+def fun_l17_n578(x)
+ if (x < 1)
+ fun_l18_n768(x)
+ else
+ fun_l18_n683(x)
+ end
+end
+
+def fun_l17_n579(x)
+ if (x < 1)
+ fun_l18_n67(x)
+ else
+ fun_l18_n423(x)
+ end
+end
+
+def fun_l17_n580(x)
+ if (x < 1)
+ fun_l18_n326(x)
+ else
+ fun_l18_n200(x)
+ end
+end
+
+def fun_l17_n581(x)
+ if (x < 1)
+ fun_l18_n186(x)
+ else
+ fun_l18_n772(x)
+ end
+end
+
+def fun_l17_n582(x)
+ if (x < 1)
+ fun_l18_n151(x)
+ else
+ fun_l18_n222(x)
+ end
+end
+
+def fun_l17_n583(x)
+ if (x < 1)
+ fun_l18_n690(x)
+ else
+ fun_l18_n925(x)
+ end
+end
+
+def fun_l17_n584(x)
+ if (x < 1)
+ fun_l18_n225(x)
+ else
+ fun_l18_n286(x)
+ end
+end
+
+def fun_l17_n585(x)
+ if (x < 1)
+ fun_l18_n542(x)
+ else
+ fun_l18_n703(x)
+ end
+end
+
+def fun_l17_n586(x)
+ if (x < 1)
+ fun_l18_n417(x)
+ else
+ fun_l18_n364(x)
+ end
+end
+
+def fun_l17_n587(x)
+ if (x < 1)
+ fun_l18_n540(x)
+ else
+ fun_l18_n231(x)
+ end
+end
+
+def fun_l17_n588(x)
+ if (x < 1)
+ fun_l18_n859(x)
+ else
+ fun_l18_n557(x)
+ end
+end
+
+def fun_l17_n589(x)
+ if (x < 1)
+ fun_l18_n131(x)
+ else
+ fun_l18_n847(x)
+ end
+end
+
+def fun_l17_n590(x)
+ if (x < 1)
+ fun_l18_n267(x)
+ else
+ fun_l18_n613(x)
+ end
+end
+
+def fun_l17_n591(x)
+ if (x < 1)
+ fun_l18_n273(x)
+ else
+ fun_l18_n857(x)
+ end
+end
+
+def fun_l17_n592(x)
+ if (x < 1)
+ fun_l18_n561(x)
+ else
+ fun_l18_n243(x)
+ end
+end
+
+def fun_l17_n593(x)
+ if (x < 1)
+ fun_l18_n742(x)
+ else
+ fun_l18_n123(x)
+ end
+end
+
+def fun_l17_n594(x)
+ if (x < 1)
+ fun_l18_n480(x)
+ else
+ fun_l18_n290(x)
+ end
+end
+
+def fun_l17_n595(x)
+ if (x < 1)
+ fun_l18_n56(x)
+ else
+ fun_l18_n727(x)
+ end
+end
+
+def fun_l17_n596(x)
+ if (x < 1)
+ fun_l18_n901(x)
+ else
+ fun_l18_n723(x)
+ end
+end
+
+def fun_l17_n597(x)
+ if (x < 1)
+ fun_l18_n405(x)
+ else
+ fun_l18_n498(x)
+ end
+end
+
+def fun_l17_n598(x)
+ if (x < 1)
+ fun_l18_n772(x)
+ else
+ fun_l18_n543(x)
+ end
+end
+
+def fun_l17_n599(x)
+ if (x < 1)
+ fun_l18_n20(x)
+ else
+ fun_l18_n39(x)
+ end
+end
+
+def fun_l17_n600(x)
+ if (x < 1)
+ fun_l18_n657(x)
+ else
+ fun_l18_n381(x)
+ end
+end
+
+def fun_l17_n601(x)
+ if (x < 1)
+ fun_l18_n505(x)
+ else
+ fun_l18_n196(x)
+ end
+end
+
+def fun_l17_n602(x)
+ if (x < 1)
+ fun_l18_n250(x)
+ else
+ fun_l18_n503(x)
+ end
+end
+
+def fun_l17_n603(x)
+ if (x < 1)
+ fun_l18_n694(x)
+ else
+ fun_l18_n589(x)
+ end
+end
+
+def fun_l17_n604(x)
+ if (x < 1)
+ fun_l18_n27(x)
+ else
+ fun_l18_n202(x)
+ end
+end
+
+def fun_l17_n605(x)
+ if (x < 1)
+ fun_l18_n901(x)
+ else
+ fun_l18_n823(x)
+ end
+end
+
+def fun_l17_n606(x)
+ if (x < 1)
+ fun_l18_n296(x)
+ else
+ fun_l18_n854(x)
+ end
+end
+
+def fun_l17_n607(x)
+ if (x < 1)
+ fun_l18_n226(x)
+ else
+ fun_l18_n110(x)
+ end
+end
+
+def fun_l17_n608(x)
+ if (x < 1)
+ fun_l18_n205(x)
+ else
+ fun_l18_n215(x)
+ end
+end
+
+def fun_l17_n609(x)
+ if (x < 1)
+ fun_l18_n265(x)
+ else
+ fun_l18_n715(x)
+ end
+end
+
+def fun_l17_n610(x)
+ if (x < 1)
+ fun_l18_n881(x)
+ else
+ fun_l18_n106(x)
+ end
+end
+
+def fun_l17_n611(x)
+ if (x < 1)
+ fun_l18_n674(x)
+ else
+ fun_l18_n189(x)
+ end
+end
+
+def fun_l17_n612(x)
+ if (x < 1)
+ fun_l18_n20(x)
+ else
+ fun_l18_n96(x)
+ end
+end
+
+def fun_l17_n613(x)
+ if (x < 1)
+ fun_l18_n880(x)
+ else
+ fun_l18_n599(x)
+ end
+end
+
+def fun_l17_n614(x)
+ if (x < 1)
+ fun_l18_n47(x)
+ else
+ fun_l18_n633(x)
+ end
+end
+
+def fun_l17_n615(x)
+ if (x < 1)
+ fun_l18_n7(x)
+ else
+ fun_l18_n165(x)
+ end
+end
+
+def fun_l17_n616(x)
+ if (x < 1)
+ fun_l18_n478(x)
+ else
+ fun_l18_n94(x)
+ end
+end
+
+def fun_l17_n617(x)
+ if (x < 1)
+ fun_l18_n97(x)
+ else
+ fun_l18_n369(x)
+ end
+end
+
+def fun_l17_n618(x)
+ if (x < 1)
+ fun_l18_n291(x)
+ else
+ fun_l18_n637(x)
+ end
+end
+
+def fun_l17_n619(x)
+ if (x < 1)
+ fun_l18_n966(x)
+ else
+ fun_l18_n851(x)
+ end
+end
+
+def fun_l17_n620(x)
+ if (x < 1)
+ fun_l18_n349(x)
+ else
+ fun_l18_n413(x)
+ end
+end
+
+def fun_l17_n621(x)
+ if (x < 1)
+ fun_l18_n343(x)
+ else
+ fun_l18_n224(x)
+ end
+end
+
+def fun_l17_n622(x)
+ if (x < 1)
+ fun_l18_n452(x)
+ else
+ fun_l18_n3(x)
+ end
+end
+
+def fun_l17_n623(x)
+ if (x < 1)
+ fun_l18_n539(x)
+ else
+ fun_l18_n542(x)
+ end
+end
+
+def fun_l17_n624(x)
+ if (x < 1)
+ fun_l18_n117(x)
+ else
+ fun_l18_n348(x)
+ end
+end
+
+def fun_l17_n625(x)
+ if (x < 1)
+ fun_l18_n753(x)
+ else
+ fun_l18_n284(x)
+ end
+end
+
+def fun_l17_n626(x)
+ if (x < 1)
+ fun_l18_n146(x)
+ else
+ fun_l18_n228(x)
+ end
+end
+
+def fun_l17_n627(x)
+ if (x < 1)
+ fun_l18_n286(x)
+ else
+ fun_l18_n413(x)
+ end
+end
+
+def fun_l17_n628(x)
+ if (x < 1)
+ fun_l18_n730(x)
+ else
+ fun_l18_n311(x)
+ end
+end
+
+def fun_l17_n629(x)
+ if (x < 1)
+ fun_l18_n455(x)
+ else
+ fun_l18_n141(x)
+ end
+end
+
+def fun_l17_n630(x)
+ if (x < 1)
+ fun_l18_n300(x)
+ else
+ fun_l18_n368(x)
+ end
+end
+
+def fun_l17_n631(x)
+ if (x < 1)
+ fun_l18_n490(x)
+ else
+ fun_l18_n711(x)
+ end
+end
+
+def fun_l17_n632(x)
+ if (x < 1)
+ fun_l18_n310(x)
+ else
+ fun_l18_n805(x)
+ end
+end
+
+def fun_l17_n633(x)
+ if (x < 1)
+ fun_l18_n2(x)
+ else
+ fun_l18_n709(x)
+ end
+end
+
+def fun_l17_n634(x)
+ if (x < 1)
+ fun_l18_n239(x)
+ else
+ fun_l18_n394(x)
+ end
+end
+
+def fun_l17_n635(x)
+ if (x < 1)
+ fun_l18_n933(x)
+ else
+ fun_l18_n749(x)
+ end
+end
+
+def fun_l17_n636(x)
+ if (x < 1)
+ fun_l18_n54(x)
+ else
+ fun_l18_n511(x)
+ end
+end
+
+def fun_l17_n637(x)
+ if (x < 1)
+ fun_l18_n908(x)
+ else
+ fun_l18_n550(x)
+ end
+end
+
+def fun_l17_n638(x)
+ if (x < 1)
+ fun_l18_n262(x)
+ else
+ fun_l18_n485(x)
+ end
+end
+
+def fun_l17_n639(x)
+ if (x < 1)
+ fun_l18_n676(x)
+ else
+ fun_l18_n860(x)
+ end
+end
+
+def fun_l17_n640(x)
+ if (x < 1)
+ fun_l18_n205(x)
+ else
+ fun_l18_n901(x)
+ end
+end
+
+def fun_l17_n641(x)
+ if (x < 1)
+ fun_l18_n834(x)
+ else
+ fun_l18_n133(x)
+ end
+end
+
+def fun_l17_n642(x)
+ if (x < 1)
+ fun_l18_n824(x)
+ else
+ fun_l18_n551(x)
+ end
+end
+
+def fun_l17_n643(x)
+ if (x < 1)
+ fun_l18_n362(x)
+ else
+ fun_l18_n684(x)
+ end
+end
+
+def fun_l17_n644(x)
+ if (x < 1)
+ fun_l18_n856(x)
+ else
+ fun_l18_n103(x)
+ end
+end
+
+def fun_l17_n645(x)
+ if (x < 1)
+ fun_l18_n999(x)
+ else
+ fun_l18_n995(x)
+ end
+end
+
+def fun_l17_n646(x)
+ if (x < 1)
+ fun_l18_n24(x)
+ else
+ fun_l18_n405(x)
+ end
+end
+
+def fun_l17_n647(x)
+ if (x < 1)
+ fun_l18_n71(x)
+ else
+ fun_l18_n201(x)
+ end
+end
+
+def fun_l17_n648(x)
+ if (x < 1)
+ fun_l18_n905(x)
+ else
+ fun_l18_n14(x)
+ end
+end
+
+def fun_l17_n649(x)
+ if (x < 1)
+ fun_l18_n490(x)
+ else
+ fun_l18_n932(x)
+ end
+end
+
+def fun_l17_n650(x)
+ if (x < 1)
+ fun_l18_n25(x)
+ else
+ fun_l18_n333(x)
+ end
+end
+
+def fun_l17_n651(x)
+ if (x < 1)
+ fun_l18_n282(x)
+ else
+ fun_l18_n197(x)
+ end
+end
+
+def fun_l17_n652(x)
+ if (x < 1)
+ fun_l18_n684(x)
+ else
+ fun_l18_n618(x)
+ end
+end
+
+def fun_l17_n653(x)
+ if (x < 1)
+ fun_l18_n201(x)
+ else
+ fun_l18_n571(x)
+ end
+end
+
+def fun_l17_n654(x)
+ if (x < 1)
+ fun_l18_n26(x)
+ else
+ fun_l18_n813(x)
+ end
+end
+
+def fun_l17_n655(x)
+ if (x < 1)
+ fun_l18_n879(x)
+ else
+ fun_l18_n860(x)
+ end
+end
+
+def fun_l17_n656(x)
+ if (x < 1)
+ fun_l18_n193(x)
+ else
+ fun_l18_n635(x)
+ end
+end
+
+def fun_l17_n657(x)
+ if (x < 1)
+ fun_l18_n163(x)
+ else
+ fun_l18_n601(x)
+ end
+end
+
+def fun_l17_n658(x)
+ if (x < 1)
+ fun_l18_n794(x)
+ else
+ fun_l18_n582(x)
+ end
+end
+
+def fun_l17_n659(x)
+ if (x < 1)
+ fun_l18_n22(x)
+ else
+ fun_l18_n427(x)
+ end
+end
+
+def fun_l17_n660(x)
+ if (x < 1)
+ fun_l18_n959(x)
+ else
+ fun_l18_n21(x)
+ end
+end
+
+def fun_l17_n661(x)
+ if (x < 1)
+ fun_l18_n233(x)
+ else
+ fun_l18_n852(x)
+ end
+end
+
+def fun_l17_n662(x)
+ if (x < 1)
+ fun_l18_n367(x)
+ else
+ fun_l18_n119(x)
+ end
+end
+
+def fun_l17_n663(x)
+ if (x < 1)
+ fun_l18_n511(x)
+ else
+ fun_l18_n425(x)
+ end
+end
+
+def fun_l17_n664(x)
+ if (x < 1)
+ fun_l18_n256(x)
+ else
+ fun_l18_n294(x)
+ end
+end
+
+def fun_l17_n665(x)
+ if (x < 1)
+ fun_l18_n263(x)
+ else
+ fun_l18_n549(x)
+ end
+end
+
+def fun_l17_n666(x)
+ if (x < 1)
+ fun_l18_n868(x)
+ else
+ fun_l18_n221(x)
+ end
+end
+
+def fun_l17_n667(x)
+ if (x < 1)
+ fun_l18_n703(x)
+ else
+ fun_l18_n157(x)
+ end
+end
+
+def fun_l17_n668(x)
+ if (x < 1)
+ fun_l18_n639(x)
+ else
+ fun_l18_n685(x)
+ end
+end
+
+def fun_l17_n669(x)
+ if (x < 1)
+ fun_l18_n278(x)
+ else
+ fun_l18_n366(x)
+ end
+end
+
+def fun_l17_n670(x)
+ if (x < 1)
+ fun_l18_n267(x)
+ else
+ fun_l18_n641(x)
+ end
+end
+
+def fun_l17_n671(x)
+ if (x < 1)
+ fun_l18_n452(x)
+ else
+ fun_l18_n851(x)
+ end
+end
+
+def fun_l17_n672(x)
+ if (x < 1)
+ fun_l18_n256(x)
+ else
+ fun_l18_n282(x)
+ end
+end
+
+def fun_l17_n673(x)
+ if (x < 1)
+ fun_l18_n397(x)
+ else
+ fun_l18_n446(x)
+ end
+end
+
+def fun_l17_n674(x)
+ if (x < 1)
+ fun_l18_n499(x)
+ else
+ fun_l18_n166(x)
+ end
+end
+
+def fun_l17_n675(x)
+ if (x < 1)
+ fun_l18_n299(x)
+ else
+ fun_l18_n473(x)
+ end
+end
+
+def fun_l17_n676(x)
+ if (x < 1)
+ fun_l18_n331(x)
+ else
+ fun_l18_n590(x)
+ end
+end
+
+def fun_l17_n677(x)
+ if (x < 1)
+ fun_l18_n951(x)
+ else
+ fun_l18_n227(x)
+ end
+end
+
+def fun_l17_n678(x)
+ if (x < 1)
+ fun_l18_n874(x)
+ else
+ fun_l18_n359(x)
+ end
+end
+
+def fun_l17_n679(x)
+ if (x < 1)
+ fun_l18_n187(x)
+ else
+ fun_l18_n13(x)
+ end
+end
+
+def fun_l17_n680(x)
+ if (x < 1)
+ fun_l18_n878(x)
+ else
+ fun_l18_n902(x)
+ end
+end
+
+def fun_l17_n681(x)
+ if (x < 1)
+ fun_l18_n450(x)
+ else
+ fun_l18_n262(x)
+ end
+end
+
+def fun_l17_n682(x)
+ if (x < 1)
+ fun_l18_n759(x)
+ else
+ fun_l18_n253(x)
+ end
+end
+
+def fun_l17_n683(x)
+ if (x < 1)
+ fun_l18_n199(x)
+ else
+ fun_l18_n191(x)
+ end
+end
+
+def fun_l17_n684(x)
+ if (x < 1)
+ fun_l18_n93(x)
+ else
+ fun_l18_n275(x)
+ end
+end
+
+def fun_l17_n685(x)
+ if (x < 1)
+ fun_l18_n17(x)
+ else
+ fun_l18_n575(x)
+ end
+end
+
+def fun_l17_n686(x)
+ if (x < 1)
+ fun_l18_n971(x)
+ else
+ fun_l18_n540(x)
+ end
+end
+
+def fun_l17_n687(x)
+ if (x < 1)
+ fun_l18_n942(x)
+ else
+ fun_l18_n285(x)
+ end
+end
+
+def fun_l17_n688(x)
+ if (x < 1)
+ fun_l18_n348(x)
+ else
+ fun_l18_n7(x)
+ end
+end
+
+def fun_l17_n689(x)
+ if (x < 1)
+ fun_l18_n839(x)
+ else
+ fun_l18_n532(x)
+ end
+end
+
+def fun_l17_n690(x)
+ if (x < 1)
+ fun_l18_n578(x)
+ else
+ fun_l18_n751(x)
+ end
+end
+
+def fun_l17_n691(x)
+ if (x < 1)
+ fun_l18_n85(x)
+ else
+ fun_l18_n311(x)
+ end
+end
+
+def fun_l17_n692(x)
+ if (x < 1)
+ fun_l18_n573(x)
+ else
+ fun_l18_n685(x)
+ end
+end
+
+def fun_l17_n693(x)
+ if (x < 1)
+ fun_l18_n449(x)
+ else
+ fun_l18_n749(x)
+ end
+end
+
+def fun_l17_n694(x)
+ if (x < 1)
+ fun_l18_n251(x)
+ else
+ fun_l18_n266(x)
+ end
+end
+
+def fun_l17_n695(x)
+ if (x < 1)
+ fun_l18_n69(x)
+ else
+ fun_l18_n725(x)
+ end
+end
+
+def fun_l17_n696(x)
+ if (x < 1)
+ fun_l18_n54(x)
+ else
+ fun_l18_n196(x)
+ end
+end
+
+def fun_l17_n697(x)
+ if (x < 1)
+ fun_l18_n950(x)
+ else
+ fun_l18_n423(x)
+ end
+end
+
+def fun_l17_n698(x)
+ if (x < 1)
+ fun_l18_n809(x)
+ else
+ fun_l18_n787(x)
+ end
+end
+
+def fun_l17_n699(x)
+ if (x < 1)
+ fun_l18_n211(x)
+ else
+ fun_l18_n79(x)
+ end
+end
+
+def fun_l17_n700(x)
+ if (x < 1)
+ fun_l18_n686(x)
+ else
+ fun_l18_n287(x)
+ end
+end
+
+def fun_l17_n701(x)
+ if (x < 1)
+ fun_l18_n412(x)
+ else
+ fun_l18_n769(x)
+ end
+end
+
+def fun_l17_n702(x)
+ if (x < 1)
+ fun_l18_n62(x)
+ else
+ fun_l18_n592(x)
+ end
+end
+
+def fun_l17_n703(x)
+ if (x < 1)
+ fun_l18_n628(x)
+ else
+ fun_l18_n121(x)
+ end
+end
+
+def fun_l17_n704(x)
+ if (x < 1)
+ fun_l18_n84(x)
+ else
+ fun_l18_n350(x)
+ end
+end
+
+def fun_l17_n705(x)
+ if (x < 1)
+ fun_l18_n599(x)
+ else
+ fun_l18_n174(x)
+ end
+end
+
+def fun_l17_n706(x)
+ if (x < 1)
+ fun_l18_n39(x)
+ else
+ fun_l18_n266(x)
+ end
+end
+
+def fun_l17_n707(x)
+ if (x < 1)
+ fun_l18_n196(x)
+ else
+ fun_l18_n838(x)
+ end
+end
+
+def fun_l17_n708(x)
+ if (x < 1)
+ fun_l18_n647(x)
+ else
+ fun_l18_n26(x)
+ end
+end
+
+def fun_l17_n709(x)
+ if (x < 1)
+ fun_l18_n693(x)
+ else
+ fun_l18_n660(x)
+ end
+end
+
+def fun_l17_n710(x)
+ if (x < 1)
+ fun_l18_n530(x)
+ else
+ fun_l18_n654(x)
+ end
+end
+
+def fun_l17_n711(x)
+ if (x < 1)
+ fun_l18_n580(x)
+ else
+ fun_l18_n65(x)
+ end
+end
+
+def fun_l17_n712(x)
+ if (x < 1)
+ fun_l18_n789(x)
+ else
+ fun_l18_n832(x)
+ end
+end
+
+def fun_l17_n713(x)
+ if (x < 1)
+ fun_l18_n366(x)
+ else
+ fun_l18_n168(x)
+ end
+end
+
+def fun_l17_n714(x)
+ if (x < 1)
+ fun_l18_n571(x)
+ else
+ fun_l18_n23(x)
+ end
+end
+
+def fun_l17_n715(x)
+ if (x < 1)
+ fun_l18_n552(x)
+ else
+ fun_l18_n400(x)
+ end
+end
+
+def fun_l17_n716(x)
+ if (x < 1)
+ fun_l18_n752(x)
+ else
+ fun_l18_n403(x)
+ end
+end
+
+def fun_l17_n717(x)
+ if (x < 1)
+ fun_l18_n498(x)
+ else
+ fun_l18_n173(x)
+ end
+end
+
+def fun_l17_n718(x)
+ if (x < 1)
+ fun_l18_n168(x)
+ else
+ fun_l18_n656(x)
+ end
+end
+
+def fun_l17_n719(x)
+ if (x < 1)
+ fun_l18_n75(x)
+ else
+ fun_l18_n393(x)
+ end
+end
+
+def fun_l17_n720(x)
+ if (x < 1)
+ fun_l18_n856(x)
+ else
+ fun_l18_n101(x)
+ end
+end
+
+def fun_l17_n721(x)
+ if (x < 1)
+ fun_l18_n445(x)
+ else
+ fun_l18_n846(x)
+ end
+end
+
+def fun_l17_n722(x)
+ if (x < 1)
+ fun_l18_n450(x)
+ else
+ fun_l18_n136(x)
+ end
+end
+
+def fun_l17_n723(x)
+ if (x < 1)
+ fun_l18_n267(x)
+ else
+ fun_l18_n800(x)
+ end
+end
+
+def fun_l17_n724(x)
+ if (x < 1)
+ fun_l18_n98(x)
+ else
+ fun_l18_n955(x)
+ end
+end
+
+def fun_l17_n725(x)
+ if (x < 1)
+ fun_l18_n951(x)
+ else
+ fun_l18_n319(x)
+ end
+end
+
+def fun_l17_n726(x)
+ if (x < 1)
+ fun_l18_n531(x)
+ else
+ fun_l18_n846(x)
+ end
+end
+
+def fun_l17_n727(x)
+ if (x < 1)
+ fun_l18_n888(x)
+ else
+ fun_l18_n600(x)
+ end
+end
+
+def fun_l17_n728(x)
+ if (x < 1)
+ fun_l18_n278(x)
+ else
+ fun_l18_n445(x)
+ end
+end
+
+def fun_l17_n729(x)
+ if (x < 1)
+ fun_l18_n113(x)
+ else
+ fun_l18_n991(x)
+ end
+end
+
+def fun_l17_n730(x)
+ if (x < 1)
+ fun_l18_n756(x)
+ else
+ fun_l18_n935(x)
+ end
+end
+
+def fun_l17_n731(x)
+ if (x < 1)
+ fun_l18_n2(x)
+ else
+ fun_l18_n969(x)
+ end
+end
+
+def fun_l17_n732(x)
+ if (x < 1)
+ fun_l18_n138(x)
+ else
+ fun_l18_n198(x)
+ end
+end
+
+def fun_l17_n733(x)
+ if (x < 1)
+ fun_l18_n845(x)
+ else
+ fun_l18_n614(x)
+ end
+end
+
+def fun_l17_n734(x)
+ if (x < 1)
+ fun_l18_n603(x)
+ else
+ fun_l18_n568(x)
+ end
+end
+
+def fun_l17_n735(x)
+ if (x < 1)
+ fun_l18_n276(x)
+ else
+ fun_l18_n58(x)
+ end
+end
+
+def fun_l17_n736(x)
+ if (x < 1)
+ fun_l18_n404(x)
+ else
+ fun_l18_n906(x)
+ end
+end
+
+def fun_l17_n737(x)
+ if (x < 1)
+ fun_l18_n199(x)
+ else
+ fun_l18_n734(x)
+ end
+end
+
+def fun_l17_n738(x)
+ if (x < 1)
+ fun_l18_n327(x)
+ else
+ fun_l18_n667(x)
+ end
+end
+
+def fun_l17_n739(x)
+ if (x < 1)
+ fun_l18_n600(x)
+ else
+ fun_l18_n986(x)
+ end
+end
+
+def fun_l17_n740(x)
+ if (x < 1)
+ fun_l18_n820(x)
+ else
+ fun_l18_n615(x)
+ end
+end
+
+def fun_l17_n741(x)
+ if (x < 1)
+ fun_l18_n779(x)
+ else
+ fun_l18_n912(x)
+ end
+end
+
+def fun_l17_n742(x)
+ if (x < 1)
+ fun_l18_n55(x)
+ else
+ fun_l18_n41(x)
+ end
+end
+
+def fun_l17_n743(x)
+ if (x < 1)
+ fun_l18_n24(x)
+ else
+ fun_l18_n877(x)
+ end
+end
+
+def fun_l17_n744(x)
+ if (x < 1)
+ fun_l18_n834(x)
+ else
+ fun_l18_n10(x)
+ end
+end
+
+def fun_l17_n745(x)
+ if (x < 1)
+ fun_l18_n369(x)
+ else
+ fun_l18_n761(x)
+ end
+end
+
+def fun_l17_n746(x)
+ if (x < 1)
+ fun_l18_n534(x)
+ else
+ fun_l18_n292(x)
+ end
+end
+
+def fun_l17_n747(x)
+ if (x < 1)
+ fun_l18_n260(x)
+ else
+ fun_l18_n98(x)
+ end
+end
+
+def fun_l17_n748(x)
+ if (x < 1)
+ fun_l18_n738(x)
+ else
+ fun_l18_n298(x)
+ end
+end
+
+def fun_l17_n749(x)
+ if (x < 1)
+ fun_l18_n156(x)
+ else
+ fun_l18_n322(x)
+ end
+end
+
+def fun_l17_n750(x)
+ if (x < 1)
+ fun_l18_n519(x)
+ else
+ fun_l18_n566(x)
+ end
+end
+
+def fun_l17_n751(x)
+ if (x < 1)
+ fun_l18_n599(x)
+ else
+ fun_l18_n525(x)
+ end
+end
+
+def fun_l17_n752(x)
+ if (x < 1)
+ fun_l18_n51(x)
+ else
+ fun_l18_n334(x)
+ end
+end
+
+def fun_l17_n753(x)
+ if (x < 1)
+ fun_l18_n593(x)
+ else
+ fun_l18_n799(x)
+ end
+end
+
+def fun_l17_n754(x)
+ if (x < 1)
+ fun_l18_n599(x)
+ else
+ fun_l18_n167(x)
+ end
+end
+
+def fun_l17_n755(x)
+ if (x < 1)
+ fun_l18_n799(x)
+ else
+ fun_l18_n909(x)
+ end
+end
+
+def fun_l17_n756(x)
+ if (x < 1)
+ fun_l18_n988(x)
+ else
+ fun_l18_n793(x)
+ end
+end
+
+def fun_l17_n757(x)
+ if (x < 1)
+ fun_l18_n144(x)
+ else
+ fun_l18_n279(x)
+ end
+end
+
+def fun_l17_n758(x)
+ if (x < 1)
+ fun_l18_n981(x)
+ else
+ fun_l18_n603(x)
+ end
+end
+
+def fun_l17_n759(x)
+ if (x < 1)
+ fun_l18_n576(x)
+ else
+ fun_l18_n730(x)
+ end
+end
+
+def fun_l17_n760(x)
+ if (x < 1)
+ fun_l18_n66(x)
+ else
+ fun_l18_n359(x)
+ end
+end
+
+def fun_l17_n761(x)
+ if (x < 1)
+ fun_l18_n555(x)
+ else
+ fun_l18_n553(x)
+ end
+end
+
+def fun_l17_n762(x)
+ if (x < 1)
+ fun_l18_n508(x)
+ else
+ fun_l18_n665(x)
+ end
+end
+
+def fun_l17_n763(x)
+ if (x < 1)
+ fun_l18_n911(x)
+ else
+ fun_l18_n19(x)
+ end
+end
+
+def fun_l17_n764(x)
+ if (x < 1)
+ fun_l18_n162(x)
+ else
+ fun_l18_n707(x)
+ end
+end
+
+def fun_l17_n765(x)
+ if (x < 1)
+ fun_l18_n262(x)
+ else
+ fun_l18_n494(x)
+ end
+end
+
+def fun_l17_n766(x)
+ if (x < 1)
+ fun_l18_n220(x)
+ else
+ fun_l18_n144(x)
+ end
+end
+
+def fun_l17_n767(x)
+ if (x < 1)
+ fun_l18_n245(x)
+ else
+ fun_l18_n727(x)
+ end
+end
+
+def fun_l17_n768(x)
+ if (x < 1)
+ fun_l18_n875(x)
+ else
+ fun_l18_n610(x)
+ end
+end
+
+def fun_l17_n769(x)
+ if (x < 1)
+ fun_l18_n338(x)
+ else
+ fun_l18_n344(x)
+ end
+end
+
+def fun_l17_n770(x)
+ if (x < 1)
+ fun_l18_n224(x)
+ else
+ fun_l18_n682(x)
+ end
+end
+
+def fun_l17_n771(x)
+ if (x < 1)
+ fun_l18_n353(x)
+ else
+ fun_l18_n102(x)
+ end
+end
+
+def fun_l17_n772(x)
+ if (x < 1)
+ fun_l18_n122(x)
+ else
+ fun_l18_n979(x)
+ end
+end
+
+def fun_l17_n773(x)
+ if (x < 1)
+ fun_l18_n549(x)
+ else
+ fun_l18_n296(x)
+ end
+end
+
+def fun_l17_n774(x)
+ if (x < 1)
+ fun_l18_n82(x)
+ else
+ fun_l18_n748(x)
+ end
+end
+
+def fun_l17_n775(x)
+ if (x < 1)
+ fun_l18_n958(x)
+ else
+ fun_l18_n917(x)
+ end
+end
+
+def fun_l17_n776(x)
+ if (x < 1)
+ fun_l18_n173(x)
+ else
+ fun_l18_n438(x)
+ end
+end
+
+def fun_l17_n777(x)
+ if (x < 1)
+ fun_l18_n222(x)
+ else
+ fun_l18_n55(x)
+ end
+end
+
+def fun_l17_n778(x)
+ if (x < 1)
+ fun_l18_n529(x)
+ else
+ fun_l18_n548(x)
+ end
+end
+
+def fun_l17_n779(x)
+ if (x < 1)
+ fun_l18_n28(x)
+ else
+ fun_l18_n582(x)
+ end
+end
+
+def fun_l17_n780(x)
+ if (x < 1)
+ fun_l18_n818(x)
+ else
+ fun_l18_n836(x)
+ end
+end
+
+def fun_l17_n781(x)
+ if (x < 1)
+ fun_l18_n972(x)
+ else
+ fun_l18_n73(x)
+ end
+end
+
+def fun_l17_n782(x)
+ if (x < 1)
+ fun_l18_n527(x)
+ else
+ fun_l18_n999(x)
+ end
+end
+
+def fun_l17_n783(x)
+ if (x < 1)
+ fun_l18_n832(x)
+ else
+ fun_l18_n833(x)
+ end
+end
+
+def fun_l17_n784(x)
+ if (x < 1)
+ fun_l18_n987(x)
+ else
+ fun_l18_n329(x)
+ end
+end
+
+def fun_l17_n785(x)
+ if (x < 1)
+ fun_l18_n715(x)
+ else
+ fun_l18_n441(x)
+ end
+end
+
+def fun_l17_n786(x)
+ if (x < 1)
+ fun_l18_n55(x)
+ else
+ fun_l18_n682(x)
+ end
+end
+
+def fun_l17_n787(x)
+ if (x < 1)
+ fun_l18_n606(x)
+ else
+ fun_l18_n656(x)
+ end
+end
+
+def fun_l17_n788(x)
+ if (x < 1)
+ fun_l18_n254(x)
+ else
+ fun_l18_n544(x)
+ end
+end
+
+def fun_l17_n789(x)
+ if (x < 1)
+ fun_l18_n285(x)
+ else
+ fun_l18_n585(x)
+ end
+end
+
+def fun_l17_n790(x)
+ if (x < 1)
+ fun_l18_n441(x)
+ else
+ fun_l18_n716(x)
+ end
+end
+
+def fun_l17_n791(x)
+ if (x < 1)
+ fun_l18_n415(x)
+ else
+ fun_l18_n126(x)
+ end
+end
+
+def fun_l17_n792(x)
+ if (x < 1)
+ fun_l18_n490(x)
+ else
+ fun_l18_n753(x)
+ end
+end
+
+def fun_l17_n793(x)
+ if (x < 1)
+ fun_l18_n324(x)
+ else
+ fun_l18_n223(x)
+ end
+end
+
+def fun_l17_n794(x)
+ if (x < 1)
+ fun_l18_n913(x)
+ else
+ fun_l18_n94(x)
+ end
+end
+
+def fun_l17_n795(x)
+ if (x < 1)
+ fun_l18_n879(x)
+ else
+ fun_l18_n404(x)
+ end
+end
+
+def fun_l17_n796(x)
+ if (x < 1)
+ fun_l18_n309(x)
+ else
+ fun_l18_n65(x)
+ end
+end
+
+def fun_l17_n797(x)
+ if (x < 1)
+ fun_l18_n712(x)
+ else
+ fun_l18_n947(x)
+ end
+end
+
+def fun_l17_n798(x)
+ if (x < 1)
+ fun_l18_n238(x)
+ else
+ fun_l18_n83(x)
+ end
+end
+
+def fun_l17_n799(x)
+ if (x < 1)
+ fun_l18_n25(x)
+ else
+ fun_l18_n371(x)
+ end
+end
+
+def fun_l17_n800(x)
+ if (x < 1)
+ fun_l18_n501(x)
+ else
+ fun_l18_n386(x)
+ end
+end
+
+def fun_l17_n801(x)
+ if (x < 1)
+ fun_l18_n453(x)
+ else
+ fun_l18_n168(x)
+ end
+end
+
+def fun_l17_n802(x)
+ if (x < 1)
+ fun_l18_n763(x)
+ else
+ fun_l18_n675(x)
+ end
+end
+
+def fun_l17_n803(x)
+ if (x < 1)
+ fun_l18_n984(x)
+ else
+ fun_l18_n882(x)
+ end
+end
+
+def fun_l17_n804(x)
+ if (x < 1)
+ fun_l18_n545(x)
+ else
+ fun_l18_n79(x)
+ end
+end
+
+def fun_l17_n805(x)
+ if (x < 1)
+ fun_l18_n263(x)
+ else
+ fun_l18_n143(x)
+ end
+end
+
+def fun_l17_n806(x)
+ if (x < 1)
+ fun_l18_n232(x)
+ else
+ fun_l18_n864(x)
+ end
+end
+
+def fun_l17_n807(x)
+ if (x < 1)
+ fun_l18_n6(x)
+ else
+ fun_l18_n983(x)
+ end
+end
+
+def fun_l17_n808(x)
+ if (x < 1)
+ fun_l18_n17(x)
+ else
+ fun_l18_n426(x)
+ end
+end
+
+def fun_l17_n809(x)
+ if (x < 1)
+ fun_l18_n1(x)
+ else
+ fun_l18_n669(x)
+ end
+end
+
+def fun_l17_n810(x)
+ if (x < 1)
+ fun_l18_n191(x)
+ else
+ fun_l18_n540(x)
+ end
+end
+
+def fun_l17_n811(x)
+ if (x < 1)
+ fun_l18_n16(x)
+ else
+ fun_l18_n871(x)
+ end
+end
+
+def fun_l17_n812(x)
+ if (x < 1)
+ fun_l18_n352(x)
+ else
+ fun_l18_n156(x)
+ end
+end
+
+def fun_l17_n813(x)
+ if (x < 1)
+ fun_l18_n239(x)
+ else
+ fun_l18_n314(x)
+ end
+end
+
+def fun_l17_n814(x)
+ if (x < 1)
+ fun_l18_n890(x)
+ else
+ fun_l18_n21(x)
+ end
+end
+
+def fun_l17_n815(x)
+ if (x < 1)
+ fun_l18_n894(x)
+ else
+ fun_l18_n894(x)
+ end
+end
+
+def fun_l17_n816(x)
+ if (x < 1)
+ fun_l18_n75(x)
+ else
+ fun_l18_n631(x)
+ end
+end
+
+def fun_l17_n817(x)
+ if (x < 1)
+ fun_l18_n118(x)
+ else
+ fun_l18_n857(x)
+ end
+end
+
+def fun_l17_n818(x)
+ if (x < 1)
+ fun_l18_n403(x)
+ else
+ fun_l18_n364(x)
+ end
+end
+
+def fun_l17_n819(x)
+ if (x < 1)
+ fun_l18_n15(x)
+ else
+ fun_l18_n232(x)
+ end
+end
+
+def fun_l17_n820(x)
+ if (x < 1)
+ fun_l18_n610(x)
+ else
+ fun_l18_n43(x)
+ end
+end
+
+def fun_l17_n821(x)
+ if (x < 1)
+ fun_l18_n949(x)
+ else
+ fun_l18_n884(x)
+ end
+end
+
+def fun_l17_n822(x)
+ if (x < 1)
+ fun_l18_n387(x)
+ else
+ fun_l18_n587(x)
+ end
+end
+
+def fun_l17_n823(x)
+ if (x < 1)
+ fun_l18_n99(x)
+ else
+ fun_l18_n653(x)
+ end
+end
+
+def fun_l17_n824(x)
+ if (x < 1)
+ fun_l18_n41(x)
+ else
+ fun_l18_n822(x)
+ end
+end
+
+def fun_l17_n825(x)
+ if (x < 1)
+ fun_l18_n325(x)
+ else
+ fun_l18_n735(x)
+ end
+end
+
+def fun_l17_n826(x)
+ if (x < 1)
+ fun_l18_n415(x)
+ else
+ fun_l18_n684(x)
+ end
+end
+
+def fun_l17_n827(x)
+ if (x < 1)
+ fun_l18_n856(x)
+ else
+ fun_l18_n257(x)
+ end
+end
+
+def fun_l17_n828(x)
+ if (x < 1)
+ fun_l18_n455(x)
+ else
+ fun_l18_n200(x)
+ end
+end
+
+def fun_l17_n829(x)
+ if (x < 1)
+ fun_l18_n486(x)
+ else
+ fun_l18_n528(x)
+ end
+end
+
+def fun_l17_n830(x)
+ if (x < 1)
+ fun_l18_n321(x)
+ else
+ fun_l18_n619(x)
+ end
+end
+
+def fun_l17_n831(x)
+ if (x < 1)
+ fun_l18_n910(x)
+ else
+ fun_l18_n796(x)
+ end
+end
+
+def fun_l17_n832(x)
+ if (x < 1)
+ fun_l18_n303(x)
+ else
+ fun_l18_n278(x)
+ end
+end
+
+def fun_l17_n833(x)
+ if (x < 1)
+ fun_l18_n477(x)
+ else
+ fun_l18_n733(x)
+ end
+end
+
+def fun_l17_n834(x)
+ if (x < 1)
+ fun_l18_n320(x)
+ else
+ fun_l18_n801(x)
+ end
+end
+
+def fun_l17_n835(x)
+ if (x < 1)
+ fun_l18_n672(x)
+ else
+ fun_l18_n183(x)
+ end
+end
+
+def fun_l17_n836(x)
+ if (x < 1)
+ fun_l18_n810(x)
+ else
+ fun_l18_n923(x)
+ end
+end
+
+def fun_l17_n837(x)
+ if (x < 1)
+ fun_l18_n775(x)
+ else
+ fun_l18_n884(x)
+ end
+end
+
+def fun_l17_n838(x)
+ if (x < 1)
+ fun_l18_n9(x)
+ else
+ fun_l18_n690(x)
+ end
+end
+
+def fun_l17_n839(x)
+ if (x < 1)
+ fun_l18_n843(x)
+ else
+ fun_l18_n482(x)
+ end
+end
+
+def fun_l17_n840(x)
+ if (x < 1)
+ fun_l18_n527(x)
+ else
+ fun_l18_n331(x)
+ end
+end
+
+def fun_l17_n841(x)
+ if (x < 1)
+ fun_l18_n210(x)
+ else
+ fun_l18_n119(x)
+ end
+end
+
+def fun_l17_n842(x)
+ if (x < 1)
+ fun_l18_n365(x)
+ else
+ fun_l18_n752(x)
+ end
+end
+
+def fun_l17_n843(x)
+ if (x < 1)
+ fun_l18_n855(x)
+ else
+ fun_l18_n149(x)
+ end
+end
+
+def fun_l17_n844(x)
+ if (x < 1)
+ fun_l18_n822(x)
+ else
+ fun_l18_n852(x)
+ end
+end
+
+def fun_l17_n845(x)
+ if (x < 1)
+ fun_l18_n182(x)
+ else
+ fun_l18_n145(x)
+ end
+end
+
+def fun_l17_n846(x)
+ if (x < 1)
+ fun_l18_n167(x)
+ else
+ fun_l18_n47(x)
+ end
+end
+
+def fun_l17_n847(x)
+ if (x < 1)
+ fun_l18_n350(x)
+ else
+ fun_l18_n894(x)
+ end
+end
+
+def fun_l17_n848(x)
+ if (x < 1)
+ fun_l18_n264(x)
+ else
+ fun_l18_n739(x)
+ end
+end
+
+def fun_l17_n849(x)
+ if (x < 1)
+ fun_l18_n475(x)
+ else
+ fun_l18_n974(x)
+ end
+end
+
+def fun_l17_n850(x)
+ if (x < 1)
+ fun_l18_n849(x)
+ else
+ fun_l18_n68(x)
+ end
+end
+
+def fun_l17_n851(x)
+ if (x < 1)
+ fun_l18_n160(x)
+ else
+ fun_l18_n173(x)
+ end
+end
+
+def fun_l17_n852(x)
+ if (x < 1)
+ fun_l18_n353(x)
+ else
+ fun_l18_n931(x)
+ end
+end
+
+def fun_l17_n853(x)
+ if (x < 1)
+ fun_l18_n706(x)
+ else
+ fun_l18_n540(x)
+ end
+end
+
+def fun_l17_n854(x)
+ if (x < 1)
+ fun_l18_n559(x)
+ else
+ fun_l18_n149(x)
+ end
+end
+
+def fun_l17_n855(x)
+ if (x < 1)
+ fun_l18_n347(x)
+ else
+ fun_l18_n559(x)
+ end
+end
+
+def fun_l17_n856(x)
+ if (x < 1)
+ fun_l18_n640(x)
+ else
+ fun_l18_n529(x)
+ end
+end
+
+def fun_l17_n857(x)
+ if (x < 1)
+ fun_l18_n410(x)
+ else
+ fun_l18_n278(x)
+ end
+end
+
+def fun_l17_n858(x)
+ if (x < 1)
+ fun_l18_n15(x)
+ else
+ fun_l18_n21(x)
+ end
+end
+
+def fun_l17_n859(x)
+ if (x < 1)
+ fun_l18_n180(x)
+ else
+ fun_l18_n530(x)
+ end
+end
+
+def fun_l17_n860(x)
+ if (x < 1)
+ fun_l18_n739(x)
+ else
+ fun_l18_n817(x)
+ end
+end
+
+def fun_l17_n861(x)
+ if (x < 1)
+ fun_l18_n341(x)
+ else
+ fun_l18_n962(x)
+ end
+end
+
+def fun_l17_n862(x)
+ if (x < 1)
+ fun_l18_n994(x)
+ else
+ fun_l18_n338(x)
+ end
+end
+
+def fun_l17_n863(x)
+ if (x < 1)
+ fun_l18_n428(x)
+ else
+ fun_l18_n608(x)
+ end
+end
+
+def fun_l17_n864(x)
+ if (x < 1)
+ fun_l18_n889(x)
+ else
+ fun_l18_n974(x)
+ end
+end
+
+def fun_l17_n865(x)
+ if (x < 1)
+ fun_l18_n300(x)
+ else
+ fun_l18_n164(x)
+ end
+end
+
+def fun_l17_n866(x)
+ if (x < 1)
+ fun_l18_n195(x)
+ else
+ fun_l18_n75(x)
+ end
+end
+
+def fun_l17_n867(x)
+ if (x < 1)
+ fun_l18_n725(x)
+ else
+ fun_l18_n639(x)
+ end
+end
+
+def fun_l17_n868(x)
+ if (x < 1)
+ fun_l18_n793(x)
+ else
+ fun_l18_n925(x)
+ end
+end
+
+def fun_l17_n869(x)
+ if (x < 1)
+ fun_l18_n845(x)
+ else
+ fun_l18_n174(x)
+ end
+end
+
+def fun_l17_n870(x)
+ if (x < 1)
+ fun_l18_n202(x)
+ else
+ fun_l18_n376(x)
+ end
+end
+
+def fun_l17_n871(x)
+ if (x < 1)
+ fun_l18_n503(x)
+ else
+ fun_l18_n441(x)
+ end
+end
+
+def fun_l17_n872(x)
+ if (x < 1)
+ fun_l18_n675(x)
+ else
+ fun_l18_n180(x)
+ end
+end
+
+def fun_l17_n873(x)
+ if (x < 1)
+ fun_l18_n457(x)
+ else
+ fun_l18_n286(x)
+ end
+end
+
+def fun_l17_n874(x)
+ if (x < 1)
+ fun_l18_n918(x)
+ else
+ fun_l18_n438(x)
+ end
+end
+
+def fun_l17_n875(x)
+ if (x < 1)
+ fun_l18_n269(x)
+ else
+ fun_l18_n539(x)
+ end
+end
+
+def fun_l17_n876(x)
+ if (x < 1)
+ fun_l18_n417(x)
+ else
+ fun_l18_n68(x)
+ end
+end
+
+def fun_l17_n877(x)
+ if (x < 1)
+ fun_l18_n382(x)
+ else
+ fun_l18_n392(x)
+ end
+end
+
+def fun_l17_n878(x)
+ if (x < 1)
+ fun_l18_n981(x)
+ else
+ fun_l18_n997(x)
+ end
+end
+
+def fun_l17_n879(x)
+ if (x < 1)
+ fun_l18_n8(x)
+ else
+ fun_l18_n255(x)
+ end
+end
+
+def fun_l17_n880(x)
+ if (x < 1)
+ fun_l18_n634(x)
+ else
+ fun_l18_n971(x)
+ end
+end
+
+def fun_l17_n881(x)
+ if (x < 1)
+ fun_l18_n940(x)
+ else
+ fun_l18_n410(x)
+ end
+end
+
+def fun_l17_n882(x)
+ if (x < 1)
+ fun_l18_n550(x)
+ else
+ fun_l18_n959(x)
+ end
+end
+
+def fun_l17_n883(x)
+ if (x < 1)
+ fun_l18_n258(x)
+ else
+ fun_l18_n766(x)
+ end
+end
+
+def fun_l17_n884(x)
+ if (x < 1)
+ fun_l18_n841(x)
+ else
+ fun_l18_n387(x)
+ end
+end
+
+def fun_l17_n885(x)
+ if (x < 1)
+ fun_l18_n357(x)
+ else
+ fun_l18_n128(x)
+ end
+end
+
+def fun_l17_n886(x)
+ if (x < 1)
+ fun_l18_n872(x)
+ else
+ fun_l18_n471(x)
+ end
+end
+
+def fun_l17_n887(x)
+ if (x < 1)
+ fun_l18_n596(x)
+ else
+ fun_l18_n639(x)
+ end
+end
+
+def fun_l17_n888(x)
+ if (x < 1)
+ fun_l18_n665(x)
+ else
+ fun_l18_n999(x)
+ end
+end
+
+def fun_l17_n889(x)
+ if (x < 1)
+ fun_l18_n898(x)
+ else
+ fun_l18_n899(x)
+ end
+end
+
+def fun_l17_n890(x)
+ if (x < 1)
+ fun_l18_n457(x)
+ else
+ fun_l18_n370(x)
+ end
+end
+
+def fun_l17_n891(x)
+ if (x < 1)
+ fun_l18_n100(x)
+ else
+ fun_l18_n899(x)
+ end
+end
+
+def fun_l17_n892(x)
+ if (x < 1)
+ fun_l18_n785(x)
+ else
+ fun_l18_n552(x)
+ end
+end
+
+def fun_l17_n893(x)
+ if (x < 1)
+ fun_l18_n386(x)
+ else
+ fun_l18_n971(x)
+ end
+end
+
+def fun_l17_n894(x)
+ if (x < 1)
+ fun_l18_n128(x)
+ else
+ fun_l18_n28(x)
+ end
+end
+
+def fun_l17_n895(x)
+ if (x < 1)
+ fun_l18_n18(x)
+ else
+ fun_l18_n682(x)
+ end
+end
+
+def fun_l17_n896(x)
+ if (x < 1)
+ fun_l18_n470(x)
+ else
+ fun_l18_n477(x)
+ end
+end
+
+def fun_l17_n897(x)
+ if (x < 1)
+ fun_l18_n543(x)
+ else
+ fun_l18_n943(x)
+ end
+end
+
+def fun_l17_n898(x)
+ if (x < 1)
+ fun_l18_n554(x)
+ else
+ fun_l18_n431(x)
+ end
+end
+
+def fun_l17_n899(x)
+ if (x < 1)
+ fun_l18_n615(x)
+ else
+ fun_l18_n480(x)
+ end
+end
+
+def fun_l17_n900(x)
+ if (x < 1)
+ fun_l18_n557(x)
+ else
+ fun_l18_n831(x)
+ end
+end
+
+def fun_l17_n901(x)
+ if (x < 1)
+ fun_l18_n245(x)
+ else
+ fun_l18_n79(x)
+ end
+end
+
+def fun_l17_n902(x)
+ if (x < 1)
+ fun_l18_n332(x)
+ else
+ fun_l18_n536(x)
+ end
+end
+
+def fun_l17_n903(x)
+ if (x < 1)
+ fun_l18_n531(x)
+ else
+ fun_l18_n933(x)
+ end
+end
+
+def fun_l17_n904(x)
+ if (x < 1)
+ fun_l18_n748(x)
+ else
+ fun_l18_n210(x)
+ end
+end
+
+def fun_l17_n905(x)
+ if (x < 1)
+ fun_l18_n351(x)
+ else
+ fun_l18_n698(x)
+ end
+end
+
+def fun_l17_n906(x)
+ if (x < 1)
+ fun_l18_n112(x)
+ else
+ fun_l18_n397(x)
+ end
+end
+
+def fun_l17_n907(x)
+ if (x < 1)
+ fun_l18_n177(x)
+ else
+ fun_l18_n826(x)
+ end
+end
+
+def fun_l17_n908(x)
+ if (x < 1)
+ fun_l18_n635(x)
+ else
+ fun_l18_n885(x)
+ end
+end
+
+def fun_l17_n909(x)
+ if (x < 1)
+ fun_l18_n225(x)
+ else
+ fun_l18_n139(x)
+ end
+end
+
+def fun_l17_n910(x)
+ if (x < 1)
+ fun_l18_n30(x)
+ else
+ fun_l18_n113(x)
+ end
+end
+
+def fun_l17_n911(x)
+ if (x < 1)
+ fun_l18_n5(x)
+ else
+ fun_l18_n324(x)
+ end
+end
+
+def fun_l17_n912(x)
+ if (x < 1)
+ fun_l18_n626(x)
+ else
+ fun_l18_n326(x)
+ end
+end
+
+def fun_l17_n913(x)
+ if (x < 1)
+ fun_l18_n478(x)
+ else
+ fun_l18_n373(x)
+ end
+end
+
+def fun_l17_n914(x)
+ if (x < 1)
+ fun_l18_n348(x)
+ else
+ fun_l18_n420(x)
+ end
+end
+
+def fun_l17_n915(x)
+ if (x < 1)
+ fun_l18_n777(x)
+ else
+ fun_l18_n185(x)
+ end
+end
+
+def fun_l17_n916(x)
+ if (x < 1)
+ fun_l18_n18(x)
+ else
+ fun_l18_n286(x)
+ end
+end
+
+def fun_l17_n917(x)
+ if (x < 1)
+ fun_l18_n199(x)
+ else
+ fun_l18_n378(x)
+ end
+end
+
+def fun_l17_n918(x)
+ if (x < 1)
+ fun_l18_n282(x)
+ else
+ fun_l18_n617(x)
+ end
+end
+
+def fun_l17_n919(x)
+ if (x < 1)
+ fun_l18_n634(x)
+ else
+ fun_l18_n396(x)
+ end
+end
+
+def fun_l17_n920(x)
+ if (x < 1)
+ fun_l18_n630(x)
+ else
+ fun_l18_n479(x)
+ end
+end
+
+def fun_l17_n921(x)
+ if (x < 1)
+ fun_l18_n828(x)
+ else
+ fun_l18_n189(x)
+ end
+end
+
+def fun_l17_n922(x)
+ if (x < 1)
+ fun_l18_n468(x)
+ else
+ fun_l18_n400(x)
+ end
+end
+
+def fun_l17_n923(x)
+ if (x < 1)
+ fun_l18_n815(x)
+ else
+ fun_l18_n0(x)
+ end
+end
+
+def fun_l17_n924(x)
+ if (x < 1)
+ fun_l18_n796(x)
+ else
+ fun_l18_n357(x)
+ end
+end
+
+def fun_l17_n925(x)
+ if (x < 1)
+ fun_l18_n4(x)
+ else
+ fun_l18_n293(x)
+ end
+end
+
+def fun_l17_n926(x)
+ if (x < 1)
+ fun_l18_n187(x)
+ else
+ fun_l18_n131(x)
+ end
+end
+
+def fun_l17_n927(x)
+ if (x < 1)
+ fun_l18_n896(x)
+ else
+ fun_l18_n257(x)
+ end
+end
+
+def fun_l17_n928(x)
+ if (x < 1)
+ fun_l18_n596(x)
+ else
+ fun_l18_n115(x)
+ end
+end
+
+def fun_l17_n929(x)
+ if (x < 1)
+ fun_l18_n630(x)
+ else
+ fun_l18_n62(x)
+ end
+end
+
+def fun_l17_n930(x)
+ if (x < 1)
+ fun_l18_n776(x)
+ else
+ fun_l18_n664(x)
+ end
+end
+
+def fun_l17_n931(x)
+ if (x < 1)
+ fun_l18_n424(x)
+ else
+ fun_l18_n298(x)
+ end
+end
+
+def fun_l17_n932(x)
+ if (x < 1)
+ fun_l18_n734(x)
+ else
+ fun_l18_n652(x)
+ end
+end
+
+def fun_l17_n933(x)
+ if (x < 1)
+ fun_l18_n796(x)
+ else
+ fun_l18_n8(x)
+ end
+end
+
+def fun_l17_n934(x)
+ if (x < 1)
+ fun_l18_n783(x)
+ else
+ fun_l18_n177(x)
+ end
+end
+
+def fun_l17_n935(x)
+ if (x < 1)
+ fun_l18_n288(x)
+ else
+ fun_l18_n274(x)
+ end
+end
+
+def fun_l17_n936(x)
+ if (x < 1)
+ fun_l18_n289(x)
+ else
+ fun_l18_n938(x)
+ end
+end
+
+def fun_l17_n937(x)
+ if (x < 1)
+ fun_l18_n815(x)
+ else
+ fun_l18_n924(x)
+ end
+end
+
+def fun_l17_n938(x)
+ if (x < 1)
+ fun_l18_n145(x)
+ else
+ fun_l18_n497(x)
+ end
+end
+
+def fun_l17_n939(x)
+ if (x < 1)
+ fun_l18_n433(x)
+ else
+ fun_l18_n628(x)
+ end
+end
+
+def fun_l17_n940(x)
+ if (x < 1)
+ fun_l18_n410(x)
+ else
+ fun_l18_n461(x)
+ end
+end
+
+def fun_l17_n941(x)
+ if (x < 1)
+ fun_l18_n682(x)
+ else
+ fun_l18_n81(x)
+ end
+end
+
+def fun_l17_n942(x)
+ if (x < 1)
+ fun_l18_n948(x)
+ else
+ fun_l18_n29(x)
+ end
+end
+
+def fun_l17_n943(x)
+ if (x < 1)
+ fun_l18_n78(x)
+ else
+ fun_l18_n237(x)
+ end
+end
+
+def fun_l17_n944(x)
+ if (x < 1)
+ fun_l18_n683(x)
+ else
+ fun_l18_n936(x)
+ end
+end
+
+def fun_l17_n945(x)
+ if (x < 1)
+ fun_l18_n339(x)
+ else
+ fun_l18_n471(x)
+ end
+end
+
+def fun_l17_n946(x)
+ if (x < 1)
+ fun_l18_n903(x)
+ else
+ fun_l18_n983(x)
+ end
+end
+
+def fun_l17_n947(x)
+ if (x < 1)
+ fun_l18_n231(x)
+ else
+ fun_l18_n985(x)
+ end
+end
+
+def fun_l17_n948(x)
+ if (x < 1)
+ fun_l18_n379(x)
+ else
+ fun_l18_n385(x)
+ end
+end
+
+def fun_l17_n949(x)
+ if (x < 1)
+ fun_l18_n89(x)
+ else
+ fun_l18_n499(x)
+ end
+end
+
+def fun_l17_n950(x)
+ if (x < 1)
+ fun_l18_n851(x)
+ else
+ fun_l18_n563(x)
+ end
+end
+
+def fun_l17_n951(x)
+ if (x < 1)
+ fun_l18_n803(x)
+ else
+ fun_l18_n109(x)
+ end
+end
+
+def fun_l17_n952(x)
+ if (x < 1)
+ fun_l18_n178(x)
+ else
+ fun_l18_n886(x)
+ end
+end
+
+def fun_l17_n953(x)
+ if (x < 1)
+ fun_l18_n705(x)
+ else
+ fun_l18_n340(x)
+ end
+end
+
+def fun_l17_n954(x)
+ if (x < 1)
+ fun_l18_n207(x)
+ else
+ fun_l18_n499(x)
+ end
+end
+
+def fun_l17_n955(x)
+ if (x < 1)
+ fun_l18_n298(x)
+ else
+ fun_l18_n921(x)
+ end
+end
+
+def fun_l17_n956(x)
+ if (x < 1)
+ fun_l18_n291(x)
+ else
+ fun_l18_n768(x)
+ end
+end
+
+def fun_l17_n957(x)
+ if (x < 1)
+ fun_l18_n144(x)
+ else
+ fun_l18_n316(x)
+ end
+end
+
+def fun_l17_n958(x)
+ if (x < 1)
+ fun_l18_n375(x)
+ else
+ fun_l18_n891(x)
+ end
+end
+
+def fun_l17_n959(x)
+ if (x < 1)
+ fun_l18_n989(x)
+ else
+ fun_l18_n773(x)
+ end
+end
+
+def fun_l17_n960(x)
+ if (x < 1)
+ fun_l18_n615(x)
+ else
+ fun_l18_n252(x)
+ end
+end
+
+def fun_l17_n961(x)
+ if (x < 1)
+ fun_l18_n827(x)
+ else
+ fun_l18_n567(x)
+ end
+end
+
+def fun_l17_n962(x)
+ if (x < 1)
+ fun_l18_n792(x)
+ else
+ fun_l18_n81(x)
+ end
+end
+
+def fun_l17_n963(x)
+ if (x < 1)
+ fun_l18_n561(x)
+ else
+ fun_l18_n732(x)
+ end
+end
+
+def fun_l17_n964(x)
+ if (x < 1)
+ fun_l18_n113(x)
+ else
+ fun_l18_n110(x)
+ end
+end
+
+def fun_l17_n965(x)
+ if (x < 1)
+ fun_l18_n321(x)
+ else
+ fun_l18_n557(x)
+ end
+end
+
+def fun_l17_n966(x)
+ if (x < 1)
+ fun_l18_n409(x)
+ else
+ fun_l18_n449(x)
+ end
+end
+
+def fun_l17_n967(x)
+ if (x < 1)
+ fun_l18_n316(x)
+ else
+ fun_l18_n669(x)
+ end
+end
+
+def fun_l17_n968(x)
+ if (x < 1)
+ fun_l18_n190(x)
+ else
+ fun_l18_n450(x)
+ end
+end
+
+def fun_l17_n969(x)
+ if (x < 1)
+ fun_l18_n174(x)
+ else
+ fun_l18_n425(x)
+ end
+end
+
+def fun_l17_n970(x)
+ if (x < 1)
+ fun_l18_n918(x)
+ else
+ fun_l18_n537(x)
+ end
+end
+
+def fun_l17_n971(x)
+ if (x < 1)
+ fun_l18_n923(x)
+ else
+ fun_l18_n998(x)
+ end
+end
+
+def fun_l17_n972(x)
+ if (x < 1)
+ fun_l18_n625(x)
+ else
+ fun_l18_n75(x)
+ end
+end
+
+def fun_l17_n973(x)
+ if (x < 1)
+ fun_l18_n171(x)
+ else
+ fun_l18_n180(x)
+ end
+end
+
+def fun_l17_n974(x)
+ if (x < 1)
+ fun_l18_n430(x)
+ else
+ fun_l18_n659(x)
+ end
+end
+
+def fun_l17_n975(x)
+ if (x < 1)
+ fun_l18_n88(x)
+ else
+ fun_l18_n363(x)
+ end
+end
+
+def fun_l17_n976(x)
+ if (x < 1)
+ fun_l18_n408(x)
+ else
+ fun_l18_n986(x)
+ end
+end
+
+def fun_l17_n977(x)
+ if (x < 1)
+ fun_l18_n988(x)
+ else
+ fun_l18_n818(x)
+ end
+end
+
+def fun_l17_n978(x)
+ if (x < 1)
+ fun_l18_n824(x)
+ else
+ fun_l18_n24(x)
+ end
+end
+
+def fun_l17_n979(x)
+ if (x < 1)
+ fun_l18_n182(x)
+ else
+ fun_l18_n969(x)
+ end
+end
+
+def fun_l17_n980(x)
+ if (x < 1)
+ fun_l18_n187(x)
+ else
+ fun_l18_n615(x)
+ end
+end
+
+def fun_l17_n981(x)
+ if (x < 1)
+ fun_l18_n646(x)
+ else
+ fun_l18_n25(x)
+ end
+end
+
+def fun_l17_n982(x)
+ if (x < 1)
+ fun_l18_n700(x)
+ else
+ fun_l18_n127(x)
+ end
+end
+
+def fun_l17_n983(x)
+ if (x < 1)
+ fun_l18_n153(x)
+ else
+ fun_l18_n831(x)
+ end
+end
+
+def fun_l17_n984(x)
+ if (x < 1)
+ fun_l18_n884(x)
+ else
+ fun_l18_n540(x)
+ end
+end
+
+def fun_l17_n985(x)
+ if (x < 1)
+ fun_l18_n225(x)
+ else
+ fun_l18_n221(x)
+ end
+end
+
+def fun_l17_n986(x)
+ if (x < 1)
+ fun_l18_n431(x)
+ else
+ fun_l18_n884(x)
+ end
+end
+
+def fun_l17_n987(x)
+ if (x < 1)
+ fun_l18_n271(x)
+ else
+ fun_l18_n541(x)
+ end
+end
+
+def fun_l17_n988(x)
+ if (x < 1)
+ fun_l18_n419(x)
+ else
+ fun_l18_n183(x)
+ end
+end
+
+def fun_l17_n989(x)
+ if (x < 1)
+ fun_l18_n85(x)
+ else
+ fun_l18_n51(x)
+ end
+end
+
+def fun_l17_n990(x)
+ if (x < 1)
+ fun_l18_n528(x)
+ else
+ fun_l18_n380(x)
+ end
+end
+
+def fun_l17_n991(x)
+ if (x < 1)
+ fun_l18_n13(x)
+ else
+ fun_l18_n137(x)
+ end
+end
+
+def fun_l17_n992(x)
+ if (x < 1)
+ fun_l18_n655(x)
+ else
+ fun_l18_n344(x)
+ end
+end
+
+def fun_l17_n993(x)
+ if (x < 1)
+ fun_l18_n911(x)
+ else
+ fun_l18_n21(x)
+ end
+end
+
+def fun_l17_n994(x)
+ if (x < 1)
+ fun_l18_n887(x)
+ else
+ fun_l18_n935(x)
+ end
+end
+
+def fun_l17_n995(x)
+ if (x < 1)
+ fun_l18_n206(x)
+ else
+ fun_l18_n374(x)
+ end
+end
+
+def fun_l17_n996(x)
+ if (x < 1)
+ fun_l18_n552(x)
+ else
+ fun_l18_n209(x)
+ end
+end
+
+def fun_l17_n997(x)
+ if (x < 1)
+ fun_l18_n540(x)
+ else
+ fun_l18_n901(x)
+ end
+end
+
+def fun_l17_n998(x)
+ if (x < 1)
+ fun_l18_n547(x)
+ else
+ fun_l18_n304(x)
+ end
+end
+
+def fun_l17_n999(x)
+ if (x < 1)
+ fun_l18_n297(x)
+ else
+ fun_l18_n868(x)
+ end
+end
+
+def fun_l18_n0(x)
+ if (x < 1)
+ fun_l19_n619(x)
+ else
+ fun_l19_n167(x)
+ end
+end
+
+def fun_l18_n1(x)
+ if (x < 1)
+ fun_l19_n669(x)
+ else
+ fun_l19_n962(x)
+ end
+end
+
+def fun_l18_n2(x)
+ if (x < 1)
+ fun_l19_n235(x)
+ else
+ fun_l19_n99(x)
+ end
+end
+
+def fun_l18_n3(x)
+ if (x < 1)
+ fun_l19_n961(x)
+ else
+ fun_l19_n200(x)
+ end
+end
+
+def fun_l18_n4(x)
+ if (x < 1)
+ fun_l19_n812(x)
+ else
+ fun_l19_n764(x)
+ end
+end
+
+def fun_l18_n5(x)
+ if (x < 1)
+ fun_l19_n605(x)
+ else
+ fun_l19_n260(x)
+ end
+end
+
+def fun_l18_n6(x)
+ if (x < 1)
+ fun_l19_n146(x)
+ else
+ fun_l19_n617(x)
+ end
+end
+
+def fun_l18_n7(x)
+ if (x < 1)
+ fun_l19_n181(x)
+ else
+ fun_l19_n31(x)
+ end
+end
+
+def fun_l18_n8(x)
+ if (x < 1)
+ fun_l19_n884(x)
+ else
+ fun_l19_n341(x)
+ end
+end
+
+def fun_l18_n9(x)
+ if (x < 1)
+ fun_l19_n741(x)
+ else
+ fun_l19_n704(x)
+ end
+end
+
+def fun_l18_n10(x)
+ if (x < 1)
+ fun_l19_n610(x)
+ else
+ fun_l19_n24(x)
+ end
+end
+
+def fun_l18_n11(x)
+ if (x < 1)
+ fun_l19_n184(x)
+ else
+ fun_l19_n125(x)
+ end
+end
+
+def fun_l18_n12(x)
+ if (x < 1)
+ fun_l19_n59(x)
+ else
+ fun_l19_n30(x)
+ end
+end
+
+def fun_l18_n13(x)
+ if (x < 1)
+ fun_l19_n255(x)
+ else
+ fun_l19_n18(x)
+ end
+end
+
+def fun_l18_n14(x)
+ if (x < 1)
+ fun_l19_n661(x)
+ else
+ fun_l19_n554(x)
+ end
+end
+
+def fun_l18_n15(x)
+ if (x < 1)
+ fun_l19_n557(x)
+ else
+ fun_l19_n757(x)
+ end
+end
+
+def fun_l18_n16(x)
+ if (x < 1)
+ fun_l19_n946(x)
+ else
+ fun_l19_n403(x)
+ end
+end
+
+def fun_l18_n17(x)
+ if (x < 1)
+ fun_l19_n872(x)
+ else
+ fun_l19_n64(x)
+ end
+end
+
+def fun_l18_n18(x)
+ if (x < 1)
+ fun_l19_n531(x)
+ else
+ fun_l19_n200(x)
+ end
+end
+
+def fun_l18_n19(x)
+ if (x < 1)
+ fun_l19_n172(x)
+ else
+ fun_l19_n319(x)
+ end
+end
+
+def fun_l18_n20(x)
+ if (x < 1)
+ fun_l19_n369(x)
+ else
+ fun_l19_n707(x)
+ end
+end
+
+def fun_l18_n21(x)
+ if (x < 1)
+ fun_l19_n726(x)
+ else
+ fun_l19_n718(x)
+ end
+end
+
+def fun_l18_n22(x)
+ if (x < 1)
+ fun_l19_n169(x)
+ else
+ fun_l19_n117(x)
+ end
+end
+
+def fun_l18_n23(x)
+ if (x < 1)
+ fun_l19_n913(x)
+ else
+ fun_l19_n489(x)
+ end
+end
+
+def fun_l18_n24(x)
+ if (x < 1)
+ fun_l19_n950(x)
+ else
+ fun_l19_n272(x)
+ end
+end
+
+def fun_l18_n25(x)
+ if (x < 1)
+ fun_l19_n835(x)
+ else
+ fun_l19_n341(x)
+ end
+end
+
+def fun_l18_n26(x)
+ if (x < 1)
+ fun_l19_n771(x)
+ else
+ fun_l19_n805(x)
+ end
+end
+
+def fun_l18_n27(x)
+ if (x < 1)
+ fun_l19_n71(x)
+ else
+ fun_l19_n515(x)
+ end
+end
+
+def fun_l18_n28(x)
+ if (x < 1)
+ fun_l19_n472(x)
+ else
+ fun_l19_n807(x)
+ end
+end
+
+def fun_l18_n29(x)
+ if (x < 1)
+ fun_l19_n957(x)
+ else
+ fun_l19_n555(x)
+ end
+end
+
+def fun_l18_n30(x)
+ if (x < 1)
+ fun_l19_n629(x)
+ else
+ fun_l19_n113(x)
+ end
+end
+
+def fun_l18_n31(x)
+ if (x < 1)
+ fun_l19_n791(x)
+ else
+ fun_l19_n340(x)
+ end
+end
+
+def fun_l18_n32(x)
+ if (x < 1)
+ fun_l19_n852(x)
+ else
+ fun_l19_n204(x)
+ end
+end
+
+def fun_l18_n33(x)
+ if (x < 1)
+ fun_l19_n441(x)
+ else
+ fun_l19_n331(x)
+ end
+end
+
+def fun_l18_n34(x)
+ if (x < 1)
+ fun_l19_n51(x)
+ else
+ fun_l19_n199(x)
+ end
+end
+
+def fun_l18_n35(x)
+ if (x < 1)
+ fun_l19_n472(x)
+ else
+ fun_l19_n589(x)
+ end
+end
+
+def fun_l18_n36(x)
+ if (x < 1)
+ fun_l19_n191(x)
+ else
+ fun_l19_n333(x)
+ end
+end
+
+def fun_l18_n37(x)
+ if (x < 1)
+ fun_l19_n412(x)
+ else
+ fun_l19_n661(x)
+ end
+end
+
+def fun_l18_n38(x)
+ if (x < 1)
+ fun_l19_n427(x)
+ else
+ fun_l19_n401(x)
+ end
+end
+
+def fun_l18_n39(x)
+ if (x < 1)
+ fun_l19_n96(x)
+ else
+ fun_l19_n235(x)
+ end
+end
+
+def fun_l18_n40(x)
+ if (x < 1)
+ fun_l19_n984(x)
+ else
+ fun_l19_n586(x)
+ end
+end
+
+def fun_l18_n41(x)
+ if (x < 1)
+ fun_l19_n559(x)
+ else
+ fun_l19_n382(x)
+ end
+end
+
+def fun_l18_n42(x)
+ if (x < 1)
+ fun_l19_n802(x)
+ else
+ fun_l19_n217(x)
+ end
+end
+
+def fun_l18_n43(x)
+ if (x < 1)
+ fun_l19_n693(x)
+ else
+ fun_l19_n178(x)
+ end
+end
+
+def fun_l18_n44(x)
+ if (x < 1)
+ fun_l19_n961(x)
+ else
+ fun_l19_n425(x)
+ end
+end
+
+def fun_l18_n45(x)
+ if (x < 1)
+ fun_l19_n242(x)
+ else
+ fun_l19_n949(x)
+ end
+end
+
+def fun_l18_n46(x)
+ if (x < 1)
+ fun_l19_n418(x)
+ else
+ fun_l19_n462(x)
+ end
+end
+
+def fun_l18_n47(x)
+ if (x < 1)
+ fun_l19_n56(x)
+ else
+ fun_l19_n79(x)
+ end
+end
+
+def fun_l18_n48(x)
+ if (x < 1)
+ fun_l19_n5(x)
+ else
+ fun_l19_n939(x)
+ end
+end
+
+def fun_l18_n49(x)
+ if (x < 1)
+ fun_l19_n4(x)
+ else
+ fun_l19_n262(x)
+ end
+end
+
+def fun_l18_n50(x)
+ if (x < 1)
+ fun_l19_n476(x)
+ else
+ fun_l19_n751(x)
+ end
+end
+
+def fun_l18_n51(x)
+ if (x < 1)
+ fun_l19_n687(x)
+ else
+ fun_l19_n489(x)
+ end
+end
+
+def fun_l18_n52(x)
+ if (x < 1)
+ fun_l19_n965(x)
+ else
+ fun_l19_n198(x)
+ end
+end
+
+def fun_l18_n53(x)
+ if (x < 1)
+ fun_l19_n349(x)
+ else
+ fun_l19_n603(x)
+ end
+end
+
+def fun_l18_n54(x)
+ if (x < 1)
+ fun_l19_n893(x)
+ else
+ fun_l19_n279(x)
+ end
+end
+
+def fun_l18_n55(x)
+ if (x < 1)
+ fun_l19_n816(x)
+ else
+ fun_l19_n922(x)
+ end
+end
+
+def fun_l18_n56(x)
+ if (x < 1)
+ fun_l19_n10(x)
+ else
+ fun_l19_n750(x)
+ end
+end
+
+def fun_l18_n57(x)
+ if (x < 1)
+ fun_l19_n787(x)
+ else
+ fun_l19_n446(x)
+ end
+end
+
+def fun_l18_n58(x)
+ if (x < 1)
+ fun_l19_n662(x)
+ else
+ fun_l19_n636(x)
+ end
+end
+
+def fun_l18_n59(x)
+ if (x < 1)
+ fun_l19_n640(x)
+ else
+ fun_l19_n604(x)
+ end
+end
+
+def fun_l18_n60(x)
+ if (x < 1)
+ fun_l19_n1(x)
+ else
+ fun_l19_n657(x)
+ end
+end
+
+def fun_l18_n61(x)
+ if (x < 1)
+ fun_l19_n657(x)
+ else
+ fun_l19_n516(x)
+ end
+end
+
+def fun_l18_n62(x)
+ if (x < 1)
+ fun_l19_n167(x)
+ else
+ fun_l19_n770(x)
+ end
+end
+
+def fun_l18_n63(x)
+ if (x < 1)
+ fun_l19_n572(x)
+ else
+ fun_l19_n224(x)
+ end
+end
+
+def fun_l18_n64(x)
+ if (x < 1)
+ fun_l19_n564(x)
+ else
+ fun_l19_n64(x)
+ end
+end
+
+def fun_l18_n65(x)
+ if (x < 1)
+ fun_l19_n200(x)
+ else
+ fun_l19_n724(x)
+ end
+end
+
+def fun_l18_n66(x)
+ if (x < 1)
+ fun_l19_n295(x)
+ else
+ fun_l19_n127(x)
+ end
+end
+
+def fun_l18_n67(x)
+ if (x < 1)
+ fun_l19_n81(x)
+ else
+ fun_l19_n757(x)
+ end
+end
+
+def fun_l18_n68(x)
+ if (x < 1)
+ fun_l19_n573(x)
+ else
+ fun_l19_n473(x)
+ end
+end
+
+def fun_l18_n69(x)
+ if (x < 1)
+ fun_l19_n475(x)
+ else
+ fun_l19_n8(x)
+ end
+end
+
+def fun_l18_n70(x)
+ if (x < 1)
+ fun_l19_n564(x)
+ else
+ fun_l19_n74(x)
+ end
+end
+
+def fun_l18_n71(x)
+ if (x < 1)
+ fun_l19_n270(x)
+ else
+ fun_l19_n12(x)
+ end
+end
+
+def fun_l18_n72(x)
+ if (x < 1)
+ fun_l19_n809(x)
+ else
+ fun_l19_n857(x)
+ end
+end
+
+def fun_l18_n73(x)
+ if (x < 1)
+ fun_l19_n329(x)
+ else
+ fun_l19_n850(x)
+ end
+end
+
+def fun_l18_n74(x)
+ if (x < 1)
+ fun_l19_n471(x)
+ else
+ fun_l19_n127(x)
+ end
+end
+
+def fun_l18_n75(x)
+ if (x < 1)
+ fun_l19_n558(x)
+ else
+ fun_l19_n626(x)
+ end
+end
+
+def fun_l18_n76(x)
+ if (x < 1)
+ fun_l19_n648(x)
+ else
+ fun_l19_n687(x)
+ end
+end
+
+def fun_l18_n77(x)
+ if (x < 1)
+ fun_l19_n690(x)
+ else
+ fun_l19_n612(x)
+ end
+end
+
+def fun_l18_n78(x)
+ if (x < 1)
+ fun_l19_n122(x)
+ else
+ fun_l19_n843(x)
+ end
+end
+
+def fun_l18_n79(x)
+ if (x < 1)
+ fun_l19_n375(x)
+ else
+ fun_l19_n56(x)
+ end
+end
+
+def fun_l18_n80(x)
+ if (x < 1)
+ fun_l19_n184(x)
+ else
+ fun_l19_n280(x)
+ end
+end
+
+def fun_l18_n81(x)
+ if (x < 1)
+ fun_l19_n588(x)
+ else
+ fun_l19_n433(x)
+ end
+end
+
+def fun_l18_n82(x)
+ if (x < 1)
+ fun_l19_n144(x)
+ else
+ fun_l19_n754(x)
+ end
+end
+
+def fun_l18_n83(x)
+ if (x < 1)
+ fun_l19_n468(x)
+ else
+ fun_l19_n951(x)
+ end
+end
+
+def fun_l18_n84(x)
+ if (x < 1)
+ fun_l19_n380(x)
+ else
+ fun_l19_n597(x)
+ end
+end
+
+def fun_l18_n85(x)
+ if (x < 1)
+ fun_l19_n651(x)
+ else
+ fun_l19_n756(x)
+ end
+end
+
+def fun_l18_n86(x)
+ if (x < 1)
+ fun_l19_n440(x)
+ else
+ fun_l19_n184(x)
+ end
+end
+
+def fun_l18_n87(x)
+ if (x < 1)
+ fun_l19_n851(x)
+ else
+ fun_l19_n753(x)
+ end
+end
+
+def fun_l18_n88(x)
+ if (x < 1)
+ fun_l19_n808(x)
+ else
+ fun_l19_n102(x)
+ end
+end
+
+def fun_l18_n89(x)
+ if (x < 1)
+ fun_l19_n768(x)
+ else
+ fun_l19_n885(x)
+ end
+end
+
+def fun_l18_n90(x)
+ if (x < 1)
+ fun_l19_n933(x)
+ else
+ fun_l19_n284(x)
+ end
+end
+
+def fun_l18_n91(x)
+ if (x < 1)
+ fun_l19_n234(x)
+ else
+ fun_l19_n927(x)
+ end
+end
+
+def fun_l18_n92(x)
+ if (x < 1)
+ fun_l19_n901(x)
+ else
+ fun_l19_n690(x)
+ end
+end
+
+def fun_l18_n93(x)
+ if (x < 1)
+ fun_l19_n386(x)
+ else
+ fun_l19_n692(x)
+ end
+end
+
+def fun_l18_n94(x)
+ if (x < 1)
+ fun_l19_n572(x)
+ else
+ fun_l19_n795(x)
+ end
+end
+
+def fun_l18_n95(x)
+ if (x < 1)
+ fun_l19_n647(x)
+ else
+ fun_l19_n337(x)
+ end
+end
+
+def fun_l18_n96(x)
+ if (x < 1)
+ fun_l19_n794(x)
+ else
+ fun_l19_n611(x)
+ end
+end
+
+def fun_l18_n97(x)
+ if (x < 1)
+ fun_l19_n752(x)
+ else
+ fun_l19_n548(x)
+ end
+end
+
+def fun_l18_n98(x)
+ if (x < 1)
+ fun_l19_n710(x)
+ else
+ fun_l19_n685(x)
+ end
+end
+
+def fun_l18_n99(x)
+ if (x < 1)
+ fun_l19_n711(x)
+ else
+ fun_l19_n307(x)
+ end
+end
+
+def fun_l18_n100(x)
+ if (x < 1)
+ fun_l19_n834(x)
+ else
+ fun_l19_n355(x)
+ end
+end
+
+def fun_l18_n101(x)
+ if (x < 1)
+ fun_l19_n473(x)
+ else
+ fun_l19_n924(x)
+ end
+end
+
+def fun_l18_n102(x)
+ if (x < 1)
+ fun_l19_n79(x)
+ else
+ fun_l19_n87(x)
+ end
+end
+
+def fun_l18_n103(x)
+ if (x < 1)
+ fun_l19_n27(x)
+ else
+ fun_l19_n914(x)
+ end
+end
+
+def fun_l18_n104(x)
+ if (x < 1)
+ fun_l19_n327(x)
+ else
+ fun_l19_n136(x)
+ end
+end
+
+def fun_l18_n105(x)
+ if (x < 1)
+ fun_l19_n42(x)
+ else
+ fun_l19_n289(x)
+ end
+end
+
+def fun_l18_n106(x)
+ if (x < 1)
+ fun_l19_n371(x)
+ else
+ fun_l19_n453(x)
+ end
+end
+
+def fun_l18_n107(x)
+ if (x < 1)
+ fun_l19_n579(x)
+ else
+ fun_l19_n500(x)
+ end
+end
+
+def fun_l18_n108(x)
+ if (x < 1)
+ fun_l19_n351(x)
+ else
+ fun_l19_n683(x)
+ end
+end
+
+def fun_l18_n109(x)
+ if (x < 1)
+ fun_l19_n831(x)
+ else
+ fun_l19_n310(x)
+ end
+end
+
+def fun_l18_n110(x)
+ if (x < 1)
+ fun_l19_n618(x)
+ else
+ fun_l19_n113(x)
+ end
+end
+
+def fun_l18_n111(x)
+ if (x < 1)
+ fun_l19_n147(x)
+ else
+ fun_l19_n324(x)
+ end
+end
+
+def fun_l18_n112(x)
+ if (x < 1)
+ fun_l19_n97(x)
+ else
+ fun_l19_n901(x)
+ end
+end
+
+def fun_l18_n113(x)
+ if (x < 1)
+ fun_l19_n223(x)
+ else
+ fun_l19_n819(x)
+ end
+end
+
+def fun_l18_n114(x)
+ if (x < 1)
+ fun_l19_n929(x)
+ else
+ fun_l19_n143(x)
+ end
+end
+
+def fun_l18_n115(x)
+ if (x < 1)
+ fun_l19_n697(x)
+ else
+ fun_l19_n934(x)
+ end
+end
+
+def fun_l18_n116(x)
+ if (x < 1)
+ fun_l19_n143(x)
+ else
+ fun_l19_n815(x)
+ end
+end
+
+def fun_l18_n117(x)
+ if (x < 1)
+ fun_l19_n889(x)
+ else
+ fun_l19_n859(x)
+ end
+end
+
+def fun_l18_n118(x)
+ if (x < 1)
+ fun_l19_n233(x)
+ else
+ fun_l19_n6(x)
+ end
+end
+
+def fun_l18_n119(x)
+ if (x < 1)
+ fun_l19_n490(x)
+ else
+ fun_l19_n783(x)
+ end
+end
+
+def fun_l18_n120(x)
+ if (x < 1)
+ fun_l19_n930(x)
+ else
+ fun_l19_n376(x)
+ end
+end
+
+def fun_l18_n121(x)
+ if (x < 1)
+ fun_l19_n567(x)
+ else
+ fun_l19_n882(x)
+ end
+end
+
+def fun_l18_n122(x)
+ if (x < 1)
+ fun_l19_n532(x)
+ else
+ fun_l19_n294(x)
+ end
+end
+
+def fun_l18_n123(x)
+ if (x < 1)
+ fun_l19_n20(x)
+ else
+ fun_l19_n433(x)
+ end
+end
+
+def fun_l18_n124(x)
+ if (x < 1)
+ fun_l19_n301(x)
+ else
+ fun_l19_n591(x)
+ end
+end
+
+def fun_l18_n125(x)
+ if (x < 1)
+ fun_l19_n424(x)
+ else
+ fun_l19_n524(x)
+ end
+end
+
+def fun_l18_n126(x)
+ if (x < 1)
+ fun_l19_n12(x)
+ else
+ fun_l19_n537(x)
+ end
+end
+
+def fun_l18_n127(x)
+ if (x < 1)
+ fun_l19_n548(x)
+ else
+ fun_l19_n850(x)
+ end
+end
+
+def fun_l18_n128(x)
+ if (x < 1)
+ fun_l19_n463(x)
+ else
+ fun_l19_n714(x)
+ end
+end
+
+def fun_l18_n129(x)
+ if (x < 1)
+ fun_l19_n438(x)
+ else
+ fun_l19_n667(x)
+ end
+end
+
+def fun_l18_n130(x)
+ if (x < 1)
+ fun_l19_n481(x)
+ else
+ fun_l19_n236(x)
+ end
+end
+
+def fun_l18_n131(x)
+ if (x < 1)
+ fun_l19_n84(x)
+ else
+ fun_l19_n370(x)
+ end
+end
+
+def fun_l18_n132(x)
+ if (x < 1)
+ fun_l19_n447(x)
+ else
+ fun_l19_n740(x)
+ end
+end
+
+def fun_l18_n133(x)
+ if (x < 1)
+ fun_l19_n807(x)
+ else
+ fun_l19_n595(x)
+ end
+end
+
+def fun_l18_n134(x)
+ if (x < 1)
+ fun_l19_n716(x)
+ else
+ fun_l19_n440(x)
+ end
+end
+
+def fun_l18_n135(x)
+ if (x < 1)
+ fun_l19_n657(x)
+ else
+ fun_l19_n683(x)
+ end
+end
+
+def fun_l18_n136(x)
+ if (x < 1)
+ fun_l19_n683(x)
+ else
+ fun_l19_n344(x)
+ end
+end
+
+def fun_l18_n137(x)
+ if (x < 1)
+ fun_l19_n228(x)
+ else
+ fun_l19_n186(x)
+ end
+end
+
+def fun_l18_n138(x)
+ if (x < 1)
+ fun_l19_n666(x)
+ else
+ fun_l19_n66(x)
+ end
+end
+
+def fun_l18_n139(x)
+ if (x < 1)
+ fun_l19_n416(x)
+ else
+ fun_l19_n398(x)
+ end
+end
+
+def fun_l18_n140(x)
+ if (x < 1)
+ fun_l19_n766(x)
+ else
+ fun_l19_n534(x)
+ end
+end
+
+def fun_l18_n141(x)
+ if (x < 1)
+ fun_l19_n370(x)
+ else
+ fun_l19_n653(x)
+ end
+end
+
+def fun_l18_n142(x)
+ if (x < 1)
+ fun_l19_n953(x)
+ else
+ fun_l19_n917(x)
+ end
+end
+
+def fun_l18_n143(x)
+ if (x < 1)
+ fun_l19_n989(x)
+ else
+ fun_l19_n862(x)
+ end
+end
+
+def fun_l18_n144(x)
+ if (x < 1)
+ fun_l19_n969(x)
+ else
+ fun_l19_n243(x)
+ end
+end
+
+def fun_l18_n145(x)
+ if (x < 1)
+ fun_l19_n379(x)
+ else
+ fun_l19_n315(x)
+ end
+end
+
+def fun_l18_n146(x)
+ if (x < 1)
+ fun_l19_n360(x)
+ else
+ fun_l19_n585(x)
+ end
+end
+
+def fun_l18_n147(x)
+ if (x < 1)
+ fun_l19_n4(x)
+ else
+ fun_l19_n372(x)
+ end
+end
+
+def fun_l18_n148(x)
+ if (x < 1)
+ fun_l19_n395(x)
+ else
+ fun_l19_n817(x)
+ end
+end
+
+def fun_l18_n149(x)
+ if (x < 1)
+ fun_l19_n237(x)
+ else
+ fun_l19_n506(x)
+ end
+end
+
+def fun_l18_n150(x)
+ if (x < 1)
+ fun_l19_n940(x)
+ else
+ fun_l19_n380(x)
+ end
+end
+
+def fun_l18_n151(x)
+ if (x < 1)
+ fun_l19_n190(x)
+ else
+ fun_l19_n925(x)
+ end
+end
+
+def fun_l18_n152(x)
+ if (x < 1)
+ fun_l19_n810(x)
+ else
+ fun_l19_n958(x)
+ end
+end
+
+def fun_l18_n153(x)
+ if (x < 1)
+ fun_l19_n69(x)
+ else
+ fun_l19_n19(x)
+ end
+end
+
+def fun_l18_n154(x)
+ if (x < 1)
+ fun_l19_n984(x)
+ else
+ fun_l19_n149(x)
+ end
+end
+
+def fun_l18_n155(x)
+ if (x < 1)
+ fun_l19_n179(x)
+ else
+ fun_l19_n583(x)
+ end
+end
+
+def fun_l18_n156(x)
+ if (x < 1)
+ fun_l19_n583(x)
+ else
+ fun_l19_n374(x)
+ end
+end
+
+def fun_l18_n157(x)
+ if (x < 1)
+ fun_l19_n908(x)
+ else
+ fun_l19_n769(x)
+ end
+end
+
+def fun_l18_n158(x)
+ if (x < 1)
+ fun_l19_n288(x)
+ else
+ fun_l19_n715(x)
+ end
+end
+
+def fun_l18_n159(x)
+ if (x < 1)
+ fun_l19_n742(x)
+ else
+ fun_l19_n733(x)
+ end
+end
+
+def fun_l18_n160(x)
+ if (x < 1)
+ fun_l19_n994(x)
+ else
+ fun_l19_n434(x)
+ end
+end
+
+def fun_l18_n161(x)
+ if (x < 1)
+ fun_l19_n440(x)
+ else
+ fun_l19_n994(x)
+ end
+end
+
+def fun_l18_n162(x)
+ if (x < 1)
+ fun_l19_n400(x)
+ else
+ fun_l19_n632(x)
+ end
+end
+
+def fun_l18_n163(x)
+ if (x < 1)
+ fun_l19_n237(x)
+ else
+ fun_l19_n369(x)
+ end
+end
+
+def fun_l18_n164(x)
+ if (x < 1)
+ fun_l19_n431(x)
+ else
+ fun_l19_n276(x)
+ end
+end
+
+def fun_l18_n165(x)
+ if (x < 1)
+ fun_l19_n173(x)
+ else
+ fun_l19_n93(x)
+ end
+end
+
+def fun_l18_n166(x)
+ if (x < 1)
+ fun_l19_n875(x)
+ else
+ fun_l19_n568(x)
+ end
+end
+
+def fun_l18_n167(x)
+ if (x < 1)
+ fun_l19_n61(x)
+ else
+ fun_l19_n79(x)
+ end
+end
+
+def fun_l18_n168(x)
+ if (x < 1)
+ fun_l19_n683(x)
+ else
+ fun_l19_n958(x)
+ end
+end
+
+def fun_l18_n169(x)
+ if (x < 1)
+ fun_l19_n419(x)
+ else
+ fun_l19_n648(x)
+ end
+end
+
+def fun_l18_n170(x)
+ if (x < 1)
+ fun_l19_n152(x)
+ else
+ fun_l19_n746(x)
+ end
+end
+
+def fun_l18_n171(x)
+ if (x < 1)
+ fun_l19_n670(x)
+ else
+ fun_l19_n974(x)
+ end
+end
+
+def fun_l18_n172(x)
+ if (x < 1)
+ fun_l19_n142(x)
+ else
+ fun_l19_n751(x)
+ end
+end
+
+def fun_l18_n173(x)
+ if (x < 1)
+ fun_l19_n640(x)
+ else
+ fun_l19_n911(x)
+ end
+end
+
+def fun_l18_n174(x)
+ if (x < 1)
+ fun_l19_n256(x)
+ else
+ fun_l19_n414(x)
+ end
+end
+
+def fun_l18_n175(x)
+ if (x < 1)
+ fun_l19_n207(x)
+ else
+ fun_l19_n80(x)
+ end
+end
+
+def fun_l18_n176(x)
+ if (x < 1)
+ fun_l19_n317(x)
+ else
+ fun_l19_n22(x)
+ end
+end
+
+def fun_l18_n177(x)
+ if (x < 1)
+ fun_l19_n457(x)
+ else
+ fun_l19_n723(x)
+ end
+end
+
+def fun_l18_n178(x)
+ if (x < 1)
+ fun_l19_n36(x)
+ else
+ fun_l19_n44(x)
+ end
+end
+
+def fun_l18_n179(x)
+ if (x < 1)
+ fun_l19_n92(x)
+ else
+ fun_l19_n75(x)
+ end
+end
+
+def fun_l18_n180(x)
+ if (x < 1)
+ fun_l19_n878(x)
+ else
+ fun_l19_n318(x)
+ end
+end
+
+def fun_l18_n181(x)
+ if (x < 1)
+ fun_l19_n499(x)
+ else
+ fun_l19_n462(x)
+ end
+end
+
+def fun_l18_n182(x)
+ if (x < 1)
+ fun_l19_n172(x)
+ else
+ fun_l19_n91(x)
+ end
+end
+
+def fun_l18_n183(x)
+ if (x < 1)
+ fun_l19_n549(x)
+ else
+ fun_l19_n126(x)
+ end
+end
+
+def fun_l18_n184(x)
+ if (x < 1)
+ fun_l19_n484(x)
+ else
+ fun_l19_n45(x)
+ end
+end
+
+def fun_l18_n185(x)
+ if (x < 1)
+ fun_l19_n237(x)
+ else
+ fun_l19_n651(x)
+ end
+end
+
+def fun_l18_n186(x)
+ if (x < 1)
+ fun_l19_n458(x)
+ else
+ fun_l19_n466(x)
+ end
+end
+
+def fun_l18_n187(x)
+ if (x < 1)
+ fun_l19_n856(x)
+ else
+ fun_l19_n184(x)
+ end
+end
+
+def fun_l18_n188(x)
+ if (x < 1)
+ fun_l19_n432(x)
+ else
+ fun_l19_n251(x)
+ end
+end
+
+def fun_l18_n189(x)
+ if (x < 1)
+ fun_l19_n719(x)
+ else
+ fun_l19_n442(x)
+ end
+end
+
+def fun_l18_n190(x)
+ if (x < 1)
+ fun_l19_n516(x)
+ else
+ fun_l19_n331(x)
+ end
+end
+
+def fun_l18_n191(x)
+ if (x < 1)
+ fun_l19_n342(x)
+ else
+ fun_l19_n750(x)
+ end
+end
+
+def fun_l18_n192(x)
+ if (x < 1)
+ fun_l19_n820(x)
+ else
+ fun_l19_n137(x)
+ end
+end
+
+def fun_l18_n193(x)
+ if (x < 1)
+ fun_l19_n514(x)
+ else
+ fun_l19_n594(x)
+ end
+end
+
+def fun_l18_n194(x)
+ if (x < 1)
+ fun_l19_n744(x)
+ else
+ fun_l19_n605(x)
+ end
+end
+
+def fun_l18_n195(x)
+ if (x < 1)
+ fun_l19_n428(x)
+ else
+ fun_l19_n528(x)
+ end
+end
+
+def fun_l18_n196(x)
+ if (x < 1)
+ fun_l19_n291(x)
+ else
+ fun_l19_n382(x)
+ end
+end
+
+def fun_l18_n197(x)
+ if (x < 1)
+ fun_l19_n238(x)
+ else
+ fun_l19_n38(x)
+ end
+end
+
+def fun_l18_n198(x)
+ if (x < 1)
+ fun_l19_n332(x)
+ else
+ fun_l19_n112(x)
+ end
+end
+
+def fun_l18_n199(x)
+ if (x < 1)
+ fun_l19_n703(x)
+ else
+ fun_l19_n108(x)
+ end
+end
+
+def fun_l18_n200(x)
+ if (x < 1)
+ fun_l19_n917(x)
+ else
+ fun_l19_n629(x)
+ end
+end
+
+def fun_l18_n201(x)
+ if (x < 1)
+ fun_l19_n402(x)
+ else
+ fun_l19_n223(x)
+ end
+end
+
+def fun_l18_n202(x)
+ if (x < 1)
+ fun_l19_n9(x)
+ else
+ fun_l19_n318(x)
+ end
+end
+
+def fun_l18_n203(x)
+ if (x < 1)
+ fun_l19_n560(x)
+ else
+ fun_l19_n77(x)
+ end
+end
+
+def fun_l18_n204(x)
+ if (x < 1)
+ fun_l19_n379(x)
+ else
+ fun_l19_n903(x)
+ end
+end
+
+def fun_l18_n205(x)
+ if (x < 1)
+ fun_l19_n185(x)
+ else
+ fun_l19_n174(x)
+ end
+end
+
+def fun_l18_n206(x)
+ if (x < 1)
+ fun_l19_n738(x)
+ else
+ fun_l19_n518(x)
+ end
+end
+
+def fun_l18_n207(x)
+ if (x < 1)
+ fun_l19_n343(x)
+ else
+ fun_l19_n567(x)
+ end
+end
+
+def fun_l18_n208(x)
+ if (x < 1)
+ fun_l19_n546(x)
+ else
+ fun_l19_n370(x)
+ end
+end
+
+def fun_l18_n209(x)
+ if (x < 1)
+ fun_l19_n589(x)
+ else
+ fun_l19_n511(x)
+ end
+end
+
+def fun_l18_n210(x)
+ if (x < 1)
+ fun_l19_n507(x)
+ else
+ fun_l19_n912(x)
+ end
+end
+
+def fun_l18_n211(x)
+ if (x < 1)
+ fun_l19_n779(x)
+ else
+ fun_l19_n133(x)
+ end
+end
+
+def fun_l18_n212(x)
+ if (x < 1)
+ fun_l19_n400(x)
+ else
+ fun_l19_n345(x)
+ end
+end
+
+def fun_l18_n213(x)
+ if (x < 1)
+ fun_l19_n214(x)
+ else
+ fun_l19_n393(x)
+ end
+end
+
+def fun_l18_n214(x)
+ if (x < 1)
+ fun_l19_n829(x)
+ else
+ fun_l19_n769(x)
+ end
+end
+
+def fun_l18_n215(x)
+ if (x < 1)
+ fun_l19_n835(x)
+ else
+ fun_l19_n80(x)
+ end
+end
+
+def fun_l18_n216(x)
+ if (x < 1)
+ fun_l19_n640(x)
+ else
+ fun_l19_n836(x)
+ end
+end
+
+def fun_l18_n217(x)
+ if (x < 1)
+ fun_l19_n861(x)
+ else
+ fun_l19_n801(x)
+ end
+end
+
+def fun_l18_n218(x)
+ if (x < 1)
+ fun_l19_n316(x)
+ else
+ fun_l19_n263(x)
+ end
+end
+
+def fun_l18_n219(x)
+ if (x < 1)
+ fun_l19_n231(x)
+ else
+ fun_l19_n315(x)
+ end
+end
+
+def fun_l18_n220(x)
+ if (x < 1)
+ fun_l19_n700(x)
+ else
+ fun_l19_n276(x)
+ end
+end
+
+def fun_l18_n221(x)
+ if (x < 1)
+ fun_l19_n654(x)
+ else
+ fun_l19_n32(x)
+ end
+end
+
+def fun_l18_n222(x)
+ if (x < 1)
+ fun_l19_n758(x)
+ else
+ fun_l19_n598(x)
+ end
+end
+
+def fun_l18_n223(x)
+ if (x < 1)
+ fun_l19_n819(x)
+ else
+ fun_l19_n764(x)
+ end
+end
+
+def fun_l18_n224(x)
+ if (x < 1)
+ fun_l19_n31(x)
+ else
+ fun_l19_n51(x)
+ end
+end
+
+def fun_l18_n225(x)
+ if (x < 1)
+ fun_l19_n704(x)
+ else
+ fun_l19_n932(x)
+ end
+end
+
+def fun_l18_n226(x)
+ if (x < 1)
+ fun_l19_n635(x)
+ else
+ fun_l19_n411(x)
+ end
+end
+
+def fun_l18_n227(x)
+ if (x < 1)
+ fun_l19_n368(x)
+ else
+ fun_l19_n472(x)
+ end
+end
+
+def fun_l18_n228(x)
+ if (x < 1)
+ fun_l19_n928(x)
+ else
+ fun_l19_n357(x)
+ end
+end
+
+def fun_l18_n229(x)
+ if (x < 1)
+ fun_l19_n503(x)
+ else
+ fun_l19_n495(x)
+ end
+end
+
+def fun_l18_n230(x)
+ if (x < 1)
+ fun_l19_n497(x)
+ else
+ fun_l19_n73(x)
+ end
+end
+
+def fun_l18_n231(x)
+ if (x < 1)
+ fun_l19_n718(x)
+ else
+ fun_l19_n971(x)
+ end
+end
+
+def fun_l18_n232(x)
+ if (x < 1)
+ fun_l19_n314(x)
+ else
+ fun_l19_n100(x)
+ end
+end
+
+def fun_l18_n233(x)
+ if (x < 1)
+ fun_l19_n490(x)
+ else
+ fun_l19_n569(x)
+ end
+end
+
+def fun_l18_n234(x)
+ if (x < 1)
+ fun_l19_n309(x)
+ else
+ fun_l19_n806(x)
+ end
+end
+
+def fun_l18_n235(x)
+ if (x < 1)
+ fun_l19_n839(x)
+ else
+ fun_l19_n388(x)
+ end
+end
+
+def fun_l18_n236(x)
+ if (x < 1)
+ fun_l19_n158(x)
+ else
+ fun_l19_n438(x)
+ end
+end
+
+def fun_l18_n237(x)
+ if (x < 1)
+ fun_l19_n181(x)
+ else
+ fun_l19_n728(x)
+ end
+end
+
+def fun_l18_n238(x)
+ if (x < 1)
+ fun_l19_n238(x)
+ else
+ fun_l19_n41(x)
+ end
+end
+
+def fun_l18_n239(x)
+ if (x < 1)
+ fun_l19_n342(x)
+ else
+ fun_l19_n756(x)
+ end
+end
+
+def fun_l18_n240(x)
+ if (x < 1)
+ fun_l19_n873(x)
+ else
+ fun_l19_n274(x)
+ end
+end
+
+def fun_l18_n241(x)
+ if (x < 1)
+ fun_l19_n273(x)
+ else
+ fun_l19_n740(x)
+ end
+end
+
+def fun_l18_n242(x)
+ if (x < 1)
+ fun_l19_n256(x)
+ else
+ fun_l19_n99(x)
+ end
+end
+
+def fun_l18_n243(x)
+ if (x < 1)
+ fun_l19_n482(x)
+ else
+ fun_l19_n569(x)
+ end
+end
+
+def fun_l18_n244(x)
+ if (x < 1)
+ fun_l19_n598(x)
+ else
+ fun_l19_n393(x)
+ end
+end
+
+def fun_l18_n245(x)
+ if (x < 1)
+ fun_l19_n320(x)
+ else
+ fun_l19_n164(x)
+ end
+end
+
+def fun_l18_n246(x)
+ if (x < 1)
+ fun_l19_n803(x)
+ else
+ fun_l19_n240(x)
+ end
+end
+
+def fun_l18_n247(x)
+ if (x < 1)
+ fun_l19_n790(x)
+ else
+ fun_l19_n55(x)
+ end
+end
+
+def fun_l18_n248(x)
+ if (x < 1)
+ fun_l19_n193(x)
+ else
+ fun_l19_n754(x)
+ end
+end
+
+def fun_l18_n249(x)
+ if (x < 1)
+ fun_l19_n122(x)
+ else
+ fun_l19_n841(x)
+ end
+end
+
+def fun_l18_n250(x)
+ if (x < 1)
+ fun_l19_n724(x)
+ else
+ fun_l19_n359(x)
+ end
+end
+
+def fun_l18_n251(x)
+ if (x < 1)
+ fun_l19_n497(x)
+ else
+ fun_l19_n777(x)
+ end
+end
+
+def fun_l18_n252(x)
+ if (x < 1)
+ fun_l19_n986(x)
+ else
+ fun_l19_n666(x)
+ end
+end
+
+def fun_l18_n253(x)
+ if (x < 1)
+ fun_l19_n864(x)
+ else
+ fun_l19_n320(x)
+ end
+end
+
+def fun_l18_n254(x)
+ if (x < 1)
+ fun_l19_n386(x)
+ else
+ fun_l19_n582(x)
+ end
+end
+
+def fun_l18_n255(x)
+ if (x < 1)
+ fun_l19_n434(x)
+ else
+ fun_l19_n224(x)
+ end
+end
+
+def fun_l18_n256(x)
+ if (x < 1)
+ fun_l19_n921(x)
+ else
+ fun_l19_n8(x)
+ end
+end
+
+def fun_l18_n257(x)
+ if (x < 1)
+ fun_l19_n789(x)
+ else
+ fun_l19_n546(x)
+ end
+end
+
+def fun_l18_n258(x)
+ if (x < 1)
+ fun_l19_n324(x)
+ else
+ fun_l19_n987(x)
+ end
+end
+
+def fun_l18_n259(x)
+ if (x < 1)
+ fun_l19_n279(x)
+ else
+ fun_l19_n180(x)
+ end
+end
+
+def fun_l18_n260(x)
+ if (x < 1)
+ fun_l19_n596(x)
+ else
+ fun_l19_n670(x)
+ end
+end
+
+def fun_l18_n261(x)
+ if (x < 1)
+ fun_l19_n940(x)
+ else
+ fun_l19_n982(x)
+ end
+end
+
+def fun_l18_n262(x)
+ if (x < 1)
+ fun_l19_n54(x)
+ else
+ fun_l19_n342(x)
+ end
+end
+
+def fun_l18_n263(x)
+ if (x < 1)
+ fun_l19_n815(x)
+ else
+ fun_l19_n663(x)
+ end
+end
+
+def fun_l18_n264(x)
+ if (x < 1)
+ fun_l19_n794(x)
+ else
+ fun_l19_n251(x)
+ end
+end
+
+def fun_l18_n265(x)
+ if (x < 1)
+ fun_l19_n485(x)
+ else
+ fun_l19_n896(x)
+ end
+end
+
+def fun_l18_n266(x)
+ if (x < 1)
+ fun_l19_n346(x)
+ else
+ fun_l19_n151(x)
+ end
+end
+
+def fun_l18_n267(x)
+ if (x < 1)
+ fun_l19_n162(x)
+ else
+ fun_l19_n395(x)
+ end
+end
+
+def fun_l18_n268(x)
+ if (x < 1)
+ fun_l19_n76(x)
+ else
+ fun_l19_n25(x)
+ end
+end
+
+def fun_l18_n269(x)
+ if (x < 1)
+ fun_l19_n943(x)
+ else
+ fun_l19_n587(x)
+ end
+end
+
+def fun_l18_n270(x)
+ if (x < 1)
+ fun_l19_n663(x)
+ else
+ fun_l19_n255(x)
+ end
+end
+
+def fun_l18_n271(x)
+ if (x < 1)
+ fun_l19_n307(x)
+ else
+ fun_l19_n261(x)
+ end
+end
+
+def fun_l18_n272(x)
+ if (x < 1)
+ fun_l19_n478(x)
+ else
+ fun_l19_n600(x)
+ end
+end
+
+def fun_l18_n273(x)
+ if (x < 1)
+ fun_l19_n345(x)
+ else
+ fun_l19_n877(x)
+ end
+end
+
+def fun_l18_n274(x)
+ if (x < 1)
+ fun_l19_n637(x)
+ else
+ fun_l19_n27(x)
+ end
+end
+
+def fun_l18_n275(x)
+ if (x < 1)
+ fun_l19_n752(x)
+ else
+ fun_l19_n946(x)
+ end
+end
+
+def fun_l18_n276(x)
+ if (x < 1)
+ fun_l19_n571(x)
+ else
+ fun_l19_n973(x)
+ end
+end
+
+def fun_l18_n277(x)
+ if (x < 1)
+ fun_l19_n274(x)
+ else
+ fun_l19_n673(x)
+ end
+end
+
+def fun_l18_n278(x)
+ if (x < 1)
+ fun_l19_n922(x)
+ else
+ fun_l19_n826(x)
+ end
+end
+
+def fun_l18_n279(x)
+ if (x < 1)
+ fun_l19_n294(x)
+ else
+ fun_l19_n236(x)
+ end
+end
+
+def fun_l18_n280(x)
+ if (x < 1)
+ fun_l19_n661(x)
+ else
+ fun_l19_n531(x)
+ end
+end
+
+def fun_l18_n281(x)
+ if (x < 1)
+ fun_l19_n295(x)
+ else
+ fun_l19_n961(x)
+ end
+end
+
+def fun_l18_n282(x)
+ if (x < 1)
+ fun_l19_n902(x)
+ else
+ fun_l19_n364(x)
+ end
+end
+
+def fun_l18_n283(x)
+ if (x < 1)
+ fun_l19_n147(x)
+ else
+ fun_l19_n709(x)
+ end
+end
+
+def fun_l18_n284(x)
+ if (x < 1)
+ fun_l19_n394(x)
+ else
+ fun_l19_n757(x)
+ end
+end
+
+def fun_l18_n285(x)
+ if (x < 1)
+ fun_l19_n372(x)
+ else
+ fun_l19_n45(x)
+ end
+end
+
+def fun_l18_n286(x)
+ if (x < 1)
+ fun_l19_n323(x)
+ else
+ fun_l19_n128(x)
+ end
+end
+
+def fun_l18_n287(x)
+ if (x < 1)
+ fun_l19_n50(x)
+ else
+ fun_l19_n650(x)
+ end
+end
+
+def fun_l18_n288(x)
+ if (x < 1)
+ fun_l19_n300(x)
+ else
+ fun_l19_n308(x)
+ end
+end
+
+def fun_l18_n289(x)
+ if (x < 1)
+ fun_l19_n2(x)
+ else
+ fun_l19_n27(x)
+ end
+end
+
+def fun_l18_n290(x)
+ if (x < 1)
+ fun_l19_n341(x)
+ else
+ fun_l19_n281(x)
+ end
+end
+
+def fun_l18_n291(x)
+ if (x < 1)
+ fun_l19_n797(x)
+ else
+ fun_l19_n575(x)
+ end
+end
+
+def fun_l18_n292(x)
+ if (x < 1)
+ fun_l19_n740(x)
+ else
+ fun_l19_n772(x)
+ end
+end
+
+def fun_l18_n293(x)
+ if (x < 1)
+ fun_l19_n707(x)
+ else
+ fun_l19_n456(x)
+ end
+end
+
+def fun_l18_n294(x)
+ if (x < 1)
+ fun_l19_n714(x)
+ else
+ fun_l19_n601(x)
+ end
+end
+
+def fun_l18_n295(x)
+ if (x < 1)
+ fun_l19_n298(x)
+ else
+ fun_l19_n367(x)
+ end
+end
+
+def fun_l18_n296(x)
+ if (x < 1)
+ fun_l19_n0(x)
+ else
+ fun_l19_n970(x)
+ end
+end
+
+def fun_l18_n297(x)
+ if (x < 1)
+ fun_l19_n703(x)
+ else
+ fun_l19_n673(x)
+ end
+end
+
+def fun_l18_n298(x)
+ if (x < 1)
+ fun_l19_n890(x)
+ else
+ fun_l19_n932(x)
+ end
+end
+
+def fun_l18_n299(x)
+ if (x < 1)
+ fun_l19_n152(x)
+ else
+ fun_l19_n784(x)
+ end
+end
+
+def fun_l18_n300(x)
+ if (x < 1)
+ fun_l19_n24(x)
+ else
+ fun_l19_n449(x)
+ end
+end
+
+def fun_l18_n301(x)
+ if (x < 1)
+ fun_l19_n161(x)
+ else
+ fun_l19_n51(x)
+ end
+end
+
+def fun_l18_n302(x)
+ if (x < 1)
+ fun_l19_n695(x)
+ else
+ fun_l19_n604(x)
+ end
+end
+
+def fun_l18_n303(x)
+ if (x < 1)
+ fun_l19_n415(x)
+ else
+ fun_l19_n752(x)
+ end
+end
+
+def fun_l18_n304(x)
+ if (x < 1)
+ fun_l19_n737(x)
+ else
+ fun_l19_n944(x)
+ end
+end
+
+def fun_l18_n305(x)
+ if (x < 1)
+ fun_l19_n833(x)
+ else
+ fun_l19_n98(x)
+ end
+end
+
+def fun_l18_n306(x)
+ if (x < 1)
+ fun_l19_n598(x)
+ else
+ fun_l19_n601(x)
+ end
+end
+
+def fun_l18_n307(x)
+ if (x < 1)
+ fun_l19_n728(x)
+ else
+ fun_l19_n116(x)
+ end
+end
+
+def fun_l18_n308(x)
+ if (x < 1)
+ fun_l19_n892(x)
+ else
+ fun_l19_n826(x)
+ end
+end
+
+def fun_l18_n309(x)
+ if (x < 1)
+ fun_l19_n926(x)
+ else
+ fun_l19_n119(x)
+ end
+end
+
+def fun_l18_n310(x)
+ if (x < 1)
+ fun_l19_n194(x)
+ else
+ fun_l19_n331(x)
+ end
+end
+
+def fun_l18_n311(x)
+ if (x < 1)
+ fun_l19_n490(x)
+ else
+ fun_l19_n401(x)
+ end
+end
+
+def fun_l18_n312(x)
+ if (x < 1)
+ fun_l19_n727(x)
+ else
+ fun_l19_n193(x)
+ end
+end
+
+def fun_l18_n313(x)
+ if (x < 1)
+ fun_l19_n643(x)
+ else
+ fun_l19_n327(x)
+ end
+end
+
+def fun_l18_n314(x)
+ if (x < 1)
+ fun_l19_n747(x)
+ else
+ fun_l19_n938(x)
+ end
+end
+
+def fun_l18_n315(x)
+ if (x < 1)
+ fun_l19_n153(x)
+ else
+ fun_l19_n438(x)
+ end
+end
+
+def fun_l18_n316(x)
+ if (x < 1)
+ fun_l19_n719(x)
+ else
+ fun_l19_n471(x)
+ end
+end
+
+def fun_l18_n317(x)
+ if (x < 1)
+ fun_l19_n105(x)
+ else
+ fun_l19_n832(x)
+ end
+end
+
+def fun_l18_n318(x)
+ if (x < 1)
+ fun_l19_n652(x)
+ else
+ fun_l19_n826(x)
+ end
+end
+
+def fun_l18_n319(x)
+ if (x < 1)
+ fun_l19_n3(x)
+ else
+ fun_l19_n250(x)
+ end
+end
+
+def fun_l18_n320(x)
+ if (x < 1)
+ fun_l19_n854(x)
+ else
+ fun_l19_n371(x)
+ end
+end
+
+def fun_l18_n321(x)
+ if (x < 1)
+ fun_l19_n241(x)
+ else
+ fun_l19_n51(x)
+ end
+end
+
+def fun_l18_n322(x)
+ if (x < 1)
+ fun_l19_n832(x)
+ else
+ fun_l19_n897(x)
+ end
+end
+
+def fun_l18_n323(x)
+ if (x < 1)
+ fun_l19_n472(x)
+ else
+ fun_l19_n838(x)
+ end
+end
+
+def fun_l18_n324(x)
+ if (x < 1)
+ fun_l19_n844(x)
+ else
+ fun_l19_n228(x)
+ end
+end
+
+def fun_l18_n325(x)
+ if (x < 1)
+ fun_l19_n132(x)
+ else
+ fun_l19_n424(x)
+ end
+end
+
+def fun_l18_n326(x)
+ if (x < 1)
+ fun_l19_n311(x)
+ else
+ fun_l19_n388(x)
+ end
+end
+
+def fun_l18_n327(x)
+ if (x < 1)
+ fun_l19_n709(x)
+ else
+ fun_l19_n98(x)
+ end
+end
+
+def fun_l18_n328(x)
+ if (x < 1)
+ fun_l19_n342(x)
+ else
+ fun_l19_n743(x)
+ end
+end
+
+def fun_l18_n329(x)
+ if (x < 1)
+ fun_l19_n984(x)
+ else
+ fun_l19_n762(x)
+ end
+end
+
+def fun_l18_n330(x)
+ if (x < 1)
+ fun_l19_n358(x)
+ else
+ fun_l19_n624(x)
+ end
+end
+
+def fun_l18_n331(x)
+ if (x < 1)
+ fun_l19_n574(x)
+ else
+ fun_l19_n35(x)
+ end
+end
+
+def fun_l18_n332(x)
+ if (x < 1)
+ fun_l19_n564(x)
+ else
+ fun_l19_n629(x)
+ end
+end
+
+def fun_l18_n333(x)
+ if (x < 1)
+ fun_l19_n70(x)
+ else
+ fun_l19_n150(x)
+ end
+end
+
+def fun_l18_n334(x)
+ if (x < 1)
+ fun_l19_n538(x)
+ else
+ fun_l19_n239(x)
+ end
+end
+
+def fun_l18_n335(x)
+ if (x < 1)
+ fun_l19_n818(x)
+ else
+ fun_l19_n878(x)
+ end
+end
+
+def fun_l18_n336(x)
+ if (x < 1)
+ fun_l19_n233(x)
+ else
+ fun_l19_n286(x)
+ end
+end
+
+def fun_l18_n337(x)
+ if (x < 1)
+ fun_l19_n731(x)
+ else
+ fun_l19_n416(x)
+ end
+end
+
+def fun_l18_n338(x)
+ if (x < 1)
+ fun_l19_n917(x)
+ else
+ fun_l19_n710(x)
+ end
+end
+
+def fun_l18_n339(x)
+ if (x < 1)
+ fun_l19_n638(x)
+ else
+ fun_l19_n187(x)
+ end
+end
+
+def fun_l18_n340(x)
+ if (x < 1)
+ fun_l19_n922(x)
+ else
+ fun_l19_n767(x)
+ end
+end
+
+def fun_l18_n341(x)
+ if (x < 1)
+ fun_l19_n9(x)
+ else
+ fun_l19_n708(x)
+ end
+end
+
+def fun_l18_n342(x)
+ if (x < 1)
+ fun_l19_n76(x)
+ else
+ fun_l19_n479(x)
+ end
+end
+
+def fun_l18_n343(x)
+ if (x < 1)
+ fun_l19_n679(x)
+ else
+ fun_l19_n85(x)
+ end
+end
+
+def fun_l18_n344(x)
+ if (x < 1)
+ fun_l19_n725(x)
+ else
+ fun_l19_n809(x)
+ end
+end
+
+def fun_l18_n345(x)
+ if (x < 1)
+ fun_l19_n680(x)
+ else
+ fun_l19_n416(x)
+ end
+end
+
+def fun_l18_n346(x)
+ if (x < 1)
+ fun_l19_n66(x)
+ else
+ fun_l19_n36(x)
+ end
+end
+
+def fun_l18_n347(x)
+ if (x < 1)
+ fun_l19_n420(x)
+ else
+ fun_l19_n879(x)
+ end
+end
+
+def fun_l18_n348(x)
+ if (x < 1)
+ fun_l19_n653(x)
+ else
+ fun_l19_n634(x)
+ end
+end
+
+def fun_l18_n349(x)
+ if (x < 1)
+ fun_l19_n134(x)
+ else
+ fun_l19_n840(x)
+ end
+end
+
+def fun_l18_n350(x)
+ if (x < 1)
+ fun_l19_n21(x)
+ else
+ fun_l19_n843(x)
+ end
+end
+
+def fun_l18_n351(x)
+ if (x < 1)
+ fun_l19_n917(x)
+ else
+ fun_l19_n101(x)
+ end
+end
+
+def fun_l18_n352(x)
+ if (x < 1)
+ fun_l19_n541(x)
+ else
+ fun_l19_n646(x)
+ end
+end
+
+def fun_l18_n353(x)
+ if (x < 1)
+ fun_l19_n555(x)
+ else
+ fun_l19_n648(x)
+ end
+end
+
+def fun_l18_n354(x)
+ if (x < 1)
+ fun_l19_n431(x)
+ else
+ fun_l19_n736(x)
+ end
+end
+
+def fun_l18_n355(x)
+ if (x < 1)
+ fun_l19_n294(x)
+ else
+ fun_l19_n512(x)
+ end
+end
+
+def fun_l18_n356(x)
+ if (x < 1)
+ fun_l19_n852(x)
+ else
+ fun_l19_n348(x)
+ end
+end
+
+def fun_l18_n357(x)
+ if (x < 1)
+ fun_l19_n670(x)
+ else
+ fun_l19_n997(x)
+ end
+end
+
+def fun_l18_n358(x)
+ if (x < 1)
+ fun_l19_n595(x)
+ else
+ fun_l19_n544(x)
+ end
+end
+
+def fun_l18_n359(x)
+ if (x < 1)
+ fun_l19_n13(x)
+ else
+ fun_l19_n838(x)
+ end
+end
+
+def fun_l18_n360(x)
+ if (x < 1)
+ fun_l19_n518(x)
+ else
+ fun_l19_n642(x)
+ end
+end
+
+def fun_l18_n361(x)
+ if (x < 1)
+ fun_l19_n333(x)
+ else
+ fun_l19_n59(x)
+ end
+end
+
+def fun_l18_n362(x)
+ if (x < 1)
+ fun_l19_n670(x)
+ else
+ fun_l19_n844(x)
+ end
+end
+
+def fun_l18_n363(x)
+ if (x < 1)
+ fun_l19_n14(x)
+ else
+ fun_l19_n932(x)
+ end
+end
+
+def fun_l18_n364(x)
+ if (x < 1)
+ fun_l19_n508(x)
+ else
+ fun_l19_n466(x)
+ end
+end
+
+def fun_l18_n365(x)
+ if (x < 1)
+ fun_l19_n177(x)
+ else
+ fun_l19_n365(x)
+ end
+end
+
+def fun_l18_n366(x)
+ if (x < 1)
+ fun_l19_n367(x)
+ else
+ fun_l19_n205(x)
+ end
+end
+
+def fun_l18_n367(x)
+ if (x < 1)
+ fun_l19_n353(x)
+ else
+ fun_l19_n328(x)
+ end
+end
+
+def fun_l18_n368(x)
+ if (x < 1)
+ fun_l19_n801(x)
+ else
+ fun_l19_n420(x)
+ end
+end
+
+def fun_l18_n369(x)
+ if (x < 1)
+ fun_l19_n162(x)
+ else
+ fun_l19_n670(x)
+ end
+end
+
+def fun_l18_n370(x)
+ if (x < 1)
+ fun_l19_n908(x)
+ else
+ fun_l19_n852(x)
+ end
+end
+
+def fun_l18_n371(x)
+ if (x < 1)
+ fun_l19_n47(x)
+ else
+ fun_l19_n130(x)
+ end
+end
+
+def fun_l18_n372(x)
+ if (x < 1)
+ fun_l19_n774(x)
+ else
+ fun_l19_n792(x)
+ end
+end
+
+def fun_l18_n373(x)
+ if (x < 1)
+ fun_l19_n124(x)
+ else
+ fun_l19_n665(x)
+ end
+end
+
+def fun_l18_n374(x)
+ if (x < 1)
+ fun_l19_n24(x)
+ else
+ fun_l19_n371(x)
+ end
+end
+
+def fun_l18_n375(x)
+ if (x < 1)
+ fun_l19_n484(x)
+ else
+ fun_l19_n708(x)
+ end
+end
+
+def fun_l18_n376(x)
+ if (x < 1)
+ fun_l19_n810(x)
+ else
+ fun_l19_n856(x)
+ end
+end
+
+def fun_l18_n377(x)
+ if (x < 1)
+ fun_l19_n23(x)
+ else
+ fun_l19_n817(x)
+ end
+end
+
+def fun_l18_n378(x)
+ if (x < 1)
+ fun_l19_n827(x)
+ else
+ fun_l19_n639(x)
+ end
+end
+
+def fun_l18_n379(x)
+ if (x < 1)
+ fun_l19_n557(x)
+ else
+ fun_l19_n268(x)
+ end
+end
+
+def fun_l18_n380(x)
+ if (x < 1)
+ fun_l19_n885(x)
+ else
+ fun_l19_n421(x)
+ end
+end
+
+def fun_l18_n381(x)
+ if (x < 1)
+ fun_l19_n543(x)
+ else
+ fun_l19_n230(x)
+ end
+end
+
+def fun_l18_n382(x)
+ if (x < 1)
+ fun_l19_n978(x)
+ else
+ fun_l19_n848(x)
+ end
+end
+
+def fun_l18_n383(x)
+ if (x < 1)
+ fun_l19_n31(x)
+ else
+ fun_l19_n731(x)
+ end
+end
+
+def fun_l18_n384(x)
+ if (x < 1)
+ fun_l19_n20(x)
+ else
+ fun_l19_n149(x)
+ end
+end
+
+def fun_l18_n385(x)
+ if (x < 1)
+ fun_l19_n650(x)
+ else
+ fun_l19_n268(x)
+ end
+end
+
+def fun_l18_n386(x)
+ if (x < 1)
+ fun_l19_n491(x)
+ else
+ fun_l19_n644(x)
+ end
+end
+
+def fun_l18_n387(x)
+ if (x < 1)
+ fun_l19_n537(x)
+ else
+ fun_l19_n400(x)
+ end
+end
+
+def fun_l18_n388(x)
+ if (x < 1)
+ fun_l19_n939(x)
+ else
+ fun_l19_n861(x)
+ end
+end
+
+def fun_l18_n389(x)
+ if (x < 1)
+ fun_l19_n728(x)
+ else
+ fun_l19_n877(x)
+ end
+end
+
+def fun_l18_n390(x)
+ if (x < 1)
+ fun_l19_n226(x)
+ else
+ fun_l19_n288(x)
+ end
+end
+
+def fun_l18_n391(x)
+ if (x < 1)
+ fun_l19_n921(x)
+ else
+ fun_l19_n754(x)
+ end
+end
+
+def fun_l18_n392(x)
+ if (x < 1)
+ fun_l19_n71(x)
+ else
+ fun_l19_n844(x)
+ end
+end
+
+def fun_l18_n393(x)
+ if (x < 1)
+ fun_l19_n310(x)
+ else
+ fun_l19_n442(x)
+ end
+end
+
+def fun_l18_n394(x)
+ if (x < 1)
+ fun_l19_n539(x)
+ else
+ fun_l19_n933(x)
+ end
+end
+
+def fun_l18_n395(x)
+ if (x < 1)
+ fun_l19_n849(x)
+ else
+ fun_l19_n719(x)
+ end
+end
+
+def fun_l18_n396(x)
+ if (x < 1)
+ fun_l19_n922(x)
+ else
+ fun_l19_n435(x)
+ end
+end
+
+def fun_l18_n397(x)
+ if (x < 1)
+ fun_l19_n916(x)
+ else
+ fun_l19_n399(x)
+ end
+end
+
+def fun_l18_n398(x)
+ if (x < 1)
+ fun_l19_n820(x)
+ else
+ fun_l19_n650(x)
+ end
+end
+
+def fun_l18_n399(x)
+ if (x < 1)
+ fun_l19_n497(x)
+ else
+ fun_l19_n678(x)
+ end
+end
+
+def fun_l18_n400(x)
+ if (x < 1)
+ fun_l19_n562(x)
+ else
+ fun_l19_n392(x)
+ end
+end
+
+def fun_l18_n401(x)
+ if (x < 1)
+ fun_l19_n298(x)
+ else
+ fun_l19_n61(x)
+ end
+end
+
+def fun_l18_n402(x)
+ if (x < 1)
+ fun_l19_n803(x)
+ else
+ fun_l19_n535(x)
+ end
+end
+
+def fun_l18_n403(x)
+ if (x < 1)
+ fun_l19_n335(x)
+ else
+ fun_l19_n431(x)
+ end
+end
+
+def fun_l18_n404(x)
+ if (x < 1)
+ fun_l19_n558(x)
+ else
+ fun_l19_n821(x)
+ end
+end
+
+def fun_l18_n405(x)
+ if (x < 1)
+ fun_l19_n608(x)
+ else
+ fun_l19_n415(x)
+ end
+end
+
+def fun_l18_n406(x)
+ if (x < 1)
+ fun_l19_n709(x)
+ else
+ fun_l19_n635(x)
+ end
+end
+
+def fun_l18_n407(x)
+ if (x < 1)
+ fun_l19_n432(x)
+ else
+ fun_l19_n923(x)
+ end
+end
+
+def fun_l18_n408(x)
+ if (x < 1)
+ fun_l19_n612(x)
+ else
+ fun_l19_n386(x)
+ end
+end
+
+def fun_l18_n409(x)
+ if (x < 1)
+ fun_l19_n1(x)
+ else
+ fun_l19_n679(x)
+ end
+end
+
+def fun_l18_n410(x)
+ if (x < 1)
+ fun_l19_n998(x)
+ else
+ fun_l19_n969(x)
+ end
+end
+
+def fun_l18_n411(x)
+ if (x < 1)
+ fun_l19_n210(x)
+ else
+ fun_l19_n642(x)
+ end
+end
+
+def fun_l18_n412(x)
+ if (x < 1)
+ fun_l19_n902(x)
+ else
+ fun_l19_n591(x)
+ end
+end
+
+def fun_l18_n413(x)
+ if (x < 1)
+ fun_l19_n417(x)
+ else
+ fun_l19_n192(x)
+ end
+end
+
+def fun_l18_n414(x)
+ if (x < 1)
+ fun_l19_n543(x)
+ else
+ fun_l19_n277(x)
+ end
+end
+
+def fun_l18_n415(x)
+ if (x < 1)
+ fun_l19_n145(x)
+ else
+ fun_l19_n157(x)
+ end
+end
+
+def fun_l18_n416(x)
+ if (x < 1)
+ fun_l19_n696(x)
+ else
+ fun_l19_n453(x)
+ end
+end
+
+def fun_l18_n417(x)
+ if (x < 1)
+ fun_l19_n593(x)
+ else
+ fun_l19_n683(x)
+ end
+end
+
+def fun_l18_n418(x)
+ if (x < 1)
+ fun_l19_n459(x)
+ else
+ fun_l19_n292(x)
+ end
+end
+
+def fun_l18_n419(x)
+ if (x < 1)
+ fun_l19_n37(x)
+ else
+ fun_l19_n281(x)
+ end
+end
+
+def fun_l18_n420(x)
+ if (x < 1)
+ fun_l19_n39(x)
+ else
+ fun_l19_n642(x)
+ end
+end
+
+def fun_l18_n421(x)
+ if (x < 1)
+ fun_l19_n942(x)
+ else
+ fun_l19_n997(x)
+ end
+end
+
+def fun_l18_n422(x)
+ if (x < 1)
+ fun_l19_n18(x)
+ else
+ fun_l19_n301(x)
+ end
+end
+
+def fun_l18_n423(x)
+ if (x < 1)
+ fun_l19_n473(x)
+ else
+ fun_l19_n231(x)
+ end
+end
+
+def fun_l18_n424(x)
+ if (x < 1)
+ fun_l19_n331(x)
+ else
+ fun_l19_n110(x)
+ end
+end
+
+def fun_l18_n425(x)
+ if (x < 1)
+ fun_l19_n786(x)
+ else
+ fun_l19_n991(x)
+ end
+end
+
+def fun_l18_n426(x)
+ if (x < 1)
+ fun_l19_n440(x)
+ else
+ fun_l19_n17(x)
+ end
+end
+
+def fun_l18_n427(x)
+ if (x < 1)
+ fun_l19_n294(x)
+ else
+ fun_l19_n3(x)
+ end
+end
+
+def fun_l18_n428(x)
+ if (x < 1)
+ fun_l19_n369(x)
+ else
+ fun_l19_n576(x)
+ end
+end
+
+def fun_l18_n429(x)
+ if (x < 1)
+ fun_l19_n818(x)
+ else
+ fun_l19_n236(x)
+ end
+end
+
+def fun_l18_n430(x)
+ if (x < 1)
+ fun_l19_n360(x)
+ else
+ fun_l19_n443(x)
+ end
+end
+
+def fun_l18_n431(x)
+ if (x < 1)
+ fun_l19_n432(x)
+ else
+ fun_l19_n863(x)
+ end
+end
+
+def fun_l18_n432(x)
+ if (x < 1)
+ fun_l19_n591(x)
+ else
+ fun_l19_n167(x)
+ end
+end
+
+def fun_l18_n433(x)
+ if (x < 1)
+ fun_l19_n955(x)
+ else
+ fun_l19_n265(x)
+ end
+end
+
+def fun_l18_n434(x)
+ if (x < 1)
+ fun_l19_n374(x)
+ else
+ fun_l19_n812(x)
+ end
+end
+
+def fun_l18_n435(x)
+ if (x < 1)
+ fun_l19_n712(x)
+ else
+ fun_l19_n603(x)
+ end
+end
+
+def fun_l18_n436(x)
+ if (x < 1)
+ fun_l19_n750(x)
+ else
+ fun_l19_n852(x)
+ end
+end
+
+def fun_l18_n437(x)
+ if (x < 1)
+ fun_l19_n393(x)
+ else
+ fun_l19_n121(x)
+ end
+end
+
+def fun_l18_n438(x)
+ if (x < 1)
+ fun_l19_n555(x)
+ else
+ fun_l19_n33(x)
+ end
+end
+
+def fun_l18_n439(x)
+ if (x < 1)
+ fun_l19_n872(x)
+ else
+ fun_l19_n841(x)
+ end
+end
+
+def fun_l18_n440(x)
+ if (x < 1)
+ fun_l19_n828(x)
+ else
+ fun_l19_n549(x)
+ end
+end
+
+def fun_l18_n441(x)
+ if (x < 1)
+ fun_l19_n647(x)
+ else
+ fun_l19_n795(x)
+ end
+end
+
+def fun_l18_n442(x)
+ if (x < 1)
+ fun_l19_n609(x)
+ else
+ fun_l19_n837(x)
+ end
+end
+
+def fun_l18_n443(x)
+ if (x < 1)
+ fun_l19_n977(x)
+ else
+ fun_l19_n670(x)
+ end
+end
+
+def fun_l18_n444(x)
+ if (x < 1)
+ fun_l19_n649(x)
+ else
+ fun_l19_n912(x)
+ end
+end
+
+def fun_l18_n445(x)
+ if (x < 1)
+ fun_l19_n856(x)
+ else
+ fun_l19_n994(x)
+ end
+end
+
+def fun_l18_n446(x)
+ if (x < 1)
+ fun_l19_n868(x)
+ else
+ fun_l19_n105(x)
+ end
+end
+
+def fun_l18_n447(x)
+ if (x < 1)
+ fun_l19_n405(x)
+ else
+ fun_l19_n318(x)
+ end
+end
+
+def fun_l18_n448(x)
+ if (x < 1)
+ fun_l19_n966(x)
+ else
+ fun_l19_n214(x)
+ end
+end
+
+def fun_l18_n449(x)
+ if (x < 1)
+ fun_l19_n458(x)
+ else
+ fun_l19_n650(x)
+ end
+end
+
+def fun_l18_n450(x)
+ if (x < 1)
+ fun_l19_n875(x)
+ else
+ fun_l19_n697(x)
+ end
+end
+
+def fun_l18_n451(x)
+ if (x < 1)
+ fun_l19_n799(x)
+ else
+ fun_l19_n661(x)
+ end
+end
+
+def fun_l18_n452(x)
+ if (x < 1)
+ fun_l19_n677(x)
+ else
+ fun_l19_n750(x)
+ end
+end
+
+def fun_l18_n453(x)
+ if (x < 1)
+ fun_l19_n530(x)
+ else
+ fun_l19_n110(x)
+ end
+end
+
+def fun_l18_n454(x)
+ if (x < 1)
+ fun_l19_n785(x)
+ else
+ fun_l19_n381(x)
+ end
+end
+
+def fun_l18_n455(x)
+ if (x < 1)
+ fun_l19_n680(x)
+ else
+ fun_l19_n201(x)
+ end
+end
+
+def fun_l18_n456(x)
+ if (x < 1)
+ fun_l19_n246(x)
+ else
+ fun_l19_n972(x)
+ end
+end
+
+def fun_l18_n457(x)
+ if (x < 1)
+ fun_l19_n656(x)
+ else
+ fun_l19_n451(x)
+ end
+end
+
+def fun_l18_n458(x)
+ if (x < 1)
+ fun_l19_n612(x)
+ else
+ fun_l19_n288(x)
+ end
+end
+
+def fun_l18_n459(x)
+ if (x < 1)
+ fun_l19_n612(x)
+ else
+ fun_l19_n150(x)
+ end
+end
+
+def fun_l18_n460(x)
+ if (x < 1)
+ fun_l19_n549(x)
+ else
+ fun_l19_n917(x)
+ end
+end
+
+def fun_l18_n461(x)
+ if (x < 1)
+ fun_l19_n661(x)
+ else
+ fun_l19_n11(x)
+ end
+end
+
+def fun_l18_n462(x)
+ if (x < 1)
+ fun_l19_n172(x)
+ else
+ fun_l19_n561(x)
+ end
+end
+
+def fun_l18_n463(x)
+ if (x < 1)
+ fun_l19_n687(x)
+ else
+ fun_l19_n12(x)
+ end
+end
+
+def fun_l18_n464(x)
+ if (x < 1)
+ fun_l19_n57(x)
+ else
+ fun_l19_n835(x)
+ end
+end
+
+def fun_l18_n465(x)
+ if (x < 1)
+ fun_l19_n116(x)
+ else
+ fun_l19_n993(x)
+ end
+end
+
+def fun_l18_n466(x)
+ if (x < 1)
+ fun_l19_n932(x)
+ else
+ fun_l19_n623(x)
+ end
+end
+
+def fun_l18_n467(x)
+ if (x < 1)
+ fun_l19_n839(x)
+ else
+ fun_l19_n70(x)
+ end
+end
+
+def fun_l18_n468(x)
+ if (x < 1)
+ fun_l19_n574(x)
+ else
+ fun_l19_n193(x)
+ end
+end
+
+def fun_l18_n469(x)
+ if (x < 1)
+ fun_l19_n762(x)
+ else
+ fun_l19_n654(x)
+ end
+end
+
+def fun_l18_n470(x)
+ if (x < 1)
+ fun_l19_n656(x)
+ else
+ fun_l19_n42(x)
+ end
+end
+
+def fun_l18_n471(x)
+ if (x < 1)
+ fun_l19_n959(x)
+ else
+ fun_l19_n368(x)
+ end
+end
+
+def fun_l18_n472(x)
+ if (x < 1)
+ fun_l19_n494(x)
+ else
+ fun_l19_n357(x)
+ end
+end
+
+def fun_l18_n473(x)
+ if (x < 1)
+ fun_l19_n394(x)
+ else
+ fun_l19_n313(x)
+ end
+end
+
+def fun_l18_n474(x)
+ if (x < 1)
+ fun_l19_n826(x)
+ else
+ fun_l19_n33(x)
+ end
+end
+
+def fun_l18_n475(x)
+ if (x < 1)
+ fun_l19_n202(x)
+ else
+ fun_l19_n455(x)
+ end
+end
+
+def fun_l18_n476(x)
+ if (x < 1)
+ fun_l19_n855(x)
+ else
+ fun_l19_n375(x)
+ end
+end
+
+def fun_l18_n477(x)
+ if (x < 1)
+ fun_l19_n554(x)
+ else
+ fun_l19_n176(x)
+ end
+end
+
+def fun_l18_n478(x)
+ if (x < 1)
+ fun_l19_n705(x)
+ else
+ fun_l19_n509(x)
+ end
+end
+
+def fun_l18_n479(x)
+ if (x < 1)
+ fun_l19_n473(x)
+ else
+ fun_l19_n123(x)
+ end
+end
+
+def fun_l18_n480(x)
+ if (x < 1)
+ fun_l19_n108(x)
+ else
+ fun_l19_n125(x)
+ end
+end
+
+def fun_l18_n481(x)
+ if (x < 1)
+ fun_l19_n476(x)
+ else
+ fun_l19_n657(x)
+ end
+end
+
+def fun_l18_n482(x)
+ if (x < 1)
+ fun_l19_n800(x)
+ else
+ fun_l19_n691(x)
+ end
+end
+
+def fun_l18_n483(x)
+ if (x < 1)
+ fun_l19_n343(x)
+ else
+ fun_l19_n573(x)
+ end
+end
+
+def fun_l18_n484(x)
+ if (x < 1)
+ fun_l19_n654(x)
+ else
+ fun_l19_n114(x)
+ end
+end
+
+def fun_l18_n485(x)
+ if (x < 1)
+ fun_l19_n231(x)
+ else
+ fun_l19_n291(x)
+ end
+end
+
+def fun_l18_n486(x)
+ if (x < 1)
+ fun_l19_n877(x)
+ else
+ fun_l19_n628(x)
+ end
+end
+
+def fun_l18_n487(x)
+ if (x < 1)
+ fun_l19_n35(x)
+ else
+ fun_l19_n992(x)
+ end
+end
+
+def fun_l18_n488(x)
+ if (x < 1)
+ fun_l19_n592(x)
+ else
+ fun_l19_n951(x)
+ end
+end
+
+def fun_l18_n489(x)
+ if (x < 1)
+ fun_l19_n292(x)
+ else
+ fun_l19_n768(x)
+ end
+end
+
+def fun_l18_n490(x)
+ if (x < 1)
+ fun_l19_n191(x)
+ else
+ fun_l19_n759(x)
+ end
+end
+
+def fun_l18_n491(x)
+ if (x < 1)
+ fun_l19_n474(x)
+ else
+ fun_l19_n393(x)
+ end
+end
+
+def fun_l18_n492(x)
+ if (x < 1)
+ fun_l19_n556(x)
+ else
+ fun_l19_n691(x)
+ end
+end
+
+def fun_l18_n493(x)
+ if (x < 1)
+ fun_l19_n717(x)
+ else
+ fun_l19_n714(x)
+ end
+end
+
+def fun_l18_n494(x)
+ if (x < 1)
+ fun_l19_n542(x)
+ else
+ fun_l19_n505(x)
+ end
+end
+
+def fun_l18_n495(x)
+ if (x < 1)
+ fun_l19_n154(x)
+ else
+ fun_l19_n500(x)
+ end
+end
+
+def fun_l18_n496(x)
+ if (x < 1)
+ fun_l19_n311(x)
+ else
+ fun_l19_n458(x)
+ end
+end
+
+def fun_l18_n497(x)
+ if (x < 1)
+ fun_l19_n523(x)
+ else
+ fun_l19_n475(x)
+ end
+end
+
+def fun_l18_n498(x)
+ if (x < 1)
+ fun_l19_n101(x)
+ else
+ fun_l19_n478(x)
+ end
+end
+
+def fun_l18_n499(x)
+ if (x < 1)
+ fun_l19_n243(x)
+ else
+ fun_l19_n586(x)
+ end
+end
+
+def fun_l18_n500(x)
+ if (x < 1)
+ fun_l19_n263(x)
+ else
+ fun_l19_n888(x)
+ end
+end
+
+def fun_l18_n501(x)
+ if (x < 1)
+ fun_l19_n415(x)
+ else
+ fun_l19_n808(x)
+ end
+end
+
+def fun_l18_n502(x)
+ if (x < 1)
+ fun_l19_n38(x)
+ else
+ fun_l19_n640(x)
+ end
+end
+
+def fun_l18_n503(x)
+ if (x < 1)
+ fun_l19_n218(x)
+ else
+ fun_l19_n577(x)
+ end
+end
+
+def fun_l18_n504(x)
+ if (x < 1)
+ fun_l19_n723(x)
+ else
+ fun_l19_n594(x)
+ end
+end
+
+def fun_l18_n505(x)
+ if (x < 1)
+ fun_l19_n392(x)
+ else
+ fun_l19_n984(x)
+ end
+end
+
+def fun_l18_n506(x)
+ if (x < 1)
+ fun_l19_n310(x)
+ else
+ fun_l19_n668(x)
+ end
+end
+
+def fun_l18_n507(x)
+ if (x < 1)
+ fun_l19_n278(x)
+ else
+ fun_l19_n812(x)
+ end
+end
+
+def fun_l18_n508(x)
+ if (x < 1)
+ fun_l19_n230(x)
+ else
+ fun_l19_n479(x)
+ end
+end
+
+def fun_l18_n509(x)
+ if (x < 1)
+ fun_l19_n63(x)
+ else
+ fun_l19_n774(x)
+ end
+end
+
+def fun_l18_n510(x)
+ if (x < 1)
+ fun_l19_n607(x)
+ else
+ fun_l19_n433(x)
+ end
+end
+
+def fun_l18_n511(x)
+ if (x < 1)
+ fun_l19_n28(x)
+ else
+ fun_l19_n672(x)
+ end
+end
+
+def fun_l18_n512(x)
+ if (x < 1)
+ fun_l19_n684(x)
+ else
+ fun_l19_n247(x)
+ end
+end
+
+def fun_l18_n513(x)
+ if (x < 1)
+ fun_l19_n181(x)
+ else
+ fun_l19_n649(x)
+ end
+end
+
+def fun_l18_n514(x)
+ if (x < 1)
+ fun_l19_n787(x)
+ else
+ fun_l19_n281(x)
+ end
+end
+
+def fun_l18_n515(x)
+ if (x < 1)
+ fun_l19_n191(x)
+ else
+ fun_l19_n848(x)
+ end
+end
+
+def fun_l18_n516(x)
+ if (x < 1)
+ fun_l19_n796(x)
+ else
+ fun_l19_n572(x)
+ end
+end
+
+def fun_l18_n517(x)
+ if (x < 1)
+ fun_l19_n780(x)
+ else
+ fun_l19_n816(x)
+ end
+end
+
+def fun_l18_n518(x)
+ if (x < 1)
+ fun_l19_n429(x)
+ else
+ fun_l19_n681(x)
+ end
+end
+
+def fun_l18_n519(x)
+ if (x < 1)
+ fun_l19_n476(x)
+ else
+ fun_l19_n954(x)
+ end
+end
+
+def fun_l18_n520(x)
+ if (x < 1)
+ fun_l19_n537(x)
+ else
+ fun_l19_n690(x)
+ end
+end
+
+def fun_l18_n521(x)
+ if (x < 1)
+ fun_l19_n657(x)
+ else
+ fun_l19_n293(x)
+ end
+end
+
+def fun_l18_n522(x)
+ if (x < 1)
+ fun_l19_n369(x)
+ else
+ fun_l19_n685(x)
+ end
+end
+
+def fun_l18_n523(x)
+ if (x < 1)
+ fun_l19_n785(x)
+ else
+ fun_l19_n184(x)
+ end
+end
+
+def fun_l18_n524(x)
+ if (x < 1)
+ fun_l19_n6(x)
+ else
+ fun_l19_n970(x)
+ end
+end
+
+def fun_l18_n525(x)
+ if (x < 1)
+ fun_l19_n395(x)
+ else
+ fun_l19_n570(x)
+ end
+end
+
+def fun_l18_n526(x)
+ if (x < 1)
+ fun_l19_n837(x)
+ else
+ fun_l19_n992(x)
+ end
+end
+
+def fun_l18_n527(x)
+ if (x < 1)
+ fun_l19_n827(x)
+ else
+ fun_l19_n119(x)
+ end
+end
+
+def fun_l18_n528(x)
+ if (x < 1)
+ fun_l19_n819(x)
+ else
+ fun_l19_n382(x)
+ end
+end
+
+def fun_l18_n529(x)
+ if (x < 1)
+ fun_l19_n365(x)
+ else
+ fun_l19_n713(x)
+ end
+end
+
+def fun_l18_n530(x)
+ if (x < 1)
+ fun_l19_n223(x)
+ else
+ fun_l19_n346(x)
+ end
+end
+
+def fun_l18_n531(x)
+ if (x < 1)
+ fun_l19_n624(x)
+ else
+ fun_l19_n671(x)
+ end
+end
+
+def fun_l18_n532(x)
+ if (x < 1)
+ fun_l19_n522(x)
+ else
+ fun_l19_n354(x)
+ end
+end
+
+def fun_l18_n533(x)
+ if (x < 1)
+ fun_l19_n324(x)
+ else
+ fun_l19_n602(x)
+ end
+end
+
+def fun_l18_n534(x)
+ if (x < 1)
+ fun_l19_n138(x)
+ else
+ fun_l19_n259(x)
+ end
+end
+
+def fun_l18_n535(x)
+ if (x < 1)
+ fun_l19_n692(x)
+ else
+ fun_l19_n810(x)
+ end
+end
+
+def fun_l18_n536(x)
+ if (x < 1)
+ fun_l19_n694(x)
+ else
+ fun_l19_n39(x)
+ end
+end
+
+def fun_l18_n537(x)
+ if (x < 1)
+ fun_l19_n441(x)
+ else
+ fun_l19_n158(x)
+ end
+end
+
+def fun_l18_n538(x)
+ if (x < 1)
+ fun_l19_n609(x)
+ else
+ fun_l19_n54(x)
+ end
+end
+
+def fun_l18_n539(x)
+ if (x < 1)
+ fun_l19_n984(x)
+ else
+ fun_l19_n206(x)
+ end
+end
+
+def fun_l18_n540(x)
+ if (x < 1)
+ fun_l19_n548(x)
+ else
+ fun_l19_n558(x)
+ end
+end
+
+def fun_l18_n541(x)
+ if (x < 1)
+ fun_l19_n640(x)
+ else
+ fun_l19_n721(x)
+ end
+end
+
+def fun_l18_n542(x)
+ if (x < 1)
+ fun_l19_n50(x)
+ else
+ fun_l19_n598(x)
+ end
+end
+
+def fun_l18_n543(x)
+ if (x < 1)
+ fun_l19_n774(x)
+ else
+ fun_l19_n753(x)
+ end
+end
+
+def fun_l18_n544(x)
+ if (x < 1)
+ fun_l19_n151(x)
+ else
+ fun_l19_n75(x)
+ end
+end
+
+def fun_l18_n545(x)
+ if (x < 1)
+ fun_l19_n162(x)
+ else
+ fun_l19_n550(x)
+ end
+end
+
+def fun_l18_n546(x)
+ if (x < 1)
+ fun_l19_n892(x)
+ else
+ fun_l19_n322(x)
+ end
+end
+
+def fun_l18_n547(x)
+ if (x < 1)
+ fun_l19_n15(x)
+ else
+ fun_l19_n854(x)
+ end
+end
+
+def fun_l18_n548(x)
+ if (x < 1)
+ fun_l19_n54(x)
+ else
+ fun_l19_n627(x)
+ end
+end
+
+def fun_l18_n549(x)
+ if (x < 1)
+ fun_l19_n847(x)
+ else
+ fun_l19_n236(x)
+ end
+end
+
+def fun_l18_n550(x)
+ if (x < 1)
+ fun_l19_n796(x)
+ else
+ fun_l19_n895(x)
+ end
+end
+
+def fun_l18_n551(x)
+ if (x < 1)
+ fun_l19_n922(x)
+ else
+ fun_l19_n854(x)
+ end
+end
+
+def fun_l18_n552(x)
+ if (x < 1)
+ fun_l19_n378(x)
+ else
+ fun_l19_n449(x)
+ end
+end
+
+def fun_l18_n553(x)
+ if (x < 1)
+ fun_l19_n188(x)
+ else
+ fun_l19_n65(x)
+ end
+end
+
+def fun_l18_n554(x)
+ if (x < 1)
+ fun_l19_n606(x)
+ else
+ fun_l19_n292(x)
+ end
+end
+
+def fun_l18_n555(x)
+ if (x < 1)
+ fun_l19_n718(x)
+ else
+ fun_l19_n926(x)
+ end
+end
+
+def fun_l18_n556(x)
+ if (x < 1)
+ fun_l19_n765(x)
+ else
+ fun_l19_n975(x)
+ end
+end
+
+def fun_l18_n557(x)
+ if (x < 1)
+ fun_l19_n987(x)
+ else
+ fun_l19_n152(x)
+ end
+end
+
+def fun_l18_n558(x)
+ if (x < 1)
+ fun_l19_n978(x)
+ else
+ fun_l19_n861(x)
+ end
+end
+
+def fun_l18_n559(x)
+ if (x < 1)
+ fun_l19_n563(x)
+ else
+ fun_l19_n532(x)
+ end
+end
+
+def fun_l18_n560(x)
+ if (x < 1)
+ fun_l19_n492(x)
+ else
+ fun_l19_n337(x)
+ end
+end
+
+def fun_l18_n561(x)
+ if (x < 1)
+ fun_l19_n967(x)
+ else
+ fun_l19_n33(x)
+ end
+end
+
+def fun_l18_n562(x)
+ if (x < 1)
+ fun_l19_n509(x)
+ else
+ fun_l19_n212(x)
+ end
+end
+
+def fun_l18_n563(x)
+ if (x < 1)
+ fun_l19_n55(x)
+ else
+ fun_l19_n167(x)
+ end
+end
+
+def fun_l18_n564(x)
+ if (x < 1)
+ fun_l19_n263(x)
+ else
+ fun_l19_n386(x)
+ end
+end
+
+def fun_l18_n565(x)
+ if (x < 1)
+ fun_l19_n292(x)
+ else
+ fun_l19_n576(x)
+ end
+end
+
+def fun_l18_n566(x)
+ if (x < 1)
+ fun_l19_n16(x)
+ else
+ fun_l19_n180(x)
+ end
+end
+
+def fun_l18_n567(x)
+ if (x < 1)
+ fun_l19_n359(x)
+ else
+ fun_l19_n398(x)
+ end
+end
+
+def fun_l18_n568(x)
+ if (x < 1)
+ fun_l19_n799(x)
+ else
+ fun_l19_n616(x)
+ end
+end
+
+def fun_l18_n569(x)
+ if (x < 1)
+ fun_l19_n751(x)
+ else
+ fun_l19_n539(x)
+ end
+end
+
+def fun_l18_n570(x)
+ if (x < 1)
+ fun_l19_n497(x)
+ else
+ fun_l19_n197(x)
+ end
+end
+
+def fun_l18_n571(x)
+ if (x < 1)
+ fun_l19_n88(x)
+ else
+ fun_l19_n565(x)
+ end
+end
+
+def fun_l18_n572(x)
+ if (x < 1)
+ fun_l19_n213(x)
+ else
+ fun_l19_n137(x)
+ end
+end
+
+def fun_l18_n573(x)
+ if (x < 1)
+ fun_l19_n570(x)
+ else
+ fun_l19_n893(x)
+ end
+end
+
+def fun_l18_n574(x)
+ if (x < 1)
+ fun_l19_n436(x)
+ else
+ fun_l19_n285(x)
+ end
+end
+
+def fun_l18_n575(x)
+ if (x < 1)
+ fun_l19_n787(x)
+ else
+ fun_l19_n541(x)
+ end
+end
+
+def fun_l18_n576(x)
+ if (x < 1)
+ fun_l19_n432(x)
+ else
+ fun_l19_n371(x)
+ end
+end
+
+def fun_l18_n577(x)
+ if (x < 1)
+ fun_l19_n542(x)
+ else
+ fun_l19_n431(x)
+ end
+end
+
+def fun_l18_n578(x)
+ if (x < 1)
+ fun_l19_n829(x)
+ else
+ fun_l19_n415(x)
+ end
+end
+
+def fun_l18_n579(x)
+ if (x < 1)
+ fun_l19_n925(x)
+ else
+ fun_l19_n862(x)
+ end
+end
+
+def fun_l18_n580(x)
+ if (x < 1)
+ fun_l19_n214(x)
+ else
+ fun_l19_n67(x)
+ end
+end
+
+def fun_l18_n581(x)
+ if (x < 1)
+ fun_l19_n734(x)
+ else
+ fun_l19_n220(x)
+ end
+end
+
+def fun_l18_n582(x)
+ if (x < 1)
+ fun_l19_n971(x)
+ else
+ fun_l19_n359(x)
+ end
+end
+
+def fun_l18_n583(x)
+ if (x < 1)
+ fun_l19_n293(x)
+ else
+ fun_l19_n286(x)
+ end
+end
+
+def fun_l18_n584(x)
+ if (x < 1)
+ fun_l19_n618(x)
+ else
+ fun_l19_n866(x)
+ end
+end
+
+def fun_l18_n585(x)
+ if (x < 1)
+ fun_l19_n315(x)
+ else
+ fun_l19_n594(x)
+ end
+end
+
+def fun_l18_n586(x)
+ if (x < 1)
+ fun_l19_n230(x)
+ else
+ fun_l19_n450(x)
+ end
+end
+
+def fun_l18_n587(x)
+ if (x < 1)
+ fun_l19_n805(x)
+ else
+ fun_l19_n429(x)
+ end
+end
+
+def fun_l18_n588(x)
+ if (x < 1)
+ fun_l19_n782(x)
+ else
+ fun_l19_n133(x)
+ end
+end
+
+def fun_l18_n589(x)
+ if (x < 1)
+ fun_l19_n166(x)
+ else
+ fun_l19_n111(x)
+ end
+end
+
+def fun_l18_n590(x)
+ if (x < 1)
+ fun_l19_n26(x)
+ else
+ fun_l19_n678(x)
+ end
+end
+
+def fun_l18_n591(x)
+ if (x < 1)
+ fun_l19_n728(x)
+ else
+ fun_l19_n346(x)
+ end
+end
+
+def fun_l18_n592(x)
+ if (x < 1)
+ fun_l19_n882(x)
+ else
+ fun_l19_n930(x)
+ end
+end
+
+def fun_l18_n593(x)
+ if (x < 1)
+ fun_l19_n454(x)
+ else
+ fun_l19_n560(x)
+ end
+end
+
+def fun_l18_n594(x)
+ if (x < 1)
+ fun_l19_n881(x)
+ else
+ fun_l19_n929(x)
+ end
+end
+
+def fun_l18_n595(x)
+ if (x < 1)
+ fun_l19_n464(x)
+ else
+ fun_l19_n8(x)
+ end
+end
+
+def fun_l18_n596(x)
+ if (x < 1)
+ fun_l19_n247(x)
+ else
+ fun_l19_n48(x)
+ end
+end
+
+def fun_l18_n597(x)
+ if (x < 1)
+ fun_l19_n838(x)
+ else
+ fun_l19_n811(x)
+ end
+end
+
+def fun_l18_n598(x)
+ if (x < 1)
+ fun_l19_n493(x)
+ else
+ fun_l19_n975(x)
+ end
+end
+
+def fun_l18_n599(x)
+ if (x < 1)
+ fun_l19_n372(x)
+ else
+ fun_l19_n334(x)
+ end
+end
+
+def fun_l18_n600(x)
+ if (x < 1)
+ fun_l19_n971(x)
+ else
+ fun_l19_n198(x)
+ end
+end
+
+def fun_l18_n601(x)
+ if (x < 1)
+ fun_l19_n494(x)
+ else
+ fun_l19_n273(x)
+ end
+end
+
+def fun_l18_n602(x)
+ if (x < 1)
+ fun_l19_n778(x)
+ else
+ fun_l19_n815(x)
+ end
+end
+
+def fun_l18_n603(x)
+ if (x < 1)
+ fun_l19_n247(x)
+ else
+ fun_l19_n615(x)
+ end
+end
+
+def fun_l18_n604(x)
+ if (x < 1)
+ fun_l19_n659(x)
+ else
+ fun_l19_n613(x)
+ end
+end
+
+def fun_l18_n605(x)
+ if (x < 1)
+ fun_l19_n814(x)
+ else
+ fun_l19_n742(x)
+ end
+end
+
+def fun_l18_n606(x)
+ if (x < 1)
+ fun_l19_n988(x)
+ else
+ fun_l19_n877(x)
+ end
+end
+
+def fun_l18_n607(x)
+ if (x < 1)
+ fun_l19_n908(x)
+ else
+ fun_l19_n491(x)
+ end
+end
+
+def fun_l18_n608(x)
+ if (x < 1)
+ fun_l19_n600(x)
+ else
+ fun_l19_n381(x)
+ end
+end
+
+def fun_l18_n609(x)
+ if (x < 1)
+ fun_l19_n695(x)
+ else
+ fun_l19_n343(x)
+ end
+end
+
+def fun_l18_n610(x)
+ if (x < 1)
+ fun_l19_n686(x)
+ else
+ fun_l19_n154(x)
+ end
+end
+
+def fun_l18_n611(x)
+ if (x < 1)
+ fun_l19_n413(x)
+ else
+ fun_l19_n364(x)
+ end
+end
+
+def fun_l18_n612(x)
+ if (x < 1)
+ fun_l19_n86(x)
+ else
+ fun_l19_n478(x)
+ end
+end
+
+def fun_l18_n613(x)
+ if (x < 1)
+ fun_l19_n288(x)
+ else
+ fun_l19_n134(x)
+ end
+end
+
+def fun_l18_n614(x)
+ if (x < 1)
+ fun_l19_n71(x)
+ else
+ fun_l19_n95(x)
+ end
+end
+
+def fun_l18_n615(x)
+ if (x < 1)
+ fun_l19_n716(x)
+ else
+ fun_l19_n697(x)
+ end
+end
+
+def fun_l18_n616(x)
+ if (x < 1)
+ fun_l19_n24(x)
+ else
+ fun_l19_n365(x)
+ end
+end
+
+def fun_l18_n617(x)
+ if (x < 1)
+ fun_l19_n317(x)
+ else
+ fun_l19_n117(x)
+ end
+end
+
+def fun_l18_n618(x)
+ if (x < 1)
+ fun_l19_n304(x)
+ else
+ fun_l19_n115(x)
+ end
+end
+
+def fun_l18_n619(x)
+ if (x < 1)
+ fun_l19_n322(x)
+ else
+ fun_l19_n105(x)
+ end
+end
+
+def fun_l18_n620(x)
+ if (x < 1)
+ fun_l19_n213(x)
+ else
+ fun_l19_n122(x)
+ end
+end
+
+def fun_l18_n621(x)
+ if (x < 1)
+ fun_l19_n675(x)
+ else
+ fun_l19_n769(x)
+ end
+end
+
+def fun_l18_n622(x)
+ if (x < 1)
+ fun_l19_n660(x)
+ else
+ fun_l19_n895(x)
+ end
+end
+
+def fun_l18_n623(x)
+ if (x < 1)
+ fun_l19_n656(x)
+ else
+ fun_l19_n698(x)
+ end
+end
+
+def fun_l18_n624(x)
+ if (x < 1)
+ fun_l19_n575(x)
+ else
+ fun_l19_n274(x)
+ end
+end
+
+def fun_l18_n625(x)
+ if (x < 1)
+ fun_l19_n44(x)
+ else
+ fun_l19_n78(x)
+ end
+end
+
+def fun_l18_n626(x)
+ if (x < 1)
+ fun_l19_n326(x)
+ else
+ fun_l19_n76(x)
+ end
+end
+
+def fun_l18_n627(x)
+ if (x < 1)
+ fun_l19_n365(x)
+ else
+ fun_l19_n453(x)
+ end
+end
+
+def fun_l18_n628(x)
+ if (x < 1)
+ fun_l19_n306(x)
+ else
+ fun_l19_n63(x)
+ end
+end
+
+def fun_l18_n629(x)
+ if (x < 1)
+ fun_l19_n116(x)
+ else
+ fun_l19_n577(x)
+ end
+end
+
+def fun_l18_n630(x)
+ if (x < 1)
+ fun_l19_n625(x)
+ else
+ fun_l19_n321(x)
+ end
+end
+
+def fun_l18_n631(x)
+ if (x < 1)
+ fun_l19_n328(x)
+ else
+ fun_l19_n989(x)
+ end
+end
+
+def fun_l18_n632(x)
+ if (x < 1)
+ fun_l19_n216(x)
+ else
+ fun_l19_n375(x)
+ end
+end
+
+def fun_l18_n633(x)
+ if (x < 1)
+ fun_l19_n942(x)
+ else
+ fun_l19_n17(x)
+ end
+end
+
+def fun_l18_n634(x)
+ if (x < 1)
+ fun_l19_n821(x)
+ else
+ fun_l19_n132(x)
+ end
+end
+
+def fun_l18_n635(x)
+ if (x < 1)
+ fun_l19_n164(x)
+ else
+ fun_l19_n679(x)
+ end
+end
+
+def fun_l18_n636(x)
+ if (x < 1)
+ fun_l19_n494(x)
+ else
+ fun_l19_n404(x)
+ end
+end
+
+def fun_l18_n637(x)
+ if (x < 1)
+ fun_l19_n715(x)
+ else
+ fun_l19_n955(x)
+ end
+end
+
+def fun_l18_n638(x)
+ if (x < 1)
+ fun_l19_n297(x)
+ else
+ fun_l19_n349(x)
+ end
+end
+
+def fun_l18_n639(x)
+ if (x < 1)
+ fun_l19_n835(x)
+ else
+ fun_l19_n965(x)
+ end
+end
+
+def fun_l18_n640(x)
+ if (x < 1)
+ fun_l19_n778(x)
+ else
+ fun_l19_n572(x)
+ end
+end
+
+def fun_l18_n641(x)
+ if (x < 1)
+ fun_l19_n51(x)
+ else
+ fun_l19_n497(x)
+ end
+end
+
+def fun_l18_n642(x)
+ if (x < 1)
+ fun_l19_n390(x)
+ else
+ fun_l19_n341(x)
+ end
+end
+
+def fun_l18_n643(x)
+ if (x < 1)
+ fun_l19_n961(x)
+ else
+ fun_l19_n966(x)
+ end
+end
+
+def fun_l18_n644(x)
+ if (x < 1)
+ fun_l19_n832(x)
+ else
+ fun_l19_n279(x)
+ end
+end
+
+def fun_l18_n645(x)
+ if (x < 1)
+ fun_l19_n0(x)
+ else
+ fun_l19_n266(x)
+ end
+end
+
+def fun_l18_n646(x)
+ if (x < 1)
+ fun_l19_n512(x)
+ else
+ fun_l19_n988(x)
+ end
+end
+
+def fun_l18_n647(x)
+ if (x < 1)
+ fun_l19_n728(x)
+ else
+ fun_l19_n390(x)
+ end
+end
+
+def fun_l18_n648(x)
+ if (x < 1)
+ fun_l19_n61(x)
+ else
+ fun_l19_n188(x)
+ end
+end
+
+def fun_l18_n649(x)
+ if (x < 1)
+ fun_l19_n772(x)
+ else
+ fun_l19_n457(x)
+ end
+end
+
+def fun_l18_n650(x)
+ if (x < 1)
+ fun_l19_n768(x)
+ else
+ fun_l19_n624(x)
+ end
+end
+
+def fun_l18_n651(x)
+ if (x < 1)
+ fun_l19_n30(x)
+ else
+ fun_l19_n663(x)
+ end
+end
+
+def fun_l18_n652(x)
+ if (x < 1)
+ fun_l19_n42(x)
+ else
+ fun_l19_n781(x)
+ end
+end
+
+def fun_l18_n653(x)
+ if (x < 1)
+ fun_l19_n59(x)
+ else
+ fun_l19_n99(x)
+ end
+end
+
+def fun_l18_n654(x)
+ if (x < 1)
+ fun_l19_n81(x)
+ else
+ fun_l19_n368(x)
+ end
+end
+
+def fun_l18_n655(x)
+ if (x < 1)
+ fun_l19_n0(x)
+ else
+ fun_l19_n321(x)
+ end
+end
+
+def fun_l18_n656(x)
+ if (x < 1)
+ fun_l19_n344(x)
+ else
+ fun_l19_n996(x)
+ end
+end
+
+def fun_l18_n657(x)
+ if (x < 1)
+ fun_l19_n384(x)
+ else
+ fun_l19_n123(x)
+ end
+end
+
+def fun_l18_n658(x)
+ if (x < 1)
+ fun_l19_n336(x)
+ else
+ fun_l19_n928(x)
+ end
+end
+
+def fun_l18_n659(x)
+ if (x < 1)
+ fun_l19_n785(x)
+ else
+ fun_l19_n370(x)
+ end
+end
+
+def fun_l18_n660(x)
+ if (x < 1)
+ fun_l19_n508(x)
+ else
+ fun_l19_n200(x)
+ end
+end
+
+def fun_l18_n661(x)
+ if (x < 1)
+ fun_l19_n674(x)
+ else
+ fun_l19_n95(x)
+ end
+end
+
+def fun_l18_n662(x)
+ if (x < 1)
+ fun_l19_n839(x)
+ else
+ fun_l19_n737(x)
+ end
+end
+
+def fun_l18_n663(x)
+ if (x < 1)
+ fun_l19_n670(x)
+ else
+ fun_l19_n77(x)
+ end
+end
+
+def fun_l18_n664(x)
+ if (x < 1)
+ fun_l19_n402(x)
+ else
+ fun_l19_n7(x)
+ end
+end
+
+def fun_l18_n665(x)
+ if (x < 1)
+ fun_l19_n357(x)
+ else
+ fun_l19_n961(x)
+ end
+end
+
+def fun_l18_n666(x)
+ if (x < 1)
+ fun_l19_n72(x)
+ else
+ fun_l19_n535(x)
+ end
+end
+
+def fun_l18_n667(x)
+ if (x < 1)
+ fun_l19_n317(x)
+ else
+ fun_l19_n450(x)
+ end
+end
+
+def fun_l18_n668(x)
+ if (x < 1)
+ fun_l19_n823(x)
+ else
+ fun_l19_n301(x)
+ end
+end
+
+def fun_l18_n669(x)
+ if (x < 1)
+ fun_l19_n36(x)
+ else
+ fun_l19_n660(x)
+ end
+end
+
+def fun_l18_n670(x)
+ if (x < 1)
+ fun_l19_n322(x)
+ else
+ fun_l19_n626(x)
+ end
+end
+
+def fun_l18_n671(x)
+ if (x < 1)
+ fun_l19_n408(x)
+ else
+ fun_l19_n872(x)
+ end
+end
+
+def fun_l18_n672(x)
+ if (x < 1)
+ fun_l19_n614(x)
+ else
+ fun_l19_n567(x)
+ end
+end
+
+def fun_l18_n673(x)
+ if (x < 1)
+ fun_l19_n601(x)
+ else
+ fun_l19_n429(x)
+ end
+end
+
+def fun_l18_n674(x)
+ if (x < 1)
+ fun_l19_n658(x)
+ else
+ fun_l19_n424(x)
+ end
+end
+
+def fun_l18_n675(x)
+ if (x < 1)
+ fun_l19_n248(x)
+ else
+ fun_l19_n29(x)
+ end
+end
+
+def fun_l18_n676(x)
+ if (x < 1)
+ fun_l19_n206(x)
+ else
+ fun_l19_n838(x)
+ end
+end
+
+def fun_l18_n677(x)
+ if (x < 1)
+ fun_l19_n354(x)
+ else
+ fun_l19_n700(x)
+ end
+end
+
+def fun_l18_n678(x)
+ if (x < 1)
+ fun_l19_n264(x)
+ else
+ fun_l19_n591(x)
+ end
+end
+
+def fun_l18_n679(x)
+ if (x < 1)
+ fun_l19_n73(x)
+ else
+ fun_l19_n419(x)
+ end
+end
+
+def fun_l18_n680(x)
+ if (x < 1)
+ fun_l19_n260(x)
+ else
+ fun_l19_n902(x)
+ end
+end
+
+def fun_l18_n681(x)
+ if (x < 1)
+ fun_l19_n776(x)
+ else
+ fun_l19_n148(x)
+ end
+end
+
+def fun_l18_n682(x)
+ if (x < 1)
+ fun_l19_n819(x)
+ else
+ fun_l19_n743(x)
+ end
+end
+
+def fun_l18_n683(x)
+ if (x < 1)
+ fun_l19_n831(x)
+ else
+ fun_l19_n194(x)
+ end
+end
+
+def fun_l18_n684(x)
+ if (x < 1)
+ fun_l19_n652(x)
+ else
+ fun_l19_n229(x)
+ end
+end
+
+def fun_l18_n685(x)
+ if (x < 1)
+ fun_l19_n533(x)
+ else
+ fun_l19_n600(x)
+ end
+end
+
+def fun_l18_n686(x)
+ if (x < 1)
+ fun_l19_n45(x)
+ else
+ fun_l19_n623(x)
+ end
+end
+
+def fun_l18_n687(x)
+ if (x < 1)
+ fun_l19_n287(x)
+ else
+ fun_l19_n443(x)
+ end
+end
+
+def fun_l18_n688(x)
+ if (x < 1)
+ fun_l19_n719(x)
+ else
+ fun_l19_n819(x)
+ end
+end
+
+def fun_l18_n689(x)
+ if (x < 1)
+ fun_l19_n872(x)
+ else
+ fun_l19_n944(x)
+ end
+end
+
+def fun_l18_n690(x)
+ if (x < 1)
+ fun_l19_n352(x)
+ else
+ fun_l19_n49(x)
+ end
+end
+
+def fun_l18_n691(x)
+ if (x < 1)
+ fun_l19_n438(x)
+ else
+ fun_l19_n592(x)
+ end
+end
+
+def fun_l18_n692(x)
+ if (x < 1)
+ fun_l19_n717(x)
+ else
+ fun_l19_n30(x)
+ end
+end
+
+def fun_l18_n693(x)
+ if (x < 1)
+ fun_l19_n132(x)
+ else
+ fun_l19_n830(x)
+ end
+end
+
+def fun_l18_n694(x)
+ if (x < 1)
+ fun_l19_n17(x)
+ else
+ fun_l19_n649(x)
+ end
+end
+
+def fun_l18_n695(x)
+ if (x < 1)
+ fun_l19_n883(x)
+ else
+ fun_l19_n812(x)
+ end
+end
+
+def fun_l18_n696(x)
+ if (x < 1)
+ fun_l19_n354(x)
+ else
+ fun_l19_n927(x)
+ end
+end
+
+def fun_l18_n697(x)
+ if (x < 1)
+ fun_l19_n534(x)
+ else
+ fun_l19_n192(x)
+ end
+end
+
+def fun_l18_n698(x)
+ if (x < 1)
+ fun_l19_n911(x)
+ else
+ fun_l19_n386(x)
+ end
+end
+
+def fun_l18_n699(x)
+ if (x < 1)
+ fun_l19_n1(x)
+ else
+ fun_l19_n253(x)
+ end
+end
+
+def fun_l18_n700(x)
+ if (x < 1)
+ fun_l19_n318(x)
+ else
+ fun_l19_n323(x)
+ end
+end
+
+def fun_l18_n701(x)
+ if (x < 1)
+ fun_l19_n158(x)
+ else
+ fun_l19_n61(x)
+ end
+end
+
+def fun_l18_n702(x)
+ if (x < 1)
+ fun_l19_n719(x)
+ else
+ fun_l19_n842(x)
+ end
+end
+
+def fun_l18_n703(x)
+ if (x < 1)
+ fun_l19_n918(x)
+ else
+ fun_l19_n231(x)
+ end
+end
+
+def fun_l18_n704(x)
+ if (x < 1)
+ fun_l19_n136(x)
+ else
+ fun_l19_n28(x)
+ end
+end
+
+def fun_l18_n705(x)
+ if (x < 1)
+ fun_l19_n451(x)
+ else
+ fun_l19_n328(x)
+ end
+end
+
+def fun_l18_n706(x)
+ if (x < 1)
+ fun_l19_n182(x)
+ else
+ fun_l19_n434(x)
+ end
+end
+
+def fun_l18_n707(x)
+ if (x < 1)
+ fun_l19_n368(x)
+ else
+ fun_l19_n302(x)
+ end
+end
+
+def fun_l18_n708(x)
+ if (x < 1)
+ fun_l19_n370(x)
+ else
+ fun_l19_n291(x)
+ end
+end
+
+def fun_l18_n709(x)
+ if (x < 1)
+ fun_l19_n104(x)
+ else
+ fun_l19_n530(x)
+ end
+end
+
+def fun_l18_n710(x)
+ if (x < 1)
+ fun_l19_n712(x)
+ else
+ fun_l19_n325(x)
+ end
+end
+
+def fun_l18_n711(x)
+ if (x < 1)
+ fun_l19_n555(x)
+ else
+ fun_l19_n299(x)
+ end
+end
+
+def fun_l18_n712(x)
+ if (x < 1)
+ fun_l19_n40(x)
+ else
+ fun_l19_n342(x)
+ end
+end
+
+def fun_l18_n713(x)
+ if (x < 1)
+ fun_l19_n871(x)
+ else
+ fun_l19_n72(x)
+ end
+end
+
+def fun_l18_n714(x)
+ if (x < 1)
+ fun_l19_n137(x)
+ else
+ fun_l19_n195(x)
+ end
+end
+
+def fun_l18_n715(x)
+ if (x < 1)
+ fun_l19_n534(x)
+ else
+ fun_l19_n613(x)
+ end
+end
+
+def fun_l18_n716(x)
+ if (x < 1)
+ fun_l19_n591(x)
+ else
+ fun_l19_n899(x)
+ end
+end
+
+def fun_l18_n717(x)
+ if (x < 1)
+ fun_l19_n103(x)
+ else
+ fun_l19_n333(x)
+ end
+end
+
+def fun_l18_n718(x)
+ if (x < 1)
+ fun_l19_n470(x)
+ else
+ fun_l19_n576(x)
+ end
+end
+
+def fun_l18_n719(x)
+ if (x < 1)
+ fun_l19_n494(x)
+ else
+ fun_l19_n765(x)
+ end
+end
+
+def fun_l18_n720(x)
+ if (x < 1)
+ fun_l19_n317(x)
+ else
+ fun_l19_n720(x)
+ end
+end
+
+def fun_l18_n721(x)
+ if (x < 1)
+ fun_l19_n567(x)
+ else
+ fun_l19_n280(x)
+ end
+end
+
+def fun_l18_n722(x)
+ if (x < 1)
+ fun_l19_n642(x)
+ else
+ fun_l19_n700(x)
+ end
+end
+
+def fun_l18_n723(x)
+ if (x < 1)
+ fun_l19_n775(x)
+ else
+ fun_l19_n239(x)
+ end
+end
+
+def fun_l18_n724(x)
+ if (x < 1)
+ fun_l19_n346(x)
+ else
+ fun_l19_n974(x)
+ end
+end
+
+def fun_l18_n725(x)
+ if (x < 1)
+ fun_l19_n509(x)
+ else
+ fun_l19_n90(x)
+ end
+end
+
+def fun_l18_n726(x)
+ if (x < 1)
+ fun_l19_n834(x)
+ else
+ fun_l19_n793(x)
+ end
+end
+
+def fun_l18_n727(x)
+ if (x < 1)
+ fun_l19_n588(x)
+ else
+ fun_l19_n895(x)
+ end
+end
+
+def fun_l18_n728(x)
+ if (x < 1)
+ fun_l19_n18(x)
+ else
+ fun_l19_n218(x)
+ end
+end
+
+def fun_l18_n729(x)
+ if (x < 1)
+ fun_l19_n109(x)
+ else
+ fun_l19_n970(x)
+ end
+end
+
+def fun_l18_n730(x)
+ if (x < 1)
+ fun_l19_n721(x)
+ else
+ fun_l19_n81(x)
+ end
+end
+
+def fun_l18_n731(x)
+ if (x < 1)
+ fun_l19_n935(x)
+ else
+ fun_l19_n652(x)
+ end
+end
+
+def fun_l18_n732(x)
+ if (x < 1)
+ fun_l19_n821(x)
+ else
+ fun_l19_n32(x)
+ end
+end
+
+def fun_l18_n733(x)
+ if (x < 1)
+ fun_l19_n189(x)
+ else
+ fun_l19_n469(x)
+ end
+end
+
+def fun_l18_n734(x)
+ if (x < 1)
+ fun_l19_n11(x)
+ else
+ fun_l19_n741(x)
+ end
+end
+
+def fun_l18_n735(x)
+ if (x < 1)
+ fun_l19_n575(x)
+ else
+ fun_l19_n679(x)
+ end
+end
+
+def fun_l18_n736(x)
+ if (x < 1)
+ fun_l19_n442(x)
+ else
+ fun_l19_n652(x)
+ end
+end
+
+def fun_l18_n737(x)
+ if (x < 1)
+ fun_l19_n22(x)
+ else
+ fun_l19_n950(x)
+ end
+end
+
+def fun_l18_n738(x)
+ if (x < 1)
+ fun_l19_n605(x)
+ else
+ fun_l19_n16(x)
+ end
+end
+
+def fun_l18_n739(x)
+ if (x < 1)
+ fun_l19_n888(x)
+ else
+ fun_l19_n873(x)
+ end
+end
+
+def fun_l18_n740(x)
+ if (x < 1)
+ fun_l19_n355(x)
+ else
+ fun_l19_n558(x)
+ end
+end
+
+def fun_l18_n741(x)
+ if (x < 1)
+ fun_l19_n171(x)
+ else
+ fun_l19_n513(x)
+ end
+end
+
+def fun_l18_n742(x)
+ if (x < 1)
+ fun_l19_n843(x)
+ else
+ fun_l19_n833(x)
+ end
+end
+
+def fun_l18_n743(x)
+ if (x < 1)
+ fun_l19_n774(x)
+ else
+ fun_l19_n992(x)
+ end
+end
+
+def fun_l18_n744(x)
+ if (x < 1)
+ fun_l19_n505(x)
+ else
+ fun_l19_n353(x)
+ end
+end
+
+def fun_l18_n745(x)
+ if (x < 1)
+ fun_l19_n93(x)
+ else
+ fun_l19_n476(x)
+ end
+end
+
+def fun_l18_n746(x)
+ if (x < 1)
+ fun_l19_n555(x)
+ else
+ fun_l19_n233(x)
+ end
+end
+
+def fun_l18_n747(x)
+ if (x < 1)
+ fun_l19_n639(x)
+ else
+ fun_l19_n239(x)
+ end
+end
+
+def fun_l18_n748(x)
+ if (x < 1)
+ fun_l19_n318(x)
+ else
+ fun_l19_n342(x)
+ end
+end
+
+def fun_l18_n749(x)
+ if (x < 1)
+ fun_l19_n80(x)
+ else
+ fun_l19_n252(x)
+ end
+end
+
+def fun_l18_n750(x)
+ if (x < 1)
+ fun_l19_n546(x)
+ else
+ fun_l19_n57(x)
+ end
+end
+
+def fun_l18_n751(x)
+ if (x < 1)
+ fun_l19_n620(x)
+ else
+ fun_l19_n732(x)
+ end
+end
+
+def fun_l18_n752(x)
+ if (x < 1)
+ fun_l19_n870(x)
+ else
+ fun_l19_n696(x)
+ end
+end
+
+def fun_l18_n753(x)
+ if (x < 1)
+ fun_l19_n633(x)
+ else
+ fun_l19_n547(x)
+ end
+end
+
+def fun_l18_n754(x)
+ if (x < 1)
+ fun_l19_n860(x)
+ else
+ fun_l19_n70(x)
+ end
+end
+
+def fun_l18_n755(x)
+ if (x < 1)
+ fun_l19_n4(x)
+ else
+ fun_l19_n560(x)
+ end
+end
+
+def fun_l18_n756(x)
+ if (x < 1)
+ fun_l19_n227(x)
+ else
+ fun_l19_n189(x)
+ end
+end
+
+def fun_l18_n757(x)
+ if (x < 1)
+ fun_l19_n560(x)
+ else
+ fun_l19_n467(x)
+ end
+end
+
+def fun_l18_n758(x)
+ if (x < 1)
+ fun_l19_n777(x)
+ else
+ fun_l19_n761(x)
+ end
+end
+
+def fun_l18_n759(x)
+ if (x < 1)
+ fun_l19_n626(x)
+ else
+ fun_l19_n391(x)
+ end
+end
+
+def fun_l18_n760(x)
+ if (x < 1)
+ fun_l19_n989(x)
+ else
+ fun_l19_n629(x)
+ end
+end
+
+def fun_l18_n761(x)
+ if (x < 1)
+ fun_l19_n509(x)
+ else
+ fun_l19_n268(x)
+ end
+end
+
+def fun_l18_n762(x)
+ if (x < 1)
+ fun_l19_n49(x)
+ else
+ fun_l19_n149(x)
+ end
+end
+
+def fun_l18_n763(x)
+ if (x < 1)
+ fun_l19_n614(x)
+ else
+ fun_l19_n490(x)
+ end
+end
+
+def fun_l18_n764(x)
+ if (x < 1)
+ fun_l19_n7(x)
+ else
+ fun_l19_n686(x)
+ end
+end
+
+def fun_l18_n765(x)
+ if (x < 1)
+ fun_l19_n93(x)
+ else
+ fun_l19_n334(x)
+ end
+end
+
+def fun_l18_n766(x)
+ if (x < 1)
+ fun_l19_n30(x)
+ else
+ fun_l19_n396(x)
+ end
+end
+
+def fun_l18_n767(x)
+ if (x < 1)
+ fun_l19_n437(x)
+ else
+ fun_l19_n614(x)
+ end
+end
+
+def fun_l18_n768(x)
+ if (x < 1)
+ fun_l19_n168(x)
+ else
+ fun_l19_n915(x)
+ end
+end
+
+def fun_l18_n769(x)
+ if (x < 1)
+ fun_l19_n465(x)
+ else
+ fun_l19_n816(x)
+ end
+end
+
+def fun_l18_n770(x)
+ if (x < 1)
+ fun_l19_n692(x)
+ else
+ fun_l19_n772(x)
+ end
+end
+
+def fun_l18_n771(x)
+ if (x < 1)
+ fun_l19_n196(x)
+ else
+ fun_l19_n812(x)
+ end
+end
+
+def fun_l18_n772(x)
+ if (x < 1)
+ fun_l19_n785(x)
+ else
+ fun_l19_n592(x)
+ end
+end
+
+def fun_l18_n773(x)
+ if (x < 1)
+ fun_l19_n649(x)
+ else
+ fun_l19_n50(x)
+ end
+end
+
+def fun_l18_n774(x)
+ if (x < 1)
+ fun_l19_n102(x)
+ else
+ fun_l19_n843(x)
+ end
+end
+
+def fun_l18_n775(x)
+ if (x < 1)
+ fun_l19_n856(x)
+ else
+ fun_l19_n805(x)
+ end
+end
+
+def fun_l18_n776(x)
+ if (x < 1)
+ fun_l19_n449(x)
+ else
+ fun_l19_n425(x)
+ end
+end
+
+def fun_l18_n777(x)
+ if (x < 1)
+ fun_l19_n855(x)
+ else
+ fun_l19_n345(x)
+ end
+end
+
+def fun_l18_n778(x)
+ if (x < 1)
+ fun_l19_n714(x)
+ else
+ fun_l19_n499(x)
+ end
+end
+
+def fun_l18_n779(x)
+ if (x < 1)
+ fun_l19_n131(x)
+ else
+ fun_l19_n396(x)
+ end
+end
+
+def fun_l18_n780(x)
+ if (x < 1)
+ fun_l19_n709(x)
+ else
+ fun_l19_n851(x)
+ end
+end
+
+def fun_l18_n781(x)
+ if (x < 1)
+ fun_l19_n104(x)
+ else
+ fun_l19_n569(x)
+ end
+end
+
+def fun_l18_n782(x)
+ if (x < 1)
+ fun_l19_n121(x)
+ else
+ fun_l19_n690(x)
+ end
+end
+
+def fun_l18_n783(x)
+ if (x < 1)
+ fun_l19_n72(x)
+ else
+ fun_l19_n522(x)
+ end
+end
+
+def fun_l18_n784(x)
+ if (x < 1)
+ fun_l19_n212(x)
+ else
+ fun_l19_n199(x)
+ end
+end
+
+def fun_l18_n785(x)
+ if (x < 1)
+ fun_l19_n168(x)
+ else
+ fun_l19_n948(x)
+ end
+end
+
+def fun_l18_n786(x)
+ if (x < 1)
+ fun_l19_n288(x)
+ else
+ fun_l19_n631(x)
+ end
+end
+
+def fun_l18_n787(x)
+ if (x < 1)
+ fun_l19_n713(x)
+ else
+ fun_l19_n232(x)
+ end
+end
+
+def fun_l18_n788(x)
+ if (x < 1)
+ fun_l19_n6(x)
+ else
+ fun_l19_n725(x)
+ end
+end
+
+def fun_l18_n789(x)
+ if (x < 1)
+ fun_l19_n893(x)
+ else
+ fun_l19_n677(x)
+ end
+end
+
+def fun_l18_n790(x)
+ if (x < 1)
+ fun_l19_n734(x)
+ else
+ fun_l19_n589(x)
+ end
+end
+
+def fun_l18_n791(x)
+ if (x < 1)
+ fun_l19_n369(x)
+ else
+ fun_l19_n710(x)
+ end
+end
+
+def fun_l18_n792(x)
+ if (x < 1)
+ fun_l19_n373(x)
+ else
+ fun_l19_n226(x)
+ end
+end
+
+def fun_l18_n793(x)
+ if (x < 1)
+ fun_l19_n651(x)
+ else
+ fun_l19_n292(x)
+ end
+end
+
+def fun_l18_n794(x)
+ if (x < 1)
+ fun_l19_n625(x)
+ else
+ fun_l19_n494(x)
+ end
+end
+
+def fun_l18_n795(x)
+ if (x < 1)
+ fun_l19_n463(x)
+ else
+ fun_l19_n113(x)
+ end
+end
+
+def fun_l18_n796(x)
+ if (x < 1)
+ fun_l19_n857(x)
+ else
+ fun_l19_n561(x)
+ end
+end
+
+def fun_l18_n797(x)
+ if (x < 1)
+ fun_l19_n845(x)
+ else
+ fun_l19_n598(x)
+ end
+end
+
+def fun_l18_n798(x)
+ if (x < 1)
+ fun_l19_n606(x)
+ else
+ fun_l19_n822(x)
+ end
+end
+
+def fun_l18_n799(x)
+ if (x < 1)
+ fun_l19_n649(x)
+ else
+ fun_l19_n610(x)
+ end
+end
+
+def fun_l18_n800(x)
+ if (x < 1)
+ fun_l19_n619(x)
+ else
+ fun_l19_n753(x)
+ end
+end
+
+def fun_l18_n801(x)
+ if (x < 1)
+ fun_l19_n947(x)
+ else
+ fun_l19_n665(x)
+ end
+end
+
+def fun_l18_n802(x)
+ if (x < 1)
+ fun_l19_n869(x)
+ else
+ fun_l19_n928(x)
+ end
+end
+
+def fun_l18_n803(x)
+ if (x < 1)
+ fun_l19_n568(x)
+ else
+ fun_l19_n624(x)
+ end
+end
+
+def fun_l18_n804(x)
+ if (x < 1)
+ fun_l19_n724(x)
+ else
+ fun_l19_n104(x)
+ end
+end
+
+def fun_l18_n805(x)
+ if (x < 1)
+ fun_l19_n687(x)
+ else
+ fun_l19_n906(x)
+ end
+end
+
+def fun_l18_n806(x)
+ if (x < 1)
+ fun_l19_n387(x)
+ else
+ fun_l19_n317(x)
+ end
+end
+
+def fun_l18_n807(x)
+ if (x < 1)
+ fun_l19_n433(x)
+ else
+ fun_l19_n211(x)
+ end
+end
+
+def fun_l18_n808(x)
+ if (x < 1)
+ fun_l19_n574(x)
+ else
+ fun_l19_n848(x)
+ end
+end
+
+def fun_l18_n809(x)
+ if (x < 1)
+ fun_l19_n929(x)
+ else
+ fun_l19_n751(x)
+ end
+end
+
+def fun_l18_n810(x)
+ if (x < 1)
+ fun_l19_n24(x)
+ else
+ fun_l19_n97(x)
+ end
+end
+
+def fun_l18_n811(x)
+ if (x < 1)
+ fun_l19_n503(x)
+ else
+ fun_l19_n173(x)
+ end
+end
+
+def fun_l18_n812(x)
+ if (x < 1)
+ fun_l19_n431(x)
+ else
+ fun_l19_n553(x)
+ end
+end
+
+def fun_l18_n813(x)
+ if (x < 1)
+ fun_l19_n215(x)
+ else
+ fun_l19_n920(x)
+ end
+end
+
+def fun_l18_n814(x)
+ if (x < 1)
+ fun_l19_n952(x)
+ else
+ fun_l19_n484(x)
+ end
+end
+
+def fun_l18_n815(x)
+ if (x < 1)
+ fun_l19_n253(x)
+ else
+ fun_l19_n20(x)
+ end
+end
+
+def fun_l18_n816(x)
+ if (x < 1)
+ fun_l19_n853(x)
+ else
+ fun_l19_n902(x)
+ end
+end
+
+def fun_l18_n817(x)
+ if (x < 1)
+ fun_l19_n606(x)
+ else
+ fun_l19_n732(x)
+ end
+end
+
+def fun_l18_n818(x)
+ if (x < 1)
+ fun_l19_n227(x)
+ else
+ fun_l19_n908(x)
+ end
+end
+
+def fun_l18_n819(x)
+ if (x < 1)
+ fun_l19_n423(x)
+ else
+ fun_l19_n511(x)
+ end
+end
+
+def fun_l18_n820(x)
+ if (x < 1)
+ fun_l19_n25(x)
+ else
+ fun_l19_n939(x)
+ end
+end
+
+def fun_l18_n821(x)
+ if (x < 1)
+ fun_l19_n709(x)
+ else
+ fun_l19_n776(x)
+ end
+end
+
+def fun_l18_n822(x)
+ if (x < 1)
+ fun_l19_n539(x)
+ else
+ fun_l19_n41(x)
+ end
+end
+
+def fun_l18_n823(x)
+ if (x < 1)
+ fun_l19_n764(x)
+ else
+ fun_l19_n240(x)
+ end
+end
+
+def fun_l18_n824(x)
+ if (x < 1)
+ fun_l19_n508(x)
+ else
+ fun_l19_n505(x)
+ end
+end
+
+def fun_l18_n825(x)
+ if (x < 1)
+ fun_l19_n788(x)
+ else
+ fun_l19_n245(x)
+ end
+end
+
+def fun_l18_n826(x)
+ if (x < 1)
+ fun_l19_n315(x)
+ else
+ fun_l19_n391(x)
+ end
+end
+
+def fun_l18_n827(x)
+ if (x < 1)
+ fun_l19_n210(x)
+ else
+ fun_l19_n17(x)
+ end
+end
+
+def fun_l18_n828(x)
+ if (x < 1)
+ fun_l19_n726(x)
+ else
+ fun_l19_n57(x)
+ end
+end
+
+def fun_l18_n829(x)
+ if (x < 1)
+ fun_l19_n228(x)
+ else
+ fun_l19_n44(x)
+ end
+end
+
+def fun_l18_n830(x)
+ if (x < 1)
+ fun_l19_n5(x)
+ else
+ fun_l19_n110(x)
+ end
+end
+
+def fun_l18_n831(x)
+ if (x < 1)
+ fun_l19_n409(x)
+ else
+ fun_l19_n874(x)
+ end
+end
+
+def fun_l18_n832(x)
+ if (x < 1)
+ fun_l19_n710(x)
+ else
+ fun_l19_n960(x)
+ end
+end
+
+def fun_l18_n833(x)
+ if (x < 1)
+ fun_l19_n92(x)
+ else
+ fun_l19_n869(x)
+ end
+end
+
+def fun_l18_n834(x)
+ if (x < 1)
+ fun_l19_n420(x)
+ else
+ fun_l19_n616(x)
+ end
+end
+
+def fun_l18_n835(x)
+ if (x < 1)
+ fun_l19_n705(x)
+ else
+ fun_l19_n727(x)
+ end
+end
+
+def fun_l18_n836(x)
+ if (x < 1)
+ fun_l19_n78(x)
+ else
+ fun_l19_n211(x)
+ end
+end
+
+def fun_l18_n837(x)
+ if (x < 1)
+ fun_l19_n214(x)
+ else
+ fun_l19_n504(x)
+ end
+end
+
+def fun_l18_n838(x)
+ if (x < 1)
+ fun_l19_n320(x)
+ else
+ fun_l19_n303(x)
+ end
+end
+
+def fun_l18_n839(x)
+ if (x < 1)
+ fun_l19_n168(x)
+ else
+ fun_l19_n677(x)
+ end
+end
+
+def fun_l18_n840(x)
+ if (x < 1)
+ fun_l19_n523(x)
+ else
+ fun_l19_n183(x)
+ end
+end
+
+def fun_l18_n841(x)
+ if (x < 1)
+ fun_l19_n757(x)
+ else
+ fun_l19_n554(x)
+ end
+end
+
+def fun_l18_n842(x)
+ if (x < 1)
+ fun_l19_n309(x)
+ else
+ fun_l19_n70(x)
+ end
+end
+
+def fun_l18_n843(x)
+ if (x < 1)
+ fun_l19_n316(x)
+ else
+ fun_l19_n758(x)
+ end
+end
+
+def fun_l18_n844(x)
+ if (x < 1)
+ fun_l19_n459(x)
+ else
+ fun_l19_n28(x)
+ end
+end
+
+def fun_l18_n845(x)
+ if (x < 1)
+ fun_l19_n458(x)
+ else
+ fun_l19_n597(x)
+ end
+end
+
+def fun_l18_n846(x)
+ if (x < 1)
+ fun_l19_n662(x)
+ else
+ fun_l19_n480(x)
+ end
+end
+
+def fun_l18_n847(x)
+ if (x < 1)
+ fun_l19_n967(x)
+ else
+ fun_l19_n764(x)
+ end
+end
+
+def fun_l18_n848(x)
+ if (x < 1)
+ fun_l19_n248(x)
+ else
+ fun_l19_n459(x)
+ end
+end
+
+def fun_l18_n849(x)
+ if (x < 1)
+ fun_l19_n306(x)
+ else
+ fun_l19_n892(x)
+ end
+end
+
+def fun_l18_n850(x)
+ if (x < 1)
+ fun_l19_n541(x)
+ else
+ fun_l19_n745(x)
+ end
+end
+
+def fun_l18_n851(x)
+ if (x < 1)
+ fun_l19_n974(x)
+ else
+ fun_l19_n593(x)
+ end
+end
+
+def fun_l18_n852(x)
+ if (x < 1)
+ fun_l19_n564(x)
+ else
+ fun_l19_n598(x)
+ end
+end
+
+def fun_l18_n853(x)
+ if (x < 1)
+ fun_l19_n447(x)
+ else
+ fun_l19_n207(x)
+ end
+end
+
+def fun_l18_n854(x)
+ if (x < 1)
+ fun_l19_n261(x)
+ else
+ fun_l19_n35(x)
+ end
+end
+
+def fun_l18_n855(x)
+ if (x < 1)
+ fun_l19_n597(x)
+ else
+ fun_l19_n898(x)
+ end
+end
+
+def fun_l18_n856(x)
+ if (x < 1)
+ fun_l19_n97(x)
+ else
+ fun_l19_n109(x)
+ end
+end
+
+def fun_l18_n857(x)
+ if (x < 1)
+ fun_l19_n487(x)
+ else
+ fun_l19_n423(x)
+ end
+end
+
+def fun_l18_n858(x)
+ if (x < 1)
+ fun_l19_n804(x)
+ else
+ fun_l19_n250(x)
+ end
+end
+
+def fun_l18_n859(x)
+ if (x < 1)
+ fun_l19_n935(x)
+ else
+ fun_l19_n952(x)
+ end
+end
+
+def fun_l18_n860(x)
+ if (x < 1)
+ fun_l19_n149(x)
+ else
+ fun_l19_n586(x)
+ end
+end
+
+def fun_l18_n861(x)
+ if (x < 1)
+ fun_l19_n750(x)
+ else
+ fun_l19_n962(x)
+ end
+end
+
+def fun_l18_n862(x)
+ if (x < 1)
+ fun_l19_n396(x)
+ else
+ fun_l19_n324(x)
+ end
+end
+
+def fun_l18_n863(x)
+ if (x < 1)
+ fun_l19_n231(x)
+ else
+ fun_l19_n897(x)
+ end
+end
+
+def fun_l18_n864(x)
+ if (x < 1)
+ fun_l19_n239(x)
+ else
+ fun_l19_n118(x)
+ end
+end
+
+def fun_l18_n865(x)
+ if (x < 1)
+ fun_l19_n221(x)
+ else
+ fun_l19_n771(x)
+ end
+end
+
+def fun_l18_n866(x)
+ if (x < 1)
+ fun_l19_n258(x)
+ else
+ fun_l19_n868(x)
+ end
+end
+
+def fun_l18_n867(x)
+ if (x < 1)
+ fun_l19_n629(x)
+ else
+ fun_l19_n491(x)
+ end
+end
+
+def fun_l18_n868(x)
+ if (x < 1)
+ fun_l19_n685(x)
+ else
+ fun_l19_n532(x)
+ end
+end
+
+def fun_l18_n869(x)
+ if (x < 1)
+ fun_l19_n45(x)
+ else
+ fun_l19_n769(x)
+ end
+end
+
+def fun_l18_n870(x)
+ if (x < 1)
+ fun_l19_n249(x)
+ else
+ fun_l19_n677(x)
+ end
+end
+
+def fun_l18_n871(x)
+ if (x < 1)
+ fun_l19_n685(x)
+ else
+ fun_l19_n953(x)
+ end
+end
+
+def fun_l18_n872(x)
+ if (x < 1)
+ fun_l19_n270(x)
+ else
+ fun_l19_n208(x)
+ end
+end
+
+def fun_l18_n873(x)
+ if (x < 1)
+ fun_l19_n195(x)
+ else
+ fun_l19_n811(x)
+ end
+end
+
+def fun_l18_n874(x)
+ if (x < 1)
+ fun_l19_n700(x)
+ else
+ fun_l19_n331(x)
+ end
+end
+
+def fun_l18_n875(x)
+ if (x < 1)
+ fun_l19_n209(x)
+ else
+ fun_l19_n304(x)
+ end
+end
+
+def fun_l18_n876(x)
+ if (x < 1)
+ fun_l19_n897(x)
+ else
+ fun_l19_n98(x)
+ end
+end
+
+def fun_l18_n877(x)
+ if (x < 1)
+ fun_l19_n400(x)
+ else
+ fun_l19_n325(x)
+ end
+end
+
+def fun_l18_n878(x)
+ if (x < 1)
+ fun_l19_n312(x)
+ else
+ fun_l19_n872(x)
+ end
+end
+
+def fun_l18_n879(x)
+ if (x < 1)
+ fun_l19_n669(x)
+ else
+ fun_l19_n729(x)
+ end
+end
+
+def fun_l18_n880(x)
+ if (x < 1)
+ fun_l19_n644(x)
+ else
+ fun_l19_n243(x)
+ end
+end
+
+def fun_l18_n881(x)
+ if (x < 1)
+ fun_l19_n440(x)
+ else
+ fun_l19_n495(x)
+ end
+end
+
+def fun_l18_n882(x)
+ if (x < 1)
+ fun_l19_n694(x)
+ else
+ fun_l19_n189(x)
+ end
+end
+
+def fun_l18_n883(x)
+ if (x < 1)
+ fun_l19_n610(x)
+ else
+ fun_l19_n802(x)
+ end
+end
+
+def fun_l18_n884(x)
+ if (x < 1)
+ fun_l19_n69(x)
+ else
+ fun_l19_n129(x)
+ end
+end
+
+def fun_l18_n885(x)
+ if (x < 1)
+ fun_l19_n837(x)
+ else
+ fun_l19_n521(x)
+ end
+end
+
+def fun_l18_n886(x)
+ if (x < 1)
+ fun_l19_n204(x)
+ else
+ fun_l19_n284(x)
+ end
+end
+
+def fun_l18_n887(x)
+ if (x < 1)
+ fun_l19_n2(x)
+ else
+ fun_l19_n378(x)
+ end
+end
+
+def fun_l18_n888(x)
+ if (x < 1)
+ fun_l19_n410(x)
+ else
+ fun_l19_n871(x)
+ end
+end
+
+def fun_l18_n889(x)
+ if (x < 1)
+ fun_l19_n976(x)
+ else
+ fun_l19_n581(x)
+ end
+end
+
+def fun_l18_n890(x)
+ if (x < 1)
+ fun_l19_n274(x)
+ else
+ fun_l19_n57(x)
+ end
+end
+
+def fun_l18_n891(x)
+ if (x < 1)
+ fun_l19_n983(x)
+ else
+ fun_l19_n900(x)
+ end
+end
+
+def fun_l18_n892(x)
+ if (x < 1)
+ fun_l19_n351(x)
+ else
+ fun_l19_n621(x)
+ end
+end
+
+def fun_l18_n893(x)
+ if (x < 1)
+ fun_l19_n539(x)
+ else
+ fun_l19_n847(x)
+ end
+end
+
+def fun_l18_n894(x)
+ if (x < 1)
+ fun_l19_n56(x)
+ else
+ fun_l19_n918(x)
+ end
+end
+
+def fun_l18_n895(x)
+ if (x < 1)
+ fun_l19_n906(x)
+ else
+ fun_l19_n509(x)
+ end
+end
+
+def fun_l18_n896(x)
+ if (x < 1)
+ fun_l19_n64(x)
+ else
+ fun_l19_n269(x)
+ end
+end
+
+def fun_l18_n897(x)
+ if (x < 1)
+ fun_l19_n348(x)
+ else
+ fun_l19_n983(x)
+ end
+end
+
+def fun_l18_n898(x)
+ if (x < 1)
+ fun_l19_n699(x)
+ else
+ fun_l19_n322(x)
+ end
+end
+
+def fun_l18_n899(x)
+ if (x < 1)
+ fun_l19_n754(x)
+ else
+ fun_l19_n608(x)
+ end
+end
+
+def fun_l18_n900(x)
+ if (x < 1)
+ fun_l19_n530(x)
+ else
+ fun_l19_n919(x)
+ end
+end
+
+def fun_l18_n901(x)
+ if (x < 1)
+ fun_l19_n359(x)
+ else
+ fun_l19_n739(x)
+ end
+end
+
+def fun_l18_n902(x)
+ if (x < 1)
+ fun_l19_n647(x)
+ else
+ fun_l19_n389(x)
+ end
+end
+
+def fun_l18_n903(x)
+ if (x < 1)
+ fun_l19_n908(x)
+ else
+ fun_l19_n680(x)
+ end
+end
+
+def fun_l18_n904(x)
+ if (x < 1)
+ fun_l19_n78(x)
+ else
+ fun_l19_n512(x)
+ end
+end
+
+def fun_l18_n905(x)
+ if (x < 1)
+ fun_l19_n514(x)
+ else
+ fun_l19_n250(x)
+ end
+end
+
+def fun_l18_n906(x)
+ if (x < 1)
+ fun_l19_n320(x)
+ else
+ fun_l19_n393(x)
+ end
+end
+
+def fun_l18_n907(x)
+ if (x < 1)
+ fun_l19_n666(x)
+ else
+ fun_l19_n846(x)
+ end
+end
+
+def fun_l18_n908(x)
+ if (x < 1)
+ fun_l19_n757(x)
+ else
+ fun_l19_n194(x)
+ end
+end
+
+def fun_l18_n909(x)
+ if (x < 1)
+ fun_l19_n386(x)
+ else
+ fun_l19_n965(x)
+ end
+end
+
+def fun_l18_n910(x)
+ if (x < 1)
+ fun_l19_n561(x)
+ else
+ fun_l19_n897(x)
+ end
+end
+
+def fun_l18_n911(x)
+ if (x < 1)
+ fun_l19_n281(x)
+ else
+ fun_l19_n960(x)
+ end
+end
+
+def fun_l18_n912(x)
+ if (x < 1)
+ fun_l19_n215(x)
+ else
+ fun_l19_n54(x)
+ end
+end
+
+def fun_l18_n913(x)
+ if (x < 1)
+ fun_l19_n561(x)
+ else
+ fun_l19_n353(x)
+ end
+end
+
+def fun_l18_n914(x)
+ if (x < 1)
+ fun_l19_n780(x)
+ else
+ fun_l19_n924(x)
+ end
+end
+
+def fun_l18_n915(x)
+ if (x < 1)
+ fun_l19_n663(x)
+ else
+ fun_l19_n112(x)
+ end
+end
+
+def fun_l18_n916(x)
+ if (x < 1)
+ fun_l19_n15(x)
+ else
+ fun_l19_n342(x)
+ end
+end
+
+def fun_l18_n917(x)
+ if (x < 1)
+ fun_l19_n226(x)
+ else
+ fun_l19_n337(x)
+ end
+end
+
+def fun_l18_n918(x)
+ if (x < 1)
+ fun_l19_n477(x)
+ else
+ fun_l19_n12(x)
+ end
+end
+
+def fun_l18_n919(x)
+ if (x < 1)
+ fun_l19_n495(x)
+ else
+ fun_l19_n721(x)
+ end
+end
+
+def fun_l18_n920(x)
+ if (x < 1)
+ fun_l19_n551(x)
+ else
+ fun_l19_n626(x)
+ end
+end
+
+def fun_l18_n921(x)
+ if (x < 1)
+ fun_l19_n491(x)
+ else
+ fun_l19_n442(x)
+ end
+end
+
+def fun_l18_n922(x)
+ if (x < 1)
+ fun_l19_n72(x)
+ else
+ fun_l19_n165(x)
+ end
+end
+
+def fun_l18_n923(x)
+ if (x < 1)
+ fun_l19_n475(x)
+ else
+ fun_l19_n381(x)
+ end
+end
+
+def fun_l18_n924(x)
+ if (x < 1)
+ fun_l19_n655(x)
+ else
+ fun_l19_n95(x)
+ end
+end
+
+def fun_l18_n925(x)
+ if (x < 1)
+ fun_l19_n882(x)
+ else
+ fun_l19_n888(x)
+ end
+end
+
+def fun_l18_n926(x)
+ if (x < 1)
+ fun_l19_n620(x)
+ else
+ fun_l19_n85(x)
+ end
+end
+
+def fun_l18_n927(x)
+ if (x < 1)
+ fun_l19_n13(x)
+ else
+ fun_l19_n776(x)
+ end
+end
+
+def fun_l18_n928(x)
+ if (x < 1)
+ fun_l19_n797(x)
+ else
+ fun_l19_n547(x)
+ end
+end
+
+def fun_l18_n929(x)
+ if (x < 1)
+ fun_l19_n34(x)
+ else
+ fun_l19_n753(x)
+ end
+end
+
+def fun_l18_n930(x)
+ if (x < 1)
+ fun_l19_n894(x)
+ else
+ fun_l19_n527(x)
+ end
+end
+
+def fun_l18_n931(x)
+ if (x < 1)
+ fun_l19_n951(x)
+ else
+ fun_l19_n261(x)
+ end
+end
+
+def fun_l18_n932(x)
+ if (x < 1)
+ fun_l19_n178(x)
+ else
+ fun_l19_n365(x)
+ end
+end
+
+def fun_l18_n933(x)
+ if (x < 1)
+ fun_l19_n813(x)
+ else
+ fun_l19_n404(x)
+ end
+end
+
+def fun_l18_n934(x)
+ if (x < 1)
+ fun_l19_n920(x)
+ else
+ fun_l19_n674(x)
+ end
+end
+
+def fun_l18_n935(x)
+ if (x < 1)
+ fun_l19_n155(x)
+ else
+ fun_l19_n250(x)
+ end
+end
+
+def fun_l18_n936(x)
+ if (x < 1)
+ fun_l19_n376(x)
+ else
+ fun_l19_n29(x)
+ end
+end
+
+def fun_l18_n937(x)
+ if (x < 1)
+ fun_l19_n104(x)
+ else
+ fun_l19_n802(x)
+ end
+end
+
+def fun_l18_n938(x)
+ if (x < 1)
+ fun_l19_n340(x)
+ else
+ fun_l19_n424(x)
+ end
+end
+
+def fun_l18_n939(x)
+ if (x < 1)
+ fun_l19_n590(x)
+ else
+ fun_l19_n525(x)
+ end
+end
+
+def fun_l18_n940(x)
+ if (x < 1)
+ fun_l19_n15(x)
+ else
+ fun_l19_n48(x)
+ end
+end
+
+def fun_l18_n941(x)
+ if (x < 1)
+ fun_l19_n83(x)
+ else
+ fun_l19_n975(x)
+ end
+end
+
+def fun_l18_n942(x)
+ if (x < 1)
+ fun_l19_n219(x)
+ else
+ fun_l19_n173(x)
+ end
+end
+
+def fun_l18_n943(x)
+ if (x < 1)
+ fun_l19_n457(x)
+ else
+ fun_l19_n956(x)
+ end
+end
+
+def fun_l18_n944(x)
+ if (x < 1)
+ fun_l19_n900(x)
+ else
+ fun_l19_n363(x)
+ end
+end
+
+def fun_l18_n945(x)
+ if (x < 1)
+ fun_l19_n973(x)
+ else
+ fun_l19_n279(x)
+ end
+end
+
+def fun_l18_n946(x)
+ if (x < 1)
+ fun_l19_n155(x)
+ else
+ fun_l19_n554(x)
+ end
+end
+
+def fun_l18_n947(x)
+ if (x < 1)
+ fun_l19_n744(x)
+ else
+ fun_l19_n854(x)
+ end
+end
+
+def fun_l18_n948(x)
+ if (x < 1)
+ fun_l19_n574(x)
+ else
+ fun_l19_n385(x)
+ end
+end
+
+def fun_l18_n949(x)
+ if (x < 1)
+ fun_l19_n447(x)
+ else
+ fun_l19_n93(x)
+ end
+end
+
+def fun_l18_n950(x)
+ if (x < 1)
+ fun_l19_n621(x)
+ else
+ fun_l19_n467(x)
+ end
+end
+
+def fun_l18_n951(x)
+ if (x < 1)
+ fun_l19_n409(x)
+ else
+ fun_l19_n260(x)
+ end
+end
+
+def fun_l18_n952(x)
+ if (x < 1)
+ fun_l19_n992(x)
+ else
+ fun_l19_n728(x)
+ end
+end
+
+def fun_l18_n953(x)
+ if (x < 1)
+ fun_l19_n760(x)
+ else
+ fun_l19_n724(x)
+ end
+end
+
+def fun_l18_n954(x)
+ if (x < 1)
+ fun_l19_n567(x)
+ else
+ fun_l19_n857(x)
+ end
+end
+
+def fun_l18_n955(x)
+ if (x < 1)
+ fun_l19_n225(x)
+ else
+ fun_l19_n132(x)
+ end
+end
+
+def fun_l18_n956(x)
+ if (x < 1)
+ fun_l19_n856(x)
+ else
+ fun_l19_n449(x)
+ end
+end
+
+def fun_l18_n957(x)
+ if (x < 1)
+ fun_l19_n200(x)
+ else
+ fun_l19_n216(x)
+ end
+end
+
+def fun_l18_n958(x)
+ if (x < 1)
+ fun_l19_n684(x)
+ else
+ fun_l19_n151(x)
+ end
+end
+
+def fun_l18_n959(x)
+ if (x < 1)
+ fun_l19_n989(x)
+ else
+ fun_l19_n137(x)
+ end
+end
+
+def fun_l18_n960(x)
+ if (x < 1)
+ fun_l19_n207(x)
+ else
+ fun_l19_n736(x)
+ end
+end
+
+def fun_l18_n961(x)
+ if (x < 1)
+ fun_l19_n984(x)
+ else
+ fun_l19_n840(x)
+ end
+end
+
+def fun_l18_n962(x)
+ if (x < 1)
+ fun_l19_n367(x)
+ else
+ fun_l19_n155(x)
+ end
+end
+
+def fun_l18_n963(x)
+ if (x < 1)
+ fun_l19_n202(x)
+ else
+ fun_l19_n237(x)
+ end
+end
+
+def fun_l18_n964(x)
+ if (x < 1)
+ fun_l19_n932(x)
+ else
+ fun_l19_n167(x)
+ end
+end
+
+def fun_l18_n965(x)
+ if (x < 1)
+ fun_l19_n269(x)
+ else
+ fun_l19_n105(x)
+ end
+end
+
+def fun_l18_n966(x)
+ if (x < 1)
+ fun_l19_n775(x)
+ else
+ fun_l19_n776(x)
+ end
+end
+
+def fun_l18_n967(x)
+ if (x < 1)
+ fun_l19_n636(x)
+ else
+ fun_l19_n460(x)
+ end
+end
+
+def fun_l18_n968(x)
+ if (x < 1)
+ fun_l19_n335(x)
+ else
+ fun_l19_n4(x)
+ end
+end
+
+def fun_l18_n969(x)
+ if (x < 1)
+ fun_l19_n987(x)
+ else
+ fun_l19_n935(x)
+ end
+end
+
+def fun_l18_n970(x)
+ if (x < 1)
+ fun_l19_n692(x)
+ else
+ fun_l19_n20(x)
+ end
+end
+
+def fun_l18_n971(x)
+ if (x < 1)
+ fun_l19_n805(x)
+ else
+ fun_l19_n139(x)
+ end
+end
+
+def fun_l18_n972(x)
+ if (x < 1)
+ fun_l19_n53(x)
+ else
+ fun_l19_n539(x)
+ end
+end
+
+def fun_l18_n973(x)
+ if (x < 1)
+ fun_l19_n620(x)
+ else
+ fun_l19_n680(x)
+ end
+end
+
+def fun_l18_n974(x)
+ if (x < 1)
+ fun_l19_n662(x)
+ else
+ fun_l19_n580(x)
+ end
+end
+
+def fun_l18_n975(x)
+ if (x < 1)
+ fun_l19_n401(x)
+ else
+ fun_l19_n428(x)
+ end
+end
+
+def fun_l18_n976(x)
+ if (x < 1)
+ fun_l19_n367(x)
+ else
+ fun_l19_n794(x)
+ end
+end
+
+def fun_l18_n977(x)
+ if (x < 1)
+ fun_l19_n204(x)
+ else
+ fun_l19_n258(x)
+ end
+end
+
+def fun_l18_n978(x)
+ if (x < 1)
+ fun_l19_n868(x)
+ else
+ fun_l19_n300(x)
+ end
+end
+
+def fun_l18_n979(x)
+ if (x < 1)
+ fun_l19_n245(x)
+ else
+ fun_l19_n460(x)
+ end
+end
+
+def fun_l18_n980(x)
+ if (x < 1)
+ fun_l19_n965(x)
+ else
+ fun_l19_n639(x)
+ end
+end
+
+def fun_l18_n981(x)
+ if (x < 1)
+ fun_l19_n903(x)
+ else
+ fun_l19_n139(x)
+ end
+end
+
+def fun_l18_n982(x)
+ if (x < 1)
+ fun_l19_n890(x)
+ else
+ fun_l19_n497(x)
+ end
+end
+
+def fun_l18_n983(x)
+ if (x < 1)
+ fun_l19_n723(x)
+ else
+ fun_l19_n705(x)
+ end
+end
+
+def fun_l18_n984(x)
+ if (x < 1)
+ fun_l19_n592(x)
+ else
+ fun_l19_n965(x)
+ end
+end
+
+def fun_l18_n985(x)
+ if (x < 1)
+ fun_l19_n660(x)
+ else
+ fun_l19_n985(x)
+ end
+end
+
+def fun_l18_n986(x)
+ if (x < 1)
+ fun_l19_n230(x)
+ else
+ fun_l19_n447(x)
+ end
+end
+
+def fun_l18_n987(x)
+ if (x < 1)
+ fun_l19_n875(x)
+ else
+ fun_l19_n86(x)
+ end
+end
+
+def fun_l18_n988(x)
+ if (x < 1)
+ fun_l19_n864(x)
+ else
+ fun_l19_n460(x)
+ end
+end
+
+def fun_l18_n989(x)
+ if (x < 1)
+ fun_l19_n834(x)
+ else
+ fun_l19_n628(x)
+ end
+end
+
+def fun_l18_n990(x)
+ if (x < 1)
+ fun_l19_n578(x)
+ else
+ fun_l19_n160(x)
+ end
+end
+
+def fun_l18_n991(x)
+ if (x < 1)
+ fun_l19_n58(x)
+ else
+ fun_l19_n839(x)
+ end
+end
+
+def fun_l18_n992(x)
+ if (x < 1)
+ fun_l19_n282(x)
+ else
+ fun_l19_n864(x)
+ end
+end
+
+def fun_l18_n993(x)
+ if (x < 1)
+ fun_l19_n957(x)
+ else
+ fun_l19_n280(x)
+ end
+end
+
+def fun_l18_n994(x)
+ if (x < 1)
+ fun_l19_n184(x)
+ else
+ fun_l19_n741(x)
+ end
+end
+
+def fun_l18_n995(x)
+ if (x < 1)
+ fun_l19_n458(x)
+ else
+ fun_l19_n802(x)
+ end
+end
+
+def fun_l18_n996(x)
+ if (x < 1)
+ fun_l19_n260(x)
+ else
+ fun_l19_n840(x)
+ end
+end
+
+def fun_l18_n997(x)
+ if (x < 1)
+ fun_l19_n500(x)
+ else
+ fun_l19_n142(x)
+ end
+end
+
+def fun_l18_n998(x)
+ if (x < 1)
+ fun_l19_n712(x)
+ else
+ fun_l19_n736(x)
+ end
+end
+
+def fun_l18_n999(x)
+ if (x < 1)
+ fun_l19_n366(x)
+ else
+ fun_l19_n726(x)
+ end
+end
+
+def fun_l19_n0(x)
+ if (x < 1)
+ fun_l20_n238(x)
+ else
+ fun_l20_n685(x)
+ end
+end
+
+def fun_l19_n1(x)
+ if (x < 1)
+ fun_l20_n892(x)
+ else
+ fun_l20_n786(x)
+ end
+end
+
+def fun_l19_n2(x)
+ if (x < 1)
+ fun_l20_n99(x)
+ else
+ fun_l20_n337(x)
+ end
+end
+
+def fun_l19_n3(x)
+ if (x < 1)
+ fun_l20_n40(x)
+ else
+ fun_l20_n773(x)
+ end
+end
+
+def fun_l19_n4(x)
+ if (x < 1)
+ fun_l20_n815(x)
+ else
+ fun_l20_n576(x)
+ end
+end
+
+def fun_l19_n5(x)
+ if (x < 1)
+ fun_l20_n294(x)
+ else
+ fun_l20_n362(x)
+ end
+end
+
+def fun_l19_n6(x)
+ if (x < 1)
+ fun_l20_n352(x)
+ else
+ fun_l20_n263(x)
+ end
+end
+
+def fun_l19_n7(x)
+ if (x < 1)
+ fun_l20_n920(x)
+ else
+ fun_l20_n164(x)
+ end
+end
+
+def fun_l19_n8(x)
+ if (x < 1)
+ fun_l20_n313(x)
+ else
+ fun_l20_n663(x)
+ end
+end
+
+def fun_l19_n9(x)
+ if (x < 1)
+ fun_l20_n261(x)
+ else
+ fun_l20_n769(x)
+ end
+end
+
+def fun_l19_n10(x)
+ if (x < 1)
+ fun_l20_n85(x)
+ else
+ fun_l20_n243(x)
+ end
+end
+
+def fun_l19_n11(x)
+ if (x < 1)
+ fun_l20_n560(x)
+ else
+ fun_l20_n969(x)
+ end
+end
+
+def fun_l19_n12(x)
+ if (x < 1)
+ fun_l20_n954(x)
+ else
+ fun_l20_n340(x)
+ end
+end
+
+def fun_l19_n13(x)
+ if (x < 1)
+ fun_l20_n548(x)
+ else
+ fun_l20_n689(x)
+ end
+end
+
+def fun_l19_n14(x)
+ if (x < 1)
+ fun_l20_n577(x)
+ else
+ fun_l20_n954(x)
+ end
+end
+
+def fun_l19_n15(x)
+ if (x < 1)
+ fun_l20_n43(x)
+ else
+ fun_l20_n3(x)
+ end
+end
+
+def fun_l19_n16(x)
+ if (x < 1)
+ fun_l20_n15(x)
+ else
+ fun_l20_n281(x)
+ end
+end
+
+def fun_l19_n17(x)
+ if (x < 1)
+ fun_l20_n439(x)
+ else
+ fun_l20_n26(x)
+ end
+end
+
+def fun_l19_n18(x)
+ if (x < 1)
+ fun_l20_n534(x)
+ else
+ fun_l20_n419(x)
+ end
+end
+
+def fun_l19_n19(x)
+ if (x < 1)
+ fun_l20_n456(x)
+ else
+ fun_l20_n959(x)
+ end
+end
+
+def fun_l19_n20(x)
+ if (x < 1)
+ fun_l20_n706(x)
+ else
+ fun_l20_n404(x)
+ end
+end
+
+def fun_l19_n21(x)
+ if (x < 1)
+ fun_l20_n559(x)
+ else
+ fun_l20_n61(x)
+ end
+end
+
+def fun_l19_n22(x)
+ if (x < 1)
+ fun_l20_n986(x)
+ else
+ fun_l20_n202(x)
+ end
+end
+
+def fun_l19_n23(x)
+ if (x < 1)
+ fun_l20_n935(x)
+ else
+ fun_l20_n804(x)
+ end
+end
+
+def fun_l19_n24(x)
+ if (x < 1)
+ fun_l20_n775(x)
+ else
+ fun_l20_n909(x)
+ end
+end
+
+def fun_l19_n25(x)
+ if (x < 1)
+ fun_l20_n28(x)
+ else
+ fun_l20_n631(x)
+ end
+end
+
+def fun_l19_n26(x)
+ if (x < 1)
+ fun_l20_n257(x)
+ else
+ fun_l20_n822(x)
+ end
+end
+
+def fun_l19_n27(x)
+ if (x < 1)
+ fun_l20_n198(x)
+ else
+ fun_l20_n1(x)
+ end
+end
+
+def fun_l19_n28(x)
+ if (x < 1)
+ fun_l20_n534(x)
+ else
+ fun_l20_n46(x)
+ end
+end
+
+def fun_l19_n29(x)
+ if (x < 1)
+ fun_l20_n880(x)
+ else
+ fun_l20_n995(x)
+ end
+end
+
+def fun_l19_n30(x)
+ if (x < 1)
+ fun_l20_n953(x)
+ else
+ fun_l20_n367(x)
+ end
+end
+
+def fun_l19_n31(x)
+ if (x < 1)
+ fun_l20_n165(x)
+ else
+ fun_l20_n404(x)
+ end
+end
+
+def fun_l19_n32(x)
+ if (x < 1)
+ fun_l20_n752(x)
+ else
+ fun_l20_n570(x)
+ end
+end
+
+def fun_l19_n33(x)
+ if (x < 1)
+ fun_l20_n973(x)
+ else
+ fun_l20_n357(x)
+ end
+end
+
+def fun_l19_n34(x)
+ if (x < 1)
+ fun_l20_n897(x)
+ else
+ fun_l20_n501(x)
+ end
+end
+
+def fun_l19_n35(x)
+ if (x < 1)
+ fun_l20_n607(x)
+ else
+ fun_l20_n679(x)
+ end
+end
+
+def fun_l19_n36(x)
+ if (x < 1)
+ fun_l20_n870(x)
+ else
+ fun_l20_n590(x)
+ end
+end
+
+def fun_l19_n37(x)
+ if (x < 1)
+ fun_l20_n620(x)
+ else
+ fun_l20_n462(x)
+ end
+end
+
+def fun_l19_n38(x)
+ if (x < 1)
+ fun_l20_n176(x)
+ else
+ fun_l20_n891(x)
+ end
+end
+
+def fun_l19_n39(x)
+ if (x < 1)
+ fun_l20_n850(x)
+ else
+ fun_l20_n730(x)
+ end
+end
+
+def fun_l19_n40(x)
+ if (x < 1)
+ fun_l20_n193(x)
+ else
+ fun_l20_n635(x)
+ end
+end
+
+def fun_l19_n41(x)
+ if (x < 1)
+ fun_l20_n443(x)
+ else
+ fun_l20_n398(x)
+ end
+end
+
+def fun_l19_n42(x)
+ if (x < 1)
+ fun_l20_n324(x)
+ else
+ fun_l20_n566(x)
+ end
+end
+
+def fun_l19_n43(x)
+ if (x < 1)
+ fun_l20_n817(x)
+ else
+ fun_l20_n791(x)
+ end
+end
+
+def fun_l19_n44(x)
+ if (x < 1)
+ fun_l20_n46(x)
+ else
+ fun_l20_n375(x)
+ end
+end
+
+def fun_l19_n45(x)
+ if (x < 1)
+ fun_l20_n504(x)
+ else
+ fun_l20_n64(x)
+ end
+end
+
+def fun_l19_n46(x)
+ if (x < 1)
+ fun_l20_n174(x)
+ else
+ fun_l20_n621(x)
+ end
+end
+
+def fun_l19_n47(x)
+ if (x < 1)
+ fun_l20_n756(x)
+ else
+ fun_l20_n857(x)
+ end
+end
+
+def fun_l19_n48(x)
+ if (x < 1)
+ fun_l20_n635(x)
+ else
+ fun_l20_n216(x)
+ end
+end
+
+def fun_l19_n49(x)
+ if (x < 1)
+ fun_l20_n806(x)
+ else
+ fun_l20_n291(x)
+ end
+end
+
+def fun_l19_n50(x)
+ if (x < 1)
+ fun_l20_n998(x)
+ else
+ fun_l20_n46(x)
+ end
+end
+
+def fun_l19_n51(x)
+ if (x < 1)
+ fun_l20_n685(x)
+ else
+ fun_l20_n968(x)
+ end
+end
+
+def fun_l19_n52(x)
+ if (x < 1)
+ fun_l20_n906(x)
+ else
+ fun_l20_n788(x)
+ end
+end
+
+def fun_l19_n53(x)
+ if (x < 1)
+ fun_l20_n814(x)
+ else
+ fun_l20_n343(x)
+ end
+end
+
+def fun_l19_n54(x)
+ if (x < 1)
+ fun_l20_n320(x)
+ else
+ fun_l20_n293(x)
+ end
+end
+
+def fun_l19_n55(x)
+ if (x < 1)
+ fun_l20_n608(x)
+ else
+ fun_l20_n958(x)
+ end
+end
+
+def fun_l19_n56(x)
+ if (x < 1)
+ fun_l20_n83(x)
+ else
+ fun_l20_n839(x)
+ end
+end
+
+def fun_l19_n57(x)
+ if (x < 1)
+ fun_l20_n618(x)
+ else
+ fun_l20_n483(x)
+ end
+end
+
+def fun_l19_n58(x)
+ if (x < 1)
+ fun_l20_n647(x)
+ else
+ fun_l20_n782(x)
+ end
+end
+
+def fun_l19_n59(x)
+ if (x < 1)
+ fun_l20_n664(x)
+ else
+ fun_l20_n3(x)
+ end
+end
+
+def fun_l19_n60(x)
+ if (x < 1)
+ fun_l20_n556(x)
+ else
+ fun_l20_n185(x)
+ end
+end
+
+def fun_l19_n61(x)
+ if (x < 1)
+ fun_l20_n657(x)
+ else
+ fun_l20_n162(x)
+ end
+end
+
+def fun_l19_n62(x)
+ if (x < 1)
+ fun_l20_n668(x)
+ else
+ fun_l20_n585(x)
+ end
+end
+
+def fun_l19_n63(x)
+ if (x < 1)
+ fun_l20_n913(x)
+ else
+ fun_l20_n855(x)
+ end
+end
+
+def fun_l19_n64(x)
+ if (x < 1)
+ fun_l20_n331(x)
+ else
+ fun_l20_n71(x)
+ end
+end
+
+def fun_l19_n65(x)
+ if (x < 1)
+ fun_l20_n321(x)
+ else
+ fun_l20_n314(x)
+ end
+end
+
+def fun_l19_n66(x)
+ if (x < 1)
+ fun_l20_n512(x)
+ else
+ fun_l20_n607(x)
+ end
+end
+
+def fun_l19_n67(x)
+ if (x < 1)
+ fun_l20_n649(x)
+ else
+ fun_l20_n733(x)
+ end
+end
+
+def fun_l19_n68(x)
+ if (x < 1)
+ fun_l20_n651(x)
+ else
+ fun_l20_n844(x)
+ end
+end
+
+def fun_l19_n69(x)
+ if (x < 1)
+ fun_l20_n510(x)
+ else
+ fun_l20_n675(x)
+ end
+end
+
+def fun_l19_n70(x)
+ if (x < 1)
+ fun_l20_n830(x)
+ else
+ fun_l20_n338(x)
+ end
+end
+
+def fun_l19_n71(x)
+ if (x < 1)
+ fun_l20_n110(x)
+ else
+ fun_l20_n806(x)
+ end
+end
+
+def fun_l19_n72(x)
+ if (x < 1)
+ fun_l20_n588(x)
+ else
+ fun_l20_n7(x)
+ end
+end
+
+def fun_l19_n73(x)
+ if (x < 1)
+ fun_l20_n495(x)
+ else
+ fun_l20_n293(x)
+ end
+end
+
+def fun_l19_n74(x)
+ if (x < 1)
+ fun_l20_n891(x)
+ else
+ fun_l20_n514(x)
+ end
+end
+
+def fun_l19_n75(x)
+ if (x < 1)
+ fun_l20_n419(x)
+ else
+ fun_l20_n934(x)
+ end
+end
+
+def fun_l19_n76(x)
+ if (x < 1)
+ fun_l20_n476(x)
+ else
+ fun_l20_n652(x)
+ end
+end
+
+def fun_l19_n77(x)
+ if (x < 1)
+ fun_l20_n927(x)
+ else
+ fun_l20_n656(x)
+ end
+end
+
+def fun_l19_n78(x)
+ if (x < 1)
+ fun_l20_n361(x)
+ else
+ fun_l20_n847(x)
+ end
+end
+
+def fun_l19_n79(x)
+ if (x < 1)
+ fun_l20_n584(x)
+ else
+ fun_l20_n24(x)
+ end
+end
+
+def fun_l19_n80(x)
+ if (x < 1)
+ fun_l20_n428(x)
+ else
+ fun_l20_n219(x)
+ end
+end
+
+def fun_l19_n81(x)
+ if (x < 1)
+ fun_l20_n922(x)
+ else
+ fun_l20_n758(x)
+ end
+end
+
+def fun_l19_n82(x)
+ if (x < 1)
+ fun_l20_n188(x)
+ else
+ fun_l20_n378(x)
+ end
+end
+
+def fun_l19_n83(x)
+ if (x < 1)
+ fun_l20_n239(x)
+ else
+ fun_l20_n690(x)
+ end
+end
+
+def fun_l19_n84(x)
+ if (x < 1)
+ fun_l20_n262(x)
+ else
+ fun_l20_n162(x)
+ end
+end
+
+def fun_l19_n85(x)
+ if (x < 1)
+ fun_l20_n117(x)
+ else
+ fun_l20_n117(x)
+ end
+end
+
+def fun_l19_n86(x)
+ if (x < 1)
+ fun_l20_n154(x)
+ else
+ fun_l20_n564(x)
+ end
+end
+
+def fun_l19_n87(x)
+ if (x < 1)
+ fun_l20_n560(x)
+ else
+ fun_l20_n591(x)
+ end
+end
+
+def fun_l19_n88(x)
+ if (x < 1)
+ fun_l20_n529(x)
+ else
+ fun_l20_n107(x)
+ end
+end
+
+def fun_l19_n89(x)
+ if (x < 1)
+ fun_l20_n609(x)
+ else
+ fun_l20_n287(x)
+ end
+end
+
+def fun_l19_n90(x)
+ if (x < 1)
+ fun_l20_n780(x)
+ else
+ fun_l20_n397(x)
+ end
+end
+
+def fun_l19_n91(x)
+ if (x < 1)
+ fun_l20_n587(x)
+ else
+ fun_l20_n416(x)
+ end
+end
+
+def fun_l19_n92(x)
+ if (x < 1)
+ fun_l20_n784(x)
+ else
+ fun_l20_n413(x)
+ end
+end
+
+def fun_l19_n93(x)
+ if (x < 1)
+ fun_l20_n83(x)
+ else
+ fun_l20_n560(x)
+ end
+end
+
+def fun_l19_n94(x)
+ if (x < 1)
+ fun_l20_n126(x)
+ else
+ fun_l20_n67(x)
+ end
+end
+
+def fun_l19_n95(x)
+ if (x < 1)
+ fun_l20_n22(x)
+ else
+ fun_l20_n865(x)
+ end
+end
+
+def fun_l19_n96(x)
+ if (x < 1)
+ fun_l20_n35(x)
+ else
+ fun_l20_n160(x)
+ end
+end
+
+def fun_l19_n97(x)
+ if (x < 1)
+ fun_l20_n701(x)
+ else
+ fun_l20_n139(x)
+ end
+end
+
+def fun_l19_n98(x)
+ if (x < 1)
+ fun_l20_n488(x)
+ else
+ fun_l20_n407(x)
+ end
+end
+
+def fun_l19_n99(x)
+ if (x < 1)
+ fun_l20_n636(x)
+ else
+ fun_l20_n135(x)
+ end
+end
+
+def fun_l19_n100(x)
+ if (x < 1)
+ fun_l20_n83(x)
+ else
+ fun_l20_n923(x)
+ end
+end
+
+def fun_l19_n101(x)
+ if (x < 1)
+ fun_l20_n232(x)
+ else
+ fun_l20_n955(x)
+ end
+end
+
+def fun_l19_n102(x)
+ if (x < 1)
+ fun_l20_n816(x)
+ else
+ fun_l20_n671(x)
+ end
+end
+
+def fun_l19_n103(x)
+ if (x < 1)
+ fun_l20_n366(x)
+ else
+ fun_l20_n646(x)
+ end
+end
+
+def fun_l19_n104(x)
+ if (x < 1)
+ fun_l20_n465(x)
+ else
+ fun_l20_n659(x)
+ end
+end
+
+def fun_l19_n105(x)
+ if (x < 1)
+ fun_l20_n488(x)
+ else
+ fun_l20_n720(x)
+ end
+end
+
+def fun_l19_n106(x)
+ if (x < 1)
+ fun_l20_n278(x)
+ else
+ fun_l20_n570(x)
+ end
+end
+
+def fun_l19_n107(x)
+ if (x < 1)
+ fun_l20_n630(x)
+ else
+ fun_l20_n280(x)
+ end
+end
+
+def fun_l19_n108(x)
+ if (x < 1)
+ fun_l20_n688(x)
+ else
+ fun_l20_n999(x)
+ end
+end
+
+def fun_l19_n109(x)
+ if (x < 1)
+ fun_l20_n175(x)
+ else
+ fun_l20_n633(x)
+ end
+end
+
+def fun_l19_n110(x)
+ if (x < 1)
+ fun_l20_n111(x)
+ else
+ fun_l20_n130(x)
+ end
+end
+
+def fun_l19_n111(x)
+ if (x < 1)
+ fun_l20_n405(x)
+ else
+ fun_l20_n148(x)
+ end
+end
+
+def fun_l19_n112(x)
+ if (x < 1)
+ fun_l20_n645(x)
+ else
+ fun_l20_n303(x)
+ end
+end
+
+def fun_l19_n113(x)
+ if (x < 1)
+ fun_l20_n685(x)
+ else
+ fun_l20_n122(x)
+ end
+end
+
+def fun_l19_n114(x)
+ if (x < 1)
+ fun_l20_n808(x)
+ else
+ fun_l20_n780(x)
+ end
+end
+
+def fun_l19_n115(x)
+ if (x < 1)
+ fun_l20_n136(x)
+ else
+ fun_l20_n749(x)
+ end
+end
+
+def fun_l19_n116(x)
+ if (x < 1)
+ fun_l20_n134(x)
+ else
+ fun_l20_n291(x)
+ end
+end
+
+def fun_l19_n117(x)
+ if (x < 1)
+ fun_l20_n288(x)
+ else
+ fun_l20_n759(x)
+ end
+end
+
+def fun_l19_n118(x)
+ if (x < 1)
+ fun_l20_n617(x)
+ else
+ fun_l20_n823(x)
+ end
+end
+
+def fun_l19_n119(x)
+ if (x < 1)
+ fun_l20_n412(x)
+ else
+ fun_l20_n548(x)
+ end
+end
+
+def fun_l19_n120(x)
+ if (x < 1)
+ fun_l20_n897(x)
+ else
+ fun_l20_n455(x)
+ end
+end
+
+def fun_l19_n121(x)
+ if (x < 1)
+ fun_l20_n105(x)
+ else
+ fun_l20_n753(x)
+ end
+end
+
+def fun_l19_n122(x)
+ if (x < 1)
+ fun_l20_n84(x)
+ else
+ fun_l20_n575(x)
+ end
+end
+
+def fun_l19_n123(x)
+ if (x < 1)
+ fun_l20_n326(x)
+ else
+ fun_l20_n858(x)
+ end
+end
+
+def fun_l19_n124(x)
+ if (x < 1)
+ fun_l20_n878(x)
+ else
+ fun_l20_n348(x)
+ end
+end
+
+def fun_l19_n125(x)
+ if (x < 1)
+ fun_l20_n285(x)
+ else
+ fun_l20_n182(x)
+ end
+end
+
+def fun_l19_n126(x)
+ if (x < 1)
+ fun_l20_n560(x)
+ else
+ fun_l20_n413(x)
+ end
+end
+
+def fun_l19_n127(x)
+ if (x < 1)
+ fun_l20_n597(x)
+ else
+ fun_l20_n748(x)
+ end
+end
+
+def fun_l19_n128(x)
+ if (x < 1)
+ fun_l20_n642(x)
+ else
+ fun_l20_n529(x)
+ end
+end
+
+def fun_l19_n129(x)
+ if (x < 1)
+ fun_l20_n842(x)
+ else
+ fun_l20_n228(x)
+ end
+end
+
+def fun_l19_n130(x)
+ if (x < 1)
+ fun_l20_n283(x)
+ else
+ fun_l20_n656(x)
+ end
+end
+
+def fun_l19_n131(x)
+ if (x < 1)
+ fun_l20_n699(x)
+ else
+ fun_l20_n135(x)
+ end
+end
+
+def fun_l19_n132(x)
+ if (x < 1)
+ fun_l20_n276(x)
+ else
+ fun_l20_n41(x)
+ end
+end
+
+def fun_l19_n133(x)
+ if (x < 1)
+ fun_l20_n734(x)
+ else
+ fun_l20_n157(x)
+ end
+end
+
+def fun_l19_n134(x)
+ if (x < 1)
+ fun_l20_n612(x)
+ else
+ fun_l20_n318(x)
+ end
+end
+
+def fun_l19_n135(x)
+ if (x < 1)
+ fun_l20_n345(x)
+ else
+ fun_l20_n332(x)
+ end
+end
+
+def fun_l19_n136(x)
+ if (x < 1)
+ fun_l20_n131(x)
+ else
+ fun_l20_n747(x)
+ end
+end
+
+def fun_l19_n137(x)
+ if (x < 1)
+ fun_l20_n911(x)
+ else
+ fun_l20_n84(x)
+ end
+end
+
+def fun_l19_n138(x)
+ if (x < 1)
+ fun_l20_n665(x)
+ else
+ fun_l20_n194(x)
+ end
+end
+
+def fun_l19_n139(x)
+ if (x < 1)
+ fun_l20_n301(x)
+ else
+ fun_l20_n71(x)
+ end
+end
+
+def fun_l19_n140(x)
+ if (x < 1)
+ fun_l20_n432(x)
+ else
+ fun_l20_n679(x)
+ end
+end
+
+def fun_l19_n141(x)
+ if (x < 1)
+ fun_l20_n628(x)
+ else
+ fun_l20_n268(x)
+ end
+end
+
+def fun_l19_n142(x)
+ if (x < 1)
+ fun_l20_n982(x)
+ else
+ fun_l20_n241(x)
+ end
+end
+
+def fun_l19_n143(x)
+ if (x < 1)
+ fun_l20_n35(x)
+ else
+ fun_l20_n593(x)
+ end
+end
+
+def fun_l19_n144(x)
+ if (x < 1)
+ fun_l20_n791(x)
+ else
+ fun_l20_n960(x)
+ end
+end
+
+def fun_l19_n145(x)
+ if (x < 1)
+ fun_l20_n613(x)
+ else
+ fun_l20_n366(x)
+ end
+end
+
+def fun_l19_n146(x)
+ if (x < 1)
+ fun_l20_n997(x)
+ else
+ fun_l20_n7(x)
+ end
+end
+
+def fun_l19_n147(x)
+ if (x < 1)
+ fun_l20_n206(x)
+ else
+ fun_l20_n785(x)
+ end
+end
+
+def fun_l19_n148(x)
+ if (x < 1)
+ fun_l20_n822(x)
+ else
+ fun_l20_n178(x)
+ end
+end
+
+def fun_l19_n149(x)
+ if (x < 1)
+ fun_l20_n793(x)
+ else
+ fun_l20_n860(x)
+ end
+end
+
+def fun_l19_n150(x)
+ if (x < 1)
+ fun_l20_n260(x)
+ else
+ fun_l20_n523(x)
+ end
+end
+
+def fun_l19_n151(x)
+ if (x < 1)
+ fun_l20_n848(x)
+ else
+ fun_l20_n568(x)
+ end
+end
+
+def fun_l19_n152(x)
+ if (x < 1)
+ fun_l20_n466(x)
+ else
+ fun_l20_n959(x)
+ end
+end
+
+def fun_l19_n153(x)
+ if (x < 1)
+ fun_l20_n972(x)
+ else
+ fun_l20_n780(x)
+ end
+end
+
+def fun_l19_n154(x)
+ if (x < 1)
+ fun_l20_n349(x)
+ else
+ fun_l20_n490(x)
+ end
+end
+
+def fun_l19_n155(x)
+ if (x < 1)
+ fun_l20_n658(x)
+ else
+ fun_l20_n766(x)
+ end
+end
+
+def fun_l19_n156(x)
+ if (x < 1)
+ fun_l20_n788(x)
+ else
+ fun_l20_n961(x)
+ end
+end
+
+def fun_l19_n157(x)
+ if (x < 1)
+ fun_l20_n32(x)
+ else
+ fun_l20_n155(x)
+ end
+end
+
+def fun_l19_n158(x)
+ if (x < 1)
+ fun_l20_n820(x)
+ else
+ fun_l20_n317(x)
+ end
+end
+
+def fun_l19_n159(x)
+ if (x < 1)
+ fun_l20_n818(x)
+ else
+ fun_l20_n570(x)
+ end
+end
+
+def fun_l19_n160(x)
+ if (x < 1)
+ fun_l20_n82(x)
+ else
+ fun_l20_n331(x)
+ end
+end
+
+def fun_l19_n161(x)
+ if (x < 1)
+ fun_l20_n576(x)
+ else
+ fun_l20_n134(x)
+ end
+end
+
+def fun_l19_n162(x)
+ if (x < 1)
+ fun_l20_n287(x)
+ else
+ fun_l20_n748(x)
+ end
+end
+
+def fun_l19_n163(x)
+ if (x < 1)
+ fun_l20_n855(x)
+ else
+ fun_l20_n97(x)
+ end
+end
+
+def fun_l19_n164(x)
+ if (x < 1)
+ fun_l20_n218(x)
+ else
+ fun_l20_n195(x)
+ end
+end
+
+def fun_l19_n165(x)
+ if (x < 1)
+ fun_l20_n179(x)
+ else
+ fun_l20_n566(x)
+ end
+end
+
+def fun_l19_n166(x)
+ if (x < 1)
+ fun_l20_n833(x)
+ else
+ fun_l20_n35(x)
+ end
+end
+
+def fun_l19_n167(x)
+ if (x < 1)
+ fun_l20_n595(x)
+ else
+ fun_l20_n344(x)
+ end
+end
+
+def fun_l19_n168(x)
+ if (x < 1)
+ fun_l20_n171(x)
+ else
+ fun_l20_n199(x)
+ end
+end
+
+def fun_l19_n169(x)
+ if (x < 1)
+ fun_l20_n531(x)
+ else
+ fun_l20_n385(x)
+ end
+end
+
+def fun_l19_n170(x)
+ if (x < 1)
+ fun_l20_n168(x)
+ else
+ fun_l20_n911(x)
+ end
+end
+
+def fun_l19_n171(x)
+ if (x < 1)
+ fun_l20_n767(x)
+ else
+ fun_l20_n521(x)
+ end
+end
+
+def fun_l19_n172(x)
+ if (x < 1)
+ fun_l20_n769(x)
+ else
+ fun_l20_n56(x)
+ end
+end
+
+def fun_l19_n173(x)
+ if (x < 1)
+ fun_l20_n521(x)
+ else
+ fun_l20_n600(x)
+ end
+end
+
+def fun_l19_n174(x)
+ if (x < 1)
+ fun_l20_n239(x)
+ else
+ fun_l20_n22(x)
+ end
+end
+
+def fun_l19_n175(x)
+ if (x < 1)
+ fun_l20_n963(x)
+ else
+ fun_l20_n497(x)
+ end
+end
+
+def fun_l19_n176(x)
+ if (x < 1)
+ fun_l20_n989(x)
+ else
+ fun_l20_n748(x)
+ end
+end
+
+def fun_l19_n177(x)
+ if (x < 1)
+ fun_l20_n105(x)
+ else
+ fun_l20_n315(x)
+ end
+end
+
+def fun_l19_n178(x)
+ if (x < 1)
+ fun_l20_n48(x)
+ else
+ fun_l20_n550(x)
+ end
+end
+
+def fun_l19_n179(x)
+ if (x < 1)
+ fun_l20_n66(x)
+ else
+ fun_l20_n595(x)
+ end
+end
+
+def fun_l19_n180(x)
+ if (x < 1)
+ fun_l20_n692(x)
+ else
+ fun_l20_n71(x)
+ end
+end
+
+def fun_l19_n181(x)
+ if (x < 1)
+ fun_l20_n639(x)
+ else
+ fun_l20_n869(x)
+ end
+end
+
+def fun_l19_n182(x)
+ if (x < 1)
+ fun_l20_n925(x)
+ else
+ fun_l20_n868(x)
+ end
+end
+
+def fun_l19_n183(x)
+ if (x < 1)
+ fun_l20_n890(x)
+ else
+ fun_l20_n924(x)
+ end
+end
+
+def fun_l19_n184(x)
+ if (x < 1)
+ fun_l20_n579(x)
+ else
+ fun_l20_n349(x)
+ end
+end
+
+def fun_l19_n185(x)
+ if (x < 1)
+ fun_l20_n313(x)
+ else
+ fun_l20_n16(x)
+ end
+end
+
+def fun_l19_n186(x)
+ if (x < 1)
+ fun_l20_n947(x)
+ else
+ fun_l20_n644(x)
+ end
+end
+
+def fun_l19_n187(x)
+ if (x < 1)
+ fun_l20_n424(x)
+ else
+ fun_l20_n815(x)
+ end
+end
+
+def fun_l19_n188(x)
+ if (x < 1)
+ fun_l20_n177(x)
+ else
+ fun_l20_n230(x)
+ end
+end
+
+def fun_l19_n189(x)
+ if (x < 1)
+ fun_l20_n556(x)
+ else
+ fun_l20_n47(x)
+ end
+end
+
+def fun_l19_n190(x)
+ if (x < 1)
+ fun_l20_n804(x)
+ else
+ fun_l20_n516(x)
+ end
+end
+
+def fun_l19_n191(x)
+ if (x < 1)
+ fun_l20_n411(x)
+ else
+ fun_l20_n779(x)
+ end
+end
+
+def fun_l19_n192(x)
+ if (x < 1)
+ fun_l20_n124(x)
+ else
+ fun_l20_n827(x)
+ end
+end
+
+def fun_l19_n193(x)
+ if (x < 1)
+ fun_l20_n514(x)
+ else
+ fun_l20_n516(x)
+ end
+end
+
+def fun_l19_n194(x)
+ if (x < 1)
+ fun_l20_n134(x)
+ else
+ fun_l20_n356(x)
+ end
+end
+
+def fun_l19_n195(x)
+ if (x < 1)
+ fun_l20_n499(x)
+ else
+ fun_l20_n809(x)
+ end
+end
+
+def fun_l19_n196(x)
+ if (x < 1)
+ fun_l20_n958(x)
+ else
+ fun_l20_n675(x)
+ end
+end
+
+def fun_l19_n197(x)
+ if (x < 1)
+ fun_l20_n847(x)
+ else
+ fun_l20_n418(x)
+ end
+end
+
+def fun_l19_n198(x)
+ if (x < 1)
+ fun_l20_n294(x)
+ else
+ fun_l20_n510(x)
+ end
+end
+
+def fun_l19_n199(x)
+ if (x < 1)
+ fun_l20_n365(x)
+ else
+ fun_l20_n952(x)
+ end
+end
+
+def fun_l19_n200(x)
+ if (x < 1)
+ fun_l20_n961(x)
+ else
+ fun_l20_n747(x)
+ end
+end
+
+def fun_l19_n201(x)
+ if (x < 1)
+ fun_l20_n731(x)
+ else
+ fun_l20_n618(x)
+ end
+end
+
+def fun_l19_n202(x)
+ if (x < 1)
+ fun_l20_n825(x)
+ else
+ fun_l20_n907(x)
+ end
+end
+
+def fun_l19_n203(x)
+ if (x < 1)
+ fun_l20_n865(x)
+ else
+ fun_l20_n886(x)
+ end
+end
+
+def fun_l19_n204(x)
+ if (x < 1)
+ fun_l20_n732(x)
+ else
+ fun_l20_n823(x)
+ end
+end
+
+def fun_l19_n205(x)
+ if (x < 1)
+ fun_l20_n305(x)
+ else
+ fun_l20_n596(x)
+ end
+end
+
+def fun_l19_n206(x)
+ if (x < 1)
+ fun_l20_n245(x)
+ else
+ fun_l20_n370(x)
+ end
+end
+
+def fun_l19_n207(x)
+ if (x < 1)
+ fun_l20_n728(x)
+ else
+ fun_l20_n917(x)
+ end
+end
+
+def fun_l19_n208(x)
+ if (x < 1)
+ fun_l20_n448(x)
+ else
+ fun_l20_n904(x)
+ end
+end
+
+def fun_l19_n209(x)
+ if (x < 1)
+ fun_l20_n90(x)
+ else
+ fun_l20_n181(x)
+ end
+end
+
+def fun_l19_n210(x)
+ if (x < 1)
+ fun_l20_n569(x)
+ else
+ fun_l20_n268(x)
+ end
+end
+
+def fun_l19_n211(x)
+ if (x < 1)
+ fun_l20_n772(x)
+ else
+ fun_l20_n770(x)
+ end
+end
+
+def fun_l19_n212(x)
+ if (x < 1)
+ fun_l20_n781(x)
+ else
+ fun_l20_n603(x)
+ end
+end
+
+def fun_l19_n213(x)
+ if (x < 1)
+ fun_l20_n733(x)
+ else
+ fun_l20_n904(x)
+ end
+end
+
+def fun_l19_n214(x)
+ if (x < 1)
+ fun_l20_n303(x)
+ else
+ fun_l20_n888(x)
+ end
+end
+
+def fun_l19_n215(x)
+ if (x < 1)
+ fun_l20_n280(x)
+ else
+ fun_l20_n428(x)
+ end
+end
+
+def fun_l19_n216(x)
+ if (x < 1)
+ fun_l20_n737(x)
+ else
+ fun_l20_n483(x)
+ end
+end
+
+def fun_l19_n217(x)
+ if (x < 1)
+ fun_l20_n780(x)
+ else
+ fun_l20_n240(x)
+ end
+end
+
+def fun_l19_n218(x)
+ if (x < 1)
+ fun_l20_n202(x)
+ else
+ fun_l20_n580(x)
+ end
+end
+
+def fun_l19_n219(x)
+ if (x < 1)
+ fun_l20_n837(x)
+ else
+ fun_l20_n83(x)
+ end
+end
+
+def fun_l19_n220(x)
+ if (x < 1)
+ fun_l20_n68(x)
+ else
+ fun_l20_n292(x)
+ end
+end
+
+def fun_l19_n221(x)
+ if (x < 1)
+ fun_l20_n289(x)
+ else
+ fun_l20_n655(x)
+ end
+end
+
+def fun_l19_n222(x)
+ if (x < 1)
+ fun_l20_n505(x)
+ else
+ fun_l20_n660(x)
+ end
+end
+
+def fun_l19_n223(x)
+ if (x < 1)
+ fun_l20_n534(x)
+ else
+ fun_l20_n391(x)
+ end
+end
+
+def fun_l19_n224(x)
+ if (x < 1)
+ fun_l20_n72(x)
+ else
+ fun_l20_n81(x)
+ end
+end
+
+def fun_l19_n225(x)
+ if (x < 1)
+ fun_l20_n194(x)
+ else
+ fun_l20_n437(x)
+ end
+end
+
+def fun_l19_n226(x)
+ if (x < 1)
+ fun_l20_n629(x)
+ else
+ fun_l20_n645(x)
+ end
+end
+
+def fun_l19_n227(x)
+ if (x < 1)
+ fun_l20_n912(x)
+ else
+ fun_l20_n425(x)
+ end
+end
+
+def fun_l19_n228(x)
+ if (x < 1)
+ fun_l20_n773(x)
+ else
+ fun_l20_n456(x)
+ end
+end
+
+def fun_l19_n229(x)
+ if (x < 1)
+ fun_l20_n247(x)
+ else
+ fun_l20_n275(x)
+ end
+end
+
+def fun_l19_n230(x)
+ if (x < 1)
+ fun_l20_n263(x)
+ else
+ fun_l20_n482(x)
+ end
+end
+
+def fun_l19_n231(x)
+ if (x < 1)
+ fun_l20_n999(x)
+ else
+ fun_l20_n146(x)
+ end
+end
+
+def fun_l19_n232(x)
+ if (x < 1)
+ fun_l20_n117(x)
+ else
+ fun_l20_n851(x)
+ end
+end
+
+def fun_l19_n233(x)
+ if (x < 1)
+ fun_l20_n889(x)
+ else
+ fun_l20_n441(x)
+ end
+end
+
+def fun_l19_n234(x)
+ if (x < 1)
+ fun_l20_n885(x)
+ else
+ fun_l20_n374(x)
+ end
+end
+
+def fun_l19_n235(x)
+ if (x < 1)
+ fun_l20_n703(x)
+ else
+ fun_l20_n962(x)
+ end
+end
+
+def fun_l19_n236(x)
+ if (x < 1)
+ fun_l20_n298(x)
+ else
+ fun_l20_n57(x)
+ end
+end
+
+def fun_l19_n237(x)
+ if (x < 1)
+ fun_l20_n821(x)
+ else
+ fun_l20_n120(x)
+ end
+end
+
+def fun_l19_n238(x)
+ if (x < 1)
+ fun_l20_n437(x)
+ else
+ fun_l20_n204(x)
+ end
+end
+
+def fun_l19_n239(x)
+ if (x < 1)
+ fun_l20_n558(x)
+ else
+ fun_l20_n645(x)
+ end
+end
+
+def fun_l19_n240(x)
+ if (x < 1)
+ fun_l20_n631(x)
+ else
+ fun_l20_n986(x)
+ end
+end
+
+def fun_l19_n241(x)
+ if (x < 1)
+ fun_l20_n418(x)
+ else
+ fun_l20_n738(x)
+ end
+end
+
+def fun_l19_n242(x)
+ if (x < 1)
+ fun_l20_n249(x)
+ else
+ fun_l20_n322(x)
+ end
+end
+
+def fun_l19_n243(x)
+ if (x < 1)
+ fun_l20_n484(x)
+ else
+ fun_l20_n270(x)
+ end
+end
+
+def fun_l19_n244(x)
+ if (x < 1)
+ fun_l20_n749(x)
+ else
+ fun_l20_n322(x)
+ end
+end
+
+def fun_l19_n245(x)
+ if (x < 1)
+ fun_l20_n562(x)
+ else
+ fun_l20_n353(x)
+ end
+end
+
+def fun_l19_n246(x)
+ if (x < 1)
+ fun_l20_n974(x)
+ else
+ fun_l20_n333(x)
+ end
+end
+
+def fun_l19_n247(x)
+ if (x < 1)
+ fun_l20_n929(x)
+ else
+ fun_l20_n885(x)
+ end
+end
+
+def fun_l19_n248(x)
+ if (x < 1)
+ fun_l20_n421(x)
+ else
+ fun_l20_n576(x)
+ end
+end
+
+def fun_l19_n249(x)
+ if (x < 1)
+ fun_l20_n757(x)
+ else
+ fun_l20_n618(x)
+ end
+end
+
+def fun_l19_n250(x)
+ if (x < 1)
+ fun_l20_n108(x)
+ else
+ fun_l20_n704(x)
+ end
+end
+
+def fun_l19_n251(x)
+ if (x < 1)
+ fun_l20_n882(x)
+ else
+ fun_l20_n994(x)
+ end
+end
+
+def fun_l19_n252(x)
+ if (x < 1)
+ fun_l20_n995(x)
+ else
+ fun_l20_n580(x)
+ end
+end
+
+def fun_l19_n253(x)
+ if (x < 1)
+ fun_l20_n869(x)
+ else
+ fun_l20_n302(x)
+ end
+end
+
+def fun_l19_n254(x)
+ if (x < 1)
+ fun_l20_n873(x)
+ else
+ fun_l20_n315(x)
+ end
+end
+
+def fun_l19_n255(x)
+ if (x < 1)
+ fun_l20_n266(x)
+ else
+ fun_l20_n263(x)
+ end
+end
+
+def fun_l19_n256(x)
+ if (x < 1)
+ fun_l20_n450(x)
+ else
+ fun_l20_n994(x)
+ end
+end
+
+def fun_l19_n257(x)
+ if (x < 1)
+ fun_l20_n552(x)
+ else
+ fun_l20_n407(x)
+ end
+end
+
+def fun_l19_n258(x)
+ if (x < 1)
+ fun_l20_n603(x)
+ else
+ fun_l20_n453(x)
+ end
+end
+
+def fun_l19_n259(x)
+ if (x < 1)
+ fun_l20_n933(x)
+ else
+ fun_l20_n609(x)
+ end
+end
+
+def fun_l19_n260(x)
+ if (x < 1)
+ fun_l20_n983(x)
+ else
+ fun_l20_n404(x)
+ end
+end
+
+def fun_l19_n261(x)
+ if (x < 1)
+ fun_l20_n123(x)
+ else
+ fun_l20_n159(x)
+ end
+end
+
+def fun_l19_n262(x)
+ if (x < 1)
+ fun_l20_n890(x)
+ else
+ fun_l20_n749(x)
+ end
+end
+
+def fun_l19_n263(x)
+ if (x < 1)
+ fun_l20_n758(x)
+ else
+ fun_l20_n123(x)
+ end
+end
+
+def fun_l19_n264(x)
+ if (x < 1)
+ fun_l20_n194(x)
+ else
+ fun_l20_n645(x)
+ end
+end
+
+def fun_l19_n265(x)
+ if (x < 1)
+ fun_l20_n71(x)
+ else
+ fun_l20_n750(x)
+ end
+end
+
+def fun_l19_n266(x)
+ if (x < 1)
+ fun_l20_n713(x)
+ else
+ fun_l20_n125(x)
+ end
+end
+
+def fun_l19_n267(x)
+ if (x < 1)
+ fun_l20_n286(x)
+ else
+ fun_l20_n227(x)
+ end
+end
+
+def fun_l19_n268(x)
+ if (x < 1)
+ fun_l20_n220(x)
+ else
+ fun_l20_n233(x)
+ end
+end
+
+def fun_l19_n269(x)
+ if (x < 1)
+ fun_l20_n263(x)
+ else
+ fun_l20_n306(x)
+ end
+end
+
+def fun_l19_n270(x)
+ if (x < 1)
+ fun_l20_n959(x)
+ else
+ fun_l20_n552(x)
+ end
+end
+
+def fun_l19_n271(x)
+ if (x < 1)
+ fun_l20_n154(x)
+ else
+ fun_l20_n212(x)
+ end
+end
+
+def fun_l19_n272(x)
+ if (x < 1)
+ fun_l20_n985(x)
+ else
+ fun_l20_n370(x)
+ end
+end
+
+def fun_l19_n273(x)
+ if (x < 1)
+ fun_l20_n763(x)
+ else
+ fun_l20_n897(x)
+ end
+end
+
+def fun_l19_n274(x)
+ if (x < 1)
+ fun_l20_n582(x)
+ else
+ fun_l20_n638(x)
+ end
+end
+
+def fun_l19_n275(x)
+ if (x < 1)
+ fun_l20_n509(x)
+ else
+ fun_l20_n366(x)
+ end
+end
+
+def fun_l19_n276(x)
+ if (x < 1)
+ fun_l20_n500(x)
+ else
+ fun_l20_n814(x)
+ end
+end
+
+def fun_l19_n277(x)
+ if (x < 1)
+ fun_l20_n726(x)
+ else
+ fun_l20_n934(x)
+ end
+end
+
+def fun_l19_n278(x)
+ if (x < 1)
+ fun_l20_n198(x)
+ else
+ fun_l20_n852(x)
+ end
+end
+
+def fun_l19_n279(x)
+ if (x < 1)
+ fun_l20_n43(x)
+ else
+ fun_l20_n614(x)
+ end
+end
+
+def fun_l19_n280(x)
+ if (x < 1)
+ fun_l20_n79(x)
+ else
+ fun_l20_n821(x)
+ end
+end
+
+def fun_l19_n281(x)
+ if (x < 1)
+ fun_l20_n269(x)
+ else
+ fun_l20_n697(x)
+ end
+end
+
+def fun_l19_n282(x)
+ if (x < 1)
+ fun_l20_n327(x)
+ else
+ fun_l20_n528(x)
+ end
+end
+
+def fun_l19_n283(x)
+ if (x < 1)
+ fun_l20_n77(x)
+ else
+ fun_l20_n743(x)
+ end
+end
+
+def fun_l19_n284(x)
+ if (x < 1)
+ fun_l20_n282(x)
+ else
+ fun_l20_n406(x)
+ end
+end
+
+def fun_l19_n285(x)
+ if (x < 1)
+ fun_l20_n129(x)
+ else
+ fun_l20_n855(x)
+ end
+end
+
+def fun_l19_n286(x)
+ if (x < 1)
+ fun_l20_n897(x)
+ else
+ fun_l20_n687(x)
+ end
+end
+
+def fun_l19_n287(x)
+ if (x < 1)
+ fun_l20_n166(x)
+ else
+ fun_l20_n5(x)
+ end
+end
+
+def fun_l19_n288(x)
+ if (x < 1)
+ fun_l20_n545(x)
+ else
+ fun_l20_n661(x)
+ end
+end
+
+def fun_l19_n289(x)
+ if (x < 1)
+ fun_l20_n630(x)
+ else
+ fun_l20_n820(x)
+ end
+end
+
+def fun_l19_n290(x)
+ if (x < 1)
+ fun_l20_n774(x)
+ else
+ fun_l20_n125(x)
+ end
+end
+
+def fun_l19_n291(x)
+ if (x < 1)
+ fun_l20_n110(x)
+ else
+ fun_l20_n721(x)
+ end
+end
+
+def fun_l19_n292(x)
+ if (x < 1)
+ fun_l20_n777(x)
+ else
+ fun_l20_n44(x)
+ end
+end
+
+def fun_l19_n293(x)
+ if (x < 1)
+ fun_l20_n504(x)
+ else
+ fun_l20_n478(x)
+ end
+end
+
+def fun_l19_n294(x)
+ if (x < 1)
+ fun_l20_n540(x)
+ else
+ fun_l20_n603(x)
+ end
+end
+
+def fun_l19_n295(x)
+ if (x < 1)
+ fun_l20_n576(x)
+ else
+ fun_l20_n417(x)
+ end
+end
+
+def fun_l19_n296(x)
+ if (x < 1)
+ fun_l20_n553(x)
+ else
+ fun_l20_n295(x)
+ end
+end
+
+def fun_l19_n297(x)
+ if (x < 1)
+ fun_l20_n56(x)
+ else
+ fun_l20_n990(x)
+ end
+end
+
+def fun_l19_n298(x)
+ if (x < 1)
+ fun_l20_n362(x)
+ else
+ fun_l20_n158(x)
+ end
+end
+
+def fun_l19_n299(x)
+ if (x < 1)
+ fun_l20_n788(x)
+ else
+ fun_l20_n70(x)
+ end
+end
+
+def fun_l19_n300(x)
+ if (x < 1)
+ fun_l20_n670(x)
+ else
+ fun_l20_n542(x)
+ end
+end
+
+def fun_l19_n301(x)
+ if (x < 1)
+ fun_l20_n960(x)
+ else
+ fun_l20_n827(x)
+ end
+end
+
+def fun_l19_n302(x)
+ if (x < 1)
+ fun_l20_n366(x)
+ else
+ fun_l20_n325(x)
+ end
+end
+
+def fun_l19_n303(x)
+ if (x < 1)
+ fun_l20_n252(x)
+ else
+ fun_l20_n931(x)
+ end
+end
+
+def fun_l19_n304(x)
+ if (x < 1)
+ fun_l20_n124(x)
+ else
+ fun_l20_n102(x)
+ end
+end
+
+def fun_l19_n305(x)
+ if (x < 1)
+ fun_l20_n678(x)
+ else
+ fun_l20_n299(x)
+ end
+end
+
+def fun_l19_n306(x)
+ if (x < 1)
+ fun_l20_n538(x)
+ else
+ fun_l20_n371(x)
+ end
+end
+
+def fun_l19_n307(x)
+ if (x < 1)
+ fun_l20_n452(x)
+ else
+ fun_l20_n879(x)
+ end
+end
+
+def fun_l19_n308(x)
+ if (x < 1)
+ fun_l20_n410(x)
+ else
+ fun_l20_n156(x)
+ end
+end
+
+def fun_l19_n309(x)
+ if (x < 1)
+ fun_l20_n259(x)
+ else
+ fun_l20_n236(x)
+ end
+end
+
+def fun_l19_n310(x)
+ if (x < 1)
+ fun_l20_n710(x)
+ else
+ fun_l20_n23(x)
+ end
+end
+
+def fun_l19_n311(x)
+ if (x < 1)
+ fun_l20_n214(x)
+ else
+ fun_l20_n649(x)
+ end
+end
+
+def fun_l19_n312(x)
+ if (x < 1)
+ fun_l20_n603(x)
+ else
+ fun_l20_n213(x)
+ end
+end
+
+def fun_l19_n313(x)
+ if (x < 1)
+ fun_l20_n874(x)
+ else
+ fun_l20_n83(x)
+ end
+end
+
+def fun_l19_n314(x)
+ if (x < 1)
+ fun_l20_n902(x)
+ else
+ fun_l20_n303(x)
+ end
+end
+
+def fun_l19_n315(x)
+ if (x < 1)
+ fun_l20_n601(x)
+ else
+ fun_l20_n801(x)
+ end
+end
+
+def fun_l19_n316(x)
+ if (x < 1)
+ fun_l20_n76(x)
+ else
+ fun_l20_n960(x)
+ end
+end
+
+def fun_l19_n317(x)
+ if (x < 1)
+ fun_l20_n926(x)
+ else
+ fun_l20_n700(x)
+ end
+end
+
+def fun_l19_n318(x)
+ if (x < 1)
+ fun_l20_n233(x)
+ else
+ fun_l20_n278(x)
+ end
+end
+
+def fun_l19_n319(x)
+ if (x < 1)
+ fun_l20_n724(x)
+ else
+ fun_l20_n181(x)
+ end
+end
+
+def fun_l19_n320(x)
+ if (x < 1)
+ fun_l20_n367(x)
+ else
+ fun_l20_n511(x)
+ end
+end
+
+def fun_l19_n321(x)
+ if (x < 1)
+ fun_l20_n855(x)
+ else
+ fun_l20_n601(x)
+ end
+end
+
+def fun_l19_n322(x)
+ if (x < 1)
+ fun_l20_n173(x)
+ else
+ fun_l20_n151(x)
+ end
+end
+
+def fun_l19_n323(x)
+ if (x < 1)
+ fun_l20_n628(x)
+ else
+ fun_l20_n790(x)
+ end
+end
+
+def fun_l19_n324(x)
+ if (x < 1)
+ fun_l20_n423(x)
+ else
+ fun_l20_n40(x)
+ end
+end
+
+def fun_l19_n325(x)
+ if (x < 1)
+ fun_l20_n850(x)
+ else
+ fun_l20_n698(x)
+ end
+end
+
+def fun_l19_n326(x)
+ if (x < 1)
+ fun_l20_n351(x)
+ else
+ fun_l20_n562(x)
+ end
+end
+
+def fun_l19_n327(x)
+ if (x < 1)
+ fun_l20_n717(x)
+ else
+ fun_l20_n386(x)
+ end
+end
+
+def fun_l19_n328(x)
+ if (x < 1)
+ fun_l20_n461(x)
+ else
+ fun_l20_n604(x)
+ end
+end
+
+def fun_l19_n329(x)
+ if (x < 1)
+ fun_l20_n423(x)
+ else
+ fun_l20_n506(x)
+ end
+end
+
+def fun_l19_n330(x)
+ if (x < 1)
+ fun_l20_n389(x)
+ else
+ fun_l20_n365(x)
+ end
+end
+
+def fun_l19_n331(x)
+ if (x < 1)
+ fun_l20_n858(x)
+ else
+ fun_l20_n623(x)
+ end
+end
+
+def fun_l19_n332(x)
+ if (x < 1)
+ fun_l20_n34(x)
+ else
+ fun_l20_n598(x)
+ end
+end
+
+def fun_l19_n333(x)
+ if (x < 1)
+ fun_l20_n458(x)
+ else
+ fun_l20_n619(x)
+ end
+end
+
+def fun_l19_n334(x)
+ if (x < 1)
+ fun_l20_n203(x)
+ else
+ fun_l20_n391(x)
+ end
+end
+
+def fun_l19_n335(x)
+ if (x < 1)
+ fun_l20_n745(x)
+ else
+ fun_l20_n197(x)
+ end
+end
+
+def fun_l19_n336(x)
+ if (x < 1)
+ fun_l20_n388(x)
+ else
+ fun_l20_n682(x)
+ end
+end
+
+def fun_l19_n337(x)
+ if (x < 1)
+ fun_l20_n340(x)
+ else
+ fun_l20_n836(x)
+ end
+end
+
+def fun_l19_n338(x)
+ if (x < 1)
+ fun_l20_n231(x)
+ else
+ fun_l20_n508(x)
+ end
+end
+
+def fun_l19_n339(x)
+ if (x < 1)
+ fun_l20_n376(x)
+ else
+ fun_l20_n733(x)
+ end
+end
+
+def fun_l19_n340(x)
+ if (x < 1)
+ fun_l20_n162(x)
+ else
+ fun_l20_n397(x)
+ end
+end
+
+def fun_l19_n341(x)
+ if (x < 1)
+ fun_l20_n526(x)
+ else
+ fun_l20_n431(x)
+ end
+end
+
+def fun_l19_n342(x)
+ if (x < 1)
+ fun_l20_n850(x)
+ else
+ fun_l20_n226(x)
+ end
+end
+
+def fun_l19_n343(x)
+ if (x < 1)
+ fun_l20_n936(x)
+ else
+ fun_l20_n739(x)
+ end
+end
+
+def fun_l19_n344(x)
+ if (x < 1)
+ fun_l20_n639(x)
+ else
+ fun_l20_n844(x)
+ end
+end
+
+def fun_l19_n345(x)
+ if (x < 1)
+ fun_l20_n230(x)
+ else
+ fun_l20_n8(x)
+ end
+end
+
+def fun_l19_n346(x)
+ if (x < 1)
+ fun_l20_n156(x)
+ else
+ fun_l20_n417(x)
+ end
+end
+
+def fun_l19_n347(x)
+ if (x < 1)
+ fun_l20_n823(x)
+ else
+ fun_l20_n843(x)
+ end
+end
+
+def fun_l19_n348(x)
+ if (x < 1)
+ fun_l20_n798(x)
+ else
+ fun_l20_n538(x)
+ end
+end
+
+def fun_l19_n349(x)
+ if (x < 1)
+ fun_l20_n701(x)
+ else
+ fun_l20_n949(x)
+ end
+end
+
+def fun_l19_n350(x)
+ if (x < 1)
+ fun_l20_n131(x)
+ else
+ fun_l20_n727(x)
+ end
+end
+
+def fun_l19_n351(x)
+ if (x < 1)
+ fun_l20_n661(x)
+ else
+ fun_l20_n655(x)
+ end
+end
+
+def fun_l19_n352(x)
+ if (x < 1)
+ fun_l20_n824(x)
+ else
+ fun_l20_n436(x)
+ end
+end
+
+def fun_l19_n353(x)
+ if (x < 1)
+ fun_l20_n599(x)
+ else
+ fun_l20_n581(x)
+ end
+end
+
+def fun_l19_n354(x)
+ if (x < 1)
+ fun_l20_n290(x)
+ else
+ fun_l20_n632(x)
+ end
+end
+
+def fun_l19_n355(x)
+ if (x < 1)
+ fun_l20_n495(x)
+ else
+ fun_l20_n466(x)
+ end
+end
+
+def fun_l19_n356(x)
+ if (x < 1)
+ fun_l20_n70(x)
+ else
+ fun_l20_n270(x)
+ end
+end
+
+def fun_l19_n357(x)
+ if (x < 1)
+ fun_l20_n409(x)
+ else
+ fun_l20_n635(x)
+ end
+end
+
+def fun_l19_n358(x)
+ if (x < 1)
+ fun_l20_n396(x)
+ else
+ fun_l20_n41(x)
+ end
+end
+
+def fun_l19_n359(x)
+ if (x < 1)
+ fun_l20_n302(x)
+ else
+ fun_l20_n209(x)
+ end
+end
+
+def fun_l19_n360(x)
+ if (x < 1)
+ fun_l20_n844(x)
+ else
+ fun_l20_n23(x)
+ end
+end
+
+def fun_l19_n361(x)
+ if (x < 1)
+ fun_l20_n18(x)
+ else
+ fun_l20_n20(x)
+ end
+end
+
+def fun_l19_n362(x)
+ if (x < 1)
+ fun_l20_n821(x)
+ else
+ fun_l20_n806(x)
+ end
+end
+
+def fun_l19_n363(x)
+ if (x < 1)
+ fun_l20_n710(x)
+ else
+ fun_l20_n209(x)
+ end
+end
+
+def fun_l19_n364(x)
+ if (x < 1)
+ fun_l20_n979(x)
+ else
+ fun_l20_n457(x)
+ end
+end
+
+def fun_l19_n365(x)
+ if (x < 1)
+ fun_l20_n787(x)
+ else
+ fun_l20_n582(x)
+ end
+end
+
+def fun_l19_n366(x)
+ if (x < 1)
+ fun_l20_n274(x)
+ else
+ fun_l20_n710(x)
+ end
+end
+
+def fun_l19_n367(x)
+ if (x < 1)
+ fun_l20_n461(x)
+ else
+ fun_l20_n685(x)
+ end
+end
+
+def fun_l19_n368(x)
+ if (x < 1)
+ fun_l20_n953(x)
+ else
+ fun_l20_n477(x)
+ end
+end
+
+def fun_l19_n369(x)
+ if (x < 1)
+ fun_l20_n363(x)
+ else
+ fun_l20_n976(x)
+ end
+end
+
+def fun_l19_n370(x)
+ if (x < 1)
+ fun_l20_n934(x)
+ else
+ fun_l20_n742(x)
+ end
+end
+
+def fun_l19_n371(x)
+ if (x < 1)
+ fun_l20_n769(x)
+ else
+ fun_l20_n358(x)
+ end
+end
+
+def fun_l19_n372(x)
+ if (x < 1)
+ fun_l20_n53(x)
+ else
+ fun_l20_n915(x)
+ end
+end
+
+def fun_l19_n373(x)
+ if (x < 1)
+ fun_l20_n678(x)
+ else
+ fun_l20_n930(x)
+ end
+end
+
+def fun_l19_n374(x)
+ if (x < 1)
+ fun_l20_n160(x)
+ else
+ fun_l20_n937(x)
+ end
+end
+
+def fun_l19_n375(x)
+ if (x < 1)
+ fun_l20_n54(x)
+ else
+ fun_l20_n844(x)
+ end
+end
+
+def fun_l19_n376(x)
+ if (x < 1)
+ fun_l20_n911(x)
+ else
+ fun_l20_n756(x)
+ end
+end
+
+def fun_l19_n377(x)
+ if (x < 1)
+ fun_l20_n138(x)
+ else
+ fun_l20_n673(x)
+ end
+end
+
+def fun_l19_n378(x)
+ if (x < 1)
+ fun_l20_n976(x)
+ else
+ fun_l20_n720(x)
+ end
+end
+
+def fun_l19_n379(x)
+ if (x < 1)
+ fun_l20_n704(x)
+ else
+ fun_l20_n53(x)
+ end
+end
+
+def fun_l19_n380(x)
+ if (x < 1)
+ fun_l20_n762(x)
+ else
+ fun_l20_n340(x)
+ end
+end
+
+def fun_l19_n381(x)
+ if (x < 1)
+ fun_l20_n323(x)
+ else
+ fun_l20_n634(x)
+ end
+end
+
+def fun_l19_n382(x)
+ if (x < 1)
+ fun_l20_n515(x)
+ else
+ fun_l20_n562(x)
+ end
+end
+
+def fun_l19_n383(x)
+ if (x < 1)
+ fun_l20_n160(x)
+ else
+ fun_l20_n826(x)
+ end
+end
+
+def fun_l19_n384(x)
+ if (x < 1)
+ fun_l20_n779(x)
+ else
+ fun_l20_n638(x)
+ end
+end
+
+def fun_l19_n385(x)
+ if (x < 1)
+ fun_l20_n401(x)
+ else
+ fun_l20_n4(x)
+ end
+end
+
+def fun_l19_n386(x)
+ if (x < 1)
+ fun_l20_n604(x)
+ else
+ fun_l20_n820(x)
+ end
+end
+
+def fun_l19_n387(x)
+ if (x < 1)
+ fun_l20_n694(x)
+ else
+ fun_l20_n533(x)
+ end
+end
+
+def fun_l19_n388(x)
+ if (x < 1)
+ fun_l20_n687(x)
+ else
+ fun_l20_n697(x)
+ end
+end
+
+def fun_l19_n389(x)
+ if (x < 1)
+ fun_l20_n19(x)
+ else
+ fun_l20_n457(x)
+ end
+end
+
+def fun_l19_n390(x)
+ if (x < 1)
+ fun_l20_n812(x)
+ else
+ fun_l20_n152(x)
+ end
+end
+
+def fun_l19_n391(x)
+ if (x < 1)
+ fun_l20_n773(x)
+ else
+ fun_l20_n25(x)
+ end
+end
+
+def fun_l19_n392(x)
+ if (x < 1)
+ fun_l20_n24(x)
+ else
+ fun_l20_n930(x)
+ end
+end
+
+def fun_l19_n393(x)
+ if (x < 1)
+ fun_l20_n277(x)
+ else
+ fun_l20_n727(x)
+ end
+end
+
+def fun_l19_n394(x)
+ if (x < 1)
+ fun_l20_n272(x)
+ else
+ fun_l20_n298(x)
+ end
+end
+
+def fun_l19_n395(x)
+ if (x < 1)
+ fun_l20_n661(x)
+ else
+ fun_l20_n269(x)
+ end
+end
+
+def fun_l19_n396(x)
+ if (x < 1)
+ fun_l20_n624(x)
+ else
+ fun_l20_n654(x)
+ end
+end
+
+def fun_l19_n397(x)
+ if (x < 1)
+ fun_l20_n501(x)
+ else
+ fun_l20_n625(x)
+ end
+end
+
+def fun_l19_n398(x)
+ if (x < 1)
+ fun_l20_n596(x)
+ else
+ fun_l20_n160(x)
+ end
+end
+
+def fun_l19_n399(x)
+ if (x < 1)
+ fun_l20_n612(x)
+ else
+ fun_l20_n954(x)
+ end
+end
+
+def fun_l19_n400(x)
+ if (x < 1)
+ fun_l20_n911(x)
+ else
+ fun_l20_n321(x)
+ end
+end
+
+def fun_l19_n401(x)
+ if (x < 1)
+ fun_l20_n294(x)
+ else
+ fun_l20_n382(x)
+ end
+end
+
+def fun_l19_n402(x)
+ if (x < 1)
+ fun_l20_n193(x)
+ else
+ fun_l20_n732(x)
+ end
+end
+
+def fun_l19_n403(x)
+ if (x < 1)
+ fun_l20_n929(x)
+ else
+ fun_l20_n109(x)
+ end
+end
+
+def fun_l19_n404(x)
+ if (x < 1)
+ fun_l20_n647(x)
+ else
+ fun_l20_n497(x)
+ end
+end
+
+def fun_l19_n405(x)
+ if (x < 1)
+ fun_l20_n124(x)
+ else
+ fun_l20_n395(x)
+ end
+end
+
+def fun_l19_n406(x)
+ if (x < 1)
+ fun_l20_n949(x)
+ else
+ fun_l20_n195(x)
+ end
+end
+
+def fun_l19_n407(x)
+ if (x < 1)
+ fun_l20_n249(x)
+ else
+ fun_l20_n771(x)
+ end
+end
+
+def fun_l19_n408(x)
+ if (x < 1)
+ fun_l20_n728(x)
+ else
+ fun_l20_n752(x)
+ end
+end
+
+def fun_l19_n409(x)
+ if (x < 1)
+ fun_l20_n135(x)
+ else
+ fun_l20_n774(x)
+ end
+end
+
+def fun_l19_n410(x)
+ if (x < 1)
+ fun_l20_n277(x)
+ else
+ fun_l20_n499(x)
+ end
+end
+
+def fun_l19_n411(x)
+ if (x < 1)
+ fun_l20_n634(x)
+ else
+ fun_l20_n713(x)
+ end
+end
+
+def fun_l19_n412(x)
+ if (x < 1)
+ fun_l20_n118(x)
+ else
+ fun_l20_n879(x)
+ end
+end
+
+def fun_l19_n413(x)
+ if (x < 1)
+ fun_l20_n202(x)
+ else
+ fun_l20_n146(x)
+ end
+end
+
+def fun_l19_n414(x)
+ if (x < 1)
+ fun_l20_n668(x)
+ else
+ fun_l20_n22(x)
+ end
+end
+
+def fun_l19_n415(x)
+ if (x < 1)
+ fun_l20_n673(x)
+ else
+ fun_l20_n91(x)
+ end
+end
+
+def fun_l19_n416(x)
+ if (x < 1)
+ fun_l20_n399(x)
+ else
+ fun_l20_n288(x)
+ end
+end
+
+def fun_l19_n417(x)
+ if (x < 1)
+ fun_l20_n985(x)
+ else
+ fun_l20_n63(x)
+ end
+end
+
+def fun_l19_n418(x)
+ if (x < 1)
+ fun_l20_n973(x)
+ else
+ fun_l20_n37(x)
+ end
+end
+
+def fun_l19_n419(x)
+ if (x < 1)
+ fun_l20_n907(x)
+ else
+ fun_l20_n274(x)
+ end
+end
+
+def fun_l19_n420(x)
+ if (x < 1)
+ fun_l20_n0(x)
+ else
+ fun_l20_n895(x)
+ end
+end
+
+def fun_l19_n421(x)
+ if (x < 1)
+ fun_l20_n138(x)
+ else
+ fun_l20_n941(x)
+ end
+end
+
+def fun_l19_n422(x)
+ if (x < 1)
+ fun_l20_n944(x)
+ else
+ fun_l20_n393(x)
+ end
+end
+
+def fun_l19_n423(x)
+ if (x < 1)
+ fun_l20_n7(x)
+ else
+ fun_l20_n879(x)
+ end
+end
+
+def fun_l19_n424(x)
+ if (x < 1)
+ fun_l20_n855(x)
+ else
+ fun_l20_n19(x)
+ end
+end
+
+def fun_l19_n425(x)
+ if (x < 1)
+ fun_l20_n11(x)
+ else
+ fun_l20_n12(x)
+ end
+end
+
+def fun_l19_n426(x)
+ if (x < 1)
+ fun_l20_n652(x)
+ else
+ fun_l20_n501(x)
+ end
+end
+
+def fun_l19_n427(x)
+ if (x < 1)
+ fun_l20_n825(x)
+ else
+ fun_l20_n547(x)
+ end
+end
+
+def fun_l19_n428(x)
+ if (x < 1)
+ fun_l20_n485(x)
+ else
+ fun_l20_n905(x)
+ end
+end
+
+def fun_l19_n429(x)
+ if (x < 1)
+ fun_l20_n800(x)
+ else
+ fun_l20_n922(x)
+ end
+end
+
+def fun_l19_n430(x)
+ if (x < 1)
+ fun_l20_n122(x)
+ else
+ fun_l20_n79(x)
+ end
+end
+
+def fun_l19_n431(x)
+ if (x < 1)
+ fun_l20_n822(x)
+ else
+ fun_l20_n228(x)
+ end
+end
+
+def fun_l19_n432(x)
+ if (x < 1)
+ fun_l20_n616(x)
+ else
+ fun_l20_n886(x)
+ end
+end
+
+def fun_l19_n433(x)
+ if (x < 1)
+ fun_l20_n232(x)
+ else
+ fun_l20_n716(x)
+ end
+end
+
+def fun_l19_n434(x)
+ if (x < 1)
+ fun_l20_n288(x)
+ else
+ fun_l20_n497(x)
+ end
+end
+
+def fun_l19_n435(x)
+ if (x < 1)
+ fun_l20_n606(x)
+ else
+ fun_l20_n220(x)
+ end
+end
+
+def fun_l19_n436(x)
+ if (x < 1)
+ fun_l20_n185(x)
+ else
+ fun_l20_n69(x)
+ end
+end
+
+def fun_l19_n437(x)
+ if (x < 1)
+ fun_l20_n869(x)
+ else
+ fun_l20_n264(x)
+ end
+end
+
+def fun_l19_n438(x)
+ if (x < 1)
+ fun_l20_n142(x)
+ else
+ fun_l20_n766(x)
+ end
+end
+
+def fun_l19_n439(x)
+ if (x < 1)
+ fun_l20_n155(x)
+ else
+ fun_l20_n697(x)
+ end
+end
+
+def fun_l19_n440(x)
+ if (x < 1)
+ fun_l20_n486(x)
+ else
+ fun_l20_n442(x)
+ end
+end
+
+def fun_l19_n441(x)
+ if (x < 1)
+ fun_l20_n896(x)
+ else
+ fun_l20_n404(x)
+ end
+end
+
+def fun_l19_n442(x)
+ if (x < 1)
+ fun_l20_n944(x)
+ else
+ fun_l20_n906(x)
+ end
+end
+
+def fun_l19_n443(x)
+ if (x < 1)
+ fun_l20_n400(x)
+ else
+ fun_l20_n230(x)
+ end
+end
+
+def fun_l19_n444(x)
+ if (x < 1)
+ fun_l20_n646(x)
+ else
+ fun_l20_n89(x)
+ end
+end
+
+def fun_l19_n445(x)
+ if (x < 1)
+ fun_l20_n683(x)
+ else
+ fun_l20_n434(x)
+ end
+end
+
+def fun_l19_n446(x)
+ if (x < 1)
+ fun_l20_n333(x)
+ else
+ fun_l20_n164(x)
+ end
+end
+
+def fun_l19_n447(x)
+ if (x < 1)
+ fun_l20_n732(x)
+ else
+ fun_l20_n721(x)
+ end
+end
+
+def fun_l19_n448(x)
+ if (x < 1)
+ fun_l20_n948(x)
+ else
+ fun_l20_n343(x)
+ end
+end
+
+def fun_l19_n449(x)
+ if (x < 1)
+ fun_l20_n211(x)
+ else
+ fun_l20_n754(x)
+ end
+end
+
+def fun_l19_n450(x)
+ if (x < 1)
+ fun_l20_n984(x)
+ else
+ fun_l20_n952(x)
+ end
+end
+
+def fun_l19_n451(x)
+ if (x < 1)
+ fun_l20_n349(x)
+ else
+ fun_l20_n424(x)
+ end
+end
+
+def fun_l19_n452(x)
+ if (x < 1)
+ fun_l20_n721(x)
+ else
+ fun_l20_n475(x)
+ end
+end
+
+def fun_l19_n453(x)
+ if (x < 1)
+ fun_l20_n143(x)
+ else
+ fun_l20_n875(x)
+ end
+end
+
+def fun_l19_n454(x)
+ if (x < 1)
+ fun_l20_n561(x)
+ else
+ fun_l20_n255(x)
+ end
+end
+
+def fun_l19_n455(x)
+ if (x < 1)
+ fun_l20_n962(x)
+ else
+ fun_l20_n489(x)
+ end
+end
+
+def fun_l19_n456(x)
+ if (x < 1)
+ fun_l20_n95(x)
+ else
+ fun_l20_n434(x)
+ end
+end
+
+def fun_l19_n457(x)
+ if (x < 1)
+ fun_l20_n863(x)
+ else
+ fun_l20_n198(x)
+ end
+end
+
+def fun_l19_n458(x)
+ if (x < 1)
+ fun_l20_n106(x)
+ else
+ fun_l20_n786(x)
+ end
+end
+
+def fun_l19_n459(x)
+ if (x < 1)
+ fun_l20_n415(x)
+ else
+ fun_l20_n456(x)
+ end
+end
+
+def fun_l19_n460(x)
+ if (x < 1)
+ fun_l20_n706(x)
+ else
+ fun_l20_n47(x)
+ end
+end
+
+def fun_l19_n461(x)
+ if (x < 1)
+ fun_l20_n894(x)
+ else
+ fun_l20_n119(x)
+ end
+end
+
+def fun_l19_n462(x)
+ if (x < 1)
+ fun_l20_n267(x)
+ else
+ fun_l20_n662(x)
+ end
+end
+
+def fun_l19_n463(x)
+ if (x < 1)
+ fun_l20_n689(x)
+ else
+ fun_l20_n633(x)
+ end
+end
+
+def fun_l19_n464(x)
+ if (x < 1)
+ fun_l20_n94(x)
+ else
+ fun_l20_n967(x)
+ end
+end
+
+def fun_l19_n465(x)
+ if (x < 1)
+ fun_l20_n902(x)
+ else
+ fun_l20_n619(x)
+ end
+end
+
+def fun_l19_n466(x)
+ if (x < 1)
+ fun_l20_n574(x)
+ else
+ fun_l20_n204(x)
+ end
+end
+
+def fun_l19_n467(x)
+ if (x < 1)
+ fun_l20_n195(x)
+ else
+ fun_l20_n455(x)
+ end
+end
+
+def fun_l19_n468(x)
+ if (x < 1)
+ fun_l20_n173(x)
+ else
+ fun_l20_n4(x)
+ end
+end
+
+def fun_l19_n469(x)
+ if (x < 1)
+ fun_l20_n769(x)
+ else
+ fun_l20_n314(x)
+ end
+end
+
+def fun_l19_n470(x)
+ if (x < 1)
+ fun_l20_n669(x)
+ else
+ fun_l20_n648(x)
+ end
+end
+
+def fun_l19_n471(x)
+ if (x < 1)
+ fun_l20_n741(x)
+ else
+ fun_l20_n238(x)
+ end
+end
+
+def fun_l19_n472(x)
+ if (x < 1)
+ fun_l20_n370(x)
+ else
+ fun_l20_n610(x)
+ end
+end
+
+def fun_l19_n473(x)
+ if (x < 1)
+ fun_l20_n200(x)
+ else
+ fun_l20_n698(x)
+ end
+end
+
+def fun_l19_n474(x)
+ if (x < 1)
+ fun_l20_n200(x)
+ else
+ fun_l20_n951(x)
+ end
+end
+
+def fun_l19_n475(x)
+ if (x < 1)
+ fun_l20_n47(x)
+ else
+ fun_l20_n244(x)
+ end
+end
+
+def fun_l19_n476(x)
+ if (x < 1)
+ fun_l20_n314(x)
+ else
+ fun_l20_n163(x)
+ end
+end
+
+def fun_l19_n477(x)
+ if (x < 1)
+ fun_l20_n665(x)
+ else
+ fun_l20_n278(x)
+ end
+end
+
+def fun_l19_n478(x)
+ if (x < 1)
+ fun_l20_n539(x)
+ else
+ fun_l20_n149(x)
+ end
+end
+
+def fun_l19_n479(x)
+ if (x < 1)
+ fun_l20_n10(x)
+ else
+ fun_l20_n686(x)
+ end
+end
+
+def fun_l19_n480(x)
+ if (x < 1)
+ fun_l20_n684(x)
+ else
+ fun_l20_n531(x)
+ end
+end
+
+def fun_l19_n481(x)
+ if (x < 1)
+ fun_l20_n579(x)
+ else
+ fun_l20_n468(x)
+ end
+end
+
+def fun_l19_n482(x)
+ if (x < 1)
+ fun_l20_n794(x)
+ else
+ fun_l20_n116(x)
+ end
+end
+
+def fun_l19_n483(x)
+ if (x < 1)
+ fun_l20_n848(x)
+ else
+ fun_l20_n278(x)
+ end
+end
+
+def fun_l19_n484(x)
+ if (x < 1)
+ fun_l20_n965(x)
+ else
+ fun_l20_n23(x)
+ end
+end
+
+def fun_l19_n485(x)
+ if (x < 1)
+ fun_l20_n123(x)
+ else
+ fun_l20_n905(x)
+ end
+end
+
+def fun_l19_n486(x)
+ if (x < 1)
+ fun_l20_n69(x)
+ else
+ fun_l20_n4(x)
+ end
+end
+
+def fun_l19_n487(x)
+ if (x < 1)
+ fun_l20_n234(x)
+ else
+ fun_l20_n648(x)
+ end
+end
+
+def fun_l19_n488(x)
+ if (x < 1)
+ fun_l20_n31(x)
+ else
+ fun_l20_n127(x)
+ end
+end
+
+def fun_l19_n489(x)
+ if (x < 1)
+ fun_l20_n469(x)
+ else
+ fun_l20_n300(x)
+ end
+end
+
+def fun_l19_n490(x)
+ if (x < 1)
+ fun_l20_n855(x)
+ else
+ fun_l20_n722(x)
+ end
+end
+
+def fun_l19_n491(x)
+ if (x < 1)
+ fun_l20_n949(x)
+ else
+ fun_l20_n567(x)
+ end
+end
+
+def fun_l19_n492(x)
+ if (x < 1)
+ fun_l20_n465(x)
+ else
+ fun_l20_n226(x)
+ end
+end
+
+def fun_l19_n493(x)
+ if (x < 1)
+ fun_l20_n436(x)
+ else
+ fun_l20_n292(x)
+ end
+end
+
+def fun_l19_n494(x)
+ if (x < 1)
+ fun_l20_n552(x)
+ else
+ fun_l20_n81(x)
+ end
+end
+
+def fun_l19_n495(x)
+ if (x < 1)
+ fun_l20_n950(x)
+ else
+ fun_l20_n481(x)
+ end
+end
+
+def fun_l19_n496(x)
+ if (x < 1)
+ fun_l20_n382(x)
+ else
+ fun_l20_n846(x)
+ end
+end
+
+def fun_l19_n497(x)
+ if (x < 1)
+ fun_l20_n355(x)
+ else
+ fun_l20_n546(x)
+ end
+end
+
+def fun_l19_n498(x)
+ if (x < 1)
+ fun_l20_n404(x)
+ else
+ fun_l20_n655(x)
+ end
+end
+
+def fun_l19_n499(x)
+ if (x < 1)
+ fun_l20_n794(x)
+ else
+ fun_l20_n531(x)
+ end
+end
+
+def fun_l19_n500(x)
+ if (x < 1)
+ fun_l20_n555(x)
+ else
+ fun_l20_n37(x)
+ end
+end
+
+def fun_l19_n501(x)
+ if (x < 1)
+ fun_l20_n955(x)
+ else
+ fun_l20_n60(x)
+ end
+end
+
+def fun_l19_n502(x)
+ if (x < 1)
+ fun_l20_n957(x)
+ else
+ fun_l20_n482(x)
+ end
+end
+
+def fun_l19_n503(x)
+ if (x < 1)
+ fun_l20_n683(x)
+ else
+ fun_l20_n374(x)
+ end
+end
+
+def fun_l19_n504(x)
+ if (x < 1)
+ fun_l20_n839(x)
+ else
+ fun_l20_n867(x)
+ end
+end
+
+def fun_l19_n505(x)
+ if (x < 1)
+ fun_l20_n956(x)
+ else
+ fun_l20_n336(x)
+ end
+end
+
+def fun_l19_n506(x)
+ if (x < 1)
+ fun_l20_n234(x)
+ else
+ fun_l20_n50(x)
+ end
+end
+
+def fun_l19_n507(x)
+ if (x < 1)
+ fun_l20_n968(x)
+ else
+ fun_l20_n627(x)
+ end
+end
+
+def fun_l19_n508(x)
+ if (x < 1)
+ fun_l20_n680(x)
+ else
+ fun_l20_n812(x)
+ end
+end
+
+def fun_l19_n509(x)
+ if (x < 1)
+ fun_l20_n106(x)
+ else
+ fun_l20_n428(x)
+ end
+end
+
+def fun_l19_n510(x)
+ if (x < 1)
+ fun_l20_n50(x)
+ else
+ fun_l20_n101(x)
+ end
+end
+
+def fun_l19_n511(x)
+ if (x < 1)
+ fun_l20_n75(x)
+ else
+ fun_l20_n299(x)
+ end
+end
+
+def fun_l19_n512(x)
+ if (x < 1)
+ fun_l20_n612(x)
+ else
+ fun_l20_n367(x)
+ end
+end
+
+def fun_l19_n513(x)
+ if (x < 1)
+ fun_l20_n278(x)
+ else
+ fun_l20_n803(x)
+ end
+end
+
+def fun_l19_n514(x)
+ if (x < 1)
+ fun_l20_n637(x)
+ else
+ fun_l20_n837(x)
+ end
+end
+
+def fun_l19_n515(x)
+ if (x < 1)
+ fun_l20_n908(x)
+ else
+ fun_l20_n410(x)
+ end
+end
+
+def fun_l19_n516(x)
+ if (x < 1)
+ fun_l20_n349(x)
+ else
+ fun_l20_n219(x)
+ end
+end
+
+def fun_l19_n517(x)
+ if (x < 1)
+ fun_l20_n869(x)
+ else
+ fun_l20_n922(x)
+ end
+end
+
+def fun_l19_n518(x)
+ if (x < 1)
+ fun_l20_n429(x)
+ else
+ fun_l20_n332(x)
+ end
+end
+
+def fun_l19_n519(x)
+ if (x < 1)
+ fun_l20_n775(x)
+ else
+ fun_l20_n417(x)
+ end
+end
+
+def fun_l19_n520(x)
+ if (x < 1)
+ fun_l20_n551(x)
+ else
+ fun_l20_n214(x)
+ end
+end
+
+def fun_l19_n521(x)
+ if (x < 1)
+ fun_l20_n643(x)
+ else
+ fun_l20_n74(x)
+ end
+end
+
+def fun_l19_n522(x)
+ if (x < 1)
+ fun_l20_n960(x)
+ else
+ fun_l20_n189(x)
+ end
+end
+
+def fun_l19_n523(x)
+ if (x < 1)
+ fun_l20_n815(x)
+ else
+ fun_l20_n624(x)
+ end
+end
+
+def fun_l19_n524(x)
+ if (x < 1)
+ fun_l20_n247(x)
+ else
+ fun_l20_n679(x)
+ end
+end
+
+def fun_l19_n525(x)
+ if (x < 1)
+ fun_l20_n261(x)
+ else
+ fun_l20_n728(x)
+ end
+end
+
+def fun_l19_n526(x)
+ if (x < 1)
+ fun_l20_n361(x)
+ else
+ fun_l20_n295(x)
+ end
+end
+
+def fun_l19_n527(x)
+ if (x < 1)
+ fun_l20_n559(x)
+ else
+ fun_l20_n763(x)
+ end
+end
+
+def fun_l19_n528(x)
+ if (x < 1)
+ fun_l20_n291(x)
+ else
+ fun_l20_n815(x)
+ end
+end
+
+def fun_l19_n529(x)
+ if (x < 1)
+ fun_l20_n224(x)
+ else
+ fun_l20_n305(x)
+ end
+end
+
+def fun_l19_n530(x)
+ if (x < 1)
+ fun_l20_n579(x)
+ else
+ fun_l20_n370(x)
+ end
+end
+
+def fun_l19_n531(x)
+ if (x < 1)
+ fun_l20_n571(x)
+ else
+ fun_l20_n65(x)
+ end
+end
+
+def fun_l19_n532(x)
+ if (x < 1)
+ fun_l20_n815(x)
+ else
+ fun_l20_n567(x)
+ end
+end
+
+def fun_l19_n533(x)
+ if (x < 1)
+ fun_l20_n48(x)
+ else
+ fun_l20_n386(x)
+ end
+end
+
+def fun_l19_n534(x)
+ if (x < 1)
+ fun_l20_n478(x)
+ else
+ fun_l20_n679(x)
+ end
+end
+
+def fun_l19_n535(x)
+ if (x < 1)
+ fun_l20_n241(x)
+ else
+ fun_l20_n829(x)
+ end
+end
+
+def fun_l19_n536(x)
+ if (x < 1)
+ fun_l20_n267(x)
+ else
+ fun_l20_n160(x)
+ end
+end
+
+def fun_l19_n537(x)
+ if (x < 1)
+ fun_l20_n719(x)
+ else
+ fun_l20_n199(x)
+ end
+end
+
+def fun_l19_n538(x)
+ if (x < 1)
+ fun_l20_n477(x)
+ else
+ fun_l20_n662(x)
+ end
+end
+
+def fun_l19_n539(x)
+ if (x < 1)
+ fun_l20_n506(x)
+ else
+ fun_l20_n856(x)
+ end
+end
+
+def fun_l19_n540(x)
+ if (x < 1)
+ fun_l20_n717(x)
+ else
+ fun_l20_n207(x)
+ end
+end
+
+def fun_l19_n541(x)
+ if (x < 1)
+ fun_l20_n94(x)
+ else
+ fun_l20_n988(x)
+ end
+end
+
+def fun_l19_n542(x)
+ if (x < 1)
+ fun_l20_n837(x)
+ else
+ fun_l20_n334(x)
+ end
+end
+
+def fun_l19_n543(x)
+ if (x < 1)
+ fun_l20_n23(x)
+ else
+ fun_l20_n991(x)
+ end
+end
+
+def fun_l19_n544(x)
+ if (x < 1)
+ fun_l20_n558(x)
+ else
+ fun_l20_n740(x)
+ end
+end
+
+def fun_l19_n545(x)
+ if (x < 1)
+ fun_l20_n762(x)
+ else
+ fun_l20_n79(x)
+ end
+end
+
+def fun_l19_n546(x)
+ if (x < 1)
+ fun_l20_n81(x)
+ else
+ fun_l20_n331(x)
+ end
+end
+
+def fun_l19_n547(x)
+ if (x < 1)
+ fun_l20_n9(x)
+ else
+ fun_l20_n267(x)
+ end
+end
+
+def fun_l19_n548(x)
+ if (x < 1)
+ fun_l20_n550(x)
+ else
+ fun_l20_n98(x)
+ end
+end
+
+def fun_l19_n549(x)
+ if (x < 1)
+ fun_l20_n735(x)
+ else
+ fun_l20_n361(x)
+ end
+end
+
+def fun_l19_n550(x)
+ if (x < 1)
+ fun_l20_n155(x)
+ else
+ fun_l20_n560(x)
+ end
+end
+
+def fun_l19_n551(x)
+ if (x < 1)
+ fun_l20_n394(x)
+ else
+ fun_l20_n793(x)
+ end
+end
+
+def fun_l19_n552(x)
+ if (x < 1)
+ fun_l20_n826(x)
+ else
+ fun_l20_n508(x)
+ end
+end
+
+def fun_l19_n553(x)
+ if (x < 1)
+ fun_l20_n569(x)
+ else
+ fun_l20_n981(x)
+ end
+end
+
+def fun_l19_n554(x)
+ if (x < 1)
+ fun_l20_n580(x)
+ else
+ fun_l20_n848(x)
+ end
+end
+
+def fun_l19_n555(x)
+ if (x < 1)
+ fun_l20_n31(x)
+ else
+ fun_l20_n191(x)
+ end
+end
+
+def fun_l19_n556(x)
+ if (x < 1)
+ fun_l20_n283(x)
+ else
+ fun_l20_n376(x)
+ end
+end
+
+def fun_l19_n557(x)
+ if (x < 1)
+ fun_l20_n978(x)
+ else
+ fun_l20_n554(x)
+ end
+end
+
+def fun_l19_n558(x)
+ if (x < 1)
+ fun_l20_n727(x)
+ else
+ fun_l20_n89(x)
+ end
+end
+
+def fun_l19_n559(x)
+ if (x < 1)
+ fun_l20_n204(x)
+ else
+ fun_l20_n652(x)
+ end
+end
+
+def fun_l19_n560(x)
+ if (x < 1)
+ fun_l20_n481(x)
+ else
+ fun_l20_n114(x)
+ end
+end
+
+def fun_l19_n561(x)
+ if (x < 1)
+ fun_l20_n601(x)
+ else
+ fun_l20_n187(x)
+ end
+end
+
+def fun_l19_n562(x)
+ if (x < 1)
+ fun_l20_n682(x)
+ else
+ fun_l20_n88(x)
+ end
+end
+
+def fun_l19_n563(x)
+ if (x < 1)
+ fun_l20_n346(x)
+ else
+ fun_l20_n190(x)
+ end
+end
+
+def fun_l19_n564(x)
+ if (x < 1)
+ fun_l20_n15(x)
+ else
+ fun_l20_n315(x)
+ end
+end
+
+def fun_l19_n565(x)
+ if (x < 1)
+ fun_l20_n555(x)
+ else
+ fun_l20_n208(x)
+ end
+end
+
+def fun_l19_n566(x)
+ if (x < 1)
+ fun_l20_n29(x)
+ else
+ fun_l20_n511(x)
+ end
+end
+
+def fun_l19_n567(x)
+ if (x < 1)
+ fun_l20_n897(x)
+ else
+ fun_l20_n309(x)
+ end
+end
+
+def fun_l19_n568(x)
+ if (x < 1)
+ fun_l20_n586(x)
+ else
+ fun_l20_n602(x)
+ end
+end
+
+def fun_l19_n569(x)
+ if (x < 1)
+ fun_l20_n51(x)
+ else
+ fun_l20_n483(x)
+ end
+end
+
+def fun_l19_n570(x)
+ if (x < 1)
+ fun_l20_n159(x)
+ else
+ fun_l20_n5(x)
+ end
+end
+
+def fun_l19_n571(x)
+ if (x < 1)
+ fun_l20_n892(x)
+ else
+ fun_l20_n336(x)
+ end
+end
+
+def fun_l19_n572(x)
+ if (x < 1)
+ fun_l20_n203(x)
+ else
+ fun_l20_n287(x)
+ end
+end
+
+def fun_l19_n573(x)
+ if (x < 1)
+ fun_l20_n41(x)
+ else
+ fun_l20_n51(x)
+ end
+end
+
+def fun_l19_n574(x)
+ if (x < 1)
+ fun_l20_n977(x)
+ else
+ fun_l20_n474(x)
+ end
+end
+
+def fun_l19_n575(x)
+ if (x < 1)
+ fun_l20_n247(x)
+ else
+ fun_l20_n281(x)
+ end
+end
+
+def fun_l19_n576(x)
+ if (x < 1)
+ fun_l20_n877(x)
+ else
+ fun_l20_n836(x)
+ end
+end
+
+def fun_l19_n577(x)
+ if (x < 1)
+ fun_l20_n527(x)
+ else
+ fun_l20_n549(x)
+ end
+end
+
+def fun_l19_n578(x)
+ if (x < 1)
+ fun_l20_n102(x)
+ else
+ fun_l20_n906(x)
+ end
+end
+
+def fun_l19_n579(x)
+ if (x < 1)
+ fun_l20_n842(x)
+ else
+ fun_l20_n554(x)
+ end
+end
+
+def fun_l19_n580(x)
+ if (x < 1)
+ fun_l20_n371(x)
+ else
+ fun_l20_n44(x)
+ end
+end
+
+def fun_l19_n581(x)
+ if (x < 1)
+ fun_l20_n306(x)
+ else
+ fun_l20_n571(x)
+ end
+end
+
+def fun_l19_n582(x)
+ if (x < 1)
+ fun_l20_n548(x)
+ else
+ fun_l20_n596(x)
+ end
+end
+
+def fun_l19_n583(x)
+ if (x < 1)
+ fun_l20_n724(x)
+ else
+ fun_l20_n835(x)
+ end
+end
+
+def fun_l19_n584(x)
+ if (x < 1)
+ fun_l20_n238(x)
+ else
+ fun_l20_n408(x)
+ end
+end
+
+def fun_l19_n585(x)
+ if (x < 1)
+ fun_l20_n378(x)
+ else
+ fun_l20_n272(x)
+ end
+end
+
+def fun_l19_n586(x)
+ if (x < 1)
+ fun_l20_n647(x)
+ else
+ fun_l20_n814(x)
+ end
+end
+
+def fun_l19_n587(x)
+ if (x < 1)
+ fun_l20_n210(x)
+ else
+ fun_l20_n801(x)
+ end
+end
+
+def fun_l19_n588(x)
+ if (x < 1)
+ fun_l20_n796(x)
+ else
+ fun_l20_n329(x)
+ end
+end
+
+def fun_l19_n589(x)
+ if (x < 1)
+ fun_l20_n403(x)
+ else
+ fun_l20_n392(x)
+ end
+end
+
+def fun_l19_n590(x)
+ if (x < 1)
+ fun_l20_n677(x)
+ else
+ fun_l20_n574(x)
+ end
+end
+
+def fun_l19_n591(x)
+ if (x < 1)
+ fun_l20_n183(x)
+ else
+ fun_l20_n962(x)
+ end
+end
+
+def fun_l19_n592(x)
+ if (x < 1)
+ fun_l20_n230(x)
+ else
+ fun_l20_n783(x)
+ end
+end
+
+def fun_l19_n593(x)
+ if (x < 1)
+ fun_l20_n191(x)
+ else
+ fun_l20_n42(x)
+ end
+end
+
+def fun_l19_n594(x)
+ if (x < 1)
+ fun_l20_n244(x)
+ else
+ fun_l20_n760(x)
+ end
+end
+
+def fun_l19_n595(x)
+ if (x < 1)
+ fun_l20_n754(x)
+ else
+ fun_l20_n570(x)
+ end
+end
+
+def fun_l19_n596(x)
+ if (x < 1)
+ fun_l20_n612(x)
+ else
+ fun_l20_n287(x)
+ end
+end
+
+def fun_l19_n597(x)
+ if (x < 1)
+ fun_l20_n89(x)
+ else
+ fun_l20_n625(x)
+ end
+end
+
+def fun_l19_n598(x)
+ if (x < 1)
+ fun_l20_n782(x)
+ else
+ fun_l20_n516(x)
+ end
+end
+
+def fun_l19_n599(x)
+ if (x < 1)
+ fun_l20_n75(x)
+ else
+ fun_l20_n857(x)
+ end
+end
+
+def fun_l19_n600(x)
+ if (x < 1)
+ fun_l20_n717(x)
+ else
+ fun_l20_n408(x)
+ end
+end
+
+def fun_l19_n601(x)
+ if (x < 1)
+ fun_l20_n528(x)
+ else
+ fun_l20_n761(x)
+ end
+end
+
+def fun_l19_n602(x)
+ if (x < 1)
+ fun_l20_n319(x)
+ else
+ fun_l20_n645(x)
+ end
+end
+
+def fun_l19_n603(x)
+ if (x < 1)
+ fun_l20_n20(x)
+ else
+ fun_l20_n621(x)
+ end
+end
+
+def fun_l19_n604(x)
+ if (x < 1)
+ fun_l20_n118(x)
+ else
+ fun_l20_n699(x)
+ end
+end
+
+def fun_l19_n605(x)
+ if (x < 1)
+ fun_l20_n19(x)
+ else
+ fun_l20_n63(x)
+ end
+end
+
+def fun_l19_n606(x)
+ if (x < 1)
+ fun_l20_n845(x)
+ else
+ fun_l20_n618(x)
+ end
+end
+
+def fun_l19_n607(x)
+ if (x < 1)
+ fun_l20_n733(x)
+ else
+ fun_l20_n880(x)
+ end
+end
+
+def fun_l19_n608(x)
+ if (x < 1)
+ fun_l20_n785(x)
+ else
+ fun_l20_n254(x)
+ end
+end
+
+def fun_l19_n609(x)
+ if (x < 1)
+ fun_l20_n393(x)
+ else
+ fun_l20_n946(x)
+ end
+end
+
+def fun_l19_n610(x)
+ if (x < 1)
+ fun_l20_n635(x)
+ else
+ fun_l20_n418(x)
+ end
+end
+
+def fun_l19_n611(x)
+ if (x < 1)
+ fun_l20_n987(x)
+ else
+ fun_l20_n703(x)
+ end
+end
+
+def fun_l19_n612(x)
+ if (x < 1)
+ fun_l20_n130(x)
+ else
+ fun_l20_n439(x)
+ end
+end
+
+def fun_l19_n613(x)
+ if (x < 1)
+ fun_l20_n516(x)
+ else
+ fun_l20_n724(x)
+ end
+end
+
+def fun_l19_n614(x)
+ if (x < 1)
+ fun_l20_n44(x)
+ else
+ fun_l20_n102(x)
+ end
+end
+
+def fun_l19_n615(x)
+ if (x < 1)
+ fun_l20_n353(x)
+ else
+ fun_l20_n999(x)
+ end
+end
+
+def fun_l19_n616(x)
+ if (x < 1)
+ fun_l20_n191(x)
+ else
+ fun_l20_n726(x)
+ end
+end
+
+def fun_l19_n617(x)
+ if (x < 1)
+ fun_l20_n375(x)
+ else
+ fun_l20_n575(x)
+ end
+end
+
+def fun_l19_n618(x)
+ if (x < 1)
+ fun_l20_n719(x)
+ else
+ fun_l20_n581(x)
+ end
+end
+
+def fun_l19_n619(x)
+ if (x < 1)
+ fun_l20_n960(x)
+ else
+ fun_l20_n316(x)
+ end
+end
+
+def fun_l19_n620(x)
+ if (x < 1)
+ fun_l20_n860(x)
+ else
+ fun_l20_n784(x)
+ end
+end
+
+def fun_l19_n621(x)
+ if (x < 1)
+ fun_l20_n124(x)
+ else
+ fun_l20_n577(x)
+ end
+end
+
+def fun_l19_n622(x)
+ if (x < 1)
+ fun_l20_n547(x)
+ else
+ fun_l20_n623(x)
+ end
+end
+
+def fun_l19_n623(x)
+ if (x < 1)
+ fun_l20_n842(x)
+ else
+ fun_l20_n380(x)
+ end
+end
+
+def fun_l19_n624(x)
+ if (x < 1)
+ fun_l20_n331(x)
+ else
+ fun_l20_n473(x)
+ end
+end
+
+def fun_l19_n625(x)
+ if (x < 1)
+ fun_l20_n118(x)
+ else
+ fun_l20_n392(x)
+ end
+end
+
+def fun_l19_n626(x)
+ if (x < 1)
+ fun_l20_n836(x)
+ else
+ fun_l20_n988(x)
+ end
+end
+
+def fun_l19_n627(x)
+ if (x < 1)
+ fun_l20_n641(x)
+ else
+ fun_l20_n372(x)
+ end
+end
+
+def fun_l19_n628(x)
+ if (x < 1)
+ fun_l20_n377(x)
+ else
+ fun_l20_n780(x)
+ end
+end
+
+def fun_l19_n629(x)
+ if (x < 1)
+ fun_l20_n180(x)
+ else
+ fun_l20_n670(x)
+ end
+end
+
+def fun_l19_n630(x)
+ if (x < 1)
+ fun_l20_n985(x)
+ else
+ fun_l20_n613(x)
+ end
+end
+
+def fun_l19_n631(x)
+ if (x < 1)
+ fun_l20_n149(x)
+ else
+ fun_l20_n754(x)
+ end
+end
+
+def fun_l19_n632(x)
+ if (x < 1)
+ fun_l20_n967(x)
+ else
+ fun_l20_n940(x)
+ end
+end
+
+def fun_l19_n633(x)
+ if (x < 1)
+ fun_l20_n91(x)
+ else
+ fun_l20_n772(x)
+ end
+end
+
+def fun_l19_n634(x)
+ if (x < 1)
+ fun_l20_n637(x)
+ else
+ fun_l20_n296(x)
+ end
+end
+
+def fun_l19_n635(x)
+ if (x < 1)
+ fun_l20_n50(x)
+ else
+ fun_l20_n314(x)
+ end
+end
+
+def fun_l19_n636(x)
+ if (x < 1)
+ fun_l20_n367(x)
+ else
+ fun_l20_n849(x)
+ end
+end
+
+def fun_l19_n637(x)
+ if (x < 1)
+ fun_l20_n229(x)
+ else
+ fun_l20_n550(x)
+ end
+end
+
+def fun_l19_n638(x)
+ if (x < 1)
+ fun_l20_n680(x)
+ else
+ fun_l20_n783(x)
+ end
+end
+
+def fun_l19_n639(x)
+ if (x < 1)
+ fun_l20_n879(x)
+ else
+ fun_l20_n264(x)
+ end
+end
+
+def fun_l19_n640(x)
+ if (x < 1)
+ fun_l20_n143(x)
+ else
+ fun_l20_n455(x)
+ end
+end
+
+def fun_l19_n641(x)
+ if (x < 1)
+ fun_l20_n191(x)
+ else
+ fun_l20_n110(x)
+ end
+end
+
+def fun_l19_n642(x)
+ if (x < 1)
+ fun_l20_n782(x)
+ else
+ fun_l20_n43(x)
+ end
+end
+
+def fun_l19_n643(x)
+ if (x < 1)
+ fun_l20_n320(x)
+ else
+ fun_l20_n376(x)
+ end
+end
+
+def fun_l19_n644(x)
+ if (x < 1)
+ fun_l20_n554(x)
+ else
+ fun_l20_n667(x)
+ end
+end
+
+def fun_l19_n645(x)
+ if (x < 1)
+ fun_l20_n29(x)
+ else
+ fun_l20_n938(x)
+ end
+end
+
+def fun_l19_n646(x)
+ if (x < 1)
+ fun_l20_n789(x)
+ else
+ fun_l20_n907(x)
+ end
+end
+
+def fun_l19_n647(x)
+ if (x < 1)
+ fun_l20_n859(x)
+ else
+ fun_l20_n138(x)
+ end
+end
+
+def fun_l19_n648(x)
+ if (x < 1)
+ fun_l20_n373(x)
+ else
+ fun_l20_n843(x)
+ end
+end
+
+def fun_l19_n649(x)
+ if (x < 1)
+ fun_l20_n50(x)
+ else
+ fun_l20_n982(x)
+ end
+end
+
+def fun_l19_n650(x)
+ if (x < 1)
+ fun_l20_n622(x)
+ else
+ fun_l20_n368(x)
+ end
+end
+
+def fun_l19_n651(x)
+ if (x < 1)
+ fun_l20_n231(x)
+ else
+ fun_l20_n523(x)
+ end
+end
+
+def fun_l19_n652(x)
+ if (x < 1)
+ fun_l20_n233(x)
+ else
+ fun_l20_n963(x)
+ end
+end
+
+def fun_l19_n653(x)
+ if (x < 1)
+ fun_l20_n363(x)
+ else
+ fun_l20_n177(x)
+ end
+end
+
+def fun_l19_n654(x)
+ if (x < 1)
+ fun_l20_n952(x)
+ else
+ fun_l20_n96(x)
+ end
+end
+
+def fun_l19_n655(x)
+ if (x < 1)
+ fun_l20_n98(x)
+ else
+ fun_l20_n93(x)
+ end
+end
+
+def fun_l19_n656(x)
+ if (x < 1)
+ fun_l20_n200(x)
+ else
+ fun_l20_n137(x)
+ end
+end
+
+def fun_l19_n657(x)
+ if (x < 1)
+ fun_l20_n485(x)
+ else
+ fun_l20_n45(x)
+ end
+end
+
+def fun_l19_n658(x)
+ if (x < 1)
+ fun_l20_n234(x)
+ else
+ fun_l20_n366(x)
+ end
+end
+
+def fun_l19_n659(x)
+ if (x < 1)
+ fun_l20_n120(x)
+ else
+ fun_l20_n850(x)
+ end
+end
+
+def fun_l19_n660(x)
+ if (x < 1)
+ fun_l20_n932(x)
+ else
+ fun_l20_n551(x)
+ end
+end
+
+def fun_l19_n661(x)
+ if (x < 1)
+ fun_l20_n952(x)
+ else
+ fun_l20_n178(x)
+ end
+end
+
+def fun_l19_n662(x)
+ if (x < 1)
+ fun_l20_n761(x)
+ else
+ fun_l20_n2(x)
+ end
+end
+
+def fun_l19_n663(x)
+ if (x < 1)
+ fun_l20_n674(x)
+ else
+ fun_l20_n698(x)
+ end
+end
+
+def fun_l19_n664(x)
+ if (x < 1)
+ fun_l20_n669(x)
+ else
+ fun_l20_n563(x)
+ end
+end
+
+def fun_l19_n665(x)
+ if (x < 1)
+ fun_l20_n106(x)
+ else
+ fun_l20_n442(x)
+ end
+end
+
+def fun_l19_n666(x)
+ if (x < 1)
+ fun_l20_n476(x)
+ else
+ fun_l20_n620(x)
+ end
+end
+
+def fun_l19_n667(x)
+ if (x < 1)
+ fun_l20_n813(x)
+ else
+ fun_l20_n501(x)
+ end
+end
+
+def fun_l19_n668(x)
+ if (x < 1)
+ fun_l20_n773(x)
+ else
+ fun_l20_n485(x)
+ end
+end
+
+def fun_l19_n669(x)
+ if (x < 1)
+ fun_l20_n533(x)
+ else
+ fun_l20_n801(x)
+ end
+end
+
+def fun_l19_n670(x)
+ if (x < 1)
+ fun_l20_n64(x)
+ else
+ fun_l20_n872(x)
+ end
+end
+
+def fun_l19_n671(x)
+ if (x < 1)
+ fun_l20_n770(x)
+ else
+ fun_l20_n101(x)
+ end
+end
+
+def fun_l19_n672(x)
+ if (x < 1)
+ fun_l20_n22(x)
+ else
+ fun_l20_n644(x)
+ end
+end
+
+def fun_l19_n673(x)
+ if (x < 1)
+ fun_l20_n634(x)
+ else
+ fun_l20_n955(x)
+ end
+end
+
+def fun_l19_n674(x)
+ if (x < 1)
+ fun_l20_n976(x)
+ else
+ fun_l20_n665(x)
+ end
+end
+
+def fun_l19_n675(x)
+ if (x < 1)
+ fun_l20_n988(x)
+ else
+ fun_l20_n793(x)
+ end
+end
+
+def fun_l19_n676(x)
+ if (x < 1)
+ fun_l20_n235(x)
+ else
+ fun_l20_n833(x)
+ end
+end
+
+def fun_l19_n677(x)
+ if (x < 1)
+ fun_l20_n604(x)
+ else
+ fun_l20_n797(x)
+ end
+end
+
+def fun_l19_n678(x)
+ if (x < 1)
+ fun_l20_n622(x)
+ else
+ fun_l20_n896(x)
+ end
+end
+
+def fun_l19_n679(x)
+ if (x < 1)
+ fun_l20_n190(x)
+ else
+ fun_l20_n281(x)
+ end
+end
+
+def fun_l19_n680(x)
+ if (x < 1)
+ fun_l20_n325(x)
+ else
+ fun_l20_n669(x)
+ end
+end
+
+def fun_l19_n681(x)
+ if (x < 1)
+ fun_l20_n898(x)
+ else
+ fun_l20_n352(x)
+ end
+end
+
+def fun_l19_n682(x)
+ if (x < 1)
+ fun_l20_n820(x)
+ else
+ fun_l20_n117(x)
+ end
+end
+
+def fun_l19_n683(x)
+ if (x < 1)
+ fun_l20_n148(x)
+ else
+ fun_l20_n842(x)
+ end
+end
+
+def fun_l19_n684(x)
+ if (x < 1)
+ fun_l20_n468(x)
+ else
+ fun_l20_n596(x)
+ end
+end
+
+def fun_l19_n685(x)
+ if (x < 1)
+ fun_l20_n285(x)
+ else
+ fun_l20_n730(x)
+ end
+end
+
+def fun_l19_n686(x)
+ if (x < 1)
+ fun_l20_n426(x)
+ else
+ fun_l20_n657(x)
+ end
+end
+
+def fun_l19_n687(x)
+ if (x < 1)
+ fun_l20_n874(x)
+ else
+ fun_l20_n867(x)
+ end
+end
+
+def fun_l19_n688(x)
+ if (x < 1)
+ fun_l20_n451(x)
+ else
+ fun_l20_n846(x)
+ end
+end
+
+def fun_l19_n689(x)
+ if (x < 1)
+ fun_l20_n425(x)
+ else
+ fun_l20_n796(x)
+ end
+end
+
+def fun_l19_n690(x)
+ if (x < 1)
+ fun_l20_n37(x)
+ else
+ fun_l20_n301(x)
+ end
+end
+
+def fun_l19_n691(x)
+ if (x < 1)
+ fun_l20_n886(x)
+ else
+ fun_l20_n513(x)
+ end
+end
+
+def fun_l19_n692(x)
+ if (x < 1)
+ fun_l20_n426(x)
+ else
+ fun_l20_n46(x)
+ end
+end
+
+def fun_l19_n693(x)
+ if (x < 1)
+ fun_l20_n622(x)
+ else
+ fun_l20_n738(x)
+ end
+end
+
+def fun_l19_n694(x)
+ if (x < 1)
+ fun_l20_n530(x)
+ else
+ fun_l20_n981(x)
+ end
+end
+
+def fun_l19_n695(x)
+ if (x < 1)
+ fun_l20_n568(x)
+ else
+ fun_l20_n934(x)
+ end
+end
+
+def fun_l19_n696(x)
+ if (x < 1)
+ fun_l20_n974(x)
+ else
+ fun_l20_n585(x)
+ end
+end
+
+def fun_l19_n697(x)
+ if (x < 1)
+ fun_l20_n780(x)
+ else
+ fun_l20_n408(x)
+ end
+end
+
+def fun_l19_n698(x)
+ if (x < 1)
+ fun_l20_n373(x)
+ else
+ fun_l20_n163(x)
+ end
+end
+
+def fun_l19_n699(x)
+ if (x < 1)
+ fun_l20_n745(x)
+ else
+ fun_l20_n4(x)
+ end
+end
+
+def fun_l19_n700(x)
+ if (x < 1)
+ fun_l20_n307(x)
+ else
+ fun_l20_n172(x)
+ end
+end
+
+def fun_l19_n701(x)
+ if (x < 1)
+ fun_l20_n342(x)
+ else
+ fun_l20_n381(x)
+ end
+end
+
+def fun_l19_n702(x)
+ if (x < 1)
+ fun_l20_n67(x)
+ else
+ fun_l20_n841(x)
+ end
+end
+
+def fun_l19_n703(x)
+ if (x < 1)
+ fun_l20_n697(x)
+ else
+ fun_l20_n597(x)
+ end
+end
+
+def fun_l19_n704(x)
+ if (x < 1)
+ fun_l20_n809(x)
+ else
+ fun_l20_n306(x)
+ end
+end
+
+def fun_l19_n705(x)
+ if (x < 1)
+ fun_l20_n575(x)
+ else
+ fun_l20_n401(x)
+ end
+end
+
+def fun_l19_n706(x)
+ if (x < 1)
+ fun_l20_n651(x)
+ else
+ fun_l20_n552(x)
+ end
+end
+
+def fun_l19_n707(x)
+ if (x < 1)
+ fun_l20_n644(x)
+ else
+ fun_l20_n697(x)
+ end
+end
+
+def fun_l19_n708(x)
+ if (x < 1)
+ fun_l20_n572(x)
+ else
+ fun_l20_n86(x)
+ end
+end
+
+def fun_l19_n709(x)
+ if (x < 1)
+ fun_l20_n239(x)
+ else
+ fun_l20_n18(x)
+ end
+end
+
+def fun_l19_n710(x)
+ if (x < 1)
+ fun_l20_n48(x)
+ else
+ fun_l20_n822(x)
+ end
+end
+
+def fun_l19_n711(x)
+ if (x < 1)
+ fun_l20_n126(x)
+ else
+ fun_l20_n186(x)
+ end
+end
+
+def fun_l19_n712(x)
+ if (x < 1)
+ fun_l20_n552(x)
+ else
+ fun_l20_n901(x)
+ end
+end
+
+def fun_l19_n713(x)
+ if (x < 1)
+ fun_l20_n993(x)
+ else
+ fun_l20_n313(x)
+ end
+end
+
+def fun_l19_n714(x)
+ if (x < 1)
+ fun_l20_n918(x)
+ else
+ fun_l20_n718(x)
+ end
+end
+
+def fun_l19_n715(x)
+ if (x < 1)
+ fun_l20_n442(x)
+ else
+ fun_l20_n652(x)
+ end
+end
+
+def fun_l19_n716(x)
+ if (x < 1)
+ fun_l20_n624(x)
+ else
+ fun_l20_n492(x)
+ end
+end
+
+def fun_l19_n717(x)
+ if (x < 1)
+ fun_l20_n585(x)
+ else
+ fun_l20_n980(x)
+ end
+end
+
+def fun_l19_n718(x)
+ if (x < 1)
+ fun_l20_n159(x)
+ else
+ fun_l20_n327(x)
+ end
+end
+
+def fun_l19_n719(x)
+ if (x < 1)
+ fun_l20_n867(x)
+ else
+ fun_l20_n239(x)
+ end
+end
+
+def fun_l19_n720(x)
+ if (x < 1)
+ fun_l20_n551(x)
+ else
+ fun_l20_n123(x)
+ end
+end
+
+def fun_l19_n721(x)
+ if (x < 1)
+ fun_l20_n794(x)
+ else
+ fun_l20_n1(x)
+ end
+end
+
+def fun_l19_n722(x)
+ if (x < 1)
+ fun_l20_n193(x)
+ else
+ fun_l20_n847(x)
+ end
+end
+
+def fun_l19_n723(x)
+ if (x < 1)
+ fun_l20_n560(x)
+ else
+ fun_l20_n163(x)
+ end
+end
+
+def fun_l19_n724(x)
+ if (x < 1)
+ fun_l20_n338(x)
+ else
+ fun_l20_n411(x)
+ end
+end
+
+def fun_l19_n725(x)
+ if (x < 1)
+ fun_l20_n227(x)
+ else
+ fun_l20_n437(x)
+ end
+end
+
+def fun_l19_n726(x)
+ if (x < 1)
+ fun_l20_n691(x)
+ else
+ fun_l20_n821(x)
+ end
+end
+
+def fun_l19_n727(x)
+ if (x < 1)
+ fun_l20_n578(x)
+ else
+ fun_l20_n589(x)
+ end
+end
+
+def fun_l19_n728(x)
+ if (x < 1)
+ fun_l20_n990(x)
+ else
+ fun_l20_n164(x)
+ end
+end
+
+def fun_l19_n729(x)
+ if (x < 1)
+ fun_l20_n620(x)
+ else
+ fun_l20_n736(x)
+ end
+end
+
+def fun_l19_n730(x)
+ if (x < 1)
+ fun_l20_n980(x)
+ else
+ fun_l20_n345(x)
+ end
+end
+
+def fun_l19_n731(x)
+ if (x < 1)
+ fun_l20_n302(x)
+ else
+ fun_l20_n75(x)
+ end
+end
+
+def fun_l19_n732(x)
+ if (x < 1)
+ fun_l20_n684(x)
+ else
+ fun_l20_n2(x)
+ end
+end
+
+def fun_l19_n733(x)
+ if (x < 1)
+ fun_l20_n11(x)
+ else
+ fun_l20_n503(x)
+ end
+end
+
+def fun_l19_n734(x)
+ if (x < 1)
+ fun_l20_n719(x)
+ else
+ fun_l20_n745(x)
+ end
+end
+
+def fun_l19_n735(x)
+ if (x < 1)
+ fun_l20_n74(x)
+ else
+ fun_l20_n413(x)
+ end
+end
+
+def fun_l19_n736(x)
+ if (x < 1)
+ fun_l20_n858(x)
+ else
+ fun_l20_n224(x)
+ end
+end
+
+def fun_l19_n737(x)
+ if (x < 1)
+ fun_l20_n372(x)
+ else
+ fun_l20_n1(x)
+ end
+end
+
+def fun_l19_n738(x)
+ if (x < 1)
+ fun_l20_n274(x)
+ else
+ fun_l20_n967(x)
+ end
+end
+
+def fun_l19_n739(x)
+ if (x < 1)
+ fun_l20_n191(x)
+ else
+ fun_l20_n984(x)
+ end
+end
+
+def fun_l19_n740(x)
+ if (x < 1)
+ fun_l20_n646(x)
+ else
+ fun_l20_n279(x)
+ end
+end
+
+def fun_l19_n741(x)
+ if (x < 1)
+ fun_l20_n55(x)
+ else
+ fun_l20_n947(x)
+ end
+end
+
+def fun_l19_n742(x)
+ if (x < 1)
+ fun_l20_n306(x)
+ else
+ fun_l20_n798(x)
+ end
+end
+
+def fun_l19_n743(x)
+ if (x < 1)
+ fun_l20_n571(x)
+ else
+ fun_l20_n905(x)
+ end
+end
+
+def fun_l19_n744(x)
+ if (x < 1)
+ fun_l20_n270(x)
+ else
+ fun_l20_n290(x)
+ end
+end
+
+def fun_l19_n745(x)
+ if (x < 1)
+ fun_l20_n39(x)
+ else
+ fun_l20_n983(x)
+ end
+end
+
+def fun_l19_n746(x)
+ if (x < 1)
+ fun_l20_n405(x)
+ else
+ fun_l20_n727(x)
+ end
+end
+
+def fun_l19_n747(x)
+ if (x < 1)
+ fun_l20_n424(x)
+ else
+ fun_l20_n597(x)
+ end
+end
+
+def fun_l19_n748(x)
+ if (x < 1)
+ fun_l20_n602(x)
+ else
+ fun_l20_n467(x)
+ end
+end
+
+def fun_l19_n749(x)
+ if (x < 1)
+ fun_l20_n859(x)
+ else
+ fun_l20_n76(x)
+ end
+end
+
+def fun_l19_n750(x)
+ if (x < 1)
+ fun_l20_n201(x)
+ else
+ fun_l20_n948(x)
+ end
+end
+
+def fun_l19_n751(x)
+ if (x < 1)
+ fun_l20_n998(x)
+ else
+ fun_l20_n425(x)
+ end
+end
+
+def fun_l19_n752(x)
+ if (x < 1)
+ fun_l20_n352(x)
+ else
+ fun_l20_n762(x)
+ end
+end
+
+def fun_l19_n753(x)
+ if (x < 1)
+ fun_l20_n996(x)
+ else
+ fun_l20_n136(x)
+ end
+end
+
+def fun_l19_n754(x)
+ if (x < 1)
+ fun_l20_n462(x)
+ else
+ fun_l20_n544(x)
+ end
+end
+
+def fun_l19_n755(x)
+ if (x < 1)
+ fun_l20_n126(x)
+ else
+ fun_l20_n857(x)
+ end
+end
+
+def fun_l19_n756(x)
+ if (x < 1)
+ fun_l20_n695(x)
+ else
+ fun_l20_n444(x)
+ end
+end
+
+def fun_l19_n757(x)
+ if (x < 1)
+ fun_l20_n694(x)
+ else
+ fun_l20_n718(x)
+ end
+end
+
+def fun_l19_n758(x)
+ if (x < 1)
+ fun_l20_n308(x)
+ else
+ fun_l20_n867(x)
+ end
+end
+
+def fun_l19_n759(x)
+ if (x < 1)
+ fun_l20_n224(x)
+ else
+ fun_l20_n739(x)
+ end
+end
+
+def fun_l19_n760(x)
+ if (x < 1)
+ fun_l20_n286(x)
+ else
+ fun_l20_n660(x)
+ end
+end
+
+def fun_l19_n761(x)
+ if (x < 1)
+ fun_l20_n486(x)
+ else
+ fun_l20_n614(x)
+ end
+end
+
+def fun_l19_n762(x)
+ if (x < 1)
+ fun_l20_n234(x)
+ else
+ fun_l20_n812(x)
+ end
+end
+
+def fun_l19_n763(x)
+ if (x < 1)
+ fun_l20_n663(x)
+ else
+ fun_l20_n649(x)
+ end
+end
+
+def fun_l19_n764(x)
+ if (x < 1)
+ fun_l20_n815(x)
+ else
+ fun_l20_n436(x)
+ end
+end
+
+def fun_l19_n765(x)
+ if (x < 1)
+ fun_l20_n330(x)
+ else
+ fun_l20_n350(x)
+ end
+end
+
+def fun_l19_n766(x)
+ if (x < 1)
+ fun_l20_n532(x)
+ else
+ fun_l20_n676(x)
+ end
+end
+
+def fun_l19_n767(x)
+ if (x < 1)
+ fun_l20_n74(x)
+ else
+ fun_l20_n182(x)
+ end
+end
+
+def fun_l19_n768(x)
+ if (x < 1)
+ fun_l20_n432(x)
+ else
+ fun_l20_n912(x)
+ end
+end
+
+def fun_l19_n769(x)
+ if (x < 1)
+ fun_l20_n413(x)
+ else
+ fun_l20_n315(x)
+ end
+end
+
+def fun_l19_n770(x)
+ if (x < 1)
+ fun_l20_n457(x)
+ else
+ fun_l20_n917(x)
+ end
+end
+
+def fun_l19_n771(x)
+ if (x < 1)
+ fun_l20_n435(x)
+ else
+ fun_l20_n768(x)
+ end
+end
+
+def fun_l19_n772(x)
+ if (x < 1)
+ fun_l20_n994(x)
+ else
+ fun_l20_n865(x)
+ end
+end
+
+def fun_l19_n773(x)
+ if (x < 1)
+ fun_l20_n425(x)
+ else
+ fun_l20_n347(x)
+ end
+end
+
+def fun_l19_n774(x)
+ if (x < 1)
+ fun_l20_n405(x)
+ else
+ fun_l20_n1(x)
+ end
+end
+
+def fun_l19_n775(x)
+ if (x < 1)
+ fun_l20_n460(x)
+ else
+ fun_l20_n417(x)
+ end
+end
+
+def fun_l19_n776(x)
+ if (x < 1)
+ fun_l20_n539(x)
+ else
+ fun_l20_n825(x)
+ end
+end
+
+def fun_l19_n777(x)
+ if (x < 1)
+ fun_l20_n180(x)
+ else
+ fun_l20_n613(x)
+ end
+end
+
+def fun_l19_n778(x)
+ if (x < 1)
+ fun_l20_n452(x)
+ else
+ fun_l20_n717(x)
+ end
+end
+
+def fun_l19_n779(x)
+ if (x < 1)
+ fun_l20_n265(x)
+ else
+ fun_l20_n802(x)
+ end
+end
+
+def fun_l19_n780(x)
+ if (x < 1)
+ fun_l20_n941(x)
+ else
+ fun_l20_n939(x)
+ end
+end
+
+def fun_l19_n781(x)
+ if (x < 1)
+ fun_l20_n777(x)
+ else
+ fun_l20_n796(x)
+ end
+end
+
+def fun_l19_n782(x)
+ if (x < 1)
+ fun_l20_n924(x)
+ else
+ fun_l20_n442(x)
+ end
+end
+
+def fun_l19_n783(x)
+ if (x < 1)
+ fun_l20_n901(x)
+ else
+ fun_l20_n817(x)
+ end
+end
+
+def fun_l19_n784(x)
+ if (x < 1)
+ fun_l20_n101(x)
+ else
+ fun_l20_n983(x)
+ end
+end
+
+def fun_l19_n785(x)
+ if (x < 1)
+ fun_l20_n992(x)
+ else
+ fun_l20_n790(x)
+ end
+end
+
+def fun_l19_n786(x)
+ if (x < 1)
+ fun_l20_n426(x)
+ else
+ fun_l20_n337(x)
+ end
+end
+
+def fun_l19_n787(x)
+ if (x < 1)
+ fun_l20_n812(x)
+ else
+ fun_l20_n7(x)
+ end
+end
+
+def fun_l19_n788(x)
+ if (x < 1)
+ fun_l20_n768(x)
+ else
+ fun_l20_n25(x)
+ end
+end
+
+def fun_l19_n789(x)
+ if (x < 1)
+ fun_l20_n292(x)
+ else
+ fun_l20_n440(x)
+ end
+end
+
+def fun_l19_n790(x)
+ if (x < 1)
+ fun_l20_n855(x)
+ else
+ fun_l20_n191(x)
+ end
+end
+
+def fun_l19_n791(x)
+ if (x < 1)
+ fun_l20_n32(x)
+ else
+ fun_l20_n855(x)
+ end
+end
+
+def fun_l19_n792(x)
+ if (x < 1)
+ fun_l20_n920(x)
+ else
+ fun_l20_n198(x)
+ end
+end
+
+def fun_l19_n793(x)
+ if (x < 1)
+ fun_l20_n411(x)
+ else
+ fun_l20_n396(x)
+ end
+end
+
+def fun_l19_n794(x)
+ if (x < 1)
+ fun_l20_n977(x)
+ else
+ fun_l20_n712(x)
+ end
+end
+
+def fun_l19_n795(x)
+ if (x < 1)
+ fun_l20_n636(x)
+ else
+ fun_l20_n66(x)
+ end
+end
+
+def fun_l19_n796(x)
+ if (x < 1)
+ fun_l20_n137(x)
+ else
+ fun_l20_n656(x)
+ end
+end
+
+def fun_l19_n797(x)
+ if (x < 1)
+ fun_l20_n51(x)
+ else
+ fun_l20_n244(x)
+ end
+end
+
+def fun_l19_n798(x)
+ if (x < 1)
+ fun_l20_n426(x)
+ else
+ fun_l20_n418(x)
+ end
+end
+
+def fun_l19_n799(x)
+ if (x < 1)
+ fun_l20_n272(x)
+ else
+ fun_l20_n365(x)
+ end
+end
+
+def fun_l19_n800(x)
+ if (x < 1)
+ fun_l20_n361(x)
+ else
+ fun_l20_n952(x)
+ end
+end
+
+def fun_l19_n801(x)
+ if (x < 1)
+ fun_l20_n428(x)
+ else
+ fun_l20_n683(x)
+ end
+end
+
+def fun_l19_n802(x)
+ if (x < 1)
+ fun_l20_n54(x)
+ else
+ fun_l20_n86(x)
+ end
+end
+
+def fun_l19_n803(x)
+ if (x < 1)
+ fun_l20_n771(x)
+ else
+ fun_l20_n555(x)
+ end
+end
+
+def fun_l19_n804(x)
+ if (x < 1)
+ fun_l20_n498(x)
+ else
+ fun_l20_n744(x)
+ end
+end
+
+def fun_l19_n805(x)
+ if (x < 1)
+ fun_l20_n30(x)
+ else
+ fun_l20_n813(x)
+ end
+end
+
+def fun_l19_n806(x)
+ if (x < 1)
+ fun_l20_n96(x)
+ else
+ fun_l20_n295(x)
+ end
+end
+
+def fun_l19_n807(x)
+ if (x < 1)
+ fun_l20_n128(x)
+ else
+ fun_l20_n584(x)
+ end
+end
+
+def fun_l19_n808(x)
+ if (x < 1)
+ fun_l20_n818(x)
+ else
+ fun_l20_n396(x)
+ end
+end
+
+def fun_l19_n809(x)
+ if (x < 1)
+ fun_l20_n896(x)
+ else
+ fun_l20_n779(x)
+ end
+end
+
+def fun_l19_n810(x)
+ if (x < 1)
+ fun_l20_n40(x)
+ else
+ fun_l20_n638(x)
+ end
+end
+
+def fun_l19_n811(x)
+ if (x < 1)
+ fun_l20_n925(x)
+ else
+ fun_l20_n914(x)
+ end
+end
+
+def fun_l19_n812(x)
+ if (x < 1)
+ fun_l20_n217(x)
+ else
+ fun_l20_n833(x)
+ end
+end
+
+def fun_l19_n813(x)
+ if (x < 1)
+ fun_l20_n687(x)
+ else
+ fun_l20_n469(x)
+ end
+end
+
+def fun_l19_n814(x)
+ if (x < 1)
+ fun_l20_n709(x)
+ else
+ fun_l20_n196(x)
+ end
+end
+
+def fun_l19_n815(x)
+ if (x < 1)
+ fun_l20_n633(x)
+ else
+ fun_l20_n622(x)
+ end
+end
+
+def fun_l19_n816(x)
+ if (x < 1)
+ fun_l20_n976(x)
+ else
+ fun_l20_n691(x)
+ end
+end
+
+def fun_l19_n817(x)
+ if (x < 1)
+ fun_l20_n260(x)
+ else
+ fun_l20_n592(x)
+ end
+end
+
+def fun_l19_n818(x)
+ if (x < 1)
+ fun_l20_n893(x)
+ else
+ fun_l20_n353(x)
+ end
+end
+
+def fun_l19_n819(x)
+ if (x < 1)
+ fun_l20_n824(x)
+ else
+ fun_l20_n875(x)
+ end
+end
+
+def fun_l19_n820(x)
+ if (x < 1)
+ fun_l20_n605(x)
+ else
+ fun_l20_n797(x)
+ end
+end
+
+def fun_l19_n821(x)
+ if (x < 1)
+ fun_l20_n990(x)
+ else
+ fun_l20_n272(x)
+ end
+end
+
+def fun_l19_n822(x)
+ if (x < 1)
+ fun_l20_n819(x)
+ else
+ fun_l20_n313(x)
+ end
+end
+
+def fun_l19_n823(x)
+ if (x < 1)
+ fun_l20_n838(x)
+ else
+ fun_l20_n513(x)
+ end
+end
+
+def fun_l19_n824(x)
+ if (x < 1)
+ fun_l20_n332(x)
+ else
+ fun_l20_n838(x)
+ end
+end
+
+def fun_l19_n825(x)
+ if (x < 1)
+ fun_l20_n994(x)
+ else
+ fun_l20_n641(x)
+ end
+end
+
+def fun_l19_n826(x)
+ if (x < 1)
+ fun_l20_n820(x)
+ else
+ fun_l20_n17(x)
+ end
+end
+
+def fun_l19_n827(x)
+ if (x < 1)
+ fun_l20_n645(x)
+ else
+ fun_l20_n587(x)
+ end
+end
+
+def fun_l19_n828(x)
+ if (x < 1)
+ fun_l20_n352(x)
+ else
+ fun_l20_n726(x)
+ end
+end
+
+def fun_l19_n829(x)
+ if (x < 1)
+ fun_l20_n33(x)
+ else
+ fun_l20_n803(x)
+ end
+end
+
+def fun_l19_n830(x)
+ if (x < 1)
+ fun_l20_n854(x)
+ else
+ fun_l20_n468(x)
+ end
+end
+
+def fun_l19_n831(x)
+ if (x < 1)
+ fun_l20_n149(x)
+ else
+ fun_l20_n529(x)
+ end
+end
+
+def fun_l19_n832(x)
+ if (x < 1)
+ fun_l20_n442(x)
+ else
+ fun_l20_n114(x)
+ end
+end
+
+def fun_l19_n833(x)
+ if (x < 1)
+ fun_l20_n986(x)
+ else
+ fun_l20_n778(x)
+ end
+end
+
+def fun_l19_n834(x)
+ if (x < 1)
+ fun_l20_n220(x)
+ else
+ fun_l20_n782(x)
+ end
+end
+
+def fun_l19_n835(x)
+ if (x < 1)
+ fun_l20_n330(x)
+ else
+ fun_l20_n361(x)
+ end
+end
+
+def fun_l19_n836(x)
+ if (x < 1)
+ fun_l20_n805(x)
+ else
+ fun_l20_n204(x)
+ end
+end
+
+def fun_l19_n837(x)
+ if (x < 1)
+ fun_l20_n534(x)
+ else
+ fun_l20_n970(x)
+ end
+end
+
+def fun_l19_n838(x)
+ if (x < 1)
+ fun_l20_n890(x)
+ else
+ fun_l20_n526(x)
+ end
+end
+
+def fun_l19_n839(x)
+ if (x < 1)
+ fun_l20_n511(x)
+ else
+ fun_l20_n743(x)
+ end
+end
+
+def fun_l19_n840(x)
+ if (x < 1)
+ fun_l20_n730(x)
+ else
+ fun_l20_n435(x)
+ end
+end
+
+def fun_l19_n841(x)
+ if (x < 1)
+ fun_l20_n34(x)
+ else
+ fun_l20_n228(x)
+ end
+end
+
+def fun_l19_n842(x)
+ if (x < 1)
+ fun_l20_n170(x)
+ else
+ fun_l20_n162(x)
+ end
+end
+
+def fun_l19_n843(x)
+ if (x < 1)
+ fun_l20_n987(x)
+ else
+ fun_l20_n631(x)
+ end
+end
+
+def fun_l19_n844(x)
+ if (x < 1)
+ fun_l20_n193(x)
+ else
+ fun_l20_n48(x)
+ end
+end
+
+def fun_l19_n845(x)
+ if (x < 1)
+ fun_l20_n479(x)
+ else
+ fun_l20_n295(x)
+ end
+end
+
+def fun_l19_n846(x)
+ if (x < 1)
+ fun_l20_n545(x)
+ else
+ fun_l20_n474(x)
+ end
+end
+
+def fun_l19_n847(x)
+ if (x < 1)
+ fun_l20_n155(x)
+ else
+ fun_l20_n222(x)
+ end
+end
+
+def fun_l19_n848(x)
+ if (x < 1)
+ fun_l20_n641(x)
+ else
+ fun_l20_n151(x)
+ end
+end
+
+def fun_l19_n849(x)
+ if (x < 1)
+ fun_l20_n191(x)
+ else
+ fun_l20_n563(x)
+ end
+end
+
+def fun_l19_n850(x)
+ if (x < 1)
+ fun_l20_n891(x)
+ else
+ fun_l20_n247(x)
+ end
+end
+
+def fun_l19_n851(x)
+ if (x < 1)
+ fun_l20_n987(x)
+ else
+ fun_l20_n296(x)
+ end
+end
+
+def fun_l19_n852(x)
+ if (x < 1)
+ fun_l20_n86(x)
+ else
+ fun_l20_n346(x)
+ end
+end
+
+def fun_l19_n853(x)
+ if (x < 1)
+ fun_l20_n93(x)
+ else
+ fun_l20_n198(x)
+ end
+end
+
+def fun_l19_n854(x)
+ if (x < 1)
+ fun_l20_n767(x)
+ else
+ fun_l20_n759(x)
+ end
+end
+
+def fun_l19_n855(x)
+ if (x < 1)
+ fun_l20_n571(x)
+ else
+ fun_l20_n456(x)
+ end
+end
+
+def fun_l19_n856(x)
+ if (x < 1)
+ fun_l20_n722(x)
+ else
+ fun_l20_n603(x)
+ end
+end
+
+def fun_l19_n857(x)
+ if (x < 1)
+ fun_l20_n940(x)
+ else
+ fun_l20_n163(x)
+ end
+end
+
+def fun_l19_n858(x)
+ if (x < 1)
+ fun_l20_n973(x)
+ else
+ fun_l20_n598(x)
+ end
+end
+
+def fun_l19_n859(x)
+ if (x < 1)
+ fun_l20_n79(x)
+ else
+ fun_l20_n401(x)
+ end
+end
+
+def fun_l19_n860(x)
+ if (x < 1)
+ fun_l20_n234(x)
+ else
+ fun_l20_n769(x)
+ end
+end
+
+def fun_l19_n861(x)
+ if (x < 1)
+ fun_l20_n292(x)
+ else
+ fun_l20_n526(x)
+ end
+end
+
+def fun_l19_n862(x)
+ if (x < 1)
+ fun_l20_n554(x)
+ else
+ fun_l20_n468(x)
+ end
+end
+
+def fun_l19_n863(x)
+ if (x < 1)
+ fun_l20_n386(x)
+ else
+ fun_l20_n946(x)
+ end
+end
+
+def fun_l19_n864(x)
+ if (x < 1)
+ fun_l20_n227(x)
+ else
+ fun_l20_n287(x)
+ end
+end
+
+def fun_l19_n865(x)
+ if (x < 1)
+ fun_l20_n485(x)
+ else
+ fun_l20_n276(x)
+ end
+end
+
+def fun_l19_n866(x)
+ if (x < 1)
+ fun_l20_n38(x)
+ else
+ fun_l20_n329(x)
+ end
+end
+
+def fun_l19_n867(x)
+ if (x < 1)
+ fun_l20_n1(x)
+ else
+ fun_l20_n985(x)
+ end
+end
+
+def fun_l19_n868(x)
+ if (x < 1)
+ fun_l20_n13(x)
+ else
+ fun_l20_n823(x)
+ end
+end
+
+def fun_l19_n869(x)
+ if (x < 1)
+ fun_l20_n834(x)
+ else
+ fun_l20_n959(x)
+ end
+end
+
+def fun_l19_n870(x)
+ if (x < 1)
+ fun_l20_n177(x)
+ else
+ fun_l20_n232(x)
+ end
+end
+
+def fun_l19_n871(x)
+ if (x < 1)
+ fun_l20_n56(x)
+ else
+ fun_l20_n712(x)
+ end
+end
+
+def fun_l19_n872(x)
+ if (x < 1)
+ fun_l20_n69(x)
+ else
+ fun_l20_n850(x)
+ end
+end
+
+def fun_l19_n873(x)
+ if (x < 1)
+ fun_l20_n558(x)
+ else
+ fun_l20_n877(x)
+ end
+end
+
+def fun_l19_n874(x)
+ if (x < 1)
+ fun_l20_n34(x)
+ else
+ fun_l20_n540(x)
+ end
+end
+
+def fun_l19_n875(x)
+ if (x < 1)
+ fun_l20_n392(x)
+ else
+ fun_l20_n904(x)
+ end
+end
+
+def fun_l19_n876(x)
+ if (x < 1)
+ fun_l20_n99(x)
+ else
+ fun_l20_n691(x)
+ end
+end
+
+def fun_l19_n877(x)
+ if (x < 1)
+ fun_l20_n799(x)
+ else
+ fun_l20_n982(x)
+ end
+end
+
+def fun_l19_n878(x)
+ if (x < 1)
+ fun_l20_n511(x)
+ else
+ fun_l20_n869(x)
+ end
+end
+
+def fun_l19_n879(x)
+ if (x < 1)
+ fun_l20_n65(x)
+ else
+ fun_l20_n318(x)
+ end
+end
+
+def fun_l19_n880(x)
+ if (x < 1)
+ fun_l20_n335(x)
+ else
+ fun_l20_n811(x)
+ end
+end
+
+def fun_l19_n881(x)
+ if (x < 1)
+ fun_l20_n165(x)
+ else
+ fun_l20_n870(x)
+ end
+end
+
+def fun_l19_n882(x)
+ if (x < 1)
+ fun_l20_n427(x)
+ else
+ fun_l20_n597(x)
+ end
+end
+
+def fun_l19_n883(x)
+ if (x < 1)
+ fun_l20_n319(x)
+ else
+ fun_l20_n503(x)
+ end
+end
+
+def fun_l19_n884(x)
+ if (x < 1)
+ fun_l20_n57(x)
+ else
+ fun_l20_n620(x)
+ end
+end
+
+def fun_l19_n885(x)
+ if (x < 1)
+ fun_l20_n489(x)
+ else
+ fun_l20_n359(x)
+ end
+end
+
+def fun_l19_n886(x)
+ if (x < 1)
+ fun_l20_n773(x)
+ else
+ fun_l20_n719(x)
+ end
+end
+
+def fun_l19_n887(x)
+ if (x < 1)
+ fun_l20_n969(x)
+ else
+ fun_l20_n32(x)
+ end
+end
+
+def fun_l19_n888(x)
+ if (x < 1)
+ fun_l20_n758(x)
+ else
+ fun_l20_n132(x)
+ end
+end
+
+def fun_l19_n889(x)
+ if (x < 1)
+ fun_l20_n130(x)
+ else
+ fun_l20_n886(x)
+ end
+end
+
+def fun_l19_n890(x)
+ if (x < 1)
+ fun_l20_n195(x)
+ else
+ fun_l20_n258(x)
+ end
+end
+
+def fun_l19_n891(x)
+ if (x < 1)
+ fun_l20_n747(x)
+ else
+ fun_l20_n967(x)
+ end
+end
+
+def fun_l19_n892(x)
+ if (x < 1)
+ fun_l20_n403(x)
+ else
+ fun_l20_n314(x)
+ end
+end
+
+def fun_l19_n893(x)
+ if (x < 1)
+ fun_l20_n927(x)
+ else
+ fun_l20_n923(x)
+ end
+end
+
+def fun_l19_n894(x)
+ if (x < 1)
+ fun_l20_n894(x)
+ else
+ fun_l20_n318(x)
+ end
+end
+
+def fun_l19_n895(x)
+ if (x < 1)
+ fun_l20_n825(x)
+ else
+ fun_l20_n574(x)
+ end
+end
+
+def fun_l19_n896(x)
+ if (x < 1)
+ fun_l20_n436(x)
+ else
+ fun_l20_n321(x)
+ end
+end
+
+def fun_l19_n897(x)
+ if (x < 1)
+ fun_l20_n317(x)
+ else
+ fun_l20_n312(x)
+ end
+end
+
+def fun_l19_n898(x)
+ if (x < 1)
+ fun_l20_n219(x)
+ else
+ fun_l20_n362(x)
+ end
+end
+
+def fun_l19_n899(x)
+ if (x < 1)
+ fun_l20_n731(x)
+ else
+ fun_l20_n1(x)
+ end
+end
+
+def fun_l19_n900(x)
+ if (x < 1)
+ fun_l20_n804(x)
+ else
+ fun_l20_n629(x)
+ end
+end
+
+def fun_l19_n901(x)
+ if (x < 1)
+ fun_l20_n152(x)
+ else
+ fun_l20_n232(x)
+ end
+end
+
+def fun_l19_n902(x)
+ if (x < 1)
+ fun_l20_n104(x)
+ else
+ fun_l20_n579(x)
+ end
+end
+
+def fun_l19_n903(x)
+ if (x < 1)
+ fun_l20_n860(x)
+ else
+ fun_l20_n322(x)
+ end
+end
+
+def fun_l19_n904(x)
+ if (x < 1)
+ fun_l20_n55(x)
+ else
+ fun_l20_n70(x)
+ end
+end
+
+def fun_l19_n905(x)
+ if (x < 1)
+ fun_l20_n674(x)
+ else
+ fun_l20_n713(x)
+ end
+end
+
+def fun_l19_n906(x)
+ if (x < 1)
+ fun_l20_n957(x)
+ else
+ fun_l20_n962(x)
+ end
+end
+
+def fun_l19_n907(x)
+ if (x < 1)
+ fun_l20_n656(x)
+ else
+ fun_l20_n582(x)
+ end
+end
+
+def fun_l19_n908(x)
+ if (x < 1)
+ fun_l20_n3(x)
+ else
+ fun_l20_n323(x)
+ end
+end
+
+def fun_l19_n909(x)
+ if (x < 1)
+ fun_l20_n763(x)
+ else
+ fun_l20_n387(x)
+ end
+end
+
+def fun_l19_n910(x)
+ if (x < 1)
+ fun_l20_n434(x)
+ else
+ fun_l20_n113(x)
+ end
+end
+
+def fun_l19_n911(x)
+ if (x < 1)
+ fun_l20_n713(x)
+ else
+ fun_l20_n4(x)
+ end
+end
+
+def fun_l19_n912(x)
+ if (x < 1)
+ fun_l20_n313(x)
+ else
+ fun_l20_n776(x)
+ end
+end
+
+def fun_l19_n913(x)
+ if (x < 1)
+ fun_l20_n541(x)
+ else
+ fun_l20_n80(x)
+ end
+end
+
+def fun_l19_n914(x)
+ if (x < 1)
+ fun_l20_n131(x)
+ else
+ fun_l20_n982(x)
+ end
+end
+
+def fun_l19_n915(x)
+ if (x < 1)
+ fun_l20_n558(x)
+ else
+ fun_l20_n538(x)
+ end
+end
+
+def fun_l19_n916(x)
+ if (x < 1)
+ fun_l20_n715(x)
+ else
+ fun_l20_n401(x)
+ end
+end
+
+def fun_l19_n917(x)
+ if (x < 1)
+ fun_l20_n820(x)
+ else
+ fun_l20_n576(x)
+ end
+end
+
+def fun_l19_n918(x)
+ if (x < 1)
+ fun_l20_n602(x)
+ else
+ fun_l20_n158(x)
+ end
+end
+
+def fun_l19_n919(x)
+ if (x < 1)
+ fun_l20_n127(x)
+ else
+ fun_l20_n493(x)
+ end
+end
+
+def fun_l19_n920(x)
+ if (x < 1)
+ fun_l20_n719(x)
+ else
+ fun_l20_n895(x)
+ end
+end
+
+def fun_l19_n921(x)
+ if (x < 1)
+ fun_l20_n277(x)
+ else
+ fun_l20_n588(x)
+ end
+end
+
+def fun_l19_n922(x)
+ if (x < 1)
+ fun_l20_n479(x)
+ else
+ fun_l20_n799(x)
+ end
+end
+
+def fun_l19_n923(x)
+ if (x < 1)
+ fun_l20_n879(x)
+ else
+ fun_l20_n809(x)
+ end
+end
+
+def fun_l19_n924(x)
+ if (x < 1)
+ fun_l20_n574(x)
+ else
+ fun_l20_n756(x)
+ end
+end
+
+def fun_l19_n925(x)
+ if (x < 1)
+ fun_l20_n774(x)
+ else
+ fun_l20_n806(x)
+ end
+end
+
+def fun_l19_n926(x)
+ if (x < 1)
+ fun_l20_n804(x)
+ else
+ fun_l20_n87(x)
+ end
+end
+
+def fun_l19_n927(x)
+ if (x < 1)
+ fun_l20_n647(x)
+ else
+ fun_l20_n497(x)
+ end
+end
+
+def fun_l19_n928(x)
+ if (x < 1)
+ fun_l20_n134(x)
+ else
+ fun_l20_n690(x)
+ end
+end
+
+def fun_l19_n929(x)
+ if (x < 1)
+ fun_l20_n981(x)
+ else
+ fun_l20_n590(x)
+ end
+end
+
+def fun_l19_n930(x)
+ if (x < 1)
+ fun_l20_n393(x)
+ else
+ fun_l20_n585(x)
+ end
+end
+
+def fun_l19_n931(x)
+ if (x < 1)
+ fun_l20_n408(x)
+ else
+ fun_l20_n753(x)
+ end
+end
+
+def fun_l19_n932(x)
+ if (x < 1)
+ fun_l20_n133(x)
+ else
+ fun_l20_n289(x)
+ end
+end
+
+def fun_l19_n933(x)
+ if (x < 1)
+ fun_l20_n552(x)
+ else
+ fun_l20_n867(x)
+ end
+end
+
+def fun_l19_n934(x)
+ if (x < 1)
+ fun_l20_n232(x)
+ else
+ fun_l20_n134(x)
+ end
+end
+
+def fun_l19_n935(x)
+ if (x < 1)
+ fun_l20_n45(x)
+ else
+ fun_l20_n100(x)
+ end
+end
+
+def fun_l19_n936(x)
+ if (x < 1)
+ fun_l20_n263(x)
+ else
+ fun_l20_n686(x)
+ end
+end
+
+def fun_l19_n937(x)
+ if (x < 1)
+ fun_l20_n63(x)
+ else
+ fun_l20_n401(x)
+ end
+end
+
+def fun_l19_n938(x)
+ if (x < 1)
+ fun_l20_n564(x)
+ else
+ fun_l20_n265(x)
+ end
+end
+
+def fun_l19_n939(x)
+ if (x < 1)
+ fun_l20_n414(x)
+ else
+ fun_l20_n32(x)
+ end
+end
+
+def fun_l19_n940(x)
+ if (x < 1)
+ fun_l20_n686(x)
+ else
+ fun_l20_n116(x)
+ end
+end
+
+def fun_l19_n941(x)
+ if (x < 1)
+ fun_l20_n812(x)
+ else
+ fun_l20_n438(x)
+ end
+end
+
+def fun_l19_n942(x)
+ if (x < 1)
+ fun_l20_n365(x)
+ else
+ fun_l20_n95(x)
+ end
+end
+
+def fun_l19_n943(x)
+ if (x < 1)
+ fun_l20_n159(x)
+ else
+ fun_l20_n763(x)
+ end
+end
+
+def fun_l19_n944(x)
+ if (x < 1)
+ fun_l20_n844(x)
+ else
+ fun_l20_n958(x)
+ end
+end
+
+def fun_l19_n945(x)
+ if (x < 1)
+ fun_l20_n730(x)
+ else
+ fun_l20_n814(x)
+ end
+end
+
+def fun_l19_n946(x)
+ if (x < 1)
+ fun_l20_n963(x)
+ else
+ fun_l20_n2(x)
+ end
+end
+
+def fun_l19_n947(x)
+ if (x < 1)
+ fun_l20_n285(x)
+ else
+ fun_l20_n605(x)
+ end
+end
+
+def fun_l19_n948(x)
+ if (x < 1)
+ fun_l20_n869(x)
+ else
+ fun_l20_n409(x)
+ end
+end
+
+def fun_l19_n949(x)
+ if (x < 1)
+ fun_l20_n313(x)
+ else
+ fun_l20_n854(x)
+ end
+end
+
+def fun_l19_n950(x)
+ if (x < 1)
+ fun_l20_n802(x)
+ else
+ fun_l20_n411(x)
+ end
+end
+
+def fun_l19_n951(x)
+ if (x < 1)
+ fun_l20_n273(x)
+ else
+ fun_l20_n100(x)
+ end
+end
+
+def fun_l19_n952(x)
+ if (x < 1)
+ fun_l20_n283(x)
+ else
+ fun_l20_n253(x)
+ end
+end
+
+def fun_l19_n953(x)
+ if (x < 1)
+ fun_l20_n137(x)
+ else
+ fun_l20_n535(x)
+ end
+end
+
+def fun_l19_n954(x)
+ if (x < 1)
+ fun_l20_n504(x)
+ else
+ fun_l20_n849(x)
+ end
+end
+
+def fun_l19_n955(x)
+ if (x < 1)
+ fun_l20_n568(x)
+ else
+ fun_l20_n208(x)
+ end
+end
+
+def fun_l19_n956(x)
+ if (x < 1)
+ fun_l20_n775(x)
+ else
+ fun_l20_n781(x)
+ end
+end
+
+def fun_l19_n957(x)
+ if (x < 1)
+ fun_l20_n144(x)
+ else
+ fun_l20_n411(x)
+ end
+end
+
+def fun_l19_n958(x)
+ if (x < 1)
+ fun_l20_n791(x)
+ else
+ fun_l20_n720(x)
+ end
+end
+
+def fun_l19_n959(x)
+ if (x < 1)
+ fun_l20_n268(x)
+ else
+ fun_l20_n251(x)
+ end
+end
+
+def fun_l19_n960(x)
+ if (x < 1)
+ fun_l20_n661(x)
+ else
+ fun_l20_n114(x)
+ end
+end
+
+def fun_l19_n961(x)
+ if (x < 1)
+ fun_l20_n559(x)
+ else
+ fun_l20_n177(x)
+ end
+end
+
+def fun_l19_n962(x)
+ if (x < 1)
+ fun_l20_n536(x)
+ else
+ fun_l20_n671(x)
+ end
+end
+
+def fun_l19_n963(x)
+ if (x < 1)
+ fun_l20_n64(x)
+ else
+ fun_l20_n656(x)
+ end
+end
+
+def fun_l19_n964(x)
+ if (x < 1)
+ fun_l20_n618(x)
+ else
+ fun_l20_n837(x)
+ end
+end
+
+def fun_l19_n965(x)
+ if (x < 1)
+ fun_l20_n201(x)
+ else
+ fun_l20_n562(x)
+ end
+end
+
+def fun_l19_n966(x)
+ if (x < 1)
+ fun_l20_n562(x)
+ else
+ fun_l20_n632(x)
+ end
+end
+
+def fun_l19_n967(x)
+ if (x < 1)
+ fun_l20_n183(x)
+ else
+ fun_l20_n589(x)
+ end
+end
+
+def fun_l19_n968(x)
+ if (x < 1)
+ fun_l20_n971(x)
+ else
+ fun_l20_n619(x)
+ end
+end
+
+def fun_l19_n969(x)
+ if (x < 1)
+ fun_l20_n826(x)
+ else
+ fun_l20_n745(x)
+ end
+end
+
+def fun_l19_n970(x)
+ if (x < 1)
+ fun_l20_n140(x)
+ else
+ fun_l20_n370(x)
+ end
+end
+
+def fun_l19_n971(x)
+ if (x < 1)
+ fun_l20_n26(x)
+ else
+ fun_l20_n243(x)
+ end
+end
+
+def fun_l19_n972(x)
+ if (x < 1)
+ fun_l20_n375(x)
+ else
+ fun_l20_n6(x)
+ end
+end
+
+def fun_l19_n973(x)
+ if (x < 1)
+ fun_l20_n289(x)
+ else
+ fun_l20_n266(x)
+ end
+end
+
+def fun_l19_n974(x)
+ if (x < 1)
+ fun_l20_n932(x)
+ else
+ fun_l20_n602(x)
+ end
+end
+
+def fun_l19_n975(x)
+ if (x < 1)
+ fun_l20_n272(x)
+ else
+ fun_l20_n671(x)
+ end
+end
+
+def fun_l19_n976(x)
+ if (x < 1)
+ fun_l20_n653(x)
+ else
+ fun_l20_n201(x)
+ end
+end
+
+def fun_l19_n977(x)
+ if (x < 1)
+ fun_l20_n785(x)
+ else
+ fun_l20_n976(x)
+ end
+end
+
+def fun_l19_n978(x)
+ if (x < 1)
+ fun_l20_n212(x)
+ else
+ fun_l20_n601(x)
+ end
+end
+
+def fun_l19_n979(x)
+ if (x < 1)
+ fun_l20_n218(x)
+ else
+ fun_l20_n914(x)
+ end
+end
+
+def fun_l19_n980(x)
+ if (x < 1)
+ fun_l20_n109(x)
+ else
+ fun_l20_n147(x)
+ end
+end
+
+def fun_l19_n981(x)
+ if (x < 1)
+ fun_l20_n46(x)
+ else
+ fun_l20_n276(x)
+ end
+end
+
+def fun_l19_n982(x)
+ if (x < 1)
+ fun_l20_n727(x)
+ else
+ fun_l20_n545(x)
+ end
+end
+
+def fun_l19_n983(x)
+ if (x < 1)
+ fun_l20_n679(x)
+ else
+ fun_l20_n731(x)
+ end
+end
+
+def fun_l19_n984(x)
+ if (x < 1)
+ fun_l20_n291(x)
+ else
+ fun_l20_n294(x)
+ end
+end
+
+def fun_l19_n985(x)
+ if (x < 1)
+ fun_l20_n741(x)
+ else
+ fun_l20_n508(x)
+ end
+end
+
+def fun_l19_n986(x)
+ if (x < 1)
+ fun_l20_n417(x)
+ else
+ fun_l20_n169(x)
+ end
+end
+
+def fun_l19_n987(x)
+ if (x < 1)
+ fun_l20_n685(x)
+ else
+ fun_l20_n871(x)
+ end
+end
+
+def fun_l19_n988(x)
+ if (x < 1)
+ fun_l20_n386(x)
+ else
+ fun_l20_n616(x)
+ end
+end
+
+def fun_l19_n989(x)
+ if (x < 1)
+ fun_l20_n317(x)
+ else
+ fun_l20_n954(x)
+ end
+end
+
+def fun_l19_n990(x)
+ if (x < 1)
+ fun_l20_n954(x)
+ else
+ fun_l20_n974(x)
+ end
+end
+
+def fun_l19_n991(x)
+ if (x < 1)
+ fun_l20_n251(x)
+ else
+ fun_l20_n56(x)
+ end
+end
+
+def fun_l19_n992(x)
+ if (x < 1)
+ fun_l20_n775(x)
+ else
+ fun_l20_n175(x)
+ end
+end
+
+def fun_l19_n993(x)
+ if (x < 1)
+ fun_l20_n578(x)
+ else
+ fun_l20_n217(x)
+ end
+end
+
+def fun_l19_n994(x)
+ if (x < 1)
+ fun_l20_n483(x)
+ else
+ fun_l20_n279(x)
+ end
+end
+
+def fun_l19_n995(x)
+ if (x < 1)
+ fun_l20_n316(x)
+ else
+ fun_l20_n343(x)
+ end
+end
+
+def fun_l19_n996(x)
+ if (x < 1)
+ fun_l20_n618(x)
+ else
+ fun_l20_n995(x)
+ end
+end
+
+def fun_l19_n997(x)
+ if (x < 1)
+ fun_l20_n396(x)
+ else
+ fun_l20_n540(x)
+ end
+end
+
+def fun_l19_n998(x)
+ if (x < 1)
+ fun_l20_n184(x)
+ else
+ fun_l20_n380(x)
+ end
+end
+
+def fun_l19_n999(x)
+ if (x < 1)
+ fun_l20_n360(x)
+ else
+ fun_l20_n48(x)
+ end
+end
+
+def fun_l20_n0(x)
+ if (x < 1)
+ fun_l21_n609(x)
+ else
+ fun_l21_n305(x)
+ end
+end
+
+def fun_l20_n1(x)
+ if (x < 1)
+ fun_l21_n937(x)
+ else
+ fun_l21_n174(x)
+ end
+end
+
+def fun_l20_n2(x)
+ if (x < 1)
+ fun_l21_n939(x)
+ else
+ fun_l21_n174(x)
+ end
+end
+
+def fun_l20_n3(x)
+ if (x < 1)
+ fun_l21_n163(x)
+ else
+ fun_l21_n572(x)
+ end
+end
+
+def fun_l20_n4(x)
+ if (x < 1)
+ fun_l21_n43(x)
+ else
+ fun_l21_n384(x)
+ end
+end
+
+def fun_l20_n5(x)
+ if (x < 1)
+ fun_l21_n565(x)
+ else
+ fun_l21_n788(x)
+ end
+end
+
+def fun_l20_n6(x)
+ if (x < 1)
+ fun_l21_n539(x)
+ else
+ fun_l21_n806(x)
+ end
+end
+
+def fun_l20_n7(x)
+ if (x < 1)
+ fun_l21_n395(x)
+ else
+ fun_l21_n9(x)
+ end
+end
+
+def fun_l20_n8(x)
+ if (x < 1)
+ fun_l21_n231(x)
+ else
+ fun_l21_n788(x)
+ end
+end
+
+def fun_l20_n9(x)
+ if (x < 1)
+ fun_l21_n511(x)
+ else
+ fun_l21_n236(x)
+ end
+end
+
+def fun_l20_n10(x)
+ if (x < 1)
+ fun_l21_n141(x)
+ else
+ fun_l21_n34(x)
+ end
+end
+
+def fun_l20_n11(x)
+ if (x < 1)
+ fun_l21_n801(x)
+ else
+ fun_l21_n760(x)
+ end
+end
+
+def fun_l20_n12(x)
+ if (x < 1)
+ fun_l21_n627(x)
+ else
+ fun_l21_n289(x)
+ end
+end
+
+def fun_l20_n13(x)
+ if (x < 1)
+ fun_l21_n795(x)
+ else
+ fun_l21_n183(x)
+ end
+end
+
+def fun_l20_n14(x)
+ if (x < 1)
+ fun_l21_n384(x)
+ else
+ fun_l21_n3(x)
+ end
+end
+
+def fun_l20_n15(x)
+ if (x < 1)
+ fun_l21_n823(x)
+ else
+ fun_l21_n312(x)
+ end
+end
+
+def fun_l20_n16(x)
+ if (x < 1)
+ fun_l21_n727(x)
+ else
+ fun_l21_n897(x)
+ end
+end
+
+def fun_l20_n17(x)
+ if (x < 1)
+ fun_l21_n710(x)
+ else
+ fun_l21_n532(x)
+ end
+end
+
+def fun_l20_n18(x)
+ if (x < 1)
+ fun_l21_n373(x)
+ else
+ fun_l21_n807(x)
+ end
+end
+
+def fun_l20_n19(x)
+ if (x < 1)
+ fun_l21_n164(x)
+ else
+ fun_l21_n472(x)
+ end
+end
+
+def fun_l20_n20(x)
+ if (x < 1)
+ fun_l21_n522(x)
+ else
+ fun_l21_n264(x)
+ end
+end
+
+def fun_l20_n21(x)
+ if (x < 1)
+ fun_l21_n122(x)
+ else
+ fun_l21_n897(x)
+ end
+end
+
+def fun_l20_n22(x)
+ if (x < 1)
+ fun_l21_n292(x)
+ else
+ fun_l21_n873(x)
+ end
+end
+
+def fun_l20_n23(x)
+ if (x < 1)
+ fun_l21_n461(x)
+ else
+ fun_l21_n681(x)
+ end
+end
+
+def fun_l20_n24(x)
+ if (x < 1)
+ fun_l21_n80(x)
+ else
+ fun_l21_n484(x)
+ end
+end
+
+def fun_l20_n25(x)
+ if (x < 1)
+ fun_l21_n7(x)
+ else
+ fun_l21_n444(x)
+ end
+end
+
+def fun_l20_n26(x)
+ if (x < 1)
+ fun_l21_n269(x)
+ else
+ fun_l21_n58(x)
+ end
+end
+
+def fun_l20_n27(x)
+ if (x < 1)
+ fun_l21_n318(x)
+ else
+ fun_l21_n224(x)
+ end
+end
+
+def fun_l20_n28(x)
+ if (x < 1)
+ fun_l21_n437(x)
+ else
+ fun_l21_n621(x)
+ end
+end
+
+def fun_l20_n29(x)
+ if (x < 1)
+ fun_l21_n907(x)
+ else
+ fun_l21_n32(x)
+ end
+end
+
+def fun_l20_n30(x)
+ if (x < 1)
+ fun_l21_n525(x)
+ else
+ fun_l21_n10(x)
+ end
+end
+
+def fun_l20_n31(x)
+ if (x < 1)
+ fun_l21_n278(x)
+ else
+ fun_l21_n243(x)
+ end
+end
+
+def fun_l20_n32(x)
+ if (x < 1)
+ fun_l21_n865(x)
+ else
+ fun_l21_n236(x)
+ end
+end
+
+def fun_l20_n33(x)
+ if (x < 1)
+ fun_l21_n732(x)
+ else
+ fun_l21_n472(x)
+ end
+end
+
+def fun_l20_n34(x)
+ if (x < 1)
+ fun_l21_n331(x)
+ else
+ fun_l21_n162(x)
+ end
+end
+
+def fun_l20_n35(x)
+ if (x < 1)
+ fun_l21_n217(x)
+ else
+ fun_l21_n877(x)
+ end
+end
+
+def fun_l20_n36(x)
+ if (x < 1)
+ fun_l21_n125(x)
+ else
+ fun_l21_n683(x)
+ end
+end
+
+def fun_l20_n37(x)
+ if (x < 1)
+ fun_l21_n236(x)
+ else
+ fun_l21_n79(x)
+ end
+end
+
+def fun_l20_n38(x)
+ if (x < 1)
+ fun_l21_n308(x)
+ else
+ fun_l21_n995(x)
+ end
+end
+
+def fun_l20_n39(x)
+ if (x < 1)
+ fun_l21_n923(x)
+ else
+ fun_l21_n956(x)
+ end
+end
+
+def fun_l20_n40(x)
+ if (x < 1)
+ fun_l21_n505(x)
+ else
+ fun_l21_n47(x)
+ end
+end
+
+def fun_l20_n41(x)
+ if (x < 1)
+ fun_l21_n24(x)
+ else
+ fun_l21_n894(x)
+ end
+end
+
+def fun_l20_n42(x)
+ if (x < 1)
+ fun_l21_n824(x)
+ else
+ fun_l21_n106(x)
+ end
+end
+
+def fun_l20_n43(x)
+ if (x < 1)
+ fun_l21_n898(x)
+ else
+ fun_l21_n576(x)
+ end
+end
+
+def fun_l20_n44(x)
+ if (x < 1)
+ fun_l21_n231(x)
+ else
+ fun_l21_n689(x)
+ end
+end
+
+def fun_l20_n45(x)
+ if (x < 1)
+ fun_l21_n340(x)
+ else
+ fun_l21_n887(x)
+ end
+end
+
+def fun_l20_n46(x)
+ if (x < 1)
+ fun_l21_n157(x)
+ else
+ fun_l21_n551(x)
+ end
+end
+
+def fun_l20_n47(x)
+ if (x < 1)
+ fun_l21_n904(x)
+ else
+ fun_l21_n975(x)
+ end
+end
+
+def fun_l20_n48(x)
+ if (x < 1)
+ fun_l21_n392(x)
+ else
+ fun_l21_n882(x)
+ end
+end
+
+def fun_l20_n49(x)
+ if (x < 1)
+ fun_l21_n484(x)
+ else
+ fun_l21_n810(x)
+ end
+end
+
+def fun_l20_n50(x)
+ if (x < 1)
+ fun_l21_n517(x)
+ else
+ fun_l21_n434(x)
+ end
+end
+
+def fun_l20_n51(x)
+ if (x < 1)
+ fun_l21_n115(x)
+ else
+ fun_l21_n975(x)
+ end
+end
+
+def fun_l20_n52(x)
+ if (x < 1)
+ fun_l21_n633(x)
+ else
+ fun_l21_n799(x)
+ end
+end
+
+def fun_l20_n53(x)
+ if (x < 1)
+ fun_l21_n938(x)
+ else
+ fun_l21_n321(x)
+ end
+end
+
+def fun_l20_n54(x)
+ if (x < 1)
+ fun_l21_n98(x)
+ else
+ fun_l21_n343(x)
+ end
+end
+
+def fun_l20_n55(x)
+ if (x < 1)
+ fun_l21_n851(x)
+ else
+ fun_l21_n794(x)
+ end
+end
+
+def fun_l20_n56(x)
+ if (x < 1)
+ fun_l21_n119(x)
+ else
+ fun_l21_n649(x)
+ end
+end
+
+def fun_l20_n57(x)
+ if (x < 1)
+ fun_l21_n799(x)
+ else
+ fun_l21_n397(x)
+ end
+end
+
+def fun_l20_n58(x)
+ if (x < 1)
+ fun_l21_n429(x)
+ else
+ fun_l21_n781(x)
+ end
+end
+
+def fun_l20_n59(x)
+ if (x < 1)
+ fun_l21_n862(x)
+ else
+ fun_l21_n870(x)
+ end
+end
+
+def fun_l20_n60(x)
+ if (x < 1)
+ fun_l21_n864(x)
+ else
+ fun_l21_n333(x)
+ end
+end
+
+def fun_l20_n61(x)
+ if (x < 1)
+ fun_l21_n673(x)
+ else
+ fun_l21_n481(x)
+ end
+end
+
+def fun_l20_n62(x)
+ if (x < 1)
+ fun_l21_n193(x)
+ else
+ fun_l21_n524(x)
+ end
+end
+
+def fun_l20_n63(x)
+ if (x < 1)
+ fun_l21_n976(x)
+ else
+ fun_l21_n0(x)
+ end
+end
+
+def fun_l20_n64(x)
+ if (x < 1)
+ fun_l21_n804(x)
+ else
+ fun_l21_n833(x)
+ end
+end
+
+def fun_l20_n65(x)
+ if (x < 1)
+ fun_l21_n20(x)
+ else
+ fun_l21_n285(x)
+ end
+end
+
+def fun_l20_n66(x)
+ if (x < 1)
+ fun_l21_n70(x)
+ else
+ fun_l21_n932(x)
+ end
+end
+
+def fun_l20_n67(x)
+ if (x < 1)
+ fun_l21_n213(x)
+ else
+ fun_l21_n196(x)
+ end
+end
+
+def fun_l20_n68(x)
+ if (x < 1)
+ fun_l21_n806(x)
+ else
+ fun_l21_n322(x)
+ end
+end
+
+def fun_l20_n69(x)
+ if (x < 1)
+ fun_l21_n583(x)
+ else
+ fun_l21_n62(x)
+ end
+end
+
+def fun_l20_n70(x)
+ if (x < 1)
+ fun_l21_n141(x)
+ else
+ fun_l21_n490(x)
+ end
+end
+
+def fun_l20_n71(x)
+ if (x < 1)
+ fun_l21_n995(x)
+ else
+ fun_l21_n398(x)
+ end
+end
+
+def fun_l20_n72(x)
+ if (x < 1)
+ fun_l21_n436(x)
+ else
+ fun_l21_n490(x)
+ end
+end
+
+def fun_l20_n73(x)
+ if (x < 1)
+ fun_l21_n585(x)
+ else
+ fun_l21_n275(x)
+ end
+end
+
+def fun_l20_n74(x)
+ if (x < 1)
+ fun_l21_n120(x)
+ else
+ fun_l21_n968(x)
+ end
+end
+
+def fun_l20_n75(x)
+ if (x < 1)
+ fun_l21_n562(x)
+ else
+ fun_l21_n896(x)
+ end
+end
+
+def fun_l20_n76(x)
+ if (x < 1)
+ fun_l21_n794(x)
+ else
+ fun_l21_n224(x)
+ end
+end
+
+def fun_l20_n77(x)
+ if (x < 1)
+ fun_l21_n71(x)
+ else
+ fun_l21_n870(x)
+ end
+end
+
+def fun_l20_n78(x)
+ if (x < 1)
+ fun_l21_n0(x)
+ else
+ fun_l21_n41(x)
+ end
+end
+
+def fun_l20_n79(x)
+ if (x < 1)
+ fun_l21_n325(x)
+ else
+ fun_l21_n814(x)
+ end
+end
+
+def fun_l20_n80(x)
+ if (x < 1)
+ fun_l21_n963(x)
+ else
+ fun_l21_n792(x)
+ end
+end
+
+def fun_l20_n81(x)
+ if (x < 1)
+ fun_l21_n415(x)
+ else
+ fun_l21_n200(x)
+ end
+end
+
+def fun_l20_n82(x)
+ if (x < 1)
+ fun_l21_n438(x)
+ else
+ fun_l21_n506(x)
+ end
+end
+
+def fun_l20_n83(x)
+ if (x < 1)
+ fun_l21_n283(x)
+ else
+ fun_l21_n708(x)
+ end
+end
+
+def fun_l20_n84(x)
+ if (x < 1)
+ fun_l21_n968(x)
+ else
+ fun_l21_n80(x)
+ end
+end
+
+def fun_l20_n85(x)
+ if (x < 1)
+ fun_l21_n839(x)
+ else
+ fun_l21_n808(x)
+ end
+end
+
+def fun_l20_n86(x)
+ if (x < 1)
+ fun_l21_n653(x)
+ else
+ fun_l21_n343(x)
+ end
+end
+
+def fun_l20_n87(x)
+ if (x < 1)
+ fun_l21_n580(x)
+ else
+ fun_l21_n652(x)
+ end
+end
+
+def fun_l20_n88(x)
+ if (x < 1)
+ fun_l21_n64(x)
+ else
+ fun_l21_n899(x)
+ end
+end
+
+def fun_l20_n89(x)
+ if (x < 1)
+ fun_l21_n325(x)
+ else
+ fun_l21_n645(x)
+ end
+end
+
+def fun_l20_n90(x)
+ if (x < 1)
+ fun_l21_n251(x)
+ else
+ fun_l21_n210(x)
+ end
+end
+
+def fun_l20_n91(x)
+ if (x < 1)
+ fun_l21_n943(x)
+ else
+ fun_l21_n451(x)
+ end
+end
+
+def fun_l20_n92(x)
+ if (x < 1)
+ fun_l21_n95(x)
+ else
+ fun_l21_n937(x)
+ end
+end
+
+def fun_l20_n93(x)
+ if (x < 1)
+ fun_l21_n263(x)
+ else
+ fun_l21_n107(x)
+ end
+end
+
+def fun_l20_n94(x)
+ if (x < 1)
+ fun_l21_n438(x)
+ else
+ fun_l21_n213(x)
+ end
+end
+
+def fun_l20_n95(x)
+ if (x < 1)
+ fun_l21_n283(x)
+ else
+ fun_l21_n203(x)
+ end
+end
+
+def fun_l20_n96(x)
+ if (x < 1)
+ fun_l21_n809(x)
+ else
+ fun_l21_n154(x)
+ end
+end
+
+def fun_l20_n97(x)
+ if (x < 1)
+ fun_l21_n513(x)
+ else
+ fun_l21_n15(x)
+ end
+end
+
+def fun_l20_n98(x)
+ if (x < 1)
+ fun_l21_n854(x)
+ else
+ fun_l21_n679(x)
+ end
+end
+
+def fun_l20_n99(x)
+ if (x < 1)
+ fun_l21_n102(x)
+ else
+ fun_l21_n546(x)
+ end
+end
+
+def fun_l20_n100(x)
+ if (x < 1)
+ fun_l21_n790(x)
+ else
+ fun_l21_n143(x)
+ end
+end
+
+def fun_l20_n101(x)
+ if (x < 1)
+ fun_l21_n835(x)
+ else
+ fun_l21_n78(x)
+ end
+end
+
+def fun_l20_n102(x)
+ if (x < 1)
+ fun_l21_n96(x)
+ else
+ fun_l21_n995(x)
+ end
+end
+
+def fun_l20_n103(x)
+ if (x < 1)
+ fun_l21_n445(x)
+ else
+ fun_l21_n332(x)
+ end
+end
+
+def fun_l20_n104(x)
+ if (x < 1)
+ fun_l21_n532(x)
+ else
+ fun_l21_n509(x)
+ end
+end
+
+def fun_l20_n105(x)
+ if (x < 1)
+ fun_l21_n592(x)
+ else
+ fun_l21_n237(x)
+ end
+end
+
+def fun_l20_n106(x)
+ if (x < 1)
+ fun_l21_n837(x)
+ else
+ fun_l21_n13(x)
+ end
+end
+
+def fun_l20_n107(x)
+ if (x < 1)
+ fun_l21_n518(x)
+ else
+ fun_l21_n463(x)
+ end
+end
+
+def fun_l20_n108(x)
+ if (x < 1)
+ fun_l21_n373(x)
+ else
+ fun_l21_n597(x)
+ end
+end
+
+def fun_l20_n109(x)
+ if (x < 1)
+ fun_l21_n832(x)
+ else
+ fun_l21_n784(x)
+ end
+end
+
+def fun_l20_n110(x)
+ if (x < 1)
+ fun_l21_n408(x)
+ else
+ fun_l21_n738(x)
+ end
+end
+
+def fun_l20_n111(x)
+ if (x < 1)
+ fun_l21_n243(x)
+ else
+ fun_l21_n96(x)
+ end
+end
+
+def fun_l20_n112(x)
+ if (x < 1)
+ fun_l21_n251(x)
+ else
+ fun_l21_n151(x)
+ end
+end
+
+def fun_l20_n113(x)
+ if (x < 1)
+ fun_l21_n970(x)
+ else
+ fun_l21_n329(x)
+ end
+end
+
+def fun_l20_n114(x)
+ if (x < 1)
+ fun_l21_n691(x)
+ else
+ fun_l21_n309(x)
+ end
+end
+
+def fun_l20_n115(x)
+ if (x < 1)
+ fun_l21_n250(x)
+ else
+ fun_l21_n927(x)
+ end
+end
+
+def fun_l20_n116(x)
+ if (x < 1)
+ fun_l21_n819(x)
+ else
+ fun_l21_n49(x)
+ end
+end
+
+def fun_l20_n117(x)
+ if (x < 1)
+ fun_l21_n761(x)
+ else
+ fun_l21_n91(x)
+ end
+end
+
+def fun_l20_n118(x)
+ if (x < 1)
+ fun_l21_n170(x)
+ else
+ fun_l21_n317(x)
+ end
+end
+
+def fun_l20_n119(x)
+ if (x < 1)
+ fun_l21_n199(x)
+ else
+ fun_l21_n406(x)
+ end
+end
+
+def fun_l20_n120(x)
+ if (x < 1)
+ fun_l21_n983(x)
+ else
+ fun_l21_n742(x)
+ end
+end
+
+def fun_l20_n121(x)
+ if (x < 1)
+ fun_l21_n428(x)
+ else
+ fun_l21_n887(x)
+ end
+end
+
+def fun_l20_n122(x)
+ if (x < 1)
+ fun_l21_n369(x)
+ else
+ fun_l21_n64(x)
+ end
+end
+
+def fun_l20_n123(x)
+ if (x < 1)
+ fun_l21_n727(x)
+ else
+ fun_l21_n484(x)
+ end
+end
+
+def fun_l20_n124(x)
+ if (x < 1)
+ fun_l21_n310(x)
+ else
+ fun_l21_n198(x)
+ end
+end
+
+def fun_l20_n125(x)
+ if (x < 1)
+ fun_l21_n747(x)
+ else
+ fun_l21_n935(x)
+ end
+end
+
+def fun_l20_n126(x)
+ if (x < 1)
+ fun_l21_n389(x)
+ else
+ fun_l21_n966(x)
+ end
+end
+
+def fun_l20_n127(x)
+ if (x < 1)
+ fun_l21_n852(x)
+ else
+ fun_l21_n128(x)
+ end
+end
+
+def fun_l20_n128(x)
+ if (x < 1)
+ fun_l21_n10(x)
+ else
+ fun_l21_n376(x)
+ end
+end
+
+def fun_l20_n129(x)
+ if (x < 1)
+ fun_l21_n413(x)
+ else
+ fun_l21_n465(x)
+ end
+end
+
+def fun_l20_n130(x)
+ if (x < 1)
+ fun_l21_n536(x)
+ else
+ fun_l21_n689(x)
+ end
+end
+
+def fun_l20_n131(x)
+ if (x < 1)
+ fun_l21_n707(x)
+ else
+ fun_l21_n793(x)
+ end
+end
+
+def fun_l20_n132(x)
+ if (x < 1)
+ fun_l21_n328(x)
+ else
+ fun_l21_n56(x)
+ end
+end
+
+def fun_l20_n133(x)
+ if (x < 1)
+ fun_l21_n318(x)
+ else
+ fun_l21_n570(x)
+ end
+end
+
+def fun_l20_n134(x)
+ if (x < 1)
+ fun_l21_n656(x)
+ else
+ fun_l21_n187(x)
+ end
+end
+
+def fun_l20_n135(x)
+ if (x < 1)
+ fun_l21_n259(x)
+ else
+ fun_l21_n718(x)
+ end
+end
+
+def fun_l20_n136(x)
+ if (x < 1)
+ fun_l21_n284(x)
+ else
+ fun_l21_n167(x)
+ end
+end
+
+def fun_l20_n137(x)
+ if (x < 1)
+ fun_l21_n788(x)
+ else
+ fun_l21_n595(x)
+ end
+end
+
+def fun_l20_n138(x)
+ if (x < 1)
+ fun_l21_n431(x)
+ else
+ fun_l21_n620(x)
+ end
+end
+
+def fun_l20_n139(x)
+ if (x < 1)
+ fun_l21_n365(x)
+ else
+ fun_l21_n995(x)
+ end
+end
+
+def fun_l20_n140(x)
+ if (x < 1)
+ fun_l21_n614(x)
+ else
+ fun_l21_n79(x)
+ end
+end
+
+def fun_l20_n141(x)
+ if (x < 1)
+ fun_l21_n138(x)
+ else
+ fun_l21_n655(x)
+ end
+end
+
+def fun_l20_n142(x)
+ if (x < 1)
+ fun_l21_n155(x)
+ else
+ fun_l21_n34(x)
+ end
+end
+
+def fun_l20_n143(x)
+ if (x < 1)
+ fun_l21_n829(x)
+ else
+ fun_l21_n703(x)
+ end
+end
+
+def fun_l20_n144(x)
+ if (x < 1)
+ fun_l21_n290(x)
+ else
+ fun_l21_n279(x)
+ end
+end
+
+def fun_l20_n145(x)
+ if (x < 1)
+ fun_l21_n825(x)
+ else
+ fun_l21_n720(x)
+ end
+end
+
+def fun_l20_n146(x)
+ if (x < 1)
+ fun_l21_n678(x)
+ else
+ fun_l21_n347(x)
+ end
+end
+
+def fun_l20_n147(x)
+ if (x < 1)
+ fun_l21_n967(x)
+ else
+ fun_l21_n133(x)
+ end
+end
+
+def fun_l20_n148(x)
+ if (x < 1)
+ fun_l21_n935(x)
+ else
+ fun_l21_n438(x)
+ end
+end
+
+def fun_l20_n149(x)
+ if (x < 1)
+ fun_l21_n14(x)
+ else
+ fun_l21_n233(x)
+ end
+end
+
+def fun_l20_n150(x)
+ if (x < 1)
+ fun_l21_n42(x)
+ else
+ fun_l21_n507(x)
+ end
+end
+
+def fun_l20_n151(x)
+ if (x < 1)
+ fun_l21_n33(x)
+ else
+ fun_l21_n404(x)
+ end
+end
+
+def fun_l20_n152(x)
+ if (x < 1)
+ fun_l21_n897(x)
+ else
+ fun_l21_n972(x)
+ end
+end
+
+def fun_l20_n153(x)
+ if (x < 1)
+ fun_l21_n221(x)
+ else
+ fun_l21_n718(x)
+ end
+end
+
+def fun_l20_n154(x)
+ if (x < 1)
+ fun_l21_n737(x)
+ else
+ fun_l21_n257(x)
+ end
+end
+
+def fun_l20_n155(x)
+ if (x < 1)
+ fun_l21_n465(x)
+ else
+ fun_l21_n917(x)
+ end
+end
+
+def fun_l20_n156(x)
+ if (x < 1)
+ fun_l21_n338(x)
+ else
+ fun_l21_n673(x)
+ end
+end
+
+def fun_l20_n157(x)
+ if (x < 1)
+ fun_l21_n429(x)
+ else
+ fun_l21_n23(x)
+ end
+end
+
+def fun_l20_n158(x)
+ if (x < 1)
+ fun_l21_n826(x)
+ else
+ fun_l21_n115(x)
+ end
+end
+
+def fun_l20_n159(x)
+ if (x < 1)
+ fun_l21_n713(x)
+ else
+ fun_l21_n954(x)
+ end
+end
+
+def fun_l20_n160(x)
+ if (x < 1)
+ fun_l21_n897(x)
+ else
+ fun_l21_n46(x)
+ end
+end
+
+def fun_l20_n161(x)
+ if (x < 1)
+ fun_l21_n751(x)
+ else
+ fun_l21_n885(x)
+ end
+end
+
+def fun_l20_n162(x)
+ if (x < 1)
+ fun_l21_n935(x)
+ else
+ fun_l21_n230(x)
+ end
+end
+
+def fun_l20_n163(x)
+ if (x < 1)
+ fun_l21_n862(x)
+ else
+ fun_l21_n874(x)
+ end
+end
+
+def fun_l20_n164(x)
+ if (x < 1)
+ fun_l21_n695(x)
+ else
+ fun_l21_n707(x)
+ end
+end
+
+def fun_l20_n165(x)
+ if (x < 1)
+ fun_l21_n539(x)
+ else
+ fun_l21_n14(x)
+ end
+end
+
+def fun_l20_n166(x)
+ if (x < 1)
+ fun_l21_n139(x)
+ else
+ fun_l21_n766(x)
+ end
+end
+
+def fun_l20_n167(x)
+ if (x < 1)
+ fun_l21_n100(x)
+ else
+ fun_l21_n229(x)
+ end
+end
+
+def fun_l20_n168(x)
+ if (x < 1)
+ fun_l21_n88(x)
+ else
+ fun_l21_n642(x)
+ end
+end
+
+def fun_l20_n169(x)
+ if (x < 1)
+ fun_l21_n57(x)
+ else
+ fun_l21_n252(x)
+ end
+end
+
+def fun_l20_n170(x)
+ if (x < 1)
+ fun_l21_n470(x)
+ else
+ fun_l21_n224(x)
+ end
+end
+
+def fun_l20_n171(x)
+ if (x < 1)
+ fun_l21_n163(x)
+ else
+ fun_l21_n114(x)
+ end
+end
+
+def fun_l20_n172(x)
+ if (x < 1)
+ fun_l21_n231(x)
+ else
+ fun_l21_n405(x)
+ end
+end
+
+def fun_l20_n173(x)
+ if (x < 1)
+ fun_l21_n553(x)
+ else
+ fun_l21_n758(x)
+ end
+end
+
+def fun_l20_n174(x)
+ if (x < 1)
+ fun_l21_n874(x)
+ else
+ fun_l21_n43(x)
+ end
+end
+
+def fun_l20_n175(x)
+ if (x < 1)
+ fun_l21_n911(x)
+ else
+ fun_l21_n644(x)
+ end
+end
+
+def fun_l20_n176(x)
+ if (x < 1)
+ fun_l21_n747(x)
+ else
+ fun_l21_n900(x)
+ end
+end
+
+def fun_l20_n177(x)
+ if (x < 1)
+ fun_l21_n956(x)
+ else
+ fun_l21_n152(x)
+ end
+end
+
+def fun_l20_n178(x)
+ if (x < 1)
+ fun_l21_n226(x)
+ else
+ fun_l21_n654(x)
+ end
+end
+
+def fun_l20_n179(x)
+ if (x < 1)
+ fun_l21_n284(x)
+ else
+ fun_l21_n968(x)
+ end
+end
+
+def fun_l20_n180(x)
+ if (x < 1)
+ fun_l21_n181(x)
+ else
+ fun_l21_n690(x)
+ end
+end
+
+def fun_l20_n181(x)
+ if (x < 1)
+ fun_l21_n35(x)
+ else
+ fun_l21_n500(x)
+ end
+end
+
+def fun_l20_n182(x)
+ if (x < 1)
+ fun_l21_n212(x)
+ else
+ fun_l21_n559(x)
+ end
+end
+
+def fun_l20_n183(x)
+ if (x < 1)
+ fun_l21_n981(x)
+ else
+ fun_l21_n605(x)
+ end
+end
+
+def fun_l20_n184(x)
+ if (x < 1)
+ fun_l21_n447(x)
+ else
+ fun_l21_n718(x)
+ end
+end
+
+def fun_l20_n185(x)
+ if (x < 1)
+ fun_l21_n272(x)
+ else
+ fun_l21_n341(x)
+ end
+end
+
+def fun_l20_n186(x)
+ if (x < 1)
+ fun_l21_n5(x)
+ else
+ fun_l21_n426(x)
+ end
+end
+
+def fun_l20_n187(x)
+ if (x < 1)
+ fun_l21_n630(x)
+ else
+ fun_l21_n62(x)
+ end
+end
+
+def fun_l20_n188(x)
+ if (x < 1)
+ fun_l21_n600(x)
+ else
+ fun_l21_n674(x)
+ end
+end
+
+def fun_l20_n189(x)
+ if (x < 1)
+ fun_l21_n645(x)
+ else
+ fun_l21_n936(x)
+ end
+end
+
+def fun_l20_n190(x)
+ if (x < 1)
+ fun_l21_n15(x)
+ else
+ fun_l21_n158(x)
+ end
+end
+
+def fun_l20_n191(x)
+ if (x < 1)
+ fun_l21_n789(x)
+ else
+ fun_l21_n103(x)
+ end
+end
+
+def fun_l20_n192(x)
+ if (x < 1)
+ fun_l21_n501(x)
+ else
+ fun_l21_n655(x)
+ end
+end
+
+def fun_l20_n193(x)
+ if (x < 1)
+ fun_l21_n242(x)
+ else
+ fun_l21_n241(x)
+ end
+end
+
+def fun_l20_n194(x)
+ if (x < 1)
+ fun_l21_n296(x)
+ else
+ fun_l21_n442(x)
+ end
+end
+
+def fun_l20_n195(x)
+ if (x < 1)
+ fun_l21_n288(x)
+ else
+ fun_l21_n165(x)
+ end
+end
+
+def fun_l20_n196(x)
+ if (x < 1)
+ fun_l21_n336(x)
+ else
+ fun_l21_n328(x)
+ end
+end
+
+def fun_l20_n197(x)
+ if (x < 1)
+ fun_l21_n423(x)
+ else
+ fun_l21_n906(x)
+ end
+end
+
+def fun_l20_n198(x)
+ if (x < 1)
+ fun_l21_n875(x)
+ else
+ fun_l21_n801(x)
+ end
+end
+
+def fun_l20_n199(x)
+ if (x < 1)
+ fun_l21_n864(x)
+ else
+ fun_l21_n594(x)
+ end
+end
+
+def fun_l20_n200(x)
+ if (x < 1)
+ fun_l21_n145(x)
+ else
+ fun_l21_n728(x)
+ end
+end
+
+def fun_l20_n201(x)
+ if (x < 1)
+ fun_l21_n941(x)
+ else
+ fun_l21_n592(x)
+ end
+end
+
+def fun_l20_n202(x)
+ if (x < 1)
+ fun_l21_n458(x)
+ else
+ fun_l21_n839(x)
+ end
+end
+
+def fun_l20_n203(x)
+ if (x < 1)
+ fun_l21_n352(x)
+ else
+ fun_l21_n319(x)
+ end
+end
+
+def fun_l20_n204(x)
+ if (x < 1)
+ fun_l21_n453(x)
+ else
+ fun_l21_n944(x)
+ end
+end
+
+def fun_l20_n205(x)
+ if (x < 1)
+ fun_l21_n479(x)
+ else
+ fun_l21_n409(x)
+ end
+end
+
+def fun_l20_n206(x)
+ if (x < 1)
+ fun_l21_n72(x)
+ else
+ fun_l21_n177(x)
+ end
+end
+
+def fun_l20_n207(x)
+ if (x < 1)
+ fun_l21_n895(x)
+ else
+ fun_l21_n77(x)
+ end
+end
+
+def fun_l20_n208(x)
+ if (x < 1)
+ fun_l21_n308(x)
+ else
+ fun_l21_n181(x)
+ end
+end
+
+def fun_l20_n209(x)
+ if (x < 1)
+ fun_l21_n358(x)
+ else
+ fun_l21_n666(x)
+ end
+end
+
+def fun_l20_n210(x)
+ if (x < 1)
+ fun_l21_n275(x)
+ else
+ fun_l21_n739(x)
+ end
+end
+
+def fun_l20_n211(x)
+ if (x < 1)
+ fun_l21_n706(x)
+ else
+ fun_l21_n722(x)
+ end
+end
+
+def fun_l20_n212(x)
+ if (x < 1)
+ fun_l21_n185(x)
+ else
+ fun_l21_n893(x)
+ end
+end
+
+def fun_l20_n213(x)
+ if (x < 1)
+ fun_l21_n307(x)
+ else
+ fun_l21_n871(x)
+ end
+end
+
+def fun_l20_n214(x)
+ if (x < 1)
+ fun_l21_n365(x)
+ else
+ fun_l21_n311(x)
+ end
+end
+
+def fun_l20_n215(x)
+ if (x < 1)
+ fun_l21_n176(x)
+ else
+ fun_l21_n998(x)
+ end
+end
+
+def fun_l20_n216(x)
+ if (x < 1)
+ fun_l21_n542(x)
+ else
+ fun_l21_n248(x)
+ end
+end
+
+def fun_l20_n217(x)
+ if (x < 1)
+ fun_l21_n568(x)
+ else
+ fun_l21_n671(x)
+ end
+end
+
+def fun_l20_n218(x)
+ if (x < 1)
+ fun_l21_n704(x)
+ else
+ fun_l21_n992(x)
+ end
+end
+
+def fun_l20_n219(x)
+ if (x < 1)
+ fun_l21_n500(x)
+ else
+ fun_l21_n845(x)
+ end
+end
+
+def fun_l20_n220(x)
+ if (x < 1)
+ fun_l21_n75(x)
+ else
+ fun_l21_n365(x)
+ end
+end
+
+def fun_l20_n221(x)
+ if (x < 1)
+ fun_l21_n780(x)
+ else
+ fun_l21_n574(x)
+ end
+end
+
+def fun_l20_n222(x)
+ if (x < 1)
+ fun_l21_n778(x)
+ else
+ fun_l21_n315(x)
+ end
+end
+
+def fun_l20_n223(x)
+ if (x < 1)
+ fun_l21_n845(x)
+ else
+ fun_l21_n521(x)
+ end
+end
+
+def fun_l20_n224(x)
+ if (x < 1)
+ fun_l21_n608(x)
+ else
+ fun_l21_n762(x)
+ end
+end
+
+def fun_l20_n225(x)
+ if (x < 1)
+ fun_l21_n912(x)
+ else
+ fun_l21_n651(x)
+ end
+end
+
+def fun_l20_n226(x)
+ if (x < 1)
+ fun_l21_n337(x)
+ else
+ fun_l21_n723(x)
+ end
+end
+
+def fun_l20_n227(x)
+ if (x < 1)
+ fun_l21_n734(x)
+ else
+ fun_l21_n967(x)
+ end
+end
+
+def fun_l20_n228(x)
+ if (x < 1)
+ fun_l21_n342(x)
+ else
+ fun_l21_n611(x)
+ end
+end
+
+def fun_l20_n229(x)
+ if (x < 1)
+ fun_l21_n607(x)
+ else
+ fun_l21_n317(x)
+ end
+end
+
+def fun_l20_n230(x)
+ if (x < 1)
+ fun_l21_n478(x)
+ else
+ fun_l21_n208(x)
+ end
+end
+
+def fun_l20_n231(x)
+ if (x < 1)
+ fun_l21_n481(x)
+ else
+ fun_l21_n171(x)
+ end
+end
+
+def fun_l20_n232(x)
+ if (x < 1)
+ fun_l21_n80(x)
+ else
+ fun_l21_n810(x)
+ end
+end
+
+def fun_l20_n233(x)
+ if (x < 1)
+ fun_l21_n597(x)
+ else
+ fun_l21_n474(x)
+ end
+end
+
+def fun_l20_n234(x)
+ if (x < 1)
+ fun_l21_n997(x)
+ else
+ fun_l21_n98(x)
+ end
+end
+
+def fun_l20_n235(x)
+ if (x < 1)
+ fun_l21_n663(x)
+ else
+ fun_l21_n103(x)
+ end
+end
+
+def fun_l20_n236(x)
+ if (x < 1)
+ fun_l21_n602(x)
+ else
+ fun_l21_n421(x)
+ end
+end
+
+def fun_l20_n237(x)
+ if (x < 1)
+ fun_l21_n888(x)
+ else
+ fun_l21_n759(x)
+ end
+end
+
+def fun_l20_n238(x)
+ if (x < 1)
+ fun_l21_n21(x)
+ else
+ fun_l21_n56(x)
+ end
+end
+
+def fun_l20_n239(x)
+ if (x < 1)
+ fun_l21_n663(x)
+ else
+ fun_l21_n102(x)
+ end
+end
+
+def fun_l20_n240(x)
+ if (x < 1)
+ fun_l21_n244(x)
+ else
+ fun_l21_n507(x)
+ end
+end
+
+def fun_l20_n241(x)
+ if (x < 1)
+ fun_l21_n263(x)
+ else
+ fun_l21_n382(x)
+ end
+end
+
+def fun_l20_n242(x)
+ if (x < 1)
+ fun_l21_n639(x)
+ else
+ fun_l21_n380(x)
+ end
+end
+
+def fun_l20_n243(x)
+ if (x < 1)
+ fun_l21_n99(x)
+ else
+ fun_l21_n35(x)
+ end
+end
+
+def fun_l20_n244(x)
+ if (x < 1)
+ fun_l21_n648(x)
+ else
+ fun_l21_n266(x)
+ end
+end
+
+def fun_l20_n245(x)
+ if (x < 1)
+ fun_l21_n613(x)
+ else
+ fun_l21_n277(x)
+ end
+end
+
+def fun_l20_n246(x)
+ if (x < 1)
+ fun_l21_n886(x)
+ else
+ fun_l21_n4(x)
+ end
+end
+
+def fun_l20_n247(x)
+ if (x < 1)
+ fun_l21_n510(x)
+ else
+ fun_l21_n146(x)
+ end
+end
+
+def fun_l20_n248(x)
+ if (x < 1)
+ fun_l21_n933(x)
+ else
+ fun_l21_n765(x)
+ end
+end
+
+def fun_l20_n249(x)
+ if (x < 1)
+ fun_l21_n323(x)
+ else
+ fun_l21_n222(x)
+ end
+end
+
+def fun_l20_n250(x)
+ if (x < 1)
+ fun_l21_n708(x)
+ else
+ fun_l21_n241(x)
+ end
+end
+
+def fun_l20_n251(x)
+ if (x < 1)
+ fun_l21_n394(x)
+ else
+ fun_l21_n899(x)
+ end
+end
+
+def fun_l20_n252(x)
+ if (x < 1)
+ fun_l21_n253(x)
+ else
+ fun_l21_n221(x)
+ end
+end
+
+def fun_l20_n253(x)
+ if (x < 1)
+ fun_l21_n842(x)
+ else
+ fun_l21_n594(x)
+ end
+end
+
+def fun_l20_n254(x)
+ if (x < 1)
+ fun_l21_n325(x)
+ else
+ fun_l21_n145(x)
+ end
+end
+
+def fun_l20_n255(x)
+ if (x < 1)
+ fun_l21_n568(x)
+ else
+ fun_l21_n736(x)
+ end
+end
+
+def fun_l20_n256(x)
+ if (x < 1)
+ fun_l21_n862(x)
+ else
+ fun_l21_n388(x)
+ end
+end
+
+def fun_l20_n257(x)
+ if (x < 1)
+ fun_l21_n738(x)
+ else
+ fun_l21_n255(x)
+ end
+end
+
+def fun_l20_n258(x)
+ if (x < 1)
+ fun_l21_n704(x)
+ else
+ fun_l21_n539(x)
+ end
+end
+
+def fun_l20_n259(x)
+ if (x < 1)
+ fun_l21_n149(x)
+ else
+ fun_l21_n940(x)
+ end
+end
+
+def fun_l20_n260(x)
+ if (x < 1)
+ fun_l21_n462(x)
+ else
+ fun_l21_n840(x)
+ end
+end
+
+def fun_l20_n261(x)
+ if (x < 1)
+ fun_l21_n549(x)
+ else
+ fun_l21_n968(x)
+ end
+end
+
+def fun_l20_n262(x)
+ if (x < 1)
+ fun_l21_n290(x)
+ else
+ fun_l21_n127(x)
+ end
+end
+
+def fun_l20_n263(x)
+ if (x < 1)
+ fun_l21_n311(x)
+ else
+ fun_l21_n652(x)
+ end
+end
+
+def fun_l20_n264(x)
+ if (x < 1)
+ fun_l21_n544(x)
+ else
+ fun_l21_n521(x)
+ end
+end
+
+def fun_l20_n265(x)
+ if (x < 1)
+ fun_l21_n984(x)
+ else
+ fun_l21_n957(x)
+ end
+end
+
+def fun_l20_n266(x)
+ if (x < 1)
+ fun_l21_n10(x)
+ else
+ fun_l21_n154(x)
+ end
+end
+
+def fun_l20_n267(x)
+ if (x < 1)
+ fun_l21_n707(x)
+ else
+ fun_l21_n623(x)
+ end
+end
+
+def fun_l20_n268(x)
+ if (x < 1)
+ fun_l21_n420(x)
+ else
+ fun_l21_n31(x)
+ end
+end
+
+def fun_l20_n269(x)
+ if (x < 1)
+ fun_l21_n380(x)
+ else
+ fun_l21_n397(x)
+ end
+end
+
+def fun_l20_n270(x)
+ if (x < 1)
+ fun_l21_n95(x)
+ else
+ fun_l21_n881(x)
+ end
+end
+
+def fun_l20_n271(x)
+ if (x < 1)
+ fun_l21_n731(x)
+ else
+ fun_l21_n521(x)
+ end
+end
+
+def fun_l20_n272(x)
+ if (x < 1)
+ fun_l21_n255(x)
+ else
+ fun_l21_n412(x)
+ end
+end
+
+def fun_l20_n273(x)
+ if (x < 1)
+ fun_l21_n455(x)
+ else
+ fun_l21_n225(x)
+ end
+end
+
+def fun_l20_n274(x)
+ if (x < 1)
+ fun_l21_n223(x)
+ else
+ fun_l21_n71(x)
+ end
+end
+
+def fun_l20_n275(x)
+ if (x < 1)
+ fun_l21_n819(x)
+ else
+ fun_l21_n765(x)
+ end
+end
+
+def fun_l20_n276(x)
+ if (x < 1)
+ fun_l21_n379(x)
+ else
+ fun_l21_n892(x)
+ end
+end
+
+def fun_l20_n277(x)
+ if (x < 1)
+ fun_l21_n695(x)
+ else
+ fun_l21_n856(x)
+ end
+end
+
+def fun_l20_n278(x)
+ if (x < 1)
+ fun_l21_n217(x)
+ else
+ fun_l21_n166(x)
+ end
+end
+
+def fun_l20_n279(x)
+ if (x < 1)
+ fun_l21_n708(x)
+ else
+ fun_l21_n987(x)
+ end
+end
+
+def fun_l20_n280(x)
+ if (x < 1)
+ fun_l21_n251(x)
+ else
+ fun_l21_n144(x)
+ end
+end
+
+def fun_l20_n281(x)
+ if (x < 1)
+ fun_l21_n262(x)
+ else
+ fun_l21_n428(x)
+ end
+end
+
+def fun_l20_n282(x)
+ if (x < 1)
+ fun_l21_n439(x)
+ else
+ fun_l21_n1(x)
+ end
+end
+
+def fun_l20_n283(x)
+ if (x < 1)
+ fun_l21_n405(x)
+ else
+ fun_l21_n413(x)
+ end
+end
+
+def fun_l20_n284(x)
+ if (x < 1)
+ fun_l21_n729(x)
+ else
+ fun_l21_n61(x)
+ end
+end
+
+def fun_l20_n285(x)
+ if (x < 1)
+ fun_l21_n255(x)
+ else
+ fun_l21_n985(x)
+ end
+end
+
+def fun_l20_n286(x)
+ if (x < 1)
+ fun_l21_n348(x)
+ else
+ fun_l21_n54(x)
+ end
+end
+
+def fun_l20_n287(x)
+ if (x < 1)
+ fun_l21_n663(x)
+ else
+ fun_l21_n837(x)
+ end
+end
+
+def fun_l20_n288(x)
+ if (x < 1)
+ fun_l21_n444(x)
+ else
+ fun_l21_n767(x)
+ end
+end
+
+def fun_l20_n289(x)
+ if (x < 1)
+ fun_l21_n756(x)
+ else
+ fun_l21_n246(x)
+ end
+end
+
+def fun_l20_n290(x)
+ if (x < 1)
+ fun_l21_n0(x)
+ else
+ fun_l21_n253(x)
+ end
+end
+
+def fun_l20_n291(x)
+ if (x < 1)
+ fun_l21_n867(x)
+ else
+ fun_l21_n464(x)
+ end
+end
+
+def fun_l20_n292(x)
+ if (x < 1)
+ fun_l21_n885(x)
+ else
+ fun_l21_n588(x)
+ end
+end
+
+def fun_l20_n293(x)
+ if (x < 1)
+ fun_l21_n420(x)
+ else
+ fun_l21_n622(x)
+ end
+end
+
+def fun_l20_n294(x)
+ if (x < 1)
+ fun_l21_n411(x)
+ else
+ fun_l21_n351(x)
+ end
+end
+
+def fun_l20_n295(x)
+ if (x < 1)
+ fun_l21_n208(x)
+ else
+ fun_l21_n0(x)
+ end
+end
+
+def fun_l20_n296(x)
+ if (x < 1)
+ fun_l21_n551(x)
+ else
+ fun_l21_n68(x)
+ end
+end
+
+def fun_l20_n297(x)
+ if (x < 1)
+ fun_l21_n351(x)
+ else
+ fun_l21_n108(x)
+ end
+end
+
+def fun_l20_n298(x)
+ if (x < 1)
+ fun_l21_n134(x)
+ else
+ fun_l21_n893(x)
+ end
+end
+
+def fun_l20_n299(x)
+ if (x < 1)
+ fun_l21_n697(x)
+ else
+ fun_l21_n538(x)
+ end
+end
+
+def fun_l20_n300(x)
+ if (x < 1)
+ fun_l21_n61(x)
+ else
+ fun_l21_n641(x)
+ end
+end
+
+def fun_l20_n301(x)
+ if (x < 1)
+ fun_l21_n13(x)
+ else
+ fun_l21_n103(x)
+ end
+end
+
+def fun_l20_n302(x)
+ if (x < 1)
+ fun_l21_n260(x)
+ else
+ fun_l21_n430(x)
+ end
+end
+
+def fun_l20_n303(x)
+ if (x < 1)
+ fun_l21_n63(x)
+ else
+ fun_l21_n911(x)
+ end
+end
+
+def fun_l20_n304(x)
+ if (x < 1)
+ fun_l21_n470(x)
+ else
+ fun_l21_n407(x)
+ end
+end
+
+def fun_l20_n305(x)
+ if (x < 1)
+ fun_l21_n615(x)
+ else
+ fun_l21_n767(x)
+ end
+end
+
+def fun_l20_n306(x)
+ if (x < 1)
+ fun_l21_n898(x)
+ else
+ fun_l21_n215(x)
+ end
+end
+
+def fun_l20_n307(x)
+ if (x < 1)
+ fun_l21_n793(x)
+ else
+ fun_l21_n468(x)
+ end
+end
+
+def fun_l20_n308(x)
+ if (x < 1)
+ fun_l21_n582(x)
+ else
+ fun_l21_n968(x)
+ end
+end
+
+def fun_l20_n309(x)
+ if (x < 1)
+ fun_l21_n7(x)
+ else
+ fun_l21_n703(x)
+ end
+end
+
+def fun_l20_n310(x)
+ if (x < 1)
+ fun_l21_n826(x)
+ else
+ fun_l21_n735(x)
+ end
+end
+
+def fun_l20_n311(x)
+ if (x < 1)
+ fun_l21_n856(x)
+ else
+ fun_l21_n959(x)
+ end
+end
+
+def fun_l20_n312(x)
+ if (x < 1)
+ fun_l21_n194(x)
+ else
+ fun_l21_n158(x)
+ end
+end
+
+def fun_l20_n313(x)
+ if (x < 1)
+ fun_l21_n690(x)
+ else
+ fun_l21_n813(x)
+ end
+end
+
+def fun_l20_n314(x)
+ if (x < 1)
+ fun_l21_n699(x)
+ else
+ fun_l21_n842(x)
+ end
+end
+
+def fun_l20_n315(x)
+ if (x < 1)
+ fun_l21_n485(x)
+ else
+ fun_l21_n0(x)
+ end
+end
+
+def fun_l20_n316(x)
+ if (x < 1)
+ fun_l21_n753(x)
+ else
+ fun_l21_n306(x)
+ end
+end
+
+def fun_l20_n317(x)
+ if (x < 1)
+ fun_l21_n516(x)
+ else
+ fun_l21_n35(x)
+ end
+end
+
+def fun_l20_n318(x)
+ if (x < 1)
+ fun_l21_n78(x)
+ else
+ fun_l21_n104(x)
+ end
+end
+
+def fun_l20_n319(x)
+ if (x < 1)
+ fun_l21_n492(x)
+ else
+ fun_l21_n211(x)
+ end
+end
+
+def fun_l20_n320(x)
+ if (x < 1)
+ fun_l21_n303(x)
+ else
+ fun_l21_n218(x)
+ end
+end
+
+def fun_l20_n321(x)
+ if (x < 1)
+ fun_l21_n614(x)
+ else
+ fun_l21_n743(x)
+ end
+end
+
+def fun_l20_n322(x)
+ if (x < 1)
+ fun_l21_n141(x)
+ else
+ fun_l21_n320(x)
+ end
+end
+
+def fun_l20_n323(x)
+ if (x < 1)
+ fun_l21_n349(x)
+ else
+ fun_l21_n396(x)
+ end
+end
+
+def fun_l20_n324(x)
+ if (x < 1)
+ fun_l21_n189(x)
+ else
+ fun_l21_n32(x)
+ end
+end
+
+def fun_l20_n325(x)
+ if (x < 1)
+ fun_l21_n938(x)
+ else
+ fun_l21_n747(x)
+ end
+end
+
+def fun_l20_n326(x)
+ if (x < 1)
+ fun_l21_n571(x)
+ else
+ fun_l21_n20(x)
+ end
+end
+
+def fun_l20_n327(x)
+ if (x < 1)
+ fun_l21_n905(x)
+ else
+ fun_l21_n106(x)
+ end
+end
+
+def fun_l20_n328(x)
+ if (x < 1)
+ fun_l21_n849(x)
+ else
+ fun_l21_n747(x)
+ end
+end
+
+def fun_l20_n329(x)
+ if (x < 1)
+ fun_l21_n830(x)
+ else
+ fun_l21_n61(x)
+ end
+end
+
+def fun_l20_n330(x)
+ if (x < 1)
+ fun_l21_n613(x)
+ else
+ fun_l21_n945(x)
+ end
+end
+
+def fun_l20_n331(x)
+ if (x < 1)
+ fun_l21_n379(x)
+ else
+ fun_l21_n920(x)
+ end
+end
+
+def fun_l20_n332(x)
+ if (x < 1)
+ fun_l21_n315(x)
+ else
+ fun_l21_n968(x)
+ end
+end
+
+def fun_l20_n333(x)
+ if (x < 1)
+ fun_l21_n256(x)
+ else
+ fun_l21_n460(x)
+ end
+end
+
+def fun_l20_n334(x)
+ if (x < 1)
+ fun_l21_n644(x)
+ else
+ fun_l21_n372(x)
+ end
+end
+
+def fun_l20_n335(x)
+ if (x < 1)
+ fun_l21_n588(x)
+ else
+ fun_l21_n351(x)
+ end
+end
+
+def fun_l20_n336(x)
+ if (x < 1)
+ fun_l21_n516(x)
+ else
+ fun_l21_n975(x)
+ end
+end
+
+def fun_l20_n337(x)
+ if (x < 1)
+ fun_l21_n432(x)
+ else
+ fun_l21_n47(x)
+ end
+end
+
+def fun_l20_n338(x)
+ if (x < 1)
+ fun_l21_n31(x)
+ else
+ fun_l21_n728(x)
+ end
+end
+
+def fun_l20_n339(x)
+ if (x < 1)
+ fun_l21_n700(x)
+ else
+ fun_l21_n454(x)
+ end
+end
+
+def fun_l20_n340(x)
+ if (x < 1)
+ fun_l21_n947(x)
+ else
+ fun_l21_n880(x)
+ end
+end
+
+def fun_l20_n341(x)
+ if (x < 1)
+ fun_l21_n363(x)
+ else
+ fun_l21_n861(x)
+ end
+end
+
+def fun_l20_n342(x)
+ if (x < 1)
+ fun_l21_n338(x)
+ else
+ fun_l21_n118(x)
+ end
+end
+
+def fun_l20_n343(x)
+ if (x < 1)
+ fun_l21_n352(x)
+ else
+ fun_l21_n402(x)
+ end
+end
+
+def fun_l20_n344(x)
+ if (x < 1)
+ fun_l21_n344(x)
+ else
+ fun_l21_n407(x)
+ end
+end
+
+def fun_l20_n345(x)
+ if (x < 1)
+ fun_l21_n869(x)
+ else
+ fun_l21_n912(x)
+ end
+end
+
+def fun_l20_n346(x)
+ if (x < 1)
+ fun_l21_n397(x)
+ else
+ fun_l21_n429(x)
+ end
+end
+
+def fun_l20_n347(x)
+ if (x < 1)
+ fun_l21_n28(x)
+ else
+ fun_l21_n671(x)
+ end
+end
+
+def fun_l20_n348(x)
+ if (x < 1)
+ fun_l21_n215(x)
+ else
+ fun_l21_n821(x)
+ end
+end
+
+def fun_l20_n349(x)
+ if (x < 1)
+ fun_l21_n432(x)
+ else
+ fun_l21_n250(x)
+ end
+end
+
+def fun_l20_n350(x)
+ if (x < 1)
+ fun_l21_n496(x)
+ else
+ fun_l21_n988(x)
+ end
+end
+
+def fun_l20_n351(x)
+ if (x < 1)
+ fun_l21_n317(x)
+ else
+ fun_l21_n516(x)
+ end
+end
+
+def fun_l20_n352(x)
+ if (x < 1)
+ fun_l21_n968(x)
+ else
+ fun_l21_n638(x)
+ end
+end
+
+def fun_l20_n353(x)
+ if (x < 1)
+ fun_l21_n447(x)
+ else
+ fun_l21_n14(x)
+ end
+end
+
+def fun_l20_n354(x)
+ if (x < 1)
+ fun_l21_n151(x)
+ else
+ fun_l21_n545(x)
+ end
+end
+
+def fun_l20_n355(x)
+ if (x < 1)
+ fun_l21_n579(x)
+ else
+ fun_l21_n934(x)
+ end
+end
+
+def fun_l20_n356(x)
+ if (x < 1)
+ fun_l21_n612(x)
+ else
+ fun_l21_n433(x)
+ end
+end
+
+def fun_l20_n357(x)
+ if (x < 1)
+ fun_l21_n969(x)
+ else
+ fun_l21_n816(x)
+ end
+end
+
+def fun_l20_n358(x)
+ if (x < 1)
+ fun_l21_n24(x)
+ else
+ fun_l21_n272(x)
+ end
+end
+
+def fun_l20_n359(x)
+ if (x < 1)
+ fun_l21_n945(x)
+ else
+ fun_l21_n458(x)
+ end
+end
+
+def fun_l20_n360(x)
+ if (x < 1)
+ fun_l21_n294(x)
+ else
+ fun_l21_n934(x)
+ end
+end
+
+def fun_l20_n361(x)
+ if (x < 1)
+ fun_l21_n777(x)
+ else
+ fun_l21_n499(x)
+ end
+end
+
+def fun_l20_n362(x)
+ if (x < 1)
+ fun_l21_n538(x)
+ else
+ fun_l21_n400(x)
+ end
+end
+
+def fun_l20_n363(x)
+ if (x < 1)
+ fun_l21_n660(x)
+ else
+ fun_l21_n970(x)
+ end
+end
+
+def fun_l20_n364(x)
+ if (x < 1)
+ fun_l21_n230(x)
+ else
+ fun_l21_n977(x)
+ end
+end
+
+def fun_l20_n365(x)
+ if (x < 1)
+ fun_l21_n335(x)
+ else
+ fun_l21_n436(x)
+ end
+end
+
+def fun_l20_n366(x)
+ if (x < 1)
+ fun_l21_n596(x)
+ else
+ fun_l21_n992(x)
+ end
+end
+
+def fun_l20_n367(x)
+ if (x < 1)
+ fun_l21_n502(x)
+ else
+ fun_l21_n251(x)
+ end
+end
+
+def fun_l20_n368(x)
+ if (x < 1)
+ fun_l21_n501(x)
+ else
+ fun_l21_n493(x)
+ end
+end
+
+def fun_l20_n369(x)
+ if (x < 1)
+ fun_l21_n48(x)
+ else
+ fun_l21_n850(x)
+ end
+end
+
+def fun_l20_n370(x)
+ if (x < 1)
+ fun_l21_n900(x)
+ else
+ fun_l21_n919(x)
+ end
+end
+
+def fun_l20_n371(x)
+ if (x < 1)
+ fun_l21_n349(x)
+ else
+ fun_l21_n80(x)
+ end
+end
+
+def fun_l20_n372(x)
+ if (x < 1)
+ fun_l21_n275(x)
+ else
+ fun_l21_n135(x)
+ end
+end
+
+def fun_l20_n373(x)
+ if (x < 1)
+ fun_l21_n987(x)
+ else
+ fun_l21_n472(x)
+ end
+end
+
+def fun_l20_n374(x)
+ if (x < 1)
+ fun_l21_n877(x)
+ else
+ fun_l21_n298(x)
+ end
+end
+
+def fun_l20_n375(x)
+ if (x < 1)
+ fun_l21_n518(x)
+ else
+ fun_l21_n676(x)
+ end
+end
+
+def fun_l20_n376(x)
+ if (x < 1)
+ fun_l21_n108(x)
+ else
+ fun_l21_n470(x)
+ end
+end
+
+def fun_l20_n377(x)
+ if (x < 1)
+ fun_l21_n643(x)
+ else
+ fun_l21_n189(x)
+ end
+end
+
+def fun_l20_n378(x)
+ if (x < 1)
+ fun_l21_n608(x)
+ else
+ fun_l21_n376(x)
+ end
+end
+
+def fun_l20_n379(x)
+ if (x < 1)
+ fun_l21_n520(x)
+ else
+ fun_l21_n651(x)
+ end
+end
+
+def fun_l20_n380(x)
+ if (x < 1)
+ fun_l21_n399(x)
+ else
+ fun_l21_n867(x)
+ end
+end
+
+def fun_l20_n381(x)
+ if (x < 1)
+ fun_l21_n815(x)
+ else
+ fun_l21_n78(x)
+ end
+end
+
+def fun_l20_n382(x)
+ if (x < 1)
+ fun_l21_n216(x)
+ else
+ fun_l21_n379(x)
+ end
+end
+
+def fun_l20_n383(x)
+ if (x < 1)
+ fun_l21_n628(x)
+ else
+ fun_l21_n227(x)
+ end
+end
+
+def fun_l20_n384(x)
+ if (x < 1)
+ fun_l21_n699(x)
+ else
+ fun_l21_n170(x)
+ end
+end
+
+def fun_l20_n385(x)
+ if (x < 1)
+ fun_l21_n444(x)
+ else
+ fun_l21_n603(x)
+ end
+end
+
+def fun_l20_n386(x)
+ if (x < 1)
+ fun_l21_n299(x)
+ else
+ fun_l21_n803(x)
+ end
+end
+
+def fun_l20_n387(x)
+ if (x < 1)
+ fun_l21_n708(x)
+ else
+ fun_l21_n187(x)
+ end
+end
+
+def fun_l20_n388(x)
+ if (x < 1)
+ fun_l21_n490(x)
+ else
+ fun_l21_n75(x)
+ end
+end
+
+def fun_l20_n389(x)
+ if (x < 1)
+ fun_l21_n856(x)
+ else
+ fun_l21_n257(x)
+ end
+end
+
+def fun_l20_n390(x)
+ if (x < 1)
+ fun_l21_n394(x)
+ else
+ fun_l21_n669(x)
+ end
+end
+
+def fun_l20_n391(x)
+ if (x < 1)
+ fun_l21_n501(x)
+ else
+ fun_l21_n555(x)
+ end
+end
+
+def fun_l20_n392(x)
+ if (x < 1)
+ fun_l21_n657(x)
+ else
+ fun_l21_n226(x)
+ end
+end
+
+def fun_l20_n393(x)
+ if (x < 1)
+ fun_l21_n229(x)
+ else
+ fun_l21_n898(x)
+ end
+end
+
+def fun_l20_n394(x)
+ if (x < 1)
+ fun_l21_n726(x)
+ else
+ fun_l21_n349(x)
+ end
+end
+
+def fun_l20_n395(x)
+ if (x < 1)
+ fun_l21_n247(x)
+ else
+ fun_l21_n996(x)
+ end
+end
+
+def fun_l20_n396(x)
+ if (x < 1)
+ fun_l21_n136(x)
+ else
+ fun_l21_n601(x)
+ end
+end
+
+def fun_l20_n397(x)
+ if (x < 1)
+ fun_l21_n365(x)
+ else
+ fun_l21_n203(x)
+ end
+end
+
+def fun_l20_n398(x)
+ if (x < 1)
+ fun_l21_n376(x)
+ else
+ fun_l21_n172(x)
+ end
+end
+
+def fun_l20_n399(x)
+ if (x < 1)
+ fun_l21_n23(x)
+ else
+ fun_l21_n577(x)
+ end
+end
+
+def fun_l20_n400(x)
+ if (x < 1)
+ fun_l21_n368(x)
+ else
+ fun_l21_n448(x)
+ end
+end
+
+def fun_l20_n401(x)
+ if (x < 1)
+ fun_l21_n934(x)
+ else
+ fun_l21_n949(x)
+ end
+end
+
+def fun_l20_n402(x)
+ if (x < 1)
+ fun_l21_n127(x)
+ else
+ fun_l21_n132(x)
+ end
+end
+
+def fun_l20_n403(x)
+ if (x < 1)
+ fun_l21_n133(x)
+ else
+ fun_l21_n389(x)
+ end
+end
+
+def fun_l20_n404(x)
+ if (x < 1)
+ fun_l21_n750(x)
+ else
+ fun_l21_n591(x)
+ end
+end
+
+def fun_l20_n405(x)
+ if (x < 1)
+ fun_l21_n492(x)
+ else
+ fun_l21_n763(x)
+ end
+end
+
+def fun_l20_n406(x)
+ if (x < 1)
+ fun_l21_n137(x)
+ else
+ fun_l21_n552(x)
+ end
+end
+
+def fun_l20_n407(x)
+ if (x < 1)
+ fun_l21_n200(x)
+ else
+ fun_l21_n537(x)
+ end
+end
+
+def fun_l20_n408(x)
+ if (x < 1)
+ fun_l21_n681(x)
+ else
+ fun_l21_n645(x)
+ end
+end
+
+def fun_l20_n409(x)
+ if (x < 1)
+ fun_l21_n86(x)
+ else
+ fun_l21_n239(x)
+ end
+end
+
+def fun_l20_n410(x)
+ if (x < 1)
+ fun_l21_n357(x)
+ else
+ fun_l21_n98(x)
+ end
+end
+
+def fun_l20_n411(x)
+ if (x < 1)
+ fun_l21_n889(x)
+ else
+ fun_l21_n199(x)
+ end
+end
+
+def fun_l20_n412(x)
+ if (x < 1)
+ fun_l21_n504(x)
+ else
+ fun_l21_n950(x)
+ end
+end
+
+def fun_l20_n413(x)
+ if (x < 1)
+ fun_l21_n220(x)
+ else
+ fun_l21_n351(x)
+ end
+end
+
+def fun_l20_n414(x)
+ if (x < 1)
+ fun_l21_n287(x)
+ else
+ fun_l21_n614(x)
+ end
+end
+
+def fun_l20_n415(x)
+ if (x < 1)
+ fun_l21_n699(x)
+ else
+ fun_l21_n464(x)
+ end
+end
+
+def fun_l20_n416(x)
+ if (x < 1)
+ fun_l21_n638(x)
+ else
+ fun_l21_n10(x)
+ end
+end
+
+def fun_l20_n417(x)
+ if (x < 1)
+ fun_l21_n52(x)
+ else
+ fun_l21_n348(x)
+ end
+end
+
+def fun_l20_n418(x)
+ if (x < 1)
+ fun_l21_n248(x)
+ else
+ fun_l21_n703(x)
+ end
+end
+
+def fun_l20_n419(x)
+ if (x < 1)
+ fun_l21_n430(x)
+ else
+ fun_l21_n886(x)
+ end
+end
+
+def fun_l20_n420(x)
+ if (x < 1)
+ fun_l21_n695(x)
+ else
+ fun_l21_n528(x)
+ end
+end
+
+def fun_l20_n421(x)
+ if (x < 1)
+ fun_l21_n545(x)
+ else
+ fun_l21_n521(x)
+ end
+end
+
+def fun_l20_n422(x)
+ if (x < 1)
+ fun_l21_n66(x)
+ else
+ fun_l21_n31(x)
+ end
+end
+
+def fun_l20_n423(x)
+ if (x < 1)
+ fun_l21_n411(x)
+ else
+ fun_l21_n476(x)
+ end
+end
+
+def fun_l20_n424(x)
+ if (x < 1)
+ fun_l21_n433(x)
+ else
+ fun_l21_n940(x)
+ end
+end
+
+def fun_l20_n425(x)
+ if (x < 1)
+ fun_l21_n622(x)
+ else
+ fun_l21_n817(x)
+ end
+end
+
+def fun_l20_n426(x)
+ if (x < 1)
+ fun_l21_n516(x)
+ else
+ fun_l21_n665(x)
+ end
+end
+
+def fun_l20_n427(x)
+ if (x < 1)
+ fun_l21_n828(x)
+ else
+ fun_l21_n47(x)
+ end
+end
+
+def fun_l20_n428(x)
+ if (x < 1)
+ fun_l21_n445(x)
+ else
+ fun_l21_n94(x)
+ end
+end
+
+def fun_l20_n429(x)
+ if (x < 1)
+ fun_l21_n799(x)
+ else
+ fun_l21_n676(x)
+ end
+end
+
+def fun_l20_n430(x)
+ if (x < 1)
+ fun_l21_n518(x)
+ else
+ fun_l21_n988(x)
+ end
+end
+
+def fun_l20_n431(x)
+ if (x < 1)
+ fun_l21_n787(x)
+ else
+ fun_l21_n127(x)
+ end
+end
+
+def fun_l20_n432(x)
+ if (x < 1)
+ fun_l21_n502(x)
+ else
+ fun_l21_n719(x)
+ end
+end
+
+def fun_l20_n433(x)
+ if (x < 1)
+ fun_l21_n406(x)
+ else
+ fun_l21_n828(x)
+ end
+end
+
+def fun_l20_n434(x)
+ if (x < 1)
+ fun_l21_n845(x)
+ else
+ fun_l21_n75(x)
+ end
+end
+
+def fun_l20_n435(x)
+ if (x < 1)
+ fun_l21_n425(x)
+ else
+ fun_l21_n449(x)
+ end
+end
+
+def fun_l20_n436(x)
+ if (x < 1)
+ fun_l21_n520(x)
+ else
+ fun_l21_n68(x)
+ end
+end
+
+def fun_l20_n437(x)
+ if (x < 1)
+ fun_l21_n872(x)
+ else
+ fun_l21_n978(x)
+ end
+end
+
+def fun_l20_n438(x)
+ if (x < 1)
+ fun_l21_n522(x)
+ else
+ fun_l21_n658(x)
+ end
+end
+
+def fun_l20_n439(x)
+ if (x < 1)
+ fun_l21_n976(x)
+ else
+ fun_l21_n224(x)
+ end
+end
+
+def fun_l20_n440(x)
+ if (x < 1)
+ fun_l21_n256(x)
+ else
+ fun_l21_n700(x)
+ end
+end
+
+def fun_l20_n441(x)
+ if (x < 1)
+ fun_l21_n722(x)
+ else
+ fun_l21_n348(x)
+ end
+end
+
+def fun_l20_n442(x)
+ if (x < 1)
+ fun_l21_n377(x)
+ else
+ fun_l21_n966(x)
+ end
+end
+
+def fun_l20_n443(x)
+ if (x < 1)
+ fun_l21_n519(x)
+ else
+ fun_l21_n611(x)
+ end
+end
+
+def fun_l20_n444(x)
+ if (x < 1)
+ fun_l21_n318(x)
+ else
+ fun_l21_n937(x)
+ end
+end
+
+def fun_l20_n445(x)
+ if (x < 1)
+ fun_l21_n416(x)
+ else
+ fun_l21_n874(x)
+ end
+end
+
+def fun_l20_n446(x)
+ if (x < 1)
+ fun_l21_n157(x)
+ else
+ fun_l21_n328(x)
+ end
+end
+
+def fun_l20_n447(x)
+ if (x < 1)
+ fun_l21_n540(x)
+ else
+ fun_l21_n906(x)
+ end
+end
+
+def fun_l20_n448(x)
+ if (x < 1)
+ fun_l21_n13(x)
+ else
+ fun_l21_n325(x)
+ end
+end
+
+def fun_l20_n449(x)
+ if (x < 1)
+ fun_l21_n771(x)
+ else
+ fun_l21_n929(x)
+ end
+end
+
+def fun_l20_n450(x)
+ if (x < 1)
+ fun_l21_n770(x)
+ else
+ fun_l21_n778(x)
+ end
+end
+
+def fun_l20_n451(x)
+ if (x < 1)
+ fun_l21_n939(x)
+ else
+ fun_l21_n493(x)
+ end
+end
+
+def fun_l20_n452(x)
+ if (x < 1)
+ fun_l21_n481(x)
+ else
+ fun_l21_n407(x)
+ end
+end
+
+def fun_l20_n453(x)
+ if (x < 1)
+ fun_l21_n759(x)
+ else
+ fun_l21_n322(x)
+ end
+end
+
+def fun_l20_n454(x)
+ if (x < 1)
+ fun_l21_n703(x)
+ else
+ fun_l21_n409(x)
+ end
+end
+
+def fun_l20_n455(x)
+ if (x < 1)
+ fun_l21_n394(x)
+ else
+ fun_l21_n415(x)
+ end
+end
+
+def fun_l20_n456(x)
+ if (x < 1)
+ fun_l21_n583(x)
+ else
+ fun_l21_n188(x)
+ end
+end
+
+def fun_l20_n457(x)
+ if (x < 1)
+ fun_l21_n668(x)
+ else
+ fun_l21_n46(x)
+ end
+end
+
+def fun_l20_n458(x)
+ if (x < 1)
+ fun_l21_n855(x)
+ else
+ fun_l21_n802(x)
+ end
+end
+
+def fun_l20_n459(x)
+ if (x < 1)
+ fun_l21_n720(x)
+ else
+ fun_l21_n691(x)
+ end
+end
+
+def fun_l20_n460(x)
+ if (x < 1)
+ fun_l21_n440(x)
+ else
+ fun_l21_n353(x)
+ end
+end
+
+def fun_l20_n461(x)
+ if (x < 1)
+ fun_l21_n604(x)
+ else
+ fun_l21_n872(x)
+ end
+end
+
+def fun_l20_n462(x)
+ if (x < 1)
+ fun_l21_n355(x)
+ else
+ fun_l21_n699(x)
+ end
+end
+
+def fun_l20_n463(x)
+ if (x < 1)
+ fun_l21_n476(x)
+ else
+ fun_l21_n447(x)
+ end
+end
+
+def fun_l20_n464(x)
+ if (x < 1)
+ fun_l21_n554(x)
+ else
+ fun_l21_n745(x)
+ end
+end
+
+def fun_l20_n465(x)
+ if (x < 1)
+ fun_l21_n632(x)
+ else
+ fun_l21_n281(x)
+ end
+end
+
+def fun_l20_n466(x)
+ if (x < 1)
+ fun_l21_n873(x)
+ else
+ fun_l21_n449(x)
+ end
+end
+
+def fun_l20_n467(x)
+ if (x < 1)
+ fun_l21_n90(x)
+ else
+ fun_l21_n933(x)
+ end
+end
+
+def fun_l20_n468(x)
+ if (x < 1)
+ fun_l21_n915(x)
+ else
+ fun_l21_n801(x)
+ end
+end
+
+def fun_l20_n469(x)
+ if (x < 1)
+ fun_l21_n429(x)
+ else
+ fun_l21_n139(x)
+ end
+end
+
+def fun_l20_n470(x)
+ if (x < 1)
+ fun_l21_n858(x)
+ else
+ fun_l21_n450(x)
+ end
+end
+
+def fun_l20_n471(x)
+ if (x < 1)
+ fun_l21_n556(x)
+ else
+ fun_l21_n109(x)
+ end
+end
+
+def fun_l20_n472(x)
+ if (x < 1)
+ fun_l21_n395(x)
+ else
+ fun_l21_n129(x)
+ end
+end
+
+def fun_l20_n473(x)
+ if (x < 1)
+ fun_l21_n282(x)
+ else
+ fun_l21_n277(x)
+ end
+end
+
+def fun_l20_n474(x)
+ if (x < 1)
+ fun_l21_n90(x)
+ else
+ fun_l21_n399(x)
+ end
+end
+
+def fun_l20_n475(x)
+ if (x < 1)
+ fun_l21_n719(x)
+ else
+ fun_l21_n698(x)
+ end
+end
+
+def fun_l20_n476(x)
+ if (x < 1)
+ fun_l21_n597(x)
+ else
+ fun_l21_n210(x)
+ end
+end
+
+def fun_l20_n477(x)
+ if (x < 1)
+ fun_l21_n722(x)
+ else
+ fun_l21_n31(x)
+ end
+end
+
+def fun_l20_n478(x)
+ if (x < 1)
+ fun_l21_n874(x)
+ else
+ fun_l21_n527(x)
+ end
+end
+
+def fun_l20_n479(x)
+ if (x < 1)
+ fun_l21_n247(x)
+ else
+ fun_l21_n164(x)
+ end
+end
+
+def fun_l20_n480(x)
+ if (x < 1)
+ fun_l21_n449(x)
+ else
+ fun_l21_n106(x)
+ end
+end
+
+def fun_l20_n481(x)
+ if (x < 1)
+ fun_l21_n787(x)
+ else
+ fun_l21_n678(x)
+ end
+end
+
+def fun_l20_n482(x)
+ if (x < 1)
+ fun_l21_n176(x)
+ else
+ fun_l21_n650(x)
+ end
+end
+
+def fun_l20_n483(x)
+ if (x < 1)
+ fun_l21_n314(x)
+ else
+ fun_l21_n325(x)
+ end
+end
+
+def fun_l20_n484(x)
+ if (x < 1)
+ fun_l21_n877(x)
+ else
+ fun_l21_n539(x)
+ end
+end
+
+def fun_l20_n485(x)
+ if (x < 1)
+ fun_l21_n230(x)
+ else
+ fun_l21_n314(x)
+ end
+end
+
+def fun_l20_n486(x)
+ if (x < 1)
+ fun_l21_n778(x)
+ else
+ fun_l21_n493(x)
+ end
+end
+
+def fun_l20_n487(x)
+ if (x < 1)
+ fun_l21_n615(x)
+ else
+ fun_l21_n111(x)
+ end
+end
+
+def fun_l20_n488(x)
+ if (x < 1)
+ fun_l21_n133(x)
+ else
+ fun_l21_n381(x)
+ end
+end
+
+def fun_l20_n489(x)
+ if (x < 1)
+ fun_l21_n332(x)
+ else
+ fun_l21_n68(x)
+ end
+end
+
+def fun_l20_n490(x)
+ if (x < 1)
+ fun_l21_n995(x)
+ else
+ fun_l21_n861(x)
+ end
+end
+
+def fun_l20_n491(x)
+ if (x < 1)
+ fun_l21_n537(x)
+ else
+ fun_l21_n164(x)
+ end
+end
+
+def fun_l20_n492(x)
+ if (x < 1)
+ fun_l21_n759(x)
+ else
+ fun_l21_n598(x)
+ end
+end
+
+def fun_l20_n493(x)
+ if (x < 1)
+ fun_l21_n890(x)
+ else
+ fun_l21_n644(x)
+ end
+end
+
+def fun_l20_n494(x)
+ if (x < 1)
+ fun_l21_n641(x)
+ else
+ fun_l21_n420(x)
+ end
+end
+
+def fun_l20_n495(x)
+ if (x < 1)
+ fun_l21_n826(x)
+ else
+ fun_l21_n821(x)
+ end
+end
+
+def fun_l20_n496(x)
+ if (x < 1)
+ fun_l21_n348(x)
+ else
+ fun_l21_n277(x)
+ end
+end
+
+def fun_l20_n497(x)
+ if (x < 1)
+ fun_l21_n14(x)
+ else
+ fun_l21_n950(x)
+ end
+end
+
+def fun_l20_n498(x)
+ if (x < 1)
+ fun_l21_n43(x)
+ else
+ fun_l21_n759(x)
+ end
+end
+
+def fun_l20_n499(x)
+ if (x < 1)
+ fun_l21_n899(x)
+ else
+ fun_l21_n730(x)
+ end
+end
+
+def fun_l20_n500(x)
+ if (x < 1)
+ fun_l21_n918(x)
+ else
+ fun_l21_n454(x)
+ end
+end
+
+def fun_l20_n501(x)
+ if (x < 1)
+ fun_l21_n821(x)
+ else
+ fun_l21_n388(x)
+ end
+end
+
+def fun_l20_n502(x)
+ if (x < 1)
+ fun_l21_n164(x)
+ else
+ fun_l21_n718(x)
+ end
+end
+
+def fun_l20_n503(x)
+ if (x < 1)
+ fun_l21_n152(x)
+ else
+ fun_l21_n613(x)
+ end
+end
+
+def fun_l20_n504(x)
+ if (x < 1)
+ fun_l21_n931(x)
+ else
+ fun_l21_n912(x)
+ end
+end
+
+def fun_l20_n505(x)
+ if (x < 1)
+ fun_l21_n655(x)
+ else
+ fun_l21_n38(x)
+ end
+end
+
+def fun_l20_n506(x)
+ if (x < 1)
+ fun_l21_n408(x)
+ else
+ fun_l21_n38(x)
+ end
+end
+
+def fun_l20_n507(x)
+ if (x < 1)
+ fun_l21_n960(x)
+ else
+ fun_l21_n857(x)
+ end
+end
+
+def fun_l20_n508(x)
+ if (x < 1)
+ fun_l21_n308(x)
+ else
+ fun_l21_n210(x)
+ end
+end
+
+def fun_l20_n509(x)
+ if (x < 1)
+ fun_l21_n985(x)
+ else
+ fun_l21_n537(x)
+ end
+end
+
+def fun_l20_n510(x)
+ if (x < 1)
+ fun_l21_n200(x)
+ else
+ fun_l21_n598(x)
+ end
+end
+
+def fun_l20_n511(x)
+ if (x < 1)
+ fun_l21_n451(x)
+ else
+ fun_l21_n958(x)
+ end
+end
+
+def fun_l20_n512(x)
+ if (x < 1)
+ fun_l21_n459(x)
+ else
+ fun_l21_n823(x)
+ end
+end
+
+def fun_l20_n513(x)
+ if (x < 1)
+ fun_l21_n153(x)
+ else
+ fun_l21_n931(x)
+ end
+end
+
+def fun_l20_n514(x)
+ if (x < 1)
+ fun_l21_n213(x)
+ else
+ fun_l21_n336(x)
+ end
+end
+
+def fun_l20_n515(x)
+ if (x < 1)
+ fun_l21_n401(x)
+ else
+ fun_l21_n222(x)
+ end
+end
+
+def fun_l20_n516(x)
+ if (x < 1)
+ fun_l21_n582(x)
+ else
+ fun_l21_n735(x)
+ end
+end
+
+def fun_l20_n517(x)
+ if (x < 1)
+ fun_l21_n799(x)
+ else
+ fun_l21_n139(x)
+ end
+end
+
+def fun_l20_n518(x)
+ if (x < 1)
+ fun_l21_n279(x)
+ else
+ fun_l21_n476(x)
+ end
+end
+
+def fun_l20_n519(x)
+ if (x < 1)
+ fun_l21_n624(x)
+ else
+ fun_l21_n276(x)
+ end
+end
+
+def fun_l20_n520(x)
+ if (x < 1)
+ fun_l21_n505(x)
+ else
+ fun_l21_n523(x)
+ end
+end
+
+def fun_l20_n521(x)
+ if (x < 1)
+ fun_l21_n887(x)
+ else
+ fun_l21_n948(x)
+ end
+end
+
+def fun_l20_n522(x)
+ if (x < 1)
+ fun_l21_n969(x)
+ else
+ fun_l21_n988(x)
+ end
+end
+
+def fun_l20_n523(x)
+ if (x < 1)
+ fun_l21_n271(x)
+ else
+ fun_l21_n189(x)
+ end
+end
+
+def fun_l20_n524(x)
+ if (x < 1)
+ fun_l21_n478(x)
+ else
+ fun_l21_n111(x)
+ end
+end
+
+def fun_l20_n525(x)
+ if (x < 1)
+ fun_l21_n808(x)
+ else
+ fun_l21_n256(x)
+ end
+end
+
+def fun_l20_n526(x)
+ if (x < 1)
+ fun_l21_n715(x)
+ else
+ fun_l21_n508(x)
+ end
+end
+
+def fun_l20_n527(x)
+ if (x < 1)
+ fun_l21_n819(x)
+ else
+ fun_l21_n670(x)
+ end
+end
+
+def fun_l20_n528(x)
+ if (x < 1)
+ fun_l21_n598(x)
+ else
+ fun_l21_n369(x)
+ end
+end
+
+def fun_l20_n529(x)
+ if (x < 1)
+ fun_l21_n391(x)
+ else
+ fun_l21_n651(x)
+ end
+end
+
+def fun_l20_n530(x)
+ if (x < 1)
+ fun_l21_n69(x)
+ else
+ fun_l21_n706(x)
+ end
+end
+
+def fun_l20_n531(x)
+ if (x < 1)
+ fun_l21_n786(x)
+ else
+ fun_l21_n289(x)
+ end
+end
+
+def fun_l20_n532(x)
+ if (x < 1)
+ fun_l21_n128(x)
+ else
+ fun_l21_n789(x)
+ end
+end
+
+def fun_l20_n533(x)
+ if (x < 1)
+ fun_l21_n935(x)
+ else
+ fun_l21_n29(x)
+ end
+end
+
+def fun_l20_n534(x)
+ if (x < 1)
+ fun_l21_n735(x)
+ else
+ fun_l21_n381(x)
+ end
+end
+
+def fun_l20_n535(x)
+ if (x < 1)
+ fun_l21_n299(x)
+ else
+ fun_l21_n932(x)
+ end
+end
+
+def fun_l20_n536(x)
+ if (x < 1)
+ fun_l21_n823(x)
+ else
+ fun_l21_n7(x)
+ end
+end
+
+def fun_l20_n537(x)
+ if (x < 1)
+ fun_l21_n152(x)
+ else
+ fun_l21_n758(x)
+ end
+end
+
+def fun_l20_n538(x)
+ if (x < 1)
+ fun_l21_n8(x)
+ else
+ fun_l21_n772(x)
+ end
+end
+
+def fun_l20_n539(x)
+ if (x < 1)
+ fun_l21_n900(x)
+ else
+ fun_l21_n984(x)
+ end
+end
+
+def fun_l20_n540(x)
+ if (x < 1)
+ fun_l21_n726(x)
+ else
+ fun_l21_n337(x)
+ end
+end
+
+def fun_l20_n541(x)
+ if (x < 1)
+ fun_l21_n557(x)
+ else
+ fun_l21_n998(x)
+ end
+end
+
+def fun_l20_n542(x)
+ if (x < 1)
+ fun_l21_n898(x)
+ else
+ fun_l21_n389(x)
+ end
+end
+
+def fun_l20_n543(x)
+ if (x < 1)
+ fun_l21_n71(x)
+ else
+ fun_l21_n276(x)
+ end
+end
+
+def fun_l20_n544(x)
+ if (x < 1)
+ fun_l21_n888(x)
+ else
+ fun_l21_n525(x)
+ end
+end
+
+def fun_l20_n545(x)
+ if (x < 1)
+ fun_l21_n797(x)
+ else
+ fun_l21_n487(x)
+ end
+end
+
+def fun_l20_n546(x)
+ if (x < 1)
+ fun_l21_n825(x)
+ else
+ fun_l21_n349(x)
+ end
+end
+
+def fun_l20_n547(x)
+ if (x < 1)
+ fun_l21_n538(x)
+ else
+ fun_l21_n817(x)
+ end
+end
+
+def fun_l20_n548(x)
+ if (x < 1)
+ fun_l21_n630(x)
+ else
+ fun_l21_n432(x)
+ end
+end
+
+def fun_l20_n549(x)
+ if (x < 1)
+ fun_l21_n553(x)
+ else
+ fun_l21_n179(x)
+ end
+end
+
+def fun_l20_n550(x)
+ if (x < 1)
+ fun_l21_n982(x)
+ else
+ fun_l21_n350(x)
+ end
+end
+
+def fun_l20_n551(x)
+ if (x < 1)
+ fun_l21_n404(x)
+ else
+ fun_l21_n313(x)
+ end
+end
+
+def fun_l20_n552(x)
+ if (x < 1)
+ fun_l21_n893(x)
+ else
+ fun_l21_n879(x)
+ end
+end
+
+def fun_l20_n553(x)
+ if (x < 1)
+ fun_l21_n360(x)
+ else
+ fun_l21_n403(x)
+ end
+end
+
+def fun_l20_n554(x)
+ if (x < 1)
+ fun_l21_n607(x)
+ else
+ fun_l21_n18(x)
+ end
+end
+
+def fun_l20_n555(x)
+ if (x < 1)
+ fun_l21_n269(x)
+ else
+ fun_l21_n514(x)
+ end
+end
+
+def fun_l20_n556(x)
+ if (x < 1)
+ fun_l21_n22(x)
+ else
+ fun_l21_n164(x)
+ end
+end
+
+def fun_l20_n557(x)
+ if (x < 1)
+ fun_l21_n560(x)
+ else
+ fun_l21_n671(x)
+ end
+end
+
+def fun_l20_n558(x)
+ if (x < 1)
+ fun_l21_n857(x)
+ else
+ fun_l21_n34(x)
+ end
+end
+
+def fun_l20_n559(x)
+ if (x < 1)
+ fun_l21_n750(x)
+ else
+ fun_l21_n267(x)
+ end
+end
+
+def fun_l20_n560(x)
+ if (x < 1)
+ fun_l21_n97(x)
+ else
+ fun_l21_n72(x)
+ end
+end
+
+def fun_l20_n561(x)
+ if (x < 1)
+ fun_l21_n482(x)
+ else
+ fun_l21_n644(x)
+ end
+end
+
+def fun_l20_n562(x)
+ if (x < 1)
+ fun_l21_n147(x)
+ else
+ fun_l21_n524(x)
+ end
+end
+
+def fun_l20_n563(x)
+ if (x < 1)
+ fun_l21_n509(x)
+ else
+ fun_l21_n124(x)
+ end
+end
+
+def fun_l20_n564(x)
+ if (x < 1)
+ fun_l21_n183(x)
+ else
+ fun_l21_n254(x)
+ end
+end
+
+def fun_l20_n565(x)
+ if (x < 1)
+ fun_l21_n919(x)
+ else
+ fun_l21_n727(x)
+ end
+end
+
+def fun_l20_n566(x)
+ if (x < 1)
+ fun_l21_n847(x)
+ else
+ fun_l21_n546(x)
+ end
+end
+
+def fun_l20_n567(x)
+ if (x < 1)
+ fun_l21_n214(x)
+ else
+ fun_l21_n692(x)
+ end
+end
+
+def fun_l20_n568(x)
+ if (x < 1)
+ fun_l21_n867(x)
+ else
+ fun_l21_n747(x)
+ end
+end
+
+def fun_l20_n569(x)
+ if (x < 1)
+ fun_l21_n277(x)
+ else
+ fun_l21_n130(x)
+ end
+end
+
+def fun_l20_n570(x)
+ if (x < 1)
+ fun_l21_n472(x)
+ else
+ fun_l21_n296(x)
+ end
+end
+
+def fun_l20_n571(x)
+ if (x < 1)
+ fun_l21_n633(x)
+ else
+ fun_l21_n704(x)
+ end
+end
+
+def fun_l20_n572(x)
+ if (x < 1)
+ fun_l21_n179(x)
+ else
+ fun_l21_n683(x)
+ end
+end
+
+def fun_l20_n573(x)
+ if (x < 1)
+ fun_l21_n607(x)
+ else
+ fun_l21_n140(x)
+ end
+end
+
+def fun_l20_n574(x)
+ if (x < 1)
+ fun_l21_n647(x)
+ else
+ fun_l21_n233(x)
+ end
+end
+
+def fun_l20_n575(x)
+ if (x < 1)
+ fun_l21_n992(x)
+ else
+ fun_l21_n951(x)
+ end
+end
+
+def fun_l20_n576(x)
+ if (x < 1)
+ fun_l21_n750(x)
+ else
+ fun_l21_n574(x)
+ end
+end
+
+def fun_l20_n577(x)
+ if (x < 1)
+ fun_l21_n116(x)
+ else
+ fun_l21_n488(x)
+ end
+end
+
+def fun_l20_n578(x)
+ if (x < 1)
+ fun_l21_n580(x)
+ else
+ fun_l21_n547(x)
+ end
+end
+
+def fun_l20_n579(x)
+ if (x < 1)
+ fun_l21_n576(x)
+ else
+ fun_l21_n744(x)
+ end
+end
+
+def fun_l20_n580(x)
+ if (x < 1)
+ fun_l21_n791(x)
+ else
+ fun_l21_n495(x)
+ end
+end
+
+def fun_l20_n581(x)
+ if (x < 1)
+ fun_l21_n188(x)
+ else
+ fun_l21_n795(x)
+ end
+end
+
+def fun_l20_n582(x)
+ if (x < 1)
+ fun_l21_n477(x)
+ else
+ fun_l21_n965(x)
+ end
+end
+
+def fun_l20_n583(x)
+ if (x < 1)
+ fun_l21_n436(x)
+ else
+ fun_l21_n169(x)
+ end
+end
+
+def fun_l20_n584(x)
+ if (x < 1)
+ fun_l21_n518(x)
+ else
+ fun_l21_n849(x)
+ end
+end
+
+def fun_l20_n585(x)
+ if (x < 1)
+ fun_l21_n747(x)
+ else
+ fun_l21_n882(x)
+ end
+end
+
+def fun_l20_n586(x)
+ if (x < 1)
+ fun_l21_n0(x)
+ else
+ fun_l21_n481(x)
+ end
+end
+
+def fun_l20_n587(x)
+ if (x < 1)
+ fun_l21_n876(x)
+ else
+ fun_l21_n279(x)
+ end
+end
+
+def fun_l20_n588(x)
+ if (x < 1)
+ fun_l21_n355(x)
+ else
+ fun_l21_n744(x)
+ end
+end
+
+def fun_l20_n589(x)
+ if (x < 1)
+ fun_l21_n408(x)
+ else
+ fun_l21_n27(x)
+ end
+end
+
+def fun_l20_n590(x)
+ if (x < 1)
+ fun_l21_n152(x)
+ else
+ fun_l21_n867(x)
+ end
+end
+
+def fun_l20_n591(x)
+ if (x < 1)
+ fun_l21_n543(x)
+ else
+ fun_l21_n193(x)
+ end
+end
+
+def fun_l20_n592(x)
+ if (x < 1)
+ fun_l21_n160(x)
+ else
+ fun_l21_n185(x)
+ end
+end
+
+def fun_l20_n593(x)
+ if (x < 1)
+ fun_l21_n613(x)
+ else
+ fun_l21_n403(x)
+ end
+end
+
+def fun_l20_n594(x)
+ if (x < 1)
+ fun_l21_n660(x)
+ else
+ fun_l21_n933(x)
+ end
+end
+
+def fun_l20_n595(x)
+ if (x < 1)
+ fun_l21_n222(x)
+ else
+ fun_l21_n922(x)
+ end
+end
+
+def fun_l20_n596(x)
+ if (x < 1)
+ fun_l21_n668(x)
+ else
+ fun_l21_n857(x)
+ end
+end
+
+def fun_l20_n597(x)
+ if (x < 1)
+ fun_l21_n846(x)
+ else
+ fun_l21_n164(x)
+ end
+end
+
+def fun_l20_n598(x)
+ if (x < 1)
+ fun_l21_n755(x)
+ else
+ fun_l21_n591(x)
+ end
+end
+
+def fun_l20_n599(x)
+ if (x < 1)
+ fun_l21_n224(x)
+ else
+ fun_l21_n390(x)
+ end
+end
+
+def fun_l20_n600(x)
+ if (x < 1)
+ fun_l21_n713(x)
+ else
+ fun_l21_n735(x)
+ end
+end
+
+def fun_l20_n601(x)
+ if (x < 1)
+ fun_l21_n551(x)
+ else
+ fun_l21_n57(x)
+ end
+end
+
+def fun_l20_n602(x)
+ if (x < 1)
+ fun_l21_n808(x)
+ else
+ fun_l21_n928(x)
+ end
+end
+
+def fun_l20_n603(x)
+ if (x < 1)
+ fun_l21_n471(x)
+ else
+ fun_l21_n436(x)
+ end
+end
+
+def fun_l20_n604(x)
+ if (x < 1)
+ fun_l21_n482(x)
+ else
+ fun_l21_n445(x)
+ end
+end
+
+def fun_l20_n605(x)
+ if (x < 1)
+ fun_l21_n680(x)
+ else
+ fun_l21_n433(x)
+ end
+end
+
+def fun_l20_n606(x)
+ if (x < 1)
+ fun_l21_n687(x)
+ else
+ fun_l21_n885(x)
+ end
+end
+
+def fun_l20_n607(x)
+ if (x < 1)
+ fun_l21_n370(x)
+ else
+ fun_l21_n414(x)
+ end
+end
+
+def fun_l20_n608(x)
+ if (x < 1)
+ fun_l21_n11(x)
+ else
+ fun_l21_n792(x)
+ end
+end
+
+def fun_l20_n609(x)
+ if (x < 1)
+ fun_l21_n490(x)
+ else
+ fun_l21_n947(x)
+ end
+end
+
+def fun_l20_n610(x)
+ if (x < 1)
+ fun_l21_n609(x)
+ else
+ fun_l21_n514(x)
+ end
+end
+
+def fun_l20_n611(x)
+ if (x < 1)
+ fun_l21_n873(x)
+ else
+ fun_l21_n247(x)
+ end
+end
+
+def fun_l20_n612(x)
+ if (x < 1)
+ fun_l21_n199(x)
+ else
+ fun_l21_n421(x)
+ end
+end
+
+def fun_l20_n613(x)
+ if (x < 1)
+ fun_l21_n807(x)
+ else
+ fun_l21_n905(x)
+ end
+end
+
+def fun_l20_n614(x)
+ if (x < 1)
+ fun_l21_n260(x)
+ else
+ fun_l21_n926(x)
+ end
+end
+
+def fun_l20_n615(x)
+ if (x < 1)
+ fun_l21_n288(x)
+ else
+ fun_l21_n944(x)
+ end
+end
+
+def fun_l20_n616(x)
+ if (x < 1)
+ fun_l21_n346(x)
+ else
+ fun_l21_n949(x)
+ end
+end
+
+def fun_l20_n617(x)
+ if (x < 1)
+ fun_l21_n243(x)
+ else
+ fun_l21_n527(x)
+ end
+end
+
+def fun_l20_n618(x)
+ if (x < 1)
+ fun_l21_n193(x)
+ else
+ fun_l21_n576(x)
+ end
+end
+
+def fun_l20_n619(x)
+ if (x < 1)
+ fun_l21_n861(x)
+ else
+ fun_l21_n19(x)
+ end
+end
+
+def fun_l20_n620(x)
+ if (x < 1)
+ fun_l21_n735(x)
+ else
+ fun_l21_n477(x)
+ end
+end
+
+def fun_l20_n621(x)
+ if (x < 1)
+ fun_l21_n368(x)
+ else
+ fun_l21_n250(x)
+ end
+end
+
+def fun_l20_n622(x)
+ if (x < 1)
+ fun_l21_n235(x)
+ else
+ fun_l21_n461(x)
+ end
+end
+
+def fun_l20_n623(x)
+ if (x < 1)
+ fun_l21_n289(x)
+ else
+ fun_l21_n217(x)
+ end
+end
+
+def fun_l20_n624(x)
+ if (x < 1)
+ fun_l21_n951(x)
+ else
+ fun_l21_n124(x)
+ end
+end
+
+def fun_l20_n625(x)
+ if (x < 1)
+ fun_l21_n590(x)
+ else
+ fun_l21_n163(x)
+ end
+end
+
+def fun_l20_n626(x)
+ if (x < 1)
+ fun_l21_n122(x)
+ else
+ fun_l21_n34(x)
+ end
+end
+
+def fun_l20_n627(x)
+ if (x < 1)
+ fun_l21_n139(x)
+ else
+ fun_l21_n452(x)
+ end
+end
+
+def fun_l20_n628(x)
+ if (x < 1)
+ fun_l21_n626(x)
+ else
+ fun_l21_n816(x)
+ end
+end
+
+def fun_l20_n629(x)
+ if (x < 1)
+ fun_l21_n713(x)
+ else
+ fun_l21_n291(x)
+ end
+end
+
+def fun_l20_n630(x)
+ if (x < 1)
+ fun_l21_n896(x)
+ else
+ fun_l21_n167(x)
+ end
+end
+
+def fun_l20_n631(x)
+ if (x < 1)
+ fun_l21_n461(x)
+ else
+ fun_l21_n965(x)
+ end
+end
+
+def fun_l20_n632(x)
+ if (x < 1)
+ fun_l21_n984(x)
+ else
+ fun_l21_n336(x)
+ end
+end
+
+def fun_l20_n633(x)
+ if (x < 1)
+ fun_l21_n525(x)
+ else
+ fun_l21_n500(x)
+ end
+end
+
+def fun_l20_n634(x)
+ if (x < 1)
+ fun_l21_n296(x)
+ else
+ fun_l21_n535(x)
+ end
+end
+
+def fun_l20_n635(x)
+ if (x < 1)
+ fun_l21_n961(x)
+ else
+ fun_l21_n296(x)
+ end
+end
+
+def fun_l20_n636(x)
+ if (x < 1)
+ fun_l21_n736(x)
+ else
+ fun_l21_n474(x)
+ end
+end
+
+def fun_l20_n637(x)
+ if (x < 1)
+ fun_l21_n942(x)
+ else
+ fun_l21_n503(x)
+ end
+end
+
+def fun_l20_n638(x)
+ if (x < 1)
+ fun_l21_n906(x)
+ else
+ fun_l21_n612(x)
+ end
+end
+
+def fun_l20_n639(x)
+ if (x < 1)
+ fun_l21_n152(x)
+ else
+ fun_l21_n772(x)
+ end
+end
+
+def fun_l20_n640(x)
+ if (x < 1)
+ fun_l21_n109(x)
+ else
+ fun_l21_n416(x)
+ end
+end
+
+def fun_l20_n641(x)
+ if (x < 1)
+ fun_l21_n189(x)
+ else
+ fun_l21_n353(x)
+ end
+end
+
+def fun_l20_n642(x)
+ if (x < 1)
+ fun_l21_n414(x)
+ else
+ fun_l21_n550(x)
+ end
+end
+
+def fun_l20_n643(x)
+ if (x < 1)
+ fun_l21_n469(x)
+ else
+ fun_l21_n542(x)
+ end
+end
+
+def fun_l20_n644(x)
+ if (x < 1)
+ fun_l21_n465(x)
+ else
+ fun_l21_n742(x)
+ end
+end
+
+def fun_l20_n645(x)
+ if (x < 1)
+ fun_l21_n139(x)
+ else
+ fun_l21_n138(x)
+ end
+end
+
+def fun_l20_n646(x)
+ if (x < 1)
+ fun_l21_n550(x)
+ else
+ fun_l21_n910(x)
+ end
+end
+
+def fun_l20_n647(x)
+ if (x < 1)
+ fun_l21_n939(x)
+ else
+ fun_l21_n347(x)
+ end
+end
+
+def fun_l20_n648(x)
+ if (x < 1)
+ fun_l21_n391(x)
+ else
+ fun_l21_n648(x)
+ end
+end
+
+def fun_l20_n649(x)
+ if (x < 1)
+ fun_l21_n690(x)
+ else
+ fun_l21_n627(x)
+ end
+end
+
+def fun_l20_n650(x)
+ if (x < 1)
+ fun_l21_n596(x)
+ else
+ fun_l21_n681(x)
+ end
+end
+
+def fun_l20_n651(x)
+ if (x < 1)
+ fun_l21_n686(x)
+ else
+ fun_l21_n399(x)
+ end
+end
+
+def fun_l20_n652(x)
+ if (x < 1)
+ fun_l21_n461(x)
+ else
+ fun_l21_n851(x)
+ end
+end
+
+def fun_l20_n653(x)
+ if (x < 1)
+ fun_l21_n562(x)
+ else
+ fun_l21_n60(x)
+ end
+end
+
+def fun_l20_n654(x)
+ if (x < 1)
+ fun_l21_n269(x)
+ else
+ fun_l21_n937(x)
+ end
+end
+
+def fun_l20_n655(x)
+ if (x < 1)
+ fun_l21_n994(x)
+ else
+ fun_l21_n386(x)
+ end
+end
+
+def fun_l20_n656(x)
+ if (x < 1)
+ fun_l21_n568(x)
+ else
+ fun_l21_n180(x)
+ end
+end
+
+def fun_l20_n657(x)
+ if (x < 1)
+ fun_l21_n334(x)
+ else
+ fun_l21_n362(x)
+ end
+end
+
+def fun_l20_n658(x)
+ if (x < 1)
+ fun_l21_n14(x)
+ else
+ fun_l21_n311(x)
+ end
+end
+
+def fun_l20_n659(x)
+ if (x < 1)
+ fun_l21_n715(x)
+ else
+ fun_l21_n945(x)
+ end
+end
+
+def fun_l20_n660(x)
+ if (x < 1)
+ fun_l21_n739(x)
+ else
+ fun_l21_n456(x)
+ end
+end
+
+def fun_l20_n661(x)
+ if (x < 1)
+ fun_l21_n298(x)
+ else
+ fun_l21_n344(x)
+ end
+end
+
+def fun_l20_n662(x)
+ if (x < 1)
+ fun_l21_n134(x)
+ else
+ fun_l21_n828(x)
+ end
+end
+
+def fun_l20_n663(x)
+ if (x < 1)
+ fun_l21_n831(x)
+ else
+ fun_l21_n231(x)
+ end
+end
+
+def fun_l20_n664(x)
+ if (x < 1)
+ fun_l21_n330(x)
+ else
+ fun_l21_n733(x)
+ end
+end
+
+def fun_l20_n665(x)
+ if (x < 1)
+ fun_l21_n22(x)
+ else
+ fun_l21_n973(x)
+ end
+end
+
+def fun_l20_n666(x)
+ if (x < 1)
+ fun_l21_n277(x)
+ else
+ fun_l21_n988(x)
+ end
+end
+
+def fun_l20_n667(x)
+ if (x < 1)
+ fun_l21_n252(x)
+ else
+ fun_l21_n8(x)
+ end
+end
+
+def fun_l20_n668(x)
+ if (x < 1)
+ fun_l21_n991(x)
+ else
+ fun_l21_n801(x)
+ end
+end
+
+def fun_l20_n669(x)
+ if (x < 1)
+ fun_l21_n811(x)
+ else
+ fun_l21_n660(x)
+ end
+end
+
+def fun_l20_n670(x)
+ if (x < 1)
+ fun_l21_n384(x)
+ else
+ fun_l21_n596(x)
+ end
+end
+
+def fun_l20_n671(x)
+ if (x < 1)
+ fun_l21_n509(x)
+ else
+ fun_l21_n133(x)
+ end
+end
+
+def fun_l20_n672(x)
+ if (x < 1)
+ fun_l21_n650(x)
+ else
+ fun_l21_n679(x)
+ end
+end
+
+def fun_l20_n673(x)
+ if (x < 1)
+ fun_l21_n323(x)
+ else
+ fun_l21_n824(x)
+ end
+end
+
+def fun_l20_n674(x)
+ if (x < 1)
+ fun_l21_n728(x)
+ else
+ fun_l21_n697(x)
+ end
+end
+
+def fun_l20_n675(x)
+ if (x < 1)
+ fun_l21_n367(x)
+ else
+ fun_l21_n383(x)
+ end
+end
+
+def fun_l20_n676(x)
+ if (x < 1)
+ fun_l21_n280(x)
+ else
+ fun_l21_n309(x)
+ end
+end
+
+def fun_l20_n677(x)
+ if (x < 1)
+ fun_l21_n17(x)
+ else
+ fun_l21_n687(x)
+ end
+end
+
+def fun_l20_n678(x)
+ if (x < 1)
+ fun_l21_n133(x)
+ else
+ fun_l21_n250(x)
+ end
+end
+
+def fun_l20_n679(x)
+ if (x < 1)
+ fun_l21_n713(x)
+ else
+ fun_l21_n630(x)
+ end
+end
+
+def fun_l20_n680(x)
+ if (x < 1)
+ fun_l21_n348(x)
+ else
+ fun_l21_n737(x)
+ end
+end
+
+def fun_l20_n681(x)
+ if (x < 1)
+ fun_l21_n450(x)
+ else
+ fun_l21_n283(x)
+ end
+end
+
+def fun_l20_n682(x)
+ if (x < 1)
+ fun_l21_n568(x)
+ else
+ fun_l21_n22(x)
+ end
+end
+
+def fun_l20_n683(x)
+ if (x < 1)
+ fun_l21_n173(x)
+ else
+ fun_l21_n457(x)
+ end
+end
+
+def fun_l20_n684(x)
+ if (x < 1)
+ fun_l21_n846(x)
+ else
+ fun_l21_n415(x)
+ end
+end
+
+def fun_l20_n685(x)
+ if (x < 1)
+ fun_l21_n757(x)
+ else
+ fun_l21_n817(x)
+ end
+end
+
+def fun_l20_n686(x)
+ if (x < 1)
+ fun_l21_n282(x)
+ else
+ fun_l21_n503(x)
+ end
+end
+
+def fun_l20_n687(x)
+ if (x < 1)
+ fun_l21_n337(x)
+ else
+ fun_l21_n407(x)
+ end
+end
+
+def fun_l20_n688(x)
+ if (x < 1)
+ fun_l21_n783(x)
+ else
+ fun_l21_n307(x)
+ end
+end
+
+def fun_l20_n689(x)
+ if (x < 1)
+ fun_l21_n397(x)
+ else
+ fun_l21_n10(x)
+ end
+end
+
+def fun_l20_n690(x)
+ if (x < 1)
+ fun_l21_n100(x)
+ else
+ fun_l21_n704(x)
+ end
+end
+
+def fun_l20_n691(x)
+ if (x < 1)
+ fun_l21_n380(x)
+ else
+ fun_l21_n780(x)
+ end
+end
+
+def fun_l20_n692(x)
+ if (x < 1)
+ fun_l21_n782(x)
+ else
+ fun_l21_n955(x)
+ end
+end
+
+def fun_l20_n693(x)
+ if (x < 1)
+ fun_l21_n40(x)
+ else
+ fun_l21_n599(x)
+ end
+end
+
+def fun_l20_n694(x)
+ if (x < 1)
+ fun_l21_n730(x)
+ else
+ fun_l21_n215(x)
+ end
+end
+
+def fun_l20_n695(x)
+ if (x < 1)
+ fun_l21_n168(x)
+ else
+ fun_l21_n757(x)
+ end
+end
+
+def fun_l20_n696(x)
+ if (x < 1)
+ fun_l21_n622(x)
+ else
+ fun_l21_n411(x)
+ end
+end
+
+def fun_l20_n697(x)
+ if (x < 1)
+ fun_l21_n958(x)
+ else
+ fun_l21_n832(x)
+ end
+end
+
+def fun_l20_n698(x)
+ if (x < 1)
+ fun_l21_n452(x)
+ else
+ fun_l21_n390(x)
+ end
+end
+
+def fun_l20_n699(x)
+ if (x < 1)
+ fun_l21_n669(x)
+ else
+ fun_l21_n642(x)
+ end
+end
+
+def fun_l20_n700(x)
+ if (x < 1)
+ fun_l21_n481(x)
+ else
+ fun_l21_n273(x)
+ end
+end
+
+def fun_l20_n701(x)
+ if (x < 1)
+ fun_l21_n305(x)
+ else
+ fun_l21_n783(x)
+ end
+end
+
+def fun_l20_n702(x)
+ if (x < 1)
+ fun_l21_n766(x)
+ else
+ fun_l21_n943(x)
+ end
+end
+
+def fun_l20_n703(x)
+ if (x < 1)
+ fun_l21_n440(x)
+ else
+ fun_l21_n875(x)
+ end
+end
+
+def fun_l20_n704(x)
+ if (x < 1)
+ fun_l21_n332(x)
+ else
+ fun_l21_n839(x)
+ end
+end
+
+def fun_l20_n705(x)
+ if (x < 1)
+ fun_l21_n459(x)
+ else
+ fun_l21_n341(x)
+ end
+end
+
+def fun_l20_n706(x)
+ if (x < 1)
+ fun_l21_n897(x)
+ else
+ fun_l21_n235(x)
+ end
+end
+
+def fun_l20_n707(x)
+ if (x < 1)
+ fun_l21_n400(x)
+ else
+ fun_l21_n349(x)
+ end
+end
+
+def fun_l20_n708(x)
+ if (x < 1)
+ fun_l21_n121(x)
+ else
+ fun_l21_n40(x)
+ end
+end
+
+def fun_l20_n709(x)
+ if (x < 1)
+ fun_l21_n496(x)
+ else
+ fun_l21_n473(x)
+ end
+end
+
+def fun_l20_n710(x)
+ if (x < 1)
+ fun_l21_n146(x)
+ else
+ fun_l21_n944(x)
+ end
+end
+
+def fun_l20_n711(x)
+ if (x < 1)
+ fun_l21_n497(x)
+ else
+ fun_l21_n322(x)
+ end
+end
+
+def fun_l20_n712(x)
+ if (x < 1)
+ fun_l21_n647(x)
+ else
+ fun_l21_n76(x)
+ end
+end
+
+def fun_l20_n713(x)
+ if (x < 1)
+ fun_l21_n402(x)
+ else
+ fun_l21_n904(x)
+ end
+end
+
+def fun_l20_n714(x)
+ if (x < 1)
+ fun_l21_n834(x)
+ else
+ fun_l21_n904(x)
+ end
+end
+
+def fun_l20_n715(x)
+ if (x < 1)
+ fun_l21_n482(x)
+ else
+ fun_l21_n399(x)
+ end
+end
+
+def fun_l20_n716(x)
+ if (x < 1)
+ fun_l21_n441(x)
+ else
+ fun_l21_n348(x)
+ end
+end
+
+def fun_l20_n717(x)
+ if (x < 1)
+ fun_l21_n577(x)
+ else
+ fun_l21_n815(x)
+ end
+end
+
+def fun_l20_n718(x)
+ if (x < 1)
+ fun_l21_n18(x)
+ else
+ fun_l21_n399(x)
+ end
+end
+
+def fun_l20_n719(x)
+ if (x < 1)
+ fun_l21_n245(x)
+ else
+ fun_l21_n928(x)
+ end
+end
+
+def fun_l20_n720(x)
+ if (x < 1)
+ fun_l21_n373(x)
+ else
+ fun_l21_n432(x)
+ end
+end
+
+def fun_l20_n721(x)
+ if (x < 1)
+ fun_l21_n20(x)
+ else
+ fun_l21_n485(x)
+ end
+end
+
+def fun_l20_n722(x)
+ if (x < 1)
+ fun_l21_n79(x)
+ else
+ fun_l21_n525(x)
+ end
+end
+
+def fun_l20_n723(x)
+ if (x < 1)
+ fun_l21_n474(x)
+ else
+ fun_l21_n706(x)
+ end
+end
+
+def fun_l20_n724(x)
+ if (x < 1)
+ fun_l21_n27(x)
+ else
+ fun_l21_n833(x)
+ end
+end
+
+def fun_l20_n725(x)
+ if (x < 1)
+ fun_l21_n386(x)
+ else
+ fun_l21_n422(x)
+ end
+end
+
+def fun_l20_n726(x)
+ if (x < 1)
+ fun_l21_n816(x)
+ else
+ fun_l21_n204(x)
+ end
+end
+
+def fun_l20_n727(x)
+ if (x < 1)
+ fun_l21_n502(x)
+ else
+ fun_l21_n554(x)
+ end
+end
+
+def fun_l20_n728(x)
+ if (x < 1)
+ fun_l21_n846(x)
+ else
+ fun_l21_n948(x)
+ end
+end
+
+def fun_l20_n729(x)
+ if (x < 1)
+ fun_l21_n308(x)
+ else
+ fun_l21_n408(x)
+ end
+end
+
+def fun_l20_n730(x)
+ if (x < 1)
+ fun_l21_n882(x)
+ else
+ fun_l21_n151(x)
+ end
+end
+
+def fun_l20_n731(x)
+ if (x < 1)
+ fun_l21_n22(x)
+ else
+ fun_l21_n839(x)
+ end
+end
+
+def fun_l20_n732(x)
+ if (x < 1)
+ fun_l21_n482(x)
+ else
+ fun_l21_n942(x)
+ end
+end
+
+def fun_l20_n733(x)
+ if (x < 1)
+ fun_l21_n959(x)
+ else
+ fun_l21_n615(x)
+ end
+end
+
+def fun_l20_n734(x)
+ if (x < 1)
+ fun_l21_n137(x)
+ else
+ fun_l21_n455(x)
+ end
+end
+
+def fun_l20_n735(x)
+ if (x < 1)
+ fun_l21_n388(x)
+ else
+ fun_l21_n362(x)
+ end
+end
+
+def fun_l20_n736(x)
+ if (x < 1)
+ fun_l21_n107(x)
+ else
+ fun_l21_n883(x)
+ end
+end
+
+def fun_l20_n737(x)
+ if (x < 1)
+ fun_l21_n42(x)
+ else
+ fun_l21_n288(x)
+ end
+end
+
+def fun_l20_n738(x)
+ if (x < 1)
+ fun_l21_n885(x)
+ else
+ fun_l21_n443(x)
+ end
+end
+
+def fun_l20_n739(x)
+ if (x < 1)
+ fun_l21_n414(x)
+ else
+ fun_l21_n976(x)
+ end
+end
+
+def fun_l20_n740(x)
+ if (x < 1)
+ fun_l21_n244(x)
+ else
+ fun_l21_n327(x)
+ end
+end
+
+def fun_l20_n741(x)
+ if (x < 1)
+ fun_l21_n832(x)
+ else
+ fun_l21_n951(x)
+ end
+end
+
+def fun_l20_n742(x)
+ if (x < 1)
+ fun_l21_n408(x)
+ else
+ fun_l21_n978(x)
+ end
+end
+
+def fun_l20_n743(x)
+ if (x < 1)
+ fun_l21_n517(x)
+ else
+ fun_l21_n468(x)
+ end
+end
+
+def fun_l20_n744(x)
+ if (x < 1)
+ fun_l21_n281(x)
+ else
+ fun_l21_n9(x)
+ end
+end
+
+def fun_l20_n745(x)
+ if (x < 1)
+ fun_l21_n488(x)
+ else
+ fun_l21_n526(x)
+ end
+end
+
+def fun_l20_n746(x)
+ if (x < 1)
+ fun_l21_n494(x)
+ else
+ fun_l21_n769(x)
+ end
+end
+
+def fun_l20_n747(x)
+ if (x < 1)
+ fun_l21_n277(x)
+ else
+ fun_l21_n103(x)
+ end
+end
+
+def fun_l20_n748(x)
+ if (x < 1)
+ fun_l21_n663(x)
+ else
+ fun_l21_n281(x)
+ end
+end
+
+def fun_l20_n749(x)
+ if (x < 1)
+ fun_l21_n260(x)
+ else
+ fun_l21_n320(x)
+ end
+end
+
+def fun_l20_n750(x)
+ if (x < 1)
+ fun_l21_n781(x)
+ else
+ fun_l21_n705(x)
+ end
+end
+
+def fun_l20_n751(x)
+ if (x < 1)
+ fun_l21_n317(x)
+ else
+ fun_l21_n728(x)
+ end
+end
+
+def fun_l20_n752(x)
+ if (x < 1)
+ fun_l21_n573(x)
+ else
+ fun_l21_n172(x)
+ end
+end
+
+def fun_l20_n753(x)
+ if (x < 1)
+ fun_l21_n352(x)
+ else
+ fun_l21_n933(x)
+ end
+end
+
+def fun_l20_n754(x)
+ if (x < 1)
+ fun_l21_n876(x)
+ else
+ fun_l21_n180(x)
+ end
+end
+
+def fun_l20_n755(x)
+ if (x < 1)
+ fun_l21_n937(x)
+ else
+ fun_l21_n387(x)
+ end
+end
+
+def fun_l20_n756(x)
+ if (x < 1)
+ fun_l21_n154(x)
+ else
+ fun_l21_n187(x)
+ end
+end
+
+def fun_l20_n757(x)
+ if (x < 1)
+ fun_l21_n766(x)
+ else
+ fun_l21_n259(x)
+ end
+end
+
+def fun_l20_n758(x)
+ if (x < 1)
+ fun_l21_n235(x)
+ else
+ fun_l21_n636(x)
+ end
+end
+
+def fun_l20_n759(x)
+ if (x < 1)
+ fun_l21_n872(x)
+ else
+ fun_l21_n913(x)
+ end
+end
+
+def fun_l20_n760(x)
+ if (x < 1)
+ fun_l21_n73(x)
+ else
+ fun_l21_n743(x)
+ end
+end
+
+def fun_l20_n761(x)
+ if (x < 1)
+ fun_l21_n666(x)
+ else
+ fun_l21_n777(x)
+ end
+end
+
+def fun_l20_n762(x)
+ if (x < 1)
+ fun_l21_n829(x)
+ else
+ fun_l21_n800(x)
+ end
+end
+
+def fun_l20_n763(x)
+ if (x < 1)
+ fun_l21_n37(x)
+ else
+ fun_l21_n152(x)
+ end
+end
+
+def fun_l20_n764(x)
+ if (x < 1)
+ fun_l21_n53(x)
+ else
+ fun_l21_n196(x)
+ end
+end
+
+def fun_l20_n765(x)
+ if (x < 1)
+ fun_l21_n511(x)
+ else
+ fun_l21_n415(x)
+ end
+end
+
+def fun_l20_n766(x)
+ if (x < 1)
+ fun_l21_n375(x)
+ else
+ fun_l21_n885(x)
+ end
+end
+
+def fun_l20_n767(x)
+ if (x < 1)
+ fun_l21_n267(x)
+ else
+ fun_l21_n597(x)
+ end
+end
+
+def fun_l20_n768(x)
+ if (x < 1)
+ fun_l21_n920(x)
+ else
+ fun_l21_n943(x)
+ end
+end
+
+def fun_l20_n769(x)
+ if (x < 1)
+ fun_l21_n585(x)
+ else
+ fun_l21_n659(x)
+ end
+end
+
+def fun_l20_n770(x)
+ if (x < 1)
+ fun_l21_n897(x)
+ else
+ fun_l21_n742(x)
+ end
+end
+
+def fun_l20_n771(x)
+ if (x < 1)
+ fun_l21_n41(x)
+ else
+ fun_l21_n431(x)
+ end
+end
+
+def fun_l20_n772(x)
+ if (x < 1)
+ fun_l21_n446(x)
+ else
+ fun_l21_n22(x)
+ end
+end
+
+def fun_l20_n773(x)
+ if (x < 1)
+ fun_l21_n918(x)
+ else
+ fun_l21_n387(x)
+ end
+end
+
+def fun_l20_n774(x)
+ if (x < 1)
+ fun_l21_n88(x)
+ else
+ fun_l21_n763(x)
+ end
+end
+
+def fun_l20_n775(x)
+ if (x < 1)
+ fun_l21_n224(x)
+ else
+ fun_l21_n886(x)
+ end
+end
+
+def fun_l20_n776(x)
+ if (x < 1)
+ fun_l21_n860(x)
+ else
+ fun_l21_n145(x)
+ end
+end
+
+def fun_l20_n777(x)
+ if (x < 1)
+ fun_l21_n198(x)
+ else
+ fun_l21_n593(x)
+ end
+end
+
+def fun_l20_n778(x)
+ if (x < 1)
+ fun_l21_n510(x)
+ else
+ fun_l21_n146(x)
+ end
+end
+
+def fun_l20_n779(x)
+ if (x < 1)
+ fun_l21_n125(x)
+ else
+ fun_l21_n390(x)
+ end
+end
+
+def fun_l20_n780(x)
+ if (x < 1)
+ fun_l21_n278(x)
+ else
+ fun_l21_n100(x)
+ end
+end
+
+def fun_l20_n781(x)
+ if (x < 1)
+ fun_l21_n9(x)
+ else
+ fun_l21_n312(x)
+ end
+end
+
+def fun_l20_n782(x)
+ if (x < 1)
+ fun_l21_n883(x)
+ else
+ fun_l21_n118(x)
+ end
+end
+
+def fun_l20_n783(x)
+ if (x < 1)
+ fun_l21_n314(x)
+ else
+ fun_l21_n357(x)
+ end
+end
+
+def fun_l20_n784(x)
+ if (x < 1)
+ fun_l21_n599(x)
+ else
+ fun_l21_n211(x)
+ end
+end
+
+def fun_l20_n785(x)
+ if (x < 1)
+ fun_l21_n882(x)
+ else
+ fun_l21_n903(x)
+ end
+end
+
+def fun_l20_n786(x)
+ if (x < 1)
+ fun_l21_n741(x)
+ else
+ fun_l21_n634(x)
+ end
+end
+
+def fun_l20_n787(x)
+ if (x < 1)
+ fun_l21_n186(x)
+ else
+ fun_l21_n68(x)
+ end
+end
+
+def fun_l20_n788(x)
+ if (x < 1)
+ fun_l21_n620(x)
+ else
+ fun_l21_n976(x)
+ end
+end
+
+def fun_l20_n789(x)
+ if (x < 1)
+ fun_l21_n692(x)
+ else
+ fun_l21_n8(x)
+ end
+end
+
+def fun_l20_n790(x)
+ if (x < 1)
+ fun_l21_n893(x)
+ else
+ fun_l21_n916(x)
+ end
+end
+
+def fun_l20_n791(x)
+ if (x < 1)
+ fun_l21_n823(x)
+ else
+ fun_l21_n498(x)
+ end
+end
+
+def fun_l20_n792(x)
+ if (x < 1)
+ fun_l21_n390(x)
+ else
+ fun_l21_n711(x)
+ end
+end
+
+def fun_l20_n793(x)
+ if (x < 1)
+ fun_l21_n918(x)
+ else
+ fun_l21_n819(x)
+ end
+end
+
+def fun_l20_n794(x)
+ if (x < 1)
+ fun_l21_n809(x)
+ else
+ fun_l21_n320(x)
+ end
+end
+
+def fun_l20_n795(x)
+ if (x < 1)
+ fun_l21_n387(x)
+ else
+ fun_l21_n377(x)
+ end
+end
+
+def fun_l20_n796(x)
+ if (x < 1)
+ fun_l21_n243(x)
+ else
+ fun_l21_n555(x)
+ end
+end
+
+def fun_l20_n797(x)
+ if (x < 1)
+ fun_l21_n946(x)
+ else
+ fun_l21_n811(x)
+ end
+end
+
+def fun_l20_n798(x)
+ if (x < 1)
+ fun_l21_n492(x)
+ else
+ fun_l21_n367(x)
+ end
+end
+
+def fun_l20_n799(x)
+ if (x < 1)
+ fun_l21_n161(x)
+ else
+ fun_l21_n818(x)
+ end
+end
+
+def fun_l20_n800(x)
+ if (x < 1)
+ fun_l21_n365(x)
+ else
+ fun_l21_n560(x)
+ end
+end
+
+def fun_l20_n801(x)
+ if (x < 1)
+ fun_l21_n456(x)
+ else
+ fun_l21_n880(x)
+ end
+end
+
+def fun_l20_n802(x)
+ if (x < 1)
+ fun_l21_n683(x)
+ else
+ fun_l21_n71(x)
+ end
+end
+
+def fun_l20_n803(x)
+ if (x < 1)
+ fun_l21_n250(x)
+ else
+ fun_l21_n183(x)
+ end
+end
+
+def fun_l20_n804(x)
+ if (x < 1)
+ fun_l21_n900(x)
+ else
+ fun_l21_n63(x)
+ end
+end
+
+def fun_l20_n805(x)
+ if (x < 1)
+ fun_l21_n798(x)
+ else
+ fun_l21_n91(x)
+ end
+end
+
+def fun_l20_n806(x)
+ if (x < 1)
+ fun_l21_n525(x)
+ else
+ fun_l21_n59(x)
+ end
+end
+
+def fun_l20_n807(x)
+ if (x < 1)
+ fun_l21_n515(x)
+ else
+ fun_l21_n457(x)
+ end
+end
+
+def fun_l20_n808(x)
+ if (x < 1)
+ fun_l21_n410(x)
+ else
+ fun_l21_n172(x)
+ end
+end
+
+def fun_l20_n809(x)
+ if (x < 1)
+ fun_l21_n194(x)
+ else
+ fun_l21_n425(x)
+ end
+end
+
+def fun_l20_n810(x)
+ if (x < 1)
+ fun_l21_n660(x)
+ else
+ fun_l21_n120(x)
+ end
+end
+
+def fun_l20_n811(x)
+ if (x < 1)
+ fun_l21_n920(x)
+ else
+ fun_l21_n97(x)
+ end
+end
+
+def fun_l20_n812(x)
+ if (x < 1)
+ fun_l21_n443(x)
+ else
+ fun_l21_n876(x)
+ end
+end
+
+def fun_l20_n813(x)
+ if (x < 1)
+ fun_l21_n935(x)
+ else
+ fun_l21_n186(x)
+ end
+end
+
+def fun_l20_n814(x)
+ if (x < 1)
+ fun_l21_n139(x)
+ else
+ fun_l21_n313(x)
+ end
+end
+
+def fun_l20_n815(x)
+ if (x < 1)
+ fun_l21_n21(x)
+ else
+ fun_l21_n500(x)
+ end
+end
+
+def fun_l20_n816(x)
+ if (x < 1)
+ fun_l21_n682(x)
+ else
+ fun_l21_n17(x)
+ end
+end
+
+def fun_l20_n817(x)
+ if (x < 1)
+ fun_l21_n945(x)
+ else
+ fun_l21_n472(x)
+ end
+end
+
+def fun_l20_n818(x)
+ if (x < 1)
+ fun_l21_n76(x)
+ else
+ fun_l21_n464(x)
+ end
+end
+
+def fun_l20_n819(x)
+ if (x < 1)
+ fun_l21_n696(x)
+ else
+ fun_l21_n989(x)
+ end
+end
+
+def fun_l20_n820(x)
+ if (x < 1)
+ fun_l21_n150(x)
+ else
+ fun_l21_n459(x)
+ end
+end
+
+def fun_l20_n821(x)
+ if (x < 1)
+ fun_l21_n280(x)
+ else
+ fun_l21_n535(x)
+ end
+end
+
+def fun_l20_n822(x)
+ if (x < 1)
+ fun_l21_n120(x)
+ else
+ fun_l21_n553(x)
+ end
+end
+
+def fun_l20_n823(x)
+ if (x < 1)
+ fun_l21_n450(x)
+ else
+ fun_l21_n168(x)
+ end
+end
+
+def fun_l20_n824(x)
+ if (x < 1)
+ fun_l21_n635(x)
+ else
+ fun_l21_n45(x)
+ end
+end
+
+def fun_l20_n825(x)
+ if (x < 1)
+ fun_l21_n245(x)
+ else
+ fun_l21_n491(x)
+ end
+end
+
+def fun_l20_n826(x)
+ if (x < 1)
+ fun_l21_n202(x)
+ else
+ fun_l21_n307(x)
+ end
+end
+
+def fun_l20_n827(x)
+ if (x < 1)
+ fun_l21_n883(x)
+ else
+ fun_l21_n113(x)
+ end
+end
+
+def fun_l20_n828(x)
+ if (x < 1)
+ fun_l21_n864(x)
+ else
+ fun_l21_n982(x)
+ end
+end
+
+def fun_l20_n829(x)
+ if (x < 1)
+ fun_l21_n707(x)
+ else
+ fun_l21_n909(x)
+ end
+end
+
+def fun_l20_n830(x)
+ if (x < 1)
+ fun_l21_n838(x)
+ else
+ fun_l21_n784(x)
+ end
+end
+
+def fun_l20_n831(x)
+ if (x < 1)
+ fun_l21_n179(x)
+ else
+ fun_l21_n445(x)
+ end
+end
+
+def fun_l20_n832(x)
+ if (x < 1)
+ fun_l21_n563(x)
+ else
+ fun_l21_n981(x)
+ end
+end
+
+def fun_l20_n833(x)
+ if (x < 1)
+ fun_l21_n441(x)
+ else
+ fun_l21_n911(x)
+ end
+end
+
+def fun_l20_n834(x)
+ if (x < 1)
+ fun_l21_n46(x)
+ else
+ fun_l21_n244(x)
+ end
+end
+
+def fun_l20_n835(x)
+ if (x < 1)
+ fun_l21_n740(x)
+ else
+ fun_l21_n877(x)
+ end
+end
+
+def fun_l20_n836(x)
+ if (x < 1)
+ fun_l21_n987(x)
+ else
+ fun_l21_n459(x)
+ end
+end
+
+def fun_l20_n837(x)
+ if (x < 1)
+ fun_l21_n51(x)
+ else
+ fun_l21_n533(x)
+ end
+end
+
+def fun_l20_n838(x)
+ if (x < 1)
+ fun_l21_n530(x)
+ else
+ fun_l21_n916(x)
+ end
+end
+
+def fun_l20_n839(x)
+ if (x < 1)
+ fun_l21_n644(x)
+ else
+ fun_l21_n574(x)
+ end
+end
+
+def fun_l20_n840(x)
+ if (x < 1)
+ fun_l21_n167(x)
+ else
+ fun_l21_n935(x)
+ end
+end
+
+def fun_l20_n841(x)
+ if (x < 1)
+ fun_l21_n657(x)
+ else
+ fun_l21_n914(x)
+ end
+end
+
+def fun_l20_n842(x)
+ if (x < 1)
+ fun_l21_n646(x)
+ else
+ fun_l21_n191(x)
+ end
+end
+
+def fun_l20_n843(x)
+ if (x < 1)
+ fun_l21_n881(x)
+ else
+ fun_l21_n744(x)
+ end
+end
+
+def fun_l20_n844(x)
+ if (x < 1)
+ fun_l21_n293(x)
+ else
+ fun_l21_n474(x)
+ end
+end
+
+def fun_l20_n845(x)
+ if (x < 1)
+ fun_l21_n481(x)
+ else
+ fun_l21_n80(x)
+ end
+end
+
+def fun_l20_n846(x)
+ if (x < 1)
+ fun_l21_n785(x)
+ else
+ fun_l21_n694(x)
+ end
+end
+
+def fun_l20_n847(x)
+ if (x < 1)
+ fun_l21_n874(x)
+ else
+ fun_l21_n465(x)
+ end
+end
+
+def fun_l20_n848(x)
+ if (x < 1)
+ fun_l21_n43(x)
+ else
+ fun_l21_n666(x)
+ end
+end
+
+def fun_l20_n849(x)
+ if (x < 1)
+ fun_l21_n868(x)
+ else
+ fun_l21_n272(x)
+ end
+end
+
+def fun_l20_n850(x)
+ if (x < 1)
+ fun_l21_n194(x)
+ else
+ fun_l21_n995(x)
+ end
+end
+
+def fun_l20_n851(x)
+ if (x < 1)
+ fun_l21_n989(x)
+ else
+ fun_l21_n385(x)
+ end
+end
+
+def fun_l20_n852(x)
+ if (x < 1)
+ fun_l21_n396(x)
+ else
+ fun_l21_n366(x)
+ end
+end
+
+def fun_l20_n853(x)
+ if (x < 1)
+ fun_l21_n439(x)
+ else
+ fun_l21_n141(x)
+ end
+end
+
+def fun_l20_n854(x)
+ if (x < 1)
+ fun_l21_n78(x)
+ else
+ fun_l21_n180(x)
+ end
+end
+
+def fun_l20_n855(x)
+ if (x < 1)
+ fun_l21_n203(x)
+ else
+ fun_l21_n382(x)
+ end
+end
+
+def fun_l20_n856(x)
+ if (x < 1)
+ fun_l21_n387(x)
+ else
+ fun_l21_n696(x)
+ end
+end
+
+def fun_l20_n857(x)
+ if (x < 1)
+ fun_l21_n383(x)
+ else
+ fun_l21_n655(x)
+ end
+end
+
+def fun_l20_n858(x)
+ if (x < 1)
+ fun_l21_n375(x)
+ else
+ fun_l21_n14(x)
+ end
+end
+
+def fun_l20_n859(x)
+ if (x < 1)
+ fun_l21_n418(x)
+ else
+ fun_l21_n435(x)
+ end
+end
+
+def fun_l20_n860(x)
+ if (x < 1)
+ fun_l21_n75(x)
+ else
+ fun_l21_n258(x)
+ end
+end
+
+def fun_l20_n861(x)
+ if (x < 1)
+ fun_l21_n509(x)
+ else
+ fun_l21_n585(x)
+ end
+end
+
+def fun_l20_n862(x)
+ if (x < 1)
+ fun_l21_n388(x)
+ else
+ fun_l21_n962(x)
+ end
+end
+
+def fun_l20_n863(x)
+ if (x < 1)
+ fun_l21_n826(x)
+ else
+ fun_l21_n691(x)
+ end
+end
+
+def fun_l20_n864(x)
+ if (x < 1)
+ fun_l21_n230(x)
+ else
+ fun_l21_n588(x)
+ end
+end
+
+def fun_l20_n865(x)
+ if (x < 1)
+ fun_l21_n138(x)
+ else
+ fun_l21_n779(x)
+ end
+end
+
+def fun_l20_n866(x)
+ if (x < 1)
+ fun_l21_n994(x)
+ else
+ fun_l21_n325(x)
+ end
+end
+
+def fun_l20_n867(x)
+ if (x < 1)
+ fun_l21_n169(x)
+ else
+ fun_l21_n384(x)
+ end
+end
+
+def fun_l20_n868(x)
+ if (x < 1)
+ fun_l21_n30(x)
+ else
+ fun_l21_n922(x)
+ end
+end
+
+def fun_l20_n869(x)
+ if (x < 1)
+ fun_l21_n500(x)
+ else
+ fun_l21_n896(x)
+ end
+end
+
+def fun_l20_n870(x)
+ if (x < 1)
+ fun_l21_n25(x)
+ else
+ fun_l21_n292(x)
+ end
+end
+
+def fun_l20_n871(x)
+ if (x < 1)
+ fun_l21_n266(x)
+ else
+ fun_l21_n58(x)
+ end
+end
+
+def fun_l20_n872(x)
+ if (x < 1)
+ fun_l21_n172(x)
+ else
+ fun_l21_n721(x)
+ end
+end
+
+def fun_l20_n873(x)
+ if (x < 1)
+ fun_l21_n87(x)
+ else
+ fun_l21_n717(x)
+ end
+end
+
+def fun_l20_n874(x)
+ if (x < 1)
+ fun_l21_n235(x)
+ else
+ fun_l21_n891(x)
+ end
+end
+
+def fun_l20_n875(x)
+ if (x < 1)
+ fun_l21_n87(x)
+ else
+ fun_l21_n810(x)
+ end
+end
+
+def fun_l20_n876(x)
+ if (x < 1)
+ fun_l21_n785(x)
+ else
+ fun_l21_n668(x)
+ end
+end
+
+def fun_l20_n877(x)
+ if (x < 1)
+ fun_l21_n532(x)
+ else
+ fun_l21_n505(x)
+ end
+end
+
+def fun_l20_n878(x)
+ if (x < 1)
+ fun_l21_n885(x)
+ else
+ fun_l21_n820(x)
+ end
+end
+
+def fun_l20_n879(x)
+ if (x < 1)
+ fun_l21_n986(x)
+ else
+ fun_l21_n916(x)
+ end
+end
+
+def fun_l20_n880(x)
+ if (x < 1)
+ fun_l21_n46(x)
+ else
+ fun_l21_n751(x)
+ end
+end
+
+def fun_l20_n881(x)
+ if (x < 1)
+ fun_l21_n964(x)
+ else
+ fun_l21_n829(x)
+ end
+end
+
+def fun_l20_n882(x)
+ if (x < 1)
+ fun_l21_n938(x)
+ else
+ fun_l21_n862(x)
+ end
+end
+
+def fun_l20_n883(x)
+ if (x < 1)
+ fun_l21_n880(x)
+ else
+ fun_l21_n548(x)
+ end
+end
+
+def fun_l20_n884(x)
+ if (x < 1)
+ fun_l21_n621(x)
+ else
+ fun_l21_n184(x)
+ end
+end
+
+def fun_l20_n885(x)
+ if (x < 1)
+ fun_l21_n587(x)
+ else
+ fun_l21_n603(x)
+ end
+end
+
+def fun_l20_n886(x)
+ if (x < 1)
+ fun_l21_n935(x)
+ else
+ fun_l21_n105(x)
+ end
+end
+
+def fun_l20_n887(x)
+ if (x < 1)
+ fun_l21_n76(x)
+ else
+ fun_l21_n96(x)
+ end
+end
+
+def fun_l20_n888(x)
+ if (x < 1)
+ fun_l21_n241(x)
+ else
+ fun_l21_n56(x)
+ end
+end
+
+def fun_l20_n889(x)
+ if (x < 1)
+ fun_l21_n180(x)
+ else
+ fun_l21_n360(x)
+ end
+end
+
+def fun_l20_n890(x)
+ if (x < 1)
+ fun_l21_n179(x)
+ else
+ fun_l21_n510(x)
+ end
+end
+
+def fun_l20_n891(x)
+ if (x < 1)
+ fun_l21_n641(x)
+ else
+ fun_l21_n70(x)
+ end
+end
+
+def fun_l20_n892(x)
+ if (x < 1)
+ fun_l21_n615(x)
+ else
+ fun_l21_n30(x)
+ end
+end
+
+def fun_l20_n893(x)
+ if (x < 1)
+ fun_l21_n787(x)
+ else
+ fun_l21_n914(x)
+ end
+end
+
+def fun_l20_n894(x)
+ if (x < 1)
+ fun_l21_n949(x)
+ else
+ fun_l21_n449(x)
+ end
+end
+
+def fun_l20_n895(x)
+ if (x < 1)
+ fun_l21_n182(x)
+ else
+ fun_l21_n935(x)
+ end
+end
+
+def fun_l20_n896(x)
+ if (x < 1)
+ fun_l21_n411(x)
+ else
+ fun_l21_n43(x)
+ end
+end
+
+def fun_l20_n897(x)
+ if (x < 1)
+ fun_l21_n70(x)
+ else
+ fun_l21_n363(x)
+ end
+end
+
+def fun_l20_n898(x)
+ if (x < 1)
+ fun_l21_n910(x)
+ else
+ fun_l21_n271(x)
+ end
+end
+
+def fun_l20_n899(x)
+ if (x < 1)
+ fun_l21_n722(x)
+ else
+ fun_l21_n793(x)
+ end
+end
+
+def fun_l20_n900(x)
+ if (x < 1)
+ fun_l21_n356(x)
+ else
+ fun_l21_n301(x)
+ end
+end
+
+def fun_l20_n901(x)
+ if (x < 1)
+ fun_l21_n915(x)
+ else
+ fun_l21_n373(x)
+ end
+end
+
+def fun_l20_n902(x)
+ if (x < 1)
+ fun_l21_n468(x)
+ else
+ fun_l21_n632(x)
+ end
+end
+
+def fun_l20_n903(x)
+ if (x < 1)
+ fun_l21_n970(x)
+ else
+ fun_l21_n54(x)
+ end
+end
+
+def fun_l20_n904(x)
+ if (x < 1)
+ fun_l21_n452(x)
+ else
+ fun_l21_n536(x)
+ end
+end
+
+def fun_l20_n905(x)
+ if (x < 1)
+ fun_l21_n223(x)
+ else
+ fun_l21_n423(x)
+ end
+end
+
+def fun_l20_n906(x)
+ if (x < 1)
+ fun_l21_n102(x)
+ else
+ fun_l21_n755(x)
+ end
+end
+
+def fun_l20_n907(x)
+ if (x < 1)
+ fun_l21_n537(x)
+ else
+ fun_l21_n84(x)
+ end
+end
+
+def fun_l20_n908(x)
+ if (x < 1)
+ fun_l21_n786(x)
+ else
+ fun_l21_n979(x)
+ end
+end
+
+def fun_l20_n909(x)
+ if (x < 1)
+ fun_l21_n573(x)
+ else
+ fun_l21_n965(x)
+ end
+end
+
+def fun_l20_n910(x)
+ if (x < 1)
+ fun_l21_n764(x)
+ else
+ fun_l21_n375(x)
+ end
+end
+
+def fun_l20_n911(x)
+ if (x < 1)
+ fun_l21_n673(x)
+ else
+ fun_l21_n545(x)
+ end
+end
+
+def fun_l20_n912(x)
+ if (x < 1)
+ fun_l21_n616(x)
+ else
+ fun_l21_n257(x)
+ end
+end
+
+def fun_l20_n913(x)
+ if (x < 1)
+ fun_l21_n276(x)
+ else
+ fun_l21_n670(x)
+ end
+end
+
+def fun_l20_n914(x)
+ if (x < 1)
+ fun_l21_n969(x)
+ else
+ fun_l21_n482(x)
+ end
+end
+
+def fun_l20_n915(x)
+ if (x < 1)
+ fun_l21_n603(x)
+ else
+ fun_l21_n916(x)
+ end
+end
+
+def fun_l20_n916(x)
+ if (x < 1)
+ fun_l21_n287(x)
+ else
+ fun_l21_n253(x)
+ end
+end
+
+def fun_l20_n917(x)
+ if (x < 1)
+ fun_l21_n201(x)
+ else
+ fun_l21_n175(x)
+ end
+end
+
+def fun_l20_n918(x)
+ if (x < 1)
+ fun_l21_n557(x)
+ else
+ fun_l21_n668(x)
+ end
+end
+
+def fun_l20_n919(x)
+ if (x < 1)
+ fun_l21_n598(x)
+ else
+ fun_l21_n85(x)
+ end
+end
+
+def fun_l20_n920(x)
+ if (x < 1)
+ fun_l21_n998(x)
+ else
+ fun_l21_n611(x)
+ end
+end
+
+def fun_l20_n921(x)
+ if (x < 1)
+ fun_l21_n22(x)
+ else
+ fun_l21_n76(x)
+ end
+end
+
+def fun_l20_n922(x)
+ if (x < 1)
+ fun_l21_n611(x)
+ else
+ fun_l21_n823(x)
+ end
+end
+
+def fun_l20_n923(x)
+ if (x < 1)
+ fun_l21_n739(x)
+ else
+ fun_l21_n231(x)
+ end
+end
+
+def fun_l20_n924(x)
+ if (x < 1)
+ fun_l21_n806(x)
+ else
+ fun_l21_n362(x)
+ end
+end
+
+def fun_l20_n925(x)
+ if (x < 1)
+ fun_l21_n32(x)
+ else
+ fun_l21_n593(x)
+ end
+end
+
+def fun_l20_n926(x)
+ if (x < 1)
+ fun_l21_n592(x)
+ else
+ fun_l21_n422(x)
+ end
+end
+
+def fun_l20_n927(x)
+ if (x < 1)
+ fun_l21_n624(x)
+ else
+ fun_l21_n690(x)
+ end
+end
+
+def fun_l20_n928(x)
+ if (x < 1)
+ fun_l21_n838(x)
+ else
+ fun_l21_n351(x)
+ end
+end
+
+def fun_l20_n929(x)
+ if (x < 1)
+ fun_l21_n289(x)
+ else
+ fun_l21_n842(x)
+ end
+end
+
+def fun_l20_n930(x)
+ if (x < 1)
+ fun_l21_n948(x)
+ else
+ fun_l21_n679(x)
+ end
+end
+
+def fun_l20_n931(x)
+ if (x < 1)
+ fun_l21_n746(x)
+ else
+ fun_l21_n267(x)
+ end
+end
+
+def fun_l20_n932(x)
+ if (x < 1)
+ fun_l21_n494(x)
+ else
+ fun_l21_n19(x)
+ end
+end
+
+def fun_l20_n933(x)
+ if (x < 1)
+ fun_l21_n8(x)
+ else
+ fun_l21_n234(x)
+ end
+end
+
+def fun_l20_n934(x)
+ if (x < 1)
+ fun_l21_n743(x)
+ else
+ fun_l21_n175(x)
+ end
+end
+
+def fun_l20_n935(x)
+ if (x < 1)
+ fun_l21_n111(x)
+ else
+ fun_l21_n300(x)
+ end
+end
+
+def fun_l20_n936(x)
+ if (x < 1)
+ fun_l21_n482(x)
+ else
+ fun_l21_n431(x)
+ end
+end
+
+def fun_l20_n937(x)
+ if (x < 1)
+ fun_l21_n885(x)
+ else
+ fun_l21_n523(x)
+ end
+end
+
+def fun_l20_n938(x)
+ if (x < 1)
+ fun_l21_n661(x)
+ else
+ fun_l21_n461(x)
+ end
+end
+
+def fun_l20_n939(x)
+ if (x < 1)
+ fun_l21_n809(x)
+ else
+ fun_l21_n868(x)
+ end
+end
+
+def fun_l20_n940(x)
+ if (x < 1)
+ fun_l21_n549(x)
+ else
+ fun_l21_n287(x)
+ end
+end
+
+def fun_l20_n941(x)
+ if (x < 1)
+ fun_l21_n246(x)
+ else
+ fun_l21_n228(x)
+ end
+end
+
+def fun_l20_n942(x)
+ if (x < 1)
+ fun_l21_n656(x)
+ else
+ fun_l21_n399(x)
+ end
+end
+
+def fun_l20_n943(x)
+ if (x < 1)
+ fun_l21_n344(x)
+ else
+ fun_l21_n77(x)
+ end
+end
+
+def fun_l20_n944(x)
+ if (x < 1)
+ fun_l21_n862(x)
+ else
+ fun_l21_n696(x)
+ end
+end
+
+def fun_l20_n945(x)
+ if (x < 1)
+ fun_l21_n892(x)
+ else
+ fun_l21_n782(x)
+ end
+end
+
+def fun_l20_n946(x)
+ if (x < 1)
+ fun_l21_n461(x)
+ else
+ fun_l21_n946(x)
+ end
+end
+
+def fun_l20_n947(x)
+ if (x < 1)
+ fun_l21_n576(x)
+ else
+ fun_l21_n216(x)
+ end
+end
+
+def fun_l20_n948(x)
+ if (x < 1)
+ fun_l21_n136(x)
+ else
+ fun_l21_n132(x)
+ end
+end
+
+def fun_l20_n949(x)
+ if (x < 1)
+ fun_l21_n987(x)
+ else
+ fun_l21_n615(x)
+ end
+end
+
+def fun_l20_n950(x)
+ if (x < 1)
+ fun_l21_n170(x)
+ else
+ fun_l21_n55(x)
+ end
+end
+
+def fun_l20_n951(x)
+ if (x < 1)
+ fun_l21_n260(x)
+ else
+ fun_l21_n675(x)
+ end
+end
+
+def fun_l20_n952(x)
+ if (x < 1)
+ fun_l21_n406(x)
+ else
+ fun_l21_n569(x)
+ end
+end
+
+def fun_l20_n953(x)
+ if (x < 1)
+ fun_l21_n41(x)
+ else
+ fun_l21_n951(x)
+ end
+end
+
+def fun_l20_n954(x)
+ if (x < 1)
+ fun_l21_n467(x)
+ else
+ fun_l21_n837(x)
+ end
+end
+
+def fun_l20_n955(x)
+ if (x < 1)
+ fun_l21_n41(x)
+ else
+ fun_l21_n349(x)
+ end
+end
+
+def fun_l20_n956(x)
+ if (x < 1)
+ fun_l21_n105(x)
+ else
+ fun_l21_n595(x)
+ end
+end
+
+def fun_l20_n957(x)
+ if (x < 1)
+ fun_l21_n132(x)
+ else
+ fun_l21_n622(x)
+ end
+end
+
+def fun_l20_n958(x)
+ if (x < 1)
+ fun_l21_n1(x)
+ else
+ fun_l21_n770(x)
+ end
+end
+
+def fun_l20_n959(x)
+ if (x < 1)
+ fun_l21_n768(x)
+ else
+ fun_l21_n979(x)
+ end
+end
+
+def fun_l20_n960(x)
+ if (x < 1)
+ fun_l21_n954(x)
+ else
+ fun_l21_n906(x)
+ end
+end
+
+def fun_l20_n961(x)
+ if (x < 1)
+ fun_l21_n759(x)
+ else
+ fun_l21_n381(x)
+ end
+end
+
+def fun_l20_n962(x)
+ if (x < 1)
+ fun_l21_n590(x)
+ else
+ fun_l21_n868(x)
+ end
+end
+
+def fun_l20_n963(x)
+ if (x < 1)
+ fun_l21_n119(x)
+ else
+ fun_l21_n962(x)
+ end
+end
+
+def fun_l20_n964(x)
+ if (x < 1)
+ fun_l21_n350(x)
+ else
+ fun_l21_n930(x)
+ end
+end
+
+def fun_l20_n965(x)
+ if (x < 1)
+ fun_l21_n542(x)
+ else
+ fun_l21_n217(x)
+ end
+end
+
+def fun_l20_n966(x)
+ if (x < 1)
+ fun_l21_n375(x)
+ else
+ fun_l21_n244(x)
+ end
+end
+
+def fun_l20_n967(x)
+ if (x < 1)
+ fun_l21_n160(x)
+ else
+ fun_l21_n610(x)
+ end
+end
+
+def fun_l20_n968(x)
+ if (x < 1)
+ fun_l21_n28(x)
+ else
+ fun_l21_n925(x)
+ end
+end
+
+def fun_l20_n969(x)
+ if (x < 1)
+ fun_l21_n661(x)
+ else
+ fun_l21_n944(x)
+ end
+end
+
+def fun_l20_n970(x)
+ if (x < 1)
+ fun_l21_n534(x)
+ else
+ fun_l21_n872(x)
+ end
+end
+
+def fun_l20_n971(x)
+ if (x < 1)
+ fun_l21_n684(x)
+ else
+ fun_l21_n271(x)
+ end
+end
+
+def fun_l20_n972(x)
+ if (x < 1)
+ fun_l21_n493(x)
+ else
+ fun_l21_n893(x)
+ end
+end
+
+def fun_l20_n973(x)
+ if (x < 1)
+ fun_l21_n912(x)
+ else
+ fun_l21_n385(x)
+ end
+end
+
+def fun_l20_n974(x)
+ if (x < 1)
+ fun_l21_n528(x)
+ else
+ fun_l21_n948(x)
+ end
+end
+
+def fun_l20_n975(x)
+ if (x < 1)
+ fun_l21_n263(x)
+ else
+ fun_l21_n362(x)
+ end
+end
+
+def fun_l20_n976(x)
+ if (x < 1)
+ fun_l21_n86(x)
+ else
+ fun_l21_n937(x)
+ end
+end
+
+def fun_l20_n977(x)
+ if (x < 1)
+ fun_l21_n886(x)
+ else
+ fun_l21_n845(x)
+ end
+end
+
+def fun_l20_n978(x)
+ if (x < 1)
+ fun_l21_n681(x)
+ else
+ fun_l21_n437(x)
+ end
+end
+
+def fun_l20_n979(x)
+ if (x < 1)
+ fun_l21_n342(x)
+ else
+ fun_l21_n333(x)
+ end
+end
+
+def fun_l20_n980(x)
+ if (x < 1)
+ fun_l21_n160(x)
+ else
+ fun_l21_n635(x)
+ end
+end
+
+def fun_l20_n981(x)
+ if (x < 1)
+ fun_l21_n580(x)
+ else
+ fun_l21_n895(x)
+ end
+end
+
+def fun_l20_n982(x)
+ if (x < 1)
+ fun_l21_n578(x)
+ else
+ fun_l21_n669(x)
+ end
+end
+
+def fun_l20_n983(x)
+ if (x < 1)
+ fun_l21_n939(x)
+ else
+ fun_l21_n321(x)
+ end
+end
+
+def fun_l20_n984(x)
+ if (x < 1)
+ fun_l21_n465(x)
+ else
+ fun_l21_n175(x)
+ end
+end
+
+def fun_l20_n985(x)
+ if (x < 1)
+ fun_l21_n522(x)
+ else
+ fun_l21_n108(x)
+ end
+end
+
+def fun_l20_n986(x)
+ if (x < 1)
+ fun_l21_n347(x)
+ else
+ fun_l21_n207(x)
+ end
+end
+
+def fun_l20_n987(x)
+ if (x < 1)
+ fun_l21_n844(x)
+ else
+ fun_l21_n39(x)
+ end
+end
+
+def fun_l20_n988(x)
+ if (x < 1)
+ fun_l21_n104(x)
+ else
+ fun_l21_n528(x)
+ end
+end
+
+def fun_l20_n989(x)
+ if (x < 1)
+ fun_l21_n486(x)
+ else
+ fun_l21_n443(x)
+ end
+end
+
+def fun_l20_n990(x)
+ if (x < 1)
+ fun_l21_n643(x)
+ else
+ fun_l21_n503(x)
+ end
+end
+
+def fun_l20_n991(x)
+ if (x < 1)
+ fun_l21_n428(x)
+ else
+ fun_l21_n813(x)
+ end
+end
+
+def fun_l20_n992(x)
+ if (x < 1)
+ fun_l21_n452(x)
+ else
+ fun_l21_n536(x)
+ end
+end
+
+def fun_l20_n993(x)
+ if (x < 1)
+ fun_l21_n247(x)
+ else
+ fun_l21_n961(x)
+ end
+end
+
+def fun_l20_n994(x)
+ if (x < 1)
+ fun_l21_n749(x)
+ else
+ fun_l21_n554(x)
+ end
+end
+
+def fun_l20_n995(x)
+ if (x < 1)
+ fun_l21_n333(x)
+ else
+ fun_l21_n162(x)
+ end
+end
+
+def fun_l20_n996(x)
+ if (x < 1)
+ fun_l21_n686(x)
+ else
+ fun_l21_n635(x)
+ end
+end
+
+def fun_l20_n997(x)
+ if (x < 1)
+ fun_l21_n709(x)
+ else
+ fun_l21_n953(x)
+ end
+end
+
+def fun_l20_n998(x)
+ if (x < 1)
+ fun_l21_n315(x)
+ else
+ fun_l21_n818(x)
+ end
+end
+
+def fun_l20_n999(x)
+ if (x < 1)
+ fun_l21_n543(x)
+ else
+ fun_l21_n385(x)
+ end
+end
+
+def fun_l21_n0(x)
+ if (x < 1)
+ fun_l22_n736(x)
+ else
+ fun_l22_n837(x)
+ end
+end
+
+def fun_l21_n1(x)
+ if (x < 1)
+ fun_l22_n333(x)
+ else
+ fun_l22_n358(x)
+ end
+end
+
+def fun_l21_n2(x)
+ if (x < 1)
+ fun_l22_n150(x)
+ else
+ fun_l22_n469(x)
+ end
+end
+
+def fun_l21_n3(x)
+ if (x < 1)
+ fun_l22_n899(x)
+ else
+ fun_l22_n917(x)
+ end
+end
+
+def fun_l21_n4(x)
+ if (x < 1)
+ fun_l22_n943(x)
+ else
+ fun_l22_n435(x)
+ end
+end
+
+def fun_l21_n5(x)
+ if (x < 1)
+ fun_l22_n56(x)
+ else
+ fun_l22_n123(x)
+ end
+end
+
+def fun_l21_n6(x)
+ if (x < 1)
+ fun_l22_n849(x)
+ else
+ fun_l22_n475(x)
+ end
+end
+
+def fun_l21_n7(x)
+ if (x < 1)
+ fun_l22_n931(x)
+ else
+ fun_l22_n529(x)
+ end
+end
+
+def fun_l21_n8(x)
+ if (x < 1)
+ fun_l22_n192(x)
+ else
+ fun_l22_n441(x)
+ end
+end
+
+def fun_l21_n9(x)
+ if (x < 1)
+ fun_l22_n84(x)
+ else
+ fun_l22_n428(x)
+ end
+end
+
+def fun_l21_n10(x)
+ if (x < 1)
+ fun_l22_n355(x)
+ else
+ fun_l22_n432(x)
+ end
+end
+
+def fun_l21_n11(x)
+ if (x < 1)
+ fun_l22_n380(x)
+ else
+ fun_l22_n739(x)
+ end
+end
+
+def fun_l21_n12(x)
+ if (x < 1)
+ fun_l22_n559(x)
+ else
+ fun_l22_n492(x)
+ end
+end
+
+def fun_l21_n13(x)
+ if (x < 1)
+ fun_l22_n542(x)
+ else
+ fun_l22_n284(x)
+ end
+end
+
+def fun_l21_n14(x)
+ if (x < 1)
+ fun_l22_n106(x)
+ else
+ fun_l22_n443(x)
+ end
+end
+
+def fun_l21_n15(x)
+ if (x < 1)
+ fun_l22_n769(x)
+ else
+ fun_l22_n111(x)
+ end
+end
+
+def fun_l21_n16(x)
+ if (x < 1)
+ fun_l22_n982(x)
+ else
+ fun_l22_n855(x)
+ end
+end
+
+def fun_l21_n17(x)
+ if (x < 1)
+ fun_l22_n994(x)
+ else
+ fun_l22_n952(x)
+ end
+end
+
+def fun_l21_n18(x)
+ if (x < 1)
+ fun_l22_n567(x)
+ else
+ fun_l22_n741(x)
+ end
+end
+
+def fun_l21_n19(x)
+ if (x < 1)
+ fun_l22_n851(x)
+ else
+ fun_l22_n830(x)
+ end
+end
+
+def fun_l21_n20(x)
+ if (x < 1)
+ fun_l22_n353(x)
+ else
+ fun_l22_n184(x)
+ end
+end
+
+def fun_l21_n21(x)
+ if (x < 1)
+ fun_l22_n891(x)
+ else
+ fun_l22_n629(x)
+ end
+end
+
+def fun_l21_n22(x)
+ if (x < 1)
+ fun_l22_n521(x)
+ else
+ fun_l22_n932(x)
+ end
+end
+
+def fun_l21_n23(x)
+ if (x < 1)
+ fun_l22_n834(x)
+ else
+ fun_l22_n913(x)
+ end
+end
+
+def fun_l21_n24(x)
+ if (x < 1)
+ fun_l22_n839(x)
+ else
+ fun_l22_n402(x)
+ end
+end
+
+def fun_l21_n25(x)
+ if (x < 1)
+ fun_l22_n525(x)
+ else
+ fun_l22_n247(x)
+ end
+end
+
+def fun_l21_n26(x)
+ if (x < 1)
+ fun_l22_n906(x)
+ else
+ fun_l22_n392(x)
+ end
+end
+
+def fun_l21_n27(x)
+ if (x < 1)
+ fun_l22_n716(x)
+ else
+ fun_l22_n804(x)
+ end
+end
+
+def fun_l21_n28(x)
+ if (x < 1)
+ fun_l22_n444(x)
+ else
+ fun_l22_n21(x)
+ end
+end
+
+def fun_l21_n29(x)
+ if (x < 1)
+ fun_l22_n674(x)
+ else
+ fun_l22_n695(x)
+ end
+end
+
+def fun_l21_n30(x)
+ if (x < 1)
+ fun_l22_n948(x)
+ else
+ fun_l22_n447(x)
+ end
+end
+
+def fun_l21_n31(x)
+ if (x < 1)
+ fun_l22_n460(x)
+ else
+ fun_l22_n743(x)
+ end
+end
+
+def fun_l21_n32(x)
+ if (x < 1)
+ fun_l22_n369(x)
+ else
+ fun_l22_n331(x)
+ end
+end
+
+def fun_l21_n33(x)
+ if (x < 1)
+ fun_l22_n602(x)
+ else
+ fun_l22_n934(x)
+ end
+end
+
+def fun_l21_n34(x)
+ if (x < 1)
+ fun_l22_n572(x)
+ else
+ fun_l22_n267(x)
+ end
+end
+
+def fun_l21_n35(x)
+ if (x < 1)
+ fun_l22_n517(x)
+ else
+ fun_l22_n298(x)
+ end
+end
+
+def fun_l21_n36(x)
+ if (x < 1)
+ fun_l22_n998(x)
+ else
+ fun_l22_n561(x)
+ end
+end
+
+def fun_l21_n37(x)
+ if (x < 1)
+ fun_l22_n457(x)
+ else
+ fun_l22_n513(x)
+ end
+end
+
+def fun_l21_n38(x)
+ if (x < 1)
+ fun_l22_n378(x)
+ else
+ fun_l22_n238(x)
+ end
+end
+
+def fun_l21_n39(x)
+ if (x < 1)
+ fun_l22_n788(x)
+ else
+ fun_l22_n45(x)
+ end
+end
+
+def fun_l21_n40(x)
+ if (x < 1)
+ fun_l22_n299(x)
+ else
+ fun_l22_n516(x)
+ end
+end
+
+def fun_l21_n41(x)
+ if (x < 1)
+ fun_l22_n454(x)
+ else
+ fun_l22_n274(x)
+ end
+end
+
+def fun_l21_n42(x)
+ if (x < 1)
+ fun_l22_n855(x)
+ else
+ fun_l22_n360(x)
+ end
+end
+
+def fun_l21_n43(x)
+ if (x < 1)
+ fun_l22_n577(x)
+ else
+ fun_l22_n213(x)
+ end
+end
+
+def fun_l21_n44(x)
+ if (x < 1)
+ fun_l22_n569(x)
+ else
+ fun_l22_n857(x)
+ end
+end
+
+def fun_l21_n45(x)
+ if (x < 1)
+ fun_l22_n667(x)
+ else
+ fun_l22_n285(x)
+ end
+end
+
+def fun_l21_n46(x)
+ if (x < 1)
+ fun_l22_n915(x)
+ else
+ fun_l22_n232(x)
+ end
+end
+
+def fun_l21_n47(x)
+ if (x < 1)
+ fun_l22_n124(x)
+ else
+ fun_l22_n708(x)
+ end
+end
+
+def fun_l21_n48(x)
+ if (x < 1)
+ fun_l22_n184(x)
+ else
+ fun_l22_n272(x)
+ end
+end
+
+def fun_l21_n49(x)
+ if (x < 1)
+ fun_l22_n376(x)
+ else
+ fun_l22_n138(x)
+ end
+end
+
+def fun_l21_n50(x)
+ if (x < 1)
+ fun_l22_n897(x)
+ else
+ fun_l22_n857(x)
+ end
+end
+
+def fun_l21_n51(x)
+ if (x < 1)
+ fun_l22_n335(x)
+ else
+ fun_l22_n614(x)
+ end
+end
+
+def fun_l21_n52(x)
+ if (x < 1)
+ fun_l22_n921(x)
+ else
+ fun_l22_n109(x)
+ end
+end
+
+def fun_l21_n53(x)
+ if (x < 1)
+ fun_l22_n27(x)
+ else
+ fun_l22_n609(x)
+ end
+end
+
+def fun_l21_n54(x)
+ if (x < 1)
+ fun_l22_n831(x)
+ else
+ fun_l22_n769(x)
+ end
+end
+
+def fun_l21_n55(x)
+ if (x < 1)
+ fun_l22_n936(x)
+ else
+ fun_l22_n250(x)
+ end
+end
+
+def fun_l21_n56(x)
+ if (x < 1)
+ fun_l22_n261(x)
+ else
+ fun_l22_n142(x)
+ end
+end
+
+def fun_l21_n57(x)
+ if (x < 1)
+ fun_l22_n721(x)
+ else
+ fun_l22_n604(x)
+ end
+end
+
+def fun_l21_n58(x)
+ if (x < 1)
+ fun_l22_n760(x)
+ else
+ fun_l22_n545(x)
+ end
+end
+
+def fun_l21_n59(x)
+ if (x < 1)
+ fun_l22_n934(x)
+ else
+ fun_l22_n110(x)
+ end
+end
+
+def fun_l21_n60(x)
+ if (x < 1)
+ fun_l22_n422(x)
+ else
+ fun_l22_n31(x)
+ end
+end
+
+def fun_l21_n61(x)
+ if (x < 1)
+ fun_l22_n776(x)
+ else
+ fun_l22_n251(x)
+ end
+end
+
+def fun_l21_n62(x)
+ if (x < 1)
+ fun_l22_n76(x)
+ else
+ fun_l22_n930(x)
+ end
+end
+
+def fun_l21_n63(x)
+ if (x < 1)
+ fun_l22_n331(x)
+ else
+ fun_l22_n550(x)
+ end
+end
+
+def fun_l21_n64(x)
+ if (x < 1)
+ fun_l22_n845(x)
+ else
+ fun_l22_n62(x)
+ end
+end
+
+def fun_l21_n65(x)
+ if (x < 1)
+ fun_l22_n887(x)
+ else
+ fun_l22_n784(x)
+ end
+end
+
+def fun_l21_n66(x)
+ if (x < 1)
+ fun_l22_n353(x)
+ else
+ fun_l22_n918(x)
+ end
+end
+
+def fun_l21_n67(x)
+ if (x < 1)
+ fun_l22_n682(x)
+ else
+ fun_l22_n840(x)
+ end
+end
+
+def fun_l21_n68(x)
+ if (x < 1)
+ fun_l22_n966(x)
+ else
+ fun_l22_n187(x)
+ end
+end
+
+def fun_l21_n69(x)
+ if (x < 1)
+ fun_l22_n424(x)
+ else
+ fun_l22_n674(x)
+ end
+end
+
+def fun_l21_n70(x)
+ if (x < 1)
+ fun_l22_n530(x)
+ else
+ fun_l22_n148(x)
+ end
+end
+
+def fun_l21_n71(x)
+ if (x < 1)
+ fun_l22_n616(x)
+ else
+ fun_l22_n945(x)
+ end
+end
+
+def fun_l21_n72(x)
+ if (x < 1)
+ fun_l22_n634(x)
+ else
+ fun_l22_n945(x)
+ end
+end
+
+def fun_l21_n73(x)
+ if (x < 1)
+ fun_l22_n153(x)
+ else
+ fun_l22_n657(x)
+ end
+end
+
+def fun_l21_n74(x)
+ if (x < 1)
+ fun_l22_n284(x)
+ else
+ fun_l22_n83(x)
+ end
+end
+
+def fun_l21_n75(x)
+ if (x < 1)
+ fun_l22_n292(x)
+ else
+ fun_l22_n440(x)
+ end
+end
+
+def fun_l21_n76(x)
+ if (x < 1)
+ fun_l22_n932(x)
+ else
+ fun_l22_n29(x)
+ end
+end
+
+def fun_l21_n77(x)
+ if (x < 1)
+ fun_l22_n292(x)
+ else
+ fun_l22_n866(x)
+ end
+end
+
+def fun_l21_n78(x)
+ if (x < 1)
+ fun_l22_n822(x)
+ else
+ fun_l22_n838(x)
+ end
+end
+
+def fun_l21_n79(x)
+ if (x < 1)
+ fun_l22_n297(x)
+ else
+ fun_l22_n677(x)
+ end
+end
+
+def fun_l21_n80(x)
+ if (x < 1)
+ fun_l22_n540(x)
+ else
+ fun_l22_n975(x)
+ end
+end
+
+def fun_l21_n81(x)
+ if (x < 1)
+ fun_l22_n375(x)
+ else
+ fun_l22_n735(x)
+ end
+end
+
+def fun_l21_n82(x)
+ if (x < 1)
+ fun_l22_n549(x)
+ else
+ fun_l22_n844(x)
+ end
+end
+
+def fun_l21_n83(x)
+ if (x < 1)
+ fun_l22_n763(x)
+ else
+ fun_l22_n863(x)
+ end
+end
+
+def fun_l21_n84(x)
+ if (x < 1)
+ fun_l22_n993(x)
+ else
+ fun_l22_n155(x)
+ end
+end
+
+def fun_l21_n85(x)
+ if (x < 1)
+ fun_l22_n751(x)
+ else
+ fun_l22_n264(x)
+ end
+end
+
+def fun_l21_n86(x)
+ if (x < 1)
+ fun_l22_n517(x)
+ else
+ fun_l22_n752(x)
+ end
+end
+
+def fun_l21_n87(x)
+ if (x < 1)
+ fun_l22_n477(x)
+ else
+ fun_l22_n486(x)
+ end
+end
+
+def fun_l21_n88(x)
+ if (x < 1)
+ fun_l22_n220(x)
+ else
+ fun_l22_n4(x)
+ end
+end
+
+def fun_l21_n89(x)
+ if (x < 1)
+ fun_l22_n678(x)
+ else
+ fun_l22_n692(x)
+ end
+end
+
+def fun_l21_n90(x)
+ if (x < 1)
+ fun_l22_n75(x)
+ else
+ fun_l22_n306(x)
+ end
+end
+
+def fun_l21_n91(x)
+ if (x < 1)
+ fun_l22_n460(x)
+ else
+ fun_l22_n514(x)
+ end
+end
+
+def fun_l21_n92(x)
+ if (x < 1)
+ fun_l22_n446(x)
+ else
+ fun_l22_n201(x)
+ end
+end
+
+def fun_l21_n93(x)
+ if (x < 1)
+ fun_l22_n872(x)
+ else
+ fun_l22_n611(x)
+ end
+end
+
+def fun_l21_n94(x)
+ if (x < 1)
+ fun_l22_n809(x)
+ else
+ fun_l22_n91(x)
+ end
+end
+
+def fun_l21_n95(x)
+ if (x < 1)
+ fun_l22_n565(x)
+ else
+ fun_l22_n968(x)
+ end
+end
+
+def fun_l21_n96(x)
+ if (x < 1)
+ fun_l22_n765(x)
+ else
+ fun_l22_n622(x)
+ end
+end
+
+def fun_l21_n97(x)
+ if (x < 1)
+ fun_l22_n856(x)
+ else
+ fun_l22_n923(x)
+ end
+end
+
+def fun_l21_n98(x)
+ if (x < 1)
+ fun_l22_n14(x)
+ else
+ fun_l22_n742(x)
+ end
+end
+
+def fun_l21_n99(x)
+ if (x < 1)
+ fun_l22_n214(x)
+ else
+ fun_l22_n118(x)
+ end
+end
+
+def fun_l21_n100(x)
+ if (x < 1)
+ fun_l22_n992(x)
+ else
+ fun_l22_n610(x)
+ end
+end
+
+def fun_l21_n101(x)
+ if (x < 1)
+ fun_l22_n603(x)
+ else
+ fun_l22_n208(x)
+ end
+end
+
+def fun_l21_n102(x)
+ if (x < 1)
+ fun_l22_n647(x)
+ else
+ fun_l22_n753(x)
+ end
+end
+
+def fun_l21_n103(x)
+ if (x < 1)
+ fun_l22_n952(x)
+ else
+ fun_l22_n25(x)
+ end
+end
+
+def fun_l21_n104(x)
+ if (x < 1)
+ fun_l22_n635(x)
+ else
+ fun_l22_n381(x)
+ end
+end
+
+def fun_l21_n105(x)
+ if (x < 1)
+ fun_l22_n258(x)
+ else
+ fun_l22_n346(x)
+ end
+end
+
+def fun_l21_n106(x)
+ if (x < 1)
+ fun_l22_n732(x)
+ else
+ fun_l22_n851(x)
+ end
+end
+
+def fun_l21_n107(x)
+ if (x < 1)
+ fun_l22_n67(x)
+ else
+ fun_l22_n80(x)
+ end
+end
+
+def fun_l21_n108(x)
+ if (x < 1)
+ fun_l22_n237(x)
+ else
+ fun_l22_n600(x)
+ end
+end
+
+def fun_l21_n109(x)
+ if (x < 1)
+ fun_l22_n448(x)
+ else
+ fun_l22_n768(x)
+ end
+end
+
+def fun_l21_n110(x)
+ if (x < 1)
+ fun_l22_n52(x)
+ else
+ fun_l22_n849(x)
+ end
+end
+
+def fun_l21_n111(x)
+ if (x < 1)
+ fun_l22_n471(x)
+ else
+ fun_l22_n400(x)
+ end
+end
+
+def fun_l21_n112(x)
+ if (x < 1)
+ fun_l22_n655(x)
+ else
+ fun_l22_n691(x)
+ end
+end
+
+def fun_l21_n113(x)
+ if (x < 1)
+ fun_l22_n325(x)
+ else
+ fun_l22_n936(x)
+ end
+end
+
+def fun_l21_n114(x)
+ if (x < 1)
+ fun_l22_n693(x)
+ else
+ fun_l22_n118(x)
+ end
+end
+
+def fun_l21_n115(x)
+ if (x < 1)
+ fun_l22_n881(x)
+ else
+ fun_l22_n167(x)
+ end
+end
+
+def fun_l21_n116(x)
+ if (x < 1)
+ fun_l22_n958(x)
+ else
+ fun_l22_n36(x)
+ end
+end
+
+def fun_l21_n117(x)
+ if (x < 1)
+ fun_l22_n233(x)
+ else
+ fun_l22_n649(x)
+ end
+end
+
+def fun_l21_n118(x)
+ if (x < 1)
+ fun_l22_n847(x)
+ else
+ fun_l22_n544(x)
+ end
+end
+
+def fun_l21_n119(x)
+ if (x < 1)
+ fun_l22_n392(x)
+ else
+ fun_l22_n2(x)
+ end
+end
+
+def fun_l21_n120(x)
+ if (x < 1)
+ fun_l22_n750(x)
+ else
+ fun_l22_n481(x)
+ end
+end
+
+def fun_l21_n121(x)
+ if (x < 1)
+ fun_l22_n124(x)
+ else
+ fun_l22_n769(x)
+ end
+end
+
+def fun_l21_n122(x)
+ if (x < 1)
+ fun_l22_n483(x)
+ else
+ fun_l22_n147(x)
+ end
+end
+
+def fun_l21_n123(x)
+ if (x < 1)
+ fun_l22_n543(x)
+ else
+ fun_l22_n454(x)
+ end
+end
+
+def fun_l21_n124(x)
+ if (x < 1)
+ fun_l22_n24(x)
+ else
+ fun_l22_n815(x)
+ end
+end
+
+def fun_l21_n125(x)
+ if (x < 1)
+ fun_l22_n315(x)
+ else
+ fun_l22_n263(x)
+ end
+end
+
+def fun_l21_n126(x)
+ if (x < 1)
+ fun_l22_n934(x)
+ else
+ fun_l22_n351(x)
+ end
+end
+
+def fun_l21_n127(x)
+ if (x < 1)
+ fun_l22_n982(x)
+ else
+ fun_l22_n755(x)
+ end
+end
+
+def fun_l21_n128(x)
+ if (x < 1)
+ fun_l22_n146(x)
+ else
+ fun_l22_n345(x)
+ end
+end
+
+def fun_l21_n129(x)
+ if (x < 1)
+ fun_l22_n85(x)
+ else
+ fun_l22_n356(x)
+ end
+end
+
+def fun_l21_n130(x)
+ if (x < 1)
+ fun_l22_n987(x)
+ else
+ fun_l22_n103(x)
+ end
+end
+
+def fun_l21_n131(x)
+ if (x < 1)
+ fun_l22_n413(x)
+ else
+ fun_l22_n260(x)
+ end
+end
+
+def fun_l21_n132(x)
+ if (x < 1)
+ fun_l22_n615(x)
+ else
+ fun_l22_n742(x)
+ end
+end
+
+def fun_l21_n133(x)
+ if (x < 1)
+ fun_l22_n836(x)
+ else
+ fun_l22_n214(x)
+ end
+end
+
+def fun_l21_n134(x)
+ if (x < 1)
+ fun_l22_n85(x)
+ else
+ fun_l22_n916(x)
+ end
+end
+
+def fun_l21_n135(x)
+ if (x < 1)
+ fun_l22_n21(x)
+ else
+ fun_l22_n902(x)
+ end
+end
+
+def fun_l21_n136(x)
+ if (x < 1)
+ fun_l22_n842(x)
+ else
+ fun_l22_n475(x)
+ end
+end
+
+def fun_l21_n137(x)
+ if (x < 1)
+ fun_l22_n573(x)
+ else
+ fun_l22_n108(x)
+ end
+end
+
+def fun_l21_n138(x)
+ if (x < 1)
+ fun_l22_n394(x)
+ else
+ fun_l22_n783(x)
+ end
+end
+
+def fun_l21_n139(x)
+ if (x < 1)
+ fun_l22_n514(x)
+ else
+ fun_l22_n37(x)
+ end
+end
+
+def fun_l21_n140(x)
+ if (x < 1)
+ fun_l22_n358(x)
+ else
+ fun_l22_n768(x)
+ end
+end
+
+def fun_l21_n141(x)
+ if (x < 1)
+ fun_l22_n201(x)
+ else
+ fun_l22_n981(x)
+ end
+end
+
+def fun_l21_n142(x)
+ if (x < 1)
+ fun_l22_n371(x)
+ else
+ fun_l22_n66(x)
+ end
+end
+
+def fun_l21_n143(x)
+ if (x < 1)
+ fun_l22_n41(x)
+ else
+ fun_l22_n869(x)
+ end
+end
+
+def fun_l21_n144(x)
+ if (x < 1)
+ fun_l22_n961(x)
+ else
+ fun_l22_n488(x)
+ end
+end
+
+def fun_l21_n145(x)
+ if (x < 1)
+ fun_l22_n769(x)
+ else
+ fun_l22_n82(x)
+ end
+end
+
+def fun_l21_n146(x)
+ if (x < 1)
+ fun_l22_n700(x)
+ else
+ fun_l22_n276(x)
+ end
+end
+
+def fun_l21_n147(x)
+ if (x < 1)
+ fun_l22_n439(x)
+ else
+ fun_l22_n654(x)
+ end
+end
+
+def fun_l21_n148(x)
+ if (x < 1)
+ fun_l22_n130(x)
+ else
+ fun_l22_n825(x)
+ end
+end
+
+def fun_l21_n149(x)
+ if (x < 1)
+ fun_l22_n174(x)
+ else
+ fun_l22_n907(x)
+ end
+end
+
+def fun_l21_n150(x)
+ if (x < 1)
+ fun_l22_n386(x)
+ else
+ fun_l22_n760(x)
+ end
+end
+
+def fun_l21_n151(x)
+ if (x < 1)
+ fun_l22_n460(x)
+ else
+ fun_l22_n403(x)
+ end
+end
+
+def fun_l21_n152(x)
+ if (x < 1)
+ fun_l22_n861(x)
+ else
+ fun_l22_n832(x)
+ end
+end
+
+def fun_l21_n153(x)
+ if (x < 1)
+ fun_l22_n564(x)
+ else
+ fun_l22_n604(x)
+ end
+end
+
+def fun_l21_n154(x)
+ if (x < 1)
+ fun_l22_n402(x)
+ else
+ fun_l22_n999(x)
+ end
+end
+
+def fun_l21_n155(x)
+ if (x < 1)
+ fun_l22_n645(x)
+ else
+ fun_l22_n807(x)
+ end
+end
+
+def fun_l21_n156(x)
+ if (x < 1)
+ fun_l22_n709(x)
+ else
+ fun_l22_n930(x)
+ end
+end
+
+def fun_l21_n157(x)
+ if (x < 1)
+ fun_l22_n353(x)
+ else
+ fun_l22_n462(x)
+ end
+end
+
+def fun_l21_n158(x)
+ if (x < 1)
+ fun_l22_n697(x)
+ else
+ fun_l22_n463(x)
+ end
+end
+
+def fun_l21_n159(x)
+ if (x < 1)
+ fun_l22_n690(x)
+ else
+ fun_l22_n309(x)
+ end
+end
+
+def fun_l21_n160(x)
+ if (x < 1)
+ fun_l22_n889(x)
+ else
+ fun_l22_n326(x)
+ end
+end
+
+def fun_l21_n161(x)
+ if (x < 1)
+ fun_l22_n952(x)
+ else
+ fun_l22_n225(x)
+ end
+end
+
+def fun_l21_n162(x)
+ if (x < 1)
+ fun_l22_n345(x)
+ else
+ fun_l22_n168(x)
+ end
+end
+
+def fun_l21_n163(x)
+ if (x < 1)
+ fun_l22_n437(x)
+ else
+ fun_l22_n494(x)
+ end
+end
+
+def fun_l21_n164(x)
+ if (x < 1)
+ fun_l22_n151(x)
+ else
+ fun_l22_n846(x)
+ end
+end
+
+def fun_l21_n165(x)
+ if (x < 1)
+ fun_l22_n324(x)
+ else
+ fun_l22_n999(x)
+ end
+end
+
+def fun_l21_n166(x)
+ if (x < 1)
+ fun_l22_n232(x)
+ else
+ fun_l22_n473(x)
+ end
+end
+
+def fun_l21_n167(x)
+ if (x < 1)
+ fun_l22_n934(x)
+ else
+ fun_l22_n437(x)
+ end
+end
+
+def fun_l21_n168(x)
+ if (x < 1)
+ fun_l22_n738(x)
+ else
+ fun_l22_n410(x)
+ end
+end
+
+def fun_l21_n169(x)
+ if (x < 1)
+ fun_l22_n686(x)
+ else
+ fun_l22_n108(x)
+ end
+end
+
+def fun_l21_n170(x)
+ if (x < 1)
+ fun_l22_n595(x)
+ else
+ fun_l22_n935(x)
+ end
+end
+
+def fun_l21_n171(x)
+ if (x < 1)
+ fun_l22_n723(x)
+ else
+ fun_l22_n478(x)
+ end
+end
+
+def fun_l21_n172(x)
+ if (x < 1)
+ fun_l22_n610(x)
+ else
+ fun_l22_n709(x)
+ end
+end
+
+def fun_l21_n173(x)
+ if (x < 1)
+ fun_l22_n539(x)
+ else
+ fun_l22_n17(x)
+ end
+end
+
+def fun_l21_n174(x)
+ if (x < 1)
+ fun_l22_n612(x)
+ else
+ fun_l22_n235(x)
+ end
+end
+
+def fun_l21_n175(x)
+ if (x < 1)
+ fun_l22_n835(x)
+ else
+ fun_l22_n138(x)
+ end
+end
+
+def fun_l21_n176(x)
+ if (x < 1)
+ fun_l22_n997(x)
+ else
+ fun_l22_n123(x)
+ end
+end
+
+def fun_l21_n177(x)
+ if (x < 1)
+ fun_l22_n97(x)
+ else
+ fun_l22_n997(x)
+ end
+end
+
+def fun_l21_n178(x)
+ if (x < 1)
+ fun_l22_n842(x)
+ else
+ fun_l22_n925(x)
+ end
+end
+
+def fun_l21_n179(x)
+ if (x < 1)
+ fun_l22_n159(x)
+ else
+ fun_l22_n412(x)
+ end
+end
+
+def fun_l21_n180(x)
+ if (x < 1)
+ fun_l22_n109(x)
+ else
+ fun_l22_n691(x)
+ end
+end
+
+def fun_l21_n181(x)
+ if (x < 1)
+ fun_l22_n315(x)
+ else
+ fun_l22_n127(x)
+ end
+end
+
+def fun_l21_n182(x)
+ if (x < 1)
+ fun_l22_n220(x)
+ else
+ fun_l22_n143(x)
+ end
+end
+
+def fun_l21_n183(x)
+ if (x < 1)
+ fun_l22_n493(x)
+ else
+ fun_l22_n895(x)
+ end
+end
+
+def fun_l21_n184(x)
+ if (x < 1)
+ fun_l22_n667(x)
+ else
+ fun_l22_n675(x)
+ end
+end
+
+def fun_l21_n185(x)
+ if (x < 1)
+ fun_l22_n995(x)
+ else
+ fun_l22_n4(x)
+ end
+end
+
+def fun_l21_n186(x)
+ if (x < 1)
+ fun_l22_n210(x)
+ else
+ fun_l22_n690(x)
+ end
+end
+
+def fun_l21_n187(x)
+ if (x < 1)
+ fun_l22_n413(x)
+ else
+ fun_l22_n227(x)
+ end
+end
+
+def fun_l21_n188(x)
+ if (x < 1)
+ fun_l22_n562(x)
+ else
+ fun_l22_n591(x)
+ end
+end
+
+def fun_l21_n189(x)
+ if (x < 1)
+ fun_l22_n171(x)
+ else
+ fun_l22_n891(x)
+ end
+end
+
+def fun_l21_n190(x)
+ if (x < 1)
+ fun_l22_n207(x)
+ else
+ fun_l22_n401(x)
+ end
+end
+
+def fun_l21_n191(x)
+ if (x < 1)
+ fun_l22_n703(x)
+ else
+ fun_l22_n604(x)
+ end
+end
+
+def fun_l21_n192(x)
+ if (x < 1)
+ fun_l22_n772(x)
+ else
+ fun_l22_n321(x)
+ end
+end
+
+def fun_l21_n193(x)
+ if (x < 1)
+ fun_l22_n576(x)
+ else
+ fun_l22_n273(x)
+ end
+end
+
+def fun_l21_n194(x)
+ if (x < 1)
+ fun_l22_n897(x)
+ else
+ fun_l22_n624(x)
+ end
+end
+
+def fun_l21_n195(x)
+ if (x < 1)
+ fun_l22_n909(x)
+ else
+ fun_l22_n216(x)
+ end
+end
+
+def fun_l21_n196(x)
+ if (x < 1)
+ fun_l22_n904(x)
+ else
+ fun_l22_n618(x)
+ end
+end
+
+def fun_l21_n197(x)
+ if (x < 1)
+ fun_l22_n410(x)
+ else
+ fun_l22_n926(x)
+ end
+end
+
+def fun_l21_n198(x)
+ if (x < 1)
+ fun_l22_n884(x)
+ else
+ fun_l22_n174(x)
+ end
+end
+
+def fun_l21_n199(x)
+ if (x < 1)
+ fun_l22_n407(x)
+ else
+ fun_l22_n270(x)
+ end
+end
+
+def fun_l21_n200(x)
+ if (x < 1)
+ fun_l22_n741(x)
+ else
+ fun_l22_n2(x)
+ end
+end
+
+def fun_l21_n201(x)
+ if (x < 1)
+ fun_l22_n143(x)
+ else
+ fun_l22_n93(x)
+ end
+end
+
+def fun_l21_n202(x)
+ if (x < 1)
+ fun_l22_n397(x)
+ else
+ fun_l22_n424(x)
+ end
+end
+
+def fun_l21_n203(x)
+ if (x < 1)
+ fun_l22_n183(x)
+ else
+ fun_l22_n258(x)
+ end
+end
+
+def fun_l21_n204(x)
+ if (x < 1)
+ fun_l22_n12(x)
+ else
+ fun_l22_n50(x)
+ end
+end
+
+def fun_l21_n205(x)
+ if (x < 1)
+ fun_l22_n488(x)
+ else
+ fun_l22_n148(x)
+ end
+end
+
+def fun_l21_n206(x)
+ if (x < 1)
+ fun_l22_n516(x)
+ else
+ fun_l22_n87(x)
+ end
+end
+
+def fun_l21_n207(x)
+ if (x < 1)
+ fun_l22_n810(x)
+ else
+ fun_l22_n773(x)
+ end
+end
+
+def fun_l21_n208(x)
+ if (x < 1)
+ fun_l22_n508(x)
+ else
+ fun_l22_n898(x)
+ end
+end
+
+def fun_l21_n209(x)
+ if (x < 1)
+ fun_l22_n188(x)
+ else
+ fun_l22_n815(x)
+ end
+end
+
+def fun_l21_n210(x)
+ if (x < 1)
+ fun_l22_n86(x)
+ else
+ fun_l22_n615(x)
+ end
+end
+
+def fun_l21_n211(x)
+ if (x < 1)
+ fun_l22_n589(x)
+ else
+ fun_l22_n774(x)
+ end
+end
+
+def fun_l21_n212(x)
+ if (x < 1)
+ fun_l22_n926(x)
+ else
+ fun_l22_n14(x)
+ end
+end
+
+def fun_l21_n213(x)
+ if (x < 1)
+ fun_l22_n104(x)
+ else
+ fun_l22_n723(x)
+ end
+end
+
+def fun_l21_n214(x)
+ if (x < 1)
+ fun_l22_n699(x)
+ else
+ fun_l22_n775(x)
+ end
+end
+
+def fun_l21_n215(x)
+ if (x < 1)
+ fun_l22_n941(x)
+ else
+ fun_l22_n997(x)
+ end
+end
+
+def fun_l21_n216(x)
+ if (x < 1)
+ fun_l22_n182(x)
+ else
+ fun_l22_n409(x)
+ end
+end
+
+def fun_l21_n217(x)
+ if (x < 1)
+ fun_l22_n410(x)
+ else
+ fun_l22_n807(x)
+ end
+end
+
+def fun_l21_n218(x)
+ if (x < 1)
+ fun_l22_n787(x)
+ else
+ fun_l22_n143(x)
+ end
+end
+
+def fun_l21_n219(x)
+ if (x < 1)
+ fun_l22_n515(x)
+ else
+ fun_l22_n558(x)
+ end
+end
+
+def fun_l21_n220(x)
+ if (x < 1)
+ fun_l22_n22(x)
+ else
+ fun_l22_n37(x)
+ end
+end
+
+def fun_l21_n221(x)
+ if (x < 1)
+ fun_l22_n366(x)
+ else
+ fun_l22_n63(x)
+ end
+end
+
+def fun_l21_n222(x)
+ if (x < 1)
+ fun_l22_n846(x)
+ else
+ fun_l22_n655(x)
+ end
+end
+
+def fun_l21_n223(x)
+ if (x < 1)
+ fun_l22_n946(x)
+ else
+ fun_l22_n587(x)
+ end
+end
+
+def fun_l21_n224(x)
+ if (x < 1)
+ fun_l22_n841(x)
+ else
+ fun_l22_n874(x)
+ end
+end
+
+def fun_l21_n225(x)
+ if (x < 1)
+ fun_l22_n19(x)
+ else
+ fun_l22_n142(x)
+ end
+end
+
+def fun_l21_n226(x)
+ if (x < 1)
+ fun_l22_n939(x)
+ else
+ fun_l22_n214(x)
+ end
+end
+
+def fun_l21_n227(x)
+ if (x < 1)
+ fun_l22_n900(x)
+ else
+ fun_l22_n673(x)
+ end
+end
+
+def fun_l21_n228(x)
+ if (x < 1)
+ fun_l22_n784(x)
+ else
+ fun_l22_n258(x)
+ end
+end
+
+def fun_l21_n229(x)
+ if (x < 1)
+ fun_l22_n553(x)
+ else
+ fun_l22_n253(x)
+ end
+end
+
+def fun_l21_n230(x)
+ if (x < 1)
+ fun_l22_n927(x)
+ else
+ fun_l22_n9(x)
+ end
+end
+
+def fun_l21_n231(x)
+ if (x < 1)
+ fun_l22_n822(x)
+ else
+ fun_l22_n870(x)
+ end
+end
+
+def fun_l21_n232(x)
+ if (x < 1)
+ fun_l22_n741(x)
+ else
+ fun_l22_n185(x)
+ end
+end
+
+def fun_l21_n233(x)
+ if (x < 1)
+ fun_l22_n691(x)
+ else
+ fun_l22_n613(x)
+ end
+end
+
+def fun_l21_n234(x)
+ if (x < 1)
+ fun_l22_n995(x)
+ else
+ fun_l22_n73(x)
+ end
+end
+
+def fun_l21_n235(x)
+ if (x < 1)
+ fun_l22_n250(x)
+ else
+ fun_l22_n356(x)
+ end
+end
+
+def fun_l21_n236(x)
+ if (x < 1)
+ fun_l22_n531(x)
+ else
+ fun_l22_n335(x)
+ end
+end
+
+def fun_l21_n237(x)
+ if (x < 1)
+ fun_l22_n376(x)
+ else
+ fun_l22_n732(x)
+ end
+end
+
+def fun_l21_n238(x)
+ if (x < 1)
+ fun_l22_n293(x)
+ else
+ fun_l22_n886(x)
+ end
+end
+
+def fun_l21_n239(x)
+ if (x < 1)
+ fun_l22_n266(x)
+ else
+ fun_l22_n820(x)
+ end
+end
+
+def fun_l21_n240(x)
+ if (x < 1)
+ fun_l22_n450(x)
+ else
+ fun_l22_n418(x)
+ end
+end
+
+def fun_l21_n241(x)
+ if (x < 1)
+ fun_l22_n902(x)
+ else
+ fun_l22_n991(x)
+ end
+end
+
+def fun_l21_n242(x)
+ if (x < 1)
+ fun_l22_n521(x)
+ else
+ fun_l22_n516(x)
+ end
+end
+
+def fun_l21_n243(x)
+ if (x < 1)
+ fun_l22_n97(x)
+ else
+ fun_l22_n388(x)
+ end
+end
+
+def fun_l21_n244(x)
+ if (x < 1)
+ fun_l22_n596(x)
+ else
+ fun_l22_n758(x)
+ end
+end
+
+def fun_l21_n245(x)
+ if (x < 1)
+ fun_l22_n370(x)
+ else
+ fun_l22_n747(x)
+ end
+end
+
+def fun_l21_n246(x)
+ if (x < 1)
+ fun_l22_n73(x)
+ else
+ fun_l22_n84(x)
+ end
+end
+
+def fun_l21_n247(x)
+ if (x < 1)
+ fun_l22_n489(x)
+ else
+ fun_l22_n166(x)
+ end
+end
+
+def fun_l21_n248(x)
+ if (x < 1)
+ fun_l22_n419(x)
+ else
+ fun_l22_n698(x)
+ end
+end
+
+def fun_l21_n249(x)
+ if (x < 1)
+ fun_l22_n330(x)
+ else
+ fun_l22_n995(x)
+ end
+end
+
+def fun_l21_n250(x)
+ if (x < 1)
+ fun_l22_n443(x)
+ else
+ fun_l22_n341(x)
+ end
+end
+
+def fun_l21_n251(x)
+ if (x < 1)
+ fun_l22_n442(x)
+ else
+ fun_l22_n311(x)
+ end
+end
+
+def fun_l21_n252(x)
+ if (x < 1)
+ fun_l22_n60(x)
+ else
+ fun_l22_n399(x)
+ end
+end
+
+def fun_l21_n253(x)
+ if (x < 1)
+ fun_l22_n831(x)
+ else
+ fun_l22_n245(x)
+ end
+end
+
+def fun_l21_n254(x)
+ if (x < 1)
+ fun_l22_n946(x)
+ else
+ fun_l22_n205(x)
+ end
+end
+
+def fun_l21_n255(x)
+ if (x < 1)
+ fun_l22_n499(x)
+ else
+ fun_l22_n476(x)
+ end
+end
+
+def fun_l21_n256(x)
+ if (x < 1)
+ fun_l22_n841(x)
+ else
+ fun_l22_n70(x)
+ end
+end
+
+def fun_l21_n257(x)
+ if (x < 1)
+ fun_l22_n289(x)
+ else
+ fun_l22_n329(x)
+ end
+end
+
+def fun_l21_n258(x)
+ if (x < 1)
+ fun_l22_n149(x)
+ else
+ fun_l22_n270(x)
+ end
+end
+
+def fun_l21_n259(x)
+ if (x < 1)
+ fun_l22_n569(x)
+ else
+ fun_l22_n972(x)
+ end
+end
+
+def fun_l21_n260(x)
+ if (x < 1)
+ fun_l22_n313(x)
+ else
+ fun_l22_n573(x)
+ end
+end
+
+def fun_l21_n261(x)
+ if (x < 1)
+ fun_l22_n458(x)
+ else
+ fun_l22_n964(x)
+ end
+end
+
+def fun_l21_n262(x)
+ if (x < 1)
+ fun_l22_n308(x)
+ else
+ fun_l22_n825(x)
+ end
+end
+
+def fun_l21_n263(x)
+ if (x < 1)
+ fun_l22_n810(x)
+ else
+ fun_l22_n864(x)
+ end
+end
+
+def fun_l21_n264(x)
+ if (x < 1)
+ fun_l22_n52(x)
+ else
+ fun_l22_n486(x)
+ end
+end
+
+def fun_l21_n265(x)
+ if (x < 1)
+ fun_l22_n520(x)
+ else
+ fun_l22_n758(x)
+ end
+end
+
+def fun_l21_n266(x)
+ if (x < 1)
+ fun_l22_n954(x)
+ else
+ fun_l22_n819(x)
+ end
+end
+
+def fun_l21_n267(x)
+ if (x < 1)
+ fun_l22_n226(x)
+ else
+ fun_l22_n893(x)
+ end
+end
+
+def fun_l21_n268(x)
+ if (x < 1)
+ fun_l22_n854(x)
+ else
+ fun_l22_n281(x)
+ end
+end
+
+def fun_l21_n269(x)
+ if (x < 1)
+ fun_l22_n354(x)
+ else
+ fun_l22_n296(x)
+ end
+end
+
+def fun_l21_n270(x)
+ if (x < 1)
+ fun_l22_n970(x)
+ else
+ fun_l22_n898(x)
+ end
+end
+
+def fun_l21_n271(x)
+ if (x < 1)
+ fun_l22_n769(x)
+ else
+ fun_l22_n94(x)
+ end
+end
+
+def fun_l21_n272(x)
+ if (x < 1)
+ fun_l22_n100(x)
+ else
+ fun_l22_n830(x)
+ end
+end
+
+def fun_l21_n273(x)
+ if (x < 1)
+ fun_l22_n514(x)
+ else
+ fun_l22_n522(x)
+ end
+end
+
+def fun_l21_n274(x)
+ if (x < 1)
+ fun_l22_n897(x)
+ else
+ fun_l22_n260(x)
+ end
+end
+
+def fun_l21_n275(x)
+ if (x < 1)
+ fun_l22_n834(x)
+ else
+ fun_l22_n125(x)
+ end
+end
+
+def fun_l21_n276(x)
+ if (x < 1)
+ fun_l22_n262(x)
+ else
+ fun_l22_n617(x)
+ end
+end
+
+def fun_l21_n277(x)
+ if (x < 1)
+ fun_l22_n84(x)
+ else
+ fun_l22_n483(x)
+ end
+end
+
+def fun_l21_n278(x)
+ if (x < 1)
+ fun_l22_n657(x)
+ else
+ fun_l22_n10(x)
+ end
+end
+
+def fun_l21_n279(x)
+ if (x < 1)
+ fun_l22_n142(x)
+ else
+ fun_l22_n666(x)
+ end
+end
+
+def fun_l21_n280(x)
+ if (x < 1)
+ fun_l22_n824(x)
+ else
+ fun_l22_n408(x)
+ end
+end
+
+def fun_l21_n281(x)
+ if (x < 1)
+ fun_l22_n39(x)
+ else
+ fun_l22_n225(x)
+ end
+end
+
+def fun_l21_n282(x)
+ if (x < 1)
+ fun_l22_n93(x)
+ else
+ fun_l22_n410(x)
+ end
+end
+
+def fun_l21_n283(x)
+ if (x < 1)
+ fun_l22_n294(x)
+ else
+ fun_l22_n268(x)
+ end
+end
+
+def fun_l21_n284(x)
+ if (x < 1)
+ fun_l22_n636(x)
+ else
+ fun_l22_n767(x)
+ end
+end
+
+def fun_l21_n285(x)
+ if (x < 1)
+ fun_l22_n181(x)
+ else
+ fun_l22_n317(x)
+ end
+end
+
+def fun_l21_n286(x)
+ if (x < 1)
+ fun_l22_n208(x)
+ else
+ fun_l22_n803(x)
+ end
+end
+
+def fun_l21_n287(x)
+ if (x < 1)
+ fun_l22_n910(x)
+ else
+ fun_l22_n872(x)
+ end
+end
+
+def fun_l21_n288(x)
+ if (x < 1)
+ fun_l22_n771(x)
+ else
+ fun_l22_n858(x)
+ end
+end
+
+def fun_l21_n289(x)
+ if (x < 1)
+ fun_l22_n109(x)
+ else
+ fun_l22_n577(x)
+ end
+end
+
+def fun_l21_n290(x)
+ if (x < 1)
+ fun_l22_n474(x)
+ else
+ fun_l22_n289(x)
+ end
+end
+
+def fun_l21_n291(x)
+ if (x < 1)
+ fun_l22_n55(x)
+ else
+ fun_l22_n448(x)
+ end
+end
+
+def fun_l21_n292(x)
+ if (x < 1)
+ fun_l22_n644(x)
+ else
+ fun_l22_n958(x)
+ end
+end
+
+def fun_l21_n293(x)
+ if (x < 1)
+ fun_l22_n775(x)
+ else
+ fun_l22_n131(x)
+ end
+end
+
+def fun_l21_n294(x)
+ if (x < 1)
+ fun_l22_n950(x)
+ else
+ fun_l22_n216(x)
+ end
+end
+
+def fun_l21_n295(x)
+ if (x < 1)
+ fun_l22_n258(x)
+ else
+ fun_l22_n919(x)
+ end
+end
+
+def fun_l21_n296(x)
+ if (x < 1)
+ fun_l22_n298(x)
+ else
+ fun_l22_n334(x)
+ end
+end
+
+def fun_l21_n297(x)
+ if (x < 1)
+ fun_l22_n124(x)
+ else
+ fun_l22_n704(x)
+ end
+end
+
+def fun_l21_n298(x)
+ if (x < 1)
+ fun_l22_n526(x)
+ else
+ fun_l22_n139(x)
+ end
+end
+
+def fun_l21_n299(x)
+ if (x < 1)
+ fun_l22_n133(x)
+ else
+ fun_l22_n65(x)
+ end
+end
+
+def fun_l21_n300(x)
+ if (x < 1)
+ fun_l22_n476(x)
+ else
+ fun_l22_n858(x)
+ end
+end
+
+def fun_l21_n301(x)
+ if (x < 1)
+ fun_l22_n23(x)
+ else
+ fun_l22_n391(x)
+ end
+end
+
+def fun_l21_n302(x)
+ if (x < 1)
+ fun_l22_n292(x)
+ else
+ fun_l22_n127(x)
+ end
+end
+
+def fun_l21_n303(x)
+ if (x < 1)
+ fun_l22_n935(x)
+ else
+ fun_l22_n399(x)
+ end
+end
+
+def fun_l21_n304(x)
+ if (x < 1)
+ fun_l22_n110(x)
+ else
+ fun_l22_n904(x)
+ end
+end
+
+def fun_l21_n305(x)
+ if (x < 1)
+ fun_l22_n865(x)
+ else
+ fun_l22_n510(x)
+ end
+end
+
+def fun_l21_n306(x)
+ if (x < 1)
+ fun_l22_n930(x)
+ else
+ fun_l22_n892(x)
+ end
+end
+
+def fun_l21_n307(x)
+ if (x < 1)
+ fun_l22_n701(x)
+ else
+ fun_l22_n172(x)
+ end
+end
+
+def fun_l21_n308(x)
+ if (x < 1)
+ fun_l22_n424(x)
+ else
+ fun_l22_n169(x)
+ end
+end
+
+def fun_l21_n309(x)
+ if (x < 1)
+ fun_l22_n494(x)
+ else
+ fun_l22_n608(x)
+ end
+end
+
+def fun_l21_n310(x)
+ if (x < 1)
+ fun_l22_n862(x)
+ else
+ fun_l22_n54(x)
+ end
+end
+
+def fun_l21_n311(x)
+ if (x < 1)
+ fun_l22_n679(x)
+ else
+ fun_l22_n246(x)
+ end
+end
+
+def fun_l21_n312(x)
+ if (x < 1)
+ fun_l22_n897(x)
+ else
+ fun_l22_n581(x)
+ end
+end
+
+def fun_l21_n313(x)
+ if (x < 1)
+ fun_l22_n788(x)
+ else
+ fun_l22_n32(x)
+ end
+end
+
+def fun_l21_n314(x)
+ if (x < 1)
+ fun_l22_n68(x)
+ else
+ fun_l22_n920(x)
+ end
+end
+
+def fun_l21_n315(x)
+ if (x < 1)
+ fun_l22_n520(x)
+ else
+ fun_l22_n814(x)
+ end
+end
+
+def fun_l21_n316(x)
+ if (x < 1)
+ fun_l22_n190(x)
+ else
+ fun_l22_n832(x)
+ end
+end
+
+def fun_l21_n317(x)
+ if (x < 1)
+ fun_l22_n500(x)
+ else
+ fun_l22_n576(x)
+ end
+end
+
+def fun_l21_n318(x)
+ if (x < 1)
+ fun_l22_n999(x)
+ else
+ fun_l22_n423(x)
+ end
+end
+
+def fun_l21_n319(x)
+ if (x < 1)
+ fun_l22_n62(x)
+ else
+ fun_l22_n451(x)
+ end
+end
+
+def fun_l21_n320(x)
+ if (x < 1)
+ fun_l22_n265(x)
+ else
+ fun_l22_n421(x)
+ end
+end
+
+def fun_l21_n321(x)
+ if (x < 1)
+ fun_l22_n340(x)
+ else
+ fun_l22_n297(x)
+ end
+end
+
+def fun_l21_n322(x)
+ if (x < 1)
+ fun_l22_n526(x)
+ else
+ fun_l22_n834(x)
+ end
+end
+
+def fun_l21_n323(x)
+ if (x < 1)
+ fun_l22_n305(x)
+ else
+ fun_l22_n444(x)
+ end
+end
+
+def fun_l21_n324(x)
+ if (x < 1)
+ fun_l22_n117(x)
+ else
+ fun_l22_n617(x)
+ end
+end
+
+def fun_l21_n325(x)
+ if (x < 1)
+ fun_l22_n715(x)
+ else
+ fun_l22_n551(x)
+ end
+end
+
+def fun_l21_n326(x)
+ if (x < 1)
+ fun_l22_n921(x)
+ else
+ fun_l22_n69(x)
+ end
+end
+
+def fun_l21_n327(x)
+ if (x < 1)
+ fun_l22_n226(x)
+ else
+ fun_l22_n21(x)
+ end
+end
+
+def fun_l21_n328(x)
+ if (x < 1)
+ fun_l22_n181(x)
+ else
+ fun_l22_n409(x)
+ end
+end
+
+def fun_l21_n329(x)
+ if (x < 1)
+ fun_l22_n894(x)
+ else
+ fun_l22_n17(x)
+ end
+end
+
+def fun_l21_n330(x)
+ if (x < 1)
+ fun_l22_n633(x)
+ else
+ fun_l22_n370(x)
+ end
+end
+
+def fun_l21_n331(x)
+ if (x < 1)
+ fun_l22_n638(x)
+ else
+ fun_l22_n994(x)
+ end
+end
+
+def fun_l21_n332(x)
+ if (x < 1)
+ fun_l22_n663(x)
+ else
+ fun_l22_n981(x)
+ end
+end
+
+def fun_l21_n333(x)
+ if (x < 1)
+ fun_l22_n861(x)
+ else
+ fun_l22_n472(x)
+ end
+end
+
+def fun_l21_n334(x)
+ if (x < 1)
+ fun_l22_n265(x)
+ else
+ fun_l22_n534(x)
+ end
+end
+
+def fun_l21_n335(x)
+ if (x < 1)
+ fun_l22_n43(x)
+ else
+ fun_l22_n613(x)
+ end
+end
+
+def fun_l21_n336(x)
+ if (x < 1)
+ fun_l22_n788(x)
+ else
+ fun_l22_n649(x)
+ end
+end
+
+def fun_l21_n337(x)
+ if (x < 1)
+ fun_l22_n406(x)
+ else
+ fun_l22_n644(x)
+ end
+end
+
+def fun_l21_n338(x)
+ if (x < 1)
+ fun_l22_n582(x)
+ else
+ fun_l22_n463(x)
+ end
+end
+
+def fun_l21_n339(x)
+ if (x < 1)
+ fun_l22_n825(x)
+ else
+ fun_l22_n775(x)
+ end
+end
+
+def fun_l21_n340(x)
+ if (x < 1)
+ fun_l22_n696(x)
+ else
+ fun_l22_n318(x)
+ end
+end
+
+def fun_l21_n341(x)
+ if (x < 1)
+ fun_l22_n21(x)
+ else
+ fun_l22_n285(x)
+ end
+end
+
+def fun_l21_n342(x)
+ if (x < 1)
+ fun_l22_n10(x)
+ else
+ fun_l22_n423(x)
+ end
+end
+
+def fun_l21_n343(x)
+ if (x < 1)
+ fun_l22_n205(x)
+ else
+ fun_l22_n86(x)
+ end
+end
+
+def fun_l21_n344(x)
+ if (x < 1)
+ fun_l22_n437(x)
+ else
+ fun_l22_n712(x)
+ end
+end
+
+def fun_l21_n345(x)
+ if (x < 1)
+ fun_l22_n941(x)
+ else
+ fun_l22_n655(x)
+ end
+end
+
+def fun_l21_n346(x)
+ if (x < 1)
+ fun_l22_n673(x)
+ else
+ fun_l22_n750(x)
+ end
+end
+
+def fun_l21_n347(x)
+ if (x < 1)
+ fun_l22_n728(x)
+ else
+ fun_l22_n605(x)
+ end
+end
+
+def fun_l21_n348(x)
+ if (x < 1)
+ fun_l22_n452(x)
+ else
+ fun_l22_n968(x)
+ end
+end
+
+def fun_l21_n349(x)
+ if (x < 1)
+ fun_l22_n554(x)
+ else
+ fun_l22_n997(x)
+ end
+end
+
+def fun_l21_n350(x)
+ if (x < 1)
+ fun_l22_n784(x)
+ else
+ fun_l22_n801(x)
+ end
+end
+
+def fun_l21_n351(x)
+ if (x < 1)
+ fun_l22_n397(x)
+ else
+ fun_l22_n636(x)
+ end
+end
+
+def fun_l21_n352(x)
+ if (x < 1)
+ fun_l22_n562(x)
+ else
+ fun_l22_n150(x)
+ end
+end
+
+def fun_l21_n353(x)
+ if (x < 1)
+ fun_l22_n142(x)
+ else
+ fun_l22_n396(x)
+ end
+end
+
+def fun_l21_n354(x)
+ if (x < 1)
+ fun_l22_n455(x)
+ else
+ fun_l22_n424(x)
+ end
+end
+
+def fun_l21_n355(x)
+ if (x < 1)
+ fun_l22_n736(x)
+ else
+ fun_l22_n534(x)
+ end
+end
+
+def fun_l21_n356(x)
+ if (x < 1)
+ fun_l22_n111(x)
+ else
+ fun_l22_n903(x)
+ end
+end
+
+def fun_l21_n357(x)
+ if (x < 1)
+ fun_l22_n996(x)
+ else
+ fun_l22_n350(x)
+ end
+end
+
+def fun_l21_n358(x)
+ if (x < 1)
+ fun_l22_n516(x)
+ else
+ fun_l22_n202(x)
+ end
+end
+
+def fun_l21_n359(x)
+ if (x < 1)
+ fun_l22_n68(x)
+ else
+ fun_l22_n823(x)
+ end
+end
+
+def fun_l21_n360(x)
+ if (x < 1)
+ fun_l22_n298(x)
+ else
+ fun_l22_n873(x)
+ end
+end
+
+def fun_l21_n361(x)
+ if (x < 1)
+ fun_l22_n491(x)
+ else
+ fun_l22_n86(x)
+ end
+end
+
+def fun_l21_n362(x)
+ if (x < 1)
+ fun_l22_n340(x)
+ else
+ fun_l22_n215(x)
+ end
+end
+
+def fun_l21_n363(x)
+ if (x < 1)
+ fun_l22_n452(x)
+ else
+ fun_l22_n416(x)
+ end
+end
+
+def fun_l21_n364(x)
+ if (x < 1)
+ fun_l22_n625(x)
+ else
+ fun_l22_n638(x)
+ end
+end
+
+def fun_l21_n365(x)
+ if (x < 1)
+ fun_l22_n166(x)
+ else
+ fun_l22_n380(x)
+ end
+end
+
+def fun_l21_n366(x)
+ if (x < 1)
+ fun_l22_n934(x)
+ else
+ fun_l22_n937(x)
+ end
+end
+
+def fun_l21_n367(x)
+ if (x < 1)
+ fun_l22_n77(x)
+ else
+ fun_l22_n117(x)
+ end
+end
+
+def fun_l21_n368(x)
+ if (x < 1)
+ fun_l22_n688(x)
+ else
+ fun_l22_n529(x)
+ end
+end
+
+def fun_l21_n369(x)
+ if (x < 1)
+ fun_l22_n950(x)
+ else
+ fun_l22_n148(x)
+ end
+end
+
+def fun_l21_n370(x)
+ if (x < 1)
+ fun_l22_n216(x)
+ else
+ fun_l22_n588(x)
+ end
+end
+
+def fun_l21_n371(x)
+ if (x < 1)
+ fun_l22_n127(x)
+ else
+ fun_l22_n901(x)
+ end
+end
+
+def fun_l21_n372(x)
+ if (x < 1)
+ fun_l22_n244(x)
+ else
+ fun_l22_n516(x)
+ end
+end
+
+def fun_l21_n373(x)
+ if (x < 1)
+ fun_l22_n791(x)
+ else
+ fun_l22_n466(x)
+ end
+end
+
+def fun_l21_n374(x)
+ if (x < 1)
+ fun_l22_n469(x)
+ else
+ fun_l22_n38(x)
+ end
+end
+
+def fun_l21_n375(x)
+ if (x < 1)
+ fun_l22_n894(x)
+ else
+ fun_l22_n82(x)
+ end
+end
+
+def fun_l21_n376(x)
+ if (x < 1)
+ fun_l22_n663(x)
+ else
+ fun_l22_n865(x)
+ end
+end
+
+def fun_l21_n377(x)
+ if (x < 1)
+ fun_l22_n782(x)
+ else
+ fun_l22_n10(x)
+ end
+end
+
+def fun_l21_n378(x)
+ if (x < 1)
+ fun_l22_n930(x)
+ else
+ fun_l22_n767(x)
+ end
+end
+
+def fun_l21_n379(x)
+ if (x < 1)
+ fun_l22_n130(x)
+ else
+ fun_l22_n437(x)
+ end
+end
+
+def fun_l21_n380(x)
+ if (x < 1)
+ fun_l22_n496(x)
+ else
+ fun_l22_n413(x)
+ end
+end
+
+def fun_l21_n381(x)
+ if (x < 1)
+ fun_l22_n453(x)
+ else
+ fun_l22_n542(x)
+ end
+end
+
+def fun_l21_n382(x)
+ if (x < 1)
+ fun_l22_n404(x)
+ else
+ fun_l22_n637(x)
+ end
+end
+
+def fun_l21_n383(x)
+ if (x < 1)
+ fun_l22_n829(x)
+ else
+ fun_l22_n526(x)
+ end
+end
+
+def fun_l21_n384(x)
+ if (x < 1)
+ fun_l22_n882(x)
+ else
+ fun_l22_n922(x)
+ end
+end
+
+def fun_l21_n385(x)
+ if (x < 1)
+ fun_l22_n58(x)
+ else
+ fun_l22_n401(x)
+ end
+end
+
+def fun_l21_n386(x)
+ if (x < 1)
+ fun_l22_n936(x)
+ else
+ fun_l22_n164(x)
+ end
+end
+
+def fun_l21_n387(x)
+ if (x < 1)
+ fun_l22_n773(x)
+ else
+ fun_l22_n323(x)
+ end
+end
+
+def fun_l21_n388(x)
+ if (x < 1)
+ fun_l22_n718(x)
+ else
+ fun_l22_n189(x)
+ end
+end
+
+def fun_l21_n389(x)
+ if (x < 1)
+ fun_l22_n950(x)
+ else
+ fun_l22_n283(x)
+ end
+end
+
+def fun_l21_n390(x)
+ if (x < 1)
+ fun_l22_n278(x)
+ else
+ fun_l22_n325(x)
+ end
+end
+
+def fun_l21_n391(x)
+ if (x < 1)
+ fun_l22_n98(x)
+ else
+ fun_l22_n162(x)
+ end
+end
+
+def fun_l21_n392(x)
+ if (x < 1)
+ fun_l22_n268(x)
+ else
+ fun_l22_n416(x)
+ end
+end
+
+def fun_l21_n393(x)
+ if (x < 1)
+ fun_l22_n344(x)
+ else
+ fun_l22_n680(x)
+ end
+end
+
+def fun_l21_n394(x)
+ if (x < 1)
+ fun_l22_n545(x)
+ else
+ fun_l22_n41(x)
+ end
+end
+
+def fun_l21_n395(x)
+ if (x < 1)
+ fun_l22_n149(x)
+ else
+ fun_l22_n659(x)
+ end
+end
+
+def fun_l21_n396(x)
+ if (x < 1)
+ fun_l22_n81(x)
+ else
+ fun_l22_n316(x)
+ end
+end
+
+def fun_l21_n397(x)
+ if (x < 1)
+ fun_l22_n657(x)
+ else
+ fun_l22_n414(x)
+ end
+end
+
+def fun_l21_n398(x)
+ if (x < 1)
+ fun_l22_n262(x)
+ else
+ fun_l22_n26(x)
+ end
+end
+
+def fun_l21_n399(x)
+ if (x < 1)
+ fun_l22_n509(x)
+ else
+ fun_l22_n658(x)
+ end
+end
+
+def fun_l21_n400(x)
+ if (x < 1)
+ fun_l22_n533(x)
+ else
+ fun_l22_n416(x)
+ end
+end
+
+def fun_l21_n401(x)
+ if (x < 1)
+ fun_l22_n631(x)
+ else
+ fun_l22_n575(x)
+ end
+end
+
+def fun_l21_n402(x)
+ if (x < 1)
+ fun_l22_n171(x)
+ else
+ fun_l22_n727(x)
+ end
+end
+
+def fun_l21_n403(x)
+ if (x < 1)
+ fun_l22_n65(x)
+ else
+ fun_l22_n109(x)
+ end
+end
+
+def fun_l21_n404(x)
+ if (x < 1)
+ fun_l22_n818(x)
+ else
+ fun_l22_n638(x)
+ end
+end
+
+def fun_l21_n405(x)
+ if (x < 1)
+ fun_l22_n515(x)
+ else
+ fun_l22_n86(x)
+ end
+end
+
+def fun_l21_n406(x)
+ if (x < 1)
+ fun_l22_n500(x)
+ else
+ fun_l22_n367(x)
+ end
+end
+
+def fun_l21_n407(x)
+ if (x < 1)
+ fun_l22_n609(x)
+ else
+ fun_l22_n926(x)
+ end
+end
+
+def fun_l21_n408(x)
+ if (x < 1)
+ fun_l22_n553(x)
+ else
+ fun_l22_n494(x)
+ end
+end
+
+def fun_l21_n409(x)
+ if (x < 1)
+ fun_l22_n837(x)
+ else
+ fun_l22_n800(x)
+ end
+end
+
+def fun_l21_n410(x)
+ if (x < 1)
+ fun_l22_n511(x)
+ else
+ fun_l22_n376(x)
+ end
+end
+
+def fun_l21_n411(x)
+ if (x < 1)
+ fun_l22_n691(x)
+ else
+ fun_l22_n135(x)
+ end
+end
+
+def fun_l21_n412(x)
+ if (x < 1)
+ fun_l22_n537(x)
+ else
+ fun_l22_n708(x)
+ end
+end
+
+def fun_l21_n413(x)
+ if (x < 1)
+ fun_l22_n858(x)
+ else
+ fun_l22_n75(x)
+ end
+end
+
+def fun_l21_n414(x)
+ if (x < 1)
+ fun_l22_n473(x)
+ else
+ fun_l22_n26(x)
+ end
+end
+
+def fun_l21_n415(x)
+ if (x < 1)
+ fun_l22_n443(x)
+ else
+ fun_l22_n709(x)
+ end
+end
+
+def fun_l21_n416(x)
+ if (x < 1)
+ fun_l22_n464(x)
+ else
+ fun_l22_n329(x)
+ end
+end
+
+def fun_l21_n417(x)
+ if (x < 1)
+ fun_l22_n402(x)
+ else
+ fun_l22_n438(x)
+ end
+end
+
+def fun_l21_n418(x)
+ if (x < 1)
+ fun_l22_n741(x)
+ else
+ fun_l22_n704(x)
+ end
+end
+
+def fun_l21_n419(x)
+ if (x < 1)
+ fun_l22_n949(x)
+ else
+ fun_l22_n46(x)
+ end
+end
+
+def fun_l21_n420(x)
+ if (x < 1)
+ fun_l22_n102(x)
+ else
+ fun_l22_n20(x)
+ end
+end
+
+def fun_l21_n421(x)
+ if (x < 1)
+ fun_l22_n834(x)
+ else
+ fun_l22_n876(x)
+ end
+end
+
+def fun_l21_n422(x)
+ if (x < 1)
+ fun_l22_n881(x)
+ else
+ fun_l22_n100(x)
+ end
+end
+
+def fun_l21_n423(x)
+ if (x < 1)
+ fun_l22_n155(x)
+ else
+ fun_l22_n99(x)
+ end
+end
+
+def fun_l21_n424(x)
+ if (x < 1)
+ fun_l22_n913(x)
+ else
+ fun_l22_n839(x)
+ end
+end
+
+def fun_l21_n425(x)
+ if (x < 1)
+ fun_l22_n981(x)
+ else
+ fun_l22_n73(x)
+ end
+end
+
+def fun_l21_n426(x)
+ if (x < 1)
+ fun_l22_n221(x)
+ else
+ fun_l22_n548(x)
+ end
+end
+
+def fun_l21_n427(x)
+ if (x < 1)
+ fun_l22_n563(x)
+ else
+ fun_l22_n978(x)
+ end
+end
+
+def fun_l21_n428(x)
+ if (x < 1)
+ fun_l22_n310(x)
+ else
+ fun_l22_n591(x)
+ end
+end
+
+def fun_l21_n429(x)
+ if (x < 1)
+ fun_l22_n962(x)
+ else
+ fun_l22_n156(x)
+ end
+end
+
+def fun_l21_n430(x)
+ if (x < 1)
+ fun_l22_n810(x)
+ else
+ fun_l22_n766(x)
+ end
+end
+
+def fun_l21_n431(x)
+ if (x < 1)
+ fun_l22_n675(x)
+ else
+ fun_l22_n354(x)
+ end
+end
+
+def fun_l21_n432(x)
+ if (x < 1)
+ fun_l22_n320(x)
+ else
+ fun_l22_n474(x)
+ end
+end
+
+def fun_l21_n433(x)
+ if (x < 1)
+ fun_l22_n50(x)
+ else
+ fun_l22_n626(x)
+ end
+end
+
+def fun_l21_n434(x)
+ if (x < 1)
+ fun_l22_n956(x)
+ else
+ fun_l22_n238(x)
+ end
+end
+
+def fun_l21_n435(x)
+ if (x < 1)
+ fun_l22_n966(x)
+ else
+ fun_l22_n729(x)
+ end
+end
+
+def fun_l21_n436(x)
+ if (x < 1)
+ fun_l22_n856(x)
+ else
+ fun_l22_n553(x)
+ end
+end
+
+def fun_l21_n437(x)
+ if (x < 1)
+ fun_l22_n833(x)
+ else
+ fun_l22_n312(x)
+ end
+end
+
+def fun_l21_n438(x)
+ if (x < 1)
+ fun_l22_n254(x)
+ else
+ fun_l22_n515(x)
+ end
+end
+
+def fun_l21_n439(x)
+ if (x < 1)
+ fun_l22_n548(x)
+ else
+ fun_l22_n184(x)
+ end
+end
+
+def fun_l21_n440(x)
+ if (x < 1)
+ fun_l22_n922(x)
+ else
+ fun_l22_n465(x)
+ end
+end
+
+def fun_l21_n441(x)
+ if (x < 1)
+ fun_l22_n136(x)
+ else
+ fun_l22_n739(x)
+ end
+end
+
+def fun_l21_n442(x)
+ if (x < 1)
+ fun_l22_n4(x)
+ else
+ fun_l22_n359(x)
+ end
+end
+
+def fun_l21_n443(x)
+ if (x < 1)
+ fun_l22_n269(x)
+ else
+ fun_l22_n417(x)
+ end
+end
+
+def fun_l21_n444(x)
+ if (x < 1)
+ fun_l22_n809(x)
+ else
+ fun_l22_n430(x)
+ end
+end
+
+def fun_l21_n445(x)
+ if (x < 1)
+ fun_l22_n428(x)
+ else
+ fun_l22_n55(x)
+ end
+end
+
+def fun_l21_n446(x)
+ if (x < 1)
+ fun_l22_n265(x)
+ else
+ fun_l22_n394(x)
+ end
+end
+
+def fun_l21_n447(x)
+ if (x < 1)
+ fun_l22_n885(x)
+ else
+ fun_l22_n139(x)
+ end
+end
+
+def fun_l21_n448(x)
+ if (x < 1)
+ fun_l22_n219(x)
+ else
+ fun_l22_n578(x)
+ end
+end
+
+def fun_l21_n449(x)
+ if (x < 1)
+ fun_l22_n458(x)
+ else
+ fun_l22_n226(x)
+ end
+end
+
+def fun_l21_n450(x)
+ if (x < 1)
+ fun_l22_n128(x)
+ else
+ fun_l22_n790(x)
+ end
+end
+
+def fun_l21_n451(x)
+ if (x < 1)
+ fun_l22_n134(x)
+ else
+ fun_l22_n471(x)
+ end
+end
+
+def fun_l21_n452(x)
+ if (x < 1)
+ fun_l22_n180(x)
+ else
+ fun_l22_n183(x)
+ end
+end
+
+def fun_l21_n453(x)
+ if (x < 1)
+ fun_l22_n823(x)
+ else
+ fun_l22_n667(x)
+ end
+end
+
+def fun_l21_n454(x)
+ if (x < 1)
+ fun_l22_n324(x)
+ else
+ fun_l22_n487(x)
+ end
+end
+
+def fun_l21_n455(x)
+ if (x < 1)
+ fun_l22_n341(x)
+ else
+ fun_l22_n784(x)
+ end
+end
+
+def fun_l21_n456(x)
+ if (x < 1)
+ fun_l22_n32(x)
+ else
+ fun_l22_n227(x)
+ end
+end
+
+def fun_l21_n457(x)
+ if (x < 1)
+ fun_l22_n567(x)
+ else
+ fun_l22_n774(x)
+ end
+end
+
+def fun_l21_n458(x)
+ if (x < 1)
+ fun_l22_n342(x)
+ else
+ fun_l22_n126(x)
+ end
+end
+
+def fun_l21_n459(x)
+ if (x < 1)
+ fun_l22_n116(x)
+ else
+ fun_l22_n367(x)
+ end
+end
+
+def fun_l21_n460(x)
+ if (x < 1)
+ fun_l22_n864(x)
+ else
+ fun_l22_n618(x)
+ end
+end
+
+def fun_l21_n461(x)
+ if (x < 1)
+ fun_l22_n823(x)
+ else
+ fun_l22_n799(x)
+ end
+end
+
+def fun_l21_n462(x)
+ if (x < 1)
+ fun_l22_n684(x)
+ else
+ fun_l22_n758(x)
+ end
+end
+
+def fun_l21_n463(x)
+ if (x < 1)
+ fun_l22_n662(x)
+ else
+ fun_l22_n514(x)
+ end
+end
+
+def fun_l21_n464(x)
+ if (x < 1)
+ fun_l22_n736(x)
+ else
+ fun_l22_n794(x)
+ end
+end
+
+def fun_l21_n465(x)
+ if (x < 1)
+ fun_l22_n200(x)
+ else
+ fun_l22_n565(x)
+ end
+end
+
+def fun_l21_n466(x)
+ if (x < 1)
+ fun_l22_n787(x)
+ else
+ fun_l22_n835(x)
+ end
+end
+
+def fun_l21_n467(x)
+ if (x < 1)
+ fun_l22_n927(x)
+ else
+ fun_l22_n399(x)
+ end
+end
+
+def fun_l21_n468(x)
+ if (x < 1)
+ fun_l22_n102(x)
+ else
+ fun_l22_n738(x)
+ end
+end
+
+def fun_l21_n469(x)
+ if (x < 1)
+ fun_l22_n833(x)
+ else
+ fun_l22_n917(x)
+ end
+end
+
+def fun_l21_n470(x)
+ if (x < 1)
+ fun_l22_n422(x)
+ else
+ fun_l22_n108(x)
+ end
+end
+
+def fun_l21_n471(x)
+ if (x < 1)
+ fun_l22_n884(x)
+ else
+ fun_l22_n19(x)
+ end
+end
+
+def fun_l21_n472(x)
+ if (x < 1)
+ fun_l22_n849(x)
+ else
+ fun_l22_n251(x)
+ end
+end
+
+def fun_l21_n473(x)
+ if (x < 1)
+ fun_l22_n636(x)
+ else
+ fun_l22_n439(x)
+ end
+end
+
+def fun_l21_n474(x)
+ if (x < 1)
+ fun_l22_n867(x)
+ else
+ fun_l22_n227(x)
+ end
+end
+
+def fun_l21_n475(x)
+ if (x < 1)
+ fun_l22_n809(x)
+ else
+ fun_l22_n548(x)
+ end
+end
+
+def fun_l21_n476(x)
+ if (x < 1)
+ fun_l22_n213(x)
+ else
+ fun_l22_n607(x)
+ end
+end
+
+def fun_l21_n477(x)
+ if (x < 1)
+ fun_l22_n44(x)
+ else
+ fun_l22_n38(x)
+ end
+end
+
+def fun_l21_n478(x)
+ if (x < 1)
+ fun_l22_n400(x)
+ else
+ fun_l22_n436(x)
+ end
+end
+
+def fun_l21_n479(x)
+ if (x < 1)
+ fun_l22_n701(x)
+ else
+ fun_l22_n84(x)
+ end
+end
+
+def fun_l21_n480(x)
+ if (x < 1)
+ fun_l22_n21(x)
+ else
+ fun_l22_n215(x)
+ end
+end
+
+def fun_l21_n481(x)
+ if (x < 1)
+ fun_l22_n27(x)
+ else
+ fun_l22_n198(x)
+ end
+end
+
+def fun_l21_n482(x)
+ if (x < 1)
+ fun_l22_n803(x)
+ else
+ fun_l22_n82(x)
+ end
+end
+
+def fun_l21_n483(x)
+ if (x < 1)
+ fun_l22_n490(x)
+ else
+ fun_l22_n126(x)
+ end
+end
+
+def fun_l21_n484(x)
+ if (x < 1)
+ fun_l22_n348(x)
+ else
+ fun_l22_n586(x)
+ end
+end
+
+def fun_l21_n485(x)
+ if (x < 1)
+ fun_l22_n279(x)
+ else
+ fun_l22_n266(x)
+ end
+end
+
+def fun_l21_n486(x)
+ if (x < 1)
+ fun_l22_n398(x)
+ else
+ fun_l22_n26(x)
+ end
+end
+
+def fun_l21_n487(x)
+ if (x < 1)
+ fun_l22_n529(x)
+ else
+ fun_l22_n972(x)
+ end
+end
+
+def fun_l21_n488(x)
+ if (x < 1)
+ fun_l22_n390(x)
+ else
+ fun_l22_n220(x)
+ end
+end
+
+def fun_l21_n489(x)
+ if (x < 1)
+ fun_l22_n909(x)
+ else
+ fun_l22_n777(x)
+ end
+end
+
+def fun_l21_n490(x)
+ if (x < 1)
+ fun_l22_n797(x)
+ else
+ fun_l22_n643(x)
+ end
+end
+
+def fun_l21_n491(x)
+ if (x < 1)
+ fun_l22_n920(x)
+ else
+ fun_l22_n820(x)
+ end
+end
+
+def fun_l21_n492(x)
+ if (x < 1)
+ fun_l22_n170(x)
+ else
+ fun_l22_n236(x)
+ end
+end
+
+def fun_l21_n493(x)
+ if (x < 1)
+ fun_l22_n352(x)
+ else
+ fun_l22_n147(x)
+ end
+end
+
+def fun_l21_n494(x)
+ if (x < 1)
+ fun_l22_n938(x)
+ else
+ fun_l22_n83(x)
+ end
+end
+
+def fun_l21_n495(x)
+ if (x < 1)
+ fun_l22_n512(x)
+ else
+ fun_l22_n798(x)
+ end
+end
+
+def fun_l21_n496(x)
+ if (x < 1)
+ fun_l22_n254(x)
+ else
+ fun_l22_n827(x)
+ end
+end
+
+def fun_l21_n497(x)
+ if (x < 1)
+ fun_l22_n730(x)
+ else
+ fun_l22_n995(x)
+ end
+end
+
+def fun_l21_n498(x)
+ if (x < 1)
+ fun_l22_n130(x)
+ else
+ fun_l22_n269(x)
+ end
+end
+
+def fun_l21_n499(x)
+ if (x < 1)
+ fun_l22_n275(x)
+ else
+ fun_l22_n176(x)
+ end
+end
+
+def fun_l21_n500(x)
+ if (x < 1)
+ fun_l22_n493(x)
+ else
+ fun_l22_n322(x)
+ end
+end
+
+def fun_l21_n501(x)
+ if (x < 1)
+ fun_l22_n421(x)
+ else
+ fun_l22_n859(x)
+ end
+end
+
+def fun_l21_n502(x)
+ if (x < 1)
+ fun_l22_n611(x)
+ else
+ fun_l22_n727(x)
+ end
+end
+
+def fun_l21_n503(x)
+ if (x < 1)
+ fun_l22_n42(x)
+ else
+ fun_l22_n294(x)
+ end
+end
+
+def fun_l21_n504(x)
+ if (x < 1)
+ fun_l22_n735(x)
+ else
+ fun_l22_n145(x)
+ end
+end
+
+def fun_l21_n505(x)
+ if (x < 1)
+ fun_l22_n865(x)
+ else
+ fun_l22_n225(x)
+ end
+end
+
+def fun_l21_n506(x)
+ if (x < 1)
+ fun_l22_n922(x)
+ else
+ fun_l22_n619(x)
+ end
+end
+
+def fun_l21_n507(x)
+ if (x < 1)
+ fun_l22_n646(x)
+ else
+ fun_l22_n145(x)
+ end
+end
+
+def fun_l21_n508(x)
+ if (x < 1)
+ fun_l22_n608(x)
+ else
+ fun_l22_n320(x)
+ end
+end
+
+def fun_l21_n509(x)
+ if (x < 1)
+ fun_l22_n624(x)
+ else
+ fun_l22_n984(x)
+ end
+end
+
+def fun_l21_n510(x)
+ if (x < 1)
+ fun_l22_n454(x)
+ else
+ fun_l22_n988(x)
+ end
+end
+
+def fun_l21_n511(x)
+ if (x < 1)
+ fun_l22_n593(x)
+ else
+ fun_l22_n796(x)
+ end
+end
+
+def fun_l21_n512(x)
+ if (x < 1)
+ fun_l22_n922(x)
+ else
+ fun_l22_n5(x)
+ end
+end
+
+def fun_l21_n513(x)
+ if (x < 1)
+ fun_l22_n0(x)
+ else
+ fun_l22_n338(x)
+ end
+end
+
+def fun_l21_n514(x)
+ if (x < 1)
+ fun_l22_n454(x)
+ else
+ fun_l22_n743(x)
+ end
+end
+
+def fun_l21_n515(x)
+ if (x < 1)
+ fun_l22_n215(x)
+ else
+ fun_l22_n689(x)
+ end
+end
+
+def fun_l21_n516(x)
+ if (x < 1)
+ fun_l22_n148(x)
+ else
+ fun_l22_n850(x)
+ end
+end
+
+def fun_l21_n517(x)
+ if (x < 1)
+ fun_l22_n466(x)
+ else
+ fun_l22_n529(x)
+ end
+end
+
+def fun_l21_n518(x)
+ if (x < 1)
+ fun_l22_n967(x)
+ else
+ fun_l22_n790(x)
+ end
+end
+
+def fun_l21_n519(x)
+ if (x < 1)
+ fun_l22_n97(x)
+ else
+ fun_l22_n461(x)
+ end
+end
+
+def fun_l21_n520(x)
+ if (x < 1)
+ fun_l22_n106(x)
+ else
+ fun_l22_n41(x)
+ end
+end
+
+def fun_l21_n521(x)
+ if (x < 1)
+ fun_l22_n561(x)
+ else
+ fun_l22_n428(x)
+ end
+end
+
+def fun_l21_n522(x)
+ if (x < 1)
+ fun_l22_n816(x)
+ else
+ fun_l22_n42(x)
+ end
+end
+
+def fun_l21_n523(x)
+ if (x < 1)
+ fun_l22_n229(x)
+ else
+ fun_l22_n720(x)
+ end
+end
+
+def fun_l21_n524(x)
+ if (x < 1)
+ fun_l22_n341(x)
+ else
+ fun_l22_n875(x)
+ end
+end
+
+def fun_l21_n525(x)
+ if (x < 1)
+ fun_l22_n23(x)
+ else
+ fun_l22_n227(x)
+ end
+end
+
+def fun_l21_n526(x)
+ if (x < 1)
+ fun_l22_n230(x)
+ else
+ fun_l22_n655(x)
+ end
+end
+
+def fun_l21_n527(x)
+ if (x < 1)
+ fun_l22_n19(x)
+ else
+ fun_l22_n957(x)
+ end
+end
+
+def fun_l21_n528(x)
+ if (x < 1)
+ fun_l22_n680(x)
+ else
+ fun_l22_n142(x)
+ end
+end
+
+def fun_l21_n529(x)
+ if (x < 1)
+ fun_l22_n994(x)
+ else
+ fun_l22_n674(x)
+ end
+end
+
+def fun_l21_n530(x)
+ if (x < 1)
+ fun_l22_n762(x)
+ else
+ fun_l22_n10(x)
+ end
+end
+
+def fun_l21_n531(x)
+ if (x < 1)
+ fun_l22_n75(x)
+ else
+ fun_l22_n43(x)
+ end
+end
+
+def fun_l21_n532(x)
+ if (x < 1)
+ fun_l22_n481(x)
+ else
+ fun_l22_n766(x)
+ end
+end
+
+def fun_l21_n533(x)
+ if (x < 1)
+ fun_l22_n261(x)
+ else
+ fun_l22_n256(x)
+ end
+end
+
+def fun_l21_n534(x)
+ if (x < 1)
+ fun_l22_n316(x)
+ else
+ fun_l22_n547(x)
+ end
+end
+
+def fun_l21_n535(x)
+ if (x < 1)
+ fun_l22_n304(x)
+ else
+ fun_l22_n392(x)
+ end
+end
+
+def fun_l21_n536(x)
+ if (x < 1)
+ fun_l22_n83(x)
+ else
+ fun_l22_n789(x)
+ end
+end
+
+def fun_l21_n537(x)
+ if (x < 1)
+ fun_l22_n434(x)
+ else
+ fun_l22_n783(x)
+ end
+end
+
+def fun_l21_n538(x)
+ if (x < 1)
+ fun_l22_n445(x)
+ else
+ fun_l22_n960(x)
+ end
+end
+
+def fun_l21_n539(x)
+ if (x < 1)
+ fun_l22_n398(x)
+ else
+ fun_l22_n529(x)
+ end
+end
+
+def fun_l21_n540(x)
+ if (x < 1)
+ fun_l22_n413(x)
+ else
+ fun_l22_n684(x)
+ end
+end
+
+def fun_l21_n541(x)
+ if (x < 1)
+ fun_l22_n812(x)
+ else
+ fun_l22_n257(x)
+ end
+end
+
+def fun_l21_n542(x)
+ if (x < 1)
+ fun_l22_n186(x)
+ else
+ fun_l22_n35(x)
+ end
+end
+
+def fun_l21_n543(x)
+ if (x < 1)
+ fun_l22_n489(x)
+ else
+ fun_l22_n93(x)
+ end
+end
+
+def fun_l21_n544(x)
+ if (x < 1)
+ fun_l22_n105(x)
+ else
+ fun_l22_n282(x)
+ end
+end
+
+def fun_l21_n545(x)
+ if (x < 1)
+ fun_l22_n586(x)
+ else
+ fun_l22_n614(x)
+ end
+end
+
+def fun_l21_n546(x)
+ if (x < 1)
+ fun_l22_n75(x)
+ else
+ fun_l22_n589(x)
+ end
+end
+
+def fun_l21_n547(x)
+ if (x < 1)
+ fun_l22_n128(x)
+ else
+ fun_l22_n552(x)
+ end
+end
+
+def fun_l21_n548(x)
+ if (x < 1)
+ fun_l22_n961(x)
+ else
+ fun_l22_n209(x)
+ end
+end
+
+def fun_l21_n549(x)
+ if (x < 1)
+ fun_l22_n727(x)
+ else
+ fun_l22_n615(x)
+ end
+end
+
+def fun_l21_n550(x)
+ if (x < 1)
+ fun_l22_n45(x)
+ else
+ fun_l22_n161(x)
+ end
+end
+
+def fun_l21_n551(x)
+ if (x < 1)
+ fun_l22_n480(x)
+ else
+ fun_l22_n852(x)
+ end
+end
+
+def fun_l21_n552(x)
+ if (x < 1)
+ fun_l22_n383(x)
+ else
+ fun_l22_n698(x)
+ end
+end
+
+def fun_l21_n553(x)
+ if (x < 1)
+ fun_l22_n805(x)
+ else
+ fun_l22_n309(x)
+ end
+end
+
+def fun_l21_n554(x)
+ if (x < 1)
+ fun_l22_n635(x)
+ else
+ fun_l22_n821(x)
+ end
+end
+
+def fun_l21_n555(x)
+ if (x < 1)
+ fun_l22_n616(x)
+ else
+ fun_l22_n52(x)
+ end
+end
+
+def fun_l21_n556(x)
+ if (x < 1)
+ fun_l22_n283(x)
+ else
+ fun_l22_n514(x)
+ end
+end
+
+def fun_l21_n557(x)
+ if (x < 1)
+ fun_l22_n6(x)
+ else
+ fun_l22_n174(x)
+ end
+end
+
+def fun_l21_n558(x)
+ if (x < 1)
+ fun_l22_n344(x)
+ else
+ fun_l22_n932(x)
+ end
+end
+
+def fun_l21_n559(x)
+ if (x < 1)
+ fun_l22_n287(x)
+ else
+ fun_l22_n98(x)
+ end
+end
+
+def fun_l21_n560(x)
+ if (x < 1)
+ fun_l22_n510(x)
+ else
+ fun_l22_n672(x)
+ end
+end
+
+def fun_l21_n561(x)
+ if (x < 1)
+ fun_l22_n951(x)
+ else
+ fun_l22_n984(x)
+ end
+end
+
+def fun_l21_n562(x)
+ if (x < 1)
+ fun_l22_n133(x)
+ else
+ fun_l22_n207(x)
+ end
+end
+
+def fun_l21_n563(x)
+ if (x < 1)
+ fun_l22_n780(x)
+ else
+ fun_l22_n402(x)
+ end
+end
+
+def fun_l21_n564(x)
+ if (x < 1)
+ fun_l22_n783(x)
+ else
+ fun_l22_n189(x)
+ end
+end
+
+def fun_l21_n565(x)
+ if (x < 1)
+ fun_l22_n736(x)
+ else
+ fun_l22_n590(x)
+ end
+end
+
+def fun_l21_n566(x)
+ if (x < 1)
+ fun_l22_n724(x)
+ else
+ fun_l22_n69(x)
+ end
+end
+
+def fun_l21_n567(x)
+ if (x < 1)
+ fun_l22_n521(x)
+ else
+ fun_l22_n242(x)
+ end
+end
+
+def fun_l21_n568(x)
+ if (x < 1)
+ fun_l22_n440(x)
+ else
+ fun_l22_n156(x)
+ end
+end
+
+def fun_l21_n569(x)
+ if (x < 1)
+ fun_l22_n776(x)
+ else
+ fun_l22_n456(x)
+ end
+end
+
+def fun_l21_n570(x)
+ if (x < 1)
+ fun_l22_n336(x)
+ else
+ fun_l22_n615(x)
+ end
+end
+
+def fun_l21_n571(x)
+ if (x < 1)
+ fun_l22_n775(x)
+ else
+ fun_l22_n585(x)
+ end
+end
+
+def fun_l21_n572(x)
+ if (x < 1)
+ fun_l22_n466(x)
+ else
+ fun_l22_n559(x)
+ end
+end
+
+def fun_l21_n573(x)
+ if (x < 1)
+ fun_l22_n609(x)
+ else
+ fun_l22_n177(x)
+ end
+end
+
+def fun_l21_n574(x)
+ if (x < 1)
+ fun_l22_n310(x)
+ else
+ fun_l22_n190(x)
+ end
+end
+
+def fun_l21_n575(x)
+ if (x < 1)
+ fun_l22_n861(x)
+ else
+ fun_l22_n289(x)
+ end
+end
+
+def fun_l21_n576(x)
+ if (x < 1)
+ fun_l22_n978(x)
+ else
+ fun_l22_n460(x)
+ end
+end
+
+def fun_l21_n577(x)
+ if (x < 1)
+ fun_l22_n440(x)
+ else
+ fun_l22_n816(x)
+ end
+end
+
+def fun_l21_n578(x)
+ if (x < 1)
+ fun_l22_n522(x)
+ else
+ fun_l22_n214(x)
+ end
+end
+
+def fun_l21_n579(x)
+ if (x < 1)
+ fun_l22_n38(x)
+ else
+ fun_l22_n166(x)
+ end
+end
+
+def fun_l21_n580(x)
+ if (x < 1)
+ fun_l22_n114(x)
+ else
+ fun_l22_n314(x)
+ end
+end
+
+def fun_l21_n581(x)
+ if (x < 1)
+ fun_l22_n233(x)
+ else
+ fun_l22_n840(x)
+ end
+end
+
+def fun_l21_n582(x)
+ if (x < 1)
+ fun_l22_n867(x)
+ else
+ fun_l22_n213(x)
+ end
+end
+
+def fun_l21_n583(x)
+ if (x < 1)
+ fun_l22_n742(x)
+ else
+ fun_l22_n798(x)
+ end
+end
+
+def fun_l21_n584(x)
+ if (x < 1)
+ fun_l22_n772(x)
+ else
+ fun_l22_n400(x)
+ end
+end
+
+def fun_l21_n585(x)
+ if (x < 1)
+ fun_l22_n564(x)
+ else
+ fun_l22_n70(x)
+ end
+end
+
+def fun_l21_n586(x)
+ if (x < 1)
+ fun_l22_n836(x)
+ else
+ fun_l22_n188(x)
+ end
+end
+
+def fun_l21_n587(x)
+ if (x < 1)
+ fun_l22_n624(x)
+ else
+ fun_l22_n923(x)
+ end
+end
+
+def fun_l21_n588(x)
+ if (x < 1)
+ fun_l22_n265(x)
+ else
+ fun_l22_n733(x)
+ end
+end
+
+def fun_l21_n589(x)
+ if (x < 1)
+ fun_l22_n545(x)
+ else
+ fun_l22_n399(x)
+ end
+end
+
+def fun_l21_n590(x)
+ if (x < 1)
+ fun_l22_n22(x)
+ else
+ fun_l22_n266(x)
+ end
+end
+
+def fun_l21_n591(x)
+ if (x < 1)
+ fun_l22_n504(x)
+ else
+ fun_l22_n798(x)
+ end
+end
+
+def fun_l21_n592(x)
+ if (x < 1)
+ fun_l22_n979(x)
+ else
+ fun_l22_n712(x)
+ end
+end
+
+def fun_l21_n593(x)
+ if (x < 1)
+ fun_l22_n343(x)
+ else
+ fun_l22_n54(x)
+ end
+end
+
+def fun_l21_n594(x)
+ if (x < 1)
+ fun_l22_n893(x)
+ else
+ fun_l22_n465(x)
+ end
+end
+
+def fun_l21_n595(x)
+ if (x < 1)
+ fun_l22_n28(x)
+ else
+ fun_l22_n162(x)
+ end
+end
+
+def fun_l21_n596(x)
+ if (x < 1)
+ fun_l22_n609(x)
+ else
+ fun_l22_n882(x)
+ end
+end
+
+def fun_l21_n597(x)
+ if (x < 1)
+ fun_l22_n575(x)
+ else
+ fun_l22_n951(x)
+ end
+end
+
+def fun_l21_n598(x)
+ if (x < 1)
+ fun_l22_n794(x)
+ else
+ fun_l22_n767(x)
+ end
+end
+
+def fun_l21_n599(x)
+ if (x < 1)
+ fun_l22_n605(x)
+ else
+ fun_l22_n141(x)
+ end
+end
+
+def fun_l21_n600(x)
+ if (x < 1)
+ fun_l22_n54(x)
+ else
+ fun_l22_n958(x)
+ end
+end
+
+def fun_l21_n601(x)
+ if (x < 1)
+ fun_l22_n506(x)
+ else
+ fun_l22_n269(x)
+ end
+end
+
+def fun_l21_n602(x)
+ if (x < 1)
+ fun_l22_n401(x)
+ else
+ fun_l22_n104(x)
+ end
+end
+
+def fun_l21_n603(x)
+ if (x < 1)
+ fun_l22_n379(x)
+ else
+ fun_l22_n489(x)
+ end
+end
+
+def fun_l21_n604(x)
+ if (x < 1)
+ fun_l22_n673(x)
+ else
+ fun_l22_n502(x)
+ end
+end
+
+def fun_l21_n605(x)
+ if (x < 1)
+ fun_l22_n355(x)
+ else
+ fun_l22_n483(x)
+ end
+end
+
+def fun_l21_n606(x)
+ if (x < 1)
+ fun_l22_n763(x)
+ else
+ fun_l22_n160(x)
+ end
+end
+
+def fun_l21_n607(x)
+ if (x < 1)
+ fun_l22_n802(x)
+ else
+ fun_l22_n414(x)
+ end
+end
+
+def fun_l21_n608(x)
+ if (x < 1)
+ fun_l22_n401(x)
+ else
+ fun_l22_n987(x)
+ end
+end
+
+def fun_l21_n609(x)
+ if (x < 1)
+ fun_l22_n741(x)
+ else
+ fun_l22_n511(x)
+ end
+end
+
+def fun_l21_n610(x)
+ if (x < 1)
+ fun_l22_n883(x)
+ else
+ fun_l22_n73(x)
+ end
+end
+
+def fun_l21_n611(x)
+ if (x < 1)
+ fun_l22_n105(x)
+ else
+ fun_l22_n612(x)
+ end
+end
+
+def fun_l21_n612(x)
+ if (x < 1)
+ fun_l22_n911(x)
+ else
+ fun_l22_n764(x)
+ end
+end
+
+def fun_l21_n613(x)
+ if (x < 1)
+ fun_l22_n818(x)
+ else
+ fun_l22_n43(x)
+ end
+end
+
+def fun_l21_n614(x)
+ if (x < 1)
+ fun_l22_n388(x)
+ else
+ fun_l22_n99(x)
+ end
+end
+
+def fun_l21_n615(x)
+ if (x < 1)
+ fun_l22_n657(x)
+ else
+ fun_l22_n231(x)
+ end
+end
+
+def fun_l21_n616(x)
+ if (x < 1)
+ fun_l22_n937(x)
+ else
+ fun_l22_n357(x)
+ end
+end
+
+def fun_l21_n617(x)
+ if (x < 1)
+ fun_l22_n691(x)
+ else
+ fun_l22_n952(x)
+ end
+end
+
+def fun_l21_n618(x)
+ if (x < 1)
+ fun_l22_n712(x)
+ else
+ fun_l22_n84(x)
+ end
+end
+
+def fun_l21_n619(x)
+ if (x < 1)
+ fun_l22_n483(x)
+ else
+ fun_l22_n506(x)
+ end
+end
+
+def fun_l21_n620(x)
+ if (x < 1)
+ fun_l22_n804(x)
+ else
+ fun_l22_n813(x)
+ end
+end
+
+def fun_l21_n621(x)
+ if (x < 1)
+ fun_l22_n280(x)
+ else
+ fun_l22_n626(x)
+ end
+end
+
+def fun_l21_n622(x)
+ if (x < 1)
+ fun_l22_n979(x)
+ else
+ fun_l22_n508(x)
+ end
+end
+
+def fun_l21_n623(x)
+ if (x < 1)
+ fun_l22_n482(x)
+ else
+ fun_l22_n120(x)
+ end
+end
+
+def fun_l21_n624(x)
+ if (x < 1)
+ fun_l22_n99(x)
+ else
+ fun_l22_n975(x)
+ end
+end
+
+def fun_l21_n625(x)
+ if (x < 1)
+ fun_l22_n540(x)
+ else
+ fun_l22_n68(x)
+ end
+end
+
+def fun_l21_n626(x)
+ if (x < 1)
+ fun_l22_n818(x)
+ else
+ fun_l22_n591(x)
+ end
+end
+
+def fun_l21_n627(x)
+ if (x < 1)
+ fun_l22_n37(x)
+ else
+ fun_l22_n984(x)
+ end
+end
+
+def fun_l21_n628(x)
+ if (x < 1)
+ fun_l22_n547(x)
+ else
+ fun_l22_n482(x)
+ end
+end
+
+def fun_l21_n629(x)
+ if (x < 1)
+ fun_l22_n851(x)
+ else
+ fun_l22_n335(x)
+ end
+end
+
+def fun_l21_n630(x)
+ if (x < 1)
+ fun_l22_n474(x)
+ else
+ fun_l22_n402(x)
+ end
+end
+
+def fun_l21_n631(x)
+ if (x < 1)
+ fun_l22_n433(x)
+ else
+ fun_l22_n298(x)
+ end
+end
+
+def fun_l21_n632(x)
+ if (x < 1)
+ fun_l22_n376(x)
+ else
+ fun_l22_n898(x)
+ end
+end
+
+def fun_l21_n633(x)
+ if (x < 1)
+ fun_l22_n456(x)
+ else
+ fun_l22_n753(x)
+ end
+end
+
+def fun_l21_n634(x)
+ if (x < 1)
+ fun_l22_n888(x)
+ else
+ fun_l22_n394(x)
+ end
+end
+
+def fun_l21_n635(x)
+ if (x < 1)
+ fun_l22_n555(x)
+ else
+ fun_l22_n69(x)
+ end
+end
+
+def fun_l21_n636(x)
+ if (x < 1)
+ fun_l22_n572(x)
+ else
+ fun_l22_n822(x)
+ end
+end
+
+def fun_l21_n637(x)
+ if (x < 1)
+ fun_l22_n645(x)
+ else
+ fun_l22_n968(x)
+ end
+end
+
+def fun_l21_n638(x)
+ if (x < 1)
+ fun_l22_n406(x)
+ else
+ fun_l22_n318(x)
+ end
+end
+
+def fun_l21_n639(x)
+ if (x < 1)
+ fun_l22_n554(x)
+ else
+ fun_l22_n591(x)
+ end
+end
+
+def fun_l21_n640(x)
+ if (x < 1)
+ fun_l22_n478(x)
+ else
+ fun_l22_n962(x)
+ end
+end
+
+def fun_l21_n641(x)
+ if (x < 1)
+ fun_l22_n688(x)
+ else
+ fun_l22_n305(x)
+ end
+end
+
+def fun_l21_n642(x)
+ if (x < 1)
+ fun_l22_n767(x)
+ else
+ fun_l22_n156(x)
+ end
+end
+
+def fun_l21_n643(x)
+ if (x < 1)
+ fun_l22_n264(x)
+ else
+ fun_l22_n489(x)
+ end
+end
+
+def fun_l21_n644(x)
+ if (x < 1)
+ fun_l22_n678(x)
+ else
+ fun_l22_n196(x)
+ end
+end
+
+def fun_l21_n645(x)
+ if (x < 1)
+ fun_l22_n849(x)
+ else
+ fun_l22_n488(x)
+ end
+end
+
+def fun_l21_n646(x)
+ if (x < 1)
+ fun_l22_n837(x)
+ else
+ fun_l22_n274(x)
+ end
+end
+
+def fun_l21_n647(x)
+ if (x < 1)
+ fun_l22_n58(x)
+ else
+ fun_l22_n694(x)
+ end
+end
+
+def fun_l21_n648(x)
+ if (x < 1)
+ fun_l22_n878(x)
+ else
+ fun_l22_n356(x)
+ end
+end
+
+def fun_l21_n649(x)
+ if (x < 1)
+ fun_l22_n945(x)
+ else
+ fun_l22_n28(x)
+ end
+end
+
+def fun_l21_n650(x)
+ if (x < 1)
+ fun_l22_n10(x)
+ else
+ fun_l22_n330(x)
+ end
+end
+
+def fun_l21_n651(x)
+ if (x < 1)
+ fun_l22_n461(x)
+ else
+ fun_l22_n872(x)
+ end
+end
+
+def fun_l21_n652(x)
+ if (x < 1)
+ fun_l22_n860(x)
+ else
+ fun_l22_n358(x)
+ end
+end
+
+def fun_l21_n653(x)
+ if (x < 1)
+ fun_l22_n11(x)
+ else
+ fun_l22_n596(x)
+ end
+end
+
+def fun_l21_n654(x)
+ if (x < 1)
+ fun_l22_n340(x)
+ else
+ fun_l22_n335(x)
+ end
+end
+
+def fun_l21_n655(x)
+ if (x < 1)
+ fun_l22_n259(x)
+ else
+ fun_l22_n642(x)
+ end
+end
+
+def fun_l21_n656(x)
+ if (x < 1)
+ fun_l22_n78(x)
+ else
+ fun_l22_n442(x)
+ end
+end
+
+def fun_l21_n657(x)
+ if (x < 1)
+ fun_l22_n151(x)
+ else
+ fun_l22_n122(x)
+ end
+end
+
+def fun_l21_n658(x)
+ if (x < 1)
+ fun_l22_n440(x)
+ else
+ fun_l22_n940(x)
+ end
+end
+
+def fun_l21_n659(x)
+ if (x < 1)
+ fun_l22_n237(x)
+ else
+ fun_l22_n899(x)
+ end
+end
+
+def fun_l21_n660(x)
+ if (x < 1)
+ fun_l22_n906(x)
+ else
+ fun_l22_n789(x)
+ end
+end
+
+def fun_l21_n661(x)
+ if (x < 1)
+ fun_l22_n812(x)
+ else
+ fun_l22_n492(x)
+ end
+end
+
+def fun_l21_n662(x)
+ if (x < 1)
+ fun_l22_n241(x)
+ else
+ fun_l22_n732(x)
+ end
+end
+
+def fun_l21_n663(x)
+ if (x < 1)
+ fun_l22_n557(x)
+ else
+ fun_l22_n570(x)
+ end
+end
+
+def fun_l21_n664(x)
+ if (x < 1)
+ fun_l22_n928(x)
+ else
+ fun_l22_n943(x)
+ end
+end
+
+def fun_l21_n665(x)
+ if (x < 1)
+ fun_l22_n400(x)
+ else
+ fun_l22_n914(x)
+ end
+end
+
+def fun_l21_n666(x)
+ if (x < 1)
+ fun_l22_n368(x)
+ else
+ fun_l22_n434(x)
+ end
+end
+
+def fun_l21_n667(x)
+ if (x < 1)
+ fun_l22_n827(x)
+ else
+ fun_l22_n213(x)
+ end
+end
+
+def fun_l21_n668(x)
+ if (x < 1)
+ fun_l22_n729(x)
+ else
+ fun_l22_n273(x)
+ end
+end
+
+def fun_l21_n669(x)
+ if (x < 1)
+ fun_l22_n649(x)
+ else
+ fun_l22_n29(x)
+ end
+end
+
+def fun_l21_n670(x)
+ if (x < 1)
+ fun_l22_n878(x)
+ else
+ fun_l22_n794(x)
+ end
+end
+
+def fun_l21_n671(x)
+ if (x < 1)
+ fun_l22_n474(x)
+ else
+ fun_l22_n960(x)
+ end
+end
+
+def fun_l21_n672(x)
+ if (x < 1)
+ fun_l22_n250(x)
+ else
+ fun_l22_n935(x)
+ end
+end
+
+def fun_l21_n673(x)
+ if (x < 1)
+ fun_l22_n766(x)
+ else
+ fun_l22_n325(x)
+ end
+end
+
+def fun_l21_n674(x)
+ if (x < 1)
+ fun_l22_n64(x)
+ else
+ fun_l22_n334(x)
+ end
+end
+
+def fun_l21_n675(x)
+ if (x < 1)
+ fun_l22_n737(x)
+ else
+ fun_l22_n983(x)
+ end
+end
+
+def fun_l21_n676(x)
+ if (x < 1)
+ fun_l22_n506(x)
+ else
+ fun_l22_n393(x)
+ end
+end
+
+def fun_l21_n677(x)
+ if (x < 1)
+ fun_l22_n348(x)
+ else
+ fun_l22_n558(x)
+ end
+end
+
+def fun_l21_n678(x)
+ if (x < 1)
+ fun_l22_n68(x)
+ else
+ fun_l22_n483(x)
+ end
+end
+
+def fun_l21_n679(x)
+ if (x < 1)
+ fun_l22_n816(x)
+ else
+ fun_l22_n959(x)
+ end
+end
+
+def fun_l21_n680(x)
+ if (x < 1)
+ fun_l22_n128(x)
+ else
+ fun_l22_n393(x)
+ end
+end
+
+def fun_l21_n681(x)
+ if (x < 1)
+ fun_l22_n738(x)
+ else
+ fun_l22_n609(x)
+ end
+end
+
+def fun_l21_n682(x)
+ if (x < 1)
+ fun_l22_n113(x)
+ else
+ fun_l22_n664(x)
+ end
+end
+
+def fun_l21_n683(x)
+ if (x < 1)
+ fun_l22_n904(x)
+ else
+ fun_l22_n699(x)
+ end
+end
+
+def fun_l21_n684(x)
+ if (x < 1)
+ fun_l22_n759(x)
+ else
+ fun_l22_n277(x)
+ end
+end
+
+def fun_l21_n685(x)
+ if (x < 1)
+ fun_l22_n359(x)
+ else
+ fun_l22_n961(x)
+ end
+end
+
+def fun_l21_n686(x)
+ if (x < 1)
+ fun_l22_n269(x)
+ else
+ fun_l22_n66(x)
+ end
+end
+
+def fun_l21_n687(x)
+ if (x < 1)
+ fun_l22_n510(x)
+ else
+ fun_l22_n935(x)
+ end
+end
+
+def fun_l21_n688(x)
+ if (x < 1)
+ fun_l22_n127(x)
+ else
+ fun_l22_n441(x)
+ end
+end
+
+def fun_l21_n689(x)
+ if (x < 1)
+ fun_l22_n515(x)
+ else
+ fun_l22_n184(x)
+ end
+end
+
+def fun_l21_n690(x)
+ if (x < 1)
+ fun_l22_n339(x)
+ else
+ fun_l22_n121(x)
+ end
+end
+
+def fun_l21_n691(x)
+ if (x < 1)
+ fun_l22_n74(x)
+ else
+ fun_l22_n172(x)
+ end
+end
+
+def fun_l21_n692(x)
+ if (x < 1)
+ fun_l22_n156(x)
+ else
+ fun_l22_n829(x)
+ end
+end
+
+def fun_l21_n693(x)
+ if (x < 1)
+ fun_l22_n761(x)
+ else
+ fun_l22_n322(x)
+ end
+end
+
+def fun_l21_n694(x)
+ if (x < 1)
+ fun_l22_n168(x)
+ else
+ fun_l22_n789(x)
+ end
+end
+
+def fun_l21_n695(x)
+ if (x < 1)
+ fun_l22_n896(x)
+ else
+ fun_l22_n275(x)
+ end
+end
+
+def fun_l21_n696(x)
+ if (x < 1)
+ fun_l22_n283(x)
+ else
+ fun_l22_n195(x)
+ end
+end
+
+def fun_l21_n697(x)
+ if (x < 1)
+ fun_l22_n353(x)
+ else
+ fun_l22_n664(x)
+ end
+end
+
+def fun_l21_n698(x)
+ if (x < 1)
+ fun_l22_n801(x)
+ else
+ fun_l22_n544(x)
+ end
+end
+
+def fun_l21_n699(x)
+ if (x < 1)
+ fun_l22_n729(x)
+ else
+ fun_l22_n323(x)
+ end
+end
+
+def fun_l21_n700(x)
+ if (x < 1)
+ fun_l22_n47(x)
+ else
+ fun_l22_n340(x)
+ end
+end
+
+def fun_l21_n701(x)
+ if (x < 1)
+ fun_l22_n132(x)
+ else
+ fun_l22_n968(x)
+ end
+end
+
+def fun_l21_n702(x)
+ if (x < 1)
+ fun_l22_n556(x)
+ else
+ fun_l22_n23(x)
+ end
+end
+
+def fun_l21_n703(x)
+ if (x < 1)
+ fun_l22_n274(x)
+ else
+ fun_l22_n276(x)
+ end
+end
+
+def fun_l21_n704(x)
+ if (x < 1)
+ fun_l22_n152(x)
+ else
+ fun_l22_n244(x)
+ end
+end
+
+def fun_l21_n705(x)
+ if (x < 1)
+ fun_l22_n508(x)
+ else
+ fun_l22_n350(x)
+ end
+end
+
+def fun_l21_n706(x)
+ if (x < 1)
+ fun_l22_n188(x)
+ else
+ fun_l22_n60(x)
+ end
+end
+
+def fun_l21_n707(x)
+ if (x < 1)
+ fun_l22_n970(x)
+ else
+ fun_l22_n55(x)
+ end
+end
+
+def fun_l21_n708(x)
+ if (x < 1)
+ fun_l22_n840(x)
+ else
+ fun_l22_n990(x)
+ end
+end
+
+def fun_l21_n709(x)
+ if (x < 1)
+ fun_l22_n466(x)
+ else
+ fun_l22_n25(x)
+ end
+end
+
+def fun_l21_n710(x)
+ if (x < 1)
+ fun_l22_n741(x)
+ else
+ fun_l22_n481(x)
+ end
+end
+
+def fun_l21_n711(x)
+ if (x < 1)
+ fun_l22_n859(x)
+ else
+ fun_l22_n58(x)
+ end
+end
+
+def fun_l21_n712(x)
+ if (x < 1)
+ fun_l22_n282(x)
+ else
+ fun_l22_n807(x)
+ end
+end
+
+def fun_l21_n713(x)
+ if (x < 1)
+ fun_l22_n387(x)
+ else
+ fun_l22_n235(x)
+ end
+end
+
+def fun_l21_n714(x)
+ if (x < 1)
+ fun_l22_n558(x)
+ else
+ fun_l22_n494(x)
+ end
+end
+
+def fun_l21_n715(x)
+ if (x < 1)
+ fun_l22_n613(x)
+ else
+ fun_l22_n194(x)
+ end
+end
+
+def fun_l21_n716(x)
+ if (x < 1)
+ fun_l22_n120(x)
+ else
+ fun_l22_n154(x)
+ end
+end
+
+def fun_l21_n717(x)
+ if (x < 1)
+ fun_l22_n501(x)
+ else
+ fun_l22_n540(x)
+ end
+end
+
+def fun_l21_n718(x)
+ if (x < 1)
+ fun_l22_n283(x)
+ else
+ fun_l22_n102(x)
+ end
+end
+
+def fun_l21_n719(x)
+ if (x < 1)
+ fun_l22_n569(x)
+ else
+ fun_l22_n407(x)
+ end
+end
+
+def fun_l21_n720(x)
+ if (x < 1)
+ fun_l22_n86(x)
+ else
+ fun_l22_n99(x)
+ end
+end
+
+def fun_l21_n721(x)
+ if (x < 1)
+ fun_l22_n872(x)
+ else
+ fun_l22_n331(x)
+ end
+end
+
+def fun_l21_n722(x)
+ if (x < 1)
+ fun_l22_n772(x)
+ else
+ fun_l22_n57(x)
+ end
+end
+
+def fun_l21_n723(x)
+ if (x < 1)
+ fun_l22_n396(x)
+ else
+ fun_l22_n534(x)
+ end
+end
+
+def fun_l21_n724(x)
+ if (x < 1)
+ fun_l22_n928(x)
+ else
+ fun_l22_n576(x)
+ end
+end
+
+def fun_l21_n725(x)
+ if (x < 1)
+ fun_l22_n650(x)
+ else
+ fun_l22_n790(x)
+ end
+end
+
+def fun_l21_n726(x)
+ if (x < 1)
+ fun_l22_n173(x)
+ else
+ fun_l22_n480(x)
+ end
+end
+
+def fun_l21_n727(x)
+ if (x < 1)
+ fun_l22_n222(x)
+ else
+ fun_l22_n258(x)
+ end
+end
+
+def fun_l21_n728(x)
+ if (x < 1)
+ fun_l22_n797(x)
+ else
+ fun_l22_n793(x)
+ end
+end
+
+def fun_l21_n729(x)
+ if (x < 1)
+ fun_l22_n260(x)
+ else
+ fun_l22_n737(x)
+ end
+end
+
+def fun_l21_n730(x)
+ if (x < 1)
+ fun_l22_n419(x)
+ else
+ fun_l22_n974(x)
+ end
+end
+
+def fun_l21_n731(x)
+ if (x < 1)
+ fun_l22_n837(x)
+ else
+ fun_l22_n628(x)
+ end
+end
+
+def fun_l21_n732(x)
+ if (x < 1)
+ fun_l22_n753(x)
+ else
+ fun_l22_n380(x)
+ end
+end
+
+def fun_l21_n733(x)
+ if (x < 1)
+ fun_l22_n420(x)
+ else
+ fun_l22_n890(x)
+ end
+end
+
+def fun_l21_n734(x)
+ if (x < 1)
+ fun_l22_n993(x)
+ else
+ fun_l22_n172(x)
+ end
+end
+
+def fun_l21_n735(x)
+ if (x < 1)
+ fun_l22_n123(x)
+ else
+ fun_l22_n290(x)
+ end
+end
+
+def fun_l21_n736(x)
+ if (x < 1)
+ fun_l22_n805(x)
+ else
+ fun_l22_n923(x)
+ end
+end
+
+def fun_l21_n737(x)
+ if (x < 1)
+ fun_l22_n124(x)
+ else
+ fun_l22_n25(x)
+ end
+end
+
+def fun_l21_n738(x)
+ if (x < 1)
+ fun_l22_n192(x)
+ else
+ fun_l22_n258(x)
+ end
+end
+
+def fun_l21_n739(x)
+ if (x < 1)
+ fun_l22_n243(x)
+ else
+ fun_l22_n512(x)
+ end
+end
+
+def fun_l21_n740(x)
+ if (x < 1)
+ fun_l22_n577(x)
+ else
+ fun_l22_n307(x)
+ end
+end
+
+def fun_l21_n741(x)
+ if (x < 1)
+ fun_l22_n422(x)
+ else
+ fun_l22_n51(x)
+ end
+end
+
+def fun_l21_n742(x)
+ if (x < 1)
+ fun_l22_n247(x)
+ else
+ fun_l22_n453(x)
+ end
+end
+
+def fun_l21_n743(x)
+ if (x < 1)
+ fun_l22_n369(x)
+ else
+ fun_l22_n564(x)
+ end
+end
+
+def fun_l21_n744(x)
+ if (x < 1)
+ fun_l22_n815(x)
+ else
+ fun_l22_n894(x)
+ end
+end
+
+def fun_l21_n745(x)
+ if (x < 1)
+ fun_l22_n526(x)
+ else
+ fun_l22_n555(x)
+ end
+end
+
+def fun_l21_n746(x)
+ if (x < 1)
+ fun_l22_n281(x)
+ else
+ fun_l22_n121(x)
+ end
+end
+
+def fun_l21_n747(x)
+ if (x < 1)
+ fun_l22_n141(x)
+ else
+ fun_l22_n335(x)
+ end
+end
+
+def fun_l21_n748(x)
+ if (x < 1)
+ fun_l22_n73(x)
+ else
+ fun_l22_n241(x)
+ end
+end
+
+def fun_l21_n749(x)
+ if (x < 1)
+ fun_l22_n201(x)
+ else
+ fun_l22_n650(x)
+ end
+end
+
+def fun_l21_n750(x)
+ if (x < 1)
+ fun_l22_n569(x)
+ else
+ fun_l22_n231(x)
+ end
+end
+
+def fun_l21_n751(x)
+ if (x < 1)
+ fun_l22_n23(x)
+ else
+ fun_l22_n315(x)
+ end
+end
+
+def fun_l21_n752(x)
+ if (x < 1)
+ fun_l22_n951(x)
+ else
+ fun_l22_n697(x)
+ end
+end
+
+def fun_l21_n753(x)
+ if (x < 1)
+ fun_l22_n734(x)
+ else
+ fun_l22_n991(x)
+ end
+end
+
+def fun_l21_n754(x)
+ if (x < 1)
+ fun_l22_n557(x)
+ else
+ fun_l22_n85(x)
+ end
+end
+
+def fun_l21_n755(x)
+ if (x < 1)
+ fun_l22_n213(x)
+ else
+ fun_l22_n918(x)
+ end
+end
+
+def fun_l21_n756(x)
+ if (x < 1)
+ fun_l22_n995(x)
+ else
+ fun_l22_n134(x)
+ end
+end
+
+def fun_l21_n757(x)
+ if (x < 1)
+ fun_l22_n173(x)
+ else
+ fun_l22_n764(x)
+ end
+end
+
+def fun_l21_n758(x)
+ if (x < 1)
+ fun_l22_n503(x)
+ else
+ fun_l22_n370(x)
+ end
+end
+
+def fun_l21_n759(x)
+ if (x < 1)
+ fun_l22_n922(x)
+ else
+ fun_l22_n819(x)
+ end
+end
+
+def fun_l21_n760(x)
+ if (x < 1)
+ fun_l22_n901(x)
+ else
+ fun_l22_n252(x)
+ end
+end
+
+def fun_l21_n761(x)
+ if (x < 1)
+ fun_l22_n928(x)
+ else
+ fun_l22_n958(x)
+ end
+end
+
+def fun_l21_n762(x)
+ if (x < 1)
+ fun_l22_n402(x)
+ else
+ fun_l22_n756(x)
+ end
+end
+
+def fun_l21_n763(x)
+ if (x < 1)
+ fun_l22_n223(x)
+ else
+ fun_l22_n781(x)
+ end
+end
+
+def fun_l21_n764(x)
+ if (x < 1)
+ fun_l22_n692(x)
+ else
+ fun_l22_n893(x)
+ end
+end
+
+def fun_l21_n765(x)
+ if (x < 1)
+ fun_l22_n308(x)
+ else
+ fun_l22_n485(x)
+ end
+end
+
+def fun_l21_n766(x)
+ if (x < 1)
+ fun_l22_n858(x)
+ else
+ fun_l22_n316(x)
+ end
+end
+
+def fun_l21_n767(x)
+ if (x < 1)
+ fun_l22_n546(x)
+ else
+ fun_l22_n793(x)
+ end
+end
+
+def fun_l21_n768(x)
+ if (x < 1)
+ fun_l22_n75(x)
+ else
+ fun_l22_n999(x)
+ end
+end
+
+def fun_l21_n769(x)
+ if (x < 1)
+ fun_l22_n758(x)
+ else
+ fun_l22_n149(x)
+ end
+end
+
+def fun_l21_n770(x)
+ if (x < 1)
+ fun_l22_n801(x)
+ else
+ fun_l22_n594(x)
+ end
+end
+
+def fun_l21_n771(x)
+ if (x < 1)
+ fun_l22_n544(x)
+ else
+ fun_l22_n477(x)
+ end
+end
+
+def fun_l21_n772(x)
+ if (x < 1)
+ fun_l22_n118(x)
+ else
+ fun_l22_n406(x)
+ end
+end
+
+def fun_l21_n773(x)
+ if (x < 1)
+ fun_l22_n741(x)
+ else
+ fun_l22_n539(x)
+ end
+end
+
+def fun_l21_n774(x)
+ if (x < 1)
+ fun_l22_n99(x)
+ else
+ fun_l22_n636(x)
+ end
+end
+
+def fun_l21_n775(x)
+ if (x < 1)
+ fun_l22_n54(x)
+ else
+ fun_l22_n139(x)
+ end
+end
+
+def fun_l21_n776(x)
+ if (x < 1)
+ fun_l22_n990(x)
+ else
+ fun_l22_n518(x)
+ end
+end
+
+def fun_l21_n777(x)
+ if (x < 1)
+ fun_l22_n172(x)
+ else
+ fun_l22_n432(x)
+ end
+end
+
+def fun_l21_n778(x)
+ if (x < 1)
+ fun_l22_n302(x)
+ else
+ fun_l22_n406(x)
+ end
+end
+
+def fun_l21_n779(x)
+ if (x < 1)
+ fun_l22_n199(x)
+ else
+ fun_l22_n198(x)
+ end
+end
+
+def fun_l21_n780(x)
+ if (x < 1)
+ fun_l22_n454(x)
+ else
+ fun_l22_n547(x)
+ end
+end
+
+def fun_l21_n781(x)
+ if (x < 1)
+ fun_l22_n234(x)
+ else
+ fun_l22_n332(x)
+ end
+end
+
+def fun_l21_n782(x)
+ if (x < 1)
+ fun_l22_n693(x)
+ else
+ fun_l22_n800(x)
+ end
+end
+
+def fun_l21_n783(x)
+ if (x < 1)
+ fun_l22_n728(x)
+ else
+ fun_l22_n799(x)
+ end
+end
+
+def fun_l21_n784(x)
+ if (x < 1)
+ fun_l22_n594(x)
+ else
+ fun_l22_n350(x)
+ end
+end
+
+def fun_l21_n785(x)
+ if (x < 1)
+ fun_l22_n695(x)
+ else
+ fun_l22_n596(x)
+ end
+end
+
+def fun_l21_n786(x)
+ if (x < 1)
+ fun_l22_n141(x)
+ else
+ fun_l22_n372(x)
+ end
+end
+
+def fun_l21_n787(x)
+ if (x < 1)
+ fun_l22_n15(x)
+ else
+ fun_l22_n352(x)
+ end
+end
+
+def fun_l21_n788(x)
+ if (x < 1)
+ fun_l22_n769(x)
+ else
+ fun_l22_n62(x)
+ end
+end
+
+def fun_l21_n789(x)
+ if (x < 1)
+ fun_l22_n284(x)
+ else
+ fun_l22_n119(x)
+ end
+end
+
+def fun_l21_n790(x)
+ if (x < 1)
+ fun_l22_n335(x)
+ else
+ fun_l22_n570(x)
+ end
+end
+
+def fun_l21_n791(x)
+ if (x < 1)
+ fun_l22_n779(x)
+ else
+ fun_l22_n104(x)
+ end
+end
+
+def fun_l21_n792(x)
+ if (x < 1)
+ fun_l22_n835(x)
+ else
+ fun_l22_n612(x)
+ end
+end
+
+def fun_l21_n793(x)
+ if (x < 1)
+ fun_l22_n241(x)
+ else
+ fun_l22_n883(x)
+ end
+end
+
+def fun_l21_n794(x)
+ if (x < 1)
+ fun_l22_n957(x)
+ else
+ fun_l22_n357(x)
+ end
+end
+
+def fun_l21_n795(x)
+ if (x < 1)
+ fun_l22_n78(x)
+ else
+ fun_l22_n392(x)
+ end
+end
+
+def fun_l21_n796(x)
+ if (x < 1)
+ fun_l22_n711(x)
+ else
+ fun_l22_n364(x)
+ end
+end
+
+def fun_l21_n797(x)
+ if (x < 1)
+ fun_l22_n909(x)
+ else
+ fun_l22_n77(x)
+ end
+end
+
+def fun_l21_n798(x)
+ if (x < 1)
+ fun_l22_n901(x)
+ else
+ fun_l22_n483(x)
+ end
+end
+
+def fun_l21_n799(x)
+ if (x < 1)
+ fun_l22_n429(x)
+ else
+ fun_l22_n244(x)
+ end
+end
+
+def fun_l21_n800(x)
+ if (x < 1)
+ fun_l22_n394(x)
+ else
+ fun_l22_n652(x)
+ end
+end
+
+def fun_l21_n801(x)
+ if (x < 1)
+ fun_l22_n831(x)
+ else
+ fun_l22_n698(x)
+ end
+end
+
+def fun_l21_n802(x)
+ if (x < 1)
+ fun_l22_n623(x)
+ else
+ fun_l22_n382(x)
+ end
+end
+
+def fun_l21_n803(x)
+ if (x < 1)
+ fun_l22_n803(x)
+ else
+ fun_l22_n370(x)
+ end
+end
+
+def fun_l21_n804(x)
+ if (x < 1)
+ fun_l22_n173(x)
+ else
+ fun_l22_n697(x)
+ end
+end
+
+def fun_l21_n805(x)
+ if (x < 1)
+ fun_l22_n653(x)
+ else
+ fun_l22_n514(x)
+ end
+end
+
+def fun_l21_n806(x)
+ if (x < 1)
+ fun_l22_n703(x)
+ else
+ fun_l22_n642(x)
+ end
+end
+
+def fun_l21_n807(x)
+ if (x < 1)
+ fun_l22_n788(x)
+ else
+ fun_l22_n594(x)
+ end
+end
+
+def fun_l21_n808(x)
+ if (x < 1)
+ fun_l22_n389(x)
+ else
+ fun_l22_n3(x)
+ end
+end
+
+def fun_l21_n809(x)
+ if (x < 1)
+ fun_l22_n548(x)
+ else
+ fun_l22_n338(x)
+ end
+end
+
+def fun_l21_n810(x)
+ if (x < 1)
+ fun_l22_n157(x)
+ else
+ fun_l22_n967(x)
+ end
+end
+
+def fun_l21_n811(x)
+ if (x < 1)
+ fun_l22_n573(x)
+ else
+ fun_l22_n91(x)
+ end
+end
+
+def fun_l21_n812(x)
+ if (x < 1)
+ fun_l22_n594(x)
+ else
+ fun_l22_n240(x)
+ end
+end
+
+def fun_l21_n813(x)
+ if (x < 1)
+ fun_l22_n661(x)
+ else
+ fun_l22_n557(x)
+ end
+end
+
+def fun_l21_n814(x)
+ if (x < 1)
+ fun_l22_n29(x)
+ else
+ fun_l22_n808(x)
+ end
+end
+
+def fun_l21_n815(x)
+ if (x < 1)
+ fun_l22_n212(x)
+ else
+ fun_l22_n592(x)
+ end
+end
+
+def fun_l21_n816(x)
+ if (x < 1)
+ fun_l22_n57(x)
+ else
+ fun_l22_n248(x)
+ end
+end
+
+def fun_l21_n817(x)
+ if (x < 1)
+ fun_l22_n656(x)
+ else
+ fun_l22_n588(x)
+ end
+end
+
+def fun_l21_n818(x)
+ if (x < 1)
+ fun_l22_n949(x)
+ else
+ fun_l22_n284(x)
+ end
+end
+
+def fun_l21_n819(x)
+ if (x < 1)
+ fun_l22_n488(x)
+ else
+ fun_l22_n543(x)
+ end
+end
+
+def fun_l21_n820(x)
+ if (x < 1)
+ fun_l22_n938(x)
+ else
+ fun_l22_n155(x)
+ end
+end
+
+def fun_l21_n821(x)
+ if (x < 1)
+ fun_l22_n4(x)
+ else
+ fun_l22_n888(x)
+ end
+end
+
+def fun_l21_n822(x)
+ if (x < 1)
+ fun_l22_n460(x)
+ else
+ fun_l22_n249(x)
+ end
+end
+
+def fun_l21_n823(x)
+ if (x < 1)
+ fun_l22_n494(x)
+ else
+ fun_l22_n864(x)
+ end
+end
+
+def fun_l21_n824(x)
+ if (x < 1)
+ fun_l22_n239(x)
+ else
+ fun_l22_n305(x)
+ end
+end
+
+def fun_l21_n825(x)
+ if (x < 1)
+ fun_l22_n578(x)
+ else
+ fun_l22_n568(x)
+ end
+end
+
+def fun_l21_n826(x)
+ if (x < 1)
+ fun_l22_n669(x)
+ else
+ fun_l22_n28(x)
+ end
+end
+
+def fun_l21_n827(x)
+ if (x < 1)
+ fun_l22_n928(x)
+ else
+ fun_l22_n43(x)
+ end
+end
+
+def fun_l21_n828(x)
+ if (x < 1)
+ fun_l22_n459(x)
+ else
+ fun_l22_n450(x)
+ end
+end
+
+def fun_l21_n829(x)
+ if (x < 1)
+ fun_l22_n834(x)
+ else
+ fun_l22_n583(x)
+ end
+end
+
+def fun_l21_n830(x)
+ if (x < 1)
+ fun_l22_n655(x)
+ else
+ fun_l22_n674(x)
+ end
+end
+
+def fun_l21_n831(x)
+ if (x < 1)
+ fun_l22_n551(x)
+ else
+ fun_l22_n367(x)
+ end
+end
+
+def fun_l21_n832(x)
+ if (x < 1)
+ fun_l22_n921(x)
+ else
+ fun_l22_n750(x)
+ end
+end
+
+def fun_l21_n833(x)
+ if (x < 1)
+ fun_l22_n255(x)
+ else
+ fun_l22_n253(x)
+ end
+end
+
+def fun_l21_n834(x)
+ if (x < 1)
+ fun_l22_n873(x)
+ else
+ fun_l22_n84(x)
+ end
+end
+
+def fun_l21_n835(x)
+ if (x < 1)
+ fun_l22_n362(x)
+ else
+ fun_l22_n976(x)
+ end
+end
+
+def fun_l21_n836(x)
+ if (x < 1)
+ fun_l22_n677(x)
+ else
+ fun_l22_n429(x)
+ end
+end
+
+def fun_l21_n837(x)
+ if (x < 1)
+ fun_l22_n78(x)
+ else
+ fun_l22_n782(x)
+ end
+end
+
+def fun_l21_n838(x)
+ if (x < 1)
+ fun_l22_n339(x)
+ else
+ fun_l22_n855(x)
+ end
+end
+
+def fun_l21_n839(x)
+ if (x < 1)
+ fun_l22_n73(x)
+ else
+ fun_l22_n13(x)
+ end
+end
+
+def fun_l21_n840(x)
+ if (x < 1)
+ fun_l22_n788(x)
+ else
+ fun_l22_n701(x)
+ end
+end
+
+def fun_l21_n841(x)
+ if (x < 1)
+ fun_l22_n583(x)
+ else
+ fun_l22_n501(x)
+ end
+end
+
+def fun_l21_n842(x)
+ if (x < 1)
+ fun_l22_n532(x)
+ else
+ fun_l22_n190(x)
+ end
+end
+
+def fun_l21_n843(x)
+ if (x < 1)
+ fun_l22_n206(x)
+ else
+ fun_l22_n718(x)
+ end
+end
+
+def fun_l21_n844(x)
+ if (x < 1)
+ fun_l22_n307(x)
+ else
+ fun_l22_n200(x)
+ end
+end
+
+def fun_l21_n845(x)
+ if (x < 1)
+ fun_l22_n83(x)
+ else
+ fun_l22_n294(x)
+ end
+end
+
+def fun_l21_n846(x)
+ if (x < 1)
+ fun_l22_n157(x)
+ else
+ fun_l22_n225(x)
+ end
+end
+
+def fun_l21_n847(x)
+ if (x < 1)
+ fun_l22_n935(x)
+ else
+ fun_l22_n888(x)
+ end
+end
+
+def fun_l21_n848(x)
+ if (x < 1)
+ fun_l22_n840(x)
+ else
+ fun_l22_n606(x)
+ end
+end
+
+def fun_l21_n849(x)
+ if (x < 1)
+ fun_l22_n214(x)
+ else
+ fun_l22_n198(x)
+ end
+end
+
+def fun_l21_n850(x)
+ if (x < 1)
+ fun_l22_n793(x)
+ else
+ fun_l22_n503(x)
+ end
+end
+
+def fun_l21_n851(x)
+ if (x < 1)
+ fun_l22_n210(x)
+ else
+ fun_l22_n267(x)
+ end
+end
+
+def fun_l21_n852(x)
+ if (x < 1)
+ fun_l22_n558(x)
+ else
+ fun_l22_n226(x)
+ end
+end
+
+def fun_l21_n853(x)
+ if (x < 1)
+ fun_l22_n12(x)
+ else
+ fun_l22_n765(x)
+ end
+end
+
+def fun_l21_n854(x)
+ if (x < 1)
+ fun_l22_n136(x)
+ else
+ fun_l22_n713(x)
+ end
+end
+
+def fun_l21_n855(x)
+ if (x < 1)
+ fun_l22_n638(x)
+ else
+ fun_l22_n999(x)
+ end
+end
+
+def fun_l21_n856(x)
+ if (x < 1)
+ fun_l22_n366(x)
+ else
+ fun_l22_n505(x)
+ end
+end
+
+def fun_l21_n857(x)
+ if (x < 1)
+ fun_l22_n935(x)
+ else
+ fun_l22_n657(x)
+ end
+end
+
+def fun_l21_n858(x)
+ if (x < 1)
+ fun_l22_n4(x)
+ else
+ fun_l22_n732(x)
+ end
+end
+
+def fun_l21_n859(x)
+ if (x < 1)
+ fun_l22_n433(x)
+ else
+ fun_l22_n350(x)
+ end
+end
+
+def fun_l21_n860(x)
+ if (x < 1)
+ fun_l22_n988(x)
+ else
+ fun_l22_n855(x)
+ end
+end
+
+def fun_l21_n861(x)
+ if (x < 1)
+ fun_l22_n906(x)
+ else
+ fun_l22_n118(x)
+ end
+end
+
+def fun_l21_n862(x)
+ if (x < 1)
+ fun_l22_n127(x)
+ else
+ fun_l22_n299(x)
+ end
+end
+
+def fun_l21_n863(x)
+ if (x < 1)
+ fun_l22_n324(x)
+ else
+ fun_l22_n776(x)
+ end
+end
+
+def fun_l21_n864(x)
+ if (x < 1)
+ fun_l22_n208(x)
+ else
+ fun_l22_n827(x)
+ end
+end
+
+def fun_l21_n865(x)
+ if (x < 1)
+ fun_l22_n846(x)
+ else
+ fun_l22_n750(x)
+ end
+end
+
+def fun_l21_n866(x)
+ if (x < 1)
+ fun_l22_n275(x)
+ else
+ fun_l22_n179(x)
+ end
+end
+
+def fun_l21_n867(x)
+ if (x < 1)
+ fun_l22_n234(x)
+ else
+ fun_l22_n809(x)
+ end
+end
+
+def fun_l21_n868(x)
+ if (x < 1)
+ fun_l22_n597(x)
+ else
+ fun_l22_n563(x)
+ end
+end
+
+def fun_l21_n869(x)
+ if (x < 1)
+ fun_l22_n987(x)
+ else
+ fun_l22_n690(x)
+ end
+end
+
+def fun_l21_n870(x)
+ if (x < 1)
+ fun_l22_n176(x)
+ else
+ fun_l22_n991(x)
+ end
+end
+
+def fun_l21_n871(x)
+ if (x < 1)
+ fun_l22_n272(x)
+ else
+ fun_l22_n211(x)
+ end
+end
+
+def fun_l21_n872(x)
+ if (x < 1)
+ fun_l22_n976(x)
+ else
+ fun_l22_n940(x)
+ end
+end
+
+def fun_l21_n873(x)
+ if (x < 1)
+ fun_l22_n871(x)
+ else
+ fun_l22_n866(x)
+ end
+end
+
+def fun_l21_n874(x)
+ if (x < 1)
+ fun_l22_n727(x)
+ else
+ fun_l22_n560(x)
+ end
+end
+
+def fun_l21_n875(x)
+ if (x < 1)
+ fun_l22_n201(x)
+ else
+ fun_l22_n423(x)
+ end
+end
+
+def fun_l21_n876(x)
+ if (x < 1)
+ fun_l22_n245(x)
+ else
+ fun_l22_n33(x)
+ end
+end
+
+def fun_l21_n877(x)
+ if (x < 1)
+ fun_l22_n535(x)
+ else
+ fun_l22_n11(x)
+ end
+end
+
+def fun_l21_n878(x)
+ if (x < 1)
+ fun_l22_n11(x)
+ else
+ fun_l22_n140(x)
+ end
+end
+
+def fun_l21_n879(x)
+ if (x < 1)
+ fun_l22_n757(x)
+ else
+ fun_l22_n64(x)
+ end
+end
+
+def fun_l21_n880(x)
+ if (x < 1)
+ fun_l22_n982(x)
+ else
+ fun_l22_n774(x)
+ end
+end
+
+def fun_l21_n881(x)
+ if (x < 1)
+ fun_l22_n324(x)
+ else
+ fun_l22_n903(x)
+ end
+end
+
+def fun_l21_n882(x)
+ if (x < 1)
+ fun_l22_n257(x)
+ else
+ fun_l22_n232(x)
+ end
+end
+
+def fun_l21_n883(x)
+ if (x < 1)
+ fun_l22_n546(x)
+ else
+ fun_l22_n317(x)
+ end
+end
+
+def fun_l21_n884(x)
+ if (x < 1)
+ fun_l22_n40(x)
+ else
+ fun_l22_n393(x)
+ end
+end
+
+def fun_l21_n885(x)
+ if (x < 1)
+ fun_l22_n281(x)
+ else
+ fun_l22_n572(x)
+ end
+end
+
+def fun_l21_n886(x)
+ if (x < 1)
+ fun_l22_n41(x)
+ else
+ fun_l22_n656(x)
+ end
+end
+
+def fun_l21_n887(x)
+ if (x < 1)
+ fun_l22_n911(x)
+ else
+ fun_l22_n55(x)
+ end
+end
+
+def fun_l21_n888(x)
+ if (x < 1)
+ fun_l22_n555(x)
+ else
+ fun_l22_n60(x)
+ end
+end
+
+def fun_l21_n889(x)
+ if (x < 1)
+ fun_l22_n69(x)
+ else
+ fun_l22_n330(x)
+ end
+end
+
+def fun_l21_n890(x)
+ if (x < 1)
+ fun_l22_n332(x)
+ else
+ fun_l22_n573(x)
+ end
+end
+
+def fun_l21_n891(x)
+ if (x < 1)
+ fun_l22_n529(x)
+ else
+ fun_l22_n555(x)
+ end
+end
+
+def fun_l21_n892(x)
+ if (x < 1)
+ fun_l22_n900(x)
+ else
+ fun_l22_n137(x)
+ end
+end
+
+def fun_l21_n893(x)
+ if (x < 1)
+ fun_l22_n479(x)
+ else
+ fun_l22_n196(x)
+ end
+end
+
+def fun_l21_n894(x)
+ if (x < 1)
+ fun_l22_n418(x)
+ else
+ fun_l22_n124(x)
+ end
+end
+
+def fun_l21_n895(x)
+ if (x < 1)
+ fun_l22_n658(x)
+ else
+ fun_l22_n196(x)
+ end
+end
+
+def fun_l21_n896(x)
+ if (x < 1)
+ fun_l22_n739(x)
+ else
+ fun_l22_n454(x)
+ end
+end
+
+def fun_l21_n897(x)
+ if (x < 1)
+ fun_l22_n716(x)
+ else
+ fun_l22_n150(x)
+ end
+end
+
+def fun_l21_n898(x)
+ if (x < 1)
+ fun_l22_n356(x)
+ else
+ fun_l22_n264(x)
+ end
+end
+
+def fun_l21_n899(x)
+ if (x < 1)
+ fun_l22_n667(x)
+ else
+ fun_l22_n629(x)
+ end
+end
+
+def fun_l21_n900(x)
+ if (x < 1)
+ fun_l22_n879(x)
+ else
+ fun_l22_n237(x)
+ end
+end
+
+def fun_l21_n901(x)
+ if (x < 1)
+ fun_l22_n462(x)
+ else
+ fun_l22_n401(x)
+ end
+end
+
+def fun_l21_n902(x)
+ if (x < 1)
+ fun_l22_n902(x)
+ else
+ fun_l22_n203(x)
+ end
+end
+
+def fun_l21_n903(x)
+ if (x < 1)
+ fun_l22_n802(x)
+ else
+ fun_l22_n383(x)
+ end
+end
+
+def fun_l21_n904(x)
+ if (x < 1)
+ fun_l22_n672(x)
+ else
+ fun_l22_n808(x)
+ end
+end
+
+def fun_l21_n905(x)
+ if (x < 1)
+ fun_l22_n625(x)
+ else
+ fun_l22_n320(x)
+ end
+end
+
+def fun_l21_n906(x)
+ if (x < 1)
+ fun_l22_n963(x)
+ else
+ fun_l22_n101(x)
+ end
+end
+
+def fun_l21_n907(x)
+ if (x < 1)
+ fun_l22_n609(x)
+ else
+ fun_l22_n500(x)
+ end
+end
+
+def fun_l21_n908(x)
+ if (x < 1)
+ fun_l22_n79(x)
+ else
+ fun_l22_n774(x)
+ end
+end
+
+def fun_l21_n909(x)
+ if (x < 1)
+ fun_l22_n152(x)
+ else
+ fun_l22_n245(x)
+ end
+end
+
+def fun_l21_n910(x)
+ if (x < 1)
+ fun_l22_n981(x)
+ else
+ fun_l22_n647(x)
+ end
+end
+
+def fun_l21_n911(x)
+ if (x < 1)
+ fun_l22_n457(x)
+ else
+ fun_l22_n394(x)
+ end
+end
+
+def fun_l21_n912(x)
+ if (x < 1)
+ fun_l22_n516(x)
+ else
+ fun_l22_n411(x)
+ end
+end
+
+def fun_l21_n913(x)
+ if (x < 1)
+ fun_l22_n212(x)
+ else
+ fun_l22_n159(x)
+ end
+end
+
+def fun_l21_n914(x)
+ if (x < 1)
+ fun_l22_n756(x)
+ else
+ fun_l22_n612(x)
+ end
+end
+
+def fun_l21_n915(x)
+ if (x < 1)
+ fun_l22_n78(x)
+ else
+ fun_l22_n387(x)
+ end
+end
+
+def fun_l21_n916(x)
+ if (x < 1)
+ fun_l22_n973(x)
+ else
+ fun_l22_n854(x)
+ end
+end
+
+def fun_l21_n917(x)
+ if (x < 1)
+ fun_l22_n613(x)
+ else
+ fun_l22_n78(x)
+ end
+end
+
+def fun_l21_n918(x)
+ if (x < 1)
+ fun_l22_n199(x)
+ else
+ fun_l22_n637(x)
+ end
+end
+
+def fun_l21_n919(x)
+ if (x < 1)
+ fun_l22_n834(x)
+ else
+ fun_l22_n804(x)
+ end
+end
+
+def fun_l21_n920(x)
+ if (x < 1)
+ fun_l22_n410(x)
+ else
+ fun_l22_n728(x)
+ end
+end
+
+def fun_l21_n921(x)
+ if (x < 1)
+ fun_l22_n139(x)
+ else
+ fun_l22_n236(x)
+ end
+end
+
+def fun_l21_n922(x)
+ if (x < 1)
+ fun_l22_n443(x)
+ else
+ fun_l22_n683(x)
+ end
+end
+
+def fun_l21_n923(x)
+ if (x < 1)
+ fun_l22_n226(x)
+ else
+ fun_l22_n906(x)
+ end
+end
+
+def fun_l21_n924(x)
+ if (x < 1)
+ fun_l22_n487(x)
+ else
+ fun_l22_n551(x)
+ end
+end
+
+def fun_l21_n925(x)
+ if (x < 1)
+ fun_l22_n143(x)
+ else
+ fun_l22_n932(x)
+ end
+end
+
+def fun_l21_n926(x)
+ if (x < 1)
+ fun_l22_n533(x)
+ else
+ fun_l22_n307(x)
+ end
+end
+
+def fun_l21_n927(x)
+ if (x < 1)
+ fun_l22_n89(x)
+ else
+ fun_l22_n278(x)
+ end
+end
+
+def fun_l21_n928(x)
+ if (x < 1)
+ fun_l22_n802(x)
+ else
+ fun_l22_n18(x)
+ end
+end
+
+def fun_l21_n929(x)
+ if (x < 1)
+ fun_l22_n266(x)
+ else
+ fun_l22_n924(x)
+ end
+end
+
+def fun_l21_n930(x)
+ if (x < 1)
+ fun_l22_n607(x)
+ else
+ fun_l22_n47(x)
+ end
+end
+
+def fun_l21_n931(x)
+ if (x < 1)
+ fun_l22_n241(x)
+ else
+ fun_l22_n983(x)
+ end
+end
+
+def fun_l21_n932(x)
+ if (x < 1)
+ fun_l22_n264(x)
+ else
+ fun_l22_n88(x)
+ end
+end
+
+def fun_l21_n933(x)
+ if (x < 1)
+ fun_l22_n26(x)
+ else
+ fun_l22_n940(x)
+ end
+end
+
+def fun_l21_n934(x)
+ if (x < 1)
+ fun_l22_n688(x)
+ else
+ fun_l22_n248(x)
+ end
+end
+
+def fun_l21_n935(x)
+ if (x < 1)
+ fun_l22_n704(x)
+ else
+ fun_l22_n808(x)
+ end
+end
+
+def fun_l21_n936(x)
+ if (x < 1)
+ fun_l22_n91(x)
+ else
+ fun_l22_n650(x)
+ end
+end
+
+def fun_l21_n937(x)
+ if (x < 1)
+ fun_l22_n308(x)
+ else
+ fun_l22_n389(x)
+ end
+end
+
+def fun_l21_n938(x)
+ if (x < 1)
+ fun_l22_n63(x)
+ else
+ fun_l22_n704(x)
+ end
+end
+
+def fun_l21_n939(x)
+ if (x < 1)
+ fun_l22_n785(x)
+ else
+ fun_l22_n852(x)
+ end
+end
+
+def fun_l21_n940(x)
+ if (x < 1)
+ fun_l22_n515(x)
+ else
+ fun_l22_n148(x)
+ end
+end
+
+def fun_l21_n941(x)
+ if (x < 1)
+ fun_l22_n607(x)
+ else
+ fun_l22_n162(x)
+ end
+end
+
+def fun_l21_n942(x)
+ if (x < 1)
+ fun_l22_n34(x)
+ else
+ fun_l22_n167(x)
+ end
+end
+
+def fun_l21_n943(x)
+ if (x < 1)
+ fun_l22_n239(x)
+ else
+ fun_l22_n100(x)
+ end
+end
+
+def fun_l21_n944(x)
+ if (x < 1)
+ fun_l22_n724(x)
+ else
+ fun_l22_n702(x)
+ end
+end
+
+def fun_l21_n945(x)
+ if (x < 1)
+ fun_l22_n121(x)
+ else
+ fun_l22_n89(x)
+ end
+end
+
+def fun_l21_n946(x)
+ if (x < 1)
+ fun_l22_n699(x)
+ else
+ fun_l22_n410(x)
+ end
+end
+
+def fun_l21_n947(x)
+ if (x < 1)
+ fun_l22_n33(x)
+ else
+ fun_l22_n843(x)
+ end
+end
+
+def fun_l21_n948(x)
+ if (x < 1)
+ fun_l22_n327(x)
+ else
+ fun_l22_n702(x)
+ end
+end
+
+def fun_l21_n949(x)
+ if (x < 1)
+ fun_l22_n191(x)
+ else
+ fun_l22_n137(x)
+ end
+end
+
+def fun_l21_n950(x)
+ if (x < 1)
+ fun_l22_n834(x)
+ else
+ fun_l22_n504(x)
+ end
+end
+
+def fun_l21_n951(x)
+ if (x < 1)
+ fun_l22_n444(x)
+ else
+ fun_l22_n857(x)
+ end
+end
+
+def fun_l21_n952(x)
+ if (x < 1)
+ fun_l22_n961(x)
+ else
+ fun_l22_n817(x)
+ end
+end
+
+def fun_l21_n953(x)
+ if (x < 1)
+ fun_l22_n166(x)
+ else
+ fun_l22_n538(x)
+ end
+end
+
+def fun_l21_n954(x)
+ if (x < 1)
+ fun_l22_n934(x)
+ else
+ fun_l22_n552(x)
+ end
+end
+
+def fun_l21_n955(x)
+ if (x < 1)
+ fun_l22_n144(x)
+ else
+ fun_l22_n814(x)
+ end
+end
+
+def fun_l21_n956(x)
+ if (x < 1)
+ fun_l22_n965(x)
+ else
+ fun_l22_n929(x)
+ end
+end
+
+def fun_l21_n957(x)
+ if (x < 1)
+ fun_l22_n812(x)
+ else
+ fun_l22_n529(x)
+ end
+end
+
+def fun_l21_n958(x)
+ if (x < 1)
+ fun_l22_n625(x)
+ else
+ fun_l22_n974(x)
+ end
+end
+
+def fun_l21_n959(x)
+ if (x < 1)
+ fun_l22_n627(x)
+ else
+ fun_l22_n262(x)
+ end
+end
+
+def fun_l21_n960(x)
+ if (x < 1)
+ fun_l22_n751(x)
+ else
+ fun_l22_n858(x)
+ end
+end
+
+def fun_l21_n961(x)
+ if (x < 1)
+ fun_l22_n819(x)
+ else
+ fun_l22_n408(x)
+ end
+end
+
+def fun_l21_n962(x)
+ if (x < 1)
+ fun_l22_n635(x)
+ else
+ fun_l22_n730(x)
+ end
+end
+
+def fun_l21_n963(x)
+ if (x < 1)
+ fun_l22_n865(x)
+ else
+ fun_l22_n919(x)
+ end
+end
+
+def fun_l21_n964(x)
+ if (x < 1)
+ fun_l22_n368(x)
+ else
+ fun_l22_n912(x)
+ end
+end
+
+def fun_l21_n965(x)
+ if (x < 1)
+ fun_l22_n202(x)
+ else
+ fun_l22_n493(x)
+ end
+end
+
+def fun_l21_n966(x)
+ if (x < 1)
+ fun_l22_n191(x)
+ else
+ fun_l22_n632(x)
+ end
+end
+
+def fun_l21_n967(x)
+ if (x < 1)
+ fun_l22_n96(x)
+ else
+ fun_l22_n329(x)
+ end
+end
+
+def fun_l21_n968(x)
+ if (x < 1)
+ fun_l22_n42(x)
+ else
+ fun_l22_n196(x)
+ end
+end
+
+def fun_l21_n969(x)
+ if (x < 1)
+ fun_l22_n521(x)
+ else
+ fun_l22_n875(x)
+ end
+end
+
+def fun_l21_n970(x)
+ if (x < 1)
+ fun_l22_n202(x)
+ else
+ fun_l22_n373(x)
+ end
+end
+
+def fun_l21_n971(x)
+ if (x < 1)
+ fun_l22_n647(x)
+ else
+ fun_l22_n591(x)
+ end
+end
+
+def fun_l21_n972(x)
+ if (x < 1)
+ fun_l22_n341(x)
+ else
+ fun_l22_n935(x)
+ end
+end
+
+def fun_l21_n973(x)
+ if (x < 1)
+ fun_l22_n151(x)
+ else
+ fun_l22_n396(x)
+ end
+end
+
+def fun_l21_n974(x)
+ if (x < 1)
+ fun_l22_n65(x)
+ else
+ fun_l22_n562(x)
+ end
+end
+
+def fun_l21_n975(x)
+ if (x < 1)
+ fun_l22_n450(x)
+ else
+ fun_l22_n482(x)
+ end
+end
+
+def fun_l21_n976(x)
+ if (x < 1)
+ fun_l22_n179(x)
+ else
+ fun_l22_n838(x)
+ end
+end
+
+def fun_l21_n977(x)
+ if (x < 1)
+ fun_l22_n571(x)
+ else
+ fun_l22_n703(x)
+ end
+end
+
+def fun_l21_n978(x)
+ if (x < 1)
+ fun_l22_n540(x)
+ else
+ fun_l22_n728(x)
+ end
+end
+
+def fun_l21_n979(x)
+ if (x < 1)
+ fun_l22_n170(x)
+ else
+ fun_l22_n487(x)
+ end
+end
+
+def fun_l21_n980(x)
+ if (x < 1)
+ fun_l22_n12(x)
+ else
+ fun_l22_n165(x)
+ end
+end
+
+def fun_l21_n981(x)
+ if (x < 1)
+ fun_l22_n722(x)
+ else
+ fun_l22_n456(x)
+ end
+end
+
+def fun_l21_n982(x)
+ if (x < 1)
+ fun_l22_n313(x)
+ else
+ fun_l22_n175(x)
+ end
+end
+
+def fun_l21_n983(x)
+ if (x < 1)
+ fun_l22_n473(x)
+ else
+ fun_l22_n840(x)
+ end
+end
+
+def fun_l21_n984(x)
+ if (x < 1)
+ fun_l22_n942(x)
+ else
+ fun_l22_n804(x)
+ end
+end
+
+def fun_l21_n985(x)
+ if (x < 1)
+ fun_l22_n116(x)
+ else
+ fun_l22_n117(x)
+ end
+end
+
+def fun_l21_n986(x)
+ if (x < 1)
+ fun_l22_n610(x)
+ else
+ fun_l22_n580(x)
+ end
+end
+
+def fun_l21_n987(x)
+ if (x < 1)
+ fun_l22_n299(x)
+ else
+ fun_l22_n416(x)
+ end
+end
+
+def fun_l21_n988(x)
+ if (x < 1)
+ fun_l22_n507(x)
+ else
+ fun_l22_n995(x)
+ end
+end
+
+def fun_l21_n989(x)
+ if (x < 1)
+ fun_l22_n239(x)
+ else
+ fun_l22_n414(x)
+ end
+end
+
+def fun_l21_n990(x)
+ if (x < 1)
+ fun_l22_n488(x)
+ else
+ fun_l22_n874(x)
+ end
+end
+
+def fun_l21_n991(x)
+ if (x < 1)
+ fun_l22_n586(x)
+ else
+ fun_l22_n88(x)
+ end
+end
+
+def fun_l21_n992(x)
+ if (x < 1)
+ fun_l22_n391(x)
+ else
+ fun_l22_n254(x)
+ end
+end
+
+def fun_l21_n993(x)
+ if (x < 1)
+ fun_l22_n64(x)
+ else
+ fun_l22_n485(x)
+ end
+end
+
+def fun_l21_n994(x)
+ if (x < 1)
+ fun_l22_n507(x)
+ else
+ fun_l22_n266(x)
+ end
+end
+
+def fun_l21_n995(x)
+ if (x < 1)
+ fun_l22_n660(x)
+ else
+ fun_l22_n208(x)
+ end
+end
+
+def fun_l21_n996(x)
+ if (x < 1)
+ fun_l22_n731(x)
+ else
+ fun_l22_n882(x)
+ end
+end
+
+def fun_l21_n997(x)
+ if (x < 1)
+ fun_l22_n283(x)
+ else
+ fun_l22_n719(x)
+ end
+end
+
+def fun_l21_n998(x)
+ if (x < 1)
+ fun_l22_n794(x)
+ else
+ fun_l22_n654(x)
+ end
+end
+
+def fun_l21_n999(x)
+ if (x < 1)
+ fun_l22_n642(x)
+ else
+ fun_l22_n158(x)
+ end
+end
+
+def fun_l22_n0(x)
+ if (x < 1)
+ fun_l23_n423(x)
+ else
+ fun_l23_n28(x)
+ end
+end
+
+def fun_l22_n1(x)
+ if (x < 1)
+ fun_l23_n494(x)
+ else
+ fun_l23_n894(x)
+ end
+end
+
+def fun_l22_n2(x)
+ if (x < 1)
+ fun_l23_n735(x)
+ else
+ fun_l23_n584(x)
+ end
+end
+
+def fun_l22_n3(x)
+ if (x < 1)
+ fun_l23_n982(x)
+ else
+ fun_l23_n790(x)
+ end
+end
+
+def fun_l22_n4(x)
+ if (x < 1)
+ fun_l23_n281(x)
+ else
+ fun_l23_n256(x)
+ end
+end
+
+def fun_l22_n5(x)
+ if (x < 1)
+ fun_l23_n286(x)
+ else
+ fun_l23_n48(x)
+ end
+end
+
+def fun_l22_n6(x)
+ if (x < 1)
+ fun_l23_n982(x)
+ else
+ fun_l23_n731(x)
+ end
+end
+
+def fun_l22_n7(x)
+ if (x < 1)
+ fun_l23_n83(x)
+ else
+ fun_l23_n267(x)
+ end
+end
+
+def fun_l22_n8(x)
+ if (x < 1)
+ fun_l23_n730(x)
+ else
+ fun_l23_n47(x)
+ end
+end
+
+def fun_l22_n9(x)
+ if (x < 1)
+ fun_l23_n106(x)
+ else
+ fun_l23_n125(x)
+ end
+end
+
+def fun_l22_n10(x)
+ if (x < 1)
+ fun_l23_n392(x)
+ else
+ fun_l23_n114(x)
+ end
+end
+
+def fun_l22_n11(x)
+ if (x < 1)
+ fun_l23_n778(x)
+ else
+ fun_l23_n103(x)
+ end
+end
+
+def fun_l22_n12(x)
+ if (x < 1)
+ fun_l23_n145(x)
+ else
+ fun_l23_n449(x)
+ end
+end
+
+def fun_l22_n13(x)
+ if (x < 1)
+ fun_l23_n106(x)
+ else
+ fun_l23_n67(x)
+ end
+end
+
+def fun_l22_n14(x)
+ if (x < 1)
+ fun_l23_n721(x)
+ else
+ fun_l23_n844(x)
+ end
+end
+
+def fun_l22_n15(x)
+ if (x < 1)
+ fun_l23_n411(x)
+ else
+ fun_l23_n479(x)
+ end
+end
+
+def fun_l22_n16(x)
+ if (x < 1)
+ fun_l23_n718(x)
+ else
+ fun_l23_n203(x)
+ end
+end
+
+def fun_l22_n17(x)
+ if (x < 1)
+ fun_l23_n660(x)
+ else
+ fun_l23_n606(x)
+ end
+end
+
+def fun_l22_n18(x)
+ if (x < 1)
+ fun_l23_n225(x)
+ else
+ fun_l23_n310(x)
+ end
+end
+
+def fun_l22_n19(x)
+ if (x < 1)
+ fun_l23_n923(x)
+ else
+ fun_l23_n10(x)
+ end
+end
+
+def fun_l22_n20(x)
+ if (x < 1)
+ fun_l23_n88(x)
+ else
+ fun_l23_n488(x)
+ end
+end
+
+def fun_l22_n21(x)
+ if (x < 1)
+ fun_l23_n986(x)
+ else
+ fun_l23_n123(x)
+ end
+end
+
+def fun_l22_n22(x)
+ if (x < 1)
+ fun_l23_n91(x)
+ else
+ fun_l23_n445(x)
+ end
+end
+
+def fun_l22_n23(x)
+ if (x < 1)
+ fun_l23_n525(x)
+ else
+ fun_l23_n454(x)
+ end
+end
+
+def fun_l22_n24(x)
+ if (x < 1)
+ fun_l23_n55(x)
+ else
+ fun_l23_n540(x)
+ end
+end
+
+def fun_l22_n25(x)
+ if (x < 1)
+ fun_l23_n562(x)
+ else
+ fun_l23_n323(x)
+ end
+end
+
+def fun_l22_n26(x)
+ if (x < 1)
+ fun_l23_n796(x)
+ else
+ fun_l23_n443(x)
+ end
+end
+
+def fun_l22_n27(x)
+ if (x < 1)
+ fun_l23_n421(x)
+ else
+ fun_l23_n654(x)
+ end
+end
+
+def fun_l22_n28(x)
+ if (x < 1)
+ fun_l23_n910(x)
+ else
+ fun_l23_n421(x)
+ end
+end
+
+def fun_l22_n29(x)
+ if (x < 1)
+ fun_l23_n184(x)
+ else
+ fun_l23_n24(x)
+ end
+end
+
+def fun_l22_n30(x)
+ if (x < 1)
+ fun_l23_n803(x)
+ else
+ fun_l23_n375(x)
+ end
+end
+
+def fun_l22_n31(x)
+ if (x < 1)
+ fun_l23_n662(x)
+ else
+ fun_l23_n50(x)
+ end
+end
+
+def fun_l22_n32(x)
+ if (x < 1)
+ fun_l23_n69(x)
+ else
+ fun_l23_n198(x)
+ end
+end
+
+def fun_l22_n33(x)
+ if (x < 1)
+ fun_l23_n465(x)
+ else
+ fun_l23_n979(x)
+ end
+end
+
+def fun_l22_n34(x)
+ if (x < 1)
+ fun_l23_n743(x)
+ else
+ fun_l23_n859(x)
+ end
+end
+
+def fun_l22_n35(x)
+ if (x < 1)
+ fun_l23_n524(x)
+ else
+ fun_l23_n157(x)
+ end
+end
+
+def fun_l22_n36(x)
+ if (x < 1)
+ fun_l23_n530(x)
+ else
+ fun_l23_n938(x)
+ end
+end
+
+def fun_l22_n37(x)
+ if (x < 1)
+ fun_l23_n386(x)
+ else
+ fun_l23_n882(x)
+ end
+end
+
+def fun_l22_n38(x)
+ if (x < 1)
+ fun_l23_n373(x)
+ else
+ fun_l23_n220(x)
+ end
+end
+
+def fun_l22_n39(x)
+ if (x < 1)
+ fun_l23_n783(x)
+ else
+ fun_l23_n731(x)
+ end
+end
+
+def fun_l22_n40(x)
+ if (x < 1)
+ fun_l23_n911(x)
+ else
+ fun_l23_n373(x)
+ end
+end
+
+def fun_l22_n41(x)
+ if (x < 1)
+ fun_l23_n516(x)
+ else
+ fun_l23_n586(x)
+ end
+end
+
+def fun_l22_n42(x)
+ if (x < 1)
+ fun_l23_n40(x)
+ else
+ fun_l23_n350(x)
+ end
+end
+
+def fun_l22_n43(x)
+ if (x < 1)
+ fun_l23_n690(x)
+ else
+ fun_l23_n349(x)
+ end
+end
+
+def fun_l22_n44(x)
+ if (x < 1)
+ fun_l23_n170(x)
+ else
+ fun_l23_n758(x)
+ end
+end
+
+def fun_l22_n45(x)
+ if (x < 1)
+ fun_l23_n317(x)
+ else
+ fun_l23_n856(x)
+ end
+end
+
+def fun_l22_n46(x)
+ if (x < 1)
+ fun_l23_n692(x)
+ else
+ fun_l23_n330(x)
+ end
+end
+
+def fun_l22_n47(x)
+ if (x < 1)
+ fun_l23_n848(x)
+ else
+ fun_l23_n767(x)
+ end
+end
+
+def fun_l22_n48(x)
+ if (x < 1)
+ fun_l23_n683(x)
+ else
+ fun_l23_n225(x)
+ end
+end
+
+def fun_l22_n49(x)
+ if (x < 1)
+ fun_l23_n967(x)
+ else
+ fun_l23_n872(x)
+ end
+end
+
+def fun_l22_n50(x)
+ if (x < 1)
+ fun_l23_n584(x)
+ else
+ fun_l23_n799(x)
+ end
+end
+
+def fun_l22_n51(x)
+ if (x < 1)
+ fun_l23_n156(x)
+ else
+ fun_l23_n710(x)
+ end
+end
+
+def fun_l22_n52(x)
+ if (x < 1)
+ fun_l23_n129(x)
+ else
+ fun_l23_n733(x)
+ end
+end
+
+def fun_l22_n53(x)
+ if (x < 1)
+ fun_l23_n364(x)
+ else
+ fun_l23_n460(x)
+ end
+end
+
+def fun_l22_n54(x)
+ if (x < 1)
+ fun_l23_n284(x)
+ else
+ fun_l23_n13(x)
+ end
+end
+
+def fun_l22_n55(x)
+ if (x < 1)
+ fun_l23_n734(x)
+ else
+ fun_l23_n498(x)
+ end
+end
+
+def fun_l22_n56(x)
+ if (x < 1)
+ fun_l23_n981(x)
+ else
+ fun_l23_n602(x)
+ end
+end
+
+def fun_l22_n57(x)
+ if (x < 1)
+ fun_l23_n632(x)
+ else
+ fun_l23_n123(x)
+ end
+end
+
+def fun_l22_n58(x)
+ if (x < 1)
+ fun_l23_n602(x)
+ else
+ fun_l23_n274(x)
+ end
+end
+
+def fun_l22_n59(x)
+ if (x < 1)
+ fun_l23_n718(x)
+ else
+ fun_l23_n351(x)
+ end
+end
+
+def fun_l22_n60(x)
+ if (x < 1)
+ fun_l23_n618(x)
+ else
+ fun_l23_n583(x)
+ end
+end
+
+def fun_l22_n61(x)
+ if (x < 1)
+ fun_l23_n63(x)
+ else
+ fun_l23_n573(x)
+ end
+end
+
+def fun_l22_n62(x)
+ if (x < 1)
+ fun_l23_n73(x)
+ else
+ fun_l23_n429(x)
+ end
+end
+
+def fun_l22_n63(x)
+ if (x < 1)
+ fun_l23_n969(x)
+ else
+ fun_l23_n518(x)
+ end
+end
+
+def fun_l22_n64(x)
+ if (x < 1)
+ fun_l23_n493(x)
+ else
+ fun_l23_n868(x)
+ end
+end
+
+def fun_l22_n65(x)
+ if (x < 1)
+ fun_l23_n31(x)
+ else
+ fun_l23_n366(x)
+ end
+end
+
+def fun_l22_n66(x)
+ if (x < 1)
+ fun_l23_n442(x)
+ else
+ fun_l23_n362(x)
+ end
+end
+
+def fun_l22_n67(x)
+ if (x < 1)
+ fun_l23_n804(x)
+ else
+ fun_l23_n513(x)
+ end
+end
+
+def fun_l22_n68(x)
+ if (x < 1)
+ fun_l23_n973(x)
+ else
+ fun_l23_n723(x)
+ end
+end
+
+def fun_l22_n69(x)
+ if (x < 1)
+ fun_l23_n424(x)
+ else
+ fun_l23_n247(x)
+ end
+end
+
+def fun_l22_n70(x)
+ if (x < 1)
+ fun_l23_n992(x)
+ else
+ fun_l23_n944(x)
+ end
+end
+
+def fun_l22_n71(x)
+ if (x < 1)
+ fun_l23_n209(x)
+ else
+ fun_l23_n645(x)
+ end
+end
+
+def fun_l22_n72(x)
+ if (x < 1)
+ fun_l23_n373(x)
+ else
+ fun_l23_n540(x)
+ end
+end
+
+def fun_l22_n73(x)
+ if (x < 1)
+ fun_l23_n785(x)
+ else
+ fun_l23_n840(x)
+ end
+end
+
+def fun_l22_n74(x)
+ if (x < 1)
+ fun_l23_n607(x)
+ else
+ fun_l23_n584(x)
+ end
+end
+
+def fun_l22_n75(x)
+ if (x < 1)
+ fun_l23_n331(x)
+ else
+ fun_l23_n196(x)
+ end
+end
+
+def fun_l22_n76(x)
+ if (x < 1)
+ fun_l23_n453(x)
+ else
+ fun_l23_n991(x)
+ end
+end
+
+def fun_l22_n77(x)
+ if (x < 1)
+ fun_l23_n689(x)
+ else
+ fun_l23_n222(x)
+ end
+end
+
+def fun_l22_n78(x)
+ if (x < 1)
+ fun_l23_n446(x)
+ else
+ fun_l23_n767(x)
+ end
+end
+
+def fun_l22_n79(x)
+ if (x < 1)
+ fun_l23_n648(x)
+ else
+ fun_l23_n811(x)
+ end
+end
+
+def fun_l22_n80(x)
+ if (x < 1)
+ fun_l23_n210(x)
+ else
+ fun_l23_n52(x)
+ end
+end
+
+def fun_l22_n81(x)
+ if (x < 1)
+ fun_l23_n786(x)
+ else
+ fun_l23_n984(x)
+ end
+end
+
+def fun_l22_n82(x)
+ if (x < 1)
+ fun_l23_n693(x)
+ else
+ fun_l23_n103(x)
+ end
+end
+
+def fun_l22_n83(x)
+ if (x < 1)
+ fun_l23_n768(x)
+ else
+ fun_l23_n794(x)
+ end
+end
+
+def fun_l22_n84(x)
+ if (x < 1)
+ fun_l23_n820(x)
+ else
+ fun_l23_n774(x)
+ end
+end
+
+def fun_l22_n85(x)
+ if (x < 1)
+ fun_l23_n972(x)
+ else
+ fun_l23_n254(x)
+ end
+end
+
+def fun_l22_n86(x)
+ if (x < 1)
+ fun_l23_n609(x)
+ else
+ fun_l23_n524(x)
+ end
+end
+
+def fun_l22_n87(x)
+ if (x < 1)
+ fun_l23_n486(x)
+ else
+ fun_l23_n173(x)
+ end
+end
+
+def fun_l22_n88(x)
+ if (x < 1)
+ fun_l23_n236(x)
+ else
+ fun_l23_n359(x)
+ end
+end
+
+def fun_l22_n89(x)
+ if (x < 1)
+ fun_l23_n292(x)
+ else
+ fun_l23_n232(x)
+ end
+end
+
+def fun_l22_n90(x)
+ if (x < 1)
+ fun_l23_n104(x)
+ else
+ fun_l23_n799(x)
+ end
+end
+
+def fun_l22_n91(x)
+ if (x < 1)
+ fun_l23_n957(x)
+ else
+ fun_l23_n836(x)
+ end
+end
+
+def fun_l22_n92(x)
+ if (x < 1)
+ fun_l23_n179(x)
+ else
+ fun_l23_n416(x)
+ end
+end
+
+def fun_l22_n93(x)
+ if (x < 1)
+ fun_l23_n281(x)
+ else
+ fun_l23_n530(x)
+ end
+end
+
+def fun_l22_n94(x)
+ if (x < 1)
+ fun_l23_n627(x)
+ else
+ fun_l23_n577(x)
+ end
+end
+
+def fun_l22_n95(x)
+ if (x < 1)
+ fun_l23_n594(x)
+ else
+ fun_l23_n949(x)
+ end
+end
+
+def fun_l22_n96(x)
+ if (x < 1)
+ fun_l23_n408(x)
+ else
+ fun_l23_n547(x)
+ end
+end
+
+def fun_l22_n97(x)
+ if (x < 1)
+ fun_l23_n276(x)
+ else
+ fun_l23_n105(x)
+ end
+end
+
+def fun_l22_n98(x)
+ if (x < 1)
+ fun_l23_n181(x)
+ else
+ fun_l23_n659(x)
+ end
+end
+
+def fun_l22_n99(x)
+ if (x < 1)
+ fun_l23_n7(x)
+ else
+ fun_l23_n423(x)
+ end
+end
+
+def fun_l22_n100(x)
+ if (x < 1)
+ fun_l23_n123(x)
+ else
+ fun_l23_n244(x)
+ end
+end
+
+def fun_l22_n101(x)
+ if (x < 1)
+ fun_l23_n476(x)
+ else
+ fun_l23_n319(x)
+ end
+end
+
+def fun_l22_n102(x)
+ if (x < 1)
+ fun_l23_n443(x)
+ else
+ fun_l23_n959(x)
+ end
+end
+
+def fun_l22_n103(x)
+ if (x < 1)
+ fun_l23_n78(x)
+ else
+ fun_l23_n490(x)
+ end
+end
+
+def fun_l22_n104(x)
+ if (x < 1)
+ fun_l23_n761(x)
+ else
+ fun_l23_n23(x)
+ end
+end
+
+def fun_l22_n105(x)
+ if (x < 1)
+ fun_l23_n126(x)
+ else
+ fun_l23_n426(x)
+ end
+end
+
+def fun_l22_n106(x)
+ if (x < 1)
+ fun_l23_n740(x)
+ else
+ fun_l23_n328(x)
+ end
+end
+
+def fun_l22_n107(x)
+ if (x < 1)
+ fun_l23_n249(x)
+ else
+ fun_l23_n890(x)
+ end
+end
+
+def fun_l22_n108(x)
+ if (x < 1)
+ fun_l23_n665(x)
+ else
+ fun_l23_n60(x)
+ end
+end
+
+def fun_l22_n109(x)
+ if (x < 1)
+ fun_l23_n617(x)
+ else
+ fun_l23_n42(x)
+ end
+end
+
+def fun_l22_n110(x)
+ if (x < 1)
+ fun_l23_n484(x)
+ else
+ fun_l23_n480(x)
+ end
+end
+
+def fun_l22_n111(x)
+ if (x < 1)
+ fun_l23_n135(x)
+ else
+ fun_l23_n447(x)
+ end
+end
+
+def fun_l22_n112(x)
+ if (x < 1)
+ fun_l23_n881(x)
+ else
+ fun_l23_n410(x)
+ end
+end
+
+def fun_l22_n113(x)
+ if (x < 1)
+ fun_l23_n989(x)
+ else
+ fun_l23_n849(x)
+ end
+end
+
+def fun_l22_n114(x)
+ if (x < 1)
+ fun_l23_n660(x)
+ else
+ fun_l23_n307(x)
+ end
+end
+
+def fun_l22_n115(x)
+ if (x < 1)
+ fun_l23_n372(x)
+ else
+ fun_l23_n150(x)
+ end
+end
+
+def fun_l22_n116(x)
+ if (x < 1)
+ fun_l23_n770(x)
+ else
+ fun_l23_n109(x)
+ end
+end
+
+def fun_l22_n117(x)
+ if (x < 1)
+ fun_l23_n364(x)
+ else
+ fun_l23_n321(x)
+ end
+end
+
+def fun_l22_n118(x)
+ if (x < 1)
+ fun_l23_n363(x)
+ else
+ fun_l23_n876(x)
+ end
+end
+
+def fun_l22_n119(x)
+ if (x < 1)
+ fun_l23_n114(x)
+ else
+ fun_l23_n25(x)
+ end
+end
+
+def fun_l22_n120(x)
+ if (x < 1)
+ fun_l23_n160(x)
+ else
+ fun_l23_n744(x)
+ end
+end
+
+def fun_l22_n121(x)
+ if (x < 1)
+ fun_l23_n265(x)
+ else
+ fun_l23_n972(x)
+ end
+end
+
+def fun_l22_n122(x)
+ if (x < 1)
+ fun_l23_n259(x)
+ else
+ fun_l23_n203(x)
+ end
+end
+
+def fun_l22_n123(x)
+ if (x < 1)
+ fun_l23_n865(x)
+ else
+ fun_l23_n137(x)
+ end
+end
+
+def fun_l22_n124(x)
+ if (x < 1)
+ fun_l23_n427(x)
+ else
+ fun_l23_n437(x)
+ end
+end
+
+def fun_l22_n125(x)
+ if (x < 1)
+ fun_l23_n405(x)
+ else
+ fun_l23_n603(x)
+ end
+end
+
+def fun_l22_n126(x)
+ if (x < 1)
+ fun_l23_n938(x)
+ else
+ fun_l23_n505(x)
+ end
+end
+
+def fun_l22_n127(x)
+ if (x < 1)
+ fun_l23_n307(x)
+ else
+ fun_l23_n26(x)
+ end
+end
+
+def fun_l22_n128(x)
+ if (x < 1)
+ fun_l23_n15(x)
+ else
+ fun_l23_n406(x)
+ end
+end
+
+def fun_l22_n129(x)
+ if (x < 1)
+ fun_l23_n633(x)
+ else
+ fun_l23_n831(x)
+ end
+end
+
+def fun_l22_n130(x)
+ if (x < 1)
+ fun_l23_n805(x)
+ else
+ fun_l23_n216(x)
+ end
+end
+
+def fun_l22_n131(x)
+ if (x < 1)
+ fun_l23_n552(x)
+ else
+ fun_l23_n864(x)
+ end
+end
+
+def fun_l22_n132(x)
+ if (x < 1)
+ fun_l23_n50(x)
+ else
+ fun_l23_n805(x)
+ end
+end
+
+def fun_l22_n133(x)
+ if (x < 1)
+ fun_l23_n823(x)
+ else
+ fun_l23_n427(x)
+ end
+end
+
+def fun_l22_n134(x)
+ if (x < 1)
+ fun_l23_n964(x)
+ else
+ fun_l23_n214(x)
+ end
+end
+
+def fun_l22_n135(x)
+ if (x < 1)
+ fun_l23_n267(x)
+ else
+ fun_l23_n351(x)
+ end
+end
+
+def fun_l22_n136(x)
+ if (x < 1)
+ fun_l23_n557(x)
+ else
+ fun_l23_n257(x)
+ end
+end
+
+def fun_l22_n137(x)
+ if (x < 1)
+ fun_l23_n966(x)
+ else
+ fun_l23_n248(x)
+ end
+end
+
+def fun_l22_n138(x)
+ if (x < 1)
+ fun_l23_n569(x)
+ else
+ fun_l23_n376(x)
+ end
+end
+
+def fun_l22_n139(x)
+ if (x < 1)
+ fun_l23_n198(x)
+ else
+ fun_l23_n595(x)
+ end
+end
+
+def fun_l22_n140(x)
+ if (x < 1)
+ fun_l23_n107(x)
+ else
+ fun_l23_n134(x)
+ end
+end
+
+def fun_l22_n141(x)
+ if (x < 1)
+ fun_l23_n113(x)
+ else
+ fun_l23_n290(x)
+ end
+end
+
+def fun_l22_n142(x)
+ if (x < 1)
+ fun_l23_n721(x)
+ else
+ fun_l23_n641(x)
+ end
+end
+
+def fun_l22_n143(x)
+ if (x < 1)
+ fun_l23_n535(x)
+ else
+ fun_l23_n103(x)
+ end
+end
+
+def fun_l22_n144(x)
+ if (x < 1)
+ fun_l23_n690(x)
+ else
+ fun_l23_n125(x)
+ end
+end
+
+def fun_l22_n145(x)
+ if (x < 1)
+ fun_l23_n514(x)
+ else
+ fun_l23_n999(x)
+ end
+end
+
+def fun_l22_n146(x)
+ if (x < 1)
+ fun_l23_n503(x)
+ else
+ fun_l23_n951(x)
+ end
+end
+
+def fun_l22_n147(x)
+ if (x < 1)
+ fun_l23_n413(x)
+ else
+ fun_l23_n634(x)
+ end
+end
+
+def fun_l22_n148(x)
+ if (x < 1)
+ fun_l23_n818(x)
+ else
+ fun_l23_n286(x)
+ end
+end
+
+def fun_l22_n149(x)
+ if (x < 1)
+ fun_l23_n768(x)
+ else
+ fun_l23_n832(x)
+ end
+end
+
+def fun_l22_n150(x)
+ if (x < 1)
+ fun_l23_n128(x)
+ else
+ fun_l23_n588(x)
+ end
+end
+
+def fun_l22_n151(x)
+ if (x < 1)
+ fun_l23_n787(x)
+ else
+ fun_l23_n742(x)
+ end
+end
+
+def fun_l22_n152(x)
+ if (x < 1)
+ fun_l23_n166(x)
+ else
+ fun_l23_n856(x)
+ end
+end
+
+def fun_l22_n153(x)
+ if (x < 1)
+ fun_l23_n377(x)
+ else
+ fun_l23_n90(x)
+ end
+end
+
+def fun_l22_n154(x)
+ if (x < 1)
+ fun_l23_n851(x)
+ else
+ fun_l23_n591(x)
+ end
+end
+
+def fun_l22_n155(x)
+ if (x < 1)
+ fun_l23_n896(x)
+ else
+ fun_l23_n372(x)
+ end
+end
+
+def fun_l22_n156(x)
+ if (x < 1)
+ fun_l23_n132(x)
+ else
+ fun_l23_n144(x)
+ end
+end
+
+def fun_l22_n157(x)
+ if (x < 1)
+ fun_l23_n251(x)
+ else
+ fun_l23_n620(x)
+ end
+end
+
+def fun_l22_n158(x)
+ if (x < 1)
+ fun_l23_n612(x)
+ else
+ fun_l23_n246(x)
+ end
+end
+
+def fun_l22_n159(x)
+ if (x < 1)
+ fun_l23_n530(x)
+ else
+ fun_l23_n94(x)
+ end
+end
+
+def fun_l22_n160(x)
+ if (x < 1)
+ fun_l23_n310(x)
+ else
+ fun_l23_n706(x)
+ end
+end
+
+def fun_l22_n161(x)
+ if (x < 1)
+ fun_l23_n420(x)
+ else
+ fun_l23_n576(x)
+ end
+end
+
+def fun_l22_n162(x)
+ if (x < 1)
+ fun_l23_n544(x)
+ else
+ fun_l23_n277(x)
+ end
+end
+
+def fun_l22_n163(x)
+ if (x < 1)
+ fun_l23_n770(x)
+ else
+ fun_l23_n94(x)
+ end
+end
+
+def fun_l22_n164(x)
+ if (x < 1)
+ fun_l23_n49(x)
+ else
+ fun_l23_n576(x)
+ end
+end
+
+def fun_l22_n165(x)
+ if (x < 1)
+ fun_l23_n610(x)
+ else
+ fun_l23_n184(x)
+ end
+end
+
+def fun_l22_n166(x)
+ if (x < 1)
+ fun_l23_n974(x)
+ else
+ fun_l23_n54(x)
+ end
+end
+
+def fun_l22_n167(x)
+ if (x < 1)
+ fun_l23_n179(x)
+ else
+ fun_l23_n485(x)
+ end
+end
+
+def fun_l22_n168(x)
+ if (x < 1)
+ fun_l23_n114(x)
+ else
+ fun_l23_n766(x)
+ end
+end
+
+def fun_l22_n169(x)
+ if (x < 1)
+ fun_l23_n399(x)
+ else
+ fun_l23_n830(x)
+ end
+end
+
+def fun_l22_n170(x)
+ if (x < 1)
+ fun_l23_n332(x)
+ else
+ fun_l23_n536(x)
+ end
+end
+
+def fun_l22_n171(x)
+ if (x < 1)
+ fun_l23_n384(x)
+ else
+ fun_l23_n773(x)
+ end
+end
+
+def fun_l22_n172(x)
+ if (x < 1)
+ fun_l23_n52(x)
+ else
+ fun_l23_n7(x)
+ end
+end
+
+def fun_l22_n173(x)
+ if (x < 1)
+ fun_l23_n85(x)
+ else
+ fun_l23_n803(x)
+ end
+end
+
+def fun_l22_n174(x)
+ if (x < 1)
+ fun_l23_n853(x)
+ else
+ fun_l23_n682(x)
+ end
+end
+
+def fun_l22_n175(x)
+ if (x < 1)
+ fun_l23_n112(x)
+ else
+ fun_l23_n295(x)
+ end
+end
+
+def fun_l22_n176(x)
+ if (x < 1)
+ fun_l23_n347(x)
+ else
+ fun_l23_n908(x)
+ end
+end
+
+def fun_l22_n177(x)
+ if (x < 1)
+ fun_l23_n267(x)
+ else
+ fun_l23_n19(x)
+ end
+end
+
+def fun_l22_n178(x)
+ if (x < 1)
+ fun_l23_n8(x)
+ else
+ fun_l23_n739(x)
+ end
+end
+
+def fun_l22_n179(x)
+ if (x < 1)
+ fun_l23_n201(x)
+ else
+ fun_l23_n321(x)
+ end
+end
+
+def fun_l22_n180(x)
+ if (x < 1)
+ fun_l23_n773(x)
+ else
+ fun_l23_n224(x)
+ end
+end
+
+def fun_l22_n181(x)
+ if (x < 1)
+ fun_l23_n966(x)
+ else
+ fun_l23_n324(x)
+ end
+end
+
+def fun_l22_n182(x)
+ if (x < 1)
+ fun_l23_n389(x)
+ else
+ fun_l23_n190(x)
+ end
+end
+
+def fun_l22_n183(x)
+ if (x < 1)
+ fun_l23_n918(x)
+ else
+ fun_l23_n512(x)
+ end
+end
+
+def fun_l22_n184(x)
+ if (x < 1)
+ fun_l23_n360(x)
+ else
+ fun_l23_n702(x)
+ end
+end
+
+def fun_l22_n185(x)
+ if (x < 1)
+ fun_l23_n794(x)
+ else
+ fun_l23_n51(x)
+ end
+end
+
+def fun_l22_n186(x)
+ if (x < 1)
+ fun_l23_n982(x)
+ else
+ fun_l23_n779(x)
+ end
+end
+
+def fun_l22_n187(x)
+ if (x < 1)
+ fun_l23_n263(x)
+ else
+ fun_l23_n659(x)
+ end
+end
+
+def fun_l22_n188(x)
+ if (x < 1)
+ fun_l23_n203(x)
+ else
+ fun_l23_n705(x)
+ end
+end
+
+def fun_l22_n189(x)
+ if (x < 1)
+ fun_l23_n976(x)
+ else
+ fun_l23_n307(x)
+ end
+end
+
+def fun_l22_n190(x)
+ if (x < 1)
+ fun_l23_n281(x)
+ else
+ fun_l23_n880(x)
+ end
+end
+
+def fun_l22_n191(x)
+ if (x < 1)
+ fun_l23_n238(x)
+ else
+ fun_l23_n752(x)
+ end
+end
+
+def fun_l22_n192(x)
+ if (x < 1)
+ fun_l23_n679(x)
+ else
+ fun_l23_n935(x)
+ end
+end
+
+def fun_l22_n193(x)
+ if (x < 1)
+ fun_l23_n823(x)
+ else
+ fun_l23_n340(x)
+ end
+end
+
+def fun_l22_n194(x)
+ if (x < 1)
+ fun_l23_n687(x)
+ else
+ fun_l23_n71(x)
+ end
+end
+
+def fun_l22_n195(x)
+ if (x < 1)
+ fun_l23_n47(x)
+ else
+ fun_l23_n119(x)
+ end
+end
+
+def fun_l22_n196(x)
+ if (x < 1)
+ fun_l23_n702(x)
+ else
+ fun_l23_n213(x)
+ end
+end
+
+def fun_l22_n197(x)
+ if (x < 1)
+ fun_l23_n300(x)
+ else
+ fun_l23_n52(x)
+ end
+end
+
+def fun_l22_n198(x)
+ if (x < 1)
+ fun_l23_n85(x)
+ else
+ fun_l23_n845(x)
+ end
+end
+
+def fun_l22_n199(x)
+ if (x < 1)
+ fun_l23_n503(x)
+ else
+ fun_l23_n322(x)
+ end
+end
+
+def fun_l22_n200(x)
+ if (x < 1)
+ fun_l23_n151(x)
+ else
+ fun_l23_n743(x)
+ end
+end
+
+def fun_l22_n201(x)
+ if (x < 1)
+ fun_l23_n531(x)
+ else
+ fun_l23_n597(x)
+ end
+end
+
+def fun_l22_n202(x)
+ if (x < 1)
+ fun_l23_n120(x)
+ else
+ fun_l23_n300(x)
+ end
+end
+
+def fun_l22_n203(x)
+ if (x < 1)
+ fun_l23_n124(x)
+ else
+ fun_l23_n609(x)
+ end
+end
+
+def fun_l22_n204(x)
+ if (x < 1)
+ fun_l23_n945(x)
+ else
+ fun_l23_n498(x)
+ end
+end
+
+def fun_l22_n205(x)
+ if (x < 1)
+ fun_l23_n983(x)
+ else
+ fun_l23_n16(x)
+ end
+end
+
+def fun_l22_n206(x)
+ if (x < 1)
+ fun_l23_n271(x)
+ else
+ fun_l23_n612(x)
+ end
+end
+
+def fun_l22_n207(x)
+ if (x < 1)
+ fun_l23_n762(x)
+ else
+ fun_l23_n596(x)
+ end
+end
+
+def fun_l22_n208(x)
+ if (x < 1)
+ fun_l23_n992(x)
+ else
+ fun_l23_n90(x)
+ end
+end
+
+def fun_l22_n209(x)
+ if (x < 1)
+ fun_l23_n994(x)
+ else
+ fun_l23_n265(x)
+ end
+end
+
+def fun_l22_n210(x)
+ if (x < 1)
+ fun_l23_n449(x)
+ else
+ fun_l23_n609(x)
+ end
+end
+
+def fun_l22_n211(x)
+ if (x < 1)
+ fun_l23_n816(x)
+ else
+ fun_l23_n8(x)
+ end
+end
+
+def fun_l22_n212(x)
+ if (x < 1)
+ fun_l23_n526(x)
+ else
+ fun_l23_n982(x)
+ end
+end
+
+def fun_l22_n213(x)
+ if (x < 1)
+ fun_l23_n25(x)
+ else
+ fun_l23_n302(x)
+ end
+end
+
+def fun_l22_n214(x)
+ if (x < 1)
+ fun_l23_n868(x)
+ else
+ fun_l23_n895(x)
+ end
+end
+
+def fun_l22_n215(x)
+ if (x < 1)
+ fun_l23_n3(x)
+ else
+ fun_l23_n914(x)
+ end
+end
+
+def fun_l22_n216(x)
+ if (x < 1)
+ fun_l23_n106(x)
+ else
+ fun_l23_n271(x)
+ end
+end
+
+def fun_l22_n217(x)
+ if (x < 1)
+ fun_l23_n567(x)
+ else
+ fun_l23_n931(x)
+ end
+end
+
+def fun_l22_n218(x)
+ if (x < 1)
+ fun_l23_n7(x)
+ else
+ fun_l23_n319(x)
+ end
+end
+
+def fun_l22_n219(x)
+ if (x < 1)
+ fun_l23_n510(x)
+ else
+ fun_l23_n753(x)
+ end
+end
+
+def fun_l22_n220(x)
+ if (x < 1)
+ fun_l23_n529(x)
+ else
+ fun_l23_n514(x)
+ end
+end
+
+def fun_l22_n221(x)
+ if (x < 1)
+ fun_l23_n871(x)
+ else
+ fun_l23_n571(x)
+ end
+end
+
+def fun_l22_n222(x)
+ if (x < 1)
+ fun_l23_n739(x)
+ else
+ fun_l23_n716(x)
+ end
+end
+
+def fun_l22_n223(x)
+ if (x < 1)
+ fun_l23_n781(x)
+ else
+ fun_l23_n730(x)
+ end
+end
+
+def fun_l22_n224(x)
+ if (x < 1)
+ fun_l23_n647(x)
+ else
+ fun_l23_n647(x)
+ end
+end
+
+def fun_l22_n225(x)
+ if (x < 1)
+ fun_l23_n968(x)
+ else
+ fun_l23_n680(x)
+ end
+end
+
+def fun_l22_n226(x)
+ if (x < 1)
+ fun_l23_n400(x)
+ else
+ fun_l23_n725(x)
+ end
+end
+
+def fun_l22_n227(x)
+ if (x < 1)
+ fun_l23_n386(x)
+ else
+ fun_l23_n859(x)
+ end
+end
+
+def fun_l22_n228(x)
+ if (x < 1)
+ fun_l23_n751(x)
+ else
+ fun_l23_n640(x)
+ end
+end
+
+def fun_l22_n229(x)
+ if (x < 1)
+ fun_l23_n273(x)
+ else
+ fun_l23_n754(x)
+ end
+end
+
+def fun_l22_n230(x)
+ if (x < 1)
+ fun_l23_n861(x)
+ else
+ fun_l23_n783(x)
+ end
+end
+
+def fun_l22_n231(x)
+ if (x < 1)
+ fun_l23_n665(x)
+ else
+ fun_l23_n18(x)
+ end
+end
+
+def fun_l22_n232(x)
+ if (x < 1)
+ fun_l23_n680(x)
+ else
+ fun_l23_n471(x)
+ end
+end
+
+def fun_l22_n233(x)
+ if (x < 1)
+ fun_l23_n400(x)
+ else
+ fun_l23_n935(x)
+ end
+end
+
+def fun_l22_n234(x)
+ if (x < 1)
+ fun_l23_n563(x)
+ else
+ fun_l23_n799(x)
+ end
+end
+
+def fun_l22_n235(x)
+ if (x < 1)
+ fun_l23_n712(x)
+ else
+ fun_l23_n20(x)
+ end
+end
+
+def fun_l22_n236(x)
+ if (x < 1)
+ fun_l23_n579(x)
+ else
+ fun_l23_n152(x)
+ end
+end
+
+def fun_l22_n237(x)
+ if (x < 1)
+ fun_l23_n752(x)
+ else
+ fun_l23_n282(x)
+ end
+end
+
+def fun_l22_n238(x)
+ if (x < 1)
+ fun_l23_n609(x)
+ else
+ fun_l23_n980(x)
+ end
+end
+
+def fun_l22_n239(x)
+ if (x < 1)
+ fun_l23_n916(x)
+ else
+ fun_l23_n52(x)
+ end
+end
+
+def fun_l22_n240(x)
+ if (x < 1)
+ fun_l23_n468(x)
+ else
+ fun_l23_n735(x)
+ end
+end
+
+def fun_l22_n241(x)
+ if (x < 1)
+ fun_l23_n894(x)
+ else
+ fun_l23_n776(x)
+ end
+end
+
+def fun_l22_n242(x)
+ if (x < 1)
+ fun_l23_n782(x)
+ else
+ fun_l23_n406(x)
+ end
+end
+
+def fun_l22_n243(x)
+ if (x < 1)
+ fun_l23_n90(x)
+ else
+ fun_l23_n226(x)
+ end
+end
+
+def fun_l22_n244(x)
+ if (x < 1)
+ fun_l23_n967(x)
+ else
+ fun_l23_n252(x)
+ end
+end
+
+def fun_l22_n245(x)
+ if (x < 1)
+ fun_l23_n189(x)
+ else
+ fun_l23_n252(x)
+ end
+end
+
+def fun_l22_n246(x)
+ if (x < 1)
+ fun_l23_n919(x)
+ else
+ fun_l23_n581(x)
+ end
+end
+
+def fun_l22_n247(x)
+ if (x < 1)
+ fun_l23_n212(x)
+ else
+ fun_l23_n465(x)
+ end
+end
+
+def fun_l22_n248(x)
+ if (x < 1)
+ fun_l23_n880(x)
+ else
+ fun_l23_n823(x)
+ end
+end
+
+def fun_l22_n249(x)
+ if (x < 1)
+ fun_l23_n227(x)
+ else
+ fun_l23_n620(x)
+ end
+end
+
+def fun_l22_n250(x)
+ if (x < 1)
+ fun_l23_n875(x)
+ else
+ fun_l23_n707(x)
+ end
+end
+
+def fun_l22_n251(x)
+ if (x < 1)
+ fun_l23_n623(x)
+ else
+ fun_l23_n132(x)
+ end
+end
+
+def fun_l22_n252(x)
+ if (x < 1)
+ fun_l23_n739(x)
+ else
+ fun_l23_n417(x)
+ end
+end
+
+def fun_l22_n253(x)
+ if (x < 1)
+ fun_l23_n977(x)
+ else
+ fun_l23_n216(x)
+ end
+end
+
+def fun_l22_n254(x)
+ if (x < 1)
+ fun_l23_n725(x)
+ else
+ fun_l23_n168(x)
+ end
+end
+
+def fun_l22_n255(x)
+ if (x < 1)
+ fun_l23_n878(x)
+ else
+ fun_l23_n699(x)
+ end
+end
+
+def fun_l22_n256(x)
+ if (x < 1)
+ fun_l23_n423(x)
+ else
+ fun_l23_n626(x)
+ end
+end
+
+def fun_l22_n257(x)
+ if (x < 1)
+ fun_l23_n29(x)
+ else
+ fun_l23_n248(x)
+ end
+end
+
+def fun_l22_n258(x)
+ if (x < 1)
+ fun_l23_n78(x)
+ else
+ fun_l23_n925(x)
+ end
+end
+
+def fun_l22_n259(x)
+ if (x < 1)
+ fun_l23_n798(x)
+ else
+ fun_l23_n220(x)
+ end
+end
+
+def fun_l22_n260(x)
+ if (x < 1)
+ fun_l23_n621(x)
+ else
+ fun_l23_n936(x)
+ end
+end
+
+def fun_l22_n261(x)
+ if (x < 1)
+ fun_l23_n894(x)
+ else
+ fun_l23_n463(x)
+ end
+end
+
+def fun_l22_n262(x)
+ if (x < 1)
+ fun_l23_n336(x)
+ else
+ fun_l23_n535(x)
+ end
+end
+
+def fun_l22_n263(x)
+ if (x < 1)
+ fun_l23_n246(x)
+ else
+ fun_l23_n676(x)
+ end
+end
+
+def fun_l22_n264(x)
+ if (x < 1)
+ fun_l23_n986(x)
+ else
+ fun_l23_n675(x)
+ end
+end
+
+def fun_l22_n265(x)
+ if (x < 1)
+ fun_l23_n92(x)
+ else
+ fun_l23_n380(x)
+ end
+end
+
+def fun_l22_n266(x)
+ if (x < 1)
+ fun_l23_n945(x)
+ else
+ fun_l23_n842(x)
+ end
+end
+
+def fun_l22_n267(x)
+ if (x < 1)
+ fun_l23_n351(x)
+ else
+ fun_l23_n261(x)
+ end
+end
+
+def fun_l22_n268(x)
+ if (x < 1)
+ fun_l23_n784(x)
+ else
+ fun_l23_n306(x)
+ end
+end
+
+def fun_l22_n269(x)
+ if (x < 1)
+ fun_l23_n940(x)
+ else
+ fun_l23_n129(x)
+ end
+end
+
+def fun_l22_n270(x)
+ if (x < 1)
+ fun_l23_n491(x)
+ else
+ fun_l23_n806(x)
+ end
+end
+
+def fun_l22_n271(x)
+ if (x < 1)
+ fun_l23_n68(x)
+ else
+ fun_l23_n91(x)
+ end
+end
+
+def fun_l22_n272(x)
+ if (x < 1)
+ fun_l23_n965(x)
+ else
+ fun_l23_n665(x)
+ end
+end
+
+def fun_l22_n273(x)
+ if (x < 1)
+ fun_l23_n461(x)
+ else
+ fun_l23_n619(x)
+ end
+end
+
+def fun_l22_n274(x)
+ if (x < 1)
+ fun_l23_n635(x)
+ else
+ fun_l23_n755(x)
+ end
+end
+
+def fun_l22_n275(x)
+ if (x < 1)
+ fun_l23_n192(x)
+ else
+ fun_l23_n729(x)
+ end
+end
+
+def fun_l22_n276(x)
+ if (x < 1)
+ fun_l23_n94(x)
+ else
+ fun_l23_n832(x)
+ end
+end
+
+def fun_l22_n277(x)
+ if (x < 1)
+ fun_l23_n619(x)
+ else
+ fun_l23_n444(x)
+ end
+end
+
+def fun_l22_n278(x)
+ if (x < 1)
+ fun_l23_n682(x)
+ else
+ fun_l23_n579(x)
+ end
+end
+
+def fun_l22_n279(x)
+ if (x < 1)
+ fun_l23_n889(x)
+ else
+ fun_l23_n425(x)
+ end
+end
+
+def fun_l22_n280(x)
+ if (x < 1)
+ fun_l23_n101(x)
+ else
+ fun_l23_n215(x)
+ end
+end
+
+def fun_l22_n281(x)
+ if (x < 1)
+ fun_l23_n747(x)
+ else
+ fun_l23_n436(x)
+ end
+end
+
+def fun_l22_n282(x)
+ if (x < 1)
+ fun_l23_n519(x)
+ else
+ fun_l23_n438(x)
+ end
+end
+
+def fun_l22_n283(x)
+ if (x < 1)
+ fun_l23_n312(x)
+ else
+ fun_l23_n804(x)
+ end
+end
+
+def fun_l22_n284(x)
+ if (x < 1)
+ fun_l23_n150(x)
+ else
+ fun_l23_n71(x)
+ end
+end
+
+def fun_l22_n285(x)
+ if (x < 1)
+ fun_l23_n698(x)
+ else
+ fun_l23_n254(x)
+ end
+end
+
+def fun_l22_n286(x)
+ if (x < 1)
+ fun_l23_n97(x)
+ else
+ fun_l23_n782(x)
+ end
+end
+
+def fun_l22_n287(x)
+ if (x < 1)
+ fun_l23_n315(x)
+ else
+ fun_l23_n164(x)
+ end
+end
+
+def fun_l22_n288(x)
+ if (x < 1)
+ fun_l23_n704(x)
+ else
+ fun_l23_n927(x)
+ end
+end
+
+def fun_l22_n289(x)
+ if (x < 1)
+ fun_l23_n447(x)
+ else
+ fun_l23_n104(x)
+ end
+end
+
+def fun_l22_n290(x)
+ if (x < 1)
+ fun_l23_n533(x)
+ else
+ fun_l23_n687(x)
+ end
+end
+
+def fun_l22_n291(x)
+ if (x < 1)
+ fun_l23_n897(x)
+ else
+ fun_l23_n692(x)
+ end
+end
+
+def fun_l22_n292(x)
+ if (x < 1)
+ fun_l23_n515(x)
+ else
+ fun_l23_n258(x)
+ end
+end
+
+def fun_l22_n293(x)
+ if (x < 1)
+ fun_l23_n25(x)
+ else
+ fun_l23_n608(x)
+ end
+end
+
+def fun_l22_n294(x)
+ if (x < 1)
+ fun_l23_n313(x)
+ else
+ fun_l23_n675(x)
+ end
+end
+
+def fun_l22_n295(x)
+ if (x < 1)
+ fun_l23_n154(x)
+ else
+ fun_l23_n779(x)
+ end
+end
+
+def fun_l22_n296(x)
+ if (x < 1)
+ fun_l23_n731(x)
+ else
+ fun_l23_n310(x)
+ end
+end
+
+def fun_l22_n297(x)
+ if (x < 1)
+ fun_l23_n443(x)
+ else
+ fun_l23_n709(x)
+ end
+end
+
+def fun_l22_n298(x)
+ if (x < 1)
+ fun_l23_n100(x)
+ else
+ fun_l23_n900(x)
+ end
+end
+
+def fun_l22_n299(x)
+ if (x < 1)
+ fun_l23_n64(x)
+ else
+ fun_l23_n80(x)
+ end
+end
+
+def fun_l22_n300(x)
+ if (x < 1)
+ fun_l23_n361(x)
+ else
+ fun_l23_n535(x)
+ end
+end
+
+def fun_l22_n301(x)
+ if (x < 1)
+ fun_l23_n628(x)
+ else
+ fun_l23_n272(x)
+ end
+end
+
+def fun_l22_n302(x)
+ if (x < 1)
+ fun_l23_n930(x)
+ else
+ fun_l23_n795(x)
+ end
+end
+
+def fun_l22_n303(x)
+ if (x < 1)
+ fun_l23_n642(x)
+ else
+ fun_l23_n766(x)
+ end
+end
+
+def fun_l22_n304(x)
+ if (x < 1)
+ fun_l23_n191(x)
+ else
+ fun_l23_n439(x)
+ end
+end
+
+def fun_l22_n305(x)
+ if (x < 1)
+ fun_l23_n387(x)
+ else
+ fun_l23_n999(x)
+ end
+end
+
+def fun_l22_n306(x)
+ if (x < 1)
+ fun_l23_n470(x)
+ else
+ fun_l23_n572(x)
+ end
+end
+
+def fun_l22_n307(x)
+ if (x < 1)
+ fun_l23_n942(x)
+ else
+ fun_l23_n254(x)
+ end
+end
+
+def fun_l22_n308(x)
+ if (x < 1)
+ fun_l23_n664(x)
+ else
+ fun_l23_n73(x)
+ end
+end
+
+def fun_l22_n309(x)
+ if (x < 1)
+ fun_l23_n63(x)
+ else
+ fun_l23_n321(x)
+ end
+end
+
+def fun_l22_n310(x)
+ if (x < 1)
+ fun_l23_n348(x)
+ else
+ fun_l23_n961(x)
+ end
+end
+
+def fun_l22_n311(x)
+ if (x < 1)
+ fun_l23_n555(x)
+ else
+ fun_l23_n315(x)
+ end
+end
+
+def fun_l22_n312(x)
+ if (x < 1)
+ fun_l23_n978(x)
+ else
+ fun_l23_n498(x)
+ end
+end
+
+def fun_l22_n313(x)
+ if (x < 1)
+ fun_l23_n880(x)
+ else
+ fun_l23_n696(x)
+ end
+end
+
+def fun_l22_n314(x)
+ if (x < 1)
+ fun_l23_n325(x)
+ else
+ fun_l23_n43(x)
+ end
+end
+
+def fun_l22_n315(x)
+ if (x < 1)
+ fun_l23_n848(x)
+ else
+ fun_l23_n314(x)
+ end
+end
+
+def fun_l22_n316(x)
+ if (x < 1)
+ fun_l23_n660(x)
+ else
+ fun_l23_n378(x)
+ end
+end
+
+def fun_l22_n317(x)
+ if (x < 1)
+ fun_l23_n975(x)
+ else
+ fun_l23_n503(x)
+ end
+end
+
+def fun_l22_n318(x)
+ if (x < 1)
+ fun_l23_n41(x)
+ else
+ fun_l23_n746(x)
+ end
+end
+
+def fun_l22_n319(x)
+ if (x < 1)
+ fun_l23_n325(x)
+ else
+ fun_l23_n565(x)
+ end
+end
+
+def fun_l22_n320(x)
+ if (x < 1)
+ fun_l23_n19(x)
+ else
+ fun_l23_n922(x)
+ end
+end
+
+def fun_l22_n321(x)
+ if (x < 1)
+ fun_l23_n235(x)
+ else
+ fun_l23_n284(x)
+ end
+end
+
+def fun_l22_n322(x)
+ if (x < 1)
+ fun_l23_n591(x)
+ else
+ fun_l23_n821(x)
+ end
+end
+
+def fun_l22_n323(x)
+ if (x < 1)
+ fun_l23_n23(x)
+ else
+ fun_l23_n151(x)
+ end
+end
+
+def fun_l22_n324(x)
+ if (x < 1)
+ fun_l23_n361(x)
+ else
+ fun_l23_n322(x)
+ end
+end
+
+def fun_l22_n325(x)
+ if (x < 1)
+ fun_l23_n245(x)
+ else
+ fun_l23_n205(x)
+ end
+end
+
+def fun_l22_n326(x)
+ if (x < 1)
+ fun_l23_n568(x)
+ else
+ fun_l23_n133(x)
+ end
+end
+
+def fun_l22_n327(x)
+ if (x < 1)
+ fun_l23_n895(x)
+ else
+ fun_l23_n315(x)
+ end
+end
+
+def fun_l22_n328(x)
+ if (x < 1)
+ fun_l23_n473(x)
+ else
+ fun_l23_n315(x)
+ end
+end
+
+def fun_l22_n329(x)
+ if (x < 1)
+ fun_l23_n618(x)
+ else
+ fun_l23_n196(x)
+ end
+end
+
+def fun_l22_n330(x)
+ if (x < 1)
+ fun_l23_n97(x)
+ else
+ fun_l23_n422(x)
+ end
+end
+
+def fun_l22_n331(x)
+ if (x < 1)
+ fun_l23_n101(x)
+ else
+ fun_l23_n447(x)
+ end
+end
+
+def fun_l22_n332(x)
+ if (x < 1)
+ fun_l23_n875(x)
+ else
+ fun_l23_n197(x)
+ end
+end
+
+def fun_l22_n333(x)
+ if (x < 1)
+ fun_l23_n25(x)
+ else
+ fun_l23_n499(x)
+ end
+end
+
+def fun_l22_n334(x)
+ if (x < 1)
+ fun_l23_n602(x)
+ else
+ fun_l23_n75(x)
+ end
+end
+
+def fun_l22_n335(x)
+ if (x < 1)
+ fun_l23_n370(x)
+ else
+ fun_l23_n150(x)
+ end
+end
+
+def fun_l22_n336(x)
+ if (x < 1)
+ fun_l23_n960(x)
+ else
+ fun_l23_n498(x)
+ end
+end
+
+def fun_l22_n337(x)
+ if (x < 1)
+ fun_l23_n675(x)
+ else
+ fun_l23_n525(x)
+ end
+end
+
+def fun_l22_n338(x)
+ if (x < 1)
+ fun_l23_n445(x)
+ else
+ fun_l23_n581(x)
+ end
+end
+
+def fun_l22_n339(x)
+ if (x < 1)
+ fun_l23_n718(x)
+ else
+ fun_l23_n995(x)
+ end
+end
+
+def fun_l22_n340(x)
+ if (x < 1)
+ fun_l23_n790(x)
+ else
+ fun_l23_n370(x)
+ end
+end
+
+def fun_l22_n341(x)
+ if (x < 1)
+ fun_l23_n234(x)
+ else
+ fun_l23_n187(x)
+ end
+end
+
+def fun_l22_n342(x)
+ if (x < 1)
+ fun_l23_n777(x)
+ else
+ fun_l23_n411(x)
+ end
+end
+
+def fun_l22_n343(x)
+ if (x < 1)
+ fun_l23_n258(x)
+ else
+ fun_l23_n129(x)
+ end
+end
+
+def fun_l22_n344(x)
+ if (x < 1)
+ fun_l23_n715(x)
+ else
+ fun_l23_n381(x)
+ end
+end
+
+def fun_l22_n345(x)
+ if (x < 1)
+ fun_l23_n495(x)
+ else
+ fun_l23_n892(x)
+ end
+end
+
+def fun_l22_n346(x)
+ if (x < 1)
+ fun_l23_n433(x)
+ else
+ fun_l23_n987(x)
+ end
+end
+
+def fun_l22_n347(x)
+ if (x < 1)
+ fun_l23_n569(x)
+ else
+ fun_l23_n832(x)
+ end
+end
+
+def fun_l22_n348(x)
+ if (x < 1)
+ fun_l23_n425(x)
+ else
+ fun_l23_n894(x)
+ end
+end
+
+def fun_l22_n349(x)
+ if (x < 1)
+ fun_l23_n186(x)
+ else
+ fun_l23_n211(x)
+ end
+end
+
+def fun_l22_n350(x)
+ if (x < 1)
+ fun_l23_n435(x)
+ else
+ fun_l23_n393(x)
+ end
+end
+
+def fun_l22_n351(x)
+ if (x < 1)
+ fun_l23_n942(x)
+ else
+ fun_l23_n364(x)
+ end
+end
+
+def fun_l22_n352(x)
+ if (x < 1)
+ fun_l23_n29(x)
+ else
+ fun_l23_n574(x)
+ end
+end
+
+def fun_l22_n353(x)
+ if (x < 1)
+ fun_l23_n548(x)
+ else
+ fun_l23_n663(x)
+ end
+end
+
+def fun_l22_n354(x)
+ if (x < 1)
+ fun_l23_n238(x)
+ else
+ fun_l23_n693(x)
+ end
+end
+
+def fun_l22_n355(x)
+ if (x < 1)
+ fun_l23_n459(x)
+ else
+ fun_l23_n197(x)
+ end
+end
+
+def fun_l22_n356(x)
+ if (x < 1)
+ fun_l23_n478(x)
+ else
+ fun_l23_n905(x)
+ end
+end
+
+def fun_l22_n357(x)
+ if (x < 1)
+ fun_l23_n732(x)
+ else
+ fun_l23_n124(x)
+ end
+end
+
+def fun_l22_n358(x)
+ if (x < 1)
+ fun_l23_n716(x)
+ else
+ fun_l23_n758(x)
+ end
+end
+
+def fun_l22_n359(x)
+ if (x < 1)
+ fun_l23_n376(x)
+ else
+ fun_l23_n883(x)
+ end
+end
+
+def fun_l22_n360(x)
+ if (x < 1)
+ fun_l23_n100(x)
+ else
+ fun_l23_n485(x)
+ end
+end
+
+def fun_l22_n361(x)
+ if (x < 1)
+ fun_l23_n62(x)
+ else
+ fun_l23_n794(x)
+ end
+end
+
+def fun_l22_n362(x)
+ if (x < 1)
+ fun_l23_n951(x)
+ else
+ fun_l23_n23(x)
+ end
+end
+
+def fun_l22_n363(x)
+ if (x < 1)
+ fun_l23_n298(x)
+ else
+ fun_l23_n775(x)
+ end
+end
+
+def fun_l22_n364(x)
+ if (x < 1)
+ fun_l23_n53(x)
+ else
+ fun_l23_n595(x)
+ end
+end
+
+def fun_l22_n365(x)
+ if (x < 1)
+ fun_l23_n695(x)
+ else
+ fun_l23_n401(x)
+ end
+end
+
+def fun_l22_n366(x)
+ if (x < 1)
+ fun_l23_n475(x)
+ else
+ fun_l23_n762(x)
+ end
+end
+
+def fun_l22_n367(x)
+ if (x < 1)
+ fun_l23_n706(x)
+ else
+ fun_l23_n527(x)
+ end
+end
+
+def fun_l22_n368(x)
+ if (x < 1)
+ fun_l23_n919(x)
+ else
+ fun_l23_n301(x)
+ end
+end
+
+def fun_l22_n369(x)
+ if (x < 1)
+ fun_l23_n755(x)
+ else
+ fun_l23_n256(x)
+ end
+end
+
+def fun_l22_n370(x)
+ if (x < 1)
+ fun_l23_n592(x)
+ else
+ fun_l23_n608(x)
+ end
+end
+
+def fun_l22_n371(x)
+ if (x < 1)
+ fun_l23_n192(x)
+ else
+ fun_l23_n10(x)
+ end
+end
+
+def fun_l22_n372(x)
+ if (x < 1)
+ fun_l23_n332(x)
+ else
+ fun_l23_n448(x)
+ end
+end
+
+def fun_l22_n373(x)
+ if (x < 1)
+ fun_l23_n135(x)
+ else
+ fun_l23_n793(x)
+ end
+end
+
+def fun_l22_n374(x)
+ if (x < 1)
+ fun_l23_n141(x)
+ else
+ fun_l23_n669(x)
+ end
+end
+
+def fun_l22_n375(x)
+ if (x < 1)
+ fun_l23_n474(x)
+ else
+ fun_l23_n356(x)
+ end
+end
+
+def fun_l22_n376(x)
+ if (x < 1)
+ fun_l23_n69(x)
+ else
+ fun_l23_n384(x)
+ end
+end
+
+def fun_l22_n377(x)
+ if (x < 1)
+ fun_l23_n386(x)
+ else
+ fun_l23_n552(x)
+ end
+end
+
+def fun_l22_n378(x)
+ if (x < 1)
+ fun_l23_n878(x)
+ else
+ fun_l23_n131(x)
+ end
+end
+
+def fun_l22_n379(x)
+ if (x < 1)
+ fun_l23_n929(x)
+ else
+ fun_l23_n479(x)
+ end
+end
+
+def fun_l22_n380(x)
+ if (x < 1)
+ fun_l23_n782(x)
+ else
+ fun_l23_n745(x)
+ end
+end
+
+def fun_l22_n381(x)
+ if (x < 1)
+ fun_l23_n126(x)
+ else
+ fun_l23_n732(x)
+ end
+end
+
+def fun_l22_n382(x)
+ if (x < 1)
+ fun_l23_n694(x)
+ else
+ fun_l23_n291(x)
+ end
+end
+
+def fun_l22_n383(x)
+ if (x < 1)
+ fun_l23_n165(x)
+ else
+ fun_l23_n49(x)
+ end
+end
+
+def fun_l22_n384(x)
+ if (x < 1)
+ fun_l23_n453(x)
+ else
+ fun_l23_n144(x)
+ end
+end
+
+def fun_l22_n385(x)
+ if (x < 1)
+ fun_l23_n182(x)
+ else
+ fun_l23_n974(x)
+ end
+end
+
+def fun_l22_n386(x)
+ if (x < 1)
+ fun_l23_n861(x)
+ else
+ fun_l23_n185(x)
+ end
+end
+
+def fun_l22_n387(x)
+ if (x < 1)
+ fun_l23_n962(x)
+ else
+ fun_l23_n578(x)
+ end
+end
+
+def fun_l22_n388(x)
+ if (x < 1)
+ fun_l23_n88(x)
+ else
+ fun_l23_n508(x)
+ end
+end
+
+def fun_l22_n389(x)
+ if (x < 1)
+ fun_l23_n421(x)
+ else
+ fun_l23_n886(x)
+ end
+end
+
+def fun_l22_n390(x)
+ if (x < 1)
+ fun_l23_n992(x)
+ else
+ fun_l23_n540(x)
+ end
+end
+
+def fun_l22_n391(x)
+ if (x < 1)
+ fun_l23_n996(x)
+ else
+ fun_l23_n533(x)
+ end
+end
+
+def fun_l22_n392(x)
+ if (x < 1)
+ fun_l23_n97(x)
+ else
+ fun_l23_n803(x)
+ end
+end
+
+def fun_l22_n393(x)
+ if (x < 1)
+ fun_l23_n505(x)
+ else
+ fun_l23_n263(x)
+ end
+end
+
+def fun_l22_n394(x)
+ if (x < 1)
+ fun_l23_n52(x)
+ else
+ fun_l23_n566(x)
+ end
+end
+
+def fun_l22_n395(x)
+ if (x < 1)
+ fun_l23_n290(x)
+ else
+ fun_l23_n558(x)
+ end
+end
+
+def fun_l22_n396(x)
+ if (x < 1)
+ fun_l23_n51(x)
+ else
+ fun_l23_n365(x)
+ end
+end
+
+def fun_l22_n397(x)
+ if (x < 1)
+ fun_l23_n505(x)
+ else
+ fun_l23_n461(x)
+ end
+end
+
+def fun_l22_n398(x)
+ if (x < 1)
+ fun_l23_n415(x)
+ else
+ fun_l23_n460(x)
+ end
+end
+
+def fun_l22_n399(x)
+ if (x < 1)
+ fun_l23_n370(x)
+ else
+ fun_l23_n377(x)
+ end
+end
+
+def fun_l22_n400(x)
+ if (x < 1)
+ fun_l23_n644(x)
+ else
+ fun_l23_n300(x)
+ end
+end
+
+def fun_l22_n401(x)
+ if (x < 1)
+ fun_l23_n22(x)
+ else
+ fun_l23_n348(x)
+ end
+end
+
+def fun_l22_n402(x)
+ if (x < 1)
+ fun_l23_n286(x)
+ else
+ fun_l23_n991(x)
+ end
+end
+
+def fun_l22_n403(x)
+ if (x < 1)
+ fun_l23_n928(x)
+ else
+ fun_l23_n627(x)
+ end
+end
+
+def fun_l22_n404(x)
+ if (x < 1)
+ fun_l23_n884(x)
+ else
+ fun_l23_n326(x)
+ end
+end
+
+def fun_l22_n405(x)
+ if (x < 1)
+ fun_l23_n586(x)
+ else
+ fun_l23_n913(x)
+ end
+end
+
+def fun_l22_n406(x)
+ if (x < 1)
+ fun_l23_n732(x)
+ else
+ fun_l23_n964(x)
+ end
+end
+
+def fun_l22_n407(x)
+ if (x < 1)
+ fun_l23_n301(x)
+ else
+ fun_l23_n946(x)
+ end
+end
+
+def fun_l22_n408(x)
+ if (x < 1)
+ fun_l23_n540(x)
+ else
+ fun_l23_n29(x)
+ end
+end
+
+def fun_l22_n409(x)
+ if (x < 1)
+ fun_l23_n793(x)
+ else
+ fun_l23_n420(x)
+ end
+end
+
+def fun_l22_n410(x)
+ if (x < 1)
+ fun_l23_n766(x)
+ else
+ fun_l23_n473(x)
+ end
+end
+
+def fun_l22_n411(x)
+ if (x < 1)
+ fun_l23_n683(x)
+ else
+ fun_l23_n12(x)
+ end
+end
+
+def fun_l22_n412(x)
+ if (x < 1)
+ fun_l23_n273(x)
+ else
+ fun_l23_n45(x)
+ end
+end
+
+def fun_l22_n413(x)
+ if (x < 1)
+ fun_l23_n732(x)
+ else
+ fun_l23_n313(x)
+ end
+end
+
+def fun_l22_n414(x)
+ if (x < 1)
+ fun_l23_n291(x)
+ else
+ fun_l23_n216(x)
+ end
+end
+
+def fun_l22_n415(x)
+ if (x < 1)
+ fun_l23_n6(x)
+ else
+ fun_l23_n482(x)
+ end
+end
+
+def fun_l22_n416(x)
+ if (x < 1)
+ fun_l23_n214(x)
+ else
+ fun_l23_n341(x)
+ end
+end
+
+def fun_l22_n417(x)
+ if (x < 1)
+ fun_l23_n690(x)
+ else
+ fun_l23_n773(x)
+ end
+end
+
+def fun_l22_n418(x)
+ if (x < 1)
+ fun_l23_n437(x)
+ else
+ fun_l23_n941(x)
+ end
+end
+
+def fun_l22_n419(x)
+ if (x < 1)
+ fun_l23_n131(x)
+ else
+ fun_l23_n14(x)
+ end
+end
+
+def fun_l22_n420(x)
+ if (x < 1)
+ fun_l23_n924(x)
+ else
+ fun_l23_n359(x)
+ end
+end
+
+def fun_l22_n421(x)
+ if (x < 1)
+ fun_l23_n653(x)
+ else
+ fun_l23_n875(x)
+ end
+end
+
+def fun_l22_n422(x)
+ if (x < 1)
+ fun_l23_n411(x)
+ else
+ fun_l23_n981(x)
+ end
+end
+
+def fun_l22_n423(x)
+ if (x < 1)
+ fun_l23_n258(x)
+ else
+ fun_l23_n876(x)
+ end
+end
+
+def fun_l22_n424(x)
+ if (x < 1)
+ fun_l23_n430(x)
+ else
+ fun_l23_n62(x)
+ end
+end
+
+def fun_l22_n425(x)
+ if (x < 1)
+ fun_l23_n444(x)
+ else
+ fun_l23_n48(x)
+ end
+end
+
+def fun_l22_n426(x)
+ if (x < 1)
+ fun_l23_n905(x)
+ else
+ fun_l23_n458(x)
+ end
+end
+
+def fun_l22_n427(x)
+ if (x < 1)
+ fun_l23_n440(x)
+ else
+ fun_l23_n411(x)
+ end
+end
+
+def fun_l22_n428(x)
+ if (x < 1)
+ fun_l23_n655(x)
+ else
+ fun_l23_n622(x)
+ end
+end
+
+def fun_l22_n429(x)
+ if (x < 1)
+ fun_l23_n587(x)
+ else
+ fun_l23_n638(x)
+ end
+end
+
+def fun_l22_n430(x)
+ if (x < 1)
+ fun_l23_n156(x)
+ else
+ fun_l23_n900(x)
+ end
+end
+
+def fun_l22_n431(x)
+ if (x < 1)
+ fun_l23_n136(x)
+ else
+ fun_l23_n562(x)
+ end
+end
+
+def fun_l22_n432(x)
+ if (x < 1)
+ fun_l23_n897(x)
+ else
+ fun_l23_n16(x)
+ end
+end
+
+def fun_l22_n433(x)
+ if (x < 1)
+ fun_l23_n28(x)
+ else
+ fun_l23_n504(x)
+ end
+end
+
+def fun_l22_n434(x)
+ if (x < 1)
+ fun_l23_n987(x)
+ else
+ fun_l23_n640(x)
+ end
+end
+
+def fun_l22_n435(x)
+ if (x < 1)
+ fun_l23_n395(x)
+ else
+ fun_l23_n922(x)
+ end
+end
+
+def fun_l22_n436(x)
+ if (x < 1)
+ fun_l23_n679(x)
+ else
+ fun_l23_n576(x)
+ end
+end
+
+def fun_l22_n437(x)
+ if (x < 1)
+ fun_l23_n915(x)
+ else
+ fun_l23_n240(x)
+ end
+end
+
+def fun_l22_n438(x)
+ if (x < 1)
+ fun_l23_n889(x)
+ else
+ fun_l23_n38(x)
+ end
+end
+
+def fun_l22_n439(x)
+ if (x < 1)
+ fun_l23_n522(x)
+ else
+ fun_l23_n481(x)
+ end
+end
+
+def fun_l22_n440(x)
+ if (x < 1)
+ fun_l23_n458(x)
+ else
+ fun_l23_n81(x)
+ end
+end
+
+def fun_l22_n441(x)
+ if (x < 1)
+ fun_l23_n220(x)
+ else
+ fun_l23_n393(x)
+ end
+end
+
+def fun_l22_n442(x)
+ if (x < 1)
+ fun_l23_n404(x)
+ else
+ fun_l23_n945(x)
+ end
+end
+
+def fun_l22_n443(x)
+ if (x < 1)
+ fun_l23_n347(x)
+ else
+ fun_l23_n377(x)
+ end
+end
+
+def fun_l22_n444(x)
+ if (x < 1)
+ fun_l23_n484(x)
+ else
+ fun_l23_n277(x)
+ end
+end
+
+def fun_l22_n445(x)
+ if (x < 1)
+ fun_l23_n118(x)
+ else
+ fun_l23_n578(x)
+ end
+end
+
+def fun_l22_n446(x)
+ if (x < 1)
+ fun_l23_n674(x)
+ else
+ fun_l23_n238(x)
+ end
+end
+
+def fun_l22_n447(x)
+ if (x < 1)
+ fun_l23_n290(x)
+ else
+ fun_l23_n275(x)
+ end
+end
+
+def fun_l22_n448(x)
+ if (x < 1)
+ fun_l23_n358(x)
+ else
+ fun_l23_n939(x)
+ end
+end
+
+def fun_l22_n449(x)
+ if (x < 1)
+ fun_l23_n38(x)
+ else
+ fun_l23_n122(x)
+ end
+end
+
+def fun_l22_n450(x)
+ if (x < 1)
+ fun_l23_n575(x)
+ else
+ fun_l23_n582(x)
+ end
+end
+
+def fun_l22_n451(x)
+ if (x < 1)
+ fun_l23_n657(x)
+ else
+ fun_l23_n986(x)
+ end
+end
+
+def fun_l22_n452(x)
+ if (x < 1)
+ fun_l23_n771(x)
+ else
+ fun_l23_n603(x)
+ end
+end
+
+def fun_l22_n453(x)
+ if (x < 1)
+ fun_l23_n981(x)
+ else
+ fun_l23_n762(x)
+ end
+end
+
+def fun_l22_n454(x)
+ if (x < 1)
+ fun_l23_n93(x)
+ else
+ fun_l23_n26(x)
+ end
+end
+
+def fun_l22_n455(x)
+ if (x < 1)
+ fun_l23_n675(x)
+ else
+ fun_l23_n332(x)
+ end
+end
+
+def fun_l22_n456(x)
+ if (x < 1)
+ fun_l23_n923(x)
+ else
+ fun_l23_n416(x)
+ end
+end
+
+def fun_l22_n457(x)
+ if (x < 1)
+ fun_l23_n179(x)
+ else
+ fun_l23_n485(x)
+ end
+end
+
+def fun_l22_n458(x)
+ if (x < 1)
+ fun_l23_n38(x)
+ else
+ fun_l23_n319(x)
+ end
+end
+
+def fun_l22_n459(x)
+ if (x < 1)
+ fun_l23_n22(x)
+ else
+ fun_l23_n747(x)
+ end
+end
+
+def fun_l22_n460(x)
+ if (x < 1)
+ fun_l23_n643(x)
+ else
+ fun_l23_n132(x)
+ end
+end
+
+def fun_l22_n461(x)
+ if (x < 1)
+ fun_l23_n165(x)
+ else
+ fun_l23_n673(x)
+ end
+end
+
+def fun_l22_n462(x)
+ if (x < 1)
+ fun_l23_n988(x)
+ else
+ fun_l23_n916(x)
+ end
+end
+
+def fun_l22_n463(x)
+ if (x < 1)
+ fun_l23_n331(x)
+ else
+ fun_l23_n853(x)
+ end
+end
+
+def fun_l22_n464(x)
+ if (x < 1)
+ fun_l23_n699(x)
+ else
+ fun_l23_n771(x)
+ end
+end
+
+def fun_l22_n465(x)
+ if (x < 1)
+ fun_l23_n358(x)
+ else
+ fun_l23_n966(x)
+ end
+end
+
+def fun_l22_n466(x)
+ if (x < 1)
+ fun_l23_n723(x)
+ else
+ fun_l23_n897(x)
+ end
+end
+
+def fun_l22_n467(x)
+ if (x < 1)
+ fun_l23_n69(x)
+ else
+ fun_l23_n186(x)
+ end
+end
+
+def fun_l22_n468(x)
+ if (x < 1)
+ fun_l23_n661(x)
+ else
+ fun_l23_n420(x)
+ end
+end
+
+def fun_l22_n469(x)
+ if (x < 1)
+ fun_l23_n175(x)
+ else
+ fun_l23_n270(x)
+ end
+end
+
+def fun_l22_n470(x)
+ if (x < 1)
+ fun_l23_n556(x)
+ else
+ fun_l23_n344(x)
+ end
+end
+
+def fun_l22_n471(x)
+ if (x < 1)
+ fun_l23_n413(x)
+ else
+ fun_l23_n338(x)
+ end
+end
+
+def fun_l22_n472(x)
+ if (x < 1)
+ fun_l23_n456(x)
+ else
+ fun_l23_n125(x)
+ end
+end
+
+def fun_l22_n473(x)
+ if (x < 1)
+ fun_l23_n364(x)
+ else
+ fun_l23_n347(x)
+ end
+end
+
+def fun_l22_n474(x)
+ if (x < 1)
+ fun_l23_n436(x)
+ else
+ fun_l23_n897(x)
+ end
+end
+
+def fun_l22_n475(x)
+ if (x < 1)
+ fun_l23_n613(x)
+ else
+ fun_l23_n851(x)
+ end
+end
+
+def fun_l22_n476(x)
+ if (x < 1)
+ fun_l23_n754(x)
+ else
+ fun_l23_n755(x)
+ end
+end
+
+def fun_l22_n477(x)
+ if (x < 1)
+ fun_l23_n899(x)
+ else
+ fun_l23_n496(x)
+ end
+end
+
+def fun_l22_n478(x)
+ if (x < 1)
+ fun_l23_n183(x)
+ else
+ fun_l23_n864(x)
+ end
+end
+
+def fun_l22_n479(x)
+ if (x < 1)
+ fun_l23_n11(x)
+ else
+ fun_l23_n679(x)
+ end
+end
+
+def fun_l22_n480(x)
+ if (x < 1)
+ fun_l23_n160(x)
+ else
+ fun_l23_n747(x)
+ end
+end
+
+def fun_l22_n481(x)
+ if (x < 1)
+ fun_l23_n138(x)
+ else
+ fun_l23_n762(x)
+ end
+end
+
+def fun_l22_n482(x)
+ if (x < 1)
+ fun_l23_n467(x)
+ else
+ fun_l23_n148(x)
+ end
+end
+
+def fun_l22_n483(x)
+ if (x < 1)
+ fun_l23_n97(x)
+ else
+ fun_l23_n826(x)
+ end
+end
+
+def fun_l22_n484(x)
+ if (x < 1)
+ fun_l23_n754(x)
+ else
+ fun_l23_n661(x)
+ end
+end
+
+def fun_l22_n485(x)
+ if (x < 1)
+ fun_l23_n415(x)
+ else
+ fun_l23_n531(x)
+ end
+end
+
+def fun_l22_n486(x)
+ if (x < 1)
+ fun_l23_n543(x)
+ else
+ fun_l23_n271(x)
+ end
+end
+
+def fun_l22_n487(x)
+ if (x < 1)
+ fun_l23_n240(x)
+ else
+ fun_l23_n221(x)
+ end
+end
+
+def fun_l22_n488(x)
+ if (x < 1)
+ fun_l23_n208(x)
+ else
+ fun_l23_n633(x)
+ end
+end
+
+def fun_l22_n489(x)
+ if (x < 1)
+ fun_l23_n539(x)
+ else
+ fun_l23_n925(x)
+ end
+end
+
+def fun_l22_n490(x)
+ if (x < 1)
+ fun_l23_n141(x)
+ else
+ fun_l23_n142(x)
+ end
+end
+
+def fun_l22_n491(x)
+ if (x < 1)
+ fun_l23_n899(x)
+ else
+ fun_l23_n407(x)
+ end
+end
+
+def fun_l22_n492(x)
+ if (x < 1)
+ fun_l23_n237(x)
+ else
+ fun_l23_n836(x)
+ end
+end
+
+def fun_l22_n493(x)
+ if (x < 1)
+ fun_l23_n23(x)
+ else
+ fun_l23_n266(x)
+ end
+end
+
+def fun_l22_n494(x)
+ if (x < 1)
+ fun_l23_n819(x)
+ else
+ fun_l23_n473(x)
+ end
+end
+
+def fun_l22_n495(x)
+ if (x < 1)
+ fun_l23_n182(x)
+ else
+ fun_l23_n253(x)
+ end
+end
+
+def fun_l22_n496(x)
+ if (x < 1)
+ fun_l23_n459(x)
+ else
+ fun_l23_n421(x)
+ end
+end
+
+def fun_l22_n497(x)
+ if (x < 1)
+ fun_l23_n553(x)
+ else
+ fun_l23_n207(x)
+ end
+end
+
+def fun_l22_n498(x)
+ if (x < 1)
+ fun_l23_n5(x)
+ else
+ fun_l23_n261(x)
+ end
+end
+
+def fun_l22_n499(x)
+ if (x < 1)
+ fun_l23_n53(x)
+ else
+ fun_l23_n478(x)
+ end
+end
+
+def fun_l22_n500(x)
+ if (x < 1)
+ fun_l23_n489(x)
+ else
+ fun_l23_n77(x)
+ end
+end
+
+def fun_l22_n501(x)
+ if (x < 1)
+ fun_l23_n551(x)
+ else
+ fun_l23_n854(x)
+ end
+end
+
+def fun_l22_n502(x)
+ if (x < 1)
+ fun_l23_n32(x)
+ else
+ fun_l23_n241(x)
+ end
+end
+
+def fun_l22_n503(x)
+ if (x < 1)
+ fun_l23_n536(x)
+ else
+ fun_l23_n820(x)
+ end
+end
+
+def fun_l22_n504(x)
+ if (x < 1)
+ fun_l23_n521(x)
+ else
+ fun_l23_n551(x)
+ end
+end
+
+def fun_l22_n505(x)
+ if (x < 1)
+ fun_l23_n812(x)
+ else
+ fun_l23_n885(x)
+ end
+end
+
+def fun_l22_n506(x)
+ if (x < 1)
+ fun_l23_n935(x)
+ else
+ fun_l23_n38(x)
+ end
+end
+
+def fun_l22_n507(x)
+ if (x < 1)
+ fun_l23_n99(x)
+ else
+ fun_l23_n907(x)
+ end
+end
+
+def fun_l22_n508(x)
+ if (x < 1)
+ fun_l23_n89(x)
+ else
+ fun_l23_n322(x)
+ end
+end
+
+def fun_l22_n509(x)
+ if (x < 1)
+ fun_l23_n279(x)
+ else
+ fun_l23_n103(x)
+ end
+end
+
+def fun_l22_n510(x)
+ if (x < 1)
+ fun_l23_n476(x)
+ else
+ fun_l23_n947(x)
+ end
+end
+
+def fun_l22_n511(x)
+ if (x < 1)
+ fun_l23_n872(x)
+ else
+ fun_l23_n497(x)
+ end
+end
+
+def fun_l22_n512(x)
+ if (x < 1)
+ fun_l23_n508(x)
+ else
+ fun_l23_n548(x)
+ end
+end
+
+def fun_l22_n513(x)
+ if (x < 1)
+ fun_l23_n640(x)
+ else
+ fun_l23_n696(x)
+ end
+end
+
+def fun_l22_n514(x)
+ if (x < 1)
+ fun_l23_n694(x)
+ else
+ fun_l23_n483(x)
+ end
+end
+
+def fun_l22_n515(x)
+ if (x < 1)
+ fun_l23_n914(x)
+ else
+ fun_l23_n772(x)
+ end
+end
+
+def fun_l22_n516(x)
+ if (x < 1)
+ fun_l23_n192(x)
+ else
+ fun_l23_n35(x)
+ end
+end
+
+def fun_l22_n517(x)
+ if (x < 1)
+ fun_l23_n597(x)
+ else
+ fun_l23_n473(x)
+ end
+end
+
+def fun_l22_n518(x)
+ if (x < 1)
+ fun_l23_n974(x)
+ else
+ fun_l23_n315(x)
+ end
+end
+
+def fun_l22_n519(x)
+ if (x < 1)
+ fun_l23_n391(x)
+ else
+ fun_l23_n800(x)
+ end
+end
+
+def fun_l22_n520(x)
+ if (x < 1)
+ fun_l23_n106(x)
+ else
+ fun_l23_n170(x)
+ end
+end
+
+def fun_l22_n521(x)
+ if (x < 1)
+ fun_l23_n926(x)
+ else
+ fun_l23_n495(x)
+ end
+end
+
+def fun_l22_n522(x)
+ if (x < 1)
+ fun_l23_n135(x)
+ else
+ fun_l23_n304(x)
+ end
+end
+
+def fun_l22_n523(x)
+ if (x < 1)
+ fun_l23_n765(x)
+ else
+ fun_l23_n53(x)
+ end
+end
+
+def fun_l22_n524(x)
+ if (x < 1)
+ fun_l23_n699(x)
+ else
+ fun_l23_n158(x)
+ end
+end
+
+def fun_l22_n525(x)
+ if (x < 1)
+ fun_l23_n759(x)
+ else
+ fun_l23_n34(x)
+ end
+end
+
+def fun_l22_n526(x)
+ if (x < 1)
+ fun_l23_n813(x)
+ else
+ fun_l23_n938(x)
+ end
+end
+
+def fun_l22_n527(x)
+ if (x < 1)
+ fun_l23_n207(x)
+ else
+ fun_l23_n549(x)
+ end
+end
+
+def fun_l22_n528(x)
+ if (x < 1)
+ fun_l23_n468(x)
+ else
+ fun_l23_n681(x)
+ end
+end
+
+def fun_l22_n529(x)
+ if (x < 1)
+ fun_l23_n643(x)
+ else
+ fun_l23_n652(x)
+ end
+end
+
+def fun_l22_n530(x)
+ if (x < 1)
+ fun_l23_n254(x)
+ else
+ fun_l23_n283(x)
+ end
+end
+
+def fun_l22_n531(x)
+ if (x < 1)
+ fun_l23_n750(x)
+ else
+ fun_l23_n969(x)
+ end
+end
+
+def fun_l22_n532(x)
+ if (x < 1)
+ fun_l23_n343(x)
+ else
+ fun_l23_n578(x)
+ end
+end
+
+def fun_l22_n533(x)
+ if (x < 1)
+ fun_l23_n240(x)
+ else
+ fun_l23_n698(x)
+ end
+end
+
+def fun_l22_n534(x)
+ if (x < 1)
+ fun_l23_n497(x)
+ else
+ fun_l23_n992(x)
+ end
+end
+
+def fun_l22_n535(x)
+ if (x < 1)
+ fun_l23_n554(x)
+ else
+ fun_l23_n53(x)
+ end
+end
+
+def fun_l22_n536(x)
+ if (x < 1)
+ fun_l23_n165(x)
+ else
+ fun_l23_n467(x)
+ end
+end
+
+def fun_l22_n537(x)
+ if (x < 1)
+ fun_l23_n2(x)
+ else
+ fun_l23_n560(x)
+ end
+end
+
+def fun_l22_n538(x)
+ if (x < 1)
+ fun_l23_n151(x)
+ else
+ fun_l23_n434(x)
+ end
+end
+
+def fun_l22_n539(x)
+ if (x < 1)
+ fun_l23_n108(x)
+ else
+ fun_l23_n108(x)
+ end
+end
+
+def fun_l22_n540(x)
+ if (x < 1)
+ fun_l23_n879(x)
+ else
+ fun_l23_n608(x)
+ end
+end
+
+def fun_l22_n541(x)
+ if (x < 1)
+ fun_l23_n160(x)
+ else
+ fun_l23_n820(x)
+ end
+end
+
+def fun_l22_n542(x)
+ if (x < 1)
+ fun_l23_n813(x)
+ else
+ fun_l23_n169(x)
+ end
+end
+
+def fun_l22_n543(x)
+ if (x < 1)
+ fun_l23_n151(x)
+ else
+ fun_l23_n420(x)
+ end
+end
+
+def fun_l22_n544(x)
+ if (x < 1)
+ fun_l23_n81(x)
+ else
+ fun_l23_n226(x)
+ end
+end
+
+def fun_l22_n545(x)
+ if (x < 1)
+ fun_l23_n464(x)
+ else
+ fun_l23_n602(x)
+ end
+end
+
+def fun_l22_n546(x)
+ if (x < 1)
+ fun_l23_n798(x)
+ else
+ fun_l23_n395(x)
+ end
+end
+
+def fun_l22_n547(x)
+ if (x < 1)
+ fun_l23_n597(x)
+ else
+ fun_l23_n147(x)
+ end
+end
+
+def fun_l22_n548(x)
+ if (x < 1)
+ fun_l23_n952(x)
+ else
+ fun_l23_n515(x)
+ end
+end
+
+def fun_l22_n549(x)
+ if (x < 1)
+ fun_l23_n134(x)
+ else
+ fun_l23_n154(x)
+ end
+end
+
+def fun_l22_n550(x)
+ if (x < 1)
+ fun_l23_n35(x)
+ else
+ fun_l23_n492(x)
+ end
+end
+
+def fun_l22_n551(x)
+ if (x < 1)
+ fun_l23_n878(x)
+ else
+ fun_l23_n899(x)
+ end
+end
+
+def fun_l22_n552(x)
+ if (x < 1)
+ fun_l23_n574(x)
+ else
+ fun_l23_n108(x)
+ end
+end
+
+def fun_l22_n553(x)
+ if (x < 1)
+ fun_l23_n386(x)
+ else
+ fun_l23_n565(x)
+ end
+end
+
+def fun_l22_n554(x)
+ if (x < 1)
+ fun_l23_n551(x)
+ else
+ fun_l23_n905(x)
+ end
+end
+
+def fun_l22_n555(x)
+ if (x < 1)
+ fun_l23_n680(x)
+ else
+ fun_l23_n367(x)
+ end
+end
+
+def fun_l22_n556(x)
+ if (x < 1)
+ fun_l23_n452(x)
+ else
+ fun_l23_n211(x)
+ end
+end
+
+def fun_l22_n557(x)
+ if (x < 1)
+ fun_l23_n597(x)
+ else
+ fun_l23_n112(x)
+ end
+end
+
+def fun_l22_n558(x)
+ if (x < 1)
+ fun_l23_n22(x)
+ else
+ fun_l23_n966(x)
+ end
+end
+
+def fun_l22_n559(x)
+ if (x < 1)
+ fun_l23_n512(x)
+ else
+ fun_l23_n337(x)
+ end
+end
+
+def fun_l22_n560(x)
+ if (x < 1)
+ fun_l23_n649(x)
+ else
+ fun_l23_n361(x)
+ end
+end
+
+def fun_l22_n561(x)
+ if (x < 1)
+ fun_l23_n500(x)
+ else
+ fun_l23_n113(x)
+ end
+end
+
+def fun_l22_n562(x)
+ if (x < 1)
+ fun_l23_n455(x)
+ else
+ fun_l23_n734(x)
+ end
+end
+
+def fun_l22_n563(x)
+ if (x < 1)
+ fun_l23_n847(x)
+ else
+ fun_l23_n86(x)
+ end
+end
+
+def fun_l22_n564(x)
+ if (x < 1)
+ fun_l23_n251(x)
+ else
+ fun_l23_n203(x)
+ end
+end
+
+def fun_l22_n565(x)
+ if (x < 1)
+ fun_l23_n977(x)
+ else
+ fun_l23_n893(x)
+ end
+end
+
+def fun_l22_n566(x)
+ if (x < 1)
+ fun_l23_n693(x)
+ else
+ fun_l23_n507(x)
+ end
+end
+
+def fun_l22_n567(x)
+ if (x < 1)
+ fun_l23_n194(x)
+ else
+ fun_l23_n972(x)
+ end
+end
+
+def fun_l22_n568(x)
+ if (x < 1)
+ fun_l23_n44(x)
+ else
+ fun_l23_n694(x)
+ end
+end
+
+def fun_l22_n569(x)
+ if (x < 1)
+ fun_l23_n277(x)
+ else
+ fun_l23_n317(x)
+ end
+end
+
+def fun_l22_n570(x)
+ if (x < 1)
+ fun_l23_n40(x)
+ else
+ fun_l23_n10(x)
+ end
+end
+
+def fun_l22_n571(x)
+ if (x < 1)
+ fun_l23_n199(x)
+ else
+ fun_l23_n454(x)
+ end
+end
+
+def fun_l22_n572(x)
+ if (x < 1)
+ fun_l23_n821(x)
+ else
+ fun_l23_n556(x)
+ end
+end
+
+def fun_l22_n573(x)
+ if (x < 1)
+ fun_l23_n142(x)
+ else
+ fun_l23_n307(x)
+ end
+end
+
+def fun_l22_n574(x)
+ if (x < 1)
+ fun_l23_n291(x)
+ else
+ fun_l23_n152(x)
+ end
+end
+
+def fun_l22_n575(x)
+ if (x < 1)
+ fun_l23_n547(x)
+ else
+ fun_l23_n580(x)
+ end
+end
+
+def fun_l22_n576(x)
+ if (x < 1)
+ fun_l23_n841(x)
+ else
+ fun_l23_n518(x)
+ end
+end
+
+def fun_l22_n577(x)
+ if (x < 1)
+ fun_l23_n91(x)
+ else
+ fun_l23_n730(x)
+ end
+end
+
+def fun_l22_n578(x)
+ if (x < 1)
+ fun_l23_n626(x)
+ else
+ fun_l23_n403(x)
+ end
+end
+
+def fun_l22_n579(x)
+ if (x < 1)
+ fun_l23_n12(x)
+ else
+ fun_l23_n863(x)
+ end
+end
+
+def fun_l22_n580(x)
+ if (x < 1)
+ fun_l23_n878(x)
+ else
+ fun_l23_n28(x)
+ end
+end
+
+def fun_l22_n581(x)
+ if (x < 1)
+ fun_l23_n793(x)
+ else
+ fun_l23_n942(x)
+ end
+end
+
+def fun_l22_n582(x)
+ if (x < 1)
+ fun_l23_n168(x)
+ else
+ fun_l23_n102(x)
+ end
+end
+
+def fun_l22_n583(x)
+ if (x < 1)
+ fun_l23_n40(x)
+ else
+ fun_l23_n231(x)
+ end
+end
+
+def fun_l22_n584(x)
+ if (x < 1)
+ fun_l23_n54(x)
+ else
+ fun_l23_n734(x)
+ end
+end
+
+def fun_l22_n585(x)
+ if (x < 1)
+ fun_l23_n878(x)
+ else
+ fun_l23_n938(x)
+ end
+end
+
+def fun_l22_n586(x)
+ if (x < 1)
+ fun_l23_n89(x)
+ else
+ fun_l23_n533(x)
+ end
+end
+
+def fun_l22_n587(x)
+ if (x < 1)
+ fun_l23_n289(x)
+ else
+ fun_l23_n587(x)
+ end
+end
+
+def fun_l22_n588(x)
+ if (x < 1)
+ fun_l23_n716(x)
+ else
+ fun_l23_n785(x)
+ end
+end
+
+def fun_l22_n589(x)
+ if (x < 1)
+ fun_l23_n22(x)
+ else
+ fun_l23_n820(x)
+ end
+end
+
+def fun_l22_n590(x)
+ if (x < 1)
+ fun_l23_n945(x)
+ else
+ fun_l23_n644(x)
+ end
+end
+
+def fun_l22_n591(x)
+ if (x < 1)
+ fun_l23_n209(x)
+ else
+ fun_l23_n86(x)
+ end
+end
+
+def fun_l22_n592(x)
+ if (x < 1)
+ fun_l23_n209(x)
+ else
+ fun_l23_n971(x)
+ end
+end
+
+def fun_l22_n593(x)
+ if (x < 1)
+ fun_l23_n489(x)
+ else
+ fun_l23_n725(x)
+ end
+end
+
+def fun_l22_n594(x)
+ if (x < 1)
+ fun_l23_n42(x)
+ else
+ fun_l23_n405(x)
+ end
+end
+
+def fun_l22_n595(x)
+ if (x < 1)
+ fun_l23_n162(x)
+ else
+ fun_l23_n222(x)
+ end
+end
+
+def fun_l22_n596(x)
+ if (x < 1)
+ fun_l23_n942(x)
+ else
+ fun_l23_n193(x)
+ end
+end
+
+def fun_l22_n597(x)
+ if (x < 1)
+ fun_l23_n616(x)
+ else
+ fun_l23_n806(x)
+ end
+end
+
+def fun_l22_n598(x)
+ if (x < 1)
+ fun_l23_n278(x)
+ else
+ fun_l23_n330(x)
+ end
+end
+
+def fun_l22_n599(x)
+ if (x < 1)
+ fun_l23_n863(x)
+ else
+ fun_l23_n428(x)
+ end
+end
+
+def fun_l22_n600(x)
+ if (x < 1)
+ fun_l23_n315(x)
+ else
+ fun_l23_n319(x)
+ end
+end
+
+def fun_l22_n601(x)
+ if (x < 1)
+ fun_l23_n409(x)
+ else
+ fun_l23_n682(x)
+ end
+end
+
+def fun_l22_n602(x)
+ if (x < 1)
+ fun_l23_n307(x)
+ else
+ fun_l23_n47(x)
+ end
+end
+
+def fun_l22_n603(x)
+ if (x < 1)
+ fun_l23_n578(x)
+ else
+ fun_l23_n762(x)
+ end
+end
+
+def fun_l22_n604(x)
+ if (x < 1)
+ fun_l23_n208(x)
+ else
+ fun_l23_n314(x)
+ end
+end
+
+def fun_l22_n605(x)
+ if (x < 1)
+ fun_l23_n259(x)
+ else
+ fun_l23_n720(x)
+ end
+end
+
+def fun_l22_n606(x)
+ if (x < 1)
+ fun_l23_n272(x)
+ else
+ fun_l23_n619(x)
+ end
+end
+
+def fun_l22_n607(x)
+ if (x < 1)
+ fun_l23_n550(x)
+ else
+ fun_l23_n850(x)
+ end
+end
+
+def fun_l22_n608(x)
+ if (x < 1)
+ fun_l23_n617(x)
+ else
+ fun_l23_n999(x)
+ end
+end
+
+def fun_l22_n609(x)
+ if (x < 1)
+ fun_l23_n203(x)
+ else
+ fun_l23_n597(x)
+ end
+end
+
+def fun_l22_n610(x)
+ if (x < 1)
+ fun_l23_n547(x)
+ else
+ fun_l23_n252(x)
+ end
+end
+
+def fun_l22_n611(x)
+ if (x < 1)
+ fun_l23_n427(x)
+ else
+ fun_l23_n16(x)
+ end
+end
+
+def fun_l22_n612(x)
+ if (x < 1)
+ fun_l23_n236(x)
+ else
+ fun_l23_n142(x)
+ end
+end
+
+def fun_l22_n613(x)
+ if (x < 1)
+ fun_l23_n94(x)
+ else
+ fun_l23_n739(x)
+ end
+end
+
+def fun_l22_n614(x)
+ if (x < 1)
+ fun_l23_n504(x)
+ else
+ fun_l23_n101(x)
+ end
+end
+
+def fun_l22_n615(x)
+ if (x < 1)
+ fun_l23_n469(x)
+ else
+ fun_l23_n650(x)
+ end
+end
+
+def fun_l22_n616(x)
+ if (x < 1)
+ fun_l23_n752(x)
+ else
+ fun_l23_n262(x)
+ end
+end
+
+def fun_l22_n617(x)
+ if (x < 1)
+ fun_l23_n256(x)
+ else
+ fun_l23_n269(x)
+ end
+end
+
+def fun_l22_n618(x)
+ if (x < 1)
+ fun_l23_n784(x)
+ else
+ fun_l23_n402(x)
+ end
+end
+
+def fun_l22_n619(x)
+ if (x < 1)
+ fun_l23_n405(x)
+ else
+ fun_l23_n585(x)
+ end
+end
+
+def fun_l22_n620(x)
+ if (x < 1)
+ fun_l23_n33(x)
+ else
+ fun_l23_n357(x)
+ end
+end
+
+def fun_l22_n621(x)
+ if (x < 1)
+ fun_l23_n448(x)
+ else
+ fun_l23_n618(x)
+ end
+end
+
+def fun_l22_n622(x)
+ if (x < 1)
+ fun_l23_n520(x)
+ else
+ fun_l23_n612(x)
+ end
+end
+
+def fun_l22_n623(x)
+ if (x < 1)
+ fun_l23_n54(x)
+ else
+ fun_l23_n872(x)
+ end
+end
+
+def fun_l22_n624(x)
+ if (x < 1)
+ fun_l23_n915(x)
+ else
+ fun_l23_n1(x)
+ end
+end
+
+def fun_l22_n625(x)
+ if (x < 1)
+ fun_l23_n274(x)
+ else
+ fun_l23_n509(x)
+ end
+end
+
+def fun_l22_n626(x)
+ if (x < 1)
+ fun_l23_n506(x)
+ else
+ fun_l23_n938(x)
+ end
+end
+
+def fun_l22_n627(x)
+ if (x < 1)
+ fun_l23_n463(x)
+ else
+ fun_l23_n436(x)
+ end
+end
+
+def fun_l22_n628(x)
+ if (x < 1)
+ fun_l23_n33(x)
+ else
+ fun_l23_n279(x)
+ end
+end
+
+def fun_l22_n629(x)
+ if (x < 1)
+ fun_l23_n825(x)
+ else
+ fun_l23_n11(x)
+ end
+end
+
+def fun_l22_n630(x)
+ if (x < 1)
+ fun_l23_n778(x)
+ else
+ fun_l23_n77(x)
+ end
+end
+
+def fun_l22_n631(x)
+ if (x < 1)
+ fun_l23_n826(x)
+ else
+ fun_l23_n601(x)
+ end
+end
+
+def fun_l22_n632(x)
+ if (x < 1)
+ fun_l23_n973(x)
+ else
+ fun_l23_n444(x)
+ end
+end
+
+def fun_l22_n633(x)
+ if (x < 1)
+ fun_l23_n59(x)
+ else
+ fun_l23_n578(x)
+ end
+end
+
+def fun_l22_n634(x)
+ if (x < 1)
+ fun_l23_n366(x)
+ else
+ fun_l23_n128(x)
+ end
+end
+
+def fun_l22_n635(x)
+ if (x < 1)
+ fun_l23_n733(x)
+ else
+ fun_l23_n486(x)
+ end
+end
+
+def fun_l22_n636(x)
+ if (x < 1)
+ fun_l23_n22(x)
+ else
+ fun_l23_n997(x)
+ end
+end
+
+def fun_l22_n637(x)
+ if (x < 1)
+ fun_l23_n286(x)
+ else
+ fun_l23_n609(x)
+ end
+end
+
+def fun_l22_n638(x)
+ if (x < 1)
+ fun_l23_n519(x)
+ else
+ fun_l23_n381(x)
+ end
+end
+
+def fun_l22_n639(x)
+ if (x < 1)
+ fun_l23_n697(x)
+ else
+ fun_l23_n954(x)
+ end
+end
+
+def fun_l22_n640(x)
+ if (x < 1)
+ fun_l23_n348(x)
+ else
+ fun_l23_n261(x)
+ end
+end
+
+def fun_l22_n641(x)
+ if (x < 1)
+ fun_l23_n426(x)
+ else
+ fun_l23_n166(x)
+ end
+end
+
+def fun_l22_n642(x)
+ if (x < 1)
+ fun_l23_n488(x)
+ else
+ fun_l23_n79(x)
+ end
+end
+
+def fun_l22_n643(x)
+ if (x < 1)
+ fun_l23_n186(x)
+ else
+ fun_l23_n723(x)
+ end
+end
+
+def fun_l22_n644(x)
+ if (x < 1)
+ fun_l23_n582(x)
+ else
+ fun_l23_n365(x)
+ end
+end
+
+def fun_l22_n645(x)
+ if (x < 1)
+ fun_l23_n36(x)
+ else
+ fun_l23_n726(x)
+ end
+end
+
+def fun_l22_n646(x)
+ if (x < 1)
+ fun_l23_n585(x)
+ else
+ fun_l23_n770(x)
+ end
+end
+
+def fun_l22_n647(x)
+ if (x < 1)
+ fun_l23_n68(x)
+ else
+ fun_l23_n261(x)
+ end
+end
+
+def fun_l22_n648(x)
+ if (x < 1)
+ fun_l23_n208(x)
+ else
+ fun_l23_n302(x)
+ end
+end
+
+def fun_l22_n649(x)
+ if (x < 1)
+ fun_l23_n539(x)
+ else
+ fun_l23_n731(x)
+ end
+end
+
+def fun_l22_n650(x)
+ if (x < 1)
+ fun_l23_n709(x)
+ else
+ fun_l23_n144(x)
+ end
+end
+
+def fun_l22_n651(x)
+ if (x < 1)
+ fun_l23_n802(x)
+ else
+ fun_l23_n886(x)
+ end
+end
+
+def fun_l22_n652(x)
+ if (x < 1)
+ fun_l23_n796(x)
+ else
+ fun_l23_n574(x)
+ end
+end
+
+def fun_l22_n653(x)
+ if (x < 1)
+ fun_l23_n755(x)
+ else
+ fun_l23_n960(x)
+ end
+end
+
+def fun_l22_n654(x)
+ if (x < 1)
+ fun_l23_n415(x)
+ else
+ fun_l23_n543(x)
+ end
+end
+
+def fun_l22_n655(x)
+ if (x < 1)
+ fun_l23_n932(x)
+ else
+ fun_l23_n412(x)
+ end
+end
+
+def fun_l22_n656(x)
+ if (x < 1)
+ fun_l23_n216(x)
+ else
+ fun_l23_n869(x)
+ end
+end
+
+def fun_l22_n657(x)
+ if (x < 1)
+ fun_l23_n750(x)
+ else
+ fun_l23_n66(x)
+ end
+end
+
+def fun_l22_n658(x)
+ if (x < 1)
+ fun_l23_n400(x)
+ else
+ fun_l23_n31(x)
+ end
+end
+
+def fun_l22_n659(x)
+ if (x < 1)
+ fun_l23_n815(x)
+ else
+ fun_l23_n866(x)
+ end
+end
+
+def fun_l22_n660(x)
+ if (x < 1)
+ fun_l23_n459(x)
+ else
+ fun_l23_n833(x)
+ end
+end
+
+def fun_l22_n661(x)
+ if (x < 1)
+ fun_l23_n167(x)
+ else
+ fun_l23_n861(x)
+ end
+end
+
+def fun_l22_n662(x)
+ if (x < 1)
+ fun_l23_n789(x)
+ else
+ fun_l23_n543(x)
+ end
+end
+
+def fun_l22_n663(x)
+ if (x < 1)
+ fun_l23_n850(x)
+ else
+ fun_l23_n899(x)
+ end
+end
+
+def fun_l22_n664(x)
+ if (x < 1)
+ fun_l23_n986(x)
+ else
+ fun_l23_n924(x)
+ end
+end
+
+def fun_l22_n665(x)
+ if (x < 1)
+ fun_l23_n667(x)
+ else
+ fun_l23_n510(x)
+ end
+end
+
+def fun_l22_n666(x)
+ if (x < 1)
+ fun_l23_n744(x)
+ else
+ fun_l23_n530(x)
+ end
+end
+
+def fun_l22_n667(x)
+ if (x < 1)
+ fun_l23_n930(x)
+ else
+ fun_l23_n693(x)
+ end
+end
+
+def fun_l22_n668(x)
+ if (x < 1)
+ fun_l23_n942(x)
+ else
+ fun_l23_n785(x)
+ end
+end
+
+def fun_l22_n669(x)
+ if (x < 1)
+ fun_l23_n520(x)
+ else
+ fun_l23_n342(x)
+ end
+end
+
+def fun_l22_n670(x)
+ if (x < 1)
+ fun_l23_n865(x)
+ else
+ fun_l23_n63(x)
+ end
+end
+
+def fun_l22_n671(x)
+ if (x < 1)
+ fun_l23_n173(x)
+ else
+ fun_l23_n142(x)
+ end
+end
+
+def fun_l22_n672(x)
+ if (x < 1)
+ fun_l23_n487(x)
+ else
+ fun_l23_n400(x)
+ end
+end
+
+def fun_l22_n673(x)
+ if (x < 1)
+ fun_l23_n330(x)
+ else
+ fun_l23_n639(x)
+ end
+end
+
+def fun_l22_n674(x)
+ if (x < 1)
+ fun_l23_n593(x)
+ else
+ fun_l23_n653(x)
+ end
+end
+
+def fun_l22_n675(x)
+ if (x < 1)
+ fun_l23_n167(x)
+ else
+ fun_l23_n173(x)
+ end
+end
+
+def fun_l22_n676(x)
+ if (x < 1)
+ fun_l23_n288(x)
+ else
+ fun_l23_n412(x)
+ end
+end
+
+def fun_l22_n677(x)
+ if (x < 1)
+ fun_l23_n266(x)
+ else
+ fun_l23_n728(x)
+ end
+end
+
+def fun_l22_n678(x)
+ if (x < 1)
+ fun_l23_n137(x)
+ else
+ fun_l23_n277(x)
+ end
+end
+
+def fun_l22_n679(x)
+ if (x < 1)
+ fun_l23_n732(x)
+ else
+ fun_l23_n760(x)
+ end
+end
+
+def fun_l22_n680(x)
+ if (x < 1)
+ fun_l23_n372(x)
+ else
+ fun_l23_n26(x)
+ end
+end
+
+def fun_l22_n681(x)
+ if (x < 1)
+ fun_l23_n156(x)
+ else
+ fun_l23_n449(x)
+ end
+end
+
+def fun_l22_n682(x)
+ if (x < 1)
+ fun_l23_n117(x)
+ else
+ fun_l23_n711(x)
+ end
+end
+
+def fun_l22_n683(x)
+ if (x < 1)
+ fun_l23_n732(x)
+ else
+ fun_l23_n922(x)
+ end
+end
+
+def fun_l22_n684(x)
+ if (x < 1)
+ fun_l23_n116(x)
+ else
+ fun_l23_n347(x)
+ end
+end
+
+def fun_l22_n685(x)
+ if (x < 1)
+ fun_l23_n277(x)
+ else
+ fun_l23_n837(x)
+ end
+end
+
+def fun_l22_n686(x)
+ if (x < 1)
+ fun_l23_n578(x)
+ else
+ fun_l23_n290(x)
+ end
+end
+
+def fun_l22_n687(x)
+ if (x < 1)
+ fun_l23_n858(x)
+ else
+ fun_l23_n390(x)
+ end
+end
+
+def fun_l22_n688(x)
+ if (x < 1)
+ fun_l23_n52(x)
+ else
+ fun_l23_n759(x)
+ end
+end
+
+def fun_l22_n689(x)
+ if (x < 1)
+ fun_l23_n873(x)
+ else
+ fun_l23_n25(x)
+ end
+end
+
+def fun_l22_n690(x)
+ if (x < 1)
+ fun_l23_n262(x)
+ else
+ fun_l23_n511(x)
+ end
+end
+
+def fun_l22_n691(x)
+ if (x < 1)
+ fun_l23_n654(x)
+ else
+ fun_l23_n359(x)
+ end
+end
+
+def fun_l22_n692(x)
+ if (x < 1)
+ fun_l23_n933(x)
+ else
+ fun_l23_n369(x)
+ end
+end
+
+def fun_l22_n693(x)
+ if (x < 1)
+ fun_l23_n845(x)
+ else
+ fun_l23_n999(x)
+ end
+end
+
+def fun_l22_n694(x)
+ if (x < 1)
+ fun_l23_n479(x)
+ else
+ fun_l23_n284(x)
+ end
+end
+
+def fun_l22_n695(x)
+ if (x < 1)
+ fun_l23_n383(x)
+ else
+ fun_l23_n91(x)
+ end
+end
+
+def fun_l22_n696(x)
+ if (x < 1)
+ fun_l23_n467(x)
+ else
+ fun_l23_n555(x)
+ end
+end
+
+def fun_l22_n697(x)
+ if (x < 1)
+ fun_l23_n590(x)
+ else
+ fun_l23_n372(x)
+ end
+end
+
+def fun_l22_n698(x)
+ if (x < 1)
+ fun_l23_n706(x)
+ else
+ fun_l23_n195(x)
+ end
+end
+
+def fun_l22_n699(x)
+ if (x < 1)
+ fun_l23_n621(x)
+ else
+ fun_l23_n265(x)
+ end
+end
+
+def fun_l22_n700(x)
+ if (x < 1)
+ fun_l23_n505(x)
+ else
+ fun_l23_n831(x)
+ end
+end
+
+def fun_l22_n701(x)
+ if (x < 1)
+ fun_l23_n361(x)
+ else
+ fun_l23_n74(x)
+ end
+end
+
+def fun_l22_n702(x)
+ if (x < 1)
+ fun_l23_n734(x)
+ else
+ fun_l23_n922(x)
+ end
+end
+
+def fun_l22_n703(x)
+ if (x < 1)
+ fun_l23_n457(x)
+ else
+ fun_l23_n219(x)
+ end
+end
+
+def fun_l22_n704(x)
+ if (x < 1)
+ fun_l23_n436(x)
+ else
+ fun_l23_n733(x)
+ end
+end
+
+def fun_l22_n705(x)
+ if (x < 1)
+ fun_l23_n150(x)
+ else
+ fun_l23_n463(x)
+ end
+end
+
+def fun_l22_n706(x)
+ if (x < 1)
+ fun_l23_n486(x)
+ else
+ fun_l23_n906(x)
+ end
+end
+
+def fun_l22_n707(x)
+ if (x < 1)
+ fun_l23_n826(x)
+ else
+ fun_l23_n829(x)
+ end
+end
+
+def fun_l22_n708(x)
+ if (x < 1)
+ fun_l23_n186(x)
+ else
+ fun_l23_n555(x)
+ end
+end
+
+def fun_l22_n709(x)
+ if (x < 1)
+ fun_l23_n186(x)
+ else
+ fun_l23_n739(x)
+ end
+end
+
+def fun_l22_n710(x)
+ if (x < 1)
+ fun_l23_n58(x)
+ else
+ fun_l23_n395(x)
+ end
+end
+
+def fun_l22_n711(x)
+ if (x < 1)
+ fun_l23_n916(x)
+ else
+ fun_l23_n546(x)
+ end
+end
+
+def fun_l22_n712(x)
+ if (x < 1)
+ fun_l23_n309(x)
+ else
+ fun_l23_n582(x)
+ end
+end
+
+def fun_l22_n713(x)
+ if (x < 1)
+ fun_l23_n460(x)
+ else
+ fun_l23_n1(x)
+ end
+end
+
+def fun_l22_n714(x)
+ if (x < 1)
+ fun_l23_n270(x)
+ else
+ fun_l23_n888(x)
+ end
+end
+
+def fun_l22_n715(x)
+ if (x < 1)
+ fun_l23_n564(x)
+ else
+ fun_l23_n652(x)
+ end
+end
+
+def fun_l22_n716(x)
+ if (x < 1)
+ fun_l23_n14(x)
+ else
+ fun_l23_n862(x)
+ end
+end
+
+def fun_l22_n717(x)
+ if (x < 1)
+ fun_l23_n15(x)
+ else
+ fun_l23_n366(x)
+ end
+end
+
+def fun_l22_n718(x)
+ if (x < 1)
+ fun_l23_n580(x)
+ else
+ fun_l23_n367(x)
+ end
+end
+
+def fun_l22_n719(x)
+ if (x < 1)
+ fun_l23_n256(x)
+ else
+ fun_l23_n385(x)
+ end
+end
+
+def fun_l22_n720(x)
+ if (x < 1)
+ fun_l23_n735(x)
+ else
+ fun_l23_n811(x)
+ end
+end
+
+def fun_l22_n721(x)
+ if (x < 1)
+ fun_l23_n348(x)
+ else
+ fun_l23_n681(x)
+ end
+end
+
+def fun_l22_n722(x)
+ if (x < 1)
+ fun_l23_n908(x)
+ else
+ fun_l23_n80(x)
+ end
+end
+
+def fun_l22_n723(x)
+ if (x < 1)
+ fun_l23_n523(x)
+ else
+ fun_l23_n91(x)
+ end
+end
+
+def fun_l22_n724(x)
+ if (x < 1)
+ fun_l23_n212(x)
+ else
+ fun_l23_n220(x)
+ end
+end
+
+def fun_l22_n725(x)
+ if (x < 1)
+ fun_l23_n396(x)
+ else
+ fun_l23_n855(x)
+ end
+end
+
+def fun_l22_n726(x)
+ if (x < 1)
+ fun_l23_n717(x)
+ else
+ fun_l23_n314(x)
+ end
+end
+
+def fun_l22_n727(x)
+ if (x < 1)
+ fun_l23_n152(x)
+ else
+ fun_l23_n374(x)
+ end
+end
+
+def fun_l22_n728(x)
+ if (x < 1)
+ fun_l23_n464(x)
+ else
+ fun_l23_n439(x)
+ end
+end
+
+def fun_l22_n729(x)
+ if (x < 1)
+ fun_l23_n631(x)
+ else
+ fun_l23_n601(x)
+ end
+end
+
+def fun_l22_n730(x)
+ if (x < 1)
+ fun_l23_n689(x)
+ else
+ fun_l23_n929(x)
+ end
+end
+
+def fun_l22_n731(x)
+ if (x < 1)
+ fun_l23_n691(x)
+ else
+ fun_l23_n868(x)
+ end
+end
+
+def fun_l22_n732(x)
+ if (x < 1)
+ fun_l23_n629(x)
+ else
+ fun_l23_n997(x)
+ end
+end
+
+def fun_l22_n733(x)
+ if (x < 1)
+ fun_l23_n815(x)
+ else
+ fun_l23_n696(x)
+ end
+end
+
+def fun_l22_n734(x)
+ if (x < 1)
+ fun_l23_n636(x)
+ else
+ fun_l23_n858(x)
+ end
+end
+
+def fun_l22_n735(x)
+ if (x < 1)
+ fun_l23_n131(x)
+ else
+ fun_l23_n350(x)
+ end
+end
+
+def fun_l22_n736(x)
+ if (x < 1)
+ fun_l23_n509(x)
+ else
+ fun_l23_n197(x)
+ end
+end
+
+def fun_l22_n737(x)
+ if (x < 1)
+ fun_l23_n549(x)
+ else
+ fun_l23_n16(x)
+ end
+end
+
+def fun_l22_n738(x)
+ if (x < 1)
+ fun_l23_n797(x)
+ else
+ fun_l23_n829(x)
+ end
+end
+
+def fun_l22_n739(x)
+ if (x < 1)
+ fun_l23_n78(x)
+ else
+ fun_l23_n299(x)
+ end
+end
+
+def fun_l22_n740(x)
+ if (x < 1)
+ fun_l23_n165(x)
+ else
+ fun_l23_n822(x)
+ end
+end
+
+def fun_l22_n741(x)
+ if (x < 1)
+ fun_l23_n494(x)
+ else
+ fun_l23_n226(x)
+ end
+end
+
+def fun_l22_n742(x)
+ if (x < 1)
+ fun_l23_n930(x)
+ else
+ fun_l23_n301(x)
+ end
+end
+
+def fun_l22_n743(x)
+ if (x < 1)
+ fun_l23_n357(x)
+ else
+ fun_l23_n399(x)
+ end
+end
+
+def fun_l22_n744(x)
+ if (x < 1)
+ fun_l23_n865(x)
+ else
+ fun_l23_n499(x)
+ end
+end
+
+def fun_l22_n745(x)
+ if (x < 1)
+ fun_l23_n437(x)
+ else
+ fun_l23_n145(x)
+ end
+end
+
+def fun_l22_n746(x)
+ if (x < 1)
+ fun_l23_n883(x)
+ else
+ fun_l23_n269(x)
+ end
+end
+
+def fun_l22_n747(x)
+ if (x < 1)
+ fun_l23_n323(x)
+ else
+ fun_l23_n199(x)
+ end
+end
+
+def fun_l22_n748(x)
+ if (x < 1)
+ fun_l23_n843(x)
+ else
+ fun_l23_n179(x)
+ end
+end
+
+def fun_l22_n749(x)
+ if (x < 1)
+ fun_l23_n413(x)
+ else
+ fun_l23_n195(x)
+ end
+end
+
+def fun_l22_n750(x)
+ if (x < 1)
+ fun_l23_n50(x)
+ else
+ fun_l23_n219(x)
+ end
+end
+
+def fun_l22_n751(x)
+ if (x < 1)
+ fun_l23_n574(x)
+ else
+ fun_l23_n649(x)
+ end
+end
+
+def fun_l22_n752(x)
+ if (x < 1)
+ fun_l23_n495(x)
+ else
+ fun_l23_n664(x)
+ end
+end
+
+def fun_l22_n753(x)
+ if (x < 1)
+ fun_l23_n899(x)
+ else
+ fun_l23_n14(x)
+ end
+end
+
+def fun_l22_n754(x)
+ if (x < 1)
+ fun_l23_n230(x)
+ else
+ fun_l23_n933(x)
+ end
+end
+
+def fun_l22_n755(x)
+ if (x < 1)
+ fun_l23_n236(x)
+ else
+ fun_l23_n854(x)
+ end
+end
+
+def fun_l22_n756(x)
+ if (x < 1)
+ fun_l23_n786(x)
+ else
+ fun_l23_n599(x)
+ end
+end
+
+def fun_l22_n757(x)
+ if (x < 1)
+ fun_l23_n921(x)
+ else
+ fun_l23_n805(x)
+ end
+end
+
+def fun_l22_n758(x)
+ if (x < 1)
+ fun_l23_n990(x)
+ else
+ fun_l23_n724(x)
+ end
+end
+
+def fun_l22_n759(x)
+ if (x < 1)
+ fun_l23_n376(x)
+ else
+ fun_l23_n568(x)
+ end
+end
+
+def fun_l22_n760(x)
+ if (x < 1)
+ fun_l23_n676(x)
+ else
+ fun_l23_n995(x)
+ end
+end
+
+def fun_l22_n761(x)
+ if (x < 1)
+ fun_l23_n144(x)
+ else
+ fun_l23_n104(x)
+ end
+end
+
+def fun_l22_n762(x)
+ if (x < 1)
+ fun_l23_n463(x)
+ else
+ fun_l23_n736(x)
+ end
+end
+
+def fun_l22_n763(x)
+ if (x < 1)
+ fun_l23_n436(x)
+ else
+ fun_l23_n475(x)
+ end
+end
+
+def fun_l22_n764(x)
+ if (x < 1)
+ fun_l23_n607(x)
+ else
+ fun_l23_n737(x)
+ end
+end
+
+def fun_l22_n765(x)
+ if (x < 1)
+ fun_l23_n108(x)
+ else
+ fun_l23_n396(x)
+ end
+end
+
+def fun_l22_n766(x)
+ if (x < 1)
+ fun_l23_n35(x)
+ else
+ fun_l23_n422(x)
+ end
+end
+
+def fun_l22_n767(x)
+ if (x < 1)
+ fun_l23_n541(x)
+ else
+ fun_l23_n756(x)
+ end
+end
+
+def fun_l22_n768(x)
+ if (x < 1)
+ fun_l23_n558(x)
+ else
+ fun_l23_n858(x)
+ end
+end
+
+def fun_l22_n769(x)
+ if (x < 1)
+ fun_l23_n153(x)
+ else
+ fun_l23_n544(x)
+ end
+end
+
+def fun_l22_n770(x)
+ if (x < 1)
+ fun_l23_n201(x)
+ else
+ fun_l23_n905(x)
+ end
+end
+
+def fun_l22_n771(x)
+ if (x < 1)
+ fun_l23_n373(x)
+ else
+ fun_l23_n420(x)
+ end
+end
+
+def fun_l22_n772(x)
+ if (x < 1)
+ fun_l23_n635(x)
+ else
+ fun_l23_n464(x)
+ end
+end
+
+def fun_l22_n773(x)
+ if (x < 1)
+ fun_l23_n822(x)
+ else
+ fun_l23_n803(x)
+ end
+end
+
+def fun_l22_n774(x)
+ if (x < 1)
+ fun_l23_n118(x)
+ else
+ fun_l23_n127(x)
+ end
+end
+
+def fun_l22_n775(x)
+ if (x < 1)
+ fun_l23_n364(x)
+ else
+ fun_l23_n512(x)
+ end
+end
+
+def fun_l22_n776(x)
+ if (x < 1)
+ fun_l23_n186(x)
+ else
+ fun_l23_n275(x)
+ end
+end
+
+def fun_l22_n777(x)
+ if (x < 1)
+ fun_l23_n803(x)
+ else
+ fun_l23_n105(x)
+ end
+end
+
+def fun_l22_n778(x)
+ if (x < 1)
+ fun_l23_n535(x)
+ else
+ fun_l23_n569(x)
+ end
+end
+
+def fun_l22_n779(x)
+ if (x < 1)
+ fun_l23_n847(x)
+ else
+ fun_l23_n505(x)
+ end
+end
+
+def fun_l22_n780(x)
+ if (x < 1)
+ fun_l23_n323(x)
+ else
+ fun_l23_n552(x)
+ end
+end
+
+def fun_l22_n781(x)
+ if (x < 1)
+ fun_l23_n294(x)
+ else
+ fun_l23_n914(x)
+ end
+end
+
+def fun_l22_n782(x)
+ if (x < 1)
+ fun_l23_n887(x)
+ else
+ fun_l23_n214(x)
+ end
+end
+
+def fun_l22_n783(x)
+ if (x < 1)
+ fun_l23_n900(x)
+ else
+ fun_l23_n729(x)
+ end
+end
+
+def fun_l22_n784(x)
+ if (x < 1)
+ fun_l23_n458(x)
+ else
+ fun_l23_n233(x)
+ end
+end
+
+def fun_l22_n785(x)
+ if (x < 1)
+ fun_l23_n553(x)
+ else
+ fun_l23_n306(x)
+ end
+end
+
+def fun_l22_n786(x)
+ if (x < 1)
+ fun_l23_n853(x)
+ else
+ fun_l23_n946(x)
+ end
+end
+
+def fun_l22_n787(x)
+ if (x < 1)
+ fun_l23_n595(x)
+ else
+ fun_l23_n288(x)
+ end
+end
+
+def fun_l22_n788(x)
+ if (x < 1)
+ fun_l23_n785(x)
+ else
+ fun_l23_n752(x)
+ end
+end
+
+def fun_l22_n789(x)
+ if (x < 1)
+ fun_l23_n787(x)
+ else
+ fun_l23_n788(x)
+ end
+end
+
+def fun_l22_n790(x)
+ if (x < 1)
+ fun_l23_n461(x)
+ else
+ fun_l23_n251(x)
+ end
+end
+
+def fun_l22_n791(x)
+ if (x < 1)
+ fun_l23_n523(x)
+ else
+ fun_l23_n328(x)
+ end
+end
+
+def fun_l22_n792(x)
+ if (x < 1)
+ fun_l23_n200(x)
+ else
+ fun_l23_n689(x)
+ end
+end
+
+def fun_l22_n793(x)
+ if (x < 1)
+ fun_l23_n612(x)
+ else
+ fun_l23_n398(x)
+ end
+end
+
+def fun_l22_n794(x)
+ if (x < 1)
+ fun_l23_n937(x)
+ else
+ fun_l23_n965(x)
+ end
+end
+
+def fun_l22_n795(x)
+ if (x < 1)
+ fun_l23_n362(x)
+ else
+ fun_l23_n789(x)
+ end
+end
+
+def fun_l22_n796(x)
+ if (x < 1)
+ fun_l23_n145(x)
+ else
+ fun_l23_n36(x)
+ end
+end
+
+def fun_l22_n797(x)
+ if (x < 1)
+ fun_l23_n923(x)
+ else
+ fun_l23_n251(x)
+ end
+end
+
+def fun_l22_n798(x)
+ if (x < 1)
+ fun_l23_n15(x)
+ else
+ fun_l23_n563(x)
+ end
+end
+
+def fun_l22_n799(x)
+ if (x < 1)
+ fun_l23_n554(x)
+ else
+ fun_l23_n336(x)
+ end
+end
+
+def fun_l22_n800(x)
+ if (x < 1)
+ fun_l23_n939(x)
+ else
+ fun_l23_n993(x)
+ end
+end
+
+def fun_l22_n801(x)
+ if (x < 1)
+ fun_l23_n506(x)
+ else
+ fun_l23_n656(x)
+ end
+end
+
+def fun_l22_n802(x)
+ if (x < 1)
+ fun_l23_n591(x)
+ else
+ fun_l23_n582(x)
+ end
+end
+
+def fun_l22_n803(x)
+ if (x < 1)
+ fun_l23_n707(x)
+ else
+ fun_l23_n235(x)
+ end
+end
+
+def fun_l22_n804(x)
+ if (x < 1)
+ fun_l23_n474(x)
+ else
+ fun_l23_n253(x)
+ end
+end
+
+def fun_l22_n805(x)
+ if (x < 1)
+ fun_l23_n707(x)
+ else
+ fun_l23_n885(x)
+ end
+end
+
+def fun_l22_n806(x)
+ if (x < 1)
+ fun_l23_n155(x)
+ else
+ fun_l23_n210(x)
+ end
+end
+
+def fun_l22_n807(x)
+ if (x < 1)
+ fun_l23_n489(x)
+ else
+ fun_l23_n249(x)
+ end
+end
+
+def fun_l22_n808(x)
+ if (x < 1)
+ fun_l23_n840(x)
+ else
+ fun_l23_n748(x)
+ end
+end
+
+def fun_l22_n809(x)
+ if (x < 1)
+ fun_l23_n910(x)
+ else
+ fun_l23_n884(x)
+ end
+end
+
+def fun_l22_n810(x)
+ if (x < 1)
+ fun_l23_n653(x)
+ else
+ fun_l23_n321(x)
+ end
+end
+
+def fun_l22_n811(x)
+ if (x < 1)
+ fun_l23_n310(x)
+ else
+ fun_l23_n366(x)
+ end
+end
+
+def fun_l22_n812(x)
+ if (x < 1)
+ fun_l23_n441(x)
+ else
+ fun_l23_n795(x)
+ end
+end
+
+def fun_l22_n813(x)
+ if (x < 1)
+ fun_l23_n666(x)
+ else
+ fun_l23_n631(x)
+ end
+end
+
+def fun_l22_n814(x)
+ if (x < 1)
+ fun_l23_n680(x)
+ else
+ fun_l23_n88(x)
+ end
+end
+
+def fun_l22_n815(x)
+ if (x < 1)
+ fun_l23_n80(x)
+ else
+ fun_l23_n989(x)
+ end
+end
+
+def fun_l22_n816(x)
+ if (x < 1)
+ fun_l23_n65(x)
+ else
+ fun_l23_n46(x)
+ end
+end
+
+def fun_l22_n817(x)
+ if (x < 1)
+ fun_l23_n427(x)
+ else
+ fun_l23_n868(x)
+ end
+end
+
+def fun_l22_n818(x)
+ if (x < 1)
+ fun_l23_n900(x)
+ else
+ fun_l23_n213(x)
+ end
+end
+
+def fun_l22_n819(x)
+ if (x < 1)
+ fun_l23_n394(x)
+ else
+ fun_l23_n647(x)
+ end
+end
+
+def fun_l22_n820(x)
+ if (x < 1)
+ fun_l23_n981(x)
+ else
+ fun_l23_n530(x)
+ end
+end
+
+def fun_l22_n821(x)
+ if (x < 1)
+ fun_l23_n806(x)
+ else
+ fun_l23_n511(x)
+ end
+end
+
+def fun_l22_n822(x)
+ if (x < 1)
+ fun_l23_n141(x)
+ else
+ fun_l23_n91(x)
+ end
+end
+
+def fun_l22_n823(x)
+ if (x < 1)
+ fun_l23_n604(x)
+ else
+ fun_l23_n270(x)
+ end
+end
+
+def fun_l22_n824(x)
+ if (x < 1)
+ fun_l23_n347(x)
+ else
+ fun_l23_n937(x)
+ end
+end
+
+def fun_l22_n825(x)
+ if (x < 1)
+ fun_l23_n302(x)
+ else
+ fun_l23_n659(x)
+ end
+end
+
+def fun_l22_n826(x)
+ if (x < 1)
+ fun_l23_n386(x)
+ else
+ fun_l23_n174(x)
+ end
+end
+
+def fun_l22_n827(x)
+ if (x < 1)
+ fun_l23_n347(x)
+ else
+ fun_l23_n659(x)
+ end
+end
+
+def fun_l22_n828(x)
+ if (x < 1)
+ fun_l23_n647(x)
+ else
+ fun_l23_n648(x)
+ end
+end
+
+def fun_l22_n829(x)
+ if (x < 1)
+ fun_l23_n892(x)
+ else
+ fun_l23_n910(x)
+ end
+end
+
+def fun_l22_n830(x)
+ if (x < 1)
+ fun_l23_n274(x)
+ else
+ fun_l23_n739(x)
+ end
+end
+
+def fun_l22_n831(x)
+ if (x < 1)
+ fun_l23_n211(x)
+ else
+ fun_l23_n658(x)
+ end
+end
+
+def fun_l22_n832(x)
+ if (x < 1)
+ fun_l23_n584(x)
+ else
+ fun_l23_n163(x)
+ end
+end
+
+def fun_l22_n833(x)
+ if (x < 1)
+ fun_l23_n598(x)
+ else
+ fun_l23_n735(x)
+ end
+end
+
+def fun_l22_n834(x)
+ if (x < 1)
+ fun_l23_n934(x)
+ else
+ fun_l23_n579(x)
+ end
+end
+
+def fun_l22_n835(x)
+ if (x < 1)
+ fun_l23_n483(x)
+ else
+ fun_l23_n632(x)
+ end
+end
+
+def fun_l22_n836(x)
+ if (x < 1)
+ fun_l23_n329(x)
+ else
+ fun_l23_n799(x)
+ end
+end
+
+def fun_l22_n837(x)
+ if (x < 1)
+ fun_l23_n699(x)
+ else
+ fun_l23_n846(x)
+ end
+end
+
+def fun_l22_n838(x)
+ if (x < 1)
+ fun_l23_n40(x)
+ else
+ fun_l23_n715(x)
+ end
+end
+
+def fun_l22_n839(x)
+ if (x < 1)
+ fun_l23_n917(x)
+ else
+ fun_l23_n595(x)
+ end
+end
+
+def fun_l22_n840(x)
+ if (x < 1)
+ fun_l23_n171(x)
+ else
+ fun_l23_n204(x)
+ end
+end
+
+def fun_l22_n841(x)
+ if (x < 1)
+ fun_l23_n652(x)
+ else
+ fun_l23_n342(x)
+ end
+end
+
+def fun_l22_n842(x)
+ if (x < 1)
+ fun_l23_n853(x)
+ else
+ fun_l23_n981(x)
+ end
+end
+
+def fun_l22_n843(x)
+ if (x < 1)
+ fun_l23_n673(x)
+ else
+ fun_l23_n2(x)
+ end
+end
+
+def fun_l22_n844(x)
+ if (x < 1)
+ fun_l23_n799(x)
+ else
+ fun_l23_n654(x)
+ end
+end
+
+def fun_l22_n845(x)
+ if (x < 1)
+ fun_l23_n989(x)
+ else
+ fun_l23_n563(x)
+ end
+end
+
+def fun_l22_n846(x)
+ if (x < 1)
+ fun_l23_n415(x)
+ else
+ fun_l23_n245(x)
+ end
+end
+
+def fun_l22_n847(x)
+ if (x < 1)
+ fun_l23_n836(x)
+ else
+ fun_l23_n347(x)
+ end
+end
+
+def fun_l22_n848(x)
+ if (x < 1)
+ fun_l23_n493(x)
+ else
+ fun_l23_n712(x)
+ end
+end
+
+def fun_l22_n849(x)
+ if (x < 1)
+ fun_l23_n780(x)
+ else
+ fun_l23_n43(x)
+ end
+end
+
+def fun_l22_n850(x)
+ if (x < 1)
+ fun_l23_n511(x)
+ else
+ fun_l23_n356(x)
+ end
+end
+
+def fun_l22_n851(x)
+ if (x < 1)
+ fun_l23_n229(x)
+ else
+ fun_l23_n355(x)
+ end
+end
+
+def fun_l22_n852(x)
+ if (x < 1)
+ fun_l23_n50(x)
+ else
+ fun_l23_n908(x)
+ end
+end
+
+def fun_l22_n853(x)
+ if (x < 1)
+ fun_l23_n156(x)
+ else
+ fun_l23_n422(x)
+ end
+end
+
+def fun_l22_n854(x)
+ if (x < 1)
+ fun_l23_n448(x)
+ else
+ fun_l23_n763(x)
+ end
+end
+
+def fun_l22_n855(x)
+ if (x < 1)
+ fun_l23_n662(x)
+ else
+ fun_l23_n887(x)
+ end
+end
+
+def fun_l22_n856(x)
+ if (x < 1)
+ fun_l23_n511(x)
+ else
+ fun_l23_n292(x)
+ end
+end
+
+def fun_l22_n857(x)
+ if (x < 1)
+ fun_l23_n313(x)
+ else
+ fun_l23_n207(x)
+ end
+end
+
+def fun_l22_n858(x)
+ if (x < 1)
+ fun_l23_n544(x)
+ else
+ fun_l23_n488(x)
+ end
+end
+
+def fun_l22_n859(x)
+ if (x < 1)
+ fun_l23_n34(x)
+ else
+ fun_l23_n133(x)
+ end
+end
+
+def fun_l22_n860(x)
+ if (x < 1)
+ fun_l23_n739(x)
+ else
+ fun_l23_n127(x)
+ end
+end
+
+def fun_l22_n861(x)
+ if (x < 1)
+ fun_l23_n727(x)
+ else
+ fun_l23_n339(x)
+ end
+end
+
+def fun_l22_n862(x)
+ if (x < 1)
+ fun_l23_n78(x)
+ else
+ fun_l23_n101(x)
+ end
+end
+
+def fun_l22_n863(x)
+ if (x < 1)
+ fun_l23_n310(x)
+ else
+ fun_l23_n884(x)
+ end
+end
+
+def fun_l22_n864(x)
+ if (x < 1)
+ fun_l23_n97(x)
+ else
+ fun_l23_n716(x)
+ end
+end
+
+def fun_l22_n865(x)
+ if (x < 1)
+ fun_l23_n63(x)
+ else
+ fun_l23_n654(x)
+ end
+end
+
+def fun_l22_n866(x)
+ if (x < 1)
+ fun_l23_n336(x)
+ else
+ fun_l23_n334(x)
+ end
+end
+
+def fun_l22_n867(x)
+ if (x < 1)
+ fun_l23_n317(x)
+ else
+ fun_l23_n197(x)
+ end
+end
+
+def fun_l22_n868(x)
+ if (x < 1)
+ fun_l23_n98(x)
+ else
+ fun_l23_n466(x)
+ end
+end
+
+def fun_l22_n869(x)
+ if (x < 1)
+ fun_l23_n157(x)
+ else
+ fun_l23_n43(x)
+ end
+end
+
+def fun_l22_n870(x)
+ if (x < 1)
+ fun_l23_n347(x)
+ else
+ fun_l23_n961(x)
+ end
+end
+
+def fun_l22_n871(x)
+ if (x < 1)
+ fun_l23_n460(x)
+ else
+ fun_l23_n820(x)
+ end
+end
+
+def fun_l22_n872(x)
+ if (x < 1)
+ fun_l23_n216(x)
+ else
+ fun_l23_n419(x)
+ end
+end
+
+def fun_l22_n873(x)
+ if (x < 1)
+ fun_l23_n879(x)
+ else
+ fun_l23_n343(x)
+ end
+end
+
+def fun_l22_n874(x)
+ if (x < 1)
+ fun_l23_n507(x)
+ else
+ fun_l23_n572(x)
+ end
+end
+
+def fun_l22_n875(x)
+ if (x < 1)
+ fun_l23_n959(x)
+ else
+ fun_l23_n750(x)
+ end
+end
+
+def fun_l22_n876(x)
+ if (x < 1)
+ fun_l23_n718(x)
+ else
+ fun_l23_n406(x)
+ end
+end
+
+def fun_l22_n877(x)
+ if (x < 1)
+ fun_l23_n733(x)
+ else
+ fun_l23_n486(x)
+ end
+end
+
+def fun_l22_n878(x)
+ if (x < 1)
+ fun_l23_n95(x)
+ else
+ fun_l23_n842(x)
+ end
+end
+
+def fun_l22_n879(x)
+ if (x < 1)
+ fun_l23_n626(x)
+ else
+ fun_l23_n428(x)
+ end
+end
+
+def fun_l22_n880(x)
+ if (x < 1)
+ fun_l23_n194(x)
+ else
+ fun_l23_n441(x)
+ end
+end
+
+def fun_l22_n881(x)
+ if (x < 1)
+ fun_l23_n10(x)
+ else
+ fun_l23_n727(x)
+ end
+end
+
+def fun_l22_n882(x)
+ if (x < 1)
+ fun_l23_n173(x)
+ else
+ fun_l23_n301(x)
+ end
+end
+
+def fun_l22_n883(x)
+ if (x < 1)
+ fun_l23_n338(x)
+ else
+ fun_l23_n420(x)
+ end
+end
+
+def fun_l22_n884(x)
+ if (x < 1)
+ fun_l23_n615(x)
+ else
+ fun_l23_n923(x)
+ end
+end
+
+def fun_l22_n885(x)
+ if (x < 1)
+ fun_l23_n547(x)
+ else
+ fun_l23_n979(x)
+ end
+end
+
+def fun_l22_n886(x)
+ if (x < 1)
+ fun_l23_n28(x)
+ else
+ fun_l23_n213(x)
+ end
+end
+
+def fun_l22_n887(x)
+ if (x < 1)
+ fun_l23_n919(x)
+ else
+ fun_l23_n228(x)
+ end
+end
+
+def fun_l22_n888(x)
+ if (x < 1)
+ fun_l23_n264(x)
+ else
+ fun_l23_n156(x)
+ end
+end
+
+def fun_l22_n889(x)
+ if (x < 1)
+ fun_l23_n137(x)
+ else
+ fun_l23_n582(x)
+ end
+end
+
+def fun_l22_n890(x)
+ if (x < 1)
+ fun_l23_n468(x)
+ else
+ fun_l23_n409(x)
+ end
+end
+
+def fun_l22_n891(x)
+ if (x < 1)
+ fun_l23_n823(x)
+ else
+ fun_l23_n999(x)
+ end
+end
+
+def fun_l22_n892(x)
+ if (x < 1)
+ fun_l23_n248(x)
+ else
+ fun_l23_n821(x)
+ end
+end
+
+def fun_l22_n893(x)
+ if (x < 1)
+ fun_l23_n117(x)
+ else
+ fun_l23_n127(x)
+ end
+end
+
+def fun_l22_n894(x)
+ if (x < 1)
+ fun_l23_n622(x)
+ else
+ fun_l23_n737(x)
+ end
+end
+
+def fun_l22_n895(x)
+ if (x < 1)
+ fun_l23_n66(x)
+ else
+ fun_l23_n261(x)
+ end
+end
+
+def fun_l22_n896(x)
+ if (x < 1)
+ fun_l23_n245(x)
+ else
+ fun_l23_n18(x)
+ end
+end
+
+def fun_l22_n897(x)
+ if (x < 1)
+ fun_l23_n269(x)
+ else
+ fun_l23_n666(x)
+ end
+end
+
+def fun_l22_n898(x)
+ if (x < 1)
+ fun_l23_n807(x)
+ else
+ fun_l23_n449(x)
+ end
+end
+
+def fun_l22_n899(x)
+ if (x < 1)
+ fun_l23_n801(x)
+ else
+ fun_l23_n34(x)
+ end
+end
+
+def fun_l22_n900(x)
+ if (x < 1)
+ fun_l23_n17(x)
+ else
+ fun_l23_n117(x)
+ end
+end
+
+def fun_l22_n901(x)
+ if (x < 1)
+ fun_l23_n677(x)
+ else
+ fun_l23_n872(x)
+ end
+end
+
+def fun_l22_n902(x)
+ if (x < 1)
+ fun_l23_n221(x)
+ else
+ fun_l23_n685(x)
+ end
+end
+
+def fun_l22_n903(x)
+ if (x < 1)
+ fun_l23_n224(x)
+ else
+ fun_l23_n15(x)
+ end
+end
+
+def fun_l22_n904(x)
+ if (x < 1)
+ fun_l23_n353(x)
+ else
+ fun_l23_n367(x)
+ end
+end
+
+def fun_l22_n905(x)
+ if (x < 1)
+ fun_l23_n466(x)
+ else
+ fun_l23_n466(x)
+ end
+end
+
+def fun_l22_n906(x)
+ if (x < 1)
+ fun_l23_n674(x)
+ else
+ fun_l23_n521(x)
+ end
+end
+
+def fun_l22_n907(x)
+ if (x < 1)
+ fun_l23_n978(x)
+ else
+ fun_l23_n79(x)
+ end
+end
+
+def fun_l22_n908(x)
+ if (x < 1)
+ fun_l23_n976(x)
+ else
+ fun_l23_n513(x)
+ end
+end
+
+def fun_l22_n909(x)
+ if (x < 1)
+ fun_l23_n478(x)
+ else
+ fun_l23_n524(x)
+ end
+end
+
+def fun_l22_n910(x)
+ if (x < 1)
+ fun_l23_n744(x)
+ else
+ fun_l23_n451(x)
+ end
+end
+
+def fun_l22_n911(x)
+ if (x < 1)
+ fun_l23_n524(x)
+ else
+ fun_l23_n409(x)
+ end
+end
+
+def fun_l22_n912(x)
+ if (x < 1)
+ fun_l23_n651(x)
+ else
+ fun_l23_n424(x)
+ end
+end
+
+def fun_l22_n913(x)
+ if (x < 1)
+ fun_l23_n740(x)
+ else
+ fun_l23_n841(x)
+ end
+end
+
+def fun_l22_n914(x)
+ if (x < 1)
+ fun_l23_n388(x)
+ else
+ fun_l23_n790(x)
+ end
+end
+
+def fun_l22_n915(x)
+ if (x < 1)
+ fun_l23_n625(x)
+ else
+ fun_l23_n276(x)
+ end
+end
+
+def fun_l22_n916(x)
+ if (x < 1)
+ fun_l23_n322(x)
+ else
+ fun_l23_n598(x)
+ end
+end
+
+def fun_l22_n917(x)
+ if (x < 1)
+ fun_l23_n51(x)
+ else
+ fun_l23_n286(x)
+ end
+end
+
+def fun_l22_n918(x)
+ if (x < 1)
+ fun_l23_n265(x)
+ else
+ fun_l23_n553(x)
+ end
+end
+
+def fun_l22_n919(x)
+ if (x < 1)
+ fun_l23_n525(x)
+ else
+ fun_l23_n825(x)
+ end
+end
+
+def fun_l22_n920(x)
+ if (x < 1)
+ fun_l23_n59(x)
+ else
+ fun_l23_n643(x)
+ end
+end
+
+def fun_l22_n921(x)
+ if (x < 1)
+ fun_l23_n135(x)
+ else
+ fun_l23_n811(x)
+ end
+end
+
+def fun_l22_n922(x)
+ if (x < 1)
+ fun_l23_n587(x)
+ else
+ fun_l23_n564(x)
+ end
+end
+
+def fun_l22_n923(x)
+ if (x < 1)
+ fun_l23_n235(x)
+ else
+ fun_l23_n337(x)
+ end
+end
+
+def fun_l22_n924(x)
+ if (x < 1)
+ fun_l23_n99(x)
+ else
+ fun_l23_n805(x)
+ end
+end
+
+def fun_l22_n925(x)
+ if (x < 1)
+ fun_l23_n360(x)
+ else
+ fun_l23_n67(x)
+ end
+end
+
+def fun_l22_n926(x)
+ if (x < 1)
+ fun_l23_n438(x)
+ else
+ fun_l23_n948(x)
+ end
+end
+
+def fun_l22_n927(x)
+ if (x < 1)
+ fun_l23_n545(x)
+ else
+ fun_l23_n287(x)
+ end
+end
+
+def fun_l22_n928(x)
+ if (x < 1)
+ fun_l23_n632(x)
+ else
+ fun_l23_n769(x)
+ end
+end
+
+def fun_l22_n929(x)
+ if (x < 1)
+ fun_l23_n17(x)
+ else
+ fun_l23_n240(x)
+ end
+end
+
+def fun_l22_n930(x)
+ if (x < 1)
+ fun_l23_n948(x)
+ else
+ fun_l23_n690(x)
+ end
+end
+
+def fun_l22_n931(x)
+ if (x < 1)
+ fun_l23_n12(x)
+ else
+ fun_l23_n640(x)
+ end
+end
+
+def fun_l22_n932(x)
+ if (x < 1)
+ fun_l23_n157(x)
+ else
+ fun_l23_n594(x)
+ end
+end
+
+def fun_l22_n933(x)
+ if (x < 1)
+ fun_l23_n96(x)
+ else
+ fun_l23_n771(x)
+ end
+end
+
+def fun_l22_n934(x)
+ if (x < 1)
+ fun_l23_n237(x)
+ else
+ fun_l23_n910(x)
+ end
+end
+
+def fun_l22_n935(x)
+ if (x < 1)
+ fun_l23_n553(x)
+ else
+ fun_l23_n300(x)
+ end
+end
+
+def fun_l22_n936(x)
+ if (x < 1)
+ fun_l23_n224(x)
+ else
+ fun_l23_n566(x)
+ end
+end
+
+def fun_l22_n937(x)
+ if (x < 1)
+ fun_l23_n314(x)
+ else
+ fun_l23_n328(x)
+ end
+end
+
+def fun_l22_n938(x)
+ if (x < 1)
+ fun_l23_n775(x)
+ else
+ fun_l23_n72(x)
+ end
+end
+
+def fun_l22_n939(x)
+ if (x < 1)
+ fun_l23_n273(x)
+ else
+ fun_l23_n43(x)
+ end
+end
+
+def fun_l22_n940(x)
+ if (x < 1)
+ fun_l23_n215(x)
+ else
+ fun_l23_n646(x)
+ end
+end
+
+def fun_l22_n941(x)
+ if (x < 1)
+ fun_l23_n925(x)
+ else
+ fun_l23_n97(x)
+ end
+end
+
+def fun_l22_n942(x)
+ if (x < 1)
+ fun_l23_n391(x)
+ else
+ fun_l23_n972(x)
+ end
+end
+
+def fun_l22_n943(x)
+ if (x < 1)
+ fun_l23_n276(x)
+ else
+ fun_l23_n725(x)
+ end
+end
+
+def fun_l22_n944(x)
+ if (x < 1)
+ fun_l23_n928(x)
+ else
+ fun_l23_n94(x)
+ end
+end
+
+def fun_l22_n945(x)
+ if (x < 1)
+ fun_l23_n176(x)
+ else
+ fun_l23_n598(x)
+ end
+end
+
+def fun_l22_n946(x)
+ if (x < 1)
+ fun_l23_n530(x)
+ else
+ fun_l23_n37(x)
+ end
+end
+
+def fun_l22_n947(x)
+ if (x < 1)
+ fun_l23_n412(x)
+ else
+ fun_l23_n718(x)
+ end
+end
+
+def fun_l22_n948(x)
+ if (x < 1)
+ fun_l23_n905(x)
+ else
+ fun_l23_n723(x)
+ end
+end
+
+def fun_l22_n949(x)
+ if (x < 1)
+ fun_l23_n451(x)
+ else
+ fun_l23_n232(x)
+ end
+end
+
+def fun_l22_n950(x)
+ if (x < 1)
+ fun_l23_n312(x)
+ else
+ fun_l23_n556(x)
+ end
+end
+
+def fun_l22_n951(x)
+ if (x < 1)
+ fun_l23_n906(x)
+ else
+ fun_l23_n33(x)
+ end
+end
+
+def fun_l22_n952(x)
+ if (x < 1)
+ fun_l23_n964(x)
+ else
+ fun_l23_n46(x)
+ end
+end
+
+def fun_l22_n953(x)
+ if (x < 1)
+ fun_l23_n813(x)
+ else
+ fun_l23_n494(x)
+ end
+end
+
+def fun_l22_n954(x)
+ if (x < 1)
+ fun_l23_n725(x)
+ else
+ fun_l23_n705(x)
+ end
+end
+
+def fun_l22_n955(x)
+ if (x < 1)
+ fun_l23_n525(x)
+ else
+ fun_l23_n370(x)
+ end
+end
+
+def fun_l22_n956(x)
+ if (x < 1)
+ fun_l23_n266(x)
+ else
+ fun_l23_n872(x)
+ end
+end
+
+def fun_l22_n957(x)
+ if (x < 1)
+ fun_l23_n492(x)
+ else
+ fun_l23_n730(x)
+ end
+end
+
+def fun_l22_n958(x)
+ if (x < 1)
+ fun_l23_n950(x)
+ else
+ fun_l23_n557(x)
+ end
+end
+
+def fun_l22_n959(x)
+ if (x < 1)
+ fun_l23_n156(x)
+ else
+ fun_l23_n379(x)
+ end
+end
+
+def fun_l22_n960(x)
+ if (x < 1)
+ fun_l23_n270(x)
+ else
+ fun_l23_n486(x)
+ end
+end
+
+def fun_l22_n961(x)
+ if (x < 1)
+ fun_l23_n789(x)
+ else
+ fun_l23_n316(x)
+ end
+end
+
+def fun_l22_n962(x)
+ if (x < 1)
+ fun_l23_n425(x)
+ else
+ fun_l23_n470(x)
+ end
+end
+
+def fun_l22_n963(x)
+ if (x < 1)
+ fun_l23_n598(x)
+ else
+ fun_l23_n304(x)
+ end
+end
+
+def fun_l22_n964(x)
+ if (x < 1)
+ fun_l23_n249(x)
+ else
+ fun_l23_n517(x)
+ end
+end
+
+def fun_l22_n965(x)
+ if (x < 1)
+ fun_l23_n775(x)
+ else
+ fun_l23_n892(x)
+ end
+end
+
+def fun_l22_n966(x)
+ if (x < 1)
+ fun_l23_n771(x)
+ else
+ fun_l23_n879(x)
+ end
+end
+
+def fun_l22_n967(x)
+ if (x < 1)
+ fun_l23_n596(x)
+ else
+ fun_l23_n22(x)
+ end
+end
+
+def fun_l22_n968(x)
+ if (x < 1)
+ fun_l23_n722(x)
+ else
+ fun_l23_n203(x)
+ end
+end
+
+def fun_l22_n969(x)
+ if (x < 1)
+ fun_l23_n912(x)
+ else
+ fun_l23_n216(x)
+ end
+end
+
+def fun_l22_n970(x)
+ if (x < 1)
+ fun_l23_n230(x)
+ else
+ fun_l23_n295(x)
+ end
+end
+
+def fun_l22_n971(x)
+ if (x < 1)
+ fun_l23_n255(x)
+ else
+ fun_l23_n407(x)
+ end
+end
+
+def fun_l22_n972(x)
+ if (x < 1)
+ fun_l23_n673(x)
+ else
+ fun_l23_n940(x)
+ end
+end
+
+def fun_l22_n973(x)
+ if (x < 1)
+ fun_l23_n793(x)
+ else
+ fun_l23_n776(x)
+ end
+end
+
+def fun_l22_n974(x)
+ if (x < 1)
+ fun_l23_n812(x)
+ else
+ fun_l23_n653(x)
+ end
+end
+
+def fun_l22_n975(x)
+ if (x < 1)
+ fun_l23_n866(x)
+ else
+ fun_l23_n25(x)
+ end
+end
+
+def fun_l22_n976(x)
+ if (x < 1)
+ fun_l23_n143(x)
+ else
+ fun_l23_n236(x)
+ end
+end
+
+def fun_l22_n977(x)
+ if (x < 1)
+ fun_l23_n274(x)
+ else
+ fun_l23_n414(x)
+ end
+end
+
+def fun_l22_n978(x)
+ if (x < 1)
+ fun_l23_n281(x)
+ else
+ fun_l23_n946(x)
+ end
+end
+
+def fun_l22_n979(x)
+ if (x < 1)
+ fun_l23_n255(x)
+ else
+ fun_l23_n585(x)
+ end
+end
+
+def fun_l22_n980(x)
+ if (x < 1)
+ fun_l23_n269(x)
+ else
+ fun_l23_n182(x)
+ end
+end
+
+def fun_l22_n981(x)
+ if (x < 1)
+ fun_l23_n340(x)
+ else
+ fun_l23_n262(x)
+ end
+end
+
+def fun_l22_n982(x)
+ if (x < 1)
+ fun_l23_n713(x)
+ else
+ fun_l23_n247(x)
+ end
+end
+
+def fun_l22_n983(x)
+ if (x < 1)
+ fun_l23_n827(x)
+ else
+ fun_l23_n821(x)
+ end
+end
+
+def fun_l22_n984(x)
+ if (x < 1)
+ fun_l23_n628(x)
+ else
+ fun_l23_n243(x)
+ end
+end
+
+def fun_l22_n985(x)
+ if (x < 1)
+ fun_l23_n479(x)
+ else
+ fun_l23_n440(x)
+ end
+end
+
+def fun_l22_n986(x)
+ if (x < 1)
+ fun_l23_n451(x)
+ else
+ fun_l23_n299(x)
+ end
+end
+
+def fun_l22_n987(x)
+ if (x < 1)
+ fun_l23_n528(x)
+ else
+ fun_l23_n336(x)
+ end
+end
+
+def fun_l22_n988(x)
+ if (x < 1)
+ fun_l23_n825(x)
+ else
+ fun_l23_n767(x)
+ end
+end
+
+def fun_l22_n989(x)
+ if (x < 1)
+ fun_l23_n427(x)
+ else
+ fun_l23_n996(x)
+ end
+end
+
+def fun_l22_n990(x)
+ if (x < 1)
+ fun_l23_n175(x)
+ else
+ fun_l23_n888(x)
+ end
+end
+
+def fun_l22_n991(x)
+ if (x < 1)
+ fun_l23_n351(x)
+ else
+ fun_l23_n982(x)
+ end
+end
+
+def fun_l22_n992(x)
+ if (x < 1)
+ fun_l23_n235(x)
+ else
+ fun_l23_n91(x)
+ end
+end
+
+def fun_l22_n993(x)
+ if (x < 1)
+ fun_l23_n966(x)
+ else
+ fun_l23_n520(x)
+ end
+end
+
+def fun_l22_n994(x)
+ if (x < 1)
+ fun_l23_n854(x)
+ else
+ fun_l23_n937(x)
+ end
+end
+
+def fun_l22_n995(x)
+ if (x < 1)
+ fun_l23_n922(x)
+ else
+ fun_l23_n176(x)
+ end
+end
+
+def fun_l22_n996(x)
+ if (x < 1)
+ fun_l23_n925(x)
+ else
+ fun_l23_n271(x)
+ end
+end
+
+def fun_l22_n997(x)
+ if (x < 1)
+ fun_l23_n513(x)
+ else
+ fun_l23_n195(x)
+ end
+end
+
+def fun_l22_n998(x)
+ if (x < 1)
+ fun_l23_n135(x)
+ else
+ fun_l23_n834(x)
+ end
+end
+
+def fun_l22_n999(x)
+ if (x < 1)
+ fun_l23_n664(x)
+ else
+ fun_l23_n861(x)
+ end
+end
+
+def fun_l23_n0(x)
+ if (x < 1)
+ fun_l24_n327(x)
+ else
+ fun_l24_n159(x)
+ end
+end
+
+def fun_l23_n1(x)
+ if (x < 1)
+ fun_l24_n433(x)
+ else
+ fun_l24_n862(x)
+ end
+end
+
+def fun_l23_n2(x)
+ if (x < 1)
+ fun_l24_n56(x)
+ else
+ fun_l24_n651(x)
+ end
+end
+
+def fun_l23_n3(x)
+ if (x < 1)
+ fun_l24_n267(x)
+ else
+ fun_l24_n566(x)
+ end
+end
+
+def fun_l23_n4(x)
+ if (x < 1)
+ fun_l24_n880(x)
+ else
+ fun_l24_n886(x)
+ end
+end
+
+def fun_l23_n5(x)
+ if (x < 1)
+ fun_l24_n66(x)
+ else
+ fun_l24_n894(x)
+ end
+end
+
+def fun_l23_n6(x)
+ if (x < 1)
+ fun_l24_n965(x)
+ else
+ fun_l24_n453(x)
+ end
+end
+
+def fun_l23_n7(x)
+ if (x < 1)
+ fun_l24_n250(x)
+ else
+ fun_l24_n42(x)
+ end
+end
+
+def fun_l23_n8(x)
+ if (x < 1)
+ fun_l24_n376(x)
+ else
+ fun_l24_n736(x)
+ end
+end
+
+def fun_l23_n9(x)
+ if (x < 1)
+ fun_l24_n434(x)
+ else
+ fun_l24_n334(x)
+ end
+end
+
+def fun_l23_n10(x)
+ if (x < 1)
+ fun_l24_n944(x)
+ else
+ fun_l24_n70(x)
+ end
+end
+
+def fun_l23_n11(x)
+ if (x < 1)
+ fun_l24_n38(x)
+ else
+ fun_l24_n532(x)
+ end
+end
+
+def fun_l23_n12(x)
+ if (x < 1)
+ fun_l24_n603(x)
+ else
+ fun_l24_n682(x)
+ end
+end
+
+def fun_l23_n13(x)
+ if (x < 1)
+ fun_l24_n716(x)
+ else
+ fun_l24_n754(x)
+ end
+end
+
+def fun_l23_n14(x)
+ if (x < 1)
+ fun_l24_n578(x)
+ else
+ fun_l24_n727(x)
+ end
+end
+
+def fun_l23_n15(x)
+ if (x < 1)
+ fun_l24_n166(x)
+ else
+ fun_l24_n224(x)
+ end
+end
+
+def fun_l23_n16(x)
+ if (x < 1)
+ fun_l24_n755(x)
+ else
+ fun_l24_n548(x)
+ end
+end
+
+def fun_l23_n17(x)
+ if (x < 1)
+ fun_l24_n355(x)
+ else
+ fun_l24_n625(x)
+ end
+end
+
+def fun_l23_n18(x)
+ if (x < 1)
+ fun_l24_n400(x)
+ else
+ fun_l24_n834(x)
+ end
+end
+
+def fun_l23_n19(x)
+ if (x < 1)
+ fun_l24_n188(x)
+ else
+ fun_l24_n305(x)
+ end
+end
+
+def fun_l23_n20(x)
+ if (x < 1)
+ fun_l24_n392(x)
+ else
+ fun_l24_n466(x)
+ end
+end
+
+def fun_l23_n21(x)
+ if (x < 1)
+ fun_l24_n937(x)
+ else
+ fun_l24_n603(x)
+ end
+end
+
+def fun_l23_n22(x)
+ if (x < 1)
+ fun_l24_n767(x)
+ else
+ fun_l24_n750(x)
+ end
+end
+
+def fun_l23_n23(x)
+ if (x < 1)
+ fun_l24_n888(x)
+ else
+ fun_l24_n472(x)
+ end
+end
+
+def fun_l23_n24(x)
+ if (x < 1)
+ fun_l24_n937(x)
+ else
+ fun_l24_n192(x)
+ end
+end
+
+def fun_l23_n25(x)
+ if (x < 1)
+ fun_l24_n704(x)
+ else
+ fun_l24_n839(x)
+ end
+end
+
+def fun_l23_n26(x)
+ if (x < 1)
+ fun_l24_n758(x)
+ else
+ fun_l24_n579(x)
+ end
+end
+
+def fun_l23_n27(x)
+ if (x < 1)
+ fun_l24_n161(x)
+ else
+ fun_l24_n268(x)
+ end
+end
+
+def fun_l23_n28(x)
+ if (x < 1)
+ fun_l24_n628(x)
+ else
+ fun_l24_n413(x)
+ end
+end
+
+def fun_l23_n29(x)
+ if (x < 1)
+ fun_l24_n954(x)
+ else
+ fun_l24_n962(x)
+ end
+end
+
+def fun_l23_n30(x)
+ if (x < 1)
+ fun_l24_n723(x)
+ else
+ fun_l24_n220(x)
+ end
+end
+
+def fun_l23_n31(x)
+ if (x < 1)
+ fun_l24_n841(x)
+ else
+ fun_l24_n331(x)
+ end
+end
+
+def fun_l23_n32(x)
+ if (x < 1)
+ fun_l24_n42(x)
+ else
+ fun_l24_n331(x)
+ end
+end
+
+def fun_l23_n33(x)
+ if (x < 1)
+ fun_l24_n873(x)
+ else
+ fun_l24_n58(x)
+ end
+end
+
+def fun_l23_n34(x)
+ if (x < 1)
+ fun_l24_n586(x)
+ else
+ fun_l24_n981(x)
+ end
+end
+
+def fun_l23_n35(x)
+ if (x < 1)
+ fun_l24_n455(x)
+ else
+ fun_l24_n279(x)
+ end
+end
+
+def fun_l23_n36(x)
+ if (x < 1)
+ fun_l24_n401(x)
+ else
+ fun_l24_n633(x)
+ end
+end
+
+def fun_l23_n37(x)
+ if (x < 1)
+ fun_l24_n432(x)
+ else
+ fun_l24_n389(x)
+ end
+end
+
+def fun_l23_n38(x)
+ if (x < 1)
+ fun_l24_n46(x)
+ else
+ fun_l24_n426(x)
+ end
+end
+
+def fun_l23_n39(x)
+ if (x < 1)
+ fun_l24_n679(x)
+ else
+ fun_l24_n222(x)
+ end
+end
+
+def fun_l23_n40(x)
+ if (x < 1)
+ fun_l24_n129(x)
+ else
+ fun_l24_n2(x)
+ end
+end
+
+def fun_l23_n41(x)
+ if (x < 1)
+ fun_l24_n228(x)
+ else
+ fun_l24_n386(x)
+ end
+end
+
+def fun_l23_n42(x)
+ if (x < 1)
+ fun_l24_n740(x)
+ else
+ fun_l24_n605(x)
+ end
+end
+
+def fun_l23_n43(x)
+ if (x < 1)
+ fun_l24_n686(x)
+ else
+ fun_l24_n755(x)
+ end
+end
+
+def fun_l23_n44(x)
+ if (x < 1)
+ fun_l24_n569(x)
+ else
+ fun_l24_n553(x)
+ end
+end
+
+def fun_l23_n45(x)
+ if (x < 1)
+ fun_l24_n908(x)
+ else
+ fun_l24_n388(x)
+ end
+end
+
+def fun_l23_n46(x)
+ if (x < 1)
+ fun_l24_n106(x)
+ else
+ fun_l24_n335(x)
+ end
+end
+
+def fun_l23_n47(x)
+ if (x < 1)
+ fun_l24_n876(x)
+ else
+ fun_l24_n813(x)
+ end
+end
+
+def fun_l23_n48(x)
+ if (x < 1)
+ fun_l24_n337(x)
+ else
+ fun_l24_n967(x)
+ end
+end
+
+def fun_l23_n49(x)
+ if (x < 1)
+ fun_l24_n309(x)
+ else
+ fun_l24_n988(x)
+ end
+end
+
+def fun_l23_n50(x)
+ if (x < 1)
+ fun_l24_n325(x)
+ else
+ fun_l24_n703(x)
+ end
+end
+
+def fun_l23_n51(x)
+ if (x < 1)
+ fun_l24_n755(x)
+ else
+ fun_l24_n146(x)
+ end
+end
+
+def fun_l23_n52(x)
+ if (x < 1)
+ fun_l24_n597(x)
+ else
+ fun_l24_n764(x)
+ end
+end
+
+def fun_l23_n53(x)
+ if (x < 1)
+ fun_l24_n259(x)
+ else
+ fun_l24_n9(x)
+ end
+end
+
+def fun_l23_n54(x)
+ if (x < 1)
+ fun_l24_n73(x)
+ else
+ fun_l24_n700(x)
+ end
+end
+
+def fun_l23_n55(x)
+ if (x < 1)
+ fun_l24_n369(x)
+ else
+ fun_l24_n632(x)
+ end
+end
+
+def fun_l23_n56(x)
+ if (x < 1)
+ fun_l24_n475(x)
+ else
+ fun_l24_n553(x)
+ end
+end
+
+def fun_l23_n57(x)
+ if (x < 1)
+ fun_l24_n473(x)
+ else
+ fun_l24_n84(x)
+ end
+end
+
+def fun_l23_n58(x)
+ if (x < 1)
+ fun_l24_n837(x)
+ else
+ fun_l24_n164(x)
+ end
+end
+
+def fun_l23_n59(x)
+ if (x < 1)
+ fun_l24_n129(x)
+ else
+ fun_l24_n993(x)
+ end
+end
+
+def fun_l23_n60(x)
+ if (x < 1)
+ fun_l24_n201(x)
+ else
+ fun_l24_n644(x)
+ end
+end
+
+def fun_l23_n61(x)
+ if (x < 1)
+ fun_l24_n825(x)
+ else
+ fun_l24_n513(x)
+ end
+end
+
+def fun_l23_n62(x)
+ if (x < 1)
+ fun_l24_n162(x)
+ else
+ fun_l24_n575(x)
+ end
+end
+
+def fun_l23_n63(x)
+ if (x < 1)
+ fun_l24_n959(x)
+ else
+ fun_l24_n514(x)
+ end
+end
+
+def fun_l23_n64(x)
+ if (x < 1)
+ fun_l24_n133(x)
+ else
+ fun_l24_n731(x)
+ end
+end
+
+def fun_l23_n65(x)
+ if (x < 1)
+ fun_l24_n370(x)
+ else
+ fun_l24_n903(x)
+ end
+end
+
+def fun_l23_n66(x)
+ if (x < 1)
+ fun_l24_n787(x)
+ else
+ fun_l24_n11(x)
+ end
+end
+
+def fun_l23_n67(x)
+ if (x < 1)
+ fun_l24_n307(x)
+ else
+ fun_l24_n7(x)
+ end
+end
+
+def fun_l23_n68(x)
+ if (x < 1)
+ fun_l24_n157(x)
+ else
+ fun_l24_n747(x)
+ end
+end
+
+def fun_l23_n69(x)
+ if (x < 1)
+ fun_l24_n435(x)
+ else
+ fun_l24_n763(x)
+ end
+end
+
+def fun_l23_n70(x)
+ if (x < 1)
+ fun_l24_n623(x)
+ else
+ fun_l24_n279(x)
+ end
+end
+
+def fun_l23_n71(x)
+ if (x < 1)
+ fun_l24_n456(x)
+ else
+ fun_l24_n465(x)
+ end
+end
+
+def fun_l23_n72(x)
+ if (x < 1)
+ fun_l24_n411(x)
+ else
+ fun_l24_n397(x)
+ end
+end
+
+def fun_l23_n73(x)
+ if (x < 1)
+ fun_l24_n964(x)
+ else
+ fun_l24_n144(x)
+ end
+end
+
+def fun_l23_n74(x)
+ if (x < 1)
+ fun_l24_n170(x)
+ else
+ fun_l24_n406(x)
+ end
+end
+
+def fun_l23_n75(x)
+ if (x < 1)
+ fun_l24_n838(x)
+ else
+ fun_l24_n295(x)
+ end
+end
+
+def fun_l23_n76(x)
+ if (x < 1)
+ fun_l24_n89(x)
+ else
+ fun_l24_n803(x)
+ end
+end
+
+def fun_l23_n77(x)
+ if (x < 1)
+ fun_l24_n580(x)
+ else
+ fun_l24_n931(x)
+ end
+end
+
+def fun_l23_n78(x)
+ if (x < 1)
+ fun_l24_n504(x)
+ else
+ fun_l24_n150(x)
+ end
+end
+
+def fun_l23_n79(x)
+ if (x < 1)
+ fun_l24_n363(x)
+ else
+ fun_l24_n717(x)
+ end
+end
+
+def fun_l23_n80(x)
+ if (x < 1)
+ fun_l24_n765(x)
+ else
+ fun_l24_n917(x)
+ end
+end
+
+def fun_l23_n81(x)
+ if (x < 1)
+ fun_l24_n673(x)
+ else
+ fun_l24_n549(x)
+ end
+end
+
+def fun_l23_n82(x)
+ if (x < 1)
+ fun_l24_n986(x)
+ else
+ fun_l24_n177(x)
+ end
+end
+
+def fun_l23_n83(x)
+ if (x < 1)
+ fun_l24_n821(x)
+ else
+ fun_l24_n302(x)
+ end
+end
+
+def fun_l23_n84(x)
+ if (x < 1)
+ fun_l24_n530(x)
+ else
+ fun_l24_n744(x)
+ end
+end
+
+def fun_l23_n85(x)
+ if (x < 1)
+ fun_l24_n456(x)
+ else
+ fun_l24_n964(x)
+ end
+end
+
+def fun_l23_n86(x)
+ if (x < 1)
+ fun_l24_n901(x)
+ else
+ fun_l24_n214(x)
+ end
+end
+
+def fun_l23_n87(x)
+ if (x < 1)
+ fun_l24_n308(x)
+ else
+ fun_l24_n329(x)
+ end
+end
+
+def fun_l23_n88(x)
+ if (x < 1)
+ fun_l24_n749(x)
+ else
+ fun_l24_n822(x)
+ end
+end
+
+def fun_l23_n89(x)
+ if (x < 1)
+ fun_l24_n283(x)
+ else
+ fun_l24_n865(x)
+ end
+end
+
+def fun_l23_n90(x)
+ if (x < 1)
+ fun_l24_n834(x)
+ else
+ fun_l24_n422(x)
+ end
+end
+
+def fun_l23_n91(x)
+ if (x < 1)
+ fun_l24_n920(x)
+ else
+ fun_l24_n799(x)
+ end
+end
+
+def fun_l23_n92(x)
+ if (x < 1)
+ fun_l24_n272(x)
+ else
+ fun_l24_n846(x)
+ end
+end
+
+def fun_l23_n93(x)
+ if (x < 1)
+ fun_l24_n447(x)
+ else
+ fun_l24_n809(x)
+ end
+end
+
+def fun_l23_n94(x)
+ if (x < 1)
+ fun_l24_n826(x)
+ else
+ fun_l24_n521(x)
+ end
+end
+
+def fun_l23_n95(x)
+ if (x < 1)
+ fun_l24_n934(x)
+ else
+ fun_l24_n774(x)
+ end
+end
+
+def fun_l23_n96(x)
+ if (x < 1)
+ fun_l24_n440(x)
+ else
+ fun_l24_n40(x)
+ end
+end
+
+def fun_l23_n97(x)
+ if (x < 1)
+ fun_l24_n980(x)
+ else
+ fun_l24_n801(x)
+ end
+end
+
+def fun_l23_n98(x)
+ if (x < 1)
+ fun_l24_n344(x)
+ else
+ fun_l24_n239(x)
+ end
+end
+
+def fun_l23_n99(x)
+ if (x < 1)
+ fun_l24_n918(x)
+ else
+ fun_l24_n241(x)
+ end
+end
+
+def fun_l23_n100(x)
+ if (x < 1)
+ fun_l24_n902(x)
+ else
+ fun_l24_n12(x)
+ end
+end
+
+def fun_l23_n101(x)
+ if (x < 1)
+ fun_l24_n533(x)
+ else
+ fun_l24_n510(x)
+ end
+end
+
+def fun_l23_n102(x)
+ if (x < 1)
+ fun_l24_n337(x)
+ else
+ fun_l24_n144(x)
+ end
+end
+
+def fun_l23_n103(x)
+ if (x < 1)
+ fun_l24_n835(x)
+ else
+ fun_l24_n268(x)
+ end
+end
+
+def fun_l23_n104(x)
+ if (x < 1)
+ fun_l24_n352(x)
+ else
+ fun_l24_n772(x)
+ end
+end
+
+def fun_l23_n105(x)
+ if (x < 1)
+ fun_l24_n135(x)
+ else
+ fun_l24_n97(x)
+ end
+end
+
+def fun_l23_n106(x)
+ if (x < 1)
+ fun_l24_n70(x)
+ else
+ fun_l24_n528(x)
+ end
+end
+
+def fun_l23_n107(x)
+ if (x < 1)
+ fun_l24_n945(x)
+ else
+ fun_l24_n85(x)
+ end
+end
+
+def fun_l23_n108(x)
+ if (x < 1)
+ fun_l24_n233(x)
+ else
+ fun_l24_n637(x)
+ end
+end
+
+def fun_l23_n109(x)
+ if (x < 1)
+ fun_l24_n715(x)
+ else
+ fun_l24_n111(x)
+ end
+end
+
+def fun_l23_n110(x)
+ if (x < 1)
+ fun_l24_n673(x)
+ else
+ fun_l24_n423(x)
+ end
+end
+
+def fun_l23_n111(x)
+ if (x < 1)
+ fun_l24_n408(x)
+ else
+ fun_l24_n5(x)
+ end
+end
+
+def fun_l23_n112(x)
+ if (x < 1)
+ fun_l24_n89(x)
+ else
+ fun_l24_n669(x)
+ end
+end
+
+def fun_l23_n113(x)
+ if (x < 1)
+ fun_l24_n733(x)
+ else
+ fun_l24_n76(x)
+ end
+end
+
+def fun_l23_n114(x)
+ if (x < 1)
+ fun_l24_n767(x)
+ else
+ fun_l24_n465(x)
+ end
+end
+
+def fun_l23_n115(x)
+ if (x < 1)
+ fun_l24_n428(x)
+ else
+ fun_l24_n948(x)
+ end
+end
+
+def fun_l23_n116(x)
+ if (x < 1)
+ fun_l24_n412(x)
+ else
+ fun_l24_n355(x)
+ end
+end
+
+def fun_l23_n117(x)
+ if (x < 1)
+ fun_l24_n550(x)
+ else
+ fun_l24_n616(x)
+ end
+end
+
+def fun_l23_n118(x)
+ if (x < 1)
+ fun_l24_n858(x)
+ else
+ fun_l24_n74(x)
+ end
+end
+
+def fun_l23_n119(x)
+ if (x < 1)
+ fun_l24_n709(x)
+ else
+ fun_l24_n939(x)
+ end
+end
+
+def fun_l23_n120(x)
+ if (x < 1)
+ fun_l24_n712(x)
+ else
+ fun_l24_n74(x)
+ end
+end
+
+def fun_l23_n121(x)
+ if (x < 1)
+ fun_l24_n34(x)
+ else
+ fun_l24_n532(x)
+ end
+end
+
+def fun_l23_n122(x)
+ if (x < 1)
+ fun_l24_n998(x)
+ else
+ fun_l24_n736(x)
+ end
+end
+
+def fun_l23_n123(x)
+ if (x < 1)
+ fun_l24_n33(x)
+ else
+ fun_l24_n561(x)
+ end
+end
+
+def fun_l23_n124(x)
+ if (x < 1)
+ fun_l24_n750(x)
+ else
+ fun_l24_n634(x)
+ end
+end
+
+def fun_l23_n125(x)
+ if (x < 1)
+ fun_l24_n935(x)
+ else
+ fun_l24_n29(x)
+ end
+end
+
+def fun_l23_n126(x)
+ if (x < 1)
+ fun_l24_n249(x)
+ else
+ fun_l24_n571(x)
+ end
+end
+
+def fun_l23_n127(x)
+ if (x < 1)
+ fun_l24_n827(x)
+ else
+ fun_l24_n892(x)
+ end
+end
+
+def fun_l23_n128(x)
+ if (x < 1)
+ fun_l24_n903(x)
+ else
+ fun_l24_n171(x)
+ end
+end
+
+def fun_l23_n129(x)
+ if (x < 1)
+ fun_l24_n725(x)
+ else
+ fun_l24_n358(x)
+ end
+end
+
+def fun_l23_n130(x)
+ if (x < 1)
+ fun_l24_n616(x)
+ else
+ fun_l24_n795(x)
+ end
+end
+
+def fun_l23_n131(x)
+ if (x < 1)
+ fun_l24_n942(x)
+ else
+ fun_l24_n574(x)
+ end
+end
+
+def fun_l23_n132(x)
+ if (x < 1)
+ fun_l24_n290(x)
+ else
+ fun_l24_n869(x)
+ end
+end
+
+def fun_l23_n133(x)
+ if (x < 1)
+ fun_l24_n73(x)
+ else
+ fun_l24_n542(x)
+ end
+end
+
+def fun_l23_n134(x)
+ if (x < 1)
+ fun_l24_n730(x)
+ else
+ fun_l24_n857(x)
+ end
+end
+
+def fun_l23_n135(x)
+ if (x < 1)
+ fun_l24_n754(x)
+ else
+ fun_l24_n579(x)
+ end
+end
+
+def fun_l23_n136(x)
+ if (x < 1)
+ fun_l24_n503(x)
+ else
+ fun_l24_n574(x)
+ end
+end
+
+def fun_l23_n137(x)
+ if (x < 1)
+ fun_l24_n682(x)
+ else
+ fun_l24_n630(x)
+ end
+end
+
+def fun_l23_n138(x)
+ if (x < 1)
+ fun_l24_n918(x)
+ else
+ fun_l24_n440(x)
+ end
+end
+
+def fun_l23_n139(x)
+ if (x < 1)
+ fun_l24_n938(x)
+ else
+ fun_l24_n524(x)
+ end
+end
+
+def fun_l23_n140(x)
+ if (x < 1)
+ fun_l24_n966(x)
+ else
+ fun_l24_n921(x)
+ end
+end
+
+def fun_l23_n141(x)
+ if (x < 1)
+ fun_l24_n87(x)
+ else
+ fun_l24_n548(x)
+ end
+end
+
+def fun_l23_n142(x)
+ if (x < 1)
+ fun_l24_n828(x)
+ else
+ fun_l24_n708(x)
+ end
+end
+
+def fun_l23_n143(x)
+ if (x < 1)
+ fun_l24_n655(x)
+ else
+ fun_l24_n322(x)
+ end
+end
+
+def fun_l23_n144(x)
+ if (x < 1)
+ fun_l24_n382(x)
+ else
+ fun_l24_n484(x)
+ end
+end
+
+def fun_l23_n145(x)
+ if (x < 1)
+ fun_l24_n830(x)
+ else
+ fun_l24_n755(x)
+ end
+end
+
+def fun_l23_n146(x)
+ if (x < 1)
+ fun_l24_n432(x)
+ else
+ fun_l24_n487(x)
+ end
+end
+
+def fun_l23_n147(x)
+ if (x < 1)
+ fun_l24_n954(x)
+ else
+ fun_l24_n453(x)
+ end
+end
+
+def fun_l23_n148(x)
+ if (x < 1)
+ fun_l24_n562(x)
+ else
+ fun_l24_n872(x)
+ end
+end
+
+def fun_l23_n149(x)
+ if (x < 1)
+ fun_l24_n929(x)
+ else
+ fun_l24_n212(x)
+ end
+end
+
+def fun_l23_n150(x)
+ if (x < 1)
+ fun_l24_n143(x)
+ else
+ fun_l24_n344(x)
+ end
+end
+
+def fun_l23_n151(x)
+ if (x < 1)
+ fun_l24_n475(x)
+ else
+ fun_l24_n379(x)
+ end
+end
+
+def fun_l23_n152(x)
+ if (x < 1)
+ fun_l24_n160(x)
+ else
+ fun_l24_n774(x)
+ end
+end
+
+def fun_l23_n153(x)
+ if (x < 1)
+ fun_l24_n689(x)
+ else
+ fun_l24_n19(x)
+ end
+end
+
+def fun_l23_n154(x)
+ if (x < 1)
+ fun_l24_n98(x)
+ else
+ fun_l24_n572(x)
+ end
+end
+
+def fun_l23_n155(x)
+ if (x < 1)
+ fun_l24_n104(x)
+ else
+ fun_l24_n797(x)
+ end
+end
+
+def fun_l23_n156(x)
+ if (x < 1)
+ fun_l24_n892(x)
+ else
+ fun_l24_n874(x)
+ end
+end
+
+def fun_l23_n157(x)
+ if (x < 1)
+ fun_l24_n900(x)
+ else
+ fun_l24_n458(x)
+ end
+end
+
+def fun_l23_n158(x)
+ if (x < 1)
+ fun_l24_n50(x)
+ else
+ fun_l24_n912(x)
+ end
+end
+
+def fun_l23_n159(x)
+ if (x < 1)
+ fun_l24_n303(x)
+ else
+ fun_l24_n373(x)
+ end
+end
+
+def fun_l23_n160(x)
+ if (x < 1)
+ fun_l24_n137(x)
+ else
+ fun_l24_n102(x)
+ end
+end
+
+def fun_l23_n161(x)
+ if (x < 1)
+ fun_l24_n263(x)
+ else
+ fun_l24_n818(x)
+ end
+end
+
+def fun_l23_n162(x)
+ if (x < 1)
+ fun_l24_n618(x)
+ else
+ fun_l24_n895(x)
+ end
+end
+
+def fun_l23_n163(x)
+ if (x < 1)
+ fun_l24_n845(x)
+ else
+ fun_l24_n26(x)
+ end
+end
+
+def fun_l23_n164(x)
+ if (x < 1)
+ fun_l24_n941(x)
+ else
+ fun_l24_n242(x)
+ end
+end
+
+def fun_l23_n165(x)
+ if (x < 1)
+ fun_l24_n145(x)
+ else
+ fun_l24_n492(x)
+ end
+end
+
+def fun_l23_n166(x)
+ if (x < 1)
+ fun_l24_n261(x)
+ else
+ fun_l24_n235(x)
+ end
+end
+
+def fun_l23_n167(x)
+ if (x < 1)
+ fun_l24_n941(x)
+ else
+ fun_l24_n618(x)
+ end
+end
+
+def fun_l23_n168(x)
+ if (x < 1)
+ fun_l24_n709(x)
+ else
+ fun_l24_n908(x)
+ end
+end
+
+def fun_l23_n169(x)
+ if (x < 1)
+ fun_l24_n746(x)
+ else
+ fun_l24_n116(x)
+ end
+end
+
+def fun_l23_n170(x)
+ if (x < 1)
+ fun_l24_n911(x)
+ else
+ fun_l24_n599(x)
+ end
+end
+
+def fun_l23_n171(x)
+ if (x < 1)
+ fun_l24_n526(x)
+ else
+ fun_l24_n275(x)
+ end
+end
+
+def fun_l23_n172(x)
+ if (x < 1)
+ fun_l24_n919(x)
+ else
+ fun_l24_n525(x)
+ end
+end
+
+def fun_l23_n173(x)
+ if (x < 1)
+ fun_l24_n945(x)
+ else
+ fun_l24_n894(x)
+ end
+end
+
+def fun_l23_n174(x)
+ if (x < 1)
+ fun_l24_n349(x)
+ else
+ fun_l24_n434(x)
+ end
+end
+
+def fun_l23_n175(x)
+ if (x < 1)
+ fun_l24_n498(x)
+ else
+ fun_l24_n679(x)
+ end
+end
+
+def fun_l23_n176(x)
+ if (x < 1)
+ fun_l24_n867(x)
+ else
+ fun_l24_n177(x)
+ end
+end
+
+def fun_l23_n177(x)
+ if (x < 1)
+ fun_l24_n680(x)
+ else
+ fun_l24_n601(x)
+ end
+end
+
+def fun_l23_n178(x)
+ if (x < 1)
+ fun_l24_n838(x)
+ else
+ fun_l24_n5(x)
+ end
+end
+
+def fun_l23_n179(x)
+ if (x < 1)
+ fun_l24_n418(x)
+ else
+ fun_l24_n780(x)
+ end
+end
+
+def fun_l23_n180(x)
+ if (x < 1)
+ fun_l24_n88(x)
+ else
+ fun_l24_n333(x)
+ end
+end
+
+def fun_l23_n181(x)
+ if (x < 1)
+ fun_l24_n657(x)
+ else
+ fun_l24_n787(x)
+ end
+end
+
+def fun_l23_n182(x)
+ if (x < 1)
+ fun_l24_n767(x)
+ else
+ fun_l24_n903(x)
+ end
+end
+
+def fun_l23_n183(x)
+ if (x < 1)
+ fun_l24_n878(x)
+ else
+ fun_l24_n426(x)
+ end
+end
+
+def fun_l23_n184(x)
+ if (x < 1)
+ fun_l24_n649(x)
+ else
+ fun_l24_n221(x)
+ end
+end
+
+def fun_l23_n185(x)
+ if (x < 1)
+ fun_l24_n315(x)
+ else
+ fun_l24_n955(x)
+ end
+end
+
+def fun_l23_n186(x)
+ if (x < 1)
+ fun_l24_n599(x)
+ else
+ fun_l24_n201(x)
+ end
+end
+
+def fun_l23_n187(x)
+ if (x < 1)
+ fun_l24_n851(x)
+ else
+ fun_l24_n294(x)
+ end
+end
+
+def fun_l23_n188(x)
+ if (x < 1)
+ fun_l24_n585(x)
+ else
+ fun_l24_n139(x)
+ end
+end
+
+def fun_l23_n189(x)
+ if (x < 1)
+ fun_l24_n893(x)
+ else
+ fun_l24_n159(x)
+ end
+end
+
+def fun_l23_n190(x)
+ if (x < 1)
+ fun_l24_n70(x)
+ else
+ fun_l24_n50(x)
+ end
+end
+
+def fun_l23_n191(x)
+ if (x < 1)
+ fun_l24_n111(x)
+ else
+ fun_l24_n967(x)
+ end
+end
+
+def fun_l23_n192(x)
+ if (x < 1)
+ fun_l24_n979(x)
+ else
+ fun_l24_n91(x)
+ end
+end
+
+def fun_l23_n193(x)
+ if (x < 1)
+ fun_l24_n651(x)
+ else
+ fun_l24_n321(x)
+ end
+end
+
+def fun_l23_n194(x)
+ if (x < 1)
+ fun_l24_n236(x)
+ else
+ fun_l24_n251(x)
+ end
+end
+
+def fun_l23_n195(x)
+ if (x < 1)
+ fun_l24_n947(x)
+ else
+ fun_l24_n116(x)
+ end
+end
+
+def fun_l23_n196(x)
+ if (x < 1)
+ fun_l24_n336(x)
+ else
+ fun_l24_n637(x)
+ end
+end
+
+def fun_l23_n197(x)
+ if (x < 1)
+ fun_l24_n192(x)
+ else
+ fun_l24_n824(x)
+ end
+end
+
+def fun_l23_n198(x)
+ if (x < 1)
+ fun_l24_n747(x)
+ else
+ fun_l24_n610(x)
+ end
+end
+
+def fun_l23_n199(x)
+ if (x < 1)
+ fun_l24_n735(x)
+ else
+ fun_l24_n347(x)
+ end
+end
+
+def fun_l23_n200(x)
+ if (x < 1)
+ fun_l24_n543(x)
+ else
+ fun_l24_n463(x)
+ end
+end
+
+def fun_l23_n201(x)
+ if (x < 1)
+ fun_l24_n933(x)
+ else
+ fun_l24_n185(x)
+ end
+end
+
+def fun_l23_n202(x)
+ if (x < 1)
+ fun_l24_n319(x)
+ else
+ fun_l24_n739(x)
+ end
+end
+
+def fun_l23_n203(x)
+ if (x < 1)
+ fun_l24_n994(x)
+ else
+ fun_l24_n248(x)
+ end
+end
+
+def fun_l23_n204(x)
+ if (x < 1)
+ fun_l24_n980(x)
+ else
+ fun_l24_n248(x)
+ end
+end
+
+def fun_l23_n205(x)
+ if (x < 1)
+ fun_l24_n427(x)
+ else
+ fun_l24_n670(x)
+ end
+end
+
+def fun_l23_n206(x)
+ if (x < 1)
+ fun_l24_n562(x)
+ else
+ fun_l24_n752(x)
+ end
+end
+
+def fun_l23_n207(x)
+ if (x < 1)
+ fun_l24_n424(x)
+ else
+ fun_l24_n310(x)
+ end
+end
+
+def fun_l23_n208(x)
+ if (x < 1)
+ fun_l24_n761(x)
+ else
+ fun_l24_n562(x)
+ end
+end
+
+def fun_l23_n209(x)
+ if (x < 1)
+ fun_l24_n264(x)
+ else
+ fun_l24_n20(x)
+ end
+end
+
+def fun_l23_n210(x)
+ if (x < 1)
+ fun_l24_n886(x)
+ else
+ fun_l24_n505(x)
+ end
+end
+
+def fun_l23_n211(x)
+ if (x < 1)
+ fun_l24_n715(x)
+ else
+ fun_l24_n641(x)
+ end
+end
+
+def fun_l23_n212(x)
+ if (x < 1)
+ fun_l24_n132(x)
+ else
+ fun_l24_n875(x)
+ end
+end
+
+def fun_l23_n213(x)
+ if (x < 1)
+ fun_l24_n121(x)
+ else
+ fun_l24_n38(x)
+ end
+end
+
+def fun_l23_n214(x)
+ if (x < 1)
+ fun_l24_n672(x)
+ else
+ fun_l24_n497(x)
+ end
+end
+
+def fun_l23_n215(x)
+ if (x < 1)
+ fun_l24_n36(x)
+ else
+ fun_l24_n696(x)
+ end
+end
+
+def fun_l23_n216(x)
+ if (x < 1)
+ fun_l24_n559(x)
+ else
+ fun_l24_n772(x)
+ end
+end
+
+def fun_l23_n217(x)
+ if (x < 1)
+ fun_l24_n63(x)
+ else
+ fun_l24_n990(x)
+ end
+end
+
+def fun_l23_n218(x)
+ if (x < 1)
+ fun_l24_n482(x)
+ else
+ fun_l24_n811(x)
+ end
+end
+
+def fun_l23_n219(x)
+ if (x < 1)
+ fun_l24_n572(x)
+ else
+ fun_l24_n651(x)
+ end
+end
+
+def fun_l23_n220(x)
+ if (x < 1)
+ fun_l24_n588(x)
+ else
+ fun_l24_n87(x)
+ end
+end
+
+def fun_l23_n221(x)
+ if (x < 1)
+ fun_l24_n462(x)
+ else
+ fun_l24_n909(x)
+ end
+end
+
+def fun_l23_n222(x)
+ if (x < 1)
+ fun_l24_n729(x)
+ else
+ fun_l24_n364(x)
+ end
+end
+
+def fun_l23_n223(x)
+ if (x < 1)
+ fun_l24_n259(x)
+ else
+ fun_l24_n661(x)
+ end
+end
+
+def fun_l23_n224(x)
+ if (x < 1)
+ fun_l24_n504(x)
+ else
+ fun_l24_n531(x)
+ end
+end
+
+def fun_l23_n225(x)
+ if (x < 1)
+ fun_l24_n114(x)
+ else
+ fun_l24_n292(x)
+ end
+end
+
+def fun_l23_n226(x)
+ if (x < 1)
+ fun_l24_n207(x)
+ else
+ fun_l24_n206(x)
+ end
+end
+
+def fun_l23_n227(x)
+ if (x < 1)
+ fun_l24_n153(x)
+ else
+ fun_l24_n572(x)
+ end
+end
+
+def fun_l23_n228(x)
+ if (x < 1)
+ fun_l24_n738(x)
+ else
+ fun_l24_n767(x)
+ end
+end
+
+def fun_l23_n229(x)
+ if (x < 1)
+ fun_l24_n374(x)
+ else
+ fun_l24_n336(x)
+ end
+end
+
+def fun_l23_n230(x)
+ if (x < 1)
+ fun_l24_n727(x)
+ else
+ fun_l24_n842(x)
+ end
+end
+
+def fun_l23_n231(x)
+ if (x < 1)
+ fun_l24_n506(x)
+ else
+ fun_l24_n8(x)
+ end
+end
+
+def fun_l23_n232(x)
+ if (x < 1)
+ fun_l24_n101(x)
+ else
+ fun_l24_n502(x)
+ end
+end
+
+def fun_l23_n233(x)
+ if (x < 1)
+ fun_l24_n469(x)
+ else
+ fun_l24_n274(x)
+ end
+end
+
+def fun_l23_n234(x)
+ if (x < 1)
+ fun_l24_n67(x)
+ else
+ fun_l24_n66(x)
+ end
+end
+
+def fun_l23_n235(x)
+ if (x < 1)
+ fun_l24_n874(x)
+ else
+ fun_l24_n104(x)
+ end
+end
+
+def fun_l23_n236(x)
+ if (x < 1)
+ fun_l24_n154(x)
+ else
+ fun_l24_n723(x)
+ end
+end
+
+def fun_l23_n237(x)
+ if (x < 1)
+ fun_l24_n300(x)
+ else
+ fun_l24_n0(x)
+ end
+end
+
+def fun_l23_n238(x)
+ if (x < 1)
+ fun_l24_n767(x)
+ else
+ fun_l24_n134(x)
+ end
+end
+
+def fun_l23_n239(x)
+ if (x < 1)
+ fun_l24_n647(x)
+ else
+ fun_l24_n890(x)
+ end
+end
+
+def fun_l23_n240(x)
+ if (x < 1)
+ fun_l24_n258(x)
+ else
+ fun_l24_n302(x)
+ end
+end
+
+def fun_l23_n241(x)
+ if (x < 1)
+ fun_l24_n104(x)
+ else
+ fun_l24_n335(x)
+ end
+end
+
+def fun_l23_n242(x)
+ if (x < 1)
+ fun_l24_n500(x)
+ else
+ fun_l24_n383(x)
+ end
+end
+
+def fun_l23_n243(x)
+ if (x < 1)
+ fun_l24_n63(x)
+ else
+ fun_l24_n421(x)
+ end
+end
+
+def fun_l23_n244(x)
+ if (x < 1)
+ fun_l24_n105(x)
+ else
+ fun_l24_n451(x)
+ end
+end
+
+def fun_l23_n245(x)
+ if (x < 1)
+ fun_l24_n729(x)
+ else
+ fun_l24_n333(x)
+ end
+end
+
+def fun_l23_n246(x)
+ if (x < 1)
+ fun_l24_n966(x)
+ else
+ fun_l24_n556(x)
+ end
+end
+
+def fun_l23_n247(x)
+ if (x < 1)
+ fun_l24_n118(x)
+ else
+ fun_l24_n565(x)
+ end
+end
+
+def fun_l23_n248(x)
+ if (x < 1)
+ fun_l24_n61(x)
+ else
+ fun_l24_n816(x)
+ end
+end
+
+def fun_l23_n249(x)
+ if (x < 1)
+ fun_l24_n769(x)
+ else
+ fun_l24_n183(x)
+ end
+end
+
+def fun_l23_n250(x)
+ if (x < 1)
+ fun_l24_n688(x)
+ else
+ fun_l24_n60(x)
+ end
+end
+
+def fun_l23_n251(x)
+ if (x < 1)
+ fun_l24_n859(x)
+ else
+ fun_l24_n434(x)
+ end
+end
+
+def fun_l23_n252(x)
+ if (x < 1)
+ fun_l24_n650(x)
+ else
+ fun_l24_n448(x)
+ end
+end
+
+def fun_l23_n253(x)
+ if (x < 1)
+ fun_l24_n519(x)
+ else
+ fun_l24_n963(x)
+ end
+end
+
+def fun_l23_n254(x)
+ if (x < 1)
+ fun_l24_n176(x)
+ else
+ fun_l24_n908(x)
+ end
+end
+
+def fun_l23_n255(x)
+ if (x < 1)
+ fun_l24_n146(x)
+ else
+ fun_l24_n751(x)
+ end
+end
+
+def fun_l23_n256(x)
+ if (x < 1)
+ fun_l24_n742(x)
+ else
+ fun_l24_n928(x)
+ end
+end
+
+def fun_l23_n257(x)
+ if (x < 1)
+ fun_l24_n22(x)
+ else
+ fun_l24_n48(x)
+ end
+end
+
+def fun_l23_n258(x)
+ if (x < 1)
+ fun_l24_n158(x)
+ else
+ fun_l24_n299(x)
+ end
+end
+
+def fun_l23_n259(x)
+ if (x < 1)
+ fun_l24_n247(x)
+ else
+ fun_l24_n419(x)
+ end
+end
+
+def fun_l23_n260(x)
+ if (x < 1)
+ fun_l24_n161(x)
+ else
+ fun_l24_n387(x)
+ end
+end
+
+def fun_l23_n261(x)
+ if (x < 1)
+ fun_l24_n627(x)
+ else
+ fun_l24_n321(x)
+ end
+end
+
+def fun_l23_n262(x)
+ if (x < 1)
+ fun_l24_n946(x)
+ else
+ fun_l24_n617(x)
+ end
+end
+
+def fun_l23_n263(x)
+ if (x < 1)
+ fun_l24_n853(x)
+ else
+ fun_l24_n208(x)
+ end
+end
+
+def fun_l23_n264(x)
+ if (x < 1)
+ fun_l24_n213(x)
+ else
+ fun_l24_n27(x)
+ end
+end
+
+def fun_l23_n265(x)
+ if (x < 1)
+ fun_l24_n819(x)
+ else
+ fun_l24_n438(x)
+ end
+end
+
+def fun_l23_n266(x)
+ if (x < 1)
+ fun_l24_n351(x)
+ else
+ fun_l24_n739(x)
+ end
+end
+
+def fun_l23_n267(x)
+ if (x < 1)
+ fun_l24_n333(x)
+ else
+ fun_l24_n179(x)
+ end
+end
+
+def fun_l23_n268(x)
+ if (x < 1)
+ fun_l24_n528(x)
+ else
+ fun_l24_n397(x)
+ end
+end
+
+def fun_l23_n269(x)
+ if (x < 1)
+ fun_l24_n655(x)
+ else
+ fun_l24_n994(x)
+ end
+end
+
+def fun_l23_n270(x)
+ if (x < 1)
+ fun_l24_n257(x)
+ else
+ fun_l24_n346(x)
+ end
+end
+
+def fun_l23_n271(x)
+ if (x < 1)
+ fun_l24_n183(x)
+ else
+ fun_l24_n908(x)
+ end
+end
+
+def fun_l23_n272(x)
+ if (x < 1)
+ fun_l24_n742(x)
+ else
+ fun_l24_n483(x)
+ end
+end
+
+def fun_l23_n273(x)
+ if (x < 1)
+ fun_l24_n803(x)
+ else
+ fun_l24_n318(x)
+ end
+end
+
+def fun_l23_n274(x)
+ if (x < 1)
+ fun_l24_n228(x)
+ else
+ fun_l24_n540(x)
+ end
+end
+
+def fun_l23_n275(x)
+ if (x < 1)
+ fun_l24_n999(x)
+ else
+ fun_l24_n55(x)
+ end
+end
+
+def fun_l23_n276(x)
+ if (x < 1)
+ fun_l24_n129(x)
+ else
+ fun_l24_n235(x)
+ end
+end
+
+def fun_l23_n277(x)
+ if (x < 1)
+ fun_l24_n320(x)
+ else
+ fun_l24_n211(x)
+ end
+end
+
+def fun_l23_n278(x)
+ if (x < 1)
+ fun_l24_n757(x)
+ else
+ fun_l24_n440(x)
+ end
+end
+
+def fun_l23_n279(x)
+ if (x < 1)
+ fun_l24_n784(x)
+ else
+ fun_l24_n117(x)
+ end
+end
+
+def fun_l23_n280(x)
+ if (x < 1)
+ fun_l24_n280(x)
+ else
+ fun_l24_n560(x)
+ end
+end
+
+def fun_l23_n281(x)
+ if (x < 1)
+ fun_l24_n981(x)
+ else
+ fun_l24_n939(x)
+ end
+end
+
+def fun_l23_n282(x)
+ if (x < 1)
+ fun_l24_n500(x)
+ else
+ fun_l24_n90(x)
+ end
+end
+
+def fun_l23_n283(x)
+ if (x < 1)
+ fun_l24_n958(x)
+ else
+ fun_l24_n415(x)
+ end
+end
+
+def fun_l23_n284(x)
+ if (x < 1)
+ fun_l24_n237(x)
+ else
+ fun_l24_n556(x)
+ end
+end
+
+def fun_l23_n285(x)
+ if (x < 1)
+ fun_l24_n87(x)
+ else
+ fun_l24_n630(x)
+ end
+end
+
+def fun_l23_n286(x)
+ if (x < 1)
+ fun_l24_n121(x)
+ else
+ fun_l24_n974(x)
+ end
+end
+
+def fun_l23_n287(x)
+ if (x < 1)
+ fun_l24_n491(x)
+ else
+ fun_l24_n505(x)
+ end
+end
+
+def fun_l23_n288(x)
+ if (x < 1)
+ fun_l24_n342(x)
+ else
+ fun_l24_n408(x)
+ end
+end
+
+def fun_l23_n289(x)
+ if (x < 1)
+ fun_l24_n456(x)
+ else
+ fun_l24_n768(x)
+ end
+end
+
+def fun_l23_n290(x)
+ if (x < 1)
+ fun_l24_n64(x)
+ else
+ fun_l24_n515(x)
+ end
+end
+
+def fun_l23_n291(x)
+ if (x < 1)
+ fun_l24_n86(x)
+ else
+ fun_l24_n420(x)
+ end
+end
+
+def fun_l23_n292(x)
+ if (x < 1)
+ fun_l24_n61(x)
+ else
+ fun_l24_n295(x)
+ end
+end
+
+def fun_l23_n293(x)
+ if (x < 1)
+ fun_l24_n893(x)
+ else
+ fun_l24_n680(x)
+ end
+end
+
+def fun_l23_n294(x)
+ if (x < 1)
+ fun_l24_n81(x)
+ else
+ fun_l24_n946(x)
+ end
+end
+
+def fun_l23_n295(x)
+ if (x < 1)
+ fun_l24_n444(x)
+ else
+ fun_l24_n205(x)
+ end
+end
+
+def fun_l23_n296(x)
+ if (x < 1)
+ fun_l24_n898(x)
+ else
+ fun_l24_n101(x)
+ end
+end
+
+def fun_l23_n297(x)
+ if (x < 1)
+ fun_l24_n617(x)
+ else
+ fun_l24_n660(x)
+ end
+end
+
+def fun_l23_n298(x)
+ if (x < 1)
+ fun_l24_n117(x)
+ else
+ fun_l24_n806(x)
+ end
+end
+
+def fun_l23_n299(x)
+ if (x < 1)
+ fun_l24_n92(x)
+ else
+ fun_l24_n660(x)
+ end
+end
+
+def fun_l23_n300(x)
+ if (x < 1)
+ fun_l24_n202(x)
+ else
+ fun_l24_n611(x)
+ end
+end
+
+def fun_l23_n301(x)
+ if (x < 1)
+ fun_l24_n852(x)
+ else
+ fun_l24_n569(x)
+ end
+end
+
+def fun_l23_n302(x)
+ if (x < 1)
+ fun_l24_n69(x)
+ else
+ fun_l24_n725(x)
+ end
+end
+
+def fun_l23_n303(x)
+ if (x < 1)
+ fun_l24_n183(x)
+ else
+ fun_l24_n406(x)
+ end
+end
+
+def fun_l23_n304(x)
+ if (x < 1)
+ fun_l24_n926(x)
+ else
+ fun_l24_n838(x)
+ end
+end
+
+def fun_l23_n305(x)
+ if (x < 1)
+ fun_l24_n16(x)
+ else
+ fun_l24_n681(x)
+ end
+end
+
+def fun_l23_n306(x)
+ if (x < 1)
+ fun_l24_n43(x)
+ else
+ fun_l24_n504(x)
+ end
+end
+
+def fun_l23_n307(x)
+ if (x < 1)
+ fun_l24_n417(x)
+ else
+ fun_l24_n239(x)
+ end
+end
+
+def fun_l23_n308(x)
+ if (x < 1)
+ fun_l24_n353(x)
+ else
+ fun_l24_n467(x)
+ end
+end
+
+def fun_l23_n309(x)
+ if (x < 1)
+ fun_l24_n633(x)
+ else
+ fun_l24_n593(x)
+ end
+end
+
+def fun_l23_n310(x)
+ if (x < 1)
+ fun_l24_n974(x)
+ else
+ fun_l24_n894(x)
+ end
+end
+
+def fun_l23_n311(x)
+ if (x < 1)
+ fun_l24_n3(x)
+ else
+ fun_l24_n751(x)
+ end
+end
+
+def fun_l23_n312(x)
+ if (x < 1)
+ fun_l24_n728(x)
+ else
+ fun_l24_n116(x)
+ end
+end
+
+def fun_l23_n313(x)
+ if (x < 1)
+ fun_l24_n588(x)
+ else
+ fun_l24_n636(x)
+ end
+end
+
+def fun_l23_n314(x)
+ if (x < 1)
+ fun_l24_n284(x)
+ else
+ fun_l24_n751(x)
+ end
+end
+
+def fun_l23_n315(x)
+ if (x < 1)
+ fun_l24_n567(x)
+ else
+ fun_l24_n356(x)
+ end
+end
+
+def fun_l23_n316(x)
+ if (x < 1)
+ fun_l24_n78(x)
+ else
+ fun_l24_n714(x)
+ end
+end
+
+def fun_l23_n317(x)
+ if (x < 1)
+ fun_l24_n592(x)
+ else
+ fun_l24_n720(x)
+ end
+end
+
+def fun_l23_n318(x)
+ if (x < 1)
+ fun_l24_n273(x)
+ else
+ fun_l24_n367(x)
+ end
+end
+
+def fun_l23_n319(x)
+ if (x < 1)
+ fun_l24_n816(x)
+ else
+ fun_l24_n964(x)
+ end
+end
+
+def fun_l23_n320(x)
+ if (x < 1)
+ fun_l24_n59(x)
+ else
+ fun_l24_n630(x)
+ end
+end
+
+def fun_l23_n321(x)
+ if (x < 1)
+ fun_l24_n298(x)
+ else
+ fun_l24_n639(x)
+ end
+end
+
+def fun_l23_n322(x)
+ if (x < 1)
+ fun_l24_n70(x)
+ else
+ fun_l24_n714(x)
+ end
+end
+
+def fun_l23_n323(x)
+ if (x < 1)
+ fun_l24_n495(x)
+ else
+ fun_l24_n630(x)
+ end
+end
+
+def fun_l23_n324(x)
+ if (x < 1)
+ fun_l24_n780(x)
+ else
+ fun_l24_n932(x)
+ end
+end
+
+def fun_l23_n325(x)
+ if (x < 1)
+ fun_l24_n494(x)
+ else
+ fun_l24_n610(x)
+ end
+end
+
+def fun_l23_n326(x)
+ if (x < 1)
+ fun_l24_n509(x)
+ else
+ fun_l24_n635(x)
+ end
+end
+
+def fun_l23_n327(x)
+ if (x < 1)
+ fun_l24_n991(x)
+ else
+ fun_l24_n355(x)
+ end
+end
+
+def fun_l23_n328(x)
+ if (x < 1)
+ fun_l24_n153(x)
+ else
+ fun_l24_n234(x)
+ end
+end
+
+def fun_l23_n329(x)
+ if (x < 1)
+ fun_l24_n483(x)
+ else
+ fun_l24_n812(x)
+ end
+end
+
+def fun_l23_n330(x)
+ if (x < 1)
+ fun_l24_n123(x)
+ else
+ fun_l24_n665(x)
+ end
+end
+
+def fun_l23_n331(x)
+ if (x < 1)
+ fun_l24_n752(x)
+ else
+ fun_l24_n471(x)
+ end
+end
+
+def fun_l23_n332(x)
+ if (x < 1)
+ fun_l24_n440(x)
+ else
+ fun_l24_n788(x)
+ end
+end
+
+def fun_l23_n333(x)
+ if (x < 1)
+ fun_l24_n381(x)
+ else
+ fun_l24_n95(x)
+ end
+end
+
+def fun_l23_n334(x)
+ if (x < 1)
+ fun_l24_n379(x)
+ else
+ fun_l24_n982(x)
+ end
+end
+
+def fun_l23_n335(x)
+ if (x < 1)
+ fun_l24_n766(x)
+ else
+ fun_l24_n14(x)
+ end
+end
+
+def fun_l23_n336(x)
+ if (x < 1)
+ fun_l24_n733(x)
+ else
+ fun_l24_n614(x)
+ end
+end
+
+def fun_l23_n337(x)
+ if (x < 1)
+ fun_l24_n946(x)
+ else
+ fun_l24_n408(x)
+ end
+end
+
+def fun_l23_n338(x)
+ if (x < 1)
+ fun_l24_n98(x)
+ else
+ fun_l24_n542(x)
+ end
+end
+
+def fun_l23_n339(x)
+ if (x < 1)
+ fun_l24_n60(x)
+ else
+ fun_l24_n970(x)
+ end
+end
+
+def fun_l23_n340(x)
+ if (x < 1)
+ fun_l24_n933(x)
+ else
+ fun_l24_n517(x)
+ end
+end
+
+def fun_l23_n341(x)
+ if (x < 1)
+ fun_l24_n634(x)
+ else
+ fun_l24_n943(x)
+ end
+end
+
+def fun_l23_n342(x)
+ if (x < 1)
+ fun_l24_n50(x)
+ else
+ fun_l24_n800(x)
+ end
+end
+
+def fun_l23_n343(x)
+ if (x < 1)
+ fun_l24_n352(x)
+ else
+ fun_l24_n450(x)
+ end
+end
+
+def fun_l23_n344(x)
+ if (x < 1)
+ fun_l24_n340(x)
+ else
+ fun_l24_n101(x)
+ end
+end
+
+def fun_l23_n345(x)
+ if (x < 1)
+ fun_l24_n383(x)
+ else
+ fun_l24_n493(x)
+ end
+end
+
+def fun_l23_n346(x)
+ if (x < 1)
+ fun_l24_n805(x)
+ else
+ fun_l24_n845(x)
+ end
+end
+
+def fun_l23_n347(x)
+ if (x < 1)
+ fun_l24_n491(x)
+ else
+ fun_l24_n756(x)
+ end
+end
+
+def fun_l23_n348(x)
+ if (x < 1)
+ fun_l24_n508(x)
+ else
+ fun_l24_n2(x)
+ end
+end
+
+def fun_l23_n349(x)
+ if (x < 1)
+ fun_l24_n865(x)
+ else
+ fun_l24_n55(x)
+ end
+end
+
+def fun_l23_n350(x)
+ if (x < 1)
+ fun_l24_n218(x)
+ else
+ fun_l24_n456(x)
+ end
+end
+
+def fun_l23_n351(x)
+ if (x < 1)
+ fun_l24_n162(x)
+ else
+ fun_l24_n312(x)
+ end
+end
+
+def fun_l23_n352(x)
+ if (x < 1)
+ fun_l24_n309(x)
+ else
+ fun_l24_n431(x)
+ end
+end
+
+def fun_l23_n353(x)
+ if (x < 1)
+ fun_l24_n411(x)
+ else
+ fun_l24_n684(x)
+ end
+end
+
+def fun_l23_n354(x)
+ if (x < 1)
+ fun_l24_n381(x)
+ else
+ fun_l24_n703(x)
+ end
+end
+
+def fun_l23_n355(x)
+ if (x < 1)
+ fun_l24_n189(x)
+ else
+ fun_l24_n217(x)
+ end
+end
+
+def fun_l23_n356(x)
+ if (x < 1)
+ fun_l24_n180(x)
+ else
+ fun_l24_n706(x)
+ end
+end
+
+def fun_l23_n357(x)
+ if (x < 1)
+ fun_l24_n76(x)
+ else
+ fun_l24_n575(x)
+ end
+end
+
+def fun_l23_n358(x)
+ if (x < 1)
+ fun_l24_n574(x)
+ else
+ fun_l24_n842(x)
+ end
+end
+
+def fun_l23_n359(x)
+ if (x < 1)
+ fun_l24_n281(x)
+ else
+ fun_l24_n572(x)
+ end
+end
+
+def fun_l23_n360(x)
+ if (x < 1)
+ fun_l24_n2(x)
+ else
+ fun_l24_n928(x)
+ end
+end
+
+def fun_l23_n361(x)
+ if (x < 1)
+ fun_l24_n840(x)
+ else
+ fun_l24_n794(x)
+ end
+end
+
+def fun_l23_n362(x)
+ if (x < 1)
+ fun_l24_n657(x)
+ else
+ fun_l24_n987(x)
+ end
+end
+
+def fun_l23_n363(x)
+ if (x < 1)
+ fun_l24_n400(x)
+ else
+ fun_l24_n151(x)
+ end
+end
+
+def fun_l23_n364(x)
+ if (x < 1)
+ fun_l24_n123(x)
+ else
+ fun_l24_n873(x)
+ end
+end
+
+def fun_l23_n365(x)
+ if (x < 1)
+ fun_l24_n51(x)
+ else
+ fun_l24_n52(x)
+ end
+end
+
+def fun_l23_n366(x)
+ if (x < 1)
+ fun_l24_n809(x)
+ else
+ fun_l24_n32(x)
+ end
+end
+
+def fun_l23_n367(x)
+ if (x < 1)
+ fun_l24_n928(x)
+ else
+ fun_l24_n618(x)
+ end
+end
+
+def fun_l23_n368(x)
+ if (x < 1)
+ fun_l24_n563(x)
+ else
+ fun_l24_n937(x)
+ end
+end
+
+def fun_l23_n369(x)
+ if (x < 1)
+ fun_l24_n312(x)
+ else
+ fun_l24_n918(x)
+ end
+end
+
+def fun_l23_n370(x)
+ if (x < 1)
+ fun_l24_n940(x)
+ else
+ fun_l24_n994(x)
+ end
+end
+
+def fun_l23_n371(x)
+ if (x < 1)
+ fun_l24_n788(x)
+ else
+ fun_l24_n187(x)
+ end
+end
+
+def fun_l23_n372(x)
+ if (x < 1)
+ fun_l24_n110(x)
+ else
+ fun_l24_n523(x)
+ end
+end
+
+def fun_l23_n373(x)
+ if (x < 1)
+ fun_l24_n158(x)
+ else
+ fun_l24_n656(x)
+ end
+end
+
+def fun_l23_n374(x)
+ if (x < 1)
+ fun_l24_n522(x)
+ else
+ fun_l24_n395(x)
+ end
+end
+
+def fun_l23_n375(x)
+ if (x < 1)
+ fun_l24_n90(x)
+ else
+ fun_l24_n732(x)
+ end
+end
+
+def fun_l23_n376(x)
+ if (x < 1)
+ fun_l24_n809(x)
+ else
+ fun_l24_n513(x)
+ end
+end
+
+def fun_l23_n377(x)
+ if (x < 1)
+ fun_l24_n916(x)
+ else
+ fun_l24_n962(x)
+ end
+end
+
+def fun_l23_n378(x)
+ if (x < 1)
+ fun_l24_n852(x)
+ else
+ fun_l24_n350(x)
+ end
+end
+
+def fun_l23_n379(x)
+ if (x < 1)
+ fun_l24_n555(x)
+ else
+ fun_l24_n375(x)
+ end
+end
+
+def fun_l23_n380(x)
+ if (x < 1)
+ fun_l24_n17(x)
+ else
+ fun_l24_n566(x)
+ end
+end
+
+def fun_l23_n381(x)
+ if (x < 1)
+ fun_l24_n332(x)
+ else
+ fun_l24_n35(x)
+ end
+end
+
+def fun_l23_n382(x)
+ if (x < 1)
+ fun_l24_n531(x)
+ else
+ fun_l24_n368(x)
+ end
+end
+
+def fun_l23_n383(x)
+ if (x < 1)
+ fun_l24_n712(x)
+ else
+ fun_l24_n32(x)
+ end
+end
+
+def fun_l23_n384(x)
+ if (x < 1)
+ fun_l24_n239(x)
+ else
+ fun_l24_n542(x)
+ end
+end
+
+def fun_l23_n385(x)
+ if (x < 1)
+ fun_l24_n914(x)
+ else
+ fun_l24_n820(x)
+ end
+end
+
+def fun_l23_n386(x)
+ if (x < 1)
+ fun_l24_n579(x)
+ else
+ fun_l24_n202(x)
+ end
+end
+
+def fun_l23_n387(x)
+ if (x < 1)
+ fun_l24_n36(x)
+ else
+ fun_l24_n591(x)
+ end
+end
+
+def fun_l23_n388(x)
+ if (x < 1)
+ fun_l24_n485(x)
+ else
+ fun_l24_n707(x)
+ end
+end
+
+def fun_l23_n389(x)
+ if (x < 1)
+ fun_l24_n587(x)
+ else
+ fun_l24_n588(x)
+ end
+end
+
+def fun_l23_n390(x)
+ if (x < 1)
+ fun_l24_n837(x)
+ else
+ fun_l24_n352(x)
+ end
+end
+
+def fun_l23_n391(x)
+ if (x < 1)
+ fun_l24_n926(x)
+ else
+ fun_l24_n553(x)
+ end
+end
+
+def fun_l23_n392(x)
+ if (x < 1)
+ fun_l24_n557(x)
+ else
+ fun_l24_n944(x)
+ end
+end
+
+def fun_l23_n393(x)
+ if (x < 1)
+ fun_l24_n870(x)
+ else
+ fun_l24_n632(x)
+ end
+end
+
+def fun_l23_n394(x)
+ if (x < 1)
+ fun_l24_n732(x)
+ else
+ fun_l24_n285(x)
+ end
+end
+
+def fun_l23_n395(x)
+ if (x < 1)
+ fun_l24_n249(x)
+ else
+ fun_l24_n709(x)
+ end
+end
+
+def fun_l23_n396(x)
+ if (x < 1)
+ fun_l24_n674(x)
+ else
+ fun_l24_n693(x)
+ end
+end
+
+def fun_l23_n397(x)
+ if (x < 1)
+ fun_l24_n20(x)
+ else
+ fun_l24_n367(x)
+ end
+end
+
+def fun_l23_n398(x)
+ if (x < 1)
+ fun_l24_n545(x)
+ else
+ fun_l24_n973(x)
+ end
+end
+
+def fun_l23_n399(x)
+ if (x < 1)
+ fun_l24_n460(x)
+ else
+ fun_l24_n627(x)
+ end
+end
+
+def fun_l23_n400(x)
+ if (x < 1)
+ fun_l24_n941(x)
+ else
+ fun_l24_n679(x)
+ end
+end
+
+def fun_l23_n401(x)
+ if (x < 1)
+ fun_l24_n161(x)
+ else
+ fun_l24_n518(x)
+ end
+end
+
+def fun_l23_n402(x)
+ if (x < 1)
+ fun_l24_n738(x)
+ else
+ fun_l24_n393(x)
+ end
+end
+
+def fun_l23_n403(x)
+ if (x < 1)
+ fun_l24_n75(x)
+ else
+ fun_l24_n776(x)
+ end
+end
+
+def fun_l23_n404(x)
+ if (x < 1)
+ fun_l24_n996(x)
+ else
+ fun_l24_n71(x)
+ end
+end
+
+def fun_l23_n405(x)
+ if (x < 1)
+ fun_l24_n732(x)
+ else
+ fun_l24_n649(x)
+ end
+end
+
+def fun_l23_n406(x)
+ if (x < 1)
+ fun_l24_n142(x)
+ else
+ fun_l24_n563(x)
+ end
+end
+
+def fun_l23_n407(x)
+ if (x < 1)
+ fun_l24_n63(x)
+ else
+ fun_l24_n629(x)
+ end
+end
+
+def fun_l23_n408(x)
+ if (x < 1)
+ fun_l24_n734(x)
+ else
+ fun_l24_n857(x)
+ end
+end
+
+def fun_l23_n409(x)
+ if (x < 1)
+ fun_l24_n100(x)
+ else
+ fun_l24_n340(x)
+ end
+end
+
+def fun_l23_n410(x)
+ if (x < 1)
+ fun_l24_n471(x)
+ else
+ fun_l24_n114(x)
+ end
+end
+
+def fun_l23_n411(x)
+ if (x < 1)
+ fun_l24_n316(x)
+ else
+ fun_l24_n965(x)
+ end
+end
+
+def fun_l23_n412(x)
+ if (x < 1)
+ fun_l24_n909(x)
+ else
+ fun_l24_n779(x)
+ end
+end
+
+def fun_l23_n413(x)
+ if (x < 1)
+ fun_l24_n846(x)
+ else
+ fun_l24_n473(x)
+ end
+end
+
+def fun_l23_n414(x)
+ if (x < 1)
+ fun_l24_n117(x)
+ else
+ fun_l24_n751(x)
+ end
+end
+
+def fun_l23_n415(x)
+ if (x < 1)
+ fun_l24_n360(x)
+ else
+ fun_l24_n285(x)
+ end
+end
+
+def fun_l23_n416(x)
+ if (x < 1)
+ fun_l24_n430(x)
+ else
+ fun_l24_n273(x)
+ end
+end
+
+def fun_l23_n417(x)
+ if (x < 1)
+ fun_l24_n925(x)
+ else
+ fun_l24_n928(x)
+ end
+end
+
+def fun_l23_n418(x)
+ if (x < 1)
+ fun_l24_n478(x)
+ else
+ fun_l24_n511(x)
+ end
+end
+
+def fun_l23_n419(x)
+ if (x < 1)
+ fun_l24_n415(x)
+ else
+ fun_l24_n127(x)
+ end
+end
+
+def fun_l23_n420(x)
+ if (x < 1)
+ fun_l24_n33(x)
+ else
+ fun_l24_n897(x)
+ end
+end
+
+def fun_l23_n421(x)
+ if (x < 1)
+ fun_l24_n112(x)
+ else
+ fun_l24_n87(x)
+ end
+end
+
+def fun_l23_n422(x)
+ if (x < 1)
+ fun_l24_n386(x)
+ else
+ fun_l24_n450(x)
+ end
+end
+
+def fun_l23_n423(x)
+ if (x < 1)
+ fun_l24_n430(x)
+ else
+ fun_l24_n517(x)
+ end
+end
+
+def fun_l23_n424(x)
+ if (x < 1)
+ fun_l24_n413(x)
+ else
+ fun_l24_n799(x)
+ end
+end
+
+def fun_l23_n425(x)
+ if (x < 1)
+ fun_l24_n744(x)
+ else
+ fun_l24_n218(x)
+ end
+end
+
+def fun_l23_n426(x)
+ if (x < 1)
+ fun_l24_n231(x)
+ else
+ fun_l24_n454(x)
+ end
+end
+
+def fun_l23_n427(x)
+ if (x < 1)
+ fun_l24_n693(x)
+ else
+ fun_l24_n28(x)
+ end
+end
+
+def fun_l23_n428(x)
+ if (x < 1)
+ fun_l24_n694(x)
+ else
+ fun_l24_n712(x)
+ end
+end
+
+def fun_l23_n429(x)
+ if (x < 1)
+ fun_l24_n949(x)
+ else
+ fun_l24_n983(x)
+ end
+end
+
+def fun_l23_n430(x)
+ if (x < 1)
+ fun_l24_n324(x)
+ else
+ fun_l24_n818(x)
+ end
+end
+
+def fun_l23_n431(x)
+ if (x < 1)
+ fun_l24_n820(x)
+ else
+ fun_l24_n662(x)
+ end
+end
+
+def fun_l23_n432(x)
+ if (x < 1)
+ fun_l24_n391(x)
+ else
+ fun_l24_n801(x)
+ end
+end
+
+def fun_l23_n433(x)
+ if (x < 1)
+ fun_l24_n285(x)
+ else
+ fun_l24_n79(x)
+ end
+end
+
+def fun_l23_n434(x)
+ if (x < 1)
+ fun_l24_n582(x)
+ else
+ fun_l24_n820(x)
+ end
+end
+
+def fun_l23_n435(x)
+ if (x < 1)
+ fun_l24_n324(x)
+ else
+ fun_l24_n348(x)
+ end
+end
+
+def fun_l23_n436(x)
+ if (x < 1)
+ fun_l24_n241(x)
+ else
+ fun_l24_n568(x)
+ end
+end
+
+def fun_l23_n437(x)
+ if (x < 1)
+ fun_l24_n261(x)
+ else
+ fun_l24_n374(x)
+ end
+end
+
+def fun_l23_n438(x)
+ if (x < 1)
+ fun_l24_n886(x)
+ else
+ fun_l24_n38(x)
+ end
+end
+
+def fun_l23_n439(x)
+ if (x < 1)
+ fun_l24_n344(x)
+ else
+ fun_l24_n991(x)
+ end
+end
+
+def fun_l23_n440(x)
+ if (x < 1)
+ fun_l24_n792(x)
+ else
+ fun_l24_n298(x)
+ end
+end
+
+def fun_l23_n441(x)
+ if (x < 1)
+ fun_l24_n728(x)
+ else
+ fun_l24_n575(x)
+ end
+end
+
+def fun_l23_n442(x)
+ if (x < 1)
+ fun_l24_n22(x)
+ else
+ fun_l24_n804(x)
+ end
+end
+
+def fun_l23_n443(x)
+ if (x < 1)
+ fun_l24_n406(x)
+ else
+ fun_l24_n723(x)
+ end
+end
+
+def fun_l23_n444(x)
+ if (x < 1)
+ fun_l24_n921(x)
+ else
+ fun_l24_n455(x)
+ end
+end
+
+def fun_l23_n445(x)
+ if (x < 1)
+ fun_l24_n725(x)
+ else
+ fun_l24_n799(x)
+ end
+end
+
+def fun_l23_n446(x)
+ if (x < 1)
+ fun_l24_n543(x)
+ else
+ fun_l24_n350(x)
+ end
+end
+
+def fun_l23_n447(x)
+ if (x < 1)
+ fun_l24_n849(x)
+ else
+ fun_l24_n447(x)
+ end
+end
+
+def fun_l23_n448(x)
+ if (x < 1)
+ fun_l24_n357(x)
+ else
+ fun_l24_n915(x)
+ end
+end
+
+def fun_l23_n449(x)
+ if (x < 1)
+ fun_l24_n143(x)
+ else
+ fun_l24_n164(x)
+ end
+end
+
+def fun_l23_n450(x)
+ if (x < 1)
+ fun_l24_n702(x)
+ else
+ fun_l24_n940(x)
+ end
+end
+
+def fun_l23_n451(x)
+ if (x < 1)
+ fun_l24_n76(x)
+ else
+ fun_l24_n229(x)
+ end
+end
+
+def fun_l23_n452(x)
+ if (x < 1)
+ fun_l24_n55(x)
+ else
+ fun_l24_n177(x)
+ end
+end
+
+def fun_l23_n453(x)
+ if (x < 1)
+ fun_l24_n65(x)
+ else
+ fun_l24_n310(x)
+ end
+end
+
+def fun_l23_n454(x)
+ if (x < 1)
+ fun_l24_n818(x)
+ else
+ fun_l24_n1(x)
+ end
+end
+
+def fun_l23_n455(x)
+ if (x < 1)
+ fun_l24_n555(x)
+ else
+ fun_l24_n475(x)
+ end
+end
+
+def fun_l23_n456(x)
+ if (x < 1)
+ fun_l24_n867(x)
+ else
+ fun_l24_n350(x)
+ end
+end
+
+def fun_l23_n457(x)
+ if (x < 1)
+ fun_l24_n953(x)
+ else
+ fun_l24_n932(x)
+ end
+end
+
+def fun_l23_n458(x)
+ if (x < 1)
+ fun_l24_n104(x)
+ else
+ fun_l24_n555(x)
+ end
+end
+
+def fun_l23_n459(x)
+ if (x < 1)
+ fun_l24_n259(x)
+ else
+ fun_l24_n196(x)
+ end
+end
+
+def fun_l23_n460(x)
+ if (x < 1)
+ fun_l24_n747(x)
+ else
+ fun_l24_n788(x)
+ end
+end
+
+def fun_l23_n461(x)
+ if (x < 1)
+ fun_l24_n302(x)
+ else
+ fun_l24_n479(x)
+ end
+end
+
+def fun_l23_n462(x)
+ if (x < 1)
+ fun_l24_n292(x)
+ else
+ fun_l24_n235(x)
+ end
+end
+
+def fun_l23_n463(x)
+ if (x < 1)
+ fun_l24_n589(x)
+ else
+ fun_l24_n277(x)
+ end
+end
+
+def fun_l23_n464(x)
+ if (x < 1)
+ fun_l24_n212(x)
+ else
+ fun_l24_n334(x)
+ end
+end
+
+def fun_l23_n465(x)
+ if (x < 1)
+ fun_l24_n878(x)
+ else
+ fun_l24_n111(x)
+ end
+end
+
+def fun_l23_n466(x)
+ if (x < 1)
+ fun_l24_n862(x)
+ else
+ fun_l24_n736(x)
+ end
+end
+
+def fun_l23_n467(x)
+ if (x < 1)
+ fun_l24_n257(x)
+ else
+ fun_l24_n745(x)
+ end
+end
+
+def fun_l23_n468(x)
+ if (x < 1)
+ fun_l24_n922(x)
+ else
+ fun_l24_n453(x)
+ end
+end
+
+def fun_l23_n469(x)
+ if (x < 1)
+ fun_l24_n334(x)
+ else
+ fun_l24_n23(x)
+ end
+end
+
+def fun_l23_n470(x)
+ if (x < 1)
+ fun_l24_n585(x)
+ else
+ fun_l24_n512(x)
+ end
+end
+
+def fun_l23_n471(x)
+ if (x < 1)
+ fun_l24_n135(x)
+ else
+ fun_l24_n244(x)
+ end
+end
+
+def fun_l23_n472(x)
+ if (x < 1)
+ fun_l24_n151(x)
+ else
+ fun_l24_n479(x)
+ end
+end
+
+def fun_l23_n473(x)
+ if (x < 1)
+ fun_l24_n192(x)
+ else
+ fun_l24_n748(x)
+ end
+end
+
+def fun_l23_n474(x)
+ if (x < 1)
+ fun_l24_n729(x)
+ else
+ fun_l24_n283(x)
+ end
+end
+
+def fun_l23_n475(x)
+ if (x < 1)
+ fun_l24_n453(x)
+ else
+ fun_l24_n244(x)
+ end
+end
+
+def fun_l23_n476(x)
+ if (x < 1)
+ fun_l24_n210(x)
+ else
+ fun_l24_n6(x)
+ end
+end
+
+def fun_l23_n477(x)
+ if (x < 1)
+ fun_l24_n387(x)
+ else
+ fun_l24_n857(x)
+ end
+end
+
+def fun_l23_n478(x)
+ if (x < 1)
+ fun_l24_n312(x)
+ else
+ fun_l24_n378(x)
+ end
+end
+
+def fun_l23_n479(x)
+ if (x < 1)
+ fun_l24_n553(x)
+ else
+ fun_l24_n264(x)
+ end
+end
+
+def fun_l23_n480(x)
+ if (x < 1)
+ fun_l24_n903(x)
+ else
+ fun_l24_n374(x)
+ end
+end
+
+def fun_l23_n481(x)
+ if (x < 1)
+ fun_l24_n9(x)
+ else
+ fun_l24_n494(x)
+ end
+end
+
+def fun_l23_n482(x)
+ if (x < 1)
+ fun_l24_n4(x)
+ else
+ fun_l24_n119(x)
+ end
+end
+
+def fun_l23_n483(x)
+ if (x < 1)
+ fun_l24_n969(x)
+ else
+ fun_l24_n716(x)
+ end
+end
+
+def fun_l23_n484(x)
+ if (x < 1)
+ fun_l24_n132(x)
+ else
+ fun_l24_n950(x)
+ end
+end
+
+def fun_l23_n485(x)
+ if (x < 1)
+ fun_l24_n641(x)
+ else
+ fun_l24_n134(x)
+ end
+end
+
+def fun_l23_n486(x)
+ if (x < 1)
+ fun_l24_n499(x)
+ else
+ fun_l24_n506(x)
+ end
+end
+
+def fun_l23_n487(x)
+ if (x < 1)
+ fun_l24_n594(x)
+ else
+ fun_l24_n508(x)
+ end
+end
+
+def fun_l23_n488(x)
+ if (x < 1)
+ fun_l24_n730(x)
+ else
+ fun_l24_n464(x)
+ end
+end
+
+def fun_l23_n489(x)
+ if (x < 1)
+ fun_l24_n564(x)
+ else
+ fun_l24_n716(x)
+ end
+end
+
+def fun_l23_n490(x)
+ if (x < 1)
+ fun_l24_n658(x)
+ else
+ fun_l24_n63(x)
+ end
+end
+
+def fun_l23_n491(x)
+ if (x < 1)
+ fun_l24_n404(x)
+ else
+ fun_l24_n982(x)
+ end
+end
+
+def fun_l23_n492(x)
+ if (x < 1)
+ fun_l24_n182(x)
+ else
+ fun_l24_n97(x)
+ end
+end
+
+def fun_l23_n493(x)
+ if (x < 1)
+ fun_l24_n97(x)
+ else
+ fun_l24_n765(x)
+ end
+end
+
+def fun_l23_n494(x)
+ if (x < 1)
+ fun_l24_n728(x)
+ else
+ fun_l24_n703(x)
+ end
+end
+
+def fun_l23_n495(x)
+ if (x < 1)
+ fun_l24_n327(x)
+ else
+ fun_l24_n484(x)
+ end
+end
+
+def fun_l23_n496(x)
+ if (x < 1)
+ fun_l24_n544(x)
+ else
+ fun_l24_n814(x)
+ end
+end
+
+def fun_l23_n497(x)
+ if (x < 1)
+ fun_l24_n555(x)
+ else
+ fun_l24_n160(x)
+ end
+end
+
+def fun_l23_n498(x)
+ if (x < 1)
+ fun_l24_n336(x)
+ else
+ fun_l24_n544(x)
+ end
+end
+
+def fun_l23_n499(x)
+ if (x < 1)
+ fun_l24_n242(x)
+ else
+ fun_l24_n337(x)
+ end
+end
+
+def fun_l23_n500(x)
+ if (x < 1)
+ fun_l24_n71(x)
+ else
+ fun_l24_n446(x)
+ end
+end
+
+def fun_l23_n501(x)
+ if (x < 1)
+ fun_l24_n726(x)
+ else
+ fun_l24_n127(x)
+ end
+end
+
+def fun_l23_n502(x)
+ if (x < 1)
+ fun_l24_n430(x)
+ else
+ fun_l24_n136(x)
+ end
+end
+
+def fun_l23_n503(x)
+ if (x < 1)
+ fun_l24_n140(x)
+ else
+ fun_l24_n942(x)
+ end
+end
+
+def fun_l23_n504(x)
+ if (x < 1)
+ fun_l24_n135(x)
+ else
+ fun_l24_n701(x)
+ end
+end
+
+def fun_l23_n505(x)
+ if (x < 1)
+ fun_l24_n409(x)
+ else
+ fun_l24_n825(x)
+ end
+end
+
+def fun_l23_n506(x)
+ if (x < 1)
+ fun_l24_n415(x)
+ else
+ fun_l24_n336(x)
+ end
+end
+
+def fun_l23_n507(x)
+ if (x < 1)
+ fun_l24_n118(x)
+ else
+ fun_l24_n904(x)
+ end
+end
+
+def fun_l23_n508(x)
+ if (x < 1)
+ fun_l24_n870(x)
+ else
+ fun_l24_n473(x)
+ end
+end
+
+def fun_l23_n509(x)
+ if (x < 1)
+ fun_l24_n99(x)
+ else
+ fun_l24_n157(x)
+ end
+end
+
+def fun_l23_n510(x)
+ if (x < 1)
+ fun_l24_n484(x)
+ else
+ fun_l24_n933(x)
+ end
+end
+
+def fun_l23_n511(x)
+ if (x < 1)
+ fun_l24_n204(x)
+ else
+ fun_l24_n95(x)
+ end
+end
+
+def fun_l23_n512(x)
+ if (x < 1)
+ fun_l24_n783(x)
+ else
+ fun_l24_n490(x)
+ end
+end
+
+def fun_l23_n513(x)
+ if (x < 1)
+ fun_l24_n642(x)
+ else
+ fun_l24_n622(x)
+ end
+end
+
+def fun_l23_n514(x)
+ if (x < 1)
+ fun_l24_n514(x)
+ else
+ fun_l24_n287(x)
+ end
+end
+
+def fun_l23_n515(x)
+ if (x < 1)
+ fun_l24_n174(x)
+ else
+ fun_l24_n19(x)
+ end
+end
+
+def fun_l23_n516(x)
+ if (x < 1)
+ fun_l24_n840(x)
+ else
+ fun_l24_n710(x)
+ end
+end
+
+def fun_l23_n517(x)
+ if (x < 1)
+ fun_l24_n921(x)
+ else
+ fun_l24_n11(x)
+ end
+end
+
+def fun_l23_n518(x)
+ if (x < 1)
+ fun_l24_n162(x)
+ else
+ fun_l24_n185(x)
+ end
+end
+
+def fun_l23_n519(x)
+ if (x < 1)
+ fun_l24_n654(x)
+ else
+ fun_l24_n514(x)
+ end
+end
+
+def fun_l23_n520(x)
+ if (x < 1)
+ fun_l24_n763(x)
+ else
+ fun_l24_n158(x)
+ end
+end
+
+def fun_l23_n521(x)
+ if (x < 1)
+ fun_l24_n471(x)
+ else
+ fun_l24_n617(x)
+ end
+end
+
+def fun_l23_n522(x)
+ if (x < 1)
+ fun_l24_n146(x)
+ else
+ fun_l24_n6(x)
+ end
+end
+
+def fun_l23_n523(x)
+ if (x < 1)
+ fun_l24_n447(x)
+ else
+ fun_l24_n981(x)
+ end
+end
+
+def fun_l23_n524(x)
+ if (x < 1)
+ fun_l24_n809(x)
+ else
+ fun_l24_n78(x)
+ end
+end
+
+def fun_l23_n525(x)
+ if (x < 1)
+ fun_l24_n554(x)
+ else
+ fun_l24_n50(x)
+ end
+end
+
+def fun_l23_n526(x)
+ if (x < 1)
+ fun_l24_n970(x)
+ else
+ fun_l24_n600(x)
+ end
+end
+
+def fun_l23_n527(x)
+ if (x < 1)
+ fun_l24_n700(x)
+ else
+ fun_l24_n982(x)
+ end
+end
+
+def fun_l23_n528(x)
+ if (x < 1)
+ fun_l24_n947(x)
+ else
+ fun_l24_n886(x)
+ end
+end
+
+def fun_l23_n529(x)
+ if (x < 1)
+ fun_l24_n198(x)
+ else
+ fun_l24_n283(x)
+ end
+end
+
+def fun_l23_n530(x)
+ if (x < 1)
+ fun_l24_n641(x)
+ else
+ fun_l24_n879(x)
+ end
+end
+
+def fun_l23_n531(x)
+ if (x < 1)
+ fun_l24_n393(x)
+ else
+ fun_l24_n451(x)
+ end
+end
+
+def fun_l23_n532(x)
+ if (x < 1)
+ fun_l24_n802(x)
+ else
+ fun_l24_n271(x)
+ end
+end
+
+def fun_l23_n533(x)
+ if (x < 1)
+ fun_l24_n926(x)
+ else
+ fun_l24_n315(x)
+ end
+end
+
+def fun_l23_n534(x)
+ if (x < 1)
+ fun_l24_n544(x)
+ else
+ fun_l24_n358(x)
+ end
+end
+
+def fun_l23_n535(x)
+ if (x < 1)
+ fun_l24_n456(x)
+ else
+ fun_l24_n569(x)
+ end
+end
+
+def fun_l23_n536(x)
+ if (x < 1)
+ fun_l24_n235(x)
+ else
+ fun_l24_n182(x)
+ end
+end
+
+def fun_l23_n537(x)
+ if (x < 1)
+ fun_l24_n159(x)
+ else
+ fun_l24_n674(x)
+ end
+end
+
+def fun_l23_n538(x)
+ if (x < 1)
+ fun_l24_n956(x)
+ else
+ fun_l24_n145(x)
+ end
+end
+
+def fun_l23_n539(x)
+ if (x < 1)
+ fun_l24_n294(x)
+ else
+ fun_l24_n910(x)
+ end
+end
+
+def fun_l23_n540(x)
+ if (x < 1)
+ fun_l24_n434(x)
+ else
+ fun_l24_n336(x)
+ end
+end
+
+def fun_l23_n541(x)
+ if (x < 1)
+ fun_l24_n635(x)
+ else
+ fun_l24_n182(x)
+ end
+end
+
+def fun_l23_n542(x)
+ if (x < 1)
+ fun_l24_n418(x)
+ else
+ fun_l24_n828(x)
+ end
+end
+
+def fun_l23_n543(x)
+ if (x < 1)
+ fun_l24_n337(x)
+ else
+ fun_l24_n740(x)
+ end
+end
+
+def fun_l23_n544(x)
+ if (x < 1)
+ fun_l24_n893(x)
+ else
+ fun_l24_n402(x)
+ end
+end
+
+def fun_l23_n545(x)
+ if (x < 1)
+ fun_l24_n407(x)
+ else
+ fun_l24_n124(x)
+ end
+end
+
+def fun_l23_n546(x)
+ if (x < 1)
+ fun_l24_n170(x)
+ else
+ fun_l24_n64(x)
+ end
+end
+
+def fun_l23_n547(x)
+ if (x < 1)
+ fun_l24_n936(x)
+ else
+ fun_l24_n876(x)
+ end
+end
+
+def fun_l23_n548(x)
+ if (x < 1)
+ fun_l24_n387(x)
+ else
+ fun_l24_n655(x)
+ end
+end
+
+def fun_l23_n549(x)
+ if (x < 1)
+ fun_l24_n162(x)
+ else
+ fun_l24_n210(x)
+ end
+end
+
+def fun_l23_n550(x)
+ if (x < 1)
+ fun_l24_n454(x)
+ else
+ fun_l24_n695(x)
+ end
+end
+
+def fun_l23_n551(x)
+ if (x < 1)
+ fun_l24_n410(x)
+ else
+ fun_l24_n529(x)
+ end
+end
+
+def fun_l23_n552(x)
+ if (x < 1)
+ fun_l24_n726(x)
+ else
+ fun_l24_n450(x)
+ end
+end
+
+def fun_l23_n553(x)
+ if (x < 1)
+ fun_l24_n39(x)
+ else
+ fun_l24_n37(x)
+ end
+end
+
+def fun_l23_n554(x)
+ if (x < 1)
+ fun_l24_n994(x)
+ else
+ fun_l24_n106(x)
+ end
+end
+
+def fun_l23_n555(x)
+ if (x < 1)
+ fun_l24_n929(x)
+ else
+ fun_l24_n766(x)
+ end
+end
+
+def fun_l23_n556(x)
+ if (x < 1)
+ fun_l24_n531(x)
+ else
+ fun_l24_n502(x)
+ end
+end
+
+def fun_l23_n557(x)
+ if (x < 1)
+ fun_l24_n890(x)
+ else
+ fun_l24_n919(x)
+ end
+end
+
+def fun_l23_n558(x)
+ if (x < 1)
+ fun_l24_n803(x)
+ else
+ fun_l24_n460(x)
+ end
+end
+
+def fun_l23_n559(x)
+ if (x < 1)
+ fun_l24_n5(x)
+ else
+ fun_l24_n464(x)
+ end
+end
+
+def fun_l23_n560(x)
+ if (x < 1)
+ fun_l24_n506(x)
+ else
+ fun_l24_n891(x)
+ end
+end
+
+def fun_l23_n561(x)
+ if (x < 1)
+ fun_l24_n98(x)
+ else
+ fun_l24_n534(x)
+ end
+end
+
+def fun_l23_n562(x)
+ if (x < 1)
+ fun_l24_n130(x)
+ else
+ fun_l24_n54(x)
+ end
+end
+
+def fun_l23_n563(x)
+ if (x < 1)
+ fun_l24_n881(x)
+ else
+ fun_l24_n699(x)
+ end
+end
+
+def fun_l23_n564(x)
+ if (x < 1)
+ fun_l24_n192(x)
+ else
+ fun_l24_n112(x)
+ end
+end
+
+def fun_l23_n565(x)
+ if (x < 1)
+ fun_l24_n249(x)
+ else
+ fun_l24_n796(x)
+ end
+end
+
+def fun_l23_n566(x)
+ if (x < 1)
+ fun_l24_n113(x)
+ else
+ fun_l24_n599(x)
+ end
+end
+
+def fun_l23_n567(x)
+ if (x < 1)
+ fun_l24_n334(x)
+ else
+ fun_l24_n80(x)
+ end
+end
+
+def fun_l23_n568(x)
+ if (x < 1)
+ fun_l24_n347(x)
+ else
+ fun_l24_n726(x)
+ end
+end
+
+def fun_l23_n569(x)
+ if (x < 1)
+ fun_l24_n60(x)
+ else
+ fun_l24_n249(x)
+ end
+end
+
+def fun_l23_n570(x)
+ if (x < 1)
+ fun_l24_n400(x)
+ else
+ fun_l24_n773(x)
+ end
+end
+
+def fun_l23_n571(x)
+ if (x < 1)
+ fun_l24_n172(x)
+ else
+ fun_l24_n787(x)
+ end
+end
+
+def fun_l23_n572(x)
+ if (x < 1)
+ fun_l24_n973(x)
+ else
+ fun_l24_n875(x)
+ end
+end
+
+def fun_l23_n573(x)
+ if (x < 1)
+ fun_l24_n290(x)
+ else
+ fun_l24_n225(x)
+ end
+end
+
+def fun_l23_n574(x)
+ if (x < 1)
+ fun_l24_n383(x)
+ else
+ fun_l24_n714(x)
+ end
+end
+
+def fun_l23_n575(x)
+ if (x < 1)
+ fun_l24_n32(x)
+ else
+ fun_l24_n508(x)
+ end
+end
+
+def fun_l23_n576(x)
+ if (x < 1)
+ fun_l24_n74(x)
+ else
+ fun_l24_n368(x)
+ end
+end
+
+def fun_l23_n577(x)
+ if (x < 1)
+ fun_l24_n431(x)
+ else
+ fun_l24_n2(x)
+ end
+end
+
+def fun_l23_n578(x)
+ if (x < 1)
+ fun_l24_n758(x)
+ else
+ fun_l24_n178(x)
+ end
+end
+
+def fun_l23_n579(x)
+ if (x < 1)
+ fun_l24_n130(x)
+ else
+ fun_l24_n512(x)
+ end
+end
+
+def fun_l23_n580(x)
+ if (x < 1)
+ fun_l24_n790(x)
+ else
+ fun_l24_n280(x)
+ end
+end
+
+def fun_l23_n581(x)
+ if (x < 1)
+ fun_l24_n76(x)
+ else
+ fun_l24_n596(x)
+ end
+end
+
+def fun_l23_n582(x)
+ if (x < 1)
+ fun_l24_n643(x)
+ else
+ fun_l24_n506(x)
+ end
+end
+
+def fun_l23_n583(x)
+ if (x < 1)
+ fun_l24_n392(x)
+ else
+ fun_l24_n671(x)
+ end
+end
+
+def fun_l23_n584(x)
+ if (x < 1)
+ fun_l24_n722(x)
+ else
+ fun_l24_n390(x)
+ end
+end
+
+def fun_l23_n585(x)
+ if (x < 1)
+ fun_l24_n613(x)
+ else
+ fun_l24_n461(x)
+ end
+end
+
+def fun_l23_n586(x)
+ if (x < 1)
+ fun_l24_n784(x)
+ else
+ fun_l24_n426(x)
+ end
+end
+
+def fun_l23_n587(x)
+ if (x < 1)
+ fun_l24_n351(x)
+ else
+ fun_l24_n68(x)
+ end
+end
+
+def fun_l23_n588(x)
+ if (x < 1)
+ fun_l24_n8(x)
+ else
+ fun_l24_n9(x)
+ end
+end
+
+def fun_l23_n589(x)
+ if (x < 1)
+ fun_l24_n984(x)
+ else
+ fun_l24_n704(x)
+ end
+end
+
+def fun_l23_n590(x)
+ if (x < 1)
+ fun_l24_n150(x)
+ else
+ fun_l24_n36(x)
+ end
+end
+
+def fun_l23_n591(x)
+ if (x < 1)
+ fun_l24_n232(x)
+ else
+ fun_l24_n293(x)
+ end
+end
+
+def fun_l23_n592(x)
+ if (x < 1)
+ fun_l24_n763(x)
+ else
+ fun_l24_n444(x)
+ end
+end
+
+def fun_l23_n593(x)
+ if (x < 1)
+ fun_l24_n246(x)
+ else
+ fun_l24_n101(x)
+ end
+end
+
+def fun_l23_n594(x)
+ if (x < 1)
+ fun_l24_n145(x)
+ else
+ fun_l24_n626(x)
+ end
+end
+
+def fun_l23_n595(x)
+ if (x < 1)
+ fun_l24_n835(x)
+ else
+ fun_l24_n827(x)
+ end
+end
+
+def fun_l23_n596(x)
+ if (x < 1)
+ fun_l24_n925(x)
+ else
+ fun_l24_n875(x)
+ end
+end
+
+def fun_l23_n597(x)
+ if (x < 1)
+ fun_l24_n600(x)
+ else
+ fun_l24_n817(x)
+ end
+end
+
+def fun_l23_n598(x)
+ if (x < 1)
+ fun_l24_n653(x)
+ else
+ fun_l24_n632(x)
+ end
+end
+
+def fun_l23_n599(x)
+ if (x < 1)
+ fun_l24_n103(x)
+ else
+ fun_l24_n675(x)
+ end
+end
+
+def fun_l23_n600(x)
+ if (x < 1)
+ fun_l24_n1(x)
+ else
+ fun_l24_n899(x)
+ end
+end
+
+def fun_l23_n601(x)
+ if (x < 1)
+ fun_l24_n357(x)
+ else
+ fun_l24_n88(x)
+ end
+end
+
+def fun_l23_n602(x)
+ if (x < 1)
+ fun_l24_n213(x)
+ else
+ fun_l24_n71(x)
+ end
+end
+
+def fun_l23_n603(x)
+ if (x < 1)
+ fun_l24_n299(x)
+ else
+ fun_l24_n283(x)
+ end
+end
+
+def fun_l23_n604(x)
+ if (x < 1)
+ fun_l24_n647(x)
+ else
+ fun_l24_n891(x)
+ end
+end
+
+def fun_l23_n605(x)
+ if (x < 1)
+ fun_l24_n86(x)
+ else
+ fun_l24_n581(x)
+ end
+end
+
+def fun_l23_n606(x)
+ if (x < 1)
+ fun_l24_n749(x)
+ else
+ fun_l24_n780(x)
+ end
+end
+
+def fun_l23_n607(x)
+ if (x < 1)
+ fun_l24_n537(x)
+ else
+ fun_l24_n22(x)
+ end
+end
+
+def fun_l23_n608(x)
+ if (x < 1)
+ fun_l24_n535(x)
+ else
+ fun_l24_n379(x)
+ end
+end
+
+def fun_l23_n609(x)
+ if (x < 1)
+ fun_l24_n860(x)
+ else
+ fun_l24_n220(x)
+ end
+end
+
+def fun_l23_n610(x)
+ if (x < 1)
+ fun_l24_n366(x)
+ else
+ fun_l24_n216(x)
+ end
+end
+
+def fun_l23_n611(x)
+ if (x < 1)
+ fun_l24_n79(x)
+ else
+ fun_l24_n506(x)
+ end
+end
+
+def fun_l23_n612(x)
+ if (x < 1)
+ fun_l24_n600(x)
+ else
+ fun_l24_n367(x)
+ end
+end
+
+def fun_l23_n613(x)
+ if (x < 1)
+ fun_l24_n764(x)
+ else
+ fun_l24_n167(x)
+ end
+end
+
+def fun_l23_n614(x)
+ if (x < 1)
+ fun_l24_n113(x)
+ else
+ fun_l24_n398(x)
+ end
+end
+
+def fun_l23_n615(x)
+ if (x < 1)
+ fun_l24_n292(x)
+ else
+ fun_l24_n1(x)
+ end
+end
+
+def fun_l23_n616(x)
+ if (x < 1)
+ fun_l24_n523(x)
+ else
+ fun_l24_n344(x)
+ end
+end
+
+def fun_l23_n617(x)
+ if (x < 1)
+ fun_l24_n60(x)
+ else
+ fun_l24_n618(x)
+ end
+end
+
+def fun_l23_n618(x)
+ if (x < 1)
+ fun_l24_n252(x)
+ else
+ fun_l24_n718(x)
+ end
+end
+
+def fun_l23_n619(x)
+ if (x < 1)
+ fun_l24_n962(x)
+ else
+ fun_l24_n69(x)
+ end
+end
+
+def fun_l23_n620(x)
+ if (x < 1)
+ fun_l24_n10(x)
+ else
+ fun_l24_n87(x)
+ end
+end
+
+def fun_l23_n621(x)
+ if (x < 1)
+ fun_l24_n128(x)
+ else
+ fun_l24_n958(x)
+ end
+end
+
+def fun_l23_n622(x)
+ if (x < 1)
+ fun_l24_n775(x)
+ else
+ fun_l24_n205(x)
+ end
+end
+
+def fun_l23_n623(x)
+ if (x < 1)
+ fun_l24_n121(x)
+ else
+ fun_l24_n69(x)
+ end
+end
+
+def fun_l23_n624(x)
+ if (x < 1)
+ fun_l24_n768(x)
+ else
+ fun_l24_n439(x)
+ end
+end
+
+def fun_l23_n625(x)
+ if (x < 1)
+ fun_l24_n332(x)
+ else
+ fun_l24_n73(x)
+ end
+end
+
+def fun_l23_n626(x)
+ if (x < 1)
+ fun_l24_n735(x)
+ else
+ fun_l24_n651(x)
+ end
+end
+
+def fun_l23_n627(x)
+ if (x < 1)
+ fun_l24_n661(x)
+ else
+ fun_l24_n827(x)
+ end
+end
+
+def fun_l23_n628(x)
+ if (x < 1)
+ fun_l24_n607(x)
+ else
+ fun_l24_n343(x)
+ end
+end
+
+def fun_l23_n629(x)
+ if (x < 1)
+ fun_l24_n868(x)
+ else
+ fun_l24_n633(x)
+ end
+end
+
+def fun_l23_n630(x)
+ if (x < 1)
+ fun_l24_n321(x)
+ else
+ fun_l24_n44(x)
+ end
+end
+
+def fun_l23_n631(x)
+ if (x < 1)
+ fun_l24_n840(x)
+ else
+ fun_l24_n265(x)
+ end
+end
+
+def fun_l23_n632(x)
+ if (x < 1)
+ fun_l24_n710(x)
+ else
+ fun_l24_n343(x)
+ end
+end
+
+def fun_l23_n633(x)
+ if (x < 1)
+ fun_l24_n640(x)
+ else
+ fun_l24_n112(x)
+ end
+end
+
+def fun_l23_n634(x)
+ if (x < 1)
+ fun_l24_n237(x)
+ else
+ fun_l24_n83(x)
+ end
+end
+
+def fun_l23_n635(x)
+ if (x < 1)
+ fun_l24_n235(x)
+ else
+ fun_l24_n970(x)
+ end
+end
+
+def fun_l23_n636(x)
+ if (x < 1)
+ fun_l24_n576(x)
+ else
+ fun_l24_n891(x)
+ end
+end
+
+def fun_l23_n637(x)
+ if (x < 1)
+ fun_l24_n489(x)
+ else
+ fun_l24_n136(x)
+ end
+end
+
+def fun_l23_n638(x)
+ if (x < 1)
+ fun_l24_n532(x)
+ else
+ fun_l24_n150(x)
+ end
+end
+
+def fun_l23_n639(x)
+ if (x < 1)
+ fun_l24_n496(x)
+ else
+ fun_l24_n57(x)
+ end
+end
+
+def fun_l23_n640(x)
+ if (x < 1)
+ fun_l24_n857(x)
+ else
+ fun_l24_n564(x)
+ end
+end
+
+def fun_l23_n641(x)
+ if (x < 1)
+ fun_l24_n203(x)
+ else
+ fun_l24_n730(x)
+ end
+end
+
+def fun_l23_n642(x)
+ if (x < 1)
+ fun_l24_n38(x)
+ else
+ fun_l24_n388(x)
+ end
+end
+
+def fun_l23_n643(x)
+ if (x < 1)
+ fun_l24_n650(x)
+ else
+ fun_l24_n672(x)
+ end
+end
+
+def fun_l23_n644(x)
+ if (x < 1)
+ fun_l24_n842(x)
+ else
+ fun_l24_n473(x)
+ end
+end
+
+def fun_l23_n645(x)
+ if (x < 1)
+ fun_l24_n650(x)
+ else
+ fun_l24_n36(x)
+ end
+end
+
+def fun_l23_n646(x)
+ if (x < 1)
+ fun_l24_n25(x)
+ else
+ fun_l24_n696(x)
+ end
+end
+
+def fun_l23_n647(x)
+ if (x < 1)
+ fun_l24_n24(x)
+ else
+ fun_l24_n414(x)
+ end
+end
+
+def fun_l23_n648(x)
+ if (x < 1)
+ fun_l24_n778(x)
+ else
+ fun_l24_n794(x)
+ end
+end
+
+def fun_l23_n649(x)
+ if (x < 1)
+ fun_l24_n132(x)
+ else
+ fun_l24_n833(x)
+ end
+end
+
+def fun_l23_n650(x)
+ if (x < 1)
+ fun_l24_n718(x)
+ else
+ fun_l24_n327(x)
+ end
+end
+
+def fun_l23_n651(x)
+ if (x < 1)
+ fun_l24_n969(x)
+ else
+ fun_l24_n865(x)
+ end
+end
+
+def fun_l23_n652(x)
+ if (x < 1)
+ fun_l24_n904(x)
+ else
+ fun_l24_n4(x)
+ end
+end
+
+def fun_l23_n653(x)
+ if (x < 1)
+ fun_l24_n342(x)
+ else
+ fun_l24_n953(x)
+ end
+end
+
+def fun_l23_n654(x)
+ if (x < 1)
+ fun_l24_n393(x)
+ else
+ fun_l24_n175(x)
+ end
+end
+
+def fun_l23_n655(x)
+ if (x < 1)
+ fun_l24_n241(x)
+ else
+ fun_l24_n835(x)
+ end
+end
+
+def fun_l23_n656(x)
+ if (x < 1)
+ fun_l24_n326(x)
+ else
+ fun_l24_n294(x)
+ end
+end
+
+def fun_l23_n657(x)
+ if (x < 1)
+ fun_l24_n8(x)
+ else
+ fun_l24_n327(x)
+ end
+end
+
+def fun_l23_n658(x)
+ if (x < 1)
+ fun_l24_n859(x)
+ else
+ fun_l24_n138(x)
+ end
+end
+
+def fun_l23_n659(x)
+ if (x < 1)
+ fun_l24_n389(x)
+ else
+ fun_l24_n840(x)
+ end
+end
+
+def fun_l23_n660(x)
+ if (x < 1)
+ fun_l24_n171(x)
+ else
+ fun_l24_n731(x)
+ end
+end
+
+def fun_l23_n661(x)
+ if (x < 1)
+ fun_l24_n284(x)
+ else
+ fun_l24_n358(x)
+ end
+end
+
+def fun_l23_n662(x)
+ if (x < 1)
+ fun_l24_n329(x)
+ else
+ fun_l24_n459(x)
+ end
+end
+
+def fun_l23_n663(x)
+ if (x < 1)
+ fun_l24_n6(x)
+ else
+ fun_l24_n29(x)
+ end
+end
+
+def fun_l23_n664(x)
+ if (x < 1)
+ fun_l24_n324(x)
+ else
+ fun_l24_n58(x)
+ end
+end
+
+def fun_l23_n665(x)
+ if (x < 1)
+ fun_l24_n473(x)
+ else
+ fun_l24_n932(x)
+ end
+end
+
+def fun_l23_n666(x)
+ if (x < 1)
+ fun_l24_n425(x)
+ else
+ fun_l24_n49(x)
+ end
+end
+
+def fun_l23_n667(x)
+ if (x < 1)
+ fun_l24_n122(x)
+ else
+ fun_l24_n515(x)
+ end
+end
+
+def fun_l23_n668(x)
+ if (x < 1)
+ fun_l24_n883(x)
+ else
+ fun_l24_n383(x)
+ end
+end
+
+def fun_l23_n669(x)
+ if (x < 1)
+ fun_l24_n316(x)
+ else
+ fun_l24_n456(x)
+ end
+end
+
+def fun_l23_n670(x)
+ if (x < 1)
+ fun_l24_n812(x)
+ else
+ fun_l24_n625(x)
+ end
+end
+
+def fun_l23_n671(x)
+ if (x < 1)
+ fun_l24_n431(x)
+ else
+ fun_l24_n685(x)
+ end
+end
+
+def fun_l23_n672(x)
+ if (x < 1)
+ fun_l24_n68(x)
+ else
+ fun_l24_n112(x)
+ end
+end
+
+def fun_l23_n673(x)
+ if (x < 1)
+ fun_l24_n137(x)
+ else
+ fun_l24_n349(x)
+ end
+end
+
+def fun_l23_n674(x)
+ if (x < 1)
+ fun_l24_n629(x)
+ else
+ fun_l24_n165(x)
+ end
+end
+
+def fun_l23_n675(x)
+ if (x < 1)
+ fun_l24_n484(x)
+ else
+ fun_l24_n102(x)
+ end
+end
+
+def fun_l23_n676(x)
+ if (x < 1)
+ fun_l24_n641(x)
+ else
+ fun_l24_n912(x)
+ end
+end
+
+def fun_l23_n677(x)
+ if (x < 1)
+ fun_l24_n817(x)
+ else
+ fun_l24_n975(x)
+ end
+end
+
+def fun_l23_n678(x)
+ if (x < 1)
+ fun_l24_n510(x)
+ else
+ fun_l24_n346(x)
+ end
+end
+
+def fun_l23_n679(x)
+ if (x < 1)
+ fun_l24_n129(x)
+ else
+ fun_l24_n602(x)
+ end
+end
+
+def fun_l23_n680(x)
+ if (x < 1)
+ fun_l24_n991(x)
+ else
+ fun_l24_n406(x)
+ end
+end
+
+def fun_l23_n681(x)
+ if (x < 1)
+ fun_l24_n433(x)
+ else
+ fun_l24_n998(x)
+ end
+end
+
+def fun_l23_n682(x)
+ if (x < 1)
+ fun_l24_n645(x)
+ else
+ fun_l24_n275(x)
+ end
+end
+
+def fun_l23_n683(x)
+ if (x < 1)
+ fun_l24_n832(x)
+ else
+ fun_l24_n346(x)
+ end
+end
+
+def fun_l23_n684(x)
+ if (x < 1)
+ fun_l24_n769(x)
+ else
+ fun_l24_n927(x)
+ end
+end
+
+def fun_l23_n685(x)
+ if (x < 1)
+ fun_l24_n389(x)
+ else
+ fun_l24_n777(x)
+ end
+end
+
+def fun_l23_n686(x)
+ if (x < 1)
+ fun_l24_n658(x)
+ else
+ fun_l24_n184(x)
+ end
+end
+
+def fun_l23_n687(x)
+ if (x < 1)
+ fun_l24_n134(x)
+ else
+ fun_l24_n517(x)
+ end
+end
+
+def fun_l23_n688(x)
+ if (x < 1)
+ fun_l24_n49(x)
+ else
+ fun_l24_n392(x)
+ end
+end
+
+def fun_l23_n689(x)
+ if (x < 1)
+ fun_l24_n23(x)
+ else
+ fun_l24_n402(x)
+ end
+end
+
+def fun_l23_n690(x)
+ if (x < 1)
+ fun_l24_n719(x)
+ else
+ fun_l24_n529(x)
+ end
+end
+
+def fun_l23_n691(x)
+ if (x < 1)
+ fun_l24_n543(x)
+ else
+ fun_l24_n789(x)
+ end
+end
+
+def fun_l23_n692(x)
+ if (x < 1)
+ fun_l24_n850(x)
+ else
+ fun_l24_n50(x)
+ end
+end
+
+def fun_l23_n693(x)
+ if (x < 1)
+ fun_l24_n728(x)
+ else
+ fun_l24_n730(x)
+ end
+end
+
+def fun_l23_n694(x)
+ if (x < 1)
+ fun_l24_n810(x)
+ else
+ fun_l24_n999(x)
+ end
+end
+
+def fun_l23_n695(x)
+ if (x < 1)
+ fun_l24_n856(x)
+ else
+ fun_l24_n404(x)
+ end
+end
+
+def fun_l23_n696(x)
+ if (x < 1)
+ fun_l24_n405(x)
+ else
+ fun_l24_n275(x)
+ end
+end
+
+def fun_l23_n697(x)
+ if (x < 1)
+ fun_l24_n446(x)
+ else
+ fun_l24_n773(x)
+ end
+end
+
+def fun_l23_n698(x)
+ if (x < 1)
+ fun_l24_n509(x)
+ else
+ fun_l24_n146(x)
+ end
+end
+
+def fun_l23_n699(x)
+ if (x < 1)
+ fun_l24_n770(x)
+ else
+ fun_l24_n275(x)
+ end
+end
+
+def fun_l23_n700(x)
+ if (x < 1)
+ fun_l24_n222(x)
+ else
+ fun_l24_n60(x)
+ end
+end
+
+def fun_l23_n701(x)
+ if (x < 1)
+ fun_l24_n380(x)
+ else
+ fun_l24_n654(x)
+ end
+end
+
+def fun_l23_n702(x)
+ if (x < 1)
+ fun_l24_n417(x)
+ else
+ fun_l24_n221(x)
+ end
+end
+
+def fun_l23_n703(x)
+ if (x < 1)
+ fun_l24_n283(x)
+ else
+ fun_l24_n171(x)
+ end
+end
+
+def fun_l23_n704(x)
+ if (x < 1)
+ fun_l24_n822(x)
+ else
+ fun_l24_n72(x)
+ end
+end
+
+def fun_l23_n705(x)
+ if (x < 1)
+ fun_l24_n171(x)
+ else
+ fun_l24_n258(x)
+ end
+end
+
+def fun_l23_n706(x)
+ if (x < 1)
+ fun_l24_n147(x)
+ else
+ fun_l24_n518(x)
+ end
+end
+
+def fun_l23_n707(x)
+ if (x < 1)
+ fun_l24_n479(x)
+ else
+ fun_l24_n267(x)
+ end
+end
+
+def fun_l23_n708(x)
+ if (x < 1)
+ fun_l24_n424(x)
+ else
+ fun_l24_n517(x)
+ end
+end
+
+def fun_l23_n709(x)
+ if (x < 1)
+ fun_l24_n816(x)
+ else
+ fun_l24_n329(x)
+ end
+end
+
+def fun_l23_n710(x)
+ if (x < 1)
+ fun_l24_n870(x)
+ else
+ fun_l24_n185(x)
+ end
+end
+
+def fun_l23_n711(x)
+ if (x < 1)
+ fun_l24_n726(x)
+ else
+ fun_l24_n950(x)
+ end
+end
+
+def fun_l23_n712(x)
+ if (x < 1)
+ fun_l24_n473(x)
+ else
+ fun_l24_n179(x)
+ end
+end
+
+def fun_l23_n713(x)
+ if (x < 1)
+ fun_l24_n345(x)
+ else
+ fun_l24_n872(x)
+ end
+end
+
+def fun_l23_n714(x)
+ if (x < 1)
+ fun_l24_n757(x)
+ else
+ fun_l24_n364(x)
+ end
+end
+
+def fun_l23_n715(x)
+ if (x < 1)
+ fun_l24_n91(x)
+ else
+ fun_l24_n999(x)
+ end
+end
+
+def fun_l23_n716(x)
+ if (x < 1)
+ fun_l24_n308(x)
+ else
+ fun_l24_n281(x)
+ end
+end
+
+def fun_l23_n717(x)
+ if (x < 1)
+ fun_l24_n855(x)
+ else
+ fun_l24_n175(x)
+ end
+end
+
+def fun_l23_n718(x)
+ if (x < 1)
+ fun_l24_n251(x)
+ else
+ fun_l24_n532(x)
+ end
+end
+
+def fun_l23_n719(x)
+ if (x < 1)
+ fun_l24_n261(x)
+ else
+ fun_l24_n755(x)
+ end
+end
+
+def fun_l23_n720(x)
+ if (x < 1)
+ fun_l24_n182(x)
+ else
+ fun_l24_n115(x)
+ end
+end
+
+def fun_l23_n721(x)
+ if (x < 1)
+ fun_l24_n648(x)
+ else
+ fun_l24_n728(x)
+ end
+end
+
+def fun_l23_n722(x)
+ if (x < 1)
+ fun_l24_n552(x)
+ else
+ fun_l24_n549(x)
+ end
+end
+
+def fun_l23_n723(x)
+ if (x < 1)
+ fun_l24_n24(x)
+ else
+ fun_l24_n794(x)
+ end
+end
+
+def fun_l23_n724(x)
+ if (x < 1)
+ fun_l24_n242(x)
+ else
+ fun_l24_n980(x)
+ end
+end
+
+def fun_l23_n725(x)
+ if (x < 1)
+ fun_l24_n931(x)
+ else
+ fun_l24_n711(x)
+ end
+end
+
+def fun_l23_n726(x)
+ if (x < 1)
+ fun_l24_n659(x)
+ else
+ fun_l24_n981(x)
+ end
+end
+
+def fun_l23_n727(x)
+ if (x < 1)
+ fun_l24_n258(x)
+ else
+ fun_l24_n915(x)
+ end
+end
+
+def fun_l23_n728(x)
+ if (x < 1)
+ fun_l24_n544(x)
+ else
+ fun_l24_n89(x)
+ end
+end
+
+def fun_l23_n729(x)
+ if (x < 1)
+ fun_l24_n497(x)
+ else
+ fun_l24_n320(x)
+ end
+end
+
+def fun_l23_n730(x)
+ if (x < 1)
+ fun_l24_n936(x)
+ else
+ fun_l24_n209(x)
+ end
+end
+
+def fun_l23_n731(x)
+ if (x < 1)
+ fun_l24_n763(x)
+ else
+ fun_l24_n836(x)
+ end
+end
+
+def fun_l23_n732(x)
+ if (x < 1)
+ fun_l24_n60(x)
+ else
+ fun_l24_n867(x)
+ end
+end
+
+def fun_l23_n733(x)
+ if (x < 1)
+ fun_l24_n146(x)
+ else
+ fun_l24_n294(x)
+ end
+end
+
+def fun_l23_n734(x)
+ if (x < 1)
+ fun_l24_n905(x)
+ else
+ fun_l24_n463(x)
+ end
+end
+
+def fun_l23_n735(x)
+ if (x < 1)
+ fun_l24_n566(x)
+ else
+ fun_l24_n240(x)
+ end
+end
+
+def fun_l23_n736(x)
+ if (x < 1)
+ fun_l24_n321(x)
+ else
+ fun_l24_n597(x)
+ end
+end
+
+def fun_l23_n737(x)
+ if (x < 1)
+ fun_l24_n169(x)
+ else
+ fun_l24_n201(x)
+ end
+end
+
+def fun_l23_n738(x)
+ if (x < 1)
+ fun_l24_n157(x)
+ else
+ fun_l24_n349(x)
+ end
+end
+
+def fun_l23_n739(x)
+ if (x < 1)
+ fun_l24_n503(x)
+ else
+ fun_l24_n342(x)
+ end
+end
+
+def fun_l23_n740(x)
+ if (x < 1)
+ fun_l24_n974(x)
+ else
+ fun_l24_n467(x)
+ end
+end
+
+def fun_l23_n741(x)
+ if (x < 1)
+ fun_l24_n566(x)
+ else
+ fun_l24_n162(x)
+ end
+end
+
+def fun_l23_n742(x)
+ if (x < 1)
+ fun_l24_n19(x)
+ else
+ fun_l24_n750(x)
+ end
+end
+
+def fun_l23_n743(x)
+ if (x < 1)
+ fun_l24_n409(x)
+ else
+ fun_l24_n362(x)
+ end
+end
+
+def fun_l23_n744(x)
+ if (x < 1)
+ fun_l24_n281(x)
+ else
+ fun_l24_n439(x)
+ end
+end
+
+def fun_l23_n745(x)
+ if (x < 1)
+ fun_l24_n808(x)
+ else
+ fun_l24_n794(x)
+ end
+end
+
+def fun_l23_n746(x)
+ if (x < 1)
+ fun_l24_n173(x)
+ else
+ fun_l24_n892(x)
+ end
+end
+
+def fun_l23_n747(x)
+ if (x < 1)
+ fun_l24_n762(x)
+ else
+ fun_l24_n339(x)
+ end
+end
+
+def fun_l23_n748(x)
+ if (x < 1)
+ fun_l24_n319(x)
+ else
+ fun_l24_n753(x)
+ end
+end
+
+def fun_l23_n749(x)
+ if (x < 1)
+ fun_l24_n546(x)
+ else
+ fun_l24_n727(x)
+ end
+end
+
+def fun_l23_n750(x)
+ if (x < 1)
+ fun_l24_n699(x)
+ else
+ fun_l24_n173(x)
+ end
+end
+
+def fun_l23_n751(x)
+ if (x < 1)
+ fun_l24_n280(x)
+ else
+ fun_l24_n468(x)
+ end
+end
+
+def fun_l23_n752(x)
+ if (x < 1)
+ fun_l24_n910(x)
+ else
+ fun_l24_n500(x)
+ end
+end
+
+def fun_l23_n753(x)
+ if (x < 1)
+ fun_l24_n463(x)
+ else
+ fun_l24_n81(x)
+ end
+end
+
+def fun_l23_n754(x)
+ if (x < 1)
+ fun_l24_n769(x)
+ else
+ fun_l24_n584(x)
+ end
+end
+
+def fun_l23_n755(x)
+ if (x < 1)
+ fun_l24_n702(x)
+ else
+ fun_l24_n337(x)
+ end
+end
+
+def fun_l23_n756(x)
+ if (x < 1)
+ fun_l24_n12(x)
+ else
+ fun_l24_n335(x)
+ end
+end
+
+def fun_l23_n757(x)
+ if (x < 1)
+ fun_l24_n100(x)
+ else
+ fun_l24_n743(x)
+ end
+end
+
+def fun_l23_n758(x)
+ if (x < 1)
+ fun_l24_n865(x)
+ else
+ fun_l24_n594(x)
+ end
+end
+
+def fun_l23_n759(x)
+ if (x < 1)
+ fun_l24_n948(x)
+ else
+ fun_l24_n32(x)
+ end
+end
+
+def fun_l23_n760(x)
+ if (x < 1)
+ fun_l24_n487(x)
+ else
+ fun_l24_n72(x)
+ end
+end
+
+def fun_l23_n761(x)
+ if (x < 1)
+ fun_l24_n566(x)
+ else
+ fun_l24_n290(x)
+ end
+end
+
+def fun_l23_n762(x)
+ if (x < 1)
+ fun_l24_n896(x)
+ else
+ fun_l24_n840(x)
+ end
+end
+
+def fun_l23_n763(x)
+ if (x < 1)
+ fun_l24_n175(x)
+ else
+ fun_l24_n50(x)
+ end
+end
+
+def fun_l23_n764(x)
+ if (x < 1)
+ fun_l24_n107(x)
+ else
+ fun_l24_n446(x)
+ end
+end
+
+def fun_l23_n765(x)
+ if (x < 1)
+ fun_l24_n238(x)
+ else
+ fun_l24_n944(x)
+ end
+end
+
+def fun_l23_n766(x)
+ if (x < 1)
+ fun_l24_n999(x)
+ else
+ fun_l24_n419(x)
+ end
+end
+
+def fun_l23_n767(x)
+ if (x < 1)
+ fun_l24_n476(x)
+ else
+ fun_l24_n976(x)
+ end
+end
+
+def fun_l23_n768(x)
+ if (x < 1)
+ fun_l24_n328(x)
+ else
+ fun_l24_n782(x)
+ end
+end
+
+def fun_l23_n769(x)
+ if (x < 1)
+ fun_l24_n875(x)
+ else
+ fun_l24_n847(x)
+ end
+end
+
+def fun_l23_n770(x)
+ if (x < 1)
+ fun_l24_n391(x)
+ else
+ fun_l24_n123(x)
+ end
+end
+
+def fun_l23_n771(x)
+ if (x < 1)
+ fun_l24_n968(x)
+ else
+ fun_l24_n915(x)
+ end
+end
+
+def fun_l23_n772(x)
+ if (x < 1)
+ fun_l24_n883(x)
+ else
+ fun_l24_n604(x)
+ end
+end
+
+def fun_l23_n773(x)
+ if (x < 1)
+ fun_l24_n307(x)
+ else
+ fun_l24_n70(x)
+ end
+end
+
+def fun_l23_n774(x)
+ if (x < 1)
+ fun_l24_n615(x)
+ else
+ fun_l24_n115(x)
+ end
+end
+
+def fun_l23_n775(x)
+ if (x < 1)
+ fun_l24_n250(x)
+ else
+ fun_l24_n178(x)
+ end
+end
+
+def fun_l23_n776(x)
+ if (x < 1)
+ fun_l24_n982(x)
+ else
+ fun_l24_n570(x)
+ end
+end
+
+def fun_l23_n777(x)
+ if (x < 1)
+ fun_l24_n317(x)
+ else
+ fun_l24_n170(x)
+ end
+end
+
+def fun_l23_n778(x)
+ if (x < 1)
+ fun_l24_n895(x)
+ else
+ fun_l24_n147(x)
+ end
+end
+
+def fun_l23_n779(x)
+ if (x < 1)
+ fun_l24_n393(x)
+ else
+ fun_l24_n513(x)
+ end
+end
+
+def fun_l23_n780(x)
+ if (x < 1)
+ fun_l24_n635(x)
+ else
+ fun_l24_n161(x)
+ end
+end
+
+def fun_l23_n781(x)
+ if (x < 1)
+ fun_l24_n189(x)
+ else
+ fun_l24_n225(x)
+ end
+end
+
+def fun_l23_n782(x)
+ if (x < 1)
+ fun_l24_n205(x)
+ else
+ fun_l24_n620(x)
+ end
+end
+
+def fun_l23_n783(x)
+ if (x < 1)
+ fun_l24_n203(x)
+ else
+ fun_l24_n58(x)
+ end
+end
+
+def fun_l23_n784(x)
+ if (x < 1)
+ fun_l24_n198(x)
+ else
+ fun_l24_n948(x)
+ end
+end
+
+def fun_l23_n785(x)
+ if (x < 1)
+ fun_l24_n60(x)
+ else
+ fun_l24_n406(x)
+ end
+end
+
+def fun_l23_n786(x)
+ if (x < 1)
+ fun_l24_n538(x)
+ else
+ fun_l24_n992(x)
+ end
+end
+
+def fun_l23_n787(x)
+ if (x < 1)
+ fun_l24_n83(x)
+ else
+ fun_l24_n544(x)
+ end
+end
+
+def fun_l23_n788(x)
+ if (x < 1)
+ fun_l24_n964(x)
+ else
+ fun_l24_n939(x)
+ end
+end
+
+def fun_l23_n789(x)
+ if (x < 1)
+ fun_l24_n120(x)
+ else
+ fun_l24_n843(x)
+ end
+end
+
+def fun_l23_n790(x)
+ if (x < 1)
+ fun_l24_n772(x)
+ else
+ fun_l24_n111(x)
+ end
+end
+
+def fun_l23_n791(x)
+ if (x < 1)
+ fun_l24_n983(x)
+ else
+ fun_l24_n934(x)
+ end
+end
+
+def fun_l23_n792(x)
+ if (x < 1)
+ fun_l24_n475(x)
+ else
+ fun_l24_n532(x)
+ end
+end
+
+def fun_l23_n793(x)
+ if (x < 1)
+ fun_l24_n316(x)
+ else
+ fun_l24_n400(x)
+ end
+end
+
+def fun_l23_n794(x)
+ if (x < 1)
+ fun_l24_n103(x)
+ else
+ fun_l24_n19(x)
+ end
+end
+
+def fun_l23_n795(x)
+ if (x < 1)
+ fun_l24_n371(x)
+ else
+ fun_l24_n176(x)
+ end
+end
+
+def fun_l23_n796(x)
+ if (x < 1)
+ fun_l24_n469(x)
+ else
+ fun_l24_n958(x)
+ end
+end
+
+def fun_l23_n797(x)
+ if (x < 1)
+ fun_l24_n706(x)
+ else
+ fun_l24_n953(x)
+ end
+end
+
+def fun_l23_n798(x)
+ if (x < 1)
+ fun_l24_n384(x)
+ else
+ fun_l24_n439(x)
+ end
+end
+
+def fun_l23_n799(x)
+ if (x < 1)
+ fun_l24_n352(x)
+ else
+ fun_l24_n36(x)
+ end
+end
+
+def fun_l23_n800(x)
+ if (x < 1)
+ fun_l24_n390(x)
+ else
+ fun_l24_n963(x)
+ end
+end
+
+def fun_l23_n801(x)
+ if (x < 1)
+ fun_l24_n470(x)
+ else
+ fun_l24_n818(x)
+ end
+end
+
+def fun_l23_n802(x)
+ if (x < 1)
+ fun_l24_n262(x)
+ else
+ fun_l24_n893(x)
+ end
+end
+
+def fun_l23_n803(x)
+ if (x < 1)
+ fun_l24_n118(x)
+ else
+ fun_l24_n684(x)
+ end
+end
+
+def fun_l23_n804(x)
+ if (x < 1)
+ fun_l24_n484(x)
+ else
+ fun_l24_n520(x)
+ end
+end
+
+def fun_l23_n805(x)
+ if (x < 1)
+ fun_l24_n370(x)
+ else
+ fun_l24_n80(x)
+ end
+end
+
+def fun_l23_n806(x)
+ if (x < 1)
+ fun_l24_n326(x)
+ else
+ fun_l24_n436(x)
+ end
+end
+
+def fun_l23_n807(x)
+ if (x < 1)
+ fun_l24_n490(x)
+ else
+ fun_l24_n811(x)
+ end
+end
+
+def fun_l23_n808(x)
+ if (x < 1)
+ fun_l24_n447(x)
+ else
+ fun_l24_n150(x)
+ end
+end
+
+def fun_l23_n809(x)
+ if (x < 1)
+ fun_l24_n339(x)
+ else
+ fun_l24_n367(x)
+ end
+end
+
+def fun_l23_n810(x)
+ if (x < 1)
+ fun_l24_n221(x)
+ else
+ fun_l24_n505(x)
+ end
+end
+
+def fun_l23_n811(x)
+ if (x < 1)
+ fun_l24_n637(x)
+ else
+ fun_l24_n101(x)
+ end
+end
+
+def fun_l23_n812(x)
+ if (x < 1)
+ fun_l24_n83(x)
+ else
+ fun_l24_n538(x)
+ end
+end
+
+def fun_l23_n813(x)
+ if (x < 1)
+ fun_l24_n927(x)
+ else
+ fun_l24_n513(x)
+ end
+end
+
+def fun_l23_n814(x)
+ if (x < 1)
+ fun_l24_n496(x)
+ else
+ fun_l24_n290(x)
+ end
+end
+
+def fun_l23_n815(x)
+ if (x < 1)
+ fun_l24_n640(x)
+ else
+ fun_l24_n796(x)
+ end
+end
+
+def fun_l23_n816(x)
+ if (x < 1)
+ fun_l24_n999(x)
+ else
+ fun_l24_n54(x)
+ end
+end
+
+def fun_l23_n817(x)
+ if (x < 1)
+ fun_l24_n162(x)
+ else
+ fun_l24_n617(x)
+ end
+end
+
+def fun_l23_n818(x)
+ if (x < 1)
+ fun_l24_n118(x)
+ else
+ fun_l24_n187(x)
+ end
+end
+
+def fun_l23_n819(x)
+ if (x < 1)
+ fun_l24_n334(x)
+ else
+ fun_l24_n901(x)
+ end
+end
+
+def fun_l23_n820(x)
+ if (x < 1)
+ fun_l24_n939(x)
+ else
+ fun_l24_n896(x)
+ end
+end
+
+def fun_l23_n821(x)
+ if (x < 1)
+ fun_l24_n970(x)
+ else
+ fun_l24_n725(x)
+ end
+end
+
+def fun_l23_n822(x)
+ if (x < 1)
+ fun_l24_n357(x)
+ else
+ fun_l24_n771(x)
+ end
+end
+
+def fun_l23_n823(x)
+ if (x < 1)
+ fun_l24_n8(x)
+ else
+ fun_l24_n214(x)
+ end
+end
+
+def fun_l23_n824(x)
+ if (x < 1)
+ fun_l24_n412(x)
+ else
+ fun_l24_n145(x)
+ end
+end
+
+def fun_l23_n825(x)
+ if (x < 1)
+ fun_l24_n218(x)
+ else
+ fun_l24_n700(x)
+ end
+end
+
+def fun_l23_n826(x)
+ if (x < 1)
+ fun_l24_n945(x)
+ else
+ fun_l24_n523(x)
+ end
+end
+
+def fun_l23_n827(x)
+ if (x < 1)
+ fun_l24_n251(x)
+ else
+ fun_l24_n854(x)
+ end
+end
+
+def fun_l23_n828(x)
+ if (x < 1)
+ fun_l24_n704(x)
+ else
+ fun_l24_n879(x)
+ end
+end
+
+def fun_l23_n829(x)
+ if (x < 1)
+ fun_l24_n161(x)
+ else
+ fun_l24_n529(x)
+ end
+end
+
+def fun_l23_n830(x)
+ if (x < 1)
+ fun_l24_n751(x)
+ else
+ fun_l24_n409(x)
+ end
+end
+
+def fun_l23_n831(x)
+ if (x < 1)
+ fun_l24_n883(x)
+ else
+ fun_l24_n1(x)
+ end
+end
+
+def fun_l23_n832(x)
+ if (x < 1)
+ fun_l24_n135(x)
+ else
+ fun_l24_n738(x)
+ end
+end
+
+def fun_l23_n833(x)
+ if (x < 1)
+ fun_l24_n507(x)
+ else
+ fun_l24_n727(x)
+ end
+end
+
+def fun_l23_n834(x)
+ if (x < 1)
+ fun_l24_n677(x)
+ else
+ fun_l24_n602(x)
+ end
+end
+
+def fun_l23_n835(x)
+ if (x < 1)
+ fun_l24_n197(x)
+ else
+ fun_l24_n481(x)
+ end
+end
+
+def fun_l23_n836(x)
+ if (x < 1)
+ fun_l24_n39(x)
+ else
+ fun_l24_n149(x)
+ end
+end
+
+def fun_l23_n837(x)
+ if (x < 1)
+ fun_l24_n950(x)
+ else
+ fun_l24_n455(x)
+ end
+end
+
+def fun_l23_n838(x)
+ if (x < 1)
+ fun_l24_n718(x)
+ else
+ fun_l24_n264(x)
+ end
+end
+
+def fun_l23_n839(x)
+ if (x < 1)
+ fun_l24_n831(x)
+ else
+ fun_l24_n576(x)
+ end
+end
+
+def fun_l23_n840(x)
+ if (x < 1)
+ fun_l24_n813(x)
+ else
+ fun_l24_n564(x)
+ end
+end
+
+def fun_l23_n841(x)
+ if (x < 1)
+ fun_l24_n537(x)
+ else
+ fun_l24_n880(x)
+ end
+end
+
+def fun_l23_n842(x)
+ if (x < 1)
+ fun_l24_n958(x)
+ else
+ fun_l24_n963(x)
+ end
+end
+
+def fun_l23_n843(x)
+ if (x < 1)
+ fun_l24_n879(x)
+ else
+ fun_l24_n281(x)
+ end
+end
+
+def fun_l23_n844(x)
+ if (x < 1)
+ fun_l24_n138(x)
+ else
+ fun_l24_n562(x)
+ end
+end
+
+def fun_l23_n845(x)
+ if (x < 1)
+ fun_l24_n804(x)
+ else
+ fun_l24_n283(x)
+ end
+end
+
+def fun_l23_n846(x)
+ if (x < 1)
+ fun_l24_n253(x)
+ else
+ fun_l24_n339(x)
+ end
+end
+
+def fun_l23_n847(x)
+ if (x < 1)
+ fun_l24_n99(x)
+ else
+ fun_l24_n623(x)
+ end
+end
+
+def fun_l23_n848(x)
+ if (x < 1)
+ fun_l24_n955(x)
+ else
+ fun_l24_n121(x)
+ end
+end
+
+def fun_l23_n849(x)
+ if (x < 1)
+ fun_l24_n437(x)
+ else
+ fun_l24_n387(x)
+ end
+end
+
+def fun_l23_n850(x)
+ if (x < 1)
+ fun_l24_n19(x)
+ else
+ fun_l24_n790(x)
+ end
+end
+
+def fun_l23_n851(x)
+ if (x < 1)
+ fun_l24_n11(x)
+ else
+ fun_l24_n931(x)
+ end
+end
+
+def fun_l23_n852(x)
+ if (x < 1)
+ fun_l24_n506(x)
+ else
+ fun_l24_n162(x)
+ end
+end
+
+def fun_l23_n853(x)
+ if (x < 1)
+ fun_l24_n262(x)
+ else
+ fun_l24_n1(x)
+ end
+end
+
+def fun_l23_n854(x)
+ if (x < 1)
+ fun_l24_n275(x)
+ else
+ fun_l24_n549(x)
+ end
+end
+
+def fun_l23_n855(x)
+ if (x < 1)
+ fun_l24_n865(x)
+ else
+ fun_l24_n472(x)
+ end
+end
+
+def fun_l23_n856(x)
+ if (x < 1)
+ fun_l24_n270(x)
+ else
+ fun_l24_n312(x)
+ end
+end
+
+def fun_l23_n857(x)
+ if (x < 1)
+ fun_l24_n261(x)
+ else
+ fun_l24_n240(x)
+ end
+end
+
+def fun_l23_n858(x)
+ if (x < 1)
+ fun_l24_n166(x)
+ else
+ fun_l24_n996(x)
+ end
+end
+
+def fun_l23_n859(x)
+ if (x < 1)
+ fun_l24_n653(x)
+ else
+ fun_l24_n464(x)
+ end
+end
+
+def fun_l23_n860(x)
+ if (x < 1)
+ fun_l24_n446(x)
+ else
+ fun_l24_n706(x)
+ end
+end
+
+def fun_l23_n861(x)
+ if (x < 1)
+ fun_l24_n744(x)
+ else
+ fun_l24_n53(x)
+ end
+end
+
+def fun_l23_n862(x)
+ if (x < 1)
+ fun_l24_n983(x)
+ else
+ fun_l24_n188(x)
+ end
+end
+
+def fun_l23_n863(x)
+ if (x < 1)
+ fun_l24_n399(x)
+ else
+ fun_l24_n582(x)
+ end
+end
+
+def fun_l23_n864(x)
+ if (x < 1)
+ fun_l24_n392(x)
+ else
+ fun_l24_n937(x)
+ end
+end
+
+def fun_l23_n865(x)
+ if (x < 1)
+ fun_l24_n495(x)
+ else
+ fun_l24_n557(x)
+ end
+end
+
+def fun_l23_n866(x)
+ if (x < 1)
+ fun_l24_n94(x)
+ else
+ fun_l24_n295(x)
+ end
+end
+
+def fun_l23_n867(x)
+ if (x < 1)
+ fun_l24_n628(x)
+ else
+ fun_l24_n432(x)
+ end
+end
+
+def fun_l23_n868(x)
+ if (x < 1)
+ fun_l24_n386(x)
+ else
+ fun_l24_n385(x)
+ end
+end
+
+def fun_l23_n869(x)
+ if (x < 1)
+ fun_l24_n376(x)
+ else
+ fun_l24_n469(x)
+ end
+end
+
+def fun_l23_n870(x)
+ if (x < 1)
+ fun_l24_n74(x)
+ else
+ fun_l24_n712(x)
+ end
+end
+
+def fun_l23_n871(x)
+ if (x < 1)
+ fun_l24_n72(x)
+ else
+ fun_l24_n642(x)
+ end
+end
+
+def fun_l23_n872(x)
+ if (x < 1)
+ fun_l24_n937(x)
+ else
+ fun_l24_n751(x)
+ end
+end
+
+def fun_l23_n873(x)
+ if (x < 1)
+ fun_l24_n385(x)
+ else
+ fun_l24_n404(x)
+ end
+end
+
+def fun_l23_n874(x)
+ if (x < 1)
+ fun_l24_n336(x)
+ else
+ fun_l24_n226(x)
+ end
+end
+
+def fun_l23_n875(x)
+ if (x < 1)
+ fun_l24_n289(x)
+ else
+ fun_l24_n989(x)
+ end
+end
+
+def fun_l23_n876(x)
+ if (x < 1)
+ fun_l24_n45(x)
+ else
+ fun_l24_n279(x)
+ end
+end
+
+def fun_l23_n877(x)
+ if (x < 1)
+ fun_l24_n683(x)
+ else
+ fun_l24_n342(x)
+ end
+end
+
+def fun_l23_n878(x)
+ if (x < 1)
+ fun_l24_n279(x)
+ else
+ fun_l24_n600(x)
+ end
+end
+
+def fun_l23_n879(x)
+ if (x < 1)
+ fun_l24_n82(x)
+ else
+ fun_l24_n177(x)
+ end
+end
+
+def fun_l23_n880(x)
+ if (x < 1)
+ fun_l24_n167(x)
+ else
+ fun_l24_n912(x)
+ end
+end
+
+def fun_l23_n881(x)
+ if (x < 1)
+ fun_l24_n311(x)
+ else
+ fun_l24_n634(x)
+ end
+end
+
+def fun_l23_n882(x)
+ if (x < 1)
+ fun_l24_n127(x)
+ else
+ fun_l24_n661(x)
+ end
+end
+
+def fun_l23_n883(x)
+ if (x < 1)
+ fun_l24_n199(x)
+ else
+ fun_l24_n999(x)
+ end
+end
+
+def fun_l23_n884(x)
+ if (x < 1)
+ fun_l24_n525(x)
+ else
+ fun_l24_n948(x)
+ end
+end
+
+def fun_l23_n885(x)
+ if (x < 1)
+ fun_l24_n590(x)
+ else
+ fun_l24_n822(x)
+ end
+end
+
+def fun_l23_n886(x)
+ if (x < 1)
+ fun_l24_n811(x)
+ else
+ fun_l24_n975(x)
+ end
+end
+
+def fun_l23_n887(x)
+ if (x < 1)
+ fun_l24_n446(x)
+ else
+ fun_l24_n710(x)
+ end
+end
+
+def fun_l23_n888(x)
+ if (x < 1)
+ fun_l24_n31(x)
+ else
+ fun_l24_n92(x)
+ end
+end
+
+def fun_l23_n889(x)
+ if (x < 1)
+ fun_l24_n535(x)
+ else
+ fun_l24_n819(x)
+ end
+end
+
+def fun_l23_n890(x)
+ if (x < 1)
+ fun_l24_n526(x)
+ else
+ fun_l24_n207(x)
+ end
+end
+
+def fun_l23_n891(x)
+ if (x < 1)
+ fun_l24_n752(x)
+ else
+ fun_l24_n994(x)
+ end
+end
+
+def fun_l23_n892(x)
+ if (x < 1)
+ fun_l24_n758(x)
+ else
+ fun_l24_n292(x)
+ end
+end
+
+def fun_l23_n893(x)
+ if (x < 1)
+ fun_l24_n106(x)
+ else
+ fun_l24_n742(x)
+ end
+end
+
+def fun_l23_n894(x)
+ if (x < 1)
+ fun_l24_n385(x)
+ else
+ fun_l24_n562(x)
+ end
+end
+
+def fun_l23_n895(x)
+ if (x < 1)
+ fun_l24_n565(x)
+ else
+ fun_l24_n242(x)
+ end
+end
+
+def fun_l23_n896(x)
+ if (x < 1)
+ fun_l24_n570(x)
+ else
+ fun_l24_n241(x)
+ end
+end
+
+def fun_l23_n897(x)
+ if (x < 1)
+ fun_l24_n840(x)
+ else
+ fun_l24_n681(x)
+ end
+end
+
+def fun_l23_n898(x)
+ if (x < 1)
+ fun_l24_n524(x)
+ else
+ fun_l24_n9(x)
+ end
+end
+
+def fun_l23_n899(x)
+ if (x < 1)
+ fun_l24_n161(x)
+ else
+ fun_l24_n795(x)
+ end
+end
+
+def fun_l23_n900(x)
+ if (x < 1)
+ fun_l24_n64(x)
+ else
+ fun_l24_n447(x)
+ end
+end
+
+def fun_l23_n901(x)
+ if (x < 1)
+ fun_l24_n676(x)
+ else
+ fun_l24_n286(x)
+ end
+end
+
+def fun_l23_n902(x)
+ if (x < 1)
+ fun_l24_n623(x)
+ else
+ fun_l24_n298(x)
+ end
+end
+
+def fun_l23_n903(x)
+ if (x < 1)
+ fun_l24_n795(x)
+ else
+ fun_l24_n646(x)
+ end
+end
+
+def fun_l23_n904(x)
+ if (x < 1)
+ fun_l24_n746(x)
+ else
+ fun_l24_n7(x)
+ end
+end
+
+def fun_l23_n905(x)
+ if (x < 1)
+ fun_l24_n311(x)
+ else
+ fun_l24_n417(x)
+ end
+end
+
+def fun_l23_n906(x)
+ if (x < 1)
+ fun_l24_n338(x)
+ else
+ fun_l24_n592(x)
+ end
+end
+
+def fun_l23_n907(x)
+ if (x < 1)
+ fun_l24_n667(x)
+ else
+ fun_l24_n370(x)
+ end
+end
+
+def fun_l23_n908(x)
+ if (x < 1)
+ fun_l24_n444(x)
+ else
+ fun_l24_n703(x)
+ end
+end
+
+def fun_l23_n909(x)
+ if (x < 1)
+ fun_l24_n325(x)
+ else
+ fun_l24_n977(x)
+ end
+end
+
+def fun_l23_n910(x)
+ if (x < 1)
+ fun_l24_n994(x)
+ else
+ fun_l24_n765(x)
+ end
+end
+
+def fun_l23_n911(x)
+ if (x < 1)
+ fun_l24_n327(x)
+ else
+ fun_l24_n657(x)
+ end
+end
+
+def fun_l23_n912(x)
+ if (x < 1)
+ fun_l24_n932(x)
+ else
+ fun_l24_n769(x)
+ end
+end
+
+def fun_l23_n913(x)
+ if (x < 1)
+ fun_l24_n263(x)
+ else
+ fun_l24_n729(x)
+ end
+end
+
+def fun_l23_n914(x)
+ if (x < 1)
+ fun_l24_n248(x)
+ else
+ fun_l24_n412(x)
+ end
+end
+
+def fun_l23_n915(x)
+ if (x < 1)
+ fun_l24_n793(x)
+ else
+ fun_l24_n329(x)
+ end
+end
+
+def fun_l23_n916(x)
+ if (x < 1)
+ fun_l24_n7(x)
+ else
+ fun_l24_n460(x)
+ end
+end
+
+def fun_l23_n917(x)
+ if (x < 1)
+ fun_l24_n612(x)
+ else
+ fun_l24_n79(x)
+ end
+end
+
+def fun_l23_n918(x)
+ if (x < 1)
+ fun_l24_n450(x)
+ else
+ fun_l24_n950(x)
+ end
+end
+
+def fun_l23_n919(x)
+ if (x < 1)
+ fun_l24_n72(x)
+ else
+ fun_l24_n550(x)
+ end
+end
+
+def fun_l23_n920(x)
+ if (x < 1)
+ fun_l24_n73(x)
+ else
+ fun_l24_n339(x)
+ end
+end
+
+def fun_l23_n921(x)
+ if (x < 1)
+ fun_l24_n6(x)
+ else
+ fun_l24_n865(x)
+ end
+end
+
+def fun_l23_n922(x)
+ if (x < 1)
+ fun_l24_n507(x)
+ else
+ fun_l24_n475(x)
+ end
+end
+
+def fun_l23_n923(x)
+ if (x < 1)
+ fun_l24_n579(x)
+ else
+ fun_l24_n832(x)
+ end
+end
+
+def fun_l23_n924(x)
+ if (x < 1)
+ fun_l24_n681(x)
+ else
+ fun_l24_n253(x)
+ end
+end
+
+def fun_l23_n925(x)
+ if (x < 1)
+ fun_l24_n611(x)
+ else
+ fun_l24_n831(x)
+ end
+end
+
+def fun_l23_n926(x)
+ if (x < 1)
+ fun_l24_n371(x)
+ else
+ fun_l24_n236(x)
+ end
+end
+
+def fun_l23_n927(x)
+ if (x < 1)
+ fun_l24_n941(x)
+ else
+ fun_l24_n905(x)
+ end
+end
+
+def fun_l23_n928(x)
+ if (x < 1)
+ fun_l24_n616(x)
+ else
+ fun_l24_n421(x)
+ end
+end
+
+def fun_l23_n929(x)
+ if (x < 1)
+ fun_l24_n469(x)
+ else
+ fun_l24_n405(x)
+ end
+end
+
+def fun_l23_n930(x)
+ if (x < 1)
+ fun_l24_n584(x)
+ else
+ fun_l24_n694(x)
+ end
+end
+
+def fun_l23_n931(x)
+ if (x < 1)
+ fun_l24_n530(x)
+ else
+ fun_l24_n112(x)
+ end
+end
+
+def fun_l23_n932(x)
+ if (x < 1)
+ fun_l24_n115(x)
+ else
+ fun_l24_n667(x)
+ end
+end
+
+def fun_l23_n933(x)
+ if (x < 1)
+ fun_l24_n23(x)
+ else
+ fun_l24_n68(x)
+ end
+end
+
+def fun_l23_n934(x)
+ if (x < 1)
+ fun_l24_n215(x)
+ else
+ fun_l24_n459(x)
+ end
+end
+
+def fun_l23_n935(x)
+ if (x < 1)
+ fun_l24_n533(x)
+ else
+ fun_l24_n882(x)
+ end
+end
+
+def fun_l23_n936(x)
+ if (x < 1)
+ fun_l24_n918(x)
+ else
+ fun_l24_n522(x)
+ end
+end
+
+def fun_l23_n937(x)
+ if (x < 1)
+ fun_l24_n472(x)
+ else
+ fun_l24_n322(x)
+ end
+end
+
+def fun_l23_n938(x)
+ if (x < 1)
+ fun_l24_n528(x)
+ else
+ fun_l24_n937(x)
+ end
+end
+
+def fun_l23_n939(x)
+ if (x < 1)
+ fun_l24_n426(x)
+ else
+ fun_l24_n904(x)
+ end
+end
+
+def fun_l23_n940(x)
+ if (x < 1)
+ fun_l24_n259(x)
+ else
+ fun_l24_n350(x)
+ end
+end
+
+def fun_l23_n941(x)
+ if (x < 1)
+ fun_l24_n770(x)
+ else
+ fun_l24_n449(x)
+ end
+end
+
+def fun_l23_n942(x)
+ if (x < 1)
+ fun_l24_n159(x)
+ else
+ fun_l24_n312(x)
+ end
+end
+
+def fun_l23_n943(x)
+ if (x < 1)
+ fun_l24_n168(x)
+ else
+ fun_l24_n820(x)
+ end
+end
+
+def fun_l23_n944(x)
+ if (x < 1)
+ fun_l24_n861(x)
+ else
+ fun_l24_n395(x)
+ end
+end
+
+def fun_l23_n945(x)
+ if (x < 1)
+ fun_l24_n802(x)
+ else
+ fun_l24_n651(x)
+ end
+end
+
+def fun_l23_n946(x)
+ if (x < 1)
+ fun_l24_n519(x)
+ else
+ fun_l24_n736(x)
+ end
+end
+
+def fun_l23_n947(x)
+ if (x < 1)
+ fun_l24_n277(x)
+ else
+ fun_l24_n705(x)
+ end
+end
+
+def fun_l23_n948(x)
+ if (x < 1)
+ fun_l24_n658(x)
+ else
+ fun_l24_n983(x)
+ end
+end
+
+def fun_l23_n949(x)
+ if (x < 1)
+ fun_l24_n390(x)
+ else
+ fun_l24_n365(x)
+ end
+end
+
+def fun_l23_n950(x)
+ if (x < 1)
+ fun_l24_n362(x)
+ else
+ fun_l24_n895(x)
+ end
+end
+
+def fun_l23_n951(x)
+ if (x < 1)
+ fun_l24_n431(x)
+ else
+ fun_l24_n240(x)
+ end
+end
+
+def fun_l23_n952(x)
+ if (x < 1)
+ fun_l24_n87(x)
+ else
+ fun_l24_n923(x)
+ end
+end
+
+def fun_l23_n953(x)
+ if (x < 1)
+ fun_l24_n605(x)
+ else
+ fun_l24_n369(x)
+ end
+end
+
+def fun_l23_n954(x)
+ if (x < 1)
+ fun_l24_n659(x)
+ else
+ fun_l24_n485(x)
+ end
+end
+
+def fun_l23_n955(x)
+ if (x < 1)
+ fun_l24_n204(x)
+ else
+ fun_l24_n719(x)
+ end
+end
+
+def fun_l23_n956(x)
+ if (x < 1)
+ fun_l24_n752(x)
+ else
+ fun_l24_n522(x)
+ end
+end
+
+def fun_l23_n957(x)
+ if (x < 1)
+ fun_l24_n827(x)
+ else
+ fun_l24_n740(x)
+ end
+end
+
+def fun_l23_n958(x)
+ if (x < 1)
+ fun_l24_n476(x)
+ else
+ fun_l24_n766(x)
+ end
+end
+
+def fun_l23_n959(x)
+ if (x < 1)
+ fun_l24_n167(x)
+ else
+ fun_l24_n552(x)
+ end
+end
+
+def fun_l23_n960(x)
+ if (x < 1)
+ fun_l24_n352(x)
+ else
+ fun_l24_n147(x)
+ end
+end
+
+def fun_l23_n961(x)
+ if (x < 1)
+ fun_l24_n641(x)
+ else
+ fun_l24_n263(x)
+ end
+end
+
+def fun_l23_n962(x)
+ if (x < 1)
+ fun_l24_n2(x)
+ else
+ fun_l24_n819(x)
+ end
+end
+
+def fun_l23_n963(x)
+ if (x < 1)
+ fun_l24_n649(x)
+ else
+ fun_l24_n589(x)
+ end
+end
+
+def fun_l23_n964(x)
+ if (x < 1)
+ fun_l24_n351(x)
+ else
+ fun_l24_n170(x)
+ end
+end
+
+def fun_l23_n965(x)
+ if (x < 1)
+ fun_l24_n913(x)
+ else
+ fun_l24_n141(x)
+ end
+end
+
+def fun_l23_n966(x)
+ if (x < 1)
+ fun_l24_n230(x)
+ else
+ fun_l24_n438(x)
+ end
+end
+
+def fun_l23_n967(x)
+ if (x < 1)
+ fun_l24_n649(x)
+ else
+ fun_l24_n867(x)
+ end
+end
+
+def fun_l23_n968(x)
+ if (x < 1)
+ fun_l24_n877(x)
+ else
+ fun_l24_n341(x)
+ end
+end
+
+def fun_l23_n969(x)
+ if (x < 1)
+ fun_l24_n802(x)
+ else
+ fun_l24_n409(x)
+ end
+end
+
+def fun_l23_n970(x)
+ if (x < 1)
+ fun_l24_n388(x)
+ else
+ fun_l24_n521(x)
+ end
+end
+
+def fun_l23_n971(x)
+ if (x < 1)
+ fun_l24_n533(x)
+ else
+ fun_l24_n856(x)
+ end
+end
+
+def fun_l23_n972(x)
+ if (x < 1)
+ fun_l24_n409(x)
+ else
+ fun_l24_n119(x)
+ end
+end
+
+def fun_l23_n973(x)
+ if (x < 1)
+ fun_l24_n774(x)
+ else
+ fun_l24_n561(x)
+ end
+end
+
+def fun_l23_n974(x)
+ if (x < 1)
+ fun_l24_n96(x)
+ else
+ fun_l24_n629(x)
+ end
+end
+
+def fun_l23_n975(x)
+ if (x < 1)
+ fun_l24_n985(x)
+ else
+ fun_l24_n651(x)
+ end
+end
+
+def fun_l23_n976(x)
+ if (x < 1)
+ fun_l24_n977(x)
+ else
+ fun_l24_n274(x)
+ end
+end
+
+def fun_l23_n977(x)
+ if (x < 1)
+ fun_l24_n85(x)
+ else
+ fun_l24_n337(x)
+ end
+end
+
+def fun_l23_n978(x)
+ if (x < 1)
+ fun_l24_n312(x)
+ else
+ fun_l24_n990(x)
+ end
+end
+
+def fun_l23_n979(x)
+ if (x < 1)
+ fun_l24_n438(x)
+ else
+ fun_l24_n42(x)
+ end
+end
+
+def fun_l23_n980(x)
+ if (x < 1)
+ fun_l24_n341(x)
+ else
+ fun_l24_n27(x)
+ end
+end
+
+def fun_l23_n981(x)
+ if (x < 1)
+ fun_l24_n300(x)
+ else
+ fun_l24_n669(x)
+ end
+end
+
+def fun_l23_n982(x)
+ if (x < 1)
+ fun_l24_n586(x)
+ else
+ fun_l24_n822(x)
+ end
+end
+
+def fun_l23_n983(x)
+ if (x < 1)
+ fun_l24_n388(x)
+ else
+ fun_l24_n966(x)
+ end
+end
+
+def fun_l23_n984(x)
+ if (x < 1)
+ fun_l24_n661(x)
+ else
+ fun_l24_n66(x)
+ end
+end
+
+def fun_l23_n985(x)
+ if (x < 1)
+ fun_l24_n384(x)
+ else
+ fun_l24_n419(x)
+ end
+end
+
+def fun_l23_n986(x)
+ if (x < 1)
+ fun_l24_n698(x)
+ else
+ fun_l24_n961(x)
+ end
+end
+
+def fun_l23_n987(x)
+ if (x < 1)
+ fun_l24_n820(x)
+ else
+ fun_l24_n112(x)
+ end
+end
+
+def fun_l23_n988(x)
+ if (x < 1)
+ fun_l24_n976(x)
+ else
+ fun_l24_n232(x)
+ end
+end
+
+def fun_l23_n989(x)
+ if (x < 1)
+ fun_l24_n292(x)
+ else
+ fun_l24_n77(x)
+ end
+end
+
+def fun_l23_n990(x)
+ if (x < 1)
+ fun_l24_n572(x)
+ else
+ fun_l24_n524(x)
+ end
+end
+
+def fun_l23_n991(x)
+ if (x < 1)
+ fun_l24_n226(x)
+ else
+ fun_l24_n821(x)
+ end
+end
+
+def fun_l23_n992(x)
+ if (x < 1)
+ fun_l24_n12(x)
+ else
+ fun_l24_n891(x)
+ end
+end
+
+def fun_l23_n993(x)
+ if (x < 1)
+ fun_l24_n101(x)
+ else
+ fun_l24_n592(x)
+ end
+end
+
+def fun_l23_n994(x)
+ if (x < 1)
+ fun_l24_n796(x)
+ else
+ fun_l24_n594(x)
+ end
+end
+
+def fun_l23_n995(x)
+ if (x < 1)
+ fun_l24_n707(x)
+ else
+ fun_l24_n577(x)
+ end
+end
+
+def fun_l23_n996(x)
+ if (x < 1)
+ fun_l24_n123(x)
+ else
+ fun_l24_n730(x)
+ end
+end
+
+def fun_l23_n997(x)
+ if (x < 1)
+ fun_l24_n520(x)
+ else
+ fun_l24_n888(x)
+ end
+end
+
+def fun_l23_n998(x)
+ if (x < 1)
+ fun_l24_n165(x)
+ else
+ fun_l24_n576(x)
+ end
+end
+
+def fun_l23_n999(x)
+ if (x < 1)
+ fun_l24_n496(x)
+ else
+ fun_l24_n722(x)
+ end
+end
+
+def fun_l24_n0(x)
+ if (x < 1)
+ fun_l25_n357(x)
+ else
+ fun_l25_n144(x)
+ end
+end
+
+def fun_l24_n1(x)
+ if (x < 1)
+ fun_l25_n49(x)
+ else
+ fun_l25_n870(x)
+ end
+end
+
+def fun_l24_n2(x)
+ if (x < 1)
+ fun_l25_n547(x)
+ else
+ fun_l25_n357(x)
+ end
+end
+
+def fun_l24_n3(x)
+ if (x < 1)
+ fun_l25_n167(x)
+ else
+ fun_l25_n908(x)
+ end
+end
+
+def fun_l24_n4(x)
+ if (x < 1)
+ fun_l25_n943(x)
+ else
+ fun_l25_n882(x)
+ end
+end
+
+def fun_l24_n5(x)
+ if (x < 1)
+ fun_l25_n635(x)
+ else
+ fun_l25_n988(x)
+ end
+end
+
+def fun_l24_n6(x)
+ if (x < 1)
+ fun_l25_n648(x)
+ else
+ fun_l25_n62(x)
+ end
+end
+
+def fun_l24_n7(x)
+ if (x < 1)
+ fun_l25_n896(x)
+ else
+ fun_l25_n636(x)
+ end
+end
+
+def fun_l24_n8(x)
+ if (x < 1)
+ fun_l25_n666(x)
+ else
+ fun_l25_n50(x)
+ end
+end
+
+def fun_l24_n9(x)
+ if (x < 1)
+ fun_l25_n42(x)
+ else
+ fun_l25_n216(x)
+ end
+end
+
+def fun_l24_n10(x)
+ if (x < 1)
+ fun_l25_n979(x)
+ else
+ fun_l25_n27(x)
+ end
+end
+
+def fun_l24_n11(x)
+ if (x < 1)
+ fun_l25_n421(x)
+ else
+ fun_l25_n239(x)
+ end
+end
+
+def fun_l24_n12(x)
+ if (x < 1)
+ fun_l25_n465(x)
+ else
+ fun_l25_n483(x)
+ end
+end
+
+def fun_l24_n13(x)
+ if (x < 1)
+ fun_l25_n172(x)
+ else
+ fun_l25_n918(x)
+ end
+end
+
+def fun_l24_n14(x)
+ if (x < 1)
+ fun_l25_n130(x)
+ else
+ fun_l25_n144(x)
+ end
+end
+
+def fun_l24_n15(x)
+ if (x < 1)
+ fun_l25_n569(x)
+ else
+ fun_l25_n319(x)
+ end
+end
+
+def fun_l24_n16(x)
+ if (x < 1)
+ fun_l25_n54(x)
+ else
+ fun_l25_n253(x)
+ end
+end
+
+def fun_l24_n17(x)
+ if (x < 1)
+ fun_l25_n127(x)
+ else
+ fun_l25_n594(x)
+ end
+end
+
+def fun_l24_n18(x)
+ if (x < 1)
+ fun_l25_n94(x)
+ else
+ fun_l25_n486(x)
+ end
+end
+
+def fun_l24_n19(x)
+ if (x < 1)
+ fun_l25_n322(x)
+ else
+ fun_l25_n731(x)
+ end
+end
+
+def fun_l24_n20(x)
+ if (x < 1)
+ fun_l25_n828(x)
+ else
+ fun_l25_n410(x)
+ end
+end
+
+def fun_l24_n21(x)
+ if (x < 1)
+ fun_l25_n422(x)
+ else
+ fun_l25_n265(x)
+ end
+end
+
+def fun_l24_n22(x)
+ if (x < 1)
+ fun_l25_n259(x)
+ else
+ fun_l25_n902(x)
+ end
+end
+
+def fun_l24_n23(x)
+ if (x < 1)
+ fun_l25_n660(x)
+ else
+ fun_l25_n525(x)
+ end
+end
+
+def fun_l24_n24(x)
+ if (x < 1)
+ fun_l25_n898(x)
+ else
+ fun_l25_n231(x)
+ end
+end
+
+def fun_l24_n25(x)
+ if (x < 1)
+ fun_l25_n319(x)
+ else
+ fun_l25_n306(x)
+ end
+end
+
+def fun_l24_n26(x)
+ if (x < 1)
+ fun_l25_n447(x)
+ else
+ fun_l25_n110(x)
+ end
+end
+
+def fun_l24_n27(x)
+ if (x < 1)
+ fun_l25_n416(x)
+ else
+ fun_l25_n335(x)
+ end
+end
+
+def fun_l24_n28(x)
+ if (x < 1)
+ fun_l25_n132(x)
+ else
+ fun_l25_n549(x)
+ end
+end
+
+def fun_l24_n29(x)
+ if (x < 1)
+ fun_l25_n878(x)
+ else
+ fun_l25_n790(x)
+ end
+end
+
+def fun_l24_n30(x)
+ if (x < 1)
+ fun_l25_n205(x)
+ else
+ fun_l25_n328(x)
+ end
+end
+
+def fun_l24_n31(x)
+ if (x < 1)
+ fun_l25_n448(x)
+ else
+ fun_l25_n255(x)
+ end
+end
+
+def fun_l24_n32(x)
+ if (x < 1)
+ fun_l25_n800(x)
+ else
+ fun_l25_n254(x)
+ end
+end
+
+def fun_l24_n33(x)
+ if (x < 1)
+ fun_l25_n377(x)
+ else
+ fun_l25_n178(x)
+ end
+end
+
+def fun_l24_n34(x)
+ if (x < 1)
+ fun_l25_n317(x)
+ else
+ fun_l25_n271(x)
+ end
+end
+
+def fun_l24_n35(x)
+ if (x < 1)
+ fun_l25_n50(x)
+ else
+ fun_l25_n801(x)
+ end
+end
+
+def fun_l24_n36(x)
+ if (x < 1)
+ fun_l25_n720(x)
+ else
+ fun_l25_n267(x)
+ end
+end
+
+def fun_l24_n37(x)
+ if (x < 1)
+ fun_l25_n688(x)
+ else
+ fun_l25_n901(x)
+ end
+end
+
+def fun_l24_n38(x)
+ if (x < 1)
+ fun_l25_n752(x)
+ else
+ fun_l25_n541(x)
+ end
+end
+
+def fun_l24_n39(x)
+ if (x < 1)
+ fun_l25_n716(x)
+ else
+ fun_l25_n884(x)
+ end
+end
+
+def fun_l24_n40(x)
+ if (x < 1)
+ fun_l25_n138(x)
+ else
+ fun_l25_n536(x)
+ end
+end
+
+def fun_l24_n41(x)
+ if (x < 1)
+ fun_l25_n382(x)
+ else
+ fun_l25_n496(x)
+ end
+end
+
+def fun_l24_n42(x)
+ if (x < 1)
+ fun_l25_n729(x)
+ else
+ fun_l25_n443(x)
+ end
+end
+
+def fun_l24_n43(x)
+ if (x < 1)
+ fun_l25_n401(x)
+ else
+ fun_l25_n300(x)
+ end
+end
+
+def fun_l24_n44(x)
+ if (x < 1)
+ fun_l25_n695(x)
+ else
+ fun_l25_n139(x)
+ end
+end
+
+def fun_l24_n45(x)
+ if (x < 1)
+ fun_l25_n186(x)
+ else
+ fun_l25_n446(x)
+ end
+end
+
+def fun_l24_n46(x)
+ if (x < 1)
+ fun_l25_n102(x)
+ else
+ fun_l25_n415(x)
+ end
+end
+
+def fun_l24_n47(x)
+ if (x < 1)
+ fun_l25_n74(x)
+ else
+ fun_l25_n947(x)
+ end
+end
+
+def fun_l24_n48(x)
+ if (x < 1)
+ fun_l25_n720(x)
+ else
+ fun_l25_n873(x)
+ end
+end
+
+def fun_l24_n49(x)
+ if (x < 1)
+ fun_l25_n779(x)
+ else
+ fun_l25_n61(x)
+ end
+end
+
+def fun_l24_n50(x)
+ if (x < 1)
+ fun_l25_n889(x)
+ else
+ fun_l25_n620(x)
+ end
+end
+
+def fun_l24_n51(x)
+ if (x < 1)
+ fun_l25_n323(x)
+ else
+ fun_l25_n412(x)
+ end
+end
+
+def fun_l24_n52(x)
+ if (x < 1)
+ fun_l25_n986(x)
+ else
+ fun_l25_n950(x)
+ end
+end
+
+def fun_l24_n53(x)
+ if (x < 1)
+ fun_l25_n810(x)
+ else
+ fun_l25_n956(x)
+ end
+end
+
+def fun_l24_n54(x)
+ if (x < 1)
+ fun_l25_n89(x)
+ else
+ fun_l25_n110(x)
+ end
+end
+
+def fun_l24_n55(x)
+ if (x < 1)
+ fun_l25_n255(x)
+ else
+ fun_l25_n953(x)
+ end
+end
+
+def fun_l24_n56(x)
+ if (x < 1)
+ fun_l25_n200(x)
+ else
+ fun_l25_n366(x)
+ end
+end
+
+def fun_l24_n57(x)
+ if (x < 1)
+ fun_l25_n431(x)
+ else
+ fun_l25_n49(x)
+ end
+end
+
+def fun_l24_n58(x)
+ if (x < 1)
+ fun_l25_n705(x)
+ else
+ fun_l25_n362(x)
+ end
+end
+
+def fun_l24_n59(x)
+ if (x < 1)
+ fun_l25_n587(x)
+ else
+ fun_l25_n511(x)
+ end
+end
+
+def fun_l24_n60(x)
+ if (x < 1)
+ fun_l25_n72(x)
+ else
+ fun_l25_n560(x)
+ end
+end
+
+def fun_l24_n61(x)
+ if (x < 1)
+ fun_l25_n732(x)
+ else
+ fun_l25_n214(x)
+ end
+end
+
+def fun_l24_n62(x)
+ if (x < 1)
+ fun_l25_n348(x)
+ else
+ fun_l25_n70(x)
+ end
+end
+
+def fun_l24_n63(x)
+ if (x < 1)
+ fun_l25_n371(x)
+ else
+ fun_l25_n625(x)
+ end
+end
+
+def fun_l24_n64(x)
+ if (x < 1)
+ fun_l25_n204(x)
+ else
+ fun_l25_n249(x)
+ end
+end
+
+def fun_l24_n65(x)
+ if (x < 1)
+ fun_l25_n608(x)
+ else
+ fun_l25_n682(x)
+ end
+end
+
+def fun_l24_n66(x)
+ if (x < 1)
+ fun_l25_n450(x)
+ else
+ fun_l25_n951(x)
+ end
+end
+
+def fun_l24_n67(x)
+ if (x < 1)
+ fun_l25_n749(x)
+ else
+ fun_l25_n39(x)
+ end
+end
+
+def fun_l24_n68(x)
+ if (x < 1)
+ fun_l25_n169(x)
+ else
+ fun_l25_n801(x)
+ end
+end
+
+def fun_l24_n69(x)
+ if (x < 1)
+ fun_l25_n55(x)
+ else
+ fun_l25_n728(x)
+ end
+end
+
+def fun_l24_n70(x)
+ if (x < 1)
+ fun_l25_n115(x)
+ else
+ fun_l25_n689(x)
+ end
+end
+
+def fun_l24_n71(x)
+ if (x < 1)
+ fun_l25_n332(x)
+ else
+ fun_l25_n474(x)
+ end
+end
+
+def fun_l24_n72(x)
+ if (x < 1)
+ fun_l25_n846(x)
+ else
+ fun_l25_n808(x)
+ end
+end
+
+def fun_l24_n73(x)
+ if (x < 1)
+ fun_l25_n521(x)
+ else
+ fun_l25_n229(x)
+ end
+end
+
+def fun_l24_n74(x)
+ if (x < 1)
+ fun_l25_n307(x)
+ else
+ fun_l25_n992(x)
+ end
+end
+
+def fun_l24_n75(x)
+ if (x < 1)
+ fun_l25_n564(x)
+ else
+ fun_l25_n940(x)
+ end
+end
+
+def fun_l24_n76(x)
+ if (x < 1)
+ fun_l25_n348(x)
+ else
+ fun_l25_n453(x)
+ end
+end
+
+def fun_l24_n77(x)
+ if (x < 1)
+ fun_l25_n252(x)
+ else
+ fun_l25_n270(x)
+ end
+end
+
+def fun_l24_n78(x)
+ if (x < 1)
+ fun_l25_n333(x)
+ else
+ fun_l25_n980(x)
+ end
+end
+
+def fun_l24_n79(x)
+ if (x < 1)
+ fun_l25_n486(x)
+ else
+ fun_l25_n276(x)
+ end
+end
+
+def fun_l24_n80(x)
+ if (x < 1)
+ fun_l25_n45(x)
+ else
+ fun_l25_n930(x)
+ end
+end
+
+def fun_l24_n81(x)
+ if (x < 1)
+ fun_l25_n527(x)
+ else
+ fun_l25_n181(x)
+ end
+end
+
+def fun_l24_n82(x)
+ if (x < 1)
+ fun_l25_n768(x)
+ else
+ fun_l25_n869(x)
+ end
+end
+
+def fun_l24_n83(x)
+ if (x < 1)
+ fun_l25_n505(x)
+ else
+ fun_l25_n214(x)
+ end
+end
+
+def fun_l24_n84(x)
+ if (x < 1)
+ fun_l25_n41(x)
+ else
+ fun_l25_n873(x)
+ end
+end
+
+def fun_l24_n85(x)
+ if (x < 1)
+ fun_l25_n646(x)
+ else
+ fun_l25_n105(x)
+ end
+end
+
+def fun_l24_n86(x)
+ if (x < 1)
+ fun_l25_n675(x)
+ else
+ fun_l25_n830(x)
+ end
+end
+
+def fun_l24_n87(x)
+ if (x < 1)
+ fun_l25_n953(x)
+ else
+ fun_l25_n268(x)
+ end
+end
+
+def fun_l24_n88(x)
+ if (x < 1)
+ fun_l25_n36(x)
+ else
+ fun_l25_n31(x)
+ end
+end
+
+def fun_l24_n89(x)
+ if (x < 1)
+ fun_l25_n810(x)
+ else
+ fun_l25_n315(x)
+ end
+end
+
+def fun_l24_n90(x)
+ if (x < 1)
+ fun_l25_n100(x)
+ else
+ fun_l25_n882(x)
+ end
+end
+
+def fun_l24_n91(x)
+ if (x < 1)
+ fun_l25_n278(x)
+ else
+ fun_l25_n720(x)
+ end
+end
+
+def fun_l24_n92(x)
+ if (x < 1)
+ fun_l25_n472(x)
+ else
+ fun_l25_n615(x)
+ end
+end
+
+def fun_l24_n93(x)
+ if (x < 1)
+ fun_l25_n42(x)
+ else
+ fun_l25_n16(x)
+ end
+end
+
+def fun_l24_n94(x)
+ if (x < 1)
+ fun_l25_n905(x)
+ else
+ fun_l25_n988(x)
+ end
+end
+
+def fun_l24_n95(x)
+ if (x < 1)
+ fun_l25_n862(x)
+ else
+ fun_l25_n355(x)
+ end
+end
+
+def fun_l24_n96(x)
+ if (x < 1)
+ fun_l25_n931(x)
+ else
+ fun_l25_n539(x)
+ end
+end
+
+def fun_l24_n97(x)
+ if (x < 1)
+ fun_l25_n185(x)
+ else
+ fun_l25_n868(x)
+ end
+end
+
+def fun_l24_n98(x)
+ if (x < 1)
+ fun_l25_n276(x)
+ else
+ fun_l25_n591(x)
+ end
+end
+
+def fun_l24_n99(x)
+ if (x < 1)
+ fun_l25_n695(x)
+ else
+ fun_l25_n965(x)
+ end
+end
+
+def fun_l24_n100(x)
+ if (x < 1)
+ fun_l25_n293(x)
+ else
+ fun_l25_n127(x)
+ end
+end
+
+def fun_l24_n101(x)
+ if (x < 1)
+ fun_l25_n71(x)
+ else
+ fun_l25_n245(x)
+ end
+end
+
+def fun_l24_n102(x)
+ if (x < 1)
+ fun_l25_n397(x)
+ else
+ fun_l25_n893(x)
+ end
+end
+
+def fun_l24_n103(x)
+ if (x < 1)
+ fun_l25_n191(x)
+ else
+ fun_l25_n101(x)
+ end
+end
+
+def fun_l24_n104(x)
+ if (x < 1)
+ fun_l25_n982(x)
+ else
+ fun_l25_n101(x)
+ end
+end
+
+def fun_l24_n105(x)
+ if (x < 1)
+ fun_l25_n385(x)
+ else
+ fun_l25_n651(x)
+ end
+end
+
+def fun_l24_n106(x)
+ if (x < 1)
+ fun_l25_n577(x)
+ else
+ fun_l25_n241(x)
+ end
+end
+
+def fun_l24_n107(x)
+ if (x < 1)
+ fun_l25_n219(x)
+ else
+ fun_l25_n92(x)
+ end
+end
+
+def fun_l24_n108(x)
+ if (x < 1)
+ fun_l25_n202(x)
+ else
+ fun_l25_n133(x)
+ end
+end
+
+def fun_l24_n109(x)
+ if (x < 1)
+ fun_l25_n706(x)
+ else
+ fun_l25_n970(x)
+ end
+end
+
+def fun_l24_n110(x)
+ if (x < 1)
+ fun_l25_n948(x)
+ else
+ fun_l25_n595(x)
+ end
+end
+
+def fun_l24_n111(x)
+ if (x < 1)
+ fun_l25_n775(x)
+ else
+ fun_l25_n609(x)
+ end
+end
+
+def fun_l24_n112(x)
+ if (x < 1)
+ fun_l25_n905(x)
+ else
+ fun_l25_n11(x)
+ end
+end
+
+def fun_l24_n113(x)
+ if (x < 1)
+ fun_l25_n730(x)
+ else
+ fun_l25_n826(x)
+ end
+end
+
+def fun_l24_n114(x)
+ if (x < 1)
+ fun_l25_n403(x)
+ else
+ fun_l25_n562(x)
+ end
+end
+
+def fun_l24_n115(x)
+ if (x < 1)
+ fun_l25_n272(x)
+ else
+ fun_l25_n844(x)
+ end
+end
+
+def fun_l24_n116(x)
+ if (x < 1)
+ fun_l25_n907(x)
+ else
+ fun_l25_n797(x)
+ end
+end
+
+def fun_l24_n117(x)
+ if (x < 1)
+ fun_l25_n910(x)
+ else
+ fun_l25_n632(x)
+ end
+end
+
+def fun_l24_n118(x)
+ if (x < 1)
+ fun_l25_n570(x)
+ else
+ fun_l25_n645(x)
+ end
+end
+
+def fun_l24_n119(x)
+ if (x < 1)
+ fun_l25_n930(x)
+ else
+ fun_l25_n31(x)
+ end
+end
+
+def fun_l24_n120(x)
+ if (x < 1)
+ fun_l25_n228(x)
+ else
+ fun_l25_n340(x)
+ end
+end
+
+def fun_l24_n121(x)
+ if (x < 1)
+ fun_l25_n891(x)
+ else
+ fun_l25_n395(x)
+ end
+end
+
+def fun_l24_n122(x)
+ if (x < 1)
+ fun_l25_n340(x)
+ else
+ fun_l25_n966(x)
+ end
+end
+
+def fun_l24_n123(x)
+ if (x < 1)
+ fun_l25_n835(x)
+ else
+ fun_l25_n407(x)
+ end
+end
+
+def fun_l24_n124(x)
+ if (x < 1)
+ fun_l25_n156(x)
+ else
+ fun_l25_n151(x)
+ end
+end
+
+def fun_l24_n125(x)
+ if (x < 1)
+ fun_l25_n912(x)
+ else
+ fun_l25_n733(x)
+ end
+end
+
+def fun_l24_n126(x)
+ if (x < 1)
+ fun_l25_n385(x)
+ else
+ fun_l25_n406(x)
+ end
+end
+
+def fun_l24_n127(x)
+ if (x < 1)
+ fun_l25_n662(x)
+ else
+ fun_l25_n932(x)
+ end
+end
+
+def fun_l24_n128(x)
+ if (x < 1)
+ fun_l25_n418(x)
+ else
+ fun_l25_n445(x)
+ end
+end
+
+def fun_l24_n129(x)
+ if (x < 1)
+ fun_l25_n659(x)
+ else
+ fun_l25_n518(x)
+ end
+end
+
+def fun_l24_n130(x)
+ if (x < 1)
+ fun_l25_n784(x)
+ else
+ fun_l25_n342(x)
+ end
+end
+
+def fun_l24_n131(x)
+ if (x < 1)
+ fun_l25_n184(x)
+ else
+ fun_l25_n316(x)
+ end
+end
+
+def fun_l24_n132(x)
+ if (x < 1)
+ fun_l25_n76(x)
+ else
+ fun_l25_n156(x)
+ end
+end
+
+def fun_l24_n133(x)
+ if (x < 1)
+ fun_l25_n355(x)
+ else
+ fun_l25_n430(x)
+ end
+end
+
+def fun_l24_n134(x)
+ if (x < 1)
+ fun_l25_n643(x)
+ else
+ fun_l25_n109(x)
+ end
+end
+
+def fun_l24_n135(x)
+ if (x < 1)
+ fun_l25_n277(x)
+ else
+ fun_l25_n76(x)
+ end
+end
+
+def fun_l24_n136(x)
+ if (x < 1)
+ fun_l25_n898(x)
+ else
+ fun_l25_n870(x)
+ end
+end
+
+def fun_l24_n137(x)
+ if (x < 1)
+ fun_l25_n275(x)
+ else
+ fun_l25_n762(x)
+ end
+end
+
+def fun_l24_n138(x)
+ if (x < 1)
+ fun_l25_n109(x)
+ else
+ fun_l25_n913(x)
+ end
+end
+
+def fun_l24_n139(x)
+ if (x < 1)
+ fun_l25_n731(x)
+ else
+ fun_l25_n767(x)
+ end
+end
+
+def fun_l24_n140(x)
+ if (x < 1)
+ fun_l25_n385(x)
+ else
+ fun_l25_n743(x)
+ end
+end
+
+def fun_l24_n141(x)
+ if (x < 1)
+ fun_l25_n518(x)
+ else
+ fun_l25_n185(x)
+ end
+end
+
+def fun_l24_n142(x)
+ if (x < 1)
+ fun_l25_n656(x)
+ else
+ fun_l25_n614(x)
+ end
+end
+
+def fun_l24_n143(x)
+ if (x < 1)
+ fun_l25_n86(x)
+ else
+ fun_l25_n825(x)
+ end
+end
+
+def fun_l24_n144(x)
+ if (x < 1)
+ fun_l25_n982(x)
+ else
+ fun_l25_n970(x)
+ end
+end
+
+def fun_l24_n145(x)
+ if (x < 1)
+ fun_l25_n608(x)
+ else
+ fun_l25_n970(x)
+ end
+end
+
+def fun_l24_n146(x)
+ if (x < 1)
+ fun_l25_n273(x)
+ else
+ fun_l25_n4(x)
+ end
+end
+
+def fun_l24_n147(x)
+ if (x < 1)
+ fun_l25_n366(x)
+ else
+ fun_l25_n902(x)
+ end
+end
+
+def fun_l24_n148(x)
+ if (x < 1)
+ fun_l25_n682(x)
+ else
+ fun_l25_n210(x)
+ end
+end
+
+def fun_l24_n149(x)
+ if (x < 1)
+ fun_l25_n212(x)
+ else
+ fun_l25_n429(x)
+ end
+end
+
+def fun_l24_n150(x)
+ if (x < 1)
+ fun_l25_n680(x)
+ else
+ fun_l25_n959(x)
+ end
+end
+
+def fun_l24_n151(x)
+ if (x < 1)
+ fun_l25_n65(x)
+ else
+ fun_l25_n654(x)
+ end
+end
+
+def fun_l24_n152(x)
+ if (x < 1)
+ fun_l25_n465(x)
+ else
+ fun_l25_n24(x)
+ end
+end
+
+def fun_l24_n153(x)
+ if (x < 1)
+ fun_l25_n254(x)
+ else
+ fun_l25_n611(x)
+ end
+end
+
+def fun_l24_n154(x)
+ if (x < 1)
+ fun_l25_n525(x)
+ else
+ fun_l25_n25(x)
+ end
+end
+
+def fun_l24_n155(x)
+ if (x < 1)
+ fun_l25_n967(x)
+ else
+ fun_l25_n163(x)
+ end
+end
+
+def fun_l24_n156(x)
+ if (x < 1)
+ fun_l25_n191(x)
+ else
+ fun_l25_n603(x)
+ end
+end
+
+def fun_l24_n157(x)
+ if (x < 1)
+ fun_l25_n724(x)
+ else
+ fun_l25_n537(x)
+ end
+end
+
+def fun_l24_n158(x)
+ if (x < 1)
+ fun_l25_n115(x)
+ else
+ fun_l25_n967(x)
+ end
+end
+
+def fun_l24_n159(x)
+ if (x < 1)
+ fun_l25_n247(x)
+ else
+ fun_l25_n650(x)
+ end
+end
+
+def fun_l24_n160(x)
+ if (x < 1)
+ fun_l25_n681(x)
+ else
+ fun_l25_n754(x)
+ end
+end
+
+def fun_l24_n161(x)
+ if (x < 1)
+ fun_l25_n689(x)
+ else
+ fun_l25_n283(x)
+ end
+end
+
+def fun_l24_n162(x)
+ if (x < 1)
+ fun_l25_n697(x)
+ else
+ fun_l25_n262(x)
+ end
+end
+
+def fun_l24_n163(x)
+ if (x < 1)
+ fun_l25_n584(x)
+ else
+ fun_l25_n502(x)
+ end
+end
+
+def fun_l24_n164(x)
+ if (x < 1)
+ fun_l25_n949(x)
+ else
+ fun_l25_n738(x)
+ end
+end
+
+def fun_l24_n165(x)
+ if (x < 1)
+ fun_l25_n847(x)
+ else
+ fun_l25_n317(x)
+ end
+end
+
+def fun_l24_n166(x)
+ if (x < 1)
+ fun_l25_n827(x)
+ else
+ fun_l25_n831(x)
+ end
+end
+
+def fun_l24_n167(x)
+ if (x < 1)
+ fun_l25_n400(x)
+ else
+ fun_l25_n60(x)
+ end
+end
+
+def fun_l24_n168(x)
+ if (x < 1)
+ fun_l25_n411(x)
+ else
+ fun_l25_n333(x)
+ end
+end
+
+def fun_l24_n169(x)
+ if (x < 1)
+ fun_l25_n481(x)
+ else
+ fun_l25_n336(x)
+ end
+end
+
+def fun_l24_n170(x)
+ if (x < 1)
+ fun_l25_n551(x)
+ else
+ fun_l25_n184(x)
+ end
+end
+
+def fun_l24_n171(x)
+ if (x < 1)
+ fun_l25_n700(x)
+ else
+ fun_l25_n542(x)
+ end
+end
+
+def fun_l24_n172(x)
+ if (x < 1)
+ fun_l25_n496(x)
+ else
+ fun_l25_n494(x)
+ end
+end
+
+def fun_l24_n173(x)
+ if (x < 1)
+ fun_l25_n684(x)
+ else
+ fun_l25_n865(x)
+ end
+end
+
+def fun_l24_n174(x)
+ if (x < 1)
+ fun_l25_n304(x)
+ else
+ fun_l25_n641(x)
+ end
+end
+
+def fun_l24_n175(x)
+ if (x < 1)
+ fun_l25_n252(x)
+ else
+ fun_l25_n573(x)
+ end
+end
+
+def fun_l24_n176(x)
+ if (x < 1)
+ fun_l25_n463(x)
+ else
+ fun_l25_n596(x)
+ end
+end
+
+def fun_l24_n177(x)
+ if (x < 1)
+ fun_l25_n864(x)
+ else
+ fun_l25_n810(x)
+ end
+end
+
+def fun_l24_n178(x)
+ if (x < 1)
+ fun_l25_n182(x)
+ else
+ fun_l25_n900(x)
+ end
+end
+
+def fun_l24_n179(x)
+ if (x < 1)
+ fun_l25_n678(x)
+ else
+ fun_l25_n299(x)
+ end
+end
+
+def fun_l24_n180(x)
+ if (x < 1)
+ fun_l25_n423(x)
+ else
+ fun_l25_n791(x)
+ end
+end
+
+def fun_l24_n181(x)
+ if (x < 1)
+ fun_l25_n582(x)
+ else
+ fun_l25_n382(x)
+ end
+end
+
+def fun_l24_n182(x)
+ if (x < 1)
+ fun_l25_n498(x)
+ else
+ fun_l25_n247(x)
+ end
+end
+
+def fun_l24_n183(x)
+ if (x < 1)
+ fun_l25_n534(x)
+ else
+ fun_l25_n504(x)
+ end
+end
+
+def fun_l24_n184(x)
+ if (x < 1)
+ fun_l25_n947(x)
+ else
+ fun_l25_n708(x)
+ end
+end
+
+def fun_l24_n185(x)
+ if (x < 1)
+ fun_l25_n673(x)
+ else
+ fun_l25_n711(x)
+ end
+end
+
+def fun_l24_n186(x)
+ if (x < 1)
+ fun_l25_n155(x)
+ else
+ fun_l25_n233(x)
+ end
+end
+
+def fun_l24_n187(x)
+ if (x < 1)
+ fun_l25_n669(x)
+ else
+ fun_l25_n558(x)
+ end
+end
+
+def fun_l24_n188(x)
+ if (x < 1)
+ fun_l25_n307(x)
+ else
+ fun_l25_n839(x)
+ end
+end
+
+def fun_l24_n189(x)
+ if (x < 1)
+ fun_l25_n623(x)
+ else
+ fun_l25_n17(x)
+ end
+end
+
+def fun_l24_n190(x)
+ if (x < 1)
+ fun_l25_n468(x)
+ else
+ fun_l25_n391(x)
+ end
+end
+
+def fun_l24_n191(x)
+ if (x < 1)
+ fun_l25_n492(x)
+ else
+ fun_l25_n953(x)
+ end
+end
+
+def fun_l24_n192(x)
+ if (x < 1)
+ fun_l25_n644(x)
+ else
+ fun_l25_n724(x)
+ end
+end
+
+def fun_l24_n193(x)
+ if (x < 1)
+ fun_l25_n438(x)
+ else
+ fun_l25_n110(x)
+ end
+end
+
+def fun_l24_n194(x)
+ if (x < 1)
+ fun_l25_n763(x)
+ else
+ fun_l25_n0(x)
+ end
+end
+
+def fun_l24_n195(x)
+ if (x < 1)
+ fun_l25_n766(x)
+ else
+ fun_l25_n436(x)
+ end
+end
+
+def fun_l24_n196(x)
+ if (x < 1)
+ fun_l25_n646(x)
+ else
+ fun_l25_n264(x)
+ end
+end
+
+def fun_l24_n197(x)
+ if (x < 1)
+ fun_l25_n140(x)
+ else
+ fun_l25_n387(x)
+ end
+end
+
+def fun_l24_n198(x)
+ if (x < 1)
+ fun_l25_n890(x)
+ else
+ fun_l25_n756(x)
+ end
+end
+
+def fun_l24_n199(x)
+ if (x < 1)
+ fun_l25_n597(x)
+ else
+ fun_l25_n330(x)
+ end
+end
+
+def fun_l24_n200(x)
+ if (x < 1)
+ fun_l25_n656(x)
+ else
+ fun_l25_n292(x)
+ end
+end
+
+def fun_l24_n201(x)
+ if (x < 1)
+ fun_l25_n224(x)
+ else
+ fun_l25_n233(x)
+ end
+end
+
+def fun_l24_n202(x)
+ if (x < 1)
+ fun_l25_n153(x)
+ else
+ fun_l25_n926(x)
+ end
+end
+
+def fun_l24_n203(x)
+ if (x < 1)
+ fun_l25_n897(x)
+ else
+ fun_l25_n680(x)
+ end
+end
+
+def fun_l24_n204(x)
+ if (x < 1)
+ fun_l25_n610(x)
+ else
+ fun_l25_n154(x)
+ end
+end
+
+def fun_l24_n205(x)
+ if (x < 1)
+ fun_l25_n307(x)
+ else
+ fun_l25_n451(x)
+ end
+end
+
+def fun_l24_n206(x)
+ if (x < 1)
+ fun_l25_n138(x)
+ else
+ fun_l25_n875(x)
+ end
+end
+
+def fun_l24_n207(x)
+ if (x < 1)
+ fun_l25_n306(x)
+ else
+ fun_l25_n474(x)
+ end
+end
+
+def fun_l24_n208(x)
+ if (x < 1)
+ fun_l25_n771(x)
+ else
+ fun_l25_n105(x)
+ end
+end
+
+def fun_l24_n209(x)
+ if (x < 1)
+ fun_l25_n120(x)
+ else
+ fun_l25_n961(x)
+ end
+end
+
+def fun_l24_n210(x)
+ if (x < 1)
+ fun_l25_n455(x)
+ else
+ fun_l25_n244(x)
+ end
+end
+
+def fun_l24_n211(x)
+ if (x < 1)
+ fun_l25_n93(x)
+ else
+ fun_l25_n31(x)
+ end
+end
+
+def fun_l24_n212(x)
+ if (x < 1)
+ fun_l25_n69(x)
+ else
+ fun_l25_n39(x)
+ end
+end
+
+def fun_l24_n213(x)
+ if (x < 1)
+ fun_l25_n379(x)
+ else
+ fun_l25_n482(x)
+ end
+end
+
+def fun_l24_n214(x)
+ if (x < 1)
+ fun_l25_n839(x)
+ else
+ fun_l25_n669(x)
+ end
+end
+
+def fun_l24_n215(x)
+ if (x < 1)
+ fun_l25_n27(x)
+ else
+ fun_l25_n46(x)
+ end
+end
+
+def fun_l24_n216(x)
+ if (x < 1)
+ fun_l25_n290(x)
+ else
+ fun_l25_n908(x)
+ end
+end
+
+def fun_l24_n217(x)
+ if (x < 1)
+ fun_l25_n618(x)
+ else
+ fun_l25_n242(x)
+ end
+end
+
+def fun_l24_n218(x)
+ if (x < 1)
+ fun_l25_n42(x)
+ else
+ fun_l25_n674(x)
+ end
+end
+
+def fun_l24_n219(x)
+ if (x < 1)
+ fun_l25_n510(x)
+ else
+ fun_l25_n963(x)
+ end
+end
+
+def fun_l24_n220(x)
+ if (x < 1)
+ fun_l25_n345(x)
+ else
+ fun_l25_n666(x)
+ end
+end
+
+def fun_l24_n221(x)
+ if (x < 1)
+ fun_l25_n548(x)
+ else
+ fun_l25_n424(x)
+ end
+end
+
+def fun_l24_n222(x)
+ if (x < 1)
+ fun_l25_n387(x)
+ else
+ fun_l25_n30(x)
+ end
+end
+
+def fun_l24_n223(x)
+ if (x < 1)
+ fun_l25_n124(x)
+ else
+ fun_l25_n374(x)
+ end
+end
+
+def fun_l24_n224(x)
+ if (x < 1)
+ fun_l25_n200(x)
+ else
+ fun_l25_n108(x)
+ end
+end
+
+def fun_l24_n225(x)
+ if (x < 1)
+ fun_l25_n462(x)
+ else
+ fun_l25_n11(x)
+ end
+end
+
+def fun_l24_n226(x)
+ if (x < 1)
+ fun_l25_n930(x)
+ else
+ fun_l25_n791(x)
+ end
+end
+
+def fun_l24_n227(x)
+ if (x < 1)
+ fun_l25_n10(x)
+ else
+ fun_l25_n447(x)
+ end
+end
+
+def fun_l24_n228(x)
+ if (x < 1)
+ fun_l25_n858(x)
+ else
+ fun_l25_n472(x)
+ end
+end
+
+def fun_l24_n229(x)
+ if (x < 1)
+ fun_l25_n409(x)
+ else
+ fun_l25_n228(x)
+ end
+end
+
+def fun_l24_n230(x)
+ if (x < 1)
+ fun_l25_n82(x)
+ else
+ fun_l25_n665(x)
+ end
+end
+
+def fun_l24_n231(x)
+ if (x < 1)
+ fun_l25_n148(x)
+ else
+ fun_l25_n174(x)
+ end
+end
+
+def fun_l24_n232(x)
+ if (x < 1)
+ fun_l25_n785(x)
+ else
+ fun_l25_n996(x)
+ end
+end
+
+def fun_l24_n233(x)
+ if (x < 1)
+ fun_l25_n827(x)
+ else
+ fun_l25_n393(x)
+ end
+end
+
+def fun_l24_n234(x)
+ if (x < 1)
+ fun_l25_n619(x)
+ else
+ fun_l25_n361(x)
+ end
+end
+
+def fun_l24_n235(x)
+ if (x < 1)
+ fun_l25_n52(x)
+ else
+ fun_l25_n420(x)
+ end
+end
+
+def fun_l24_n236(x)
+ if (x < 1)
+ fun_l25_n355(x)
+ else
+ fun_l25_n561(x)
+ end
+end
+
+def fun_l24_n237(x)
+ if (x < 1)
+ fun_l25_n36(x)
+ else
+ fun_l25_n885(x)
+ end
+end
+
+def fun_l24_n238(x)
+ if (x < 1)
+ fun_l25_n15(x)
+ else
+ fun_l25_n19(x)
+ end
+end
+
+def fun_l24_n239(x)
+ if (x < 1)
+ fun_l25_n137(x)
+ else
+ fun_l25_n34(x)
+ end
+end
+
+def fun_l24_n240(x)
+ if (x < 1)
+ fun_l25_n776(x)
+ else
+ fun_l25_n199(x)
+ end
+end
+
+def fun_l24_n241(x)
+ if (x < 1)
+ fun_l25_n904(x)
+ else
+ fun_l25_n396(x)
+ end
+end
+
+def fun_l24_n242(x)
+ if (x < 1)
+ fun_l25_n122(x)
+ else
+ fun_l25_n720(x)
+ end
+end
+
+def fun_l24_n243(x)
+ if (x < 1)
+ fun_l25_n513(x)
+ else
+ fun_l25_n429(x)
+ end
+end
+
+def fun_l24_n244(x)
+ if (x < 1)
+ fun_l25_n289(x)
+ else
+ fun_l25_n265(x)
+ end
+end
+
+def fun_l24_n245(x)
+ if (x < 1)
+ fun_l25_n334(x)
+ else
+ fun_l25_n42(x)
+ end
+end
+
+def fun_l24_n246(x)
+ if (x < 1)
+ fun_l25_n55(x)
+ else
+ fun_l25_n67(x)
+ end
+end
+
+def fun_l24_n247(x)
+ if (x < 1)
+ fun_l25_n648(x)
+ else
+ fun_l25_n38(x)
+ end
+end
+
+def fun_l24_n248(x)
+ if (x < 1)
+ fun_l25_n904(x)
+ else
+ fun_l25_n732(x)
+ end
+end
+
+def fun_l24_n249(x)
+ if (x < 1)
+ fun_l25_n243(x)
+ else
+ fun_l25_n704(x)
+ end
+end
+
+def fun_l24_n250(x)
+ if (x < 1)
+ fun_l25_n513(x)
+ else
+ fun_l25_n326(x)
+ end
+end
+
+def fun_l24_n251(x)
+ if (x < 1)
+ fun_l25_n122(x)
+ else
+ fun_l25_n617(x)
+ end
+end
+
+def fun_l24_n252(x)
+ if (x < 1)
+ fun_l25_n837(x)
+ else
+ fun_l25_n891(x)
+ end
+end
+
+def fun_l24_n253(x)
+ if (x < 1)
+ fun_l25_n39(x)
+ else
+ fun_l25_n318(x)
+ end
+end
+
+def fun_l24_n254(x)
+ if (x < 1)
+ fun_l25_n79(x)
+ else
+ fun_l25_n195(x)
+ end
+end
+
+def fun_l24_n255(x)
+ if (x < 1)
+ fun_l25_n671(x)
+ else
+ fun_l25_n485(x)
+ end
+end
+
+def fun_l24_n256(x)
+ if (x < 1)
+ fun_l25_n775(x)
+ else
+ fun_l25_n187(x)
+ end
+end
+
+def fun_l24_n257(x)
+ if (x < 1)
+ fun_l25_n150(x)
+ else
+ fun_l25_n740(x)
+ end
+end
+
+def fun_l24_n258(x)
+ if (x < 1)
+ fun_l25_n131(x)
+ else
+ fun_l25_n960(x)
+ end
+end
+
+def fun_l24_n259(x)
+ if (x < 1)
+ fun_l25_n608(x)
+ else
+ fun_l25_n931(x)
+ end
+end
+
+def fun_l24_n260(x)
+ if (x < 1)
+ fun_l25_n846(x)
+ else
+ fun_l25_n278(x)
+ end
+end
+
+def fun_l24_n261(x)
+ if (x < 1)
+ fun_l25_n532(x)
+ else
+ fun_l25_n432(x)
+ end
+end
+
+def fun_l24_n262(x)
+ if (x < 1)
+ fun_l25_n367(x)
+ else
+ fun_l25_n847(x)
+ end
+end
+
+def fun_l24_n263(x)
+ if (x < 1)
+ fun_l25_n782(x)
+ else
+ fun_l25_n33(x)
+ end
+end
+
+def fun_l24_n264(x)
+ if (x < 1)
+ fun_l25_n822(x)
+ else
+ fun_l25_n711(x)
+ end
+end
+
+def fun_l24_n265(x)
+ if (x < 1)
+ fun_l25_n994(x)
+ else
+ fun_l25_n573(x)
+ end
+end
+
+def fun_l24_n266(x)
+ if (x < 1)
+ fun_l25_n234(x)
+ else
+ fun_l25_n617(x)
+ end
+end
+
+def fun_l24_n267(x)
+ if (x < 1)
+ fun_l25_n52(x)
+ else
+ fun_l25_n759(x)
+ end
+end
+
+def fun_l24_n268(x)
+ if (x < 1)
+ fun_l25_n161(x)
+ else
+ fun_l25_n167(x)
+ end
+end
+
+def fun_l24_n269(x)
+ if (x < 1)
+ fun_l25_n113(x)
+ else
+ fun_l25_n158(x)
+ end
+end
+
+def fun_l24_n270(x)
+ if (x < 1)
+ fun_l25_n151(x)
+ else
+ fun_l25_n127(x)
+ end
+end
+
+def fun_l24_n271(x)
+ if (x < 1)
+ fun_l25_n811(x)
+ else
+ fun_l25_n81(x)
+ end
+end
+
+def fun_l24_n272(x)
+ if (x < 1)
+ fun_l25_n622(x)
+ else
+ fun_l25_n796(x)
+ end
+end
+
+def fun_l24_n273(x)
+ if (x < 1)
+ fun_l25_n106(x)
+ else
+ fun_l25_n697(x)
+ end
+end
+
+def fun_l24_n274(x)
+ if (x < 1)
+ fun_l25_n63(x)
+ else
+ fun_l25_n599(x)
+ end
+end
+
+def fun_l24_n275(x)
+ if (x < 1)
+ fun_l25_n999(x)
+ else
+ fun_l25_n188(x)
+ end
+end
+
+def fun_l24_n276(x)
+ if (x < 1)
+ fun_l25_n491(x)
+ else
+ fun_l25_n614(x)
+ end
+end
+
+def fun_l24_n277(x)
+ if (x < 1)
+ fun_l25_n549(x)
+ else
+ fun_l25_n141(x)
+ end
+end
+
+def fun_l24_n278(x)
+ if (x < 1)
+ fun_l25_n442(x)
+ else
+ fun_l25_n900(x)
+ end
+end
+
+def fun_l24_n279(x)
+ if (x < 1)
+ fun_l25_n816(x)
+ else
+ fun_l25_n904(x)
+ end
+end
+
+def fun_l24_n280(x)
+ if (x < 1)
+ fun_l25_n508(x)
+ else
+ fun_l25_n569(x)
+ end
+end
+
+def fun_l24_n281(x)
+ if (x < 1)
+ fun_l25_n438(x)
+ else
+ fun_l25_n750(x)
+ end
+end
+
+def fun_l24_n282(x)
+ if (x < 1)
+ fun_l25_n984(x)
+ else
+ fun_l25_n573(x)
+ end
+end
+
+def fun_l24_n283(x)
+ if (x < 1)
+ fun_l25_n425(x)
+ else
+ fun_l25_n963(x)
+ end
+end
+
+def fun_l24_n284(x)
+ if (x < 1)
+ fun_l25_n213(x)
+ else
+ fun_l25_n344(x)
+ end
+end
+
+def fun_l24_n285(x)
+ if (x < 1)
+ fun_l25_n1(x)
+ else
+ fun_l25_n826(x)
+ end
+end
+
+def fun_l24_n286(x)
+ if (x < 1)
+ fun_l25_n297(x)
+ else
+ fun_l25_n266(x)
+ end
+end
+
+def fun_l24_n287(x)
+ if (x < 1)
+ fun_l25_n203(x)
+ else
+ fun_l25_n570(x)
+ end
+end
+
+def fun_l24_n288(x)
+ if (x < 1)
+ fun_l25_n849(x)
+ else
+ fun_l25_n336(x)
+ end
+end
+
+def fun_l24_n289(x)
+ if (x < 1)
+ fun_l25_n982(x)
+ else
+ fun_l25_n38(x)
+ end
+end
+
+def fun_l24_n290(x)
+ if (x < 1)
+ fun_l25_n687(x)
+ else
+ fun_l25_n906(x)
+ end
+end
+
+def fun_l24_n291(x)
+ if (x < 1)
+ fun_l25_n921(x)
+ else
+ fun_l25_n229(x)
+ end
+end
+
+def fun_l24_n292(x)
+ if (x < 1)
+ fun_l25_n494(x)
+ else
+ fun_l25_n138(x)
+ end
+end
+
+def fun_l24_n293(x)
+ if (x < 1)
+ fun_l25_n175(x)
+ else
+ fun_l25_n575(x)
+ end
+end
+
+def fun_l24_n294(x)
+ if (x < 1)
+ fun_l25_n126(x)
+ else
+ fun_l25_n902(x)
+ end
+end
+
+def fun_l24_n295(x)
+ if (x < 1)
+ fun_l25_n634(x)
+ else
+ fun_l25_n199(x)
+ end
+end
+
+def fun_l24_n296(x)
+ if (x < 1)
+ fun_l25_n929(x)
+ else
+ fun_l25_n468(x)
+ end
+end
+
+def fun_l24_n297(x)
+ if (x < 1)
+ fun_l25_n856(x)
+ else
+ fun_l25_n135(x)
+ end
+end
+
+def fun_l24_n298(x)
+ if (x < 1)
+ fun_l25_n655(x)
+ else
+ fun_l25_n545(x)
+ end
+end
+
+def fun_l24_n299(x)
+ if (x < 1)
+ fun_l25_n373(x)
+ else
+ fun_l25_n173(x)
+ end
+end
+
+def fun_l24_n300(x)
+ if (x < 1)
+ fun_l25_n874(x)
+ else
+ fun_l25_n85(x)
+ end
+end
+
+def fun_l24_n301(x)
+ if (x < 1)
+ fun_l25_n398(x)
+ else
+ fun_l25_n43(x)
+ end
+end
+
+def fun_l24_n302(x)
+ if (x < 1)
+ fun_l25_n995(x)
+ else
+ fun_l25_n890(x)
+ end
+end
+
+def fun_l24_n303(x)
+ if (x < 1)
+ fun_l25_n971(x)
+ else
+ fun_l25_n250(x)
+ end
+end
+
+def fun_l24_n304(x)
+ if (x < 1)
+ fun_l25_n752(x)
+ else
+ fun_l25_n681(x)
+ end
+end
+
+def fun_l24_n305(x)
+ if (x < 1)
+ fun_l25_n688(x)
+ else
+ fun_l25_n451(x)
+ end
+end
+
+def fun_l24_n306(x)
+ if (x < 1)
+ fun_l25_n167(x)
+ else
+ fun_l25_n784(x)
+ end
+end
+
+def fun_l24_n307(x)
+ if (x < 1)
+ fun_l25_n479(x)
+ else
+ fun_l25_n295(x)
+ end
+end
+
+def fun_l24_n308(x)
+ if (x < 1)
+ fun_l25_n779(x)
+ else
+ fun_l25_n472(x)
+ end
+end
+
+def fun_l24_n309(x)
+ if (x < 1)
+ fun_l25_n10(x)
+ else
+ fun_l25_n301(x)
+ end
+end
+
+def fun_l24_n310(x)
+ if (x < 1)
+ fun_l25_n197(x)
+ else
+ fun_l25_n152(x)
+ end
+end
+
+def fun_l24_n311(x)
+ if (x < 1)
+ fun_l25_n300(x)
+ else
+ fun_l25_n105(x)
+ end
+end
+
+def fun_l24_n312(x)
+ if (x < 1)
+ fun_l25_n1(x)
+ else
+ fun_l25_n956(x)
+ end
+end
+
+def fun_l24_n313(x)
+ if (x < 1)
+ fun_l25_n310(x)
+ else
+ fun_l25_n701(x)
+ end
+end
+
+def fun_l24_n314(x)
+ if (x < 1)
+ fun_l25_n0(x)
+ else
+ fun_l25_n58(x)
+ end
+end
+
+def fun_l24_n315(x)
+ if (x < 1)
+ fun_l25_n31(x)
+ else
+ fun_l25_n69(x)
+ end
+end
+
+def fun_l24_n316(x)
+ if (x < 1)
+ fun_l25_n967(x)
+ else
+ fun_l25_n130(x)
+ end
+end
+
+def fun_l24_n317(x)
+ if (x < 1)
+ fun_l25_n995(x)
+ else
+ fun_l25_n630(x)
+ end
+end
+
+def fun_l24_n318(x)
+ if (x < 1)
+ fun_l25_n349(x)
+ else
+ fun_l25_n916(x)
+ end
+end
+
+def fun_l24_n319(x)
+ if (x < 1)
+ fun_l25_n230(x)
+ else
+ fun_l25_n880(x)
+ end
+end
+
+def fun_l24_n320(x)
+ if (x < 1)
+ fun_l25_n452(x)
+ else
+ fun_l25_n316(x)
+ end
+end
+
+def fun_l24_n321(x)
+ if (x < 1)
+ fun_l25_n581(x)
+ else
+ fun_l25_n262(x)
+ end
+end
+
+def fun_l24_n322(x)
+ if (x < 1)
+ fun_l25_n70(x)
+ else
+ fun_l25_n674(x)
+ end
+end
+
+def fun_l24_n323(x)
+ if (x < 1)
+ fun_l25_n726(x)
+ else
+ fun_l25_n943(x)
+ end
+end
+
+def fun_l24_n324(x)
+ if (x < 1)
+ fun_l25_n779(x)
+ else
+ fun_l25_n209(x)
+ end
+end
+
+def fun_l24_n325(x)
+ if (x < 1)
+ fun_l25_n132(x)
+ else
+ fun_l25_n301(x)
+ end
+end
+
+def fun_l24_n326(x)
+ if (x < 1)
+ fun_l25_n255(x)
+ else
+ fun_l25_n154(x)
+ end
+end
+
+def fun_l24_n327(x)
+ if (x < 1)
+ fun_l25_n248(x)
+ else
+ fun_l25_n152(x)
+ end
+end
+
+def fun_l24_n328(x)
+ if (x < 1)
+ fun_l25_n536(x)
+ else
+ fun_l25_n703(x)
+ end
+end
+
+def fun_l24_n329(x)
+ if (x < 1)
+ fun_l25_n744(x)
+ else
+ fun_l25_n133(x)
+ end
+end
+
+def fun_l24_n330(x)
+ if (x < 1)
+ fun_l25_n455(x)
+ else
+ fun_l25_n576(x)
+ end
+end
+
+def fun_l24_n331(x)
+ if (x < 1)
+ fun_l25_n590(x)
+ else
+ fun_l25_n357(x)
+ end
+end
+
+def fun_l24_n332(x)
+ if (x < 1)
+ fun_l25_n151(x)
+ else
+ fun_l25_n969(x)
+ end
+end
+
+def fun_l24_n333(x)
+ if (x < 1)
+ fun_l25_n725(x)
+ else
+ fun_l25_n681(x)
+ end
+end
+
+def fun_l24_n334(x)
+ if (x < 1)
+ fun_l25_n157(x)
+ else
+ fun_l25_n643(x)
+ end
+end
+
+def fun_l24_n335(x)
+ if (x < 1)
+ fun_l25_n42(x)
+ else
+ fun_l25_n749(x)
+ end
+end
+
+def fun_l24_n336(x)
+ if (x < 1)
+ fun_l25_n831(x)
+ else
+ fun_l25_n126(x)
+ end
+end
+
+def fun_l24_n337(x)
+ if (x < 1)
+ fun_l25_n424(x)
+ else
+ fun_l25_n559(x)
+ end
+end
+
+def fun_l24_n338(x)
+ if (x < 1)
+ fun_l25_n897(x)
+ else
+ fun_l25_n89(x)
+ end
+end
+
+def fun_l24_n339(x)
+ if (x < 1)
+ fun_l25_n755(x)
+ else
+ fun_l25_n506(x)
+ end
+end
+
+def fun_l24_n340(x)
+ if (x < 1)
+ fun_l25_n387(x)
+ else
+ fun_l25_n631(x)
+ end
+end
+
+def fun_l24_n341(x)
+ if (x < 1)
+ fun_l25_n694(x)
+ else
+ fun_l25_n707(x)
+ end
+end
+
+def fun_l24_n342(x)
+ if (x < 1)
+ fun_l25_n65(x)
+ else
+ fun_l25_n687(x)
+ end
+end
+
+def fun_l24_n343(x)
+ if (x < 1)
+ fun_l25_n84(x)
+ else
+ fun_l25_n738(x)
+ end
+end
+
+def fun_l24_n344(x)
+ if (x < 1)
+ fun_l25_n729(x)
+ else
+ fun_l25_n639(x)
+ end
+end
+
+def fun_l24_n345(x)
+ if (x < 1)
+ fun_l25_n102(x)
+ else
+ fun_l25_n299(x)
+ end
+end
+
+def fun_l24_n346(x)
+ if (x < 1)
+ fun_l25_n604(x)
+ else
+ fun_l25_n94(x)
+ end
+end
+
+def fun_l24_n347(x)
+ if (x < 1)
+ fun_l25_n93(x)
+ else
+ fun_l25_n975(x)
+ end
+end
+
+def fun_l24_n348(x)
+ if (x < 1)
+ fun_l25_n124(x)
+ else
+ fun_l25_n927(x)
+ end
+end
+
+def fun_l24_n349(x)
+ if (x < 1)
+ fun_l25_n944(x)
+ else
+ fun_l25_n162(x)
+ end
+end
+
+def fun_l24_n350(x)
+ if (x < 1)
+ fun_l25_n623(x)
+ else
+ fun_l25_n5(x)
+ end
+end
+
+def fun_l24_n351(x)
+ if (x < 1)
+ fun_l25_n885(x)
+ else
+ fun_l25_n884(x)
+ end
+end
+
+def fun_l24_n352(x)
+ if (x < 1)
+ fun_l25_n1(x)
+ else
+ fun_l25_n366(x)
+ end
+end
+
+def fun_l24_n353(x)
+ if (x < 1)
+ fun_l25_n240(x)
+ else
+ fun_l25_n630(x)
+ end
+end
+
+def fun_l24_n354(x)
+ if (x < 1)
+ fun_l25_n232(x)
+ else
+ fun_l25_n758(x)
+ end
+end
+
+def fun_l24_n355(x)
+ if (x < 1)
+ fun_l25_n529(x)
+ else
+ fun_l25_n810(x)
+ end
+end
+
+def fun_l24_n356(x)
+ if (x < 1)
+ fun_l25_n438(x)
+ else
+ fun_l25_n146(x)
+ end
+end
+
+def fun_l24_n357(x)
+ if (x < 1)
+ fun_l25_n551(x)
+ else
+ fun_l25_n727(x)
+ end
+end
+
+def fun_l24_n358(x)
+ if (x < 1)
+ fun_l25_n764(x)
+ else
+ fun_l25_n379(x)
+ end
+end
+
+def fun_l24_n359(x)
+ if (x < 1)
+ fun_l25_n89(x)
+ else
+ fun_l25_n518(x)
+ end
+end
+
+def fun_l24_n360(x)
+ if (x < 1)
+ fun_l25_n567(x)
+ else
+ fun_l25_n98(x)
+ end
+end
+
+def fun_l24_n361(x)
+ if (x < 1)
+ fun_l25_n26(x)
+ else
+ fun_l25_n818(x)
+ end
+end
+
+def fun_l24_n362(x)
+ if (x < 1)
+ fun_l25_n205(x)
+ else
+ fun_l25_n460(x)
+ end
+end
+
+def fun_l24_n363(x)
+ if (x < 1)
+ fun_l25_n19(x)
+ else
+ fun_l25_n134(x)
+ end
+end
+
+def fun_l24_n364(x)
+ if (x < 1)
+ fun_l25_n221(x)
+ else
+ fun_l25_n391(x)
+ end
+end
+
+def fun_l24_n365(x)
+ if (x < 1)
+ fun_l25_n546(x)
+ else
+ fun_l25_n62(x)
+ end
+end
+
+def fun_l24_n366(x)
+ if (x < 1)
+ fun_l25_n412(x)
+ else
+ fun_l25_n593(x)
+ end
+end
+
+def fun_l24_n367(x)
+ if (x < 1)
+ fun_l25_n576(x)
+ else
+ fun_l25_n798(x)
+ end
+end
+
+def fun_l24_n368(x)
+ if (x < 1)
+ fun_l25_n528(x)
+ else
+ fun_l25_n575(x)
+ end
+end
+
+def fun_l24_n369(x)
+ if (x < 1)
+ fun_l25_n914(x)
+ else
+ fun_l25_n417(x)
+ end
+end
+
+def fun_l24_n370(x)
+ if (x < 1)
+ fun_l25_n397(x)
+ else
+ fun_l25_n684(x)
+ end
+end
+
+def fun_l24_n371(x)
+ if (x < 1)
+ fun_l25_n827(x)
+ else
+ fun_l25_n677(x)
+ end
+end
+
+def fun_l24_n372(x)
+ if (x < 1)
+ fun_l25_n256(x)
+ else
+ fun_l25_n841(x)
+ end
+end
+
+def fun_l24_n373(x)
+ if (x < 1)
+ fun_l25_n671(x)
+ else
+ fun_l25_n712(x)
+ end
+end
+
+def fun_l24_n374(x)
+ if (x < 1)
+ fun_l25_n696(x)
+ else
+ fun_l25_n598(x)
+ end
+end
+
+def fun_l24_n375(x)
+ if (x < 1)
+ fun_l25_n384(x)
+ else
+ fun_l25_n426(x)
+ end
+end
+
+def fun_l24_n376(x)
+ if (x < 1)
+ fun_l25_n578(x)
+ else
+ fun_l25_n555(x)
+ end
+end
+
+def fun_l24_n377(x)
+ if (x < 1)
+ fun_l25_n290(x)
+ else
+ fun_l25_n480(x)
+ end
+end
+
+def fun_l24_n378(x)
+ if (x < 1)
+ fun_l25_n481(x)
+ else
+ fun_l25_n647(x)
+ end
+end
+
+def fun_l24_n379(x)
+ if (x < 1)
+ fun_l25_n502(x)
+ else
+ fun_l25_n985(x)
+ end
+end
+
+def fun_l24_n380(x)
+ if (x < 1)
+ fun_l25_n275(x)
+ else
+ fun_l25_n575(x)
+ end
+end
+
+def fun_l24_n381(x)
+ if (x < 1)
+ fun_l25_n901(x)
+ else
+ fun_l25_n396(x)
+ end
+end
+
+def fun_l24_n382(x)
+ if (x < 1)
+ fun_l25_n283(x)
+ else
+ fun_l25_n544(x)
+ end
+end
+
+def fun_l24_n383(x)
+ if (x < 1)
+ fun_l25_n192(x)
+ else
+ fun_l25_n953(x)
+ end
+end
+
+def fun_l24_n384(x)
+ if (x < 1)
+ fun_l25_n862(x)
+ else
+ fun_l25_n264(x)
+ end
+end
+
+def fun_l24_n385(x)
+ if (x < 1)
+ fun_l25_n528(x)
+ else
+ fun_l25_n429(x)
+ end
+end
+
+def fun_l24_n386(x)
+ if (x < 1)
+ fun_l25_n29(x)
+ else
+ fun_l25_n831(x)
+ end
+end
+
+def fun_l24_n387(x)
+ if (x < 1)
+ fun_l25_n152(x)
+ else
+ fun_l25_n902(x)
+ end
+end
+
+def fun_l24_n388(x)
+ if (x < 1)
+ fun_l25_n538(x)
+ else
+ fun_l25_n468(x)
+ end
+end
+
+def fun_l24_n389(x)
+ if (x < 1)
+ fun_l25_n772(x)
+ else
+ fun_l25_n105(x)
+ end
+end
+
+def fun_l24_n390(x)
+ if (x < 1)
+ fun_l25_n875(x)
+ else
+ fun_l25_n723(x)
+ end
+end
+
+def fun_l24_n391(x)
+ if (x < 1)
+ fun_l25_n330(x)
+ else
+ fun_l25_n659(x)
+ end
+end
+
+def fun_l24_n392(x)
+ if (x < 1)
+ fun_l25_n168(x)
+ else
+ fun_l25_n68(x)
+ end
+end
+
+def fun_l24_n393(x)
+ if (x < 1)
+ fun_l25_n481(x)
+ else
+ fun_l25_n200(x)
+ end
+end
+
+def fun_l24_n394(x)
+ if (x < 1)
+ fun_l25_n391(x)
+ else
+ fun_l25_n255(x)
+ end
+end
+
+def fun_l24_n395(x)
+ if (x < 1)
+ fun_l25_n383(x)
+ else
+ fun_l25_n250(x)
+ end
+end
+
+def fun_l24_n396(x)
+ if (x < 1)
+ fun_l25_n537(x)
+ else
+ fun_l25_n283(x)
+ end
+end
+
+def fun_l24_n397(x)
+ if (x < 1)
+ fun_l25_n504(x)
+ else
+ fun_l25_n916(x)
+ end
+end
+
+def fun_l24_n398(x)
+ if (x < 1)
+ fun_l25_n992(x)
+ else
+ fun_l25_n504(x)
+ end
+end
+
+def fun_l24_n399(x)
+ if (x < 1)
+ fun_l25_n294(x)
+ else
+ fun_l25_n412(x)
+ end
+end
+
+def fun_l24_n400(x)
+ if (x < 1)
+ fun_l25_n686(x)
+ else
+ fun_l25_n85(x)
+ end
+end
+
+def fun_l24_n401(x)
+ if (x < 1)
+ fun_l25_n874(x)
+ else
+ fun_l25_n980(x)
+ end
+end
+
+def fun_l24_n402(x)
+ if (x < 1)
+ fun_l25_n454(x)
+ else
+ fun_l25_n867(x)
+ end
+end
+
+def fun_l24_n403(x)
+ if (x < 1)
+ fun_l25_n594(x)
+ else
+ fun_l25_n970(x)
+ end
+end
+
+def fun_l24_n404(x)
+ if (x < 1)
+ fun_l25_n281(x)
+ else
+ fun_l25_n881(x)
+ end
+end
+
+def fun_l24_n405(x)
+ if (x < 1)
+ fun_l25_n713(x)
+ else
+ fun_l25_n530(x)
+ end
+end
+
+def fun_l24_n406(x)
+ if (x < 1)
+ fun_l25_n874(x)
+ else
+ fun_l25_n953(x)
+ end
+end
+
+def fun_l24_n407(x)
+ if (x < 1)
+ fun_l25_n569(x)
+ else
+ fun_l25_n991(x)
+ end
+end
+
+def fun_l24_n408(x)
+ if (x < 1)
+ fun_l25_n875(x)
+ else
+ fun_l25_n409(x)
+ end
+end
+
+def fun_l24_n409(x)
+ if (x < 1)
+ fun_l25_n604(x)
+ else
+ fun_l25_n454(x)
+ end
+end
+
+def fun_l24_n410(x)
+ if (x < 1)
+ fun_l25_n267(x)
+ else
+ fun_l25_n100(x)
+ end
+end
+
+def fun_l24_n411(x)
+ if (x < 1)
+ fun_l25_n966(x)
+ else
+ fun_l25_n537(x)
+ end
+end
+
+def fun_l24_n412(x)
+ if (x < 1)
+ fun_l25_n261(x)
+ else
+ fun_l25_n106(x)
+ end
+end
+
+def fun_l24_n413(x)
+ if (x < 1)
+ fun_l25_n869(x)
+ else
+ fun_l25_n890(x)
+ end
+end
+
+def fun_l24_n414(x)
+ if (x < 1)
+ fun_l25_n784(x)
+ else
+ fun_l25_n147(x)
+ end
+end
+
+def fun_l24_n415(x)
+ if (x < 1)
+ fun_l25_n6(x)
+ else
+ fun_l25_n808(x)
+ end
+end
+
+def fun_l24_n416(x)
+ if (x < 1)
+ fun_l25_n940(x)
+ else
+ fun_l25_n680(x)
+ end
+end
+
+def fun_l24_n417(x)
+ if (x < 1)
+ fun_l25_n3(x)
+ else
+ fun_l25_n799(x)
+ end
+end
+
+def fun_l24_n418(x)
+ if (x < 1)
+ fun_l25_n196(x)
+ else
+ fun_l25_n785(x)
+ end
+end
+
+def fun_l24_n419(x)
+ if (x < 1)
+ fun_l25_n786(x)
+ else
+ fun_l25_n607(x)
+ end
+end
+
+def fun_l24_n420(x)
+ if (x < 1)
+ fun_l25_n720(x)
+ else
+ fun_l25_n74(x)
+ end
+end
+
+def fun_l24_n421(x)
+ if (x < 1)
+ fun_l25_n962(x)
+ else
+ fun_l25_n489(x)
+ end
+end
+
+def fun_l24_n422(x)
+ if (x < 1)
+ fun_l25_n231(x)
+ else
+ fun_l25_n878(x)
+ end
+end
+
+def fun_l24_n423(x)
+ if (x < 1)
+ fun_l25_n720(x)
+ else
+ fun_l25_n988(x)
+ end
+end
+
+def fun_l24_n424(x)
+ if (x < 1)
+ fun_l25_n883(x)
+ else
+ fun_l25_n510(x)
+ end
+end
+
+def fun_l24_n425(x)
+ if (x < 1)
+ fun_l25_n443(x)
+ else
+ fun_l25_n533(x)
+ end
+end
+
+def fun_l24_n426(x)
+ if (x < 1)
+ fun_l25_n541(x)
+ else
+ fun_l25_n747(x)
+ end
+end
+
+def fun_l24_n427(x)
+ if (x < 1)
+ fun_l25_n308(x)
+ else
+ fun_l25_n373(x)
+ end
+end
+
+def fun_l24_n428(x)
+ if (x < 1)
+ fun_l25_n484(x)
+ else
+ fun_l25_n632(x)
+ end
+end
+
+def fun_l24_n429(x)
+ if (x < 1)
+ fun_l25_n777(x)
+ else
+ fun_l25_n128(x)
+ end
+end
+
+def fun_l24_n430(x)
+ if (x < 1)
+ fun_l25_n729(x)
+ else
+ fun_l25_n644(x)
+ end
+end
+
+def fun_l24_n431(x)
+ if (x < 1)
+ fun_l25_n330(x)
+ else
+ fun_l25_n947(x)
+ end
+end
+
+def fun_l24_n432(x)
+ if (x < 1)
+ fun_l25_n929(x)
+ else
+ fun_l25_n80(x)
+ end
+end
+
+def fun_l24_n433(x)
+ if (x < 1)
+ fun_l25_n269(x)
+ else
+ fun_l25_n307(x)
+ end
+end
+
+def fun_l24_n434(x)
+ if (x < 1)
+ fun_l25_n824(x)
+ else
+ fun_l25_n451(x)
+ end
+end
+
+def fun_l24_n435(x)
+ if (x < 1)
+ fun_l25_n93(x)
+ else
+ fun_l25_n198(x)
+ end
+end
+
+def fun_l24_n436(x)
+ if (x < 1)
+ fun_l25_n359(x)
+ else
+ fun_l25_n412(x)
+ end
+end
+
+def fun_l24_n437(x)
+ if (x < 1)
+ fun_l25_n427(x)
+ else
+ fun_l25_n321(x)
+ end
+end
+
+def fun_l24_n438(x)
+ if (x < 1)
+ fun_l25_n765(x)
+ else
+ fun_l25_n223(x)
+ end
+end
+
+def fun_l24_n439(x)
+ if (x < 1)
+ fun_l25_n918(x)
+ else
+ fun_l25_n902(x)
+ end
+end
+
+def fun_l24_n440(x)
+ if (x < 1)
+ fun_l25_n320(x)
+ else
+ fun_l25_n428(x)
+ end
+end
+
+def fun_l24_n441(x)
+ if (x < 1)
+ fun_l25_n159(x)
+ else
+ fun_l25_n857(x)
+ end
+end
+
+def fun_l24_n442(x)
+ if (x < 1)
+ fun_l25_n505(x)
+ else
+ fun_l25_n565(x)
+ end
+end
+
+def fun_l24_n443(x)
+ if (x < 1)
+ fun_l25_n214(x)
+ else
+ fun_l25_n861(x)
+ end
+end
+
+def fun_l24_n444(x)
+ if (x < 1)
+ fun_l25_n185(x)
+ else
+ fun_l25_n255(x)
+ end
+end
+
+def fun_l24_n445(x)
+ if (x < 1)
+ fun_l25_n198(x)
+ else
+ fun_l25_n314(x)
+ end
+end
+
+def fun_l24_n446(x)
+ if (x < 1)
+ fun_l25_n334(x)
+ else
+ fun_l25_n633(x)
+ end
+end
+
+def fun_l24_n447(x)
+ if (x < 1)
+ fun_l25_n972(x)
+ else
+ fun_l25_n671(x)
+ end
+end
+
+def fun_l24_n448(x)
+ if (x < 1)
+ fun_l25_n608(x)
+ else
+ fun_l25_n720(x)
+ end
+end
+
+def fun_l24_n449(x)
+ if (x < 1)
+ fun_l25_n71(x)
+ else
+ fun_l25_n479(x)
+ end
+end
+
+def fun_l24_n450(x)
+ if (x < 1)
+ fun_l25_n689(x)
+ else
+ fun_l25_n716(x)
+ end
+end
+
+def fun_l24_n451(x)
+ if (x < 1)
+ fun_l25_n696(x)
+ else
+ fun_l25_n453(x)
+ end
+end
+
+def fun_l24_n452(x)
+ if (x < 1)
+ fun_l25_n804(x)
+ else
+ fun_l25_n508(x)
+ end
+end
+
+def fun_l24_n453(x)
+ if (x < 1)
+ fun_l25_n32(x)
+ else
+ fun_l25_n180(x)
+ end
+end
+
+def fun_l24_n454(x)
+ if (x < 1)
+ fun_l25_n493(x)
+ else
+ fun_l25_n200(x)
+ end
+end
+
+def fun_l24_n455(x)
+ if (x < 1)
+ fun_l25_n763(x)
+ else
+ fun_l25_n362(x)
+ end
+end
+
+def fun_l24_n456(x)
+ if (x < 1)
+ fun_l25_n488(x)
+ else
+ fun_l25_n202(x)
+ end
+end
+
+def fun_l24_n457(x)
+ if (x < 1)
+ fun_l25_n752(x)
+ else
+ fun_l25_n670(x)
+ end
+end
+
+def fun_l24_n458(x)
+ if (x < 1)
+ fun_l25_n462(x)
+ else
+ fun_l25_n457(x)
+ end
+end
+
+def fun_l24_n459(x)
+ if (x < 1)
+ fun_l25_n266(x)
+ else
+ fun_l25_n455(x)
+ end
+end
+
+def fun_l24_n460(x)
+ if (x < 1)
+ fun_l25_n173(x)
+ else
+ fun_l25_n873(x)
+ end
+end
+
+def fun_l24_n461(x)
+ if (x < 1)
+ fun_l25_n127(x)
+ else
+ fun_l25_n213(x)
+ end
+end
+
+def fun_l24_n462(x)
+ if (x < 1)
+ fun_l25_n579(x)
+ else
+ fun_l25_n44(x)
+ end
+end
+
+def fun_l24_n463(x)
+ if (x < 1)
+ fun_l25_n68(x)
+ else
+ fun_l25_n989(x)
+ end
+end
+
+def fun_l24_n464(x)
+ if (x < 1)
+ fun_l25_n826(x)
+ else
+ fun_l25_n883(x)
+ end
+end
+
+def fun_l24_n465(x)
+ if (x < 1)
+ fun_l25_n855(x)
+ else
+ fun_l25_n131(x)
+ end
+end
+
+def fun_l24_n466(x)
+ if (x < 1)
+ fun_l25_n923(x)
+ else
+ fun_l25_n433(x)
+ end
+end
+
+def fun_l24_n467(x)
+ if (x < 1)
+ fun_l25_n84(x)
+ else
+ fun_l25_n648(x)
+ end
+end
+
+def fun_l24_n468(x)
+ if (x < 1)
+ fun_l25_n53(x)
+ else
+ fun_l25_n766(x)
+ end
+end
+
+def fun_l24_n469(x)
+ if (x < 1)
+ fun_l25_n689(x)
+ else
+ fun_l25_n201(x)
+ end
+end
+
+def fun_l24_n470(x)
+ if (x < 1)
+ fun_l25_n361(x)
+ else
+ fun_l25_n459(x)
+ end
+end
+
+def fun_l24_n471(x)
+ if (x < 1)
+ fun_l25_n550(x)
+ else
+ fun_l25_n522(x)
+ end
+end
+
+def fun_l24_n472(x)
+ if (x < 1)
+ fun_l25_n128(x)
+ else
+ fun_l25_n417(x)
+ end
+end
+
+def fun_l24_n473(x)
+ if (x < 1)
+ fun_l25_n600(x)
+ else
+ fun_l25_n137(x)
+ end
+end
+
+def fun_l24_n474(x)
+ if (x < 1)
+ fun_l25_n72(x)
+ else
+ fun_l25_n548(x)
+ end
+end
+
+def fun_l24_n475(x)
+ if (x < 1)
+ fun_l25_n879(x)
+ else
+ fun_l25_n376(x)
+ end
+end
+
+def fun_l24_n476(x)
+ if (x < 1)
+ fun_l25_n822(x)
+ else
+ fun_l25_n695(x)
+ end
+end
+
+def fun_l24_n477(x)
+ if (x < 1)
+ fun_l25_n991(x)
+ else
+ fun_l25_n208(x)
+ end
+end
+
+def fun_l24_n478(x)
+ if (x < 1)
+ fun_l25_n17(x)
+ else
+ fun_l25_n332(x)
+ end
+end
+
+def fun_l24_n479(x)
+ if (x < 1)
+ fun_l25_n353(x)
+ else
+ fun_l25_n438(x)
+ end
+end
+
+def fun_l24_n480(x)
+ if (x < 1)
+ fun_l25_n109(x)
+ else
+ fun_l25_n360(x)
+ end
+end
+
+def fun_l24_n481(x)
+ if (x < 1)
+ fun_l25_n57(x)
+ else
+ fun_l25_n417(x)
+ end
+end
+
+def fun_l24_n482(x)
+ if (x < 1)
+ fun_l25_n903(x)
+ else
+ fun_l25_n486(x)
+ end
+end
+
+def fun_l24_n483(x)
+ if (x < 1)
+ fun_l25_n677(x)
+ else
+ fun_l25_n77(x)
+ end
+end
+
+def fun_l24_n484(x)
+ if (x < 1)
+ fun_l25_n117(x)
+ else
+ fun_l25_n582(x)
+ end
+end
+
+def fun_l24_n485(x)
+ if (x < 1)
+ fun_l25_n454(x)
+ else
+ fun_l25_n198(x)
+ end
+end
+
+def fun_l24_n486(x)
+ if (x < 1)
+ fun_l25_n779(x)
+ else
+ fun_l25_n301(x)
+ end
+end
+
+def fun_l24_n487(x)
+ if (x < 1)
+ fun_l25_n3(x)
+ else
+ fun_l25_n363(x)
+ end
+end
+
+def fun_l24_n488(x)
+ if (x < 1)
+ fun_l25_n84(x)
+ else
+ fun_l25_n793(x)
+ end
+end
+
+def fun_l24_n489(x)
+ if (x < 1)
+ fun_l25_n344(x)
+ else
+ fun_l25_n342(x)
+ end
+end
+
+def fun_l24_n490(x)
+ if (x < 1)
+ fun_l25_n365(x)
+ else
+ fun_l25_n546(x)
+ end
+end
+
+def fun_l24_n491(x)
+ if (x < 1)
+ fun_l25_n431(x)
+ else
+ fun_l25_n193(x)
+ end
+end
+
+def fun_l24_n492(x)
+ if (x < 1)
+ fun_l25_n763(x)
+ else
+ fun_l25_n174(x)
+ end
+end
+
+def fun_l24_n493(x)
+ if (x < 1)
+ fun_l25_n231(x)
+ else
+ fun_l25_n435(x)
+ end
+end
+
+def fun_l24_n494(x)
+ if (x < 1)
+ fun_l25_n408(x)
+ else
+ fun_l25_n848(x)
+ end
+end
+
+def fun_l24_n495(x)
+ if (x < 1)
+ fun_l25_n955(x)
+ else
+ fun_l25_n232(x)
+ end
+end
+
+def fun_l24_n496(x)
+ if (x < 1)
+ fun_l25_n72(x)
+ else
+ fun_l25_n11(x)
+ end
+end
+
+def fun_l24_n497(x)
+ if (x < 1)
+ fun_l25_n196(x)
+ else
+ fun_l25_n180(x)
+ end
+end
+
+def fun_l24_n498(x)
+ if (x < 1)
+ fun_l25_n102(x)
+ else
+ fun_l25_n360(x)
+ end
+end
+
+def fun_l24_n499(x)
+ if (x < 1)
+ fun_l25_n755(x)
+ else
+ fun_l25_n760(x)
+ end
+end
+
+def fun_l24_n500(x)
+ if (x < 1)
+ fun_l25_n676(x)
+ else
+ fun_l25_n825(x)
+ end
+end
+
+def fun_l24_n501(x)
+ if (x < 1)
+ fun_l25_n203(x)
+ else
+ fun_l25_n731(x)
+ end
+end
+
+def fun_l24_n502(x)
+ if (x < 1)
+ fun_l25_n551(x)
+ else
+ fun_l25_n165(x)
+ end
+end
+
+def fun_l24_n503(x)
+ if (x < 1)
+ fun_l25_n702(x)
+ else
+ fun_l25_n779(x)
+ end
+end
+
+def fun_l24_n504(x)
+ if (x < 1)
+ fun_l25_n525(x)
+ else
+ fun_l25_n846(x)
+ end
+end
+
+def fun_l24_n505(x)
+ if (x < 1)
+ fun_l25_n97(x)
+ else
+ fun_l25_n331(x)
+ end
+end
+
+def fun_l24_n506(x)
+ if (x < 1)
+ fun_l25_n572(x)
+ else
+ fun_l25_n759(x)
+ end
+end
+
+def fun_l24_n507(x)
+ if (x < 1)
+ fun_l25_n402(x)
+ else
+ fun_l25_n460(x)
+ end
+end
+
+def fun_l24_n508(x)
+ if (x < 1)
+ fun_l25_n640(x)
+ else
+ fun_l25_n833(x)
+ end
+end
+
+def fun_l24_n509(x)
+ if (x < 1)
+ fun_l25_n190(x)
+ else
+ fun_l25_n524(x)
+ end
+end
+
+def fun_l24_n510(x)
+ if (x < 1)
+ fun_l25_n307(x)
+ else
+ fun_l25_n92(x)
+ end
+end
+
+def fun_l24_n511(x)
+ if (x < 1)
+ fun_l25_n444(x)
+ else
+ fun_l25_n593(x)
+ end
+end
+
+def fun_l24_n512(x)
+ if (x < 1)
+ fun_l25_n684(x)
+ else
+ fun_l25_n163(x)
+ end
+end
+
+def fun_l24_n513(x)
+ if (x < 1)
+ fun_l25_n998(x)
+ else
+ fun_l25_n582(x)
+ end
+end
+
+def fun_l24_n514(x)
+ if (x < 1)
+ fun_l25_n767(x)
+ else
+ fun_l25_n557(x)
+ end
+end
+
+def fun_l24_n515(x)
+ if (x < 1)
+ fun_l25_n893(x)
+ else
+ fun_l25_n179(x)
+ end
+end
+
+def fun_l24_n516(x)
+ if (x < 1)
+ fun_l25_n726(x)
+ else
+ fun_l25_n651(x)
+ end
+end
+
+def fun_l24_n517(x)
+ if (x < 1)
+ fun_l25_n57(x)
+ else
+ fun_l25_n454(x)
+ end
+end
+
+def fun_l24_n518(x)
+ if (x < 1)
+ fun_l25_n598(x)
+ else
+ fun_l25_n554(x)
+ end
+end
+
+def fun_l24_n519(x)
+ if (x < 1)
+ fun_l25_n437(x)
+ else
+ fun_l25_n349(x)
+ end
+end
+
+def fun_l24_n520(x)
+ if (x < 1)
+ fun_l25_n754(x)
+ else
+ fun_l25_n259(x)
+ end
+end
+
+def fun_l24_n521(x)
+ if (x < 1)
+ fun_l25_n856(x)
+ else
+ fun_l25_n155(x)
+ end
+end
+
+def fun_l24_n522(x)
+ if (x < 1)
+ fun_l25_n607(x)
+ else
+ fun_l25_n751(x)
+ end
+end
+
+def fun_l24_n523(x)
+ if (x < 1)
+ fun_l25_n510(x)
+ else
+ fun_l25_n297(x)
+ end
+end
+
+def fun_l24_n524(x)
+ if (x < 1)
+ fun_l25_n433(x)
+ else
+ fun_l25_n102(x)
+ end
+end
+
+def fun_l24_n525(x)
+ if (x < 1)
+ fun_l25_n173(x)
+ else
+ fun_l25_n487(x)
+ end
+end
+
+def fun_l24_n526(x)
+ if (x < 1)
+ fun_l25_n716(x)
+ else
+ fun_l25_n230(x)
+ end
+end
+
+def fun_l24_n527(x)
+ if (x < 1)
+ fun_l25_n511(x)
+ else
+ fun_l25_n272(x)
+ end
+end
+
+def fun_l24_n528(x)
+ if (x < 1)
+ fun_l25_n974(x)
+ else
+ fun_l25_n954(x)
+ end
+end
+
+def fun_l24_n529(x)
+ if (x < 1)
+ fun_l25_n92(x)
+ else
+ fun_l25_n704(x)
+ end
+end
+
+def fun_l24_n530(x)
+ if (x < 1)
+ fun_l25_n117(x)
+ else
+ fun_l25_n725(x)
+ end
+end
+
+def fun_l24_n531(x)
+ if (x < 1)
+ fun_l25_n817(x)
+ else
+ fun_l25_n6(x)
+ end
+end
+
+def fun_l24_n532(x)
+ if (x < 1)
+ fun_l25_n27(x)
+ else
+ fun_l25_n438(x)
+ end
+end
+
+def fun_l24_n533(x)
+ if (x < 1)
+ fun_l25_n964(x)
+ else
+ fun_l25_n291(x)
+ end
+end
+
+def fun_l24_n534(x)
+ if (x < 1)
+ fun_l25_n786(x)
+ else
+ fun_l25_n871(x)
+ end
+end
+
+def fun_l24_n535(x)
+ if (x < 1)
+ fun_l25_n79(x)
+ else
+ fun_l25_n786(x)
+ end
+end
+
+def fun_l24_n536(x)
+ if (x < 1)
+ fun_l25_n403(x)
+ else
+ fun_l25_n78(x)
+ end
+end
+
+def fun_l24_n537(x)
+ if (x < 1)
+ fun_l25_n20(x)
+ else
+ fun_l25_n239(x)
+ end
+end
+
+def fun_l24_n538(x)
+ if (x < 1)
+ fun_l25_n818(x)
+ else
+ fun_l25_n917(x)
+ end
+end
+
+def fun_l24_n539(x)
+ if (x < 1)
+ fun_l25_n598(x)
+ else
+ fun_l25_n708(x)
+ end
+end
+
+def fun_l24_n540(x)
+ if (x < 1)
+ fun_l25_n802(x)
+ else
+ fun_l25_n208(x)
+ end
+end
+
+def fun_l24_n541(x)
+ if (x < 1)
+ fun_l25_n962(x)
+ else
+ fun_l25_n487(x)
+ end
+end
+
+def fun_l24_n542(x)
+ if (x < 1)
+ fun_l25_n690(x)
+ else
+ fun_l25_n503(x)
+ end
+end
+
+def fun_l24_n543(x)
+ if (x < 1)
+ fun_l25_n548(x)
+ else
+ fun_l25_n295(x)
+ end
+end
+
+def fun_l24_n544(x)
+ if (x < 1)
+ fun_l25_n373(x)
+ else
+ fun_l25_n896(x)
+ end
+end
+
+def fun_l24_n545(x)
+ if (x < 1)
+ fun_l25_n759(x)
+ else
+ fun_l25_n171(x)
+ end
+end
+
+def fun_l24_n546(x)
+ if (x < 1)
+ fun_l25_n269(x)
+ else
+ fun_l25_n153(x)
+ end
+end
+
+def fun_l24_n547(x)
+ if (x < 1)
+ fun_l25_n489(x)
+ else
+ fun_l25_n628(x)
+ end
+end
+
+def fun_l24_n548(x)
+ if (x < 1)
+ fun_l25_n540(x)
+ else
+ fun_l25_n7(x)
+ end
+end
+
+def fun_l24_n549(x)
+ if (x < 1)
+ fun_l25_n916(x)
+ else
+ fun_l25_n365(x)
+ end
+end
+
+def fun_l24_n550(x)
+ if (x < 1)
+ fun_l25_n377(x)
+ else
+ fun_l25_n420(x)
+ end
+end
+
+def fun_l24_n551(x)
+ if (x < 1)
+ fun_l25_n331(x)
+ else
+ fun_l25_n568(x)
+ end
+end
+
+def fun_l24_n552(x)
+ if (x < 1)
+ fun_l25_n348(x)
+ else
+ fun_l25_n934(x)
+ end
+end
+
+def fun_l24_n553(x)
+ if (x < 1)
+ fun_l25_n676(x)
+ else
+ fun_l25_n142(x)
+ end
+end
+
+def fun_l24_n554(x)
+ if (x < 1)
+ fun_l25_n913(x)
+ else
+ fun_l25_n255(x)
+ end
+end
+
+def fun_l24_n555(x)
+ if (x < 1)
+ fun_l25_n873(x)
+ else
+ fun_l25_n951(x)
+ end
+end
+
+def fun_l24_n556(x)
+ if (x < 1)
+ fun_l25_n300(x)
+ else
+ fun_l25_n969(x)
+ end
+end
+
+def fun_l24_n557(x)
+ if (x < 1)
+ fun_l25_n674(x)
+ else
+ fun_l25_n290(x)
+ end
+end
+
+def fun_l24_n558(x)
+ if (x < 1)
+ fun_l25_n323(x)
+ else
+ fun_l25_n325(x)
+ end
+end
+
+def fun_l24_n559(x)
+ if (x < 1)
+ fun_l25_n547(x)
+ else
+ fun_l25_n207(x)
+ end
+end
+
+def fun_l24_n560(x)
+ if (x < 1)
+ fun_l25_n858(x)
+ else
+ fun_l25_n304(x)
+ end
+end
+
+def fun_l24_n561(x)
+ if (x < 1)
+ fun_l25_n831(x)
+ else
+ fun_l25_n840(x)
+ end
+end
+
+def fun_l24_n562(x)
+ if (x < 1)
+ fun_l25_n174(x)
+ else
+ fun_l25_n162(x)
+ end
+end
+
+def fun_l24_n563(x)
+ if (x < 1)
+ fun_l25_n662(x)
+ else
+ fun_l25_n676(x)
+ end
+end
+
+def fun_l24_n564(x)
+ if (x < 1)
+ fun_l25_n474(x)
+ else
+ fun_l25_n173(x)
+ end
+end
+
+def fun_l24_n565(x)
+ if (x < 1)
+ fun_l25_n232(x)
+ else
+ fun_l25_n57(x)
+ end
+end
+
+def fun_l24_n566(x)
+ if (x < 1)
+ fun_l25_n615(x)
+ else
+ fun_l25_n944(x)
+ end
+end
+
+def fun_l24_n567(x)
+ if (x < 1)
+ fun_l25_n586(x)
+ else
+ fun_l25_n183(x)
+ end
+end
+
+def fun_l24_n568(x)
+ if (x < 1)
+ fun_l25_n758(x)
+ else
+ fun_l25_n376(x)
+ end
+end
+
+def fun_l24_n569(x)
+ if (x < 1)
+ fun_l25_n755(x)
+ else
+ fun_l25_n903(x)
+ end
+end
+
+def fun_l24_n570(x)
+ if (x < 1)
+ fun_l25_n562(x)
+ else
+ fun_l25_n843(x)
+ end
+end
+
+def fun_l24_n571(x)
+ if (x < 1)
+ fun_l25_n369(x)
+ else
+ fun_l25_n712(x)
+ end
+end
+
+def fun_l24_n572(x)
+ if (x < 1)
+ fun_l25_n183(x)
+ else
+ fun_l25_n273(x)
+ end
+end
+
+def fun_l24_n573(x)
+ if (x < 1)
+ fun_l25_n150(x)
+ else
+ fun_l25_n309(x)
+ end
+end
+
+def fun_l24_n574(x)
+ if (x < 1)
+ fun_l25_n485(x)
+ else
+ fun_l25_n20(x)
+ end
+end
+
+def fun_l24_n575(x)
+ if (x < 1)
+ fun_l25_n325(x)
+ else
+ fun_l25_n770(x)
+ end
+end
+
+def fun_l24_n576(x)
+ if (x < 1)
+ fun_l25_n528(x)
+ else
+ fun_l25_n529(x)
+ end
+end
+
+def fun_l24_n577(x)
+ if (x < 1)
+ fun_l25_n557(x)
+ else
+ fun_l25_n416(x)
+ end
+end
+
+def fun_l24_n578(x)
+ if (x < 1)
+ fun_l25_n501(x)
+ else
+ fun_l25_n81(x)
+ end
+end
+
+def fun_l24_n579(x)
+ if (x < 1)
+ fun_l25_n355(x)
+ else
+ fun_l25_n391(x)
+ end
+end
+
+def fun_l24_n580(x)
+ if (x < 1)
+ fun_l25_n665(x)
+ else
+ fun_l25_n656(x)
+ end
+end
+
+def fun_l24_n581(x)
+ if (x < 1)
+ fun_l25_n496(x)
+ else
+ fun_l25_n933(x)
+ end
+end
+
+def fun_l24_n582(x)
+ if (x < 1)
+ fun_l25_n71(x)
+ else
+ fun_l25_n815(x)
+ end
+end
+
+def fun_l24_n583(x)
+ if (x < 1)
+ fun_l25_n488(x)
+ else
+ fun_l25_n587(x)
+ end
+end
+
+def fun_l24_n584(x)
+ if (x < 1)
+ fun_l25_n909(x)
+ else
+ fun_l25_n673(x)
+ end
+end
+
+def fun_l24_n585(x)
+ if (x < 1)
+ fun_l25_n452(x)
+ else
+ fun_l25_n774(x)
+ end
+end
+
+def fun_l24_n586(x)
+ if (x < 1)
+ fun_l25_n376(x)
+ else
+ fun_l25_n855(x)
+ end
+end
+
+def fun_l24_n587(x)
+ if (x < 1)
+ fun_l25_n452(x)
+ else
+ fun_l25_n331(x)
+ end
+end
+
+def fun_l24_n588(x)
+ if (x < 1)
+ fun_l25_n718(x)
+ else
+ fun_l25_n496(x)
+ end
+end
+
+def fun_l24_n589(x)
+ if (x < 1)
+ fun_l25_n923(x)
+ else
+ fun_l25_n633(x)
+ end
+end
+
+def fun_l24_n590(x)
+ if (x < 1)
+ fun_l25_n815(x)
+ else
+ fun_l25_n633(x)
+ end
+end
+
+def fun_l24_n591(x)
+ if (x < 1)
+ fun_l25_n699(x)
+ else
+ fun_l25_n609(x)
+ end
+end
+
+def fun_l24_n592(x)
+ if (x < 1)
+ fun_l25_n722(x)
+ else
+ fun_l25_n884(x)
+ end
+end
+
+def fun_l24_n593(x)
+ if (x < 1)
+ fun_l25_n580(x)
+ else
+ fun_l25_n48(x)
+ end
+end
+
+def fun_l24_n594(x)
+ if (x < 1)
+ fun_l25_n245(x)
+ else
+ fun_l25_n126(x)
+ end
+end
+
+def fun_l24_n595(x)
+ if (x < 1)
+ fun_l25_n778(x)
+ else
+ fun_l25_n989(x)
+ end
+end
+
+def fun_l24_n596(x)
+ if (x < 1)
+ fun_l25_n813(x)
+ else
+ fun_l25_n117(x)
+ end
+end
+
+def fun_l24_n597(x)
+ if (x < 1)
+ fun_l25_n622(x)
+ else
+ fun_l25_n293(x)
+ end
+end
+
+def fun_l24_n598(x)
+ if (x < 1)
+ fun_l25_n996(x)
+ else
+ fun_l25_n704(x)
+ end
+end
+
+def fun_l24_n599(x)
+ if (x < 1)
+ fun_l25_n173(x)
+ else
+ fun_l25_n336(x)
+ end
+end
+
+def fun_l24_n600(x)
+ if (x < 1)
+ fun_l25_n295(x)
+ else
+ fun_l25_n293(x)
+ end
+end
+
+def fun_l24_n601(x)
+ if (x < 1)
+ fun_l25_n104(x)
+ else
+ fun_l25_n907(x)
+ end
+end
+
+def fun_l24_n602(x)
+ if (x < 1)
+ fun_l25_n136(x)
+ else
+ fun_l25_n915(x)
+ end
+end
+
+def fun_l24_n603(x)
+ if (x < 1)
+ fun_l25_n19(x)
+ else
+ fun_l25_n113(x)
+ end
+end
+
+def fun_l24_n604(x)
+ if (x < 1)
+ fun_l25_n389(x)
+ else
+ fun_l25_n863(x)
+ end
+end
+
+def fun_l24_n605(x)
+ if (x < 1)
+ fun_l25_n20(x)
+ else
+ fun_l25_n830(x)
+ end
+end
+
+def fun_l24_n606(x)
+ if (x < 1)
+ fun_l25_n723(x)
+ else
+ fun_l25_n956(x)
+ end
+end
+
+def fun_l24_n607(x)
+ if (x < 1)
+ fun_l25_n765(x)
+ else
+ fun_l25_n27(x)
+ end
+end
+
+def fun_l24_n608(x)
+ if (x < 1)
+ fun_l25_n682(x)
+ else
+ fun_l25_n953(x)
+ end
+end
+
+def fun_l24_n609(x)
+ if (x < 1)
+ fun_l25_n501(x)
+ else
+ fun_l25_n81(x)
+ end
+end
+
+def fun_l24_n610(x)
+ if (x < 1)
+ fun_l25_n896(x)
+ else
+ fun_l25_n192(x)
+ end
+end
+
+def fun_l24_n611(x)
+ if (x < 1)
+ fun_l25_n605(x)
+ else
+ fun_l25_n443(x)
+ end
+end
+
+def fun_l24_n612(x)
+ if (x < 1)
+ fun_l25_n298(x)
+ else
+ fun_l25_n818(x)
+ end
+end
+
+def fun_l24_n613(x)
+ if (x < 1)
+ fun_l25_n289(x)
+ else
+ fun_l25_n227(x)
+ end
+end
+
+def fun_l24_n614(x)
+ if (x < 1)
+ fun_l25_n511(x)
+ else
+ fun_l25_n460(x)
+ end
+end
+
+def fun_l24_n615(x)
+ if (x < 1)
+ fun_l25_n774(x)
+ else
+ fun_l25_n794(x)
+ end
+end
+
+def fun_l24_n616(x)
+ if (x < 1)
+ fun_l25_n933(x)
+ else
+ fun_l25_n448(x)
+ end
+end
+
+def fun_l24_n617(x)
+ if (x < 1)
+ fun_l25_n239(x)
+ else
+ fun_l25_n156(x)
+ end
+end
+
+def fun_l24_n618(x)
+ if (x < 1)
+ fun_l25_n713(x)
+ else
+ fun_l25_n337(x)
+ end
+end
+
+def fun_l24_n619(x)
+ if (x < 1)
+ fun_l25_n450(x)
+ else
+ fun_l25_n282(x)
+ end
+end
+
+def fun_l24_n620(x)
+ if (x < 1)
+ fun_l25_n97(x)
+ else
+ fun_l25_n360(x)
+ end
+end
+
+def fun_l24_n621(x)
+ if (x < 1)
+ fun_l25_n197(x)
+ else
+ fun_l25_n406(x)
+ end
+end
+
+def fun_l24_n622(x)
+ if (x < 1)
+ fun_l25_n791(x)
+ else
+ fun_l25_n876(x)
+ end
+end
+
+def fun_l24_n623(x)
+ if (x < 1)
+ fun_l25_n989(x)
+ else
+ fun_l25_n616(x)
+ end
+end
+
+def fun_l24_n624(x)
+ if (x < 1)
+ fun_l25_n754(x)
+ else
+ fun_l25_n605(x)
+ end
+end
+
+def fun_l24_n625(x)
+ if (x < 1)
+ fun_l25_n113(x)
+ else
+ fun_l25_n400(x)
+ end
+end
+
+def fun_l24_n626(x)
+ if (x < 1)
+ fun_l25_n6(x)
+ else
+ fun_l25_n742(x)
+ end
+end
+
+def fun_l24_n627(x)
+ if (x < 1)
+ fun_l25_n916(x)
+ else
+ fun_l25_n5(x)
+ end
+end
+
+def fun_l24_n628(x)
+ if (x < 1)
+ fun_l25_n5(x)
+ else
+ fun_l25_n327(x)
+ end
+end
+
+def fun_l24_n629(x)
+ if (x < 1)
+ fun_l25_n867(x)
+ else
+ fun_l25_n37(x)
+ end
+end
+
+def fun_l24_n630(x)
+ if (x < 1)
+ fun_l25_n409(x)
+ else
+ fun_l25_n137(x)
+ end
+end
+
+def fun_l24_n631(x)
+ if (x < 1)
+ fun_l25_n128(x)
+ else
+ fun_l25_n499(x)
+ end
+end
+
+def fun_l24_n632(x)
+ if (x < 1)
+ fun_l25_n694(x)
+ else
+ fun_l25_n983(x)
+ end
+end
+
+def fun_l24_n633(x)
+ if (x < 1)
+ fun_l25_n62(x)
+ else
+ fun_l25_n538(x)
+ end
+end
+
+def fun_l24_n634(x)
+ if (x < 1)
+ fun_l25_n740(x)
+ else
+ fun_l25_n795(x)
+ end
+end
+
+def fun_l24_n635(x)
+ if (x < 1)
+ fun_l25_n597(x)
+ else
+ fun_l25_n557(x)
+ end
+end
+
+def fun_l24_n636(x)
+ if (x < 1)
+ fun_l25_n642(x)
+ else
+ fun_l25_n40(x)
+ end
+end
+
+def fun_l24_n637(x)
+ if (x < 1)
+ fun_l25_n303(x)
+ else
+ fun_l25_n931(x)
+ end
+end
+
+def fun_l24_n638(x)
+ if (x < 1)
+ fun_l25_n977(x)
+ else
+ fun_l25_n848(x)
+ end
+end
+
+def fun_l24_n639(x)
+ if (x < 1)
+ fun_l25_n983(x)
+ else
+ fun_l25_n11(x)
+ end
+end
+
+def fun_l24_n640(x)
+ if (x < 1)
+ fun_l25_n258(x)
+ else
+ fun_l25_n280(x)
+ end
+end
+
+def fun_l24_n641(x)
+ if (x < 1)
+ fun_l25_n553(x)
+ else
+ fun_l25_n351(x)
+ end
+end
+
+def fun_l24_n642(x)
+ if (x < 1)
+ fun_l25_n4(x)
+ else
+ fun_l25_n375(x)
+ end
+end
+
+def fun_l24_n643(x)
+ if (x < 1)
+ fun_l25_n678(x)
+ else
+ fun_l25_n139(x)
+ end
+end
+
+def fun_l24_n644(x)
+ if (x < 1)
+ fun_l25_n193(x)
+ else
+ fun_l25_n490(x)
+ end
+end
+
+def fun_l24_n645(x)
+ if (x < 1)
+ fun_l25_n146(x)
+ else
+ fun_l25_n450(x)
+ end
+end
+
+def fun_l24_n646(x)
+ if (x < 1)
+ fun_l25_n813(x)
+ else
+ fun_l25_n59(x)
+ end
+end
+
+def fun_l24_n647(x)
+ if (x < 1)
+ fun_l25_n726(x)
+ else
+ fun_l25_n792(x)
+ end
+end
+
+def fun_l24_n648(x)
+ if (x < 1)
+ fun_l25_n508(x)
+ else
+ fun_l25_n496(x)
+ end
+end
+
+def fun_l24_n649(x)
+ if (x < 1)
+ fun_l25_n231(x)
+ else
+ fun_l25_n688(x)
+ end
+end
+
+def fun_l24_n650(x)
+ if (x < 1)
+ fun_l25_n602(x)
+ else
+ fun_l25_n641(x)
+ end
+end
+
+def fun_l24_n651(x)
+ if (x < 1)
+ fun_l25_n101(x)
+ else
+ fun_l25_n394(x)
+ end
+end
+
+def fun_l24_n652(x)
+ if (x < 1)
+ fun_l25_n454(x)
+ else
+ fun_l25_n466(x)
+ end
+end
+
+def fun_l24_n653(x)
+ if (x < 1)
+ fun_l25_n147(x)
+ else
+ fun_l25_n116(x)
+ end
+end
+
+def fun_l24_n654(x)
+ if (x < 1)
+ fun_l25_n83(x)
+ else
+ fun_l25_n951(x)
+ end
+end
+
+def fun_l24_n655(x)
+ if (x < 1)
+ fun_l25_n667(x)
+ else
+ fun_l25_n293(x)
+ end
+end
+
+def fun_l24_n656(x)
+ if (x < 1)
+ fun_l25_n413(x)
+ else
+ fun_l25_n708(x)
+ end
+end
+
+def fun_l24_n657(x)
+ if (x < 1)
+ fun_l25_n495(x)
+ else
+ fun_l25_n277(x)
+ end
+end
+
+def fun_l24_n658(x)
+ if (x < 1)
+ fun_l25_n926(x)
+ else
+ fun_l25_n624(x)
+ end
+end
+
+def fun_l24_n659(x)
+ if (x < 1)
+ fun_l25_n612(x)
+ else
+ fun_l25_n666(x)
+ end
+end
+
+def fun_l24_n660(x)
+ if (x < 1)
+ fun_l25_n32(x)
+ else
+ fun_l25_n290(x)
+ end
+end
+
+def fun_l24_n661(x)
+ if (x < 1)
+ fun_l25_n674(x)
+ else
+ fun_l25_n937(x)
+ end
+end
+
+def fun_l24_n662(x)
+ if (x < 1)
+ fun_l25_n556(x)
+ else
+ fun_l25_n576(x)
+ end
+end
+
+def fun_l24_n663(x)
+ if (x < 1)
+ fun_l25_n763(x)
+ else
+ fun_l25_n898(x)
+ end
+end
+
+def fun_l24_n664(x)
+ if (x < 1)
+ fun_l25_n564(x)
+ else
+ fun_l25_n478(x)
+ end
+end
+
+def fun_l24_n665(x)
+ if (x < 1)
+ fun_l25_n515(x)
+ else
+ fun_l25_n991(x)
+ end
+end
+
+def fun_l24_n666(x)
+ if (x < 1)
+ fun_l25_n737(x)
+ else
+ fun_l25_n936(x)
+ end
+end
+
+def fun_l24_n667(x)
+ if (x < 1)
+ fun_l25_n829(x)
+ else
+ fun_l25_n350(x)
+ end
+end
+
+def fun_l24_n668(x)
+ if (x < 1)
+ fun_l25_n59(x)
+ else
+ fun_l25_n979(x)
+ end
+end
+
+def fun_l24_n669(x)
+ if (x < 1)
+ fun_l25_n866(x)
+ else
+ fun_l25_n624(x)
+ end
+end
+
+def fun_l24_n670(x)
+ if (x < 1)
+ fun_l25_n572(x)
+ else
+ fun_l25_n203(x)
+ end
+end
+
+def fun_l24_n671(x)
+ if (x < 1)
+ fun_l25_n96(x)
+ else
+ fun_l25_n862(x)
+ end
+end
+
+def fun_l24_n672(x)
+ if (x < 1)
+ fun_l25_n979(x)
+ else
+ fun_l25_n484(x)
+ end
+end
+
+def fun_l24_n673(x)
+ if (x < 1)
+ fun_l25_n20(x)
+ else
+ fun_l25_n201(x)
+ end
+end
+
+def fun_l24_n674(x)
+ if (x < 1)
+ fun_l25_n109(x)
+ else
+ fun_l25_n788(x)
+ end
+end
+
+def fun_l24_n675(x)
+ if (x < 1)
+ fun_l25_n792(x)
+ else
+ fun_l25_n132(x)
+ end
+end
+
+def fun_l24_n676(x)
+ if (x < 1)
+ fun_l25_n786(x)
+ else
+ fun_l25_n77(x)
+ end
+end
+
+def fun_l24_n677(x)
+ if (x < 1)
+ fun_l25_n21(x)
+ else
+ fun_l25_n96(x)
+ end
+end
+
+def fun_l24_n678(x)
+ if (x < 1)
+ fun_l25_n299(x)
+ else
+ fun_l25_n649(x)
+ end
+end
+
+def fun_l24_n679(x)
+ if (x < 1)
+ fun_l25_n247(x)
+ else
+ fun_l25_n607(x)
+ end
+end
+
+def fun_l24_n680(x)
+ if (x < 1)
+ fun_l25_n480(x)
+ else
+ fun_l25_n471(x)
+ end
+end
+
+def fun_l24_n681(x)
+ if (x < 1)
+ fun_l25_n277(x)
+ else
+ fun_l25_n460(x)
+ end
+end
+
+def fun_l24_n682(x)
+ if (x < 1)
+ fun_l25_n573(x)
+ else
+ fun_l25_n193(x)
+ end
+end
+
+def fun_l24_n683(x)
+ if (x < 1)
+ fun_l25_n741(x)
+ else
+ fun_l25_n441(x)
+ end
+end
+
+def fun_l24_n684(x)
+ if (x < 1)
+ fun_l25_n821(x)
+ else
+ fun_l25_n24(x)
+ end
+end
+
+def fun_l24_n685(x)
+ if (x < 1)
+ fun_l25_n150(x)
+ else
+ fun_l25_n530(x)
+ end
+end
+
+def fun_l24_n686(x)
+ if (x < 1)
+ fun_l25_n564(x)
+ else
+ fun_l25_n26(x)
+ end
+end
+
+def fun_l24_n687(x)
+ if (x < 1)
+ fun_l25_n872(x)
+ else
+ fun_l25_n522(x)
+ end
+end
+
+def fun_l24_n688(x)
+ if (x < 1)
+ fun_l25_n963(x)
+ else
+ fun_l25_n422(x)
+ end
+end
+
+def fun_l24_n689(x)
+ if (x < 1)
+ fun_l25_n418(x)
+ else
+ fun_l25_n900(x)
+ end
+end
+
+def fun_l24_n690(x)
+ if (x < 1)
+ fun_l25_n117(x)
+ else
+ fun_l25_n900(x)
+ end
+end
+
+def fun_l24_n691(x)
+ if (x < 1)
+ fun_l25_n412(x)
+ else
+ fun_l25_n466(x)
+ end
+end
+
+def fun_l24_n692(x)
+ if (x < 1)
+ fun_l25_n761(x)
+ else
+ fun_l25_n190(x)
+ end
+end
+
+def fun_l24_n693(x)
+ if (x < 1)
+ fun_l25_n875(x)
+ else
+ fun_l25_n222(x)
+ end
+end
+
+def fun_l24_n694(x)
+ if (x < 1)
+ fun_l25_n405(x)
+ else
+ fun_l25_n66(x)
+ end
+end
+
+def fun_l24_n695(x)
+ if (x < 1)
+ fun_l25_n570(x)
+ else
+ fun_l25_n801(x)
+ end
+end
+
+def fun_l24_n696(x)
+ if (x < 1)
+ fun_l25_n591(x)
+ else
+ fun_l25_n121(x)
+ end
+end
+
+def fun_l24_n697(x)
+ if (x < 1)
+ fun_l25_n27(x)
+ else
+ fun_l25_n610(x)
+ end
+end
+
+def fun_l24_n698(x)
+ if (x < 1)
+ fun_l25_n843(x)
+ else
+ fun_l25_n488(x)
+ end
+end
+
+def fun_l24_n699(x)
+ if (x < 1)
+ fun_l25_n946(x)
+ else
+ fun_l25_n164(x)
+ end
+end
+
+def fun_l24_n700(x)
+ if (x < 1)
+ fun_l25_n424(x)
+ else
+ fun_l25_n614(x)
+ end
+end
+
+def fun_l24_n701(x)
+ if (x < 1)
+ fun_l25_n692(x)
+ else
+ fun_l25_n893(x)
+ end
+end
+
+def fun_l24_n702(x)
+ if (x < 1)
+ fun_l25_n39(x)
+ else
+ fun_l25_n274(x)
+ end
+end
+
+def fun_l24_n703(x)
+ if (x < 1)
+ fun_l25_n814(x)
+ else
+ fun_l25_n281(x)
+ end
+end
+
+def fun_l24_n704(x)
+ if (x < 1)
+ fun_l25_n670(x)
+ else
+ fun_l25_n882(x)
+ end
+end
+
+def fun_l24_n705(x)
+ if (x < 1)
+ fun_l25_n498(x)
+ else
+ fun_l25_n881(x)
+ end
+end
+
+def fun_l24_n706(x)
+ if (x < 1)
+ fun_l25_n193(x)
+ else
+ fun_l25_n10(x)
+ end
+end
+
+def fun_l24_n707(x)
+ if (x < 1)
+ fun_l25_n531(x)
+ else
+ fun_l25_n870(x)
+ end
+end
+
+def fun_l24_n708(x)
+ if (x < 1)
+ fun_l25_n106(x)
+ else
+ fun_l25_n692(x)
+ end
+end
+
+def fun_l24_n709(x)
+ if (x < 1)
+ fun_l25_n484(x)
+ else
+ fun_l25_n700(x)
+ end
+end
+
+def fun_l24_n710(x)
+ if (x < 1)
+ fun_l25_n699(x)
+ else
+ fun_l25_n117(x)
+ end
+end
+
+def fun_l24_n711(x)
+ if (x < 1)
+ fun_l25_n138(x)
+ else
+ fun_l25_n532(x)
+ end
+end
+
+def fun_l24_n712(x)
+ if (x < 1)
+ fun_l25_n468(x)
+ else
+ fun_l25_n350(x)
+ end
+end
+
+def fun_l24_n713(x)
+ if (x < 1)
+ fun_l25_n906(x)
+ else
+ fun_l25_n25(x)
+ end
+end
+
+def fun_l24_n714(x)
+ if (x < 1)
+ fun_l25_n23(x)
+ else
+ fun_l25_n745(x)
+ end
+end
+
+def fun_l24_n715(x)
+ if (x < 1)
+ fun_l25_n917(x)
+ else
+ fun_l25_n942(x)
+ end
+end
+
+def fun_l24_n716(x)
+ if (x < 1)
+ fun_l25_n986(x)
+ else
+ fun_l25_n605(x)
+ end
+end
+
+def fun_l24_n717(x)
+ if (x < 1)
+ fun_l25_n771(x)
+ else
+ fun_l25_n100(x)
+ end
+end
+
+def fun_l24_n718(x)
+ if (x < 1)
+ fun_l25_n994(x)
+ else
+ fun_l25_n249(x)
+ end
+end
+
+def fun_l24_n719(x)
+ if (x < 1)
+ fun_l25_n368(x)
+ else
+ fun_l25_n657(x)
+ end
+end
+
+def fun_l24_n720(x)
+ if (x < 1)
+ fun_l25_n856(x)
+ else
+ fun_l25_n650(x)
+ end
+end
+
+def fun_l24_n721(x)
+ if (x < 1)
+ fun_l25_n667(x)
+ else
+ fun_l25_n609(x)
+ end
+end
+
+def fun_l24_n722(x)
+ if (x < 1)
+ fun_l25_n353(x)
+ else
+ fun_l25_n665(x)
+ end
+end
+
+def fun_l24_n723(x)
+ if (x < 1)
+ fun_l25_n520(x)
+ else
+ fun_l25_n771(x)
+ end
+end
+
+def fun_l24_n724(x)
+ if (x < 1)
+ fun_l25_n636(x)
+ else
+ fun_l25_n34(x)
+ end
+end
+
+def fun_l24_n725(x)
+ if (x < 1)
+ fun_l25_n222(x)
+ else
+ fun_l25_n444(x)
+ end
+end
+
+def fun_l24_n726(x)
+ if (x < 1)
+ fun_l25_n519(x)
+ else
+ fun_l25_n675(x)
+ end
+end
+
+def fun_l24_n727(x)
+ if (x < 1)
+ fun_l25_n739(x)
+ else
+ fun_l25_n910(x)
+ end
+end
+
+def fun_l24_n728(x)
+ if (x < 1)
+ fun_l25_n669(x)
+ else
+ fun_l25_n645(x)
+ end
+end
+
+def fun_l24_n729(x)
+ if (x < 1)
+ fun_l25_n358(x)
+ else
+ fun_l25_n316(x)
+ end
+end
+
+def fun_l24_n730(x)
+ if (x < 1)
+ fun_l25_n614(x)
+ else
+ fun_l25_n484(x)
+ end
+end
+
+def fun_l24_n731(x)
+ if (x < 1)
+ fun_l25_n640(x)
+ else
+ fun_l25_n613(x)
+ end
+end
+
+def fun_l24_n732(x)
+ if (x < 1)
+ fun_l25_n16(x)
+ else
+ fun_l25_n596(x)
+ end
+end
+
+def fun_l24_n733(x)
+ if (x < 1)
+ fun_l25_n780(x)
+ else
+ fun_l25_n673(x)
+ end
+end
+
+def fun_l24_n734(x)
+ if (x < 1)
+ fun_l25_n999(x)
+ else
+ fun_l25_n210(x)
+ end
+end
+
+def fun_l24_n735(x)
+ if (x < 1)
+ fun_l25_n915(x)
+ else
+ fun_l25_n788(x)
+ end
+end
+
+def fun_l24_n736(x)
+ if (x < 1)
+ fun_l25_n484(x)
+ else
+ fun_l25_n369(x)
+ end
+end
+
+def fun_l24_n737(x)
+ if (x < 1)
+ fun_l25_n851(x)
+ else
+ fun_l25_n674(x)
+ end
+end
+
+def fun_l24_n738(x)
+ if (x < 1)
+ fun_l25_n830(x)
+ else
+ fun_l25_n382(x)
+ end
+end
+
+def fun_l24_n739(x)
+ if (x < 1)
+ fun_l25_n861(x)
+ else
+ fun_l25_n482(x)
+ end
+end
+
+def fun_l24_n740(x)
+ if (x < 1)
+ fun_l25_n244(x)
+ else
+ fun_l25_n414(x)
+ end
+end
+
+def fun_l24_n741(x)
+ if (x < 1)
+ fun_l25_n829(x)
+ else
+ fun_l25_n846(x)
+ end
+end
+
+def fun_l24_n742(x)
+ if (x < 1)
+ fun_l25_n197(x)
+ else
+ fun_l25_n943(x)
+ end
+end
+
+def fun_l24_n743(x)
+ if (x < 1)
+ fun_l25_n290(x)
+ else
+ fun_l25_n394(x)
+ end
+end
+
+def fun_l24_n744(x)
+ if (x < 1)
+ fun_l25_n965(x)
+ else
+ fun_l25_n987(x)
+ end
+end
+
+def fun_l24_n745(x)
+ if (x < 1)
+ fun_l25_n104(x)
+ else
+ fun_l25_n369(x)
+ end
+end
+
+def fun_l24_n746(x)
+ if (x < 1)
+ fun_l25_n880(x)
+ else
+ fun_l25_n541(x)
+ end
+end
+
+def fun_l24_n747(x)
+ if (x < 1)
+ fun_l25_n345(x)
+ else
+ fun_l25_n155(x)
+ end
+end
+
+def fun_l24_n748(x)
+ if (x < 1)
+ fun_l25_n803(x)
+ else
+ fun_l25_n383(x)
+ end
+end
+
+def fun_l24_n749(x)
+ if (x < 1)
+ fun_l25_n848(x)
+ else
+ fun_l25_n340(x)
+ end
+end
+
+def fun_l24_n750(x)
+ if (x < 1)
+ fun_l25_n197(x)
+ else
+ fun_l25_n313(x)
+ end
+end
+
+def fun_l24_n751(x)
+ if (x < 1)
+ fun_l25_n253(x)
+ else
+ fun_l25_n99(x)
+ end
+end
+
+def fun_l24_n752(x)
+ if (x < 1)
+ fun_l25_n873(x)
+ else
+ fun_l25_n347(x)
+ end
+end
+
+def fun_l24_n753(x)
+ if (x < 1)
+ fun_l25_n849(x)
+ else
+ fun_l25_n627(x)
+ end
+end
+
+def fun_l24_n754(x)
+ if (x < 1)
+ fun_l25_n817(x)
+ else
+ fun_l25_n441(x)
+ end
+end
+
+def fun_l24_n755(x)
+ if (x < 1)
+ fun_l25_n235(x)
+ else
+ fun_l25_n602(x)
+ end
+end
+
+def fun_l24_n756(x)
+ if (x < 1)
+ fun_l25_n950(x)
+ else
+ fun_l25_n516(x)
+ end
+end
+
+def fun_l24_n757(x)
+ if (x < 1)
+ fun_l25_n646(x)
+ else
+ fun_l25_n996(x)
+ end
+end
+
+def fun_l24_n758(x)
+ if (x < 1)
+ fun_l25_n27(x)
+ else
+ fun_l25_n650(x)
+ end
+end
+
+def fun_l24_n759(x)
+ if (x < 1)
+ fun_l25_n290(x)
+ else
+ fun_l25_n852(x)
+ end
+end
+
+def fun_l24_n760(x)
+ if (x < 1)
+ fun_l25_n118(x)
+ else
+ fun_l25_n871(x)
+ end
+end
+
+def fun_l24_n761(x)
+ if (x < 1)
+ fun_l25_n372(x)
+ else
+ fun_l25_n537(x)
+ end
+end
+
+def fun_l24_n762(x)
+ if (x < 1)
+ fun_l25_n124(x)
+ else
+ fun_l25_n939(x)
+ end
+end
+
+def fun_l24_n763(x)
+ if (x < 1)
+ fun_l25_n163(x)
+ else
+ fun_l25_n787(x)
+ end
+end
+
+def fun_l24_n764(x)
+ if (x < 1)
+ fun_l25_n485(x)
+ else
+ fun_l25_n753(x)
+ end
+end
+
+def fun_l24_n765(x)
+ if (x < 1)
+ fun_l25_n181(x)
+ else
+ fun_l25_n595(x)
+ end
+end
+
+def fun_l24_n766(x)
+ if (x < 1)
+ fun_l25_n909(x)
+ else
+ fun_l25_n734(x)
+ end
+end
+
+def fun_l24_n767(x)
+ if (x < 1)
+ fun_l25_n980(x)
+ else
+ fun_l25_n673(x)
+ end
+end
+
+def fun_l24_n768(x)
+ if (x < 1)
+ fun_l25_n756(x)
+ else
+ fun_l25_n429(x)
+ end
+end
+
+def fun_l24_n769(x)
+ if (x < 1)
+ fun_l25_n301(x)
+ else
+ fun_l25_n197(x)
+ end
+end
+
+def fun_l24_n770(x)
+ if (x < 1)
+ fun_l25_n977(x)
+ else
+ fun_l25_n569(x)
+ end
+end
+
+def fun_l24_n771(x)
+ if (x < 1)
+ fun_l25_n829(x)
+ else
+ fun_l25_n34(x)
+ end
+end
+
+def fun_l24_n772(x)
+ if (x < 1)
+ fun_l25_n601(x)
+ else
+ fun_l25_n762(x)
+ end
+end
+
+def fun_l24_n773(x)
+ if (x < 1)
+ fun_l25_n790(x)
+ else
+ fun_l25_n282(x)
+ end
+end
+
+def fun_l24_n774(x)
+ if (x < 1)
+ fun_l25_n464(x)
+ else
+ fun_l25_n814(x)
+ end
+end
+
+def fun_l24_n775(x)
+ if (x < 1)
+ fun_l25_n562(x)
+ else
+ fun_l25_n543(x)
+ end
+end
+
+def fun_l24_n776(x)
+ if (x < 1)
+ fun_l25_n869(x)
+ else
+ fun_l25_n857(x)
+ end
+end
+
+def fun_l24_n777(x)
+ if (x < 1)
+ fun_l25_n206(x)
+ else
+ fun_l25_n369(x)
+ end
+end
+
+def fun_l24_n778(x)
+ if (x < 1)
+ fun_l25_n43(x)
+ else
+ fun_l25_n405(x)
+ end
+end
+
+def fun_l24_n779(x)
+ if (x < 1)
+ fun_l25_n116(x)
+ else
+ fun_l25_n644(x)
+ end
+end
+
+def fun_l24_n780(x)
+ if (x < 1)
+ fun_l25_n455(x)
+ else
+ fun_l25_n174(x)
+ end
+end
+
+def fun_l24_n781(x)
+ if (x < 1)
+ fun_l25_n234(x)
+ else
+ fun_l25_n887(x)
+ end
+end
+
+def fun_l24_n782(x)
+ if (x < 1)
+ fun_l25_n157(x)
+ else
+ fun_l25_n459(x)
+ end
+end
+
+def fun_l24_n783(x)
+ if (x < 1)
+ fun_l25_n441(x)
+ else
+ fun_l25_n830(x)
+ end
+end
+
+def fun_l24_n784(x)
+ if (x < 1)
+ fun_l25_n908(x)
+ else
+ fun_l25_n363(x)
+ end
+end
+
+def fun_l24_n785(x)
+ if (x < 1)
+ fun_l25_n495(x)
+ else
+ fun_l25_n790(x)
+ end
+end
+
+def fun_l24_n786(x)
+ if (x < 1)
+ fun_l25_n365(x)
+ else
+ fun_l25_n561(x)
+ end
+end
+
+def fun_l24_n787(x)
+ if (x < 1)
+ fun_l25_n419(x)
+ else
+ fun_l25_n471(x)
+ end
+end
+
+def fun_l24_n788(x)
+ if (x < 1)
+ fun_l25_n568(x)
+ else
+ fun_l25_n807(x)
+ end
+end
+
+def fun_l24_n789(x)
+ if (x < 1)
+ fun_l25_n148(x)
+ else
+ fun_l25_n476(x)
+ end
+end
+
+def fun_l24_n790(x)
+ if (x < 1)
+ fun_l25_n470(x)
+ else
+ fun_l25_n662(x)
+ end
+end
+
+def fun_l24_n791(x)
+ if (x < 1)
+ fun_l25_n307(x)
+ else
+ fun_l25_n828(x)
+ end
+end
+
+def fun_l24_n792(x)
+ if (x < 1)
+ fun_l25_n227(x)
+ else
+ fun_l25_n802(x)
+ end
+end
+
+def fun_l24_n793(x)
+ if (x < 1)
+ fun_l25_n891(x)
+ else
+ fun_l25_n561(x)
+ end
+end
+
+def fun_l24_n794(x)
+ if (x < 1)
+ fun_l25_n465(x)
+ else
+ fun_l25_n805(x)
+ end
+end
+
+def fun_l24_n795(x)
+ if (x < 1)
+ fun_l25_n869(x)
+ else
+ fun_l25_n250(x)
+ end
+end
+
+def fun_l24_n796(x)
+ if (x < 1)
+ fun_l25_n479(x)
+ else
+ fun_l25_n996(x)
+ end
+end
+
+def fun_l24_n797(x)
+ if (x < 1)
+ fun_l25_n773(x)
+ else
+ fun_l25_n294(x)
+ end
+end
+
+def fun_l24_n798(x)
+ if (x < 1)
+ fun_l25_n601(x)
+ else
+ fun_l25_n259(x)
+ end
+end
+
+def fun_l24_n799(x)
+ if (x < 1)
+ fun_l25_n334(x)
+ else
+ fun_l25_n696(x)
+ end
+end
+
+def fun_l24_n800(x)
+ if (x < 1)
+ fun_l25_n6(x)
+ else
+ fun_l25_n184(x)
+ end
+end
+
+def fun_l24_n801(x)
+ if (x < 1)
+ fun_l25_n345(x)
+ else
+ fun_l25_n476(x)
+ end
+end
+
+def fun_l24_n802(x)
+ if (x < 1)
+ fun_l25_n957(x)
+ else
+ fun_l25_n893(x)
+ end
+end
+
+def fun_l24_n803(x)
+ if (x < 1)
+ fun_l25_n541(x)
+ else
+ fun_l25_n562(x)
+ end
+end
+
+def fun_l24_n804(x)
+ if (x < 1)
+ fun_l25_n403(x)
+ else
+ fun_l25_n398(x)
+ end
+end
+
+def fun_l24_n805(x)
+ if (x < 1)
+ fun_l25_n759(x)
+ else
+ fun_l25_n861(x)
+ end
+end
+
+def fun_l24_n806(x)
+ if (x < 1)
+ fun_l25_n145(x)
+ else
+ fun_l25_n460(x)
+ end
+end
+
+def fun_l24_n807(x)
+ if (x < 1)
+ fun_l25_n960(x)
+ else
+ fun_l25_n865(x)
+ end
+end
+
+def fun_l24_n808(x)
+ if (x < 1)
+ fun_l25_n386(x)
+ else
+ fun_l25_n443(x)
+ end
+end
+
+def fun_l24_n809(x)
+ if (x < 1)
+ fun_l25_n789(x)
+ else
+ fun_l25_n295(x)
+ end
+end
+
+def fun_l24_n810(x)
+ if (x < 1)
+ fun_l25_n985(x)
+ else
+ fun_l25_n15(x)
+ end
+end
+
+def fun_l24_n811(x)
+ if (x < 1)
+ fun_l25_n976(x)
+ else
+ fun_l25_n636(x)
+ end
+end
+
+def fun_l24_n812(x)
+ if (x < 1)
+ fun_l25_n183(x)
+ else
+ fun_l25_n146(x)
+ end
+end
+
+def fun_l24_n813(x)
+ if (x < 1)
+ fun_l25_n457(x)
+ else
+ fun_l25_n141(x)
+ end
+end
+
+def fun_l24_n814(x)
+ if (x < 1)
+ fun_l25_n1(x)
+ else
+ fun_l25_n708(x)
+ end
+end
+
+def fun_l24_n815(x)
+ if (x < 1)
+ fun_l25_n696(x)
+ else
+ fun_l25_n898(x)
+ end
+end
+
+def fun_l24_n816(x)
+ if (x < 1)
+ fun_l25_n423(x)
+ else
+ fun_l25_n250(x)
+ end
+end
+
+def fun_l24_n817(x)
+ if (x < 1)
+ fun_l25_n432(x)
+ else
+ fun_l25_n918(x)
+ end
+end
+
+def fun_l24_n818(x)
+ if (x < 1)
+ fun_l25_n712(x)
+ else
+ fun_l25_n8(x)
+ end
+end
+
+def fun_l24_n819(x)
+ if (x < 1)
+ fun_l25_n331(x)
+ else
+ fun_l25_n194(x)
+ end
+end
+
+def fun_l24_n820(x)
+ if (x < 1)
+ fun_l25_n106(x)
+ else
+ fun_l25_n588(x)
+ end
+end
+
+def fun_l24_n821(x)
+ if (x < 1)
+ fun_l25_n662(x)
+ else
+ fun_l25_n365(x)
+ end
+end
+
+def fun_l24_n822(x)
+ if (x < 1)
+ fun_l25_n461(x)
+ else
+ fun_l25_n931(x)
+ end
+end
+
+def fun_l24_n823(x)
+ if (x < 1)
+ fun_l25_n243(x)
+ else
+ fun_l25_n26(x)
+ end
+end
+
+def fun_l24_n824(x)
+ if (x < 1)
+ fun_l25_n6(x)
+ else
+ fun_l25_n787(x)
+ end
+end
+
+def fun_l24_n825(x)
+ if (x < 1)
+ fun_l25_n536(x)
+ else
+ fun_l25_n721(x)
+ end
+end
+
+def fun_l24_n826(x)
+ if (x < 1)
+ fun_l25_n693(x)
+ else
+ fun_l25_n649(x)
+ end
+end
+
+def fun_l24_n827(x)
+ if (x < 1)
+ fun_l25_n662(x)
+ else
+ fun_l25_n981(x)
+ end
+end
+
+def fun_l24_n828(x)
+ if (x < 1)
+ fun_l25_n594(x)
+ else
+ fun_l25_n345(x)
+ end
+end
+
+def fun_l24_n829(x)
+ if (x < 1)
+ fun_l25_n917(x)
+ else
+ fun_l25_n665(x)
+ end
+end
+
+def fun_l24_n830(x)
+ if (x < 1)
+ fun_l25_n246(x)
+ else
+ fun_l25_n58(x)
+ end
+end
+
+def fun_l24_n831(x)
+ if (x < 1)
+ fun_l25_n415(x)
+ else
+ fun_l25_n617(x)
+ end
+end
+
+def fun_l24_n832(x)
+ if (x < 1)
+ fun_l25_n596(x)
+ else
+ fun_l25_n858(x)
+ end
+end
+
+def fun_l24_n833(x)
+ if (x < 1)
+ fun_l25_n810(x)
+ else
+ fun_l25_n532(x)
+ end
+end
+
+def fun_l24_n834(x)
+ if (x < 1)
+ fun_l25_n298(x)
+ else
+ fun_l25_n881(x)
+ end
+end
+
+def fun_l24_n835(x)
+ if (x < 1)
+ fun_l25_n791(x)
+ else
+ fun_l25_n344(x)
+ end
+end
+
+def fun_l24_n836(x)
+ if (x < 1)
+ fun_l25_n531(x)
+ else
+ fun_l25_n880(x)
+ end
+end
+
+def fun_l24_n837(x)
+ if (x < 1)
+ fun_l25_n571(x)
+ else
+ fun_l25_n306(x)
+ end
+end
+
+def fun_l24_n838(x)
+ if (x < 1)
+ fun_l25_n191(x)
+ else
+ fun_l25_n450(x)
+ end
+end
+
+def fun_l24_n839(x)
+ if (x < 1)
+ fun_l25_n777(x)
+ else
+ fun_l25_n234(x)
+ end
+end
+
+def fun_l24_n840(x)
+ if (x < 1)
+ fun_l25_n876(x)
+ else
+ fun_l25_n548(x)
+ end
+end
+
+def fun_l24_n841(x)
+ if (x < 1)
+ fun_l25_n83(x)
+ else
+ fun_l25_n346(x)
+ end
+end
+
+def fun_l24_n842(x)
+ if (x < 1)
+ fun_l25_n976(x)
+ else
+ fun_l25_n843(x)
+ end
+end
+
+def fun_l24_n843(x)
+ if (x < 1)
+ fun_l25_n559(x)
+ else
+ fun_l25_n424(x)
+ end
+end
+
+def fun_l24_n844(x)
+ if (x < 1)
+ fun_l25_n974(x)
+ else
+ fun_l25_n906(x)
+ end
+end
+
+def fun_l24_n845(x)
+ if (x < 1)
+ fun_l25_n274(x)
+ else
+ fun_l25_n528(x)
+ end
+end
+
+def fun_l24_n846(x)
+ if (x < 1)
+ fun_l25_n773(x)
+ else
+ fun_l25_n507(x)
+ end
+end
+
+def fun_l24_n847(x)
+ if (x < 1)
+ fun_l25_n80(x)
+ else
+ fun_l25_n274(x)
+ end
+end
+
+def fun_l24_n848(x)
+ if (x < 1)
+ fun_l25_n557(x)
+ else
+ fun_l25_n541(x)
+ end
+end
+
+def fun_l24_n849(x)
+ if (x < 1)
+ fun_l25_n208(x)
+ else
+ fun_l25_n765(x)
+ end
+end
+
+def fun_l24_n850(x)
+ if (x < 1)
+ fun_l25_n705(x)
+ else
+ fun_l25_n81(x)
+ end
+end
+
+def fun_l24_n851(x)
+ if (x < 1)
+ fun_l25_n151(x)
+ else
+ fun_l25_n706(x)
+ end
+end
+
+def fun_l24_n852(x)
+ if (x < 1)
+ fun_l25_n723(x)
+ else
+ fun_l25_n451(x)
+ end
+end
+
+def fun_l24_n853(x)
+ if (x < 1)
+ fun_l25_n155(x)
+ else
+ fun_l25_n48(x)
+ end
+end
+
+def fun_l24_n854(x)
+ if (x < 1)
+ fun_l25_n317(x)
+ else
+ fun_l25_n118(x)
+ end
+end
+
+def fun_l24_n855(x)
+ if (x < 1)
+ fun_l25_n794(x)
+ else
+ fun_l25_n880(x)
+ end
+end
+
+def fun_l24_n856(x)
+ if (x < 1)
+ fun_l25_n556(x)
+ else
+ fun_l25_n255(x)
+ end
+end
+
+def fun_l24_n857(x)
+ if (x < 1)
+ fun_l25_n665(x)
+ else
+ fun_l25_n640(x)
+ end
+end
+
+def fun_l24_n858(x)
+ if (x < 1)
+ fun_l25_n732(x)
+ else
+ fun_l25_n771(x)
+ end
+end
+
+def fun_l24_n859(x)
+ if (x < 1)
+ fun_l25_n367(x)
+ else
+ fun_l25_n616(x)
+ end
+end
+
+def fun_l24_n860(x)
+ if (x < 1)
+ fun_l25_n184(x)
+ else
+ fun_l25_n912(x)
+ end
+end
+
+def fun_l24_n861(x)
+ if (x < 1)
+ fun_l25_n916(x)
+ else
+ fun_l25_n66(x)
+ end
+end
+
+def fun_l24_n862(x)
+ if (x < 1)
+ fun_l25_n526(x)
+ else
+ fun_l25_n807(x)
+ end
+end
+
+def fun_l24_n863(x)
+ if (x < 1)
+ fun_l25_n83(x)
+ else
+ fun_l25_n180(x)
+ end
+end
+
+def fun_l24_n864(x)
+ if (x < 1)
+ fun_l25_n199(x)
+ else
+ fun_l25_n471(x)
+ end
+end
+
+def fun_l24_n865(x)
+ if (x < 1)
+ fun_l25_n763(x)
+ else
+ fun_l25_n16(x)
+ end
+end
+
+def fun_l24_n866(x)
+ if (x < 1)
+ fun_l25_n280(x)
+ else
+ fun_l25_n66(x)
+ end
+end
+
+def fun_l24_n867(x)
+ if (x < 1)
+ fun_l25_n366(x)
+ else
+ fun_l25_n143(x)
+ end
+end
+
+def fun_l24_n868(x)
+ if (x < 1)
+ fun_l25_n110(x)
+ else
+ fun_l25_n151(x)
+ end
+end
+
+def fun_l24_n869(x)
+ if (x < 1)
+ fun_l25_n936(x)
+ else
+ fun_l25_n153(x)
+ end
+end
+
+def fun_l24_n870(x)
+ if (x < 1)
+ fun_l25_n555(x)
+ else
+ fun_l25_n915(x)
+ end
+end
+
+def fun_l24_n871(x)
+ if (x < 1)
+ fun_l25_n199(x)
+ else
+ fun_l25_n613(x)
+ end
+end
+
+def fun_l24_n872(x)
+ if (x < 1)
+ fun_l25_n381(x)
+ else
+ fun_l25_n899(x)
+ end
+end
+
+def fun_l24_n873(x)
+ if (x < 1)
+ fun_l25_n64(x)
+ else
+ fun_l25_n337(x)
+ end
+end
+
+def fun_l24_n874(x)
+ if (x < 1)
+ fun_l25_n753(x)
+ else
+ fun_l25_n981(x)
+ end
+end
+
+def fun_l24_n875(x)
+ if (x < 1)
+ fun_l25_n113(x)
+ else
+ fun_l25_n126(x)
+ end
+end
+
+def fun_l24_n876(x)
+ if (x < 1)
+ fun_l25_n3(x)
+ else
+ fun_l25_n288(x)
+ end
+end
+
+def fun_l24_n877(x)
+ if (x < 1)
+ fun_l25_n359(x)
+ else
+ fun_l25_n596(x)
+ end
+end
+
+def fun_l24_n878(x)
+ if (x < 1)
+ fun_l25_n937(x)
+ else
+ fun_l25_n72(x)
+ end
+end
+
+def fun_l24_n879(x)
+ if (x < 1)
+ fun_l25_n495(x)
+ else
+ fun_l25_n368(x)
+ end
+end
+
+def fun_l24_n880(x)
+ if (x < 1)
+ fun_l25_n524(x)
+ else
+ fun_l25_n228(x)
+ end
+end
+
+def fun_l24_n881(x)
+ if (x < 1)
+ fun_l25_n438(x)
+ else
+ fun_l25_n986(x)
+ end
+end
+
+def fun_l24_n882(x)
+ if (x < 1)
+ fun_l25_n334(x)
+ else
+ fun_l25_n54(x)
+ end
+end
+
+def fun_l24_n883(x)
+ if (x < 1)
+ fun_l25_n612(x)
+ else
+ fun_l25_n126(x)
+ end
+end
+
+def fun_l24_n884(x)
+ if (x < 1)
+ fun_l25_n316(x)
+ else
+ fun_l25_n222(x)
+ end
+end
+
+def fun_l24_n885(x)
+ if (x < 1)
+ fun_l25_n915(x)
+ else
+ fun_l25_n971(x)
+ end
+end
+
+def fun_l24_n886(x)
+ if (x < 1)
+ fun_l25_n987(x)
+ else
+ fun_l25_n499(x)
+ end
+end
+
+def fun_l24_n887(x)
+ if (x < 1)
+ fun_l25_n476(x)
+ else
+ fun_l25_n280(x)
+ end
+end
+
+def fun_l24_n888(x)
+ if (x < 1)
+ fun_l25_n420(x)
+ else
+ fun_l25_n584(x)
+ end
+end
+
+def fun_l24_n889(x)
+ if (x < 1)
+ fun_l25_n560(x)
+ else
+ fun_l25_n767(x)
+ end
+end
+
+def fun_l24_n890(x)
+ if (x < 1)
+ fun_l25_n26(x)
+ else
+ fun_l25_n431(x)
+ end
+end
+
+def fun_l24_n891(x)
+ if (x < 1)
+ fun_l25_n107(x)
+ else
+ fun_l25_n803(x)
+ end
+end
+
+def fun_l24_n892(x)
+ if (x < 1)
+ fun_l25_n225(x)
+ else
+ fun_l25_n665(x)
+ end
+end
+
+def fun_l24_n893(x)
+ if (x < 1)
+ fun_l25_n19(x)
+ else
+ fun_l25_n507(x)
+ end
+end
+
+def fun_l24_n894(x)
+ if (x < 1)
+ fun_l25_n44(x)
+ else
+ fun_l25_n420(x)
+ end
+end
+
+def fun_l24_n895(x)
+ if (x < 1)
+ fun_l25_n526(x)
+ else
+ fun_l25_n871(x)
+ end
+end
+
+def fun_l24_n896(x)
+ if (x < 1)
+ fun_l25_n900(x)
+ else
+ fun_l25_n824(x)
+ end
+end
+
+def fun_l24_n897(x)
+ if (x < 1)
+ fun_l25_n105(x)
+ else
+ fun_l25_n602(x)
+ end
+end
+
+def fun_l24_n898(x)
+ if (x < 1)
+ fun_l25_n228(x)
+ else
+ fun_l25_n993(x)
+ end
+end
+
+def fun_l24_n899(x)
+ if (x < 1)
+ fun_l25_n330(x)
+ else
+ fun_l25_n60(x)
+ end
+end
+
+def fun_l24_n900(x)
+ if (x < 1)
+ fun_l25_n512(x)
+ else
+ fun_l25_n708(x)
+ end
+end
+
+def fun_l24_n901(x)
+ if (x < 1)
+ fun_l25_n791(x)
+ else
+ fun_l25_n554(x)
+ end
+end
+
+def fun_l24_n902(x)
+ if (x < 1)
+ fun_l25_n204(x)
+ else
+ fun_l25_n439(x)
+ end
+end
+
+def fun_l24_n903(x)
+ if (x < 1)
+ fun_l25_n577(x)
+ else
+ fun_l25_n174(x)
+ end
+end
+
+def fun_l24_n904(x)
+ if (x < 1)
+ fun_l25_n713(x)
+ else
+ fun_l25_n35(x)
+ end
+end
+
+def fun_l24_n905(x)
+ if (x < 1)
+ fun_l25_n290(x)
+ else
+ fun_l25_n342(x)
+ end
+end
+
+def fun_l24_n906(x)
+ if (x < 1)
+ fun_l25_n607(x)
+ else
+ fun_l25_n52(x)
+ end
+end
+
+def fun_l24_n907(x)
+ if (x < 1)
+ fun_l25_n72(x)
+ else
+ fun_l25_n169(x)
+ end
+end
+
+def fun_l24_n908(x)
+ if (x < 1)
+ fun_l25_n179(x)
+ else
+ fun_l25_n383(x)
+ end
+end
+
+def fun_l24_n909(x)
+ if (x < 1)
+ fun_l25_n52(x)
+ else
+ fun_l25_n504(x)
+ end
+end
+
+def fun_l24_n910(x)
+ if (x < 1)
+ fun_l25_n346(x)
+ else
+ fun_l25_n775(x)
+ end
+end
+
+def fun_l24_n911(x)
+ if (x < 1)
+ fun_l25_n535(x)
+ else
+ fun_l25_n210(x)
+ end
+end
+
+def fun_l24_n912(x)
+ if (x < 1)
+ fun_l25_n937(x)
+ else
+ fun_l25_n409(x)
+ end
+end
+
+def fun_l24_n913(x)
+ if (x < 1)
+ fun_l25_n889(x)
+ else
+ fun_l25_n463(x)
+ end
+end
+
+def fun_l24_n914(x)
+ if (x < 1)
+ fun_l25_n75(x)
+ else
+ fun_l25_n817(x)
+ end
+end
+
+def fun_l24_n915(x)
+ if (x < 1)
+ fun_l25_n277(x)
+ else
+ fun_l25_n3(x)
+ end
+end
+
+def fun_l24_n916(x)
+ if (x < 1)
+ fun_l25_n97(x)
+ else
+ fun_l25_n819(x)
+ end
+end
+
+def fun_l24_n917(x)
+ if (x < 1)
+ fun_l25_n412(x)
+ else
+ fun_l25_n851(x)
+ end
+end
+
+def fun_l24_n918(x)
+ if (x < 1)
+ fun_l25_n803(x)
+ else
+ fun_l25_n429(x)
+ end
+end
+
+def fun_l24_n919(x)
+ if (x < 1)
+ fun_l25_n12(x)
+ else
+ fun_l25_n434(x)
+ end
+end
+
+def fun_l24_n920(x)
+ if (x < 1)
+ fun_l25_n721(x)
+ else
+ fun_l25_n553(x)
+ end
+end
+
+def fun_l24_n921(x)
+ if (x < 1)
+ fun_l25_n438(x)
+ else
+ fun_l25_n211(x)
+ end
+end
+
+def fun_l24_n922(x)
+ if (x < 1)
+ fun_l25_n123(x)
+ else
+ fun_l25_n89(x)
+ end
+end
+
+def fun_l24_n923(x)
+ if (x < 1)
+ fun_l25_n696(x)
+ else
+ fun_l25_n78(x)
+ end
+end
+
+def fun_l24_n924(x)
+ if (x < 1)
+ fun_l25_n556(x)
+ else
+ fun_l25_n788(x)
+ end
+end
+
+def fun_l24_n925(x)
+ if (x < 1)
+ fun_l25_n928(x)
+ else
+ fun_l25_n797(x)
+ end
+end
+
+def fun_l24_n926(x)
+ if (x < 1)
+ fun_l25_n796(x)
+ else
+ fun_l25_n84(x)
+ end
+end
+
+def fun_l24_n927(x)
+ if (x < 1)
+ fun_l25_n874(x)
+ else
+ fun_l25_n255(x)
+ end
+end
+
+def fun_l24_n928(x)
+ if (x < 1)
+ fun_l25_n715(x)
+ else
+ fun_l25_n812(x)
+ end
+end
+
+def fun_l24_n929(x)
+ if (x < 1)
+ fun_l25_n384(x)
+ else
+ fun_l25_n859(x)
+ end
+end
+
+def fun_l24_n930(x)
+ if (x < 1)
+ fun_l25_n133(x)
+ else
+ fun_l25_n923(x)
+ end
+end
+
+def fun_l24_n931(x)
+ if (x < 1)
+ fun_l25_n712(x)
+ else
+ fun_l25_n850(x)
+ end
+end
+
+def fun_l24_n932(x)
+ if (x < 1)
+ fun_l25_n301(x)
+ else
+ fun_l25_n743(x)
+ end
+end
+
+def fun_l24_n933(x)
+ if (x < 1)
+ fun_l25_n554(x)
+ else
+ fun_l25_n4(x)
+ end
+end
+
+def fun_l24_n934(x)
+ if (x < 1)
+ fun_l25_n407(x)
+ else
+ fun_l25_n656(x)
+ end
+end
+
+def fun_l24_n935(x)
+ if (x < 1)
+ fun_l25_n109(x)
+ else
+ fun_l25_n356(x)
+ end
+end
+
+def fun_l24_n936(x)
+ if (x < 1)
+ fun_l25_n985(x)
+ else
+ fun_l25_n183(x)
+ end
+end
+
+def fun_l24_n937(x)
+ if (x < 1)
+ fun_l25_n365(x)
+ else
+ fun_l25_n949(x)
+ end
+end
+
+def fun_l24_n938(x)
+ if (x < 1)
+ fun_l25_n672(x)
+ else
+ fun_l25_n417(x)
+ end
+end
+
+def fun_l24_n939(x)
+ if (x < 1)
+ fun_l25_n360(x)
+ else
+ fun_l25_n271(x)
+ end
+end
+
+def fun_l24_n940(x)
+ if (x < 1)
+ fun_l25_n654(x)
+ else
+ fun_l25_n365(x)
+ end
+end
+
+def fun_l24_n941(x)
+ if (x < 1)
+ fun_l25_n836(x)
+ else
+ fun_l25_n303(x)
+ end
+end
+
+def fun_l24_n942(x)
+ if (x < 1)
+ fun_l25_n299(x)
+ else
+ fun_l25_n130(x)
+ end
+end
+
+def fun_l24_n943(x)
+ if (x < 1)
+ fun_l25_n566(x)
+ else
+ fun_l25_n347(x)
+ end
+end
+
+def fun_l24_n944(x)
+ if (x < 1)
+ fun_l25_n754(x)
+ else
+ fun_l25_n670(x)
+ end
+end
+
+def fun_l24_n945(x)
+ if (x < 1)
+ fun_l25_n484(x)
+ else
+ fun_l25_n278(x)
+ end
+end
+
+def fun_l24_n946(x)
+ if (x < 1)
+ fun_l25_n35(x)
+ else
+ fun_l25_n915(x)
+ end
+end
+
+def fun_l24_n947(x)
+ if (x < 1)
+ fun_l25_n488(x)
+ else
+ fun_l25_n664(x)
+ end
+end
+
+def fun_l24_n948(x)
+ if (x < 1)
+ fun_l25_n249(x)
+ else
+ fun_l25_n931(x)
+ end
+end
+
+def fun_l24_n949(x)
+ if (x < 1)
+ fun_l25_n165(x)
+ else
+ fun_l25_n101(x)
+ end
+end
+
+def fun_l24_n950(x)
+ if (x < 1)
+ fun_l25_n304(x)
+ else
+ fun_l25_n668(x)
+ end
+end
+
+def fun_l24_n951(x)
+ if (x < 1)
+ fun_l25_n279(x)
+ else
+ fun_l25_n600(x)
+ end
+end
+
+def fun_l24_n952(x)
+ if (x < 1)
+ fun_l25_n70(x)
+ else
+ fun_l25_n852(x)
+ end
+end
+
+def fun_l24_n953(x)
+ if (x < 1)
+ fun_l25_n419(x)
+ else
+ fun_l25_n856(x)
+ end
+end
+
+def fun_l24_n954(x)
+ if (x < 1)
+ fun_l25_n55(x)
+ else
+ fun_l25_n857(x)
+ end
+end
+
+def fun_l24_n955(x)
+ if (x < 1)
+ fun_l25_n122(x)
+ else
+ fun_l25_n658(x)
+ end
+end
+
+def fun_l24_n956(x)
+ if (x < 1)
+ fun_l25_n973(x)
+ else
+ fun_l25_n421(x)
+ end
+end
+
+def fun_l24_n957(x)
+ if (x < 1)
+ fun_l25_n82(x)
+ else
+ fun_l25_n264(x)
+ end
+end
+
+def fun_l24_n958(x)
+ if (x < 1)
+ fun_l25_n608(x)
+ else
+ fun_l25_n469(x)
+ end
+end
+
+def fun_l24_n959(x)
+ if (x < 1)
+ fun_l25_n823(x)
+ else
+ fun_l25_n320(x)
+ end
+end
+
+def fun_l24_n960(x)
+ if (x < 1)
+ fun_l25_n765(x)
+ else
+ fun_l25_n461(x)
+ end
+end
+
+def fun_l24_n961(x)
+ if (x < 1)
+ fun_l25_n343(x)
+ else
+ fun_l25_n18(x)
+ end
+end
+
+def fun_l24_n962(x)
+ if (x < 1)
+ fun_l25_n346(x)
+ else
+ fun_l25_n821(x)
+ end
+end
+
+def fun_l24_n963(x)
+ if (x < 1)
+ fun_l25_n80(x)
+ else
+ fun_l25_n949(x)
+ end
+end
+
+def fun_l24_n964(x)
+ if (x < 1)
+ fun_l25_n171(x)
+ else
+ fun_l25_n514(x)
+ end
+end
+
+def fun_l24_n965(x)
+ if (x < 1)
+ fun_l25_n625(x)
+ else
+ fun_l25_n768(x)
+ end
+end
+
+def fun_l24_n966(x)
+ if (x < 1)
+ fun_l25_n390(x)
+ else
+ fun_l25_n195(x)
+ end
+end
+
+def fun_l24_n967(x)
+ if (x < 1)
+ fun_l25_n774(x)
+ else
+ fun_l25_n928(x)
+ end
+end
+
+def fun_l24_n968(x)
+ if (x < 1)
+ fun_l25_n997(x)
+ else
+ fun_l25_n441(x)
+ end
+end
+
+def fun_l24_n969(x)
+ if (x < 1)
+ fun_l25_n865(x)
+ else
+ fun_l25_n418(x)
+ end
+end
+
+def fun_l24_n970(x)
+ if (x < 1)
+ fun_l25_n238(x)
+ else
+ fun_l25_n816(x)
+ end
+end
+
+def fun_l24_n971(x)
+ if (x < 1)
+ fun_l25_n521(x)
+ else
+ fun_l25_n427(x)
+ end
+end
+
+def fun_l24_n972(x)
+ if (x < 1)
+ fun_l25_n214(x)
+ else
+ fun_l25_n282(x)
+ end
+end
+
+def fun_l24_n973(x)
+ if (x < 1)
+ fun_l25_n611(x)
+ else
+ fun_l25_n439(x)
+ end
+end
+
+def fun_l24_n974(x)
+ if (x < 1)
+ fun_l25_n395(x)
+ else
+ fun_l25_n593(x)
+ end
+end
+
+def fun_l24_n975(x)
+ if (x < 1)
+ fun_l25_n720(x)
+ else
+ fun_l25_n477(x)
+ end
+end
+
+def fun_l24_n976(x)
+ if (x < 1)
+ fun_l25_n204(x)
+ else
+ fun_l25_n912(x)
+ end
+end
+
+def fun_l24_n977(x)
+ if (x < 1)
+ fun_l25_n703(x)
+ else
+ fun_l25_n651(x)
+ end
+end
+
+def fun_l24_n978(x)
+ if (x < 1)
+ fun_l25_n247(x)
+ else
+ fun_l25_n917(x)
+ end
+end
+
+def fun_l24_n979(x)
+ if (x < 1)
+ fun_l25_n792(x)
+ else
+ fun_l25_n320(x)
+ end
+end
+
+def fun_l24_n980(x)
+ if (x < 1)
+ fun_l25_n480(x)
+ else
+ fun_l25_n128(x)
+ end
+end
+
+def fun_l24_n981(x)
+ if (x < 1)
+ fun_l25_n848(x)
+ else
+ fun_l25_n344(x)
+ end
+end
+
+def fun_l24_n982(x)
+ if (x < 1)
+ fun_l25_n84(x)
+ else
+ fun_l25_n977(x)
+ end
+end
+
+def fun_l24_n983(x)
+ if (x < 1)
+ fun_l25_n213(x)
+ else
+ fun_l25_n131(x)
+ end
+end
+
+def fun_l24_n984(x)
+ if (x < 1)
+ fun_l25_n2(x)
+ else
+ fun_l25_n21(x)
+ end
+end
+
+def fun_l24_n985(x)
+ if (x < 1)
+ fun_l25_n301(x)
+ else
+ fun_l25_n910(x)
+ end
+end
+
+def fun_l24_n986(x)
+ if (x < 1)
+ fun_l25_n533(x)
+ else
+ fun_l25_n397(x)
+ end
+end
+
+def fun_l24_n987(x)
+ if (x < 1)
+ fun_l25_n226(x)
+ else
+ fun_l25_n281(x)
+ end
+end
+
+def fun_l24_n988(x)
+ if (x < 1)
+ fun_l25_n402(x)
+ else
+ fun_l25_n70(x)
+ end
+end
+
+def fun_l24_n989(x)
+ if (x < 1)
+ fun_l25_n190(x)
+ else
+ fun_l25_n70(x)
+ end
+end
+
+def fun_l24_n990(x)
+ if (x < 1)
+ fun_l25_n376(x)
+ else
+ fun_l25_n331(x)
+ end
+end
+
+def fun_l24_n991(x)
+ if (x < 1)
+ fun_l25_n915(x)
+ else
+ fun_l25_n234(x)
+ end
+end
+
+def fun_l24_n992(x)
+ if (x < 1)
+ fun_l25_n146(x)
+ else
+ fun_l25_n825(x)
+ end
+end
+
+def fun_l24_n993(x)
+ if (x < 1)
+ fun_l25_n877(x)
+ else
+ fun_l25_n237(x)
+ end
+end
+
+def fun_l24_n994(x)
+ if (x < 1)
+ fun_l25_n454(x)
+ else
+ fun_l25_n852(x)
+ end
+end
+
+def fun_l24_n995(x)
+ if (x < 1)
+ fun_l25_n45(x)
+ else
+ fun_l25_n337(x)
+ end
+end
+
+def fun_l24_n996(x)
+ if (x < 1)
+ fun_l25_n491(x)
+ else
+ fun_l25_n319(x)
+ end
+end
+
+def fun_l24_n997(x)
+ if (x < 1)
+ fun_l25_n216(x)
+ else
+ fun_l25_n249(x)
+ end
+end
+
+def fun_l24_n998(x)
+ if (x < 1)
+ fun_l25_n370(x)
+ else
+ fun_l25_n747(x)
+ end
+end
+
+def fun_l24_n999(x)
+ if (x < 1)
+ fun_l25_n584(x)
+ else
+ fun_l25_n813(x)
+ end
+end
+
+def fun_l25_n0(x)
+ if (x < 1)
+ fun_l26_n818(x)
+ else
+ fun_l26_n750(x)
+ end
+end
+
+def fun_l25_n1(x)
+ if (x < 1)
+ fun_l26_n725(x)
+ else
+ fun_l26_n848(x)
+ end
+end
+
+def fun_l25_n2(x)
+ if (x < 1)
+ fun_l26_n716(x)
+ else
+ fun_l26_n190(x)
+ end
+end
+
+def fun_l25_n3(x)
+ if (x < 1)
+ fun_l26_n977(x)
+ else
+ fun_l26_n222(x)
+ end
+end
+
+def fun_l25_n4(x)
+ if (x < 1)
+ fun_l26_n931(x)
+ else
+ fun_l26_n615(x)
+ end
+end
+
+def fun_l25_n5(x)
+ if (x < 1)
+ fun_l26_n720(x)
+ else
+ fun_l26_n440(x)
+ end
+end
+
+def fun_l25_n6(x)
+ if (x < 1)
+ fun_l26_n400(x)
+ else
+ fun_l26_n336(x)
+ end
+end
+
+def fun_l25_n7(x)
+ if (x < 1)
+ fun_l26_n109(x)
+ else
+ fun_l26_n74(x)
+ end
+end
+
+def fun_l25_n8(x)
+ if (x < 1)
+ fun_l26_n12(x)
+ else
+ fun_l26_n857(x)
+ end
+end
+
+def fun_l25_n9(x)
+ if (x < 1)
+ fun_l26_n778(x)
+ else
+ fun_l26_n286(x)
+ end
+end
+
+def fun_l25_n10(x)
+ if (x < 1)
+ fun_l26_n857(x)
+ else
+ fun_l26_n311(x)
+ end
+end
+
+def fun_l25_n11(x)
+ if (x < 1)
+ fun_l26_n204(x)
+ else
+ fun_l26_n348(x)
+ end
+end
+
+def fun_l25_n12(x)
+ if (x < 1)
+ fun_l26_n626(x)
+ else
+ fun_l26_n983(x)
+ end
+end
+
+def fun_l25_n13(x)
+ if (x < 1)
+ fun_l26_n417(x)
+ else
+ fun_l26_n334(x)
+ end
+end
+
+def fun_l25_n14(x)
+ if (x < 1)
+ fun_l26_n34(x)
+ else
+ fun_l26_n269(x)
+ end
+end
+
+def fun_l25_n15(x)
+ if (x < 1)
+ fun_l26_n184(x)
+ else
+ fun_l26_n183(x)
+ end
+end
+
+def fun_l25_n16(x)
+ if (x < 1)
+ fun_l26_n744(x)
+ else
+ fun_l26_n450(x)
+ end
+end
+
+def fun_l25_n17(x)
+ if (x < 1)
+ fun_l26_n763(x)
+ else
+ fun_l26_n390(x)
+ end
+end
+
+def fun_l25_n18(x)
+ if (x < 1)
+ fun_l26_n926(x)
+ else
+ fun_l26_n379(x)
+ end
+end
+
+def fun_l25_n19(x)
+ if (x < 1)
+ fun_l26_n746(x)
+ else
+ fun_l26_n946(x)
+ end
+end
+
+def fun_l25_n20(x)
+ if (x < 1)
+ fun_l26_n500(x)
+ else
+ fun_l26_n599(x)
+ end
+end
+
+def fun_l25_n21(x)
+ if (x < 1)
+ fun_l26_n757(x)
+ else
+ fun_l26_n725(x)
+ end
+end
+
+def fun_l25_n22(x)
+ if (x < 1)
+ fun_l26_n738(x)
+ else
+ fun_l26_n24(x)
+ end
+end
+
+def fun_l25_n23(x)
+ if (x < 1)
+ fun_l26_n350(x)
+ else
+ fun_l26_n344(x)
+ end
+end
+
+def fun_l25_n24(x)
+ if (x < 1)
+ fun_l26_n521(x)
+ else
+ fun_l26_n680(x)
+ end
+end
+
+def fun_l25_n25(x)
+ if (x < 1)
+ fun_l26_n647(x)
+ else
+ fun_l26_n604(x)
+ end
+end
+
+def fun_l25_n26(x)
+ if (x < 1)
+ fun_l26_n990(x)
+ else
+ fun_l26_n262(x)
+ end
+end
+
+def fun_l25_n27(x)
+ if (x < 1)
+ fun_l26_n309(x)
+ else
+ fun_l26_n759(x)
+ end
+end
+
+def fun_l25_n28(x)
+ if (x < 1)
+ fun_l26_n720(x)
+ else
+ fun_l26_n11(x)
+ end
+end
+
+def fun_l25_n29(x)
+ if (x < 1)
+ fun_l26_n761(x)
+ else
+ fun_l26_n690(x)
+ end
+end
+
+def fun_l25_n30(x)
+ if (x < 1)
+ fun_l26_n729(x)
+ else
+ fun_l26_n577(x)
+ end
+end
+
+def fun_l25_n31(x)
+ if (x < 1)
+ fun_l26_n321(x)
+ else
+ fun_l26_n608(x)
+ end
+end
+
+def fun_l25_n32(x)
+ if (x < 1)
+ fun_l26_n325(x)
+ else
+ fun_l26_n541(x)
+ end
+end
+
+def fun_l25_n33(x)
+ if (x < 1)
+ fun_l26_n644(x)
+ else
+ fun_l26_n15(x)
+ end
+end
+
+def fun_l25_n34(x)
+ if (x < 1)
+ fun_l26_n53(x)
+ else
+ fun_l26_n887(x)
+ end
+end
+
+def fun_l25_n35(x)
+ if (x < 1)
+ fun_l26_n470(x)
+ else
+ fun_l26_n564(x)
+ end
+end
+
+def fun_l25_n36(x)
+ if (x < 1)
+ fun_l26_n198(x)
+ else
+ fun_l26_n542(x)
+ end
+end
+
+def fun_l25_n37(x)
+ if (x < 1)
+ fun_l26_n455(x)
+ else
+ fun_l26_n373(x)
+ end
+end
+
+def fun_l25_n38(x)
+ if (x < 1)
+ fun_l26_n216(x)
+ else
+ fun_l26_n86(x)
+ end
+end
+
+def fun_l25_n39(x)
+ if (x < 1)
+ fun_l26_n417(x)
+ else
+ fun_l26_n50(x)
+ end
+end
+
+def fun_l25_n40(x)
+ if (x < 1)
+ fun_l26_n955(x)
+ else
+ fun_l26_n979(x)
+ end
+end
+
+def fun_l25_n41(x)
+ if (x < 1)
+ fun_l26_n692(x)
+ else
+ fun_l26_n935(x)
+ end
+end
+
+def fun_l25_n42(x)
+ if (x < 1)
+ fun_l26_n360(x)
+ else
+ fun_l26_n246(x)
+ end
+end
+
+def fun_l25_n43(x)
+ if (x < 1)
+ fun_l26_n826(x)
+ else
+ fun_l26_n433(x)
+ end
+end
+
+def fun_l25_n44(x)
+ if (x < 1)
+ fun_l26_n222(x)
+ else
+ fun_l26_n101(x)
+ end
+end
+
+def fun_l25_n45(x)
+ if (x < 1)
+ fun_l26_n590(x)
+ else
+ fun_l26_n398(x)
+ end
+end
+
+def fun_l25_n46(x)
+ if (x < 1)
+ fun_l26_n959(x)
+ else
+ fun_l26_n620(x)
+ end
+end
+
+def fun_l25_n47(x)
+ if (x < 1)
+ fun_l26_n530(x)
+ else
+ fun_l26_n503(x)
+ end
+end
+
+def fun_l25_n48(x)
+ if (x < 1)
+ fun_l26_n615(x)
+ else
+ fun_l26_n640(x)
+ end
+end
+
+def fun_l25_n49(x)
+ if (x < 1)
+ fun_l26_n774(x)
+ else
+ fun_l26_n23(x)
+ end
+end
+
+def fun_l25_n50(x)
+ if (x < 1)
+ fun_l26_n344(x)
+ else
+ fun_l26_n303(x)
+ end
+end
+
+def fun_l25_n51(x)
+ if (x < 1)
+ fun_l26_n54(x)
+ else
+ fun_l26_n26(x)
+ end
+end
+
+def fun_l25_n52(x)
+ if (x < 1)
+ fun_l26_n545(x)
+ else
+ fun_l26_n791(x)
+ end
+end
+
+def fun_l25_n53(x)
+ if (x < 1)
+ fun_l26_n554(x)
+ else
+ fun_l26_n42(x)
+ end
+end
+
+def fun_l25_n54(x)
+ if (x < 1)
+ fun_l26_n419(x)
+ else
+ fun_l26_n179(x)
+ end
+end
+
+def fun_l25_n55(x)
+ if (x < 1)
+ fun_l26_n845(x)
+ else
+ fun_l26_n641(x)
+ end
+end
+
+def fun_l25_n56(x)
+ if (x < 1)
+ fun_l26_n389(x)
+ else
+ fun_l26_n547(x)
+ end
+end
+
+def fun_l25_n57(x)
+ if (x < 1)
+ fun_l26_n744(x)
+ else
+ fun_l26_n946(x)
+ end
+end
+
+def fun_l25_n58(x)
+ if (x < 1)
+ fun_l26_n410(x)
+ else
+ fun_l26_n909(x)
+ end
+end
+
+def fun_l25_n59(x)
+ if (x < 1)
+ fun_l26_n126(x)
+ else
+ fun_l26_n382(x)
+ end
+end
+
+def fun_l25_n60(x)
+ if (x < 1)
+ fun_l26_n355(x)
+ else
+ fun_l26_n902(x)
+ end
+end
+
+def fun_l25_n61(x)
+ if (x < 1)
+ fun_l26_n759(x)
+ else
+ fun_l26_n445(x)
+ end
+end
+
+def fun_l25_n62(x)
+ if (x < 1)
+ fun_l26_n859(x)
+ else
+ fun_l26_n362(x)
+ end
+end
+
+def fun_l25_n63(x)
+ if (x < 1)
+ fun_l26_n488(x)
+ else
+ fun_l26_n725(x)
+ end
+end
+
+def fun_l25_n64(x)
+ if (x < 1)
+ fun_l26_n268(x)
+ else
+ fun_l26_n865(x)
+ end
+end
+
+def fun_l25_n65(x)
+ if (x < 1)
+ fun_l26_n33(x)
+ else
+ fun_l26_n417(x)
+ end
+end
+
+def fun_l25_n66(x)
+ if (x < 1)
+ fun_l26_n281(x)
+ else
+ fun_l26_n485(x)
+ end
+end
+
+def fun_l25_n67(x)
+ if (x < 1)
+ fun_l26_n627(x)
+ else
+ fun_l26_n200(x)
+ end
+end
+
+def fun_l25_n68(x)
+ if (x < 1)
+ fun_l26_n392(x)
+ else
+ fun_l26_n639(x)
+ end
+end
+
+def fun_l25_n69(x)
+ if (x < 1)
+ fun_l26_n799(x)
+ else
+ fun_l26_n242(x)
+ end
+end
+
+def fun_l25_n70(x)
+ if (x < 1)
+ fun_l26_n783(x)
+ else
+ fun_l26_n564(x)
+ end
+end
+
+def fun_l25_n71(x)
+ if (x < 1)
+ fun_l26_n768(x)
+ else
+ fun_l26_n908(x)
+ end
+end
+
+def fun_l25_n72(x)
+ if (x < 1)
+ fun_l26_n567(x)
+ else
+ fun_l26_n365(x)
+ end
+end
+
+def fun_l25_n73(x)
+ if (x < 1)
+ fun_l26_n291(x)
+ else
+ fun_l26_n887(x)
+ end
+end
+
+def fun_l25_n74(x)
+ if (x < 1)
+ fun_l26_n889(x)
+ else
+ fun_l26_n180(x)
+ end
+end
+
+def fun_l25_n75(x)
+ if (x < 1)
+ fun_l26_n142(x)
+ else
+ fun_l26_n101(x)
+ end
+end
+
+def fun_l25_n76(x)
+ if (x < 1)
+ fun_l26_n108(x)
+ else
+ fun_l26_n863(x)
+ end
+end
+
+def fun_l25_n77(x)
+ if (x < 1)
+ fun_l26_n441(x)
+ else
+ fun_l26_n51(x)
+ end
+end
+
+def fun_l25_n78(x)
+ if (x < 1)
+ fun_l26_n787(x)
+ else
+ fun_l26_n543(x)
+ end
+end
+
+def fun_l25_n79(x)
+ if (x < 1)
+ fun_l26_n699(x)
+ else
+ fun_l26_n513(x)
+ end
+end
+
+def fun_l25_n80(x)
+ if (x < 1)
+ fun_l26_n400(x)
+ else
+ fun_l26_n72(x)
+ end
+end
+
+def fun_l25_n81(x)
+ if (x < 1)
+ fun_l26_n814(x)
+ else
+ fun_l26_n732(x)
+ end
+end
+
+def fun_l25_n82(x)
+ if (x < 1)
+ fun_l26_n755(x)
+ else
+ fun_l26_n606(x)
+ end
+end
+
+def fun_l25_n83(x)
+ if (x < 1)
+ fun_l26_n351(x)
+ else
+ fun_l26_n208(x)
+ end
+end
+
+def fun_l25_n84(x)
+ if (x < 1)
+ fun_l26_n124(x)
+ else
+ fun_l26_n554(x)
+ end
+end
+
+def fun_l25_n85(x)
+ if (x < 1)
+ fun_l26_n19(x)
+ else
+ fun_l26_n58(x)
+ end
+end
+
+def fun_l25_n86(x)
+ if (x < 1)
+ fun_l26_n710(x)
+ else
+ fun_l26_n300(x)
+ end
+end
+
+def fun_l25_n87(x)
+ if (x < 1)
+ fun_l26_n833(x)
+ else
+ fun_l26_n53(x)
+ end
+end
+
+def fun_l25_n88(x)
+ if (x < 1)
+ fun_l26_n923(x)
+ else
+ fun_l26_n445(x)
+ end
+end
+
+def fun_l25_n89(x)
+ if (x < 1)
+ fun_l26_n674(x)
+ else
+ fun_l26_n176(x)
+ end
+end
+
+def fun_l25_n90(x)
+ if (x < 1)
+ fun_l26_n78(x)
+ else
+ fun_l26_n506(x)
+ end
+end
+
+def fun_l25_n91(x)
+ if (x < 1)
+ fun_l26_n352(x)
+ else
+ fun_l26_n312(x)
+ end
+end
+
+def fun_l25_n92(x)
+ if (x < 1)
+ fun_l26_n400(x)
+ else
+ fun_l26_n787(x)
+ end
+end
+
+def fun_l25_n93(x)
+ if (x < 1)
+ fun_l26_n897(x)
+ else
+ fun_l26_n395(x)
+ end
+end
+
+def fun_l25_n94(x)
+ if (x < 1)
+ fun_l26_n267(x)
+ else
+ fun_l26_n974(x)
+ end
+end
+
+def fun_l25_n95(x)
+ if (x < 1)
+ fun_l26_n547(x)
+ else
+ fun_l26_n280(x)
+ end
+end
+
+def fun_l25_n96(x)
+ if (x < 1)
+ fun_l26_n281(x)
+ else
+ fun_l26_n222(x)
+ end
+end
+
+def fun_l25_n97(x)
+ if (x < 1)
+ fun_l26_n130(x)
+ else
+ fun_l26_n232(x)
+ end
+end
+
+def fun_l25_n98(x)
+ if (x < 1)
+ fun_l26_n863(x)
+ else
+ fun_l26_n970(x)
+ end
+end
+
+def fun_l25_n99(x)
+ if (x < 1)
+ fun_l26_n28(x)
+ else
+ fun_l26_n344(x)
+ end
+end
+
+def fun_l25_n100(x)
+ if (x < 1)
+ fun_l26_n906(x)
+ else
+ fun_l26_n818(x)
+ end
+end
+
+def fun_l25_n101(x)
+ if (x < 1)
+ fun_l26_n658(x)
+ else
+ fun_l26_n708(x)
+ end
+end
+
+def fun_l25_n102(x)
+ if (x < 1)
+ fun_l26_n545(x)
+ else
+ fun_l26_n627(x)
+ end
+end
+
+def fun_l25_n103(x)
+ if (x < 1)
+ fun_l26_n377(x)
+ else
+ fun_l26_n555(x)
+ end
+end
+
+def fun_l25_n104(x)
+ if (x < 1)
+ fun_l26_n628(x)
+ else
+ fun_l26_n465(x)
+ end
+end
+
+def fun_l25_n105(x)
+ if (x < 1)
+ fun_l26_n208(x)
+ else
+ fun_l26_n720(x)
+ end
+end
+
+def fun_l25_n106(x)
+ if (x < 1)
+ fun_l26_n203(x)
+ else
+ fun_l26_n984(x)
+ end
+end
+
+def fun_l25_n107(x)
+ if (x < 1)
+ fun_l26_n265(x)
+ else
+ fun_l26_n124(x)
+ end
+end
+
+def fun_l25_n108(x)
+ if (x < 1)
+ fun_l26_n786(x)
+ else
+ fun_l26_n305(x)
+ end
+end
+
+def fun_l25_n109(x)
+ if (x < 1)
+ fun_l26_n907(x)
+ else
+ fun_l26_n57(x)
+ end
+end
+
+def fun_l25_n110(x)
+ if (x < 1)
+ fun_l26_n883(x)
+ else
+ fun_l26_n107(x)
+ end
+end
+
+def fun_l25_n111(x)
+ if (x < 1)
+ fun_l26_n783(x)
+ else
+ fun_l26_n443(x)
+ end
+end
+
+def fun_l25_n112(x)
+ if (x < 1)
+ fun_l26_n309(x)
+ else
+ fun_l26_n127(x)
+ end
+end
+
+def fun_l25_n113(x)
+ if (x < 1)
+ fun_l26_n578(x)
+ else
+ fun_l26_n656(x)
+ end
+end
+
+def fun_l25_n114(x)
+ if (x < 1)
+ fun_l26_n352(x)
+ else
+ fun_l26_n610(x)
+ end
+end
+
+def fun_l25_n115(x)
+ if (x < 1)
+ fun_l26_n975(x)
+ else
+ fun_l26_n580(x)
+ end
+end
+
+def fun_l25_n116(x)
+ if (x < 1)
+ fun_l26_n892(x)
+ else
+ fun_l26_n596(x)
+ end
+end
+
+def fun_l25_n117(x)
+ if (x < 1)
+ fun_l26_n80(x)
+ else
+ fun_l26_n759(x)
+ end
+end
+
+def fun_l25_n118(x)
+ if (x < 1)
+ fun_l26_n866(x)
+ else
+ fun_l26_n964(x)
+ end
+end
+
+def fun_l25_n119(x)
+ if (x < 1)
+ fun_l26_n367(x)
+ else
+ fun_l26_n896(x)
+ end
+end
+
+def fun_l25_n120(x)
+ if (x < 1)
+ fun_l26_n787(x)
+ else
+ fun_l26_n17(x)
+ end
+end
+
+def fun_l25_n121(x)
+ if (x < 1)
+ fun_l26_n312(x)
+ else
+ fun_l26_n247(x)
+ end
+end
+
+def fun_l25_n122(x)
+ if (x < 1)
+ fun_l26_n163(x)
+ else
+ fun_l26_n906(x)
+ end
+end
+
+def fun_l25_n123(x)
+ if (x < 1)
+ fun_l26_n706(x)
+ else
+ fun_l26_n840(x)
+ end
+end
+
+def fun_l25_n124(x)
+ if (x < 1)
+ fun_l26_n85(x)
+ else
+ fun_l26_n200(x)
+ end
+end
+
+def fun_l25_n125(x)
+ if (x < 1)
+ fun_l26_n389(x)
+ else
+ fun_l26_n274(x)
+ end
+end
+
+def fun_l25_n126(x)
+ if (x < 1)
+ fun_l26_n509(x)
+ else
+ fun_l26_n471(x)
+ end
+end
+
+def fun_l25_n127(x)
+ if (x < 1)
+ fun_l26_n924(x)
+ else
+ fun_l26_n132(x)
+ end
+end
+
+def fun_l25_n128(x)
+ if (x < 1)
+ fun_l26_n496(x)
+ else
+ fun_l26_n865(x)
+ end
+end
+
+def fun_l25_n129(x)
+ if (x < 1)
+ fun_l26_n775(x)
+ else
+ fun_l26_n22(x)
+ end
+end
+
+def fun_l25_n130(x)
+ if (x < 1)
+ fun_l26_n875(x)
+ else
+ fun_l26_n771(x)
+ end
+end
+
+def fun_l25_n131(x)
+ if (x < 1)
+ fun_l26_n656(x)
+ else
+ fun_l26_n709(x)
+ end
+end
+
+def fun_l25_n132(x)
+ if (x < 1)
+ fun_l26_n733(x)
+ else
+ fun_l26_n343(x)
+ end
+end
+
+def fun_l25_n133(x)
+ if (x < 1)
+ fun_l26_n791(x)
+ else
+ fun_l26_n954(x)
+ end
+end
+
+def fun_l25_n134(x)
+ if (x < 1)
+ fun_l26_n792(x)
+ else
+ fun_l26_n118(x)
+ end
+end
+
+def fun_l25_n135(x)
+ if (x < 1)
+ fun_l26_n93(x)
+ else
+ fun_l26_n683(x)
+ end
+end
+
+def fun_l25_n136(x)
+ if (x < 1)
+ fun_l26_n290(x)
+ else
+ fun_l26_n787(x)
+ end
+end
+
+def fun_l25_n137(x)
+ if (x < 1)
+ fun_l26_n459(x)
+ else
+ fun_l26_n283(x)
+ end
+end
+
+def fun_l25_n138(x)
+ if (x < 1)
+ fun_l26_n240(x)
+ else
+ fun_l26_n552(x)
+ end
+end
+
+def fun_l25_n139(x)
+ if (x < 1)
+ fun_l26_n323(x)
+ else
+ fun_l26_n157(x)
+ end
+end
+
+def fun_l25_n140(x)
+ if (x < 1)
+ fun_l26_n926(x)
+ else
+ fun_l26_n446(x)
+ end
+end
+
+def fun_l25_n141(x)
+ if (x < 1)
+ fun_l26_n382(x)
+ else
+ fun_l26_n317(x)
+ end
+end
+
+def fun_l25_n142(x)
+ if (x < 1)
+ fun_l26_n296(x)
+ else
+ fun_l26_n672(x)
+ end
+end
+
+def fun_l25_n143(x)
+ if (x < 1)
+ fun_l26_n313(x)
+ else
+ fun_l26_n222(x)
+ end
+end
+
+def fun_l25_n144(x)
+ if (x < 1)
+ fun_l26_n25(x)
+ else
+ fun_l26_n260(x)
+ end
+end
+
+def fun_l25_n145(x)
+ if (x < 1)
+ fun_l26_n457(x)
+ else
+ fun_l26_n876(x)
+ end
+end
+
+def fun_l25_n146(x)
+ if (x < 1)
+ fun_l26_n503(x)
+ else
+ fun_l26_n850(x)
+ end
+end
+
+def fun_l25_n147(x)
+ if (x < 1)
+ fun_l26_n811(x)
+ else
+ fun_l26_n293(x)
+ end
+end
+
+def fun_l25_n148(x)
+ if (x < 1)
+ fun_l26_n433(x)
+ else
+ fun_l26_n582(x)
+ end
+end
+
+def fun_l25_n149(x)
+ if (x < 1)
+ fun_l26_n860(x)
+ else
+ fun_l26_n663(x)
+ end
+end
+
+def fun_l25_n150(x)
+ if (x < 1)
+ fun_l26_n293(x)
+ else
+ fun_l26_n341(x)
+ end
+end
+
+def fun_l25_n151(x)
+ if (x < 1)
+ fun_l26_n187(x)
+ else
+ fun_l26_n430(x)
+ end
+end
+
+def fun_l25_n152(x)
+ if (x < 1)
+ fun_l26_n914(x)
+ else
+ fun_l26_n250(x)
+ end
+end
+
+def fun_l25_n153(x)
+ if (x < 1)
+ fun_l26_n370(x)
+ else
+ fun_l26_n378(x)
+ end
+end
+
+def fun_l25_n154(x)
+ if (x < 1)
+ fun_l26_n238(x)
+ else
+ fun_l26_n743(x)
+ end
+end
+
+def fun_l25_n155(x)
+ if (x < 1)
+ fun_l26_n149(x)
+ else
+ fun_l26_n556(x)
+ end
+end
+
+def fun_l25_n156(x)
+ if (x < 1)
+ fun_l26_n530(x)
+ else
+ fun_l26_n543(x)
+ end
+end
+
+def fun_l25_n157(x)
+ if (x < 1)
+ fun_l26_n230(x)
+ else
+ fun_l26_n600(x)
+ end
+end
+
+def fun_l25_n158(x)
+ if (x < 1)
+ fun_l26_n110(x)
+ else
+ fun_l26_n954(x)
+ end
+end
+
+def fun_l25_n159(x)
+ if (x < 1)
+ fun_l26_n952(x)
+ else
+ fun_l26_n110(x)
+ end
+end
+
+def fun_l25_n160(x)
+ if (x < 1)
+ fun_l26_n525(x)
+ else
+ fun_l26_n435(x)
+ end
+end
+
+def fun_l25_n161(x)
+ if (x < 1)
+ fun_l26_n511(x)
+ else
+ fun_l26_n10(x)
+ end
+end
+
+def fun_l25_n162(x)
+ if (x < 1)
+ fun_l26_n755(x)
+ else
+ fun_l26_n567(x)
+ end
+end
+
+def fun_l25_n163(x)
+ if (x < 1)
+ fun_l26_n618(x)
+ else
+ fun_l26_n249(x)
+ end
+end
+
+def fun_l25_n164(x)
+ if (x < 1)
+ fun_l26_n803(x)
+ else
+ fun_l26_n512(x)
+ end
+end
+
+def fun_l25_n165(x)
+ if (x < 1)
+ fun_l26_n234(x)
+ else
+ fun_l26_n806(x)
+ end
+end
+
+def fun_l25_n166(x)
+ if (x < 1)
+ fun_l26_n442(x)
+ else
+ fun_l26_n904(x)
+ end
+end
+
+def fun_l25_n167(x)
+ if (x < 1)
+ fun_l26_n369(x)
+ else
+ fun_l26_n910(x)
+ end
+end
+
+def fun_l25_n168(x)
+ if (x < 1)
+ fun_l26_n107(x)
+ else
+ fun_l26_n125(x)
+ end
+end
+
+def fun_l25_n169(x)
+ if (x < 1)
+ fun_l26_n415(x)
+ else
+ fun_l26_n37(x)
+ end
+end
+
+def fun_l25_n170(x)
+ if (x < 1)
+ fun_l26_n315(x)
+ else
+ fun_l26_n977(x)
+ end
+end
+
+def fun_l25_n171(x)
+ if (x < 1)
+ fun_l26_n106(x)
+ else
+ fun_l26_n908(x)
+ end
+end
+
+def fun_l25_n172(x)
+ if (x < 1)
+ fun_l26_n870(x)
+ else
+ fun_l26_n74(x)
+ end
+end
+
+def fun_l25_n173(x)
+ if (x < 1)
+ fun_l26_n290(x)
+ else
+ fun_l26_n938(x)
+ end
+end
+
+def fun_l25_n174(x)
+ if (x < 1)
+ fun_l26_n908(x)
+ else
+ fun_l26_n215(x)
+ end
+end
+
+def fun_l25_n175(x)
+ if (x < 1)
+ fun_l26_n671(x)
+ else
+ fun_l26_n976(x)
+ end
+end
+
+def fun_l25_n176(x)
+ if (x < 1)
+ fun_l26_n727(x)
+ else
+ fun_l26_n559(x)
+ end
+end
+
+def fun_l25_n177(x)
+ if (x < 1)
+ fun_l26_n684(x)
+ else
+ fun_l26_n353(x)
+ end
+end
+
+def fun_l25_n178(x)
+ if (x < 1)
+ fun_l26_n353(x)
+ else
+ fun_l26_n327(x)
+ end
+end
+
+def fun_l25_n179(x)
+ if (x < 1)
+ fun_l26_n393(x)
+ else
+ fun_l26_n774(x)
+ end
+end
+
+def fun_l25_n180(x)
+ if (x < 1)
+ fun_l26_n500(x)
+ else
+ fun_l26_n23(x)
+ end
+end
+
+def fun_l25_n181(x)
+ if (x < 1)
+ fun_l26_n49(x)
+ else
+ fun_l26_n504(x)
+ end
+end
+
+def fun_l25_n182(x)
+ if (x < 1)
+ fun_l26_n631(x)
+ else
+ fun_l26_n147(x)
+ end
+end
+
+def fun_l25_n183(x)
+ if (x < 1)
+ fun_l26_n353(x)
+ else
+ fun_l26_n64(x)
+ end
+end
+
+def fun_l25_n184(x)
+ if (x < 1)
+ fun_l26_n215(x)
+ else
+ fun_l26_n416(x)
+ end
+end
+
+def fun_l25_n185(x)
+ if (x < 1)
+ fun_l26_n701(x)
+ else
+ fun_l26_n809(x)
+ end
+end
+
+def fun_l25_n186(x)
+ if (x < 1)
+ fun_l26_n267(x)
+ else
+ fun_l26_n197(x)
+ end
+end
+
+def fun_l25_n187(x)
+ if (x < 1)
+ fun_l26_n436(x)
+ else
+ fun_l26_n609(x)
+ end
+end
+
+def fun_l25_n188(x)
+ if (x < 1)
+ fun_l26_n993(x)
+ else
+ fun_l26_n740(x)
+ end
+end
+
+def fun_l25_n189(x)
+ if (x < 1)
+ fun_l26_n742(x)
+ else
+ fun_l26_n507(x)
+ end
+end
+
+def fun_l25_n190(x)
+ if (x < 1)
+ fun_l26_n850(x)
+ else
+ fun_l26_n394(x)
+ end
+end
+
+def fun_l25_n191(x)
+ if (x < 1)
+ fun_l26_n494(x)
+ else
+ fun_l26_n219(x)
+ end
+end
+
+def fun_l25_n192(x)
+ if (x < 1)
+ fun_l26_n477(x)
+ else
+ fun_l26_n115(x)
+ end
+end
+
+def fun_l25_n193(x)
+ if (x < 1)
+ fun_l26_n629(x)
+ else
+ fun_l26_n772(x)
+ end
+end
+
+def fun_l25_n194(x)
+ if (x < 1)
+ fun_l26_n995(x)
+ else
+ fun_l26_n75(x)
+ end
+end
+
+def fun_l25_n195(x)
+ if (x < 1)
+ fun_l26_n34(x)
+ else
+ fun_l26_n590(x)
+ end
+end
+
+def fun_l25_n196(x)
+ if (x < 1)
+ fun_l26_n767(x)
+ else
+ fun_l26_n468(x)
+ end
+end
+
+def fun_l25_n197(x)
+ if (x < 1)
+ fun_l26_n883(x)
+ else
+ fun_l26_n757(x)
+ end
+end
+
+def fun_l25_n198(x)
+ if (x < 1)
+ fun_l26_n687(x)
+ else
+ fun_l26_n288(x)
+ end
+end
+
+def fun_l25_n199(x)
+ if (x < 1)
+ fun_l26_n328(x)
+ else
+ fun_l26_n556(x)
+ end
+end
+
+def fun_l25_n200(x)
+ if (x < 1)
+ fun_l26_n894(x)
+ else
+ fun_l26_n854(x)
+ end
+end
+
+def fun_l25_n201(x)
+ if (x < 1)
+ fun_l26_n343(x)
+ else
+ fun_l26_n889(x)
+ end
+end
+
+def fun_l25_n202(x)
+ if (x < 1)
+ fun_l26_n430(x)
+ else
+ fun_l26_n935(x)
+ end
+end
+
+def fun_l25_n203(x)
+ if (x < 1)
+ fun_l26_n384(x)
+ else
+ fun_l26_n37(x)
+ end
+end
+
+def fun_l25_n204(x)
+ if (x < 1)
+ fun_l26_n821(x)
+ else
+ fun_l26_n509(x)
+ end
+end
+
+def fun_l25_n205(x)
+ if (x < 1)
+ fun_l26_n985(x)
+ else
+ fun_l26_n877(x)
+ end
+end
+
+def fun_l25_n206(x)
+ if (x < 1)
+ fun_l26_n184(x)
+ else
+ fun_l26_n568(x)
+ end
+end
+
+def fun_l25_n207(x)
+ if (x < 1)
+ fun_l26_n753(x)
+ else
+ fun_l26_n922(x)
+ end
+end
+
+def fun_l25_n208(x)
+ if (x < 1)
+ fun_l26_n454(x)
+ else
+ fun_l26_n499(x)
+ end
+end
+
+def fun_l25_n209(x)
+ if (x < 1)
+ fun_l26_n695(x)
+ else
+ fun_l26_n181(x)
+ end
+end
+
+def fun_l25_n210(x)
+ if (x < 1)
+ fun_l26_n139(x)
+ else
+ fun_l26_n456(x)
+ end
+end
+
+def fun_l25_n211(x)
+ if (x < 1)
+ fun_l26_n745(x)
+ else
+ fun_l26_n447(x)
+ end
+end
+
+def fun_l25_n212(x)
+ if (x < 1)
+ fun_l26_n785(x)
+ else
+ fun_l26_n946(x)
+ end
+end
+
+def fun_l25_n213(x)
+ if (x < 1)
+ fun_l26_n161(x)
+ else
+ fun_l26_n283(x)
+ end
+end
+
+def fun_l25_n214(x)
+ if (x < 1)
+ fun_l26_n16(x)
+ else
+ fun_l26_n450(x)
+ end
+end
+
+def fun_l25_n215(x)
+ if (x < 1)
+ fun_l26_n818(x)
+ else
+ fun_l26_n2(x)
+ end
+end
+
+def fun_l25_n216(x)
+ if (x < 1)
+ fun_l26_n242(x)
+ else
+ fun_l26_n691(x)
+ end
+end
+
+def fun_l25_n217(x)
+ if (x < 1)
+ fun_l26_n18(x)
+ else
+ fun_l26_n522(x)
+ end
+end
+
+def fun_l25_n218(x)
+ if (x < 1)
+ fun_l26_n87(x)
+ else
+ fun_l26_n888(x)
+ end
+end
+
+def fun_l25_n219(x)
+ if (x < 1)
+ fun_l26_n317(x)
+ else
+ fun_l26_n593(x)
+ end
+end
+
+def fun_l25_n220(x)
+ if (x < 1)
+ fun_l26_n650(x)
+ else
+ fun_l26_n258(x)
+ end
+end
+
+def fun_l25_n221(x)
+ if (x < 1)
+ fun_l26_n381(x)
+ else
+ fun_l26_n500(x)
+ end
+end
+
+def fun_l25_n222(x)
+ if (x < 1)
+ fun_l26_n607(x)
+ else
+ fun_l26_n138(x)
+ end
+end
+
+def fun_l25_n223(x)
+ if (x < 1)
+ fun_l26_n595(x)
+ else
+ fun_l26_n657(x)
+ end
+end
+
+def fun_l25_n224(x)
+ if (x < 1)
+ fun_l26_n166(x)
+ else
+ fun_l26_n420(x)
+ end
+end
+
+def fun_l25_n225(x)
+ if (x < 1)
+ fun_l26_n744(x)
+ else
+ fun_l26_n684(x)
+ end
+end
+
+def fun_l25_n226(x)
+ if (x < 1)
+ fun_l26_n225(x)
+ else
+ fun_l26_n264(x)
+ end
+end
+
+def fun_l25_n227(x)
+ if (x < 1)
+ fun_l26_n140(x)
+ else
+ fun_l26_n387(x)
+ end
+end
+
+def fun_l25_n228(x)
+ if (x < 1)
+ fun_l26_n563(x)
+ else
+ fun_l26_n83(x)
+ end
+end
+
+def fun_l25_n229(x)
+ if (x < 1)
+ fun_l26_n392(x)
+ else
+ fun_l26_n130(x)
+ end
+end
+
+def fun_l25_n230(x)
+ if (x < 1)
+ fun_l26_n687(x)
+ else
+ fun_l26_n970(x)
+ end
+end
+
+def fun_l25_n231(x)
+ if (x < 1)
+ fun_l26_n328(x)
+ else
+ fun_l26_n809(x)
+ end
+end
+
+def fun_l25_n232(x)
+ if (x < 1)
+ fun_l26_n963(x)
+ else
+ fun_l26_n429(x)
+ end
+end
+
+def fun_l25_n233(x)
+ if (x < 1)
+ fun_l26_n290(x)
+ else
+ fun_l26_n131(x)
+ end
+end
+
+def fun_l25_n234(x)
+ if (x < 1)
+ fun_l26_n877(x)
+ else
+ fun_l26_n729(x)
+ end
+end
+
+def fun_l25_n235(x)
+ if (x < 1)
+ fun_l26_n916(x)
+ else
+ fun_l26_n694(x)
+ end
+end
+
+def fun_l25_n236(x)
+ if (x < 1)
+ fun_l26_n901(x)
+ else
+ fun_l26_n226(x)
+ end
+end
+
+def fun_l25_n237(x)
+ if (x < 1)
+ fun_l26_n65(x)
+ else
+ fun_l26_n748(x)
+ end
+end
+
+def fun_l25_n238(x)
+ if (x < 1)
+ fun_l26_n171(x)
+ else
+ fun_l26_n858(x)
+ end
+end
+
+def fun_l25_n239(x)
+ if (x < 1)
+ fun_l26_n391(x)
+ else
+ fun_l26_n809(x)
+ end
+end
+
+def fun_l25_n240(x)
+ if (x < 1)
+ fun_l26_n336(x)
+ else
+ fun_l26_n391(x)
+ end
+end
+
+def fun_l25_n241(x)
+ if (x < 1)
+ fun_l26_n418(x)
+ else
+ fun_l26_n133(x)
+ end
+end
+
+def fun_l25_n242(x)
+ if (x < 1)
+ fun_l26_n617(x)
+ else
+ fun_l26_n283(x)
+ end
+end
+
+def fun_l25_n243(x)
+ if (x < 1)
+ fun_l26_n962(x)
+ else
+ fun_l26_n763(x)
+ end
+end
+
+def fun_l25_n244(x)
+ if (x < 1)
+ fun_l26_n34(x)
+ else
+ fun_l26_n629(x)
+ end
+end
+
+def fun_l25_n245(x)
+ if (x < 1)
+ fun_l26_n444(x)
+ else
+ fun_l26_n271(x)
+ end
+end
+
+def fun_l25_n246(x)
+ if (x < 1)
+ fun_l26_n478(x)
+ else
+ fun_l26_n541(x)
+ end
+end
+
+def fun_l25_n247(x)
+ if (x < 1)
+ fun_l26_n796(x)
+ else
+ fun_l26_n673(x)
+ end
+end
+
+def fun_l25_n248(x)
+ if (x < 1)
+ fun_l26_n400(x)
+ else
+ fun_l26_n602(x)
+ end
+end
+
+def fun_l25_n249(x)
+ if (x < 1)
+ fun_l26_n70(x)
+ else
+ fun_l26_n796(x)
+ end
+end
+
+def fun_l25_n250(x)
+ if (x < 1)
+ fun_l26_n187(x)
+ else
+ fun_l26_n602(x)
+ end
+end
+
+def fun_l25_n251(x)
+ if (x < 1)
+ fun_l26_n29(x)
+ else
+ fun_l26_n283(x)
+ end
+end
+
+def fun_l25_n252(x)
+ if (x < 1)
+ fun_l26_n49(x)
+ else
+ fun_l26_n522(x)
+ end
+end
+
+def fun_l25_n253(x)
+ if (x < 1)
+ fun_l26_n998(x)
+ else
+ fun_l26_n986(x)
+ end
+end
+
+def fun_l25_n254(x)
+ if (x < 1)
+ fun_l26_n586(x)
+ else
+ fun_l26_n566(x)
+ end
+end
+
+def fun_l25_n255(x)
+ if (x < 1)
+ fun_l26_n474(x)
+ else
+ fun_l26_n279(x)
+ end
+end
+
+def fun_l25_n256(x)
+ if (x < 1)
+ fun_l26_n769(x)
+ else
+ fun_l26_n240(x)
+ end
+end
+
+def fun_l25_n257(x)
+ if (x < 1)
+ fun_l26_n212(x)
+ else
+ fun_l26_n512(x)
+ end
+end
+
+def fun_l25_n258(x)
+ if (x < 1)
+ fun_l26_n980(x)
+ else
+ fun_l26_n715(x)
+ end
+end
+
+def fun_l25_n259(x)
+ if (x < 1)
+ fun_l26_n237(x)
+ else
+ fun_l26_n355(x)
+ end
+end
+
+def fun_l25_n260(x)
+ if (x < 1)
+ fun_l26_n406(x)
+ else
+ fun_l26_n584(x)
+ end
+end
+
+def fun_l25_n261(x)
+ if (x < 1)
+ fun_l26_n632(x)
+ else
+ fun_l26_n28(x)
+ end
+end
+
+def fun_l25_n262(x)
+ if (x < 1)
+ fun_l26_n481(x)
+ else
+ fun_l26_n303(x)
+ end
+end
+
+def fun_l25_n263(x)
+ if (x < 1)
+ fun_l26_n676(x)
+ else
+ fun_l26_n220(x)
+ end
+end
+
+def fun_l25_n264(x)
+ if (x < 1)
+ fun_l26_n757(x)
+ else
+ fun_l26_n58(x)
+ end
+end
+
+def fun_l25_n265(x)
+ if (x < 1)
+ fun_l26_n525(x)
+ else
+ fun_l26_n168(x)
+ end
+end
+
+def fun_l25_n266(x)
+ if (x < 1)
+ fun_l26_n832(x)
+ else
+ fun_l26_n754(x)
+ end
+end
+
+def fun_l25_n267(x)
+ if (x < 1)
+ fun_l26_n723(x)
+ else
+ fun_l26_n830(x)
+ end
+end
+
+def fun_l25_n268(x)
+ if (x < 1)
+ fun_l26_n171(x)
+ else
+ fun_l26_n411(x)
+ end
+end
+
+def fun_l25_n269(x)
+ if (x < 1)
+ fun_l26_n150(x)
+ else
+ fun_l26_n360(x)
+ end
+end
+
+def fun_l25_n270(x)
+ if (x < 1)
+ fun_l26_n401(x)
+ else
+ fun_l26_n767(x)
+ end
+end
+
+def fun_l25_n271(x)
+ if (x < 1)
+ fun_l26_n462(x)
+ else
+ fun_l26_n305(x)
+ end
+end
+
+def fun_l25_n272(x)
+ if (x < 1)
+ fun_l26_n989(x)
+ else
+ fun_l26_n780(x)
+ end
+end
+
+def fun_l25_n273(x)
+ if (x < 1)
+ fun_l26_n2(x)
+ else
+ fun_l26_n735(x)
+ end
+end
+
+def fun_l25_n274(x)
+ if (x < 1)
+ fun_l26_n646(x)
+ else
+ fun_l26_n30(x)
+ end
+end
+
+def fun_l25_n275(x)
+ if (x < 1)
+ fun_l26_n197(x)
+ else
+ fun_l26_n262(x)
+ end
+end
+
+def fun_l25_n276(x)
+ if (x < 1)
+ fun_l26_n647(x)
+ else
+ fun_l26_n715(x)
+ end
+end
+
+def fun_l25_n277(x)
+ if (x < 1)
+ fun_l26_n597(x)
+ else
+ fun_l26_n228(x)
+ end
+end
+
+def fun_l25_n278(x)
+ if (x < 1)
+ fun_l26_n880(x)
+ else
+ fun_l26_n324(x)
+ end
+end
+
+def fun_l25_n279(x)
+ if (x < 1)
+ fun_l26_n40(x)
+ else
+ fun_l26_n615(x)
+ end
+end
+
+def fun_l25_n280(x)
+ if (x < 1)
+ fun_l26_n697(x)
+ else
+ fun_l26_n671(x)
+ end
+end
+
+def fun_l25_n281(x)
+ if (x < 1)
+ fun_l26_n819(x)
+ else
+ fun_l26_n469(x)
+ end
+end
+
+def fun_l25_n282(x)
+ if (x < 1)
+ fun_l26_n427(x)
+ else
+ fun_l26_n295(x)
+ end
+end
+
+def fun_l25_n283(x)
+ if (x < 1)
+ fun_l26_n35(x)
+ else
+ fun_l26_n432(x)
+ end
+end
+
+def fun_l25_n284(x)
+ if (x < 1)
+ fun_l26_n691(x)
+ else
+ fun_l26_n846(x)
+ end
+end
+
+def fun_l25_n285(x)
+ if (x < 1)
+ fun_l26_n353(x)
+ else
+ fun_l26_n473(x)
+ end
+end
+
+def fun_l25_n286(x)
+ if (x < 1)
+ fun_l26_n959(x)
+ else
+ fun_l26_n608(x)
+ end
+end
+
+def fun_l25_n287(x)
+ if (x < 1)
+ fun_l26_n728(x)
+ else
+ fun_l26_n993(x)
+ end
+end
+
+def fun_l25_n288(x)
+ if (x < 1)
+ fun_l26_n836(x)
+ else
+ fun_l26_n587(x)
+ end
+end
+
+def fun_l25_n289(x)
+ if (x < 1)
+ fun_l26_n300(x)
+ else
+ fun_l26_n965(x)
+ end
+end
+
+def fun_l25_n290(x)
+ if (x < 1)
+ fun_l26_n925(x)
+ else
+ fun_l26_n180(x)
+ end
+end
+
+def fun_l25_n291(x)
+ if (x < 1)
+ fun_l26_n934(x)
+ else
+ fun_l26_n579(x)
+ end
+end
+
+def fun_l25_n292(x)
+ if (x < 1)
+ fun_l26_n97(x)
+ else
+ fun_l26_n33(x)
+ end
+end
+
+def fun_l25_n293(x)
+ if (x < 1)
+ fun_l26_n653(x)
+ else
+ fun_l26_n968(x)
+ end
+end
+
+def fun_l25_n294(x)
+ if (x < 1)
+ fun_l26_n264(x)
+ else
+ fun_l26_n68(x)
+ end
+end
+
+def fun_l25_n295(x)
+ if (x < 1)
+ fun_l26_n420(x)
+ else
+ fun_l26_n450(x)
+ end
+end
+
+def fun_l25_n296(x)
+ if (x < 1)
+ fun_l26_n200(x)
+ else
+ fun_l26_n599(x)
+ end
+end
+
+def fun_l25_n297(x)
+ if (x < 1)
+ fun_l26_n922(x)
+ else
+ fun_l26_n36(x)
+ end
+end
+
+def fun_l25_n298(x)
+ if (x < 1)
+ fun_l26_n741(x)
+ else
+ fun_l26_n743(x)
+ end
+end
+
+def fun_l25_n299(x)
+ if (x < 1)
+ fun_l26_n989(x)
+ else
+ fun_l26_n777(x)
+ end
+end
+
+def fun_l25_n300(x)
+ if (x < 1)
+ fun_l26_n600(x)
+ else
+ fun_l26_n228(x)
+ end
+end
+
+def fun_l25_n301(x)
+ if (x < 1)
+ fun_l26_n493(x)
+ else
+ fun_l26_n852(x)
+ end
+end
+
+def fun_l25_n302(x)
+ if (x < 1)
+ fun_l26_n552(x)
+ else
+ fun_l26_n305(x)
+ end
+end
+
+def fun_l25_n303(x)
+ if (x < 1)
+ fun_l26_n280(x)
+ else
+ fun_l26_n373(x)
+ end
+end
+
+def fun_l25_n304(x)
+ if (x < 1)
+ fun_l26_n379(x)
+ else
+ fun_l26_n877(x)
+ end
+end
+
+def fun_l25_n305(x)
+ if (x < 1)
+ fun_l26_n562(x)
+ else
+ fun_l26_n165(x)
+ end
+end
+
+def fun_l25_n306(x)
+ if (x < 1)
+ fun_l26_n890(x)
+ else
+ fun_l26_n24(x)
+ end
+end
+
+def fun_l25_n307(x)
+ if (x < 1)
+ fun_l26_n881(x)
+ else
+ fun_l26_n936(x)
+ end
+end
+
+def fun_l25_n308(x)
+ if (x < 1)
+ fun_l26_n31(x)
+ else
+ fun_l26_n851(x)
+ end
+end
+
+def fun_l25_n309(x)
+ if (x < 1)
+ fun_l26_n894(x)
+ else
+ fun_l26_n496(x)
+ end
+end
+
+def fun_l25_n310(x)
+ if (x < 1)
+ fun_l26_n477(x)
+ else
+ fun_l26_n436(x)
+ end
+end
+
+def fun_l25_n311(x)
+ if (x < 1)
+ fun_l26_n943(x)
+ else
+ fun_l26_n565(x)
+ end
+end
+
+def fun_l25_n312(x)
+ if (x < 1)
+ fun_l26_n795(x)
+ else
+ fun_l26_n416(x)
+ end
+end
+
+def fun_l25_n313(x)
+ if (x < 1)
+ fun_l26_n264(x)
+ else
+ fun_l26_n528(x)
+ end
+end
+
+def fun_l25_n314(x)
+ if (x < 1)
+ fun_l26_n269(x)
+ else
+ fun_l26_n666(x)
+ end
+end
+
+def fun_l25_n315(x)
+ if (x < 1)
+ fun_l26_n166(x)
+ else
+ fun_l26_n633(x)
+ end
+end
+
+def fun_l25_n316(x)
+ if (x < 1)
+ fun_l26_n463(x)
+ else
+ fun_l26_n82(x)
+ end
+end
+
+def fun_l25_n317(x)
+ if (x < 1)
+ fun_l26_n379(x)
+ else
+ fun_l26_n429(x)
+ end
+end
+
+def fun_l25_n318(x)
+ if (x < 1)
+ fun_l26_n538(x)
+ else
+ fun_l26_n714(x)
+ end
+end
+
+def fun_l25_n319(x)
+ if (x < 1)
+ fun_l26_n913(x)
+ else
+ fun_l26_n584(x)
+ end
+end
+
+def fun_l25_n320(x)
+ if (x < 1)
+ fun_l26_n833(x)
+ else
+ fun_l26_n887(x)
+ end
+end
+
+def fun_l25_n321(x)
+ if (x < 1)
+ fun_l26_n332(x)
+ else
+ fun_l26_n720(x)
+ end
+end
+
+def fun_l25_n322(x)
+ if (x < 1)
+ fun_l26_n409(x)
+ else
+ fun_l26_n924(x)
+ end
+end
+
+def fun_l25_n323(x)
+ if (x < 1)
+ fun_l26_n201(x)
+ else
+ fun_l26_n15(x)
+ end
+end
+
+def fun_l25_n324(x)
+ if (x < 1)
+ fun_l26_n454(x)
+ else
+ fun_l26_n348(x)
+ end
+end
+
+def fun_l25_n325(x)
+ if (x < 1)
+ fun_l26_n798(x)
+ else
+ fun_l26_n310(x)
+ end
+end
+
+def fun_l25_n326(x)
+ if (x < 1)
+ fun_l26_n70(x)
+ else
+ fun_l26_n973(x)
+ end
+end
+
+def fun_l25_n327(x)
+ if (x < 1)
+ fun_l26_n683(x)
+ else
+ fun_l26_n857(x)
+ end
+end
+
+def fun_l25_n328(x)
+ if (x < 1)
+ fun_l26_n885(x)
+ else
+ fun_l26_n855(x)
+ end
+end
+
+def fun_l25_n329(x)
+ if (x < 1)
+ fun_l26_n725(x)
+ else
+ fun_l26_n625(x)
+ end
+end
+
+def fun_l25_n330(x)
+ if (x < 1)
+ fun_l26_n960(x)
+ else
+ fun_l26_n710(x)
+ end
+end
+
+def fun_l25_n331(x)
+ if (x < 1)
+ fun_l26_n899(x)
+ else
+ fun_l26_n671(x)
+ end
+end
+
+def fun_l25_n332(x)
+ if (x < 1)
+ fun_l26_n743(x)
+ else
+ fun_l26_n541(x)
+ end
+end
+
+def fun_l25_n333(x)
+ if (x < 1)
+ fun_l26_n353(x)
+ else
+ fun_l26_n336(x)
+ end
+end
+
+def fun_l25_n334(x)
+ if (x < 1)
+ fun_l26_n53(x)
+ else
+ fun_l26_n422(x)
+ end
+end
+
+def fun_l25_n335(x)
+ if (x < 1)
+ fun_l26_n291(x)
+ else
+ fun_l26_n586(x)
+ end
+end
+
+def fun_l25_n336(x)
+ if (x < 1)
+ fun_l26_n395(x)
+ else
+ fun_l26_n716(x)
+ end
+end
+
+def fun_l25_n337(x)
+ if (x < 1)
+ fun_l26_n655(x)
+ else
+ fun_l26_n590(x)
+ end
+end
+
+def fun_l25_n338(x)
+ if (x < 1)
+ fun_l26_n443(x)
+ else
+ fun_l26_n680(x)
+ end
+end
+
+def fun_l25_n339(x)
+ if (x < 1)
+ fun_l26_n930(x)
+ else
+ fun_l26_n828(x)
+ end
+end
+
+def fun_l25_n340(x)
+ if (x < 1)
+ fun_l26_n488(x)
+ else
+ fun_l26_n514(x)
+ end
+end
+
+def fun_l25_n341(x)
+ if (x < 1)
+ fun_l26_n504(x)
+ else
+ fun_l26_n592(x)
+ end
+end
+
+def fun_l25_n342(x)
+ if (x < 1)
+ fun_l26_n695(x)
+ else
+ fun_l26_n945(x)
+ end
+end
+
+def fun_l25_n343(x)
+ if (x < 1)
+ fun_l26_n483(x)
+ else
+ fun_l26_n511(x)
+ end
+end
+
+def fun_l25_n344(x)
+ if (x < 1)
+ fun_l26_n958(x)
+ else
+ fun_l26_n316(x)
+ end
+end
+
+def fun_l25_n345(x)
+ if (x < 1)
+ fun_l26_n481(x)
+ else
+ fun_l26_n473(x)
+ end
+end
+
+def fun_l25_n346(x)
+ if (x < 1)
+ fun_l26_n340(x)
+ else
+ fun_l26_n672(x)
+ end
+end
+
+def fun_l25_n347(x)
+ if (x < 1)
+ fun_l26_n222(x)
+ else
+ fun_l26_n232(x)
+ end
+end
+
+def fun_l25_n348(x)
+ if (x < 1)
+ fun_l26_n162(x)
+ else
+ fun_l26_n846(x)
+ end
+end
+
+def fun_l25_n349(x)
+ if (x < 1)
+ fun_l26_n56(x)
+ else
+ fun_l26_n93(x)
+ end
+end
+
+def fun_l25_n350(x)
+ if (x < 1)
+ fun_l26_n191(x)
+ else
+ fun_l26_n245(x)
+ end
+end
+
+def fun_l25_n351(x)
+ if (x < 1)
+ fun_l26_n294(x)
+ else
+ fun_l26_n494(x)
+ end
+end
+
+def fun_l25_n352(x)
+ if (x < 1)
+ fun_l26_n591(x)
+ else
+ fun_l26_n524(x)
+ end
+end
+
+def fun_l25_n353(x)
+ if (x < 1)
+ fun_l26_n904(x)
+ else
+ fun_l26_n793(x)
+ end
+end
+
+def fun_l25_n354(x)
+ if (x < 1)
+ fun_l26_n1(x)
+ else
+ fun_l26_n432(x)
+ end
+end
+
+def fun_l25_n355(x)
+ if (x < 1)
+ fun_l26_n757(x)
+ else
+ fun_l26_n733(x)
+ end
+end
+
+def fun_l25_n356(x)
+ if (x < 1)
+ fun_l26_n987(x)
+ else
+ fun_l26_n425(x)
+ end
+end
+
+def fun_l25_n357(x)
+ if (x < 1)
+ fun_l26_n288(x)
+ else
+ fun_l26_n587(x)
+ end
+end
+
+def fun_l25_n358(x)
+ if (x < 1)
+ fun_l26_n843(x)
+ else
+ fun_l26_n731(x)
+ end
+end
+
+def fun_l25_n359(x)
+ if (x < 1)
+ fun_l26_n433(x)
+ else
+ fun_l26_n208(x)
+ end
+end
+
+def fun_l25_n360(x)
+ if (x < 1)
+ fun_l26_n473(x)
+ else
+ fun_l26_n992(x)
+ end
+end
+
+def fun_l25_n361(x)
+ if (x < 1)
+ fun_l26_n210(x)
+ else
+ fun_l26_n704(x)
+ end
+end
+
+def fun_l25_n362(x)
+ if (x < 1)
+ fun_l26_n625(x)
+ else
+ fun_l26_n365(x)
+ end
+end
+
+def fun_l25_n363(x)
+ if (x < 1)
+ fun_l26_n55(x)
+ else
+ fun_l26_n555(x)
+ end
+end
+
+def fun_l25_n364(x)
+ if (x < 1)
+ fun_l26_n763(x)
+ else
+ fun_l26_n417(x)
+ end
+end
+
+def fun_l25_n365(x)
+ if (x < 1)
+ fun_l26_n557(x)
+ else
+ fun_l26_n24(x)
+ end
+end
+
+def fun_l25_n366(x)
+ if (x < 1)
+ fun_l26_n791(x)
+ else
+ fun_l26_n753(x)
+ end
+end
+
+def fun_l25_n367(x)
+ if (x < 1)
+ fun_l26_n490(x)
+ else
+ fun_l26_n765(x)
+ end
+end
+
+def fun_l25_n368(x)
+ if (x < 1)
+ fun_l26_n875(x)
+ else
+ fun_l26_n628(x)
+ end
+end
+
+def fun_l25_n369(x)
+ if (x < 1)
+ fun_l26_n544(x)
+ else
+ fun_l26_n234(x)
+ end
+end
+
+def fun_l25_n370(x)
+ if (x < 1)
+ fun_l26_n288(x)
+ else
+ fun_l26_n524(x)
+ end
+end
+
+def fun_l25_n371(x)
+ if (x < 1)
+ fun_l26_n548(x)
+ else
+ fun_l26_n782(x)
+ end
+end
+
+def fun_l25_n372(x)
+ if (x < 1)
+ fun_l26_n112(x)
+ else
+ fun_l26_n861(x)
+ end
+end
+
+def fun_l25_n373(x)
+ if (x < 1)
+ fun_l26_n565(x)
+ else
+ fun_l26_n442(x)
+ end
+end
+
+def fun_l25_n374(x)
+ if (x < 1)
+ fun_l26_n37(x)
+ else
+ fun_l26_n810(x)
+ end
+end
+
+def fun_l25_n375(x)
+ if (x < 1)
+ fun_l26_n384(x)
+ else
+ fun_l26_n103(x)
+ end
+end
+
+def fun_l25_n376(x)
+ if (x < 1)
+ fun_l26_n371(x)
+ else
+ fun_l26_n219(x)
+ end
+end
+
+def fun_l25_n377(x)
+ if (x < 1)
+ fun_l26_n964(x)
+ else
+ fun_l26_n542(x)
+ end
+end
+
+def fun_l25_n378(x)
+ if (x < 1)
+ fun_l26_n617(x)
+ else
+ fun_l26_n616(x)
+ end
+end
+
+def fun_l25_n379(x)
+ if (x < 1)
+ fun_l26_n94(x)
+ else
+ fun_l26_n870(x)
+ end
+end
+
+def fun_l25_n380(x)
+ if (x < 1)
+ fun_l26_n538(x)
+ else
+ fun_l26_n483(x)
+ end
+end
+
+def fun_l25_n381(x)
+ if (x < 1)
+ fun_l26_n395(x)
+ else
+ fun_l26_n873(x)
+ end
+end
+
+def fun_l25_n382(x)
+ if (x < 1)
+ fun_l26_n406(x)
+ else
+ fun_l26_n843(x)
+ end
+end
+
+def fun_l25_n383(x)
+ if (x < 1)
+ fun_l26_n422(x)
+ else
+ fun_l26_n367(x)
+ end
+end
+
+def fun_l25_n384(x)
+ if (x < 1)
+ fun_l26_n472(x)
+ else
+ fun_l26_n676(x)
+ end
+end
+
+def fun_l25_n385(x)
+ if (x < 1)
+ fun_l26_n782(x)
+ else
+ fun_l26_n995(x)
+ end
+end
+
+def fun_l25_n386(x)
+ if (x < 1)
+ fun_l26_n655(x)
+ else
+ fun_l26_n758(x)
+ end
+end
+
+def fun_l25_n387(x)
+ if (x < 1)
+ fun_l26_n665(x)
+ else
+ fun_l26_n775(x)
+ end
+end
+
+def fun_l25_n388(x)
+ if (x < 1)
+ fun_l26_n168(x)
+ else
+ fun_l26_n604(x)
+ end
+end
+
+def fun_l25_n389(x)
+ if (x < 1)
+ fun_l26_n31(x)
+ else
+ fun_l26_n681(x)
+ end
+end
+
+def fun_l25_n390(x)
+ if (x < 1)
+ fun_l26_n758(x)
+ else
+ fun_l26_n596(x)
+ end
+end
+
+def fun_l25_n391(x)
+ if (x < 1)
+ fun_l26_n413(x)
+ else
+ fun_l26_n528(x)
+ end
+end
+
+def fun_l25_n392(x)
+ if (x < 1)
+ fun_l26_n136(x)
+ else
+ fun_l26_n408(x)
+ end
+end
+
+def fun_l25_n393(x)
+ if (x < 1)
+ fun_l26_n493(x)
+ else
+ fun_l26_n182(x)
+ end
+end
+
+def fun_l25_n394(x)
+ if (x < 1)
+ fun_l26_n156(x)
+ else
+ fun_l26_n775(x)
+ end
+end
+
+def fun_l25_n395(x)
+ if (x < 1)
+ fun_l26_n839(x)
+ else
+ fun_l26_n823(x)
+ end
+end
+
+def fun_l25_n396(x)
+ if (x < 1)
+ fun_l26_n248(x)
+ else
+ fun_l26_n679(x)
+ end
+end
+
+def fun_l25_n397(x)
+ if (x < 1)
+ fun_l26_n594(x)
+ else
+ fun_l26_n117(x)
+ end
+end
+
+def fun_l25_n398(x)
+ if (x < 1)
+ fun_l26_n82(x)
+ else
+ fun_l26_n595(x)
+ end
+end
+
+def fun_l25_n399(x)
+ if (x < 1)
+ fun_l26_n978(x)
+ else
+ fun_l26_n391(x)
+ end
+end
+
+def fun_l25_n400(x)
+ if (x < 1)
+ fun_l26_n731(x)
+ else
+ fun_l26_n252(x)
+ end
+end
+
+def fun_l25_n401(x)
+ if (x < 1)
+ fun_l26_n297(x)
+ else
+ fun_l26_n918(x)
+ end
+end
+
+def fun_l25_n402(x)
+ if (x < 1)
+ fun_l26_n745(x)
+ else
+ fun_l26_n972(x)
+ end
+end
+
+def fun_l25_n403(x)
+ if (x < 1)
+ fun_l26_n685(x)
+ else
+ fun_l26_n555(x)
+ end
+end
+
+def fun_l25_n404(x)
+ if (x < 1)
+ fun_l26_n667(x)
+ else
+ fun_l26_n384(x)
+ end
+end
+
+def fun_l25_n405(x)
+ if (x < 1)
+ fun_l26_n330(x)
+ else
+ fun_l26_n440(x)
+ end
+end
+
+def fun_l25_n406(x)
+ if (x < 1)
+ fun_l26_n911(x)
+ else
+ fun_l26_n580(x)
+ end
+end
+
+def fun_l25_n407(x)
+ if (x < 1)
+ fun_l26_n789(x)
+ else
+ fun_l26_n297(x)
+ end
+end
+
+def fun_l25_n408(x)
+ if (x < 1)
+ fun_l26_n879(x)
+ else
+ fun_l26_n201(x)
+ end
+end
+
+def fun_l25_n409(x)
+ if (x < 1)
+ fun_l26_n36(x)
+ else
+ fun_l26_n885(x)
+ end
+end
+
+def fun_l25_n410(x)
+ if (x < 1)
+ fun_l26_n224(x)
+ else
+ fun_l26_n571(x)
+ end
+end
+
+def fun_l25_n411(x)
+ if (x < 1)
+ fun_l26_n395(x)
+ else
+ fun_l26_n640(x)
+ end
+end
+
+def fun_l25_n412(x)
+ if (x < 1)
+ fun_l26_n754(x)
+ else
+ fun_l26_n754(x)
+ end
+end
+
+def fun_l25_n413(x)
+ if (x < 1)
+ fun_l26_n885(x)
+ else
+ fun_l26_n857(x)
+ end
+end
+
+def fun_l25_n414(x)
+ if (x < 1)
+ fun_l26_n464(x)
+ else
+ fun_l26_n44(x)
+ end
+end
+
+def fun_l25_n415(x)
+ if (x < 1)
+ fun_l26_n13(x)
+ else
+ fun_l26_n546(x)
+ end
+end
+
+def fun_l25_n416(x)
+ if (x < 1)
+ fun_l26_n318(x)
+ else
+ fun_l26_n313(x)
+ end
+end
+
+def fun_l25_n417(x)
+ if (x < 1)
+ fun_l26_n98(x)
+ else
+ fun_l26_n139(x)
+ end
+end
+
+def fun_l25_n418(x)
+ if (x < 1)
+ fun_l26_n654(x)
+ else
+ fun_l26_n602(x)
+ end
+end
+
+def fun_l25_n419(x)
+ if (x < 1)
+ fun_l26_n808(x)
+ else
+ fun_l26_n987(x)
+ end
+end
+
+def fun_l25_n420(x)
+ if (x < 1)
+ fun_l26_n878(x)
+ else
+ fun_l26_n36(x)
+ end
+end
+
+def fun_l25_n421(x)
+ if (x < 1)
+ fun_l26_n427(x)
+ else
+ fun_l26_n620(x)
+ end
+end
+
+def fun_l25_n422(x)
+ if (x < 1)
+ fun_l26_n118(x)
+ else
+ fun_l26_n145(x)
+ end
+end
+
+def fun_l25_n423(x)
+ if (x < 1)
+ fun_l26_n131(x)
+ else
+ fun_l26_n520(x)
+ end
+end
+
+def fun_l25_n424(x)
+ if (x < 1)
+ fun_l26_n295(x)
+ else
+ fun_l26_n197(x)
+ end
+end
+
+def fun_l25_n425(x)
+ if (x < 1)
+ fun_l26_n632(x)
+ else
+ fun_l26_n951(x)
+ end
+end
+
+def fun_l25_n426(x)
+ if (x < 1)
+ fun_l26_n92(x)
+ else
+ fun_l26_n96(x)
+ end
+end
+
+def fun_l25_n427(x)
+ if (x < 1)
+ fun_l26_n677(x)
+ else
+ fun_l26_n5(x)
+ end
+end
+
+def fun_l25_n428(x)
+ if (x < 1)
+ fun_l26_n425(x)
+ else
+ fun_l26_n864(x)
+ end
+end
+
+def fun_l25_n429(x)
+ if (x < 1)
+ fun_l26_n187(x)
+ else
+ fun_l26_n62(x)
+ end
+end
+
+def fun_l25_n430(x)
+ if (x < 1)
+ fun_l26_n964(x)
+ else
+ fun_l26_n704(x)
+ end
+end
+
+def fun_l25_n431(x)
+ if (x < 1)
+ fun_l26_n109(x)
+ else
+ fun_l26_n181(x)
+ end
+end
+
+def fun_l25_n432(x)
+ if (x < 1)
+ fun_l26_n620(x)
+ else
+ fun_l26_n484(x)
+ end
+end
+
+def fun_l25_n433(x)
+ if (x < 1)
+ fun_l26_n283(x)
+ else
+ fun_l26_n622(x)
+ end
+end
+
+def fun_l25_n434(x)
+ if (x < 1)
+ fun_l26_n377(x)
+ else
+ fun_l26_n357(x)
+ end
+end
+
+def fun_l25_n435(x)
+ if (x < 1)
+ fun_l26_n375(x)
+ else
+ fun_l26_n346(x)
+ end
+end
+
+def fun_l25_n436(x)
+ if (x < 1)
+ fun_l26_n50(x)
+ else
+ fun_l26_n283(x)
+ end
+end
+
+def fun_l25_n437(x)
+ if (x < 1)
+ fun_l26_n348(x)
+ else
+ fun_l26_n465(x)
+ end
+end
+
+def fun_l25_n438(x)
+ if (x < 1)
+ fun_l26_n206(x)
+ else
+ fun_l26_n968(x)
+ end
+end
+
+def fun_l25_n439(x)
+ if (x < 1)
+ fun_l26_n878(x)
+ else
+ fun_l26_n248(x)
+ end
+end
+
+def fun_l25_n440(x)
+ if (x < 1)
+ fun_l26_n469(x)
+ else
+ fun_l26_n842(x)
+ end
+end
+
+def fun_l25_n441(x)
+ if (x < 1)
+ fun_l26_n476(x)
+ else
+ fun_l26_n666(x)
+ end
+end
+
+def fun_l25_n442(x)
+ if (x < 1)
+ fun_l26_n491(x)
+ else
+ fun_l26_n365(x)
+ end
+end
+
+def fun_l25_n443(x)
+ if (x < 1)
+ fun_l26_n412(x)
+ else
+ fun_l26_n308(x)
+ end
+end
+
+def fun_l25_n444(x)
+ if (x < 1)
+ fun_l26_n750(x)
+ else
+ fun_l26_n82(x)
+ end
+end
+
+def fun_l25_n445(x)
+ if (x < 1)
+ fun_l26_n434(x)
+ else
+ fun_l26_n711(x)
+ end
+end
+
+def fun_l25_n446(x)
+ if (x < 1)
+ fun_l26_n698(x)
+ else
+ fun_l26_n407(x)
+ end
+end
+
+def fun_l25_n447(x)
+ if (x < 1)
+ fun_l26_n992(x)
+ else
+ fun_l26_n404(x)
+ end
+end
+
+def fun_l25_n448(x)
+ if (x < 1)
+ fun_l26_n723(x)
+ else
+ fun_l26_n317(x)
+ end
+end
+
+def fun_l25_n449(x)
+ if (x < 1)
+ fun_l26_n582(x)
+ else
+ fun_l26_n384(x)
+ end
+end
+
+def fun_l25_n450(x)
+ if (x < 1)
+ fun_l26_n956(x)
+ else
+ fun_l26_n111(x)
+ end
+end
+
+def fun_l25_n451(x)
+ if (x < 1)
+ fun_l26_n506(x)
+ else
+ fun_l26_n775(x)
+ end
+end
+
+def fun_l25_n452(x)
+ if (x < 1)
+ fun_l26_n857(x)
+ else
+ fun_l26_n884(x)
+ end
+end
+
+def fun_l25_n453(x)
+ if (x < 1)
+ fun_l26_n889(x)
+ else
+ fun_l26_n471(x)
+ end
+end
+
+def fun_l25_n454(x)
+ if (x < 1)
+ fun_l26_n850(x)
+ else
+ fun_l26_n204(x)
+ end
+end
+
+def fun_l25_n455(x)
+ if (x < 1)
+ fun_l26_n244(x)
+ else
+ fun_l26_n507(x)
+ end
+end
+
+def fun_l25_n456(x)
+ if (x < 1)
+ fun_l26_n875(x)
+ else
+ fun_l26_n694(x)
+ end
+end
+
+def fun_l25_n457(x)
+ if (x < 1)
+ fun_l26_n517(x)
+ else
+ fun_l26_n64(x)
+ end
+end
+
+def fun_l25_n458(x)
+ if (x < 1)
+ fun_l26_n870(x)
+ else
+ fun_l26_n495(x)
+ end
+end
+
+def fun_l25_n459(x)
+ if (x < 1)
+ fun_l26_n577(x)
+ else
+ fun_l26_n42(x)
+ end
+end
+
+def fun_l25_n460(x)
+ if (x < 1)
+ fun_l26_n919(x)
+ else
+ fun_l26_n508(x)
+ end
+end
+
+def fun_l25_n461(x)
+ if (x < 1)
+ fun_l26_n334(x)
+ else
+ fun_l26_n720(x)
+ end
+end
+
+def fun_l25_n462(x)
+ if (x < 1)
+ fun_l26_n682(x)
+ else
+ fun_l26_n422(x)
+ end
+end
+
+def fun_l25_n463(x)
+ if (x < 1)
+ fun_l26_n415(x)
+ else
+ fun_l26_n505(x)
+ end
+end
+
+def fun_l25_n464(x)
+ if (x < 1)
+ fun_l26_n783(x)
+ else
+ fun_l26_n269(x)
+ end
+end
+
+def fun_l25_n465(x)
+ if (x < 1)
+ fun_l26_n797(x)
+ else
+ fun_l26_n780(x)
+ end
+end
+
+def fun_l25_n466(x)
+ if (x < 1)
+ fun_l26_n806(x)
+ else
+ fun_l26_n773(x)
+ end
+end
+
+def fun_l25_n467(x)
+ if (x < 1)
+ fun_l26_n922(x)
+ else
+ fun_l26_n45(x)
+ end
+end
+
+def fun_l25_n468(x)
+ if (x < 1)
+ fun_l26_n919(x)
+ else
+ fun_l26_n780(x)
+ end
+end
+
+def fun_l25_n469(x)
+ if (x < 1)
+ fun_l26_n354(x)
+ else
+ fun_l26_n360(x)
+ end
+end
+
+def fun_l25_n470(x)
+ if (x < 1)
+ fun_l26_n492(x)
+ else
+ fun_l26_n230(x)
+ end
+end
+
+def fun_l25_n471(x)
+ if (x < 1)
+ fun_l26_n1(x)
+ else
+ fun_l26_n845(x)
+ end
+end
+
+def fun_l25_n472(x)
+ if (x < 1)
+ fun_l26_n854(x)
+ else
+ fun_l26_n408(x)
+ end
+end
+
+def fun_l25_n473(x)
+ if (x < 1)
+ fun_l26_n17(x)
+ else
+ fun_l26_n570(x)
+ end
+end
+
+def fun_l25_n474(x)
+ if (x < 1)
+ fun_l26_n485(x)
+ else
+ fun_l26_n953(x)
+ end
+end
+
+def fun_l25_n475(x)
+ if (x < 1)
+ fun_l26_n398(x)
+ else
+ fun_l26_n712(x)
+ end
+end
+
+def fun_l25_n476(x)
+ if (x < 1)
+ fun_l26_n499(x)
+ else
+ fun_l26_n218(x)
+ end
+end
+
+def fun_l25_n477(x)
+ if (x < 1)
+ fun_l26_n107(x)
+ else
+ fun_l26_n38(x)
+ end
+end
+
+def fun_l25_n478(x)
+ if (x < 1)
+ fun_l26_n234(x)
+ else
+ fun_l26_n718(x)
+ end
+end
+
+def fun_l25_n479(x)
+ if (x < 1)
+ fun_l26_n396(x)
+ else
+ fun_l26_n247(x)
+ end
+end
+
+def fun_l25_n480(x)
+ if (x < 1)
+ fun_l26_n457(x)
+ else
+ fun_l26_n259(x)
+ end
+end
+
+def fun_l25_n481(x)
+ if (x < 1)
+ fun_l26_n581(x)
+ else
+ fun_l26_n512(x)
+ end
+end
+
+def fun_l25_n482(x)
+ if (x < 1)
+ fun_l26_n262(x)
+ else
+ fun_l26_n790(x)
+ end
+end
+
+def fun_l25_n483(x)
+ if (x < 1)
+ fun_l26_n140(x)
+ else
+ fun_l26_n821(x)
+ end
+end
+
+def fun_l25_n484(x)
+ if (x < 1)
+ fun_l26_n133(x)
+ else
+ fun_l26_n863(x)
+ end
+end
+
+def fun_l25_n485(x)
+ if (x < 1)
+ fun_l26_n440(x)
+ else
+ fun_l26_n265(x)
+ end
+end
+
+def fun_l25_n486(x)
+ if (x < 1)
+ fun_l26_n913(x)
+ else
+ fun_l26_n994(x)
+ end
+end
+
+def fun_l25_n487(x)
+ if (x < 1)
+ fun_l26_n186(x)
+ else
+ fun_l26_n433(x)
+ end
+end
+
+def fun_l25_n488(x)
+ if (x < 1)
+ fun_l26_n357(x)
+ else
+ fun_l26_n16(x)
+ end
+end
+
+def fun_l25_n489(x)
+ if (x < 1)
+ fun_l26_n165(x)
+ else
+ fun_l26_n674(x)
+ end
+end
+
+def fun_l25_n490(x)
+ if (x < 1)
+ fun_l26_n772(x)
+ else
+ fun_l26_n749(x)
+ end
+end
+
+def fun_l25_n491(x)
+ if (x < 1)
+ fun_l26_n677(x)
+ else
+ fun_l26_n36(x)
+ end
+end
+
+def fun_l25_n492(x)
+ if (x < 1)
+ fun_l26_n962(x)
+ else
+ fun_l26_n750(x)
+ end
+end
+
+def fun_l25_n493(x)
+ if (x < 1)
+ fun_l26_n22(x)
+ else
+ fun_l26_n657(x)
+ end
+end
+
+def fun_l25_n494(x)
+ if (x < 1)
+ fun_l26_n302(x)
+ else
+ fun_l26_n394(x)
+ end
+end
+
+def fun_l25_n495(x)
+ if (x < 1)
+ fun_l26_n313(x)
+ else
+ fun_l26_n552(x)
+ end
+end
+
+def fun_l25_n496(x)
+ if (x < 1)
+ fun_l26_n946(x)
+ else
+ fun_l26_n447(x)
+ end
+end
+
+def fun_l25_n497(x)
+ if (x < 1)
+ fun_l26_n565(x)
+ else
+ fun_l26_n242(x)
+ end
+end
+
+def fun_l25_n498(x)
+ if (x < 1)
+ fun_l26_n932(x)
+ else
+ fun_l26_n413(x)
+ end
+end
+
+def fun_l25_n499(x)
+ if (x < 1)
+ fun_l26_n751(x)
+ else
+ fun_l26_n921(x)
+ end
+end
+
+def fun_l25_n500(x)
+ if (x < 1)
+ fun_l26_n1(x)
+ else
+ fun_l26_n722(x)
+ end
+end
+
+def fun_l25_n501(x)
+ if (x < 1)
+ fun_l26_n63(x)
+ else
+ fun_l26_n205(x)
+ end
+end
+
+def fun_l25_n502(x)
+ if (x < 1)
+ fun_l26_n67(x)
+ else
+ fun_l26_n638(x)
+ end
+end
+
+def fun_l25_n503(x)
+ if (x < 1)
+ fun_l26_n762(x)
+ else
+ fun_l26_n688(x)
+ end
+end
+
+def fun_l25_n504(x)
+ if (x < 1)
+ fun_l26_n839(x)
+ else
+ fun_l26_n775(x)
+ end
+end
+
+def fun_l25_n505(x)
+ if (x < 1)
+ fun_l26_n773(x)
+ else
+ fun_l26_n986(x)
+ end
+end
+
+def fun_l25_n506(x)
+ if (x < 1)
+ fun_l26_n934(x)
+ else
+ fun_l26_n117(x)
+ end
+end
+
+def fun_l25_n507(x)
+ if (x < 1)
+ fun_l26_n507(x)
+ else
+ fun_l26_n217(x)
+ end
+end
+
+def fun_l25_n508(x)
+ if (x < 1)
+ fun_l26_n833(x)
+ else
+ fun_l26_n779(x)
+ end
+end
+
+def fun_l25_n509(x)
+ if (x < 1)
+ fun_l26_n244(x)
+ else
+ fun_l26_n71(x)
+ end
+end
+
+def fun_l25_n510(x)
+ if (x < 1)
+ fun_l26_n466(x)
+ else
+ fun_l26_n440(x)
+ end
+end
+
+def fun_l25_n511(x)
+ if (x < 1)
+ fun_l26_n829(x)
+ else
+ fun_l26_n459(x)
+ end
+end
+
+def fun_l25_n512(x)
+ if (x < 1)
+ fun_l26_n923(x)
+ else
+ fun_l26_n672(x)
+ end
+end
+
+def fun_l25_n513(x)
+ if (x < 1)
+ fun_l26_n925(x)
+ else
+ fun_l26_n758(x)
+ end
+end
+
+def fun_l25_n514(x)
+ if (x < 1)
+ fun_l26_n782(x)
+ else
+ fun_l26_n157(x)
+ end
+end
+
+def fun_l25_n515(x)
+ if (x < 1)
+ fun_l26_n987(x)
+ else
+ fun_l26_n407(x)
+ end
+end
+
+def fun_l25_n516(x)
+ if (x < 1)
+ fun_l26_n224(x)
+ else
+ fun_l26_n531(x)
+ end
+end
+
+def fun_l25_n517(x)
+ if (x < 1)
+ fun_l26_n222(x)
+ else
+ fun_l26_n141(x)
+ end
+end
+
+def fun_l25_n518(x)
+ if (x < 1)
+ fun_l26_n723(x)
+ else
+ fun_l26_n787(x)
+ end
+end
+
+def fun_l25_n519(x)
+ if (x < 1)
+ fun_l26_n802(x)
+ else
+ fun_l26_n448(x)
+ end
+end
+
+def fun_l25_n520(x)
+ if (x < 1)
+ fun_l26_n152(x)
+ else
+ fun_l26_n666(x)
+ end
+end
+
+def fun_l25_n521(x)
+ if (x < 1)
+ fun_l26_n476(x)
+ else
+ fun_l26_n7(x)
+ end
+end
+
+def fun_l25_n522(x)
+ if (x < 1)
+ fun_l26_n523(x)
+ else
+ fun_l26_n326(x)
+ end
+end
+
+def fun_l25_n523(x)
+ if (x < 1)
+ fun_l26_n432(x)
+ else
+ fun_l26_n525(x)
+ end
+end
+
+def fun_l25_n524(x)
+ if (x < 1)
+ fun_l26_n403(x)
+ else
+ fun_l26_n983(x)
+ end
+end
+
+def fun_l25_n525(x)
+ if (x < 1)
+ fun_l26_n681(x)
+ else
+ fun_l26_n326(x)
+ end
+end
+
+def fun_l25_n526(x)
+ if (x < 1)
+ fun_l26_n352(x)
+ else
+ fun_l26_n402(x)
+ end
+end
+
+def fun_l25_n527(x)
+ if (x < 1)
+ fun_l26_n870(x)
+ else
+ fun_l26_n181(x)
+ end
+end
+
+def fun_l25_n528(x)
+ if (x < 1)
+ fun_l26_n382(x)
+ else
+ fun_l26_n880(x)
+ end
+end
+
+def fun_l25_n529(x)
+ if (x < 1)
+ fun_l26_n337(x)
+ else
+ fun_l26_n616(x)
+ end
+end
+
+def fun_l25_n530(x)
+ if (x < 1)
+ fun_l26_n959(x)
+ else
+ fun_l26_n239(x)
+ end
+end
+
+def fun_l25_n531(x)
+ if (x < 1)
+ fun_l26_n57(x)
+ else
+ fun_l26_n896(x)
+ end
+end
+
+def fun_l25_n532(x)
+ if (x < 1)
+ fun_l26_n456(x)
+ else
+ fun_l26_n365(x)
+ end
+end
+
+def fun_l25_n533(x)
+ if (x < 1)
+ fun_l26_n73(x)
+ else
+ fun_l26_n420(x)
+ end
+end
+
+def fun_l25_n534(x)
+ if (x < 1)
+ fun_l26_n295(x)
+ else
+ fun_l26_n663(x)
+ end
+end
+
+def fun_l25_n535(x)
+ if (x < 1)
+ fun_l26_n881(x)
+ else
+ fun_l26_n391(x)
+ end
+end
+
+def fun_l25_n536(x)
+ if (x < 1)
+ fun_l26_n775(x)
+ else
+ fun_l26_n19(x)
+ end
+end
+
+def fun_l25_n537(x)
+ if (x < 1)
+ fun_l26_n954(x)
+ else
+ fun_l26_n97(x)
+ end
+end
+
+def fun_l25_n538(x)
+ if (x < 1)
+ fun_l26_n764(x)
+ else
+ fun_l26_n353(x)
+ end
+end
+
+def fun_l25_n539(x)
+ if (x < 1)
+ fun_l26_n220(x)
+ else
+ fun_l26_n958(x)
+ end
+end
+
+def fun_l25_n540(x)
+ if (x < 1)
+ fun_l26_n915(x)
+ else
+ fun_l26_n792(x)
+ end
+end
+
+def fun_l25_n541(x)
+ if (x < 1)
+ fun_l26_n880(x)
+ else
+ fun_l26_n374(x)
+ end
+end
+
+def fun_l25_n542(x)
+ if (x < 1)
+ fun_l26_n655(x)
+ else
+ fun_l26_n578(x)
+ end
+end
+
+def fun_l25_n543(x)
+ if (x < 1)
+ fun_l26_n862(x)
+ else
+ fun_l26_n177(x)
+ end
+end
+
+def fun_l25_n544(x)
+ if (x < 1)
+ fun_l26_n286(x)
+ else
+ fun_l26_n670(x)
+ end
+end
+
+def fun_l25_n545(x)
+ if (x < 1)
+ fun_l26_n862(x)
+ else
+ fun_l26_n45(x)
+ end
+end
+
+def fun_l25_n546(x)
+ if (x < 1)
+ fun_l26_n743(x)
+ else
+ fun_l26_n575(x)
+ end
+end
+
+def fun_l25_n547(x)
+ if (x < 1)
+ fun_l26_n909(x)
+ else
+ fun_l26_n457(x)
+ end
+end
+
+def fun_l25_n548(x)
+ if (x < 1)
+ fun_l26_n784(x)
+ else
+ fun_l26_n482(x)
+ end
+end
+
+def fun_l25_n549(x)
+ if (x < 1)
+ fun_l26_n381(x)
+ else
+ fun_l26_n560(x)
+ end
+end
+
+def fun_l25_n550(x)
+ if (x < 1)
+ fun_l26_n62(x)
+ else
+ fun_l26_n640(x)
+ end
+end
+
+def fun_l25_n551(x)
+ if (x < 1)
+ fun_l26_n714(x)
+ else
+ fun_l26_n898(x)
+ end
+end
+
+def fun_l25_n552(x)
+ if (x < 1)
+ fun_l26_n515(x)
+ else
+ fun_l26_n221(x)
+ end
+end
+
+def fun_l25_n553(x)
+ if (x < 1)
+ fun_l26_n217(x)
+ else
+ fun_l26_n932(x)
+ end
+end
+
+def fun_l25_n554(x)
+ if (x < 1)
+ fun_l26_n583(x)
+ else
+ fun_l26_n722(x)
+ end
+end
+
+def fun_l25_n555(x)
+ if (x < 1)
+ fun_l26_n398(x)
+ else
+ fun_l26_n503(x)
+ end
+end
+
+def fun_l25_n556(x)
+ if (x < 1)
+ fun_l26_n891(x)
+ else
+ fun_l26_n72(x)
+ end
+end
+
+def fun_l25_n557(x)
+ if (x < 1)
+ fun_l26_n367(x)
+ else
+ fun_l26_n141(x)
+ end
+end
+
+def fun_l25_n558(x)
+ if (x < 1)
+ fun_l26_n477(x)
+ else
+ fun_l26_n40(x)
+ end
+end
+
+def fun_l25_n559(x)
+ if (x < 1)
+ fun_l26_n156(x)
+ else
+ fun_l26_n491(x)
+ end
+end
+
+def fun_l25_n560(x)
+ if (x < 1)
+ fun_l26_n859(x)
+ else
+ fun_l26_n423(x)
+ end
+end
+
+def fun_l25_n561(x)
+ if (x < 1)
+ fun_l26_n693(x)
+ else
+ fun_l26_n281(x)
+ end
+end
+
+def fun_l25_n562(x)
+ if (x < 1)
+ fun_l26_n460(x)
+ else
+ fun_l26_n151(x)
+ end
+end
+
+def fun_l25_n563(x)
+ if (x < 1)
+ fun_l26_n14(x)
+ else
+ fun_l26_n395(x)
+ end
+end
+
+def fun_l25_n564(x)
+ if (x < 1)
+ fun_l26_n423(x)
+ else
+ fun_l26_n198(x)
+ end
+end
+
+def fun_l25_n565(x)
+ if (x < 1)
+ fun_l26_n911(x)
+ else
+ fun_l26_n841(x)
+ end
+end
+
+def fun_l25_n566(x)
+ if (x < 1)
+ fun_l26_n273(x)
+ else
+ fun_l26_n361(x)
+ end
+end
+
+def fun_l25_n567(x)
+ if (x < 1)
+ fun_l26_n94(x)
+ else
+ fun_l26_n932(x)
+ end
+end
+
+def fun_l25_n568(x)
+ if (x < 1)
+ fun_l26_n734(x)
+ else
+ fun_l26_n191(x)
+ end
+end
+
+def fun_l25_n569(x)
+ if (x < 1)
+ fun_l26_n699(x)
+ else
+ fun_l26_n496(x)
+ end
+end
+
+def fun_l25_n570(x)
+ if (x < 1)
+ fun_l26_n90(x)
+ else
+ fun_l26_n574(x)
+ end
+end
+
+def fun_l25_n571(x)
+ if (x < 1)
+ fun_l26_n818(x)
+ else
+ fun_l26_n529(x)
+ end
+end
+
+def fun_l25_n572(x)
+ if (x < 1)
+ fun_l26_n459(x)
+ else
+ fun_l26_n770(x)
+ end
+end
+
+def fun_l25_n573(x)
+ if (x < 1)
+ fun_l26_n725(x)
+ else
+ fun_l26_n896(x)
+ end
+end
+
+def fun_l25_n574(x)
+ if (x < 1)
+ fun_l26_n773(x)
+ else
+ fun_l26_n8(x)
+ end
+end
+
+def fun_l25_n575(x)
+ if (x < 1)
+ fun_l26_n582(x)
+ else
+ fun_l26_n274(x)
+ end
+end
+
+def fun_l25_n576(x)
+ if (x < 1)
+ fun_l26_n529(x)
+ else
+ fun_l26_n434(x)
+ end
+end
+
+def fun_l25_n577(x)
+ if (x < 1)
+ fun_l26_n197(x)
+ else
+ fun_l26_n88(x)
+ end
+end
+
+def fun_l25_n578(x)
+ if (x < 1)
+ fun_l26_n938(x)
+ else
+ fun_l26_n184(x)
+ end
+end
+
+def fun_l25_n579(x)
+ if (x < 1)
+ fun_l26_n801(x)
+ else
+ fun_l26_n990(x)
+ end
+end
+
+def fun_l25_n580(x)
+ if (x < 1)
+ fun_l26_n732(x)
+ else
+ fun_l26_n955(x)
+ end
+end
+
+def fun_l25_n581(x)
+ if (x < 1)
+ fun_l26_n130(x)
+ else
+ fun_l26_n167(x)
+ end
+end
+
+def fun_l25_n582(x)
+ if (x < 1)
+ fun_l26_n942(x)
+ else
+ fun_l26_n352(x)
+ end
+end
+
+def fun_l25_n583(x)
+ if (x < 1)
+ fun_l26_n673(x)
+ else
+ fun_l26_n613(x)
+ end
+end
+
+def fun_l25_n584(x)
+ if (x < 1)
+ fun_l26_n386(x)
+ else
+ fun_l26_n840(x)
+ end
+end
+
+def fun_l25_n585(x)
+ if (x < 1)
+ fun_l26_n847(x)
+ else
+ fun_l26_n372(x)
+ end
+end
+
+def fun_l25_n586(x)
+ if (x < 1)
+ fun_l26_n0(x)
+ else
+ fun_l26_n717(x)
+ end
+end
+
+def fun_l25_n587(x)
+ if (x < 1)
+ fun_l26_n403(x)
+ else
+ fun_l26_n689(x)
+ end
+end
+
+def fun_l25_n588(x)
+ if (x < 1)
+ fun_l26_n325(x)
+ else
+ fun_l26_n75(x)
+ end
+end
+
+def fun_l25_n589(x)
+ if (x < 1)
+ fun_l26_n653(x)
+ else
+ fun_l26_n993(x)
+ end
+end
+
+def fun_l25_n590(x)
+ if (x < 1)
+ fun_l26_n413(x)
+ else
+ fun_l26_n428(x)
+ end
+end
+
+def fun_l25_n591(x)
+ if (x < 1)
+ fun_l26_n93(x)
+ else
+ fun_l26_n264(x)
+ end
+end
+
+def fun_l25_n592(x)
+ if (x < 1)
+ fun_l26_n117(x)
+ else
+ fun_l26_n466(x)
+ end
+end
+
+def fun_l25_n593(x)
+ if (x < 1)
+ fun_l26_n463(x)
+ else
+ fun_l26_n270(x)
+ end
+end
+
+def fun_l25_n594(x)
+ if (x < 1)
+ fun_l26_n348(x)
+ else
+ fun_l26_n844(x)
+ end
+end
+
+def fun_l25_n595(x)
+ if (x < 1)
+ fun_l26_n939(x)
+ else
+ fun_l26_n891(x)
+ end
+end
+
+def fun_l25_n596(x)
+ if (x < 1)
+ fun_l26_n949(x)
+ else
+ fun_l26_n743(x)
+ end
+end
+
+def fun_l25_n597(x)
+ if (x < 1)
+ fun_l26_n884(x)
+ else
+ fun_l26_n831(x)
+ end
+end
+
+def fun_l25_n598(x)
+ if (x < 1)
+ fun_l26_n910(x)
+ else
+ fun_l26_n79(x)
+ end
+end
+
+def fun_l25_n599(x)
+ if (x < 1)
+ fun_l26_n491(x)
+ else
+ fun_l26_n727(x)
+ end
+end
+
+def fun_l25_n600(x)
+ if (x < 1)
+ fun_l26_n295(x)
+ else
+ fun_l26_n929(x)
+ end
+end
+
+def fun_l25_n601(x)
+ if (x < 1)
+ fun_l26_n130(x)
+ else
+ fun_l26_n35(x)
+ end
+end
+
+def fun_l25_n602(x)
+ if (x < 1)
+ fun_l26_n673(x)
+ else
+ fun_l26_n103(x)
+ end
+end
+
+def fun_l25_n603(x)
+ if (x < 1)
+ fun_l26_n669(x)
+ else
+ fun_l26_n449(x)
+ end
+end
+
+def fun_l25_n604(x)
+ if (x < 1)
+ fun_l26_n201(x)
+ else
+ fun_l26_n616(x)
+ end
+end
+
+def fun_l25_n605(x)
+ if (x < 1)
+ fun_l26_n326(x)
+ else
+ fun_l26_n718(x)
+ end
+end
+
+def fun_l25_n606(x)
+ if (x < 1)
+ fun_l26_n857(x)
+ else
+ fun_l26_n188(x)
+ end
+end
+
+def fun_l25_n607(x)
+ if (x < 1)
+ fun_l26_n351(x)
+ else
+ fun_l26_n688(x)
+ end
+end
+
+def fun_l25_n608(x)
+ if (x < 1)
+ fun_l26_n652(x)
+ else
+ fun_l26_n280(x)
+ end
+end
+
+def fun_l25_n609(x)
+ if (x < 1)
+ fun_l26_n994(x)
+ else
+ fun_l26_n341(x)
+ end
+end
+
+def fun_l25_n610(x)
+ if (x < 1)
+ fun_l26_n876(x)
+ else
+ fun_l26_n643(x)
+ end
+end
+
+def fun_l25_n611(x)
+ if (x < 1)
+ fun_l26_n825(x)
+ else
+ fun_l26_n306(x)
+ end
+end
+
+def fun_l25_n612(x)
+ if (x < 1)
+ fun_l26_n139(x)
+ else
+ fun_l26_n452(x)
+ end
+end
+
+def fun_l25_n613(x)
+ if (x < 1)
+ fun_l26_n689(x)
+ else
+ fun_l26_n818(x)
+ end
+end
+
+def fun_l25_n614(x)
+ if (x < 1)
+ fun_l26_n171(x)
+ else
+ fun_l26_n366(x)
+ end
+end
+
+def fun_l25_n615(x)
+ if (x < 1)
+ fun_l26_n658(x)
+ else
+ fun_l26_n603(x)
+ end
+end
+
+def fun_l25_n616(x)
+ if (x < 1)
+ fun_l26_n150(x)
+ else
+ fun_l26_n603(x)
+ end
+end
+
+def fun_l25_n617(x)
+ if (x < 1)
+ fun_l26_n432(x)
+ else
+ fun_l26_n391(x)
+ end
+end
+
+def fun_l25_n618(x)
+ if (x < 1)
+ fun_l26_n79(x)
+ else
+ fun_l26_n416(x)
+ end
+end
+
+def fun_l25_n619(x)
+ if (x < 1)
+ fun_l26_n494(x)
+ else
+ fun_l26_n355(x)
+ end
+end
+
+def fun_l25_n620(x)
+ if (x < 1)
+ fun_l26_n868(x)
+ else
+ fun_l26_n461(x)
+ end
+end
+
+def fun_l25_n621(x)
+ if (x < 1)
+ fun_l26_n954(x)
+ else
+ fun_l26_n31(x)
+ end
+end
+
+def fun_l25_n622(x)
+ if (x < 1)
+ fun_l26_n620(x)
+ else
+ fun_l26_n777(x)
+ end
+end
+
+def fun_l25_n623(x)
+ if (x < 1)
+ fun_l26_n938(x)
+ else
+ fun_l26_n339(x)
+ end
+end
+
+def fun_l25_n624(x)
+ if (x < 1)
+ fun_l26_n385(x)
+ else
+ fun_l26_n462(x)
+ end
+end
+
+def fun_l25_n625(x)
+ if (x < 1)
+ fun_l26_n83(x)
+ else
+ fun_l26_n351(x)
+ end
+end
+
+def fun_l25_n626(x)
+ if (x < 1)
+ fun_l26_n317(x)
+ else
+ fun_l26_n16(x)
+ end
+end
+
+def fun_l25_n627(x)
+ if (x < 1)
+ fun_l26_n321(x)
+ else
+ fun_l26_n955(x)
+ end
+end
+
+def fun_l25_n628(x)
+ if (x < 1)
+ fun_l26_n649(x)
+ else
+ fun_l26_n195(x)
+ end
+end
+
+def fun_l25_n629(x)
+ if (x < 1)
+ fun_l26_n351(x)
+ else
+ fun_l26_n429(x)
+ end
+end
+
+def fun_l25_n630(x)
+ if (x < 1)
+ fun_l26_n338(x)
+ else
+ fun_l26_n334(x)
+ end
+end
+
+def fun_l25_n631(x)
+ if (x < 1)
+ fun_l26_n355(x)
+ else
+ fun_l26_n782(x)
+ end
+end
+
+def fun_l25_n632(x)
+ if (x < 1)
+ fun_l26_n619(x)
+ else
+ fun_l26_n189(x)
+ end
+end
+
+def fun_l25_n633(x)
+ if (x < 1)
+ fun_l26_n818(x)
+ else
+ fun_l26_n740(x)
+ end
+end
+
+def fun_l25_n634(x)
+ if (x < 1)
+ fun_l26_n725(x)
+ else
+ fun_l26_n114(x)
+ end
+end
+
+def fun_l25_n635(x)
+ if (x < 1)
+ fun_l26_n948(x)
+ else
+ fun_l26_n587(x)
+ end
+end
+
+def fun_l25_n636(x)
+ if (x < 1)
+ fun_l26_n268(x)
+ else
+ fun_l26_n871(x)
+ end
+end
+
+def fun_l25_n637(x)
+ if (x < 1)
+ fun_l26_n128(x)
+ else
+ fun_l26_n5(x)
+ end
+end
+
+def fun_l25_n638(x)
+ if (x < 1)
+ fun_l26_n981(x)
+ else
+ fun_l26_n209(x)
+ end
+end
+
+def fun_l25_n639(x)
+ if (x < 1)
+ fun_l26_n729(x)
+ else
+ fun_l26_n786(x)
+ end
+end
+
+def fun_l25_n640(x)
+ if (x < 1)
+ fun_l26_n86(x)
+ else
+ fun_l26_n320(x)
+ end
+end
+
+def fun_l25_n641(x)
+ if (x < 1)
+ fun_l26_n59(x)
+ else
+ fun_l26_n457(x)
+ end
+end
+
+def fun_l25_n642(x)
+ if (x < 1)
+ fun_l26_n517(x)
+ else
+ fun_l26_n249(x)
+ end
+end
+
+def fun_l25_n643(x)
+ if (x < 1)
+ fun_l26_n528(x)
+ else
+ fun_l26_n754(x)
+ end
+end
+
+def fun_l25_n644(x)
+ if (x < 1)
+ fun_l26_n254(x)
+ else
+ fun_l26_n886(x)
+ end
+end
+
+def fun_l25_n645(x)
+ if (x < 1)
+ fun_l26_n244(x)
+ else
+ fun_l26_n364(x)
+ end
+end
+
+def fun_l25_n646(x)
+ if (x < 1)
+ fun_l26_n550(x)
+ else
+ fun_l26_n877(x)
+ end
+end
+
+def fun_l25_n647(x)
+ if (x < 1)
+ fun_l26_n274(x)
+ else
+ fun_l26_n712(x)
+ end
+end
+
+def fun_l25_n648(x)
+ if (x < 1)
+ fun_l26_n299(x)
+ else
+ fun_l26_n957(x)
+ end
+end
+
+def fun_l25_n649(x)
+ if (x < 1)
+ fun_l26_n996(x)
+ else
+ fun_l26_n671(x)
+ end
+end
+
+def fun_l25_n650(x)
+ if (x < 1)
+ fun_l26_n91(x)
+ else
+ fun_l26_n867(x)
+ end
+end
+
+def fun_l25_n651(x)
+ if (x < 1)
+ fun_l26_n987(x)
+ else
+ fun_l26_n643(x)
+ end
+end
+
+def fun_l25_n652(x)
+ if (x < 1)
+ fun_l26_n429(x)
+ else
+ fun_l26_n802(x)
+ end
+end
+
+def fun_l25_n653(x)
+ if (x < 1)
+ fun_l26_n967(x)
+ else
+ fun_l26_n590(x)
+ end
+end
+
+def fun_l25_n654(x)
+ if (x < 1)
+ fun_l26_n404(x)
+ else
+ fun_l26_n283(x)
+ end
+end
+
+def fun_l25_n655(x)
+ if (x < 1)
+ fun_l26_n438(x)
+ else
+ fun_l26_n232(x)
+ end
+end
+
+def fun_l25_n656(x)
+ if (x < 1)
+ fun_l26_n295(x)
+ else
+ fun_l26_n559(x)
+ end
+end
+
+def fun_l25_n657(x)
+ if (x < 1)
+ fun_l26_n892(x)
+ else
+ fun_l26_n46(x)
+ end
+end
+
+def fun_l25_n658(x)
+ if (x < 1)
+ fun_l26_n30(x)
+ else
+ fun_l26_n640(x)
+ end
+end
+
+def fun_l25_n659(x)
+ if (x < 1)
+ fun_l26_n323(x)
+ else
+ fun_l26_n583(x)
+ end
+end
+
+def fun_l25_n660(x)
+ if (x < 1)
+ fun_l26_n682(x)
+ else
+ fun_l26_n668(x)
+ end
+end
+
+def fun_l25_n661(x)
+ if (x < 1)
+ fun_l26_n78(x)
+ else
+ fun_l26_n83(x)
+ end
+end
+
+def fun_l25_n662(x)
+ if (x < 1)
+ fun_l26_n457(x)
+ else
+ fun_l26_n289(x)
+ end
+end
+
+def fun_l25_n663(x)
+ if (x < 1)
+ fun_l26_n444(x)
+ else
+ fun_l26_n159(x)
+ end
+end
+
+def fun_l25_n664(x)
+ if (x < 1)
+ fun_l26_n10(x)
+ else
+ fun_l26_n925(x)
+ end
+end
+
+def fun_l25_n665(x)
+ if (x < 1)
+ fun_l26_n870(x)
+ else
+ fun_l26_n253(x)
+ end
+end
+
+def fun_l25_n666(x)
+ if (x < 1)
+ fun_l26_n55(x)
+ else
+ fun_l26_n705(x)
+ end
+end
+
+def fun_l25_n667(x)
+ if (x < 1)
+ fun_l26_n179(x)
+ else
+ fun_l26_n607(x)
+ end
+end
+
+def fun_l25_n668(x)
+ if (x < 1)
+ fun_l26_n359(x)
+ else
+ fun_l26_n56(x)
+ end
+end
+
+def fun_l25_n669(x)
+ if (x < 1)
+ fun_l26_n908(x)
+ else
+ fun_l26_n997(x)
+ end
+end
+
+def fun_l25_n670(x)
+ if (x < 1)
+ fun_l26_n469(x)
+ else
+ fun_l26_n438(x)
+ end
+end
+
+def fun_l25_n671(x)
+ if (x < 1)
+ fun_l26_n740(x)
+ else
+ fun_l26_n847(x)
+ end
+end
+
+def fun_l25_n672(x)
+ if (x < 1)
+ fun_l26_n123(x)
+ else
+ fun_l26_n636(x)
+ end
+end
+
+def fun_l25_n673(x)
+ if (x < 1)
+ fun_l26_n654(x)
+ else
+ fun_l26_n221(x)
+ end
+end
+
+def fun_l25_n674(x)
+ if (x < 1)
+ fun_l26_n14(x)
+ else
+ fun_l26_n792(x)
+ end
+end
+
+def fun_l25_n675(x)
+ if (x < 1)
+ fun_l26_n424(x)
+ else
+ fun_l26_n999(x)
+ end
+end
+
+def fun_l25_n676(x)
+ if (x < 1)
+ fun_l26_n491(x)
+ else
+ fun_l26_n698(x)
+ end
+end
+
+def fun_l25_n677(x)
+ if (x < 1)
+ fun_l26_n859(x)
+ else
+ fun_l26_n749(x)
+ end
+end
+
+def fun_l25_n678(x)
+ if (x < 1)
+ fun_l26_n357(x)
+ else
+ fun_l26_n861(x)
+ end
+end
+
+def fun_l25_n679(x)
+ if (x < 1)
+ fun_l26_n144(x)
+ else
+ fun_l26_n347(x)
+ end
+end
+
+def fun_l25_n680(x)
+ if (x < 1)
+ fun_l26_n42(x)
+ else
+ fun_l26_n168(x)
+ end
+end
+
+def fun_l25_n681(x)
+ if (x < 1)
+ fun_l26_n808(x)
+ else
+ fun_l26_n639(x)
+ end
+end
+
+def fun_l25_n682(x)
+ if (x < 1)
+ fun_l26_n943(x)
+ else
+ fun_l26_n152(x)
+ end
+end
+
+def fun_l25_n683(x)
+ if (x < 1)
+ fun_l26_n668(x)
+ else
+ fun_l26_n186(x)
+ end
+end
+
+def fun_l25_n684(x)
+ if (x < 1)
+ fun_l26_n607(x)
+ else
+ fun_l26_n141(x)
+ end
+end
+
+def fun_l25_n685(x)
+ if (x < 1)
+ fun_l26_n221(x)
+ else
+ fun_l26_n960(x)
+ end
+end
+
+def fun_l25_n686(x)
+ if (x < 1)
+ fun_l26_n85(x)
+ else
+ fun_l26_n285(x)
+ end
+end
+
+def fun_l25_n687(x)
+ if (x < 1)
+ fun_l26_n707(x)
+ else
+ fun_l26_n638(x)
+ end
+end
+
+def fun_l25_n688(x)
+ if (x < 1)
+ fun_l26_n288(x)
+ else
+ fun_l26_n318(x)
+ end
+end
+
+def fun_l25_n689(x)
+ if (x < 1)
+ fun_l26_n505(x)
+ else
+ fun_l26_n802(x)
+ end
+end
+
+def fun_l25_n690(x)
+ if (x < 1)
+ fun_l26_n757(x)
+ else
+ fun_l26_n988(x)
+ end
+end
+
+def fun_l25_n691(x)
+ if (x < 1)
+ fun_l26_n211(x)
+ else
+ fun_l26_n868(x)
+ end
+end
+
+def fun_l25_n692(x)
+ if (x < 1)
+ fun_l26_n945(x)
+ else
+ fun_l26_n689(x)
+ end
+end
+
+def fun_l25_n693(x)
+ if (x < 1)
+ fun_l26_n65(x)
+ else
+ fun_l26_n326(x)
+ end
+end
+
+def fun_l25_n694(x)
+ if (x < 1)
+ fun_l26_n905(x)
+ else
+ fun_l26_n912(x)
+ end
+end
+
+def fun_l25_n695(x)
+ if (x < 1)
+ fun_l26_n408(x)
+ else
+ fun_l26_n834(x)
+ end
+end
+
+def fun_l25_n696(x)
+ if (x < 1)
+ fun_l26_n862(x)
+ else
+ fun_l26_n827(x)
+ end
+end
+
+def fun_l25_n697(x)
+ if (x < 1)
+ fun_l26_n356(x)
+ else
+ fun_l26_n201(x)
+ end
+end
+
+def fun_l25_n698(x)
+ if (x < 1)
+ fun_l26_n819(x)
+ else
+ fun_l26_n672(x)
+ end
+end
+
+def fun_l25_n699(x)
+ if (x < 1)
+ fun_l26_n252(x)
+ else
+ fun_l26_n672(x)
+ end
+end
+
+def fun_l25_n700(x)
+ if (x < 1)
+ fun_l26_n620(x)
+ else
+ fun_l26_n693(x)
+ end
+end
+
+def fun_l25_n701(x)
+ if (x < 1)
+ fun_l26_n393(x)
+ else
+ fun_l26_n246(x)
+ end
+end
+
+def fun_l25_n702(x)
+ if (x < 1)
+ fun_l26_n601(x)
+ else
+ fun_l26_n230(x)
+ end
+end
+
+def fun_l25_n703(x)
+ if (x < 1)
+ fun_l26_n583(x)
+ else
+ fun_l26_n503(x)
+ end
+end
+
+def fun_l25_n704(x)
+ if (x < 1)
+ fun_l26_n156(x)
+ else
+ fun_l26_n951(x)
+ end
+end
+
+def fun_l25_n705(x)
+ if (x < 1)
+ fun_l26_n681(x)
+ else
+ fun_l26_n692(x)
+ end
+end
+
+def fun_l25_n706(x)
+ if (x < 1)
+ fun_l26_n176(x)
+ else
+ fun_l26_n158(x)
+ end
+end
+
+def fun_l25_n707(x)
+ if (x < 1)
+ fun_l26_n607(x)
+ else
+ fun_l26_n3(x)
+ end
+end
+
+def fun_l25_n708(x)
+ if (x < 1)
+ fun_l26_n999(x)
+ else
+ fun_l26_n614(x)
+ end
+end
+
+def fun_l25_n709(x)
+ if (x < 1)
+ fun_l26_n930(x)
+ else
+ fun_l26_n888(x)
+ end
+end
+
+def fun_l25_n710(x)
+ if (x < 1)
+ fun_l26_n347(x)
+ else
+ fun_l26_n106(x)
+ end
+end
+
+def fun_l25_n711(x)
+ if (x < 1)
+ fun_l26_n425(x)
+ else
+ fun_l26_n474(x)
+ end
+end
+
+def fun_l25_n712(x)
+ if (x < 1)
+ fun_l26_n265(x)
+ else
+ fun_l26_n519(x)
+ end
+end
+
+def fun_l25_n713(x)
+ if (x < 1)
+ fun_l26_n205(x)
+ else
+ fun_l26_n76(x)
+ end
+end
+
+def fun_l25_n714(x)
+ if (x < 1)
+ fun_l26_n628(x)
+ else
+ fun_l26_n784(x)
+ end
+end
+
+def fun_l25_n715(x)
+ if (x < 1)
+ fun_l26_n217(x)
+ else
+ fun_l26_n484(x)
+ end
+end
+
+def fun_l25_n716(x)
+ if (x < 1)
+ fun_l26_n883(x)
+ else
+ fun_l26_n5(x)
+ end
+end
+
+def fun_l25_n717(x)
+ if (x < 1)
+ fun_l26_n23(x)
+ else
+ fun_l26_n457(x)
+ end
+end
+
+def fun_l25_n718(x)
+ if (x < 1)
+ fun_l26_n370(x)
+ else
+ fun_l26_n789(x)
+ end
+end
+
+def fun_l25_n719(x)
+ if (x < 1)
+ fun_l26_n636(x)
+ else
+ fun_l26_n776(x)
+ end
+end
+
+def fun_l25_n720(x)
+ if (x < 1)
+ fun_l26_n558(x)
+ else
+ fun_l26_n491(x)
+ end
+end
+
+def fun_l25_n721(x)
+ if (x < 1)
+ fun_l26_n867(x)
+ else
+ fun_l26_n49(x)
+ end
+end
+
+def fun_l25_n722(x)
+ if (x < 1)
+ fun_l26_n178(x)
+ else
+ fun_l26_n835(x)
+ end
+end
+
+def fun_l25_n723(x)
+ if (x < 1)
+ fun_l26_n967(x)
+ else
+ fun_l26_n266(x)
+ end
+end
+
+def fun_l25_n724(x)
+ if (x < 1)
+ fun_l26_n191(x)
+ else
+ fun_l26_n58(x)
+ end
+end
+
+def fun_l25_n725(x)
+ if (x < 1)
+ fun_l26_n536(x)
+ else
+ fun_l26_n78(x)
+ end
+end
+
+def fun_l25_n726(x)
+ if (x < 1)
+ fun_l26_n128(x)
+ else
+ fun_l26_n764(x)
+ end
+end
+
+def fun_l25_n727(x)
+ if (x < 1)
+ fun_l26_n243(x)
+ else
+ fun_l26_n217(x)
+ end
+end
+
+def fun_l25_n728(x)
+ if (x < 1)
+ fun_l26_n608(x)
+ else
+ fun_l26_n613(x)
+ end
+end
+
+def fun_l25_n729(x)
+ if (x < 1)
+ fun_l26_n765(x)
+ else
+ fun_l26_n822(x)
+ end
+end
+
+def fun_l25_n730(x)
+ if (x < 1)
+ fun_l26_n445(x)
+ else
+ fun_l26_n160(x)
+ end
+end
+
+def fun_l25_n731(x)
+ if (x < 1)
+ fun_l26_n209(x)
+ else
+ fun_l26_n980(x)
+ end
+end
+
+def fun_l25_n732(x)
+ if (x < 1)
+ fun_l26_n888(x)
+ else
+ fun_l26_n726(x)
+ end
+end
+
+def fun_l25_n733(x)
+ if (x < 1)
+ fun_l26_n232(x)
+ else
+ fun_l26_n47(x)
+ end
+end
+
+def fun_l25_n734(x)
+ if (x < 1)
+ fun_l26_n278(x)
+ else
+ fun_l26_n878(x)
+ end
+end
+
+def fun_l25_n735(x)
+ if (x < 1)
+ fun_l26_n894(x)
+ else
+ fun_l26_n523(x)
+ end
+end
+
+def fun_l25_n736(x)
+ if (x < 1)
+ fun_l26_n334(x)
+ else
+ fun_l26_n270(x)
+ end
+end
+
+def fun_l25_n737(x)
+ if (x < 1)
+ fun_l26_n877(x)
+ else
+ fun_l26_n105(x)
+ end
+end
+
+def fun_l25_n738(x)
+ if (x < 1)
+ fun_l26_n761(x)
+ else
+ fun_l26_n187(x)
+ end
+end
+
+def fun_l25_n739(x)
+ if (x < 1)
+ fun_l26_n668(x)
+ else
+ fun_l26_n592(x)
+ end
+end
+
+def fun_l25_n740(x)
+ if (x < 1)
+ fun_l26_n497(x)
+ else
+ fun_l26_n98(x)
+ end
+end
+
+def fun_l25_n741(x)
+ if (x < 1)
+ fun_l26_n415(x)
+ else
+ fun_l26_n85(x)
+ end
+end
+
+def fun_l25_n742(x)
+ if (x < 1)
+ fun_l26_n883(x)
+ else
+ fun_l26_n505(x)
+ end
+end
+
+def fun_l25_n743(x)
+ if (x < 1)
+ fun_l26_n12(x)
+ else
+ fun_l26_n91(x)
+ end
+end
+
+def fun_l25_n744(x)
+ if (x < 1)
+ fun_l26_n487(x)
+ else
+ fun_l26_n336(x)
+ end
+end
+
+def fun_l25_n745(x)
+ if (x < 1)
+ fun_l26_n489(x)
+ else
+ fun_l26_n186(x)
+ end
+end
+
+def fun_l25_n746(x)
+ if (x < 1)
+ fun_l26_n783(x)
+ else
+ fun_l26_n233(x)
+ end
+end
+
+def fun_l25_n747(x)
+ if (x < 1)
+ fun_l26_n171(x)
+ else
+ fun_l26_n574(x)
+ end
+end
+
+def fun_l25_n748(x)
+ if (x < 1)
+ fun_l26_n171(x)
+ else
+ fun_l26_n61(x)
+ end
+end
+
+def fun_l25_n749(x)
+ if (x < 1)
+ fun_l26_n444(x)
+ else
+ fun_l26_n89(x)
+ end
+end
+
+def fun_l25_n750(x)
+ if (x < 1)
+ fun_l26_n609(x)
+ else
+ fun_l26_n998(x)
+ end
+end
+
+def fun_l25_n751(x)
+ if (x < 1)
+ fun_l26_n914(x)
+ else
+ fun_l26_n893(x)
+ end
+end
+
+def fun_l25_n752(x)
+ if (x < 1)
+ fun_l26_n782(x)
+ else
+ fun_l26_n984(x)
+ end
+end
+
+def fun_l25_n753(x)
+ if (x < 1)
+ fun_l26_n351(x)
+ else
+ fun_l26_n370(x)
+ end
+end
+
+def fun_l25_n754(x)
+ if (x < 1)
+ fun_l26_n689(x)
+ else
+ fun_l26_n234(x)
+ end
+end
+
+def fun_l25_n755(x)
+ if (x < 1)
+ fun_l26_n131(x)
+ else
+ fun_l26_n960(x)
+ end
+end
+
+def fun_l25_n756(x)
+ if (x < 1)
+ fun_l26_n635(x)
+ else
+ fun_l26_n89(x)
+ end
+end
+
+def fun_l25_n757(x)
+ if (x < 1)
+ fun_l26_n309(x)
+ else
+ fun_l26_n74(x)
+ end
+end
+
+def fun_l25_n758(x)
+ if (x < 1)
+ fun_l26_n818(x)
+ else
+ fun_l26_n520(x)
+ end
+end
+
+def fun_l25_n759(x)
+ if (x < 1)
+ fun_l26_n873(x)
+ else
+ fun_l26_n761(x)
+ end
+end
+
+def fun_l25_n760(x)
+ if (x < 1)
+ fun_l26_n216(x)
+ else
+ fun_l26_n449(x)
+ end
+end
+
+def fun_l25_n761(x)
+ if (x < 1)
+ fun_l26_n596(x)
+ else
+ fun_l26_n617(x)
+ end
+end
+
+def fun_l25_n762(x)
+ if (x < 1)
+ fun_l26_n485(x)
+ else
+ fun_l26_n164(x)
+ end
+end
+
+def fun_l25_n763(x)
+ if (x < 1)
+ fun_l26_n434(x)
+ else
+ fun_l26_n422(x)
+ end
+end
+
+def fun_l25_n764(x)
+ if (x < 1)
+ fun_l26_n845(x)
+ else
+ fun_l26_n678(x)
+ end
+end
+
+def fun_l25_n765(x)
+ if (x < 1)
+ fun_l26_n376(x)
+ else
+ fun_l26_n128(x)
+ end
+end
+
+def fun_l25_n766(x)
+ if (x < 1)
+ fun_l26_n217(x)
+ else
+ fun_l26_n721(x)
+ end
+end
+
+def fun_l25_n767(x)
+ if (x < 1)
+ fun_l26_n929(x)
+ else
+ fun_l26_n425(x)
+ end
+end
+
+def fun_l25_n768(x)
+ if (x < 1)
+ fun_l26_n420(x)
+ else
+ fun_l26_n990(x)
+ end
+end
+
+def fun_l25_n769(x)
+ if (x < 1)
+ fun_l26_n310(x)
+ else
+ fun_l26_n901(x)
+ end
+end
+
+def fun_l25_n770(x)
+ if (x < 1)
+ fun_l26_n667(x)
+ else
+ fun_l26_n627(x)
+ end
+end
+
+def fun_l25_n771(x)
+ if (x < 1)
+ fun_l26_n265(x)
+ else
+ fun_l26_n852(x)
+ end
+end
+
+def fun_l25_n772(x)
+ if (x < 1)
+ fun_l26_n520(x)
+ else
+ fun_l26_n596(x)
+ end
+end
+
+def fun_l25_n773(x)
+ if (x < 1)
+ fun_l26_n280(x)
+ else
+ fun_l26_n0(x)
+ end
+end
+
+def fun_l25_n774(x)
+ if (x < 1)
+ fun_l26_n451(x)
+ else
+ fun_l26_n828(x)
+ end
+end
+
+def fun_l25_n775(x)
+ if (x < 1)
+ fun_l26_n814(x)
+ else
+ fun_l26_n797(x)
+ end
+end
+
+def fun_l25_n776(x)
+ if (x < 1)
+ fun_l26_n345(x)
+ else
+ fun_l26_n223(x)
+ end
+end
+
+def fun_l25_n777(x)
+ if (x < 1)
+ fun_l26_n392(x)
+ else
+ fun_l26_n847(x)
+ end
+end
+
+def fun_l25_n778(x)
+ if (x < 1)
+ fun_l26_n957(x)
+ else
+ fun_l26_n474(x)
+ end
+end
+
+def fun_l25_n779(x)
+ if (x < 1)
+ fun_l26_n950(x)
+ else
+ fun_l26_n804(x)
+ end
+end
+
+def fun_l25_n780(x)
+ if (x < 1)
+ fun_l26_n939(x)
+ else
+ fun_l26_n133(x)
+ end
+end
+
+def fun_l25_n781(x)
+ if (x < 1)
+ fun_l26_n176(x)
+ else
+ fun_l26_n237(x)
+ end
+end
+
+def fun_l25_n782(x)
+ if (x < 1)
+ fun_l26_n156(x)
+ else
+ fun_l26_n268(x)
+ end
+end
+
+def fun_l25_n783(x)
+ if (x < 1)
+ fun_l26_n750(x)
+ else
+ fun_l26_n88(x)
+ end
+end
+
+def fun_l25_n784(x)
+ if (x < 1)
+ fun_l26_n638(x)
+ else
+ fun_l26_n147(x)
+ end
+end
+
+def fun_l25_n785(x)
+ if (x < 1)
+ fun_l26_n570(x)
+ else
+ fun_l26_n698(x)
+ end
+end
+
+def fun_l25_n786(x)
+ if (x < 1)
+ fun_l26_n749(x)
+ else
+ fun_l26_n728(x)
+ end
+end
+
+def fun_l25_n787(x)
+ if (x < 1)
+ fun_l26_n183(x)
+ else
+ fun_l26_n649(x)
+ end
+end
+
+def fun_l25_n788(x)
+ if (x < 1)
+ fun_l26_n157(x)
+ else
+ fun_l26_n55(x)
+ end
+end
+
+def fun_l25_n789(x)
+ if (x < 1)
+ fun_l26_n559(x)
+ else
+ fun_l26_n228(x)
+ end
+end
+
+def fun_l25_n790(x)
+ if (x < 1)
+ fun_l26_n690(x)
+ else
+ fun_l26_n214(x)
+ end
+end
+
+def fun_l25_n791(x)
+ if (x < 1)
+ fun_l26_n621(x)
+ else
+ fun_l26_n184(x)
+ end
+end
+
+def fun_l25_n792(x)
+ if (x < 1)
+ fun_l26_n13(x)
+ else
+ fun_l26_n610(x)
+ end
+end
+
+def fun_l25_n793(x)
+ if (x < 1)
+ fun_l26_n709(x)
+ else
+ fun_l26_n40(x)
+ end
+end
+
+def fun_l25_n794(x)
+ if (x < 1)
+ fun_l26_n51(x)
+ else
+ fun_l26_n288(x)
+ end
+end
+
+def fun_l25_n795(x)
+ if (x < 1)
+ fun_l26_n526(x)
+ else
+ fun_l26_n237(x)
+ end
+end
+
+def fun_l25_n796(x)
+ if (x < 1)
+ fun_l26_n279(x)
+ else
+ fun_l26_n157(x)
+ end
+end
+
+def fun_l25_n797(x)
+ if (x < 1)
+ fun_l26_n299(x)
+ else
+ fun_l26_n999(x)
+ end
+end
+
+def fun_l25_n798(x)
+ if (x < 1)
+ fun_l26_n547(x)
+ else
+ fun_l26_n41(x)
+ end
+end
+
+def fun_l25_n799(x)
+ if (x < 1)
+ fun_l26_n522(x)
+ else
+ fun_l26_n544(x)
+ end
+end
+
+def fun_l25_n800(x)
+ if (x < 1)
+ fun_l26_n509(x)
+ else
+ fun_l26_n364(x)
+ end
+end
+
+def fun_l25_n801(x)
+ if (x < 1)
+ fun_l26_n412(x)
+ else
+ fun_l26_n719(x)
+ end
+end
+
+def fun_l25_n802(x)
+ if (x < 1)
+ fun_l26_n844(x)
+ else
+ fun_l26_n452(x)
+ end
+end
+
+def fun_l25_n803(x)
+ if (x < 1)
+ fun_l26_n681(x)
+ else
+ fun_l26_n217(x)
+ end
+end
+
+def fun_l25_n804(x)
+ if (x < 1)
+ fun_l26_n855(x)
+ else
+ fun_l26_n97(x)
+ end
+end
+
+def fun_l25_n805(x)
+ if (x < 1)
+ fun_l26_n32(x)
+ else
+ fun_l26_n512(x)
+ end
+end
+
+def fun_l25_n806(x)
+ if (x < 1)
+ fun_l26_n674(x)
+ else
+ fun_l26_n675(x)
+ end
+end
+
+def fun_l25_n807(x)
+ if (x < 1)
+ fun_l26_n684(x)
+ else
+ fun_l26_n848(x)
+ end
+end
+
+def fun_l25_n808(x)
+ if (x < 1)
+ fun_l26_n784(x)
+ else
+ fun_l26_n603(x)
+ end
+end
+
+def fun_l25_n809(x)
+ if (x < 1)
+ fun_l26_n58(x)
+ else
+ fun_l26_n20(x)
+ end
+end
+
+def fun_l25_n810(x)
+ if (x < 1)
+ fun_l26_n654(x)
+ else
+ fun_l26_n230(x)
+ end
+end
+
+def fun_l25_n811(x)
+ if (x < 1)
+ fun_l26_n627(x)
+ else
+ fun_l26_n812(x)
+ end
+end
+
+def fun_l25_n812(x)
+ if (x < 1)
+ fun_l26_n30(x)
+ else
+ fun_l26_n315(x)
+ end
+end
+
+def fun_l25_n813(x)
+ if (x < 1)
+ fun_l26_n690(x)
+ else
+ fun_l26_n755(x)
+ end
+end
+
+def fun_l25_n814(x)
+ if (x < 1)
+ fun_l26_n566(x)
+ else
+ fun_l26_n44(x)
+ end
+end
+
+def fun_l25_n815(x)
+ if (x < 1)
+ fun_l26_n884(x)
+ else
+ fun_l26_n954(x)
+ end
+end
+
+def fun_l25_n816(x)
+ if (x < 1)
+ fun_l26_n64(x)
+ else
+ fun_l26_n179(x)
+ end
+end
+
+def fun_l25_n817(x)
+ if (x < 1)
+ fun_l26_n341(x)
+ else
+ fun_l26_n440(x)
+ end
+end
+
+def fun_l25_n818(x)
+ if (x < 1)
+ fun_l26_n934(x)
+ else
+ fun_l26_n678(x)
+ end
+end
+
+def fun_l25_n819(x)
+ if (x < 1)
+ fun_l26_n225(x)
+ else
+ fun_l26_n807(x)
+ end
+end
+
+def fun_l25_n820(x)
+ if (x < 1)
+ fun_l26_n625(x)
+ else
+ fun_l26_n63(x)
+ end
+end
+
+def fun_l25_n821(x)
+ if (x < 1)
+ fun_l26_n744(x)
+ else
+ fun_l26_n68(x)
+ end
+end
+
+def fun_l25_n822(x)
+ if (x < 1)
+ fun_l26_n962(x)
+ else
+ fun_l26_n205(x)
+ end
+end
+
+def fun_l25_n823(x)
+ if (x < 1)
+ fun_l26_n715(x)
+ else
+ fun_l26_n130(x)
+ end
+end
+
+def fun_l25_n824(x)
+ if (x < 1)
+ fun_l26_n843(x)
+ else
+ fun_l26_n853(x)
+ end
+end
+
+def fun_l25_n825(x)
+ if (x < 1)
+ fun_l26_n34(x)
+ else
+ fun_l26_n665(x)
+ end
+end
+
+def fun_l25_n826(x)
+ if (x < 1)
+ fun_l26_n540(x)
+ else
+ fun_l26_n693(x)
+ end
+end
+
+def fun_l25_n827(x)
+ if (x < 1)
+ fun_l26_n482(x)
+ else
+ fun_l26_n527(x)
+ end
+end
+
+def fun_l25_n828(x)
+ if (x < 1)
+ fun_l26_n98(x)
+ else
+ fun_l26_n888(x)
+ end
+end
+
+def fun_l25_n829(x)
+ if (x < 1)
+ fun_l26_n681(x)
+ else
+ fun_l26_n176(x)
+ end
+end
+
+def fun_l25_n830(x)
+ if (x < 1)
+ fun_l26_n453(x)
+ else
+ fun_l26_n455(x)
+ end
+end
+
+def fun_l25_n831(x)
+ if (x < 1)
+ fun_l26_n587(x)
+ else
+ fun_l26_n501(x)
+ end
+end
+
+def fun_l25_n832(x)
+ if (x < 1)
+ fun_l26_n725(x)
+ else
+ fun_l26_n608(x)
+ end
+end
+
+def fun_l25_n833(x)
+ if (x < 1)
+ fun_l26_n589(x)
+ else
+ fun_l26_n945(x)
+ end
+end
+
+def fun_l25_n834(x)
+ if (x < 1)
+ fun_l26_n41(x)
+ else
+ fun_l26_n925(x)
+ end
+end
+
+def fun_l25_n835(x)
+ if (x < 1)
+ fun_l26_n858(x)
+ else
+ fun_l26_n840(x)
+ end
+end
+
+def fun_l25_n836(x)
+ if (x < 1)
+ fun_l26_n572(x)
+ else
+ fun_l26_n360(x)
+ end
+end
+
+def fun_l25_n837(x)
+ if (x < 1)
+ fun_l26_n446(x)
+ else
+ fun_l26_n912(x)
+ end
+end
+
+def fun_l25_n838(x)
+ if (x < 1)
+ fun_l26_n104(x)
+ else
+ fun_l26_n795(x)
+ end
+end
+
+def fun_l25_n839(x)
+ if (x < 1)
+ fun_l26_n607(x)
+ else
+ fun_l26_n803(x)
+ end
+end
+
+def fun_l25_n840(x)
+ if (x < 1)
+ fun_l26_n156(x)
+ else
+ fun_l26_n874(x)
+ end
+end
+
+def fun_l25_n841(x)
+ if (x < 1)
+ fun_l26_n314(x)
+ else
+ fun_l26_n28(x)
+ end
+end
+
+def fun_l25_n842(x)
+ if (x < 1)
+ fun_l26_n683(x)
+ else
+ fun_l26_n695(x)
+ end
+end
+
+def fun_l25_n843(x)
+ if (x < 1)
+ fun_l26_n881(x)
+ else
+ fun_l26_n272(x)
+ end
+end
+
+def fun_l25_n844(x)
+ if (x < 1)
+ fun_l26_n354(x)
+ else
+ fun_l26_n993(x)
+ end
+end
+
+def fun_l25_n845(x)
+ if (x < 1)
+ fun_l26_n686(x)
+ else
+ fun_l26_n594(x)
+ end
+end
+
+def fun_l25_n846(x)
+ if (x < 1)
+ fun_l26_n644(x)
+ else
+ fun_l26_n930(x)
+ end
+end
+
+def fun_l25_n847(x)
+ if (x < 1)
+ fun_l26_n417(x)
+ else
+ fun_l26_n705(x)
+ end
+end
+
+def fun_l25_n848(x)
+ if (x < 1)
+ fun_l26_n694(x)
+ else
+ fun_l26_n331(x)
+ end
+end
+
+def fun_l25_n849(x)
+ if (x < 1)
+ fun_l26_n546(x)
+ else
+ fun_l26_n848(x)
+ end
+end
+
+def fun_l25_n850(x)
+ if (x < 1)
+ fun_l26_n199(x)
+ else
+ fun_l26_n49(x)
+ end
+end
+
+def fun_l25_n851(x)
+ if (x < 1)
+ fun_l26_n439(x)
+ else
+ fun_l26_n406(x)
+ end
+end
+
+def fun_l25_n852(x)
+ if (x < 1)
+ fun_l26_n355(x)
+ else
+ fun_l26_n582(x)
+ end
+end
+
+def fun_l25_n853(x)
+ if (x < 1)
+ fun_l26_n839(x)
+ else
+ fun_l26_n485(x)
+ end
+end
+
+def fun_l25_n854(x)
+ if (x < 1)
+ fun_l26_n952(x)
+ else
+ fun_l26_n781(x)
+ end
+end
+
+def fun_l25_n855(x)
+ if (x < 1)
+ fun_l26_n616(x)
+ else
+ fun_l26_n811(x)
+ end
+end
+
+def fun_l25_n856(x)
+ if (x < 1)
+ fun_l26_n590(x)
+ else
+ fun_l26_n977(x)
+ end
+end
+
+def fun_l25_n857(x)
+ if (x < 1)
+ fun_l26_n167(x)
+ else
+ fun_l26_n329(x)
+ end
+end
+
+def fun_l25_n858(x)
+ if (x < 1)
+ fun_l26_n732(x)
+ else
+ fun_l26_n707(x)
+ end
+end
+
+def fun_l25_n859(x)
+ if (x < 1)
+ fun_l26_n956(x)
+ else
+ fun_l26_n955(x)
+ end
+end
+
+def fun_l25_n860(x)
+ if (x < 1)
+ fun_l26_n443(x)
+ else
+ fun_l26_n816(x)
+ end
+end
+
+def fun_l25_n861(x)
+ if (x < 1)
+ fun_l26_n584(x)
+ else
+ fun_l26_n671(x)
+ end
+end
+
+def fun_l25_n862(x)
+ if (x < 1)
+ fun_l26_n43(x)
+ else
+ fun_l26_n0(x)
+ end
+end
+
+def fun_l25_n863(x)
+ if (x < 1)
+ fun_l26_n697(x)
+ else
+ fun_l26_n842(x)
+ end
+end
+
+def fun_l25_n864(x)
+ if (x < 1)
+ fun_l26_n423(x)
+ else
+ fun_l26_n509(x)
+ end
+end
+
+def fun_l25_n865(x)
+ if (x < 1)
+ fun_l26_n239(x)
+ else
+ fun_l26_n257(x)
+ end
+end
+
+def fun_l25_n866(x)
+ if (x < 1)
+ fun_l26_n78(x)
+ else
+ fun_l26_n450(x)
+ end
+end
+
+def fun_l25_n867(x)
+ if (x < 1)
+ fun_l26_n121(x)
+ else
+ fun_l26_n453(x)
+ end
+end
+
+def fun_l25_n868(x)
+ if (x < 1)
+ fun_l26_n844(x)
+ else
+ fun_l26_n977(x)
+ end
+end
+
+def fun_l25_n869(x)
+ if (x < 1)
+ fun_l26_n54(x)
+ else
+ fun_l26_n869(x)
+ end
+end
+
+def fun_l25_n870(x)
+ if (x < 1)
+ fun_l26_n18(x)
+ else
+ fun_l26_n799(x)
+ end
+end
+
+def fun_l25_n871(x)
+ if (x < 1)
+ fun_l26_n990(x)
+ else
+ fun_l26_n53(x)
+ end
+end
+
+def fun_l25_n872(x)
+ if (x < 1)
+ fun_l26_n607(x)
+ else
+ fun_l26_n822(x)
+ end
+end
+
+def fun_l25_n873(x)
+ if (x < 1)
+ fun_l26_n378(x)
+ else
+ fun_l26_n158(x)
+ end
+end
+
+def fun_l25_n874(x)
+ if (x < 1)
+ fun_l26_n206(x)
+ else
+ fun_l26_n271(x)
+ end
+end
+
+def fun_l25_n875(x)
+ if (x < 1)
+ fun_l26_n536(x)
+ else
+ fun_l26_n850(x)
+ end
+end
+
+def fun_l25_n876(x)
+ if (x < 1)
+ fun_l26_n129(x)
+ else
+ fun_l26_n750(x)
+ end
+end
+
+def fun_l25_n877(x)
+ if (x < 1)
+ fun_l26_n553(x)
+ else
+ fun_l26_n815(x)
+ end
+end
+
+def fun_l25_n878(x)
+ if (x < 1)
+ fun_l26_n619(x)
+ else
+ fun_l26_n182(x)
+ end
+end
+
+def fun_l25_n879(x)
+ if (x < 1)
+ fun_l26_n529(x)
+ else
+ fun_l26_n541(x)
+ end
+end
+
+def fun_l25_n880(x)
+ if (x < 1)
+ fun_l26_n228(x)
+ else
+ fun_l26_n672(x)
+ end
+end
+
+def fun_l25_n881(x)
+ if (x < 1)
+ fun_l26_n834(x)
+ else
+ fun_l26_n830(x)
+ end
+end
+
+def fun_l25_n882(x)
+ if (x < 1)
+ fun_l26_n80(x)
+ else
+ fun_l26_n257(x)
+ end
+end
+
+def fun_l25_n883(x)
+ if (x < 1)
+ fun_l26_n805(x)
+ else
+ fun_l26_n589(x)
+ end
+end
+
+def fun_l25_n884(x)
+ if (x < 1)
+ fun_l26_n20(x)
+ else
+ fun_l26_n880(x)
+ end
+end
+
+def fun_l25_n885(x)
+ if (x < 1)
+ fun_l26_n924(x)
+ else
+ fun_l26_n832(x)
+ end
+end
+
+def fun_l25_n886(x)
+ if (x < 1)
+ fun_l26_n262(x)
+ else
+ fun_l26_n928(x)
+ end
+end
+
+def fun_l25_n887(x)
+ if (x < 1)
+ fun_l26_n461(x)
+ else
+ fun_l26_n81(x)
+ end
+end
+
+def fun_l25_n888(x)
+ if (x < 1)
+ fun_l26_n484(x)
+ else
+ fun_l26_n376(x)
+ end
+end
+
+def fun_l25_n889(x)
+ if (x < 1)
+ fun_l26_n26(x)
+ else
+ fun_l26_n28(x)
+ end
+end
+
+def fun_l25_n890(x)
+ if (x < 1)
+ fun_l26_n184(x)
+ else
+ fun_l26_n623(x)
+ end
+end
+
+def fun_l25_n891(x)
+ if (x < 1)
+ fun_l26_n326(x)
+ else
+ fun_l26_n441(x)
+ end
+end
+
+def fun_l25_n892(x)
+ if (x < 1)
+ fun_l26_n35(x)
+ else
+ fun_l26_n543(x)
+ end
+end
+
+def fun_l25_n893(x)
+ if (x < 1)
+ fun_l26_n568(x)
+ else
+ fun_l26_n229(x)
+ end
+end
+
+def fun_l25_n894(x)
+ if (x < 1)
+ fun_l26_n163(x)
+ else
+ fun_l26_n505(x)
+ end
+end
+
+def fun_l25_n895(x)
+ if (x < 1)
+ fun_l26_n675(x)
+ else
+ fun_l26_n508(x)
+ end
+end
+
+def fun_l25_n896(x)
+ if (x < 1)
+ fun_l26_n285(x)
+ else
+ fun_l26_n936(x)
+ end
+end
+
+def fun_l25_n897(x)
+ if (x < 1)
+ fun_l26_n848(x)
+ else
+ fun_l26_n169(x)
+ end
+end
+
+def fun_l25_n898(x)
+ if (x < 1)
+ fun_l26_n139(x)
+ else
+ fun_l26_n479(x)
+ end
+end
+
+def fun_l25_n899(x)
+ if (x < 1)
+ fun_l26_n355(x)
+ else
+ fun_l26_n49(x)
+ end
+end
+
+def fun_l25_n900(x)
+ if (x < 1)
+ fun_l26_n918(x)
+ else
+ fun_l26_n215(x)
+ end
+end
+
+def fun_l25_n901(x)
+ if (x < 1)
+ fun_l26_n55(x)
+ else
+ fun_l26_n550(x)
+ end
+end
+
+def fun_l25_n902(x)
+ if (x < 1)
+ fun_l26_n660(x)
+ else
+ fun_l26_n117(x)
+ end
+end
+
+def fun_l25_n903(x)
+ if (x < 1)
+ fun_l26_n968(x)
+ else
+ fun_l26_n279(x)
+ end
+end
+
+def fun_l25_n904(x)
+ if (x < 1)
+ fun_l26_n693(x)
+ else
+ fun_l26_n57(x)
+ end
+end
+
+def fun_l25_n905(x)
+ if (x < 1)
+ fun_l26_n248(x)
+ else
+ fun_l26_n154(x)
+ end
+end
+
+def fun_l25_n906(x)
+ if (x < 1)
+ fun_l26_n837(x)
+ else
+ fun_l26_n698(x)
+ end
+end
+
+def fun_l25_n907(x)
+ if (x < 1)
+ fun_l26_n630(x)
+ else
+ fun_l26_n460(x)
+ end
+end
+
+def fun_l25_n908(x)
+ if (x < 1)
+ fun_l26_n424(x)
+ else
+ fun_l26_n243(x)
+ end
+end
+
+def fun_l25_n909(x)
+ if (x < 1)
+ fun_l26_n897(x)
+ else
+ fun_l26_n736(x)
+ end
+end
+
+def fun_l25_n910(x)
+ if (x < 1)
+ fun_l26_n573(x)
+ else
+ fun_l26_n205(x)
+ end
+end
+
+def fun_l25_n911(x)
+ if (x < 1)
+ fun_l26_n535(x)
+ else
+ fun_l26_n970(x)
+ end
+end
+
+def fun_l25_n912(x)
+ if (x < 1)
+ fun_l26_n826(x)
+ else
+ fun_l26_n744(x)
+ end
+end
+
+def fun_l25_n913(x)
+ if (x < 1)
+ fun_l26_n244(x)
+ else
+ fun_l26_n216(x)
+ end
+end
+
+def fun_l25_n914(x)
+ if (x < 1)
+ fun_l26_n958(x)
+ else
+ fun_l26_n617(x)
+ end
+end
+
+def fun_l25_n915(x)
+ if (x < 1)
+ fun_l26_n911(x)
+ else
+ fun_l26_n684(x)
+ end
+end
+
+def fun_l25_n916(x)
+ if (x < 1)
+ fun_l26_n294(x)
+ else
+ fun_l26_n319(x)
+ end
+end
+
+def fun_l25_n917(x)
+ if (x < 1)
+ fun_l26_n665(x)
+ else
+ fun_l26_n867(x)
+ end
+end
+
+def fun_l25_n918(x)
+ if (x < 1)
+ fun_l26_n733(x)
+ else
+ fun_l26_n746(x)
+ end
+end
+
+def fun_l25_n919(x)
+ if (x < 1)
+ fun_l26_n243(x)
+ else
+ fun_l26_n328(x)
+ end
+end
+
+def fun_l25_n920(x)
+ if (x < 1)
+ fun_l26_n897(x)
+ else
+ fun_l26_n197(x)
+ end
+end
+
+def fun_l25_n921(x)
+ if (x < 1)
+ fun_l26_n528(x)
+ else
+ fun_l26_n229(x)
+ end
+end
+
+def fun_l25_n922(x)
+ if (x < 1)
+ fun_l26_n897(x)
+ else
+ fun_l26_n547(x)
+ end
+end
+
+def fun_l25_n923(x)
+ if (x < 1)
+ fun_l26_n234(x)
+ else
+ fun_l26_n920(x)
+ end
+end
+
+def fun_l25_n924(x)
+ if (x < 1)
+ fun_l26_n827(x)
+ else
+ fun_l26_n257(x)
+ end
+end
+
+def fun_l25_n925(x)
+ if (x < 1)
+ fun_l26_n847(x)
+ else
+ fun_l26_n469(x)
+ end
+end
+
+def fun_l25_n926(x)
+ if (x < 1)
+ fun_l26_n27(x)
+ else
+ fun_l26_n974(x)
+ end
+end
+
+def fun_l25_n927(x)
+ if (x < 1)
+ fun_l26_n872(x)
+ else
+ fun_l26_n535(x)
+ end
+end
+
+def fun_l25_n928(x)
+ if (x < 1)
+ fun_l26_n870(x)
+ else
+ fun_l26_n783(x)
+ end
+end
+
+def fun_l25_n929(x)
+ if (x < 1)
+ fun_l26_n993(x)
+ else
+ fun_l26_n168(x)
+ end
+end
+
+def fun_l25_n930(x)
+ if (x < 1)
+ fun_l26_n852(x)
+ else
+ fun_l26_n41(x)
+ end
+end
+
+def fun_l25_n931(x)
+ if (x < 1)
+ fun_l26_n290(x)
+ else
+ fun_l26_n249(x)
+ end
+end
+
+def fun_l25_n932(x)
+ if (x < 1)
+ fun_l26_n446(x)
+ else
+ fun_l26_n841(x)
+ end
+end
+
+def fun_l25_n933(x)
+ if (x < 1)
+ fun_l26_n303(x)
+ else
+ fun_l26_n779(x)
+ end
+end
+
+def fun_l25_n934(x)
+ if (x < 1)
+ fun_l26_n352(x)
+ else
+ fun_l26_n731(x)
+ end
+end
+
+def fun_l25_n935(x)
+ if (x < 1)
+ fun_l26_n377(x)
+ else
+ fun_l26_n214(x)
+ end
+end
+
+def fun_l25_n936(x)
+ if (x < 1)
+ fun_l26_n374(x)
+ else
+ fun_l26_n793(x)
+ end
+end
+
+def fun_l25_n937(x)
+ if (x < 1)
+ fun_l26_n656(x)
+ else
+ fun_l26_n575(x)
+ end
+end
+
+def fun_l25_n938(x)
+ if (x < 1)
+ fun_l26_n777(x)
+ else
+ fun_l26_n773(x)
+ end
+end
+
+def fun_l25_n939(x)
+ if (x < 1)
+ fun_l26_n5(x)
+ else
+ fun_l26_n206(x)
+ end
+end
+
+def fun_l25_n940(x)
+ if (x < 1)
+ fun_l26_n780(x)
+ else
+ fun_l26_n486(x)
+ end
+end
+
+def fun_l25_n941(x)
+ if (x < 1)
+ fun_l26_n634(x)
+ else
+ fun_l26_n727(x)
+ end
+end
+
+def fun_l25_n942(x)
+ if (x < 1)
+ fun_l26_n78(x)
+ else
+ fun_l26_n918(x)
+ end
+end
+
+def fun_l25_n943(x)
+ if (x < 1)
+ fun_l26_n616(x)
+ else
+ fun_l26_n35(x)
+ end
+end
+
+def fun_l25_n944(x)
+ if (x < 1)
+ fun_l26_n540(x)
+ else
+ fun_l26_n837(x)
+ end
+end
+
+def fun_l25_n945(x)
+ if (x < 1)
+ fun_l26_n365(x)
+ else
+ fun_l26_n561(x)
+ end
+end
+
+def fun_l25_n946(x)
+ if (x < 1)
+ fun_l26_n519(x)
+ else
+ fun_l26_n440(x)
+ end
+end
+
+def fun_l25_n947(x)
+ if (x < 1)
+ fun_l26_n144(x)
+ else
+ fun_l26_n426(x)
+ end
+end
+
+def fun_l25_n948(x)
+ if (x < 1)
+ fun_l26_n973(x)
+ else
+ fun_l26_n63(x)
+ end
+end
+
+def fun_l25_n949(x)
+ if (x < 1)
+ fun_l26_n258(x)
+ else
+ fun_l26_n690(x)
+ end
+end
+
+def fun_l25_n950(x)
+ if (x < 1)
+ fun_l26_n368(x)
+ else
+ fun_l26_n307(x)
+ end
+end
+
+def fun_l25_n951(x)
+ if (x < 1)
+ fun_l26_n133(x)
+ else
+ fun_l26_n774(x)
+ end
+end
+
+def fun_l25_n952(x)
+ if (x < 1)
+ fun_l26_n866(x)
+ else
+ fun_l26_n299(x)
+ end
+end
+
+def fun_l25_n953(x)
+ if (x < 1)
+ fun_l26_n72(x)
+ else
+ fun_l26_n421(x)
+ end
+end
+
+def fun_l25_n954(x)
+ if (x < 1)
+ fun_l26_n990(x)
+ else
+ fun_l26_n716(x)
+ end
+end
+
+def fun_l25_n955(x)
+ if (x < 1)
+ fun_l26_n138(x)
+ else
+ fun_l26_n387(x)
+ end
+end
+
+def fun_l25_n956(x)
+ if (x < 1)
+ fun_l26_n451(x)
+ else
+ fun_l26_n965(x)
+ end
+end
+
+def fun_l25_n957(x)
+ if (x < 1)
+ fun_l26_n292(x)
+ else
+ fun_l26_n741(x)
+ end
+end
+
+def fun_l25_n958(x)
+ if (x < 1)
+ fun_l26_n835(x)
+ else
+ fun_l26_n82(x)
+ end
+end
+
+def fun_l25_n959(x)
+ if (x < 1)
+ fun_l26_n73(x)
+ else
+ fun_l26_n987(x)
+ end
+end
+
+def fun_l25_n960(x)
+ if (x < 1)
+ fun_l26_n465(x)
+ else
+ fun_l26_n893(x)
+ end
+end
+
+def fun_l25_n961(x)
+ if (x < 1)
+ fun_l26_n277(x)
+ else
+ fun_l26_n846(x)
+ end
+end
+
+def fun_l25_n962(x)
+ if (x < 1)
+ fun_l26_n1(x)
+ else
+ fun_l26_n408(x)
+ end
+end
+
+def fun_l25_n963(x)
+ if (x < 1)
+ fun_l26_n139(x)
+ else
+ fun_l26_n43(x)
+ end
+end
+
+def fun_l25_n964(x)
+ if (x < 1)
+ fun_l26_n238(x)
+ else
+ fun_l26_n427(x)
+ end
+end
+
+def fun_l25_n965(x)
+ if (x < 1)
+ fun_l26_n150(x)
+ else
+ fun_l26_n60(x)
+ end
+end
+
+def fun_l25_n966(x)
+ if (x < 1)
+ fun_l26_n423(x)
+ else
+ fun_l26_n166(x)
+ end
+end
+
+def fun_l25_n967(x)
+ if (x < 1)
+ fun_l26_n102(x)
+ else
+ fun_l26_n679(x)
+ end
+end
+
+def fun_l25_n968(x)
+ if (x < 1)
+ fun_l26_n41(x)
+ else
+ fun_l26_n553(x)
+ end
+end
+
+def fun_l25_n969(x)
+ if (x < 1)
+ fun_l26_n577(x)
+ else
+ fun_l26_n589(x)
+ end
+end
+
+def fun_l25_n970(x)
+ if (x < 1)
+ fun_l26_n569(x)
+ else
+ fun_l26_n677(x)
+ end
+end
+
+def fun_l25_n971(x)
+ if (x < 1)
+ fun_l26_n845(x)
+ else
+ fun_l26_n237(x)
+ end
+end
+
+def fun_l25_n972(x)
+ if (x < 1)
+ fun_l26_n33(x)
+ else
+ fun_l26_n281(x)
+ end
+end
+
+def fun_l25_n973(x)
+ if (x < 1)
+ fun_l26_n432(x)
+ else
+ fun_l26_n800(x)
+ end
+end
+
+def fun_l25_n974(x)
+ if (x < 1)
+ fun_l26_n49(x)
+ else
+ fun_l26_n864(x)
+ end
+end
+
+def fun_l25_n975(x)
+ if (x < 1)
+ fun_l26_n379(x)
+ else
+ fun_l26_n704(x)
+ end
+end
+
+def fun_l25_n976(x)
+ if (x < 1)
+ fun_l26_n778(x)
+ else
+ fun_l26_n310(x)
+ end
+end
+
+def fun_l25_n977(x)
+ if (x < 1)
+ fun_l26_n137(x)
+ else
+ fun_l26_n261(x)
+ end
+end
+
+def fun_l25_n978(x)
+ if (x < 1)
+ fun_l26_n38(x)
+ else
+ fun_l26_n244(x)
+ end
+end
+
+def fun_l25_n979(x)
+ if (x < 1)
+ fun_l26_n665(x)
+ else
+ fun_l26_n883(x)
+ end
+end
+
+def fun_l25_n980(x)
+ if (x < 1)
+ fun_l26_n448(x)
+ else
+ fun_l26_n619(x)
+ end
+end
+
+def fun_l25_n981(x)
+ if (x < 1)
+ fun_l26_n652(x)
+ else
+ fun_l26_n804(x)
+ end
+end
+
+def fun_l25_n982(x)
+ if (x < 1)
+ fun_l26_n804(x)
+ else
+ fun_l26_n110(x)
+ end
+end
+
+def fun_l25_n983(x)
+ if (x < 1)
+ fun_l26_n151(x)
+ else
+ fun_l26_n588(x)
+ end
+end
+
+def fun_l25_n984(x)
+ if (x < 1)
+ fun_l26_n379(x)
+ else
+ fun_l26_n156(x)
+ end
+end
+
+def fun_l25_n985(x)
+ if (x < 1)
+ fun_l26_n936(x)
+ else
+ fun_l26_n31(x)
+ end
+end
+
+def fun_l25_n986(x)
+ if (x < 1)
+ fun_l26_n65(x)
+ else
+ fun_l26_n303(x)
+ end
+end
+
+def fun_l25_n987(x)
+ if (x < 1)
+ fun_l26_n273(x)
+ else
+ fun_l26_n4(x)
+ end
+end
+
+def fun_l25_n988(x)
+ if (x < 1)
+ fun_l26_n538(x)
+ else
+ fun_l26_n357(x)
+ end
+end
+
+def fun_l25_n989(x)
+ if (x < 1)
+ fun_l26_n922(x)
+ else
+ fun_l26_n457(x)
+ end
+end
+
+def fun_l25_n990(x)
+ if (x < 1)
+ fun_l26_n250(x)
+ else
+ fun_l26_n945(x)
+ end
+end
+
+def fun_l25_n991(x)
+ if (x < 1)
+ fun_l26_n878(x)
+ else
+ fun_l26_n992(x)
+ end
+end
+
+def fun_l25_n992(x)
+ if (x < 1)
+ fun_l26_n767(x)
+ else
+ fun_l26_n132(x)
+ end
+end
+
+def fun_l25_n993(x)
+ if (x < 1)
+ fun_l26_n737(x)
+ else
+ fun_l26_n323(x)
+ end
+end
+
+def fun_l25_n994(x)
+ if (x < 1)
+ fun_l26_n173(x)
+ else
+ fun_l26_n424(x)
+ end
+end
+
+def fun_l25_n995(x)
+ if (x < 1)
+ fun_l26_n860(x)
+ else
+ fun_l26_n390(x)
+ end
+end
+
+def fun_l25_n996(x)
+ if (x < 1)
+ fun_l26_n794(x)
+ else
+ fun_l26_n613(x)
+ end
+end
+
+def fun_l25_n997(x)
+ if (x < 1)
+ fun_l26_n807(x)
+ else
+ fun_l26_n277(x)
+ end
+end
+
+def fun_l25_n998(x)
+ if (x < 1)
+ fun_l26_n418(x)
+ else
+ fun_l26_n830(x)
+ end
+end
+
+def fun_l25_n999(x)
+ if (x < 1)
+ fun_l26_n212(x)
+ else
+ fun_l26_n863(x)
+ end
+end
+
+def fun_l26_n0(x)
+ if (x < 1)
+ fun_l27_n276(x)
+ else
+ fun_l27_n243(x)
+ end
+end
+
+def fun_l26_n1(x)
+ if (x < 1)
+ fun_l27_n136(x)
+ else
+ fun_l27_n625(x)
+ end
+end
+
+def fun_l26_n2(x)
+ if (x < 1)
+ fun_l27_n205(x)
+ else
+ fun_l27_n576(x)
+ end
+end
+
+def fun_l26_n3(x)
+ if (x < 1)
+ fun_l27_n97(x)
+ else
+ fun_l27_n753(x)
+ end
+end
+
+def fun_l26_n4(x)
+ if (x < 1)
+ fun_l27_n984(x)
+ else
+ fun_l27_n827(x)
+ end
+end
+
+def fun_l26_n5(x)
+ if (x < 1)
+ fun_l27_n428(x)
+ else
+ fun_l27_n559(x)
+ end
+end
+
+def fun_l26_n6(x)
+ if (x < 1)
+ fun_l27_n148(x)
+ else
+ fun_l27_n351(x)
+ end
+end
+
+def fun_l26_n7(x)
+ if (x < 1)
+ fun_l27_n90(x)
+ else
+ fun_l27_n241(x)
+ end
+end
+
+def fun_l26_n8(x)
+ if (x < 1)
+ fun_l27_n860(x)
+ else
+ fun_l27_n495(x)
+ end
+end
+
+def fun_l26_n9(x)
+ if (x < 1)
+ fun_l27_n245(x)
+ else
+ fun_l27_n429(x)
+ end
+end
+
+def fun_l26_n10(x)
+ if (x < 1)
+ fun_l27_n999(x)
+ else
+ fun_l27_n536(x)
+ end
+end
+
+def fun_l26_n11(x)
+ if (x < 1)
+ fun_l27_n777(x)
+ else
+ fun_l27_n823(x)
+ end
+end
+
+def fun_l26_n12(x)
+ if (x < 1)
+ fun_l27_n158(x)
+ else
+ fun_l27_n249(x)
+ end
+end
+
+def fun_l26_n13(x)
+ if (x < 1)
+ fun_l27_n781(x)
+ else
+ fun_l27_n710(x)
+ end
+end
+
+def fun_l26_n14(x)
+ if (x < 1)
+ fun_l27_n784(x)
+ else
+ fun_l27_n728(x)
+ end
+end
+
+def fun_l26_n15(x)
+ if (x < 1)
+ fun_l27_n225(x)
+ else
+ fun_l27_n216(x)
+ end
+end
+
+def fun_l26_n16(x)
+ if (x < 1)
+ fun_l27_n228(x)
+ else
+ fun_l27_n219(x)
+ end
+end
+
+def fun_l26_n17(x)
+ if (x < 1)
+ fun_l27_n849(x)
+ else
+ fun_l27_n348(x)
+ end
+end
+
+def fun_l26_n18(x)
+ if (x < 1)
+ fun_l27_n722(x)
+ else
+ fun_l27_n884(x)
+ end
+end
+
+def fun_l26_n19(x)
+ if (x < 1)
+ fun_l27_n756(x)
+ else
+ fun_l27_n715(x)
+ end
+end
+
+def fun_l26_n20(x)
+ if (x < 1)
+ fun_l27_n217(x)
+ else
+ fun_l27_n909(x)
+ end
+end
+
+def fun_l26_n21(x)
+ if (x < 1)
+ fun_l27_n239(x)
+ else
+ fun_l27_n370(x)
+ end
+end
+
+def fun_l26_n22(x)
+ if (x < 1)
+ fun_l27_n954(x)
+ else
+ fun_l27_n223(x)
+ end
+end
+
+def fun_l26_n23(x)
+ if (x < 1)
+ fun_l27_n781(x)
+ else
+ fun_l27_n845(x)
+ end
+end
+
+def fun_l26_n24(x)
+ if (x < 1)
+ fun_l27_n80(x)
+ else
+ fun_l27_n71(x)
+ end
+end
+
+def fun_l26_n25(x)
+ if (x < 1)
+ fun_l27_n850(x)
+ else
+ fun_l27_n715(x)
+ end
+end
+
+def fun_l26_n26(x)
+ if (x < 1)
+ fun_l27_n632(x)
+ else
+ fun_l27_n624(x)
+ end
+end
+
+def fun_l26_n27(x)
+ if (x < 1)
+ fun_l27_n342(x)
+ else
+ fun_l27_n999(x)
+ end
+end
+
+def fun_l26_n28(x)
+ if (x < 1)
+ fun_l27_n105(x)
+ else
+ fun_l27_n390(x)
+ end
+end
+
+def fun_l26_n29(x)
+ if (x < 1)
+ fun_l27_n972(x)
+ else
+ fun_l27_n451(x)
+ end
+end
+
+def fun_l26_n30(x)
+ if (x < 1)
+ fun_l27_n364(x)
+ else
+ fun_l27_n392(x)
+ end
+end
+
+def fun_l26_n31(x)
+ if (x < 1)
+ fun_l27_n892(x)
+ else
+ fun_l27_n874(x)
+ end
+end
+
+def fun_l26_n32(x)
+ if (x < 1)
+ fun_l27_n783(x)
+ else
+ fun_l27_n456(x)
+ end
+end
+
+def fun_l26_n33(x)
+ if (x < 1)
+ fun_l27_n491(x)
+ else
+ fun_l27_n479(x)
+ end
+end
+
+def fun_l26_n34(x)
+ if (x < 1)
+ fun_l27_n799(x)
+ else
+ fun_l27_n438(x)
+ end
+end
+
+def fun_l26_n35(x)
+ if (x < 1)
+ fun_l27_n335(x)
+ else
+ fun_l27_n263(x)
+ end
+end
+
+def fun_l26_n36(x)
+ if (x < 1)
+ fun_l27_n935(x)
+ else
+ fun_l27_n715(x)
+ end
+end
+
+def fun_l26_n37(x)
+ if (x < 1)
+ fun_l27_n2(x)
+ else
+ fun_l27_n13(x)
+ end
+end
+
+def fun_l26_n38(x)
+ if (x < 1)
+ fun_l27_n567(x)
+ else
+ fun_l27_n878(x)
+ end
+end
+
+def fun_l26_n39(x)
+ if (x < 1)
+ fun_l27_n144(x)
+ else
+ fun_l27_n349(x)
+ end
+end
+
+def fun_l26_n40(x)
+ if (x < 1)
+ fun_l27_n957(x)
+ else
+ fun_l27_n990(x)
+ end
+end
+
+def fun_l26_n41(x)
+ if (x < 1)
+ fun_l27_n501(x)
+ else
+ fun_l27_n752(x)
+ end
+end
+
+def fun_l26_n42(x)
+ if (x < 1)
+ fun_l27_n23(x)
+ else
+ fun_l27_n200(x)
+ end
+end
+
+def fun_l26_n43(x)
+ if (x < 1)
+ fun_l27_n61(x)
+ else
+ fun_l27_n306(x)
+ end
+end
+
+def fun_l26_n44(x)
+ if (x < 1)
+ fun_l27_n336(x)
+ else
+ fun_l27_n468(x)
+ end
+end
+
+def fun_l26_n45(x)
+ if (x < 1)
+ fun_l27_n350(x)
+ else
+ fun_l27_n359(x)
+ end
+end
+
+def fun_l26_n46(x)
+ if (x < 1)
+ fun_l27_n574(x)
+ else
+ fun_l27_n791(x)
+ end
+end
+
+def fun_l26_n47(x)
+ if (x < 1)
+ fun_l27_n859(x)
+ else
+ fun_l27_n524(x)
+ end
+end
+
+def fun_l26_n48(x)
+ if (x < 1)
+ fun_l27_n530(x)
+ else
+ fun_l27_n387(x)
+ end
+end
+
+def fun_l26_n49(x)
+ if (x < 1)
+ fun_l27_n174(x)
+ else
+ fun_l27_n673(x)
+ end
+end
+
+def fun_l26_n50(x)
+ if (x < 1)
+ fun_l27_n457(x)
+ else
+ fun_l27_n996(x)
+ end
+end
+
+def fun_l26_n51(x)
+ if (x < 1)
+ fun_l27_n757(x)
+ else
+ fun_l27_n84(x)
+ end
+end
+
+def fun_l26_n52(x)
+ if (x < 1)
+ fun_l27_n315(x)
+ else
+ fun_l27_n790(x)
+ end
+end
+
+def fun_l26_n53(x)
+ if (x < 1)
+ fun_l27_n452(x)
+ else
+ fun_l27_n201(x)
+ end
+end
+
+def fun_l26_n54(x)
+ if (x < 1)
+ fun_l27_n153(x)
+ else
+ fun_l27_n143(x)
+ end
+end
+
+def fun_l26_n55(x)
+ if (x < 1)
+ fun_l27_n476(x)
+ else
+ fun_l27_n149(x)
+ end
+end
+
+def fun_l26_n56(x)
+ if (x < 1)
+ fun_l27_n737(x)
+ else
+ fun_l27_n628(x)
+ end
+end
+
+def fun_l26_n57(x)
+ if (x < 1)
+ fun_l27_n780(x)
+ else
+ fun_l27_n906(x)
+ end
+end
+
+def fun_l26_n58(x)
+ if (x < 1)
+ fun_l27_n914(x)
+ else
+ fun_l27_n197(x)
+ end
+end
+
+def fun_l26_n59(x)
+ if (x < 1)
+ fun_l27_n816(x)
+ else
+ fun_l27_n16(x)
+ end
+end
+
+def fun_l26_n60(x)
+ if (x < 1)
+ fun_l27_n643(x)
+ else
+ fun_l27_n90(x)
+ end
+end
+
+def fun_l26_n61(x)
+ if (x < 1)
+ fun_l27_n514(x)
+ else
+ fun_l27_n156(x)
+ end
+end
+
+def fun_l26_n62(x)
+ if (x < 1)
+ fun_l27_n261(x)
+ else
+ fun_l27_n410(x)
+ end
+end
+
+def fun_l26_n63(x)
+ if (x < 1)
+ fun_l27_n82(x)
+ else
+ fun_l27_n817(x)
+ end
+end
+
+def fun_l26_n64(x)
+ if (x < 1)
+ fun_l27_n755(x)
+ else
+ fun_l27_n438(x)
+ end
+end
+
+def fun_l26_n65(x)
+ if (x < 1)
+ fun_l27_n960(x)
+ else
+ fun_l27_n600(x)
+ end
+end
+
+def fun_l26_n66(x)
+ if (x < 1)
+ fun_l27_n100(x)
+ else
+ fun_l27_n699(x)
+ end
+end
+
+def fun_l26_n67(x)
+ if (x < 1)
+ fun_l27_n367(x)
+ else
+ fun_l27_n783(x)
+ end
+end
+
+def fun_l26_n68(x)
+ if (x < 1)
+ fun_l27_n691(x)
+ else
+ fun_l27_n996(x)
+ end
+end
+
+def fun_l26_n69(x)
+ if (x < 1)
+ fun_l27_n989(x)
+ else
+ fun_l27_n628(x)
+ end
+end
+
+def fun_l26_n70(x)
+ if (x < 1)
+ fun_l27_n139(x)
+ else
+ fun_l27_n4(x)
+ end
+end
+
+def fun_l26_n71(x)
+ if (x < 1)
+ fun_l27_n890(x)
+ else
+ fun_l27_n88(x)
+ end
+end
+
+def fun_l26_n72(x)
+ if (x < 1)
+ fun_l27_n35(x)
+ else
+ fun_l27_n991(x)
+ end
+end
+
+def fun_l26_n73(x)
+ if (x < 1)
+ fun_l27_n613(x)
+ else
+ fun_l27_n836(x)
+ end
+end
+
+def fun_l26_n74(x)
+ if (x < 1)
+ fun_l27_n739(x)
+ else
+ fun_l27_n455(x)
+ end
+end
+
+def fun_l26_n75(x)
+ if (x < 1)
+ fun_l27_n382(x)
+ else
+ fun_l27_n909(x)
+ end
+end
+
+def fun_l26_n76(x)
+ if (x < 1)
+ fun_l27_n480(x)
+ else
+ fun_l27_n178(x)
+ end
+end
+
+def fun_l26_n77(x)
+ if (x < 1)
+ fun_l27_n180(x)
+ else
+ fun_l27_n577(x)
+ end
+end
+
+def fun_l26_n78(x)
+ if (x < 1)
+ fun_l27_n910(x)
+ else
+ fun_l27_n659(x)
+ end
+end
+
+def fun_l26_n79(x)
+ if (x < 1)
+ fun_l27_n710(x)
+ else
+ fun_l27_n159(x)
+ end
+end
+
+def fun_l26_n80(x)
+ if (x < 1)
+ fun_l27_n153(x)
+ else
+ fun_l27_n367(x)
+ end
+end
+
+def fun_l26_n81(x)
+ if (x < 1)
+ fun_l27_n935(x)
+ else
+ fun_l27_n389(x)
+ end
+end
+
+def fun_l26_n82(x)
+ if (x < 1)
+ fun_l27_n782(x)
+ else
+ fun_l27_n333(x)
+ end
+end
+
+def fun_l26_n83(x)
+ if (x < 1)
+ fun_l27_n85(x)
+ else
+ fun_l27_n122(x)
+ end
+end
+
+def fun_l26_n84(x)
+ if (x < 1)
+ fun_l27_n722(x)
+ else
+ fun_l27_n937(x)
+ end
+end
+
+def fun_l26_n85(x)
+ if (x < 1)
+ fun_l27_n403(x)
+ else
+ fun_l27_n270(x)
+ end
+end
+
+def fun_l26_n86(x)
+ if (x < 1)
+ fun_l27_n987(x)
+ else
+ fun_l27_n622(x)
+ end
+end
+
+def fun_l26_n87(x)
+ if (x < 1)
+ fun_l27_n316(x)
+ else
+ fun_l27_n519(x)
+ end
+end
+
+def fun_l26_n88(x)
+ if (x < 1)
+ fun_l27_n503(x)
+ else
+ fun_l27_n320(x)
+ end
+end
+
+def fun_l26_n89(x)
+ if (x < 1)
+ fun_l27_n936(x)
+ else
+ fun_l27_n77(x)
+ end
+end
+
+def fun_l26_n90(x)
+ if (x < 1)
+ fun_l27_n875(x)
+ else
+ fun_l27_n857(x)
+ end
+end
+
+def fun_l26_n91(x)
+ if (x < 1)
+ fun_l27_n277(x)
+ else
+ fun_l27_n231(x)
+ end
+end
+
+def fun_l26_n92(x)
+ if (x < 1)
+ fun_l27_n743(x)
+ else
+ fun_l27_n468(x)
+ end
+end
+
+def fun_l26_n93(x)
+ if (x < 1)
+ fun_l27_n997(x)
+ else
+ fun_l27_n49(x)
+ end
+end
+
+def fun_l26_n94(x)
+ if (x < 1)
+ fun_l27_n410(x)
+ else
+ fun_l27_n123(x)
+ end
+end
+
+def fun_l26_n95(x)
+ if (x < 1)
+ fun_l27_n696(x)
+ else
+ fun_l27_n799(x)
+ end
+end
+
+def fun_l26_n96(x)
+ if (x < 1)
+ fun_l27_n47(x)
+ else
+ fun_l27_n195(x)
+ end
+end
+
+def fun_l26_n97(x)
+ if (x < 1)
+ fun_l27_n559(x)
+ else
+ fun_l27_n242(x)
+ end
+end
+
+def fun_l26_n98(x)
+ if (x < 1)
+ fun_l27_n407(x)
+ else
+ fun_l27_n797(x)
+ end
+end
+
+def fun_l26_n99(x)
+ if (x < 1)
+ fun_l27_n886(x)
+ else
+ fun_l27_n253(x)
+ end
+end
+
+def fun_l26_n100(x)
+ if (x < 1)
+ fun_l27_n753(x)
+ else
+ fun_l27_n103(x)
+ end
+end
+
+def fun_l26_n101(x)
+ if (x < 1)
+ fun_l27_n717(x)
+ else
+ fun_l27_n596(x)
+ end
+end
+
+def fun_l26_n102(x)
+ if (x < 1)
+ fun_l27_n88(x)
+ else
+ fun_l27_n916(x)
+ end
+end
+
+def fun_l26_n103(x)
+ if (x < 1)
+ fun_l27_n504(x)
+ else
+ fun_l27_n91(x)
+ end
+end
+
+def fun_l26_n104(x)
+ if (x < 1)
+ fun_l27_n418(x)
+ else
+ fun_l27_n810(x)
+ end
+end
+
+def fun_l26_n105(x)
+ if (x < 1)
+ fun_l27_n736(x)
+ else
+ fun_l27_n515(x)
+ end
+end
+
+def fun_l26_n106(x)
+ if (x < 1)
+ fun_l27_n450(x)
+ else
+ fun_l27_n778(x)
+ end
+end
+
+def fun_l26_n107(x)
+ if (x < 1)
+ fun_l27_n670(x)
+ else
+ fun_l27_n483(x)
+ end
+end
+
+def fun_l26_n108(x)
+ if (x < 1)
+ fun_l27_n592(x)
+ else
+ fun_l27_n638(x)
+ end
+end
+
+def fun_l26_n109(x)
+ if (x < 1)
+ fun_l27_n803(x)
+ else
+ fun_l27_n865(x)
+ end
+end
+
+def fun_l26_n110(x)
+ if (x < 1)
+ fun_l27_n555(x)
+ else
+ fun_l27_n123(x)
+ end
+end
+
+def fun_l26_n111(x)
+ if (x < 1)
+ fun_l27_n5(x)
+ else
+ fun_l27_n768(x)
+ end
+end
+
+def fun_l26_n112(x)
+ if (x < 1)
+ fun_l27_n452(x)
+ else
+ fun_l27_n356(x)
+ end
+end
+
+def fun_l26_n113(x)
+ if (x < 1)
+ fun_l27_n353(x)
+ else
+ fun_l27_n513(x)
+ end
+end
+
+def fun_l26_n114(x)
+ if (x < 1)
+ fun_l27_n859(x)
+ else
+ fun_l27_n851(x)
+ end
+end
+
+def fun_l26_n115(x)
+ if (x < 1)
+ fun_l27_n47(x)
+ else
+ fun_l27_n206(x)
+ end
+end
+
+def fun_l26_n116(x)
+ if (x < 1)
+ fun_l27_n260(x)
+ else
+ fun_l27_n746(x)
+ end
+end
+
+def fun_l26_n117(x)
+ if (x < 1)
+ fun_l27_n733(x)
+ else
+ fun_l27_n906(x)
+ end
+end
+
+def fun_l26_n118(x)
+ if (x < 1)
+ fun_l27_n40(x)
+ else
+ fun_l27_n467(x)
+ end
+end
+
+def fun_l26_n119(x)
+ if (x < 1)
+ fun_l27_n764(x)
+ else
+ fun_l27_n69(x)
+ end
+end
+
+def fun_l26_n120(x)
+ if (x < 1)
+ fun_l27_n851(x)
+ else
+ fun_l27_n905(x)
+ end
+end
+
+def fun_l26_n121(x)
+ if (x < 1)
+ fun_l27_n793(x)
+ else
+ fun_l27_n169(x)
+ end
+end
+
+def fun_l26_n122(x)
+ if (x < 1)
+ fun_l27_n126(x)
+ else
+ fun_l27_n440(x)
+ end
+end
+
+def fun_l26_n123(x)
+ if (x < 1)
+ fun_l27_n147(x)
+ else
+ fun_l27_n720(x)
+ end
+end
+
+def fun_l26_n124(x)
+ if (x < 1)
+ fun_l27_n843(x)
+ else
+ fun_l27_n789(x)
+ end
+end
+
+def fun_l26_n125(x)
+ if (x < 1)
+ fun_l27_n927(x)
+ else
+ fun_l27_n364(x)
+ end
+end
+
+def fun_l26_n126(x)
+ if (x < 1)
+ fun_l27_n203(x)
+ else
+ fun_l27_n344(x)
+ end
+end
+
+def fun_l26_n127(x)
+ if (x < 1)
+ fun_l27_n398(x)
+ else
+ fun_l27_n202(x)
+ end
+end
+
+def fun_l26_n128(x)
+ if (x < 1)
+ fun_l27_n216(x)
+ else
+ fun_l27_n344(x)
+ end
+end
+
+def fun_l26_n129(x)
+ if (x < 1)
+ fun_l27_n496(x)
+ else
+ fun_l27_n40(x)
+ end
+end
+
+def fun_l26_n130(x)
+ if (x < 1)
+ fun_l27_n615(x)
+ else
+ fun_l27_n762(x)
+ end
+end
+
+def fun_l26_n131(x)
+ if (x < 1)
+ fun_l27_n642(x)
+ else
+ fun_l27_n329(x)
+ end
+end
+
+def fun_l26_n132(x)
+ if (x < 1)
+ fun_l27_n364(x)
+ else
+ fun_l27_n436(x)
+ end
+end
+
+def fun_l26_n133(x)
+ if (x < 1)
+ fun_l27_n502(x)
+ else
+ fun_l27_n176(x)
+ end
+end
+
+def fun_l26_n134(x)
+ if (x < 1)
+ fun_l27_n591(x)
+ else
+ fun_l27_n119(x)
+ end
+end
+
+def fun_l26_n135(x)
+ if (x < 1)
+ fun_l27_n946(x)
+ else
+ fun_l27_n963(x)
+ end
+end
+
+def fun_l26_n136(x)
+ if (x < 1)
+ fun_l27_n688(x)
+ else
+ fun_l27_n44(x)
+ end
+end
+
+def fun_l26_n137(x)
+ if (x < 1)
+ fun_l27_n786(x)
+ else
+ fun_l27_n965(x)
+ end
+end
+
+def fun_l26_n138(x)
+ if (x < 1)
+ fun_l27_n259(x)
+ else
+ fun_l27_n63(x)
+ end
+end
+
+def fun_l26_n139(x)
+ if (x < 1)
+ fun_l27_n568(x)
+ else
+ fun_l27_n129(x)
+ end
+end
+
+def fun_l26_n140(x)
+ if (x < 1)
+ fun_l27_n255(x)
+ else
+ fun_l27_n873(x)
+ end
+end
+
+def fun_l26_n141(x)
+ if (x < 1)
+ fun_l27_n777(x)
+ else
+ fun_l27_n86(x)
+ end
+end
+
+def fun_l26_n142(x)
+ if (x < 1)
+ fun_l27_n134(x)
+ else
+ fun_l27_n569(x)
+ end
+end
+
+def fun_l26_n143(x)
+ if (x < 1)
+ fun_l27_n147(x)
+ else
+ fun_l27_n388(x)
+ end
+end
+
+def fun_l26_n144(x)
+ if (x < 1)
+ fun_l27_n633(x)
+ else
+ fun_l27_n256(x)
+ end
+end
+
+def fun_l26_n145(x)
+ if (x < 1)
+ fun_l27_n38(x)
+ else
+ fun_l27_n94(x)
+ end
+end
+
+def fun_l26_n146(x)
+ if (x < 1)
+ fun_l27_n710(x)
+ else
+ fun_l27_n489(x)
+ end
+end
+
+def fun_l26_n147(x)
+ if (x < 1)
+ fun_l27_n187(x)
+ else
+ fun_l27_n252(x)
+ end
+end
+
+def fun_l26_n148(x)
+ if (x < 1)
+ fun_l27_n978(x)
+ else
+ fun_l27_n835(x)
+ end
+end
+
+def fun_l26_n149(x)
+ if (x < 1)
+ fun_l27_n759(x)
+ else
+ fun_l27_n742(x)
+ end
+end
+
+def fun_l26_n150(x)
+ if (x < 1)
+ fun_l27_n438(x)
+ else
+ fun_l27_n808(x)
+ end
+end
+
+def fun_l26_n151(x)
+ if (x < 1)
+ fun_l27_n424(x)
+ else
+ fun_l27_n54(x)
+ end
+end
+
+def fun_l26_n152(x)
+ if (x < 1)
+ fun_l27_n455(x)
+ else
+ fun_l27_n953(x)
+ end
+end
+
+def fun_l26_n153(x)
+ if (x < 1)
+ fun_l27_n13(x)
+ else
+ fun_l27_n330(x)
+ end
+end
+
+def fun_l26_n154(x)
+ if (x < 1)
+ fun_l27_n399(x)
+ else
+ fun_l27_n81(x)
+ end
+end
+
+def fun_l26_n155(x)
+ if (x < 1)
+ fun_l27_n356(x)
+ else
+ fun_l27_n237(x)
+ end
+end
+
+def fun_l26_n156(x)
+ if (x < 1)
+ fun_l27_n636(x)
+ else
+ fun_l27_n446(x)
+ end
+end
+
+def fun_l26_n157(x)
+ if (x < 1)
+ fun_l27_n715(x)
+ else
+ fun_l27_n800(x)
+ end
+end
+
+def fun_l26_n158(x)
+ if (x < 1)
+ fun_l27_n284(x)
+ else
+ fun_l27_n280(x)
+ end
+end
+
+def fun_l26_n159(x)
+ if (x < 1)
+ fun_l27_n41(x)
+ else
+ fun_l27_n65(x)
+ end
+end
+
+def fun_l26_n160(x)
+ if (x < 1)
+ fun_l27_n691(x)
+ else
+ fun_l27_n76(x)
+ end
+end
+
+def fun_l26_n161(x)
+ if (x < 1)
+ fun_l27_n863(x)
+ else
+ fun_l27_n878(x)
+ end
+end
+
+def fun_l26_n162(x)
+ if (x < 1)
+ fun_l27_n694(x)
+ else
+ fun_l27_n5(x)
+ end
+end
+
+def fun_l26_n163(x)
+ if (x < 1)
+ fun_l27_n16(x)
+ else
+ fun_l27_n644(x)
+ end
+end
+
+def fun_l26_n164(x)
+ if (x < 1)
+ fun_l27_n760(x)
+ else
+ fun_l27_n167(x)
+ end
+end
+
+def fun_l26_n165(x)
+ if (x < 1)
+ fun_l27_n884(x)
+ else
+ fun_l27_n297(x)
+ end
+end
+
+def fun_l26_n166(x)
+ if (x < 1)
+ fun_l27_n707(x)
+ else
+ fun_l27_n456(x)
+ end
+end
+
+def fun_l26_n167(x)
+ if (x < 1)
+ fun_l27_n140(x)
+ else
+ fun_l27_n143(x)
+ end
+end
+
+def fun_l26_n168(x)
+ if (x < 1)
+ fun_l27_n581(x)
+ else
+ fun_l27_n369(x)
+ end
+end
+
+def fun_l26_n169(x)
+ if (x < 1)
+ fun_l27_n538(x)
+ else
+ fun_l27_n276(x)
+ end
+end
+
+def fun_l26_n170(x)
+ if (x < 1)
+ fun_l27_n984(x)
+ else
+ fun_l27_n729(x)
+ end
+end
+
+def fun_l26_n171(x)
+ if (x < 1)
+ fun_l27_n274(x)
+ else
+ fun_l27_n519(x)
+ end
+end
+
+def fun_l26_n172(x)
+ if (x < 1)
+ fun_l27_n597(x)
+ else
+ fun_l27_n632(x)
+ end
+end
+
+def fun_l26_n173(x)
+ if (x < 1)
+ fun_l27_n485(x)
+ else
+ fun_l27_n130(x)
+ end
+end
+
+def fun_l26_n174(x)
+ if (x < 1)
+ fun_l27_n460(x)
+ else
+ fun_l27_n133(x)
+ end
+end
+
+def fun_l26_n175(x)
+ if (x < 1)
+ fun_l27_n512(x)
+ else
+ fun_l27_n252(x)
+ end
+end
+
+def fun_l26_n176(x)
+ if (x < 1)
+ fun_l27_n429(x)
+ else
+ fun_l27_n297(x)
+ end
+end
+
+def fun_l26_n177(x)
+ if (x < 1)
+ fun_l27_n497(x)
+ else
+ fun_l27_n845(x)
+ end
+end
+
+def fun_l26_n178(x)
+ if (x < 1)
+ fun_l27_n930(x)
+ else
+ fun_l27_n923(x)
+ end
+end
+
+def fun_l26_n179(x)
+ if (x < 1)
+ fun_l27_n218(x)
+ else
+ fun_l27_n921(x)
+ end
+end
+
+def fun_l26_n180(x)
+ if (x < 1)
+ fun_l27_n793(x)
+ else
+ fun_l27_n278(x)
+ end
+end
+
+def fun_l26_n181(x)
+ if (x < 1)
+ fun_l27_n606(x)
+ else
+ fun_l27_n9(x)
+ end
+end
+
+def fun_l26_n182(x)
+ if (x < 1)
+ fun_l27_n297(x)
+ else
+ fun_l27_n62(x)
+ end
+end
+
+def fun_l26_n183(x)
+ if (x < 1)
+ fun_l27_n174(x)
+ else
+ fun_l27_n698(x)
+ end
+end
+
+def fun_l26_n184(x)
+ if (x < 1)
+ fun_l27_n773(x)
+ else
+ fun_l27_n312(x)
+ end
+end
+
+def fun_l26_n185(x)
+ if (x < 1)
+ fun_l27_n75(x)
+ else
+ fun_l27_n65(x)
+ end
+end
+
+def fun_l26_n186(x)
+ if (x < 1)
+ fun_l27_n389(x)
+ else
+ fun_l27_n27(x)
+ end
+end
+
+def fun_l26_n187(x)
+ if (x < 1)
+ fun_l27_n674(x)
+ else
+ fun_l27_n70(x)
+ end
+end
+
+def fun_l26_n188(x)
+ if (x < 1)
+ fun_l27_n157(x)
+ else
+ fun_l27_n160(x)
+ end
+end
+
+def fun_l26_n189(x)
+ if (x < 1)
+ fun_l27_n401(x)
+ else
+ fun_l27_n340(x)
+ end
+end
+
+def fun_l26_n190(x)
+ if (x < 1)
+ fun_l27_n550(x)
+ else
+ fun_l27_n551(x)
+ end
+end
+
+def fun_l26_n191(x)
+ if (x < 1)
+ fun_l27_n971(x)
+ else
+ fun_l27_n925(x)
+ end
+end
+
+def fun_l26_n192(x)
+ if (x < 1)
+ fun_l27_n370(x)
+ else
+ fun_l27_n697(x)
+ end
+end
+
+def fun_l26_n193(x)
+ if (x < 1)
+ fun_l27_n188(x)
+ else
+ fun_l27_n989(x)
+ end
+end
+
+def fun_l26_n194(x)
+ if (x < 1)
+ fun_l27_n848(x)
+ else
+ fun_l27_n288(x)
+ end
+end
+
+def fun_l26_n195(x)
+ if (x < 1)
+ fun_l27_n886(x)
+ else
+ fun_l27_n554(x)
+ end
+end
+
+def fun_l26_n196(x)
+ if (x < 1)
+ fun_l27_n989(x)
+ else
+ fun_l27_n577(x)
+ end
+end
+
+def fun_l26_n197(x)
+ if (x < 1)
+ fun_l27_n55(x)
+ else
+ fun_l27_n951(x)
+ end
+end
+
+def fun_l26_n198(x)
+ if (x < 1)
+ fun_l27_n750(x)
+ else
+ fun_l27_n941(x)
+ end
+end
+
+def fun_l26_n199(x)
+ if (x < 1)
+ fun_l27_n468(x)
+ else
+ fun_l27_n64(x)
+ end
+end
+
+def fun_l26_n200(x)
+ if (x < 1)
+ fun_l27_n617(x)
+ else
+ fun_l27_n156(x)
+ end
+end
+
+def fun_l26_n201(x)
+ if (x < 1)
+ fun_l27_n119(x)
+ else
+ fun_l27_n63(x)
+ end
+end
+
+def fun_l26_n202(x)
+ if (x < 1)
+ fun_l27_n524(x)
+ else
+ fun_l27_n455(x)
+ end
+end
+
+def fun_l26_n203(x)
+ if (x < 1)
+ fun_l27_n489(x)
+ else
+ fun_l27_n328(x)
+ end
+end
+
+def fun_l26_n204(x)
+ if (x < 1)
+ fun_l27_n854(x)
+ else
+ fun_l27_n605(x)
+ end
+end
+
+def fun_l26_n205(x)
+ if (x < 1)
+ fun_l27_n591(x)
+ else
+ fun_l27_n787(x)
+ end
+end
+
+def fun_l26_n206(x)
+ if (x < 1)
+ fun_l27_n122(x)
+ else
+ fun_l27_n977(x)
+ end
+end
+
+def fun_l26_n207(x)
+ if (x < 1)
+ fun_l27_n204(x)
+ else
+ fun_l27_n652(x)
+ end
+end
+
+def fun_l26_n208(x)
+ if (x < 1)
+ fun_l27_n213(x)
+ else
+ fun_l27_n699(x)
+ end
+end
+
+def fun_l26_n209(x)
+ if (x < 1)
+ fun_l27_n731(x)
+ else
+ fun_l27_n910(x)
+ end
+end
+
+def fun_l26_n210(x)
+ if (x < 1)
+ fun_l27_n398(x)
+ else
+ fun_l27_n2(x)
+ end
+end
+
+def fun_l26_n211(x)
+ if (x < 1)
+ fun_l27_n132(x)
+ else
+ fun_l27_n574(x)
+ end
+end
+
+def fun_l26_n212(x)
+ if (x < 1)
+ fun_l27_n701(x)
+ else
+ fun_l27_n617(x)
+ end
+end
+
+def fun_l26_n213(x)
+ if (x < 1)
+ fun_l27_n486(x)
+ else
+ fun_l27_n861(x)
+ end
+end
+
+def fun_l26_n214(x)
+ if (x < 1)
+ fun_l27_n305(x)
+ else
+ fun_l27_n20(x)
+ end
+end
+
+def fun_l26_n215(x)
+ if (x < 1)
+ fun_l27_n598(x)
+ else
+ fun_l27_n842(x)
+ end
+end
+
+def fun_l26_n216(x)
+ if (x < 1)
+ fun_l27_n948(x)
+ else
+ fun_l27_n669(x)
+ end
+end
+
+def fun_l26_n217(x)
+ if (x < 1)
+ fun_l27_n344(x)
+ else
+ fun_l27_n101(x)
+ end
+end
+
+def fun_l26_n218(x)
+ if (x < 1)
+ fun_l27_n527(x)
+ else
+ fun_l27_n930(x)
+ end
+end
+
+def fun_l26_n219(x)
+ if (x < 1)
+ fun_l27_n889(x)
+ else
+ fun_l27_n380(x)
+ end
+end
+
+def fun_l26_n220(x)
+ if (x < 1)
+ fun_l27_n873(x)
+ else
+ fun_l27_n925(x)
+ end
+end
+
+def fun_l26_n221(x)
+ if (x < 1)
+ fun_l27_n403(x)
+ else
+ fun_l27_n280(x)
+ end
+end
+
+def fun_l26_n222(x)
+ if (x < 1)
+ fun_l27_n614(x)
+ else
+ fun_l27_n370(x)
+ end
+end
+
+def fun_l26_n223(x)
+ if (x < 1)
+ fun_l27_n543(x)
+ else
+ fun_l27_n543(x)
+ end
+end
+
+def fun_l26_n224(x)
+ if (x < 1)
+ fun_l27_n873(x)
+ else
+ fun_l27_n895(x)
+ end
+end
+
+def fun_l26_n225(x)
+ if (x < 1)
+ fun_l27_n665(x)
+ else
+ fun_l27_n259(x)
+ end
+end
+
+def fun_l26_n226(x)
+ if (x < 1)
+ fun_l27_n663(x)
+ else
+ fun_l27_n271(x)
+ end
+end
+
+def fun_l26_n227(x)
+ if (x < 1)
+ fun_l27_n816(x)
+ else
+ fun_l27_n353(x)
+ end
+end
+
+def fun_l26_n228(x)
+ if (x < 1)
+ fun_l27_n941(x)
+ else
+ fun_l27_n484(x)
+ end
+end
+
+def fun_l26_n229(x)
+ if (x < 1)
+ fun_l27_n455(x)
+ else
+ fun_l27_n385(x)
+ end
+end
+
+def fun_l26_n230(x)
+ if (x < 1)
+ fun_l27_n398(x)
+ else
+ fun_l27_n888(x)
+ end
+end
+
+def fun_l26_n231(x)
+ if (x < 1)
+ fun_l27_n93(x)
+ else
+ fun_l27_n297(x)
+ end
+end
+
+def fun_l26_n232(x)
+ if (x < 1)
+ fun_l27_n197(x)
+ else
+ fun_l27_n779(x)
+ end
+end
+
+def fun_l26_n233(x)
+ if (x < 1)
+ fun_l27_n826(x)
+ else
+ fun_l27_n835(x)
+ end
+end
+
+def fun_l26_n234(x)
+ if (x < 1)
+ fun_l27_n32(x)
+ else
+ fun_l27_n430(x)
+ end
+end
+
+def fun_l26_n235(x)
+ if (x < 1)
+ fun_l27_n133(x)
+ else
+ fun_l27_n743(x)
+ end
+end
+
+def fun_l26_n236(x)
+ if (x < 1)
+ fun_l27_n763(x)
+ else
+ fun_l27_n683(x)
+ end
+end
+
+def fun_l26_n237(x)
+ if (x < 1)
+ fun_l27_n211(x)
+ else
+ fun_l27_n726(x)
+ end
+end
+
+def fun_l26_n238(x)
+ if (x < 1)
+ fun_l27_n19(x)
+ else
+ fun_l27_n404(x)
+ end
+end
+
+def fun_l26_n239(x)
+ if (x < 1)
+ fun_l27_n635(x)
+ else
+ fun_l27_n427(x)
+ end
+end
+
+def fun_l26_n240(x)
+ if (x < 1)
+ fun_l27_n102(x)
+ else
+ fun_l27_n875(x)
+ end
+end
+
+def fun_l26_n241(x)
+ if (x < 1)
+ fun_l27_n930(x)
+ else
+ fun_l27_n189(x)
+ end
+end
+
+def fun_l26_n242(x)
+ if (x < 1)
+ fun_l27_n860(x)
+ else
+ fun_l27_n347(x)
+ end
+end
+
+def fun_l26_n243(x)
+ if (x < 1)
+ fun_l27_n826(x)
+ else
+ fun_l27_n848(x)
+ end
+end
+
+def fun_l26_n244(x)
+ if (x < 1)
+ fun_l27_n491(x)
+ else
+ fun_l27_n797(x)
+ end
+end
+
+def fun_l26_n245(x)
+ if (x < 1)
+ fun_l27_n361(x)
+ else
+ fun_l27_n382(x)
+ end
+end
+
+def fun_l26_n246(x)
+ if (x < 1)
+ fun_l27_n391(x)
+ else
+ fun_l27_n907(x)
+ end
+end
+
+def fun_l26_n247(x)
+ if (x < 1)
+ fun_l27_n352(x)
+ else
+ fun_l27_n501(x)
+ end
+end
+
+def fun_l26_n248(x)
+ if (x < 1)
+ fun_l27_n235(x)
+ else
+ fun_l27_n610(x)
+ end
+end
+
+def fun_l26_n249(x)
+ if (x < 1)
+ fun_l27_n970(x)
+ else
+ fun_l27_n561(x)
+ end
+end
+
+def fun_l26_n250(x)
+ if (x < 1)
+ fun_l27_n625(x)
+ else
+ fun_l27_n526(x)
+ end
+end
+
+def fun_l26_n251(x)
+ if (x < 1)
+ fun_l27_n185(x)
+ else
+ fun_l27_n911(x)
+ end
+end
+
+def fun_l26_n252(x)
+ if (x < 1)
+ fun_l27_n426(x)
+ else
+ fun_l27_n247(x)
+ end
+end
+
+def fun_l26_n253(x)
+ if (x < 1)
+ fun_l27_n874(x)
+ else
+ fun_l27_n28(x)
+ end
+end
+
+def fun_l26_n254(x)
+ if (x < 1)
+ fun_l27_n178(x)
+ else
+ fun_l27_n290(x)
+ end
+end
+
+def fun_l26_n255(x)
+ if (x < 1)
+ fun_l27_n218(x)
+ else
+ fun_l27_n816(x)
+ end
+end
+
+def fun_l26_n256(x)
+ if (x < 1)
+ fun_l27_n27(x)
+ else
+ fun_l27_n896(x)
+ end
+end
+
+def fun_l26_n257(x)
+ if (x < 1)
+ fun_l27_n690(x)
+ else
+ fun_l27_n27(x)
+ end
+end
+
+def fun_l26_n258(x)
+ if (x < 1)
+ fun_l27_n549(x)
+ else
+ fun_l27_n481(x)
+ end
+end
+
+def fun_l26_n259(x)
+ if (x < 1)
+ fun_l27_n357(x)
+ else
+ fun_l27_n604(x)
+ end
+end
+
+def fun_l26_n260(x)
+ if (x < 1)
+ fun_l27_n731(x)
+ else
+ fun_l27_n111(x)
+ end
+end
+
+def fun_l26_n261(x)
+ if (x < 1)
+ fun_l27_n849(x)
+ else
+ fun_l27_n91(x)
+ end
+end
+
+def fun_l26_n262(x)
+ if (x < 1)
+ fun_l27_n686(x)
+ else
+ fun_l27_n969(x)
+ end
+end
+
+def fun_l26_n263(x)
+ if (x < 1)
+ fun_l27_n17(x)
+ else
+ fun_l27_n424(x)
+ end
+end
+
+def fun_l26_n264(x)
+ if (x < 1)
+ fun_l27_n25(x)
+ else
+ fun_l27_n487(x)
+ end
+end
+
+def fun_l26_n265(x)
+ if (x < 1)
+ fun_l27_n715(x)
+ else
+ fun_l27_n210(x)
+ end
+end
+
+def fun_l26_n266(x)
+ if (x < 1)
+ fun_l27_n997(x)
+ else
+ fun_l27_n563(x)
+ end
+end
+
+def fun_l26_n267(x)
+ if (x < 1)
+ fun_l27_n489(x)
+ else
+ fun_l27_n666(x)
+ end
+end
+
+def fun_l26_n268(x)
+ if (x < 1)
+ fun_l27_n85(x)
+ else
+ fun_l27_n780(x)
+ end
+end
+
+def fun_l26_n269(x)
+ if (x < 1)
+ fun_l27_n420(x)
+ else
+ fun_l27_n897(x)
+ end
+end
+
+def fun_l26_n270(x)
+ if (x < 1)
+ fun_l27_n152(x)
+ else
+ fun_l27_n841(x)
+ end
+end
+
+def fun_l26_n271(x)
+ if (x < 1)
+ fun_l27_n60(x)
+ else
+ fun_l27_n808(x)
+ end
+end
+
+def fun_l26_n272(x)
+ if (x < 1)
+ fun_l27_n27(x)
+ else
+ fun_l27_n69(x)
+ end
+end
+
+def fun_l26_n273(x)
+ if (x < 1)
+ fun_l27_n992(x)
+ else
+ fun_l27_n306(x)
+ end
+end
+
+def fun_l26_n274(x)
+ if (x < 1)
+ fun_l27_n893(x)
+ else
+ fun_l27_n837(x)
+ end
+end
+
+def fun_l26_n275(x)
+ if (x < 1)
+ fun_l27_n617(x)
+ else
+ fun_l27_n628(x)
+ end
+end
+
+def fun_l26_n276(x)
+ if (x < 1)
+ fun_l27_n402(x)
+ else
+ fun_l27_n766(x)
+ end
+end
+
+def fun_l26_n277(x)
+ if (x < 1)
+ fun_l27_n692(x)
+ else
+ fun_l27_n999(x)
+ end
+end
+
+def fun_l26_n278(x)
+ if (x < 1)
+ fun_l27_n896(x)
+ else
+ fun_l27_n941(x)
+ end
+end
+
+def fun_l26_n279(x)
+ if (x < 1)
+ fun_l27_n440(x)
+ else
+ fun_l27_n888(x)
+ end
+end
+
+def fun_l26_n280(x)
+ if (x < 1)
+ fun_l27_n350(x)
+ else
+ fun_l27_n19(x)
+ end
+end
+
+def fun_l26_n281(x)
+ if (x < 1)
+ fun_l27_n324(x)
+ else
+ fun_l27_n63(x)
+ end
+end
+
+def fun_l26_n282(x)
+ if (x < 1)
+ fun_l27_n422(x)
+ else
+ fun_l27_n369(x)
+ end
+end
+
+def fun_l26_n283(x)
+ if (x < 1)
+ fun_l27_n629(x)
+ else
+ fun_l27_n200(x)
+ end
+end
+
+def fun_l26_n284(x)
+ if (x < 1)
+ fun_l27_n466(x)
+ else
+ fun_l27_n392(x)
+ end
+end
+
+def fun_l26_n285(x)
+ if (x < 1)
+ fun_l27_n995(x)
+ else
+ fun_l27_n374(x)
+ end
+end
+
+def fun_l26_n286(x)
+ if (x < 1)
+ fun_l27_n808(x)
+ else
+ fun_l27_n529(x)
+ end
+end
+
+def fun_l26_n287(x)
+ if (x < 1)
+ fun_l27_n764(x)
+ else
+ fun_l27_n155(x)
+ end
+end
+
+def fun_l26_n288(x)
+ if (x < 1)
+ fun_l27_n282(x)
+ else
+ fun_l27_n676(x)
+ end
+end
+
+def fun_l26_n289(x)
+ if (x < 1)
+ fun_l27_n797(x)
+ else
+ fun_l27_n462(x)
+ end
+end
+
+def fun_l26_n290(x)
+ if (x < 1)
+ fun_l27_n572(x)
+ else
+ fun_l27_n909(x)
+ end
+end
+
+def fun_l26_n291(x)
+ if (x < 1)
+ fun_l27_n401(x)
+ else
+ fun_l27_n906(x)
+ end
+end
+
+def fun_l26_n292(x)
+ if (x < 1)
+ fun_l27_n680(x)
+ else
+ fun_l27_n922(x)
+ end
+end
+
+def fun_l26_n293(x)
+ if (x < 1)
+ fun_l27_n876(x)
+ else
+ fun_l27_n882(x)
+ end
+end
+
+def fun_l26_n294(x)
+ if (x < 1)
+ fun_l27_n40(x)
+ else
+ fun_l27_n752(x)
+ end
+end
+
+def fun_l26_n295(x)
+ if (x < 1)
+ fun_l27_n164(x)
+ else
+ fun_l27_n479(x)
+ end
+end
+
+def fun_l26_n296(x)
+ if (x < 1)
+ fun_l27_n836(x)
+ else
+ fun_l27_n956(x)
+ end
+end
+
+def fun_l26_n297(x)
+ if (x < 1)
+ fun_l27_n197(x)
+ else
+ fun_l27_n135(x)
+ end
+end
+
+def fun_l26_n298(x)
+ if (x < 1)
+ fun_l27_n289(x)
+ else
+ fun_l27_n314(x)
+ end
+end
+
+def fun_l26_n299(x)
+ if (x < 1)
+ fun_l27_n942(x)
+ else
+ fun_l27_n747(x)
+ end
+end
+
+def fun_l26_n300(x)
+ if (x < 1)
+ fun_l27_n4(x)
+ else
+ fun_l27_n355(x)
+ end
+end
+
+def fun_l26_n301(x)
+ if (x < 1)
+ fun_l27_n616(x)
+ else
+ fun_l27_n681(x)
+ end
+end
+
+def fun_l26_n302(x)
+ if (x < 1)
+ fun_l27_n175(x)
+ else
+ fun_l27_n859(x)
+ end
+end
+
+def fun_l26_n303(x)
+ if (x < 1)
+ fun_l27_n323(x)
+ else
+ fun_l27_n491(x)
+ end
+end
+
+def fun_l26_n304(x)
+ if (x < 1)
+ fun_l27_n630(x)
+ else
+ fun_l27_n821(x)
+ end
+end
+
+def fun_l26_n305(x)
+ if (x < 1)
+ fun_l27_n416(x)
+ else
+ fun_l27_n927(x)
+ end
+end
+
+def fun_l26_n306(x)
+ if (x < 1)
+ fun_l27_n80(x)
+ else
+ fun_l27_n69(x)
+ end
+end
+
+def fun_l26_n307(x)
+ if (x < 1)
+ fun_l27_n209(x)
+ else
+ fun_l27_n476(x)
+ end
+end
+
+def fun_l26_n308(x)
+ if (x < 1)
+ fun_l27_n201(x)
+ else
+ fun_l27_n18(x)
+ end
+end
+
+def fun_l26_n309(x)
+ if (x < 1)
+ fun_l27_n712(x)
+ else
+ fun_l27_n697(x)
+ end
+end
+
+def fun_l26_n310(x)
+ if (x < 1)
+ fun_l27_n815(x)
+ else
+ fun_l27_n626(x)
+ end
+end
+
+def fun_l26_n311(x)
+ if (x < 1)
+ fun_l27_n159(x)
+ else
+ fun_l27_n483(x)
+ end
+end
+
+def fun_l26_n312(x)
+ if (x < 1)
+ fun_l27_n304(x)
+ else
+ fun_l27_n260(x)
+ end
+end
+
+def fun_l26_n313(x)
+ if (x < 1)
+ fun_l27_n15(x)
+ else
+ fun_l27_n50(x)
+ end
+end
+
+def fun_l26_n314(x)
+ if (x < 1)
+ fun_l27_n748(x)
+ else
+ fun_l27_n71(x)
+ end
+end
+
+def fun_l26_n315(x)
+ if (x < 1)
+ fun_l27_n957(x)
+ else
+ fun_l27_n90(x)
+ end
+end
+
+def fun_l26_n316(x)
+ if (x < 1)
+ fun_l27_n189(x)
+ else
+ fun_l27_n276(x)
+ end
+end
+
+def fun_l26_n317(x)
+ if (x < 1)
+ fun_l27_n926(x)
+ else
+ fun_l27_n916(x)
+ end
+end
+
+def fun_l26_n318(x)
+ if (x < 1)
+ fun_l27_n74(x)
+ else
+ fun_l27_n395(x)
+ end
+end
+
+def fun_l26_n319(x)
+ if (x < 1)
+ fun_l27_n424(x)
+ else
+ fun_l27_n826(x)
+ end
+end
+
+def fun_l26_n320(x)
+ if (x < 1)
+ fun_l27_n321(x)
+ else
+ fun_l27_n553(x)
+ end
+end
+
+def fun_l26_n321(x)
+ if (x < 1)
+ fun_l27_n906(x)
+ else
+ fun_l27_n344(x)
+ end
+end
+
+def fun_l26_n322(x)
+ if (x < 1)
+ fun_l27_n706(x)
+ else
+ fun_l27_n189(x)
+ end
+end
+
+def fun_l26_n323(x)
+ if (x < 1)
+ fun_l27_n303(x)
+ else
+ fun_l27_n135(x)
+ end
+end
+
+def fun_l26_n324(x)
+ if (x < 1)
+ fun_l27_n103(x)
+ else
+ fun_l27_n579(x)
+ end
+end
+
+def fun_l26_n325(x)
+ if (x < 1)
+ fun_l27_n655(x)
+ else
+ fun_l27_n619(x)
+ end
+end
+
+def fun_l26_n326(x)
+ if (x < 1)
+ fun_l27_n119(x)
+ else
+ fun_l27_n950(x)
+ end
+end
+
+def fun_l26_n327(x)
+ if (x < 1)
+ fun_l27_n402(x)
+ else
+ fun_l27_n490(x)
+ end
+end
+
+def fun_l26_n328(x)
+ if (x < 1)
+ fun_l27_n6(x)
+ else
+ fun_l27_n844(x)
+ end
+end
+
+def fun_l26_n329(x)
+ if (x < 1)
+ fun_l27_n297(x)
+ else
+ fun_l27_n879(x)
+ end
+end
+
+def fun_l26_n330(x)
+ if (x < 1)
+ fun_l27_n747(x)
+ else
+ fun_l27_n701(x)
+ end
+end
+
+def fun_l26_n331(x)
+ if (x < 1)
+ fun_l27_n714(x)
+ else
+ fun_l27_n770(x)
+ end
+end
+
+def fun_l26_n332(x)
+ if (x < 1)
+ fun_l27_n377(x)
+ else
+ fun_l27_n434(x)
+ end
+end
+
+def fun_l26_n333(x)
+ if (x < 1)
+ fun_l27_n530(x)
+ else
+ fun_l27_n678(x)
+ end
+end
+
+def fun_l26_n334(x)
+ if (x < 1)
+ fun_l27_n28(x)
+ else
+ fun_l27_n154(x)
+ end
+end
+
+def fun_l26_n335(x)
+ if (x < 1)
+ fun_l27_n905(x)
+ else
+ fun_l27_n207(x)
+ end
+end
+
+def fun_l26_n336(x)
+ if (x < 1)
+ fun_l27_n537(x)
+ else
+ fun_l27_n426(x)
+ end
+end
+
+def fun_l26_n337(x)
+ if (x < 1)
+ fun_l27_n284(x)
+ else
+ fun_l27_n118(x)
+ end
+end
+
+def fun_l26_n338(x)
+ if (x < 1)
+ fun_l27_n40(x)
+ else
+ fun_l27_n123(x)
+ end
+end
+
+def fun_l26_n339(x)
+ if (x < 1)
+ fun_l27_n620(x)
+ else
+ fun_l27_n370(x)
+ end
+end
+
+def fun_l26_n340(x)
+ if (x < 1)
+ fun_l27_n946(x)
+ else
+ fun_l27_n994(x)
+ end
+end
+
+def fun_l26_n341(x)
+ if (x < 1)
+ fun_l27_n685(x)
+ else
+ fun_l27_n911(x)
+ end
+end
+
+def fun_l26_n342(x)
+ if (x < 1)
+ fun_l27_n641(x)
+ else
+ fun_l27_n339(x)
+ end
+end
+
+def fun_l26_n343(x)
+ if (x < 1)
+ fun_l27_n936(x)
+ else
+ fun_l27_n344(x)
+ end
+end
+
+def fun_l26_n344(x)
+ if (x < 1)
+ fun_l27_n822(x)
+ else
+ fun_l27_n939(x)
+ end
+end
+
+def fun_l26_n345(x)
+ if (x < 1)
+ fun_l27_n608(x)
+ else
+ fun_l27_n870(x)
+ end
+end
+
+def fun_l26_n346(x)
+ if (x < 1)
+ fun_l27_n211(x)
+ else
+ fun_l27_n124(x)
+ end
+end
+
+def fun_l26_n347(x)
+ if (x < 1)
+ fun_l27_n71(x)
+ else
+ fun_l27_n9(x)
+ end
+end
+
+def fun_l26_n348(x)
+ if (x < 1)
+ fun_l27_n68(x)
+ else
+ fun_l27_n51(x)
+ end
+end
+
+def fun_l26_n349(x)
+ if (x < 1)
+ fun_l27_n641(x)
+ else
+ fun_l27_n665(x)
+ end
+end
+
+def fun_l26_n350(x)
+ if (x < 1)
+ fun_l27_n516(x)
+ else
+ fun_l27_n364(x)
+ end
+end
+
+def fun_l26_n351(x)
+ if (x < 1)
+ fun_l27_n104(x)
+ else
+ fun_l27_n569(x)
+ end
+end
+
+def fun_l26_n352(x)
+ if (x < 1)
+ fun_l27_n90(x)
+ else
+ fun_l27_n565(x)
+ end
+end
+
+def fun_l26_n353(x)
+ if (x < 1)
+ fun_l27_n647(x)
+ else
+ fun_l27_n124(x)
+ end
+end
+
+def fun_l26_n354(x)
+ if (x < 1)
+ fun_l27_n332(x)
+ else
+ fun_l27_n368(x)
+ end
+end
+
+def fun_l26_n355(x)
+ if (x < 1)
+ fun_l27_n547(x)
+ else
+ fun_l27_n797(x)
+ end
+end
+
+def fun_l26_n356(x)
+ if (x < 1)
+ fun_l27_n462(x)
+ else
+ fun_l27_n503(x)
+ end
+end
+
+def fun_l26_n357(x)
+ if (x < 1)
+ fun_l27_n25(x)
+ else
+ fun_l27_n920(x)
+ end
+end
+
+def fun_l26_n358(x)
+ if (x < 1)
+ fun_l27_n891(x)
+ else
+ fun_l27_n136(x)
+ end
+end
+
+def fun_l26_n359(x)
+ if (x < 1)
+ fun_l27_n785(x)
+ else
+ fun_l27_n600(x)
+ end
+end
+
+def fun_l26_n360(x)
+ if (x < 1)
+ fun_l27_n945(x)
+ else
+ fun_l27_n617(x)
+ end
+end
+
+def fun_l26_n361(x)
+ if (x < 1)
+ fun_l27_n995(x)
+ else
+ fun_l27_n781(x)
+ end
+end
+
+def fun_l26_n362(x)
+ if (x < 1)
+ fun_l27_n553(x)
+ else
+ fun_l27_n650(x)
+ end
+end
+
+def fun_l26_n363(x)
+ if (x < 1)
+ fun_l27_n937(x)
+ else
+ fun_l27_n382(x)
+ end
+end
+
+def fun_l26_n364(x)
+ if (x < 1)
+ fun_l27_n946(x)
+ else
+ fun_l27_n980(x)
+ end
+end
+
+def fun_l26_n365(x)
+ if (x < 1)
+ fun_l27_n293(x)
+ else
+ fun_l27_n225(x)
+ end
+end
+
+def fun_l26_n366(x)
+ if (x < 1)
+ fun_l27_n872(x)
+ else
+ fun_l27_n535(x)
+ end
+end
+
+def fun_l26_n367(x)
+ if (x < 1)
+ fun_l27_n427(x)
+ else
+ fun_l27_n175(x)
+ end
+end
+
+def fun_l26_n368(x)
+ if (x < 1)
+ fun_l27_n111(x)
+ else
+ fun_l27_n379(x)
+ end
+end
+
+def fun_l26_n369(x)
+ if (x < 1)
+ fun_l27_n735(x)
+ else
+ fun_l27_n921(x)
+ end
+end
+
+def fun_l26_n370(x)
+ if (x < 1)
+ fun_l27_n818(x)
+ else
+ fun_l27_n189(x)
+ end
+end
+
+def fun_l26_n371(x)
+ if (x < 1)
+ fun_l27_n932(x)
+ else
+ fun_l27_n884(x)
+ end
+end
+
+def fun_l26_n372(x)
+ if (x < 1)
+ fun_l27_n40(x)
+ else
+ fun_l27_n732(x)
+ end
+end
+
+def fun_l26_n373(x)
+ if (x < 1)
+ fun_l27_n54(x)
+ else
+ fun_l27_n365(x)
+ end
+end
+
+def fun_l26_n374(x)
+ if (x < 1)
+ fun_l27_n742(x)
+ else
+ fun_l27_n319(x)
+ end
+end
+
+def fun_l26_n375(x)
+ if (x < 1)
+ fun_l27_n149(x)
+ else
+ fun_l27_n504(x)
+ end
+end
+
+def fun_l26_n376(x)
+ if (x < 1)
+ fun_l27_n185(x)
+ else
+ fun_l27_n458(x)
+ end
+end
+
+def fun_l26_n377(x)
+ if (x < 1)
+ fun_l27_n107(x)
+ else
+ fun_l27_n201(x)
+ end
+end
+
+def fun_l26_n378(x)
+ if (x < 1)
+ fun_l27_n94(x)
+ else
+ fun_l27_n173(x)
+ end
+end
+
+def fun_l26_n379(x)
+ if (x < 1)
+ fun_l27_n198(x)
+ else
+ fun_l27_n885(x)
+ end
+end
+
+def fun_l26_n380(x)
+ if (x < 1)
+ fun_l27_n164(x)
+ else
+ fun_l27_n23(x)
+ end
+end
+
+def fun_l26_n381(x)
+ if (x < 1)
+ fun_l27_n170(x)
+ else
+ fun_l27_n431(x)
+ end
+end
+
+def fun_l26_n382(x)
+ if (x < 1)
+ fun_l27_n679(x)
+ else
+ fun_l27_n613(x)
+ end
+end
+
+def fun_l26_n383(x)
+ if (x < 1)
+ fun_l27_n981(x)
+ else
+ fun_l27_n69(x)
+ end
+end
+
+def fun_l26_n384(x)
+ if (x < 1)
+ fun_l27_n600(x)
+ else
+ fun_l27_n544(x)
+ end
+end
+
+def fun_l26_n385(x)
+ if (x < 1)
+ fun_l27_n153(x)
+ else
+ fun_l27_n332(x)
+ end
+end
+
+def fun_l26_n386(x)
+ if (x < 1)
+ fun_l27_n63(x)
+ else
+ fun_l27_n597(x)
+ end
+end
+
+def fun_l26_n387(x)
+ if (x < 1)
+ fun_l27_n259(x)
+ else
+ fun_l27_n33(x)
+ end
+end
+
+def fun_l26_n388(x)
+ if (x < 1)
+ fun_l27_n363(x)
+ else
+ fun_l27_n765(x)
+ end
+end
+
+def fun_l26_n389(x)
+ if (x < 1)
+ fun_l27_n495(x)
+ else
+ fun_l27_n133(x)
+ end
+end
+
+def fun_l26_n390(x)
+ if (x < 1)
+ fun_l27_n62(x)
+ else
+ fun_l27_n462(x)
+ end
+end
+
+def fun_l26_n391(x)
+ if (x < 1)
+ fun_l27_n811(x)
+ else
+ fun_l27_n30(x)
+ end
+end
+
+def fun_l26_n392(x)
+ if (x < 1)
+ fun_l27_n222(x)
+ else
+ fun_l27_n451(x)
+ end
+end
+
+def fun_l26_n393(x)
+ if (x < 1)
+ fun_l27_n286(x)
+ else
+ fun_l27_n664(x)
+ end
+end
+
+def fun_l26_n394(x)
+ if (x < 1)
+ fun_l27_n935(x)
+ else
+ fun_l27_n392(x)
+ end
+end
+
+def fun_l26_n395(x)
+ if (x < 1)
+ fun_l27_n621(x)
+ else
+ fun_l27_n434(x)
+ end
+end
+
+def fun_l26_n396(x)
+ if (x < 1)
+ fun_l27_n318(x)
+ else
+ fun_l27_n410(x)
+ end
+end
+
+def fun_l26_n397(x)
+ if (x < 1)
+ fun_l27_n847(x)
+ else
+ fun_l27_n727(x)
+ end
+end
+
+def fun_l26_n398(x)
+ if (x < 1)
+ fun_l27_n705(x)
+ else
+ fun_l27_n453(x)
+ end
+end
+
+def fun_l26_n399(x)
+ if (x < 1)
+ fun_l27_n787(x)
+ else
+ fun_l27_n442(x)
+ end
+end
+
+def fun_l26_n400(x)
+ if (x < 1)
+ fun_l27_n854(x)
+ else
+ fun_l27_n885(x)
+ end
+end
+
+def fun_l26_n401(x)
+ if (x < 1)
+ fun_l27_n825(x)
+ else
+ fun_l27_n399(x)
+ end
+end
+
+def fun_l26_n402(x)
+ if (x < 1)
+ fun_l27_n420(x)
+ else
+ fun_l27_n747(x)
+ end
+end
+
+def fun_l26_n403(x)
+ if (x < 1)
+ fun_l27_n985(x)
+ else
+ fun_l27_n875(x)
+ end
+end
+
+def fun_l26_n404(x)
+ if (x < 1)
+ fun_l27_n193(x)
+ else
+ fun_l27_n448(x)
+ end
+end
+
+def fun_l26_n405(x)
+ if (x < 1)
+ fun_l27_n594(x)
+ else
+ fun_l27_n769(x)
+ end
+end
+
+def fun_l26_n406(x)
+ if (x < 1)
+ fun_l27_n774(x)
+ else
+ fun_l27_n44(x)
+ end
+end
+
+def fun_l26_n407(x)
+ if (x < 1)
+ fun_l27_n563(x)
+ else
+ fun_l27_n979(x)
+ end
+end
+
+def fun_l26_n408(x)
+ if (x < 1)
+ fun_l27_n369(x)
+ else
+ fun_l27_n825(x)
+ end
+end
+
+def fun_l26_n409(x)
+ if (x < 1)
+ fun_l27_n70(x)
+ else
+ fun_l27_n894(x)
+ end
+end
+
+def fun_l26_n410(x)
+ if (x < 1)
+ fun_l27_n651(x)
+ else
+ fun_l27_n224(x)
+ end
+end
+
+def fun_l26_n411(x)
+ if (x < 1)
+ fun_l27_n219(x)
+ else
+ fun_l27_n193(x)
+ end
+end
+
+def fun_l26_n412(x)
+ if (x < 1)
+ fun_l27_n16(x)
+ else
+ fun_l27_n113(x)
+ end
+end
+
+def fun_l26_n413(x)
+ if (x < 1)
+ fun_l27_n653(x)
+ else
+ fun_l27_n754(x)
+ end
+end
+
+def fun_l26_n414(x)
+ if (x < 1)
+ fun_l27_n682(x)
+ else
+ fun_l27_n378(x)
+ end
+end
+
+def fun_l26_n415(x)
+ if (x < 1)
+ fun_l27_n326(x)
+ else
+ fun_l27_n534(x)
+ end
+end
+
+def fun_l26_n416(x)
+ if (x < 1)
+ fun_l27_n552(x)
+ else
+ fun_l27_n627(x)
+ end
+end
+
+def fun_l26_n417(x)
+ if (x < 1)
+ fun_l27_n486(x)
+ else
+ fun_l27_n729(x)
+ end
+end
+
+def fun_l26_n418(x)
+ if (x < 1)
+ fun_l27_n153(x)
+ else
+ fun_l27_n220(x)
+ end
+end
+
+def fun_l26_n419(x)
+ if (x < 1)
+ fun_l27_n636(x)
+ else
+ fun_l27_n492(x)
+ end
+end
+
+def fun_l26_n420(x)
+ if (x < 1)
+ fun_l27_n692(x)
+ else
+ fun_l27_n7(x)
+ end
+end
+
+def fun_l26_n421(x)
+ if (x < 1)
+ fun_l27_n303(x)
+ else
+ fun_l27_n396(x)
+ end
+end
+
+def fun_l26_n422(x)
+ if (x < 1)
+ fun_l27_n937(x)
+ else
+ fun_l27_n940(x)
+ end
+end
+
+def fun_l26_n423(x)
+ if (x < 1)
+ fun_l27_n581(x)
+ else
+ fun_l27_n355(x)
+ end
+end
+
+def fun_l26_n424(x)
+ if (x < 1)
+ fun_l27_n743(x)
+ else
+ fun_l27_n636(x)
+ end
+end
+
+def fun_l26_n425(x)
+ if (x < 1)
+ fun_l27_n385(x)
+ else
+ fun_l27_n573(x)
+ end
+end
+
+def fun_l26_n426(x)
+ if (x < 1)
+ fun_l27_n595(x)
+ else
+ fun_l27_n873(x)
+ end
+end
+
+def fun_l26_n427(x)
+ if (x < 1)
+ fun_l27_n700(x)
+ else
+ fun_l27_n541(x)
+ end
+end
+
+def fun_l26_n428(x)
+ if (x < 1)
+ fun_l27_n445(x)
+ else
+ fun_l27_n239(x)
+ end
+end
+
+def fun_l26_n429(x)
+ if (x < 1)
+ fun_l27_n500(x)
+ else
+ fun_l27_n7(x)
+ end
+end
+
+def fun_l26_n430(x)
+ if (x < 1)
+ fun_l27_n615(x)
+ else
+ fun_l27_n383(x)
+ end
+end
+
+def fun_l26_n431(x)
+ if (x < 1)
+ fun_l27_n962(x)
+ else
+ fun_l27_n424(x)
+ end
+end
+
+def fun_l26_n432(x)
+ if (x < 1)
+ fun_l27_n289(x)
+ else
+ fun_l27_n142(x)
+ end
+end
+
+def fun_l26_n433(x)
+ if (x < 1)
+ fun_l27_n527(x)
+ else
+ fun_l27_n112(x)
+ end
+end
+
+def fun_l26_n434(x)
+ if (x < 1)
+ fun_l27_n884(x)
+ else
+ fun_l27_n509(x)
+ end
+end
+
+def fun_l26_n435(x)
+ if (x < 1)
+ fun_l27_n65(x)
+ else
+ fun_l27_n431(x)
+ end
+end
+
+def fun_l26_n436(x)
+ if (x < 1)
+ fun_l27_n324(x)
+ else
+ fun_l27_n885(x)
+ end
+end
+
+def fun_l26_n437(x)
+ if (x < 1)
+ fun_l27_n826(x)
+ else
+ fun_l27_n372(x)
+ end
+end
+
+def fun_l26_n438(x)
+ if (x < 1)
+ fun_l27_n291(x)
+ else
+ fun_l27_n793(x)
+ end
+end
+
+def fun_l26_n439(x)
+ if (x < 1)
+ fun_l27_n677(x)
+ else
+ fun_l27_n31(x)
+ end
+end
+
+def fun_l26_n440(x)
+ if (x < 1)
+ fun_l27_n948(x)
+ else
+ fun_l27_n320(x)
+ end
+end
+
+def fun_l26_n441(x)
+ if (x < 1)
+ fun_l27_n951(x)
+ else
+ fun_l27_n504(x)
+ end
+end
+
+def fun_l26_n442(x)
+ if (x < 1)
+ fun_l27_n388(x)
+ else
+ fun_l27_n1(x)
+ end
+end
+
+def fun_l26_n443(x)
+ if (x < 1)
+ fun_l27_n92(x)
+ else
+ fun_l27_n570(x)
+ end
+end
+
+def fun_l26_n444(x)
+ if (x < 1)
+ fun_l27_n956(x)
+ else
+ fun_l27_n120(x)
+ end
+end
+
+def fun_l26_n445(x)
+ if (x < 1)
+ fun_l27_n985(x)
+ else
+ fun_l27_n233(x)
+ end
+end
+
+def fun_l26_n446(x)
+ if (x < 1)
+ fun_l27_n153(x)
+ else
+ fun_l27_n590(x)
+ end
+end
+
+def fun_l26_n447(x)
+ if (x < 1)
+ fun_l27_n793(x)
+ else
+ fun_l27_n675(x)
+ end
+end
+
+def fun_l26_n448(x)
+ if (x < 1)
+ fun_l27_n351(x)
+ else
+ fun_l27_n781(x)
+ end
+end
+
+def fun_l26_n449(x)
+ if (x < 1)
+ fun_l27_n137(x)
+ else
+ fun_l27_n147(x)
+ end
+end
+
+def fun_l26_n450(x)
+ if (x < 1)
+ fun_l27_n138(x)
+ else
+ fun_l27_n636(x)
+ end
+end
+
+def fun_l26_n451(x)
+ if (x < 1)
+ fun_l27_n154(x)
+ else
+ fun_l27_n755(x)
+ end
+end
+
+def fun_l26_n452(x)
+ if (x < 1)
+ fun_l27_n665(x)
+ else
+ fun_l27_n65(x)
+ end
+end
+
+def fun_l26_n453(x)
+ if (x < 1)
+ fun_l27_n769(x)
+ else
+ fun_l27_n847(x)
+ end
+end
+
+def fun_l26_n454(x)
+ if (x < 1)
+ fun_l27_n959(x)
+ else
+ fun_l27_n731(x)
+ end
+end
+
+def fun_l26_n455(x)
+ if (x < 1)
+ fun_l27_n565(x)
+ else
+ fun_l27_n916(x)
+ end
+end
+
+def fun_l26_n456(x)
+ if (x < 1)
+ fun_l27_n421(x)
+ else
+ fun_l27_n57(x)
+ end
+end
+
+def fun_l26_n457(x)
+ if (x < 1)
+ fun_l27_n595(x)
+ else
+ fun_l27_n920(x)
+ end
+end
+
+def fun_l26_n458(x)
+ if (x < 1)
+ fun_l27_n660(x)
+ else
+ fun_l27_n835(x)
+ end
+end
+
+def fun_l26_n459(x)
+ if (x < 1)
+ fun_l27_n114(x)
+ else
+ fun_l27_n418(x)
+ end
+end
+
+def fun_l26_n460(x)
+ if (x < 1)
+ fun_l27_n744(x)
+ else
+ fun_l27_n674(x)
+ end
+end
+
+def fun_l26_n461(x)
+ if (x < 1)
+ fun_l27_n436(x)
+ else
+ fun_l27_n448(x)
+ end
+end
+
+def fun_l26_n462(x)
+ if (x < 1)
+ fun_l27_n796(x)
+ else
+ fun_l27_n960(x)
+ end
+end
+
+def fun_l26_n463(x)
+ if (x < 1)
+ fun_l27_n871(x)
+ else
+ fun_l27_n300(x)
+ end
+end
+
+def fun_l26_n464(x)
+ if (x < 1)
+ fun_l27_n942(x)
+ else
+ fun_l27_n625(x)
+ end
+end
+
+def fun_l26_n465(x)
+ if (x < 1)
+ fun_l27_n219(x)
+ else
+ fun_l27_n383(x)
+ end
+end
+
+def fun_l26_n466(x)
+ if (x < 1)
+ fun_l27_n440(x)
+ else
+ fun_l27_n177(x)
+ end
+end
+
+def fun_l26_n467(x)
+ if (x < 1)
+ fun_l27_n958(x)
+ else
+ fun_l27_n441(x)
+ end
+end
+
+def fun_l26_n468(x)
+ if (x < 1)
+ fun_l27_n899(x)
+ else
+ fun_l27_n613(x)
+ end
+end
+
+def fun_l26_n469(x)
+ if (x < 1)
+ fun_l27_n535(x)
+ else
+ fun_l27_n439(x)
+ end
+end
+
+def fun_l26_n470(x)
+ if (x < 1)
+ fun_l27_n18(x)
+ else
+ fun_l27_n716(x)
+ end
+end
+
+def fun_l26_n471(x)
+ if (x < 1)
+ fun_l27_n768(x)
+ else
+ fun_l27_n374(x)
+ end
+end
+
+def fun_l26_n472(x)
+ if (x < 1)
+ fun_l27_n537(x)
+ else
+ fun_l27_n434(x)
+ end
+end
+
+def fun_l26_n473(x)
+ if (x < 1)
+ fun_l27_n632(x)
+ else
+ fun_l27_n733(x)
+ end
+end
+
+def fun_l26_n474(x)
+ if (x < 1)
+ fun_l27_n347(x)
+ else
+ fun_l27_n562(x)
+ end
+end
+
+def fun_l26_n475(x)
+ if (x < 1)
+ fun_l27_n741(x)
+ else
+ fun_l27_n684(x)
+ end
+end
+
+def fun_l26_n476(x)
+ if (x < 1)
+ fun_l27_n222(x)
+ else
+ fun_l27_n41(x)
+ end
+end
+
+def fun_l26_n477(x)
+ if (x < 1)
+ fun_l27_n23(x)
+ else
+ fun_l27_n541(x)
+ end
+end
+
+def fun_l26_n478(x)
+ if (x < 1)
+ fun_l27_n588(x)
+ else
+ fun_l27_n394(x)
+ end
+end
+
+def fun_l26_n479(x)
+ if (x < 1)
+ fun_l27_n526(x)
+ else
+ fun_l27_n974(x)
+ end
+end
+
+def fun_l26_n480(x)
+ if (x < 1)
+ fun_l27_n845(x)
+ else
+ fun_l27_n528(x)
+ end
+end
+
+def fun_l26_n481(x)
+ if (x < 1)
+ fun_l27_n505(x)
+ else
+ fun_l27_n913(x)
+ end
+end
+
+def fun_l26_n482(x)
+ if (x < 1)
+ fun_l27_n100(x)
+ else
+ fun_l27_n233(x)
+ end
+end
+
+def fun_l26_n483(x)
+ if (x < 1)
+ fun_l27_n87(x)
+ else
+ fun_l27_n339(x)
+ end
+end
+
+def fun_l26_n484(x)
+ if (x < 1)
+ fun_l27_n744(x)
+ else
+ fun_l27_n404(x)
+ end
+end
+
+def fun_l26_n485(x)
+ if (x < 1)
+ fun_l27_n965(x)
+ else
+ fun_l27_n86(x)
+ end
+end
+
+def fun_l26_n486(x)
+ if (x < 1)
+ fun_l27_n826(x)
+ else
+ fun_l27_n25(x)
+ end
+end
+
+def fun_l26_n487(x)
+ if (x < 1)
+ fun_l27_n950(x)
+ else
+ fun_l27_n876(x)
+ end
+end
+
+def fun_l26_n488(x)
+ if (x < 1)
+ fun_l27_n964(x)
+ else
+ fun_l27_n60(x)
+ end
+end
+
+def fun_l26_n489(x)
+ if (x < 1)
+ fun_l27_n171(x)
+ else
+ fun_l27_n768(x)
+ end
+end
+
+def fun_l26_n490(x)
+ if (x < 1)
+ fun_l27_n391(x)
+ else
+ fun_l27_n308(x)
+ end
+end
+
+def fun_l26_n491(x)
+ if (x < 1)
+ fun_l27_n440(x)
+ else
+ fun_l27_n51(x)
+ end
+end
+
+def fun_l26_n492(x)
+ if (x < 1)
+ fun_l27_n403(x)
+ else
+ fun_l27_n956(x)
+ end
+end
+
+def fun_l26_n493(x)
+ if (x < 1)
+ fun_l27_n802(x)
+ else
+ fun_l27_n931(x)
+ end
+end
+
+def fun_l26_n494(x)
+ if (x < 1)
+ fun_l27_n7(x)
+ else
+ fun_l27_n291(x)
+ end
+end
+
+def fun_l26_n495(x)
+ if (x < 1)
+ fun_l27_n149(x)
+ else
+ fun_l27_n173(x)
+ end
+end
+
+def fun_l26_n496(x)
+ if (x < 1)
+ fun_l27_n864(x)
+ else
+ fun_l27_n488(x)
+ end
+end
+
+def fun_l26_n497(x)
+ if (x < 1)
+ fun_l27_n290(x)
+ else
+ fun_l27_n431(x)
+ end
+end
+
+def fun_l26_n498(x)
+ if (x < 1)
+ fun_l27_n269(x)
+ else
+ fun_l27_n622(x)
+ end
+end
+
+def fun_l26_n499(x)
+ if (x < 1)
+ fun_l27_n168(x)
+ else
+ fun_l27_n225(x)
+ end
+end
+
+def fun_l26_n500(x)
+ if (x < 1)
+ fun_l27_n512(x)
+ else
+ fun_l27_n363(x)
+ end
+end
+
+def fun_l26_n501(x)
+ if (x < 1)
+ fun_l27_n844(x)
+ else
+ fun_l27_n15(x)
+ end
+end
+
+def fun_l26_n502(x)
+ if (x < 1)
+ fun_l27_n242(x)
+ else
+ fun_l27_n479(x)
+ end
+end
+
+def fun_l26_n503(x)
+ if (x < 1)
+ fun_l27_n285(x)
+ else
+ fun_l27_n202(x)
+ end
+end
+
+def fun_l26_n504(x)
+ if (x < 1)
+ fun_l27_n64(x)
+ else
+ fun_l27_n223(x)
+ end
+end
+
+def fun_l26_n505(x)
+ if (x < 1)
+ fun_l27_n85(x)
+ else
+ fun_l27_n477(x)
+ end
+end
+
+def fun_l26_n506(x)
+ if (x < 1)
+ fun_l27_n360(x)
+ else
+ fun_l27_n406(x)
+ end
+end
+
+def fun_l26_n507(x)
+ if (x < 1)
+ fun_l27_n515(x)
+ else
+ fun_l27_n599(x)
+ end
+end
+
+def fun_l26_n508(x)
+ if (x < 1)
+ fun_l27_n848(x)
+ else
+ fun_l27_n832(x)
+ end
+end
+
+def fun_l26_n509(x)
+ if (x < 1)
+ fun_l27_n831(x)
+ else
+ fun_l27_n334(x)
+ end
+end
+
+def fun_l26_n510(x)
+ if (x < 1)
+ fun_l27_n53(x)
+ else
+ fun_l27_n937(x)
+ end
+end
+
+def fun_l26_n511(x)
+ if (x < 1)
+ fun_l27_n583(x)
+ else
+ fun_l27_n901(x)
+ end
+end
+
+def fun_l26_n512(x)
+ if (x < 1)
+ fun_l27_n394(x)
+ else
+ fun_l27_n135(x)
+ end
+end
+
+def fun_l26_n513(x)
+ if (x < 1)
+ fun_l27_n175(x)
+ else
+ fun_l27_n339(x)
+ end
+end
+
+def fun_l26_n514(x)
+ if (x < 1)
+ fun_l27_n200(x)
+ else
+ fun_l27_n124(x)
+ end
+end
+
+def fun_l26_n515(x)
+ if (x < 1)
+ fun_l27_n145(x)
+ else
+ fun_l27_n426(x)
+ end
+end
+
+def fun_l26_n516(x)
+ if (x < 1)
+ fun_l27_n803(x)
+ else
+ fun_l27_n466(x)
+ end
+end
+
+def fun_l26_n517(x)
+ if (x < 1)
+ fun_l27_n773(x)
+ else
+ fun_l27_n296(x)
+ end
+end
+
+def fun_l26_n518(x)
+ if (x < 1)
+ fun_l27_n957(x)
+ else
+ fun_l27_n373(x)
+ end
+end
+
+def fun_l26_n519(x)
+ if (x < 1)
+ fun_l27_n887(x)
+ else
+ fun_l27_n498(x)
+ end
+end
+
+def fun_l26_n520(x)
+ if (x < 1)
+ fun_l27_n629(x)
+ else
+ fun_l27_n477(x)
+ end
+end
+
+def fun_l26_n521(x)
+ if (x < 1)
+ fun_l27_n634(x)
+ else
+ fun_l27_n138(x)
+ end
+end
+
+def fun_l26_n522(x)
+ if (x < 1)
+ fun_l27_n942(x)
+ else
+ fun_l27_n853(x)
+ end
+end
+
+def fun_l26_n523(x)
+ if (x < 1)
+ fun_l27_n453(x)
+ else
+ fun_l27_n520(x)
+ end
+end
+
+def fun_l26_n524(x)
+ if (x < 1)
+ fun_l27_n125(x)
+ else
+ fun_l27_n922(x)
+ end
+end
+
+def fun_l26_n525(x)
+ if (x < 1)
+ fun_l27_n629(x)
+ else
+ fun_l27_n711(x)
+ end
+end
+
+def fun_l26_n526(x)
+ if (x < 1)
+ fun_l27_n243(x)
+ else
+ fun_l27_n374(x)
+ end
+end
+
+def fun_l26_n527(x)
+ if (x < 1)
+ fun_l27_n476(x)
+ else
+ fun_l27_n348(x)
+ end
+end
+
+def fun_l26_n528(x)
+ if (x < 1)
+ fun_l27_n532(x)
+ else
+ fun_l27_n156(x)
+ end
+end
+
+def fun_l26_n529(x)
+ if (x < 1)
+ fun_l27_n139(x)
+ else
+ fun_l27_n976(x)
+ end
+end
+
+def fun_l26_n530(x)
+ if (x < 1)
+ fun_l27_n323(x)
+ else
+ fun_l27_n48(x)
+ end
+end
+
+def fun_l26_n531(x)
+ if (x < 1)
+ fun_l27_n626(x)
+ else
+ fun_l27_n913(x)
+ end
+end
+
+def fun_l26_n532(x)
+ if (x < 1)
+ fun_l27_n98(x)
+ else
+ fun_l27_n369(x)
+ end
+end
+
+def fun_l26_n533(x)
+ if (x < 1)
+ fun_l27_n50(x)
+ else
+ fun_l27_n41(x)
+ end
+end
+
+def fun_l26_n534(x)
+ if (x < 1)
+ fun_l27_n163(x)
+ else
+ fun_l27_n722(x)
+ end
+end
+
+def fun_l26_n535(x)
+ if (x < 1)
+ fun_l27_n640(x)
+ else
+ fun_l27_n622(x)
+ end
+end
+
+def fun_l26_n536(x)
+ if (x < 1)
+ fun_l27_n98(x)
+ else
+ fun_l27_n970(x)
+ end
+end
+
+def fun_l26_n537(x)
+ if (x < 1)
+ fun_l27_n828(x)
+ else
+ fun_l27_n240(x)
+ end
+end
+
+def fun_l26_n538(x)
+ if (x < 1)
+ fun_l27_n303(x)
+ else
+ fun_l27_n116(x)
+ end
+end
+
+def fun_l26_n539(x)
+ if (x < 1)
+ fun_l27_n341(x)
+ else
+ fun_l27_n545(x)
+ end
+end
+
+def fun_l26_n540(x)
+ if (x < 1)
+ fun_l27_n476(x)
+ else
+ fun_l27_n943(x)
+ end
+end
+
+def fun_l26_n541(x)
+ if (x < 1)
+ fun_l27_n380(x)
+ else
+ fun_l27_n894(x)
+ end
+end
+
+def fun_l26_n542(x)
+ if (x < 1)
+ fun_l27_n330(x)
+ else
+ fun_l27_n96(x)
+ end
+end
+
+def fun_l26_n543(x)
+ if (x < 1)
+ fun_l27_n676(x)
+ else
+ fun_l27_n876(x)
+ end
+end
+
+def fun_l26_n544(x)
+ if (x < 1)
+ fun_l27_n396(x)
+ else
+ fun_l27_n116(x)
+ end
+end
+
+def fun_l26_n545(x)
+ if (x < 1)
+ fun_l27_n691(x)
+ else
+ fun_l27_n178(x)
+ end
+end
+
+def fun_l26_n546(x)
+ if (x < 1)
+ fun_l27_n118(x)
+ else
+ fun_l27_n956(x)
+ end
+end
+
+def fun_l26_n547(x)
+ if (x < 1)
+ fun_l27_n20(x)
+ else
+ fun_l27_n777(x)
+ end
+end
+
+def fun_l26_n548(x)
+ if (x < 1)
+ fun_l27_n522(x)
+ else
+ fun_l27_n808(x)
+ end
+end
+
+def fun_l26_n549(x)
+ if (x < 1)
+ fun_l27_n624(x)
+ else
+ fun_l27_n54(x)
+ end
+end
+
+def fun_l26_n550(x)
+ if (x < 1)
+ fun_l27_n364(x)
+ else
+ fun_l27_n243(x)
+ end
+end
+
+def fun_l26_n551(x)
+ if (x < 1)
+ fun_l27_n283(x)
+ else
+ fun_l27_n913(x)
+ end
+end
+
+def fun_l26_n552(x)
+ if (x < 1)
+ fun_l27_n101(x)
+ else
+ fun_l27_n136(x)
+ end
+end
+
+def fun_l26_n553(x)
+ if (x < 1)
+ fun_l27_n965(x)
+ else
+ fun_l27_n453(x)
+ end
+end
+
+def fun_l26_n554(x)
+ if (x < 1)
+ fun_l27_n807(x)
+ else
+ fun_l27_n442(x)
+ end
+end
+
+def fun_l26_n555(x)
+ if (x < 1)
+ fun_l27_n987(x)
+ else
+ fun_l27_n883(x)
+ end
+end
+
+def fun_l26_n556(x)
+ if (x < 1)
+ fun_l27_n475(x)
+ else
+ fun_l27_n439(x)
+ end
+end
+
+def fun_l26_n557(x)
+ if (x < 1)
+ fun_l27_n580(x)
+ else
+ fun_l27_n301(x)
+ end
+end
+
+def fun_l26_n558(x)
+ if (x < 1)
+ fun_l27_n91(x)
+ else
+ fun_l27_n514(x)
+ end
+end
+
+def fun_l26_n559(x)
+ if (x < 1)
+ fun_l27_n395(x)
+ else
+ fun_l27_n583(x)
+ end
+end
+
+def fun_l26_n560(x)
+ if (x < 1)
+ fun_l27_n81(x)
+ else
+ fun_l27_n817(x)
+ end
+end
+
+def fun_l26_n561(x)
+ if (x < 1)
+ fun_l27_n816(x)
+ else
+ fun_l27_n423(x)
+ end
+end
+
+def fun_l26_n562(x)
+ if (x < 1)
+ fun_l27_n513(x)
+ else
+ fun_l27_n577(x)
+ end
+end
+
+def fun_l26_n563(x)
+ if (x < 1)
+ fun_l27_n864(x)
+ else
+ fun_l27_n249(x)
+ end
+end
+
+def fun_l26_n564(x)
+ if (x < 1)
+ fun_l27_n408(x)
+ else
+ fun_l27_n281(x)
+ end
+end
+
+def fun_l26_n565(x)
+ if (x < 1)
+ fun_l27_n963(x)
+ else
+ fun_l27_n736(x)
+ end
+end
+
+def fun_l26_n566(x)
+ if (x < 1)
+ fun_l27_n366(x)
+ else
+ fun_l27_n774(x)
+ end
+end
+
+def fun_l26_n567(x)
+ if (x < 1)
+ fun_l27_n239(x)
+ else
+ fun_l27_n473(x)
+ end
+end
+
+def fun_l26_n568(x)
+ if (x < 1)
+ fun_l27_n272(x)
+ else
+ fun_l27_n790(x)
+ end
+end
+
+def fun_l26_n569(x)
+ if (x < 1)
+ fun_l27_n225(x)
+ else
+ fun_l27_n970(x)
+ end
+end
+
+def fun_l26_n570(x)
+ if (x < 1)
+ fun_l27_n631(x)
+ else
+ fun_l27_n988(x)
+ end
+end
+
+def fun_l26_n571(x)
+ if (x < 1)
+ fun_l27_n224(x)
+ else
+ fun_l27_n286(x)
+ end
+end
+
+def fun_l26_n572(x)
+ if (x < 1)
+ fun_l27_n141(x)
+ else
+ fun_l27_n573(x)
+ end
+end
+
+def fun_l26_n573(x)
+ if (x < 1)
+ fun_l27_n493(x)
+ else
+ fun_l27_n288(x)
+ end
+end
+
+def fun_l26_n574(x)
+ if (x < 1)
+ fun_l27_n573(x)
+ else
+ fun_l27_n88(x)
+ end
+end
+
+def fun_l26_n575(x)
+ if (x < 1)
+ fun_l27_n174(x)
+ else
+ fun_l27_n635(x)
+ end
+end
+
+def fun_l26_n576(x)
+ if (x < 1)
+ fun_l27_n146(x)
+ else
+ fun_l27_n48(x)
+ end
+end
+
+def fun_l26_n577(x)
+ if (x < 1)
+ fun_l27_n344(x)
+ else
+ fun_l27_n668(x)
+ end
+end
+
+def fun_l26_n578(x)
+ if (x < 1)
+ fun_l27_n624(x)
+ else
+ fun_l27_n516(x)
+ end
+end
+
+def fun_l26_n579(x)
+ if (x < 1)
+ fun_l27_n349(x)
+ else
+ fun_l27_n510(x)
+ end
+end
+
+def fun_l26_n580(x)
+ if (x < 1)
+ fun_l27_n625(x)
+ else
+ fun_l27_n474(x)
+ end
+end
+
+def fun_l26_n581(x)
+ if (x < 1)
+ fun_l27_n473(x)
+ else
+ fun_l27_n785(x)
+ end
+end
+
+def fun_l26_n582(x)
+ if (x < 1)
+ fun_l27_n246(x)
+ else
+ fun_l27_n803(x)
+ end
+end
+
+def fun_l26_n583(x)
+ if (x < 1)
+ fun_l27_n232(x)
+ else
+ fun_l27_n981(x)
+ end
+end
+
+def fun_l26_n584(x)
+ if (x < 1)
+ fun_l27_n825(x)
+ else
+ fun_l27_n65(x)
+ end
+end
+
+def fun_l26_n585(x)
+ if (x < 1)
+ fun_l27_n258(x)
+ else
+ fun_l27_n700(x)
+ end
+end
+
+def fun_l26_n586(x)
+ if (x < 1)
+ fun_l27_n404(x)
+ else
+ fun_l27_n124(x)
+ end
+end
+
+def fun_l26_n587(x)
+ if (x < 1)
+ fun_l27_n390(x)
+ else
+ fun_l27_n812(x)
+ end
+end
+
+def fun_l26_n588(x)
+ if (x < 1)
+ fun_l27_n874(x)
+ else
+ fun_l27_n249(x)
+ end
+end
+
+def fun_l26_n589(x)
+ if (x < 1)
+ fun_l27_n837(x)
+ else
+ fun_l27_n480(x)
+ end
+end
+
+def fun_l26_n590(x)
+ if (x < 1)
+ fun_l27_n126(x)
+ else
+ fun_l27_n446(x)
+ end
+end
+
+def fun_l26_n591(x)
+ if (x < 1)
+ fun_l27_n838(x)
+ else
+ fun_l27_n285(x)
+ end
+end
+
+def fun_l26_n592(x)
+ if (x < 1)
+ fun_l27_n364(x)
+ else
+ fun_l27_n821(x)
+ end
+end
+
+def fun_l26_n593(x)
+ if (x < 1)
+ fun_l27_n781(x)
+ else
+ fun_l27_n310(x)
+ end
+end
+
+def fun_l26_n594(x)
+ if (x < 1)
+ fun_l27_n343(x)
+ else
+ fun_l27_n853(x)
+ end
+end
+
+def fun_l26_n595(x)
+ if (x < 1)
+ fun_l27_n216(x)
+ else
+ fun_l27_n334(x)
+ end
+end
+
+def fun_l26_n596(x)
+ if (x < 1)
+ fun_l27_n866(x)
+ else
+ fun_l27_n981(x)
+ end
+end
+
+def fun_l26_n597(x)
+ if (x < 1)
+ fun_l27_n551(x)
+ else
+ fun_l27_n184(x)
+ end
+end
+
+def fun_l26_n598(x)
+ if (x < 1)
+ fun_l27_n538(x)
+ else
+ fun_l27_n878(x)
+ end
+end
+
+def fun_l26_n599(x)
+ if (x < 1)
+ fun_l27_n909(x)
+ else
+ fun_l27_n435(x)
+ end
+end
+
+def fun_l26_n600(x)
+ if (x < 1)
+ fun_l27_n695(x)
+ else
+ fun_l27_n886(x)
+ end
+end
+
+def fun_l26_n601(x)
+ if (x < 1)
+ fun_l27_n927(x)
+ else
+ fun_l27_n303(x)
+ end
+end
+
+def fun_l26_n602(x)
+ if (x < 1)
+ fun_l27_n323(x)
+ else
+ fun_l27_n534(x)
+ end
+end
+
+def fun_l26_n603(x)
+ if (x < 1)
+ fun_l27_n803(x)
+ else
+ fun_l27_n34(x)
+ end
+end
+
+def fun_l26_n604(x)
+ if (x < 1)
+ fun_l27_n266(x)
+ else
+ fun_l27_n800(x)
+ end
+end
+
+def fun_l26_n605(x)
+ if (x < 1)
+ fun_l27_n831(x)
+ else
+ fun_l27_n338(x)
+ end
+end
+
+def fun_l26_n606(x)
+ if (x < 1)
+ fun_l27_n97(x)
+ else
+ fun_l27_n772(x)
+ end
+end
+
+def fun_l26_n607(x)
+ if (x < 1)
+ fun_l27_n291(x)
+ else
+ fun_l27_n756(x)
+ end
+end
+
+def fun_l26_n608(x)
+ if (x < 1)
+ fun_l27_n906(x)
+ else
+ fun_l27_n861(x)
+ end
+end
+
+def fun_l26_n609(x)
+ if (x < 1)
+ fun_l27_n793(x)
+ else
+ fun_l27_n845(x)
+ end
+end
+
+def fun_l26_n610(x)
+ if (x < 1)
+ fun_l27_n83(x)
+ else
+ fun_l27_n359(x)
+ end
+end
+
+def fun_l26_n611(x)
+ if (x < 1)
+ fun_l27_n911(x)
+ else
+ fun_l27_n526(x)
+ end
+end
+
+def fun_l26_n612(x)
+ if (x < 1)
+ fun_l27_n377(x)
+ else
+ fun_l27_n387(x)
+ end
+end
+
+def fun_l26_n613(x)
+ if (x < 1)
+ fun_l27_n809(x)
+ else
+ fun_l27_n802(x)
+ end
+end
+
+def fun_l26_n614(x)
+ if (x < 1)
+ fun_l27_n984(x)
+ else
+ fun_l27_n683(x)
+ end
+end
+
+def fun_l26_n615(x)
+ if (x < 1)
+ fun_l27_n330(x)
+ else
+ fun_l27_n439(x)
+ end
+end
+
+def fun_l26_n616(x)
+ if (x < 1)
+ fun_l27_n16(x)
+ else
+ fun_l27_n831(x)
+ end
+end
+
+def fun_l26_n617(x)
+ if (x < 1)
+ fun_l27_n149(x)
+ else
+ fun_l27_n934(x)
+ end
+end
+
+def fun_l26_n618(x)
+ if (x < 1)
+ fun_l27_n383(x)
+ else
+ fun_l27_n439(x)
+ end
+end
+
+def fun_l26_n619(x)
+ if (x < 1)
+ fun_l27_n599(x)
+ else
+ fun_l27_n855(x)
+ end
+end
+
+def fun_l26_n620(x)
+ if (x < 1)
+ fun_l27_n202(x)
+ else
+ fun_l27_n902(x)
+ end
+end
+
+def fun_l26_n621(x)
+ if (x < 1)
+ fun_l27_n219(x)
+ else
+ fun_l27_n13(x)
+ end
+end
+
+def fun_l26_n622(x)
+ if (x < 1)
+ fun_l27_n473(x)
+ else
+ fun_l27_n12(x)
+ end
+end
+
+def fun_l26_n623(x)
+ if (x < 1)
+ fun_l27_n918(x)
+ else
+ fun_l27_n50(x)
+ end
+end
+
+def fun_l26_n624(x)
+ if (x < 1)
+ fun_l27_n585(x)
+ else
+ fun_l27_n902(x)
+ end
+end
+
+def fun_l26_n625(x)
+ if (x < 1)
+ fun_l27_n676(x)
+ else
+ fun_l27_n533(x)
+ end
+end
+
+def fun_l26_n626(x)
+ if (x < 1)
+ fun_l27_n122(x)
+ else
+ fun_l27_n823(x)
+ end
+end
+
+def fun_l26_n627(x)
+ if (x < 1)
+ fun_l27_n214(x)
+ else
+ fun_l27_n485(x)
+ end
+end
+
+def fun_l26_n628(x)
+ if (x < 1)
+ fun_l27_n453(x)
+ else
+ fun_l27_n312(x)
+ end
+end
+
+def fun_l26_n629(x)
+ if (x < 1)
+ fun_l27_n929(x)
+ else
+ fun_l27_n272(x)
+ end
+end
+
+def fun_l26_n630(x)
+ if (x < 1)
+ fun_l27_n546(x)
+ else
+ fun_l27_n950(x)
+ end
+end
+
+def fun_l26_n631(x)
+ if (x < 1)
+ fun_l27_n222(x)
+ else
+ fun_l27_n780(x)
+ end
+end
+
+def fun_l26_n632(x)
+ if (x < 1)
+ fun_l27_n878(x)
+ else
+ fun_l27_n721(x)
+ end
+end
+
+def fun_l26_n633(x)
+ if (x < 1)
+ fun_l27_n611(x)
+ else
+ fun_l27_n15(x)
+ end
+end
+
+def fun_l26_n634(x)
+ if (x < 1)
+ fun_l27_n728(x)
+ else
+ fun_l27_n848(x)
+ end
+end
+
+def fun_l26_n635(x)
+ if (x < 1)
+ fun_l27_n489(x)
+ else
+ fun_l27_n3(x)
+ end
+end
+
+def fun_l26_n636(x)
+ if (x < 1)
+ fun_l27_n138(x)
+ else
+ fun_l27_n231(x)
+ end
+end
+
+def fun_l26_n637(x)
+ if (x < 1)
+ fun_l27_n861(x)
+ else
+ fun_l27_n115(x)
+ end
+end
+
+def fun_l26_n638(x)
+ if (x < 1)
+ fun_l27_n7(x)
+ else
+ fun_l27_n894(x)
+ end
+end
+
+def fun_l26_n639(x)
+ if (x < 1)
+ fun_l27_n683(x)
+ else
+ fun_l27_n964(x)
+ end
+end
+
+def fun_l26_n640(x)
+ if (x < 1)
+ fun_l27_n100(x)
+ else
+ fun_l27_n40(x)
+ end
+end
+
+def fun_l26_n641(x)
+ if (x < 1)
+ fun_l27_n744(x)
+ else
+ fun_l27_n855(x)
+ end
+end
+
+def fun_l26_n642(x)
+ if (x < 1)
+ fun_l27_n923(x)
+ else
+ fun_l27_n664(x)
+ end
+end
+
+def fun_l26_n643(x)
+ if (x < 1)
+ fun_l27_n150(x)
+ else
+ fun_l27_n713(x)
+ end
+end
+
+def fun_l26_n644(x)
+ if (x < 1)
+ fun_l27_n95(x)
+ else
+ fun_l27_n566(x)
+ end
+end
+
+def fun_l26_n645(x)
+ if (x < 1)
+ fun_l27_n886(x)
+ else
+ fun_l27_n811(x)
+ end
+end
+
+def fun_l26_n646(x)
+ if (x < 1)
+ fun_l27_n547(x)
+ else
+ fun_l27_n412(x)
+ end
+end
+
+def fun_l26_n647(x)
+ if (x < 1)
+ fun_l27_n570(x)
+ else
+ fun_l27_n606(x)
+ end
+end
+
+def fun_l26_n648(x)
+ if (x < 1)
+ fun_l27_n181(x)
+ else
+ fun_l27_n216(x)
+ end
+end
+
+def fun_l26_n649(x)
+ if (x < 1)
+ fun_l27_n198(x)
+ else
+ fun_l27_n988(x)
+ end
+end
+
+def fun_l26_n650(x)
+ if (x < 1)
+ fun_l27_n503(x)
+ else
+ fun_l27_n257(x)
+ end
+end
+
+def fun_l26_n651(x)
+ if (x < 1)
+ fun_l27_n799(x)
+ else
+ fun_l27_n175(x)
+ end
+end
+
+def fun_l26_n652(x)
+ if (x < 1)
+ fun_l27_n338(x)
+ else
+ fun_l27_n560(x)
+ end
+end
+
+def fun_l26_n653(x)
+ if (x < 1)
+ fun_l27_n597(x)
+ else
+ fun_l27_n988(x)
+ end
+end
+
+def fun_l26_n654(x)
+ if (x < 1)
+ fun_l27_n319(x)
+ else
+ fun_l27_n299(x)
+ end
+end
+
+def fun_l26_n655(x)
+ if (x < 1)
+ fun_l27_n510(x)
+ else
+ fun_l27_n375(x)
+ end
+end
+
+def fun_l26_n656(x)
+ if (x < 1)
+ fun_l27_n808(x)
+ else
+ fun_l27_n289(x)
+ end
+end
+
+def fun_l26_n657(x)
+ if (x < 1)
+ fun_l27_n170(x)
+ else
+ fun_l27_n64(x)
+ end
+end
+
+def fun_l26_n658(x)
+ if (x < 1)
+ fun_l27_n966(x)
+ else
+ fun_l27_n487(x)
+ end
+end
+
+def fun_l26_n659(x)
+ if (x < 1)
+ fun_l27_n238(x)
+ else
+ fun_l27_n638(x)
+ end
+end
+
+def fun_l26_n660(x)
+ if (x < 1)
+ fun_l27_n814(x)
+ else
+ fun_l27_n203(x)
+ end
+end
+
+def fun_l26_n661(x)
+ if (x < 1)
+ fun_l27_n840(x)
+ else
+ fun_l27_n867(x)
+ end
+end
+
+def fun_l26_n662(x)
+ if (x < 1)
+ fun_l27_n753(x)
+ else
+ fun_l27_n543(x)
+ end
+end
+
+def fun_l26_n663(x)
+ if (x < 1)
+ fun_l27_n850(x)
+ else
+ fun_l27_n539(x)
+ end
+end
+
+def fun_l26_n664(x)
+ if (x < 1)
+ fun_l27_n878(x)
+ else
+ fun_l27_n648(x)
+ end
+end
+
+def fun_l26_n665(x)
+ if (x < 1)
+ fun_l27_n256(x)
+ else
+ fun_l27_n243(x)
+ end
+end
+
+def fun_l26_n666(x)
+ if (x < 1)
+ fun_l27_n833(x)
+ else
+ fun_l27_n251(x)
+ end
+end
+
+def fun_l26_n667(x)
+ if (x < 1)
+ fun_l27_n26(x)
+ else
+ fun_l27_n206(x)
+ end
+end
+
+def fun_l26_n668(x)
+ if (x < 1)
+ fun_l27_n860(x)
+ else
+ fun_l27_n736(x)
+ end
+end
+
+def fun_l26_n669(x)
+ if (x < 1)
+ fun_l27_n794(x)
+ else
+ fun_l27_n185(x)
+ end
+end
+
+def fun_l26_n670(x)
+ if (x < 1)
+ fun_l27_n849(x)
+ else
+ fun_l27_n218(x)
+ end
+end
+
+def fun_l26_n671(x)
+ if (x < 1)
+ fun_l27_n423(x)
+ else
+ fun_l27_n163(x)
+ end
+end
+
+def fun_l26_n672(x)
+ if (x < 1)
+ fun_l27_n94(x)
+ else
+ fun_l27_n341(x)
+ end
+end
+
+def fun_l26_n673(x)
+ if (x < 1)
+ fun_l27_n927(x)
+ else
+ fun_l27_n721(x)
+ end
+end
+
+def fun_l26_n674(x)
+ if (x < 1)
+ fun_l27_n390(x)
+ else
+ fun_l27_n807(x)
+ end
+end
+
+def fun_l26_n675(x)
+ if (x < 1)
+ fun_l27_n818(x)
+ else
+ fun_l27_n532(x)
+ end
+end
+
+def fun_l26_n676(x)
+ if (x < 1)
+ fun_l27_n513(x)
+ else
+ fun_l27_n414(x)
+ end
+end
+
+def fun_l26_n677(x)
+ if (x < 1)
+ fun_l27_n364(x)
+ else
+ fun_l27_n940(x)
+ end
+end
+
+def fun_l26_n678(x)
+ if (x < 1)
+ fun_l27_n178(x)
+ else
+ fun_l27_n857(x)
+ end
+end
+
+def fun_l26_n679(x)
+ if (x < 1)
+ fun_l27_n806(x)
+ else
+ fun_l27_n838(x)
+ end
+end
+
+def fun_l26_n680(x)
+ if (x < 1)
+ fun_l27_n216(x)
+ else
+ fun_l27_n774(x)
+ end
+end
+
+def fun_l26_n681(x)
+ if (x < 1)
+ fun_l27_n969(x)
+ else
+ fun_l27_n247(x)
+ end
+end
+
+def fun_l26_n682(x)
+ if (x < 1)
+ fun_l27_n175(x)
+ else
+ fun_l27_n588(x)
+ end
+end
+
+def fun_l26_n683(x)
+ if (x < 1)
+ fun_l27_n310(x)
+ else
+ fun_l27_n48(x)
+ end
+end
+
+def fun_l26_n684(x)
+ if (x < 1)
+ fun_l27_n669(x)
+ else
+ fun_l27_n428(x)
+ end
+end
+
+def fun_l26_n685(x)
+ if (x < 1)
+ fun_l27_n592(x)
+ else
+ fun_l27_n535(x)
+ end
+end
+
+def fun_l26_n686(x)
+ if (x < 1)
+ fun_l27_n81(x)
+ else
+ fun_l27_n259(x)
+ end
+end
+
+def fun_l26_n687(x)
+ if (x < 1)
+ fun_l27_n498(x)
+ else
+ fun_l27_n859(x)
+ end
+end
+
+def fun_l26_n688(x)
+ if (x < 1)
+ fun_l27_n695(x)
+ else
+ fun_l27_n67(x)
+ end
+end
+
+def fun_l26_n689(x)
+ if (x < 1)
+ fun_l27_n97(x)
+ else
+ fun_l27_n11(x)
+ end
+end
+
+def fun_l26_n690(x)
+ if (x < 1)
+ fun_l27_n901(x)
+ else
+ fun_l27_n525(x)
+ end
+end
+
+def fun_l26_n691(x)
+ if (x < 1)
+ fun_l27_n545(x)
+ else
+ fun_l27_n649(x)
+ end
+end
+
+def fun_l26_n692(x)
+ if (x < 1)
+ fun_l27_n866(x)
+ else
+ fun_l27_n379(x)
+ end
+end
+
+def fun_l26_n693(x)
+ if (x < 1)
+ fun_l27_n475(x)
+ else
+ fun_l27_n504(x)
+ end
+end
+
+def fun_l26_n694(x)
+ if (x < 1)
+ fun_l27_n527(x)
+ else
+ fun_l27_n701(x)
+ end
+end
+
+def fun_l26_n695(x)
+ if (x < 1)
+ fun_l27_n159(x)
+ else
+ fun_l27_n946(x)
+ end
+end
+
+def fun_l26_n696(x)
+ if (x < 1)
+ fun_l27_n850(x)
+ else
+ fun_l27_n200(x)
+ end
+end
+
+def fun_l26_n697(x)
+ if (x < 1)
+ fun_l27_n318(x)
+ else
+ fun_l27_n55(x)
+ end
+end
+
+def fun_l26_n698(x)
+ if (x < 1)
+ fun_l27_n563(x)
+ else
+ fun_l27_n413(x)
+ end
+end
+
+def fun_l26_n699(x)
+ if (x < 1)
+ fun_l27_n976(x)
+ else
+ fun_l27_n42(x)
+ end
+end
+
+def fun_l26_n700(x)
+ if (x < 1)
+ fun_l27_n112(x)
+ else
+ fun_l27_n764(x)
+ end
+end
+
+def fun_l26_n701(x)
+ if (x < 1)
+ fun_l27_n519(x)
+ else
+ fun_l27_n800(x)
+ end
+end
+
+def fun_l26_n702(x)
+ if (x < 1)
+ fun_l27_n701(x)
+ else
+ fun_l27_n102(x)
+ end
+end
+
+def fun_l26_n703(x)
+ if (x < 1)
+ fun_l27_n200(x)
+ else
+ fun_l27_n685(x)
+ end
+end
+
+def fun_l26_n704(x)
+ if (x < 1)
+ fun_l27_n770(x)
+ else
+ fun_l27_n47(x)
+ end
+end
+
+def fun_l26_n705(x)
+ if (x < 1)
+ fun_l27_n479(x)
+ else
+ fun_l27_n875(x)
+ end
+end
+
+def fun_l26_n706(x)
+ if (x < 1)
+ fun_l27_n369(x)
+ else
+ fun_l27_n53(x)
+ end
+end
+
+def fun_l26_n707(x)
+ if (x < 1)
+ fun_l27_n16(x)
+ else
+ fun_l27_n612(x)
+ end
+end
+
+def fun_l26_n708(x)
+ if (x < 1)
+ fun_l27_n235(x)
+ else
+ fun_l27_n211(x)
+ end
+end
+
+def fun_l26_n709(x)
+ if (x < 1)
+ fun_l27_n636(x)
+ else
+ fun_l27_n890(x)
+ end
+end
+
+def fun_l26_n710(x)
+ if (x < 1)
+ fun_l27_n877(x)
+ else
+ fun_l27_n301(x)
+ end
+end
+
+def fun_l26_n711(x)
+ if (x < 1)
+ fun_l27_n783(x)
+ else
+ fun_l27_n409(x)
+ end
+end
+
+def fun_l26_n712(x)
+ if (x < 1)
+ fun_l27_n595(x)
+ else
+ fun_l27_n968(x)
+ end
+end
+
+def fun_l26_n713(x)
+ if (x < 1)
+ fun_l27_n858(x)
+ else
+ fun_l27_n879(x)
+ end
+end
+
+def fun_l26_n714(x)
+ if (x < 1)
+ fun_l27_n66(x)
+ else
+ fun_l27_n107(x)
+ end
+end
+
+def fun_l26_n715(x)
+ if (x < 1)
+ fun_l27_n636(x)
+ else
+ fun_l27_n912(x)
+ end
+end
+
+def fun_l26_n716(x)
+ if (x < 1)
+ fun_l27_n605(x)
+ else
+ fun_l27_n935(x)
+ end
+end
+
+def fun_l26_n717(x)
+ if (x < 1)
+ fun_l27_n186(x)
+ else
+ fun_l27_n664(x)
+ end
+end
+
+def fun_l26_n718(x)
+ if (x < 1)
+ fun_l27_n865(x)
+ else
+ fun_l27_n462(x)
+ end
+end
+
+def fun_l26_n719(x)
+ if (x < 1)
+ fun_l27_n783(x)
+ else
+ fun_l27_n668(x)
+ end
+end
+
+def fun_l26_n720(x)
+ if (x < 1)
+ fun_l27_n697(x)
+ else
+ fun_l27_n850(x)
+ end
+end
+
+def fun_l26_n721(x)
+ if (x < 1)
+ fun_l27_n668(x)
+ else
+ fun_l27_n493(x)
+ end
+end
+
+def fun_l26_n722(x)
+ if (x < 1)
+ fun_l27_n25(x)
+ else
+ fun_l27_n473(x)
+ end
+end
+
+def fun_l26_n723(x)
+ if (x < 1)
+ fun_l27_n311(x)
+ else
+ fun_l27_n380(x)
+ end
+end
+
+def fun_l26_n724(x)
+ if (x < 1)
+ fun_l27_n766(x)
+ else
+ fun_l27_n303(x)
+ end
+end
+
+def fun_l26_n725(x)
+ if (x < 1)
+ fun_l27_n97(x)
+ else
+ fun_l27_n306(x)
+ end
+end
+
+def fun_l26_n726(x)
+ if (x < 1)
+ fun_l27_n333(x)
+ else
+ fun_l27_n590(x)
+ end
+end
+
+def fun_l26_n727(x)
+ if (x < 1)
+ fun_l27_n596(x)
+ else
+ fun_l27_n509(x)
+ end
+end
+
+def fun_l26_n728(x)
+ if (x < 1)
+ fun_l27_n234(x)
+ else
+ fun_l27_n583(x)
+ end
+end
+
+def fun_l26_n729(x)
+ if (x < 1)
+ fun_l27_n692(x)
+ else
+ fun_l27_n890(x)
+ end
+end
+
+def fun_l26_n730(x)
+ if (x < 1)
+ fun_l27_n864(x)
+ else
+ fun_l27_n433(x)
+ end
+end
+
+def fun_l26_n731(x)
+ if (x < 1)
+ fun_l27_n866(x)
+ else
+ fun_l27_n350(x)
+ end
+end
+
+def fun_l26_n732(x)
+ if (x < 1)
+ fun_l27_n913(x)
+ else
+ fun_l27_n651(x)
+ end
+end
+
+def fun_l26_n733(x)
+ if (x < 1)
+ fun_l27_n919(x)
+ else
+ fun_l27_n902(x)
+ end
+end
+
+def fun_l26_n734(x)
+ if (x < 1)
+ fun_l27_n731(x)
+ else
+ fun_l27_n768(x)
+ end
+end
+
+def fun_l26_n735(x)
+ if (x < 1)
+ fun_l27_n613(x)
+ else
+ fun_l27_n550(x)
+ end
+end
+
+def fun_l26_n736(x)
+ if (x < 1)
+ fun_l27_n795(x)
+ else
+ fun_l27_n152(x)
+ end
+end
+
+def fun_l26_n737(x)
+ if (x < 1)
+ fun_l27_n214(x)
+ else
+ fun_l27_n990(x)
+ end
+end
+
+def fun_l26_n738(x)
+ if (x < 1)
+ fun_l27_n521(x)
+ else
+ fun_l27_n773(x)
+ end
+end
+
+def fun_l26_n739(x)
+ if (x < 1)
+ fun_l27_n44(x)
+ else
+ fun_l27_n580(x)
+ end
+end
+
+def fun_l26_n740(x)
+ if (x < 1)
+ fun_l27_n800(x)
+ else
+ fun_l27_n385(x)
+ end
+end
+
+def fun_l26_n741(x)
+ if (x < 1)
+ fun_l27_n412(x)
+ else
+ fun_l27_n979(x)
+ end
+end
+
+def fun_l26_n742(x)
+ if (x < 1)
+ fun_l27_n392(x)
+ else
+ fun_l27_n627(x)
+ end
+end
+
+def fun_l26_n743(x)
+ if (x < 1)
+ fun_l27_n348(x)
+ else
+ fun_l27_n141(x)
+ end
+end
+
+def fun_l26_n744(x)
+ if (x < 1)
+ fun_l27_n199(x)
+ else
+ fun_l27_n327(x)
+ end
+end
+
+def fun_l26_n745(x)
+ if (x < 1)
+ fun_l27_n302(x)
+ else
+ fun_l27_n708(x)
+ end
+end
+
+def fun_l26_n746(x)
+ if (x < 1)
+ fun_l27_n431(x)
+ else
+ fun_l27_n362(x)
+ end
+end
+
+def fun_l26_n747(x)
+ if (x < 1)
+ fun_l27_n409(x)
+ else
+ fun_l27_n102(x)
+ end
+end
+
+def fun_l26_n748(x)
+ if (x < 1)
+ fun_l27_n631(x)
+ else
+ fun_l27_n415(x)
+ end
+end
+
+def fun_l26_n749(x)
+ if (x < 1)
+ fun_l27_n196(x)
+ else
+ fun_l27_n835(x)
+ end
+end
+
+def fun_l26_n750(x)
+ if (x < 1)
+ fun_l27_n731(x)
+ else
+ fun_l27_n400(x)
+ end
+end
+
+def fun_l26_n751(x)
+ if (x < 1)
+ fun_l27_n561(x)
+ else
+ fun_l27_n444(x)
+ end
+end
+
+def fun_l26_n752(x)
+ if (x < 1)
+ fun_l27_n444(x)
+ else
+ fun_l27_n245(x)
+ end
+end
+
+def fun_l26_n753(x)
+ if (x < 1)
+ fun_l27_n784(x)
+ else
+ fun_l27_n640(x)
+ end
+end
+
+def fun_l26_n754(x)
+ if (x < 1)
+ fun_l27_n988(x)
+ else
+ fun_l27_n335(x)
+ end
+end
+
+def fun_l26_n755(x)
+ if (x < 1)
+ fun_l27_n188(x)
+ else
+ fun_l27_n584(x)
+ end
+end
+
+def fun_l26_n756(x)
+ if (x < 1)
+ fun_l27_n356(x)
+ else
+ fun_l27_n989(x)
+ end
+end
+
+def fun_l26_n757(x)
+ if (x < 1)
+ fun_l27_n687(x)
+ else
+ fun_l27_n409(x)
+ end
+end
+
+def fun_l26_n758(x)
+ if (x < 1)
+ fun_l27_n383(x)
+ else
+ fun_l27_n502(x)
+ end
+end
+
+def fun_l26_n759(x)
+ if (x < 1)
+ fun_l27_n507(x)
+ else
+ fun_l27_n868(x)
+ end
+end
+
+def fun_l26_n760(x)
+ if (x < 1)
+ fun_l27_n109(x)
+ else
+ fun_l27_n641(x)
+ end
+end
+
+def fun_l26_n761(x)
+ if (x < 1)
+ fun_l27_n831(x)
+ else
+ fun_l27_n248(x)
+ end
+end
+
+def fun_l26_n762(x)
+ if (x < 1)
+ fun_l27_n150(x)
+ else
+ fun_l27_n116(x)
+ end
+end
+
+def fun_l26_n763(x)
+ if (x < 1)
+ fun_l27_n811(x)
+ else
+ fun_l27_n680(x)
+ end
+end
+
+def fun_l26_n764(x)
+ if (x < 1)
+ fun_l27_n593(x)
+ else
+ fun_l27_n756(x)
+ end
+end
+
+def fun_l26_n765(x)
+ if (x < 1)
+ fun_l27_n468(x)
+ else
+ fun_l27_n888(x)
+ end
+end
+
+def fun_l26_n766(x)
+ if (x < 1)
+ fun_l27_n154(x)
+ else
+ fun_l27_n65(x)
+ end
+end
+
+def fun_l26_n767(x)
+ if (x < 1)
+ fun_l27_n709(x)
+ else
+ fun_l27_n878(x)
+ end
+end
+
+def fun_l26_n768(x)
+ if (x < 1)
+ fun_l27_n270(x)
+ else
+ fun_l27_n393(x)
+ end
+end
+
+def fun_l26_n769(x)
+ if (x < 1)
+ fun_l27_n315(x)
+ else
+ fun_l27_n46(x)
+ end
+end
+
+def fun_l26_n770(x)
+ if (x < 1)
+ fun_l27_n448(x)
+ else
+ fun_l27_n364(x)
+ end
+end
+
+def fun_l26_n771(x)
+ if (x < 1)
+ fun_l27_n865(x)
+ else
+ fun_l27_n842(x)
+ end
+end
+
+def fun_l26_n772(x)
+ if (x < 1)
+ fun_l27_n231(x)
+ else
+ fun_l27_n731(x)
+ end
+end
+
+def fun_l26_n773(x)
+ if (x < 1)
+ fun_l27_n303(x)
+ else
+ fun_l27_n769(x)
+ end
+end
+
+def fun_l26_n774(x)
+ if (x < 1)
+ fun_l27_n257(x)
+ else
+ fun_l27_n513(x)
+ end
+end
+
+def fun_l26_n775(x)
+ if (x < 1)
+ fun_l27_n805(x)
+ else
+ fun_l27_n947(x)
+ end
+end
+
+def fun_l26_n776(x)
+ if (x < 1)
+ fun_l27_n199(x)
+ else
+ fun_l27_n413(x)
+ end
+end
+
+def fun_l26_n777(x)
+ if (x < 1)
+ fun_l27_n631(x)
+ else
+ fun_l27_n734(x)
+ end
+end
+
+def fun_l26_n778(x)
+ if (x < 1)
+ fun_l27_n978(x)
+ else
+ fun_l27_n638(x)
+ end
+end
+
+def fun_l26_n779(x)
+ if (x < 1)
+ fun_l27_n441(x)
+ else
+ fun_l27_n936(x)
+ end
+end
+
+def fun_l26_n780(x)
+ if (x < 1)
+ fun_l27_n120(x)
+ else
+ fun_l27_n37(x)
+ end
+end
+
+def fun_l26_n781(x)
+ if (x < 1)
+ fun_l27_n44(x)
+ else
+ fun_l27_n240(x)
+ end
+end
+
+def fun_l26_n782(x)
+ if (x < 1)
+ fun_l27_n920(x)
+ else
+ fun_l27_n54(x)
+ end
+end
+
+def fun_l26_n783(x)
+ if (x < 1)
+ fun_l27_n488(x)
+ else
+ fun_l27_n965(x)
+ end
+end
+
+def fun_l26_n784(x)
+ if (x < 1)
+ fun_l27_n226(x)
+ else
+ fun_l27_n449(x)
+ end
+end
+
+def fun_l26_n785(x)
+ if (x < 1)
+ fun_l27_n794(x)
+ else
+ fun_l27_n469(x)
+ end
+end
+
+def fun_l26_n786(x)
+ if (x < 1)
+ fun_l27_n287(x)
+ else
+ fun_l27_n863(x)
+ end
+end
+
+def fun_l26_n787(x)
+ if (x < 1)
+ fun_l27_n714(x)
+ else
+ fun_l27_n606(x)
+ end
+end
+
+def fun_l26_n788(x)
+ if (x < 1)
+ fun_l27_n649(x)
+ else
+ fun_l27_n347(x)
+ end
+end
+
+def fun_l26_n789(x)
+ if (x < 1)
+ fun_l27_n176(x)
+ else
+ fun_l27_n410(x)
+ end
+end
+
+def fun_l26_n790(x)
+ if (x < 1)
+ fun_l27_n688(x)
+ else
+ fun_l27_n248(x)
+ end
+end
+
+def fun_l26_n791(x)
+ if (x < 1)
+ fun_l27_n157(x)
+ else
+ fun_l27_n119(x)
+ end
+end
+
+def fun_l26_n792(x)
+ if (x < 1)
+ fun_l27_n470(x)
+ else
+ fun_l27_n657(x)
+ end
+end
+
+def fun_l26_n793(x)
+ if (x < 1)
+ fun_l27_n246(x)
+ else
+ fun_l27_n262(x)
+ end
+end
+
+def fun_l26_n794(x)
+ if (x < 1)
+ fun_l27_n142(x)
+ else
+ fun_l27_n524(x)
+ end
+end
+
+def fun_l26_n795(x)
+ if (x < 1)
+ fun_l27_n695(x)
+ else
+ fun_l27_n88(x)
+ end
+end
+
+def fun_l26_n796(x)
+ if (x < 1)
+ fun_l27_n599(x)
+ else
+ fun_l27_n776(x)
+ end
+end
+
+def fun_l26_n797(x)
+ if (x < 1)
+ fun_l27_n364(x)
+ else
+ fun_l27_n616(x)
+ end
+end
+
+def fun_l26_n798(x)
+ if (x < 1)
+ fun_l27_n793(x)
+ else
+ fun_l27_n416(x)
+ end
+end
+
+def fun_l26_n799(x)
+ if (x < 1)
+ fun_l27_n552(x)
+ else
+ fun_l27_n490(x)
+ end
+end
+
+def fun_l26_n800(x)
+ if (x < 1)
+ fun_l27_n691(x)
+ else
+ fun_l27_n743(x)
+ end
+end
+
+def fun_l26_n801(x)
+ if (x < 1)
+ fun_l27_n257(x)
+ else
+ fun_l27_n687(x)
+ end
+end
+
+def fun_l26_n802(x)
+ if (x < 1)
+ fun_l27_n877(x)
+ else
+ fun_l27_n273(x)
+ end
+end
+
+def fun_l26_n803(x)
+ if (x < 1)
+ fun_l27_n398(x)
+ else
+ fun_l27_n874(x)
+ end
+end
+
+def fun_l26_n804(x)
+ if (x < 1)
+ fun_l27_n114(x)
+ else
+ fun_l27_n96(x)
+ end
+end
+
+def fun_l26_n805(x)
+ if (x < 1)
+ fun_l27_n489(x)
+ else
+ fun_l27_n537(x)
+ end
+end
+
+def fun_l26_n806(x)
+ if (x < 1)
+ fun_l27_n619(x)
+ else
+ fun_l27_n813(x)
+ end
+end
+
+def fun_l26_n807(x)
+ if (x < 1)
+ fun_l27_n335(x)
+ else
+ fun_l27_n467(x)
+ end
+end
+
+def fun_l26_n808(x)
+ if (x < 1)
+ fun_l27_n17(x)
+ else
+ fun_l27_n133(x)
+ end
+end
+
+def fun_l26_n809(x)
+ if (x < 1)
+ fun_l27_n266(x)
+ else
+ fun_l27_n383(x)
+ end
+end
+
+def fun_l26_n810(x)
+ if (x < 1)
+ fun_l27_n391(x)
+ else
+ fun_l27_n326(x)
+ end
+end
+
+def fun_l26_n811(x)
+ if (x < 1)
+ fun_l27_n292(x)
+ else
+ fun_l27_n444(x)
+ end
+end
+
+def fun_l26_n812(x)
+ if (x < 1)
+ fun_l27_n920(x)
+ else
+ fun_l27_n909(x)
+ end
+end
+
+def fun_l26_n813(x)
+ if (x < 1)
+ fun_l27_n575(x)
+ else
+ fun_l27_n221(x)
+ end
+end
+
+def fun_l26_n814(x)
+ if (x < 1)
+ fun_l27_n66(x)
+ else
+ fun_l27_n241(x)
+ end
+end
+
+def fun_l26_n815(x)
+ if (x < 1)
+ fun_l27_n552(x)
+ else
+ fun_l27_n906(x)
+ end
+end
+
+def fun_l26_n816(x)
+ if (x < 1)
+ fun_l27_n301(x)
+ else
+ fun_l27_n656(x)
+ end
+end
+
+def fun_l26_n817(x)
+ if (x < 1)
+ fun_l27_n472(x)
+ else
+ fun_l27_n688(x)
+ end
+end
+
+def fun_l26_n818(x)
+ if (x < 1)
+ fun_l27_n712(x)
+ else
+ fun_l27_n830(x)
+ end
+end
+
+def fun_l26_n819(x)
+ if (x < 1)
+ fun_l27_n102(x)
+ else
+ fun_l27_n146(x)
+ end
+end
+
+def fun_l26_n820(x)
+ if (x < 1)
+ fun_l27_n448(x)
+ else
+ fun_l27_n207(x)
+ end
+end
+
+def fun_l26_n821(x)
+ if (x < 1)
+ fun_l27_n732(x)
+ else
+ fun_l27_n285(x)
+ end
+end
+
+def fun_l26_n822(x)
+ if (x < 1)
+ fun_l27_n973(x)
+ else
+ fun_l27_n395(x)
+ end
+end
+
+def fun_l26_n823(x)
+ if (x < 1)
+ fun_l27_n329(x)
+ else
+ fun_l27_n748(x)
+ end
+end
+
+def fun_l26_n824(x)
+ if (x < 1)
+ fun_l27_n280(x)
+ else
+ fun_l27_n676(x)
+ end
+end
+
+def fun_l26_n825(x)
+ if (x < 1)
+ fun_l27_n867(x)
+ else
+ fun_l27_n285(x)
+ end
+end
+
+def fun_l26_n826(x)
+ if (x < 1)
+ fun_l27_n380(x)
+ else
+ fun_l27_n720(x)
+ end
+end
+
+def fun_l26_n827(x)
+ if (x < 1)
+ fun_l27_n595(x)
+ else
+ fun_l27_n740(x)
+ end
+end
+
+def fun_l26_n828(x)
+ if (x < 1)
+ fun_l27_n356(x)
+ else
+ fun_l27_n878(x)
+ end
+end
+
+def fun_l26_n829(x)
+ if (x < 1)
+ fun_l27_n453(x)
+ else
+ fun_l27_n234(x)
+ end
+end
+
+def fun_l26_n830(x)
+ if (x < 1)
+ fun_l27_n775(x)
+ else
+ fun_l27_n13(x)
+ end
+end
+
+def fun_l26_n831(x)
+ if (x < 1)
+ fun_l27_n242(x)
+ else
+ fun_l27_n144(x)
+ end
+end
+
+def fun_l26_n832(x)
+ if (x < 1)
+ fun_l27_n734(x)
+ else
+ fun_l27_n432(x)
+ end
+end
+
+def fun_l26_n833(x)
+ if (x < 1)
+ fun_l27_n996(x)
+ else
+ fun_l27_n396(x)
+ end
+end
+
+def fun_l26_n834(x)
+ if (x < 1)
+ fun_l27_n367(x)
+ else
+ fun_l27_n991(x)
+ end
+end
+
+def fun_l26_n835(x)
+ if (x < 1)
+ fun_l27_n285(x)
+ else
+ fun_l27_n526(x)
+ end
+end
+
+def fun_l26_n836(x)
+ if (x < 1)
+ fun_l27_n945(x)
+ else
+ fun_l27_n418(x)
+ end
+end
+
+def fun_l26_n837(x)
+ if (x < 1)
+ fun_l27_n622(x)
+ else
+ fun_l27_n922(x)
+ end
+end
+
+def fun_l26_n838(x)
+ if (x < 1)
+ fun_l27_n997(x)
+ else
+ fun_l27_n786(x)
+ end
+end
+
+def fun_l26_n839(x)
+ if (x < 1)
+ fun_l27_n478(x)
+ else
+ fun_l27_n991(x)
+ end
+end
+
+def fun_l26_n840(x)
+ if (x < 1)
+ fun_l27_n473(x)
+ else
+ fun_l27_n801(x)
+ end
+end
+
+def fun_l26_n841(x)
+ if (x < 1)
+ fun_l27_n675(x)
+ else
+ fun_l27_n486(x)
+ end
+end
+
+def fun_l26_n842(x)
+ if (x < 1)
+ fun_l27_n170(x)
+ else
+ fun_l27_n27(x)
+ end
+end
+
+def fun_l26_n843(x)
+ if (x < 1)
+ fun_l27_n699(x)
+ else
+ fun_l27_n536(x)
+ end
+end
+
+def fun_l26_n844(x)
+ if (x < 1)
+ fun_l27_n388(x)
+ else
+ fun_l27_n431(x)
+ end
+end
+
+def fun_l26_n845(x)
+ if (x < 1)
+ fun_l27_n248(x)
+ else
+ fun_l27_n64(x)
+ end
+end
+
+def fun_l26_n846(x)
+ if (x < 1)
+ fun_l27_n64(x)
+ else
+ fun_l27_n829(x)
+ end
+end
+
+def fun_l26_n847(x)
+ if (x < 1)
+ fun_l27_n850(x)
+ else
+ fun_l27_n626(x)
+ end
+end
+
+def fun_l26_n848(x)
+ if (x < 1)
+ fun_l27_n889(x)
+ else
+ fun_l27_n504(x)
+ end
+end
+
+def fun_l26_n849(x)
+ if (x < 1)
+ fun_l27_n121(x)
+ else
+ fun_l27_n864(x)
+ end
+end
+
+def fun_l26_n850(x)
+ if (x < 1)
+ fun_l27_n985(x)
+ else
+ fun_l27_n447(x)
+ end
+end
+
+def fun_l26_n851(x)
+ if (x < 1)
+ fun_l27_n952(x)
+ else
+ fun_l27_n30(x)
+ end
+end
+
+def fun_l26_n852(x)
+ if (x < 1)
+ fun_l27_n444(x)
+ else
+ fun_l27_n780(x)
+ end
+end
+
+def fun_l26_n853(x)
+ if (x < 1)
+ fun_l27_n969(x)
+ else
+ fun_l27_n400(x)
+ end
+end
+
+def fun_l26_n854(x)
+ if (x < 1)
+ fun_l27_n711(x)
+ else
+ fun_l27_n165(x)
+ end
+end
+
+def fun_l26_n855(x)
+ if (x < 1)
+ fun_l27_n514(x)
+ else
+ fun_l27_n464(x)
+ end
+end
+
+def fun_l26_n856(x)
+ if (x < 1)
+ fun_l27_n531(x)
+ else
+ fun_l27_n548(x)
+ end
+end
+
+def fun_l26_n857(x)
+ if (x < 1)
+ fun_l27_n996(x)
+ else
+ fun_l27_n63(x)
+ end
+end
+
+def fun_l26_n858(x)
+ if (x < 1)
+ fun_l27_n516(x)
+ else
+ fun_l27_n905(x)
+ end
+end
+
+def fun_l26_n859(x)
+ if (x < 1)
+ fun_l27_n42(x)
+ else
+ fun_l27_n327(x)
+ end
+end
+
+def fun_l26_n860(x)
+ if (x < 1)
+ fun_l27_n300(x)
+ else
+ fun_l27_n276(x)
+ end
+end
+
+def fun_l26_n861(x)
+ if (x < 1)
+ fun_l27_n734(x)
+ else
+ fun_l27_n859(x)
+ end
+end
+
+def fun_l26_n862(x)
+ if (x < 1)
+ fun_l27_n135(x)
+ else
+ fun_l27_n821(x)
+ end
+end
+
+def fun_l26_n863(x)
+ if (x < 1)
+ fun_l27_n645(x)
+ else
+ fun_l27_n287(x)
+ end
+end
+
+def fun_l26_n864(x)
+ if (x < 1)
+ fun_l27_n243(x)
+ else
+ fun_l27_n844(x)
+ end
+end
+
+def fun_l26_n865(x)
+ if (x < 1)
+ fun_l27_n909(x)
+ else
+ fun_l27_n291(x)
+ end
+end
+
+def fun_l26_n866(x)
+ if (x < 1)
+ fun_l27_n925(x)
+ else
+ fun_l27_n484(x)
+ end
+end
+
+def fun_l26_n867(x)
+ if (x < 1)
+ fun_l27_n678(x)
+ else
+ fun_l27_n205(x)
+ end
+end
+
+def fun_l26_n868(x)
+ if (x < 1)
+ fun_l27_n612(x)
+ else
+ fun_l27_n339(x)
+ end
+end
+
+def fun_l26_n869(x)
+ if (x < 1)
+ fun_l27_n622(x)
+ else
+ fun_l27_n246(x)
+ end
+end
+
+def fun_l26_n870(x)
+ if (x < 1)
+ fun_l27_n431(x)
+ else
+ fun_l27_n635(x)
+ end
+end
+
+def fun_l26_n871(x)
+ if (x < 1)
+ fun_l27_n89(x)
+ else
+ fun_l27_n969(x)
+ end
+end
+
+def fun_l26_n872(x)
+ if (x < 1)
+ fun_l27_n839(x)
+ else
+ fun_l27_n398(x)
+ end
+end
+
+def fun_l26_n873(x)
+ if (x < 1)
+ fun_l27_n230(x)
+ else
+ fun_l27_n885(x)
+ end
+end
+
+def fun_l26_n874(x)
+ if (x < 1)
+ fun_l27_n202(x)
+ else
+ fun_l27_n530(x)
+ end
+end
+
+def fun_l26_n875(x)
+ if (x < 1)
+ fun_l27_n153(x)
+ else
+ fun_l27_n959(x)
+ end
+end
+
+def fun_l26_n876(x)
+ if (x < 1)
+ fun_l27_n891(x)
+ else
+ fun_l27_n307(x)
+ end
+end
+
+def fun_l26_n877(x)
+ if (x < 1)
+ fun_l27_n648(x)
+ else
+ fun_l27_n767(x)
+ end
+end
+
+def fun_l26_n878(x)
+ if (x < 1)
+ fun_l27_n120(x)
+ else
+ fun_l27_n614(x)
+ end
+end
+
+def fun_l26_n879(x)
+ if (x < 1)
+ fun_l27_n46(x)
+ else
+ fun_l27_n766(x)
+ end
+end
+
+def fun_l26_n880(x)
+ if (x < 1)
+ fun_l27_n882(x)
+ else
+ fun_l27_n745(x)
+ end
+end
+
+def fun_l26_n881(x)
+ if (x < 1)
+ fun_l27_n966(x)
+ else
+ fun_l27_n699(x)
+ end
+end
+
+def fun_l26_n882(x)
+ if (x < 1)
+ fun_l27_n354(x)
+ else
+ fun_l27_n698(x)
+ end
+end
+
+def fun_l26_n883(x)
+ if (x < 1)
+ fun_l27_n723(x)
+ else
+ fun_l27_n507(x)
+ end
+end
+
+def fun_l26_n884(x)
+ if (x < 1)
+ fun_l27_n705(x)
+ else
+ fun_l27_n865(x)
+ end
+end
+
+def fun_l26_n885(x)
+ if (x < 1)
+ fun_l27_n609(x)
+ else
+ fun_l27_n830(x)
+ end
+end
+
+def fun_l26_n886(x)
+ if (x < 1)
+ fun_l27_n679(x)
+ else
+ fun_l27_n359(x)
+ end
+end
+
+def fun_l26_n887(x)
+ if (x < 1)
+ fun_l27_n830(x)
+ else
+ fun_l27_n59(x)
+ end
+end
+
+def fun_l26_n888(x)
+ if (x < 1)
+ fun_l27_n160(x)
+ else
+ fun_l27_n559(x)
+ end
+end
+
+def fun_l26_n889(x)
+ if (x < 1)
+ fun_l27_n233(x)
+ else
+ fun_l27_n148(x)
+ end
+end
+
+def fun_l26_n890(x)
+ if (x < 1)
+ fun_l27_n520(x)
+ else
+ fun_l27_n104(x)
+ end
+end
+
+def fun_l26_n891(x)
+ if (x < 1)
+ fun_l27_n826(x)
+ else
+ fun_l27_n884(x)
+ end
+end
+
+def fun_l26_n892(x)
+ if (x < 1)
+ fun_l27_n546(x)
+ else
+ fun_l27_n651(x)
+ end
+end
+
+def fun_l26_n893(x)
+ if (x < 1)
+ fun_l27_n181(x)
+ else
+ fun_l27_n430(x)
+ end
+end
+
+def fun_l26_n894(x)
+ if (x < 1)
+ fun_l27_n540(x)
+ else
+ fun_l27_n424(x)
+ end
+end
+
+def fun_l26_n895(x)
+ if (x < 1)
+ fun_l27_n321(x)
+ else
+ fun_l27_n72(x)
+ end
+end
+
+def fun_l26_n896(x)
+ if (x < 1)
+ fun_l27_n532(x)
+ else
+ fun_l27_n535(x)
+ end
+end
+
+def fun_l26_n897(x)
+ if (x < 1)
+ fun_l27_n171(x)
+ else
+ fun_l27_n575(x)
+ end
+end
+
+def fun_l26_n898(x)
+ if (x < 1)
+ fun_l27_n150(x)
+ else
+ fun_l27_n539(x)
+ end
+end
+
+def fun_l26_n899(x)
+ if (x < 1)
+ fun_l27_n27(x)
+ else
+ fun_l27_n487(x)
+ end
+end
+
+def fun_l26_n900(x)
+ if (x < 1)
+ fun_l27_n484(x)
+ else
+ fun_l27_n366(x)
+ end
+end
+
+def fun_l26_n901(x)
+ if (x < 1)
+ fun_l27_n708(x)
+ else
+ fun_l27_n624(x)
+ end
+end
+
+def fun_l26_n902(x)
+ if (x < 1)
+ fun_l27_n811(x)
+ else
+ fun_l27_n905(x)
+ end
+end
+
+def fun_l26_n903(x)
+ if (x < 1)
+ fun_l27_n474(x)
+ else
+ fun_l27_n252(x)
+ end
+end
+
+def fun_l26_n904(x)
+ if (x < 1)
+ fun_l27_n765(x)
+ else
+ fun_l27_n86(x)
+ end
+end
+
+def fun_l26_n905(x)
+ if (x < 1)
+ fun_l27_n120(x)
+ else
+ fun_l27_n868(x)
+ end
+end
+
+def fun_l26_n906(x)
+ if (x < 1)
+ fun_l27_n824(x)
+ else
+ fun_l27_n167(x)
+ end
+end
+
+def fun_l26_n907(x)
+ if (x < 1)
+ fun_l27_n874(x)
+ else
+ fun_l27_n428(x)
+ end
+end
+
+def fun_l26_n908(x)
+ if (x < 1)
+ fun_l27_n270(x)
+ else
+ fun_l27_n539(x)
+ end
+end
+
+def fun_l26_n909(x)
+ if (x < 1)
+ fun_l27_n451(x)
+ else
+ fun_l27_n64(x)
+ end
+end
+
+def fun_l26_n910(x)
+ if (x < 1)
+ fun_l27_n680(x)
+ else
+ fun_l27_n556(x)
+ end
+end
+
+def fun_l26_n911(x)
+ if (x < 1)
+ fun_l27_n480(x)
+ else
+ fun_l27_n599(x)
+ end
+end
+
+def fun_l26_n912(x)
+ if (x < 1)
+ fun_l27_n861(x)
+ else
+ fun_l27_n768(x)
+ end
+end
+
+def fun_l26_n913(x)
+ if (x < 1)
+ fun_l27_n679(x)
+ else
+ fun_l27_n541(x)
+ end
+end
+
+def fun_l26_n914(x)
+ if (x < 1)
+ fun_l27_n69(x)
+ else
+ fun_l27_n904(x)
+ end
+end
+
+def fun_l26_n915(x)
+ if (x < 1)
+ fun_l27_n658(x)
+ else
+ fun_l27_n580(x)
+ end
+end
+
+def fun_l26_n916(x)
+ if (x < 1)
+ fun_l27_n595(x)
+ else
+ fun_l27_n194(x)
+ end
+end
+
+def fun_l26_n917(x)
+ if (x < 1)
+ fun_l27_n518(x)
+ else
+ fun_l27_n613(x)
+ end
+end
+
+def fun_l26_n918(x)
+ if (x < 1)
+ fun_l27_n46(x)
+ else
+ fun_l27_n910(x)
+ end
+end
+
+def fun_l26_n919(x)
+ if (x < 1)
+ fun_l27_n471(x)
+ else
+ fun_l27_n562(x)
+ end
+end
+
+def fun_l26_n920(x)
+ if (x < 1)
+ fun_l27_n637(x)
+ else
+ fun_l27_n638(x)
+ end
+end
+
+def fun_l26_n921(x)
+ if (x < 1)
+ fun_l27_n77(x)
+ else
+ fun_l27_n100(x)
+ end
+end
+
+def fun_l26_n922(x)
+ if (x < 1)
+ fun_l27_n382(x)
+ else
+ fun_l27_n235(x)
+ end
+end
+
+def fun_l26_n923(x)
+ if (x < 1)
+ fun_l27_n576(x)
+ else
+ fun_l27_n404(x)
+ end
+end
+
+def fun_l26_n924(x)
+ if (x < 1)
+ fun_l27_n338(x)
+ else
+ fun_l27_n919(x)
+ end
+end
+
+def fun_l26_n925(x)
+ if (x < 1)
+ fun_l27_n758(x)
+ else
+ fun_l27_n141(x)
+ end
+end
+
+def fun_l26_n926(x)
+ if (x < 1)
+ fun_l27_n904(x)
+ else
+ fun_l27_n965(x)
+ end
+end
+
+def fun_l26_n927(x)
+ if (x < 1)
+ fun_l27_n149(x)
+ else
+ fun_l27_n707(x)
+ end
+end
+
+def fun_l26_n928(x)
+ if (x < 1)
+ fun_l27_n337(x)
+ else
+ fun_l27_n601(x)
+ end
+end
+
+def fun_l26_n929(x)
+ if (x < 1)
+ fun_l27_n34(x)
+ else
+ fun_l27_n383(x)
+ end
+end
+
+def fun_l26_n930(x)
+ if (x < 1)
+ fun_l27_n937(x)
+ else
+ fun_l27_n656(x)
+ end
+end
+
+def fun_l26_n931(x)
+ if (x < 1)
+ fun_l27_n786(x)
+ else
+ fun_l27_n73(x)
+ end
+end
+
+def fun_l26_n932(x)
+ if (x < 1)
+ fun_l27_n568(x)
+ else
+ fun_l27_n465(x)
+ end
+end
+
+def fun_l26_n933(x)
+ if (x < 1)
+ fun_l27_n552(x)
+ else
+ fun_l27_n557(x)
+ end
+end
+
+def fun_l26_n934(x)
+ if (x < 1)
+ fun_l27_n261(x)
+ else
+ fun_l27_n612(x)
+ end
+end
+
+def fun_l26_n935(x)
+ if (x < 1)
+ fun_l27_n707(x)
+ else
+ fun_l27_n955(x)
+ end
+end
+
+def fun_l26_n936(x)
+ if (x < 1)
+ fun_l27_n948(x)
+ else
+ fun_l27_n78(x)
+ end
+end
+
+def fun_l26_n937(x)
+ if (x < 1)
+ fun_l27_n963(x)
+ else
+ fun_l27_n203(x)
+ end
+end
+
+def fun_l26_n938(x)
+ if (x < 1)
+ fun_l27_n779(x)
+ else
+ fun_l27_n393(x)
+ end
+end
+
+def fun_l26_n939(x)
+ if (x < 1)
+ fun_l27_n403(x)
+ else
+ fun_l27_n303(x)
+ end
+end
+
+def fun_l26_n940(x)
+ if (x < 1)
+ fun_l27_n779(x)
+ else
+ fun_l27_n934(x)
+ end
+end
+
+def fun_l26_n941(x)
+ if (x < 1)
+ fun_l27_n191(x)
+ else
+ fun_l27_n414(x)
+ end
+end
+
+def fun_l26_n942(x)
+ if (x < 1)
+ fun_l27_n22(x)
+ else
+ fun_l27_n101(x)
+ end
+end
+
+def fun_l26_n943(x)
+ if (x < 1)
+ fun_l27_n501(x)
+ else
+ fun_l27_n43(x)
+ end
+end
+
+def fun_l26_n944(x)
+ if (x < 1)
+ fun_l27_n154(x)
+ else
+ fun_l27_n659(x)
+ end
+end
+
+def fun_l26_n945(x)
+ if (x < 1)
+ fun_l27_n346(x)
+ else
+ fun_l27_n380(x)
+ end
+end
+
+def fun_l26_n946(x)
+ if (x < 1)
+ fun_l27_n653(x)
+ else
+ fun_l27_n762(x)
+ end
+end
+
+def fun_l26_n947(x)
+ if (x < 1)
+ fun_l27_n191(x)
+ else
+ fun_l27_n649(x)
+ end
+end
+
+def fun_l26_n948(x)
+ if (x < 1)
+ fun_l27_n645(x)
+ else
+ fun_l27_n199(x)
+ end
+end
+
+def fun_l26_n949(x)
+ if (x < 1)
+ fun_l27_n251(x)
+ else
+ fun_l27_n461(x)
+ end
+end
+
+def fun_l26_n950(x)
+ if (x < 1)
+ fun_l27_n720(x)
+ else
+ fun_l27_n645(x)
+ end
+end
+
+def fun_l26_n951(x)
+ if (x < 1)
+ fun_l27_n200(x)
+ else
+ fun_l27_n73(x)
+ end
+end
+
+def fun_l26_n952(x)
+ if (x < 1)
+ fun_l27_n86(x)
+ else
+ fun_l27_n526(x)
+ end
+end
+
+def fun_l26_n953(x)
+ if (x < 1)
+ fun_l27_n448(x)
+ else
+ fun_l27_n108(x)
+ end
+end
+
+def fun_l26_n954(x)
+ if (x < 1)
+ fun_l27_n931(x)
+ else
+ fun_l27_n540(x)
+ end
+end
+
+def fun_l26_n955(x)
+ if (x < 1)
+ fun_l27_n298(x)
+ else
+ fun_l27_n836(x)
+ end
+end
+
+def fun_l26_n956(x)
+ if (x < 1)
+ fun_l27_n232(x)
+ else
+ fun_l27_n200(x)
+ end
+end
+
+def fun_l26_n957(x)
+ if (x < 1)
+ fun_l27_n342(x)
+ else
+ fun_l27_n885(x)
+ end
+end
+
+def fun_l26_n958(x)
+ if (x < 1)
+ fun_l27_n254(x)
+ else
+ fun_l27_n764(x)
+ end
+end
+
+def fun_l26_n959(x)
+ if (x < 1)
+ fun_l27_n765(x)
+ else
+ fun_l27_n264(x)
+ end
+end
+
+def fun_l26_n960(x)
+ if (x < 1)
+ fun_l27_n45(x)
+ else
+ fun_l27_n993(x)
+ end
+end
+
+def fun_l26_n961(x)
+ if (x < 1)
+ fun_l27_n105(x)
+ else
+ fun_l27_n100(x)
+ end
+end
+
+def fun_l26_n962(x)
+ if (x < 1)
+ fun_l27_n979(x)
+ else
+ fun_l27_n87(x)
+ end
+end
+
+def fun_l26_n963(x)
+ if (x < 1)
+ fun_l27_n103(x)
+ else
+ fun_l27_n927(x)
+ end
+end
+
+def fun_l26_n964(x)
+ if (x < 1)
+ fun_l27_n635(x)
+ else
+ fun_l27_n489(x)
+ end
+end
+
+def fun_l26_n965(x)
+ if (x < 1)
+ fun_l27_n565(x)
+ else
+ fun_l27_n70(x)
+ end
+end
+
+def fun_l26_n966(x)
+ if (x < 1)
+ fun_l27_n370(x)
+ else
+ fun_l27_n975(x)
+ end
+end
+
+def fun_l26_n967(x)
+ if (x < 1)
+ fun_l27_n997(x)
+ else
+ fun_l27_n132(x)
+ end
+end
+
+def fun_l26_n968(x)
+ if (x < 1)
+ fun_l27_n964(x)
+ else
+ fun_l27_n201(x)
+ end
+end
+
+def fun_l26_n969(x)
+ if (x < 1)
+ fun_l27_n710(x)
+ else
+ fun_l27_n875(x)
+ end
+end
+
+def fun_l26_n970(x)
+ if (x < 1)
+ fun_l27_n736(x)
+ else
+ fun_l27_n338(x)
+ end
+end
+
+def fun_l26_n971(x)
+ if (x < 1)
+ fun_l27_n429(x)
+ else
+ fun_l27_n64(x)
+ end
+end
+
+def fun_l26_n972(x)
+ if (x < 1)
+ fun_l27_n986(x)
+ else
+ fun_l27_n27(x)
+ end
+end
+
+def fun_l26_n973(x)
+ if (x < 1)
+ fun_l27_n419(x)
+ else
+ fun_l27_n579(x)
+ end
+end
+
+def fun_l26_n974(x)
+ if (x < 1)
+ fun_l27_n479(x)
+ else
+ fun_l27_n709(x)
+ end
+end
+
+def fun_l26_n975(x)
+ if (x < 1)
+ fun_l27_n524(x)
+ else
+ fun_l27_n550(x)
+ end
+end
+
+def fun_l26_n976(x)
+ if (x < 1)
+ fun_l27_n679(x)
+ else
+ fun_l27_n822(x)
+ end
+end
+
+def fun_l26_n977(x)
+ if (x < 1)
+ fun_l27_n535(x)
+ else
+ fun_l27_n198(x)
+ end
+end
+
+def fun_l26_n978(x)
+ if (x < 1)
+ fun_l27_n226(x)
+ else
+ fun_l27_n610(x)
+ end
+end
+
+def fun_l26_n979(x)
+ if (x < 1)
+ fun_l27_n460(x)
+ else
+ fun_l27_n562(x)
+ end
+end
+
+def fun_l26_n980(x)
+ if (x < 1)
+ fun_l27_n109(x)
+ else
+ fun_l27_n632(x)
+ end
+end
+
+def fun_l26_n981(x)
+ if (x < 1)
+ fun_l27_n936(x)
+ else
+ fun_l27_n288(x)
+ end
+end
+
+def fun_l26_n982(x)
+ if (x < 1)
+ fun_l27_n668(x)
+ else
+ fun_l27_n5(x)
+ end
+end
+
+def fun_l26_n983(x)
+ if (x < 1)
+ fun_l27_n458(x)
+ else
+ fun_l27_n861(x)
+ end
+end
+
+def fun_l26_n984(x)
+ if (x < 1)
+ fun_l27_n722(x)
+ else
+ fun_l27_n838(x)
+ end
+end
+
+def fun_l26_n985(x)
+ if (x < 1)
+ fun_l27_n883(x)
+ else
+ fun_l27_n124(x)
+ end
+end
+
+def fun_l26_n986(x)
+ if (x < 1)
+ fun_l27_n873(x)
+ else
+ fun_l27_n399(x)
+ end
+end
+
+def fun_l26_n987(x)
+ if (x < 1)
+ fun_l27_n449(x)
+ else
+ fun_l27_n34(x)
+ end
+end
+
+def fun_l26_n988(x)
+ if (x < 1)
+ fun_l27_n549(x)
+ else
+ fun_l27_n304(x)
+ end
+end
+
+def fun_l26_n989(x)
+ if (x < 1)
+ fun_l27_n287(x)
+ else
+ fun_l27_n270(x)
+ end
+end
+
+def fun_l26_n990(x)
+ if (x < 1)
+ fun_l27_n950(x)
+ else
+ fun_l27_n203(x)
+ end
+end
+
+def fun_l26_n991(x)
+ if (x < 1)
+ fun_l27_n39(x)
+ else
+ fun_l27_n284(x)
+ end
+end
+
+def fun_l26_n992(x)
+ if (x < 1)
+ fun_l27_n944(x)
+ else
+ fun_l27_n420(x)
+ end
+end
+
+def fun_l26_n993(x)
+ if (x < 1)
+ fun_l27_n254(x)
+ else
+ fun_l27_n960(x)
+ end
+end
+
+def fun_l26_n994(x)
+ if (x < 1)
+ fun_l27_n374(x)
+ else
+ fun_l27_n354(x)
+ end
+end
+
+def fun_l26_n995(x)
+ if (x < 1)
+ fun_l27_n766(x)
+ else
+ fun_l27_n937(x)
+ end
+end
+
+def fun_l26_n996(x)
+ if (x < 1)
+ fun_l27_n299(x)
+ else
+ fun_l27_n565(x)
+ end
+end
+
+def fun_l26_n997(x)
+ if (x < 1)
+ fun_l27_n390(x)
+ else
+ fun_l27_n924(x)
+ end
+end
+
+def fun_l26_n998(x)
+ if (x < 1)
+ fun_l27_n452(x)
+ else
+ fun_l27_n653(x)
+ end
+end
+
+def fun_l26_n999(x)
+ if (x < 1)
+ fun_l27_n110(x)
+ else
+ fun_l27_n781(x)
+ end
+end
+
+def fun_l27_n0(x)
+ if (x < 1)
+ fun_l28_n77(x)
+ else
+ fun_l28_n170(x)
+ end
+end
+
+def fun_l27_n1(x)
+ if (x < 1)
+ fun_l28_n420(x)
+ else
+ fun_l28_n414(x)
+ end
+end
+
+def fun_l27_n2(x)
+ if (x < 1)
+ fun_l28_n802(x)
+ else
+ fun_l28_n702(x)
+ end
+end
+
+def fun_l27_n3(x)
+ if (x < 1)
+ fun_l28_n742(x)
+ else
+ fun_l28_n819(x)
+ end
+end
+
+def fun_l27_n4(x)
+ if (x < 1)
+ fun_l28_n75(x)
+ else
+ fun_l28_n675(x)
+ end
+end
+
+def fun_l27_n5(x)
+ if (x < 1)
+ fun_l28_n276(x)
+ else
+ fun_l28_n554(x)
+ end
+end
+
+def fun_l27_n6(x)
+ if (x < 1)
+ fun_l28_n505(x)
+ else
+ fun_l28_n462(x)
+ end
+end
+
+def fun_l27_n7(x)
+ if (x < 1)
+ fun_l28_n401(x)
+ else
+ fun_l28_n437(x)
+ end
+end
+
+def fun_l27_n8(x)
+ if (x < 1)
+ fun_l28_n987(x)
+ else
+ fun_l28_n911(x)
+ end
+end
+
+def fun_l27_n9(x)
+ if (x < 1)
+ fun_l28_n196(x)
+ else
+ fun_l28_n507(x)
+ end
+end
+
+def fun_l27_n10(x)
+ if (x < 1)
+ fun_l28_n676(x)
+ else
+ fun_l28_n612(x)
+ end
+end
+
+def fun_l27_n11(x)
+ if (x < 1)
+ fun_l28_n630(x)
+ else
+ fun_l28_n897(x)
+ end
+end
+
+def fun_l27_n12(x)
+ if (x < 1)
+ fun_l28_n655(x)
+ else
+ fun_l28_n58(x)
+ end
+end
+
+def fun_l27_n13(x)
+ if (x < 1)
+ fun_l28_n777(x)
+ else
+ fun_l28_n138(x)
+ end
+end
+
+def fun_l27_n14(x)
+ if (x < 1)
+ fun_l28_n233(x)
+ else
+ fun_l28_n296(x)
+ end
+end
+
+def fun_l27_n15(x)
+ if (x < 1)
+ fun_l28_n580(x)
+ else
+ fun_l28_n538(x)
+ end
+end
+
+def fun_l27_n16(x)
+ if (x < 1)
+ fun_l28_n124(x)
+ else
+ fun_l28_n285(x)
+ end
+end
+
+def fun_l27_n17(x)
+ if (x < 1)
+ fun_l28_n250(x)
+ else
+ fun_l28_n255(x)
+ end
+end
+
+def fun_l27_n18(x)
+ if (x < 1)
+ fun_l28_n872(x)
+ else
+ fun_l28_n242(x)
+ end
+end
+
+def fun_l27_n19(x)
+ if (x < 1)
+ fun_l28_n548(x)
+ else
+ fun_l28_n30(x)
+ end
+end
+
+def fun_l27_n20(x)
+ if (x < 1)
+ fun_l28_n411(x)
+ else
+ fun_l28_n997(x)
+ end
+end
+
+def fun_l27_n21(x)
+ if (x < 1)
+ fun_l28_n860(x)
+ else
+ fun_l28_n22(x)
+ end
+end
+
+def fun_l27_n22(x)
+ if (x < 1)
+ fun_l28_n147(x)
+ else
+ fun_l28_n210(x)
+ end
+end
+
+def fun_l27_n23(x)
+ if (x < 1)
+ fun_l28_n763(x)
+ else
+ fun_l28_n652(x)
+ end
+end
+
+def fun_l27_n24(x)
+ if (x < 1)
+ fun_l28_n678(x)
+ else
+ fun_l28_n637(x)
+ end
+end
+
+def fun_l27_n25(x)
+ if (x < 1)
+ fun_l28_n748(x)
+ else
+ fun_l28_n445(x)
+ end
+end
+
+def fun_l27_n26(x)
+ if (x < 1)
+ fun_l28_n796(x)
+ else
+ fun_l28_n780(x)
+ end
+end
+
+def fun_l27_n27(x)
+ if (x < 1)
+ fun_l28_n26(x)
+ else
+ fun_l28_n737(x)
+ end
+end
+
+def fun_l27_n28(x)
+ if (x < 1)
+ fun_l28_n779(x)
+ else
+ fun_l28_n206(x)
+ end
+end
+
+def fun_l27_n29(x)
+ if (x < 1)
+ fun_l28_n236(x)
+ else
+ fun_l28_n864(x)
+ end
+end
+
+def fun_l27_n30(x)
+ if (x < 1)
+ fun_l28_n937(x)
+ else
+ fun_l28_n524(x)
+ end
+end
+
+def fun_l27_n31(x)
+ if (x < 1)
+ fun_l28_n61(x)
+ else
+ fun_l28_n791(x)
+ end
+end
+
+def fun_l27_n32(x)
+ if (x < 1)
+ fun_l28_n891(x)
+ else
+ fun_l28_n424(x)
+ end
+end
+
+def fun_l27_n33(x)
+ if (x < 1)
+ fun_l28_n856(x)
+ else
+ fun_l28_n544(x)
+ end
+end
+
+def fun_l27_n34(x)
+ if (x < 1)
+ fun_l28_n575(x)
+ else
+ fun_l28_n608(x)
+ end
+end
+
+def fun_l27_n35(x)
+ if (x < 1)
+ fun_l28_n546(x)
+ else
+ fun_l28_n164(x)
+ end
+end
+
+def fun_l27_n36(x)
+ if (x < 1)
+ fun_l28_n482(x)
+ else
+ fun_l28_n854(x)
+ end
+end
+
+def fun_l27_n37(x)
+ if (x < 1)
+ fun_l28_n667(x)
+ else
+ fun_l28_n568(x)
+ end
+end
+
+def fun_l27_n38(x)
+ if (x < 1)
+ fun_l28_n8(x)
+ else
+ fun_l28_n794(x)
+ end
+end
+
+def fun_l27_n39(x)
+ if (x < 1)
+ fun_l28_n504(x)
+ else
+ fun_l28_n199(x)
+ end
+end
+
+def fun_l27_n40(x)
+ if (x < 1)
+ fun_l28_n360(x)
+ else
+ fun_l28_n714(x)
+ end
+end
+
+def fun_l27_n41(x)
+ if (x < 1)
+ fun_l28_n758(x)
+ else
+ fun_l28_n499(x)
+ end
+end
+
+def fun_l27_n42(x)
+ if (x < 1)
+ fun_l28_n617(x)
+ else
+ fun_l28_n239(x)
+ end
+end
+
+def fun_l27_n43(x)
+ if (x < 1)
+ fun_l28_n357(x)
+ else
+ fun_l28_n950(x)
+ end
+end
+
+def fun_l27_n44(x)
+ if (x < 1)
+ fun_l28_n308(x)
+ else
+ fun_l28_n248(x)
+ end
+end
+
+def fun_l27_n45(x)
+ if (x < 1)
+ fun_l28_n887(x)
+ else
+ fun_l28_n541(x)
+ end
+end
+
+def fun_l27_n46(x)
+ if (x < 1)
+ fun_l28_n922(x)
+ else
+ fun_l28_n21(x)
+ end
+end
+
+def fun_l27_n47(x)
+ if (x < 1)
+ fun_l28_n398(x)
+ else
+ fun_l28_n781(x)
+ end
+end
+
+def fun_l27_n48(x)
+ if (x < 1)
+ fun_l28_n573(x)
+ else
+ fun_l28_n22(x)
+ end
+end
+
+def fun_l27_n49(x)
+ if (x < 1)
+ fun_l28_n324(x)
+ else
+ fun_l28_n764(x)
+ end
+end
+
+def fun_l27_n50(x)
+ if (x < 1)
+ fun_l28_n428(x)
+ else
+ fun_l28_n3(x)
+ end
+end
+
+def fun_l27_n51(x)
+ if (x < 1)
+ fun_l28_n637(x)
+ else
+ fun_l28_n871(x)
+ end
+end
+
+def fun_l27_n52(x)
+ if (x < 1)
+ fun_l28_n547(x)
+ else
+ fun_l28_n370(x)
+ end
+end
+
+def fun_l27_n53(x)
+ if (x < 1)
+ fun_l28_n864(x)
+ else
+ fun_l28_n360(x)
+ end
+end
+
+def fun_l27_n54(x)
+ if (x < 1)
+ fun_l28_n960(x)
+ else
+ fun_l28_n80(x)
+ end
+end
+
+def fun_l27_n55(x)
+ if (x < 1)
+ fun_l28_n339(x)
+ else
+ fun_l28_n828(x)
+ end
+end
+
+def fun_l27_n56(x)
+ if (x < 1)
+ fun_l28_n613(x)
+ else
+ fun_l28_n109(x)
+ end
+end
+
+def fun_l27_n57(x)
+ if (x < 1)
+ fun_l28_n458(x)
+ else
+ fun_l28_n339(x)
+ end
+end
+
+def fun_l27_n58(x)
+ if (x < 1)
+ fun_l28_n313(x)
+ else
+ fun_l28_n20(x)
+ end
+end
+
+def fun_l27_n59(x)
+ if (x < 1)
+ fun_l28_n642(x)
+ else
+ fun_l28_n582(x)
+ end
+end
+
+def fun_l27_n60(x)
+ if (x < 1)
+ fun_l28_n407(x)
+ else
+ fun_l28_n182(x)
+ end
+end
+
+def fun_l27_n61(x)
+ if (x < 1)
+ fun_l28_n475(x)
+ else
+ fun_l28_n865(x)
+ end
+end
+
+def fun_l27_n62(x)
+ if (x < 1)
+ fun_l28_n867(x)
+ else
+ fun_l28_n935(x)
+ end
+end
+
+def fun_l27_n63(x)
+ if (x < 1)
+ fun_l28_n361(x)
+ else
+ fun_l28_n675(x)
+ end
+end
+
+def fun_l27_n64(x)
+ if (x < 1)
+ fun_l28_n583(x)
+ else
+ fun_l28_n990(x)
+ end
+end
+
+def fun_l27_n65(x)
+ if (x < 1)
+ fun_l28_n305(x)
+ else
+ fun_l28_n918(x)
+ end
+end
+
+def fun_l27_n66(x)
+ if (x < 1)
+ fun_l28_n449(x)
+ else
+ fun_l28_n172(x)
+ end
+end
+
+def fun_l27_n67(x)
+ if (x < 1)
+ fun_l28_n384(x)
+ else
+ fun_l28_n102(x)
+ end
+end
+
+def fun_l27_n68(x)
+ if (x < 1)
+ fun_l28_n27(x)
+ else
+ fun_l28_n638(x)
+ end
+end
+
+def fun_l27_n69(x)
+ if (x < 1)
+ fun_l28_n370(x)
+ else
+ fun_l28_n305(x)
+ end
+end
+
+def fun_l27_n70(x)
+ if (x < 1)
+ fun_l28_n91(x)
+ else
+ fun_l28_n516(x)
+ end
+end
+
+def fun_l27_n71(x)
+ if (x < 1)
+ fun_l28_n835(x)
+ else
+ fun_l28_n422(x)
+ end
+end
+
+def fun_l27_n72(x)
+ if (x < 1)
+ fun_l28_n528(x)
+ else
+ fun_l28_n924(x)
+ end
+end
+
+def fun_l27_n73(x)
+ if (x < 1)
+ fun_l28_n910(x)
+ else
+ fun_l28_n177(x)
+ end
+end
+
+def fun_l27_n74(x)
+ if (x < 1)
+ fun_l28_n424(x)
+ else
+ fun_l28_n133(x)
+ end
+end
+
+def fun_l27_n75(x)
+ if (x < 1)
+ fun_l28_n207(x)
+ else
+ fun_l28_n206(x)
+ end
+end
+
+def fun_l27_n76(x)
+ if (x < 1)
+ fun_l28_n285(x)
+ else
+ fun_l28_n513(x)
+ end
+end
+
+def fun_l27_n77(x)
+ if (x < 1)
+ fun_l28_n446(x)
+ else
+ fun_l28_n985(x)
+ end
+end
+
+def fun_l27_n78(x)
+ if (x < 1)
+ fun_l28_n814(x)
+ else
+ fun_l28_n43(x)
+ end
+end
+
+def fun_l27_n79(x)
+ if (x < 1)
+ fun_l28_n155(x)
+ else
+ fun_l28_n944(x)
+ end
+end
+
+def fun_l27_n80(x)
+ if (x < 1)
+ fun_l28_n22(x)
+ else
+ fun_l28_n815(x)
+ end
+end
+
+def fun_l27_n81(x)
+ if (x < 1)
+ fun_l28_n465(x)
+ else
+ fun_l28_n132(x)
+ end
+end
+
+def fun_l27_n82(x)
+ if (x < 1)
+ fun_l28_n540(x)
+ else
+ fun_l28_n199(x)
+ end
+end
+
+def fun_l27_n83(x)
+ if (x < 1)
+ fun_l28_n28(x)
+ else
+ fun_l28_n64(x)
+ end
+end
+
+def fun_l27_n84(x)
+ if (x < 1)
+ fun_l28_n4(x)
+ else
+ fun_l28_n782(x)
+ end
+end
+
+def fun_l27_n85(x)
+ if (x < 1)
+ fun_l28_n685(x)
+ else
+ fun_l28_n57(x)
+ end
+end
+
+def fun_l27_n86(x)
+ if (x < 1)
+ fun_l28_n755(x)
+ else
+ fun_l28_n317(x)
+ end
+end
+
+def fun_l27_n87(x)
+ if (x < 1)
+ fun_l28_n298(x)
+ else
+ fun_l28_n645(x)
+ end
+end
+
+def fun_l27_n88(x)
+ if (x < 1)
+ fun_l28_n489(x)
+ else
+ fun_l28_n357(x)
+ end
+end
+
+def fun_l27_n89(x)
+ if (x < 1)
+ fun_l28_n225(x)
+ else
+ fun_l28_n465(x)
+ end
+end
+
+def fun_l27_n90(x)
+ if (x < 1)
+ fun_l28_n729(x)
+ else
+ fun_l28_n688(x)
+ end
+end
+
+def fun_l27_n91(x)
+ if (x < 1)
+ fun_l28_n936(x)
+ else
+ fun_l28_n62(x)
+ end
+end
+
+def fun_l27_n92(x)
+ if (x < 1)
+ fun_l28_n564(x)
+ else
+ fun_l28_n497(x)
+ end
+end
+
+def fun_l27_n93(x)
+ if (x < 1)
+ fun_l28_n78(x)
+ else
+ fun_l28_n167(x)
+ end
+end
+
+def fun_l27_n94(x)
+ if (x < 1)
+ fun_l28_n24(x)
+ else
+ fun_l28_n543(x)
+ end
+end
+
+def fun_l27_n95(x)
+ if (x < 1)
+ fun_l28_n56(x)
+ else
+ fun_l28_n796(x)
+ end
+end
+
+def fun_l27_n96(x)
+ if (x < 1)
+ fun_l28_n768(x)
+ else
+ fun_l28_n909(x)
+ end
+end
+
+def fun_l27_n97(x)
+ if (x < 1)
+ fun_l28_n72(x)
+ else
+ fun_l28_n604(x)
+ end
+end
+
+def fun_l27_n98(x)
+ if (x < 1)
+ fun_l28_n903(x)
+ else
+ fun_l28_n998(x)
+ end
+end
+
+def fun_l27_n99(x)
+ if (x < 1)
+ fun_l28_n525(x)
+ else
+ fun_l28_n158(x)
+ end
+end
+
+def fun_l27_n100(x)
+ if (x < 1)
+ fun_l28_n54(x)
+ else
+ fun_l28_n667(x)
+ end
+end
+
+def fun_l27_n101(x)
+ if (x < 1)
+ fun_l28_n894(x)
+ else
+ fun_l28_n807(x)
+ end
+end
+
+def fun_l27_n102(x)
+ if (x < 1)
+ fun_l28_n334(x)
+ else
+ fun_l28_n479(x)
+ end
+end
+
+def fun_l27_n103(x)
+ if (x < 1)
+ fun_l28_n211(x)
+ else
+ fun_l28_n383(x)
+ end
+end
+
+def fun_l27_n104(x)
+ if (x < 1)
+ fun_l28_n598(x)
+ else
+ fun_l28_n793(x)
+ end
+end
+
+def fun_l27_n105(x)
+ if (x < 1)
+ fun_l28_n812(x)
+ else
+ fun_l28_n806(x)
+ end
+end
+
+def fun_l27_n106(x)
+ if (x < 1)
+ fun_l28_n726(x)
+ else
+ fun_l28_n769(x)
+ end
+end
+
+def fun_l27_n107(x)
+ if (x < 1)
+ fun_l28_n593(x)
+ else
+ fun_l28_n173(x)
+ end
+end
+
+def fun_l27_n108(x)
+ if (x < 1)
+ fun_l28_n490(x)
+ else
+ fun_l28_n681(x)
+ end
+end
+
+def fun_l27_n109(x)
+ if (x < 1)
+ fun_l28_n691(x)
+ else
+ fun_l28_n323(x)
+ end
+end
+
+def fun_l27_n110(x)
+ if (x < 1)
+ fun_l28_n710(x)
+ else
+ fun_l28_n624(x)
+ end
+end
+
+def fun_l27_n111(x)
+ if (x < 1)
+ fun_l28_n563(x)
+ else
+ fun_l28_n335(x)
+ end
+end
+
+def fun_l27_n112(x)
+ if (x < 1)
+ fun_l28_n510(x)
+ else
+ fun_l28_n879(x)
+ end
+end
+
+def fun_l27_n113(x)
+ if (x < 1)
+ fun_l28_n900(x)
+ else
+ fun_l28_n119(x)
+ end
+end
+
+def fun_l27_n114(x)
+ if (x < 1)
+ fun_l28_n17(x)
+ else
+ fun_l28_n8(x)
+ end
+end
+
+def fun_l27_n115(x)
+ if (x < 1)
+ fun_l28_n813(x)
+ else
+ fun_l28_n948(x)
+ end
+end
+
+def fun_l27_n116(x)
+ if (x < 1)
+ fun_l28_n644(x)
+ else
+ fun_l28_n177(x)
+ end
+end
+
+def fun_l27_n117(x)
+ if (x < 1)
+ fun_l28_n635(x)
+ else
+ fun_l28_n489(x)
+ end
+end
+
+def fun_l27_n118(x)
+ if (x < 1)
+ fun_l28_n520(x)
+ else
+ fun_l28_n127(x)
+ end
+end
+
+def fun_l27_n119(x)
+ if (x < 1)
+ fun_l28_n859(x)
+ else
+ fun_l28_n264(x)
+ end
+end
+
+def fun_l27_n120(x)
+ if (x < 1)
+ fun_l28_n29(x)
+ else
+ fun_l28_n984(x)
+ end
+end
+
+def fun_l27_n121(x)
+ if (x < 1)
+ fun_l28_n2(x)
+ else
+ fun_l28_n858(x)
+ end
+end
+
+def fun_l27_n122(x)
+ if (x < 1)
+ fun_l28_n907(x)
+ else
+ fun_l28_n34(x)
+ end
+end
+
+def fun_l27_n123(x)
+ if (x < 1)
+ fun_l28_n495(x)
+ else
+ fun_l28_n144(x)
+ end
+end
+
+def fun_l27_n124(x)
+ if (x < 1)
+ fun_l28_n160(x)
+ else
+ fun_l28_n987(x)
+ end
+end
+
+def fun_l27_n125(x)
+ if (x < 1)
+ fun_l28_n60(x)
+ else
+ fun_l28_n415(x)
+ end
+end
+
+def fun_l27_n126(x)
+ if (x < 1)
+ fun_l28_n473(x)
+ else
+ fun_l28_n461(x)
+ end
+end
+
+def fun_l27_n127(x)
+ if (x < 1)
+ fun_l28_n664(x)
+ else
+ fun_l28_n764(x)
+ end
+end
+
+def fun_l27_n128(x)
+ if (x < 1)
+ fun_l28_n815(x)
+ else
+ fun_l28_n677(x)
+ end
+end
+
+def fun_l27_n129(x)
+ if (x < 1)
+ fun_l28_n828(x)
+ else
+ fun_l28_n575(x)
+ end
+end
+
+def fun_l27_n130(x)
+ if (x < 1)
+ fun_l28_n100(x)
+ else
+ fun_l28_n811(x)
+ end
+end
+
+def fun_l27_n131(x)
+ if (x < 1)
+ fun_l28_n789(x)
+ else
+ fun_l28_n246(x)
+ end
+end
+
+def fun_l27_n132(x)
+ if (x < 1)
+ fun_l28_n506(x)
+ else
+ fun_l28_n555(x)
+ end
+end
+
+def fun_l27_n133(x)
+ if (x < 1)
+ fun_l28_n272(x)
+ else
+ fun_l28_n115(x)
+ end
+end
+
+def fun_l27_n134(x)
+ if (x < 1)
+ fun_l28_n925(x)
+ else
+ fun_l28_n34(x)
+ end
+end
+
+def fun_l27_n135(x)
+ if (x < 1)
+ fun_l28_n844(x)
+ else
+ fun_l28_n725(x)
+ end
+end
+
+def fun_l27_n136(x)
+ if (x < 1)
+ fun_l28_n825(x)
+ else
+ fun_l28_n38(x)
+ end
+end
+
+def fun_l27_n137(x)
+ if (x < 1)
+ fun_l28_n607(x)
+ else
+ fun_l28_n343(x)
+ end
+end
+
+def fun_l27_n138(x)
+ if (x < 1)
+ fun_l28_n874(x)
+ else
+ fun_l28_n449(x)
+ end
+end
+
+def fun_l27_n139(x)
+ if (x < 1)
+ fun_l28_n632(x)
+ else
+ fun_l28_n454(x)
+ end
+end
+
+def fun_l27_n140(x)
+ if (x < 1)
+ fun_l28_n902(x)
+ else
+ fun_l28_n301(x)
+ end
+end
+
+def fun_l27_n141(x)
+ if (x < 1)
+ fun_l28_n395(x)
+ else
+ fun_l28_n890(x)
+ end
+end
+
+def fun_l27_n142(x)
+ if (x < 1)
+ fun_l28_n625(x)
+ else
+ fun_l28_n246(x)
+ end
+end
+
+def fun_l27_n143(x)
+ if (x < 1)
+ fun_l28_n312(x)
+ else
+ fun_l28_n975(x)
+ end
+end
+
+def fun_l27_n144(x)
+ if (x < 1)
+ fun_l28_n974(x)
+ else
+ fun_l28_n451(x)
+ end
+end
+
+def fun_l27_n145(x)
+ if (x < 1)
+ fun_l28_n541(x)
+ else
+ fun_l28_n566(x)
+ end
+end
+
+def fun_l27_n146(x)
+ if (x < 1)
+ fun_l28_n285(x)
+ else
+ fun_l28_n443(x)
+ end
+end
+
+def fun_l27_n147(x)
+ if (x < 1)
+ fun_l28_n71(x)
+ else
+ fun_l28_n200(x)
+ end
+end
+
+def fun_l27_n148(x)
+ if (x < 1)
+ fun_l28_n681(x)
+ else
+ fun_l28_n561(x)
+ end
+end
+
+def fun_l27_n149(x)
+ if (x < 1)
+ fun_l28_n470(x)
+ else
+ fun_l28_n529(x)
+ end
+end
+
+def fun_l27_n150(x)
+ if (x < 1)
+ fun_l28_n83(x)
+ else
+ fun_l28_n755(x)
+ end
+end
+
+def fun_l27_n151(x)
+ if (x < 1)
+ fun_l28_n142(x)
+ else
+ fun_l28_n631(x)
+ end
+end
+
+def fun_l27_n152(x)
+ if (x < 1)
+ fun_l28_n49(x)
+ else
+ fun_l28_n531(x)
+ end
+end
+
+def fun_l27_n153(x)
+ if (x < 1)
+ fun_l28_n237(x)
+ else
+ fun_l28_n241(x)
+ end
+end
+
+def fun_l27_n154(x)
+ if (x < 1)
+ fun_l28_n36(x)
+ else
+ fun_l28_n862(x)
+ end
+end
+
+def fun_l27_n155(x)
+ if (x < 1)
+ fun_l28_n310(x)
+ else
+ fun_l28_n387(x)
+ end
+end
+
+def fun_l27_n156(x)
+ if (x < 1)
+ fun_l28_n1(x)
+ else
+ fun_l28_n131(x)
+ end
+end
+
+def fun_l27_n157(x)
+ if (x < 1)
+ fun_l28_n232(x)
+ else
+ fun_l28_n503(x)
+ end
+end
+
+def fun_l27_n158(x)
+ if (x < 1)
+ fun_l28_n48(x)
+ else
+ fun_l28_n68(x)
+ end
+end
+
+def fun_l27_n159(x)
+ if (x < 1)
+ fun_l28_n98(x)
+ else
+ fun_l28_n82(x)
+ end
+end
+
+def fun_l27_n160(x)
+ if (x < 1)
+ fun_l28_n175(x)
+ else
+ fun_l28_n466(x)
+ end
+end
+
+def fun_l27_n161(x)
+ if (x < 1)
+ fun_l28_n105(x)
+ else
+ fun_l28_n159(x)
+ end
+end
+
+def fun_l27_n162(x)
+ if (x < 1)
+ fun_l28_n336(x)
+ else
+ fun_l28_n314(x)
+ end
+end
+
+def fun_l27_n163(x)
+ if (x < 1)
+ fun_l28_n458(x)
+ else
+ fun_l28_n901(x)
+ end
+end
+
+def fun_l27_n164(x)
+ if (x < 1)
+ fun_l28_n621(x)
+ else
+ fun_l28_n876(x)
+ end
+end
+
+def fun_l27_n165(x)
+ if (x < 1)
+ fun_l28_n830(x)
+ else
+ fun_l28_n468(x)
+ end
+end
+
+def fun_l27_n166(x)
+ if (x < 1)
+ fun_l28_n606(x)
+ else
+ fun_l28_n253(x)
+ end
+end
+
+def fun_l27_n167(x)
+ if (x < 1)
+ fun_l28_n905(x)
+ else
+ fun_l28_n582(x)
+ end
+end
+
+def fun_l27_n168(x)
+ if (x < 1)
+ fun_l28_n882(x)
+ else
+ fun_l28_n280(x)
+ end
+end
+
+def fun_l27_n169(x)
+ if (x < 1)
+ fun_l28_n824(x)
+ else
+ fun_l28_n672(x)
+ end
+end
+
+def fun_l27_n170(x)
+ if (x < 1)
+ fun_l28_n455(x)
+ else
+ fun_l28_n621(x)
+ end
+end
+
+def fun_l27_n171(x)
+ if (x < 1)
+ fun_l28_n594(x)
+ else
+ fun_l28_n143(x)
+ end
+end
+
+def fun_l27_n172(x)
+ if (x < 1)
+ fun_l28_n414(x)
+ else
+ fun_l28_n371(x)
+ end
+end
+
+def fun_l27_n173(x)
+ if (x < 1)
+ fun_l28_n2(x)
+ else
+ fun_l28_n883(x)
+ end
+end
+
+def fun_l27_n174(x)
+ if (x < 1)
+ fun_l28_n710(x)
+ else
+ fun_l28_n322(x)
+ end
+end
+
+def fun_l27_n175(x)
+ if (x < 1)
+ fun_l28_n271(x)
+ else
+ fun_l28_n110(x)
+ end
+end
+
+def fun_l27_n176(x)
+ if (x < 1)
+ fun_l28_n100(x)
+ else
+ fun_l28_n870(x)
+ end
+end
+
+def fun_l27_n177(x)
+ if (x < 1)
+ fun_l28_n446(x)
+ else
+ fun_l28_n742(x)
+ end
+end
+
+def fun_l27_n178(x)
+ if (x < 1)
+ fun_l28_n175(x)
+ else
+ fun_l28_n170(x)
+ end
+end
+
+def fun_l27_n179(x)
+ if (x < 1)
+ fun_l28_n724(x)
+ else
+ fun_l28_n364(x)
+ end
+end
+
+def fun_l27_n180(x)
+ if (x < 1)
+ fun_l28_n167(x)
+ else
+ fun_l28_n826(x)
+ end
+end
+
+def fun_l27_n181(x)
+ if (x < 1)
+ fun_l28_n65(x)
+ else
+ fun_l28_n375(x)
+ end
+end
+
+def fun_l27_n182(x)
+ if (x < 1)
+ fun_l28_n709(x)
+ else
+ fun_l28_n62(x)
+ end
+end
+
+def fun_l27_n183(x)
+ if (x < 1)
+ fun_l28_n584(x)
+ else
+ fun_l28_n611(x)
+ end
+end
+
+def fun_l27_n184(x)
+ if (x < 1)
+ fun_l28_n442(x)
+ else
+ fun_l28_n174(x)
+ end
+end
+
+def fun_l27_n185(x)
+ if (x < 1)
+ fun_l28_n684(x)
+ else
+ fun_l28_n768(x)
+ end
+end
+
+def fun_l27_n186(x)
+ if (x < 1)
+ fun_l28_n424(x)
+ else
+ fun_l28_n207(x)
+ end
+end
+
+def fun_l27_n187(x)
+ if (x < 1)
+ fun_l28_n670(x)
+ else
+ fun_l28_n970(x)
+ end
+end
+
+def fun_l27_n188(x)
+ if (x < 1)
+ fun_l28_n470(x)
+ else
+ fun_l28_n774(x)
+ end
+end
+
+def fun_l27_n189(x)
+ if (x < 1)
+ fun_l28_n58(x)
+ else
+ fun_l28_n578(x)
+ end
+end
+
+def fun_l27_n190(x)
+ if (x < 1)
+ fun_l28_n697(x)
+ else
+ fun_l28_n310(x)
+ end
+end
+
+def fun_l27_n191(x)
+ if (x < 1)
+ fun_l28_n493(x)
+ else
+ fun_l28_n56(x)
+ end
+end
+
+def fun_l27_n192(x)
+ if (x < 1)
+ fun_l28_n12(x)
+ else
+ fun_l28_n471(x)
+ end
+end
+
+def fun_l27_n193(x)
+ if (x < 1)
+ fun_l28_n306(x)
+ else
+ fun_l28_n10(x)
+ end
+end
+
+def fun_l27_n194(x)
+ if (x < 1)
+ fun_l28_n87(x)
+ else
+ fun_l28_n59(x)
+ end
+end
+
+def fun_l27_n195(x)
+ if (x < 1)
+ fun_l28_n207(x)
+ else
+ fun_l28_n555(x)
+ end
+end
+
+def fun_l27_n196(x)
+ if (x < 1)
+ fun_l28_n563(x)
+ else
+ fun_l28_n256(x)
+ end
+end
+
+def fun_l27_n197(x)
+ if (x < 1)
+ fun_l28_n14(x)
+ else
+ fun_l28_n895(x)
+ end
+end
+
+def fun_l27_n198(x)
+ if (x < 1)
+ fun_l28_n986(x)
+ else
+ fun_l28_n287(x)
+ end
+end
+
+def fun_l27_n199(x)
+ if (x < 1)
+ fun_l28_n810(x)
+ else
+ fun_l28_n66(x)
+ end
+end
+
+def fun_l27_n200(x)
+ if (x < 1)
+ fun_l28_n457(x)
+ else
+ fun_l28_n186(x)
+ end
+end
+
+def fun_l27_n201(x)
+ if (x < 1)
+ fun_l28_n580(x)
+ else
+ fun_l28_n248(x)
+ end
+end
+
+def fun_l27_n202(x)
+ if (x < 1)
+ fun_l28_n9(x)
+ else
+ fun_l28_n66(x)
+ end
+end
+
+def fun_l27_n203(x)
+ if (x < 1)
+ fun_l28_n659(x)
+ else
+ fun_l28_n403(x)
+ end
+end
+
+def fun_l27_n204(x)
+ if (x < 1)
+ fun_l28_n66(x)
+ else
+ fun_l28_n524(x)
+ end
+end
+
+def fun_l27_n205(x)
+ if (x < 1)
+ fun_l28_n754(x)
+ else
+ fun_l28_n46(x)
+ end
+end
+
+def fun_l27_n206(x)
+ if (x < 1)
+ fun_l28_n32(x)
+ else
+ fun_l28_n655(x)
+ end
+end
+
+def fun_l27_n207(x)
+ if (x < 1)
+ fun_l28_n559(x)
+ else
+ fun_l28_n619(x)
+ end
+end
+
+def fun_l27_n208(x)
+ if (x < 1)
+ fun_l28_n251(x)
+ else
+ fun_l28_n410(x)
+ end
+end
+
+def fun_l27_n209(x)
+ if (x < 1)
+ fun_l28_n339(x)
+ else
+ fun_l28_n726(x)
+ end
+end
+
+def fun_l27_n210(x)
+ if (x < 1)
+ fun_l28_n104(x)
+ else
+ fun_l28_n733(x)
+ end
+end
+
+def fun_l27_n211(x)
+ if (x < 1)
+ fun_l28_n500(x)
+ else
+ fun_l28_n654(x)
+ end
+end
+
+def fun_l27_n212(x)
+ if (x < 1)
+ fun_l28_n244(x)
+ else
+ fun_l28_n471(x)
+ end
+end
+
+def fun_l27_n213(x)
+ if (x < 1)
+ fun_l28_n692(x)
+ else
+ fun_l28_n56(x)
+ end
+end
+
+def fun_l27_n214(x)
+ if (x < 1)
+ fun_l28_n54(x)
+ else
+ fun_l28_n753(x)
+ end
+end
+
+def fun_l27_n215(x)
+ if (x < 1)
+ fun_l28_n770(x)
+ else
+ fun_l28_n756(x)
+ end
+end
+
+def fun_l27_n216(x)
+ if (x < 1)
+ fun_l28_n771(x)
+ else
+ fun_l28_n407(x)
+ end
+end
+
+def fun_l27_n217(x)
+ if (x < 1)
+ fun_l28_n728(x)
+ else
+ fun_l28_n361(x)
+ end
+end
+
+def fun_l27_n218(x)
+ if (x < 1)
+ fun_l28_n983(x)
+ else
+ fun_l28_n440(x)
+ end
+end
+
+def fun_l27_n219(x)
+ if (x < 1)
+ fun_l28_n105(x)
+ else
+ fun_l28_n906(x)
+ end
+end
+
+def fun_l27_n220(x)
+ if (x < 1)
+ fun_l28_n694(x)
+ else
+ fun_l28_n792(x)
+ end
+end
+
+def fun_l27_n221(x)
+ if (x < 1)
+ fun_l28_n325(x)
+ else
+ fun_l28_n98(x)
+ end
+end
+
+def fun_l27_n222(x)
+ if (x < 1)
+ fun_l28_n354(x)
+ else
+ fun_l28_n683(x)
+ end
+end
+
+def fun_l27_n223(x)
+ if (x < 1)
+ fun_l28_n236(x)
+ else
+ fun_l28_n999(x)
+ end
+end
+
+def fun_l27_n224(x)
+ if (x < 1)
+ fun_l28_n671(x)
+ else
+ fun_l28_n621(x)
+ end
+end
+
+def fun_l27_n225(x)
+ if (x < 1)
+ fun_l28_n113(x)
+ else
+ fun_l28_n532(x)
+ end
+end
+
+def fun_l27_n226(x)
+ if (x < 1)
+ fun_l28_n43(x)
+ else
+ fun_l28_n449(x)
+ end
+end
+
+def fun_l27_n227(x)
+ if (x < 1)
+ fun_l28_n402(x)
+ else
+ fun_l28_n298(x)
+ end
+end
+
+def fun_l27_n228(x)
+ if (x < 1)
+ fun_l28_n858(x)
+ else
+ fun_l28_n626(x)
+ end
+end
+
+def fun_l27_n229(x)
+ if (x < 1)
+ fun_l28_n596(x)
+ else
+ fun_l28_n21(x)
+ end
+end
+
+def fun_l27_n230(x)
+ if (x < 1)
+ fun_l28_n713(x)
+ else
+ fun_l28_n755(x)
+ end
+end
+
+def fun_l27_n231(x)
+ if (x < 1)
+ fun_l28_n59(x)
+ else
+ fun_l28_n695(x)
+ end
+end
+
+def fun_l27_n232(x)
+ if (x < 1)
+ fun_l28_n715(x)
+ else
+ fun_l28_n614(x)
+ end
+end
+
+def fun_l27_n233(x)
+ if (x < 1)
+ fun_l28_n124(x)
+ else
+ fun_l28_n877(x)
+ end
+end
+
+def fun_l27_n234(x)
+ if (x < 1)
+ fun_l28_n563(x)
+ else
+ fun_l28_n273(x)
+ end
+end
+
+def fun_l27_n235(x)
+ if (x < 1)
+ fun_l28_n331(x)
+ else
+ fun_l28_n866(x)
+ end
+end
+
+def fun_l27_n236(x)
+ if (x < 1)
+ fun_l28_n950(x)
+ else
+ fun_l28_n765(x)
+ end
+end
+
+def fun_l27_n237(x)
+ if (x < 1)
+ fun_l28_n550(x)
+ else
+ fun_l28_n133(x)
+ end
+end
+
+def fun_l27_n238(x)
+ if (x < 1)
+ fun_l28_n0(x)
+ else
+ fun_l28_n749(x)
+ end
+end
+
+def fun_l27_n239(x)
+ if (x < 1)
+ fun_l28_n578(x)
+ else
+ fun_l28_n692(x)
+ end
+end
+
+def fun_l27_n240(x)
+ if (x < 1)
+ fun_l28_n111(x)
+ else
+ fun_l28_n301(x)
+ end
+end
+
+def fun_l27_n241(x)
+ if (x < 1)
+ fun_l28_n191(x)
+ else
+ fun_l28_n272(x)
+ end
+end
+
+def fun_l27_n242(x)
+ if (x < 1)
+ fun_l28_n547(x)
+ else
+ fun_l28_n425(x)
+ end
+end
+
+def fun_l27_n243(x)
+ if (x < 1)
+ fun_l28_n173(x)
+ else
+ fun_l28_n101(x)
+ end
+end
+
+def fun_l27_n244(x)
+ if (x < 1)
+ fun_l28_n511(x)
+ else
+ fun_l28_n758(x)
+ end
+end
+
+def fun_l27_n245(x)
+ if (x < 1)
+ fun_l28_n272(x)
+ else
+ fun_l28_n497(x)
+ end
+end
+
+def fun_l27_n246(x)
+ if (x < 1)
+ fun_l28_n59(x)
+ else
+ fun_l28_n348(x)
+ end
+end
+
+def fun_l27_n247(x)
+ if (x < 1)
+ fun_l28_n583(x)
+ else
+ fun_l28_n730(x)
+ end
+end
+
+def fun_l27_n248(x)
+ if (x < 1)
+ fun_l28_n635(x)
+ else
+ fun_l28_n714(x)
+ end
+end
+
+def fun_l27_n249(x)
+ if (x < 1)
+ fun_l28_n815(x)
+ else
+ fun_l28_n844(x)
+ end
+end
+
+def fun_l27_n250(x)
+ if (x < 1)
+ fun_l28_n694(x)
+ else
+ fun_l28_n869(x)
+ end
+end
+
+def fun_l27_n251(x)
+ if (x < 1)
+ fun_l28_n681(x)
+ else
+ fun_l28_n894(x)
+ end
+end
+
+def fun_l27_n252(x)
+ if (x < 1)
+ fun_l28_n756(x)
+ else
+ fun_l28_n657(x)
+ end
+end
+
+def fun_l27_n253(x)
+ if (x < 1)
+ fun_l28_n392(x)
+ else
+ fun_l28_n706(x)
+ end
+end
+
+def fun_l27_n254(x)
+ if (x < 1)
+ fun_l28_n267(x)
+ else
+ fun_l28_n238(x)
+ end
+end
+
+def fun_l27_n255(x)
+ if (x < 1)
+ fun_l28_n914(x)
+ else
+ fun_l28_n574(x)
+ end
+end
+
+def fun_l27_n256(x)
+ if (x < 1)
+ fun_l28_n872(x)
+ else
+ fun_l28_n269(x)
+ end
+end
+
+def fun_l27_n257(x)
+ if (x < 1)
+ fun_l28_n454(x)
+ else
+ fun_l28_n485(x)
+ end
+end
+
+def fun_l27_n258(x)
+ if (x < 1)
+ fun_l28_n994(x)
+ else
+ fun_l28_n83(x)
+ end
+end
+
+def fun_l27_n259(x)
+ if (x < 1)
+ fun_l28_n41(x)
+ else
+ fun_l28_n495(x)
+ end
+end
+
+def fun_l27_n260(x)
+ if (x < 1)
+ fun_l28_n75(x)
+ else
+ fun_l28_n508(x)
+ end
+end
+
+def fun_l27_n261(x)
+ if (x < 1)
+ fun_l28_n684(x)
+ else
+ fun_l28_n524(x)
+ end
+end
+
+def fun_l27_n262(x)
+ if (x < 1)
+ fun_l28_n78(x)
+ else
+ fun_l28_n563(x)
+ end
+end
+
+def fun_l27_n263(x)
+ if (x < 1)
+ fun_l28_n227(x)
+ else
+ fun_l28_n359(x)
+ end
+end
+
+def fun_l27_n264(x)
+ if (x < 1)
+ fun_l28_n679(x)
+ else
+ fun_l28_n711(x)
+ end
+end
+
+def fun_l27_n265(x)
+ if (x < 1)
+ fun_l28_n0(x)
+ else
+ fun_l28_n720(x)
+ end
+end
+
+def fun_l27_n266(x)
+ if (x < 1)
+ fun_l28_n384(x)
+ else
+ fun_l28_n915(x)
+ end
+end
+
+def fun_l27_n267(x)
+ if (x < 1)
+ fun_l28_n912(x)
+ else
+ fun_l28_n24(x)
+ end
+end
+
+def fun_l27_n268(x)
+ if (x < 1)
+ fun_l28_n337(x)
+ else
+ fun_l28_n880(x)
+ end
+end
+
+def fun_l27_n269(x)
+ if (x < 1)
+ fun_l28_n84(x)
+ else
+ fun_l28_n387(x)
+ end
+end
+
+def fun_l27_n270(x)
+ if (x < 1)
+ fun_l28_n155(x)
+ else
+ fun_l28_n705(x)
+ end
+end
+
+def fun_l27_n271(x)
+ if (x < 1)
+ fun_l28_n159(x)
+ else
+ fun_l28_n815(x)
+ end
+end
+
+def fun_l27_n272(x)
+ if (x < 1)
+ fun_l28_n182(x)
+ else
+ fun_l28_n210(x)
+ end
+end
+
+def fun_l27_n273(x)
+ if (x < 1)
+ fun_l28_n446(x)
+ else
+ fun_l28_n524(x)
+ end
+end
+
+def fun_l27_n274(x)
+ if (x < 1)
+ fun_l28_n828(x)
+ else
+ fun_l28_n14(x)
+ end
+end
+
+def fun_l27_n275(x)
+ if (x < 1)
+ fun_l28_n176(x)
+ else
+ fun_l28_n857(x)
+ end
+end
+
+def fun_l27_n276(x)
+ if (x < 1)
+ fun_l28_n39(x)
+ else
+ fun_l28_n973(x)
+ end
+end
+
+def fun_l27_n277(x)
+ if (x < 1)
+ fun_l28_n310(x)
+ else
+ fun_l28_n900(x)
+ end
+end
+
+def fun_l27_n278(x)
+ if (x < 1)
+ fun_l28_n729(x)
+ else
+ fun_l28_n544(x)
+ end
+end
+
+def fun_l27_n279(x)
+ if (x < 1)
+ fun_l28_n111(x)
+ else
+ fun_l28_n939(x)
+ end
+end
+
+def fun_l27_n280(x)
+ if (x < 1)
+ fun_l28_n102(x)
+ else
+ fun_l28_n658(x)
+ end
+end
+
+def fun_l27_n281(x)
+ if (x < 1)
+ fun_l28_n186(x)
+ else
+ fun_l28_n939(x)
+ end
+end
+
+def fun_l27_n282(x)
+ if (x < 1)
+ fun_l28_n276(x)
+ else
+ fun_l28_n428(x)
+ end
+end
+
+def fun_l27_n283(x)
+ if (x < 1)
+ fun_l28_n137(x)
+ else
+ fun_l28_n876(x)
+ end
+end
+
+def fun_l27_n284(x)
+ if (x < 1)
+ fun_l28_n31(x)
+ else
+ fun_l28_n351(x)
+ end
+end
+
+def fun_l27_n285(x)
+ if (x < 1)
+ fun_l28_n143(x)
+ else
+ fun_l28_n192(x)
+ end
+end
+
+def fun_l27_n286(x)
+ if (x < 1)
+ fun_l28_n63(x)
+ else
+ fun_l28_n764(x)
+ end
+end
+
+def fun_l27_n287(x)
+ if (x < 1)
+ fun_l28_n361(x)
+ else
+ fun_l28_n512(x)
+ end
+end
+
+def fun_l27_n288(x)
+ if (x < 1)
+ fun_l28_n817(x)
+ else
+ fun_l28_n997(x)
+ end
+end
+
+def fun_l27_n289(x)
+ if (x < 1)
+ fun_l28_n837(x)
+ else
+ fun_l28_n834(x)
+ end
+end
+
+def fun_l27_n290(x)
+ if (x < 1)
+ fun_l28_n436(x)
+ else
+ fun_l28_n873(x)
+ end
+end
+
+def fun_l27_n291(x)
+ if (x < 1)
+ fun_l28_n412(x)
+ else
+ fun_l28_n494(x)
+ end
+end
+
+def fun_l27_n292(x)
+ if (x < 1)
+ fun_l28_n794(x)
+ else
+ fun_l28_n972(x)
+ end
+end
+
+def fun_l27_n293(x)
+ if (x < 1)
+ fun_l28_n486(x)
+ else
+ fun_l28_n401(x)
+ end
+end
+
+def fun_l27_n294(x)
+ if (x < 1)
+ fun_l28_n171(x)
+ else
+ fun_l28_n334(x)
+ end
+end
+
+def fun_l27_n295(x)
+ if (x < 1)
+ fun_l28_n681(x)
+ else
+ fun_l28_n753(x)
+ end
+end
+
+def fun_l27_n296(x)
+ if (x < 1)
+ fun_l28_n541(x)
+ else
+ fun_l28_n855(x)
+ end
+end
+
+def fun_l27_n297(x)
+ if (x < 1)
+ fun_l28_n270(x)
+ else
+ fun_l28_n257(x)
+ end
+end
+
+def fun_l27_n298(x)
+ if (x < 1)
+ fun_l28_n923(x)
+ else
+ fun_l28_n997(x)
+ end
+end
+
+def fun_l27_n299(x)
+ if (x < 1)
+ fun_l28_n508(x)
+ else
+ fun_l28_n649(x)
+ end
+end
+
+def fun_l27_n300(x)
+ if (x < 1)
+ fun_l28_n351(x)
+ else
+ fun_l28_n966(x)
+ end
+end
+
+def fun_l27_n301(x)
+ if (x < 1)
+ fun_l28_n622(x)
+ else
+ fun_l28_n436(x)
+ end
+end
+
+def fun_l27_n302(x)
+ if (x < 1)
+ fun_l28_n723(x)
+ else
+ fun_l28_n261(x)
+ end
+end
+
+def fun_l27_n303(x)
+ if (x < 1)
+ fun_l28_n269(x)
+ else
+ fun_l28_n483(x)
+ end
+end
+
+def fun_l27_n304(x)
+ if (x < 1)
+ fun_l28_n449(x)
+ else
+ fun_l28_n5(x)
+ end
+end
+
+def fun_l27_n305(x)
+ if (x < 1)
+ fun_l28_n967(x)
+ else
+ fun_l28_n967(x)
+ end
+end
+
+def fun_l27_n306(x)
+ if (x < 1)
+ fun_l28_n866(x)
+ else
+ fun_l28_n590(x)
+ end
+end
+
+def fun_l27_n307(x)
+ if (x < 1)
+ fun_l28_n145(x)
+ else
+ fun_l28_n75(x)
+ end
+end
+
+def fun_l27_n308(x)
+ if (x < 1)
+ fun_l28_n329(x)
+ else
+ fun_l28_n834(x)
+ end
+end
+
+def fun_l27_n309(x)
+ if (x < 1)
+ fun_l28_n668(x)
+ else
+ fun_l28_n909(x)
+ end
+end
+
+def fun_l27_n310(x)
+ if (x < 1)
+ fun_l28_n70(x)
+ else
+ fun_l28_n311(x)
+ end
+end
+
+def fun_l27_n311(x)
+ if (x < 1)
+ fun_l28_n669(x)
+ else
+ fun_l28_n90(x)
+ end
+end
+
+def fun_l27_n312(x)
+ if (x < 1)
+ fun_l28_n805(x)
+ else
+ fun_l28_n558(x)
+ end
+end
+
+def fun_l27_n313(x)
+ if (x < 1)
+ fun_l28_n493(x)
+ else
+ fun_l28_n642(x)
+ end
+end
+
+def fun_l27_n314(x)
+ if (x < 1)
+ fun_l28_n285(x)
+ else
+ fun_l28_n968(x)
+ end
+end
+
+def fun_l27_n315(x)
+ if (x < 1)
+ fun_l28_n806(x)
+ else
+ fun_l28_n731(x)
+ end
+end
+
+def fun_l27_n316(x)
+ if (x < 1)
+ fun_l28_n284(x)
+ else
+ fun_l28_n441(x)
+ end
+end
+
+def fun_l27_n317(x)
+ if (x < 1)
+ fun_l28_n644(x)
+ else
+ fun_l28_n16(x)
+ end
+end
+
+def fun_l27_n318(x)
+ if (x < 1)
+ fun_l28_n411(x)
+ else
+ fun_l28_n739(x)
+ end
+end
+
+def fun_l27_n319(x)
+ if (x < 1)
+ fun_l28_n462(x)
+ else
+ fun_l28_n680(x)
+ end
+end
+
+def fun_l27_n320(x)
+ if (x < 1)
+ fun_l28_n126(x)
+ else
+ fun_l28_n558(x)
+ end
+end
+
+def fun_l27_n321(x)
+ if (x < 1)
+ fun_l28_n869(x)
+ else
+ fun_l28_n581(x)
+ end
+end
+
+def fun_l27_n322(x)
+ if (x < 1)
+ fun_l28_n25(x)
+ else
+ fun_l28_n352(x)
+ end
+end
+
+def fun_l27_n323(x)
+ if (x < 1)
+ fun_l28_n203(x)
+ else
+ fun_l28_n776(x)
+ end
+end
+
+def fun_l27_n324(x)
+ if (x < 1)
+ fun_l28_n6(x)
+ else
+ fun_l28_n833(x)
+ end
+end
+
+def fun_l27_n325(x)
+ if (x < 1)
+ fun_l28_n817(x)
+ else
+ fun_l28_n258(x)
+ end
+end
+
+def fun_l27_n326(x)
+ if (x < 1)
+ fun_l28_n607(x)
+ else
+ fun_l28_n813(x)
+ end
+end
+
+def fun_l27_n327(x)
+ if (x < 1)
+ fun_l28_n761(x)
+ else
+ fun_l28_n893(x)
+ end
+end
+
+def fun_l27_n328(x)
+ if (x < 1)
+ fun_l28_n861(x)
+ else
+ fun_l28_n879(x)
+ end
+end
+
+def fun_l27_n329(x)
+ if (x < 1)
+ fun_l28_n682(x)
+ else
+ fun_l28_n680(x)
+ end
+end
+
+def fun_l27_n330(x)
+ if (x < 1)
+ fun_l28_n61(x)
+ else
+ fun_l28_n481(x)
+ end
+end
+
+def fun_l27_n331(x)
+ if (x < 1)
+ fun_l28_n738(x)
+ else
+ fun_l28_n230(x)
+ end
+end
+
+def fun_l27_n332(x)
+ if (x < 1)
+ fun_l28_n45(x)
+ else
+ fun_l28_n279(x)
+ end
+end
+
+def fun_l27_n333(x)
+ if (x < 1)
+ fun_l28_n24(x)
+ else
+ fun_l28_n561(x)
+ end
+end
+
+def fun_l27_n334(x)
+ if (x < 1)
+ fun_l28_n459(x)
+ else
+ fun_l28_n594(x)
+ end
+end
+
+def fun_l27_n335(x)
+ if (x < 1)
+ fun_l28_n695(x)
+ else
+ fun_l28_n513(x)
+ end
+end
+
+def fun_l27_n336(x)
+ if (x < 1)
+ fun_l28_n729(x)
+ else
+ fun_l28_n89(x)
+ end
+end
+
+def fun_l27_n337(x)
+ if (x < 1)
+ fun_l28_n509(x)
+ else
+ fun_l28_n574(x)
+ end
+end
+
+def fun_l27_n338(x)
+ if (x < 1)
+ fun_l28_n80(x)
+ else
+ fun_l28_n448(x)
+ end
+end
+
+def fun_l27_n339(x)
+ if (x < 1)
+ fun_l28_n279(x)
+ else
+ fun_l28_n177(x)
+ end
+end
+
+def fun_l27_n340(x)
+ if (x < 1)
+ fun_l28_n508(x)
+ else
+ fun_l28_n706(x)
+ end
+end
+
+def fun_l27_n341(x)
+ if (x < 1)
+ fun_l28_n790(x)
+ else
+ fun_l28_n774(x)
+ end
+end
+
+def fun_l27_n342(x)
+ if (x < 1)
+ fun_l28_n606(x)
+ else
+ fun_l28_n642(x)
+ end
+end
+
+def fun_l27_n343(x)
+ if (x < 1)
+ fun_l28_n108(x)
+ else
+ fun_l28_n539(x)
+ end
+end
+
+def fun_l27_n344(x)
+ if (x < 1)
+ fun_l28_n418(x)
+ else
+ fun_l28_n687(x)
+ end
+end
+
+def fun_l27_n345(x)
+ if (x < 1)
+ fun_l28_n386(x)
+ else
+ fun_l28_n170(x)
+ end
+end
+
+def fun_l27_n346(x)
+ if (x < 1)
+ fun_l28_n648(x)
+ else
+ fun_l28_n340(x)
+ end
+end
+
+def fun_l27_n347(x)
+ if (x < 1)
+ fun_l28_n516(x)
+ else
+ fun_l28_n586(x)
+ end
+end
+
+def fun_l27_n348(x)
+ if (x < 1)
+ fun_l28_n646(x)
+ else
+ fun_l28_n448(x)
+ end
+end
+
+def fun_l27_n349(x)
+ if (x < 1)
+ fun_l28_n378(x)
+ else
+ fun_l28_n413(x)
+ end
+end
+
+def fun_l27_n350(x)
+ if (x < 1)
+ fun_l28_n885(x)
+ else
+ fun_l28_n932(x)
+ end
+end
+
+def fun_l27_n351(x)
+ if (x < 1)
+ fun_l28_n9(x)
+ else
+ fun_l28_n843(x)
+ end
+end
+
+def fun_l27_n352(x)
+ if (x < 1)
+ fun_l28_n502(x)
+ else
+ fun_l28_n229(x)
+ end
+end
+
+def fun_l27_n353(x)
+ if (x < 1)
+ fun_l28_n752(x)
+ else
+ fun_l28_n677(x)
+ end
+end
+
+def fun_l27_n354(x)
+ if (x < 1)
+ fun_l28_n246(x)
+ else
+ fun_l28_n32(x)
+ end
+end
+
+def fun_l27_n355(x)
+ if (x < 1)
+ fun_l28_n969(x)
+ else
+ fun_l28_n933(x)
+ end
+end
+
+def fun_l27_n356(x)
+ if (x < 1)
+ fun_l28_n44(x)
+ else
+ fun_l28_n704(x)
+ end
+end
+
+def fun_l27_n357(x)
+ if (x < 1)
+ fun_l28_n863(x)
+ else
+ fun_l28_n324(x)
+ end
+end
+
+def fun_l27_n358(x)
+ if (x < 1)
+ fun_l28_n467(x)
+ else
+ fun_l28_n418(x)
+ end
+end
+
+def fun_l27_n359(x)
+ if (x < 1)
+ fun_l28_n222(x)
+ else
+ fun_l28_n138(x)
+ end
+end
+
+def fun_l27_n360(x)
+ if (x < 1)
+ fun_l28_n261(x)
+ else
+ fun_l28_n605(x)
+ end
+end
+
+def fun_l27_n361(x)
+ if (x < 1)
+ fun_l28_n470(x)
+ else
+ fun_l28_n519(x)
+ end
+end
+
+def fun_l27_n362(x)
+ if (x < 1)
+ fun_l28_n717(x)
+ else
+ fun_l28_n817(x)
+ end
+end
+
+def fun_l27_n363(x)
+ if (x < 1)
+ fun_l28_n591(x)
+ else
+ fun_l28_n537(x)
+ end
+end
+
+def fun_l27_n364(x)
+ if (x < 1)
+ fun_l28_n733(x)
+ else
+ fun_l28_n222(x)
+ end
+end
+
+def fun_l27_n365(x)
+ if (x < 1)
+ fun_l28_n137(x)
+ else
+ fun_l28_n225(x)
+ end
+end
+
+def fun_l27_n366(x)
+ if (x < 1)
+ fun_l28_n610(x)
+ else
+ fun_l28_n870(x)
+ end
+end
+
+def fun_l27_n367(x)
+ if (x < 1)
+ fun_l28_n697(x)
+ else
+ fun_l28_n866(x)
+ end
+end
+
+def fun_l27_n368(x)
+ if (x < 1)
+ fun_l28_n902(x)
+ else
+ fun_l28_n827(x)
+ end
+end
+
+def fun_l27_n369(x)
+ if (x < 1)
+ fun_l28_n769(x)
+ else
+ fun_l28_n238(x)
+ end
+end
+
+def fun_l27_n370(x)
+ if (x < 1)
+ fun_l28_n66(x)
+ else
+ fun_l28_n958(x)
+ end
+end
+
+def fun_l27_n371(x)
+ if (x < 1)
+ fun_l28_n847(x)
+ else
+ fun_l28_n177(x)
+ end
+end
+
+def fun_l27_n372(x)
+ if (x < 1)
+ fun_l28_n64(x)
+ else
+ fun_l28_n198(x)
+ end
+end
+
+def fun_l27_n373(x)
+ if (x < 1)
+ fun_l28_n36(x)
+ else
+ fun_l28_n282(x)
+ end
+end
+
+def fun_l27_n374(x)
+ if (x < 1)
+ fun_l28_n647(x)
+ else
+ fun_l28_n228(x)
+ end
+end
+
+def fun_l27_n375(x)
+ if (x < 1)
+ fun_l28_n737(x)
+ else
+ fun_l28_n689(x)
+ end
+end
+
+def fun_l27_n376(x)
+ if (x < 1)
+ fun_l28_n336(x)
+ else
+ fun_l28_n20(x)
+ end
+end
+
+def fun_l27_n377(x)
+ if (x < 1)
+ fun_l28_n859(x)
+ else
+ fun_l28_n661(x)
+ end
+end
+
+def fun_l27_n378(x)
+ if (x < 1)
+ fun_l28_n148(x)
+ else
+ fun_l28_n197(x)
+ end
+end
+
+def fun_l27_n379(x)
+ if (x < 1)
+ fun_l28_n986(x)
+ else
+ fun_l28_n441(x)
+ end
+end
+
+def fun_l27_n380(x)
+ if (x < 1)
+ fun_l28_n966(x)
+ else
+ fun_l28_n994(x)
+ end
+end
+
+def fun_l27_n381(x)
+ if (x < 1)
+ fun_l28_n546(x)
+ else
+ fun_l28_n687(x)
+ end
+end
+
+def fun_l27_n382(x)
+ if (x < 1)
+ fun_l28_n63(x)
+ else
+ fun_l28_n366(x)
+ end
+end
+
+def fun_l27_n383(x)
+ if (x < 1)
+ fun_l28_n146(x)
+ else
+ fun_l28_n96(x)
+ end
+end
+
+def fun_l27_n384(x)
+ if (x < 1)
+ fun_l28_n747(x)
+ else
+ fun_l28_n168(x)
+ end
+end
+
+def fun_l27_n385(x)
+ if (x < 1)
+ fun_l28_n556(x)
+ else
+ fun_l28_n194(x)
+ end
+end
+
+def fun_l27_n386(x)
+ if (x < 1)
+ fun_l28_n180(x)
+ else
+ fun_l28_n648(x)
+ end
+end
+
+def fun_l27_n387(x)
+ if (x < 1)
+ fun_l28_n898(x)
+ else
+ fun_l28_n499(x)
+ end
+end
+
+def fun_l27_n388(x)
+ if (x < 1)
+ fun_l28_n720(x)
+ else
+ fun_l28_n996(x)
+ end
+end
+
+def fun_l27_n389(x)
+ if (x < 1)
+ fun_l28_n743(x)
+ else
+ fun_l28_n781(x)
+ end
+end
+
+def fun_l27_n390(x)
+ if (x < 1)
+ fun_l28_n372(x)
+ else
+ fun_l28_n907(x)
+ end
+end
+
+def fun_l27_n391(x)
+ if (x < 1)
+ fun_l28_n893(x)
+ else
+ fun_l28_n911(x)
+ end
+end
+
+def fun_l27_n392(x)
+ if (x < 1)
+ fun_l28_n304(x)
+ else
+ fun_l28_n164(x)
+ end
+end
+
+def fun_l27_n393(x)
+ if (x < 1)
+ fun_l28_n212(x)
+ else
+ fun_l28_n575(x)
+ end
+end
+
+def fun_l27_n394(x)
+ if (x < 1)
+ fun_l28_n279(x)
+ else
+ fun_l28_n306(x)
+ end
+end
+
+def fun_l27_n395(x)
+ if (x < 1)
+ fun_l28_n662(x)
+ else
+ fun_l28_n838(x)
+ end
+end
+
+def fun_l27_n396(x)
+ if (x < 1)
+ fun_l28_n882(x)
+ else
+ fun_l28_n321(x)
+ end
+end
+
+def fun_l27_n397(x)
+ if (x < 1)
+ fun_l28_n996(x)
+ else
+ fun_l28_n170(x)
+ end
+end
+
+def fun_l27_n398(x)
+ if (x < 1)
+ fun_l28_n309(x)
+ else
+ fun_l28_n805(x)
+ end
+end
+
+def fun_l27_n399(x)
+ if (x < 1)
+ fun_l28_n584(x)
+ else
+ fun_l28_n304(x)
+ end
+end
+
+def fun_l27_n400(x)
+ if (x < 1)
+ fun_l28_n575(x)
+ else
+ fun_l28_n405(x)
+ end
+end
+
+def fun_l27_n401(x)
+ if (x < 1)
+ fun_l28_n507(x)
+ else
+ fun_l28_n773(x)
+ end
+end
+
+def fun_l27_n402(x)
+ if (x < 1)
+ fun_l28_n759(x)
+ else
+ fun_l28_n583(x)
+ end
+end
+
+def fun_l27_n403(x)
+ if (x < 1)
+ fun_l28_n689(x)
+ else
+ fun_l28_n511(x)
+ end
+end
+
+def fun_l27_n404(x)
+ if (x < 1)
+ fun_l28_n706(x)
+ else
+ fun_l28_n258(x)
+ end
+end
+
+def fun_l27_n405(x)
+ if (x < 1)
+ fun_l28_n736(x)
+ else
+ fun_l28_n482(x)
+ end
+end
+
+def fun_l27_n406(x)
+ if (x < 1)
+ fun_l28_n851(x)
+ else
+ fun_l28_n898(x)
+ end
+end
+
+def fun_l27_n407(x)
+ if (x < 1)
+ fun_l28_n86(x)
+ else
+ fun_l28_n913(x)
+ end
+end
+
+def fun_l27_n408(x)
+ if (x < 1)
+ fun_l28_n277(x)
+ else
+ fun_l28_n960(x)
+ end
+end
+
+def fun_l27_n409(x)
+ if (x < 1)
+ fun_l28_n137(x)
+ else
+ fun_l28_n789(x)
+ end
+end
+
+def fun_l27_n410(x)
+ if (x < 1)
+ fun_l28_n23(x)
+ else
+ fun_l28_n633(x)
+ end
+end
+
+def fun_l27_n411(x)
+ if (x < 1)
+ fun_l28_n246(x)
+ else
+ fun_l28_n560(x)
+ end
+end
+
+def fun_l27_n412(x)
+ if (x < 1)
+ fun_l28_n218(x)
+ else
+ fun_l28_n66(x)
+ end
+end
+
+def fun_l27_n413(x)
+ if (x < 1)
+ fun_l28_n680(x)
+ else
+ fun_l28_n9(x)
+ end
+end
+
+def fun_l27_n414(x)
+ if (x < 1)
+ fun_l28_n693(x)
+ else
+ fun_l28_n625(x)
+ end
+end
+
+def fun_l27_n415(x)
+ if (x < 1)
+ fun_l28_n560(x)
+ else
+ fun_l28_n739(x)
+ end
+end
+
+def fun_l27_n416(x)
+ if (x < 1)
+ fun_l28_n467(x)
+ else
+ fun_l28_n542(x)
+ end
+end
+
+def fun_l27_n417(x)
+ if (x < 1)
+ fun_l28_n364(x)
+ else
+ fun_l28_n468(x)
+ end
+end
+
+def fun_l27_n418(x)
+ if (x < 1)
+ fun_l28_n123(x)
+ else
+ fun_l28_n775(x)
+ end
+end
+
+def fun_l27_n419(x)
+ if (x < 1)
+ fun_l28_n17(x)
+ else
+ fun_l28_n875(x)
+ end
+end
+
+def fun_l27_n420(x)
+ if (x < 1)
+ fun_l28_n596(x)
+ else
+ fun_l28_n163(x)
+ end
+end
+
+def fun_l27_n421(x)
+ if (x < 1)
+ fun_l28_n638(x)
+ else
+ fun_l28_n426(x)
+ end
+end
+
+def fun_l27_n422(x)
+ if (x < 1)
+ fun_l28_n637(x)
+ else
+ fun_l28_n696(x)
+ end
+end
+
+def fun_l27_n423(x)
+ if (x < 1)
+ fun_l28_n299(x)
+ else
+ fun_l28_n218(x)
+ end
+end
+
+def fun_l27_n424(x)
+ if (x < 1)
+ fun_l28_n683(x)
+ else
+ fun_l28_n248(x)
+ end
+end
+
+def fun_l27_n425(x)
+ if (x < 1)
+ fun_l28_n272(x)
+ else
+ fun_l28_n359(x)
+ end
+end
+
+def fun_l27_n426(x)
+ if (x < 1)
+ fun_l28_n327(x)
+ else
+ fun_l28_n984(x)
+ end
+end
+
+def fun_l27_n427(x)
+ if (x < 1)
+ fun_l28_n912(x)
+ else
+ fun_l28_n393(x)
+ end
+end
+
+def fun_l27_n428(x)
+ if (x < 1)
+ fun_l28_n842(x)
+ else
+ fun_l28_n919(x)
+ end
+end
+
+def fun_l27_n429(x)
+ if (x < 1)
+ fun_l28_n721(x)
+ else
+ fun_l28_n36(x)
+ end
+end
+
+def fun_l27_n430(x)
+ if (x < 1)
+ fun_l28_n16(x)
+ else
+ fun_l28_n418(x)
+ end
+end
+
+def fun_l27_n431(x)
+ if (x < 1)
+ fun_l28_n747(x)
+ else
+ fun_l28_n132(x)
+ end
+end
+
+def fun_l27_n432(x)
+ if (x < 1)
+ fun_l28_n906(x)
+ else
+ fun_l28_n718(x)
+ end
+end
+
+def fun_l27_n433(x)
+ if (x < 1)
+ fun_l28_n508(x)
+ else
+ fun_l28_n862(x)
+ end
+end
+
+def fun_l27_n434(x)
+ if (x < 1)
+ fun_l28_n478(x)
+ else
+ fun_l28_n542(x)
+ end
+end
+
+def fun_l27_n435(x)
+ if (x < 1)
+ fun_l28_n186(x)
+ else
+ fun_l28_n976(x)
+ end
+end
+
+def fun_l27_n436(x)
+ if (x < 1)
+ fun_l28_n637(x)
+ else
+ fun_l28_n49(x)
+ end
+end
+
+def fun_l27_n437(x)
+ if (x < 1)
+ fun_l28_n242(x)
+ else
+ fun_l28_n774(x)
+ end
+end
+
+def fun_l27_n438(x)
+ if (x < 1)
+ fun_l28_n303(x)
+ else
+ fun_l28_n175(x)
+ end
+end
+
+def fun_l27_n439(x)
+ if (x < 1)
+ fun_l28_n851(x)
+ else
+ fun_l28_n908(x)
+ end
+end
+
+def fun_l27_n440(x)
+ if (x < 1)
+ fun_l28_n139(x)
+ else
+ fun_l28_n473(x)
+ end
+end
+
+def fun_l27_n441(x)
+ if (x < 1)
+ fun_l28_n70(x)
+ else
+ fun_l28_n406(x)
+ end
+end
+
+def fun_l27_n442(x)
+ if (x < 1)
+ fun_l28_n368(x)
+ else
+ fun_l28_n624(x)
+ end
+end
+
+def fun_l27_n443(x)
+ if (x < 1)
+ fun_l28_n900(x)
+ else
+ fun_l28_n173(x)
+ end
+end
+
+def fun_l27_n444(x)
+ if (x < 1)
+ fun_l28_n646(x)
+ else
+ fun_l28_n733(x)
+ end
+end
+
+def fun_l27_n445(x)
+ if (x < 1)
+ fun_l28_n859(x)
+ else
+ fun_l28_n100(x)
+ end
+end
+
+def fun_l27_n446(x)
+ if (x < 1)
+ fun_l28_n418(x)
+ else
+ fun_l28_n765(x)
+ end
+end
+
+def fun_l27_n447(x)
+ if (x < 1)
+ fun_l28_n204(x)
+ else
+ fun_l28_n541(x)
+ end
+end
+
+def fun_l27_n448(x)
+ if (x < 1)
+ fun_l28_n192(x)
+ else
+ fun_l28_n414(x)
+ end
+end
+
+def fun_l27_n449(x)
+ if (x < 1)
+ fun_l28_n904(x)
+ else
+ fun_l28_n247(x)
+ end
+end
+
+def fun_l27_n450(x)
+ if (x < 1)
+ fun_l28_n528(x)
+ else
+ fun_l28_n24(x)
+ end
+end
+
+def fun_l27_n451(x)
+ if (x < 1)
+ fun_l28_n312(x)
+ else
+ fun_l28_n48(x)
+ end
+end
+
+def fun_l27_n452(x)
+ if (x < 1)
+ fun_l28_n169(x)
+ else
+ fun_l28_n37(x)
+ end
+end
+
+def fun_l27_n453(x)
+ if (x < 1)
+ fun_l28_n713(x)
+ else
+ fun_l28_n168(x)
+ end
+end
+
+def fun_l27_n454(x)
+ if (x < 1)
+ fun_l28_n748(x)
+ else
+ fun_l28_n213(x)
+ end
+end
+
+def fun_l27_n455(x)
+ if (x < 1)
+ fun_l28_n157(x)
+ else
+ fun_l28_n444(x)
+ end
+end
+
+def fun_l27_n456(x)
+ if (x < 1)
+ fun_l28_n32(x)
+ else
+ fun_l28_n475(x)
+ end
+end
+
+def fun_l27_n457(x)
+ if (x < 1)
+ fun_l28_n252(x)
+ else
+ fun_l28_n730(x)
+ end
+end
+
+def fun_l27_n458(x)
+ if (x < 1)
+ fun_l28_n261(x)
+ else
+ fun_l28_n576(x)
+ end
+end
+
+def fun_l27_n459(x)
+ if (x < 1)
+ fun_l28_n859(x)
+ else
+ fun_l28_n401(x)
+ end
+end
+
+def fun_l27_n460(x)
+ if (x < 1)
+ fun_l28_n394(x)
+ else
+ fun_l28_n10(x)
+ end
+end
+
+def fun_l27_n461(x)
+ if (x < 1)
+ fun_l28_n89(x)
+ else
+ fun_l28_n402(x)
+ end
+end
+
+def fun_l27_n462(x)
+ if (x < 1)
+ fun_l28_n100(x)
+ else
+ fun_l28_n207(x)
+ end
+end
+
+def fun_l27_n463(x)
+ if (x < 1)
+ fun_l28_n907(x)
+ else
+ fun_l28_n354(x)
+ end
+end
+
+def fun_l27_n464(x)
+ if (x < 1)
+ fun_l28_n612(x)
+ else
+ fun_l28_n31(x)
+ end
+end
+
+def fun_l27_n465(x)
+ if (x < 1)
+ fun_l28_n622(x)
+ else
+ fun_l28_n342(x)
+ end
+end
+
+def fun_l27_n466(x)
+ if (x < 1)
+ fun_l28_n373(x)
+ else
+ fun_l28_n831(x)
+ end
+end
+
+def fun_l27_n467(x)
+ if (x < 1)
+ fun_l28_n858(x)
+ else
+ fun_l28_n233(x)
+ end
+end
+
+def fun_l27_n468(x)
+ if (x < 1)
+ fun_l28_n104(x)
+ else
+ fun_l28_n918(x)
+ end
+end
+
+def fun_l27_n469(x)
+ if (x < 1)
+ fun_l28_n778(x)
+ else
+ fun_l28_n758(x)
+ end
+end
+
+def fun_l27_n470(x)
+ if (x < 1)
+ fun_l28_n695(x)
+ else
+ fun_l28_n217(x)
+ end
+end
+
+def fun_l27_n471(x)
+ if (x < 1)
+ fun_l28_n781(x)
+ else
+ fun_l28_n584(x)
+ end
+end
+
+def fun_l27_n472(x)
+ if (x < 1)
+ fun_l28_n883(x)
+ else
+ fun_l28_n152(x)
+ end
+end
+
+def fun_l27_n473(x)
+ if (x < 1)
+ fun_l28_n525(x)
+ else
+ fun_l28_n369(x)
+ end
+end
+
+def fun_l27_n474(x)
+ if (x < 1)
+ fun_l28_n42(x)
+ else
+ fun_l28_n299(x)
+ end
+end
+
+def fun_l27_n475(x)
+ if (x < 1)
+ fun_l28_n174(x)
+ else
+ fun_l28_n664(x)
+ end
+end
+
+def fun_l27_n476(x)
+ if (x < 1)
+ fun_l28_n489(x)
+ else
+ fun_l28_n296(x)
+ end
+end
+
+def fun_l27_n477(x)
+ if (x < 1)
+ fun_l28_n725(x)
+ else
+ fun_l28_n384(x)
+ end
+end
+
+def fun_l27_n478(x)
+ if (x < 1)
+ fun_l28_n138(x)
+ else
+ fun_l28_n812(x)
+ end
+end
+
+def fun_l27_n479(x)
+ if (x < 1)
+ fun_l28_n161(x)
+ else
+ fun_l28_n786(x)
+ end
+end
+
+def fun_l27_n480(x)
+ if (x < 1)
+ fun_l28_n751(x)
+ else
+ fun_l28_n91(x)
+ end
+end
+
+def fun_l27_n481(x)
+ if (x < 1)
+ fun_l28_n434(x)
+ else
+ fun_l28_n507(x)
+ end
+end
+
+def fun_l27_n482(x)
+ if (x < 1)
+ fun_l28_n101(x)
+ else
+ fun_l28_n809(x)
+ end
+end
+
+def fun_l27_n483(x)
+ if (x < 1)
+ fun_l28_n79(x)
+ else
+ fun_l28_n565(x)
+ end
+end
+
+def fun_l27_n484(x)
+ if (x < 1)
+ fun_l28_n681(x)
+ else
+ fun_l28_n390(x)
+ end
+end
+
+def fun_l27_n485(x)
+ if (x < 1)
+ fun_l28_n950(x)
+ else
+ fun_l28_n262(x)
+ end
+end
+
+def fun_l27_n486(x)
+ if (x < 1)
+ fun_l28_n188(x)
+ else
+ fun_l28_n731(x)
+ end
+end
+
+def fun_l27_n487(x)
+ if (x < 1)
+ fun_l28_n724(x)
+ else
+ fun_l28_n806(x)
+ end
+end
+
+def fun_l27_n488(x)
+ if (x < 1)
+ fun_l28_n680(x)
+ else
+ fun_l28_n475(x)
+ end
+end
+
+def fun_l27_n489(x)
+ if (x < 1)
+ fun_l28_n662(x)
+ else
+ fun_l28_n242(x)
+ end
+end
+
+def fun_l27_n490(x)
+ if (x < 1)
+ fun_l28_n578(x)
+ else
+ fun_l28_n534(x)
+ end
+end
+
+def fun_l27_n491(x)
+ if (x < 1)
+ fun_l28_n173(x)
+ else
+ fun_l28_n239(x)
+ end
+end
+
+def fun_l27_n492(x)
+ if (x < 1)
+ fun_l28_n724(x)
+ else
+ fun_l28_n579(x)
+ end
+end
+
+def fun_l27_n493(x)
+ if (x < 1)
+ fun_l28_n449(x)
+ else
+ fun_l28_n44(x)
+ end
+end
+
+def fun_l27_n494(x)
+ if (x < 1)
+ fun_l28_n180(x)
+ else
+ fun_l28_n836(x)
+ end
+end
+
+def fun_l27_n495(x)
+ if (x < 1)
+ fun_l28_n232(x)
+ else
+ fun_l28_n371(x)
+ end
+end
+
+def fun_l27_n496(x)
+ if (x < 1)
+ fun_l28_n558(x)
+ else
+ fun_l28_n904(x)
+ end
+end
+
+def fun_l27_n497(x)
+ if (x < 1)
+ fun_l28_n324(x)
+ else
+ fun_l28_n85(x)
+ end
+end
+
+def fun_l27_n498(x)
+ if (x < 1)
+ fun_l28_n272(x)
+ else
+ fun_l28_n469(x)
+ end
+end
+
+def fun_l27_n499(x)
+ if (x < 1)
+ fun_l28_n232(x)
+ else
+ fun_l28_n899(x)
+ end
+end
+
+def fun_l27_n500(x)
+ if (x < 1)
+ fun_l28_n654(x)
+ else
+ fun_l28_n390(x)
+ end
+end
+
+def fun_l27_n501(x)
+ if (x < 1)
+ fun_l28_n84(x)
+ else
+ fun_l28_n74(x)
+ end
+end
+
+def fun_l27_n502(x)
+ if (x < 1)
+ fun_l28_n799(x)
+ else
+ fun_l28_n224(x)
+ end
+end
+
+def fun_l27_n503(x)
+ if (x < 1)
+ fun_l28_n635(x)
+ else
+ fun_l28_n770(x)
+ end
+end
+
+def fun_l27_n504(x)
+ if (x < 1)
+ fun_l28_n734(x)
+ else
+ fun_l28_n451(x)
+ end
+end
+
+def fun_l27_n505(x)
+ if (x < 1)
+ fun_l28_n340(x)
+ else
+ fun_l28_n318(x)
+ end
+end
+
+def fun_l27_n506(x)
+ if (x < 1)
+ fun_l28_n521(x)
+ else
+ fun_l28_n590(x)
+ end
+end
+
+def fun_l27_n507(x)
+ if (x < 1)
+ fun_l28_n727(x)
+ else
+ fun_l28_n825(x)
+ end
+end
+
+def fun_l27_n508(x)
+ if (x < 1)
+ fun_l28_n923(x)
+ else
+ fun_l28_n413(x)
+ end
+end
+
+def fun_l27_n509(x)
+ if (x < 1)
+ fun_l28_n825(x)
+ else
+ fun_l28_n235(x)
+ end
+end
+
+def fun_l27_n510(x)
+ if (x < 1)
+ fun_l28_n212(x)
+ else
+ fun_l28_n509(x)
+ end
+end
+
+def fun_l27_n511(x)
+ if (x < 1)
+ fun_l28_n6(x)
+ else
+ fun_l28_n16(x)
+ end
+end
+
+def fun_l27_n512(x)
+ if (x < 1)
+ fun_l28_n409(x)
+ else
+ fun_l28_n473(x)
+ end
+end
+
+def fun_l27_n513(x)
+ if (x < 1)
+ fun_l28_n220(x)
+ else
+ fun_l28_n383(x)
+ end
+end
+
+def fun_l27_n514(x)
+ if (x < 1)
+ fun_l28_n338(x)
+ else
+ fun_l28_n32(x)
+ end
+end
+
+def fun_l27_n515(x)
+ if (x < 1)
+ fun_l28_n218(x)
+ else
+ fun_l28_n307(x)
+ end
+end
+
+def fun_l27_n516(x)
+ if (x < 1)
+ fun_l28_n591(x)
+ else
+ fun_l28_n545(x)
+ end
+end
+
+def fun_l27_n517(x)
+ if (x < 1)
+ fun_l28_n405(x)
+ else
+ fun_l28_n241(x)
+ end
+end
+
+def fun_l27_n518(x)
+ if (x < 1)
+ fun_l28_n545(x)
+ else
+ fun_l28_n215(x)
+ end
+end
+
+def fun_l27_n519(x)
+ if (x < 1)
+ fun_l28_n989(x)
+ else
+ fun_l28_n480(x)
+ end
+end
+
+def fun_l27_n520(x)
+ if (x < 1)
+ fun_l28_n479(x)
+ else
+ fun_l28_n869(x)
+ end
+end
+
+def fun_l27_n521(x)
+ if (x < 1)
+ fun_l28_n376(x)
+ else
+ fun_l28_n216(x)
+ end
+end
+
+def fun_l27_n522(x)
+ if (x < 1)
+ fun_l28_n74(x)
+ else
+ fun_l28_n370(x)
+ end
+end
+
+def fun_l27_n523(x)
+ if (x < 1)
+ fun_l28_n665(x)
+ else
+ fun_l28_n982(x)
+ end
+end
+
+def fun_l27_n524(x)
+ if (x < 1)
+ fun_l28_n412(x)
+ else
+ fun_l28_n515(x)
+ end
+end
+
+def fun_l27_n525(x)
+ if (x < 1)
+ fun_l28_n421(x)
+ else
+ fun_l28_n718(x)
+ end
+end
+
+def fun_l27_n526(x)
+ if (x < 1)
+ fun_l28_n914(x)
+ else
+ fun_l28_n297(x)
+ end
+end
+
+def fun_l27_n527(x)
+ if (x < 1)
+ fun_l28_n134(x)
+ else
+ fun_l28_n602(x)
+ end
+end
+
+def fun_l27_n528(x)
+ if (x < 1)
+ fun_l28_n0(x)
+ else
+ fun_l28_n23(x)
+ end
+end
+
+def fun_l27_n529(x)
+ if (x < 1)
+ fun_l28_n610(x)
+ else
+ fun_l28_n736(x)
+ end
+end
+
+def fun_l27_n530(x)
+ if (x < 1)
+ fun_l28_n350(x)
+ else
+ fun_l28_n51(x)
+ end
+end
+
+def fun_l27_n531(x)
+ if (x < 1)
+ fun_l28_n648(x)
+ else
+ fun_l28_n382(x)
+ end
+end
+
+def fun_l27_n532(x)
+ if (x < 1)
+ fun_l28_n432(x)
+ else
+ fun_l28_n872(x)
+ end
+end
+
+def fun_l27_n533(x)
+ if (x < 1)
+ fun_l28_n747(x)
+ else
+ fun_l28_n588(x)
+ end
+end
+
+def fun_l27_n534(x)
+ if (x < 1)
+ fun_l28_n763(x)
+ else
+ fun_l28_n846(x)
+ end
+end
+
+def fun_l27_n535(x)
+ if (x < 1)
+ fun_l28_n300(x)
+ else
+ fun_l28_n26(x)
+ end
+end
+
+def fun_l27_n536(x)
+ if (x < 1)
+ fun_l28_n851(x)
+ else
+ fun_l28_n907(x)
+ end
+end
+
+def fun_l27_n537(x)
+ if (x < 1)
+ fun_l28_n759(x)
+ else
+ fun_l28_n927(x)
+ end
+end
+
+def fun_l27_n538(x)
+ if (x < 1)
+ fun_l28_n188(x)
+ else
+ fun_l28_n199(x)
+ end
+end
+
+def fun_l27_n539(x)
+ if (x < 1)
+ fun_l28_n496(x)
+ else
+ fun_l28_n664(x)
+ end
+end
+
+def fun_l27_n540(x)
+ if (x < 1)
+ fun_l28_n595(x)
+ else
+ fun_l28_n651(x)
+ end
+end
+
+def fun_l27_n541(x)
+ if (x < 1)
+ fun_l28_n678(x)
+ else
+ fun_l28_n172(x)
+ end
+end
+
+def fun_l27_n542(x)
+ if (x < 1)
+ fun_l28_n37(x)
+ else
+ fun_l28_n255(x)
+ end
+end
+
+def fun_l27_n543(x)
+ if (x < 1)
+ fun_l28_n58(x)
+ else
+ fun_l28_n367(x)
+ end
+end
+
+def fun_l27_n544(x)
+ if (x < 1)
+ fun_l28_n275(x)
+ else
+ fun_l28_n925(x)
+ end
+end
+
+def fun_l27_n545(x)
+ if (x < 1)
+ fun_l28_n469(x)
+ else
+ fun_l28_n774(x)
+ end
+end
+
+def fun_l27_n546(x)
+ if (x < 1)
+ fun_l28_n508(x)
+ else
+ fun_l28_n267(x)
+ end
+end
+
+def fun_l27_n547(x)
+ if (x < 1)
+ fun_l28_n288(x)
+ else
+ fun_l28_n64(x)
+ end
+end
+
+def fun_l27_n548(x)
+ if (x < 1)
+ fun_l28_n941(x)
+ else
+ fun_l28_n632(x)
+ end
+end
+
+def fun_l27_n549(x)
+ if (x < 1)
+ fun_l28_n816(x)
+ else
+ fun_l28_n551(x)
+ end
+end
+
+def fun_l27_n550(x)
+ if (x < 1)
+ fun_l28_n848(x)
+ else
+ fun_l28_n778(x)
+ end
+end
+
+def fun_l27_n551(x)
+ if (x < 1)
+ fun_l28_n273(x)
+ else
+ fun_l28_n846(x)
+ end
+end
+
+def fun_l27_n552(x)
+ if (x < 1)
+ fun_l28_n18(x)
+ else
+ fun_l28_n530(x)
+ end
+end
+
+def fun_l27_n553(x)
+ if (x < 1)
+ fun_l28_n673(x)
+ else
+ fun_l28_n824(x)
+ end
+end
+
+def fun_l27_n554(x)
+ if (x < 1)
+ fun_l28_n376(x)
+ else
+ fun_l28_n32(x)
+ end
+end
+
+def fun_l27_n555(x)
+ if (x < 1)
+ fun_l28_n500(x)
+ else
+ fun_l28_n389(x)
+ end
+end
+
+def fun_l27_n556(x)
+ if (x < 1)
+ fun_l28_n712(x)
+ else
+ fun_l28_n729(x)
+ end
+end
+
+def fun_l27_n557(x)
+ if (x < 1)
+ fun_l28_n951(x)
+ else
+ fun_l28_n846(x)
+ end
+end
+
+def fun_l27_n558(x)
+ if (x < 1)
+ fun_l28_n269(x)
+ else
+ fun_l28_n538(x)
+ end
+end
+
+def fun_l27_n559(x)
+ if (x < 1)
+ fun_l28_n72(x)
+ else
+ fun_l28_n711(x)
+ end
+end
+
+def fun_l27_n560(x)
+ if (x < 1)
+ fun_l28_n510(x)
+ else
+ fun_l28_n718(x)
+ end
+end
+
+def fun_l27_n561(x)
+ if (x < 1)
+ fun_l28_n123(x)
+ else
+ fun_l28_n983(x)
+ end
+end
+
+def fun_l27_n562(x)
+ if (x < 1)
+ fun_l28_n486(x)
+ else
+ fun_l28_n796(x)
+ end
+end
+
+def fun_l27_n563(x)
+ if (x < 1)
+ fun_l28_n925(x)
+ else
+ fun_l28_n499(x)
+ end
+end
+
+def fun_l27_n564(x)
+ if (x < 1)
+ fun_l28_n811(x)
+ else
+ fun_l28_n604(x)
+ end
+end
+
+def fun_l27_n565(x)
+ if (x < 1)
+ fun_l28_n685(x)
+ else
+ fun_l28_n721(x)
+ end
+end
+
+def fun_l27_n566(x)
+ if (x < 1)
+ fun_l28_n946(x)
+ else
+ fun_l28_n890(x)
+ end
+end
+
+def fun_l27_n567(x)
+ if (x < 1)
+ fun_l28_n646(x)
+ else
+ fun_l28_n2(x)
+ end
+end
+
+def fun_l27_n568(x)
+ if (x < 1)
+ fun_l28_n570(x)
+ else
+ fun_l28_n427(x)
+ end
+end
+
+def fun_l27_n569(x)
+ if (x < 1)
+ fun_l28_n435(x)
+ else
+ fun_l28_n877(x)
+ end
+end
+
+def fun_l27_n570(x)
+ if (x < 1)
+ fun_l28_n67(x)
+ else
+ fun_l28_n879(x)
+ end
+end
+
+def fun_l27_n571(x)
+ if (x < 1)
+ fun_l28_n278(x)
+ else
+ fun_l28_n90(x)
+ end
+end
+
+def fun_l27_n572(x)
+ if (x < 1)
+ fun_l28_n748(x)
+ else
+ fun_l28_n202(x)
+ end
+end
+
+def fun_l27_n573(x)
+ if (x < 1)
+ fun_l28_n795(x)
+ else
+ fun_l28_n862(x)
+ end
+end
+
+def fun_l27_n574(x)
+ if (x < 1)
+ fun_l28_n208(x)
+ else
+ fun_l28_n979(x)
+ end
+end
+
+def fun_l27_n575(x)
+ if (x < 1)
+ fun_l28_n134(x)
+ else
+ fun_l28_n208(x)
+ end
+end
+
+def fun_l27_n576(x)
+ if (x < 1)
+ fun_l28_n591(x)
+ else
+ fun_l28_n400(x)
+ end
+end
+
+def fun_l27_n577(x)
+ if (x < 1)
+ fun_l28_n579(x)
+ else
+ fun_l28_n675(x)
+ end
+end
+
+def fun_l27_n578(x)
+ if (x < 1)
+ fun_l28_n186(x)
+ else
+ fun_l28_n643(x)
+ end
+end
+
+def fun_l27_n579(x)
+ if (x < 1)
+ fun_l28_n974(x)
+ else
+ fun_l28_n716(x)
+ end
+end
+
+def fun_l27_n580(x)
+ if (x < 1)
+ fun_l28_n168(x)
+ else
+ fun_l28_n10(x)
+ end
+end
+
+def fun_l27_n581(x)
+ if (x < 1)
+ fun_l28_n124(x)
+ else
+ fun_l28_n657(x)
+ end
+end
+
+def fun_l27_n582(x)
+ if (x < 1)
+ fun_l28_n240(x)
+ else
+ fun_l28_n335(x)
+ end
+end
+
+def fun_l27_n583(x)
+ if (x < 1)
+ fun_l28_n346(x)
+ else
+ fun_l28_n170(x)
+ end
+end
+
+def fun_l27_n584(x)
+ if (x < 1)
+ fun_l28_n854(x)
+ else
+ fun_l28_n681(x)
+ end
+end
+
+def fun_l27_n585(x)
+ if (x < 1)
+ fun_l28_n515(x)
+ else
+ fun_l28_n884(x)
+ end
+end
+
+def fun_l27_n586(x)
+ if (x < 1)
+ fun_l28_n901(x)
+ else
+ fun_l28_n12(x)
+ end
+end
+
+def fun_l27_n587(x)
+ if (x < 1)
+ fun_l28_n300(x)
+ else
+ fun_l28_n205(x)
+ end
+end
+
+def fun_l27_n588(x)
+ if (x < 1)
+ fun_l28_n52(x)
+ else
+ fun_l28_n823(x)
+ end
+end
+
+def fun_l27_n589(x)
+ if (x < 1)
+ fun_l28_n170(x)
+ else
+ fun_l28_n588(x)
+ end
+end
+
+def fun_l27_n590(x)
+ if (x < 1)
+ fun_l28_n777(x)
+ else
+ fun_l28_n232(x)
+ end
+end
+
+def fun_l27_n591(x)
+ if (x < 1)
+ fun_l28_n234(x)
+ else
+ fun_l28_n552(x)
+ end
+end
+
+def fun_l27_n592(x)
+ if (x < 1)
+ fun_l28_n83(x)
+ else
+ fun_l28_n736(x)
+ end
+end
+
+def fun_l27_n593(x)
+ if (x < 1)
+ fun_l28_n623(x)
+ else
+ fun_l28_n663(x)
+ end
+end
+
+def fun_l27_n594(x)
+ if (x < 1)
+ fun_l28_n137(x)
+ else
+ fun_l28_n858(x)
+ end
+end
+
+def fun_l27_n595(x)
+ if (x < 1)
+ fun_l28_n238(x)
+ else
+ fun_l28_n11(x)
+ end
+end
+
+def fun_l27_n596(x)
+ if (x < 1)
+ fun_l28_n692(x)
+ else
+ fun_l28_n815(x)
+ end
+end
+
+def fun_l27_n597(x)
+ if (x < 1)
+ fun_l28_n259(x)
+ else
+ fun_l28_n535(x)
+ end
+end
+
+def fun_l27_n598(x)
+ if (x < 1)
+ fun_l28_n135(x)
+ else
+ fun_l28_n567(x)
+ end
+end
+
+def fun_l27_n599(x)
+ if (x < 1)
+ fun_l28_n725(x)
+ else
+ fun_l28_n393(x)
+ end
+end
+
+def fun_l27_n600(x)
+ if (x < 1)
+ fun_l28_n790(x)
+ else
+ fun_l28_n478(x)
+ end
+end
+
+def fun_l27_n601(x)
+ if (x < 1)
+ fun_l28_n248(x)
+ else
+ fun_l28_n62(x)
+ end
+end
+
+def fun_l27_n602(x)
+ if (x < 1)
+ fun_l28_n790(x)
+ else
+ fun_l28_n854(x)
+ end
+end
+
+def fun_l27_n603(x)
+ if (x < 1)
+ fun_l28_n345(x)
+ else
+ fun_l28_n795(x)
+ end
+end
+
+def fun_l27_n604(x)
+ if (x < 1)
+ fun_l28_n689(x)
+ else
+ fun_l28_n357(x)
+ end
+end
+
+def fun_l27_n605(x)
+ if (x < 1)
+ fun_l28_n314(x)
+ else
+ fun_l28_n886(x)
+ end
+end
+
+def fun_l27_n606(x)
+ if (x < 1)
+ fun_l28_n401(x)
+ else
+ fun_l28_n688(x)
+ end
+end
+
+def fun_l27_n607(x)
+ if (x < 1)
+ fun_l28_n386(x)
+ else
+ fun_l28_n126(x)
+ end
+end
+
+def fun_l27_n608(x)
+ if (x < 1)
+ fun_l28_n232(x)
+ else
+ fun_l28_n387(x)
+ end
+end
+
+def fun_l27_n609(x)
+ if (x < 1)
+ fun_l28_n938(x)
+ else
+ fun_l28_n657(x)
+ end
+end
+
+def fun_l27_n610(x)
+ if (x < 1)
+ fun_l28_n40(x)
+ else
+ fun_l28_n141(x)
+ end
+end
+
+def fun_l27_n611(x)
+ if (x < 1)
+ fun_l28_n909(x)
+ else
+ fun_l28_n265(x)
+ end
+end
+
+def fun_l27_n612(x)
+ if (x < 1)
+ fun_l28_n486(x)
+ else
+ fun_l28_n470(x)
+ end
+end
+
+def fun_l27_n613(x)
+ if (x < 1)
+ fun_l28_n959(x)
+ else
+ fun_l28_n793(x)
+ end
+end
+
+def fun_l27_n614(x)
+ if (x < 1)
+ fun_l28_n422(x)
+ else
+ fun_l28_n246(x)
+ end
+end
+
+def fun_l27_n615(x)
+ if (x < 1)
+ fun_l28_n860(x)
+ else
+ fun_l28_n315(x)
+ end
+end
+
+def fun_l27_n616(x)
+ if (x < 1)
+ fun_l28_n529(x)
+ else
+ fun_l28_n647(x)
+ end
+end
+
+def fun_l27_n617(x)
+ if (x < 1)
+ fun_l28_n860(x)
+ else
+ fun_l28_n860(x)
+ end
+end
+
+def fun_l27_n618(x)
+ if (x < 1)
+ fun_l28_n147(x)
+ else
+ fun_l28_n814(x)
+ end
+end
+
+def fun_l27_n619(x)
+ if (x < 1)
+ fun_l28_n828(x)
+ else
+ fun_l28_n854(x)
+ end
+end
+
+def fun_l27_n620(x)
+ if (x < 1)
+ fun_l28_n464(x)
+ else
+ fun_l28_n838(x)
+ end
+end
+
+def fun_l27_n621(x)
+ if (x < 1)
+ fun_l28_n89(x)
+ else
+ fun_l28_n884(x)
+ end
+end
+
+def fun_l27_n622(x)
+ if (x < 1)
+ fun_l28_n933(x)
+ else
+ fun_l28_n889(x)
+ end
+end
+
+def fun_l27_n623(x)
+ if (x < 1)
+ fun_l28_n638(x)
+ else
+ fun_l28_n246(x)
+ end
+end
+
+def fun_l27_n624(x)
+ if (x < 1)
+ fun_l28_n724(x)
+ else
+ fun_l28_n305(x)
+ end
+end
+
+def fun_l27_n625(x)
+ if (x < 1)
+ fun_l28_n927(x)
+ else
+ fun_l28_n772(x)
+ end
+end
+
+def fun_l27_n626(x)
+ if (x < 1)
+ fun_l28_n612(x)
+ else
+ fun_l28_n953(x)
+ end
+end
+
+def fun_l27_n627(x)
+ if (x < 1)
+ fun_l28_n694(x)
+ else
+ fun_l28_n529(x)
+ end
+end
+
+def fun_l27_n628(x)
+ if (x < 1)
+ fun_l28_n136(x)
+ else
+ fun_l28_n977(x)
+ end
+end
+
+def fun_l27_n629(x)
+ if (x < 1)
+ fun_l28_n108(x)
+ else
+ fun_l28_n940(x)
+ end
+end
+
+def fun_l27_n630(x)
+ if (x < 1)
+ fun_l28_n773(x)
+ else
+ fun_l28_n62(x)
+ end
+end
+
+def fun_l27_n631(x)
+ if (x < 1)
+ fun_l28_n531(x)
+ else
+ fun_l28_n68(x)
+ end
+end
+
+def fun_l27_n632(x)
+ if (x < 1)
+ fun_l28_n910(x)
+ else
+ fun_l28_n638(x)
+ end
+end
+
+def fun_l27_n633(x)
+ if (x < 1)
+ fun_l28_n943(x)
+ else
+ fun_l28_n530(x)
+ end
+end
+
+def fun_l27_n634(x)
+ if (x < 1)
+ fun_l28_n161(x)
+ else
+ fun_l28_n842(x)
+ end
+end
+
+def fun_l27_n635(x)
+ if (x < 1)
+ fun_l28_n252(x)
+ else
+ fun_l28_n659(x)
+ end
+end
+
+def fun_l27_n636(x)
+ if (x < 1)
+ fun_l28_n739(x)
+ else
+ fun_l28_n116(x)
+ end
+end
+
+def fun_l27_n637(x)
+ if (x < 1)
+ fun_l28_n528(x)
+ else
+ fun_l28_n451(x)
+ end
+end
+
+def fun_l27_n638(x)
+ if (x < 1)
+ fun_l28_n772(x)
+ else
+ fun_l28_n163(x)
+ end
+end
+
+def fun_l27_n639(x)
+ if (x < 1)
+ fun_l28_n300(x)
+ else
+ fun_l28_n174(x)
+ end
+end
+
+def fun_l27_n640(x)
+ if (x < 1)
+ fun_l28_n967(x)
+ else
+ fun_l28_n437(x)
+ end
+end
+
+def fun_l27_n641(x)
+ if (x < 1)
+ fun_l28_n716(x)
+ else
+ fun_l28_n855(x)
+ end
+end
+
+def fun_l27_n642(x)
+ if (x < 1)
+ fun_l28_n510(x)
+ else
+ fun_l28_n958(x)
+ end
+end
+
+def fun_l27_n643(x)
+ if (x < 1)
+ fun_l28_n57(x)
+ else
+ fun_l28_n347(x)
+ end
+end
+
+def fun_l27_n644(x)
+ if (x < 1)
+ fun_l28_n145(x)
+ else
+ fun_l28_n652(x)
+ end
+end
+
+def fun_l27_n645(x)
+ if (x < 1)
+ fun_l28_n730(x)
+ else
+ fun_l28_n388(x)
+ end
+end
+
+def fun_l27_n646(x)
+ if (x < 1)
+ fun_l28_n409(x)
+ else
+ fun_l28_n394(x)
+ end
+end
+
+def fun_l27_n647(x)
+ if (x < 1)
+ fun_l28_n484(x)
+ else
+ fun_l28_n754(x)
+ end
+end
+
+def fun_l27_n648(x)
+ if (x < 1)
+ fun_l28_n888(x)
+ else
+ fun_l28_n229(x)
+ end
+end
+
+def fun_l27_n649(x)
+ if (x < 1)
+ fun_l28_n1(x)
+ else
+ fun_l28_n995(x)
+ end
+end
+
+def fun_l27_n650(x)
+ if (x < 1)
+ fun_l28_n992(x)
+ else
+ fun_l28_n522(x)
+ end
+end
+
+def fun_l27_n651(x)
+ if (x < 1)
+ fun_l28_n69(x)
+ else
+ fun_l28_n696(x)
+ end
+end
+
+def fun_l27_n652(x)
+ if (x < 1)
+ fun_l28_n496(x)
+ else
+ fun_l28_n47(x)
+ end
+end
+
+def fun_l27_n653(x)
+ if (x < 1)
+ fun_l28_n176(x)
+ else
+ fun_l28_n830(x)
+ end
+end
+
+def fun_l27_n654(x)
+ if (x < 1)
+ fun_l28_n277(x)
+ else
+ fun_l28_n311(x)
+ end
+end
+
+def fun_l27_n655(x)
+ if (x < 1)
+ fun_l28_n994(x)
+ else
+ fun_l28_n518(x)
+ end
+end
+
+def fun_l27_n656(x)
+ if (x < 1)
+ fun_l28_n238(x)
+ else
+ fun_l28_n99(x)
+ end
+end
+
+def fun_l27_n657(x)
+ if (x < 1)
+ fun_l28_n636(x)
+ else
+ fun_l28_n734(x)
+ end
+end
+
+def fun_l27_n658(x)
+ if (x < 1)
+ fun_l28_n796(x)
+ else
+ fun_l28_n109(x)
+ end
+end
+
+def fun_l27_n659(x)
+ if (x < 1)
+ fun_l28_n271(x)
+ else
+ fun_l28_n348(x)
+ end
+end
+
+def fun_l27_n660(x)
+ if (x < 1)
+ fun_l28_n847(x)
+ else
+ fun_l28_n926(x)
+ end
+end
+
+def fun_l27_n661(x)
+ if (x < 1)
+ fun_l28_n559(x)
+ else
+ fun_l28_n636(x)
+ end
+end
+
+def fun_l27_n662(x)
+ if (x < 1)
+ fun_l28_n528(x)
+ else
+ fun_l28_n0(x)
+ end
+end
+
+def fun_l27_n663(x)
+ if (x < 1)
+ fun_l28_n835(x)
+ else
+ fun_l28_n41(x)
+ end
+end
+
+def fun_l27_n664(x)
+ if (x < 1)
+ fun_l28_n135(x)
+ else
+ fun_l28_n356(x)
+ end
+end
+
+def fun_l27_n665(x)
+ if (x < 1)
+ fun_l28_n825(x)
+ else
+ fun_l28_n55(x)
+ end
+end
+
+def fun_l27_n666(x)
+ if (x < 1)
+ fun_l28_n659(x)
+ else
+ fun_l28_n384(x)
+ end
+end
+
+def fun_l27_n667(x)
+ if (x < 1)
+ fun_l28_n604(x)
+ else
+ fun_l28_n870(x)
+ end
+end
+
+def fun_l27_n668(x)
+ if (x < 1)
+ fun_l28_n136(x)
+ else
+ fun_l28_n343(x)
+ end
+end
+
+def fun_l27_n669(x)
+ if (x < 1)
+ fun_l28_n206(x)
+ else
+ fun_l28_n341(x)
+ end
+end
+
+def fun_l27_n670(x)
+ if (x < 1)
+ fun_l28_n947(x)
+ else
+ fun_l28_n926(x)
+ end
+end
+
+def fun_l27_n671(x)
+ if (x < 1)
+ fun_l28_n303(x)
+ else
+ fun_l28_n79(x)
+ end
+end
+
+def fun_l27_n672(x)
+ if (x < 1)
+ fun_l28_n181(x)
+ else
+ fun_l28_n937(x)
+ end
+end
+
+def fun_l27_n673(x)
+ if (x < 1)
+ fun_l28_n301(x)
+ else
+ fun_l28_n687(x)
+ end
+end
+
+def fun_l27_n674(x)
+ if (x < 1)
+ fun_l28_n992(x)
+ else
+ fun_l28_n814(x)
+ end
+end
+
+def fun_l27_n675(x)
+ if (x < 1)
+ fun_l28_n239(x)
+ else
+ fun_l28_n248(x)
+ end
+end
+
+def fun_l27_n676(x)
+ if (x < 1)
+ fun_l28_n728(x)
+ else
+ fun_l28_n368(x)
+ end
+end
+
+def fun_l27_n677(x)
+ if (x < 1)
+ fun_l28_n411(x)
+ else
+ fun_l28_n773(x)
+ end
+end
+
+def fun_l27_n678(x)
+ if (x < 1)
+ fun_l28_n522(x)
+ else
+ fun_l28_n754(x)
+ end
+end
+
+def fun_l27_n679(x)
+ if (x < 1)
+ fun_l28_n538(x)
+ else
+ fun_l28_n976(x)
+ end
+end
+
+def fun_l27_n680(x)
+ if (x < 1)
+ fun_l28_n744(x)
+ else
+ fun_l28_n752(x)
+ end
+end
+
+def fun_l27_n681(x)
+ if (x < 1)
+ fun_l28_n658(x)
+ else
+ fun_l28_n19(x)
+ end
+end
+
+def fun_l27_n682(x)
+ if (x < 1)
+ fun_l28_n843(x)
+ else
+ fun_l28_n657(x)
+ end
+end
+
+def fun_l27_n683(x)
+ if (x < 1)
+ fun_l28_n256(x)
+ else
+ fun_l28_n744(x)
+ end
+end
+
+def fun_l27_n684(x)
+ if (x < 1)
+ fun_l28_n380(x)
+ else
+ fun_l28_n223(x)
+ end
+end
+
+def fun_l27_n685(x)
+ if (x < 1)
+ fun_l28_n762(x)
+ else
+ fun_l28_n122(x)
+ end
+end
+
+def fun_l27_n686(x)
+ if (x < 1)
+ fun_l28_n860(x)
+ else
+ fun_l28_n51(x)
+ end
+end
+
+def fun_l27_n687(x)
+ if (x < 1)
+ fun_l28_n210(x)
+ else
+ fun_l28_n658(x)
+ end
+end
+
+def fun_l27_n688(x)
+ if (x < 1)
+ fun_l28_n250(x)
+ else
+ fun_l28_n165(x)
+ end
+end
+
+def fun_l27_n689(x)
+ if (x < 1)
+ fun_l28_n955(x)
+ else
+ fun_l28_n862(x)
+ end
+end
+
+def fun_l27_n690(x)
+ if (x < 1)
+ fun_l28_n592(x)
+ else
+ fun_l28_n54(x)
+ end
+end
+
+def fun_l27_n691(x)
+ if (x < 1)
+ fun_l28_n558(x)
+ else
+ fun_l28_n750(x)
+ end
+end
+
+def fun_l27_n692(x)
+ if (x < 1)
+ fun_l28_n307(x)
+ else
+ fun_l28_n143(x)
+ end
+end
+
+def fun_l27_n693(x)
+ if (x < 1)
+ fun_l28_n625(x)
+ else
+ fun_l28_n743(x)
+ end
+end
+
+def fun_l27_n694(x)
+ if (x < 1)
+ fun_l28_n883(x)
+ else
+ fun_l28_n567(x)
+ end
+end
+
+def fun_l27_n695(x)
+ if (x < 1)
+ fun_l28_n889(x)
+ else
+ fun_l28_n805(x)
+ end
+end
+
+def fun_l27_n696(x)
+ if (x < 1)
+ fun_l28_n366(x)
+ else
+ fun_l28_n112(x)
+ end
+end
+
+def fun_l27_n697(x)
+ if (x < 1)
+ fun_l28_n746(x)
+ else
+ fun_l28_n924(x)
+ end
+end
+
+def fun_l27_n698(x)
+ if (x < 1)
+ fun_l28_n694(x)
+ else
+ fun_l28_n703(x)
+ end
+end
+
+def fun_l27_n699(x)
+ if (x < 1)
+ fun_l28_n304(x)
+ else
+ fun_l28_n200(x)
+ end
+end
+
+def fun_l27_n700(x)
+ if (x < 1)
+ fun_l28_n477(x)
+ else
+ fun_l28_n851(x)
+ end
+end
+
+def fun_l27_n701(x)
+ if (x < 1)
+ fun_l28_n940(x)
+ else
+ fun_l28_n8(x)
+ end
+end
+
+def fun_l27_n702(x)
+ if (x < 1)
+ fun_l28_n675(x)
+ else
+ fun_l28_n631(x)
+ end
+end
+
+def fun_l27_n703(x)
+ if (x < 1)
+ fun_l28_n683(x)
+ else
+ fun_l28_n191(x)
+ end
+end
+
+def fun_l27_n704(x)
+ if (x < 1)
+ fun_l28_n431(x)
+ else
+ fun_l28_n573(x)
+ end
+end
+
+def fun_l27_n705(x)
+ if (x < 1)
+ fun_l28_n86(x)
+ else
+ fun_l28_n89(x)
+ end
+end
+
+def fun_l27_n706(x)
+ if (x < 1)
+ fun_l28_n315(x)
+ else
+ fun_l28_n388(x)
+ end
+end
+
+def fun_l27_n707(x)
+ if (x < 1)
+ fun_l28_n94(x)
+ else
+ fun_l28_n176(x)
+ end
+end
+
+def fun_l27_n708(x)
+ if (x < 1)
+ fun_l28_n391(x)
+ else
+ fun_l28_n187(x)
+ end
+end
+
+def fun_l27_n709(x)
+ if (x < 1)
+ fun_l28_n845(x)
+ else
+ fun_l28_n497(x)
+ end
+end
+
+def fun_l27_n710(x)
+ if (x < 1)
+ fun_l28_n195(x)
+ else
+ fun_l28_n242(x)
+ end
+end
+
+def fun_l27_n711(x)
+ if (x < 1)
+ fun_l28_n276(x)
+ else
+ fun_l28_n856(x)
+ end
+end
+
+def fun_l27_n712(x)
+ if (x < 1)
+ fun_l28_n42(x)
+ else
+ fun_l28_n184(x)
+ end
+end
+
+def fun_l27_n713(x)
+ if (x < 1)
+ fun_l28_n270(x)
+ else
+ fun_l28_n813(x)
+ end
+end
+
+def fun_l27_n714(x)
+ if (x < 1)
+ fun_l28_n281(x)
+ else
+ fun_l28_n54(x)
+ end
+end
+
+def fun_l27_n715(x)
+ if (x < 1)
+ fun_l28_n226(x)
+ else
+ fun_l28_n202(x)
+ end
+end
+
+def fun_l27_n716(x)
+ if (x < 1)
+ fun_l28_n391(x)
+ else
+ fun_l28_n143(x)
+ end
+end
+
+def fun_l27_n717(x)
+ if (x < 1)
+ fun_l28_n449(x)
+ else
+ fun_l28_n530(x)
+ end
+end
+
+def fun_l27_n718(x)
+ if (x < 1)
+ fun_l28_n198(x)
+ else
+ fun_l28_n342(x)
+ end
+end
+
+def fun_l27_n719(x)
+ if (x < 1)
+ fun_l28_n741(x)
+ else
+ fun_l28_n703(x)
+ end
+end
+
+def fun_l27_n720(x)
+ if (x < 1)
+ fun_l28_n779(x)
+ else
+ fun_l28_n706(x)
+ end
+end
+
+def fun_l27_n721(x)
+ if (x < 1)
+ fun_l28_n184(x)
+ else
+ fun_l28_n472(x)
+ end
+end
+
+def fun_l27_n722(x)
+ if (x < 1)
+ fun_l28_n752(x)
+ else
+ fun_l28_n230(x)
+ end
+end
+
+def fun_l27_n723(x)
+ if (x < 1)
+ fun_l28_n137(x)
+ else
+ fun_l28_n228(x)
+ end
+end
+
+def fun_l27_n724(x)
+ if (x < 1)
+ fun_l28_n360(x)
+ else
+ fun_l28_n186(x)
+ end
+end
+
+def fun_l27_n725(x)
+ if (x < 1)
+ fun_l28_n791(x)
+ else
+ fun_l28_n752(x)
+ end
+end
+
+def fun_l27_n726(x)
+ if (x < 1)
+ fun_l28_n162(x)
+ else
+ fun_l28_n492(x)
+ end
+end
+
+def fun_l27_n727(x)
+ if (x < 1)
+ fun_l28_n329(x)
+ else
+ fun_l28_n286(x)
+ end
+end
+
+def fun_l27_n728(x)
+ if (x < 1)
+ fun_l28_n262(x)
+ else
+ fun_l28_n775(x)
+ end
+end
+
+def fun_l27_n729(x)
+ if (x < 1)
+ fun_l28_n773(x)
+ else
+ fun_l28_n424(x)
+ end
+end
+
+def fun_l27_n730(x)
+ if (x < 1)
+ fun_l28_n202(x)
+ else
+ fun_l28_n379(x)
+ end
+end
+
+def fun_l27_n731(x)
+ if (x < 1)
+ fun_l28_n761(x)
+ else
+ fun_l28_n759(x)
+ end
+end
+
+def fun_l27_n732(x)
+ if (x < 1)
+ fun_l28_n544(x)
+ else
+ fun_l28_n980(x)
+ end
+end
+
+def fun_l27_n733(x)
+ if (x < 1)
+ fun_l28_n75(x)
+ else
+ fun_l28_n786(x)
+ end
+end
+
+def fun_l27_n734(x)
+ if (x < 1)
+ fun_l28_n708(x)
+ else
+ fun_l28_n92(x)
+ end
+end
+
+def fun_l27_n735(x)
+ if (x < 1)
+ fun_l28_n213(x)
+ else
+ fun_l28_n966(x)
+ end
+end
+
+def fun_l27_n736(x)
+ if (x < 1)
+ fun_l28_n298(x)
+ else
+ fun_l28_n517(x)
+ end
+end
+
+def fun_l27_n737(x)
+ if (x < 1)
+ fun_l28_n665(x)
+ else
+ fun_l28_n960(x)
+ end
+end
+
+def fun_l27_n738(x)
+ if (x < 1)
+ fun_l28_n51(x)
+ else
+ fun_l28_n605(x)
+ end
+end
+
+def fun_l27_n739(x)
+ if (x < 1)
+ fun_l28_n931(x)
+ else
+ fun_l28_n697(x)
+ end
+end
+
+def fun_l27_n740(x)
+ if (x < 1)
+ fun_l28_n341(x)
+ else
+ fun_l28_n57(x)
+ end
+end
+
+def fun_l27_n741(x)
+ if (x < 1)
+ fun_l28_n614(x)
+ else
+ fun_l28_n623(x)
+ end
+end
+
+def fun_l27_n742(x)
+ if (x < 1)
+ fun_l28_n466(x)
+ else
+ fun_l28_n260(x)
+ end
+end
+
+def fun_l27_n743(x)
+ if (x < 1)
+ fun_l28_n741(x)
+ else
+ fun_l28_n337(x)
+ end
+end
+
+def fun_l27_n744(x)
+ if (x < 1)
+ fun_l28_n414(x)
+ else
+ fun_l28_n277(x)
+ end
+end
+
+def fun_l27_n745(x)
+ if (x < 1)
+ fun_l28_n377(x)
+ else
+ fun_l28_n245(x)
+ end
+end
+
+def fun_l27_n746(x)
+ if (x < 1)
+ fun_l28_n441(x)
+ else
+ fun_l28_n347(x)
+ end
+end
+
+def fun_l27_n747(x)
+ if (x < 1)
+ fun_l28_n473(x)
+ else
+ fun_l28_n54(x)
+ end
+end
+
+def fun_l27_n748(x)
+ if (x < 1)
+ fun_l28_n140(x)
+ else
+ fun_l28_n680(x)
+ end
+end
+
+def fun_l27_n749(x)
+ if (x < 1)
+ fun_l28_n491(x)
+ else
+ fun_l28_n830(x)
+ end
+end
+
+def fun_l27_n750(x)
+ if (x < 1)
+ fun_l28_n803(x)
+ else
+ fun_l28_n917(x)
+ end
+end
+
+def fun_l27_n751(x)
+ if (x < 1)
+ fun_l28_n97(x)
+ else
+ fun_l28_n702(x)
+ end
+end
+
+def fun_l27_n752(x)
+ if (x < 1)
+ fun_l28_n113(x)
+ else
+ fun_l28_n447(x)
+ end
+end
+
+def fun_l27_n753(x)
+ if (x < 1)
+ fun_l28_n589(x)
+ else
+ fun_l28_n933(x)
+ end
+end
+
+def fun_l27_n754(x)
+ if (x < 1)
+ fun_l28_n610(x)
+ else
+ fun_l28_n365(x)
+ end
+end
+
+def fun_l27_n755(x)
+ if (x < 1)
+ fun_l28_n813(x)
+ else
+ fun_l28_n930(x)
+ end
+end
+
+def fun_l27_n756(x)
+ if (x < 1)
+ fun_l28_n997(x)
+ else
+ fun_l28_n112(x)
+ end
+end
+
+def fun_l27_n757(x)
+ if (x < 1)
+ fun_l28_n635(x)
+ else
+ fun_l28_n852(x)
+ end
+end
+
+def fun_l27_n758(x)
+ if (x < 1)
+ fun_l28_n735(x)
+ else
+ fun_l28_n3(x)
+ end
+end
+
+def fun_l27_n759(x)
+ if (x < 1)
+ fun_l28_n473(x)
+ else
+ fun_l28_n276(x)
+ end
+end
+
+def fun_l27_n760(x)
+ if (x < 1)
+ fun_l28_n708(x)
+ else
+ fun_l28_n602(x)
+ end
+end
+
+def fun_l27_n761(x)
+ if (x < 1)
+ fun_l28_n178(x)
+ else
+ fun_l28_n766(x)
+ end
+end
+
+def fun_l27_n762(x)
+ if (x < 1)
+ fun_l28_n968(x)
+ else
+ fun_l28_n935(x)
+ end
+end
+
+def fun_l27_n763(x)
+ if (x < 1)
+ fun_l28_n17(x)
+ else
+ fun_l28_n680(x)
+ end
+end
+
+def fun_l27_n764(x)
+ if (x < 1)
+ fun_l28_n465(x)
+ else
+ fun_l28_n484(x)
+ end
+end
+
+def fun_l27_n765(x)
+ if (x < 1)
+ fun_l28_n157(x)
+ else
+ fun_l28_n33(x)
+ end
+end
+
+def fun_l27_n766(x)
+ if (x < 1)
+ fun_l28_n306(x)
+ else
+ fun_l28_n588(x)
+ end
+end
+
+def fun_l27_n767(x)
+ if (x < 1)
+ fun_l28_n73(x)
+ else
+ fun_l28_n144(x)
+ end
+end
+
+def fun_l27_n768(x)
+ if (x < 1)
+ fun_l28_n838(x)
+ else
+ fun_l28_n984(x)
+ end
+end
+
+def fun_l27_n769(x)
+ if (x < 1)
+ fun_l28_n541(x)
+ else
+ fun_l28_n687(x)
+ end
+end
+
+def fun_l27_n770(x)
+ if (x < 1)
+ fun_l28_n129(x)
+ else
+ fun_l28_n256(x)
+ end
+end
+
+def fun_l27_n771(x)
+ if (x < 1)
+ fun_l28_n78(x)
+ else
+ fun_l28_n617(x)
+ end
+end
+
+def fun_l27_n772(x)
+ if (x < 1)
+ fun_l28_n590(x)
+ else
+ fun_l28_n78(x)
+ end
+end
+
+def fun_l27_n773(x)
+ if (x < 1)
+ fun_l28_n609(x)
+ else
+ fun_l28_n942(x)
+ end
+end
+
+def fun_l27_n774(x)
+ if (x < 1)
+ fun_l28_n794(x)
+ else
+ fun_l28_n361(x)
+ end
+end
+
+def fun_l27_n775(x)
+ if (x < 1)
+ fun_l28_n632(x)
+ else
+ fun_l28_n722(x)
+ end
+end
+
+def fun_l27_n776(x)
+ if (x < 1)
+ fun_l28_n655(x)
+ else
+ fun_l28_n944(x)
+ end
+end
+
+def fun_l27_n777(x)
+ if (x < 1)
+ fun_l28_n117(x)
+ else
+ fun_l28_n725(x)
+ end
+end
+
+def fun_l27_n778(x)
+ if (x < 1)
+ fun_l28_n511(x)
+ else
+ fun_l28_n934(x)
+ end
+end
+
+def fun_l27_n779(x)
+ if (x < 1)
+ fun_l28_n11(x)
+ else
+ fun_l28_n421(x)
+ end
+end
+
+def fun_l27_n780(x)
+ if (x < 1)
+ fun_l28_n957(x)
+ else
+ fun_l28_n941(x)
+ end
+end
+
+def fun_l27_n781(x)
+ if (x < 1)
+ fun_l28_n899(x)
+ else
+ fun_l28_n122(x)
+ end
+end
+
+def fun_l27_n782(x)
+ if (x < 1)
+ fun_l28_n42(x)
+ else
+ fun_l28_n885(x)
+ end
+end
+
+def fun_l27_n783(x)
+ if (x < 1)
+ fun_l28_n696(x)
+ else
+ fun_l28_n25(x)
+ end
+end
+
+def fun_l27_n784(x)
+ if (x < 1)
+ fun_l28_n683(x)
+ else
+ fun_l28_n201(x)
+ end
+end
+
+def fun_l27_n785(x)
+ if (x < 1)
+ fun_l28_n337(x)
+ else
+ fun_l28_n977(x)
+ end
+end
+
+def fun_l27_n786(x)
+ if (x < 1)
+ fun_l28_n113(x)
+ else
+ fun_l28_n946(x)
+ end
+end
+
+def fun_l27_n787(x)
+ if (x < 1)
+ fun_l28_n311(x)
+ else
+ fun_l28_n396(x)
+ end
+end
+
+def fun_l27_n788(x)
+ if (x < 1)
+ fun_l28_n963(x)
+ else
+ fun_l28_n592(x)
+ end
+end
+
+def fun_l27_n789(x)
+ if (x < 1)
+ fun_l28_n647(x)
+ else
+ fun_l28_n614(x)
+ end
+end
+
+def fun_l27_n790(x)
+ if (x < 1)
+ fun_l28_n15(x)
+ else
+ fun_l28_n602(x)
+ end
+end
+
+def fun_l27_n791(x)
+ if (x < 1)
+ fun_l28_n648(x)
+ else
+ fun_l28_n921(x)
+ end
+end
+
+def fun_l27_n792(x)
+ if (x < 1)
+ fun_l28_n272(x)
+ else
+ fun_l28_n585(x)
+ end
+end
+
+def fun_l27_n793(x)
+ if (x < 1)
+ fun_l28_n74(x)
+ else
+ fun_l28_n412(x)
+ end
+end
+
+def fun_l27_n794(x)
+ if (x < 1)
+ fun_l28_n610(x)
+ else
+ fun_l28_n121(x)
+ end
+end
+
+def fun_l27_n795(x)
+ if (x < 1)
+ fun_l28_n905(x)
+ else
+ fun_l28_n620(x)
+ end
+end
+
+def fun_l27_n796(x)
+ if (x < 1)
+ fun_l28_n691(x)
+ else
+ fun_l28_n833(x)
+ end
+end
+
+def fun_l27_n797(x)
+ if (x < 1)
+ fun_l28_n148(x)
+ else
+ fun_l28_n223(x)
+ end
+end
+
+def fun_l27_n798(x)
+ if (x < 1)
+ fun_l28_n835(x)
+ else
+ fun_l28_n59(x)
+ end
+end
+
+def fun_l27_n799(x)
+ if (x < 1)
+ fun_l28_n317(x)
+ else
+ fun_l28_n39(x)
+ end
+end
+
+def fun_l27_n800(x)
+ if (x < 1)
+ fun_l28_n694(x)
+ else
+ fun_l28_n833(x)
+ end
+end
+
+def fun_l27_n801(x)
+ if (x < 1)
+ fun_l28_n280(x)
+ else
+ fun_l28_n322(x)
+ end
+end
+
+def fun_l27_n802(x)
+ if (x < 1)
+ fun_l28_n612(x)
+ else
+ fun_l28_n866(x)
+ end
+end
+
+def fun_l27_n803(x)
+ if (x < 1)
+ fun_l28_n114(x)
+ else
+ fun_l28_n901(x)
+ end
+end
+
+def fun_l27_n804(x)
+ if (x < 1)
+ fun_l28_n983(x)
+ else
+ fun_l28_n837(x)
+ end
+end
+
+def fun_l27_n805(x)
+ if (x < 1)
+ fun_l28_n225(x)
+ else
+ fun_l28_n345(x)
+ end
+end
+
+def fun_l27_n806(x)
+ if (x < 1)
+ fun_l28_n879(x)
+ else
+ fun_l28_n929(x)
+ end
+end
+
+def fun_l27_n807(x)
+ if (x < 1)
+ fun_l28_n41(x)
+ else
+ fun_l28_n670(x)
+ end
+end
+
+def fun_l27_n808(x)
+ if (x < 1)
+ fun_l28_n407(x)
+ else
+ fun_l28_n46(x)
+ end
+end
+
+def fun_l27_n809(x)
+ if (x < 1)
+ fun_l28_n377(x)
+ else
+ fun_l28_n646(x)
+ end
+end
+
+def fun_l27_n810(x)
+ if (x < 1)
+ fun_l28_n293(x)
+ else
+ fun_l28_n40(x)
+ end
+end
+
+def fun_l27_n811(x)
+ if (x < 1)
+ fun_l28_n150(x)
+ else
+ fun_l28_n743(x)
+ end
+end
+
+def fun_l27_n812(x)
+ if (x < 1)
+ fun_l28_n285(x)
+ else
+ fun_l28_n124(x)
+ end
+end
+
+def fun_l27_n813(x)
+ if (x < 1)
+ fun_l28_n861(x)
+ else
+ fun_l28_n641(x)
+ end
+end
+
+def fun_l27_n814(x)
+ if (x < 1)
+ fun_l28_n917(x)
+ else
+ fun_l28_n51(x)
+ end
+end
+
+def fun_l27_n815(x)
+ if (x < 1)
+ fun_l28_n573(x)
+ else
+ fun_l28_n551(x)
+ end
+end
+
+def fun_l27_n816(x)
+ if (x < 1)
+ fun_l28_n420(x)
+ else
+ fun_l28_n155(x)
+ end
+end
+
+def fun_l27_n817(x)
+ if (x < 1)
+ fun_l28_n283(x)
+ else
+ fun_l28_n797(x)
+ end
+end
+
+def fun_l27_n818(x)
+ if (x < 1)
+ fun_l28_n744(x)
+ else
+ fun_l28_n22(x)
+ end
+end
+
+def fun_l27_n819(x)
+ if (x < 1)
+ fun_l28_n370(x)
+ else
+ fun_l28_n287(x)
+ end
+end
+
+def fun_l27_n820(x)
+ if (x < 1)
+ fun_l28_n435(x)
+ else
+ fun_l28_n23(x)
+ end
+end
+
+def fun_l27_n821(x)
+ if (x < 1)
+ fun_l28_n947(x)
+ else
+ fun_l28_n200(x)
+ end
+end
+
+def fun_l27_n822(x)
+ if (x < 1)
+ fun_l28_n259(x)
+ else
+ fun_l28_n444(x)
+ end
+end
+
+def fun_l27_n823(x)
+ if (x < 1)
+ fun_l28_n663(x)
+ else
+ fun_l28_n755(x)
+ end
+end
+
+def fun_l27_n824(x)
+ if (x < 1)
+ fun_l28_n564(x)
+ else
+ fun_l28_n572(x)
+ end
+end
+
+def fun_l27_n825(x)
+ if (x < 1)
+ fun_l28_n679(x)
+ else
+ fun_l28_n351(x)
+ end
+end
+
+def fun_l27_n826(x)
+ if (x < 1)
+ fun_l28_n654(x)
+ else
+ fun_l28_n393(x)
+ end
+end
+
+def fun_l27_n827(x)
+ if (x < 1)
+ fun_l28_n454(x)
+ else
+ fun_l28_n698(x)
+ end
+end
+
+def fun_l27_n828(x)
+ if (x < 1)
+ fun_l28_n389(x)
+ else
+ fun_l28_n118(x)
+ end
+end
+
+def fun_l27_n829(x)
+ if (x < 1)
+ fun_l28_n918(x)
+ else
+ fun_l28_n176(x)
+ end
+end
+
+def fun_l27_n830(x)
+ if (x < 1)
+ fun_l28_n158(x)
+ else
+ fun_l28_n309(x)
+ end
+end
+
+def fun_l27_n831(x)
+ if (x < 1)
+ fun_l28_n86(x)
+ else
+ fun_l28_n250(x)
+ end
+end
+
+def fun_l27_n832(x)
+ if (x < 1)
+ fun_l28_n21(x)
+ else
+ fun_l28_n688(x)
+ end
+end
+
+def fun_l27_n833(x)
+ if (x < 1)
+ fun_l28_n587(x)
+ else
+ fun_l28_n484(x)
+ end
+end
+
+def fun_l27_n834(x)
+ if (x < 1)
+ fun_l28_n886(x)
+ else
+ fun_l28_n579(x)
+ end
+end
+
+def fun_l27_n835(x)
+ if (x < 1)
+ fun_l28_n923(x)
+ else
+ fun_l28_n140(x)
+ end
+end
+
+def fun_l27_n836(x)
+ if (x < 1)
+ fun_l28_n120(x)
+ else
+ fun_l28_n704(x)
+ end
+end
+
+def fun_l27_n837(x)
+ if (x < 1)
+ fun_l28_n905(x)
+ else
+ fun_l28_n918(x)
+ end
+end
+
+def fun_l27_n838(x)
+ if (x < 1)
+ fun_l28_n679(x)
+ else
+ fun_l28_n588(x)
+ end
+end
+
+def fun_l27_n839(x)
+ if (x < 1)
+ fun_l28_n445(x)
+ else
+ fun_l28_n187(x)
+ end
+end
+
+def fun_l27_n840(x)
+ if (x < 1)
+ fun_l28_n695(x)
+ else
+ fun_l28_n86(x)
+ end
+end
+
+def fun_l27_n841(x)
+ if (x < 1)
+ fun_l28_n784(x)
+ else
+ fun_l28_n802(x)
+ end
+end
+
+def fun_l27_n842(x)
+ if (x < 1)
+ fun_l28_n854(x)
+ else
+ fun_l28_n617(x)
+ end
+end
+
+def fun_l27_n843(x)
+ if (x < 1)
+ fun_l28_n466(x)
+ else
+ fun_l28_n261(x)
+ end
+end
+
+def fun_l27_n844(x)
+ if (x < 1)
+ fun_l28_n326(x)
+ else
+ fun_l28_n517(x)
+ end
+end
+
+def fun_l27_n845(x)
+ if (x < 1)
+ fun_l28_n686(x)
+ else
+ fun_l28_n81(x)
+ end
+end
+
+def fun_l27_n846(x)
+ if (x < 1)
+ fun_l28_n71(x)
+ else
+ fun_l28_n685(x)
+ end
+end
+
+def fun_l27_n847(x)
+ if (x < 1)
+ fun_l28_n622(x)
+ else
+ fun_l28_n469(x)
+ end
+end
+
+def fun_l27_n848(x)
+ if (x < 1)
+ fun_l28_n125(x)
+ else
+ fun_l28_n252(x)
+ end
+end
+
+def fun_l27_n849(x)
+ if (x < 1)
+ fun_l28_n820(x)
+ else
+ fun_l28_n752(x)
+ end
+end
+
+def fun_l27_n850(x)
+ if (x < 1)
+ fun_l28_n278(x)
+ else
+ fun_l28_n198(x)
+ end
+end
+
+def fun_l27_n851(x)
+ if (x < 1)
+ fun_l28_n631(x)
+ else
+ fun_l28_n241(x)
+ end
+end
+
+def fun_l27_n852(x)
+ if (x < 1)
+ fun_l28_n917(x)
+ else
+ fun_l28_n95(x)
+ end
+end
+
+def fun_l27_n853(x)
+ if (x < 1)
+ fun_l28_n271(x)
+ else
+ fun_l28_n493(x)
+ end
+end
+
+def fun_l27_n854(x)
+ if (x < 1)
+ fun_l28_n578(x)
+ else
+ fun_l28_n31(x)
+ end
+end
+
+def fun_l27_n855(x)
+ if (x < 1)
+ fun_l28_n407(x)
+ else
+ fun_l28_n694(x)
+ end
+end
+
+def fun_l27_n856(x)
+ if (x < 1)
+ fun_l28_n541(x)
+ else
+ fun_l28_n81(x)
+ end
+end
+
+def fun_l27_n857(x)
+ if (x < 1)
+ fun_l28_n144(x)
+ else
+ fun_l28_n965(x)
+ end
+end
+
+def fun_l27_n858(x)
+ if (x < 1)
+ fun_l28_n476(x)
+ else
+ fun_l28_n44(x)
+ end
+end
+
+def fun_l27_n859(x)
+ if (x < 1)
+ fun_l28_n647(x)
+ else
+ fun_l28_n973(x)
+ end
+end
+
+def fun_l27_n860(x)
+ if (x < 1)
+ fun_l28_n641(x)
+ else
+ fun_l28_n331(x)
+ end
+end
+
+def fun_l27_n861(x)
+ if (x < 1)
+ fun_l28_n75(x)
+ else
+ fun_l28_n10(x)
+ end
+end
+
+def fun_l27_n862(x)
+ if (x < 1)
+ fun_l28_n435(x)
+ else
+ fun_l28_n182(x)
+ end
+end
+
+def fun_l27_n863(x)
+ if (x < 1)
+ fun_l28_n244(x)
+ else
+ fun_l28_n135(x)
+ end
+end
+
+def fun_l27_n864(x)
+ if (x < 1)
+ fun_l28_n598(x)
+ else
+ fun_l28_n495(x)
+ end
+end
+
+def fun_l27_n865(x)
+ if (x < 1)
+ fun_l28_n456(x)
+ else
+ fun_l28_n16(x)
+ end
+end
+
+def fun_l27_n866(x)
+ if (x < 1)
+ fun_l28_n43(x)
+ else
+ fun_l28_n279(x)
+ end
+end
+
+def fun_l27_n867(x)
+ if (x < 1)
+ fun_l28_n853(x)
+ else
+ fun_l28_n906(x)
+ end
+end
+
+def fun_l27_n868(x)
+ if (x < 1)
+ fun_l28_n641(x)
+ else
+ fun_l28_n479(x)
+ end
+end
+
+def fun_l27_n869(x)
+ if (x < 1)
+ fun_l28_n78(x)
+ else
+ fun_l28_n727(x)
+ end
+end
+
+def fun_l27_n870(x)
+ if (x < 1)
+ fun_l28_n815(x)
+ else
+ fun_l28_n803(x)
+ end
+end
+
+def fun_l27_n871(x)
+ if (x < 1)
+ fun_l28_n343(x)
+ else
+ fun_l28_n665(x)
+ end
+end
+
+def fun_l27_n872(x)
+ if (x < 1)
+ fun_l28_n907(x)
+ else
+ fun_l28_n410(x)
+ end
+end
+
+def fun_l27_n873(x)
+ if (x < 1)
+ fun_l28_n797(x)
+ else
+ fun_l28_n626(x)
+ end
+end
+
+def fun_l27_n874(x)
+ if (x < 1)
+ fun_l28_n784(x)
+ else
+ fun_l28_n679(x)
+ end
+end
+
+def fun_l27_n875(x)
+ if (x < 1)
+ fun_l28_n247(x)
+ else
+ fun_l28_n89(x)
+ end
+end
+
+def fun_l27_n876(x)
+ if (x < 1)
+ fun_l28_n911(x)
+ else
+ fun_l28_n503(x)
+ end
+end
+
+def fun_l27_n877(x)
+ if (x < 1)
+ fun_l28_n233(x)
+ else
+ fun_l28_n437(x)
+ end
+end
+
+def fun_l27_n878(x)
+ if (x < 1)
+ fun_l28_n913(x)
+ else
+ fun_l28_n984(x)
+ end
+end
+
+def fun_l27_n879(x)
+ if (x < 1)
+ fun_l28_n690(x)
+ else
+ fun_l28_n642(x)
+ end
+end
+
+def fun_l27_n880(x)
+ if (x < 1)
+ fun_l28_n222(x)
+ else
+ fun_l28_n400(x)
+ end
+end
+
+def fun_l27_n881(x)
+ if (x < 1)
+ fun_l28_n611(x)
+ else
+ fun_l28_n446(x)
+ end
+end
+
+def fun_l27_n882(x)
+ if (x < 1)
+ fun_l28_n821(x)
+ else
+ fun_l28_n784(x)
+ end
+end
+
+def fun_l27_n883(x)
+ if (x < 1)
+ fun_l28_n849(x)
+ else
+ fun_l28_n83(x)
+ end
+end
+
+def fun_l27_n884(x)
+ if (x < 1)
+ fun_l28_n366(x)
+ else
+ fun_l28_n822(x)
+ end
+end
+
+def fun_l27_n885(x)
+ if (x < 1)
+ fun_l28_n40(x)
+ else
+ fun_l28_n626(x)
+ end
+end
+
+def fun_l27_n886(x)
+ if (x < 1)
+ fun_l28_n280(x)
+ else
+ fun_l28_n957(x)
+ end
+end
+
+def fun_l27_n887(x)
+ if (x < 1)
+ fun_l28_n466(x)
+ else
+ fun_l28_n377(x)
+ end
+end
+
+def fun_l27_n888(x)
+ if (x < 1)
+ fun_l28_n258(x)
+ else
+ fun_l28_n816(x)
+ end
+end
+
+def fun_l27_n889(x)
+ if (x < 1)
+ fun_l28_n893(x)
+ else
+ fun_l28_n263(x)
+ end
+end
+
+def fun_l27_n890(x)
+ if (x < 1)
+ fun_l28_n366(x)
+ else
+ fun_l28_n890(x)
+ end
+end
+
+def fun_l27_n891(x)
+ if (x < 1)
+ fun_l28_n692(x)
+ else
+ fun_l28_n781(x)
+ end
+end
+
+def fun_l27_n892(x)
+ if (x < 1)
+ fun_l28_n301(x)
+ else
+ fun_l28_n142(x)
+ end
+end
+
+def fun_l27_n893(x)
+ if (x < 1)
+ fun_l28_n275(x)
+ else
+ fun_l28_n302(x)
+ end
+end
+
+def fun_l27_n894(x)
+ if (x < 1)
+ fun_l28_n726(x)
+ else
+ fun_l28_n445(x)
+ end
+end
+
+def fun_l27_n895(x)
+ if (x < 1)
+ fun_l28_n859(x)
+ else
+ fun_l28_n839(x)
+ end
+end
+
+def fun_l27_n896(x)
+ if (x < 1)
+ fun_l28_n252(x)
+ else
+ fun_l28_n844(x)
+ end
+end
+
+def fun_l27_n897(x)
+ if (x < 1)
+ fun_l28_n245(x)
+ else
+ fun_l28_n133(x)
+ end
+end
+
+def fun_l27_n898(x)
+ if (x < 1)
+ fun_l28_n233(x)
+ else
+ fun_l28_n417(x)
+ end
+end
+
+def fun_l27_n899(x)
+ if (x < 1)
+ fun_l28_n171(x)
+ else
+ fun_l28_n479(x)
+ end
+end
+
+def fun_l27_n900(x)
+ if (x < 1)
+ fun_l28_n528(x)
+ else
+ fun_l28_n196(x)
+ end
+end
+
+def fun_l27_n901(x)
+ if (x < 1)
+ fun_l28_n243(x)
+ else
+ fun_l28_n270(x)
+ end
+end
+
+def fun_l27_n902(x)
+ if (x < 1)
+ fun_l28_n319(x)
+ else
+ fun_l28_n885(x)
+ end
+end
+
+def fun_l27_n903(x)
+ if (x < 1)
+ fun_l28_n570(x)
+ else
+ fun_l28_n321(x)
+ end
+end
+
+def fun_l27_n904(x)
+ if (x < 1)
+ fun_l28_n522(x)
+ else
+ fun_l28_n720(x)
+ end
+end
+
+def fun_l27_n905(x)
+ if (x < 1)
+ fun_l28_n820(x)
+ else
+ fun_l28_n789(x)
+ end
+end
+
+def fun_l27_n906(x)
+ if (x < 1)
+ fun_l28_n592(x)
+ else
+ fun_l28_n113(x)
+ end
+end
+
+def fun_l27_n907(x)
+ if (x < 1)
+ fun_l28_n432(x)
+ else
+ fun_l28_n591(x)
+ end
+end
+
+def fun_l27_n908(x)
+ if (x < 1)
+ fun_l28_n538(x)
+ else
+ fun_l28_n701(x)
+ end
+end
+
+def fun_l27_n909(x)
+ if (x < 1)
+ fun_l28_n963(x)
+ else
+ fun_l28_n756(x)
+ end
+end
+
+def fun_l27_n910(x)
+ if (x < 1)
+ fun_l28_n871(x)
+ else
+ fun_l28_n387(x)
+ end
+end
+
+def fun_l27_n911(x)
+ if (x < 1)
+ fun_l28_n779(x)
+ else
+ fun_l28_n862(x)
+ end
+end
+
+def fun_l27_n912(x)
+ if (x < 1)
+ fun_l28_n0(x)
+ else
+ fun_l28_n208(x)
+ end
+end
+
+def fun_l27_n913(x)
+ if (x < 1)
+ fun_l28_n994(x)
+ else
+ fun_l28_n756(x)
+ end
+end
+
+def fun_l27_n914(x)
+ if (x < 1)
+ fun_l28_n950(x)
+ else
+ fun_l28_n770(x)
+ end
+end
+
+def fun_l27_n915(x)
+ if (x < 1)
+ fun_l28_n922(x)
+ else
+ fun_l28_n372(x)
+ end
+end
+
+def fun_l27_n916(x)
+ if (x < 1)
+ fun_l28_n786(x)
+ else
+ fun_l28_n786(x)
+ end
+end
+
+def fun_l27_n917(x)
+ if (x < 1)
+ fun_l28_n745(x)
+ else
+ fun_l28_n822(x)
+ end
+end
+
+def fun_l27_n918(x)
+ if (x < 1)
+ fun_l28_n69(x)
+ else
+ fun_l28_n669(x)
+ end
+end
+
+def fun_l27_n919(x)
+ if (x < 1)
+ fun_l28_n714(x)
+ else
+ fun_l28_n777(x)
+ end
+end
+
+def fun_l27_n920(x)
+ if (x < 1)
+ fun_l28_n934(x)
+ else
+ fun_l28_n392(x)
+ end
+end
+
+def fun_l27_n921(x)
+ if (x < 1)
+ fun_l28_n746(x)
+ else
+ fun_l28_n355(x)
+ end
+end
+
+def fun_l27_n922(x)
+ if (x < 1)
+ fun_l28_n645(x)
+ else
+ fun_l28_n351(x)
+ end
+end
+
+def fun_l27_n923(x)
+ if (x < 1)
+ fun_l28_n48(x)
+ else
+ fun_l28_n826(x)
+ end
+end
+
+def fun_l27_n924(x)
+ if (x < 1)
+ fun_l28_n531(x)
+ else
+ fun_l28_n577(x)
+ end
+end
+
+def fun_l27_n925(x)
+ if (x < 1)
+ fun_l28_n907(x)
+ else
+ fun_l28_n136(x)
+ end
+end
+
+def fun_l27_n926(x)
+ if (x < 1)
+ fun_l28_n256(x)
+ else
+ fun_l28_n527(x)
+ end
+end
+
+def fun_l27_n927(x)
+ if (x < 1)
+ fun_l28_n870(x)
+ else
+ fun_l28_n475(x)
+ end
+end
+
+def fun_l27_n928(x)
+ if (x < 1)
+ fun_l28_n184(x)
+ else
+ fun_l28_n397(x)
+ end
+end
+
+def fun_l27_n929(x)
+ if (x < 1)
+ fun_l28_n99(x)
+ else
+ fun_l28_n363(x)
+ end
+end
+
+def fun_l27_n930(x)
+ if (x < 1)
+ fun_l28_n217(x)
+ else
+ fun_l28_n978(x)
+ end
+end
+
+def fun_l27_n931(x)
+ if (x < 1)
+ fun_l28_n372(x)
+ else
+ fun_l28_n542(x)
+ end
+end
+
+def fun_l27_n932(x)
+ if (x < 1)
+ fun_l28_n337(x)
+ else
+ fun_l28_n150(x)
+ end
+end
+
+def fun_l27_n933(x)
+ if (x < 1)
+ fun_l28_n81(x)
+ else
+ fun_l28_n206(x)
+ end
+end
+
+def fun_l27_n934(x)
+ if (x < 1)
+ fun_l28_n984(x)
+ else
+ fun_l28_n748(x)
+ end
+end
+
+def fun_l27_n935(x)
+ if (x < 1)
+ fun_l28_n746(x)
+ else
+ fun_l28_n824(x)
+ end
+end
+
+def fun_l27_n936(x)
+ if (x < 1)
+ fun_l28_n737(x)
+ else
+ fun_l28_n353(x)
+ end
+end
+
+def fun_l27_n937(x)
+ if (x < 1)
+ fun_l28_n681(x)
+ else
+ fun_l28_n518(x)
+ end
+end
+
+def fun_l27_n938(x)
+ if (x < 1)
+ fun_l28_n401(x)
+ else
+ fun_l28_n99(x)
+ end
+end
+
+def fun_l27_n939(x)
+ if (x < 1)
+ fun_l28_n821(x)
+ else
+ fun_l28_n456(x)
+ end
+end
+
+def fun_l27_n940(x)
+ if (x < 1)
+ fun_l28_n411(x)
+ else
+ fun_l28_n578(x)
+ end
+end
+
+def fun_l27_n941(x)
+ if (x < 1)
+ fun_l28_n318(x)
+ else
+ fun_l28_n479(x)
+ end
+end
+
+def fun_l27_n942(x)
+ if (x < 1)
+ fun_l28_n229(x)
+ else
+ fun_l28_n338(x)
+ end
+end
+
+def fun_l27_n943(x)
+ if (x < 1)
+ fun_l28_n195(x)
+ else
+ fun_l28_n667(x)
+ end
+end
+
+def fun_l27_n944(x)
+ if (x < 1)
+ fun_l28_n256(x)
+ else
+ fun_l28_n309(x)
+ end
+end
+
+def fun_l27_n945(x)
+ if (x < 1)
+ fun_l28_n939(x)
+ else
+ fun_l28_n284(x)
+ end
+end
+
+def fun_l27_n946(x)
+ if (x < 1)
+ fun_l28_n70(x)
+ else
+ fun_l28_n408(x)
+ end
+end
+
+def fun_l27_n947(x)
+ if (x < 1)
+ fun_l28_n586(x)
+ else
+ fun_l28_n931(x)
+ end
+end
+
+def fun_l27_n948(x)
+ if (x < 1)
+ fun_l28_n878(x)
+ else
+ fun_l28_n95(x)
+ end
+end
+
+def fun_l27_n949(x)
+ if (x < 1)
+ fun_l28_n749(x)
+ else
+ fun_l28_n414(x)
+ end
+end
+
+def fun_l27_n950(x)
+ if (x < 1)
+ fun_l28_n913(x)
+ else
+ fun_l28_n933(x)
+ end
+end
+
+def fun_l27_n951(x)
+ if (x < 1)
+ fun_l28_n394(x)
+ else
+ fun_l28_n121(x)
+ end
+end
+
+def fun_l27_n952(x)
+ if (x < 1)
+ fun_l28_n381(x)
+ else
+ fun_l28_n279(x)
+ end
+end
+
+def fun_l27_n953(x)
+ if (x < 1)
+ fun_l28_n302(x)
+ else
+ fun_l28_n710(x)
+ end
+end
+
+def fun_l27_n954(x)
+ if (x < 1)
+ fun_l28_n765(x)
+ else
+ fun_l28_n254(x)
+ end
+end
+
+def fun_l27_n955(x)
+ if (x < 1)
+ fun_l28_n736(x)
+ else
+ fun_l28_n67(x)
+ end
+end
+
+def fun_l27_n956(x)
+ if (x < 1)
+ fun_l28_n61(x)
+ else
+ fun_l28_n873(x)
+ end
+end
+
+def fun_l27_n957(x)
+ if (x < 1)
+ fun_l28_n920(x)
+ else
+ fun_l28_n261(x)
+ end
+end
+
+def fun_l27_n958(x)
+ if (x < 1)
+ fun_l28_n350(x)
+ else
+ fun_l28_n545(x)
+ end
+end
+
+def fun_l27_n959(x)
+ if (x < 1)
+ fun_l28_n538(x)
+ else
+ fun_l28_n829(x)
+ end
+end
+
+def fun_l27_n960(x)
+ if (x < 1)
+ fun_l28_n920(x)
+ else
+ fun_l28_n534(x)
+ end
+end
+
+def fun_l27_n961(x)
+ if (x < 1)
+ fun_l28_n730(x)
+ else
+ fun_l28_n19(x)
+ end
+end
+
+def fun_l27_n962(x)
+ if (x < 1)
+ fun_l28_n293(x)
+ else
+ fun_l28_n187(x)
+ end
+end
+
+def fun_l27_n963(x)
+ if (x < 1)
+ fun_l28_n169(x)
+ else
+ fun_l28_n751(x)
+ end
+end
+
+def fun_l27_n964(x)
+ if (x < 1)
+ fun_l28_n195(x)
+ else
+ fun_l28_n112(x)
+ end
+end
+
+def fun_l27_n965(x)
+ if (x < 1)
+ fun_l28_n756(x)
+ else
+ fun_l28_n700(x)
+ end
+end
+
+def fun_l27_n966(x)
+ if (x < 1)
+ fun_l28_n739(x)
+ else
+ fun_l28_n320(x)
+ end
+end
+
+def fun_l27_n967(x)
+ if (x < 1)
+ fun_l28_n693(x)
+ else
+ fun_l28_n101(x)
+ end
+end
+
+def fun_l27_n968(x)
+ if (x < 1)
+ fun_l28_n94(x)
+ else
+ fun_l28_n131(x)
+ end
+end
+
+def fun_l27_n969(x)
+ if (x < 1)
+ fun_l28_n142(x)
+ else
+ fun_l28_n839(x)
+ end
+end
+
+def fun_l27_n970(x)
+ if (x < 1)
+ fun_l28_n792(x)
+ else
+ fun_l28_n243(x)
+ end
+end
+
+def fun_l27_n971(x)
+ if (x < 1)
+ fun_l28_n268(x)
+ else
+ fun_l28_n525(x)
+ end
+end
+
+def fun_l27_n972(x)
+ if (x < 1)
+ fun_l28_n776(x)
+ else
+ fun_l28_n117(x)
+ end
+end
+
+def fun_l27_n973(x)
+ if (x < 1)
+ fun_l28_n401(x)
+ else
+ fun_l28_n571(x)
+ end
+end
+
+def fun_l27_n974(x)
+ if (x < 1)
+ fun_l28_n515(x)
+ else
+ fun_l28_n5(x)
+ end
+end
+
+def fun_l27_n975(x)
+ if (x < 1)
+ fun_l28_n225(x)
+ else
+ fun_l28_n956(x)
+ end
+end
+
+def fun_l27_n976(x)
+ if (x < 1)
+ fun_l28_n536(x)
+ else
+ fun_l28_n379(x)
+ end
+end
+
+def fun_l27_n977(x)
+ if (x < 1)
+ fun_l28_n942(x)
+ else
+ fun_l28_n665(x)
+ end
+end
+
+def fun_l27_n978(x)
+ if (x < 1)
+ fun_l28_n753(x)
+ else
+ fun_l28_n807(x)
+ end
+end
+
+def fun_l27_n979(x)
+ if (x < 1)
+ fun_l28_n206(x)
+ else
+ fun_l28_n548(x)
+ end
+end
+
+def fun_l27_n980(x)
+ if (x < 1)
+ fun_l28_n149(x)
+ else
+ fun_l28_n126(x)
+ end
+end
+
+def fun_l27_n981(x)
+ if (x < 1)
+ fun_l28_n829(x)
+ else
+ fun_l28_n384(x)
+ end
+end
+
+def fun_l27_n982(x)
+ if (x < 1)
+ fun_l28_n764(x)
+ else
+ fun_l28_n554(x)
+ end
+end
+
+def fun_l27_n983(x)
+ if (x < 1)
+ fun_l28_n868(x)
+ else
+ fun_l28_n933(x)
+ end
+end
+
+def fun_l27_n984(x)
+ if (x < 1)
+ fun_l28_n627(x)
+ else
+ fun_l28_n791(x)
+ end
+end
+
+def fun_l27_n985(x)
+ if (x < 1)
+ fun_l28_n796(x)
+ else
+ fun_l28_n352(x)
+ end
+end
+
+def fun_l27_n986(x)
+ if (x < 1)
+ fun_l28_n213(x)
+ else
+ fun_l28_n282(x)
+ end
+end
+
+def fun_l27_n987(x)
+ if (x < 1)
+ fun_l28_n403(x)
+ else
+ fun_l28_n504(x)
+ end
+end
+
+def fun_l27_n988(x)
+ if (x < 1)
+ fun_l28_n78(x)
+ else
+ fun_l28_n283(x)
+ end
+end
+
+def fun_l27_n989(x)
+ if (x < 1)
+ fun_l28_n364(x)
+ else
+ fun_l28_n802(x)
+ end
+end
+
+def fun_l27_n990(x)
+ if (x < 1)
+ fun_l28_n508(x)
+ else
+ fun_l28_n561(x)
+ end
+end
+
+def fun_l27_n991(x)
+ if (x < 1)
+ fun_l28_n922(x)
+ else
+ fun_l28_n901(x)
+ end
+end
+
+def fun_l27_n992(x)
+ if (x < 1)
+ fun_l28_n103(x)
+ else
+ fun_l28_n275(x)
+ end
+end
+
+def fun_l27_n993(x)
+ if (x < 1)
+ fun_l28_n566(x)
+ else
+ fun_l28_n88(x)
+ end
+end
+
+def fun_l27_n994(x)
+ if (x < 1)
+ fun_l28_n174(x)
+ else
+ fun_l28_n741(x)
+ end
+end
+
+def fun_l27_n995(x)
+ if (x < 1)
+ fun_l28_n40(x)
+ else
+ fun_l28_n426(x)
+ end
+end
+
+def fun_l27_n996(x)
+ if (x < 1)
+ fun_l28_n941(x)
+ else
+ fun_l28_n941(x)
+ end
+end
+
+def fun_l27_n997(x)
+ if (x < 1)
+ fun_l28_n651(x)
+ else
+ fun_l28_n301(x)
+ end
+end
+
+def fun_l27_n998(x)
+ if (x < 1)
+ fun_l28_n789(x)
+ else
+ fun_l28_n720(x)
+ end
+end
+
+def fun_l27_n999(x)
+ if (x < 1)
+ fun_l28_n536(x)
+ else
+ fun_l28_n903(x)
+ end
+end
+
+def fun_l28_n0(x)
+ if (x < 1)
+ fun_l29_n585(x)
+ else
+ fun_l29_n979(x)
+ end
+end
+
+def fun_l28_n1(x)
+ if (x < 1)
+ fun_l29_n182(x)
+ else
+ fun_l29_n513(x)
+ end
+end
+
+def fun_l28_n2(x)
+ if (x < 1)
+ fun_l29_n975(x)
+ else
+ fun_l29_n445(x)
+ end
+end
+
+def fun_l28_n3(x)
+ if (x < 1)
+ fun_l29_n7(x)
+ else
+ fun_l29_n958(x)
+ end
+end
+
+def fun_l28_n4(x)
+ if (x < 1)
+ fun_l29_n751(x)
+ else
+ fun_l29_n426(x)
+ end
+end
+
+def fun_l28_n5(x)
+ if (x < 1)
+ fun_l29_n29(x)
+ else
+ fun_l29_n840(x)
+ end
+end
+
+def fun_l28_n6(x)
+ if (x < 1)
+ fun_l29_n571(x)
+ else
+ fun_l29_n971(x)
+ end
+end
+
+def fun_l28_n7(x)
+ if (x < 1)
+ fun_l29_n384(x)
+ else
+ fun_l29_n495(x)
+ end
+end
+
+def fun_l28_n8(x)
+ if (x < 1)
+ fun_l29_n185(x)
+ else
+ fun_l29_n507(x)
+ end
+end
+
+def fun_l28_n9(x)
+ if (x < 1)
+ fun_l29_n496(x)
+ else
+ fun_l29_n241(x)
+ end
+end
+
+def fun_l28_n10(x)
+ if (x < 1)
+ fun_l29_n494(x)
+ else
+ fun_l29_n473(x)
+ end
+end
+
+def fun_l28_n11(x)
+ if (x < 1)
+ fun_l29_n851(x)
+ else
+ fun_l29_n809(x)
+ end
+end
+
+def fun_l28_n12(x)
+ if (x < 1)
+ fun_l29_n875(x)
+ else
+ fun_l29_n135(x)
+ end
+end
+
+def fun_l28_n13(x)
+ if (x < 1)
+ fun_l29_n957(x)
+ else
+ fun_l29_n337(x)
+ end
+end
+
+def fun_l28_n14(x)
+ if (x < 1)
+ fun_l29_n82(x)
+ else
+ fun_l29_n901(x)
+ end
+end
+
+def fun_l28_n15(x)
+ if (x < 1)
+ fun_l29_n608(x)
+ else
+ fun_l29_n334(x)
+ end
+end
+
+def fun_l28_n16(x)
+ if (x < 1)
+ fun_l29_n772(x)
+ else
+ fun_l29_n912(x)
+ end
+end
+
+def fun_l28_n17(x)
+ if (x < 1)
+ fun_l29_n971(x)
+ else
+ fun_l29_n127(x)
+ end
+end
+
+def fun_l28_n18(x)
+ if (x < 1)
+ fun_l29_n667(x)
+ else
+ fun_l29_n347(x)
+ end
+end
+
+def fun_l28_n19(x)
+ if (x < 1)
+ fun_l29_n453(x)
+ else
+ fun_l29_n39(x)
+ end
+end
+
+def fun_l28_n20(x)
+ if (x < 1)
+ fun_l29_n853(x)
+ else
+ fun_l29_n747(x)
+ end
+end
+
+def fun_l28_n21(x)
+ if (x < 1)
+ fun_l29_n433(x)
+ else
+ fun_l29_n298(x)
+ end
+end
+
+def fun_l28_n22(x)
+ if (x < 1)
+ fun_l29_n94(x)
+ else
+ fun_l29_n307(x)
+ end
+end
+
+def fun_l28_n23(x)
+ if (x < 1)
+ fun_l29_n424(x)
+ else
+ fun_l29_n599(x)
+ end
+end
+
+def fun_l28_n24(x)
+ if (x < 1)
+ fun_l29_n986(x)
+ else
+ fun_l29_n232(x)
+ end
+end
+
+def fun_l28_n25(x)
+ if (x < 1)
+ fun_l29_n658(x)
+ else
+ fun_l29_n744(x)
+ end
+end
+
+def fun_l28_n26(x)
+ if (x < 1)
+ fun_l29_n151(x)
+ else
+ fun_l29_n855(x)
+ end
+end
+
+def fun_l28_n27(x)
+ if (x < 1)
+ fun_l29_n416(x)
+ else
+ fun_l29_n763(x)
+ end
+end
+
+def fun_l28_n28(x)
+ if (x < 1)
+ fun_l29_n489(x)
+ else
+ fun_l29_n55(x)
+ end
+end
+
+def fun_l28_n29(x)
+ if (x < 1)
+ fun_l29_n714(x)
+ else
+ fun_l29_n489(x)
+ end
+end
+
+def fun_l28_n30(x)
+ if (x < 1)
+ fun_l29_n328(x)
+ else
+ fun_l29_n476(x)
+ end
+end
+
+def fun_l28_n31(x)
+ if (x < 1)
+ fun_l29_n317(x)
+ else
+ fun_l29_n836(x)
+ end
+end
+
+def fun_l28_n32(x)
+ if (x < 1)
+ fun_l29_n970(x)
+ else
+ fun_l29_n48(x)
+ end
+end
+
+def fun_l28_n33(x)
+ if (x < 1)
+ fun_l29_n159(x)
+ else
+ fun_l29_n449(x)
+ end
+end
+
+def fun_l28_n34(x)
+ if (x < 1)
+ fun_l29_n80(x)
+ else
+ fun_l29_n994(x)
+ end
+end
+
+def fun_l28_n35(x)
+ if (x < 1)
+ fun_l29_n413(x)
+ else
+ fun_l29_n718(x)
+ end
+end
+
+def fun_l28_n36(x)
+ if (x < 1)
+ fun_l29_n196(x)
+ else
+ fun_l29_n713(x)
+ end
+end
+
+def fun_l28_n37(x)
+ if (x < 1)
+ fun_l29_n815(x)
+ else
+ fun_l29_n595(x)
+ end
+end
+
+def fun_l28_n38(x)
+ if (x < 1)
+ fun_l29_n862(x)
+ else
+ fun_l29_n546(x)
+ end
+end
+
+def fun_l28_n39(x)
+ if (x < 1)
+ fun_l29_n875(x)
+ else
+ fun_l29_n456(x)
+ end
+end
+
+def fun_l28_n40(x)
+ if (x < 1)
+ fun_l29_n424(x)
+ else
+ fun_l29_n445(x)
+ end
+end
+
+def fun_l28_n41(x)
+ if (x < 1)
+ fun_l29_n743(x)
+ else
+ fun_l29_n498(x)
+ end
+end
+
+def fun_l28_n42(x)
+ if (x < 1)
+ fun_l29_n950(x)
+ else
+ fun_l29_n497(x)
+ end
+end
+
+def fun_l28_n43(x)
+ if (x < 1)
+ fun_l29_n792(x)
+ else
+ fun_l29_n487(x)
+ end
+end
+
+def fun_l28_n44(x)
+ if (x < 1)
+ fun_l29_n421(x)
+ else
+ fun_l29_n484(x)
+ end
+end
+
+def fun_l28_n45(x)
+ if (x < 1)
+ fun_l29_n862(x)
+ else
+ fun_l29_n824(x)
+ end
+end
+
+def fun_l28_n46(x)
+ if (x < 1)
+ fun_l29_n163(x)
+ else
+ fun_l29_n184(x)
+ end
+end
+
+def fun_l28_n47(x)
+ if (x < 1)
+ fun_l29_n374(x)
+ else
+ fun_l29_n954(x)
+ end
+end
+
+def fun_l28_n48(x)
+ if (x < 1)
+ fun_l29_n422(x)
+ else
+ fun_l29_n223(x)
+ end
+end
+
+def fun_l28_n49(x)
+ if (x < 1)
+ fun_l29_n885(x)
+ else
+ fun_l29_n527(x)
+ end
+end
+
+def fun_l28_n50(x)
+ if (x < 1)
+ fun_l29_n694(x)
+ else
+ fun_l29_n702(x)
+ end
+end
+
+def fun_l28_n51(x)
+ if (x < 1)
+ fun_l29_n273(x)
+ else
+ fun_l29_n504(x)
+ end
+end
+
+def fun_l28_n52(x)
+ if (x < 1)
+ fun_l29_n330(x)
+ else
+ fun_l29_n267(x)
+ end
+end
+
+def fun_l28_n53(x)
+ if (x < 1)
+ fun_l29_n103(x)
+ else
+ fun_l29_n407(x)
+ end
+end
+
+def fun_l28_n54(x)
+ if (x < 1)
+ fun_l29_n210(x)
+ else
+ fun_l29_n645(x)
+ end
+end
+
+def fun_l28_n55(x)
+ if (x < 1)
+ fun_l29_n871(x)
+ else
+ fun_l29_n641(x)
+ end
+end
+
+def fun_l28_n56(x)
+ if (x < 1)
+ fun_l29_n233(x)
+ else
+ fun_l29_n715(x)
+ end
+end
+
+def fun_l28_n57(x)
+ if (x < 1)
+ fun_l29_n742(x)
+ else
+ fun_l29_n104(x)
+ end
+end
+
+def fun_l28_n58(x)
+ if (x < 1)
+ fun_l29_n713(x)
+ else
+ fun_l29_n919(x)
+ end
+end
+
+def fun_l28_n59(x)
+ if (x < 1)
+ fun_l29_n192(x)
+ else
+ fun_l29_n988(x)
+ end
+end
+
+def fun_l28_n60(x)
+ if (x < 1)
+ fun_l29_n533(x)
+ else
+ fun_l29_n972(x)
+ end
+end
+
+def fun_l28_n61(x)
+ if (x < 1)
+ fun_l29_n286(x)
+ else
+ fun_l29_n129(x)
+ end
+end
+
+def fun_l28_n62(x)
+ if (x < 1)
+ fun_l29_n208(x)
+ else
+ fun_l29_n715(x)
+ end
+end
+
+def fun_l28_n63(x)
+ if (x < 1)
+ fun_l29_n588(x)
+ else
+ fun_l29_n975(x)
+ end
+end
+
+def fun_l28_n64(x)
+ if (x < 1)
+ fun_l29_n202(x)
+ else
+ fun_l29_n784(x)
+ end
+end
+
+def fun_l28_n65(x)
+ if (x < 1)
+ fun_l29_n531(x)
+ else
+ fun_l29_n758(x)
+ end
+end
+
+def fun_l28_n66(x)
+ if (x < 1)
+ fun_l29_n102(x)
+ else
+ fun_l29_n23(x)
+ end
+end
+
+def fun_l28_n67(x)
+ if (x < 1)
+ fun_l29_n546(x)
+ else
+ fun_l29_n964(x)
+ end
+end
+
+def fun_l28_n68(x)
+ if (x < 1)
+ fun_l29_n31(x)
+ else
+ fun_l29_n223(x)
+ end
+end
+
+def fun_l28_n69(x)
+ if (x < 1)
+ fun_l29_n344(x)
+ else
+ fun_l29_n250(x)
+ end
+end
+
+def fun_l28_n70(x)
+ if (x < 1)
+ fun_l29_n910(x)
+ else
+ fun_l29_n880(x)
+ end
+end
+
+def fun_l28_n71(x)
+ if (x < 1)
+ fun_l29_n181(x)
+ else
+ fun_l29_n950(x)
+ end
+end
+
+def fun_l28_n72(x)
+ if (x < 1)
+ fun_l29_n405(x)
+ else
+ fun_l29_n105(x)
+ end
+end
+
+def fun_l28_n73(x)
+ if (x < 1)
+ fun_l29_n419(x)
+ else
+ fun_l29_n120(x)
+ end
+end
+
+def fun_l28_n74(x)
+ if (x < 1)
+ fun_l29_n485(x)
+ else
+ fun_l29_n616(x)
+ end
+end
+
+def fun_l28_n75(x)
+ if (x < 1)
+ fun_l29_n690(x)
+ else
+ fun_l29_n581(x)
+ end
+end
+
+def fun_l28_n76(x)
+ if (x < 1)
+ fun_l29_n68(x)
+ else
+ fun_l29_n47(x)
+ end
+end
+
+def fun_l28_n77(x)
+ if (x < 1)
+ fun_l29_n324(x)
+ else
+ fun_l29_n102(x)
+ end
+end
+
+def fun_l28_n78(x)
+ if (x < 1)
+ fun_l29_n416(x)
+ else
+ fun_l29_n965(x)
+ end
+end
+
+def fun_l28_n79(x)
+ if (x < 1)
+ fun_l29_n584(x)
+ else
+ fun_l29_n901(x)
+ end
+end
+
+def fun_l28_n80(x)
+ if (x < 1)
+ fun_l29_n914(x)
+ else
+ fun_l29_n890(x)
+ end
+end
+
+def fun_l28_n81(x)
+ if (x < 1)
+ fun_l29_n85(x)
+ else
+ fun_l29_n822(x)
+ end
+end
+
+def fun_l28_n82(x)
+ if (x < 1)
+ fun_l29_n311(x)
+ else
+ fun_l29_n621(x)
+ end
+end
+
+def fun_l28_n83(x)
+ if (x < 1)
+ fun_l29_n361(x)
+ else
+ fun_l29_n336(x)
+ end
+end
+
+def fun_l28_n84(x)
+ if (x < 1)
+ fun_l29_n642(x)
+ else
+ fun_l29_n495(x)
+ end
+end
+
+def fun_l28_n85(x)
+ if (x < 1)
+ fun_l29_n688(x)
+ else
+ fun_l29_n20(x)
+ end
+end
+
+def fun_l28_n86(x)
+ if (x < 1)
+ fun_l29_n805(x)
+ else
+ fun_l29_n363(x)
+ end
+end
+
+def fun_l28_n87(x)
+ if (x < 1)
+ fun_l29_n215(x)
+ else
+ fun_l29_n530(x)
+ end
+end
+
+def fun_l28_n88(x)
+ if (x < 1)
+ fun_l29_n355(x)
+ else
+ fun_l29_n820(x)
+ end
+end
+
+def fun_l28_n89(x)
+ if (x < 1)
+ fun_l29_n593(x)
+ else
+ fun_l29_n443(x)
+ end
+end
+
+def fun_l28_n90(x)
+ if (x < 1)
+ fun_l29_n917(x)
+ else
+ fun_l29_n920(x)
+ end
+end
+
+def fun_l28_n91(x)
+ if (x < 1)
+ fun_l29_n571(x)
+ else
+ fun_l29_n545(x)
+ end
+end
+
+def fun_l28_n92(x)
+ if (x < 1)
+ fun_l29_n871(x)
+ else
+ fun_l29_n497(x)
+ end
+end
+
+def fun_l28_n93(x)
+ if (x < 1)
+ fun_l29_n433(x)
+ else
+ fun_l29_n899(x)
+ end
+end
+
+def fun_l28_n94(x)
+ if (x < 1)
+ fun_l29_n139(x)
+ else
+ fun_l29_n836(x)
+ end
+end
+
+def fun_l28_n95(x)
+ if (x < 1)
+ fun_l29_n265(x)
+ else
+ fun_l29_n297(x)
+ end
+end
+
+def fun_l28_n96(x)
+ if (x < 1)
+ fun_l29_n554(x)
+ else
+ fun_l29_n345(x)
+ end
+end
+
+def fun_l28_n97(x)
+ if (x < 1)
+ fun_l29_n674(x)
+ else
+ fun_l29_n632(x)
+ end
+end
+
+def fun_l28_n98(x)
+ if (x < 1)
+ fun_l29_n287(x)
+ else
+ fun_l29_n606(x)
+ end
+end
+
+def fun_l28_n99(x)
+ if (x < 1)
+ fun_l29_n288(x)
+ else
+ fun_l29_n751(x)
+ end
+end
+
+def fun_l28_n100(x)
+ if (x < 1)
+ fun_l29_n673(x)
+ else
+ fun_l29_n461(x)
+ end
+end
+
+def fun_l28_n101(x)
+ if (x < 1)
+ fun_l29_n633(x)
+ else
+ fun_l29_n688(x)
+ end
+end
+
+def fun_l28_n102(x)
+ if (x < 1)
+ fun_l29_n487(x)
+ else
+ fun_l29_n879(x)
+ end
+end
+
+def fun_l28_n103(x)
+ if (x < 1)
+ fun_l29_n12(x)
+ else
+ fun_l29_n808(x)
+ end
+end
+
+def fun_l28_n104(x)
+ if (x < 1)
+ fun_l29_n560(x)
+ else
+ fun_l29_n174(x)
+ end
+end
+
+def fun_l28_n105(x)
+ if (x < 1)
+ fun_l29_n379(x)
+ else
+ fun_l29_n509(x)
+ end
+end
+
+def fun_l28_n106(x)
+ if (x < 1)
+ fun_l29_n848(x)
+ else
+ fun_l29_n783(x)
+ end
+end
+
+def fun_l28_n107(x)
+ if (x < 1)
+ fun_l29_n564(x)
+ else
+ fun_l29_n584(x)
+ end
+end
+
+def fun_l28_n108(x)
+ if (x < 1)
+ fun_l29_n251(x)
+ else
+ fun_l29_n77(x)
+ end
+end
+
+def fun_l28_n109(x)
+ if (x < 1)
+ fun_l29_n588(x)
+ else
+ fun_l29_n351(x)
+ end
+end
+
+def fun_l28_n110(x)
+ if (x < 1)
+ fun_l29_n43(x)
+ else
+ fun_l29_n102(x)
+ end
+end
+
+def fun_l28_n111(x)
+ if (x < 1)
+ fun_l29_n33(x)
+ else
+ fun_l29_n168(x)
+ end
+end
+
+def fun_l28_n112(x)
+ if (x < 1)
+ fun_l29_n977(x)
+ else
+ fun_l29_n832(x)
+ end
+end
+
+def fun_l28_n113(x)
+ if (x < 1)
+ fun_l29_n189(x)
+ else
+ fun_l29_n657(x)
+ end
+end
+
+def fun_l28_n114(x)
+ if (x < 1)
+ fun_l29_n833(x)
+ else
+ fun_l29_n237(x)
+ end
+end
+
+def fun_l28_n115(x)
+ if (x < 1)
+ fun_l29_n621(x)
+ else
+ fun_l29_n675(x)
+ end
+end
+
+def fun_l28_n116(x)
+ if (x < 1)
+ fun_l29_n944(x)
+ else
+ fun_l29_n469(x)
+ end
+end
+
+def fun_l28_n117(x)
+ if (x < 1)
+ fun_l29_n2(x)
+ else
+ fun_l29_n959(x)
+ end
+end
+
+def fun_l28_n118(x)
+ if (x < 1)
+ fun_l29_n260(x)
+ else
+ fun_l29_n580(x)
+ end
+end
+
+def fun_l28_n119(x)
+ if (x < 1)
+ fun_l29_n464(x)
+ else
+ fun_l29_n411(x)
+ end
+end
+
+def fun_l28_n120(x)
+ if (x < 1)
+ fun_l29_n973(x)
+ else
+ fun_l29_n837(x)
+ end
+end
+
+def fun_l28_n121(x)
+ if (x < 1)
+ fun_l29_n511(x)
+ else
+ fun_l29_n896(x)
+ end
+end
+
+def fun_l28_n122(x)
+ if (x < 1)
+ fun_l29_n621(x)
+ else
+ fun_l29_n952(x)
+ end
+end
+
+def fun_l28_n123(x)
+ if (x < 1)
+ fun_l29_n250(x)
+ else
+ fun_l29_n551(x)
+ end
+end
+
+def fun_l28_n124(x)
+ if (x < 1)
+ fun_l29_n761(x)
+ else
+ fun_l29_n659(x)
+ end
+end
+
+def fun_l28_n125(x)
+ if (x < 1)
+ fun_l29_n43(x)
+ else
+ fun_l29_n265(x)
+ end
+end
+
+def fun_l28_n126(x)
+ if (x < 1)
+ fun_l29_n794(x)
+ else
+ fun_l29_n953(x)
+ end
+end
+
+def fun_l28_n127(x)
+ if (x < 1)
+ fun_l29_n858(x)
+ else
+ fun_l29_n582(x)
+ end
+end
+
+def fun_l28_n128(x)
+ if (x < 1)
+ fun_l29_n762(x)
+ else
+ fun_l29_n710(x)
+ end
+end
+
+def fun_l28_n129(x)
+ if (x < 1)
+ fun_l29_n541(x)
+ else
+ fun_l29_n182(x)
+ end
+end
+
+def fun_l28_n130(x)
+ if (x < 1)
+ fun_l29_n325(x)
+ else
+ fun_l29_n318(x)
+ end
+end
+
+def fun_l28_n131(x)
+ if (x < 1)
+ fun_l29_n751(x)
+ else
+ fun_l29_n499(x)
+ end
+end
+
+def fun_l28_n132(x)
+ if (x < 1)
+ fun_l29_n185(x)
+ else
+ fun_l29_n547(x)
+ end
+end
+
+def fun_l28_n133(x)
+ if (x < 1)
+ fun_l29_n155(x)
+ else
+ fun_l29_n691(x)
+ end
+end
+
+def fun_l28_n134(x)
+ if (x < 1)
+ fun_l29_n326(x)
+ else
+ fun_l29_n950(x)
+ end
+end
+
+def fun_l28_n135(x)
+ if (x < 1)
+ fun_l29_n782(x)
+ else
+ fun_l29_n968(x)
+ end
+end
+
+def fun_l28_n136(x)
+ if (x < 1)
+ fun_l29_n349(x)
+ else
+ fun_l29_n668(x)
+ end
+end
+
+def fun_l28_n137(x)
+ if (x < 1)
+ fun_l29_n897(x)
+ else
+ fun_l29_n243(x)
+ end
+end
+
+def fun_l28_n138(x)
+ if (x < 1)
+ fun_l29_n994(x)
+ else
+ fun_l29_n84(x)
+ end
+end
+
+def fun_l28_n139(x)
+ if (x < 1)
+ fun_l29_n95(x)
+ else
+ fun_l29_n705(x)
+ end
+end
+
+def fun_l28_n140(x)
+ if (x < 1)
+ fun_l29_n864(x)
+ else
+ fun_l29_n636(x)
+ end
+end
+
+def fun_l28_n141(x)
+ if (x < 1)
+ fun_l29_n587(x)
+ else
+ fun_l29_n908(x)
+ end
+end
+
+def fun_l28_n142(x)
+ if (x < 1)
+ fun_l29_n255(x)
+ else
+ fun_l29_n633(x)
+ end
+end
+
+def fun_l28_n143(x)
+ if (x < 1)
+ fun_l29_n142(x)
+ else
+ fun_l29_n305(x)
+ end
+end
+
+def fun_l28_n144(x)
+ if (x < 1)
+ fun_l29_n735(x)
+ else
+ fun_l29_n637(x)
+ end
+end
+
+def fun_l28_n145(x)
+ if (x < 1)
+ fun_l29_n637(x)
+ else
+ fun_l29_n975(x)
+ end
+end
+
+def fun_l28_n146(x)
+ if (x < 1)
+ fun_l29_n560(x)
+ else
+ fun_l29_n534(x)
+ end
+end
+
+def fun_l28_n147(x)
+ if (x < 1)
+ fun_l29_n829(x)
+ else
+ fun_l29_n344(x)
+ end
+end
+
+def fun_l28_n148(x)
+ if (x < 1)
+ fun_l29_n38(x)
+ else
+ fun_l29_n339(x)
+ end
+end
+
+def fun_l28_n149(x)
+ if (x < 1)
+ fun_l29_n178(x)
+ else
+ fun_l29_n178(x)
+ end
+end
+
+def fun_l28_n150(x)
+ if (x < 1)
+ fun_l29_n434(x)
+ else
+ fun_l29_n677(x)
+ end
+end
+
+def fun_l28_n151(x)
+ if (x < 1)
+ fun_l29_n910(x)
+ else
+ fun_l29_n230(x)
+ end
+end
+
+def fun_l28_n152(x)
+ if (x < 1)
+ fun_l29_n750(x)
+ else
+ fun_l29_n534(x)
+ end
+end
+
+def fun_l28_n153(x)
+ if (x < 1)
+ fun_l29_n550(x)
+ else
+ fun_l29_n757(x)
+ end
+end
+
+def fun_l28_n154(x)
+ if (x < 1)
+ fun_l29_n832(x)
+ else
+ fun_l29_n177(x)
+ end
+end
+
+def fun_l28_n155(x)
+ if (x < 1)
+ fun_l29_n724(x)
+ else
+ fun_l29_n669(x)
+ end
+end
+
+def fun_l28_n156(x)
+ if (x < 1)
+ fun_l29_n362(x)
+ else
+ fun_l29_n882(x)
+ end
+end
+
+def fun_l28_n157(x)
+ if (x < 1)
+ fun_l29_n164(x)
+ else
+ fun_l29_n919(x)
+ end
+end
+
+def fun_l28_n158(x)
+ if (x < 1)
+ fun_l29_n300(x)
+ else
+ fun_l29_n343(x)
+ end
+end
+
+def fun_l28_n159(x)
+ if (x < 1)
+ fun_l29_n395(x)
+ else
+ fun_l29_n535(x)
+ end
+end
+
+def fun_l28_n160(x)
+ if (x < 1)
+ fun_l29_n127(x)
+ else
+ fun_l29_n666(x)
+ end
+end
+
+def fun_l28_n161(x)
+ if (x < 1)
+ fun_l29_n207(x)
+ else
+ fun_l29_n935(x)
+ end
+end
+
+def fun_l28_n162(x)
+ if (x < 1)
+ fun_l29_n865(x)
+ else
+ fun_l29_n692(x)
+ end
+end
+
+def fun_l28_n163(x)
+ if (x < 1)
+ fun_l29_n429(x)
+ else
+ fun_l29_n329(x)
+ end
+end
+
+def fun_l28_n164(x)
+ if (x < 1)
+ fun_l29_n874(x)
+ else
+ fun_l29_n650(x)
+ end
+end
+
+def fun_l28_n165(x)
+ if (x < 1)
+ fun_l29_n985(x)
+ else
+ fun_l29_n488(x)
+ end
+end
+
+def fun_l28_n166(x)
+ if (x < 1)
+ fun_l29_n425(x)
+ else
+ fun_l29_n297(x)
+ end
+end
+
+def fun_l28_n167(x)
+ if (x < 1)
+ fun_l29_n468(x)
+ else
+ fun_l29_n331(x)
+ end
+end
+
+def fun_l28_n168(x)
+ if (x < 1)
+ fun_l29_n991(x)
+ else
+ fun_l29_n399(x)
+ end
+end
+
+def fun_l28_n169(x)
+ if (x < 1)
+ fun_l29_n402(x)
+ else
+ fun_l29_n931(x)
+ end
+end
+
+def fun_l28_n170(x)
+ if (x < 1)
+ fun_l29_n984(x)
+ else
+ fun_l29_n586(x)
+ end
+end
+
+def fun_l28_n171(x)
+ if (x < 1)
+ fun_l29_n305(x)
+ else
+ fun_l29_n638(x)
+ end
+end
+
+def fun_l28_n172(x)
+ if (x < 1)
+ fun_l29_n251(x)
+ else
+ fun_l29_n94(x)
+ end
+end
+
+def fun_l28_n173(x)
+ if (x < 1)
+ fun_l29_n225(x)
+ else
+ fun_l29_n466(x)
+ end
+end
+
+def fun_l28_n174(x)
+ if (x < 1)
+ fun_l29_n643(x)
+ else
+ fun_l29_n974(x)
+ end
+end
+
+def fun_l28_n175(x)
+ if (x < 1)
+ fun_l29_n634(x)
+ else
+ fun_l29_n321(x)
+ end
+end
+
+def fun_l28_n176(x)
+ if (x < 1)
+ fun_l29_n269(x)
+ else
+ fun_l29_n237(x)
+ end
+end
+
+def fun_l28_n177(x)
+ if (x < 1)
+ fun_l29_n649(x)
+ else
+ fun_l29_n661(x)
+ end
+end
+
+def fun_l28_n178(x)
+ if (x < 1)
+ fun_l29_n919(x)
+ else
+ fun_l29_n997(x)
+ end
+end
+
+def fun_l28_n179(x)
+ if (x < 1)
+ fun_l29_n634(x)
+ else
+ fun_l29_n967(x)
+ end
+end
+
+def fun_l28_n180(x)
+ if (x < 1)
+ fun_l29_n798(x)
+ else
+ fun_l29_n733(x)
+ end
+end
+
+def fun_l28_n181(x)
+ if (x < 1)
+ fun_l29_n975(x)
+ else
+ fun_l29_n28(x)
+ end
+end
+
+def fun_l28_n182(x)
+ if (x < 1)
+ fun_l29_n973(x)
+ else
+ fun_l29_n616(x)
+ end
+end
+
+def fun_l28_n183(x)
+ if (x < 1)
+ fun_l29_n360(x)
+ else
+ fun_l29_n18(x)
+ end
+end
+
+def fun_l28_n184(x)
+ if (x < 1)
+ fun_l29_n281(x)
+ else
+ fun_l29_n271(x)
+ end
+end
+
+def fun_l28_n185(x)
+ if (x < 1)
+ fun_l29_n216(x)
+ else
+ fun_l29_n193(x)
+ end
+end
+
+def fun_l28_n186(x)
+ if (x < 1)
+ fun_l29_n262(x)
+ else
+ fun_l29_n509(x)
+ end
+end
+
+def fun_l28_n187(x)
+ if (x < 1)
+ fun_l29_n160(x)
+ else
+ fun_l29_n770(x)
+ end
+end
+
+def fun_l28_n188(x)
+ if (x < 1)
+ fun_l29_n411(x)
+ else
+ fun_l29_n605(x)
+ end
+end
+
+def fun_l28_n189(x)
+ if (x < 1)
+ fun_l29_n397(x)
+ else
+ fun_l29_n205(x)
+ end
+end
+
+def fun_l28_n190(x)
+ if (x < 1)
+ fun_l29_n529(x)
+ else
+ fun_l29_n545(x)
+ end
+end
+
+def fun_l28_n191(x)
+ if (x < 1)
+ fun_l29_n528(x)
+ else
+ fun_l29_n472(x)
+ end
+end
+
+def fun_l28_n192(x)
+ if (x < 1)
+ fun_l29_n843(x)
+ else
+ fun_l29_n88(x)
+ end
+end
+
+def fun_l28_n193(x)
+ if (x < 1)
+ fun_l29_n827(x)
+ else
+ fun_l29_n6(x)
+ end
+end
+
+def fun_l28_n194(x)
+ if (x < 1)
+ fun_l29_n567(x)
+ else
+ fun_l29_n622(x)
+ end
+end
+
+def fun_l28_n195(x)
+ if (x < 1)
+ fun_l29_n799(x)
+ else
+ fun_l29_n605(x)
+ end
+end
+
+def fun_l28_n196(x)
+ if (x < 1)
+ fun_l29_n930(x)
+ else
+ fun_l29_n643(x)
+ end
+end
+
+def fun_l28_n197(x)
+ if (x < 1)
+ fun_l29_n445(x)
+ else
+ fun_l29_n226(x)
+ end
+end
+
+def fun_l28_n198(x)
+ if (x < 1)
+ fun_l29_n453(x)
+ else
+ fun_l29_n941(x)
+ end
+end
+
+def fun_l28_n199(x)
+ if (x < 1)
+ fun_l29_n40(x)
+ else
+ fun_l29_n602(x)
+ end
+end
+
+def fun_l28_n200(x)
+ if (x < 1)
+ fun_l29_n804(x)
+ else
+ fun_l29_n355(x)
+ end
+end
+
+def fun_l28_n201(x)
+ if (x < 1)
+ fun_l29_n894(x)
+ else
+ fun_l29_n749(x)
+ end
+end
+
+def fun_l28_n202(x)
+ if (x < 1)
+ fun_l29_n105(x)
+ else
+ fun_l29_n182(x)
+ end
+end
+
+def fun_l28_n203(x)
+ if (x < 1)
+ fun_l29_n106(x)
+ else
+ fun_l29_n670(x)
+ end
+end
+
+def fun_l28_n204(x)
+ if (x < 1)
+ fun_l29_n897(x)
+ else
+ fun_l29_n337(x)
+ end
+end
+
+def fun_l28_n205(x)
+ if (x < 1)
+ fun_l29_n149(x)
+ else
+ fun_l29_n822(x)
+ end
+end
+
+def fun_l28_n206(x)
+ if (x < 1)
+ fun_l29_n2(x)
+ else
+ fun_l29_n370(x)
+ end
+end
+
+def fun_l28_n207(x)
+ if (x < 1)
+ fun_l29_n430(x)
+ else
+ fun_l29_n262(x)
+ end
+end
+
+def fun_l28_n208(x)
+ if (x < 1)
+ fun_l29_n275(x)
+ else
+ fun_l29_n156(x)
+ end
+end
+
+def fun_l28_n209(x)
+ if (x < 1)
+ fun_l29_n677(x)
+ else
+ fun_l29_n620(x)
+ end
+end
+
+def fun_l28_n210(x)
+ if (x < 1)
+ fun_l29_n732(x)
+ else
+ fun_l29_n533(x)
+ end
+end
+
+def fun_l28_n211(x)
+ if (x < 1)
+ fun_l29_n934(x)
+ else
+ fun_l29_n334(x)
+ end
+end
+
+def fun_l28_n212(x)
+ if (x < 1)
+ fun_l29_n656(x)
+ else
+ fun_l29_n889(x)
+ end
+end
+
+def fun_l28_n213(x)
+ if (x < 1)
+ fun_l29_n210(x)
+ else
+ fun_l29_n225(x)
+ end
+end
+
+def fun_l28_n214(x)
+ if (x < 1)
+ fun_l29_n496(x)
+ else
+ fun_l29_n901(x)
+ end
+end
+
+def fun_l28_n215(x)
+ if (x < 1)
+ fun_l29_n190(x)
+ else
+ fun_l29_n254(x)
+ end
+end
+
+def fun_l28_n216(x)
+ if (x < 1)
+ fun_l29_n708(x)
+ else
+ fun_l29_n680(x)
+ end
+end
+
+def fun_l28_n217(x)
+ if (x < 1)
+ fun_l29_n616(x)
+ else
+ fun_l29_n942(x)
+ end
+end
+
+def fun_l28_n218(x)
+ if (x < 1)
+ fun_l29_n515(x)
+ else
+ fun_l29_n269(x)
+ end
+end
+
+def fun_l28_n219(x)
+ if (x < 1)
+ fun_l29_n422(x)
+ else
+ fun_l29_n644(x)
+ end
+end
+
+def fun_l28_n220(x)
+ if (x < 1)
+ fun_l29_n114(x)
+ else
+ fun_l29_n566(x)
+ end
+end
+
+def fun_l28_n221(x)
+ if (x < 1)
+ fun_l29_n750(x)
+ else
+ fun_l29_n799(x)
+ end
+end
+
+def fun_l28_n222(x)
+ if (x < 1)
+ fun_l29_n121(x)
+ else
+ fun_l29_n556(x)
+ end
+end
+
+def fun_l28_n223(x)
+ if (x < 1)
+ fun_l29_n161(x)
+ else
+ fun_l29_n422(x)
+ end
+end
+
+def fun_l28_n224(x)
+ if (x < 1)
+ fun_l29_n779(x)
+ else
+ fun_l29_n214(x)
+ end
+end
+
+def fun_l28_n225(x)
+ if (x < 1)
+ fun_l29_n355(x)
+ else
+ fun_l29_n10(x)
+ end
+end
+
+def fun_l28_n226(x)
+ if (x < 1)
+ fun_l29_n923(x)
+ else
+ fun_l29_n672(x)
+ end
+end
+
+def fun_l28_n227(x)
+ if (x < 1)
+ fun_l29_n578(x)
+ else
+ fun_l29_n809(x)
+ end
+end
+
+def fun_l28_n228(x)
+ if (x < 1)
+ fun_l29_n277(x)
+ else
+ fun_l29_n979(x)
+ end
+end
+
+def fun_l28_n229(x)
+ if (x < 1)
+ fun_l29_n248(x)
+ else
+ fun_l29_n731(x)
+ end
+end
+
+def fun_l28_n230(x)
+ if (x < 1)
+ fun_l29_n374(x)
+ else
+ fun_l29_n675(x)
+ end
+end
+
+def fun_l28_n231(x)
+ if (x < 1)
+ fun_l29_n339(x)
+ else
+ fun_l29_n62(x)
+ end
+end
+
+def fun_l28_n232(x)
+ if (x < 1)
+ fun_l29_n350(x)
+ else
+ fun_l29_n51(x)
+ end
+end
+
+def fun_l28_n233(x)
+ if (x < 1)
+ fun_l29_n606(x)
+ else
+ fun_l29_n460(x)
+ end
+end
+
+def fun_l28_n234(x)
+ if (x < 1)
+ fun_l29_n266(x)
+ else
+ fun_l29_n843(x)
+ end
+end
+
+def fun_l28_n235(x)
+ if (x < 1)
+ fun_l29_n762(x)
+ else
+ fun_l29_n1(x)
+ end
+end
+
+def fun_l28_n236(x)
+ if (x < 1)
+ fun_l29_n405(x)
+ else
+ fun_l29_n867(x)
+ end
+end
+
+def fun_l28_n237(x)
+ if (x < 1)
+ fun_l29_n62(x)
+ else
+ fun_l29_n288(x)
+ end
+end
+
+def fun_l28_n238(x)
+ if (x < 1)
+ fun_l29_n120(x)
+ else
+ fun_l29_n346(x)
+ end
+end
+
+def fun_l28_n239(x)
+ if (x < 1)
+ fun_l29_n789(x)
+ else
+ fun_l29_n633(x)
+ end
+end
+
+def fun_l28_n240(x)
+ if (x < 1)
+ fun_l29_n467(x)
+ else
+ fun_l29_n150(x)
+ end
+end
+
+def fun_l28_n241(x)
+ if (x < 1)
+ fun_l29_n487(x)
+ else
+ fun_l29_n671(x)
+ end
+end
+
+def fun_l28_n242(x)
+ if (x < 1)
+ fun_l29_n147(x)
+ else
+ fun_l29_n636(x)
+ end
+end
+
+def fun_l28_n243(x)
+ if (x < 1)
+ fun_l29_n710(x)
+ else
+ fun_l29_n196(x)
+ end
+end
+
+def fun_l28_n244(x)
+ if (x < 1)
+ fun_l29_n943(x)
+ else
+ fun_l29_n768(x)
+ end
+end
+
+def fun_l28_n245(x)
+ if (x < 1)
+ fun_l29_n670(x)
+ else
+ fun_l29_n522(x)
+ end
+end
+
+def fun_l28_n246(x)
+ if (x < 1)
+ fun_l29_n12(x)
+ else
+ fun_l29_n459(x)
+ end
+end
+
+def fun_l28_n247(x)
+ if (x < 1)
+ fun_l29_n901(x)
+ else
+ fun_l29_n726(x)
+ end
+end
+
+def fun_l28_n248(x)
+ if (x < 1)
+ fun_l29_n824(x)
+ else
+ fun_l29_n327(x)
+ end
+end
+
+def fun_l28_n249(x)
+ if (x < 1)
+ fun_l29_n327(x)
+ else
+ fun_l29_n343(x)
+ end
+end
+
+def fun_l28_n250(x)
+ if (x < 1)
+ fun_l29_n242(x)
+ else
+ fun_l29_n764(x)
+ end
+end
+
+def fun_l28_n251(x)
+ if (x < 1)
+ fun_l29_n780(x)
+ else
+ fun_l29_n117(x)
+ end
+end
+
+def fun_l28_n252(x)
+ if (x < 1)
+ fun_l29_n309(x)
+ else
+ fun_l29_n821(x)
+ end
+end
+
+def fun_l28_n253(x)
+ if (x < 1)
+ fun_l29_n250(x)
+ else
+ fun_l29_n933(x)
+ end
+end
+
+def fun_l28_n254(x)
+ if (x < 1)
+ fun_l29_n470(x)
+ else
+ fun_l29_n808(x)
+ end
+end
+
+def fun_l28_n255(x)
+ if (x < 1)
+ fun_l29_n425(x)
+ else
+ fun_l29_n800(x)
+ end
+end
+
+def fun_l28_n256(x)
+ if (x < 1)
+ fun_l29_n913(x)
+ else
+ fun_l29_n199(x)
+ end
+end
+
+def fun_l28_n257(x)
+ if (x < 1)
+ fun_l29_n25(x)
+ else
+ fun_l29_n412(x)
+ end
+end
+
+def fun_l28_n258(x)
+ if (x < 1)
+ fun_l29_n194(x)
+ else
+ fun_l29_n606(x)
+ end
+end
+
+def fun_l28_n259(x)
+ if (x < 1)
+ fun_l29_n653(x)
+ else
+ fun_l29_n72(x)
+ end
+end
+
+def fun_l28_n260(x)
+ if (x < 1)
+ fun_l29_n198(x)
+ else
+ fun_l29_n742(x)
+ end
+end
+
+def fun_l28_n261(x)
+ if (x < 1)
+ fun_l29_n452(x)
+ else
+ fun_l29_n522(x)
+ end
+end
+
+def fun_l28_n262(x)
+ if (x < 1)
+ fun_l29_n214(x)
+ else
+ fun_l29_n131(x)
+ end
+end
+
+def fun_l28_n263(x)
+ if (x < 1)
+ fun_l29_n481(x)
+ else
+ fun_l29_n848(x)
+ end
+end
+
+def fun_l28_n264(x)
+ if (x < 1)
+ fun_l29_n147(x)
+ else
+ fun_l29_n187(x)
+ end
+end
+
+def fun_l28_n265(x)
+ if (x < 1)
+ fun_l29_n476(x)
+ else
+ fun_l29_n859(x)
+ end
+end
+
+def fun_l28_n266(x)
+ if (x < 1)
+ fun_l29_n130(x)
+ else
+ fun_l29_n356(x)
+ end
+end
+
+def fun_l28_n267(x)
+ if (x < 1)
+ fun_l29_n427(x)
+ else
+ fun_l29_n578(x)
+ end
+end
+
+def fun_l28_n268(x)
+ if (x < 1)
+ fun_l29_n810(x)
+ else
+ fun_l29_n483(x)
+ end
+end
+
+def fun_l28_n269(x)
+ if (x < 1)
+ fun_l29_n496(x)
+ else
+ fun_l29_n548(x)
+ end
+end
+
+def fun_l28_n270(x)
+ if (x < 1)
+ fun_l29_n159(x)
+ else
+ fun_l29_n184(x)
+ end
+end
+
+def fun_l28_n271(x)
+ if (x < 1)
+ fun_l29_n407(x)
+ else
+ fun_l29_n855(x)
+ end
+end
+
+def fun_l28_n272(x)
+ if (x < 1)
+ fun_l29_n41(x)
+ else
+ fun_l29_n493(x)
+ end
+end
+
+def fun_l28_n273(x)
+ if (x < 1)
+ fun_l29_n853(x)
+ else
+ fun_l29_n711(x)
+ end
+end
+
+def fun_l28_n274(x)
+ if (x < 1)
+ fun_l29_n397(x)
+ else
+ fun_l29_n68(x)
+ end
+end
+
+def fun_l28_n275(x)
+ if (x < 1)
+ fun_l29_n744(x)
+ else
+ fun_l29_n944(x)
+ end
+end
+
+def fun_l28_n276(x)
+ if (x < 1)
+ fun_l29_n641(x)
+ else
+ fun_l29_n766(x)
+ end
+end
+
+def fun_l28_n277(x)
+ if (x < 1)
+ fun_l29_n983(x)
+ else
+ fun_l29_n587(x)
+ end
+end
+
+def fun_l28_n278(x)
+ if (x < 1)
+ fun_l29_n683(x)
+ else
+ fun_l29_n192(x)
+ end
+end
+
+def fun_l28_n279(x)
+ if (x < 1)
+ fun_l29_n252(x)
+ else
+ fun_l29_n30(x)
+ end
+end
+
+def fun_l28_n280(x)
+ if (x < 1)
+ fun_l29_n129(x)
+ else
+ fun_l29_n561(x)
+ end
+end
+
+def fun_l28_n281(x)
+ if (x < 1)
+ fun_l29_n828(x)
+ else
+ fun_l29_n697(x)
+ end
+end
+
+def fun_l28_n282(x)
+ if (x < 1)
+ fun_l29_n492(x)
+ else
+ fun_l29_n243(x)
+ end
+end
+
+def fun_l28_n283(x)
+ if (x < 1)
+ fun_l29_n642(x)
+ else
+ fun_l29_n736(x)
+ end
+end
+
+def fun_l28_n284(x)
+ if (x < 1)
+ fun_l29_n448(x)
+ else
+ fun_l29_n838(x)
+ end
+end
+
+def fun_l28_n285(x)
+ if (x < 1)
+ fun_l29_n133(x)
+ else
+ fun_l29_n372(x)
+ end
+end
+
+def fun_l28_n286(x)
+ if (x < 1)
+ fun_l29_n318(x)
+ else
+ fun_l29_n739(x)
+ end
+end
+
+def fun_l28_n287(x)
+ if (x < 1)
+ fun_l29_n449(x)
+ else
+ fun_l29_n743(x)
+ end
+end
+
+def fun_l28_n288(x)
+ if (x < 1)
+ fun_l29_n769(x)
+ else
+ fun_l29_n496(x)
+ end
+end
+
+def fun_l28_n289(x)
+ if (x < 1)
+ fun_l29_n455(x)
+ else
+ fun_l29_n893(x)
+ end
+end
+
+def fun_l28_n290(x)
+ if (x < 1)
+ fun_l29_n651(x)
+ else
+ fun_l29_n865(x)
+ end
+end
+
+def fun_l28_n291(x)
+ if (x < 1)
+ fun_l29_n194(x)
+ else
+ fun_l29_n491(x)
+ end
+end
+
+def fun_l28_n292(x)
+ if (x < 1)
+ fun_l29_n178(x)
+ else
+ fun_l29_n96(x)
+ end
+end
+
+def fun_l28_n293(x)
+ if (x < 1)
+ fun_l29_n32(x)
+ else
+ fun_l29_n262(x)
+ end
+end
+
+def fun_l28_n294(x)
+ if (x < 1)
+ fun_l29_n706(x)
+ else
+ fun_l29_n864(x)
+ end
+end
+
+def fun_l28_n295(x)
+ if (x < 1)
+ fun_l29_n209(x)
+ else
+ fun_l29_n220(x)
+ end
+end
+
+def fun_l28_n296(x)
+ if (x < 1)
+ fun_l29_n970(x)
+ else
+ fun_l29_n194(x)
+ end
+end
+
+def fun_l28_n297(x)
+ if (x < 1)
+ fun_l29_n959(x)
+ else
+ fun_l29_n472(x)
+ end
+end
+
+def fun_l28_n298(x)
+ if (x < 1)
+ fun_l29_n778(x)
+ else
+ fun_l29_n66(x)
+ end
+end
+
+def fun_l28_n299(x)
+ if (x < 1)
+ fun_l29_n942(x)
+ else
+ fun_l29_n461(x)
+ end
+end
+
+def fun_l28_n300(x)
+ if (x < 1)
+ fun_l29_n563(x)
+ else
+ fun_l29_n426(x)
+ end
+end
+
+def fun_l28_n301(x)
+ if (x < 1)
+ fun_l29_n603(x)
+ else
+ fun_l29_n968(x)
+ end
+end
+
+def fun_l28_n302(x)
+ if (x < 1)
+ fun_l29_n908(x)
+ else
+ fun_l29_n767(x)
+ end
+end
+
+def fun_l28_n303(x)
+ if (x < 1)
+ fun_l29_n387(x)
+ else
+ fun_l29_n484(x)
+ end
+end
+
+def fun_l28_n304(x)
+ if (x < 1)
+ fun_l29_n744(x)
+ else
+ fun_l29_n463(x)
+ end
+end
+
+def fun_l28_n305(x)
+ if (x < 1)
+ fun_l29_n964(x)
+ else
+ fun_l29_n43(x)
+ end
+end
+
+def fun_l28_n306(x)
+ if (x < 1)
+ fun_l29_n65(x)
+ else
+ fun_l29_n910(x)
+ end
+end
+
+def fun_l28_n307(x)
+ if (x < 1)
+ fun_l29_n318(x)
+ else
+ fun_l29_n375(x)
+ end
+end
+
+def fun_l28_n308(x)
+ if (x < 1)
+ fun_l29_n775(x)
+ else
+ fun_l29_n588(x)
+ end
+end
+
+def fun_l28_n309(x)
+ if (x < 1)
+ fun_l29_n977(x)
+ else
+ fun_l29_n299(x)
+ end
+end
+
+def fun_l28_n310(x)
+ if (x < 1)
+ fun_l29_n497(x)
+ else
+ fun_l29_n792(x)
+ end
+end
+
+def fun_l28_n311(x)
+ if (x < 1)
+ fun_l29_n909(x)
+ else
+ fun_l29_n740(x)
+ end
+end
+
+def fun_l28_n312(x)
+ if (x < 1)
+ fun_l29_n967(x)
+ else
+ fun_l29_n4(x)
+ end
+end
+
+def fun_l28_n313(x)
+ if (x < 1)
+ fun_l29_n455(x)
+ else
+ fun_l29_n11(x)
+ end
+end
+
+def fun_l28_n314(x)
+ if (x < 1)
+ fun_l29_n996(x)
+ else
+ fun_l29_n851(x)
+ end
+end
+
+def fun_l28_n315(x)
+ if (x < 1)
+ fun_l29_n110(x)
+ else
+ fun_l29_n517(x)
+ end
+end
+
+def fun_l28_n316(x)
+ if (x < 1)
+ fun_l29_n648(x)
+ else
+ fun_l29_n279(x)
+ end
+end
+
+def fun_l28_n317(x)
+ if (x < 1)
+ fun_l29_n820(x)
+ else
+ fun_l29_n157(x)
+ end
+end
+
+def fun_l28_n318(x)
+ if (x < 1)
+ fun_l29_n957(x)
+ else
+ fun_l29_n93(x)
+ end
+end
+
+def fun_l28_n319(x)
+ if (x < 1)
+ fun_l29_n681(x)
+ else
+ fun_l29_n508(x)
+ end
+end
+
+def fun_l28_n320(x)
+ if (x < 1)
+ fun_l29_n613(x)
+ else
+ fun_l29_n274(x)
+ end
+end
+
+def fun_l28_n321(x)
+ if (x < 1)
+ fun_l29_n239(x)
+ else
+ fun_l29_n862(x)
+ end
+end
+
+def fun_l28_n322(x)
+ if (x < 1)
+ fun_l29_n101(x)
+ else
+ fun_l29_n81(x)
+ end
+end
+
+def fun_l28_n323(x)
+ if (x < 1)
+ fun_l29_n96(x)
+ else
+ fun_l29_n908(x)
+ end
+end
+
+def fun_l28_n324(x)
+ if (x < 1)
+ fun_l29_n443(x)
+ else
+ fun_l29_n78(x)
+ end
+end
+
+def fun_l28_n325(x)
+ if (x < 1)
+ fun_l29_n857(x)
+ else
+ fun_l29_n210(x)
+ end
+end
+
+def fun_l28_n326(x)
+ if (x < 1)
+ fun_l29_n51(x)
+ else
+ fun_l29_n524(x)
+ end
+end
+
+def fun_l28_n327(x)
+ if (x < 1)
+ fun_l29_n381(x)
+ else
+ fun_l29_n309(x)
+ end
+end
+
+def fun_l28_n328(x)
+ if (x < 1)
+ fun_l29_n787(x)
+ else
+ fun_l29_n176(x)
+ end
+end
+
+def fun_l28_n329(x)
+ if (x < 1)
+ fun_l29_n568(x)
+ else
+ fun_l29_n652(x)
+ end
+end
+
+def fun_l28_n330(x)
+ if (x < 1)
+ fun_l29_n1(x)
+ else
+ fun_l29_n634(x)
+ end
+end
+
+def fun_l28_n331(x)
+ if (x < 1)
+ fun_l29_n491(x)
+ else
+ fun_l29_n365(x)
+ end
+end
+
+def fun_l28_n332(x)
+ if (x < 1)
+ fun_l29_n604(x)
+ else
+ fun_l29_n586(x)
+ end
+end
+
+def fun_l28_n333(x)
+ if (x < 1)
+ fun_l29_n811(x)
+ else
+ fun_l29_n981(x)
+ end
+end
+
+def fun_l28_n334(x)
+ if (x < 1)
+ fun_l29_n485(x)
+ else
+ fun_l29_n843(x)
+ end
+end
+
+def fun_l28_n335(x)
+ if (x < 1)
+ fun_l29_n188(x)
+ else
+ fun_l29_n805(x)
+ end
+end
+
+def fun_l28_n336(x)
+ if (x < 1)
+ fun_l29_n818(x)
+ else
+ fun_l29_n650(x)
+ end
+end
+
+def fun_l28_n337(x)
+ if (x < 1)
+ fun_l29_n829(x)
+ else
+ fun_l29_n13(x)
+ end
+end
+
+def fun_l28_n338(x)
+ if (x < 1)
+ fun_l29_n665(x)
+ else
+ fun_l29_n7(x)
+ end
+end
+
+def fun_l28_n339(x)
+ if (x < 1)
+ fun_l29_n347(x)
+ else
+ fun_l29_n914(x)
+ end
+end
+
+def fun_l28_n340(x)
+ if (x < 1)
+ fun_l29_n819(x)
+ else
+ fun_l29_n7(x)
+ end
+end
+
+def fun_l28_n341(x)
+ if (x < 1)
+ fun_l29_n108(x)
+ else
+ fun_l29_n838(x)
+ end
+end
+
+def fun_l28_n342(x)
+ if (x < 1)
+ fun_l29_n292(x)
+ else
+ fun_l29_n831(x)
+ end
+end
+
+def fun_l28_n343(x)
+ if (x < 1)
+ fun_l29_n892(x)
+ else
+ fun_l29_n717(x)
+ end
+end
+
+def fun_l28_n344(x)
+ if (x < 1)
+ fun_l29_n664(x)
+ else
+ fun_l29_n422(x)
+ end
+end
+
+def fun_l28_n345(x)
+ if (x < 1)
+ fun_l29_n59(x)
+ else
+ fun_l29_n858(x)
+ end
+end
+
+def fun_l28_n346(x)
+ if (x < 1)
+ fun_l29_n88(x)
+ else
+ fun_l29_n97(x)
+ end
+end
+
+def fun_l28_n347(x)
+ if (x < 1)
+ fun_l29_n852(x)
+ else
+ fun_l29_n37(x)
+ end
+end
+
+def fun_l28_n348(x)
+ if (x < 1)
+ fun_l29_n201(x)
+ else
+ fun_l29_n663(x)
+ end
+end
+
+def fun_l28_n349(x)
+ if (x < 1)
+ fun_l29_n928(x)
+ else
+ fun_l29_n743(x)
+ end
+end
+
+def fun_l28_n350(x)
+ if (x < 1)
+ fun_l29_n206(x)
+ else
+ fun_l29_n609(x)
+ end
+end
+
+def fun_l28_n351(x)
+ if (x < 1)
+ fun_l29_n98(x)
+ else
+ fun_l29_n659(x)
+ end
+end
+
+def fun_l28_n352(x)
+ if (x < 1)
+ fun_l29_n350(x)
+ else
+ fun_l29_n604(x)
+ end
+end
+
+def fun_l28_n353(x)
+ if (x < 1)
+ fun_l29_n273(x)
+ else
+ fun_l29_n831(x)
+ end
+end
+
+def fun_l28_n354(x)
+ if (x < 1)
+ fun_l29_n377(x)
+ else
+ fun_l29_n926(x)
+ end
+end
+
+def fun_l28_n355(x)
+ if (x < 1)
+ fun_l29_n783(x)
+ else
+ fun_l29_n646(x)
+ end
+end
+
+def fun_l28_n356(x)
+ if (x < 1)
+ fun_l29_n968(x)
+ else
+ fun_l29_n587(x)
+ end
+end
+
+def fun_l28_n357(x)
+ if (x < 1)
+ fun_l29_n813(x)
+ else
+ fun_l29_n791(x)
+ end
+end
+
+def fun_l28_n358(x)
+ if (x < 1)
+ fun_l29_n130(x)
+ else
+ fun_l29_n851(x)
+ end
+end
+
+def fun_l28_n359(x)
+ if (x < 1)
+ fun_l29_n858(x)
+ else
+ fun_l29_n112(x)
+ end
+end
+
+def fun_l28_n360(x)
+ if (x < 1)
+ fun_l29_n349(x)
+ else
+ fun_l29_n612(x)
+ end
+end
+
+def fun_l28_n361(x)
+ if (x < 1)
+ fun_l29_n282(x)
+ else
+ fun_l29_n357(x)
+ end
+end
+
+def fun_l28_n362(x)
+ if (x < 1)
+ fun_l29_n144(x)
+ else
+ fun_l29_n426(x)
+ end
+end
+
+def fun_l28_n363(x)
+ if (x < 1)
+ fun_l29_n438(x)
+ else
+ fun_l29_n539(x)
+ end
+end
+
+def fun_l28_n364(x)
+ if (x < 1)
+ fun_l29_n321(x)
+ else
+ fun_l29_n874(x)
+ end
+end
+
+def fun_l28_n365(x)
+ if (x < 1)
+ fun_l29_n443(x)
+ else
+ fun_l29_n985(x)
+ end
+end
+
+def fun_l28_n366(x)
+ if (x < 1)
+ fun_l29_n436(x)
+ else
+ fun_l29_n787(x)
+ end
+end
+
+def fun_l28_n367(x)
+ if (x < 1)
+ fun_l29_n354(x)
+ else
+ fun_l29_n75(x)
+ end
+end
+
+def fun_l28_n368(x)
+ if (x < 1)
+ fun_l29_n515(x)
+ else
+ fun_l29_n57(x)
+ end
+end
+
+def fun_l28_n369(x)
+ if (x < 1)
+ fun_l29_n222(x)
+ else
+ fun_l29_n954(x)
+ end
+end
+
+def fun_l28_n370(x)
+ if (x < 1)
+ fun_l29_n37(x)
+ else
+ fun_l29_n683(x)
+ end
+end
+
+def fun_l28_n371(x)
+ if (x < 1)
+ fun_l29_n104(x)
+ else
+ fun_l29_n721(x)
+ end
+end
+
+def fun_l28_n372(x)
+ if (x < 1)
+ fun_l29_n763(x)
+ else
+ fun_l29_n173(x)
+ end
+end
+
+def fun_l28_n373(x)
+ if (x < 1)
+ fun_l29_n693(x)
+ else
+ fun_l29_n132(x)
+ end
+end
+
+def fun_l28_n374(x)
+ if (x < 1)
+ fun_l29_n586(x)
+ else
+ fun_l29_n992(x)
+ end
+end
+
+def fun_l28_n375(x)
+ if (x < 1)
+ fun_l29_n815(x)
+ else
+ fun_l29_n721(x)
+ end
+end
+
+def fun_l28_n376(x)
+ if (x < 1)
+ fun_l29_n653(x)
+ else
+ fun_l29_n67(x)
+ end
+end
+
+def fun_l28_n377(x)
+ if (x < 1)
+ fun_l29_n710(x)
+ else
+ fun_l29_n787(x)
+ end
+end
+
+def fun_l28_n378(x)
+ if (x < 1)
+ fun_l29_n448(x)
+ else
+ fun_l29_n170(x)
+ end
+end
+
+def fun_l28_n379(x)
+ if (x < 1)
+ fun_l29_n433(x)
+ else
+ fun_l29_n970(x)
+ end
+end
+
+def fun_l28_n380(x)
+ if (x < 1)
+ fun_l29_n933(x)
+ else
+ fun_l29_n995(x)
+ end
+end
+
+def fun_l28_n381(x)
+ if (x < 1)
+ fun_l29_n78(x)
+ else
+ fun_l29_n791(x)
+ end
+end
+
+def fun_l28_n382(x)
+ if (x < 1)
+ fun_l29_n101(x)
+ else
+ fun_l29_n592(x)
+ end
+end
+
+def fun_l28_n383(x)
+ if (x < 1)
+ fun_l29_n470(x)
+ else
+ fun_l29_n988(x)
+ end
+end
+
+def fun_l28_n384(x)
+ if (x < 1)
+ fun_l29_n260(x)
+ else
+ fun_l29_n359(x)
+ end
+end
+
+def fun_l28_n385(x)
+ if (x < 1)
+ fun_l29_n743(x)
+ else
+ fun_l29_n373(x)
+ end
+end
+
+def fun_l28_n386(x)
+ if (x < 1)
+ fun_l29_n49(x)
+ else
+ fun_l29_n591(x)
+ end
+end
+
+def fun_l28_n387(x)
+ if (x < 1)
+ fun_l29_n271(x)
+ else
+ fun_l29_n924(x)
+ end
+end
+
+def fun_l28_n388(x)
+ if (x < 1)
+ fun_l29_n876(x)
+ else
+ fun_l29_n219(x)
+ end
+end
+
+def fun_l28_n389(x)
+ if (x < 1)
+ fun_l29_n262(x)
+ else
+ fun_l29_n857(x)
+ end
+end
+
+def fun_l28_n390(x)
+ if (x < 1)
+ fun_l29_n217(x)
+ else
+ fun_l29_n198(x)
+ end
+end
+
+def fun_l28_n391(x)
+ if (x < 1)
+ fun_l29_n603(x)
+ else
+ fun_l29_n87(x)
+ end
+end
+
+def fun_l28_n392(x)
+ if (x < 1)
+ fun_l29_n498(x)
+ else
+ fun_l29_n913(x)
+ end
+end
+
+def fun_l28_n393(x)
+ if (x < 1)
+ fun_l29_n795(x)
+ else
+ fun_l29_n87(x)
+ end
+end
+
+def fun_l28_n394(x)
+ if (x < 1)
+ fun_l29_n528(x)
+ else
+ fun_l29_n217(x)
+ end
+end
+
+def fun_l28_n395(x)
+ if (x < 1)
+ fun_l29_n300(x)
+ else
+ fun_l29_n725(x)
+ end
+end
+
+def fun_l28_n396(x)
+ if (x < 1)
+ fun_l29_n538(x)
+ else
+ fun_l29_n812(x)
+ end
+end
+
+def fun_l28_n397(x)
+ if (x < 1)
+ fun_l29_n179(x)
+ else
+ fun_l29_n765(x)
+ end
+end
+
+def fun_l28_n398(x)
+ if (x < 1)
+ fun_l29_n28(x)
+ else
+ fun_l29_n475(x)
+ end
+end
+
+def fun_l28_n399(x)
+ if (x < 1)
+ fun_l29_n471(x)
+ else
+ fun_l29_n368(x)
+ end
+end
+
+def fun_l28_n400(x)
+ if (x < 1)
+ fun_l29_n241(x)
+ else
+ fun_l29_n461(x)
+ end
+end
+
+def fun_l28_n401(x)
+ if (x < 1)
+ fun_l29_n707(x)
+ else
+ fun_l29_n502(x)
+ end
+end
+
+def fun_l28_n402(x)
+ if (x < 1)
+ fun_l29_n129(x)
+ else
+ fun_l29_n176(x)
+ end
+end
+
+def fun_l28_n403(x)
+ if (x < 1)
+ fun_l29_n410(x)
+ else
+ fun_l29_n954(x)
+ end
+end
+
+def fun_l28_n404(x)
+ if (x < 1)
+ fun_l29_n203(x)
+ else
+ fun_l29_n455(x)
+ end
+end
+
+def fun_l28_n405(x)
+ if (x < 1)
+ fun_l29_n238(x)
+ else
+ fun_l29_n865(x)
+ end
+end
+
+def fun_l28_n406(x)
+ if (x < 1)
+ fun_l29_n836(x)
+ else
+ fun_l29_n778(x)
+ end
+end
+
+def fun_l28_n407(x)
+ if (x < 1)
+ fun_l29_n620(x)
+ else
+ fun_l29_n879(x)
+ end
+end
+
+def fun_l28_n408(x)
+ if (x < 1)
+ fun_l29_n656(x)
+ else
+ fun_l29_n594(x)
+ end
+end
+
+def fun_l28_n409(x)
+ if (x < 1)
+ fun_l29_n382(x)
+ else
+ fun_l29_n51(x)
+ end
+end
+
+def fun_l28_n410(x)
+ if (x < 1)
+ fun_l29_n357(x)
+ else
+ fun_l29_n660(x)
+ end
+end
+
+def fun_l28_n411(x)
+ if (x < 1)
+ fun_l29_n900(x)
+ else
+ fun_l29_n902(x)
+ end
+end
+
+def fun_l28_n412(x)
+ if (x < 1)
+ fun_l29_n645(x)
+ else
+ fun_l29_n0(x)
+ end
+end
+
+def fun_l28_n413(x)
+ if (x < 1)
+ fun_l29_n250(x)
+ else
+ fun_l29_n499(x)
+ end
+end
+
+def fun_l28_n414(x)
+ if (x < 1)
+ fun_l29_n700(x)
+ else
+ fun_l29_n301(x)
+ end
+end
+
+def fun_l28_n415(x)
+ if (x < 1)
+ fun_l29_n711(x)
+ else
+ fun_l29_n83(x)
+ end
+end
+
+def fun_l28_n416(x)
+ if (x < 1)
+ fun_l29_n332(x)
+ else
+ fun_l29_n237(x)
+ end
+end
+
+def fun_l28_n417(x)
+ if (x < 1)
+ fun_l29_n573(x)
+ else
+ fun_l29_n822(x)
+ end
+end
+
+def fun_l28_n418(x)
+ if (x < 1)
+ fun_l29_n766(x)
+ else
+ fun_l29_n131(x)
+ end
+end
+
+def fun_l28_n419(x)
+ if (x < 1)
+ fun_l29_n696(x)
+ else
+ fun_l29_n772(x)
+ end
+end
+
+def fun_l28_n420(x)
+ if (x < 1)
+ fun_l29_n361(x)
+ else
+ fun_l29_n598(x)
+ end
+end
+
+def fun_l28_n421(x)
+ if (x < 1)
+ fun_l29_n941(x)
+ else
+ fun_l29_n403(x)
+ end
+end
+
+def fun_l28_n422(x)
+ if (x < 1)
+ fun_l29_n471(x)
+ else
+ fun_l29_n636(x)
+ end
+end
+
+def fun_l28_n423(x)
+ if (x < 1)
+ fun_l29_n650(x)
+ else
+ fun_l29_n787(x)
+ end
+end
+
+def fun_l28_n424(x)
+ if (x < 1)
+ fun_l29_n982(x)
+ else
+ fun_l29_n51(x)
+ end
+end
+
+def fun_l28_n425(x)
+ if (x < 1)
+ fun_l29_n140(x)
+ else
+ fun_l29_n255(x)
+ end
+end
+
+def fun_l28_n426(x)
+ if (x < 1)
+ fun_l29_n694(x)
+ else
+ fun_l29_n777(x)
+ end
+end
+
+def fun_l28_n427(x)
+ if (x < 1)
+ fun_l29_n984(x)
+ else
+ fun_l29_n118(x)
+ end
+end
+
+def fun_l28_n428(x)
+ if (x < 1)
+ fun_l29_n641(x)
+ else
+ fun_l29_n904(x)
+ end
+end
+
+def fun_l28_n429(x)
+ if (x < 1)
+ fun_l29_n537(x)
+ else
+ fun_l29_n950(x)
+ end
+end
+
+def fun_l28_n430(x)
+ if (x < 1)
+ fun_l29_n844(x)
+ else
+ fun_l29_n350(x)
+ end
+end
+
+def fun_l28_n431(x)
+ if (x < 1)
+ fun_l29_n223(x)
+ else
+ fun_l29_n711(x)
+ end
+end
+
+def fun_l28_n432(x)
+ if (x < 1)
+ fun_l29_n287(x)
+ else
+ fun_l29_n424(x)
+ end
+end
+
+def fun_l28_n433(x)
+ if (x < 1)
+ fun_l29_n447(x)
+ else
+ fun_l29_n253(x)
+ end
+end
+
+def fun_l28_n434(x)
+ if (x < 1)
+ fun_l29_n484(x)
+ else
+ fun_l29_n377(x)
+ end
+end
+
+def fun_l28_n435(x)
+ if (x < 1)
+ fun_l29_n899(x)
+ else
+ fun_l29_n385(x)
+ end
+end
+
+def fun_l28_n436(x)
+ if (x < 1)
+ fun_l29_n13(x)
+ else
+ fun_l29_n910(x)
+ end
+end
+
+def fun_l28_n437(x)
+ if (x < 1)
+ fun_l29_n431(x)
+ else
+ fun_l29_n505(x)
+ end
+end
+
+def fun_l28_n438(x)
+ if (x < 1)
+ fun_l29_n974(x)
+ else
+ fun_l29_n162(x)
+ end
+end
+
+def fun_l28_n439(x)
+ if (x < 1)
+ fun_l29_n833(x)
+ else
+ fun_l29_n26(x)
+ end
+end
+
+def fun_l28_n440(x)
+ if (x < 1)
+ fun_l29_n576(x)
+ else
+ fun_l29_n783(x)
+ end
+end
+
+def fun_l28_n441(x)
+ if (x < 1)
+ fun_l29_n580(x)
+ else
+ fun_l29_n476(x)
+ end
+end
+
+def fun_l28_n442(x)
+ if (x < 1)
+ fun_l29_n415(x)
+ else
+ fun_l29_n695(x)
+ end
+end
+
+def fun_l28_n443(x)
+ if (x < 1)
+ fun_l29_n279(x)
+ else
+ fun_l29_n442(x)
+ end
+end
+
+def fun_l28_n444(x)
+ if (x < 1)
+ fun_l29_n784(x)
+ else
+ fun_l29_n25(x)
+ end
+end
+
+def fun_l28_n445(x)
+ if (x < 1)
+ fun_l29_n682(x)
+ else
+ fun_l29_n632(x)
+ end
+end
+
+def fun_l28_n446(x)
+ if (x < 1)
+ fun_l29_n793(x)
+ else
+ fun_l29_n199(x)
+ end
+end
+
+def fun_l28_n447(x)
+ if (x < 1)
+ fun_l29_n885(x)
+ else
+ fun_l29_n590(x)
+ end
+end
+
+def fun_l28_n448(x)
+ if (x < 1)
+ fun_l29_n457(x)
+ else
+ fun_l29_n664(x)
+ end
+end
+
+def fun_l28_n449(x)
+ if (x < 1)
+ fun_l29_n272(x)
+ else
+ fun_l29_n207(x)
+ end
+end
+
+def fun_l28_n450(x)
+ if (x < 1)
+ fun_l29_n73(x)
+ else
+ fun_l29_n598(x)
+ end
+end
+
+def fun_l28_n451(x)
+ if (x < 1)
+ fun_l29_n674(x)
+ else
+ fun_l29_n305(x)
+ end
+end
+
+def fun_l28_n452(x)
+ if (x < 1)
+ fun_l29_n97(x)
+ else
+ fun_l29_n472(x)
+ end
+end
+
+def fun_l28_n453(x)
+ if (x < 1)
+ fun_l29_n995(x)
+ else
+ fun_l29_n156(x)
+ end
+end
+
+def fun_l28_n454(x)
+ if (x < 1)
+ fun_l29_n890(x)
+ else
+ fun_l29_n885(x)
+ end
+end
+
+def fun_l28_n455(x)
+ if (x < 1)
+ fun_l29_n481(x)
+ else
+ fun_l29_n712(x)
+ end
+end
+
+def fun_l28_n456(x)
+ if (x < 1)
+ fun_l29_n34(x)
+ else
+ fun_l29_n186(x)
+ end
+end
+
+def fun_l28_n457(x)
+ if (x < 1)
+ fun_l29_n767(x)
+ else
+ fun_l29_n769(x)
+ end
+end
+
+def fun_l28_n458(x)
+ if (x < 1)
+ fun_l29_n185(x)
+ else
+ fun_l29_n55(x)
+ end
+end
+
+def fun_l28_n459(x)
+ if (x < 1)
+ fun_l29_n826(x)
+ else
+ fun_l29_n954(x)
+ end
+end
+
+def fun_l28_n460(x)
+ if (x < 1)
+ fun_l29_n111(x)
+ else
+ fun_l29_n374(x)
+ end
+end
+
+def fun_l28_n461(x)
+ if (x < 1)
+ fun_l29_n988(x)
+ else
+ fun_l29_n719(x)
+ end
+end
+
+def fun_l28_n462(x)
+ if (x < 1)
+ fun_l29_n355(x)
+ else
+ fun_l29_n772(x)
+ end
+end
+
+def fun_l28_n463(x)
+ if (x < 1)
+ fun_l29_n348(x)
+ else
+ fun_l29_n973(x)
+ end
+end
+
+def fun_l28_n464(x)
+ if (x < 1)
+ fun_l29_n466(x)
+ else
+ fun_l29_n661(x)
+ end
+end
+
+def fun_l28_n465(x)
+ if (x < 1)
+ fun_l29_n95(x)
+ else
+ fun_l29_n300(x)
+ end
+end
+
+def fun_l28_n466(x)
+ if (x < 1)
+ fun_l29_n373(x)
+ else
+ fun_l29_n425(x)
+ end
+end
+
+def fun_l28_n467(x)
+ if (x < 1)
+ fun_l29_n669(x)
+ else
+ fun_l29_n990(x)
+ end
+end
+
+def fun_l28_n468(x)
+ if (x < 1)
+ fun_l29_n908(x)
+ else
+ fun_l29_n416(x)
+ end
+end
+
+def fun_l28_n469(x)
+ if (x < 1)
+ fun_l29_n795(x)
+ else
+ fun_l29_n7(x)
+ end
+end
+
+def fun_l28_n470(x)
+ if (x < 1)
+ fun_l29_n660(x)
+ else
+ fun_l29_n938(x)
+ end
+end
+
+def fun_l28_n471(x)
+ if (x < 1)
+ fun_l29_n816(x)
+ else
+ fun_l29_n857(x)
+ end
+end
+
+def fun_l28_n472(x)
+ if (x < 1)
+ fun_l29_n685(x)
+ else
+ fun_l29_n631(x)
+ end
+end
+
+def fun_l28_n473(x)
+ if (x < 1)
+ fun_l29_n521(x)
+ else
+ fun_l29_n21(x)
+ end
+end
+
+def fun_l28_n474(x)
+ if (x < 1)
+ fun_l29_n994(x)
+ else
+ fun_l29_n888(x)
+ end
+end
+
+def fun_l28_n475(x)
+ if (x < 1)
+ fun_l29_n819(x)
+ else
+ fun_l29_n735(x)
+ end
+end
+
+def fun_l28_n476(x)
+ if (x < 1)
+ fun_l29_n809(x)
+ else
+ fun_l29_n265(x)
+ end
+end
+
+def fun_l28_n477(x)
+ if (x < 1)
+ fun_l29_n99(x)
+ else
+ fun_l29_n484(x)
+ end
+end
+
+def fun_l28_n478(x)
+ if (x < 1)
+ fun_l29_n985(x)
+ else
+ fun_l29_n922(x)
+ end
+end
+
+def fun_l28_n479(x)
+ if (x < 1)
+ fun_l29_n502(x)
+ else
+ fun_l29_n475(x)
+ end
+end
+
+def fun_l28_n480(x)
+ if (x < 1)
+ fun_l29_n104(x)
+ else
+ fun_l29_n168(x)
+ end
+end
+
+def fun_l28_n481(x)
+ if (x < 1)
+ fun_l29_n176(x)
+ else
+ fun_l29_n736(x)
+ end
+end
+
+def fun_l28_n482(x)
+ if (x < 1)
+ fun_l29_n817(x)
+ else
+ fun_l29_n155(x)
+ end
+end
+
+def fun_l28_n483(x)
+ if (x < 1)
+ fun_l29_n162(x)
+ else
+ fun_l29_n45(x)
+ end
+end
+
+def fun_l28_n484(x)
+ if (x < 1)
+ fun_l29_n733(x)
+ else
+ fun_l29_n438(x)
+ end
+end
+
+def fun_l28_n485(x)
+ if (x < 1)
+ fun_l29_n323(x)
+ else
+ fun_l29_n410(x)
+ end
+end
+
+def fun_l28_n486(x)
+ if (x < 1)
+ fun_l29_n141(x)
+ else
+ fun_l29_n327(x)
+ end
+end
+
+def fun_l28_n487(x)
+ if (x < 1)
+ fun_l29_n122(x)
+ else
+ fun_l29_n280(x)
+ end
+end
+
+def fun_l28_n488(x)
+ if (x < 1)
+ fun_l29_n966(x)
+ else
+ fun_l29_n407(x)
+ end
+end
+
+def fun_l28_n489(x)
+ if (x < 1)
+ fun_l29_n826(x)
+ else
+ fun_l29_n852(x)
+ end
+end
+
+def fun_l28_n490(x)
+ if (x < 1)
+ fun_l29_n823(x)
+ else
+ fun_l29_n724(x)
+ end
+end
+
+def fun_l28_n491(x)
+ if (x < 1)
+ fun_l29_n291(x)
+ else
+ fun_l29_n151(x)
+ end
+end
+
+def fun_l28_n492(x)
+ if (x < 1)
+ fun_l29_n944(x)
+ else
+ fun_l29_n663(x)
+ end
+end
+
+def fun_l28_n493(x)
+ if (x < 1)
+ fun_l29_n552(x)
+ else
+ fun_l29_n954(x)
+ end
+end
+
+def fun_l28_n494(x)
+ if (x < 1)
+ fun_l29_n622(x)
+ else
+ fun_l29_n378(x)
+ end
+end
+
+def fun_l28_n495(x)
+ if (x < 1)
+ fun_l29_n824(x)
+ else
+ fun_l29_n377(x)
+ end
+end
+
+def fun_l28_n496(x)
+ if (x < 1)
+ fun_l29_n939(x)
+ else
+ fun_l29_n927(x)
+ end
+end
+
+def fun_l28_n497(x)
+ if (x < 1)
+ fun_l29_n760(x)
+ else
+ fun_l29_n215(x)
+ end
+end
+
+def fun_l28_n498(x)
+ if (x < 1)
+ fun_l29_n208(x)
+ else
+ fun_l29_n256(x)
+ end
+end
+
+def fun_l28_n499(x)
+ if (x < 1)
+ fun_l29_n19(x)
+ else
+ fun_l29_n956(x)
+ end
+end
+
+def fun_l28_n500(x)
+ if (x < 1)
+ fun_l29_n963(x)
+ else
+ fun_l29_n322(x)
+ end
+end
+
+def fun_l28_n501(x)
+ if (x < 1)
+ fun_l29_n564(x)
+ else
+ fun_l29_n261(x)
+ end
+end
+
+def fun_l28_n502(x)
+ if (x < 1)
+ fun_l29_n105(x)
+ else
+ fun_l29_n82(x)
+ end
+end
+
+def fun_l28_n503(x)
+ if (x < 1)
+ fun_l29_n165(x)
+ else
+ fun_l29_n101(x)
+ end
+end
+
+def fun_l28_n504(x)
+ if (x < 1)
+ fun_l29_n619(x)
+ else
+ fun_l29_n453(x)
+ end
+end
+
+def fun_l28_n505(x)
+ if (x < 1)
+ fun_l29_n20(x)
+ else
+ fun_l29_n329(x)
+ end
+end
+
+def fun_l28_n506(x)
+ if (x < 1)
+ fun_l29_n889(x)
+ else
+ fun_l29_n392(x)
+ end
+end
+
+def fun_l28_n507(x)
+ if (x < 1)
+ fun_l29_n824(x)
+ else
+ fun_l29_n709(x)
+ end
+end
+
+def fun_l28_n508(x)
+ if (x < 1)
+ fun_l29_n838(x)
+ else
+ fun_l29_n384(x)
+ end
+end
+
+def fun_l28_n509(x)
+ if (x < 1)
+ fun_l29_n364(x)
+ else
+ fun_l29_n789(x)
+ end
+end
+
+def fun_l28_n510(x)
+ if (x < 1)
+ fun_l29_n824(x)
+ else
+ fun_l29_n4(x)
+ end
+end
+
+def fun_l28_n511(x)
+ if (x < 1)
+ fun_l29_n481(x)
+ else
+ fun_l29_n883(x)
+ end
+end
+
+def fun_l28_n512(x)
+ if (x < 1)
+ fun_l29_n842(x)
+ else
+ fun_l29_n959(x)
+ end
+end
+
+def fun_l28_n513(x)
+ if (x < 1)
+ fun_l29_n989(x)
+ else
+ fun_l29_n400(x)
+ end
+end
+
+def fun_l28_n514(x)
+ if (x < 1)
+ fun_l29_n952(x)
+ else
+ fun_l29_n245(x)
+ end
+end
+
+def fun_l28_n515(x)
+ if (x < 1)
+ fun_l29_n966(x)
+ else
+ fun_l29_n91(x)
+ end
+end
+
+def fun_l28_n516(x)
+ if (x < 1)
+ fun_l29_n489(x)
+ else
+ fun_l29_n280(x)
+ end
+end
+
+def fun_l28_n517(x)
+ if (x < 1)
+ fun_l29_n128(x)
+ else
+ fun_l29_n722(x)
+ end
+end
+
+def fun_l28_n518(x)
+ if (x < 1)
+ fun_l29_n429(x)
+ else
+ fun_l29_n412(x)
+ end
+end
+
+def fun_l28_n519(x)
+ if (x < 1)
+ fun_l29_n884(x)
+ else
+ fun_l29_n993(x)
+ end
+end
+
+def fun_l28_n520(x)
+ if (x < 1)
+ fun_l29_n470(x)
+ else
+ fun_l29_n308(x)
+ end
+end
+
+def fun_l28_n521(x)
+ if (x < 1)
+ fun_l29_n583(x)
+ else
+ fun_l29_n683(x)
+ end
+end
+
+def fun_l28_n522(x)
+ if (x < 1)
+ fun_l29_n400(x)
+ else
+ fun_l29_n643(x)
+ end
+end
+
+def fun_l28_n523(x)
+ if (x < 1)
+ fun_l29_n750(x)
+ else
+ fun_l29_n388(x)
+ end
+end
+
+def fun_l28_n524(x)
+ if (x < 1)
+ fun_l29_n252(x)
+ else
+ fun_l29_n426(x)
+ end
+end
+
+def fun_l28_n525(x)
+ if (x < 1)
+ fun_l29_n51(x)
+ else
+ fun_l29_n720(x)
+ end
+end
+
+def fun_l28_n526(x)
+ if (x < 1)
+ fun_l29_n633(x)
+ else
+ fun_l29_n160(x)
+ end
+end
+
+def fun_l28_n527(x)
+ if (x < 1)
+ fun_l29_n507(x)
+ else
+ fun_l29_n630(x)
+ end
+end
+
+def fun_l28_n528(x)
+ if (x < 1)
+ fun_l29_n53(x)
+ else
+ fun_l29_n189(x)
+ end
+end
+
+def fun_l28_n529(x)
+ if (x < 1)
+ fun_l29_n191(x)
+ else
+ fun_l29_n767(x)
+ end
+end
+
+def fun_l28_n530(x)
+ if (x < 1)
+ fun_l29_n265(x)
+ else
+ fun_l29_n130(x)
+ end
+end
+
+def fun_l28_n531(x)
+ if (x < 1)
+ fun_l29_n936(x)
+ else
+ fun_l29_n270(x)
+ end
+end
+
+def fun_l28_n532(x)
+ if (x < 1)
+ fun_l29_n910(x)
+ else
+ fun_l29_n144(x)
+ end
+end
+
+def fun_l28_n533(x)
+ if (x < 1)
+ fun_l29_n155(x)
+ else
+ fun_l29_n947(x)
+ end
+end
+
+def fun_l28_n534(x)
+ if (x < 1)
+ fun_l29_n977(x)
+ else
+ fun_l29_n372(x)
+ end
+end
+
+def fun_l28_n535(x)
+ if (x < 1)
+ fun_l29_n728(x)
+ else
+ fun_l29_n657(x)
+ end
+end
+
+def fun_l28_n536(x)
+ if (x < 1)
+ fun_l29_n360(x)
+ else
+ fun_l29_n154(x)
+ end
+end
+
+def fun_l28_n537(x)
+ if (x < 1)
+ fun_l29_n934(x)
+ else
+ fun_l29_n93(x)
+ end
+end
+
+def fun_l28_n538(x)
+ if (x < 1)
+ fun_l29_n254(x)
+ else
+ fun_l29_n201(x)
+ end
+end
+
+def fun_l28_n539(x)
+ if (x < 1)
+ fun_l29_n310(x)
+ else
+ fun_l29_n104(x)
+ end
+end
+
+def fun_l28_n540(x)
+ if (x < 1)
+ fun_l29_n197(x)
+ else
+ fun_l29_n332(x)
+ end
+end
+
+def fun_l28_n541(x)
+ if (x < 1)
+ fun_l29_n144(x)
+ else
+ fun_l29_n519(x)
+ end
+end
+
+def fun_l28_n542(x)
+ if (x < 1)
+ fun_l29_n582(x)
+ else
+ fun_l29_n257(x)
+ end
+end
+
+def fun_l28_n543(x)
+ if (x < 1)
+ fun_l29_n984(x)
+ else
+ fun_l29_n375(x)
+ end
+end
+
+def fun_l28_n544(x)
+ if (x < 1)
+ fun_l29_n201(x)
+ else
+ fun_l29_n746(x)
+ end
+end
+
+def fun_l28_n545(x)
+ if (x < 1)
+ fun_l29_n530(x)
+ else
+ fun_l29_n209(x)
+ end
+end
+
+def fun_l28_n546(x)
+ if (x < 1)
+ fun_l29_n764(x)
+ else
+ fun_l29_n858(x)
+ end
+end
+
+def fun_l28_n547(x)
+ if (x < 1)
+ fun_l29_n830(x)
+ else
+ fun_l29_n58(x)
+ end
+end
+
+def fun_l28_n548(x)
+ if (x < 1)
+ fun_l29_n746(x)
+ else
+ fun_l29_n374(x)
+ end
+end
+
+def fun_l28_n549(x)
+ if (x < 1)
+ fun_l29_n923(x)
+ else
+ fun_l29_n489(x)
+ end
+end
+
+def fun_l28_n550(x)
+ if (x < 1)
+ fun_l29_n188(x)
+ else
+ fun_l29_n866(x)
+ end
+end
+
+def fun_l28_n551(x)
+ if (x < 1)
+ fun_l29_n959(x)
+ else
+ fun_l29_n493(x)
+ end
+end
+
+def fun_l28_n552(x)
+ if (x < 1)
+ fun_l29_n568(x)
+ else
+ fun_l29_n747(x)
+ end
+end
+
+def fun_l28_n553(x)
+ if (x < 1)
+ fun_l29_n972(x)
+ else
+ fun_l29_n507(x)
+ end
+end
+
+def fun_l28_n554(x)
+ if (x < 1)
+ fun_l29_n557(x)
+ else
+ fun_l29_n765(x)
+ end
+end
+
+def fun_l28_n555(x)
+ if (x < 1)
+ fun_l29_n430(x)
+ else
+ fun_l29_n941(x)
+ end
+end
+
+def fun_l28_n556(x)
+ if (x < 1)
+ fun_l29_n631(x)
+ else
+ fun_l29_n384(x)
+ end
+end
+
+def fun_l28_n557(x)
+ if (x < 1)
+ fun_l29_n681(x)
+ else
+ fun_l29_n976(x)
+ end
+end
+
+def fun_l28_n558(x)
+ if (x < 1)
+ fun_l29_n326(x)
+ else
+ fun_l29_n481(x)
+ end
+end
+
+def fun_l28_n559(x)
+ if (x < 1)
+ fun_l29_n882(x)
+ else
+ fun_l29_n129(x)
+ end
+end
+
+def fun_l28_n560(x)
+ if (x < 1)
+ fun_l29_n471(x)
+ else
+ fun_l29_n156(x)
+ end
+end
+
+def fun_l28_n561(x)
+ if (x < 1)
+ fun_l29_n692(x)
+ else
+ fun_l29_n968(x)
+ end
+end
+
+def fun_l28_n562(x)
+ if (x < 1)
+ fun_l29_n207(x)
+ else
+ fun_l29_n251(x)
+ end
+end
+
+def fun_l28_n563(x)
+ if (x < 1)
+ fun_l29_n519(x)
+ else
+ fun_l29_n749(x)
+ end
+end
+
+def fun_l28_n564(x)
+ if (x < 1)
+ fun_l29_n609(x)
+ else
+ fun_l29_n657(x)
+ end
+end
+
+def fun_l28_n565(x)
+ if (x < 1)
+ fun_l29_n100(x)
+ else
+ fun_l29_n932(x)
+ end
+end
+
+def fun_l28_n566(x)
+ if (x < 1)
+ fun_l29_n499(x)
+ else
+ fun_l29_n455(x)
+ end
+end
+
+def fun_l28_n567(x)
+ if (x < 1)
+ fun_l29_n486(x)
+ else
+ fun_l29_n13(x)
+ end
+end
+
+def fun_l28_n568(x)
+ if (x < 1)
+ fun_l29_n855(x)
+ else
+ fun_l29_n809(x)
+ end
+end
+
+def fun_l28_n569(x)
+ if (x < 1)
+ fun_l29_n295(x)
+ else
+ fun_l29_n576(x)
+ end
+end
+
+def fun_l28_n570(x)
+ if (x < 1)
+ fun_l29_n354(x)
+ else
+ fun_l29_n430(x)
+ end
+end
+
+def fun_l28_n571(x)
+ if (x < 1)
+ fun_l29_n307(x)
+ else
+ fun_l29_n560(x)
+ end
+end
+
+def fun_l28_n572(x)
+ if (x < 1)
+ fun_l29_n528(x)
+ else
+ fun_l29_n642(x)
+ end
+end
+
+def fun_l28_n573(x)
+ if (x < 1)
+ fun_l29_n552(x)
+ else
+ fun_l29_n421(x)
+ end
+end
+
+def fun_l28_n574(x)
+ if (x < 1)
+ fun_l29_n238(x)
+ else
+ fun_l29_n471(x)
+ end
+end
+
+def fun_l28_n575(x)
+ if (x < 1)
+ fun_l29_n748(x)
+ else
+ fun_l29_n381(x)
+ end
+end
+
+def fun_l28_n576(x)
+ if (x < 1)
+ fun_l29_n75(x)
+ else
+ fun_l29_n994(x)
+ end
+end
+
+def fun_l28_n577(x)
+ if (x < 1)
+ fun_l29_n159(x)
+ else
+ fun_l29_n923(x)
+ end
+end
+
+def fun_l28_n578(x)
+ if (x < 1)
+ fun_l29_n657(x)
+ else
+ fun_l29_n984(x)
+ end
+end
+
+def fun_l28_n579(x)
+ if (x < 1)
+ fun_l29_n150(x)
+ else
+ fun_l29_n887(x)
+ end
+end
+
+def fun_l28_n580(x)
+ if (x < 1)
+ fun_l29_n362(x)
+ else
+ fun_l29_n574(x)
+ end
+end
+
+def fun_l28_n581(x)
+ if (x < 1)
+ fun_l29_n95(x)
+ else
+ fun_l29_n258(x)
+ end
+end
+
+def fun_l28_n582(x)
+ if (x < 1)
+ fun_l29_n123(x)
+ else
+ fun_l29_n501(x)
+ end
+end
+
+def fun_l28_n583(x)
+ if (x < 1)
+ fun_l29_n934(x)
+ else
+ fun_l29_n94(x)
+ end
+end
+
+def fun_l28_n584(x)
+ if (x < 1)
+ fun_l29_n764(x)
+ else
+ fun_l29_n350(x)
+ end
+end
+
+def fun_l28_n585(x)
+ if (x < 1)
+ fun_l29_n328(x)
+ else
+ fun_l29_n483(x)
+ end
+end
+
+def fun_l28_n586(x)
+ if (x < 1)
+ fun_l29_n533(x)
+ else
+ fun_l29_n956(x)
+ end
+end
+
+def fun_l28_n587(x)
+ if (x < 1)
+ fun_l29_n632(x)
+ else
+ fun_l29_n243(x)
+ end
+end
+
+def fun_l28_n588(x)
+ if (x < 1)
+ fun_l29_n897(x)
+ else
+ fun_l29_n894(x)
+ end
+end
+
+def fun_l28_n589(x)
+ if (x < 1)
+ fun_l29_n867(x)
+ else
+ fun_l29_n68(x)
+ end
+end
+
+def fun_l28_n590(x)
+ if (x < 1)
+ fun_l29_n266(x)
+ else
+ fun_l29_n763(x)
+ end
+end
+
+def fun_l28_n591(x)
+ if (x < 1)
+ fun_l29_n104(x)
+ else
+ fun_l29_n940(x)
+ end
+end
+
+def fun_l28_n592(x)
+ if (x < 1)
+ fun_l29_n409(x)
+ else
+ fun_l29_n561(x)
+ end
+end
+
+def fun_l28_n593(x)
+ if (x < 1)
+ fun_l29_n485(x)
+ else
+ fun_l29_n780(x)
+ end
+end
+
+def fun_l28_n594(x)
+ if (x < 1)
+ fun_l29_n925(x)
+ else
+ fun_l29_n581(x)
+ end
+end
+
+def fun_l28_n595(x)
+ if (x < 1)
+ fun_l29_n566(x)
+ else
+ fun_l29_n288(x)
+ end
+end
+
+def fun_l28_n596(x)
+ if (x < 1)
+ fun_l29_n166(x)
+ else
+ fun_l29_n702(x)
+ end
+end
+
+def fun_l28_n597(x)
+ if (x < 1)
+ fun_l29_n82(x)
+ else
+ fun_l29_n815(x)
+ end
+end
+
+def fun_l28_n598(x)
+ if (x < 1)
+ fun_l29_n913(x)
+ else
+ fun_l29_n623(x)
+ end
+end
+
+def fun_l28_n599(x)
+ if (x < 1)
+ fun_l29_n431(x)
+ else
+ fun_l29_n216(x)
+ end
+end
+
+def fun_l28_n600(x)
+ if (x < 1)
+ fun_l29_n260(x)
+ else
+ fun_l29_n907(x)
+ end
+end
+
+def fun_l28_n601(x)
+ if (x < 1)
+ fun_l29_n232(x)
+ else
+ fun_l29_n504(x)
+ end
+end
+
+def fun_l28_n602(x)
+ if (x < 1)
+ fun_l29_n25(x)
+ else
+ fun_l29_n844(x)
+ end
+end
+
+def fun_l28_n603(x)
+ if (x < 1)
+ fun_l29_n997(x)
+ else
+ fun_l29_n821(x)
+ end
+end
+
+def fun_l28_n604(x)
+ if (x < 1)
+ fun_l29_n732(x)
+ else
+ fun_l29_n301(x)
+ end
+end
+
+def fun_l28_n605(x)
+ if (x < 1)
+ fun_l29_n971(x)
+ else
+ fun_l29_n522(x)
+ end
+end
+
+def fun_l28_n606(x)
+ if (x < 1)
+ fun_l29_n518(x)
+ else
+ fun_l29_n874(x)
+ end
+end
+
+def fun_l28_n607(x)
+ if (x < 1)
+ fun_l29_n104(x)
+ else
+ fun_l29_n529(x)
+ end
+end
+
+def fun_l28_n608(x)
+ if (x < 1)
+ fun_l29_n662(x)
+ else
+ fun_l29_n830(x)
+ end
+end
+
+def fun_l28_n609(x)
+ if (x < 1)
+ fun_l29_n521(x)
+ else
+ fun_l29_n944(x)
+ end
+end
+
+def fun_l28_n610(x)
+ if (x < 1)
+ fun_l29_n231(x)
+ else
+ fun_l29_n92(x)
+ end
+end
+
+def fun_l28_n611(x)
+ if (x < 1)
+ fun_l29_n290(x)
+ else
+ fun_l29_n261(x)
+ end
+end
+
+def fun_l28_n612(x)
+ if (x < 1)
+ fun_l29_n490(x)
+ else
+ fun_l29_n621(x)
+ end
+end
+
+def fun_l28_n613(x)
+ if (x < 1)
+ fun_l29_n131(x)
+ else
+ fun_l29_n946(x)
+ end
+end
+
+def fun_l28_n614(x)
+ if (x < 1)
+ fun_l29_n34(x)
+ else
+ fun_l29_n159(x)
+ end
+end
+
+def fun_l28_n615(x)
+ if (x < 1)
+ fun_l29_n811(x)
+ else
+ fun_l29_n895(x)
+ end
+end
+
+def fun_l28_n616(x)
+ if (x < 1)
+ fun_l29_n713(x)
+ else
+ fun_l29_n686(x)
+ end
+end
+
+def fun_l28_n617(x)
+ if (x < 1)
+ fun_l29_n650(x)
+ else
+ fun_l29_n256(x)
+ end
+end
+
+def fun_l28_n618(x)
+ if (x < 1)
+ fun_l29_n815(x)
+ else
+ fun_l29_n537(x)
+ end
+end
+
+def fun_l28_n619(x)
+ if (x < 1)
+ fun_l29_n739(x)
+ else
+ fun_l29_n735(x)
+ end
+end
+
+def fun_l28_n620(x)
+ if (x < 1)
+ fun_l29_n857(x)
+ else
+ fun_l29_n863(x)
+ end
+end
+
+def fun_l28_n621(x)
+ if (x < 1)
+ fun_l29_n81(x)
+ else
+ fun_l29_n755(x)
+ end
+end
+
+def fun_l28_n622(x)
+ if (x < 1)
+ fun_l29_n841(x)
+ else
+ fun_l29_n597(x)
+ end
+end
+
+def fun_l28_n623(x)
+ if (x < 1)
+ fun_l29_n87(x)
+ else
+ fun_l29_n676(x)
+ end
+end
+
+def fun_l28_n624(x)
+ if (x < 1)
+ fun_l29_n67(x)
+ else
+ fun_l29_n883(x)
+ end
+end
+
+def fun_l28_n625(x)
+ if (x < 1)
+ fun_l29_n223(x)
+ else
+ fun_l29_n139(x)
+ end
+end
+
+def fun_l28_n626(x)
+ if (x < 1)
+ fun_l29_n351(x)
+ else
+ fun_l29_n11(x)
+ end
+end
+
+def fun_l28_n627(x)
+ if (x < 1)
+ fun_l29_n281(x)
+ else
+ fun_l29_n138(x)
+ end
+end
+
+def fun_l28_n628(x)
+ if (x < 1)
+ fun_l29_n118(x)
+ else
+ fun_l29_n44(x)
+ end
+end
+
+def fun_l28_n629(x)
+ if (x < 1)
+ fun_l29_n55(x)
+ else
+ fun_l29_n249(x)
+ end
+end
+
+def fun_l28_n630(x)
+ if (x < 1)
+ fun_l29_n636(x)
+ else
+ fun_l29_n717(x)
+ end
+end
+
+def fun_l28_n631(x)
+ if (x < 1)
+ fun_l29_n88(x)
+ else
+ fun_l29_n670(x)
+ end
+end
+
+def fun_l28_n632(x)
+ if (x < 1)
+ fun_l29_n311(x)
+ else
+ fun_l29_n337(x)
+ end
+end
+
+def fun_l28_n633(x)
+ if (x < 1)
+ fun_l29_n67(x)
+ else
+ fun_l29_n12(x)
+ end
+end
+
+def fun_l28_n634(x)
+ if (x < 1)
+ fun_l29_n581(x)
+ else
+ fun_l29_n618(x)
+ end
+end
+
+def fun_l28_n635(x)
+ if (x < 1)
+ fun_l29_n709(x)
+ else
+ fun_l29_n120(x)
+ end
+end
+
+def fun_l28_n636(x)
+ if (x < 1)
+ fun_l29_n904(x)
+ else
+ fun_l29_n987(x)
+ end
+end
+
+def fun_l28_n637(x)
+ if (x < 1)
+ fun_l29_n274(x)
+ else
+ fun_l29_n219(x)
+ end
+end
+
+def fun_l28_n638(x)
+ if (x < 1)
+ fun_l29_n444(x)
+ else
+ fun_l29_n609(x)
+ end
+end
+
+def fun_l28_n639(x)
+ if (x < 1)
+ fun_l29_n473(x)
+ else
+ fun_l29_n433(x)
+ end
+end
+
+def fun_l28_n640(x)
+ if (x < 1)
+ fun_l29_n344(x)
+ else
+ fun_l29_n59(x)
+ end
+end
+
+def fun_l28_n641(x)
+ if (x < 1)
+ fun_l29_n973(x)
+ else
+ fun_l29_n506(x)
+ end
+end
+
+def fun_l28_n642(x)
+ if (x < 1)
+ fun_l29_n387(x)
+ else
+ fun_l29_n347(x)
+ end
+end
+
+def fun_l28_n643(x)
+ if (x < 1)
+ fun_l29_n138(x)
+ else
+ fun_l29_n597(x)
+ end
+end
+
+def fun_l28_n644(x)
+ if (x < 1)
+ fun_l29_n622(x)
+ else
+ fun_l29_n276(x)
+ end
+end
+
+def fun_l28_n645(x)
+ if (x < 1)
+ fun_l29_n454(x)
+ else
+ fun_l29_n930(x)
+ end
+end
+
+def fun_l28_n646(x)
+ if (x < 1)
+ fun_l29_n586(x)
+ else
+ fun_l29_n3(x)
+ end
+end
+
+def fun_l28_n647(x)
+ if (x < 1)
+ fun_l29_n508(x)
+ else
+ fun_l29_n489(x)
+ end
+end
+
+def fun_l28_n648(x)
+ if (x < 1)
+ fun_l29_n549(x)
+ else
+ fun_l29_n57(x)
+ end
+end
+
+def fun_l28_n649(x)
+ if (x < 1)
+ fun_l29_n32(x)
+ else
+ fun_l29_n487(x)
+ end
+end
+
+def fun_l28_n650(x)
+ if (x < 1)
+ fun_l29_n567(x)
+ else
+ fun_l29_n733(x)
+ end
+end
+
+def fun_l28_n651(x)
+ if (x < 1)
+ fun_l29_n401(x)
+ else
+ fun_l29_n234(x)
+ end
+end
+
+def fun_l28_n652(x)
+ if (x < 1)
+ fun_l29_n124(x)
+ else
+ fun_l29_n387(x)
+ end
+end
+
+def fun_l28_n653(x)
+ if (x < 1)
+ fun_l29_n517(x)
+ else
+ fun_l29_n150(x)
+ end
+end
+
+def fun_l28_n654(x)
+ if (x < 1)
+ fun_l29_n502(x)
+ else
+ fun_l29_n139(x)
+ end
+end
+
+def fun_l28_n655(x)
+ if (x < 1)
+ fun_l29_n304(x)
+ else
+ fun_l29_n871(x)
+ end
+end
+
+def fun_l28_n656(x)
+ if (x < 1)
+ fun_l29_n413(x)
+ else
+ fun_l29_n759(x)
+ end
+end
+
+def fun_l28_n657(x)
+ if (x < 1)
+ fun_l29_n810(x)
+ else
+ fun_l29_n274(x)
+ end
+end
+
+def fun_l28_n658(x)
+ if (x < 1)
+ fun_l29_n706(x)
+ else
+ fun_l29_n564(x)
+ end
+end
+
+def fun_l28_n659(x)
+ if (x < 1)
+ fun_l29_n205(x)
+ else
+ fun_l29_n857(x)
+ end
+end
+
+def fun_l28_n660(x)
+ if (x < 1)
+ fun_l29_n534(x)
+ else
+ fun_l29_n853(x)
+ end
+end
+
+def fun_l28_n661(x)
+ if (x < 1)
+ fun_l29_n436(x)
+ else
+ fun_l29_n227(x)
+ end
+end
+
+def fun_l28_n662(x)
+ if (x < 1)
+ fun_l29_n784(x)
+ else
+ fun_l29_n352(x)
+ end
+end
+
+def fun_l28_n663(x)
+ if (x < 1)
+ fun_l29_n889(x)
+ else
+ fun_l29_n186(x)
+ end
+end
+
+def fun_l28_n664(x)
+ if (x < 1)
+ fun_l29_n872(x)
+ else
+ fun_l29_n217(x)
+ end
+end
+
+def fun_l28_n665(x)
+ if (x < 1)
+ fun_l29_n111(x)
+ else
+ fun_l29_n355(x)
+ end
+end
+
+def fun_l28_n666(x)
+ if (x < 1)
+ fun_l29_n175(x)
+ else
+ fun_l29_n971(x)
+ end
+end
+
+def fun_l28_n667(x)
+ if (x < 1)
+ fun_l29_n823(x)
+ else
+ fun_l29_n123(x)
+ end
+end
+
+def fun_l28_n668(x)
+ if (x < 1)
+ fun_l29_n239(x)
+ else
+ fun_l29_n58(x)
+ end
+end
+
+def fun_l28_n669(x)
+ if (x < 1)
+ fun_l29_n127(x)
+ else
+ fun_l29_n628(x)
+ end
+end
+
+def fun_l28_n670(x)
+ if (x < 1)
+ fun_l29_n967(x)
+ else
+ fun_l29_n575(x)
+ end
+end
+
+def fun_l28_n671(x)
+ if (x < 1)
+ fun_l29_n994(x)
+ else
+ fun_l29_n352(x)
+ end
+end
+
+def fun_l28_n672(x)
+ if (x < 1)
+ fun_l29_n598(x)
+ else
+ fun_l29_n620(x)
+ end
+end
+
+def fun_l28_n673(x)
+ if (x < 1)
+ fun_l29_n407(x)
+ else
+ fun_l29_n132(x)
+ end
+end
+
+def fun_l28_n674(x)
+ if (x < 1)
+ fun_l29_n553(x)
+ else
+ fun_l29_n807(x)
+ end
+end
+
+def fun_l28_n675(x)
+ if (x < 1)
+ fun_l29_n918(x)
+ else
+ fun_l29_n462(x)
+ end
+end
+
+def fun_l28_n676(x)
+ if (x < 1)
+ fun_l29_n340(x)
+ else
+ fun_l29_n905(x)
+ end
+end
+
+def fun_l28_n677(x)
+ if (x < 1)
+ fun_l29_n322(x)
+ else
+ fun_l29_n657(x)
+ end
+end
+
+def fun_l28_n678(x)
+ if (x < 1)
+ fun_l29_n249(x)
+ else
+ fun_l29_n691(x)
+ end
+end
+
+def fun_l28_n679(x)
+ if (x < 1)
+ fun_l29_n227(x)
+ else
+ fun_l29_n559(x)
+ end
+end
+
+def fun_l28_n680(x)
+ if (x < 1)
+ fun_l29_n151(x)
+ else
+ fun_l29_n191(x)
+ end
+end
+
+def fun_l28_n681(x)
+ if (x < 1)
+ fun_l29_n211(x)
+ else
+ fun_l29_n400(x)
+ end
+end
+
+def fun_l28_n682(x)
+ if (x < 1)
+ fun_l29_n124(x)
+ else
+ fun_l29_n334(x)
+ end
+end
+
+def fun_l28_n683(x)
+ if (x < 1)
+ fun_l29_n876(x)
+ else
+ fun_l29_n839(x)
+ end
+end
+
+def fun_l28_n684(x)
+ if (x < 1)
+ fun_l29_n764(x)
+ else
+ fun_l29_n449(x)
+ end
+end
+
+def fun_l28_n685(x)
+ if (x < 1)
+ fun_l29_n316(x)
+ else
+ fun_l29_n730(x)
+ end
+end
+
+def fun_l28_n686(x)
+ if (x < 1)
+ fun_l29_n557(x)
+ else
+ fun_l29_n851(x)
+ end
+end
+
+def fun_l28_n687(x)
+ if (x < 1)
+ fun_l29_n315(x)
+ else
+ fun_l29_n280(x)
+ end
+end
+
+def fun_l28_n688(x)
+ if (x < 1)
+ fun_l29_n467(x)
+ else
+ fun_l29_n593(x)
+ end
+end
+
+def fun_l28_n689(x)
+ if (x < 1)
+ fun_l29_n537(x)
+ else
+ fun_l29_n37(x)
+ end
+end
+
+def fun_l28_n690(x)
+ if (x < 1)
+ fun_l29_n582(x)
+ else
+ fun_l29_n205(x)
+ end
+end
+
+def fun_l28_n691(x)
+ if (x < 1)
+ fun_l29_n672(x)
+ else
+ fun_l29_n656(x)
+ end
+end
+
+def fun_l28_n692(x)
+ if (x < 1)
+ fun_l29_n280(x)
+ else
+ fun_l29_n404(x)
+ end
+end
+
+def fun_l28_n693(x)
+ if (x < 1)
+ fun_l29_n609(x)
+ else
+ fun_l29_n914(x)
+ end
+end
+
+def fun_l28_n694(x)
+ if (x < 1)
+ fun_l29_n563(x)
+ else
+ fun_l29_n215(x)
+ end
+end
+
+def fun_l28_n695(x)
+ if (x < 1)
+ fun_l29_n207(x)
+ else
+ fun_l29_n548(x)
+ end
+end
+
+def fun_l28_n696(x)
+ if (x < 1)
+ fun_l29_n981(x)
+ else
+ fun_l29_n79(x)
+ end
+end
+
+def fun_l28_n697(x)
+ if (x < 1)
+ fun_l29_n747(x)
+ else
+ fun_l29_n687(x)
+ end
+end
+
+def fun_l28_n698(x)
+ if (x < 1)
+ fun_l29_n30(x)
+ else
+ fun_l29_n104(x)
+ end
+end
+
+def fun_l28_n699(x)
+ if (x < 1)
+ fun_l29_n587(x)
+ else
+ fun_l29_n414(x)
+ end
+end
+
+def fun_l28_n700(x)
+ if (x < 1)
+ fun_l29_n956(x)
+ else
+ fun_l29_n601(x)
+ end
+end
+
+def fun_l28_n701(x)
+ if (x < 1)
+ fun_l29_n276(x)
+ else
+ fun_l29_n815(x)
+ end
+end
+
+def fun_l28_n702(x)
+ if (x < 1)
+ fun_l29_n294(x)
+ else
+ fun_l29_n94(x)
+ end
+end
+
+def fun_l28_n703(x)
+ if (x < 1)
+ fun_l29_n161(x)
+ else
+ fun_l29_n133(x)
+ end
+end
+
+def fun_l28_n704(x)
+ if (x < 1)
+ fun_l29_n898(x)
+ else
+ fun_l29_n483(x)
+ end
+end
+
+def fun_l28_n705(x)
+ if (x < 1)
+ fun_l29_n651(x)
+ else
+ fun_l29_n577(x)
+ end
+end
+
+def fun_l28_n706(x)
+ if (x < 1)
+ fun_l29_n389(x)
+ else
+ fun_l29_n595(x)
+ end
+end
+
+def fun_l28_n707(x)
+ if (x < 1)
+ fun_l29_n856(x)
+ else
+ fun_l29_n65(x)
+ end
+end
+
+def fun_l28_n708(x)
+ if (x < 1)
+ fun_l29_n77(x)
+ else
+ fun_l29_n687(x)
+ end
+end
+
+def fun_l28_n709(x)
+ if (x < 1)
+ fun_l29_n962(x)
+ else
+ fun_l29_n517(x)
+ end
+end
+
+def fun_l28_n710(x)
+ if (x < 1)
+ fun_l29_n934(x)
+ else
+ fun_l29_n804(x)
+ end
+end
+
+def fun_l28_n711(x)
+ if (x < 1)
+ fun_l29_n267(x)
+ else
+ fun_l29_n557(x)
+ end
+end
+
+def fun_l28_n712(x)
+ if (x < 1)
+ fun_l29_n691(x)
+ else
+ fun_l29_n558(x)
+ end
+end
+
+def fun_l28_n713(x)
+ if (x < 1)
+ fun_l29_n420(x)
+ else
+ fun_l29_n150(x)
+ end
+end
+
+def fun_l28_n714(x)
+ if (x < 1)
+ fun_l29_n289(x)
+ else
+ fun_l29_n814(x)
+ end
+end
+
+def fun_l28_n715(x)
+ if (x < 1)
+ fun_l29_n579(x)
+ else
+ fun_l29_n730(x)
+ end
+end
+
+def fun_l28_n716(x)
+ if (x < 1)
+ fun_l29_n331(x)
+ else
+ fun_l29_n178(x)
+ end
+end
+
+def fun_l28_n717(x)
+ if (x < 1)
+ fun_l29_n914(x)
+ else
+ fun_l29_n176(x)
+ end
+end
+
+def fun_l28_n718(x)
+ if (x < 1)
+ fun_l29_n261(x)
+ else
+ fun_l29_n203(x)
+ end
+end
+
+def fun_l28_n719(x)
+ if (x < 1)
+ fun_l29_n621(x)
+ else
+ fun_l29_n236(x)
+ end
+end
+
+def fun_l28_n720(x)
+ if (x < 1)
+ fun_l29_n453(x)
+ else
+ fun_l29_n420(x)
+ end
+end
+
+def fun_l28_n721(x)
+ if (x < 1)
+ fun_l29_n39(x)
+ else
+ fun_l29_n499(x)
+ end
+end
+
+def fun_l28_n722(x)
+ if (x < 1)
+ fun_l29_n629(x)
+ else
+ fun_l29_n23(x)
+ end
+end
+
+def fun_l28_n723(x)
+ if (x < 1)
+ fun_l29_n55(x)
+ else
+ fun_l29_n497(x)
+ end
+end
+
+def fun_l28_n724(x)
+ if (x < 1)
+ fun_l29_n934(x)
+ else
+ fun_l29_n891(x)
+ end
+end
+
+def fun_l28_n725(x)
+ if (x < 1)
+ fun_l29_n532(x)
+ else
+ fun_l29_n959(x)
+ end
+end
+
+def fun_l28_n726(x)
+ if (x < 1)
+ fun_l29_n510(x)
+ else
+ fun_l29_n171(x)
+ end
+end
+
+def fun_l28_n727(x)
+ if (x < 1)
+ fun_l29_n42(x)
+ else
+ fun_l29_n680(x)
+ end
+end
+
+def fun_l28_n728(x)
+ if (x < 1)
+ fun_l29_n488(x)
+ else
+ fun_l29_n994(x)
+ end
+end
+
+def fun_l28_n729(x)
+ if (x < 1)
+ fun_l29_n347(x)
+ else
+ fun_l29_n135(x)
+ end
+end
+
+def fun_l28_n730(x)
+ if (x < 1)
+ fun_l29_n97(x)
+ else
+ fun_l29_n176(x)
+ end
+end
+
+def fun_l28_n731(x)
+ if (x < 1)
+ fun_l29_n4(x)
+ else
+ fun_l29_n330(x)
+ end
+end
+
+def fun_l28_n732(x)
+ if (x < 1)
+ fun_l29_n808(x)
+ else
+ fun_l29_n491(x)
+ end
+end
+
+def fun_l28_n733(x)
+ if (x < 1)
+ fun_l29_n147(x)
+ else
+ fun_l29_n520(x)
+ end
+end
+
+def fun_l28_n734(x)
+ if (x < 1)
+ fun_l29_n510(x)
+ else
+ fun_l29_n980(x)
+ end
+end
+
+def fun_l28_n735(x)
+ if (x < 1)
+ fun_l29_n656(x)
+ else
+ fun_l29_n861(x)
+ end
+end
+
+def fun_l28_n736(x)
+ if (x < 1)
+ fun_l29_n445(x)
+ else
+ fun_l29_n625(x)
+ end
+end
+
+def fun_l28_n737(x)
+ if (x < 1)
+ fun_l29_n101(x)
+ else
+ fun_l29_n874(x)
+ end
+end
+
+def fun_l28_n738(x)
+ if (x < 1)
+ fun_l29_n337(x)
+ else
+ fun_l29_n231(x)
+ end
+end
+
+def fun_l28_n739(x)
+ if (x < 1)
+ fun_l29_n518(x)
+ else
+ fun_l29_n575(x)
+ end
+end
+
+def fun_l28_n740(x)
+ if (x < 1)
+ fun_l29_n472(x)
+ else
+ fun_l29_n401(x)
+ end
+end
+
+def fun_l28_n741(x)
+ if (x < 1)
+ fun_l29_n47(x)
+ else
+ fun_l29_n435(x)
+ end
+end
+
+def fun_l28_n742(x)
+ if (x < 1)
+ fun_l29_n113(x)
+ else
+ fun_l29_n56(x)
+ end
+end
+
+def fun_l28_n743(x)
+ if (x < 1)
+ fun_l29_n435(x)
+ else
+ fun_l29_n972(x)
+ end
+end
+
+def fun_l28_n744(x)
+ if (x < 1)
+ fun_l29_n692(x)
+ else
+ fun_l29_n328(x)
+ end
+end
+
+def fun_l28_n745(x)
+ if (x < 1)
+ fun_l29_n830(x)
+ else
+ fun_l29_n92(x)
+ end
+end
+
+def fun_l28_n746(x)
+ if (x < 1)
+ fun_l29_n921(x)
+ else
+ fun_l29_n340(x)
+ end
+end
+
+def fun_l28_n747(x)
+ if (x < 1)
+ fun_l29_n346(x)
+ else
+ fun_l29_n654(x)
+ end
+end
+
+def fun_l28_n748(x)
+ if (x < 1)
+ fun_l29_n850(x)
+ else
+ fun_l29_n40(x)
+ end
+end
+
+def fun_l28_n749(x)
+ if (x < 1)
+ fun_l29_n432(x)
+ else
+ fun_l29_n445(x)
+ end
+end
+
+def fun_l28_n750(x)
+ if (x < 1)
+ fun_l29_n28(x)
+ else
+ fun_l29_n537(x)
+ end
+end
+
+def fun_l28_n751(x)
+ if (x < 1)
+ fun_l29_n858(x)
+ else
+ fun_l29_n375(x)
+ end
+end
+
+def fun_l28_n752(x)
+ if (x < 1)
+ fun_l29_n625(x)
+ else
+ fun_l29_n581(x)
+ end
+end
+
+def fun_l28_n753(x)
+ if (x < 1)
+ fun_l29_n223(x)
+ else
+ fun_l29_n509(x)
+ end
+end
+
+def fun_l28_n754(x)
+ if (x < 1)
+ fun_l29_n655(x)
+ else
+ fun_l29_n218(x)
+ end
+end
+
+def fun_l28_n755(x)
+ if (x < 1)
+ fun_l29_n998(x)
+ else
+ fun_l29_n177(x)
+ end
+end
+
+def fun_l28_n756(x)
+ if (x < 1)
+ fun_l29_n66(x)
+ else
+ fun_l29_n763(x)
+ end
+end
+
+def fun_l28_n757(x)
+ if (x < 1)
+ fun_l29_n112(x)
+ else
+ fun_l29_n494(x)
+ end
+end
+
+def fun_l28_n758(x)
+ if (x < 1)
+ fun_l29_n144(x)
+ else
+ fun_l29_n402(x)
+ end
+end
+
+def fun_l28_n759(x)
+ if (x < 1)
+ fun_l29_n162(x)
+ else
+ fun_l29_n338(x)
+ end
+end
+
+def fun_l28_n760(x)
+ if (x < 1)
+ fun_l29_n975(x)
+ else
+ fun_l29_n431(x)
+ end
+end
+
+def fun_l28_n761(x)
+ if (x < 1)
+ fun_l29_n676(x)
+ else
+ fun_l29_n787(x)
+ end
+end
+
+def fun_l28_n762(x)
+ if (x < 1)
+ fun_l29_n90(x)
+ else
+ fun_l29_n828(x)
+ end
+end
+
+def fun_l28_n763(x)
+ if (x < 1)
+ fun_l29_n816(x)
+ else
+ fun_l29_n119(x)
+ end
+end
+
+def fun_l28_n764(x)
+ if (x < 1)
+ fun_l29_n624(x)
+ else
+ fun_l29_n885(x)
+ end
+end
+
+def fun_l28_n765(x)
+ if (x < 1)
+ fun_l29_n933(x)
+ else
+ fun_l29_n378(x)
+ end
+end
+
+def fun_l28_n766(x)
+ if (x < 1)
+ fun_l29_n967(x)
+ else
+ fun_l29_n580(x)
+ end
+end
+
+def fun_l28_n767(x)
+ if (x < 1)
+ fun_l29_n752(x)
+ else
+ fun_l29_n607(x)
+ end
+end
+
+def fun_l28_n768(x)
+ if (x < 1)
+ fun_l29_n333(x)
+ else
+ fun_l29_n339(x)
+ end
+end
+
+def fun_l28_n769(x)
+ if (x < 1)
+ fun_l29_n720(x)
+ else
+ fun_l29_n952(x)
+ end
+end
+
+def fun_l28_n770(x)
+ if (x < 1)
+ fun_l29_n323(x)
+ else
+ fun_l29_n542(x)
+ end
+end
+
+def fun_l28_n771(x)
+ if (x < 1)
+ fun_l29_n472(x)
+ else
+ fun_l29_n4(x)
+ end
+end
+
+def fun_l28_n772(x)
+ if (x < 1)
+ fun_l29_n962(x)
+ else
+ fun_l29_n345(x)
+ end
+end
+
+def fun_l28_n773(x)
+ if (x < 1)
+ fun_l29_n305(x)
+ else
+ fun_l29_n106(x)
+ end
+end
+
+def fun_l28_n774(x)
+ if (x < 1)
+ fun_l29_n880(x)
+ else
+ fun_l29_n731(x)
+ end
+end
+
+def fun_l28_n775(x)
+ if (x < 1)
+ fun_l29_n760(x)
+ else
+ fun_l29_n460(x)
+ end
+end
+
+def fun_l28_n776(x)
+ if (x < 1)
+ fun_l29_n445(x)
+ else
+ fun_l29_n725(x)
+ end
+end
+
+def fun_l28_n777(x)
+ if (x < 1)
+ fun_l29_n850(x)
+ else
+ fun_l29_n121(x)
+ end
+end
+
+def fun_l28_n778(x)
+ if (x < 1)
+ fun_l29_n270(x)
+ else
+ fun_l29_n85(x)
+ end
+end
+
+def fun_l28_n779(x)
+ if (x < 1)
+ fun_l29_n208(x)
+ else
+ fun_l29_n822(x)
+ end
+end
+
+def fun_l28_n780(x)
+ if (x < 1)
+ fun_l29_n832(x)
+ else
+ fun_l29_n712(x)
+ end
+end
+
+def fun_l28_n781(x)
+ if (x < 1)
+ fun_l29_n456(x)
+ else
+ fun_l29_n947(x)
+ end
+end
+
+def fun_l28_n782(x)
+ if (x < 1)
+ fun_l29_n973(x)
+ else
+ fun_l29_n912(x)
+ end
+end
+
+def fun_l28_n783(x)
+ if (x < 1)
+ fun_l29_n365(x)
+ else
+ fun_l29_n496(x)
+ end
+end
+
+def fun_l28_n784(x)
+ if (x < 1)
+ fun_l29_n717(x)
+ else
+ fun_l29_n157(x)
+ end
+end
+
+def fun_l28_n785(x)
+ if (x < 1)
+ fun_l29_n754(x)
+ else
+ fun_l29_n462(x)
+ end
+end
+
+def fun_l28_n786(x)
+ if (x < 1)
+ fun_l29_n470(x)
+ else
+ fun_l29_n528(x)
+ end
+end
+
+def fun_l28_n787(x)
+ if (x < 1)
+ fun_l29_n463(x)
+ else
+ fun_l29_n107(x)
+ end
+end
+
+def fun_l28_n788(x)
+ if (x < 1)
+ fun_l29_n583(x)
+ else
+ fun_l29_n387(x)
+ end
+end
+
+def fun_l28_n789(x)
+ if (x < 1)
+ fun_l29_n55(x)
+ else
+ fun_l29_n694(x)
+ end
+end
+
+def fun_l28_n790(x)
+ if (x < 1)
+ fun_l29_n834(x)
+ else
+ fun_l29_n306(x)
+ end
+end
+
+def fun_l28_n791(x)
+ if (x < 1)
+ fun_l29_n374(x)
+ else
+ fun_l29_n502(x)
+ end
+end
+
+def fun_l28_n792(x)
+ if (x < 1)
+ fun_l29_n462(x)
+ else
+ fun_l29_n221(x)
+ end
+end
+
+def fun_l28_n793(x)
+ if (x < 1)
+ fun_l29_n680(x)
+ else
+ fun_l29_n966(x)
+ end
+end
+
+def fun_l28_n794(x)
+ if (x < 1)
+ fun_l29_n936(x)
+ else
+ fun_l29_n911(x)
+ end
+end
+
+def fun_l28_n795(x)
+ if (x < 1)
+ fun_l29_n863(x)
+ else
+ fun_l29_n978(x)
+ end
+end
+
+def fun_l28_n796(x)
+ if (x < 1)
+ fun_l29_n1(x)
+ else
+ fun_l29_n399(x)
+ end
+end
+
+def fun_l28_n797(x)
+ if (x < 1)
+ fun_l29_n628(x)
+ else
+ fun_l29_n603(x)
+ end
+end
+
+def fun_l28_n798(x)
+ if (x < 1)
+ fun_l29_n799(x)
+ else
+ fun_l29_n979(x)
+ end
+end
+
+def fun_l28_n799(x)
+ if (x < 1)
+ fun_l29_n856(x)
+ else
+ fun_l29_n946(x)
+ end
+end
+
+def fun_l28_n800(x)
+ if (x < 1)
+ fun_l29_n556(x)
+ else
+ fun_l29_n816(x)
+ end
+end
+
+def fun_l28_n801(x)
+ if (x < 1)
+ fun_l29_n619(x)
+ else
+ fun_l29_n19(x)
+ end
+end
+
+def fun_l28_n802(x)
+ if (x < 1)
+ fun_l29_n143(x)
+ else
+ fun_l29_n287(x)
+ end
+end
+
+def fun_l28_n803(x)
+ if (x < 1)
+ fun_l29_n816(x)
+ else
+ fun_l29_n271(x)
+ end
+end
+
+def fun_l28_n804(x)
+ if (x < 1)
+ fun_l29_n517(x)
+ else
+ fun_l29_n931(x)
+ end
+end
+
+def fun_l28_n805(x)
+ if (x < 1)
+ fun_l29_n298(x)
+ else
+ fun_l29_n509(x)
+ end
+end
+
+def fun_l28_n806(x)
+ if (x < 1)
+ fun_l29_n493(x)
+ else
+ fun_l29_n341(x)
+ end
+end
+
+def fun_l28_n807(x)
+ if (x < 1)
+ fun_l29_n270(x)
+ else
+ fun_l29_n82(x)
+ end
+end
+
+def fun_l28_n808(x)
+ if (x < 1)
+ fun_l29_n980(x)
+ else
+ fun_l29_n771(x)
+ end
+end
+
+def fun_l28_n809(x)
+ if (x < 1)
+ fun_l29_n784(x)
+ else
+ fun_l29_n696(x)
+ end
+end
+
+def fun_l28_n810(x)
+ if (x < 1)
+ fun_l29_n966(x)
+ else
+ fun_l29_n216(x)
+ end
+end
+
+def fun_l28_n811(x)
+ if (x < 1)
+ fun_l29_n374(x)
+ else
+ fun_l29_n482(x)
+ end
+end
+
+def fun_l28_n812(x)
+ if (x < 1)
+ fun_l29_n682(x)
+ else
+ fun_l29_n42(x)
+ end
+end
+
+def fun_l28_n813(x)
+ if (x < 1)
+ fun_l29_n254(x)
+ else
+ fun_l29_n899(x)
+ end
+end
+
+def fun_l28_n814(x)
+ if (x < 1)
+ fun_l29_n115(x)
+ else
+ fun_l29_n336(x)
+ end
+end
+
+def fun_l28_n815(x)
+ if (x < 1)
+ fun_l29_n842(x)
+ else
+ fun_l29_n201(x)
+ end
+end
+
+def fun_l28_n816(x)
+ if (x < 1)
+ fun_l29_n258(x)
+ else
+ fun_l29_n675(x)
+ end
+end
+
+def fun_l28_n817(x)
+ if (x < 1)
+ fun_l29_n594(x)
+ else
+ fun_l29_n61(x)
+ end
+end
+
+def fun_l28_n818(x)
+ if (x < 1)
+ fun_l29_n691(x)
+ else
+ fun_l29_n627(x)
+ end
+end
+
+def fun_l28_n819(x)
+ if (x < 1)
+ fun_l29_n963(x)
+ else
+ fun_l29_n611(x)
+ end
+end
+
+def fun_l28_n820(x)
+ if (x < 1)
+ fun_l29_n455(x)
+ else
+ fun_l29_n829(x)
+ end
+end
+
+def fun_l28_n821(x)
+ if (x < 1)
+ fun_l29_n818(x)
+ else
+ fun_l29_n242(x)
+ end
+end
+
+def fun_l28_n822(x)
+ if (x < 1)
+ fun_l29_n242(x)
+ else
+ fun_l29_n474(x)
+ end
+end
+
+def fun_l28_n823(x)
+ if (x < 1)
+ fun_l29_n847(x)
+ else
+ fun_l29_n119(x)
+ end
+end
+
+def fun_l28_n824(x)
+ if (x < 1)
+ fun_l29_n141(x)
+ else
+ fun_l29_n371(x)
+ end
+end
+
+def fun_l28_n825(x)
+ if (x < 1)
+ fun_l29_n913(x)
+ else
+ fun_l29_n129(x)
+ end
+end
+
+def fun_l28_n826(x)
+ if (x < 1)
+ fun_l29_n440(x)
+ else
+ fun_l29_n860(x)
+ end
+end
+
+def fun_l28_n827(x)
+ if (x < 1)
+ fun_l29_n194(x)
+ else
+ fun_l29_n940(x)
+ end
+end
+
+def fun_l28_n828(x)
+ if (x < 1)
+ fun_l29_n444(x)
+ else
+ fun_l29_n332(x)
+ end
+end
+
+def fun_l28_n829(x)
+ if (x < 1)
+ fun_l29_n435(x)
+ else
+ fun_l29_n559(x)
+ end
+end
+
+def fun_l28_n830(x)
+ if (x < 1)
+ fun_l29_n898(x)
+ else
+ fun_l29_n418(x)
+ end
+end
+
+def fun_l28_n831(x)
+ if (x < 1)
+ fun_l29_n13(x)
+ else
+ fun_l29_n917(x)
+ end
+end
+
+def fun_l28_n832(x)
+ if (x < 1)
+ fun_l29_n705(x)
+ else
+ fun_l29_n738(x)
+ end
+end
+
+def fun_l28_n833(x)
+ if (x < 1)
+ fun_l29_n519(x)
+ else
+ fun_l29_n35(x)
+ end
+end
+
+def fun_l28_n834(x)
+ if (x < 1)
+ fun_l29_n205(x)
+ else
+ fun_l29_n928(x)
+ end
+end
+
+def fun_l28_n835(x)
+ if (x < 1)
+ fun_l29_n401(x)
+ else
+ fun_l29_n191(x)
+ end
+end
+
+def fun_l28_n836(x)
+ if (x < 1)
+ fun_l29_n497(x)
+ else
+ fun_l29_n789(x)
+ end
+end
+
+def fun_l28_n837(x)
+ if (x < 1)
+ fun_l29_n745(x)
+ else
+ fun_l29_n714(x)
+ end
+end
+
+def fun_l28_n838(x)
+ if (x < 1)
+ fun_l29_n885(x)
+ else
+ fun_l29_n845(x)
+ end
+end
+
+def fun_l28_n839(x)
+ if (x < 1)
+ fun_l29_n423(x)
+ else
+ fun_l29_n835(x)
+ end
+end
+
+def fun_l28_n840(x)
+ if (x < 1)
+ fun_l29_n844(x)
+ else
+ fun_l29_n296(x)
+ end
+end
+
+def fun_l28_n841(x)
+ if (x < 1)
+ fun_l29_n980(x)
+ else
+ fun_l29_n298(x)
+ end
+end
+
+def fun_l28_n842(x)
+ if (x < 1)
+ fun_l29_n169(x)
+ else
+ fun_l29_n613(x)
+ end
+end
+
+def fun_l28_n843(x)
+ if (x < 1)
+ fun_l29_n323(x)
+ else
+ fun_l29_n437(x)
+ end
+end
+
+def fun_l28_n844(x)
+ if (x < 1)
+ fun_l29_n532(x)
+ else
+ fun_l29_n841(x)
+ end
+end
+
+def fun_l28_n845(x)
+ if (x < 1)
+ fun_l29_n984(x)
+ else
+ fun_l29_n696(x)
+ end
+end
+
+def fun_l28_n846(x)
+ if (x < 1)
+ fun_l29_n474(x)
+ else
+ fun_l29_n346(x)
+ end
+end
+
+def fun_l28_n847(x)
+ if (x < 1)
+ fun_l29_n725(x)
+ else
+ fun_l29_n994(x)
+ end
+end
+
+def fun_l28_n848(x)
+ if (x < 1)
+ fun_l29_n650(x)
+ else
+ fun_l29_n920(x)
+ end
+end
+
+def fun_l28_n849(x)
+ if (x < 1)
+ fun_l29_n626(x)
+ else
+ fun_l29_n704(x)
+ end
+end
+
+def fun_l28_n850(x)
+ if (x < 1)
+ fun_l29_n506(x)
+ else
+ fun_l29_n440(x)
+ end
+end
+
+def fun_l28_n851(x)
+ if (x < 1)
+ fun_l29_n512(x)
+ else
+ fun_l29_n811(x)
+ end
+end
+
+def fun_l28_n852(x)
+ if (x < 1)
+ fun_l29_n763(x)
+ else
+ fun_l29_n986(x)
+ end
+end
+
+def fun_l28_n853(x)
+ if (x < 1)
+ fun_l29_n866(x)
+ else
+ fun_l29_n972(x)
+ end
+end
+
+def fun_l28_n854(x)
+ if (x < 1)
+ fun_l29_n71(x)
+ else
+ fun_l29_n347(x)
+ end
+end
+
+def fun_l28_n855(x)
+ if (x < 1)
+ fun_l29_n380(x)
+ else
+ fun_l29_n809(x)
+ end
+end
+
+def fun_l28_n856(x)
+ if (x < 1)
+ fun_l29_n802(x)
+ else
+ fun_l29_n13(x)
+ end
+end
+
+def fun_l28_n857(x)
+ if (x < 1)
+ fun_l29_n631(x)
+ else
+ fun_l29_n636(x)
+ end
+end
+
+def fun_l28_n858(x)
+ if (x < 1)
+ fun_l29_n542(x)
+ else
+ fun_l29_n166(x)
+ end
+end
+
+def fun_l28_n859(x)
+ if (x < 1)
+ fun_l29_n393(x)
+ else
+ fun_l29_n317(x)
+ end
+end
+
+def fun_l28_n860(x)
+ if (x < 1)
+ fun_l29_n833(x)
+ else
+ fun_l29_n424(x)
+ end
+end
+
+def fun_l28_n861(x)
+ if (x < 1)
+ fun_l29_n62(x)
+ else
+ fun_l29_n78(x)
+ end
+end
+
+def fun_l28_n862(x)
+ if (x < 1)
+ fun_l29_n145(x)
+ else
+ fun_l29_n322(x)
+ end
+end
+
+def fun_l28_n863(x)
+ if (x < 1)
+ fun_l29_n733(x)
+ else
+ fun_l29_n171(x)
+ end
+end
+
+def fun_l28_n864(x)
+ if (x < 1)
+ fun_l29_n35(x)
+ else
+ fun_l29_n626(x)
+ end
+end
+
+def fun_l28_n865(x)
+ if (x < 1)
+ fun_l29_n356(x)
+ else
+ fun_l29_n832(x)
+ end
+end
+
+def fun_l28_n866(x)
+ if (x < 1)
+ fun_l29_n823(x)
+ else
+ fun_l29_n480(x)
+ end
+end
+
+def fun_l28_n867(x)
+ if (x < 1)
+ fun_l29_n397(x)
+ else
+ fun_l29_n245(x)
+ end
+end
+
+def fun_l28_n868(x)
+ if (x < 1)
+ fun_l29_n403(x)
+ else
+ fun_l29_n682(x)
+ end
+end
+
+def fun_l28_n869(x)
+ if (x < 1)
+ fun_l29_n481(x)
+ else
+ fun_l29_n543(x)
+ end
+end
+
+def fun_l28_n870(x)
+ if (x < 1)
+ fun_l29_n759(x)
+ else
+ fun_l29_n281(x)
+ end
+end
+
+def fun_l28_n871(x)
+ if (x < 1)
+ fun_l29_n671(x)
+ else
+ fun_l29_n644(x)
+ end
+end
+
+def fun_l28_n872(x)
+ if (x < 1)
+ fun_l29_n210(x)
+ else
+ fun_l29_n76(x)
+ end
+end
+
+def fun_l28_n873(x)
+ if (x < 1)
+ fun_l29_n823(x)
+ else
+ fun_l29_n461(x)
+ end
+end
+
+def fun_l28_n874(x)
+ if (x < 1)
+ fun_l29_n269(x)
+ else
+ fun_l29_n368(x)
+ end
+end
+
+def fun_l28_n875(x)
+ if (x < 1)
+ fun_l29_n727(x)
+ else
+ fun_l29_n37(x)
+ end
+end
+
+def fun_l28_n876(x)
+ if (x < 1)
+ fun_l29_n670(x)
+ else
+ fun_l29_n389(x)
+ end
+end
+
+def fun_l28_n877(x)
+ if (x < 1)
+ fun_l29_n844(x)
+ else
+ fun_l29_n424(x)
+ end
+end
+
+def fun_l28_n878(x)
+ if (x < 1)
+ fun_l29_n612(x)
+ else
+ fun_l29_n201(x)
+ end
+end
+
+def fun_l28_n879(x)
+ if (x < 1)
+ fun_l29_n790(x)
+ else
+ fun_l29_n270(x)
+ end
+end
+
+def fun_l28_n880(x)
+ if (x < 1)
+ fun_l29_n976(x)
+ else
+ fun_l29_n362(x)
+ end
+end
+
+def fun_l28_n881(x)
+ if (x < 1)
+ fun_l29_n701(x)
+ else
+ fun_l29_n846(x)
+ end
+end
+
+def fun_l28_n882(x)
+ if (x < 1)
+ fun_l29_n354(x)
+ else
+ fun_l29_n803(x)
+ end
+end
+
+def fun_l28_n883(x)
+ if (x < 1)
+ fun_l29_n40(x)
+ else
+ fun_l29_n168(x)
+ end
+end
+
+def fun_l28_n884(x)
+ if (x < 1)
+ fun_l29_n471(x)
+ else
+ fun_l29_n15(x)
+ end
+end
+
+def fun_l28_n885(x)
+ if (x < 1)
+ fun_l29_n87(x)
+ else
+ fun_l29_n287(x)
+ end
+end
+
+def fun_l28_n886(x)
+ if (x < 1)
+ fun_l29_n659(x)
+ else
+ fun_l29_n623(x)
+ end
+end
+
+def fun_l28_n887(x)
+ if (x < 1)
+ fun_l29_n318(x)
+ else
+ fun_l29_n377(x)
+ end
+end
+
+def fun_l28_n888(x)
+ if (x < 1)
+ fun_l29_n996(x)
+ else
+ fun_l29_n393(x)
+ end
+end
+
+def fun_l28_n889(x)
+ if (x < 1)
+ fun_l29_n999(x)
+ else
+ fun_l29_n370(x)
+ end
+end
+
+def fun_l28_n890(x)
+ if (x < 1)
+ fun_l29_n900(x)
+ else
+ fun_l29_n902(x)
+ end
+end
+
+def fun_l28_n891(x)
+ if (x < 1)
+ fun_l29_n180(x)
+ else
+ fun_l29_n477(x)
+ end
+end
+
+def fun_l28_n892(x)
+ if (x < 1)
+ fun_l29_n254(x)
+ else
+ fun_l29_n762(x)
+ end
+end
+
+def fun_l28_n893(x)
+ if (x < 1)
+ fun_l29_n36(x)
+ else
+ fun_l29_n198(x)
+ end
+end
+
+def fun_l28_n894(x)
+ if (x < 1)
+ fun_l29_n811(x)
+ else
+ fun_l29_n667(x)
+ end
+end
+
+def fun_l28_n895(x)
+ if (x < 1)
+ fun_l29_n711(x)
+ else
+ fun_l29_n462(x)
+ end
+end
+
+def fun_l28_n896(x)
+ if (x < 1)
+ fun_l29_n535(x)
+ else
+ fun_l29_n759(x)
+ end
+end
+
+def fun_l28_n897(x)
+ if (x < 1)
+ fun_l29_n336(x)
+ else
+ fun_l29_n72(x)
+ end
+end
+
+def fun_l28_n898(x)
+ if (x < 1)
+ fun_l29_n556(x)
+ else
+ fun_l29_n324(x)
+ end
+end
+
+def fun_l28_n899(x)
+ if (x < 1)
+ fun_l29_n821(x)
+ else
+ fun_l29_n520(x)
+ end
+end
+
+def fun_l28_n900(x)
+ if (x < 1)
+ fun_l29_n820(x)
+ else
+ fun_l29_n581(x)
+ end
+end
+
+def fun_l28_n901(x)
+ if (x < 1)
+ fun_l29_n416(x)
+ else
+ fun_l29_n662(x)
+ end
+end
+
+def fun_l28_n902(x)
+ if (x < 1)
+ fun_l29_n574(x)
+ else
+ fun_l29_n472(x)
+ end
+end
+
+def fun_l28_n903(x)
+ if (x < 1)
+ fun_l29_n140(x)
+ else
+ fun_l29_n608(x)
+ end
+end
+
+def fun_l28_n904(x)
+ if (x < 1)
+ fun_l29_n492(x)
+ else
+ fun_l29_n50(x)
+ end
+end
+
+def fun_l28_n905(x)
+ if (x < 1)
+ fun_l29_n240(x)
+ else
+ fun_l29_n308(x)
+ end
+end
+
+def fun_l28_n906(x)
+ if (x < 1)
+ fun_l29_n400(x)
+ else
+ fun_l29_n560(x)
+ end
+end
+
+def fun_l28_n907(x)
+ if (x < 1)
+ fun_l29_n974(x)
+ else
+ fun_l29_n580(x)
+ end
+end
+
+def fun_l28_n908(x)
+ if (x < 1)
+ fun_l29_n234(x)
+ else
+ fun_l29_n921(x)
+ end
+end
+
+def fun_l28_n909(x)
+ if (x < 1)
+ fun_l29_n712(x)
+ else
+ fun_l29_n861(x)
+ end
+end
+
+def fun_l28_n910(x)
+ if (x < 1)
+ fun_l29_n716(x)
+ else
+ fun_l29_n818(x)
+ end
+end
+
+def fun_l28_n911(x)
+ if (x < 1)
+ fun_l29_n574(x)
+ else
+ fun_l29_n668(x)
+ end
+end
+
+def fun_l28_n912(x)
+ if (x < 1)
+ fun_l29_n259(x)
+ else
+ fun_l29_n573(x)
+ end
+end
+
+def fun_l28_n913(x)
+ if (x < 1)
+ fun_l29_n427(x)
+ else
+ fun_l29_n572(x)
+ end
+end
+
+def fun_l28_n914(x)
+ if (x < 1)
+ fun_l29_n449(x)
+ else
+ fun_l29_n25(x)
+ end
+end
+
+def fun_l28_n915(x)
+ if (x < 1)
+ fun_l29_n234(x)
+ else
+ fun_l29_n391(x)
+ end
+end
+
+def fun_l28_n916(x)
+ if (x < 1)
+ fun_l29_n115(x)
+ else
+ fun_l29_n918(x)
+ end
+end
+
+def fun_l28_n917(x)
+ if (x < 1)
+ fun_l29_n83(x)
+ else
+ fun_l29_n295(x)
+ end
+end
+
+def fun_l28_n918(x)
+ if (x < 1)
+ fun_l29_n917(x)
+ else
+ fun_l29_n542(x)
+ end
+end
+
+def fun_l28_n919(x)
+ if (x < 1)
+ fun_l29_n836(x)
+ else
+ fun_l29_n460(x)
+ end
+end
+
+def fun_l28_n920(x)
+ if (x < 1)
+ fun_l29_n333(x)
+ else
+ fun_l29_n622(x)
+ end
+end
+
+def fun_l28_n921(x)
+ if (x < 1)
+ fun_l29_n717(x)
+ else
+ fun_l29_n342(x)
+ end
+end
+
+def fun_l28_n922(x)
+ if (x < 1)
+ fun_l29_n670(x)
+ else
+ fun_l29_n735(x)
+ end
+end
+
+def fun_l28_n923(x)
+ if (x < 1)
+ fun_l29_n723(x)
+ else
+ fun_l29_n994(x)
+ end
+end
+
+def fun_l28_n924(x)
+ if (x < 1)
+ fun_l29_n477(x)
+ else
+ fun_l29_n234(x)
+ end
+end
+
+def fun_l28_n925(x)
+ if (x < 1)
+ fun_l29_n514(x)
+ else
+ fun_l29_n194(x)
+ end
+end
+
+def fun_l28_n926(x)
+ if (x < 1)
+ fun_l29_n33(x)
+ else
+ fun_l29_n149(x)
+ end
+end
+
+def fun_l28_n927(x)
+ if (x < 1)
+ fun_l29_n805(x)
+ else
+ fun_l29_n9(x)
+ end
+end
+
+def fun_l28_n928(x)
+ if (x < 1)
+ fun_l29_n351(x)
+ else
+ fun_l29_n250(x)
+ end
+end
+
+def fun_l28_n929(x)
+ if (x < 1)
+ fun_l29_n22(x)
+ else
+ fun_l29_n294(x)
+ end
+end
+
+def fun_l28_n930(x)
+ if (x < 1)
+ fun_l29_n456(x)
+ else
+ fun_l29_n194(x)
+ end
+end
+
+def fun_l28_n931(x)
+ if (x < 1)
+ fun_l29_n354(x)
+ else
+ fun_l29_n341(x)
+ end
+end
+
+def fun_l28_n932(x)
+ if (x < 1)
+ fun_l29_n782(x)
+ else
+ fun_l29_n159(x)
+ end
+end
+
+def fun_l28_n933(x)
+ if (x < 1)
+ fun_l29_n636(x)
+ else
+ fun_l29_n588(x)
+ end
+end
+
+def fun_l28_n934(x)
+ if (x < 1)
+ fun_l29_n473(x)
+ else
+ fun_l29_n527(x)
+ end
+end
+
+def fun_l28_n935(x)
+ if (x < 1)
+ fun_l29_n776(x)
+ else
+ fun_l29_n349(x)
+ end
+end
+
+def fun_l28_n936(x)
+ if (x < 1)
+ fun_l29_n786(x)
+ else
+ fun_l29_n95(x)
+ end
+end
+
+def fun_l28_n937(x)
+ if (x < 1)
+ fun_l29_n276(x)
+ else
+ fun_l29_n952(x)
+ end
+end
+
+def fun_l28_n938(x)
+ if (x < 1)
+ fun_l29_n826(x)
+ else
+ fun_l29_n183(x)
+ end
+end
+
+def fun_l28_n939(x)
+ if (x < 1)
+ fun_l29_n11(x)
+ else
+ fun_l29_n775(x)
+ end
+end
+
+def fun_l28_n940(x)
+ if (x < 1)
+ fun_l29_n161(x)
+ else
+ fun_l29_n255(x)
+ end
+end
+
+def fun_l28_n941(x)
+ if (x < 1)
+ fun_l29_n77(x)
+ else
+ fun_l29_n673(x)
+ end
+end
+
+def fun_l28_n942(x)
+ if (x < 1)
+ fun_l29_n659(x)
+ else
+ fun_l29_n413(x)
+ end
+end
+
+def fun_l28_n943(x)
+ if (x < 1)
+ fun_l29_n827(x)
+ else
+ fun_l29_n262(x)
+ end
+end
+
+def fun_l28_n944(x)
+ if (x < 1)
+ fun_l29_n720(x)
+ else
+ fun_l29_n476(x)
+ end
+end
+
+def fun_l28_n945(x)
+ if (x < 1)
+ fun_l29_n457(x)
+ else
+ fun_l29_n613(x)
+ end
+end
+
+def fun_l28_n946(x)
+ if (x < 1)
+ fun_l29_n137(x)
+ else
+ fun_l29_n763(x)
+ end
+end
+
+def fun_l28_n947(x)
+ if (x < 1)
+ fun_l29_n569(x)
+ else
+ fun_l29_n331(x)
+ end
+end
+
+def fun_l28_n948(x)
+ if (x < 1)
+ fun_l29_n687(x)
+ else
+ fun_l29_n684(x)
+ end
+end
+
+def fun_l28_n949(x)
+ if (x < 1)
+ fun_l29_n532(x)
+ else
+ fun_l29_n203(x)
+ end
+end
+
+def fun_l28_n950(x)
+ if (x < 1)
+ fun_l29_n211(x)
+ else
+ fun_l29_n606(x)
+ end
+end
+
+def fun_l28_n951(x)
+ if (x < 1)
+ fun_l29_n522(x)
+ else
+ fun_l29_n907(x)
+ end
+end
+
+def fun_l28_n952(x)
+ if (x < 1)
+ fun_l29_n64(x)
+ else
+ fun_l29_n742(x)
+ end
+end
+
+def fun_l28_n953(x)
+ if (x < 1)
+ fun_l29_n28(x)
+ else
+ fun_l29_n712(x)
+ end
+end
+
+def fun_l28_n954(x)
+ if (x < 1)
+ fun_l29_n177(x)
+ else
+ fun_l29_n327(x)
+ end
+end
+
+def fun_l28_n955(x)
+ if (x < 1)
+ fun_l29_n274(x)
+ else
+ fun_l29_n830(x)
+ end
+end
+
+def fun_l28_n956(x)
+ if (x < 1)
+ fun_l29_n709(x)
+ else
+ fun_l29_n115(x)
+ end
+end
+
+def fun_l28_n957(x)
+ if (x < 1)
+ fun_l29_n72(x)
+ else
+ fun_l29_n849(x)
+ end
+end
+
+def fun_l28_n958(x)
+ if (x < 1)
+ fun_l29_n347(x)
+ else
+ fun_l29_n317(x)
+ end
+end
+
+def fun_l28_n959(x)
+ if (x < 1)
+ fun_l29_n540(x)
+ else
+ fun_l29_n226(x)
+ end
+end
+
+def fun_l28_n960(x)
+ if (x < 1)
+ fun_l29_n383(x)
+ else
+ fun_l29_n634(x)
+ end
+end
+
+def fun_l28_n961(x)
+ if (x < 1)
+ fun_l29_n616(x)
+ else
+ fun_l29_n300(x)
+ end
+end
+
+def fun_l28_n962(x)
+ if (x < 1)
+ fun_l29_n955(x)
+ else
+ fun_l29_n861(x)
+ end
+end
+
+def fun_l28_n963(x)
+ if (x < 1)
+ fun_l29_n143(x)
+ else
+ fun_l29_n106(x)
+ end
+end
+
+def fun_l28_n964(x)
+ if (x < 1)
+ fun_l29_n883(x)
+ else
+ fun_l29_n997(x)
+ end
+end
+
+def fun_l28_n965(x)
+ if (x < 1)
+ fun_l29_n247(x)
+ else
+ fun_l29_n471(x)
+ end
+end
+
+def fun_l28_n966(x)
+ if (x < 1)
+ fun_l29_n237(x)
+ else
+ fun_l29_n107(x)
+ end
+end
+
+def fun_l28_n967(x)
+ if (x < 1)
+ fun_l29_n754(x)
+ else
+ fun_l29_n996(x)
+ end
+end
+
+def fun_l28_n968(x)
+ if (x < 1)
+ fun_l29_n951(x)
+ else
+ fun_l29_n216(x)
+ end
+end
+
+def fun_l28_n969(x)
+ if (x < 1)
+ fun_l29_n36(x)
+ else
+ fun_l29_n815(x)
+ end
+end
+
+def fun_l28_n970(x)
+ if (x < 1)
+ fun_l29_n362(x)
+ else
+ fun_l29_n27(x)
+ end
+end
+
+def fun_l28_n971(x)
+ if (x < 1)
+ fun_l29_n837(x)
+ else
+ fun_l29_n230(x)
+ end
+end
+
+def fun_l28_n972(x)
+ if (x < 1)
+ fun_l29_n295(x)
+ else
+ fun_l29_n772(x)
+ end
+end
+
+def fun_l28_n973(x)
+ if (x < 1)
+ fun_l29_n570(x)
+ else
+ fun_l29_n514(x)
+ end
+end
+
+def fun_l28_n974(x)
+ if (x < 1)
+ fun_l29_n151(x)
+ else
+ fun_l29_n368(x)
+ end
+end
+
+def fun_l28_n975(x)
+ if (x < 1)
+ fun_l29_n229(x)
+ else
+ fun_l29_n408(x)
+ end
+end
+
+def fun_l28_n976(x)
+ if (x < 1)
+ fun_l29_n209(x)
+ else
+ fun_l29_n513(x)
+ end
+end
+
+def fun_l28_n977(x)
+ if (x < 1)
+ fun_l29_n753(x)
+ else
+ fun_l29_n36(x)
+ end
+end
+
+def fun_l28_n978(x)
+ if (x < 1)
+ fun_l29_n887(x)
+ else
+ fun_l29_n330(x)
+ end
+end
+
+def fun_l28_n979(x)
+ if (x < 1)
+ fun_l29_n880(x)
+ else
+ fun_l29_n6(x)
+ end
+end
+
+def fun_l28_n980(x)
+ if (x < 1)
+ fun_l29_n953(x)
+ else
+ fun_l29_n573(x)
+ end
+end
+
+def fun_l28_n981(x)
+ if (x < 1)
+ fun_l29_n960(x)
+ else
+ fun_l29_n774(x)
+ end
+end
+
+def fun_l28_n982(x)
+ if (x < 1)
+ fun_l29_n769(x)
+ else
+ fun_l29_n43(x)
+ end
+end
+
+def fun_l28_n983(x)
+ if (x < 1)
+ fun_l29_n43(x)
+ else
+ fun_l29_n168(x)
+ end
+end
+
+def fun_l28_n984(x)
+ if (x < 1)
+ fun_l29_n70(x)
+ else
+ fun_l29_n695(x)
+ end
+end
+
+def fun_l28_n985(x)
+ if (x < 1)
+ fun_l29_n421(x)
+ else
+ fun_l29_n9(x)
+ end
+end
+
+def fun_l28_n986(x)
+ if (x < 1)
+ fun_l29_n588(x)
+ else
+ fun_l29_n916(x)
+ end
+end
+
+def fun_l28_n987(x)
+ if (x < 1)
+ fun_l29_n693(x)
+ else
+ fun_l29_n979(x)
+ end
+end
+
+def fun_l28_n988(x)
+ if (x < 1)
+ fun_l29_n684(x)
+ else
+ fun_l29_n342(x)
+ end
+end
+
+def fun_l28_n989(x)
+ if (x < 1)
+ fun_l29_n148(x)
+ else
+ fun_l29_n348(x)
+ end
+end
+
+def fun_l28_n990(x)
+ if (x < 1)
+ fun_l29_n740(x)
+ else
+ fun_l29_n120(x)
+ end
+end
+
+def fun_l28_n991(x)
+ if (x < 1)
+ fun_l29_n258(x)
+ else
+ fun_l29_n670(x)
+ end
+end
+
+def fun_l28_n992(x)
+ if (x < 1)
+ fun_l29_n514(x)
+ else
+ fun_l29_n198(x)
+ end
+end
+
+def fun_l28_n993(x)
+ if (x < 1)
+ fun_l29_n563(x)
+ else
+ fun_l29_n174(x)
+ end
+end
+
+def fun_l28_n994(x)
+ if (x < 1)
+ fun_l29_n391(x)
+ else
+ fun_l29_n689(x)
+ end
+end
+
+def fun_l28_n995(x)
+ if (x < 1)
+ fun_l29_n156(x)
+ else
+ fun_l29_n579(x)
+ end
+end
+
+def fun_l28_n996(x)
+ if (x < 1)
+ fun_l29_n411(x)
+ else
+ fun_l29_n212(x)
+ end
+end
+
+def fun_l28_n997(x)
+ if (x < 1)
+ fun_l29_n709(x)
+ else
+ fun_l29_n735(x)
+ end
+end
+
+def fun_l28_n998(x)
+ if (x < 1)
+ fun_l29_n960(x)
+ else
+ fun_l29_n813(x)
+ end
+end
+
+def fun_l28_n999(x)
+ if (x < 1)
+ fun_l29_n553(x)
+ else
+ fun_l29_n875(x)
+ end
+end
+
+def fun_l29_n0(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n1(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n2(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n3(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n4(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n5(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n6(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n7(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n8(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n9(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n10(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n11(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n12(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n13(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n14(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n15(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n16(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n17(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n18(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n19(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n20(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n21(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n22(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n23(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n24(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n25(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n26(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n27(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n28(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n29(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n30(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n31(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n32(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n33(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n34(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n35(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n36(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n37(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n38(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n39(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n40(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n41(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n42(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n43(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n44(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n45(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n46(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n47(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n48(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n49(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n50(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n51(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n52(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n53(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n54(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n55(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n56(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n57(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n58(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n59(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n60(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n61(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n62(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n63(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n64(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n65(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n66(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n67(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n68(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n69(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n70(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n71(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n72(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n73(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n74(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n75(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n76(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n77(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n78(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n79(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n80(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n81(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n82(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n83(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n84(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n85(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n86(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n87(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n88(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n89(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n90(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n91(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n92(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n93(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n94(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n95(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n96(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n97(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n98(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n99(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n100(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n101(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n102(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n103(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n104(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n105(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n106(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n107(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n108(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n109(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n110(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n111(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n112(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n113(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n114(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n115(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n116(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n117(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n118(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n119(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n120(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n121(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n122(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n123(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n124(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n125(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n126(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n127(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n128(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n129(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n130(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n131(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n132(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n133(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n134(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n135(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n136(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n137(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n138(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n139(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n140(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n141(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n142(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n143(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n144(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n145(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n146(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n147(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n148(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n149(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n150(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n151(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n152(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n153(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n154(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n155(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n156(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n157(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n158(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n159(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n160(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n161(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n162(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n163(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n164(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n165(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n166(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n167(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n168(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n169(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n170(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n171(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n172(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n173(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n174(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n175(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n176(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n177(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n178(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n179(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n180(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n181(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n182(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n183(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n184(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n185(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n186(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n187(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n188(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n189(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n190(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n191(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n192(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n193(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n194(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n195(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n196(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n197(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n198(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n199(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n200(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n201(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n202(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n203(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n204(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n205(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n206(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n207(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n208(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n209(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n210(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n211(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n212(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n213(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n214(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n215(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n216(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n217(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n218(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n219(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n220(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n221(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n222(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n223(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n224(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n225(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n226(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n227(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n228(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n229(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n230(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n231(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n232(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n233(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n234(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n235(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n236(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n237(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n238(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n239(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n240(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n241(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n242(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n243(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n244(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n245(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n246(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n247(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n248(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n249(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n250(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n251(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n252(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n253(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n254(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n255(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n256(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n257(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n258(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n259(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n260(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n261(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n262(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n263(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n264(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n265(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n266(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n267(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n268(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n269(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n270(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n271(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n272(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n273(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n274(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n275(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n276(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n277(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n278(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n279(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n280(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n281(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n282(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n283(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n284(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n285(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n286(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n287(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n288(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n289(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n290(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n291(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n292(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n293(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n294(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n295(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n296(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n297(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n298(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n299(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n300(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n301(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n302(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n303(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n304(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n305(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n306(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n307(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n308(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n309(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n310(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n311(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n312(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n313(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n314(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n315(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n316(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n317(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n318(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n319(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n320(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n321(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n322(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n323(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n324(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n325(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n326(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n327(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n328(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n329(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n330(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n331(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n332(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n333(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n334(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n335(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n336(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n337(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n338(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n339(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n340(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n341(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n342(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n343(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n344(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n345(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n346(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n347(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n348(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n349(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n350(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n351(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n352(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n353(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n354(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n355(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n356(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n357(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n358(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n359(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n360(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n361(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n362(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n363(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n364(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n365(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n366(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n367(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n368(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n369(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n370(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n371(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n372(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n373(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n374(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n375(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n376(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n377(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n378(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n379(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n380(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n381(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n382(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n383(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n384(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n385(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n386(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n387(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n388(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n389(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n390(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n391(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n392(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n393(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n394(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n395(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n396(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n397(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n398(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n399(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n400(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n401(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n402(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n403(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n404(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n405(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n406(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n407(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n408(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n409(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n410(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n411(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n412(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n413(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n414(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n415(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n416(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n417(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n418(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n419(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n420(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n421(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n422(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n423(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n424(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n425(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n426(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n427(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n428(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n429(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n430(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n431(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n432(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n433(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n434(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n435(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n436(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n437(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n438(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n439(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n440(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n441(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n442(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n443(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n444(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n445(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n446(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n447(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n448(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n449(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n450(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n451(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n452(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n453(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n454(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n455(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n456(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n457(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n458(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n459(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n460(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n461(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n462(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n463(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n464(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n465(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n466(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n467(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n468(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n469(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n470(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n471(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n472(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n473(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n474(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n475(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n476(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n477(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n478(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n479(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n480(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n481(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n482(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n483(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n484(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n485(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n486(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n487(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n488(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n489(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n490(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n491(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n492(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n493(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n494(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n495(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n496(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n497(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n498(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n499(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n500(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n501(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n502(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n503(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n504(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n505(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n506(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n507(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n508(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n509(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n510(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n511(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n512(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n513(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n514(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n515(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n516(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n517(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n518(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n519(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n520(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n521(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n522(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n523(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n524(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n525(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n526(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n527(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n528(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n529(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n530(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n531(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n532(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n533(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n534(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n535(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n536(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n537(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n538(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n539(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n540(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n541(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n542(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n543(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n544(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n545(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n546(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n547(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n548(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n549(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n550(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n551(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n552(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n553(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n554(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n555(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n556(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n557(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n558(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n559(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n560(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n561(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n562(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n563(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n564(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n565(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n566(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n567(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n568(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n569(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n570(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n571(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n572(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n573(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n574(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n575(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n576(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n577(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n578(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n579(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n580(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n581(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n582(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n583(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n584(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n585(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n586(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n587(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n588(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n589(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n590(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n591(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n592(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n593(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n594(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n595(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n596(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n597(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n598(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n599(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n600(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n601(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n602(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n603(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n604(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n605(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n606(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n607(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n608(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n609(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n610(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n611(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n612(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n613(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n614(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n615(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n616(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n617(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n618(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n619(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n620(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n621(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n622(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n623(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n624(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n625(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n626(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n627(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n628(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n629(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n630(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n631(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n632(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n633(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n634(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n635(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n636(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n637(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n638(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n639(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n640(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n641(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n642(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n643(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n644(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n645(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n646(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n647(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n648(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n649(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n650(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n651(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n652(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n653(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n654(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n655(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n656(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n657(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n658(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n659(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n660(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n661(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n662(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n663(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n664(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n665(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n666(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n667(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n668(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n669(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n670(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n671(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n672(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n673(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n674(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n675(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n676(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n677(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n678(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n679(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n680(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n681(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n682(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n683(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n684(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n685(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n686(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n687(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n688(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n689(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n690(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n691(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n692(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n693(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n694(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n695(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n696(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n697(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n698(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n699(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n700(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n701(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n702(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n703(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n704(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n705(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n706(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n707(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n708(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n709(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n710(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n711(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n712(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n713(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n714(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n715(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n716(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n717(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n718(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n719(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n720(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n721(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n722(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n723(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n724(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n725(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n726(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n727(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n728(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n729(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n730(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n731(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n732(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n733(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n734(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n735(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n736(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n737(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n738(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n739(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n740(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n741(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n742(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n743(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n744(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n745(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n746(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n747(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n748(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n749(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n750(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n751(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n752(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n753(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n754(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n755(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n756(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n757(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n758(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n759(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n760(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n761(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n762(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n763(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n764(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n765(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n766(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n767(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n768(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n769(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n770(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n771(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n772(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n773(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n774(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n775(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n776(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n777(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n778(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n779(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n780(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n781(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n782(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n783(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n784(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n785(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n786(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n787(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n788(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n789(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n790(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n791(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n792(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n793(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n794(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n795(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n796(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n797(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n798(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n799(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n800(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n801(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n802(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n803(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n804(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n805(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n806(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n807(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n808(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n809(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n810(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n811(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n812(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n813(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n814(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n815(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n816(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n817(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n818(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n819(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n820(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n821(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n822(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n823(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n824(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n825(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n826(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n827(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n828(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n829(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n830(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n831(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n832(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n833(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n834(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n835(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n836(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n837(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n838(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n839(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n840(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n841(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n842(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n843(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n844(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n845(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n846(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n847(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n848(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n849(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n850(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n851(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n852(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n853(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n854(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n855(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n856(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n857(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n858(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n859(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n860(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n861(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n862(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n863(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n864(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n865(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n866(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n867(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n868(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n869(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n870(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n871(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n872(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n873(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n874(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n875(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n876(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n877(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n878(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n879(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n880(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n881(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n882(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n883(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n884(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n885(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n886(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n887(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n888(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n889(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n890(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n891(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n892(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n893(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n894(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n895(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n896(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n897(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n898(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n899(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n900(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n901(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n902(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n903(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n904(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n905(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n906(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n907(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n908(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n909(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n910(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n911(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n912(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n913(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n914(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n915(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n916(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n917(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n918(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n919(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n920(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n921(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n922(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n923(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n924(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n925(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n926(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n927(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n928(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n929(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n930(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n931(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n932(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n933(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n934(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n935(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n936(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n937(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n938(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n939(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n940(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n941(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n942(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n943(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n944(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n945(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n946(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n947(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n948(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n949(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n950(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n951(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n952(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n953(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n954(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n955(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n956(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n957(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n958(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n959(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n960(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n961(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n962(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n963(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n964(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n965(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n966(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n967(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n968(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n969(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n970(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n971(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n972(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n973(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n974(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n975(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n976(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n977(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n978(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n979(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n980(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n981(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n982(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n983(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n984(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n985(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n986(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n987(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n988(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n989(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n990(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n991(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n992(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n993(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n994(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n995(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n996(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n997(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n998(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+def fun_l29_n999(x)
+ if (x < 1)
+ inc(x)
+ else
+ inc(x)
+ end
+end
+
+@a = 0
+@b = 0
+@c = 0
+@d = 0
+
+@count = 0
+def inc(x)
+ @count += 1
+end
+
+@x = 0
+
+100.times do
+ @x = (@x < 1)? 1:0
+ fun_l0_n0(@x)
+ fun_l0_n1(@x)
+ fun_l0_n2(@x)
+ fun_l0_n3(@x)
+ fun_l0_n4(@x)
+ fun_l0_n5(@x)
+ fun_l0_n6(@x)
+ fun_l0_n7(@x)
+ fun_l0_n8(@x)
+ fun_l0_n9(@x)
+ fun_l0_n10(@x)
+ fun_l0_n11(@x)
+ fun_l0_n12(@x)
+ fun_l0_n13(@x)
+ fun_l0_n14(@x)
+ fun_l0_n15(@x)
+ fun_l0_n16(@x)
+ fun_l0_n17(@x)
+ fun_l0_n18(@x)
+ fun_l0_n19(@x)
+ fun_l0_n20(@x)
+ fun_l0_n21(@x)
+ fun_l0_n22(@x)
+ fun_l0_n23(@x)
+ fun_l0_n24(@x)
+ fun_l0_n25(@x)
+ fun_l0_n26(@x)
+ fun_l0_n27(@x)
+ fun_l0_n28(@x)
+ fun_l0_n29(@x)
+ fun_l0_n30(@x)
+ fun_l0_n31(@x)
+ fun_l0_n32(@x)
+ fun_l0_n33(@x)
+ fun_l0_n34(@x)
+ fun_l0_n35(@x)
+ fun_l0_n36(@x)
+ fun_l0_n37(@x)
+ fun_l0_n38(@x)
+ fun_l0_n39(@x)
+ fun_l0_n40(@x)
+ fun_l0_n41(@x)
+ fun_l0_n42(@x)
+ fun_l0_n43(@x)
+ fun_l0_n44(@x)
+ fun_l0_n45(@x)
+ fun_l0_n46(@x)
+ fun_l0_n47(@x)
+ fun_l0_n48(@x)
+ fun_l0_n49(@x)
+ fun_l0_n50(@x)
+ fun_l0_n51(@x)
+ fun_l0_n52(@x)
+ fun_l0_n53(@x)
+ fun_l0_n54(@x)
+ fun_l0_n55(@x)
+ fun_l0_n56(@x)
+ fun_l0_n57(@x)
+ fun_l0_n58(@x)
+ fun_l0_n59(@x)
+ fun_l0_n60(@x)
+ fun_l0_n61(@x)
+ fun_l0_n62(@x)
+ fun_l0_n63(@x)
+ fun_l0_n64(@x)
+ fun_l0_n65(@x)
+ fun_l0_n66(@x)
+ fun_l0_n67(@x)
+ fun_l0_n68(@x)
+ fun_l0_n69(@x)
+ fun_l0_n70(@x)
+ fun_l0_n71(@x)
+ fun_l0_n72(@x)
+ fun_l0_n73(@x)
+ fun_l0_n74(@x)
+ fun_l0_n75(@x)
+ fun_l0_n76(@x)
+ fun_l0_n77(@x)
+ fun_l0_n78(@x)
+ fun_l0_n79(@x)
+ fun_l0_n80(@x)
+ fun_l0_n81(@x)
+ fun_l0_n82(@x)
+ fun_l0_n83(@x)
+ fun_l0_n84(@x)
+ fun_l0_n85(@x)
+ fun_l0_n86(@x)
+ fun_l0_n87(@x)
+ fun_l0_n88(@x)
+ fun_l0_n89(@x)
+ fun_l0_n90(@x)
+ fun_l0_n91(@x)
+ fun_l0_n92(@x)
+ fun_l0_n93(@x)
+ fun_l0_n94(@x)
+ fun_l0_n95(@x)
+ fun_l0_n96(@x)
+ fun_l0_n97(@x)
+ fun_l0_n98(@x)
+ fun_l0_n99(@x)
+ fun_l0_n100(@x)
+ fun_l0_n101(@x)
+ fun_l0_n102(@x)
+ fun_l0_n103(@x)
+ fun_l0_n104(@x)
+ fun_l0_n105(@x)
+ fun_l0_n106(@x)
+ fun_l0_n107(@x)
+ fun_l0_n108(@x)
+ fun_l0_n109(@x)
+ fun_l0_n110(@x)
+ fun_l0_n111(@x)
+ fun_l0_n112(@x)
+ fun_l0_n113(@x)
+ fun_l0_n114(@x)
+ fun_l0_n115(@x)
+ fun_l0_n116(@x)
+ fun_l0_n117(@x)
+ fun_l0_n118(@x)
+ fun_l0_n119(@x)
+ fun_l0_n120(@x)
+ fun_l0_n121(@x)
+ fun_l0_n122(@x)
+ fun_l0_n123(@x)
+ fun_l0_n124(@x)
+ fun_l0_n125(@x)
+ fun_l0_n126(@x)
+ fun_l0_n127(@x)
+ fun_l0_n128(@x)
+ fun_l0_n129(@x)
+ fun_l0_n130(@x)
+ fun_l0_n131(@x)
+ fun_l0_n132(@x)
+ fun_l0_n133(@x)
+ fun_l0_n134(@x)
+ fun_l0_n135(@x)
+ fun_l0_n136(@x)
+ fun_l0_n137(@x)
+ fun_l0_n138(@x)
+ fun_l0_n139(@x)
+ fun_l0_n140(@x)
+ fun_l0_n141(@x)
+ fun_l0_n142(@x)
+ fun_l0_n143(@x)
+ fun_l0_n144(@x)
+ fun_l0_n145(@x)
+ fun_l0_n146(@x)
+ fun_l0_n147(@x)
+ fun_l0_n148(@x)
+ fun_l0_n149(@x)
+ fun_l0_n150(@x)
+ fun_l0_n151(@x)
+ fun_l0_n152(@x)
+ fun_l0_n153(@x)
+ fun_l0_n154(@x)
+ fun_l0_n155(@x)
+ fun_l0_n156(@x)
+ fun_l0_n157(@x)
+ fun_l0_n158(@x)
+ fun_l0_n159(@x)
+ fun_l0_n160(@x)
+ fun_l0_n161(@x)
+ fun_l0_n162(@x)
+ fun_l0_n163(@x)
+ fun_l0_n164(@x)
+ fun_l0_n165(@x)
+ fun_l0_n166(@x)
+ fun_l0_n167(@x)
+ fun_l0_n168(@x)
+ fun_l0_n169(@x)
+ fun_l0_n170(@x)
+ fun_l0_n171(@x)
+ fun_l0_n172(@x)
+ fun_l0_n173(@x)
+ fun_l0_n174(@x)
+ fun_l0_n175(@x)
+ fun_l0_n176(@x)
+ fun_l0_n177(@x)
+ fun_l0_n178(@x)
+ fun_l0_n179(@x)
+ fun_l0_n180(@x)
+ fun_l0_n181(@x)
+ fun_l0_n182(@x)
+ fun_l0_n183(@x)
+ fun_l0_n184(@x)
+ fun_l0_n185(@x)
+ fun_l0_n186(@x)
+ fun_l0_n187(@x)
+ fun_l0_n188(@x)
+ fun_l0_n189(@x)
+ fun_l0_n190(@x)
+ fun_l0_n191(@x)
+ fun_l0_n192(@x)
+ fun_l0_n193(@x)
+ fun_l0_n194(@x)
+ fun_l0_n195(@x)
+ fun_l0_n196(@x)
+ fun_l0_n197(@x)
+ fun_l0_n198(@x)
+ fun_l0_n199(@x)
+ fun_l0_n200(@x)
+ fun_l0_n201(@x)
+ fun_l0_n202(@x)
+ fun_l0_n203(@x)
+ fun_l0_n204(@x)
+ fun_l0_n205(@x)
+ fun_l0_n206(@x)
+ fun_l0_n207(@x)
+ fun_l0_n208(@x)
+ fun_l0_n209(@x)
+ fun_l0_n210(@x)
+ fun_l0_n211(@x)
+ fun_l0_n212(@x)
+ fun_l0_n213(@x)
+ fun_l0_n214(@x)
+ fun_l0_n215(@x)
+ fun_l0_n216(@x)
+ fun_l0_n217(@x)
+ fun_l0_n218(@x)
+ fun_l0_n219(@x)
+ fun_l0_n220(@x)
+ fun_l0_n221(@x)
+ fun_l0_n222(@x)
+ fun_l0_n223(@x)
+ fun_l0_n224(@x)
+ fun_l0_n225(@x)
+ fun_l0_n226(@x)
+ fun_l0_n227(@x)
+ fun_l0_n228(@x)
+ fun_l0_n229(@x)
+ fun_l0_n230(@x)
+ fun_l0_n231(@x)
+ fun_l0_n232(@x)
+ fun_l0_n233(@x)
+ fun_l0_n234(@x)
+ fun_l0_n235(@x)
+ fun_l0_n236(@x)
+ fun_l0_n237(@x)
+ fun_l0_n238(@x)
+ fun_l0_n239(@x)
+ fun_l0_n240(@x)
+ fun_l0_n241(@x)
+ fun_l0_n242(@x)
+ fun_l0_n243(@x)
+ fun_l0_n244(@x)
+ fun_l0_n245(@x)
+ fun_l0_n246(@x)
+ fun_l0_n247(@x)
+ fun_l0_n248(@x)
+ fun_l0_n249(@x)
+ fun_l0_n250(@x)
+ fun_l0_n251(@x)
+ fun_l0_n252(@x)
+ fun_l0_n253(@x)
+ fun_l0_n254(@x)
+ fun_l0_n255(@x)
+ fun_l0_n256(@x)
+ fun_l0_n257(@x)
+ fun_l0_n258(@x)
+ fun_l0_n259(@x)
+ fun_l0_n260(@x)
+ fun_l0_n261(@x)
+ fun_l0_n262(@x)
+ fun_l0_n263(@x)
+ fun_l0_n264(@x)
+ fun_l0_n265(@x)
+ fun_l0_n266(@x)
+ fun_l0_n267(@x)
+ fun_l0_n268(@x)
+ fun_l0_n269(@x)
+ fun_l0_n270(@x)
+ fun_l0_n271(@x)
+ fun_l0_n272(@x)
+ fun_l0_n273(@x)
+ fun_l0_n274(@x)
+ fun_l0_n275(@x)
+ fun_l0_n276(@x)
+ fun_l0_n277(@x)
+ fun_l0_n278(@x)
+ fun_l0_n279(@x)
+ fun_l0_n280(@x)
+ fun_l0_n281(@x)
+ fun_l0_n282(@x)
+ fun_l0_n283(@x)
+ fun_l0_n284(@x)
+ fun_l0_n285(@x)
+ fun_l0_n286(@x)
+ fun_l0_n287(@x)
+ fun_l0_n288(@x)
+ fun_l0_n289(@x)
+ fun_l0_n290(@x)
+ fun_l0_n291(@x)
+ fun_l0_n292(@x)
+ fun_l0_n293(@x)
+ fun_l0_n294(@x)
+ fun_l0_n295(@x)
+ fun_l0_n296(@x)
+ fun_l0_n297(@x)
+ fun_l0_n298(@x)
+ fun_l0_n299(@x)
+ fun_l0_n300(@x)
+ fun_l0_n301(@x)
+ fun_l0_n302(@x)
+ fun_l0_n303(@x)
+ fun_l0_n304(@x)
+ fun_l0_n305(@x)
+ fun_l0_n306(@x)
+ fun_l0_n307(@x)
+ fun_l0_n308(@x)
+ fun_l0_n309(@x)
+ fun_l0_n310(@x)
+ fun_l0_n311(@x)
+ fun_l0_n312(@x)
+ fun_l0_n313(@x)
+ fun_l0_n314(@x)
+ fun_l0_n315(@x)
+ fun_l0_n316(@x)
+ fun_l0_n317(@x)
+ fun_l0_n318(@x)
+ fun_l0_n319(@x)
+ fun_l0_n320(@x)
+ fun_l0_n321(@x)
+ fun_l0_n322(@x)
+ fun_l0_n323(@x)
+ fun_l0_n324(@x)
+ fun_l0_n325(@x)
+ fun_l0_n326(@x)
+ fun_l0_n327(@x)
+ fun_l0_n328(@x)
+ fun_l0_n329(@x)
+ fun_l0_n330(@x)
+ fun_l0_n331(@x)
+ fun_l0_n332(@x)
+ fun_l0_n333(@x)
+ fun_l0_n334(@x)
+ fun_l0_n335(@x)
+ fun_l0_n336(@x)
+ fun_l0_n337(@x)
+ fun_l0_n338(@x)
+ fun_l0_n339(@x)
+ fun_l0_n340(@x)
+ fun_l0_n341(@x)
+ fun_l0_n342(@x)
+ fun_l0_n343(@x)
+ fun_l0_n344(@x)
+ fun_l0_n345(@x)
+ fun_l0_n346(@x)
+ fun_l0_n347(@x)
+ fun_l0_n348(@x)
+ fun_l0_n349(@x)
+ fun_l0_n350(@x)
+ fun_l0_n351(@x)
+ fun_l0_n352(@x)
+ fun_l0_n353(@x)
+ fun_l0_n354(@x)
+ fun_l0_n355(@x)
+ fun_l0_n356(@x)
+ fun_l0_n357(@x)
+ fun_l0_n358(@x)
+ fun_l0_n359(@x)
+ fun_l0_n360(@x)
+ fun_l0_n361(@x)
+ fun_l0_n362(@x)
+ fun_l0_n363(@x)
+ fun_l0_n364(@x)
+ fun_l0_n365(@x)
+ fun_l0_n366(@x)
+ fun_l0_n367(@x)
+ fun_l0_n368(@x)
+ fun_l0_n369(@x)
+ fun_l0_n370(@x)
+ fun_l0_n371(@x)
+ fun_l0_n372(@x)
+ fun_l0_n373(@x)
+ fun_l0_n374(@x)
+ fun_l0_n375(@x)
+ fun_l0_n376(@x)
+ fun_l0_n377(@x)
+ fun_l0_n378(@x)
+ fun_l0_n379(@x)
+ fun_l0_n380(@x)
+ fun_l0_n381(@x)
+ fun_l0_n382(@x)
+ fun_l0_n383(@x)
+ fun_l0_n384(@x)
+ fun_l0_n385(@x)
+ fun_l0_n386(@x)
+ fun_l0_n387(@x)
+ fun_l0_n388(@x)
+ fun_l0_n389(@x)
+ fun_l0_n390(@x)
+ fun_l0_n391(@x)
+ fun_l0_n392(@x)
+ fun_l0_n393(@x)
+ fun_l0_n394(@x)
+ fun_l0_n395(@x)
+ fun_l0_n396(@x)
+ fun_l0_n397(@x)
+ fun_l0_n398(@x)
+ fun_l0_n399(@x)
+ fun_l0_n400(@x)
+ fun_l0_n401(@x)
+ fun_l0_n402(@x)
+ fun_l0_n403(@x)
+ fun_l0_n404(@x)
+ fun_l0_n405(@x)
+ fun_l0_n406(@x)
+ fun_l0_n407(@x)
+ fun_l0_n408(@x)
+ fun_l0_n409(@x)
+ fun_l0_n410(@x)
+ fun_l0_n411(@x)
+ fun_l0_n412(@x)
+ fun_l0_n413(@x)
+ fun_l0_n414(@x)
+ fun_l0_n415(@x)
+ fun_l0_n416(@x)
+ fun_l0_n417(@x)
+ fun_l0_n418(@x)
+ fun_l0_n419(@x)
+ fun_l0_n420(@x)
+ fun_l0_n421(@x)
+ fun_l0_n422(@x)
+ fun_l0_n423(@x)
+ fun_l0_n424(@x)
+ fun_l0_n425(@x)
+ fun_l0_n426(@x)
+ fun_l0_n427(@x)
+ fun_l0_n428(@x)
+ fun_l0_n429(@x)
+ fun_l0_n430(@x)
+ fun_l0_n431(@x)
+ fun_l0_n432(@x)
+ fun_l0_n433(@x)
+ fun_l0_n434(@x)
+ fun_l0_n435(@x)
+ fun_l0_n436(@x)
+ fun_l0_n437(@x)
+ fun_l0_n438(@x)
+ fun_l0_n439(@x)
+ fun_l0_n440(@x)
+ fun_l0_n441(@x)
+ fun_l0_n442(@x)
+ fun_l0_n443(@x)
+ fun_l0_n444(@x)
+ fun_l0_n445(@x)
+ fun_l0_n446(@x)
+ fun_l0_n447(@x)
+ fun_l0_n448(@x)
+ fun_l0_n449(@x)
+ fun_l0_n450(@x)
+ fun_l0_n451(@x)
+ fun_l0_n452(@x)
+ fun_l0_n453(@x)
+ fun_l0_n454(@x)
+ fun_l0_n455(@x)
+ fun_l0_n456(@x)
+ fun_l0_n457(@x)
+ fun_l0_n458(@x)
+ fun_l0_n459(@x)
+ fun_l0_n460(@x)
+ fun_l0_n461(@x)
+ fun_l0_n462(@x)
+ fun_l0_n463(@x)
+ fun_l0_n464(@x)
+ fun_l0_n465(@x)
+ fun_l0_n466(@x)
+ fun_l0_n467(@x)
+ fun_l0_n468(@x)
+ fun_l0_n469(@x)
+ fun_l0_n470(@x)
+ fun_l0_n471(@x)
+ fun_l0_n472(@x)
+ fun_l0_n473(@x)
+ fun_l0_n474(@x)
+ fun_l0_n475(@x)
+ fun_l0_n476(@x)
+ fun_l0_n477(@x)
+ fun_l0_n478(@x)
+ fun_l0_n479(@x)
+ fun_l0_n480(@x)
+ fun_l0_n481(@x)
+ fun_l0_n482(@x)
+ fun_l0_n483(@x)
+ fun_l0_n484(@x)
+ fun_l0_n485(@x)
+ fun_l0_n486(@x)
+ fun_l0_n487(@x)
+ fun_l0_n488(@x)
+ fun_l0_n489(@x)
+ fun_l0_n490(@x)
+ fun_l0_n491(@x)
+ fun_l0_n492(@x)
+ fun_l0_n493(@x)
+ fun_l0_n494(@x)
+ fun_l0_n495(@x)
+ fun_l0_n496(@x)
+ fun_l0_n497(@x)
+ fun_l0_n498(@x)
+ fun_l0_n499(@x)
+ fun_l0_n500(@x)
+ fun_l0_n501(@x)
+ fun_l0_n502(@x)
+ fun_l0_n503(@x)
+ fun_l0_n504(@x)
+ fun_l0_n505(@x)
+ fun_l0_n506(@x)
+ fun_l0_n507(@x)
+ fun_l0_n508(@x)
+ fun_l0_n509(@x)
+ fun_l0_n510(@x)
+ fun_l0_n511(@x)
+ fun_l0_n512(@x)
+ fun_l0_n513(@x)
+ fun_l0_n514(@x)
+ fun_l0_n515(@x)
+ fun_l0_n516(@x)
+ fun_l0_n517(@x)
+ fun_l0_n518(@x)
+ fun_l0_n519(@x)
+ fun_l0_n520(@x)
+ fun_l0_n521(@x)
+ fun_l0_n522(@x)
+ fun_l0_n523(@x)
+ fun_l0_n524(@x)
+ fun_l0_n525(@x)
+ fun_l0_n526(@x)
+ fun_l0_n527(@x)
+ fun_l0_n528(@x)
+ fun_l0_n529(@x)
+ fun_l0_n530(@x)
+ fun_l0_n531(@x)
+ fun_l0_n532(@x)
+ fun_l0_n533(@x)
+ fun_l0_n534(@x)
+ fun_l0_n535(@x)
+ fun_l0_n536(@x)
+ fun_l0_n537(@x)
+ fun_l0_n538(@x)
+ fun_l0_n539(@x)
+ fun_l0_n540(@x)
+ fun_l0_n541(@x)
+ fun_l0_n542(@x)
+ fun_l0_n543(@x)
+ fun_l0_n544(@x)
+ fun_l0_n545(@x)
+ fun_l0_n546(@x)
+ fun_l0_n547(@x)
+ fun_l0_n548(@x)
+ fun_l0_n549(@x)
+ fun_l0_n550(@x)
+ fun_l0_n551(@x)
+ fun_l0_n552(@x)
+ fun_l0_n553(@x)
+ fun_l0_n554(@x)
+ fun_l0_n555(@x)
+ fun_l0_n556(@x)
+ fun_l0_n557(@x)
+ fun_l0_n558(@x)
+ fun_l0_n559(@x)
+ fun_l0_n560(@x)
+ fun_l0_n561(@x)
+ fun_l0_n562(@x)
+ fun_l0_n563(@x)
+ fun_l0_n564(@x)
+ fun_l0_n565(@x)
+ fun_l0_n566(@x)
+ fun_l0_n567(@x)
+ fun_l0_n568(@x)
+ fun_l0_n569(@x)
+ fun_l0_n570(@x)
+ fun_l0_n571(@x)
+ fun_l0_n572(@x)
+ fun_l0_n573(@x)
+ fun_l0_n574(@x)
+ fun_l0_n575(@x)
+ fun_l0_n576(@x)
+ fun_l0_n577(@x)
+ fun_l0_n578(@x)
+ fun_l0_n579(@x)
+ fun_l0_n580(@x)
+ fun_l0_n581(@x)
+ fun_l0_n582(@x)
+ fun_l0_n583(@x)
+ fun_l0_n584(@x)
+ fun_l0_n585(@x)
+ fun_l0_n586(@x)
+ fun_l0_n587(@x)
+ fun_l0_n588(@x)
+ fun_l0_n589(@x)
+ fun_l0_n590(@x)
+ fun_l0_n591(@x)
+ fun_l0_n592(@x)
+ fun_l0_n593(@x)
+ fun_l0_n594(@x)
+ fun_l0_n595(@x)
+ fun_l0_n596(@x)
+ fun_l0_n597(@x)
+ fun_l0_n598(@x)
+ fun_l0_n599(@x)
+ fun_l0_n600(@x)
+ fun_l0_n601(@x)
+ fun_l0_n602(@x)
+ fun_l0_n603(@x)
+ fun_l0_n604(@x)
+ fun_l0_n605(@x)
+ fun_l0_n606(@x)
+ fun_l0_n607(@x)
+ fun_l0_n608(@x)
+ fun_l0_n609(@x)
+ fun_l0_n610(@x)
+ fun_l0_n611(@x)
+ fun_l0_n612(@x)
+ fun_l0_n613(@x)
+ fun_l0_n614(@x)
+ fun_l0_n615(@x)
+ fun_l0_n616(@x)
+ fun_l0_n617(@x)
+ fun_l0_n618(@x)
+ fun_l0_n619(@x)
+ fun_l0_n620(@x)
+ fun_l0_n621(@x)
+ fun_l0_n622(@x)
+ fun_l0_n623(@x)
+ fun_l0_n624(@x)
+ fun_l0_n625(@x)
+ fun_l0_n626(@x)
+ fun_l0_n627(@x)
+ fun_l0_n628(@x)
+ fun_l0_n629(@x)
+ fun_l0_n630(@x)
+ fun_l0_n631(@x)
+ fun_l0_n632(@x)
+ fun_l0_n633(@x)
+ fun_l0_n634(@x)
+ fun_l0_n635(@x)
+ fun_l0_n636(@x)
+ fun_l0_n637(@x)
+ fun_l0_n638(@x)
+ fun_l0_n639(@x)
+ fun_l0_n640(@x)
+ fun_l0_n641(@x)
+ fun_l0_n642(@x)
+ fun_l0_n643(@x)
+ fun_l0_n644(@x)
+ fun_l0_n645(@x)
+ fun_l0_n646(@x)
+ fun_l0_n647(@x)
+ fun_l0_n648(@x)
+ fun_l0_n649(@x)
+ fun_l0_n650(@x)
+ fun_l0_n651(@x)
+ fun_l0_n652(@x)
+ fun_l0_n653(@x)
+ fun_l0_n654(@x)
+ fun_l0_n655(@x)
+ fun_l0_n656(@x)
+ fun_l0_n657(@x)
+ fun_l0_n658(@x)
+ fun_l0_n659(@x)
+ fun_l0_n660(@x)
+ fun_l0_n661(@x)
+ fun_l0_n662(@x)
+ fun_l0_n663(@x)
+ fun_l0_n664(@x)
+ fun_l0_n665(@x)
+ fun_l0_n666(@x)
+ fun_l0_n667(@x)
+ fun_l0_n668(@x)
+ fun_l0_n669(@x)
+ fun_l0_n670(@x)
+ fun_l0_n671(@x)
+ fun_l0_n672(@x)
+ fun_l0_n673(@x)
+ fun_l0_n674(@x)
+ fun_l0_n675(@x)
+ fun_l0_n676(@x)
+ fun_l0_n677(@x)
+ fun_l0_n678(@x)
+ fun_l0_n679(@x)
+ fun_l0_n680(@x)
+ fun_l0_n681(@x)
+ fun_l0_n682(@x)
+ fun_l0_n683(@x)
+ fun_l0_n684(@x)
+ fun_l0_n685(@x)
+ fun_l0_n686(@x)
+ fun_l0_n687(@x)
+ fun_l0_n688(@x)
+ fun_l0_n689(@x)
+ fun_l0_n690(@x)
+ fun_l0_n691(@x)
+ fun_l0_n692(@x)
+ fun_l0_n693(@x)
+ fun_l0_n694(@x)
+ fun_l0_n695(@x)
+ fun_l0_n696(@x)
+ fun_l0_n697(@x)
+ fun_l0_n698(@x)
+ fun_l0_n699(@x)
+ fun_l0_n700(@x)
+ fun_l0_n701(@x)
+ fun_l0_n702(@x)
+ fun_l0_n703(@x)
+ fun_l0_n704(@x)
+ fun_l0_n705(@x)
+ fun_l0_n706(@x)
+ fun_l0_n707(@x)
+ fun_l0_n708(@x)
+ fun_l0_n709(@x)
+ fun_l0_n710(@x)
+ fun_l0_n711(@x)
+ fun_l0_n712(@x)
+ fun_l0_n713(@x)
+ fun_l0_n714(@x)
+ fun_l0_n715(@x)
+ fun_l0_n716(@x)
+ fun_l0_n717(@x)
+ fun_l0_n718(@x)
+ fun_l0_n719(@x)
+ fun_l0_n720(@x)
+ fun_l0_n721(@x)
+ fun_l0_n722(@x)
+ fun_l0_n723(@x)
+ fun_l0_n724(@x)
+ fun_l0_n725(@x)
+ fun_l0_n726(@x)
+ fun_l0_n727(@x)
+ fun_l0_n728(@x)
+ fun_l0_n729(@x)
+ fun_l0_n730(@x)
+ fun_l0_n731(@x)
+ fun_l0_n732(@x)
+ fun_l0_n733(@x)
+ fun_l0_n734(@x)
+ fun_l0_n735(@x)
+ fun_l0_n736(@x)
+ fun_l0_n737(@x)
+ fun_l0_n738(@x)
+ fun_l0_n739(@x)
+ fun_l0_n740(@x)
+ fun_l0_n741(@x)
+ fun_l0_n742(@x)
+ fun_l0_n743(@x)
+ fun_l0_n744(@x)
+ fun_l0_n745(@x)
+ fun_l0_n746(@x)
+ fun_l0_n747(@x)
+ fun_l0_n748(@x)
+ fun_l0_n749(@x)
+ fun_l0_n750(@x)
+ fun_l0_n751(@x)
+ fun_l0_n752(@x)
+ fun_l0_n753(@x)
+ fun_l0_n754(@x)
+ fun_l0_n755(@x)
+ fun_l0_n756(@x)
+ fun_l0_n757(@x)
+ fun_l0_n758(@x)
+ fun_l0_n759(@x)
+ fun_l0_n760(@x)
+ fun_l0_n761(@x)
+ fun_l0_n762(@x)
+ fun_l0_n763(@x)
+ fun_l0_n764(@x)
+ fun_l0_n765(@x)
+ fun_l0_n766(@x)
+ fun_l0_n767(@x)
+ fun_l0_n768(@x)
+ fun_l0_n769(@x)
+ fun_l0_n770(@x)
+ fun_l0_n771(@x)
+ fun_l0_n772(@x)
+ fun_l0_n773(@x)
+ fun_l0_n774(@x)
+ fun_l0_n775(@x)
+ fun_l0_n776(@x)
+ fun_l0_n777(@x)
+ fun_l0_n778(@x)
+ fun_l0_n779(@x)
+ fun_l0_n780(@x)
+ fun_l0_n781(@x)
+ fun_l0_n782(@x)
+ fun_l0_n783(@x)
+ fun_l0_n784(@x)
+ fun_l0_n785(@x)
+ fun_l0_n786(@x)
+ fun_l0_n787(@x)
+ fun_l0_n788(@x)
+ fun_l0_n789(@x)
+ fun_l0_n790(@x)
+ fun_l0_n791(@x)
+ fun_l0_n792(@x)
+ fun_l0_n793(@x)
+ fun_l0_n794(@x)
+ fun_l0_n795(@x)
+ fun_l0_n796(@x)
+ fun_l0_n797(@x)
+ fun_l0_n798(@x)
+ fun_l0_n799(@x)
+ fun_l0_n800(@x)
+ fun_l0_n801(@x)
+ fun_l0_n802(@x)
+ fun_l0_n803(@x)
+ fun_l0_n804(@x)
+ fun_l0_n805(@x)
+ fun_l0_n806(@x)
+ fun_l0_n807(@x)
+ fun_l0_n808(@x)
+ fun_l0_n809(@x)
+ fun_l0_n810(@x)
+ fun_l0_n811(@x)
+ fun_l0_n812(@x)
+ fun_l0_n813(@x)
+ fun_l0_n814(@x)
+ fun_l0_n815(@x)
+ fun_l0_n816(@x)
+ fun_l0_n817(@x)
+ fun_l0_n818(@x)
+ fun_l0_n819(@x)
+ fun_l0_n820(@x)
+ fun_l0_n821(@x)
+ fun_l0_n822(@x)
+ fun_l0_n823(@x)
+ fun_l0_n824(@x)
+ fun_l0_n825(@x)
+ fun_l0_n826(@x)
+ fun_l0_n827(@x)
+ fun_l0_n828(@x)
+ fun_l0_n829(@x)
+ fun_l0_n830(@x)
+ fun_l0_n831(@x)
+ fun_l0_n832(@x)
+ fun_l0_n833(@x)
+ fun_l0_n834(@x)
+ fun_l0_n835(@x)
+ fun_l0_n836(@x)
+ fun_l0_n837(@x)
+ fun_l0_n838(@x)
+ fun_l0_n839(@x)
+ fun_l0_n840(@x)
+ fun_l0_n841(@x)
+ fun_l0_n842(@x)
+ fun_l0_n843(@x)
+ fun_l0_n844(@x)
+ fun_l0_n845(@x)
+ fun_l0_n846(@x)
+ fun_l0_n847(@x)
+ fun_l0_n848(@x)
+ fun_l0_n849(@x)
+ fun_l0_n850(@x)
+ fun_l0_n851(@x)
+ fun_l0_n852(@x)
+ fun_l0_n853(@x)
+ fun_l0_n854(@x)
+ fun_l0_n855(@x)
+ fun_l0_n856(@x)
+ fun_l0_n857(@x)
+ fun_l0_n858(@x)
+ fun_l0_n859(@x)
+ fun_l0_n860(@x)
+ fun_l0_n861(@x)
+ fun_l0_n862(@x)
+ fun_l0_n863(@x)
+ fun_l0_n864(@x)
+ fun_l0_n865(@x)
+ fun_l0_n866(@x)
+ fun_l0_n867(@x)
+ fun_l0_n868(@x)
+ fun_l0_n869(@x)
+ fun_l0_n870(@x)
+ fun_l0_n871(@x)
+ fun_l0_n872(@x)
+ fun_l0_n873(@x)
+ fun_l0_n874(@x)
+ fun_l0_n875(@x)
+ fun_l0_n876(@x)
+ fun_l0_n877(@x)
+ fun_l0_n878(@x)
+ fun_l0_n879(@x)
+ fun_l0_n880(@x)
+ fun_l0_n881(@x)
+ fun_l0_n882(@x)
+ fun_l0_n883(@x)
+ fun_l0_n884(@x)
+ fun_l0_n885(@x)
+ fun_l0_n886(@x)
+ fun_l0_n887(@x)
+ fun_l0_n888(@x)
+ fun_l0_n889(@x)
+ fun_l0_n890(@x)
+ fun_l0_n891(@x)
+ fun_l0_n892(@x)
+ fun_l0_n893(@x)
+ fun_l0_n894(@x)
+ fun_l0_n895(@x)
+ fun_l0_n896(@x)
+ fun_l0_n897(@x)
+ fun_l0_n898(@x)
+ fun_l0_n899(@x)
+ fun_l0_n900(@x)
+ fun_l0_n901(@x)
+ fun_l0_n902(@x)
+ fun_l0_n903(@x)
+ fun_l0_n904(@x)
+ fun_l0_n905(@x)
+ fun_l0_n906(@x)
+ fun_l0_n907(@x)
+ fun_l0_n908(@x)
+ fun_l0_n909(@x)
+ fun_l0_n910(@x)
+ fun_l0_n911(@x)
+ fun_l0_n912(@x)
+ fun_l0_n913(@x)
+ fun_l0_n914(@x)
+ fun_l0_n915(@x)
+ fun_l0_n916(@x)
+ fun_l0_n917(@x)
+ fun_l0_n918(@x)
+ fun_l0_n919(@x)
+ fun_l0_n920(@x)
+ fun_l0_n921(@x)
+ fun_l0_n922(@x)
+ fun_l0_n923(@x)
+ fun_l0_n924(@x)
+ fun_l0_n925(@x)
+ fun_l0_n926(@x)
+ fun_l0_n927(@x)
+ fun_l0_n928(@x)
+ fun_l0_n929(@x)
+ fun_l0_n930(@x)
+ fun_l0_n931(@x)
+ fun_l0_n932(@x)
+ fun_l0_n933(@x)
+ fun_l0_n934(@x)
+ fun_l0_n935(@x)
+ fun_l0_n936(@x)
+ fun_l0_n937(@x)
+ fun_l0_n938(@x)
+ fun_l0_n939(@x)
+ fun_l0_n940(@x)
+ fun_l0_n941(@x)
+ fun_l0_n942(@x)
+ fun_l0_n943(@x)
+ fun_l0_n944(@x)
+ fun_l0_n945(@x)
+ fun_l0_n946(@x)
+ fun_l0_n947(@x)
+ fun_l0_n948(@x)
+ fun_l0_n949(@x)
+ fun_l0_n950(@x)
+ fun_l0_n951(@x)
+ fun_l0_n952(@x)
+ fun_l0_n953(@x)
+ fun_l0_n954(@x)
+ fun_l0_n955(@x)
+ fun_l0_n956(@x)
+ fun_l0_n957(@x)
+ fun_l0_n958(@x)
+ fun_l0_n959(@x)
+ fun_l0_n960(@x)
+ fun_l0_n961(@x)
+ fun_l0_n962(@x)
+ fun_l0_n963(@x)
+ fun_l0_n964(@x)
+ fun_l0_n965(@x)
+ fun_l0_n966(@x)
+ fun_l0_n967(@x)
+ fun_l0_n968(@x)
+ fun_l0_n969(@x)
+ fun_l0_n970(@x)
+ fun_l0_n971(@x)
+ fun_l0_n972(@x)
+ fun_l0_n973(@x)
+ fun_l0_n974(@x)
+ fun_l0_n975(@x)
+ fun_l0_n976(@x)
+ fun_l0_n977(@x)
+ fun_l0_n978(@x)
+ fun_l0_n979(@x)
+ fun_l0_n980(@x)
+ fun_l0_n981(@x)
+ fun_l0_n982(@x)
+ fun_l0_n983(@x)
+ fun_l0_n984(@x)
+ fun_l0_n985(@x)
+ fun_l0_n986(@x)
+ fun_l0_n987(@x)
+ fun_l0_n988(@x)
+ fun_l0_n989(@x)
+ fun_l0_n990(@x)
+ fun_l0_n991(@x)
+ fun_l0_n992(@x)
+ fun_l0_n993(@x)
+ fun_l0_n994(@x)
+ fun_l0_n995(@x)
+ fun_l0_n996(@x)
+ fun_l0_n997(@x)
+ fun_l0_n998(@x)
+ fun_l0_n999(@x)
+end
+
+@count
+
+}
diff --git a/bootstraptest/test_yjit_30k_methods.rb b/bootstraptest/test_yjit_30k_methods.rb
new file mode 100644
index 0000000000..f2acea4ce5
--- /dev/null
+++ b/bootstraptest/test_yjit_30k_methods.rb
@@ -0,0 +1,121018 @@
+# This is a torture test for the JIT.
+# There are 30K tiny methods in a 30-deep call hierarchy.
+assert_equal '1000000', %q{
+
+def fun_l0_n0()
+ fun_l1_n758
+end
+
+def fun_l0_n1()
+ fun_l1_n491
+end
+
+def fun_l0_n2()
+ fun_l1_n804
+end
+
+def fun_l0_n3()
+ fun_l1_n253
+end
+
+def fun_l0_n4()
+ fun_l1_n409
+end
+
+def fun_l0_n5()
+ fun_l1_n383
+end
+
+def fun_l0_n6()
+ fun_l1_n170
+end
+
+def fun_l0_n7()
+ fun_l1_n821
+end
+
+def fun_l0_n8()
+ fun_l1_n424
+end
+
+def fun_l0_n9()
+ fun_l1_n328
+end
+
+def fun_l0_n10()
+ fun_l1_n326
+end
+
+def fun_l0_n11()
+ fun_l1_n879
+end
+
+def fun_l0_n12()
+ fun_l1_n509
+end
+
+def fun_l0_n13()
+ fun_l1_n464
+end
+
+def fun_l0_n14()
+ fun_l1_n806
+end
+
+def fun_l0_n15()
+ fun_l1_n277
+end
+
+def fun_l0_n16()
+ fun_l1_n684
+end
+
+def fun_l0_n17()
+ fun_l1_n54
+end
+
+def fun_l0_n18()
+ fun_l1_n514
+end
+
+def fun_l0_n19()
+ fun_l1_n967
+end
+
+def fun_l0_n20()
+ fun_l1_n50
+end
+
+def fun_l0_n21()
+ fun_l1_n248
+end
+
+def fun_l0_n22()
+ fun_l1_n410
+end
+
+def fun_l0_n23()
+ fun_l1_n411
+end
+
+def fun_l0_n24()
+ fun_l1_n422
+end
+
+def fun_l0_n25()
+ fun_l1_n427
+end
+
+def fun_l0_n26()
+ fun_l1_n929
+end
+
+def fun_l0_n27()
+ fun_l1_n93
+end
+
+def fun_l0_n28()
+ fun_l1_n790
+end
+
+def fun_l0_n29()
+ fun_l1_n107
+end
+
+def fun_l0_n30()
+ fun_l1_n29
+end
+
+def fun_l0_n31()
+ fun_l1_n164
+end
+
+def fun_l0_n32()
+ fun_l1_n720
+end
+
+def fun_l0_n33()
+ fun_l1_n30
+end
+
+def fun_l0_n34()
+ fun_l1_n133
+end
+
+def fun_l0_n35()
+ fun_l1_n122
+end
+
+def fun_l0_n36()
+ fun_l1_n101
+end
+
+def fun_l0_n37()
+ fun_l1_n80
+end
+
+def fun_l0_n38()
+ fun_l1_n759
+end
+
+def fun_l0_n39()
+ fun_l1_n315
+end
+
+def fun_l0_n40()
+ fun_l1_n508
+end
+
+def fun_l0_n41()
+ fun_l1_n750
+end
+
+def fun_l0_n42()
+ fun_l1_n200
+end
+
+def fun_l0_n43()
+ fun_l1_n662
+end
+
+def fun_l0_n44()
+ fun_l1_n2
+end
+
+def fun_l0_n45()
+ fun_l1_n864
+end
+
+def fun_l0_n46()
+ fun_l1_n482
+end
+
+def fun_l0_n47()
+ fun_l1_n196
+end
+
+def fun_l0_n48()
+ fun_l1_n867
+end
+
+def fun_l0_n49()
+ fun_l1_n942
+end
+
+def fun_l0_n50()
+ fun_l1_n179
+end
+
+def fun_l0_n51()
+ fun_l1_n442
+end
+
+def fun_l0_n52()
+ fun_l1_n613
+end
+
+def fun_l0_n53()
+ fun_l1_n282
+end
+
+def fun_l0_n54()
+ fun_l1_n624
+end
+
+def fun_l0_n55()
+ fun_l1_n514
+end
+
+def fun_l0_n56()
+ fun_l1_n59
+end
+
+def fun_l0_n57()
+ fun_l1_n401
+end
+
+def fun_l0_n58()
+ fun_l1_n693
+end
+
+def fun_l0_n59()
+ fun_l1_n643
+end
+
+def fun_l0_n60()
+ fun_l1_n104
+end
+
+def fun_l0_n61()
+ fun_l1_n407
+end
+
+def fun_l0_n62()
+ fun_l1_n418
+end
+
+def fun_l0_n63()
+ fun_l1_n775
+end
+
+def fun_l0_n64()
+ fun_l1_n351
+end
+
+def fun_l0_n65()
+ fun_l1_n320
+end
+
+def fun_l0_n66()
+ fun_l1_n181
+end
+
+def fun_l0_n67()
+ fun_l1_n878
+end
+
+def fun_l0_n68()
+ fun_l1_n404
+end
+
+def fun_l0_n69()
+ fun_l1_n660
+end
+
+def fun_l0_n70()
+ fun_l1_n644
+end
+
+def fun_l0_n71()
+ fun_l1_n416
+end
+
+def fun_l0_n72()
+ fun_l1_n372
+end
+
+def fun_l0_n73()
+ fun_l1_n525
+end
+
+def fun_l0_n74()
+ fun_l1_n468
+end
+
+def fun_l0_n75()
+ fun_l1_n652
+end
+
+def fun_l0_n76()
+ fun_l1_n418
+end
+
+def fun_l0_n77()
+ fun_l1_n935
+end
+
+def fun_l0_n78()
+ fun_l1_n170
+end
+
+def fun_l0_n79()
+ fun_l1_n805
+end
+
+def fun_l0_n80()
+ fun_l1_n405
+end
+
+def fun_l0_n81()
+ fun_l1_n994
+end
+
+def fun_l0_n82()
+ fun_l1_n395
+end
+
+def fun_l0_n83()
+ fun_l1_n399
+end
+
+def fun_l0_n84()
+ fun_l1_n503
+end
+
+def fun_l0_n85()
+ fun_l1_n451
+end
+
+def fun_l0_n86()
+ fun_l1_n920
+end
+
+def fun_l0_n87()
+ fun_l1_n446
+end
+
+def fun_l0_n88()
+ fun_l1_n637
+end
+
+def fun_l0_n89()
+ fun_l1_n732
+end
+
+def fun_l0_n90()
+ fun_l1_n823
+end
+
+def fun_l0_n91()
+ fun_l1_n347
+end
+
+def fun_l0_n92()
+ fun_l1_n808
+end
+
+def fun_l0_n93()
+ fun_l1_n941
+end
+
+def fun_l0_n94()
+ fun_l1_n808
+end
+
+def fun_l0_n95()
+ fun_l1_n575
+end
+
+def fun_l0_n96()
+ fun_l1_n835
+end
+
+def fun_l0_n97()
+ fun_l1_n601
+end
+
+def fun_l0_n98()
+ fun_l1_n522
+end
+
+def fun_l0_n99()
+ fun_l1_n884
+end
+
+def fun_l0_n100()
+ fun_l1_n234
+end
+
+def fun_l0_n101()
+ fun_l1_n58
+end
+
+def fun_l0_n102()
+ fun_l1_n702
+end
+
+def fun_l0_n103()
+ fun_l1_n816
+end
+
+def fun_l0_n104()
+ fun_l1_n92
+end
+
+def fun_l0_n105()
+ fun_l1_n673
+end
+
+def fun_l0_n106()
+ fun_l1_n360
+end
+
+def fun_l0_n107()
+ fun_l1_n305
+end
+
+def fun_l0_n108()
+ fun_l1_n202
+end
+
+def fun_l0_n109()
+ fun_l1_n879
+end
+
+def fun_l0_n110()
+ fun_l1_n84
+end
+
+def fun_l0_n111()
+ fun_l1_n50
+end
+
+def fun_l0_n112()
+ fun_l1_n648
+end
+
+def fun_l0_n113()
+ fun_l1_n786
+end
+
+def fun_l0_n114()
+ fun_l1_n627
+end
+
+def fun_l0_n115()
+ fun_l1_n404
+end
+
+def fun_l0_n116()
+ fun_l1_n496
+end
+
+def fun_l0_n117()
+ fun_l1_n778
+end
+
+def fun_l0_n118()
+ fun_l1_n119
+end
+
+def fun_l0_n119()
+ fun_l1_n350
+end
+
+def fun_l0_n120()
+ fun_l1_n767
+end
+
+def fun_l0_n121()
+ fun_l1_n463
+end
+
+def fun_l0_n122()
+ fun_l1_n481
+end
+
+def fun_l0_n123()
+ fun_l1_n80
+end
+
+def fun_l0_n124()
+ fun_l1_n271
+end
+
+def fun_l0_n125()
+ fun_l1_n315
+end
+
+def fun_l0_n126()
+ fun_l1_n545
+end
+
+def fun_l0_n127()
+ fun_l1_n598
+end
+
+def fun_l0_n128()
+ fun_l1_n599
+end
+
+def fun_l0_n129()
+ fun_l1_n263
+end
+
+def fun_l0_n130()
+ fun_l1_n514
+end
+
+def fun_l0_n131()
+ fun_l1_n779
+end
+
+def fun_l0_n132()
+ fun_l1_n585
+end
+
+def fun_l0_n133()
+ fun_l1_n919
+end
+
+def fun_l0_n134()
+ fun_l1_n665
+end
+
+def fun_l0_n135()
+ fun_l1_n442
+end
+
+def fun_l0_n136()
+ fun_l1_n84
+end
+
+def fun_l0_n137()
+ fun_l1_n74
+end
+
+def fun_l0_n138()
+ fun_l1_n606
+end
+
+def fun_l0_n139()
+ fun_l1_n655
+end
+
+def fun_l0_n140()
+ fun_l1_n130
+end
+
+def fun_l0_n141()
+ fun_l1_n626
+end
+
+def fun_l0_n142()
+ fun_l1_n605
+end
+
+def fun_l0_n143()
+ fun_l1_n420
+end
+
+def fun_l0_n144()
+ fun_l1_n100
+end
+
+def fun_l0_n145()
+ fun_l1_n961
+end
+
+def fun_l0_n146()
+ fun_l1_n721
+end
+
+def fun_l0_n147()
+ fun_l1_n453
+end
+
+def fun_l0_n148()
+ fun_l1_n737
+end
+
+def fun_l0_n149()
+ fun_l1_n230
+end
+
+def fun_l0_n150()
+ fun_l1_n881
+end
+
+def fun_l0_n151()
+ fun_l1_n471
+end
+
+def fun_l0_n152()
+ fun_l1_n72
+end
+
+def fun_l0_n153()
+ fun_l1_n221
+end
+
+def fun_l0_n154()
+ fun_l1_n504
+end
+
+def fun_l0_n155()
+ fun_l1_n222
+end
+
+def fun_l0_n156()
+ fun_l1_n348
+end
+
+def fun_l0_n157()
+ fun_l1_n738
+end
+
+def fun_l0_n158()
+ fun_l1_n588
+end
+
+def fun_l0_n159()
+ fun_l1_n64
+end
+
+def fun_l0_n160()
+ fun_l1_n829
+end
+
+def fun_l0_n161()
+ fun_l1_n265
+end
+
+def fun_l0_n162()
+ fun_l1_n471
+end
+
+def fun_l0_n163()
+ fun_l1_n304
+end
+
+def fun_l0_n164()
+ fun_l1_n518
+end
+
+def fun_l0_n165()
+ fun_l1_n89
+end
+
+def fun_l0_n166()
+ fun_l1_n728
+end
+
+def fun_l0_n167()
+ fun_l1_n292
+end
+
+def fun_l0_n168()
+ fun_l1_n142
+end
+
+def fun_l0_n169()
+ fun_l1_n374
+end
+
+def fun_l0_n170()
+ fun_l1_n371
+end
+
+def fun_l0_n171()
+ fun_l1_n904
+end
+
+def fun_l0_n172()
+ fun_l1_n519
+end
+
+def fun_l0_n173()
+ fun_l1_n239
+end
+
+def fun_l0_n174()
+ fun_l1_n664
+end
+
+def fun_l0_n175()
+ fun_l1_n701
+end
+
+def fun_l0_n176()
+ fun_l1_n586
+end
+
+def fun_l0_n177()
+ fun_l1_n78
+end
+
+def fun_l0_n178()
+ fun_l1_n663
+end
+
+def fun_l0_n179()
+ fun_l1_n46
+end
+
+def fun_l0_n180()
+ fun_l1_n273
+end
+
+def fun_l0_n181()
+ fun_l1_n250
+end
+
+def fun_l0_n182()
+ fun_l1_n362
+end
+
+def fun_l0_n183()
+ fun_l1_n69
+end
+
+def fun_l0_n184()
+ fun_l1_n874
+end
+
+def fun_l0_n185()
+ fun_l1_n135
+end
+
+def fun_l0_n186()
+ fun_l1_n634
+end
+
+def fun_l0_n187()
+ fun_l1_n885
+end
+
+def fun_l0_n188()
+ fun_l1_n589
+end
+
+def fun_l0_n189()
+ fun_l1_n21
+end
+
+def fun_l0_n190()
+ fun_l1_n962
+end
+
+def fun_l0_n191()
+ fun_l1_n267
+end
+
+def fun_l0_n192()
+ fun_l1_n569
+end
+
+def fun_l0_n193()
+ fun_l1_n921
+end
+
+def fun_l0_n194()
+ fun_l1_n535
+end
+
+def fun_l0_n195()
+ fun_l1_n362
+end
+
+def fun_l0_n196()
+ fun_l1_n862
+end
+
+def fun_l0_n197()
+ fun_l1_n565
+end
+
+def fun_l0_n198()
+ fun_l1_n779
+end
+
+def fun_l0_n199()
+ fun_l1_n848
+end
+
+def fun_l0_n200()
+ fun_l1_n755
+end
+
+def fun_l0_n201()
+ fun_l1_n493
+end
+
+def fun_l0_n202()
+ fun_l1_n574
+end
+
+def fun_l0_n203()
+ fun_l1_n172
+end
+
+def fun_l0_n204()
+ fun_l1_n388
+end
+
+def fun_l0_n205()
+ fun_l1_n67
+end
+
+def fun_l0_n206()
+ fun_l1_n449
+end
+
+def fun_l0_n207()
+ fun_l1_n883
+end
+
+def fun_l0_n208()
+ fun_l1_n749
+end
+
+def fun_l0_n209()
+ fun_l1_n425
+end
+
+def fun_l0_n210()
+ fun_l1_n848
+end
+
+def fun_l0_n211()
+ fun_l1_n320
+end
+
+def fun_l0_n212()
+ fun_l1_n122
+end
+
+def fun_l0_n213()
+ fun_l1_n878
+end
+
+def fun_l0_n214()
+ fun_l1_n763
+end
+
+def fun_l0_n215()
+ fun_l1_n70
+end
+
+def fun_l0_n216()
+ fun_l1_n494
+end
+
+def fun_l0_n217()
+ fun_l1_n13
+end
+
+def fun_l0_n218()
+ fun_l1_n907
+end
+
+def fun_l0_n219()
+ fun_l1_n775
+end
+
+def fun_l0_n220()
+ fun_l1_n633
+end
+
+def fun_l0_n221()
+ fun_l1_n371
+end
+
+def fun_l0_n222()
+ fun_l1_n691
+end
+
+def fun_l0_n223()
+ fun_l1_n994
+end
+
+def fun_l0_n224()
+ fun_l1_n268
+end
+
+def fun_l0_n225()
+ fun_l1_n52
+end
+
+def fun_l0_n226()
+ fun_l1_n291
+end
+
+def fun_l0_n227()
+ fun_l1_n903
+end
+
+def fun_l0_n228()
+ fun_l1_n369
+end
+
+def fun_l0_n229()
+ fun_l1_n232
+end
+
+def fun_l0_n230()
+ fun_l1_n554
+end
+
+def fun_l0_n231()
+ fun_l1_n479
+end
+
+def fun_l0_n232()
+ fun_l1_n838
+end
+
+def fun_l0_n233()
+ fun_l1_n316
+end
+
+def fun_l0_n234()
+ fun_l1_n685
+end
+
+def fun_l0_n235()
+ fun_l1_n95
+end
+
+def fun_l0_n236()
+ fun_l1_n629
+end
+
+def fun_l0_n237()
+ fun_l1_n218
+end
+
+def fun_l0_n238()
+ fun_l1_n406
+end
+
+def fun_l0_n239()
+ fun_l1_n187
+end
+
+def fun_l0_n240()
+ fun_l1_n905
+end
+
+def fun_l0_n241()
+ fun_l1_n262
+end
+
+def fun_l0_n242()
+ fun_l1_n314
+end
+
+def fun_l0_n243()
+ fun_l1_n669
+end
+
+def fun_l0_n244()
+ fun_l1_n112
+end
+
+def fun_l0_n245()
+ fun_l1_n744
+end
+
+def fun_l0_n246()
+ fun_l1_n637
+end
+
+def fun_l0_n247()
+ fun_l1_n409
+end
+
+def fun_l0_n248()
+ fun_l1_n706
+end
+
+def fun_l0_n249()
+ fun_l1_n150
+end
+
+def fun_l0_n250()
+ fun_l1_n863
+end
+
+def fun_l0_n251()
+ fun_l1_n364
+end
+
+def fun_l0_n252()
+ fun_l1_n989
+end
+
+def fun_l0_n253()
+ fun_l1_n565
+end
+
+def fun_l0_n254()
+ fun_l1_n701
+end
+
+def fun_l0_n255()
+ fun_l1_n48
+end
+
+def fun_l0_n256()
+ fun_l1_n278
+end
+
+def fun_l0_n257()
+ fun_l1_n816
+end
+
+def fun_l0_n258()
+ fun_l1_n981
+end
+
+def fun_l0_n259()
+ fun_l1_n556
+end
+
+def fun_l0_n260()
+ fun_l1_n887
+end
+
+def fun_l0_n261()
+ fun_l1_n193
+end
+
+def fun_l0_n262()
+ fun_l1_n690
+end
+
+def fun_l0_n263()
+ fun_l1_n144
+end
+
+def fun_l0_n264()
+ fun_l1_n577
+end
+
+def fun_l0_n265()
+ fun_l1_n949
+end
+
+def fun_l0_n266()
+ fun_l1_n320
+end
+
+def fun_l0_n267()
+ fun_l1_n857
+end
+
+def fun_l0_n268()
+ fun_l1_n676
+end
+
+def fun_l0_n269()
+ fun_l1_n683
+end
+
+def fun_l0_n270()
+ fun_l1_n303
+end
+
+def fun_l0_n271()
+ fun_l1_n847
+end
+
+def fun_l0_n272()
+ fun_l1_n588
+end
+
+def fun_l0_n273()
+ fun_l1_n456
+end
+
+def fun_l0_n274()
+ fun_l1_n355
+end
+
+def fun_l0_n275()
+ fun_l1_n183
+end
+
+def fun_l0_n276()
+ fun_l1_n271
+end
+
+def fun_l0_n277()
+ fun_l1_n746
+end
+
+def fun_l0_n278()
+ fun_l1_n885
+end
+
+def fun_l0_n279()
+ fun_l1_n951
+end
+
+def fun_l0_n280()
+ fun_l1_n935
+end
+
+def fun_l0_n281()
+ fun_l1_n445
+end
+
+def fun_l0_n282()
+ fun_l1_n2
+end
+
+def fun_l0_n283()
+ fun_l1_n52
+end
+
+def fun_l0_n284()
+ fun_l1_n208
+end
+
+def fun_l0_n285()
+ fun_l1_n27
+end
+
+def fun_l0_n286()
+ fun_l1_n657
+end
+
+def fun_l0_n287()
+ fun_l1_n373
+end
+
+def fun_l0_n288()
+ fun_l1_n439
+end
+
+def fun_l0_n289()
+ fun_l1_n974
+end
+
+def fun_l0_n290()
+ fun_l1_n834
+end
+
+def fun_l0_n291()
+ fun_l1_n673
+end
+
+def fun_l0_n292()
+ fun_l1_n978
+end
+
+def fun_l0_n293()
+ fun_l1_n123
+end
+
+def fun_l0_n294()
+ fun_l1_n644
+end
+
+def fun_l0_n295()
+ fun_l1_n715
+end
+
+def fun_l0_n296()
+ fun_l1_n912
+end
+
+def fun_l0_n297()
+ fun_l1_n954
+end
+
+def fun_l0_n298()
+ fun_l1_n519
+end
+
+def fun_l0_n299()
+ fun_l1_n726
+end
+
+def fun_l0_n300()
+ fun_l1_n417
+end
+
+def fun_l0_n301()
+ fun_l1_n199
+end
+
+def fun_l0_n302()
+ fun_l1_n157
+end
+
+def fun_l0_n303()
+ fun_l1_n432
+end
+
+def fun_l0_n304()
+ fun_l1_n59
+end
+
+def fun_l0_n305()
+ fun_l1_n604
+end
+
+def fun_l0_n306()
+ fun_l1_n301
+end
+
+def fun_l0_n307()
+ fun_l1_n558
+end
+
+def fun_l0_n308()
+ fun_l1_n443
+end
+
+def fun_l0_n309()
+ fun_l1_n873
+end
+
+def fun_l0_n310()
+ fun_l1_n415
+end
+
+def fun_l0_n311()
+ fun_l1_n907
+end
+
+def fun_l0_n312()
+ fun_l1_n159
+end
+
+def fun_l0_n313()
+ fun_l1_n695
+end
+
+def fun_l0_n314()
+ fun_l1_n679
+end
+
+def fun_l0_n315()
+ fun_l1_n788
+end
+
+def fun_l0_n316()
+ fun_l1_n510
+end
+
+def fun_l0_n317()
+ fun_l1_n997
+end
+
+def fun_l0_n318()
+ fun_l1_n821
+end
+
+def fun_l0_n319()
+ fun_l1_n554
+end
+
+def fun_l0_n320()
+ fun_l1_n982
+end
+
+def fun_l0_n321()
+ fun_l1_n996
+end
+
+def fun_l0_n322()
+ fun_l1_n73
+end
+
+def fun_l0_n323()
+ fun_l1_n951
+end
+
+def fun_l0_n324()
+ fun_l1_n597
+end
+
+def fun_l0_n325()
+ fun_l1_n502
+end
+
+def fun_l0_n326()
+ fun_l1_n150
+end
+
+def fun_l0_n327()
+ fun_l1_n979
+end
+
+def fun_l0_n328()
+ fun_l1_n81
+end
+
+def fun_l0_n329()
+ fun_l1_n87
+end
+
+def fun_l0_n330()
+ fun_l1_n726
+end
+
+def fun_l0_n331()
+ fun_l1_n159
+end
+
+def fun_l0_n332()
+ fun_l1_n799
+end
+
+def fun_l0_n333()
+ fun_l1_n202
+end
+
+def fun_l0_n334()
+ fun_l1_n904
+end
+
+def fun_l0_n335()
+ fun_l1_n14
+end
+
+def fun_l0_n336()
+ fun_l1_n136
+end
+
+def fun_l0_n337()
+ fun_l1_n865
+end
+
+def fun_l0_n338()
+ fun_l1_n307
+end
+
+def fun_l0_n339()
+ fun_l1_n827
+end
+
+def fun_l0_n340()
+ fun_l1_n518
+end
+
+def fun_l0_n341()
+ fun_l1_n416
+end
+
+def fun_l0_n342()
+ fun_l1_n277
+end
+
+def fun_l0_n343()
+ fun_l1_n609
+end
+
+def fun_l0_n344()
+ fun_l1_n328
+end
+
+def fun_l0_n345()
+ fun_l1_n941
+end
+
+def fun_l0_n346()
+ fun_l1_n707
+end
+
+def fun_l0_n347()
+ fun_l1_n452
+end
+
+def fun_l0_n348()
+ fun_l1_n874
+end
+
+def fun_l0_n349()
+ fun_l1_n117
+end
+
+def fun_l0_n350()
+ fun_l1_n739
+end
+
+def fun_l0_n351()
+ fun_l1_n202
+end
+
+def fun_l0_n352()
+ fun_l1_n80
+end
+
+def fun_l0_n353()
+ fun_l1_n373
+end
+
+def fun_l0_n354()
+ fun_l1_n747
+end
+
+def fun_l0_n355()
+ fun_l1_n949
+end
+
+def fun_l0_n356()
+ fun_l1_n901
+end
+
+def fun_l0_n357()
+ fun_l1_n512
+end
+
+def fun_l0_n358()
+ fun_l1_n528
+end
+
+def fun_l0_n359()
+ fun_l1_n895
+end
+
+def fun_l0_n360()
+ fun_l1_n683
+end
+
+def fun_l0_n361()
+ fun_l1_n80
+end
+
+def fun_l0_n362()
+ fun_l1_n718
+end
+
+def fun_l0_n363()
+ fun_l1_n388
+end
+
+def fun_l0_n364()
+ fun_l1_n701
+end
+
+def fun_l0_n365()
+ fun_l1_n146
+end
+
+def fun_l0_n366()
+ fun_l1_n143
+end
+
+def fun_l0_n367()
+ fun_l1_n872
+end
+
+def fun_l0_n368()
+ fun_l1_n818
+end
+
+def fun_l0_n369()
+ fun_l1_n821
+end
+
+def fun_l0_n370()
+ fun_l1_n180
+end
+
+def fun_l0_n371()
+ fun_l1_n346
+end
+
+def fun_l0_n372()
+ fun_l1_n524
+end
+
+def fun_l0_n373()
+ fun_l1_n451
+end
+
+def fun_l0_n374()
+ fun_l1_n592
+end
+
+def fun_l0_n375()
+ fun_l1_n215
+end
+
+def fun_l0_n376()
+ fun_l1_n737
+end
+
+def fun_l0_n377()
+ fun_l1_n631
+end
+
+def fun_l0_n378()
+ fun_l1_n385
+end
+
+def fun_l0_n379()
+ fun_l1_n593
+end
+
+def fun_l0_n380()
+ fun_l1_n484
+end
+
+def fun_l0_n381()
+ fun_l1_n979
+end
+
+def fun_l0_n382()
+ fun_l1_n491
+end
+
+def fun_l0_n383()
+ fun_l1_n632
+end
+
+def fun_l0_n384()
+ fun_l1_n939
+end
+
+def fun_l0_n385()
+ fun_l1_n932
+end
+
+def fun_l0_n386()
+ fun_l1_n816
+end
+
+def fun_l0_n387()
+ fun_l1_n308
+end
+
+def fun_l0_n388()
+ fun_l1_n525
+end
+
+def fun_l0_n389()
+ fun_l1_n160
+end
+
+def fun_l0_n390()
+ fun_l1_n313
+end
+
+def fun_l0_n391()
+ fun_l1_n816
+end
+
+def fun_l0_n392()
+ fun_l1_n641
+end
+
+def fun_l0_n393()
+ fun_l1_n319
+end
+
+def fun_l0_n394()
+ fun_l1_n559
+end
+
+def fun_l0_n395()
+ fun_l1_n520
+end
+
+def fun_l0_n396()
+ fun_l1_n277
+end
+
+def fun_l0_n397()
+ fun_l1_n410
+end
+
+def fun_l0_n398()
+ fun_l1_n956
+end
+
+def fun_l0_n399()
+ fun_l1_n101
+end
+
+def fun_l0_n400()
+ fun_l1_n33
+end
+
+def fun_l0_n401()
+ fun_l1_n554
+end
+
+def fun_l0_n402()
+ fun_l1_n821
+end
+
+def fun_l0_n403()
+ fun_l1_n230
+end
+
+def fun_l0_n404()
+ fun_l1_n185
+end
+
+def fun_l0_n405()
+ fun_l1_n430
+end
+
+def fun_l0_n406()
+ fun_l1_n94
+end
+
+def fun_l0_n407()
+ fun_l1_n776
+end
+
+def fun_l0_n408()
+ fun_l1_n981
+end
+
+def fun_l0_n409()
+ fun_l1_n414
+end
+
+def fun_l0_n410()
+ fun_l1_n421
+end
+
+def fun_l0_n411()
+ fun_l1_n343
+end
+
+def fun_l0_n412()
+ fun_l1_n484
+end
+
+def fun_l0_n413()
+ fun_l1_n818
+end
+
+def fun_l0_n414()
+ fun_l1_n860
+end
+
+def fun_l0_n415()
+ fun_l1_n70
+end
+
+def fun_l0_n416()
+ fun_l1_n643
+end
+
+def fun_l0_n417()
+ fun_l1_n382
+end
+
+def fun_l0_n418()
+ fun_l1_n174
+end
+
+def fun_l0_n419()
+ fun_l1_n500
+end
+
+def fun_l0_n420()
+ fun_l1_n904
+end
+
+def fun_l0_n421()
+ fun_l1_n971
+end
+
+def fun_l0_n422()
+ fun_l1_n438
+end
+
+def fun_l0_n423()
+ fun_l1_n524
+end
+
+def fun_l0_n424()
+ fun_l1_n537
+end
+
+def fun_l0_n425()
+ fun_l1_n564
+end
+
+def fun_l0_n426()
+ fun_l1_n378
+end
+
+def fun_l0_n427()
+ fun_l1_n603
+end
+
+def fun_l0_n428()
+ fun_l1_n442
+end
+
+def fun_l0_n429()
+ fun_l1_n687
+end
+
+def fun_l0_n430()
+ fun_l1_n682
+end
+
+def fun_l0_n431()
+ fun_l1_n664
+end
+
+def fun_l0_n432()
+ fun_l1_n319
+end
+
+def fun_l0_n433()
+ fun_l1_n671
+end
+
+def fun_l0_n434()
+ fun_l1_n211
+end
+
+def fun_l0_n435()
+ fun_l1_n65
+end
+
+def fun_l0_n436()
+ fun_l1_n2
+end
+
+def fun_l0_n437()
+ fun_l1_n36
+end
+
+def fun_l0_n438()
+ fun_l1_n270
+end
+
+def fun_l0_n439()
+ fun_l1_n793
+end
+
+def fun_l0_n440()
+ fun_l1_n312
+end
+
+def fun_l0_n441()
+ fun_l1_n134
+end
+
+def fun_l0_n442()
+ fun_l1_n246
+end
+
+def fun_l0_n443()
+ fun_l1_n498
+end
+
+def fun_l0_n444()
+ fun_l1_n606
+end
+
+def fun_l0_n445()
+ fun_l1_n986
+end
+
+def fun_l0_n446()
+ fun_l1_n659
+end
+
+def fun_l0_n447()
+ fun_l1_n823
+end
+
+def fun_l0_n448()
+ fun_l1_n635
+end
+
+def fun_l0_n449()
+ fun_l1_n388
+end
+
+def fun_l0_n450()
+ fun_l1_n474
+end
+
+def fun_l0_n451()
+ fun_l1_n742
+end
+
+def fun_l0_n452()
+ fun_l1_n605
+end
+
+def fun_l0_n453()
+ fun_l1_n0
+end
+
+def fun_l0_n454()
+ fun_l1_n691
+end
+
+def fun_l0_n455()
+ fun_l1_n791
+end
+
+def fun_l0_n456()
+ fun_l1_n363
+end
+
+def fun_l0_n457()
+ fun_l1_n370
+end
+
+def fun_l0_n458()
+ fun_l1_n168
+end
+
+def fun_l0_n459()
+ fun_l1_n626
+end
+
+def fun_l0_n460()
+ fun_l1_n139
+end
+
+def fun_l0_n461()
+ fun_l1_n708
+end
+
+def fun_l0_n462()
+ fun_l1_n77
+end
+
+def fun_l0_n463()
+ fun_l1_n27
+end
+
+def fun_l0_n464()
+ fun_l1_n706
+end
+
+def fun_l0_n465()
+ fun_l1_n29
+end
+
+def fun_l0_n466()
+ fun_l1_n470
+end
+
+def fun_l0_n467()
+ fun_l1_n606
+end
+
+def fun_l0_n468()
+ fun_l1_n458
+end
+
+def fun_l0_n469()
+ fun_l1_n465
+end
+
+def fun_l0_n470()
+ fun_l1_n23
+end
+
+def fun_l0_n471()
+ fun_l1_n364
+end
+
+def fun_l0_n472()
+ fun_l1_n606
+end
+
+def fun_l0_n473()
+ fun_l1_n109
+end
+
+def fun_l0_n474()
+ fun_l1_n904
+end
+
+def fun_l0_n475()
+ fun_l1_n923
+end
+
+def fun_l0_n476()
+ fun_l1_n19
+end
+
+def fun_l0_n477()
+ fun_l1_n871
+end
+
+def fun_l0_n478()
+ fun_l1_n422
+end
+
+def fun_l0_n479()
+ fun_l1_n72
+end
+
+def fun_l0_n480()
+ fun_l1_n528
+end
+
+def fun_l0_n481()
+ fun_l1_n181
+end
+
+def fun_l0_n482()
+ fun_l1_n33
+end
+
+def fun_l0_n483()
+ fun_l1_n951
+end
+
+def fun_l0_n484()
+ fun_l1_n747
+end
+
+def fun_l0_n485()
+ fun_l1_n200
+end
+
+def fun_l0_n486()
+ fun_l1_n474
+end
+
+def fun_l0_n487()
+ fun_l1_n126
+end
+
+def fun_l0_n488()
+ fun_l1_n757
+end
+
+def fun_l0_n489()
+ fun_l1_n101
+end
+
+def fun_l0_n490()
+ fun_l1_n925
+end
+
+def fun_l0_n491()
+ fun_l1_n791
+end
+
+def fun_l0_n492()
+ fun_l1_n404
+end
+
+def fun_l0_n493()
+ fun_l1_n841
+end
+
+def fun_l0_n494()
+ fun_l1_n774
+end
+
+def fun_l0_n495()
+ fun_l1_n230
+end
+
+def fun_l0_n496()
+ fun_l1_n796
+end
+
+def fun_l0_n497()
+ fun_l1_n270
+end
+
+def fun_l0_n498()
+ fun_l1_n795
+end
+
+def fun_l0_n499()
+ fun_l1_n628
+end
+
+def fun_l0_n500()
+ fun_l1_n865
+end
+
+def fun_l0_n501()
+ fun_l1_n105
+end
+
+def fun_l0_n502()
+ fun_l1_n538
+end
+
+def fun_l0_n503()
+ fun_l1_n769
+end
+
+def fun_l0_n504()
+ fun_l1_n714
+end
+
+def fun_l0_n505()
+ fun_l1_n889
+end
+
+def fun_l0_n506()
+ fun_l1_n191
+end
+
+def fun_l0_n507()
+ fun_l1_n966
+end
+
+def fun_l0_n508()
+ fun_l1_n196
+end
+
+def fun_l0_n509()
+ fun_l1_n878
+end
+
+def fun_l0_n510()
+ fun_l1_n487
+end
+
+def fun_l0_n511()
+ fun_l1_n242
+end
+
+def fun_l0_n512()
+ fun_l1_n740
+end
+
+def fun_l0_n513()
+ fun_l1_n938
+end
+
+def fun_l0_n514()
+ fun_l1_n485
+end
+
+def fun_l0_n515()
+ fun_l1_n380
+end
+
+def fun_l0_n516()
+ fun_l1_n936
+end
+
+def fun_l0_n517()
+ fun_l1_n237
+end
+
+def fun_l0_n518()
+ fun_l1_n79
+end
+
+def fun_l0_n519()
+ fun_l1_n501
+end
+
+def fun_l0_n520()
+ fun_l1_n966
+end
+
+def fun_l0_n521()
+ fun_l1_n741
+end
+
+def fun_l0_n522()
+ fun_l1_n170
+end
+
+def fun_l0_n523()
+ fun_l1_n183
+end
+
+def fun_l0_n524()
+ fun_l1_n556
+end
+
+def fun_l0_n525()
+ fun_l1_n865
+end
+
+def fun_l0_n526()
+ fun_l1_n884
+end
+
+def fun_l0_n527()
+ fun_l1_n725
+end
+
+def fun_l0_n528()
+ fun_l1_n205
+end
+
+def fun_l0_n529()
+ fun_l1_n72
+end
+
+def fun_l0_n530()
+ fun_l1_n432
+end
+
+def fun_l0_n531()
+ fun_l1_n90
+end
+
+def fun_l0_n532()
+ fun_l1_n189
+end
+
+def fun_l0_n533()
+ fun_l1_n395
+end
+
+def fun_l0_n534()
+ fun_l1_n201
+end
+
+def fun_l0_n535()
+ fun_l1_n534
+end
+
+def fun_l0_n536()
+ fun_l1_n748
+end
+
+def fun_l0_n537()
+ fun_l1_n439
+end
+
+def fun_l0_n538()
+ fun_l1_n495
+end
+
+def fun_l0_n539()
+ fun_l1_n904
+end
+
+def fun_l0_n540()
+ fun_l1_n525
+end
+
+def fun_l0_n541()
+ fun_l1_n924
+end
+
+def fun_l0_n542()
+ fun_l1_n549
+end
+
+def fun_l0_n543()
+ fun_l1_n2
+end
+
+def fun_l0_n544()
+ fun_l1_n257
+end
+
+def fun_l0_n545()
+ fun_l1_n921
+end
+
+def fun_l0_n546()
+ fun_l1_n82
+end
+
+def fun_l0_n547()
+ fun_l1_n384
+end
+
+def fun_l0_n548()
+ fun_l1_n219
+end
+
+def fun_l0_n549()
+ fun_l1_n379
+end
+
+def fun_l0_n550()
+ fun_l1_n488
+end
+
+def fun_l0_n551()
+ fun_l1_n4
+end
+
+def fun_l0_n552()
+ fun_l1_n150
+end
+
+def fun_l0_n553()
+ fun_l1_n168
+end
+
+def fun_l0_n554()
+ fun_l1_n773
+end
+
+def fun_l0_n555()
+ fun_l1_n444
+end
+
+def fun_l0_n556()
+ fun_l1_n201
+end
+
+def fun_l0_n557()
+ fun_l1_n333
+end
+
+def fun_l0_n558()
+ fun_l1_n556
+end
+
+def fun_l0_n559()
+ fun_l1_n394
+end
+
+def fun_l0_n560()
+ fun_l1_n540
+end
+
+def fun_l0_n561()
+ fun_l1_n640
+end
+
+def fun_l0_n562()
+ fun_l1_n321
+end
+
+def fun_l0_n563()
+ fun_l1_n286
+end
+
+def fun_l0_n564()
+ fun_l1_n320
+end
+
+def fun_l0_n565()
+ fun_l1_n2
+end
+
+def fun_l0_n566()
+ fun_l1_n50
+end
+
+def fun_l0_n567()
+ fun_l1_n269
+end
+
+def fun_l0_n568()
+ fun_l1_n412
+end
+
+def fun_l0_n569()
+ fun_l1_n984
+end
+
+def fun_l0_n570()
+ fun_l1_n307
+end
+
+def fun_l0_n571()
+ fun_l1_n954
+end
+
+def fun_l0_n572()
+ fun_l1_n728
+end
+
+def fun_l0_n573()
+ fun_l1_n227
+end
+
+def fun_l0_n574()
+ fun_l1_n917
+end
+
+def fun_l0_n575()
+ fun_l1_n974
+end
+
+def fun_l0_n576()
+ fun_l1_n995
+end
+
+def fun_l0_n577()
+ fun_l1_n593
+end
+
+def fun_l0_n578()
+ fun_l1_n704
+end
+
+def fun_l0_n579()
+ fun_l1_n142
+end
+
+def fun_l0_n580()
+ fun_l1_n585
+end
+
+def fun_l0_n581()
+ fun_l1_n634
+end
+
+def fun_l0_n582()
+ fun_l1_n888
+end
+
+def fun_l0_n583()
+ fun_l1_n873
+end
+
+def fun_l0_n584()
+ fun_l1_n674
+end
+
+def fun_l0_n585()
+ fun_l1_n657
+end
+
+def fun_l0_n586()
+ fun_l1_n248
+end
+
+def fun_l0_n587()
+ fun_l1_n478
+end
+
+def fun_l0_n588()
+ fun_l1_n263
+end
+
+def fun_l0_n589()
+ fun_l1_n908
+end
+
+def fun_l0_n590()
+ fun_l1_n741
+end
+
+def fun_l0_n591()
+ fun_l1_n299
+end
+
+def fun_l0_n592()
+ fun_l1_n763
+end
+
+def fun_l0_n593()
+ fun_l1_n746
+end
+
+def fun_l0_n594()
+ fun_l1_n367
+end
+
+def fun_l0_n595()
+ fun_l1_n394
+end
+
+def fun_l0_n596()
+ fun_l1_n304
+end
+
+def fun_l0_n597()
+ fun_l1_n939
+end
+
+def fun_l0_n598()
+ fun_l1_n392
+end
+
+def fun_l0_n599()
+ fun_l1_n758
+end
+
+def fun_l0_n600()
+ fun_l1_n133
+end
+
+def fun_l0_n601()
+ fun_l1_n212
+end
+
+def fun_l0_n602()
+ fun_l1_n719
+end
+
+def fun_l0_n603()
+ fun_l1_n952
+end
+
+def fun_l0_n604()
+ fun_l1_n818
+end
+
+def fun_l0_n605()
+ fun_l1_n216
+end
+
+def fun_l0_n606()
+ fun_l1_n438
+end
+
+def fun_l0_n607()
+ fun_l1_n315
+end
+
+def fun_l0_n608()
+ fun_l1_n450
+end
+
+def fun_l0_n609()
+ fun_l1_n420
+end
+
+def fun_l0_n610()
+ fun_l1_n917
+end
+
+def fun_l0_n611()
+ fun_l1_n921
+end
+
+def fun_l0_n612()
+ fun_l1_n596
+end
+
+def fun_l0_n613()
+ fun_l1_n253
+end
+
+def fun_l0_n614()
+ fun_l1_n395
+end
+
+def fun_l0_n615()
+ fun_l1_n120
+end
+
+def fun_l0_n616()
+ fun_l1_n742
+end
+
+def fun_l0_n617()
+ fun_l1_n489
+end
+
+def fun_l0_n618()
+ fun_l1_n338
+end
+
+def fun_l0_n619()
+ fun_l1_n351
+end
+
+def fun_l0_n620()
+ fun_l1_n384
+end
+
+def fun_l0_n621()
+ fun_l1_n581
+end
+
+def fun_l0_n622()
+ fun_l1_n667
+end
+
+def fun_l0_n623()
+ fun_l1_n956
+end
+
+def fun_l0_n624()
+ fun_l1_n156
+end
+
+def fun_l0_n625()
+ fun_l1_n909
+end
+
+def fun_l0_n626()
+ fun_l1_n548
+end
+
+def fun_l0_n627()
+ fun_l1_n293
+end
+
+def fun_l0_n628()
+ fun_l1_n997
+end
+
+def fun_l0_n629()
+ fun_l1_n950
+end
+
+def fun_l0_n630()
+ fun_l1_n761
+end
+
+def fun_l0_n631()
+ fun_l1_n72
+end
+
+def fun_l0_n632()
+ fun_l1_n213
+end
+
+def fun_l0_n633()
+ fun_l1_n746
+end
+
+def fun_l0_n634()
+ fun_l1_n327
+end
+
+def fun_l0_n635()
+ fun_l1_n166
+end
+
+def fun_l0_n636()
+ fun_l1_n749
+end
+
+def fun_l0_n637()
+ fun_l1_n196
+end
+
+def fun_l0_n638()
+ fun_l1_n786
+end
+
+def fun_l0_n639()
+ fun_l1_n613
+end
+
+def fun_l0_n640()
+ fun_l1_n903
+end
+
+def fun_l0_n641()
+ fun_l1_n836
+end
+
+def fun_l0_n642()
+ fun_l1_n687
+end
+
+def fun_l0_n643()
+ fun_l1_n533
+end
+
+def fun_l0_n644()
+ fun_l1_n544
+end
+
+def fun_l0_n645()
+ fun_l1_n637
+end
+
+def fun_l0_n646()
+ fun_l1_n859
+end
+
+def fun_l0_n647()
+ fun_l1_n917
+end
+
+def fun_l0_n648()
+ fun_l1_n119
+end
+
+def fun_l0_n649()
+ fun_l1_n327
+end
+
+def fun_l0_n650()
+ fun_l1_n759
+end
+
+def fun_l0_n651()
+ fun_l1_n169
+end
+
+def fun_l0_n652()
+ fun_l1_n497
+end
+
+def fun_l0_n653()
+ fun_l1_n441
+end
+
+def fun_l0_n654()
+ fun_l1_n151
+end
+
+def fun_l0_n655()
+ fun_l1_n553
+end
+
+def fun_l0_n656()
+ fun_l1_n441
+end
+
+def fun_l0_n657()
+ fun_l1_n390
+end
+
+def fun_l0_n658()
+ fun_l1_n615
+end
+
+def fun_l0_n659()
+ fun_l1_n578
+end
+
+def fun_l0_n660()
+ fun_l1_n873
+end
+
+def fun_l0_n661()
+ fun_l1_n608
+end
+
+def fun_l0_n662()
+ fun_l1_n446
+end
+
+def fun_l0_n663()
+ fun_l1_n647
+end
+
+def fun_l0_n664()
+ fun_l1_n601
+end
+
+def fun_l0_n665()
+ fun_l1_n945
+end
+
+def fun_l0_n666()
+ fun_l1_n172
+end
+
+def fun_l0_n667()
+ fun_l1_n547
+end
+
+def fun_l0_n668()
+ fun_l1_n977
+end
+
+def fun_l0_n669()
+ fun_l1_n419
+end
+
+def fun_l0_n670()
+ fun_l1_n626
+end
+
+def fun_l0_n671()
+ fun_l1_n345
+end
+
+def fun_l0_n672()
+ fun_l1_n899
+end
+
+def fun_l0_n673()
+ fun_l1_n442
+end
+
+def fun_l0_n674()
+ fun_l1_n296
+end
+
+def fun_l0_n675()
+ fun_l1_n303
+end
+
+def fun_l0_n676()
+ fun_l1_n679
+end
+
+def fun_l0_n677()
+ fun_l1_n655
+end
+
+def fun_l0_n678()
+ fun_l1_n998
+end
+
+def fun_l0_n679()
+ fun_l1_n157
+end
+
+def fun_l0_n680()
+ fun_l1_n705
+end
+
+def fun_l0_n681()
+ fun_l1_n832
+end
+
+def fun_l0_n682()
+ fun_l1_n113
+end
+
+def fun_l0_n683()
+ fun_l1_n550
+end
+
+def fun_l0_n684()
+ fun_l1_n21
+end
+
+def fun_l0_n685()
+ fun_l1_n21
+end
+
+def fun_l0_n686()
+ fun_l1_n195
+end
+
+def fun_l0_n687()
+ fun_l1_n269
+end
+
+def fun_l0_n688()
+ fun_l1_n12
+end
+
+def fun_l0_n689()
+ fun_l1_n49
+end
+
+def fun_l0_n690()
+ fun_l1_n836
+end
+
+def fun_l0_n691()
+ fun_l1_n808
+end
+
+def fun_l0_n692()
+ fun_l1_n938
+end
+
+def fun_l0_n693()
+ fun_l1_n531
+end
+
+def fun_l0_n694()
+ fun_l1_n296
+end
+
+def fun_l0_n695()
+ fun_l1_n32
+end
+
+def fun_l0_n696()
+ fun_l1_n641
+end
+
+def fun_l0_n697()
+ fun_l1_n549
+end
+
+def fun_l0_n698()
+ fun_l1_n437
+end
+
+def fun_l0_n699()
+ fun_l1_n133
+end
+
+def fun_l0_n700()
+ fun_l1_n734
+end
+
+def fun_l0_n701()
+ fun_l1_n340
+end
+
+def fun_l0_n702()
+ fun_l1_n768
+end
+
+def fun_l0_n703()
+ fun_l1_n97
+end
+
+def fun_l0_n704()
+ fun_l1_n52
+end
+
+def fun_l0_n705()
+ fun_l1_n121
+end
+
+def fun_l0_n706()
+ fun_l1_n471
+end
+
+def fun_l0_n707()
+ fun_l1_n94
+end
+
+def fun_l0_n708()
+ fun_l1_n946
+end
+
+def fun_l0_n709()
+ fun_l1_n151
+end
+
+def fun_l0_n710()
+ fun_l1_n946
+end
+
+def fun_l0_n711()
+ fun_l1_n191
+end
+
+def fun_l0_n712()
+ fun_l1_n552
+end
+
+def fun_l0_n713()
+ fun_l1_n733
+end
+
+def fun_l0_n714()
+ fun_l1_n895
+end
+
+def fun_l0_n715()
+ fun_l1_n850
+end
+
+def fun_l0_n716()
+ fun_l1_n113
+end
+
+def fun_l0_n717()
+ fun_l1_n69
+end
+
+def fun_l0_n718()
+ fun_l1_n862
+end
+
+def fun_l0_n719()
+ fun_l1_n635
+end
+
+def fun_l0_n720()
+ fun_l1_n714
+end
+
+def fun_l0_n721()
+ fun_l1_n179
+end
+
+def fun_l0_n722()
+ fun_l1_n17
+end
+
+def fun_l0_n723()
+ fun_l1_n299
+end
+
+def fun_l0_n724()
+ fun_l1_n141
+end
+
+def fun_l0_n725()
+ fun_l1_n338
+end
+
+def fun_l0_n726()
+ fun_l1_n650
+end
+
+def fun_l0_n727()
+ fun_l1_n784
+end
+
+def fun_l0_n728()
+ fun_l1_n333
+end
+
+def fun_l0_n729()
+ fun_l1_n10
+end
+
+def fun_l0_n730()
+ fun_l1_n271
+end
+
+def fun_l0_n731()
+ fun_l1_n882
+end
+
+def fun_l0_n732()
+ fun_l1_n512
+end
+
+def fun_l0_n733()
+ fun_l1_n932
+end
+
+def fun_l0_n734()
+ fun_l1_n68
+end
+
+def fun_l0_n735()
+ fun_l1_n111
+end
+
+def fun_l0_n736()
+ fun_l1_n649
+end
+
+def fun_l0_n737()
+ fun_l1_n512
+end
+
+def fun_l0_n738()
+ fun_l1_n551
+end
+
+def fun_l0_n739()
+ fun_l1_n153
+end
+
+def fun_l0_n740()
+ fun_l1_n582
+end
+
+def fun_l0_n741()
+ fun_l1_n366
+end
+
+def fun_l0_n742()
+ fun_l1_n135
+end
+
+def fun_l0_n743()
+ fun_l1_n136
+end
+
+def fun_l0_n744()
+ fun_l1_n782
+end
+
+def fun_l0_n745()
+ fun_l1_n258
+end
+
+def fun_l0_n746()
+ fun_l1_n44
+end
+
+def fun_l0_n747()
+ fun_l1_n379
+end
+
+def fun_l0_n748()
+ fun_l1_n14
+end
+
+def fun_l0_n749()
+ fun_l1_n563
+end
+
+def fun_l0_n750()
+ fun_l1_n361
+end
+
+def fun_l0_n751()
+ fun_l1_n624
+end
+
+def fun_l0_n752()
+ fun_l1_n516
+end
+
+def fun_l0_n753()
+ fun_l1_n944
+end
+
+def fun_l0_n754()
+ fun_l1_n783
+end
+
+def fun_l0_n755()
+ fun_l1_n744
+end
+
+def fun_l0_n756()
+ fun_l1_n500
+end
+
+def fun_l0_n757()
+ fun_l1_n809
+end
+
+def fun_l0_n758()
+ fun_l1_n757
+end
+
+def fun_l0_n759()
+ fun_l1_n995
+end
+
+def fun_l0_n760()
+ fun_l1_n114
+end
+
+def fun_l0_n761()
+ fun_l1_n802
+end
+
+def fun_l0_n762()
+ fun_l1_n114
+end
+
+def fun_l0_n763()
+ fun_l1_n683
+end
+
+def fun_l0_n764()
+ fun_l1_n775
+end
+
+def fun_l0_n765()
+ fun_l1_n967
+end
+
+def fun_l0_n766()
+ fun_l1_n499
+end
+
+def fun_l0_n767()
+ fun_l1_n561
+end
+
+def fun_l0_n768()
+ fun_l1_n206
+end
+
+def fun_l0_n769()
+ fun_l1_n738
+end
+
+def fun_l0_n770()
+ fun_l1_n953
+end
+
+def fun_l0_n771()
+ fun_l1_n394
+end
+
+def fun_l0_n772()
+ fun_l1_n393
+end
+
+def fun_l0_n773()
+ fun_l1_n226
+end
+
+def fun_l0_n774()
+ fun_l1_n363
+end
+
+def fun_l0_n775()
+ fun_l1_n928
+end
+
+def fun_l0_n776()
+ fun_l1_n213
+end
+
+def fun_l0_n777()
+ fun_l1_n3
+end
+
+def fun_l0_n778()
+ fun_l1_n656
+end
+
+def fun_l0_n779()
+ fun_l1_n927
+end
+
+def fun_l0_n780()
+ fun_l1_n406
+end
+
+def fun_l0_n781()
+ fun_l1_n589
+end
+
+def fun_l0_n782()
+ fun_l1_n56
+end
+
+def fun_l0_n783()
+ fun_l1_n280
+end
+
+def fun_l0_n784()
+ fun_l1_n156
+end
+
+def fun_l0_n785()
+ fun_l1_n257
+end
+
+def fun_l0_n786()
+ fun_l1_n269
+end
+
+def fun_l0_n787()
+ fun_l1_n453
+end
+
+def fun_l0_n788()
+ fun_l1_n293
+end
+
+def fun_l0_n789()
+ fun_l1_n570
+end
+
+def fun_l0_n790()
+ fun_l1_n194
+end
+
+def fun_l0_n791()
+ fun_l1_n120
+end
+
+def fun_l0_n792()
+ fun_l1_n976
+end
+
+def fun_l0_n793()
+ fun_l1_n115
+end
+
+def fun_l0_n794()
+ fun_l1_n74
+end
+
+def fun_l0_n795()
+ fun_l1_n25
+end
+
+def fun_l0_n796()
+ fun_l1_n288
+end
+
+def fun_l0_n797()
+ fun_l1_n49
+end
+
+def fun_l0_n798()
+ fun_l1_n237
+end
+
+def fun_l0_n799()
+ fun_l1_n481
+end
+
+def fun_l0_n800()
+ fun_l1_n329
+end
+
+def fun_l0_n801()
+ fun_l1_n907
+end
+
+def fun_l0_n802()
+ fun_l1_n804
+end
+
+def fun_l0_n803()
+ fun_l1_n8
+end
+
+def fun_l0_n804()
+ fun_l1_n270
+end
+
+def fun_l0_n805()
+ fun_l1_n315
+end
+
+def fun_l0_n806()
+ fun_l1_n941
+end
+
+def fun_l0_n807()
+ fun_l1_n343
+end
+
+def fun_l0_n808()
+ fun_l1_n817
+end
+
+def fun_l0_n809()
+ fun_l1_n315
+end
+
+def fun_l0_n810()
+ fun_l1_n156
+end
+
+def fun_l0_n811()
+ fun_l1_n689
+end
+
+def fun_l0_n812()
+ fun_l1_n644
+end
+
+def fun_l0_n813()
+ fun_l1_n158
+end
+
+def fun_l0_n814()
+ fun_l1_n588
+end
+
+def fun_l0_n815()
+ fun_l1_n820
+end
+
+def fun_l0_n816()
+ fun_l1_n86
+end
+
+def fun_l0_n817()
+ fun_l1_n176
+end
+
+def fun_l0_n818()
+ fun_l1_n611
+end
+
+def fun_l0_n819()
+ fun_l1_n816
+end
+
+def fun_l0_n820()
+ fun_l1_n332
+end
+
+def fun_l0_n821()
+ fun_l1_n170
+end
+
+def fun_l0_n822()
+ fun_l1_n483
+end
+
+def fun_l0_n823()
+ fun_l1_n768
+end
+
+def fun_l0_n824()
+ fun_l1_n825
+end
+
+def fun_l0_n825()
+ fun_l1_n114
+end
+
+def fun_l0_n826()
+ fun_l1_n102
+end
+
+def fun_l0_n827()
+ fun_l1_n963
+end
+
+def fun_l0_n828()
+ fun_l1_n202
+end
+
+def fun_l0_n829()
+ fun_l1_n708
+end
+
+def fun_l0_n830()
+ fun_l1_n350
+end
+
+def fun_l0_n831()
+ fun_l1_n976
+end
+
+def fun_l0_n832()
+ fun_l1_n834
+end
+
+def fun_l0_n833()
+ fun_l1_n342
+end
+
+def fun_l0_n834()
+ fun_l1_n764
+end
+
+def fun_l0_n835()
+ fun_l1_n211
+end
+
+def fun_l0_n836()
+ fun_l1_n173
+end
+
+def fun_l0_n837()
+ fun_l1_n988
+end
+
+def fun_l0_n838()
+ fun_l1_n369
+end
+
+def fun_l0_n839()
+ fun_l1_n481
+end
+
+def fun_l0_n840()
+ fun_l1_n580
+end
+
+def fun_l0_n841()
+ fun_l1_n255
+end
+
+def fun_l0_n842()
+ fun_l1_n476
+end
+
+def fun_l0_n843()
+ fun_l1_n795
+end
+
+def fun_l0_n844()
+ fun_l1_n296
+end
+
+def fun_l0_n845()
+ fun_l1_n880
+end
+
+def fun_l0_n846()
+ fun_l1_n457
+end
+
+def fun_l0_n847()
+ fun_l1_n88
+end
+
+def fun_l0_n848()
+ fun_l1_n901
+end
+
+def fun_l0_n849()
+ fun_l1_n988
+end
+
+def fun_l0_n850()
+ fun_l1_n396
+end
+
+def fun_l0_n851()
+ fun_l1_n60
+end
+
+def fun_l0_n852()
+ fun_l1_n738
+end
+
+def fun_l0_n853()
+ fun_l1_n2
+end
+
+def fun_l0_n854()
+ fun_l1_n652
+end
+
+def fun_l0_n855()
+ fun_l1_n982
+end
+
+def fun_l0_n856()
+ fun_l1_n987
+end
+
+def fun_l0_n857()
+ fun_l1_n488
+end
+
+def fun_l0_n858()
+ fun_l1_n354
+end
+
+def fun_l0_n859()
+ fun_l1_n320
+end
+
+def fun_l0_n860()
+ fun_l1_n378
+end
+
+def fun_l0_n861()
+ fun_l1_n965
+end
+
+def fun_l0_n862()
+ fun_l1_n858
+end
+
+def fun_l0_n863()
+ fun_l1_n360
+end
+
+def fun_l0_n864()
+ fun_l1_n812
+end
+
+def fun_l0_n865()
+ fun_l1_n590
+end
+
+def fun_l0_n866()
+ fun_l1_n339
+end
+
+def fun_l0_n867()
+ fun_l1_n365
+end
+
+def fun_l0_n868()
+ fun_l1_n190
+end
+
+def fun_l0_n869()
+ fun_l1_n555
+end
+
+def fun_l0_n870()
+ fun_l1_n676
+end
+
+def fun_l0_n871()
+ fun_l1_n681
+end
+
+def fun_l0_n872()
+ fun_l1_n283
+end
+
+def fun_l0_n873()
+ fun_l1_n865
+end
+
+def fun_l0_n874()
+ fun_l1_n402
+end
+
+def fun_l0_n875()
+ fun_l1_n530
+end
+
+def fun_l0_n876()
+ fun_l1_n25
+end
+
+def fun_l0_n877()
+ fun_l1_n10
+end
+
+def fun_l0_n878()
+ fun_l1_n252
+end
+
+def fun_l0_n879()
+ fun_l1_n174
+end
+
+def fun_l0_n880()
+ fun_l1_n449
+end
+
+def fun_l0_n881()
+ fun_l1_n385
+end
+
+def fun_l0_n882()
+ fun_l1_n689
+end
+
+def fun_l0_n883()
+ fun_l1_n492
+end
+
+def fun_l0_n884()
+ fun_l1_n949
+end
+
+def fun_l0_n885()
+ fun_l1_n912
+end
+
+def fun_l0_n886()
+ fun_l1_n131
+end
+
+def fun_l0_n887()
+ fun_l1_n484
+end
+
+def fun_l0_n888()
+ fun_l1_n647
+end
+
+def fun_l0_n889()
+ fun_l1_n679
+end
+
+def fun_l0_n890()
+ fun_l1_n16
+end
+
+def fun_l0_n891()
+ fun_l1_n745
+end
+
+def fun_l0_n892()
+ fun_l1_n490
+end
+
+def fun_l0_n893()
+ fun_l1_n104
+end
+
+def fun_l0_n894()
+ fun_l1_n91
+end
+
+def fun_l0_n895()
+ fun_l1_n368
+end
+
+def fun_l0_n896()
+ fun_l1_n439
+end
+
+def fun_l0_n897()
+ fun_l1_n23
+end
+
+def fun_l0_n898()
+ fun_l1_n277
+end
+
+def fun_l0_n899()
+ fun_l1_n597
+end
+
+def fun_l0_n900()
+ fun_l1_n644
+end
+
+def fun_l0_n901()
+ fun_l1_n255
+end
+
+def fun_l0_n902()
+ fun_l1_n767
+end
+
+def fun_l0_n903()
+ fun_l1_n417
+end
+
+def fun_l0_n904()
+ fun_l1_n517
+end
+
+def fun_l0_n905()
+ fun_l1_n609
+end
+
+def fun_l0_n906()
+ fun_l1_n498
+end
+
+def fun_l0_n907()
+ fun_l1_n24
+end
+
+def fun_l0_n908()
+ fun_l1_n722
+end
+
+def fun_l0_n909()
+ fun_l1_n494
+end
+
+def fun_l0_n910()
+ fun_l1_n450
+end
+
+def fun_l0_n911()
+ fun_l1_n302
+end
+
+def fun_l0_n912()
+ fun_l1_n801
+end
+
+def fun_l0_n913()
+ fun_l1_n709
+end
+
+def fun_l0_n914()
+ fun_l1_n555
+end
+
+def fun_l0_n915()
+ fun_l1_n955
+end
+
+def fun_l0_n916()
+ fun_l1_n310
+end
+
+def fun_l0_n917()
+ fun_l1_n839
+end
+
+def fun_l0_n918()
+ fun_l1_n590
+end
+
+def fun_l0_n919()
+ fun_l1_n83
+end
+
+def fun_l0_n920()
+ fun_l1_n335
+end
+
+def fun_l0_n921()
+ fun_l1_n740
+end
+
+def fun_l0_n922()
+ fun_l1_n357
+end
+
+def fun_l0_n923()
+ fun_l1_n312
+end
+
+def fun_l0_n924()
+ fun_l1_n544
+end
+
+def fun_l0_n925()
+ fun_l1_n611
+end
+
+def fun_l0_n926()
+ fun_l1_n651
+end
+
+def fun_l0_n927()
+ fun_l1_n730
+end
+
+def fun_l0_n928()
+ fun_l1_n623
+end
+
+def fun_l0_n929()
+ fun_l1_n337
+end
+
+def fun_l0_n930()
+ fun_l1_n574
+end
+
+def fun_l0_n931()
+ fun_l1_n795
+end
+
+def fun_l0_n932()
+ fun_l1_n224
+end
+
+def fun_l0_n933()
+ fun_l1_n355
+end
+
+def fun_l0_n934()
+ fun_l1_n286
+end
+
+def fun_l0_n935()
+ fun_l1_n893
+end
+
+def fun_l0_n936()
+ fun_l1_n278
+end
+
+def fun_l0_n937()
+ fun_l1_n970
+end
+
+def fun_l0_n938()
+ fun_l1_n761
+end
+
+def fun_l0_n939()
+ fun_l1_n244
+end
+
+def fun_l0_n940()
+ fun_l1_n381
+end
+
+def fun_l0_n941()
+ fun_l1_n661
+end
+
+def fun_l0_n942()
+ fun_l1_n543
+end
+
+def fun_l0_n943()
+ fun_l1_n432
+end
+
+def fun_l0_n944()
+ fun_l1_n237
+end
+
+def fun_l0_n945()
+ fun_l1_n815
+end
+
+def fun_l0_n946()
+ fun_l1_n580
+end
+
+def fun_l0_n947()
+ fun_l1_n99
+end
+
+def fun_l0_n948()
+ fun_l1_n492
+end
+
+def fun_l0_n949()
+ fun_l1_n799
+end
+
+def fun_l0_n950()
+ fun_l1_n727
+end
+
+def fun_l0_n951()
+ fun_l1_n632
+end
+
+def fun_l0_n952()
+ fun_l1_n689
+end
+
+def fun_l0_n953()
+ fun_l1_n69
+end
+
+def fun_l0_n954()
+ fun_l1_n782
+end
+
+def fun_l0_n955()
+ fun_l1_n140
+end
+
+def fun_l0_n956()
+ fun_l1_n451
+end
+
+def fun_l0_n957()
+ fun_l1_n440
+end
+
+def fun_l0_n958()
+ fun_l1_n88
+end
+
+def fun_l0_n959()
+ fun_l1_n775
+end
+
+def fun_l0_n960()
+ fun_l1_n455
+end
+
+def fun_l0_n961()
+ fun_l1_n402
+end
+
+def fun_l0_n962()
+ fun_l1_n906
+end
+
+def fun_l0_n963()
+ fun_l1_n990
+end
+
+def fun_l0_n964()
+ fun_l1_n432
+end
+
+def fun_l0_n965()
+ fun_l1_n419
+end
+
+def fun_l0_n966()
+ fun_l1_n568
+end
+
+def fun_l0_n967()
+ fun_l1_n177
+end
+
+def fun_l0_n968()
+ fun_l1_n206
+end
+
+def fun_l0_n969()
+ fun_l1_n170
+end
+
+def fun_l0_n970()
+ fun_l1_n216
+end
+
+def fun_l0_n971()
+ fun_l1_n700
+end
+
+def fun_l0_n972()
+ fun_l1_n286
+end
+
+def fun_l0_n973()
+ fun_l1_n817
+end
+
+def fun_l0_n974()
+ fun_l1_n605
+end
+
+def fun_l0_n975()
+ fun_l1_n400
+end
+
+def fun_l0_n976()
+ fun_l1_n282
+end
+
+def fun_l0_n977()
+ fun_l1_n978
+end
+
+def fun_l0_n978()
+ fun_l1_n661
+end
+
+def fun_l0_n979()
+ fun_l1_n42
+end
+
+def fun_l0_n980()
+ fun_l1_n1
+end
+
+def fun_l0_n981()
+ fun_l1_n864
+end
+
+def fun_l0_n982()
+ fun_l1_n829
+end
+
+def fun_l0_n983()
+ fun_l1_n713
+end
+
+def fun_l0_n984()
+ fun_l1_n653
+end
+
+def fun_l0_n985()
+ fun_l1_n332
+end
+
+def fun_l0_n986()
+ fun_l1_n21
+end
+
+def fun_l0_n987()
+ fun_l1_n532
+end
+
+def fun_l0_n988()
+ fun_l1_n163
+end
+
+def fun_l0_n989()
+ fun_l1_n154
+end
+
+def fun_l0_n990()
+ fun_l1_n351
+end
+
+def fun_l0_n991()
+ fun_l1_n708
+end
+
+def fun_l0_n992()
+ fun_l1_n955
+end
+
+def fun_l0_n993()
+ fun_l1_n250
+end
+
+def fun_l0_n994()
+ fun_l1_n645
+end
+
+def fun_l0_n995()
+ fun_l1_n668
+end
+
+def fun_l0_n996()
+ fun_l1_n764
+end
+
+def fun_l0_n997()
+ fun_l1_n79
+end
+
+def fun_l0_n998()
+ fun_l1_n251
+end
+
+def fun_l0_n999()
+ fun_l1_n586
+end
+
+def fun_l1_n0()
+ fun_l2_n188
+end
+
+def fun_l1_n1()
+ fun_l2_n165
+end
+
+def fun_l1_n2()
+ fun_l2_n875
+end
+
+def fun_l1_n3()
+ fun_l2_n246
+end
+
+def fun_l1_n4()
+ fun_l2_n887
+end
+
+def fun_l1_n5()
+ fun_l2_n191
+end
+
+def fun_l1_n6()
+ fun_l2_n187
+end
+
+def fun_l1_n7()
+ fun_l2_n138
+end
+
+def fun_l1_n8()
+ fun_l2_n455
+end
+
+def fun_l1_n9()
+ fun_l2_n861
+end
+
+def fun_l1_n10()
+ fun_l2_n588
+end
+
+def fun_l1_n11()
+ fun_l2_n157
+end
+
+def fun_l1_n12()
+ fun_l2_n903
+end
+
+def fun_l1_n13()
+ fun_l2_n655
+end
+
+def fun_l1_n14()
+ fun_l2_n252
+end
+
+def fun_l1_n15()
+ fun_l2_n894
+end
+
+def fun_l1_n16()
+ fun_l2_n908
+end
+
+def fun_l1_n17()
+ fun_l2_n649
+end
+
+def fun_l1_n18()
+ fun_l2_n890
+end
+
+def fun_l1_n19()
+ fun_l2_n451
+end
+
+def fun_l1_n20()
+ fun_l2_n775
+end
+
+def fun_l1_n21()
+ fun_l2_n522
+end
+
+def fun_l1_n22()
+ fun_l2_n666
+end
+
+def fun_l1_n23()
+ fun_l2_n784
+end
+
+def fun_l1_n24()
+ fun_l2_n204
+end
+
+def fun_l1_n25()
+ fun_l2_n310
+end
+
+def fun_l1_n26()
+ fun_l2_n740
+end
+
+def fun_l1_n27()
+ fun_l2_n22
+end
+
+def fun_l1_n28()
+ fun_l2_n114
+end
+
+def fun_l1_n29()
+ fun_l2_n132
+end
+
+def fun_l1_n30()
+ fun_l2_n935
+end
+
+def fun_l1_n31()
+ fun_l2_n459
+end
+
+def fun_l1_n32()
+ fun_l2_n262
+end
+
+def fun_l1_n33()
+ fun_l2_n22
+end
+
+def fun_l1_n34()
+ fun_l2_n649
+end
+
+def fun_l1_n35()
+ fun_l2_n817
+end
+
+def fun_l1_n36()
+ fun_l2_n17
+end
+
+def fun_l1_n37()
+ fun_l2_n685
+end
+
+def fun_l1_n38()
+ fun_l2_n118
+end
+
+def fun_l1_n39()
+ fun_l2_n285
+end
+
+def fun_l1_n40()
+ fun_l2_n186
+end
+
+def fun_l1_n41()
+ fun_l2_n318
+end
+
+def fun_l1_n42()
+ fun_l2_n133
+end
+
+def fun_l1_n43()
+ fun_l2_n364
+end
+
+def fun_l1_n44()
+ fun_l2_n672
+end
+
+def fun_l1_n45()
+ fun_l2_n710
+end
+
+def fun_l1_n46()
+ fun_l2_n568
+end
+
+def fun_l1_n47()
+ fun_l2_n923
+end
+
+def fun_l1_n48()
+ fun_l2_n664
+end
+
+def fun_l1_n49()
+ fun_l2_n460
+end
+
+def fun_l1_n50()
+ fun_l2_n900
+end
+
+def fun_l1_n51()
+ fun_l2_n144
+end
+
+def fun_l1_n52()
+ fun_l2_n798
+end
+
+def fun_l1_n53()
+ fun_l2_n529
+end
+
+def fun_l1_n54()
+ fun_l2_n547
+end
+
+def fun_l1_n55()
+ fun_l2_n643
+end
+
+def fun_l1_n56()
+ fun_l2_n454
+end
+
+def fun_l1_n57()
+ fun_l2_n210
+end
+
+def fun_l1_n58()
+ fun_l2_n69
+end
+
+def fun_l1_n59()
+ fun_l2_n140
+end
+
+def fun_l1_n60()
+ fun_l2_n844
+end
+
+def fun_l1_n61()
+ fun_l2_n933
+end
+
+def fun_l1_n62()
+ fun_l2_n569
+end
+
+def fun_l1_n63()
+ fun_l2_n596
+end
+
+def fun_l1_n64()
+ fun_l2_n254
+end
+
+def fun_l1_n65()
+ fun_l2_n838
+end
+
+def fun_l1_n66()
+ fun_l2_n796
+end
+
+def fun_l1_n67()
+ fun_l2_n262
+end
+
+def fun_l1_n68()
+ fun_l2_n379
+end
+
+def fun_l1_n69()
+ fun_l2_n700
+end
+
+def fun_l1_n70()
+ fun_l2_n947
+end
+
+def fun_l1_n71()
+ fun_l2_n226
+end
+
+def fun_l1_n72()
+ fun_l2_n550
+end
+
+def fun_l1_n73()
+ fun_l2_n791
+end
+
+def fun_l1_n74()
+ fun_l2_n252
+end
+
+def fun_l1_n75()
+ fun_l2_n347
+end
+
+def fun_l1_n76()
+ fun_l2_n812
+end
+
+def fun_l1_n77()
+ fun_l2_n14
+end
+
+def fun_l1_n78()
+ fun_l2_n19
+end
+
+def fun_l1_n79()
+ fun_l2_n296
+end
+
+def fun_l1_n80()
+ fun_l2_n217
+end
+
+def fun_l1_n81()
+ fun_l2_n979
+end
+
+def fun_l1_n82()
+ fun_l2_n815
+end
+
+def fun_l1_n83()
+ fun_l2_n879
+end
+
+def fun_l1_n84()
+ fun_l2_n311
+end
+
+def fun_l1_n85()
+ fun_l2_n351
+end
+
+def fun_l1_n86()
+ fun_l2_n997
+end
+
+def fun_l1_n87()
+ fun_l2_n551
+end
+
+def fun_l1_n88()
+ fun_l2_n221
+end
+
+def fun_l1_n89()
+ fun_l2_n869
+end
+
+def fun_l1_n90()
+ fun_l2_n700
+end
+
+def fun_l1_n91()
+ fun_l2_n627
+end
+
+def fun_l1_n92()
+ fun_l2_n106
+end
+
+def fun_l1_n93()
+ fun_l2_n731
+end
+
+def fun_l1_n94()
+ fun_l2_n61
+end
+
+def fun_l1_n95()
+ fun_l2_n386
+end
+
+def fun_l1_n96()
+ fun_l2_n960
+end
+
+def fun_l1_n97()
+ fun_l2_n75
+end
+
+def fun_l1_n98()
+ fun_l2_n896
+end
+
+def fun_l1_n99()
+ fun_l2_n597
+end
+
+def fun_l1_n100()
+ fun_l2_n73
+end
+
+def fun_l1_n101()
+ fun_l2_n78
+end
+
+def fun_l1_n102()
+ fun_l2_n919
+end
+
+def fun_l1_n103()
+ fun_l2_n784
+end
+
+def fun_l1_n104()
+ fun_l2_n798
+end
+
+def fun_l1_n105()
+ fun_l2_n478
+end
+
+def fun_l1_n106()
+ fun_l2_n883
+end
+
+def fun_l1_n107()
+ fun_l2_n855
+end
+
+def fun_l1_n108()
+ fun_l2_n581
+end
+
+def fun_l1_n109()
+ fun_l2_n694
+end
+
+def fun_l1_n110()
+ fun_l2_n490
+end
+
+def fun_l1_n111()
+ fun_l2_n44
+end
+
+def fun_l1_n112()
+ fun_l2_n537
+end
+
+def fun_l1_n113()
+ fun_l2_n21
+end
+
+def fun_l1_n114()
+ fun_l2_n312
+end
+
+def fun_l1_n115()
+ fun_l2_n700
+end
+
+def fun_l1_n116()
+ fun_l2_n227
+end
+
+def fun_l1_n117()
+ fun_l2_n689
+end
+
+def fun_l1_n118()
+ fun_l2_n664
+end
+
+def fun_l1_n119()
+ fun_l2_n669
+end
+
+def fun_l1_n120()
+ fun_l2_n306
+end
+
+def fun_l1_n121()
+ fun_l2_n278
+end
+
+def fun_l1_n122()
+ fun_l2_n312
+end
+
+def fun_l1_n123()
+ fun_l2_n416
+end
+
+def fun_l1_n124()
+ fun_l2_n912
+end
+
+def fun_l1_n125()
+ fun_l2_n135
+end
+
+def fun_l1_n126()
+ fun_l2_n814
+end
+
+def fun_l1_n127()
+ fun_l2_n468
+end
+
+def fun_l1_n128()
+ fun_l2_n342
+end
+
+def fun_l1_n129()
+ fun_l2_n584
+end
+
+def fun_l1_n130()
+ fun_l2_n826
+end
+
+def fun_l1_n131()
+ fun_l2_n361
+end
+
+def fun_l1_n132()
+ fun_l2_n517
+end
+
+def fun_l1_n133()
+ fun_l2_n894
+end
+
+def fun_l1_n134()
+ fun_l2_n40
+end
+
+def fun_l1_n135()
+ fun_l2_n674
+end
+
+def fun_l1_n136()
+ fun_l2_n137
+end
+
+def fun_l1_n137()
+ fun_l2_n915
+end
+
+def fun_l1_n138()
+ fun_l2_n990
+end
+
+def fun_l1_n139()
+ fun_l2_n86
+end
+
+def fun_l1_n140()
+ fun_l2_n692
+end
+
+def fun_l1_n141()
+ fun_l2_n977
+end
+
+def fun_l1_n142()
+ fun_l2_n956
+end
+
+def fun_l1_n143()
+ fun_l2_n909
+end
+
+def fun_l1_n144()
+ fun_l2_n854
+end
+
+def fun_l1_n145()
+ fun_l2_n223
+end
+
+def fun_l1_n146()
+ fun_l2_n873
+end
+
+def fun_l1_n147()
+ fun_l2_n962
+end
+
+def fun_l1_n148()
+ fun_l2_n441
+end
+
+def fun_l1_n149()
+ fun_l2_n598
+end
+
+def fun_l1_n150()
+ fun_l2_n329
+end
+
+def fun_l1_n151()
+ fun_l2_n749
+end
+
+def fun_l1_n152()
+ fun_l2_n756
+end
+
+def fun_l1_n153()
+ fun_l2_n567
+end
+
+def fun_l1_n154()
+ fun_l2_n23
+end
+
+def fun_l1_n155()
+ fun_l2_n626
+end
+
+def fun_l1_n156()
+ fun_l2_n368
+end
+
+def fun_l1_n157()
+ fun_l2_n169
+end
+
+def fun_l1_n158()
+ fun_l2_n496
+end
+
+def fun_l1_n159()
+ fun_l2_n582
+end
+
+def fun_l1_n160()
+ fun_l2_n443
+end
+
+def fun_l1_n161()
+ fun_l2_n406
+end
+
+def fun_l1_n162()
+ fun_l2_n97
+end
+
+def fun_l1_n163()
+ fun_l2_n293
+end
+
+def fun_l1_n164()
+ fun_l2_n608
+end
+
+def fun_l1_n165()
+ fun_l2_n255
+end
+
+def fun_l1_n166()
+ fun_l2_n421
+end
+
+def fun_l1_n167()
+ fun_l2_n126
+end
+
+def fun_l1_n168()
+ fun_l2_n894
+end
+
+def fun_l1_n169()
+ fun_l2_n486
+end
+
+def fun_l1_n170()
+ fun_l2_n219
+end
+
+def fun_l1_n171()
+ fun_l2_n343
+end
+
+def fun_l1_n172()
+ fun_l2_n914
+end
+
+def fun_l1_n173()
+ fun_l2_n815
+end
+
+def fun_l1_n174()
+ fun_l2_n436
+end
+
+def fun_l1_n175()
+ fun_l2_n923
+end
+
+def fun_l1_n176()
+ fun_l2_n706
+end
+
+def fun_l1_n177()
+ fun_l2_n769
+end
+
+def fun_l1_n178()
+ fun_l2_n271
+end
+
+def fun_l1_n179()
+ fun_l2_n489
+end
+
+def fun_l1_n180()
+ fun_l2_n724
+end
+
+def fun_l1_n181()
+ fun_l2_n202
+end
+
+def fun_l1_n182()
+ fun_l2_n884
+end
+
+def fun_l1_n183()
+ fun_l2_n957
+end
+
+def fun_l1_n184()
+ fun_l2_n690
+end
+
+def fun_l1_n185()
+ fun_l2_n468
+end
+
+def fun_l1_n186()
+ fun_l2_n6
+end
+
+def fun_l1_n187()
+ fun_l2_n94
+end
+
+def fun_l1_n188()
+ fun_l2_n226
+end
+
+def fun_l1_n189()
+ fun_l2_n462
+end
+
+def fun_l1_n190()
+ fun_l2_n228
+end
+
+def fun_l1_n191()
+ fun_l2_n497
+end
+
+def fun_l1_n192()
+ fun_l2_n246
+end
+
+def fun_l1_n193()
+ fun_l2_n960
+end
+
+def fun_l1_n194()
+ fun_l2_n492
+end
+
+def fun_l1_n195()
+ fun_l2_n485
+end
+
+def fun_l1_n196()
+ fun_l2_n18
+end
+
+def fun_l1_n197()
+ fun_l2_n536
+end
+
+def fun_l1_n198()
+ fun_l2_n802
+end
+
+def fun_l1_n199()
+ fun_l2_n151
+end
+
+def fun_l1_n200()
+ fun_l2_n82
+end
+
+def fun_l1_n201()
+ fun_l2_n266
+end
+
+def fun_l1_n202()
+ fun_l2_n445
+end
+
+def fun_l1_n203()
+ fun_l2_n64
+end
+
+def fun_l1_n204()
+ fun_l2_n11
+end
+
+def fun_l1_n205()
+ fun_l2_n351
+end
+
+def fun_l1_n206()
+ fun_l2_n994
+end
+
+def fun_l1_n207()
+ fun_l2_n305
+end
+
+def fun_l1_n208()
+ fun_l2_n258
+end
+
+def fun_l1_n209()
+ fun_l2_n122
+end
+
+def fun_l1_n210()
+ fun_l2_n426
+end
+
+def fun_l1_n211()
+ fun_l2_n385
+end
+
+def fun_l1_n212()
+ fun_l2_n556
+end
+
+def fun_l1_n213()
+ fun_l2_n490
+end
+
+def fun_l1_n214()
+ fun_l2_n809
+end
+
+def fun_l1_n215()
+ fun_l2_n547
+end
+
+def fun_l1_n216()
+ fun_l2_n62
+end
+
+def fun_l1_n217()
+ fun_l2_n675
+end
+
+def fun_l1_n218()
+ fun_l2_n923
+end
+
+def fun_l1_n219()
+ fun_l2_n746
+end
+
+def fun_l1_n220()
+ fun_l2_n222
+end
+
+def fun_l1_n221()
+ fun_l2_n962
+end
+
+def fun_l1_n222()
+ fun_l2_n925
+end
+
+def fun_l1_n223()
+ fun_l2_n908
+end
+
+def fun_l1_n224()
+ fun_l2_n593
+end
+
+def fun_l1_n225()
+ fun_l2_n653
+end
+
+def fun_l1_n226()
+ fun_l2_n21
+end
+
+def fun_l1_n227()
+ fun_l2_n135
+end
+
+def fun_l1_n228()
+ fun_l2_n892
+end
+
+def fun_l1_n229()
+ fun_l2_n976
+end
+
+def fun_l1_n230()
+ fun_l2_n20
+end
+
+def fun_l1_n231()
+ fun_l2_n469
+end
+
+def fun_l1_n232()
+ fun_l2_n741
+end
+
+def fun_l1_n233()
+ fun_l2_n259
+end
+
+def fun_l1_n234()
+ fun_l2_n638
+end
+
+def fun_l1_n235()
+ fun_l2_n335
+end
+
+def fun_l1_n236()
+ fun_l2_n775
+end
+
+def fun_l1_n237()
+ fun_l2_n228
+end
+
+def fun_l1_n238()
+ fun_l2_n287
+end
+
+def fun_l1_n239()
+ fun_l2_n690
+end
+
+def fun_l1_n240()
+ fun_l2_n241
+end
+
+def fun_l1_n241()
+ fun_l2_n728
+end
+
+def fun_l1_n242()
+ fun_l2_n507
+end
+
+def fun_l1_n243()
+ fun_l2_n631
+end
+
+def fun_l1_n244()
+ fun_l2_n338
+end
+
+def fun_l1_n245()
+ fun_l2_n41
+end
+
+def fun_l1_n246()
+ fun_l2_n744
+end
+
+def fun_l1_n247()
+ fun_l2_n52
+end
+
+def fun_l1_n248()
+ fun_l2_n406
+end
+
+def fun_l1_n249()
+ fun_l2_n619
+end
+
+def fun_l1_n250()
+ fun_l2_n710
+end
+
+def fun_l1_n251()
+ fun_l2_n54
+end
+
+def fun_l1_n252()
+ fun_l2_n162
+end
+
+def fun_l1_n253()
+ fun_l2_n952
+end
+
+def fun_l1_n254()
+ fun_l2_n909
+end
+
+def fun_l1_n255()
+ fun_l2_n270
+end
+
+def fun_l1_n256()
+ fun_l2_n752
+end
+
+def fun_l1_n257()
+ fun_l2_n377
+end
+
+def fun_l1_n258()
+ fun_l2_n606
+end
+
+def fun_l1_n259()
+ fun_l2_n368
+end
+
+def fun_l1_n260()
+ fun_l2_n165
+end
+
+def fun_l1_n261()
+ fun_l2_n353
+end
+
+def fun_l1_n262()
+ fun_l2_n199
+end
+
+def fun_l1_n263()
+ fun_l2_n17
+end
+
+def fun_l1_n264()
+ fun_l2_n613
+end
+
+def fun_l1_n265()
+ fun_l2_n329
+end
+
+def fun_l1_n266()
+ fun_l2_n827
+end
+
+def fun_l1_n267()
+ fun_l2_n415
+end
+
+def fun_l1_n268()
+ fun_l2_n835
+end
+
+def fun_l1_n269()
+ fun_l2_n267
+end
+
+def fun_l1_n270()
+ fun_l2_n911
+end
+
+def fun_l1_n271()
+ fun_l2_n640
+end
+
+def fun_l1_n272()
+ fun_l2_n810
+end
+
+def fun_l1_n273()
+ fun_l2_n469
+end
+
+def fun_l1_n274()
+ fun_l2_n121
+end
+
+def fun_l1_n275()
+ fun_l2_n661
+end
+
+def fun_l1_n276()
+ fun_l2_n882
+end
+
+def fun_l1_n277()
+ fun_l2_n469
+end
+
+def fun_l1_n278()
+ fun_l2_n356
+end
+
+def fun_l1_n279()
+ fun_l2_n328
+end
+
+def fun_l1_n280()
+ fun_l2_n155
+end
+
+def fun_l1_n281()
+ fun_l2_n386
+end
+
+def fun_l1_n282()
+ fun_l2_n974
+end
+
+def fun_l1_n283()
+ fun_l2_n126
+end
+
+def fun_l1_n284()
+ fun_l2_n294
+end
+
+def fun_l1_n285()
+ fun_l2_n338
+end
+
+def fun_l1_n286()
+ fun_l2_n366
+end
+
+def fun_l1_n287()
+ fun_l2_n159
+end
+
+def fun_l1_n288()
+ fun_l2_n729
+end
+
+def fun_l1_n289()
+ fun_l2_n422
+end
+
+def fun_l1_n290()
+ fun_l2_n865
+end
+
+def fun_l1_n291()
+ fun_l2_n930
+end
+
+def fun_l1_n292()
+ fun_l2_n469
+end
+
+def fun_l1_n293()
+ fun_l2_n567
+end
+
+def fun_l1_n294()
+ fun_l2_n521
+end
+
+def fun_l1_n295()
+ fun_l2_n208
+end
+
+def fun_l1_n296()
+ fun_l2_n778
+end
+
+def fun_l1_n297()
+ fun_l2_n898
+end
+
+def fun_l1_n298()
+ fun_l2_n523
+end
+
+def fun_l1_n299()
+ fun_l2_n475
+end
+
+def fun_l1_n300()
+ fun_l2_n0
+end
+
+def fun_l1_n301()
+ fun_l2_n818
+end
+
+def fun_l1_n302()
+ fun_l2_n278
+end
+
+def fun_l1_n303()
+ fun_l2_n420
+end
+
+def fun_l1_n304()
+ fun_l2_n988
+end
+
+def fun_l1_n305()
+ fun_l2_n311
+end
+
+def fun_l1_n306()
+ fun_l2_n258
+end
+
+def fun_l1_n307()
+ fun_l2_n41
+end
+
+def fun_l1_n308()
+ fun_l2_n654
+end
+
+def fun_l1_n309()
+ fun_l2_n1
+end
+
+def fun_l1_n310()
+ fun_l2_n161
+end
+
+def fun_l1_n311()
+ fun_l2_n438
+end
+
+def fun_l1_n312()
+ fun_l2_n615
+end
+
+def fun_l1_n313()
+ fun_l2_n461
+end
+
+def fun_l1_n314()
+ fun_l2_n617
+end
+
+def fun_l1_n315()
+ fun_l2_n589
+end
+
+def fun_l1_n316()
+ fun_l2_n793
+end
+
+def fun_l1_n317()
+ fun_l2_n955
+end
+
+def fun_l1_n318()
+ fun_l2_n570
+end
+
+def fun_l1_n319()
+ fun_l2_n15
+end
+
+def fun_l1_n320()
+ fun_l2_n422
+end
+
+def fun_l1_n321()
+ fun_l2_n736
+end
+
+def fun_l1_n322()
+ fun_l2_n726
+end
+
+def fun_l1_n323()
+ fun_l2_n704
+end
+
+def fun_l1_n324()
+ fun_l2_n141
+end
+
+def fun_l1_n325()
+ fun_l2_n262
+end
+
+def fun_l1_n326()
+ fun_l2_n426
+end
+
+def fun_l1_n327()
+ fun_l2_n525
+end
+
+def fun_l1_n328()
+ fun_l2_n806
+end
+
+def fun_l1_n329()
+ fun_l2_n450
+end
+
+def fun_l1_n330()
+ fun_l2_n326
+end
+
+def fun_l1_n331()
+ fun_l2_n760
+end
+
+def fun_l1_n332()
+ fun_l2_n51
+end
+
+def fun_l1_n333()
+ fun_l2_n456
+end
+
+def fun_l1_n334()
+ fun_l2_n94
+end
+
+def fun_l1_n335()
+ fun_l2_n503
+end
+
+def fun_l1_n336()
+ fun_l2_n499
+end
+
+def fun_l1_n337()
+ fun_l2_n645
+end
+
+def fun_l1_n338()
+ fun_l2_n279
+end
+
+def fun_l1_n339()
+ fun_l2_n665
+end
+
+def fun_l1_n340()
+ fun_l2_n153
+end
+
+def fun_l1_n341()
+ fun_l2_n184
+end
+
+def fun_l1_n342()
+ fun_l2_n630
+end
+
+def fun_l1_n343()
+ fun_l2_n59
+end
+
+def fun_l1_n344()
+ fun_l2_n745
+end
+
+def fun_l1_n345()
+ fun_l2_n310
+end
+
+def fun_l1_n346()
+ fun_l2_n380
+end
+
+def fun_l1_n347()
+ fun_l2_n11
+end
+
+def fun_l1_n348()
+ fun_l2_n424
+end
+
+def fun_l1_n349()
+ fun_l2_n484
+end
+
+def fun_l1_n350()
+ fun_l2_n255
+end
+
+def fun_l1_n351()
+ fun_l2_n350
+end
+
+def fun_l1_n352()
+ fun_l2_n672
+end
+
+def fun_l1_n353()
+ fun_l2_n835
+end
+
+def fun_l1_n354()
+ fun_l2_n380
+end
+
+def fun_l1_n355()
+ fun_l2_n897
+end
+
+def fun_l1_n356()
+ fun_l2_n963
+end
+
+def fun_l1_n357()
+ fun_l2_n16
+end
+
+def fun_l1_n358()
+ fun_l2_n584
+end
+
+def fun_l1_n359()
+ fun_l2_n684
+end
+
+def fun_l1_n360()
+ fun_l2_n582
+end
+
+def fun_l1_n361()
+ fun_l2_n982
+end
+
+def fun_l1_n362()
+ fun_l2_n224
+end
+
+def fun_l1_n363()
+ fun_l2_n143
+end
+
+def fun_l1_n364()
+ fun_l2_n809
+end
+
+def fun_l1_n365()
+ fun_l2_n94
+end
+
+def fun_l1_n366()
+ fun_l2_n643
+end
+
+def fun_l1_n367()
+ fun_l2_n511
+end
+
+def fun_l1_n368()
+ fun_l2_n858
+end
+
+def fun_l1_n369()
+ fun_l2_n649
+end
+
+def fun_l1_n370()
+ fun_l2_n98
+end
+
+def fun_l1_n371()
+ fun_l2_n537
+end
+
+def fun_l1_n372()
+ fun_l2_n418
+end
+
+def fun_l1_n373()
+ fun_l2_n456
+end
+
+def fun_l1_n374()
+ fun_l2_n694
+end
+
+def fun_l1_n375()
+ fun_l2_n37
+end
+
+def fun_l1_n376()
+ fun_l2_n152
+end
+
+def fun_l1_n377()
+ fun_l2_n916
+end
+
+def fun_l1_n378()
+ fun_l2_n926
+end
+
+def fun_l1_n379()
+ fun_l2_n978
+end
+
+def fun_l1_n380()
+ fun_l2_n706
+end
+
+def fun_l1_n381()
+ fun_l2_n666
+end
+
+def fun_l1_n382()
+ fun_l2_n407
+end
+
+def fun_l1_n383()
+ fun_l2_n839
+end
+
+def fun_l1_n384()
+ fun_l2_n936
+end
+
+def fun_l1_n385()
+ fun_l2_n122
+end
+
+def fun_l1_n386()
+ fun_l2_n189
+end
+
+def fun_l1_n387()
+ fun_l2_n799
+end
+
+def fun_l1_n388()
+ fun_l2_n494
+end
+
+def fun_l1_n389()
+ fun_l2_n534
+end
+
+def fun_l1_n390()
+ fun_l2_n986
+end
+
+def fun_l1_n391()
+ fun_l2_n870
+end
+
+def fun_l1_n392()
+ fun_l2_n341
+end
+
+def fun_l1_n393()
+ fun_l2_n251
+end
+
+def fun_l1_n394()
+ fun_l2_n95
+end
+
+def fun_l1_n395()
+ fun_l2_n127
+end
+
+def fun_l1_n396()
+ fun_l2_n496
+end
+
+def fun_l1_n397()
+ fun_l2_n81
+end
+
+def fun_l1_n398()
+ fun_l2_n628
+end
+
+def fun_l1_n399()
+ fun_l2_n212
+end
+
+def fun_l1_n400()
+ fun_l2_n968
+end
+
+def fun_l1_n401()
+ fun_l2_n3
+end
+
+def fun_l1_n402()
+ fun_l2_n266
+end
+
+def fun_l1_n403()
+ fun_l2_n227
+end
+
+def fun_l1_n404()
+ fun_l2_n311
+end
+
+def fun_l1_n405()
+ fun_l2_n977
+end
+
+def fun_l1_n406()
+ fun_l2_n298
+end
+
+def fun_l1_n407()
+ fun_l2_n619
+end
+
+def fun_l1_n408()
+ fun_l2_n11
+end
+
+def fun_l1_n409()
+ fun_l2_n40
+end
+
+def fun_l1_n410()
+ fun_l2_n238
+end
+
+def fun_l1_n411()
+ fun_l2_n378
+end
+
+def fun_l1_n412()
+ fun_l2_n166
+end
+
+def fun_l1_n413()
+ fun_l2_n392
+end
+
+def fun_l1_n414()
+ fun_l2_n374
+end
+
+def fun_l1_n415()
+ fun_l2_n195
+end
+
+def fun_l1_n416()
+ fun_l2_n627
+end
+
+def fun_l1_n417()
+ fun_l2_n795
+end
+
+def fun_l1_n418()
+ fun_l2_n79
+end
+
+def fun_l1_n419()
+ fun_l2_n425
+end
+
+def fun_l1_n420()
+ fun_l2_n733
+end
+
+def fun_l1_n421()
+ fun_l2_n974
+end
+
+def fun_l1_n422()
+ fun_l2_n697
+end
+
+def fun_l1_n423()
+ fun_l2_n997
+end
+
+def fun_l1_n424()
+ fun_l2_n860
+end
+
+def fun_l1_n425()
+ fun_l2_n446
+end
+
+def fun_l1_n426()
+ fun_l2_n250
+end
+
+def fun_l1_n427()
+ fun_l2_n556
+end
+
+def fun_l1_n428()
+ fun_l2_n945
+end
+
+def fun_l1_n429()
+ fun_l2_n307
+end
+
+def fun_l1_n430()
+ fun_l2_n541
+end
+
+def fun_l1_n431()
+ fun_l2_n171
+end
+
+def fun_l1_n432()
+ fun_l2_n859
+end
+
+def fun_l1_n433()
+ fun_l2_n351
+end
+
+def fun_l1_n434()
+ fun_l2_n218
+end
+
+def fun_l1_n435()
+ fun_l2_n456
+end
+
+def fun_l1_n436()
+ fun_l2_n418
+end
+
+def fun_l1_n437()
+ fun_l2_n611
+end
+
+def fun_l1_n438()
+ fun_l2_n797
+end
+
+def fun_l1_n439()
+ fun_l2_n738
+end
+
+def fun_l1_n440()
+ fun_l2_n796
+end
+
+def fun_l1_n441()
+ fun_l2_n978
+end
+
+def fun_l1_n442()
+ fun_l2_n400
+end
+
+def fun_l1_n443()
+ fun_l2_n295
+end
+
+def fun_l1_n444()
+ fun_l2_n749
+end
+
+def fun_l1_n445()
+ fun_l2_n401
+end
+
+def fun_l1_n446()
+ fun_l2_n96
+end
+
+def fun_l1_n447()
+ fun_l2_n134
+end
+
+def fun_l1_n448()
+ fun_l2_n149
+end
+
+def fun_l1_n449()
+ fun_l2_n306
+end
+
+def fun_l1_n450()
+ fun_l2_n125
+end
+
+def fun_l1_n451()
+ fun_l2_n34
+end
+
+def fun_l1_n452()
+ fun_l2_n891
+end
+
+def fun_l1_n453()
+ fun_l2_n260
+end
+
+def fun_l1_n454()
+ fun_l2_n104
+end
+
+def fun_l1_n455()
+ fun_l2_n766
+end
+
+def fun_l1_n456()
+ fun_l2_n246
+end
+
+def fun_l1_n457()
+ fun_l2_n292
+end
+
+def fun_l1_n458()
+ fun_l2_n730
+end
+
+def fun_l1_n459()
+ fun_l2_n536
+end
+
+def fun_l1_n460()
+ fun_l2_n139
+end
+
+def fun_l1_n461()
+ fun_l2_n433
+end
+
+def fun_l1_n462()
+ fun_l2_n983
+end
+
+def fun_l1_n463()
+ fun_l2_n730
+end
+
+def fun_l1_n464()
+ fun_l2_n543
+end
+
+def fun_l1_n465()
+ fun_l2_n499
+end
+
+def fun_l1_n466()
+ fun_l2_n180
+end
+
+def fun_l1_n467()
+ fun_l2_n242
+end
+
+def fun_l1_n468()
+ fun_l2_n351
+end
+
+def fun_l1_n469()
+ fun_l2_n229
+end
+
+def fun_l1_n470()
+ fun_l2_n999
+end
+
+def fun_l1_n471()
+ fun_l2_n261
+end
+
+def fun_l1_n472()
+ fun_l2_n738
+end
+
+def fun_l1_n473()
+ fun_l2_n406
+end
+
+def fun_l1_n474()
+ fun_l2_n672
+end
+
+def fun_l1_n475()
+ fun_l2_n86
+end
+
+def fun_l1_n476()
+ fun_l2_n616
+end
+
+def fun_l1_n477()
+ fun_l2_n555
+end
+
+def fun_l1_n478()
+ fun_l2_n686
+end
+
+def fun_l1_n479()
+ fun_l2_n964
+end
+
+def fun_l1_n480()
+ fun_l2_n171
+end
+
+def fun_l1_n481()
+ fun_l2_n525
+end
+
+def fun_l1_n482()
+ fun_l2_n106
+end
+
+def fun_l1_n483()
+ fun_l2_n992
+end
+
+def fun_l1_n484()
+ fun_l2_n988
+end
+
+def fun_l1_n485()
+ fun_l2_n657
+end
+
+def fun_l1_n486()
+ fun_l2_n464
+end
+
+def fun_l1_n487()
+ fun_l2_n55
+end
+
+def fun_l1_n488()
+ fun_l2_n416
+end
+
+def fun_l1_n489()
+ fun_l2_n582
+end
+
+def fun_l1_n490()
+ fun_l2_n873
+end
+
+def fun_l1_n491()
+ fun_l2_n629
+end
+
+def fun_l1_n492()
+ fun_l2_n156
+end
+
+def fun_l1_n493()
+ fun_l2_n68
+end
+
+def fun_l1_n494()
+ fun_l2_n239
+end
+
+def fun_l1_n495()
+ fun_l2_n319
+end
+
+def fun_l1_n496()
+ fun_l2_n539
+end
+
+def fun_l1_n497()
+ fun_l2_n237
+end
+
+def fun_l1_n498()
+ fun_l2_n241
+end
+
+def fun_l1_n499()
+ fun_l2_n34
+end
+
+def fun_l1_n500()
+ fun_l2_n588
+end
+
+def fun_l1_n501()
+ fun_l2_n540
+end
+
+def fun_l1_n502()
+ fun_l2_n591
+end
+
+def fun_l1_n503()
+ fun_l2_n199
+end
+
+def fun_l1_n504()
+ fun_l2_n265
+end
+
+def fun_l1_n505()
+ fun_l2_n170
+end
+
+def fun_l1_n506()
+ fun_l2_n29
+end
+
+def fun_l1_n507()
+ fun_l2_n741
+end
+
+def fun_l1_n508()
+ fun_l2_n877
+end
+
+def fun_l1_n509()
+ fun_l2_n710
+end
+
+def fun_l1_n510()
+ fun_l2_n197
+end
+
+def fun_l1_n511()
+ fun_l2_n319
+end
+
+def fun_l1_n512()
+ fun_l2_n60
+end
+
+def fun_l1_n513()
+ fun_l2_n753
+end
+
+def fun_l1_n514()
+ fun_l2_n492
+end
+
+def fun_l1_n515()
+ fun_l2_n961
+end
+
+def fun_l1_n516()
+ fun_l2_n227
+end
+
+def fun_l1_n517()
+ fun_l2_n361
+end
+
+def fun_l1_n518()
+ fun_l2_n265
+end
+
+def fun_l1_n519()
+ fun_l2_n392
+end
+
+def fun_l1_n520()
+ fun_l2_n425
+end
+
+def fun_l1_n521()
+ fun_l2_n869
+end
+
+def fun_l1_n522()
+ fun_l2_n859
+end
+
+def fun_l1_n523()
+ fun_l2_n140
+end
+
+def fun_l1_n524()
+ fun_l2_n451
+end
+
+def fun_l1_n525()
+ fun_l2_n274
+end
+
+def fun_l1_n526()
+ fun_l2_n358
+end
+
+def fun_l1_n527()
+ fun_l2_n475
+end
+
+def fun_l1_n528()
+ fun_l2_n948
+end
+
+def fun_l1_n529()
+ fun_l2_n866
+end
+
+def fun_l1_n530()
+ fun_l2_n70
+end
+
+def fun_l1_n531()
+ fun_l2_n756
+end
+
+def fun_l1_n532()
+ fun_l2_n704
+end
+
+def fun_l1_n533()
+ fun_l2_n59
+end
+
+def fun_l1_n534()
+ fun_l2_n174
+end
+
+def fun_l1_n535()
+ fun_l2_n476
+end
+
+def fun_l1_n536()
+ fun_l2_n269
+end
+
+def fun_l1_n537()
+ fun_l2_n897
+end
+
+def fun_l1_n538()
+ fun_l2_n550
+end
+
+def fun_l1_n539()
+ fun_l2_n404
+end
+
+def fun_l1_n540()
+ fun_l2_n167
+end
+
+def fun_l1_n541()
+ fun_l2_n332
+end
+
+def fun_l1_n542()
+ fun_l2_n853
+end
+
+def fun_l1_n543()
+ fun_l2_n621
+end
+
+def fun_l1_n544()
+ fun_l2_n36
+end
+
+def fun_l1_n545()
+ fun_l2_n978
+end
+
+def fun_l1_n546()
+ fun_l2_n295
+end
+
+def fun_l1_n547()
+ fun_l2_n537
+end
+
+def fun_l1_n548()
+ fun_l2_n315
+end
+
+def fun_l1_n549()
+ fun_l2_n944
+end
+
+def fun_l1_n550()
+ fun_l2_n933
+end
+
+def fun_l1_n551()
+ fun_l2_n209
+end
+
+def fun_l1_n552()
+ fun_l2_n524
+end
+
+def fun_l1_n553()
+ fun_l2_n115
+end
+
+def fun_l1_n554()
+ fun_l2_n475
+end
+
+def fun_l1_n555()
+ fun_l2_n417
+end
+
+def fun_l1_n556()
+ fun_l2_n507
+end
+
+def fun_l1_n557()
+ fun_l2_n812
+end
+
+def fun_l1_n558()
+ fun_l2_n261
+end
+
+def fun_l1_n559()
+ fun_l2_n268
+end
+
+def fun_l1_n560()
+ fun_l2_n34
+end
+
+def fun_l1_n561()
+ fun_l2_n774
+end
+
+def fun_l1_n562()
+ fun_l2_n102
+end
+
+def fun_l1_n563()
+ fun_l2_n791
+end
+
+def fun_l1_n564()
+ fun_l2_n760
+end
+
+def fun_l1_n565()
+ fun_l2_n376
+end
+
+def fun_l1_n566()
+ fun_l2_n897
+end
+
+def fun_l1_n567()
+ fun_l2_n456
+end
+
+def fun_l1_n568()
+ fun_l2_n120
+end
+
+def fun_l1_n569()
+ fun_l2_n892
+end
+
+def fun_l1_n570()
+ fun_l2_n948
+end
+
+def fun_l1_n571()
+ fun_l2_n586
+end
+
+def fun_l1_n572()
+ fun_l2_n428
+end
+
+def fun_l1_n573()
+ fun_l2_n182
+end
+
+def fun_l1_n574()
+ fun_l2_n980
+end
+
+def fun_l1_n575()
+ fun_l2_n192
+end
+
+def fun_l1_n576()
+ fun_l2_n440
+end
+
+def fun_l1_n577()
+ fun_l2_n381
+end
+
+def fun_l1_n578()
+ fun_l2_n508
+end
+
+def fun_l1_n579()
+ fun_l2_n560
+end
+
+def fun_l1_n580()
+ fun_l2_n673
+end
+
+def fun_l1_n581()
+ fun_l2_n236
+end
+
+def fun_l1_n582()
+ fun_l2_n936
+end
+
+def fun_l1_n583()
+ fun_l2_n104
+end
+
+def fun_l1_n584()
+ fun_l2_n439
+end
+
+def fun_l1_n585()
+ fun_l2_n844
+end
+
+def fun_l1_n586()
+ fun_l2_n115
+end
+
+def fun_l1_n587()
+ fun_l2_n114
+end
+
+def fun_l1_n588()
+ fun_l2_n963
+end
+
+def fun_l1_n589()
+ fun_l2_n972
+end
+
+def fun_l1_n590()
+ fun_l2_n333
+end
+
+def fun_l1_n591()
+ fun_l2_n624
+end
+
+def fun_l1_n592()
+ fun_l2_n478
+end
+
+def fun_l1_n593()
+ fun_l2_n581
+end
+
+def fun_l1_n594()
+ fun_l2_n199
+end
+
+def fun_l1_n595()
+ fun_l2_n596
+end
+
+def fun_l1_n596()
+ fun_l2_n458
+end
+
+def fun_l1_n597()
+ fun_l2_n729
+end
+
+def fun_l1_n598()
+ fun_l2_n545
+end
+
+def fun_l1_n599()
+ fun_l2_n60
+end
+
+def fun_l1_n600()
+ fun_l2_n801
+end
+
+def fun_l1_n601()
+ fun_l2_n164
+end
+
+def fun_l1_n602()
+ fun_l2_n3
+end
+
+def fun_l1_n603()
+ fun_l2_n334
+end
+
+def fun_l1_n604()
+ fun_l2_n887
+end
+
+def fun_l1_n605()
+ fun_l2_n777
+end
+
+def fun_l1_n606()
+ fun_l2_n765
+end
+
+def fun_l1_n607()
+ fun_l2_n529
+end
+
+def fun_l1_n608()
+ fun_l2_n233
+end
+
+def fun_l1_n609()
+ fun_l2_n164
+end
+
+def fun_l1_n610()
+ fun_l2_n289
+end
+
+def fun_l1_n611()
+ fun_l2_n918
+end
+
+def fun_l1_n612()
+ fun_l2_n13
+end
+
+def fun_l1_n613()
+ fun_l2_n530
+end
+
+def fun_l1_n614()
+ fun_l2_n574
+end
+
+def fun_l1_n615()
+ fun_l2_n383
+end
+
+def fun_l1_n616()
+ fun_l2_n470
+end
+
+def fun_l1_n617()
+ fun_l2_n551
+end
+
+def fun_l1_n618()
+ fun_l2_n539
+end
+
+def fun_l1_n619()
+ fun_l2_n858
+end
+
+def fun_l1_n620()
+ fun_l2_n523
+end
+
+def fun_l1_n621()
+ fun_l2_n439
+end
+
+def fun_l1_n622()
+ fun_l2_n909
+end
+
+def fun_l1_n623()
+ fun_l2_n686
+end
+
+def fun_l1_n624()
+ fun_l2_n133
+end
+
+def fun_l1_n625()
+ fun_l2_n92
+end
+
+def fun_l1_n626()
+ fun_l2_n443
+end
+
+def fun_l1_n627()
+ fun_l2_n682
+end
+
+def fun_l1_n628()
+ fun_l2_n113
+end
+
+def fun_l1_n629()
+ fun_l2_n353
+end
+
+def fun_l1_n630()
+ fun_l2_n631
+end
+
+def fun_l1_n631()
+ fun_l2_n858
+end
+
+def fun_l1_n632()
+ fun_l2_n816
+end
+
+def fun_l1_n633()
+ fun_l2_n683
+end
+
+def fun_l1_n634()
+ fun_l2_n32
+end
+
+def fun_l1_n635()
+ fun_l2_n983
+end
+
+def fun_l1_n636()
+ fun_l2_n587
+end
+
+def fun_l1_n637()
+ fun_l2_n17
+end
+
+def fun_l1_n638()
+ fun_l2_n129
+end
+
+def fun_l1_n639()
+ fun_l2_n166
+end
+
+def fun_l1_n640()
+ fun_l2_n742
+end
+
+def fun_l1_n641()
+ fun_l2_n8
+end
+
+def fun_l1_n642()
+ fun_l2_n119
+end
+
+def fun_l1_n643()
+ fun_l2_n615
+end
+
+def fun_l1_n644()
+ fun_l2_n419
+end
+
+def fun_l1_n645()
+ fun_l2_n324
+end
+
+def fun_l1_n646()
+ fun_l2_n806
+end
+
+def fun_l1_n647()
+ fun_l2_n722
+end
+
+def fun_l1_n648()
+ fun_l2_n462
+end
+
+def fun_l1_n649()
+ fun_l2_n602
+end
+
+def fun_l1_n650()
+ fun_l2_n39
+end
+
+def fun_l1_n651()
+ fun_l2_n53
+end
+
+def fun_l1_n652()
+ fun_l2_n201
+end
+
+def fun_l1_n653()
+ fun_l2_n403
+end
+
+def fun_l1_n654()
+ fun_l2_n595
+end
+
+def fun_l1_n655()
+ fun_l2_n467
+end
+
+def fun_l1_n656()
+ fun_l2_n904
+end
+
+def fun_l1_n657()
+ fun_l2_n429
+end
+
+def fun_l1_n658()
+ fun_l2_n463
+end
+
+def fun_l1_n659()
+ fun_l2_n470
+end
+
+def fun_l1_n660()
+ fun_l2_n0
+end
+
+def fun_l1_n661()
+ fun_l2_n258
+end
+
+def fun_l1_n662()
+ fun_l2_n950
+end
+
+def fun_l1_n663()
+ fun_l2_n953
+end
+
+def fun_l1_n664()
+ fun_l2_n664
+end
+
+def fun_l1_n665()
+ fun_l2_n12
+end
+
+def fun_l1_n666()
+ fun_l2_n317
+end
+
+def fun_l1_n667()
+ fun_l2_n526
+end
+
+def fun_l1_n668()
+ fun_l2_n984
+end
+
+def fun_l1_n669()
+ fun_l2_n273
+end
+
+def fun_l1_n670()
+ fun_l2_n822
+end
+
+def fun_l1_n671()
+ fun_l2_n759
+end
+
+def fun_l1_n672()
+ fun_l2_n927
+end
+
+def fun_l1_n673()
+ fun_l2_n419
+end
+
+def fun_l1_n674()
+ fun_l2_n546
+end
+
+def fun_l1_n675()
+ fun_l2_n879
+end
+
+def fun_l1_n676()
+ fun_l2_n659
+end
+
+def fun_l1_n677()
+ fun_l2_n317
+end
+
+def fun_l1_n678()
+ fun_l2_n234
+end
+
+def fun_l1_n679()
+ fun_l2_n416
+end
+
+def fun_l1_n680()
+ fun_l2_n890
+end
+
+def fun_l1_n681()
+ fun_l2_n401
+end
+
+def fun_l1_n682()
+ fun_l2_n271
+end
+
+def fun_l1_n683()
+ fun_l2_n915
+end
+
+def fun_l1_n684()
+ fun_l2_n666
+end
+
+def fun_l1_n685()
+ fun_l2_n151
+end
+
+def fun_l1_n686()
+ fun_l2_n786
+end
+
+def fun_l1_n687()
+ fun_l2_n82
+end
+
+def fun_l1_n688()
+ fun_l2_n831
+end
+
+def fun_l1_n689()
+ fun_l2_n830
+end
+
+def fun_l1_n690()
+ fun_l2_n221
+end
+
+def fun_l1_n691()
+ fun_l2_n530
+end
+
+def fun_l1_n692()
+ fun_l2_n131
+end
+
+def fun_l1_n693()
+ fun_l2_n17
+end
+
+def fun_l1_n694()
+ fun_l2_n265
+end
+
+def fun_l1_n695()
+ fun_l2_n111
+end
+
+def fun_l1_n696()
+ fun_l2_n39
+end
+
+def fun_l1_n697()
+ fun_l2_n326
+end
+
+def fun_l1_n698()
+ fun_l2_n713
+end
+
+def fun_l1_n699()
+ fun_l2_n960
+end
+
+def fun_l1_n700()
+ fun_l2_n633
+end
+
+def fun_l1_n701()
+ fun_l2_n291
+end
+
+def fun_l1_n702()
+ fun_l2_n746
+end
+
+def fun_l1_n703()
+ fun_l2_n316
+end
+
+def fun_l1_n704()
+ fun_l2_n116
+end
+
+def fun_l1_n705()
+ fun_l2_n195
+end
+
+def fun_l1_n706()
+ fun_l2_n614
+end
+
+def fun_l1_n707()
+ fun_l2_n591
+end
+
+def fun_l1_n708()
+ fun_l2_n879
+end
+
+def fun_l1_n709()
+ fun_l2_n770
+end
+
+def fun_l1_n710()
+ fun_l2_n332
+end
+
+def fun_l1_n711()
+ fun_l2_n696
+end
+
+def fun_l1_n712()
+ fun_l2_n42
+end
+
+def fun_l1_n713()
+ fun_l2_n126
+end
+
+def fun_l1_n714()
+ fun_l2_n486
+end
+
+def fun_l1_n715()
+ fun_l2_n259
+end
+
+def fun_l1_n716()
+ fun_l2_n390
+end
+
+def fun_l1_n717()
+ fun_l2_n590
+end
+
+def fun_l1_n718()
+ fun_l2_n180
+end
+
+def fun_l1_n719()
+ fun_l2_n673
+end
+
+def fun_l1_n720()
+ fun_l2_n565
+end
+
+def fun_l1_n721()
+ fun_l2_n504
+end
+
+def fun_l1_n722()
+ fun_l2_n585
+end
+
+def fun_l1_n723()
+ fun_l2_n746
+end
+
+def fun_l1_n724()
+ fun_l2_n797
+end
+
+def fun_l1_n725()
+ fun_l2_n281
+end
+
+def fun_l1_n726()
+ fun_l2_n670
+end
+
+def fun_l1_n727()
+ fun_l2_n678
+end
+
+def fun_l1_n728()
+ fun_l2_n329
+end
+
+def fun_l1_n729()
+ fun_l2_n581
+end
+
+def fun_l1_n730()
+ fun_l2_n313
+end
+
+def fun_l1_n731()
+ fun_l2_n893
+end
+
+def fun_l1_n732()
+ fun_l2_n773
+end
+
+def fun_l1_n733()
+ fun_l2_n527
+end
+
+def fun_l1_n734()
+ fun_l2_n473
+end
+
+def fun_l1_n735()
+ fun_l2_n242
+end
+
+def fun_l1_n736()
+ fun_l2_n681
+end
+
+def fun_l1_n737()
+ fun_l2_n593
+end
+
+def fun_l1_n738()
+ fun_l2_n214
+end
+
+def fun_l1_n739()
+ fun_l2_n931
+end
+
+def fun_l1_n740()
+ fun_l2_n157
+end
+
+def fun_l1_n741()
+ fun_l2_n207
+end
+
+def fun_l1_n742()
+ fun_l2_n583
+end
+
+def fun_l1_n743()
+ fun_l2_n978
+end
+
+def fun_l1_n744()
+ fun_l2_n220
+end
+
+def fun_l1_n745()
+ fun_l2_n0
+end
+
+def fun_l1_n746()
+ fun_l2_n871
+end
+
+def fun_l1_n747()
+ fun_l2_n344
+end
+
+def fun_l1_n748()
+ fun_l2_n445
+end
+
+def fun_l1_n749()
+ fun_l2_n682
+end
+
+def fun_l1_n750()
+ fun_l2_n553
+end
+
+def fun_l1_n751()
+ fun_l2_n616
+end
+
+def fun_l1_n752()
+ fun_l2_n93
+end
+
+def fun_l1_n753()
+ fun_l2_n297
+end
+
+def fun_l1_n754()
+ fun_l2_n653
+end
+
+def fun_l1_n755()
+ fun_l2_n730
+end
+
+def fun_l1_n756()
+ fun_l2_n375
+end
+
+def fun_l1_n757()
+ fun_l2_n522
+end
+
+def fun_l1_n758()
+ fun_l2_n855
+end
+
+def fun_l1_n759()
+ fun_l2_n727
+end
+
+def fun_l1_n760()
+ fun_l2_n516
+end
+
+def fun_l1_n761()
+ fun_l2_n322
+end
+
+def fun_l1_n762()
+ fun_l2_n84
+end
+
+def fun_l1_n763()
+ fun_l2_n704
+end
+
+def fun_l1_n764()
+ fun_l2_n516
+end
+
+def fun_l1_n765()
+ fun_l2_n97
+end
+
+def fun_l1_n766()
+ fun_l2_n678
+end
+
+def fun_l1_n767()
+ fun_l2_n690
+end
+
+def fun_l1_n768()
+ fun_l2_n704
+end
+
+def fun_l1_n769()
+ fun_l2_n664
+end
+
+def fun_l1_n770()
+ fun_l2_n157
+end
+
+def fun_l1_n771()
+ fun_l2_n24
+end
+
+def fun_l1_n772()
+ fun_l2_n399
+end
+
+def fun_l1_n773()
+ fun_l2_n362
+end
+
+def fun_l1_n774()
+ fun_l2_n687
+end
+
+def fun_l1_n775()
+ fun_l2_n228
+end
+
+def fun_l1_n776()
+ fun_l2_n781
+end
+
+def fun_l1_n777()
+ fun_l2_n112
+end
+
+def fun_l1_n778()
+ fun_l2_n126
+end
+
+def fun_l1_n779()
+ fun_l2_n298
+end
+
+def fun_l1_n780()
+ fun_l2_n779
+end
+
+def fun_l1_n781()
+ fun_l2_n354
+end
+
+def fun_l1_n782()
+ fun_l2_n357
+end
+
+def fun_l1_n783()
+ fun_l2_n814
+end
+
+def fun_l1_n784()
+ fun_l2_n975
+end
+
+def fun_l1_n785()
+ fun_l2_n853
+end
+
+def fun_l1_n786()
+ fun_l2_n58
+end
+
+def fun_l1_n787()
+ fun_l2_n455
+end
+
+def fun_l1_n788()
+ fun_l2_n31
+end
+
+def fun_l1_n789()
+ fun_l2_n621
+end
+
+def fun_l1_n790()
+ fun_l2_n714
+end
+
+def fun_l1_n791()
+ fun_l2_n931
+end
+
+def fun_l1_n792()
+ fun_l2_n511
+end
+
+def fun_l1_n793()
+ fun_l2_n128
+end
+
+def fun_l1_n794()
+ fun_l2_n750
+end
+
+def fun_l1_n795()
+ fun_l2_n121
+end
+
+def fun_l1_n796()
+ fun_l2_n226
+end
+
+def fun_l1_n797()
+ fun_l2_n515
+end
+
+def fun_l1_n798()
+ fun_l2_n8
+end
+
+def fun_l1_n799()
+ fun_l2_n372
+end
+
+def fun_l1_n800()
+ fun_l2_n646
+end
+
+def fun_l1_n801()
+ fun_l2_n722
+end
+
+def fun_l1_n802()
+ fun_l2_n932
+end
+
+def fun_l1_n803()
+ fun_l2_n992
+end
+
+def fun_l1_n804()
+ fun_l2_n628
+end
+
+def fun_l1_n805()
+ fun_l2_n97
+end
+
+def fun_l1_n806()
+ fun_l2_n113
+end
+
+def fun_l1_n807()
+ fun_l2_n249
+end
+
+def fun_l1_n808()
+ fun_l2_n211
+end
+
+def fun_l1_n809()
+ fun_l2_n40
+end
+
+def fun_l1_n810()
+ fun_l2_n608
+end
+
+def fun_l1_n811()
+ fun_l2_n560
+end
+
+def fun_l1_n812()
+ fun_l2_n182
+end
+
+def fun_l1_n813()
+ fun_l2_n7
+end
+
+def fun_l1_n814()
+ fun_l2_n641
+end
+
+def fun_l1_n815()
+ fun_l2_n541
+end
+
+def fun_l1_n816()
+ fun_l2_n951
+end
+
+def fun_l1_n817()
+ fun_l2_n122
+end
+
+def fun_l1_n818()
+ fun_l2_n270
+end
+
+def fun_l1_n819()
+ fun_l2_n631
+end
+
+def fun_l1_n820()
+ fun_l2_n787
+end
+
+def fun_l1_n821()
+ fun_l2_n543
+end
+
+def fun_l1_n822()
+ fun_l2_n599
+end
+
+def fun_l1_n823()
+ fun_l2_n686
+end
+
+def fun_l1_n824()
+ fun_l2_n11
+end
+
+def fun_l1_n825()
+ fun_l2_n379
+end
+
+def fun_l1_n826()
+ fun_l2_n190
+end
+
+def fun_l1_n827()
+ fun_l2_n815
+end
+
+def fun_l1_n828()
+ fun_l2_n117
+end
+
+def fun_l1_n829()
+ fun_l2_n465
+end
+
+def fun_l1_n830()
+ fun_l2_n333
+end
+
+def fun_l1_n831()
+ fun_l2_n928
+end
+
+def fun_l1_n832()
+ fun_l2_n565
+end
+
+def fun_l1_n833()
+ fun_l2_n83
+end
+
+def fun_l1_n834()
+ fun_l2_n364
+end
+
+def fun_l1_n835()
+ fun_l2_n93
+end
+
+def fun_l1_n836()
+ fun_l2_n20
+end
+
+def fun_l1_n837()
+ fun_l2_n223
+end
+
+def fun_l1_n838()
+ fun_l2_n720
+end
+
+def fun_l1_n839()
+ fun_l2_n848
+end
+
+def fun_l1_n840()
+ fun_l2_n228
+end
+
+def fun_l1_n841()
+ fun_l2_n607
+end
+
+def fun_l1_n842()
+ fun_l2_n253
+end
+
+def fun_l1_n843()
+ fun_l2_n426
+end
+
+def fun_l1_n844()
+ fun_l2_n295
+end
+
+def fun_l1_n845()
+ fun_l2_n213
+end
+
+def fun_l1_n846()
+ fun_l2_n991
+end
+
+def fun_l1_n847()
+ fun_l2_n169
+end
+
+def fun_l1_n848()
+ fun_l2_n32
+end
+
+def fun_l1_n849()
+ fun_l2_n495
+end
+
+def fun_l1_n850()
+ fun_l2_n528
+end
+
+def fun_l1_n851()
+ fun_l2_n862
+end
+
+def fun_l1_n852()
+ fun_l2_n712
+end
+
+def fun_l1_n853()
+ fun_l2_n234
+end
+
+def fun_l1_n854()
+ fun_l2_n646
+end
+
+def fun_l1_n855()
+ fun_l2_n720
+end
+
+def fun_l1_n856()
+ fun_l2_n605
+end
+
+def fun_l1_n857()
+ fun_l2_n966
+end
+
+def fun_l1_n858()
+ fun_l2_n68
+end
+
+def fun_l1_n859()
+ fun_l2_n914
+end
+
+def fun_l1_n860()
+ fun_l2_n234
+end
+
+def fun_l1_n861()
+ fun_l2_n410
+end
+
+def fun_l1_n862()
+ fun_l2_n370
+end
+
+def fun_l1_n863()
+ fun_l2_n127
+end
+
+def fun_l1_n864()
+ fun_l2_n187
+end
+
+def fun_l1_n865()
+ fun_l2_n98
+end
+
+def fun_l1_n866()
+ fun_l2_n256
+end
+
+def fun_l1_n867()
+ fun_l2_n747
+end
+
+def fun_l1_n868()
+ fun_l2_n344
+end
+
+def fun_l1_n869()
+ fun_l2_n570
+end
+
+def fun_l1_n870()
+ fun_l2_n552
+end
+
+def fun_l1_n871()
+ fun_l2_n499
+end
+
+def fun_l1_n872()
+ fun_l2_n763
+end
+
+def fun_l1_n873()
+ fun_l2_n35
+end
+
+def fun_l1_n874()
+ fun_l2_n229
+end
+
+def fun_l1_n875()
+ fun_l2_n124
+end
+
+def fun_l1_n876()
+ fun_l2_n258
+end
+
+def fun_l1_n877()
+ fun_l2_n280
+end
+
+def fun_l1_n878()
+ fun_l2_n899
+end
+
+def fun_l1_n879()
+ fun_l2_n211
+end
+
+def fun_l1_n880()
+ fun_l2_n741
+end
+
+def fun_l1_n881()
+ fun_l2_n32
+end
+
+def fun_l1_n882()
+ fun_l2_n212
+end
+
+def fun_l1_n883()
+ fun_l2_n661
+end
+
+def fun_l1_n884()
+ fun_l2_n889
+end
+
+def fun_l1_n885()
+ fun_l2_n975
+end
+
+def fun_l1_n886()
+ fun_l2_n288
+end
+
+def fun_l1_n887()
+ fun_l2_n448
+end
+
+def fun_l1_n888()
+ fun_l2_n520
+end
+
+def fun_l1_n889()
+ fun_l2_n284
+end
+
+def fun_l1_n890()
+ fun_l2_n254
+end
+
+def fun_l1_n891()
+ fun_l2_n703
+end
+
+def fun_l1_n892()
+ fun_l2_n706
+end
+
+def fun_l1_n893()
+ fun_l2_n9
+end
+
+def fun_l1_n894()
+ fun_l2_n717
+end
+
+def fun_l1_n895()
+ fun_l2_n290
+end
+
+def fun_l1_n896()
+ fun_l2_n657
+end
+
+def fun_l1_n897()
+ fun_l2_n452
+end
+
+def fun_l1_n898()
+ fun_l2_n493
+end
+
+def fun_l1_n899()
+ fun_l2_n308
+end
+
+def fun_l1_n900()
+ fun_l2_n781
+end
+
+def fun_l1_n901()
+ fun_l2_n970
+end
+
+def fun_l1_n902()
+ fun_l2_n371
+end
+
+def fun_l1_n903()
+ fun_l2_n195
+end
+
+def fun_l1_n904()
+ fun_l2_n662
+end
+
+def fun_l1_n905()
+ fun_l2_n172
+end
+
+def fun_l1_n906()
+ fun_l2_n579
+end
+
+def fun_l1_n907()
+ fun_l2_n913
+end
+
+def fun_l1_n908()
+ fun_l2_n949
+end
+
+def fun_l1_n909()
+ fun_l2_n386
+end
+
+def fun_l1_n910()
+ fun_l2_n727
+end
+
+def fun_l1_n911()
+ fun_l2_n283
+end
+
+def fun_l1_n912()
+ fun_l2_n136
+end
+
+def fun_l1_n913()
+ fun_l2_n818
+end
+
+def fun_l1_n914()
+ fun_l2_n118
+end
+
+def fun_l1_n915()
+ fun_l2_n366
+end
+
+def fun_l1_n916()
+ fun_l2_n362
+end
+
+def fun_l1_n917()
+ fun_l2_n854
+end
+
+def fun_l1_n918()
+ fun_l2_n272
+end
+
+def fun_l1_n919()
+ fun_l2_n754
+end
+
+def fun_l1_n920()
+ fun_l2_n145
+end
+
+def fun_l1_n921()
+ fun_l2_n631
+end
+
+def fun_l1_n922()
+ fun_l2_n131
+end
+
+def fun_l1_n923()
+ fun_l2_n862
+end
+
+def fun_l1_n924()
+ fun_l2_n930
+end
+
+def fun_l1_n925()
+ fun_l2_n24
+end
+
+def fun_l1_n926()
+ fun_l2_n336
+end
+
+def fun_l1_n927()
+ fun_l2_n438
+end
+
+def fun_l1_n928()
+ fun_l2_n306
+end
+
+def fun_l1_n929()
+ fun_l2_n897
+end
+
+def fun_l1_n930()
+ fun_l2_n186
+end
+
+def fun_l1_n931()
+ fun_l2_n227
+end
+
+def fun_l1_n932()
+ fun_l2_n462
+end
+
+def fun_l1_n933()
+ fun_l2_n224
+end
+
+def fun_l1_n934()
+ fun_l2_n210
+end
+
+def fun_l1_n935()
+ fun_l2_n315
+end
+
+def fun_l1_n936()
+ fun_l2_n850
+end
+
+def fun_l1_n937()
+ fun_l2_n997
+end
+
+def fun_l1_n938()
+ fun_l2_n703
+end
+
+def fun_l1_n939()
+ fun_l2_n635
+end
+
+def fun_l1_n940()
+ fun_l2_n507
+end
+
+def fun_l1_n941()
+ fun_l2_n202
+end
+
+def fun_l1_n942()
+ fun_l2_n319
+end
+
+def fun_l1_n943()
+ fun_l2_n785
+end
+
+def fun_l1_n944()
+ fun_l2_n26
+end
+
+def fun_l1_n945()
+ fun_l2_n777
+end
+
+def fun_l1_n946()
+ fun_l2_n235
+end
+
+def fun_l1_n947()
+ fun_l2_n845
+end
+
+def fun_l1_n948()
+ fun_l2_n515
+end
+
+def fun_l1_n949()
+ fun_l2_n427
+end
+
+def fun_l1_n950()
+ fun_l2_n34
+end
+
+def fun_l1_n951()
+ fun_l2_n905
+end
+
+def fun_l1_n952()
+ fun_l2_n683
+end
+
+def fun_l1_n953()
+ fun_l2_n171
+end
+
+def fun_l1_n954()
+ fun_l2_n593
+end
+
+def fun_l1_n955()
+ fun_l2_n191
+end
+
+def fun_l1_n956()
+ fun_l2_n370
+end
+
+def fun_l1_n957()
+ fun_l2_n911
+end
+
+def fun_l1_n958()
+ fun_l2_n813
+end
+
+def fun_l1_n959()
+ fun_l2_n765
+end
+
+def fun_l1_n960()
+ fun_l2_n434
+end
+
+def fun_l1_n961()
+ fun_l2_n442
+end
+
+def fun_l1_n962()
+ fun_l2_n390
+end
+
+def fun_l1_n963()
+ fun_l2_n549
+end
+
+def fun_l1_n964()
+ fun_l2_n757
+end
+
+def fun_l1_n965()
+ fun_l2_n12
+end
+
+def fun_l1_n966()
+ fun_l2_n456
+end
+
+def fun_l1_n967()
+ fun_l2_n889
+end
+
+def fun_l1_n968()
+ fun_l2_n933
+end
+
+def fun_l1_n969()
+ fun_l2_n695
+end
+
+def fun_l1_n970()
+ fun_l2_n628
+end
+
+def fun_l1_n971()
+ fun_l2_n265
+end
+
+def fun_l1_n972()
+ fun_l2_n634
+end
+
+def fun_l1_n973()
+ fun_l2_n31
+end
+
+def fun_l1_n974()
+ fun_l2_n49
+end
+
+def fun_l1_n975()
+ fun_l2_n872
+end
+
+def fun_l1_n976()
+ fun_l2_n475
+end
+
+def fun_l1_n977()
+ fun_l2_n927
+end
+
+def fun_l1_n978()
+ fun_l2_n459
+end
+
+def fun_l1_n979()
+ fun_l2_n364
+end
+
+def fun_l1_n980()
+ fun_l2_n246
+end
+
+def fun_l1_n981()
+ fun_l2_n693
+end
+
+def fun_l1_n982()
+ fun_l2_n218
+end
+
+def fun_l1_n983()
+ fun_l2_n21
+end
+
+def fun_l1_n984()
+ fun_l2_n967
+end
+
+def fun_l1_n985()
+ fun_l2_n81
+end
+
+def fun_l1_n986()
+ fun_l2_n753
+end
+
+def fun_l1_n987()
+ fun_l2_n386
+end
+
+def fun_l1_n988()
+ fun_l2_n394
+end
+
+def fun_l1_n989()
+ fun_l2_n804
+end
+
+def fun_l1_n990()
+ fun_l2_n55
+end
+
+def fun_l1_n991()
+ fun_l2_n359
+end
+
+def fun_l1_n992()
+ fun_l2_n883
+end
+
+def fun_l1_n993()
+ fun_l2_n404
+end
+
+def fun_l1_n994()
+ fun_l2_n145
+end
+
+def fun_l1_n995()
+ fun_l2_n684
+end
+
+def fun_l1_n996()
+ fun_l2_n38
+end
+
+def fun_l1_n997()
+ fun_l2_n309
+end
+
+def fun_l1_n998()
+ fun_l2_n560
+end
+
+def fun_l1_n999()
+ fun_l2_n95
+end
+
+def fun_l2_n0()
+ fun_l3_n813
+end
+
+def fun_l2_n1()
+ fun_l3_n785
+end
+
+def fun_l2_n2()
+ fun_l3_n218
+end
+
+def fun_l2_n3()
+ fun_l3_n111
+end
+
+def fun_l2_n4()
+ fun_l3_n581
+end
+
+def fun_l2_n5()
+ fun_l3_n873
+end
+
+def fun_l2_n6()
+ fun_l3_n123
+end
+
+def fun_l2_n7()
+ fun_l3_n576
+end
+
+def fun_l2_n8()
+ fun_l3_n543
+end
+
+def fun_l2_n9()
+ fun_l3_n720
+end
+
+def fun_l2_n10()
+ fun_l3_n970
+end
+
+def fun_l2_n11()
+ fun_l3_n663
+end
+
+def fun_l2_n12()
+ fun_l3_n549
+end
+
+def fun_l2_n13()
+ fun_l3_n787
+end
+
+def fun_l2_n14()
+ fun_l3_n15
+end
+
+def fun_l2_n15()
+ fun_l3_n858
+end
+
+def fun_l2_n16()
+ fun_l3_n873
+end
+
+def fun_l2_n17()
+ fun_l3_n482
+end
+
+def fun_l2_n18()
+ fun_l3_n26
+end
+
+def fun_l2_n19()
+ fun_l3_n591
+end
+
+def fun_l2_n20()
+ fun_l3_n879
+end
+
+def fun_l2_n21()
+ fun_l3_n891
+end
+
+def fun_l2_n22()
+ fun_l3_n381
+end
+
+def fun_l2_n23()
+ fun_l3_n504
+end
+
+def fun_l2_n24()
+ fun_l3_n595
+end
+
+def fun_l2_n25()
+ fun_l3_n985
+end
+
+def fun_l2_n26()
+ fun_l3_n77
+end
+
+def fun_l2_n27()
+ fun_l3_n144
+end
+
+def fun_l2_n28()
+ fun_l3_n912
+end
+
+def fun_l2_n29()
+ fun_l3_n1
+end
+
+def fun_l2_n30()
+ fun_l3_n816
+end
+
+def fun_l2_n31()
+ fun_l3_n246
+end
+
+def fun_l2_n32()
+ fun_l3_n599
+end
+
+def fun_l2_n33()
+ fun_l3_n961
+end
+
+def fun_l2_n34()
+ fun_l3_n392
+end
+
+def fun_l2_n35()
+ fun_l3_n437
+end
+
+def fun_l2_n36()
+ fun_l3_n520
+end
+
+def fun_l2_n37()
+ fun_l3_n146
+end
+
+def fun_l2_n38()
+ fun_l3_n186
+end
+
+def fun_l2_n39()
+ fun_l3_n699
+end
+
+def fun_l2_n40()
+ fun_l3_n863
+end
+
+def fun_l2_n41()
+ fun_l3_n539
+end
+
+def fun_l2_n42()
+ fun_l3_n581
+end
+
+def fun_l2_n43()
+ fun_l3_n325
+end
+
+def fun_l2_n44()
+ fun_l3_n604
+end
+
+def fun_l2_n45()
+ fun_l3_n79
+end
+
+def fun_l2_n46()
+ fun_l3_n530
+end
+
+def fun_l2_n47()
+ fun_l3_n344
+end
+
+def fun_l2_n48()
+ fun_l3_n92
+end
+
+def fun_l2_n49()
+ fun_l3_n826
+end
+
+def fun_l2_n50()
+ fun_l3_n283
+end
+
+def fun_l2_n51()
+ fun_l3_n220
+end
+
+def fun_l2_n52()
+ fun_l3_n96
+end
+
+def fun_l2_n53()
+ fun_l3_n647
+end
+
+def fun_l2_n54()
+ fun_l3_n664
+end
+
+def fun_l2_n55()
+ fun_l3_n718
+end
+
+def fun_l2_n56()
+ fun_l3_n281
+end
+
+def fun_l2_n57()
+ fun_l3_n214
+end
+
+def fun_l2_n58()
+ fun_l3_n143
+end
+
+def fun_l2_n59()
+ fun_l3_n423
+end
+
+def fun_l2_n60()
+ fun_l3_n815
+end
+
+def fun_l2_n61()
+ fun_l3_n561
+end
+
+def fun_l2_n62()
+ fun_l3_n634
+end
+
+def fun_l2_n63()
+ fun_l3_n354
+end
+
+def fun_l2_n64()
+ fun_l3_n39
+end
+
+def fun_l2_n65()
+ fun_l3_n704
+end
+
+def fun_l2_n66()
+ fun_l3_n193
+end
+
+def fun_l2_n67()
+ fun_l3_n267
+end
+
+def fun_l2_n68()
+ fun_l3_n225
+end
+
+def fun_l2_n69()
+ fun_l3_n253
+end
+
+def fun_l2_n70()
+ fun_l3_n97
+end
+
+def fun_l2_n71()
+ fun_l3_n312
+end
+
+def fun_l2_n72()
+ fun_l3_n663
+end
+
+def fun_l2_n73()
+ fun_l3_n730
+end
+
+def fun_l2_n74()
+ fun_l3_n31
+end
+
+def fun_l2_n75()
+ fun_l3_n94
+end
+
+def fun_l2_n76()
+ fun_l3_n719
+end
+
+def fun_l2_n77()
+ fun_l3_n72
+end
+
+def fun_l2_n78()
+ fun_l3_n593
+end
+
+def fun_l2_n79()
+ fun_l3_n586
+end
+
+def fun_l2_n80()
+ fun_l3_n477
+end
+
+def fun_l2_n81()
+ fun_l3_n406
+end
+
+def fun_l2_n82()
+ fun_l3_n624
+end
+
+def fun_l2_n83()
+ fun_l3_n127
+end
+
+def fun_l2_n84()
+ fun_l3_n993
+end
+
+def fun_l2_n85()
+ fun_l3_n764
+end
+
+def fun_l2_n86()
+ fun_l3_n892
+end
+
+def fun_l2_n87()
+ fun_l3_n147
+end
+
+def fun_l2_n88()
+ fun_l3_n971
+end
+
+def fun_l2_n89()
+ fun_l3_n239
+end
+
+def fun_l2_n90()
+ fun_l3_n96
+end
+
+def fun_l2_n91()
+ fun_l3_n686
+end
+
+def fun_l2_n92()
+ fun_l3_n388
+end
+
+def fun_l2_n93()
+ fun_l3_n848
+end
+
+def fun_l2_n94()
+ fun_l3_n415
+end
+
+def fun_l2_n95()
+ fun_l3_n155
+end
+
+def fun_l2_n96()
+ fun_l3_n245
+end
+
+def fun_l2_n97()
+ fun_l3_n103
+end
+
+def fun_l2_n98()
+ fun_l3_n591
+end
+
+def fun_l2_n99()
+ fun_l3_n610
+end
+
+def fun_l2_n100()
+ fun_l3_n925
+end
+
+def fun_l2_n101()
+ fun_l3_n435
+end
+
+def fun_l2_n102()
+ fun_l3_n580
+end
+
+def fun_l2_n103()
+ fun_l3_n116
+end
+
+def fun_l2_n104()
+ fun_l3_n160
+end
+
+def fun_l2_n105()
+ fun_l3_n245
+end
+
+def fun_l2_n106()
+ fun_l3_n970
+end
+
+def fun_l2_n107()
+ fun_l3_n540
+end
+
+def fun_l2_n108()
+ fun_l3_n385
+end
+
+def fun_l2_n109()
+ fun_l3_n292
+end
+
+def fun_l2_n110()
+ fun_l3_n785
+end
+
+def fun_l2_n111()
+ fun_l3_n310
+end
+
+def fun_l2_n112()
+ fun_l3_n983
+end
+
+def fun_l2_n113()
+ fun_l3_n378
+end
+
+def fun_l2_n114()
+ fun_l3_n538
+end
+
+def fun_l2_n115()
+ fun_l3_n161
+end
+
+def fun_l2_n116()
+ fun_l3_n537
+end
+
+def fun_l2_n117()
+ fun_l3_n1
+end
+
+def fun_l2_n118()
+ fun_l3_n606
+end
+
+def fun_l2_n119()
+ fun_l3_n377
+end
+
+def fun_l2_n120()
+ fun_l3_n839
+end
+
+def fun_l2_n121()
+ fun_l3_n174
+end
+
+def fun_l2_n122()
+ fun_l3_n709
+end
+
+def fun_l2_n123()
+ fun_l3_n384
+end
+
+def fun_l2_n124()
+ fun_l3_n566
+end
+
+def fun_l2_n125()
+ fun_l3_n329
+end
+
+def fun_l2_n126()
+ fun_l3_n238
+end
+
+def fun_l2_n127()
+ fun_l3_n366
+end
+
+def fun_l2_n128()
+ fun_l3_n443
+end
+
+def fun_l2_n129()
+ fun_l3_n901
+end
+
+def fun_l2_n130()
+ fun_l3_n16
+end
+
+def fun_l2_n131()
+ fun_l3_n959
+end
+
+def fun_l2_n132()
+ fun_l3_n460
+end
+
+def fun_l2_n133()
+ fun_l3_n26
+end
+
+def fun_l2_n134()
+ fun_l3_n552
+end
+
+def fun_l2_n135()
+ fun_l3_n207
+end
+
+def fun_l2_n136()
+ fun_l3_n804
+end
+
+def fun_l2_n137()
+ fun_l3_n178
+end
+
+def fun_l2_n138()
+ fun_l3_n826
+end
+
+def fun_l2_n139()
+ fun_l3_n421
+end
+
+def fun_l2_n140()
+ fun_l3_n101
+end
+
+def fun_l2_n141()
+ fun_l3_n529
+end
+
+def fun_l2_n142()
+ fun_l3_n594
+end
+
+def fun_l2_n143()
+ fun_l3_n977
+end
+
+def fun_l2_n144()
+ fun_l3_n859
+end
+
+def fun_l2_n145()
+ fun_l3_n24
+end
+
+def fun_l2_n146()
+ fun_l3_n806
+end
+
+def fun_l2_n147()
+ fun_l3_n355
+end
+
+def fun_l2_n148()
+ fun_l3_n648
+end
+
+def fun_l2_n149()
+ fun_l3_n554
+end
+
+def fun_l2_n150()
+ fun_l3_n188
+end
+
+def fun_l2_n151()
+ fun_l3_n711
+end
+
+def fun_l2_n152()
+ fun_l3_n574
+end
+
+def fun_l2_n153()
+ fun_l3_n667
+end
+
+def fun_l2_n154()
+ fun_l3_n638
+end
+
+def fun_l2_n155()
+ fun_l3_n283
+end
+
+def fun_l2_n156()
+ fun_l3_n999
+end
+
+def fun_l2_n157()
+ fun_l3_n412
+end
+
+def fun_l2_n158()
+ fun_l3_n621
+end
+
+def fun_l2_n159()
+ fun_l3_n821
+end
+
+def fun_l2_n160()
+ fun_l3_n857
+end
+
+def fun_l2_n161()
+ fun_l3_n73
+end
+
+def fun_l2_n162()
+ fun_l3_n768
+end
+
+def fun_l2_n163()
+ fun_l3_n929
+end
+
+def fun_l2_n164()
+ fun_l3_n205
+end
+
+def fun_l2_n165()
+ fun_l3_n120
+end
+
+def fun_l2_n166()
+ fun_l3_n787
+end
+
+def fun_l2_n167()
+ fun_l3_n69
+end
+
+def fun_l2_n168()
+ fun_l3_n567
+end
+
+def fun_l2_n169()
+ fun_l3_n106
+end
+
+def fun_l2_n170()
+ fun_l3_n751
+end
+
+def fun_l2_n171()
+ fun_l3_n642
+end
+
+def fun_l2_n172()
+ fun_l3_n744
+end
+
+def fun_l2_n173()
+ fun_l3_n730
+end
+
+def fun_l2_n174()
+ fun_l3_n681
+end
+
+def fun_l2_n175()
+ fun_l3_n493
+end
+
+def fun_l2_n176()
+ fun_l3_n773
+end
+
+def fun_l2_n177()
+ fun_l3_n393
+end
+
+def fun_l2_n178()
+ fun_l3_n702
+end
+
+def fun_l2_n179()
+ fun_l3_n353
+end
+
+def fun_l2_n180()
+ fun_l3_n21
+end
+
+def fun_l2_n181()
+ fun_l3_n575
+end
+
+def fun_l2_n182()
+ fun_l3_n975
+end
+
+def fun_l2_n183()
+ fun_l3_n969
+end
+
+def fun_l2_n184()
+ fun_l3_n8
+end
+
+def fun_l2_n185()
+ fun_l3_n81
+end
+
+def fun_l2_n186()
+ fun_l3_n650
+end
+
+def fun_l2_n187()
+ fun_l3_n257
+end
+
+def fun_l2_n188()
+ fun_l3_n443
+end
+
+def fun_l2_n189()
+ fun_l3_n647
+end
+
+def fun_l2_n190()
+ fun_l3_n783
+end
+
+def fun_l2_n191()
+ fun_l3_n447
+end
+
+def fun_l2_n192()
+ fun_l3_n50
+end
+
+def fun_l2_n193()
+ fun_l3_n25
+end
+
+def fun_l2_n194()
+ fun_l3_n646
+end
+
+def fun_l2_n195()
+ fun_l3_n878
+end
+
+def fun_l2_n196()
+ fun_l3_n156
+end
+
+def fun_l2_n197()
+ fun_l3_n999
+end
+
+def fun_l2_n198()
+ fun_l3_n292
+end
+
+def fun_l2_n199()
+ fun_l3_n386
+end
+
+def fun_l2_n200()
+ fun_l3_n3
+end
+
+def fun_l2_n201()
+ fun_l3_n111
+end
+
+def fun_l2_n202()
+ fun_l3_n89
+end
+
+def fun_l2_n203()
+ fun_l3_n628
+end
+
+def fun_l2_n204()
+ fun_l3_n384
+end
+
+def fun_l2_n205()
+ fun_l3_n951
+end
+
+def fun_l2_n206()
+ fun_l3_n662
+end
+
+def fun_l2_n207()
+ fun_l3_n607
+end
+
+def fun_l2_n208()
+ fun_l3_n245
+end
+
+def fun_l2_n209()
+ fun_l3_n875
+end
+
+def fun_l2_n210()
+ fun_l3_n493
+end
+
+def fun_l2_n211()
+ fun_l3_n639
+end
+
+def fun_l2_n212()
+ fun_l3_n257
+end
+
+def fun_l2_n213()
+ fun_l3_n710
+end
+
+def fun_l2_n214()
+ fun_l3_n848
+end
+
+def fun_l2_n215()
+ fun_l3_n86
+end
+
+def fun_l2_n216()
+ fun_l3_n269
+end
+
+def fun_l2_n217()
+ fun_l3_n907
+end
+
+def fun_l2_n218()
+ fun_l3_n491
+end
+
+def fun_l2_n219()
+ fun_l3_n194
+end
+
+def fun_l2_n220()
+ fun_l3_n204
+end
+
+def fun_l2_n221()
+ fun_l3_n647
+end
+
+def fun_l2_n222()
+ fun_l3_n277
+end
+
+def fun_l2_n223()
+ fun_l3_n687
+end
+
+def fun_l2_n224()
+ fun_l3_n438
+end
+
+def fun_l2_n225()
+ fun_l3_n634
+end
+
+def fun_l2_n226()
+ fun_l3_n826
+end
+
+def fun_l2_n227()
+ fun_l3_n702
+end
+
+def fun_l2_n228()
+ fun_l3_n541
+end
+
+def fun_l2_n229()
+ fun_l3_n741
+end
+
+def fun_l2_n230()
+ fun_l3_n886
+end
+
+def fun_l2_n231()
+ fun_l3_n243
+end
+
+def fun_l2_n232()
+ fun_l3_n313
+end
+
+def fun_l2_n233()
+ fun_l3_n499
+end
+
+def fun_l2_n234()
+ fun_l3_n100
+end
+
+def fun_l2_n235()
+ fun_l3_n958
+end
+
+def fun_l2_n236()
+ fun_l3_n192
+end
+
+def fun_l2_n237()
+ fun_l3_n529
+end
+
+def fun_l2_n238()
+ fun_l3_n761
+end
+
+def fun_l2_n239()
+ fun_l3_n558
+end
+
+def fun_l2_n240()
+ fun_l3_n58
+end
+
+def fun_l2_n241()
+ fun_l3_n65
+end
+
+def fun_l2_n242()
+ fun_l3_n685
+end
+
+def fun_l2_n243()
+ fun_l3_n418
+end
+
+def fun_l2_n244()
+ fun_l3_n206
+end
+
+def fun_l2_n245()
+ fun_l3_n147
+end
+
+def fun_l2_n246()
+ fun_l3_n98
+end
+
+def fun_l2_n247()
+ fun_l3_n104
+end
+
+def fun_l2_n248()
+ fun_l3_n336
+end
+
+def fun_l2_n249()
+ fun_l3_n406
+end
+
+def fun_l2_n250()
+ fun_l3_n835
+end
+
+def fun_l2_n251()
+ fun_l3_n611
+end
+
+def fun_l2_n252()
+ fun_l3_n890
+end
+
+def fun_l2_n253()
+ fun_l3_n272
+end
+
+def fun_l2_n254()
+ fun_l3_n962
+end
+
+def fun_l2_n255()
+ fun_l3_n960
+end
+
+def fun_l2_n256()
+ fun_l3_n675
+end
+
+def fun_l2_n257()
+ fun_l3_n161
+end
+
+def fun_l2_n258()
+ fun_l3_n509
+end
+
+def fun_l2_n259()
+ fun_l3_n36
+end
+
+def fun_l2_n260()
+ fun_l3_n381
+end
+
+def fun_l2_n261()
+ fun_l3_n721
+end
+
+def fun_l2_n262()
+ fun_l3_n807
+end
+
+def fun_l2_n263()
+ fun_l3_n424
+end
+
+def fun_l2_n264()
+ fun_l3_n733
+end
+
+def fun_l2_n265()
+ fun_l3_n417
+end
+
+def fun_l2_n266()
+ fun_l3_n630
+end
+
+def fun_l2_n267()
+ fun_l3_n733
+end
+
+def fun_l2_n268()
+ fun_l3_n797
+end
+
+def fun_l2_n269()
+ fun_l3_n446
+end
+
+def fun_l2_n270()
+ fun_l3_n877
+end
+
+def fun_l2_n271()
+ fun_l3_n64
+end
+
+def fun_l2_n272()
+ fun_l3_n553
+end
+
+def fun_l2_n273()
+ fun_l3_n369
+end
+
+def fun_l2_n274()
+ fun_l3_n261
+end
+
+def fun_l2_n275()
+ fun_l3_n244
+end
+
+def fun_l2_n276()
+ fun_l3_n544
+end
+
+def fun_l2_n277()
+ fun_l3_n779
+end
+
+def fun_l2_n278()
+ fun_l3_n864
+end
+
+def fun_l2_n279()
+ fun_l3_n235
+end
+
+def fun_l2_n280()
+ fun_l3_n343
+end
+
+def fun_l2_n281()
+ fun_l3_n601
+end
+
+def fun_l2_n282()
+ fun_l3_n925
+end
+
+def fun_l2_n283()
+ fun_l3_n822
+end
+
+def fun_l2_n284()
+ fun_l3_n675
+end
+
+def fun_l2_n285()
+ fun_l3_n791
+end
+
+def fun_l2_n286()
+ fun_l3_n359
+end
+
+def fun_l2_n287()
+ fun_l3_n596
+end
+
+def fun_l2_n288()
+ fun_l3_n153
+end
+
+def fun_l2_n289()
+ fun_l3_n420
+end
+
+def fun_l2_n290()
+ fun_l3_n464
+end
+
+def fun_l2_n291()
+ fun_l3_n393
+end
+
+def fun_l2_n292()
+ fun_l3_n614
+end
+
+def fun_l2_n293()
+ fun_l3_n449
+end
+
+def fun_l2_n294()
+ fun_l3_n561
+end
+
+def fun_l2_n295()
+ fun_l3_n119
+end
+
+def fun_l2_n296()
+ fun_l3_n82
+end
+
+def fun_l2_n297()
+ fun_l3_n932
+end
+
+def fun_l2_n298()
+ fun_l3_n505
+end
+
+def fun_l2_n299()
+ fun_l3_n664
+end
+
+def fun_l2_n300()
+ fun_l3_n222
+end
+
+def fun_l2_n301()
+ fun_l3_n428
+end
+
+def fun_l2_n302()
+ fun_l3_n975
+end
+
+def fun_l2_n303()
+ fun_l3_n481
+end
+
+def fun_l2_n304()
+ fun_l3_n263
+end
+
+def fun_l2_n305()
+ fun_l3_n816
+end
+
+def fun_l2_n306()
+ fun_l3_n58
+end
+
+def fun_l2_n307()
+ fun_l3_n89
+end
+
+def fun_l2_n308()
+ fun_l3_n509
+end
+
+def fun_l2_n309()
+ fun_l3_n162
+end
+
+def fun_l2_n310()
+ fun_l3_n222
+end
+
+def fun_l2_n311()
+ fun_l3_n999
+end
+
+def fun_l2_n312()
+ fun_l3_n26
+end
+
+def fun_l2_n313()
+ fun_l3_n857
+end
+
+def fun_l2_n314()
+ fun_l3_n485
+end
+
+def fun_l2_n315()
+ fun_l3_n935
+end
+
+def fun_l2_n316()
+ fun_l3_n159
+end
+
+def fun_l2_n317()
+ fun_l3_n987
+end
+
+def fun_l2_n318()
+ fun_l3_n122
+end
+
+def fun_l2_n319()
+ fun_l3_n675
+end
+
+def fun_l2_n320()
+ fun_l3_n88
+end
+
+def fun_l2_n321()
+ fun_l3_n84
+end
+
+def fun_l2_n322()
+ fun_l3_n17
+end
+
+def fun_l2_n323()
+ fun_l3_n859
+end
+
+def fun_l2_n324()
+ fun_l3_n340
+end
+
+def fun_l2_n325()
+ fun_l3_n122
+end
+
+def fun_l2_n326()
+ fun_l3_n675
+end
+
+def fun_l2_n327()
+ fun_l3_n502
+end
+
+def fun_l2_n328()
+ fun_l3_n56
+end
+
+def fun_l2_n329()
+ fun_l3_n398
+end
+
+def fun_l2_n330()
+ fun_l3_n985
+end
+
+def fun_l2_n331()
+ fun_l3_n117
+end
+
+def fun_l2_n332()
+ fun_l3_n264
+end
+
+def fun_l2_n333()
+ fun_l3_n664
+end
+
+def fun_l2_n334()
+ fun_l3_n958
+end
+
+def fun_l2_n335()
+ fun_l3_n495
+end
+
+def fun_l2_n336()
+ fun_l3_n794
+end
+
+def fun_l2_n337()
+ fun_l3_n95
+end
+
+def fun_l2_n338()
+ fun_l3_n202
+end
+
+def fun_l2_n339()
+ fun_l3_n510
+end
+
+def fun_l2_n340()
+ fun_l3_n919
+end
+
+def fun_l2_n341()
+ fun_l3_n602
+end
+
+def fun_l2_n342()
+ fun_l3_n750
+end
+
+def fun_l2_n343()
+ fun_l3_n122
+end
+
+def fun_l2_n344()
+ fun_l3_n358
+end
+
+def fun_l2_n345()
+ fun_l3_n539
+end
+
+def fun_l2_n346()
+ fun_l3_n67
+end
+
+def fun_l2_n347()
+ fun_l3_n881
+end
+
+def fun_l2_n348()
+ fun_l3_n257
+end
+
+def fun_l2_n349()
+ fun_l3_n987
+end
+
+def fun_l2_n350()
+ fun_l3_n482
+end
+
+def fun_l2_n351()
+ fun_l3_n803
+end
+
+def fun_l2_n352()
+ fun_l3_n172
+end
+
+def fun_l2_n353()
+ fun_l3_n826
+end
+
+def fun_l2_n354()
+ fun_l3_n977
+end
+
+def fun_l2_n355()
+ fun_l3_n976
+end
+
+def fun_l2_n356()
+ fun_l3_n970
+end
+
+def fun_l2_n357()
+ fun_l3_n904
+end
+
+def fun_l2_n358()
+ fun_l3_n735
+end
+
+def fun_l2_n359()
+ fun_l3_n146
+end
+
+def fun_l2_n360()
+ fun_l3_n810
+end
+
+def fun_l2_n361()
+ fun_l3_n591
+end
+
+def fun_l2_n362()
+ fun_l3_n882
+end
+
+def fun_l2_n363()
+ fun_l3_n980
+end
+
+def fun_l2_n364()
+ fun_l3_n594
+end
+
+def fun_l2_n365()
+ fun_l3_n431
+end
+
+def fun_l2_n366()
+ fun_l3_n225
+end
+
+def fun_l2_n367()
+ fun_l3_n11
+end
+
+def fun_l2_n368()
+ fun_l3_n283
+end
+
+def fun_l2_n369()
+ fun_l3_n476
+end
+
+def fun_l2_n370()
+ fun_l3_n382
+end
+
+def fun_l2_n371()
+ fun_l3_n422
+end
+
+def fun_l2_n372()
+ fun_l3_n272
+end
+
+def fun_l2_n373()
+ fun_l3_n911
+end
+
+def fun_l2_n374()
+ fun_l3_n282
+end
+
+def fun_l2_n375()
+ fun_l3_n388
+end
+
+def fun_l2_n376()
+ fun_l3_n928
+end
+
+def fun_l2_n377()
+ fun_l3_n784
+end
+
+def fun_l2_n378()
+ fun_l3_n817
+end
+
+def fun_l2_n379()
+ fun_l3_n799
+end
+
+def fun_l2_n380()
+ fun_l3_n538
+end
+
+def fun_l2_n381()
+ fun_l3_n24
+end
+
+def fun_l2_n382()
+ fun_l3_n726
+end
+
+def fun_l2_n383()
+ fun_l3_n213
+end
+
+def fun_l2_n384()
+ fun_l3_n15
+end
+
+def fun_l2_n385()
+ fun_l3_n915
+end
+
+def fun_l2_n386()
+ fun_l3_n357
+end
+
+def fun_l2_n387()
+ fun_l3_n343
+end
+
+def fun_l2_n388()
+ fun_l3_n258
+end
+
+def fun_l2_n389()
+ fun_l3_n396
+end
+
+def fun_l2_n390()
+ fun_l3_n478
+end
+
+def fun_l2_n391()
+ fun_l3_n122
+end
+
+def fun_l2_n392()
+ fun_l3_n925
+end
+
+def fun_l2_n393()
+ fun_l3_n6
+end
+
+def fun_l2_n394()
+ fun_l3_n251
+end
+
+def fun_l2_n395()
+ fun_l3_n21
+end
+
+def fun_l2_n396()
+ fun_l3_n781
+end
+
+def fun_l2_n397()
+ fun_l3_n765
+end
+
+def fun_l2_n398()
+ fun_l3_n574
+end
+
+def fun_l2_n399()
+ fun_l3_n347
+end
+
+def fun_l2_n400()
+ fun_l3_n409
+end
+
+def fun_l2_n401()
+ fun_l3_n343
+end
+
+def fun_l2_n402()
+ fun_l3_n580
+end
+
+def fun_l2_n403()
+ fun_l3_n878
+end
+
+def fun_l2_n404()
+ fun_l3_n150
+end
+
+def fun_l2_n405()
+ fun_l3_n900
+end
+
+def fun_l2_n406()
+ fun_l3_n19
+end
+
+def fun_l2_n407()
+ fun_l3_n671
+end
+
+def fun_l2_n408()
+ fun_l3_n714
+end
+
+def fun_l2_n409()
+ fun_l3_n865
+end
+
+def fun_l2_n410()
+ fun_l3_n634
+end
+
+def fun_l2_n411()
+ fun_l3_n780
+end
+
+def fun_l2_n412()
+ fun_l3_n404
+end
+
+def fun_l2_n413()
+ fun_l3_n506
+end
+
+def fun_l2_n414()
+ fun_l3_n503
+end
+
+def fun_l2_n415()
+ fun_l3_n120
+end
+
+def fun_l2_n416()
+ fun_l3_n603
+end
+
+def fun_l2_n417()
+ fun_l3_n263
+end
+
+def fun_l2_n418()
+ fun_l3_n142
+end
+
+def fun_l2_n419()
+ fun_l3_n174
+end
+
+def fun_l2_n420()
+ fun_l3_n474
+end
+
+def fun_l2_n421()
+ fun_l3_n980
+end
+
+def fun_l2_n422()
+ fun_l3_n302
+end
+
+def fun_l2_n423()
+ fun_l3_n850
+end
+
+def fun_l2_n424()
+ fun_l3_n395
+end
+
+def fun_l2_n425()
+ fun_l3_n49
+end
+
+def fun_l2_n426()
+ fun_l3_n732
+end
+
+def fun_l2_n427()
+ fun_l3_n473
+end
+
+def fun_l2_n428()
+ fun_l3_n906
+end
+
+def fun_l2_n429()
+ fun_l3_n120
+end
+
+def fun_l2_n430()
+ fun_l3_n818
+end
+
+def fun_l2_n431()
+ fun_l3_n177
+end
+
+def fun_l2_n432()
+ fun_l3_n47
+end
+
+def fun_l2_n433()
+ fun_l3_n423
+end
+
+def fun_l2_n434()
+ fun_l3_n435
+end
+
+def fun_l2_n435()
+ fun_l3_n748
+end
+
+def fun_l2_n436()
+ fun_l3_n953
+end
+
+def fun_l2_n437()
+ fun_l3_n78
+end
+
+def fun_l2_n438()
+ fun_l3_n184
+end
+
+def fun_l2_n439()
+ fun_l3_n533
+end
+
+def fun_l2_n440()
+ fun_l3_n184
+end
+
+def fun_l2_n441()
+ fun_l3_n698
+end
+
+def fun_l2_n442()
+ fun_l3_n752
+end
+
+def fun_l2_n443()
+ fun_l3_n448
+end
+
+def fun_l2_n444()
+ fun_l3_n307
+end
+
+def fun_l2_n445()
+ fun_l3_n333
+end
+
+def fun_l2_n446()
+ fun_l3_n237
+end
+
+def fun_l2_n447()
+ fun_l3_n550
+end
+
+def fun_l2_n448()
+ fun_l3_n951
+end
+
+def fun_l2_n449()
+ fun_l3_n341
+end
+
+def fun_l2_n450()
+ fun_l3_n188
+end
+
+def fun_l2_n451()
+ fun_l3_n505
+end
+
+def fun_l2_n452()
+ fun_l3_n779
+end
+
+def fun_l2_n453()
+ fun_l3_n368
+end
+
+def fun_l2_n454()
+ fun_l3_n191
+end
+
+def fun_l2_n455()
+ fun_l3_n952
+end
+
+def fun_l2_n456()
+ fun_l3_n472
+end
+
+def fun_l2_n457()
+ fun_l3_n294
+end
+
+def fun_l2_n458()
+ fun_l3_n280
+end
+
+def fun_l2_n459()
+ fun_l3_n794
+end
+
+def fun_l2_n460()
+ fun_l3_n780
+end
+
+def fun_l2_n461()
+ fun_l3_n527
+end
+
+def fun_l2_n462()
+ fun_l3_n129
+end
+
+def fun_l2_n463()
+ fun_l3_n365
+end
+
+def fun_l2_n464()
+ fun_l3_n898
+end
+
+def fun_l2_n465()
+ fun_l3_n932
+end
+
+def fun_l2_n466()
+ fun_l3_n616
+end
+
+def fun_l2_n467()
+ fun_l3_n828
+end
+
+def fun_l2_n468()
+ fun_l3_n660
+end
+
+def fun_l2_n469()
+ fun_l3_n255
+end
+
+def fun_l2_n470()
+ fun_l3_n845
+end
+
+def fun_l2_n471()
+ fun_l3_n347
+end
+
+def fun_l2_n472()
+ fun_l3_n154
+end
+
+def fun_l2_n473()
+ fun_l3_n349
+end
+
+def fun_l2_n474()
+ fun_l3_n276
+end
+
+def fun_l2_n475()
+ fun_l3_n962
+end
+
+def fun_l2_n476()
+ fun_l3_n195
+end
+
+def fun_l2_n477()
+ fun_l3_n648
+end
+
+def fun_l2_n478()
+ fun_l3_n692
+end
+
+def fun_l2_n479()
+ fun_l3_n294
+end
+
+def fun_l2_n480()
+ fun_l3_n144
+end
+
+def fun_l2_n481()
+ fun_l3_n702
+end
+
+def fun_l2_n482()
+ fun_l3_n110
+end
+
+def fun_l2_n483()
+ fun_l3_n169
+end
+
+def fun_l2_n484()
+ fun_l3_n140
+end
+
+def fun_l2_n485()
+ fun_l3_n614
+end
+
+def fun_l2_n486()
+ fun_l3_n309
+end
+
+def fun_l2_n487()
+ fun_l3_n792
+end
+
+def fun_l2_n488()
+ fun_l3_n465
+end
+
+def fun_l2_n489()
+ fun_l3_n892
+end
+
+def fun_l2_n490()
+ fun_l3_n205
+end
+
+def fun_l2_n491()
+ fun_l3_n267
+end
+
+def fun_l2_n492()
+ fun_l3_n743
+end
+
+def fun_l2_n493()
+ fun_l3_n669
+end
+
+def fun_l2_n494()
+ fun_l3_n882
+end
+
+def fun_l2_n495()
+ fun_l3_n654
+end
+
+def fun_l2_n496()
+ fun_l3_n885
+end
+
+def fun_l2_n497()
+ fun_l3_n955
+end
+
+def fun_l2_n498()
+ fun_l3_n251
+end
+
+def fun_l2_n499()
+ fun_l3_n521
+end
+
+def fun_l2_n500()
+ fun_l3_n484
+end
+
+def fun_l2_n501()
+ fun_l3_n525
+end
+
+def fun_l2_n502()
+ fun_l3_n493
+end
+
+def fun_l2_n503()
+ fun_l3_n161
+end
+
+def fun_l2_n504()
+ fun_l3_n447
+end
+
+def fun_l2_n505()
+ fun_l3_n339
+end
+
+def fun_l2_n506()
+ fun_l3_n946
+end
+
+def fun_l2_n507()
+ fun_l3_n564
+end
+
+def fun_l2_n508()
+ fun_l3_n586
+end
+
+def fun_l2_n509()
+ fun_l3_n345
+end
+
+def fun_l2_n510()
+ fun_l3_n814
+end
+
+def fun_l2_n511()
+ fun_l3_n946
+end
+
+def fun_l2_n512()
+ fun_l3_n629
+end
+
+def fun_l2_n513()
+ fun_l3_n726
+end
+
+def fun_l2_n514()
+ fun_l3_n91
+end
+
+def fun_l2_n515()
+ fun_l3_n393
+end
+
+def fun_l2_n516()
+ fun_l3_n620
+end
+
+def fun_l2_n517()
+ fun_l3_n907
+end
+
+def fun_l2_n518()
+ fun_l3_n911
+end
+
+def fun_l2_n519()
+ fun_l3_n361
+end
+
+def fun_l2_n520()
+ fun_l3_n420
+end
+
+def fun_l2_n521()
+ fun_l3_n479
+end
+
+def fun_l2_n522()
+ fun_l3_n686
+end
+
+def fun_l2_n523()
+ fun_l3_n888
+end
+
+def fun_l2_n524()
+ fun_l3_n141
+end
+
+def fun_l2_n525()
+ fun_l3_n830
+end
+
+def fun_l2_n526()
+ fun_l3_n681
+end
+
+def fun_l2_n527()
+ fun_l3_n58
+end
+
+def fun_l2_n528()
+ fun_l3_n835
+end
+
+def fun_l2_n529()
+ fun_l3_n390
+end
+
+def fun_l2_n530()
+ fun_l3_n930
+end
+
+def fun_l2_n531()
+ fun_l3_n569
+end
+
+def fun_l2_n532()
+ fun_l3_n943
+end
+
+def fun_l2_n533()
+ fun_l3_n888
+end
+
+def fun_l2_n534()
+ fun_l3_n220
+end
+
+def fun_l2_n535()
+ fun_l3_n809
+end
+
+def fun_l2_n536()
+ fun_l3_n382
+end
+
+def fun_l2_n537()
+ fun_l3_n356
+end
+
+def fun_l2_n538()
+ fun_l3_n912
+end
+
+def fun_l2_n539()
+ fun_l3_n151
+end
+
+def fun_l2_n540()
+ fun_l3_n740
+end
+
+def fun_l2_n541()
+ fun_l3_n925
+end
+
+def fun_l2_n542()
+ fun_l3_n776
+end
+
+def fun_l2_n543()
+ fun_l3_n4
+end
+
+def fun_l2_n544()
+ fun_l3_n549
+end
+
+def fun_l2_n545()
+ fun_l3_n220
+end
+
+def fun_l2_n546()
+ fun_l3_n932
+end
+
+def fun_l2_n547()
+ fun_l3_n267
+end
+
+def fun_l2_n548()
+ fun_l3_n646
+end
+
+def fun_l2_n549()
+ fun_l3_n217
+end
+
+def fun_l2_n550()
+ fun_l3_n217
+end
+
+def fun_l2_n551()
+ fun_l3_n197
+end
+
+def fun_l2_n552()
+ fun_l3_n419
+end
+
+def fun_l2_n553()
+ fun_l3_n232
+end
+
+def fun_l2_n554()
+ fun_l3_n327
+end
+
+def fun_l2_n555()
+ fun_l3_n201
+end
+
+def fun_l2_n556()
+ fun_l3_n567
+end
+
+def fun_l2_n557()
+ fun_l3_n870
+end
+
+def fun_l2_n558()
+ fun_l3_n222
+end
+
+def fun_l2_n559()
+ fun_l3_n792
+end
+
+def fun_l2_n560()
+ fun_l3_n157
+end
+
+def fun_l2_n561()
+ fun_l3_n870
+end
+
+def fun_l2_n562()
+ fun_l3_n564
+end
+
+def fun_l2_n563()
+ fun_l3_n571
+end
+
+def fun_l2_n564()
+ fun_l3_n211
+end
+
+def fun_l2_n565()
+ fun_l3_n657
+end
+
+def fun_l2_n566()
+ fun_l3_n869
+end
+
+def fun_l2_n567()
+ fun_l3_n288
+end
+
+def fun_l2_n568()
+ fun_l3_n736
+end
+
+def fun_l2_n569()
+ fun_l3_n273
+end
+
+def fun_l2_n570()
+ fun_l3_n194
+end
+
+def fun_l2_n571()
+ fun_l3_n435
+end
+
+def fun_l2_n572()
+ fun_l3_n775
+end
+
+def fun_l2_n573()
+ fun_l3_n342
+end
+
+def fun_l2_n574()
+ fun_l3_n843
+end
+
+def fun_l2_n575()
+ fun_l3_n585
+end
+
+def fun_l2_n576()
+ fun_l3_n518
+end
+
+def fun_l2_n577()
+ fun_l3_n524
+end
+
+def fun_l2_n578()
+ fun_l3_n457
+end
+
+def fun_l2_n579()
+ fun_l3_n905
+end
+
+def fun_l2_n580()
+ fun_l3_n346
+end
+
+def fun_l2_n581()
+ fun_l3_n412
+end
+
+def fun_l2_n582()
+ fun_l3_n970
+end
+
+def fun_l2_n583()
+ fun_l3_n648
+end
+
+def fun_l2_n584()
+ fun_l3_n870
+end
+
+def fun_l2_n585()
+ fun_l3_n783
+end
+
+def fun_l2_n586()
+ fun_l3_n856
+end
+
+def fun_l2_n587()
+ fun_l3_n708
+end
+
+def fun_l2_n588()
+ fun_l3_n473
+end
+
+def fun_l2_n589()
+ fun_l3_n277
+end
+
+def fun_l2_n590()
+ fun_l3_n112
+end
+
+def fun_l2_n591()
+ fun_l3_n785
+end
+
+def fun_l2_n592()
+ fun_l3_n283
+end
+
+def fun_l2_n593()
+ fun_l3_n720
+end
+
+def fun_l2_n594()
+ fun_l3_n195
+end
+
+def fun_l2_n595()
+ fun_l3_n923
+end
+
+def fun_l2_n596()
+ fun_l3_n306
+end
+
+def fun_l2_n597()
+ fun_l3_n108
+end
+
+def fun_l2_n598()
+ fun_l3_n615
+end
+
+def fun_l2_n599()
+ fun_l3_n135
+end
+
+def fun_l2_n600()
+ fun_l3_n710
+end
+
+def fun_l2_n601()
+ fun_l3_n722
+end
+
+def fun_l2_n602()
+ fun_l3_n943
+end
+
+def fun_l2_n603()
+ fun_l3_n626
+end
+
+def fun_l2_n604()
+ fun_l3_n702
+end
+
+def fun_l2_n605()
+ fun_l3_n812
+end
+
+def fun_l2_n606()
+ fun_l3_n551
+end
+
+def fun_l2_n607()
+ fun_l3_n497
+end
+
+def fun_l2_n608()
+ fun_l3_n123
+end
+
+def fun_l2_n609()
+ fun_l3_n302
+end
+
+def fun_l2_n610()
+ fun_l3_n850
+end
+
+def fun_l2_n611()
+ fun_l3_n327
+end
+
+def fun_l2_n612()
+ fun_l3_n529
+end
+
+def fun_l2_n613()
+ fun_l3_n441
+end
+
+def fun_l2_n614()
+ fun_l3_n26
+end
+
+def fun_l2_n615()
+ fun_l3_n275
+end
+
+def fun_l2_n616()
+ fun_l3_n211
+end
+
+def fun_l2_n617()
+ fun_l3_n253
+end
+
+def fun_l2_n618()
+ fun_l3_n767
+end
+
+def fun_l2_n619()
+ fun_l3_n601
+end
+
+def fun_l2_n620()
+ fun_l3_n350
+end
+
+def fun_l2_n621()
+ fun_l3_n407
+end
+
+def fun_l2_n622()
+ fun_l3_n12
+end
+
+def fun_l2_n623()
+ fun_l3_n378
+end
+
+def fun_l2_n624()
+ fun_l3_n159
+end
+
+def fun_l2_n625()
+ fun_l3_n521
+end
+
+def fun_l2_n626()
+ fun_l3_n657
+end
+
+def fun_l2_n627()
+ fun_l3_n997
+end
+
+def fun_l2_n628()
+ fun_l3_n504
+end
+
+def fun_l2_n629()
+ fun_l3_n177
+end
+
+def fun_l2_n630()
+ fun_l3_n352
+end
+
+def fun_l2_n631()
+ fun_l3_n579
+end
+
+def fun_l2_n632()
+ fun_l3_n607
+end
+
+def fun_l2_n633()
+ fun_l3_n430
+end
+
+def fun_l2_n634()
+ fun_l3_n437
+end
+
+def fun_l2_n635()
+ fun_l3_n495
+end
+
+def fun_l2_n636()
+ fun_l3_n247
+end
+
+def fun_l2_n637()
+ fun_l3_n68
+end
+
+def fun_l2_n638()
+ fun_l3_n815
+end
+
+def fun_l2_n639()
+ fun_l3_n477
+end
+
+def fun_l2_n640()
+ fun_l3_n894
+end
+
+def fun_l2_n641()
+ fun_l3_n804
+end
+
+def fun_l2_n642()
+ fun_l3_n198
+end
+
+def fun_l2_n643()
+ fun_l3_n676
+end
+
+def fun_l2_n644()
+ fun_l3_n306
+end
+
+def fun_l2_n645()
+ fun_l3_n545
+end
+
+def fun_l2_n646()
+ fun_l3_n519
+end
+
+def fun_l2_n647()
+ fun_l3_n328
+end
+
+def fun_l2_n648()
+ fun_l3_n654
+end
+
+def fun_l2_n649()
+ fun_l3_n879
+end
+
+def fun_l2_n650()
+ fun_l3_n224
+end
+
+def fun_l2_n651()
+ fun_l3_n826
+end
+
+def fun_l2_n652()
+ fun_l3_n976
+end
+
+def fun_l2_n653()
+ fun_l3_n287
+end
+
+def fun_l2_n654()
+ fun_l3_n471
+end
+
+def fun_l2_n655()
+ fun_l3_n738
+end
+
+def fun_l2_n656()
+ fun_l3_n545
+end
+
+def fun_l2_n657()
+ fun_l3_n819
+end
+
+def fun_l2_n658()
+ fun_l3_n866
+end
+
+def fun_l2_n659()
+ fun_l3_n215
+end
+
+def fun_l2_n660()
+ fun_l3_n656
+end
+
+def fun_l2_n661()
+ fun_l3_n519
+end
+
+def fun_l2_n662()
+ fun_l3_n812
+end
+
+def fun_l2_n663()
+ fun_l3_n241
+end
+
+def fun_l2_n664()
+ fun_l3_n245
+end
+
+def fun_l2_n665()
+ fun_l3_n60
+end
+
+def fun_l2_n666()
+ fun_l3_n516
+end
+
+def fun_l2_n667()
+ fun_l3_n264
+end
+
+def fun_l2_n668()
+ fun_l3_n254
+end
+
+def fun_l2_n669()
+ fun_l3_n952
+end
+
+def fun_l2_n670()
+ fun_l3_n928
+end
+
+def fun_l2_n671()
+ fun_l3_n718
+end
+
+def fun_l2_n672()
+ fun_l3_n937
+end
+
+def fun_l2_n673()
+ fun_l3_n549
+end
+
+def fun_l2_n674()
+ fun_l3_n138
+end
+
+def fun_l2_n675()
+ fun_l3_n441
+end
+
+def fun_l2_n676()
+ fun_l3_n641
+end
+
+def fun_l2_n677()
+ fun_l3_n611
+end
+
+def fun_l2_n678()
+ fun_l3_n711
+end
+
+def fun_l2_n679()
+ fun_l3_n60
+end
+
+def fun_l2_n680()
+ fun_l3_n894
+end
+
+def fun_l2_n681()
+ fun_l3_n957
+end
+
+def fun_l2_n682()
+ fun_l3_n516
+end
+
+def fun_l2_n683()
+ fun_l3_n348
+end
+
+def fun_l2_n684()
+ fun_l3_n600
+end
+
+def fun_l2_n685()
+ fun_l3_n955
+end
+
+def fun_l2_n686()
+ fun_l3_n842
+end
+
+def fun_l2_n687()
+ fun_l3_n126
+end
+
+def fun_l2_n688()
+ fun_l3_n739
+end
+
+def fun_l2_n689()
+ fun_l3_n435
+end
+
+def fun_l2_n690()
+ fun_l3_n445
+end
+
+def fun_l2_n691()
+ fun_l3_n973
+end
+
+def fun_l2_n692()
+ fun_l3_n54
+end
+
+def fun_l2_n693()
+ fun_l3_n629
+end
+
+def fun_l2_n694()
+ fun_l3_n83
+end
+
+def fun_l2_n695()
+ fun_l3_n887
+end
+
+def fun_l2_n696()
+ fun_l3_n552
+end
+
+def fun_l2_n697()
+ fun_l3_n263
+end
+
+def fun_l2_n698()
+ fun_l3_n532
+end
+
+def fun_l2_n699()
+ fun_l3_n462
+end
+
+def fun_l2_n700()
+ fun_l3_n319
+end
+
+def fun_l2_n701()
+ fun_l3_n464
+end
+
+def fun_l2_n702()
+ fun_l3_n340
+end
+
+def fun_l2_n703()
+ fun_l3_n188
+end
+
+def fun_l2_n704()
+ fun_l3_n157
+end
+
+def fun_l2_n705()
+ fun_l3_n345
+end
+
+def fun_l2_n706()
+ fun_l3_n637
+end
+
+def fun_l2_n707()
+ fun_l3_n157
+end
+
+def fun_l2_n708()
+ fun_l3_n270
+end
+
+def fun_l2_n709()
+ fun_l3_n13
+end
+
+def fun_l2_n710()
+ fun_l3_n360
+end
+
+def fun_l2_n711()
+ fun_l3_n890
+end
+
+def fun_l2_n712()
+ fun_l3_n539
+end
+
+def fun_l2_n713()
+ fun_l3_n582
+end
+
+def fun_l2_n714()
+ fun_l3_n466
+end
+
+def fun_l2_n715()
+ fun_l3_n623
+end
+
+def fun_l2_n716()
+ fun_l3_n995
+end
+
+def fun_l2_n717()
+ fun_l3_n810
+end
+
+def fun_l2_n718()
+ fun_l3_n95
+end
+
+def fun_l2_n719()
+ fun_l3_n103
+end
+
+def fun_l2_n720()
+ fun_l3_n755
+end
+
+def fun_l2_n721()
+ fun_l3_n858
+end
+
+def fun_l2_n722()
+ fun_l3_n519
+end
+
+def fun_l2_n723()
+ fun_l3_n489
+end
+
+def fun_l2_n724()
+ fun_l3_n578
+end
+
+def fun_l2_n725()
+ fun_l3_n176
+end
+
+def fun_l2_n726()
+ fun_l3_n58
+end
+
+def fun_l2_n727()
+ fun_l3_n817
+end
+
+def fun_l2_n728()
+ fun_l3_n612
+end
+
+def fun_l2_n729()
+ fun_l3_n510
+end
+
+def fun_l2_n730()
+ fun_l3_n934
+end
+
+def fun_l2_n731()
+ fun_l3_n691
+end
+
+def fun_l2_n732()
+ fun_l3_n697
+end
+
+def fun_l2_n733()
+ fun_l3_n667
+end
+
+def fun_l2_n734()
+ fun_l3_n49
+end
+
+def fun_l2_n735()
+ fun_l3_n113
+end
+
+def fun_l2_n736()
+ fun_l3_n157
+end
+
+def fun_l2_n737()
+ fun_l3_n756
+end
+
+def fun_l2_n738()
+ fun_l3_n888
+end
+
+def fun_l2_n739()
+ fun_l3_n847
+end
+
+def fun_l2_n740()
+ fun_l3_n693
+end
+
+def fun_l2_n741()
+ fun_l3_n116
+end
+
+def fun_l2_n742()
+ fun_l3_n95
+end
+
+def fun_l2_n743()
+ fun_l3_n662
+end
+
+def fun_l2_n744()
+ fun_l3_n744
+end
+
+def fun_l2_n745()
+ fun_l3_n800
+end
+
+def fun_l2_n746()
+ fun_l3_n732
+end
+
+def fun_l2_n747()
+ fun_l3_n278
+end
+
+def fun_l2_n748()
+ fun_l3_n441
+end
+
+def fun_l2_n749()
+ fun_l3_n838
+end
+
+def fun_l2_n750()
+ fun_l3_n616
+end
+
+def fun_l2_n751()
+ fun_l3_n438
+end
+
+def fun_l2_n752()
+ fun_l3_n271
+end
+
+def fun_l2_n753()
+ fun_l3_n527
+end
+
+def fun_l2_n754()
+ fun_l3_n568
+end
+
+def fun_l2_n755()
+ fun_l3_n584
+end
+
+def fun_l2_n756()
+ fun_l3_n514
+end
+
+def fun_l2_n757()
+ fun_l3_n599
+end
+
+def fun_l2_n758()
+ fun_l3_n878
+end
+
+def fun_l2_n759()
+ fun_l3_n314
+end
+
+def fun_l2_n760()
+ fun_l3_n277
+end
+
+def fun_l2_n761()
+ fun_l3_n296
+end
+
+def fun_l2_n762()
+ fun_l3_n729
+end
+
+def fun_l2_n763()
+ fun_l3_n192
+end
+
+def fun_l2_n764()
+ fun_l3_n549
+end
+
+def fun_l2_n765()
+ fun_l3_n304
+end
+
+def fun_l2_n766()
+ fun_l3_n133
+end
+
+def fun_l2_n767()
+ fun_l3_n678
+end
+
+def fun_l2_n768()
+ fun_l3_n608
+end
+
+def fun_l2_n769()
+ fun_l3_n830
+end
+
+def fun_l2_n770()
+ fun_l3_n419
+end
+
+def fun_l2_n771()
+ fun_l3_n174
+end
+
+def fun_l2_n772()
+ fun_l3_n806
+end
+
+def fun_l2_n773()
+ fun_l3_n257
+end
+
+def fun_l2_n774()
+ fun_l3_n203
+end
+
+def fun_l2_n775()
+ fun_l3_n572
+end
+
+def fun_l2_n776()
+ fun_l3_n665
+end
+
+def fun_l2_n777()
+ fun_l3_n417
+end
+
+def fun_l2_n778()
+ fun_l3_n44
+end
+
+def fun_l2_n779()
+ fun_l3_n202
+end
+
+def fun_l2_n780()
+ fun_l3_n343
+end
+
+def fun_l2_n781()
+ fun_l3_n343
+end
+
+def fun_l2_n782()
+ fun_l3_n57
+end
+
+def fun_l2_n783()
+ fun_l3_n836
+end
+
+def fun_l2_n784()
+ fun_l3_n634
+end
+
+def fun_l2_n785()
+ fun_l3_n788
+end
+
+def fun_l2_n786()
+ fun_l3_n541
+end
+
+def fun_l2_n787()
+ fun_l3_n906
+end
+
+def fun_l2_n788()
+ fun_l3_n12
+end
+
+def fun_l2_n789()
+ fun_l3_n682
+end
+
+def fun_l2_n790()
+ fun_l3_n80
+end
+
+def fun_l2_n791()
+ fun_l3_n594
+end
+
+def fun_l2_n792()
+ fun_l3_n120
+end
+
+def fun_l2_n793()
+ fun_l3_n551
+end
+
+def fun_l2_n794()
+ fun_l3_n164
+end
+
+def fun_l2_n795()
+ fun_l3_n817
+end
+
+def fun_l2_n796()
+ fun_l3_n611
+end
+
+def fun_l2_n797()
+ fun_l3_n878
+end
+
+def fun_l2_n798()
+ fun_l3_n235
+end
+
+def fun_l2_n799()
+ fun_l3_n210
+end
+
+def fun_l2_n800()
+ fun_l3_n343
+end
+
+def fun_l2_n801()
+ fun_l3_n445
+end
+
+def fun_l2_n802()
+ fun_l3_n549
+end
+
+def fun_l2_n803()
+ fun_l3_n992
+end
+
+def fun_l2_n804()
+ fun_l3_n751
+end
+
+def fun_l2_n805()
+ fun_l3_n514
+end
+
+def fun_l2_n806()
+ fun_l3_n593
+end
+
+def fun_l2_n807()
+ fun_l3_n876
+end
+
+def fun_l2_n808()
+ fun_l3_n612
+end
+
+def fun_l2_n809()
+ fun_l3_n184
+end
+
+def fun_l2_n810()
+ fun_l3_n34
+end
+
+def fun_l2_n811()
+ fun_l3_n703
+end
+
+def fun_l2_n812()
+ fun_l3_n296
+end
+
+def fun_l2_n813()
+ fun_l3_n815
+end
+
+def fun_l2_n814()
+ fun_l3_n417
+end
+
+def fun_l2_n815()
+ fun_l3_n230
+end
+
+def fun_l2_n816()
+ fun_l3_n140
+end
+
+def fun_l2_n817()
+ fun_l3_n772
+end
+
+def fun_l2_n818()
+ fun_l3_n671
+end
+
+def fun_l2_n819()
+ fun_l3_n670
+end
+
+def fun_l2_n820()
+ fun_l3_n286
+end
+
+def fun_l2_n821()
+ fun_l3_n406
+end
+
+def fun_l2_n822()
+ fun_l3_n757
+end
+
+def fun_l2_n823()
+ fun_l3_n995
+end
+
+def fun_l2_n824()
+ fun_l3_n816
+end
+
+def fun_l2_n825()
+ fun_l3_n624
+end
+
+def fun_l2_n826()
+ fun_l3_n625
+end
+
+def fun_l2_n827()
+ fun_l3_n559
+end
+
+def fun_l2_n828()
+ fun_l3_n224
+end
+
+def fun_l2_n829()
+ fun_l3_n437
+end
+
+def fun_l2_n830()
+ fun_l3_n745
+end
+
+def fun_l2_n831()
+ fun_l3_n289
+end
+
+def fun_l2_n832()
+ fun_l3_n555
+end
+
+def fun_l2_n833()
+ fun_l3_n477
+end
+
+def fun_l2_n834()
+ fun_l3_n545
+end
+
+def fun_l2_n835()
+ fun_l3_n87
+end
+
+def fun_l2_n836()
+ fun_l3_n100
+end
+
+def fun_l2_n837()
+ fun_l3_n796
+end
+
+def fun_l2_n838()
+ fun_l3_n166
+end
+
+def fun_l2_n839()
+ fun_l3_n91
+end
+
+def fun_l2_n840()
+ fun_l3_n325
+end
+
+def fun_l2_n841()
+ fun_l3_n717
+end
+
+def fun_l2_n842()
+ fun_l3_n522
+end
+
+def fun_l2_n843()
+ fun_l3_n560
+end
+
+def fun_l2_n844()
+ fun_l3_n811
+end
+
+def fun_l2_n845()
+ fun_l3_n451
+end
+
+def fun_l2_n846()
+ fun_l3_n45
+end
+
+def fun_l2_n847()
+ fun_l3_n410
+end
+
+def fun_l2_n848()
+ fun_l3_n976
+end
+
+def fun_l2_n849()
+ fun_l3_n873
+end
+
+def fun_l2_n850()
+ fun_l3_n302
+end
+
+def fun_l2_n851()
+ fun_l3_n346
+end
+
+def fun_l2_n852()
+ fun_l3_n314
+end
+
+def fun_l2_n853()
+ fun_l3_n829
+end
+
+def fun_l2_n854()
+ fun_l3_n259
+end
+
+def fun_l2_n855()
+ fun_l3_n799
+end
+
+def fun_l2_n856()
+ fun_l3_n451
+end
+
+def fun_l2_n857()
+ fun_l3_n154
+end
+
+def fun_l2_n858()
+ fun_l3_n867
+end
+
+def fun_l2_n859()
+ fun_l3_n806
+end
+
+def fun_l2_n860()
+ fun_l3_n138
+end
+
+def fun_l2_n861()
+ fun_l3_n508
+end
+
+def fun_l2_n862()
+ fun_l3_n627
+end
+
+def fun_l2_n863()
+ fun_l3_n931
+end
+
+def fun_l2_n864()
+ fun_l3_n95
+end
+
+def fun_l2_n865()
+ fun_l3_n533
+end
+
+def fun_l2_n866()
+ fun_l3_n425
+end
+
+def fun_l2_n867()
+ fun_l3_n996
+end
+
+def fun_l2_n868()
+ fun_l3_n331
+end
+
+def fun_l2_n869()
+ fun_l3_n126
+end
+
+def fun_l2_n870()
+ fun_l3_n848
+end
+
+def fun_l2_n871()
+ fun_l3_n174
+end
+
+def fun_l2_n872()
+ fun_l3_n867
+end
+
+def fun_l2_n873()
+ fun_l3_n800
+end
+
+def fun_l2_n874()
+ fun_l3_n526
+end
+
+def fun_l2_n875()
+ fun_l3_n250
+end
+
+def fun_l2_n876()
+ fun_l3_n896
+end
+
+def fun_l2_n877()
+ fun_l3_n229
+end
+
+def fun_l2_n878()
+ fun_l3_n290
+end
+
+def fun_l2_n879()
+ fun_l3_n130
+end
+
+def fun_l2_n880()
+ fun_l3_n437
+end
+
+def fun_l2_n881()
+ fun_l3_n654
+end
+
+def fun_l2_n882()
+ fun_l3_n93
+end
+
+def fun_l2_n883()
+ fun_l3_n632
+end
+
+def fun_l2_n884()
+ fun_l3_n772
+end
+
+def fun_l2_n885()
+ fun_l3_n597
+end
+
+def fun_l2_n886()
+ fun_l3_n668
+end
+
+def fun_l2_n887()
+ fun_l3_n969
+end
+
+def fun_l2_n888()
+ fun_l3_n908
+end
+
+def fun_l2_n889()
+ fun_l3_n10
+end
+
+def fun_l2_n890()
+ fun_l3_n676
+end
+
+def fun_l2_n891()
+ fun_l3_n729
+end
+
+def fun_l2_n892()
+ fun_l3_n659
+end
+
+def fun_l2_n893()
+ fun_l3_n121
+end
+
+def fun_l2_n894()
+ fun_l3_n543
+end
+
+def fun_l2_n895()
+ fun_l3_n931
+end
+
+def fun_l2_n896()
+ fun_l3_n64
+end
+
+def fun_l2_n897()
+ fun_l3_n500
+end
+
+def fun_l2_n898()
+ fun_l3_n664
+end
+
+def fun_l2_n899()
+ fun_l3_n929
+end
+
+def fun_l2_n900()
+ fun_l3_n772
+end
+
+def fun_l2_n901()
+ fun_l3_n309
+end
+
+def fun_l2_n902()
+ fun_l3_n284
+end
+
+def fun_l2_n903()
+ fun_l3_n304
+end
+
+def fun_l2_n904()
+ fun_l3_n18
+end
+
+def fun_l2_n905()
+ fun_l3_n715
+end
+
+def fun_l2_n906()
+ fun_l3_n469
+end
+
+def fun_l2_n907()
+ fun_l3_n524
+end
+
+def fun_l2_n908()
+ fun_l3_n476
+end
+
+def fun_l2_n909()
+ fun_l3_n90
+end
+
+def fun_l2_n910()
+ fun_l3_n471
+end
+
+def fun_l2_n911()
+ fun_l3_n885
+end
+
+def fun_l2_n912()
+ fun_l3_n696
+end
+
+def fun_l2_n913()
+ fun_l3_n393
+end
+
+def fun_l2_n914()
+ fun_l3_n987
+end
+
+def fun_l2_n915()
+ fun_l3_n830
+end
+
+def fun_l2_n916()
+ fun_l3_n684
+end
+
+def fun_l2_n917()
+ fun_l3_n379
+end
+
+def fun_l2_n918()
+ fun_l3_n237
+end
+
+def fun_l2_n919()
+ fun_l3_n115
+end
+
+def fun_l2_n920()
+ fun_l3_n499
+end
+
+def fun_l2_n921()
+ fun_l3_n88
+end
+
+def fun_l2_n922()
+ fun_l3_n563
+end
+
+def fun_l2_n923()
+ fun_l3_n280
+end
+
+def fun_l2_n924()
+ fun_l3_n400
+end
+
+def fun_l2_n925()
+ fun_l3_n750
+end
+
+def fun_l2_n926()
+ fun_l3_n429
+end
+
+def fun_l2_n927()
+ fun_l3_n669
+end
+
+def fun_l2_n928()
+ fun_l3_n275
+end
+
+def fun_l2_n929()
+ fun_l3_n468
+end
+
+def fun_l2_n930()
+ fun_l3_n617
+end
+
+def fun_l2_n931()
+ fun_l3_n291
+end
+
+def fun_l2_n932()
+ fun_l3_n870
+end
+
+def fun_l2_n933()
+ fun_l3_n169
+end
+
+def fun_l2_n934()
+ fun_l3_n603
+end
+
+def fun_l2_n935()
+ fun_l3_n669
+end
+
+def fun_l2_n936()
+ fun_l3_n738
+end
+
+def fun_l2_n937()
+ fun_l3_n417
+end
+
+def fun_l2_n938()
+ fun_l3_n339
+end
+
+def fun_l2_n939()
+ fun_l3_n660
+end
+
+def fun_l2_n940()
+ fun_l3_n253
+end
+
+def fun_l2_n941()
+ fun_l3_n598
+end
+
+def fun_l2_n942()
+ fun_l3_n369
+end
+
+def fun_l2_n943()
+ fun_l3_n453
+end
+
+def fun_l2_n944()
+ fun_l3_n535
+end
+
+def fun_l2_n945()
+ fun_l3_n492
+end
+
+def fun_l2_n946()
+ fun_l3_n950
+end
+
+def fun_l2_n947()
+ fun_l3_n939
+end
+
+def fun_l2_n948()
+ fun_l3_n607
+end
+
+def fun_l2_n949()
+ fun_l3_n440
+end
+
+def fun_l2_n950()
+ fun_l3_n615
+end
+
+def fun_l2_n951()
+ fun_l3_n690
+end
+
+def fun_l2_n952()
+ fun_l3_n205
+end
+
+def fun_l2_n953()
+ fun_l3_n831
+end
+
+def fun_l2_n954()
+ fun_l3_n56
+end
+
+def fun_l2_n955()
+ fun_l3_n695
+end
+
+def fun_l2_n956()
+ fun_l3_n358
+end
+
+def fun_l2_n957()
+ fun_l3_n2
+end
+
+def fun_l2_n958()
+ fun_l3_n663
+end
+
+def fun_l2_n959()
+ fun_l3_n829
+end
+
+def fun_l2_n960()
+ fun_l3_n627
+end
+
+def fun_l2_n961()
+ fun_l3_n43
+end
+
+def fun_l2_n962()
+ fun_l3_n293
+end
+
+def fun_l2_n963()
+ fun_l3_n982
+end
+
+def fun_l2_n964()
+ fun_l3_n472
+end
+
+def fun_l2_n965()
+ fun_l3_n703
+end
+
+def fun_l2_n966()
+ fun_l3_n884
+end
+
+def fun_l2_n967()
+ fun_l3_n395
+end
+
+def fun_l2_n968()
+ fun_l3_n398
+end
+
+def fun_l2_n969()
+ fun_l3_n251
+end
+
+def fun_l2_n970()
+ fun_l3_n52
+end
+
+def fun_l2_n971()
+ fun_l3_n263
+end
+
+def fun_l2_n972()
+ fun_l3_n172
+end
+
+def fun_l2_n973()
+ fun_l3_n334
+end
+
+def fun_l2_n974()
+ fun_l3_n552
+end
+
+def fun_l2_n975()
+ fun_l3_n898
+end
+
+def fun_l2_n976()
+ fun_l3_n55
+end
+
+def fun_l2_n977()
+ fun_l3_n556
+end
+
+def fun_l2_n978()
+ fun_l3_n852
+end
+
+def fun_l2_n979()
+ fun_l3_n681
+end
+
+def fun_l2_n980()
+ fun_l3_n470
+end
+
+def fun_l2_n981()
+ fun_l3_n807
+end
+
+def fun_l2_n982()
+ fun_l3_n411
+end
+
+def fun_l2_n983()
+ fun_l3_n251
+end
+
+def fun_l2_n984()
+ fun_l3_n302
+end
+
+def fun_l2_n985()
+ fun_l3_n598
+end
+
+def fun_l2_n986()
+ fun_l3_n897
+end
+
+def fun_l2_n987()
+ fun_l3_n449
+end
+
+def fun_l2_n988()
+ fun_l3_n178
+end
+
+def fun_l2_n989()
+ fun_l3_n208
+end
+
+def fun_l2_n990()
+ fun_l3_n287
+end
+
+def fun_l2_n991()
+ fun_l3_n237
+end
+
+def fun_l2_n992()
+ fun_l3_n56
+end
+
+def fun_l2_n993()
+ fun_l3_n66
+end
+
+def fun_l2_n994()
+ fun_l3_n838
+end
+
+def fun_l2_n995()
+ fun_l3_n726
+end
+
+def fun_l2_n996()
+ fun_l3_n758
+end
+
+def fun_l2_n997()
+ fun_l3_n850
+end
+
+def fun_l2_n998()
+ fun_l3_n132
+end
+
+def fun_l2_n999()
+ fun_l3_n477
+end
+
+def fun_l3_n0()
+ fun_l4_n984
+end
+
+def fun_l3_n1()
+ fun_l4_n136
+end
+
+def fun_l3_n2()
+ fun_l4_n494
+end
+
+def fun_l3_n3()
+ fun_l4_n267
+end
+
+def fun_l3_n4()
+ fun_l4_n305
+end
+
+def fun_l3_n5()
+ fun_l4_n646
+end
+
+def fun_l3_n6()
+ fun_l4_n144
+end
+
+def fun_l3_n7()
+ fun_l4_n341
+end
+
+def fun_l3_n8()
+ fun_l4_n142
+end
+
+def fun_l3_n9()
+ fun_l4_n382
+end
+
+def fun_l3_n10()
+ fun_l4_n726
+end
+
+def fun_l3_n11()
+ fun_l4_n23
+end
+
+def fun_l3_n12()
+ fun_l4_n911
+end
+
+def fun_l3_n13()
+ fun_l4_n221
+end
+
+def fun_l3_n14()
+ fun_l4_n554
+end
+
+def fun_l3_n15()
+ fun_l4_n602
+end
+
+def fun_l3_n16()
+ fun_l4_n893
+end
+
+def fun_l3_n17()
+ fun_l4_n943
+end
+
+def fun_l3_n18()
+ fun_l4_n523
+end
+
+def fun_l3_n19()
+ fun_l4_n896
+end
+
+def fun_l3_n20()
+ fun_l4_n539
+end
+
+def fun_l3_n21()
+ fun_l4_n333
+end
+
+def fun_l3_n22()
+ fun_l4_n230
+end
+
+def fun_l3_n23()
+ fun_l4_n256
+end
+
+def fun_l3_n24()
+ fun_l4_n278
+end
+
+def fun_l3_n25()
+ fun_l4_n699
+end
+
+def fun_l3_n26()
+ fun_l4_n584
+end
+
+def fun_l3_n27()
+ fun_l4_n259
+end
+
+def fun_l3_n28()
+ fun_l4_n993
+end
+
+def fun_l3_n29()
+ fun_l4_n183
+end
+
+def fun_l3_n30()
+ fun_l4_n249
+end
+
+def fun_l3_n31()
+ fun_l4_n253
+end
+
+def fun_l3_n32()
+ fun_l4_n507
+end
+
+def fun_l3_n33()
+ fun_l4_n507
+end
+
+def fun_l3_n34()
+ fun_l4_n142
+end
+
+def fun_l3_n35()
+ fun_l4_n392
+end
+
+def fun_l3_n36()
+ fun_l4_n962
+end
+
+def fun_l3_n37()
+ fun_l4_n799
+end
+
+def fun_l3_n38()
+ fun_l4_n110
+end
+
+def fun_l3_n39()
+ fun_l4_n623
+end
+
+def fun_l3_n40()
+ fun_l4_n508
+end
+
+def fun_l3_n41()
+ fun_l4_n726
+end
+
+def fun_l3_n42()
+ fun_l4_n282
+end
+
+def fun_l3_n43()
+ fun_l4_n942
+end
+
+def fun_l3_n44()
+ fun_l4_n711
+end
+
+def fun_l3_n45()
+ fun_l4_n926
+end
+
+def fun_l3_n46()
+ fun_l4_n793
+end
+
+def fun_l3_n47()
+ fun_l4_n658
+end
+
+def fun_l3_n48()
+ fun_l4_n802
+end
+
+def fun_l3_n49()
+ fun_l4_n499
+end
+
+def fun_l3_n50()
+ fun_l4_n648
+end
+
+def fun_l3_n51()
+ fun_l4_n465
+end
+
+def fun_l3_n52()
+ fun_l4_n460
+end
+
+def fun_l3_n53()
+ fun_l4_n904
+end
+
+def fun_l3_n54()
+ fun_l4_n939
+end
+
+def fun_l3_n55()
+ fun_l4_n306
+end
+
+def fun_l3_n56()
+ fun_l4_n235
+end
+
+def fun_l3_n57()
+ fun_l4_n783
+end
+
+def fun_l3_n58()
+ fun_l4_n992
+end
+
+def fun_l3_n59()
+ fun_l4_n196
+end
+
+def fun_l3_n60()
+ fun_l4_n637
+end
+
+def fun_l3_n61()
+ fun_l4_n512
+end
+
+def fun_l3_n62()
+ fun_l4_n480
+end
+
+def fun_l3_n63()
+ fun_l4_n31
+end
+
+def fun_l3_n64()
+ fun_l4_n277
+end
+
+def fun_l3_n65()
+ fun_l4_n814
+end
+
+def fun_l3_n66()
+ fun_l4_n170
+end
+
+def fun_l3_n67()
+ fun_l4_n604
+end
+
+def fun_l3_n68()
+ fun_l4_n794
+end
+
+def fun_l3_n69()
+ fun_l4_n530
+end
+
+def fun_l3_n70()
+ fun_l4_n291
+end
+
+def fun_l3_n71()
+ fun_l4_n146
+end
+
+def fun_l3_n72()
+ fun_l4_n588
+end
+
+def fun_l3_n73()
+ fun_l4_n624
+end
+
+def fun_l3_n74()
+ fun_l4_n210
+end
+
+def fun_l3_n75()
+ fun_l4_n924
+end
+
+def fun_l3_n76()
+ fun_l4_n77
+end
+
+def fun_l3_n77()
+ fun_l4_n727
+end
+
+def fun_l3_n78()
+ fun_l4_n840
+end
+
+def fun_l3_n79()
+ fun_l4_n257
+end
+
+def fun_l3_n80()
+ fun_l4_n654
+end
+
+def fun_l3_n81()
+ fun_l4_n498
+end
+
+def fun_l3_n82()
+ fun_l4_n445
+end
+
+def fun_l3_n83()
+ fun_l4_n820
+end
+
+def fun_l3_n84()
+ fun_l4_n376
+end
+
+def fun_l3_n85()
+ fun_l4_n702
+end
+
+def fun_l3_n86()
+ fun_l4_n22
+end
+
+def fun_l3_n87()
+ fun_l4_n278
+end
+
+def fun_l3_n88()
+ fun_l4_n399
+end
+
+def fun_l3_n89()
+ fun_l4_n166
+end
+
+def fun_l3_n90()
+ fun_l4_n461
+end
+
+def fun_l3_n91()
+ fun_l4_n992
+end
+
+def fun_l3_n92()
+ fun_l4_n207
+end
+
+def fun_l3_n93()
+ fun_l4_n915
+end
+
+def fun_l3_n94()
+ fun_l4_n852
+end
+
+def fun_l3_n95()
+ fun_l4_n591
+end
+
+def fun_l3_n96()
+ fun_l4_n74
+end
+
+def fun_l3_n97()
+ fun_l4_n735
+end
+
+def fun_l3_n98()
+ fun_l4_n863
+end
+
+def fun_l3_n99()
+ fun_l4_n692
+end
+
+def fun_l3_n100()
+ fun_l4_n633
+end
+
+def fun_l3_n101()
+ fun_l4_n618
+end
+
+def fun_l3_n102()
+ fun_l4_n306
+end
+
+def fun_l3_n103()
+ fun_l4_n620
+end
+
+def fun_l3_n104()
+ fun_l4_n981
+end
+
+def fun_l3_n105()
+ fun_l4_n763
+end
+
+def fun_l3_n106()
+ fun_l4_n727
+end
+
+def fun_l3_n107()
+ fun_l4_n173
+end
+
+def fun_l3_n108()
+ fun_l4_n645
+end
+
+def fun_l3_n109()
+ fun_l4_n333
+end
+
+def fun_l3_n110()
+ fun_l4_n847
+end
+
+def fun_l3_n111()
+ fun_l4_n905
+end
+
+def fun_l3_n112()
+ fun_l4_n753
+end
+
+def fun_l3_n113()
+ fun_l4_n294
+end
+
+def fun_l3_n114()
+ fun_l4_n891
+end
+
+def fun_l3_n115()
+ fun_l4_n495
+end
+
+def fun_l3_n116()
+ fun_l4_n683
+end
+
+def fun_l3_n117()
+ fun_l4_n925
+end
+
+def fun_l3_n118()
+ fun_l4_n630
+end
+
+def fun_l3_n119()
+ fun_l4_n548
+end
+
+def fun_l3_n120()
+ fun_l4_n767
+end
+
+def fun_l3_n121()
+ fun_l4_n623
+end
+
+def fun_l3_n122()
+ fun_l4_n0
+end
+
+def fun_l3_n123()
+ fun_l4_n849
+end
+
+def fun_l3_n124()
+ fun_l4_n643
+end
+
+def fun_l3_n125()
+ fun_l4_n559
+end
+
+def fun_l3_n126()
+ fun_l4_n533
+end
+
+def fun_l3_n127()
+ fun_l4_n287
+end
+
+def fun_l3_n128()
+ fun_l4_n146
+end
+
+def fun_l3_n129()
+ fun_l4_n636
+end
+
+def fun_l3_n130()
+ fun_l4_n914
+end
+
+def fun_l3_n131()
+ fun_l4_n274
+end
+
+def fun_l3_n132()
+ fun_l4_n60
+end
+
+def fun_l3_n133()
+ fun_l4_n858
+end
+
+def fun_l3_n134()
+ fun_l4_n334
+end
+
+def fun_l3_n135()
+ fun_l4_n892
+end
+
+def fun_l3_n136()
+ fun_l4_n81
+end
+
+def fun_l3_n137()
+ fun_l4_n567
+end
+
+def fun_l3_n138()
+ fun_l4_n456
+end
+
+def fun_l3_n139()
+ fun_l4_n625
+end
+
+def fun_l3_n140()
+ fun_l4_n690
+end
+
+def fun_l3_n141()
+ fun_l4_n919
+end
+
+def fun_l3_n142()
+ fun_l4_n504
+end
+
+def fun_l3_n143()
+ fun_l4_n986
+end
+
+def fun_l3_n144()
+ fun_l4_n99
+end
+
+def fun_l3_n145()
+ fun_l4_n312
+end
+
+def fun_l3_n146()
+ fun_l4_n36
+end
+
+def fun_l3_n147()
+ fun_l4_n3
+end
+
+def fun_l3_n148()
+ fun_l4_n328
+end
+
+def fun_l3_n149()
+ fun_l4_n978
+end
+
+def fun_l3_n150()
+ fun_l4_n474
+end
+
+def fun_l3_n151()
+ fun_l4_n985
+end
+
+def fun_l3_n152()
+ fun_l4_n809
+end
+
+def fun_l3_n153()
+ fun_l4_n379
+end
+
+def fun_l3_n154()
+ fun_l4_n589
+end
+
+def fun_l3_n155()
+ fun_l4_n625
+end
+
+def fun_l3_n156()
+ fun_l4_n937
+end
+
+def fun_l3_n157()
+ fun_l4_n774
+end
+
+def fun_l3_n158()
+ fun_l4_n465
+end
+
+def fun_l3_n159()
+ fun_l4_n315
+end
+
+def fun_l3_n160()
+ fun_l4_n733
+end
+
+def fun_l3_n161()
+ fun_l4_n572
+end
+
+def fun_l3_n162()
+ fun_l4_n794
+end
+
+def fun_l3_n163()
+ fun_l4_n76
+end
+
+def fun_l3_n164()
+ fun_l4_n550
+end
+
+def fun_l3_n165()
+ fun_l4_n913
+end
+
+def fun_l3_n166()
+ fun_l4_n553
+end
+
+def fun_l3_n167()
+ fun_l4_n383
+end
+
+def fun_l3_n168()
+ fun_l4_n118
+end
+
+def fun_l3_n169()
+ fun_l4_n561
+end
+
+def fun_l3_n170()
+ fun_l4_n517
+end
+
+def fun_l3_n171()
+ fun_l4_n680
+end
+
+def fun_l3_n172()
+ fun_l4_n466
+end
+
+def fun_l3_n173()
+ fun_l4_n629
+end
+
+def fun_l3_n174()
+ fun_l4_n469
+end
+
+def fun_l3_n175()
+ fun_l4_n731
+end
+
+def fun_l3_n176()
+ fun_l4_n579
+end
+
+def fun_l3_n177()
+ fun_l4_n574
+end
+
+def fun_l3_n178()
+ fun_l4_n936
+end
+
+def fun_l3_n179()
+ fun_l4_n405
+end
+
+def fun_l3_n180()
+ fun_l4_n667
+end
+
+def fun_l3_n181()
+ fun_l4_n369
+end
+
+def fun_l3_n182()
+ fun_l4_n852
+end
+
+def fun_l3_n183()
+ fun_l4_n861
+end
+
+def fun_l3_n184()
+ fun_l4_n425
+end
+
+def fun_l3_n185()
+ fun_l4_n4
+end
+
+def fun_l3_n186()
+ fun_l4_n28
+end
+
+def fun_l3_n187()
+ fun_l4_n470
+end
+
+def fun_l3_n188()
+ fun_l4_n568
+end
+
+def fun_l3_n189()
+ fun_l4_n83
+end
+
+def fun_l3_n190()
+ fun_l4_n981
+end
+
+def fun_l3_n191()
+ fun_l4_n526
+end
+
+def fun_l3_n192()
+ fun_l4_n496
+end
+
+def fun_l3_n193()
+ fun_l4_n954
+end
+
+def fun_l3_n194()
+ fun_l4_n340
+end
+
+def fun_l3_n195()
+ fun_l4_n343
+end
+
+def fun_l3_n196()
+ fun_l4_n964
+end
+
+def fun_l3_n197()
+ fun_l4_n58
+end
+
+def fun_l3_n198()
+ fun_l4_n317
+end
+
+def fun_l3_n199()
+ fun_l4_n255
+end
+
+def fun_l3_n200()
+ fun_l4_n546
+end
+
+def fun_l3_n201()
+ fun_l4_n933
+end
+
+def fun_l3_n202()
+ fun_l4_n387
+end
+
+def fun_l3_n203()
+ fun_l4_n32
+end
+
+def fun_l3_n204()
+ fun_l4_n514
+end
+
+def fun_l3_n205()
+ fun_l4_n175
+end
+
+def fun_l3_n206()
+ fun_l4_n813
+end
+
+def fun_l3_n207()
+ fun_l4_n881
+end
+
+def fun_l3_n208()
+ fun_l4_n52
+end
+
+def fun_l3_n209()
+ fun_l4_n839
+end
+
+def fun_l3_n210()
+ fun_l4_n919
+end
+
+def fun_l3_n211()
+ fun_l4_n208
+end
+
+def fun_l3_n212()
+ fun_l4_n111
+end
+
+def fun_l3_n213()
+ fun_l4_n878
+end
+
+def fun_l3_n214()
+ fun_l4_n110
+end
+
+def fun_l3_n215()
+ fun_l4_n701
+end
+
+def fun_l3_n216()
+ fun_l4_n769
+end
+
+def fun_l3_n217()
+ fun_l4_n487
+end
+
+def fun_l3_n218()
+ fun_l4_n940
+end
+
+def fun_l3_n219()
+ fun_l4_n427
+end
+
+def fun_l3_n220()
+ fun_l4_n731
+end
+
+def fun_l3_n221()
+ fun_l4_n92
+end
+
+def fun_l3_n222()
+ fun_l4_n246
+end
+
+def fun_l3_n223()
+ fun_l4_n574
+end
+
+def fun_l3_n224()
+ fun_l4_n297
+end
+
+def fun_l3_n225()
+ fun_l4_n48
+end
+
+def fun_l3_n226()
+ fun_l4_n433
+end
+
+def fun_l3_n227()
+ fun_l4_n628
+end
+
+def fun_l3_n228()
+ fun_l4_n426
+end
+
+def fun_l3_n229()
+ fun_l4_n22
+end
+
+def fun_l3_n230()
+ fun_l4_n878
+end
+
+def fun_l3_n231()
+ fun_l4_n905
+end
+
+def fun_l3_n232()
+ fun_l4_n222
+end
+
+def fun_l3_n233()
+ fun_l4_n523
+end
+
+def fun_l3_n234()
+ fun_l4_n9
+end
+
+def fun_l3_n235()
+ fun_l4_n705
+end
+
+def fun_l3_n236()
+ fun_l4_n811
+end
+
+def fun_l3_n237()
+ fun_l4_n987
+end
+
+def fun_l3_n238()
+ fun_l4_n915
+end
+
+def fun_l3_n239()
+ fun_l4_n302
+end
+
+def fun_l3_n240()
+ fun_l4_n766
+end
+
+def fun_l3_n241()
+ fun_l4_n29
+end
+
+def fun_l3_n242()
+ fun_l4_n154
+end
+
+def fun_l3_n243()
+ fun_l4_n853
+end
+
+def fun_l3_n244()
+ fun_l4_n619
+end
+
+def fun_l3_n245()
+ fun_l4_n739
+end
+
+def fun_l3_n246()
+ fun_l4_n814
+end
+
+def fun_l3_n247()
+ fun_l4_n768
+end
+
+def fun_l3_n248()
+ fun_l4_n2
+end
+
+def fun_l3_n249()
+ fun_l4_n595
+end
+
+def fun_l3_n250()
+ fun_l4_n606
+end
+
+def fun_l3_n251()
+ fun_l4_n144
+end
+
+def fun_l3_n252()
+ fun_l4_n550
+end
+
+def fun_l3_n253()
+ fun_l4_n268
+end
+
+def fun_l3_n254()
+ fun_l4_n320
+end
+
+def fun_l3_n255()
+ fun_l4_n59
+end
+
+def fun_l3_n256()
+ fun_l4_n586
+end
+
+def fun_l3_n257()
+ fun_l4_n766
+end
+
+def fun_l3_n258()
+ fun_l4_n96
+end
+
+def fun_l3_n259()
+ fun_l4_n964
+end
+
+def fun_l3_n260()
+ fun_l4_n163
+end
+
+def fun_l3_n261()
+ fun_l4_n305
+end
+
+def fun_l3_n262()
+ fun_l4_n155
+end
+
+def fun_l3_n263()
+ fun_l4_n249
+end
+
+def fun_l3_n264()
+ fun_l4_n887
+end
+
+def fun_l3_n265()
+ fun_l4_n625
+end
+
+def fun_l3_n266()
+ fun_l4_n241
+end
+
+def fun_l3_n267()
+ fun_l4_n385
+end
+
+def fun_l3_n268()
+ fun_l4_n287
+end
+
+def fun_l3_n269()
+ fun_l4_n375
+end
+
+def fun_l3_n270()
+ fun_l4_n13
+end
+
+def fun_l3_n271()
+ fun_l4_n44
+end
+
+def fun_l3_n272()
+ fun_l4_n259
+end
+
+def fun_l3_n273()
+ fun_l4_n231
+end
+
+def fun_l3_n274()
+ fun_l4_n692
+end
+
+def fun_l3_n275()
+ fun_l4_n279
+end
+
+def fun_l3_n276()
+ fun_l4_n353
+end
+
+def fun_l3_n277()
+ fun_l4_n287
+end
+
+def fun_l3_n278()
+ fun_l4_n254
+end
+
+def fun_l3_n279()
+ fun_l4_n717
+end
+
+def fun_l3_n280()
+ fun_l4_n635
+end
+
+def fun_l3_n281()
+ fun_l4_n264
+end
+
+def fun_l3_n282()
+ fun_l4_n390
+end
+
+def fun_l3_n283()
+ fun_l4_n824
+end
+
+def fun_l3_n284()
+ fun_l4_n919
+end
+
+def fun_l3_n285()
+ fun_l4_n273
+end
+
+def fun_l3_n286()
+ fun_l4_n566
+end
+
+def fun_l3_n287()
+ fun_l4_n6
+end
+
+def fun_l3_n288()
+ fun_l4_n28
+end
+
+def fun_l3_n289()
+ fun_l4_n602
+end
+
+def fun_l3_n290()
+ fun_l4_n209
+end
+
+def fun_l3_n291()
+ fun_l4_n753
+end
+
+def fun_l3_n292()
+ fun_l4_n914
+end
+
+def fun_l3_n293()
+ fun_l4_n345
+end
+
+def fun_l3_n294()
+ fun_l4_n616
+end
+
+def fun_l3_n295()
+ fun_l4_n640
+end
+
+def fun_l3_n296()
+ fun_l4_n47
+end
+
+def fun_l3_n297()
+ fun_l4_n542
+end
+
+def fun_l3_n298()
+ fun_l4_n379
+end
+
+def fun_l3_n299()
+ fun_l4_n14
+end
+
+def fun_l3_n300()
+ fun_l4_n126
+end
+
+def fun_l3_n301()
+ fun_l4_n913
+end
+
+def fun_l3_n302()
+ fun_l4_n933
+end
+
+def fun_l3_n303()
+ fun_l4_n429
+end
+
+def fun_l3_n304()
+ fun_l4_n175
+end
+
+def fun_l3_n305()
+ fun_l4_n152
+end
+
+def fun_l3_n306()
+ fun_l4_n556
+end
+
+def fun_l3_n307()
+ fun_l4_n799
+end
+
+def fun_l3_n308()
+ fun_l4_n865
+end
+
+def fun_l3_n309()
+ fun_l4_n501
+end
+
+def fun_l3_n310()
+ fun_l4_n148
+end
+
+def fun_l3_n311()
+ fun_l4_n160
+end
+
+def fun_l3_n312()
+ fun_l4_n333
+end
+
+def fun_l3_n313()
+ fun_l4_n987
+end
+
+def fun_l3_n314()
+ fun_l4_n449
+end
+
+def fun_l3_n315()
+ fun_l4_n460
+end
+
+def fun_l3_n316()
+ fun_l4_n866
+end
+
+def fun_l3_n317()
+ fun_l4_n554
+end
+
+def fun_l3_n318()
+ fun_l4_n497
+end
+
+def fun_l3_n319()
+ fun_l4_n25
+end
+
+def fun_l3_n320()
+ fun_l4_n483
+end
+
+def fun_l3_n321()
+ fun_l4_n412
+end
+
+def fun_l3_n322()
+ fun_l4_n594
+end
+
+def fun_l3_n323()
+ fun_l4_n727
+end
+
+def fun_l3_n324()
+ fun_l4_n209
+end
+
+def fun_l3_n325()
+ fun_l4_n956
+end
+
+def fun_l3_n326()
+ fun_l4_n127
+end
+
+def fun_l3_n327()
+ fun_l4_n942
+end
+
+def fun_l3_n328()
+ fun_l4_n984
+end
+
+def fun_l3_n329()
+ fun_l4_n387
+end
+
+def fun_l3_n330()
+ fun_l4_n834
+end
+
+def fun_l3_n331()
+ fun_l4_n723
+end
+
+def fun_l3_n332()
+ fun_l4_n576
+end
+
+def fun_l3_n333()
+ fun_l4_n949
+end
+
+def fun_l3_n334()
+ fun_l4_n792
+end
+
+def fun_l3_n335()
+ fun_l4_n28
+end
+
+def fun_l3_n336()
+ fun_l4_n805
+end
+
+def fun_l3_n337()
+ fun_l4_n469
+end
+
+def fun_l3_n338()
+ fun_l4_n651
+end
+
+def fun_l3_n339()
+ fun_l4_n672
+end
+
+def fun_l3_n340()
+ fun_l4_n835
+end
+
+def fun_l3_n341()
+ fun_l4_n902
+end
+
+def fun_l3_n342()
+ fun_l4_n9
+end
+
+def fun_l3_n343()
+ fun_l4_n111
+end
+
+def fun_l3_n344()
+ fun_l4_n234
+end
+
+def fun_l3_n345()
+ fun_l4_n608
+end
+
+def fun_l3_n346()
+ fun_l4_n577
+end
+
+def fun_l3_n347()
+ fun_l4_n966
+end
+
+def fun_l3_n348()
+ fun_l4_n777
+end
+
+def fun_l3_n349()
+ fun_l4_n387
+end
+
+def fun_l3_n350()
+ fun_l4_n27
+end
+
+def fun_l3_n351()
+ fun_l4_n94
+end
+
+def fun_l3_n352()
+ fun_l4_n12
+end
+
+def fun_l3_n353()
+ fun_l4_n632
+end
+
+def fun_l3_n354()
+ fun_l4_n314
+end
+
+def fun_l3_n355()
+ fun_l4_n472
+end
+
+def fun_l3_n356()
+ fun_l4_n737
+end
+
+def fun_l3_n357()
+ fun_l4_n775
+end
+
+def fun_l3_n358()
+ fun_l4_n255
+end
+
+def fun_l3_n359()
+ fun_l4_n474
+end
+
+def fun_l3_n360()
+ fun_l4_n668
+end
+
+def fun_l3_n361()
+ fun_l4_n907
+end
+
+def fun_l3_n362()
+ fun_l4_n608
+end
+
+def fun_l3_n363()
+ fun_l4_n885
+end
+
+def fun_l3_n364()
+ fun_l4_n63
+end
+
+def fun_l3_n365()
+ fun_l4_n432
+end
+
+def fun_l3_n366()
+ fun_l4_n748
+end
+
+def fun_l3_n367()
+ fun_l4_n741
+end
+
+def fun_l3_n368()
+ fun_l4_n799
+end
+
+def fun_l3_n369()
+ fun_l4_n747
+end
+
+def fun_l3_n370()
+ fun_l4_n939
+end
+
+def fun_l3_n371()
+ fun_l4_n569
+end
+
+def fun_l3_n372()
+ fun_l4_n267
+end
+
+def fun_l3_n373()
+ fun_l4_n640
+end
+
+def fun_l3_n374()
+ fun_l4_n647
+end
+
+def fun_l3_n375()
+ fun_l4_n658
+end
+
+def fun_l3_n376()
+ fun_l4_n346
+end
+
+def fun_l3_n377()
+ fun_l4_n781
+end
+
+def fun_l3_n378()
+ fun_l4_n820
+end
+
+def fun_l3_n379()
+ fun_l4_n11
+end
+
+def fun_l3_n380()
+ fun_l4_n238
+end
+
+def fun_l3_n381()
+ fun_l4_n78
+end
+
+def fun_l3_n382()
+ fun_l4_n497
+end
+
+def fun_l3_n383()
+ fun_l4_n815
+end
+
+def fun_l3_n384()
+ fun_l4_n876
+end
+
+def fun_l3_n385()
+ fun_l4_n392
+end
+
+def fun_l3_n386()
+ fun_l4_n228
+end
+
+def fun_l3_n387()
+ fun_l4_n230
+end
+
+def fun_l3_n388()
+ fun_l4_n216
+end
+
+def fun_l3_n389()
+ fun_l4_n661
+end
+
+def fun_l3_n390()
+ fun_l4_n831
+end
+
+def fun_l3_n391()
+ fun_l4_n588
+end
+
+def fun_l3_n392()
+ fun_l4_n377
+end
+
+def fun_l3_n393()
+ fun_l4_n245
+end
+
+def fun_l3_n394()
+ fun_l4_n546
+end
+
+def fun_l3_n395()
+ fun_l4_n48
+end
+
+def fun_l3_n396()
+ fun_l4_n109
+end
+
+def fun_l3_n397()
+ fun_l4_n958
+end
+
+def fun_l3_n398()
+ fun_l4_n779
+end
+
+def fun_l3_n399()
+ fun_l4_n942
+end
+
+def fun_l3_n400()
+ fun_l4_n436
+end
+
+def fun_l3_n401()
+ fun_l4_n321
+end
+
+def fun_l3_n402()
+ fun_l4_n789
+end
+
+def fun_l3_n403()
+ fun_l4_n96
+end
+
+def fun_l3_n404()
+ fun_l4_n101
+end
+
+def fun_l3_n405()
+ fun_l4_n373
+end
+
+def fun_l3_n406()
+ fun_l4_n143
+end
+
+def fun_l3_n407()
+ fun_l4_n869
+end
+
+def fun_l3_n408()
+ fun_l4_n836
+end
+
+def fun_l3_n409()
+ fun_l4_n278
+end
+
+def fun_l3_n410()
+ fun_l4_n819
+end
+
+def fun_l3_n411()
+ fun_l4_n716
+end
+
+def fun_l3_n412()
+ fun_l4_n729
+end
+
+def fun_l3_n413()
+ fun_l4_n565
+end
+
+def fun_l3_n414()
+ fun_l4_n258
+end
+
+def fun_l3_n415()
+ fun_l4_n187
+end
+
+def fun_l3_n416()
+ fun_l4_n425
+end
+
+def fun_l3_n417()
+ fun_l4_n239
+end
+
+def fun_l3_n418()
+ fun_l4_n352
+end
+
+def fun_l3_n419()
+ fun_l4_n747
+end
+
+def fun_l3_n420()
+ fun_l4_n103
+end
+
+def fun_l3_n421()
+ fun_l4_n276
+end
+
+def fun_l3_n422()
+ fun_l4_n348
+end
+
+def fun_l3_n423()
+ fun_l4_n737
+end
+
+def fun_l3_n424()
+ fun_l4_n615
+end
+
+def fun_l3_n425()
+ fun_l4_n305
+end
+
+def fun_l3_n426()
+ fun_l4_n474
+end
+
+def fun_l3_n427()
+ fun_l4_n304
+end
+
+def fun_l3_n428()
+ fun_l4_n607
+end
+
+def fun_l3_n429()
+ fun_l4_n202
+end
+
+def fun_l3_n430()
+ fun_l4_n370
+end
+
+def fun_l3_n431()
+ fun_l4_n580
+end
+
+def fun_l3_n432()
+ fun_l4_n752
+end
+
+def fun_l3_n433()
+ fun_l4_n720
+end
+
+def fun_l3_n434()
+ fun_l4_n916
+end
+
+def fun_l3_n435()
+ fun_l4_n424
+end
+
+def fun_l3_n436()
+ fun_l4_n922
+end
+
+def fun_l3_n437()
+ fun_l4_n885
+end
+
+def fun_l3_n438()
+ fun_l4_n849
+end
+
+def fun_l3_n439()
+ fun_l4_n595
+end
+
+def fun_l3_n440()
+ fun_l4_n753
+end
+
+def fun_l3_n441()
+ fun_l4_n871
+end
+
+def fun_l3_n442()
+ fun_l4_n979
+end
+
+def fun_l3_n443()
+ fun_l4_n217
+end
+
+def fun_l3_n444()
+ fun_l4_n249
+end
+
+def fun_l3_n445()
+ fun_l4_n181
+end
+
+def fun_l3_n446()
+ fun_l4_n283
+end
+
+def fun_l3_n447()
+ fun_l4_n495
+end
+
+def fun_l3_n448()
+ fun_l4_n701
+end
+
+def fun_l3_n449()
+ fun_l4_n897
+end
+
+def fun_l3_n450()
+ fun_l4_n479
+end
+
+def fun_l3_n451()
+ fun_l4_n410
+end
+
+def fun_l3_n452()
+ fun_l4_n842
+end
+
+def fun_l3_n453()
+ fun_l4_n700
+end
+
+def fun_l3_n454()
+ fun_l4_n855
+end
+
+def fun_l3_n455()
+ fun_l4_n743
+end
+
+def fun_l3_n456()
+ fun_l4_n842
+end
+
+def fun_l3_n457()
+ fun_l4_n575
+end
+
+def fun_l3_n458()
+ fun_l4_n48
+end
+
+def fun_l3_n459()
+ fun_l4_n650
+end
+
+def fun_l3_n460()
+ fun_l4_n714
+end
+
+def fun_l3_n461()
+ fun_l4_n409
+end
+
+def fun_l3_n462()
+ fun_l4_n225
+end
+
+def fun_l3_n463()
+ fun_l4_n419
+end
+
+def fun_l3_n464()
+ fun_l4_n563
+end
+
+def fun_l3_n465()
+ fun_l4_n416
+end
+
+def fun_l3_n466()
+ fun_l4_n738
+end
+
+def fun_l3_n467()
+ fun_l4_n955
+end
+
+def fun_l3_n468()
+ fun_l4_n406
+end
+
+def fun_l3_n469()
+ fun_l4_n157
+end
+
+def fun_l3_n470()
+ fun_l4_n732
+end
+
+def fun_l3_n471()
+ fun_l4_n567
+end
+
+def fun_l3_n472()
+ fun_l4_n895
+end
+
+def fun_l3_n473()
+ fun_l4_n377
+end
+
+def fun_l3_n474()
+ fun_l4_n105
+end
+
+def fun_l3_n475()
+ fun_l4_n640
+end
+
+def fun_l3_n476()
+ fun_l4_n617
+end
+
+def fun_l3_n477()
+ fun_l4_n109
+end
+
+def fun_l3_n478()
+ fun_l4_n358
+end
+
+def fun_l3_n479()
+ fun_l4_n522
+end
+
+def fun_l3_n480()
+ fun_l4_n550
+end
+
+def fun_l3_n481()
+ fun_l4_n648
+end
+
+def fun_l3_n482()
+ fun_l4_n533
+end
+
+def fun_l3_n483()
+ fun_l4_n782
+end
+
+def fun_l3_n484()
+ fun_l4_n369
+end
+
+def fun_l3_n485()
+ fun_l4_n644
+end
+
+def fun_l3_n486()
+ fun_l4_n989
+end
+
+def fun_l3_n487()
+ fun_l4_n434
+end
+
+def fun_l3_n488()
+ fun_l4_n914
+end
+
+def fun_l3_n489()
+ fun_l4_n2
+end
+
+def fun_l3_n490()
+ fun_l4_n494
+end
+
+def fun_l3_n491()
+ fun_l4_n479
+end
+
+def fun_l3_n492()
+ fun_l4_n733
+end
+
+def fun_l3_n493()
+ fun_l4_n394
+end
+
+def fun_l3_n494()
+ fun_l4_n39
+end
+
+def fun_l3_n495()
+ fun_l4_n866
+end
+
+def fun_l3_n496()
+ fun_l4_n151
+end
+
+def fun_l3_n497()
+ fun_l4_n155
+end
+
+def fun_l3_n498()
+ fun_l4_n417
+end
+
+def fun_l3_n499()
+ fun_l4_n933
+end
+
+def fun_l3_n500()
+ fun_l4_n44
+end
+
+def fun_l3_n501()
+ fun_l4_n738
+end
+
+def fun_l3_n502()
+ fun_l4_n859
+end
+
+def fun_l3_n503()
+ fun_l4_n124
+end
+
+def fun_l3_n504()
+ fun_l4_n344
+end
+
+def fun_l3_n505()
+ fun_l4_n921
+end
+
+def fun_l3_n506()
+ fun_l4_n168
+end
+
+def fun_l3_n507()
+ fun_l4_n135
+end
+
+def fun_l3_n508()
+ fun_l4_n730
+end
+
+def fun_l3_n509()
+ fun_l4_n671
+end
+
+def fun_l3_n510()
+ fun_l4_n899
+end
+
+def fun_l3_n511()
+ fun_l4_n630
+end
+
+def fun_l3_n512()
+ fun_l4_n228
+end
+
+def fun_l3_n513()
+ fun_l4_n429
+end
+
+def fun_l3_n514()
+ fun_l4_n723
+end
+
+def fun_l3_n515()
+ fun_l4_n185
+end
+
+def fun_l3_n516()
+ fun_l4_n161
+end
+
+def fun_l3_n517()
+ fun_l4_n491
+end
+
+def fun_l3_n518()
+ fun_l4_n643
+end
+
+def fun_l3_n519()
+ fun_l4_n3
+end
+
+def fun_l3_n520()
+ fun_l4_n399
+end
+
+def fun_l3_n521()
+ fun_l4_n927
+end
+
+def fun_l3_n522()
+ fun_l4_n501
+end
+
+def fun_l3_n523()
+ fun_l4_n729
+end
+
+def fun_l3_n524()
+ fun_l4_n628
+end
+
+def fun_l3_n525()
+ fun_l4_n469
+end
+
+def fun_l3_n526()
+ fun_l4_n754
+end
+
+def fun_l3_n527()
+ fun_l4_n448
+end
+
+def fun_l3_n528()
+ fun_l4_n562
+end
+
+def fun_l3_n529()
+ fun_l4_n779
+end
+
+def fun_l3_n530()
+ fun_l4_n452
+end
+
+def fun_l3_n531()
+ fun_l4_n756
+end
+
+def fun_l3_n532()
+ fun_l4_n107
+end
+
+def fun_l3_n533()
+ fun_l4_n311
+end
+
+def fun_l3_n534()
+ fun_l4_n169
+end
+
+def fun_l3_n535()
+ fun_l4_n956
+end
+
+def fun_l3_n536()
+ fun_l4_n754
+end
+
+def fun_l3_n537()
+ fun_l4_n675
+end
+
+def fun_l3_n538()
+ fun_l4_n636
+end
+
+def fun_l3_n539()
+ fun_l4_n691
+end
+
+def fun_l3_n540()
+ fun_l4_n867
+end
+
+def fun_l3_n541()
+ fun_l4_n179
+end
+
+def fun_l3_n542()
+ fun_l4_n153
+end
+
+def fun_l3_n543()
+ fun_l4_n133
+end
+
+def fun_l3_n544()
+ fun_l4_n592
+end
+
+def fun_l3_n545()
+ fun_l4_n71
+end
+
+def fun_l3_n546()
+ fun_l4_n87
+end
+
+def fun_l3_n547()
+ fun_l4_n740
+end
+
+def fun_l3_n548()
+ fun_l4_n436
+end
+
+def fun_l3_n549()
+ fun_l4_n59
+end
+
+def fun_l3_n550()
+ fun_l4_n252
+end
+
+def fun_l3_n551()
+ fun_l4_n596
+end
+
+def fun_l3_n552()
+ fun_l4_n851
+end
+
+def fun_l3_n553()
+ fun_l4_n708
+end
+
+def fun_l3_n554()
+ fun_l4_n210
+end
+
+def fun_l3_n555()
+ fun_l4_n931
+end
+
+def fun_l3_n556()
+ fun_l4_n293
+end
+
+def fun_l3_n557()
+ fun_l4_n413
+end
+
+def fun_l3_n558()
+ fun_l4_n547
+end
+
+def fun_l3_n559()
+ fun_l4_n338
+end
+
+def fun_l3_n560()
+ fun_l4_n194
+end
+
+def fun_l3_n561()
+ fun_l4_n937
+end
+
+def fun_l3_n562()
+ fun_l4_n19
+end
+
+def fun_l3_n563()
+ fun_l4_n651
+end
+
+def fun_l3_n564()
+ fun_l4_n364
+end
+
+def fun_l3_n565()
+ fun_l4_n295
+end
+
+def fun_l3_n566()
+ fun_l4_n946
+end
+
+def fun_l3_n567()
+ fun_l4_n712
+end
+
+def fun_l3_n568()
+ fun_l4_n243
+end
+
+def fun_l3_n569()
+ fun_l4_n563
+end
+
+def fun_l3_n570()
+ fun_l4_n651
+end
+
+def fun_l3_n571()
+ fun_l4_n645
+end
+
+def fun_l3_n572()
+ fun_l4_n46
+end
+
+def fun_l3_n573()
+ fun_l4_n971
+end
+
+def fun_l3_n574()
+ fun_l4_n769
+end
+
+def fun_l3_n575()
+ fun_l4_n315
+end
+
+def fun_l3_n576()
+ fun_l4_n657
+end
+
+def fun_l3_n577()
+ fun_l4_n607
+end
+
+def fun_l3_n578()
+ fun_l4_n352
+end
+
+def fun_l3_n579()
+ fun_l4_n346
+end
+
+def fun_l3_n580()
+ fun_l4_n424
+end
+
+def fun_l3_n581()
+ fun_l4_n703
+end
+
+def fun_l3_n582()
+ fun_l4_n872
+end
+
+def fun_l3_n583()
+ fun_l4_n828
+end
+
+def fun_l3_n584()
+ fun_l4_n283
+end
+
+def fun_l3_n585()
+ fun_l4_n557
+end
+
+def fun_l3_n586()
+ fun_l4_n942
+end
+
+def fun_l3_n587()
+ fun_l4_n121
+end
+
+def fun_l3_n588()
+ fun_l4_n866
+end
+
+def fun_l3_n589()
+ fun_l4_n539
+end
+
+def fun_l3_n590()
+ fun_l4_n240
+end
+
+def fun_l3_n591()
+ fun_l4_n438
+end
+
+def fun_l3_n592()
+ fun_l4_n652
+end
+
+def fun_l3_n593()
+ fun_l4_n540
+end
+
+def fun_l3_n594()
+ fun_l4_n122
+end
+
+def fun_l3_n595()
+ fun_l4_n877
+end
+
+def fun_l3_n596()
+ fun_l4_n30
+end
+
+def fun_l3_n597()
+ fun_l4_n465
+end
+
+def fun_l3_n598()
+ fun_l4_n964
+end
+
+def fun_l3_n599()
+ fun_l4_n123
+end
+
+def fun_l3_n600()
+ fun_l4_n365
+end
+
+def fun_l3_n601()
+ fun_l4_n531
+end
+
+def fun_l3_n602()
+ fun_l4_n774
+end
+
+def fun_l3_n603()
+ fun_l4_n961
+end
+
+def fun_l3_n604()
+ fun_l4_n360
+end
+
+def fun_l3_n605()
+ fun_l4_n640
+end
+
+def fun_l3_n606()
+ fun_l4_n785
+end
+
+def fun_l3_n607()
+ fun_l4_n433
+end
+
+def fun_l3_n608()
+ fun_l4_n528
+end
+
+def fun_l3_n609()
+ fun_l4_n125
+end
+
+def fun_l3_n610()
+ fun_l4_n179
+end
+
+def fun_l3_n611()
+ fun_l4_n946
+end
+
+def fun_l3_n612()
+ fun_l4_n899
+end
+
+def fun_l3_n613()
+ fun_l4_n917
+end
+
+def fun_l3_n614()
+ fun_l4_n444
+end
+
+def fun_l3_n615()
+ fun_l4_n823
+end
+
+def fun_l3_n616()
+ fun_l4_n221
+end
+
+def fun_l3_n617()
+ fun_l4_n483
+end
+
+def fun_l3_n618()
+ fun_l4_n112
+end
+
+def fun_l3_n619()
+ fun_l4_n814
+end
+
+def fun_l3_n620()
+ fun_l4_n648
+end
+
+def fun_l3_n621()
+ fun_l4_n823
+end
+
+def fun_l3_n622()
+ fun_l4_n457
+end
+
+def fun_l3_n623()
+ fun_l4_n92
+end
+
+def fun_l3_n624()
+ fun_l4_n8
+end
+
+def fun_l3_n625()
+ fun_l4_n297
+end
+
+def fun_l3_n626()
+ fun_l4_n517
+end
+
+def fun_l3_n627()
+ fun_l4_n159
+end
+
+def fun_l3_n628()
+ fun_l4_n79
+end
+
+def fun_l3_n629()
+ fun_l4_n791
+end
+
+def fun_l3_n630()
+ fun_l4_n692
+end
+
+def fun_l3_n631()
+ fun_l4_n554
+end
+
+def fun_l3_n632()
+ fun_l4_n872
+end
+
+def fun_l3_n633()
+ fun_l4_n871
+end
+
+def fun_l3_n634()
+ fun_l4_n524
+end
+
+def fun_l3_n635()
+ fun_l4_n588
+end
+
+def fun_l3_n636()
+ fun_l4_n596
+end
+
+def fun_l3_n637()
+ fun_l4_n936
+end
+
+def fun_l3_n638()
+ fun_l4_n478
+end
+
+def fun_l3_n639()
+ fun_l4_n893
+end
+
+def fun_l3_n640()
+ fun_l4_n348
+end
+
+def fun_l3_n641()
+ fun_l4_n806
+end
+
+def fun_l3_n642()
+ fun_l4_n522
+end
+
+def fun_l3_n643()
+ fun_l4_n249
+end
+
+def fun_l3_n644()
+ fun_l4_n208
+end
+
+def fun_l3_n645()
+ fun_l4_n989
+end
+
+def fun_l3_n646()
+ fun_l4_n194
+end
+
+def fun_l3_n647()
+ fun_l4_n157
+end
+
+def fun_l3_n648()
+ fun_l4_n395
+end
+
+def fun_l3_n649()
+ fun_l4_n191
+end
+
+def fun_l3_n650()
+ fun_l4_n292
+end
+
+def fun_l3_n651()
+ fun_l4_n640
+end
+
+def fun_l3_n652()
+ fun_l4_n818
+end
+
+def fun_l3_n653()
+ fun_l4_n481
+end
+
+def fun_l3_n654()
+ fun_l4_n304
+end
+
+def fun_l3_n655()
+ fun_l4_n102
+end
+
+def fun_l3_n656()
+ fun_l4_n51
+end
+
+def fun_l3_n657()
+ fun_l4_n110
+end
+
+def fun_l3_n658()
+ fun_l4_n226
+end
+
+def fun_l3_n659()
+ fun_l4_n48
+end
+
+def fun_l3_n660()
+ fun_l4_n112
+end
+
+def fun_l3_n661()
+ fun_l4_n677
+end
+
+def fun_l3_n662()
+ fun_l4_n168
+end
+
+def fun_l3_n663()
+ fun_l4_n15
+end
+
+def fun_l3_n664()
+ fun_l4_n311
+end
+
+def fun_l3_n665()
+ fun_l4_n935
+end
+
+def fun_l3_n666()
+ fun_l4_n861
+end
+
+def fun_l3_n667()
+ fun_l4_n169
+end
+
+def fun_l3_n668()
+ fun_l4_n395
+end
+
+def fun_l3_n669()
+ fun_l4_n371
+end
+
+def fun_l3_n670()
+ fun_l4_n625
+end
+
+def fun_l3_n671()
+ fun_l4_n183
+end
+
+def fun_l3_n672()
+ fun_l4_n299
+end
+
+def fun_l3_n673()
+ fun_l4_n104
+end
+
+def fun_l3_n674()
+ fun_l4_n413
+end
+
+def fun_l3_n675()
+ fun_l4_n957
+end
+
+def fun_l3_n676()
+ fun_l4_n878
+end
+
+def fun_l3_n677()
+ fun_l4_n222
+end
+
+def fun_l3_n678()
+ fun_l4_n832
+end
+
+def fun_l3_n679()
+ fun_l4_n406
+end
+
+def fun_l3_n680()
+ fun_l4_n779
+end
+
+def fun_l3_n681()
+ fun_l4_n874
+end
+
+def fun_l3_n682()
+ fun_l4_n328
+end
+
+def fun_l3_n683()
+ fun_l4_n412
+end
+
+def fun_l3_n684()
+ fun_l4_n46
+end
+
+def fun_l3_n685()
+ fun_l4_n799
+end
+
+def fun_l3_n686()
+ fun_l4_n751
+end
+
+def fun_l3_n687()
+ fun_l4_n32
+end
+
+def fun_l3_n688()
+ fun_l4_n237
+end
+
+def fun_l3_n689()
+ fun_l4_n770
+end
+
+def fun_l3_n690()
+ fun_l4_n120
+end
+
+def fun_l3_n691()
+ fun_l4_n977
+end
+
+def fun_l3_n692()
+ fun_l4_n35
+end
+
+def fun_l3_n693()
+ fun_l4_n398
+end
+
+def fun_l3_n694()
+ fun_l4_n551
+end
+
+def fun_l3_n695()
+ fun_l4_n122
+end
+
+def fun_l3_n696()
+ fun_l4_n268
+end
+
+def fun_l3_n697()
+ fun_l4_n628
+end
+
+def fun_l3_n698()
+ fun_l4_n611
+end
+
+def fun_l3_n699()
+ fun_l4_n382
+end
+
+def fun_l3_n700()
+ fun_l4_n819
+end
+
+def fun_l3_n701()
+ fun_l4_n124
+end
+
+def fun_l3_n702()
+ fun_l4_n529
+end
+
+def fun_l3_n703()
+ fun_l4_n838
+end
+
+def fun_l3_n704()
+ fun_l4_n181
+end
+
+def fun_l3_n705()
+ fun_l4_n123
+end
+
+def fun_l3_n706()
+ fun_l4_n646
+end
+
+def fun_l3_n707()
+ fun_l4_n193
+end
+
+def fun_l3_n708()
+ fun_l4_n233
+end
+
+def fun_l3_n709()
+ fun_l4_n621
+end
+
+def fun_l3_n710()
+ fun_l4_n772
+end
+
+def fun_l3_n711()
+ fun_l4_n461
+end
+
+def fun_l3_n712()
+ fun_l4_n673
+end
+
+def fun_l3_n713()
+ fun_l4_n101
+end
+
+def fun_l3_n714()
+ fun_l4_n467
+end
+
+def fun_l3_n715()
+ fun_l4_n211
+end
+
+def fun_l3_n716()
+ fun_l4_n554
+end
+
+def fun_l3_n717()
+ fun_l4_n276
+end
+
+def fun_l3_n718()
+ fun_l4_n655
+end
+
+def fun_l3_n719()
+ fun_l4_n425
+end
+
+def fun_l3_n720()
+ fun_l4_n241
+end
+
+def fun_l3_n721()
+ fun_l4_n904
+end
+
+def fun_l3_n722()
+ fun_l4_n839
+end
+
+def fun_l3_n723()
+ fun_l4_n991
+end
+
+def fun_l3_n724()
+ fun_l4_n556
+end
+
+def fun_l3_n725()
+ fun_l4_n86
+end
+
+def fun_l3_n726()
+ fun_l4_n953
+end
+
+def fun_l3_n727()
+ fun_l4_n18
+end
+
+def fun_l3_n728()
+ fun_l4_n374
+end
+
+def fun_l3_n729()
+ fun_l4_n712
+end
+
+def fun_l3_n730()
+ fun_l4_n228
+end
+
+def fun_l3_n731()
+ fun_l4_n830
+end
+
+def fun_l3_n732()
+ fun_l4_n49
+end
+
+def fun_l3_n733()
+ fun_l4_n987
+end
+
+def fun_l3_n734()
+ fun_l4_n815
+end
+
+def fun_l3_n735()
+ fun_l4_n386
+end
+
+def fun_l3_n736()
+ fun_l4_n843
+end
+
+def fun_l3_n737()
+ fun_l4_n958
+end
+
+def fun_l3_n738()
+ fun_l4_n317
+end
+
+def fun_l3_n739()
+ fun_l4_n361
+end
+
+def fun_l3_n740()
+ fun_l4_n392
+end
+
+def fun_l3_n741()
+ fun_l4_n888
+end
+
+def fun_l3_n742()
+ fun_l4_n186
+end
+
+def fun_l3_n743()
+ fun_l4_n493
+end
+
+def fun_l3_n744()
+ fun_l4_n302
+end
+
+def fun_l3_n745()
+ fun_l4_n690
+end
+
+def fun_l3_n746()
+ fun_l4_n601
+end
+
+def fun_l3_n747()
+ fun_l4_n975
+end
+
+def fun_l3_n748()
+ fun_l4_n543
+end
+
+def fun_l3_n749()
+ fun_l4_n8
+end
+
+def fun_l3_n750()
+ fun_l4_n905
+end
+
+def fun_l3_n751()
+ fun_l4_n964
+end
+
+def fun_l3_n752()
+ fun_l4_n739
+end
+
+def fun_l3_n753()
+ fun_l4_n24
+end
+
+def fun_l3_n754()
+ fun_l4_n806
+end
+
+def fun_l3_n755()
+ fun_l4_n704
+end
+
+def fun_l3_n756()
+ fun_l4_n579
+end
+
+def fun_l3_n757()
+ fun_l4_n264
+end
+
+def fun_l3_n758()
+ fun_l4_n357
+end
+
+def fun_l3_n759()
+ fun_l4_n333
+end
+
+def fun_l3_n760()
+ fun_l4_n309
+end
+
+def fun_l3_n761()
+ fun_l4_n419
+end
+
+def fun_l3_n762()
+ fun_l4_n347
+end
+
+def fun_l3_n763()
+ fun_l4_n132
+end
+
+def fun_l3_n764()
+ fun_l4_n45
+end
+
+def fun_l3_n765()
+ fun_l4_n740
+end
+
+def fun_l3_n766()
+ fun_l4_n332
+end
+
+def fun_l3_n767()
+ fun_l4_n600
+end
+
+def fun_l3_n768()
+ fun_l4_n343
+end
+
+def fun_l3_n769()
+ fun_l4_n872
+end
+
+def fun_l3_n770()
+ fun_l4_n326
+end
+
+def fun_l3_n771()
+ fun_l4_n862
+end
+
+def fun_l3_n772()
+ fun_l4_n800
+end
+
+def fun_l3_n773()
+ fun_l4_n616
+end
+
+def fun_l3_n774()
+ fun_l4_n392
+end
+
+def fun_l3_n775()
+ fun_l4_n252
+end
+
+def fun_l3_n776()
+ fun_l4_n289
+end
+
+def fun_l3_n777()
+ fun_l4_n789
+end
+
+def fun_l3_n778()
+ fun_l4_n370
+end
+
+def fun_l3_n779()
+ fun_l4_n969
+end
+
+def fun_l3_n780()
+ fun_l4_n444
+end
+
+def fun_l3_n781()
+ fun_l4_n671
+end
+
+def fun_l3_n782()
+ fun_l4_n301
+end
+
+def fun_l3_n783()
+ fun_l4_n418
+end
+
+def fun_l3_n784()
+ fun_l4_n491
+end
+
+def fun_l3_n785()
+ fun_l4_n746
+end
+
+def fun_l3_n786()
+ fun_l4_n212
+end
+
+def fun_l3_n787()
+ fun_l4_n856
+end
+
+def fun_l3_n788()
+ fun_l4_n155
+end
+
+def fun_l3_n789()
+ fun_l4_n685
+end
+
+def fun_l3_n790()
+ fun_l4_n879
+end
+
+def fun_l3_n791()
+ fun_l4_n363
+end
+
+def fun_l3_n792()
+ fun_l4_n231
+end
+
+def fun_l3_n793()
+ fun_l4_n727
+end
+
+def fun_l3_n794()
+ fun_l4_n355
+end
+
+def fun_l3_n795()
+ fun_l4_n671
+end
+
+def fun_l3_n796()
+ fun_l4_n20
+end
+
+def fun_l3_n797()
+ fun_l4_n523
+end
+
+def fun_l3_n798()
+ fun_l4_n26
+end
+
+def fun_l3_n799()
+ fun_l4_n785
+end
+
+def fun_l3_n800()
+ fun_l4_n458
+end
+
+def fun_l3_n801()
+ fun_l4_n160
+end
+
+def fun_l3_n802()
+ fun_l4_n543
+end
+
+def fun_l3_n803()
+ fun_l4_n292
+end
+
+def fun_l3_n804()
+ fun_l4_n64
+end
+
+def fun_l3_n805()
+ fun_l4_n851
+end
+
+def fun_l3_n806()
+ fun_l4_n369
+end
+
+def fun_l3_n807()
+ fun_l4_n827
+end
+
+def fun_l3_n808()
+ fun_l4_n420
+end
+
+def fun_l3_n809()
+ fun_l4_n98
+end
+
+def fun_l3_n810()
+ fun_l4_n508
+end
+
+def fun_l3_n811()
+ fun_l4_n366
+end
+
+def fun_l3_n812()
+ fun_l4_n795
+end
+
+def fun_l3_n813()
+ fun_l4_n345
+end
+
+def fun_l3_n814()
+ fun_l4_n505
+end
+
+def fun_l3_n815()
+ fun_l4_n302
+end
+
+def fun_l3_n816()
+ fun_l4_n561
+end
+
+def fun_l3_n817()
+ fun_l4_n781
+end
+
+def fun_l3_n818()
+ fun_l4_n599
+end
+
+def fun_l3_n819()
+ fun_l4_n967
+end
+
+def fun_l3_n820()
+ fun_l4_n691
+end
+
+def fun_l3_n821()
+ fun_l4_n563
+end
+
+def fun_l3_n822()
+ fun_l4_n769
+end
+
+def fun_l3_n823()
+ fun_l4_n531
+end
+
+def fun_l3_n824()
+ fun_l4_n957
+end
+
+def fun_l3_n825()
+ fun_l4_n395
+end
+
+def fun_l3_n826()
+ fun_l4_n92
+end
+
+def fun_l3_n827()
+ fun_l4_n781
+end
+
+def fun_l3_n828()
+ fun_l4_n758
+end
+
+def fun_l3_n829()
+ fun_l4_n648
+end
+
+def fun_l3_n830()
+ fun_l4_n799
+end
+
+def fun_l3_n831()
+ fun_l4_n922
+end
+
+def fun_l3_n832()
+ fun_l4_n808
+end
+
+def fun_l3_n833()
+ fun_l4_n180
+end
+
+def fun_l3_n834()
+ fun_l4_n126
+end
+
+def fun_l3_n835()
+ fun_l4_n261
+end
+
+def fun_l3_n836()
+ fun_l4_n470
+end
+
+def fun_l3_n837()
+ fun_l4_n441
+end
+
+def fun_l3_n838()
+ fun_l4_n505
+end
+
+def fun_l3_n839()
+ fun_l4_n490
+end
+
+def fun_l3_n840()
+ fun_l4_n663
+end
+
+def fun_l3_n841()
+ fun_l4_n256
+end
+
+def fun_l3_n842()
+ fun_l4_n797
+end
+
+def fun_l3_n843()
+ fun_l4_n836
+end
+
+def fun_l3_n844()
+ fun_l4_n868
+end
+
+def fun_l3_n845()
+ fun_l4_n927
+end
+
+def fun_l3_n846()
+ fun_l4_n746
+end
+
+def fun_l3_n847()
+ fun_l4_n143
+end
+
+def fun_l3_n848()
+ fun_l4_n90
+end
+
+def fun_l3_n849()
+ fun_l4_n63
+end
+
+def fun_l3_n850()
+ fun_l4_n629
+end
+
+def fun_l3_n851()
+ fun_l4_n66
+end
+
+def fun_l3_n852()
+ fun_l4_n192
+end
+
+def fun_l3_n853()
+ fun_l4_n780
+end
+
+def fun_l3_n854()
+ fun_l4_n744
+end
+
+def fun_l3_n855()
+ fun_l4_n989
+end
+
+def fun_l3_n856()
+ fun_l4_n609
+end
+
+def fun_l3_n857()
+ fun_l4_n534
+end
+
+def fun_l3_n858()
+ fun_l4_n961
+end
+
+def fun_l3_n859()
+ fun_l4_n605
+end
+
+def fun_l3_n860()
+ fun_l4_n675
+end
+
+def fun_l3_n861()
+ fun_l4_n520
+end
+
+def fun_l3_n862()
+ fun_l4_n656
+end
+
+def fun_l3_n863()
+ fun_l4_n917
+end
+
+def fun_l3_n864()
+ fun_l4_n291
+end
+
+def fun_l3_n865()
+ fun_l4_n343
+end
+
+def fun_l3_n866()
+ fun_l4_n704
+end
+
+def fun_l3_n867()
+ fun_l4_n368
+end
+
+def fun_l3_n868()
+ fun_l4_n678
+end
+
+def fun_l3_n869()
+ fun_l4_n788
+end
+
+def fun_l3_n870()
+ fun_l4_n458
+end
+
+def fun_l3_n871()
+ fun_l4_n882
+end
+
+def fun_l3_n872()
+ fun_l4_n830
+end
+
+def fun_l3_n873()
+ fun_l4_n434
+end
+
+def fun_l3_n874()
+ fun_l4_n92
+end
+
+def fun_l3_n875()
+ fun_l4_n633
+end
+
+def fun_l3_n876()
+ fun_l4_n243
+end
+
+def fun_l3_n877()
+ fun_l4_n641
+end
+
+def fun_l3_n878()
+ fun_l4_n114
+end
+
+def fun_l3_n879()
+ fun_l4_n696
+end
+
+def fun_l3_n880()
+ fun_l4_n354
+end
+
+def fun_l3_n881()
+ fun_l4_n644
+end
+
+def fun_l3_n882()
+ fun_l4_n771
+end
+
+def fun_l3_n883()
+ fun_l4_n196
+end
+
+def fun_l3_n884()
+ fun_l4_n202
+end
+
+def fun_l3_n885()
+ fun_l4_n322
+end
+
+def fun_l3_n886()
+ fun_l4_n125
+end
+
+def fun_l3_n887()
+ fun_l4_n760
+end
+
+def fun_l3_n888()
+ fun_l4_n69
+end
+
+def fun_l3_n889()
+ fun_l4_n101
+end
+
+def fun_l3_n890()
+ fun_l4_n108
+end
+
+def fun_l3_n891()
+ fun_l4_n929
+end
+
+def fun_l3_n892()
+ fun_l4_n766
+end
+
+def fun_l3_n893()
+ fun_l4_n811
+end
+
+def fun_l3_n894()
+ fun_l4_n169
+end
+
+def fun_l3_n895()
+ fun_l4_n613
+end
+
+def fun_l3_n896()
+ fun_l4_n145
+end
+
+def fun_l3_n897()
+ fun_l4_n780
+end
+
+def fun_l3_n898()
+ fun_l4_n972
+end
+
+def fun_l3_n899()
+ fun_l4_n508
+end
+
+def fun_l3_n900()
+ fun_l4_n468
+end
+
+def fun_l3_n901()
+ fun_l4_n968
+end
+
+def fun_l3_n902()
+ fun_l4_n714
+end
+
+def fun_l3_n903()
+ fun_l4_n817
+end
+
+def fun_l3_n904()
+ fun_l4_n111
+end
+
+def fun_l3_n905()
+ fun_l4_n115
+end
+
+def fun_l3_n906()
+ fun_l4_n593
+end
+
+def fun_l3_n907()
+ fun_l4_n961
+end
+
+def fun_l3_n908()
+ fun_l4_n362
+end
+
+def fun_l3_n909()
+ fun_l4_n251
+end
+
+def fun_l3_n910()
+ fun_l4_n532
+end
+
+def fun_l3_n911()
+ fun_l4_n252
+end
+
+def fun_l3_n912()
+ fun_l4_n751
+end
+
+def fun_l3_n913()
+ fun_l4_n962
+end
+
+def fun_l3_n914()
+ fun_l4_n151
+end
+
+def fun_l3_n915()
+ fun_l4_n91
+end
+
+def fun_l3_n916()
+ fun_l4_n164
+end
+
+def fun_l3_n917()
+ fun_l4_n714
+end
+
+def fun_l3_n918()
+ fun_l4_n496
+end
+
+def fun_l3_n919()
+ fun_l4_n833
+end
+
+def fun_l3_n920()
+ fun_l4_n315
+end
+
+def fun_l3_n921()
+ fun_l4_n551
+end
+
+def fun_l3_n922()
+ fun_l4_n986
+end
+
+def fun_l3_n923()
+ fun_l4_n924
+end
+
+def fun_l3_n924()
+ fun_l4_n670
+end
+
+def fun_l3_n925()
+ fun_l4_n611
+end
+
+def fun_l3_n926()
+ fun_l4_n590
+end
+
+def fun_l3_n927()
+ fun_l4_n951
+end
+
+def fun_l3_n928()
+ fun_l4_n438
+end
+
+def fun_l3_n929()
+ fun_l4_n914
+end
+
+def fun_l3_n930()
+ fun_l4_n357
+end
+
+def fun_l3_n931()
+ fun_l4_n330
+end
+
+def fun_l3_n932()
+ fun_l4_n737
+end
+
+def fun_l3_n933()
+ fun_l4_n857
+end
+
+def fun_l3_n934()
+ fun_l4_n32
+end
+
+def fun_l3_n935()
+ fun_l4_n980
+end
+
+def fun_l3_n936()
+ fun_l4_n229
+end
+
+def fun_l3_n937()
+ fun_l4_n779
+end
+
+def fun_l3_n938()
+ fun_l4_n365
+end
+
+def fun_l3_n939()
+ fun_l4_n681
+end
+
+def fun_l3_n940()
+ fun_l4_n55
+end
+
+def fun_l3_n941()
+ fun_l4_n324
+end
+
+def fun_l3_n942()
+ fun_l4_n630
+end
+
+def fun_l3_n943()
+ fun_l4_n910
+end
+
+def fun_l3_n944()
+ fun_l4_n590
+end
+
+def fun_l3_n945()
+ fun_l4_n798
+end
+
+def fun_l3_n946()
+ fun_l4_n973
+end
+
+def fun_l3_n947()
+ fun_l4_n180
+end
+
+def fun_l3_n948()
+ fun_l4_n425
+end
+
+def fun_l3_n949()
+ fun_l4_n446
+end
+
+def fun_l3_n950()
+ fun_l4_n296
+end
+
+def fun_l3_n951()
+ fun_l4_n61
+end
+
+def fun_l3_n952()
+ fun_l4_n797
+end
+
+def fun_l3_n953()
+ fun_l4_n824
+end
+
+def fun_l3_n954()
+ fun_l4_n336
+end
+
+def fun_l3_n955()
+ fun_l4_n82
+end
+
+def fun_l3_n956()
+ fun_l4_n310
+end
+
+def fun_l3_n957()
+ fun_l4_n983
+end
+
+def fun_l3_n958()
+ fun_l4_n780
+end
+
+def fun_l3_n959()
+ fun_l4_n697
+end
+
+def fun_l3_n960()
+ fun_l4_n822
+end
+
+def fun_l3_n961()
+ fun_l4_n209
+end
+
+def fun_l3_n962()
+ fun_l4_n549
+end
+
+def fun_l3_n963()
+ fun_l4_n226
+end
+
+def fun_l3_n964()
+ fun_l4_n324
+end
+
+def fun_l3_n965()
+ fun_l4_n63
+end
+
+def fun_l3_n966()
+ fun_l4_n430
+end
+
+def fun_l3_n967()
+ fun_l4_n645
+end
+
+def fun_l3_n968()
+ fun_l4_n875
+end
+
+def fun_l3_n969()
+ fun_l4_n713
+end
+
+def fun_l3_n970()
+ fun_l4_n457
+end
+
+def fun_l3_n971()
+ fun_l4_n768
+end
+
+def fun_l3_n972()
+ fun_l4_n548
+end
+
+def fun_l3_n973()
+ fun_l4_n577
+end
+
+def fun_l3_n974()
+ fun_l4_n109
+end
+
+def fun_l3_n975()
+ fun_l4_n460
+end
+
+def fun_l3_n976()
+ fun_l4_n83
+end
+
+def fun_l3_n977()
+ fun_l4_n152
+end
+
+def fun_l3_n978()
+ fun_l4_n224
+end
+
+def fun_l3_n979()
+ fun_l4_n897
+end
+
+def fun_l3_n980()
+ fun_l4_n830
+end
+
+def fun_l3_n981()
+ fun_l4_n747
+end
+
+def fun_l3_n982()
+ fun_l4_n21
+end
+
+def fun_l3_n983()
+ fun_l4_n84
+end
+
+def fun_l3_n984()
+ fun_l4_n342
+end
+
+def fun_l3_n985()
+ fun_l4_n950
+end
+
+def fun_l3_n986()
+ fun_l4_n33
+end
+
+def fun_l3_n987()
+ fun_l4_n388
+end
+
+def fun_l3_n988()
+ fun_l4_n766
+end
+
+def fun_l3_n989()
+ fun_l4_n708
+end
+
+def fun_l3_n990()
+ fun_l4_n392
+end
+
+def fun_l3_n991()
+ fun_l4_n782
+end
+
+def fun_l3_n992()
+ fun_l4_n223
+end
+
+def fun_l3_n993()
+ fun_l4_n416
+end
+
+def fun_l3_n994()
+ fun_l4_n609
+end
+
+def fun_l3_n995()
+ fun_l4_n158
+end
+
+def fun_l3_n996()
+ fun_l4_n246
+end
+
+def fun_l3_n997()
+ fun_l4_n667
+end
+
+def fun_l3_n998()
+ fun_l4_n126
+end
+
+def fun_l3_n999()
+ fun_l4_n726
+end
+
+def fun_l4_n0()
+ fun_l5_n544
+end
+
+def fun_l4_n1()
+ fun_l5_n456
+end
+
+def fun_l4_n2()
+ fun_l5_n364
+end
+
+def fun_l4_n3()
+ fun_l5_n929
+end
+
+def fun_l4_n4()
+ fun_l5_n593
+end
+
+def fun_l4_n5()
+ fun_l5_n287
+end
+
+def fun_l4_n6()
+ fun_l5_n272
+end
+
+def fun_l4_n7()
+ fun_l5_n71
+end
+
+def fun_l4_n8()
+ fun_l5_n704
+end
+
+def fun_l4_n9()
+ fun_l5_n462
+end
+
+def fun_l4_n10()
+ fun_l5_n239
+end
+
+def fun_l4_n11()
+ fun_l5_n853
+end
+
+def fun_l4_n12()
+ fun_l5_n217
+end
+
+def fun_l4_n13()
+ fun_l5_n822
+end
+
+def fun_l4_n14()
+ fun_l5_n663
+end
+
+def fun_l4_n15()
+ fun_l5_n400
+end
+
+def fun_l4_n16()
+ fun_l5_n307
+end
+
+def fun_l4_n17()
+ fun_l5_n820
+end
+
+def fun_l4_n18()
+ fun_l5_n885
+end
+
+def fun_l4_n19()
+ fun_l5_n680
+end
+
+def fun_l4_n20()
+ fun_l5_n592
+end
+
+def fun_l4_n21()
+ fun_l5_n615
+end
+
+def fun_l4_n22()
+ fun_l5_n669
+end
+
+def fun_l4_n23()
+ fun_l5_n978
+end
+
+def fun_l4_n24()
+ fun_l5_n946
+end
+
+def fun_l4_n25()
+ fun_l5_n915
+end
+
+def fun_l4_n26()
+ fun_l5_n286
+end
+
+def fun_l4_n27()
+ fun_l5_n466
+end
+
+def fun_l4_n28()
+ fun_l5_n970
+end
+
+def fun_l4_n29()
+ fun_l5_n822
+end
+
+def fun_l4_n30()
+ fun_l5_n883
+end
+
+def fun_l4_n31()
+ fun_l5_n137
+end
+
+def fun_l4_n32()
+ fun_l5_n957
+end
+
+def fun_l4_n33()
+ fun_l5_n912
+end
+
+def fun_l4_n34()
+ fun_l5_n156
+end
+
+def fun_l4_n35()
+ fun_l5_n207
+end
+
+def fun_l4_n36()
+ fun_l5_n525
+end
+
+def fun_l4_n37()
+ fun_l5_n673
+end
+
+def fun_l4_n38()
+ fun_l5_n151
+end
+
+def fun_l4_n39()
+ fun_l5_n517
+end
+
+def fun_l4_n40()
+ fun_l5_n459
+end
+
+def fun_l4_n41()
+ fun_l5_n738
+end
+
+def fun_l4_n42()
+ fun_l5_n809
+end
+
+def fun_l4_n43()
+ fun_l5_n853
+end
+
+def fun_l4_n44()
+ fun_l5_n653
+end
+
+def fun_l4_n45()
+ fun_l5_n346
+end
+
+def fun_l4_n46()
+ fun_l5_n704
+end
+
+def fun_l4_n47()
+ fun_l5_n662
+end
+
+def fun_l4_n48()
+ fun_l5_n990
+end
+
+def fun_l4_n49()
+ fun_l5_n731
+end
+
+def fun_l4_n50()
+ fun_l5_n305
+end
+
+def fun_l4_n51()
+ fun_l5_n238
+end
+
+def fun_l4_n52()
+ fun_l5_n710
+end
+
+def fun_l4_n53()
+ fun_l5_n61
+end
+
+def fun_l4_n54()
+ fun_l5_n572
+end
+
+def fun_l4_n55()
+ fun_l5_n939
+end
+
+def fun_l4_n56()
+ fun_l5_n223
+end
+
+def fun_l4_n57()
+ fun_l5_n466
+end
+
+def fun_l4_n58()
+ fun_l5_n442
+end
+
+def fun_l4_n59()
+ fun_l5_n971
+end
+
+def fun_l4_n60()
+ fun_l5_n42
+end
+
+def fun_l4_n61()
+ fun_l5_n390
+end
+
+def fun_l4_n62()
+ fun_l5_n254
+end
+
+def fun_l4_n63()
+ fun_l5_n522
+end
+
+def fun_l4_n64()
+ fun_l5_n16
+end
+
+def fun_l4_n65()
+ fun_l5_n567
+end
+
+def fun_l4_n66()
+ fun_l5_n353
+end
+
+def fun_l4_n67()
+ fun_l5_n676
+end
+
+def fun_l4_n68()
+ fun_l5_n526
+end
+
+def fun_l4_n69()
+ fun_l5_n140
+end
+
+def fun_l4_n70()
+ fun_l5_n829
+end
+
+def fun_l4_n71()
+ fun_l5_n562
+end
+
+def fun_l4_n72()
+ fun_l5_n489
+end
+
+def fun_l4_n73()
+ fun_l5_n205
+end
+
+def fun_l4_n74()
+ fun_l5_n558
+end
+
+def fun_l4_n75()
+ fun_l5_n689
+end
+
+def fun_l4_n76()
+ fun_l5_n803
+end
+
+def fun_l4_n77()
+ fun_l5_n222
+end
+
+def fun_l4_n78()
+ fun_l5_n696
+end
+
+def fun_l4_n79()
+ fun_l5_n457
+end
+
+def fun_l4_n80()
+ fun_l5_n794
+end
+
+def fun_l4_n81()
+ fun_l5_n886
+end
+
+def fun_l4_n82()
+ fun_l5_n742
+end
+
+def fun_l4_n83()
+ fun_l5_n560
+end
+
+def fun_l4_n84()
+ fun_l5_n207
+end
+
+def fun_l4_n85()
+ fun_l5_n265
+end
+
+def fun_l4_n86()
+ fun_l5_n871
+end
+
+def fun_l4_n87()
+ fun_l5_n113
+end
+
+def fun_l4_n88()
+ fun_l5_n141
+end
+
+def fun_l4_n89()
+ fun_l5_n231
+end
+
+def fun_l4_n90()
+ fun_l5_n980
+end
+
+def fun_l4_n91()
+ fun_l5_n586
+end
+
+def fun_l4_n92()
+ fun_l5_n961
+end
+
+def fun_l4_n93()
+ fun_l5_n128
+end
+
+def fun_l4_n94()
+ fun_l5_n395
+end
+
+def fun_l4_n95()
+ fun_l5_n810
+end
+
+def fun_l4_n96()
+ fun_l5_n337
+end
+
+def fun_l4_n97()
+ fun_l5_n256
+end
+
+def fun_l4_n98()
+ fun_l5_n188
+end
+
+def fun_l4_n99()
+ fun_l5_n358
+end
+
+def fun_l4_n100()
+ fun_l5_n751
+end
+
+def fun_l4_n101()
+ fun_l5_n898
+end
+
+def fun_l4_n102()
+ fun_l5_n323
+end
+
+def fun_l4_n103()
+ fun_l5_n455
+end
+
+def fun_l4_n104()
+ fun_l5_n976
+end
+
+def fun_l4_n105()
+ fun_l5_n962
+end
+
+def fun_l4_n106()
+ fun_l5_n781
+end
+
+def fun_l4_n107()
+ fun_l5_n277
+end
+
+def fun_l4_n108()
+ fun_l5_n146
+end
+
+def fun_l4_n109()
+ fun_l5_n793
+end
+
+def fun_l4_n110()
+ fun_l5_n787
+end
+
+def fun_l4_n111()
+ fun_l5_n597
+end
+
+def fun_l4_n112()
+ fun_l5_n799
+end
+
+def fun_l4_n113()
+ fun_l5_n598
+end
+
+def fun_l4_n114()
+ fun_l5_n456
+end
+
+def fun_l4_n115()
+ fun_l5_n45
+end
+
+def fun_l4_n116()
+ fun_l5_n265
+end
+
+def fun_l4_n117()
+ fun_l5_n661
+end
+
+def fun_l4_n118()
+ fun_l5_n657
+end
+
+def fun_l4_n119()
+ fun_l5_n703
+end
+
+def fun_l4_n120()
+ fun_l5_n164
+end
+
+def fun_l4_n121()
+ fun_l5_n182
+end
+
+def fun_l4_n122()
+ fun_l5_n605
+end
+
+def fun_l4_n123()
+ fun_l5_n237
+end
+
+def fun_l4_n124()
+ fun_l5_n582
+end
+
+def fun_l4_n125()
+ fun_l5_n381
+end
+
+def fun_l4_n126()
+ fun_l5_n244
+end
+
+def fun_l4_n127()
+ fun_l5_n272
+end
+
+def fun_l4_n128()
+ fun_l5_n989
+end
+
+def fun_l4_n129()
+ fun_l5_n366
+end
+
+def fun_l4_n130()
+ fun_l5_n640
+end
+
+def fun_l4_n131()
+ fun_l5_n953
+end
+
+def fun_l4_n132()
+ fun_l5_n990
+end
+
+def fun_l4_n133()
+ fun_l5_n497
+end
+
+def fun_l4_n134()
+ fun_l5_n12
+end
+
+def fun_l4_n135()
+ fun_l5_n993
+end
+
+def fun_l4_n136()
+ fun_l5_n802
+end
+
+def fun_l4_n137()
+ fun_l5_n411
+end
+
+def fun_l4_n138()
+ fun_l5_n154
+end
+
+def fun_l4_n139()
+ fun_l5_n924
+end
+
+def fun_l4_n140()
+ fun_l5_n772
+end
+
+def fun_l4_n141()
+ fun_l5_n972
+end
+
+def fun_l4_n142()
+ fun_l5_n847
+end
+
+def fun_l4_n143()
+ fun_l5_n481
+end
+
+def fun_l4_n144()
+ fun_l5_n52
+end
+
+def fun_l4_n145()
+ fun_l5_n451
+end
+
+def fun_l4_n146()
+ fun_l5_n339
+end
+
+def fun_l4_n147()
+ fun_l5_n531
+end
+
+def fun_l4_n148()
+ fun_l5_n735
+end
+
+def fun_l4_n149()
+ fun_l5_n747
+end
+
+def fun_l4_n150()
+ fun_l5_n750
+end
+
+def fun_l4_n151()
+ fun_l5_n762
+end
+
+def fun_l4_n152()
+ fun_l5_n131
+end
+
+def fun_l4_n153()
+ fun_l5_n532
+end
+
+def fun_l4_n154()
+ fun_l5_n398
+end
+
+def fun_l4_n155()
+ fun_l5_n660
+end
+
+def fun_l4_n156()
+ fun_l5_n374
+end
+
+def fun_l4_n157()
+ fun_l5_n245
+end
+
+def fun_l4_n158()
+ fun_l5_n850
+end
+
+def fun_l4_n159()
+ fun_l5_n518
+end
+
+def fun_l4_n160()
+ fun_l5_n607
+end
+
+def fun_l4_n161()
+ fun_l5_n823
+end
+
+def fun_l4_n162()
+ fun_l5_n816
+end
+
+def fun_l4_n163()
+ fun_l5_n735
+end
+
+def fun_l4_n164()
+ fun_l5_n802
+end
+
+def fun_l4_n165()
+ fun_l5_n398
+end
+
+def fun_l4_n166()
+ fun_l5_n149
+end
+
+def fun_l4_n167()
+ fun_l5_n292
+end
+
+def fun_l4_n168()
+ fun_l5_n733
+end
+
+def fun_l4_n169()
+ fun_l5_n145
+end
+
+def fun_l4_n170()
+ fun_l5_n288
+end
+
+def fun_l4_n171()
+ fun_l5_n131
+end
+
+def fun_l4_n172()
+ fun_l5_n31
+end
+
+def fun_l4_n173()
+ fun_l5_n253
+end
+
+def fun_l4_n174()
+ fun_l5_n41
+end
+
+def fun_l4_n175()
+ fun_l5_n403
+end
+
+def fun_l4_n176()
+ fun_l5_n859
+end
+
+def fun_l4_n177()
+ fun_l5_n804
+end
+
+def fun_l4_n178()
+ fun_l5_n26
+end
+
+def fun_l4_n179()
+ fun_l5_n729
+end
+
+def fun_l4_n180()
+ fun_l5_n978
+end
+
+def fun_l4_n181()
+ fun_l5_n42
+end
+
+def fun_l4_n182()
+ fun_l5_n38
+end
+
+def fun_l4_n183()
+ fun_l5_n758
+end
+
+def fun_l4_n184()
+ fun_l5_n885
+end
+
+def fun_l4_n185()
+ fun_l5_n473
+end
+
+def fun_l4_n186()
+ fun_l5_n737
+end
+
+def fun_l4_n187()
+ fun_l5_n889
+end
+
+def fun_l4_n188()
+ fun_l5_n398
+end
+
+def fun_l4_n189()
+ fun_l5_n72
+end
+
+def fun_l4_n190()
+ fun_l5_n725
+end
+
+def fun_l4_n191()
+ fun_l5_n774
+end
+
+def fun_l4_n192()
+ fun_l5_n453
+end
+
+def fun_l4_n193()
+ fun_l5_n370
+end
+
+def fun_l4_n194()
+ fun_l5_n648
+end
+
+def fun_l4_n195()
+ fun_l5_n882
+end
+
+def fun_l4_n196()
+ fun_l5_n745
+end
+
+def fun_l4_n197()
+ fun_l5_n529
+end
+
+def fun_l4_n198()
+ fun_l5_n957
+end
+
+def fun_l4_n199()
+ fun_l5_n423
+end
+
+def fun_l4_n200()
+ fun_l5_n399
+end
+
+def fun_l4_n201()
+ fun_l5_n917
+end
+
+def fun_l4_n202()
+ fun_l5_n634
+end
+
+def fun_l4_n203()
+ fun_l5_n868
+end
+
+def fun_l4_n204()
+ fun_l5_n627
+end
+
+def fun_l4_n205()
+ fun_l5_n514
+end
+
+def fun_l4_n206()
+ fun_l5_n61
+end
+
+def fun_l4_n207()
+ fun_l5_n848
+end
+
+def fun_l4_n208()
+ fun_l5_n611
+end
+
+def fun_l4_n209()
+ fun_l5_n417
+end
+
+def fun_l4_n210()
+ fun_l5_n423
+end
+
+def fun_l4_n211()
+ fun_l5_n247
+end
+
+def fun_l4_n212()
+ fun_l5_n208
+end
+
+def fun_l4_n213()
+ fun_l5_n253
+end
+
+def fun_l4_n214()
+ fun_l5_n833
+end
+
+def fun_l4_n215()
+ fun_l5_n351
+end
+
+def fun_l4_n216()
+ fun_l5_n326
+end
+
+def fun_l4_n217()
+ fun_l5_n741
+end
+
+def fun_l4_n218()
+ fun_l5_n958
+end
+
+def fun_l4_n219()
+ fun_l5_n347
+end
+
+def fun_l4_n220()
+ fun_l5_n317
+end
+
+def fun_l4_n221()
+ fun_l5_n291
+end
+
+def fun_l4_n222()
+ fun_l5_n863
+end
+
+def fun_l4_n223()
+ fun_l5_n30
+end
+
+def fun_l4_n224()
+ fun_l5_n413
+end
+
+def fun_l4_n225()
+ fun_l5_n352
+end
+
+def fun_l4_n226()
+ fun_l5_n125
+end
+
+def fun_l4_n227()
+ fun_l5_n266
+end
+
+def fun_l4_n228()
+ fun_l5_n264
+end
+
+def fun_l4_n229()
+ fun_l5_n745
+end
+
+def fun_l4_n230()
+ fun_l5_n622
+end
+
+def fun_l4_n231()
+ fun_l5_n160
+end
+
+def fun_l4_n232()
+ fun_l5_n121
+end
+
+def fun_l4_n233()
+ fun_l5_n150
+end
+
+def fun_l4_n234()
+ fun_l5_n495
+end
+
+def fun_l4_n235()
+ fun_l5_n905
+end
+
+def fun_l4_n236()
+ fun_l5_n886
+end
+
+def fun_l4_n237()
+ fun_l5_n221
+end
+
+def fun_l4_n238()
+ fun_l5_n912
+end
+
+def fun_l4_n239()
+ fun_l5_n834
+end
+
+def fun_l4_n240()
+ fun_l5_n703
+end
+
+def fun_l4_n241()
+ fun_l5_n651
+end
+
+def fun_l4_n242()
+ fun_l5_n404
+end
+
+def fun_l4_n243()
+ fun_l5_n213
+end
+
+def fun_l4_n244()
+ fun_l5_n342
+end
+
+def fun_l4_n245()
+ fun_l5_n887
+end
+
+def fun_l4_n246()
+ fun_l5_n69
+end
+
+def fun_l4_n247()
+ fun_l5_n835
+end
+
+def fun_l4_n248()
+ fun_l5_n856
+end
+
+def fun_l4_n249()
+ fun_l5_n485
+end
+
+def fun_l4_n250()
+ fun_l5_n441
+end
+
+def fun_l4_n251()
+ fun_l5_n976
+end
+
+def fun_l4_n252()
+ fun_l5_n586
+end
+
+def fun_l4_n253()
+ fun_l5_n728
+end
+
+def fun_l4_n254()
+ fun_l5_n377
+end
+
+def fun_l4_n255()
+ fun_l5_n293
+end
+
+def fun_l4_n256()
+ fun_l5_n149
+end
+
+def fun_l4_n257()
+ fun_l5_n205
+end
+
+def fun_l4_n258()
+ fun_l5_n301
+end
+
+def fun_l4_n259()
+ fun_l5_n528
+end
+
+def fun_l4_n260()
+ fun_l5_n642
+end
+
+def fun_l4_n261()
+ fun_l5_n430
+end
+
+def fun_l4_n262()
+ fun_l5_n14
+end
+
+def fun_l4_n263()
+ fun_l5_n796
+end
+
+def fun_l4_n264()
+ fun_l5_n849
+end
+
+def fun_l4_n265()
+ fun_l5_n547
+end
+
+def fun_l4_n266()
+ fun_l5_n946
+end
+
+def fun_l4_n267()
+ fun_l5_n131
+end
+
+def fun_l4_n268()
+ fun_l5_n141
+end
+
+def fun_l4_n269()
+ fun_l5_n9
+end
+
+def fun_l4_n270()
+ fun_l5_n884
+end
+
+def fun_l4_n271()
+ fun_l5_n978
+end
+
+def fun_l4_n272()
+ fun_l5_n47
+end
+
+def fun_l4_n273()
+ fun_l5_n100
+end
+
+def fun_l4_n274()
+ fun_l5_n254
+end
+
+def fun_l4_n275()
+ fun_l5_n972
+end
+
+def fun_l4_n276()
+ fun_l5_n705
+end
+
+def fun_l4_n277()
+ fun_l5_n504
+end
+
+def fun_l4_n278()
+ fun_l5_n854
+end
+
+def fun_l4_n279()
+ fun_l5_n331
+end
+
+def fun_l4_n280()
+ fun_l5_n394
+end
+
+def fun_l4_n281()
+ fun_l5_n922
+end
+
+def fun_l4_n282()
+ fun_l5_n503
+end
+
+def fun_l4_n283()
+ fun_l5_n854
+end
+
+def fun_l4_n284()
+ fun_l5_n679
+end
+
+def fun_l4_n285()
+ fun_l5_n317
+end
+
+def fun_l4_n286()
+ fun_l5_n753
+end
+
+def fun_l4_n287()
+ fun_l5_n154
+end
+
+def fun_l4_n288()
+ fun_l5_n184
+end
+
+def fun_l4_n289()
+ fun_l5_n416
+end
+
+def fun_l4_n290()
+ fun_l5_n426
+end
+
+def fun_l4_n291()
+ fun_l5_n186
+end
+
+def fun_l4_n292()
+ fun_l5_n527
+end
+
+def fun_l4_n293()
+ fun_l5_n483
+end
+
+def fun_l4_n294()
+ fun_l5_n718
+end
+
+def fun_l4_n295()
+ fun_l5_n469
+end
+
+def fun_l4_n296()
+ fun_l5_n842
+end
+
+def fun_l4_n297()
+ fun_l5_n998
+end
+
+def fun_l4_n298()
+ fun_l5_n964
+end
+
+def fun_l4_n299()
+ fun_l5_n377
+end
+
+def fun_l4_n300()
+ fun_l5_n9
+end
+
+def fun_l4_n301()
+ fun_l5_n234
+end
+
+def fun_l4_n302()
+ fun_l5_n813
+end
+
+def fun_l4_n303()
+ fun_l5_n211
+end
+
+def fun_l4_n304()
+ fun_l5_n593
+end
+
+def fun_l4_n305()
+ fun_l5_n847
+end
+
+def fun_l4_n306()
+ fun_l5_n628
+end
+
+def fun_l4_n307()
+ fun_l5_n827
+end
+
+def fun_l4_n308()
+ fun_l5_n417
+end
+
+def fun_l4_n309()
+ fun_l5_n958
+end
+
+def fun_l4_n310()
+ fun_l5_n838
+end
+
+def fun_l4_n311()
+ fun_l5_n712
+end
+
+def fun_l4_n312()
+ fun_l5_n615
+end
+
+def fun_l4_n313()
+ fun_l5_n693
+end
+
+def fun_l4_n314()
+ fun_l5_n708
+end
+
+def fun_l4_n315()
+ fun_l5_n525
+end
+
+def fun_l4_n316()
+ fun_l5_n943
+end
+
+def fun_l4_n317()
+ fun_l5_n959
+end
+
+def fun_l4_n318()
+ fun_l5_n316
+end
+
+def fun_l4_n319()
+ fun_l5_n424
+end
+
+def fun_l4_n320()
+ fun_l5_n391
+end
+
+def fun_l4_n321()
+ fun_l5_n303
+end
+
+def fun_l4_n322()
+ fun_l5_n159
+end
+
+def fun_l4_n323()
+ fun_l5_n853
+end
+
+def fun_l4_n324()
+ fun_l5_n525
+end
+
+def fun_l4_n325()
+ fun_l5_n390
+end
+
+def fun_l4_n326()
+ fun_l5_n225
+end
+
+def fun_l4_n327()
+ fun_l5_n983
+end
+
+def fun_l4_n328()
+ fun_l5_n509
+end
+
+def fun_l4_n329()
+ fun_l5_n141
+end
+
+def fun_l4_n330()
+ fun_l5_n92
+end
+
+def fun_l4_n331()
+ fun_l5_n288
+end
+
+def fun_l4_n332()
+ fun_l5_n213
+end
+
+def fun_l4_n333()
+ fun_l5_n830
+end
+
+def fun_l4_n334()
+ fun_l5_n512
+end
+
+def fun_l4_n335()
+ fun_l5_n449
+end
+
+def fun_l4_n336()
+ fun_l5_n148
+end
+
+def fun_l4_n337()
+ fun_l5_n829
+end
+
+def fun_l4_n338()
+ fun_l5_n232
+end
+
+def fun_l4_n339()
+ fun_l5_n989
+end
+
+def fun_l4_n340()
+ fun_l5_n226
+end
+
+def fun_l4_n341()
+ fun_l5_n187
+end
+
+def fun_l4_n342()
+ fun_l5_n874
+end
+
+def fun_l4_n343()
+ fun_l5_n621
+end
+
+def fun_l4_n344()
+ fun_l5_n861
+end
+
+def fun_l4_n345()
+ fun_l5_n22
+end
+
+def fun_l4_n346()
+ fun_l5_n6
+end
+
+def fun_l4_n347()
+ fun_l5_n580
+end
+
+def fun_l4_n348()
+ fun_l5_n56
+end
+
+def fun_l4_n349()
+ fun_l5_n834
+end
+
+def fun_l4_n350()
+ fun_l5_n460
+end
+
+def fun_l4_n351()
+ fun_l5_n697
+end
+
+def fun_l4_n352()
+ fun_l5_n792
+end
+
+def fun_l4_n353()
+ fun_l5_n777
+end
+
+def fun_l4_n354()
+ fun_l5_n73
+end
+
+def fun_l4_n355()
+ fun_l5_n555
+end
+
+def fun_l4_n356()
+ fun_l5_n32
+end
+
+def fun_l4_n357()
+ fun_l5_n242
+end
+
+def fun_l4_n358()
+ fun_l5_n791
+end
+
+def fun_l4_n359()
+ fun_l5_n570
+end
+
+def fun_l4_n360()
+ fun_l5_n272
+end
+
+def fun_l4_n361()
+ fun_l5_n757
+end
+
+def fun_l4_n362()
+ fun_l5_n946
+end
+
+def fun_l4_n363()
+ fun_l5_n127
+end
+
+def fun_l4_n364()
+ fun_l5_n940
+end
+
+def fun_l4_n365()
+ fun_l5_n662
+end
+
+def fun_l4_n366()
+ fun_l5_n99
+end
+
+def fun_l4_n367()
+ fun_l5_n107
+end
+
+def fun_l4_n368()
+ fun_l5_n370
+end
+
+def fun_l4_n369()
+ fun_l5_n738
+end
+
+def fun_l4_n370()
+ fun_l5_n346
+end
+
+def fun_l4_n371()
+ fun_l5_n63
+end
+
+def fun_l4_n372()
+ fun_l5_n274
+end
+
+def fun_l4_n373()
+ fun_l5_n936
+end
+
+def fun_l4_n374()
+ fun_l5_n602
+end
+
+def fun_l4_n375()
+ fun_l5_n362
+end
+
+def fun_l4_n376()
+ fun_l5_n605
+end
+
+def fun_l4_n377()
+ fun_l5_n477
+end
+
+def fun_l4_n378()
+ fun_l5_n349
+end
+
+def fun_l4_n379()
+ fun_l5_n241
+end
+
+def fun_l4_n380()
+ fun_l5_n913
+end
+
+def fun_l4_n381()
+ fun_l5_n392
+end
+
+def fun_l4_n382()
+ fun_l5_n669
+end
+
+def fun_l4_n383()
+ fun_l5_n41
+end
+
+def fun_l4_n384()
+ fun_l5_n928
+end
+
+def fun_l4_n385()
+ fun_l5_n646
+end
+
+def fun_l4_n386()
+ fun_l5_n23
+end
+
+def fun_l4_n387()
+ fun_l5_n815
+end
+
+def fun_l4_n388()
+ fun_l5_n595
+end
+
+def fun_l4_n389()
+ fun_l5_n210
+end
+
+def fun_l4_n390()
+ fun_l5_n247
+end
+
+def fun_l4_n391()
+ fun_l5_n914
+end
+
+def fun_l4_n392()
+ fun_l5_n882
+end
+
+def fun_l4_n393()
+ fun_l5_n319
+end
+
+def fun_l4_n394()
+ fun_l5_n764
+end
+
+def fun_l4_n395()
+ fun_l5_n282
+end
+
+def fun_l4_n396()
+ fun_l5_n585
+end
+
+def fun_l4_n397()
+ fun_l5_n551
+end
+
+def fun_l4_n398()
+ fun_l5_n56
+end
+
+def fun_l4_n399()
+ fun_l5_n807
+end
+
+def fun_l4_n400()
+ fun_l5_n678
+end
+
+def fun_l4_n401()
+ fun_l5_n153
+end
+
+def fun_l4_n402()
+ fun_l5_n993
+end
+
+def fun_l4_n403()
+ fun_l5_n835
+end
+
+def fun_l4_n404()
+ fun_l5_n642
+end
+
+def fun_l4_n405()
+ fun_l5_n460
+end
+
+def fun_l4_n406()
+ fun_l5_n135
+end
+
+def fun_l4_n407()
+ fun_l5_n199
+end
+
+def fun_l4_n408()
+ fun_l5_n782
+end
+
+def fun_l4_n409()
+ fun_l5_n723
+end
+
+def fun_l4_n410()
+ fun_l5_n638
+end
+
+def fun_l4_n411()
+ fun_l5_n157
+end
+
+def fun_l4_n412()
+ fun_l5_n840
+end
+
+def fun_l4_n413()
+ fun_l5_n11
+end
+
+def fun_l4_n414()
+ fun_l5_n148
+end
+
+def fun_l4_n415()
+ fun_l5_n577
+end
+
+def fun_l4_n416()
+ fun_l5_n403
+end
+
+def fun_l4_n417()
+ fun_l5_n971
+end
+
+def fun_l4_n418()
+ fun_l5_n951
+end
+
+def fun_l4_n419()
+ fun_l5_n620
+end
+
+def fun_l4_n420()
+ fun_l5_n120
+end
+
+def fun_l4_n421()
+ fun_l5_n981
+end
+
+def fun_l4_n422()
+ fun_l5_n543
+end
+
+def fun_l4_n423()
+ fun_l5_n543
+end
+
+def fun_l4_n424()
+ fun_l5_n161
+end
+
+def fun_l4_n425()
+ fun_l5_n308
+end
+
+def fun_l4_n426()
+ fun_l5_n94
+end
+
+def fun_l4_n427()
+ fun_l5_n209
+end
+
+def fun_l4_n428()
+ fun_l5_n543
+end
+
+def fun_l4_n429()
+ fun_l5_n825
+end
+
+def fun_l4_n430()
+ fun_l5_n808
+end
+
+def fun_l4_n431()
+ fun_l5_n315
+end
+
+def fun_l4_n432()
+ fun_l5_n846
+end
+
+def fun_l4_n433()
+ fun_l5_n448
+end
+
+def fun_l4_n434()
+ fun_l5_n903
+end
+
+def fun_l4_n435()
+ fun_l5_n933
+end
+
+def fun_l4_n436()
+ fun_l5_n872
+end
+
+def fun_l4_n437()
+ fun_l5_n297
+end
+
+def fun_l4_n438()
+ fun_l5_n689
+end
+
+def fun_l4_n439()
+ fun_l5_n700
+end
+
+def fun_l4_n440()
+ fun_l5_n316
+end
+
+def fun_l4_n441()
+ fun_l5_n983
+end
+
+def fun_l4_n442()
+ fun_l5_n32
+end
+
+def fun_l4_n443()
+ fun_l5_n404
+end
+
+def fun_l4_n444()
+ fun_l5_n770
+end
+
+def fun_l4_n445()
+ fun_l5_n497
+end
+
+def fun_l4_n446()
+ fun_l5_n762
+end
+
+def fun_l4_n447()
+ fun_l5_n402
+end
+
+def fun_l4_n448()
+ fun_l5_n773
+end
+
+def fun_l4_n449()
+ fun_l5_n264
+end
+
+def fun_l4_n450()
+ fun_l5_n373
+end
+
+def fun_l4_n451()
+ fun_l5_n907
+end
+
+def fun_l4_n452()
+ fun_l5_n477
+end
+
+def fun_l4_n453()
+ fun_l5_n15
+end
+
+def fun_l4_n454()
+ fun_l5_n550
+end
+
+def fun_l4_n455()
+ fun_l5_n973
+end
+
+def fun_l4_n456()
+ fun_l5_n247
+end
+
+def fun_l4_n457()
+ fun_l5_n231
+end
+
+def fun_l4_n458()
+ fun_l5_n431
+end
+
+def fun_l4_n459()
+ fun_l5_n549
+end
+
+def fun_l4_n460()
+ fun_l5_n251
+end
+
+def fun_l4_n461()
+ fun_l5_n313
+end
+
+def fun_l4_n462()
+ fun_l5_n826
+end
+
+def fun_l4_n463()
+ fun_l5_n454
+end
+
+def fun_l4_n464()
+ fun_l5_n329
+end
+
+def fun_l4_n465()
+ fun_l5_n502
+end
+
+def fun_l4_n466()
+ fun_l5_n786
+end
+
+def fun_l4_n467()
+ fun_l5_n195
+end
+
+def fun_l4_n468()
+ fun_l5_n710
+end
+
+def fun_l4_n469()
+ fun_l5_n970
+end
+
+def fun_l4_n470()
+ fun_l5_n925
+end
+
+def fun_l4_n471()
+ fun_l5_n420
+end
+
+def fun_l4_n472()
+ fun_l5_n231
+end
+
+def fun_l4_n473()
+ fun_l5_n867
+end
+
+def fun_l4_n474()
+ fun_l5_n798
+end
+
+def fun_l4_n475()
+ fun_l5_n697
+end
+
+def fun_l4_n476()
+ fun_l5_n767
+end
+
+def fun_l4_n477()
+ fun_l5_n199
+end
+
+def fun_l4_n478()
+ fun_l5_n190
+end
+
+def fun_l4_n479()
+ fun_l5_n524
+end
+
+def fun_l4_n480()
+ fun_l5_n451
+end
+
+def fun_l4_n481()
+ fun_l5_n182
+end
+
+def fun_l4_n482()
+ fun_l5_n906
+end
+
+def fun_l4_n483()
+ fun_l5_n806
+end
+
+def fun_l4_n484()
+ fun_l5_n871
+end
+
+def fun_l4_n485()
+ fun_l5_n947
+end
+
+def fun_l4_n486()
+ fun_l5_n599
+end
+
+def fun_l4_n487()
+ fun_l5_n266
+end
+
+def fun_l4_n488()
+ fun_l5_n20
+end
+
+def fun_l4_n489()
+ fun_l5_n875
+end
+
+def fun_l4_n490()
+ fun_l5_n393
+end
+
+def fun_l4_n491()
+ fun_l5_n673
+end
+
+def fun_l4_n492()
+ fun_l5_n159
+end
+
+def fun_l4_n493()
+ fun_l5_n327
+end
+
+def fun_l4_n494()
+ fun_l5_n71
+end
+
+def fun_l4_n495()
+ fun_l5_n146
+end
+
+def fun_l4_n496()
+ fun_l5_n372
+end
+
+def fun_l4_n497()
+ fun_l5_n654
+end
+
+def fun_l4_n498()
+ fun_l5_n1
+end
+
+def fun_l4_n499()
+ fun_l5_n448
+end
+
+def fun_l4_n500()
+ fun_l5_n684
+end
+
+def fun_l4_n501()
+ fun_l5_n561
+end
+
+def fun_l4_n502()
+ fun_l5_n47
+end
+
+def fun_l4_n503()
+ fun_l5_n313
+end
+
+def fun_l4_n504()
+ fun_l5_n380
+end
+
+def fun_l4_n505()
+ fun_l5_n416
+end
+
+def fun_l4_n506()
+ fun_l5_n90
+end
+
+def fun_l4_n507()
+ fun_l5_n65
+end
+
+def fun_l4_n508()
+ fun_l5_n61
+end
+
+def fun_l4_n509()
+ fun_l5_n451
+end
+
+def fun_l4_n510()
+ fun_l5_n174
+end
+
+def fun_l4_n511()
+ fun_l5_n236
+end
+
+def fun_l4_n512()
+ fun_l5_n470
+end
+
+def fun_l4_n513()
+ fun_l5_n304
+end
+
+def fun_l4_n514()
+ fun_l5_n146
+end
+
+def fun_l4_n515()
+ fun_l5_n671
+end
+
+def fun_l4_n516()
+ fun_l5_n626
+end
+
+def fun_l4_n517()
+ fun_l5_n164
+end
+
+def fun_l4_n518()
+ fun_l5_n308
+end
+
+def fun_l4_n519()
+ fun_l5_n799
+end
+
+def fun_l4_n520()
+ fun_l5_n521
+end
+
+def fun_l4_n521()
+ fun_l5_n675
+end
+
+def fun_l4_n522()
+ fun_l5_n110
+end
+
+def fun_l4_n523()
+ fun_l5_n726
+end
+
+def fun_l4_n524()
+ fun_l5_n189
+end
+
+def fun_l4_n525()
+ fun_l5_n303
+end
+
+def fun_l4_n526()
+ fun_l5_n571
+end
+
+def fun_l4_n527()
+ fun_l5_n693
+end
+
+def fun_l4_n528()
+ fun_l5_n782
+end
+
+def fun_l4_n529()
+ fun_l5_n764
+end
+
+def fun_l4_n530()
+ fun_l5_n629
+end
+
+def fun_l4_n531()
+ fun_l5_n677
+end
+
+def fun_l4_n532()
+ fun_l5_n745
+end
+
+def fun_l4_n533()
+ fun_l5_n868
+end
+
+def fun_l4_n534()
+ fun_l5_n771
+end
+
+def fun_l4_n535()
+ fun_l5_n248
+end
+
+def fun_l4_n536()
+ fun_l5_n412
+end
+
+def fun_l4_n537()
+ fun_l5_n736
+end
+
+def fun_l4_n538()
+ fun_l5_n296
+end
+
+def fun_l4_n539()
+ fun_l5_n847
+end
+
+def fun_l4_n540()
+ fun_l5_n188
+end
+
+def fun_l4_n541()
+ fun_l5_n131
+end
+
+def fun_l4_n542()
+ fun_l5_n31
+end
+
+def fun_l4_n543()
+ fun_l5_n563
+end
+
+def fun_l4_n544()
+ fun_l5_n479
+end
+
+def fun_l4_n545()
+ fun_l5_n243
+end
+
+def fun_l4_n546()
+ fun_l5_n471
+end
+
+def fun_l4_n547()
+ fun_l5_n237
+end
+
+def fun_l4_n548()
+ fun_l5_n772
+end
+
+def fun_l4_n549()
+ fun_l5_n723
+end
+
+def fun_l4_n550()
+ fun_l5_n733
+end
+
+def fun_l4_n551()
+ fun_l5_n274
+end
+
+def fun_l4_n552()
+ fun_l5_n351
+end
+
+def fun_l4_n553()
+ fun_l5_n30
+end
+
+def fun_l4_n554()
+ fun_l5_n112
+end
+
+def fun_l4_n555()
+ fun_l5_n438
+end
+
+def fun_l4_n556()
+ fun_l5_n969
+end
+
+def fun_l4_n557()
+ fun_l5_n57
+end
+
+def fun_l4_n558()
+ fun_l5_n971
+end
+
+def fun_l4_n559()
+ fun_l5_n831
+end
+
+def fun_l4_n560()
+ fun_l5_n833
+end
+
+def fun_l4_n561()
+ fun_l5_n896
+end
+
+def fun_l4_n562()
+ fun_l5_n607
+end
+
+def fun_l4_n563()
+ fun_l5_n793
+end
+
+def fun_l4_n564()
+ fun_l5_n711
+end
+
+def fun_l4_n565()
+ fun_l5_n570
+end
+
+def fun_l4_n566()
+ fun_l5_n933
+end
+
+def fun_l4_n567()
+ fun_l5_n917
+end
+
+def fun_l4_n568()
+ fun_l5_n811
+end
+
+def fun_l4_n569()
+ fun_l5_n414
+end
+
+def fun_l4_n570()
+ fun_l5_n14
+end
+
+def fun_l4_n571()
+ fun_l5_n911
+end
+
+def fun_l4_n572()
+ fun_l5_n114
+end
+
+def fun_l4_n573()
+ fun_l5_n732
+end
+
+def fun_l4_n574()
+ fun_l5_n913
+end
+
+def fun_l4_n575()
+ fun_l5_n66
+end
+
+def fun_l4_n576()
+ fun_l5_n330
+end
+
+def fun_l4_n577()
+ fun_l5_n892
+end
+
+def fun_l4_n578()
+ fun_l5_n329
+end
+
+def fun_l4_n579()
+ fun_l5_n539
+end
+
+def fun_l4_n580()
+ fun_l5_n268
+end
+
+def fun_l4_n581()
+ fun_l5_n357
+end
+
+def fun_l4_n582()
+ fun_l5_n259
+end
+
+def fun_l4_n583()
+ fun_l5_n968
+end
+
+def fun_l4_n584()
+ fun_l5_n873
+end
+
+def fun_l4_n585()
+ fun_l5_n644
+end
+
+def fun_l4_n586()
+ fun_l5_n659
+end
+
+def fun_l4_n587()
+ fun_l5_n906
+end
+
+def fun_l4_n588()
+ fun_l5_n746
+end
+
+def fun_l4_n589()
+ fun_l5_n802
+end
+
+def fun_l4_n590()
+ fun_l5_n9
+end
+
+def fun_l4_n591()
+ fun_l5_n620
+end
+
+def fun_l4_n592()
+ fun_l5_n507
+end
+
+def fun_l4_n593()
+ fun_l5_n338
+end
+
+def fun_l4_n594()
+ fun_l5_n396
+end
+
+def fun_l4_n595()
+ fun_l5_n627
+end
+
+def fun_l4_n596()
+ fun_l5_n621
+end
+
+def fun_l4_n597()
+ fun_l5_n597
+end
+
+def fun_l4_n598()
+ fun_l5_n496
+end
+
+def fun_l4_n599()
+ fun_l5_n265
+end
+
+def fun_l4_n600()
+ fun_l5_n897
+end
+
+def fun_l4_n601()
+ fun_l5_n142
+end
+
+def fun_l4_n602()
+ fun_l5_n614
+end
+
+def fun_l4_n603()
+ fun_l5_n565
+end
+
+def fun_l4_n604()
+ fun_l5_n653
+end
+
+def fun_l4_n605()
+ fun_l5_n728
+end
+
+def fun_l4_n606()
+ fun_l5_n799
+end
+
+def fun_l4_n607()
+ fun_l5_n714
+end
+
+def fun_l4_n608()
+ fun_l5_n448
+end
+
+def fun_l4_n609()
+ fun_l5_n778
+end
+
+def fun_l4_n610()
+ fun_l5_n508
+end
+
+def fun_l4_n611()
+ fun_l5_n216
+end
+
+def fun_l4_n612()
+ fun_l5_n604
+end
+
+def fun_l4_n613()
+ fun_l5_n231
+end
+
+def fun_l4_n614()
+ fun_l5_n696
+end
+
+def fun_l4_n615()
+ fun_l5_n354
+end
+
+def fun_l4_n616()
+ fun_l5_n595
+end
+
+def fun_l4_n617()
+ fun_l5_n747
+end
+
+def fun_l4_n618()
+ fun_l5_n377
+end
+
+def fun_l4_n619()
+ fun_l5_n852
+end
+
+def fun_l4_n620()
+ fun_l5_n381
+end
+
+def fun_l4_n621()
+ fun_l5_n674
+end
+
+def fun_l4_n622()
+ fun_l5_n696
+end
+
+def fun_l4_n623()
+ fun_l5_n25
+end
+
+def fun_l4_n624()
+ fun_l5_n133
+end
+
+def fun_l4_n625()
+ fun_l5_n419
+end
+
+def fun_l4_n626()
+ fun_l5_n612
+end
+
+def fun_l4_n627()
+ fun_l5_n798
+end
+
+def fun_l4_n628()
+ fun_l5_n702
+end
+
+def fun_l4_n629()
+ fun_l5_n125
+end
+
+def fun_l4_n630()
+ fun_l5_n567
+end
+
+def fun_l4_n631()
+ fun_l5_n825
+end
+
+def fun_l4_n632()
+ fun_l5_n794
+end
+
+def fun_l4_n633()
+ fun_l5_n802
+end
+
+def fun_l4_n634()
+ fun_l5_n297
+end
+
+def fun_l4_n635()
+ fun_l5_n366
+end
+
+def fun_l4_n636()
+ fun_l5_n149
+end
+
+def fun_l4_n637()
+ fun_l5_n648
+end
+
+def fun_l4_n638()
+ fun_l5_n997
+end
+
+def fun_l4_n639()
+ fun_l5_n569
+end
+
+def fun_l4_n640()
+ fun_l5_n917
+end
+
+def fun_l4_n641()
+ fun_l5_n172
+end
+
+def fun_l4_n642()
+ fun_l5_n353
+end
+
+def fun_l4_n643()
+ fun_l5_n940
+end
+
+def fun_l4_n644()
+ fun_l5_n255
+end
+
+def fun_l4_n645()
+ fun_l5_n690
+end
+
+def fun_l4_n646()
+ fun_l5_n17
+end
+
+def fun_l4_n647()
+ fun_l5_n320
+end
+
+def fun_l4_n648()
+ fun_l5_n328
+end
+
+def fun_l4_n649()
+ fun_l5_n467
+end
+
+def fun_l4_n650()
+ fun_l5_n352
+end
+
+def fun_l4_n651()
+ fun_l5_n671
+end
+
+def fun_l4_n652()
+ fun_l5_n104
+end
+
+def fun_l4_n653()
+ fun_l5_n40
+end
+
+def fun_l4_n654()
+ fun_l5_n445
+end
+
+def fun_l4_n655()
+ fun_l5_n703
+end
+
+def fun_l4_n656()
+ fun_l5_n699
+end
+
+def fun_l4_n657()
+ fun_l5_n156
+end
+
+def fun_l4_n658()
+ fun_l5_n1
+end
+
+def fun_l4_n659()
+ fun_l5_n728
+end
+
+def fun_l4_n660()
+ fun_l5_n200
+end
+
+def fun_l4_n661()
+ fun_l5_n369
+end
+
+def fun_l4_n662()
+ fun_l5_n621
+end
+
+def fun_l4_n663()
+ fun_l5_n600
+end
+
+def fun_l4_n664()
+ fun_l5_n342
+end
+
+def fun_l4_n665()
+ fun_l5_n129
+end
+
+def fun_l4_n666()
+ fun_l5_n627
+end
+
+def fun_l4_n667()
+ fun_l5_n44
+end
+
+def fun_l4_n668()
+ fun_l5_n43
+end
+
+def fun_l4_n669()
+ fun_l5_n708
+end
+
+def fun_l4_n670()
+ fun_l5_n378
+end
+
+def fun_l4_n671()
+ fun_l5_n320
+end
+
+def fun_l4_n672()
+ fun_l5_n896
+end
+
+def fun_l4_n673()
+ fun_l5_n185
+end
+
+def fun_l4_n674()
+ fun_l5_n456
+end
+
+def fun_l4_n675()
+ fun_l5_n520
+end
+
+def fun_l4_n676()
+ fun_l5_n633
+end
+
+def fun_l4_n677()
+ fun_l5_n122
+end
+
+def fun_l4_n678()
+ fun_l5_n333
+end
+
+def fun_l4_n679()
+ fun_l5_n100
+end
+
+def fun_l4_n680()
+ fun_l5_n941
+end
+
+def fun_l4_n681()
+ fun_l5_n468
+end
+
+def fun_l4_n682()
+ fun_l5_n45
+end
+
+def fun_l4_n683()
+ fun_l5_n295
+end
+
+def fun_l4_n684()
+ fun_l5_n400
+end
+
+def fun_l4_n685()
+ fun_l5_n999
+end
+
+def fun_l4_n686()
+ fun_l5_n294
+end
+
+def fun_l4_n687()
+ fun_l5_n575
+end
+
+def fun_l4_n688()
+ fun_l5_n372
+end
+
+def fun_l4_n689()
+ fun_l5_n777
+end
+
+def fun_l4_n690()
+ fun_l5_n795
+end
+
+def fun_l4_n691()
+ fun_l5_n44
+end
+
+def fun_l4_n692()
+ fun_l5_n27
+end
+
+def fun_l4_n693()
+ fun_l5_n488
+end
+
+def fun_l4_n694()
+ fun_l5_n932
+end
+
+def fun_l4_n695()
+ fun_l5_n104
+end
+
+def fun_l4_n696()
+ fun_l5_n552
+end
+
+def fun_l4_n697()
+ fun_l5_n830
+end
+
+def fun_l4_n698()
+ fun_l5_n612
+end
+
+def fun_l4_n699()
+ fun_l5_n889
+end
+
+def fun_l4_n700()
+ fun_l5_n205
+end
+
+def fun_l4_n701()
+ fun_l5_n90
+end
+
+def fun_l4_n702()
+ fun_l5_n210
+end
+
+def fun_l4_n703()
+ fun_l5_n514
+end
+
+def fun_l4_n704()
+ fun_l5_n374
+end
+
+def fun_l4_n705()
+ fun_l5_n176
+end
+
+def fun_l4_n706()
+ fun_l5_n465
+end
+
+def fun_l4_n707()
+ fun_l5_n542
+end
+
+def fun_l4_n708()
+ fun_l5_n175
+end
+
+def fun_l4_n709()
+ fun_l5_n148
+end
+
+def fun_l4_n710()
+ fun_l5_n212
+end
+
+def fun_l4_n711()
+ fun_l5_n418
+end
+
+def fun_l4_n712()
+ fun_l5_n401
+end
+
+def fun_l4_n713()
+ fun_l5_n14
+end
+
+def fun_l4_n714()
+ fun_l5_n965
+end
+
+def fun_l4_n715()
+ fun_l5_n783
+end
+
+def fun_l4_n716()
+ fun_l5_n421
+end
+
+def fun_l4_n717()
+ fun_l5_n346
+end
+
+def fun_l4_n718()
+ fun_l5_n176
+end
+
+def fun_l4_n719()
+ fun_l5_n522
+end
+
+def fun_l4_n720()
+ fun_l5_n207
+end
+
+def fun_l4_n721()
+ fun_l5_n707
+end
+
+def fun_l4_n722()
+ fun_l5_n593
+end
+
+def fun_l4_n723()
+ fun_l5_n609
+end
+
+def fun_l4_n724()
+ fun_l5_n798
+end
+
+def fun_l4_n725()
+ fun_l5_n744
+end
+
+def fun_l4_n726()
+ fun_l5_n514
+end
+
+def fun_l4_n727()
+ fun_l5_n278
+end
+
+def fun_l4_n728()
+ fun_l5_n425
+end
+
+def fun_l4_n729()
+ fun_l5_n147
+end
+
+def fun_l4_n730()
+ fun_l5_n676
+end
+
+def fun_l4_n731()
+ fun_l5_n887
+end
+
+def fun_l4_n732()
+ fun_l5_n865
+end
+
+def fun_l4_n733()
+ fun_l5_n811
+end
+
+def fun_l4_n734()
+ fun_l5_n545
+end
+
+def fun_l4_n735()
+ fun_l5_n219
+end
+
+def fun_l4_n736()
+ fun_l5_n121
+end
+
+def fun_l4_n737()
+ fun_l5_n253
+end
+
+def fun_l4_n738()
+ fun_l5_n349
+end
+
+def fun_l4_n739()
+ fun_l5_n540
+end
+
+def fun_l4_n740()
+ fun_l5_n301
+end
+
+def fun_l4_n741()
+ fun_l5_n367
+end
+
+def fun_l4_n742()
+ fun_l5_n989
+end
+
+def fun_l4_n743()
+ fun_l5_n454
+end
+
+def fun_l4_n744()
+ fun_l5_n390
+end
+
+def fun_l4_n745()
+ fun_l5_n650
+end
+
+def fun_l4_n746()
+ fun_l5_n403
+end
+
+def fun_l4_n747()
+ fun_l5_n807
+end
+
+def fun_l4_n748()
+ fun_l5_n219
+end
+
+def fun_l4_n749()
+ fun_l5_n756
+end
+
+def fun_l4_n750()
+ fun_l5_n730
+end
+
+def fun_l4_n751()
+ fun_l5_n923
+end
+
+def fun_l4_n752()
+ fun_l5_n407
+end
+
+def fun_l4_n753()
+ fun_l5_n734
+end
+
+def fun_l4_n754()
+ fun_l5_n192
+end
+
+def fun_l4_n755()
+ fun_l5_n26
+end
+
+def fun_l4_n756()
+ fun_l5_n571
+end
+
+def fun_l4_n757()
+ fun_l5_n515
+end
+
+def fun_l4_n758()
+ fun_l5_n701
+end
+
+def fun_l4_n759()
+ fun_l5_n808
+end
+
+def fun_l4_n760()
+ fun_l5_n607
+end
+
+def fun_l4_n761()
+ fun_l5_n231
+end
+
+def fun_l4_n762()
+ fun_l5_n144
+end
+
+def fun_l4_n763()
+ fun_l5_n829
+end
+
+def fun_l4_n764()
+ fun_l5_n939
+end
+
+def fun_l4_n765()
+ fun_l5_n486
+end
+
+def fun_l4_n766()
+ fun_l5_n73
+end
+
+def fun_l4_n767()
+ fun_l5_n409
+end
+
+def fun_l4_n768()
+ fun_l5_n197
+end
+
+def fun_l4_n769()
+ fun_l5_n803
+end
+
+def fun_l4_n770()
+ fun_l5_n877
+end
+
+def fun_l4_n771()
+ fun_l5_n739
+end
+
+def fun_l4_n772()
+ fun_l5_n500
+end
+
+def fun_l4_n773()
+ fun_l5_n104
+end
+
+def fun_l4_n774()
+ fun_l5_n526
+end
+
+def fun_l4_n775()
+ fun_l5_n443
+end
+
+def fun_l4_n776()
+ fun_l5_n397
+end
+
+def fun_l4_n777()
+ fun_l5_n496
+end
+
+def fun_l4_n778()
+ fun_l5_n360
+end
+
+def fun_l4_n779()
+ fun_l5_n93
+end
+
+def fun_l4_n780()
+ fun_l5_n635
+end
+
+def fun_l4_n781()
+ fun_l5_n724
+end
+
+def fun_l4_n782()
+ fun_l5_n445
+end
+
+def fun_l4_n783()
+ fun_l5_n546
+end
+
+def fun_l4_n784()
+ fun_l5_n353
+end
+
+def fun_l4_n785()
+ fun_l5_n546
+end
+
+def fun_l4_n786()
+ fun_l5_n243
+end
+
+def fun_l4_n787()
+ fun_l5_n614
+end
+
+def fun_l4_n788()
+ fun_l5_n249
+end
+
+def fun_l4_n789()
+ fun_l5_n281
+end
+
+def fun_l4_n790()
+ fun_l5_n22
+end
+
+def fun_l4_n791()
+ fun_l5_n857
+end
+
+def fun_l4_n792()
+ fun_l5_n685
+end
+
+def fun_l4_n793()
+ fun_l5_n784
+end
+
+def fun_l4_n794()
+ fun_l5_n522
+end
+
+def fun_l4_n795()
+ fun_l5_n970
+end
+
+def fun_l4_n796()
+ fun_l5_n734
+end
+
+def fun_l4_n797()
+ fun_l5_n36
+end
+
+def fun_l4_n798()
+ fun_l5_n257
+end
+
+def fun_l4_n799()
+ fun_l5_n677
+end
+
+def fun_l4_n800()
+ fun_l5_n556
+end
+
+def fun_l4_n801()
+ fun_l5_n783
+end
+
+def fun_l4_n802()
+ fun_l5_n501
+end
+
+def fun_l4_n803()
+ fun_l5_n731
+end
+
+def fun_l4_n804()
+ fun_l5_n175
+end
+
+def fun_l4_n805()
+ fun_l5_n712
+end
+
+def fun_l4_n806()
+ fun_l5_n566
+end
+
+def fun_l4_n807()
+ fun_l5_n158
+end
+
+def fun_l4_n808()
+ fun_l5_n63
+end
+
+def fun_l4_n809()
+ fun_l5_n354
+end
+
+def fun_l4_n810()
+ fun_l5_n552
+end
+
+def fun_l4_n811()
+ fun_l5_n255
+end
+
+def fun_l4_n812()
+ fun_l5_n830
+end
+
+def fun_l4_n813()
+ fun_l5_n792
+end
+
+def fun_l4_n814()
+ fun_l5_n214
+end
+
+def fun_l4_n815()
+ fun_l5_n906
+end
+
+def fun_l4_n816()
+ fun_l5_n852
+end
+
+def fun_l4_n817()
+ fun_l5_n286
+end
+
+def fun_l4_n818()
+ fun_l5_n704
+end
+
+def fun_l4_n819()
+ fun_l5_n860
+end
+
+def fun_l4_n820()
+ fun_l5_n150
+end
+
+def fun_l4_n821()
+ fun_l5_n793
+end
+
+def fun_l4_n822()
+ fun_l5_n356
+end
+
+def fun_l4_n823()
+ fun_l5_n369
+end
+
+def fun_l4_n824()
+ fun_l5_n519
+end
+
+def fun_l4_n825()
+ fun_l5_n765
+end
+
+def fun_l4_n826()
+ fun_l5_n974
+end
+
+def fun_l4_n827()
+ fun_l5_n265
+end
+
+def fun_l4_n828()
+ fun_l5_n948
+end
+
+def fun_l4_n829()
+ fun_l5_n2
+end
+
+def fun_l4_n830()
+ fun_l5_n269
+end
+
+def fun_l4_n831()
+ fun_l5_n96
+end
+
+def fun_l4_n832()
+ fun_l5_n964
+end
+
+def fun_l4_n833()
+ fun_l5_n362
+end
+
+def fun_l4_n834()
+ fun_l5_n915
+end
+
+def fun_l4_n835()
+ fun_l5_n179
+end
+
+def fun_l4_n836()
+ fun_l5_n128
+end
+
+def fun_l4_n837()
+ fun_l5_n195
+end
+
+def fun_l4_n838()
+ fun_l5_n393
+end
+
+def fun_l4_n839()
+ fun_l5_n120
+end
+
+def fun_l4_n840()
+ fun_l5_n239
+end
+
+def fun_l4_n841()
+ fun_l5_n669
+end
+
+def fun_l4_n842()
+ fun_l5_n234
+end
+
+def fun_l4_n843()
+ fun_l5_n60
+end
+
+def fun_l4_n844()
+ fun_l5_n962
+end
+
+def fun_l4_n845()
+ fun_l5_n770
+end
+
+def fun_l4_n846()
+ fun_l5_n207
+end
+
+def fun_l4_n847()
+ fun_l5_n46
+end
+
+def fun_l4_n848()
+ fun_l5_n615
+end
+
+def fun_l4_n849()
+ fun_l5_n709
+end
+
+def fun_l4_n850()
+ fun_l5_n198
+end
+
+def fun_l4_n851()
+ fun_l5_n639
+end
+
+def fun_l4_n852()
+ fun_l5_n125
+end
+
+def fun_l4_n853()
+ fun_l5_n193
+end
+
+def fun_l4_n854()
+ fun_l5_n806
+end
+
+def fun_l4_n855()
+ fun_l5_n237
+end
+
+def fun_l4_n856()
+ fun_l5_n319
+end
+
+def fun_l4_n857()
+ fun_l5_n533
+end
+
+def fun_l4_n858()
+ fun_l5_n320
+end
+
+def fun_l4_n859()
+ fun_l5_n501
+end
+
+def fun_l4_n860()
+ fun_l5_n404
+end
+
+def fun_l4_n861()
+ fun_l5_n849
+end
+
+def fun_l4_n862()
+ fun_l5_n743
+end
+
+def fun_l4_n863()
+ fun_l5_n764
+end
+
+def fun_l4_n864()
+ fun_l5_n956
+end
+
+def fun_l4_n865()
+ fun_l5_n914
+end
+
+def fun_l4_n866()
+ fun_l5_n652
+end
+
+def fun_l4_n867()
+ fun_l5_n30
+end
+
+def fun_l4_n868()
+ fun_l5_n330
+end
+
+def fun_l4_n869()
+ fun_l5_n677
+end
+
+def fun_l4_n870()
+ fun_l5_n988
+end
+
+def fun_l4_n871()
+ fun_l5_n676
+end
+
+def fun_l4_n872()
+ fun_l5_n752
+end
+
+def fun_l4_n873()
+ fun_l5_n636
+end
+
+def fun_l4_n874()
+ fun_l5_n395
+end
+
+def fun_l4_n875()
+ fun_l5_n428
+end
+
+def fun_l4_n876()
+ fun_l5_n83
+end
+
+def fun_l4_n877()
+ fun_l5_n712
+end
+
+def fun_l4_n878()
+ fun_l5_n708
+end
+
+def fun_l4_n879()
+ fun_l5_n418
+end
+
+def fun_l4_n880()
+ fun_l5_n265
+end
+
+def fun_l4_n881()
+ fun_l5_n379
+end
+
+def fun_l4_n882()
+ fun_l5_n758
+end
+
+def fun_l4_n883()
+ fun_l5_n251
+end
+
+def fun_l4_n884()
+ fun_l5_n723
+end
+
+def fun_l4_n885()
+ fun_l5_n216
+end
+
+def fun_l4_n886()
+ fun_l5_n197
+end
+
+def fun_l4_n887()
+ fun_l5_n261
+end
+
+def fun_l4_n888()
+ fun_l5_n62
+end
+
+def fun_l4_n889()
+ fun_l5_n941
+end
+
+def fun_l4_n890()
+ fun_l5_n535
+end
+
+def fun_l4_n891()
+ fun_l5_n727
+end
+
+def fun_l4_n892()
+ fun_l5_n279
+end
+
+def fun_l4_n893()
+ fun_l5_n541
+end
+
+def fun_l4_n894()
+ fun_l5_n684
+end
+
+def fun_l4_n895()
+ fun_l5_n649
+end
+
+def fun_l4_n896()
+ fun_l5_n396
+end
+
+def fun_l4_n897()
+ fun_l5_n992
+end
+
+def fun_l4_n898()
+ fun_l5_n160
+end
+
+def fun_l4_n899()
+ fun_l5_n84
+end
+
+def fun_l4_n900()
+ fun_l5_n318
+end
+
+def fun_l4_n901()
+ fun_l5_n428
+end
+
+def fun_l4_n902()
+ fun_l5_n534
+end
+
+def fun_l4_n903()
+ fun_l5_n25
+end
+
+def fun_l4_n904()
+ fun_l5_n392
+end
+
+def fun_l4_n905()
+ fun_l5_n926
+end
+
+def fun_l4_n906()
+ fun_l5_n724
+end
+
+def fun_l4_n907()
+ fun_l5_n311
+end
+
+def fun_l4_n908()
+ fun_l5_n535
+end
+
+def fun_l4_n909()
+ fun_l5_n179
+end
+
+def fun_l4_n910()
+ fun_l5_n533
+end
+
+def fun_l4_n911()
+ fun_l5_n875
+end
+
+def fun_l4_n912()
+ fun_l5_n105
+end
+
+def fun_l4_n913()
+ fun_l5_n618
+end
+
+def fun_l4_n914()
+ fun_l5_n827
+end
+
+def fun_l4_n915()
+ fun_l5_n555
+end
+
+def fun_l4_n916()
+ fun_l5_n339
+end
+
+def fun_l4_n917()
+ fun_l5_n848
+end
+
+def fun_l4_n918()
+ fun_l5_n676
+end
+
+def fun_l4_n919()
+ fun_l5_n204
+end
+
+def fun_l4_n920()
+ fun_l5_n769
+end
+
+def fun_l4_n921()
+ fun_l5_n229
+end
+
+def fun_l4_n922()
+ fun_l5_n92
+end
+
+def fun_l4_n923()
+ fun_l5_n973
+end
+
+def fun_l4_n924()
+ fun_l5_n700
+end
+
+def fun_l4_n925()
+ fun_l5_n581
+end
+
+def fun_l4_n926()
+ fun_l5_n138
+end
+
+def fun_l4_n927()
+ fun_l5_n43
+end
+
+def fun_l4_n928()
+ fun_l5_n537
+end
+
+def fun_l4_n929()
+ fun_l5_n882
+end
+
+def fun_l4_n930()
+ fun_l5_n871
+end
+
+def fun_l4_n931()
+ fun_l5_n158
+end
+
+def fun_l4_n932()
+ fun_l5_n542
+end
+
+def fun_l4_n933()
+ fun_l5_n468
+end
+
+def fun_l4_n934()
+ fun_l5_n28
+end
+
+def fun_l4_n935()
+ fun_l5_n976
+end
+
+def fun_l4_n936()
+ fun_l5_n632
+end
+
+def fun_l4_n937()
+ fun_l5_n857
+end
+
+def fun_l4_n938()
+ fun_l5_n841
+end
+
+def fun_l4_n939()
+ fun_l5_n762
+end
+
+def fun_l4_n940()
+ fun_l5_n522
+end
+
+def fun_l4_n941()
+ fun_l5_n841
+end
+
+def fun_l4_n942()
+ fun_l5_n42
+end
+
+def fun_l4_n943()
+ fun_l5_n771
+end
+
+def fun_l4_n944()
+ fun_l5_n145
+end
+
+def fun_l4_n945()
+ fun_l5_n435
+end
+
+def fun_l4_n946()
+ fun_l5_n573
+end
+
+def fun_l4_n947()
+ fun_l5_n422
+end
+
+def fun_l4_n948()
+ fun_l5_n34
+end
+
+def fun_l4_n949()
+ fun_l5_n577
+end
+
+def fun_l4_n950()
+ fun_l5_n156
+end
+
+def fun_l4_n951()
+ fun_l5_n707
+end
+
+def fun_l4_n952()
+ fun_l5_n198
+end
+
+def fun_l4_n953()
+ fun_l5_n950
+end
+
+def fun_l4_n954()
+ fun_l5_n474
+end
+
+def fun_l4_n955()
+ fun_l5_n319
+end
+
+def fun_l4_n956()
+ fun_l5_n208
+end
+
+def fun_l4_n957()
+ fun_l5_n360
+end
+
+def fun_l4_n958()
+ fun_l5_n101
+end
+
+def fun_l4_n959()
+ fun_l5_n37
+end
+
+def fun_l4_n960()
+ fun_l5_n20
+end
+
+def fun_l4_n961()
+ fun_l5_n897
+end
+
+def fun_l4_n962()
+ fun_l5_n92
+end
+
+def fun_l4_n963()
+ fun_l5_n105
+end
+
+def fun_l4_n964()
+ fun_l5_n255
+end
+
+def fun_l4_n965()
+ fun_l5_n97
+end
+
+def fun_l4_n966()
+ fun_l5_n398
+end
+
+def fun_l4_n967()
+ fun_l5_n393
+end
+
+def fun_l4_n968()
+ fun_l5_n135
+end
+
+def fun_l4_n969()
+ fun_l5_n306
+end
+
+def fun_l4_n970()
+ fun_l5_n202
+end
+
+def fun_l4_n971()
+ fun_l5_n832
+end
+
+def fun_l4_n972()
+ fun_l5_n444
+end
+
+def fun_l4_n973()
+ fun_l5_n768
+end
+
+def fun_l4_n974()
+ fun_l5_n384
+end
+
+def fun_l4_n975()
+ fun_l5_n142
+end
+
+def fun_l4_n976()
+ fun_l5_n208
+end
+
+def fun_l4_n977()
+ fun_l5_n818
+end
+
+def fun_l4_n978()
+ fun_l5_n5
+end
+
+def fun_l4_n979()
+ fun_l5_n410
+end
+
+def fun_l4_n980()
+ fun_l5_n713
+end
+
+def fun_l4_n981()
+ fun_l5_n42
+end
+
+def fun_l4_n982()
+ fun_l5_n335
+end
+
+def fun_l4_n983()
+ fun_l5_n446
+end
+
+def fun_l4_n984()
+ fun_l5_n957
+end
+
+def fun_l4_n985()
+ fun_l5_n652
+end
+
+def fun_l4_n986()
+ fun_l5_n341
+end
+
+def fun_l4_n987()
+ fun_l5_n300
+end
+
+def fun_l4_n988()
+ fun_l5_n859
+end
+
+def fun_l4_n989()
+ fun_l5_n467
+end
+
+def fun_l4_n990()
+ fun_l5_n182
+end
+
+def fun_l4_n991()
+ fun_l5_n755
+end
+
+def fun_l4_n992()
+ fun_l5_n925
+end
+
+def fun_l4_n993()
+ fun_l5_n695
+end
+
+def fun_l4_n994()
+ fun_l5_n901
+end
+
+def fun_l4_n995()
+ fun_l5_n844
+end
+
+def fun_l4_n996()
+ fun_l5_n430
+end
+
+def fun_l4_n997()
+ fun_l5_n568
+end
+
+def fun_l4_n998()
+ fun_l5_n472
+end
+
+def fun_l4_n999()
+ fun_l5_n871
+end
+
+def fun_l5_n0()
+ fun_l6_n383
+end
+
+def fun_l5_n1()
+ fun_l6_n172
+end
+
+def fun_l5_n2()
+ fun_l6_n405
+end
+
+def fun_l5_n3()
+ fun_l6_n960
+end
+
+def fun_l5_n4()
+ fun_l6_n846
+end
+
+def fun_l5_n5()
+ fun_l6_n207
+end
+
+def fun_l5_n6()
+ fun_l6_n217
+end
+
+def fun_l5_n7()
+ fun_l6_n317
+end
+
+def fun_l5_n8()
+ fun_l6_n628
+end
+
+def fun_l5_n9()
+ fun_l6_n407
+end
+
+def fun_l5_n10()
+ fun_l6_n933
+end
+
+def fun_l5_n11()
+ fun_l6_n318
+end
+
+def fun_l5_n12()
+ fun_l6_n349
+end
+
+def fun_l5_n13()
+ fun_l6_n559
+end
+
+def fun_l5_n14()
+ fun_l6_n352
+end
+
+def fun_l5_n15()
+ fun_l6_n531
+end
+
+def fun_l5_n16()
+ fun_l6_n6
+end
+
+def fun_l5_n17()
+ fun_l6_n285
+end
+
+def fun_l5_n18()
+ fun_l6_n419
+end
+
+def fun_l5_n19()
+ fun_l6_n232
+end
+
+def fun_l5_n20()
+ fun_l6_n285
+end
+
+def fun_l5_n21()
+ fun_l6_n814
+end
+
+def fun_l5_n22()
+ fun_l6_n773
+end
+
+def fun_l5_n23()
+ fun_l6_n771
+end
+
+def fun_l5_n24()
+ fun_l6_n903
+end
+
+def fun_l5_n25()
+ fun_l6_n116
+end
+
+def fun_l5_n26()
+ fun_l6_n116
+end
+
+def fun_l5_n27()
+ fun_l6_n531
+end
+
+def fun_l5_n28()
+ fun_l6_n418
+end
+
+def fun_l5_n29()
+ fun_l6_n564
+end
+
+def fun_l5_n30()
+ fun_l6_n691
+end
+
+def fun_l5_n31()
+ fun_l6_n267
+end
+
+def fun_l5_n32()
+ fun_l6_n209
+end
+
+def fun_l5_n33()
+ fun_l6_n27
+end
+
+def fun_l5_n34()
+ fun_l6_n312
+end
+
+def fun_l5_n35()
+ fun_l6_n240
+end
+
+def fun_l5_n36()
+ fun_l6_n507
+end
+
+def fun_l5_n37()
+ fun_l6_n808
+end
+
+def fun_l5_n38()
+ fun_l6_n28
+end
+
+def fun_l5_n39()
+ fun_l6_n33
+end
+
+def fun_l5_n40()
+ fun_l6_n808
+end
+
+def fun_l5_n41()
+ fun_l6_n15
+end
+
+def fun_l5_n42()
+ fun_l6_n995
+end
+
+def fun_l5_n43()
+ fun_l6_n886
+end
+
+def fun_l5_n44()
+ fun_l6_n164
+end
+
+def fun_l5_n45()
+ fun_l6_n804
+end
+
+def fun_l5_n46()
+ fun_l6_n776
+end
+
+def fun_l5_n47()
+ fun_l6_n584
+end
+
+def fun_l5_n48()
+ fun_l6_n220
+end
+
+def fun_l5_n49()
+ fun_l6_n680
+end
+
+def fun_l5_n50()
+ fun_l6_n438
+end
+
+def fun_l5_n51()
+ fun_l6_n565
+end
+
+def fun_l5_n52()
+ fun_l6_n394
+end
+
+def fun_l5_n53()
+ fun_l6_n867
+end
+
+def fun_l5_n54()
+ fun_l6_n468
+end
+
+def fun_l5_n55()
+ fun_l6_n622
+end
+
+def fun_l5_n56()
+ fun_l6_n846
+end
+
+def fun_l5_n57()
+ fun_l6_n718
+end
+
+def fun_l5_n58()
+ fun_l6_n367
+end
+
+def fun_l5_n59()
+ fun_l6_n284
+end
+
+def fun_l5_n60()
+ fun_l6_n350
+end
+
+def fun_l5_n61()
+ fun_l6_n849
+end
+
+def fun_l5_n62()
+ fun_l6_n537
+end
+
+def fun_l5_n63()
+ fun_l6_n475
+end
+
+def fun_l5_n64()
+ fun_l6_n525
+end
+
+def fun_l5_n65()
+ fun_l6_n416
+end
+
+def fun_l5_n66()
+ fun_l6_n261
+end
+
+def fun_l5_n67()
+ fun_l6_n528
+end
+
+def fun_l5_n68()
+ fun_l6_n331
+end
+
+def fun_l5_n69()
+ fun_l6_n387
+end
+
+def fun_l5_n70()
+ fun_l6_n780
+end
+
+def fun_l5_n71()
+ fun_l6_n542
+end
+
+def fun_l5_n72()
+ fun_l6_n930
+end
+
+def fun_l5_n73()
+ fun_l6_n79
+end
+
+def fun_l5_n74()
+ fun_l6_n351
+end
+
+def fun_l5_n75()
+ fun_l6_n290
+end
+
+def fun_l5_n76()
+ fun_l6_n659
+end
+
+def fun_l5_n77()
+ fun_l6_n421
+end
+
+def fun_l5_n78()
+ fun_l6_n454
+end
+
+def fun_l5_n79()
+ fun_l6_n78
+end
+
+def fun_l5_n80()
+ fun_l6_n63
+end
+
+def fun_l5_n81()
+ fun_l6_n555
+end
+
+def fun_l5_n82()
+ fun_l6_n54
+end
+
+def fun_l5_n83()
+ fun_l6_n46
+end
+
+def fun_l5_n84()
+ fun_l6_n225
+end
+
+def fun_l5_n85()
+ fun_l6_n330
+end
+
+def fun_l5_n86()
+ fun_l6_n772
+end
+
+def fun_l5_n87()
+ fun_l6_n654
+end
+
+def fun_l5_n88()
+ fun_l6_n281
+end
+
+def fun_l5_n89()
+ fun_l6_n857
+end
+
+def fun_l5_n90()
+ fun_l6_n453
+end
+
+def fun_l5_n91()
+ fun_l6_n504
+end
+
+def fun_l5_n92()
+ fun_l6_n649
+end
+
+def fun_l5_n93()
+ fun_l6_n90
+end
+
+def fun_l5_n94()
+ fun_l6_n520
+end
+
+def fun_l5_n95()
+ fun_l6_n251
+end
+
+def fun_l5_n96()
+ fun_l6_n738
+end
+
+def fun_l5_n97()
+ fun_l6_n837
+end
+
+def fun_l5_n98()
+ fun_l6_n98
+end
+
+def fun_l5_n99()
+ fun_l6_n844
+end
+
+def fun_l5_n100()
+ fun_l6_n699
+end
+
+def fun_l5_n101()
+ fun_l6_n901
+end
+
+def fun_l5_n102()
+ fun_l6_n342
+end
+
+def fun_l5_n103()
+ fun_l6_n856
+end
+
+def fun_l5_n104()
+ fun_l6_n113
+end
+
+def fun_l5_n105()
+ fun_l6_n530
+end
+
+def fun_l5_n106()
+ fun_l6_n445
+end
+
+def fun_l5_n107()
+ fun_l6_n515
+end
+
+def fun_l5_n108()
+ fun_l6_n958
+end
+
+def fun_l5_n109()
+ fun_l6_n561
+end
+
+def fun_l5_n110()
+ fun_l6_n130
+end
+
+def fun_l5_n111()
+ fun_l6_n653
+end
+
+def fun_l5_n112()
+ fun_l6_n367
+end
+
+def fun_l5_n113()
+ fun_l6_n515
+end
+
+def fun_l5_n114()
+ fun_l6_n50
+end
+
+def fun_l5_n115()
+ fun_l6_n259
+end
+
+def fun_l5_n116()
+ fun_l6_n280
+end
+
+def fun_l5_n117()
+ fun_l6_n589
+end
+
+def fun_l5_n118()
+ fun_l6_n988
+end
+
+def fun_l5_n119()
+ fun_l6_n544
+end
+
+def fun_l5_n120()
+ fun_l6_n564
+end
+
+def fun_l5_n121()
+ fun_l6_n468
+end
+
+def fun_l5_n122()
+ fun_l6_n586
+end
+
+def fun_l5_n123()
+ fun_l6_n705
+end
+
+def fun_l5_n124()
+ fun_l6_n510
+end
+
+def fun_l5_n125()
+ fun_l6_n995
+end
+
+def fun_l5_n126()
+ fun_l6_n576
+end
+
+def fun_l5_n127()
+ fun_l6_n221
+end
+
+def fun_l5_n128()
+ fun_l6_n498
+end
+
+def fun_l5_n129()
+ fun_l6_n113
+end
+
+def fun_l5_n130()
+ fun_l6_n916
+end
+
+def fun_l5_n131()
+ fun_l6_n626
+end
+
+def fun_l5_n132()
+ fun_l6_n635
+end
+
+def fun_l5_n133()
+ fun_l6_n605
+end
+
+def fun_l5_n134()
+ fun_l6_n931
+end
+
+def fun_l5_n135()
+ fun_l6_n282
+end
+
+def fun_l5_n136()
+ fun_l6_n904
+end
+
+def fun_l5_n137()
+ fun_l6_n522
+end
+
+def fun_l5_n138()
+ fun_l6_n255
+end
+
+def fun_l5_n139()
+ fun_l6_n308
+end
+
+def fun_l5_n140()
+ fun_l6_n482
+end
+
+def fun_l5_n141()
+ fun_l6_n911
+end
+
+def fun_l5_n142()
+ fun_l6_n640
+end
+
+def fun_l5_n143()
+ fun_l6_n783
+end
+
+def fun_l5_n144()
+ fun_l6_n980
+end
+
+def fun_l5_n145()
+ fun_l6_n85
+end
+
+def fun_l5_n146()
+ fun_l6_n181
+end
+
+def fun_l5_n147()
+ fun_l6_n963
+end
+
+def fun_l5_n148()
+ fun_l6_n516
+end
+
+def fun_l5_n149()
+ fun_l6_n315
+end
+
+def fun_l5_n150()
+ fun_l6_n822
+end
+
+def fun_l5_n151()
+ fun_l6_n528
+end
+
+def fun_l5_n152()
+ fun_l6_n220
+end
+
+def fun_l5_n153()
+ fun_l6_n13
+end
+
+def fun_l5_n154()
+ fun_l6_n172
+end
+
+def fun_l5_n155()
+ fun_l6_n987
+end
+
+def fun_l5_n156()
+ fun_l6_n414
+end
+
+def fun_l5_n157()
+ fun_l6_n758
+end
+
+def fun_l5_n158()
+ fun_l6_n889
+end
+
+def fun_l5_n159()
+ fun_l6_n526
+end
+
+def fun_l5_n160()
+ fun_l6_n576
+end
+
+def fun_l5_n161()
+ fun_l6_n35
+end
+
+def fun_l5_n162()
+ fun_l6_n382
+end
+
+def fun_l5_n163()
+ fun_l6_n503
+end
+
+def fun_l5_n164()
+ fun_l6_n950
+end
+
+def fun_l5_n165()
+ fun_l6_n796
+end
+
+def fun_l5_n166()
+ fun_l6_n72
+end
+
+def fun_l5_n167()
+ fun_l6_n258
+end
+
+def fun_l5_n168()
+ fun_l6_n624
+end
+
+def fun_l5_n169()
+ fun_l6_n146
+end
+
+def fun_l5_n170()
+ fun_l6_n202
+end
+
+def fun_l5_n171()
+ fun_l6_n18
+end
+
+def fun_l5_n172()
+ fun_l6_n822
+end
+
+def fun_l5_n173()
+ fun_l6_n839
+end
+
+def fun_l5_n174()
+ fun_l6_n201
+end
+
+def fun_l5_n175()
+ fun_l6_n109
+end
+
+def fun_l5_n176()
+ fun_l6_n265
+end
+
+def fun_l5_n177()
+ fun_l6_n899
+end
+
+def fun_l5_n178()
+ fun_l6_n805
+end
+
+def fun_l5_n179()
+ fun_l6_n245
+end
+
+def fun_l5_n180()
+ fun_l6_n309
+end
+
+def fun_l5_n181()
+ fun_l6_n31
+end
+
+def fun_l5_n182()
+ fun_l6_n642
+end
+
+def fun_l5_n183()
+ fun_l6_n552
+end
+
+def fun_l5_n184()
+ fun_l6_n217
+end
+
+def fun_l5_n185()
+ fun_l6_n382
+end
+
+def fun_l5_n186()
+ fun_l6_n642
+end
+
+def fun_l5_n187()
+ fun_l6_n415
+end
+
+def fun_l5_n188()
+ fun_l6_n246
+end
+
+def fun_l5_n189()
+ fun_l6_n754
+end
+
+def fun_l5_n190()
+ fun_l6_n869
+end
+
+def fun_l5_n191()
+ fun_l6_n944
+end
+
+def fun_l5_n192()
+ fun_l6_n558
+end
+
+def fun_l5_n193()
+ fun_l6_n548
+end
+
+def fun_l5_n194()
+ fun_l6_n156
+end
+
+def fun_l5_n195()
+ fun_l6_n507
+end
+
+def fun_l5_n196()
+ fun_l6_n897
+end
+
+def fun_l5_n197()
+ fun_l6_n297
+end
+
+def fun_l5_n198()
+ fun_l6_n775
+end
+
+def fun_l5_n199()
+ fun_l6_n897
+end
+
+def fun_l5_n200()
+ fun_l6_n232
+end
+
+def fun_l5_n201()
+ fun_l6_n341
+end
+
+def fun_l5_n202()
+ fun_l6_n881
+end
+
+def fun_l5_n203()
+ fun_l6_n757
+end
+
+def fun_l5_n204()
+ fun_l6_n673
+end
+
+def fun_l5_n205()
+ fun_l6_n753
+end
+
+def fun_l5_n206()
+ fun_l6_n191
+end
+
+def fun_l5_n207()
+ fun_l6_n768
+end
+
+def fun_l5_n208()
+ fun_l6_n963
+end
+
+def fun_l5_n209()
+ fun_l6_n102
+end
+
+def fun_l5_n210()
+ fun_l6_n355
+end
+
+def fun_l5_n211()
+ fun_l6_n838
+end
+
+def fun_l5_n212()
+ fun_l6_n388
+end
+
+def fun_l5_n213()
+ fun_l6_n840
+end
+
+def fun_l5_n214()
+ fun_l6_n501
+end
+
+def fun_l5_n215()
+ fun_l6_n792
+end
+
+def fun_l5_n216()
+ fun_l6_n360
+end
+
+def fun_l5_n217()
+ fun_l6_n70
+end
+
+def fun_l5_n218()
+ fun_l6_n887
+end
+
+def fun_l5_n219()
+ fun_l6_n57
+end
+
+def fun_l5_n220()
+ fun_l6_n595
+end
+
+def fun_l5_n221()
+ fun_l6_n988
+end
+
+def fun_l5_n222()
+ fun_l6_n191
+end
+
+def fun_l5_n223()
+ fun_l6_n667
+end
+
+def fun_l5_n224()
+ fun_l6_n410
+end
+
+def fun_l5_n225()
+ fun_l6_n636
+end
+
+def fun_l5_n226()
+ fun_l6_n669
+end
+
+def fun_l5_n227()
+ fun_l6_n980
+end
+
+def fun_l5_n228()
+ fun_l6_n521
+end
+
+def fun_l5_n229()
+ fun_l6_n707
+end
+
+def fun_l5_n230()
+ fun_l6_n757
+end
+
+def fun_l5_n231()
+ fun_l6_n360
+end
+
+def fun_l5_n232()
+ fun_l6_n480
+end
+
+def fun_l5_n233()
+ fun_l6_n8
+end
+
+def fun_l5_n234()
+ fun_l6_n47
+end
+
+def fun_l5_n235()
+ fun_l6_n985
+end
+
+def fun_l5_n236()
+ fun_l6_n331
+end
+
+def fun_l5_n237()
+ fun_l6_n314
+end
+
+def fun_l5_n238()
+ fun_l6_n666
+end
+
+def fun_l5_n239()
+ fun_l6_n289
+end
+
+def fun_l5_n240()
+ fun_l6_n487
+end
+
+def fun_l5_n241()
+ fun_l6_n298
+end
+
+def fun_l5_n242()
+ fun_l6_n460
+end
+
+def fun_l5_n243()
+ fun_l6_n63
+end
+
+def fun_l5_n244()
+ fun_l6_n898
+end
+
+def fun_l5_n245()
+ fun_l6_n706
+end
+
+def fun_l5_n246()
+ fun_l6_n276
+end
+
+def fun_l5_n247()
+ fun_l6_n709
+end
+
+def fun_l5_n248()
+ fun_l6_n60
+end
+
+def fun_l5_n249()
+ fun_l6_n53
+end
+
+def fun_l5_n250()
+ fun_l6_n396
+end
+
+def fun_l5_n251()
+ fun_l6_n124
+end
+
+def fun_l5_n252()
+ fun_l6_n713
+end
+
+def fun_l5_n253()
+ fun_l6_n208
+end
+
+def fun_l5_n254()
+ fun_l6_n345
+end
+
+def fun_l5_n255()
+ fun_l6_n976
+end
+
+def fun_l5_n256()
+ fun_l6_n775
+end
+
+def fun_l5_n257()
+ fun_l6_n20
+end
+
+def fun_l5_n258()
+ fun_l6_n476
+end
+
+def fun_l5_n259()
+ fun_l6_n80
+end
+
+def fun_l5_n260()
+ fun_l6_n160
+end
+
+def fun_l5_n261()
+ fun_l6_n624
+end
+
+def fun_l5_n262()
+ fun_l6_n275
+end
+
+def fun_l5_n263()
+ fun_l6_n301
+end
+
+def fun_l5_n264()
+ fun_l6_n640
+end
+
+def fun_l5_n265()
+ fun_l6_n473
+end
+
+def fun_l5_n266()
+ fun_l6_n991
+end
+
+def fun_l5_n267()
+ fun_l6_n458
+end
+
+def fun_l5_n268()
+ fun_l6_n128
+end
+
+def fun_l5_n269()
+ fun_l6_n28
+end
+
+def fun_l5_n270()
+ fun_l6_n40
+end
+
+def fun_l5_n271()
+ fun_l6_n48
+end
+
+def fun_l5_n272()
+ fun_l6_n916
+end
+
+def fun_l5_n273()
+ fun_l6_n114
+end
+
+def fun_l5_n274()
+ fun_l6_n747
+end
+
+def fun_l5_n275()
+ fun_l6_n239
+end
+
+def fun_l5_n276()
+ fun_l6_n151
+end
+
+def fun_l5_n277()
+ fun_l6_n820
+end
+
+def fun_l5_n278()
+ fun_l6_n684
+end
+
+def fun_l5_n279()
+ fun_l6_n628
+end
+
+def fun_l5_n280()
+ fun_l6_n248
+end
+
+def fun_l5_n281()
+ fun_l6_n793
+end
+
+def fun_l5_n282()
+ fun_l6_n137
+end
+
+def fun_l5_n283()
+ fun_l6_n520
+end
+
+def fun_l5_n284()
+ fun_l6_n750
+end
+
+def fun_l5_n285()
+ fun_l6_n445
+end
+
+def fun_l5_n286()
+ fun_l6_n419
+end
+
+def fun_l5_n287()
+ fun_l6_n681
+end
+
+def fun_l5_n288()
+ fun_l6_n16
+end
+
+def fun_l5_n289()
+ fun_l6_n939
+end
+
+def fun_l5_n290()
+ fun_l6_n664
+end
+
+def fun_l5_n291()
+ fun_l6_n580
+end
+
+def fun_l5_n292()
+ fun_l6_n945
+end
+
+def fun_l5_n293()
+ fun_l6_n129
+end
+
+def fun_l5_n294()
+ fun_l6_n142
+end
+
+def fun_l5_n295()
+ fun_l6_n774
+end
+
+def fun_l5_n296()
+ fun_l6_n667
+end
+
+def fun_l5_n297()
+ fun_l6_n659
+end
+
+def fun_l5_n298()
+ fun_l6_n82
+end
+
+def fun_l5_n299()
+ fun_l6_n452
+end
+
+def fun_l5_n300()
+ fun_l6_n340
+end
+
+def fun_l5_n301()
+ fun_l6_n675
+end
+
+def fun_l5_n302()
+ fun_l6_n506
+end
+
+def fun_l5_n303()
+ fun_l6_n166
+end
+
+def fun_l5_n304()
+ fun_l6_n220
+end
+
+def fun_l5_n305()
+ fun_l6_n894
+end
+
+def fun_l5_n306()
+ fun_l6_n467
+end
+
+def fun_l5_n307()
+ fun_l6_n204
+end
+
+def fun_l5_n308()
+ fun_l6_n580
+end
+
+def fun_l5_n309()
+ fun_l6_n90
+end
+
+def fun_l5_n310()
+ fun_l6_n854
+end
+
+def fun_l5_n311()
+ fun_l6_n384
+end
+
+def fun_l5_n312()
+ fun_l6_n540
+end
+
+def fun_l5_n313()
+ fun_l6_n314
+end
+
+def fun_l5_n314()
+ fun_l6_n90
+end
+
+def fun_l5_n315()
+ fun_l6_n106
+end
+
+def fun_l5_n316()
+ fun_l6_n404
+end
+
+def fun_l5_n317()
+ fun_l6_n396
+end
+
+def fun_l5_n318()
+ fun_l6_n229
+end
+
+def fun_l5_n319()
+ fun_l6_n137
+end
+
+def fun_l5_n320()
+ fun_l6_n781
+end
+
+def fun_l5_n321()
+ fun_l6_n949
+end
+
+def fun_l5_n322()
+ fun_l6_n810
+end
+
+def fun_l5_n323()
+ fun_l6_n574
+end
+
+def fun_l5_n324()
+ fun_l6_n465
+end
+
+def fun_l5_n325()
+ fun_l6_n785
+end
+
+def fun_l5_n326()
+ fun_l6_n408
+end
+
+def fun_l5_n327()
+ fun_l6_n658
+end
+
+def fun_l5_n328()
+ fun_l6_n1
+end
+
+def fun_l5_n329()
+ fun_l6_n586
+end
+
+def fun_l5_n330()
+ fun_l6_n375
+end
+
+def fun_l5_n331()
+ fun_l6_n950
+end
+
+def fun_l5_n332()
+ fun_l6_n924
+end
+
+def fun_l5_n333()
+ fun_l6_n224
+end
+
+def fun_l5_n334()
+ fun_l6_n786
+end
+
+def fun_l5_n335()
+ fun_l6_n184
+end
+
+def fun_l5_n336()
+ fun_l6_n125
+end
+
+def fun_l5_n337()
+ fun_l6_n215
+end
+
+def fun_l5_n338()
+ fun_l6_n110
+end
+
+def fun_l5_n339()
+ fun_l6_n16
+end
+
+def fun_l5_n340()
+ fun_l6_n746
+end
+
+def fun_l5_n341()
+ fun_l6_n50
+end
+
+def fun_l5_n342()
+ fun_l6_n198
+end
+
+def fun_l5_n343()
+ fun_l6_n735
+end
+
+def fun_l5_n344()
+ fun_l6_n260
+end
+
+def fun_l5_n345()
+ fun_l6_n481
+end
+
+def fun_l5_n346()
+ fun_l6_n100
+end
+
+def fun_l5_n347()
+ fun_l6_n581
+end
+
+def fun_l5_n348()
+ fun_l6_n803
+end
+
+def fun_l5_n349()
+ fun_l6_n495
+end
+
+def fun_l5_n350()
+ fun_l6_n316
+end
+
+def fun_l5_n351()
+ fun_l6_n810
+end
+
+def fun_l5_n352()
+ fun_l6_n21
+end
+
+def fun_l5_n353()
+ fun_l6_n409
+end
+
+def fun_l5_n354()
+ fun_l6_n814
+end
+
+def fun_l5_n355()
+ fun_l6_n525
+end
+
+def fun_l5_n356()
+ fun_l6_n445
+end
+
+def fun_l5_n357()
+ fun_l6_n940
+end
+
+def fun_l5_n358()
+ fun_l6_n508
+end
+
+def fun_l5_n359()
+ fun_l6_n511
+end
+
+def fun_l5_n360()
+ fun_l6_n29
+end
+
+def fun_l5_n361()
+ fun_l6_n272
+end
+
+def fun_l5_n362()
+ fun_l6_n715
+end
+
+def fun_l5_n363()
+ fun_l6_n518
+end
+
+def fun_l5_n364()
+ fun_l6_n392
+end
+
+def fun_l5_n365()
+ fun_l6_n762
+end
+
+def fun_l5_n366()
+ fun_l6_n250
+end
+
+def fun_l5_n367()
+ fun_l6_n192
+end
+
+def fun_l5_n368()
+ fun_l6_n741
+end
+
+def fun_l5_n369()
+ fun_l6_n340
+end
+
+def fun_l5_n370()
+ fun_l6_n891
+end
+
+def fun_l5_n371()
+ fun_l6_n22
+end
+
+def fun_l5_n372()
+ fun_l6_n369
+end
+
+def fun_l5_n373()
+ fun_l6_n653
+end
+
+def fun_l5_n374()
+ fun_l6_n282
+end
+
+def fun_l5_n375()
+ fun_l6_n7
+end
+
+def fun_l5_n376()
+ fun_l6_n511
+end
+
+def fun_l5_n377()
+ fun_l6_n511
+end
+
+def fun_l5_n378()
+ fun_l6_n718
+end
+
+def fun_l5_n379()
+ fun_l6_n521
+end
+
+def fun_l5_n380()
+ fun_l6_n331
+end
+
+def fun_l5_n381()
+ fun_l6_n343
+end
+
+def fun_l5_n382()
+ fun_l6_n411
+end
+
+def fun_l5_n383()
+ fun_l6_n780
+end
+
+def fun_l5_n384()
+ fun_l6_n398
+end
+
+def fun_l5_n385()
+ fun_l6_n173
+end
+
+def fun_l5_n386()
+ fun_l6_n693
+end
+
+def fun_l5_n387()
+ fun_l6_n360
+end
+
+def fun_l5_n388()
+ fun_l6_n146
+end
+
+def fun_l5_n389()
+ fun_l6_n796
+end
+
+def fun_l5_n390()
+ fun_l6_n403
+end
+
+def fun_l5_n391()
+ fun_l6_n662
+end
+
+def fun_l5_n392()
+ fun_l6_n281
+end
+
+def fun_l5_n393()
+ fun_l6_n617
+end
+
+def fun_l5_n394()
+ fun_l6_n367
+end
+
+def fun_l5_n395()
+ fun_l6_n433
+end
+
+def fun_l5_n396()
+ fun_l6_n748
+end
+
+def fun_l5_n397()
+ fun_l6_n600
+end
+
+def fun_l5_n398()
+ fun_l6_n490
+end
+
+def fun_l5_n399()
+ fun_l6_n120
+end
+
+def fun_l5_n400()
+ fun_l6_n549
+end
+
+def fun_l5_n401()
+ fun_l6_n148
+end
+
+def fun_l5_n402()
+ fun_l6_n488
+end
+
+def fun_l5_n403()
+ fun_l6_n316
+end
+
+def fun_l5_n404()
+ fun_l6_n106
+end
+
+def fun_l5_n405()
+ fun_l6_n702
+end
+
+def fun_l5_n406()
+ fun_l6_n787
+end
+
+def fun_l5_n407()
+ fun_l6_n9
+end
+
+def fun_l5_n408()
+ fun_l6_n338
+end
+
+def fun_l5_n409()
+ fun_l6_n83
+end
+
+def fun_l5_n410()
+ fun_l6_n234
+end
+
+def fun_l5_n411()
+ fun_l6_n147
+end
+
+def fun_l5_n412()
+ fun_l6_n602
+end
+
+def fun_l5_n413()
+ fun_l6_n173
+end
+
+def fun_l5_n414()
+ fun_l6_n420
+end
+
+def fun_l5_n415()
+ fun_l6_n214
+end
+
+def fun_l5_n416()
+ fun_l6_n400
+end
+
+def fun_l5_n417()
+ fun_l6_n35
+end
+
+def fun_l5_n418()
+ fun_l6_n545
+end
+
+def fun_l5_n419()
+ fun_l6_n823
+end
+
+def fun_l5_n420()
+ fun_l6_n401
+end
+
+def fun_l5_n421()
+ fun_l6_n447
+end
+
+def fun_l5_n422()
+ fun_l6_n461
+end
+
+def fun_l5_n423()
+ fun_l6_n447
+end
+
+def fun_l5_n424()
+ fun_l6_n530
+end
+
+def fun_l5_n425()
+ fun_l6_n104
+end
+
+def fun_l5_n426()
+ fun_l6_n206
+end
+
+def fun_l5_n427()
+ fun_l6_n25
+end
+
+def fun_l5_n428()
+ fun_l6_n867
+end
+
+def fun_l5_n429()
+ fun_l6_n160
+end
+
+def fun_l5_n430()
+ fun_l6_n152
+end
+
+def fun_l5_n431()
+ fun_l6_n308
+end
+
+def fun_l5_n432()
+ fun_l6_n603
+end
+
+def fun_l5_n433()
+ fun_l6_n270
+end
+
+def fun_l5_n434()
+ fun_l6_n397
+end
+
+def fun_l5_n435()
+ fun_l6_n819
+end
+
+def fun_l5_n436()
+ fun_l6_n476
+end
+
+def fun_l5_n437()
+ fun_l6_n533
+end
+
+def fun_l5_n438()
+ fun_l6_n989
+end
+
+def fun_l5_n439()
+ fun_l6_n329
+end
+
+def fun_l5_n440()
+ fun_l6_n216
+end
+
+def fun_l5_n441()
+ fun_l6_n54
+end
+
+def fun_l5_n442()
+ fun_l6_n374
+end
+
+def fun_l5_n443()
+ fun_l6_n544
+end
+
+def fun_l5_n444()
+ fun_l6_n586
+end
+
+def fun_l5_n445()
+ fun_l6_n137
+end
+
+def fun_l5_n446()
+ fun_l6_n115
+end
+
+def fun_l5_n447()
+ fun_l6_n908
+end
+
+def fun_l5_n448()
+ fun_l6_n657
+end
+
+def fun_l5_n449()
+ fun_l6_n876
+end
+
+def fun_l5_n450()
+ fun_l6_n585
+end
+
+def fun_l5_n451()
+ fun_l6_n159
+end
+
+def fun_l5_n452()
+ fun_l6_n66
+end
+
+def fun_l5_n453()
+ fun_l6_n327
+end
+
+def fun_l5_n454()
+ fun_l6_n441
+end
+
+def fun_l5_n455()
+ fun_l6_n399
+end
+
+def fun_l5_n456()
+ fun_l6_n335
+end
+
+def fun_l5_n457()
+ fun_l6_n820
+end
+
+def fun_l5_n458()
+ fun_l6_n494
+end
+
+def fun_l5_n459()
+ fun_l6_n683
+end
+
+def fun_l5_n460()
+ fun_l6_n453
+end
+
+def fun_l5_n461()
+ fun_l6_n202
+end
+
+def fun_l5_n462()
+ fun_l6_n274
+end
+
+def fun_l5_n463()
+ fun_l6_n493
+end
+
+def fun_l5_n464()
+ fun_l6_n874
+end
+
+def fun_l5_n465()
+ fun_l6_n882
+end
+
+def fun_l5_n466()
+ fun_l6_n706
+end
+
+def fun_l5_n467()
+ fun_l6_n356
+end
+
+def fun_l5_n468()
+ fun_l6_n21
+end
+
+def fun_l5_n469()
+ fun_l6_n131
+end
+
+def fun_l5_n470()
+ fun_l6_n818
+end
+
+def fun_l5_n471()
+ fun_l6_n58
+end
+
+def fun_l5_n472()
+ fun_l6_n606
+end
+
+def fun_l5_n473()
+ fun_l6_n368
+end
+
+def fun_l5_n474()
+ fun_l6_n266
+end
+
+def fun_l5_n475()
+ fun_l6_n910
+end
+
+def fun_l5_n476()
+ fun_l6_n406
+end
+
+def fun_l5_n477()
+ fun_l6_n522
+end
+
+def fun_l5_n478()
+ fun_l6_n479
+end
+
+def fun_l5_n479()
+ fun_l6_n247
+end
+
+def fun_l5_n480()
+ fun_l6_n785
+end
+
+def fun_l5_n481()
+ fun_l6_n953
+end
+
+def fun_l5_n482()
+ fun_l6_n443
+end
+
+def fun_l5_n483()
+ fun_l6_n834
+end
+
+def fun_l5_n484()
+ fun_l6_n494
+end
+
+def fun_l5_n485()
+ fun_l6_n65
+end
+
+def fun_l5_n486()
+ fun_l6_n93
+end
+
+def fun_l5_n487()
+ fun_l6_n702
+end
+
+def fun_l5_n488()
+ fun_l6_n571
+end
+
+def fun_l5_n489()
+ fun_l6_n233
+end
+
+def fun_l5_n490()
+ fun_l6_n106
+end
+
+def fun_l5_n491()
+ fun_l6_n806
+end
+
+def fun_l5_n492()
+ fun_l6_n795
+end
+
+def fun_l5_n493()
+ fun_l6_n273
+end
+
+def fun_l5_n494()
+ fun_l6_n943
+end
+
+def fun_l5_n495()
+ fun_l6_n710
+end
+
+def fun_l5_n496()
+ fun_l6_n419
+end
+
+def fun_l5_n497()
+ fun_l6_n758
+end
+
+def fun_l5_n498()
+ fun_l6_n677
+end
+
+def fun_l5_n499()
+ fun_l6_n573
+end
+
+def fun_l5_n500()
+ fun_l6_n576
+end
+
+def fun_l5_n501()
+ fun_l6_n654
+end
+
+def fun_l5_n502()
+ fun_l6_n497
+end
+
+def fun_l5_n503()
+ fun_l6_n75
+end
+
+def fun_l5_n504()
+ fun_l6_n660
+end
+
+def fun_l5_n505()
+ fun_l6_n923
+end
+
+def fun_l5_n506()
+ fun_l6_n250
+end
+
+def fun_l5_n507()
+ fun_l6_n648
+end
+
+def fun_l5_n508()
+ fun_l6_n785
+end
+
+def fun_l5_n509()
+ fun_l6_n158
+end
+
+def fun_l5_n510()
+ fun_l6_n564
+end
+
+def fun_l5_n511()
+ fun_l6_n916
+end
+
+def fun_l5_n512()
+ fun_l6_n943
+end
+
+def fun_l5_n513()
+ fun_l6_n468
+end
+
+def fun_l5_n514()
+ fun_l6_n165
+end
+
+def fun_l5_n515()
+ fun_l6_n566
+end
+
+def fun_l5_n516()
+ fun_l6_n280
+end
+
+def fun_l5_n517()
+ fun_l6_n998
+end
+
+def fun_l5_n518()
+ fun_l6_n282
+end
+
+def fun_l5_n519()
+ fun_l6_n419
+end
+
+def fun_l5_n520()
+ fun_l6_n10
+end
+
+def fun_l5_n521()
+ fun_l6_n298
+end
+
+def fun_l5_n522()
+ fun_l6_n571
+end
+
+def fun_l5_n523()
+ fun_l6_n873
+end
+
+def fun_l5_n524()
+ fun_l6_n165
+end
+
+def fun_l5_n525()
+ fun_l6_n807
+end
+
+def fun_l5_n526()
+ fun_l6_n194
+end
+
+def fun_l5_n527()
+ fun_l6_n410
+end
+
+def fun_l5_n528()
+ fun_l6_n377
+end
+
+def fun_l5_n529()
+ fun_l6_n328
+end
+
+def fun_l5_n530()
+ fun_l6_n322
+end
+
+def fun_l5_n531()
+ fun_l6_n760
+end
+
+def fun_l5_n532()
+ fun_l6_n738
+end
+
+def fun_l5_n533()
+ fun_l6_n388
+end
+
+def fun_l5_n534()
+ fun_l6_n609
+end
+
+def fun_l5_n535()
+ fun_l6_n808
+end
+
+def fun_l5_n536()
+ fun_l6_n686
+end
+
+def fun_l5_n537()
+ fun_l6_n825
+end
+
+def fun_l5_n538()
+ fun_l6_n940
+end
+
+def fun_l5_n539()
+ fun_l6_n147
+end
+
+def fun_l5_n540()
+ fun_l6_n851
+end
+
+def fun_l5_n541()
+ fun_l6_n983
+end
+
+def fun_l5_n542()
+ fun_l6_n938
+end
+
+def fun_l5_n543()
+ fun_l6_n323
+end
+
+def fun_l5_n544()
+ fun_l6_n662
+end
+
+def fun_l5_n545()
+ fun_l6_n611
+end
+
+def fun_l5_n546()
+ fun_l6_n185
+end
+
+def fun_l5_n547()
+ fun_l6_n321
+end
+
+def fun_l5_n548()
+ fun_l6_n353
+end
+
+def fun_l5_n549()
+ fun_l6_n240
+end
+
+def fun_l5_n550()
+ fun_l6_n69
+end
+
+def fun_l5_n551()
+ fun_l6_n58
+end
+
+def fun_l5_n552()
+ fun_l6_n108
+end
+
+def fun_l5_n553()
+ fun_l6_n169
+end
+
+def fun_l5_n554()
+ fun_l6_n649
+end
+
+def fun_l5_n555()
+ fun_l6_n28
+end
+
+def fun_l5_n556()
+ fun_l6_n136
+end
+
+def fun_l5_n557()
+ fun_l6_n958
+end
+
+def fun_l5_n558()
+ fun_l6_n107
+end
+
+def fun_l5_n559()
+ fun_l6_n495
+end
+
+def fun_l5_n560()
+ fun_l6_n927
+end
+
+def fun_l5_n561()
+ fun_l6_n994
+end
+
+def fun_l5_n562()
+ fun_l6_n134
+end
+
+def fun_l5_n563()
+ fun_l6_n393
+end
+
+def fun_l5_n564()
+ fun_l6_n73
+end
+
+def fun_l5_n565()
+ fun_l6_n860
+end
+
+def fun_l5_n566()
+ fun_l6_n763
+end
+
+def fun_l5_n567()
+ fun_l6_n545
+end
+
+def fun_l5_n568()
+ fun_l6_n429
+end
+
+def fun_l5_n569()
+ fun_l6_n430
+end
+
+def fun_l5_n570()
+ fun_l6_n50
+end
+
+def fun_l5_n571()
+ fun_l6_n574
+end
+
+def fun_l5_n572()
+ fun_l6_n195
+end
+
+def fun_l5_n573()
+ fun_l6_n327
+end
+
+def fun_l5_n574()
+ fun_l6_n207
+end
+
+def fun_l5_n575()
+ fun_l6_n669
+end
+
+def fun_l5_n576()
+ fun_l6_n978
+end
+
+def fun_l5_n577()
+ fun_l6_n60
+end
+
+def fun_l5_n578()
+ fun_l6_n561
+end
+
+def fun_l5_n579()
+ fun_l6_n298
+end
+
+def fun_l5_n580()
+ fun_l6_n790
+end
+
+def fun_l5_n581()
+ fun_l6_n887
+end
+
+def fun_l5_n582()
+ fun_l6_n516
+end
+
+def fun_l5_n583()
+ fun_l6_n895
+end
+
+def fun_l5_n584()
+ fun_l6_n345
+end
+
+def fun_l5_n585()
+ fun_l6_n117
+end
+
+def fun_l5_n586()
+ fun_l6_n493
+end
+
+def fun_l5_n587()
+ fun_l6_n84
+end
+
+def fun_l5_n588()
+ fun_l6_n62
+end
+
+def fun_l5_n589()
+ fun_l6_n91
+end
+
+def fun_l5_n590()
+ fun_l6_n113
+end
+
+def fun_l5_n591()
+ fun_l6_n568
+end
+
+def fun_l5_n592()
+ fun_l6_n273
+end
+
+def fun_l5_n593()
+ fun_l6_n557
+end
+
+def fun_l5_n594()
+ fun_l6_n528
+end
+
+def fun_l5_n595()
+ fun_l6_n283
+end
+
+def fun_l5_n596()
+ fun_l6_n962
+end
+
+def fun_l5_n597()
+ fun_l6_n140
+end
+
+def fun_l5_n598()
+ fun_l6_n780
+end
+
+def fun_l5_n599()
+ fun_l6_n220
+end
+
+def fun_l5_n600()
+ fun_l6_n43
+end
+
+def fun_l5_n601()
+ fun_l6_n256
+end
+
+def fun_l5_n602()
+ fun_l6_n619
+end
+
+def fun_l5_n603()
+ fun_l6_n873
+end
+
+def fun_l5_n604()
+ fun_l6_n975
+end
+
+def fun_l5_n605()
+ fun_l6_n308
+end
+
+def fun_l5_n606()
+ fun_l6_n519
+end
+
+def fun_l5_n607()
+ fun_l6_n356
+end
+
+def fun_l5_n608()
+ fun_l6_n7
+end
+
+def fun_l5_n609()
+ fun_l6_n161
+end
+
+def fun_l5_n610()
+ fun_l6_n122
+end
+
+def fun_l5_n611()
+ fun_l6_n311
+end
+
+def fun_l5_n612()
+ fun_l6_n130
+end
+
+def fun_l5_n613()
+ fun_l6_n603
+end
+
+def fun_l5_n614()
+ fun_l6_n53
+end
+
+def fun_l5_n615()
+ fun_l6_n478
+end
+
+def fun_l5_n616()
+ fun_l6_n585
+end
+
+def fun_l5_n617()
+ fun_l6_n639
+end
+
+def fun_l5_n618()
+ fun_l6_n943
+end
+
+def fun_l5_n619()
+ fun_l6_n432
+end
+
+def fun_l5_n620()
+ fun_l6_n959
+end
+
+def fun_l5_n621()
+ fun_l6_n220
+end
+
+def fun_l5_n622()
+ fun_l6_n243
+end
+
+def fun_l5_n623()
+ fun_l6_n755
+end
+
+def fun_l5_n624()
+ fun_l6_n312
+end
+
+def fun_l5_n625()
+ fun_l6_n61
+end
+
+def fun_l5_n626()
+ fun_l6_n290
+end
+
+def fun_l5_n627()
+ fun_l6_n452
+end
+
+def fun_l5_n628()
+ fun_l6_n225
+end
+
+def fun_l5_n629()
+ fun_l6_n69
+end
+
+def fun_l5_n630()
+ fun_l6_n329
+end
+
+def fun_l5_n631()
+ fun_l6_n24
+end
+
+def fun_l5_n632()
+ fun_l6_n798
+end
+
+def fun_l5_n633()
+ fun_l6_n931
+end
+
+def fun_l5_n634()
+ fun_l6_n801
+end
+
+def fun_l5_n635()
+ fun_l6_n725
+end
+
+def fun_l5_n636()
+ fun_l6_n839
+end
+
+def fun_l5_n637()
+ fun_l6_n870
+end
+
+def fun_l5_n638()
+ fun_l6_n847
+end
+
+def fun_l5_n639()
+ fun_l6_n448
+end
+
+def fun_l5_n640()
+ fun_l6_n46
+end
+
+def fun_l5_n641()
+ fun_l6_n359
+end
+
+def fun_l5_n642()
+ fun_l6_n102
+end
+
+def fun_l5_n643()
+ fun_l6_n149
+end
+
+def fun_l5_n644()
+ fun_l6_n126
+end
+
+def fun_l5_n645()
+ fun_l6_n72
+end
+
+def fun_l5_n646()
+ fun_l6_n320
+end
+
+def fun_l5_n647()
+ fun_l6_n483
+end
+
+def fun_l5_n648()
+ fun_l6_n797
+end
+
+def fun_l5_n649()
+ fun_l6_n130
+end
+
+def fun_l5_n650()
+ fun_l6_n711
+end
+
+def fun_l5_n651()
+ fun_l6_n979
+end
+
+def fun_l5_n652()
+ fun_l6_n534
+end
+
+def fun_l5_n653()
+ fun_l6_n335
+end
+
+def fun_l5_n654()
+ fun_l6_n181
+end
+
+def fun_l5_n655()
+ fun_l6_n435
+end
+
+def fun_l5_n656()
+ fun_l6_n412
+end
+
+def fun_l5_n657()
+ fun_l6_n247
+end
+
+def fun_l5_n658()
+ fun_l6_n450
+end
+
+def fun_l5_n659()
+ fun_l6_n367
+end
+
+def fun_l5_n660()
+ fun_l6_n220
+end
+
+def fun_l5_n661()
+ fun_l6_n410
+end
+
+def fun_l5_n662()
+ fun_l6_n739
+end
+
+def fun_l5_n663()
+ fun_l6_n846
+end
+
+def fun_l5_n664()
+ fun_l6_n238
+end
+
+def fun_l5_n665()
+ fun_l6_n419
+end
+
+def fun_l5_n666()
+ fun_l6_n687
+end
+
+def fun_l5_n667()
+ fun_l6_n229
+end
+
+def fun_l5_n668()
+ fun_l6_n129
+end
+
+def fun_l5_n669()
+ fun_l6_n767
+end
+
+def fun_l5_n670()
+ fun_l6_n809
+end
+
+def fun_l5_n671()
+ fun_l6_n301
+end
+
+def fun_l5_n672()
+ fun_l6_n268
+end
+
+def fun_l5_n673()
+ fun_l6_n635
+end
+
+def fun_l5_n674()
+ fun_l6_n623
+end
+
+def fun_l5_n675()
+ fun_l6_n601
+end
+
+def fun_l5_n676()
+ fun_l6_n464
+end
+
+def fun_l5_n677()
+ fun_l6_n285
+end
+
+def fun_l5_n678()
+ fun_l6_n536
+end
+
+def fun_l5_n679()
+ fun_l6_n233
+end
+
+def fun_l5_n680()
+ fun_l6_n78
+end
+
+def fun_l5_n681()
+ fun_l6_n644
+end
+
+def fun_l5_n682()
+ fun_l6_n289
+end
+
+def fun_l5_n683()
+ fun_l6_n314
+end
+
+def fun_l5_n684()
+ fun_l6_n743
+end
+
+def fun_l5_n685()
+ fun_l6_n444
+end
+
+def fun_l5_n686()
+ fun_l6_n645
+end
+
+def fun_l5_n687()
+ fun_l6_n800
+end
+
+def fun_l5_n688()
+ fun_l6_n507
+end
+
+def fun_l5_n689()
+ fun_l6_n675
+end
+
+def fun_l5_n690()
+ fun_l6_n231
+end
+
+def fun_l5_n691()
+ fun_l6_n595
+end
+
+def fun_l5_n692()
+ fun_l6_n675
+end
+
+def fun_l5_n693()
+ fun_l6_n555
+end
+
+def fun_l5_n694()
+ fun_l6_n35
+end
+
+def fun_l5_n695()
+ fun_l6_n342
+end
+
+def fun_l5_n696()
+ fun_l6_n250
+end
+
+def fun_l5_n697()
+ fun_l6_n706
+end
+
+def fun_l5_n698()
+ fun_l6_n550
+end
+
+def fun_l5_n699()
+ fun_l6_n446
+end
+
+def fun_l5_n700()
+ fun_l6_n190
+end
+
+def fun_l5_n701()
+ fun_l6_n404
+end
+
+def fun_l5_n702()
+ fun_l6_n545
+end
+
+def fun_l5_n703()
+ fun_l6_n721
+end
+
+def fun_l5_n704()
+ fun_l6_n681
+end
+
+def fun_l5_n705()
+ fun_l6_n760
+end
+
+def fun_l5_n706()
+ fun_l6_n853
+end
+
+def fun_l5_n707()
+ fun_l6_n847
+end
+
+def fun_l5_n708()
+ fun_l6_n661
+end
+
+def fun_l5_n709()
+ fun_l6_n257
+end
+
+def fun_l5_n710()
+ fun_l6_n151
+end
+
+def fun_l5_n711()
+ fun_l6_n120
+end
+
+def fun_l5_n712()
+ fun_l6_n701
+end
+
+def fun_l5_n713()
+ fun_l6_n89
+end
+
+def fun_l5_n714()
+ fun_l6_n443
+end
+
+def fun_l5_n715()
+ fun_l6_n969
+end
+
+def fun_l5_n716()
+ fun_l6_n879
+end
+
+def fun_l5_n717()
+ fun_l6_n525
+end
+
+def fun_l5_n718()
+ fun_l6_n471
+end
+
+def fun_l5_n719()
+ fun_l6_n762
+end
+
+def fun_l5_n720()
+ fun_l6_n803
+end
+
+def fun_l5_n721()
+ fun_l6_n741
+end
+
+def fun_l5_n722()
+ fun_l6_n279
+end
+
+def fun_l5_n723()
+ fun_l6_n903
+end
+
+def fun_l5_n724()
+ fun_l6_n20
+end
+
+def fun_l5_n725()
+ fun_l6_n930
+end
+
+def fun_l5_n726()
+ fun_l6_n504
+end
+
+def fun_l5_n727()
+ fun_l6_n978
+end
+
+def fun_l5_n728()
+ fun_l6_n304
+end
+
+def fun_l5_n729()
+ fun_l6_n133
+end
+
+def fun_l5_n730()
+ fun_l6_n430
+end
+
+def fun_l5_n731()
+ fun_l6_n917
+end
+
+def fun_l5_n732()
+ fun_l6_n987
+end
+
+def fun_l5_n733()
+ fun_l6_n24
+end
+
+def fun_l5_n734()
+ fun_l6_n884
+end
+
+def fun_l5_n735()
+ fun_l6_n928
+end
+
+def fun_l5_n736()
+ fun_l6_n126
+end
+
+def fun_l5_n737()
+ fun_l6_n425
+end
+
+def fun_l5_n738()
+ fun_l6_n113
+end
+
+def fun_l5_n739()
+ fun_l6_n779
+end
+
+def fun_l5_n740()
+ fun_l6_n649
+end
+
+def fun_l5_n741()
+ fun_l6_n352
+end
+
+def fun_l5_n742()
+ fun_l6_n369
+end
+
+def fun_l5_n743()
+ fun_l6_n13
+end
+
+def fun_l5_n744()
+ fun_l6_n460
+end
+
+def fun_l5_n745()
+ fun_l6_n476
+end
+
+def fun_l5_n746()
+ fun_l6_n146
+end
+
+def fun_l5_n747()
+ fun_l6_n38
+end
+
+def fun_l5_n748()
+ fun_l6_n86
+end
+
+def fun_l5_n749()
+ fun_l6_n875
+end
+
+def fun_l5_n750()
+ fun_l6_n812
+end
+
+def fun_l5_n751()
+ fun_l6_n282
+end
+
+def fun_l5_n752()
+ fun_l6_n474
+end
+
+def fun_l5_n753()
+ fun_l6_n546
+end
+
+def fun_l5_n754()
+ fun_l6_n107
+end
+
+def fun_l5_n755()
+ fun_l6_n550
+end
+
+def fun_l5_n756()
+ fun_l6_n868
+end
+
+def fun_l5_n757()
+ fun_l6_n149
+end
+
+def fun_l5_n758()
+ fun_l6_n662
+end
+
+def fun_l5_n759()
+ fun_l6_n642
+end
+
+def fun_l5_n760()
+ fun_l6_n760
+end
+
+def fun_l5_n761()
+ fun_l6_n530
+end
+
+def fun_l5_n762()
+ fun_l6_n765
+end
+
+def fun_l5_n763()
+ fun_l6_n634
+end
+
+def fun_l5_n764()
+ fun_l6_n946
+end
+
+def fun_l5_n765()
+ fun_l6_n423
+end
+
+def fun_l5_n766()
+ fun_l6_n478
+end
+
+def fun_l5_n767()
+ fun_l6_n142
+end
+
+def fun_l5_n768()
+ fun_l6_n550
+end
+
+def fun_l5_n769()
+ fun_l6_n610
+end
+
+def fun_l5_n770()
+ fun_l6_n340
+end
+
+def fun_l5_n771()
+ fun_l6_n29
+end
+
+def fun_l5_n772()
+ fun_l6_n164
+end
+
+def fun_l5_n773()
+ fun_l6_n476
+end
+
+def fun_l5_n774()
+ fun_l6_n48
+end
+
+def fun_l5_n775()
+ fun_l6_n123
+end
+
+def fun_l5_n776()
+ fun_l6_n879
+end
+
+def fun_l5_n777()
+ fun_l6_n958
+end
+
+def fun_l5_n778()
+ fun_l6_n100
+end
+
+def fun_l5_n779()
+ fun_l6_n927
+end
+
+def fun_l5_n780()
+ fun_l6_n105
+end
+
+def fun_l5_n781()
+ fun_l6_n360
+end
+
+def fun_l5_n782()
+ fun_l6_n327
+end
+
+def fun_l5_n783()
+ fun_l6_n677
+end
+
+def fun_l5_n784()
+ fun_l6_n378
+end
+
+def fun_l5_n785()
+ fun_l6_n9
+end
+
+def fun_l5_n786()
+ fun_l6_n692
+end
+
+def fun_l5_n787()
+ fun_l6_n952
+end
+
+def fun_l5_n788()
+ fun_l6_n156
+end
+
+def fun_l5_n789()
+ fun_l6_n222
+end
+
+def fun_l5_n790()
+ fun_l6_n419
+end
+
+def fun_l5_n791()
+ fun_l6_n128
+end
+
+def fun_l5_n792()
+ fun_l6_n311
+end
+
+def fun_l5_n793()
+ fun_l6_n610
+end
+
+def fun_l5_n794()
+ fun_l6_n897
+end
+
+def fun_l5_n795()
+ fun_l6_n806
+end
+
+def fun_l5_n796()
+ fun_l6_n291
+end
+
+def fun_l5_n797()
+ fun_l6_n942
+end
+
+def fun_l5_n798()
+ fun_l6_n208
+end
+
+def fun_l5_n799()
+ fun_l6_n776
+end
+
+def fun_l5_n800()
+ fun_l6_n866
+end
+
+def fun_l5_n801()
+ fun_l6_n132
+end
+
+def fun_l5_n802()
+ fun_l6_n436
+end
+
+def fun_l5_n803()
+ fun_l6_n804
+end
+
+def fun_l5_n804()
+ fun_l6_n810
+end
+
+def fun_l5_n805()
+ fun_l6_n302
+end
+
+def fun_l5_n806()
+ fun_l6_n501
+end
+
+def fun_l5_n807()
+ fun_l6_n812
+end
+
+def fun_l5_n808()
+ fun_l6_n861
+end
+
+def fun_l5_n809()
+ fun_l6_n359
+end
+
+def fun_l5_n810()
+ fun_l6_n366
+end
+
+def fun_l5_n811()
+ fun_l6_n855
+end
+
+def fun_l5_n812()
+ fun_l6_n960
+end
+
+def fun_l5_n813()
+ fun_l6_n868
+end
+
+def fun_l5_n814()
+ fun_l6_n101
+end
+
+def fun_l5_n815()
+ fun_l6_n540
+end
+
+def fun_l5_n816()
+ fun_l6_n486
+end
+
+def fun_l5_n817()
+ fun_l6_n896
+end
+
+def fun_l5_n818()
+ fun_l6_n240
+end
+
+def fun_l5_n819()
+ fun_l6_n425
+end
+
+def fun_l5_n820()
+ fun_l6_n408
+end
+
+def fun_l5_n821()
+ fun_l6_n779
+end
+
+def fun_l5_n822()
+ fun_l6_n486
+end
+
+def fun_l5_n823()
+ fun_l6_n903
+end
+
+def fun_l5_n824()
+ fun_l6_n957
+end
+
+def fun_l5_n825()
+ fun_l6_n213
+end
+
+def fun_l5_n826()
+ fun_l6_n326
+end
+
+def fun_l5_n827()
+ fun_l6_n944
+end
+
+def fun_l5_n828()
+ fun_l6_n772
+end
+
+def fun_l5_n829()
+ fun_l6_n879
+end
+
+def fun_l5_n830()
+ fun_l6_n406
+end
+
+def fun_l5_n831()
+ fun_l6_n488
+end
+
+def fun_l5_n832()
+ fun_l6_n615
+end
+
+def fun_l5_n833()
+ fun_l6_n113
+end
+
+def fun_l5_n834()
+ fun_l6_n826
+end
+
+def fun_l5_n835()
+ fun_l6_n621
+end
+
+def fun_l5_n836()
+ fun_l6_n520
+end
+
+def fun_l5_n837()
+ fun_l6_n729
+end
+
+def fun_l5_n838()
+ fun_l6_n83
+end
+
+def fun_l5_n839()
+ fun_l6_n616
+end
+
+def fun_l5_n840()
+ fun_l6_n477
+end
+
+def fun_l5_n841()
+ fun_l6_n25
+end
+
+def fun_l5_n842()
+ fun_l6_n391
+end
+
+def fun_l5_n843()
+ fun_l6_n974
+end
+
+def fun_l5_n844()
+ fun_l6_n970
+end
+
+def fun_l5_n845()
+ fun_l6_n316
+end
+
+def fun_l5_n846()
+ fun_l6_n596
+end
+
+def fun_l5_n847()
+ fun_l6_n518
+end
+
+def fun_l5_n848()
+ fun_l6_n437
+end
+
+def fun_l5_n849()
+ fun_l6_n268
+end
+
+def fun_l5_n850()
+ fun_l6_n347
+end
+
+def fun_l5_n851()
+ fun_l6_n110
+end
+
+def fun_l5_n852()
+ fun_l6_n783
+end
+
+def fun_l5_n853()
+ fun_l6_n503
+end
+
+def fun_l5_n854()
+ fun_l6_n56
+end
+
+def fun_l5_n855()
+ fun_l6_n294
+end
+
+def fun_l5_n856()
+ fun_l6_n145
+end
+
+def fun_l5_n857()
+ fun_l6_n627
+end
+
+def fun_l5_n858()
+ fun_l6_n917
+end
+
+def fun_l5_n859()
+ fun_l6_n242
+end
+
+def fun_l5_n860()
+ fun_l6_n35
+end
+
+def fun_l5_n861()
+ fun_l6_n883
+end
+
+def fun_l5_n862()
+ fun_l6_n766
+end
+
+def fun_l5_n863()
+ fun_l6_n877
+end
+
+def fun_l5_n864()
+ fun_l6_n974
+end
+
+def fun_l5_n865()
+ fun_l6_n525
+end
+
+def fun_l5_n866()
+ fun_l6_n490
+end
+
+def fun_l5_n867()
+ fun_l6_n920
+end
+
+def fun_l5_n868()
+ fun_l6_n28
+end
+
+def fun_l5_n869()
+ fun_l6_n855
+end
+
+def fun_l5_n870()
+ fun_l6_n246
+end
+
+def fun_l5_n871()
+ fun_l6_n60
+end
+
+def fun_l5_n872()
+ fun_l6_n868
+end
+
+def fun_l5_n873()
+ fun_l6_n706
+end
+
+def fun_l5_n874()
+ fun_l6_n629
+end
+
+def fun_l5_n875()
+ fun_l6_n44
+end
+
+def fun_l5_n876()
+ fun_l6_n521
+end
+
+def fun_l5_n877()
+ fun_l6_n607
+end
+
+def fun_l5_n878()
+ fun_l6_n385
+end
+
+def fun_l5_n879()
+ fun_l6_n109
+end
+
+def fun_l5_n880()
+ fun_l6_n296
+end
+
+def fun_l5_n881()
+ fun_l6_n466
+end
+
+def fun_l5_n882()
+ fun_l6_n933
+end
+
+def fun_l5_n883()
+ fun_l6_n529
+end
+
+def fun_l5_n884()
+ fun_l6_n863
+end
+
+def fun_l5_n885()
+ fun_l6_n112
+end
+
+def fun_l5_n886()
+ fun_l6_n262
+end
+
+def fun_l5_n887()
+ fun_l6_n853
+end
+
+def fun_l5_n888()
+ fun_l6_n657
+end
+
+def fun_l5_n889()
+ fun_l6_n860
+end
+
+def fun_l5_n890()
+ fun_l6_n878
+end
+
+def fun_l5_n891()
+ fun_l6_n810
+end
+
+def fun_l5_n892()
+ fun_l6_n285
+end
+
+def fun_l5_n893()
+ fun_l6_n319
+end
+
+def fun_l5_n894()
+ fun_l6_n927
+end
+
+def fun_l5_n895()
+ fun_l6_n530
+end
+
+def fun_l5_n896()
+ fun_l6_n874
+end
+
+def fun_l5_n897()
+ fun_l6_n522
+end
+
+def fun_l5_n898()
+ fun_l6_n31
+end
+
+def fun_l5_n899()
+ fun_l6_n292
+end
+
+def fun_l5_n900()
+ fun_l6_n847
+end
+
+def fun_l5_n901()
+ fun_l6_n989
+end
+
+def fun_l5_n902()
+ fun_l6_n435
+end
+
+def fun_l5_n903()
+ fun_l6_n368
+end
+
+def fun_l5_n904()
+ fun_l6_n320
+end
+
+def fun_l5_n905()
+ fun_l6_n889
+end
+
+def fun_l5_n906()
+ fun_l6_n101
+end
+
+def fun_l5_n907()
+ fun_l6_n717
+end
+
+def fun_l5_n908()
+ fun_l6_n456
+end
+
+def fun_l5_n909()
+ fun_l6_n448
+end
+
+def fun_l5_n910()
+ fun_l6_n523
+end
+
+def fun_l5_n911()
+ fun_l6_n604
+end
+
+def fun_l5_n912()
+ fun_l6_n429
+end
+
+def fun_l5_n913()
+ fun_l6_n947
+end
+
+def fun_l5_n914()
+ fun_l6_n804
+end
+
+def fun_l5_n915()
+ fun_l6_n665
+end
+
+def fun_l5_n916()
+ fun_l6_n195
+end
+
+def fun_l5_n917()
+ fun_l6_n803
+end
+
+def fun_l5_n918()
+ fun_l6_n957
+end
+
+def fun_l5_n919()
+ fun_l6_n187
+end
+
+def fun_l5_n920()
+ fun_l6_n489
+end
+
+def fun_l5_n921()
+ fun_l6_n315
+end
+
+def fun_l5_n922()
+ fun_l6_n216
+end
+
+def fun_l5_n923()
+ fun_l6_n482
+end
+
+def fun_l5_n924()
+ fun_l6_n20
+end
+
+def fun_l5_n925()
+ fun_l6_n941
+end
+
+def fun_l5_n926()
+ fun_l6_n73
+end
+
+def fun_l5_n927()
+ fun_l6_n563
+end
+
+def fun_l5_n928()
+ fun_l6_n179
+end
+
+def fun_l5_n929()
+ fun_l6_n861
+end
+
+def fun_l5_n930()
+ fun_l6_n811
+end
+
+def fun_l5_n931()
+ fun_l6_n996
+end
+
+def fun_l5_n932()
+ fun_l6_n25
+end
+
+def fun_l5_n933()
+ fun_l6_n232
+end
+
+def fun_l5_n934()
+ fun_l6_n671
+end
+
+def fun_l5_n935()
+ fun_l6_n162
+end
+
+def fun_l5_n936()
+ fun_l6_n363
+end
+
+def fun_l5_n937()
+ fun_l6_n517
+end
+
+def fun_l5_n938()
+ fun_l6_n655
+end
+
+def fun_l5_n939()
+ fun_l6_n825
+end
+
+def fun_l5_n940()
+ fun_l6_n58
+end
+
+def fun_l5_n941()
+ fun_l6_n440
+end
+
+def fun_l5_n942()
+ fun_l6_n106
+end
+
+def fun_l5_n943()
+ fun_l6_n218
+end
+
+def fun_l5_n944()
+ fun_l6_n580
+end
+
+def fun_l5_n945()
+ fun_l6_n63
+end
+
+def fun_l5_n946()
+ fun_l6_n116
+end
+
+def fun_l5_n947()
+ fun_l6_n329
+end
+
+def fun_l5_n948()
+ fun_l6_n511
+end
+
+def fun_l5_n949()
+ fun_l6_n499
+end
+
+def fun_l5_n950()
+ fun_l6_n469
+end
+
+def fun_l5_n951()
+ fun_l6_n18
+end
+
+def fun_l5_n952()
+ fun_l6_n200
+end
+
+def fun_l5_n953()
+ fun_l6_n924
+end
+
+def fun_l5_n954()
+ fun_l6_n879
+end
+
+def fun_l5_n955()
+ fun_l6_n959
+end
+
+def fun_l5_n956()
+ fun_l6_n867
+end
+
+def fun_l5_n957()
+ fun_l6_n650
+end
+
+def fun_l5_n958()
+ fun_l6_n481
+end
+
+def fun_l5_n959()
+ fun_l6_n892
+end
+
+def fun_l5_n960()
+ fun_l6_n499
+end
+
+def fun_l5_n961()
+ fun_l6_n406
+end
+
+def fun_l5_n962()
+ fun_l6_n762
+end
+
+def fun_l5_n963()
+ fun_l6_n479
+end
+
+def fun_l5_n964()
+ fun_l6_n869
+end
+
+def fun_l5_n965()
+ fun_l6_n321
+end
+
+def fun_l5_n966()
+ fun_l6_n722
+end
+
+def fun_l5_n967()
+ fun_l6_n834
+end
+
+def fun_l5_n968()
+ fun_l6_n873
+end
+
+def fun_l5_n969()
+ fun_l6_n295
+end
+
+def fun_l5_n970()
+ fun_l6_n394
+end
+
+def fun_l5_n971()
+ fun_l6_n944
+end
+
+def fun_l5_n972()
+ fun_l6_n335
+end
+
+def fun_l5_n973()
+ fun_l6_n958
+end
+
+def fun_l5_n974()
+ fun_l6_n159
+end
+
+def fun_l5_n975()
+ fun_l6_n336
+end
+
+def fun_l5_n976()
+ fun_l6_n979
+end
+
+def fun_l5_n977()
+ fun_l6_n106
+end
+
+def fun_l5_n978()
+ fun_l6_n587
+end
+
+def fun_l5_n979()
+ fun_l6_n693
+end
+
+def fun_l5_n980()
+ fun_l6_n633
+end
+
+def fun_l5_n981()
+ fun_l6_n359
+end
+
+def fun_l5_n982()
+ fun_l6_n118
+end
+
+def fun_l5_n983()
+ fun_l6_n689
+end
+
+def fun_l5_n984()
+ fun_l6_n398
+end
+
+def fun_l5_n985()
+ fun_l6_n985
+end
+
+def fun_l5_n986()
+ fun_l6_n381
+end
+
+def fun_l5_n987()
+ fun_l6_n322
+end
+
+def fun_l5_n988()
+ fun_l6_n817
+end
+
+def fun_l5_n989()
+ fun_l6_n793
+end
+
+def fun_l5_n990()
+ fun_l6_n619
+end
+
+def fun_l5_n991()
+ fun_l6_n876
+end
+
+def fun_l5_n992()
+ fun_l6_n390
+end
+
+def fun_l5_n993()
+ fun_l6_n58
+end
+
+def fun_l5_n994()
+ fun_l6_n545
+end
+
+def fun_l5_n995()
+ fun_l6_n364
+end
+
+def fun_l5_n996()
+ fun_l6_n849
+end
+
+def fun_l5_n997()
+ fun_l6_n185
+end
+
+def fun_l5_n998()
+ fun_l6_n56
+end
+
+def fun_l5_n999()
+ fun_l6_n156
+end
+
+def fun_l6_n0()
+ fun_l7_n367
+end
+
+def fun_l6_n1()
+ fun_l7_n681
+end
+
+def fun_l6_n2()
+ fun_l7_n170
+end
+
+def fun_l6_n3()
+ fun_l7_n39
+end
+
+def fun_l6_n4()
+ fun_l7_n320
+end
+
+def fun_l6_n5()
+ fun_l7_n862
+end
+
+def fun_l6_n6()
+ fun_l7_n604
+end
+
+def fun_l6_n7()
+ fun_l7_n816
+end
+
+def fun_l6_n8()
+ fun_l7_n31
+end
+
+def fun_l6_n9()
+ fun_l7_n285
+end
+
+def fun_l6_n10()
+ fun_l7_n74
+end
+
+def fun_l6_n11()
+ fun_l7_n638
+end
+
+def fun_l6_n12()
+ fun_l7_n471
+end
+
+def fun_l6_n13()
+ fun_l7_n909
+end
+
+def fun_l6_n14()
+ fun_l7_n677
+end
+
+def fun_l6_n15()
+ fun_l7_n603
+end
+
+def fun_l6_n16()
+ fun_l7_n670
+end
+
+def fun_l6_n17()
+ fun_l7_n270
+end
+
+def fun_l6_n18()
+ fun_l7_n10
+end
+
+def fun_l6_n19()
+ fun_l7_n963
+end
+
+def fun_l6_n20()
+ fun_l7_n517
+end
+
+def fun_l6_n21()
+ fun_l7_n956
+end
+
+def fun_l6_n22()
+ fun_l7_n13
+end
+
+def fun_l6_n23()
+ fun_l7_n157
+end
+
+def fun_l6_n24()
+ fun_l7_n828
+end
+
+def fun_l6_n25()
+ fun_l7_n895
+end
+
+def fun_l6_n26()
+ fun_l7_n48
+end
+
+def fun_l6_n27()
+ fun_l7_n760
+end
+
+def fun_l6_n28()
+ fun_l7_n674
+end
+
+def fun_l6_n29()
+ fun_l7_n639
+end
+
+def fun_l6_n30()
+ fun_l7_n395
+end
+
+def fun_l6_n31()
+ fun_l7_n541
+end
+
+def fun_l6_n32()
+ fun_l7_n548
+end
+
+def fun_l6_n33()
+ fun_l7_n348
+end
+
+def fun_l6_n34()
+ fun_l7_n257
+end
+
+def fun_l6_n35()
+ fun_l7_n531
+end
+
+def fun_l6_n36()
+ fun_l7_n210
+end
+
+def fun_l6_n37()
+ fun_l7_n56
+end
+
+def fun_l6_n38()
+ fun_l7_n466
+end
+
+def fun_l6_n39()
+ fun_l7_n369
+end
+
+def fun_l6_n40()
+ fun_l7_n465
+end
+
+def fun_l6_n41()
+ fun_l7_n665
+end
+
+def fun_l6_n42()
+ fun_l7_n662
+end
+
+def fun_l6_n43()
+ fun_l7_n205
+end
+
+def fun_l6_n44()
+ fun_l7_n997
+end
+
+def fun_l6_n45()
+ fun_l7_n840
+end
+
+def fun_l6_n46()
+ fun_l7_n998
+end
+
+def fun_l6_n47()
+ fun_l7_n563
+end
+
+def fun_l6_n48()
+ fun_l7_n442
+end
+
+def fun_l6_n49()
+ fun_l7_n768
+end
+
+def fun_l6_n50()
+ fun_l7_n948
+end
+
+def fun_l6_n51()
+ fun_l7_n773
+end
+
+def fun_l6_n52()
+ fun_l7_n910
+end
+
+def fun_l6_n53()
+ fun_l7_n152
+end
+
+def fun_l6_n54()
+ fun_l7_n277
+end
+
+def fun_l6_n55()
+ fun_l7_n139
+end
+
+def fun_l6_n56()
+ fun_l7_n530
+end
+
+def fun_l6_n57()
+ fun_l7_n587
+end
+
+def fun_l6_n58()
+ fun_l7_n650
+end
+
+def fun_l6_n59()
+ fun_l7_n30
+end
+
+def fun_l6_n60()
+ fun_l7_n31
+end
+
+def fun_l6_n61()
+ fun_l7_n908
+end
+
+def fun_l6_n62()
+ fun_l7_n228
+end
+
+def fun_l6_n63()
+ fun_l7_n210
+end
+
+def fun_l6_n64()
+ fun_l7_n854
+end
+
+def fun_l6_n65()
+ fun_l7_n198
+end
+
+def fun_l6_n66()
+ fun_l7_n183
+end
+
+def fun_l6_n67()
+ fun_l7_n633
+end
+
+def fun_l6_n68()
+ fun_l7_n523
+end
+
+def fun_l6_n69()
+ fun_l7_n392
+end
+
+def fun_l6_n70()
+ fun_l7_n293
+end
+
+def fun_l6_n71()
+ fun_l7_n523
+end
+
+def fun_l6_n72()
+ fun_l7_n314
+end
+
+def fun_l6_n73()
+ fun_l7_n500
+end
+
+def fun_l6_n74()
+ fun_l7_n685
+end
+
+def fun_l6_n75()
+ fun_l7_n692
+end
+
+def fun_l6_n76()
+ fun_l7_n773
+end
+
+def fun_l6_n77()
+ fun_l7_n582
+end
+
+def fun_l6_n78()
+ fun_l7_n934
+end
+
+def fun_l6_n79()
+ fun_l7_n829
+end
+
+def fun_l6_n80()
+ fun_l7_n603
+end
+
+def fun_l6_n81()
+ fun_l7_n735
+end
+
+def fun_l6_n82()
+ fun_l7_n906
+end
+
+def fun_l6_n83()
+ fun_l7_n828
+end
+
+def fun_l6_n84()
+ fun_l7_n945
+end
+
+def fun_l6_n85()
+ fun_l7_n316
+end
+
+def fun_l6_n86()
+ fun_l7_n135
+end
+
+def fun_l6_n87()
+ fun_l7_n444
+end
+
+def fun_l6_n88()
+ fun_l7_n300
+end
+
+def fun_l6_n89()
+ fun_l7_n975
+end
+
+def fun_l6_n90()
+ fun_l7_n385
+end
+
+def fun_l6_n91()
+ fun_l7_n885
+end
+
+def fun_l6_n92()
+ fun_l7_n838
+end
+
+def fun_l6_n93()
+ fun_l7_n769
+end
+
+def fun_l6_n94()
+ fun_l7_n263
+end
+
+def fun_l6_n95()
+ fun_l7_n719
+end
+
+def fun_l6_n96()
+ fun_l7_n585
+end
+
+def fun_l6_n97()
+ fun_l7_n238
+end
+
+def fun_l6_n98()
+ fun_l7_n366
+end
+
+def fun_l6_n99()
+ fun_l7_n498
+end
+
+def fun_l6_n100()
+ fun_l7_n596
+end
+
+def fun_l6_n101()
+ fun_l7_n437
+end
+
+def fun_l6_n102()
+ fun_l7_n441
+end
+
+def fun_l6_n103()
+ fun_l7_n721
+end
+
+def fun_l6_n104()
+ fun_l7_n9
+end
+
+def fun_l6_n105()
+ fun_l7_n412
+end
+
+def fun_l6_n106()
+ fun_l7_n981
+end
+
+def fun_l6_n107()
+ fun_l7_n824
+end
+
+def fun_l6_n108()
+ fun_l7_n255
+end
+
+def fun_l6_n109()
+ fun_l7_n608
+end
+
+def fun_l6_n110()
+ fun_l7_n481
+end
+
+def fun_l6_n111()
+ fun_l7_n804
+end
+
+def fun_l6_n112()
+ fun_l7_n316
+end
+
+def fun_l6_n113()
+ fun_l7_n446
+end
+
+def fun_l6_n114()
+ fun_l7_n123
+end
+
+def fun_l6_n115()
+ fun_l7_n522
+end
+
+def fun_l6_n116()
+ fun_l7_n52
+end
+
+def fun_l6_n117()
+ fun_l7_n559
+end
+
+def fun_l6_n118()
+ fun_l7_n937
+end
+
+def fun_l6_n119()
+ fun_l7_n425
+end
+
+def fun_l6_n120()
+ fun_l7_n112
+end
+
+def fun_l6_n121()
+ fun_l7_n83
+end
+
+def fun_l6_n122()
+ fun_l7_n305
+end
+
+def fun_l6_n123()
+ fun_l7_n157
+end
+
+def fun_l6_n124()
+ fun_l7_n944
+end
+
+def fun_l6_n125()
+ fun_l7_n356
+end
+
+def fun_l6_n126()
+ fun_l7_n69
+end
+
+def fun_l6_n127()
+ fun_l7_n689
+end
+
+def fun_l6_n128()
+ fun_l7_n145
+end
+
+def fun_l6_n129()
+ fun_l7_n633
+end
+
+def fun_l6_n130()
+ fun_l7_n389
+end
+
+def fun_l6_n131()
+ fun_l7_n646
+end
+
+def fun_l6_n132()
+ fun_l7_n684
+end
+
+def fun_l6_n133()
+ fun_l7_n38
+end
+
+def fun_l6_n134()
+ fun_l7_n104
+end
+
+def fun_l6_n135()
+ fun_l7_n856
+end
+
+def fun_l6_n136()
+ fun_l7_n237
+end
+
+def fun_l6_n137()
+ fun_l7_n594
+end
+
+def fun_l6_n138()
+ fun_l7_n929
+end
+
+def fun_l6_n139()
+ fun_l7_n686
+end
+
+def fun_l6_n140()
+ fun_l7_n501
+end
+
+def fun_l6_n141()
+ fun_l7_n309
+end
+
+def fun_l6_n142()
+ fun_l7_n567
+end
+
+def fun_l6_n143()
+ fun_l7_n451
+end
+
+def fun_l6_n144()
+ fun_l7_n325
+end
+
+def fun_l6_n145()
+ fun_l7_n363
+end
+
+def fun_l6_n146()
+ fun_l7_n650
+end
+
+def fun_l6_n147()
+ fun_l7_n551
+end
+
+def fun_l6_n148()
+ fun_l7_n495
+end
+
+def fun_l6_n149()
+ fun_l7_n998
+end
+
+def fun_l6_n150()
+ fun_l7_n584
+end
+
+def fun_l6_n151()
+ fun_l7_n36
+end
+
+def fun_l6_n152()
+ fun_l7_n109
+end
+
+def fun_l6_n153()
+ fun_l7_n855
+end
+
+def fun_l6_n154()
+ fun_l7_n544
+end
+
+def fun_l6_n155()
+ fun_l7_n580
+end
+
+def fun_l6_n156()
+ fun_l7_n872
+end
+
+def fun_l6_n157()
+ fun_l7_n954
+end
+
+def fun_l6_n158()
+ fun_l7_n14
+end
+
+def fun_l6_n159()
+ fun_l7_n802
+end
+
+def fun_l6_n160()
+ fun_l7_n298
+end
+
+def fun_l6_n161()
+ fun_l7_n876
+end
+
+def fun_l6_n162()
+ fun_l7_n694
+end
+
+def fun_l6_n163()
+ fun_l7_n538
+end
+
+def fun_l6_n164()
+ fun_l7_n325
+end
+
+def fun_l6_n165()
+ fun_l7_n47
+end
+
+def fun_l6_n166()
+ fun_l7_n433
+end
+
+def fun_l6_n167()
+ fun_l7_n356
+end
+
+def fun_l6_n168()
+ fun_l7_n81
+end
+
+def fun_l6_n169()
+ fun_l7_n10
+end
+
+def fun_l6_n170()
+ fun_l7_n391
+end
+
+def fun_l6_n171()
+ fun_l7_n770
+end
+
+def fun_l6_n172()
+ fun_l7_n45
+end
+
+def fun_l6_n173()
+ fun_l7_n808
+end
+
+def fun_l6_n174()
+ fun_l7_n722
+end
+
+def fun_l6_n175()
+ fun_l7_n532
+end
+
+def fun_l6_n176()
+ fun_l7_n983
+end
+
+def fun_l6_n177()
+ fun_l7_n666
+end
+
+def fun_l6_n178()
+ fun_l7_n505
+end
+
+def fun_l6_n179()
+ fun_l7_n200
+end
+
+def fun_l6_n180()
+ fun_l7_n57
+end
+
+def fun_l6_n181()
+ fun_l7_n888
+end
+
+def fun_l6_n182()
+ fun_l7_n288
+end
+
+def fun_l6_n183()
+ fun_l7_n435
+end
+
+def fun_l6_n184()
+ fun_l7_n330
+end
+
+def fun_l6_n185()
+ fun_l7_n432
+end
+
+def fun_l6_n186()
+ fun_l7_n321
+end
+
+def fun_l6_n187()
+ fun_l7_n160
+end
+
+def fun_l6_n188()
+ fun_l7_n806
+end
+
+def fun_l6_n189()
+ fun_l7_n929
+end
+
+def fun_l6_n190()
+ fun_l7_n49
+end
+
+def fun_l6_n191()
+ fun_l7_n642
+end
+
+def fun_l6_n192()
+ fun_l7_n551
+end
+
+def fun_l6_n193()
+ fun_l7_n243
+end
+
+def fun_l6_n194()
+ fun_l7_n126
+end
+
+def fun_l6_n195()
+ fun_l7_n594
+end
+
+def fun_l6_n196()
+ fun_l7_n166
+end
+
+def fun_l6_n197()
+ fun_l7_n610
+end
+
+def fun_l6_n198()
+ fun_l7_n730
+end
+
+def fun_l6_n199()
+ fun_l7_n770
+end
+
+def fun_l6_n200()
+ fun_l7_n873
+end
+
+def fun_l6_n201()
+ fun_l7_n833
+end
+
+def fun_l6_n202()
+ fun_l7_n883
+end
+
+def fun_l6_n203()
+ fun_l7_n639
+end
+
+def fun_l6_n204()
+ fun_l7_n563
+end
+
+def fun_l6_n205()
+ fun_l7_n437
+end
+
+def fun_l6_n206()
+ fun_l7_n722
+end
+
+def fun_l6_n207()
+ fun_l7_n785
+end
+
+def fun_l6_n208()
+ fun_l7_n241
+end
+
+def fun_l6_n209()
+ fun_l7_n42
+end
+
+def fun_l6_n210()
+ fun_l7_n352
+end
+
+def fun_l6_n211()
+ fun_l7_n633
+end
+
+def fun_l6_n212()
+ fun_l7_n758
+end
+
+def fun_l6_n213()
+ fun_l7_n194
+end
+
+def fun_l6_n214()
+ fun_l7_n864
+end
+
+def fun_l6_n215()
+ fun_l7_n407
+end
+
+def fun_l6_n216()
+ fun_l7_n78
+end
+
+def fun_l6_n217()
+ fun_l7_n723
+end
+
+def fun_l6_n218()
+ fun_l7_n98
+end
+
+def fun_l6_n219()
+ fun_l7_n909
+end
+
+def fun_l6_n220()
+ fun_l7_n380
+end
+
+def fun_l6_n221()
+ fun_l7_n348
+end
+
+def fun_l6_n222()
+ fun_l7_n934
+end
+
+def fun_l6_n223()
+ fun_l7_n114
+end
+
+def fun_l6_n224()
+ fun_l7_n34
+end
+
+def fun_l6_n225()
+ fun_l7_n774
+end
+
+def fun_l6_n226()
+ fun_l7_n681
+end
+
+def fun_l6_n227()
+ fun_l7_n215
+end
+
+def fun_l6_n228()
+ fun_l7_n526
+end
+
+def fun_l6_n229()
+ fun_l7_n38
+end
+
+def fun_l6_n230()
+ fun_l7_n506
+end
+
+def fun_l6_n231()
+ fun_l7_n456
+end
+
+def fun_l6_n232()
+ fun_l7_n476
+end
+
+def fun_l6_n233()
+ fun_l7_n183
+end
+
+def fun_l6_n234()
+ fun_l7_n73
+end
+
+def fun_l6_n235()
+ fun_l7_n639
+end
+
+def fun_l6_n236()
+ fun_l7_n344
+end
+
+def fun_l6_n237()
+ fun_l7_n656
+end
+
+def fun_l6_n238()
+ fun_l7_n887
+end
+
+def fun_l6_n239()
+ fun_l7_n705
+end
+
+def fun_l6_n240()
+ fun_l7_n342
+end
+
+def fun_l6_n241()
+ fun_l7_n461
+end
+
+def fun_l6_n242()
+ fun_l7_n215
+end
+
+def fun_l6_n243()
+ fun_l7_n74
+end
+
+def fun_l6_n244()
+ fun_l7_n715
+end
+
+def fun_l6_n245()
+ fun_l7_n317
+end
+
+def fun_l6_n246()
+ fun_l7_n238
+end
+
+def fun_l6_n247()
+ fun_l7_n899
+end
+
+def fun_l6_n248()
+ fun_l7_n360
+end
+
+def fun_l6_n249()
+ fun_l7_n753
+end
+
+def fun_l6_n250()
+ fun_l7_n722
+end
+
+def fun_l6_n251()
+ fun_l7_n649
+end
+
+def fun_l6_n252()
+ fun_l7_n640
+end
+
+def fun_l6_n253()
+ fun_l7_n146
+end
+
+def fun_l6_n254()
+ fun_l7_n385
+end
+
+def fun_l6_n255()
+ fun_l7_n483
+end
+
+def fun_l6_n256()
+ fun_l7_n142
+end
+
+def fun_l6_n257()
+ fun_l7_n815
+end
+
+def fun_l6_n258()
+ fun_l7_n499
+end
+
+def fun_l6_n259()
+ fun_l7_n827
+end
+
+def fun_l6_n260()
+ fun_l7_n799
+end
+
+def fun_l6_n261()
+ fun_l7_n633
+end
+
+def fun_l6_n262()
+ fun_l7_n399
+end
+
+def fun_l6_n263()
+ fun_l7_n123
+end
+
+def fun_l6_n264()
+ fun_l7_n94
+end
+
+def fun_l6_n265()
+ fun_l7_n799
+end
+
+def fun_l6_n266()
+ fun_l7_n884
+end
+
+def fun_l6_n267()
+ fun_l7_n983
+end
+
+def fun_l6_n268()
+ fun_l7_n880
+end
+
+def fun_l6_n269()
+ fun_l7_n58
+end
+
+def fun_l6_n270()
+ fun_l7_n181
+end
+
+def fun_l6_n271()
+ fun_l7_n241
+end
+
+def fun_l6_n272()
+ fun_l7_n971
+end
+
+def fun_l6_n273()
+ fun_l7_n297
+end
+
+def fun_l6_n274()
+ fun_l7_n435
+end
+
+def fun_l6_n275()
+ fun_l7_n57
+end
+
+def fun_l6_n276()
+ fun_l7_n665
+end
+
+def fun_l6_n277()
+ fun_l7_n725
+end
+
+def fun_l6_n278()
+ fun_l7_n258
+end
+
+def fun_l6_n279()
+ fun_l7_n680
+end
+
+def fun_l6_n280()
+ fun_l7_n969
+end
+
+def fun_l6_n281()
+ fun_l7_n714
+end
+
+def fun_l6_n282()
+ fun_l7_n166
+end
+
+def fun_l6_n283()
+ fun_l7_n876
+end
+
+def fun_l6_n284()
+ fun_l7_n893
+end
+
+def fun_l6_n285()
+ fun_l7_n530
+end
+
+def fun_l6_n286()
+ fun_l7_n552
+end
+
+def fun_l6_n287()
+ fun_l7_n212
+end
+
+def fun_l6_n288()
+ fun_l7_n194
+end
+
+def fun_l6_n289()
+ fun_l7_n375
+end
+
+def fun_l6_n290()
+ fun_l7_n726
+end
+
+def fun_l6_n291()
+ fun_l7_n498
+end
+
+def fun_l6_n292()
+ fun_l7_n630
+end
+
+def fun_l6_n293()
+ fun_l7_n781
+end
+
+def fun_l6_n294()
+ fun_l7_n122
+end
+
+def fun_l6_n295()
+ fun_l7_n864
+end
+
+def fun_l6_n296()
+ fun_l7_n931
+end
+
+def fun_l6_n297()
+ fun_l7_n561
+end
+
+def fun_l6_n298()
+ fun_l7_n891
+end
+
+def fun_l6_n299()
+ fun_l7_n149
+end
+
+def fun_l6_n300()
+ fun_l7_n697
+end
+
+def fun_l6_n301()
+ fun_l7_n152
+end
+
+def fun_l6_n302()
+ fun_l7_n973
+end
+
+def fun_l6_n303()
+ fun_l7_n32
+end
+
+def fun_l6_n304()
+ fun_l7_n254
+end
+
+def fun_l6_n305()
+ fun_l7_n68
+end
+
+def fun_l6_n306()
+ fun_l7_n46
+end
+
+def fun_l6_n307()
+ fun_l7_n2
+end
+
+def fun_l6_n308()
+ fun_l7_n862
+end
+
+def fun_l6_n309()
+ fun_l7_n722
+end
+
+def fun_l6_n310()
+ fun_l7_n501
+end
+
+def fun_l6_n311()
+ fun_l7_n779
+end
+
+def fun_l6_n312()
+ fun_l7_n899
+end
+
+def fun_l6_n313()
+ fun_l7_n209
+end
+
+def fun_l6_n314()
+ fun_l7_n445
+end
+
+def fun_l6_n315()
+ fun_l7_n882
+end
+
+def fun_l6_n316()
+ fun_l7_n825
+end
+
+def fun_l6_n317()
+ fun_l7_n52
+end
+
+def fun_l6_n318()
+ fun_l7_n813
+end
+
+def fun_l6_n319()
+ fun_l7_n103
+end
+
+def fun_l6_n320()
+ fun_l7_n480
+end
+
+def fun_l6_n321()
+ fun_l7_n357
+end
+
+def fun_l6_n322()
+ fun_l7_n138
+end
+
+def fun_l6_n323()
+ fun_l7_n277
+end
+
+def fun_l6_n324()
+ fun_l7_n287
+end
+
+def fun_l6_n325()
+ fun_l7_n822
+end
+
+def fun_l6_n326()
+ fun_l7_n299
+end
+
+def fun_l6_n327()
+ fun_l7_n617
+end
+
+def fun_l6_n328()
+ fun_l7_n618
+end
+
+def fun_l6_n329()
+ fun_l7_n721
+end
+
+def fun_l6_n330()
+ fun_l7_n600
+end
+
+def fun_l6_n331()
+ fun_l7_n349
+end
+
+def fun_l6_n332()
+ fun_l7_n978
+end
+
+def fun_l6_n333()
+ fun_l7_n889
+end
+
+def fun_l6_n334()
+ fun_l7_n129
+end
+
+def fun_l6_n335()
+ fun_l7_n404
+end
+
+def fun_l6_n336()
+ fun_l7_n169
+end
+
+def fun_l6_n337()
+ fun_l7_n498
+end
+
+def fun_l6_n338()
+ fun_l7_n428
+end
+
+def fun_l6_n339()
+ fun_l7_n910
+end
+
+def fun_l6_n340()
+ fun_l7_n441
+end
+
+def fun_l6_n341()
+ fun_l7_n649
+end
+
+def fun_l6_n342()
+ fun_l7_n251
+end
+
+def fun_l6_n343()
+ fun_l7_n146
+end
+
+def fun_l6_n344()
+ fun_l7_n979
+end
+
+def fun_l6_n345()
+ fun_l7_n561
+end
+
+def fun_l6_n346()
+ fun_l7_n667
+end
+
+def fun_l6_n347()
+ fun_l7_n50
+end
+
+def fun_l6_n348()
+ fun_l7_n324
+end
+
+def fun_l6_n349()
+ fun_l7_n60
+end
+
+def fun_l6_n350()
+ fun_l7_n292
+end
+
+def fun_l6_n351()
+ fun_l7_n227
+end
+
+def fun_l6_n352()
+ fun_l7_n99
+end
+
+def fun_l6_n353()
+ fun_l7_n124
+end
+
+def fun_l6_n354()
+ fun_l7_n519
+end
+
+def fun_l6_n355()
+ fun_l7_n245
+end
+
+def fun_l6_n356()
+ fun_l7_n438
+end
+
+def fun_l6_n357()
+ fun_l7_n916
+end
+
+def fun_l6_n358()
+ fun_l7_n865
+end
+
+def fun_l6_n359()
+ fun_l7_n886
+end
+
+def fun_l6_n360()
+ fun_l7_n432
+end
+
+def fun_l6_n361()
+ fun_l7_n406
+end
+
+def fun_l6_n362()
+ fun_l7_n709
+end
+
+def fun_l6_n363()
+ fun_l7_n271
+end
+
+def fun_l6_n364()
+ fun_l7_n320
+end
+
+def fun_l6_n365()
+ fun_l7_n3
+end
+
+def fun_l6_n366()
+ fun_l7_n831
+end
+
+def fun_l6_n367()
+ fun_l7_n417
+end
+
+def fun_l6_n368()
+ fun_l7_n949
+end
+
+def fun_l6_n369()
+ fun_l7_n941
+end
+
+def fun_l6_n370()
+ fun_l7_n404
+end
+
+def fun_l6_n371()
+ fun_l7_n715
+end
+
+def fun_l6_n372()
+ fun_l7_n223
+end
+
+def fun_l6_n373()
+ fun_l7_n813
+end
+
+def fun_l6_n374()
+ fun_l7_n594
+end
+
+def fun_l6_n375()
+ fun_l7_n949
+end
+
+def fun_l6_n376()
+ fun_l7_n107
+end
+
+def fun_l6_n377()
+ fun_l7_n951
+end
+
+def fun_l6_n378()
+ fun_l7_n940
+end
+
+def fun_l6_n379()
+ fun_l7_n224
+end
+
+def fun_l6_n380()
+ fun_l7_n82
+end
+
+def fun_l6_n381()
+ fun_l7_n815
+end
+
+def fun_l6_n382()
+ fun_l7_n443
+end
+
+def fun_l6_n383()
+ fun_l7_n566
+end
+
+def fun_l6_n384()
+ fun_l7_n954
+end
+
+def fun_l6_n385()
+ fun_l7_n562
+end
+
+def fun_l6_n386()
+ fun_l7_n9
+end
+
+def fun_l6_n387()
+ fun_l7_n233
+end
+
+def fun_l6_n388()
+ fun_l7_n510
+end
+
+def fun_l6_n389()
+ fun_l7_n616
+end
+
+def fun_l6_n390()
+ fun_l7_n991
+end
+
+def fun_l6_n391()
+ fun_l7_n184
+end
+
+def fun_l6_n392()
+ fun_l7_n288
+end
+
+def fun_l6_n393()
+ fun_l7_n282
+end
+
+def fun_l6_n394()
+ fun_l7_n81
+end
+
+def fun_l6_n395()
+ fun_l7_n567
+end
+
+def fun_l6_n396()
+ fun_l7_n465
+end
+
+def fun_l6_n397()
+ fun_l7_n856
+end
+
+def fun_l6_n398()
+ fun_l7_n268
+end
+
+def fun_l6_n399()
+ fun_l7_n695
+end
+
+def fun_l6_n400()
+ fun_l7_n403
+end
+
+def fun_l6_n401()
+ fun_l7_n153
+end
+
+def fun_l6_n402()
+ fun_l7_n321
+end
+
+def fun_l6_n403()
+ fun_l7_n233
+end
+
+def fun_l6_n404()
+ fun_l7_n218
+end
+
+def fun_l6_n405()
+ fun_l7_n285
+end
+
+def fun_l6_n406()
+ fun_l7_n829
+end
+
+def fun_l6_n407()
+ fun_l7_n218
+end
+
+def fun_l6_n408()
+ fun_l7_n457
+end
+
+def fun_l6_n409()
+ fun_l7_n513
+end
+
+def fun_l6_n410()
+ fun_l7_n677
+end
+
+def fun_l6_n411()
+ fun_l7_n849
+end
+
+def fun_l6_n412()
+ fun_l7_n579
+end
+
+def fun_l6_n413()
+ fun_l7_n160
+end
+
+def fun_l6_n414()
+ fun_l7_n567
+end
+
+def fun_l6_n415()
+ fun_l7_n394
+end
+
+def fun_l6_n416()
+ fun_l7_n480
+end
+
+def fun_l6_n417()
+ fun_l7_n234
+end
+
+def fun_l6_n418()
+ fun_l7_n410
+end
+
+def fun_l6_n419()
+ fun_l7_n405
+end
+
+def fun_l6_n420()
+ fun_l7_n497
+end
+
+def fun_l6_n421()
+ fun_l7_n242
+end
+
+def fun_l6_n422()
+ fun_l7_n190
+end
+
+def fun_l6_n423()
+ fun_l7_n513
+end
+
+def fun_l6_n424()
+ fun_l7_n790
+end
+
+def fun_l6_n425()
+ fun_l7_n112
+end
+
+def fun_l6_n426()
+ fun_l7_n792
+end
+
+def fun_l6_n427()
+ fun_l7_n209
+end
+
+def fun_l6_n428()
+ fun_l7_n451
+end
+
+def fun_l6_n429()
+ fun_l7_n897
+end
+
+def fun_l6_n430()
+ fun_l7_n884
+end
+
+def fun_l6_n431()
+ fun_l7_n81
+end
+
+def fun_l6_n432()
+ fun_l7_n764
+end
+
+def fun_l6_n433()
+ fun_l7_n204
+end
+
+def fun_l6_n434()
+ fun_l7_n56
+end
+
+def fun_l6_n435()
+ fun_l7_n394
+end
+
+def fun_l6_n436()
+ fun_l7_n903
+end
+
+def fun_l6_n437()
+ fun_l7_n423
+end
+
+def fun_l6_n438()
+ fun_l7_n899
+end
+
+def fun_l6_n439()
+ fun_l7_n40
+end
+
+def fun_l6_n440()
+ fun_l7_n145
+end
+
+def fun_l6_n441()
+ fun_l7_n811
+end
+
+def fun_l6_n442()
+ fun_l7_n821
+end
+
+def fun_l6_n443()
+ fun_l7_n675
+end
+
+def fun_l6_n444()
+ fun_l7_n665
+end
+
+def fun_l6_n445()
+ fun_l7_n1
+end
+
+def fun_l6_n446()
+ fun_l7_n936
+end
+
+def fun_l6_n447()
+ fun_l7_n838
+end
+
+def fun_l6_n448()
+ fun_l7_n820
+end
+
+def fun_l6_n449()
+ fun_l7_n206
+end
+
+def fun_l6_n450()
+ fun_l7_n234
+end
+
+def fun_l6_n451()
+ fun_l7_n150
+end
+
+def fun_l6_n452()
+ fun_l7_n699
+end
+
+def fun_l6_n453()
+ fun_l7_n369
+end
+
+def fun_l6_n454()
+ fun_l7_n759
+end
+
+def fun_l6_n455()
+ fun_l7_n836
+end
+
+def fun_l6_n456()
+ fun_l7_n55
+end
+
+def fun_l6_n457()
+ fun_l7_n457
+end
+
+def fun_l6_n458()
+ fun_l7_n623
+end
+
+def fun_l6_n459()
+ fun_l7_n679
+end
+
+def fun_l6_n460()
+ fun_l7_n199
+end
+
+def fun_l6_n461()
+ fun_l7_n738
+end
+
+def fun_l6_n462()
+ fun_l7_n479
+end
+
+def fun_l6_n463()
+ fun_l7_n673
+end
+
+def fun_l6_n464()
+ fun_l7_n323
+end
+
+def fun_l6_n465()
+ fun_l7_n652
+end
+
+def fun_l6_n466()
+ fun_l7_n470
+end
+
+def fun_l6_n467()
+ fun_l7_n133
+end
+
+def fun_l6_n468()
+ fun_l7_n179
+end
+
+def fun_l6_n469()
+ fun_l7_n647
+end
+
+def fun_l6_n470()
+ fun_l7_n869
+end
+
+def fun_l6_n471()
+ fun_l7_n553
+end
+
+def fun_l6_n472()
+ fun_l7_n173
+end
+
+def fun_l6_n473()
+ fun_l7_n188
+end
+
+def fun_l6_n474()
+ fun_l7_n530
+end
+
+def fun_l6_n475()
+ fun_l7_n233
+end
+
+def fun_l6_n476()
+ fun_l7_n46
+end
+
+def fun_l6_n477()
+ fun_l7_n892
+end
+
+def fun_l6_n478()
+ fun_l7_n879
+end
+
+def fun_l6_n479()
+ fun_l7_n507
+end
+
+def fun_l6_n480()
+ fun_l7_n383
+end
+
+def fun_l6_n481()
+ fun_l7_n500
+end
+
+def fun_l6_n482()
+ fun_l7_n595
+end
+
+def fun_l6_n483()
+ fun_l7_n225
+end
+
+def fun_l6_n484()
+ fun_l7_n396
+end
+
+def fun_l6_n485()
+ fun_l7_n61
+end
+
+def fun_l6_n486()
+ fun_l7_n953
+end
+
+def fun_l6_n487()
+ fun_l7_n891
+end
+
+def fun_l6_n488()
+ fun_l7_n620
+end
+
+def fun_l6_n489()
+ fun_l7_n672
+end
+
+def fun_l6_n490()
+ fun_l7_n824
+end
+
+def fun_l6_n491()
+ fun_l7_n216
+end
+
+def fun_l6_n492()
+ fun_l7_n404
+end
+
+def fun_l6_n493()
+ fun_l7_n428
+end
+
+def fun_l6_n494()
+ fun_l7_n907
+end
+
+def fun_l6_n495()
+ fun_l7_n297
+end
+
+def fun_l6_n496()
+ fun_l7_n349
+end
+
+def fun_l6_n497()
+ fun_l7_n291
+end
+
+def fun_l6_n498()
+ fun_l7_n642
+end
+
+def fun_l6_n499()
+ fun_l7_n906
+end
+
+def fun_l6_n500()
+ fun_l7_n78
+end
+
+def fun_l6_n501()
+ fun_l7_n568
+end
+
+def fun_l6_n502()
+ fun_l7_n591
+end
+
+def fun_l6_n503()
+ fun_l7_n921
+end
+
+def fun_l6_n504()
+ fun_l7_n832
+end
+
+def fun_l6_n505()
+ fun_l7_n826
+end
+
+def fun_l6_n506()
+ fun_l7_n930
+end
+
+def fun_l6_n507()
+ fun_l7_n791
+end
+
+def fun_l6_n508()
+ fun_l7_n608
+end
+
+def fun_l6_n509()
+ fun_l7_n144
+end
+
+def fun_l6_n510()
+ fun_l7_n202
+end
+
+def fun_l6_n511()
+ fun_l7_n379
+end
+
+def fun_l6_n512()
+ fun_l7_n354
+end
+
+def fun_l6_n513()
+ fun_l7_n245
+end
+
+def fun_l6_n514()
+ fun_l7_n402
+end
+
+def fun_l6_n515()
+ fun_l7_n875
+end
+
+def fun_l6_n516()
+ fun_l7_n847
+end
+
+def fun_l6_n517()
+ fun_l7_n736
+end
+
+def fun_l6_n518()
+ fun_l7_n325
+end
+
+def fun_l6_n519()
+ fun_l7_n949
+end
+
+def fun_l6_n520()
+ fun_l7_n993
+end
+
+def fun_l6_n521()
+ fun_l7_n271
+end
+
+def fun_l6_n522()
+ fun_l7_n799
+end
+
+def fun_l6_n523()
+ fun_l7_n861
+end
+
+def fun_l6_n524()
+ fun_l7_n164
+end
+
+def fun_l6_n525()
+ fun_l7_n293
+end
+
+def fun_l6_n526()
+ fun_l7_n948
+end
+
+def fun_l6_n527()
+ fun_l7_n682
+end
+
+def fun_l6_n528()
+ fun_l7_n914
+end
+
+def fun_l6_n529()
+ fun_l7_n395
+end
+
+def fun_l6_n530()
+ fun_l7_n399
+end
+
+def fun_l6_n531()
+ fun_l7_n220
+end
+
+def fun_l6_n532()
+ fun_l7_n874
+end
+
+def fun_l6_n533()
+ fun_l7_n504
+end
+
+def fun_l6_n534()
+ fun_l7_n713
+end
+
+def fun_l6_n535()
+ fun_l7_n185
+end
+
+def fun_l6_n536()
+ fun_l7_n229
+end
+
+def fun_l6_n537()
+ fun_l7_n696
+end
+
+def fun_l6_n538()
+ fun_l7_n840
+end
+
+def fun_l6_n539()
+ fun_l7_n323
+end
+
+def fun_l6_n540()
+ fun_l7_n342
+end
+
+def fun_l6_n541()
+ fun_l7_n60
+end
+
+def fun_l6_n542()
+ fun_l7_n149
+end
+
+def fun_l6_n543()
+ fun_l7_n465
+end
+
+def fun_l6_n544()
+ fun_l7_n392
+end
+
+def fun_l6_n545()
+ fun_l7_n210
+end
+
+def fun_l6_n546()
+ fun_l7_n565
+end
+
+def fun_l6_n547()
+ fun_l7_n63
+end
+
+def fun_l6_n548()
+ fun_l7_n722
+end
+
+def fun_l6_n549()
+ fun_l7_n119
+end
+
+def fun_l6_n550()
+ fun_l7_n933
+end
+
+def fun_l6_n551()
+ fun_l7_n612
+end
+
+def fun_l6_n552()
+ fun_l7_n479
+end
+
+def fun_l6_n553()
+ fun_l7_n866
+end
+
+def fun_l6_n554()
+ fun_l7_n268
+end
+
+def fun_l6_n555()
+ fun_l7_n547
+end
+
+def fun_l6_n556()
+ fun_l7_n621
+end
+
+def fun_l6_n557()
+ fun_l7_n461
+end
+
+def fun_l6_n558()
+ fun_l7_n907
+end
+
+def fun_l6_n559()
+ fun_l7_n660
+end
+
+def fun_l6_n560()
+ fun_l7_n857
+end
+
+def fun_l6_n561()
+ fun_l7_n398
+end
+
+def fun_l6_n562()
+ fun_l7_n484
+end
+
+def fun_l6_n563()
+ fun_l7_n16
+end
+
+def fun_l6_n564()
+ fun_l7_n697
+end
+
+def fun_l6_n565()
+ fun_l7_n135
+end
+
+def fun_l6_n566()
+ fun_l7_n265
+end
+
+def fun_l6_n567()
+ fun_l7_n627
+end
+
+def fun_l6_n568()
+ fun_l7_n345
+end
+
+def fun_l6_n569()
+ fun_l7_n528
+end
+
+def fun_l6_n570()
+ fun_l7_n926
+end
+
+def fun_l6_n571()
+ fun_l7_n198
+end
+
+def fun_l6_n572()
+ fun_l7_n837
+end
+
+def fun_l6_n573()
+ fun_l7_n95
+end
+
+def fun_l6_n574()
+ fun_l7_n802
+end
+
+def fun_l6_n575()
+ fun_l7_n265
+end
+
+def fun_l6_n576()
+ fun_l7_n884
+end
+
+def fun_l6_n577()
+ fun_l7_n227
+end
+
+def fun_l6_n578()
+ fun_l7_n915
+end
+
+def fun_l6_n579()
+ fun_l7_n221
+end
+
+def fun_l6_n580()
+ fun_l7_n718
+end
+
+def fun_l6_n581()
+ fun_l7_n179
+end
+
+def fun_l6_n582()
+ fun_l7_n975
+end
+
+def fun_l6_n583()
+ fun_l7_n207
+end
+
+def fun_l6_n584()
+ fun_l7_n874
+end
+
+def fun_l6_n585()
+ fun_l7_n540
+end
+
+def fun_l6_n586()
+ fun_l7_n765
+end
+
+def fun_l6_n587()
+ fun_l7_n613
+end
+
+def fun_l6_n588()
+ fun_l7_n853
+end
+
+def fun_l6_n589()
+ fun_l7_n241
+end
+
+def fun_l6_n590()
+ fun_l7_n91
+end
+
+def fun_l6_n591()
+ fun_l7_n383
+end
+
+def fun_l6_n592()
+ fun_l7_n567
+end
+
+def fun_l6_n593()
+ fun_l7_n144
+end
+
+def fun_l6_n594()
+ fun_l7_n663
+end
+
+def fun_l6_n595()
+ fun_l7_n674
+end
+
+def fun_l6_n596()
+ fun_l7_n407
+end
+
+def fun_l6_n597()
+ fun_l7_n207
+end
+
+def fun_l6_n598()
+ fun_l7_n746
+end
+
+def fun_l6_n599()
+ fun_l7_n24
+end
+
+def fun_l6_n600()
+ fun_l7_n150
+end
+
+def fun_l6_n601()
+ fun_l7_n317
+end
+
+def fun_l6_n602()
+ fun_l7_n773
+end
+
+def fun_l6_n603()
+ fun_l7_n932
+end
+
+def fun_l6_n604()
+ fun_l7_n772
+end
+
+def fun_l6_n605()
+ fun_l7_n495
+end
+
+def fun_l6_n606()
+ fun_l7_n526
+end
+
+def fun_l6_n607()
+ fun_l7_n758
+end
+
+def fun_l6_n608()
+ fun_l7_n941
+end
+
+def fun_l6_n609()
+ fun_l7_n998
+end
+
+def fun_l6_n610()
+ fun_l7_n543
+end
+
+def fun_l6_n611()
+ fun_l7_n216
+end
+
+def fun_l6_n612()
+ fun_l7_n445
+end
+
+def fun_l6_n613()
+ fun_l7_n314
+end
+
+def fun_l6_n614()
+ fun_l7_n840
+end
+
+def fun_l6_n615()
+ fun_l7_n722
+end
+
+def fun_l6_n616()
+ fun_l7_n89
+end
+
+def fun_l6_n617()
+ fun_l7_n353
+end
+
+def fun_l6_n618()
+ fun_l7_n800
+end
+
+def fun_l6_n619()
+ fun_l7_n736
+end
+
+def fun_l6_n620()
+ fun_l7_n376
+end
+
+def fun_l6_n621()
+ fun_l7_n24
+end
+
+def fun_l6_n622()
+ fun_l7_n258
+end
+
+def fun_l6_n623()
+ fun_l7_n943
+end
+
+def fun_l6_n624()
+ fun_l7_n963
+end
+
+def fun_l6_n625()
+ fun_l7_n709
+end
+
+def fun_l6_n626()
+ fun_l7_n350
+end
+
+def fun_l6_n627()
+ fun_l7_n322
+end
+
+def fun_l6_n628()
+ fun_l7_n717
+end
+
+def fun_l6_n629()
+ fun_l7_n529
+end
+
+def fun_l6_n630()
+ fun_l7_n365
+end
+
+def fun_l6_n631()
+ fun_l7_n977
+end
+
+def fun_l6_n632()
+ fun_l7_n606
+end
+
+def fun_l6_n633()
+ fun_l7_n712
+end
+
+def fun_l6_n634()
+ fun_l7_n559
+end
+
+def fun_l6_n635()
+ fun_l7_n499
+end
+
+def fun_l6_n636()
+ fun_l7_n871
+end
+
+def fun_l6_n637()
+ fun_l7_n684
+end
+
+def fun_l6_n638()
+ fun_l7_n558
+end
+
+def fun_l6_n639()
+ fun_l7_n333
+end
+
+def fun_l6_n640()
+ fun_l7_n37
+end
+
+def fun_l6_n641()
+ fun_l7_n559
+end
+
+def fun_l6_n642()
+ fun_l7_n17
+end
+
+def fun_l6_n643()
+ fun_l7_n913
+end
+
+def fun_l6_n644()
+ fun_l7_n79
+end
+
+def fun_l6_n645()
+ fun_l7_n402
+end
+
+def fun_l6_n646()
+ fun_l7_n268
+end
+
+def fun_l6_n647()
+ fun_l7_n797
+end
+
+def fun_l6_n648()
+ fun_l7_n985
+end
+
+def fun_l6_n649()
+ fun_l7_n192
+end
+
+def fun_l6_n650()
+ fun_l7_n774
+end
+
+def fun_l6_n651()
+ fun_l7_n805
+end
+
+def fun_l6_n652()
+ fun_l7_n208
+end
+
+def fun_l6_n653()
+ fun_l7_n608
+end
+
+def fun_l6_n654()
+ fun_l7_n714
+end
+
+def fun_l6_n655()
+ fun_l7_n883
+end
+
+def fun_l6_n656()
+ fun_l7_n841
+end
+
+def fun_l6_n657()
+ fun_l7_n646
+end
+
+def fun_l6_n658()
+ fun_l7_n39
+end
+
+def fun_l6_n659()
+ fun_l7_n432
+end
+
+def fun_l6_n660()
+ fun_l7_n177
+end
+
+def fun_l6_n661()
+ fun_l7_n700
+end
+
+def fun_l6_n662()
+ fun_l7_n815
+end
+
+def fun_l6_n663()
+ fun_l7_n553
+end
+
+def fun_l6_n664()
+ fun_l7_n540
+end
+
+def fun_l6_n665()
+ fun_l7_n853
+end
+
+def fun_l6_n666()
+ fun_l7_n526
+end
+
+def fun_l6_n667()
+ fun_l7_n670
+end
+
+def fun_l6_n668()
+ fun_l7_n753
+end
+
+def fun_l6_n669()
+ fun_l7_n811
+end
+
+def fun_l6_n670()
+ fun_l7_n782
+end
+
+def fun_l6_n671()
+ fun_l7_n275
+end
+
+def fun_l6_n672()
+ fun_l7_n884
+end
+
+def fun_l6_n673()
+ fun_l7_n984
+end
+
+def fun_l6_n674()
+ fun_l7_n980
+end
+
+def fun_l6_n675()
+ fun_l7_n341
+end
+
+def fun_l6_n676()
+ fun_l7_n346
+end
+
+def fun_l6_n677()
+ fun_l7_n164
+end
+
+def fun_l6_n678()
+ fun_l7_n600
+end
+
+def fun_l6_n679()
+ fun_l7_n351
+end
+
+def fun_l6_n680()
+ fun_l7_n527
+end
+
+def fun_l6_n681()
+ fun_l7_n206
+end
+
+def fun_l6_n682()
+ fun_l7_n50
+end
+
+def fun_l6_n683()
+ fun_l7_n476
+end
+
+def fun_l6_n684()
+ fun_l7_n684
+end
+
+def fun_l6_n685()
+ fun_l7_n883
+end
+
+def fun_l6_n686()
+ fun_l7_n41
+end
+
+def fun_l6_n687()
+ fun_l7_n382
+end
+
+def fun_l6_n688()
+ fun_l7_n418
+end
+
+def fun_l6_n689()
+ fun_l7_n22
+end
+
+def fun_l6_n690()
+ fun_l7_n543
+end
+
+def fun_l6_n691()
+ fun_l7_n143
+end
+
+def fun_l6_n692()
+ fun_l7_n120
+end
+
+def fun_l6_n693()
+ fun_l7_n431
+end
+
+def fun_l6_n694()
+ fun_l7_n405
+end
+
+def fun_l6_n695()
+ fun_l7_n474
+end
+
+def fun_l6_n696()
+ fun_l7_n117
+end
+
+def fun_l6_n697()
+ fun_l7_n475
+end
+
+def fun_l6_n698()
+ fun_l7_n674
+end
+
+def fun_l6_n699()
+ fun_l7_n398
+end
+
+def fun_l6_n700()
+ fun_l7_n709
+end
+
+def fun_l6_n701()
+ fun_l7_n360
+end
+
+def fun_l6_n702()
+ fun_l7_n241
+end
+
+def fun_l6_n703()
+ fun_l7_n837
+end
+
+def fun_l6_n704()
+ fun_l7_n483
+end
+
+def fun_l6_n705()
+ fun_l7_n943
+end
+
+def fun_l6_n706()
+ fun_l7_n292
+end
+
+def fun_l6_n707()
+ fun_l7_n659
+end
+
+def fun_l6_n708()
+ fun_l7_n657
+end
+
+def fun_l6_n709()
+ fun_l7_n143
+end
+
+def fun_l6_n710()
+ fun_l7_n883
+end
+
+def fun_l6_n711()
+ fun_l7_n764
+end
+
+def fun_l6_n712()
+ fun_l7_n421
+end
+
+def fun_l6_n713()
+ fun_l7_n611
+end
+
+def fun_l6_n714()
+ fun_l7_n657
+end
+
+def fun_l6_n715()
+ fun_l7_n765
+end
+
+def fun_l6_n716()
+ fun_l7_n793
+end
+
+def fun_l6_n717()
+ fun_l7_n752
+end
+
+def fun_l6_n718()
+ fun_l7_n713
+end
+
+def fun_l6_n719()
+ fun_l7_n577
+end
+
+def fun_l6_n720()
+ fun_l7_n422
+end
+
+def fun_l6_n721()
+ fun_l7_n368
+end
+
+def fun_l6_n722()
+ fun_l7_n2
+end
+
+def fun_l6_n723()
+ fun_l7_n739
+end
+
+def fun_l6_n724()
+ fun_l7_n481
+end
+
+def fun_l6_n725()
+ fun_l7_n516
+end
+
+def fun_l6_n726()
+ fun_l7_n266
+end
+
+def fun_l6_n727()
+ fun_l7_n269
+end
+
+def fun_l6_n728()
+ fun_l7_n308
+end
+
+def fun_l6_n729()
+ fun_l7_n915
+end
+
+def fun_l6_n730()
+ fun_l7_n603
+end
+
+def fun_l6_n731()
+ fun_l7_n585
+end
+
+def fun_l6_n732()
+ fun_l7_n182
+end
+
+def fun_l6_n733()
+ fun_l7_n28
+end
+
+def fun_l6_n734()
+ fun_l7_n829
+end
+
+def fun_l6_n735()
+ fun_l7_n365
+end
+
+def fun_l6_n736()
+ fun_l7_n208
+end
+
+def fun_l6_n737()
+ fun_l7_n395
+end
+
+def fun_l6_n738()
+ fun_l7_n745
+end
+
+def fun_l6_n739()
+ fun_l7_n90
+end
+
+def fun_l6_n740()
+ fun_l7_n696
+end
+
+def fun_l6_n741()
+ fun_l7_n730
+end
+
+def fun_l6_n742()
+ fun_l7_n143
+end
+
+def fun_l6_n743()
+ fun_l7_n753
+end
+
+def fun_l6_n744()
+ fun_l7_n484
+end
+
+def fun_l6_n745()
+ fun_l7_n779
+end
+
+def fun_l6_n746()
+ fun_l7_n668
+end
+
+def fun_l6_n747()
+ fun_l7_n331
+end
+
+def fun_l6_n748()
+ fun_l7_n961
+end
+
+def fun_l6_n749()
+ fun_l7_n875
+end
+
+def fun_l6_n750()
+ fun_l7_n541
+end
+
+def fun_l6_n751()
+ fun_l7_n122
+end
+
+def fun_l6_n752()
+ fun_l7_n278
+end
+
+def fun_l6_n753()
+ fun_l7_n510
+end
+
+def fun_l6_n754()
+ fun_l7_n619
+end
+
+def fun_l6_n755()
+ fun_l7_n165
+end
+
+def fun_l6_n756()
+ fun_l7_n537
+end
+
+def fun_l6_n757()
+ fun_l7_n917
+end
+
+def fun_l6_n758()
+ fun_l7_n102
+end
+
+def fun_l6_n759()
+ fun_l7_n504
+end
+
+def fun_l6_n760()
+ fun_l7_n768
+end
+
+def fun_l6_n761()
+ fun_l7_n259
+end
+
+def fun_l6_n762()
+ fun_l7_n371
+end
+
+def fun_l6_n763()
+ fun_l7_n727
+end
+
+def fun_l6_n764()
+ fun_l7_n959
+end
+
+def fun_l6_n765()
+ fun_l7_n191
+end
+
+def fun_l6_n766()
+ fun_l7_n570
+end
+
+def fun_l6_n767()
+ fun_l7_n746
+end
+
+def fun_l6_n768()
+ fun_l7_n133
+end
+
+def fun_l6_n769()
+ fun_l7_n520
+end
+
+def fun_l6_n770()
+ fun_l7_n602
+end
+
+def fun_l6_n771()
+ fun_l7_n722
+end
+
+def fun_l6_n772()
+ fun_l7_n165
+end
+
+def fun_l6_n773()
+ fun_l7_n132
+end
+
+def fun_l6_n774()
+ fun_l7_n328
+end
+
+def fun_l6_n775()
+ fun_l7_n88
+end
+
+def fun_l6_n776()
+ fun_l7_n296
+end
+
+def fun_l6_n777()
+ fun_l7_n389
+end
+
+def fun_l6_n778()
+ fun_l7_n433
+end
+
+def fun_l6_n779()
+ fun_l7_n525
+end
+
+def fun_l6_n780()
+ fun_l7_n736
+end
+
+def fun_l6_n781()
+ fun_l7_n300
+end
+
+def fun_l6_n782()
+ fun_l7_n663
+end
+
+def fun_l6_n783()
+ fun_l7_n33
+end
+
+def fun_l6_n784()
+ fun_l7_n964
+end
+
+def fun_l6_n785()
+ fun_l7_n459
+end
+
+def fun_l6_n786()
+ fun_l7_n397
+end
+
+def fun_l6_n787()
+ fun_l7_n453
+end
+
+def fun_l6_n788()
+ fun_l7_n951
+end
+
+def fun_l6_n789()
+ fun_l7_n485
+end
+
+def fun_l6_n790()
+ fun_l7_n480
+end
+
+def fun_l6_n791()
+ fun_l7_n663
+end
+
+def fun_l6_n792()
+ fun_l7_n245
+end
+
+def fun_l6_n793()
+ fun_l7_n933
+end
+
+def fun_l6_n794()
+ fun_l7_n253
+end
+
+def fun_l6_n795()
+ fun_l7_n746
+end
+
+def fun_l6_n796()
+ fun_l7_n242
+end
+
+def fun_l6_n797()
+ fun_l7_n435
+end
+
+def fun_l6_n798()
+ fun_l7_n982
+end
+
+def fun_l6_n799()
+ fun_l7_n516
+end
+
+def fun_l6_n800()
+ fun_l7_n118
+end
+
+def fun_l6_n801()
+ fun_l7_n787
+end
+
+def fun_l6_n802()
+ fun_l7_n13
+end
+
+def fun_l6_n803()
+ fun_l7_n381
+end
+
+def fun_l6_n804()
+ fun_l7_n601
+end
+
+def fun_l6_n805()
+ fun_l7_n95
+end
+
+def fun_l6_n806()
+ fun_l7_n589
+end
+
+def fun_l6_n807()
+ fun_l7_n33
+end
+
+def fun_l6_n808()
+ fun_l7_n801
+end
+
+def fun_l6_n809()
+ fun_l7_n857
+end
+
+def fun_l6_n810()
+ fun_l7_n23
+end
+
+def fun_l6_n811()
+ fun_l7_n998
+end
+
+def fun_l6_n812()
+ fun_l7_n424
+end
+
+def fun_l6_n813()
+ fun_l7_n525
+end
+
+def fun_l6_n814()
+ fun_l7_n428
+end
+
+def fun_l6_n815()
+ fun_l7_n509
+end
+
+def fun_l6_n816()
+ fun_l7_n599
+end
+
+def fun_l6_n817()
+ fun_l7_n642
+end
+
+def fun_l6_n818()
+ fun_l7_n381
+end
+
+def fun_l6_n819()
+ fun_l7_n802
+end
+
+def fun_l6_n820()
+ fun_l7_n324
+end
+
+def fun_l6_n821()
+ fun_l7_n804
+end
+
+def fun_l6_n822()
+ fun_l7_n743
+end
+
+def fun_l6_n823()
+ fun_l7_n961
+end
+
+def fun_l6_n824()
+ fun_l7_n222
+end
+
+def fun_l6_n825()
+ fun_l7_n184
+end
+
+def fun_l6_n826()
+ fun_l7_n157
+end
+
+def fun_l6_n827()
+ fun_l7_n387
+end
+
+def fun_l6_n828()
+ fun_l7_n963
+end
+
+def fun_l6_n829()
+ fun_l7_n817
+end
+
+def fun_l6_n830()
+ fun_l7_n673
+end
+
+def fun_l6_n831()
+ fun_l7_n471
+end
+
+def fun_l6_n832()
+ fun_l7_n662
+end
+
+def fun_l6_n833()
+ fun_l7_n385
+end
+
+def fun_l6_n834()
+ fun_l7_n802
+end
+
+def fun_l6_n835()
+ fun_l7_n827
+end
+
+def fun_l6_n836()
+ fun_l7_n495
+end
+
+def fun_l6_n837()
+ fun_l7_n44
+end
+
+def fun_l6_n838()
+ fun_l7_n958
+end
+
+def fun_l6_n839()
+ fun_l7_n436
+end
+
+def fun_l6_n840()
+ fun_l7_n210
+end
+
+def fun_l6_n841()
+ fun_l7_n14
+end
+
+def fun_l6_n842()
+ fun_l7_n67
+end
+
+def fun_l6_n843()
+ fun_l7_n0
+end
+
+def fun_l6_n844()
+ fun_l7_n50
+end
+
+def fun_l6_n845()
+ fun_l7_n398
+end
+
+def fun_l6_n846()
+ fun_l7_n269
+end
+
+def fun_l6_n847()
+ fun_l7_n478
+end
+
+def fun_l6_n848()
+ fun_l7_n879
+end
+
+def fun_l6_n849()
+ fun_l7_n713
+end
+
+def fun_l6_n850()
+ fun_l7_n496
+end
+
+def fun_l6_n851()
+ fun_l7_n995
+end
+
+def fun_l6_n852()
+ fun_l7_n973
+end
+
+def fun_l6_n853()
+ fun_l7_n990
+end
+
+def fun_l6_n854()
+ fun_l7_n193
+end
+
+def fun_l6_n855()
+ fun_l7_n200
+end
+
+def fun_l6_n856()
+ fun_l7_n377
+end
+
+def fun_l6_n857()
+ fun_l7_n82
+end
+
+def fun_l6_n858()
+ fun_l7_n261
+end
+
+def fun_l6_n859()
+ fun_l7_n464
+end
+
+def fun_l6_n860()
+ fun_l7_n358
+end
+
+def fun_l6_n861()
+ fun_l7_n920
+end
+
+def fun_l6_n862()
+ fun_l7_n724
+end
+
+def fun_l6_n863()
+ fun_l7_n536
+end
+
+def fun_l6_n864()
+ fun_l7_n127
+end
+
+def fun_l6_n865()
+ fun_l7_n919
+end
+
+def fun_l6_n866()
+ fun_l7_n972
+end
+
+def fun_l6_n867()
+ fun_l7_n773
+end
+
+def fun_l6_n868()
+ fun_l7_n444
+end
+
+def fun_l6_n869()
+ fun_l7_n242
+end
+
+def fun_l6_n870()
+ fun_l7_n910
+end
+
+def fun_l6_n871()
+ fun_l7_n396
+end
+
+def fun_l6_n872()
+ fun_l7_n110
+end
+
+def fun_l6_n873()
+ fun_l7_n393
+end
+
+def fun_l6_n874()
+ fun_l7_n295
+end
+
+def fun_l6_n875()
+ fun_l7_n998
+end
+
+def fun_l6_n876()
+ fun_l7_n357
+end
+
+def fun_l6_n877()
+ fun_l7_n586
+end
+
+def fun_l6_n878()
+ fun_l7_n752
+end
+
+def fun_l6_n879()
+ fun_l7_n998
+end
+
+def fun_l6_n880()
+ fun_l7_n33
+end
+
+def fun_l6_n881()
+ fun_l7_n472
+end
+
+def fun_l6_n882()
+ fun_l7_n511
+end
+
+def fun_l6_n883()
+ fun_l7_n677
+end
+
+def fun_l6_n884()
+ fun_l7_n562
+end
+
+def fun_l6_n885()
+ fun_l7_n100
+end
+
+def fun_l6_n886()
+ fun_l7_n964
+end
+
+def fun_l6_n887()
+ fun_l7_n306
+end
+
+def fun_l6_n888()
+ fun_l7_n295
+end
+
+def fun_l6_n889()
+ fun_l7_n323
+end
+
+def fun_l6_n890()
+ fun_l7_n559
+end
+
+def fun_l6_n891()
+ fun_l7_n872
+end
+
+def fun_l6_n892()
+ fun_l7_n236
+end
+
+def fun_l6_n893()
+ fun_l7_n845
+end
+
+def fun_l6_n894()
+ fun_l7_n853
+end
+
+def fun_l6_n895()
+ fun_l7_n333
+end
+
+def fun_l6_n896()
+ fun_l7_n404
+end
+
+def fun_l6_n897()
+ fun_l7_n17
+end
+
+def fun_l6_n898()
+ fun_l7_n997
+end
+
+def fun_l6_n899()
+ fun_l7_n844
+end
+
+def fun_l6_n900()
+ fun_l7_n327
+end
+
+def fun_l6_n901()
+ fun_l7_n863
+end
+
+def fun_l6_n902()
+ fun_l7_n516
+end
+
+def fun_l6_n903()
+ fun_l7_n298
+end
+
+def fun_l6_n904()
+ fun_l7_n171
+end
+
+def fun_l6_n905()
+ fun_l7_n908
+end
+
+def fun_l6_n906()
+ fun_l7_n934
+end
+
+def fun_l6_n907()
+ fun_l7_n361
+end
+
+def fun_l6_n908()
+ fun_l7_n901
+end
+
+def fun_l6_n909()
+ fun_l7_n830
+end
+
+def fun_l6_n910()
+ fun_l7_n313
+end
+
+def fun_l6_n911()
+ fun_l7_n799
+end
+
+def fun_l6_n912()
+ fun_l7_n223
+end
+
+def fun_l6_n913()
+ fun_l7_n108
+end
+
+def fun_l6_n914()
+ fun_l7_n822
+end
+
+def fun_l6_n915()
+ fun_l7_n42
+end
+
+def fun_l6_n916()
+ fun_l7_n276
+end
+
+def fun_l6_n917()
+ fun_l7_n535
+end
+
+def fun_l6_n918()
+ fun_l7_n586
+end
+
+def fun_l6_n919()
+ fun_l7_n847
+end
+
+def fun_l6_n920()
+ fun_l7_n851
+end
+
+def fun_l6_n921()
+ fun_l7_n544
+end
+
+def fun_l6_n922()
+ fun_l7_n416
+end
+
+def fun_l6_n923()
+ fun_l7_n670
+end
+
+def fun_l6_n924()
+ fun_l7_n366
+end
+
+def fun_l6_n925()
+ fun_l7_n94
+end
+
+def fun_l6_n926()
+ fun_l7_n187
+end
+
+def fun_l6_n927()
+ fun_l7_n72
+end
+
+def fun_l6_n928()
+ fun_l7_n19
+end
+
+def fun_l6_n929()
+ fun_l7_n424
+end
+
+def fun_l6_n930()
+ fun_l7_n833
+end
+
+def fun_l6_n931()
+ fun_l7_n438
+end
+
+def fun_l6_n932()
+ fun_l7_n9
+end
+
+def fun_l6_n933()
+ fun_l7_n967
+end
+
+def fun_l6_n934()
+ fun_l7_n155
+end
+
+def fun_l6_n935()
+ fun_l7_n119
+end
+
+def fun_l6_n936()
+ fun_l7_n916
+end
+
+def fun_l6_n937()
+ fun_l7_n232
+end
+
+def fun_l6_n938()
+ fun_l7_n880
+end
+
+def fun_l6_n939()
+ fun_l7_n456
+end
+
+def fun_l6_n940()
+ fun_l7_n764
+end
+
+def fun_l6_n941()
+ fun_l7_n525
+end
+
+def fun_l6_n942()
+ fun_l7_n794
+end
+
+def fun_l6_n943()
+ fun_l7_n887
+end
+
+def fun_l6_n944()
+ fun_l7_n756
+end
+
+def fun_l6_n945()
+ fun_l7_n863
+end
+
+def fun_l6_n946()
+ fun_l7_n959
+end
+
+def fun_l6_n947()
+ fun_l7_n597
+end
+
+def fun_l6_n948()
+ fun_l7_n919
+end
+
+def fun_l6_n949()
+ fun_l7_n196
+end
+
+def fun_l6_n950()
+ fun_l7_n505
+end
+
+def fun_l6_n951()
+ fun_l7_n374
+end
+
+def fun_l6_n952()
+ fun_l7_n272
+end
+
+def fun_l6_n953()
+ fun_l7_n317
+end
+
+def fun_l6_n954()
+ fun_l7_n149
+end
+
+def fun_l6_n955()
+ fun_l7_n885
+end
+
+def fun_l6_n956()
+ fun_l7_n174
+end
+
+def fun_l6_n957()
+ fun_l7_n234
+end
+
+def fun_l6_n958()
+ fun_l7_n848
+end
+
+def fun_l6_n959()
+ fun_l7_n18
+end
+
+def fun_l6_n960()
+ fun_l7_n111
+end
+
+def fun_l6_n961()
+ fun_l7_n355
+end
+
+def fun_l6_n962()
+ fun_l7_n640
+end
+
+def fun_l6_n963()
+ fun_l7_n486
+end
+
+def fun_l6_n964()
+ fun_l7_n940
+end
+
+def fun_l6_n965()
+ fun_l7_n54
+end
+
+def fun_l6_n966()
+ fun_l7_n970
+end
+
+def fun_l6_n967()
+ fun_l7_n127
+end
+
+def fun_l6_n968()
+ fun_l7_n581
+end
+
+def fun_l6_n969()
+ fun_l7_n921
+end
+
+def fun_l6_n970()
+ fun_l7_n837
+end
+
+def fun_l6_n971()
+ fun_l7_n933
+end
+
+def fun_l6_n972()
+ fun_l7_n109
+end
+
+def fun_l6_n973()
+ fun_l7_n846
+end
+
+def fun_l6_n974()
+ fun_l7_n178
+end
+
+def fun_l6_n975()
+ fun_l7_n278
+end
+
+def fun_l6_n976()
+ fun_l7_n404
+end
+
+def fun_l6_n977()
+ fun_l7_n456
+end
+
+def fun_l6_n978()
+ fun_l7_n860
+end
+
+def fun_l6_n979()
+ fun_l7_n637
+end
+
+def fun_l6_n980()
+ fun_l7_n201
+end
+
+def fun_l6_n981()
+ fun_l7_n836
+end
+
+def fun_l6_n982()
+ fun_l7_n172
+end
+
+def fun_l6_n983()
+ fun_l7_n935
+end
+
+def fun_l6_n984()
+ fun_l7_n937
+end
+
+def fun_l6_n985()
+ fun_l7_n817
+end
+
+def fun_l6_n986()
+ fun_l7_n16
+end
+
+def fun_l6_n987()
+ fun_l7_n152
+end
+
+def fun_l6_n988()
+ fun_l7_n359
+end
+
+def fun_l6_n989()
+ fun_l7_n357
+end
+
+def fun_l6_n990()
+ fun_l7_n609
+end
+
+def fun_l6_n991()
+ fun_l7_n604
+end
+
+def fun_l6_n992()
+ fun_l7_n998
+end
+
+def fun_l6_n993()
+ fun_l7_n366
+end
+
+def fun_l6_n994()
+ fun_l7_n150
+end
+
+def fun_l6_n995()
+ fun_l7_n823
+end
+
+def fun_l6_n996()
+ fun_l7_n476
+end
+
+def fun_l6_n997()
+ fun_l7_n535
+end
+
+def fun_l6_n998()
+ fun_l7_n222
+end
+
+def fun_l6_n999()
+ fun_l7_n238
+end
+
+def fun_l7_n0()
+ fun_l8_n3
+end
+
+def fun_l7_n1()
+ fun_l8_n706
+end
+
+def fun_l7_n2()
+ fun_l8_n887
+end
+
+def fun_l7_n3()
+ fun_l8_n693
+end
+
+def fun_l7_n4()
+ fun_l8_n11
+end
+
+def fun_l7_n5()
+ fun_l8_n155
+end
+
+def fun_l7_n6()
+ fun_l8_n604
+end
+
+def fun_l7_n7()
+ fun_l8_n616
+end
+
+def fun_l7_n8()
+ fun_l8_n686
+end
+
+def fun_l7_n9()
+ fun_l8_n257
+end
+
+def fun_l7_n10()
+ fun_l8_n594
+end
+
+def fun_l7_n11()
+ fun_l8_n548
+end
+
+def fun_l7_n12()
+ fun_l8_n305
+end
+
+def fun_l7_n13()
+ fun_l8_n125
+end
+
+def fun_l7_n14()
+ fun_l8_n183
+end
+
+def fun_l7_n15()
+ fun_l8_n799
+end
+
+def fun_l7_n16()
+ fun_l8_n333
+end
+
+def fun_l7_n17()
+ fun_l8_n873
+end
+
+def fun_l7_n18()
+ fun_l8_n110
+end
+
+def fun_l7_n19()
+ fun_l8_n578
+end
+
+def fun_l7_n20()
+ fun_l8_n423
+end
+
+def fun_l7_n21()
+ fun_l8_n686
+end
+
+def fun_l7_n22()
+ fun_l8_n162
+end
+
+def fun_l7_n23()
+ fun_l8_n277
+end
+
+def fun_l7_n24()
+ fun_l8_n651
+end
+
+def fun_l7_n25()
+ fun_l8_n575
+end
+
+def fun_l7_n26()
+ fun_l8_n937
+end
+
+def fun_l7_n27()
+ fun_l8_n636
+end
+
+def fun_l7_n28()
+ fun_l8_n1
+end
+
+def fun_l7_n29()
+ fun_l8_n83
+end
+
+def fun_l7_n30()
+ fun_l8_n318
+end
+
+def fun_l7_n31()
+ fun_l8_n675
+end
+
+def fun_l7_n32()
+ fun_l8_n118
+end
+
+def fun_l7_n33()
+ fun_l8_n522
+end
+
+def fun_l7_n34()
+ fun_l8_n507
+end
+
+def fun_l7_n35()
+ fun_l8_n846
+end
+
+def fun_l7_n36()
+ fun_l8_n584
+end
+
+def fun_l7_n37()
+ fun_l8_n816
+end
+
+def fun_l7_n38()
+ fun_l8_n217
+end
+
+def fun_l7_n39()
+ fun_l8_n366
+end
+
+def fun_l7_n40()
+ fun_l8_n283
+end
+
+def fun_l7_n41()
+ fun_l8_n536
+end
+
+def fun_l7_n42()
+ fun_l8_n414
+end
+
+def fun_l7_n43()
+ fun_l8_n216
+end
+
+def fun_l7_n44()
+ fun_l8_n743
+end
+
+def fun_l7_n45()
+ fun_l8_n449
+end
+
+def fun_l7_n46()
+ fun_l8_n629
+end
+
+def fun_l7_n47()
+ fun_l8_n711
+end
+
+def fun_l7_n48()
+ fun_l8_n113
+end
+
+def fun_l7_n49()
+ fun_l8_n440
+end
+
+def fun_l7_n50()
+ fun_l8_n822
+end
+
+def fun_l7_n51()
+ fun_l8_n567
+end
+
+def fun_l7_n52()
+ fun_l8_n854
+end
+
+def fun_l7_n53()
+ fun_l8_n204
+end
+
+def fun_l7_n54()
+ fun_l8_n796
+end
+
+def fun_l7_n55()
+ fun_l8_n989
+end
+
+def fun_l7_n56()
+ fun_l8_n504
+end
+
+def fun_l7_n57()
+ fun_l8_n952
+end
+
+def fun_l7_n58()
+ fun_l8_n797
+end
+
+def fun_l7_n59()
+ fun_l8_n492
+end
+
+def fun_l7_n60()
+ fun_l8_n949
+end
+
+def fun_l7_n61()
+ fun_l8_n215
+end
+
+def fun_l7_n62()
+ fun_l8_n306
+end
+
+def fun_l7_n63()
+ fun_l8_n632
+end
+
+def fun_l7_n64()
+ fun_l8_n572
+end
+
+def fun_l7_n65()
+ fun_l8_n69
+end
+
+def fun_l7_n66()
+ fun_l8_n97
+end
+
+def fun_l7_n67()
+ fun_l8_n708
+end
+
+def fun_l7_n68()
+ fun_l8_n548
+end
+
+def fun_l7_n69()
+ fun_l8_n999
+end
+
+def fun_l7_n70()
+ fun_l8_n872
+end
+
+def fun_l7_n71()
+ fun_l8_n20
+end
+
+def fun_l7_n72()
+ fun_l8_n220
+end
+
+def fun_l7_n73()
+ fun_l8_n28
+end
+
+def fun_l7_n74()
+ fun_l8_n79
+end
+
+def fun_l7_n75()
+ fun_l8_n248
+end
+
+def fun_l7_n76()
+ fun_l8_n601
+end
+
+def fun_l7_n77()
+ fun_l8_n469
+end
+
+def fun_l7_n78()
+ fun_l8_n315
+end
+
+def fun_l7_n79()
+ fun_l8_n712
+end
+
+def fun_l7_n80()
+ fun_l8_n177
+end
+
+def fun_l7_n81()
+ fun_l8_n106
+end
+
+def fun_l7_n82()
+ fun_l8_n668
+end
+
+def fun_l7_n83()
+ fun_l8_n299
+end
+
+def fun_l7_n84()
+ fun_l8_n59
+end
+
+def fun_l7_n85()
+ fun_l8_n120
+end
+
+def fun_l7_n86()
+ fun_l8_n209
+end
+
+def fun_l7_n87()
+ fun_l8_n502
+end
+
+def fun_l7_n88()
+ fun_l8_n935
+end
+
+def fun_l7_n89()
+ fun_l8_n697
+end
+
+def fun_l7_n90()
+ fun_l8_n231
+end
+
+def fun_l7_n91()
+ fun_l8_n47
+end
+
+def fun_l7_n92()
+ fun_l8_n125
+end
+
+def fun_l7_n93()
+ fun_l8_n975
+end
+
+def fun_l7_n94()
+ fun_l8_n627
+end
+
+def fun_l7_n95()
+ fun_l8_n898
+end
+
+def fun_l7_n96()
+ fun_l8_n124
+end
+
+def fun_l7_n97()
+ fun_l8_n722
+end
+
+def fun_l7_n98()
+ fun_l8_n745
+end
+
+def fun_l7_n99()
+ fun_l8_n999
+end
+
+def fun_l7_n100()
+ fun_l8_n791
+end
+
+def fun_l7_n101()
+ fun_l8_n360
+end
+
+def fun_l7_n102()
+ fun_l8_n755
+end
+
+def fun_l7_n103()
+ fun_l8_n718
+end
+
+def fun_l7_n104()
+ fun_l8_n495
+end
+
+def fun_l7_n105()
+ fun_l8_n19
+end
+
+def fun_l7_n106()
+ fun_l8_n280
+end
+
+def fun_l7_n107()
+ fun_l8_n710
+end
+
+def fun_l7_n108()
+ fun_l8_n871
+end
+
+def fun_l7_n109()
+ fun_l8_n727
+end
+
+def fun_l7_n110()
+ fun_l8_n807
+end
+
+def fun_l7_n111()
+ fun_l8_n170
+end
+
+def fun_l7_n112()
+ fun_l8_n661
+end
+
+def fun_l7_n113()
+ fun_l8_n684
+end
+
+def fun_l7_n114()
+ fun_l8_n202
+end
+
+def fun_l7_n115()
+ fun_l8_n679
+end
+
+def fun_l7_n116()
+ fun_l8_n773
+end
+
+def fun_l7_n117()
+ fun_l8_n538
+end
+
+def fun_l7_n118()
+ fun_l8_n411
+end
+
+def fun_l7_n119()
+ fun_l8_n264
+end
+
+def fun_l7_n120()
+ fun_l8_n487
+end
+
+def fun_l7_n121()
+ fun_l8_n906
+end
+
+def fun_l7_n122()
+ fun_l8_n833
+end
+
+def fun_l7_n123()
+ fun_l8_n721
+end
+
+def fun_l7_n124()
+ fun_l8_n792
+end
+
+def fun_l7_n125()
+ fun_l8_n852
+end
+
+def fun_l7_n126()
+ fun_l8_n876
+end
+
+def fun_l7_n127()
+ fun_l8_n489
+end
+
+def fun_l7_n128()
+ fun_l8_n715
+end
+
+def fun_l7_n129()
+ fun_l8_n863
+end
+
+def fun_l7_n130()
+ fun_l8_n842
+end
+
+def fun_l7_n131()
+ fun_l8_n99
+end
+
+def fun_l7_n132()
+ fun_l8_n472
+end
+
+def fun_l7_n133()
+ fun_l8_n826
+end
+
+def fun_l7_n134()
+ fun_l8_n805
+end
+
+def fun_l7_n135()
+ fun_l8_n914
+end
+
+def fun_l7_n136()
+ fun_l8_n691
+end
+
+def fun_l7_n137()
+ fun_l8_n880
+end
+
+def fun_l7_n138()
+ fun_l8_n708
+end
+
+def fun_l7_n139()
+ fun_l8_n445
+end
+
+def fun_l7_n140()
+ fun_l8_n173
+end
+
+def fun_l7_n141()
+ fun_l8_n785
+end
+
+def fun_l7_n142()
+ fun_l8_n638
+end
+
+def fun_l7_n143()
+ fun_l8_n319
+end
+
+def fun_l7_n144()
+ fun_l8_n825
+end
+
+def fun_l7_n145()
+ fun_l8_n497
+end
+
+def fun_l7_n146()
+ fun_l8_n941
+end
+
+def fun_l7_n147()
+ fun_l8_n164
+end
+
+def fun_l7_n148()
+ fun_l8_n773
+end
+
+def fun_l7_n149()
+ fun_l8_n603
+end
+
+def fun_l7_n150()
+ fun_l8_n701
+end
+
+def fun_l7_n151()
+ fun_l8_n279
+end
+
+def fun_l7_n152()
+ fun_l8_n120
+end
+
+def fun_l7_n153()
+ fun_l8_n352
+end
+
+def fun_l7_n154()
+ fun_l8_n401
+end
+
+def fun_l7_n155()
+ fun_l8_n195
+end
+
+def fun_l7_n156()
+ fun_l8_n206
+end
+
+def fun_l7_n157()
+ fun_l8_n209
+end
+
+def fun_l7_n158()
+ fun_l8_n594
+end
+
+def fun_l7_n159()
+ fun_l8_n49
+end
+
+def fun_l7_n160()
+ fun_l8_n835
+end
+
+def fun_l7_n161()
+ fun_l8_n108
+end
+
+def fun_l7_n162()
+ fun_l8_n499
+end
+
+def fun_l7_n163()
+ fun_l8_n822
+end
+
+def fun_l7_n164()
+ fun_l8_n712
+end
+
+def fun_l7_n165()
+ fun_l8_n757
+end
+
+def fun_l7_n166()
+ fun_l8_n706
+end
+
+def fun_l7_n167()
+ fun_l8_n517
+end
+
+def fun_l7_n168()
+ fun_l8_n74
+end
+
+def fun_l7_n169()
+ fun_l8_n292
+end
+
+def fun_l7_n170()
+ fun_l8_n560
+end
+
+def fun_l7_n171()
+ fun_l8_n476
+end
+
+def fun_l7_n172()
+ fun_l8_n818
+end
+
+def fun_l7_n173()
+ fun_l8_n91
+end
+
+def fun_l7_n174()
+ fun_l8_n835
+end
+
+def fun_l7_n175()
+ fun_l8_n84
+end
+
+def fun_l7_n176()
+ fun_l8_n506
+end
+
+def fun_l7_n177()
+ fun_l8_n602
+end
+
+def fun_l7_n178()
+ fun_l8_n758
+end
+
+def fun_l7_n179()
+ fun_l8_n591
+end
+
+def fun_l7_n180()
+ fun_l8_n757
+end
+
+def fun_l7_n181()
+ fun_l8_n127
+end
+
+def fun_l7_n182()
+ fun_l8_n287
+end
+
+def fun_l7_n183()
+ fun_l8_n672
+end
+
+def fun_l7_n184()
+ fun_l8_n870
+end
+
+def fun_l7_n185()
+ fun_l8_n267
+end
+
+def fun_l7_n186()
+ fun_l8_n396
+end
+
+def fun_l7_n187()
+ fun_l8_n128
+end
+
+def fun_l7_n188()
+ fun_l8_n670
+end
+
+def fun_l7_n189()
+ fun_l8_n142
+end
+
+def fun_l7_n190()
+ fun_l8_n320
+end
+
+def fun_l7_n191()
+ fun_l8_n829
+end
+
+def fun_l7_n192()
+ fun_l8_n788
+end
+
+def fun_l7_n193()
+ fun_l8_n174
+end
+
+def fun_l7_n194()
+ fun_l8_n526
+end
+
+def fun_l7_n195()
+ fun_l8_n185
+end
+
+def fun_l7_n196()
+ fun_l8_n746
+end
+
+def fun_l7_n197()
+ fun_l8_n889
+end
+
+def fun_l7_n198()
+ fun_l8_n154
+end
+
+def fun_l7_n199()
+ fun_l8_n19
+end
+
+def fun_l7_n200()
+ fun_l8_n913
+end
+
+def fun_l7_n201()
+ fun_l8_n560
+end
+
+def fun_l7_n202()
+ fun_l8_n768
+end
+
+def fun_l7_n203()
+ fun_l8_n412
+end
+
+def fun_l7_n204()
+ fun_l8_n394
+end
+
+def fun_l7_n205()
+ fun_l8_n641
+end
+
+def fun_l7_n206()
+ fun_l8_n83
+end
+
+def fun_l7_n207()
+ fun_l8_n39
+end
+
+def fun_l7_n208()
+ fun_l8_n502
+end
+
+def fun_l7_n209()
+ fun_l8_n904
+end
+
+def fun_l7_n210()
+ fun_l8_n639
+end
+
+def fun_l7_n211()
+ fun_l8_n873
+end
+
+def fun_l7_n212()
+ fun_l8_n940
+end
+
+def fun_l7_n213()
+ fun_l8_n594
+end
+
+def fun_l7_n214()
+ fun_l8_n397
+end
+
+def fun_l7_n215()
+ fun_l8_n318
+end
+
+def fun_l7_n216()
+ fun_l8_n116
+end
+
+def fun_l7_n217()
+ fun_l8_n888
+end
+
+def fun_l7_n218()
+ fun_l8_n148
+end
+
+def fun_l7_n219()
+ fun_l8_n329
+end
+
+def fun_l7_n220()
+ fun_l8_n973
+end
+
+def fun_l7_n221()
+ fun_l8_n913
+end
+
+def fun_l7_n222()
+ fun_l8_n170
+end
+
+def fun_l7_n223()
+ fun_l8_n103
+end
+
+def fun_l7_n224()
+ fun_l8_n835
+end
+
+def fun_l7_n225()
+ fun_l8_n104
+end
+
+def fun_l7_n226()
+ fun_l8_n111
+end
+
+def fun_l7_n227()
+ fun_l8_n12
+end
+
+def fun_l7_n228()
+ fun_l8_n299
+end
+
+def fun_l7_n229()
+ fun_l8_n639
+end
+
+def fun_l7_n230()
+ fun_l8_n789
+end
+
+def fun_l7_n231()
+ fun_l8_n968
+end
+
+def fun_l7_n232()
+ fun_l8_n905
+end
+
+def fun_l7_n233()
+ fun_l8_n325
+end
+
+def fun_l7_n234()
+ fun_l8_n841
+end
+
+def fun_l7_n235()
+ fun_l8_n605
+end
+
+def fun_l7_n236()
+ fun_l8_n495
+end
+
+def fun_l7_n237()
+ fun_l8_n154
+end
+
+def fun_l7_n238()
+ fun_l8_n331
+end
+
+def fun_l7_n239()
+ fun_l8_n30
+end
+
+def fun_l7_n240()
+ fun_l8_n170
+end
+
+def fun_l7_n241()
+ fun_l8_n376
+end
+
+def fun_l7_n242()
+ fun_l8_n49
+end
+
+def fun_l7_n243()
+ fun_l8_n463
+end
+
+def fun_l7_n244()
+ fun_l8_n269
+end
+
+def fun_l7_n245()
+ fun_l8_n573
+end
+
+def fun_l7_n246()
+ fun_l8_n782
+end
+
+def fun_l7_n247()
+ fun_l8_n85
+end
+
+def fun_l7_n248()
+ fun_l8_n667
+end
+
+def fun_l7_n249()
+ fun_l8_n686
+end
+
+def fun_l7_n250()
+ fun_l8_n575
+end
+
+def fun_l7_n251()
+ fun_l8_n349
+end
+
+def fun_l7_n252()
+ fun_l8_n252
+end
+
+def fun_l7_n253()
+ fun_l8_n490
+end
+
+def fun_l7_n254()
+ fun_l8_n600
+end
+
+def fun_l7_n255()
+ fun_l8_n772
+end
+
+def fun_l7_n256()
+ fun_l8_n645
+end
+
+def fun_l7_n257()
+ fun_l8_n633
+end
+
+def fun_l7_n258()
+ fun_l8_n323
+end
+
+def fun_l7_n259()
+ fun_l8_n590
+end
+
+def fun_l7_n260()
+ fun_l8_n77
+end
+
+def fun_l7_n261()
+ fun_l8_n349
+end
+
+def fun_l7_n262()
+ fun_l8_n98
+end
+
+def fun_l7_n263()
+ fun_l8_n312
+end
+
+def fun_l7_n264()
+ fun_l8_n449
+end
+
+def fun_l7_n265()
+ fun_l8_n550
+end
+
+def fun_l7_n266()
+ fun_l8_n717
+end
+
+def fun_l7_n267()
+ fun_l8_n249
+end
+
+def fun_l7_n268()
+ fun_l8_n940
+end
+
+def fun_l7_n269()
+ fun_l8_n243
+end
+
+def fun_l7_n270()
+ fun_l8_n392
+end
+
+def fun_l7_n271()
+ fun_l8_n129
+end
+
+def fun_l7_n272()
+ fun_l8_n704
+end
+
+def fun_l7_n273()
+ fun_l8_n815
+end
+
+def fun_l7_n274()
+ fun_l8_n123
+end
+
+def fun_l7_n275()
+ fun_l8_n281
+end
+
+def fun_l7_n276()
+ fun_l8_n110
+end
+
+def fun_l7_n277()
+ fun_l8_n250
+end
+
+def fun_l7_n278()
+ fun_l8_n245
+end
+
+def fun_l7_n279()
+ fun_l8_n612
+end
+
+def fun_l7_n280()
+ fun_l8_n693
+end
+
+def fun_l7_n281()
+ fun_l8_n441
+end
+
+def fun_l7_n282()
+ fun_l8_n716
+end
+
+def fun_l7_n283()
+ fun_l8_n467
+end
+
+def fun_l7_n284()
+ fun_l8_n944
+end
+
+def fun_l7_n285()
+ fun_l8_n14
+end
+
+def fun_l7_n286()
+ fun_l8_n453
+end
+
+def fun_l7_n287()
+ fun_l8_n342
+end
+
+def fun_l7_n288()
+ fun_l8_n666
+end
+
+def fun_l7_n289()
+ fun_l8_n111
+end
+
+def fun_l7_n290()
+ fun_l8_n353
+end
+
+def fun_l7_n291()
+ fun_l8_n279
+end
+
+def fun_l7_n292()
+ fun_l8_n556
+end
+
+def fun_l7_n293()
+ fun_l8_n780
+end
+
+def fun_l7_n294()
+ fun_l8_n137
+end
+
+def fun_l7_n295()
+ fun_l8_n760
+end
+
+def fun_l7_n296()
+ fun_l8_n56
+end
+
+def fun_l7_n297()
+ fun_l8_n927
+end
+
+def fun_l7_n298()
+ fun_l8_n861
+end
+
+def fun_l7_n299()
+ fun_l8_n653
+end
+
+def fun_l7_n300()
+ fun_l8_n948
+end
+
+def fun_l7_n301()
+ fun_l8_n159
+end
+
+def fun_l7_n302()
+ fun_l8_n426
+end
+
+def fun_l7_n303()
+ fun_l8_n175
+end
+
+def fun_l7_n304()
+ fun_l8_n35
+end
+
+def fun_l7_n305()
+ fun_l8_n700
+end
+
+def fun_l7_n306()
+ fun_l8_n603
+end
+
+def fun_l7_n307()
+ fun_l8_n600
+end
+
+def fun_l7_n308()
+ fun_l8_n280
+end
+
+def fun_l7_n309()
+ fun_l8_n599
+end
+
+def fun_l7_n310()
+ fun_l8_n404
+end
+
+def fun_l7_n311()
+ fun_l8_n475
+end
+
+def fun_l7_n312()
+ fun_l8_n837
+end
+
+def fun_l7_n313()
+ fun_l8_n61
+end
+
+def fun_l7_n314()
+ fun_l8_n571
+end
+
+def fun_l7_n315()
+ fun_l8_n442
+end
+
+def fun_l7_n316()
+ fun_l8_n256
+end
+
+def fun_l7_n317()
+ fun_l8_n751
+end
+
+def fun_l7_n318()
+ fun_l8_n672
+end
+
+def fun_l7_n319()
+ fun_l8_n953
+end
+
+def fun_l7_n320()
+ fun_l8_n330
+end
+
+def fun_l7_n321()
+ fun_l8_n54
+end
+
+def fun_l7_n322()
+ fun_l8_n11
+end
+
+def fun_l7_n323()
+ fun_l8_n504
+end
+
+def fun_l7_n324()
+ fun_l8_n786
+end
+
+def fun_l7_n325()
+ fun_l8_n32
+end
+
+def fun_l7_n326()
+ fun_l8_n85
+end
+
+def fun_l7_n327()
+ fun_l8_n727
+end
+
+def fun_l7_n328()
+ fun_l8_n445
+end
+
+def fun_l7_n329()
+ fun_l8_n787
+end
+
+def fun_l7_n330()
+ fun_l8_n663
+end
+
+def fun_l7_n331()
+ fun_l8_n461
+end
+
+def fun_l7_n332()
+ fun_l8_n82
+end
+
+def fun_l7_n333()
+ fun_l8_n974
+end
+
+def fun_l7_n334()
+ fun_l8_n511
+end
+
+def fun_l7_n335()
+ fun_l8_n827
+end
+
+def fun_l7_n336()
+ fun_l8_n12
+end
+
+def fun_l7_n337()
+ fun_l8_n696
+end
+
+def fun_l7_n338()
+ fun_l8_n325
+end
+
+def fun_l7_n339()
+ fun_l8_n148
+end
+
+def fun_l7_n340()
+ fun_l8_n609
+end
+
+def fun_l7_n341()
+ fun_l8_n471
+end
+
+def fun_l7_n342()
+ fun_l8_n63
+end
+
+def fun_l7_n343()
+ fun_l8_n358
+end
+
+def fun_l7_n344()
+ fun_l8_n658
+end
+
+def fun_l7_n345()
+ fun_l8_n730
+end
+
+def fun_l7_n346()
+ fun_l8_n139
+end
+
+def fun_l7_n347()
+ fun_l8_n951
+end
+
+def fun_l7_n348()
+ fun_l8_n113
+end
+
+def fun_l7_n349()
+ fun_l8_n695
+end
+
+def fun_l7_n350()
+ fun_l8_n803
+end
+
+def fun_l7_n351()
+ fun_l8_n93
+end
+
+def fun_l7_n352()
+ fun_l8_n340
+end
+
+def fun_l7_n353()
+ fun_l8_n551
+end
+
+def fun_l7_n354()
+ fun_l8_n5
+end
+
+def fun_l7_n355()
+ fun_l8_n960
+end
+
+def fun_l7_n356()
+ fun_l8_n76
+end
+
+def fun_l7_n357()
+ fun_l8_n142
+end
+
+def fun_l7_n358()
+ fun_l8_n305
+end
+
+def fun_l7_n359()
+ fun_l8_n739
+end
+
+def fun_l7_n360()
+ fun_l8_n293
+end
+
+def fun_l7_n361()
+ fun_l8_n812
+end
+
+def fun_l7_n362()
+ fun_l8_n635
+end
+
+def fun_l7_n363()
+ fun_l8_n239
+end
+
+def fun_l7_n364()
+ fun_l8_n880
+end
+
+def fun_l7_n365()
+ fun_l8_n999
+end
+
+def fun_l7_n366()
+ fun_l8_n997
+end
+
+def fun_l7_n367()
+ fun_l8_n190
+end
+
+def fun_l7_n368()
+ fun_l8_n763
+end
+
+def fun_l7_n369()
+ fun_l8_n369
+end
+
+def fun_l7_n370()
+ fun_l8_n538
+end
+
+def fun_l7_n371()
+ fun_l8_n553
+end
+
+def fun_l7_n372()
+ fun_l8_n844
+end
+
+def fun_l7_n373()
+ fun_l8_n773
+end
+
+def fun_l7_n374()
+ fun_l8_n589
+end
+
+def fun_l7_n375()
+ fun_l8_n492
+end
+
+def fun_l7_n376()
+ fun_l8_n848
+end
+
+def fun_l7_n377()
+ fun_l8_n715
+end
+
+def fun_l7_n378()
+ fun_l8_n82
+end
+
+def fun_l7_n379()
+ fun_l8_n267
+end
+
+def fun_l7_n380()
+ fun_l8_n84
+end
+
+def fun_l7_n381()
+ fun_l8_n996
+end
+
+def fun_l7_n382()
+ fun_l8_n536
+end
+
+def fun_l7_n383()
+ fun_l8_n518
+end
+
+def fun_l7_n384()
+ fun_l8_n70
+end
+
+def fun_l7_n385()
+ fun_l8_n545
+end
+
+def fun_l7_n386()
+ fun_l8_n156
+end
+
+def fun_l7_n387()
+ fun_l8_n558
+end
+
+def fun_l7_n388()
+ fun_l8_n519
+end
+
+def fun_l7_n389()
+ fun_l8_n321
+end
+
+def fun_l7_n390()
+ fun_l8_n133
+end
+
+def fun_l7_n391()
+ fun_l8_n253
+end
+
+def fun_l7_n392()
+ fun_l8_n969
+end
+
+def fun_l7_n393()
+ fun_l8_n986
+end
+
+def fun_l7_n394()
+ fun_l8_n991
+end
+
+def fun_l7_n395()
+ fun_l8_n757
+end
+
+def fun_l7_n396()
+ fun_l8_n496
+end
+
+def fun_l7_n397()
+ fun_l8_n841
+end
+
+def fun_l7_n398()
+ fun_l8_n922
+end
+
+def fun_l7_n399()
+ fun_l8_n51
+end
+
+def fun_l7_n400()
+ fun_l8_n961
+end
+
+def fun_l7_n401()
+ fun_l8_n82
+end
+
+def fun_l7_n402()
+ fun_l8_n190
+end
+
+def fun_l7_n403()
+ fun_l8_n543
+end
+
+def fun_l7_n404()
+ fun_l8_n768
+end
+
+def fun_l7_n405()
+ fun_l8_n810
+end
+
+def fun_l7_n406()
+ fun_l8_n714
+end
+
+def fun_l7_n407()
+ fun_l8_n692
+end
+
+def fun_l7_n408()
+ fun_l8_n357
+end
+
+def fun_l7_n409()
+ fun_l8_n380
+end
+
+def fun_l7_n410()
+ fun_l8_n958
+end
+
+def fun_l7_n411()
+ fun_l8_n992
+end
+
+def fun_l7_n412()
+ fun_l8_n819
+end
+
+def fun_l7_n413()
+ fun_l8_n4
+end
+
+def fun_l7_n414()
+ fun_l8_n429
+end
+
+def fun_l7_n415()
+ fun_l8_n56
+end
+
+def fun_l7_n416()
+ fun_l8_n212
+end
+
+def fun_l7_n417()
+ fun_l8_n267
+end
+
+def fun_l7_n418()
+ fun_l8_n948
+end
+
+def fun_l7_n419()
+ fun_l8_n221
+end
+
+def fun_l7_n420()
+ fun_l8_n711
+end
+
+def fun_l7_n421()
+ fun_l8_n307
+end
+
+def fun_l7_n422()
+ fun_l8_n482
+end
+
+def fun_l7_n423()
+ fun_l8_n522
+end
+
+def fun_l7_n424()
+ fun_l8_n166
+end
+
+def fun_l7_n425()
+ fun_l8_n410
+end
+
+def fun_l7_n426()
+ fun_l8_n143
+end
+
+def fun_l7_n427()
+ fun_l8_n54
+end
+
+def fun_l7_n428()
+ fun_l8_n217
+end
+
+def fun_l7_n429()
+ fun_l8_n423
+end
+
+def fun_l7_n430()
+ fun_l8_n181
+end
+
+def fun_l7_n431()
+ fun_l8_n456
+end
+
+def fun_l7_n432()
+ fun_l8_n640
+end
+
+def fun_l7_n433()
+ fun_l8_n588
+end
+
+def fun_l7_n434()
+ fun_l8_n49
+end
+
+def fun_l7_n435()
+ fun_l8_n373
+end
+
+def fun_l7_n436()
+ fun_l8_n668
+end
+
+def fun_l7_n437()
+ fun_l8_n478
+end
+
+def fun_l7_n438()
+ fun_l8_n468
+end
+
+def fun_l7_n439()
+ fun_l8_n230
+end
+
+def fun_l7_n440()
+ fun_l8_n361
+end
+
+def fun_l7_n441()
+ fun_l8_n770
+end
+
+def fun_l7_n442()
+ fun_l8_n876
+end
+
+def fun_l7_n443()
+ fun_l8_n383
+end
+
+def fun_l7_n444()
+ fun_l8_n568
+end
+
+def fun_l7_n445()
+ fun_l8_n236
+end
+
+def fun_l7_n446()
+ fun_l8_n136
+end
+
+def fun_l7_n447()
+ fun_l8_n883
+end
+
+def fun_l7_n448()
+ fun_l8_n227
+end
+
+def fun_l7_n449()
+ fun_l8_n634
+end
+
+def fun_l7_n450()
+ fun_l8_n985
+end
+
+def fun_l7_n451()
+ fun_l8_n314
+end
+
+def fun_l7_n452()
+ fun_l8_n90
+end
+
+def fun_l7_n453()
+ fun_l8_n31
+end
+
+def fun_l7_n454()
+ fun_l8_n226
+end
+
+def fun_l7_n455()
+ fun_l8_n309
+end
+
+def fun_l7_n456()
+ fun_l8_n912
+end
+
+def fun_l7_n457()
+ fun_l8_n7
+end
+
+def fun_l7_n458()
+ fun_l8_n304
+end
+
+def fun_l7_n459()
+ fun_l8_n488
+end
+
+def fun_l7_n460()
+ fun_l8_n576
+end
+
+def fun_l7_n461()
+ fun_l8_n854
+end
+
+def fun_l7_n462()
+ fun_l8_n164
+end
+
+def fun_l7_n463()
+ fun_l8_n381
+end
+
+def fun_l7_n464()
+ fun_l8_n241
+end
+
+def fun_l7_n465()
+ fun_l8_n330
+end
+
+def fun_l7_n466()
+ fun_l8_n517
+end
+
+def fun_l7_n467()
+ fun_l8_n647
+end
+
+def fun_l7_n468()
+ fun_l8_n320
+end
+
+def fun_l7_n469()
+ fun_l8_n479
+end
+
+def fun_l7_n470()
+ fun_l8_n913
+end
+
+def fun_l7_n471()
+ fun_l8_n13
+end
+
+def fun_l7_n472()
+ fun_l8_n601
+end
+
+def fun_l7_n473()
+ fun_l8_n364
+end
+
+def fun_l7_n474()
+ fun_l8_n360
+end
+
+def fun_l7_n475()
+ fun_l8_n374
+end
+
+def fun_l7_n476()
+ fun_l8_n651
+end
+
+def fun_l7_n477()
+ fun_l8_n579
+end
+
+def fun_l7_n478()
+ fun_l8_n583
+end
+
+def fun_l7_n479()
+ fun_l8_n693
+end
+
+def fun_l7_n480()
+ fun_l8_n941
+end
+
+def fun_l7_n481()
+ fun_l8_n743
+end
+
+def fun_l7_n482()
+ fun_l8_n511
+end
+
+def fun_l7_n483()
+ fun_l8_n528
+end
+
+def fun_l7_n484()
+ fun_l8_n898
+end
+
+def fun_l7_n485()
+ fun_l8_n175
+end
+
+def fun_l7_n486()
+ fun_l8_n45
+end
+
+def fun_l7_n487()
+ fun_l8_n871
+end
+
+def fun_l7_n488()
+ fun_l8_n464
+end
+
+def fun_l7_n489()
+ fun_l8_n69
+end
+
+def fun_l7_n490()
+ fun_l8_n334
+end
+
+def fun_l7_n491()
+ fun_l8_n687
+end
+
+def fun_l7_n492()
+ fun_l8_n729
+end
+
+def fun_l7_n493()
+ fun_l8_n47
+end
+
+def fun_l7_n494()
+ fun_l8_n905
+end
+
+def fun_l7_n495()
+ fun_l8_n586
+end
+
+def fun_l7_n496()
+ fun_l8_n657
+end
+
+def fun_l7_n497()
+ fun_l8_n673
+end
+
+def fun_l7_n498()
+ fun_l8_n173
+end
+
+def fun_l7_n499()
+ fun_l8_n333
+end
+
+def fun_l7_n500()
+ fun_l8_n712
+end
+
+def fun_l7_n501()
+ fun_l8_n349
+end
+
+def fun_l7_n502()
+ fun_l8_n969
+end
+
+def fun_l7_n503()
+ fun_l8_n678
+end
+
+def fun_l7_n504()
+ fun_l8_n507
+end
+
+def fun_l7_n505()
+ fun_l8_n206
+end
+
+def fun_l7_n506()
+ fun_l8_n370
+end
+
+def fun_l7_n507()
+ fun_l8_n270
+end
+
+def fun_l7_n508()
+ fun_l8_n20
+end
+
+def fun_l7_n509()
+ fun_l8_n545
+end
+
+def fun_l7_n510()
+ fun_l8_n926
+end
+
+def fun_l7_n511()
+ fun_l8_n882
+end
+
+def fun_l7_n512()
+ fun_l8_n630
+end
+
+def fun_l7_n513()
+ fun_l8_n51
+end
+
+def fun_l7_n514()
+ fun_l8_n69
+end
+
+def fun_l7_n515()
+ fun_l8_n859
+end
+
+def fun_l7_n516()
+ fun_l8_n808
+end
+
+def fun_l7_n517()
+ fun_l8_n800
+end
+
+def fun_l7_n518()
+ fun_l8_n226
+end
+
+def fun_l7_n519()
+ fun_l8_n340
+end
+
+def fun_l7_n520()
+ fun_l8_n391
+end
+
+def fun_l7_n521()
+ fun_l8_n538
+end
+
+def fun_l7_n522()
+ fun_l8_n458
+end
+
+def fun_l7_n523()
+ fun_l8_n114
+end
+
+def fun_l7_n524()
+ fun_l8_n593
+end
+
+def fun_l7_n525()
+ fun_l8_n276
+end
+
+def fun_l7_n526()
+ fun_l8_n276
+end
+
+def fun_l7_n527()
+ fun_l8_n719
+end
+
+def fun_l7_n528()
+ fun_l8_n75
+end
+
+def fun_l7_n529()
+ fun_l8_n855
+end
+
+def fun_l7_n530()
+ fun_l8_n731
+end
+
+def fun_l7_n531()
+ fun_l8_n257
+end
+
+def fun_l7_n532()
+ fun_l8_n572
+end
+
+def fun_l7_n533()
+ fun_l8_n483
+end
+
+def fun_l7_n534()
+ fun_l8_n548
+end
+
+def fun_l7_n535()
+ fun_l8_n867
+end
+
+def fun_l7_n536()
+ fun_l8_n923
+end
+
+def fun_l7_n537()
+ fun_l8_n988
+end
+
+def fun_l7_n538()
+ fun_l8_n813
+end
+
+def fun_l7_n539()
+ fun_l8_n503
+end
+
+def fun_l7_n540()
+ fun_l8_n326
+end
+
+def fun_l7_n541()
+ fun_l8_n521
+end
+
+def fun_l7_n542()
+ fun_l8_n804
+end
+
+def fun_l7_n543()
+ fun_l8_n693
+end
+
+def fun_l7_n544()
+ fun_l8_n887
+end
+
+def fun_l7_n545()
+ fun_l8_n543
+end
+
+def fun_l7_n546()
+ fun_l8_n438
+end
+
+def fun_l7_n547()
+ fun_l8_n295
+end
+
+def fun_l7_n548()
+ fun_l8_n361
+end
+
+def fun_l7_n549()
+ fun_l8_n495
+end
+
+def fun_l7_n550()
+ fun_l8_n34
+end
+
+def fun_l7_n551()
+ fun_l8_n491
+end
+
+def fun_l7_n552()
+ fun_l8_n659
+end
+
+def fun_l7_n553()
+ fun_l8_n589
+end
+
+def fun_l7_n554()
+ fun_l8_n450
+end
+
+def fun_l7_n555()
+ fun_l8_n365
+end
+
+def fun_l7_n556()
+ fun_l8_n171
+end
+
+def fun_l7_n557()
+ fun_l8_n145
+end
+
+def fun_l7_n558()
+ fun_l8_n760
+end
+
+def fun_l7_n559()
+ fun_l8_n767
+end
+
+def fun_l7_n560()
+ fun_l8_n51
+end
+
+def fun_l7_n561()
+ fun_l8_n596
+end
+
+def fun_l7_n562()
+ fun_l8_n744
+end
+
+def fun_l7_n563()
+ fun_l8_n80
+end
+
+def fun_l7_n564()
+ fun_l8_n787
+end
+
+def fun_l7_n565()
+ fun_l8_n783
+end
+
+def fun_l7_n566()
+ fun_l8_n310
+end
+
+def fun_l7_n567()
+ fun_l8_n703
+end
+
+def fun_l7_n568()
+ fun_l8_n665
+end
+
+def fun_l7_n569()
+ fun_l8_n866
+end
+
+def fun_l7_n570()
+ fun_l8_n80
+end
+
+def fun_l7_n571()
+ fun_l8_n694
+end
+
+def fun_l7_n572()
+ fun_l8_n970
+end
+
+def fun_l7_n573()
+ fun_l8_n102
+end
+
+def fun_l7_n574()
+ fun_l8_n362
+end
+
+def fun_l7_n575()
+ fun_l8_n119
+end
+
+def fun_l7_n576()
+ fun_l8_n772
+end
+
+def fun_l7_n577()
+ fun_l8_n715
+end
+
+def fun_l7_n578()
+ fun_l8_n487
+end
+
+def fun_l7_n579()
+ fun_l8_n48
+end
+
+def fun_l7_n580()
+ fun_l8_n824
+end
+
+def fun_l7_n581()
+ fun_l8_n208
+end
+
+def fun_l7_n582()
+ fun_l8_n494
+end
+
+def fun_l7_n583()
+ fun_l8_n138
+end
+
+def fun_l7_n584()
+ fun_l8_n961
+end
+
+def fun_l7_n585()
+ fun_l8_n553
+end
+
+def fun_l7_n586()
+ fun_l8_n302
+end
+
+def fun_l7_n587()
+ fun_l8_n266
+end
+
+def fun_l7_n588()
+ fun_l8_n589
+end
+
+def fun_l7_n589()
+ fun_l8_n964
+end
+
+def fun_l7_n590()
+ fun_l8_n238
+end
+
+def fun_l7_n591()
+ fun_l8_n139
+end
+
+def fun_l7_n592()
+ fun_l8_n680
+end
+
+def fun_l7_n593()
+ fun_l8_n252
+end
+
+def fun_l7_n594()
+ fun_l8_n701
+end
+
+def fun_l7_n595()
+ fun_l8_n100
+end
+
+def fun_l7_n596()
+ fun_l8_n358
+end
+
+def fun_l7_n597()
+ fun_l8_n770
+end
+
+def fun_l7_n598()
+ fun_l8_n880
+end
+
+def fun_l7_n599()
+ fun_l8_n761
+end
+
+def fun_l7_n600()
+ fun_l8_n876
+end
+
+def fun_l7_n601()
+ fun_l8_n373
+end
+
+def fun_l7_n602()
+ fun_l8_n775
+end
+
+def fun_l7_n603()
+ fun_l8_n317
+end
+
+def fun_l7_n604()
+ fun_l8_n456
+end
+
+def fun_l7_n605()
+ fun_l8_n343
+end
+
+def fun_l7_n606()
+ fun_l8_n68
+end
+
+def fun_l7_n607()
+ fun_l8_n25
+end
+
+def fun_l7_n608()
+ fun_l8_n399
+end
+
+def fun_l7_n609()
+ fun_l8_n14
+end
+
+def fun_l7_n610()
+ fun_l8_n549
+end
+
+def fun_l7_n611()
+ fun_l8_n45
+end
+
+def fun_l7_n612()
+ fun_l8_n516
+end
+
+def fun_l7_n613()
+ fun_l8_n345
+end
+
+def fun_l7_n614()
+ fun_l8_n909
+end
+
+def fun_l7_n615()
+ fun_l8_n954
+end
+
+def fun_l7_n616()
+ fun_l8_n893
+end
+
+def fun_l7_n617()
+ fun_l8_n57
+end
+
+def fun_l7_n618()
+ fun_l8_n83
+end
+
+def fun_l7_n619()
+ fun_l8_n658
+end
+
+def fun_l7_n620()
+ fun_l8_n585
+end
+
+def fun_l7_n621()
+ fun_l8_n260
+end
+
+def fun_l7_n622()
+ fun_l8_n226
+end
+
+def fun_l7_n623()
+ fun_l8_n186
+end
+
+def fun_l7_n624()
+ fun_l8_n994
+end
+
+def fun_l7_n625()
+ fun_l8_n408
+end
+
+def fun_l7_n626()
+ fun_l8_n878
+end
+
+def fun_l7_n627()
+ fun_l8_n473
+end
+
+def fun_l7_n628()
+ fun_l8_n153
+end
+
+def fun_l7_n629()
+ fun_l8_n590
+end
+
+def fun_l7_n630()
+ fun_l8_n610
+end
+
+def fun_l7_n631()
+ fun_l8_n438
+end
+
+def fun_l7_n632()
+ fun_l8_n484
+end
+
+def fun_l7_n633()
+ fun_l8_n908
+end
+
+def fun_l7_n634()
+ fun_l8_n992
+end
+
+def fun_l7_n635()
+ fun_l8_n556
+end
+
+def fun_l7_n636()
+ fun_l8_n929
+end
+
+def fun_l7_n637()
+ fun_l8_n128
+end
+
+def fun_l7_n638()
+ fun_l8_n372
+end
+
+def fun_l7_n639()
+ fun_l8_n36
+end
+
+def fun_l7_n640()
+ fun_l8_n545
+end
+
+def fun_l7_n641()
+ fun_l8_n801
+end
+
+def fun_l7_n642()
+ fun_l8_n444
+end
+
+def fun_l7_n643()
+ fun_l8_n822
+end
+
+def fun_l7_n644()
+ fun_l8_n587
+end
+
+def fun_l7_n645()
+ fun_l8_n418
+end
+
+def fun_l7_n646()
+ fun_l8_n539
+end
+
+def fun_l7_n647()
+ fun_l8_n266
+end
+
+def fun_l7_n648()
+ fun_l8_n869
+end
+
+def fun_l7_n649()
+ fun_l8_n84
+end
+
+def fun_l7_n650()
+ fun_l8_n265
+end
+
+def fun_l7_n651()
+ fun_l8_n551
+end
+
+def fun_l7_n652()
+ fun_l8_n35
+end
+
+def fun_l7_n653()
+ fun_l8_n606
+end
+
+def fun_l7_n654()
+ fun_l8_n379
+end
+
+def fun_l7_n655()
+ fun_l8_n417
+end
+
+def fun_l7_n656()
+ fun_l8_n641
+end
+
+def fun_l7_n657()
+ fun_l8_n889
+end
+
+def fun_l7_n658()
+ fun_l8_n232
+end
+
+def fun_l7_n659()
+ fun_l8_n957
+end
+
+def fun_l7_n660()
+ fun_l8_n666
+end
+
+def fun_l7_n661()
+ fun_l8_n588
+end
+
+def fun_l7_n662()
+ fun_l8_n591
+end
+
+def fun_l7_n663()
+ fun_l8_n489
+end
+
+def fun_l7_n664()
+ fun_l8_n927
+end
+
+def fun_l7_n665()
+ fun_l8_n304
+end
+
+def fun_l7_n666()
+ fun_l8_n856
+end
+
+def fun_l7_n667()
+ fun_l8_n969
+end
+
+def fun_l7_n668()
+ fun_l8_n36
+end
+
+def fun_l7_n669()
+ fun_l8_n335
+end
+
+def fun_l7_n670()
+ fun_l8_n51
+end
+
+def fun_l7_n671()
+ fun_l8_n765
+end
+
+def fun_l7_n672()
+ fun_l8_n262
+end
+
+def fun_l7_n673()
+ fun_l8_n858
+end
+
+def fun_l7_n674()
+ fun_l8_n412
+end
+
+def fun_l7_n675()
+ fun_l8_n789
+end
+
+def fun_l7_n676()
+ fun_l8_n290
+end
+
+def fun_l7_n677()
+ fun_l8_n935
+end
+
+def fun_l7_n678()
+ fun_l8_n212
+end
+
+def fun_l7_n679()
+ fun_l8_n35
+end
+
+def fun_l7_n680()
+ fun_l8_n141
+end
+
+def fun_l7_n681()
+ fun_l8_n985
+end
+
+def fun_l7_n682()
+ fun_l8_n626
+end
+
+def fun_l7_n683()
+ fun_l8_n996
+end
+
+def fun_l7_n684()
+ fun_l8_n906
+end
+
+def fun_l7_n685()
+ fun_l8_n242
+end
+
+def fun_l7_n686()
+ fun_l8_n431
+end
+
+def fun_l7_n687()
+ fun_l8_n494
+end
+
+def fun_l7_n688()
+ fun_l8_n564
+end
+
+def fun_l7_n689()
+ fun_l8_n737
+end
+
+def fun_l7_n690()
+ fun_l8_n366
+end
+
+def fun_l7_n691()
+ fun_l8_n763
+end
+
+def fun_l7_n692()
+ fun_l8_n556
+end
+
+def fun_l7_n693()
+ fun_l8_n436
+end
+
+def fun_l7_n694()
+ fun_l8_n17
+end
+
+def fun_l7_n695()
+ fun_l8_n283
+end
+
+def fun_l7_n696()
+ fun_l8_n641
+end
+
+def fun_l7_n697()
+ fun_l8_n298
+end
+
+def fun_l7_n698()
+ fun_l8_n819
+end
+
+def fun_l7_n699()
+ fun_l8_n858
+end
+
+def fun_l7_n700()
+ fun_l8_n161
+end
+
+def fun_l7_n701()
+ fun_l8_n813
+end
+
+def fun_l7_n702()
+ fun_l8_n604
+end
+
+def fun_l7_n703()
+ fun_l8_n878
+end
+
+def fun_l7_n704()
+ fun_l8_n880
+end
+
+def fun_l7_n705()
+ fun_l8_n431
+end
+
+def fun_l7_n706()
+ fun_l8_n944
+end
+
+def fun_l7_n707()
+ fun_l8_n672
+end
+
+def fun_l7_n708()
+ fun_l8_n983
+end
+
+def fun_l7_n709()
+ fun_l8_n224
+end
+
+def fun_l7_n710()
+ fun_l8_n915
+end
+
+def fun_l7_n711()
+ fun_l8_n699
+end
+
+def fun_l7_n712()
+ fun_l8_n112
+end
+
+def fun_l7_n713()
+ fun_l8_n64
+end
+
+def fun_l7_n714()
+ fun_l8_n3
+end
+
+def fun_l7_n715()
+ fun_l8_n508
+end
+
+def fun_l7_n716()
+ fun_l8_n172
+end
+
+def fun_l7_n717()
+ fun_l8_n777
+end
+
+def fun_l7_n718()
+ fun_l8_n328
+end
+
+def fun_l7_n719()
+ fun_l8_n338
+end
+
+def fun_l7_n720()
+ fun_l8_n897
+end
+
+def fun_l7_n721()
+ fun_l8_n373
+end
+
+def fun_l7_n722()
+ fun_l8_n91
+end
+
+def fun_l7_n723()
+ fun_l8_n149
+end
+
+def fun_l7_n724()
+ fun_l8_n65
+end
+
+def fun_l7_n725()
+ fun_l8_n685
+end
+
+def fun_l7_n726()
+ fun_l8_n939
+end
+
+def fun_l7_n727()
+ fun_l8_n427
+end
+
+def fun_l7_n728()
+ fun_l8_n606
+end
+
+def fun_l7_n729()
+ fun_l8_n818
+end
+
+def fun_l7_n730()
+ fun_l8_n24
+end
+
+def fun_l7_n731()
+ fun_l8_n901
+end
+
+def fun_l7_n732()
+ fun_l8_n979
+end
+
+def fun_l7_n733()
+ fun_l8_n88
+end
+
+def fun_l7_n734()
+ fun_l8_n516
+end
+
+def fun_l7_n735()
+ fun_l8_n44
+end
+
+def fun_l7_n736()
+ fun_l8_n540
+end
+
+def fun_l7_n737()
+ fun_l8_n586
+end
+
+def fun_l7_n738()
+ fun_l8_n695
+end
+
+def fun_l7_n739()
+ fun_l8_n774
+end
+
+def fun_l7_n740()
+ fun_l8_n797
+end
+
+def fun_l7_n741()
+ fun_l8_n524
+end
+
+def fun_l7_n742()
+ fun_l8_n784
+end
+
+def fun_l7_n743()
+ fun_l8_n203
+end
+
+def fun_l7_n744()
+ fun_l8_n808
+end
+
+def fun_l7_n745()
+ fun_l8_n216
+end
+
+def fun_l7_n746()
+ fun_l8_n14
+end
+
+def fun_l7_n747()
+ fun_l8_n799
+end
+
+def fun_l7_n748()
+ fun_l8_n660
+end
+
+def fun_l7_n749()
+ fun_l8_n417
+end
+
+def fun_l7_n750()
+ fun_l8_n573
+end
+
+def fun_l7_n751()
+ fun_l8_n919
+end
+
+def fun_l7_n752()
+ fun_l8_n956
+end
+
+def fun_l7_n753()
+ fun_l8_n475
+end
+
+def fun_l7_n754()
+ fun_l8_n941
+end
+
+def fun_l7_n755()
+ fun_l8_n629
+end
+
+def fun_l7_n756()
+ fun_l8_n745
+end
+
+def fun_l7_n757()
+ fun_l8_n656
+end
+
+def fun_l7_n758()
+ fun_l8_n315
+end
+
+def fun_l7_n759()
+ fun_l8_n952
+end
+
+def fun_l7_n760()
+ fun_l8_n241
+end
+
+def fun_l7_n761()
+ fun_l8_n341
+end
+
+def fun_l7_n762()
+ fun_l8_n156
+end
+
+def fun_l7_n763()
+ fun_l8_n258
+end
+
+def fun_l7_n764()
+ fun_l8_n275
+end
+
+def fun_l7_n765()
+ fun_l8_n950
+end
+
+def fun_l7_n766()
+ fun_l8_n715
+end
+
+def fun_l7_n767()
+ fun_l8_n746
+end
+
+def fun_l7_n768()
+ fun_l8_n428
+end
+
+def fun_l7_n769()
+ fun_l8_n176
+end
+
+def fun_l7_n770()
+ fun_l8_n586
+end
+
+def fun_l7_n771()
+ fun_l8_n912
+end
+
+def fun_l7_n772()
+ fun_l8_n484
+end
+
+def fun_l7_n773()
+ fun_l8_n155
+end
+
+def fun_l7_n774()
+ fun_l8_n648
+end
+
+def fun_l7_n775()
+ fun_l8_n27
+end
+
+def fun_l7_n776()
+ fun_l8_n188
+end
+
+def fun_l7_n777()
+ fun_l8_n804
+end
+
+def fun_l7_n778()
+ fun_l8_n646
+end
+
+def fun_l7_n779()
+ fun_l8_n884
+end
+
+def fun_l7_n780()
+ fun_l8_n332
+end
+
+def fun_l7_n781()
+ fun_l8_n28
+end
+
+def fun_l7_n782()
+ fun_l8_n966
+end
+
+def fun_l7_n783()
+ fun_l8_n531
+end
+
+def fun_l7_n784()
+ fun_l8_n955
+end
+
+def fun_l7_n785()
+ fun_l8_n264
+end
+
+def fun_l7_n786()
+ fun_l8_n387
+end
+
+def fun_l7_n787()
+ fun_l8_n274
+end
+
+def fun_l7_n788()
+ fun_l8_n790
+end
+
+def fun_l7_n789()
+ fun_l8_n80
+end
+
+def fun_l7_n790()
+ fun_l8_n551
+end
+
+def fun_l7_n791()
+ fun_l8_n762
+end
+
+def fun_l7_n792()
+ fun_l8_n777
+end
+
+def fun_l7_n793()
+ fun_l8_n120
+end
+
+def fun_l7_n794()
+ fun_l8_n189
+end
+
+def fun_l7_n795()
+ fun_l8_n241
+end
+
+def fun_l7_n796()
+ fun_l8_n608
+end
+
+def fun_l7_n797()
+ fun_l8_n689
+end
+
+def fun_l7_n798()
+ fun_l8_n406
+end
+
+def fun_l7_n799()
+ fun_l8_n853
+end
+
+def fun_l7_n800()
+ fun_l8_n606
+end
+
+def fun_l7_n801()
+ fun_l8_n723
+end
+
+def fun_l7_n802()
+ fun_l8_n498
+end
+
+def fun_l7_n803()
+ fun_l8_n109
+end
+
+def fun_l7_n804()
+ fun_l8_n400
+end
+
+def fun_l7_n805()
+ fun_l8_n266
+end
+
+def fun_l7_n806()
+ fun_l8_n661
+end
+
+def fun_l7_n807()
+ fun_l8_n107
+end
+
+def fun_l7_n808()
+ fun_l8_n541
+end
+
+def fun_l7_n809()
+ fun_l8_n44
+end
+
+def fun_l7_n810()
+ fun_l8_n184
+end
+
+def fun_l7_n811()
+ fun_l8_n516
+end
+
+def fun_l7_n812()
+ fun_l8_n706
+end
+
+def fun_l7_n813()
+ fun_l8_n714
+end
+
+def fun_l7_n814()
+ fun_l8_n399
+end
+
+def fun_l7_n815()
+ fun_l8_n877
+end
+
+def fun_l7_n816()
+ fun_l8_n301
+end
+
+def fun_l7_n817()
+ fun_l8_n75
+end
+
+def fun_l7_n818()
+ fun_l8_n169
+end
+
+def fun_l7_n819()
+ fun_l8_n99
+end
+
+def fun_l7_n820()
+ fun_l8_n155
+end
+
+def fun_l7_n821()
+ fun_l8_n281
+end
+
+def fun_l7_n822()
+ fun_l8_n210
+end
+
+def fun_l7_n823()
+ fun_l8_n835
+end
+
+def fun_l7_n824()
+ fun_l8_n700
+end
+
+def fun_l7_n825()
+ fun_l8_n231
+end
+
+def fun_l7_n826()
+ fun_l8_n967
+end
+
+def fun_l7_n827()
+ fun_l8_n818
+end
+
+def fun_l7_n828()
+ fun_l8_n670
+end
+
+def fun_l7_n829()
+ fun_l8_n311
+end
+
+def fun_l7_n830()
+ fun_l8_n919
+end
+
+def fun_l7_n831()
+ fun_l8_n949
+end
+
+def fun_l7_n832()
+ fun_l8_n677
+end
+
+def fun_l7_n833()
+ fun_l8_n626
+end
+
+def fun_l7_n834()
+ fun_l8_n171
+end
+
+def fun_l7_n835()
+ fun_l8_n723
+end
+
+def fun_l7_n836()
+ fun_l8_n606
+end
+
+def fun_l7_n837()
+ fun_l8_n580
+end
+
+def fun_l7_n838()
+ fun_l8_n369
+end
+
+def fun_l7_n839()
+ fun_l8_n510
+end
+
+def fun_l7_n840()
+ fun_l8_n554
+end
+
+def fun_l7_n841()
+ fun_l8_n749
+end
+
+def fun_l7_n842()
+ fun_l8_n623
+end
+
+def fun_l7_n843()
+ fun_l8_n735
+end
+
+def fun_l7_n844()
+ fun_l8_n401
+end
+
+def fun_l7_n845()
+ fun_l8_n693
+end
+
+def fun_l7_n846()
+ fun_l8_n367
+end
+
+def fun_l7_n847()
+ fun_l8_n351
+end
+
+def fun_l7_n848()
+ fun_l8_n527
+end
+
+def fun_l7_n849()
+ fun_l8_n964
+end
+
+def fun_l7_n850()
+ fun_l8_n193
+end
+
+def fun_l7_n851()
+ fun_l8_n401
+end
+
+def fun_l7_n852()
+ fun_l8_n873
+end
+
+def fun_l7_n853()
+ fun_l8_n326
+end
+
+def fun_l7_n854()
+ fun_l8_n292
+end
+
+def fun_l7_n855()
+ fun_l8_n519
+end
+
+def fun_l7_n856()
+ fun_l8_n801
+end
+
+def fun_l7_n857()
+ fun_l8_n45
+end
+
+def fun_l7_n858()
+ fun_l8_n212
+end
+
+def fun_l7_n859()
+ fun_l8_n812
+end
+
+def fun_l7_n860()
+ fun_l8_n541
+end
+
+def fun_l7_n861()
+ fun_l8_n410
+end
+
+def fun_l7_n862()
+ fun_l8_n177
+end
+
+def fun_l7_n863()
+ fun_l8_n940
+end
+
+def fun_l7_n864()
+ fun_l8_n832
+end
+
+def fun_l7_n865()
+ fun_l8_n7
+end
+
+def fun_l7_n866()
+ fun_l8_n654
+end
+
+def fun_l7_n867()
+ fun_l8_n282
+end
+
+def fun_l7_n868()
+ fun_l8_n916
+end
+
+def fun_l7_n869()
+ fun_l8_n638
+end
+
+def fun_l7_n870()
+ fun_l8_n71
+end
+
+def fun_l7_n871()
+ fun_l8_n153
+end
+
+def fun_l7_n872()
+ fun_l8_n285
+end
+
+def fun_l7_n873()
+ fun_l8_n744
+end
+
+def fun_l7_n874()
+ fun_l8_n912
+end
+
+def fun_l7_n875()
+ fun_l8_n258
+end
+
+def fun_l7_n876()
+ fun_l8_n346
+end
+
+def fun_l7_n877()
+ fun_l8_n366
+end
+
+def fun_l7_n878()
+ fun_l8_n165
+end
+
+def fun_l7_n879()
+ fun_l8_n745
+end
+
+def fun_l7_n880()
+ fun_l8_n472
+end
+
+def fun_l7_n881()
+ fun_l8_n290
+end
+
+def fun_l7_n882()
+ fun_l8_n695
+end
+
+def fun_l7_n883()
+ fun_l8_n522
+end
+
+def fun_l7_n884()
+ fun_l8_n851
+end
+
+def fun_l7_n885()
+ fun_l8_n870
+end
+
+def fun_l7_n886()
+ fun_l8_n70
+end
+
+def fun_l7_n887()
+ fun_l8_n334
+end
+
+def fun_l7_n888()
+ fun_l8_n786
+end
+
+def fun_l7_n889()
+ fun_l8_n41
+end
+
+def fun_l7_n890()
+ fun_l8_n316
+end
+
+def fun_l7_n891()
+ fun_l8_n594
+end
+
+def fun_l7_n892()
+ fun_l8_n168
+end
+
+def fun_l7_n893()
+ fun_l8_n960
+end
+
+def fun_l7_n894()
+ fun_l8_n357
+end
+
+def fun_l7_n895()
+ fun_l8_n695
+end
+
+def fun_l7_n896()
+ fun_l8_n616
+end
+
+def fun_l7_n897()
+ fun_l8_n63
+end
+
+def fun_l7_n898()
+ fun_l8_n59
+end
+
+def fun_l7_n899()
+ fun_l8_n958
+end
+
+def fun_l7_n900()
+ fun_l8_n623
+end
+
+def fun_l7_n901()
+ fun_l8_n427
+end
+
+def fun_l7_n902()
+ fun_l8_n203
+end
+
+def fun_l7_n903()
+ fun_l8_n752
+end
+
+def fun_l7_n904()
+ fun_l8_n28
+end
+
+def fun_l7_n905()
+ fun_l8_n687
+end
+
+def fun_l7_n906()
+ fun_l8_n723
+end
+
+def fun_l7_n907()
+ fun_l8_n688
+end
+
+def fun_l7_n908()
+ fun_l8_n417
+end
+
+def fun_l7_n909()
+ fun_l8_n769
+end
+
+def fun_l7_n910()
+ fun_l8_n683
+end
+
+def fun_l7_n911()
+ fun_l8_n865
+end
+
+def fun_l7_n912()
+ fun_l8_n75
+end
+
+def fun_l7_n913()
+ fun_l8_n671
+end
+
+def fun_l7_n914()
+ fun_l8_n168
+end
+
+def fun_l7_n915()
+ fun_l8_n958
+end
+
+def fun_l7_n916()
+ fun_l8_n96
+end
+
+def fun_l7_n917()
+ fun_l8_n981
+end
+
+def fun_l7_n918()
+ fun_l8_n481
+end
+
+def fun_l7_n919()
+ fun_l8_n887
+end
+
+def fun_l7_n920()
+ fun_l8_n319
+end
+
+def fun_l7_n921()
+ fun_l8_n349
+end
+
+def fun_l7_n922()
+ fun_l8_n774
+end
+
+def fun_l7_n923()
+ fun_l8_n490
+end
+
+def fun_l7_n924()
+ fun_l8_n64
+end
+
+def fun_l7_n925()
+ fun_l8_n581
+end
+
+def fun_l7_n926()
+ fun_l8_n306
+end
+
+def fun_l7_n927()
+ fun_l8_n141
+end
+
+def fun_l7_n928()
+ fun_l8_n353
+end
+
+def fun_l7_n929()
+ fun_l8_n653
+end
+
+def fun_l7_n930()
+ fun_l8_n995
+end
+
+def fun_l7_n931()
+ fun_l8_n546
+end
+
+def fun_l7_n932()
+ fun_l8_n163
+end
+
+def fun_l7_n933()
+ fun_l8_n986
+end
+
+def fun_l7_n934()
+ fun_l8_n822
+end
+
+def fun_l7_n935()
+ fun_l8_n445
+end
+
+def fun_l7_n936()
+ fun_l8_n595
+end
+
+def fun_l7_n937()
+ fun_l8_n457
+end
+
+def fun_l7_n938()
+ fun_l8_n119
+end
+
+def fun_l7_n939()
+ fun_l8_n575
+end
+
+def fun_l7_n940()
+ fun_l8_n738
+end
+
+def fun_l7_n941()
+ fun_l8_n307
+end
+
+def fun_l7_n942()
+ fun_l8_n322
+end
+
+def fun_l7_n943()
+ fun_l8_n938
+end
+
+def fun_l7_n944()
+ fun_l8_n787
+end
+
+def fun_l7_n945()
+ fun_l8_n834
+end
+
+def fun_l7_n946()
+ fun_l8_n360
+end
+
+def fun_l7_n947()
+ fun_l8_n631
+end
+
+def fun_l7_n948()
+ fun_l8_n796
+end
+
+def fun_l7_n949()
+ fun_l8_n498
+end
+
+def fun_l7_n950()
+ fun_l8_n494
+end
+
+def fun_l7_n951()
+ fun_l8_n303
+end
+
+def fun_l7_n952()
+ fun_l8_n107
+end
+
+def fun_l7_n953()
+ fun_l8_n403
+end
+
+def fun_l7_n954()
+ fun_l8_n635
+end
+
+def fun_l7_n955()
+ fun_l8_n81
+end
+
+def fun_l7_n956()
+ fun_l8_n770
+end
+
+def fun_l7_n957()
+ fun_l8_n123
+end
+
+def fun_l7_n958()
+ fun_l8_n389
+end
+
+def fun_l7_n959()
+ fun_l8_n965
+end
+
+def fun_l7_n960()
+ fun_l8_n579
+end
+
+def fun_l7_n961()
+ fun_l8_n816
+end
+
+def fun_l7_n962()
+ fun_l8_n570
+end
+
+def fun_l7_n963()
+ fun_l8_n85
+end
+
+def fun_l7_n964()
+ fun_l8_n70
+end
+
+def fun_l7_n965()
+ fun_l8_n13
+end
+
+def fun_l7_n966()
+ fun_l8_n142
+end
+
+def fun_l7_n967()
+ fun_l8_n765
+end
+
+def fun_l7_n968()
+ fun_l8_n912
+end
+
+def fun_l7_n969()
+ fun_l8_n496
+end
+
+def fun_l7_n970()
+ fun_l8_n77
+end
+
+def fun_l7_n971()
+ fun_l8_n75
+end
+
+def fun_l7_n972()
+ fun_l8_n822
+end
+
+def fun_l7_n973()
+ fun_l8_n859
+end
+
+def fun_l7_n974()
+ fun_l8_n502
+end
+
+def fun_l7_n975()
+ fun_l8_n673
+end
+
+def fun_l7_n976()
+ fun_l8_n3
+end
+
+def fun_l7_n977()
+ fun_l8_n288
+end
+
+def fun_l7_n978()
+ fun_l8_n547
+end
+
+def fun_l7_n979()
+ fun_l8_n720
+end
+
+def fun_l7_n980()
+ fun_l8_n822
+end
+
+def fun_l7_n981()
+ fun_l8_n518
+end
+
+def fun_l7_n982()
+ fun_l8_n243
+end
+
+def fun_l7_n983()
+ fun_l8_n695
+end
+
+def fun_l7_n984()
+ fun_l8_n182
+end
+
+def fun_l7_n985()
+ fun_l8_n783
+end
+
+def fun_l7_n986()
+ fun_l8_n237
+end
+
+def fun_l7_n987()
+ fun_l8_n722
+end
+
+def fun_l7_n988()
+ fun_l8_n154
+end
+
+def fun_l7_n989()
+ fun_l8_n728
+end
+
+def fun_l7_n990()
+ fun_l8_n673
+end
+
+def fun_l7_n991()
+ fun_l8_n885
+end
+
+def fun_l7_n992()
+ fun_l8_n490
+end
+
+def fun_l7_n993()
+ fun_l8_n50
+end
+
+def fun_l7_n994()
+ fun_l8_n557
+end
+
+def fun_l7_n995()
+ fun_l8_n993
+end
+
+def fun_l7_n996()
+ fun_l8_n509
+end
+
+def fun_l7_n997()
+ fun_l8_n40
+end
+
+def fun_l7_n998()
+ fun_l8_n754
+end
+
+def fun_l7_n999()
+ fun_l8_n651
+end
+
+def fun_l8_n0()
+ fun_l9_n463
+end
+
+def fun_l8_n1()
+ fun_l9_n312
+end
+
+def fun_l8_n2()
+ fun_l9_n831
+end
+
+def fun_l8_n3()
+ fun_l9_n378
+end
+
+def fun_l8_n4()
+ fun_l9_n706
+end
+
+def fun_l8_n5()
+ fun_l9_n367
+end
+
+def fun_l8_n6()
+ fun_l9_n890
+end
+
+def fun_l8_n7()
+ fun_l9_n315
+end
+
+def fun_l8_n8()
+ fun_l9_n808
+end
+
+def fun_l8_n9()
+ fun_l9_n338
+end
+
+def fun_l8_n10()
+ fun_l9_n911
+end
+
+def fun_l8_n11()
+ fun_l9_n630
+end
+
+def fun_l8_n12()
+ fun_l9_n273
+end
+
+def fun_l8_n13()
+ fun_l9_n835
+end
+
+def fun_l8_n14()
+ fun_l9_n306
+end
+
+def fun_l8_n15()
+ fun_l9_n81
+end
+
+def fun_l8_n16()
+ fun_l9_n26
+end
+
+def fun_l8_n17()
+ fun_l9_n210
+end
+
+def fun_l8_n18()
+ fun_l9_n74
+end
+
+def fun_l8_n19()
+ fun_l9_n297
+end
+
+def fun_l8_n20()
+ fun_l9_n94
+end
+
+def fun_l8_n21()
+ fun_l9_n897
+end
+
+def fun_l8_n22()
+ fun_l9_n839
+end
+
+def fun_l8_n23()
+ fun_l9_n384
+end
+
+def fun_l8_n24()
+ fun_l9_n297
+end
+
+def fun_l8_n25()
+ fun_l9_n198
+end
+
+def fun_l8_n26()
+ fun_l9_n829
+end
+
+def fun_l8_n27()
+ fun_l9_n796
+end
+
+def fun_l8_n28()
+ fun_l9_n89
+end
+
+def fun_l8_n29()
+ fun_l9_n510
+end
+
+def fun_l8_n30()
+ fun_l9_n761
+end
+
+def fun_l8_n31()
+ fun_l9_n665
+end
+
+def fun_l8_n32()
+ fun_l9_n570
+end
+
+def fun_l8_n33()
+ fun_l9_n270
+end
+
+def fun_l8_n34()
+ fun_l9_n600
+end
+
+def fun_l8_n35()
+ fun_l9_n390
+end
+
+def fun_l8_n36()
+ fun_l9_n583
+end
+
+def fun_l8_n37()
+ fun_l9_n392
+end
+
+def fun_l8_n38()
+ fun_l9_n862
+end
+
+def fun_l8_n39()
+ fun_l9_n164
+end
+
+def fun_l8_n40()
+ fun_l9_n626
+end
+
+def fun_l8_n41()
+ fun_l9_n558
+end
+
+def fun_l8_n42()
+ fun_l9_n929
+end
+
+def fun_l8_n43()
+ fun_l9_n161
+end
+
+def fun_l8_n44()
+ fun_l9_n80
+end
+
+def fun_l8_n45()
+ fun_l9_n884
+end
+
+def fun_l8_n46()
+ fun_l9_n784
+end
+
+def fun_l8_n47()
+ fun_l9_n41
+end
+
+def fun_l8_n48()
+ fun_l9_n787
+end
+
+def fun_l8_n49()
+ fun_l9_n179
+end
+
+def fun_l8_n50()
+ fun_l9_n852
+end
+
+def fun_l8_n51()
+ fun_l9_n697
+end
+
+def fun_l8_n52()
+ fun_l9_n8
+end
+
+def fun_l8_n53()
+ fun_l9_n320
+end
+
+def fun_l8_n54()
+ fun_l9_n768
+end
+
+def fun_l8_n55()
+ fun_l9_n574
+end
+
+def fun_l8_n56()
+ fun_l9_n339
+end
+
+def fun_l8_n57()
+ fun_l9_n757
+end
+
+def fun_l8_n58()
+ fun_l9_n221
+end
+
+def fun_l8_n59()
+ fun_l9_n34
+end
+
+def fun_l8_n60()
+ fun_l9_n36
+end
+
+def fun_l8_n61()
+ fun_l9_n244
+end
+
+def fun_l8_n62()
+ fun_l9_n347
+end
+
+def fun_l8_n63()
+ fun_l9_n330
+end
+
+def fun_l8_n64()
+ fun_l9_n717
+end
+
+def fun_l8_n65()
+ fun_l9_n187
+end
+
+def fun_l8_n66()
+ fun_l9_n179
+end
+
+def fun_l8_n67()
+ fun_l9_n807
+end
+
+def fun_l8_n68()
+ fun_l9_n350
+end
+
+def fun_l8_n69()
+ fun_l9_n882
+end
+
+def fun_l8_n70()
+ fun_l9_n936
+end
+
+def fun_l8_n71()
+ fun_l9_n282
+end
+
+def fun_l8_n72()
+ fun_l9_n483
+end
+
+def fun_l8_n73()
+ fun_l9_n296
+end
+
+def fun_l8_n74()
+ fun_l9_n461
+end
+
+def fun_l8_n75()
+ fun_l9_n153
+end
+
+def fun_l8_n76()
+ fun_l9_n555
+end
+
+def fun_l8_n77()
+ fun_l9_n826
+end
+
+def fun_l8_n78()
+ fun_l9_n134
+end
+
+def fun_l8_n79()
+ fun_l9_n552
+end
+
+def fun_l8_n80()
+ fun_l9_n793
+end
+
+def fun_l8_n81()
+ fun_l9_n832
+end
+
+def fun_l8_n82()
+ fun_l9_n270
+end
+
+def fun_l8_n83()
+ fun_l9_n685
+end
+
+def fun_l8_n84()
+ fun_l9_n145
+end
+
+def fun_l8_n85()
+ fun_l9_n331
+end
+
+def fun_l8_n86()
+ fun_l9_n775
+end
+
+def fun_l8_n87()
+ fun_l9_n350
+end
+
+def fun_l8_n88()
+ fun_l9_n569
+end
+
+def fun_l8_n89()
+ fun_l9_n808
+end
+
+def fun_l8_n90()
+ fun_l9_n537
+end
+
+def fun_l8_n91()
+ fun_l9_n40
+end
+
+def fun_l8_n92()
+ fun_l9_n180
+end
+
+def fun_l8_n93()
+ fun_l9_n79
+end
+
+def fun_l8_n94()
+ fun_l9_n664
+end
+
+def fun_l8_n95()
+ fun_l9_n43
+end
+
+def fun_l8_n96()
+ fun_l9_n113
+end
+
+def fun_l8_n97()
+ fun_l9_n108
+end
+
+def fun_l8_n98()
+ fun_l9_n343
+end
+
+def fun_l8_n99()
+ fun_l9_n881
+end
+
+def fun_l8_n100()
+ fun_l9_n272
+end
+
+def fun_l8_n101()
+ fun_l9_n559
+end
+
+def fun_l8_n102()
+ fun_l9_n500
+end
+
+def fun_l8_n103()
+ fun_l9_n738
+end
+
+def fun_l8_n104()
+ fun_l9_n195
+end
+
+def fun_l8_n105()
+ fun_l9_n220
+end
+
+def fun_l8_n106()
+ fun_l9_n321
+end
+
+def fun_l8_n107()
+ fun_l9_n965
+end
+
+def fun_l8_n108()
+ fun_l9_n771
+end
+
+def fun_l8_n109()
+ fun_l9_n227
+end
+
+def fun_l8_n110()
+ fun_l9_n710
+end
+
+def fun_l8_n111()
+ fun_l9_n865
+end
+
+def fun_l8_n112()
+ fun_l9_n791
+end
+
+def fun_l8_n113()
+ fun_l9_n591
+end
+
+def fun_l8_n114()
+ fun_l9_n296
+end
+
+def fun_l8_n115()
+ fun_l9_n269
+end
+
+def fun_l8_n116()
+ fun_l9_n816
+end
+
+def fun_l8_n117()
+ fun_l9_n666
+end
+
+def fun_l8_n118()
+ fun_l9_n31
+end
+
+def fun_l8_n119()
+ fun_l9_n275
+end
+
+def fun_l8_n120()
+ fun_l9_n660
+end
+
+def fun_l8_n121()
+ fun_l9_n514
+end
+
+def fun_l8_n122()
+ fun_l9_n435
+end
+
+def fun_l8_n123()
+ fun_l9_n351
+end
+
+def fun_l8_n124()
+ fun_l9_n190
+end
+
+def fun_l8_n125()
+ fun_l9_n276
+end
+
+def fun_l8_n126()
+ fun_l9_n536
+end
+
+def fun_l8_n127()
+ fun_l9_n551
+end
+
+def fun_l8_n128()
+ fun_l9_n315
+end
+
+def fun_l8_n129()
+ fun_l9_n957
+end
+
+def fun_l8_n130()
+ fun_l9_n609
+end
+
+def fun_l8_n131()
+ fun_l9_n31
+end
+
+def fun_l8_n132()
+ fun_l9_n375
+end
+
+def fun_l8_n133()
+ fun_l9_n363
+end
+
+def fun_l8_n134()
+ fun_l9_n797
+end
+
+def fun_l8_n135()
+ fun_l9_n985
+end
+
+def fun_l8_n136()
+ fun_l9_n797
+end
+
+def fun_l8_n137()
+ fun_l9_n992
+end
+
+def fun_l8_n138()
+ fun_l9_n503
+end
+
+def fun_l8_n139()
+ fun_l9_n336
+end
+
+def fun_l8_n140()
+ fun_l9_n328
+end
+
+def fun_l8_n141()
+ fun_l9_n326
+end
+
+def fun_l8_n142()
+ fun_l9_n983
+end
+
+def fun_l8_n143()
+ fun_l9_n509
+end
+
+def fun_l8_n144()
+ fun_l9_n873
+end
+
+def fun_l8_n145()
+ fun_l9_n97
+end
+
+def fun_l8_n146()
+ fun_l9_n46
+end
+
+def fun_l8_n147()
+ fun_l9_n146
+end
+
+def fun_l8_n148()
+ fun_l9_n293
+end
+
+def fun_l8_n149()
+ fun_l9_n993
+end
+
+def fun_l8_n150()
+ fun_l9_n230
+end
+
+def fun_l8_n151()
+ fun_l9_n485
+end
+
+def fun_l8_n152()
+ fun_l9_n844
+end
+
+def fun_l8_n153()
+ fun_l9_n782
+end
+
+def fun_l8_n154()
+ fun_l9_n493
+end
+
+def fun_l8_n155()
+ fun_l9_n699
+end
+
+def fun_l8_n156()
+ fun_l9_n132
+end
+
+def fun_l8_n157()
+ fun_l9_n573
+end
+
+def fun_l8_n158()
+ fun_l9_n993
+end
+
+def fun_l8_n159()
+ fun_l9_n644
+end
+
+def fun_l8_n160()
+ fun_l9_n151
+end
+
+def fun_l8_n161()
+ fun_l9_n181
+end
+
+def fun_l8_n162()
+ fun_l9_n314
+end
+
+def fun_l8_n163()
+ fun_l9_n716
+end
+
+def fun_l8_n164()
+ fun_l9_n541
+end
+
+def fun_l8_n165()
+ fun_l9_n283
+end
+
+def fun_l8_n166()
+ fun_l9_n55
+end
+
+def fun_l8_n167()
+ fun_l9_n351
+end
+
+def fun_l8_n168()
+ fun_l9_n29
+end
+
+def fun_l8_n169()
+ fun_l9_n117
+end
+
+def fun_l8_n170()
+ fun_l9_n529
+end
+
+def fun_l8_n171()
+ fun_l9_n735
+end
+
+def fun_l8_n172()
+ fun_l9_n161
+end
+
+def fun_l8_n173()
+ fun_l9_n399
+end
+
+def fun_l8_n174()
+ fun_l9_n952
+end
+
+def fun_l8_n175()
+ fun_l9_n420
+end
+
+def fun_l8_n176()
+ fun_l9_n664
+end
+
+def fun_l8_n177()
+ fun_l9_n697
+end
+
+def fun_l8_n178()
+ fun_l9_n506
+end
+
+def fun_l8_n179()
+ fun_l9_n241
+end
+
+def fun_l8_n180()
+ fun_l9_n516
+end
+
+def fun_l8_n181()
+ fun_l9_n540
+end
+
+def fun_l8_n182()
+ fun_l9_n891
+end
+
+def fun_l8_n183()
+ fun_l9_n200
+end
+
+def fun_l8_n184()
+ fun_l9_n118
+end
+
+def fun_l8_n185()
+ fun_l9_n186
+end
+
+def fun_l8_n186()
+ fun_l9_n899
+end
+
+def fun_l8_n187()
+ fun_l9_n766
+end
+
+def fun_l8_n188()
+ fun_l9_n437
+end
+
+def fun_l8_n189()
+ fun_l9_n431
+end
+
+def fun_l8_n190()
+ fun_l9_n814
+end
+
+def fun_l8_n191()
+ fun_l9_n446
+end
+
+def fun_l8_n192()
+ fun_l9_n364
+end
+
+def fun_l8_n193()
+ fun_l9_n634
+end
+
+def fun_l8_n194()
+ fun_l9_n74
+end
+
+def fun_l8_n195()
+ fun_l9_n258
+end
+
+def fun_l8_n196()
+ fun_l9_n105
+end
+
+def fun_l8_n197()
+ fun_l9_n295
+end
+
+def fun_l8_n198()
+ fun_l9_n811
+end
+
+def fun_l8_n199()
+ fun_l9_n210
+end
+
+def fun_l8_n200()
+ fun_l9_n566
+end
+
+def fun_l8_n201()
+ fun_l9_n813
+end
+
+def fun_l8_n202()
+ fun_l9_n624
+end
+
+def fun_l8_n203()
+ fun_l9_n757
+end
+
+def fun_l8_n204()
+ fun_l9_n256
+end
+
+def fun_l8_n205()
+ fun_l9_n439
+end
+
+def fun_l8_n206()
+ fun_l9_n359
+end
+
+def fun_l8_n207()
+ fun_l9_n795
+end
+
+def fun_l8_n208()
+ fun_l9_n178
+end
+
+def fun_l8_n209()
+ fun_l9_n96
+end
+
+def fun_l8_n210()
+ fun_l9_n273
+end
+
+def fun_l8_n211()
+ fun_l9_n976
+end
+
+def fun_l8_n212()
+ fun_l9_n412
+end
+
+def fun_l8_n213()
+ fun_l9_n372
+end
+
+def fun_l8_n214()
+ fun_l9_n902
+end
+
+def fun_l8_n215()
+ fun_l9_n283
+end
+
+def fun_l8_n216()
+ fun_l9_n101
+end
+
+def fun_l8_n217()
+ fun_l9_n792
+end
+
+def fun_l8_n218()
+ fun_l9_n207
+end
+
+def fun_l8_n219()
+ fun_l9_n653
+end
+
+def fun_l8_n220()
+ fun_l9_n784
+end
+
+def fun_l8_n221()
+ fun_l9_n455
+end
+
+def fun_l8_n222()
+ fun_l9_n188
+end
+
+def fun_l8_n223()
+ fun_l9_n169
+end
+
+def fun_l8_n224()
+ fun_l9_n88
+end
+
+def fun_l8_n225()
+ fun_l9_n132
+end
+
+def fun_l8_n226()
+ fun_l9_n269
+end
+
+def fun_l8_n227()
+ fun_l9_n903
+end
+
+def fun_l8_n228()
+ fun_l9_n463
+end
+
+def fun_l8_n229()
+ fun_l9_n73
+end
+
+def fun_l8_n230()
+ fun_l9_n36
+end
+
+def fun_l8_n231()
+ fun_l9_n224
+end
+
+def fun_l8_n232()
+ fun_l9_n739
+end
+
+def fun_l8_n233()
+ fun_l9_n887
+end
+
+def fun_l8_n234()
+ fun_l9_n522
+end
+
+def fun_l8_n235()
+ fun_l9_n261
+end
+
+def fun_l8_n236()
+ fun_l9_n222
+end
+
+def fun_l8_n237()
+ fun_l9_n358
+end
+
+def fun_l8_n238()
+ fun_l9_n855
+end
+
+def fun_l8_n239()
+ fun_l9_n263
+end
+
+def fun_l8_n240()
+ fun_l9_n411
+end
+
+def fun_l8_n241()
+ fun_l9_n450
+end
+
+def fun_l8_n242()
+ fun_l9_n706
+end
+
+def fun_l8_n243()
+ fun_l9_n125
+end
+
+def fun_l8_n244()
+ fun_l9_n163
+end
+
+def fun_l8_n245()
+ fun_l9_n758
+end
+
+def fun_l8_n246()
+ fun_l9_n168
+end
+
+def fun_l8_n247()
+ fun_l9_n250
+end
+
+def fun_l8_n248()
+ fun_l9_n73
+end
+
+def fun_l8_n249()
+ fun_l9_n25
+end
+
+def fun_l8_n250()
+ fun_l9_n311
+end
+
+def fun_l8_n251()
+ fun_l9_n992
+end
+
+def fun_l8_n252()
+ fun_l9_n95
+end
+
+def fun_l8_n253()
+ fun_l9_n470
+end
+
+def fun_l8_n254()
+ fun_l9_n906
+end
+
+def fun_l8_n255()
+ fun_l9_n695
+end
+
+def fun_l8_n256()
+ fun_l9_n835
+end
+
+def fun_l8_n257()
+ fun_l9_n601
+end
+
+def fun_l8_n258()
+ fun_l9_n20
+end
+
+def fun_l8_n259()
+ fun_l9_n806
+end
+
+def fun_l8_n260()
+ fun_l9_n689
+end
+
+def fun_l8_n261()
+ fun_l9_n183
+end
+
+def fun_l8_n262()
+ fun_l9_n444
+end
+
+def fun_l8_n263()
+ fun_l9_n344
+end
+
+def fun_l8_n264()
+ fun_l9_n585
+end
+
+def fun_l8_n265()
+ fun_l9_n109
+end
+
+def fun_l8_n266()
+ fun_l9_n551
+end
+
+def fun_l8_n267()
+ fun_l9_n654
+end
+
+def fun_l8_n268()
+ fun_l9_n573
+end
+
+def fun_l8_n269()
+ fun_l9_n196
+end
+
+def fun_l8_n270()
+ fun_l9_n764
+end
+
+def fun_l8_n271()
+ fun_l9_n349
+end
+
+def fun_l8_n272()
+ fun_l9_n8
+end
+
+def fun_l8_n273()
+ fun_l9_n815
+end
+
+def fun_l8_n274()
+ fun_l9_n343
+end
+
+def fun_l8_n275()
+ fun_l9_n98
+end
+
+def fun_l8_n276()
+ fun_l9_n967
+end
+
+def fun_l8_n277()
+ fun_l9_n368
+end
+
+def fun_l8_n278()
+ fun_l9_n626
+end
+
+def fun_l8_n279()
+ fun_l9_n931
+end
+
+def fun_l8_n280()
+ fun_l9_n723
+end
+
+def fun_l8_n281()
+ fun_l9_n319
+end
+
+def fun_l8_n282()
+ fun_l9_n243
+end
+
+def fun_l8_n283()
+ fun_l9_n683
+end
+
+def fun_l8_n284()
+ fun_l9_n127
+end
+
+def fun_l8_n285()
+ fun_l9_n941
+end
+
+def fun_l8_n286()
+ fun_l9_n263
+end
+
+def fun_l8_n287()
+ fun_l9_n227
+end
+
+def fun_l8_n288()
+ fun_l9_n807
+end
+
+def fun_l8_n289()
+ fun_l9_n486
+end
+
+def fun_l8_n290()
+ fun_l9_n801
+end
+
+def fun_l8_n291()
+ fun_l9_n319
+end
+
+def fun_l8_n292()
+ fun_l9_n687
+end
+
+def fun_l8_n293()
+ fun_l9_n639
+end
+
+def fun_l8_n294()
+ fun_l9_n908
+end
+
+def fun_l8_n295()
+ fun_l9_n522
+end
+
+def fun_l8_n296()
+ fun_l9_n839
+end
+
+def fun_l8_n297()
+ fun_l9_n238
+end
+
+def fun_l8_n298()
+ fun_l9_n66
+end
+
+def fun_l8_n299()
+ fun_l9_n224
+end
+
+def fun_l8_n300()
+ fun_l9_n114
+end
+
+def fun_l8_n301()
+ fun_l9_n237
+end
+
+def fun_l8_n302()
+ fun_l9_n416
+end
+
+def fun_l8_n303()
+ fun_l9_n554
+end
+
+def fun_l8_n304()
+ fun_l9_n613
+end
+
+def fun_l8_n305()
+ fun_l9_n641
+end
+
+def fun_l8_n306()
+ fun_l9_n507
+end
+
+def fun_l8_n307()
+ fun_l9_n367
+end
+
+def fun_l8_n308()
+ fun_l9_n387
+end
+
+def fun_l8_n309()
+ fun_l9_n423
+end
+
+def fun_l8_n310()
+ fun_l9_n981
+end
+
+def fun_l8_n311()
+ fun_l9_n658
+end
+
+def fun_l8_n312()
+ fun_l9_n845
+end
+
+def fun_l8_n313()
+ fun_l9_n944
+end
+
+def fun_l8_n314()
+ fun_l9_n87
+end
+
+def fun_l8_n315()
+ fun_l9_n106
+end
+
+def fun_l8_n316()
+ fun_l9_n461
+end
+
+def fun_l8_n317()
+ fun_l9_n722
+end
+
+def fun_l8_n318()
+ fun_l9_n636
+end
+
+def fun_l8_n319()
+ fun_l9_n420
+end
+
+def fun_l8_n320()
+ fun_l9_n633
+end
+
+def fun_l8_n321()
+ fun_l9_n801
+end
+
+def fun_l8_n322()
+ fun_l9_n754
+end
+
+def fun_l8_n323()
+ fun_l9_n697
+end
+
+def fun_l8_n324()
+ fun_l9_n983
+end
+
+def fun_l8_n325()
+ fun_l9_n244
+end
+
+def fun_l8_n326()
+ fun_l9_n980
+end
+
+def fun_l8_n327()
+ fun_l9_n242
+end
+
+def fun_l8_n328()
+ fun_l9_n798
+end
+
+def fun_l8_n329()
+ fun_l9_n395
+end
+
+def fun_l8_n330()
+ fun_l9_n931
+end
+
+def fun_l8_n331()
+ fun_l9_n827
+end
+
+def fun_l8_n332()
+ fun_l9_n704
+end
+
+def fun_l8_n333()
+ fun_l9_n392
+end
+
+def fun_l8_n334()
+ fun_l9_n288
+end
+
+def fun_l8_n335()
+ fun_l9_n95
+end
+
+def fun_l8_n336()
+ fun_l9_n123
+end
+
+def fun_l8_n337()
+ fun_l9_n238
+end
+
+def fun_l8_n338()
+ fun_l9_n903
+end
+
+def fun_l8_n339()
+ fun_l9_n515
+end
+
+def fun_l8_n340()
+ fun_l9_n368
+end
+
+def fun_l8_n341()
+ fun_l9_n156
+end
+
+def fun_l8_n342()
+ fun_l9_n714
+end
+
+def fun_l8_n343()
+ fun_l9_n435
+end
+
+def fun_l8_n344()
+ fun_l9_n653
+end
+
+def fun_l8_n345()
+ fun_l9_n304
+end
+
+def fun_l8_n346()
+ fun_l9_n880
+end
+
+def fun_l8_n347()
+ fun_l9_n701
+end
+
+def fun_l8_n348()
+ fun_l9_n815
+end
+
+def fun_l8_n349()
+ fun_l9_n180
+end
+
+def fun_l8_n350()
+ fun_l9_n24
+end
+
+def fun_l8_n351()
+ fun_l9_n970
+end
+
+def fun_l8_n352()
+ fun_l9_n829
+end
+
+def fun_l8_n353()
+ fun_l9_n908
+end
+
+def fun_l8_n354()
+ fun_l9_n355
+end
+
+def fun_l8_n355()
+ fun_l9_n844
+end
+
+def fun_l8_n356()
+ fun_l9_n936
+end
+
+def fun_l8_n357()
+ fun_l9_n555
+end
+
+def fun_l8_n358()
+ fun_l9_n936
+end
+
+def fun_l8_n359()
+ fun_l9_n61
+end
+
+def fun_l8_n360()
+ fun_l9_n936
+end
+
+def fun_l8_n361()
+ fun_l9_n244
+end
+
+def fun_l8_n362()
+ fun_l9_n799
+end
+
+def fun_l8_n363()
+ fun_l9_n429
+end
+
+def fun_l8_n364()
+ fun_l9_n676
+end
+
+def fun_l8_n365()
+ fun_l9_n877
+end
+
+def fun_l8_n366()
+ fun_l9_n862
+end
+
+def fun_l8_n367()
+ fun_l9_n937
+end
+
+def fun_l8_n368()
+ fun_l9_n59
+end
+
+def fun_l8_n369()
+ fun_l9_n50
+end
+
+def fun_l8_n370()
+ fun_l9_n550
+end
+
+def fun_l8_n371()
+ fun_l9_n562
+end
+
+def fun_l8_n372()
+ fun_l9_n270
+end
+
+def fun_l8_n373()
+ fun_l9_n774
+end
+
+def fun_l8_n374()
+ fun_l9_n61
+end
+
+def fun_l8_n375()
+ fun_l9_n221
+end
+
+def fun_l8_n376()
+ fun_l9_n483
+end
+
+def fun_l8_n377()
+ fun_l9_n63
+end
+
+def fun_l8_n378()
+ fun_l9_n921
+end
+
+def fun_l8_n379()
+ fun_l9_n34
+end
+
+def fun_l8_n380()
+ fun_l9_n684
+end
+
+def fun_l8_n381()
+ fun_l9_n583
+end
+
+def fun_l8_n382()
+ fun_l9_n918
+end
+
+def fun_l8_n383()
+ fun_l9_n193
+end
+
+def fun_l8_n384()
+ fun_l9_n525
+end
+
+def fun_l8_n385()
+ fun_l9_n789
+end
+
+def fun_l8_n386()
+ fun_l9_n158
+end
+
+def fun_l8_n387()
+ fun_l9_n32
+end
+
+def fun_l8_n388()
+ fun_l9_n741
+end
+
+def fun_l8_n389()
+ fun_l9_n880
+end
+
+def fun_l8_n390()
+ fun_l9_n710
+end
+
+def fun_l8_n391()
+ fun_l9_n837
+end
+
+def fun_l8_n392()
+ fun_l9_n866
+end
+
+def fun_l8_n393()
+ fun_l9_n511
+end
+
+def fun_l8_n394()
+ fun_l9_n794
+end
+
+def fun_l8_n395()
+ fun_l9_n508
+end
+
+def fun_l8_n396()
+ fun_l9_n102
+end
+
+def fun_l8_n397()
+ fun_l9_n24
+end
+
+def fun_l8_n398()
+ fun_l9_n512
+end
+
+def fun_l8_n399()
+ fun_l9_n764
+end
+
+def fun_l8_n400()
+ fun_l9_n100
+end
+
+def fun_l8_n401()
+ fun_l9_n159
+end
+
+def fun_l8_n402()
+ fun_l9_n774
+end
+
+def fun_l8_n403()
+ fun_l9_n382
+end
+
+def fun_l8_n404()
+ fun_l9_n596
+end
+
+def fun_l8_n405()
+ fun_l9_n581
+end
+
+def fun_l8_n406()
+ fun_l9_n818
+end
+
+def fun_l8_n407()
+ fun_l9_n158
+end
+
+def fun_l8_n408()
+ fun_l9_n59
+end
+
+def fun_l8_n409()
+ fun_l9_n392
+end
+
+def fun_l8_n410()
+ fun_l9_n877
+end
+
+def fun_l8_n411()
+ fun_l9_n49
+end
+
+def fun_l8_n412()
+ fun_l9_n379
+end
+
+def fun_l8_n413()
+ fun_l9_n367
+end
+
+def fun_l8_n414()
+ fun_l9_n740
+end
+
+def fun_l8_n415()
+ fun_l9_n880
+end
+
+def fun_l8_n416()
+ fun_l9_n354
+end
+
+def fun_l8_n417()
+ fun_l9_n874
+end
+
+def fun_l8_n418()
+ fun_l9_n769
+end
+
+def fun_l8_n419()
+ fun_l9_n821
+end
+
+def fun_l8_n420()
+ fun_l9_n595
+end
+
+def fun_l8_n421()
+ fun_l9_n471
+end
+
+def fun_l8_n422()
+ fun_l9_n963
+end
+
+def fun_l8_n423()
+ fun_l9_n806
+end
+
+def fun_l8_n424()
+ fun_l9_n863
+end
+
+def fun_l8_n425()
+ fun_l9_n255
+end
+
+def fun_l8_n426()
+ fun_l9_n787
+end
+
+def fun_l8_n427()
+ fun_l9_n369
+end
+
+def fun_l8_n428()
+ fun_l9_n876
+end
+
+def fun_l8_n429()
+ fun_l9_n660
+end
+
+def fun_l8_n430()
+ fun_l9_n678
+end
+
+def fun_l8_n431()
+ fun_l9_n690
+end
+
+def fun_l8_n432()
+ fun_l9_n954
+end
+
+def fun_l8_n433()
+ fun_l9_n250
+end
+
+def fun_l8_n434()
+ fun_l9_n834
+end
+
+def fun_l8_n435()
+ fun_l9_n852
+end
+
+def fun_l8_n436()
+ fun_l9_n987
+end
+
+def fun_l8_n437()
+ fun_l9_n297
+end
+
+def fun_l8_n438()
+ fun_l9_n263
+end
+
+def fun_l8_n439()
+ fun_l9_n120
+end
+
+def fun_l8_n440()
+ fun_l9_n57
+end
+
+def fun_l8_n441()
+ fun_l9_n363
+end
+
+def fun_l8_n442()
+ fun_l9_n458
+end
+
+def fun_l8_n443()
+ fun_l9_n323
+end
+
+def fun_l8_n444()
+ fun_l9_n80
+end
+
+def fun_l8_n445()
+ fun_l9_n88
+end
+
+def fun_l8_n446()
+ fun_l9_n928
+end
+
+def fun_l8_n447()
+ fun_l9_n682
+end
+
+def fun_l8_n448()
+ fun_l9_n740
+end
+
+def fun_l8_n449()
+ fun_l9_n132
+end
+
+def fun_l8_n450()
+ fun_l9_n194
+end
+
+def fun_l8_n451()
+ fun_l9_n694
+end
+
+def fun_l8_n452()
+ fun_l9_n53
+end
+
+def fun_l8_n453()
+ fun_l9_n84
+end
+
+def fun_l8_n454()
+ fun_l9_n801
+end
+
+def fun_l8_n455()
+ fun_l9_n176
+end
+
+def fun_l8_n456()
+ fun_l9_n375
+end
+
+def fun_l8_n457()
+ fun_l9_n161
+end
+
+def fun_l8_n458()
+ fun_l9_n723
+end
+
+def fun_l8_n459()
+ fun_l9_n704
+end
+
+def fun_l8_n460()
+ fun_l9_n335
+end
+
+def fun_l8_n461()
+ fun_l9_n106
+end
+
+def fun_l8_n462()
+ fun_l9_n425
+end
+
+def fun_l8_n463()
+ fun_l9_n972
+end
+
+def fun_l8_n464()
+ fun_l9_n18
+end
+
+def fun_l8_n465()
+ fun_l9_n872
+end
+
+def fun_l8_n466()
+ fun_l9_n453
+end
+
+def fun_l8_n467()
+ fun_l9_n220
+end
+
+def fun_l8_n468()
+ fun_l9_n283
+end
+
+def fun_l8_n469()
+ fun_l9_n48
+end
+
+def fun_l8_n470()
+ fun_l9_n891
+end
+
+def fun_l8_n471()
+ fun_l9_n640
+end
+
+def fun_l8_n472()
+ fun_l9_n842
+end
+
+def fun_l8_n473()
+ fun_l9_n440
+end
+
+def fun_l8_n474()
+ fun_l9_n109
+end
+
+def fun_l8_n475()
+ fun_l9_n910
+end
+
+def fun_l8_n476()
+ fun_l9_n136
+end
+
+def fun_l8_n477()
+ fun_l9_n187
+end
+
+def fun_l8_n478()
+ fun_l9_n279
+end
+
+def fun_l8_n479()
+ fun_l9_n8
+end
+
+def fun_l8_n480()
+ fun_l9_n372
+end
+
+def fun_l8_n481()
+ fun_l9_n504
+end
+
+def fun_l8_n482()
+ fun_l9_n250
+end
+
+def fun_l8_n483()
+ fun_l9_n122
+end
+
+def fun_l8_n484()
+ fun_l9_n435
+end
+
+def fun_l8_n485()
+ fun_l9_n282
+end
+
+def fun_l8_n486()
+ fun_l9_n213
+end
+
+def fun_l8_n487()
+ fun_l9_n256
+end
+
+def fun_l8_n488()
+ fun_l9_n162
+end
+
+def fun_l8_n489()
+ fun_l9_n419
+end
+
+def fun_l8_n490()
+ fun_l9_n286
+end
+
+def fun_l8_n491()
+ fun_l9_n102
+end
+
+def fun_l8_n492()
+ fun_l9_n434
+end
+
+def fun_l8_n493()
+ fun_l9_n782
+end
+
+def fun_l8_n494()
+ fun_l9_n993
+end
+
+def fun_l8_n495()
+ fun_l9_n275
+end
+
+def fun_l8_n496()
+ fun_l9_n873
+end
+
+def fun_l8_n497()
+ fun_l9_n346
+end
+
+def fun_l8_n498()
+ fun_l9_n57
+end
+
+def fun_l8_n499()
+ fun_l9_n77
+end
+
+def fun_l8_n500()
+ fun_l9_n936
+end
+
+def fun_l8_n501()
+ fun_l9_n320
+end
+
+def fun_l8_n502()
+ fun_l9_n921
+end
+
+def fun_l8_n503()
+ fun_l9_n505
+end
+
+def fun_l8_n504()
+ fun_l9_n184
+end
+
+def fun_l8_n505()
+ fun_l9_n476
+end
+
+def fun_l8_n506()
+ fun_l9_n2
+end
+
+def fun_l8_n507()
+ fun_l9_n573
+end
+
+def fun_l8_n508()
+ fun_l9_n150
+end
+
+def fun_l8_n509()
+ fun_l9_n637
+end
+
+def fun_l8_n510()
+ fun_l9_n435
+end
+
+def fun_l8_n511()
+ fun_l9_n361
+end
+
+def fun_l8_n512()
+ fun_l9_n808
+end
+
+def fun_l8_n513()
+ fun_l9_n129
+end
+
+def fun_l8_n514()
+ fun_l9_n57
+end
+
+def fun_l8_n515()
+ fun_l9_n646
+end
+
+def fun_l8_n516()
+ fun_l9_n679
+end
+
+def fun_l8_n517()
+ fun_l9_n256
+end
+
+def fun_l8_n518()
+ fun_l9_n672
+end
+
+def fun_l8_n519()
+ fun_l9_n406
+end
+
+def fun_l8_n520()
+ fun_l9_n59
+end
+
+def fun_l8_n521()
+ fun_l9_n215
+end
+
+def fun_l8_n522()
+ fun_l9_n435
+end
+
+def fun_l8_n523()
+ fun_l9_n693
+end
+
+def fun_l8_n524()
+ fun_l9_n863
+end
+
+def fun_l8_n525()
+ fun_l9_n79
+end
+
+def fun_l8_n526()
+ fun_l9_n527
+end
+
+def fun_l8_n527()
+ fun_l9_n711
+end
+
+def fun_l8_n528()
+ fun_l9_n51
+end
+
+def fun_l8_n529()
+ fun_l9_n712
+end
+
+def fun_l8_n530()
+ fun_l9_n84
+end
+
+def fun_l8_n531()
+ fun_l9_n854
+end
+
+def fun_l8_n532()
+ fun_l9_n43
+end
+
+def fun_l8_n533()
+ fun_l9_n354
+end
+
+def fun_l8_n534()
+ fun_l9_n74
+end
+
+def fun_l8_n535()
+ fun_l9_n736
+end
+
+def fun_l8_n536()
+ fun_l9_n573
+end
+
+def fun_l8_n537()
+ fun_l9_n56
+end
+
+def fun_l8_n538()
+ fun_l9_n818
+end
+
+def fun_l8_n539()
+ fun_l9_n861
+end
+
+def fun_l8_n540()
+ fun_l9_n531
+end
+
+def fun_l8_n541()
+ fun_l9_n204
+end
+
+def fun_l8_n542()
+ fun_l9_n451
+end
+
+def fun_l8_n543()
+ fun_l9_n138
+end
+
+def fun_l8_n544()
+ fun_l9_n888
+end
+
+def fun_l8_n545()
+ fun_l9_n846
+end
+
+def fun_l8_n546()
+ fun_l9_n873
+end
+
+def fun_l8_n547()
+ fun_l9_n467
+end
+
+def fun_l8_n548()
+ fun_l9_n210
+end
+
+def fun_l8_n549()
+ fun_l9_n773
+end
+
+def fun_l8_n550()
+ fun_l9_n546
+end
+
+def fun_l8_n551()
+ fun_l9_n768
+end
+
+def fun_l8_n552()
+ fun_l9_n115
+end
+
+def fun_l8_n553()
+ fun_l9_n20
+end
+
+def fun_l8_n554()
+ fun_l9_n891
+end
+
+def fun_l8_n555()
+ fun_l9_n924
+end
+
+def fun_l8_n556()
+ fun_l9_n192
+end
+
+def fun_l8_n557()
+ fun_l9_n581
+end
+
+def fun_l8_n558()
+ fun_l9_n517
+end
+
+def fun_l8_n559()
+ fun_l9_n533
+end
+
+def fun_l8_n560()
+ fun_l9_n930
+end
+
+def fun_l8_n561()
+ fun_l9_n321
+end
+
+def fun_l8_n562()
+ fun_l9_n648
+end
+
+def fun_l8_n563()
+ fun_l9_n963
+end
+
+def fun_l8_n564()
+ fun_l9_n406
+end
+
+def fun_l8_n565()
+ fun_l9_n823
+end
+
+def fun_l8_n566()
+ fun_l9_n394
+end
+
+def fun_l8_n567()
+ fun_l9_n442
+end
+
+def fun_l8_n568()
+ fun_l9_n851
+end
+
+def fun_l8_n569()
+ fun_l9_n652
+end
+
+def fun_l8_n570()
+ fun_l9_n165
+end
+
+def fun_l8_n571()
+ fun_l9_n213
+end
+
+def fun_l8_n572()
+ fun_l9_n633
+end
+
+def fun_l8_n573()
+ fun_l9_n243
+end
+
+def fun_l8_n574()
+ fun_l9_n232
+end
+
+def fun_l8_n575()
+ fun_l9_n76
+end
+
+def fun_l8_n576()
+ fun_l9_n547
+end
+
+def fun_l8_n577()
+ fun_l9_n628
+end
+
+def fun_l8_n578()
+ fun_l9_n20
+end
+
+def fun_l8_n579()
+ fun_l9_n525
+end
+
+def fun_l8_n580()
+ fun_l9_n788
+end
+
+def fun_l8_n581()
+ fun_l9_n326
+end
+
+def fun_l8_n582()
+ fun_l9_n206
+end
+
+def fun_l8_n583()
+ fun_l9_n709
+end
+
+def fun_l8_n584()
+ fun_l9_n185
+end
+
+def fun_l8_n585()
+ fun_l9_n106
+end
+
+def fun_l8_n586()
+ fun_l9_n180
+end
+
+def fun_l8_n587()
+ fun_l9_n304
+end
+
+def fun_l8_n588()
+ fun_l9_n689
+end
+
+def fun_l8_n589()
+ fun_l9_n124
+end
+
+def fun_l8_n590()
+ fun_l9_n91
+end
+
+def fun_l8_n591()
+ fun_l9_n856
+end
+
+def fun_l8_n592()
+ fun_l9_n16
+end
+
+def fun_l8_n593()
+ fun_l9_n875
+end
+
+def fun_l8_n594()
+ fun_l9_n407
+end
+
+def fun_l8_n595()
+ fun_l9_n386
+end
+
+def fun_l8_n596()
+ fun_l9_n269
+end
+
+def fun_l8_n597()
+ fun_l9_n254
+end
+
+def fun_l8_n598()
+ fun_l9_n452
+end
+
+def fun_l8_n599()
+ fun_l9_n450
+end
+
+def fun_l8_n600()
+ fun_l9_n268
+end
+
+def fun_l8_n601()
+ fun_l9_n965
+end
+
+def fun_l8_n602()
+ fun_l9_n190
+end
+
+def fun_l8_n603()
+ fun_l9_n811
+end
+
+def fun_l8_n604()
+ fun_l9_n802
+end
+
+def fun_l8_n605()
+ fun_l9_n732
+end
+
+def fun_l8_n606()
+ fun_l9_n997
+end
+
+def fun_l8_n607()
+ fun_l9_n929
+end
+
+def fun_l8_n608()
+ fun_l9_n18
+end
+
+def fun_l8_n609()
+ fun_l9_n260
+end
+
+def fun_l8_n610()
+ fun_l9_n17
+end
+
+def fun_l8_n611()
+ fun_l9_n324
+end
+
+def fun_l8_n612()
+ fun_l9_n473
+end
+
+def fun_l8_n613()
+ fun_l9_n266
+end
+
+def fun_l8_n614()
+ fun_l9_n753
+end
+
+def fun_l8_n615()
+ fun_l9_n929
+end
+
+def fun_l8_n616()
+ fun_l9_n374
+end
+
+def fun_l8_n617()
+ fun_l9_n254
+end
+
+def fun_l8_n618()
+ fun_l9_n520
+end
+
+def fun_l8_n619()
+ fun_l9_n561
+end
+
+def fun_l8_n620()
+ fun_l9_n309
+end
+
+def fun_l8_n621()
+ fun_l9_n875
+end
+
+def fun_l8_n622()
+ fun_l9_n635
+end
+
+def fun_l8_n623()
+ fun_l9_n138
+end
+
+def fun_l8_n624()
+ fun_l9_n554
+end
+
+def fun_l8_n625()
+ fun_l9_n903
+end
+
+def fun_l8_n626()
+ fun_l9_n771
+end
+
+def fun_l8_n627()
+ fun_l9_n358
+end
+
+def fun_l8_n628()
+ fun_l9_n238
+end
+
+def fun_l8_n629()
+ fun_l9_n896
+end
+
+def fun_l8_n630()
+ fun_l9_n675
+end
+
+def fun_l8_n631()
+ fun_l9_n817
+end
+
+def fun_l8_n632()
+ fun_l9_n530
+end
+
+def fun_l8_n633()
+ fun_l9_n262
+end
+
+def fun_l8_n634()
+ fun_l9_n221
+end
+
+def fun_l8_n635()
+ fun_l9_n590
+end
+
+def fun_l8_n636()
+ fun_l9_n536
+end
+
+def fun_l8_n637()
+ fun_l9_n910
+end
+
+def fun_l8_n638()
+ fun_l9_n383
+end
+
+def fun_l8_n639()
+ fun_l9_n977
+end
+
+def fun_l8_n640()
+ fun_l9_n172
+end
+
+def fun_l8_n641()
+ fun_l9_n428
+end
+
+def fun_l8_n642()
+ fun_l9_n278
+end
+
+def fun_l8_n643()
+ fun_l9_n77
+end
+
+def fun_l8_n644()
+ fun_l9_n992
+end
+
+def fun_l8_n645()
+ fun_l9_n783
+end
+
+def fun_l8_n646()
+ fun_l9_n285
+end
+
+def fun_l8_n647()
+ fun_l9_n589
+end
+
+def fun_l8_n648()
+ fun_l9_n280
+end
+
+def fun_l8_n649()
+ fun_l9_n626
+end
+
+def fun_l8_n650()
+ fun_l9_n172
+end
+
+def fun_l8_n651()
+ fun_l9_n389
+end
+
+def fun_l8_n652()
+ fun_l9_n53
+end
+
+def fun_l8_n653()
+ fun_l9_n676
+end
+
+def fun_l8_n654()
+ fun_l9_n499
+end
+
+def fun_l8_n655()
+ fun_l9_n270
+end
+
+def fun_l8_n656()
+ fun_l9_n976
+end
+
+def fun_l8_n657()
+ fun_l9_n681
+end
+
+def fun_l8_n658()
+ fun_l9_n960
+end
+
+def fun_l8_n659()
+ fun_l9_n779
+end
+
+def fun_l8_n660()
+ fun_l9_n953
+end
+
+def fun_l8_n661()
+ fun_l9_n856
+end
+
+def fun_l8_n662()
+ fun_l9_n672
+end
+
+def fun_l8_n663()
+ fun_l9_n877
+end
+
+def fun_l8_n664()
+ fun_l9_n667
+end
+
+def fun_l8_n665()
+ fun_l9_n593
+end
+
+def fun_l8_n666()
+ fun_l9_n115
+end
+
+def fun_l8_n667()
+ fun_l9_n117
+end
+
+def fun_l8_n668()
+ fun_l9_n582
+end
+
+def fun_l8_n669()
+ fun_l9_n695
+end
+
+def fun_l8_n670()
+ fun_l9_n119
+end
+
+def fun_l8_n671()
+ fun_l9_n521
+end
+
+def fun_l8_n672()
+ fun_l9_n291
+end
+
+def fun_l8_n673()
+ fun_l9_n630
+end
+
+def fun_l8_n674()
+ fun_l9_n8
+end
+
+def fun_l8_n675()
+ fun_l9_n331
+end
+
+def fun_l8_n676()
+ fun_l9_n32
+end
+
+def fun_l8_n677()
+ fun_l9_n494
+end
+
+def fun_l8_n678()
+ fun_l9_n744
+end
+
+def fun_l8_n679()
+ fun_l9_n220
+end
+
+def fun_l8_n680()
+ fun_l9_n793
+end
+
+def fun_l8_n681()
+ fun_l9_n592
+end
+
+def fun_l8_n682()
+ fun_l9_n40
+end
+
+def fun_l8_n683()
+ fun_l9_n442
+end
+
+def fun_l8_n684()
+ fun_l9_n606
+end
+
+def fun_l8_n685()
+ fun_l9_n592
+end
+
+def fun_l8_n686()
+ fun_l9_n264
+end
+
+def fun_l8_n687()
+ fun_l9_n570
+end
+
+def fun_l8_n688()
+ fun_l9_n69
+end
+
+def fun_l8_n689()
+ fun_l9_n137
+end
+
+def fun_l8_n690()
+ fun_l9_n712
+end
+
+def fun_l8_n691()
+ fun_l9_n593
+end
+
+def fun_l8_n692()
+ fun_l9_n481
+end
+
+def fun_l8_n693()
+ fun_l9_n669
+end
+
+def fun_l8_n694()
+ fun_l9_n504
+end
+
+def fun_l8_n695()
+ fun_l9_n732
+end
+
+def fun_l8_n696()
+ fun_l9_n771
+end
+
+def fun_l8_n697()
+ fun_l9_n258
+end
+
+def fun_l8_n698()
+ fun_l9_n756
+end
+
+def fun_l8_n699()
+ fun_l9_n61
+end
+
+def fun_l8_n700()
+ fun_l9_n257
+end
+
+def fun_l8_n701()
+ fun_l9_n788
+end
+
+def fun_l8_n702()
+ fun_l9_n142
+end
+
+def fun_l8_n703()
+ fun_l9_n380
+end
+
+def fun_l8_n704()
+ fun_l9_n698
+end
+
+def fun_l8_n705()
+ fun_l9_n482
+end
+
+def fun_l8_n706()
+ fun_l9_n515
+end
+
+def fun_l8_n707()
+ fun_l9_n253
+end
+
+def fun_l8_n708()
+ fun_l9_n323
+end
+
+def fun_l8_n709()
+ fun_l9_n524
+end
+
+def fun_l8_n710()
+ fun_l9_n681
+end
+
+def fun_l8_n711()
+ fun_l9_n473
+end
+
+def fun_l8_n712()
+ fun_l9_n186
+end
+
+def fun_l8_n713()
+ fun_l9_n117
+end
+
+def fun_l8_n714()
+ fun_l9_n682
+end
+
+def fun_l8_n715()
+ fun_l9_n475
+end
+
+def fun_l8_n716()
+ fun_l9_n190
+end
+
+def fun_l8_n717()
+ fun_l9_n56
+end
+
+def fun_l8_n718()
+ fun_l9_n492
+end
+
+def fun_l8_n719()
+ fun_l9_n561
+end
+
+def fun_l8_n720()
+ fun_l9_n130
+end
+
+def fun_l8_n721()
+ fun_l9_n296
+end
+
+def fun_l8_n722()
+ fun_l9_n425
+end
+
+def fun_l8_n723()
+ fun_l9_n248
+end
+
+def fun_l8_n724()
+ fun_l9_n523
+end
+
+def fun_l8_n725()
+ fun_l9_n730
+end
+
+def fun_l8_n726()
+ fun_l9_n231
+end
+
+def fun_l8_n727()
+ fun_l9_n953
+end
+
+def fun_l8_n728()
+ fun_l9_n511
+end
+
+def fun_l8_n729()
+ fun_l9_n78
+end
+
+def fun_l8_n730()
+ fun_l9_n284
+end
+
+def fun_l8_n731()
+ fun_l9_n450
+end
+
+def fun_l8_n732()
+ fun_l9_n149
+end
+
+def fun_l8_n733()
+ fun_l9_n396
+end
+
+def fun_l8_n734()
+ fun_l9_n202
+end
+
+def fun_l8_n735()
+ fun_l9_n250
+end
+
+def fun_l8_n736()
+ fun_l9_n459
+end
+
+def fun_l8_n737()
+ fun_l9_n869
+end
+
+def fun_l8_n738()
+ fun_l9_n454
+end
+
+def fun_l8_n739()
+ fun_l9_n322
+end
+
+def fun_l8_n740()
+ fun_l9_n190
+end
+
+def fun_l8_n741()
+ fun_l9_n997
+end
+
+def fun_l8_n742()
+ fun_l9_n983
+end
+
+def fun_l8_n743()
+ fun_l9_n191
+end
+
+def fun_l8_n744()
+ fun_l9_n773
+end
+
+def fun_l8_n745()
+ fun_l9_n261
+end
+
+def fun_l8_n746()
+ fun_l9_n442
+end
+
+def fun_l8_n747()
+ fun_l9_n297
+end
+
+def fun_l8_n748()
+ fun_l9_n103
+end
+
+def fun_l8_n749()
+ fun_l9_n981
+end
+
+def fun_l8_n750()
+ fun_l9_n143
+end
+
+def fun_l8_n751()
+ fun_l9_n499
+end
+
+def fun_l8_n752()
+ fun_l9_n129
+end
+
+def fun_l8_n753()
+ fun_l9_n357
+end
+
+def fun_l8_n754()
+ fun_l9_n273
+end
+
+def fun_l8_n755()
+ fun_l9_n217
+end
+
+def fun_l8_n756()
+ fun_l9_n383
+end
+
+def fun_l8_n757()
+ fun_l9_n965
+end
+
+def fun_l8_n758()
+ fun_l9_n305
+end
+
+def fun_l8_n759()
+ fun_l9_n450
+end
+
+def fun_l8_n760()
+ fun_l9_n450
+end
+
+def fun_l8_n761()
+ fun_l9_n545
+end
+
+def fun_l8_n762()
+ fun_l9_n236
+end
+
+def fun_l8_n763()
+ fun_l9_n329
+end
+
+def fun_l8_n764()
+ fun_l9_n536
+end
+
+def fun_l8_n765()
+ fun_l9_n56
+end
+
+def fun_l8_n766()
+ fun_l9_n214
+end
+
+def fun_l8_n767()
+ fun_l9_n227
+end
+
+def fun_l8_n768()
+ fun_l9_n585
+end
+
+def fun_l8_n769()
+ fun_l9_n368
+end
+
+def fun_l8_n770()
+ fun_l9_n997
+end
+
+def fun_l8_n771()
+ fun_l9_n895
+end
+
+def fun_l8_n772()
+ fun_l9_n601
+end
+
+def fun_l8_n773()
+ fun_l9_n975
+end
+
+def fun_l8_n774()
+ fun_l9_n687
+end
+
+def fun_l8_n775()
+ fun_l9_n498
+end
+
+def fun_l8_n776()
+ fun_l9_n665
+end
+
+def fun_l8_n777()
+ fun_l9_n915
+end
+
+def fun_l8_n778()
+ fun_l9_n823
+end
+
+def fun_l8_n779()
+ fun_l9_n479
+end
+
+def fun_l8_n780()
+ fun_l9_n632
+end
+
+def fun_l8_n781()
+ fun_l9_n793
+end
+
+def fun_l8_n782()
+ fun_l9_n698
+end
+
+def fun_l8_n783()
+ fun_l9_n940
+end
+
+def fun_l8_n784()
+ fun_l9_n982
+end
+
+def fun_l8_n785()
+ fun_l9_n983
+end
+
+def fun_l8_n786()
+ fun_l9_n711
+end
+
+def fun_l8_n787()
+ fun_l9_n61
+end
+
+def fun_l8_n788()
+ fun_l9_n347
+end
+
+def fun_l8_n789()
+ fun_l9_n856
+end
+
+def fun_l8_n790()
+ fun_l9_n363
+end
+
+def fun_l8_n791()
+ fun_l9_n995
+end
+
+def fun_l8_n792()
+ fun_l9_n296
+end
+
+def fun_l8_n793()
+ fun_l9_n497
+end
+
+def fun_l8_n794()
+ fun_l9_n915
+end
+
+def fun_l8_n795()
+ fun_l9_n899
+end
+
+def fun_l8_n796()
+ fun_l9_n388
+end
+
+def fun_l8_n797()
+ fun_l9_n538
+end
+
+def fun_l8_n798()
+ fun_l9_n247
+end
+
+def fun_l8_n799()
+ fun_l9_n426
+end
+
+def fun_l8_n800()
+ fun_l9_n127
+end
+
+def fun_l8_n801()
+ fun_l9_n945
+end
+
+def fun_l8_n802()
+ fun_l9_n656
+end
+
+def fun_l8_n803()
+ fun_l9_n900
+end
+
+def fun_l8_n804()
+ fun_l9_n262
+end
+
+def fun_l8_n805()
+ fun_l9_n371
+end
+
+def fun_l8_n806()
+ fun_l9_n876
+end
+
+def fun_l8_n807()
+ fun_l9_n601
+end
+
+def fun_l8_n808()
+ fun_l9_n271
+end
+
+def fun_l8_n809()
+ fun_l9_n837
+end
+
+def fun_l8_n810()
+ fun_l9_n969
+end
+
+def fun_l8_n811()
+ fun_l9_n287
+end
+
+def fun_l8_n812()
+ fun_l9_n224
+end
+
+def fun_l8_n813()
+ fun_l9_n129
+end
+
+def fun_l8_n814()
+ fun_l9_n938
+end
+
+def fun_l8_n815()
+ fun_l9_n198
+end
+
+def fun_l8_n816()
+ fun_l9_n33
+end
+
+def fun_l8_n817()
+ fun_l9_n535
+end
+
+def fun_l8_n818()
+ fun_l9_n705
+end
+
+def fun_l8_n819()
+ fun_l9_n19
+end
+
+def fun_l8_n820()
+ fun_l9_n434
+end
+
+def fun_l8_n821()
+ fun_l9_n430
+end
+
+def fun_l8_n822()
+ fun_l9_n501
+end
+
+def fun_l8_n823()
+ fun_l9_n349
+end
+
+def fun_l8_n824()
+ fun_l9_n970
+end
+
+def fun_l8_n825()
+ fun_l9_n467
+end
+
+def fun_l8_n826()
+ fun_l9_n218
+end
+
+def fun_l8_n827()
+ fun_l9_n163
+end
+
+def fun_l8_n828()
+ fun_l9_n752
+end
+
+def fun_l8_n829()
+ fun_l9_n34
+end
+
+def fun_l8_n830()
+ fun_l9_n977
+end
+
+def fun_l8_n831()
+ fun_l9_n517
+end
+
+def fun_l8_n832()
+ fun_l9_n740
+end
+
+def fun_l8_n833()
+ fun_l9_n7
+end
+
+def fun_l8_n834()
+ fun_l9_n117
+end
+
+def fun_l8_n835()
+ fun_l9_n879
+end
+
+def fun_l8_n836()
+ fun_l9_n916
+end
+
+def fun_l8_n837()
+ fun_l9_n895
+end
+
+def fun_l8_n838()
+ fun_l9_n831
+end
+
+def fun_l8_n839()
+ fun_l9_n559
+end
+
+def fun_l8_n840()
+ fun_l9_n419
+end
+
+def fun_l8_n841()
+ fun_l9_n994
+end
+
+def fun_l8_n842()
+ fun_l9_n893
+end
+
+def fun_l8_n843()
+ fun_l9_n664
+end
+
+def fun_l8_n844()
+ fun_l9_n611
+end
+
+def fun_l8_n845()
+ fun_l9_n988
+end
+
+def fun_l8_n846()
+ fun_l9_n501
+end
+
+def fun_l8_n847()
+ fun_l9_n97
+end
+
+def fun_l8_n848()
+ fun_l9_n348
+end
+
+def fun_l8_n849()
+ fun_l9_n23
+end
+
+def fun_l8_n850()
+ fun_l9_n164
+end
+
+def fun_l8_n851()
+ fun_l9_n751
+end
+
+def fun_l8_n852()
+ fun_l9_n544
+end
+
+def fun_l8_n853()
+ fun_l9_n944
+end
+
+def fun_l8_n854()
+ fun_l9_n25
+end
+
+def fun_l8_n855()
+ fun_l9_n125
+end
+
+def fun_l8_n856()
+ fun_l9_n720
+end
+
+def fun_l8_n857()
+ fun_l9_n298
+end
+
+def fun_l8_n858()
+ fun_l9_n7
+end
+
+def fun_l8_n859()
+ fun_l9_n885
+end
+
+def fun_l8_n860()
+ fun_l9_n785
+end
+
+def fun_l8_n861()
+ fun_l9_n653
+end
+
+def fun_l8_n862()
+ fun_l9_n206
+end
+
+def fun_l8_n863()
+ fun_l9_n460
+end
+
+def fun_l8_n864()
+ fun_l9_n361
+end
+
+def fun_l8_n865()
+ fun_l9_n782
+end
+
+def fun_l8_n866()
+ fun_l9_n965
+end
+
+def fun_l8_n867()
+ fun_l9_n653
+end
+
+def fun_l8_n868()
+ fun_l9_n757
+end
+
+def fun_l8_n869()
+ fun_l9_n892
+end
+
+def fun_l8_n870()
+ fun_l9_n939
+end
+
+def fun_l8_n871()
+ fun_l9_n105
+end
+
+def fun_l8_n872()
+ fun_l9_n334
+end
+
+def fun_l8_n873()
+ fun_l9_n120
+end
+
+def fun_l8_n874()
+ fun_l9_n530
+end
+
+def fun_l8_n875()
+ fun_l9_n777
+end
+
+def fun_l8_n876()
+ fun_l9_n546
+end
+
+def fun_l8_n877()
+ fun_l9_n235
+end
+
+def fun_l8_n878()
+ fun_l9_n647
+end
+
+def fun_l8_n879()
+ fun_l9_n813
+end
+
+def fun_l8_n880()
+ fun_l9_n756
+end
+
+def fun_l8_n881()
+ fun_l9_n202
+end
+
+def fun_l8_n882()
+ fun_l9_n58
+end
+
+def fun_l8_n883()
+ fun_l9_n895
+end
+
+def fun_l8_n884()
+ fun_l9_n556
+end
+
+def fun_l8_n885()
+ fun_l9_n974
+end
+
+def fun_l8_n886()
+ fun_l9_n671
+end
+
+def fun_l8_n887()
+ fun_l9_n700
+end
+
+def fun_l8_n888()
+ fun_l9_n788
+end
+
+def fun_l8_n889()
+ fun_l9_n568
+end
+
+def fun_l8_n890()
+ fun_l9_n431
+end
+
+def fun_l8_n891()
+ fun_l9_n517
+end
+
+def fun_l8_n892()
+ fun_l9_n330
+end
+
+def fun_l8_n893()
+ fun_l9_n573
+end
+
+def fun_l8_n894()
+ fun_l9_n510
+end
+
+def fun_l8_n895()
+ fun_l9_n784
+end
+
+def fun_l8_n896()
+ fun_l9_n75
+end
+
+def fun_l8_n897()
+ fun_l9_n314
+end
+
+def fun_l8_n898()
+ fun_l9_n703
+end
+
+def fun_l8_n899()
+ fun_l9_n740
+end
+
+def fun_l8_n900()
+ fun_l9_n806
+end
+
+def fun_l8_n901()
+ fun_l9_n208
+end
+
+def fun_l8_n902()
+ fun_l9_n678
+end
+
+def fun_l8_n903()
+ fun_l9_n443
+end
+
+def fun_l8_n904()
+ fun_l9_n285
+end
+
+def fun_l8_n905()
+ fun_l9_n840
+end
+
+def fun_l8_n906()
+ fun_l9_n896
+end
+
+def fun_l8_n907()
+ fun_l9_n253
+end
+
+def fun_l8_n908()
+ fun_l9_n786
+end
+
+def fun_l8_n909()
+ fun_l9_n364
+end
+
+def fun_l8_n910()
+ fun_l9_n314
+end
+
+def fun_l8_n911()
+ fun_l9_n178
+end
+
+def fun_l8_n912()
+ fun_l9_n14
+end
+
+def fun_l8_n913()
+ fun_l9_n594
+end
+
+def fun_l8_n914()
+ fun_l9_n524
+end
+
+def fun_l8_n915()
+ fun_l9_n449
+end
+
+def fun_l8_n916()
+ fun_l9_n970
+end
+
+def fun_l8_n917()
+ fun_l9_n418
+end
+
+def fun_l8_n918()
+ fun_l9_n978
+end
+
+def fun_l8_n919()
+ fun_l9_n266
+end
+
+def fun_l8_n920()
+ fun_l9_n384
+end
+
+def fun_l8_n921()
+ fun_l9_n806
+end
+
+def fun_l8_n922()
+ fun_l9_n99
+end
+
+def fun_l8_n923()
+ fun_l9_n116
+end
+
+def fun_l8_n924()
+ fun_l9_n494
+end
+
+def fun_l8_n925()
+ fun_l9_n891
+end
+
+def fun_l8_n926()
+ fun_l9_n49
+end
+
+def fun_l8_n927()
+ fun_l9_n87
+end
+
+def fun_l8_n928()
+ fun_l9_n502
+end
+
+def fun_l8_n929()
+ fun_l9_n528
+end
+
+def fun_l8_n930()
+ fun_l9_n403
+end
+
+def fun_l8_n931()
+ fun_l9_n385
+end
+
+def fun_l8_n932()
+ fun_l9_n965
+end
+
+def fun_l8_n933()
+ fun_l9_n658
+end
+
+def fun_l8_n934()
+ fun_l9_n316
+end
+
+def fun_l8_n935()
+ fun_l9_n441
+end
+
+def fun_l8_n936()
+ fun_l9_n453
+end
+
+def fun_l8_n937()
+ fun_l9_n957
+end
+
+def fun_l8_n938()
+ fun_l9_n360
+end
+
+def fun_l8_n939()
+ fun_l9_n150
+end
+
+def fun_l8_n940()
+ fun_l9_n934
+end
+
+def fun_l8_n941()
+ fun_l9_n676
+end
+
+def fun_l8_n942()
+ fun_l9_n943
+end
+
+def fun_l8_n943()
+ fun_l9_n824
+end
+
+def fun_l8_n944()
+ fun_l9_n7
+end
+
+def fun_l8_n945()
+ fun_l9_n640
+end
+
+def fun_l8_n946()
+ fun_l9_n18
+end
+
+def fun_l8_n947()
+ fun_l9_n483
+end
+
+def fun_l8_n948()
+ fun_l9_n495
+end
+
+def fun_l8_n949()
+ fun_l9_n711
+end
+
+def fun_l8_n950()
+ fun_l9_n382
+end
+
+def fun_l8_n951()
+ fun_l9_n479
+end
+
+def fun_l8_n952()
+ fun_l9_n920
+end
+
+def fun_l8_n953()
+ fun_l9_n477
+end
+
+def fun_l8_n954()
+ fun_l9_n411
+end
+
+def fun_l8_n955()
+ fun_l9_n801
+end
+
+def fun_l8_n956()
+ fun_l9_n630
+end
+
+def fun_l8_n957()
+ fun_l9_n172
+end
+
+def fun_l8_n958()
+ fun_l9_n104
+end
+
+def fun_l8_n959()
+ fun_l9_n197
+end
+
+def fun_l8_n960()
+ fun_l9_n231
+end
+
+def fun_l8_n961()
+ fun_l9_n769
+end
+
+def fun_l8_n962()
+ fun_l9_n293
+end
+
+def fun_l8_n963()
+ fun_l9_n580
+end
+
+def fun_l8_n964()
+ fun_l9_n345
+end
+
+def fun_l8_n965()
+ fun_l9_n199
+end
+
+def fun_l8_n966()
+ fun_l9_n899
+end
+
+def fun_l8_n967()
+ fun_l9_n68
+end
+
+def fun_l8_n968()
+ fun_l9_n954
+end
+
+def fun_l8_n969()
+ fun_l9_n205
+end
+
+def fun_l8_n970()
+ fun_l9_n697
+end
+
+def fun_l8_n971()
+ fun_l9_n445
+end
+
+def fun_l8_n972()
+ fun_l9_n294
+end
+
+def fun_l8_n973()
+ fun_l9_n96
+end
+
+def fun_l8_n974()
+ fun_l9_n798
+end
+
+def fun_l8_n975()
+ fun_l9_n509
+end
+
+def fun_l8_n976()
+ fun_l9_n918
+end
+
+def fun_l8_n977()
+ fun_l9_n624
+end
+
+def fun_l8_n978()
+ fun_l9_n798
+end
+
+def fun_l8_n979()
+ fun_l9_n267
+end
+
+def fun_l8_n980()
+ fun_l9_n977
+end
+
+def fun_l8_n981()
+ fun_l9_n128
+end
+
+def fun_l8_n982()
+ fun_l9_n759
+end
+
+def fun_l8_n983()
+ fun_l9_n999
+end
+
+def fun_l8_n984()
+ fun_l9_n908
+end
+
+def fun_l8_n985()
+ fun_l9_n713
+end
+
+def fun_l8_n986()
+ fun_l9_n423
+end
+
+def fun_l8_n987()
+ fun_l9_n789
+end
+
+def fun_l8_n988()
+ fun_l9_n342
+end
+
+def fun_l8_n989()
+ fun_l9_n963
+end
+
+def fun_l8_n990()
+ fun_l9_n393
+end
+
+def fun_l8_n991()
+ fun_l9_n446
+end
+
+def fun_l8_n992()
+ fun_l9_n62
+end
+
+def fun_l8_n993()
+ fun_l9_n567
+end
+
+def fun_l8_n994()
+ fun_l9_n99
+end
+
+def fun_l8_n995()
+ fun_l9_n6
+end
+
+def fun_l8_n996()
+ fun_l9_n582
+end
+
+def fun_l8_n997()
+ fun_l9_n714
+end
+
+def fun_l8_n998()
+ fun_l9_n440
+end
+
+def fun_l8_n999()
+ fun_l9_n89
+end
+
+def fun_l9_n0()
+ fun_l10_n441
+end
+
+def fun_l9_n1()
+ fun_l10_n18
+end
+
+def fun_l9_n2()
+ fun_l10_n406
+end
+
+def fun_l9_n3()
+ fun_l10_n623
+end
+
+def fun_l9_n4()
+ fun_l10_n323
+end
+
+def fun_l9_n5()
+ fun_l10_n702
+end
+
+def fun_l9_n6()
+ fun_l10_n46
+end
+
+def fun_l9_n7()
+ fun_l10_n519
+end
+
+def fun_l9_n8()
+ fun_l10_n572
+end
+
+def fun_l9_n9()
+ fun_l10_n670
+end
+
+def fun_l9_n10()
+ fun_l10_n917
+end
+
+def fun_l9_n11()
+ fun_l10_n160
+end
+
+def fun_l9_n12()
+ fun_l10_n153
+end
+
+def fun_l9_n13()
+ fun_l10_n73
+end
+
+def fun_l9_n14()
+ fun_l10_n775
+end
+
+def fun_l9_n15()
+ fun_l10_n97
+end
+
+def fun_l9_n16()
+ fun_l10_n307
+end
+
+def fun_l9_n17()
+ fun_l10_n630
+end
+
+def fun_l9_n18()
+ fun_l10_n446
+end
+
+def fun_l9_n19()
+ fun_l10_n798
+end
+
+def fun_l9_n20()
+ fun_l10_n633
+end
+
+def fun_l9_n21()
+ fun_l10_n83
+end
+
+def fun_l9_n22()
+ fun_l10_n373
+end
+
+def fun_l9_n23()
+ fun_l10_n777
+end
+
+def fun_l9_n24()
+ fun_l10_n47
+end
+
+def fun_l9_n25()
+ fun_l10_n533
+end
+
+def fun_l9_n26()
+ fun_l10_n780
+end
+
+def fun_l9_n27()
+ fun_l10_n220
+end
+
+def fun_l9_n28()
+ fun_l10_n777
+end
+
+def fun_l9_n29()
+ fun_l10_n71
+end
+
+def fun_l9_n30()
+ fun_l10_n590
+end
+
+def fun_l9_n31()
+ fun_l10_n544
+end
+
+def fun_l9_n32()
+ fun_l10_n173
+end
+
+def fun_l9_n33()
+ fun_l10_n464
+end
+
+def fun_l9_n34()
+ fun_l10_n267
+end
+
+def fun_l9_n35()
+ fun_l10_n152
+end
+
+def fun_l9_n36()
+ fun_l10_n330
+end
+
+def fun_l9_n37()
+ fun_l10_n267
+end
+
+def fun_l9_n38()
+ fun_l10_n499
+end
+
+def fun_l9_n39()
+ fun_l10_n213
+end
+
+def fun_l9_n40()
+ fun_l10_n825
+end
+
+def fun_l9_n41()
+ fun_l10_n567
+end
+
+def fun_l9_n42()
+ fun_l10_n112
+end
+
+def fun_l9_n43()
+ fun_l10_n483
+end
+
+def fun_l9_n44()
+ fun_l10_n52
+end
+
+def fun_l9_n45()
+ fun_l10_n564
+end
+
+def fun_l9_n46()
+ fun_l10_n667
+end
+
+def fun_l9_n47()
+ fun_l10_n965
+end
+
+def fun_l9_n48()
+ fun_l10_n49
+end
+
+def fun_l9_n49()
+ fun_l10_n206
+end
+
+def fun_l9_n50()
+ fun_l10_n904
+end
+
+def fun_l9_n51()
+ fun_l10_n161
+end
+
+def fun_l9_n52()
+ fun_l10_n739
+end
+
+def fun_l9_n53()
+ fun_l10_n62
+end
+
+def fun_l9_n54()
+ fun_l10_n881
+end
+
+def fun_l9_n55()
+ fun_l10_n392
+end
+
+def fun_l9_n56()
+ fun_l10_n560
+end
+
+def fun_l9_n57()
+ fun_l10_n202
+end
+
+def fun_l9_n58()
+ fun_l10_n486
+end
+
+def fun_l9_n59()
+ fun_l10_n347
+end
+
+def fun_l9_n60()
+ fun_l10_n593
+end
+
+def fun_l9_n61()
+ fun_l10_n542
+end
+
+def fun_l9_n62()
+ fun_l10_n914
+end
+
+def fun_l9_n63()
+ fun_l10_n956
+end
+
+def fun_l9_n64()
+ fun_l10_n337
+end
+
+def fun_l9_n65()
+ fun_l10_n383
+end
+
+def fun_l9_n66()
+ fun_l10_n332
+end
+
+def fun_l9_n67()
+ fun_l10_n610
+end
+
+def fun_l9_n68()
+ fun_l10_n396
+end
+
+def fun_l9_n69()
+ fun_l10_n847
+end
+
+def fun_l9_n70()
+ fun_l10_n473
+end
+
+def fun_l9_n71()
+ fun_l10_n657
+end
+
+def fun_l9_n72()
+ fun_l10_n933
+end
+
+def fun_l9_n73()
+ fun_l10_n384
+end
+
+def fun_l9_n74()
+ fun_l10_n275
+end
+
+def fun_l9_n75()
+ fun_l10_n90
+end
+
+def fun_l9_n76()
+ fun_l10_n841
+end
+
+def fun_l9_n77()
+ fun_l10_n326
+end
+
+def fun_l9_n78()
+ fun_l10_n275
+end
+
+def fun_l9_n79()
+ fun_l10_n153
+end
+
+def fun_l9_n80()
+ fun_l10_n651
+end
+
+def fun_l9_n81()
+ fun_l10_n724
+end
+
+def fun_l9_n82()
+ fun_l10_n204
+end
+
+def fun_l9_n83()
+ fun_l10_n389
+end
+
+def fun_l9_n84()
+ fun_l10_n583
+end
+
+def fun_l9_n85()
+ fun_l10_n938
+end
+
+def fun_l9_n86()
+ fun_l10_n433
+end
+
+def fun_l9_n87()
+ fun_l10_n917
+end
+
+def fun_l9_n88()
+ fun_l10_n147
+end
+
+def fun_l9_n89()
+ fun_l10_n578
+end
+
+def fun_l9_n90()
+ fun_l10_n760
+end
+
+def fun_l9_n91()
+ fun_l10_n891
+end
+
+def fun_l9_n92()
+ fun_l10_n676
+end
+
+def fun_l9_n93()
+ fun_l10_n130
+end
+
+def fun_l9_n94()
+ fun_l10_n506
+end
+
+def fun_l9_n95()
+ fun_l10_n67
+end
+
+def fun_l9_n96()
+ fun_l10_n98
+end
+
+def fun_l9_n97()
+ fun_l10_n788
+end
+
+def fun_l9_n98()
+ fun_l10_n151
+end
+
+def fun_l9_n99()
+ fun_l10_n170
+end
+
+def fun_l9_n100()
+ fun_l10_n853
+end
+
+def fun_l9_n101()
+ fun_l10_n76
+end
+
+def fun_l9_n102()
+ fun_l10_n577
+end
+
+def fun_l9_n103()
+ fun_l10_n703
+end
+
+def fun_l9_n104()
+ fun_l10_n436
+end
+
+def fun_l9_n105()
+ fun_l10_n983
+end
+
+def fun_l9_n106()
+ fun_l10_n715
+end
+
+def fun_l9_n107()
+ fun_l10_n703
+end
+
+def fun_l9_n108()
+ fun_l10_n986
+end
+
+def fun_l9_n109()
+ fun_l10_n328
+end
+
+def fun_l9_n110()
+ fun_l10_n719
+end
+
+def fun_l9_n111()
+ fun_l10_n885
+end
+
+def fun_l9_n112()
+ fun_l10_n364
+end
+
+def fun_l9_n113()
+ fun_l10_n554
+end
+
+def fun_l9_n114()
+ fun_l10_n909
+end
+
+def fun_l9_n115()
+ fun_l10_n718
+end
+
+def fun_l9_n116()
+ fun_l10_n866
+end
+
+def fun_l9_n117()
+ fun_l10_n592
+end
+
+def fun_l9_n118()
+ fun_l10_n954
+end
+
+def fun_l9_n119()
+ fun_l10_n204
+end
+
+def fun_l9_n120()
+ fun_l10_n565
+end
+
+def fun_l9_n121()
+ fun_l10_n982
+end
+
+def fun_l9_n122()
+ fun_l10_n64
+end
+
+def fun_l9_n123()
+ fun_l10_n851
+end
+
+def fun_l9_n124()
+ fun_l10_n615
+end
+
+def fun_l9_n125()
+ fun_l10_n141
+end
+
+def fun_l9_n126()
+ fun_l10_n663
+end
+
+def fun_l9_n127()
+ fun_l10_n625
+end
+
+def fun_l9_n128()
+ fun_l10_n183
+end
+
+def fun_l9_n129()
+ fun_l10_n433
+end
+
+def fun_l9_n130()
+ fun_l10_n620
+end
+
+def fun_l9_n131()
+ fun_l10_n251
+end
+
+def fun_l9_n132()
+ fun_l10_n726
+end
+
+def fun_l9_n133()
+ fun_l10_n871
+end
+
+def fun_l9_n134()
+ fun_l10_n835
+end
+
+def fun_l9_n135()
+ fun_l10_n643
+end
+
+def fun_l9_n136()
+ fun_l10_n342
+end
+
+def fun_l9_n137()
+ fun_l10_n13
+end
+
+def fun_l9_n138()
+ fun_l10_n173
+end
+
+def fun_l9_n139()
+ fun_l10_n555
+end
+
+def fun_l9_n140()
+ fun_l10_n723
+end
+
+def fun_l9_n141()
+ fun_l10_n269
+end
+
+def fun_l9_n142()
+ fun_l10_n127
+end
+
+def fun_l9_n143()
+ fun_l10_n238
+end
+
+def fun_l9_n144()
+ fun_l10_n962
+end
+
+def fun_l9_n145()
+ fun_l10_n259
+end
+
+def fun_l9_n146()
+ fun_l10_n813
+end
+
+def fun_l9_n147()
+ fun_l10_n506
+end
+
+def fun_l9_n148()
+ fun_l10_n38
+end
+
+def fun_l9_n149()
+ fun_l10_n465
+end
+
+def fun_l9_n150()
+ fun_l10_n602
+end
+
+def fun_l9_n151()
+ fun_l10_n857
+end
+
+def fun_l9_n152()
+ fun_l10_n346
+end
+
+def fun_l9_n153()
+ fun_l10_n611
+end
+
+def fun_l9_n154()
+ fun_l10_n696
+end
+
+def fun_l9_n155()
+ fun_l10_n93
+end
+
+def fun_l9_n156()
+ fun_l10_n874
+end
+
+def fun_l9_n157()
+ fun_l10_n750
+end
+
+def fun_l9_n158()
+ fun_l10_n339
+end
+
+def fun_l9_n159()
+ fun_l10_n395
+end
+
+def fun_l9_n160()
+ fun_l10_n838
+end
+
+def fun_l9_n161()
+ fun_l10_n620
+end
+
+def fun_l9_n162()
+ fun_l10_n934
+end
+
+def fun_l9_n163()
+ fun_l10_n908
+end
+
+def fun_l9_n164()
+ fun_l10_n603
+end
+
+def fun_l9_n165()
+ fun_l10_n906
+end
+
+def fun_l9_n166()
+ fun_l10_n718
+end
+
+def fun_l9_n167()
+ fun_l10_n514
+end
+
+def fun_l9_n168()
+ fun_l10_n766
+end
+
+def fun_l9_n169()
+ fun_l10_n179
+end
+
+def fun_l9_n170()
+ fun_l10_n290
+end
+
+def fun_l9_n171()
+ fun_l10_n833
+end
+
+def fun_l9_n172()
+ fun_l10_n420
+end
+
+def fun_l9_n173()
+ fun_l10_n605
+end
+
+def fun_l9_n174()
+ fun_l10_n356
+end
+
+def fun_l9_n175()
+ fun_l10_n744
+end
+
+def fun_l9_n176()
+ fun_l10_n715
+end
+
+def fun_l9_n177()
+ fun_l10_n725
+end
+
+def fun_l9_n178()
+ fun_l10_n434
+end
+
+def fun_l9_n179()
+ fun_l10_n127
+end
+
+def fun_l9_n180()
+ fun_l10_n982
+end
+
+def fun_l9_n181()
+ fun_l10_n377
+end
+
+def fun_l9_n182()
+ fun_l10_n302
+end
+
+def fun_l9_n183()
+ fun_l10_n472
+end
+
+def fun_l9_n184()
+ fun_l10_n850
+end
+
+def fun_l9_n185()
+ fun_l10_n900
+end
+
+def fun_l9_n186()
+ fun_l10_n581
+end
+
+def fun_l9_n187()
+ fun_l10_n628
+end
+
+def fun_l9_n188()
+ fun_l10_n453
+end
+
+def fun_l9_n189()
+ fun_l10_n31
+end
+
+def fun_l9_n190()
+ fun_l10_n257
+end
+
+def fun_l9_n191()
+ fun_l10_n416
+end
+
+def fun_l9_n192()
+ fun_l10_n399
+end
+
+def fun_l9_n193()
+ fun_l10_n113
+end
+
+def fun_l9_n194()
+ fun_l10_n217
+end
+
+def fun_l9_n195()
+ fun_l10_n975
+end
+
+def fun_l9_n196()
+ fun_l10_n525
+end
+
+def fun_l9_n197()
+ fun_l10_n534
+end
+
+def fun_l9_n198()
+ fun_l10_n986
+end
+
+def fun_l9_n199()
+ fun_l10_n992
+end
+
+def fun_l9_n200()
+ fun_l10_n579
+end
+
+def fun_l9_n201()
+ fun_l10_n776
+end
+
+def fun_l9_n202()
+ fun_l10_n102
+end
+
+def fun_l9_n203()
+ fun_l10_n287
+end
+
+def fun_l9_n204()
+ fun_l10_n11
+end
+
+def fun_l9_n205()
+ fun_l10_n522
+end
+
+def fun_l9_n206()
+ fun_l10_n777
+end
+
+def fun_l9_n207()
+ fun_l10_n984
+end
+
+def fun_l9_n208()
+ fun_l10_n369
+end
+
+def fun_l9_n209()
+ fun_l10_n889
+end
+
+def fun_l9_n210()
+ fun_l10_n619
+end
+
+def fun_l9_n211()
+ fun_l10_n878
+end
+
+def fun_l9_n212()
+ fun_l10_n540
+end
+
+def fun_l9_n213()
+ fun_l10_n285
+end
+
+def fun_l9_n214()
+ fun_l10_n627
+end
+
+def fun_l9_n215()
+ fun_l10_n196
+end
+
+def fun_l9_n216()
+ fun_l10_n166
+end
+
+def fun_l9_n217()
+ fun_l10_n648
+end
+
+def fun_l9_n218()
+ fun_l10_n980
+end
+
+def fun_l9_n219()
+ fun_l10_n801
+end
+
+def fun_l9_n220()
+ fun_l10_n949
+end
+
+def fun_l9_n221()
+ fun_l10_n985
+end
+
+def fun_l9_n222()
+ fun_l10_n384
+end
+
+def fun_l9_n223()
+ fun_l10_n840
+end
+
+def fun_l9_n224()
+ fun_l10_n80
+end
+
+def fun_l9_n225()
+ fun_l10_n79
+end
+
+def fun_l9_n226()
+ fun_l10_n630
+end
+
+def fun_l9_n227()
+ fun_l10_n20
+end
+
+def fun_l9_n228()
+ fun_l10_n224
+end
+
+def fun_l9_n229()
+ fun_l10_n480
+end
+
+def fun_l9_n230()
+ fun_l10_n145
+end
+
+def fun_l9_n231()
+ fun_l10_n923
+end
+
+def fun_l9_n232()
+ fun_l10_n794
+end
+
+def fun_l9_n233()
+ fun_l10_n271
+end
+
+def fun_l9_n234()
+ fun_l10_n124
+end
+
+def fun_l9_n235()
+ fun_l10_n925
+end
+
+def fun_l9_n236()
+ fun_l10_n938
+end
+
+def fun_l9_n237()
+ fun_l10_n470
+end
+
+def fun_l9_n238()
+ fun_l10_n557
+end
+
+def fun_l9_n239()
+ fun_l10_n152
+end
+
+def fun_l9_n240()
+ fun_l10_n200
+end
+
+def fun_l9_n241()
+ fun_l10_n110
+end
+
+def fun_l9_n242()
+ fun_l10_n329
+end
+
+def fun_l9_n243()
+ fun_l10_n2
+end
+
+def fun_l9_n244()
+ fun_l10_n432
+end
+
+def fun_l9_n245()
+ fun_l10_n175
+end
+
+def fun_l9_n246()
+ fun_l10_n33
+end
+
+def fun_l9_n247()
+ fun_l10_n441
+end
+
+def fun_l9_n248()
+ fun_l10_n54
+end
+
+def fun_l9_n249()
+ fun_l10_n408
+end
+
+def fun_l9_n250()
+ fun_l10_n911
+end
+
+def fun_l9_n251()
+ fun_l10_n100
+end
+
+def fun_l9_n252()
+ fun_l10_n645
+end
+
+def fun_l9_n253()
+ fun_l10_n826
+end
+
+def fun_l9_n254()
+ fun_l10_n319
+end
+
+def fun_l9_n255()
+ fun_l10_n735
+end
+
+def fun_l9_n256()
+ fun_l10_n6
+end
+
+def fun_l9_n257()
+ fun_l10_n428
+end
+
+def fun_l9_n258()
+ fun_l10_n511
+end
+
+def fun_l9_n259()
+ fun_l10_n47
+end
+
+def fun_l9_n260()
+ fun_l10_n985
+end
+
+def fun_l9_n261()
+ fun_l10_n278
+end
+
+def fun_l9_n262()
+ fun_l10_n839
+end
+
+def fun_l9_n263()
+ fun_l10_n948
+end
+
+def fun_l9_n264()
+ fun_l10_n572
+end
+
+def fun_l9_n265()
+ fun_l10_n864
+end
+
+def fun_l9_n266()
+ fun_l10_n159
+end
+
+def fun_l9_n267()
+ fun_l10_n870
+end
+
+def fun_l9_n268()
+ fun_l10_n194
+end
+
+def fun_l9_n269()
+ fun_l10_n424
+end
+
+def fun_l9_n270()
+ fun_l10_n238
+end
+
+def fun_l9_n271()
+ fun_l10_n804
+end
+
+def fun_l9_n272()
+ fun_l10_n945
+end
+
+def fun_l9_n273()
+ fun_l10_n181
+end
+
+def fun_l9_n274()
+ fun_l10_n90
+end
+
+def fun_l9_n275()
+ fun_l10_n552
+end
+
+def fun_l9_n276()
+ fun_l10_n690
+end
+
+def fun_l9_n277()
+ fun_l10_n416
+end
+
+def fun_l9_n278()
+ fun_l10_n977
+end
+
+def fun_l9_n279()
+ fun_l10_n930
+end
+
+def fun_l9_n280()
+ fun_l10_n77
+end
+
+def fun_l9_n281()
+ fun_l10_n102
+end
+
+def fun_l9_n282()
+ fun_l10_n263
+end
+
+def fun_l9_n283()
+ fun_l10_n973
+end
+
+def fun_l9_n284()
+ fun_l10_n119
+end
+
+def fun_l9_n285()
+ fun_l10_n102
+end
+
+def fun_l9_n286()
+ fun_l10_n744
+end
+
+def fun_l9_n287()
+ fun_l10_n430
+end
+
+def fun_l9_n288()
+ fun_l10_n465
+end
+
+def fun_l9_n289()
+ fun_l10_n54
+end
+
+def fun_l9_n290()
+ fun_l10_n191
+end
+
+def fun_l9_n291()
+ fun_l10_n781
+end
+
+def fun_l9_n292()
+ fun_l10_n158
+end
+
+def fun_l9_n293()
+ fun_l10_n512
+end
+
+def fun_l9_n294()
+ fun_l10_n396
+end
+
+def fun_l9_n295()
+ fun_l10_n814
+end
+
+def fun_l9_n296()
+ fun_l10_n509
+end
+
+def fun_l9_n297()
+ fun_l10_n340
+end
+
+def fun_l9_n298()
+ fun_l10_n338
+end
+
+def fun_l9_n299()
+ fun_l10_n822
+end
+
+def fun_l9_n300()
+ fun_l10_n64
+end
+
+def fun_l9_n301()
+ fun_l10_n867
+end
+
+def fun_l9_n302()
+ fun_l10_n924
+end
+
+def fun_l9_n303()
+ fun_l10_n628
+end
+
+def fun_l9_n304()
+ fun_l10_n929
+end
+
+def fun_l9_n305()
+ fun_l10_n874
+end
+
+def fun_l9_n306()
+ fun_l10_n411
+end
+
+def fun_l9_n307()
+ fun_l10_n836
+end
+
+def fun_l9_n308()
+ fun_l10_n574
+end
+
+def fun_l9_n309()
+ fun_l10_n865
+end
+
+def fun_l9_n310()
+ fun_l10_n992
+end
+
+def fun_l9_n311()
+ fun_l10_n75
+end
+
+def fun_l9_n312()
+ fun_l10_n221
+end
+
+def fun_l9_n313()
+ fun_l10_n439
+end
+
+def fun_l9_n314()
+ fun_l10_n826
+end
+
+def fun_l9_n315()
+ fun_l10_n589
+end
+
+def fun_l9_n316()
+ fun_l10_n123
+end
+
+def fun_l9_n317()
+ fun_l10_n641
+end
+
+def fun_l9_n318()
+ fun_l10_n556
+end
+
+def fun_l9_n319()
+ fun_l10_n92
+end
+
+def fun_l9_n320()
+ fun_l10_n728
+end
+
+def fun_l9_n321()
+ fun_l10_n503
+end
+
+def fun_l9_n322()
+ fun_l10_n626
+end
+
+def fun_l9_n323()
+ fun_l10_n416
+end
+
+def fun_l9_n324()
+ fun_l10_n331
+end
+
+def fun_l9_n325()
+ fun_l10_n330
+end
+
+def fun_l9_n326()
+ fun_l10_n387
+end
+
+def fun_l9_n327()
+ fun_l10_n337
+end
+
+def fun_l9_n328()
+ fun_l10_n652
+end
+
+def fun_l9_n329()
+ fun_l10_n654
+end
+
+def fun_l9_n330()
+ fun_l10_n413
+end
+
+def fun_l9_n331()
+ fun_l10_n763
+end
+
+def fun_l9_n332()
+ fun_l10_n962
+end
+
+def fun_l9_n333()
+ fun_l10_n944
+end
+
+def fun_l9_n334()
+ fun_l10_n655
+end
+
+def fun_l9_n335()
+ fun_l10_n907
+end
+
+def fun_l9_n336()
+ fun_l10_n293
+end
+
+def fun_l9_n337()
+ fun_l10_n684
+end
+
+def fun_l9_n338()
+ fun_l10_n566
+end
+
+def fun_l9_n339()
+ fun_l10_n547
+end
+
+def fun_l9_n340()
+ fun_l10_n112
+end
+
+def fun_l9_n341()
+ fun_l10_n854
+end
+
+def fun_l9_n342()
+ fun_l10_n336
+end
+
+def fun_l9_n343()
+ fun_l10_n473
+end
+
+def fun_l9_n344()
+ fun_l10_n485
+end
+
+def fun_l9_n345()
+ fun_l10_n588
+end
+
+def fun_l9_n346()
+ fun_l10_n889
+end
+
+def fun_l9_n347()
+ fun_l10_n523
+end
+
+def fun_l9_n348()
+ fun_l10_n8
+end
+
+def fun_l9_n349()
+ fun_l10_n368
+end
+
+def fun_l9_n350()
+ fun_l10_n636
+end
+
+def fun_l9_n351()
+ fun_l10_n879
+end
+
+def fun_l9_n352()
+ fun_l10_n524
+end
+
+def fun_l9_n353()
+ fun_l10_n209
+end
+
+def fun_l9_n354()
+ fun_l10_n271
+end
+
+def fun_l9_n355()
+ fun_l10_n90
+end
+
+def fun_l9_n356()
+ fun_l10_n698
+end
+
+def fun_l9_n357()
+ fun_l10_n268
+end
+
+def fun_l9_n358()
+ fun_l10_n948
+end
+
+def fun_l9_n359()
+ fun_l10_n847
+end
+
+def fun_l9_n360()
+ fun_l10_n985
+end
+
+def fun_l9_n361()
+ fun_l10_n978
+end
+
+def fun_l9_n362()
+ fun_l10_n808
+end
+
+def fun_l9_n363()
+ fun_l10_n796
+end
+
+def fun_l9_n364()
+ fun_l10_n810
+end
+
+def fun_l9_n365()
+ fun_l10_n665
+end
+
+def fun_l9_n366()
+ fun_l10_n765
+end
+
+def fun_l9_n367()
+ fun_l10_n74
+end
+
+def fun_l9_n368()
+ fun_l10_n330
+end
+
+def fun_l9_n369()
+ fun_l10_n125
+end
+
+def fun_l9_n370()
+ fun_l10_n814
+end
+
+def fun_l9_n371()
+ fun_l10_n498
+end
+
+def fun_l9_n372()
+ fun_l10_n783
+end
+
+def fun_l9_n373()
+ fun_l10_n169
+end
+
+def fun_l9_n374()
+ fun_l10_n490
+end
+
+def fun_l9_n375()
+ fun_l10_n923
+end
+
+def fun_l9_n376()
+ fun_l10_n63
+end
+
+def fun_l9_n377()
+ fun_l10_n687
+end
+
+def fun_l9_n378()
+ fun_l10_n603
+end
+
+def fun_l9_n379()
+ fun_l10_n916
+end
+
+def fun_l9_n380()
+ fun_l10_n930
+end
+
+def fun_l9_n381()
+ fun_l10_n884
+end
+
+def fun_l9_n382()
+ fun_l10_n782
+end
+
+def fun_l9_n383()
+ fun_l10_n63
+end
+
+def fun_l9_n384()
+ fun_l10_n488
+end
+
+def fun_l9_n385()
+ fun_l10_n188
+end
+
+def fun_l9_n386()
+ fun_l10_n692
+end
+
+def fun_l9_n387()
+ fun_l10_n213
+end
+
+def fun_l9_n388()
+ fun_l10_n358
+end
+
+def fun_l9_n389()
+ fun_l10_n200
+end
+
+def fun_l9_n390()
+ fun_l10_n881
+end
+
+def fun_l9_n391()
+ fun_l10_n533
+end
+
+def fun_l9_n392()
+ fun_l10_n889
+end
+
+def fun_l9_n393()
+ fun_l10_n444
+end
+
+def fun_l9_n394()
+ fun_l10_n184
+end
+
+def fun_l9_n395()
+ fun_l10_n775
+end
+
+def fun_l9_n396()
+ fun_l10_n714
+end
+
+def fun_l9_n397()
+ fun_l10_n385
+end
+
+def fun_l9_n398()
+ fun_l10_n432
+end
+
+def fun_l9_n399()
+ fun_l10_n357
+end
+
+def fun_l9_n400()
+ fun_l10_n223
+end
+
+def fun_l9_n401()
+ fun_l10_n73
+end
+
+def fun_l9_n402()
+ fun_l10_n139
+end
+
+def fun_l9_n403()
+ fun_l10_n930
+end
+
+def fun_l9_n404()
+ fun_l10_n43
+end
+
+def fun_l9_n405()
+ fun_l10_n104
+end
+
+def fun_l9_n406()
+ fun_l10_n334
+end
+
+def fun_l9_n407()
+ fun_l10_n959
+end
+
+def fun_l9_n408()
+ fun_l10_n59
+end
+
+def fun_l9_n409()
+ fun_l10_n794
+end
+
+def fun_l9_n410()
+ fun_l10_n204
+end
+
+def fun_l9_n411()
+ fun_l10_n225
+end
+
+def fun_l9_n412()
+ fun_l10_n849
+end
+
+def fun_l9_n413()
+ fun_l10_n227
+end
+
+def fun_l9_n414()
+ fun_l10_n59
+end
+
+def fun_l9_n415()
+ fun_l10_n352
+end
+
+def fun_l9_n416()
+ fun_l10_n910
+end
+
+def fun_l9_n417()
+ fun_l10_n628
+end
+
+def fun_l9_n418()
+ fun_l10_n653
+end
+
+def fun_l9_n419()
+ fun_l10_n827
+end
+
+def fun_l9_n420()
+ fun_l10_n960
+end
+
+def fun_l9_n421()
+ fun_l10_n142
+end
+
+def fun_l9_n422()
+ fun_l10_n928
+end
+
+def fun_l9_n423()
+ fun_l10_n370
+end
+
+def fun_l9_n424()
+ fun_l10_n121
+end
+
+def fun_l9_n425()
+ fun_l10_n684
+end
+
+def fun_l9_n426()
+ fun_l10_n187
+end
+
+def fun_l9_n427()
+ fun_l10_n93
+end
+
+def fun_l9_n428()
+ fun_l10_n792
+end
+
+def fun_l9_n429()
+ fun_l10_n565
+end
+
+def fun_l9_n430()
+ fun_l10_n933
+end
+
+def fun_l9_n431()
+ fun_l10_n393
+end
+
+def fun_l9_n432()
+ fun_l10_n412
+end
+
+def fun_l9_n433()
+ fun_l10_n121
+end
+
+def fun_l9_n434()
+ fun_l10_n522
+end
+
+def fun_l9_n435()
+ fun_l10_n408
+end
+
+def fun_l9_n436()
+ fun_l10_n670
+end
+
+def fun_l9_n437()
+ fun_l10_n685
+end
+
+def fun_l9_n438()
+ fun_l10_n138
+end
+
+def fun_l9_n439()
+ fun_l10_n658
+end
+
+def fun_l9_n440()
+ fun_l10_n567
+end
+
+def fun_l9_n441()
+ fun_l10_n121
+end
+
+def fun_l9_n442()
+ fun_l10_n532
+end
+
+def fun_l9_n443()
+ fun_l10_n37
+end
+
+def fun_l9_n444()
+ fun_l10_n502
+end
+
+def fun_l9_n445()
+ fun_l10_n779
+end
+
+def fun_l9_n446()
+ fun_l10_n376
+end
+
+def fun_l9_n447()
+ fun_l10_n412
+end
+
+def fun_l9_n448()
+ fun_l10_n932
+end
+
+def fun_l9_n449()
+ fun_l10_n779
+end
+
+def fun_l9_n450()
+ fun_l10_n231
+end
+
+def fun_l9_n451()
+ fun_l10_n302
+end
+
+def fun_l9_n452()
+ fun_l10_n273
+end
+
+def fun_l9_n453()
+ fun_l10_n531
+end
+
+def fun_l9_n454()
+ fun_l10_n291
+end
+
+def fun_l9_n455()
+ fun_l10_n56
+end
+
+def fun_l9_n456()
+ fun_l10_n970
+end
+
+def fun_l9_n457()
+ fun_l10_n936
+end
+
+def fun_l9_n458()
+ fun_l10_n537
+end
+
+def fun_l9_n459()
+ fun_l10_n145
+end
+
+def fun_l9_n460()
+ fun_l10_n756
+end
+
+def fun_l9_n461()
+ fun_l10_n0
+end
+
+def fun_l9_n462()
+ fun_l10_n691
+end
+
+def fun_l9_n463()
+ fun_l10_n635
+end
+
+def fun_l9_n464()
+ fun_l10_n485
+end
+
+def fun_l9_n465()
+ fun_l10_n407
+end
+
+def fun_l9_n466()
+ fun_l10_n393
+end
+
+def fun_l9_n467()
+ fun_l10_n336
+end
+
+def fun_l9_n468()
+ fun_l10_n169
+end
+
+def fun_l9_n469()
+ fun_l10_n43
+end
+
+def fun_l9_n470()
+ fun_l10_n907
+end
+
+def fun_l9_n471()
+ fun_l10_n215
+end
+
+def fun_l9_n472()
+ fun_l10_n118
+end
+
+def fun_l9_n473()
+ fun_l10_n735
+end
+
+def fun_l9_n474()
+ fun_l10_n319
+end
+
+def fun_l9_n475()
+ fun_l10_n631
+end
+
+def fun_l9_n476()
+ fun_l10_n150
+end
+
+def fun_l9_n477()
+ fun_l10_n899
+end
+
+def fun_l9_n478()
+ fun_l10_n407
+end
+
+def fun_l9_n479()
+ fun_l10_n830
+end
+
+def fun_l9_n480()
+ fun_l10_n931
+end
+
+def fun_l9_n481()
+ fun_l10_n392
+end
+
+def fun_l9_n482()
+ fun_l10_n100
+end
+
+def fun_l9_n483()
+ fun_l10_n210
+end
+
+def fun_l9_n484()
+ fun_l10_n506
+end
+
+def fun_l9_n485()
+ fun_l10_n160
+end
+
+def fun_l9_n486()
+ fun_l10_n998
+end
+
+def fun_l9_n487()
+ fun_l10_n170
+end
+
+def fun_l9_n488()
+ fun_l10_n722
+end
+
+def fun_l9_n489()
+ fun_l10_n196
+end
+
+def fun_l9_n490()
+ fun_l10_n518
+end
+
+def fun_l9_n491()
+ fun_l10_n350
+end
+
+def fun_l9_n492()
+ fun_l10_n89
+end
+
+def fun_l9_n493()
+ fun_l10_n49
+end
+
+def fun_l9_n494()
+ fun_l10_n366
+end
+
+def fun_l9_n495()
+ fun_l10_n850
+end
+
+def fun_l9_n496()
+ fun_l10_n430
+end
+
+def fun_l9_n497()
+ fun_l10_n485
+end
+
+def fun_l9_n498()
+ fun_l10_n584
+end
+
+def fun_l9_n499()
+ fun_l10_n36
+end
+
+def fun_l9_n500()
+ fun_l10_n58
+end
+
+def fun_l9_n501()
+ fun_l10_n81
+end
+
+def fun_l9_n502()
+ fun_l10_n161
+end
+
+def fun_l9_n503()
+ fun_l10_n983
+end
+
+def fun_l9_n504()
+ fun_l10_n994
+end
+
+def fun_l9_n505()
+ fun_l10_n26
+end
+
+def fun_l9_n506()
+ fun_l10_n286
+end
+
+def fun_l9_n507()
+ fun_l10_n118
+end
+
+def fun_l9_n508()
+ fun_l10_n509
+end
+
+def fun_l9_n509()
+ fun_l10_n630
+end
+
+def fun_l9_n510()
+ fun_l10_n302
+end
+
+def fun_l9_n511()
+ fun_l10_n307
+end
+
+def fun_l9_n512()
+ fun_l10_n810
+end
+
+def fun_l9_n513()
+ fun_l10_n21
+end
+
+def fun_l9_n514()
+ fun_l10_n76
+end
+
+def fun_l9_n515()
+ fun_l10_n769
+end
+
+def fun_l9_n516()
+ fun_l10_n58
+end
+
+def fun_l9_n517()
+ fun_l10_n368
+end
+
+def fun_l9_n518()
+ fun_l10_n8
+end
+
+def fun_l9_n519()
+ fun_l10_n559
+end
+
+def fun_l9_n520()
+ fun_l10_n949
+end
+
+def fun_l9_n521()
+ fun_l10_n781
+end
+
+def fun_l9_n522()
+ fun_l10_n453
+end
+
+def fun_l9_n523()
+ fun_l10_n227
+end
+
+def fun_l9_n524()
+ fun_l10_n389
+end
+
+def fun_l9_n525()
+ fun_l10_n641
+end
+
+def fun_l9_n526()
+ fun_l10_n221
+end
+
+def fun_l9_n527()
+ fun_l10_n322
+end
+
+def fun_l9_n528()
+ fun_l10_n918
+end
+
+def fun_l9_n529()
+ fun_l10_n246
+end
+
+def fun_l9_n530()
+ fun_l10_n431
+end
+
+def fun_l9_n531()
+ fun_l10_n445
+end
+
+def fun_l9_n532()
+ fun_l10_n781
+end
+
+def fun_l9_n533()
+ fun_l10_n626
+end
+
+def fun_l9_n534()
+ fun_l10_n51
+end
+
+def fun_l9_n535()
+ fun_l10_n441
+end
+
+def fun_l9_n536()
+ fun_l10_n806
+end
+
+def fun_l9_n537()
+ fun_l10_n58
+end
+
+def fun_l9_n538()
+ fun_l10_n710
+end
+
+def fun_l9_n539()
+ fun_l10_n782
+end
+
+def fun_l9_n540()
+ fun_l10_n991
+end
+
+def fun_l9_n541()
+ fun_l10_n792
+end
+
+def fun_l9_n542()
+ fun_l10_n376
+end
+
+def fun_l9_n543()
+ fun_l10_n716
+end
+
+def fun_l9_n544()
+ fun_l10_n500
+end
+
+def fun_l9_n545()
+ fun_l10_n251
+end
+
+def fun_l9_n546()
+ fun_l10_n951
+end
+
+def fun_l9_n547()
+ fun_l10_n584
+end
+
+def fun_l9_n548()
+ fun_l10_n150
+end
+
+def fun_l9_n549()
+ fun_l10_n380
+end
+
+def fun_l9_n550()
+ fun_l10_n432
+end
+
+def fun_l9_n551()
+ fun_l10_n787
+end
+
+def fun_l9_n552()
+ fun_l10_n749
+end
+
+def fun_l9_n553()
+ fun_l10_n646
+end
+
+def fun_l9_n554()
+ fun_l10_n405
+end
+
+def fun_l9_n555()
+ fun_l10_n345
+end
+
+def fun_l9_n556()
+ fun_l10_n855
+end
+
+def fun_l9_n557()
+ fun_l10_n575
+end
+
+def fun_l9_n558()
+ fun_l10_n368
+end
+
+def fun_l9_n559()
+ fun_l10_n511
+end
+
+def fun_l9_n560()
+ fun_l10_n158
+end
+
+def fun_l9_n561()
+ fun_l10_n243
+end
+
+def fun_l9_n562()
+ fun_l10_n536
+end
+
+def fun_l9_n563()
+ fun_l10_n107
+end
+
+def fun_l9_n564()
+ fun_l10_n270
+end
+
+def fun_l9_n565()
+ fun_l10_n783
+end
+
+def fun_l9_n566()
+ fun_l10_n289
+end
+
+def fun_l9_n567()
+ fun_l10_n360
+end
+
+def fun_l9_n568()
+ fun_l10_n190
+end
+
+def fun_l9_n569()
+ fun_l10_n245
+end
+
+def fun_l9_n570()
+ fun_l10_n565
+end
+
+def fun_l9_n571()
+ fun_l10_n310
+end
+
+def fun_l9_n572()
+ fun_l10_n939
+end
+
+def fun_l9_n573()
+ fun_l10_n955
+end
+
+def fun_l9_n574()
+ fun_l10_n521
+end
+
+def fun_l9_n575()
+ fun_l10_n597
+end
+
+def fun_l9_n576()
+ fun_l10_n122
+end
+
+def fun_l9_n577()
+ fun_l10_n987
+end
+
+def fun_l9_n578()
+ fun_l10_n267
+end
+
+def fun_l9_n579()
+ fun_l10_n798
+end
+
+def fun_l9_n580()
+ fun_l10_n468
+end
+
+def fun_l9_n581()
+ fun_l10_n807
+end
+
+def fun_l9_n582()
+ fun_l10_n749
+end
+
+def fun_l9_n583()
+ fun_l10_n578
+end
+
+def fun_l9_n584()
+ fun_l10_n878
+end
+
+def fun_l9_n585()
+ fun_l10_n404
+end
+
+def fun_l9_n586()
+ fun_l10_n501
+end
+
+def fun_l9_n587()
+ fun_l10_n165
+end
+
+def fun_l9_n588()
+ fun_l10_n270
+end
+
+def fun_l9_n589()
+ fun_l10_n197
+end
+
+def fun_l9_n590()
+ fun_l10_n940
+end
+
+def fun_l9_n591()
+ fun_l10_n667
+end
+
+def fun_l9_n592()
+ fun_l10_n67
+end
+
+def fun_l9_n593()
+ fun_l10_n652
+end
+
+def fun_l9_n594()
+ fun_l10_n728
+end
+
+def fun_l9_n595()
+ fun_l10_n829
+end
+
+def fun_l9_n596()
+ fun_l10_n528
+end
+
+def fun_l9_n597()
+ fun_l10_n765
+end
+
+def fun_l9_n598()
+ fun_l10_n841
+end
+
+def fun_l9_n599()
+ fun_l10_n605
+end
+
+def fun_l9_n600()
+ fun_l10_n316
+end
+
+def fun_l9_n601()
+ fun_l10_n676
+end
+
+def fun_l9_n602()
+ fun_l10_n673
+end
+
+def fun_l9_n603()
+ fun_l10_n400
+end
+
+def fun_l9_n604()
+ fun_l10_n774
+end
+
+def fun_l9_n605()
+ fun_l10_n717
+end
+
+def fun_l9_n606()
+ fun_l10_n853
+end
+
+def fun_l9_n607()
+ fun_l10_n336
+end
+
+def fun_l9_n608()
+ fun_l10_n169
+end
+
+def fun_l9_n609()
+ fun_l10_n7
+end
+
+def fun_l9_n610()
+ fun_l10_n846
+end
+
+def fun_l9_n611()
+ fun_l10_n87
+end
+
+def fun_l9_n612()
+ fun_l10_n805
+end
+
+def fun_l9_n613()
+ fun_l10_n591
+end
+
+def fun_l9_n614()
+ fun_l10_n674
+end
+
+def fun_l9_n615()
+ fun_l10_n796
+end
+
+def fun_l9_n616()
+ fun_l10_n390
+end
+
+def fun_l9_n617()
+ fun_l10_n107
+end
+
+def fun_l9_n618()
+ fun_l10_n302
+end
+
+def fun_l9_n619()
+ fun_l10_n848
+end
+
+def fun_l9_n620()
+ fun_l10_n263
+end
+
+def fun_l9_n621()
+ fun_l10_n380
+end
+
+def fun_l9_n622()
+ fun_l10_n778
+end
+
+def fun_l9_n623()
+ fun_l10_n593
+end
+
+def fun_l9_n624()
+ fun_l10_n147
+end
+
+def fun_l9_n625()
+ fun_l10_n683
+end
+
+def fun_l9_n626()
+ fun_l10_n850
+end
+
+def fun_l9_n627()
+ fun_l10_n545
+end
+
+def fun_l9_n628()
+ fun_l10_n549
+end
+
+def fun_l9_n629()
+ fun_l10_n692
+end
+
+def fun_l9_n630()
+ fun_l10_n688
+end
+
+def fun_l9_n631()
+ fun_l10_n656
+end
+
+def fun_l9_n632()
+ fun_l10_n201
+end
+
+def fun_l9_n633()
+ fun_l10_n216
+end
+
+def fun_l9_n634()
+ fun_l10_n661
+end
+
+def fun_l9_n635()
+ fun_l10_n670
+end
+
+def fun_l9_n636()
+ fun_l10_n436
+end
+
+def fun_l9_n637()
+ fun_l10_n591
+end
+
+def fun_l9_n638()
+ fun_l10_n419
+end
+
+def fun_l9_n639()
+ fun_l10_n133
+end
+
+def fun_l9_n640()
+ fun_l10_n998
+end
+
+def fun_l9_n641()
+ fun_l10_n20
+end
+
+def fun_l9_n642()
+ fun_l10_n484
+end
+
+def fun_l9_n643()
+ fun_l10_n349
+end
+
+def fun_l9_n644()
+ fun_l10_n548
+end
+
+def fun_l9_n645()
+ fun_l10_n67
+end
+
+def fun_l9_n646()
+ fun_l10_n99
+end
+
+def fun_l9_n647()
+ fun_l10_n758
+end
+
+def fun_l9_n648()
+ fun_l10_n559
+end
+
+def fun_l9_n649()
+ fun_l10_n518
+end
+
+def fun_l9_n650()
+ fun_l10_n698
+end
+
+def fun_l9_n651()
+ fun_l10_n807
+end
+
+def fun_l9_n652()
+ fun_l10_n557
+end
+
+def fun_l9_n653()
+ fun_l10_n53
+end
+
+def fun_l9_n654()
+ fun_l10_n783
+end
+
+def fun_l9_n655()
+ fun_l10_n687
+end
+
+def fun_l9_n656()
+ fun_l10_n40
+end
+
+def fun_l9_n657()
+ fun_l10_n758
+end
+
+def fun_l9_n658()
+ fun_l10_n308
+end
+
+def fun_l9_n659()
+ fun_l10_n828
+end
+
+def fun_l9_n660()
+ fun_l10_n510
+end
+
+def fun_l9_n661()
+ fun_l10_n621
+end
+
+def fun_l9_n662()
+ fun_l10_n885
+end
+
+def fun_l9_n663()
+ fun_l10_n765
+end
+
+def fun_l9_n664()
+ fun_l10_n213
+end
+
+def fun_l9_n665()
+ fun_l10_n530
+end
+
+def fun_l9_n666()
+ fun_l10_n178
+end
+
+def fun_l9_n667()
+ fun_l10_n550
+end
+
+def fun_l9_n668()
+ fun_l10_n650
+end
+
+def fun_l9_n669()
+ fun_l10_n695
+end
+
+def fun_l9_n670()
+ fun_l10_n295
+end
+
+def fun_l9_n671()
+ fun_l10_n672
+end
+
+def fun_l9_n672()
+ fun_l10_n603
+end
+
+def fun_l9_n673()
+ fun_l10_n394
+end
+
+def fun_l9_n674()
+ fun_l10_n470
+end
+
+def fun_l9_n675()
+ fun_l10_n869
+end
+
+def fun_l9_n676()
+ fun_l10_n270
+end
+
+def fun_l9_n677()
+ fun_l10_n933
+end
+
+def fun_l9_n678()
+ fun_l10_n268
+end
+
+def fun_l9_n679()
+ fun_l10_n862
+end
+
+def fun_l9_n680()
+ fun_l10_n84
+end
+
+def fun_l9_n681()
+ fun_l10_n370
+end
+
+def fun_l9_n682()
+ fun_l10_n538
+end
+
+def fun_l9_n683()
+ fun_l10_n752
+end
+
+def fun_l9_n684()
+ fun_l10_n868
+end
+
+def fun_l9_n685()
+ fun_l10_n278
+end
+
+def fun_l9_n686()
+ fun_l10_n65
+end
+
+def fun_l9_n687()
+ fun_l10_n713
+end
+
+def fun_l9_n688()
+ fun_l10_n577
+end
+
+def fun_l9_n689()
+ fun_l10_n508
+end
+
+def fun_l9_n690()
+ fun_l10_n400
+end
+
+def fun_l9_n691()
+ fun_l10_n830
+end
+
+def fun_l9_n692()
+ fun_l10_n366
+end
+
+def fun_l9_n693()
+ fun_l10_n545
+end
+
+def fun_l9_n694()
+ fun_l10_n479
+end
+
+def fun_l9_n695()
+ fun_l10_n978
+end
+
+def fun_l9_n696()
+ fun_l10_n935
+end
+
+def fun_l9_n697()
+ fun_l10_n235
+end
+
+def fun_l9_n698()
+ fun_l10_n196
+end
+
+def fun_l9_n699()
+ fun_l10_n508
+end
+
+def fun_l9_n700()
+ fun_l10_n879
+end
+
+def fun_l9_n701()
+ fun_l10_n81
+end
+
+def fun_l9_n702()
+ fun_l10_n676
+end
+
+def fun_l9_n703()
+ fun_l10_n276
+end
+
+def fun_l9_n704()
+ fun_l10_n565
+end
+
+def fun_l9_n705()
+ fun_l10_n98
+end
+
+def fun_l9_n706()
+ fun_l10_n66
+end
+
+def fun_l9_n707()
+ fun_l10_n894
+end
+
+def fun_l9_n708()
+ fun_l10_n258
+end
+
+def fun_l9_n709()
+ fun_l10_n465
+end
+
+def fun_l9_n710()
+ fun_l10_n677
+end
+
+def fun_l9_n711()
+ fun_l10_n644
+end
+
+def fun_l9_n712()
+ fun_l10_n729
+end
+
+def fun_l9_n713()
+ fun_l10_n222
+end
+
+def fun_l9_n714()
+ fun_l10_n186
+end
+
+def fun_l9_n715()
+ fun_l10_n387
+end
+
+def fun_l9_n716()
+ fun_l10_n933
+end
+
+def fun_l9_n717()
+ fun_l10_n280
+end
+
+def fun_l9_n718()
+ fun_l10_n939
+end
+
+def fun_l9_n719()
+ fun_l10_n993
+end
+
+def fun_l9_n720()
+ fun_l10_n529
+end
+
+def fun_l9_n721()
+ fun_l10_n189
+end
+
+def fun_l9_n722()
+ fun_l10_n544
+end
+
+def fun_l9_n723()
+ fun_l10_n655
+end
+
+def fun_l9_n724()
+ fun_l10_n88
+end
+
+def fun_l9_n725()
+ fun_l10_n448
+end
+
+def fun_l9_n726()
+ fun_l10_n656
+end
+
+def fun_l9_n727()
+ fun_l10_n106
+end
+
+def fun_l9_n728()
+ fun_l10_n711
+end
+
+def fun_l9_n729()
+ fun_l10_n400
+end
+
+def fun_l9_n730()
+ fun_l10_n138
+end
+
+def fun_l9_n731()
+ fun_l10_n90
+end
+
+def fun_l9_n732()
+ fun_l10_n290
+end
+
+def fun_l9_n733()
+ fun_l10_n563
+end
+
+def fun_l9_n734()
+ fun_l10_n103
+end
+
+def fun_l9_n735()
+ fun_l10_n115
+end
+
+def fun_l9_n736()
+ fun_l10_n771
+end
+
+def fun_l9_n737()
+ fun_l10_n291
+end
+
+def fun_l9_n738()
+ fun_l10_n46
+end
+
+def fun_l9_n739()
+ fun_l10_n872
+end
+
+def fun_l9_n740()
+ fun_l10_n871
+end
+
+def fun_l9_n741()
+ fun_l10_n190
+end
+
+def fun_l9_n742()
+ fun_l10_n641
+end
+
+def fun_l9_n743()
+ fun_l10_n951
+end
+
+def fun_l9_n744()
+ fun_l10_n248
+end
+
+def fun_l9_n745()
+ fun_l10_n275
+end
+
+def fun_l9_n746()
+ fun_l10_n943
+end
+
+def fun_l9_n747()
+ fun_l10_n995
+end
+
+def fun_l9_n748()
+ fun_l10_n194
+end
+
+def fun_l9_n749()
+ fun_l10_n121
+end
+
+def fun_l9_n750()
+ fun_l10_n707
+end
+
+def fun_l9_n751()
+ fun_l10_n591
+end
+
+def fun_l9_n752()
+ fun_l10_n616
+end
+
+def fun_l9_n753()
+ fun_l10_n155
+end
+
+def fun_l9_n754()
+ fun_l10_n779
+end
+
+def fun_l9_n755()
+ fun_l10_n449
+end
+
+def fun_l9_n756()
+ fun_l10_n937
+end
+
+def fun_l9_n757()
+ fun_l10_n571
+end
+
+def fun_l9_n758()
+ fun_l10_n892
+end
+
+def fun_l9_n759()
+ fun_l10_n441
+end
+
+def fun_l9_n760()
+ fun_l10_n686
+end
+
+def fun_l9_n761()
+ fun_l10_n55
+end
+
+def fun_l9_n762()
+ fun_l10_n852
+end
+
+def fun_l9_n763()
+ fun_l10_n102
+end
+
+def fun_l9_n764()
+ fun_l10_n207
+end
+
+def fun_l9_n765()
+ fun_l10_n269
+end
+
+def fun_l9_n766()
+ fun_l10_n422
+end
+
+def fun_l9_n767()
+ fun_l10_n589
+end
+
+def fun_l9_n768()
+ fun_l10_n406
+end
+
+def fun_l9_n769()
+ fun_l10_n88
+end
+
+def fun_l9_n770()
+ fun_l10_n441
+end
+
+def fun_l9_n771()
+ fun_l10_n506
+end
+
+def fun_l9_n772()
+ fun_l10_n797
+end
+
+def fun_l9_n773()
+ fun_l10_n639
+end
+
+def fun_l9_n774()
+ fun_l10_n390
+end
+
+def fun_l9_n775()
+ fun_l10_n511
+end
+
+def fun_l9_n776()
+ fun_l10_n353
+end
+
+def fun_l9_n777()
+ fun_l10_n137
+end
+
+def fun_l9_n778()
+ fun_l10_n692
+end
+
+def fun_l9_n779()
+ fun_l10_n522
+end
+
+def fun_l9_n780()
+ fun_l10_n532
+end
+
+def fun_l9_n781()
+ fun_l10_n4
+end
+
+def fun_l9_n782()
+ fun_l10_n548
+end
+
+def fun_l9_n783()
+ fun_l10_n386
+end
+
+def fun_l9_n784()
+ fun_l10_n932
+end
+
+def fun_l9_n785()
+ fun_l10_n552
+end
+
+def fun_l9_n786()
+ fun_l10_n215
+end
+
+def fun_l9_n787()
+ fun_l10_n981
+end
+
+def fun_l9_n788()
+ fun_l10_n379
+end
+
+def fun_l9_n789()
+ fun_l10_n208
+end
+
+def fun_l9_n790()
+ fun_l10_n252
+end
+
+def fun_l9_n791()
+ fun_l10_n471
+end
+
+def fun_l9_n792()
+ fun_l10_n300
+end
+
+def fun_l9_n793()
+ fun_l10_n877
+end
+
+def fun_l9_n794()
+ fun_l10_n92
+end
+
+def fun_l9_n795()
+ fun_l10_n75
+end
+
+def fun_l9_n796()
+ fun_l10_n837
+end
+
+def fun_l9_n797()
+ fun_l10_n328
+end
+
+def fun_l9_n798()
+ fun_l10_n454
+end
+
+def fun_l9_n799()
+ fun_l10_n392
+end
+
+def fun_l9_n800()
+ fun_l10_n115
+end
+
+def fun_l9_n801()
+ fun_l10_n966
+end
+
+def fun_l9_n802()
+ fun_l10_n565
+end
+
+def fun_l9_n803()
+ fun_l10_n268
+end
+
+def fun_l9_n804()
+ fun_l10_n13
+end
+
+def fun_l9_n805()
+ fun_l10_n484
+end
+
+def fun_l9_n806()
+ fun_l10_n893
+end
+
+def fun_l9_n807()
+ fun_l10_n59
+end
+
+def fun_l9_n808()
+ fun_l10_n87
+end
+
+def fun_l9_n809()
+ fun_l10_n455
+end
+
+def fun_l9_n810()
+ fun_l10_n972
+end
+
+def fun_l9_n811()
+ fun_l10_n804
+end
+
+def fun_l9_n812()
+ fun_l10_n20
+end
+
+def fun_l9_n813()
+ fun_l10_n148
+end
+
+def fun_l9_n814()
+ fun_l10_n284
+end
+
+def fun_l9_n815()
+ fun_l10_n704
+end
+
+def fun_l9_n816()
+ fun_l10_n346
+end
+
+def fun_l9_n817()
+ fun_l10_n101
+end
+
+def fun_l9_n818()
+ fun_l10_n543
+end
+
+def fun_l9_n819()
+ fun_l10_n207
+end
+
+def fun_l9_n820()
+ fun_l10_n256
+end
+
+def fun_l9_n821()
+ fun_l10_n300
+end
+
+def fun_l9_n822()
+ fun_l10_n69
+end
+
+def fun_l9_n823()
+ fun_l10_n139
+end
+
+def fun_l9_n824()
+ fun_l10_n566
+end
+
+def fun_l9_n825()
+ fun_l10_n277
+end
+
+def fun_l9_n826()
+ fun_l10_n75
+end
+
+def fun_l9_n827()
+ fun_l10_n585
+end
+
+def fun_l9_n828()
+ fun_l10_n2
+end
+
+def fun_l9_n829()
+ fun_l10_n959
+end
+
+def fun_l9_n830()
+ fun_l10_n982
+end
+
+def fun_l9_n831()
+ fun_l10_n621
+end
+
+def fun_l9_n832()
+ fun_l10_n680
+end
+
+def fun_l9_n833()
+ fun_l10_n535
+end
+
+def fun_l9_n834()
+ fun_l10_n732
+end
+
+def fun_l9_n835()
+ fun_l10_n282
+end
+
+def fun_l9_n836()
+ fun_l10_n825
+end
+
+def fun_l9_n837()
+ fun_l10_n323
+end
+
+def fun_l9_n838()
+ fun_l10_n963
+end
+
+def fun_l9_n839()
+ fun_l10_n138
+end
+
+def fun_l9_n840()
+ fun_l10_n370
+end
+
+def fun_l9_n841()
+ fun_l10_n44
+end
+
+def fun_l9_n842()
+ fun_l10_n694
+end
+
+def fun_l9_n843()
+ fun_l10_n532
+end
+
+def fun_l9_n844()
+ fun_l10_n987
+end
+
+def fun_l9_n845()
+ fun_l10_n730
+end
+
+def fun_l9_n846()
+ fun_l10_n376
+end
+
+def fun_l9_n847()
+ fun_l10_n33
+end
+
+def fun_l9_n848()
+ fun_l10_n381
+end
+
+def fun_l9_n849()
+ fun_l10_n569
+end
+
+def fun_l9_n850()
+ fun_l10_n264
+end
+
+def fun_l9_n851()
+ fun_l10_n260
+end
+
+def fun_l9_n852()
+ fun_l10_n750
+end
+
+def fun_l9_n853()
+ fun_l10_n710
+end
+
+def fun_l9_n854()
+ fun_l10_n665
+end
+
+def fun_l9_n855()
+ fun_l10_n544
+end
+
+def fun_l9_n856()
+ fun_l10_n306
+end
+
+def fun_l9_n857()
+ fun_l10_n303
+end
+
+def fun_l9_n858()
+ fun_l10_n754
+end
+
+def fun_l9_n859()
+ fun_l10_n552
+end
+
+def fun_l9_n860()
+ fun_l10_n404
+end
+
+def fun_l9_n861()
+ fun_l10_n123
+end
+
+def fun_l9_n862()
+ fun_l10_n240
+end
+
+def fun_l9_n863()
+ fun_l10_n213
+end
+
+def fun_l9_n864()
+ fun_l10_n697
+end
+
+def fun_l9_n865()
+ fun_l10_n185
+end
+
+def fun_l9_n866()
+ fun_l10_n245
+end
+
+def fun_l9_n867()
+ fun_l10_n889
+end
+
+def fun_l9_n868()
+ fun_l10_n64
+end
+
+def fun_l9_n869()
+ fun_l10_n685
+end
+
+def fun_l9_n870()
+ fun_l10_n653
+end
+
+def fun_l9_n871()
+ fun_l10_n331
+end
+
+def fun_l9_n872()
+ fun_l10_n548
+end
+
+def fun_l9_n873()
+ fun_l10_n120
+end
+
+def fun_l9_n874()
+ fun_l10_n511
+end
+
+def fun_l9_n875()
+ fun_l10_n280
+end
+
+def fun_l9_n876()
+ fun_l10_n250
+end
+
+def fun_l9_n877()
+ fun_l10_n871
+end
+
+def fun_l9_n878()
+ fun_l10_n356
+end
+
+def fun_l9_n879()
+ fun_l10_n985
+end
+
+def fun_l9_n880()
+ fun_l10_n285
+end
+
+def fun_l9_n881()
+ fun_l10_n836
+end
+
+def fun_l9_n882()
+ fun_l10_n906
+end
+
+def fun_l9_n883()
+ fun_l10_n497
+end
+
+def fun_l9_n884()
+ fun_l10_n320
+end
+
+def fun_l9_n885()
+ fun_l10_n932
+end
+
+def fun_l9_n886()
+ fun_l10_n470
+end
+
+def fun_l9_n887()
+ fun_l10_n453
+end
+
+def fun_l9_n888()
+ fun_l10_n208
+end
+
+def fun_l9_n889()
+ fun_l10_n80
+end
+
+def fun_l9_n890()
+ fun_l10_n943
+end
+
+def fun_l9_n891()
+ fun_l10_n711
+end
+
+def fun_l9_n892()
+ fun_l10_n548
+end
+
+def fun_l9_n893()
+ fun_l10_n160
+end
+
+def fun_l9_n894()
+ fun_l10_n44
+end
+
+def fun_l9_n895()
+ fun_l10_n241
+end
+
+def fun_l9_n896()
+ fun_l10_n390
+end
+
+def fun_l9_n897()
+ fun_l10_n133
+end
+
+def fun_l9_n898()
+ fun_l10_n3
+end
+
+def fun_l9_n899()
+ fun_l10_n651
+end
+
+def fun_l9_n900()
+ fun_l10_n556
+end
+
+def fun_l9_n901()
+ fun_l10_n423
+end
+
+def fun_l9_n902()
+ fun_l10_n521
+end
+
+def fun_l9_n903()
+ fun_l10_n589
+end
+
+def fun_l9_n904()
+ fun_l10_n284
+end
+
+def fun_l9_n905()
+ fun_l10_n816
+end
+
+def fun_l9_n906()
+ fun_l10_n326
+end
+
+def fun_l9_n907()
+ fun_l10_n309
+end
+
+def fun_l9_n908()
+ fun_l10_n656
+end
+
+def fun_l9_n909()
+ fun_l10_n636
+end
+
+def fun_l9_n910()
+ fun_l10_n633
+end
+
+def fun_l9_n911()
+ fun_l10_n955
+end
+
+def fun_l9_n912()
+ fun_l10_n807
+end
+
+def fun_l9_n913()
+ fun_l10_n547
+end
+
+def fun_l9_n914()
+ fun_l10_n300
+end
+
+def fun_l9_n915()
+ fun_l10_n98
+end
+
+def fun_l9_n916()
+ fun_l10_n848
+end
+
+def fun_l9_n917()
+ fun_l10_n702
+end
+
+def fun_l9_n918()
+ fun_l10_n102
+end
+
+def fun_l9_n919()
+ fun_l10_n184
+end
+
+def fun_l9_n920()
+ fun_l10_n91
+end
+
+def fun_l9_n921()
+ fun_l10_n744
+end
+
+def fun_l9_n922()
+ fun_l10_n923
+end
+
+def fun_l9_n923()
+ fun_l10_n710
+end
+
+def fun_l9_n924()
+ fun_l10_n137
+end
+
+def fun_l9_n925()
+ fun_l10_n381
+end
+
+def fun_l9_n926()
+ fun_l10_n795
+end
+
+def fun_l9_n927()
+ fun_l10_n255
+end
+
+def fun_l9_n928()
+ fun_l10_n191
+end
+
+def fun_l9_n929()
+ fun_l10_n650
+end
+
+def fun_l9_n930()
+ fun_l10_n928
+end
+
+def fun_l9_n931()
+ fun_l10_n277
+end
+
+def fun_l9_n932()
+ fun_l10_n269
+end
+
+def fun_l9_n933()
+ fun_l10_n221
+end
+
+def fun_l9_n934()
+ fun_l10_n2
+end
+
+def fun_l9_n935()
+ fun_l10_n359
+end
+
+def fun_l9_n936()
+ fun_l10_n403
+end
+
+def fun_l9_n937()
+ fun_l10_n376
+end
+
+def fun_l9_n938()
+ fun_l10_n309
+end
+
+def fun_l9_n939()
+ fun_l10_n245
+end
+
+def fun_l9_n940()
+ fun_l10_n973
+end
+
+def fun_l9_n941()
+ fun_l10_n835
+end
+
+def fun_l9_n942()
+ fun_l10_n884
+end
+
+def fun_l9_n943()
+ fun_l10_n700
+end
+
+def fun_l9_n944()
+ fun_l10_n809
+end
+
+def fun_l9_n945()
+ fun_l10_n864
+end
+
+def fun_l9_n946()
+ fun_l10_n577
+end
+
+def fun_l9_n947()
+ fun_l10_n487
+end
+
+def fun_l9_n948()
+ fun_l10_n205
+end
+
+def fun_l9_n949()
+ fun_l10_n980
+end
+
+def fun_l9_n950()
+ fun_l10_n855
+end
+
+def fun_l9_n951()
+ fun_l10_n100
+end
+
+def fun_l9_n952()
+ fun_l10_n514
+end
+
+def fun_l9_n953()
+ fun_l10_n385
+end
+
+def fun_l9_n954()
+ fun_l10_n676
+end
+
+def fun_l9_n955()
+ fun_l10_n808
+end
+
+def fun_l9_n956()
+ fun_l10_n111
+end
+
+def fun_l9_n957()
+ fun_l10_n571
+end
+
+def fun_l9_n958()
+ fun_l10_n895
+end
+
+def fun_l9_n959()
+ fun_l10_n858
+end
+
+def fun_l9_n960()
+ fun_l10_n74
+end
+
+def fun_l9_n961()
+ fun_l10_n952
+end
+
+def fun_l9_n962()
+ fun_l10_n164
+end
+
+def fun_l9_n963()
+ fun_l10_n149
+end
+
+def fun_l9_n964()
+ fun_l10_n705
+end
+
+def fun_l9_n965()
+ fun_l10_n406
+end
+
+def fun_l9_n966()
+ fun_l10_n569
+end
+
+def fun_l9_n967()
+ fun_l10_n57
+end
+
+def fun_l9_n968()
+ fun_l10_n402
+end
+
+def fun_l9_n969()
+ fun_l10_n988
+end
+
+def fun_l9_n970()
+ fun_l10_n114
+end
+
+def fun_l9_n971()
+ fun_l10_n456
+end
+
+def fun_l9_n972()
+ fun_l10_n346
+end
+
+def fun_l9_n973()
+ fun_l10_n250
+end
+
+def fun_l9_n974()
+ fun_l10_n684
+end
+
+def fun_l9_n975()
+ fun_l10_n445
+end
+
+def fun_l9_n976()
+ fun_l10_n628
+end
+
+def fun_l9_n977()
+ fun_l10_n536
+end
+
+def fun_l9_n978()
+ fun_l10_n937
+end
+
+def fun_l9_n979()
+ fun_l10_n320
+end
+
+def fun_l9_n980()
+ fun_l10_n412
+end
+
+def fun_l9_n981()
+ fun_l10_n280
+end
+
+def fun_l9_n982()
+ fun_l10_n435
+end
+
+def fun_l9_n983()
+ fun_l10_n643
+end
+
+def fun_l9_n984()
+ fun_l10_n702
+end
+
+def fun_l9_n985()
+ fun_l10_n919
+end
+
+def fun_l9_n986()
+ fun_l10_n127
+end
+
+def fun_l9_n987()
+ fun_l10_n770
+end
+
+def fun_l9_n988()
+ fun_l10_n673
+end
+
+def fun_l9_n989()
+ fun_l10_n625
+end
+
+def fun_l9_n990()
+ fun_l10_n196
+end
+
+def fun_l9_n991()
+ fun_l10_n676
+end
+
+def fun_l9_n992()
+ fun_l10_n634
+end
+
+def fun_l9_n993()
+ fun_l10_n694
+end
+
+def fun_l9_n994()
+ fun_l10_n46
+end
+
+def fun_l9_n995()
+ fun_l10_n762
+end
+
+def fun_l9_n996()
+ fun_l10_n163
+end
+
+def fun_l9_n997()
+ fun_l10_n24
+end
+
+def fun_l9_n998()
+ fun_l10_n279
+end
+
+def fun_l9_n999()
+ fun_l10_n110
+end
+
+def fun_l10_n0()
+ fun_l11_n375
+end
+
+def fun_l10_n1()
+ fun_l11_n360
+end
+
+def fun_l10_n2()
+ fun_l11_n220
+end
+
+def fun_l10_n3()
+ fun_l11_n847
+end
+
+def fun_l10_n4()
+ fun_l11_n431
+end
+
+def fun_l10_n5()
+ fun_l11_n609
+end
+
+def fun_l10_n6()
+ fun_l11_n584
+end
+
+def fun_l10_n7()
+ fun_l11_n41
+end
+
+def fun_l10_n8()
+ fun_l11_n259
+end
+
+def fun_l10_n9()
+ fun_l11_n885
+end
+
+def fun_l10_n10()
+ fun_l11_n353
+end
+
+def fun_l10_n11()
+ fun_l11_n675
+end
+
+def fun_l10_n12()
+ fun_l11_n208
+end
+
+def fun_l10_n13()
+ fun_l11_n66
+end
+
+def fun_l10_n14()
+ fun_l11_n420
+end
+
+def fun_l10_n15()
+ fun_l11_n987
+end
+
+def fun_l10_n16()
+ fun_l11_n703
+end
+
+def fun_l10_n17()
+ fun_l11_n755
+end
+
+def fun_l10_n18()
+ fun_l11_n996
+end
+
+def fun_l10_n19()
+ fun_l11_n189
+end
+
+def fun_l10_n20()
+ fun_l11_n950
+end
+
+def fun_l10_n21()
+ fun_l11_n602
+end
+
+def fun_l10_n22()
+ fun_l11_n971
+end
+
+def fun_l10_n23()
+ fun_l11_n797
+end
+
+def fun_l10_n24()
+ fun_l11_n950
+end
+
+def fun_l10_n25()
+ fun_l11_n606
+end
+
+def fun_l10_n26()
+ fun_l11_n201
+end
+
+def fun_l10_n27()
+ fun_l11_n844
+end
+
+def fun_l10_n28()
+ fun_l11_n546
+end
+
+def fun_l10_n29()
+ fun_l11_n448
+end
+
+def fun_l10_n30()
+ fun_l11_n717
+end
+
+def fun_l10_n31()
+ fun_l11_n236
+end
+
+def fun_l10_n32()
+ fun_l11_n49
+end
+
+def fun_l10_n33()
+ fun_l11_n930
+end
+
+def fun_l10_n34()
+ fun_l11_n818
+end
+
+def fun_l10_n35()
+ fun_l11_n795
+end
+
+def fun_l10_n36()
+ fun_l11_n933
+end
+
+def fun_l10_n37()
+ fun_l11_n198
+end
+
+def fun_l10_n38()
+ fun_l11_n666
+end
+
+def fun_l10_n39()
+ fun_l11_n998
+end
+
+def fun_l10_n40()
+ fun_l11_n570
+end
+
+def fun_l10_n41()
+ fun_l11_n759
+end
+
+def fun_l10_n42()
+ fun_l11_n306
+end
+
+def fun_l10_n43()
+ fun_l11_n735
+end
+
+def fun_l10_n44()
+ fun_l11_n730
+end
+
+def fun_l10_n45()
+ fun_l11_n429
+end
+
+def fun_l10_n46()
+ fun_l11_n239
+end
+
+def fun_l10_n47()
+ fun_l11_n877
+end
+
+def fun_l10_n48()
+ fun_l11_n615
+end
+
+def fun_l10_n49()
+ fun_l11_n462
+end
+
+def fun_l10_n50()
+ fun_l11_n187
+end
+
+def fun_l10_n51()
+ fun_l11_n584
+end
+
+def fun_l10_n52()
+ fun_l11_n565
+end
+
+def fun_l10_n53()
+ fun_l11_n53
+end
+
+def fun_l10_n54()
+ fun_l11_n69
+end
+
+def fun_l10_n55()
+ fun_l11_n594
+end
+
+def fun_l10_n56()
+ fun_l11_n307
+end
+
+def fun_l10_n57()
+ fun_l11_n913
+end
+
+def fun_l10_n58()
+ fun_l11_n814
+end
+
+def fun_l10_n59()
+ fun_l11_n764
+end
+
+def fun_l10_n60()
+ fun_l11_n367
+end
+
+def fun_l10_n61()
+ fun_l11_n335
+end
+
+def fun_l10_n62()
+ fun_l11_n166
+end
+
+def fun_l10_n63()
+ fun_l11_n348
+end
+
+def fun_l10_n64()
+ fun_l11_n175
+end
+
+def fun_l10_n65()
+ fun_l11_n685
+end
+
+def fun_l10_n66()
+ fun_l11_n804
+end
+
+def fun_l10_n67()
+ fun_l11_n857
+end
+
+def fun_l10_n68()
+ fun_l11_n361
+end
+
+def fun_l10_n69()
+ fun_l11_n744
+end
+
+def fun_l10_n70()
+ fun_l11_n902
+end
+
+def fun_l10_n71()
+ fun_l11_n142
+end
+
+def fun_l10_n72()
+ fun_l11_n129
+end
+
+def fun_l10_n73()
+ fun_l11_n597
+end
+
+def fun_l10_n74()
+ fun_l11_n416
+end
+
+def fun_l10_n75()
+ fun_l11_n983
+end
+
+def fun_l10_n76()
+ fun_l11_n504
+end
+
+def fun_l10_n77()
+ fun_l11_n887
+end
+
+def fun_l10_n78()
+ fun_l11_n114
+end
+
+def fun_l10_n79()
+ fun_l11_n292
+end
+
+def fun_l10_n80()
+ fun_l11_n635
+end
+
+def fun_l10_n81()
+ fun_l11_n910
+end
+
+def fun_l10_n82()
+ fun_l11_n82
+end
+
+def fun_l10_n83()
+ fun_l11_n149
+end
+
+def fun_l10_n84()
+ fun_l11_n240
+end
+
+def fun_l10_n85()
+ fun_l11_n349
+end
+
+def fun_l10_n86()
+ fun_l11_n873
+end
+
+def fun_l10_n87()
+ fun_l11_n269
+end
+
+def fun_l10_n88()
+ fun_l11_n81
+end
+
+def fun_l10_n89()
+ fun_l11_n735
+end
+
+def fun_l10_n90()
+ fun_l11_n21
+end
+
+def fun_l10_n91()
+ fun_l11_n491
+end
+
+def fun_l10_n92()
+ fun_l11_n808
+end
+
+def fun_l10_n93()
+ fun_l11_n628
+end
+
+def fun_l10_n94()
+ fun_l11_n456
+end
+
+def fun_l10_n95()
+ fun_l11_n982
+end
+
+def fun_l10_n96()
+ fun_l11_n440
+end
+
+def fun_l10_n97()
+ fun_l11_n406
+end
+
+def fun_l10_n98()
+ fun_l11_n920
+end
+
+def fun_l10_n99()
+ fun_l11_n155
+end
+
+def fun_l10_n100()
+ fun_l11_n673
+end
+
+def fun_l10_n101()
+ fun_l11_n902
+end
+
+def fun_l10_n102()
+ fun_l11_n321
+end
+
+def fun_l10_n103()
+ fun_l11_n723
+end
+
+def fun_l10_n104()
+ fun_l11_n914
+end
+
+def fun_l10_n105()
+ fun_l11_n305
+end
+
+def fun_l10_n106()
+ fun_l11_n16
+end
+
+def fun_l10_n107()
+ fun_l11_n342
+end
+
+def fun_l10_n108()
+ fun_l11_n808
+end
+
+def fun_l10_n109()
+ fun_l11_n593
+end
+
+def fun_l10_n110()
+ fun_l11_n912
+end
+
+def fun_l10_n111()
+ fun_l11_n373
+end
+
+def fun_l10_n112()
+ fun_l11_n491
+end
+
+def fun_l10_n113()
+ fun_l11_n893
+end
+
+def fun_l10_n114()
+ fun_l11_n776
+end
+
+def fun_l10_n115()
+ fun_l11_n932
+end
+
+def fun_l10_n116()
+ fun_l11_n347
+end
+
+def fun_l10_n117()
+ fun_l11_n475
+end
+
+def fun_l10_n118()
+ fun_l11_n656
+end
+
+def fun_l10_n119()
+ fun_l11_n199
+end
+
+def fun_l10_n120()
+ fun_l11_n888
+end
+
+def fun_l10_n121()
+ fun_l11_n110
+end
+
+def fun_l10_n122()
+ fun_l11_n520
+end
+
+def fun_l10_n123()
+ fun_l11_n743
+end
+
+def fun_l10_n124()
+ fun_l11_n830
+end
+
+def fun_l10_n125()
+ fun_l11_n740
+end
+
+def fun_l10_n126()
+ fun_l11_n693
+end
+
+def fun_l10_n127()
+ fun_l11_n500
+end
+
+def fun_l10_n128()
+ fun_l11_n311
+end
+
+def fun_l10_n129()
+ fun_l11_n842
+end
+
+def fun_l10_n130()
+ fun_l11_n769
+end
+
+def fun_l10_n131()
+ fun_l11_n341
+end
+
+def fun_l10_n132()
+ fun_l11_n367
+end
+
+def fun_l10_n133()
+ fun_l11_n872
+end
+
+def fun_l10_n134()
+ fun_l11_n460
+end
+
+def fun_l10_n135()
+ fun_l11_n154
+end
+
+def fun_l10_n136()
+ fun_l11_n953
+end
+
+def fun_l10_n137()
+ fun_l11_n300
+end
+
+def fun_l10_n138()
+ fun_l11_n466
+end
+
+def fun_l10_n139()
+ fun_l11_n474
+end
+
+def fun_l10_n140()
+ fun_l11_n145
+end
+
+def fun_l10_n141()
+ fun_l11_n953
+end
+
+def fun_l10_n142()
+ fun_l11_n613
+end
+
+def fun_l10_n143()
+ fun_l11_n55
+end
+
+def fun_l10_n144()
+ fun_l11_n847
+end
+
+def fun_l10_n145()
+ fun_l11_n888
+end
+
+def fun_l10_n146()
+ fun_l11_n721
+end
+
+def fun_l10_n147()
+ fun_l11_n8
+end
+
+def fun_l10_n148()
+ fun_l11_n595
+end
+
+def fun_l10_n149()
+ fun_l11_n326
+end
+
+def fun_l10_n150()
+ fun_l11_n134
+end
+
+def fun_l10_n151()
+ fun_l11_n567
+end
+
+def fun_l10_n152()
+ fun_l11_n87
+end
+
+def fun_l10_n153()
+ fun_l11_n581
+end
+
+def fun_l10_n154()
+ fun_l11_n973
+end
+
+def fun_l10_n155()
+ fun_l11_n349
+end
+
+def fun_l10_n156()
+ fun_l11_n550
+end
+
+def fun_l10_n157()
+ fun_l11_n545
+end
+
+def fun_l10_n158()
+ fun_l11_n325
+end
+
+def fun_l10_n159()
+ fun_l11_n568
+end
+
+def fun_l10_n160()
+ fun_l11_n768
+end
+
+def fun_l10_n161()
+ fun_l11_n320
+end
+
+def fun_l10_n162()
+ fun_l11_n667
+end
+
+def fun_l10_n163()
+ fun_l11_n415
+end
+
+def fun_l10_n164()
+ fun_l11_n185
+end
+
+def fun_l10_n165()
+ fun_l11_n576
+end
+
+def fun_l10_n166()
+ fun_l11_n436
+end
+
+def fun_l10_n167()
+ fun_l11_n290
+end
+
+def fun_l10_n168()
+ fun_l11_n783
+end
+
+def fun_l10_n169()
+ fun_l11_n865
+end
+
+def fun_l10_n170()
+ fun_l11_n837
+end
+
+def fun_l10_n171()
+ fun_l11_n806
+end
+
+def fun_l10_n172()
+ fun_l11_n847
+end
+
+def fun_l10_n173()
+ fun_l11_n425
+end
+
+def fun_l10_n174()
+ fun_l11_n740
+end
+
+def fun_l10_n175()
+ fun_l11_n885
+end
+
+def fun_l10_n176()
+ fun_l11_n787
+end
+
+def fun_l10_n177()
+ fun_l11_n189
+end
+
+def fun_l10_n178()
+ fun_l11_n122
+end
+
+def fun_l10_n179()
+ fun_l11_n132
+end
+
+def fun_l10_n180()
+ fun_l11_n778
+end
+
+def fun_l10_n181()
+ fun_l11_n45
+end
+
+def fun_l10_n182()
+ fun_l11_n856
+end
+
+def fun_l10_n183()
+ fun_l11_n853
+end
+
+def fun_l10_n184()
+ fun_l11_n370
+end
+
+def fun_l10_n185()
+ fun_l11_n850
+end
+
+def fun_l10_n186()
+ fun_l11_n623
+end
+
+def fun_l10_n187()
+ fun_l11_n747
+end
+
+def fun_l10_n188()
+ fun_l11_n792
+end
+
+def fun_l10_n189()
+ fun_l11_n184
+end
+
+def fun_l10_n190()
+ fun_l11_n683
+end
+
+def fun_l10_n191()
+ fun_l11_n831
+end
+
+def fun_l10_n192()
+ fun_l11_n741
+end
+
+def fun_l10_n193()
+ fun_l11_n380
+end
+
+def fun_l10_n194()
+ fun_l11_n183
+end
+
+def fun_l10_n195()
+ fun_l11_n800
+end
+
+def fun_l10_n196()
+ fun_l11_n466
+end
+
+def fun_l10_n197()
+ fun_l11_n930
+end
+
+def fun_l10_n198()
+ fun_l11_n680
+end
+
+def fun_l10_n199()
+ fun_l11_n820
+end
+
+def fun_l10_n200()
+ fun_l11_n699
+end
+
+def fun_l10_n201()
+ fun_l11_n246
+end
+
+def fun_l10_n202()
+ fun_l11_n238
+end
+
+def fun_l10_n203()
+ fun_l11_n481
+end
+
+def fun_l10_n204()
+ fun_l11_n586
+end
+
+def fun_l10_n205()
+ fun_l11_n550
+end
+
+def fun_l10_n206()
+ fun_l11_n662
+end
+
+def fun_l10_n207()
+ fun_l11_n680
+end
+
+def fun_l10_n208()
+ fun_l11_n544
+end
+
+def fun_l10_n209()
+ fun_l11_n927
+end
+
+def fun_l10_n210()
+ fun_l11_n383
+end
+
+def fun_l10_n211()
+ fun_l11_n21
+end
+
+def fun_l10_n212()
+ fun_l11_n628
+end
+
+def fun_l10_n213()
+ fun_l11_n635
+end
+
+def fun_l10_n214()
+ fun_l11_n648
+end
+
+def fun_l10_n215()
+ fun_l11_n349
+end
+
+def fun_l10_n216()
+ fun_l11_n242
+end
+
+def fun_l10_n217()
+ fun_l11_n868
+end
+
+def fun_l10_n218()
+ fun_l11_n804
+end
+
+def fun_l10_n219()
+ fun_l11_n84
+end
+
+def fun_l10_n220()
+ fun_l11_n970
+end
+
+def fun_l10_n221()
+ fun_l11_n400
+end
+
+def fun_l10_n222()
+ fun_l11_n133
+end
+
+def fun_l10_n223()
+ fun_l11_n58
+end
+
+def fun_l10_n224()
+ fun_l11_n790
+end
+
+def fun_l10_n225()
+ fun_l11_n738
+end
+
+def fun_l10_n226()
+ fun_l11_n682
+end
+
+def fun_l10_n227()
+ fun_l11_n822
+end
+
+def fun_l10_n228()
+ fun_l11_n630
+end
+
+def fun_l10_n229()
+ fun_l11_n399
+end
+
+def fun_l10_n230()
+ fun_l11_n177
+end
+
+def fun_l10_n231()
+ fun_l11_n531
+end
+
+def fun_l10_n232()
+ fun_l11_n671
+end
+
+def fun_l10_n233()
+ fun_l11_n34
+end
+
+def fun_l10_n234()
+ fun_l11_n305
+end
+
+def fun_l10_n235()
+ fun_l11_n410
+end
+
+def fun_l10_n236()
+ fun_l11_n72
+end
+
+def fun_l10_n237()
+ fun_l11_n236
+end
+
+def fun_l10_n238()
+ fun_l11_n135
+end
+
+def fun_l10_n239()
+ fun_l11_n718
+end
+
+def fun_l10_n240()
+ fun_l11_n453
+end
+
+def fun_l10_n241()
+ fun_l11_n965
+end
+
+def fun_l10_n242()
+ fun_l11_n919
+end
+
+def fun_l10_n243()
+ fun_l11_n56
+end
+
+def fun_l10_n244()
+ fun_l11_n853
+end
+
+def fun_l10_n245()
+ fun_l11_n719
+end
+
+def fun_l10_n246()
+ fun_l11_n45
+end
+
+def fun_l10_n247()
+ fun_l11_n344
+end
+
+def fun_l10_n248()
+ fun_l11_n907
+end
+
+def fun_l10_n249()
+ fun_l11_n340
+end
+
+def fun_l10_n250()
+ fun_l11_n625
+end
+
+def fun_l10_n251()
+ fun_l11_n274
+end
+
+def fun_l10_n252()
+ fun_l11_n392
+end
+
+def fun_l10_n253()
+ fun_l11_n15
+end
+
+def fun_l10_n254()
+ fun_l11_n474
+end
+
+def fun_l10_n255()
+ fun_l11_n792
+end
+
+def fun_l10_n256()
+ fun_l11_n580
+end
+
+def fun_l10_n257()
+ fun_l11_n375
+end
+
+def fun_l10_n258()
+ fun_l11_n169
+end
+
+def fun_l10_n259()
+ fun_l11_n792
+end
+
+def fun_l10_n260()
+ fun_l11_n553
+end
+
+def fun_l10_n261()
+ fun_l11_n919
+end
+
+def fun_l10_n262()
+ fun_l11_n814
+end
+
+def fun_l10_n263()
+ fun_l11_n845
+end
+
+def fun_l10_n264()
+ fun_l11_n337
+end
+
+def fun_l10_n265()
+ fun_l11_n362
+end
+
+def fun_l10_n266()
+ fun_l11_n400
+end
+
+def fun_l10_n267()
+ fun_l11_n335
+end
+
+def fun_l10_n268()
+ fun_l11_n142
+end
+
+def fun_l10_n269()
+ fun_l11_n262
+end
+
+def fun_l10_n270()
+ fun_l11_n969
+end
+
+def fun_l10_n271()
+ fun_l11_n599
+end
+
+def fun_l10_n272()
+ fun_l11_n763
+end
+
+def fun_l10_n273()
+ fun_l11_n154
+end
+
+def fun_l10_n274()
+ fun_l11_n289
+end
+
+def fun_l10_n275()
+ fun_l11_n852
+end
+
+def fun_l10_n276()
+ fun_l11_n994
+end
+
+def fun_l10_n277()
+ fun_l11_n583
+end
+
+def fun_l10_n278()
+ fun_l11_n580
+end
+
+def fun_l10_n279()
+ fun_l11_n610
+end
+
+def fun_l10_n280()
+ fun_l11_n624
+end
+
+def fun_l10_n281()
+ fun_l11_n987
+end
+
+def fun_l10_n282()
+ fun_l11_n973
+end
+
+def fun_l10_n283()
+ fun_l11_n128
+end
+
+def fun_l10_n284()
+ fun_l11_n864
+end
+
+def fun_l10_n285()
+ fun_l11_n270
+end
+
+def fun_l10_n286()
+ fun_l11_n878
+end
+
+def fun_l10_n287()
+ fun_l11_n242
+end
+
+def fun_l10_n288()
+ fun_l11_n214
+end
+
+def fun_l10_n289()
+ fun_l11_n51
+end
+
+def fun_l10_n290()
+ fun_l11_n122
+end
+
+def fun_l10_n291()
+ fun_l11_n288
+end
+
+def fun_l10_n292()
+ fun_l11_n751
+end
+
+def fun_l10_n293()
+ fun_l11_n723
+end
+
+def fun_l10_n294()
+ fun_l11_n884
+end
+
+def fun_l10_n295()
+ fun_l11_n671
+end
+
+def fun_l10_n296()
+ fun_l11_n949
+end
+
+def fun_l10_n297()
+ fun_l11_n859
+end
+
+def fun_l10_n298()
+ fun_l11_n293
+end
+
+def fun_l10_n299()
+ fun_l11_n548
+end
+
+def fun_l10_n300()
+ fun_l11_n659
+end
+
+def fun_l10_n301()
+ fun_l11_n434
+end
+
+def fun_l10_n302()
+ fun_l11_n251
+end
+
+def fun_l10_n303()
+ fun_l11_n225
+end
+
+def fun_l10_n304()
+ fun_l11_n242
+end
+
+def fun_l10_n305()
+ fun_l11_n401
+end
+
+def fun_l10_n306()
+ fun_l11_n603
+end
+
+def fun_l10_n307()
+ fun_l11_n926
+end
+
+def fun_l10_n308()
+ fun_l11_n922
+end
+
+def fun_l10_n309()
+ fun_l11_n27
+end
+
+def fun_l10_n310()
+ fun_l11_n834
+end
+
+def fun_l10_n311()
+ fun_l11_n119
+end
+
+def fun_l10_n312()
+ fun_l11_n391
+end
+
+def fun_l10_n313()
+ fun_l11_n768
+end
+
+def fun_l10_n314()
+ fun_l11_n147
+end
+
+def fun_l10_n315()
+ fun_l11_n472
+end
+
+def fun_l10_n316()
+ fun_l11_n107
+end
+
+def fun_l10_n317()
+ fun_l11_n682
+end
+
+def fun_l10_n318()
+ fun_l11_n670
+end
+
+def fun_l10_n319()
+ fun_l11_n827
+end
+
+def fun_l10_n320()
+ fun_l11_n812
+end
+
+def fun_l10_n321()
+ fun_l11_n737
+end
+
+def fun_l10_n322()
+ fun_l11_n446
+end
+
+def fun_l10_n323()
+ fun_l11_n312
+end
+
+def fun_l10_n324()
+ fun_l11_n697
+end
+
+def fun_l10_n325()
+ fun_l11_n785
+end
+
+def fun_l10_n326()
+ fun_l11_n379
+end
+
+def fun_l10_n327()
+ fun_l11_n994
+end
+
+def fun_l10_n328()
+ fun_l11_n651
+end
+
+def fun_l10_n329()
+ fun_l11_n896
+end
+
+def fun_l10_n330()
+ fun_l11_n289
+end
+
+def fun_l10_n331()
+ fun_l11_n217
+end
+
+def fun_l10_n332()
+ fun_l11_n502
+end
+
+def fun_l10_n333()
+ fun_l11_n24
+end
+
+def fun_l10_n334()
+ fun_l11_n187
+end
+
+def fun_l10_n335()
+ fun_l11_n301
+end
+
+def fun_l10_n336()
+ fun_l11_n640
+end
+
+def fun_l10_n337()
+ fun_l11_n90
+end
+
+def fun_l10_n338()
+ fun_l11_n226
+end
+
+def fun_l10_n339()
+ fun_l11_n192
+end
+
+def fun_l10_n340()
+ fun_l11_n737
+end
+
+def fun_l10_n341()
+ fun_l11_n197
+end
+
+def fun_l10_n342()
+ fun_l11_n859
+end
+
+def fun_l10_n343()
+ fun_l11_n406
+end
+
+def fun_l10_n344()
+ fun_l11_n179
+end
+
+def fun_l10_n345()
+ fun_l11_n535
+end
+
+def fun_l10_n346()
+ fun_l11_n330
+end
+
+def fun_l10_n347()
+ fun_l11_n117
+end
+
+def fun_l10_n348()
+ fun_l11_n399
+end
+
+def fun_l10_n349()
+ fun_l11_n129
+end
+
+def fun_l10_n350()
+ fun_l11_n295
+end
+
+def fun_l10_n351()
+ fun_l11_n226
+end
+
+def fun_l10_n352()
+ fun_l11_n551
+end
+
+def fun_l10_n353()
+ fun_l11_n394
+end
+
+def fun_l10_n354()
+ fun_l11_n120
+end
+
+def fun_l10_n355()
+ fun_l11_n713
+end
+
+def fun_l10_n356()
+ fun_l11_n873
+end
+
+def fun_l10_n357()
+ fun_l11_n841
+end
+
+def fun_l10_n358()
+ fun_l11_n708
+end
+
+def fun_l10_n359()
+ fun_l11_n351
+end
+
+def fun_l10_n360()
+ fun_l11_n753
+end
+
+def fun_l10_n361()
+ fun_l11_n397
+end
+
+def fun_l10_n362()
+ fun_l11_n986
+end
+
+def fun_l10_n363()
+ fun_l11_n544
+end
+
+def fun_l10_n364()
+ fun_l11_n476
+end
+
+def fun_l10_n365()
+ fun_l11_n596
+end
+
+def fun_l10_n366()
+ fun_l11_n922
+end
+
+def fun_l10_n367()
+ fun_l11_n137
+end
+
+def fun_l10_n368()
+ fun_l11_n87
+end
+
+def fun_l10_n369()
+ fun_l11_n537
+end
+
+def fun_l10_n370()
+ fun_l11_n678
+end
+
+def fun_l10_n371()
+ fun_l11_n729
+end
+
+def fun_l10_n372()
+ fun_l11_n286
+end
+
+def fun_l10_n373()
+ fun_l11_n831
+end
+
+def fun_l10_n374()
+ fun_l11_n130
+end
+
+def fun_l10_n375()
+ fun_l11_n853
+end
+
+def fun_l10_n376()
+ fun_l11_n876
+end
+
+def fun_l10_n377()
+ fun_l11_n291
+end
+
+def fun_l10_n378()
+ fun_l11_n823
+end
+
+def fun_l10_n379()
+ fun_l11_n66
+end
+
+def fun_l10_n380()
+ fun_l11_n460
+end
+
+def fun_l10_n381()
+ fun_l11_n261
+end
+
+def fun_l10_n382()
+ fun_l11_n632
+end
+
+def fun_l10_n383()
+ fun_l11_n341
+end
+
+def fun_l10_n384()
+ fun_l11_n158
+end
+
+def fun_l10_n385()
+ fun_l11_n105
+end
+
+def fun_l10_n386()
+ fun_l11_n735
+end
+
+def fun_l10_n387()
+ fun_l11_n659
+end
+
+def fun_l10_n388()
+ fun_l11_n232
+end
+
+def fun_l10_n389()
+ fun_l11_n909
+end
+
+def fun_l10_n390()
+ fun_l11_n594
+end
+
+def fun_l10_n391()
+ fun_l11_n347
+end
+
+def fun_l10_n392()
+ fun_l11_n650
+end
+
+def fun_l10_n393()
+ fun_l11_n652
+end
+
+def fun_l10_n394()
+ fun_l11_n129
+end
+
+def fun_l10_n395()
+ fun_l11_n791
+end
+
+def fun_l10_n396()
+ fun_l11_n933
+end
+
+def fun_l10_n397()
+ fun_l11_n903
+end
+
+def fun_l10_n398()
+ fun_l11_n301
+end
+
+def fun_l10_n399()
+ fun_l11_n102
+end
+
+def fun_l10_n400()
+ fun_l11_n865
+end
+
+def fun_l10_n401()
+ fun_l11_n112
+end
+
+def fun_l10_n402()
+ fun_l11_n242
+end
+
+def fun_l10_n403()
+ fun_l11_n928
+end
+
+def fun_l10_n404()
+ fun_l11_n289
+end
+
+def fun_l10_n405()
+ fun_l11_n435
+end
+
+def fun_l10_n406()
+ fun_l11_n303
+end
+
+def fun_l10_n407()
+ fun_l11_n979
+end
+
+def fun_l10_n408()
+ fun_l11_n785
+end
+
+def fun_l10_n409()
+ fun_l11_n241
+end
+
+def fun_l10_n410()
+ fun_l11_n32
+end
+
+def fun_l10_n411()
+ fun_l11_n821
+end
+
+def fun_l10_n412()
+ fun_l11_n748
+end
+
+def fun_l10_n413()
+ fun_l11_n454
+end
+
+def fun_l10_n414()
+ fun_l11_n555
+end
+
+def fun_l10_n415()
+ fun_l11_n136
+end
+
+def fun_l10_n416()
+ fun_l11_n996
+end
+
+def fun_l10_n417()
+ fun_l11_n987
+end
+
+def fun_l10_n418()
+ fun_l11_n987
+end
+
+def fun_l10_n419()
+ fun_l11_n817
+end
+
+def fun_l10_n420()
+ fun_l11_n674
+end
+
+def fun_l10_n421()
+ fun_l11_n57
+end
+
+def fun_l10_n422()
+ fun_l11_n43
+end
+
+def fun_l10_n423()
+ fun_l11_n767
+end
+
+def fun_l10_n424()
+ fun_l11_n924
+end
+
+def fun_l10_n425()
+ fun_l11_n63
+end
+
+def fun_l10_n426()
+ fun_l11_n636
+end
+
+def fun_l10_n427()
+ fun_l11_n824
+end
+
+def fun_l10_n428()
+ fun_l11_n266
+end
+
+def fun_l10_n429()
+ fun_l11_n540
+end
+
+def fun_l10_n430()
+ fun_l11_n992
+end
+
+def fun_l10_n431()
+ fun_l11_n215
+end
+
+def fun_l10_n432()
+ fun_l11_n28
+end
+
+def fun_l10_n433()
+ fun_l11_n37
+end
+
+def fun_l10_n434()
+ fun_l11_n38
+end
+
+def fun_l10_n435()
+ fun_l11_n937
+end
+
+def fun_l10_n436()
+ fun_l11_n419
+end
+
+def fun_l10_n437()
+ fun_l11_n390
+end
+
+def fun_l10_n438()
+ fun_l11_n987
+end
+
+def fun_l10_n439()
+ fun_l11_n742
+end
+
+def fun_l10_n440()
+ fun_l11_n173
+end
+
+def fun_l10_n441()
+ fun_l11_n640
+end
+
+def fun_l10_n442()
+ fun_l11_n111
+end
+
+def fun_l10_n443()
+ fun_l11_n492
+end
+
+def fun_l10_n444()
+ fun_l11_n659
+end
+
+def fun_l10_n445()
+ fun_l11_n863
+end
+
+def fun_l10_n446()
+ fun_l11_n938
+end
+
+def fun_l10_n447()
+ fun_l11_n54
+end
+
+def fun_l10_n448()
+ fun_l11_n224
+end
+
+def fun_l10_n449()
+ fun_l11_n863
+end
+
+def fun_l10_n450()
+ fun_l11_n80
+end
+
+def fun_l10_n451()
+ fun_l11_n791
+end
+
+def fun_l10_n452()
+ fun_l11_n93
+end
+
+def fun_l10_n453()
+ fun_l11_n416
+end
+
+def fun_l10_n454()
+ fun_l11_n610
+end
+
+def fun_l10_n455()
+ fun_l11_n455
+end
+
+def fun_l10_n456()
+ fun_l11_n834
+end
+
+def fun_l10_n457()
+ fun_l11_n462
+end
+
+def fun_l10_n458()
+ fun_l11_n69
+end
+
+def fun_l10_n459()
+ fun_l11_n174
+end
+
+def fun_l10_n460()
+ fun_l11_n657
+end
+
+def fun_l10_n461()
+ fun_l11_n608
+end
+
+def fun_l10_n462()
+ fun_l11_n248
+end
+
+def fun_l10_n463()
+ fun_l11_n492
+end
+
+def fun_l10_n464()
+ fun_l11_n125
+end
+
+def fun_l10_n465()
+ fun_l11_n737
+end
+
+def fun_l10_n466()
+ fun_l11_n354
+end
+
+def fun_l10_n467()
+ fun_l11_n890
+end
+
+def fun_l10_n468()
+ fun_l11_n753
+end
+
+def fun_l10_n469()
+ fun_l11_n380
+end
+
+def fun_l10_n470()
+ fun_l11_n428
+end
+
+def fun_l10_n471()
+ fun_l11_n243
+end
+
+def fun_l10_n472()
+ fun_l11_n532
+end
+
+def fun_l10_n473()
+ fun_l11_n328
+end
+
+def fun_l10_n474()
+ fun_l11_n922
+end
+
+def fun_l10_n475()
+ fun_l11_n115
+end
+
+def fun_l10_n476()
+ fun_l11_n705
+end
+
+def fun_l10_n477()
+ fun_l11_n457
+end
+
+def fun_l10_n478()
+ fun_l11_n201
+end
+
+def fun_l10_n479()
+ fun_l11_n801
+end
+
+def fun_l10_n480()
+ fun_l11_n492
+end
+
+def fun_l10_n481()
+ fun_l11_n148
+end
+
+def fun_l10_n482()
+ fun_l11_n802
+end
+
+def fun_l10_n483()
+ fun_l11_n725
+end
+
+def fun_l10_n484()
+ fun_l11_n835
+end
+
+def fun_l10_n485()
+ fun_l11_n564
+end
+
+def fun_l10_n486()
+ fun_l11_n803
+end
+
+def fun_l10_n487()
+ fun_l11_n696
+end
+
+def fun_l10_n488()
+ fun_l11_n171
+end
+
+def fun_l10_n489()
+ fun_l11_n759
+end
+
+def fun_l10_n490()
+ fun_l11_n728
+end
+
+def fun_l10_n491()
+ fun_l11_n64
+end
+
+def fun_l10_n492()
+ fun_l11_n717
+end
+
+def fun_l10_n493()
+ fun_l11_n97
+end
+
+def fun_l10_n494()
+ fun_l11_n157
+end
+
+def fun_l10_n495()
+ fun_l11_n589
+end
+
+def fun_l10_n496()
+ fun_l11_n642
+end
+
+def fun_l10_n497()
+ fun_l11_n994
+end
+
+def fun_l10_n498()
+ fun_l11_n566
+end
+
+def fun_l10_n499()
+ fun_l11_n325
+end
+
+def fun_l10_n500()
+ fun_l11_n905
+end
+
+def fun_l10_n501()
+ fun_l11_n242
+end
+
+def fun_l10_n502()
+ fun_l11_n135
+end
+
+def fun_l10_n503()
+ fun_l11_n476
+end
+
+def fun_l10_n504()
+ fun_l11_n63
+end
+
+def fun_l10_n505()
+ fun_l11_n908
+end
+
+def fun_l10_n506()
+ fun_l11_n51
+end
+
+def fun_l10_n507()
+ fun_l11_n261
+end
+
+def fun_l10_n508()
+ fun_l11_n680
+end
+
+def fun_l10_n509()
+ fun_l11_n346
+end
+
+def fun_l10_n510()
+ fun_l11_n490
+end
+
+def fun_l10_n511()
+ fun_l11_n896
+end
+
+def fun_l10_n512()
+ fun_l11_n788
+end
+
+def fun_l10_n513()
+ fun_l11_n672
+end
+
+def fun_l10_n514()
+ fun_l11_n17
+end
+
+def fun_l10_n515()
+ fun_l11_n744
+end
+
+def fun_l10_n516()
+ fun_l11_n90
+end
+
+def fun_l10_n517()
+ fun_l11_n451
+end
+
+def fun_l10_n518()
+ fun_l11_n942
+end
+
+def fun_l10_n519()
+ fun_l11_n275
+end
+
+def fun_l10_n520()
+ fun_l11_n422
+end
+
+def fun_l10_n521()
+ fun_l11_n463
+end
+
+def fun_l10_n522()
+ fun_l11_n198
+end
+
+def fun_l10_n523()
+ fun_l11_n703
+end
+
+def fun_l10_n524()
+ fun_l11_n745
+end
+
+def fun_l10_n525()
+ fun_l11_n476
+end
+
+def fun_l10_n526()
+ fun_l11_n122
+end
+
+def fun_l10_n527()
+ fun_l11_n111
+end
+
+def fun_l10_n528()
+ fun_l11_n354
+end
+
+def fun_l10_n529()
+ fun_l11_n63
+end
+
+def fun_l10_n530()
+ fun_l11_n652
+end
+
+def fun_l10_n531()
+ fun_l11_n535
+end
+
+def fun_l10_n532()
+ fun_l11_n990
+end
+
+def fun_l10_n533()
+ fun_l11_n506
+end
+
+def fun_l10_n534()
+ fun_l11_n741
+end
+
+def fun_l10_n535()
+ fun_l11_n12
+end
+
+def fun_l10_n536()
+ fun_l11_n138
+end
+
+def fun_l10_n537()
+ fun_l11_n247
+end
+
+def fun_l10_n538()
+ fun_l11_n469
+end
+
+def fun_l10_n539()
+ fun_l11_n574
+end
+
+def fun_l10_n540()
+ fun_l11_n474
+end
+
+def fun_l10_n541()
+ fun_l11_n639
+end
+
+def fun_l10_n542()
+ fun_l11_n932
+end
+
+def fun_l10_n543()
+ fun_l11_n587
+end
+
+def fun_l10_n544()
+ fun_l11_n502
+end
+
+def fun_l10_n545()
+ fun_l11_n134
+end
+
+def fun_l10_n546()
+ fun_l11_n470
+end
+
+def fun_l10_n547()
+ fun_l11_n118
+end
+
+def fun_l10_n548()
+ fun_l11_n253
+end
+
+def fun_l10_n549()
+ fun_l11_n331
+end
+
+def fun_l10_n550()
+ fun_l11_n461
+end
+
+def fun_l10_n551()
+ fun_l11_n807
+end
+
+def fun_l10_n552()
+ fun_l11_n266
+end
+
+def fun_l10_n553()
+ fun_l11_n537
+end
+
+def fun_l10_n554()
+ fun_l11_n649
+end
+
+def fun_l10_n555()
+ fun_l11_n620
+end
+
+def fun_l10_n556()
+ fun_l11_n646
+end
+
+def fun_l10_n557()
+ fun_l11_n972
+end
+
+def fun_l10_n558()
+ fun_l11_n311
+end
+
+def fun_l10_n559()
+ fun_l11_n555
+end
+
+def fun_l10_n560()
+ fun_l11_n930
+end
+
+def fun_l10_n561()
+ fun_l11_n249
+end
+
+def fun_l10_n562()
+ fun_l11_n270
+end
+
+def fun_l10_n563()
+ fun_l11_n769
+end
+
+def fun_l10_n564()
+ fun_l11_n281
+end
+
+def fun_l10_n565()
+ fun_l11_n213
+end
+
+def fun_l10_n566()
+ fun_l11_n849
+end
+
+def fun_l10_n567()
+ fun_l11_n665
+end
+
+def fun_l10_n568()
+ fun_l11_n339
+end
+
+def fun_l10_n569()
+ fun_l11_n476
+end
+
+def fun_l10_n570()
+ fun_l11_n732
+end
+
+def fun_l10_n571()
+ fun_l11_n266
+end
+
+def fun_l10_n572()
+ fun_l11_n85
+end
+
+def fun_l10_n573()
+ fun_l11_n260
+end
+
+def fun_l10_n574()
+ fun_l11_n275
+end
+
+def fun_l10_n575()
+ fun_l11_n673
+end
+
+def fun_l10_n576()
+ fun_l11_n252
+end
+
+def fun_l10_n577()
+ fun_l11_n376
+end
+
+def fun_l10_n578()
+ fun_l11_n407
+end
+
+def fun_l10_n579()
+ fun_l11_n134
+end
+
+def fun_l10_n580()
+ fun_l11_n825
+end
+
+def fun_l10_n581()
+ fun_l11_n266
+end
+
+def fun_l10_n582()
+ fun_l11_n40
+end
+
+def fun_l10_n583()
+ fun_l11_n346
+end
+
+def fun_l10_n584()
+ fun_l11_n503
+end
+
+def fun_l10_n585()
+ fun_l11_n743
+end
+
+def fun_l10_n586()
+ fun_l11_n199
+end
+
+def fun_l10_n587()
+ fun_l11_n268
+end
+
+def fun_l10_n588()
+ fun_l11_n6
+end
+
+def fun_l10_n589()
+ fun_l11_n859
+end
+
+def fun_l10_n590()
+ fun_l11_n499
+end
+
+def fun_l10_n591()
+ fun_l11_n397
+end
+
+def fun_l10_n592()
+ fun_l11_n580
+end
+
+def fun_l10_n593()
+ fun_l11_n299
+end
+
+def fun_l10_n594()
+ fun_l11_n691
+end
+
+def fun_l10_n595()
+ fun_l11_n973
+end
+
+def fun_l10_n596()
+ fun_l11_n987
+end
+
+def fun_l10_n597()
+ fun_l11_n342
+end
+
+def fun_l10_n598()
+ fun_l11_n556
+end
+
+def fun_l10_n599()
+ fun_l11_n754
+end
+
+def fun_l10_n600()
+ fun_l11_n54
+end
+
+def fun_l10_n601()
+ fun_l11_n334
+end
+
+def fun_l10_n602()
+ fun_l11_n6
+end
+
+def fun_l10_n603()
+ fun_l11_n574
+end
+
+def fun_l10_n604()
+ fun_l11_n615
+end
+
+def fun_l10_n605()
+ fun_l11_n314
+end
+
+def fun_l10_n606()
+ fun_l11_n659
+end
+
+def fun_l10_n607()
+ fun_l11_n41
+end
+
+def fun_l10_n608()
+ fun_l11_n119
+end
+
+def fun_l10_n609()
+ fun_l11_n204
+end
+
+def fun_l10_n610()
+ fun_l11_n952
+end
+
+def fun_l10_n611()
+ fun_l11_n587
+end
+
+def fun_l10_n612()
+ fun_l11_n87
+end
+
+def fun_l10_n613()
+ fun_l11_n840
+end
+
+def fun_l10_n614()
+ fun_l11_n520
+end
+
+def fun_l10_n615()
+ fun_l11_n814
+end
+
+def fun_l10_n616()
+ fun_l11_n595
+end
+
+def fun_l10_n617()
+ fun_l11_n765
+end
+
+def fun_l10_n618()
+ fun_l11_n383
+end
+
+def fun_l10_n619()
+ fun_l11_n277
+end
+
+def fun_l10_n620()
+ fun_l11_n897
+end
+
+def fun_l10_n621()
+ fun_l11_n131
+end
+
+def fun_l10_n622()
+ fun_l11_n674
+end
+
+def fun_l10_n623()
+ fun_l11_n971
+end
+
+def fun_l10_n624()
+ fun_l11_n503
+end
+
+def fun_l10_n625()
+ fun_l11_n471
+end
+
+def fun_l10_n626()
+ fun_l11_n805
+end
+
+def fun_l10_n627()
+ fun_l11_n58
+end
+
+def fun_l10_n628()
+ fun_l11_n784
+end
+
+def fun_l10_n629()
+ fun_l11_n222
+end
+
+def fun_l10_n630()
+ fun_l11_n382
+end
+
+def fun_l10_n631()
+ fun_l11_n239
+end
+
+def fun_l10_n632()
+ fun_l11_n53
+end
+
+def fun_l10_n633()
+ fun_l11_n730
+end
+
+def fun_l10_n634()
+ fun_l11_n522
+end
+
+def fun_l10_n635()
+ fun_l11_n182
+end
+
+def fun_l10_n636()
+ fun_l11_n837
+end
+
+def fun_l10_n637()
+ fun_l11_n815
+end
+
+def fun_l10_n638()
+ fun_l11_n754
+end
+
+def fun_l10_n639()
+ fun_l11_n74
+end
+
+def fun_l10_n640()
+ fun_l11_n695
+end
+
+def fun_l10_n641()
+ fun_l11_n454
+end
+
+def fun_l10_n642()
+ fun_l11_n250
+end
+
+def fun_l10_n643()
+ fun_l11_n385
+end
+
+def fun_l10_n644()
+ fun_l11_n115
+end
+
+def fun_l10_n645()
+ fun_l11_n624
+end
+
+def fun_l10_n646()
+ fun_l11_n697
+end
+
+def fun_l10_n647()
+ fun_l11_n184
+end
+
+def fun_l10_n648()
+ fun_l11_n921
+end
+
+def fun_l10_n649()
+ fun_l11_n699
+end
+
+def fun_l10_n650()
+ fun_l11_n952
+end
+
+def fun_l10_n651()
+ fun_l11_n879
+end
+
+def fun_l10_n652()
+ fun_l11_n569
+end
+
+def fun_l10_n653()
+ fun_l11_n85
+end
+
+def fun_l10_n654()
+ fun_l11_n316
+end
+
+def fun_l10_n655()
+ fun_l11_n203
+end
+
+def fun_l10_n656()
+ fun_l11_n424
+end
+
+def fun_l10_n657()
+ fun_l11_n731
+end
+
+def fun_l10_n658()
+ fun_l11_n65
+end
+
+def fun_l10_n659()
+ fun_l11_n232
+end
+
+def fun_l10_n660()
+ fun_l11_n306
+end
+
+def fun_l10_n661()
+ fun_l11_n71
+end
+
+def fun_l10_n662()
+ fun_l11_n577
+end
+
+def fun_l10_n663()
+ fun_l11_n670
+end
+
+def fun_l10_n664()
+ fun_l11_n905
+end
+
+def fun_l10_n665()
+ fun_l11_n717
+end
+
+def fun_l10_n666()
+ fun_l11_n198
+end
+
+def fun_l10_n667()
+ fun_l11_n982
+end
+
+def fun_l10_n668()
+ fun_l11_n933
+end
+
+def fun_l10_n669()
+ fun_l11_n446
+end
+
+def fun_l10_n670()
+ fun_l11_n913
+end
+
+def fun_l10_n671()
+ fun_l11_n794
+end
+
+def fun_l10_n672()
+ fun_l11_n604
+end
+
+def fun_l10_n673()
+ fun_l11_n408
+end
+
+def fun_l10_n674()
+ fun_l11_n297
+end
+
+def fun_l10_n675()
+ fun_l11_n113
+end
+
+def fun_l10_n676()
+ fun_l11_n197
+end
+
+def fun_l10_n677()
+ fun_l11_n606
+end
+
+def fun_l10_n678()
+ fun_l11_n333
+end
+
+def fun_l10_n679()
+ fun_l11_n130
+end
+
+def fun_l10_n680()
+ fun_l11_n893
+end
+
+def fun_l10_n681()
+ fun_l11_n997
+end
+
+def fun_l10_n682()
+ fun_l11_n826
+end
+
+def fun_l10_n683()
+ fun_l11_n889
+end
+
+def fun_l10_n684()
+ fun_l11_n887
+end
+
+def fun_l10_n685()
+ fun_l11_n913
+end
+
+def fun_l10_n686()
+ fun_l11_n563
+end
+
+def fun_l10_n687()
+ fun_l11_n112
+end
+
+def fun_l10_n688()
+ fun_l11_n527
+end
+
+def fun_l10_n689()
+ fun_l11_n423
+end
+
+def fun_l10_n690()
+ fun_l11_n906
+end
+
+def fun_l10_n691()
+ fun_l11_n134
+end
+
+def fun_l10_n692()
+ fun_l11_n549
+end
+
+def fun_l10_n693()
+ fun_l11_n864
+end
+
+def fun_l10_n694()
+ fun_l11_n750
+end
+
+def fun_l10_n695()
+ fun_l11_n357
+end
+
+def fun_l10_n696()
+ fun_l11_n79
+end
+
+def fun_l10_n697()
+ fun_l11_n99
+end
+
+def fun_l10_n698()
+ fun_l11_n638
+end
+
+def fun_l10_n699()
+ fun_l11_n946
+end
+
+def fun_l10_n700()
+ fun_l11_n498
+end
+
+def fun_l10_n701()
+ fun_l11_n490
+end
+
+def fun_l10_n702()
+ fun_l11_n860
+end
+
+def fun_l10_n703()
+ fun_l11_n194
+end
+
+def fun_l10_n704()
+ fun_l11_n130
+end
+
+def fun_l10_n705()
+ fun_l11_n647
+end
+
+def fun_l10_n706()
+ fun_l11_n162
+end
+
+def fun_l10_n707()
+ fun_l11_n41
+end
+
+def fun_l10_n708()
+ fun_l11_n583
+end
+
+def fun_l10_n709()
+ fun_l11_n687
+end
+
+def fun_l10_n710()
+ fun_l11_n83
+end
+
+def fun_l10_n711()
+ fun_l11_n365
+end
+
+def fun_l10_n712()
+ fun_l11_n797
+end
+
+def fun_l10_n713()
+ fun_l11_n730
+end
+
+def fun_l10_n714()
+ fun_l11_n844
+end
+
+def fun_l10_n715()
+ fun_l11_n514
+end
+
+def fun_l10_n716()
+ fun_l11_n212
+end
+
+def fun_l10_n717()
+ fun_l11_n600
+end
+
+def fun_l10_n718()
+ fun_l11_n823
+end
+
+def fun_l10_n719()
+ fun_l11_n439
+end
+
+def fun_l10_n720()
+ fun_l11_n361
+end
+
+def fun_l10_n721()
+ fun_l11_n390
+end
+
+def fun_l10_n722()
+ fun_l11_n10
+end
+
+def fun_l10_n723()
+ fun_l11_n984
+end
+
+def fun_l10_n724()
+ fun_l11_n193
+end
+
+def fun_l10_n725()
+ fun_l11_n584
+end
+
+def fun_l10_n726()
+ fun_l11_n552
+end
+
+def fun_l10_n727()
+ fun_l11_n795
+end
+
+def fun_l10_n728()
+ fun_l11_n958
+end
+
+def fun_l10_n729()
+ fun_l11_n408
+end
+
+def fun_l10_n730()
+ fun_l11_n584
+end
+
+def fun_l10_n731()
+ fun_l11_n707
+end
+
+def fun_l10_n732()
+ fun_l11_n291
+end
+
+def fun_l10_n733()
+ fun_l11_n777
+end
+
+def fun_l10_n734()
+ fun_l11_n634
+end
+
+def fun_l10_n735()
+ fun_l11_n716
+end
+
+def fun_l10_n736()
+ fun_l11_n167
+end
+
+def fun_l10_n737()
+ fun_l11_n119
+end
+
+def fun_l10_n738()
+ fun_l11_n835
+end
+
+def fun_l10_n739()
+ fun_l11_n53
+end
+
+def fun_l10_n740()
+ fun_l11_n743
+end
+
+def fun_l10_n741()
+ fun_l11_n564
+end
+
+def fun_l10_n742()
+ fun_l11_n917
+end
+
+def fun_l10_n743()
+ fun_l11_n848
+end
+
+def fun_l10_n744()
+ fun_l11_n135
+end
+
+def fun_l10_n745()
+ fun_l11_n159
+end
+
+def fun_l10_n746()
+ fun_l11_n374
+end
+
+def fun_l10_n747()
+ fun_l11_n885
+end
+
+def fun_l10_n748()
+ fun_l11_n0
+end
+
+def fun_l10_n749()
+ fun_l11_n735
+end
+
+def fun_l10_n750()
+ fun_l11_n995
+end
+
+def fun_l10_n751()
+ fun_l11_n522
+end
+
+def fun_l10_n752()
+ fun_l11_n166
+end
+
+def fun_l10_n753()
+ fun_l11_n191
+end
+
+def fun_l10_n754()
+ fun_l11_n820
+end
+
+def fun_l10_n755()
+ fun_l11_n180
+end
+
+def fun_l10_n756()
+ fun_l11_n480
+end
+
+def fun_l10_n757()
+ fun_l11_n107
+end
+
+def fun_l10_n758()
+ fun_l11_n263
+end
+
+def fun_l10_n759()
+ fun_l11_n534
+end
+
+def fun_l10_n760()
+ fun_l11_n442
+end
+
+def fun_l10_n761()
+ fun_l11_n719
+end
+
+def fun_l10_n762()
+ fun_l11_n778
+end
+
+def fun_l10_n763()
+ fun_l11_n297
+end
+
+def fun_l10_n764()
+ fun_l11_n582
+end
+
+def fun_l10_n765()
+ fun_l11_n230
+end
+
+def fun_l10_n766()
+ fun_l11_n921
+end
+
+def fun_l10_n767()
+ fun_l11_n629
+end
+
+def fun_l10_n768()
+ fun_l11_n473
+end
+
+def fun_l10_n769()
+ fun_l11_n563
+end
+
+def fun_l10_n770()
+ fun_l11_n61
+end
+
+def fun_l10_n771()
+ fun_l11_n343
+end
+
+def fun_l10_n772()
+ fun_l11_n713
+end
+
+def fun_l10_n773()
+ fun_l11_n724
+end
+
+def fun_l10_n774()
+ fun_l11_n454
+end
+
+def fun_l10_n775()
+ fun_l11_n680
+end
+
+def fun_l10_n776()
+ fun_l11_n620
+end
+
+def fun_l10_n777()
+ fun_l11_n949
+end
+
+def fun_l10_n778()
+ fun_l11_n208
+end
+
+def fun_l10_n779()
+ fun_l11_n904
+end
+
+def fun_l10_n780()
+ fun_l11_n88
+end
+
+def fun_l10_n781()
+ fun_l11_n710
+end
+
+def fun_l10_n782()
+ fun_l11_n875
+end
+
+def fun_l10_n783()
+ fun_l11_n970
+end
+
+def fun_l10_n784()
+ fun_l11_n123
+end
+
+def fun_l10_n785()
+ fun_l11_n420
+end
+
+def fun_l10_n786()
+ fun_l11_n122
+end
+
+def fun_l10_n787()
+ fun_l11_n200
+end
+
+def fun_l10_n788()
+ fun_l11_n716
+end
+
+def fun_l10_n789()
+ fun_l11_n592
+end
+
+def fun_l10_n790()
+ fun_l11_n159
+end
+
+def fun_l10_n791()
+ fun_l11_n852
+end
+
+def fun_l10_n792()
+ fun_l11_n913
+end
+
+def fun_l10_n793()
+ fun_l11_n305
+end
+
+def fun_l10_n794()
+ fun_l11_n123
+end
+
+def fun_l10_n795()
+ fun_l11_n210
+end
+
+def fun_l10_n796()
+ fun_l11_n416
+end
+
+def fun_l10_n797()
+ fun_l11_n800
+end
+
+def fun_l10_n798()
+ fun_l11_n689
+end
+
+def fun_l10_n799()
+ fun_l11_n358
+end
+
+def fun_l10_n800()
+ fun_l11_n542
+end
+
+def fun_l10_n801()
+ fun_l11_n715
+end
+
+def fun_l10_n802()
+ fun_l11_n879
+end
+
+def fun_l10_n803()
+ fun_l11_n414
+end
+
+def fun_l10_n804()
+ fun_l11_n623
+end
+
+def fun_l10_n805()
+ fun_l11_n282
+end
+
+def fun_l10_n806()
+ fun_l11_n719
+end
+
+def fun_l10_n807()
+ fun_l11_n111
+end
+
+def fun_l10_n808()
+ fun_l11_n348
+end
+
+def fun_l10_n809()
+ fun_l11_n836
+end
+
+def fun_l10_n810()
+ fun_l11_n878
+end
+
+def fun_l10_n811()
+ fun_l11_n569
+end
+
+def fun_l10_n812()
+ fun_l11_n701
+end
+
+def fun_l10_n813()
+ fun_l11_n602
+end
+
+def fun_l10_n814()
+ fun_l11_n746
+end
+
+def fun_l10_n815()
+ fun_l11_n892
+end
+
+def fun_l10_n816()
+ fun_l11_n150
+end
+
+def fun_l10_n817()
+ fun_l11_n804
+end
+
+def fun_l10_n818()
+ fun_l11_n459
+end
+
+def fun_l10_n819()
+ fun_l11_n932
+end
+
+def fun_l10_n820()
+ fun_l11_n492
+end
+
+def fun_l10_n821()
+ fun_l11_n351
+end
+
+def fun_l10_n822()
+ fun_l11_n933
+end
+
+def fun_l10_n823()
+ fun_l11_n328
+end
+
+def fun_l10_n824()
+ fun_l11_n75
+end
+
+def fun_l10_n825()
+ fun_l11_n935
+end
+
+def fun_l10_n826()
+ fun_l11_n495
+end
+
+def fun_l10_n827()
+ fun_l11_n328
+end
+
+def fun_l10_n828()
+ fun_l11_n888
+end
+
+def fun_l10_n829()
+ fun_l11_n547
+end
+
+def fun_l10_n830()
+ fun_l11_n315
+end
+
+def fun_l10_n831()
+ fun_l11_n243
+end
+
+def fun_l10_n832()
+ fun_l11_n972
+end
+
+def fun_l10_n833()
+ fun_l11_n33
+end
+
+def fun_l10_n834()
+ fun_l11_n765
+end
+
+def fun_l10_n835()
+ fun_l11_n614
+end
+
+def fun_l10_n836()
+ fun_l11_n686
+end
+
+def fun_l10_n837()
+ fun_l11_n373
+end
+
+def fun_l10_n838()
+ fun_l11_n534
+end
+
+def fun_l10_n839()
+ fun_l11_n375
+end
+
+def fun_l10_n840()
+ fun_l11_n297
+end
+
+def fun_l10_n841()
+ fun_l11_n107
+end
+
+def fun_l10_n842()
+ fun_l11_n409
+end
+
+def fun_l10_n843()
+ fun_l11_n24
+end
+
+def fun_l10_n844()
+ fun_l11_n43
+end
+
+def fun_l10_n845()
+ fun_l11_n93
+end
+
+def fun_l10_n846()
+ fun_l11_n667
+end
+
+def fun_l10_n847()
+ fun_l11_n520
+end
+
+def fun_l10_n848()
+ fun_l11_n109
+end
+
+def fun_l10_n849()
+ fun_l11_n829
+end
+
+def fun_l10_n850()
+ fun_l11_n946
+end
+
+def fun_l10_n851()
+ fun_l11_n232
+end
+
+def fun_l10_n852()
+ fun_l11_n568
+end
+
+def fun_l10_n853()
+ fun_l11_n589
+end
+
+def fun_l10_n854()
+ fun_l11_n76
+end
+
+def fun_l10_n855()
+ fun_l11_n106
+end
+
+def fun_l10_n856()
+ fun_l11_n46
+end
+
+def fun_l10_n857()
+ fun_l11_n261
+end
+
+def fun_l10_n858()
+ fun_l11_n788
+end
+
+def fun_l10_n859()
+ fun_l11_n289
+end
+
+def fun_l10_n860()
+ fun_l11_n269
+end
+
+def fun_l10_n861()
+ fun_l11_n669
+end
+
+def fun_l10_n862()
+ fun_l11_n925
+end
+
+def fun_l10_n863()
+ fun_l11_n782
+end
+
+def fun_l10_n864()
+ fun_l11_n432
+end
+
+def fun_l10_n865()
+ fun_l11_n278
+end
+
+def fun_l10_n866()
+ fun_l11_n380
+end
+
+def fun_l10_n867()
+ fun_l11_n488
+end
+
+def fun_l10_n868()
+ fun_l11_n718
+end
+
+def fun_l10_n869()
+ fun_l11_n569
+end
+
+def fun_l10_n870()
+ fun_l11_n59
+end
+
+def fun_l10_n871()
+ fun_l11_n581
+end
+
+def fun_l10_n872()
+ fun_l11_n128
+end
+
+def fun_l10_n873()
+ fun_l11_n200
+end
+
+def fun_l10_n874()
+ fun_l11_n258
+end
+
+def fun_l10_n875()
+ fun_l11_n869
+end
+
+def fun_l10_n876()
+ fun_l11_n337
+end
+
+def fun_l10_n877()
+ fun_l11_n11
+end
+
+def fun_l10_n878()
+ fun_l11_n968
+end
+
+def fun_l10_n879()
+ fun_l11_n188
+end
+
+def fun_l10_n880()
+ fun_l11_n361
+end
+
+def fun_l10_n881()
+ fun_l11_n268
+end
+
+def fun_l10_n882()
+ fun_l11_n518
+end
+
+def fun_l10_n883()
+ fun_l11_n253
+end
+
+def fun_l10_n884()
+ fun_l11_n159
+end
+
+def fun_l10_n885()
+ fun_l11_n977
+end
+
+def fun_l10_n886()
+ fun_l11_n602
+end
+
+def fun_l10_n887()
+ fun_l11_n957
+end
+
+def fun_l10_n888()
+ fun_l11_n53
+end
+
+def fun_l10_n889()
+ fun_l11_n680
+end
+
+def fun_l10_n890()
+ fun_l11_n6
+end
+
+def fun_l10_n891()
+ fun_l11_n202
+end
+
+def fun_l10_n892()
+ fun_l11_n25
+end
+
+def fun_l10_n893()
+ fun_l11_n857
+end
+
+def fun_l10_n894()
+ fun_l11_n505
+end
+
+def fun_l10_n895()
+ fun_l11_n966
+end
+
+def fun_l10_n896()
+ fun_l11_n381
+end
+
+def fun_l10_n897()
+ fun_l11_n811
+end
+
+def fun_l10_n898()
+ fun_l11_n863
+end
+
+def fun_l10_n899()
+ fun_l11_n902
+end
+
+def fun_l10_n900()
+ fun_l11_n711
+end
+
+def fun_l10_n901()
+ fun_l11_n42
+end
+
+def fun_l10_n902()
+ fun_l11_n324
+end
+
+def fun_l10_n903()
+ fun_l11_n729
+end
+
+def fun_l10_n904()
+ fun_l11_n535
+end
+
+def fun_l10_n905()
+ fun_l11_n427
+end
+
+def fun_l10_n906()
+ fun_l11_n469
+end
+
+def fun_l10_n907()
+ fun_l11_n887
+end
+
+def fun_l10_n908()
+ fun_l11_n822
+end
+
+def fun_l10_n909()
+ fun_l11_n567
+end
+
+def fun_l10_n910()
+ fun_l11_n2
+end
+
+def fun_l10_n911()
+ fun_l11_n957
+end
+
+def fun_l10_n912()
+ fun_l11_n850
+end
+
+def fun_l10_n913()
+ fun_l11_n146
+end
+
+def fun_l10_n914()
+ fun_l11_n318
+end
+
+def fun_l10_n915()
+ fun_l11_n452
+end
+
+def fun_l10_n916()
+ fun_l11_n366
+end
+
+def fun_l10_n917()
+ fun_l11_n126
+end
+
+def fun_l10_n918()
+ fun_l11_n56
+end
+
+def fun_l10_n919()
+ fun_l11_n742
+end
+
+def fun_l10_n920()
+ fun_l11_n1
+end
+
+def fun_l10_n921()
+ fun_l11_n778
+end
+
+def fun_l10_n922()
+ fun_l11_n703
+end
+
+def fun_l10_n923()
+ fun_l11_n622
+end
+
+def fun_l10_n924()
+ fun_l11_n942
+end
+
+def fun_l10_n925()
+ fun_l11_n909
+end
+
+def fun_l10_n926()
+ fun_l11_n98
+end
+
+def fun_l10_n927()
+ fun_l11_n518
+end
+
+def fun_l10_n928()
+ fun_l11_n932
+end
+
+def fun_l10_n929()
+ fun_l11_n768
+end
+
+def fun_l10_n930()
+ fun_l11_n846
+end
+
+def fun_l10_n931()
+ fun_l11_n231
+end
+
+def fun_l10_n932()
+ fun_l11_n944
+end
+
+def fun_l10_n933()
+ fun_l11_n561
+end
+
+def fun_l10_n934()
+ fun_l11_n587
+end
+
+def fun_l10_n935()
+ fun_l11_n372
+end
+
+def fun_l10_n936()
+ fun_l11_n322
+end
+
+def fun_l10_n937()
+ fun_l11_n416
+end
+
+def fun_l10_n938()
+ fun_l11_n191
+end
+
+def fun_l10_n939()
+ fun_l11_n915
+end
+
+def fun_l10_n940()
+ fun_l11_n215
+end
+
+def fun_l10_n941()
+ fun_l11_n271
+end
+
+def fun_l10_n942()
+ fun_l11_n890
+end
+
+def fun_l10_n943()
+ fun_l11_n914
+end
+
+def fun_l10_n944()
+ fun_l11_n313
+end
+
+def fun_l10_n945()
+ fun_l11_n705
+end
+
+def fun_l10_n946()
+ fun_l11_n725
+end
+
+def fun_l10_n947()
+ fun_l11_n46
+end
+
+def fun_l10_n948()
+ fun_l11_n793
+end
+
+def fun_l10_n949()
+ fun_l11_n986
+end
+
+def fun_l10_n950()
+ fun_l11_n607
+end
+
+def fun_l10_n951()
+ fun_l11_n429
+end
+
+def fun_l10_n952()
+ fun_l11_n251
+end
+
+def fun_l10_n953()
+ fun_l11_n264
+end
+
+def fun_l10_n954()
+ fun_l11_n677
+end
+
+def fun_l10_n955()
+ fun_l11_n616
+end
+
+def fun_l10_n956()
+ fun_l11_n264
+end
+
+def fun_l10_n957()
+ fun_l11_n188
+end
+
+def fun_l10_n958()
+ fun_l11_n834
+end
+
+def fun_l10_n959()
+ fun_l11_n231
+end
+
+def fun_l10_n960()
+ fun_l11_n584
+end
+
+def fun_l10_n961()
+ fun_l11_n153
+end
+
+def fun_l10_n962()
+ fun_l11_n215
+end
+
+def fun_l10_n963()
+ fun_l11_n902
+end
+
+def fun_l10_n964()
+ fun_l11_n600
+end
+
+def fun_l10_n965()
+ fun_l11_n113
+end
+
+def fun_l10_n966()
+ fun_l11_n264
+end
+
+def fun_l10_n967()
+ fun_l11_n92
+end
+
+def fun_l10_n968()
+ fun_l11_n346
+end
+
+def fun_l10_n969()
+ fun_l11_n531
+end
+
+def fun_l10_n970()
+ fun_l11_n134
+end
+
+def fun_l10_n971()
+ fun_l11_n883
+end
+
+def fun_l10_n972()
+ fun_l11_n662
+end
+
+def fun_l10_n973()
+ fun_l11_n836
+end
+
+def fun_l10_n974()
+ fun_l11_n418
+end
+
+def fun_l10_n975()
+ fun_l11_n384
+end
+
+def fun_l10_n976()
+ fun_l11_n57
+end
+
+def fun_l10_n977()
+ fun_l11_n827
+end
+
+def fun_l10_n978()
+ fun_l11_n114
+end
+
+def fun_l10_n979()
+ fun_l11_n720
+end
+
+def fun_l10_n980()
+ fun_l11_n328
+end
+
+def fun_l10_n981()
+ fun_l11_n597
+end
+
+def fun_l10_n982()
+ fun_l11_n941
+end
+
+def fun_l10_n983()
+ fun_l11_n848
+end
+
+def fun_l10_n984()
+ fun_l11_n269
+end
+
+def fun_l10_n985()
+ fun_l11_n666
+end
+
+def fun_l10_n986()
+ fun_l11_n538
+end
+
+def fun_l10_n987()
+ fun_l11_n755
+end
+
+def fun_l10_n988()
+ fun_l11_n747
+end
+
+def fun_l10_n989()
+ fun_l11_n100
+end
+
+def fun_l10_n990()
+ fun_l11_n995
+end
+
+def fun_l10_n991()
+ fun_l11_n904
+end
+
+def fun_l10_n992()
+ fun_l11_n948
+end
+
+def fun_l10_n993()
+ fun_l11_n135
+end
+
+def fun_l10_n994()
+ fun_l11_n120
+end
+
+def fun_l10_n995()
+ fun_l11_n156
+end
+
+def fun_l10_n996()
+ fun_l11_n264
+end
+
+def fun_l10_n997()
+ fun_l11_n522
+end
+
+def fun_l10_n998()
+ fun_l11_n105
+end
+
+def fun_l10_n999()
+ fun_l11_n919
+end
+
+def fun_l11_n0()
+ fun_l12_n731
+end
+
+def fun_l11_n1()
+ fun_l12_n521
+end
+
+def fun_l11_n2()
+ fun_l12_n875
+end
+
+def fun_l11_n3()
+ fun_l12_n806
+end
+
+def fun_l11_n4()
+ fun_l12_n211
+end
+
+def fun_l11_n5()
+ fun_l12_n965
+end
+
+def fun_l11_n6()
+ fun_l12_n770
+end
+
+def fun_l11_n7()
+ fun_l12_n440
+end
+
+def fun_l11_n8()
+ fun_l12_n900
+end
+
+def fun_l11_n9()
+ fun_l12_n581
+end
+
+def fun_l11_n10()
+ fun_l12_n427
+end
+
+def fun_l11_n11()
+ fun_l12_n156
+end
+
+def fun_l11_n12()
+ fun_l12_n941
+end
+
+def fun_l11_n13()
+ fun_l12_n711
+end
+
+def fun_l11_n14()
+ fun_l12_n69
+end
+
+def fun_l11_n15()
+ fun_l12_n665
+end
+
+def fun_l11_n16()
+ fun_l12_n325
+end
+
+def fun_l11_n17()
+ fun_l12_n120
+end
+
+def fun_l11_n18()
+ fun_l12_n455
+end
+
+def fun_l11_n19()
+ fun_l12_n14
+end
+
+def fun_l11_n20()
+ fun_l12_n909
+end
+
+def fun_l11_n21()
+ fun_l12_n297
+end
+
+def fun_l11_n22()
+ fun_l12_n81
+end
+
+def fun_l11_n23()
+ fun_l12_n420
+end
+
+def fun_l11_n24()
+ fun_l12_n439
+end
+
+def fun_l11_n25()
+ fun_l12_n867
+end
+
+def fun_l11_n26()
+ fun_l12_n147
+end
+
+def fun_l11_n27()
+ fun_l12_n422
+end
+
+def fun_l11_n28()
+ fun_l12_n338
+end
+
+def fun_l11_n29()
+ fun_l12_n730
+end
+
+def fun_l11_n30()
+ fun_l12_n15
+end
+
+def fun_l11_n31()
+ fun_l12_n276
+end
+
+def fun_l11_n32()
+ fun_l12_n298
+end
+
+def fun_l11_n33()
+ fun_l12_n749
+end
+
+def fun_l11_n34()
+ fun_l12_n255
+end
+
+def fun_l11_n35()
+ fun_l12_n104
+end
+
+def fun_l11_n36()
+ fun_l12_n91
+end
+
+def fun_l11_n37()
+ fun_l12_n825
+end
+
+def fun_l11_n38()
+ fun_l12_n983
+end
+
+def fun_l11_n39()
+ fun_l12_n711
+end
+
+def fun_l11_n40()
+ fun_l12_n991
+end
+
+def fun_l11_n41()
+ fun_l12_n143
+end
+
+def fun_l11_n42()
+ fun_l12_n579
+end
+
+def fun_l11_n43()
+ fun_l12_n217
+end
+
+def fun_l11_n44()
+ fun_l12_n353
+end
+
+def fun_l11_n45()
+ fun_l12_n849
+end
+
+def fun_l11_n46()
+ fun_l12_n452
+end
+
+def fun_l11_n47()
+ fun_l12_n982
+end
+
+def fun_l11_n48()
+ fun_l12_n201
+end
+
+def fun_l11_n49()
+ fun_l12_n289
+end
+
+def fun_l11_n50()
+ fun_l12_n419
+end
+
+def fun_l11_n51()
+ fun_l12_n490
+end
+
+def fun_l11_n52()
+ fun_l12_n969
+end
+
+def fun_l11_n53()
+ fun_l12_n721
+end
+
+def fun_l11_n54()
+ fun_l12_n657
+end
+
+def fun_l11_n55()
+ fun_l12_n498
+end
+
+def fun_l11_n56()
+ fun_l12_n44
+end
+
+def fun_l11_n57()
+ fun_l12_n863
+end
+
+def fun_l11_n58()
+ fun_l12_n366
+end
+
+def fun_l11_n59()
+ fun_l12_n515
+end
+
+def fun_l11_n60()
+ fun_l12_n302
+end
+
+def fun_l11_n61()
+ fun_l12_n717
+end
+
+def fun_l11_n62()
+ fun_l12_n165
+end
+
+def fun_l11_n63()
+ fun_l12_n980
+end
+
+def fun_l11_n64()
+ fun_l12_n988
+end
+
+def fun_l11_n65()
+ fun_l12_n397
+end
+
+def fun_l11_n66()
+ fun_l12_n648
+end
+
+def fun_l11_n67()
+ fun_l12_n8
+end
+
+def fun_l11_n68()
+ fun_l12_n164
+end
+
+def fun_l11_n69()
+ fun_l12_n999
+end
+
+def fun_l11_n70()
+ fun_l12_n434
+end
+
+def fun_l11_n71()
+ fun_l12_n991
+end
+
+def fun_l11_n72()
+ fun_l12_n596
+end
+
+def fun_l11_n73()
+ fun_l12_n533
+end
+
+def fun_l11_n74()
+ fun_l12_n222
+end
+
+def fun_l11_n75()
+ fun_l12_n817
+end
+
+def fun_l11_n76()
+ fun_l12_n740
+end
+
+def fun_l11_n77()
+ fun_l12_n638
+end
+
+def fun_l11_n78()
+ fun_l12_n81
+end
+
+def fun_l11_n79()
+ fun_l12_n702
+end
+
+def fun_l11_n80()
+ fun_l12_n783
+end
+
+def fun_l11_n81()
+ fun_l12_n228
+end
+
+def fun_l11_n82()
+ fun_l12_n487
+end
+
+def fun_l11_n83()
+ fun_l12_n59
+end
+
+def fun_l11_n84()
+ fun_l12_n910
+end
+
+def fun_l11_n85()
+ fun_l12_n581
+end
+
+def fun_l11_n86()
+ fun_l12_n947
+end
+
+def fun_l11_n87()
+ fun_l12_n645
+end
+
+def fun_l11_n88()
+ fun_l12_n505
+end
+
+def fun_l11_n89()
+ fun_l12_n171
+end
+
+def fun_l11_n90()
+ fun_l12_n713
+end
+
+def fun_l11_n91()
+ fun_l12_n414
+end
+
+def fun_l11_n92()
+ fun_l12_n427
+end
+
+def fun_l11_n93()
+ fun_l12_n225
+end
+
+def fun_l11_n94()
+ fun_l12_n655
+end
+
+def fun_l11_n95()
+ fun_l12_n437
+end
+
+def fun_l11_n96()
+ fun_l12_n879
+end
+
+def fun_l11_n97()
+ fun_l12_n222
+end
+
+def fun_l11_n98()
+ fun_l12_n642
+end
+
+def fun_l11_n99()
+ fun_l12_n142
+end
+
+def fun_l11_n100()
+ fun_l12_n612
+end
+
+def fun_l11_n101()
+ fun_l12_n548
+end
+
+def fun_l11_n102()
+ fun_l12_n535
+end
+
+def fun_l11_n103()
+ fun_l12_n245
+end
+
+def fun_l11_n104()
+ fun_l12_n0
+end
+
+def fun_l11_n105()
+ fun_l12_n305
+end
+
+def fun_l11_n106()
+ fun_l12_n674
+end
+
+def fun_l11_n107()
+ fun_l12_n626
+end
+
+def fun_l11_n108()
+ fun_l12_n335
+end
+
+def fun_l11_n109()
+ fun_l12_n963
+end
+
+def fun_l11_n110()
+ fun_l12_n958
+end
+
+def fun_l11_n111()
+ fun_l12_n32
+end
+
+def fun_l11_n112()
+ fun_l12_n149
+end
+
+def fun_l11_n113()
+ fun_l12_n923
+end
+
+def fun_l11_n114()
+ fun_l12_n853
+end
+
+def fun_l11_n115()
+ fun_l12_n793
+end
+
+def fun_l11_n116()
+ fun_l12_n354
+end
+
+def fun_l11_n117()
+ fun_l12_n839
+end
+
+def fun_l11_n118()
+ fun_l12_n995
+end
+
+def fun_l11_n119()
+ fun_l12_n610
+end
+
+def fun_l11_n120()
+ fun_l12_n147
+end
+
+def fun_l11_n121()
+ fun_l12_n191
+end
+
+def fun_l11_n122()
+ fun_l12_n237
+end
+
+def fun_l11_n123()
+ fun_l12_n766
+end
+
+def fun_l11_n124()
+ fun_l12_n830
+end
+
+def fun_l11_n125()
+ fun_l12_n968
+end
+
+def fun_l11_n126()
+ fun_l12_n163
+end
+
+def fun_l11_n127()
+ fun_l12_n357
+end
+
+def fun_l11_n128()
+ fun_l12_n741
+end
+
+def fun_l11_n129()
+ fun_l12_n502
+end
+
+def fun_l11_n130()
+ fun_l12_n569
+end
+
+def fun_l11_n131()
+ fun_l12_n696
+end
+
+def fun_l11_n132()
+ fun_l12_n326
+end
+
+def fun_l11_n133()
+ fun_l12_n765
+end
+
+def fun_l11_n134()
+ fun_l12_n126
+end
+
+def fun_l11_n135()
+ fun_l12_n107
+end
+
+def fun_l11_n136()
+ fun_l12_n8
+end
+
+def fun_l11_n137()
+ fun_l12_n969
+end
+
+def fun_l11_n138()
+ fun_l12_n49
+end
+
+def fun_l11_n139()
+ fun_l12_n65
+end
+
+def fun_l11_n140()
+ fun_l12_n631
+end
+
+def fun_l11_n141()
+ fun_l12_n984
+end
+
+def fun_l11_n142()
+ fun_l12_n520
+end
+
+def fun_l11_n143()
+ fun_l12_n348
+end
+
+def fun_l11_n144()
+ fun_l12_n51
+end
+
+def fun_l11_n145()
+ fun_l12_n756
+end
+
+def fun_l11_n146()
+ fun_l12_n981
+end
+
+def fun_l11_n147()
+ fun_l12_n671
+end
+
+def fun_l11_n148()
+ fun_l12_n4
+end
+
+def fun_l11_n149()
+ fun_l12_n66
+end
+
+def fun_l11_n150()
+ fun_l12_n445
+end
+
+def fun_l11_n151()
+ fun_l12_n131
+end
+
+def fun_l11_n152()
+ fun_l12_n927
+end
+
+def fun_l11_n153()
+ fun_l12_n715
+end
+
+def fun_l11_n154()
+ fun_l12_n767
+end
+
+def fun_l11_n155()
+ fun_l12_n50
+end
+
+def fun_l11_n156()
+ fun_l12_n360
+end
+
+def fun_l11_n157()
+ fun_l12_n311
+end
+
+def fun_l11_n158()
+ fun_l12_n509
+end
+
+def fun_l11_n159()
+ fun_l12_n868
+end
+
+def fun_l11_n160()
+ fun_l12_n185
+end
+
+def fun_l11_n161()
+ fun_l12_n338
+end
+
+def fun_l11_n162()
+ fun_l12_n539
+end
+
+def fun_l11_n163()
+ fun_l12_n30
+end
+
+def fun_l11_n164()
+ fun_l12_n485
+end
+
+def fun_l11_n165()
+ fun_l12_n808
+end
+
+def fun_l11_n166()
+ fun_l12_n78
+end
+
+def fun_l11_n167()
+ fun_l12_n370
+end
+
+def fun_l11_n168()
+ fun_l12_n1
+end
+
+def fun_l11_n169()
+ fun_l12_n473
+end
+
+def fun_l11_n170()
+ fun_l12_n362
+end
+
+def fun_l11_n171()
+ fun_l12_n209
+end
+
+def fun_l11_n172()
+ fun_l12_n431
+end
+
+def fun_l11_n173()
+ fun_l12_n383
+end
+
+def fun_l11_n174()
+ fun_l12_n214
+end
+
+def fun_l11_n175()
+ fun_l12_n215
+end
+
+def fun_l11_n176()
+ fun_l12_n639
+end
+
+def fun_l11_n177()
+ fun_l12_n486
+end
+
+def fun_l11_n178()
+ fun_l12_n486
+end
+
+def fun_l11_n179()
+ fun_l12_n409
+end
+
+def fun_l11_n180()
+ fun_l12_n558
+end
+
+def fun_l11_n181()
+ fun_l12_n546
+end
+
+def fun_l11_n182()
+ fun_l12_n439
+end
+
+def fun_l11_n183()
+ fun_l12_n11
+end
+
+def fun_l11_n184()
+ fun_l12_n304
+end
+
+def fun_l11_n185()
+ fun_l12_n525
+end
+
+def fun_l11_n186()
+ fun_l12_n886
+end
+
+def fun_l11_n187()
+ fun_l12_n17
+end
+
+def fun_l11_n188()
+ fun_l12_n11
+end
+
+def fun_l11_n189()
+ fun_l12_n382
+end
+
+def fun_l11_n190()
+ fun_l12_n185
+end
+
+def fun_l11_n191()
+ fun_l12_n454
+end
+
+def fun_l11_n192()
+ fun_l12_n23
+end
+
+def fun_l11_n193()
+ fun_l12_n900
+end
+
+def fun_l11_n194()
+ fun_l12_n233
+end
+
+def fun_l11_n195()
+ fun_l12_n245
+end
+
+def fun_l11_n196()
+ fun_l12_n474
+end
+
+def fun_l11_n197()
+ fun_l12_n368
+end
+
+def fun_l11_n198()
+ fun_l12_n80
+end
+
+def fun_l11_n199()
+ fun_l12_n522
+end
+
+def fun_l11_n200()
+ fun_l12_n439
+end
+
+def fun_l11_n201()
+ fun_l12_n553
+end
+
+def fun_l11_n202()
+ fun_l12_n713
+end
+
+def fun_l11_n203()
+ fun_l12_n898
+end
+
+def fun_l11_n204()
+ fun_l12_n571
+end
+
+def fun_l11_n205()
+ fun_l12_n830
+end
+
+def fun_l11_n206()
+ fun_l12_n404
+end
+
+def fun_l11_n207()
+ fun_l12_n120
+end
+
+def fun_l11_n208()
+ fun_l12_n147
+end
+
+def fun_l11_n209()
+ fun_l12_n924
+end
+
+def fun_l11_n210()
+ fun_l12_n988
+end
+
+def fun_l11_n211()
+ fun_l12_n25
+end
+
+def fun_l11_n212()
+ fun_l12_n848
+end
+
+def fun_l11_n213()
+ fun_l12_n875
+end
+
+def fun_l11_n214()
+ fun_l12_n718
+end
+
+def fun_l11_n215()
+ fun_l12_n657
+end
+
+def fun_l11_n216()
+ fun_l12_n364
+end
+
+def fun_l11_n217()
+ fun_l12_n342
+end
+
+def fun_l11_n218()
+ fun_l12_n16
+end
+
+def fun_l11_n219()
+ fun_l12_n167
+end
+
+def fun_l11_n220()
+ fun_l12_n719
+end
+
+def fun_l11_n221()
+ fun_l12_n414
+end
+
+def fun_l11_n222()
+ fun_l12_n874
+end
+
+def fun_l11_n223()
+ fun_l12_n482
+end
+
+def fun_l11_n224()
+ fun_l12_n191
+end
+
+def fun_l11_n225()
+ fun_l12_n172
+end
+
+def fun_l11_n226()
+ fun_l12_n768
+end
+
+def fun_l11_n227()
+ fun_l12_n746
+end
+
+def fun_l11_n228()
+ fun_l12_n460
+end
+
+def fun_l11_n229()
+ fun_l12_n64
+end
+
+def fun_l11_n230()
+ fun_l12_n747
+end
+
+def fun_l11_n231()
+ fun_l12_n147
+end
+
+def fun_l11_n232()
+ fun_l12_n157
+end
+
+def fun_l11_n233()
+ fun_l12_n336
+end
+
+def fun_l11_n234()
+ fun_l12_n904
+end
+
+def fun_l11_n235()
+ fun_l12_n76
+end
+
+def fun_l11_n236()
+ fun_l12_n499
+end
+
+def fun_l11_n237()
+ fun_l12_n559
+end
+
+def fun_l11_n238()
+ fun_l12_n949
+end
+
+def fun_l11_n239()
+ fun_l12_n525
+end
+
+def fun_l11_n240()
+ fun_l12_n741
+end
+
+def fun_l11_n241()
+ fun_l12_n11
+end
+
+def fun_l11_n242()
+ fun_l12_n449
+end
+
+def fun_l11_n243()
+ fun_l12_n767
+end
+
+def fun_l11_n244()
+ fun_l12_n94
+end
+
+def fun_l11_n245()
+ fun_l12_n721
+end
+
+def fun_l11_n246()
+ fun_l12_n592
+end
+
+def fun_l11_n247()
+ fun_l12_n184
+end
+
+def fun_l11_n248()
+ fun_l12_n166
+end
+
+def fun_l11_n249()
+ fun_l12_n773
+end
+
+def fun_l11_n250()
+ fun_l12_n334
+end
+
+def fun_l11_n251()
+ fun_l12_n965
+end
+
+def fun_l11_n252()
+ fun_l12_n154
+end
+
+def fun_l11_n253()
+ fun_l12_n182
+end
+
+def fun_l11_n254()
+ fun_l12_n298
+end
+
+def fun_l11_n255()
+ fun_l12_n29
+end
+
+def fun_l11_n256()
+ fun_l12_n409
+end
+
+def fun_l11_n257()
+ fun_l12_n452
+end
+
+def fun_l11_n258()
+ fun_l12_n369
+end
+
+def fun_l11_n259()
+ fun_l12_n794
+end
+
+def fun_l11_n260()
+ fun_l12_n210
+end
+
+def fun_l11_n261()
+ fun_l12_n255
+end
+
+def fun_l11_n262()
+ fun_l12_n801
+end
+
+def fun_l11_n263()
+ fun_l12_n650
+end
+
+def fun_l11_n264()
+ fun_l12_n612
+end
+
+def fun_l11_n265()
+ fun_l12_n122
+end
+
+def fun_l11_n266()
+ fun_l12_n70
+end
+
+def fun_l11_n267()
+ fun_l12_n254
+end
+
+def fun_l11_n268()
+ fun_l12_n104
+end
+
+def fun_l11_n269()
+ fun_l12_n564
+end
+
+def fun_l11_n270()
+ fun_l12_n256
+end
+
+def fun_l11_n271()
+ fun_l12_n525
+end
+
+def fun_l11_n272()
+ fun_l12_n734
+end
+
+def fun_l11_n273()
+ fun_l12_n127
+end
+
+def fun_l11_n274()
+ fun_l12_n705
+end
+
+def fun_l11_n275()
+ fun_l12_n607
+end
+
+def fun_l11_n276()
+ fun_l12_n681
+end
+
+def fun_l11_n277()
+ fun_l12_n510
+end
+
+def fun_l11_n278()
+ fun_l12_n889
+end
+
+def fun_l11_n279()
+ fun_l12_n153
+end
+
+def fun_l11_n280()
+ fun_l12_n457
+end
+
+def fun_l11_n281()
+ fun_l12_n394
+end
+
+def fun_l11_n282()
+ fun_l12_n628
+end
+
+def fun_l11_n283()
+ fun_l12_n576
+end
+
+def fun_l11_n284()
+ fun_l12_n294
+end
+
+def fun_l11_n285()
+ fun_l12_n79
+end
+
+def fun_l11_n286()
+ fun_l12_n505
+end
+
+def fun_l11_n287()
+ fun_l12_n726
+end
+
+def fun_l11_n288()
+ fun_l12_n171
+end
+
+def fun_l11_n289()
+ fun_l12_n317
+end
+
+def fun_l11_n290()
+ fun_l12_n350
+end
+
+def fun_l11_n291()
+ fun_l12_n134
+end
+
+def fun_l11_n292()
+ fun_l12_n595
+end
+
+def fun_l11_n293()
+ fun_l12_n924
+end
+
+def fun_l11_n294()
+ fun_l12_n713
+end
+
+def fun_l11_n295()
+ fun_l12_n630
+end
+
+def fun_l11_n296()
+ fun_l12_n444
+end
+
+def fun_l11_n297()
+ fun_l12_n751
+end
+
+def fun_l11_n298()
+ fun_l12_n324
+end
+
+def fun_l11_n299()
+ fun_l12_n851
+end
+
+def fun_l11_n300()
+ fun_l12_n883
+end
+
+def fun_l11_n301()
+ fun_l12_n289
+end
+
+def fun_l11_n302()
+ fun_l12_n427
+end
+
+def fun_l11_n303()
+ fun_l12_n593
+end
+
+def fun_l11_n304()
+ fun_l12_n380
+end
+
+def fun_l11_n305()
+ fun_l12_n630
+end
+
+def fun_l11_n306()
+ fun_l12_n245
+end
+
+def fun_l11_n307()
+ fun_l12_n369
+end
+
+def fun_l11_n308()
+ fun_l12_n641
+end
+
+def fun_l11_n309()
+ fun_l12_n271
+end
+
+def fun_l11_n310()
+ fun_l12_n67
+end
+
+def fun_l11_n311()
+ fun_l12_n109
+end
+
+def fun_l11_n312()
+ fun_l12_n559
+end
+
+def fun_l11_n313()
+ fun_l12_n211
+end
+
+def fun_l11_n314()
+ fun_l12_n396
+end
+
+def fun_l11_n315()
+ fun_l12_n390
+end
+
+def fun_l11_n316()
+ fun_l12_n72
+end
+
+def fun_l11_n317()
+ fun_l12_n13
+end
+
+def fun_l11_n318()
+ fun_l12_n690
+end
+
+def fun_l11_n319()
+ fun_l12_n104
+end
+
+def fun_l11_n320()
+ fun_l12_n671
+end
+
+def fun_l11_n321()
+ fun_l12_n506
+end
+
+def fun_l11_n322()
+ fun_l12_n679
+end
+
+def fun_l11_n323()
+ fun_l12_n809
+end
+
+def fun_l11_n324()
+ fun_l12_n750
+end
+
+def fun_l11_n325()
+ fun_l12_n754
+end
+
+def fun_l11_n326()
+ fun_l12_n6
+end
+
+def fun_l11_n327()
+ fun_l12_n522
+end
+
+def fun_l11_n328()
+ fun_l12_n414
+end
+
+def fun_l11_n329()
+ fun_l12_n934
+end
+
+def fun_l11_n330()
+ fun_l12_n653
+end
+
+def fun_l11_n331()
+ fun_l12_n290
+end
+
+def fun_l11_n332()
+ fun_l12_n262
+end
+
+def fun_l11_n333()
+ fun_l12_n933
+end
+
+def fun_l11_n334()
+ fun_l12_n332
+end
+
+def fun_l11_n335()
+ fun_l12_n882
+end
+
+def fun_l11_n336()
+ fun_l12_n448
+end
+
+def fun_l11_n337()
+ fun_l12_n5
+end
+
+def fun_l11_n338()
+ fun_l12_n993
+end
+
+def fun_l11_n339()
+ fun_l12_n354
+end
+
+def fun_l11_n340()
+ fun_l12_n643
+end
+
+def fun_l11_n341()
+ fun_l12_n85
+end
+
+def fun_l11_n342()
+ fun_l12_n957
+end
+
+def fun_l11_n343()
+ fun_l12_n581
+end
+
+def fun_l11_n344()
+ fun_l12_n837
+end
+
+def fun_l11_n345()
+ fun_l12_n210
+end
+
+def fun_l11_n346()
+ fun_l12_n45
+end
+
+def fun_l11_n347()
+ fun_l12_n672
+end
+
+def fun_l11_n348()
+ fun_l12_n559
+end
+
+def fun_l11_n349()
+ fun_l12_n76
+end
+
+def fun_l11_n350()
+ fun_l12_n500
+end
+
+def fun_l11_n351()
+ fun_l12_n23
+end
+
+def fun_l11_n352()
+ fun_l12_n364
+end
+
+def fun_l11_n353()
+ fun_l12_n72
+end
+
+def fun_l11_n354()
+ fun_l12_n953
+end
+
+def fun_l11_n355()
+ fun_l12_n104
+end
+
+def fun_l11_n356()
+ fun_l12_n446
+end
+
+def fun_l11_n357()
+ fun_l12_n231
+end
+
+def fun_l11_n358()
+ fun_l12_n923
+end
+
+def fun_l11_n359()
+ fun_l12_n396
+end
+
+def fun_l11_n360()
+ fun_l12_n748
+end
+
+def fun_l11_n361()
+ fun_l12_n168
+end
+
+def fun_l11_n362()
+ fun_l12_n329
+end
+
+def fun_l11_n363()
+ fun_l12_n843
+end
+
+def fun_l11_n364()
+ fun_l12_n864
+end
+
+def fun_l11_n365()
+ fun_l12_n163
+end
+
+def fun_l11_n366()
+ fun_l12_n811
+end
+
+def fun_l11_n367()
+ fun_l12_n7
+end
+
+def fun_l11_n368()
+ fun_l12_n105
+end
+
+def fun_l11_n369()
+ fun_l12_n367
+end
+
+def fun_l11_n370()
+ fun_l12_n650
+end
+
+def fun_l11_n371()
+ fun_l12_n966
+end
+
+def fun_l11_n372()
+ fun_l12_n248
+end
+
+def fun_l11_n373()
+ fun_l12_n431
+end
+
+def fun_l11_n374()
+ fun_l12_n329
+end
+
+def fun_l11_n375()
+ fun_l12_n788
+end
+
+def fun_l11_n376()
+ fun_l12_n407
+end
+
+def fun_l11_n377()
+ fun_l12_n551
+end
+
+def fun_l11_n378()
+ fun_l12_n703
+end
+
+def fun_l11_n379()
+ fun_l12_n414
+end
+
+def fun_l11_n380()
+ fun_l12_n23
+end
+
+def fun_l11_n381()
+ fun_l12_n747
+end
+
+def fun_l11_n382()
+ fun_l12_n10
+end
+
+def fun_l11_n383()
+ fun_l12_n943
+end
+
+def fun_l11_n384()
+ fun_l12_n26
+end
+
+def fun_l11_n385()
+ fun_l12_n459
+end
+
+def fun_l11_n386()
+ fun_l12_n256
+end
+
+def fun_l11_n387()
+ fun_l12_n606
+end
+
+def fun_l11_n388()
+ fun_l12_n138
+end
+
+def fun_l11_n389()
+ fun_l12_n371
+end
+
+def fun_l11_n390()
+ fun_l12_n304
+end
+
+def fun_l11_n391()
+ fun_l12_n459
+end
+
+def fun_l11_n392()
+ fun_l12_n968
+end
+
+def fun_l11_n393()
+ fun_l12_n153
+end
+
+def fun_l11_n394()
+ fun_l12_n742
+end
+
+def fun_l11_n395()
+ fun_l12_n617
+end
+
+def fun_l11_n396()
+ fun_l12_n562
+end
+
+def fun_l11_n397()
+ fun_l12_n474
+end
+
+def fun_l11_n398()
+ fun_l12_n633
+end
+
+def fun_l11_n399()
+ fun_l12_n950
+end
+
+def fun_l11_n400()
+ fun_l12_n370
+end
+
+def fun_l11_n401()
+ fun_l12_n301
+end
+
+def fun_l11_n402()
+ fun_l12_n74
+end
+
+def fun_l11_n403()
+ fun_l12_n759
+end
+
+def fun_l11_n404()
+ fun_l12_n634
+end
+
+def fun_l11_n405()
+ fun_l12_n678
+end
+
+def fun_l11_n406()
+ fun_l12_n761
+end
+
+def fun_l11_n407()
+ fun_l12_n669
+end
+
+def fun_l11_n408()
+ fun_l12_n737
+end
+
+def fun_l11_n409()
+ fun_l12_n666
+end
+
+def fun_l11_n410()
+ fun_l12_n43
+end
+
+def fun_l11_n411()
+ fun_l12_n64
+end
+
+def fun_l11_n412()
+ fun_l12_n956
+end
+
+def fun_l11_n413()
+ fun_l12_n749
+end
+
+def fun_l11_n414()
+ fun_l12_n22
+end
+
+def fun_l11_n415()
+ fun_l12_n170
+end
+
+def fun_l11_n416()
+ fun_l12_n113
+end
+
+def fun_l11_n417()
+ fun_l12_n780
+end
+
+def fun_l11_n418()
+ fun_l12_n855
+end
+
+def fun_l11_n419()
+ fun_l12_n551
+end
+
+def fun_l11_n420()
+ fun_l12_n101
+end
+
+def fun_l11_n421()
+ fun_l12_n543
+end
+
+def fun_l11_n422()
+ fun_l12_n773
+end
+
+def fun_l11_n423()
+ fun_l12_n13
+end
+
+def fun_l11_n424()
+ fun_l12_n997
+end
+
+def fun_l11_n425()
+ fun_l12_n199
+end
+
+def fun_l11_n426()
+ fun_l12_n281
+end
+
+def fun_l11_n427()
+ fun_l12_n685
+end
+
+def fun_l11_n428()
+ fun_l12_n588
+end
+
+def fun_l11_n429()
+ fun_l12_n693
+end
+
+def fun_l11_n430()
+ fun_l12_n595
+end
+
+def fun_l11_n431()
+ fun_l12_n632
+end
+
+def fun_l11_n432()
+ fun_l12_n923
+end
+
+def fun_l11_n433()
+ fun_l12_n388
+end
+
+def fun_l11_n434()
+ fun_l12_n307
+end
+
+def fun_l11_n435()
+ fun_l12_n169
+end
+
+def fun_l11_n436()
+ fun_l12_n13
+end
+
+def fun_l11_n437()
+ fun_l12_n207
+end
+
+def fun_l11_n438()
+ fun_l12_n711
+end
+
+def fun_l11_n439()
+ fun_l12_n649
+end
+
+def fun_l11_n440()
+ fun_l12_n817
+end
+
+def fun_l11_n441()
+ fun_l12_n280
+end
+
+def fun_l11_n442()
+ fun_l12_n833
+end
+
+def fun_l11_n443()
+ fun_l12_n962
+end
+
+def fun_l11_n444()
+ fun_l12_n431
+end
+
+def fun_l11_n445()
+ fun_l12_n564
+end
+
+def fun_l11_n446()
+ fun_l12_n107
+end
+
+def fun_l11_n447()
+ fun_l12_n504
+end
+
+def fun_l11_n448()
+ fun_l12_n680
+end
+
+def fun_l11_n449()
+ fun_l12_n653
+end
+
+def fun_l11_n450()
+ fun_l12_n549
+end
+
+def fun_l11_n451()
+ fun_l12_n34
+end
+
+def fun_l11_n452()
+ fun_l12_n607
+end
+
+def fun_l11_n453()
+ fun_l12_n831
+end
+
+def fun_l11_n454()
+ fun_l12_n974
+end
+
+def fun_l11_n455()
+ fun_l12_n815
+end
+
+def fun_l11_n456()
+ fun_l12_n700
+end
+
+def fun_l11_n457()
+ fun_l12_n583
+end
+
+def fun_l11_n458()
+ fun_l12_n479
+end
+
+def fun_l11_n459()
+ fun_l12_n815
+end
+
+def fun_l11_n460()
+ fun_l12_n45
+end
+
+def fun_l11_n461()
+ fun_l12_n740
+end
+
+def fun_l11_n462()
+ fun_l12_n637
+end
+
+def fun_l11_n463()
+ fun_l12_n568
+end
+
+def fun_l11_n464()
+ fun_l12_n340
+end
+
+def fun_l11_n465()
+ fun_l12_n532
+end
+
+def fun_l11_n466()
+ fun_l12_n13
+end
+
+def fun_l11_n467()
+ fun_l12_n479
+end
+
+def fun_l11_n468()
+ fun_l12_n263
+end
+
+def fun_l11_n469()
+ fun_l12_n109
+end
+
+def fun_l11_n470()
+ fun_l12_n290
+end
+
+def fun_l11_n471()
+ fun_l12_n85
+end
+
+def fun_l11_n472()
+ fun_l12_n360
+end
+
+def fun_l11_n473()
+ fun_l12_n33
+end
+
+def fun_l11_n474()
+ fun_l12_n603
+end
+
+def fun_l11_n475()
+ fun_l12_n82
+end
+
+def fun_l11_n476()
+ fun_l12_n250
+end
+
+def fun_l11_n477()
+ fun_l12_n233
+end
+
+def fun_l11_n478()
+ fun_l12_n530
+end
+
+def fun_l11_n479()
+ fun_l12_n619
+end
+
+def fun_l11_n480()
+ fun_l12_n756
+end
+
+def fun_l11_n481()
+ fun_l12_n681
+end
+
+def fun_l11_n482()
+ fun_l12_n981
+end
+
+def fun_l11_n483()
+ fun_l12_n308
+end
+
+def fun_l11_n484()
+ fun_l12_n955
+end
+
+def fun_l11_n485()
+ fun_l12_n197
+end
+
+def fun_l11_n486()
+ fun_l12_n620
+end
+
+def fun_l11_n487()
+ fun_l12_n485
+end
+
+def fun_l11_n488()
+ fun_l12_n866
+end
+
+def fun_l11_n489()
+ fun_l12_n502
+end
+
+def fun_l11_n490()
+ fun_l12_n16
+end
+
+def fun_l11_n491()
+ fun_l12_n727
+end
+
+def fun_l11_n492()
+ fun_l12_n13
+end
+
+def fun_l11_n493()
+ fun_l12_n268
+end
+
+def fun_l11_n494()
+ fun_l12_n501
+end
+
+def fun_l11_n495()
+ fun_l12_n303
+end
+
+def fun_l11_n496()
+ fun_l12_n223
+end
+
+def fun_l11_n497()
+ fun_l12_n623
+end
+
+def fun_l11_n498()
+ fun_l12_n479
+end
+
+def fun_l11_n499()
+ fun_l12_n310
+end
+
+def fun_l11_n500()
+ fun_l12_n337
+end
+
+def fun_l11_n501()
+ fun_l12_n406
+end
+
+def fun_l11_n502()
+ fun_l12_n727
+end
+
+def fun_l11_n503()
+ fun_l12_n329
+end
+
+def fun_l11_n504()
+ fun_l12_n675
+end
+
+def fun_l11_n505()
+ fun_l12_n41
+end
+
+def fun_l11_n506()
+ fun_l12_n176
+end
+
+def fun_l11_n507()
+ fun_l12_n277
+end
+
+def fun_l11_n508()
+ fun_l12_n767
+end
+
+def fun_l11_n509()
+ fun_l12_n863
+end
+
+def fun_l11_n510()
+ fun_l12_n459
+end
+
+def fun_l11_n511()
+ fun_l12_n360
+end
+
+def fun_l11_n512()
+ fun_l12_n870
+end
+
+def fun_l11_n513()
+ fun_l12_n939
+end
+
+def fun_l11_n514()
+ fun_l12_n697
+end
+
+def fun_l11_n515()
+ fun_l12_n91
+end
+
+def fun_l11_n516()
+ fun_l12_n382
+end
+
+def fun_l11_n517()
+ fun_l12_n649
+end
+
+def fun_l11_n518()
+ fun_l12_n455
+end
+
+def fun_l11_n519()
+ fun_l12_n52
+end
+
+def fun_l11_n520()
+ fun_l12_n857
+end
+
+def fun_l11_n521()
+ fun_l12_n110
+end
+
+def fun_l11_n522()
+ fun_l12_n21
+end
+
+def fun_l11_n523()
+ fun_l12_n786
+end
+
+def fun_l11_n524()
+ fun_l12_n56
+end
+
+def fun_l11_n525()
+ fun_l12_n558
+end
+
+def fun_l11_n526()
+ fun_l12_n923
+end
+
+def fun_l11_n527()
+ fun_l12_n716
+end
+
+def fun_l11_n528()
+ fun_l12_n20
+end
+
+def fun_l11_n529()
+ fun_l12_n503
+end
+
+def fun_l11_n530()
+ fun_l12_n221
+end
+
+def fun_l11_n531()
+ fun_l12_n364
+end
+
+def fun_l11_n532()
+ fun_l12_n412
+end
+
+def fun_l11_n533()
+ fun_l12_n925
+end
+
+def fun_l11_n534()
+ fun_l12_n638
+end
+
+def fun_l11_n535()
+ fun_l12_n413
+end
+
+def fun_l11_n536()
+ fun_l12_n873
+end
+
+def fun_l11_n537()
+ fun_l12_n499
+end
+
+def fun_l11_n538()
+ fun_l12_n231
+end
+
+def fun_l11_n539()
+ fun_l12_n450
+end
+
+def fun_l11_n540()
+ fun_l12_n137
+end
+
+def fun_l11_n541()
+ fun_l12_n516
+end
+
+def fun_l11_n542()
+ fun_l12_n479
+end
+
+def fun_l11_n543()
+ fun_l12_n541
+end
+
+def fun_l11_n544()
+ fun_l12_n42
+end
+
+def fun_l11_n545()
+ fun_l12_n207
+end
+
+def fun_l11_n546()
+ fun_l12_n340
+end
+
+def fun_l11_n547()
+ fun_l12_n888
+end
+
+def fun_l11_n548()
+ fun_l12_n443
+end
+
+def fun_l11_n549()
+ fun_l12_n375
+end
+
+def fun_l11_n550()
+ fun_l12_n972
+end
+
+def fun_l11_n551()
+ fun_l12_n622
+end
+
+def fun_l11_n552()
+ fun_l12_n958
+end
+
+def fun_l11_n553()
+ fun_l12_n279
+end
+
+def fun_l11_n554()
+ fun_l12_n498
+end
+
+def fun_l11_n555()
+ fun_l12_n498
+end
+
+def fun_l11_n556()
+ fun_l12_n502
+end
+
+def fun_l11_n557()
+ fun_l12_n113
+end
+
+def fun_l11_n558()
+ fun_l12_n636
+end
+
+def fun_l11_n559()
+ fun_l12_n525
+end
+
+def fun_l11_n560()
+ fun_l12_n541
+end
+
+def fun_l11_n561()
+ fun_l12_n336
+end
+
+def fun_l11_n562()
+ fun_l12_n787
+end
+
+def fun_l11_n563()
+ fun_l12_n858
+end
+
+def fun_l11_n564()
+ fun_l12_n772
+end
+
+def fun_l11_n565()
+ fun_l12_n831
+end
+
+def fun_l11_n566()
+ fun_l12_n95
+end
+
+def fun_l11_n567()
+ fun_l12_n927
+end
+
+def fun_l11_n568()
+ fun_l12_n888
+end
+
+def fun_l11_n569()
+ fun_l12_n444
+end
+
+def fun_l11_n570()
+ fun_l12_n23
+end
+
+def fun_l11_n571()
+ fun_l12_n995
+end
+
+def fun_l11_n572()
+ fun_l12_n372
+end
+
+def fun_l11_n573()
+ fun_l12_n432
+end
+
+def fun_l11_n574()
+ fun_l12_n156
+end
+
+def fun_l11_n575()
+ fun_l12_n981
+end
+
+def fun_l11_n576()
+ fun_l12_n328
+end
+
+def fun_l11_n577()
+ fun_l12_n411
+end
+
+def fun_l11_n578()
+ fun_l12_n734
+end
+
+def fun_l11_n579()
+ fun_l12_n646
+end
+
+def fun_l11_n580()
+ fun_l12_n214
+end
+
+def fun_l11_n581()
+ fun_l12_n334
+end
+
+def fun_l11_n582()
+ fun_l12_n800
+end
+
+def fun_l11_n583()
+ fun_l12_n344
+end
+
+def fun_l11_n584()
+ fun_l12_n672
+end
+
+def fun_l11_n585()
+ fun_l12_n403
+end
+
+def fun_l11_n586()
+ fun_l12_n351
+end
+
+def fun_l11_n587()
+ fun_l12_n506
+end
+
+def fun_l11_n588()
+ fun_l12_n878
+end
+
+def fun_l11_n589()
+ fun_l12_n986
+end
+
+def fun_l11_n590()
+ fun_l12_n524
+end
+
+def fun_l11_n591()
+ fun_l12_n552
+end
+
+def fun_l11_n592()
+ fun_l12_n735
+end
+
+def fun_l11_n593()
+ fun_l12_n953
+end
+
+def fun_l11_n594()
+ fun_l12_n138
+end
+
+def fun_l11_n595()
+ fun_l12_n185
+end
+
+def fun_l11_n596()
+ fun_l12_n865
+end
+
+def fun_l11_n597()
+ fun_l12_n143
+end
+
+def fun_l11_n598()
+ fun_l12_n879
+end
+
+def fun_l11_n599()
+ fun_l12_n751
+end
+
+def fun_l11_n600()
+ fun_l12_n750
+end
+
+def fun_l11_n601()
+ fun_l12_n574
+end
+
+def fun_l11_n602()
+ fun_l12_n91
+end
+
+def fun_l11_n603()
+ fun_l12_n116
+end
+
+def fun_l11_n604()
+ fun_l12_n398
+end
+
+def fun_l11_n605()
+ fun_l12_n782
+end
+
+def fun_l11_n606()
+ fun_l12_n770
+end
+
+def fun_l11_n607()
+ fun_l12_n240
+end
+
+def fun_l11_n608()
+ fun_l12_n385
+end
+
+def fun_l11_n609()
+ fun_l12_n106
+end
+
+def fun_l11_n610()
+ fun_l12_n959
+end
+
+def fun_l11_n611()
+ fun_l12_n84
+end
+
+def fun_l11_n612()
+ fun_l12_n235
+end
+
+def fun_l11_n613()
+ fun_l12_n429
+end
+
+def fun_l11_n614()
+ fun_l12_n402
+end
+
+def fun_l11_n615()
+ fun_l12_n32
+end
+
+def fun_l11_n616()
+ fun_l12_n517
+end
+
+def fun_l11_n617()
+ fun_l12_n304
+end
+
+def fun_l11_n618()
+ fun_l12_n374
+end
+
+def fun_l11_n619()
+ fun_l12_n884
+end
+
+def fun_l11_n620()
+ fun_l12_n399
+end
+
+def fun_l11_n621()
+ fun_l12_n721
+end
+
+def fun_l11_n622()
+ fun_l12_n58
+end
+
+def fun_l11_n623()
+ fun_l12_n237
+end
+
+def fun_l11_n624()
+ fun_l12_n659
+end
+
+def fun_l11_n625()
+ fun_l12_n454
+end
+
+def fun_l11_n626()
+ fun_l12_n942
+end
+
+def fun_l11_n627()
+ fun_l12_n975
+end
+
+def fun_l11_n628()
+ fun_l12_n192
+end
+
+def fun_l11_n629()
+ fun_l12_n590
+end
+
+def fun_l11_n630()
+ fun_l12_n340
+end
+
+def fun_l11_n631()
+ fun_l12_n229
+end
+
+def fun_l11_n632()
+ fun_l12_n478
+end
+
+def fun_l11_n633()
+ fun_l12_n84
+end
+
+def fun_l11_n634()
+ fun_l12_n280
+end
+
+def fun_l11_n635()
+ fun_l12_n896
+end
+
+def fun_l11_n636()
+ fun_l12_n872
+end
+
+def fun_l11_n637()
+ fun_l12_n924
+end
+
+def fun_l11_n638()
+ fun_l12_n957
+end
+
+def fun_l11_n639()
+ fun_l12_n252
+end
+
+def fun_l11_n640()
+ fun_l12_n308
+end
+
+def fun_l11_n641()
+ fun_l12_n217
+end
+
+def fun_l11_n642()
+ fun_l12_n477
+end
+
+def fun_l11_n643()
+ fun_l12_n754
+end
+
+def fun_l11_n644()
+ fun_l12_n561
+end
+
+def fun_l11_n645()
+ fun_l12_n597
+end
+
+def fun_l11_n646()
+ fun_l12_n194
+end
+
+def fun_l11_n647()
+ fun_l12_n708
+end
+
+def fun_l11_n648()
+ fun_l12_n892
+end
+
+def fun_l11_n649()
+ fun_l12_n771
+end
+
+def fun_l11_n650()
+ fun_l12_n549
+end
+
+def fun_l11_n651()
+ fun_l12_n84
+end
+
+def fun_l11_n652()
+ fun_l12_n256
+end
+
+def fun_l11_n653()
+ fun_l12_n454
+end
+
+def fun_l11_n654()
+ fun_l12_n773
+end
+
+def fun_l11_n655()
+ fun_l12_n674
+end
+
+def fun_l11_n656()
+ fun_l12_n364
+end
+
+def fun_l11_n657()
+ fun_l12_n548
+end
+
+def fun_l11_n658()
+ fun_l12_n287
+end
+
+def fun_l11_n659()
+ fun_l12_n211
+end
+
+def fun_l11_n660()
+ fun_l12_n213
+end
+
+def fun_l11_n661()
+ fun_l12_n975
+end
+
+def fun_l11_n662()
+ fun_l12_n221
+end
+
+def fun_l11_n663()
+ fun_l12_n524
+end
+
+def fun_l11_n664()
+ fun_l12_n167
+end
+
+def fun_l11_n665()
+ fun_l12_n361
+end
+
+def fun_l11_n666()
+ fun_l12_n435
+end
+
+def fun_l11_n667()
+ fun_l12_n881
+end
+
+def fun_l11_n668()
+ fun_l12_n977
+end
+
+def fun_l11_n669()
+ fun_l12_n87
+end
+
+def fun_l11_n670()
+ fun_l12_n281
+end
+
+def fun_l11_n671()
+ fun_l12_n44
+end
+
+def fun_l11_n672()
+ fun_l12_n584
+end
+
+def fun_l11_n673()
+ fun_l12_n645
+end
+
+def fun_l11_n674()
+ fun_l12_n268
+end
+
+def fun_l11_n675()
+ fun_l12_n98
+end
+
+def fun_l11_n676()
+ fun_l12_n861
+end
+
+def fun_l11_n677()
+ fun_l12_n9
+end
+
+def fun_l11_n678()
+ fun_l12_n91
+end
+
+def fun_l11_n679()
+ fun_l12_n976
+end
+
+def fun_l11_n680()
+ fun_l12_n373
+end
+
+def fun_l11_n681()
+ fun_l12_n673
+end
+
+def fun_l11_n682()
+ fun_l12_n206
+end
+
+def fun_l11_n683()
+ fun_l12_n838
+end
+
+def fun_l11_n684()
+ fun_l12_n972
+end
+
+def fun_l11_n685()
+ fun_l12_n607
+end
+
+def fun_l11_n686()
+ fun_l12_n55
+end
+
+def fun_l11_n687()
+ fun_l12_n294
+end
+
+def fun_l11_n688()
+ fun_l12_n871
+end
+
+def fun_l11_n689()
+ fun_l12_n518
+end
+
+def fun_l11_n690()
+ fun_l12_n552
+end
+
+def fun_l11_n691()
+ fun_l12_n622
+end
+
+def fun_l11_n692()
+ fun_l12_n505
+end
+
+def fun_l11_n693()
+ fun_l12_n33
+end
+
+def fun_l11_n694()
+ fun_l12_n522
+end
+
+def fun_l11_n695()
+ fun_l12_n729
+end
+
+def fun_l11_n696()
+ fun_l12_n477
+end
+
+def fun_l11_n697()
+ fun_l12_n424
+end
+
+def fun_l11_n698()
+ fun_l12_n258
+end
+
+def fun_l11_n699()
+ fun_l12_n328
+end
+
+def fun_l11_n700()
+ fun_l12_n501
+end
+
+def fun_l11_n701()
+ fun_l12_n841
+end
+
+def fun_l11_n702()
+ fun_l12_n684
+end
+
+def fun_l11_n703()
+ fun_l12_n864
+end
+
+def fun_l11_n704()
+ fun_l12_n527
+end
+
+def fun_l11_n705()
+ fun_l12_n808
+end
+
+def fun_l11_n706()
+ fun_l12_n213
+end
+
+def fun_l11_n707()
+ fun_l12_n711
+end
+
+def fun_l11_n708()
+ fun_l12_n727
+end
+
+def fun_l11_n709()
+ fun_l12_n82
+end
+
+def fun_l11_n710()
+ fun_l12_n926
+end
+
+def fun_l11_n711()
+ fun_l12_n719
+end
+
+def fun_l11_n712()
+ fun_l12_n180
+end
+
+def fun_l11_n713()
+ fun_l12_n568
+end
+
+def fun_l11_n714()
+ fun_l12_n11
+end
+
+def fun_l11_n715()
+ fun_l12_n624
+end
+
+def fun_l11_n716()
+ fun_l12_n954
+end
+
+def fun_l11_n717()
+ fun_l12_n584
+end
+
+def fun_l11_n718()
+ fun_l12_n222
+end
+
+def fun_l11_n719()
+ fun_l12_n460
+end
+
+def fun_l11_n720()
+ fun_l12_n253
+end
+
+def fun_l11_n721()
+ fun_l12_n938
+end
+
+def fun_l11_n722()
+ fun_l12_n552
+end
+
+def fun_l11_n723()
+ fun_l12_n491
+end
+
+def fun_l11_n724()
+ fun_l12_n146
+end
+
+def fun_l11_n725()
+ fun_l12_n833
+end
+
+def fun_l11_n726()
+ fun_l12_n43
+end
+
+def fun_l11_n727()
+ fun_l12_n700
+end
+
+def fun_l11_n728()
+ fun_l12_n730
+end
+
+def fun_l11_n729()
+ fun_l12_n84
+end
+
+def fun_l11_n730()
+ fun_l12_n468
+end
+
+def fun_l11_n731()
+ fun_l12_n253
+end
+
+def fun_l11_n732()
+ fun_l12_n473
+end
+
+def fun_l11_n733()
+ fun_l12_n997
+end
+
+def fun_l11_n734()
+ fun_l12_n584
+end
+
+def fun_l11_n735()
+ fun_l12_n815
+end
+
+def fun_l11_n736()
+ fun_l12_n577
+end
+
+def fun_l11_n737()
+ fun_l12_n890
+end
+
+def fun_l11_n738()
+ fun_l12_n282
+end
+
+def fun_l11_n739()
+ fun_l12_n794
+end
+
+def fun_l11_n740()
+ fun_l12_n615
+end
+
+def fun_l11_n741()
+ fun_l12_n254
+end
+
+def fun_l11_n742()
+ fun_l12_n250
+end
+
+def fun_l11_n743()
+ fun_l12_n45
+end
+
+def fun_l11_n744()
+ fun_l12_n513
+end
+
+def fun_l11_n745()
+ fun_l12_n786
+end
+
+def fun_l11_n746()
+ fun_l12_n764
+end
+
+def fun_l11_n747()
+ fun_l12_n73
+end
+
+def fun_l11_n748()
+ fun_l12_n944
+end
+
+def fun_l11_n749()
+ fun_l12_n49
+end
+
+def fun_l11_n750()
+ fun_l12_n513
+end
+
+def fun_l11_n751()
+ fun_l12_n367
+end
+
+def fun_l11_n752()
+ fun_l12_n61
+end
+
+def fun_l11_n753()
+ fun_l12_n279
+end
+
+def fun_l11_n754()
+ fun_l12_n991
+end
+
+def fun_l11_n755()
+ fun_l12_n747
+end
+
+def fun_l11_n756()
+ fun_l12_n422
+end
+
+def fun_l11_n757()
+ fun_l12_n414
+end
+
+def fun_l11_n758()
+ fun_l12_n61
+end
+
+def fun_l11_n759()
+ fun_l12_n471
+end
+
+def fun_l11_n760()
+ fun_l12_n436
+end
+
+def fun_l11_n761()
+ fun_l12_n183
+end
+
+def fun_l11_n762()
+ fun_l12_n173
+end
+
+def fun_l11_n763()
+ fun_l12_n362
+end
+
+def fun_l11_n764()
+ fun_l12_n174
+end
+
+def fun_l11_n765()
+ fun_l12_n710
+end
+
+def fun_l11_n766()
+ fun_l12_n212
+end
+
+def fun_l11_n767()
+ fun_l12_n649
+end
+
+def fun_l11_n768()
+ fun_l12_n409
+end
+
+def fun_l11_n769()
+ fun_l12_n375
+end
+
+def fun_l11_n770()
+ fun_l12_n608
+end
+
+def fun_l11_n771()
+ fun_l12_n447
+end
+
+def fun_l11_n772()
+ fun_l12_n530
+end
+
+def fun_l11_n773()
+ fun_l12_n359
+end
+
+def fun_l11_n774()
+ fun_l12_n317
+end
+
+def fun_l11_n775()
+ fun_l12_n105
+end
+
+def fun_l11_n776()
+ fun_l12_n65
+end
+
+def fun_l11_n777()
+ fun_l12_n243
+end
+
+def fun_l11_n778()
+ fun_l12_n274
+end
+
+def fun_l11_n779()
+ fun_l12_n560
+end
+
+def fun_l11_n780()
+ fun_l12_n155
+end
+
+def fun_l11_n781()
+ fun_l12_n277
+end
+
+def fun_l11_n782()
+ fun_l12_n255
+end
+
+def fun_l11_n783()
+ fun_l12_n184
+end
+
+def fun_l11_n784()
+ fun_l12_n495
+end
+
+def fun_l11_n785()
+ fun_l12_n910
+end
+
+def fun_l11_n786()
+ fun_l12_n245
+end
+
+def fun_l11_n787()
+ fun_l12_n761
+end
+
+def fun_l11_n788()
+ fun_l12_n501
+end
+
+def fun_l11_n789()
+ fun_l12_n11
+end
+
+def fun_l11_n790()
+ fun_l12_n87
+end
+
+def fun_l11_n791()
+ fun_l12_n233
+end
+
+def fun_l11_n792()
+ fun_l12_n201
+end
+
+def fun_l11_n793()
+ fun_l12_n471
+end
+
+def fun_l11_n794()
+ fun_l12_n6
+end
+
+def fun_l11_n795()
+ fun_l12_n257
+end
+
+def fun_l11_n796()
+ fun_l12_n104
+end
+
+def fun_l11_n797()
+ fun_l12_n712
+end
+
+def fun_l11_n798()
+ fun_l12_n408
+end
+
+def fun_l11_n799()
+ fun_l12_n713
+end
+
+def fun_l11_n800()
+ fun_l12_n622
+end
+
+def fun_l11_n801()
+ fun_l12_n498
+end
+
+def fun_l11_n802()
+ fun_l12_n904
+end
+
+def fun_l11_n803()
+ fun_l12_n413
+end
+
+def fun_l11_n804()
+ fun_l12_n424
+end
+
+def fun_l11_n805()
+ fun_l12_n209
+end
+
+def fun_l11_n806()
+ fun_l12_n171
+end
+
+def fun_l11_n807()
+ fun_l12_n835
+end
+
+def fun_l11_n808()
+ fun_l12_n872
+end
+
+def fun_l11_n809()
+ fun_l12_n456
+end
+
+def fun_l11_n810()
+ fun_l12_n586
+end
+
+def fun_l11_n811()
+ fun_l12_n422
+end
+
+def fun_l11_n812()
+ fun_l12_n125
+end
+
+def fun_l11_n813()
+ fun_l12_n482
+end
+
+def fun_l11_n814()
+ fun_l12_n17
+end
+
+def fun_l11_n815()
+ fun_l12_n966
+end
+
+def fun_l11_n816()
+ fun_l12_n408
+end
+
+def fun_l11_n817()
+ fun_l12_n874
+end
+
+def fun_l11_n818()
+ fun_l12_n454
+end
+
+def fun_l11_n819()
+ fun_l12_n818
+end
+
+def fun_l11_n820()
+ fun_l12_n469
+end
+
+def fun_l11_n821()
+ fun_l12_n104
+end
+
+def fun_l11_n822()
+ fun_l12_n765
+end
+
+def fun_l11_n823()
+ fun_l12_n472
+end
+
+def fun_l11_n824()
+ fun_l12_n794
+end
+
+def fun_l11_n825()
+ fun_l12_n609
+end
+
+def fun_l11_n826()
+ fun_l12_n609
+end
+
+def fun_l11_n827()
+ fun_l12_n99
+end
+
+def fun_l11_n828()
+ fun_l12_n844
+end
+
+def fun_l11_n829()
+ fun_l12_n423
+end
+
+def fun_l11_n830()
+ fun_l12_n560
+end
+
+def fun_l11_n831()
+ fun_l12_n60
+end
+
+def fun_l11_n832()
+ fun_l12_n670
+end
+
+def fun_l11_n833()
+ fun_l12_n591
+end
+
+def fun_l11_n834()
+ fun_l12_n572
+end
+
+def fun_l11_n835()
+ fun_l12_n96
+end
+
+def fun_l11_n836()
+ fun_l12_n567
+end
+
+def fun_l11_n837()
+ fun_l12_n239
+end
+
+def fun_l11_n838()
+ fun_l12_n937
+end
+
+def fun_l11_n839()
+ fun_l12_n853
+end
+
+def fun_l11_n840()
+ fun_l12_n440
+end
+
+def fun_l11_n841()
+ fun_l12_n930
+end
+
+def fun_l11_n842()
+ fun_l12_n448
+end
+
+def fun_l11_n843()
+ fun_l12_n185
+end
+
+def fun_l11_n844()
+ fun_l12_n904
+end
+
+def fun_l11_n845()
+ fun_l12_n399
+end
+
+def fun_l11_n846()
+ fun_l12_n184
+end
+
+def fun_l11_n847()
+ fun_l12_n985
+end
+
+def fun_l11_n848()
+ fun_l12_n966
+end
+
+def fun_l11_n849()
+ fun_l12_n183
+end
+
+def fun_l11_n850()
+ fun_l12_n418
+end
+
+def fun_l11_n851()
+ fun_l12_n546
+end
+
+def fun_l11_n852()
+ fun_l12_n96
+end
+
+def fun_l11_n853()
+ fun_l12_n172
+end
+
+def fun_l11_n854()
+ fun_l12_n546
+end
+
+def fun_l11_n855()
+ fun_l12_n86
+end
+
+def fun_l11_n856()
+ fun_l12_n815
+end
+
+def fun_l11_n857()
+ fun_l12_n552
+end
+
+def fun_l11_n858()
+ fun_l12_n657
+end
+
+def fun_l11_n859()
+ fun_l12_n567
+end
+
+def fun_l11_n860()
+ fun_l12_n561
+end
+
+def fun_l11_n861()
+ fun_l12_n590
+end
+
+def fun_l11_n862()
+ fun_l12_n28
+end
+
+def fun_l11_n863()
+ fun_l12_n935
+end
+
+def fun_l11_n864()
+ fun_l12_n950
+end
+
+def fun_l11_n865()
+ fun_l12_n946
+end
+
+def fun_l11_n866()
+ fun_l12_n77
+end
+
+def fun_l11_n867()
+ fun_l12_n454
+end
+
+def fun_l11_n868()
+ fun_l12_n813
+end
+
+def fun_l11_n869()
+ fun_l12_n562
+end
+
+def fun_l11_n870()
+ fun_l12_n598
+end
+
+def fun_l11_n871()
+ fun_l12_n331
+end
+
+def fun_l11_n872()
+ fun_l12_n156
+end
+
+def fun_l11_n873()
+ fun_l12_n807
+end
+
+def fun_l11_n874()
+ fun_l12_n442
+end
+
+def fun_l11_n875()
+ fun_l12_n322
+end
+
+def fun_l11_n876()
+ fun_l12_n472
+end
+
+def fun_l11_n877()
+ fun_l12_n581
+end
+
+def fun_l11_n878()
+ fun_l12_n94
+end
+
+def fun_l11_n879()
+ fun_l12_n270
+end
+
+def fun_l11_n880()
+ fun_l12_n63
+end
+
+def fun_l11_n881()
+ fun_l12_n290
+end
+
+def fun_l11_n882()
+ fun_l12_n148
+end
+
+def fun_l11_n883()
+ fun_l12_n862
+end
+
+def fun_l11_n884()
+ fun_l12_n527
+end
+
+def fun_l11_n885()
+ fun_l12_n166
+end
+
+def fun_l11_n886()
+ fun_l12_n422
+end
+
+def fun_l11_n887()
+ fun_l12_n195
+end
+
+def fun_l11_n888()
+ fun_l12_n592
+end
+
+def fun_l11_n889()
+ fun_l12_n116
+end
+
+def fun_l11_n890()
+ fun_l12_n923
+end
+
+def fun_l11_n891()
+ fun_l12_n422
+end
+
+def fun_l11_n892()
+ fun_l12_n945
+end
+
+def fun_l11_n893()
+ fun_l12_n850
+end
+
+def fun_l11_n894()
+ fun_l12_n598
+end
+
+def fun_l11_n895()
+ fun_l12_n448
+end
+
+def fun_l11_n896()
+ fun_l12_n955
+end
+
+def fun_l11_n897()
+ fun_l12_n259
+end
+
+def fun_l11_n898()
+ fun_l12_n145
+end
+
+def fun_l11_n899()
+ fun_l12_n321
+end
+
+def fun_l11_n900()
+ fun_l12_n680
+end
+
+def fun_l11_n901()
+ fun_l12_n856
+end
+
+def fun_l11_n902()
+ fun_l12_n776
+end
+
+def fun_l11_n903()
+ fun_l12_n108
+end
+
+def fun_l11_n904()
+ fun_l12_n340
+end
+
+def fun_l11_n905()
+ fun_l12_n78
+end
+
+def fun_l11_n906()
+ fun_l12_n218
+end
+
+def fun_l11_n907()
+ fun_l12_n288
+end
+
+def fun_l11_n908()
+ fun_l12_n197
+end
+
+def fun_l11_n909()
+ fun_l12_n890
+end
+
+def fun_l11_n910()
+ fun_l12_n850
+end
+
+def fun_l11_n911()
+ fun_l12_n964
+end
+
+def fun_l11_n912()
+ fun_l12_n47
+end
+
+def fun_l11_n913()
+ fun_l12_n462
+end
+
+def fun_l11_n914()
+ fun_l12_n461
+end
+
+def fun_l11_n915()
+ fun_l12_n57
+end
+
+def fun_l11_n916()
+ fun_l12_n938
+end
+
+def fun_l11_n917()
+ fun_l12_n841
+end
+
+def fun_l11_n918()
+ fun_l12_n462
+end
+
+def fun_l11_n919()
+ fun_l12_n425
+end
+
+def fun_l11_n920()
+ fun_l12_n775
+end
+
+def fun_l11_n921()
+ fun_l12_n302
+end
+
+def fun_l11_n922()
+ fun_l12_n921
+end
+
+def fun_l11_n923()
+ fun_l12_n322
+end
+
+def fun_l11_n924()
+ fun_l12_n414
+end
+
+def fun_l11_n925()
+ fun_l12_n461
+end
+
+def fun_l11_n926()
+ fun_l12_n476
+end
+
+def fun_l11_n927()
+ fun_l12_n537
+end
+
+def fun_l11_n928()
+ fun_l12_n359
+end
+
+def fun_l11_n929()
+ fun_l12_n297
+end
+
+def fun_l11_n930()
+ fun_l12_n134
+end
+
+def fun_l11_n931()
+ fun_l12_n875
+end
+
+def fun_l11_n932()
+ fun_l12_n763
+end
+
+def fun_l11_n933()
+ fun_l12_n180
+end
+
+def fun_l11_n934()
+ fun_l12_n522
+end
+
+def fun_l11_n935()
+ fun_l12_n701
+end
+
+def fun_l11_n936()
+ fun_l12_n793
+end
+
+def fun_l11_n937()
+ fun_l12_n853
+end
+
+def fun_l11_n938()
+ fun_l12_n208
+end
+
+def fun_l11_n939()
+ fun_l12_n307
+end
+
+def fun_l11_n940()
+ fun_l12_n695
+end
+
+def fun_l11_n941()
+ fun_l12_n171
+end
+
+def fun_l11_n942()
+ fun_l12_n181
+end
+
+def fun_l11_n943()
+ fun_l12_n58
+end
+
+def fun_l11_n944()
+ fun_l12_n733
+end
+
+def fun_l11_n945()
+ fun_l12_n7
+end
+
+def fun_l11_n946()
+ fun_l12_n332
+end
+
+def fun_l11_n947()
+ fun_l12_n323
+end
+
+def fun_l11_n948()
+ fun_l12_n240
+end
+
+def fun_l11_n949()
+ fun_l12_n21
+end
+
+def fun_l11_n950()
+ fun_l12_n814
+end
+
+def fun_l11_n951()
+ fun_l12_n943
+end
+
+def fun_l11_n952()
+ fun_l12_n4
+end
+
+def fun_l11_n953()
+ fun_l12_n747
+end
+
+def fun_l11_n954()
+ fun_l12_n500
+end
+
+def fun_l11_n955()
+ fun_l12_n361
+end
+
+def fun_l11_n956()
+ fun_l12_n898
+end
+
+def fun_l11_n957()
+ fun_l12_n216
+end
+
+def fun_l11_n958()
+ fun_l12_n58
+end
+
+def fun_l11_n959()
+ fun_l12_n327
+end
+
+def fun_l11_n960()
+ fun_l12_n405
+end
+
+def fun_l11_n961()
+ fun_l12_n665
+end
+
+def fun_l11_n962()
+ fun_l12_n456
+end
+
+def fun_l11_n963()
+ fun_l12_n399
+end
+
+def fun_l11_n964()
+ fun_l12_n836
+end
+
+def fun_l11_n965()
+ fun_l12_n18
+end
+
+def fun_l11_n966()
+ fun_l12_n236
+end
+
+def fun_l11_n967()
+ fun_l12_n594
+end
+
+def fun_l11_n968()
+ fun_l12_n147
+end
+
+def fun_l11_n969()
+ fun_l12_n758
+end
+
+def fun_l11_n970()
+ fun_l12_n271
+end
+
+def fun_l11_n971()
+ fun_l12_n551
+end
+
+def fun_l11_n972()
+ fun_l12_n332
+end
+
+def fun_l11_n973()
+ fun_l12_n348
+end
+
+def fun_l11_n974()
+ fun_l12_n158
+end
+
+def fun_l11_n975()
+ fun_l12_n990
+end
+
+def fun_l11_n976()
+ fun_l12_n330
+end
+
+def fun_l11_n977()
+ fun_l12_n764
+end
+
+def fun_l11_n978()
+ fun_l12_n844
+end
+
+def fun_l11_n979()
+ fun_l12_n452
+end
+
+def fun_l11_n980()
+ fun_l12_n593
+end
+
+def fun_l11_n981()
+ fun_l12_n762
+end
+
+def fun_l11_n982()
+ fun_l12_n736
+end
+
+def fun_l11_n983()
+ fun_l12_n957
+end
+
+def fun_l11_n984()
+ fun_l12_n174
+end
+
+def fun_l11_n985()
+ fun_l12_n454
+end
+
+def fun_l11_n986()
+ fun_l12_n492
+end
+
+def fun_l11_n987()
+ fun_l12_n986
+end
+
+def fun_l11_n988()
+ fun_l12_n868
+end
+
+def fun_l11_n989()
+ fun_l12_n445
+end
+
+def fun_l11_n990()
+ fun_l12_n422
+end
+
+def fun_l11_n991()
+ fun_l12_n877
+end
+
+def fun_l11_n992()
+ fun_l12_n150
+end
+
+def fun_l11_n993()
+ fun_l12_n163
+end
+
+def fun_l11_n994()
+ fun_l12_n183
+end
+
+def fun_l11_n995()
+ fun_l12_n100
+end
+
+def fun_l11_n996()
+ fun_l12_n297
+end
+
+def fun_l11_n997()
+ fun_l12_n43
+end
+
+def fun_l11_n998()
+ fun_l12_n324
+end
+
+def fun_l11_n999()
+ fun_l12_n732
+end
+
+def fun_l12_n0()
+ fun_l13_n595
+end
+
+def fun_l12_n1()
+ fun_l13_n185
+end
+
+def fun_l12_n2()
+ fun_l13_n257
+end
+
+def fun_l12_n3()
+ fun_l13_n865
+end
+
+def fun_l12_n4()
+ fun_l13_n857
+end
+
+def fun_l12_n5()
+ fun_l13_n9
+end
+
+def fun_l12_n6()
+ fun_l13_n41
+end
+
+def fun_l12_n7()
+ fun_l13_n430
+end
+
+def fun_l12_n8()
+ fun_l13_n394
+end
+
+def fun_l12_n9()
+ fun_l13_n20
+end
+
+def fun_l12_n10()
+ fun_l13_n527
+end
+
+def fun_l12_n11()
+ fun_l13_n158
+end
+
+def fun_l12_n12()
+ fun_l13_n229
+end
+
+def fun_l12_n13()
+ fun_l13_n205
+end
+
+def fun_l12_n14()
+ fun_l13_n88
+end
+
+def fun_l12_n15()
+ fun_l13_n359
+end
+
+def fun_l12_n16()
+ fun_l13_n204
+end
+
+def fun_l12_n17()
+ fun_l13_n297
+end
+
+def fun_l12_n18()
+ fun_l13_n531
+end
+
+def fun_l12_n19()
+ fun_l13_n244
+end
+
+def fun_l12_n20()
+ fun_l13_n587
+end
+
+def fun_l12_n21()
+ fun_l13_n731
+end
+
+def fun_l12_n22()
+ fun_l13_n839
+end
+
+def fun_l12_n23()
+ fun_l13_n560
+end
+
+def fun_l12_n24()
+ fun_l13_n22
+end
+
+def fun_l12_n25()
+ fun_l13_n383
+end
+
+def fun_l12_n26()
+ fun_l13_n321
+end
+
+def fun_l12_n27()
+ fun_l13_n286
+end
+
+def fun_l12_n28()
+ fun_l13_n951
+end
+
+def fun_l12_n29()
+ fun_l13_n172
+end
+
+def fun_l12_n30()
+ fun_l13_n804
+end
+
+def fun_l12_n31()
+ fun_l13_n619
+end
+
+def fun_l12_n32()
+ fun_l13_n464
+end
+
+def fun_l12_n33()
+ fun_l13_n87
+end
+
+def fun_l12_n34()
+ fun_l13_n544
+end
+
+def fun_l12_n35()
+ fun_l13_n37
+end
+
+def fun_l12_n36()
+ fun_l13_n614
+end
+
+def fun_l12_n37()
+ fun_l13_n426
+end
+
+def fun_l12_n38()
+ fun_l13_n335
+end
+
+def fun_l12_n39()
+ fun_l13_n689
+end
+
+def fun_l12_n40()
+ fun_l13_n220
+end
+
+def fun_l12_n41()
+ fun_l13_n77
+end
+
+def fun_l12_n42()
+ fun_l13_n791
+end
+
+def fun_l12_n43()
+ fun_l13_n514
+end
+
+def fun_l12_n44()
+ fun_l13_n802
+end
+
+def fun_l12_n45()
+ fun_l13_n860
+end
+
+def fun_l12_n46()
+ fun_l13_n562
+end
+
+def fun_l12_n47()
+ fun_l13_n208
+end
+
+def fun_l12_n48()
+ fun_l13_n167
+end
+
+def fun_l12_n49()
+ fun_l13_n772
+end
+
+def fun_l12_n50()
+ fun_l13_n303
+end
+
+def fun_l12_n51()
+ fun_l13_n757
+end
+
+def fun_l12_n52()
+ fun_l13_n558
+end
+
+def fun_l12_n53()
+ fun_l13_n45
+end
+
+def fun_l12_n54()
+ fun_l13_n292
+end
+
+def fun_l12_n55()
+ fun_l13_n558
+end
+
+def fun_l12_n56()
+ fun_l13_n361
+end
+
+def fun_l12_n57()
+ fun_l13_n605
+end
+
+def fun_l12_n58()
+ fun_l13_n16
+end
+
+def fun_l12_n59()
+ fun_l13_n73
+end
+
+def fun_l12_n60()
+ fun_l13_n292
+end
+
+def fun_l12_n61()
+ fun_l13_n747
+end
+
+def fun_l12_n62()
+ fun_l13_n798
+end
+
+def fun_l12_n63()
+ fun_l13_n130
+end
+
+def fun_l12_n64()
+ fun_l13_n261
+end
+
+def fun_l12_n65()
+ fun_l13_n122
+end
+
+def fun_l12_n66()
+ fun_l13_n346
+end
+
+def fun_l12_n67()
+ fun_l13_n308
+end
+
+def fun_l12_n68()
+ fun_l13_n27
+end
+
+def fun_l12_n69()
+ fun_l13_n433
+end
+
+def fun_l12_n70()
+ fun_l13_n509
+end
+
+def fun_l12_n71()
+ fun_l13_n643
+end
+
+def fun_l12_n72()
+ fun_l13_n462
+end
+
+def fun_l12_n73()
+ fun_l13_n976
+end
+
+def fun_l12_n74()
+ fun_l13_n157
+end
+
+def fun_l12_n75()
+ fun_l13_n733
+end
+
+def fun_l12_n76()
+ fun_l13_n976
+end
+
+def fun_l12_n77()
+ fun_l13_n369
+end
+
+def fun_l12_n78()
+ fun_l13_n308
+end
+
+def fun_l12_n79()
+ fun_l13_n958
+end
+
+def fun_l12_n80()
+ fun_l13_n95
+end
+
+def fun_l12_n81()
+ fun_l13_n653
+end
+
+def fun_l12_n82()
+ fun_l13_n624
+end
+
+def fun_l12_n83()
+ fun_l13_n712
+end
+
+def fun_l12_n84()
+ fun_l13_n950
+end
+
+def fun_l12_n85()
+ fun_l13_n836
+end
+
+def fun_l12_n86()
+ fun_l13_n496
+end
+
+def fun_l12_n87()
+ fun_l13_n727
+end
+
+def fun_l12_n88()
+ fun_l13_n368
+end
+
+def fun_l12_n89()
+ fun_l13_n727
+end
+
+def fun_l12_n90()
+ fun_l13_n682
+end
+
+def fun_l12_n91()
+ fun_l13_n758
+end
+
+def fun_l12_n92()
+ fun_l13_n910
+end
+
+def fun_l12_n93()
+ fun_l13_n490
+end
+
+def fun_l12_n94()
+ fun_l13_n405
+end
+
+def fun_l12_n95()
+ fun_l13_n171
+end
+
+def fun_l12_n96()
+ fun_l13_n69
+end
+
+def fun_l12_n97()
+ fun_l13_n519
+end
+
+def fun_l12_n98()
+ fun_l13_n476
+end
+
+def fun_l12_n99()
+ fun_l13_n399
+end
+
+def fun_l12_n100()
+ fun_l13_n93
+end
+
+def fun_l12_n101()
+ fun_l13_n220
+end
+
+def fun_l12_n102()
+ fun_l13_n483
+end
+
+def fun_l12_n103()
+ fun_l13_n176
+end
+
+def fun_l12_n104()
+ fun_l13_n210
+end
+
+def fun_l12_n105()
+ fun_l13_n111
+end
+
+def fun_l12_n106()
+ fun_l13_n436
+end
+
+def fun_l12_n107()
+ fun_l13_n887
+end
+
+def fun_l12_n108()
+ fun_l13_n118
+end
+
+def fun_l12_n109()
+ fun_l13_n630
+end
+
+def fun_l12_n110()
+ fun_l13_n262
+end
+
+def fun_l12_n111()
+ fun_l13_n975
+end
+
+def fun_l12_n112()
+ fun_l13_n280
+end
+
+def fun_l12_n113()
+ fun_l13_n341
+end
+
+def fun_l12_n114()
+ fun_l13_n452
+end
+
+def fun_l12_n115()
+ fun_l13_n762
+end
+
+def fun_l12_n116()
+ fun_l13_n230
+end
+
+def fun_l12_n117()
+ fun_l13_n470
+end
+
+def fun_l12_n118()
+ fun_l13_n257
+end
+
+def fun_l12_n119()
+ fun_l13_n920
+end
+
+def fun_l12_n120()
+ fun_l13_n600
+end
+
+def fun_l12_n121()
+ fun_l13_n947
+end
+
+def fun_l12_n122()
+ fun_l13_n643
+end
+
+def fun_l12_n123()
+ fun_l13_n18
+end
+
+def fun_l12_n124()
+ fun_l13_n680
+end
+
+def fun_l12_n125()
+ fun_l13_n926
+end
+
+def fun_l12_n126()
+ fun_l13_n841
+end
+
+def fun_l12_n127()
+ fun_l13_n391
+end
+
+def fun_l12_n128()
+ fun_l13_n617
+end
+
+def fun_l12_n129()
+ fun_l13_n484
+end
+
+def fun_l12_n130()
+ fun_l13_n211
+end
+
+def fun_l12_n131()
+ fun_l13_n206
+end
+
+def fun_l12_n132()
+ fun_l13_n789
+end
+
+def fun_l12_n133()
+ fun_l13_n660
+end
+
+def fun_l12_n134()
+ fun_l13_n386
+end
+
+def fun_l12_n135()
+ fun_l13_n414
+end
+
+def fun_l12_n136()
+ fun_l13_n271
+end
+
+def fun_l12_n137()
+ fun_l13_n444
+end
+
+def fun_l12_n138()
+ fun_l13_n661
+end
+
+def fun_l12_n139()
+ fun_l13_n784
+end
+
+def fun_l12_n140()
+ fun_l13_n919
+end
+
+def fun_l12_n141()
+ fun_l13_n29
+end
+
+def fun_l12_n142()
+ fun_l13_n92
+end
+
+def fun_l12_n143()
+ fun_l13_n380
+end
+
+def fun_l12_n144()
+ fun_l13_n826
+end
+
+def fun_l12_n145()
+ fun_l13_n222
+end
+
+def fun_l12_n146()
+ fun_l13_n891
+end
+
+def fun_l12_n147()
+ fun_l13_n162
+end
+
+def fun_l12_n148()
+ fun_l13_n737
+end
+
+def fun_l12_n149()
+ fun_l13_n342
+end
+
+def fun_l12_n150()
+ fun_l13_n371
+end
+
+def fun_l12_n151()
+ fun_l13_n903
+end
+
+def fun_l12_n152()
+ fun_l13_n556
+end
+
+def fun_l12_n153()
+ fun_l13_n333
+end
+
+def fun_l12_n154()
+ fun_l13_n193
+end
+
+def fun_l12_n155()
+ fun_l13_n518
+end
+
+def fun_l12_n156()
+ fun_l13_n411
+end
+
+def fun_l12_n157()
+ fun_l13_n249
+end
+
+def fun_l12_n158()
+ fun_l13_n53
+end
+
+def fun_l12_n159()
+ fun_l13_n467
+end
+
+def fun_l12_n160()
+ fun_l13_n433
+end
+
+def fun_l12_n161()
+ fun_l13_n773
+end
+
+def fun_l12_n162()
+ fun_l13_n178
+end
+
+def fun_l12_n163()
+ fun_l13_n641
+end
+
+def fun_l12_n164()
+ fun_l13_n308
+end
+
+def fun_l12_n165()
+ fun_l13_n787
+end
+
+def fun_l12_n166()
+ fun_l13_n829
+end
+
+def fun_l12_n167()
+ fun_l13_n929
+end
+
+def fun_l12_n168()
+ fun_l13_n788
+end
+
+def fun_l12_n169()
+ fun_l13_n948
+end
+
+def fun_l12_n170()
+ fun_l13_n444
+end
+
+def fun_l12_n171()
+ fun_l13_n946
+end
+
+def fun_l12_n172()
+ fun_l13_n303
+end
+
+def fun_l12_n173()
+ fun_l13_n196
+end
+
+def fun_l12_n174()
+ fun_l13_n521
+end
+
+def fun_l12_n175()
+ fun_l13_n372
+end
+
+def fun_l12_n176()
+ fun_l13_n411
+end
+
+def fun_l12_n177()
+ fun_l13_n434
+end
+
+def fun_l12_n178()
+ fun_l13_n599
+end
+
+def fun_l12_n179()
+ fun_l13_n507
+end
+
+def fun_l12_n180()
+ fun_l13_n781
+end
+
+def fun_l12_n181()
+ fun_l13_n186
+end
+
+def fun_l12_n182()
+ fun_l13_n737
+end
+
+def fun_l12_n183()
+ fun_l13_n993
+end
+
+def fun_l12_n184()
+ fun_l13_n806
+end
+
+def fun_l12_n185()
+ fun_l13_n45
+end
+
+def fun_l12_n186()
+ fun_l13_n30
+end
+
+def fun_l12_n187()
+ fun_l13_n774
+end
+
+def fun_l12_n188()
+ fun_l13_n715
+end
+
+def fun_l12_n189()
+ fun_l13_n351
+end
+
+def fun_l12_n190()
+ fun_l13_n173
+end
+
+def fun_l12_n191()
+ fun_l13_n574
+end
+
+def fun_l12_n192()
+ fun_l13_n768
+end
+
+def fun_l12_n193()
+ fun_l13_n514
+end
+
+def fun_l12_n194()
+ fun_l13_n505
+end
+
+def fun_l12_n195()
+ fun_l13_n460
+end
+
+def fun_l12_n196()
+ fun_l13_n377
+end
+
+def fun_l12_n197()
+ fun_l13_n275
+end
+
+def fun_l12_n198()
+ fun_l13_n642
+end
+
+def fun_l12_n199()
+ fun_l13_n746
+end
+
+def fun_l12_n200()
+ fun_l13_n507
+end
+
+def fun_l12_n201()
+ fun_l13_n576
+end
+
+def fun_l12_n202()
+ fun_l13_n899
+end
+
+def fun_l12_n203()
+ fun_l13_n88
+end
+
+def fun_l12_n204()
+ fun_l13_n735
+end
+
+def fun_l12_n205()
+ fun_l13_n270
+end
+
+def fun_l12_n206()
+ fun_l13_n398
+end
+
+def fun_l12_n207()
+ fun_l13_n98
+end
+
+def fun_l12_n208()
+ fun_l13_n272
+end
+
+def fun_l12_n209()
+ fun_l13_n493
+end
+
+def fun_l12_n210()
+ fun_l13_n893
+end
+
+def fun_l12_n211()
+ fun_l13_n550
+end
+
+def fun_l12_n212()
+ fun_l13_n428
+end
+
+def fun_l12_n213()
+ fun_l13_n20
+end
+
+def fun_l12_n214()
+ fun_l13_n437
+end
+
+def fun_l12_n215()
+ fun_l13_n964
+end
+
+def fun_l12_n216()
+ fun_l13_n880
+end
+
+def fun_l12_n217()
+ fun_l13_n119
+end
+
+def fun_l12_n218()
+ fun_l13_n125
+end
+
+def fun_l12_n219()
+ fun_l13_n48
+end
+
+def fun_l12_n220()
+ fun_l13_n749
+end
+
+def fun_l12_n221()
+ fun_l13_n65
+end
+
+def fun_l12_n222()
+ fun_l13_n535
+end
+
+def fun_l12_n223()
+ fun_l13_n770
+end
+
+def fun_l12_n224()
+ fun_l13_n118
+end
+
+def fun_l12_n225()
+ fun_l13_n859
+end
+
+def fun_l12_n226()
+ fun_l13_n768
+end
+
+def fun_l12_n227()
+ fun_l13_n981
+end
+
+def fun_l12_n228()
+ fun_l13_n518
+end
+
+def fun_l12_n229()
+ fun_l13_n361
+end
+
+def fun_l12_n230()
+ fun_l13_n255
+end
+
+def fun_l12_n231()
+ fun_l13_n922
+end
+
+def fun_l12_n232()
+ fun_l13_n375
+end
+
+def fun_l12_n233()
+ fun_l13_n265
+end
+
+def fun_l12_n234()
+ fun_l13_n832
+end
+
+def fun_l12_n235()
+ fun_l13_n147
+end
+
+def fun_l12_n236()
+ fun_l13_n162
+end
+
+def fun_l12_n237()
+ fun_l13_n832
+end
+
+def fun_l12_n238()
+ fun_l13_n930
+end
+
+def fun_l12_n239()
+ fun_l13_n429
+end
+
+def fun_l12_n240()
+ fun_l13_n429
+end
+
+def fun_l12_n241()
+ fun_l13_n152
+end
+
+def fun_l12_n242()
+ fun_l13_n287
+end
+
+def fun_l12_n243()
+ fun_l13_n140
+end
+
+def fun_l12_n244()
+ fun_l13_n994
+end
+
+def fun_l12_n245()
+ fun_l13_n815
+end
+
+def fun_l12_n246()
+ fun_l13_n865
+end
+
+def fun_l12_n247()
+ fun_l13_n613
+end
+
+def fun_l12_n248()
+ fun_l13_n347
+end
+
+def fun_l12_n249()
+ fun_l13_n959
+end
+
+def fun_l12_n250()
+ fun_l13_n870
+end
+
+def fun_l12_n251()
+ fun_l13_n167
+end
+
+def fun_l12_n252()
+ fun_l13_n860
+end
+
+def fun_l12_n253()
+ fun_l13_n897
+end
+
+def fun_l12_n254()
+ fun_l13_n605
+end
+
+def fun_l12_n255()
+ fun_l13_n136
+end
+
+def fun_l12_n256()
+ fun_l13_n636
+end
+
+def fun_l12_n257()
+ fun_l13_n60
+end
+
+def fun_l12_n258()
+ fun_l13_n925
+end
+
+def fun_l12_n259()
+ fun_l13_n472
+end
+
+def fun_l12_n260()
+ fun_l13_n423
+end
+
+def fun_l12_n261()
+ fun_l13_n798
+end
+
+def fun_l12_n262()
+ fun_l13_n381
+end
+
+def fun_l12_n263()
+ fun_l13_n922
+end
+
+def fun_l12_n264()
+ fun_l13_n923
+end
+
+def fun_l12_n265()
+ fun_l13_n644
+end
+
+def fun_l12_n266()
+ fun_l13_n334
+end
+
+def fun_l12_n267()
+ fun_l13_n201
+end
+
+def fun_l12_n268()
+ fun_l13_n690
+end
+
+def fun_l12_n269()
+ fun_l13_n699
+end
+
+def fun_l12_n270()
+ fun_l13_n269
+end
+
+def fun_l12_n271()
+ fun_l13_n582
+end
+
+def fun_l12_n272()
+ fun_l13_n513
+end
+
+def fun_l12_n273()
+ fun_l13_n723
+end
+
+def fun_l12_n274()
+ fun_l13_n757
+end
+
+def fun_l12_n275()
+ fun_l13_n390
+end
+
+def fun_l12_n276()
+ fun_l13_n459
+end
+
+def fun_l12_n277()
+ fun_l13_n973
+end
+
+def fun_l12_n278()
+ fun_l13_n762
+end
+
+def fun_l12_n279()
+ fun_l13_n829
+end
+
+def fun_l12_n280()
+ fun_l13_n706
+end
+
+def fun_l12_n281()
+ fun_l13_n769
+end
+
+def fun_l12_n282()
+ fun_l13_n736
+end
+
+def fun_l12_n283()
+ fun_l13_n931
+end
+
+def fun_l12_n284()
+ fun_l13_n226
+end
+
+def fun_l12_n285()
+ fun_l13_n688
+end
+
+def fun_l12_n286()
+ fun_l13_n74
+end
+
+def fun_l12_n287()
+ fun_l13_n470
+end
+
+def fun_l12_n288()
+ fun_l13_n932
+end
+
+def fun_l12_n289()
+ fun_l13_n923
+end
+
+def fun_l12_n290()
+ fun_l13_n53
+end
+
+def fun_l12_n291()
+ fun_l13_n113
+end
+
+def fun_l12_n292()
+ fun_l13_n115
+end
+
+def fun_l12_n293()
+ fun_l13_n864
+end
+
+def fun_l12_n294()
+ fun_l13_n503
+end
+
+def fun_l12_n295()
+ fun_l13_n998
+end
+
+def fun_l12_n296()
+ fun_l13_n637
+end
+
+def fun_l12_n297()
+ fun_l13_n655
+end
+
+def fun_l12_n298()
+ fun_l13_n50
+end
+
+def fun_l12_n299()
+ fun_l13_n564
+end
+
+def fun_l12_n300()
+ fun_l13_n39
+end
+
+def fun_l12_n301()
+ fun_l13_n836
+end
+
+def fun_l12_n302()
+ fun_l13_n85
+end
+
+def fun_l12_n303()
+ fun_l13_n992
+end
+
+def fun_l12_n304()
+ fun_l13_n956
+end
+
+def fun_l12_n305()
+ fun_l13_n746
+end
+
+def fun_l12_n306()
+ fun_l13_n281
+end
+
+def fun_l12_n307()
+ fun_l13_n790
+end
+
+def fun_l12_n308()
+ fun_l13_n69
+end
+
+def fun_l12_n309()
+ fun_l13_n296
+end
+
+def fun_l12_n310()
+ fun_l13_n239
+end
+
+def fun_l12_n311()
+ fun_l13_n451
+end
+
+def fun_l12_n312()
+ fun_l13_n756
+end
+
+def fun_l12_n313()
+ fun_l13_n339
+end
+
+def fun_l12_n314()
+ fun_l13_n438
+end
+
+def fun_l12_n315()
+ fun_l13_n840
+end
+
+def fun_l12_n316()
+ fun_l13_n903
+end
+
+def fun_l12_n317()
+ fun_l13_n506
+end
+
+def fun_l12_n318()
+ fun_l13_n529
+end
+
+def fun_l12_n319()
+ fun_l13_n242
+end
+
+def fun_l12_n320()
+ fun_l13_n658
+end
+
+def fun_l12_n321()
+ fun_l13_n34
+end
+
+def fun_l12_n322()
+ fun_l13_n89
+end
+
+def fun_l12_n323()
+ fun_l13_n29
+end
+
+def fun_l12_n324()
+ fun_l13_n981
+end
+
+def fun_l12_n325()
+ fun_l13_n463
+end
+
+def fun_l12_n326()
+ fun_l13_n889
+end
+
+def fun_l12_n327()
+ fun_l13_n583
+end
+
+def fun_l12_n328()
+ fun_l13_n291
+end
+
+def fun_l12_n329()
+ fun_l13_n618
+end
+
+def fun_l12_n330()
+ fun_l13_n660
+end
+
+def fun_l12_n331()
+ fun_l13_n545
+end
+
+def fun_l12_n332()
+ fun_l13_n817
+end
+
+def fun_l12_n333()
+ fun_l13_n399
+end
+
+def fun_l12_n334()
+ fun_l13_n579
+end
+
+def fun_l12_n335()
+ fun_l13_n508
+end
+
+def fun_l12_n336()
+ fun_l13_n979
+end
+
+def fun_l12_n337()
+ fun_l13_n826
+end
+
+def fun_l12_n338()
+ fun_l13_n18
+end
+
+def fun_l12_n339()
+ fun_l13_n218
+end
+
+def fun_l12_n340()
+ fun_l13_n344
+end
+
+def fun_l12_n341()
+ fun_l13_n280
+end
+
+def fun_l12_n342()
+ fun_l13_n244
+end
+
+def fun_l12_n343()
+ fun_l13_n857
+end
+
+def fun_l12_n344()
+ fun_l13_n301
+end
+
+def fun_l12_n345()
+ fun_l13_n428
+end
+
+def fun_l12_n346()
+ fun_l13_n192
+end
+
+def fun_l12_n347()
+ fun_l13_n155
+end
+
+def fun_l12_n348()
+ fun_l13_n414
+end
+
+def fun_l12_n349()
+ fun_l13_n196
+end
+
+def fun_l12_n350()
+ fun_l13_n824
+end
+
+def fun_l12_n351()
+ fun_l13_n901
+end
+
+def fun_l12_n352()
+ fun_l13_n705
+end
+
+def fun_l12_n353()
+ fun_l13_n872
+end
+
+def fun_l12_n354()
+ fun_l13_n82
+end
+
+def fun_l12_n355()
+ fun_l13_n664
+end
+
+def fun_l12_n356()
+ fun_l13_n948
+end
+
+def fun_l12_n357()
+ fun_l13_n430
+end
+
+def fun_l12_n358()
+ fun_l13_n716
+end
+
+def fun_l12_n359()
+ fun_l13_n319
+end
+
+def fun_l12_n360()
+ fun_l13_n680
+end
+
+def fun_l12_n361()
+ fun_l13_n961
+end
+
+def fun_l12_n362()
+ fun_l13_n347
+end
+
+def fun_l12_n363()
+ fun_l13_n164
+end
+
+def fun_l12_n364()
+ fun_l13_n849
+end
+
+def fun_l12_n365()
+ fun_l13_n448
+end
+
+def fun_l12_n366()
+ fun_l13_n622
+end
+
+def fun_l12_n367()
+ fun_l13_n191
+end
+
+def fun_l12_n368()
+ fun_l13_n818
+end
+
+def fun_l12_n369()
+ fun_l13_n525
+end
+
+def fun_l12_n370()
+ fun_l13_n343
+end
+
+def fun_l12_n371()
+ fun_l13_n789
+end
+
+def fun_l12_n372()
+ fun_l13_n811
+end
+
+def fun_l12_n373()
+ fun_l13_n503
+end
+
+def fun_l12_n374()
+ fun_l13_n529
+end
+
+def fun_l12_n375()
+ fun_l13_n471
+end
+
+def fun_l12_n376()
+ fun_l13_n654
+end
+
+def fun_l12_n377()
+ fun_l13_n155
+end
+
+def fun_l12_n378()
+ fun_l13_n79
+end
+
+def fun_l12_n379()
+ fun_l13_n545
+end
+
+def fun_l12_n380()
+ fun_l13_n315
+end
+
+def fun_l12_n381()
+ fun_l13_n655
+end
+
+def fun_l12_n382()
+ fun_l13_n450
+end
+
+def fun_l12_n383()
+ fun_l13_n353
+end
+
+def fun_l12_n384()
+ fun_l13_n700
+end
+
+def fun_l12_n385()
+ fun_l13_n524
+end
+
+def fun_l12_n386()
+ fun_l13_n158
+end
+
+def fun_l12_n387()
+ fun_l13_n880
+end
+
+def fun_l12_n388()
+ fun_l13_n366
+end
+
+def fun_l12_n389()
+ fun_l13_n848
+end
+
+def fun_l12_n390()
+ fun_l13_n45
+end
+
+def fun_l12_n391()
+ fun_l13_n318
+end
+
+def fun_l12_n392()
+ fun_l13_n331
+end
+
+def fun_l12_n393()
+ fun_l13_n528
+end
+
+def fun_l12_n394()
+ fun_l13_n789
+end
+
+def fun_l12_n395()
+ fun_l13_n71
+end
+
+def fun_l12_n396()
+ fun_l13_n317
+end
+
+def fun_l12_n397()
+ fun_l13_n671
+end
+
+def fun_l12_n398()
+ fun_l13_n788
+end
+
+def fun_l12_n399()
+ fun_l13_n276
+end
+
+def fun_l12_n400()
+ fun_l13_n34
+end
+
+def fun_l12_n401()
+ fun_l13_n321
+end
+
+def fun_l12_n402()
+ fun_l13_n737
+end
+
+def fun_l12_n403()
+ fun_l13_n900
+end
+
+def fun_l12_n404()
+ fun_l13_n491
+end
+
+def fun_l12_n405()
+ fun_l13_n826
+end
+
+def fun_l12_n406()
+ fun_l13_n124
+end
+
+def fun_l12_n407()
+ fun_l13_n658
+end
+
+def fun_l12_n408()
+ fun_l13_n159
+end
+
+def fun_l12_n409()
+ fun_l13_n481
+end
+
+def fun_l12_n410()
+ fun_l13_n900
+end
+
+def fun_l12_n411()
+ fun_l13_n481
+end
+
+def fun_l12_n412()
+ fun_l13_n252
+end
+
+def fun_l12_n413()
+ fun_l13_n732
+end
+
+def fun_l12_n414()
+ fun_l13_n94
+end
+
+def fun_l12_n415()
+ fun_l13_n699
+end
+
+def fun_l12_n416()
+ fun_l13_n638
+end
+
+def fun_l12_n417()
+ fun_l13_n108
+end
+
+def fun_l12_n418()
+ fun_l13_n731
+end
+
+def fun_l12_n419()
+ fun_l13_n965
+end
+
+def fun_l12_n420()
+ fun_l13_n704
+end
+
+def fun_l12_n421()
+ fun_l13_n710
+end
+
+def fun_l12_n422()
+ fun_l13_n888
+end
+
+def fun_l12_n423()
+ fun_l13_n331
+end
+
+def fun_l12_n424()
+ fun_l13_n586
+end
+
+def fun_l12_n425()
+ fun_l13_n302
+end
+
+def fun_l12_n426()
+ fun_l13_n514
+end
+
+def fun_l12_n427()
+ fun_l13_n533
+end
+
+def fun_l12_n428()
+ fun_l13_n759
+end
+
+def fun_l12_n429()
+ fun_l13_n652
+end
+
+def fun_l12_n430()
+ fun_l13_n600
+end
+
+def fun_l12_n431()
+ fun_l13_n808
+end
+
+def fun_l12_n432()
+ fun_l13_n345
+end
+
+def fun_l12_n433()
+ fun_l13_n257
+end
+
+def fun_l12_n434()
+ fun_l13_n91
+end
+
+def fun_l12_n435()
+ fun_l13_n627
+end
+
+def fun_l12_n436()
+ fun_l13_n293
+end
+
+def fun_l12_n437()
+ fun_l13_n618
+end
+
+def fun_l12_n438()
+ fun_l13_n462
+end
+
+def fun_l12_n439()
+ fun_l13_n0
+end
+
+def fun_l12_n440()
+ fun_l13_n32
+end
+
+def fun_l12_n441()
+ fun_l13_n4
+end
+
+def fun_l12_n442()
+ fun_l13_n257
+end
+
+def fun_l12_n443()
+ fun_l13_n548
+end
+
+def fun_l12_n444()
+ fun_l13_n300
+end
+
+def fun_l12_n445()
+ fun_l13_n253
+end
+
+def fun_l12_n446()
+ fun_l13_n603
+end
+
+def fun_l12_n447()
+ fun_l13_n295
+end
+
+def fun_l12_n448()
+ fun_l13_n921
+end
+
+def fun_l12_n449()
+ fun_l13_n119
+end
+
+def fun_l12_n450()
+ fun_l13_n51
+end
+
+def fun_l12_n451()
+ fun_l13_n544
+end
+
+def fun_l12_n452()
+ fun_l13_n735
+end
+
+def fun_l12_n453()
+ fun_l13_n20
+end
+
+def fun_l12_n454()
+ fun_l13_n285
+end
+
+def fun_l12_n455()
+ fun_l13_n370
+end
+
+def fun_l12_n456()
+ fun_l13_n245
+end
+
+def fun_l12_n457()
+ fun_l13_n909
+end
+
+def fun_l12_n458()
+ fun_l13_n536
+end
+
+def fun_l12_n459()
+ fun_l13_n665
+end
+
+def fun_l12_n460()
+ fun_l13_n95
+end
+
+def fun_l12_n461()
+ fun_l13_n499
+end
+
+def fun_l12_n462()
+ fun_l13_n105
+end
+
+def fun_l12_n463()
+ fun_l13_n300
+end
+
+def fun_l12_n464()
+ fun_l13_n49
+end
+
+def fun_l12_n465()
+ fun_l13_n567
+end
+
+def fun_l12_n466()
+ fun_l13_n197
+end
+
+def fun_l12_n467()
+ fun_l13_n918
+end
+
+def fun_l12_n468()
+ fun_l13_n735
+end
+
+def fun_l12_n469()
+ fun_l13_n415
+end
+
+def fun_l12_n470()
+ fun_l13_n580
+end
+
+def fun_l12_n471()
+ fun_l13_n119
+end
+
+def fun_l12_n472()
+ fun_l13_n699
+end
+
+def fun_l12_n473()
+ fun_l13_n128
+end
+
+def fun_l12_n474()
+ fun_l13_n251
+end
+
+def fun_l12_n475()
+ fun_l13_n986
+end
+
+def fun_l12_n476()
+ fun_l13_n55
+end
+
+def fun_l12_n477()
+ fun_l13_n394
+end
+
+def fun_l12_n478()
+ fun_l13_n564
+end
+
+def fun_l12_n479()
+ fun_l13_n927
+end
+
+def fun_l12_n480()
+ fun_l13_n614
+end
+
+def fun_l12_n481()
+ fun_l13_n425
+end
+
+def fun_l12_n482()
+ fun_l13_n55
+end
+
+def fun_l12_n483()
+ fun_l13_n212
+end
+
+def fun_l12_n484()
+ fun_l13_n712
+end
+
+def fun_l12_n485()
+ fun_l13_n393
+end
+
+def fun_l12_n486()
+ fun_l13_n891
+end
+
+def fun_l12_n487()
+ fun_l13_n54
+end
+
+def fun_l12_n488()
+ fun_l13_n508
+end
+
+def fun_l12_n489()
+ fun_l13_n266
+end
+
+def fun_l12_n490()
+ fun_l13_n637
+end
+
+def fun_l12_n491()
+ fun_l13_n683
+end
+
+def fun_l12_n492()
+ fun_l13_n499
+end
+
+def fun_l12_n493()
+ fun_l13_n770
+end
+
+def fun_l12_n494()
+ fun_l13_n254
+end
+
+def fun_l12_n495()
+ fun_l13_n801
+end
+
+def fun_l12_n496()
+ fun_l13_n75
+end
+
+def fun_l12_n497()
+ fun_l13_n652
+end
+
+def fun_l12_n498()
+ fun_l13_n638
+end
+
+def fun_l12_n499()
+ fun_l13_n515
+end
+
+def fun_l12_n500()
+ fun_l13_n580
+end
+
+def fun_l12_n501()
+ fun_l13_n198
+end
+
+def fun_l12_n502()
+ fun_l13_n723
+end
+
+def fun_l12_n503()
+ fun_l13_n855
+end
+
+def fun_l12_n504()
+ fun_l13_n969
+end
+
+def fun_l12_n505()
+ fun_l13_n16
+end
+
+def fun_l12_n506()
+ fun_l13_n477
+end
+
+def fun_l12_n507()
+ fun_l13_n873
+end
+
+def fun_l12_n508()
+ fun_l13_n456
+end
+
+def fun_l12_n509()
+ fun_l13_n711
+end
+
+def fun_l12_n510()
+ fun_l13_n979
+end
+
+def fun_l12_n511()
+ fun_l13_n830
+end
+
+def fun_l12_n512()
+ fun_l13_n336
+end
+
+def fun_l12_n513()
+ fun_l13_n579
+end
+
+def fun_l12_n514()
+ fun_l13_n128
+end
+
+def fun_l12_n515()
+ fun_l13_n977
+end
+
+def fun_l12_n516()
+ fun_l13_n870
+end
+
+def fun_l12_n517()
+ fun_l13_n133
+end
+
+def fun_l12_n518()
+ fun_l13_n315
+end
+
+def fun_l12_n519()
+ fun_l13_n324
+end
+
+def fun_l12_n520()
+ fun_l13_n721
+end
+
+def fun_l12_n521()
+ fun_l13_n392
+end
+
+def fun_l12_n522()
+ fun_l13_n945
+end
+
+def fun_l12_n523()
+ fun_l13_n497
+end
+
+def fun_l12_n524()
+ fun_l13_n999
+end
+
+def fun_l12_n525()
+ fun_l13_n152
+end
+
+def fun_l12_n526()
+ fun_l13_n535
+end
+
+def fun_l12_n527()
+ fun_l13_n938
+end
+
+def fun_l12_n528()
+ fun_l13_n813
+end
+
+def fun_l12_n529()
+ fun_l13_n497
+end
+
+def fun_l12_n530()
+ fun_l13_n700
+end
+
+def fun_l12_n531()
+ fun_l13_n493
+end
+
+def fun_l12_n532()
+ fun_l13_n549
+end
+
+def fun_l12_n533()
+ fun_l13_n406
+end
+
+def fun_l12_n534()
+ fun_l13_n918
+end
+
+def fun_l12_n535()
+ fun_l13_n891
+end
+
+def fun_l12_n536()
+ fun_l13_n924
+end
+
+def fun_l12_n537()
+ fun_l13_n753
+end
+
+def fun_l12_n538()
+ fun_l13_n582
+end
+
+def fun_l12_n539()
+ fun_l13_n769
+end
+
+def fun_l12_n540()
+ fun_l13_n297
+end
+
+def fun_l12_n541()
+ fun_l13_n261
+end
+
+def fun_l12_n542()
+ fun_l13_n581
+end
+
+def fun_l12_n543()
+ fun_l13_n667
+end
+
+def fun_l12_n544()
+ fun_l13_n955
+end
+
+def fun_l12_n545()
+ fun_l13_n296
+end
+
+def fun_l12_n546()
+ fun_l13_n762
+end
+
+def fun_l12_n547()
+ fun_l13_n755
+end
+
+def fun_l12_n548()
+ fun_l13_n369
+end
+
+def fun_l12_n549()
+ fun_l13_n685
+end
+
+def fun_l12_n550()
+ fun_l13_n675
+end
+
+def fun_l12_n551()
+ fun_l13_n430
+end
+
+def fun_l12_n552()
+ fun_l13_n530
+end
+
+def fun_l12_n553()
+ fun_l13_n17
+end
+
+def fun_l12_n554()
+ fun_l13_n406
+end
+
+def fun_l12_n555()
+ fun_l13_n687
+end
+
+def fun_l12_n556()
+ fun_l13_n972
+end
+
+def fun_l12_n557()
+ fun_l13_n561
+end
+
+def fun_l12_n558()
+ fun_l13_n202
+end
+
+def fun_l12_n559()
+ fun_l13_n788
+end
+
+def fun_l12_n560()
+ fun_l13_n705
+end
+
+def fun_l12_n561()
+ fun_l13_n434
+end
+
+def fun_l12_n562()
+ fun_l13_n965
+end
+
+def fun_l12_n563()
+ fun_l13_n525
+end
+
+def fun_l12_n564()
+ fun_l13_n938
+end
+
+def fun_l12_n565()
+ fun_l13_n346
+end
+
+def fun_l12_n566()
+ fun_l13_n95
+end
+
+def fun_l12_n567()
+ fun_l13_n458
+end
+
+def fun_l12_n568()
+ fun_l13_n769
+end
+
+def fun_l12_n569()
+ fun_l13_n858
+end
+
+def fun_l12_n570()
+ fun_l13_n230
+end
+
+def fun_l12_n571()
+ fun_l13_n977
+end
+
+def fun_l12_n572()
+ fun_l13_n304
+end
+
+def fun_l12_n573()
+ fun_l13_n271
+end
+
+def fun_l12_n574()
+ fun_l13_n106
+end
+
+def fun_l12_n575()
+ fun_l13_n733
+end
+
+def fun_l12_n576()
+ fun_l13_n197
+end
+
+def fun_l12_n577()
+ fun_l13_n624
+end
+
+def fun_l12_n578()
+ fun_l13_n844
+end
+
+def fun_l12_n579()
+ fun_l13_n268
+end
+
+def fun_l12_n580()
+ fun_l13_n394
+end
+
+def fun_l12_n581()
+ fun_l13_n573
+end
+
+def fun_l12_n582()
+ fun_l13_n950
+end
+
+def fun_l12_n583()
+ fun_l13_n163
+end
+
+def fun_l12_n584()
+ fun_l13_n458
+end
+
+def fun_l12_n585()
+ fun_l13_n569
+end
+
+def fun_l12_n586()
+ fun_l13_n808
+end
+
+def fun_l12_n587()
+ fun_l13_n830
+end
+
+def fun_l12_n588()
+ fun_l13_n328
+end
+
+def fun_l12_n589()
+ fun_l13_n235
+end
+
+def fun_l12_n590()
+ fun_l13_n695
+end
+
+def fun_l12_n591()
+ fun_l13_n543
+end
+
+def fun_l12_n592()
+ fun_l13_n635
+end
+
+def fun_l12_n593()
+ fun_l13_n783
+end
+
+def fun_l12_n594()
+ fun_l13_n349
+end
+
+def fun_l12_n595()
+ fun_l13_n108
+end
+
+def fun_l12_n596()
+ fun_l13_n856
+end
+
+def fun_l12_n597()
+ fun_l13_n743
+end
+
+def fun_l12_n598()
+ fun_l13_n640
+end
+
+def fun_l12_n599()
+ fun_l13_n768
+end
+
+def fun_l12_n600()
+ fun_l13_n798
+end
+
+def fun_l12_n601()
+ fun_l13_n941
+end
+
+def fun_l12_n602()
+ fun_l13_n389
+end
+
+def fun_l12_n603()
+ fun_l13_n624
+end
+
+def fun_l12_n604()
+ fun_l13_n209
+end
+
+def fun_l12_n605()
+ fun_l13_n636
+end
+
+def fun_l12_n606()
+ fun_l13_n741
+end
+
+def fun_l12_n607()
+ fun_l13_n461
+end
+
+def fun_l12_n608()
+ fun_l13_n570
+end
+
+def fun_l12_n609()
+ fun_l13_n358
+end
+
+def fun_l12_n610()
+ fun_l13_n408
+end
+
+def fun_l12_n611()
+ fun_l13_n693
+end
+
+def fun_l12_n612()
+ fun_l13_n760
+end
+
+def fun_l12_n613()
+ fun_l13_n402
+end
+
+def fun_l12_n614()
+ fun_l13_n20
+end
+
+def fun_l12_n615()
+ fun_l13_n15
+end
+
+def fun_l12_n616()
+ fun_l13_n931
+end
+
+def fun_l12_n617()
+ fun_l13_n58
+end
+
+def fun_l12_n618()
+ fun_l13_n627
+end
+
+def fun_l12_n619()
+ fun_l13_n149
+end
+
+def fun_l12_n620()
+ fun_l13_n200
+end
+
+def fun_l12_n621()
+ fun_l13_n832
+end
+
+def fun_l12_n622()
+ fun_l13_n605
+end
+
+def fun_l12_n623()
+ fun_l13_n868
+end
+
+def fun_l12_n624()
+ fun_l13_n480
+end
+
+def fun_l12_n625()
+ fun_l13_n991
+end
+
+def fun_l12_n626()
+ fun_l13_n493
+end
+
+def fun_l12_n627()
+ fun_l13_n2
+end
+
+def fun_l12_n628()
+ fun_l13_n851
+end
+
+def fun_l12_n629()
+ fun_l13_n864
+end
+
+def fun_l12_n630()
+ fun_l13_n293
+end
+
+def fun_l12_n631()
+ fun_l13_n909
+end
+
+def fun_l12_n632()
+ fun_l13_n955
+end
+
+def fun_l12_n633()
+ fun_l13_n276
+end
+
+def fun_l12_n634()
+ fun_l13_n345
+end
+
+def fun_l12_n635()
+ fun_l13_n606
+end
+
+def fun_l12_n636()
+ fun_l13_n685
+end
+
+def fun_l12_n637()
+ fun_l13_n989
+end
+
+def fun_l12_n638()
+ fun_l13_n920
+end
+
+def fun_l12_n639()
+ fun_l13_n702
+end
+
+def fun_l12_n640()
+ fun_l13_n6
+end
+
+def fun_l12_n641()
+ fun_l13_n216
+end
+
+def fun_l12_n642()
+ fun_l13_n501
+end
+
+def fun_l12_n643()
+ fun_l13_n500
+end
+
+def fun_l12_n644()
+ fun_l13_n845
+end
+
+def fun_l12_n645()
+ fun_l13_n758
+end
+
+def fun_l12_n646()
+ fun_l13_n999
+end
+
+def fun_l12_n647()
+ fun_l13_n30
+end
+
+def fun_l12_n648()
+ fun_l13_n670
+end
+
+def fun_l12_n649()
+ fun_l13_n551
+end
+
+def fun_l12_n650()
+ fun_l13_n668
+end
+
+def fun_l12_n651()
+ fun_l13_n51
+end
+
+def fun_l12_n652()
+ fun_l13_n35
+end
+
+def fun_l12_n653()
+ fun_l13_n523
+end
+
+def fun_l12_n654()
+ fun_l13_n118
+end
+
+def fun_l12_n655()
+ fun_l13_n49
+end
+
+def fun_l12_n656()
+ fun_l13_n457
+end
+
+def fun_l12_n657()
+ fun_l13_n669
+end
+
+def fun_l12_n658()
+ fun_l13_n93
+end
+
+def fun_l12_n659()
+ fun_l13_n809
+end
+
+def fun_l12_n660()
+ fun_l13_n759
+end
+
+def fun_l12_n661()
+ fun_l13_n224
+end
+
+def fun_l12_n662()
+ fun_l13_n876
+end
+
+def fun_l12_n663()
+ fun_l13_n784
+end
+
+def fun_l12_n664()
+ fun_l13_n39
+end
+
+def fun_l12_n665()
+ fun_l13_n930
+end
+
+def fun_l12_n666()
+ fun_l13_n250
+end
+
+def fun_l12_n667()
+ fun_l13_n247
+end
+
+def fun_l12_n668()
+ fun_l13_n907
+end
+
+def fun_l12_n669()
+ fun_l13_n333
+end
+
+def fun_l12_n670()
+ fun_l13_n97
+end
+
+def fun_l12_n671()
+ fun_l13_n475
+end
+
+def fun_l12_n672()
+ fun_l13_n480
+end
+
+def fun_l12_n673()
+ fun_l13_n943
+end
+
+def fun_l12_n674()
+ fun_l13_n263
+end
+
+def fun_l12_n675()
+ fun_l13_n879
+end
+
+def fun_l12_n676()
+ fun_l13_n537
+end
+
+def fun_l12_n677()
+ fun_l13_n475
+end
+
+def fun_l12_n678()
+ fun_l13_n626
+end
+
+def fun_l12_n679()
+ fun_l13_n397
+end
+
+def fun_l12_n680()
+ fun_l13_n194
+end
+
+def fun_l12_n681()
+ fun_l13_n468
+end
+
+def fun_l12_n682()
+ fun_l13_n566
+end
+
+def fun_l12_n683()
+ fun_l13_n573
+end
+
+def fun_l12_n684()
+ fun_l13_n354
+end
+
+def fun_l12_n685()
+ fun_l13_n251
+end
+
+def fun_l12_n686()
+ fun_l13_n626
+end
+
+def fun_l12_n687()
+ fun_l13_n954
+end
+
+def fun_l12_n688()
+ fun_l13_n732
+end
+
+def fun_l12_n689()
+ fun_l13_n543
+end
+
+def fun_l12_n690()
+ fun_l13_n878
+end
+
+def fun_l12_n691()
+ fun_l13_n520
+end
+
+def fun_l12_n692()
+ fun_l13_n262
+end
+
+def fun_l12_n693()
+ fun_l13_n179
+end
+
+def fun_l12_n694()
+ fun_l13_n851
+end
+
+def fun_l12_n695()
+ fun_l13_n821
+end
+
+def fun_l12_n696()
+ fun_l13_n951
+end
+
+def fun_l12_n697()
+ fun_l13_n707
+end
+
+def fun_l12_n698()
+ fun_l13_n388
+end
+
+def fun_l12_n699()
+ fun_l13_n660
+end
+
+def fun_l12_n700()
+ fun_l13_n658
+end
+
+def fun_l12_n701()
+ fun_l13_n463
+end
+
+def fun_l12_n702()
+ fun_l13_n547
+end
+
+def fun_l12_n703()
+ fun_l13_n319
+end
+
+def fun_l12_n704()
+ fun_l13_n405
+end
+
+def fun_l12_n705()
+ fun_l13_n645
+end
+
+def fun_l12_n706()
+ fun_l13_n147
+end
+
+def fun_l12_n707()
+ fun_l13_n582
+end
+
+def fun_l12_n708()
+ fun_l13_n618
+end
+
+def fun_l12_n709()
+ fun_l13_n156
+end
+
+def fun_l12_n710()
+ fun_l13_n606
+end
+
+def fun_l12_n711()
+ fun_l13_n525
+end
+
+def fun_l12_n712()
+ fun_l13_n513
+end
+
+def fun_l12_n713()
+ fun_l13_n827
+end
+
+def fun_l12_n714()
+ fun_l13_n438
+end
+
+def fun_l12_n715()
+ fun_l13_n72
+end
+
+def fun_l12_n716()
+ fun_l13_n364
+end
+
+def fun_l12_n717()
+ fun_l13_n380
+end
+
+def fun_l12_n718()
+ fun_l13_n898
+end
+
+def fun_l12_n719()
+ fun_l13_n998
+end
+
+def fun_l12_n720()
+ fun_l13_n679
+end
+
+def fun_l12_n721()
+ fun_l13_n738
+end
+
+def fun_l12_n722()
+ fun_l13_n887
+end
+
+def fun_l12_n723()
+ fun_l13_n73
+end
+
+def fun_l12_n724()
+ fun_l13_n309
+end
+
+def fun_l12_n725()
+ fun_l13_n791
+end
+
+def fun_l12_n726()
+ fun_l13_n939
+end
+
+def fun_l12_n727()
+ fun_l13_n27
+end
+
+def fun_l12_n728()
+ fun_l13_n269
+end
+
+def fun_l12_n729()
+ fun_l13_n418
+end
+
+def fun_l12_n730()
+ fun_l13_n659
+end
+
+def fun_l12_n731()
+ fun_l13_n257
+end
+
+def fun_l12_n732()
+ fun_l13_n519
+end
+
+def fun_l12_n733()
+ fun_l13_n305
+end
+
+def fun_l12_n734()
+ fun_l13_n994
+end
+
+def fun_l12_n735()
+ fun_l13_n159
+end
+
+def fun_l12_n736()
+ fun_l13_n704
+end
+
+def fun_l12_n737()
+ fun_l13_n826
+end
+
+def fun_l12_n738()
+ fun_l13_n204
+end
+
+def fun_l12_n739()
+ fun_l13_n886
+end
+
+def fun_l12_n740()
+ fun_l13_n403
+end
+
+def fun_l12_n741()
+ fun_l13_n567
+end
+
+def fun_l12_n742()
+ fun_l13_n425
+end
+
+def fun_l12_n743()
+ fun_l13_n174
+end
+
+def fun_l12_n744()
+ fun_l13_n530
+end
+
+def fun_l12_n745()
+ fun_l13_n143
+end
+
+def fun_l12_n746()
+ fun_l13_n950
+end
+
+def fun_l12_n747()
+ fun_l13_n982
+end
+
+def fun_l12_n748()
+ fun_l13_n340
+end
+
+def fun_l12_n749()
+ fun_l13_n964
+end
+
+def fun_l12_n750()
+ fun_l13_n747
+end
+
+def fun_l12_n751()
+ fun_l13_n886
+end
+
+def fun_l12_n752()
+ fun_l13_n148
+end
+
+def fun_l12_n753()
+ fun_l13_n675
+end
+
+def fun_l12_n754()
+ fun_l13_n69
+end
+
+def fun_l12_n755()
+ fun_l13_n992
+end
+
+def fun_l12_n756()
+ fun_l13_n126
+end
+
+def fun_l12_n757()
+ fun_l13_n919
+end
+
+def fun_l12_n758()
+ fun_l13_n286
+end
+
+def fun_l12_n759()
+ fun_l13_n472
+end
+
+def fun_l12_n760()
+ fun_l13_n35
+end
+
+def fun_l12_n761()
+ fun_l13_n130
+end
+
+def fun_l12_n762()
+ fun_l13_n394
+end
+
+def fun_l12_n763()
+ fun_l13_n372
+end
+
+def fun_l12_n764()
+ fun_l13_n630
+end
+
+def fun_l12_n765()
+ fun_l13_n439
+end
+
+def fun_l12_n766()
+ fun_l13_n973
+end
+
+def fun_l12_n767()
+ fun_l13_n859
+end
+
+def fun_l12_n768()
+ fun_l13_n903
+end
+
+def fun_l12_n769()
+ fun_l13_n441
+end
+
+def fun_l12_n770()
+ fun_l13_n530
+end
+
+def fun_l12_n771()
+ fun_l13_n584
+end
+
+def fun_l12_n772()
+ fun_l13_n676
+end
+
+def fun_l12_n773()
+ fun_l13_n595
+end
+
+def fun_l12_n774()
+ fun_l13_n523
+end
+
+def fun_l12_n775()
+ fun_l13_n619
+end
+
+def fun_l12_n776()
+ fun_l13_n727
+end
+
+def fun_l12_n777()
+ fun_l13_n793
+end
+
+def fun_l12_n778()
+ fun_l13_n55
+end
+
+def fun_l12_n779()
+ fun_l13_n675
+end
+
+def fun_l12_n780()
+ fun_l13_n779
+end
+
+def fun_l12_n781()
+ fun_l13_n413
+end
+
+def fun_l12_n782()
+ fun_l13_n148
+end
+
+def fun_l12_n783()
+ fun_l13_n149
+end
+
+def fun_l12_n784()
+ fun_l13_n242
+end
+
+def fun_l12_n785()
+ fun_l13_n619
+end
+
+def fun_l12_n786()
+ fun_l13_n171
+end
+
+def fun_l12_n787()
+ fun_l13_n646
+end
+
+def fun_l12_n788()
+ fun_l13_n470
+end
+
+def fun_l12_n789()
+ fun_l13_n812
+end
+
+def fun_l12_n790()
+ fun_l13_n891
+end
+
+def fun_l12_n791()
+ fun_l13_n958
+end
+
+def fun_l12_n792()
+ fun_l13_n451
+end
+
+def fun_l12_n793()
+ fun_l13_n651
+end
+
+def fun_l12_n794()
+ fun_l13_n904
+end
+
+def fun_l12_n795()
+ fun_l13_n400
+end
+
+def fun_l12_n796()
+ fun_l13_n286
+end
+
+def fun_l12_n797()
+ fun_l13_n17
+end
+
+def fun_l12_n798()
+ fun_l13_n280
+end
+
+def fun_l12_n799()
+ fun_l13_n19
+end
+
+def fun_l12_n800()
+ fun_l13_n909
+end
+
+def fun_l12_n801()
+ fun_l13_n434
+end
+
+def fun_l12_n802()
+ fun_l13_n920
+end
+
+def fun_l12_n803()
+ fun_l13_n196
+end
+
+def fun_l12_n804()
+ fun_l13_n374
+end
+
+def fun_l12_n805()
+ fun_l13_n393
+end
+
+def fun_l12_n806()
+ fun_l13_n623
+end
+
+def fun_l12_n807()
+ fun_l13_n846
+end
+
+def fun_l12_n808()
+ fun_l13_n354
+end
+
+def fun_l12_n809()
+ fun_l13_n16
+end
+
+def fun_l12_n810()
+ fun_l13_n371
+end
+
+def fun_l12_n811()
+ fun_l13_n139
+end
+
+def fun_l12_n812()
+ fun_l13_n156
+end
+
+def fun_l12_n813()
+ fun_l13_n799
+end
+
+def fun_l12_n814()
+ fun_l13_n817
+end
+
+def fun_l12_n815()
+ fun_l13_n475
+end
+
+def fun_l12_n816()
+ fun_l13_n799
+end
+
+def fun_l12_n817()
+ fun_l13_n838
+end
+
+def fun_l12_n818()
+ fun_l13_n297
+end
+
+def fun_l12_n819()
+ fun_l13_n834
+end
+
+def fun_l12_n820()
+ fun_l13_n788
+end
+
+def fun_l12_n821()
+ fun_l13_n649
+end
+
+def fun_l12_n822()
+ fun_l13_n908
+end
+
+def fun_l12_n823()
+ fun_l13_n264
+end
+
+def fun_l12_n824()
+ fun_l13_n66
+end
+
+def fun_l12_n825()
+ fun_l13_n367
+end
+
+def fun_l12_n826()
+ fun_l13_n569
+end
+
+def fun_l12_n827()
+ fun_l13_n735
+end
+
+def fun_l12_n828()
+ fun_l13_n704
+end
+
+def fun_l12_n829()
+ fun_l13_n440
+end
+
+def fun_l12_n830()
+ fun_l13_n126
+end
+
+def fun_l12_n831()
+ fun_l13_n590
+end
+
+def fun_l12_n832()
+ fun_l13_n485
+end
+
+def fun_l12_n833()
+ fun_l13_n869
+end
+
+def fun_l12_n834()
+ fun_l13_n691
+end
+
+def fun_l12_n835()
+ fun_l13_n912
+end
+
+def fun_l12_n836()
+ fun_l13_n618
+end
+
+def fun_l12_n837()
+ fun_l13_n64
+end
+
+def fun_l12_n838()
+ fun_l13_n927
+end
+
+def fun_l12_n839()
+ fun_l13_n500
+end
+
+def fun_l12_n840()
+ fun_l13_n280
+end
+
+def fun_l12_n841()
+ fun_l13_n272
+end
+
+def fun_l12_n842()
+ fun_l13_n66
+end
+
+def fun_l12_n843()
+ fun_l13_n169
+end
+
+def fun_l12_n844()
+ fun_l13_n568
+end
+
+def fun_l12_n845()
+ fun_l13_n678
+end
+
+def fun_l12_n846()
+ fun_l13_n269
+end
+
+def fun_l12_n847()
+ fun_l13_n936
+end
+
+def fun_l12_n848()
+ fun_l13_n34
+end
+
+def fun_l12_n849()
+ fun_l13_n475
+end
+
+def fun_l12_n850()
+ fun_l13_n558
+end
+
+def fun_l12_n851()
+ fun_l13_n779
+end
+
+def fun_l12_n852()
+ fun_l13_n421
+end
+
+def fun_l12_n853()
+ fun_l13_n339
+end
+
+def fun_l12_n854()
+ fun_l13_n266
+end
+
+def fun_l12_n855()
+ fun_l13_n346
+end
+
+def fun_l12_n856()
+ fun_l13_n247
+end
+
+def fun_l12_n857()
+ fun_l13_n608
+end
+
+def fun_l12_n858()
+ fun_l13_n878
+end
+
+def fun_l12_n859()
+ fun_l13_n89
+end
+
+def fun_l12_n860()
+ fun_l13_n380
+end
+
+def fun_l12_n861()
+ fun_l13_n859
+end
+
+def fun_l12_n862()
+ fun_l13_n955
+end
+
+def fun_l12_n863()
+ fun_l13_n392
+end
+
+def fun_l12_n864()
+ fun_l13_n43
+end
+
+def fun_l12_n865()
+ fun_l13_n506
+end
+
+def fun_l12_n866()
+ fun_l13_n45
+end
+
+def fun_l12_n867()
+ fun_l13_n898
+end
+
+def fun_l12_n868()
+ fun_l13_n1
+end
+
+def fun_l12_n869()
+ fun_l13_n159
+end
+
+def fun_l12_n870()
+ fun_l13_n265
+end
+
+def fun_l12_n871()
+ fun_l13_n540
+end
+
+def fun_l12_n872()
+ fun_l13_n563
+end
+
+def fun_l12_n873()
+ fun_l13_n845
+end
+
+def fun_l12_n874()
+ fun_l13_n753
+end
+
+def fun_l12_n875()
+ fun_l13_n815
+end
+
+def fun_l12_n876()
+ fun_l13_n483
+end
+
+def fun_l12_n877()
+ fun_l13_n868
+end
+
+def fun_l12_n878()
+ fun_l13_n961
+end
+
+def fun_l12_n879()
+ fun_l13_n688
+end
+
+def fun_l12_n880()
+ fun_l13_n357
+end
+
+def fun_l12_n881()
+ fun_l13_n543
+end
+
+def fun_l12_n882()
+ fun_l13_n965
+end
+
+def fun_l12_n883()
+ fun_l13_n977
+end
+
+def fun_l12_n884()
+ fun_l13_n185
+end
+
+def fun_l12_n885()
+ fun_l13_n734
+end
+
+def fun_l12_n886()
+ fun_l13_n343
+end
+
+def fun_l12_n887()
+ fun_l13_n43
+end
+
+def fun_l12_n888()
+ fun_l13_n248
+end
+
+def fun_l12_n889()
+ fun_l13_n943
+end
+
+def fun_l12_n890()
+ fun_l13_n504
+end
+
+def fun_l12_n891()
+ fun_l13_n330
+end
+
+def fun_l12_n892()
+ fun_l13_n898
+end
+
+def fun_l12_n893()
+ fun_l13_n495
+end
+
+def fun_l12_n894()
+ fun_l13_n180
+end
+
+def fun_l12_n895()
+ fun_l13_n134
+end
+
+def fun_l12_n896()
+ fun_l13_n883
+end
+
+def fun_l12_n897()
+ fun_l13_n881
+end
+
+def fun_l12_n898()
+ fun_l13_n376
+end
+
+def fun_l12_n899()
+ fun_l13_n840
+end
+
+def fun_l12_n900()
+ fun_l13_n784
+end
+
+def fun_l12_n901()
+ fun_l13_n694
+end
+
+def fun_l12_n902()
+ fun_l13_n431
+end
+
+def fun_l12_n903()
+ fun_l13_n16
+end
+
+def fun_l12_n904()
+ fun_l13_n192
+end
+
+def fun_l12_n905()
+ fun_l13_n932
+end
+
+def fun_l12_n906()
+ fun_l13_n160
+end
+
+def fun_l12_n907()
+ fun_l13_n426
+end
+
+def fun_l12_n908()
+ fun_l13_n283
+end
+
+def fun_l12_n909()
+ fun_l13_n569
+end
+
+def fun_l12_n910()
+ fun_l13_n206
+end
+
+def fun_l12_n911()
+ fun_l13_n741
+end
+
+def fun_l12_n912()
+ fun_l13_n173
+end
+
+def fun_l12_n913()
+ fun_l13_n272
+end
+
+def fun_l12_n914()
+ fun_l13_n172
+end
+
+def fun_l12_n915()
+ fun_l13_n63
+end
+
+def fun_l12_n916()
+ fun_l13_n749
+end
+
+def fun_l12_n917()
+ fun_l13_n450
+end
+
+def fun_l12_n918()
+ fun_l13_n53
+end
+
+def fun_l12_n919()
+ fun_l13_n331
+end
+
+def fun_l12_n920()
+ fun_l13_n186
+end
+
+def fun_l12_n921()
+ fun_l13_n454
+end
+
+def fun_l12_n922()
+ fun_l13_n763
+end
+
+def fun_l12_n923()
+ fun_l13_n124
+end
+
+def fun_l12_n924()
+ fun_l13_n134
+end
+
+def fun_l12_n925()
+ fun_l13_n38
+end
+
+def fun_l12_n926()
+ fun_l13_n645
+end
+
+def fun_l12_n927()
+ fun_l13_n683
+end
+
+def fun_l12_n928()
+ fun_l13_n859
+end
+
+def fun_l12_n929()
+ fun_l13_n406
+end
+
+def fun_l12_n930()
+ fun_l13_n534
+end
+
+def fun_l12_n931()
+ fun_l13_n72
+end
+
+def fun_l12_n932()
+ fun_l13_n288
+end
+
+def fun_l12_n933()
+ fun_l13_n3
+end
+
+def fun_l12_n934()
+ fun_l13_n852
+end
+
+def fun_l12_n935()
+ fun_l13_n290
+end
+
+def fun_l12_n936()
+ fun_l13_n237
+end
+
+def fun_l12_n937()
+ fun_l13_n674
+end
+
+def fun_l12_n938()
+ fun_l13_n278
+end
+
+def fun_l12_n939()
+ fun_l13_n579
+end
+
+def fun_l12_n940()
+ fun_l13_n736
+end
+
+def fun_l12_n941()
+ fun_l13_n684
+end
+
+def fun_l12_n942()
+ fun_l13_n744
+end
+
+def fun_l12_n943()
+ fun_l13_n726
+end
+
+def fun_l12_n944()
+ fun_l13_n767
+end
+
+def fun_l12_n945()
+ fun_l13_n466
+end
+
+def fun_l12_n946()
+ fun_l13_n679
+end
+
+def fun_l12_n947()
+ fun_l13_n774
+end
+
+def fun_l12_n948()
+ fun_l13_n104
+end
+
+def fun_l12_n949()
+ fun_l13_n744
+end
+
+def fun_l12_n950()
+ fun_l13_n339
+end
+
+def fun_l12_n951()
+ fun_l13_n848
+end
+
+def fun_l12_n952()
+ fun_l13_n194
+end
+
+def fun_l12_n953()
+ fun_l13_n733
+end
+
+def fun_l12_n954()
+ fun_l13_n430
+end
+
+def fun_l12_n955()
+ fun_l13_n95
+end
+
+def fun_l12_n956()
+ fun_l13_n68
+end
+
+def fun_l12_n957()
+ fun_l13_n951
+end
+
+def fun_l12_n958()
+ fun_l13_n671
+end
+
+def fun_l12_n959()
+ fun_l13_n464
+end
+
+def fun_l12_n960()
+ fun_l13_n700
+end
+
+def fun_l12_n961()
+ fun_l13_n662
+end
+
+def fun_l12_n962()
+ fun_l13_n765
+end
+
+def fun_l12_n963()
+ fun_l13_n662
+end
+
+def fun_l12_n964()
+ fun_l13_n750
+end
+
+def fun_l12_n965()
+ fun_l13_n935
+end
+
+def fun_l12_n966()
+ fun_l13_n585
+end
+
+def fun_l12_n967()
+ fun_l13_n430
+end
+
+def fun_l12_n968()
+ fun_l13_n219
+end
+
+def fun_l12_n969()
+ fun_l13_n895
+end
+
+def fun_l12_n970()
+ fun_l13_n47
+end
+
+def fun_l12_n971()
+ fun_l13_n755
+end
+
+def fun_l12_n972()
+ fun_l13_n56
+end
+
+def fun_l12_n973()
+ fun_l13_n341
+end
+
+def fun_l12_n974()
+ fun_l13_n192
+end
+
+def fun_l12_n975()
+ fun_l13_n434
+end
+
+def fun_l12_n976()
+ fun_l13_n215
+end
+
+def fun_l12_n977()
+ fun_l13_n747
+end
+
+def fun_l12_n978()
+ fun_l13_n463
+end
+
+def fun_l12_n979()
+ fun_l13_n408
+end
+
+def fun_l12_n980()
+ fun_l13_n993
+end
+
+def fun_l12_n981()
+ fun_l13_n583
+end
+
+def fun_l12_n982()
+ fun_l13_n752
+end
+
+def fun_l12_n983()
+ fun_l13_n583
+end
+
+def fun_l12_n984()
+ fun_l13_n601
+end
+
+def fun_l12_n985()
+ fun_l13_n490
+end
+
+def fun_l12_n986()
+ fun_l13_n61
+end
+
+def fun_l12_n987()
+ fun_l13_n89
+end
+
+def fun_l12_n988()
+ fun_l13_n533
+end
+
+def fun_l12_n989()
+ fun_l13_n628
+end
+
+def fun_l12_n990()
+ fun_l13_n301
+end
+
+def fun_l12_n991()
+ fun_l13_n553
+end
+
+def fun_l12_n992()
+ fun_l13_n105
+end
+
+def fun_l12_n993()
+ fun_l13_n595
+end
+
+def fun_l12_n994()
+ fun_l13_n384
+end
+
+def fun_l12_n995()
+ fun_l13_n704
+end
+
+def fun_l12_n996()
+ fun_l13_n657
+end
+
+def fun_l12_n997()
+ fun_l13_n468
+end
+
+def fun_l12_n998()
+ fun_l13_n582
+end
+
+def fun_l12_n999()
+ fun_l13_n335
+end
+
+def fun_l13_n0()
+ fun_l14_n123
+end
+
+def fun_l13_n1()
+ fun_l14_n796
+end
+
+def fun_l13_n2()
+ fun_l14_n217
+end
+
+def fun_l13_n3()
+ fun_l14_n810
+end
+
+def fun_l13_n4()
+ fun_l14_n297
+end
+
+def fun_l13_n5()
+ fun_l14_n682
+end
+
+def fun_l13_n6()
+ fun_l14_n397
+end
+
+def fun_l13_n7()
+ fun_l14_n372
+end
+
+def fun_l13_n8()
+ fun_l14_n688
+end
+
+def fun_l13_n9()
+ fun_l14_n250
+end
+
+def fun_l13_n10()
+ fun_l14_n248
+end
+
+def fun_l13_n11()
+ fun_l14_n335
+end
+
+def fun_l13_n12()
+ fun_l14_n404
+end
+
+def fun_l13_n13()
+ fun_l14_n223
+end
+
+def fun_l13_n14()
+ fun_l14_n894
+end
+
+def fun_l13_n15()
+ fun_l14_n537
+end
+
+def fun_l13_n16()
+ fun_l14_n641
+end
+
+def fun_l13_n17()
+ fun_l14_n509
+end
+
+def fun_l13_n18()
+ fun_l14_n624
+end
+
+def fun_l13_n19()
+ fun_l14_n224
+end
+
+def fun_l13_n20()
+ fun_l14_n283
+end
+
+def fun_l13_n21()
+ fun_l14_n624
+end
+
+def fun_l13_n22()
+ fun_l14_n972
+end
+
+def fun_l13_n23()
+ fun_l14_n698
+end
+
+def fun_l13_n24()
+ fun_l14_n313
+end
+
+def fun_l13_n25()
+ fun_l14_n344
+end
+
+def fun_l13_n26()
+ fun_l14_n823
+end
+
+def fun_l13_n27()
+ fun_l14_n699
+end
+
+def fun_l13_n28()
+ fun_l14_n943
+end
+
+def fun_l13_n29()
+ fun_l14_n69
+end
+
+def fun_l13_n30()
+ fun_l14_n839
+end
+
+def fun_l13_n31()
+ fun_l14_n834
+end
+
+def fun_l13_n32()
+ fun_l14_n143
+end
+
+def fun_l13_n33()
+ fun_l14_n500
+end
+
+def fun_l13_n34()
+ fun_l14_n266
+end
+
+def fun_l13_n35()
+ fun_l14_n576
+end
+
+def fun_l13_n36()
+ fun_l14_n247
+end
+
+def fun_l13_n37()
+ fun_l14_n847
+end
+
+def fun_l13_n38()
+ fun_l14_n474
+end
+
+def fun_l13_n39()
+ fun_l14_n293
+end
+
+def fun_l13_n40()
+ fun_l14_n475
+end
+
+def fun_l13_n41()
+ fun_l14_n641
+end
+
+def fun_l13_n42()
+ fun_l14_n583
+end
+
+def fun_l13_n43()
+ fun_l14_n857
+end
+
+def fun_l13_n44()
+ fun_l14_n97
+end
+
+def fun_l13_n45()
+ fun_l14_n196
+end
+
+def fun_l13_n46()
+ fun_l14_n201
+end
+
+def fun_l13_n47()
+ fun_l14_n877
+end
+
+def fun_l13_n48()
+ fun_l14_n464
+end
+
+def fun_l13_n49()
+ fun_l14_n706
+end
+
+def fun_l13_n50()
+ fun_l14_n274
+end
+
+def fun_l13_n51()
+ fun_l14_n844
+end
+
+def fun_l13_n52()
+ fun_l14_n883
+end
+
+def fun_l13_n53()
+ fun_l14_n77
+end
+
+def fun_l13_n54()
+ fun_l14_n981
+end
+
+def fun_l13_n55()
+ fun_l14_n189
+end
+
+def fun_l13_n56()
+ fun_l14_n597
+end
+
+def fun_l13_n57()
+ fun_l14_n333
+end
+
+def fun_l13_n58()
+ fun_l14_n566
+end
+
+def fun_l13_n59()
+ fun_l14_n231
+end
+
+def fun_l13_n60()
+ fun_l14_n207
+end
+
+def fun_l13_n61()
+ fun_l14_n555
+end
+
+def fun_l13_n62()
+ fun_l14_n46
+end
+
+def fun_l13_n63()
+ fun_l14_n879
+end
+
+def fun_l13_n64()
+ fun_l14_n672
+end
+
+def fun_l13_n65()
+ fun_l14_n266
+end
+
+def fun_l13_n66()
+ fun_l14_n898
+end
+
+def fun_l13_n67()
+ fun_l14_n966
+end
+
+def fun_l13_n68()
+ fun_l14_n63
+end
+
+def fun_l13_n69()
+ fun_l14_n531
+end
+
+def fun_l13_n70()
+ fun_l14_n80
+end
+
+def fun_l13_n71()
+ fun_l14_n206
+end
+
+def fun_l13_n72()
+ fun_l14_n594
+end
+
+def fun_l13_n73()
+ fun_l14_n852
+end
+
+def fun_l13_n74()
+ fun_l14_n443
+end
+
+def fun_l13_n75()
+ fun_l14_n987
+end
+
+def fun_l13_n76()
+ fun_l14_n119
+end
+
+def fun_l13_n77()
+ fun_l14_n113
+end
+
+def fun_l13_n78()
+ fun_l14_n904
+end
+
+def fun_l13_n79()
+ fun_l14_n88
+end
+
+def fun_l13_n80()
+ fun_l14_n209
+end
+
+def fun_l13_n81()
+ fun_l14_n190
+end
+
+def fun_l13_n82()
+ fun_l14_n594
+end
+
+def fun_l13_n83()
+ fun_l14_n87
+end
+
+def fun_l13_n84()
+ fun_l14_n206
+end
+
+def fun_l13_n85()
+ fun_l14_n974
+end
+
+def fun_l13_n86()
+ fun_l14_n646
+end
+
+def fun_l13_n87()
+ fun_l14_n450
+end
+
+def fun_l13_n88()
+ fun_l14_n981
+end
+
+def fun_l13_n89()
+ fun_l14_n277
+end
+
+def fun_l13_n90()
+ fun_l14_n309
+end
+
+def fun_l13_n91()
+ fun_l14_n648
+end
+
+def fun_l13_n92()
+ fun_l14_n353
+end
+
+def fun_l13_n93()
+ fun_l14_n43
+end
+
+def fun_l13_n94()
+ fun_l14_n217
+end
+
+def fun_l13_n95()
+ fun_l14_n945
+end
+
+def fun_l13_n96()
+ fun_l14_n172
+end
+
+def fun_l13_n97()
+ fun_l14_n604
+end
+
+def fun_l13_n98()
+ fun_l14_n252
+end
+
+def fun_l13_n99()
+ fun_l14_n478
+end
+
+def fun_l13_n100()
+ fun_l14_n564
+end
+
+def fun_l13_n101()
+ fun_l14_n937
+end
+
+def fun_l13_n102()
+ fun_l14_n940
+end
+
+def fun_l13_n103()
+ fun_l14_n110
+end
+
+def fun_l13_n104()
+ fun_l14_n175
+end
+
+def fun_l13_n105()
+ fun_l14_n708
+end
+
+def fun_l13_n106()
+ fun_l14_n161
+end
+
+def fun_l13_n107()
+ fun_l14_n129
+end
+
+def fun_l13_n108()
+ fun_l14_n186
+end
+
+def fun_l13_n109()
+ fun_l14_n449
+end
+
+def fun_l13_n110()
+ fun_l14_n358
+end
+
+def fun_l13_n111()
+ fun_l14_n278
+end
+
+def fun_l13_n112()
+ fun_l14_n598
+end
+
+def fun_l13_n113()
+ fun_l14_n896
+end
+
+def fun_l13_n114()
+ fun_l14_n964
+end
+
+def fun_l13_n115()
+ fun_l14_n986
+end
+
+def fun_l13_n116()
+ fun_l14_n268
+end
+
+def fun_l13_n117()
+ fun_l14_n521
+end
+
+def fun_l13_n118()
+ fun_l14_n968
+end
+
+def fun_l13_n119()
+ fun_l14_n380
+end
+
+def fun_l13_n120()
+ fun_l14_n549
+end
+
+def fun_l13_n121()
+ fun_l14_n300
+end
+
+def fun_l13_n122()
+ fun_l14_n246
+end
+
+def fun_l13_n123()
+ fun_l14_n329
+end
+
+def fun_l13_n124()
+ fun_l14_n134
+end
+
+def fun_l13_n125()
+ fun_l14_n740
+end
+
+def fun_l13_n126()
+ fun_l14_n965
+end
+
+def fun_l13_n127()
+ fun_l14_n284
+end
+
+def fun_l13_n128()
+ fun_l14_n409
+end
+
+def fun_l13_n129()
+ fun_l14_n597
+end
+
+def fun_l13_n130()
+ fun_l14_n285
+end
+
+def fun_l13_n131()
+ fun_l14_n270
+end
+
+def fun_l13_n132()
+ fun_l14_n66
+end
+
+def fun_l13_n133()
+ fun_l14_n588
+end
+
+def fun_l13_n134()
+ fun_l14_n534
+end
+
+def fun_l13_n135()
+ fun_l14_n673
+end
+
+def fun_l13_n136()
+ fun_l14_n867
+end
+
+def fun_l13_n137()
+ fun_l14_n157
+end
+
+def fun_l13_n138()
+ fun_l14_n755
+end
+
+def fun_l13_n139()
+ fun_l14_n68
+end
+
+def fun_l13_n140()
+ fun_l14_n859
+end
+
+def fun_l13_n141()
+ fun_l14_n804
+end
+
+def fun_l13_n142()
+ fun_l14_n300
+end
+
+def fun_l13_n143()
+ fun_l14_n157
+end
+
+def fun_l13_n144()
+ fun_l14_n376
+end
+
+def fun_l13_n145()
+ fun_l14_n62
+end
+
+def fun_l13_n146()
+ fun_l14_n755
+end
+
+def fun_l13_n147()
+ fun_l14_n547
+end
+
+def fun_l13_n148()
+ fun_l14_n223
+end
+
+def fun_l13_n149()
+ fun_l14_n277
+end
+
+def fun_l13_n150()
+ fun_l14_n57
+end
+
+def fun_l13_n151()
+ fun_l14_n552
+end
+
+def fun_l13_n152()
+ fun_l14_n390
+end
+
+def fun_l13_n153()
+ fun_l14_n691
+end
+
+def fun_l13_n154()
+ fun_l14_n871
+end
+
+def fun_l13_n155()
+ fun_l14_n14
+end
+
+def fun_l13_n156()
+ fun_l14_n68
+end
+
+def fun_l13_n157()
+ fun_l14_n589
+end
+
+def fun_l13_n158()
+ fun_l14_n504
+end
+
+def fun_l13_n159()
+ fun_l14_n966
+end
+
+def fun_l13_n160()
+ fun_l14_n62
+end
+
+def fun_l13_n161()
+ fun_l14_n880
+end
+
+def fun_l13_n162()
+ fun_l14_n897
+end
+
+def fun_l13_n163()
+ fun_l14_n630
+end
+
+def fun_l13_n164()
+ fun_l14_n129
+end
+
+def fun_l13_n165()
+ fun_l14_n461
+end
+
+def fun_l13_n166()
+ fun_l14_n193
+end
+
+def fun_l13_n167()
+ fun_l14_n588
+end
+
+def fun_l13_n168()
+ fun_l14_n49
+end
+
+def fun_l13_n169()
+ fun_l14_n872
+end
+
+def fun_l13_n170()
+ fun_l14_n199
+end
+
+def fun_l13_n171()
+ fun_l14_n887
+end
+
+def fun_l13_n172()
+ fun_l14_n932
+end
+
+def fun_l13_n173()
+ fun_l14_n616
+end
+
+def fun_l13_n174()
+ fun_l14_n62
+end
+
+def fun_l13_n175()
+ fun_l14_n162
+end
+
+def fun_l13_n176()
+ fun_l14_n979
+end
+
+def fun_l13_n177()
+ fun_l14_n813
+end
+
+def fun_l13_n178()
+ fun_l14_n529
+end
+
+def fun_l13_n179()
+ fun_l14_n202
+end
+
+def fun_l13_n180()
+ fun_l14_n916
+end
+
+def fun_l13_n181()
+ fun_l14_n719
+end
+
+def fun_l13_n182()
+ fun_l14_n256
+end
+
+def fun_l13_n183()
+ fun_l14_n137
+end
+
+def fun_l13_n184()
+ fun_l14_n562
+end
+
+def fun_l13_n185()
+ fun_l14_n614
+end
+
+def fun_l13_n186()
+ fun_l14_n918
+end
+
+def fun_l13_n187()
+ fun_l14_n435
+end
+
+def fun_l13_n188()
+ fun_l14_n429
+end
+
+def fun_l13_n189()
+ fun_l14_n561
+end
+
+def fun_l13_n190()
+ fun_l14_n422
+end
+
+def fun_l13_n191()
+ fun_l14_n396
+end
+
+def fun_l13_n192()
+ fun_l14_n971
+end
+
+def fun_l13_n193()
+ fun_l14_n419
+end
+
+def fun_l13_n194()
+ fun_l14_n319
+end
+
+def fun_l13_n195()
+ fun_l14_n8
+end
+
+def fun_l13_n196()
+ fun_l14_n378
+end
+
+def fun_l13_n197()
+ fun_l14_n709
+end
+
+def fun_l13_n198()
+ fun_l14_n308
+end
+
+def fun_l13_n199()
+ fun_l14_n916
+end
+
+def fun_l13_n200()
+ fun_l14_n822
+end
+
+def fun_l13_n201()
+ fun_l14_n736
+end
+
+def fun_l13_n202()
+ fun_l14_n259
+end
+
+def fun_l13_n203()
+ fun_l14_n965
+end
+
+def fun_l13_n204()
+ fun_l14_n52
+end
+
+def fun_l13_n205()
+ fun_l14_n237
+end
+
+def fun_l13_n206()
+ fun_l14_n850
+end
+
+def fun_l13_n207()
+ fun_l14_n961
+end
+
+def fun_l13_n208()
+ fun_l14_n289
+end
+
+def fun_l13_n209()
+ fun_l14_n465
+end
+
+def fun_l13_n210()
+ fun_l14_n635
+end
+
+def fun_l13_n211()
+ fun_l14_n222
+end
+
+def fun_l13_n212()
+ fun_l14_n796
+end
+
+def fun_l13_n213()
+ fun_l14_n20
+end
+
+def fun_l13_n214()
+ fun_l14_n576
+end
+
+def fun_l13_n215()
+ fun_l14_n947
+end
+
+def fun_l13_n216()
+ fun_l14_n482
+end
+
+def fun_l13_n217()
+ fun_l14_n236
+end
+
+def fun_l13_n218()
+ fun_l14_n405
+end
+
+def fun_l13_n219()
+ fun_l14_n874
+end
+
+def fun_l13_n220()
+ fun_l14_n827
+end
+
+def fun_l13_n221()
+ fun_l14_n975
+end
+
+def fun_l13_n222()
+ fun_l14_n741
+end
+
+def fun_l13_n223()
+ fun_l14_n60
+end
+
+def fun_l13_n224()
+ fun_l14_n587
+end
+
+def fun_l13_n225()
+ fun_l14_n557
+end
+
+def fun_l13_n226()
+ fun_l14_n621
+end
+
+def fun_l13_n227()
+ fun_l14_n426
+end
+
+def fun_l13_n228()
+ fun_l14_n848
+end
+
+def fun_l13_n229()
+ fun_l14_n164
+end
+
+def fun_l13_n230()
+ fun_l14_n427
+end
+
+def fun_l13_n231()
+ fun_l14_n815
+end
+
+def fun_l13_n232()
+ fun_l14_n465
+end
+
+def fun_l13_n233()
+ fun_l14_n474
+end
+
+def fun_l13_n234()
+ fun_l14_n577
+end
+
+def fun_l13_n235()
+ fun_l14_n427
+end
+
+def fun_l13_n236()
+ fun_l14_n580
+end
+
+def fun_l13_n237()
+ fun_l14_n275
+end
+
+def fun_l13_n238()
+ fun_l14_n559
+end
+
+def fun_l13_n239()
+ fun_l14_n834
+end
+
+def fun_l13_n240()
+ fun_l14_n656
+end
+
+def fun_l13_n241()
+ fun_l14_n411
+end
+
+def fun_l13_n242()
+ fun_l14_n54
+end
+
+def fun_l13_n243()
+ fun_l14_n223
+end
+
+def fun_l13_n244()
+ fun_l14_n623
+end
+
+def fun_l13_n245()
+ fun_l14_n251
+end
+
+def fun_l13_n246()
+ fun_l14_n948
+end
+
+def fun_l13_n247()
+ fun_l14_n857
+end
+
+def fun_l13_n248()
+ fun_l14_n528
+end
+
+def fun_l13_n249()
+ fun_l14_n396
+end
+
+def fun_l13_n250()
+ fun_l14_n832
+end
+
+def fun_l13_n251()
+ fun_l14_n191
+end
+
+def fun_l13_n252()
+ fun_l14_n729
+end
+
+def fun_l13_n253()
+ fun_l14_n22
+end
+
+def fun_l13_n254()
+ fun_l14_n10
+end
+
+def fun_l13_n255()
+ fun_l14_n871
+end
+
+def fun_l13_n256()
+ fun_l14_n664
+end
+
+def fun_l13_n257()
+ fun_l14_n877
+end
+
+def fun_l13_n258()
+ fun_l14_n477
+end
+
+def fun_l13_n259()
+ fun_l14_n861
+end
+
+def fun_l13_n260()
+ fun_l14_n160
+end
+
+def fun_l13_n261()
+ fun_l14_n127
+end
+
+def fun_l13_n262()
+ fun_l14_n744
+end
+
+def fun_l13_n263()
+ fun_l14_n305
+end
+
+def fun_l13_n264()
+ fun_l14_n473
+end
+
+def fun_l13_n265()
+ fun_l14_n445
+end
+
+def fun_l13_n266()
+ fun_l14_n31
+end
+
+def fun_l13_n267()
+ fun_l14_n58
+end
+
+def fun_l13_n268()
+ fun_l14_n739
+end
+
+def fun_l13_n269()
+ fun_l14_n840
+end
+
+def fun_l13_n270()
+ fun_l14_n275
+end
+
+def fun_l13_n271()
+ fun_l14_n264
+end
+
+def fun_l13_n272()
+ fun_l14_n503
+end
+
+def fun_l13_n273()
+ fun_l14_n559
+end
+
+def fun_l13_n274()
+ fun_l14_n693
+end
+
+def fun_l13_n275()
+ fun_l14_n723
+end
+
+def fun_l13_n276()
+ fun_l14_n716
+end
+
+def fun_l13_n277()
+ fun_l14_n181
+end
+
+def fun_l13_n278()
+ fun_l14_n904
+end
+
+def fun_l13_n279()
+ fun_l14_n75
+end
+
+def fun_l13_n280()
+ fun_l14_n992
+end
+
+def fun_l13_n281()
+ fun_l14_n904
+end
+
+def fun_l13_n282()
+ fun_l14_n856
+end
+
+def fun_l13_n283()
+ fun_l14_n218
+end
+
+def fun_l13_n284()
+ fun_l14_n896
+end
+
+def fun_l13_n285()
+ fun_l14_n456
+end
+
+def fun_l13_n286()
+ fun_l14_n591
+end
+
+def fun_l13_n287()
+ fun_l14_n960
+end
+
+def fun_l13_n288()
+ fun_l14_n949
+end
+
+def fun_l13_n289()
+ fun_l14_n92
+end
+
+def fun_l13_n290()
+ fun_l14_n945
+end
+
+def fun_l13_n291()
+ fun_l14_n684
+end
+
+def fun_l13_n292()
+ fun_l14_n8
+end
+
+def fun_l13_n293()
+ fun_l14_n147
+end
+
+def fun_l13_n294()
+ fun_l14_n129
+end
+
+def fun_l13_n295()
+ fun_l14_n308
+end
+
+def fun_l13_n296()
+ fun_l14_n112
+end
+
+def fun_l13_n297()
+ fun_l14_n657
+end
+
+def fun_l13_n298()
+ fun_l14_n910
+end
+
+def fun_l13_n299()
+ fun_l14_n804
+end
+
+def fun_l13_n300()
+ fun_l14_n580
+end
+
+def fun_l13_n301()
+ fun_l14_n373
+end
+
+def fun_l13_n302()
+ fun_l14_n749
+end
+
+def fun_l13_n303()
+ fun_l14_n353
+end
+
+def fun_l13_n304()
+ fun_l14_n58
+end
+
+def fun_l13_n305()
+ fun_l14_n207
+end
+
+def fun_l13_n306()
+ fun_l14_n977
+end
+
+def fun_l13_n307()
+ fun_l14_n95
+end
+
+def fun_l13_n308()
+ fun_l14_n836
+end
+
+def fun_l13_n309()
+ fun_l14_n244
+end
+
+def fun_l13_n310()
+ fun_l14_n676
+end
+
+def fun_l13_n311()
+ fun_l14_n617
+end
+
+def fun_l13_n312()
+ fun_l14_n633
+end
+
+def fun_l13_n313()
+ fun_l14_n550
+end
+
+def fun_l13_n314()
+ fun_l14_n564
+end
+
+def fun_l13_n315()
+ fun_l14_n261
+end
+
+def fun_l13_n316()
+ fun_l14_n968
+end
+
+def fun_l13_n317()
+ fun_l14_n16
+end
+
+def fun_l13_n318()
+ fun_l14_n894
+end
+
+def fun_l13_n319()
+ fun_l14_n717
+end
+
+def fun_l13_n320()
+ fun_l14_n802
+end
+
+def fun_l13_n321()
+ fun_l14_n628
+end
+
+def fun_l13_n322()
+ fun_l14_n306
+end
+
+def fun_l13_n323()
+ fun_l14_n121
+end
+
+def fun_l13_n324()
+ fun_l14_n468
+end
+
+def fun_l13_n325()
+ fun_l14_n863
+end
+
+def fun_l13_n326()
+ fun_l14_n970
+end
+
+def fun_l13_n327()
+ fun_l14_n637
+end
+
+def fun_l13_n328()
+ fun_l14_n12
+end
+
+def fun_l13_n329()
+ fun_l14_n244
+end
+
+def fun_l13_n330()
+ fun_l14_n847
+end
+
+def fun_l13_n331()
+ fun_l14_n122
+end
+
+def fun_l13_n332()
+ fun_l14_n546
+end
+
+def fun_l13_n333()
+ fun_l14_n640
+end
+
+def fun_l13_n334()
+ fun_l14_n224
+end
+
+def fun_l13_n335()
+ fun_l14_n73
+end
+
+def fun_l13_n336()
+ fun_l14_n25
+end
+
+def fun_l13_n337()
+ fun_l14_n226
+end
+
+def fun_l13_n338()
+ fun_l14_n63
+end
+
+def fun_l13_n339()
+ fun_l14_n591
+end
+
+def fun_l13_n340()
+ fun_l14_n32
+end
+
+def fun_l13_n341()
+ fun_l14_n646
+end
+
+def fun_l13_n342()
+ fun_l14_n954
+end
+
+def fun_l13_n343()
+ fun_l14_n915
+end
+
+def fun_l13_n344()
+ fun_l14_n359
+end
+
+def fun_l13_n345()
+ fun_l14_n967
+end
+
+def fun_l13_n346()
+ fun_l14_n980
+end
+
+def fun_l13_n347()
+ fun_l14_n324
+end
+
+def fun_l13_n348()
+ fun_l14_n263
+end
+
+def fun_l13_n349()
+ fun_l14_n644
+end
+
+def fun_l13_n350()
+ fun_l14_n575
+end
+
+def fun_l13_n351()
+ fun_l14_n820
+end
+
+def fun_l13_n352()
+ fun_l14_n767
+end
+
+def fun_l13_n353()
+ fun_l14_n175
+end
+
+def fun_l13_n354()
+ fun_l14_n990
+end
+
+def fun_l13_n355()
+ fun_l14_n631
+end
+
+def fun_l13_n356()
+ fun_l14_n503
+end
+
+def fun_l13_n357()
+ fun_l14_n785
+end
+
+def fun_l13_n358()
+ fun_l14_n239
+end
+
+def fun_l13_n359()
+ fun_l14_n678
+end
+
+def fun_l13_n360()
+ fun_l14_n11
+end
+
+def fun_l13_n361()
+ fun_l14_n829
+end
+
+def fun_l13_n362()
+ fun_l14_n205
+end
+
+def fun_l13_n363()
+ fun_l14_n146
+end
+
+def fun_l13_n364()
+ fun_l14_n972
+end
+
+def fun_l13_n365()
+ fun_l14_n68
+end
+
+def fun_l13_n366()
+ fun_l14_n830
+end
+
+def fun_l13_n367()
+ fun_l14_n60
+end
+
+def fun_l13_n368()
+ fun_l14_n521
+end
+
+def fun_l13_n369()
+ fun_l14_n287
+end
+
+def fun_l13_n370()
+ fun_l14_n932
+end
+
+def fun_l13_n371()
+ fun_l14_n268
+end
+
+def fun_l13_n372()
+ fun_l14_n285
+end
+
+def fun_l13_n373()
+ fun_l14_n101
+end
+
+def fun_l13_n374()
+ fun_l14_n811
+end
+
+def fun_l13_n375()
+ fun_l14_n966
+end
+
+def fun_l13_n376()
+ fun_l14_n201
+end
+
+def fun_l13_n377()
+ fun_l14_n176
+end
+
+def fun_l13_n378()
+ fun_l14_n850
+end
+
+def fun_l13_n379()
+ fun_l14_n436
+end
+
+def fun_l13_n380()
+ fun_l14_n83
+end
+
+def fun_l13_n381()
+ fun_l14_n393
+end
+
+def fun_l13_n382()
+ fun_l14_n812
+end
+
+def fun_l13_n383()
+ fun_l14_n276
+end
+
+def fun_l13_n384()
+ fun_l14_n997
+end
+
+def fun_l13_n385()
+ fun_l14_n942
+end
+
+def fun_l13_n386()
+ fun_l14_n851
+end
+
+def fun_l13_n387()
+ fun_l14_n747
+end
+
+def fun_l13_n388()
+ fun_l14_n573
+end
+
+def fun_l13_n389()
+ fun_l14_n949
+end
+
+def fun_l13_n390()
+ fun_l14_n857
+end
+
+def fun_l13_n391()
+ fun_l14_n495
+end
+
+def fun_l13_n392()
+ fun_l14_n399
+end
+
+def fun_l13_n393()
+ fun_l14_n603
+end
+
+def fun_l13_n394()
+ fun_l14_n208
+end
+
+def fun_l13_n395()
+ fun_l14_n736
+end
+
+def fun_l13_n396()
+ fun_l14_n339
+end
+
+def fun_l13_n397()
+ fun_l14_n759
+end
+
+def fun_l13_n398()
+ fun_l14_n912
+end
+
+def fun_l13_n399()
+ fun_l14_n899
+end
+
+def fun_l13_n400()
+ fun_l14_n954
+end
+
+def fun_l13_n401()
+ fun_l14_n143
+end
+
+def fun_l13_n402()
+ fun_l14_n866
+end
+
+def fun_l13_n403()
+ fun_l14_n657
+end
+
+def fun_l13_n404()
+ fun_l14_n854
+end
+
+def fun_l13_n405()
+ fun_l14_n365
+end
+
+def fun_l13_n406()
+ fun_l14_n79
+end
+
+def fun_l13_n407()
+ fun_l14_n724
+end
+
+def fun_l13_n408()
+ fun_l14_n544
+end
+
+def fun_l13_n409()
+ fun_l14_n562
+end
+
+def fun_l13_n410()
+ fun_l14_n946
+end
+
+def fun_l13_n411()
+ fun_l14_n761
+end
+
+def fun_l13_n412()
+ fun_l14_n251
+end
+
+def fun_l13_n413()
+ fun_l14_n689
+end
+
+def fun_l13_n414()
+ fun_l14_n94
+end
+
+def fun_l13_n415()
+ fun_l14_n466
+end
+
+def fun_l13_n416()
+ fun_l14_n186
+end
+
+def fun_l13_n417()
+ fun_l14_n367
+end
+
+def fun_l13_n418()
+ fun_l14_n477
+end
+
+def fun_l13_n419()
+ fun_l14_n356
+end
+
+def fun_l13_n420()
+ fun_l14_n279
+end
+
+def fun_l13_n421()
+ fun_l14_n76
+end
+
+def fun_l13_n422()
+ fun_l14_n677
+end
+
+def fun_l13_n423()
+ fun_l14_n334
+end
+
+def fun_l13_n424()
+ fun_l14_n777
+end
+
+def fun_l13_n425()
+ fun_l14_n632
+end
+
+def fun_l13_n426()
+ fun_l14_n380
+end
+
+def fun_l13_n427()
+ fun_l14_n833
+end
+
+def fun_l13_n428()
+ fun_l14_n395
+end
+
+def fun_l13_n429()
+ fun_l14_n324
+end
+
+def fun_l13_n430()
+ fun_l14_n608
+end
+
+def fun_l13_n431()
+ fun_l14_n916
+end
+
+def fun_l13_n432()
+ fun_l14_n89
+end
+
+def fun_l13_n433()
+ fun_l14_n239
+end
+
+def fun_l13_n434()
+ fun_l14_n712
+end
+
+def fun_l13_n435()
+ fun_l14_n911
+end
+
+def fun_l13_n436()
+ fun_l14_n810
+end
+
+def fun_l13_n437()
+ fun_l14_n670
+end
+
+def fun_l13_n438()
+ fun_l14_n125
+end
+
+def fun_l13_n439()
+ fun_l14_n903
+end
+
+def fun_l13_n440()
+ fun_l14_n277
+end
+
+def fun_l13_n441()
+ fun_l14_n581
+end
+
+def fun_l13_n442()
+ fun_l14_n726
+end
+
+def fun_l13_n443()
+ fun_l14_n360
+end
+
+def fun_l13_n444()
+ fun_l14_n439
+end
+
+def fun_l13_n445()
+ fun_l14_n441
+end
+
+def fun_l13_n446()
+ fun_l14_n464
+end
+
+def fun_l13_n447()
+ fun_l14_n550
+end
+
+def fun_l13_n448()
+ fun_l14_n94
+end
+
+def fun_l13_n449()
+ fun_l14_n844
+end
+
+def fun_l13_n450()
+ fun_l14_n571
+end
+
+def fun_l13_n451()
+ fun_l14_n161
+end
+
+def fun_l13_n452()
+ fun_l14_n863
+end
+
+def fun_l13_n453()
+ fun_l14_n173
+end
+
+def fun_l13_n454()
+ fun_l14_n330
+end
+
+def fun_l13_n455()
+ fun_l14_n175
+end
+
+def fun_l13_n456()
+ fun_l14_n40
+end
+
+def fun_l13_n457()
+ fun_l14_n335
+end
+
+def fun_l13_n458()
+ fun_l14_n46
+end
+
+def fun_l13_n459()
+ fun_l14_n57
+end
+
+def fun_l13_n460()
+ fun_l14_n428
+end
+
+def fun_l13_n461()
+ fun_l14_n773
+end
+
+def fun_l13_n462()
+ fun_l14_n712
+end
+
+def fun_l13_n463()
+ fun_l14_n624
+end
+
+def fun_l13_n464()
+ fun_l14_n103
+end
+
+def fun_l13_n465()
+ fun_l14_n962
+end
+
+def fun_l13_n466()
+ fun_l14_n424
+end
+
+def fun_l13_n467()
+ fun_l14_n780
+end
+
+def fun_l13_n468()
+ fun_l14_n852
+end
+
+def fun_l13_n469()
+ fun_l14_n175
+end
+
+def fun_l13_n470()
+ fun_l14_n900
+end
+
+def fun_l13_n471()
+ fun_l14_n866
+end
+
+def fun_l13_n472()
+ fun_l14_n541
+end
+
+def fun_l13_n473()
+ fun_l14_n966
+end
+
+def fun_l13_n474()
+ fun_l14_n107
+end
+
+def fun_l13_n475()
+ fun_l14_n917
+end
+
+def fun_l13_n476()
+ fun_l14_n683
+end
+
+def fun_l13_n477()
+ fun_l14_n625
+end
+
+def fun_l13_n478()
+ fun_l14_n439
+end
+
+def fun_l13_n479()
+ fun_l14_n69
+end
+
+def fun_l13_n480()
+ fun_l14_n252
+end
+
+def fun_l13_n481()
+ fun_l14_n753
+end
+
+def fun_l13_n482()
+ fun_l14_n50
+end
+
+def fun_l13_n483()
+ fun_l14_n634
+end
+
+def fun_l13_n484()
+ fun_l14_n908
+end
+
+def fun_l13_n485()
+ fun_l14_n733
+end
+
+def fun_l13_n486()
+ fun_l14_n450
+end
+
+def fun_l13_n487()
+ fun_l14_n373
+end
+
+def fun_l13_n488()
+ fun_l14_n226
+end
+
+def fun_l13_n489()
+ fun_l14_n320
+end
+
+def fun_l13_n490()
+ fun_l14_n498
+end
+
+def fun_l13_n491()
+ fun_l14_n49
+end
+
+def fun_l13_n492()
+ fun_l14_n46
+end
+
+def fun_l13_n493()
+ fun_l14_n993
+end
+
+def fun_l13_n494()
+ fun_l14_n123
+end
+
+def fun_l13_n495()
+ fun_l14_n393
+end
+
+def fun_l13_n496()
+ fun_l14_n500
+end
+
+def fun_l13_n497()
+ fun_l14_n328
+end
+
+def fun_l13_n498()
+ fun_l14_n711
+end
+
+def fun_l13_n499()
+ fun_l14_n734
+end
+
+def fun_l13_n500()
+ fun_l14_n354
+end
+
+def fun_l13_n501()
+ fun_l14_n565
+end
+
+def fun_l13_n502()
+ fun_l14_n699
+end
+
+def fun_l13_n503()
+ fun_l14_n157
+end
+
+def fun_l13_n504()
+ fun_l14_n634
+end
+
+def fun_l13_n505()
+ fun_l14_n282
+end
+
+def fun_l13_n506()
+ fun_l14_n484
+end
+
+def fun_l13_n507()
+ fun_l14_n972
+end
+
+def fun_l13_n508()
+ fun_l14_n763
+end
+
+def fun_l13_n509()
+ fun_l14_n530
+end
+
+def fun_l13_n510()
+ fun_l14_n88
+end
+
+def fun_l13_n511()
+ fun_l14_n718
+end
+
+def fun_l13_n512()
+ fun_l14_n988
+end
+
+def fun_l13_n513()
+ fun_l14_n266
+end
+
+def fun_l13_n514()
+ fun_l14_n489
+end
+
+def fun_l13_n515()
+ fun_l14_n662
+end
+
+def fun_l13_n516()
+ fun_l14_n821
+end
+
+def fun_l13_n517()
+ fun_l14_n697
+end
+
+def fun_l13_n518()
+ fun_l14_n984
+end
+
+def fun_l13_n519()
+ fun_l14_n847
+end
+
+def fun_l13_n520()
+ fun_l14_n916
+end
+
+def fun_l13_n521()
+ fun_l14_n304
+end
+
+def fun_l13_n522()
+ fun_l14_n778
+end
+
+def fun_l13_n523()
+ fun_l14_n105
+end
+
+def fun_l13_n524()
+ fun_l14_n272
+end
+
+def fun_l13_n525()
+ fun_l14_n814
+end
+
+def fun_l13_n526()
+ fun_l14_n689
+end
+
+def fun_l13_n527()
+ fun_l14_n314
+end
+
+def fun_l13_n528()
+ fun_l14_n483
+end
+
+def fun_l13_n529()
+ fun_l14_n571
+end
+
+def fun_l13_n530()
+ fun_l14_n162
+end
+
+def fun_l13_n531()
+ fun_l14_n737
+end
+
+def fun_l13_n532()
+ fun_l14_n886
+end
+
+def fun_l13_n533()
+ fun_l14_n638
+end
+
+def fun_l13_n534()
+ fun_l14_n765
+end
+
+def fun_l13_n535()
+ fun_l14_n452
+end
+
+def fun_l13_n536()
+ fun_l14_n367
+end
+
+def fun_l13_n537()
+ fun_l14_n245
+end
+
+def fun_l13_n538()
+ fun_l14_n590
+end
+
+def fun_l13_n539()
+ fun_l14_n383
+end
+
+def fun_l13_n540()
+ fun_l14_n210
+end
+
+def fun_l13_n541()
+ fun_l14_n25
+end
+
+def fun_l13_n542()
+ fun_l14_n612
+end
+
+def fun_l13_n543()
+ fun_l14_n639
+end
+
+def fun_l13_n544()
+ fun_l14_n540
+end
+
+def fun_l13_n545()
+ fun_l14_n538
+end
+
+def fun_l13_n546()
+ fun_l14_n323
+end
+
+def fun_l13_n547()
+ fun_l14_n556
+end
+
+def fun_l13_n548()
+ fun_l14_n219
+end
+
+def fun_l13_n549()
+ fun_l14_n583
+end
+
+def fun_l13_n550()
+ fun_l14_n818
+end
+
+def fun_l13_n551()
+ fun_l14_n167
+end
+
+def fun_l13_n552()
+ fun_l14_n310
+end
+
+def fun_l13_n553()
+ fun_l14_n528
+end
+
+def fun_l13_n554()
+ fun_l14_n604
+end
+
+def fun_l13_n555()
+ fun_l14_n426
+end
+
+def fun_l13_n556()
+ fun_l14_n398
+end
+
+def fun_l13_n557()
+ fun_l14_n885
+end
+
+def fun_l13_n558()
+ fun_l14_n905
+end
+
+def fun_l13_n559()
+ fun_l14_n882
+end
+
+def fun_l13_n560()
+ fun_l14_n536
+end
+
+def fun_l13_n561()
+ fun_l14_n392
+end
+
+def fun_l13_n562()
+ fun_l14_n948
+end
+
+def fun_l13_n563()
+ fun_l14_n522
+end
+
+def fun_l13_n564()
+ fun_l14_n704
+end
+
+def fun_l13_n565()
+ fun_l14_n365
+end
+
+def fun_l13_n566()
+ fun_l14_n925
+end
+
+def fun_l13_n567()
+ fun_l14_n353
+end
+
+def fun_l13_n568()
+ fun_l14_n215
+end
+
+def fun_l13_n569()
+ fun_l14_n932
+end
+
+def fun_l13_n570()
+ fun_l14_n458
+end
+
+def fun_l13_n571()
+ fun_l14_n793
+end
+
+def fun_l13_n572()
+ fun_l14_n650
+end
+
+def fun_l13_n573()
+ fun_l14_n888
+end
+
+def fun_l13_n574()
+ fun_l14_n986
+end
+
+def fun_l13_n575()
+ fun_l14_n834
+end
+
+def fun_l13_n576()
+ fun_l14_n253
+end
+
+def fun_l13_n577()
+ fun_l14_n382
+end
+
+def fun_l13_n578()
+ fun_l14_n300
+end
+
+def fun_l13_n579()
+ fun_l14_n457
+end
+
+def fun_l13_n580()
+ fun_l14_n398
+end
+
+def fun_l13_n581()
+ fun_l14_n93
+end
+
+def fun_l13_n582()
+ fun_l14_n226
+end
+
+def fun_l13_n583()
+ fun_l14_n665
+end
+
+def fun_l13_n584()
+ fun_l14_n354
+end
+
+def fun_l13_n585()
+ fun_l14_n460
+end
+
+def fun_l13_n586()
+ fun_l14_n185
+end
+
+def fun_l13_n587()
+ fun_l14_n577
+end
+
+def fun_l13_n588()
+ fun_l14_n180
+end
+
+def fun_l13_n589()
+ fun_l14_n769
+end
+
+def fun_l13_n590()
+ fun_l14_n78
+end
+
+def fun_l13_n591()
+ fun_l14_n455
+end
+
+def fun_l13_n592()
+ fun_l14_n862
+end
+
+def fun_l13_n593()
+ fun_l14_n471
+end
+
+def fun_l13_n594()
+ fun_l14_n931
+end
+
+def fun_l13_n595()
+ fun_l14_n255
+end
+
+def fun_l13_n596()
+ fun_l14_n261
+end
+
+def fun_l13_n597()
+ fun_l14_n586
+end
+
+def fun_l13_n598()
+ fun_l14_n45
+end
+
+def fun_l13_n599()
+ fun_l14_n892
+end
+
+def fun_l13_n600()
+ fun_l14_n615
+end
+
+def fun_l13_n601()
+ fun_l14_n910
+end
+
+def fun_l13_n602()
+ fun_l14_n888
+end
+
+def fun_l13_n603()
+ fun_l14_n827
+end
+
+def fun_l13_n604()
+ fun_l14_n765
+end
+
+def fun_l13_n605()
+ fun_l14_n118
+end
+
+def fun_l13_n606()
+ fun_l14_n895
+end
+
+def fun_l13_n607()
+ fun_l14_n183
+end
+
+def fun_l13_n608()
+ fun_l14_n200
+end
+
+def fun_l13_n609()
+ fun_l14_n873
+end
+
+def fun_l13_n610()
+ fun_l14_n402
+end
+
+def fun_l13_n611()
+ fun_l14_n414
+end
+
+def fun_l13_n612()
+ fun_l14_n492
+end
+
+def fun_l13_n613()
+ fun_l14_n811
+end
+
+def fun_l13_n614()
+ fun_l14_n814
+end
+
+def fun_l13_n615()
+ fun_l14_n95
+end
+
+def fun_l13_n616()
+ fun_l14_n782
+end
+
+def fun_l13_n617()
+ fun_l14_n329
+end
+
+def fun_l13_n618()
+ fun_l14_n180
+end
+
+def fun_l13_n619()
+ fun_l14_n104
+end
+
+def fun_l13_n620()
+ fun_l14_n341
+end
+
+def fun_l13_n621()
+ fun_l14_n132
+end
+
+def fun_l13_n622()
+ fun_l14_n815
+end
+
+def fun_l13_n623()
+ fun_l14_n785
+end
+
+def fun_l13_n624()
+ fun_l14_n934
+end
+
+def fun_l13_n625()
+ fun_l14_n760
+end
+
+def fun_l13_n626()
+ fun_l14_n307
+end
+
+def fun_l13_n627()
+ fun_l14_n433
+end
+
+def fun_l13_n628()
+ fun_l14_n156
+end
+
+def fun_l13_n629()
+ fun_l14_n95
+end
+
+def fun_l13_n630()
+ fun_l14_n44
+end
+
+def fun_l13_n631()
+ fun_l14_n643
+end
+
+def fun_l13_n632()
+ fun_l14_n876
+end
+
+def fun_l13_n633()
+ fun_l14_n477
+end
+
+def fun_l13_n634()
+ fun_l14_n549
+end
+
+def fun_l13_n635()
+ fun_l14_n795
+end
+
+def fun_l13_n636()
+ fun_l14_n814
+end
+
+def fun_l13_n637()
+ fun_l14_n52
+end
+
+def fun_l13_n638()
+ fun_l14_n542
+end
+
+def fun_l13_n639()
+ fun_l14_n204
+end
+
+def fun_l13_n640()
+ fun_l14_n256
+end
+
+def fun_l13_n641()
+ fun_l14_n198
+end
+
+def fun_l13_n642()
+ fun_l14_n221
+end
+
+def fun_l13_n643()
+ fun_l14_n855
+end
+
+def fun_l13_n644()
+ fun_l14_n978
+end
+
+def fun_l13_n645()
+ fun_l14_n954
+end
+
+def fun_l13_n646()
+ fun_l14_n148
+end
+
+def fun_l13_n647()
+ fun_l14_n528
+end
+
+def fun_l13_n648()
+ fun_l14_n807
+end
+
+def fun_l13_n649()
+ fun_l14_n735
+end
+
+def fun_l13_n650()
+ fun_l14_n518
+end
+
+def fun_l13_n651()
+ fun_l14_n255
+end
+
+def fun_l13_n652()
+ fun_l14_n251
+end
+
+def fun_l13_n653()
+ fun_l14_n311
+end
+
+def fun_l13_n654()
+ fun_l14_n134
+end
+
+def fun_l13_n655()
+ fun_l14_n474
+end
+
+def fun_l13_n656()
+ fun_l14_n857
+end
+
+def fun_l13_n657()
+ fun_l14_n758
+end
+
+def fun_l13_n658()
+ fun_l14_n310
+end
+
+def fun_l13_n659()
+ fun_l14_n846
+end
+
+def fun_l13_n660()
+ fun_l14_n220
+end
+
+def fun_l13_n661()
+ fun_l14_n81
+end
+
+def fun_l13_n662()
+ fun_l14_n958
+end
+
+def fun_l13_n663()
+ fun_l14_n221
+end
+
+def fun_l13_n664()
+ fun_l14_n107
+end
+
+def fun_l13_n665()
+ fun_l14_n131
+end
+
+def fun_l13_n666()
+ fun_l14_n750
+end
+
+def fun_l13_n667()
+ fun_l14_n455
+end
+
+def fun_l13_n668()
+ fun_l14_n354
+end
+
+def fun_l13_n669()
+ fun_l14_n76
+end
+
+def fun_l13_n670()
+ fun_l14_n111
+end
+
+def fun_l13_n671()
+ fun_l14_n411
+end
+
+def fun_l13_n672()
+ fun_l14_n400
+end
+
+def fun_l13_n673()
+ fun_l14_n407
+end
+
+def fun_l13_n674()
+ fun_l14_n851
+end
+
+def fun_l13_n675()
+ fun_l14_n521
+end
+
+def fun_l13_n676()
+ fun_l14_n448
+end
+
+def fun_l13_n677()
+ fun_l14_n615
+end
+
+def fun_l13_n678()
+ fun_l14_n574
+end
+
+def fun_l13_n679()
+ fun_l14_n300
+end
+
+def fun_l13_n680()
+ fun_l14_n783
+end
+
+def fun_l13_n681()
+ fun_l14_n172
+end
+
+def fun_l13_n682()
+ fun_l14_n725
+end
+
+def fun_l13_n683()
+ fun_l14_n657
+end
+
+def fun_l13_n684()
+ fun_l14_n550
+end
+
+def fun_l13_n685()
+ fun_l14_n976
+end
+
+def fun_l13_n686()
+ fun_l14_n77
+end
+
+def fun_l13_n687()
+ fun_l14_n472
+end
+
+def fun_l13_n688()
+ fun_l14_n300
+end
+
+def fun_l13_n689()
+ fun_l14_n139
+end
+
+def fun_l13_n690()
+ fun_l14_n623
+end
+
+def fun_l13_n691()
+ fun_l14_n336
+end
+
+def fun_l13_n692()
+ fun_l14_n502
+end
+
+def fun_l13_n693()
+ fun_l14_n184
+end
+
+def fun_l13_n694()
+ fun_l14_n745
+end
+
+def fun_l13_n695()
+ fun_l14_n27
+end
+
+def fun_l13_n696()
+ fun_l14_n299
+end
+
+def fun_l13_n697()
+ fun_l14_n7
+end
+
+def fun_l13_n698()
+ fun_l14_n842
+end
+
+def fun_l13_n699()
+ fun_l14_n592
+end
+
+def fun_l13_n700()
+ fun_l14_n993
+end
+
+def fun_l13_n701()
+ fun_l14_n113
+end
+
+def fun_l13_n702()
+ fun_l14_n997
+end
+
+def fun_l13_n703()
+ fun_l14_n740
+end
+
+def fun_l13_n704()
+ fun_l14_n261
+end
+
+def fun_l13_n705()
+ fun_l14_n737
+end
+
+def fun_l13_n706()
+ fun_l14_n216
+end
+
+def fun_l13_n707()
+ fun_l14_n607
+end
+
+def fun_l13_n708()
+ fun_l14_n520
+end
+
+def fun_l13_n709()
+ fun_l14_n133
+end
+
+def fun_l13_n710()
+ fun_l14_n615
+end
+
+def fun_l13_n711()
+ fun_l14_n476
+end
+
+def fun_l13_n712()
+ fun_l14_n154
+end
+
+def fun_l13_n713()
+ fun_l14_n947
+end
+
+def fun_l13_n714()
+ fun_l14_n893
+end
+
+def fun_l13_n715()
+ fun_l14_n296
+end
+
+def fun_l13_n716()
+ fun_l14_n275
+end
+
+def fun_l13_n717()
+ fun_l14_n622
+end
+
+def fun_l13_n718()
+ fun_l14_n561
+end
+
+def fun_l13_n719()
+ fun_l14_n216
+end
+
+def fun_l13_n720()
+ fun_l14_n459
+end
+
+def fun_l13_n721()
+ fun_l14_n329
+end
+
+def fun_l13_n722()
+ fun_l14_n901
+end
+
+def fun_l13_n723()
+ fun_l14_n824
+end
+
+def fun_l13_n724()
+ fun_l14_n359
+end
+
+def fun_l13_n725()
+ fun_l14_n399
+end
+
+def fun_l13_n726()
+ fun_l14_n998
+end
+
+def fun_l13_n727()
+ fun_l14_n327
+end
+
+def fun_l13_n728()
+ fun_l14_n659
+end
+
+def fun_l13_n729()
+ fun_l14_n564
+end
+
+def fun_l13_n730()
+ fun_l14_n718
+end
+
+def fun_l13_n731()
+ fun_l14_n751
+end
+
+def fun_l13_n732()
+ fun_l14_n172
+end
+
+def fun_l13_n733()
+ fun_l14_n289
+end
+
+def fun_l13_n734()
+ fun_l14_n956
+end
+
+def fun_l13_n735()
+ fun_l14_n375
+end
+
+def fun_l13_n736()
+ fun_l14_n459
+end
+
+def fun_l13_n737()
+ fun_l14_n471
+end
+
+def fun_l13_n738()
+ fun_l14_n957
+end
+
+def fun_l13_n739()
+ fun_l14_n670
+end
+
+def fun_l13_n740()
+ fun_l14_n396
+end
+
+def fun_l13_n741()
+ fun_l14_n909
+end
+
+def fun_l13_n742()
+ fun_l14_n226
+end
+
+def fun_l13_n743()
+ fun_l14_n458
+end
+
+def fun_l13_n744()
+ fun_l14_n923
+end
+
+def fun_l13_n745()
+ fun_l14_n255
+end
+
+def fun_l13_n746()
+ fun_l14_n2
+end
+
+def fun_l13_n747()
+ fun_l14_n805
+end
+
+def fun_l13_n748()
+ fun_l14_n157
+end
+
+def fun_l13_n749()
+ fun_l14_n952
+end
+
+def fun_l13_n750()
+ fun_l14_n902
+end
+
+def fun_l13_n751()
+ fun_l14_n723
+end
+
+def fun_l13_n752()
+ fun_l14_n204
+end
+
+def fun_l13_n753()
+ fun_l14_n53
+end
+
+def fun_l13_n754()
+ fun_l14_n240
+end
+
+def fun_l13_n755()
+ fun_l14_n161
+end
+
+def fun_l13_n756()
+ fun_l14_n735
+end
+
+def fun_l13_n757()
+ fun_l14_n298
+end
+
+def fun_l13_n758()
+ fun_l14_n743
+end
+
+def fun_l13_n759()
+ fun_l14_n886
+end
+
+def fun_l13_n760()
+ fun_l14_n559
+end
+
+def fun_l13_n761()
+ fun_l14_n42
+end
+
+def fun_l13_n762()
+ fun_l14_n86
+end
+
+def fun_l13_n763()
+ fun_l14_n138
+end
+
+def fun_l13_n764()
+ fun_l14_n477
+end
+
+def fun_l13_n765()
+ fun_l14_n763
+end
+
+def fun_l13_n766()
+ fun_l14_n360
+end
+
+def fun_l13_n767()
+ fun_l14_n486
+end
+
+def fun_l13_n768()
+ fun_l14_n734
+end
+
+def fun_l13_n769()
+ fun_l14_n442
+end
+
+def fun_l13_n770()
+ fun_l14_n512
+end
+
+def fun_l13_n771()
+ fun_l14_n399
+end
+
+def fun_l13_n772()
+ fun_l14_n88
+end
+
+def fun_l13_n773()
+ fun_l14_n55
+end
+
+def fun_l13_n774()
+ fun_l14_n138
+end
+
+def fun_l13_n775()
+ fun_l14_n104
+end
+
+def fun_l13_n776()
+ fun_l14_n901
+end
+
+def fun_l13_n777()
+ fun_l14_n7
+end
+
+def fun_l13_n778()
+ fun_l14_n72
+end
+
+def fun_l13_n779()
+ fun_l14_n588
+end
+
+def fun_l13_n780()
+ fun_l14_n266
+end
+
+def fun_l13_n781()
+ fun_l14_n428
+end
+
+def fun_l13_n782()
+ fun_l14_n802
+end
+
+def fun_l13_n783()
+ fun_l14_n59
+end
+
+def fun_l13_n784()
+ fun_l14_n734
+end
+
+def fun_l13_n785()
+ fun_l14_n674
+end
+
+def fun_l13_n786()
+ fun_l14_n126
+end
+
+def fun_l13_n787()
+ fun_l14_n199
+end
+
+def fun_l13_n788()
+ fun_l14_n695
+end
+
+def fun_l13_n789()
+ fun_l14_n332
+end
+
+def fun_l13_n790()
+ fun_l14_n734
+end
+
+def fun_l13_n791()
+ fun_l14_n856
+end
+
+def fun_l13_n792()
+ fun_l14_n447
+end
+
+def fun_l13_n793()
+ fun_l14_n931
+end
+
+def fun_l13_n794()
+ fun_l14_n608
+end
+
+def fun_l13_n795()
+ fun_l14_n131
+end
+
+def fun_l13_n796()
+ fun_l14_n961
+end
+
+def fun_l13_n797()
+ fun_l14_n109
+end
+
+def fun_l13_n798()
+ fun_l14_n766
+end
+
+def fun_l13_n799()
+ fun_l14_n149
+end
+
+def fun_l13_n800()
+ fun_l14_n44
+end
+
+def fun_l13_n801()
+ fun_l14_n893
+end
+
+def fun_l13_n802()
+ fun_l14_n826
+end
+
+def fun_l13_n803()
+ fun_l14_n372
+end
+
+def fun_l13_n804()
+ fun_l14_n7
+end
+
+def fun_l13_n805()
+ fun_l14_n655
+end
+
+def fun_l13_n806()
+ fun_l14_n418
+end
+
+def fun_l13_n807()
+ fun_l14_n746
+end
+
+def fun_l13_n808()
+ fun_l14_n810
+end
+
+def fun_l13_n809()
+ fun_l14_n838
+end
+
+def fun_l13_n810()
+ fun_l14_n522
+end
+
+def fun_l13_n811()
+ fun_l14_n723
+end
+
+def fun_l13_n812()
+ fun_l14_n476
+end
+
+def fun_l13_n813()
+ fun_l14_n760
+end
+
+def fun_l13_n814()
+ fun_l14_n728
+end
+
+def fun_l13_n815()
+ fun_l14_n926
+end
+
+def fun_l13_n816()
+ fun_l14_n16
+end
+
+def fun_l13_n817()
+ fun_l14_n888
+end
+
+def fun_l13_n818()
+ fun_l14_n812
+end
+
+def fun_l13_n819()
+ fun_l14_n430
+end
+
+def fun_l13_n820()
+ fun_l14_n211
+end
+
+def fun_l13_n821()
+ fun_l14_n204
+end
+
+def fun_l13_n822()
+ fun_l14_n868
+end
+
+def fun_l13_n823()
+ fun_l14_n460
+end
+
+def fun_l13_n824()
+ fun_l14_n597
+end
+
+def fun_l13_n825()
+ fun_l14_n217
+end
+
+def fun_l13_n826()
+ fun_l14_n425
+end
+
+def fun_l13_n827()
+ fun_l14_n216
+end
+
+def fun_l13_n828()
+ fun_l14_n931
+end
+
+def fun_l13_n829()
+ fun_l14_n3
+end
+
+def fun_l13_n830()
+ fun_l14_n55
+end
+
+def fun_l13_n831()
+ fun_l14_n362
+end
+
+def fun_l13_n832()
+ fun_l14_n591
+end
+
+def fun_l13_n833()
+ fun_l14_n339
+end
+
+def fun_l13_n834()
+ fun_l14_n641
+end
+
+def fun_l13_n835()
+ fun_l14_n389
+end
+
+def fun_l13_n836()
+ fun_l14_n668
+end
+
+def fun_l13_n837()
+ fun_l14_n845
+end
+
+def fun_l13_n838()
+ fun_l14_n202
+end
+
+def fun_l13_n839()
+ fun_l14_n575
+end
+
+def fun_l13_n840()
+ fun_l14_n357
+end
+
+def fun_l13_n841()
+ fun_l14_n271
+end
+
+def fun_l13_n842()
+ fun_l14_n876
+end
+
+def fun_l13_n843()
+ fun_l14_n983
+end
+
+def fun_l13_n844()
+ fun_l14_n512
+end
+
+def fun_l13_n845()
+ fun_l14_n205
+end
+
+def fun_l13_n846()
+ fun_l14_n463
+end
+
+def fun_l13_n847()
+ fun_l14_n422
+end
+
+def fun_l13_n848()
+ fun_l14_n54
+end
+
+def fun_l13_n849()
+ fun_l14_n575
+end
+
+def fun_l13_n850()
+ fun_l14_n187
+end
+
+def fun_l13_n851()
+ fun_l14_n151
+end
+
+def fun_l13_n852()
+ fun_l14_n176
+end
+
+def fun_l13_n853()
+ fun_l14_n501
+end
+
+def fun_l13_n854()
+ fun_l14_n390
+end
+
+def fun_l13_n855()
+ fun_l14_n902
+end
+
+def fun_l13_n856()
+ fun_l14_n354
+end
+
+def fun_l13_n857()
+ fun_l14_n245
+end
+
+def fun_l13_n858()
+ fun_l14_n299
+end
+
+def fun_l13_n859()
+ fun_l14_n532
+end
+
+def fun_l13_n860()
+ fun_l14_n263
+end
+
+def fun_l13_n861()
+ fun_l14_n811
+end
+
+def fun_l13_n862()
+ fun_l14_n298
+end
+
+def fun_l13_n863()
+ fun_l14_n635
+end
+
+def fun_l13_n864()
+ fun_l14_n913
+end
+
+def fun_l13_n865()
+ fun_l14_n901
+end
+
+def fun_l13_n866()
+ fun_l14_n380
+end
+
+def fun_l13_n867()
+ fun_l14_n9
+end
+
+def fun_l13_n868()
+ fun_l14_n982
+end
+
+def fun_l13_n869()
+ fun_l14_n703
+end
+
+def fun_l13_n870()
+ fun_l14_n272
+end
+
+def fun_l13_n871()
+ fun_l14_n209
+end
+
+def fun_l13_n872()
+ fun_l14_n429
+end
+
+def fun_l13_n873()
+ fun_l14_n108
+end
+
+def fun_l13_n874()
+ fun_l14_n116
+end
+
+def fun_l13_n875()
+ fun_l14_n169
+end
+
+def fun_l13_n876()
+ fun_l14_n642
+end
+
+def fun_l13_n877()
+ fun_l14_n265
+end
+
+def fun_l13_n878()
+ fun_l14_n227
+end
+
+def fun_l13_n879()
+ fun_l14_n202
+end
+
+def fun_l13_n880()
+ fun_l14_n336
+end
+
+def fun_l13_n881()
+ fun_l14_n856
+end
+
+def fun_l13_n882()
+ fun_l14_n821
+end
+
+def fun_l13_n883()
+ fun_l14_n275
+end
+
+def fun_l13_n884()
+ fun_l14_n903
+end
+
+def fun_l13_n885()
+ fun_l14_n407
+end
+
+def fun_l13_n886()
+ fun_l14_n129
+end
+
+def fun_l13_n887()
+ fun_l14_n68
+end
+
+def fun_l13_n888()
+ fun_l14_n124
+end
+
+def fun_l13_n889()
+ fun_l14_n936
+end
+
+def fun_l13_n890()
+ fun_l14_n401
+end
+
+def fun_l13_n891()
+ fun_l14_n574
+end
+
+def fun_l13_n892()
+ fun_l14_n593
+end
+
+def fun_l13_n893()
+ fun_l14_n262
+end
+
+def fun_l13_n894()
+ fun_l14_n215
+end
+
+def fun_l13_n895()
+ fun_l14_n49
+end
+
+def fun_l13_n896()
+ fun_l14_n767
+end
+
+def fun_l13_n897()
+ fun_l14_n280
+end
+
+def fun_l13_n898()
+ fun_l14_n112
+end
+
+def fun_l13_n899()
+ fun_l14_n202
+end
+
+def fun_l13_n900()
+ fun_l14_n73
+end
+
+def fun_l13_n901()
+ fun_l14_n798
+end
+
+def fun_l13_n902()
+ fun_l14_n827
+end
+
+def fun_l13_n903()
+ fun_l14_n824
+end
+
+def fun_l13_n904()
+ fun_l14_n414
+end
+
+def fun_l13_n905()
+ fun_l14_n502
+end
+
+def fun_l13_n906()
+ fun_l14_n323
+end
+
+def fun_l13_n907()
+ fun_l14_n216
+end
+
+def fun_l13_n908()
+ fun_l14_n173
+end
+
+def fun_l13_n909()
+ fun_l14_n26
+end
+
+def fun_l13_n910()
+ fun_l14_n40
+end
+
+def fun_l13_n911()
+ fun_l14_n883
+end
+
+def fun_l13_n912()
+ fun_l14_n523
+end
+
+def fun_l13_n913()
+ fun_l14_n979
+end
+
+def fun_l13_n914()
+ fun_l14_n921
+end
+
+def fun_l13_n915()
+ fun_l14_n842
+end
+
+def fun_l13_n916()
+ fun_l14_n943
+end
+
+def fun_l13_n917()
+ fun_l14_n97
+end
+
+def fun_l13_n918()
+ fun_l14_n515
+end
+
+def fun_l13_n919()
+ fun_l14_n145
+end
+
+def fun_l13_n920()
+ fun_l14_n497
+end
+
+def fun_l13_n921()
+ fun_l14_n264
+end
+
+def fun_l13_n922()
+ fun_l14_n901
+end
+
+def fun_l13_n923()
+ fun_l14_n436
+end
+
+def fun_l13_n924()
+ fun_l14_n315
+end
+
+def fun_l13_n925()
+ fun_l14_n512
+end
+
+def fun_l13_n926()
+ fun_l14_n611
+end
+
+def fun_l13_n927()
+ fun_l14_n103
+end
+
+def fun_l13_n928()
+ fun_l14_n149
+end
+
+def fun_l13_n929()
+ fun_l14_n407
+end
+
+def fun_l13_n930()
+ fun_l14_n380
+end
+
+def fun_l13_n931()
+ fun_l14_n429
+end
+
+def fun_l13_n932()
+ fun_l14_n870
+end
+
+def fun_l13_n933()
+ fun_l14_n274
+end
+
+def fun_l13_n934()
+ fun_l14_n57
+end
+
+def fun_l13_n935()
+ fun_l14_n718
+end
+
+def fun_l13_n936()
+ fun_l14_n571
+end
+
+def fun_l13_n937()
+ fun_l14_n447
+end
+
+def fun_l13_n938()
+ fun_l14_n742
+end
+
+def fun_l13_n939()
+ fun_l14_n811
+end
+
+def fun_l13_n940()
+ fun_l14_n148
+end
+
+def fun_l13_n941()
+ fun_l14_n795
+end
+
+def fun_l13_n942()
+ fun_l14_n807
+end
+
+def fun_l13_n943()
+ fun_l14_n279
+end
+
+def fun_l13_n944()
+ fun_l14_n939
+end
+
+def fun_l13_n945()
+ fun_l14_n435
+end
+
+def fun_l13_n946()
+ fun_l14_n937
+end
+
+def fun_l13_n947()
+ fun_l14_n543
+end
+
+def fun_l13_n948()
+ fun_l14_n374
+end
+
+def fun_l13_n949()
+ fun_l14_n707
+end
+
+def fun_l13_n950()
+ fun_l14_n866
+end
+
+def fun_l13_n951()
+ fun_l14_n67
+end
+
+def fun_l13_n952()
+ fun_l14_n752
+end
+
+def fun_l13_n953()
+ fun_l14_n113
+end
+
+def fun_l13_n954()
+ fun_l14_n358
+end
+
+def fun_l13_n955()
+ fun_l14_n432
+end
+
+def fun_l13_n956()
+ fun_l14_n132
+end
+
+def fun_l13_n957()
+ fun_l14_n807
+end
+
+def fun_l13_n958()
+ fun_l14_n293
+end
+
+def fun_l13_n959()
+ fun_l14_n681
+end
+
+def fun_l13_n960()
+ fun_l14_n335
+end
+
+def fun_l13_n961()
+ fun_l14_n285
+end
+
+def fun_l13_n962()
+ fun_l14_n366
+end
+
+def fun_l13_n963()
+ fun_l14_n674
+end
+
+def fun_l13_n964()
+ fun_l14_n914
+end
+
+def fun_l13_n965()
+ fun_l14_n776
+end
+
+def fun_l13_n966()
+ fun_l14_n297
+end
+
+def fun_l13_n967()
+ fun_l14_n623
+end
+
+def fun_l13_n968()
+ fun_l14_n357
+end
+
+def fun_l13_n969()
+ fun_l14_n430
+end
+
+def fun_l13_n970()
+ fun_l14_n201
+end
+
+def fun_l13_n971()
+ fun_l14_n482
+end
+
+def fun_l13_n972()
+ fun_l14_n363
+end
+
+def fun_l13_n973()
+ fun_l14_n530
+end
+
+def fun_l13_n974()
+ fun_l14_n892
+end
+
+def fun_l13_n975()
+ fun_l14_n548
+end
+
+def fun_l13_n976()
+ fun_l14_n257
+end
+
+def fun_l13_n977()
+ fun_l14_n449
+end
+
+def fun_l13_n978()
+ fun_l14_n346
+end
+
+def fun_l13_n979()
+ fun_l14_n448
+end
+
+def fun_l13_n980()
+ fun_l14_n912
+end
+
+def fun_l13_n981()
+ fun_l14_n358
+end
+
+def fun_l13_n982()
+ fun_l14_n55
+end
+
+def fun_l13_n983()
+ fun_l14_n712
+end
+
+def fun_l13_n984()
+ fun_l14_n179
+end
+
+def fun_l13_n985()
+ fun_l14_n749
+end
+
+def fun_l13_n986()
+ fun_l14_n469
+end
+
+def fun_l13_n987()
+ fun_l14_n557
+end
+
+def fun_l13_n988()
+ fun_l14_n383
+end
+
+def fun_l13_n989()
+ fun_l14_n929
+end
+
+def fun_l13_n990()
+ fun_l14_n659
+end
+
+def fun_l13_n991()
+ fun_l14_n285
+end
+
+def fun_l13_n992()
+ fun_l14_n779
+end
+
+def fun_l13_n993()
+ fun_l14_n235
+end
+
+def fun_l13_n994()
+ fun_l14_n756
+end
+
+def fun_l13_n995()
+ fun_l14_n249
+end
+
+def fun_l13_n996()
+ fun_l14_n8
+end
+
+def fun_l13_n997()
+ fun_l14_n785
+end
+
+def fun_l13_n998()
+ fun_l14_n945
+end
+
+def fun_l13_n999()
+ fun_l14_n410
+end
+
+def fun_l14_n0()
+ fun_l15_n85
+end
+
+def fun_l14_n1()
+ fun_l15_n932
+end
+
+def fun_l14_n2()
+ fun_l15_n422
+end
+
+def fun_l14_n3()
+ fun_l15_n439
+end
+
+def fun_l14_n4()
+ fun_l15_n186
+end
+
+def fun_l14_n5()
+ fun_l15_n914
+end
+
+def fun_l14_n6()
+ fun_l15_n830
+end
+
+def fun_l14_n7()
+ fun_l15_n384
+end
+
+def fun_l14_n8()
+ fun_l15_n200
+end
+
+def fun_l14_n9()
+ fun_l15_n72
+end
+
+def fun_l14_n10()
+ fun_l15_n498
+end
+
+def fun_l14_n11()
+ fun_l15_n247
+end
+
+def fun_l14_n12()
+ fun_l15_n432
+end
+
+def fun_l14_n13()
+ fun_l15_n718
+end
+
+def fun_l14_n14()
+ fun_l15_n568
+end
+
+def fun_l14_n15()
+ fun_l15_n971
+end
+
+def fun_l14_n16()
+ fun_l15_n545
+end
+
+def fun_l14_n17()
+ fun_l15_n441
+end
+
+def fun_l14_n18()
+ fun_l15_n532
+end
+
+def fun_l14_n19()
+ fun_l15_n484
+end
+
+def fun_l14_n20()
+ fun_l15_n659
+end
+
+def fun_l14_n21()
+ fun_l15_n494
+end
+
+def fun_l14_n22()
+ fun_l15_n379
+end
+
+def fun_l14_n23()
+ fun_l15_n180
+end
+
+def fun_l14_n24()
+ fun_l15_n955
+end
+
+def fun_l14_n25()
+ fun_l15_n536
+end
+
+def fun_l14_n26()
+ fun_l15_n940
+end
+
+def fun_l14_n27()
+ fun_l15_n3
+end
+
+def fun_l14_n28()
+ fun_l15_n520
+end
+
+def fun_l14_n29()
+ fun_l15_n478
+end
+
+def fun_l14_n30()
+ fun_l15_n865
+end
+
+def fun_l14_n31()
+ fun_l15_n330
+end
+
+def fun_l14_n32()
+ fun_l15_n217
+end
+
+def fun_l14_n33()
+ fun_l15_n381
+end
+
+def fun_l14_n34()
+ fun_l15_n88
+end
+
+def fun_l14_n35()
+ fun_l15_n111
+end
+
+def fun_l14_n36()
+ fun_l15_n181
+end
+
+def fun_l14_n37()
+ fun_l15_n978
+end
+
+def fun_l14_n38()
+ fun_l15_n596
+end
+
+def fun_l14_n39()
+ fun_l15_n764
+end
+
+def fun_l14_n40()
+ fun_l15_n779
+end
+
+def fun_l14_n41()
+ fun_l15_n994
+end
+
+def fun_l14_n42()
+ fun_l15_n90
+end
+
+def fun_l14_n43()
+ fun_l15_n329
+end
+
+def fun_l14_n44()
+ fun_l15_n684
+end
+
+def fun_l14_n45()
+ fun_l15_n191
+end
+
+def fun_l14_n46()
+ fun_l15_n282
+end
+
+def fun_l14_n47()
+ fun_l15_n915
+end
+
+def fun_l14_n48()
+ fun_l15_n330
+end
+
+def fun_l14_n49()
+ fun_l15_n136
+end
+
+def fun_l14_n50()
+ fun_l15_n167
+end
+
+def fun_l14_n51()
+ fun_l15_n418
+end
+
+def fun_l14_n52()
+ fun_l15_n822
+end
+
+def fun_l14_n53()
+ fun_l15_n557
+end
+
+def fun_l14_n54()
+ fun_l15_n155
+end
+
+def fun_l14_n55()
+ fun_l15_n629
+end
+
+def fun_l14_n56()
+ fun_l15_n694
+end
+
+def fun_l14_n57()
+ fun_l15_n577
+end
+
+def fun_l14_n58()
+ fun_l15_n412
+end
+
+def fun_l14_n59()
+ fun_l15_n618
+end
+
+def fun_l14_n60()
+ fun_l15_n873
+end
+
+def fun_l14_n61()
+ fun_l15_n758
+end
+
+def fun_l14_n62()
+ fun_l15_n820
+end
+
+def fun_l14_n63()
+ fun_l15_n89
+end
+
+def fun_l14_n64()
+ fun_l15_n788
+end
+
+def fun_l14_n65()
+ fun_l15_n390
+end
+
+def fun_l14_n66()
+ fun_l15_n177
+end
+
+def fun_l14_n67()
+ fun_l15_n972
+end
+
+def fun_l14_n68()
+ fun_l15_n124
+end
+
+def fun_l14_n69()
+ fun_l15_n426
+end
+
+def fun_l14_n70()
+ fun_l15_n490
+end
+
+def fun_l14_n71()
+ fun_l15_n963
+end
+
+def fun_l14_n72()
+ fun_l15_n960
+end
+
+def fun_l14_n73()
+ fun_l15_n111
+end
+
+def fun_l14_n74()
+ fun_l15_n535
+end
+
+def fun_l14_n75()
+ fun_l15_n936
+end
+
+def fun_l14_n76()
+ fun_l15_n17
+end
+
+def fun_l14_n77()
+ fun_l15_n732
+end
+
+def fun_l14_n78()
+ fun_l15_n905
+end
+
+def fun_l14_n79()
+ fun_l15_n658
+end
+
+def fun_l14_n80()
+ fun_l15_n869
+end
+
+def fun_l14_n81()
+ fun_l15_n966
+end
+
+def fun_l14_n82()
+ fun_l15_n413
+end
+
+def fun_l14_n83()
+ fun_l15_n360
+end
+
+def fun_l14_n84()
+ fun_l15_n955
+end
+
+def fun_l14_n85()
+ fun_l15_n612
+end
+
+def fun_l14_n86()
+ fun_l15_n665
+end
+
+def fun_l14_n87()
+ fun_l15_n570
+end
+
+def fun_l14_n88()
+ fun_l15_n381
+end
+
+def fun_l14_n89()
+ fun_l15_n169
+end
+
+def fun_l14_n90()
+ fun_l15_n33
+end
+
+def fun_l14_n91()
+ fun_l15_n574
+end
+
+def fun_l14_n92()
+ fun_l15_n826
+end
+
+def fun_l14_n93()
+ fun_l15_n183
+end
+
+def fun_l14_n94()
+ fun_l15_n878
+end
+
+def fun_l14_n95()
+ fun_l15_n898
+end
+
+def fun_l14_n96()
+ fun_l15_n296
+end
+
+def fun_l14_n97()
+ fun_l15_n769
+end
+
+def fun_l14_n98()
+ fun_l15_n41
+end
+
+def fun_l14_n99()
+ fun_l15_n644
+end
+
+def fun_l14_n100()
+ fun_l15_n218
+end
+
+def fun_l14_n101()
+ fun_l15_n267
+end
+
+def fun_l14_n102()
+ fun_l15_n846
+end
+
+def fun_l14_n103()
+ fun_l15_n409
+end
+
+def fun_l14_n104()
+ fun_l15_n776
+end
+
+def fun_l14_n105()
+ fun_l15_n224
+end
+
+def fun_l14_n106()
+ fun_l15_n401
+end
+
+def fun_l14_n107()
+ fun_l15_n726
+end
+
+def fun_l14_n108()
+ fun_l15_n624
+end
+
+def fun_l14_n109()
+ fun_l15_n319
+end
+
+def fun_l14_n110()
+ fun_l15_n180
+end
+
+def fun_l14_n111()
+ fun_l15_n370
+end
+
+def fun_l14_n112()
+ fun_l15_n834
+end
+
+def fun_l14_n113()
+ fun_l15_n397
+end
+
+def fun_l14_n114()
+ fun_l15_n685
+end
+
+def fun_l14_n115()
+ fun_l15_n286
+end
+
+def fun_l14_n116()
+ fun_l15_n740
+end
+
+def fun_l14_n117()
+ fun_l15_n122
+end
+
+def fun_l14_n118()
+ fun_l15_n112
+end
+
+def fun_l14_n119()
+ fun_l15_n658
+end
+
+def fun_l14_n120()
+ fun_l15_n844
+end
+
+def fun_l14_n121()
+ fun_l15_n715
+end
+
+def fun_l14_n122()
+ fun_l15_n14
+end
+
+def fun_l14_n123()
+ fun_l15_n677
+end
+
+def fun_l14_n124()
+ fun_l15_n742
+end
+
+def fun_l14_n125()
+ fun_l15_n311
+end
+
+def fun_l14_n126()
+ fun_l15_n234
+end
+
+def fun_l14_n127()
+ fun_l15_n746
+end
+
+def fun_l14_n128()
+ fun_l15_n616
+end
+
+def fun_l14_n129()
+ fun_l15_n529
+end
+
+def fun_l14_n130()
+ fun_l15_n330
+end
+
+def fun_l14_n131()
+ fun_l15_n182
+end
+
+def fun_l14_n132()
+ fun_l15_n588
+end
+
+def fun_l14_n133()
+ fun_l15_n477
+end
+
+def fun_l14_n134()
+ fun_l15_n267
+end
+
+def fun_l14_n135()
+ fun_l15_n667
+end
+
+def fun_l14_n136()
+ fun_l15_n233
+end
+
+def fun_l14_n137()
+ fun_l15_n630
+end
+
+def fun_l14_n138()
+ fun_l15_n993
+end
+
+def fun_l14_n139()
+ fun_l15_n79
+end
+
+def fun_l14_n140()
+ fun_l15_n2
+end
+
+def fun_l14_n141()
+ fun_l15_n774
+end
+
+def fun_l14_n142()
+ fun_l15_n762
+end
+
+def fun_l14_n143()
+ fun_l15_n832
+end
+
+def fun_l14_n144()
+ fun_l15_n359
+end
+
+def fun_l14_n145()
+ fun_l15_n344
+end
+
+def fun_l14_n146()
+ fun_l15_n521
+end
+
+def fun_l14_n147()
+ fun_l15_n867
+end
+
+def fun_l14_n148()
+ fun_l15_n132
+end
+
+def fun_l14_n149()
+ fun_l15_n19
+end
+
+def fun_l14_n150()
+ fun_l15_n513
+end
+
+def fun_l14_n151()
+ fun_l15_n732
+end
+
+def fun_l14_n152()
+ fun_l15_n709
+end
+
+def fun_l14_n153()
+ fun_l15_n876
+end
+
+def fun_l14_n154()
+ fun_l15_n400
+end
+
+def fun_l14_n155()
+ fun_l15_n539
+end
+
+def fun_l14_n156()
+ fun_l15_n895
+end
+
+def fun_l14_n157()
+ fun_l15_n208
+end
+
+def fun_l14_n158()
+ fun_l15_n268
+end
+
+def fun_l14_n159()
+ fun_l15_n286
+end
+
+def fun_l14_n160()
+ fun_l15_n457
+end
+
+def fun_l14_n161()
+ fun_l15_n985
+end
+
+def fun_l14_n162()
+ fun_l15_n48
+end
+
+def fun_l14_n163()
+ fun_l15_n495
+end
+
+def fun_l14_n164()
+ fun_l15_n10
+end
+
+def fun_l14_n165()
+ fun_l15_n368
+end
+
+def fun_l14_n166()
+ fun_l15_n266
+end
+
+def fun_l14_n167()
+ fun_l15_n587
+end
+
+def fun_l14_n168()
+ fun_l15_n210
+end
+
+def fun_l14_n169()
+ fun_l15_n5
+end
+
+def fun_l14_n170()
+ fun_l15_n635
+end
+
+def fun_l14_n171()
+ fun_l15_n47
+end
+
+def fun_l14_n172()
+ fun_l15_n88
+end
+
+def fun_l14_n173()
+ fun_l15_n79
+end
+
+def fun_l14_n174()
+ fun_l15_n791
+end
+
+def fun_l14_n175()
+ fun_l15_n812
+end
+
+def fun_l14_n176()
+ fun_l15_n112
+end
+
+def fun_l14_n177()
+ fun_l15_n590
+end
+
+def fun_l14_n178()
+ fun_l15_n59
+end
+
+def fun_l14_n179()
+ fun_l15_n275
+end
+
+def fun_l14_n180()
+ fun_l15_n206
+end
+
+def fun_l14_n181()
+ fun_l15_n385
+end
+
+def fun_l14_n182()
+ fun_l15_n809
+end
+
+def fun_l14_n183()
+ fun_l15_n704
+end
+
+def fun_l14_n184()
+ fun_l15_n331
+end
+
+def fun_l14_n185()
+ fun_l15_n819
+end
+
+def fun_l14_n186()
+ fun_l15_n165
+end
+
+def fun_l14_n187()
+ fun_l15_n623
+end
+
+def fun_l14_n188()
+ fun_l15_n528
+end
+
+def fun_l14_n189()
+ fun_l15_n393
+end
+
+def fun_l14_n190()
+ fun_l15_n712
+end
+
+def fun_l14_n191()
+ fun_l15_n951
+end
+
+def fun_l14_n192()
+ fun_l15_n584
+end
+
+def fun_l14_n193()
+ fun_l15_n984
+end
+
+def fun_l14_n194()
+ fun_l15_n283
+end
+
+def fun_l14_n195()
+ fun_l15_n821
+end
+
+def fun_l14_n196()
+ fun_l15_n105
+end
+
+def fun_l14_n197()
+ fun_l15_n49
+end
+
+def fun_l14_n198()
+ fun_l15_n191
+end
+
+def fun_l14_n199()
+ fun_l15_n751
+end
+
+def fun_l14_n200()
+ fun_l15_n108
+end
+
+def fun_l14_n201()
+ fun_l15_n121
+end
+
+def fun_l14_n202()
+ fun_l15_n751
+end
+
+def fun_l14_n203()
+ fun_l15_n837
+end
+
+def fun_l14_n204()
+ fun_l15_n747
+end
+
+def fun_l14_n205()
+ fun_l15_n682
+end
+
+def fun_l14_n206()
+ fun_l15_n689
+end
+
+def fun_l14_n207()
+ fun_l15_n562
+end
+
+def fun_l14_n208()
+ fun_l15_n580
+end
+
+def fun_l14_n209()
+ fun_l15_n556
+end
+
+def fun_l14_n210()
+ fun_l15_n155
+end
+
+def fun_l14_n211()
+ fun_l15_n661
+end
+
+def fun_l14_n212()
+ fun_l15_n571
+end
+
+def fun_l14_n213()
+ fun_l15_n341
+end
+
+def fun_l14_n214()
+ fun_l15_n200
+end
+
+def fun_l14_n215()
+ fun_l15_n78
+end
+
+def fun_l14_n216()
+ fun_l15_n922
+end
+
+def fun_l14_n217()
+ fun_l15_n437
+end
+
+def fun_l14_n218()
+ fun_l15_n263
+end
+
+def fun_l14_n219()
+ fun_l15_n971
+end
+
+def fun_l14_n220()
+ fun_l15_n65
+end
+
+def fun_l14_n221()
+ fun_l15_n951
+end
+
+def fun_l14_n222()
+ fun_l15_n163
+end
+
+def fun_l14_n223()
+ fun_l15_n732
+end
+
+def fun_l14_n224()
+ fun_l15_n424
+end
+
+def fun_l14_n225()
+ fun_l15_n91
+end
+
+def fun_l14_n226()
+ fun_l15_n711
+end
+
+def fun_l14_n227()
+ fun_l15_n224
+end
+
+def fun_l14_n228()
+ fun_l15_n885
+end
+
+def fun_l14_n229()
+ fun_l15_n489
+end
+
+def fun_l14_n230()
+ fun_l15_n733
+end
+
+def fun_l14_n231()
+ fun_l15_n355
+end
+
+def fun_l14_n232()
+ fun_l15_n819
+end
+
+def fun_l14_n233()
+ fun_l15_n934
+end
+
+def fun_l14_n234()
+ fun_l15_n643
+end
+
+def fun_l14_n235()
+ fun_l15_n555
+end
+
+def fun_l14_n236()
+ fun_l15_n508
+end
+
+def fun_l14_n237()
+ fun_l15_n181
+end
+
+def fun_l14_n238()
+ fun_l15_n171
+end
+
+def fun_l14_n239()
+ fun_l15_n834
+end
+
+def fun_l14_n240()
+ fun_l15_n599
+end
+
+def fun_l14_n241()
+ fun_l15_n492
+end
+
+def fun_l14_n242()
+ fun_l15_n131
+end
+
+def fun_l14_n243()
+ fun_l15_n838
+end
+
+def fun_l14_n244()
+ fun_l15_n745
+end
+
+def fun_l14_n245()
+ fun_l15_n653
+end
+
+def fun_l14_n246()
+ fun_l15_n905
+end
+
+def fun_l14_n247()
+ fun_l15_n962
+end
+
+def fun_l14_n248()
+ fun_l15_n269
+end
+
+def fun_l14_n249()
+ fun_l15_n920
+end
+
+def fun_l14_n250()
+ fun_l15_n428
+end
+
+def fun_l14_n251()
+ fun_l15_n305
+end
+
+def fun_l14_n252()
+ fun_l15_n630
+end
+
+def fun_l14_n253()
+ fun_l15_n458
+end
+
+def fun_l14_n254()
+ fun_l15_n933
+end
+
+def fun_l14_n255()
+ fun_l15_n852
+end
+
+def fun_l14_n256()
+ fun_l15_n855
+end
+
+def fun_l14_n257()
+ fun_l15_n207
+end
+
+def fun_l14_n258()
+ fun_l15_n865
+end
+
+def fun_l14_n259()
+ fun_l15_n958
+end
+
+def fun_l14_n260()
+ fun_l15_n230
+end
+
+def fun_l14_n261()
+ fun_l15_n872
+end
+
+def fun_l14_n262()
+ fun_l15_n963
+end
+
+def fun_l14_n263()
+ fun_l15_n945
+end
+
+def fun_l14_n264()
+ fun_l15_n410
+end
+
+def fun_l14_n265()
+ fun_l15_n735
+end
+
+def fun_l14_n266()
+ fun_l15_n496
+end
+
+def fun_l14_n267()
+ fun_l15_n110
+end
+
+def fun_l14_n268()
+ fun_l15_n267
+end
+
+def fun_l14_n269()
+ fun_l15_n699
+end
+
+def fun_l14_n270()
+ fun_l15_n812
+end
+
+def fun_l14_n271()
+ fun_l15_n273
+end
+
+def fun_l14_n272()
+ fun_l15_n499
+end
+
+def fun_l14_n273()
+ fun_l15_n341
+end
+
+def fun_l14_n274()
+ fun_l15_n512
+end
+
+def fun_l14_n275()
+ fun_l15_n110
+end
+
+def fun_l14_n276()
+ fun_l15_n62
+end
+
+def fun_l14_n277()
+ fun_l15_n541
+end
+
+def fun_l14_n278()
+ fun_l15_n622
+end
+
+def fun_l14_n279()
+ fun_l15_n456
+end
+
+def fun_l14_n280()
+ fun_l15_n527
+end
+
+def fun_l14_n281()
+ fun_l15_n141
+end
+
+def fun_l14_n282()
+ fun_l15_n266
+end
+
+def fun_l14_n283()
+ fun_l15_n817
+end
+
+def fun_l14_n284()
+ fun_l15_n448
+end
+
+def fun_l14_n285()
+ fun_l15_n208
+end
+
+def fun_l14_n286()
+ fun_l15_n368
+end
+
+def fun_l14_n287()
+ fun_l15_n947
+end
+
+def fun_l14_n288()
+ fun_l15_n192
+end
+
+def fun_l14_n289()
+ fun_l15_n68
+end
+
+def fun_l14_n290()
+ fun_l15_n704
+end
+
+def fun_l14_n291()
+ fun_l15_n278
+end
+
+def fun_l14_n292()
+ fun_l15_n352
+end
+
+def fun_l14_n293()
+ fun_l15_n629
+end
+
+def fun_l14_n294()
+ fun_l15_n404
+end
+
+def fun_l14_n295()
+ fun_l15_n89
+end
+
+def fun_l14_n296()
+ fun_l15_n920
+end
+
+def fun_l14_n297()
+ fun_l15_n984
+end
+
+def fun_l14_n298()
+ fun_l15_n198
+end
+
+def fun_l14_n299()
+ fun_l15_n524
+end
+
+def fun_l14_n300()
+ fun_l15_n891
+end
+
+def fun_l14_n301()
+ fun_l15_n921
+end
+
+def fun_l14_n302()
+ fun_l15_n785
+end
+
+def fun_l14_n303()
+ fun_l15_n618
+end
+
+def fun_l14_n304()
+ fun_l15_n387
+end
+
+def fun_l14_n305()
+ fun_l15_n361
+end
+
+def fun_l14_n306()
+ fun_l15_n535
+end
+
+def fun_l14_n307()
+ fun_l15_n137
+end
+
+def fun_l14_n308()
+ fun_l15_n77
+end
+
+def fun_l14_n309()
+ fun_l15_n877
+end
+
+def fun_l14_n310()
+ fun_l15_n178
+end
+
+def fun_l14_n311()
+ fun_l15_n67
+end
+
+def fun_l14_n312()
+ fun_l15_n539
+end
+
+def fun_l14_n313()
+ fun_l15_n971
+end
+
+def fun_l14_n314()
+ fun_l15_n743
+end
+
+def fun_l14_n315()
+ fun_l15_n787
+end
+
+def fun_l14_n316()
+ fun_l15_n451
+end
+
+def fun_l14_n317()
+ fun_l15_n12
+end
+
+def fun_l14_n318()
+ fun_l15_n303
+end
+
+def fun_l14_n319()
+ fun_l15_n210
+end
+
+def fun_l14_n320()
+ fun_l15_n853
+end
+
+def fun_l14_n321()
+ fun_l15_n154
+end
+
+def fun_l14_n322()
+ fun_l15_n71
+end
+
+def fun_l14_n323()
+ fun_l15_n448
+end
+
+def fun_l14_n324()
+ fun_l15_n178
+end
+
+def fun_l14_n325()
+ fun_l15_n312
+end
+
+def fun_l14_n326()
+ fun_l15_n671
+end
+
+def fun_l14_n327()
+ fun_l15_n282
+end
+
+def fun_l14_n328()
+ fun_l15_n315
+end
+
+def fun_l14_n329()
+ fun_l15_n449
+end
+
+def fun_l14_n330()
+ fun_l15_n338
+end
+
+def fun_l14_n331()
+ fun_l15_n260
+end
+
+def fun_l14_n332()
+ fun_l15_n664
+end
+
+def fun_l14_n333()
+ fun_l15_n312
+end
+
+def fun_l14_n334()
+ fun_l15_n202
+end
+
+def fun_l14_n335()
+ fun_l15_n969
+end
+
+def fun_l14_n336()
+ fun_l15_n698
+end
+
+def fun_l14_n337()
+ fun_l15_n802
+end
+
+def fun_l14_n338()
+ fun_l15_n175
+end
+
+def fun_l14_n339()
+ fun_l15_n646
+end
+
+def fun_l14_n340()
+ fun_l15_n145
+end
+
+def fun_l14_n341()
+ fun_l15_n19
+end
+
+def fun_l14_n342()
+ fun_l15_n764
+end
+
+def fun_l14_n343()
+ fun_l15_n970
+end
+
+def fun_l14_n344()
+ fun_l15_n519
+end
+
+def fun_l14_n345()
+ fun_l15_n121
+end
+
+def fun_l14_n346()
+ fun_l15_n299
+end
+
+def fun_l14_n347()
+ fun_l15_n553
+end
+
+def fun_l14_n348()
+ fun_l15_n618
+end
+
+def fun_l14_n349()
+ fun_l15_n725
+end
+
+def fun_l14_n350()
+ fun_l15_n635
+end
+
+def fun_l14_n351()
+ fun_l15_n382
+end
+
+def fun_l14_n352()
+ fun_l15_n529
+end
+
+def fun_l14_n353()
+ fun_l15_n168
+end
+
+def fun_l14_n354()
+ fun_l15_n948
+end
+
+def fun_l14_n355()
+ fun_l15_n192
+end
+
+def fun_l14_n356()
+ fun_l15_n27
+end
+
+def fun_l14_n357()
+ fun_l15_n254
+end
+
+def fun_l14_n358()
+ fun_l15_n384
+end
+
+def fun_l14_n359()
+ fun_l15_n559
+end
+
+def fun_l14_n360()
+ fun_l15_n560
+end
+
+def fun_l14_n361()
+ fun_l15_n781
+end
+
+def fun_l14_n362()
+ fun_l15_n494
+end
+
+def fun_l14_n363()
+ fun_l15_n997
+end
+
+def fun_l14_n364()
+ fun_l15_n203
+end
+
+def fun_l14_n365()
+ fun_l15_n61
+end
+
+def fun_l14_n366()
+ fun_l15_n190
+end
+
+def fun_l14_n367()
+ fun_l15_n755
+end
+
+def fun_l14_n368()
+ fun_l15_n876
+end
+
+def fun_l14_n369()
+ fun_l15_n761
+end
+
+def fun_l14_n370()
+ fun_l15_n641
+end
+
+def fun_l14_n371()
+ fun_l15_n307
+end
+
+def fun_l14_n372()
+ fun_l15_n351
+end
+
+def fun_l14_n373()
+ fun_l15_n929
+end
+
+def fun_l14_n374()
+ fun_l15_n455
+end
+
+def fun_l14_n375()
+ fun_l15_n740
+end
+
+def fun_l14_n376()
+ fun_l15_n803
+end
+
+def fun_l14_n377()
+ fun_l15_n544
+end
+
+def fun_l14_n378()
+ fun_l15_n666
+end
+
+def fun_l14_n379()
+ fun_l15_n274
+end
+
+def fun_l14_n380()
+ fun_l15_n374
+end
+
+def fun_l14_n381()
+ fun_l15_n108
+end
+
+def fun_l14_n382()
+ fun_l15_n632
+end
+
+def fun_l14_n383()
+ fun_l15_n782
+end
+
+def fun_l14_n384()
+ fun_l15_n16
+end
+
+def fun_l14_n385()
+ fun_l15_n323
+end
+
+def fun_l14_n386()
+ fun_l15_n923
+end
+
+def fun_l14_n387()
+ fun_l15_n929
+end
+
+def fun_l14_n388()
+ fun_l15_n318
+end
+
+def fun_l14_n389()
+ fun_l15_n929
+end
+
+def fun_l14_n390()
+ fun_l15_n633
+end
+
+def fun_l14_n391()
+ fun_l15_n159
+end
+
+def fun_l14_n392()
+ fun_l15_n18
+end
+
+def fun_l14_n393()
+ fun_l15_n997
+end
+
+def fun_l14_n394()
+ fun_l15_n585
+end
+
+def fun_l14_n395()
+ fun_l15_n216
+end
+
+def fun_l14_n396()
+ fun_l15_n665
+end
+
+def fun_l14_n397()
+ fun_l15_n51
+end
+
+def fun_l14_n398()
+ fun_l15_n681
+end
+
+def fun_l14_n399()
+ fun_l15_n921
+end
+
+def fun_l14_n400()
+ fun_l15_n937
+end
+
+def fun_l14_n401()
+ fun_l15_n251
+end
+
+def fun_l14_n402()
+ fun_l15_n359
+end
+
+def fun_l14_n403()
+ fun_l15_n262
+end
+
+def fun_l14_n404()
+ fun_l15_n631
+end
+
+def fun_l14_n405()
+ fun_l15_n218
+end
+
+def fun_l14_n406()
+ fun_l15_n138
+end
+
+def fun_l14_n407()
+ fun_l15_n695
+end
+
+def fun_l14_n408()
+ fun_l15_n95
+end
+
+def fun_l14_n409()
+ fun_l15_n166
+end
+
+def fun_l14_n410()
+ fun_l15_n566
+end
+
+def fun_l14_n411()
+ fun_l15_n322
+end
+
+def fun_l14_n412()
+ fun_l15_n278
+end
+
+def fun_l14_n413()
+ fun_l15_n144
+end
+
+def fun_l14_n414()
+ fun_l15_n949
+end
+
+def fun_l14_n415()
+ fun_l15_n351
+end
+
+def fun_l14_n416()
+ fun_l15_n887
+end
+
+def fun_l14_n417()
+ fun_l15_n501
+end
+
+def fun_l14_n418()
+ fun_l15_n997
+end
+
+def fun_l14_n419()
+ fun_l15_n212
+end
+
+def fun_l14_n420()
+ fun_l15_n725
+end
+
+def fun_l14_n421()
+ fun_l15_n728
+end
+
+def fun_l14_n422()
+ fun_l15_n923
+end
+
+def fun_l14_n423()
+ fun_l15_n694
+end
+
+def fun_l14_n424()
+ fun_l15_n472
+end
+
+def fun_l14_n425()
+ fun_l15_n967
+end
+
+def fun_l14_n426()
+ fun_l15_n908
+end
+
+def fun_l14_n427()
+ fun_l15_n199
+end
+
+def fun_l14_n428()
+ fun_l15_n384
+end
+
+def fun_l14_n429()
+ fun_l15_n485
+end
+
+def fun_l14_n430()
+ fun_l15_n767
+end
+
+def fun_l14_n431()
+ fun_l15_n337
+end
+
+def fun_l14_n432()
+ fun_l15_n664
+end
+
+def fun_l14_n433()
+ fun_l15_n735
+end
+
+def fun_l14_n434()
+ fun_l15_n76
+end
+
+def fun_l14_n435()
+ fun_l15_n879
+end
+
+def fun_l14_n436()
+ fun_l15_n815
+end
+
+def fun_l14_n437()
+ fun_l15_n290
+end
+
+def fun_l14_n438()
+ fun_l15_n836
+end
+
+def fun_l14_n439()
+ fun_l15_n56
+end
+
+def fun_l14_n440()
+ fun_l15_n671
+end
+
+def fun_l14_n441()
+ fun_l15_n90
+end
+
+def fun_l14_n442()
+ fun_l15_n930
+end
+
+def fun_l14_n443()
+ fun_l15_n754
+end
+
+def fun_l14_n444()
+ fun_l15_n241
+end
+
+def fun_l14_n445()
+ fun_l15_n362
+end
+
+def fun_l14_n446()
+ fun_l15_n260
+end
+
+def fun_l14_n447()
+ fun_l15_n846
+end
+
+def fun_l14_n448()
+ fun_l15_n754
+end
+
+def fun_l14_n449()
+ fun_l15_n571
+end
+
+def fun_l14_n450()
+ fun_l15_n602
+end
+
+def fun_l14_n451()
+ fun_l15_n243
+end
+
+def fun_l14_n452()
+ fun_l15_n59
+end
+
+def fun_l14_n453()
+ fun_l15_n660
+end
+
+def fun_l14_n454()
+ fun_l15_n338
+end
+
+def fun_l14_n455()
+ fun_l15_n461
+end
+
+def fun_l14_n456()
+ fun_l15_n702
+end
+
+def fun_l14_n457()
+ fun_l15_n878
+end
+
+def fun_l14_n458()
+ fun_l15_n625
+end
+
+def fun_l14_n459()
+ fun_l15_n762
+end
+
+def fun_l14_n460()
+ fun_l15_n36
+end
+
+def fun_l14_n461()
+ fun_l15_n432
+end
+
+def fun_l14_n462()
+ fun_l15_n685
+end
+
+def fun_l14_n463()
+ fun_l15_n398
+end
+
+def fun_l14_n464()
+ fun_l15_n828
+end
+
+def fun_l14_n465()
+ fun_l15_n306
+end
+
+def fun_l14_n466()
+ fun_l15_n717
+end
+
+def fun_l14_n467()
+ fun_l15_n271
+end
+
+def fun_l14_n468()
+ fun_l15_n444
+end
+
+def fun_l14_n469()
+ fun_l15_n82
+end
+
+def fun_l14_n470()
+ fun_l15_n363
+end
+
+def fun_l14_n471()
+ fun_l15_n648
+end
+
+def fun_l14_n472()
+ fun_l15_n33
+end
+
+def fun_l14_n473()
+ fun_l15_n968
+end
+
+def fun_l14_n474()
+ fun_l15_n331
+end
+
+def fun_l14_n475()
+ fun_l15_n228
+end
+
+def fun_l14_n476()
+ fun_l15_n944
+end
+
+def fun_l14_n477()
+ fun_l15_n771
+end
+
+def fun_l14_n478()
+ fun_l15_n228
+end
+
+def fun_l14_n479()
+ fun_l15_n442
+end
+
+def fun_l14_n480()
+ fun_l15_n75
+end
+
+def fun_l14_n481()
+ fun_l15_n911
+end
+
+def fun_l14_n482()
+ fun_l15_n591
+end
+
+def fun_l14_n483()
+ fun_l15_n929
+end
+
+def fun_l14_n484()
+ fun_l15_n504
+end
+
+def fun_l14_n485()
+ fun_l15_n48
+end
+
+def fun_l14_n486()
+ fun_l15_n592
+end
+
+def fun_l14_n487()
+ fun_l15_n399
+end
+
+def fun_l14_n488()
+ fun_l15_n467
+end
+
+def fun_l14_n489()
+ fun_l15_n192
+end
+
+def fun_l14_n490()
+ fun_l15_n347
+end
+
+def fun_l14_n491()
+ fun_l15_n517
+end
+
+def fun_l14_n492()
+ fun_l15_n436
+end
+
+def fun_l14_n493()
+ fun_l15_n50
+end
+
+def fun_l14_n494()
+ fun_l15_n237
+end
+
+def fun_l14_n495()
+ fun_l15_n878
+end
+
+def fun_l14_n496()
+ fun_l15_n46
+end
+
+def fun_l14_n497()
+ fun_l15_n499
+end
+
+def fun_l14_n498()
+ fun_l15_n779
+end
+
+def fun_l14_n499()
+ fun_l15_n763
+end
+
+def fun_l14_n500()
+ fun_l15_n195
+end
+
+def fun_l14_n501()
+ fun_l15_n868
+end
+
+def fun_l14_n502()
+ fun_l15_n83
+end
+
+def fun_l14_n503()
+ fun_l15_n386
+end
+
+def fun_l14_n504()
+ fun_l15_n907
+end
+
+def fun_l14_n505()
+ fun_l15_n889
+end
+
+def fun_l14_n506()
+ fun_l15_n314
+end
+
+def fun_l14_n507()
+ fun_l15_n24
+end
+
+def fun_l14_n508()
+ fun_l15_n122
+end
+
+def fun_l14_n509()
+ fun_l15_n772
+end
+
+def fun_l14_n510()
+ fun_l15_n204
+end
+
+def fun_l14_n511()
+ fun_l15_n646
+end
+
+def fun_l14_n512()
+ fun_l15_n105
+end
+
+def fun_l14_n513()
+ fun_l15_n393
+end
+
+def fun_l14_n514()
+ fun_l15_n533
+end
+
+def fun_l14_n515()
+ fun_l15_n572
+end
+
+def fun_l14_n516()
+ fun_l15_n360
+end
+
+def fun_l14_n517()
+ fun_l15_n241
+end
+
+def fun_l14_n518()
+ fun_l15_n962
+end
+
+def fun_l14_n519()
+ fun_l15_n771
+end
+
+def fun_l14_n520()
+ fun_l15_n379
+end
+
+def fun_l14_n521()
+ fun_l15_n749
+end
+
+def fun_l14_n522()
+ fun_l15_n601
+end
+
+def fun_l14_n523()
+ fun_l15_n0
+end
+
+def fun_l14_n524()
+ fun_l15_n345
+end
+
+def fun_l14_n525()
+ fun_l15_n896
+end
+
+def fun_l14_n526()
+ fun_l15_n612
+end
+
+def fun_l14_n527()
+ fun_l15_n897
+end
+
+def fun_l14_n528()
+ fun_l15_n760
+end
+
+def fun_l14_n529()
+ fun_l15_n283
+end
+
+def fun_l14_n530()
+ fun_l15_n269
+end
+
+def fun_l14_n531()
+ fun_l15_n967
+end
+
+def fun_l14_n532()
+ fun_l15_n399
+end
+
+def fun_l14_n533()
+ fun_l15_n343
+end
+
+def fun_l14_n534()
+ fun_l15_n590
+end
+
+def fun_l14_n535()
+ fun_l15_n37
+end
+
+def fun_l14_n536()
+ fun_l15_n882
+end
+
+def fun_l14_n537()
+ fun_l15_n275
+end
+
+def fun_l14_n538()
+ fun_l15_n169
+end
+
+def fun_l14_n539()
+ fun_l15_n474
+end
+
+def fun_l14_n540()
+ fun_l15_n993
+end
+
+def fun_l14_n541()
+ fun_l15_n872
+end
+
+def fun_l14_n542()
+ fun_l15_n650
+end
+
+def fun_l14_n543()
+ fun_l15_n238
+end
+
+def fun_l14_n544()
+ fun_l15_n80
+end
+
+def fun_l14_n545()
+ fun_l15_n585
+end
+
+def fun_l14_n546()
+ fun_l15_n961
+end
+
+def fun_l14_n547()
+ fun_l15_n574
+end
+
+def fun_l14_n548()
+ fun_l15_n447
+end
+
+def fun_l14_n549()
+ fun_l15_n405
+end
+
+def fun_l14_n550()
+ fun_l15_n347
+end
+
+def fun_l14_n551()
+ fun_l15_n326
+end
+
+def fun_l14_n552()
+ fun_l15_n679
+end
+
+def fun_l14_n553()
+ fun_l15_n848
+end
+
+def fun_l14_n554()
+ fun_l15_n391
+end
+
+def fun_l14_n555()
+ fun_l15_n293
+end
+
+def fun_l14_n556()
+ fun_l15_n997
+end
+
+def fun_l14_n557()
+ fun_l15_n247
+end
+
+def fun_l14_n558()
+ fun_l15_n138
+end
+
+def fun_l14_n559()
+ fun_l15_n737
+end
+
+def fun_l14_n560()
+ fun_l15_n764
+end
+
+def fun_l14_n561()
+ fun_l15_n541
+end
+
+def fun_l14_n562()
+ fun_l15_n373
+end
+
+def fun_l14_n563()
+ fun_l15_n562
+end
+
+def fun_l14_n564()
+ fun_l15_n626
+end
+
+def fun_l14_n565()
+ fun_l15_n601
+end
+
+def fun_l14_n566()
+ fun_l15_n547
+end
+
+def fun_l14_n567()
+ fun_l15_n226
+end
+
+def fun_l14_n568()
+ fun_l15_n182
+end
+
+def fun_l14_n569()
+ fun_l15_n647
+end
+
+def fun_l14_n570()
+ fun_l15_n912
+end
+
+def fun_l14_n571()
+ fun_l15_n33
+end
+
+def fun_l14_n572()
+ fun_l15_n397
+end
+
+def fun_l14_n573()
+ fun_l15_n413
+end
+
+def fun_l14_n574()
+ fun_l15_n714
+end
+
+def fun_l14_n575()
+ fun_l15_n930
+end
+
+def fun_l14_n576()
+ fun_l15_n35
+end
+
+def fun_l14_n577()
+ fun_l15_n868
+end
+
+def fun_l14_n578()
+ fun_l15_n606
+end
+
+def fun_l14_n579()
+ fun_l15_n516
+end
+
+def fun_l14_n580()
+ fun_l15_n127
+end
+
+def fun_l14_n581()
+ fun_l15_n689
+end
+
+def fun_l14_n582()
+ fun_l15_n346
+end
+
+def fun_l14_n583()
+ fun_l15_n352
+end
+
+def fun_l14_n584()
+ fun_l15_n810
+end
+
+def fun_l14_n585()
+ fun_l15_n38
+end
+
+def fun_l14_n586()
+ fun_l15_n751
+end
+
+def fun_l14_n587()
+ fun_l15_n888
+end
+
+def fun_l14_n588()
+ fun_l15_n938
+end
+
+def fun_l14_n589()
+ fun_l15_n941
+end
+
+def fun_l14_n590()
+ fun_l15_n768
+end
+
+def fun_l14_n591()
+ fun_l15_n544
+end
+
+def fun_l14_n592()
+ fun_l15_n393
+end
+
+def fun_l14_n593()
+ fun_l15_n74
+end
+
+def fun_l14_n594()
+ fun_l15_n812
+end
+
+def fun_l14_n595()
+ fun_l15_n94
+end
+
+def fun_l14_n596()
+ fun_l15_n122
+end
+
+def fun_l14_n597()
+ fun_l15_n552
+end
+
+def fun_l14_n598()
+ fun_l15_n586
+end
+
+def fun_l14_n599()
+ fun_l15_n100
+end
+
+def fun_l14_n600()
+ fun_l15_n338
+end
+
+def fun_l14_n601()
+ fun_l15_n627
+end
+
+def fun_l14_n602()
+ fun_l15_n445
+end
+
+def fun_l14_n603()
+ fun_l15_n734
+end
+
+def fun_l14_n604()
+ fun_l15_n852
+end
+
+def fun_l14_n605()
+ fun_l15_n908
+end
+
+def fun_l14_n606()
+ fun_l15_n736
+end
+
+def fun_l14_n607()
+ fun_l15_n590
+end
+
+def fun_l14_n608()
+ fun_l15_n988
+end
+
+def fun_l14_n609()
+ fun_l15_n241
+end
+
+def fun_l14_n610()
+ fun_l15_n375
+end
+
+def fun_l14_n611()
+ fun_l15_n25
+end
+
+def fun_l14_n612()
+ fun_l15_n176
+end
+
+def fun_l14_n613()
+ fun_l15_n375
+end
+
+def fun_l14_n614()
+ fun_l15_n248
+end
+
+def fun_l14_n615()
+ fun_l15_n393
+end
+
+def fun_l14_n616()
+ fun_l15_n2
+end
+
+def fun_l14_n617()
+ fun_l15_n964
+end
+
+def fun_l14_n618()
+ fun_l15_n581
+end
+
+def fun_l14_n619()
+ fun_l15_n190
+end
+
+def fun_l14_n620()
+ fun_l15_n847
+end
+
+def fun_l14_n621()
+ fun_l15_n748
+end
+
+def fun_l14_n622()
+ fun_l15_n27
+end
+
+def fun_l14_n623()
+ fun_l15_n984
+end
+
+def fun_l14_n624()
+ fun_l15_n728
+end
+
+def fun_l14_n625()
+ fun_l15_n740
+end
+
+def fun_l14_n626()
+ fun_l15_n480
+end
+
+def fun_l14_n627()
+ fun_l15_n175
+end
+
+def fun_l14_n628()
+ fun_l15_n152
+end
+
+def fun_l14_n629()
+ fun_l15_n880
+end
+
+def fun_l14_n630()
+ fun_l15_n337
+end
+
+def fun_l14_n631()
+ fun_l15_n862
+end
+
+def fun_l14_n632()
+ fun_l15_n367
+end
+
+def fun_l14_n633()
+ fun_l15_n768
+end
+
+def fun_l14_n634()
+ fun_l15_n178
+end
+
+def fun_l14_n635()
+ fun_l15_n693
+end
+
+def fun_l14_n636()
+ fun_l15_n176
+end
+
+def fun_l14_n637()
+ fun_l15_n348
+end
+
+def fun_l14_n638()
+ fun_l15_n31
+end
+
+def fun_l14_n639()
+ fun_l15_n601
+end
+
+def fun_l14_n640()
+ fun_l15_n824
+end
+
+def fun_l14_n641()
+ fun_l15_n920
+end
+
+def fun_l14_n642()
+ fun_l15_n464
+end
+
+def fun_l14_n643()
+ fun_l15_n747
+end
+
+def fun_l14_n644()
+ fun_l15_n378
+end
+
+def fun_l14_n645()
+ fun_l15_n88
+end
+
+def fun_l14_n646()
+ fun_l15_n267
+end
+
+def fun_l14_n647()
+ fun_l15_n805
+end
+
+def fun_l14_n648()
+ fun_l15_n793
+end
+
+def fun_l14_n649()
+ fun_l15_n135
+end
+
+def fun_l14_n650()
+ fun_l15_n51
+end
+
+def fun_l14_n651()
+ fun_l15_n500
+end
+
+def fun_l14_n652()
+ fun_l15_n726
+end
+
+def fun_l14_n653()
+ fun_l15_n736
+end
+
+def fun_l14_n654()
+ fun_l15_n691
+end
+
+def fun_l14_n655()
+ fun_l15_n718
+end
+
+def fun_l14_n656()
+ fun_l15_n456
+end
+
+def fun_l14_n657()
+ fun_l15_n868
+end
+
+def fun_l14_n658()
+ fun_l15_n818
+end
+
+def fun_l14_n659()
+ fun_l15_n693
+end
+
+def fun_l14_n660()
+ fun_l15_n117
+end
+
+def fun_l14_n661()
+ fun_l15_n872
+end
+
+def fun_l14_n662()
+ fun_l15_n312
+end
+
+def fun_l14_n663()
+ fun_l15_n538
+end
+
+def fun_l14_n664()
+ fun_l15_n449
+end
+
+def fun_l14_n665()
+ fun_l15_n954
+end
+
+def fun_l14_n666()
+ fun_l15_n163
+end
+
+def fun_l14_n667()
+ fun_l15_n291
+end
+
+def fun_l14_n668()
+ fun_l15_n17
+end
+
+def fun_l14_n669()
+ fun_l15_n189
+end
+
+def fun_l14_n670()
+ fun_l15_n25
+end
+
+def fun_l14_n671()
+ fun_l15_n381
+end
+
+def fun_l14_n672()
+ fun_l15_n66
+end
+
+def fun_l14_n673()
+ fun_l15_n28
+end
+
+def fun_l14_n674()
+ fun_l15_n79
+end
+
+def fun_l14_n675()
+ fun_l15_n237
+end
+
+def fun_l14_n676()
+ fun_l15_n301
+end
+
+def fun_l14_n677()
+ fun_l15_n876
+end
+
+def fun_l14_n678()
+ fun_l15_n573
+end
+
+def fun_l14_n679()
+ fun_l15_n758
+end
+
+def fun_l14_n680()
+ fun_l15_n152
+end
+
+def fun_l14_n681()
+ fun_l15_n597
+end
+
+def fun_l14_n682()
+ fun_l15_n872
+end
+
+def fun_l14_n683()
+ fun_l15_n329
+end
+
+def fun_l14_n684()
+ fun_l15_n537
+end
+
+def fun_l14_n685()
+ fun_l15_n379
+end
+
+def fun_l14_n686()
+ fun_l15_n748
+end
+
+def fun_l14_n687()
+ fun_l15_n407
+end
+
+def fun_l14_n688()
+ fun_l15_n762
+end
+
+def fun_l14_n689()
+ fun_l15_n792
+end
+
+def fun_l14_n690()
+ fun_l15_n179
+end
+
+def fun_l14_n691()
+ fun_l15_n855
+end
+
+def fun_l14_n692()
+ fun_l15_n635
+end
+
+def fun_l14_n693()
+ fun_l15_n807
+end
+
+def fun_l14_n694()
+ fun_l15_n957
+end
+
+def fun_l14_n695()
+ fun_l15_n130
+end
+
+def fun_l14_n696()
+ fun_l15_n183
+end
+
+def fun_l14_n697()
+ fun_l15_n881
+end
+
+def fun_l14_n698()
+ fun_l15_n744
+end
+
+def fun_l14_n699()
+ fun_l15_n360
+end
+
+def fun_l14_n700()
+ fun_l15_n661
+end
+
+def fun_l14_n701()
+ fun_l15_n136
+end
+
+def fun_l14_n702()
+ fun_l15_n868
+end
+
+def fun_l14_n703()
+ fun_l15_n718
+end
+
+def fun_l14_n704()
+ fun_l15_n253
+end
+
+def fun_l14_n705()
+ fun_l15_n272
+end
+
+def fun_l14_n706()
+ fun_l15_n474
+end
+
+def fun_l14_n707()
+ fun_l15_n457
+end
+
+def fun_l14_n708()
+ fun_l15_n836
+end
+
+def fun_l14_n709()
+ fun_l15_n141
+end
+
+def fun_l14_n710()
+ fun_l15_n80
+end
+
+def fun_l14_n711()
+ fun_l15_n538
+end
+
+def fun_l14_n712()
+ fun_l15_n68
+end
+
+def fun_l14_n713()
+ fun_l15_n603
+end
+
+def fun_l14_n714()
+ fun_l15_n604
+end
+
+def fun_l14_n715()
+ fun_l15_n415
+end
+
+def fun_l14_n716()
+ fun_l15_n269
+end
+
+def fun_l14_n717()
+ fun_l15_n836
+end
+
+def fun_l14_n718()
+ fun_l15_n599
+end
+
+def fun_l14_n719()
+ fun_l15_n373
+end
+
+def fun_l14_n720()
+ fun_l15_n256
+end
+
+def fun_l14_n721()
+ fun_l15_n18
+end
+
+def fun_l14_n722()
+ fun_l15_n719
+end
+
+def fun_l14_n723()
+ fun_l15_n994
+end
+
+def fun_l14_n724()
+ fun_l15_n361
+end
+
+def fun_l14_n725()
+ fun_l15_n789
+end
+
+def fun_l14_n726()
+ fun_l15_n453
+end
+
+def fun_l14_n727()
+ fun_l15_n950
+end
+
+def fun_l14_n728()
+ fun_l15_n410
+end
+
+def fun_l14_n729()
+ fun_l15_n678
+end
+
+def fun_l14_n730()
+ fun_l15_n948
+end
+
+def fun_l14_n731()
+ fun_l15_n964
+end
+
+def fun_l14_n732()
+ fun_l15_n199
+end
+
+def fun_l14_n733()
+ fun_l15_n812
+end
+
+def fun_l14_n734()
+ fun_l15_n983
+end
+
+def fun_l14_n735()
+ fun_l15_n550
+end
+
+def fun_l14_n736()
+ fun_l15_n776
+end
+
+def fun_l14_n737()
+ fun_l15_n510
+end
+
+def fun_l14_n738()
+ fun_l15_n959
+end
+
+def fun_l14_n739()
+ fun_l15_n537
+end
+
+def fun_l14_n740()
+ fun_l15_n717
+end
+
+def fun_l14_n741()
+ fun_l15_n437
+end
+
+def fun_l14_n742()
+ fun_l15_n364
+end
+
+def fun_l14_n743()
+ fun_l15_n785
+end
+
+def fun_l14_n744()
+ fun_l15_n658
+end
+
+def fun_l14_n745()
+ fun_l15_n462
+end
+
+def fun_l14_n746()
+ fun_l15_n263
+end
+
+def fun_l14_n747()
+ fun_l15_n657
+end
+
+def fun_l14_n748()
+ fun_l15_n395
+end
+
+def fun_l14_n749()
+ fun_l15_n852
+end
+
+def fun_l14_n750()
+ fun_l15_n809
+end
+
+def fun_l14_n751()
+ fun_l15_n959
+end
+
+def fun_l14_n752()
+ fun_l15_n547
+end
+
+def fun_l14_n753()
+ fun_l15_n719
+end
+
+def fun_l14_n754()
+ fun_l15_n118
+end
+
+def fun_l14_n755()
+ fun_l15_n503
+end
+
+def fun_l14_n756()
+ fun_l15_n112
+end
+
+def fun_l14_n757()
+ fun_l15_n39
+end
+
+def fun_l14_n758()
+ fun_l15_n12
+end
+
+def fun_l14_n759()
+ fun_l15_n692
+end
+
+def fun_l14_n760()
+ fun_l15_n276
+end
+
+def fun_l14_n761()
+ fun_l15_n771
+end
+
+def fun_l14_n762()
+ fun_l15_n643
+end
+
+def fun_l14_n763()
+ fun_l15_n820
+end
+
+def fun_l14_n764()
+ fun_l15_n956
+end
+
+def fun_l14_n765()
+ fun_l15_n169
+end
+
+def fun_l14_n766()
+ fun_l15_n558
+end
+
+def fun_l14_n767()
+ fun_l15_n106
+end
+
+def fun_l14_n768()
+ fun_l15_n813
+end
+
+def fun_l14_n769()
+ fun_l15_n65
+end
+
+def fun_l14_n770()
+ fun_l15_n214
+end
+
+def fun_l14_n771()
+ fun_l15_n264
+end
+
+def fun_l14_n772()
+ fun_l15_n687
+end
+
+def fun_l14_n773()
+ fun_l15_n8
+end
+
+def fun_l14_n774()
+ fun_l15_n703
+end
+
+def fun_l14_n775()
+ fun_l15_n971
+end
+
+def fun_l14_n776()
+ fun_l15_n144
+end
+
+def fun_l14_n777()
+ fun_l15_n542
+end
+
+def fun_l14_n778()
+ fun_l15_n57
+end
+
+def fun_l14_n779()
+ fun_l15_n772
+end
+
+def fun_l14_n780()
+ fun_l15_n347
+end
+
+def fun_l14_n781()
+ fun_l15_n895
+end
+
+def fun_l14_n782()
+ fun_l15_n547
+end
+
+def fun_l14_n783()
+ fun_l15_n254
+end
+
+def fun_l14_n784()
+ fun_l15_n358
+end
+
+def fun_l14_n785()
+ fun_l15_n861
+end
+
+def fun_l14_n786()
+ fun_l15_n169
+end
+
+def fun_l14_n787()
+ fun_l15_n607
+end
+
+def fun_l14_n788()
+ fun_l15_n909
+end
+
+def fun_l14_n789()
+ fun_l15_n796
+end
+
+def fun_l14_n790()
+ fun_l15_n414
+end
+
+def fun_l14_n791()
+ fun_l15_n575
+end
+
+def fun_l14_n792()
+ fun_l15_n115
+end
+
+def fun_l14_n793()
+ fun_l15_n289
+end
+
+def fun_l14_n794()
+ fun_l15_n285
+end
+
+def fun_l14_n795()
+ fun_l15_n563
+end
+
+def fun_l14_n796()
+ fun_l15_n78
+end
+
+def fun_l14_n797()
+ fun_l15_n913
+end
+
+def fun_l14_n798()
+ fun_l15_n852
+end
+
+def fun_l14_n799()
+ fun_l15_n779
+end
+
+def fun_l14_n800()
+ fun_l15_n301
+end
+
+def fun_l14_n801()
+ fun_l15_n180
+end
+
+def fun_l14_n802()
+ fun_l15_n618
+end
+
+def fun_l14_n803()
+ fun_l15_n48
+end
+
+def fun_l14_n804()
+ fun_l15_n839
+end
+
+def fun_l14_n805()
+ fun_l15_n608
+end
+
+def fun_l14_n806()
+ fun_l15_n408
+end
+
+def fun_l14_n807()
+ fun_l15_n23
+end
+
+def fun_l14_n808()
+ fun_l15_n723
+end
+
+def fun_l14_n809()
+ fun_l15_n849
+end
+
+def fun_l14_n810()
+ fun_l15_n112
+end
+
+def fun_l14_n811()
+ fun_l15_n801
+end
+
+def fun_l14_n812()
+ fun_l15_n905
+end
+
+def fun_l14_n813()
+ fun_l15_n40
+end
+
+def fun_l14_n814()
+ fun_l15_n628
+end
+
+def fun_l14_n815()
+ fun_l15_n761
+end
+
+def fun_l14_n816()
+ fun_l15_n631
+end
+
+def fun_l14_n817()
+ fun_l15_n565
+end
+
+def fun_l14_n818()
+ fun_l15_n985
+end
+
+def fun_l14_n819()
+ fun_l15_n408
+end
+
+def fun_l14_n820()
+ fun_l15_n173
+end
+
+def fun_l14_n821()
+ fun_l15_n508
+end
+
+def fun_l14_n822()
+ fun_l15_n641
+end
+
+def fun_l14_n823()
+ fun_l15_n348
+end
+
+def fun_l14_n824()
+ fun_l15_n988
+end
+
+def fun_l14_n825()
+ fun_l15_n790
+end
+
+def fun_l14_n826()
+ fun_l15_n915
+end
+
+def fun_l14_n827()
+ fun_l15_n727
+end
+
+def fun_l14_n828()
+ fun_l15_n613
+end
+
+def fun_l14_n829()
+ fun_l15_n21
+end
+
+def fun_l14_n830()
+ fun_l15_n533
+end
+
+def fun_l14_n831()
+ fun_l15_n904
+end
+
+def fun_l14_n832()
+ fun_l15_n586
+end
+
+def fun_l14_n833()
+ fun_l15_n794
+end
+
+def fun_l14_n834()
+ fun_l15_n475
+end
+
+def fun_l14_n835()
+ fun_l15_n14
+end
+
+def fun_l14_n836()
+ fun_l15_n69
+end
+
+def fun_l14_n837()
+ fun_l15_n850
+end
+
+def fun_l14_n838()
+ fun_l15_n426
+end
+
+def fun_l14_n839()
+ fun_l15_n552
+end
+
+def fun_l14_n840()
+ fun_l15_n968
+end
+
+def fun_l14_n841()
+ fun_l15_n305
+end
+
+def fun_l14_n842()
+ fun_l15_n865
+end
+
+def fun_l14_n843()
+ fun_l15_n190
+end
+
+def fun_l14_n844()
+ fun_l15_n610
+end
+
+def fun_l14_n845()
+ fun_l15_n478
+end
+
+def fun_l14_n846()
+ fun_l15_n640
+end
+
+def fun_l14_n847()
+ fun_l15_n294
+end
+
+def fun_l14_n848()
+ fun_l15_n493
+end
+
+def fun_l14_n849()
+ fun_l15_n580
+end
+
+def fun_l14_n850()
+ fun_l15_n173
+end
+
+def fun_l14_n851()
+ fun_l15_n134
+end
+
+def fun_l14_n852()
+ fun_l15_n352
+end
+
+def fun_l14_n853()
+ fun_l15_n738
+end
+
+def fun_l14_n854()
+ fun_l15_n289
+end
+
+def fun_l14_n855()
+ fun_l15_n44
+end
+
+def fun_l14_n856()
+ fun_l15_n200
+end
+
+def fun_l14_n857()
+ fun_l15_n584
+end
+
+def fun_l14_n858()
+ fun_l15_n787
+end
+
+def fun_l14_n859()
+ fun_l15_n901
+end
+
+def fun_l14_n860()
+ fun_l15_n103
+end
+
+def fun_l14_n861()
+ fun_l15_n628
+end
+
+def fun_l14_n862()
+ fun_l15_n521
+end
+
+def fun_l14_n863()
+ fun_l15_n465
+end
+
+def fun_l14_n864()
+ fun_l15_n649
+end
+
+def fun_l14_n865()
+ fun_l15_n60
+end
+
+def fun_l14_n866()
+ fun_l15_n567
+end
+
+def fun_l14_n867()
+ fun_l15_n775
+end
+
+def fun_l14_n868()
+ fun_l15_n333
+end
+
+def fun_l14_n869()
+ fun_l15_n791
+end
+
+def fun_l14_n870()
+ fun_l15_n401
+end
+
+def fun_l14_n871()
+ fun_l15_n289
+end
+
+def fun_l14_n872()
+ fun_l15_n376
+end
+
+def fun_l14_n873()
+ fun_l15_n825
+end
+
+def fun_l14_n874()
+ fun_l15_n233
+end
+
+def fun_l14_n875()
+ fun_l15_n742
+end
+
+def fun_l14_n876()
+ fun_l15_n308
+end
+
+def fun_l14_n877()
+ fun_l15_n793
+end
+
+def fun_l14_n878()
+ fun_l15_n937
+end
+
+def fun_l14_n879()
+ fun_l15_n469
+end
+
+def fun_l14_n880()
+ fun_l15_n129
+end
+
+def fun_l14_n881()
+ fun_l15_n221
+end
+
+def fun_l14_n882()
+ fun_l15_n900
+end
+
+def fun_l14_n883()
+ fun_l15_n548
+end
+
+def fun_l14_n884()
+ fun_l15_n782
+end
+
+def fun_l14_n885()
+ fun_l15_n99
+end
+
+def fun_l14_n886()
+ fun_l15_n33
+end
+
+def fun_l14_n887()
+ fun_l15_n139
+end
+
+def fun_l14_n888()
+ fun_l15_n832
+end
+
+def fun_l14_n889()
+ fun_l15_n24
+end
+
+def fun_l14_n890()
+ fun_l15_n342
+end
+
+def fun_l14_n891()
+ fun_l15_n329
+end
+
+def fun_l14_n892()
+ fun_l15_n706
+end
+
+def fun_l14_n893()
+ fun_l15_n873
+end
+
+def fun_l14_n894()
+ fun_l15_n776
+end
+
+def fun_l14_n895()
+ fun_l15_n799
+end
+
+def fun_l14_n896()
+ fun_l15_n560
+end
+
+def fun_l14_n897()
+ fun_l15_n372
+end
+
+def fun_l14_n898()
+ fun_l15_n370
+end
+
+def fun_l14_n899()
+ fun_l15_n385
+end
+
+def fun_l14_n900()
+ fun_l15_n648
+end
+
+def fun_l14_n901()
+ fun_l15_n376
+end
+
+def fun_l14_n902()
+ fun_l15_n527
+end
+
+def fun_l14_n903()
+ fun_l15_n190
+end
+
+def fun_l14_n904()
+ fun_l15_n633
+end
+
+def fun_l14_n905()
+ fun_l15_n684
+end
+
+def fun_l14_n906()
+ fun_l15_n8
+end
+
+def fun_l14_n907()
+ fun_l15_n814
+end
+
+def fun_l14_n908()
+ fun_l15_n50
+end
+
+def fun_l14_n909()
+ fun_l15_n646
+end
+
+def fun_l14_n910()
+ fun_l15_n442
+end
+
+def fun_l14_n911()
+ fun_l15_n514
+end
+
+def fun_l14_n912()
+ fun_l15_n137
+end
+
+def fun_l14_n913()
+ fun_l15_n126
+end
+
+def fun_l14_n914()
+ fun_l15_n266
+end
+
+def fun_l14_n915()
+ fun_l15_n479
+end
+
+def fun_l14_n916()
+ fun_l15_n985
+end
+
+def fun_l14_n917()
+ fun_l15_n88
+end
+
+def fun_l14_n918()
+ fun_l15_n438
+end
+
+def fun_l14_n919()
+ fun_l15_n347
+end
+
+def fun_l14_n920()
+ fun_l15_n215
+end
+
+def fun_l14_n921()
+ fun_l15_n220
+end
+
+def fun_l14_n922()
+ fun_l15_n507
+end
+
+def fun_l14_n923()
+ fun_l15_n501
+end
+
+def fun_l14_n924()
+ fun_l15_n955
+end
+
+def fun_l14_n925()
+ fun_l15_n59
+end
+
+def fun_l14_n926()
+ fun_l15_n850
+end
+
+def fun_l14_n927()
+ fun_l15_n447
+end
+
+def fun_l14_n928()
+ fun_l15_n298
+end
+
+def fun_l14_n929()
+ fun_l15_n173
+end
+
+def fun_l14_n930()
+ fun_l15_n216
+end
+
+def fun_l14_n931()
+ fun_l15_n594
+end
+
+def fun_l14_n932()
+ fun_l15_n662
+end
+
+def fun_l14_n933()
+ fun_l15_n818
+end
+
+def fun_l14_n934()
+ fun_l15_n783
+end
+
+def fun_l14_n935()
+ fun_l15_n776
+end
+
+def fun_l14_n936()
+ fun_l15_n570
+end
+
+def fun_l14_n937()
+ fun_l15_n495
+end
+
+def fun_l14_n938()
+ fun_l15_n139
+end
+
+def fun_l14_n939()
+ fun_l15_n657
+end
+
+def fun_l14_n940()
+ fun_l15_n773
+end
+
+def fun_l14_n941()
+ fun_l15_n228
+end
+
+def fun_l14_n942()
+ fun_l15_n912
+end
+
+def fun_l14_n943()
+ fun_l15_n837
+end
+
+def fun_l14_n944()
+ fun_l15_n925
+end
+
+def fun_l14_n945()
+ fun_l15_n247
+end
+
+def fun_l14_n946()
+ fun_l15_n890
+end
+
+def fun_l14_n947()
+ fun_l15_n12
+end
+
+def fun_l14_n948()
+ fun_l15_n196
+end
+
+def fun_l14_n949()
+ fun_l15_n887
+end
+
+def fun_l14_n950()
+ fun_l15_n0
+end
+
+def fun_l14_n951()
+ fun_l15_n475
+end
+
+def fun_l14_n952()
+ fun_l15_n548
+end
+
+def fun_l14_n953()
+ fun_l15_n184
+end
+
+def fun_l14_n954()
+ fun_l15_n89
+end
+
+def fun_l14_n955()
+ fun_l15_n604
+end
+
+def fun_l14_n956()
+ fun_l15_n375
+end
+
+def fun_l14_n957()
+ fun_l15_n222
+end
+
+def fun_l14_n958()
+ fun_l15_n629
+end
+
+def fun_l14_n959()
+ fun_l15_n371
+end
+
+def fun_l14_n960()
+ fun_l15_n233
+end
+
+def fun_l14_n961()
+ fun_l15_n268
+end
+
+def fun_l14_n962()
+ fun_l15_n43
+end
+
+def fun_l14_n963()
+ fun_l15_n824
+end
+
+def fun_l14_n964()
+ fun_l15_n574
+end
+
+def fun_l14_n965()
+ fun_l15_n617
+end
+
+def fun_l14_n966()
+ fun_l15_n959
+end
+
+def fun_l14_n967()
+ fun_l15_n757
+end
+
+def fun_l14_n968()
+ fun_l15_n76
+end
+
+def fun_l14_n969()
+ fun_l15_n312
+end
+
+def fun_l14_n970()
+ fun_l15_n895
+end
+
+def fun_l14_n971()
+ fun_l15_n356
+end
+
+def fun_l14_n972()
+ fun_l15_n938
+end
+
+def fun_l14_n973()
+ fun_l15_n233
+end
+
+def fun_l14_n974()
+ fun_l15_n723
+end
+
+def fun_l14_n975()
+ fun_l15_n102
+end
+
+def fun_l14_n976()
+ fun_l15_n8
+end
+
+def fun_l14_n977()
+ fun_l15_n840
+end
+
+def fun_l14_n978()
+ fun_l15_n539
+end
+
+def fun_l14_n979()
+ fun_l15_n936
+end
+
+def fun_l14_n980()
+ fun_l15_n7
+end
+
+def fun_l14_n981()
+ fun_l15_n259
+end
+
+def fun_l14_n982()
+ fun_l15_n680
+end
+
+def fun_l14_n983()
+ fun_l15_n16
+end
+
+def fun_l14_n984()
+ fun_l15_n278
+end
+
+def fun_l14_n985()
+ fun_l15_n951
+end
+
+def fun_l14_n986()
+ fun_l15_n940
+end
+
+def fun_l14_n987()
+ fun_l15_n463
+end
+
+def fun_l14_n988()
+ fun_l15_n54
+end
+
+def fun_l14_n989()
+ fun_l15_n117
+end
+
+def fun_l14_n990()
+ fun_l15_n342
+end
+
+def fun_l14_n991()
+ fun_l15_n345
+end
+
+def fun_l14_n992()
+ fun_l15_n135
+end
+
+def fun_l14_n993()
+ fun_l15_n397
+end
+
+def fun_l14_n994()
+ fun_l15_n406
+end
+
+def fun_l14_n995()
+ fun_l15_n687
+end
+
+def fun_l14_n996()
+ fun_l15_n506
+end
+
+def fun_l14_n997()
+ fun_l15_n406
+end
+
+def fun_l14_n998()
+ fun_l15_n305
+end
+
+def fun_l14_n999()
+ fun_l15_n619
+end
+
+def fun_l15_n0()
+ fun_l16_n214
+end
+
+def fun_l15_n1()
+ fun_l16_n640
+end
+
+def fun_l15_n2()
+ fun_l16_n129
+end
+
+def fun_l15_n3()
+ fun_l16_n883
+end
+
+def fun_l15_n4()
+ fun_l16_n253
+end
+
+def fun_l15_n5()
+ fun_l16_n426
+end
+
+def fun_l15_n6()
+ fun_l16_n969
+end
+
+def fun_l15_n7()
+ fun_l16_n728
+end
+
+def fun_l15_n8()
+ fun_l16_n30
+end
+
+def fun_l15_n9()
+ fun_l16_n337
+end
+
+def fun_l15_n10()
+ fun_l16_n601
+end
+
+def fun_l15_n11()
+ fun_l16_n736
+end
+
+def fun_l15_n12()
+ fun_l16_n905
+end
+
+def fun_l15_n13()
+ fun_l16_n303
+end
+
+def fun_l15_n14()
+ fun_l16_n778
+end
+
+def fun_l15_n15()
+ fun_l16_n92
+end
+
+def fun_l15_n16()
+ fun_l16_n184
+end
+
+def fun_l15_n17()
+ fun_l16_n196
+end
+
+def fun_l15_n18()
+ fun_l16_n68
+end
+
+def fun_l15_n19()
+ fun_l16_n941
+end
+
+def fun_l15_n20()
+ fun_l16_n374
+end
+
+def fun_l15_n21()
+ fun_l16_n680
+end
+
+def fun_l15_n22()
+ fun_l16_n424
+end
+
+def fun_l15_n23()
+ fun_l16_n701
+end
+
+def fun_l15_n24()
+ fun_l16_n211
+end
+
+def fun_l15_n25()
+ fun_l16_n944
+end
+
+def fun_l15_n26()
+ fun_l16_n112
+end
+
+def fun_l15_n27()
+ fun_l16_n219
+end
+
+def fun_l15_n28()
+ fun_l16_n917
+end
+
+def fun_l15_n29()
+ fun_l16_n1
+end
+
+def fun_l15_n30()
+ fun_l16_n178
+end
+
+def fun_l15_n31()
+ fun_l16_n978
+end
+
+def fun_l15_n32()
+ fun_l16_n852
+end
+
+def fun_l15_n33()
+ fun_l16_n633
+end
+
+def fun_l15_n34()
+ fun_l16_n373
+end
+
+def fun_l15_n35()
+ fun_l16_n766
+end
+
+def fun_l15_n36()
+ fun_l16_n324
+end
+
+def fun_l15_n37()
+ fun_l16_n600
+end
+
+def fun_l15_n38()
+ fun_l16_n835
+end
+
+def fun_l15_n39()
+ fun_l16_n518
+end
+
+def fun_l15_n40()
+ fun_l16_n916
+end
+
+def fun_l15_n41()
+ fun_l16_n557
+end
+
+def fun_l15_n42()
+ fun_l16_n401
+end
+
+def fun_l15_n43()
+ fun_l16_n162
+end
+
+def fun_l15_n44()
+ fun_l16_n593
+end
+
+def fun_l15_n45()
+ fun_l16_n615
+end
+
+def fun_l15_n46()
+ fun_l16_n174
+end
+
+def fun_l15_n47()
+ fun_l16_n651
+end
+
+def fun_l15_n48()
+ fun_l16_n168
+end
+
+def fun_l15_n49()
+ fun_l16_n139
+end
+
+def fun_l15_n50()
+ fun_l16_n791
+end
+
+def fun_l15_n51()
+ fun_l16_n1
+end
+
+def fun_l15_n52()
+ fun_l16_n220
+end
+
+def fun_l15_n53()
+ fun_l16_n375
+end
+
+def fun_l15_n54()
+ fun_l16_n530
+end
+
+def fun_l15_n55()
+ fun_l16_n27
+end
+
+def fun_l15_n56()
+ fun_l16_n400
+end
+
+def fun_l15_n57()
+ fun_l16_n489
+end
+
+def fun_l15_n58()
+ fun_l16_n716
+end
+
+def fun_l15_n59()
+ fun_l16_n956
+end
+
+def fun_l15_n60()
+ fun_l16_n147
+end
+
+def fun_l15_n61()
+ fun_l16_n901
+end
+
+def fun_l15_n62()
+ fun_l16_n430
+end
+
+def fun_l15_n63()
+ fun_l16_n161
+end
+
+def fun_l15_n64()
+ fun_l16_n823
+end
+
+def fun_l15_n65()
+ fun_l16_n20
+end
+
+def fun_l15_n66()
+ fun_l16_n767
+end
+
+def fun_l15_n67()
+ fun_l16_n643
+end
+
+def fun_l15_n68()
+ fun_l16_n152
+end
+
+def fun_l15_n69()
+ fun_l16_n54
+end
+
+def fun_l15_n70()
+ fun_l16_n691
+end
+
+def fun_l15_n71()
+ fun_l16_n349
+end
+
+def fun_l15_n72()
+ fun_l16_n9
+end
+
+def fun_l15_n73()
+ fun_l16_n410
+end
+
+def fun_l15_n74()
+ fun_l16_n173
+end
+
+def fun_l15_n75()
+ fun_l16_n187
+end
+
+def fun_l15_n76()
+ fun_l16_n224
+end
+
+def fun_l15_n77()
+ fun_l16_n482
+end
+
+def fun_l15_n78()
+ fun_l16_n230
+end
+
+def fun_l15_n79()
+ fun_l16_n599
+end
+
+def fun_l15_n80()
+ fun_l16_n76
+end
+
+def fun_l15_n81()
+ fun_l16_n343
+end
+
+def fun_l15_n82()
+ fun_l16_n734
+end
+
+def fun_l15_n83()
+ fun_l16_n41
+end
+
+def fun_l15_n84()
+ fun_l16_n338
+end
+
+def fun_l15_n85()
+ fun_l16_n593
+end
+
+def fun_l15_n86()
+ fun_l16_n596
+end
+
+def fun_l15_n87()
+ fun_l16_n610
+end
+
+def fun_l15_n88()
+ fun_l16_n760
+end
+
+def fun_l15_n89()
+ fun_l16_n766
+end
+
+def fun_l15_n90()
+ fun_l16_n946
+end
+
+def fun_l15_n91()
+ fun_l16_n205
+end
+
+def fun_l15_n92()
+ fun_l16_n434
+end
+
+def fun_l15_n93()
+ fun_l16_n507
+end
+
+def fun_l15_n94()
+ fun_l16_n995
+end
+
+def fun_l15_n95()
+ fun_l16_n744
+end
+
+def fun_l15_n96()
+ fun_l16_n706
+end
+
+def fun_l15_n97()
+ fun_l16_n270
+end
+
+def fun_l15_n98()
+ fun_l16_n874
+end
+
+def fun_l15_n99()
+ fun_l16_n18
+end
+
+def fun_l15_n100()
+ fun_l16_n685
+end
+
+def fun_l15_n101()
+ fun_l16_n344
+end
+
+def fun_l15_n102()
+ fun_l16_n265
+end
+
+def fun_l15_n103()
+ fun_l16_n44
+end
+
+def fun_l15_n104()
+ fun_l16_n730
+end
+
+def fun_l15_n105()
+ fun_l16_n314
+end
+
+def fun_l15_n106()
+ fun_l16_n878
+end
+
+def fun_l15_n107()
+ fun_l16_n877
+end
+
+def fun_l15_n108()
+ fun_l16_n237
+end
+
+def fun_l15_n109()
+ fun_l16_n666
+end
+
+def fun_l15_n110()
+ fun_l16_n469
+end
+
+def fun_l15_n111()
+ fun_l16_n925
+end
+
+def fun_l15_n112()
+ fun_l16_n630
+end
+
+def fun_l15_n113()
+ fun_l16_n517
+end
+
+def fun_l15_n114()
+ fun_l16_n550
+end
+
+def fun_l15_n115()
+ fun_l16_n384
+end
+
+def fun_l15_n116()
+ fun_l16_n976
+end
+
+def fun_l15_n117()
+ fun_l16_n702
+end
+
+def fun_l15_n118()
+ fun_l16_n677
+end
+
+def fun_l15_n119()
+ fun_l16_n737
+end
+
+def fun_l15_n120()
+ fun_l16_n380
+end
+
+def fun_l15_n121()
+ fun_l16_n635
+end
+
+def fun_l15_n122()
+ fun_l16_n112
+end
+
+def fun_l15_n123()
+ fun_l16_n779
+end
+
+def fun_l15_n124()
+ fun_l16_n853
+end
+
+def fun_l15_n125()
+ fun_l16_n697
+end
+
+def fun_l15_n126()
+ fun_l16_n289
+end
+
+def fun_l15_n127()
+ fun_l16_n701
+end
+
+def fun_l15_n128()
+ fun_l16_n867
+end
+
+def fun_l15_n129()
+ fun_l16_n537
+end
+
+def fun_l15_n130()
+ fun_l16_n735
+end
+
+def fun_l15_n131()
+ fun_l16_n285
+end
+
+def fun_l15_n132()
+ fun_l16_n196
+end
+
+def fun_l15_n133()
+ fun_l16_n137
+end
+
+def fun_l15_n134()
+ fun_l16_n937
+end
+
+def fun_l15_n135()
+ fun_l16_n285
+end
+
+def fun_l15_n136()
+ fun_l16_n566
+end
+
+def fun_l15_n137()
+ fun_l16_n163
+end
+
+def fun_l15_n138()
+ fun_l16_n223
+end
+
+def fun_l15_n139()
+ fun_l16_n373
+end
+
+def fun_l15_n140()
+ fun_l16_n16
+end
+
+def fun_l15_n141()
+ fun_l16_n539
+end
+
+def fun_l15_n142()
+ fun_l16_n696
+end
+
+def fun_l15_n143()
+ fun_l16_n735
+end
+
+def fun_l15_n144()
+ fun_l16_n81
+end
+
+def fun_l15_n145()
+ fun_l16_n102
+end
+
+def fun_l15_n146()
+ fun_l16_n658
+end
+
+def fun_l15_n147()
+ fun_l16_n858
+end
+
+def fun_l15_n148()
+ fun_l16_n398
+end
+
+def fun_l15_n149()
+ fun_l16_n122
+end
+
+def fun_l15_n150()
+ fun_l16_n712
+end
+
+def fun_l15_n151()
+ fun_l16_n888
+end
+
+def fun_l15_n152()
+ fun_l16_n537
+end
+
+def fun_l15_n153()
+ fun_l16_n190
+end
+
+def fun_l15_n154()
+ fun_l16_n164
+end
+
+def fun_l15_n155()
+ fun_l16_n351
+end
+
+def fun_l15_n156()
+ fun_l16_n641
+end
+
+def fun_l15_n157()
+ fun_l16_n300
+end
+
+def fun_l15_n158()
+ fun_l16_n177
+end
+
+def fun_l15_n159()
+ fun_l16_n634
+end
+
+def fun_l15_n160()
+ fun_l16_n475
+end
+
+def fun_l15_n161()
+ fun_l16_n843
+end
+
+def fun_l15_n162()
+ fun_l16_n262
+end
+
+def fun_l15_n163()
+ fun_l16_n471
+end
+
+def fun_l15_n164()
+ fun_l16_n229
+end
+
+def fun_l15_n165()
+ fun_l16_n374
+end
+
+def fun_l15_n166()
+ fun_l16_n920
+end
+
+def fun_l15_n167()
+ fun_l16_n194
+end
+
+def fun_l15_n168()
+ fun_l16_n369
+end
+
+def fun_l15_n169()
+ fun_l16_n41
+end
+
+def fun_l15_n170()
+ fun_l16_n339
+end
+
+def fun_l15_n171()
+ fun_l16_n152
+end
+
+def fun_l15_n172()
+ fun_l16_n337
+end
+
+def fun_l15_n173()
+ fun_l16_n906
+end
+
+def fun_l15_n174()
+ fun_l16_n13
+end
+
+def fun_l15_n175()
+ fun_l16_n343
+end
+
+def fun_l15_n176()
+ fun_l16_n116
+end
+
+def fun_l15_n177()
+ fun_l16_n722
+end
+
+def fun_l15_n178()
+ fun_l16_n62
+end
+
+def fun_l15_n179()
+ fun_l16_n12
+end
+
+def fun_l15_n180()
+ fun_l16_n177
+end
+
+def fun_l15_n181()
+ fun_l16_n632
+end
+
+def fun_l15_n182()
+ fun_l16_n990
+end
+
+def fun_l15_n183()
+ fun_l16_n749
+end
+
+def fun_l15_n184()
+ fun_l16_n368
+end
+
+def fun_l15_n185()
+ fun_l16_n881
+end
+
+def fun_l15_n186()
+ fun_l16_n760
+end
+
+def fun_l15_n187()
+ fun_l16_n740
+end
+
+def fun_l15_n188()
+ fun_l16_n379
+end
+
+def fun_l15_n189()
+ fun_l16_n194
+end
+
+def fun_l15_n190()
+ fun_l16_n282
+end
+
+def fun_l15_n191()
+ fun_l16_n520
+end
+
+def fun_l15_n192()
+ fun_l16_n113
+end
+
+def fun_l15_n193()
+ fun_l16_n470
+end
+
+def fun_l15_n194()
+ fun_l16_n303
+end
+
+def fun_l15_n195()
+ fun_l16_n712
+end
+
+def fun_l15_n196()
+ fun_l16_n215
+end
+
+def fun_l15_n197()
+ fun_l16_n121
+end
+
+def fun_l15_n198()
+ fun_l16_n281
+end
+
+def fun_l15_n199()
+ fun_l16_n702
+end
+
+def fun_l15_n200()
+ fun_l16_n727
+end
+
+def fun_l15_n201()
+ fun_l16_n856
+end
+
+def fun_l15_n202()
+ fun_l16_n368
+end
+
+def fun_l15_n203()
+ fun_l16_n252
+end
+
+def fun_l15_n204()
+ fun_l16_n86
+end
+
+def fun_l15_n205()
+ fun_l16_n323
+end
+
+def fun_l15_n206()
+ fun_l16_n749
+end
+
+def fun_l15_n207()
+ fun_l16_n728
+end
+
+def fun_l15_n208()
+ fun_l16_n195
+end
+
+def fun_l15_n209()
+ fun_l16_n141
+end
+
+def fun_l15_n210()
+ fun_l16_n685
+end
+
+def fun_l15_n211()
+ fun_l16_n855
+end
+
+def fun_l15_n212()
+ fun_l16_n401
+end
+
+def fun_l15_n213()
+ fun_l16_n415
+end
+
+def fun_l15_n214()
+ fun_l16_n349
+end
+
+def fun_l15_n215()
+ fun_l16_n45
+end
+
+def fun_l15_n216()
+ fun_l16_n534
+end
+
+def fun_l15_n217()
+ fun_l16_n705
+end
+
+def fun_l15_n218()
+ fun_l16_n97
+end
+
+def fun_l15_n219()
+ fun_l16_n828
+end
+
+def fun_l15_n220()
+ fun_l16_n698
+end
+
+def fun_l15_n221()
+ fun_l16_n505
+end
+
+def fun_l15_n222()
+ fun_l16_n100
+end
+
+def fun_l15_n223()
+ fun_l16_n710
+end
+
+def fun_l15_n224()
+ fun_l16_n883
+end
+
+def fun_l15_n225()
+ fun_l16_n503
+end
+
+def fun_l15_n226()
+ fun_l16_n583
+end
+
+def fun_l15_n227()
+ fun_l16_n269
+end
+
+def fun_l15_n228()
+ fun_l16_n570
+end
+
+def fun_l15_n229()
+ fun_l16_n877
+end
+
+def fun_l15_n230()
+ fun_l16_n906
+end
+
+def fun_l15_n231()
+ fun_l16_n123
+end
+
+def fun_l15_n232()
+ fun_l16_n626
+end
+
+def fun_l15_n233()
+ fun_l16_n911
+end
+
+def fun_l15_n234()
+ fun_l16_n741
+end
+
+def fun_l15_n235()
+ fun_l16_n255
+end
+
+def fun_l15_n236()
+ fun_l16_n499
+end
+
+def fun_l15_n237()
+ fun_l16_n998
+end
+
+def fun_l15_n238()
+ fun_l16_n156
+end
+
+def fun_l15_n239()
+ fun_l16_n677
+end
+
+def fun_l15_n240()
+ fun_l16_n551
+end
+
+def fun_l15_n241()
+ fun_l16_n906
+end
+
+def fun_l15_n242()
+ fun_l16_n146
+end
+
+def fun_l15_n243()
+ fun_l16_n372
+end
+
+def fun_l15_n244()
+ fun_l16_n867
+end
+
+def fun_l15_n245()
+ fun_l16_n232
+end
+
+def fun_l15_n246()
+ fun_l16_n952
+end
+
+def fun_l15_n247()
+ fun_l16_n256
+end
+
+def fun_l15_n248()
+ fun_l16_n263
+end
+
+def fun_l15_n249()
+ fun_l16_n642
+end
+
+def fun_l15_n250()
+ fun_l16_n165
+end
+
+def fun_l15_n251()
+ fun_l16_n147
+end
+
+def fun_l15_n252()
+ fun_l16_n182
+end
+
+def fun_l15_n253()
+ fun_l16_n346
+end
+
+def fun_l15_n254()
+ fun_l16_n263
+end
+
+def fun_l15_n255()
+ fun_l16_n512
+end
+
+def fun_l15_n256()
+ fun_l16_n504
+end
+
+def fun_l15_n257()
+ fun_l16_n671
+end
+
+def fun_l15_n258()
+ fun_l16_n219
+end
+
+def fun_l15_n259()
+ fun_l16_n878
+end
+
+def fun_l15_n260()
+ fun_l16_n754
+end
+
+def fun_l15_n261()
+ fun_l16_n976
+end
+
+def fun_l15_n262()
+ fun_l16_n756
+end
+
+def fun_l15_n263()
+ fun_l16_n840
+end
+
+def fun_l15_n264()
+ fun_l16_n320
+end
+
+def fun_l15_n265()
+ fun_l16_n447
+end
+
+def fun_l15_n266()
+ fun_l16_n179
+end
+
+def fun_l15_n267()
+ fun_l16_n669
+end
+
+def fun_l15_n268()
+ fun_l16_n279
+end
+
+def fun_l15_n269()
+ fun_l16_n919
+end
+
+def fun_l15_n270()
+ fun_l16_n55
+end
+
+def fun_l15_n271()
+ fun_l16_n713
+end
+
+def fun_l15_n272()
+ fun_l16_n140
+end
+
+def fun_l15_n273()
+ fun_l16_n738
+end
+
+def fun_l15_n274()
+ fun_l16_n534
+end
+
+def fun_l15_n275()
+ fun_l16_n739
+end
+
+def fun_l15_n276()
+ fun_l16_n733
+end
+
+def fun_l15_n277()
+ fun_l16_n792
+end
+
+def fun_l15_n278()
+ fun_l16_n719
+end
+
+def fun_l15_n279()
+ fun_l16_n946
+end
+
+def fun_l15_n280()
+ fun_l16_n942
+end
+
+def fun_l15_n281()
+ fun_l16_n547
+end
+
+def fun_l15_n282()
+ fun_l16_n961
+end
+
+def fun_l15_n283()
+ fun_l16_n382
+end
+
+def fun_l15_n284()
+ fun_l16_n642
+end
+
+def fun_l15_n285()
+ fun_l16_n761
+end
+
+def fun_l15_n286()
+ fun_l16_n999
+end
+
+def fun_l15_n287()
+ fun_l16_n827
+end
+
+def fun_l15_n288()
+ fun_l16_n364
+end
+
+def fun_l15_n289()
+ fun_l16_n588
+end
+
+def fun_l15_n290()
+ fun_l16_n3
+end
+
+def fun_l15_n291()
+ fun_l16_n741
+end
+
+def fun_l15_n292()
+ fun_l16_n839
+end
+
+def fun_l15_n293()
+ fun_l16_n889
+end
+
+def fun_l15_n294()
+ fun_l16_n106
+end
+
+def fun_l15_n295()
+ fun_l16_n616
+end
+
+def fun_l15_n296()
+ fun_l16_n124
+end
+
+def fun_l15_n297()
+ fun_l16_n691
+end
+
+def fun_l15_n298()
+ fun_l16_n135
+end
+
+def fun_l15_n299()
+ fun_l16_n654
+end
+
+def fun_l15_n300()
+ fun_l16_n706
+end
+
+def fun_l15_n301()
+ fun_l16_n957
+end
+
+def fun_l15_n302()
+ fun_l16_n213
+end
+
+def fun_l15_n303()
+ fun_l16_n340
+end
+
+def fun_l15_n304()
+ fun_l16_n126
+end
+
+def fun_l15_n305()
+ fun_l16_n807
+end
+
+def fun_l15_n306()
+ fun_l16_n901
+end
+
+def fun_l15_n307()
+ fun_l16_n371
+end
+
+def fun_l15_n308()
+ fun_l16_n904
+end
+
+def fun_l15_n309()
+ fun_l16_n475
+end
+
+def fun_l15_n310()
+ fun_l16_n863
+end
+
+def fun_l15_n311()
+ fun_l16_n37
+end
+
+def fun_l15_n312()
+ fun_l16_n315
+end
+
+def fun_l15_n313()
+ fun_l16_n527
+end
+
+def fun_l15_n314()
+ fun_l16_n549
+end
+
+def fun_l15_n315()
+ fun_l16_n351
+end
+
+def fun_l15_n316()
+ fun_l16_n193
+end
+
+def fun_l15_n317()
+ fun_l16_n395
+end
+
+def fun_l15_n318()
+ fun_l16_n373
+end
+
+def fun_l15_n319()
+ fun_l16_n142
+end
+
+def fun_l15_n320()
+ fun_l16_n250
+end
+
+def fun_l15_n321()
+ fun_l16_n544
+end
+
+def fun_l15_n322()
+ fun_l16_n446
+end
+
+def fun_l15_n323()
+ fun_l16_n375
+end
+
+def fun_l15_n324()
+ fun_l16_n832
+end
+
+def fun_l15_n325()
+ fun_l16_n987
+end
+
+def fun_l15_n326()
+ fun_l16_n539
+end
+
+def fun_l15_n327()
+ fun_l16_n293
+end
+
+def fun_l15_n328()
+ fun_l16_n128
+end
+
+def fun_l15_n329()
+ fun_l16_n228
+end
+
+def fun_l15_n330()
+ fun_l16_n952
+end
+
+def fun_l15_n331()
+ fun_l16_n116
+end
+
+def fun_l15_n332()
+ fun_l16_n823
+end
+
+def fun_l15_n333()
+ fun_l16_n933
+end
+
+def fun_l15_n334()
+ fun_l16_n252
+end
+
+def fun_l15_n335()
+ fun_l16_n140
+end
+
+def fun_l15_n336()
+ fun_l16_n245
+end
+
+def fun_l15_n337()
+ fun_l16_n822
+end
+
+def fun_l15_n338()
+ fun_l16_n389
+end
+
+def fun_l15_n339()
+ fun_l16_n824
+end
+
+def fun_l15_n340()
+ fun_l16_n507
+end
+
+def fun_l15_n341()
+ fun_l16_n153
+end
+
+def fun_l15_n342()
+ fun_l16_n661
+end
+
+def fun_l15_n343()
+ fun_l16_n633
+end
+
+def fun_l15_n344()
+ fun_l16_n478
+end
+
+def fun_l15_n345()
+ fun_l16_n423
+end
+
+def fun_l15_n346()
+ fun_l16_n425
+end
+
+def fun_l15_n347()
+ fun_l16_n168
+end
+
+def fun_l15_n348()
+ fun_l16_n426
+end
+
+def fun_l15_n349()
+ fun_l16_n85
+end
+
+def fun_l15_n350()
+ fun_l16_n35
+end
+
+def fun_l15_n351()
+ fun_l16_n796
+end
+
+def fun_l15_n352()
+ fun_l16_n295
+end
+
+def fun_l15_n353()
+ fun_l16_n564
+end
+
+def fun_l15_n354()
+ fun_l16_n273
+end
+
+def fun_l15_n355()
+ fun_l16_n821
+end
+
+def fun_l15_n356()
+ fun_l16_n504
+end
+
+def fun_l15_n357()
+ fun_l16_n911
+end
+
+def fun_l15_n358()
+ fun_l16_n277
+end
+
+def fun_l15_n359()
+ fun_l16_n749
+end
+
+def fun_l15_n360()
+ fun_l16_n886
+end
+
+def fun_l15_n361()
+ fun_l16_n165
+end
+
+def fun_l15_n362()
+ fun_l16_n353
+end
+
+def fun_l15_n363()
+ fun_l16_n309
+end
+
+def fun_l15_n364()
+ fun_l16_n853
+end
+
+def fun_l15_n365()
+ fun_l16_n981
+end
+
+def fun_l15_n366()
+ fun_l16_n429
+end
+
+def fun_l15_n367()
+ fun_l16_n114
+end
+
+def fun_l15_n368()
+ fun_l16_n649
+end
+
+def fun_l15_n369()
+ fun_l16_n966
+end
+
+def fun_l15_n370()
+ fun_l16_n356
+end
+
+def fun_l15_n371()
+ fun_l16_n364
+end
+
+def fun_l15_n372()
+ fun_l16_n12
+end
+
+def fun_l15_n373()
+ fun_l16_n969
+end
+
+def fun_l15_n374()
+ fun_l16_n705
+end
+
+def fun_l15_n375()
+ fun_l16_n194
+end
+
+def fun_l15_n376()
+ fun_l16_n487
+end
+
+def fun_l15_n377()
+ fun_l16_n148
+end
+
+def fun_l15_n378()
+ fun_l16_n419
+end
+
+def fun_l15_n379()
+ fun_l16_n686
+end
+
+def fun_l15_n380()
+ fun_l16_n552
+end
+
+def fun_l15_n381()
+ fun_l16_n630
+end
+
+def fun_l15_n382()
+ fun_l16_n509
+end
+
+def fun_l15_n383()
+ fun_l16_n251
+end
+
+def fun_l15_n384()
+ fun_l16_n506
+end
+
+def fun_l15_n385()
+ fun_l16_n317
+end
+
+def fun_l15_n386()
+ fun_l16_n881
+end
+
+def fun_l15_n387()
+ fun_l16_n12
+end
+
+def fun_l15_n388()
+ fun_l16_n686
+end
+
+def fun_l15_n389()
+ fun_l16_n277
+end
+
+def fun_l15_n390()
+ fun_l16_n174
+end
+
+def fun_l15_n391()
+ fun_l16_n799
+end
+
+def fun_l15_n392()
+ fun_l16_n682
+end
+
+def fun_l15_n393()
+ fun_l16_n102
+end
+
+def fun_l15_n394()
+ fun_l16_n127
+end
+
+def fun_l15_n395()
+ fun_l16_n110
+end
+
+def fun_l15_n396()
+ fun_l16_n331
+end
+
+def fun_l15_n397()
+ fun_l16_n165
+end
+
+def fun_l15_n398()
+ fun_l16_n360
+end
+
+def fun_l15_n399()
+ fun_l16_n622
+end
+
+def fun_l15_n400()
+ fun_l16_n928
+end
+
+def fun_l15_n401()
+ fun_l16_n324
+end
+
+def fun_l15_n402()
+ fun_l16_n712
+end
+
+def fun_l15_n403()
+ fun_l16_n250
+end
+
+def fun_l15_n404()
+ fun_l16_n289
+end
+
+def fun_l15_n405()
+ fun_l16_n520
+end
+
+def fun_l15_n406()
+ fun_l16_n445
+end
+
+def fun_l15_n407()
+ fun_l16_n328
+end
+
+def fun_l15_n408()
+ fun_l16_n496
+end
+
+def fun_l15_n409()
+ fun_l16_n614
+end
+
+def fun_l15_n410()
+ fun_l16_n428
+end
+
+def fun_l15_n411()
+ fun_l16_n226
+end
+
+def fun_l15_n412()
+ fun_l16_n450
+end
+
+def fun_l15_n413()
+ fun_l16_n410
+end
+
+def fun_l15_n414()
+ fun_l16_n926
+end
+
+def fun_l15_n415()
+ fun_l16_n353
+end
+
+def fun_l15_n416()
+ fun_l16_n822
+end
+
+def fun_l15_n417()
+ fun_l16_n800
+end
+
+def fun_l15_n418()
+ fun_l16_n577
+end
+
+def fun_l15_n419()
+ fun_l16_n483
+end
+
+def fun_l15_n420()
+ fun_l16_n744
+end
+
+def fun_l15_n421()
+ fun_l16_n314
+end
+
+def fun_l15_n422()
+ fun_l16_n206
+end
+
+def fun_l15_n423()
+ fun_l16_n359
+end
+
+def fun_l15_n424()
+ fun_l16_n371
+end
+
+def fun_l15_n425()
+ fun_l16_n817
+end
+
+def fun_l15_n426()
+ fun_l16_n471
+end
+
+def fun_l15_n427()
+ fun_l16_n681
+end
+
+def fun_l15_n428()
+ fun_l16_n598
+end
+
+def fun_l15_n429()
+ fun_l16_n532
+end
+
+def fun_l15_n430()
+ fun_l16_n173
+end
+
+def fun_l15_n431()
+ fun_l16_n670
+end
+
+def fun_l15_n432()
+ fun_l16_n310
+end
+
+def fun_l15_n433()
+ fun_l16_n376
+end
+
+def fun_l15_n434()
+ fun_l16_n142
+end
+
+def fun_l15_n435()
+ fun_l16_n591
+end
+
+def fun_l15_n436()
+ fun_l16_n313
+end
+
+def fun_l15_n437()
+ fun_l16_n724
+end
+
+def fun_l15_n438()
+ fun_l16_n313
+end
+
+def fun_l15_n439()
+ fun_l16_n238
+end
+
+def fun_l15_n440()
+ fun_l16_n840
+end
+
+def fun_l15_n441()
+ fun_l16_n235
+end
+
+def fun_l15_n442()
+ fun_l16_n720
+end
+
+def fun_l15_n443()
+ fun_l16_n427
+end
+
+def fun_l15_n444()
+ fun_l16_n269
+end
+
+def fun_l15_n445()
+ fun_l16_n557
+end
+
+def fun_l15_n446()
+ fun_l16_n97
+end
+
+def fun_l15_n447()
+ fun_l16_n655
+end
+
+def fun_l15_n448()
+ fun_l16_n723
+end
+
+def fun_l15_n449()
+ fun_l16_n634
+end
+
+def fun_l15_n450()
+ fun_l16_n208
+end
+
+def fun_l15_n451()
+ fun_l16_n130
+end
+
+def fun_l15_n452()
+ fun_l16_n472
+end
+
+def fun_l15_n453()
+ fun_l16_n172
+end
+
+def fun_l15_n454()
+ fun_l16_n323
+end
+
+def fun_l15_n455()
+ fun_l16_n643
+end
+
+def fun_l15_n456()
+ fun_l16_n20
+end
+
+def fun_l15_n457()
+ fun_l16_n721
+end
+
+def fun_l15_n458()
+ fun_l16_n928
+end
+
+def fun_l15_n459()
+ fun_l16_n312
+end
+
+def fun_l15_n460()
+ fun_l16_n767
+end
+
+def fun_l15_n461()
+ fun_l16_n191
+end
+
+def fun_l15_n462()
+ fun_l16_n88
+end
+
+def fun_l15_n463()
+ fun_l16_n782
+end
+
+def fun_l15_n464()
+ fun_l16_n448
+end
+
+def fun_l15_n465()
+ fun_l16_n595
+end
+
+def fun_l15_n466()
+ fun_l16_n545
+end
+
+def fun_l15_n467()
+ fun_l16_n98
+end
+
+def fun_l15_n468()
+ fun_l16_n523
+end
+
+def fun_l15_n469()
+ fun_l16_n548
+end
+
+def fun_l15_n470()
+ fun_l16_n799
+end
+
+def fun_l15_n471()
+ fun_l16_n727
+end
+
+def fun_l15_n472()
+ fun_l16_n342
+end
+
+def fun_l15_n473()
+ fun_l16_n30
+end
+
+def fun_l15_n474()
+ fun_l16_n461
+end
+
+def fun_l15_n475()
+ fun_l16_n249
+end
+
+def fun_l15_n476()
+ fun_l16_n466
+end
+
+def fun_l15_n477()
+ fun_l16_n28
+end
+
+def fun_l15_n478()
+ fun_l16_n845
+end
+
+def fun_l15_n479()
+ fun_l16_n53
+end
+
+def fun_l15_n480()
+ fun_l16_n122
+end
+
+def fun_l15_n481()
+ fun_l16_n264
+end
+
+def fun_l15_n482()
+ fun_l16_n802
+end
+
+def fun_l15_n483()
+ fun_l16_n688
+end
+
+def fun_l15_n484()
+ fun_l16_n656
+end
+
+def fun_l15_n485()
+ fun_l16_n17
+end
+
+def fun_l15_n486()
+ fun_l16_n956
+end
+
+def fun_l15_n487()
+ fun_l16_n649
+end
+
+def fun_l15_n488()
+ fun_l16_n948
+end
+
+def fun_l15_n489()
+ fun_l16_n85
+end
+
+def fun_l15_n490()
+ fun_l16_n411
+end
+
+def fun_l15_n491()
+ fun_l16_n572
+end
+
+def fun_l15_n492()
+ fun_l16_n698
+end
+
+def fun_l15_n493()
+ fun_l16_n767
+end
+
+def fun_l15_n494()
+ fun_l16_n513
+end
+
+def fun_l15_n495()
+ fun_l16_n983
+end
+
+def fun_l15_n496()
+ fun_l16_n763
+end
+
+def fun_l15_n497()
+ fun_l16_n207
+end
+
+def fun_l15_n498()
+ fun_l16_n154
+end
+
+def fun_l15_n499()
+ fun_l16_n152
+end
+
+def fun_l15_n500()
+ fun_l16_n929
+end
+
+def fun_l15_n501()
+ fun_l16_n573
+end
+
+def fun_l15_n502()
+ fun_l16_n97
+end
+
+def fun_l15_n503()
+ fun_l16_n696
+end
+
+def fun_l15_n504()
+ fun_l16_n877
+end
+
+def fun_l15_n505()
+ fun_l16_n401
+end
+
+def fun_l15_n506()
+ fun_l16_n509
+end
+
+def fun_l15_n507()
+ fun_l16_n933
+end
+
+def fun_l15_n508()
+ fun_l16_n946
+end
+
+def fun_l15_n509()
+ fun_l16_n290
+end
+
+def fun_l15_n510()
+ fun_l16_n630
+end
+
+def fun_l15_n511()
+ fun_l16_n279
+end
+
+def fun_l15_n512()
+ fun_l16_n833
+end
+
+def fun_l15_n513()
+ fun_l16_n984
+end
+
+def fun_l15_n514()
+ fun_l16_n82
+end
+
+def fun_l15_n515()
+ fun_l16_n372
+end
+
+def fun_l15_n516()
+ fun_l16_n407
+end
+
+def fun_l15_n517()
+ fun_l16_n801
+end
+
+def fun_l15_n518()
+ fun_l16_n530
+end
+
+def fun_l15_n519()
+ fun_l16_n349
+end
+
+def fun_l15_n520()
+ fun_l16_n633
+end
+
+def fun_l15_n521()
+ fun_l16_n189
+end
+
+def fun_l15_n522()
+ fun_l16_n613
+end
+
+def fun_l15_n523()
+ fun_l16_n335
+end
+
+def fun_l15_n524()
+ fun_l16_n163
+end
+
+def fun_l15_n525()
+ fun_l16_n542
+end
+
+def fun_l15_n526()
+ fun_l16_n454
+end
+
+def fun_l15_n527()
+ fun_l16_n428
+end
+
+def fun_l15_n528()
+ fun_l16_n985
+end
+
+def fun_l15_n529()
+ fun_l16_n414
+end
+
+def fun_l15_n530()
+ fun_l16_n294
+end
+
+def fun_l15_n531()
+ fun_l16_n493
+end
+
+def fun_l15_n532()
+ fun_l16_n467
+end
+
+def fun_l15_n533()
+ fun_l16_n398
+end
+
+def fun_l15_n534()
+ fun_l16_n861
+end
+
+def fun_l15_n535()
+ fun_l16_n219
+end
+
+def fun_l15_n536()
+ fun_l16_n178
+end
+
+def fun_l15_n537()
+ fun_l16_n436
+end
+
+def fun_l15_n538()
+ fun_l16_n821
+end
+
+def fun_l15_n539()
+ fun_l16_n732
+end
+
+def fun_l15_n540()
+ fun_l16_n432
+end
+
+def fun_l15_n541()
+ fun_l16_n32
+end
+
+def fun_l15_n542()
+ fun_l16_n128
+end
+
+def fun_l15_n543()
+ fun_l16_n2
+end
+
+def fun_l15_n544()
+ fun_l16_n117
+end
+
+def fun_l15_n545()
+ fun_l16_n861
+end
+
+def fun_l15_n546()
+ fun_l16_n817
+end
+
+def fun_l15_n547()
+ fun_l16_n833
+end
+
+def fun_l15_n548()
+ fun_l16_n180
+end
+
+def fun_l15_n549()
+ fun_l16_n176
+end
+
+def fun_l15_n550()
+ fun_l16_n772
+end
+
+def fun_l15_n551()
+ fun_l16_n469
+end
+
+def fun_l15_n552()
+ fun_l16_n209
+end
+
+def fun_l15_n553()
+ fun_l16_n200
+end
+
+def fun_l15_n554()
+ fun_l16_n434
+end
+
+def fun_l15_n555()
+ fun_l16_n529
+end
+
+def fun_l15_n556()
+ fun_l16_n847
+end
+
+def fun_l15_n557()
+ fun_l16_n134
+end
+
+def fun_l15_n558()
+ fun_l16_n748
+end
+
+def fun_l15_n559()
+ fun_l16_n153
+end
+
+def fun_l15_n560()
+ fun_l16_n903
+end
+
+def fun_l15_n561()
+ fun_l16_n449
+end
+
+def fun_l15_n562()
+ fun_l16_n267
+end
+
+def fun_l15_n563()
+ fun_l16_n47
+end
+
+def fun_l15_n564()
+ fun_l16_n762
+end
+
+def fun_l15_n565()
+ fun_l16_n932
+end
+
+def fun_l15_n566()
+ fun_l16_n782
+end
+
+def fun_l15_n567()
+ fun_l16_n580
+end
+
+def fun_l15_n568()
+ fun_l16_n172
+end
+
+def fun_l15_n569()
+ fun_l16_n379
+end
+
+def fun_l15_n570()
+ fun_l16_n890
+end
+
+def fun_l15_n571()
+ fun_l16_n257
+end
+
+def fun_l15_n572()
+ fun_l16_n964
+end
+
+def fun_l15_n573()
+ fun_l16_n164
+end
+
+def fun_l15_n574()
+ fun_l16_n606
+end
+
+def fun_l15_n575()
+ fun_l16_n475
+end
+
+def fun_l15_n576()
+ fun_l16_n500
+end
+
+def fun_l15_n577()
+ fun_l16_n65
+end
+
+def fun_l15_n578()
+ fun_l16_n81
+end
+
+def fun_l15_n579()
+ fun_l16_n952
+end
+
+def fun_l15_n580()
+ fun_l16_n524
+end
+
+def fun_l15_n581()
+ fun_l16_n573
+end
+
+def fun_l15_n582()
+ fun_l16_n812
+end
+
+def fun_l15_n583()
+ fun_l16_n498
+end
+
+def fun_l15_n584()
+ fun_l16_n106
+end
+
+def fun_l15_n585()
+ fun_l16_n807
+end
+
+def fun_l15_n586()
+ fun_l16_n70
+end
+
+def fun_l15_n587()
+ fun_l16_n41
+end
+
+def fun_l15_n588()
+ fun_l16_n78
+end
+
+def fun_l15_n589()
+ fun_l16_n235
+end
+
+def fun_l15_n590()
+ fun_l16_n974
+end
+
+def fun_l15_n591()
+ fun_l16_n450
+end
+
+def fun_l15_n592()
+ fun_l16_n191
+end
+
+def fun_l15_n593()
+ fun_l16_n988
+end
+
+def fun_l15_n594()
+ fun_l16_n516
+end
+
+def fun_l15_n595()
+ fun_l16_n7
+end
+
+def fun_l15_n596()
+ fun_l16_n186
+end
+
+def fun_l15_n597()
+ fun_l16_n249
+end
+
+def fun_l15_n598()
+ fun_l16_n832
+end
+
+def fun_l15_n599()
+ fun_l16_n502
+end
+
+def fun_l15_n600()
+ fun_l16_n967
+end
+
+def fun_l15_n601()
+ fun_l16_n930
+end
+
+def fun_l15_n602()
+ fun_l16_n497
+end
+
+def fun_l15_n603()
+ fun_l16_n467
+end
+
+def fun_l15_n604()
+ fun_l16_n742
+end
+
+def fun_l15_n605()
+ fun_l16_n52
+end
+
+def fun_l15_n606()
+ fun_l16_n494
+end
+
+def fun_l15_n607()
+ fun_l16_n604
+end
+
+def fun_l15_n608()
+ fun_l16_n372
+end
+
+def fun_l15_n609()
+ fun_l16_n503
+end
+
+def fun_l15_n610()
+ fun_l16_n853
+end
+
+def fun_l15_n611()
+ fun_l16_n146
+end
+
+def fun_l15_n612()
+ fun_l16_n812
+end
+
+def fun_l15_n613()
+ fun_l16_n235
+end
+
+def fun_l15_n614()
+ fun_l16_n924
+end
+
+def fun_l15_n615()
+ fun_l16_n212
+end
+
+def fun_l15_n616()
+ fun_l16_n332
+end
+
+def fun_l15_n617()
+ fun_l16_n179
+end
+
+def fun_l15_n618()
+ fun_l16_n767
+end
+
+def fun_l15_n619()
+ fun_l16_n46
+end
+
+def fun_l15_n620()
+ fun_l16_n275
+end
+
+def fun_l15_n621()
+ fun_l16_n348
+end
+
+def fun_l15_n622()
+ fun_l16_n136
+end
+
+def fun_l15_n623()
+ fun_l16_n814
+end
+
+def fun_l15_n624()
+ fun_l16_n782
+end
+
+def fun_l15_n625()
+ fun_l16_n692
+end
+
+def fun_l15_n626()
+ fun_l16_n331
+end
+
+def fun_l15_n627()
+ fun_l16_n228
+end
+
+def fun_l15_n628()
+ fun_l16_n249
+end
+
+def fun_l15_n629()
+ fun_l16_n387
+end
+
+def fun_l15_n630()
+ fun_l16_n994
+end
+
+def fun_l15_n631()
+ fun_l16_n219
+end
+
+def fun_l15_n632()
+ fun_l16_n743
+end
+
+def fun_l15_n633()
+ fun_l16_n674
+end
+
+def fun_l15_n634()
+ fun_l16_n411
+end
+
+def fun_l15_n635()
+ fun_l16_n757
+end
+
+def fun_l15_n636()
+ fun_l16_n568
+end
+
+def fun_l15_n637()
+ fun_l16_n323
+end
+
+def fun_l15_n638()
+ fun_l16_n910
+end
+
+def fun_l15_n639()
+ fun_l16_n823
+end
+
+def fun_l15_n640()
+ fun_l16_n942
+end
+
+def fun_l15_n641()
+ fun_l16_n796
+end
+
+def fun_l15_n642()
+ fun_l16_n507
+end
+
+def fun_l15_n643()
+ fun_l16_n72
+end
+
+def fun_l15_n644()
+ fun_l16_n285
+end
+
+def fun_l15_n645()
+ fun_l16_n654
+end
+
+def fun_l15_n646()
+ fun_l16_n361
+end
+
+def fun_l15_n647()
+ fun_l16_n766
+end
+
+def fun_l15_n648()
+ fun_l16_n587
+end
+
+def fun_l15_n649()
+ fun_l16_n99
+end
+
+def fun_l15_n650()
+ fun_l16_n558
+end
+
+def fun_l15_n651()
+ fun_l16_n623
+end
+
+def fun_l15_n652()
+ fun_l16_n428
+end
+
+def fun_l15_n653()
+ fun_l16_n695
+end
+
+def fun_l15_n654()
+ fun_l16_n514
+end
+
+def fun_l15_n655()
+ fun_l16_n159
+end
+
+def fun_l15_n656()
+ fun_l16_n41
+end
+
+def fun_l15_n657()
+ fun_l16_n510
+end
+
+def fun_l15_n658()
+ fun_l16_n26
+end
+
+def fun_l15_n659()
+ fun_l16_n947
+end
+
+def fun_l15_n660()
+ fun_l16_n766
+end
+
+def fun_l15_n661()
+ fun_l16_n470
+end
+
+def fun_l15_n662()
+ fun_l16_n46
+end
+
+def fun_l15_n663()
+ fun_l16_n499
+end
+
+def fun_l15_n664()
+ fun_l16_n593
+end
+
+def fun_l15_n665()
+ fun_l16_n803
+end
+
+def fun_l15_n666()
+ fun_l16_n321
+end
+
+def fun_l15_n667()
+ fun_l16_n165
+end
+
+def fun_l15_n668()
+ fun_l16_n762
+end
+
+def fun_l15_n669()
+ fun_l16_n800
+end
+
+def fun_l15_n670()
+ fun_l16_n530
+end
+
+def fun_l15_n671()
+ fun_l16_n198
+end
+
+def fun_l15_n672()
+ fun_l16_n365
+end
+
+def fun_l15_n673()
+ fun_l16_n204
+end
+
+def fun_l15_n674()
+ fun_l16_n782
+end
+
+def fun_l15_n675()
+ fun_l16_n465
+end
+
+def fun_l15_n676()
+ fun_l16_n733
+end
+
+def fun_l15_n677()
+ fun_l16_n101
+end
+
+def fun_l15_n678()
+ fun_l16_n38
+end
+
+def fun_l15_n679()
+ fun_l16_n800
+end
+
+def fun_l15_n680()
+ fun_l16_n45
+end
+
+def fun_l15_n681()
+ fun_l16_n996
+end
+
+def fun_l15_n682()
+ fun_l16_n156
+end
+
+def fun_l15_n683()
+ fun_l16_n868
+end
+
+def fun_l15_n684()
+ fun_l16_n537
+end
+
+def fun_l15_n685()
+ fun_l16_n450
+end
+
+def fun_l15_n686()
+ fun_l16_n932
+end
+
+def fun_l15_n687()
+ fun_l16_n733
+end
+
+def fun_l15_n688()
+ fun_l16_n150
+end
+
+def fun_l15_n689()
+ fun_l16_n770
+end
+
+def fun_l15_n690()
+ fun_l16_n522
+end
+
+def fun_l15_n691()
+ fun_l16_n867
+end
+
+def fun_l15_n692()
+ fun_l16_n318
+end
+
+def fun_l15_n693()
+ fun_l16_n23
+end
+
+def fun_l15_n694()
+ fun_l16_n402
+end
+
+def fun_l15_n695()
+ fun_l16_n261
+end
+
+def fun_l15_n696()
+ fun_l16_n726
+end
+
+def fun_l15_n697()
+ fun_l16_n406
+end
+
+def fun_l15_n698()
+ fun_l16_n308
+end
+
+def fun_l15_n699()
+ fun_l16_n428
+end
+
+def fun_l15_n700()
+ fun_l16_n141
+end
+
+def fun_l15_n701()
+ fun_l16_n987
+end
+
+def fun_l15_n702()
+ fun_l16_n371
+end
+
+def fun_l15_n703()
+ fun_l16_n578
+end
+
+def fun_l15_n704()
+ fun_l16_n780
+end
+
+def fun_l15_n705()
+ fun_l16_n914
+end
+
+def fun_l15_n706()
+ fun_l16_n976
+end
+
+def fun_l15_n707()
+ fun_l16_n268
+end
+
+def fun_l15_n708()
+ fun_l16_n431
+end
+
+def fun_l15_n709()
+ fun_l16_n188
+end
+
+def fun_l15_n710()
+ fun_l16_n190
+end
+
+def fun_l15_n711()
+ fun_l16_n742
+end
+
+def fun_l15_n712()
+ fun_l16_n223
+end
+
+def fun_l15_n713()
+ fun_l16_n993
+end
+
+def fun_l15_n714()
+ fun_l16_n482
+end
+
+def fun_l15_n715()
+ fun_l16_n890
+end
+
+def fun_l15_n716()
+ fun_l16_n929
+end
+
+def fun_l15_n717()
+ fun_l16_n644
+end
+
+def fun_l15_n718()
+ fun_l16_n646
+end
+
+def fun_l15_n719()
+ fun_l16_n121
+end
+
+def fun_l15_n720()
+ fun_l16_n417
+end
+
+def fun_l15_n721()
+ fun_l16_n203
+end
+
+def fun_l15_n722()
+ fun_l16_n145
+end
+
+def fun_l15_n723()
+ fun_l16_n401
+end
+
+def fun_l15_n724()
+ fun_l16_n823
+end
+
+def fun_l15_n725()
+ fun_l16_n554
+end
+
+def fun_l15_n726()
+ fun_l16_n641
+end
+
+def fun_l15_n727()
+ fun_l16_n232
+end
+
+def fun_l15_n728()
+ fun_l16_n313
+end
+
+def fun_l15_n729()
+ fun_l16_n943
+end
+
+def fun_l15_n730()
+ fun_l16_n964
+end
+
+def fun_l15_n731()
+ fun_l16_n409
+end
+
+def fun_l15_n732()
+ fun_l16_n375
+end
+
+def fun_l15_n733()
+ fun_l16_n147
+end
+
+def fun_l15_n734()
+ fun_l16_n779
+end
+
+def fun_l15_n735()
+ fun_l16_n690
+end
+
+def fun_l15_n736()
+ fun_l16_n91
+end
+
+def fun_l15_n737()
+ fun_l16_n819
+end
+
+def fun_l15_n738()
+ fun_l16_n68
+end
+
+def fun_l15_n739()
+ fun_l16_n810
+end
+
+def fun_l15_n740()
+ fun_l16_n787
+end
+
+def fun_l15_n741()
+ fun_l16_n90
+end
+
+def fun_l15_n742()
+ fun_l16_n800
+end
+
+def fun_l15_n743()
+ fun_l16_n491
+end
+
+def fun_l15_n744()
+ fun_l16_n729
+end
+
+def fun_l15_n745()
+ fun_l16_n917
+end
+
+def fun_l15_n746()
+ fun_l16_n360
+end
+
+def fun_l15_n747()
+ fun_l16_n489
+end
+
+def fun_l15_n748()
+ fun_l16_n755
+end
+
+def fun_l15_n749()
+ fun_l16_n999
+end
+
+def fun_l15_n750()
+ fun_l16_n268
+end
+
+def fun_l15_n751()
+ fun_l16_n213
+end
+
+def fun_l15_n752()
+ fun_l16_n923
+end
+
+def fun_l15_n753()
+ fun_l16_n456
+end
+
+def fun_l15_n754()
+ fun_l16_n653
+end
+
+def fun_l15_n755()
+ fun_l16_n855
+end
+
+def fun_l15_n756()
+ fun_l16_n833
+end
+
+def fun_l15_n757()
+ fun_l16_n269
+end
+
+def fun_l15_n758()
+ fun_l16_n152
+end
+
+def fun_l15_n759()
+ fun_l16_n391
+end
+
+def fun_l15_n760()
+ fun_l16_n850
+end
+
+def fun_l15_n761()
+ fun_l16_n70
+end
+
+def fun_l15_n762()
+ fun_l16_n774
+end
+
+def fun_l15_n763()
+ fun_l16_n379
+end
+
+def fun_l15_n764()
+ fun_l16_n271
+end
+
+def fun_l15_n765()
+ fun_l16_n667
+end
+
+def fun_l15_n766()
+ fun_l16_n149
+end
+
+def fun_l15_n767()
+ fun_l16_n715
+end
+
+def fun_l15_n768()
+ fun_l16_n645
+end
+
+def fun_l15_n769()
+ fun_l16_n741
+end
+
+def fun_l15_n770()
+ fun_l16_n147
+end
+
+def fun_l15_n771()
+ fun_l16_n23
+end
+
+def fun_l15_n772()
+ fun_l16_n653
+end
+
+def fun_l15_n773()
+ fun_l16_n109
+end
+
+def fun_l15_n774()
+ fun_l16_n402
+end
+
+def fun_l15_n775()
+ fun_l16_n995
+end
+
+def fun_l15_n776()
+ fun_l16_n112
+end
+
+def fun_l15_n777()
+ fun_l16_n416
+end
+
+def fun_l15_n778()
+ fun_l16_n641
+end
+
+def fun_l15_n779()
+ fun_l16_n412
+end
+
+def fun_l15_n780()
+ fun_l16_n548
+end
+
+def fun_l15_n781()
+ fun_l16_n329
+end
+
+def fun_l15_n782()
+ fun_l16_n804
+end
+
+def fun_l15_n783()
+ fun_l16_n377
+end
+
+def fun_l15_n784()
+ fun_l16_n107
+end
+
+def fun_l15_n785()
+ fun_l16_n364
+end
+
+def fun_l15_n786()
+ fun_l16_n950
+end
+
+def fun_l15_n787()
+ fun_l16_n769
+end
+
+def fun_l15_n788()
+ fun_l16_n322
+end
+
+def fun_l15_n789()
+ fun_l16_n604
+end
+
+def fun_l15_n790()
+ fun_l16_n425
+end
+
+def fun_l15_n791()
+ fun_l16_n318
+end
+
+def fun_l15_n792()
+ fun_l16_n236
+end
+
+def fun_l15_n793()
+ fun_l16_n794
+end
+
+def fun_l15_n794()
+ fun_l16_n948
+end
+
+def fun_l15_n795()
+ fun_l16_n421
+end
+
+def fun_l15_n796()
+ fun_l16_n565
+end
+
+def fun_l15_n797()
+ fun_l16_n363
+end
+
+def fun_l15_n798()
+ fun_l16_n274
+end
+
+def fun_l15_n799()
+ fun_l16_n391
+end
+
+def fun_l15_n800()
+ fun_l16_n303
+end
+
+def fun_l15_n801()
+ fun_l16_n31
+end
+
+def fun_l15_n802()
+ fun_l16_n585
+end
+
+def fun_l15_n803()
+ fun_l16_n769
+end
+
+def fun_l15_n804()
+ fun_l16_n749
+end
+
+def fun_l15_n805()
+ fun_l16_n405
+end
+
+def fun_l15_n806()
+ fun_l16_n53
+end
+
+def fun_l15_n807()
+ fun_l16_n951
+end
+
+def fun_l15_n808()
+ fun_l16_n817
+end
+
+def fun_l15_n809()
+ fun_l16_n217
+end
+
+def fun_l15_n810()
+ fun_l16_n210
+end
+
+def fun_l15_n811()
+ fun_l16_n830
+end
+
+def fun_l15_n812()
+ fun_l16_n743
+end
+
+def fun_l15_n813()
+ fun_l16_n908
+end
+
+def fun_l15_n814()
+ fun_l16_n343
+end
+
+def fun_l15_n815()
+ fun_l16_n135
+end
+
+def fun_l15_n816()
+ fun_l16_n346
+end
+
+def fun_l15_n817()
+ fun_l16_n947
+end
+
+def fun_l15_n818()
+ fun_l16_n969
+end
+
+def fun_l15_n819()
+ fun_l16_n313
+end
+
+def fun_l15_n820()
+ fun_l16_n668
+end
+
+def fun_l15_n821()
+ fun_l16_n923
+end
+
+def fun_l15_n822()
+ fun_l16_n650
+end
+
+def fun_l15_n823()
+ fun_l16_n601
+end
+
+def fun_l15_n824()
+ fun_l16_n775
+end
+
+def fun_l15_n825()
+ fun_l16_n748
+end
+
+def fun_l15_n826()
+ fun_l16_n353
+end
+
+def fun_l15_n827()
+ fun_l16_n164
+end
+
+def fun_l15_n828()
+ fun_l16_n458
+end
+
+def fun_l15_n829()
+ fun_l16_n257
+end
+
+def fun_l15_n830()
+ fun_l16_n968
+end
+
+def fun_l15_n831()
+ fun_l16_n932
+end
+
+def fun_l15_n832()
+ fun_l16_n749
+end
+
+def fun_l15_n833()
+ fun_l16_n873
+end
+
+def fun_l15_n834()
+ fun_l16_n940
+end
+
+def fun_l15_n835()
+ fun_l16_n404
+end
+
+def fun_l15_n836()
+ fun_l16_n235
+end
+
+def fun_l15_n837()
+ fun_l16_n584
+end
+
+def fun_l15_n838()
+ fun_l16_n12
+end
+
+def fun_l15_n839()
+ fun_l16_n378
+end
+
+def fun_l15_n840()
+ fun_l16_n463
+end
+
+def fun_l15_n841()
+ fun_l16_n310
+end
+
+def fun_l15_n842()
+ fun_l16_n832
+end
+
+def fun_l15_n843()
+ fun_l16_n641
+end
+
+def fun_l15_n844()
+ fun_l16_n484
+end
+
+def fun_l15_n845()
+ fun_l16_n589
+end
+
+def fun_l15_n846()
+ fun_l16_n315
+end
+
+def fun_l15_n847()
+ fun_l16_n977
+end
+
+def fun_l15_n848()
+ fun_l16_n946
+end
+
+def fun_l15_n849()
+ fun_l16_n848
+end
+
+def fun_l15_n850()
+ fun_l16_n956
+end
+
+def fun_l15_n851()
+ fun_l16_n608
+end
+
+def fun_l15_n852()
+ fun_l16_n787
+end
+
+def fun_l15_n853()
+ fun_l16_n527
+end
+
+def fun_l15_n854()
+ fun_l16_n426
+end
+
+def fun_l15_n855()
+ fun_l16_n330
+end
+
+def fun_l15_n856()
+ fun_l16_n687
+end
+
+def fun_l15_n857()
+ fun_l16_n672
+end
+
+def fun_l15_n858()
+ fun_l16_n133
+end
+
+def fun_l15_n859()
+ fun_l16_n515
+end
+
+def fun_l15_n860()
+ fun_l16_n20
+end
+
+def fun_l15_n861()
+ fun_l16_n419
+end
+
+def fun_l15_n862()
+ fun_l16_n239
+end
+
+def fun_l15_n863()
+ fun_l16_n379
+end
+
+def fun_l15_n864()
+ fun_l16_n241
+end
+
+def fun_l15_n865()
+ fun_l16_n713
+end
+
+def fun_l15_n866()
+ fun_l16_n705
+end
+
+def fun_l15_n867()
+ fun_l16_n487
+end
+
+def fun_l15_n868()
+ fun_l16_n959
+end
+
+def fun_l15_n869()
+ fun_l16_n914
+end
+
+def fun_l15_n870()
+ fun_l16_n325
+end
+
+def fun_l15_n871()
+ fun_l16_n983
+end
+
+def fun_l15_n872()
+ fun_l16_n363
+end
+
+def fun_l15_n873()
+ fun_l16_n617
+end
+
+def fun_l15_n874()
+ fun_l16_n420
+end
+
+def fun_l15_n875()
+ fun_l16_n732
+end
+
+def fun_l15_n876()
+ fun_l16_n560
+end
+
+def fun_l15_n877()
+ fun_l16_n318
+end
+
+def fun_l15_n878()
+ fun_l16_n97
+end
+
+def fun_l15_n879()
+ fun_l16_n242
+end
+
+def fun_l15_n880()
+ fun_l16_n801
+end
+
+def fun_l15_n881()
+ fun_l16_n56
+end
+
+def fun_l15_n882()
+ fun_l16_n68
+end
+
+def fun_l15_n883()
+ fun_l16_n625
+end
+
+def fun_l15_n884()
+ fun_l16_n400
+end
+
+def fun_l15_n885()
+ fun_l16_n405
+end
+
+def fun_l15_n886()
+ fun_l16_n778
+end
+
+def fun_l15_n887()
+ fun_l16_n865
+end
+
+def fun_l15_n888()
+ fun_l16_n737
+end
+
+def fun_l15_n889()
+ fun_l16_n233
+end
+
+def fun_l15_n890()
+ fun_l16_n594
+end
+
+def fun_l15_n891()
+ fun_l16_n240
+end
+
+def fun_l15_n892()
+ fun_l16_n511
+end
+
+def fun_l15_n893()
+ fun_l16_n711
+end
+
+def fun_l15_n894()
+ fun_l16_n238
+end
+
+def fun_l15_n895()
+ fun_l16_n903
+end
+
+def fun_l15_n896()
+ fun_l16_n506
+end
+
+def fun_l15_n897()
+ fun_l16_n794
+end
+
+def fun_l15_n898()
+ fun_l16_n812
+end
+
+def fun_l15_n899()
+ fun_l16_n829
+end
+
+def fun_l15_n900()
+ fun_l16_n686
+end
+
+def fun_l15_n901()
+ fun_l16_n302
+end
+
+def fun_l15_n902()
+ fun_l16_n947
+end
+
+def fun_l15_n903()
+ fun_l16_n107
+end
+
+def fun_l15_n904()
+ fun_l16_n79
+end
+
+def fun_l15_n905()
+ fun_l16_n570
+end
+
+def fun_l15_n906()
+ fun_l16_n567
+end
+
+def fun_l15_n907()
+ fun_l16_n853
+end
+
+def fun_l15_n908()
+ fun_l16_n49
+end
+
+def fun_l15_n909()
+ fun_l16_n721
+end
+
+def fun_l15_n910()
+ fun_l16_n376
+end
+
+def fun_l15_n911()
+ fun_l16_n513
+end
+
+def fun_l15_n912()
+ fun_l16_n863
+end
+
+def fun_l15_n913()
+ fun_l16_n692
+end
+
+def fun_l15_n914()
+ fun_l16_n391
+end
+
+def fun_l15_n915()
+ fun_l16_n263
+end
+
+def fun_l15_n916()
+ fun_l16_n159
+end
+
+def fun_l15_n917()
+ fun_l16_n291
+end
+
+def fun_l15_n918()
+ fun_l16_n290
+end
+
+def fun_l15_n919()
+ fun_l16_n328
+end
+
+def fun_l15_n920()
+ fun_l16_n838
+end
+
+def fun_l15_n921()
+ fun_l16_n66
+end
+
+def fun_l15_n922()
+ fun_l16_n821
+end
+
+def fun_l15_n923()
+ fun_l16_n549
+end
+
+def fun_l15_n924()
+ fun_l16_n235
+end
+
+def fun_l15_n925()
+ fun_l16_n800
+end
+
+def fun_l15_n926()
+ fun_l16_n486
+end
+
+def fun_l15_n927()
+ fun_l16_n824
+end
+
+def fun_l15_n928()
+ fun_l16_n881
+end
+
+def fun_l15_n929()
+ fun_l16_n772
+end
+
+def fun_l15_n930()
+ fun_l16_n563
+end
+
+def fun_l15_n931()
+ fun_l16_n99
+end
+
+def fun_l15_n932()
+ fun_l16_n691
+end
+
+def fun_l15_n933()
+ fun_l16_n983
+end
+
+def fun_l15_n934()
+ fun_l16_n593
+end
+
+def fun_l15_n935()
+ fun_l16_n611
+end
+
+def fun_l15_n936()
+ fun_l16_n600
+end
+
+def fun_l15_n937()
+ fun_l16_n892
+end
+
+def fun_l15_n938()
+ fun_l16_n653
+end
+
+def fun_l15_n939()
+ fun_l16_n78
+end
+
+def fun_l15_n940()
+ fun_l16_n139
+end
+
+def fun_l15_n941()
+ fun_l16_n995
+end
+
+def fun_l15_n942()
+ fun_l16_n63
+end
+
+def fun_l15_n943()
+ fun_l16_n466
+end
+
+def fun_l15_n944()
+ fun_l16_n740
+end
+
+def fun_l15_n945()
+ fun_l16_n870
+end
+
+def fun_l15_n946()
+ fun_l16_n373
+end
+
+def fun_l15_n947()
+ fun_l16_n375
+end
+
+def fun_l15_n948()
+ fun_l16_n360
+end
+
+def fun_l15_n949()
+ fun_l16_n526
+end
+
+def fun_l15_n950()
+ fun_l16_n100
+end
+
+def fun_l15_n951()
+ fun_l16_n644
+end
+
+def fun_l15_n952()
+ fun_l16_n773
+end
+
+def fun_l15_n953()
+ fun_l16_n311
+end
+
+def fun_l15_n954()
+ fun_l16_n152
+end
+
+def fun_l15_n955()
+ fun_l16_n754
+end
+
+def fun_l15_n956()
+ fun_l16_n31
+end
+
+def fun_l15_n957()
+ fun_l16_n501
+end
+
+def fun_l15_n958()
+ fun_l16_n333
+end
+
+def fun_l15_n959()
+ fun_l16_n952
+end
+
+def fun_l15_n960()
+ fun_l16_n753
+end
+
+def fun_l15_n961()
+ fun_l16_n694
+end
+
+def fun_l15_n962()
+ fun_l16_n82
+end
+
+def fun_l15_n963()
+ fun_l16_n204
+end
+
+def fun_l15_n964()
+ fun_l16_n910
+end
+
+def fun_l15_n965()
+ fun_l16_n127
+end
+
+def fun_l15_n966()
+ fun_l16_n203
+end
+
+def fun_l15_n967()
+ fun_l16_n760
+end
+
+def fun_l15_n968()
+ fun_l16_n718
+end
+
+def fun_l15_n969()
+ fun_l16_n446
+end
+
+def fun_l15_n970()
+ fun_l16_n595
+end
+
+def fun_l15_n971()
+ fun_l16_n165
+end
+
+def fun_l15_n972()
+ fun_l16_n393
+end
+
+def fun_l15_n973()
+ fun_l16_n766
+end
+
+def fun_l15_n974()
+ fun_l16_n276
+end
+
+def fun_l15_n975()
+ fun_l16_n97
+end
+
+def fun_l15_n976()
+ fun_l16_n319
+end
+
+def fun_l15_n977()
+ fun_l16_n333
+end
+
+def fun_l15_n978()
+ fun_l16_n635
+end
+
+def fun_l15_n979()
+ fun_l16_n466
+end
+
+def fun_l15_n980()
+ fun_l16_n841
+end
+
+def fun_l15_n981()
+ fun_l16_n415
+end
+
+def fun_l15_n982()
+ fun_l16_n630
+end
+
+def fun_l15_n983()
+ fun_l16_n19
+end
+
+def fun_l15_n984()
+ fun_l16_n901
+end
+
+def fun_l15_n985()
+ fun_l16_n933
+end
+
+def fun_l15_n986()
+ fun_l16_n558
+end
+
+def fun_l15_n987()
+ fun_l16_n357
+end
+
+def fun_l15_n988()
+ fun_l16_n929
+end
+
+def fun_l15_n989()
+ fun_l16_n871
+end
+
+def fun_l15_n990()
+ fun_l16_n967
+end
+
+def fun_l15_n991()
+ fun_l16_n803
+end
+
+def fun_l15_n992()
+ fun_l16_n484
+end
+
+def fun_l15_n993()
+ fun_l16_n270
+end
+
+def fun_l15_n994()
+ fun_l16_n670
+end
+
+def fun_l15_n995()
+ fun_l16_n77
+end
+
+def fun_l15_n996()
+ fun_l16_n480
+end
+
+def fun_l15_n997()
+ fun_l16_n279
+end
+
+def fun_l15_n998()
+ fun_l16_n109
+end
+
+def fun_l15_n999()
+ fun_l16_n333
+end
+
+def fun_l16_n0()
+ fun_l17_n358
+end
+
+def fun_l16_n1()
+ fun_l17_n388
+end
+
+def fun_l16_n2()
+ fun_l17_n450
+end
+
+def fun_l16_n3()
+ fun_l17_n274
+end
+
+def fun_l16_n4()
+ fun_l17_n83
+end
+
+def fun_l16_n5()
+ fun_l17_n148
+end
+
+def fun_l16_n6()
+ fun_l17_n370
+end
+
+def fun_l16_n7()
+ fun_l17_n956
+end
+
+def fun_l16_n8()
+ fun_l17_n137
+end
+
+def fun_l16_n9()
+ fun_l17_n702
+end
+
+def fun_l16_n10()
+ fun_l17_n296
+end
+
+def fun_l16_n11()
+ fun_l17_n44
+end
+
+def fun_l16_n12()
+ fun_l17_n937
+end
+
+def fun_l16_n13()
+ fun_l17_n100
+end
+
+def fun_l16_n14()
+ fun_l17_n599
+end
+
+def fun_l16_n15()
+ fun_l17_n757
+end
+
+def fun_l16_n16()
+ fun_l17_n831
+end
+
+def fun_l16_n17()
+ fun_l17_n753
+end
+
+def fun_l16_n18()
+ fun_l17_n726
+end
+
+def fun_l16_n19()
+ fun_l17_n126
+end
+
+def fun_l16_n20()
+ fun_l17_n106
+end
+
+def fun_l16_n21()
+ fun_l17_n46
+end
+
+def fun_l16_n22()
+ fun_l17_n56
+end
+
+def fun_l16_n23()
+ fun_l17_n16
+end
+
+def fun_l16_n24()
+ fun_l17_n298
+end
+
+def fun_l16_n25()
+ fun_l17_n173
+end
+
+def fun_l16_n26()
+ fun_l17_n479
+end
+
+def fun_l16_n27()
+ fun_l17_n304
+end
+
+def fun_l16_n28()
+ fun_l17_n426
+end
+
+def fun_l16_n29()
+ fun_l17_n214
+end
+
+def fun_l16_n30()
+ fun_l17_n818
+end
+
+def fun_l16_n31()
+ fun_l17_n362
+end
+
+def fun_l16_n32()
+ fun_l17_n392
+end
+
+def fun_l16_n33()
+ fun_l17_n751
+end
+
+def fun_l16_n34()
+ fun_l17_n719
+end
+
+def fun_l16_n35()
+ fun_l17_n258
+end
+
+def fun_l16_n36()
+ fun_l17_n128
+end
+
+def fun_l16_n37()
+ fun_l17_n95
+end
+
+def fun_l16_n38()
+ fun_l17_n30
+end
+
+def fun_l16_n39()
+ fun_l17_n539
+end
+
+def fun_l16_n40()
+ fun_l17_n139
+end
+
+def fun_l16_n41()
+ fun_l17_n309
+end
+
+def fun_l16_n42()
+ fun_l17_n943
+end
+
+def fun_l16_n43()
+ fun_l17_n242
+end
+
+def fun_l16_n44()
+ fun_l17_n402
+end
+
+def fun_l16_n45()
+ fun_l17_n173
+end
+
+def fun_l16_n46()
+ fun_l17_n328
+end
+
+def fun_l16_n47()
+ fun_l17_n883
+end
+
+def fun_l16_n48()
+ fun_l17_n992
+end
+
+def fun_l16_n49()
+ fun_l17_n921
+end
+
+def fun_l16_n50()
+ fun_l17_n130
+end
+
+def fun_l16_n51()
+ fun_l17_n374
+end
+
+def fun_l16_n52()
+ fun_l17_n555
+end
+
+def fun_l16_n53()
+ fun_l17_n965
+end
+
+def fun_l16_n54()
+ fun_l17_n353
+end
+
+def fun_l16_n55()
+ fun_l17_n525
+end
+
+def fun_l16_n56()
+ fun_l17_n569
+end
+
+def fun_l16_n57()
+ fun_l17_n156
+end
+
+def fun_l16_n58()
+ fun_l17_n695
+end
+
+def fun_l16_n59()
+ fun_l17_n864
+end
+
+def fun_l16_n60()
+ fun_l17_n415
+end
+
+def fun_l16_n61()
+ fun_l17_n605
+end
+
+def fun_l16_n62()
+ fun_l17_n995
+end
+
+def fun_l16_n63()
+ fun_l17_n794
+end
+
+def fun_l16_n64()
+ fun_l17_n813
+end
+
+def fun_l16_n65()
+ fun_l17_n839
+end
+
+def fun_l16_n66()
+ fun_l17_n273
+end
+
+def fun_l16_n67()
+ fun_l17_n223
+end
+
+def fun_l16_n68()
+ fun_l17_n168
+end
+
+def fun_l16_n69()
+ fun_l17_n798
+end
+
+def fun_l16_n70()
+ fun_l17_n892
+end
+
+def fun_l16_n71()
+ fun_l17_n966
+end
+
+def fun_l16_n72()
+ fun_l17_n102
+end
+
+def fun_l16_n73()
+ fun_l17_n209
+end
+
+def fun_l16_n74()
+ fun_l17_n618
+end
+
+def fun_l16_n75()
+ fun_l17_n432
+end
+
+def fun_l16_n76()
+ fun_l17_n254
+end
+
+def fun_l16_n77()
+ fun_l17_n413
+end
+
+def fun_l16_n78()
+ fun_l17_n908
+end
+
+def fun_l16_n79()
+ fun_l17_n519
+end
+
+def fun_l16_n80()
+ fun_l17_n67
+end
+
+def fun_l16_n81()
+ fun_l17_n914
+end
+
+def fun_l16_n82()
+ fun_l17_n356
+end
+
+def fun_l16_n83()
+ fun_l17_n138
+end
+
+def fun_l16_n84()
+ fun_l17_n714
+end
+
+def fun_l16_n85()
+ fun_l17_n803
+end
+
+def fun_l16_n86()
+ fun_l17_n770
+end
+
+def fun_l16_n87()
+ fun_l17_n813
+end
+
+def fun_l16_n88()
+ fun_l17_n752
+end
+
+def fun_l16_n89()
+ fun_l17_n580
+end
+
+def fun_l16_n90()
+ fun_l17_n368
+end
+
+def fun_l16_n91()
+ fun_l17_n169
+end
+
+def fun_l16_n92()
+ fun_l17_n565
+end
+
+def fun_l16_n93()
+ fun_l17_n111
+end
+
+def fun_l16_n94()
+ fun_l17_n911
+end
+
+def fun_l16_n95()
+ fun_l17_n448
+end
+
+def fun_l16_n96()
+ fun_l17_n455
+end
+
+def fun_l16_n97()
+ fun_l17_n76
+end
+
+def fun_l16_n98()
+ fun_l17_n27
+end
+
+def fun_l16_n99()
+ fun_l17_n884
+end
+
+def fun_l16_n100()
+ fun_l17_n144
+end
+
+def fun_l16_n101()
+ fun_l17_n344
+end
+
+def fun_l16_n102()
+ fun_l17_n293
+end
+
+def fun_l16_n103()
+ fun_l17_n91
+end
+
+def fun_l16_n104()
+ fun_l17_n398
+end
+
+def fun_l16_n105()
+ fun_l17_n398
+end
+
+def fun_l16_n106()
+ fun_l17_n216
+end
+
+def fun_l16_n107()
+ fun_l17_n22
+end
+
+def fun_l16_n108()
+ fun_l17_n901
+end
+
+def fun_l16_n109()
+ fun_l17_n817
+end
+
+def fun_l16_n110()
+ fun_l17_n574
+end
+
+def fun_l16_n111()
+ fun_l17_n546
+end
+
+def fun_l16_n112()
+ fun_l17_n704
+end
+
+def fun_l16_n113()
+ fun_l17_n184
+end
+
+def fun_l16_n114()
+ fun_l17_n993
+end
+
+def fun_l16_n115()
+ fun_l17_n582
+end
+
+def fun_l16_n116()
+ fun_l17_n943
+end
+
+def fun_l16_n117()
+ fun_l17_n692
+end
+
+def fun_l16_n118()
+ fun_l17_n203
+end
+
+def fun_l16_n119()
+ fun_l17_n283
+end
+
+def fun_l16_n120()
+ fun_l17_n600
+end
+
+def fun_l16_n121()
+ fun_l17_n953
+end
+
+def fun_l16_n122()
+ fun_l17_n810
+end
+
+def fun_l16_n123()
+ fun_l17_n861
+end
+
+def fun_l16_n124()
+ fun_l17_n680
+end
+
+def fun_l16_n125()
+ fun_l17_n401
+end
+
+def fun_l16_n126()
+ fun_l17_n905
+end
+
+def fun_l16_n127()
+ fun_l17_n376
+end
+
+def fun_l16_n128()
+ fun_l17_n231
+end
+
+def fun_l16_n129()
+ fun_l17_n693
+end
+
+def fun_l16_n130()
+ fun_l17_n219
+end
+
+def fun_l16_n131()
+ fun_l17_n560
+end
+
+def fun_l16_n132()
+ fun_l17_n17
+end
+
+def fun_l16_n133()
+ fun_l17_n706
+end
+
+def fun_l16_n134()
+ fun_l17_n355
+end
+
+def fun_l16_n135()
+ fun_l17_n309
+end
+
+def fun_l16_n136()
+ fun_l17_n514
+end
+
+def fun_l16_n137()
+ fun_l17_n428
+end
+
+def fun_l16_n138()
+ fun_l17_n80
+end
+
+def fun_l16_n139()
+ fun_l17_n548
+end
+
+def fun_l16_n140()
+ fun_l17_n514
+end
+
+def fun_l16_n141()
+ fun_l17_n316
+end
+
+def fun_l16_n142()
+ fun_l17_n791
+end
+
+def fun_l16_n143()
+ fun_l17_n70
+end
+
+def fun_l16_n144()
+ fun_l17_n953
+end
+
+def fun_l16_n145()
+ fun_l17_n416
+end
+
+def fun_l16_n146()
+ fun_l17_n989
+end
+
+def fun_l16_n147()
+ fun_l17_n604
+end
+
+def fun_l16_n148()
+ fun_l17_n845
+end
+
+def fun_l16_n149()
+ fun_l17_n576
+end
+
+def fun_l16_n150()
+ fun_l17_n831
+end
+
+def fun_l16_n151()
+ fun_l17_n727
+end
+
+def fun_l16_n152()
+ fun_l17_n231
+end
+
+def fun_l16_n153()
+ fun_l17_n405
+end
+
+def fun_l16_n154()
+ fun_l17_n643
+end
+
+def fun_l16_n155()
+ fun_l17_n117
+end
+
+def fun_l16_n156()
+ fun_l17_n842
+end
+
+def fun_l16_n157()
+ fun_l17_n522
+end
+
+def fun_l16_n158()
+ fun_l17_n415
+end
+
+def fun_l16_n159()
+ fun_l17_n239
+end
+
+def fun_l16_n160()
+ fun_l17_n512
+end
+
+def fun_l16_n161()
+ fun_l17_n247
+end
+
+def fun_l16_n162()
+ fun_l17_n798
+end
+
+def fun_l16_n163()
+ fun_l17_n771
+end
+
+def fun_l16_n164()
+ fun_l17_n47
+end
+
+def fun_l16_n165()
+ fun_l17_n803
+end
+
+def fun_l16_n166()
+ fun_l17_n500
+end
+
+def fun_l16_n167()
+ fun_l17_n797
+end
+
+def fun_l16_n168()
+ fun_l17_n467
+end
+
+def fun_l16_n169()
+ fun_l17_n893
+end
+
+def fun_l16_n170()
+ fun_l17_n900
+end
+
+def fun_l16_n171()
+ fun_l17_n539
+end
+
+def fun_l16_n172()
+ fun_l17_n631
+end
+
+def fun_l16_n173()
+ fun_l17_n113
+end
+
+def fun_l16_n174()
+ fun_l17_n674
+end
+
+def fun_l16_n175()
+ fun_l17_n827
+end
+
+def fun_l16_n176()
+ fun_l17_n751
+end
+
+def fun_l16_n177()
+ fun_l17_n600
+end
+
+def fun_l16_n178()
+ fun_l17_n290
+end
+
+def fun_l16_n179()
+ fun_l17_n947
+end
+
+def fun_l16_n180()
+ fun_l17_n718
+end
+
+def fun_l16_n181()
+ fun_l17_n531
+end
+
+def fun_l16_n182()
+ fun_l17_n849
+end
+
+def fun_l16_n183()
+ fun_l17_n310
+end
+
+def fun_l16_n184()
+ fun_l17_n795
+end
+
+def fun_l16_n185()
+ fun_l17_n65
+end
+
+def fun_l16_n186()
+ fun_l17_n242
+end
+
+def fun_l16_n187()
+ fun_l17_n832
+end
+
+def fun_l16_n188()
+ fun_l17_n749
+end
+
+def fun_l16_n189()
+ fun_l17_n826
+end
+
+def fun_l16_n190()
+ fun_l17_n244
+end
+
+def fun_l16_n191()
+ fun_l17_n279
+end
+
+def fun_l16_n192()
+ fun_l17_n746
+end
+
+def fun_l16_n193()
+ fun_l17_n199
+end
+
+def fun_l16_n194()
+ fun_l17_n458
+end
+
+def fun_l16_n195()
+ fun_l17_n161
+end
+
+def fun_l16_n196()
+ fun_l17_n584
+end
+
+def fun_l16_n197()
+ fun_l17_n400
+end
+
+def fun_l16_n198()
+ fun_l17_n598
+end
+
+def fun_l16_n199()
+ fun_l17_n685
+end
+
+def fun_l16_n200()
+ fun_l17_n939
+end
+
+def fun_l16_n201()
+ fun_l17_n374
+end
+
+def fun_l16_n202()
+ fun_l17_n463
+end
+
+def fun_l16_n203()
+ fun_l17_n677
+end
+
+def fun_l16_n204()
+ fun_l17_n857
+end
+
+def fun_l16_n205()
+ fun_l17_n39
+end
+
+def fun_l16_n206()
+ fun_l17_n899
+end
+
+def fun_l16_n207()
+ fun_l17_n733
+end
+
+def fun_l16_n208()
+ fun_l17_n137
+end
+
+def fun_l16_n209()
+ fun_l17_n988
+end
+
+def fun_l16_n210()
+ fun_l17_n792
+end
+
+def fun_l16_n211()
+ fun_l17_n861
+end
+
+def fun_l16_n212()
+ fun_l17_n889
+end
+
+def fun_l16_n213()
+ fun_l17_n933
+end
+
+def fun_l16_n214()
+ fun_l17_n898
+end
+
+def fun_l16_n215()
+ fun_l17_n723
+end
+
+def fun_l16_n216()
+ fun_l17_n116
+end
+
+def fun_l16_n217()
+ fun_l17_n251
+end
+
+def fun_l16_n218()
+ fun_l17_n586
+end
+
+def fun_l16_n219()
+ fun_l17_n428
+end
+
+def fun_l16_n220()
+ fun_l17_n53
+end
+
+def fun_l16_n221()
+ fun_l17_n611
+end
+
+def fun_l16_n222()
+ fun_l17_n480
+end
+
+def fun_l16_n223()
+ fun_l17_n2
+end
+
+def fun_l16_n224()
+ fun_l17_n623
+end
+
+def fun_l16_n225()
+ fun_l17_n178
+end
+
+def fun_l16_n226()
+ fun_l17_n938
+end
+
+def fun_l16_n227()
+ fun_l17_n284
+end
+
+def fun_l16_n228()
+ fun_l17_n925
+end
+
+def fun_l16_n229()
+ fun_l17_n899
+end
+
+def fun_l16_n230()
+ fun_l17_n314
+end
+
+def fun_l16_n231()
+ fun_l17_n931
+end
+
+def fun_l16_n232()
+ fun_l17_n103
+end
+
+def fun_l16_n233()
+ fun_l17_n201
+end
+
+def fun_l16_n234()
+ fun_l17_n139
+end
+
+def fun_l16_n235()
+ fun_l17_n509
+end
+
+def fun_l16_n236()
+ fun_l17_n168
+end
+
+def fun_l16_n237()
+ fun_l17_n667
+end
+
+def fun_l16_n238()
+ fun_l17_n998
+end
+
+def fun_l16_n239()
+ fun_l17_n931
+end
+
+def fun_l16_n240()
+ fun_l17_n159
+end
+
+def fun_l16_n241()
+ fun_l17_n402
+end
+
+def fun_l16_n242()
+ fun_l17_n488
+end
+
+def fun_l16_n243()
+ fun_l17_n319
+end
+
+def fun_l16_n244()
+ fun_l17_n209
+end
+
+def fun_l16_n245()
+ fun_l17_n409
+end
+
+def fun_l16_n246()
+ fun_l17_n712
+end
+
+def fun_l16_n247()
+ fun_l17_n680
+end
+
+def fun_l16_n248()
+ fun_l17_n57
+end
+
+def fun_l16_n249()
+ fun_l17_n68
+end
+
+def fun_l16_n250()
+ fun_l17_n676
+end
+
+def fun_l16_n251()
+ fun_l17_n870
+end
+
+def fun_l16_n252()
+ fun_l17_n718
+end
+
+def fun_l16_n253()
+ fun_l17_n753
+end
+
+def fun_l16_n254()
+ fun_l17_n317
+end
+
+def fun_l16_n255()
+ fun_l17_n905
+end
+
+def fun_l16_n256()
+ fun_l17_n524
+end
+
+def fun_l16_n257()
+ fun_l17_n496
+end
+
+def fun_l16_n258()
+ fun_l17_n253
+end
+
+def fun_l16_n259()
+ fun_l17_n32
+end
+
+def fun_l16_n260()
+ fun_l17_n299
+end
+
+def fun_l16_n261()
+ fun_l17_n291
+end
+
+def fun_l16_n262()
+ fun_l17_n516
+end
+
+def fun_l16_n263()
+ fun_l17_n542
+end
+
+def fun_l16_n264()
+ fun_l17_n550
+end
+
+def fun_l16_n265()
+ fun_l17_n886
+end
+
+def fun_l16_n266()
+ fun_l17_n428
+end
+
+def fun_l16_n267()
+ fun_l17_n741
+end
+
+def fun_l16_n268()
+ fun_l17_n711
+end
+
+def fun_l16_n269()
+ fun_l17_n709
+end
+
+def fun_l16_n270()
+ fun_l17_n71
+end
+
+def fun_l16_n271()
+ fun_l17_n256
+end
+
+def fun_l16_n272()
+ fun_l17_n585
+end
+
+def fun_l16_n273()
+ fun_l17_n478
+end
+
+def fun_l16_n274()
+ fun_l17_n314
+end
+
+def fun_l16_n275()
+ fun_l17_n223
+end
+
+def fun_l16_n276()
+ fun_l17_n691
+end
+
+def fun_l16_n277()
+ fun_l17_n637
+end
+
+def fun_l16_n278()
+ fun_l17_n218
+end
+
+def fun_l16_n279()
+ fun_l17_n675
+end
+
+def fun_l16_n280()
+ fun_l17_n705
+end
+
+def fun_l16_n281()
+ fun_l17_n492
+end
+
+def fun_l16_n282()
+ fun_l17_n426
+end
+
+def fun_l16_n283()
+ fun_l17_n366
+end
+
+def fun_l16_n284()
+ fun_l17_n533
+end
+
+def fun_l16_n285()
+ fun_l17_n980
+end
+
+def fun_l16_n286()
+ fun_l17_n660
+end
+
+def fun_l16_n287()
+ fun_l17_n550
+end
+
+def fun_l16_n288()
+ fun_l17_n37
+end
+
+def fun_l16_n289()
+ fun_l17_n453
+end
+
+def fun_l16_n290()
+ fun_l17_n687
+end
+
+def fun_l16_n291()
+ fun_l17_n82
+end
+
+def fun_l16_n292()
+ fun_l17_n327
+end
+
+def fun_l16_n293()
+ fun_l17_n842
+end
+
+def fun_l16_n294()
+ fun_l17_n201
+end
+
+def fun_l16_n295()
+ fun_l17_n26
+end
+
+def fun_l16_n296()
+ fun_l17_n153
+end
+
+def fun_l16_n297()
+ fun_l17_n684
+end
+
+def fun_l16_n298()
+ fun_l17_n752
+end
+
+def fun_l16_n299()
+ fun_l17_n763
+end
+
+def fun_l16_n300()
+ fun_l17_n651
+end
+
+def fun_l16_n301()
+ fun_l17_n605
+end
+
+def fun_l16_n302()
+ fun_l17_n48
+end
+
+def fun_l16_n303()
+ fun_l17_n71
+end
+
+def fun_l16_n304()
+ fun_l17_n57
+end
+
+def fun_l16_n305()
+ fun_l17_n72
+end
+
+def fun_l16_n306()
+ fun_l17_n561
+end
+
+def fun_l16_n307()
+ fun_l17_n10
+end
+
+def fun_l16_n308()
+ fun_l17_n543
+end
+
+def fun_l16_n309()
+ fun_l17_n17
+end
+
+def fun_l16_n310()
+ fun_l17_n340
+end
+
+def fun_l16_n311()
+ fun_l17_n184
+end
+
+def fun_l16_n312()
+ fun_l17_n208
+end
+
+def fun_l16_n313()
+ fun_l17_n46
+end
+
+def fun_l16_n314()
+ fun_l17_n386
+end
+
+def fun_l16_n315()
+ fun_l17_n258
+end
+
+def fun_l16_n316()
+ fun_l17_n594
+end
+
+def fun_l16_n317()
+ fun_l17_n968
+end
+
+def fun_l16_n318()
+ fun_l17_n403
+end
+
+def fun_l16_n319()
+ fun_l17_n256
+end
+
+def fun_l16_n320()
+ fun_l17_n212
+end
+
+def fun_l16_n321()
+ fun_l17_n567
+end
+
+def fun_l16_n322()
+ fun_l17_n61
+end
+
+def fun_l16_n323()
+ fun_l17_n925
+end
+
+def fun_l16_n324()
+ fun_l17_n679
+end
+
+def fun_l16_n325()
+ fun_l17_n136
+end
+
+def fun_l16_n326()
+ fun_l17_n403
+end
+
+def fun_l16_n327()
+ fun_l17_n35
+end
+
+def fun_l16_n328()
+ fun_l17_n833
+end
+
+def fun_l16_n329()
+ fun_l17_n925
+end
+
+def fun_l16_n330()
+ fun_l17_n193
+end
+
+def fun_l16_n331()
+ fun_l17_n474
+end
+
+def fun_l16_n332()
+ fun_l17_n271
+end
+
+def fun_l16_n333()
+ fun_l17_n604
+end
+
+def fun_l16_n334()
+ fun_l17_n570
+end
+
+def fun_l16_n335()
+ fun_l17_n110
+end
+
+def fun_l16_n336()
+ fun_l17_n920
+end
+
+def fun_l16_n337()
+ fun_l17_n388
+end
+
+def fun_l16_n338()
+ fun_l17_n207
+end
+
+def fun_l16_n339()
+ fun_l17_n899
+end
+
+def fun_l16_n340()
+ fun_l17_n337
+end
+
+def fun_l16_n341()
+ fun_l17_n611
+end
+
+def fun_l16_n342()
+ fun_l17_n474
+end
+
+def fun_l16_n343()
+ fun_l17_n71
+end
+
+def fun_l16_n344()
+ fun_l17_n347
+end
+
+def fun_l16_n345()
+ fun_l17_n911
+end
+
+def fun_l16_n346()
+ fun_l17_n625
+end
+
+def fun_l16_n347()
+ fun_l17_n683
+end
+
+def fun_l16_n348()
+ fun_l17_n628
+end
+
+def fun_l16_n349()
+ fun_l17_n73
+end
+
+def fun_l16_n350()
+ fun_l17_n710
+end
+
+def fun_l16_n351()
+ fun_l17_n550
+end
+
+def fun_l16_n352()
+ fun_l17_n96
+end
+
+def fun_l16_n353()
+ fun_l17_n815
+end
+
+def fun_l16_n354()
+ fun_l17_n494
+end
+
+def fun_l16_n355()
+ fun_l17_n831
+end
+
+def fun_l16_n356()
+ fun_l17_n174
+end
+
+def fun_l16_n357()
+ fun_l17_n196
+end
+
+def fun_l16_n358()
+ fun_l17_n191
+end
+
+def fun_l16_n359()
+ fun_l17_n278
+end
+
+def fun_l16_n360()
+ fun_l17_n433
+end
+
+def fun_l16_n361()
+ fun_l17_n673
+end
+
+def fun_l16_n362()
+ fun_l17_n313
+end
+
+def fun_l16_n363()
+ fun_l17_n517
+end
+
+def fun_l16_n364()
+ fun_l17_n392
+end
+
+def fun_l16_n365()
+ fun_l17_n574
+end
+
+def fun_l16_n366()
+ fun_l17_n531
+end
+
+def fun_l16_n367()
+ fun_l17_n222
+end
+
+def fun_l16_n368()
+ fun_l17_n226
+end
+
+def fun_l16_n369()
+ fun_l17_n309
+end
+
+def fun_l16_n370()
+ fun_l17_n125
+end
+
+def fun_l16_n371()
+ fun_l17_n523
+end
+
+def fun_l16_n372()
+ fun_l17_n261
+end
+
+def fun_l16_n373()
+ fun_l17_n830
+end
+
+def fun_l16_n374()
+ fun_l17_n851
+end
+
+def fun_l16_n375()
+ fun_l17_n845
+end
+
+def fun_l16_n376()
+ fun_l17_n76
+end
+
+def fun_l16_n377()
+ fun_l17_n405
+end
+
+def fun_l16_n378()
+ fun_l17_n972
+end
+
+def fun_l16_n379()
+ fun_l17_n769
+end
+
+def fun_l16_n380()
+ fun_l17_n246
+end
+
+def fun_l16_n381()
+ fun_l17_n95
+end
+
+def fun_l16_n382()
+ fun_l17_n768
+end
+
+def fun_l16_n383()
+ fun_l17_n12
+end
+
+def fun_l16_n384()
+ fun_l17_n164
+end
+
+def fun_l16_n385()
+ fun_l17_n579
+end
+
+def fun_l16_n386()
+ fun_l17_n241
+end
+
+def fun_l16_n387()
+ fun_l17_n913
+end
+
+def fun_l16_n388()
+ fun_l17_n518
+end
+
+def fun_l16_n389()
+ fun_l17_n376
+end
+
+def fun_l16_n390()
+ fun_l17_n256
+end
+
+def fun_l16_n391()
+ fun_l17_n25
+end
+
+def fun_l16_n392()
+ fun_l17_n699
+end
+
+def fun_l16_n393()
+ fun_l17_n808
+end
+
+def fun_l16_n394()
+ fun_l17_n234
+end
+
+def fun_l16_n395()
+ fun_l17_n517
+end
+
+def fun_l16_n396()
+ fun_l17_n172
+end
+
+def fun_l16_n397()
+ fun_l17_n811
+end
+
+def fun_l16_n398()
+ fun_l17_n513
+end
+
+def fun_l16_n399()
+ fun_l17_n144
+end
+
+def fun_l16_n400()
+ fun_l17_n92
+end
+
+def fun_l16_n401()
+ fun_l17_n599
+end
+
+def fun_l16_n402()
+ fun_l17_n394
+end
+
+def fun_l16_n403()
+ fun_l17_n17
+end
+
+def fun_l16_n404()
+ fun_l17_n450
+end
+
+def fun_l16_n405()
+ fun_l17_n46
+end
+
+def fun_l16_n406()
+ fun_l17_n819
+end
+
+def fun_l16_n407()
+ fun_l17_n955
+end
+
+def fun_l16_n408()
+ fun_l17_n261
+end
+
+def fun_l16_n409()
+ fun_l17_n695
+end
+
+def fun_l16_n410()
+ fun_l17_n90
+end
+
+def fun_l16_n411()
+ fun_l17_n93
+end
+
+def fun_l16_n412()
+ fun_l17_n529
+end
+
+def fun_l16_n413()
+ fun_l17_n831
+end
+
+def fun_l16_n414()
+ fun_l17_n107
+end
+
+def fun_l16_n415()
+ fun_l17_n977
+end
+
+def fun_l16_n416()
+ fun_l17_n891
+end
+
+def fun_l16_n417()
+ fun_l17_n256
+end
+
+def fun_l16_n418()
+ fun_l17_n45
+end
+
+def fun_l16_n419()
+ fun_l17_n862
+end
+
+def fun_l16_n420()
+ fun_l17_n294
+end
+
+def fun_l16_n421()
+ fun_l17_n421
+end
+
+def fun_l16_n422()
+ fun_l17_n749
+end
+
+def fun_l16_n423()
+ fun_l17_n689
+end
+
+def fun_l16_n424()
+ fun_l17_n524
+end
+
+def fun_l16_n425()
+ fun_l17_n946
+end
+
+def fun_l16_n426()
+ fun_l17_n222
+end
+
+def fun_l16_n427()
+ fun_l17_n146
+end
+
+def fun_l16_n428()
+ fun_l17_n219
+end
+
+def fun_l16_n429()
+ fun_l17_n380
+end
+
+def fun_l16_n430()
+ fun_l17_n371
+end
+
+def fun_l16_n431()
+ fun_l17_n813
+end
+
+def fun_l16_n432()
+ fun_l17_n546
+end
+
+def fun_l16_n433()
+ fun_l17_n429
+end
+
+def fun_l16_n434()
+ fun_l17_n672
+end
+
+def fun_l16_n435()
+ fun_l17_n374
+end
+
+def fun_l16_n436()
+ fun_l17_n695
+end
+
+def fun_l16_n437()
+ fun_l17_n682
+end
+
+def fun_l16_n438()
+ fun_l17_n894
+end
+
+def fun_l16_n439()
+ fun_l17_n268
+end
+
+def fun_l16_n440()
+ fun_l17_n393
+end
+
+def fun_l16_n441()
+ fun_l17_n852
+end
+
+def fun_l16_n442()
+ fun_l17_n481
+end
+
+def fun_l16_n443()
+ fun_l17_n598
+end
+
+def fun_l16_n444()
+ fun_l17_n851
+end
+
+def fun_l16_n445()
+ fun_l17_n132
+end
+
+def fun_l16_n446()
+ fun_l17_n357
+end
+
+def fun_l16_n447()
+ fun_l17_n132
+end
+
+def fun_l16_n448()
+ fun_l17_n829
+end
+
+def fun_l16_n449()
+ fun_l17_n591
+end
+
+def fun_l16_n450()
+ fun_l17_n437
+end
+
+def fun_l16_n451()
+ fun_l17_n108
+end
+
+def fun_l16_n452()
+ fun_l17_n898
+end
+
+def fun_l16_n453()
+ fun_l17_n263
+end
+
+def fun_l16_n454()
+ fun_l17_n942
+end
+
+def fun_l16_n455()
+ fun_l17_n470
+end
+
+def fun_l16_n456()
+ fun_l17_n427
+end
+
+def fun_l16_n457()
+ fun_l17_n884
+end
+
+def fun_l16_n458()
+ fun_l17_n413
+end
+
+def fun_l16_n459()
+ fun_l17_n105
+end
+
+def fun_l16_n460()
+ fun_l17_n75
+end
+
+def fun_l16_n461()
+ fun_l17_n149
+end
+
+def fun_l16_n462()
+ fun_l17_n133
+end
+
+def fun_l16_n463()
+ fun_l17_n173
+end
+
+def fun_l16_n464()
+ fun_l17_n232
+end
+
+def fun_l16_n465()
+ fun_l17_n909
+end
+
+def fun_l16_n466()
+ fun_l17_n400
+end
+
+def fun_l16_n467()
+ fun_l17_n500
+end
+
+def fun_l16_n468()
+ fun_l17_n446
+end
+
+def fun_l16_n469()
+ fun_l17_n288
+end
+
+def fun_l16_n470()
+ fun_l17_n228
+end
+
+def fun_l16_n471()
+ fun_l17_n169
+end
+
+def fun_l16_n472()
+ fun_l17_n10
+end
+
+def fun_l16_n473()
+ fun_l17_n538
+end
+
+def fun_l16_n474()
+ fun_l17_n722
+end
+
+def fun_l16_n475()
+ fun_l17_n430
+end
+
+def fun_l16_n476()
+ fun_l17_n687
+end
+
+def fun_l16_n477()
+ fun_l17_n932
+end
+
+def fun_l16_n478()
+ fun_l17_n658
+end
+
+def fun_l16_n479()
+ fun_l17_n104
+end
+
+def fun_l16_n480()
+ fun_l17_n723
+end
+
+def fun_l16_n481()
+ fun_l17_n121
+end
+
+def fun_l16_n482()
+ fun_l17_n836
+end
+
+def fun_l16_n483()
+ fun_l17_n860
+end
+
+def fun_l16_n484()
+ fun_l17_n583
+end
+
+def fun_l16_n485()
+ fun_l17_n582
+end
+
+def fun_l16_n486()
+ fun_l17_n470
+end
+
+def fun_l16_n487()
+ fun_l17_n103
+end
+
+def fun_l16_n488()
+ fun_l17_n69
+end
+
+def fun_l16_n489()
+ fun_l17_n164
+end
+
+def fun_l16_n490()
+ fun_l17_n218
+end
+
+def fun_l16_n491()
+ fun_l17_n458
+end
+
+def fun_l16_n492()
+ fun_l17_n653
+end
+
+def fun_l16_n493()
+ fun_l17_n367
+end
+
+def fun_l16_n494()
+ fun_l17_n40
+end
+
+def fun_l16_n495()
+ fun_l17_n533
+end
+
+def fun_l16_n496()
+ fun_l17_n614
+end
+
+def fun_l16_n497()
+ fun_l17_n228
+end
+
+def fun_l16_n498()
+ fun_l17_n172
+end
+
+def fun_l16_n499()
+ fun_l17_n101
+end
+
+def fun_l16_n500()
+ fun_l17_n843
+end
+
+def fun_l16_n501()
+ fun_l17_n710
+end
+
+def fun_l16_n502()
+ fun_l17_n109
+end
+
+def fun_l16_n503()
+ fun_l17_n858
+end
+
+def fun_l16_n504()
+ fun_l17_n81
+end
+
+def fun_l16_n505()
+ fun_l17_n951
+end
+
+def fun_l16_n506()
+ fun_l17_n303
+end
+
+def fun_l16_n507()
+ fun_l17_n591
+end
+
+def fun_l16_n508()
+ fun_l17_n956
+end
+
+def fun_l16_n509()
+ fun_l17_n207
+end
+
+def fun_l16_n510()
+ fun_l17_n113
+end
+
+def fun_l16_n511()
+ fun_l17_n875
+end
+
+def fun_l16_n512()
+ fun_l17_n514
+end
+
+def fun_l16_n513()
+ fun_l17_n990
+end
+
+def fun_l16_n514()
+ fun_l17_n418
+end
+
+def fun_l16_n515()
+ fun_l17_n849
+end
+
+def fun_l16_n516()
+ fun_l17_n491
+end
+
+def fun_l16_n517()
+ fun_l17_n740
+end
+
+def fun_l16_n518()
+ fun_l17_n46
+end
+
+def fun_l16_n519()
+ fun_l17_n923
+end
+
+def fun_l16_n520()
+ fun_l17_n632
+end
+
+def fun_l16_n521()
+ fun_l17_n198
+end
+
+def fun_l16_n522()
+ fun_l17_n441
+end
+
+def fun_l16_n523()
+ fun_l17_n291
+end
+
+def fun_l16_n524()
+ fun_l17_n32
+end
+
+def fun_l16_n525()
+ fun_l17_n600
+end
+
+def fun_l16_n526()
+ fun_l17_n536
+end
+
+def fun_l16_n527()
+ fun_l17_n702
+end
+
+def fun_l16_n528()
+ fun_l17_n193
+end
+
+def fun_l16_n529()
+ fun_l17_n155
+end
+
+def fun_l16_n530()
+ fun_l17_n957
+end
+
+def fun_l16_n531()
+ fun_l17_n543
+end
+
+def fun_l16_n532()
+ fun_l17_n932
+end
+
+def fun_l16_n533()
+ fun_l17_n685
+end
+
+def fun_l16_n534()
+ fun_l17_n56
+end
+
+def fun_l16_n535()
+ fun_l17_n488
+end
+
+def fun_l16_n536()
+ fun_l17_n894
+end
+
+def fun_l16_n537()
+ fun_l17_n753
+end
+
+def fun_l16_n538()
+ fun_l17_n577
+end
+
+def fun_l16_n539()
+ fun_l17_n827
+end
+
+def fun_l16_n540()
+ fun_l17_n619
+end
+
+def fun_l16_n541()
+ fun_l17_n144
+end
+
+def fun_l16_n542()
+ fun_l17_n756
+end
+
+def fun_l16_n543()
+ fun_l17_n32
+end
+
+def fun_l16_n544()
+ fun_l17_n774
+end
+
+def fun_l16_n545()
+ fun_l17_n143
+end
+
+def fun_l16_n546()
+ fun_l17_n605
+end
+
+def fun_l16_n547()
+ fun_l17_n573
+end
+
+def fun_l16_n548()
+ fun_l17_n242
+end
+
+def fun_l16_n549()
+ fun_l17_n522
+end
+
+def fun_l16_n550()
+ fun_l17_n208
+end
+
+def fun_l16_n551()
+ fun_l17_n740
+end
+
+def fun_l16_n552()
+ fun_l17_n972
+end
+
+def fun_l16_n553()
+ fun_l17_n390
+end
+
+def fun_l16_n554()
+ fun_l17_n889
+end
+
+def fun_l16_n555()
+ fun_l17_n60
+end
+
+def fun_l16_n556()
+ fun_l17_n682
+end
+
+def fun_l16_n557()
+ fun_l17_n592
+end
+
+def fun_l16_n558()
+ fun_l17_n480
+end
+
+def fun_l16_n559()
+ fun_l17_n963
+end
+
+def fun_l16_n560()
+ fun_l17_n128
+end
+
+def fun_l16_n561()
+ fun_l17_n167
+end
+
+def fun_l16_n562()
+ fun_l17_n415
+end
+
+def fun_l16_n563()
+ fun_l17_n199
+end
+
+def fun_l16_n564()
+ fun_l17_n926
+end
+
+def fun_l16_n565()
+ fun_l17_n165
+end
+
+def fun_l16_n566()
+ fun_l17_n226
+end
+
+def fun_l16_n567()
+ fun_l17_n346
+end
+
+def fun_l16_n568()
+ fun_l17_n351
+end
+
+def fun_l16_n569()
+ fun_l17_n934
+end
+
+def fun_l16_n570()
+ fun_l17_n658
+end
+
+def fun_l16_n571()
+ fun_l17_n941
+end
+
+def fun_l16_n572()
+ fun_l17_n20
+end
+
+def fun_l16_n573()
+ fun_l17_n769
+end
+
+def fun_l16_n574()
+ fun_l17_n419
+end
+
+def fun_l16_n575()
+ fun_l17_n51
+end
+
+def fun_l16_n576()
+ fun_l17_n809
+end
+
+def fun_l16_n577()
+ fun_l17_n315
+end
+
+def fun_l16_n578()
+ fun_l17_n479
+end
+
+def fun_l16_n579()
+ fun_l17_n99
+end
+
+def fun_l16_n580()
+ fun_l17_n675
+end
+
+def fun_l16_n581()
+ fun_l17_n381
+end
+
+def fun_l16_n582()
+ fun_l17_n340
+end
+
+def fun_l16_n583()
+ fun_l17_n569
+end
+
+def fun_l16_n584()
+ fun_l17_n697
+end
+
+def fun_l16_n585()
+ fun_l17_n376
+end
+
+def fun_l16_n586()
+ fun_l17_n179
+end
+
+def fun_l16_n587()
+ fun_l17_n266
+end
+
+def fun_l16_n588()
+ fun_l17_n638
+end
+
+def fun_l16_n589()
+ fun_l17_n236
+end
+
+def fun_l16_n590()
+ fun_l17_n293
+end
+
+def fun_l16_n591()
+ fun_l17_n310
+end
+
+def fun_l16_n592()
+ fun_l17_n213
+end
+
+def fun_l16_n593()
+ fun_l17_n716
+end
+
+def fun_l16_n594()
+ fun_l17_n563
+end
+
+def fun_l16_n595()
+ fun_l17_n781
+end
+
+def fun_l16_n596()
+ fun_l17_n961
+end
+
+def fun_l16_n597()
+ fun_l17_n445
+end
+
+def fun_l16_n598()
+ fun_l17_n68
+end
+
+def fun_l16_n599()
+ fun_l17_n946
+end
+
+def fun_l16_n600()
+ fun_l17_n246
+end
+
+def fun_l16_n601()
+ fun_l17_n842
+end
+
+def fun_l16_n602()
+ fun_l17_n43
+end
+
+def fun_l16_n603()
+ fun_l17_n274
+end
+
+def fun_l16_n604()
+ fun_l17_n10
+end
+
+def fun_l16_n605()
+ fun_l17_n319
+end
+
+def fun_l16_n606()
+ fun_l17_n834
+end
+
+def fun_l16_n607()
+ fun_l17_n483
+end
+
+def fun_l16_n608()
+ fun_l17_n846
+end
+
+def fun_l16_n609()
+ fun_l17_n779
+end
+
+def fun_l16_n610()
+ fun_l17_n539
+end
+
+def fun_l16_n611()
+ fun_l17_n579
+end
+
+def fun_l16_n612()
+ fun_l17_n841
+end
+
+def fun_l16_n613()
+ fun_l17_n27
+end
+
+def fun_l16_n614()
+ fun_l17_n283
+end
+
+def fun_l16_n615()
+ fun_l17_n782
+end
+
+def fun_l16_n616()
+ fun_l17_n815
+end
+
+def fun_l16_n617()
+ fun_l17_n961
+end
+
+def fun_l16_n618()
+ fun_l17_n626
+end
+
+def fun_l16_n619()
+ fun_l17_n79
+end
+
+def fun_l16_n620()
+ fun_l17_n814
+end
+
+def fun_l16_n621()
+ fun_l17_n674
+end
+
+def fun_l16_n622()
+ fun_l17_n788
+end
+
+def fun_l16_n623()
+ fun_l17_n714
+end
+
+def fun_l16_n624()
+ fun_l17_n257
+end
+
+def fun_l16_n625()
+ fun_l17_n424
+end
+
+def fun_l16_n626()
+ fun_l17_n393
+end
+
+def fun_l16_n627()
+ fun_l17_n187
+end
+
+def fun_l16_n628()
+ fun_l17_n778
+end
+
+def fun_l16_n629()
+ fun_l17_n466
+end
+
+def fun_l16_n630()
+ fun_l17_n63
+end
+
+def fun_l16_n631()
+ fun_l17_n375
+end
+
+def fun_l16_n632()
+ fun_l17_n584
+end
+
+def fun_l16_n633()
+ fun_l17_n148
+end
+
+def fun_l16_n634()
+ fun_l17_n466
+end
+
+def fun_l16_n635()
+ fun_l17_n889
+end
+
+def fun_l16_n636()
+ fun_l17_n360
+end
+
+def fun_l16_n637()
+ fun_l17_n578
+end
+
+def fun_l16_n638()
+ fun_l17_n345
+end
+
+def fun_l16_n639()
+ fun_l17_n224
+end
+
+def fun_l16_n640()
+ fun_l17_n574
+end
+
+def fun_l16_n641()
+ fun_l17_n175
+end
+
+def fun_l16_n642()
+ fun_l17_n141
+end
+
+def fun_l16_n643()
+ fun_l17_n405
+end
+
+def fun_l16_n644()
+ fun_l17_n992
+end
+
+def fun_l16_n645()
+ fun_l17_n503
+end
+
+def fun_l16_n646()
+ fun_l17_n553
+end
+
+def fun_l16_n647()
+ fun_l17_n615
+end
+
+def fun_l16_n648()
+ fun_l17_n925
+end
+
+def fun_l16_n649()
+ fun_l17_n174
+end
+
+def fun_l16_n650()
+ fun_l17_n552
+end
+
+def fun_l16_n651()
+ fun_l17_n243
+end
+
+def fun_l16_n652()
+ fun_l17_n364
+end
+
+def fun_l16_n653()
+ fun_l17_n76
+end
+
+def fun_l16_n654()
+ fun_l17_n68
+end
+
+def fun_l16_n655()
+ fun_l17_n623
+end
+
+def fun_l16_n656()
+ fun_l17_n539
+end
+
+def fun_l16_n657()
+ fun_l17_n875
+end
+
+def fun_l16_n658()
+ fun_l17_n593
+end
+
+def fun_l16_n659()
+ fun_l17_n740
+end
+
+def fun_l16_n660()
+ fun_l17_n241
+end
+
+def fun_l16_n661()
+ fun_l17_n338
+end
+
+def fun_l16_n662()
+ fun_l17_n430
+end
+
+def fun_l16_n663()
+ fun_l17_n49
+end
+
+def fun_l16_n664()
+ fun_l17_n42
+end
+
+def fun_l16_n665()
+ fun_l17_n254
+end
+
+def fun_l16_n666()
+ fun_l17_n538
+end
+
+def fun_l16_n667()
+ fun_l17_n192
+end
+
+def fun_l16_n668()
+ fun_l17_n803
+end
+
+def fun_l16_n669()
+ fun_l17_n898
+end
+
+def fun_l16_n670()
+ fun_l17_n825
+end
+
+def fun_l16_n671()
+ fun_l17_n968
+end
+
+def fun_l16_n672()
+ fun_l17_n417
+end
+
+def fun_l16_n673()
+ fun_l17_n255
+end
+
+def fun_l16_n674()
+ fun_l17_n311
+end
+
+def fun_l16_n675()
+ fun_l17_n296
+end
+
+def fun_l16_n676()
+ fun_l17_n209
+end
+
+def fun_l16_n677()
+ fun_l17_n560
+end
+
+def fun_l16_n678()
+ fun_l17_n909
+end
+
+def fun_l16_n679()
+ fun_l17_n927
+end
+
+def fun_l16_n680()
+ fun_l17_n844
+end
+
+def fun_l16_n681()
+ fun_l17_n411
+end
+
+def fun_l16_n682()
+ fun_l17_n757
+end
+
+def fun_l16_n683()
+ fun_l17_n723
+end
+
+def fun_l16_n684()
+ fun_l17_n119
+end
+
+def fun_l16_n685()
+ fun_l17_n906
+end
+
+def fun_l16_n686()
+ fun_l17_n674
+end
+
+def fun_l16_n687()
+ fun_l17_n42
+end
+
+def fun_l16_n688()
+ fun_l17_n350
+end
+
+def fun_l16_n689()
+ fun_l17_n574
+end
+
+def fun_l16_n690()
+ fun_l17_n363
+end
+
+def fun_l16_n691()
+ fun_l17_n342
+end
+
+def fun_l16_n692()
+ fun_l17_n79
+end
+
+def fun_l16_n693()
+ fun_l17_n253
+end
+
+def fun_l16_n694()
+ fun_l17_n66
+end
+
+def fun_l16_n695()
+ fun_l17_n503
+end
+
+def fun_l16_n696()
+ fun_l17_n846
+end
+
+def fun_l16_n697()
+ fun_l17_n100
+end
+
+def fun_l16_n698()
+ fun_l17_n844
+end
+
+def fun_l16_n699()
+ fun_l17_n317
+end
+
+def fun_l16_n700()
+ fun_l17_n690
+end
+
+def fun_l16_n701()
+ fun_l17_n484
+end
+
+def fun_l16_n702()
+ fun_l17_n451
+end
+
+def fun_l16_n703()
+ fun_l17_n101
+end
+
+def fun_l16_n704()
+ fun_l17_n962
+end
+
+def fun_l16_n705()
+ fun_l17_n459
+end
+
+def fun_l16_n706()
+ fun_l17_n842
+end
+
+def fun_l16_n707()
+ fun_l17_n705
+end
+
+def fun_l16_n708()
+ fun_l17_n827
+end
+
+def fun_l16_n709()
+ fun_l17_n250
+end
+
+def fun_l16_n710()
+ fun_l17_n561
+end
+
+def fun_l16_n711()
+ fun_l17_n568
+end
+
+def fun_l16_n712()
+ fun_l17_n216
+end
+
+def fun_l16_n713()
+ fun_l17_n292
+end
+
+def fun_l16_n714()
+ fun_l17_n221
+end
+
+def fun_l16_n715()
+ fun_l17_n952
+end
+
+def fun_l16_n716()
+ fun_l17_n486
+end
+
+def fun_l16_n717()
+ fun_l17_n266
+end
+
+def fun_l16_n718()
+ fun_l17_n858
+end
+
+def fun_l16_n719()
+ fun_l17_n464
+end
+
+def fun_l16_n720()
+ fun_l17_n555
+end
+
+def fun_l16_n721()
+ fun_l17_n732
+end
+
+def fun_l16_n722()
+ fun_l17_n281
+end
+
+def fun_l16_n723()
+ fun_l17_n210
+end
+
+def fun_l16_n724()
+ fun_l17_n211
+end
+
+def fun_l16_n725()
+ fun_l17_n971
+end
+
+def fun_l16_n726()
+ fun_l17_n94
+end
+
+def fun_l16_n727()
+ fun_l17_n103
+end
+
+def fun_l16_n728()
+ fun_l17_n655
+end
+
+def fun_l16_n729()
+ fun_l17_n272
+end
+
+def fun_l16_n730()
+ fun_l17_n908
+end
+
+def fun_l16_n731()
+ fun_l17_n126
+end
+
+def fun_l16_n732()
+ fun_l17_n417
+end
+
+def fun_l16_n733()
+ fun_l17_n573
+end
+
+def fun_l16_n734()
+ fun_l17_n733
+end
+
+def fun_l16_n735()
+ fun_l17_n483
+end
+
+def fun_l16_n736()
+ fun_l17_n330
+end
+
+def fun_l16_n737()
+ fun_l17_n159
+end
+
+def fun_l16_n738()
+ fun_l17_n548
+end
+
+def fun_l16_n739()
+ fun_l17_n770
+end
+
+def fun_l16_n740()
+ fun_l17_n320
+end
+
+def fun_l16_n741()
+ fun_l17_n706
+end
+
+def fun_l16_n742()
+ fun_l17_n383
+end
+
+def fun_l16_n743()
+ fun_l17_n737
+end
+
+def fun_l16_n744()
+ fun_l17_n470
+end
+
+def fun_l16_n745()
+ fun_l17_n956
+end
+
+def fun_l16_n746()
+ fun_l17_n582
+end
+
+def fun_l16_n747()
+ fun_l17_n0
+end
+
+def fun_l16_n748()
+ fun_l17_n744
+end
+
+def fun_l16_n749()
+ fun_l17_n810
+end
+
+def fun_l16_n750()
+ fun_l17_n130
+end
+
+def fun_l16_n751()
+ fun_l17_n17
+end
+
+def fun_l16_n752()
+ fun_l17_n191
+end
+
+def fun_l16_n753()
+ fun_l17_n557
+end
+
+def fun_l16_n754()
+ fun_l17_n675
+end
+
+def fun_l16_n755()
+ fun_l17_n43
+end
+
+def fun_l16_n756()
+ fun_l17_n907
+end
+
+def fun_l16_n757()
+ fun_l17_n203
+end
+
+def fun_l16_n758()
+ fun_l17_n388
+end
+
+def fun_l16_n759()
+ fun_l17_n101
+end
+
+def fun_l16_n760()
+ fun_l17_n110
+end
+
+def fun_l16_n761()
+ fun_l17_n765
+end
+
+def fun_l16_n762()
+ fun_l17_n406
+end
+
+def fun_l16_n763()
+ fun_l17_n120
+end
+
+def fun_l16_n764()
+ fun_l17_n266
+end
+
+def fun_l16_n765()
+ fun_l17_n35
+end
+
+def fun_l16_n766()
+ fun_l17_n478
+end
+
+def fun_l16_n767()
+ fun_l17_n135
+end
+
+def fun_l16_n768()
+ fun_l17_n934
+end
+
+def fun_l16_n769()
+ fun_l17_n442
+end
+
+def fun_l16_n770()
+ fun_l17_n233
+end
+
+def fun_l16_n771()
+ fun_l17_n336
+end
+
+def fun_l16_n772()
+ fun_l17_n832
+end
+
+def fun_l16_n773()
+ fun_l17_n207
+end
+
+def fun_l16_n774()
+ fun_l17_n752
+end
+
+def fun_l16_n775()
+ fun_l17_n928
+end
+
+def fun_l16_n776()
+ fun_l17_n217
+end
+
+def fun_l16_n777()
+ fun_l17_n925
+end
+
+def fun_l16_n778()
+ fun_l17_n833
+end
+
+def fun_l16_n779()
+ fun_l17_n421
+end
+
+def fun_l16_n780()
+ fun_l17_n878
+end
+
+def fun_l16_n781()
+ fun_l17_n117
+end
+
+def fun_l16_n782()
+ fun_l17_n55
+end
+
+def fun_l16_n783()
+ fun_l17_n46
+end
+
+def fun_l16_n784()
+ fun_l17_n260
+end
+
+def fun_l16_n785()
+ fun_l17_n270
+end
+
+def fun_l16_n786()
+ fun_l17_n68
+end
+
+def fun_l16_n787()
+ fun_l17_n768
+end
+
+def fun_l16_n788()
+ fun_l17_n671
+end
+
+def fun_l16_n789()
+ fun_l17_n338
+end
+
+def fun_l16_n790()
+ fun_l17_n442
+end
+
+def fun_l16_n791()
+ fun_l17_n677
+end
+
+def fun_l16_n792()
+ fun_l17_n141
+end
+
+def fun_l16_n793()
+ fun_l17_n427
+end
+
+def fun_l16_n794()
+ fun_l17_n493
+end
+
+def fun_l16_n795()
+ fun_l17_n461
+end
+
+def fun_l16_n796()
+ fun_l17_n615
+end
+
+def fun_l16_n797()
+ fun_l17_n895
+end
+
+def fun_l16_n798()
+ fun_l17_n883
+end
+
+def fun_l16_n799()
+ fun_l17_n992
+end
+
+def fun_l16_n800()
+ fun_l17_n754
+end
+
+def fun_l16_n801()
+ fun_l17_n668
+end
+
+def fun_l16_n802()
+ fun_l17_n362
+end
+
+def fun_l16_n803()
+ fun_l17_n179
+end
+
+def fun_l16_n804()
+ fun_l17_n35
+end
+
+def fun_l16_n805()
+ fun_l17_n999
+end
+
+def fun_l16_n806()
+ fun_l17_n211
+end
+
+def fun_l16_n807()
+ fun_l17_n859
+end
+
+def fun_l16_n808()
+ fun_l17_n126
+end
+
+def fun_l16_n809()
+ fun_l17_n935
+end
+
+def fun_l16_n810()
+ fun_l17_n682
+end
+
+def fun_l16_n811()
+ fun_l17_n788
+end
+
+def fun_l16_n812()
+ fun_l17_n939
+end
+
+def fun_l16_n813()
+ fun_l17_n687
+end
+
+def fun_l16_n814()
+ fun_l17_n274
+end
+
+def fun_l16_n815()
+ fun_l17_n699
+end
+
+def fun_l16_n816()
+ fun_l17_n129
+end
+
+def fun_l16_n817()
+ fun_l17_n201
+end
+
+def fun_l16_n818()
+ fun_l17_n448
+end
+
+def fun_l16_n819()
+ fun_l17_n482
+end
+
+def fun_l16_n820()
+ fun_l17_n199
+end
+
+def fun_l16_n821()
+ fun_l17_n283
+end
+
+def fun_l16_n822()
+ fun_l17_n413
+end
+
+def fun_l16_n823()
+ fun_l17_n373
+end
+
+def fun_l16_n824()
+ fun_l17_n368
+end
+
+def fun_l16_n825()
+ fun_l17_n892
+end
+
+def fun_l16_n826()
+ fun_l17_n40
+end
+
+def fun_l16_n827()
+ fun_l17_n258
+end
+
+def fun_l16_n828()
+ fun_l17_n218
+end
+
+def fun_l16_n829()
+ fun_l17_n647
+end
+
+def fun_l16_n830()
+ fun_l17_n429
+end
+
+def fun_l16_n831()
+ fun_l17_n524
+end
+
+def fun_l16_n832()
+ fun_l17_n424
+end
+
+def fun_l16_n833()
+ fun_l17_n755
+end
+
+def fun_l16_n834()
+ fun_l17_n82
+end
+
+def fun_l16_n835()
+ fun_l17_n109
+end
+
+def fun_l16_n836()
+ fun_l17_n399
+end
+
+def fun_l16_n837()
+ fun_l17_n829
+end
+
+def fun_l16_n838()
+ fun_l17_n26
+end
+
+def fun_l16_n839()
+ fun_l17_n537
+end
+
+def fun_l16_n840()
+ fun_l17_n969
+end
+
+def fun_l16_n841()
+ fun_l17_n248
+end
+
+def fun_l16_n842()
+ fun_l17_n178
+end
+
+def fun_l16_n843()
+ fun_l17_n816
+end
+
+def fun_l16_n844()
+ fun_l17_n925
+end
+
+def fun_l16_n845()
+ fun_l17_n388
+end
+
+def fun_l16_n846()
+ fun_l17_n923
+end
+
+def fun_l16_n847()
+ fun_l17_n386
+end
+
+def fun_l16_n848()
+ fun_l17_n940
+end
+
+def fun_l16_n849()
+ fun_l17_n831
+end
+
+def fun_l16_n850()
+ fun_l17_n771
+end
+
+def fun_l16_n851()
+ fun_l17_n45
+end
+
+def fun_l16_n852()
+ fun_l17_n18
+end
+
+def fun_l16_n853()
+ fun_l17_n435
+end
+
+def fun_l16_n854()
+ fun_l17_n397
+end
+
+def fun_l16_n855()
+ fun_l17_n656
+end
+
+def fun_l16_n856()
+ fun_l17_n72
+end
+
+def fun_l16_n857()
+ fun_l17_n531
+end
+
+def fun_l16_n858()
+ fun_l17_n790
+end
+
+def fun_l16_n859()
+ fun_l17_n25
+end
+
+def fun_l16_n860()
+ fun_l17_n926
+end
+
+def fun_l16_n861()
+ fun_l17_n474
+end
+
+def fun_l16_n862()
+ fun_l17_n888
+end
+
+def fun_l16_n863()
+ fun_l17_n110
+end
+
+def fun_l16_n864()
+ fun_l17_n561
+end
+
+def fun_l16_n865()
+ fun_l17_n59
+end
+
+def fun_l16_n866()
+ fun_l17_n611
+end
+
+def fun_l16_n867()
+ fun_l17_n436
+end
+
+def fun_l16_n868()
+ fun_l17_n851
+end
+
+def fun_l16_n869()
+ fun_l17_n714
+end
+
+def fun_l16_n870()
+ fun_l17_n423
+end
+
+def fun_l16_n871()
+ fun_l17_n884
+end
+
+def fun_l16_n872()
+ fun_l17_n230
+end
+
+def fun_l16_n873()
+ fun_l17_n988
+end
+
+def fun_l16_n874()
+ fun_l17_n763
+end
+
+def fun_l16_n875()
+ fun_l17_n929
+end
+
+def fun_l16_n876()
+ fun_l17_n521
+end
+
+def fun_l16_n877()
+ fun_l17_n262
+end
+
+def fun_l16_n878()
+ fun_l17_n774
+end
+
+def fun_l16_n879()
+ fun_l17_n358
+end
+
+def fun_l16_n880()
+ fun_l17_n861
+end
+
+def fun_l16_n881()
+ fun_l17_n984
+end
+
+def fun_l16_n882()
+ fun_l17_n272
+end
+
+def fun_l16_n883()
+ fun_l17_n293
+end
+
+def fun_l16_n884()
+ fun_l17_n525
+end
+
+def fun_l16_n885()
+ fun_l17_n226
+end
+
+def fun_l16_n886()
+ fun_l17_n941
+end
+
+def fun_l16_n887()
+ fun_l17_n671
+end
+
+def fun_l16_n888()
+ fun_l17_n960
+end
+
+def fun_l16_n889()
+ fun_l17_n218
+end
+
+def fun_l16_n890()
+ fun_l17_n475
+end
+
+def fun_l16_n891()
+ fun_l17_n300
+end
+
+def fun_l16_n892()
+ fun_l17_n908
+end
+
+def fun_l16_n893()
+ fun_l17_n739
+end
+
+def fun_l16_n894()
+ fun_l17_n878
+end
+
+def fun_l16_n895()
+ fun_l17_n906
+end
+
+def fun_l16_n896()
+ fun_l17_n944
+end
+
+def fun_l16_n897()
+ fun_l17_n302
+end
+
+def fun_l16_n898()
+ fun_l17_n486
+end
+
+def fun_l16_n899()
+ fun_l17_n135
+end
+
+def fun_l16_n900()
+ fun_l17_n470
+end
+
+def fun_l16_n901()
+ fun_l17_n895
+end
+
+def fun_l16_n902()
+ fun_l17_n333
+end
+
+def fun_l16_n903()
+ fun_l17_n310
+end
+
+def fun_l16_n904()
+ fun_l17_n229
+end
+
+def fun_l16_n905()
+ fun_l17_n315
+end
+
+def fun_l16_n906()
+ fun_l17_n333
+end
+
+def fun_l16_n907()
+ fun_l17_n563
+end
+
+def fun_l16_n908()
+ fun_l17_n558
+end
+
+def fun_l16_n909()
+ fun_l17_n580
+end
+
+def fun_l16_n910()
+ fun_l17_n916
+end
+
+def fun_l16_n911()
+ fun_l17_n378
+end
+
+def fun_l16_n912()
+ fun_l17_n882
+end
+
+def fun_l16_n913()
+ fun_l17_n28
+end
+
+def fun_l16_n914()
+ fun_l17_n767
+end
+
+def fun_l16_n915()
+ fun_l17_n105
+end
+
+def fun_l16_n916()
+ fun_l17_n463
+end
+
+def fun_l16_n917()
+ fun_l17_n92
+end
+
+def fun_l16_n918()
+ fun_l17_n722
+end
+
+def fun_l16_n919()
+ fun_l17_n403
+end
+
+def fun_l16_n920()
+ fun_l17_n771
+end
+
+def fun_l16_n921()
+ fun_l17_n818
+end
+
+def fun_l16_n922()
+ fun_l17_n214
+end
+
+def fun_l16_n923()
+ fun_l17_n167
+end
+
+def fun_l16_n924()
+ fun_l17_n189
+end
+
+def fun_l16_n925()
+ fun_l17_n401
+end
+
+def fun_l16_n926()
+ fun_l17_n377
+end
+
+def fun_l16_n927()
+ fun_l17_n980
+end
+
+def fun_l16_n928()
+ fun_l17_n476
+end
+
+def fun_l16_n929()
+ fun_l17_n321
+end
+
+def fun_l16_n930()
+ fun_l17_n485
+end
+
+def fun_l16_n931()
+ fun_l17_n902
+end
+
+def fun_l16_n932()
+ fun_l17_n269
+end
+
+def fun_l16_n933()
+ fun_l17_n806
+end
+
+def fun_l16_n934()
+ fun_l17_n952
+end
+
+def fun_l16_n935()
+ fun_l17_n401
+end
+
+def fun_l16_n936()
+ fun_l17_n416
+end
+
+def fun_l16_n937()
+ fun_l17_n739
+end
+
+def fun_l16_n938()
+ fun_l17_n47
+end
+
+def fun_l16_n939()
+ fun_l17_n556
+end
+
+def fun_l16_n940()
+ fun_l17_n426
+end
+
+def fun_l16_n941()
+ fun_l17_n474
+end
+
+def fun_l16_n942()
+ fun_l17_n393
+end
+
+def fun_l16_n943()
+ fun_l17_n492
+end
+
+def fun_l16_n944()
+ fun_l17_n528
+end
+
+def fun_l16_n945()
+ fun_l17_n66
+end
+
+def fun_l16_n946()
+ fun_l17_n587
+end
+
+def fun_l16_n947()
+ fun_l17_n116
+end
+
+def fun_l16_n948()
+ fun_l17_n205
+end
+
+def fun_l16_n949()
+ fun_l17_n958
+end
+
+def fun_l16_n950()
+ fun_l17_n264
+end
+
+def fun_l16_n951()
+ fun_l17_n78
+end
+
+def fun_l16_n952()
+ fun_l17_n990
+end
+
+def fun_l16_n953()
+ fun_l17_n154
+end
+
+def fun_l16_n954()
+ fun_l17_n213
+end
+
+def fun_l16_n955()
+ fun_l17_n979
+end
+
+def fun_l16_n956()
+ fun_l17_n632
+end
+
+def fun_l16_n957()
+ fun_l17_n292
+end
+
+def fun_l16_n958()
+ fun_l17_n719
+end
+
+def fun_l16_n959()
+ fun_l17_n320
+end
+
+def fun_l16_n960()
+ fun_l17_n448
+end
+
+def fun_l16_n961()
+ fun_l17_n532
+end
+
+def fun_l16_n962()
+ fun_l17_n662
+end
+
+def fun_l16_n963()
+ fun_l17_n423
+end
+
+def fun_l16_n964()
+ fun_l17_n193
+end
+
+def fun_l16_n965()
+ fun_l17_n475
+end
+
+def fun_l16_n966()
+ fun_l17_n168
+end
+
+def fun_l16_n967()
+ fun_l17_n92
+end
+
+def fun_l16_n968()
+ fun_l17_n925
+end
+
+def fun_l16_n969()
+ fun_l17_n138
+end
+
+def fun_l16_n970()
+ fun_l17_n673
+end
+
+def fun_l16_n971()
+ fun_l17_n697
+end
+
+def fun_l16_n972()
+ fun_l17_n438
+end
+
+def fun_l16_n973()
+ fun_l17_n114
+end
+
+def fun_l16_n974()
+ fun_l17_n40
+end
+
+def fun_l16_n975()
+ fun_l17_n344
+end
+
+def fun_l16_n976()
+ fun_l17_n568
+end
+
+def fun_l16_n977()
+ fun_l17_n350
+end
+
+def fun_l16_n978()
+ fun_l17_n873
+end
+
+def fun_l16_n979()
+ fun_l17_n719
+end
+
+def fun_l16_n980()
+ fun_l17_n631
+end
+
+def fun_l16_n981()
+ fun_l17_n848
+end
+
+def fun_l16_n982()
+ fun_l17_n912
+end
+
+def fun_l16_n983()
+ fun_l17_n872
+end
+
+def fun_l16_n984()
+ fun_l17_n290
+end
+
+def fun_l16_n985()
+ fun_l17_n416
+end
+
+def fun_l16_n986()
+ fun_l17_n552
+end
+
+def fun_l16_n987()
+ fun_l17_n458
+end
+
+def fun_l16_n988()
+ fun_l17_n808
+end
+
+def fun_l16_n989()
+ fun_l17_n953
+end
+
+def fun_l16_n990()
+ fun_l17_n136
+end
+
+def fun_l16_n991()
+ fun_l17_n798
+end
+
+def fun_l16_n992()
+ fun_l17_n419
+end
+
+def fun_l16_n993()
+ fun_l17_n293
+end
+
+def fun_l16_n994()
+ fun_l17_n663
+end
+
+def fun_l16_n995()
+ fun_l17_n533
+end
+
+def fun_l16_n996()
+ fun_l17_n625
+end
+
+def fun_l16_n997()
+ fun_l17_n215
+end
+
+def fun_l16_n998()
+ fun_l17_n954
+end
+
+def fun_l16_n999()
+ fun_l17_n797
+end
+
+def fun_l17_n0()
+ fun_l18_n287
+end
+
+def fun_l17_n1()
+ fun_l18_n242
+end
+
+def fun_l17_n2()
+ fun_l18_n595
+end
+
+def fun_l17_n3()
+ fun_l18_n801
+end
+
+def fun_l17_n4()
+ fun_l18_n367
+end
+
+def fun_l17_n5()
+ fun_l18_n21
+end
+
+def fun_l17_n6()
+ fun_l18_n439
+end
+
+def fun_l17_n7()
+ fun_l18_n96
+end
+
+def fun_l17_n8()
+ fun_l18_n500
+end
+
+def fun_l17_n9()
+ fun_l18_n332
+end
+
+def fun_l17_n10()
+ fun_l18_n374
+end
+
+def fun_l17_n11()
+ fun_l18_n338
+end
+
+def fun_l17_n12()
+ fun_l18_n737
+end
+
+def fun_l17_n13()
+ fun_l18_n437
+end
+
+def fun_l17_n14()
+ fun_l18_n442
+end
+
+def fun_l17_n15()
+ fun_l18_n309
+end
+
+def fun_l17_n16()
+ fun_l18_n173
+end
+
+def fun_l17_n17()
+ fun_l18_n615
+end
+
+def fun_l17_n18()
+ fun_l18_n881
+end
+
+def fun_l17_n19()
+ fun_l18_n629
+end
+
+def fun_l17_n20()
+ fun_l18_n304
+end
+
+def fun_l17_n21()
+ fun_l18_n788
+end
+
+def fun_l17_n22()
+ fun_l18_n425
+end
+
+def fun_l17_n23()
+ fun_l18_n376
+end
+
+def fun_l17_n24()
+ fun_l18_n353
+end
+
+def fun_l17_n25()
+ fun_l18_n273
+end
+
+def fun_l17_n26()
+ fun_l18_n337
+end
+
+def fun_l17_n27()
+ fun_l18_n588
+end
+
+def fun_l17_n28()
+ fun_l18_n64
+end
+
+def fun_l17_n29()
+ fun_l18_n651
+end
+
+def fun_l17_n30()
+ fun_l18_n91
+end
+
+def fun_l17_n31()
+ fun_l18_n392
+end
+
+def fun_l17_n32()
+ fun_l18_n65
+end
+
+def fun_l17_n33()
+ fun_l18_n166
+end
+
+def fun_l17_n34()
+ fun_l18_n917
+end
+
+def fun_l17_n35()
+ fun_l18_n217
+end
+
+def fun_l17_n36()
+ fun_l18_n416
+end
+
+def fun_l17_n37()
+ fun_l18_n977
+end
+
+def fun_l17_n38()
+ fun_l18_n76
+end
+
+def fun_l17_n39()
+ fun_l18_n322
+end
+
+def fun_l17_n40()
+ fun_l18_n253
+end
+
+def fun_l17_n41()
+ fun_l18_n192
+end
+
+def fun_l17_n42()
+ fun_l18_n883
+end
+
+def fun_l17_n43()
+ fun_l18_n132
+end
+
+def fun_l17_n44()
+ fun_l18_n480
+end
+
+def fun_l17_n45()
+ fun_l18_n36
+end
+
+def fun_l17_n46()
+ fun_l18_n142
+end
+
+def fun_l17_n47()
+ fun_l18_n172
+end
+
+def fun_l17_n48()
+ fun_l18_n339
+end
+
+def fun_l17_n49()
+ fun_l18_n664
+end
+
+def fun_l17_n50()
+ fun_l18_n482
+end
+
+def fun_l17_n51()
+ fun_l18_n809
+end
+
+def fun_l17_n52()
+ fun_l18_n525
+end
+
+def fun_l17_n53()
+ fun_l18_n50
+end
+
+def fun_l17_n54()
+ fun_l18_n977
+end
+
+def fun_l17_n55()
+ fun_l18_n730
+end
+
+def fun_l17_n56()
+ fun_l18_n565
+end
+
+def fun_l17_n57()
+ fun_l18_n997
+end
+
+def fun_l17_n58()
+ fun_l18_n811
+end
+
+def fun_l17_n59()
+ fun_l18_n898
+end
+
+def fun_l17_n60()
+ fun_l18_n627
+end
+
+def fun_l17_n61()
+ fun_l18_n539
+end
+
+def fun_l17_n62()
+ fun_l18_n877
+end
+
+def fun_l17_n63()
+ fun_l18_n428
+end
+
+def fun_l17_n64()
+ fun_l18_n779
+end
+
+def fun_l17_n65()
+ fun_l18_n14
+end
+
+def fun_l17_n66()
+ fun_l18_n202
+end
+
+def fun_l17_n67()
+ fun_l18_n23
+end
+
+def fun_l17_n68()
+ fun_l18_n861
+end
+
+def fun_l17_n69()
+ fun_l18_n356
+end
+
+def fun_l17_n70()
+ fun_l18_n997
+end
+
+def fun_l17_n71()
+ fun_l18_n130
+end
+
+def fun_l17_n72()
+ fun_l18_n462
+end
+
+def fun_l17_n73()
+ fun_l18_n590
+end
+
+def fun_l17_n74()
+ fun_l18_n544
+end
+
+def fun_l17_n75()
+ fun_l18_n571
+end
+
+def fun_l17_n76()
+ fun_l18_n336
+end
+
+def fun_l17_n77()
+ fun_l18_n154
+end
+
+def fun_l17_n78()
+ fun_l18_n18
+end
+
+def fun_l17_n79()
+ fun_l18_n911
+end
+
+def fun_l17_n80()
+ fun_l18_n980
+end
+
+def fun_l17_n81()
+ fun_l18_n156
+end
+
+def fun_l17_n82()
+ fun_l18_n487
+end
+
+def fun_l17_n83()
+ fun_l18_n292
+end
+
+def fun_l17_n84()
+ fun_l18_n709
+end
+
+def fun_l17_n85()
+ fun_l18_n557
+end
+
+def fun_l17_n86()
+ fun_l18_n910
+end
+
+def fun_l17_n87()
+ fun_l18_n121
+end
+
+def fun_l17_n88()
+ fun_l18_n706
+end
+
+def fun_l17_n89()
+ fun_l18_n949
+end
+
+def fun_l17_n90()
+ fun_l18_n529
+end
+
+def fun_l17_n91()
+ fun_l18_n778
+end
+
+def fun_l17_n92()
+ fun_l18_n682
+end
+
+def fun_l17_n93()
+ fun_l18_n743
+end
+
+def fun_l17_n94()
+ fun_l18_n714
+end
+
+def fun_l17_n95()
+ fun_l18_n749
+end
+
+def fun_l17_n96()
+ fun_l18_n453
+end
+
+def fun_l17_n97()
+ fun_l18_n248
+end
+
+def fun_l17_n98()
+ fun_l18_n315
+end
+
+def fun_l17_n99()
+ fun_l18_n534
+end
+
+def fun_l17_n100()
+ fun_l18_n391
+end
+
+def fun_l17_n101()
+ fun_l18_n515
+end
+
+def fun_l17_n102()
+ fun_l18_n495
+end
+
+def fun_l17_n103()
+ fun_l18_n776
+end
+
+def fun_l17_n104()
+ fun_l18_n957
+end
+
+def fun_l17_n105()
+ fun_l18_n982
+end
+
+def fun_l17_n106()
+ fun_l18_n401
+end
+
+def fun_l17_n107()
+ fun_l18_n230
+end
+
+def fun_l17_n108()
+ fun_l18_n13
+end
+
+def fun_l17_n109()
+ fun_l18_n318
+end
+
+def fun_l17_n110()
+ fun_l18_n275
+end
+
+def fun_l17_n111()
+ fun_l18_n155
+end
+
+def fun_l17_n112()
+ fun_l18_n86
+end
+
+def fun_l17_n113()
+ fun_l18_n573
+end
+
+def fun_l17_n114()
+ fun_l18_n124
+end
+
+def fun_l17_n115()
+ fun_l18_n694
+end
+
+def fun_l17_n116()
+ fun_l18_n929
+end
+
+def fun_l17_n117()
+ fun_l18_n177
+end
+
+def fun_l17_n118()
+ fun_l18_n510
+end
+
+def fun_l17_n119()
+ fun_l18_n143
+end
+
+def fun_l17_n120()
+ fun_l18_n358
+end
+
+def fun_l17_n121()
+ fun_l18_n739
+end
+
+def fun_l17_n122()
+ fun_l18_n463
+end
+
+def fun_l17_n123()
+ fun_l18_n343
+end
+
+def fun_l17_n124()
+ fun_l18_n714
+end
+
+def fun_l17_n125()
+ fun_l18_n53
+end
+
+def fun_l17_n126()
+ fun_l18_n375
+end
+
+def fun_l17_n127()
+ fun_l18_n870
+end
+
+def fun_l17_n128()
+ fun_l18_n555
+end
+
+def fun_l17_n129()
+ fun_l18_n773
+end
+
+def fun_l17_n130()
+ fun_l18_n309
+end
+
+def fun_l17_n131()
+ fun_l18_n50
+end
+
+def fun_l17_n132()
+ fun_l18_n408
+end
+
+def fun_l17_n133()
+ fun_l18_n339
+end
+
+def fun_l17_n134()
+ fun_l18_n952
+end
+
+def fun_l17_n135()
+ fun_l18_n599
+end
+
+def fun_l17_n136()
+ fun_l18_n280
+end
+
+def fun_l17_n137()
+ fun_l18_n922
+end
+
+def fun_l17_n138()
+ fun_l18_n132
+end
+
+def fun_l17_n139()
+ fun_l18_n224
+end
+
+def fun_l17_n140()
+ fun_l18_n841
+end
+
+def fun_l17_n141()
+ fun_l18_n84
+end
+
+def fun_l17_n142()
+ fun_l18_n697
+end
+
+def fun_l17_n143()
+ fun_l18_n60
+end
+
+def fun_l17_n144()
+ fun_l18_n479
+end
+
+def fun_l17_n145()
+ fun_l18_n671
+end
+
+def fun_l17_n146()
+ fun_l18_n422
+end
+
+def fun_l17_n147()
+ fun_l18_n255
+end
+
+def fun_l17_n148()
+ fun_l18_n615
+end
+
+def fun_l17_n149()
+ fun_l18_n878
+end
+
+def fun_l17_n150()
+ fun_l18_n402
+end
+
+def fun_l17_n151()
+ fun_l18_n134
+end
+
+def fun_l17_n152()
+ fun_l18_n493
+end
+
+def fun_l17_n153()
+ fun_l18_n347
+end
+
+def fun_l17_n154()
+ fun_l18_n679
+end
+
+def fun_l17_n155()
+ fun_l18_n477
+end
+
+def fun_l17_n156()
+ fun_l18_n56
+end
+
+def fun_l17_n157()
+ fun_l18_n43
+end
+
+def fun_l17_n158()
+ fun_l18_n928
+end
+
+def fun_l17_n159()
+ fun_l18_n190
+end
+
+def fun_l17_n160()
+ fun_l18_n402
+end
+
+def fun_l17_n161()
+ fun_l18_n894
+end
+
+def fun_l17_n162()
+ fun_l18_n869
+end
+
+def fun_l17_n163()
+ fun_l18_n36
+end
+
+def fun_l17_n164()
+ fun_l18_n635
+end
+
+def fun_l17_n165()
+ fun_l18_n414
+end
+
+def fun_l17_n166()
+ fun_l18_n744
+end
+
+def fun_l17_n167()
+ fun_l18_n87
+end
+
+def fun_l17_n168()
+ fun_l18_n531
+end
+
+def fun_l17_n169()
+ fun_l18_n923
+end
+
+def fun_l17_n170()
+ fun_l18_n815
+end
+
+def fun_l17_n171()
+ fun_l18_n27
+end
+
+def fun_l17_n172()
+ fun_l18_n194
+end
+
+def fun_l17_n173()
+ fun_l18_n456
+end
+
+def fun_l17_n174()
+ fun_l18_n275
+end
+
+def fun_l17_n175()
+ fun_l18_n48
+end
+
+def fun_l17_n176()
+ fun_l18_n230
+end
+
+def fun_l17_n177()
+ fun_l18_n806
+end
+
+def fun_l17_n178()
+ fun_l18_n851
+end
+
+def fun_l17_n179()
+ fun_l18_n76
+end
+
+def fun_l17_n180()
+ fun_l18_n925
+end
+
+def fun_l17_n181()
+ fun_l18_n680
+end
+
+def fun_l17_n182()
+ fun_l18_n547
+end
+
+def fun_l17_n183()
+ fun_l18_n439
+end
+
+def fun_l17_n184()
+ fun_l18_n642
+end
+
+def fun_l17_n185()
+ fun_l18_n249
+end
+
+def fun_l17_n186()
+ fun_l18_n92
+end
+
+def fun_l17_n187()
+ fun_l18_n727
+end
+
+def fun_l17_n188()
+ fun_l18_n358
+end
+
+def fun_l17_n189()
+ fun_l18_n874
+end
+
+def fun_l17_n190()
+ fun_l18_n357
+end
+
+def fun_l17_n191()
+ fun_l18_n773
+end
+
+def fun_l17_n192()
+ fun_l18_n487
+end
+
+def fun_l17_n193()
+ fun_l18_n985
+end
+
+def fun_l17_n194()
+ fun_l18_n771
+end
+
+def fun_l17_n195()
+ fun_l18_n918
+end
+
+def fun_l17_n196()
+ fun_l18_n768
+end
+
+def fun_l17_n197()
+ fun_l18_n275
+end
+
+def fun_l17_n198()
+ fun_l18_n72
+end
+
+def fun_l17_n199()
+ fun_l18_n288
+end
+
+def fun_l17_n200()
+ fun_l18_n187
+end
+
+def fun_l17_n201()
+ fun_l18_n905
+end
+
+def fun_l17_n202()
+ fun_l18_n61
+end
+
+def fun_l17_n203()
+ fun_l18_n845
+end
+
+def fun_l17_n204()
+ fun_l18_n390
+end
+
+def fun_l17_n205()
+ fun_l18_n501
+end
+
+def fun_l17_n206()
+ fun_l18_n820
+end
+
+def fun_l17_n207()
+ fun_l18_n889
+end
+
+def fun_l17_n208()
+ fun_l18_n746
+end
+
+def fun_l17_n209()
+ fun_l18_n640
+end
+
+def fun_l17_n210()
+ fun_l18_n974
+end
+
+def fun_l17_n211()
+ fun_l18_n128
+end
+
+def fun_l17_n212()
+ fun_l18_n227
+end
+
+def fun_l17_n213()
+ fun_l18_n646
+end
+
+def fun_l17_n214()
+ fun_l18_n55
+end
+
+def fun_l17_n215()
+ fun_l18_n989
+end
+
+def fun_l17_n216()
+ fun_l18_n417
+end
+
+def fun_l17_n217()
+ fun_l18_n85
+end
+
+def fun_l17_n218()
+ fun_l18_n477
+end
+
+def fun_l17_n219()
+ fun_l18_n442
+end
+
+def fun_l17_n220()
+ fun_l18_n804
+end
+
+def fun_l17_n221()
+ fun_l18_n135
+end
+
+def fun_l17_n222()
+ fun_l18_n347
+end
+
+def fun_l17_n223()
+ fun_l18_n34
+end
+
+def fun_l17_n224()
+ fun_l18_n534
+end
+
+def fun_l17_n225()
+ fun_l18_n789
+end
+
+def fun_l17_n226()
+ fun_l18_n938
+end
+
+def fun_l17_n227()
+ fun_l18_n777
+end
+
+def fun_l17_n228()
+ fun_l18_n247
+end
+
+def fun_l17_n229()
+ fun_l18_n935
+end
+
+def fun_l17_n230()
+ fun_l18_n406
+end
+
+def fun_l17_n231()
+ fun_l18_n0
+end
+
+def fun_l17_n232()
+ fun_l18_n530
+end
+
+def fun_l17_n233()
+ fun_l18_n994
+end
+
+def fun_l17_n234()
+ fun_l18_n818
+end
+
+def fun_l17_n235()
+ fun_l18_n941
+end
+
+def fun_l17_n236()
+ fun_l18_n687
+end
+
+def fun_l17_n237()
+ fun_l18_n372
+end
+
+def fun_l17_n238()
+ fun_l18_n344
+end
+
+def fun_l17_n239()
+ fun_l18_n336
+end
+
+def fun_l17_n240()
+ fun_l18_n870
+end
+
+def fun_l17_n241()
+ fun_l18_n694
+end
+
+def fun_l17_n242()
+ fun_l18_n233
+end
+
+def fun_l17_n243()
+ fun_l18_n301
+end
+
+def fun_l17_n244()
+ fun_l18_n425
+end
+
+def fun_l17_n245()
+ fun_l18_n334
+end
+
+def fun_l17_n246()
+ fun_l18_n848
+end
+
+def fun_l17_n247()
+ fun_l18_n27
+end
+
+def fun_l17_n248()
+ fun_l18_n964
+end
+
+def fun_l17_n249()
+ fun_l18_n953
+end
+
+def fun_l17_n250()
+ fun_l18_n4
+end
+
+def fun_l17_n251()
+ fun_l18_n504
+end
+
+def fun_l17_n252()
+ fun_l18_n165
+end
+
+def fun_l17_n253()
+ fun_l18_n401
+end
+
+def fun_l17_n254()
+ fun_l18_n267
+end
+
+def fun_l17_n255()
+ fun_l18_n966
+end
+
+def fun_l17_n256()
+ fun_l18_n854
+end
+
+def fun_l17_n257()
+ fun_l18_n927
+end
+
+def fun_l17_n258()
+ fun_l18_n476
+end
+
+def fun_l17_n259()
+ fun_l18_n274
+end
+
+def fun_l17_n260()
+ fun_l18_n711
+end
+
+def fun_l17_n261()
+ fun_l18_n96
+end
+
+def fun_l17_n262()
+ fun_l18_n901
+end
+
+def fun_l17_n263()
+ fun_l18_n601
+end
+
+def fun_l17_n264()
+ fun_l18_n495
+end
+
+def fun_l17_n265()
+ fun_l18_n672
+end
+
+def fun_l17_n266()
+ fun_l18_n946
+end
+
+def fun_l17_n267()
+ fun_l18_n91
+end
+
+def fun_l17_n268()
+ fun_l18_n547
+end
+
+def fun_l17_n269()
+ fun_l18_n977
+end
+
+def fun_l17_n270()
+ fun_l18_n113
+end
+
+def fun_l17_n271()
+ fun_l18_n818
+end
+
+def fun_l17_n272()
+ fun_l18_n370
+end
+
+def fun_l17_n273()
+ fun_l18_n940
+end
+
+def fun_l17_n274()
+ fun_l18_n892
+end
+
+def fun_l17_n275()
+ fun_l18_n501
+end
+
+def fun_l17_n276()
+ fun_l18_n252
+end
+
+def fun_l17_n277()
+ fun_l18_n720
+end
+
+def fun_l17_n278()
+ fun_l18_n12
+end
+
+def fun_l17_n279()
+ fun_l18_n318
+end
+
+def fun_l17_n280()
+ fun_l18_n536
+end
+
+def fun_l17_n281()
+ fun_l18_n344
+end
+
+def fun_l17_n282()
+ fun_l18_n613
+end
+
+def fun_l17_n283()
+ fun_l18_n198
+end
+
+def fun_l17_n284()
+ fun_l18_n153
+end
+
+def fun_l17_n285()
+ fun_l18_n118
+end
+
+def fun_l17_n286()
+ fun_l18_n694
+end
+
+def fun_l17_n287()
+ fun_l18_n402
+end
+
+def fun_l17_n288()
+ fun_l18_n609
+end
+
+def fun_l17_n289()
+ fun_l18_n334
+end
+
+def fun_l17_n290()
+ fun_l18_n266
+end
+
+def fun_l17_n291()
+ fun_l18_n235
+end
+
+def fun_l17_n292()
+ fun_l18_n942
+end
+
+def fun_l17_n293()
+ fun_l18_n165
+end
+
+def fun_l17_n294()
+ fun_l18_n443
+end
+
+def fun_l17_n295()
+ fun_l18_n837
+end
+
+def fun_l17_n296()
+ fun_l18_n329
+end
+
+def fun_l17_n297()
+ fun_l18_n64
+end
+
+def fun_l17_n298()
+ fun_l18_n469
+end
+
+def fun_l17_n299()
+ fun_l18_n557
+end
+
+def fun_l17_n300()
+ fun_l18_n158
+end
+
+def fun_l17_n301()
+ fun_l18_n250
+end
+
+def fun_l17_n302()
+ fun_l18_n733
+end
+
+def fun_l17_n303()
+ fun_l18_n491
+end
+
+def fun_l17_n304()
+ fun_l18_n966
+end
+
+def fun_l17_n305()
+ fun_l18_n210
+end
+
+def fun_l17_n306()
+ fun_l18_n118
+end
+
+def fun_l17_n307()
+ fun_l18_n394
+end
+
+def fun_l17_n308()
+ fun_l18_n421
+end
+
+def fun_l17_n309()
+ fun_l18_n559
+end
+
+def fun_l17_n310()
+ fun_l18_n386
+end
+
+def fun_l17_n311()
+ fun_l18_n350
+end
+
+def fun_l17_n312()
+ fun_l18_n527
+end
+
+def fun_l17_n313()
+ fun_l18_n539
+end
+
+def fun_l17_n314()
+ fun_l18_n468
+end
+
+def fun_l17_n315()
+ fun_l18_n533
+end
+
+def fun_l17_n316()
+ fun_l18_n607
+end
+
+def fun_l17_n317()
+ fun_l18_n410
+end
+
+def fun_l17_n318()
+ fun_l18_n391
+end
+
+def fun_l17_n319()
+ fun_l18_n709
+end
+
+def fun_l17_n320()
+ fun_l18_n131
+end
+
+def fun_l17_n321()
+ fun_l18_n401
+end
+
+def fun_l17_n322()
+ fun_l18_n249
+end
+
+def fun_l17_n323()
+ fun_l18_n459
+end
+
+def fun_l17_n324()
+ fun_l18_n111
+end
+
+def fun_l17_n325()
+ fun_l18_n539
+end
+
+def fun_l17_n326()
+ fun_l18_n493
+end
+
+def fun_l17_n327()
+ fun_l18_n415
+end
+
+def fun_l17_n328()
+ fun_l18_n334
+end
+
+def fun_l17_n329()
+ fun_l18_n784
+end
+
+def fun_l17_n330()
+ fun_l18_n45
+end
+
+def fun_l17_n331()
+ fun_l18_n820
+end
+
+def fun_l17_n332()
+ fun_l18_n892
+end
+
+def fun_l17_n333()
+ fun_l18_n598
+end
+
+def fun_l17_n334()
+ fun_l18_n800
+end
+
+def fun_l17_n335()
+ fun_l18_n384
+end
+
+def fun_l17_n336()
+ fun_l18_n364
+end
+
+def fun_l17_n337()
+ fun_l18_n857
+end
+
+def fun_l17_n338()
+ fun_l18_n617
+end
+
+def fun_l17_n339()
+ fun_l18_n669
+end
+
+def fun_l17_n340()
+ fun_l18_n332
+end
+
+def fun_l17_n341()
+ fun_l18_n104
+end
+
+def fun_l17_n342()
+ fun_l18_n716
+end
+
+def fun_l17_n343()
+ fun_l18_n836
+end
+
+def fun_l17_n344()
+ fun_l18_n31
+end
+
+def fun_l17_n345()
+ fun_l18_n345
+end
+
+def fun_l17_n346()
+ fun_l18_n988
+end
+
+def fun_l17_n347()
+ fun_l18_n63
+end
+
+def fun_l17_n348()
+ fun_l18_n637
+end
+
+def fun_l17_n349()
+ fun_l18_n767
+end
+
+def fun_l17_n350()
+ fun_l18_n45
+end
+
+def fun_l17_n351()
+ fun_l18_n332
+end
+
+def fun_l17_n352()
+ fun_l18_n622
+end
+
+def fun_l17_n353()
+ fun_l18_n879
+end
+
+def fun_l17_n354()
+ fun_l18_n499
+end
+
+def fun_l17_n355()
+ fun_l18_n446
+end
+
+def fun_l17_n356()
+ fun_l18_n355
+end
+
+def fun_l17_n357()
+ fun_l18_n40
+end
+
+def fun_l17_n358()
+ fun_l18_n602
+end
+
+def fun_l17_n359()
+ fun_l18_n162
+end
+
+def fun_l17_n360()
+ fun_l18_n415
+end
+
+def fun_l17_n361()
+ fun_l18_n966
+end
+
+def fun_l17_n362()
+ fun_l18_n801
+end
+
+def fun_l17_n363()
+ fun_l18_n242
+end
+
+def fun_l17_n364()
+ fun_l18_n563
+end
+
+def fun_l17_n365()
+ fun_l18_n150
+end
+
+def fun_l17_n366()
+ fun_l18_n667
+end
+
+def fun_l17_n367()
+ fun_l18_n997
+end
+
+def fun_l17_n368()
+ fun_l18_n550
+end
+
+def fun_l17_n369()
+ fun_l18_n313
+end
+
+def fun_l17_n370()
+ fun_l18_n434
+end
+
+def fun_l17_n371()
+ fun_l18_n254
+end
+
+def fun_l17_n372()
+ fun_l18_n138
+end
+
+def fun_l17_n373()
+ fun_l18_n371
+end
+
+def fun_l17_n374()
+ fun_l18_n135
+end
+
+def fun_l17_n375()
+ fun_l18_n405
+end
+
+def fun_l17_n376()
+ fun_l18_n501
+end
+
+def fun_l17_n377()
+ fun_l18_n565
+end
+
+def fun_l17_n378()
+ fun_l18_n769
+end
+
+def fun_l17_n379()
+ fun_l18_n20
+end
+
+def fun_l17_n380()
+ fun_l18_n917
+end
+
+def fun_l17_n381()
+ fun_l18_n983
+end
+
+def fun_l17_n382()
+ fun_l18_n783
+end
+
+def fun_l17_n383()
+ fun_l18_n849
+end
+
+def fun_l17_n384()
+ fun_l18_n21
+end
+
+def fun_l17_n385()
+ fun_l18_n806
+end
+
+def fun_l17_n386()
+ fun_l18_n440
+end
+
+def fun_l17_n387()
+ fun_l18_n810
+end
+
+def fun_l17_n388()
+ fun_l18_n744
+end
+
+def fun_l17_n389()
+ fun_l18_n184
+end
+
+def fun_l17_n390()
+ fun_l18_n775
+end
+
+def fun_l17_n391()
+ fun_l18_n704
+end
+
+def fun_l17_n392()
+ fun_l18_n413
+end
+
+def fun_l17_n393()
+ fun_l18_n329
+end
+
+def fun_l17_n394()
+ fun_l18_n874
+end
+
+def fun_l17_n395()
+ fun_l18_n756
+end
+
+def fun_l17_n396()
+ fun_l18_n502
+end
+
+def fun_l17_n397()
+ fun_l18_n675
+end
+
+def fun_l17_n398()
+ fun_l18_n504
+end
+
+def fun_l17_n399()
+ fun_l18_n117
+end
+
+def fun_l17_n400()
+ fun_l18_n203
+end
+
+def fun_l17_n401()
+ fun_l18_n672
+end
+
+def fun_l17_n402()
+ fun_l18_n971
+end
+
+def fun_l17_n403()
+ fun_l18_n742
+end
+
+def fun_l17_n404()
+ fun_l18_n817
+end
+
+def fun_l17_n405()
+ fun_l18_n981
+end
+
+def fun_l17_n406()
+ fun_l18_n791
+end
+
+def fun_l17_n407()
+ fun_l18_n660
+end
+
+def fun_l17_n408()
+ fun_l18_n988
+end
+
+def fun_l17_n409()
+ fun_l18_n875
+end
+
+def fun_l17_n410()
+ fun_l18_n469
+end
+
+def fun_l17_n411()
+ fun_l18_n890
+end
+
+def fun_l17_n412()
+ fun_l18_n739
+end
+
+def fun_l17_n413()
+ fun_l18_n880
+end
+
+def fun_l17_n414()
+ fun_l18_n47
+end
+
+def fun_l17_n415()
+ fun_l18_n474
+end
+
+def fun_l17_n416()
+ fun_l18_n923
+end
+
+def fun_l17_n417()
+ fun_l18_n959
+end
+
+def fun_l17_n418()
+ fun_l18_n748
+end
+
+def fun_l17_n419()
+ fun_l18_n555
+end
+
+def fun_l17_n420()
+ fun_l18_n785
+end
+
+def fun_l17_n421()
+ fun_l18_n49
+end
+
+def fun_l17_n422()
+ fun_l18_n509
+end
+
+def fun_l17_n423()
+ fun_l18_n0
+end
+
+def fun_l17_n424()
+ fun_l18_n388
+end
+
+def fun_l17_n425()
+ fun_l18_n394
+end
+
+def fun_l17_n426()
+ fun_l18_n199
+end
+
+def fun_l17_n427()
+ fun_l18_n554
+end
+
+def fun_l17_n428()
+ fun_l18_n963
+end
+
+def fun_l17_n429()
+ fun_l18_n464
+end
+
+def fun_l17_n430()
+ fun_l18_n941
+end
+
+def fun_l17_n431()
+ fun_l18_n116
+end
+
+def fun_l17_n432()
+ fun_l18_n370
+end
+
+def fun_l17_n433()
+ fun_l18_n848
+end
+
+def fun_l17_n434()
+ fun_l18_n123
+end
+
+def fun_l17_n435()
+ fun_l18_n32
+end
+
+def fun_l17_n436()
+ fun_l18_n285
+end
+
+def fun_l17_n437()
+ fun_l18_n823
+end
+
+def fun_l17_n438()
+ fun_l18_n517
+end
+
+def fun_l17_n439()
+ fun_l18_n292
+end
+
+def fun_l17_n440()
+ fun_l18_n29
+end
+
+def fun_l17_n441()
+ fun_l18_n166
+end
+
+def fun_l17_n442()
+ fun_l18_n282
+end
+
+def fun_l17_n443()
+ fun_l18_n300
+end
+
+def fun_l17_n444()
+ fun_l18_n8
+end
+
+def fun_l17_n445()
+ fun_l18_n458
+end
+
+def fun_l17_n446()
+ fun_l18_n797
+end
+
+def fun_l17_n447()
+ fun_l18_n835
+end
+
+def fun_l17_n448()
+ fun_l18_n535
+end
+
+def fun_l17_n449()
+ fun_l18_n909
+end
+
+def fun_l17_n450()
+ fun_l18_n890
+end
+
+def fun_l17_n451()
+ fun_l18_n706
+end
+
+def fun_l17_n452()
+ fun_l18_n636
+end
+
+def fun_l17_n453()
+ fun_l18_n541
+end
+
+def fun_l17_n454()
+ fun_l18_n332
+end
+
+def fun_l17_n455()
+ fun_l18_n241
+end
+
+def fun_l17_n456()
+ fun_l18_n334
+end
+
+def fun_l17_n457()
+ fun_l18_n212
+end
+
+def fun_l17_n458()
+ fun_l18_n414
+end
+
+def fun_l17_n459()
+ fun_l18_n600
+end
+
+def fun_l17_n460()
+ fun_l18_n237
+end
+
+def fun_l17_n461()
+ fun_l18_n881
+end
+
+def fun_l17_n462()
+ fun_l18_n539
+end
+
+def fun_l17_n463()
+ fun_l18_n262
+end
+
+def fun_l17_n464()
+ fun_l18_n437
+end
+
+def fun_l17_n465()
+ fun_l18_n874
+end
+
+def fun_l17_n466()
+ fun_l18_n418
+end
+
+def fun_l17_n467()
+ fun_l18_n963
+end
+
+def fun_l17_n468()
+ fun_l18_n340
+end
+
+def fun_l17_n469()
+ fun_l18_n708
+end
+
+def fun_l17_n470()
+ fun_l18_n725
+end
+
+def fun_l17_n471()
+ fun_l18_n59
+end
+
+def fun_l17_n472()
+ fun_l18_n309
+end
+
+def fun_l17_n473()
+ fun_l18_n490
+end
+
+def fun_l17_n474()
+ fun_l18_n588
+end
+
+def fun_l17_n475()
+ fun_l18_n623
+end
+
+def fun_l17_n476()
+ fun_l18_n127
+end
+
+def fun_l17_n477()
+ fun_l18_n385
+end
+
+def fun_l17_n478()
+ fun_l18_n381
+end
+
+def fun_l17_n479()
+ fun_l18_n603
+end
+
+def fun_l17_n480()
+ fun_l18_n524
+end
+
+def fun_l17_n481()
+ fun_l18_n829
+end
+
+def fun_l17_n482()
+ fun_l18_n675
+end
+
+def fun_l17_n483()
+ fun_l18_n792
+end
+
+def fun_l17_n484()
+ fun_l18_n438
+end
+
+def fun_l17_n485()
+ fun_l18_n101
+end
+
+def fun_l17_n486()
+ fun_l18_n513
+end
+
+def fun_l17_n487()
+ fun_l18_n44
+end
+
+def fun_l17_n488()
+ fun_l18_n975
+end
+
+def fun_l17_n489()
+ fun_l18_n891
+end
+
+def fun_l17_n490()
+ fun_l18_n650
+end
+
+def fun_l17_n491()
+ fun_l18_n840
+end
+
+def fun_l17_n492()
+ fun_l18_n954
+end
+
+def fun_l17_n493()
+ fun_l18_n326
+end
+
+def fun_l17_n494()
+ fun_l18_n93
+end
+
+def fun_l17_n495()
+ fun_l18_n537
+end
+
+def fun_l17_n496()
+ fun_l18_n871
+end
+
+def fun_l17_n497()
+ fun_l18_n786
+end
+
+def fun_l17_n498()
+ fun_l18_n311
+end
+
+def fun_l17_n499()
+ fun_l18_n494
+end
+
+def fun_l17_n500()
+ fun_l18_n787
+end
+
+def fun_l17_n501()
+ fun_l18_n511
+end
+
+def fun_l17_n502()
+ fun_l18_n342
+end
+
+def fun_l17_n503()
+ fun_l18_n218
+end
+
+def fun_l17_n504()
+ fun_l18_n432
+end
+
+def fun_l17_n505()
+ fun_l18_n637
+end
+
+def fun_l17_n506()
+ fun_l18_n877
+end
+
+def fun_l17_n507()
+ fun_l18_n767
+end
+
+def fun_l17_n508()
+ fun_l18_n854
+end
+
+def fun_l17_n509()
+ fun_l18_n614
+end
+
+def fun_l17_n510()
+ fun_l18_n720
+end
+
+def fun_l17_n511()
+ fun_l18_n556
+end
+
+def fun_l17_n512()
+ fun_l18_n950
+end
+
+def fun_l17_n513()
+ fun_l18_n502
+end
+
+def fun_l17_n514()
+ fun_l18_n841
+end
+
+def fun_l17_n515()
+ fun_l18_n24
+end
+
+def fun_l17_n516()
+ fun_l18_n392
+end
+
+def fun_l17_n517()
+ fun_l18_n99
+end
+
+def fun_l17_n518()
+ fun_l18_n370
+end
+
+def fun_l17_n519()
+ fun_l18_n798
+end
+
+def fun_l17_n520()
+ fun_l18_n405
+end
+
+def fun_l17_n521()
+ fun_l18_n736
+end
+
+def fun_l17_n522()
+ fun_l18_n616
+end
+
+def fun_l17_n523()
+ fun_l18_n701
+end
+
+def fun_l17_n524()
+ fun_l18_n914
+end
+
+def fun_l17_n525()
+ fun_l18_n832
+end
+
+def fun_l17_n526()
+ fun_l18_n234
+end
+
+def fun_l17_n527()
+ fun_l18_n65
+end
+
+def fun_l17_n528()
+ fun_l18_n61
+end
+
+def fun_l17_n529()
+ fun_l18_n639
+end
+
+def fun_l17_n530()
+ fun_l18_n162
+end
+
+def fun_l17_n531()
+ fun_l18_n250
+end
+
+def fun_l17_n532()
+ fun_l18_n567
+end
+
+def fun_l17_n533()
+ fun_l18_n183
+end
+
+def fun_l17_n534()
+ fun_l18_n170
+end
+
+def fun_l17_n535()
+ fun_l18_n663
+end
+
+def fun_l17_n536()
+ fun_l18_n654
+end
+
+def fun_l17_n537()
+ fun_l18_n616
+end
+
+def fun_l17_n538()
+ fun_l18_n836
+end
+
+def fun_l17_n539()
+ fun_l18_n679
+end
+
+def fun_l17_n540()
+ fun_l18_n286
+end
+
+def fun_l17_n541()
+ fun_l18_n35
+end
+
+def fun_l17_n542()
+ fun_l18_n622
+end
+
+def fun_l17_n543()
+ fun_l18_n305
+end
+
+def fun_l17_n544()
+ fun_l18_n665
+end
+
+def fun_l17_n545()
+ fun_l18_n376
+end
+
+def fun_l17_n546()
+ fun_l18_n831
+end
+
+def fun_l17_n547()
+ fun_l18_n917
+end
+
+def fun_l17_n548()
+ fun_l18_n72
+end
+
+def fun_l17_n549()
+ fun_l18_n934
+end
+
+def fun_l17_n550()
+ fun_l18_n450
+end
+
+def fun_l17_n551()
+ fun_l18_n683
+end
+
+def fun_l17_n552()
+ fun_l18_n775
+end
+
+def fun_l17_n553()
+ fun_l18_n418
+end
+
+def fun_l17_n554()
+ fun_l18_n95
+end
+
+def fun_l17_n555()
+ fun_l18_n395
+end
+
+def fun_l17_n556()
+ fun_l18_n398
+end
+
+def fun_l17_n557()
+ fun_l18_n192
+end
+
+def fun_l17_n558()
+ fun_l18_n773
+end
+
+def fun_l17_n559()
+ fun_l18_n924
+end
+
+def fun_l17_n560()
+ fun_l18_n338
+end
+
+def fun_l17_n561()
+ fun_l18_n926
+end
+
+def fun_l17_n562()
+ fun_l18_n153
+end
+
+def fun_l17_n563()
+ fun_l18_n76
+end
+
+def fun_l17_n564()
+ fun_l18_n192
+end
+
+def fun_l17_n565()
+ fun_l18_n605
+end
+
+def fun_l17_n566()
+ fun_l18_n219
+end
+
+def fun_l17_n567()
+ fun_l18_n58
+end
+
+def fun_l17_n568()
+ fun_l18_n245
+end
+
+def fun_l17_n569()
+ fun_l18_n810
+end
+
+def fun_l17_n570()
+ fun_l18_n541
+end
+
+def fun_l17_n571()
+ fun_l18_n37
+end
+
+def fun_l17_n572()
+ fun_l18_n329
+end
+
+def fun_l17_n573()
+ fun_l18_n159
+end
+
+def fun_l17_n574()
+ fun_l18_n926
+end
+
+def fun_l17_n575()
+ fun_l18_n940
+end
+
+def fun_l17_n576()
+ fun_l18_n547
+end
+
+def fun_l17_n577()
+ fun_l18_n694
+end
+
+def fun_l17_n578()
+ fun_l18_n513
+end
+
+def fun_l17_n579()
+ fun_l18_n197
+end
+
+def fun_l17_n580()
+ fun_l18_n97
+end
+
+def fun_l17_n581()
+ fun_l18_n504
+end
+
+def fun_l17_n582()
+ fun_l18_n30
+end
+
+def fun_l17_n583()
+ fun_l18_n972
+end
+
+def fun_l17_n584()
+ fun_l18_n684
+end
+
+def fun_l17_n585()
+ fun_l18_n720
+end
+
+def fun_l17_n586()
+ fun_l18_n999
+end
+
+def fun_l17_n587()
+ fun_l18_n241
+end
+
+def fun_l17_n588()
+ fun_l18_n289
+end
+
+def fun_l17_n589()
+ fun_l18_n168
+end
+
+def fun_l17_n590()
+ fun_l18_n890
+end
+
+def fun_l17_n591()
+ fun_l18_n566
+end
+
+def fun_l17_n592()
+ fun_l18_n722
+end
+
+def fun_l17_n593()
+ fun_l18_n65
+end
+
+def fun_l17_n594()
+ fun_l18_n975
+end
+
+def fun_l17_n595()
+ fun_l18_n68
+end
+
+def fun_l17_n596()
+ fun_l18_n930
+end
+
+def fun_l17_n597()
+ fun_l18_n386
+end
+
+def fun_l17_n598()
+ fun_l18_n755
+end
+
+def fun_l17_n599()
+ fun_l18_n571
+end
+
+def fun_l17_n600()
+ fun_l18_n633
+end
+
+def fun_l17_n601()
+ fun_l18_n823
+end
+
+def fun_l17_n602()
+ fun_l18_n618
+end
+
+def fun_l17_n603()
+ fun_l18_n587
+end
+
+def fun_l17_n604()
+ fun_l18_n730
+end
+
+def fun_l17_n605()
+ fun_l18_n829
+end
+
+def fun_l17_n606()
+ fun_l18_n591
+end
+
+def fun_l17_n607()
+ fun_l18_n971
+end
+
+def fun_l17_n608()
+ fun_l18_n79
+end
+
+def fun_l17_n609()
+ fun_l18_n971
+end
+
+def fun_l17_n610()
+ fun_l18_n571
+end
+
+def fun_l17_n611()
+ fun_l18_n768
+end
+
+def fun_l17_n612()
+ fun_l18_n894
+end
+
+def fun_l17_n613()
+ fun_l18_n424
+end
+
+def fun_l17_n614()
+ fun_l18_n452
+end
+
+def fun_l17_n615()
+ fun_l18_n928
+end
+
+def fun_l17_n616()
+ fun_l18_n273
+end
+
+def fun_l17_n617()
+ fun_l18_n344
+end
+
+def fun_l17_n618()
+ fun_l18_n673
+end
+
+def fun_l17_n619()
+ fun_l18_n849
+end
+
+def fun_l17_n620()
+ fun_l18_n462
+end
+
+def fun_l17_n621()
+ fun_l18_n691
+end
+
+def fun_l17_n622()
+ fun_l18_n111
+end
+
+def fun_l17_n623()
+ fun_l18_n140
+end
+
+def fun_l17_n624()
+ fun_l18_n949
+end
+
+def fun_l17_n625()
+ fun_l18_n743
+end
+
+def fun_l17_n626()
+ fun_l18_n985
+end
+
+def fun_l17_n627()
+ fun_l18_n123
+end
+
+def fun_l17_n628()
+ fun_l18_n59
+end
+
+def fun_l17_n629()
+ fun_l18_n355
+end
+
+def fun_l17_n630()
+ fun_l18_n828
+end
+
+def fun_l17_n631()
+ fun_l18_n602
+end
+
+def fun_l17_n632()
+ fun_l18_n597
+end
+
+def fun_l17_n633()
+ fun_l18_n156
+end
+
+def fun_l17_n634()
+ fun_l18_n249
+end
+
+def fun_l17_n635()
+ fun_l18_n166
+end
+
+def fun_l17_n636()
+ fun_l18_n913
+end
+
+def fun_l17_n637()
+ fun_l18_n667
+end
+
+def fun_l17_n638()
+ fun_l18_n641
+end
+
+def fun_l17_n639()
+ fun_l18_n31
+end
+
+def fun_l17_n640()
+ fun_l18_n481
+end
+
+def fun_l17_n641()
+ fun_l18_n670
+end
+
+def fun_l17_n642()
+ fun_l18_n104
+end
+
+def fun_l17_n643()
+ fun_l18_n490
+end
+
+def fun_l17_n644()
+ fun_l18_n653
+end
+
+def fun_l17_n645()
+ fun_l18_n582
+end
+
+def fun_l17_n646()
+ fun_l18_n805
+end
+
+def fun_l17_n647()
+ fun_l18_n89
+end
+
+def fun_l17_n648()
+ fun_l18_n226
+end
+
+def fun_l17_n649()
+ fun_l18_n657
+end
+
+def fun_l17_n650()
+ fun_l18_n711
+end
+
+def fun_l17_n651()
+ fun_l18_n991
+end
+
+def fun_l17_n652()
+ fun_l18_n955
+end
+
+def fun_l17_n653()
+ fun_l18_n357
+end
+
+def fun_l17_n654()
+ fun_l18_n816
+end
+
+def fun_l17_n655()
+ fun_l18_n3
+end
+
+def fun_l17_n656()
+ fun_l18_n796
+end
+
+def fun_l17_n657()
+ fun_l18_n864
+end
+
+def fun_l17_n658()
+ fun_l18_n484
+end
+
+def fun_l17_n659()
+ fun_l18_n59
+end
+
+def fun_l17_n660()
+ fun_l18_n465
+end
+
+def fun_l17_n661()
+ fun_l18_n175
+end
+
+def fun_l17_n662()
+ fun_l18_n721
+end
+
+def fun_l17_n663()
+ fun_l18_n203
+end
+
+def fun_l17_n664()
+ fun_l18_n77
+end
+
+def fun_l17_n665()
+ fun_l18_n428
+end
+
+def fun_l17_n666()
+ fun_l18_n651
+end
+
+def fun_l17_n667()
+ fun_l18_n652
+end
+
+def fun_l17_n668()
+ fun_l18_n199
+end
+
+def fun_l17_n669()
+ fun_l18_n851
+end
+
+def fun_l17_n670()
+ fun_l18_n27
+end
+
+def fun_l17_n671()
+ fun_l18_n399
+end
+
+def fun_l17_n672()
+ fun_l18_n233
+end
+
+def fun_l17_n673()
+ fun_l18_n213
+end
+
+def fun_l17_n674()
+ fun_l18_n112
+end
+
+def fun_l17_n675()
+ fun_l18_n56
+end
+
+def fun_l17_n676()
+ fun_l18_n813
+end
+
+def fun_l17_n677()
+ fun_l18_n344
+end
+
+def fun_l17_n678()
+ fun_l18_n705
+end
+
+def fun_l17_n679()
+ fun_l18_n117
+end
+
+def fun_l17_n680()
+ fun_l18_n644
+end
+
+def fun_l17_n681()
+ fun_l18_n544
+end
+
+def fun_l17_n682()
+ fun_l18_n910
+end
+
+def fun_l17_n683()
+ fun_l18_n604
+end
+
+def fun_l17_n684()
+ fun_l18_n916
+end
+
+def fun_l17_n685()
+ fun_l18_n795
+end
+
+def fun_l17_n686()
+ fun_l18_n983
+end
+
+def fun_l17_n687()
+ fun_l18_n200
+end
+
+def fun_l17_n688()
+ fun_l18_n699
+end
+
+def fun_l17_n689()
+ fun_l18_n736
+end
+
+def fun_l17_n690()
+ fun_l18_n465
+end
+
+def fun_l17_n691()
+ fun_l18_n496
+end
+
+def fun_l17_n692()
+ fun_l18_n505
+end
+
+def fun_l17_n693()
+ fun_l18_n753
+end
+
+def fun_l17_n694()
+ fun_l18_n473
+end
+
+def fun_l17_n695()
+ fun_l18_n320
+end
+
+def fun_l17_n696()
+ fun_l18_n319
+end
+
+def fun_l17_n697()
+ fun_l18_n789
+end
+
+def fun_l17_n698()
+ fun_l18_n474
+end
+
+def fun_l17_n699()
+ fun_l18_n561
+end
+
+def fun_l17_n700()
+ fun_l18_n455
+end
+
+def fun_l17_n701()
+ fun_l18_n863
+end
+
+def fun_l17_n702()
+ fun_l18_n22
+end
+
+def fun_l17_n703()
+ fun_l18_n850
+end
+
+def fun_l17_n704()
+ fun_l18_n200
+end
+
+def fun_l17_n705()
+ fun_l18_n411
+end
+
+def fun_l17_n706()
+ fun_l18_n655
+end
+
+def fun_l17_n707()
+ fun_l18_n101
+end
+
+def fun_l17_n708()
+ fun_l18_n911
+end
+
+def fun_l17_n709()
+ fun_l18_n974
+end
+
+def fun_l17_n710()
+ fun_l18_n354
+end
+
+def fun_l17_n711()
+ fun_l18_n265
+end
+
+def fun_l17_n712()
+ fun_l18_n995
+end
+
+def fun_l17_n713()
+ fun_l18_n21
+end
+
+def fun_l17_n714()
+ fun_l18_n783
+end
+
+def fun_l17_n715()
+ fun_l18_n974
+end
+
+def fun_l17_n716()
+ fun_l18_n814
+end
+
+def fun_l17_n717()
+ fun_l18_n833
+end
+
+def fun_l17_n718()
+ fun_l18_n919
+end
+
+def fun_l17_n719()
+ fun_l18_n379
+end
+
+def fun_l17_n720()
+ fun_l18_n995
+end
+
+def fun_l17_n721()
+ fun_l18_n473
+end
+
+def fun_l17_n722()
+ fun_l18_n345
+end
+
+def fun_l17_n723()
+ fun_l18_n982
+end
+
+def fun_l17_n724()
+ fun_l18_n857
+end
+
+def fun_l17_n725()
+ fun_l18_n238
+end
+
+def fun_l17_n726()
+ fun_l18_n428
+end
+
+def fun_l17_n727()
+ fun_l18_n387
+end
+
+def fun_l17_n728()
+ fun_l18_n690
+end
+
+def fun_l17_n729()
+ fun_l18_n581
+end
+
+def fun_l17_n730()
+ fun_l18_n110
+end
+
+def fun_l17_n731()
+ fun_l18_n788
+end
+
+def fun_l17_n732()
+ fun_l18_n190
+end
+
+def fun_l17_n733()
+ fun_l18_n856
+end
+
+def fun_l17_n734()
+ fun_l18_n724
+end
+
+def fun_l17_n735()
+ fun_l18_n174
+end
+
+def fun_l17_n736()
+ fun_l18_n527
+end
+
+def fun_l17_n737()
+ fun_l18_n816
+end
+
+def fun_l17_n738()
+ fun_l18_n425
+end
+
+def fun_l17_n739()
+ fun_l18_n476
+end
+
+def fun_l17_n740()
+ fun_l18_n685
+end
+
+def fun_l17_n741()
+ fun_l18_n211
+end
+
+def fun_l17_n742()
+ fun_l18_n354
+end
+
+def fun_l17_n743()
+ fun_l18_n849
+end
+
+def fun_l17_n744()
+ fun_l18_n673
+end
+
+def fun_l17_n745()
+ fun_l18_n274
+end
+
+def fun_l17_n746()
+ fun_l18_n147
+end
+
+def fun_l17_n747()
+ fun_l18_n103
+end
+
+def fun_l17_n748()
+ fun_l18_n185
+end
+
+def fun_l17_n749()
+ fun_l18_n781
+end
+
+def fun_l17_n750()
+ fun_l18_n980
+end
+
+def fun_l17_n751()
+ fun_l18_n961
+end
+
+def fun_l17_n752()
+ fun_l18_n447
+end
+
+def fun_l17_n753()
+ fun_l18_n124
+end
+
+def fun_l17_n754()
+ fun_l18_n605
+end
+
+def fun_l17_n755()
+ fun_l18_n7
+end
+
+def fun_l17_n756()
+ fun_l18_n731
+end
+
+def fun_l17_n757()
+ fun_l18_n479
+end
+
+def fun_l17_n758()
+ fun_l18_n931
+end
+
+def fun_l17_n759()
+ fun_l18_n535
+end
+
+def fun_l17_n760()
+ fun_l18_n772
+end
+
+def fun_l17_n761()
+ fun_l18_n827
+end
+
+def fun_l17_n762()
+ fun_l18_n265
+end
+
+def fun_l17_n763()
+ fun_l18_n81
+end
+
+def fun_l17_n764()
+ fun_l18_n377
+end
+
+def fun_l17_n765()
+ fun_l18_n565
+end
+
+def fun_l17_n766()
+ fun_l18_n520
+end
+
+def fun_l17_n767()
+ fun_l18_n556
+end
+
+def fun_l17_n768()
+ fun_l18_n711
+end
+
+def fun_l17_n769()
+ fun_l18_n460
+end
+
+def fun_l17_n770()
+ fun_l18_n902
+end
+
+def fun_l17_n771()
+ fun_l18_n874
+end
+
+def fun_l17_n772()
+ fun_l18_n742
+end
+
+def fun_l17_n773()
+ fun_l18_n578
+end
+
+def fun_l17_n774()
+ fun_l18_n198
+end
+
+def fun_l17_n775()
+ fun_l18_n965
+end
+
+def fun_l17_n776()
+ fun_l18_n342
+end
+
+def fun_l17_n777()
+ fun_l18_n50
+end
+
+def fun_l17_n778()
+ fun_l18_n299
+end
+
+def fun_l17_n779()
+ fun_l18_n289
+end
+
+def fun_l17_n780()
+ fun_l18_n830
+end
+
+def fun_l17_n781()
+ fun_l18_n157
+end
+
+def fun_l17_n782()
+ fun_l18_n628
+end
+
+def fun_l17_n783()
+ fun_l18_n875
+end
+
+def fun_l17_n784()
+ fun_l18_n810
+end
+
+def fun_l17_n785()
+ fun_l18_n642
+end
+
+def fun_l17_n786()
+ fun_l18_n422
+end
+
+def fun_l17_n787()
+ fun_l18_n816
+end
+
+def fun_l17_n788()
+ fun_l18_n184
+end
+
+def fun_l17_n789()
+ fun_l18_n391
+end
+
+def fun_l17_n790()
+ fun_l18_n804
+end
+
+def fun_l17_n791()
+ fun_l18_n534
+end
+
+def fun_l17_n792()
+ fun_l18_n353
+end
+
+def fun_l17_n793()
+ fun_l18_n329
+end
+
+def fun_l17_n794()
+ fun_l18_n75
+end
+
+def fun_l17_n795()
+ fun_l18_n854
+end
+
+def fun_l17_n796()
+ fun_l18_n478
+end
+
+def fun_l17_n797()
+ fun_l18_n403
+end
+
+def fun_l17_n798()
+ fun_l18_n842
+end
+
+def fun_l17_n799()
+ fun_l18_n569
+end
+
+def fun_l17_n800()
+ fun_l18_n596
+end
+
+def fun_l17_n801()
+ fun_l18_n548
+end
+
+def fun_l17_n802()
+ fun_l18_n393
+end
+
+def fun_l17_n803()
+ fun_l18_n253
+end
+
+def fun_l17_n804()
+ fun_l18_n987
+end
+
+def fun_l17_n805()
+ fun_l18_n560
+end
+
+def fun_l17_n806()
+ fun_l18_n582
+end
+
+def fun_l17_n807()
+ fun_l18_n356
+end
+
+def fun_l17_n808()
+ fun_l18_n458
+end
+
+def fun_l17_n809()
+ fun_l18_n215
+end
+
+def fun_l17_n810()
+ fun_l18_n16
+end
+
+def fun_l17_n811()
+ fun_l18_n586
+end
+
+def fun_l17_n812()
+ fun_l18_n312
+end
+
+def fun_l17_n813()
+ fun_l18_n861
+end
+
+def fun_l17_n814()
+ fun_l18_n455
+end
+
+def fun_l17_n815()
+ fun_l18_n530
+end
+
+def fun_l17_n816()
+ fun_l18_n583
+end
+
+def fun_l17_n817()
+ fun_l18_n511
+end
+
+def fun_l17_n818()
+ fun_l18_n568
+end
+
+def fun_l17_n819()
+ fun_l18_n411
+end
+
+def fun_l17_n820()
+ fun_l18_n404
+end
+
+def fun_l17_n821()
+ fun_l18_n199
+end
+
+def fun_l17_n822()
+ fun_l18_n393
+end
+
+def fun_l17_n823()
+ fun_l18_n856
+end
+
+def fun_l17_n824()
+ fun_l18_n638
+end
+
+def fun_l17_n825()
+ fun_l18_n853
+end
+
+def fun_l17_n826()
+ fun_l18_n896
+end
+
+def fun_l17_n827()
+ fun_l18_n267
+end
+
+def fun_l17_n828()
+ fun_l18_n419
+end
+
+def fun_l17_n829()
+ fun_l18_n47
+end
+
+def fun_l17_n830()
+ fun_l18_n436
+end
+
+def fun_l17_n831()
+ fun_l18_n714
+end
+
+def fun_l17_n832()
+ fun_l18_n156
+end
+
+def fun_l17_n833()
+ fun_l18_n32
+end
+
+def fun_l17_n834()
+ fun_l18_n467
+end
+
+def fun_l17_n835()
+ fun_l18_n905
+end
+
+def fun_l17_n836()
+ fun_l18_n824
+end
+
+def fun_l17_n837()
+ fun_l18_n503
+end
+
+def fun_l17_n838()
+ fun_l18_n454
+end
+
+def fun_l17_n839()
+ fun_l18_n295
+end
+
+def fun_l17_n840()
+ fun_l18_n669
+end
+
+def fun_l17_n841()
+ fun_l18_n618
+end
+
+def fun_l17_n842()
+ fun_l18_n984
+end
+
+def fun_l17_n843()
+ fun_l18_n485
+end
+
+def fun_l17_n844()
+ fun_l18_n952
+end
+
+def fun_l17_n845()
+ fun_l18_n374
+end
+
+def fun_l17_n846()
+ fun_l18_n933
+end
+
+def fun_l17_n847()
+ fun_l18_n246
+end
+
+def fun_l17_n848()
+ fun_l18_n672
+end
+
+def fun_l17_n849()
+ fun_l18_n23
+end
+
+def fun_l17_n850()
+ fun_l18_n641
+end
+
+def fun_l17_n851()
+ fun_l18_n439
+end
+
+def fun_l17_n852()
+ fun_l18_n423
+end
+
+def fun_l17_n853()
+ fun_l18_n565
+end
+
+def fun_l17_n854()
+ fun_l18_n189
+end
+
+def fun_l17_n855()
+ fun_l18_n265
+end
+
+def fun_l17_n856()
+ fun_l18_n101
+end
+
+def fun_l17_n857()
+ fun_l18_n799
+end
+
+def fun_l17_n858()
+ fun_l18_n831
+end
+
+def fun_l17_n859()
+ fun_l18_n222
+end
+
+def fun_l17_n860()
+ fun_l18_n398
+end
+
+def fun_l17_n861()
+ fun_l18_n946
+end
+
+def fun_l17_n862()
+ fun_l18_n693
+end
+
+def fun_l17_n863()
+ fun_l18_n947
+end
+
+def fun_l17_n864()
+ fun_l18_n22
+end
+
+def fun_l17_n865()
+ fun_l18_n386
+end
+
+def fun_l17_n866()
+ fun_l18_n771
+end
+
+def fun_l17_n867()
+ fun_l18_n38
+end
+
+def fun_l17_n868()
+ fun_l18_n290
+end
+
+def fun_l17_n869()
+ fun_l18_n204
+end
+
+def fun_l17_n870()
+ fun_l18_n780
+end
+
+def fun_l17_n871()
+ fun_l18_n275
+end
+
+def fun_l17_n872()
+ fun_l18_n810
+end
+
+def fun_l17_n873()
+ fun_l18_n104
+end
+
+def fun_l17_n874()
+ fun_l18_n433
+end
+
+def fun_l17_n875()
+ fun_l18_n55
+end
+
+def fun_l17_n876()
+ fun_l18_n508
+end
+
+def fun_l17_n877()
+ fun_l18_n997
+end
+
+def fun_l17_n878()
+ fun_l18_n115
+end
+
+def fun_l17_n879()
+ fun_l18_n568
+end
+
+def fun_l17_n880()
+ fun_l18_n385
+end
+
+def fun_l17_n881()
+ fun_l18_n912
+end
+
+def fun_l17_n882()
+ fun_l18_n234
+end
+
+def fun_l17_n883()
+ fun_l18_n85
+end
+
+def fun_l17_n884()
+ fun_l18_n935
+end
+
+def fun_l17_n885()
+ fun_l18_n389
+end
+
+def fun_l17_n886()
+ fun_l18_n925
+end
+
+def fun_l17_n887()
+ fun_l18_n629
+end
+
+def fun_l17_n888()
+ fun_l18_n310
+end
+
+def fun_l17_n889()
+ fun_l18_n538
+end
+
+def fun_l17_n890()
+ fun_l18_n172
+end
+
+def fun_l17_n891()
+ fun_l18_n161
+end
+
+def fun_l17_n892()
+ fun_l18_n11
+end
+
+def fun_l17_n893()
+ fun_l18_n216
+end
+
+def fun_l17_n894()
+ fun_l18_n802
+end
+
+def fun_l17_n895()
+ fun_l18_n982
+end
+
+def fun_l17_n896()
+ fun_l18_n220
+end
+
+def fun_l17_n897()
+ fun_l18_n169
+end
+
+def fun_l17_n898()
+ fun_l18_n64
+end
+
+def fun_l17_n899()
+ fun_l18_n282
+end
+
+def fun_l17_n900()
+ fun_l18_n134
+end
+
+def fun_l17_n901()
+ fun_l18_n424
+end
+
+def fun_l17_n902()
+ fun_l18_n766
+end
+
+def fun_l17_n903()
+ fun_l18_n808
+end
+
+def fun_l17_n904()
+ fun_l18_n766
+end
+
+def fun_l17_n905()
+ fun_l18_n836
+end
+
+def fun_l17_n906()
+ fun_l18_n5
+end
+
+def fun_l17_n907()
+ fun_l18_n47
+end
+
+def fun_l17_n908()
+ fun_l18_n414
+end
+
+def fun_l17_n909()
+ fun_l18_n11
+end
+
+def fun_l17_n910()
+ fun_l18_n446
+end
+
+def fun_l17_n911()
+ fun_l18_n161
+end
+
+def fun_l17_n912()
+ fun_l18_n291
+end
+
+def fun_l17_n913()
+ fun_l18_n728
+end
+
+def fun_l17_n914()
+ fun_l18_n806
+end
+
+def fun_l17_n915()
+ fun_l18_n355
+end
+
+def fun_l17_n916()
+ fun_l18_n157
+end
+
+def fun_l17_n917()
+ fun_l18_n912
+end
+
+def fun_l17_n918()
+ fun_l18_n354
+end
+
+def fun_l17_n919()
+ fun_l18_n84
+end
+
+def fun_l17_n920()
+ fun_l18_n291
+end
+
+def fun_l17_n921()
+ fun_l18_n258
+end
+
+def fun_l17_n922()
+ fun_l18_n935
+end
+
+def fun_l17_n923()
+ fun_l18_n622
+end
+
+def fun_l17_n924()
+ fun_l18_n760
+end
+
+def fun_l17_n925()
+ fun_l18_n153
+end
+
+def fun_l17_n926()
+ fun_l18_n673
+end
+
+def fun_l17_n927()
+ fun_l18_n105
+end
+
+def fun_l17_n928()
+ fun_l18_n432
+end
+
+def fun_l17_n929()
+ fun_l18_n403
+end
+
+def fun_l17_n930()
+ fun_l18_n312
+end
+
+def fun_l17_n931()
+ fun_l18_n874
+end
+
+def fun_l17_n932()
+ fun_l18_n642
+end
+
+def fun_l17_n933()
+ fun_l18_n694
+end
+
+def fun_l17_n934()
+ fun_l18_n247
+end
+
+def fun_l17_n935()
+ fun_l18_n483
+end
+
+def fun_l17_n936()
+ fun_l18_n849
+end
+
+def fun_l17_n937()
+ fun_l18_n784
+end
+
+def fun_l17_n938()
+ fun_l18_n948
+end
+
+def fun_l17_n939()
+ fun_l18_n26
+end
+
+def fun_l17_n940()
+ fun_l18_n36
+end
+
+def fun_l17_n941()
+ fun_l18_n933
+end
+
+def fun_l17_n942()
+ fun_l18_n734
+end
+
+def fun_l17_n943()
+ fun_l18_n33
+end
+
+def fun_l17_n944()
+ fun_l18_n78
+end
+
+def fun_l17_n945()
+ fun_l18_n592
+end
+
+def fun_l17_n946()
+ fun_l18_n504
+end
+
+def fun_l17_n947()
+ fun_l18_n255
+end
+
+def fun_l17_n948()
+ fun_l18_n389
+end
+
+def fun_l17_n949()
+ fun_l18_n71
+end
+
+def fun_l17_n950()
+ fun_l18_n938
+end
+
+def fun_l17_n951()
+ fun_l18_n125
+end
+
+def fun_l17_n952()
+ fun_l18_n310
+end
+
+def fun_l17_n953()
+ fun_l18_n422
+end
+
+def fun_l17_n954()
+ fun_l18_n268
+end
+
+def fun_l17_n955()
+ fun_l18_n655
+end
+
+def fun_l17_n956()
+ fun_l18_n106
+end
+
+def fun_l17_n957()
+ fun_l18_n226
+end
+
+def fun_l17_n958()
+ fun_l18_n247
+end
+
+def fun_l17_n959()
+ fun_l18_n282
+end
+
+def fun_l17_n960()
+ fun_l18_n495
+end
+
+def fun_l17_n961()
+ fun_l18_n333
+end
+
+def fun_l17_n962()
+ fun_l18_n796
+end
+
+def fun_l17_n963()
+ fun_l18_n939
+end
+
+def fun_l17_n964()
+ fun_l18_n529
+end
+
+def fun_l17_n965()
+ fun_l18_n835
+end
+
+def fun_l17_n966()
+ fun_l18_n947
+end
+
+def fun_l17_n967()
+ fun_l18_n925
+end
+
+def fun_l17_n968()
+ fun_l18_n445
+end
+
+def fun_l17_n969()
+ fun_l18_n815
+end
+
+def fun_l17_n970()
+ fun_l18_n476
+end
+
+def fun_l17_n971()
+ fun_l18_n39
+end
+
+def fun_l17_n972()
+ fun_l18_n374
+end
+
+def fun_l17_n973()
+ fun_l18_n332
+end
+
+def fun_l17_n974()
+ fun_l18_n231
+end
+
+def fun_l17_n975()
+ fun_l18_n155
+end
+
+def fun_l17_n976()
+ fun_l18_n892
+end
+
+def fun_l17_n977()
+ fun_l18_n890
+end
+
+def fun_l17_n978()
+ fun_l18_n304
+end
+
+def fun_l17_n979()
+ fun_l18_n67
+end
+
+def fun_l17_n980()
+ fun_l18_n793
+end
+
+def fun_l17_n981()
+ fun_l18_n902
+end
+
+def fun_l17_n982()
+ fun_l18_n990
+end
+
+def fun_l17_n983()
+ fun_l18_n506
+end
+
+def fun_l17_n984()
+ fun_l18_n411
+end
+
+def fun_l17_n985()
+ fun_l18_n360
+end
+
+def fun_l17_n986()
+ fun_l18_n958
+end
+
+def fun_l17_n987()
+ fun_l18_n941
+end
+
+def fun_l17_n988()
+ fun_l18_n896
+end
+
+def fun_l17_n989()
+ fun_l18_n17
+end
+
+def fun_l17_n990()
+ fun_l18_n971
+end
+
+def fun_l17_n991()
+ fun_l18_n71
+end
+
+def fun_l17_n992()
+ fun_l18_n880
+end
+
+def fun_l17_n993()
+ fun_l18_n473
+end
+
+def fun_l17_n994()
+ fun_l18_n602
+end
+
+def fun_l17_n995()
+ fun_l18_n112
+end
+
+def fun_l17_n996()
+ fun_l18_n748
+end
+
+def fun_l17_n997()
+ fun_l18_n156
+end
+
+def fun_l17_n998()
+ fun_l18_n979
+end
+
+def fun_l17_n999()
+ fun_l18_n950
+end
+
+def fun_l18_n0()
+ fun_l19_n673
+end
+
+def fun_l18_n1()
+ fun_l19_n72
+end
+
+def fun_l18_n2()
+ fun_l19_n941
+end
+
+def fun_l18_n3()
+ fun_l19_n32
+end
+
+def fun_l18_n4()
+ fun_l19_n386
+end
+
+def fun_l18_n5()
+ fun_l19_n834
+end
+
+def fun_l18_n6()
+ fun_l19_n337
+end
+
+def fun_l18_n7()
+ fun_l19_n669
+end
+
+def fun_l18_n8()
+ fun_l19_n953
+end
+
+def fun_l18_n9()
+ fun_l19_n823
+end
+
+def fun_l18_n10()
+ fun_l19_n709
+end
+
+def fun_l18_n11()
+ fun_l19_n70
+end
+
+def fun_l18_n12()
+ fun_l19_n54
+end
+
+def fun_l18_n13()
+ fun_l19_n601
+end
+
+def fun_l18_n14()
+ fun_l19_n638
+end
+
+def fun_l18_n15()
+ fun_l19_n497
+end
+
+def fun_l18_n16()
+ fun_l19_n7
+end
+
+def fun_l18_n17()
+ fun_l19_n955
+end
+
+def fun_l18_n18()
+ fun_l19_n229
+end
+
+def fun_l18_n19()
+ fun_l19_n158
+end
+
+def fun_l18_n20()
+ fun_l19_n905
+end
+
+def fun_l18_n21()
+ fun_l19_n34
+end
+
+def fun_l18_n22()
+ fun_l19_n462
+end
+
+def fun_l18_n23()
+ fun_l19_n496
+end
+
+def fun_l18_n24()
+ fun_l19_n560
+end
+
+def fun_l18_n25()
+ fun_l19_n877
+end
+
+def fun_l18_n26()
+ fun_l19_n555
+end
+
+def fun_l18_n27()
+ fun_l19_n973
+end
+
+def fun_l18_n28()
+ fun_l19_n680
+end
+
+def fun_l18_n29()
+ fun_l19_n525
+end
+
+def fun_l18_n30()
+ fun_l19_n26
+end
+
+def fun_l18_n31()
+ fun_l19_n51
+end
+
+def fun_l18_n32()
+ fun_l19_n859
+end
+
+def fun_l18_n33()
+ fun_l19_n345
+end
+
+def fun_l18_n34()
+ fun_l19_n376
+end
+
+def fun_l18_n35()
+ fun_l19_n411
+end
+
+def fun_l18_n36()
+ fun_l19_n717
+end
+
+def fun_l18_n37()
+ fun_l19_n750
+end
+
+def fun_l18_n38()
+ fun_l19_n927
+end
+
+def fun_l18_n39()
+ fun_l19_n129
+end
+
+def fun_l18_n40()
+ fun_l19_n121
+end
+
+def fun_l18_n41()
+ fun_l19_n670
+end
+
+def fun_l18_n42()
+ fun_l19_n926
+end
+
+def fun_l18_n43()
+ fun_l19_n80
+end
+
+def fun_l18_n44()
+ fun_l19_n355
+end
+
+def fun_l18_n45()
+ fun_l19_n107
+end
+
+def fun_l18_n46()
+ fun_l19_n437
+end
+
+def fun_l18_n47()
+ fun_l19_n821
+end
+
+def fun_l18_n48()
+ fun_l19_n215
+end
+
+def fun_l18_n49()
+ fun_l19_n783
+end
+
+def fun_l18_n50()
+ fun_l19_n941
+end
+
+def fun_l18_n51()
+ fun_l19_n156
+end
+
+def fun_l18_n52()
+ fun_l19_n797
+end
+
+def fun_l18_n53()
+ fun_l19_n522
+end
+
+def fun_l18_n54()
+ fun_l19_n294
+end
+
+def fun_l18_n55()
+ fun_l19_n985
+end
+
+def fun_l18_n56()
+ fun_l19_n709
+end
+
+def fun_l18_n57()
+ fun_l19_n492
+end
+
+def fun_l18_n58()
+ fun_l19_n460
+end
+
+def fun_l18_n59()
+ fun_l19_n186
+end
+
+def fun_l18_n60()
+ fun_l19_n764
+end
+
+def fun_l18_n61()
+ fun_l19_n439
+end
+
+def fun_l18_n62()
+ fun_l19_n568
+end
+
+def fun_l18_n63()
+ fun_l19_n797
+end
+
+def fun_l18_n64()
+ fun_l19_n542
+end
+
+def fun_l18_n65()
+ fun_l19_n985
+end
+
+def fun_l18_n66()
+ fun_l19_n787
+end
+
+def fun_l18_n67()
+ fun_l19_n447
+end
+
+def fun_l18_n68()
+ fun_l19_n567
+end
+
+def fun_l18_n69()
+ fun_l19_n406
+end
+
+def fun_l18_n70()
+ fun_l19_n984
+end
+
+def fun_l18_n71()
+ fun_l19_n58
+end
+
+def fun_l18_n72()
+ fun_l19_n820
+end
+
+def fun_l18_n73()
+ fun_l19_n831
+end
+
+def fun_l18_n74()
+ fun_l19_n533
+end
+
+def fun_l18_n75()
+ fun_l19_n277
+end
+
+def fun_l18_n76()
+ fun_l19_n92
+end
+
+def fun_l18_n77()
+ fun_l19_n965
+end
+
+def fun_l18_n78()
+ fun_l19_n127
+end
+
+def fun_l18_n79()
+ fun_l19_n728
+end
+
+def fun_l18_n80()
+ fun_l19_n672
+end
+
+def fun_l18_n81()
+ fun_l19_n748
+end
+
+def fun_l18_n82()
+ fun_l19_n485
+end
+
+def fun_l18_n83()
+ fun_l19_n815
+end
+
+def fun_l18_n84()
+ fun_l19_n957
+end
+
+def fun_l18_n85()
+ fun_l19_n884
+end
+
+def fun_l18_n86()
+ fun_l19_n107
+end
+
+def fun_l18_n87()
+ fun_l19_n255
+end
+
+def fun_l18_n88()
+ fun_l19_n498
+end
+
+def fun_l18_n89()
+ fun_l19_n589
+end
+
+def fun_l18_n90()
+ fun_l19_n726
+end
+
+def fun_l18_n91()
+ fun_l19_n755
+end
+
+def fun_l18_n92()
+ fun_l19_n855
+end
+
+def fun_l18_n93()
+ fun_l19_n490
+end
+
+def fun_l18_n94()
+ fun_l19_n463
+end
+
+def fun_l18_n95()
+ fun_l19_n213
+end
+
+def fun_l18_n96()
+ fun_l19_n946
+end
+
+def fun_l18_n97()
+ fun_l19_n319
+end
+
+def fun_l18_n98()
+ fun_l19_n565
+end
+
+def fun_l18_n99()
+ fun_l19_n805
+end
+
+def fun_l18_n100()
+ fun_l19_n21
+end
+
+def fun_l18_n101()
+ fun_l19_n168
+end
+
+def fun_l18_n102()
+ fun_l19_n462
+end
+
+def fun_l18_n103()
+ fun_l19_n15
+end
+
+def fun_l18_n104()
+ fun_l19_n408
+end
+
+def fun_l18_n105()
+ fun_l19_n736
+end
+
+def fun_l18_n106()
+ fun_l19_n313
+end
+
+def fun_l18_n107()
+ fun_l19_n736
+end
+
+def fun_l18_n108()
+ fun_l19_n703
+end
+
+def fun_l18_n109()
+ fun_l19_n456
+end
+
+def fun_l18_n110()
+ fun_l19_n467
+end
+
+def fun_l18_n111()
+ fun_l19_n287
+end
+
+def fun_l18_n112()
+ fun_l19_n630
+end
+
+def fun_l18_n113()
+ fun_l19_n499
+end
+
+def fun_l18_n114()
+ fun_l19_n308
+end
+
+def fun_l18_n115()
+ fun_l19_n902
+end
+
+def fun_l18_n116()
+ fun_l19_n894
+end
+
+def fun_l18_n117()
+ fun_l19_n545
+end
+
+def fun_l18_n118()
+ fun_l19_n467
+end
+
+def fun_l18_n119()
+ fun_l19_n791
+end
+
+def fun_l18_n120()
+ fun_l19_n845
+end
+
+def fun_l18_n121()
+ fun_l19_n376
+end
+
+def fun_l18_n122()
+ fun_l19_n898
+end
+
+def fun_l18_n123()
+ fun_l19_n200
+end
+
+def fun_l18_n124()
+ fun_l19_n415
+end
+
+def fun_l18_n125()
+ fun_l19_n80
+end
+
+def fun_l18_n126()
+ fun_l19_n6
+end
+
+def fun_l18_n127()
+ fun_l19_n150
+end
+
+def fun_l18_n128()
+ fun_l19_n223
+end
+
+def fun_l18_n129()
+ fun_l19_n179
+end
+
+def fun_l18_n130()
+ fun_l19_n687
+end
+
+def fun_l18_n131()
+ fun_l19_n625
+end
+
+def fun_l18_n132()
+ fun_l19_n332
+end
+
+def fun_l18_n133()
+ fun_l19_n87
+end
+
+def fun_l18_n134()
+ fun_l19_n469
+end
+
+def fun_l18_n135()
+ fun_l19_n4
+end
+
+def fun_l18_n136()
+ fun_l19_n142
+end
+
+def fun_l18_n137()
+ fun_l19_n506
+end
+
+def fun_l18_n138()
+ fun_l19_n227
+end
+
+def fun_l18_n139()
+ fun_l19_n332
+end
+
+def fun_l18_n140()
+ fun_l19_n18
+end
+
+def fun_l18_n141()
+ fun_l19_n773
+end
+
+def fun_l18_n142()
+ fun_l19_n306
+end
+
+def fun_l18_n143()
+ fun_l19_n376
+end
+
+def fun_l18_n144()
+ fun_l19_n524
+end
+
+def fun_l18_n145()
+ fun_l19_n61
+end
+
+def fun_l18_n146()
+ fun_l19_n635
+end
+
+def fun_l18_n147()
+ fun_l19_n816
+end
+
+def fun_l18_n148()
+ fun_l19_n398
+end
+
+def fun_l18_n149()
+ fun_l19_n408
+end
+
+def fun_l18_n150()
+ fun_l19_n889
+end
+
+def fun_l18_n151()
+ fun_l19_n167
+end
+
+def fun_l18_n152()
+ fun_l19_n436
+end
+
+def fun_l18_n153()
+ fun_l19_n738
+end
+
+def fun_l18_n154()
+ fun_l19_n382
+end
+
+def fun_l18_n155()
+ fun_l19_n260
+end
+
+def fun_l18_n156()
+ fun_l19_n227
+end
+
+def fun_l18_n157()
+ fun_l19_n191
+end
+
+def fun_l18_n158()
+ fun_l19_n269
+end
+
+def fun_l18_n159()
+ fun_l19_n599
+end
+
+def fun_l18_n160()
+ fun_l19_n992
+end
+
+def fun_l18_n161()
+ fun_l19_n754
+end
+
+def fun_l18_n162()
+ fun_l19_n578
+end
+
+def fun_l18_n163()
+ fun_l19_n162
+end
+
+def fun_l18_n164()
+ fun_l19_n88
+end
+
+def fun_l18_n165()
+ fun_l19_n592
+end
+
+def fun_l18_n166()
+ fun_l19_n621
+end
+
+def fun_l18_n167()
+ fun_l19_n398
+end
+
+def fun_l18_n168()
+ fun_l19_n585
+end
+
+def fun_l18_n169()
+ fun_l19_n51
+end
+
+def fun_l18_n170()
+ fun_l19_n715
+end
+
+def fun_l18_n171()
+ fun_l19_n841
+end
+
+def fun_l18_n172()
+ fun_l19_n882
+end
+
+def fun_l18_n173()
+ fun_l19_n676
+end
+
+def fun_l18_n174()
+ fun_l19_n93
+end
+
+def fun_l18_n175()
+ fun_l19_n41
+end
+
+def fun_l18_n176()
+ fun_l19_n565
+end
+
+def fun_l18_n177()
+ fun_l19_n895
+end
+
+def fun_l18_n178()
+ fun_l19_n743
+end
+
+def fun_l18_n179()
+ fun_l19_n679
+end
+
+def fun_l18_n180()
+ fun_l19_n77
+end
+
+def fun_l18_n181()
+ fun_l19_n539
+end
+
+def fun_l18_n182()
+ fun_l19_n439
+end
+
+def fun_l18_n183()
+ fun_l19_n758
+end
+
+def fun_l18_n184()
+ fun_l19_n327
+end
+
+def fun_l18_n185()
+ fun_l19_n257
+end
+
+def fun_l18_n186()
+ fun_l19_n544
+end
+
+def fun_l18_n187()
+ fun_l19_n632
+end
+
+def fun_l18_n188()
+ fun_l19_n83
+end
+
+def fun_l18_n189()
+ fun_l19_n88
+end
+
+def fun_l18_n190()
+ fun_l19_n244
+end
+
+def fun_l18_n191()
+ fun_l19_n403
+end
+
+def fun_l18_n192()
+ fun_l19_n644
+end
+
+def fun_l18_n193()
+ fun_l19_n953
+end
+
+def fun_l18_n194()
+ fun_l19_n690
+end
+
+def fun_l18_n195()
+ fun_l19_n534
+end
+
+def fun_l18_n196()
+ fun_l19_n352
+end
+
+def fun_l18_n197()
+ fun_l19_n502
+end
+
+def fun_l18_n198()
+ fun_l19_n924
+end
+
+def fun_l18_n199()
+ fun_l19_n815
+end
+
+def fun_l18_n200()
+ fun_l19_n910
+end
+
+def fun_l18_n201()
+ fun_l19_n391
+end
+
+def fun_l18_n202()
+ fun_l19_n144
+end
+
+def fun_l18_n203()
+ fun_l19_n823
+end
+
+def fun_l18_n204()
+ fun_l19_n732
+end
+
+def fun_l18_n205()
+ fun_l19_n109
+end
+
+def fun_l18_n206()
+ fun_l19_n677
+end
+
+def fun_l18_n207()
+ fun_l19_n736
+end
+
+def fun_l18_n208()
+ fun_l19_n141
+end
+
+def fun_l18_n209()
+ fun_l19_n45
+end
+
+def fun_l18_n210()
+ fun_l19_n11
+end
+
+def fun_l18_n211()
+ fun_l19_n924
+end
+
+def fun_l18_n212()
+ fun_l19_n940
+end
+
+def fun_l18_n213()
+ fun_l19_n683
+end
+
+def fun_l18_n214()
+ fun_l19_n383
+end
+
+def fun_l18_n215()
+ fun_l19_n798
+end
+
+def fun_l18_n216()
+ fun_l19_n99
+end
+
+def fun_l18_n217()
+ fun_l19_n814
+end
+
+def fun_l18_n218()
+ fun_l19_n827
+end
+
+def fun_l18_n219()
+ fun_l19_n629
+end
+
+def fun_l18_n220()
+ fun_l19_n814
+end
+
+def fun_l18_n221()
+ fun_l19_n452
+end
+
+def fun_l18_n222()
+ fun_l19_n388
+end
+
+def fun_l18_n223()
+ fun_l19_n324
+end
+
+def fun_l18_n224()
+ fun_l19_n233
+end
+
+def fun_l18_n225()
+ fun_l19_n596
+end
+
+def fun_l18_n226()
+ fun_l19_n396
+end
+
+def fun_l18_n227()
+ fun_l19_n529
+end
+
+def fun_l18_n228()
+ fun_l19_n603
+end
+
+def fun_l18_n229()
+ fun_l19_n76
+end
+
+def fun_l18_n230()
+ fun_l19_n799
+end
+
+def fun_l18_n231()
+ fun_l19_n576
+end
+
+def fun_l18_n232()
+ fun_l19_n35
+end
+
+def fun_l18_n233()
+ fun_l19_n883
+end
+
+def fun_l18_n234()
+ fun_l19_n776
+end
+
+def fun_l18_n235()
+ fun_l19_n478
+end
+
+def fun_l18_n236()
+ fun_l19_n922
+end
+
+def fun_l18_n237()
+ fun_l19_n636
+end
+
+def fun_l18_n238()
+ fun_l19_n680
+end
+
+def fun_l18_n239()
+ fun_l19_n735
+end
+
+def fun_l18_n240()
+ fun_l19_n893
+end
+
+def fun_l18_n241()
+ fun_l19_n785
+end
+
+def fun_l18_n242()
+ fun_l19_n325
+end
+
+def fun_l18_n243()
+ fun_l19_n25
+end
+
+def fun_l18_n244()
+ fun_l19_n930
+end
+
+def fun_l18_n245()
+ fun_l19_n747
+end
+
+def fun_l18_n246()
+ fun_l19_n808
+end
+
+def fun_l18_n247()
+ fun_l19_n356
+end
+
+def fun_l18_n248()
+ fun_l19_n16
+end
+
+def fun_l18_n249()
+ fun_l19_n191
+end
+
+def fun_l18_n250()
+ fun_l19_n772
+end
+
+def fun_l18_n251()
+ fun_l19_n247
+end
+
+def fun_l18_n252()
+ fun_l19_n112
+end
+
+def fun_l18_n253()
+ fun_l19_n22
+end
+
+def fun_l18_n254()
+ fun_l19_n15
+end
+
+def fun_l18_n255()
+ fun_l19_n444
+end
+
+def fun_l18_n256()
+ fun_l19_n498
+end
+
+def fun_l18_n257()
+ fun_l19_n403
+end
+
+def fun_l18_n258()
+ fun_l19_n572
+end
+
+def fun_l18_n259()
+ fun_l19_n451
+end
+
+def fun_l18_n260()
+ fun_l19_n224
+end
+
+def fun_l18_n261()
+ fun_l19_n197
+end
+
+def fun_l18_n262()
+ fun_l19_n891
+end
+
+def fun_l18_n263()
+ fun_l19_n612
+end
+
+def fun_l18_n264()
+ fun_l19_n107
+end
+
+def fun_l18_n265()
+ fun_l19_n267
+end
+
+def fun_l18_n266()
+ fun_l19_n746
+end
+
+def fun_l18_n267()
+ fun_l19_n547
+end
+
+def fun_l18_n268()
+ fun_l19_n608
+end
+
+def fun_l18_n269()
+ fun_l19_n474
+end
+
+def fun_l18_n270()
+ fun_l19_n285
+end
+
+def fun_l18_n271()
+ fun_l19_n970
+end
+
+def fun_l18_n272()
+ fun_l19_n227
+end
+
+def fun_l18_n273()
+ fun_l19_n440
+end
+
+def fun_l18_n274()
+ fun_l19_n816
+end
+
+def fun_l18_n275()
+ fun_l19_n320
+end
+
+def fun_l18_n276()
+ fun_l19_n237
+end
+
+def fun_l18_n277()
+ fun_l19_n37
+end
+
+def fun_l18_n278()
+ fun_l19_n408
+end
+
+def fun_l18_n279()
+ fun_l19_n229
+end
+
+def fun_l18_n280()
+ fun_l19_n576
+end
+
+def fun_l18_n281()
+ fun_l19_n422
+end
+
+def fun_l18_n282()
+ fun_l19_n725
+end
+
+def fun_l18_n283()
+ fun_l19_n498
+end
+
+def fun_l18_n284()
+ fun_l19_n28
+end
+
+def fun_l18_n285()
+ fun_l19_n711
+end
+
+def fun_l18_n286()
+ fun_l19_n222
+end
+
+def fun_l18_n287()
+ fun_l19_n688
+end
+
+def fun_l18_n288()
+ fun_l19_n885
+end
+
+def fun_l18_n289()
+ fun_l19_n522
+end
+
+def fun_l18_n290()
+ fun_l19_n776
+end
+
+def fun_l18_n291()
+ fun_l19_n862
+end
+
+def fun_l18_n292()
+ fun_l19_n415
+end
+
+def fun_l18_n293()
+ fun_l19_n194
+end
+
+def fun_l18_n294()
+ fun_l19_n652
+end
+
+def fun_l18_n295()
+ fun_l19_n929
+end
+
+def fun_l18_n296()
+ fun_l19_n923
+end
+
+def fun_l18_n297()
+ fun_l19_n104
+end
+
+def fun_l18_n298()
+ fun_l19_n191
+end
+
+def fun_l18_n299()
+ fun_l19_n996
+end
+
+def fun_l18_n300()
+ fun_l19_n426
+end
+
+def fun_l18_n301()
+ fun_l19_n698
+end
+
+def fun_l18_n302()
+ fun_l19_n397
+end
+
+def fun_l18_n303()
+ fun_l19_n287
+end
+
+def fun_l18_n304()
+ fun_l19_n731
+end
+
+def fun_l18_n305()
+ fun_l19_n162
+end
+
+def fun_l18_n306()
+ fun_l19_n794
+end
+
+def fun_l18_n307()
+ fun_l19_n234
+end
+
+def fun_l18_n308()
+ fun_l19_n184
+end
+
+def fun_l18_n309()
+ fun_l19_n314
+end
+
+def fun_l18_n310()
+ fun_l19_n259
+end
+
+def fun_l18_n311()
+ fun_l19_n687
+end
+
+def fun_l18_n312()
+ fun_l19_n653
+end
+
+def fun_l18_n313()
+ fun_l19_n834
+end
+
+def fun_l18_n314()
+ fun_l19_n519
+end
+
+def fun_l18_n315()
+ fun_l19_n706
+end
+
+def fun_l18_n316()
+ fun_l19_n860
+end
+
+def fun_l18_n317()
+ fun_l19_n99
+end
+
+def fun_l18_n318()
+ fun_l19_n757
+end
+
+def fun_l18_n319()
+ fun_l19_n860
+end
+
+def fun_l18_n320()
+ fun_l19_n266
+end
+
+def fun_l18_n321()
+ fun_l19_n802
+end
+
+def fun_l18_n322()
+ fun_l19_n349
+end
+
+def fun_l18_n323()
+ fun_l19_n408
+end
+
+def fun_l18_n324()
+ fun_l19_n539
+end
+
+def fun_l18_n325()
+ fun_l19_n696
+end
+
+def fun_l18_n326()
+ fun_l19_n233
+end
+
+def fun_l18_n327()
+ fun_l19_n476
+end
+
+def fun_l18_n328()
+ fun_l19_n101
+end
+
+def fun_l18_n329()
+ fun_l19_n881
+end
+
+def fun_l18_n330()
+ fun_l19_n699
+end
+
+def fun_l18_n331()
+ fun_l19_n559
+end
+
+def fun_l18_n332()
+ fun_l19_n990
+end
+
+def fun_l18_n333()
+ fun_l19_n382
+end
+
+def fun_l18_n334()
+ fun_l19_n941
+end
+
+def fun_l18_n335()
+ fun_l19_n363
+end
+
+def fun_l18_n336()
+ fun_l19_n870
+end
+
+def fun_l18_n337()
+ fun_l19_n250
+end
+
+def fun_l18_n338()
+ fun_l19_n209
+end
+
+def fun_l18_n339()
+ fun_l19_n156
+end
+
+def fun_l18_n340()
+ fun_l19_n320
+end
+
+def fun_l18_n341()
+ fun_l19_n320
+end
+
+def fun_l18_n342()
+ fun_l19_n68
+end
+
+def fun_l18_n343()
+ fun_l19_n823
+end
+
+def fun_l18_n344()
+ fun_l19_n713
+end
+
+def fun_l18_n345()
+ fun_l19_n893
+end
+
+def fun_l18_n346()
+ fun_l19_n628
+end
+
+def fun_l18_n347()
+ fun_l19_n429
+end
+
+def fun_l18_n348()
+ fun_l19_n766
+end
+
+def fun_l18_n349()
+ fun_l19_n937
+end
+
+def fun_l18_n350()
+ fun_l19_n983
+end
+
+def fun_l18_n351()
+ fun_l19_n131
+end
+
+def fun_l18_n352()
+ fun_l19_n76
+end
+
+def fun_l18_n353()
+ fun_l19_n225
+end
+
+def fun_l18_n354()
+ fun_l19_n979
+end
+
+def fun_l18_n355()
+ fun_l19_n279
+end
+
+def fun_l18_n356()
+ fun_l19_n434
+end
+
+def fun_l18_n357()
+ fun_l19_n723
+end
+
+def fun_l18_n358()
+ fun_l19_n44
+end
+
+def fun_l18_n359()
+ fun_l19_n895
+end
+
+def fun_l18_n360()
+ fun_l19_n602
+end
+
+def fun_l18_n361()
+ fun_l19_n420
+end
+
+def fun_l18_n362()
+ fun_l19_n318
+end
+
+def fun_l18_n363()
+ fun_l19_n990
+end
+
+def fun_l18_n364()
+ fun_l19_n318
+end
+
+def fun_l18_n365()
+ fun_l19_n640
+end
+
+def fun_l18_n366()
+ fun_l19_n679
+end
+
+def fun_l18_n367()
+ fun_l19_n572
+end
+
+def fun_l18_n368()
+ fun_l19_n411
+end
+
+def fun_l18_n369()
+ fun_l19_n703
+end
+
+def fun_l18_n370()
+ fun_l19_n39
+end
+
+def fun_l18_n371()
+ fun_l19_n656
+end
+
+def fun_l18_n372()
+ fun_l19_n960
+end
+
+def fun_l18_n373()
+ fun_l19_n491
+end
+
+def fun_l18_n374()
+ fun_l19_n916
+end
+
+def fun_l18_n375()
+ fun_l19_n413
+end
+
+def fun_l18_n376()
+ fun_l19_n90
+end
+
+def fun_l18_n377()
+ fun_l19_n790
+end
+
+def fun_l18_n378()
+ fun_l19_n424
+end
+
+def fun_l18_n379()
+ fun_l19_n578
+end
+
+def fun_l18_n380()
+ fun_l19_n555
+end
+
+def fun_l18_n381()
+ fun_l19_n405
+end
+
+def fun_l18_n382()
+ fun_l19_n378
+end
+
+def fun_l18_n383()
+ fun_l19_n594
+end
+
+def fun_l18_n384()
+ fun_l19_n593
+end
+
+def fun_l18_n385()
+ fun_l19_n115
+end
+
+def fun_l18_n386()
+ fun_l19_n67
+end
+
+def fun_l18_n387()
+ fun_l19_n531
+end
+
+def fun_l18_n388()
+ fun_l19_n7
+end
+
+def fun_l18_n389()
+ fun_l19_n535
+end
+
+def fun_l18_n390()
+ fun_l19_n35
+end
+
+def fun_l18_n391()
+ fun_l19_n410
+end
+
+def fun_l18_n392()
+ fun_l19_n811
+end
+
+def fun_l18_n393()
+ fun_l19_n719
+end
+
+def fun_l18_n394()
+ fun_l19_n859
+end
+
+def fun_l18_n395()
+ fun_l19_n491
+end
+
+def fun_l18_n396()
+ fun_l19_n131
+end
+
+def fun_l18_n397()
+ fun_l19_n501
+end
+
+def fun_l18_n398()
+ fun_l19_n917
+end
+
+def fun_l18_n399()
+ fun_l19_n467
+end
+
+def fun_l18_n400()
+ fun_l19_n189
+end
+
+def fun_l18_n401()
+ fun_l19_n135
+end
+
+def fun_l18_n402()
+ fun_l19_n105
+end
+
+def fun_l18_n403()
+ fun_l19_n120
+end
+
+def fun_l18_n404()
+ fun_l19_n611
+end
+
+def fun_l18_n405()
+ fun_l19_n386
+end
+
+def fun_l18_n406()
+ fun_l19_n239
+end
+
+def fun_l18_n407()
+ fun_l19_n717
+end
+
+def fun_l18_n408()
+ fun_l19_n425
+end
+
+def fun_l18_n409()
+ fun_l19_n500
+end
+
+def fun_l18_n410()
+ fun_l19_n424
+end
+
+def fun_l18_n411()
+ fun_l19_n654
+end
+
+def fun_l18_n412()
+ fun_l19_n243
+end
+
+def fun_l18_n413()
+ fun_l19_n920
+end
+
+def fun_l18_n414()
+ fun_l19_n556
+end
+
+def fun_l18_n415()
+ fun_l19_n693
+end
+
+def fun_l18_n416()
+ fun_l19_n656
+end
+
+def fun_l18_n417()
+ fun_l19_n596
+end
+
+def fun_l18_n418()
+ fun_l19_n573
+end
+
+def fun_l18_n419()
+ fun_l19_n504
+end
+
+def fun_l18_n420()
+ fun_l19_n5
+end
+
+def fun_l18_n421()
+ fun_l19_n554
+end
+
+def fun_l18_n422()
+ fun_l19_n852
+end
+
+def fun_l18_n423()
+ fun_l19_n725
+end
+
+def fun_l18_n424()
+ fun_l19_n121
+end
+
+def fun_l18_n425()
+ fun_l19_n184
+end
+
+def fun_l18_n426()
+ fun_l19_n752
+end
+
+def fun_l18_n427()
+ fun_l19_n636
+end
+
+def fun_l18_n428()
+ fun_l19_n858
+end
+
+def fun_l18_n429()
+ fun_l19_n249
+end
+
+def fun_l18_n430()
+ fun_l19_n696
+end
+
+def fun_l18_n431()
+ fun_l19_n560
+end
+
+def fun_l18_n432()
+ fun_l19_n978
+end
+
+def fun_l18_n433()
+ fun_l19_n776
+end
+
+def fun_l18_n434()
+ fun_l19_n954
+end
+
+def fun_l18_n435()
+ fun_l19_n552
+end
+
+def fun_l18_n436()
+ fun_l19_n238
+end
+
+def fun_l18_n437()
+ fun_l19_n496
+end
+
+def fun_l18_n438()
+ fun_l19_n444
+end
+
+def fun_l18_n439()
+ fun_l19_n632
+end
+
+def fun_l18_n440()
+ fun_l19_n243
+end
+
+def fun_l18_n441()
+ fun_l19_n41
+end
+
+def fun_l18_n442()
+ fun_l19_n267
+end
+
+def fun_l18_n443()
+ fun_l19_n449
+end
+
+def fun_l18_n444()
+ fun_l19_n718
+end
+
+def fun_l18_n445()
+ fun_l19_n458
+end
+
+def fun_l18_n446()
+ fun_l19_n23
+end
+
+def fun_l18_n447()
+ fun_l19_n642
+end
+
+def fun_l18_n448()
+ fun_l19_n46
+end
+
+def fun_l18_n449()
+ fun_l19_n812
+end
+
+def fun_l18_n450()
+ fun_l19_n659
+end
+
+def fun_l18_n451()
+ fun_l19_n499
+end
+
+def fun_l18_n452()
+ fun_l19_n691
+end
+
+def fun_l18_n453()
+ fun_l19_n453
+end
+
+def fun_l18_n454()
+ fun_l19_n348
+end
+
+def fun_l18_n455()
+ fun_l19_n115
+end
+
+def fun_l18_n456()
+ fun_l19_n429
+end
+
+def fun_l18_n457()
+ fun_l19_n751
+end
+
+def fun_l18_n458()
+ fun_l19_n669
+end
+
+def fun_l18_n459()
+ fun_l19_n692
+end
+
+def fun_l18_n460()
+ fun_l19_n510
+end
+
+def fun_l18_n461()
+ fun_l19_n276
+end
+
+def fun_l18_n462()
+ fun_l19_n967
+end
+
+def fun_l18_n463()
+ fun_l19_n464
+end
+
+def fun_l18_n464()
+ fun_l19_n742
+end
+
+def fun_l18_n465()
+ fun_l19_n512
+end
+
+def fun_l18_n466()
+ fun_l19_n864
+end
+
+def fun_l18_n467()
+ fun_l19_n956
+end
+
+def fun_l18_n468()
+ fun_l19_n547
+end
+
+def fun_l18_n469()
+ fun_l19_n875
+end
+
+def fun_l18_n470()
+ fun_l19_n840
+end
+
+def fun_l18_n471()
+ fun_l19_n37
+end
+
+def fun_l18_n472()
+ fun_l19_n499
+end
+
+def fun_l18_n473()
+ fun_l19_n112
+end
+
+def fun_l18_n474()
+ fun_l19_n293
+end
+
+def fun_l18_n475()
+ fun_l19_n320
+end
+
+def fun_l18_n476()
+ fun_l19_n502
+end
+
+def fun_l18_n477()
+ fun_l19_n224
+end
+
+def fun_l18_n478()
+ fun_l19_n145
+end
+
+def fun_l18_n479()
+ fun_l19_n71
+end
+
+def fun_l18_n480()
+ fun_l19_n349
+end
+
+def fun_l18_n481()
+ fun_l19_n302
+end
+
+def fun_l18_n482()
+ fun_l19_n205
+end
+
+def fun_l18_n483()
+ fun_l19_n951
+end
+
+def fun_l18_n484()
+ fun_l19_n630
+end
+
+def fun_l18_n485()
+ fun_l19_n288
+end
+
+def fun_l18_n486()
+ fun_l19_n542
+end
+
+def fun_l18_n487()
+ fun_l19_n146
+end
+
+def fun_l18_n488()
+ fun_l19_n530
+end
+
+def fun_l18_n489()
+ fun_l19_n762
+end
+
+def fun_l18_n490()
+ fun_l19_n207
+end
+
+def fun_l18_n491()
+ fun_l19_n915
+end
+
+def fun_l18_n492()
+ fun_l19_n424
+end
+
+def fun_l18_n493()
+ fun_l19_n959
+end
+
+def fun_l18_n494()
+ fun_l19_n4
+end
+
+def fun_l18_n495()
+ fun_l19_n349
+end
+
+def fun_l18_n496()
+ fun_l19_n533
+end
+
+def fun_l18_n497()
+ fun_l19_n727
+end
+
+def fun_l18_n498()
+ fun_l19_n42
+end
+
+def fun_l18_n499()
+ fun_l19_n321
+end
+
+def fun_l18_n500()
+ fun_l19_n440
+end
+
+def fun_l18_n501()
+ fun_l19_n401
+end
+
+def fun_l18_n502()
+ fun_l19_n857
+end
+
+def fun_l18_n503()
+ fun_l19_n750
+end
+
+def fun_l18_n504()
+ fun_l19_n494
+end
+
+def fun_l18_n505()
+ fun_l19_n848
+end
+
+def fun_l18_n506()
+ fun_l19_n676
+end
+
+def fun_l18_n507()
+ fun_l19_n390
+end
+
+def fun_l18_n508()
+ fun_l19_n135
+end
+
+def fun_l18_n509()
+ fun_l19_n241
+end
+
+def fun_l18_n510()
+ fun_l19_n290
+end
+
+def fun_l18_n511()
+ fun_l19_n912
+end
+
+def fun_l18_n512()
+ fun_l19_n410
+end
+
+def fun_l18_n513()
+ fun_l19_n911
+end
+
+def fun_l18_n514()
+ fun_l19_n173
+end
+
+def fun_l18_n515()
+ fun_l19_n383
+end
+
+def fun_l18_n516()
+ fun_l19_n540
+end
+
+def fun_l18_n517()
+ fun_l19_n434
+end
+
+def fun_l18_n518()
+ fun_l19_n997
+end
+
+def fun_l18_n519()
+ fun_l19_n355
+end
+
+def fun_l18_n520()
+ fun_l19_n825
+end
+
+def fun_l18_n521()
+ fun_l19_n711
+end
+
+def fun_l18_n522()
+ fun_l19_n937
+end
+
+def fun_l18_n523()
+ fun_l19_n191
+end
+
+def fun_l18_n524()
+ fun_l19_n284
+end
+
+def fun_l18_n525()
+ fun_l19_n483
+end
+
+def fun_l18_n526()
+ fun_l19_n163
+end
+
+def fun_l18_n527()
+ fun_l19_n514
+end
+
+def fun_l18_n528()
+ fun_l19_n111
+end
+
+def fun_l18_n529()
+ fun_l19_n339
+end
+
+def fun_l18_n530()
+ fun_l19_n322
+end
+
+def fun_l18_n531()
+ fun_l19_n208
+end
+
+def fun_l18_n532()
+ fun_l19_n34
+end
+
+def fun_l18_n533()
+ fun_l19_n106
+end
+
+def fun_l18_n534()
+ fun_l19_n532
+end
+
+def fun_l18_n535()
+ fun_l19_n277
+end
+
+def fun_l18_n536()
+ fun_l19_n936
+end
+
+def fun_l18_n537()
+ fun_l19_n955
+end
+
+def fun_l18_n538()
+ fun_l19_n75
+end
+
+def fun_l18_n539()
+ fun_l19_n349
+end
+
+def fun_l18_n540()
+ fun_l19_n430
+end
+
+def fun_l18_n541()
+ fun_l19_n598
+end
+
+def fun_l18_n542()
+ fun_l19_n336
+end
+
+def fun_l18_n543()
+ fun_l19_n763
+end
+
+def fun_l18_n544()
+ fun_l19_n150
+end
+
+def fun_l18_n545()
+ fun_l19_n301
+end
+
+def fun_l18_n546()
+ fun_l19_n600
+end
+
+def fun_l18_n547()
+ fun_l19_n576
+end
+
+def fun_l18_n548()
+ fun_l19_n119
+end
+
+def fun_l18_n549()
+ fun_l19_n681
+end
+
+def fun_l18_n550()
+ fun_l19_n303
+end
+
+def fun_l18_n551()
+ fun_l19_n498
+end
+
+def fun_l18_n552()
+ fun_l19_n75
+end
+
+def fun_l18_n553()
+ fun_l19_n690
+end
+
+def fun_l18_n554()
+ fun_l19_n496
+end
+
+def fun_l18_n555()
+ fun_l19_n542
+end
+
+def fun_l18_n556()
+ fun_l19_n684
+end
+
+def fun_l18_n557()
+ fun_l19_n315
+end
+
+def fun_l18_n558()
+ fun_l19_n470
+end
+
+def fun_l18_n559()
+ fun_l19_n357
+end
+
+def fun_l18_n560()
+ fun_l19_n805
+end
+
+def fun_l18_n561()
+ fun_l19_n306
+end
+
+def fun_l18_n562()
+ fun_l19_n460
+end
+
+def fun_l18_n563()
+ fun_l19_n173
+end
+
+def fun_l18_n564()
+ fun_l19_n327
+end
+
+def fun_l18_n565()
+ fun_l19_n871
+end
+
+def fun_l18_n566()
+ fun_l19_n792
+end
+
+def fun_l18_n567()
+ fun_l19_n251
+end
+
+def fun_l18_n568()
+ fun_l19_n113
+end
+
+def fun_l18_n569()
+ fun_l19_n877
+end
+
+def fun_l18_n570()
+ fun_l19_n921
+end
+
+def fun_l18_n571()
+ fun_l19_n610
+end
+
+def fun_l18_n572()
+ fun_l19_n895
+end
+
+def fun_l18_n573()
+ fun_l19_n215
+end
+
+def fun_l18_n574()
+ fun_l19_n751
+end
+
+def fun_l18_n575()
+ fun_l19_n2
+end
+
+def fun_l18_n576()
+ fun_l19_n32
+end
+
+def fun_l18_n577()
+ fun_l19_n447
+end
+
+def fun_l18_n578()
+ fun_l19_n652
+end
+
+def fun_l18_n579()
+ fun_l19_n74
+end
+
+def fun_l18_n580()
+ fun_l19_n487
+end
+
+def fun_l18_n581()
+ fun_l19_n522
+end
+
+def fun_l18_n582()
+ fun_l19_n422
+end
+
+def fun_l18_n583()
+ fun_l19_n951
+end
+
+def fun_l18_n584()
+ fun_l19_n216
+end
+
+def fun_l18_n585()
+ fun_l19_n897
+end
+
+def fun_l18_n586()
+ fun_l19_n469
+end
+
+def fun_l18_n587()
+ fun_l19_n315
+end
+
+def fun_l18_n588()
+ fun_l19_n937
+end
+
+def fun_l18_n589()
+ fun_l19_n685
+end
+
+def fun_l18_n590()
+ fun_l19_n322
+end
+
+def fun_l18_n591()
+ fun_l19_n234
+end
+
+def fun_l18_n592()
+ fun_l19_n693
+end
+
+def fun_l18_n593()
+ fun_l19_n941
+end
+
+def fun_l18_n594()
+ fun_l19_n626
+end
+
+def fun_l18_n595()
+ fun_l19_n729
+end
+
+def fun_l18_n596()
+ fun_l19_n65
+end
+
+def fun_l18_n597()
+ fun_l19_n359
+end
+
+def fun_l18_n598()
+ fun_l19_n826
+end
+
+def fun_l18_n599()
+ fun_l19_n631
+end
+
+def fun_l18_n600()
+ fun_l19_n156
+end
+
+def fun_l18_n601()
+ fun_l19_n132
+end
+
+def fun_l18_n602()
+ fun_l19_n23
+end
+
+def fun_l18_n603()
+ fun_l19_n867
+end
+
+def fun_l18_n604()
+ fun_l19_n327
+end
+
+def fun_l18_n605()
+ fun_l19_n9
+end
+
+def fun_l18_n606()
+ fun_l19_n99
+end
+
+def fun_l18_n607()
+ fun_l19_n597
+end
+
+def fun_l18_n608()
+ fun_l19_n969
+end
+
+def fun_l18_n609()
+ fun_l19_n106
+end
+
+def fun_l18_n610()
+ fun_l19_n183
+end
+
+def fun_l18_n611()
+ fun_l19_n956
+end
+
+def fun_l18_n612()
+ fun_l19_n661
+end
+
+def fun_l18_n613()
+ fun_l19_n562
+end
+
+def fun_l18_n614()
+ fun_l19_n49
+end
+
+def fun_l18_n615()
+ fun_l19_n769
+end
+
+def fun_l18_n616()
+ fun_l19_n215
+end
+
+def fun_l18_n617()
+ fun_l19_n89
+end
+
+def fun_l18_n618()
+ fun_l19_n928
+end
+
+def fun_l18_n619()
+ fun_l19_n213
+end
+
+def fun_l18_n620()
+ fun_l19_n215
+end
+
+def fun_l18_n621()
+ fun_l19_n472
+end
+
+def fun_l18_n622()
+ fun_l19_n363
+end
+
+def fun_l18_n623()
+ fun_l19_n251
+end
+
+def fun_l18_n624()
+ fun_l19_n780
+end
+
+def fun_l18_n625()
+ fun_l19_n414
+end
+
+def fun_l18_n626()
+ fun_l19_n348
+end
+
+def fun_l18_n627()
+ fun_l19_n268
+end
+
+def fun_l18_n628()
+ fun_l19_n772
+end
+
+def fun_l18_n629()
+ fun_l19_n232
+end
+
+def fun_l18_n630()
+ fun_l19_n775
+end
+
+def fun_l18_n631()
+ fun_l19_n181
+end
+
+def fun_l18_n632()
+ fun_l19_n953
+end
+
+def fun_l18_n633()
+ fun_l19_n927
+end
+
+def fun_l18_n634()
+ fun_l19_n241
+end
+
+def fun_l18_n635()
+ fun_l19_n426
+end
+
+def fun_l18_n636()
+ fun_l19_n337
+end
+
+def fun_l18_n637()
+ fun_l19_n948
+end
+
+def fun_l18_n638()
+ fun_l19_n703
+end
+
+def fun_l18_n639()
+ fun_l19_n938
+end
+
+def fun_l18_n640()
+ fun_l19_n432
+end
+
+def fun_l18_n641()
+ fun_l19_n117
+end
+
+def fun_l18_n642()
+ fun_l19_n362
+end
+
+def fun_l18_n643()
+ fun_l19_n956
+end
+
+def fun_l18_n644()
+ fun_l19_n947
+end
+
+def fun_l18_n645()
+ fun_l19_n954
+end
+
+def fun_l18_n646()
+ fun_l19_n159
+end
+
+def fun_l18_n647()
+ fun_l19_n838
+end
+
+def fun_l18_n648()
+ fun_l19_n614
+end
+
+def fun_l18_n649()
+ fun_l19_n589
+end
+
+def fun_l18_n650()
+ fun_l19_n16
+end
+
+def fun_l18_n651()
+ fun_l19_n721
+end
+
+def fun_l18_n652()
+ fun_l19_n608
+end
+
+def fun_l18_n653()
+ fun_l19_n462
+end
+
+def fun_l18_n654()
+ fun_l19_n66
+end
+
+def fun_l18_n655()
+ fun_l19_n219
+end
+
+def fun_l18_n656()
+ fun_l19_n660
+end
+
+def fun_l18_n657()
+ fun_l19_n466
+end
+
+def fun_l18_n658()
+ fun_l19_n441
+end
+
+def fun_l18_n659()
+ fun_l19_n140
+end
+
+def fun_l18_n660()
+ fun_l19_n538
+end
+
+def fun_l18_n661()
+ fun_l19_n602
+end
+
+def fun_l18_n662()
+ fun_l19_n94
+end
+
+def fun_l18_n663()
+ fun_l19_n435
+end
+
+def fun_l18_n664()
+ fun_l19_n632
+end
+
+def fun_l18_n665()
+ fun_l19_n404
+end
+
+def fun_l18_n666()
+ fun_l19_n894
+end
+
+def fun_l18_n667()
+ fun_l19_n668
+end
+
+def fun_l18_n668()
+ fun_l19_n802
+end
+
+def fun_l18_n669()
+ fun_l19_n785
+end
+
+def fun_l18_n670()
+ fun_l19_n16
+end
+
+def fun_l18_n671()
+ fun_l19_n124
+end
+
+def fun_l18_n672()
+ fun_l19_n587
+end
+
+def fun_l18_n673()
+ fun_l19_n605
+end
+
+def fun_l18_n674()
+ fun_l19_n903
+end
+
+def fun_l18_n675()
+ fun_l19_n980
+end
+
+def fun_l18_n676()
+ fun_l19_n463
+end
+
+def fun_l18_n677()
+ fun_l19_n716
+end
+
+def fun_l18_n678()
+ fun_l19_n815
+end
+
+def fun_l18_n679()
+ fun_l19_n909
+end
+
+def fun_l18_n680()
+ fun_l19_n924
+end
+
+def fun_l18_n681()
+ fun_l19_n383
+end
+
+def fun_l18_n682()
+ fun_l19_n761
+end
+
+def fun_l18_n683()
+ fun_l19_n663
+end
+
+def fun_l18_n684()
+ fun_l19_n176
+end
+
+def fun_l18_n685()
+ fun_l19_n87
+end
+
+def fun_l18_n686()
+ fun_l19_n1
+end
+
+def fun_l18_n687()
+ fun_l19_n953
+end
+
+def fun_l18_n688()
+ fun_l19_n737
+end
+
+def fun_l18_n689()
+ fun_l19_n792
+end
+
+def fun_l18_n690()
+ fun_l19_n165
+end
+
+def fun_l18_n691()
+ fun_l19_n266
+end
+
+def fun_l18_n692()
+ fun_l19_n357
+end
+
+def fun_l18_n693()
+ fun_l19_n780
+end
+
+def fun_l18_n694()
+ fun_l19_n893
+end
+
+def fun_l18_n695()
+ fun_l19_n280
+end
+
+def fun_l18_n696()
+ fun_l19_n117
+end
+
+def fun_l18_n697()
+ fun_l19_n985
+end
+
+def fun_l18_n698()
+ fun_l19_n306
+end
+
+def fun_l18_n699()
+ fun_l19_n421
+end
+
+def fun_l18_n700()
+ fun_l19_n62
+end
+
+def fun_l18_n701()
+ fun_l19_n384
+end
+
+def fun_l18_n702()
+ fun_l19_n394
+end
+
+def fun_l18_n703()
+ fun_l19_n707
+end
+
+def fun_l18_n704()
+ fun_l19_n599
+end
+
+def fun_l18_n705()
+ fun_l19_n590
+end
+
+def fun_l18_n706()
+ fun_l19_n49
+end
+
+def fun_l18_n707()
+ fun_l19_n529
+end
+
+def fun_l18_n708()
+ fun_l19_n824
+end
+
+def fun_l18_n709()
+ fun_l19_n481
+end
+
+def fun_l18_n710()
+ fun_l19_n221
+end
+
+def fun_l18_n711()
+ fun_l19_n305
+end
+
+def fun_l18_n712()
+ fun_l19_n612
+end
+
+def fun_l18_n713()
+ fun_l19_n809
+end
+
+def fun_l18_n714()
+ fun_l19_n41
+end
+
+def fun_l18_n715()
+ fun_l19_n477
+end
+
+def fun_l18_n716()
+ fun_l19_n717
+end
+
+def fun_l18_n717()
+ fun_l19_n447
+end
+
+def fun_l18_n718()
+ fun_l19_n501
+end
+
+def fun_l18_n719()
+ fun_l19_n86
+end
+
+def fun_l18_n720()
+ fun_l19_n250
+end
+
+def fun_l18_n721()
+ fun_l19_n504
+end
+
+def fun_l18_n722()
+ fun_l19_n274
+end
+
+def fun_l18_n723()
+ fun_l19_n167
+end
+
+def fun_l18_n724()
+ fun_l19_n824
+end
+
+def fun_l18_n725()
+ fun_l19_n188
+end
+
+def fun_l18_n726()
+ fun_l19_n953
+end
+
+def fun_l18_n727()
+ fun_l19_n61
+end
+
+def fun_l18_n728()
+ fun_l19_n242
+end
+
+def fun_l18_n729()
+ fun_l19_n167
+end
+
+def fun_l18_n730()
+ fun_l19_n936
+end
+
+def fun_l18_n731()
+ fun_l19_n293
+end
+
+def fun_l18_n732()
+ fun_l19_n951
+end
+
+def fun_l18_n733()
+ fun_l19_n235
+end
+
+def fun_l18_n734()
+ fun_l19_n718
+end
+
+def fun_l18_n735()
+ fun_l19_n930
+end
+
+def fun_l18_n736()
+ fun_l19_n842
+end
+
+def fun_l18_n737()
+ fun_l19_n697
+end
+
+def fun_l18_n738()
+ fun_l19_n503
+end
+
+def fun_l18_n739()
+ fun_l19_n789
+end
+
+def fun_l18_n740()
+ fun_l19_n87
+end
+
+def fun_l18_n741()
+ fun_l19_n919
+end
+
+def fun_l18_n742()
+ fun_l19_n26
+end
+
+def fun_l18_n743()
+ fun_l19_n873
+end
+
+def fun_l18_n744()
+ fun_l19_n334
+end
+
+def fun_l18_n745()
+ fun_l19_n112
+end
+
+def fun_l18_n746()
+ fun_l19_n648
+end
+
+def fun_l18_n747()
+ fun_l19_n261
+end
+
+def fun_l18_n748()
+ fun_l19_n617
+end
+
+def fun_l18_n749()
+ fun_l19_n922
+end
+
+def fun_l18_n750()
+ fun_l19_n434
+end
+
+def fun_l18_n751()
+ fun_l19_n842
+end
+
+def fun_l18_n752()
+ fun_l19_n498
+end
+
+def fun_l18_n753()
+ fun_l19_n367
+end
+
+def fun_l18_n754()
+ fun_l19_n799
+end
+
+def fun_l18_n755()
+ fun_l19_n780
+end
+
+def fun_l18_n756()
+ fun_l19_n119
+end
+
+def fun_l18_n757()
+ fun_l19_n871
+end
+
+def fun_l18_n758()
+ fun_l19_n293
+end
+
+def fun_l18_n759()
+ fun_l19_n645
+end
+
+def fun_l18_n760()
+ fun_l19_n226
+end
+
+def fun_l18_n761()
+ fun_l19_n518
+end
+
+def fun_l18_n762()
+ fun_l19_n223
+end
+
+def fun_l18_n763()
+ fun_l19_n859
+end
+
+def fun_l18_n764()
+ fun_l19_n545
+end
+
+def fun_l18_n765()
+ fun_l19_n452
+end
+
+def fun_l18_n766()
+ fun_l19_n538
+end
+
+def fun_l18_n767()
+ fun_l19_n574
+end
+
+def fun_l18_n768()
+ fun_l19_n605
+end
+
+def fun_l18_n769()
+ fun_l19_n794
+end
+
+def fun_l18_n770()
+ fun_l19_n35
+end
+
+def fun_l18_n771()
+ fun_l19_n990
+end
+
+def fun_l18_n772()
+ fun_l19_n276
+end
+
+def fun_l18_n773()
+ fun_l19_n806
+end
+
+def fun_l18_n774()
+ fun_l19_n321
+end
+
+def fun_l18_n775()
+ fun_l19_n874
+end
+
+def fun_l18_n776()
+ fun_l19_n349
+end
+
+def fun_l18_n777()
+ fun_l19_n595
+end
+
+def fun_l18_n778()
+ fun_l19_n944
+end
+
+def fun_l18_n779()
+ fun_l19_n617
+end
+
+def fun_l18_n780()
+ fun_l19_n982
+end
+
+def fun_l18_n781()
+ fun_l19_n395
+end
+
+def fun_l18_n782()
+ fun_l19_n362
+end
+
+def fun_l18_n783()
+ fun_l19_n533
+end
+
+def fun_l18_n784()
+ fun_l19_n646
+end
+
+def fun_l18_n785()
+ fun_l19_n160
+end
+
+def fun_l18_n786()
+ fun_l19_n288
+end
+
+def fun_l18_n787()
+ fun_l19_n381
+end
+
+def fun_l18_n788()
+ fun_l19_n299
+end
+
+def fun_l18_n789()
+ fun_l19_n546
+end
+
+def fun_l18_n790()
+ fun_l19_n906
+end
+
+def fun_l18_n791()
+ fun_l19_n788
+end
+
+def fun_l18_n792()
+ fun_l19_n389
+end
+
+def fun_l18_n793()
+ fun_l19_n593
+end
+
+def fun_l18_n794()
+ fun_l19_n224
+end
+
+def fun_l18_n795()
+ fun_l19_n815
+end
+
+def fun_l18_n796()
+ fun_l19_n533
+end
+
+def fun_l18_n797()
+ fun_l19_n47
+end
+
+def fun_l18_n798()
+ fun_l19_n457
+end
+
+def fun_l18_n799()
+ fun_l19_n951
+end
+
+def fun_l18_n800()
+ fun_l19_n680
+end
+
+def fun_l18_n801()
+ fun_l19_n362
+end
+
+def fun_l18_n802()
+ fun_l19_n667
+end
+
+def fun_l18_n803()
+ fun_l19_n906
+end
+
+def fun_l18_n804()
+ fun_l19_n444
+end
+
+def fun_l18_n805()
+ fun_l19_n562
+end
+
+def fun_l18_n806()
+ fun_l19_n472
+end
+
+def fun_l18_n807()
+ fun_l19_n706
+end
+
+def fun_l18_n808()
+ fun_l19_n611
+end
+
+def fun_l18_n809()
+ fun_l19_n514
+end
+
+def fun_l18_n810()
+ fun_l19_n742
+end
+
+def fun_l18_n811()
+ fun_l19_n144
+end
+
+def fun_l18_n812()
+ fun_l19_n938
+end
+
+def fun_l18_n813()
+ fun_l19_n835
+end
+
+def fun_l18_n814()
+ fun_l19_n127
+end
+
+def fun_l18_n815()
+ fun_l19_n188
+end
+
+def fun_l18_n816()
+ fun_l19_n511
+end
+
+def fun_l18_n817()
+ fun_l19_n919
+end
+
+def fun_l18_n818()
+ fun_l19_n46
+end
+
+def fun_l18_n819()
+ fun_l19_n927
+end
+
+def fun_l18_n820()
+ fun_l19_n655
+end
+
+def fun_l18_n821()
+ fun_l19_n713
+end
+
+def fun_l18_n822()
+ fun_l19_n803
+end
+
+def fun_l18_n823()
+ fun_l19_n116
+end
+
+def fun_l18_n824()
+ fun_l19_n139
+end
+
+def fun_l18_n825()
+ fun_l19_n263
+end
+
+def fun_l18_n826()
+ fun_l19_n728
+end
+
+def fun_l18_n827()
+ fun_l19_n77
+end
+
+def fun_l18_n828()
+ fun_l19_n958
+end
+
+def fun_l18_n829()
+ fun_l19_n827
+end
+
+def fun_l18_n830()
+ fun_l19_n738
+end
+
+def fun_l18_n831()
+ fun_l19_n430
+end
+
+def fun_l18_n832()
+ fun_l19_n16
+end
+
+def fun_l18_n833()
+ fun_l19_n335
+end
+
+def fun_l18_n834()
+ fun_l19_n674
+end
+
+def fun_l18_n835()
+ fun_l19_n938
+end
+
+def fun_l18_n836()
+ fun_l19_n460
+end
+
+def fun_l18_n837()
+ fun_l19_n268
+end
+
+def fun_l18_n838()
+ fun_l19_n250
+end
+
+def fun_l18_n839()
+ fun_l19_n460
+end
+
+def fun_l18_n840()
+ fun_l19_n966
+end
+
+def fun_l18_n841()
+ fun_l19_n228
+end
+
+def fun_l18_n842()
+ fun_l19_n90
+end
+
+def fun_l18_n843()
+ fun_l19_n227
+end
+
+def fun_l18_n844()
+ fun_l19_n494
+end
+
+def fun_l18_n845()
+ fun_l19_n85
+end
+
+def fun_l18_n846()
+ fun_l19_n497
+end
+
+def fun_l18_n847()
+ fun_l19_n395
+end
+
+def fun_l18_n848()
+ fun_l19_n874
+end
+
+def fun_l18_n849()
+ fun_l19_n826
+end
+
+def fun_l18_n850()
+ fun_l19_n467
+end
+
+def fun_l18_n851()
+ fun_l19_n330
+end
+
+def fun_l18_n852()
+ fun_l19_n229
+end
+
+def fun_l18_n853()
+ fun_l19_n172
+end
+
+def fun_l18_n854()
+ fun_l19_n604
+end
+
+def fun_l18_n855()
+ fun_l19_n314
+end
+
+def fun_l18_n856()
+ fun_l19_n553
+end
+
+def fun_l18_n857()
+ fun_l19_n946
+end
+
+def fun_l18_n858()
+ fun_l19_n347
+end
+
+def fun_l18_n859()
+ fun_l19_n566
+end
+
+def fun_l18_n860()
+ fun_l19_n144
+end
+
+def fun_l18_n861()
+ fun_l19_n812
+end
+
+def fun_l18_n862()
+ fun_l19_n615
+end
+
+def fun_l18_n863()
+ fun_l19_n411
+end
+
+def fun_l18_n864()
+ fun_l19_n67
+end
+
+def fun_l18_n865()
+ fun_l19_n830
+end
+
+def fun_l18_n866()
+ fun_l19_n849
+end
+
+def fun_l18_n867()
+ fun_l19_n933
+end
+
+def fun_l18_n868()
+ fun_l19_n892
+end
+
+def fun_l18_n869()
+ fun_l19_n644
+end
+
+def fun_l18_n870()
+ fun_l19_n567
+end
+
+def fun_l18_n871()
+ fun_l19_n558
+end
+
+def fun_l18_n872()
+ fun_l19_n766
+end
+
+def fun_l18_n873()
+ fun_l19_n715
+end
+
+def fun_l18_n874()
+ fun_l19_n641
+end
+
+def fun_l18_n875()
+ fun_l19_n81
+end
+
+def fun_l18_n876()
+ fun_l19_n472
+end
+
+def fun_l18_n877()
+ fun_l19_n907
+end
+
+def fun_l18_n878()
+ fun_l19_n426
+end
+
+def fun_l18_n879()
+ fun_l19_n329
+end
+
+def fun_l18_n880()
+ fun_l19_n935
+end
+
+def fun_l18_n881()
+ fun_l19_n100
+end
+
+def fun_l18_n882()
+ fun_l19_n540
+end
+
+def fun_l18_n883()
+ fun_l19_n905
+end
+
+def fun_l18_n884()
+ fun_l19_n991
+end
+
+def fun_l18_n885()
+ fun_l19_n700
+end
+
+def fun_l18_n886()
+ fun_l19_n698
+end
+
+def fun_l18_n887()
+ fun_l19_n805
+end
+
+def fun_l18_n888()
+ fun_l19_n736
+end
+
+def fun_l18_n889()
+ fun_l19_n386
+end
+
+def fun_l18_n890()
+ fun_l19_n895
+end
+
+def fun_l18_n891()
+ fun_l19_n542
+end
+
+def fun_l18_n892()
+ fun_l19_n261
+end
+
+def fun_l18_n893()
+ fun_l19_n600
+end
+
+def fun_l18_n894()
+ fun_l19_n153
+end
+
+def fun_l18_n895()
+ fun_l19_n767
+end
+
+def fun_l18_n896()
+ fun_l19_n201
+end
+
+def fun_l18_n897()
+ fun_l19_n98
+end
+
+def fun_l18_n898()
+ fun_l19_n423
+end
+
+def fun_l18_n899()
+ fun_l19_n247
+end
+
+def fun_l18_n900()
+ fun_l19_n720
+end
+
+def fun_l18_n901()
+ fun_l19_n1
+end
+
+def fun_l18_n902()
+ fun_l19_n21
+end
+
+def fun_l18_n903()
+ fun_l19_n591
+end
+
+def fun_l18_n904()
+ fun_l19_n36
+end
+
+def fun_l18_n905()
+ fun_l19_n654
+end
+
+def fun_l18_n906()
+ fun_l19_n378
+end
+
+def fun_l18_n907()
+ fun_l19_n841
+end
+
+def fun_l18_n908()
+ fun_l19_n685
+end
+
+def fun_l18_n909()
+ fun_l19_n933
+end
+
+def fun_l18_n910()
+ fun_l19_n71
+end
+
+def fun_l18_n911()
+ fun_l19_n963
+end
+
+def fun_l18_n912()
+ fun_l19_n590
+end
+
+def fun_l18_n913()
+ fun_l19_n24
+end
+
+def fun_l18_n914()
+ fun_l19_n213
+end
+
+def fun_l18_n915()
+ fun_l19_n862
+end
+
+def fun_l18_n916()
+ fun_l19_n2
+end
+
+def fun_l18_n917()
+ fun_l19_n728
+end
+
+def fun_l18_n918()
+ fun_l19_n23
+end
+
+def fun_l18_n919()
+ fun_l19_n345
+end
+
+def fun_l18_n920()
+ fun_l19_n515
+end
+
+def fun_l18_n921()
+ fun_l19_n803
+end
+
+def fun_l18_n922()
+ fun_l19_n378
+end
+
+def fun_l18_n923()
+ fun_l19_n260
+end
+
+def fun_l18_n924()
+ fun_l19_n824
+end
+
+def fun_l18_n925()
+ fun_l19_n698
+end
+
+def fun_l18_n926()
+ fun_l19_n719
+end
+
+def fun_l18_n927()
+ fun_l19_n126
+end
+
+def fun_l18_n928()
+ fun_l19_n647
+end
+
+def fun_l18_n929()
+ fun_l19_n412
+end
+
+def fun_l18_n930()
+ fun_l19_n617
+end
+
+def fun_l18_n931()
+ fun_l19_n295
+end
+
+def fun_l18_n932()
+ fun_l19_n231
+end
+
+def fun_l18_n933()
+ fun_l19_n301
+end
+
+def fun_l18_n934()
+ fun_l19_n25
+end
+
+def fun_l18_n935()
+ fun_l19_n341
+end
+
+def fun_l18_n936()
+ fun_l19_n845
+end
+
+def fun_l18_n937()
+ fun_l19_n97
+end
+
+def fun_l18_n938()
+ fun_l19_n787
+end
+
+def fun_l18_n939()
+ fun_l19_n828
+end
+
+def fun_l18_n940()
+ fun_l19_n298
+end
+
+def fun_l18_n941()
+ fun_l19_n234
+end
+
+def fun_l18_n942()
+ fun_l19_n74
+end
+
+def fun_l18_n943()
+ fun_l19_n928
+end
+
+def fun_l18_n944()
+ fun_l19_n276
+end
+
+def fun_l18_n945()
+ fun_l19_n699
+end
+
+def fun_l18_n946()
+ fun_l19_n507
+end
+
+def fun_l18_n947()
+ fun_l19_n385
+end
+
+def fun_l18_n948()
+ fun_l19_n651
+end
+
+def fun_l18_n949()
+ fun_l19_n315
+end
+
+def fun_l18_n950()
+ fun_l19_n289
+end
+
+def fun_l18_n951()
+ fun_l19_n879
+end
+
+def fun_l18_n952()
+ fun_l19_n549
+end
+
+def fun_l18_n953()
+ fun_l19_n205
+end
+
+def fun_l18_n954()
+ fun_l19_n468
+end
+
+def fun_l18_n955()
+ fun_l19_n11
+end
+
+def fun_l18_n956()
+ fun_l19_n644
+end
+
+def fun_l18_n957()
+ fun_l19_n492
+end
+
+def fun_l18_n958()
+ fun_l19_n94
+end
+
+def fun_l18_n959()
+ fun_l19_n331
+end
+
+def fun_l18_n960()
+ fun_l19_n708
+end
+
+def fun_l18_n961()
+ fun_l19_n646
+end
+
+def fun_l18_n962()
+ fun_l19_n206
+end
+
+def fun_l18_n963()
+ fun_l19_n793
+end
+
+def fun_l18_n964()
+ fun_l19_n426
+end
+
+def fun_l18_n965()
+ fun_l19_n181
+end
+
+def fun_l18_n966()
+ fun_l19_n773
+end
+
+def fun_l18_n967()
+ fun_l19_n324
+end
+
+def fun_l18_n968()
+ fun_l19_n451
+end
+
+def fun_l18_n969()
+ fun_l19_n155
+end
+
+def fun_l18_n970()
+ fun_l19_n812
+end
+
+def fun_l18_n971()
+ fun_l19_n906
+end
+
+def fun_l18_n972()
+ fun_l19_n367
+end
+
+def fun_l18_n973()
+ fun_l19_n260
+end
+
+def fun_l18_n974()
+ fun_l19_n226
+end
+
+def fun_l18_n975()
+ fun_l19_n189
+end
+
+def fun_l18_n976()
+ fun_l19_n32
+end
+
+def fun_l18_n977()
+ fun_l19_n43
+end
+
+def fun_l18_n978()
+ fun_l19_n285
+end
+
+def fun_l18_n979()
+ fun_l19_n511
+end
+
+def fun_l18_n980()
+ fun_l19_n714
+end
+
+def fun_l18_n981()
+ fun_l19_n587
+end
+
+def fun_l18_n982()
+ fun_l19_n247
+end
+
+def fun_l18_n983()
+ fun_l19_n258
+end
+
+def fun_l18_n984()
+ fun_l19_n115
+end
+
+def fun_l18_n985()
+ fun_l19_n873
+end
+
+def fun_l18_n986()
+ fun_l19_n452
+end
+
+def fun_l18_n987()
+ fun_l19_n994
+end
+
+def fun_l18_n988()
+ fun_l19_n912
+end
+
+def fun_l18_n989()
+ fun_l19_n534
+end
+
+def fun_l18_n990()
+ fun_l19_n186
+end
+
+def fun_l18_n991()
+ fun_l19_n49
+end
+
+def fun_l18_n992()
+ fun_l19_n676
+end
+
+def fun_l18_n993()
+ fun_l19_n466
+end
+
+def fun_l18_n994()
+ fun_l19_n571
+end
+
+def fun_l18_n995()
+ fun_l19_n573
+end
+
+def fun_l18_n996()
+ fun_l19_n47
+end
+
+def fun_l18_n997()
+ fun_l19_n657
+end
+
+def fun_l18_n998()
+ fun_l19_n11
+end
+
+def fun_l18_n999()
+ fun_l19_n342
+end
+
+def fun_l19_n0()
+ fun_l20_n278
+end
+
+def fun_l19_n1()
+ fun_l20_n159
+end
+
+def fun_l19_n2()
+ fun_l20_n289
+end
+
+def fun_l19_n3()
+ fun_l20_n766
+end
+
+def fun_l19_n4()
+ fun_l20_n45
+end
+
+def fun_l19_n5()
+ fun_l20_n453
+end
+
+def fun_l19_n6()
+ fun_l20_n581
+end
+
+def fun_l19_n7()
+ fun_l20_n607
+end
+
+def fun_l19_n8()
+ fun_l20_n427
+end
+
+def fun_l19_n9()
+ fun_l20_n287
+end
+
+def fun_l19_n10()
+ fun_l20_n28
+end
+
+def fun_l19_n11()
+ fun_l20_n456
+end
+
+def fun_l19_n12()
+ fun_l20_n283
+end
+
+def fun_l19_n13()
+ fun_l20_n451
+end
+
+def fun_l19_n14()
+ fun_l20_n220
+end
+
+def fun_l19_n15()
+ fun_l20_n497
+end
+
+def fun_l19_n16()
+ fun_l20_n295
+end
+
+def fun_l19_n17()
+ fun_l20_n66
+end
+
+def fun_l19_n18()
+ fun_l20_n863
+end
+
+def fun_l19_n19()
+ fun_l20_n919
+end
+
+def fun_l19_n20()
+ fun_l20_n712
+end
+
+def fun_l19_n21()
+ fun_l20_n323
+end
+
+def fun_l19_n22()
+ fun_l20_n666
+end
+
+def fun_l19_n23()
+ fun_l20_n947
+end
+
+def fun_l19_n24()
+ fun_l20_n422
+end
+
+def fun_l19_n25()
+ fun_l20_n728
+end
+
+def fun_l19_n26()
+ fun_l20_n886
+end
+
+def fun_l19_n27()
+ fun_l20_n585
+end
+
+def fun_l19_n28()
+ fun_l20_n835
+end
+
+def fun_l19_n29()
+ fun_l20_n812
+end
+
+def fun_l19_n30()
+ fun_l20_n425
+end
+
+def fun_l19_n31()
+ fun_l20_n378
+end
+
+def fun_l19_n32()
+ fun_l20_n128
+end
+
+def fun_l19_n33()
+ fun_l20_n714
+end
+
+def fun_l19_n34()
+ fun_l20_n502
+end
+
+def fun_l19_n35()
+ fun_l20_n447
+end
+
+def fun_l19_n36()
+ fun_l20_n512
+end
+
+def fun_l19_n37()
+ fun_l20_n642
+end
+
+def fun_l19_n38()
+ fun_l20_n839
+end
+
+def fun_l19_n39()
+ fun_l20_n539
+end
+
+def fun_l19_n40()
+ fun_l20_n204
+end
+
+def fun_l19_n41()
+ fun_l20_n294
+end
+
+def fun_l19_n42()
+ fun_l20_n360
+end
+
+def fun_l19_n43()
+ fun_l20_n132
+end
+
+def fun_l19_n44()
+ fun_l20_n529
+end
+
+def fun_l19_n45()
+ fun_l20_n783
+end
+
+def fun_l19_n46()
+ fun_l20_n694
+end
+
+def fun_l19_n47()
+ fun_l20_n939
+end
+
+def fun_l19_n48()
+ fun_l20_n972
+end
+
+def fun_l19_n49()
+ fun_l20_n187
+end
+
+def fun_l19_n50()
+ fun_l20_n236
+end
+
+def fun_l19_n51()
+ fun_l20_n218
+end
+
+def fun_l19_n52()
+ fun_l20_n278
+end
+
+def fun_l19_n53()
+ fun_l20_n895
+end
+
+def fun_l19_n54()
+ fun_l20_n967
+end
+
+def fun_l19_n55()
+ fun_l20_n110
+end
+
+def fun_l19_n56()
+ fun_l20_n918
+end
+
+def fun_l19_n57()
+ fun_l20_n458
+end
+
+def fun_l19_n58()
+ fun_l20_n262
+end
+
+def fun_l19_n59()
+ fun_l20_n978
+end
+
+def fun_l19_n60()
+ fun_l20_n434
+end
+
+def fun_l19_n61()
+ fun_l20_n86
+end
+
+def fun_l19_n62()
+ fun_l20_n364
+end
+
+def fun_l19_n63()
+ fun_l20_n92
+end
+
+def fun_l19_n64()
+ fun_l20_n173
+end
+
+def fun_l19_n65()
+ fun_l20_n530
+end
+
+def fun_l19_n66()
+ fun_l20_n291
+end
+
+def fun_l19_n67()
+ fun_l20_n758
+end
+
+def fun_l19_n68()
+ fun_l20_n311
+end
+
+def fun_l19_n69()
+ fun_l20_n984
+end
+
+def fun_l19_n70()
+ fun_l20_n976
+end
+
+def fun_l19_n71()
+ fun_l20_n622
+end
+
+def fun_l19_n72()
+ fun_l20_n467
+end
+
+def fun_l19_n73()
+ fun_l20_n369
+end
+
+def fun_l19_n74()
+ fun_l20_n81
+end
+
+def fun_l19_n75()
+ fun_l20_n6
+end
+
+def fun_l19_n76()
+ fun_l20_n23
+end
+
+def fun_l19_n77()
+ fun_l20_n631
+end
+
+def fun_l19_n78()
+ fun_l20_n535
+end
+
+def fun_l19_n79()
+ fun_l20_n572
+end
+
+def fun_l19_n80()
+ fun_l20_n905
+end
+
+def fun_l19_n81()
+ fun_l20_n709
+end
+
+def fun_l19_n82()
+ fun_l20_n362
+end
+
+def fun_l19_n83()
+ fun_l20_n505
+end
+
+def fun_l19_n84()
+ fun_l20_n247
+end
+
+def fun_l19_n85()
+ fun_l20_n88
+end
+
+def fun_l19_n86()
+ fun_l20_n214
+end
+
+def fun_l19_n87()
+ fun_l20_n607
+end
+
+def fun_l19_n88()
+ fun_l20_n161
+end
+
+def fun_l19_n89()
+ fun_l20_n419
+end
+
+def fun_l19_n90()
+ fun_l20_n514
+end
+
+def fun_l19_n91()
+ fun_l20_n879
+end
+
+def fun_l19_n92()
+ fun_l20_n11
+end
+
+def fun_l19_n93()
+ fun_l20_n269
+end
+
+def fun_l19_n94()
+ fun_l20_n685
+end
+
+def fun_l19_n95()
+ fun_l20_n435
+end
+
+def fun_l19_n96()
+ fun_l20_n183
+end
+
+def fun_l19_n97()
+ fun_l20_n548
+end
+
+def fun_l19_n98()
+ fun_l20_n460
+end
+
+def fun_l19_n99()
+ fun_l20_n636
+end
+
+def fun_l19_n100()
+ fun_l20_n829
+end
+
+def fun_l19_n101()
+ fun_l20_n224
+end
+
+def fun_l19_n102()
+ fun_l20_n291
+end
+
+def fun_l19_n103()
+ fun_l20_n498
+end
+
+def fun_l19_n104()
+ fun_l20_n403
+end
+
+def fun_l19_n105()
+ fun_l20_n699
+end
+
+def fun_l19_n106()
+ fun_l20_n851
+end
+
+def fun_l19_n107()
+ fun_l20_n400
+end
+
+def fun_l19_n108()
+ fun_l20_n834
+end
+
+def fun_l19_n109()
+ fun_l20_n635
+end
+
+def fun_l19_n110()
+ fun_l20_n651
+end
+
+def fun_l19_n111()
+ fun_l20_n930
+end
+
+def fun_l19_n112()
+ fun_l20_n547
+end
+
+def fun_l19_n113()
+ fun_l20_n237
+end
+
+def fun_l19_n114()
+ fun_l20_n298
+end
+
+def fun_l19_n115()
+ fun_l20_n979
+end
+
+def fun_l19_n116()
+ fun_l20_n409
+end
+
+def fun_l19_n117()
+ fun_l20_n942
+end
+
+def fun_l19_n118()
+ fun_l20_n224
+end
+
+def fun_l19_n119()
+ fun_l20_n288
+end
+
+def fun_l19_n120()
+ fun_l20_n42
+end
+
+def fun_l19_n121()
+ fun_l20_n718
+end
+
+def fun_l19_n122()
+ fun_l20_n392
+end
+
+def fun_l19_n123()
+ fun_l20_n375
+end
+
+def fun_l19_n124()
+ fun_l20_n499
+end
+
+def fun_l19_n125()
+ fun_l20_n499
+end
+
+def fun_l19_n126()
+ fun_l20_n998
+end
+
+def fun_l19_n127()
+ fun_l20_n659
+end
+
+def fun_l19_n128()
+ fun_l20_n782
+end
+
+def fun_l19_n129()
+ fun_l20_n607
+end
+
+def fun_l19_n130()
+ fun_l20_n802
+end
+
+def fun_l19_n131()
+ fun_l20_n773
+end
+
+def fun_l19_n132()
+ fun_l20_n861
+end
+
+def fun_l19_n133()
+ fun_l20_n38
+end
+
+def fun_l19_n134()
+ fun_l20_n614
+end
+
+def fun_l19_n135()
+ fun_l20_n546
+end
+
+def fun_l19_n136()
+ fun_l20_n890
+end
+
+def fun_l19_n137()
+ fun_l20_n987
+end
+
+def fun_l19_n138()
+ fun_l20_n518
+end
+
+def fun_l19_n139()
+ fun_l20_n708
+end
+
+def fun_l19_n140()
+ fun_l20_n838
+end
+
+def fun_l19_n141()
+ fun_l20_n642
+end
+
+def fun_l19_n142()
+ fun_l20_n275
+end
+
+def fun_l19_n143()
+ fun_l20_n274
+end
+
+def fun_l19_n144()
+ fun_l20_n479
+end
+
+def fun_l19_n145()
+ fun_l20_n215
+end
+
+def fun_l19_n146()
+ fun_l20_n794
+end
+
+def fun_l19_n147()
+ fun_l20_n329
+end
+
+def fun_l19_n148()
+ fun_l20_n146
+end
+
+def fun_l19_n149()
+ fun_l20_n561
+end
+
+def fun_l19_n150()
+ fun_l20_n782
+end
+
+def fun_l19_n151()
+ fun_l20_n903
+end
+
+def fun_l19_n152()
+ fun_l20_n97
+end
+
+def fun_l19_n153()
+ fun_l20_n962
+end
+
+def fun_l19_n154()
+ fun_l20_n758
+end
+
+def fun_l19_n155()
+ fun_l20_n58
+end
+
+def fun_l19_n156()
+ fun_l20_n683
+end
+
+def fun_l19_n157()
+ fun_l20_n48
+end
+
+def fun_l19_n158()
+ fun_l20_n476
+end
+
+def fun_l19_n159()
+ fun_l20_n19
+end
+
+def fun_l19_n160()
+ fun_l20_n938
+end
+
+def fun_l19_n161()
+ fun_l20_n40
+end
+
+def fun_l19_n162()
+ fun_l20_n817
+end
+
+def fun_l19_n163()
+ fun_l20_n745
+end
+
+def fun_l19_n164()
+ fun_l20_n10
+end
+
+def fun_l19_n165()
+ fun_l20_n486
+end
+
+def fun_l19_n166()
+ fun_l20_n321
+end
+
+def fun_l19_n167()
+ fun_l20_n255
+end
+
+def fun_l19_n168()
+ fun_l20_n286
+end
+
+def fun_l19_n169()
+ fun_l20_n777
+end
+
+def fun_l19_n170()
+ fun_l20_n985
+end
+
+def fun_l19_n171()
+ fun_l20_n827
+end
+
+def fun_l19_n172()
+ fun_l20_n422
+end
+
+def fun_l19_n173()
+ fun_l20_n194
+end
+
+def fun_l19_n174()
+ fun_l20_n399
+end
+
+def fun_l19_n175()
+ fun_l20_n562
+end
+
+def fun_l19_n176()
+ fun_l20_n808
+end
+
+def fun_l19_n177()
+ fun_l20_n646
+end
+
+def fun_l19_n178()
+ fun_l20_n806
+end
+
+def fun_l19_n179()
+ fun_l20_n203
+end
+
+def fun_l19_n180()
+ fun_l20_n426
+end
+
+def fun_l19_n181()
+ fun_l20_n361
+end
+
+def fun_l19_n182()
+ fun_l20_n738
+end
+
+def fun_l19_n183()
+ fun_l20_n446
+end
+
+def fun_l19_n184()
+ fun_l20_n781
+end
+
+def fun_l19_n185()
+ fun_l20_n521
+end
+
+def fun_l19_n186()
+ fun_l20_n599
+end
+
+def fun_l19_n187()
+ fun_l20_n178
+end
+
+def fun_l19_n188()
+ fun_l20_n15
+end
+
+def fun_l19_n189()
+ fun_l20_n846
+end
+
+def fun_l19_n190()
+ fun_l20_n888
+end
+
+def fun_l19_n191()
+ fun_l20_n53
+end
+
+def fun_l19_n192()
+ fun_l20_n943
+end
+
+def fun_l19_n193()
+ fun_l20_n73
+end
+
+def fun_l19_n194()
+ fun_l20_n918
+end
+
+def fun_l19_n195()
+ fun_l20_n924
+end
+
+def fun_l19_n196()
+ fun_l20_n37
+end
+
+def fun_l19_n197()
+ fun_l20_n674
+end
+
+def fun_l19_n198()
+ fun_l20_n167
+end
+
+def fun_l19_n199()
+ fun_l20_n167
+end
+
+def fun_l19_n200()
+ fun_l20_n201
+end
+
+def fun_l19_n201()
+ fun_l20_n785
+end
+
+def fun_l19_n202()
+ fun_l20_n980
+end
+
+def fun_l19_n203()
+ fun_l20_n295
+end
+
+def fun_l19_n204()
+ fun_l20_n586
+end
+
+def fun_l19_n205()
+ fun_l20_n541
+end
+
+def fun_l19_n206()
+ fun_l20_n220
+end
+
+def fun_l19_n207()
+ fun_l20_n956
+end
+
+def fun_l19_n208()
+ fun_l20_n195
+end
+
+def fun_l19_n209()
+ fun_l20_n232
+end
+
+def fun_l19_n210()
+ fun_l20_n91
+end
+
+def fun_l19_n211()
+ fun_l20_n525
+end
+
+def fun_l19_n212()
+ fun_l20_n50
+end
+
+def fun_l19_n213()
+ fun_l20_n635
+end
+
+def fun_l19_n214()
+ fun_l20_n24
+end
+
+def fun_l19_n215()
+ fun_l20_n795
+end
+
+def fun_l19_n216()
+ fun_l20_n743
+end
+
+def fun_l19_n217()
+ fun_l20_n418
+end
+
+def fun_l19_n218()
+ fun_l20_n63
+end
+
+def fun_l19_n219()
+ fun_l20_n866
+end
+
+def fun_l19_n220()
+ fun_l20_n195
+end
+
+def fun_l19_n221()
+ fun_l20_n178
+end
+
+def fun_l19_n222()
+ fun_l20_n147
+end
+
+def fun_l19_n223()
+ fun_l20_n891
+end
+
+def fun_l19_n224()
+ fun_l20_n804
+end
+
+def fun_l19_n225()
+ fun_l20_n379
+end
+
+def fun_l19_n226()
+ fun_l20_n894
+end
+
+def fun_l19_n227()
+ fun_l20_n767
+end
+
+def fun_l19_n228()
+ fun_l20_n532
+end
+
+def fun_l19_n229()
+ fun_l20_n69
+end
+
+def fun_l19_n230()
+ fun_l20_n602
+end
+
+def fun_l19_n231()
+ fun_l20_n933
+end
+
+def fun_l19_n232()
+ fun_l20_n940
+end
+
+def fun_l19_n233()
+ fun_l20_n935
+end
+
+def fun_l19_n234()
+ fun_l20_n234
+end
+
+def fun_l19_n235()
+ fun_l20_n984
+end
+
+def fun_l19_n236()
+ fun_l20_n962
+end
+
+def fun_l19_n237()
+ fun_l20_n334
+end
+
+def fun_l19_n238()
+ fun_l20_n945
+end
+
+def fun_l19_n239()
+ fun_l20_n778
+end
+
+def fun_l19_n240()
+ fun_l20_n946
+end
+
+def fun_l19_n241()
+ fun_l20_n27
+end
+
+def fun_l19_n242()
+ fun_l20_n535
+end
+
+def fun_l19_n243()
+ fun_l20_n940
+end
+
+def fun_l19_n244()
+ fun_l20_n991
+end
+
+def fun_l19_n245()
+ fun_l20_n926
+end
+
+def fun_l19_n246()
+ fun_l20_n945
+end
+
+def fun_l19_n247()
+ fun_l20_n56
+end
+
+def fun_l19_n248()
+ fun_l20_n529
+end
+
+def fun_l19_n249()
+ fun_l20_n497
+end
+
+def fun_l19_n250()
+ fun_l20_n823
+end
+
+def fun_l19_n251()
+ fun_l20_n296
+end
+
+def fun_l19_n252()
+ fun_l20_n342
+end
+
+def fun_l19_n253()
+ fun_l20_n843
+end
+
+def fun_l19_n254()
+ fun_l20_n95
+end
+
+def fun_l19_n255()
+ fun_l20_n0
+end
+
+def fun_l19_n256()
+ fun_l20_n289
+end
+
+def fun_l19_n257()
+ fun_l20_n816
+end
+
+def fun_l19_n258()
+ fun_l20_n318
+end
+
+def fun_l19_n259()
+ fun_l20_n401
+end
+
+def fun_l19_n260()
+ fun_l20_n495
+end
+
+def fun_l19_n261()
+ fun_l20_n331
+end
+
+def fun_l19_n262()
+ fun_l20_n457
+end
+
+def fun_l19_n263()
+ fun_l20_n169
+end
+
+def fun_l19_n264()
+ fun_l20_n736
+end
+
+def fun_l19_n265()
+ fun_l20_n12
+end
+
+def fun_l19_n266()
+ fun_l20_n552
+end
+
+def fun_l19_n267()
+ fun_l20_n350
+end
+
+def fun_l19_n268()
+ fun_l20_n417
+end
+
+def fun_l19_n269()
+ fun_l20_n960
+end
+
+def fun_l19_n270()
+ fun_l20_n251
+end
+
+def fun_l19_n271()
+ fun_l20_n218
+end
+
+def fun_l19_n272()
+ fun_l20_n496
+end
+
+def fun_l19_n273()
+ fun_l20_n262
+end
+
+def fun_l19_n274()
+ fun_l20_n617
+end
+
+def fun_l19_n275()
+ fun_l20_n225
+end
+
+def fun_l19_n276()
+ fun_l20_n878
+end
+
+def fun_l19_n277()
+ fun_l20_n538
+end
+
+def fun_l19_n278()
+ fun_l20_n99
+end
+
+def fun_l19_n279()
+ fun_l20_n654
+end
+
+def fun_l19_n280()
+ fun_l20_n460
+end
+
+def fun_l19_n281()
+ fun_l20_n108
+end
+
+def fun_l19_n282()
+ fun_l20_n62
+end
+
+def fun_l19_n283()
+ fun_l20_n855
+end
+
+def fun_l19_n284()
+ fun_l20_n790
+end
+
+def fun_l19_n285()
+ fun_l20_n838
+end
+
+def fun_l19_n286()
+ fun_l20_n570
+end
+
+def fun_l19_n287()
+ fun_l20_n376
+end
+
+def fun_l19_n288()
+ fun_l20_n219
+end
+
+def fun_l19_n289()
+ fun_l20_n793
+end
+
+def fun_l19_n290()
+ fun_l20_n17
+end
+
+def fun_l19_n291()
+ fun_l20_n408
+end
+
+def fun_l19_n292()
+ fun_l20_n224
+end
+
+def fun_l19_n293()
+ fun_l20_n953
+end
+
+def fun_l19_n294()
+ fun_l20_n0
+end
+
+def fun_l19_n295()
+ fun_l20_n15
+end
+
+def fun_l19_n296()
+ fun_l20_n304
+end
+
+def fun_l19_n297()
+ fun_l20_n917
+end
+
+def fun_l19_n298()
+ fun_l20_n903
+end
+
+def fun_l19_n299()
+ fun_l20_n151
+end
+
+def fun_l19_n300()
+ fun_l20_n704
+end
+
+def fun_l19_n301()
+ fun_l20_n559
+end
+
+def fun_l19_n302()
+ fun_l20_n957
+end
+
+def fun_l19_n303()
+ fun_l20_n607
+end
+
+def fun_l19_n304()
+ fun_l20_n776
+end
+
+def fun_l19_n305()
+ fun_l20_n661
+end
+
+def fun_l19_n306()
+ fun_l20_n545
+end
+
+def fun_l19_n307()
+ fun_l20_n735
+end
+
+def fun_l19_n308()
+ fun_l20_n427
+end
+
+def fun_l19_n309()
+ fun_l20_n427
+end
+
+def fun_l19_n310()
+ fun_l20_n11
+end
+
+def fun_l19_n311()
+ fun_l20_n109
+end
+
+def fun_l19_n312()
+ fun_l20_n84
+end
+
+def fun_l19_n313()
+ fun_l20_n106
+end
+
+def fun_l19_n314()
+ fun_l20_n758
+end
+
+def fun_l19_n315()
+ fun_l20_n343
+end
+
+def fun_l19_n316()
+ fun_l20_n998
+end
+
+def fun_l19_n317()
+ fun_l20_n174
+end
+
+def fun_l19_n318()
+ fun_l20_n12
+end
+
+def fun_l19_n319()
+ fun_l20_n116
+end
+
+def fun_l19_n320()
+ fun_l20_n517
+end
+
+def fun_l19_n321()
+ fun_l20_n15
+end
+
+def fun_l19_n322()
+ fun_l20_n441
+end
+
+def fun_l19_n323()
+ fun_l20_n25
+end
+
+def fun_l19_n324()
+ fun_l20_n101
+end
+
+def fun_l19_n325()
+ fun_l20_n160
+end
+
+def fun_l19_n326()
+ fun_l20_n784
+end
+
+def fun_l19_n327()
+ fun_l20_n940
+end
+
+def fun_l19_n328()
+ fun_l20_n969
+end
+
+def fun_l19_n329()
+ fun_l20_n306
+end
+
+def fun_l19_n330()
+ fun_l20_n337
+end
+
+def fun_l19_n331()
+ fun_l20_n199
+end
+
+def fun_l19_n332()
+ fun_l20_n341
+end
+
+def fun_l19_n333()
+ fun_l20_n2
+end
+
+def fun_l19_n334()
+ fun_l20_n954
+end
+
+def fun_l19_n335()
+ fun_l20_n463
+end
+
+def fun_l19_n336()
+ fun_l20_n16
+end
+
+def fun_l19_n337()
+ fun_l20_n566
+end
+
+def fun_l19_n338()
+ fun_l20_n807
+end
+
+def fun_l19_n339()
+ fun_l20_n785
+end
+
+def fun_l19_n340()
+ fun_l20_n577
+end
+
+def fun_l19_n341()
+ fun_l20_n744
+end
+
+def fun_l19_n342()
+ fun_l20_n769
+end
+
+def fun_l19_n343()
+ fun_l20_n120
+end
+
+def fun_l19_n344()
+ fun_l20_n846
+end
+
+def fun_l19_n345()
+ fun_l20_n7
+end
+
+def fun_l19_n346()
+ fun_l20_n517
+end
+
+def fun_l19_n347()
+ fun_l20_n138
+end
+
+def fun_l19_n348()
+ fun_l20_n551
+end
+
+def fun_l19_n349()
+ fun_l20_n667
+end
+
+def fun_l19_n350()
+ fun_l20_n983
+end
+
+def fun_l19_n351()
+ fun_l20_n941
+end
+
+def fun_l19_n352()
+ fun_l20_n278
+end
+
+def fun_l19_n353()
+ fun_l20_n360
+end
+
+def fun_l19_n354()
+ fun_l20_n327
+end
+
+def fun_l19_n355()
+ fun_l20_n414
+end
+
+def fun_l19_n356()
+ fun_l20_n200
+end
+
+def fun_l19_n357()
+ fun_l20_n298
+end
+
+def fun_l19_n358()
+ fun_l20_n337
+end
+
+def fun_l19_n359()
+ fun_l20_n602
+end
+
+def fun_l19_n360()
+ fun_l20_n631
+end
+
+def fun_l19_n361()
+ fun_l20_n100
+end
+
+def fun_l19_n362()
+ fun_l20_n179
+end
+
+def fun_l19_n363()
+ fun_l20_n710
+end
+
+def fun_l19_n364()
+ fun_l20_n1
+end
+
+def fun_l19_n365()
+ fun_l20_n88
+end
+
+def fun_l19_n366()
+ fun_l20_n98
+end
+
+def fun_l19_n367()
+ fun_l20_n499
+end
+
+def fun_l19_n368()
+ fun_l20_n610
+end
+
+def fun_l19_n369()
+ fun_l20_n243
+end
+
+def fun_l19_n370()
+ fun_l20_n954
+end
+
+def fun_l19_n371()
+ fun_l20_n204
+end
+
+def fun_l19_n372()
+ fun_l20_n618
+end
+
+def fun_l19_n373()
+ fun_l20_n513
+end
+
+def fun_l19_n374()
+ fun_l20_n341
+end
+
+def fun_l19_n375()
+ fun_l20_n31
+end
+
+def fun_l19_n376()
+ fun_l20_n627
+end
+
+def fun_l19_n377()
+ fun_l20_n817
+end
+
+def fun_l19_n378()
+ fun_l20_n545
+end
+
+def fun_l19_n379()
+ fun_l20_n236
+end
+
+def fun_l19_n380()
+ fun_l20_n926
+end
+
+def fun_l19_n381()
+ fun_l20_n167
+end
+
+def fun_l19_n382()
+ fun_l20_n287
+end
+
+def fun_l19_n383()
+ fun_l20_n264
+end
+
+def fun_l19_n384()
+ fun_l20_n16
+end
+
+def fun_l19_n385()
+ fun_l20_n197
+end
+
+def fun_l19_n386()
+ fun_l20_n791
+end
+
+def fun_l19_n387()
+ fun_l20_n124
+end
+
+def fun_l19_n388()
+ fun_l20_n351
+end
+
+def fun_l19_n389()
+ fun_l20_n893
+end
+
+def fun_l19_n390()
+ fun_l20_n191
+end
+
+def fun_l19_n391()
+ fun_l20_n441
+end
+
+def fun_l19_n392()
+ fun_l20_n781
+end
+
+def fun_l19_n393()
+ fun_l20_n614
+end
+
+def fun_l19_n394()
+ fun_l20_n301
+end
+
+def fun_l19_n395()
+ fun_l20_n749
+end
+
+def fun_l19_n396()
+ fun_l20_n815
+end
+
+def fun_l19_n397()
+ fun_l20_n380
+end
+
+def fun_l19_n398()
+ fun_l20_n594
+end
+
+def fun_l19_n399()
+ fun_l20_n279
+end
+
+def fun_l19_n400()
+ fun_l20_n313
+end
+
+def fun_l19_n401()
+ fun_l20_n151
+end
+
+def fun_l19_n402()
+ fun_l20_n101
+end
+
+def fun_l19_n403()
+ fun_l20_n573
+end
+
+def fun_l19_n404()
+ fun_l20_n386
+end
+
+def fun_l19_n405()
+ fun_l20_n40
+end
+
+def fun_l19_n406()
+ fun_l20_n383
+end
+
+def fun_l19_n407()
+ fun_l20_n612
+end
+
+def fun_l19_n408()
+ fun_l20_n555
+end
+
+def fun_l19_n409()
+ fun_l20_n507
+end
+
+def fun_l19_n410()
+ fun_l20_n519
+end
+
+def fun_l19_n411()
+ fun_l20_n842
+end
+
+def fun_l19_n412()
+ fun_l20_n867
+end
+
+def fun_l19_n413()
+ fun_l20_n84
+end
+
+def fun_l19_n414()
+ fun_l20_n84
+end
+
+def fun_l19_n415()
+ fun_l20_n304
+end
+
+def fun_l19_n416()
+ fun_l20_n776
+end
+
+def fun_l19_n417()
+ fun_l20_n712
+end
+
+def fun_l19_n418()
+ fun_l20_n447
+end
+
+def fun_l19_n419()
+ fun_l20_n428
+end
+
+def fun_l19_n420()
+ fun_l20_n350
+end
+
+def fun_l19_n421()
+ fun_l20_n989
+end
+
+def fun_l19_n422()
+ fun_l20_n444
+end
+
+def fun_l19_n423()
+ fun_l20_n771
+end
+
+def fun_l19_n424()
+ fun_l20_n228
+end
+
+def fun_l19_n425()
+ fun_l20_n870
+end
+
+def fun_l19_n426()
+ fun_l20_n553
+end
+
+def fun_l19_n427()
+ fun_l20_n529
+end
+
+def fun_l19_n428()
+ fun_l20_n118
+end
+
+def fun_l19_n429()
+ fun_l20_n886
+end
+
+def fun_l19_n430()
+ fun_l20_n731
+end
+
+def fun_l19_n431()
+ fun_l20_n585
+end
+
+def fun_l19_n432()
+ fun_l20_n997
+end
+
+def fun_l19_n433()
+ fun_l20_n927
+end
+
+def fun_l19_n434()
+ fun_l20_n739
+end
+
+def fun_l19_n435()
+ fun_l20_n691
+end
+
+def fun_l19_n436()
+ fun_l20_n446
+end
+
+def fun_l19_n437()
+ fun_l20_n932
+end
+
+def fun_l19_n438()
+ fun_l20_n297
+end
+
+def fun_l19_n439()
+ fun_l20_n118
+end
+
+def fun_l19_n440()
+ fun_l20_n464
+end
+
+def fun_l19_n441()
+ fun_l20_n367
+end
+
+def fun_l19_n442()
+ fun_l20_n450
+end
+
+def fun_l19_n443()
+ fun_l20_n690
+end
+
+def fun_l19_n444()
+ fun_l20_n996
+end
+
+def fun_l19_n445()
+ fun_l20_n328
+end
+
+def fun_l19_n446()
+ fun_l20_n873
+end
+
+def fun_l19_n447()
+ fun_l20_n843
+end
+
+def fun_l19_n448()
+ fun_l20_n89
+end
+
+def fun_l19_n449()
+ fun_l20_n485
+end
+
+def fun_l19_n450()
+ fun_l20_n343
+end
+
+def fun_l19_n451()
+ fun_l20_n852
+end
+
+def fun_l19_n452()
+ fun_l20_n545
+end
+
+def fun_l19_n453()
+ fun_l20_n41
+end
+
+def fun_l19_n454()
+ fun_l20_n376
+end
+
+def fun_l19_n455()
+ fun_l20_n625
+end
+
+def fun_l19_n456()
+ fun_l20_n495
+end
+
+def fun_l19_n457()
+ fun_l20_n82
+end
+
+def fun_l19_n458()
+ fun_l20_n238
+end
+
+def fun_l19_n459()
+ fun_l20_n355
+end
+
+def fun_l19_n460()
+ fun_l20_n530
+end
+
+def fun_l19_n461()
+ fun_l20_n926
+end
+
+def fun_l19_n462()
+ fun_l20_n721
+end
+
+def fun_l19_n463()
+ fun_l20_n724
+end
+
+def fun_l19_n464()
+ fun_l20_n280
+end
+
+def fun_l19_n465()
+ fun_l20_n656
+end
+
+def fun_l19_n466()
+ fun_l20_n78
+end
+
+def fun_l19_n467()
+ fun_l20_n353
+end
+
+def fun_l19_n468()
+ fun_l20_n712
+end
+
+def fun_l19_n469()
+ fun_l20_n849
+end
+
+def fun_l19_n470()
+ fun_l20_n682
+end
+
+def fun_l19_n471()
+ fun_l20_n964
+end
+
+def fun_l19_n472()
+ fun_l20_n483
+end
+
+def fun_l19_n473()
+ fun_l20_n6
+end
+
+def fun_l19_n474()
+ fun_l20_n19
+end
+
+def fun_l19_n475()
+ fun_l20_n206
+end
+
+def fun_l19_n476()
+ fun_l20_n165
+end
+
+def fun_l19_n477()
+ fun_l20_n514
+end
+
+def fun_l19_n478()
+ fun_l20_n380
+end
+
+def fun_l19_n479()
+ fun_l20_n381
+end
+
+def fun_l19_n480()
+ fun_l20_n210
+end
+
+def fun_l19_n481()
+ fun_l20_n972
+end
+
+def fun_l19_n482()
+ fun_l20_n211
+end
+
+def fun_l19_n483()
+ fun_l20_n795
+end
+
+def fun_l19_n484()
+ fun_l20_n441
+end
+
+def fun_l19_n485()
+ fun_l20_n539
+end
+
+def fun_l19_n486()
+ fun_l20_n217
+end
+
+def fun_l19_n487()
+ fun_l20_n644
+end
+
+def fun_l19_n488()
+ fun_l20_n641
+end
+
+def fun_l19_n489()
+ fun_l20_n179
+end
+
+def fun_l19_n490()
+ fun_l20_n643
+end
+
+def fun_l19_n491()
+ fun_l20_n797
+end
+
+def fun_l19_n492()
+ fun_l20_n863
+end
+
+def fun_l19_n493()
+ fun_l20_n915
+end
+
+def fun_l19_n494()
+ fun_l20_n13
+end
+
+def fun_l19_n495()
+ fun_l20_n427
+end
+
+def fun_l19_n496()
+ fun_l20_n40
+end
+
+def fun_l19_n497()
+ fun_l20_n724
+end
+
+def fun_l19_n498()
+ fun_l20_n666
+end
+
+def fun_l19_n499()
+ fun_l20_n876
+end
+
+def fun_l19_n500()
+ fun_l20_n980
+end
+
+def fun_l19_n501()
+ fun_l20_n817
+end
+
+def fun_l19_n502()
+ fun_l20_n158
+end
+
+def fun_l19_n503()
+ fun_l20_n738
+end
+
+def fun_l19_n504()
+ fun_l20_n347
+end
+
+def fun_l19_n505()
+ fun_l20_n941
+end
+
+def fun_l19_n506()
+ fun_l20_n330
+end
+
+def fun_l19_n507()
+ fun_l20_n196
+end
+
+def fun_l19_n508()
+ fun_l20_n961
+end
+
+def fun_l19_n509()
+ fun_l20_n909
+end
+
+def fun_l19_n510()
+ fun_l20_n489
+end
+
+def fun_l19_n511()
+ fun_l20_n341
+end
+
+def fun_l19_n512()
+ fun_l20_n437
+end
+
+def fun_l19_n513()
+ fun_l20_n293
+end
+
+def fun_l19_n514()
+ fun_l20_n388
+end
+
+def fun_l19_n515()
+ fun_l20_n85
+end
+
+def fun_l19_n516()
+ fun_l20_n769
+end
+
+def fun_l19_n517()
+ fun_l20_n875
+end
+
+def fun_l19_n518()
+ fun_l20_n247
+end
+
+def fun_l19_n519()
+ fun_l20_n607
+end
+
+def fun_l19_n520()
+ fun_l20_n119
+end
+
+def fun_l19_n521()
+ fun_l20_n44
+end
+
+def fun_l19_n522()
+ fun_l20_n870
+end
+
+def fun_l19_n523()
+ fun_l20_n815
+end
+
+def fun_l19_n524()
+ fun_l20_n393
+end
+
+def fun_l19_n525()
+ fun_l20_n158
+end
+
+def fun_l19_n526()
+ fun_l20_n139
+end
+
+def fun_l19_n527()
+ fun_l20_n808
+end
+
+def fun_l19_n528()
+ fun_l20_n549
+end
+
+def fun_l19_n529()
+ fun_l20_n725
+end
+
+def fun_l19_n530()
+ fun_l20_n758
+end
+
+def fun_l19_n531()
+ fun_l20_n650
+end
+
+def fun_l19_n532()
+ fun_l20_n739
+end
+
+def fun_l19_n533()
+ fun_l20_n912
+end
+
+def fun_l19_n534()
+ fun_l20_n632
+end
+
+def fun_l19_n535()
+ fun_l20_n889
+end
+
+def fun_l19_n536()
+ fun_l20_n609
+end
+
+def fun_l19_n537()
+ fun_l20_n997
+end
+
+def fun_l19_n538()
+ fun_l20_n773
+end
+
+def fun_l19_n539()
+ fun_l20_n48
+end
+
+def fun_l19_n540()
+ fun_l20_n102
+end
+
+def fun_l19_n541()
+ fun_l20_n392
+end
+
+def fun_l19_n542()
+ fun_l20_n570
+end
+
+def fun_l19_n543()
+ fun_l20_n36
+end
+
+def fun_l19_n544()
+ fun_l20_n400
+end
+
+def fun_l19_n545()
+ fun_l20_n545
+end
+
+def fun_l19_n546()
+ fun_l20_n27
+end
+
+def fun_l19_n547()
+ fun_l20_n746
+end
+
+def fun_l19_n548()
+ fun_l20_n796
+end
+
+def fun_l19_n549()
+ fun_l20_n651
+end
+
+def fun_l19_n550()
+ fun_l20_n719
+end
+
+def fun_l19_n551()
+ fun_l20_n941
+end
+
+def fun_l19_n552()
+ fun_l20_n799
+end
+
+def fun_l19_n553()
+ fun_l20_n900
+end
+
+def fun_l19_n554()
+ fun_l20_n288
+end
+
+def fun_l19_n555()
+ fun_l20_n52
+end
+
+def fun_l19_n556()
+ fun_l20_n497
+end
+
+def fun_l19_n557()
+ fun_l20_n781
+end
+
+def fun_l19_n558()
+ fun_l20_n209
+end
+
+def fun_l19_n559()
+ fun_l20_n157
+end
+
+def fun_l19_n560()
+ fun_l20_n102
+end
+
+def fun_l19_n561()
+ fun_l20_n248
+end
+
+def fun_l19_n562()
+ fun_l20_n760
+end
+
+def fun_l19_n563()
+ fun_l20_n640
+end
+
+def fun_l19_n564()
+ fun_l20_n30
+end
+
+def fun_l19_n565()
+ fun_l20_n375
+end
+
+def fun_l19_n566()
+ fun_l20_n472
+end
+
+def fun_l19_n567()
+ fun_l20_n223
+end
+
+def fun_l19_n568()
+ fun_l20_n834
+end
+
+def fun_l19_n569()
+ fun_l20_n804
+end
+
+def fun_l19_n570()
+ fun_l20_n620
+end
+
+def fun_l19_n571()
+ fun_l20_n942
+end
+
+def fun_l19_n572()
+ fun_l20_n58
+end
+
+def fun_l19_n573()
+ fun_l20_n113
+end
+
+def fun_l19_n574()
+ fun_l20_n884
+end
+
+def fun_l19_n575()
+ fun_l20_n965
+end
+
+def fun_l19_n576()
+ fun_l20_n975
+end
+
+def fun_l19_n577()
+ fun_l20_n840
+end
+
+def fun_l19_n578()
+ fun_l20_n422
+end
+
+def fun_l19_n579()
+ fun_l20_n213
+end
+
+def fun_l19_n580()
+ fun_l20_n338
+end
+
+def fun_l19_n581()
+ fun_l20_n823
+end
+
+def fun_l19_n582()
+ fun_l20_n284
+end
+
+def fun_l19_n583()
+ fun_l20_n706
+end
+
+def fun_l19_n584()
+ fun_l20_n148
+end
+
+def fun_l19_n585()
+ fun_l20_n750
+end
+
+def fun_l19_n586()
+ fun_l20_n556
+end
+
+def fun_l19_n587()
+ fun_l20_n939
+end
+
+def fun_l19_n588()
+ fun_l20_n885
+end
+
+def fun_l19_n589()
+ fun_l20_n36
+end
+
+def fun_l19_n590()
+ fun_l20_n771
+end
+
+def fun_l19_n591()
+ fun_l20_n958
+end
+
+def fun_l19_n592()
+ fun_l20_n829
+end
+
+def fun_l19_n593()
+ fun_l20_n334
+end
+
+def fun_l19_n594()
+ fun_l20_n546
+end
+
+def fun_l19_n595()
+ fun_l20_n269
+end
+
+def fun_l19_n596()
+ fun_l20_n528
+end
+
+def fun_l19_n597()
+ fun_l20_n63
+end
+
+def fun_l19_n598()
+ fun_l20_n10
+end
+
+def fun_l19_n599()
+ fun_l20_n160
+end
+
+def fun_l19_n600()
+ fun_l20_n750
+end
+
+def fun_l19_n601()
+ fun_l20_n307
+end
+
+def fun_l19_n602()
+ fun_l20_n700
+end
+
+def fun_l19_n603()
+ fun_l20_n720
+end
+
+def fun_l19_n604()
+ fun_l20_n60
+end
+
+def fun_l19_n605()
+ fun_l20_n179
+end
+
+def fun_l19_n606()
+ fun_l20_n425
+end
+
+def fun_l19_n607()
+ fun_l20_n489
+end
+
+def fun_l19_n608()
+ fun_l20_n804
+end
+
+def fun_l19_n609()
+ fun_l20_n276
+end
+
+def fun_l19_n610()
+ fun_l20_n888
+end
+
+def fun_l19_n611()
+ fun_l20_n412
+end
+
+def fun_l19_n612()
+ fun_l20_n715
+end
+
+def fun_l19_n613()
+ fun_l20_n737
+end
+
+def fun_l19_n614()
+ fun_l20_n332
+end
+
+def fun_l19_n615()
+ fun_l20_n4
+end
+
+def fun_l19_n616()
+ fun_l20_n114
+end
+
+def fun_l19_n617()
+ fun_l20_n502
+end
+
+def fun_l19_n618()
+ fun_l20_n825
+end
+
+def fun_l19_n619()
+ fun_l20_n606
+end
+
+def fun_l19_n620()
+ fun_l20_n396
+end
+
+def fun_l19_n621()
+ fun_l20_n810
+end
+
+def fun_l19_n622()
+ fun_l20_n158
+end
+
+def fun_l19_n623()
+ fun_l20_n246
+end
+
+def fun_l19_n624()
+ fun_l20_n973
+end
+
+def fun_l19_n625()
+ fun_l20_n603
+end
+
+def fun_l19_n626()
+ fun_l20_n192
+end
+
+def fun_l19_n627()
+ fun_l20_n744
+end
+
+def fun_l19_n628()
+ fun_l20_n82
+end
+
+def fun_l19_n629()
+ fun_l20_n491
+end
+
+def fun_l19_n630()
+ fun_l20_n576
+end
+
+def fun_l19_n631()
+ fun_l20_n824
+end
+
+def fun_l19_n632()
+ fun_l20_n711
+end
+
+def fun_l19_n633()
+ fun_l20_n989
+end
+
+def fun_l19_n634()
+ fun_l20_n392
+end
+
+def fun_l19_n635()
+ fun_l20_n39
+end
+
+def fun_l19_n636()
+ fun_l20_n755
+end
+
+def fun_l19_n637()
+ fun_l20_n181
+end
+
+def fun_l19_n638()
+ fun_l20_n538
+end
+
+def fun_l19_n639()
+ fun_l20_n801
+end
+
+def fun_l19_n640()
+ fun_l20_n837
+end
+
+def fun_l19_n641()
+ fun_l20_n587
+end
+
+def fun_l19_n642()
+ fun_l20_n680
+end
+
+def fun_l19_n643()
+ fun_l20_n157
+end
+
+def fun_l19_n644()
+ fun_l20_n885
+end
+
+def fun_l19_n645()
+ fun_l20_n421
+end
+
+def fun_l19_n646()
+ fun_l20_n928
+end
+
+def fun_l19_n647()
+ fun_l20_n819
+end
+
+def fun_l19_n648()
+ fun_l20_n206
+end
+
+def fun_l19_n649()
+ fun_l20_n496
+end
+
+def fun_l19_n650()
+ fun_l20_n706
+end
+
+def fun_l19_n651()
+ fun_l20_n976
+end
+
+def fun_l19_n652()
+ fun_l20_n54
+end
+
+def fun_l19_n653()
+ fun_l20_n530
+end
+
+def fun_l19_n654()
+ fun_l20_n893
+end
+
+def fun_l19_n655()
+ fun_l20_n148
+end
+
+def fun_l19_n656()
+ fun_l20_n461
+end
+
+def fun_l19_n657()
+ fun_l20_n286
+end
+
+def fun_l19_n658()
+ fun_l20_n214
+end
+
+def fun_l19_n659()
+ fun_l20_n818
+end
+
+def fun_l19_n660()
+ fun_l20_n685
+end
+
+def fun_l19_n661()
+ fun_l20_n497
+end
+
+def fun_l19_n662()
+ fun_l20_n251
+end
+
+def fun_l19_n663()
+ fun_l20_n385
+end
+
+def fun_l19_n664()
+ fun_l20_n93
+end
+
+def fun_l19_n665()
+ fun_l20_n853
+end
+
+def fun_l19_n666()
+ fun_l20_n298
+end
+
+def fun_l19_n667()
+ fun_l20_n300
+end
+
+def fun_l19_n668()
+ fun_l20_n702
+end
+
+def fun_l19_n669()
+ fun_l20_n430
+end
+
+def fun_l19_n670()
+ fun_l20_n688
+end
+
+def fun_l19_n671()
+ fun_l20_n272
+end
+
+def fun_l19_n672()
+ fun_l20_n351
+end
+
+def fun_l19_n673()
+ fun_l20_n290
+end
+
+def fun_l19_n674()
+ fun_l20_n45
+end
+
+def fun_l19_n675()
+ fun_l20_n530
+end
+
+def fun_l19_n676()
+ fun_l20_n477
+end
+
+def fun_l19_n677()
+ fun_l20_n770
+end
+
+def fun_l19_n678()
+ fun_l20_n49
+end
+
+def fun_l19_n679()
+ fun_l20_n404
+end
+
+def fun_l19_n680()
+ fun_l20_n344
+end
+
+def fun_l19_n681()
+ fun_l20_n707
+end
+
+def fun_l19_n682()
+ fun_l20_n18
+end
+
+def fun_l19_n683()
+ fun_l20_n590
+end
+
+def fun_l19_n684()
+ fun_l20_n281
+end
+
+def fun_l19_n685()
+ fun_l20_n913
+end
+
+def fun_l19_n686()
+ fun_l20_n884
+end
+
+def fun_l19_n687()
+ fun_l20_n696
+end
+
+def fun_l19_n688()
+ fun_l20_n727
+end
+
+def fun_l19_n689()
+ fun_l20_n168
+end
+
+def fun_l19_n690()
+ fun_l20_n178
+end
+
+def fun_l19_n691()
+ fun_l20_n414
+end
+
+def fun_l19_n692()
+ fun_l20_n331
+end
+
+def fun_l19_n693()
+ fun_l20_n701
+end
+
+def fun_l19_n694()
+ fun_l20_n795
+end
+
+def fun_l19_n695()
+ fun_l20_n413
+end
+
+def fun_l19_n696()
+ fun_l20_n613
+end
+
+def fun_l19_n697()
+ fun_l20_n129
+end
+
+def fun_l19_n698()
+ fun_l20_n162
+end
+
+def fun_l19_n699()
+ fun_l20_n24
+end
+
+def fun_l19_n700()
+ fun_l20_n497
+end
+
+def fun_l19_n701()
+ fun_l20_n850
+end
+
+def fun_l19_n702()
+ fun_l20_n28
+end
+
+def fun_l19_n703()
+ fun_l20_n571
+end
+
+def fun_l19_n704()
+ fun_l20_n77
+end
+
+def fun_l19_n705()
+ fun_l20_n705
+end
+
+def fun_l19_n706()
+ fun_l20_n473
+end
+
+def fun_l19_n707()
+ fun_l20_n993
+end
+
+def fun_l19_n708()
+ fun_l20_n51
+end
+
+def fun_l19_n709()
+ fun_l20_n921
+end
+
+def fun_l19_n710()
+ fun_l20_n773
+end
+
+def fun_l19_n711()
+ fun_l20_n137
+end
+
+def fun_l19_n712()
+ fun_l20_n127
+end
+
+def fun_l19_n713()
+ fun_l20_n714
+end
+
+def fun_l19_n714()
+ fun_l20_n76
+end
+
+def fun_l19_n715()
+ fun_l20_n909
+end
+
+def fun_l19_n716()
+ fun_l20_n206
+end
+
+def fun_l19_n717()
+ fun_l20_n37
+end
+
+def fun_l19_n718()
+ fun_l20_n121
+end
+
+def fun_l19_n719()
+ fun_l20_n438
+end
+
+def fun_l19_n720()
+ fun_l20_n42
+end
+
+def fun_l19_n721()
+ fun_l20_n743
+end
+
+def fun_l19_n722()
+ fun_l20_n730
+end
+
+def fun_l19_n723()
+ fun_l20_n190
+end
+
+def fun_l19_n724()
+ fun_l20_n817
+end
+
+def fun_l19_n725()
+ fun_l20_n119
+end
+
+def fun_l19_n726()
+ fun_l20_n201
+end
+
+def fun_l19_n727()
+ fun_l20_n9
+end
+
+def fun_l19_n728()
+ fun_l20_n666
+end
+
+def fun_l19_n729()
+ fun_l20_n595
+end
+
+def fun_l19_n730()
+ fun_l20_n285
+end
+
+def fun_l19_n731()
+ fun_l20_n586
+end
+
+def fun_l19_n732()
+ fun_l20_n228
+end
+
+def fun_l19_n733()
+ fun_l20_n663
+end
+
+def fun_l19_n734()
+ fun_l20_n810
+end
+
+def fun_l19_n735()
+ fun_l20_n348
+end
+
+def fun_l19_n736()
+ fun_l20_n316
+end
+
+def fun_l19_n737()
+ fun_l20_n140
+end
+
+def fun_l19_n738()
+ fun_l20_n668
+end
+
+def fun_l19_n739()
+ fun_l20_n956
+end
+
+def fun_l19_n740()
+ fun_l20_n252
+end
+
+def fun_l19_n741()
+ fun_l20_n490
+end
+
+def fun_l19_n742()
+ fun_l20_n6
+end
+
+def fun_l19_n743()
+ fun_l20_n389
+end
+
+def fun_l19_n744()
+ fun_l20_n939
+end
+
+def fun_l19_n745()
+ fun_l20_n152
+end
+
+def fun_l19_n746()
+ fun_l20_n895
+end
+
+def fun_l19_n747()
+ fun_l20_n769
+end
+
+def fun_l19_n748()
+ fun_l20_n100
+end
+
+def fun_l19_n749()
+ fun_l20_n492
+end
+
+def fun_l19_n750()
+ fun_l20_n410
+end
+
+def fun_l19_n751()
+ fun_l20_n514
+end
+
+def fun_l19_n752()
+ fun_l20_n801
+end
+
+def fun_l19_n753()
+ fun_l20_n148
+end
+
+def fun_l19_n754()
+ fun_l20_n179
+end
+
+def fun_l19_n755()
+ fun_l20_n35
+end
+
+def fun_l19_n756()
+ fun_l20_n60
+end
+
+def fun_l19_n757()
+ fun_l20_n247
+end
+
+def fun_l19_n758()
+ fun_l20_n783
+end
+
+def fun_l19_n759()
+ fun_l20_n357
+end
+
+def fun_l19_n760()
+ fun_l20_n245
+end
+
+def fun_l19_n761()
+ fun_l20_n26
+end
+
+def fun_l19_n762()
+ fun_l20_n77
+end
+
+def fun_l19_n763()
+ fun_l20_n886
+end
+
+def fun_l19_n764()
+ fun_l20_n375
+end
+
+def fun_l19_n765()
+ fun_l20_n238
+end
+
+def fun_l19_n766()
+ fun_l20_n444
+end
+
+def fun_l19_n767()
+ fun_l20_n665
+end
+
+def fun_l19_n768()
+ fun_l20_n328
+end
+
+def fun_l19_n769()
+ fun_l20_n598
+end
+
+def fun_l19_n770()
+ fun_l20_n988
+end
+
+def fun_l19_n771()
+ fun_l20_n350
+end
+
+def fun_l19_n772()
+ fun_l20_n474
+end
+
+def fun_l19_n773()
+ fun_l20_n460
+end
+
+def fun_l19_n774()
+ fun_l20_n535
+end
+
+def fun_l19_n775()
+ fun_l20_n451
+end
+
+def fun_l19_n776()
+ fun_l20_n945
+end
+
+def fun_l19_n777()
+ fun_l20_n902
+end
+
+def fun_l19_n778()
+ fun_l20_n714
+end
+
+def fun_l19_n779()
+ fun_l20_n5
+end
+
+def fun_l19_n780()
+ fun_l20_n32
+end
+
+def fun_l19_n781()
+ fun_l20_n99
+end
+
+def fun_l19_n782()
+ fun_l20_n931
+end
+
+def fun_l19_n783()
+ fun_l20_n664
+end
+
+def fun_l19_n784()
+ fun_l20_n676
+end
+
+def fun_l19_n785()
+ fun_l20_n671
+end
+
+def fun_l19_n786()
+ fun_l20_n982
+end
+
+def fun_l19_n787()
+ fun_l20_n754
+end
+
+def fun_l19_n788()
+ fun_l20_n945
+end
+
+def fun_l19_n789()
+ fun_l20_n130
+end
+
+def fun_l19_n790()
+ fun_l20_n390
+end
+
+def fun_l19_n791()
+ fun_l20_n999
+end
+
+def fun_l19_n792()
+ fun_l20_n138
+end
+
+def fun_l19_n793()
+ fun_l20_n180
+end
+
+def fun_l19_n794()
+ fun_l20_n897
+end
+
+def fun_l19_n795()
+ fun_l20_n85
+end
+
+def fun_l19_n796()
+ fun_l20_n295
+end
+
+def fun_l19_n797()
+ fun_l20_n577
+end
+
+def fun_l19_n798()
+ fun_l20_n131
+end
+
+def fun_l19_n799()
+ fun_l20_n847
+end
+
+def fun_l19_n800()
+ fun_l20_n703
+end
+
+def fun_l19_n801()
+ fun_l20_n82
+end
+
+def fun_l19_n802()
+ fun_l20_n758
+end
+
+def fun_l19_n803()
+ fun_l20_n789
+end
+
+def fun_l19_n804()
+ fun_l20_n353
+end
+
+def fun_l19_n805()
+ fun_l20_n957
+end
+
+def fun_l19_n806()
+ fun_l20_n135
+end
+
+def fun_l19_n807()
+ fun_l20_n87
+end
+
+def fun_l19_n808()
+ fun_l20_n428
+end
+
+def fun_l19_n809()
+ fun_l20_n660
+end
+
+def fun_l19_n810()
+ fun_l20_n844
+end
+
+def fun_l19_n811()
+ fun_l20_n816
+end
+
+def fun_l19_n812()
+ fun_l20_n478
+end
+
+def fun_l19_n813()
+ fun_l20_n823
+end
+
+def fun_l19_n814()
+ fun_l20_n28
+end
+
+def fun_l19_n815()
+ fun_l20_n965
+end
+
+def fun_l19_n816()
+ fun_l20_n469
+end
+
+def fun_l19_n817()
+ fun_l20_n31
+end
+
+def fun_l19_n818()
+ fun_l20_n639
+end
+
+def fun_l19_n819()
+ fun_l20_n831
+end
+
+def fun_l19_n820()
+ fun_l20_n337
+end
+
+def fun_l19_n821()
+ fun_l20_n330
+end
+
+def fun_l19_n822()
+ fun_l20_n366
+end
+
+def fun_l19_n823()
+ fun_l20_n992
+end
+
+def fun_l19_n824()
+ fun_l20_n349
+end
+
+def fun_l19_n825()
+ fun_l20_n291
+end
+
+def fun_l19_n826()
+ fun_l20_n110
+end
+
+def fun_l19_n827()
+ fun_l20_n204
+end
+
+def fun_l19_n828()
+ fun_l20_n122
+end
+
+def fun_l19_n829()
+ fun_l20_n683
+end
+
+def fun_l19_n830()
+ fun_l20_n759
+end
+
+def fun_l19_n831()
+ fun_l20_n619
+end
+
+def fun_l19_n832()
+ fun_l20_n102
+end
+
+def fun_l19_n833()
+ fun_l20_n532
+end
+
+def fun_l19_n834()
+ fun_l20_n620
+end
+
+def fun_l19_n835()
+ fun_l20_n511
+end
+
+def fun_l19_n836()
+ fun_l20_n80
+end
+
+def fun_l19_n837()
+ fun_l20_n731
+end
+
+def fun_l19_n838()
+ fun_l20_n975
+end
+
+def fun_l19_n839()
+ fun_l20_n947
+end
+
+def fun_l19_n840()
+ fun_l20_n243
+end
+
+def fun_l19_n841()
+ fun_l20_n168
+end
+
+def fun_l19_n842()
+ fun_l20_n31
+end
+
+def fun_l19_n843()
+ fun_l20_n979
+end
+
+def fun_l19_n844()
+ fun_l20_n232
+end
+
+def fun_l19_n845()
+ fun_l20_n596
+end
+
+def fun_l19_n846()
+ fun_l20_n415
+end
+
+def fun_l19_n847()
+ fun_l20_n380
+end
+
+def fun_l19_n848()
+ fun_l20_n904
+end
+
+def fun_l19_n849()
+ fun_l20_n858
+end
+
+def fun_l19_n850()
+ fun_l20_n70
+end
+
+def fun_l19_n851()
+ fun_l20_n204
+end
+
+def fun_l19_n852()
+ fun_l20_n501
+end
+
+def fun_l19_n853()
+ fun_l20_n901
+end
+
+def fun_l19_n854()
+ fun_l20_n107
+end
+
+def fun_l19_n855()
+ fun_l20_n391
+end
+
+def fun_l19_n856()
+ fun_l20_n225
+end
+
+def fun_l19_n857()
+ fun_l20_n173
+end
+
+def fun_l19_n858()
+ fun_l20_n143
+end
+
+def fun_l19_n859()
+ fun_l20_n482
+end
+
+def fun_l19_n860()
+ fun_l20_n614
+end
+
+def fun_l19_n861()
+ fun_l20_n819
+end
+
+def fun_l19_n862()
+ fun_l20_n536
+end
+
+def fun_l19_n863()
+ fun_l20_n370
+end
+
+def fun_l19_n864()
+ fun_l20_n139
+end
+
+def fun_l19_n865()
+ fun_l20_n434
+end
+
+def fun_l19_n866()
+ fun_l20_n529
+end
+
+def fun_l19_n867()
+ fun_l20_n770
+end
+
+def fun_l19_n868()
+ fun_l20_n507
+end
+
+def fun_l19_n869()
+ fun_l20_n453
+end
+
+def fun_l19_n870()
+ fun_l20_n417
+end
+
+def fun_l19_n871()
+ fun_l20_n305
+end
+
+def fun_l19_n872()
+ fun_l20_n537
+end
+
+def fun_l19_n873()
+ fun_l20_n613
+end
+
+def fun_l19_n874()
+ fun_l20_n920
+end
+
+def fun_l19_n875()
+ fun_l20_n623
+end
+
+def fun_l19_n876()
+ fun_l20_n212
+end
+
+def fun_l19_n877()
+ fun_l20_n980
+end
+
+def fun_l19_n878()
+ fun_l20_n580
+end
+
+def fun_l19_n879()
+ fun_l20_n112
+end
+
+def fun_l19_n880()
+ fun_l20_n460
+end
+
+def fun_l19_n881()
+ fun_l20_n364
+end
+
+def fun_l19_n882()
+ fun_l20_n685
+end
+
+def fun_l19_n883()
+ fun_l20_n429
+end
+
+def fun_l19_n884()
+ fun_l20_n90
+end
+
+def fun_l19_n885()
+ fun_l20_n448
+end
+
+def fun_l19_n886()
+ fun_l20_n898
+end
+
+def fun_l19_n887()
+ fun_l20_n10
+end
+
+def fun_l19_n888()
+ fun_l20_n618
+end
+
+def fun_l19_n889()
+ fun_l20_n447
+end
+
+def fun_l19_n890()
+ fun_l20_n414
+end
+
+def fun_l19_n891()
+ fun_l20_n570
+end
+
+def fun_l19_n892()
+ fun_l20_n828
+end
+
+def fun_l19_n893()
+ fun_l20_n367
+end
+
+def fun_l19_n894()
+ fun_l20_n897
+end
+
+def fun_l19_n895()
+ fun_l20_n978
+end
+
+def fun_l19_n896()
+ fun_l20_n57
+end
+
+def fun_l19_n897()
+ fun_l20_n61
+end
+
+def fun_l19_n898()
+ fun_l20_n483
+end
+
+def fun_l19_n899()
+ fun_l20_n407
+end
+
+def fun_l19_n900()
+ fun_l20_n369
+end
+
+def fun_l19_n901()
+ fun_l20_n635
+end
+
+def fun_l19_n902()
+ fun_l20_n800
+end
+
+def fun_l19_n903()
+ fun_l20_n748
+end
+
+def fun_l19_n904()
+ fun_l20_n436
+end
+
+def fun_l19_n905()
+ fun_l20_n990
+end
+
+def fun_l19_n906()
+ fun_l20_n484
+end
+
+def fun_l19_n907()
+ fun_l20_n530
+end
+
+def fun_l19_n908()
+ fun_l20_n692
+end
+
+def fun_l19_n909()
+ fun_l20_n356
+end
+
+def fun_l19_n910()
+ fun_l20_n786
+end
+
+def fun_l19_n911()
+ fun_l20_n894
+end
+
+def fun_l19_n912()
+ fun_l20_n217
+end
+
+def fun_l19_n913()
+ fun_l20_n495
+end
+
+def fun_l19_n914()
+ fun_l20_n878
+end
+
+def fun_l19_n915()
+ fun_l20_n166
+end
+
+def fun_l19_n916()
+ fun_l20_n558
+end
+
+def fun_l19_n917()
+ fun_l20_n704
+end
+
+def fun_l19_n918()
+ fun_l20_n996
+end
+
+def fun_l19_n919()
+ fun_l20_n302
+end
+
+def fun_l19_n920()
+ fun_l20_n44
+end
+
+def fun_l19_n921()
+ fun_l20_n694
+end
+
+def fun_l19_n922()
+ fun_l20_n221
+end
+
+def fun_l19_n923()
+ fun_l20_n419
+end
+
+def fun_l19_n924()
+ fun_l20_n400
+end
+
+def fun_l19_n925()
+ fun_l20_n306
+end
+
+def fun_l19_n926()
+ fun_l20_n785
+end
+
+def fun_l19_n927()
+ fun_l20_n851
+end
+
+def fun_l19_n928()
+ fun_l20_n769
+end
+
+def fun_l19_n929()
+ fun_l20_n547
+end
+
+def fun_l19_n930()
+ fun_l20_n887
+end
+
+def fun_l19_n931()
+ fun_l20_n413
+end
+
+def fun_l19_n932()
+ fun_l20_n253
+end
+
+def fun_l19_n933()
+ fun_l20_n37
+end
+
+def fun_l19_n934()
+ fun_l20_n405
+end
+
+def fun_l19_n935()
+ fun_l20_n926
+end
+
+def fun_l19_n936()
+ fun_l20_n864
+end
+
+def fun_l19_n937()
+ fun_l20_n231
+end
+
+def fun_l19_n938()
+ fun_l20_n688
+end
+
+def fun_l19_n939()
+ fun_l20_n144
+end
+
+def fun_l19_n940()
+ fun_l20_n606
+end
+
+def fun_l19_n941()
+ fun_l20_n180
+end
+
+def fun_l19_n942()
+ fun_l20_n103
+end
+
+def fun_l19_n943()
+ fun_l20_n314
+end
+
+def fun_l19_n944()
+ fun_l20_n966
+end
+
+def fun_l19_n945()
+ fun_l20_n15
+end
+
+def fun_l19_n946()
+ fun_l20_n343
+end
+
+def fun_l19_n947()
+ fun_l20_n388
+end
+
+def fun_l19_n948()
+ fun_l20_n868
+end
+
+def fun_l19_n949()
+ fun_l20_n939
+end
+
+def fun_l19_n950()
+ fun_l20_n364
+end
+
+def fun_l19_n951()
+ fun_l20_n739
+end
+
+def fun_l19_n952()
+ fun_l20_n725
+end
+
+def fun_l19_n953()
+ fun_l20_n463
+end
+
+def fun_l19_n954()
+ fun_l20_n737
+end
+
+def fun_l19_n955()
+ fun_l20_n83
+end
+
+def fun_l19_n956()
+ fun_l20_n807
+end
+
+def fun_l19_n957()
+ fun_l20_n710
+end
+
+def fun_l19_n958()
+ fun_l20_n48
+end
+
+def fun_l19_n959()
+ fun_l20_n82
+end
+
+def fun_l19_n960()
+ fun_l20_n330
+end
+
+def fun_l19_n961()
+ fun_l20_n378
+end
+
+def fun_l19_n962()
+ fun_l20_n35
+end
+
+def fun_l19_n963()
+ fun_l20_n191
+end
+
+def fun_l19_n964()
+ fun_l20_n282
+end
+
+def fun_l19_n965()
+ fun_l20_n222
+end
+
+def fun_l19_n966()
+ fun_l20_n416
+end
+
+def fun_l19_n967()
+ fun_l20_n304
+end
+
+def fun_l19_n968()
+ fun_l20_n325
+end
+
+def fun_l19_n969()
+ fun_l20_n374
+end
+
+def fun_l19_n970()
+ fun_l20_n25
+end
+
+def fun_l19_n971()
+ fun_l20_n815
+end
+
+def fun_l19_n972()
+ fun_l20_n272
+end
+
+def fun_l19_n973()
+ fun_l20_n57
+end
+
+def fun_l19_n974()
+ fun_l20_n567
+end
+
+def fun_l19_n975()
+ fun_l20_n995
+end
+
+def fun_l19_n976()
+ fun_l20_n390
+end
+
+def fun_l19_n977()
+ fun_l20_n706
+end
+
+def fun_l19_n978()
+ fun_l20_n496
+end
+
+def fun_l19_n979()
+ fun_l20_n685
+end
+
+def fun_l19_n980()
+ fun_l20_n277
+end
+
+def fun_l19_n981()
+ fun_l20_n933
+end
+
+def fun_l19_n982()
+ fun_l20_n958
+end
+
+def fun_l19_n983()
+ fun_l20_n9
+end
+
+def fun_l19_n984()
+ fun_l20_n455
+end
+
+def fun_l19_n985()
+ fun_l20_n824
+end
+
+def fun_l19_n986()
+ fun_l20_n855
+end
+
+def fun_l19_n987()
+ fun_l20_n561
+end
+
+def fun_l19_n988()
+ fun_l20_n66
+end
+
+def fun_l19_n989()
+ fun_l20_n836
+end
+
+def fun_l19_n990()
+ fun_l20_n466
+end
+
+def fun_l19_n991()
+ fun_l20_n902
+end
+
+def fun_l19_n992()
+ fun_l20_n196
+end
+
+def fun_l19_n993()
+ fun_l20_n488
+end
+
+def fun_l19_n994()
+ fun_l20_n490
+end
+
+def fun_l19_n995()
+ fun_l20_n463
+end
+
+def fun_l19_n996()
+ fun_l20_n222
+end
+
+def fun_l19_n997()
+ fun_l20_n935
+end
+
+def fun_l19_n998()
+ fun_l20_n664
+end
+
+def fun_l19_n999()
+ fun_l20_n44
+end
+
+def fun_l20_n0()
+ fun_l21_n583
+end
+
+def fun_l20_n1()
+ fun_l21_n600
+end
+
+def fun_l20_n2()
+ fun_l21_n308
+end
+
+def fun_l20_n3()
+ fun_l21_n395
+end
+
+def fun_l20_n4()
+ fun_l21_n468
+end
+
+def fun_l20_n5()
+ fun_l21_n340
+end
+
+def fun_l20_n6()
+ fun_l21_n647
+end
+
+def fun_l20_n7()
+ fun_l21_n53
+end
+
+def fun_l20_n8()
+ fun_l21_n231
+end
+
+def fun_l20_n9()
+ fun_l21_n965
+end
+
+def fun_l20_n10()
+ fun_l21_n82
+end
+
+def fun_l20_n11()
+ fun_l21_n464
+end
+
+def fun_l20_n12()
+ fun_l21_n694
+end
+
+def fun_l20_n13()
+ fun_l21_n398
+end
+
+def fun_l20_n14()
+ fun_l21_n197
+end
+
+def fun_l20_n15()
+ fun_l21_n447
+end
+
+def fun_l20_n16()
+ fun_l21_n976
+end
+
+def fun_l20_n17()
+ fun_l21_n421
+end
+
+def fun_l20_n18()
+ fun_l21_n163
+end
+
+def fun_l20_n19()
+ fun_l21_n467
+end
+
+def fun_l20_n20()
+ fun_l21_n210
+end
+
+def fun_l20_n21()
+ fun_l21_n837
+end
+
+def fun_l20_n22()
+ fun_l21_n257
+end
+
+def fun_l20_n23()
+ fun_l21_n818
+end
+
+def fun_l20_n24()
+ fun_l21_n585
+end
+
+def fun_l20_n25()
+ fun_l21_n125
+end
+
+def fun_l20_n26()
+ fun_l21_n740
+end
+
+def fun_l20_n27()
+ fun_l21_n771
+end
+
+def fun_l20_n28()
+ fun_l21_n559
+end
+
+def fun_l20_n29()
+ fun_l21_n591
+end
+
+def fun_l20_n30()
+ fun_l21_n37
+end
+
+def fun_l20_n31()
+ fun_l21_n796
+end
+
+def fun_l20_n32()
+ fun_l21_n762
+end
+
+def fun_l20_n33()
+ fun_l21_n26
+end
+
+def fun_l20_n34()
+ fun_l21_n70
+end
+
+def fun_l20_n35()
+ fun_l21_n789
+end
+
+def fun_l20_n36()
+ fun_l21_n389
+end
+
+def fun_l20_n37()
+ fun_l21_n769
+end
+
+def fun_l20_n38()
+ fun_l21_n296
+end
+
+def fun_l20_n39()
+ fun_l21_n131
+end
+
+def fun_l20_n40()
+ fun_l21_n405
+end
+
+def fun_l20_n41()
+ fun_l21_n546
+end
+
+def fun_l20_n42()
+ fun_l21_n232
+end
+
+def fun_l20_n43()
+ fun_l21_n538
+end
+
+def fun_l20_n44()
+ fun_l21_n55
+end
+
+def fun_l20_n45()
+ fun_l21_n962
+end
+
+def fun_l20_n46()
+ fun_l21_n664
+end
+
+def fun_l20_n47()
+ fun_l21_n443
+end
+
+def fun_l20_n48()
+ fun_l21_n854
+end
+
+def fun_l20_n49()
+ fun_l21_n392
+end
+
+def fun_l20_n50()
+ fun_l21_n699
+end
+
+def fun_l20_n51()
+ fun_l21_n748
+end
+
+def fun_l20_n52()
+ fun_l21_n891
+end
+
+def fun_l20_n53()
+ fun_l21_n411
+end
+
+def fun_l20_n54()
+ fun_l21_n798
+end
+
+def fun_l20_n55()
+ fun_l21_n99
+end
+
+def fun_l20_n56()
+ fun_l21_n538
+end
+
+def fun_l20_n57()
+ fun_l21_n473
+end
+
+def fun_l20_n58()
+ fun_l21_n498
+end
+
+def fun_l20_n59()
+ fun_l21_n769
+end
+
+def fun_l20_n60()
+ fun_l21_n117
+end
+
+def fun_l20_n61()
+ fun_l21_n487
+end
+
+def fun_l20_n62()
+ fun_l21_n538
+end
+
+def fun_l20_n63()
+ fun_l21_n312
+end
+
+def fun_l20_n64()
+ fun_l21_n642
+end
+
+def fun_l20_n65()
+ fun_l21_n877
+end
+
+def fun_l20_n66()
+ fun_l21_n481
+end
+
+def fun_l20_n67()
+ fun_l21_n252
+end
+
+def fun_l20_n68()
+ fun_l21_n367
+end
+
+def fun_l20_n69()
+ fun_l21_n438
+end
+
+def fun_l20_n70()
+ fun_l21_n811
+end
+
+def fun_l20_n71()
+ fun_l21_n807
+end
+
+def fun_l20_n72()
+ fun_l21_n410
+end
+
+def fun_l20_n73()
+ fun_l21_n590
+end
+
+def fun_l20_n74()
+ fun_l21_n963
+end
+
+def fun_l20_n75()
+ fun_l21_n103
+end
+
+def fun_l20_n76()
+ fun_l21_n786
+end
+
+def fun_l20_n77()
+ fun_l21_n256
+end
+
+def fun_l20_n78()
+ fun_l21_n306
+end
+
+def fun_l20_n79()
+ fun_l21_n248
+end
+
+def fun_l20_n80()
+ fun_l21_n931
+end
+
+def fun_l20_n81()
+ fun_l21_n926
+end
+
+def fun_l20_n82()
+ fun_l21_n702
+end
+
+def fun_l20_n83()
+ fun_l21_n611
+end
+
+def fun_l20_n84()
+ fun_l21_n279
+end
+
+def fun_l20_n85()
+ fun_l21_n977
+end
+
+def fun_l20_n86()
+ fun_l21_n239
+end
+
+def fun_l20_n87()
+ fun_l21_n370
+end
+
+def fun_l20_n88()
+ fun_l21_n652
+end
+
+def fun_l20_n89()
+ fun_l21_n956
+end
+
+def fun_l20_n90()
+ fun_l21_n998
+end
+
+def fun_l20_n91()
+ fun_l21_n523
+end
+
+def fun_l20_n92()
+ fun_l21_n376
+end
+
+def fun_l20_n93()
+ fun_l21_n604
+end
+
+def fun_l20_n94()
+ fun_l21_n908
+end
+
+def fun_l20_n95()
+ fun_l21_n716
+end
+
+def fun_l20_n96()
+ fun_l21_n9
+end
+
+def fun_l20_n97()
+ fun_l21_n571
+end
+
+def fun_l20_n98()
+ fun_l21_n787
+end
+
+def fun_l20_n99()
+ fun_l21_n453
+end
+
+def fun_l20_n100()
+ fun_l21_n899
+end
+
+def fun_l20_n101()
+ fun_l21_n491
+end
+
+def fun_l20_n102()
+ fun_l21_n47
+end
+
+def fun_l20_n103()
+ fun_l21_n892
+end
+
+def fun_l20_n104()
+ fun_l21_n974
+end
+
+def fun_l20_n105()
+ fun_l21_n993
+end
+
+def fun_l20_n106()
+ fun_l21_n625
+end
+
+def fun_l20_n107()
+ fun_l21_n743
+end
+
+def fun_l20_n108()
+ fun_l21_n266
+end
+
+def fun_l20_n109()
+ fun_l21_n650
+end
+
+def fun_l20_n110()
+ fun_l21_n642
+end
+
+def fun_l20_n111()
+ fun_l21_n905
+end
+
+def fun_l20_n112()
+ fun_l21_n225
+end
+
+def fun_l20_n113()
+ fun_l21_n857
+end
+
+def fun_l20_n114()
+ fun_l21_n82
+end
+
+def fun_l20_n115()
+ fun_l21_n166
+end
+
+def fun_l20_n116()
+ fun_l21_n844
+end
+
+def fun_l20_n117()
+ fun_l21_n619
+end
+
+def fun_l20_n118()
+ fun_l21_n743
+end
+
+def fun_l20_n119()
+ fun_l21_n69
+end
+
+def fun_l20_n120()
+ fun_l21_n410
+end
+
+def fun_l20_n121()
+ fun_l21_n364
+end
+
+def fun_l20_n122()
+ fun_l21_n186
+end
+
+def fun_l20_n123()
+ fun_l21_n750
+end
+
+def fun_l20_n124()
+ fun_l21_n683
+end
+
+def fun_l20_n125()
+ fun_l21_n576
+end
+
+def fun_l20_n126()
+ fun_l21_n287
+end
+
+def fun_l20_n127()
+ fun_l21_n483
+end
+
+def fun_l20_n128()
+ fun_l21_n738
+end
+
+def fun_l20_n129()
+ fun_l21_n779
+end
+
+def fun_l20_n130()
+ fun_l21_n209
+end
+
+def fun_l20_n131()
+ fun_l21_n652
+end
+
+def fun_l20_n132()
+ fun_l21_n583
+end
+
+def fun_l20_n133()
+ fun_l21_n389
+end
+
+def fun_l20_n134()
+ fun_l21_n289
+end
+
+def fun_l20_n135()
+ fun_l21_n993
+end
+
+def fun_l20_n136()
+ fun_l21_n216
+end
+
+def fun_l20_n137()
+ fun_l21_n118
+end
+
+def fun_l20_n138()
+ fun_l21_n484
+end
+
+def fun_l20_n139()
+ fun_l21_n602
+end
+
+def fun_l20_n140()
+ fun_l21_n714
+end
+
+def fun_l20_n141()
+ fun_l21_n247
+end
+
+def fun_l20_n142()
+ fun_l21_n27
+end
+
+def fun_l20_n143()
+ fun_l21_n939
+end
+
+def fun_l20_n144()
+ fun_l21_n565
+end
+
+def fun_l20_n145()
+ fun_l21_n869
+end
+
+def fun_l20_n146()
+ fun_l21_n569
+end
+
+def fun_l20_n147()
+ fun_l21_n876
+end
+
+def fun_l20_n148()
+ fun_l21_n796
+end
+
+def fun_l20_n149()
+ fun_l21_n754
+end
+
+def fun_l20_n150()
+ fun_l21_n664
+end
+
+def fun_l20_n151()
+ fun_l21_n836
+end
+
+def fun_l20_n152()
+ fun_l21_n389
+end
+
+def fun_l20_n153()
+ fun_l21_n111
+end
+
+def fun_l20_n154()
+ fun_l21_n361
+end
+
+def fun_l20_n155()
+ fun_l21_n733
+end
+
+def fun_l20_n156()
+ fun_l21_n215
+end
+
+def fun_l20_n157()
+ fun_l21_n509
+end
+
+def fun_l20_n158()
+ fun_l21_n12
+end
+
+def fun_l20_n159()
+ fun_l21_n351
+end
+
+def fun_l20_n160()
+ fun_l21_n872
+end
+
+def fun_l20_n161()
+ fun_l21_n888
+end
+
+def fun_l20_n162()
+ fun_l21_n126
+end
+
+def fun_l20_n163()
+ fun_l21_n681
+end
+
+def fun_l20_n164()
+ fun_l21_n160
+end
+
+def fun_l20_n165()
+ fun_l21_n917
+end
+
+def fun_l20_n166()
+ fun_l21_n255
+end
+
+def fun_l20_n167()
+ fun_l21_n37
+end
+
+def fun_l20_n168()
+ fun_l21_n949
+end
+
+def fun_l20_n169()
+ fun_l21_n925
+end
+
+def fun_l20_n170()
+ fun_l21_n921
+end
+
+def fun_l20_n171()
+ fun_l21_n123
+end
+
+def fun_l20_n172()
+ fun_l21_n783
+end
+
+def fun_l20_n173()
+ fun_l21_n45
+end
+
+def fun_l20_n174()
+ fun_l21_n994
+end
+
+def fun_l20_n175()
+ fun_l21_n745
+end
+
+def fun_l20_n176()
+ fun_l21_n122
+end
+
+def fun_l20_n177()
+ fun_l21_n25
+end
+
+def fun_l20_n178()
+ fun_l21_n594
+end
+
+def fun_l20_n179()
+ fun_l21_n115
+end
+
+def fun_l20_n180()
+ fun_l21_n274
+end
+
+def fun_l20_n181()
+ fun_l21_n423
+end
+
+def fun_l20_n182()
+ fun_l21_n68
+end
+
+def fun_l20_n183()
+ fun_l21_n598
+end
+
+def fun_l20_n184()
+ fun_l21_n640
+end
+
+def fun_l20_n185()
+ fun_l21_n810
+end
+
+def fun_l20_n186()
+ fun_l21_n150
+end
+
+def fun_l20_n187()
+ fun_l21_n4
+end
+
+def fun_l20_n188()
+ fun_l21_n487
+end
+
+def fun_l20_n189()
+ fun_l21_n327
+end
+
+def fun_l20_n190()
+ fun_l21_n652
+end
+
+def fun_l20_n191()
+ fun_l21_n913
+end
+
+def fun_l20_n192()
+ fun_l21_n323
+end
+
+def fun_l20_n193()
+ fun_l21_n193
+end
+
+def fun_l20_n194()
+ fun_l21_n527
+end
+
+def fun_l20_n195()
+ fun_l21_n123
+end
+
+def fun_l20_n196()
+ fun_l21_n568
+end
+
+def fun_l20_n197()
+ fun_l21_n629
+end
+
+def fun_l20_n198()
+ fun_l21_n727
+end
+
+def fun_l20_n199()
+ fun_l21_n470
+end
+
+def fun_l20_n200()
+ fun_l21_n608
+end
+
+def fun_l20_n201()
+ fun_l21_n941
+end
+
+def fun_l20_n202()
+ fun_l21_n256
+end
+
+def fun_l20_n203()
+ fun_l21_n624
+end
+
+def fun_l20_n204()
+ fun_l21_n714
+end
+
+def fun_l20_n205()
+ fun_l21_n754
+end
+
+def fun_l20_n206()
+ fun_l21_n513
+end
+
+def fun_l20_n207()
+ fun_l21_n730
+end
+
+def fun_l20_n208()
+ fun_l21_n132
+end
+
+def fun_l20_n209()
+ fun_l21_n205
+end
+
+def fun_l20_n210()
+ fun_l21_n549
+end
+
+def fun_l20_n211()
+ fun_l21_n713
+end
+
+def fun_l20_n212()
+ fun_l21_n51
+end
+
+def fun_l20_n213()
+ fun_l21_n712
+end
+
+def fun_l20_n214()
+ fun_l21_n439
+end
+
+def fun_l20_n215()
+ fun_l21_n969
+end
+
+def fun_l20_n216()
+ fun_l21_n338
+end
+
+def fun_l20_n217()
+ fun_l21_n852
+end
+
+def fun_l20_n218()
+ fun_l21_n935
+end
+
+def fun_l20_n219()
+ fun_l21_n935
+end
+
+def fun_l20_n220()
+ fun_l21_n967
+end
+
+def fun_l20_n221()
+ fun_l21_n195
+end
+
+def fun_l20_n222()
+ fun_l21_n556
+end
+
+def fun_l20_n223()
+ fun_l21_n669
+end
+
+def fun_l20_n224()
+ fun_l21_n874
+end
+
+def fun_l20_n225()
+ fun_l21_n985
+end
+
+def fun_l20_n226()
+ fun_l21_n769
+end
+
+def fun_l20_n227()
+ fun_l21_n482
+end
+
+def fun_l20_n228()
+ fun_l21_n268
+end
+
+def fun_l20_n229()
+ fun_l21_n161
+end
+
+def fun_l20_n230()
+ fun_l21_n383
+end
+
+def fun_l20_n231()
+ fun_l21_n100
+end
+
+def fun_l20_n232()
+ fun_l21_n285
+end
+
+def fun_l20_n233()
+ fun_l21_n255
+end
+
+def fun_l20_n234()
+ fun_l21_n214
+end
+
+def fun_l20_n235()
+ fun_l21_n206
+end
+
+def fun_l20_n236()
+ fun_l21_n990
+end
+
+def fun_l20_n237()
+ fun_l21_n24
+end
+
+def fun_l20_n238()
+ fun_l21_n531
+end
+
+def fun_l20_n239()
+ fun_l21_n171
+end
+
+def fun_l20_n240()
+ fun_l21_n859
+end
+
+def fun_l20_n241()
+ fun_l21_n342
+end
+
+def fun_l20_n242()
+ fun_l21_n724
+end
+
+def fun_l20_n243()
+ fun_l21_n55
+end
+
+def fun_l20_n244()
+ fun_l21_n404
+end
+
+def fun_l20_n245()
+ fun_l21_n615
+end
+
+def fun_l20_n246()
+ fun_l21_n692
+end
+
+def fun_l20_n247()
+ fun_l21_n851
+end
+
+def fun_l20_n248()
+ fun_l21_n715
+end
+
+def fun_l20_n249()
+ fun_l21_n723
+end
+
+def fun_l20_n250()
+ fun_l21_n929
+end
+
+def fun_l20_n251()
+ fun_l21_n26
+end
+
+def fun_l20_n252()
+ fun_l21_n314
+end
+
+def fun_l20_n253()
+ fun_l21_n182
+end
+
+def fun_l20_n254()
+ fun_l21_n889
+end
+
+def fun_l20_n255()
+ fun_l21_n725
+end
+
+def fun_l20_n256()
+ fun_l21_n538
+end
+
+def fun_l20_n257()
+ fun_l21_n303
+end
+
+def fun_l20_n258()
+ fun_l21_n843
+end
+
+def fun_l20_n259()
+ fun_l21_n977
+end
+
+def fun_l20_n260()
+ fun_l21_n438
+end
+
+def fun_l20_n261()
+ fun_l21_n772
+end
+
+def fun_l20_n262()
+ fun_l21_n432
+end
+
+def fun_l20_n263()
+ fun_l21_n204
+end
+
+def fun_l20_n264()
+ fun_l21_n853
+end
+
+def fun_l20_n265()
+ fun_l21_n7
+end
+
+def fun_l20_n266()
+ fun_l21_n171
+end
+
+def fun_l20_n267()
+ fun_l21_n907
+end
+
+def fun_l20_n268()
+ fun_l21_n450
+end
+
+def fun_l20_n269()
+ fun_l21_n836
+end
+
+def fun_l20_n270()
+ fun_l21_n118
+end
+
+def fun_l20_n271()
+ fun_l21_n782
+end
+
+def fun_l20_n272()
+ fun_l21_n160
+end
+
+def fun_l20_n273()
+ fun_l21_n73
+end
+
+def fun_l20_n274()
+ fun_l21_n339
+end
+
+def fun_l20_n275()
+ fun_l21_n257
+end
+
+def fun_l20_n276()
+ fun_l21_n860
+end
+
+def fun_l20_n277()
+ fun_l21_n837
+end
+
+def fun_l20_n278()
+ fun_l21_n936
+end
+
+def fun_l20_n279()
+ fun_l21_n627
+end
+
+def fun_l20_n280()
+ fun_l21_n45
+end
+
+def fun_l20_n281()
+ fun_l21_n934
+end
+
+def fun_l20_n282()
+ fun_l21_n213
+end
+
+def fun_l20_n283()
+ fun_l21_n629
+end
+
+def fun_l20_n284()
+ fun_l21_n944
+end
+
+def fun_l20_n285()
+ fun_l21_n44
+end
+
+def fun_l20_n286()
+ fun_l21_n306
+end
+
+def fun_l20_n287()
+ fun_l21_n259
+end
+
+def fun_l20_n288()
+ fun_l21_n805
+end
+
+def fun_l20_n289()
+ fun_l21_n118
+end
+
+def fun_l20_n290()
+ fun_l21_n456
+end
+
+def fun_l20_n291()
+ fun_l21_n11
+end
+
+def fun_l20_n292()
+ fun_l21_n138
+end
+
+def fun_l20_n293()
+ fun_l21_n110
+end
+
+def fun_l20_n294()
+ fun_l21_n165
+end
+
+def fun_l20_n295()
+ fun_l21_n129
+end
+
+def fun_l20_n296()
+ fun_l21_n731
+end
+
+def fun_l20_n297()
+ fun_l21_n219
+end
+
+def fun_l20_n298()
+ fun_l21_n175
+end
+
+def fun_l20_n299()
+ fun_l21_n497
+end
+
+def fun_l20_n300()
+ fun_l21_n154
+end
+
+def fun_l20_n301()
+ fun_l21_n446
+end
+
+def fun_l20_n302()
+ fun_l21_n890
+end
+
+def fun_l20_n303()
+ fun_l21_n325
+end
+
+def fun_l20_n304()
+ fun_l21_n616
+end
+
+def fun_l20_n305()
+ fun_l21_n743
+end
+
+def fun_l20_n306()
+ fun_l21_n327
+end
+
+def fun_l20_n307()
+ fun_l21_n890
+end
+
+def fun_l20_n308()
+ fun_l21_n289
+end
+
+def fun_l20_n309()
+ fun_l21_n150
+end
+
+def fun_l20_n310()
+ fun_l21_n22
+end
+
+def fun_l20_n311()
+ fun_l21_n290
+end
+
+def fun_l20_n312()
+ fun_l21_n780
+end
+
+def fun_l20_n313()
+ fun_l21_n204
+end
+
+def fun_l20_n314()
+ fun_l21_n204
+end
+
+def fun_l20_n315()
+ fun_l21_n841
+end
+
+def fun_l20_n316()
+ fun_l21_n990
+end
+
+def fun_l20_n317()
+ fun_l21_n574
+end
+
+def fun_l20_n318()
+ fun_l21_n543
+end
+
+def fun_l20_n319()
+ fun_l21_n388
+end
+
+def fun_l20_n320()
+ fun_l21_n44
+end
+
+def fun_l20_n321()
+ fun_l21_n65
+end
+
+def fun_l20_n322()
+ fun_l21_n952
+end
+
+def fun_l20_n323()
+ fun_l21_n633
+end
+
+def fun_l20_n324()
+ fun_l21_n729
+end
+
+def fun_l20_n325()
+ fun_l21_n356
+end
+
+def fun_l20_n326()
+ fun_l21_n968
+end
+
+def fun_l20_n327()
+ fun_l21_n92
+end
+
+def fun_l20_n328()
+ fun_l21_n285
+end
+
+def fun_l20_n329()
+ fun_l21_n341
+end
+
+def fun_l20_n330()
+ fun_l21_n818
+end
+
+def fun_l20_n331()
+ fun_l21_n373
+end
+
+def fun_l20_n332()
+ fun_l21_n166
+end
+
+def fun_l20_n333()
+ fun_l21_n618
+end
+
+def fun_l20_n334()
+ fun_l21_n160
+end
+
+def fun_l20_n335()
+ fun_l21_n965
+end
+
+def fun_l20_n336()
+ fun_l21_n436
+end
+
+def fun_l20_n337()
+ fun_l21_n244
+end
+
+def fun_l20_n338()
+ fun_l21_n425
+end
+
+def fun_l20_n339()
+ fun_l21_n576
+end
+
+def fun_l20_n340()
+ fun_l21_n789
+end
+
+def fun_l20_n341()
+ fun_l21_n559
+end
+
+def fun_l20_n342()
+ fun_l21_n766
+end
+
+def fun_l20_n343()
+ fun_l21_n131
+end
+
+def fun_l20_n344()
+ fun_l21_n806
+end
+
+def fun_l20_n345()
+ fun_l21_n624
+end
+
+def fun_l20_n346()
+ fun_l21_n342
+end
+
+def fun_l20_n347()
+ fun_l21_n567
+end
+
+def fun_l20_n348()
+ fun_l21_n569
+end
+
+def fun_l20_n349()
+ fun_l21_n623
+end
+
+def fun_l20_n350()
+ fun_l21_n984
+end
+
+def fun_l20_n351()
+ fun_l21_n931
+end
+
+def fun_l20_n352()
+ fun_l21_n48
+end
+
+def fun_l20_n353()
+ fun_l21_n962
+end
+
+def fun_l20_n354()
+ fun_l21_n757
+end
+
+def fun_l20_n355()
+ fun_l21_n844
+end
+
+def fun_l20_n356()
+ fun_l21_n217
+end
+
+def fun_l20_n357()
+ fun_l21_n933
+end
+
+def fun_l20_n358()
+ fun_l21_n579
+end
+
+def fun_l20_n359()
+ fun_l21_n342
+end
+
+def fun_l20_n360()
+ fun_l21_n975
+end
+
+def fun_l20_n361()
+ fun_l21_n177
+end
+
+def fun_l20_n362()
+ fun_l21_n491
+end
+
+def fun_l20_n363()
+ fun_l21_n637
+end
+
+def fun_l20_n364()
+ fun_l21_n505
+end
+
+def fun_l20_n365()
+ fun_l21_n784
+end
+
+def fun_l20_n366()
+ fun_l21_n62
+end
+
+def fun_l20_n367()
+ fun_l21_n478
+end
+
+def fun_l20_n368()
+ fun_l21_n369
+end
+
+def fun_l20_n369()
+ fun_l21_n105
+end
+
+def fun_l20_n370()
+ fun_l21_n352
+end
+
+def fun_l20_n371()
+ fun_l21_n537
+end
+
+def fun_l20_n372()
+ fun_l21_n180
+end
+
+def fun_l20_n373()
+ fun_l21_n216
+end
+
+def fun_l20_n374()
+ fun_l21_n938
+end
+
+def fun_l20_n375()
+ fun_l21_n441
+end
+
+def fun_l20_n376()
+ fun_l21_n308
+end
+
+def fun_l20_n377()
+ fun_l21_n544
+end
+
+def fun_l20_n378()
+ fun_l21_n505
+end
+
+def fun_l20_n379()
+ fun_l21_n681
+end
+
+def fun_l20_n380()
+ fun_l21_n844
+end
+
+def fun_l20_n381()
+ fun_l21_n269
+end
+
+def fun_l20_n382()
+ fun_l21_n195
+end
+
+def fun_l20_n383()
+ fun_l21_n214
+end
+
+def fun_l20_n384()
+ fun_l21_n206
+end
+
+def fun_l20_n385()
+ fun_l21_n807
+end
+
+def fun_l20_n386()
+ fun_l21_n932
+end
+
+def fun_l20_n387()
+ fun_l21_n245
+end
+
+def fun_l20_n388()
+ fun_l21_n942
+end
+
+def fun_l20_n389()
+ fun_l21_n618
+end
+
+def fun_l20_n390()
+ fun_l21_n684
+end
+
+def fun_l20_n391()
+ fun_l21_n536
+end
+
+def fun_l20_n392()
+ fun_l21_n899
+end
+
+def fun_l20_n393()
+ fun_l21_n775
+end
+
+def fun_l20_n394()
+ fun_l21_n634
+end
+
+def fun_l20_n395()
+ fun_l21_n870
+end
+
+def fun_l20_n396()
+ fun_l21_n882
+end
+
+def fun_l20_n397()
+ fun_l21_n317
+end
+
+def fun_l20_n398()
+ fun_l21_n162
+end
+
+def fun_l20_n399()
+ fun_l21_n446
+end
+
+def fun_l20_n400()
+ fun_l21_n716
+end
+
+def fun_l20_n401()
+ fun_l21_n869
+end
+
+def fun_l20_n402()
+ fun_l21_n965
+end
+
+def fun_l20_n403()
+ fun_l21_n616
+end
+
+def fun_l20_n404()
+ fun_l21_n385
+end
+
+def fun_l20_n405()
+ fun_l21_n964
+end
+
+def fun_l20_n406()
+ fun_l21_n360
+end
+
+def fun_l20_n407()
+ fun_l21_n432
+end
+
+def fun_l20_n408()
+ fun_l21_n40
+end
+
+def fun_l20_n409()
+ fun_l21_n734
+end
+
+def fun_l20_n410()
+ fun_l21_n978
+end
+
+def fun_l20_n411()
+ fun_l21_n721
+end
+
+def fun_l20_n412()
+ fun_l21_n941
+end
+
+def fun_l20_n413()
+ fun_l21_n315
+end
+
+def fun_l20_n414()
+ fun_l21_n242
+end
+
+def fun_l20_n415()
+ fun_l21_n153
+end
+
+def fun_l20_n416()
+ fun_l21_n999
+end
+
+def fun_l20_n417()
+ fun_l21_n219
+end
+
+def fun_l20_n418()
+ fun_l21_n809
+end
+
+def fun_l20_n419()
+ fun_l21_n139
+end
+
+def fun_l20_n420()
+ fun_l21_n311
+end
+
+def fun_l20_n421()
+ fun_l21_n460
+end
+
+def fun_l20_n422()
+ fun_l21_n0
+end
+
+def fun_l20_n423()
+ fun_l21_n863
+end
+
+def fun_l20_n424()
+ fun_l21_n216
+end
+
+def fun_l20_n425()
+ fun_l21_n1
+end
+
+def fun_l20_n426()
+ fun_l21_n829
+end
+
+def fun_l20_n427()
+ fun_l21_n844
+end
+
+def fun_l20_n428()
+ fun_l21_n941
+end
+
+def fun_l20_n429()
+ fun_l21_n344
+end
+
+def fun_l20_n430()
+ fun_l21_n443
+end
+
+def fun_l20_n431()
+ fun_l21_n549
+end
+
+def fun_l20_n432()
+ fun_l21_n654
+end
+
+def fun_l20_n433()
+ fun_l21_n167
+end
+
+def fun_l20_n434()
+ fun_l21_n392
+end
+
+def fun_l20_n435()
+ fun_l21_n570
+end
+
+def fun_l20_n436()
+ fun_l21_n370
+end
+
+def fun_l20_n437()
+ fun_l21_n65
+end
+
+def fun_l20_n438()
+ fun_l21_n78
+end
+
+def fun_l20_n439()
+ fun_l21_n271
+end
+
+def fun_l20_n440()
+ fun_l21_n606
+end
+
+def fun_l20_n441()
+ fun_l21_n25
+end
+
+def fun_l20_n442()
+ fun_l21_n629
+end
+
+def fun_l20_n443()
+ fun_l21_n294
+end
+
+def fun_l20_n444()
+ fun_l21_n928
+end
+
+def fun_l20_n445()
+ fun_l21_n596
+end
+
+def fun_l20_n446()
+ fun_l21_n630
+end
+
+def fun_l20_n447()
+ fun_l21_n849
+end
+
+def fun_l20_n448()
+ fun_l21_n239
+end
+
+def fun_l20_n449()
+ fun_l21_n641
+end
+
+def fun_l20_n450()
+ fun_l21_n333
+end
+
+def fun_l20_n451()
+ fun_l21_n86
+end
+
+def fun_l20_n452()
+ fun_l21_n68
+end
+
+def fun_l20_n453()
+ fun_l21_n28
+end
+
+def fun_l20_n454()
+ fun_l21_n644
+end
+
+def fun_l20_n455()
+ fun_l21_n282
+end
+
+def fun_l20_n456()
+ fun_l21_n3
+end
+
+def fun_l20_n457()
+ fun_l21_n594
+end
+
+def fun_l20_n458()
+ fun_l21_n173
+end
+
+def fun_l20_n459()
+ fun_l21_n986
+end
+
+def fun_l20_n460()
+ fun_l21_n597
+end
+
+def fun_l20_n461()
+ fun_l21_n488
+end
+
+def fun_l20_n462()
+ fun_l21_n288
+end
+
+def fun_l20_n463()
+ fun_l21_n729
+end
+
+def fun_l20_n464()
+ fun_l21_n985
+end
+
+def fun_l20_n465()
+ fun_l21_n794
+end
+
+def fun_l20_n466()
+ fun_l21_n405
+end
+
+def fun_l20_n467()
+ fun_l21_n985
+end
+
+def fun_l20_n468()
+ fun_l21_n596
+end
+
+def fun_l20_n469()
+ fun_l21_n331
+end
+
+def fun_l20_n470()
+ fun_l21_n480
+end
+
+def fun_l20_n471()
+ fun_l21_n160
+end
+
+def fun_l20_n472()
+ fun_l21_n529
+end
+
+def fun_l20_n473()
+ fun_l21_n185
+end
+
+def fun_l20_n474()
+ fun_l21_n300
+end
+
+def fun_l20_n475()
+ fun_l21_n131
+end
+
+def fun_l20_n476()
+ fun_l21_n561
+end
+
+def fun_l20_n477()
+ fun_l21_n634
+end
+
+def fun_l20_n478()
+ fun_l21_n92
+end
+
+def fun_l20_n479()
+ fun_l21_n105
+end
+
+def fun_l20_n480()
+ fun_l21_n887
+end
+
+def fun_l20_n481()
+ fun_l21_n841
+end
+
+def fun_l20_n482()
+ fun_l21_n404
+end
+
+def fun_l20_n483()
+ fun_l21_n813
+end
+
+def fun_l20_n484()
+ fun_l21_n90
+end
+
+def fun_l20_n485()
+ fun_l21_n978
+end
+
+def fun_l20_n486()
+ fun_l21_n342
+end
+
+def fun_l20_n487()
+ fun_l21_n263
+end
+
+def fun_l20_n488()
+ fun_l21_n587
+end
+
+def fun_l20_n489()
+ fun_l21_n950
+end
+
+def fun_l20_n490()
+ fun_l21_n121
+end
+
+def fun_l20_n491()
+ fun_l21_n85
+end
+
+def fun_l20_n492()
+ fun_l21_n53
+end
+
+def fun_l20_n493()
+ fun_l21_n706
+end
+
+def fun_l20_n494()
+ fun_l21_n612
+end
+
+def fun_l20_n495()
+ fun_l21_n322
+end
+
+def fun_l20_n496()
+ fun_l21_n610
+end
+
+def fun_l20_n497()
+ fun_l21_n465
+end
+
+def fun_l20_n498()
+ fun_l21_n998
+end
+
+def fun_l20_n499()
+ fun_l21_n79
+end
+
+def fun_l20_n500()
+ fun_l21_n203
+end
+
+def fun_l20_n501()
+ fun_l21_n99
+end
+
+def fun_l20_n502()
+ fun_l21_n958
+end
+
+def fun_l20_n503()
+ fun_l21_n528
+end
+
+def fun_l20_n504()
+ fun_l21_n210
+end
+
+def fun_l20_n505()
+ fun_l21_n546
+end
+
+def fun_l20_n506()
+ fun_l21_n343
+end
+
+def fun_l20_n507()
+ fun_l21_n9
+end
+
+def fun_l20_n508()
+ fun_l21_n486
+end
+
+def fun_l20_n509()
+ fun_l21_n252
+end
+
+def fun_l20_n510()
+ fun_l21_n489
+end
+
+def fun_l20_n511()
+ fun_l21_n851
+end
+
+def fun_l20_n512()
+ fun_l21_n150
+end
+
+def fun_l20_n513()
+ fun_l21_n691
+end
+
+def fun_l20_n514()
+ fun_l21_n718
+end
+
+def fun_l20_n515()
+ fun_l21_n681
+end
+
+def fun_l20_n516()
+ fun_l21_n636
+end
+
+def fun_l20_n517()
+ fun_l21_n828
+end
+
+def fun_l20_n518()
+ fun_l21_n15
+end
+
+def fun_l20_n519()
+ fun_l21_n186
+end
+
+def fun_l20_n520()
+ fun_l21_n260
+end
+
+def fun_l20_n521()
+ fun_l21_n646
+end
+
+def fun_l20_n522()
+ fun_l21_n768
+end
+
+def fun_l20_n523()
+ fun_l21_n387
+end
+
+def fun_l20_n524()
+ fun_l21_n597
+end
+
+def fun_l20_n525()
+ fun_l21_n980
+end
+
+def fun_l20_n526()
+ fun_l21_n996
+end
+
+def fun_l20_n527()
+ fun_l21_n945
+end
+
+def fun_l20_n528()
+ fun_l21_n234
+end
+
+def fun_l20_n529()
+ fun_l21_n673
+end
+
+def fun_l20_n530()
+ fun_l21_n766
+end
+
+def fun_l20_n531()
+ fun_l21_n498
+end
+
+def fun_l20_n532()
+ fun_l21_n210
+end
+
+def fun_l20_n533()
+ fun_l21_n537
+end
+
+def fun_l20_n534()
+ fun_l21_n376
+end
+
+def fun_l20_n535()
+ fun_l21_n13
+end
+
+def fun_l20_n536()
+ fun_l21_n994
+end
+
+def fun_l20_n537()
+ fun_l21_n954
+end
+
+def fun_l20_n538()
+ fun_l21_n171
+end
+
+def fun_l20_n539()
+ fun_l21_n778
+end
+
+def fun_l20_n540()
+ fun_l21_n940
+end
+
+def fun_l20_n541()
+ fun_l21_n114
+end
+
+def fun_l20_n542()
+ fun_l21_n987
+end
+
+def fun_l20_n543()
+ fun_l21_n553
+end
+
+def fun_l20_n544()
+ fun_l21_n473
+end
+
+def fun_l20_n545()
+ fun_l21_n503
+end
+
+def fun_l20_n546()
+ fun_l21_n436
+end
+
+def fun_l20_n547()
+ fun_l21_n901
+end
+
+def fun_l20_n548()
+ fun_l21_n98
+end
+
+def fun_l20_n549()
+ fun_l21_n389
+end
+
+def fun_l20_n550()
+ fun_l21_n852
+end
+
+def fun_l20_n551()
+ fun_l21_n193
+end
+
+def fun_l20_n552()
+ fun_l21_n783
+end
+
+def fun_l20_n553()
+ fun_l21_n46
+end
+
+def fun_l20_n554()
+ fun_l21_n38
+end
+
+def fun_l20_n555()
+ fun_l21_n300
+end
+
+def fun_l20_n556()
+ fun_l21_n221
+end
+
+def fun_l20_n557()
+ fun_l21_n816
+end
+
+def fun_l20_n558()
+ fun_l21_n534
+end
+
+def fun_l20_n559()
+ fun_l21_n932
+end
+
+def fun_l20_n560()
+ fun_l21_n880
+end
+
+def fun_l20_n561()
+ fun_l21_n796
+end
+
+def fun_l20_n562()
+ fun_l21_n927
+end
+
+def fun_l20_n563()
+ fun_l21_n10
+end
+
+def fun_l20_n564()
+ fun_l21_n843
+end
+
+def fun_l20_n565()
+ fun_l21_n625
+end
+
+def fun_l20_n566()
+ fun_l21_n429
+end
+
+def fun_l20_n567()
+ fun_l21_n475
+end
+
+def fun_l20_n568()
+ fun_l21_n931
+end
+
+def fun_l20_n569()
+ fun_l21_n460
+end
+
+def fun_l20_n570()
+ fun_l21_n857
+end
+
+def fun_l20_n571()
+ fun_l21_n607
+end
+
+def fun_l20_n572()
+ fun_l21_n727
+end
+
+def fun_l20_n573()
+ fun_l21_n922
+end
+
+def fun_l20_n574()
+ fun_l21_n393
+end
+
+def fun_l20_n575()
+ fun_l21_n232
+end
+
+def fun_l20_n576()
+ fun_l21_n665
+end
+
+def fun_l20_n577()
+ fun_l21_n796
+end
+
+def fun_l20_n578()
+ fun_l21_n80
+end
+
+def fun_l20_n579()
+ fun_l21_n769
+end
+
+def fun_l20_n580()
+ fun_l21_n558
+end
+
+def fun_l20_n581()
+ fun_l21_n630
+end
+
+def fun_l20_n582()
+ fun_l21_n911
+end
+
+def fun_l20_n583()
+ fun_l21_n457
+end
+
+def fun_l20_n584()
+ fun_l21_n61
+end
+
+def fun_l20_n585()
+ fun_l21_n671
+end
+
+def fun_l20_n586()
+ fun_l21_n493
+end
+
+def fun_l20_n587()
+ fun_l21_n780
+end
+
+def fun_l20_n588()
+ fun_l21_n373
+end
+
+def fun_l20_n589()
+ fun_l21_n138
+end
+
+def fun_l20_n590()
+ fun_l21_n377
+end
+
+def fun_l20_n591()
+ fun_l21_n793
+end
+
+def fun_l20_n592()
+ fun_l21_n995
+end
+
+def fun_l20_n593()
+ fun_l21_n46
+end
+
+def fun_l20_n594()
+ fun_l21_n171
+end
+
+def fun_l20_n595()
+ fun_l21_n907
+end
+
+def fun_l20_n596()
+ fun_l21_n182
+end
+
+def fun_l20_n597()
+ fun_l21_n203
+end
+
+def fun_l20_n598()
+ fun_l21_n475
+end
+
+def fun_l20_n599()
+ fun_l21_n198
+end
+
+def fun_l20_n600()
+ fun_l21_n654
+end
+
+def fun_l20_n601()
+ fun_l21_n236
+end
+
+def fun_l20_n602()
+ fun_l21_n854
+end
+
+def fun_l20_n603()
+ fun_l21_n344
+end
+
+def fun_l20_n604()
+ fun_l21_n575
+end
+
+def fun_l20_n605()
+ fun_l21_n214
+end
+
+def fun_l20_n606()
+ fun_l21_n105
+end
+
+def fun_l20_n607()
+ fun_l21_n624
+end
+
+def fun_l20_n608()
+ fun_l21_n505
+end
+
+def fun_l20_n609()
+ fun_l21_n468
+end
+
+def fun_l20_n610()
+ fun_l21_n946
+end
+
+def fun_l20_n611()
+ fun_l21_n197
+end
+
+def fun_l20_n612()
+ fun_l21_n749
+end
+
+def fun_l20_n613()
+ fun_l21_n280
+end
+
+def fun_l20_n614()
+ fun_l21_n587
+end
+
+def fun_l20_n615()
+ fun_l21_n463
+end
+
+def fun_l20_n616()
+ fun_l21_n47
+end
+
+def fun_l20_n617()
+ fun_l21_n467
+end
+
+def fun_l20_n618()
+ fun_l21_n934
+end
+
+def fun_l20_n619()
+ fun_l21_n648
+end
+
+def fun_l20_n620()
+ fun_l21_n572
+end
+
+def fun_l20_n621()
+ fun_l21_n524
+end
+
+def fun_l20_n622()
+ fun_l21_n623
+end
+
+def fun_l20_n623()
+ fun_l21_n142
+end
+
+def fun_l20_n624()
+ fun_l21_n370
+end
+
+def fun_l20_n625()
+ fun_l21_n427
+end
+
+def fun_l20_n626()
+ fun_l21_n23
+end
+
+def fun_l20_n627()
+ fun_l21_n710
+end
+
+def fun_l20_n628()
+ fun_l21_n714
+end
+
+def fun_l20_n629()
+ fun_l21_n929
+end
+
+def fun_l20_n630()
+ fun_l21_n882
+end
+
+def fun_l20_n631()
+ fun_l21_n971
+end
+
+def fun_l20_n632()
+ fun_l21_n484
+end
+
+def fun_l20_n633()
+ fun_l21_n757
+end
+
+def fun_l20_n634()
+ fun_l21_n543
+end
+
+def fun_l20_n635()
+ fun_l21_n96
+end
+
+def fun_l20_n636()
+ fun_l21_n780
+end
+
+def fun_l20_n637()
+ fun_l21_n912
+end
+
+def fun_l20_n638()
+ fun_l21_n288
+end
+
+def fun_l20_n639()
+ fun_l21_n580
+end
+
+def fun_l20_n640()
+ fun_l21_n831
+end
+
+def fun_l20_n641()
+ fun_l21_n660
+end
+
+def fun_l20_n642()
+ fun_l21_n216
+end
+
+def fun_l20_n643()
+ fun_l21_n341
+end
+
+def fun_l20_n644()
+ fun_l21_n747
+end
+
+def fun_l20_n645()
+ fun_l21_n633
+end
+
+def fun_l20_n646()
+ fun_l21_n422
+end
+
+def fun_l20_n647()
+ fun_l21_n122
+end
+
+def fun_l20_n648()
+ fun_l21_n721
+end
+
+def fun_l20_n649()
+ fun_l21_n439
+end
+
+def fun_l20_n650()
+ fun_l21_n663
+end
+
+def fun_l20_n651()
+ fun_l21_n409
+end
+
+def fun_l20_n652()
+ fun_l21_n475
+end
+
+def fun_l20_n653()
+ fun_l21_n812
+end
+
+def fun_l20_n654()
+ fun_l21_n849
+end
+
+def fun_l20_n655()
+ fun_l21_n500
+end
+
+def fun_l20_n656()
+ fun_l21_n120
+end
+
+def fun_l20_n657()
+ fun_l21_n971
+end
+
+def fun_l20_n658()
+ fun_l21_n935
+end
+
+def fun_l20_n659()
+ fun_l21_n952
+end
+
+def fun_l20_n660()
+ fun_l21_n84
+end
+
+def fun_l20_n661()
+ fun_l21_n393
+end
+
+def fun_l20_n662()
+ fun_l21_n454
+end
+
+def fun_l20_n663()
+ fun_l21_n440
+end
+
+def fun_l20_n664()
+ fun_l21_n5
+end
+
+def fun_l20_n665()
+ fun_l21_n475
+end
+
+def fun_l20_n666()
+ fun_l21_n929
+end
+
+def fun_l20_n667()
+ fun_l21_n164
+end
+
+def fun_l20_n668()
+ fun_l21_n23
+end
+
+def fun_l20_n669()
+ fun_l21_n66
+end
+
+def fun_l20_n670()
+ fun_l21_n463
+end
+
+def fun_l20_n671()
+ fun_l21_n425
+end
+
+def fun_l20_n672()
+ fun_l21_n414
+end
+
+def fun_l20_n673()
+ fun_l21_n990
+end
+
+def fun_l20_n674()
+ fun_l21_n504
+end
+
+def fun_l20_n675()
+ fun_l21_n974
+end
+
+def fun_l20_n676()
+ fun_l21_n620
+end
+
+def fun_l20_n677()
+ fun_l21_n798
+end
+
+def fun_l20_n678()
+ fun_l21_n432
+end
+
+def fun_l20_n679()
+ fun_l21_n487
+end
+
+def fun_l20_n680()
+ fun_l21_n570
+end
+
+def fun_l20_n681()
+ fun_l21_n746
+end
+
+def fun_l20_n682()
+ fun_l21_n358
+end
+
+def fun_l20_n683()
+ fun_l21_n207
+end
+
+def fun_l20_n684()
+ fun_l21_n408
+end
+
+def fun_l20_n685()
+ fun_l21_n679
+end
+
+def fun_l20_n686()
+ fun_l21_n38
+end
+
+def fun_l20_n687()
+ fun_l21_n58
+end
+
+def fun_l20_n688()
+ fun_l21_n460
+end
+
+def fun_l20_n689()
+ fun_l21_n855
+end
+
+def fun_l20_n690()
+ fun_l21_n641
+end
+
+def fun_l20_n691()
+ fun_l21_n146
+end
+
+def fun_l20_n692()
+ fun_l21_n709
+end
+
+def fun_l20_n693()
+ fun_l21_n801
+end
+
+def fun_l20_n694()
+ fun_l21_n375
+end
+
+def fun_l20_n695()
+ fun_l21_n778
+end
+
+def fun_l20_n696()
+ fun_l21_n620
+end
+
+def fun_l20_n697()
+ fun_l21_n630
+end
+
+def fun_l20_n698()
+ fun_l21_n582
+end
+
+def fun_l20_n699()
+ fun_l21_n198
+end
+
+def fun_l20_n700()
+ fun_l21_n830
+end
+
+def fun_l20_n701()
+ fun_l21_n101
+end
+
+def fun_l20_n702()
+ fun_l21_n824
+end
+
+def fun_l20_n703()
+ fun_l21_n97
+end
+
+def fun_l20_n704()
+ fun_l21_n628
+end
+
+def fun_l20_n705()
+ fun_l21_n688
+end
+
+def fun_l20_n706()
+ fun_l21_n120
+end
+
+def fun_l20_n707()
+ fun_l21_n343
+end
+
+def fun_l20_n708()
+ fun_l21_n175
+end
+
+def fun_l20_n709()
+ fun_l21_n122
+end
+
+def fun_l20_n710()
+ fun_l21_n272
+end
+
+def fun_l20_n711()
+ fun_l21_n343
+end
+
+def fun_l20_n712()
+ fun_l21_n317
+end
+
+def fun_l20_n713()
+ fun_l21_n982
+end
+
+def fun_l20_n714()
+ fun_l21_n458
+end
+
+def fun_l20_n715()
+ fun_l21_n906
+end
+
+def fun_l20_n716()
+ fun_l21_n565
+end
+
+def fun_l20_n717()
+ fun_l21_n174
+end
+
+def fun_l20_n718()
+ fun_l21_n34
+end
+
+def fun_l20_n719()
+ fun_l21_n832
+end
+
+def fun_l20_n720()
+ fun_l21_n111
+end
+
+def fun_l20_n721()
+ fun_l21_n701
+end
+
+def fun_l20_n722()
+ fun_l21_n201
+end
+
+def fun_l20_n723()
+ fun_l21_n285
+end
+
+def fun_l20_n724()
+ fun_l21_n269
+end
+
+def fun_l20_n725()
+ fun_l21_n144
+end
+
+def fun_l20_n726()
+ fun_l21_n246
+end
+
+def fun_l20_n727()
+ fun_l21_n221
+end
+
+def fun_l20_n728()
+ fun_l21_n599
+end
+
+def fun_l20_n729()
+ fun_l21_n909
+end
+
+def fun_l20_n730()
+ fun_l21_n693
+end
+
+def fun_l20_n731()
+ fun_l21_n879
+end
+
+def fun_l20_n732()
+ fun_l21_n452
+end
+
+def fun_l20_n733()
+ fun_l21_n772
+end
+
+def fun_l20_n734()
+ fun_l21_n116
+end
+
+def fun_l20_n735()
+ fun_l21_n895
+end
+
+def fun_l20_n736()
+ fun_l21_n937
+end
+
+def fun_l20_n737()
+ fun_l21_n50
+end
+
+def fun_l20_n738()
+ fun_l21_n947
+end
+
+def fun_l20_n739()
+ fun_l21_n500
+end
+
+def fun_l20_n740()
+ fun_l21_n753
+end
+
+def fun_l20_n741()
+ fun_l21_n497
+end
+
+def fun_l20_n742()
+ fun_l21_n524
+end
+
+def fun_l20_n743()
+ fun_l21_n389
+end
+
+def fun_l20_n744()
+ fun_l21_n539
+end
+
+def fun_l20_n745()
+ fun_l21_n70
+end
+
+def fun_l20_n746()
+ fun_l21_n736
+end
+
+def fun_l20_n747()
+ fun_l21_n94
+end
+
+def fun_l20_n748()
+ fun_l21_n686
+end
+
+def fun_l20_n749()
+ fun_l21_n269
+end
+
+def fun_l20_n750()
+ fun_l21_n809
+end
+
+def fun_l20_n751()
+ fun_l21_n570
+end
+
+def fun_l20_n752()
+ fun_l21_n522
+end
+
+def fun_l20_n753()
+ fun_l21_n167
+end
+
+def fun_l20_n754()
+ fun_l21_n610
+end
+
+def fun_l20_n755()
+ fun_l21_n72
+end
+
+def fun_l20_n756()
+ fun_l21_n146
+end
+
+def fun_l20_n757()
+ fun_l21_n916
+end
+
+def fun_l20_n758()
+ fun_l21_n163
+end
+
+def fun_l20_n759()
+ fun_l21_n279
+end
+
+def fun_l20_n760()
+ fun_l21_n677
+end
+
+def fun_l20_n761()
+ fun_l21_n876
+end
+
+def fun_l20_n762()
+ fun_l21_n333
+end
+
+def fun_l20_n763()
+ fun_l21_n36
+end
+
+def fun_l20_n764()
+ fun_l21_n166
+end
+
+def fun_l20_n765()
+ fun_l21_n824
+end
+
+def fun_l20_n766()
+ fun_l21_n416
+end
+
+def fun_l20_n767()
+ fun_l21_n655
+end
+
+def fun_l20_n768()
+ fun_l21_n267
+end
+
+def fun_l20_n769()
+ fun_l21_n257
+end
+
+def fun_l20_n770()
+ fun_l21_n839
+end
+
+def fun_l20_n771()
+ fun_l21_n504
+end
+
+def fun_l20_n772()
+ fun_l21_n717
+end
+
+def fun_l20_n773()
+ fun_l21_n332
+end
+
+def fun_l20_n774()
+ fun_l21_n949
+end
+
+def fun_l20_n775()
+ fun_l21_n226
+end
+
+def fun_l20_n776()
+ fun_l21_n145
+end
+
+def fun_l20_n777()
+ fun_l21_n548
+end
+
+def fun_l20_n778()
+ fun_l21_n912
+end
+
+def fun_l20_n779()
+ fun_l21_n984
+end
+
+def fun_l20_n780()
+ fun_l21_n907
+end
+
+def fun_l20_n781()
+ fun_l21_n433
+end
+
+def fun_l20_n782()
+ fun_l21_n542
+end
+
+def fun_l20_n783()
+ fun_l21_n88
+end
+
+def fun_l20_n784()
+ fun_l21_n104
+end
+
+def fun_l20_n785()
+ fun_l21_n383
+end
+
+def fun_l20_n786()
+ fun_l21_n998
+end
+
+def fun_l20_n787()
+ fun_l21_n525
+end
+
+def fun_l20_n788()
+ fun_l21_n276
+end
+
+def fun_l20_n789()
+ fun_l21_n162
+end
+
+def fun_l20_n790()
+ fun_l21_n420
+end
+
+def fun_l20_n791()
+ fun_l21_n793
+end
+
+def fun_l20_n792()
+ fun_l21_n121
+end
+
+def fun_l20_n793()
+ fun_l21_n164
+end
+
+def fun_l20_n794()
+ fun_l21_n110
+end
+
+def fun_l20_n795()
+ fun_l21_n68
+end
+
+def fun_l20_n796()
+ fun_l21_n417
+end
+
+def fun_l20_n797()
+ fun_l21_n878
+end
+
+def fun_l20_n798()
+ fun_l21_n987
+end
+
+def fun_l20_n799()
+ fun_l21_n197
+end
+
+def fun_l20_n800()
+ fun_l21_n729
+end
+
+def fun_l20_n801()
+ fun_l21_n956
+end
+
+def fun_l20_n802()
+ fun_l21_n33
+end
+
+def fun_l20_n803()
+ fun_l21_n73
+end
+
+def fun_l20_n804()
+ fun_l21_n759
+end
+
+def fun_l20_n805()
+ fun_l21_n784
+end
+
+def fun_l20_n806()
+ fun_l21_n102
+end
+
+def fun_l20_n807()
+ fun_l21_n624
+end
+
+def fun_l20_n808()
+ fun_l21_n580
+end
+
+def fun_l20_n809()
+ fun_l21_n347
+end
+
+def fun_l20_n810()
+ fun_l21_n163
+end
+
+def fun_l20_n811()
+ fun_l21_n220
+end
+
+def fun_l20_n812()
+ fun_l21_n324
+end
+
+def fun_l20_n813()
+ fun_l21_n299
+end
+
+def fun_l20_n814()
+ fun_l21_n958
+end
+
+def fun_l20_n815()
+ fun_l21_n252
+end
+
+def fun_l20_n816()
+ fun_l21_n479
+end
+
+def fun_l20_n817()
+ fun_l21_n536
+end
+
+def fun_l20_n818()
+ fun_l21_n624
+end
+
+def fun_l20_n819()
+ fun_l21_n347
+end
+
+def fun_l20_n820()
+ fun_l21_n308
+end
+
+def fun_l20_n821()
+ fun_l21_n4
+end
+
+def fun_l20_n822()
+ fun_l21_n88
+end
+
+def fun_l20_n823()
+ fun_l21_n787
+end
+
+def fun_l20_n824()
+ fun_l21_n450
+end
+
+def fun_l20_n825()
+ fun_l21_n384
+end
+
+def fun_l20_n826()
+ fun_l21_n416
+end
+
+def fun_l20_n827()
+ fun_l21_n73
+end
+
+def fun_l20_n828()
+ fun_l21_n884
+end
+
+def fun_l20_n829()
+ fun_l21_n51
+end
+
+def fun_l20_n830()
+ fun_l21_n37
+end
+
+def fun_l20_n831()
+ fun_l21_n326
+end
+
+def fun_l20_n832()
+ fun_l21_n120
+end
+
+def fun_l20_n833()
+ fun_l21_n957
+end
+
+def fun_l20_n834()
+ fun_l21_n973
+end
+
+def fun_l20_n835()
+ fun_l21_n966
+end
+
+def fun_l20_n836()
+ fun_l21_n110
+end
+
+def fun_l20_n837()
+ fun_l21_n57
+end
+
+def fun_l20_n838()
+ fun_l21_n836
+end
+
+def fun_l20_n839()
+ fun_l21_n701
+end
+
+def fun_l20_n840()
+ fun_l21_n607
+end
+
+def fun_l20_n841()
+ fun_l21_n92
+end
+
+def fun_l20_n842()
+ fun_l21_n304
+end
+
+def fun_l20_n843()
+ fun_l21_n443
+end
+
+def fun_l20_n844()
+ fun_l21_n282
+end
+
+def fun_l20_n845()
+ fun_l21_n301
+end
+
+def fun_l20_n846()
+ fun_l21_n360
+end
+
+def fun_l20_n847()
+ fun_l21_n848
+end
+
+def fun_l20_n848()
+ fun_l21_n796
+end
+
+def fun_l20_n849()
+ fun_l21_n81
+end
+
+def fun_l20_n850()
+ fun_l21_n126
+end
+
+def fun_l20_n851()
+ fun_l21_n951
+end
+
+def fun_l20_n852()
+ fun_l21_n187
+end
+
+def fun_l20_n853()
+ fun_l21_n498
+end
+
+def fun_l20_n854()
+ fun_l21_n885
+end
+
+def fun_l20_n855()
+ fun_l21_n391
+end
+
+def fun_l20_n856()
+ fun_l21_n823
+end
+
+def fun_l20_n857()
+ fun_l21_n516
+end
+
+def fun_l20_n858()
+ fun_l21_n266
+end
+
+def fun_l20_n859()
+ fun_l21_n617
+end
+
+def fun_l20_n860()
+ fun_l21_n440
+end
+
+def fun_l20_n861()
+ fun_l21_n694
+end
+
+def fun_l20_n862()
+ fun_l21_n128
+end
+
+def fun_l20_n863()
+ fun_l21_n340
+end
+
+def fun_l20_n864()
+ fun_l21_n234
+end
+
+def fun_l20_n865()
+ fun_l21_n324
+end
+
+def fun_l20_n866()
+ fun_l21_n233
+end
+
+def fun_l20_n867()
+ fun_l21_n26
+end
+
+def fun_l20_n868()
+ fun_l21_n548
+end
+
+def fun_l20_n869()
+ fun_l21_n563
+end
+
+def fun_l20_n870()
+ fun_l21_n452
+end
+
+def fun_l20_n871()
+ fun_l21_n223
+end
+
+def fun_l20_n872()
+ fun_l21_n147
+end
+
+def fun_l20_n873()
+ fun_l21_n147
+end
+
+def fun_l20_n874()
+ fun_l21_n266
+end
+
+def fun_l20_n875()
+ fun_l21_n335
+end
+
+def fun_l20_n876()
+ fun_l21_n253
+end
+
+def fun_l20_n877()
+ fun_l21_n479
+end
+
+def fun_l20_n878()
+ fun_l21_n34
+end
+
+def fun_l20_n879()
+ fun_l21_n798
+end
+
+def fun_l20_n880()
+ fun_l21_n223
+end
+
+def fun_l20_n881()
+ fun_l21_n343
+end
+
+def fun_l20_n882()
+ fun_l21_n728
+end
+
+def fun_l20_n883()
+ fun_l21_n351
+end
+
+def fun_l20_n884()
+ fun_l21_n997
+end
+
+def fun_l20_n885()
+ fun_l21_n49
+end
+
+def fun_l20_n886()
+ fun_l21_n773
+end
+
+def fun_l20_n887()
+ fun_l21_n93
+end
+
+def fun_l20_n888()
+ fun_l21_n124
+end
+
+def fun_l20_n889()
+ fun_l21_n897
+end
+
+def fun_l20_n890()
+ fun_l21_n692
+end
+
+def fun_l20_n891()
+ fun_l21_n158
+end
+
+def fun_l20_n892()
+ fun_l21_n456
+end
+
+def fun_l20_n893()
+ fun_l21_n49
+end
+
+def fun_l20_n894()
+ fun_l21_n751
+end
+
+def fun_l20_n895()
+ fun_l21_n672
+end
+
+def fun_l20_n896()
+ fun_l21_n726
+end
+
+def fun_l20_n897()
+ fun_l21_n95
+end
+
+def fun_l20_n898()
+ fun_l21_n420
+end
+
+def fun_l20_n899()
+ fun_l21_n77
+end
+
+def fun_l20_n900()
+ fun_l21_n770
+end
+
+def fun_l20_n901()
+ fun_l21_n127
+end
+
+def fun_l20_n902()
+ fun_l21_n566
+end
+
+def fun_l20_n903()
+ fun_l21_n398
+end
+
+def fun_l20_n904()
+ fun_l21_n720
+end
+
+def fun_l20_n905()
+ fun_l21_n350
+end
+
+def fun_l20_n906()
+ fun_l21_n935
+end
+
+def fun_l20_n907()
+ fun_l21_n172
+end
+
+def fun_l20_n908()
+ fun_l21_n988
+end
+
+def fun_l20_n909()
+ fun_l21_n627
+end
+
+def fun_l20_n910()
+ fun_l21_n776
+end
+
+def fun_l20_n911()
+ fun_l21_n34
+end
+
+def fun_l20_n912()
+ fun_l21_n361
+end
+
+def fun_l20_n913()
+ fun_l21_n408
+end
+
+def fun_l20_n914()
+ fun_l21_n941
+end
+
+def fun_l20_n915()
+ fun_l21_n275
+end
+
+def fun_l20_n916()
+ fun_l21_n864
+end
+
+def fun_l20_n917()
+ fun_l21_n839
+end
+
+def fun_l20_n918()
+ fun_l21_n837
+end
+
+def fun_l20_n919()
+ fun_l21_n837
+end
+
+def fun_l20_n920()
+ fun_l21_n627
+end
+
+def fun_l20_n921()
+ fun_l21_n321
+end
+
+def fun_l20_n922()
+ fun_l21_n308
+end
+
+def fun_l20_n923()
+ fun_l21_n475
+end
+
+def fun_l20_n924()
+ fun_l21_n115
+end
+
+def fun_l20_n925()
+ fun_l21_n794
+end
+
+def fun_l20_n926()
+ fun_l21_n376
+end
+
+def fun_l20_n927()
+ fun_l21_n951
+end
+
+def fun_l20_n928()
+ fun_l21_n744
+end
+
+def fun_l20_n929()
+ fun_l21_n621
+end
+
+def fun_l20_n930()
+ fun_l21_n630
+end
+
+def fun_l20_n931()
+ fun_l21_n459
+end
+
+def fun_l20_n932()
+ fun_l21_n41
+end
+
+def fun_l20_n933()
+ fun_l21_n313
+end
+
+def fun_l20_n934()
+ fun_l21_n130
+end
+
+def fun_l20_n935()
+ fun_l21_n605
+end
+
+def fun_l20_n936()
+ fun_l21_n261
+end
+
+def fun_l20_n937()
+ fun_l21_n54
+end
+
+def fun_l20_n938()
+ fun_l21_n319
+end
+
+def fun_l20_n939()
+ fun_l21_n541
+end
+
+def fun_l20_n940()
+ fun_l21_n104
+end
+
+def fun_l20_n941()
+ fun_l21_n339
+end
+
+def fun_l20_n942()
+ fun_l21_n220
+end
+
+def fun_l20_n943()
+ fun_l21_n560
+end
+
+def fun_l20_n944()
+ fun_l21_n931
+end
+
+def fun_l20_n945()
+ fun_l21_n642
+end
+
+def fun_l20_n946()
+ fun_l21_n584
+end
+
+def fun_l20_n947()
+ fun_l21_n324
+end
+
+def fun_l20_n948()
+ fun_l21_n10
+end
+
+def fun_l20_n949()
+ fun_l21_n976
+end
+
+def fun_l20_n950()
+ fun_l21_n65
+end
+
+def fun_l20_n951()
+ fun_l21_n392
+end
+
+def fun_l20_n952()
+ fun_l21_n263
+end
+
+def fun_l20_n953()
+ fun_l21_n228
+end
+
+def fun_l20_n954()
+ fun_l21_n177
+end
+
+def fun_l20_n955()
+ fun_l21_n81
+end
+
+def fun_l20_n956()
+ fun_l21_n141
+end
+
+def fun_l20_n957()
+ fun_l21_n540
+end
+
+def fun_l20_n958()
+ fun_l21_n802
+end
+
+def fun_l20_n959()
+ fun_l21_n28
+end
+
+def fun_l20_n960()
+ fun_l21_n438
+end
+
+def fun_l20_n961()
+ fun_l21_n722
+end
+
+def fun_l20_n962()
+ fun_l21_n707
+end
+
+def fun_l20_n963()
+ fun_l21_n598
+end
+
+def fun_l20_n964()
+ fun_l21_n687
+end
+
+def fun_l20_n965()
+ fun_l21_n258
+end
+
+def fun_l20_n966()
+ fun_l21_n786
+end
+
+def fun_l20_n967()
+ fun_l21_n362
+end
+
+def fun_l20_n968()
+ fun_l21_n41
+end
+
+def fun_l20_n969()
+ fun_l21_n933
+end
+
+def fun_l20_n970()
+ fun_l21_n250
+end
+
+def fun_l20_n971()
+ fun_l21_n760
+end
+
+def fun_l20_n972()
+ fun_l21_n993
+end
+
+def fun_l20_n973()
+ fun_l21_n278
+end
+
+def fun_l20_n974()
+ fun_l21_n477
+end
+
+def fun_l20_n975()
+ fun_l21_n901
+end
+
+def fun_l20_n976()
+ fun_l21_n820
+end
+
+def fun_l20_n977()
+ fun_l21_n739
+end
+
+def fun_l20_n978()
+ fun_l21_n722
+end
+
+def fun_l20_n979()
+ fun_l21_n418
+end
+
+def fun_l20_n980()
+ fun_l21_n207
+end
+
+def fun_l20_n981()
+ fun_l21_n213
+end
+
+def fun_l20_n982()
+ fun_l21_n30
+end
+
+def fun_l20_n983()
+ fun_l21_n667
+end
+
+def fun_l20_n984()
+ fun_l21_n582
+end
+
+def fun_l20_n985()
+ fun_l21_n398
+end
+
+def fun_l20_n986()
+ fun_l21_n376
+end
+
+def fun_l20_n987()
+ fun_l21_n84
+end
+
+def fun_l20_n988()
+ fun_l21_n701
+end
+
+def fun_l20_n989()
+ fun_l21_n100
+end
+
+def fun_l20_n990()
+ fun_l21_n247
+end
+
+def fun_l20_n991()
+ fun_l21_n992
+end
+
+def fun_l20_n992()
+ fun_l21_n635
+end
+
+def fun_l20_n993()
+ fun_l21_n493
+end
+
+def fun_l20_n994()
+ fun_l21_n184
+end
+
+def fun_l20_n995()
+ fun_l21_n31
+end
+
+def fun_l20_n996()
+ fun_l21_n555
+end
+
+def fun_l20_n997()
+ fun_l21_n258
+end
+
+def fun_l20_n998()
+ fun_l21_n32
+end
+
+def fun_l20_n999()
+ fun_l21_n6
+end
+
+def fun_l21_n0()
+ fun_l22_n98
+end
+
+def fun_l21_n1()
+ fun_l22_n194
+end
+
+def fun_l21_n2()
+ fun_l22_n510
+end
+
+def fun_l21_n3()
+ fun_l22_n707
+end
+
+def fun_l21_n4()
+ fun_l22_n878
+end
+
+def fun_l21_n5()
+ fun_l22_n615
+end
+
+def fun_l21_n6()
+ fun_l22_n891
+end
+
+def fun_l21_n7()
+ fun_l22_n458
+end
+
+def fun_l21_n8()
+ fun_l22_n478
+end
+
+def fun_l21_n9()
+ fun_l22_n30
+end
+
+def fun_l21_n10()
+ fun_l22_n345
+end
+
+def fun_l21_n11()
+ fun_l22_n202
+end
+
+def fun_l21_n12()
+ fun_l22_n354
+end
+
+def fun_l21_n13()
+ fun_l22_n673
+end
+
+def fun_l21_n14()
+ fun_l22_n662
+end
+
+def fun_l21_n15()
+ fun_l22_n593
+end
+
+def fun_l21_n16()
+ fun_l22_n127
+end
+
+def fun_l21_n17()
+ fun_l22_n876
+end
+
+def fun_l21_n18()
+ fun_l22_n862
+end
+
+def fun_l21_n19()
+ fun_l22_n337
+end
+
+def fun_l21_n20()
+ fun_l22_n365
+end
+
+def fun_l21_n21()
+ fun_l22_n323
+end
+
+def fun_l21_n22()
+ fun_l22_n767
+end
+
+def fun_l21_n23()
+ fun_l22_n364
+end
+
+def fun_l21_n24()
+ fun_l22_n562
+end
+
+def fun_l21_n25()
+ fun_l22_n420
+end
+
+def fun_l21_n26()
+ fun_l22_n754
+end
+
+def fun_l21_n27()
+ fun_l22_n381
+end
+
+def fun_l21_n28()
+ fun_l22_n393
+end
+
+def fun_l21_n29()
+ fun_l22_n25
+end
+
+def fun_l21_n30()
+ fun_l22_n951
+end
+
+def fun_l21_n31()
+ fun_l22_n271
+end
+
+def fun_l21_n32()
+ fun_l22_n127
+end
+
+def fun_l21_n33()
+ fun_l22_n962
+end
+
+def fun_l21_n34()
+ fun_l22_n611
+end
+
+def fun_l21_n35()
+ fun_l22_n936
+end
+
+def fun_l21_n36()
+ fun_l22_n340
+end
+
+def fun_l21_n37()
+ fun_l22_n349
+end
+
+def fun_l21_n38()
+ fun_l22_n692
+end
+
+def fun_l21_n39()
+ fun_l22_n184
+end
+
+def fun_l21_n40()
+ fun_l22_n490
+end
+
+def fun_l21_n41()
+ fun_l22_n316
+end
+
+def fun_l21_n42()
+ fun_l22_n545
+end
+
+def fun_l21_n43()
+ fun_l22_n344
+end
+
+def fun_l21_n44()
+ fun_l22_n938
+end
+
+def fun_l21_n45()
+ fun_l22_n820
+end
+
+def fun_l21_n46()
+ fun_l22_n60
+end
+
+def fun_l21_n47()
+ fun_l22_n649
+end
+
+def fun_l21_n48()
+ fun_l22_n41
+end
+
+def fun_l21_n49()
+ fun_l22_n305
+end
+
+def fun_l21_n50()
+ fun_l22_n677
+end
+
+def fun_l21_n51()
+ fun_l22_n880
+end
+
+def fun_l21_n52()
+ fun_l22_n535
+end
+
+def fun_l21_n53()
+ fun_l22_n686
+end
+
+def fun_l21_n54()
+ fun_l22_n194
+end
+
+def fun_l21_n55()
+ fun_l22_n313
+end
+
+def fun_l21_n56()
+ fun_l22_n639
+end
+
+def fun_l21_n57()
+ fun_l22_n182
+end
+
+def fun_l21_n58()
+ fun_l22_n588
+end
+
+def fun_l21_n59()
+ fun_l22_n979
+end
+
+def fun_l21_n60()
+ fun_l22_n230
+end
+
+def fun_l21_n61()
+ fun_l22_n139
+end
+
+def fun_l21_n62()
+ fun_l22_n899
+end
+
+def fun_l21_n63()
+ fun_l22_n532
+end
+
+def fun_l21_n64()
+ fun_l22_n479
+end
+
+def fun_l21_n65()
+ fun_l22_n735
+end
+
+def fun_l21_n66()
+ fun_l22_n425
+end
+
+def fun_l21_n67()
+ fun_l22_n878
+end
+
+def fun_l21_n68()
+ fun_l22_n706
+end
+
+def fun_l21_n69()
+ fun_l22_n826
+end
+
+def fun_l21_n70()
+ fun_l22_n44
+end
+
+def fun_l21_n71()
+ fun_l22_n107
+end
+
+def fun_l21_n72()
+ fun_l22_n737
+end
+
+def fun_l21_n73()
+ fun_l22_n659
+end
+
+def fun_l21_n74()
+ fun_l22_n707
+end
+
+def fun_l21_n75()
+ fun_l22_n658
+end
+
+def fun_l21_n76()
+ fun_l22_n937
+end
+
+def fun_l21_n77()
+ fun_l22_n86
+end
+
+def fun_l21_n78()
+ fun_l22_n606
+end
+
+def fun_l21_n79()
+ fun_l22_n61
+end
+
+def fun_l21_n80()
+ fun_l22_n780
+end
+
+def fun_l21_n81()
+ fun_l22_n560
+end
+
+def fun_l21_n82()
+ fun_l22_n949
+end
+
+def fun_l21_n83()
+ fun_l22_n790
+end
+
+def fun_l21_n84()
+ fun_l22_n851
+end
+
+def fun_l21_n85()
+ fun_l22_n148
+end
+
+def fun_l21_n86()
+ fun_l22_n406
+end
+
+def fun_l21_n87()
+ fun_l22_n38
+end
+
+def fun_l21_n88()
+ fun_l22_n468
+end
+
+def fun_l21_n89()
+ fun_l22_n783
+end
+
+def fun_l21_n90()
+ fun_l22_n853
+end
+
+def fun_l21_n91()
+ fun_l22_n758
+end
+
+def fun_l21_n92()
+ fun_l22_n34
+end
+
+def fun_l21_n93()
+ fun_l22_n387
+end
+
+def fun_l21_n94()
+ fun_l22_n181
+end
+
+def fun_l21_n95()
+ fun_l22_n514
+end
+
+def fun_l21_n96()
+ fun_l22_n139
+end
+
+def fun_l21_n97()
+ fun_l22_n543
+end
+
+def fun_l21_n98()
+ fun_l22_n462
+end
+
+def fun_l21_n99()
+ fun_l22_n570
+end
+
+def fun_l21_n100()
+ fun_l22_n634
+end
+
+def fun_l21_n101()
+ fun_l22_n69
+end
+
+def fun_l21_n102()
+ fun_l22_n142
+end
+
+def fun_l21_n103()
+ fun_l22_n964
+end
+
+def fun_l21_n104()
+ fun_l22_n851
+end
+
+def fun_l21_n105()
+ fun_l22_n410
+end
+
+def fun_l21_n106()
+ fun_l22_n563
+end
+
+def fun_l21_n107()
+ fun_l22_n914
+end
+
+def fun_l21_n108()
+ fun_l22_n163
+end
+
+def fun_l21_n109()
+ fun_l22_n248
+end
+
+def fun_l21_n110()
+ fun_l22_n309
+end
+
+def fun_l21_n111()
+ fun_l22_n894
+end
+
+def fun_l21_n112()
+ fun_l22_n916
+end
+
+def fun_l21_n113()
+ fun_l22_n818
+end
+
+def fun_l21_n114()
+ fun_l22_n824
+end
+
+def fun_l21_n115()
+ fun_l22_n34
+end
+
+def fun_l21_n116()
+ fun_l22_n538
+end
+
+def fun_l21_n117()
+ fun_l22_n841
+end
+
+def fun_l21_n118()
+ fun_l22_n934
+end
+
+def fun_l21_n119()
+ fun_l22_n217
+end
+
+def fun_l21_n120()
+ fun_l22_n479
+end
+
+def fun_l21_n121()
+ fun_l22_n693
+end
+
+def fun_l21_n122()
+ fun_l22_n182
+end
+
+def fun_l21_n123()
+ fun_l22_n269
+end
+
+def fun_l21_n124()
+ fun_l22_n324
+end
+
+def fun_l21_n125()
+ fun_l22_n688
+end
+
+def fun_l21_n126()
+ fun_l22_n725
+end
+
+def fun_l21_n127()
+ fun_l22_n48
+end
+
+def fun_l21_n128()
+ fun_l22_n884
+end
+
+def fun_l21_n129()
+ fun_l22_n295
+end
+
+def fun_l21_n130()
+ fun_l22_n192
+end
+
+def fun_l21_n131()
+ fun_l22_n777
+end
+
+def fun_l21_n132()
+ fun_l22_n87
+end
+
+def fun_l21_n133()
+ fun_l22_n724
+end
+
+def fun_l21_n134()
+ fun_l22_n235
+end
+
+def fun_l21_n135()
+ fun_l22_n239
+end
+
+def fun_l21_n136()
+ fun_l22_n820
+end
+
+def fun_l21_n137()
+ fun_l22_n552
+end
+
+def fun_l21_n138()
+ fun_l22_n227
+end
+
+def fun_l21_n139()
+ fun_l22_n806
+end
+
+def fun_l21_n140()
+ fun_l22_n350
+end
+
+def fun_l21_n141()
+ fun_l22_n226
+end
+
+def fun_l21_n142()
+ fun_l22_n166
+end
+
+def fun_l21_n143()
+ fun_l22_n480
+end
+
+def fun_l21_n144()
+ fun_l22_n28
+end
+
+def fun_l21_n145()
+ fun_l22_n661
+end
+
+def fun_l21_n146()
+ fun_l22_n464
+end
+
+def fun_l21_n147()
+ fun_l22_n573
+end
+
+def fun_l21_n148()
+ fun_l22_n589
+end
+
+def fun_l21_n149()
+ fun_l22_n856
+end
+
+def fun_l21_n150()
+ fun_l22_n181
+end
+
+def fun_l21_n151()
+ fun_l22_n252
+end
+
+def fun_l21_n152()
+ fun_l22_n80
+end
+
+def fun_l21_n153()
+ fun_l22_n417
+end
+
+def fun_l21_n154()
+ fun_l22_n442
+end
+
+def fun_l21_n155()
+ fun_l22_n928
+end
+
+def fun_l21_n156()
+ fun_l22_n38
+end
+
+def fun_l21_n157()
+ fun_l22_n515
+end
+
+def fun_l21_n158()
+ fun_l22_n986
+end
+
+def fun_l21_n159()
+ fun_l22_n173
+end
+
+def fun_l21_n160()
+ fun_l22_n592
+end
+
+def fun_l21_n161()
+ fun_l22_n50
+end
+
+def fun_l21_n162()
+ fun_l22_n625
+end
+
+def fun_l21_n163()
+ fun_l22_n651
+end
+
+def fun_l21_n164()
+ fun_l22_n183
+end
+
+def fun_l21_n165()
+ fun_l22_n976
+end
+
+def fun_l21_n166()
+ fun_l22_n533
+end
+
+def fun_l21_n167()
+ fun_l22_n313
+end
+
+def fun_l21_n168()
+ fun_l22_n948
+end
+
+def fun_l21_n169()
+ fun_l22_n860
+end
+
+def fun_l21_n170()
+ fun_l22_n393
+end
+
+def fun_l21_n171()
+ fun_l22_n986
+end
+
+def fun_l21_n172()
+ fun_l22_n206
+end
+
+def fun_l21_n173()
+ fun_l22_n189
+end
+
+def fun_l21_n174()
+ fun_l22_n209
+end
+
+def fun_l21_n175()
+ fun_l22_n822
+end
+
+def fun_l21_n176()
+ fun_l22_n960
+end
+
+def fun_l21_n177()
+ fun_l22_n646
+end
+
+def fun_l21_n178()
+ fun_l22_n523
+end
+
+def fun_l21_n179()
+ fun_l22_n520
+end
+
+def fun_l21_n180()
+ fun_l22_n146
+end
+
+def fun_l21_n181()
+ fun_l22_n336
+end
+
+def fun_l21_n182()
+ fun_l22_n129
+end
+
+def fun_l21_n183()
+ fun_l22_n382
+end
+
+def fun_l21_n184()
+ fun_l22_n833
+end
+
+def fun_l21_n185()
+ fun_l22_n398
+end
+
+def fun_l21_n186()
+ fun_l22_n919
+end
+
+def fun_l21_n187()
+ fun_l22_n463
+end
+
+def fun_l21_n188()
+ fun_l22_n442
+end
+
+def fun_l21_n189()
+ fun_l22_n395
+end
+
+def fun_l21_n190()
+ fun_l22_n934
+end
+
+def fun_l21_n191()
+ fun_l22_n117
+end
+
+def fun_l21_n192()
+ fun_l22_n436
+end
+
+def fun_l21_n193()
+ fun_l22_n316
+end
+
+def fun_l21_n194()
+ fun_l22_n512
+end
+
+def fun_l21_n195()
+ fun_l22_n565
+end
+
+def fun_l21_n196()
+ fun_l22_n494
+end
+
+def fun_l21_n197()
+ fun_l22_n586
+end
+
+def fun_l21_n198()
+ fun_l22_n456
+end
+
+def fun_l21_n199()
+ fun_l22_n465
+end
+
+def fun_l21_n200()
+ fun_l22_n622
+end
+
+def fun_l21_n201()
+ fun_l22_n747
+end
+
+def fun_l21_n202()
+ fun_l22_n216
+end
+
+def fun_l21_n203()
+ fun_l22_n568
+end
+
+def fun_l21_n204()
+ fun_l22_n94
+end
+
+def fun_l21_n205()
+ fun_l22_n839
+end
+
+def fun_l21_n206()
+ fun_l22_n357
+end
+
+def fun_l21_n207()
+ fun_l22_n485
+end
+
+def fun_l21_n208()
+ fun_l22_n818
+end
+
+def fun_l21_n209()
+ fun_l22_n852
+end
+
+def fun_l21_n210()
+ fun_l22_n264
+end
+
+def fun_l21_n211()
+ fun_l22_n519
+end
+
+def fun_l21_n212()
+ fun_l22_n362
+end
+
+def fun_l21_n213()
+ fun_l22_n955
+end
+
+def fun_l21_n214()
+ fun_l22_n756
+end
+
+def fun_l21_n215()
+ fun_l22_n271
+end
+
+def fun_l21_n216()
+ fun_l22_n169
+end
+
+def fun_l21_n217()
+ fun_l22_n456
+end
+
+def fun_l21_n218()
+ fun_l22_n227
+end
+
+def fun_l21_n219()
+ fun_l22_n75
+end
+
+def fun_l21_n220()
+ fun_l22_n21
+end
+
+def fun_l21_n221()
+ fun_l22_n35
+end
+
+def fun_l21_n222()
+ fun_l22_n386
+end
+
+def fun_l21_n223()
+ fun_l22_n678
+end
+
+def fun_l21_n224()
+ fun_l22_n463
+end
+
+def fun_l21_n225()
+ fun_l22_n200
+end
+
+def fun_l21_n226()
+ fun_l22_n502
+end
+
+def fun_l21_n227()
+ fun_l22_n690
+end
+
+def fun_l21_n228()
+ fun_l22_n153
+end
+
+def fun_l21_n229()
+ fun_l22_n218
+end
+
+def fun_l21_n230()
+ fun_l22_n20
+end
+
+def fun_l21_n231()
+ fun_l22_n48
+end
+
+def fun_l21_n232()
+ fun_l22_n549
+end
+
+def fun_l21_n233()
+ fun_l22_n994
+end
+
+def fun_l21_n234()
+ fun_l22_n242
+end
+
+def fun_l21_n235()
+ fun_l22_n153
+end
+
+def fun_l21_n236()
+ fun_l22_n830
+end
+
+def fun_l21_n237()
+ fun_l22_n663
+end
+
+def fun_l21_n238()
+ fun_l22_n387
+end
+
+def fun_l21_n239()
+ fun_l22_n87
+end
+
+def fun_l21_n240()
+ fun_l22_n341
+end
+
+def fun_l21_n241()
+ fun_l22_n499
+end
+
+def fun_l21_n242()
+ fun_l22_n231
+end
+
+def fun_l21_n243()
+ fun_l22_n644
+end
+
+def fun_l21_n244()
+ fun_l22_n212
+end
+
+def fun_l21_n245()
+ fun_l22_n197
+end
+
+def fun_l21_n246()
+ fun_l22_n831
+end
+
+def fun_l21_n247()
+ fun_l22_n62
+end
+
+def fun_l21_n248()
+ fun_l22_n689
+end
+
+def fun_l21_n249()
+ fun_l22_n884
+end
+
+def fun_l21_n250()
+ fun_l22_n767
+end
+
+def fun_l21_n251()
+ fun_l22_n278
+end
+
+def fun_l21_n252()
+ fun_l22_n881
+end
+
+def fun_l21_n253()
+ fun_l22_n585
+end
+
+def fun_l21_n254()
+ fun_l22_n967
+end
+
+def fun_l21_n255()
+ fun_l22_n381
+end
+
+def fun_l21_n256()
+ fun_l22_n579
+end
+
+def fun_l21_n257()
+ fun_l22_n447
+end
+
+def fun_l21_n258()
+ fun_l22_n156
+end
+
+def fun_l21_n259()
+ fun_l22_n722
+end
+
+def fun_l21_n260()
+ fun_l22_n431
+end
+
+def fun_l21_n261()
+ fun_l22_n83
+end
+
+def fun_l21_n262()
+ fun_l22_n41
+end
+
+def fun_l21_n263()
+ fun_l22_n18
+end
+
+def fun_l21_n264()
+ fun_l22_n686
+end
+
+def fun_l21_n265()
+ fun_l22_n668
+end
+
+def fun_l21_n266()
+ fun_l22_n652
+end
+
+def fun_l21_n267()
+ fun_l22_n121
+end
+
+def fun_l21_n268()
+ fun_l22_n279
+end
+
+def fun_l21_n269()
+ fun_l22_n540
+end
+
+def fun_l21_n270()
+ fun_l22_n360
+end
+
+def fun_l21_n271()
+ fun_l22_n106
+end
+
+def fun_l21_n272()
+ fun_l22_n454
+end
+
+def fun_l21_n273()
+ fun_l22_n882
+end
+
+def fun_l21_n274()
+ fun_l22_n523
+end
+
+def fun_l21_n275()
+ fun_l22_n938
+end
+
+def fun_l21_n276()
+ fun_l22_n932
+end
+
+def fun_l21_n277()
+ fun_l22_n923
+end
+
+def fun_l21_n278()
+ fun_l22_n728
+end
+
+def fun_l21_n279()
+ fun_l22_n587
+end
+
+def fun_l21_n280()
+ fun_l22_n608
+end
+
+def fun_l21_n281()
+ fun_l22_n366
+end
+
+def fun_l21_n282()
+ fun_l22_n486
+end
+
+def fun_l21_n283()
+ fun_l22_n864
+end
+
+def fun_l21_n284()
+ fun_l22_n34
+end
+
+def fun_l21_n285()
+ fun_l22_n658
+end
+
+def fun_l21_n286()
+ fun_l22_n488
+end
+
+def fun_l21_n287()
+ fun_l22_n266
+end
+
+def fun_l21_n288()
+ fun_l22_n810
+end
+
+def fun_l21_n289()
+ fun_l22_n965
+end
+
+def fun_l21_n290()
+ fun_l22_n513
+end
+
+def fun_l21_n291()
+ fun_l22_n608
+end
+
+def fun_l21_n292()
+ fun_l22_n499
+end
+
+def fun_l21_n293()
+ fun_l22_n360
+end
+
+def fun_l21_n294()
+ fun_l22_n511
+end
+
+def fun_l21_n295()
+ fun_l22_n940
+end
+
+def fun_l21_n296()
+ fun_l22_n99
+end
+
+def fun_l21_n297()
+ fun_l22_n496
+end
+
+def fun_l21_n298()
+ fun_l22_n273
+end
+
+def fun_l21_n299()
+ fun_l22_n232
+end
+
+def fun_l21_n300()
+ fun_l22_n165
+end
+
+def fun_l21_n301()
+ fun_l22_n531
+end
+
+def fun_l21_n302()
+ fun_l22_n773
+end
+
+def fun_l21_n303()
+ fun_l22_n610
+end
+
+def fun_l21_n304()
+ fun_l22_n564
+end
+
+def fun_l21_n305()
+ fun_l22_n16
+end
+
+def fun_l21_n306()
+ fun_l22_n176
+end
+
+def fun_l21_n307()
+ fun_l22_n846
+end
+
+def fun_l21_n308()
+ fun_l22_n680
+end
+
+def fun_l21_n309()
+ fun_l22_n858
+end
+
+def fun_l21_n310()
+ fun_l22_n220
+end
+
+def fun_l21_n311()
+ fun_l22_n125
+end
+
+def fun_l21_n312()
+ fun_l22_n441
+end
+
+def fun_l21_n313()
+ fun_l22_n751
+end
+
+def fun_l21_n314()
+ fun_l22_n863
+end
+
+def fun_l21_n315()
+ fun_l22_n284
+end
+
+def fun_l21_n316()
+ fun_l22_n648
+end
+
+def fun_l21_n317()
+ fun_l22_n363
+end
+
+def fun_l21_n318()
+ fun_l22_n427
+end
+
+def fun_l21_n319()
+ fun_l22_n557
+end
+
+def fun_l21_n320()
+ fun_l22_n531
+end
+
+def fun_l21_n321()
+ fun_l22_n252
+end
+
+def fun_l21_n322()
+ fun_l22_n393
+end
+
+def fun_l21_n323()
+ fun_l22_n108
+end
+
+def fun_l21_n324()
+ fun_l22_n138
+end
+
+def fun_l21_n325()
+ fun_l22_n68
+end
+
+def fun_l21_n326()
+ fun_l22_n909
+end
+
+def fun_l21_n327()
+ fun_l22_n672
+end
+
+def fun_l21_n328()
+ fun_l22_n746
+end
+
+def fun_l21_n329()
+ fun_l22_n479
+end
+
+def fun_l21_n330()
+ fun_l22_n892
+end
+
+def fun_l21_n331()
+ fun_l22_n30
+end
+
+def fun_l21_n332()
+ fun_l22_n184
+end
+
+def fun_l21_n333()
+ fun_l22_n956
+end
+
+def fun_l21_n334()
+ fun_l22_n712
+end
+
+def fun_l21_n335()
+ fun_l22_n929
+end
+
+def fun_l21_n336()
+ fun_l22_n914
+end
+
+def fun_l21_n337()
+ fun_l22_n14
+end
+
+def fun_l21_n338()
+ fun_l22_n471
+end
+
+def fun_l21_n339()
+ fun_l22_n488
+end
+
+def fun_l21_n340()
+ fun_l22_n40
+end
+
+def fun_l21_n341()
+ fun_l22_n406
+end
+
+def fun_l21_n342()
+ fun_l22_n11
+end
+
+def fun_l21_n343()
+ fun_l22_n779
+end
+
+def fun_l21_n344()
+ fun_l22_n999
+end
+
+def fun_l21_n345()
+ fun_l22_n833
+end
+
+def fun_l21_n346()
+ fun_l22_n897
+end
+
+def fun_l21_n347()
+ fun_l22_n365
+end
+
+def fun_l21_n348()
+ fun_l22_n583
+end
+
+def fun_l21_n349()
+ fun_l22_n326
+end
+
+def fun_l21_n350()
+ fun_l22_n556
+end
+
+def fun_l21_n351()
+ fun_l22_n249
+end
+
+def fun_l21_n352()
+ fun_l22_n146
+end
+
+def fun_l21_n353()
+ fun_l22_n865
+end
+
+def fun_l21_n354()
+ fun_l22_n303
+end
+
+def fun_l21_n355()
+ fun_l22_n64
+end
+
+def fun_l21_n356()
+ fun_l22_n785
+end
+
+def fun_l21_n357()
+ fun_l22_n176
+end
+
+def fun_l21_n358()
+ fun_l22_n891
+end
+
+def fun_l21_n359()
+ fun_l22_n129
+end
+
+def fun_l21_n360()
+ fun_l22_n19
+end
+
+def fun_l21_n361()
+ fun_l22_n372
+end
+
+def fun_l21_n362()
+ fun_l22_n999
+end
+
+def fun_l21_n363()
+ fun_l22_n450
+end
+
+def fun_l21_n364()
+ fun_l22_n455
+end
+
+def fun_l21_n365()
+ fun_l22_n174
+end
+
+def fun_l21_n366()
+ fun_l22_n719
+end
+
+def fun_l21_n367()
+ fun_l22_n997
+end
+
+def fun_l21_n368()
+ fun_l22_n256
+end
+
+def fun_l21_n369()
+ fun_l22_n206
+end
+
+def fun_l21_n370()
+ fun_l22_n988
+end
+
+def fun_l21_n371()
+ fun_l22_n147
+end
+
+def fun_l21_n372()
+ fun_l22_n750
+end
+
+def fun_l21_n373()
+ fun_l22_n585
+end
+
+def fun_l21_n374()
+ fun_l22_n213
+end
+
+def fun_l21_n375()
+ fun_l22_n583
+end
+
+def fun_l21_n376()
+ fun_l22_n564
+end
+
+def fun_l21_n377()
+ fun_l22_n689
+end
+
+def fun_l21_n378()
+ fun_l22_n955
+end
+
+def fun_l21_n379()
+ fun_l22_n560
+end
+
+def fun_l21_n380()
+ fun_l22_n237
+end
+
+def fun_l21_n381()
+ fun_l22_n272
+end
+
+def fun_l21_n382()
+ fun_l22_n455
+end
+
+def fun_l21_n383()
+ fun_l22_n233
+end
+
+def fun_l21_n384()
+ fun_l22_n658
+end
+
+def fun_l21_n385()
+ fun_l22_n319
+end
+
+def fun_l21_n386()
+ fun_l22_n852
+end
+
+def fun_l21_n387()
+ fun_l22_n343
+end
+
+def fun_l21_n388()
+ fun_l22_n645
+end
+
+def fun_l21_n389()
+ fun_l22_n433
+end
+
+def fun_l21_n390()
+ fun_l22_n430
+end
+
+def fun_l21_n391()
+ fun_l22_n636
+end
+
+def fun_l21_n392()
+ fun_l22_n682
+end
+
+def fun_l21_n393()
+ fun_l22_n859
+end
+
+def fun_l21_n394()
+ fun_l22_n315
+end
+
+def fun_l21_n395()
+ fun_l22_n91
+end
+
+def fun_l21_n396()
+ fun_l22_n817
+end
+
+def fun_l21_n397()
+ fun_l22_n268
+end
+
+def fun_l21_n398()
+ fun_l22_n476
+end
+
+def fun_l21_n399()
+ fun_l22_n612
+end
+
+def fun_l21_n400()
+ fun_l22_n392
+end
+
+def fun_l21_n401()
+ fun_l22_n728
+end
+
+def fun_l21_n402()
+ fun_l22_n652
+end
+
+def fun_l21_n403()
+ fun_l22_n547
+end
+
+def fun_l21_n404()
+ fun_l22_n101
+end
+
+def fun_l21_n405()
+ fun_l22_n666
+end
+
+def fun_l21_n406()
+ fun_l22_n521
+end
+
+def fun_l21_n407()
+ fun_l22_n860
+end
+
+def fun_l21_n408()
+ fun_l22_n577
+end
+
+def fun_l21_n409()
+ fun_l22_n258
+end
+
+def fun_l21_n410()
+ fun_l22_n260
+end
+
+def fun_l21_n411()
+ fun_l22_n927
+end
+
+def fun_l21_n412()
+ fun_l22_n13
+end
+
+def fun_l21_n413()
+ fun_l22_n308
+end
+
+def fun_l21_n414()
+ fun_l22_n189
+end
+
+def fun_l21_n415()
+ fun_l22_n183
+end
+
+def fun_l21_n416()
+ fun_l22_n370
+end
+
+def fun_l21_n417()
+ fun_l22_n407
+end
+
+def fun_l21_n418()
+ fun_l22_n959
+end
+
+def fun_l21_n419()
+ fun_l22_n908
+end
+
+def fun_l21_n420()
+ fun_l22_n84
+end
+
+def fun_l21_n421()
+ fun_l22_n951
+end
+
+def fun_l21_n422()
+ fun_l22_n286
+end
+
+def fun_l21_n423()
+ fun_l22_n54
+end
+
+def fun_l21_n424()
+ fun_l22_n410
+end
+
+def fun_l21_n425()
+ fun_l22_n387
+end
+
+def fun_l21_n426()
+ fun_l22_n751
+end
+
+def fun_l21_n427()
+ fun_l22_n971
+end
+
+def fun_l21_n428()
+ fun_l22_n162
+end
+
+def fun_l21_n429()
+ fun_l22_n15
+end
+
+def fun_l21_n430()
+ fun_l22_n35
+end
+
+def fun_l21_n431()
+ fun_l22_n354
+end
+
+def fun_l21_n432()
+ fun_l22_n979
+end
+
+def fun_l21_n433()
+ fun_l22_n999
+end
+
+def fun_l21_n434()
+ fun_l22_n622
+end
+
+def fun_l21_n435()
+ fun_l22_n970
+end
+
+def fun_l21_n436()
+ fun_l22_n758
+end
+
+def fun_l21_n437()
+ fun_l22_n950
+end
+
+def fun_l21_n438()
+ fun_l22_n865
+end
+
+def fun_l21_n439()
+ fun_l22_n31
+end
+
+def fun_l21_n440()
+ fun_l22_n620
+end
+
+def fun_l21_n441()
+ fun_l22_n170
+end
+
+def fun_l21_n442()
+ fun_l22_n816
+end
+
+def fun_l21_n443()
+ fun_l22_n364
+end
+
+def fun_l21_n444()
+ fun_l22_n289
+end
+
+def fun_l21_n445()
+ fun_l22_n949
+end
+
+def fun_l21_n446()
+ fun_l22_n876
+end
+
+def fun_l21_n447()
+ fun_l22_n971
+end
+
+def fun_l21_n448()
+ fun_l22_n343
+end
+
+def fun_l21_n449()
+ fun_l22_n14
+end
+
+def fun_l21_n450()
+ fun_l22_n925
+end
+
+def fun_l21_n451()
+ fun_l22_n234
+end
+
+def fun_l21_n452()
+ fun_l22_n242
+end
+
+def fun_l21_n453()
+ fun_l22_n184
+end
+
+def fun_l21_n454()
+ fun_l22_n158
+end
+
+def fun_l21_n455()
+ fun_l22_n645
+end
+
+def fun_l21_n456()
+ fun_l22_n173
+end
+
+def fun_l21_n457()
+ fun_l22_n363
+end
+
+def fun_l21_n458()
+ fun_l22_n787
+end
+
+def fun_l21_n459()
+ fun_l22_n102
+end
+
+def fun_l21_n460()
+ fun_l22_n886
+end
+
+def fun_l21_n461()
+ fun_l22_n279
+end
+
+def fun_l21_n462()
+ fun_l22_n909
+end
+
+def fun_l21_n463()
+ fun_l22_n767
+end
+
+def fun_l21_n464()
+ fun_l22_n82
+end
+
+def fun_l21_n465()
+ fun_l22_n249
+end
+
+def fun_l21_n466()
+ fun_l22_n670
+end
+
+def fun_l21_n467()
+ fun_l22_n944
+end
+
+def fun_l21_n468()
+ fun_l22_n191
+end
+
+def fun_l21_n469()
+ fun_l22_n897
+end
+
+def fun_l21_n470()
+ fun_l22_n591
+end
+
+def fun_l21_n471()
+ fun_l22_n164
+end
+
+def fun_l21_n472()
+ fun_l22_n984
+end
+
+def fun_l21_n473()
+ fun_l22_n26
+end
+
+def fun_l21_n474()
+ fun_l22_n398
+end
+
+def fun_l21_n475()
+ fun_l22_n668
+end
+
+def fun_l21_n476()
+ fun_l22_n190
+end
+
+def fun_l21_n477()
+ fun_l22_n249
+end
+
+def fun_l21_n478()
+ fun_l22_n736
+end
+
+def fun_l21_n479()
+ fun_l22_n714
+end
+
+def fun_l21_n480()
+ fun_l22_n929
+end
+
+def fun_l21_n481()
+ fun_l22_n448
+end
+
+def fun_l21_n482()
+ fun_l22_n922
+end
+
+def fun_l21_n483()
+ fun_l22_n992
+end
+
+def fun_l21_n484()
+ fun_l22_n306
+end
+
+def fun_l21_n485()
+ fun_l22_n420
+end
+
+def fun_l21_n486()
+ fun_l22_n630
+end
+
+def fun_l21_n487()
+ fun_l22_n263
+end
+
+def fun_l21_n488()
+ fun_l22_n754
+end
+
+def fun_l21_n489()
+ fun_l22_n96
+end
+
+def fun_l21_n490()
+ fun_l22_n338
+end
+
+def fun_l21_n491()
+ fun_l22_n615
+end
+
+def fun_l21_n492()
+ fun_l22_n704
+end
+
+def fun_l21_n493()
+ fun_l22_n581
+end
+
+def fun_l21_n494()
+ fun_l22_n801
+end
+
+def fun_l21_n495()
+ fun_l22_n204
+end
+
+def fun_l21_n496()
+ fun_l22_n835
+end
+
+def fun_l21_n497()
+ fun_l22_n479
+end
+
+def fun_l21_n498()
+ fun_l22_n379
+end
+
+def fun_l21_n499()
+ fun_l22_n937
+end
+
+def fun_l21_n500()
+ fun_l22_n830
+end
+
+def fun_l21_n501()
+ fun_l22_n458
+end
+
+def fun_l21_n502()
+ fun_l22_n806
+end
+
+def fun_l21_n503()
+ fun_l22_n158
+end
+
+def fun_l21_n504()
+ fun_l22_n151
+end
+
+def fun_l21_n505()
+ fun_l22_n685
+end
+
+def fun_l21_n506()
+ fun_l22_n806
+end
+
+def fun_l21_n507()
+ fun_l22_n584
+end
+
+def fun_l21_n508()
+ fun_l22_n644
+end
+
+def fun_l21_n509()
+ fun_l22_n237
+end
+
+def fun_l21_n510()
+ fun_l22_n542
+end
+
+def fun_l21_n511()
+ fun_l22_n450
+end
+
+def fun_l21_n512()
+ fun_l22_n385
+end
+
+def fun_l21_n513()
+ fun_l22_n321
+end
+
+def fun_l21_n514()
+ fun_l22_n548
+end
+
+def fun_l21_n515()
+ fun_l22_n519
+end
+
+def fun_l21_n516()
+ fun_l22_n309
+end
+
+def fun_l21_n517()
+ fun_l22_n4
+end
+
+def fun_l21_n518()
+ fun_l22_n930
+end
+
+def fun_l21_n519()
+ fun_l22_n245
+end
+
+def fun_l21_n520()
+ fun_l22_n568
+end
+
+def fun_l21_n521()
+ fun_l22_n527
+end
+
+def fun_l21_n522()
+ fun_l22_n650
+end
+
+def fun_l21_n523()
+ fun_l22_n391
+end
+
+def fun_l21_n524()
+ fun_l22_n749
+end
+
+def fun_l21_n525()
+ fun_l22_n810
+end
+
+def fun_l21_n526()
+ fun_l22_n615
+end
+
+def fun_l21_n527()
+ fun_l22_n702
+end
+
+def fun_l21_n528()
+ fun_l22_n62
+end
+
+def fun_l21_n529()
+ fun_l22_n316
+end
+
+def fun_l21_n530()
+ fun_l22_n201
+end
+
+def fun_l21_n531()
+ fun_l22_n447
+end
+
+def fun_l21_n532()
+ fun_l22_n506
+end
+
+def fun_l21_n533()
+ fun_l22_n900
+end
+
+def fun_l21_n534()
+ fun_l22_n652
+end
+
+def fun_l21_n535()
+ fun_l22_n493
+end
+
+def fun_l21_n536()
+ fun_l22_n803
+end
+
+def fun_l21_n537()
+ fun_l22_n263
+end
+
+def fun_l21_n538()
+ fun_l22_n303
+end
+
+def fun_l21_n539()
+ fun_l22_n17
+end
+
+def fun_l21_n540()
+ fun_l22_n900
+end
+
+def fun_l21_n541()
+ fun_l22_n917
+end
+
+def fun_l21_n542()
+ fun_l22_n789
+end
+
+def fun_l21_n543()
+ fun_l22_n668
+end
+
+def fun_l21_n544()
+ fun_l22_n335
+end
+
+def fun_l21_n545()
+ fun_l22_n560
+end
+
+def fun_l21_n546()
+ fun_l22_n705
+end
+
+def fun_l21_n547()
+ fun_l22_n159
+end
+
+def fun_l21_n548()
+ fun_l22_n874
+end
+
+def fun_l21_n549()
+ fun_l22_n809
+end
+
+def fun_l21_n550()
+ fun_l22_n726
+end
+
+def fun_l21_n551()
+ fun_l22_n27
+end
+
+def fun_l21_n552()
+ fun_l22_n63
+end
+
+def fun_l21_n553()
+ fun_l22_n642
+end
+
+def fun_l21_n554()
+ fun_l22_n694
+end
+
+def fun_l21_n555()
+ fun_l22_n432
+end
+
+def fun_l21_n556()
+ fun_l22_n439
+end
+
+def fun_l21_n557()
+ fun_l22_n876
+end
+
+def fun_l21_n558()
+ fun_l22_n998
+end
+
+def fun_l21_n559()
+ fun_l22_n703
+end
+
+def fun_l21_n560()
+ fun_l22_n785
+end
+
+def fun_l21_n561()
+ fun_l22_n543
+end
+
+def fun_l21_n562()
+ fun_l22_n286
+end
+
+def fun_l21_n563()
+ fun_l22_n771
+end
+
+def fun_l21_n564()
+ fun_l22_n447
+end
+
+def fun_l21_n565()
+ fun_l22_n955
+end
+
+def fun_l21_n566()
+ fun_l22_n603
+end
+
+def fun_l21_n567()
+ fun_l22_n258
+end
+
+def fun_l21_n568()
+ fun_l22_n936
+end
+
+def fun_l21_n569()
+ fun_l22_n524
+end
+
+def fun_l21_n570()
+ fun_l22_n205
+end
+
+def fun_l21_n571()
+ fun_l22_n41
+end
+
+def fun_l21_n572()
+ fun_l22_n589
+end
+
+def fun_l21_n573()
+ fun_l22_n519
+end
+
+def fun_l21_n574()
+ fun_l22_n500
+end
+
+def fun_l21_n575()
+ fun_l22_n307
+end
+
+def fun_l21_n576()
+ fun_l22_n598
+end
+
+def fun_l21_n577()
+ fun_l22_n698
+end
+
+def fun_l21_n578()
+ fun_l22_n200
+end
+
+def fun_l21_n579()
+ fun_l22_n657
+end
+
+def fun_l21_n580()
+ fun_l22_n353
+end
+
+def fun_l21_n581()
+ fun_l22_n553
+end
+
+def fun_l21_n582()
+ fun_l22_n490
+end
+
+def fun_l21_n583()
+ fun_l22_n112
+end
+
+def fun_l21_n584()
+ fun_l22_n626
+end
+
+def fun_l21_n585()
+ fun_l22_n815
+end
+
+def fun_l21_n586()
+ fun_l22_n792
+end
+
+def fun_l21_n587()
+ fun_l22_n295
+end
+
+def fun_l21_n588()
+ fun_l22_n201
+end
+
+def fun_l21_n589()
+ fun_l22_n248
+end
+
+def fun_l21_n590()
+ fun_l22_n295
+end
+
+def fun_l21_n591()
+ fun_l22_n708
+end
+
+def fun_l21_n592()
+ fun_l22_n507
+end
+
+def fun_l21_n593()
+ fun_l22_n177
+end
+
+def fun_l21_n594()
+ fun_l22_n467
+end
+
+def fun_l21_n595()
+ fun_l22_n113
+end
+
+def fun_l21_n596()
+ fun_l22_n390
+end
+
+def fun_l21_n597()
+ fun_l22_n348
+end
+
+def fun_l21_n598()
+ fun_l22_n545
+end
+
+def fun_l21_n599()
+ fun_l22_n695
+end
+
+def fun_l21_n600()
+ fun_l22_n170
+end
+
+def fun_l21_n601()
+ fun_l22_n978
+end
+
+def fun_l21_n602()
+ fun_l22_n70
+end
+
+def fun_l21_n603()
+ fun_l22_n161
+end
+
+def fun_l21_n604()
+ fun_l22_n33
+end
+
+def fun_l21_n605()
+ fun_l22_n275
+end
+
+def fun_l21_n606()
+ fun_l22_n738
+end
+
+def fun_l21_n607()
+ fun_l22_n152
+end
+
+def fun_l21_n608()
+ fun_l22_n380
+end
+
+def fun_l21_n609()
+ fun_l22_n903
+end
+
+def fun_l21_n610()
+ fun_l22_n274
+end
+
+def fun_l21_n611()
+ fun_l22_n100
+end
+
+def fun_l21_n612()
+ fun_l22_n206
+end
+
+def fun_l21_n613()
+ fun_l22_n225
+end
+
+def fun_l21_n614()
+ fun_l22_n627
+end
+
+def fun_l21_n615()
+ fun_l22_n332
+end
+
+def fun_l21_n616()
+ fun_l22_n312
+end
+
+def fun_l21_n617()
+ fun_l22_n379
+end
+
+def fun_l21_n618()
+ fun_l22_n889
+end
+
+def fun_l21_n619()
+ fun_l22_n399
+end
+
+def fun_l21_n620()
+ fun_l22_n212
+end
+
+def fun_l21_n621()
+ fun_l22_n289
+end
+
+def fun_l21_n622()
+ fun_l22_n161
+end
+
+def fun_l21_n623()
+ fun_l22_n764
+end
+
+def fun_l21_n624()
+ fun_l22_n165
+end
+
+def fun_l21_n625()
+ fun_l22_n768
+end
+
+def fun_l21_n626()
+ fun_l22_n596
+end
+
+def fun_l21_n627()
+ fun_l22_n506
+end
+
+def fun_l21_n628()
+ fun_l22_n523
+end
+
+def fun_l21_n629()
+ fun_l22_n261
+end
+
+def fun_l21_n630()
+ fun_l22_n683
+end
+
+def fun_l21_n631()
+ fun_l22_n518
+end
+
+def fun_l21_n632()
+ fun_l22_n813
+end
+
+def fun_l21_n633()
+ fun_l22_n949
+end
+
+def fun_l21_n634()
+ fun_l22_n856
+end
+
+def fun_l21_n635()
+ fun_l22_n250
+end
+
+def fun_l21_n636()
+ fun_l22_n840
+end
+
+def fun_l21_n637()
+ fun_l22_n763
+end
+
+def fun_l21_n638()
+ fun_l22_n40
+end
+
+def fun_l21_n639()
+ fun_l22_n13
+end
+
+def fun_l21_n640()
+ fun_l22_n789
+end
+
+def fun_l21_n641()
+ fun_l22_n517
+end
+
+def fun_l21_n642()
+ fun_l22_n366
+end
+
+def fun_l21_n643()
+ fun_l22_n155
+end
+
+def fun_l21_n644()
+ fun_l22_n370
+end
+
+def fun_l21_n645()
+ fun_l22_n633
+end
+
+def fun_l21_n646()
+ fun_l22_n996
+end
+
+def fun_l21_n647()
+ fun_l22_n943
+end
+
+def fun_l21_n648()
+ fun_l22_n81
+end
+
+def fun_l21_n649()
+ fun_l22_n161
+end
+
+def fun_l21_n650()
+ fun_l22_n346
+end
+
+def fun_l21_n651()
+ fun_l22_n338
+end
+
+def fun_l21_n652()
+ fun_l22_n989
+end
+
+def fun_l21_n653()
+ fun_l22_n727
+end
+
+def fun_l21_n654()
+ fun_l22_n261
+end
+
+def fun_l21_n655()
+ fun_l22_n975
+end
+
+def fun_l21_n656()
+ fun_l22_n635
+end
+
+def fun_l21_n657()
+ fun_l22_n622
+end
+
+def fun_l21_n658()
+ fun_l22_n519
+end
+
+def fun_l21_n659()
+ fun_l22_n619
+end
+
+def fun_l21_n660()
+ fun_l22_n489
+end
+
+def fun_l21_n661()
+ fun_l22_n876
+end
+
+def fun_l21_n662()
+ fun_l22_n261
+end
+
+def fun_l21_n663()
+ fun_l22_n96
+end
+
+def fun_l21_n664()
+ fun_l22_n984
+end
+
+def fun_l21_n665()
+ fun_l22_n367
+end
+
+def fun_l21_n666()
+ fun_l22_n100
+end
+
+def fun_l21_n667()
+ fun_l22_n555
+end
+
+def fun_l21_n668()
+ fun_l22_n438
+end
+
+def fun_l21_n669()
+ fun_l22_n141
+end
+
+def fun_l21_n670()
+ fun_l22_n240
+end
+
+def fun_l21_n671()
+ fun_l22_n185
+end
+
+def fun_l21_n672()
+ fun_l22_n199
+end
+
+def fun_l21_n673()
+ fun_l22_n166
+end
+
+def fun_l21_n674()
+ fun_l22_n322
+end
+
+def fun_l21_n675()
+ fun_l22_n811
+end
+
+def fun_l21_n676()
+ fun_l22_n18
+end
+
+def fun_l21_n677()
+ fun_l22_n800
+end
+
+def fun_l21_n678()
+ fun_l22_n729
+end
+
+def fun_l21_n679()
+ fun_l22_n862
+end
+
+def fun_l21_n680()
+ fun_l22_n911
+end
+
+def fun_l21_n681()
+ fun_l22_n342
+end
+
+def fun_l21_n682()
+ fun_l22_n635
+end
+
+def fun_l21_n683()
+ fun_l22_n814
+end
+
+def fun_l21_n684()
+ fun_l22_n786
+end
+
+def fun_l21_n685()
+ fun_l22_n598
+end
+
+def fun_l21_n686()
+ fun_l22_n622
+end
+
+def fun_l21_n687()
+ fun_l22_n847
+end
+
+def fun_l21_n688()
+ fun_l22_n94
+end
+
+def fun_l21_n689()
+ fun_l22_n683
+end
+
+def fun_l21_n690()
+ fun_l22_n260
+end
+
+def fun_l21_n691()
+ fun_l22_n684
+end
+
+def fun_l21_n692()
+ fun_l22_n923
+end
+
+def fun_l21_n693()
+ fun_l22_n124
+end
+
+def fun_l21_n694()
+ fun_l22_n641
+end
+
+def fun_l21_n695()
+ fun_l22_n62
+end
+
+def fun_l21_n696()
+ fun_l22_n394
+end
+
+def fun_l21_n697()
+ fun_l22_n336
+end
+
+def fun_l21_n698()
+ fun_l22_n896
+end
+
+def fun_l21_n699()
+ fun_l22_n451
+end
+
+def fun_l21_n700()
+ fun_l22_n519
+end
+
+def fun_l21_n701()
+ fun_l22_n207
+end
+
+def fun_l21_n702()
+ fun_l22_n690
+end
+
+def fun_l21_n703()
+ fun_l22_n901
+end
+
+def fun_l21_n704()
+ fun_l22_n722
+end
+
+def fun_l21_n705()
+ fun_l22_n446
+end
+
+def fun_l21_n706()
+ fun_l22_n292
+end
+
+def fun_l21_n707()
+ fun_l22_n678
+end
+
+def fun_l21_n708()
+ fun_l22_n77
+end
+
+def fun_l21_n709()
+ fun_l22_n564
+end
+
+def fun_l21_n710()
+ fun_l22_n253
+end
+
+def fun_l21_n711()
+ fun_l22_n342
+end
+
+def fun_l21_n712()
+ fun_l22_n841
+end
+
+def fun_l21_n713()
+ fun_l22_n981
+end
+
+def fun_l21_n714()
+ fun_l22_n130
+end
+
+def fun_l21_n715()
+ fun_l22_n11
+end
+
+def fun_l21_n716()
+ fun_l22_n320
+end
+
+def fun_l21_n717()
+ fun_l22_n653
+end
+
+def fun_l21_n718()
+ fun_l22_n46
+end
+
+def fun_l21_n719()
+ fun_l22_n500
+end
+
+def fun_l21_n720()
+ fun_l22_n694
+end
+
+def fun_l21_n721()
+ fun_l22_n422
+end
+
+def fun_l21_n722()
+ fun_l22_n354
+end
+
+def fun_l21_n723()
+ fun_l22_n951
+end
+
+def fun_l21_n724()
+ fun_l22_n835
+end
+
+def fun_l21_n725()
+ fun_l22_n138
+end
+
+def fun_l21_n726()
+ fun_l22_n416
+end
+
+def fun_l21_n727()
+ fun_l22_n798
+end
+
+def fun_l21_n728()
+ fun_l22_n941
+end
+
+def fun_l21_n729()
+ fun_l22_n522
+end
+
+def fun_l21_n730()
+ fun_l22_n183
+end
+
+def fun_l21_n731()
+ fun_l22_n538
+end
+
+def fun_l21_n732()
+ fun_l22_n422
+end
+
+def fun_l21_n733()
+ fun_l22_n692
+end
+
+def fun_l21_n734()
+ fun_l22_n272
+end
+
+def fun_l21_n735()
+ fun_l22_n434
+end
+
+def fun_l21_n736()
+ fun_l22_n876
+end
+
+def fun_l21_n737()
+ fun_l22_n685
+end
+
+def fun_l21_n738()
+ fun_l22_n338
+end
+
+def fun_l21_n739()
+ fun_l22_n835
+end
+
+def fun_l21_n740()
+ fun_l22_n307
+end
+
+def fun_l21_n741()
+ fun_l22_n270
+end
+
+def fun_l21_n742()
+ fun_l22_n626
+end
+
+def fun_l21_n743()
+ fun_l22_n92
+end
+
+def fun_l21_n744()
+ fun_l22_n532
+end
+
+def fun_l21_n745()
+ fun_l22_n508
+end
+
+def fun_l21_n746()
+ fun_l22_n866
+end
+
+def fun_l21_n747()
+ fun_l22_n474
+end
+
+def fun_l21_n748()
+ fun_l22_n697
+end
+
+def fun_l21_n749()
+ fun_l22_n952
+end
+
+def fun_l21_n750()
+ fun_l22_n835
+end
+
+def fun_l21_n751()
+ fun_l22_n21
+end
+
+def fun_l21_n752()
+ fun_l22_n386
+end
+
+def fun_l21_n753()
+ fun_l22_n55
+end
+
+def fun_l21_n754()
+ fun_l22_n727
+end
+
+def fun_l21_n755()
+ fun_l22_n944
+end
+
+def fun_l21_n756()
+ fun_l22_n850
+end
+
+def fun_l21_n757()
+ fun_l22_n305
+end
+
+def fun_l21_n758()
+ fun_l22_n502
+end
+
+def fun_l21_n759()
+ fun_l22_n544
+end
+
+def fun_l21_n760()
+ fun_l22_n308
+end
+
+def fun_l21_n761()
+ fun_l22_n3
+end
+
+def fun_l21_n762()
+ fun_l22_n724
+end
+
+def fun_l21_n763()
+ fun_l22_n87
+end
+
+def fun_l21_n764()
+ fun_l22_n683
+end
+
+def fun_l21_n765()
+ fun_l22_n597
+end
+
+def fun_l21_n766()
+ fun_l22_n641
+end
+
+def fun_l21_n767()
+ fun_l22_n614
+end
+
+def fun_l21_n768()
+ fun_l22_n668
+end
+
+def fun_l21_n769()
+ fun_l22_n320
+end
+
+def fun_l21_n770()
+ fun_l22_n923
+end
+
+def fun_l21_n771()
+ fun_l22_n762
+end
+
+def fun_l21_n772()
+ fun_l22_n545
+end
+
+def fun_l21_n773()
+ fun_l22_n692
+end
+
+def fun_l21_n774()
+ fun_l22_n237
+end
+
+def fun_l21_n775()
+ fun_l22_n373
+end
+
+def fun_l21_n776()
+ fun_l22_n44
+end
+
+def fun_l21_n777()
+ fun_l22_n78
+end
+
+def fun_l21_n778()
+ fun_l22_n42
+end
+
+def fun_l21_n779()
+ fun_l22_n133
+end
+
+def fun_l21_n780()
+ fun_l22_n428
+end
+
+def fun_l21_n781()
+ fun_l22_n689
+end
+
+def fun_l21_n782()
+ fun_l22_n903
+end
+
+def fun_l21_n783()
+ fun_l22_n758
+end
+
+def fun_l21_n784()
+ fun_l22_n762
+end
+
+def fun_l21_n785()
+ fun_l22_n516
+end
+
+def fun_l21_n786()
+ fun_l22_n466
+end
+
+def fun_l21_n787()
+ fun_l22_n373
+end
+
+def fun_l21_n788()
+ fun_l22_n390
+end
+
+def fun_l21_n789()
+ fun_l22_n109
+end
+
+def fun_l21_n790()
+ fun_l22_n865
+end
+
+def fun_l21_n791()
+ fun_l22_n112
+end
+
+def fun_l21_n792()
+ fun_l22_n865
+end
+
+def fun_l21_n793()
+ fun_l22_n645
+end
+
+def fun_l21_n794()
+ fun_l22_n621
+end
+
+def fun_l21_n795()
+ fun_l22_n758
+end
+
+def fun_l21_n796()
+ fun_l22_n519
+end
+
+def fun_l21_n797()
+ fun_l22_n104
+end
+
+def fun_l21_n798()
+ fun_l22_n79
+end
+
+def fun_l21_n799()
+ fun_l22_n840
+end
+
+def fun_l21_n800()
+ fun_l22_n613
+end
+
+def fun_l21_n801()
+ fun_l22_n982
+end
+
+def fun_l21_n802()
+ fun_l22_n484
+end
+
+def fun_l21_n803()
+ fun_l22_n321
+end
+
+def fun_l21_n804()
+ fun_l22_n445
+end
+
+def fun_l21_n805()
+ fun_l22_n857
+end
+
+def fun_l21_n806()
+ fun_l22_n811
+end
+
+def fun_l21_n807()
+ fun_l22_n763
+end
+
+def fun_l21_n808()
+ fun_l22_n40
+end
+
+def fun_l21_n809()
+ fun_l22_n376
+end
+
+def fun_l21_n810()
+ fun_l22_n111
+end
+
+def fun_l21_n811()
+ fun_l22_n318
+end
+
+def fun_l21_n812()
+ fun_l22_n455
+end
+
+def fun_l21_n813()
+ fun_l22_n860
+end
+
+def fun_l21_n814()
+ fun_l22_n185
+end
+
+def fun_l21_n815()
+ fun_l22_n932
+end
+
+def fun_l21_n816()
+ fun_l22_n673
+end
+
+def fun_l21_n817()
+ fun_l22_n413
+end
+
+def fun_l21_n818()
+ fun_l22_n927
+end
+
+def fun_l21_n819()
+ fun_l22_n827
+end
+
+def fun_l21_n820()
+ fun_l22_n572
+end
+
+def fun_l21_n821()
+ fun_l22_n682
+end
+
+def fun_l21_n822()
+ fun_l22_n810
+end
+
+def fun_l21_n823()
+ fun_l22_n492
+end
+
+def fun_l21_n824()
+ fun_l22_n677
+end
+
+def fun_l21_n825()
+ fun_l22_n658
+end
+
+def fun_l21_n826()
+ fun_l22_n584
+end
+
+def fun_l21_n827()
+ fun_l22_n360
+end
+
+def fun_l21_n828()
+ fun_l22_n677
+end
+
+def fun_l21_n829()
+ fun_l22_n669
+end
+
+def fun_l21_n830()
+ fun_l22_n209
+end
+
+def fun_l21_n831()
+ fun_l22_n526
+end
+
+def fun_l21_n832()
+ fun_l22_n820
+end
+
+def fun_l21_n833()
+ fun_l22_n81
+end
+
+def fun_l21_n834()
+ fun_l22_n140
+end
+
+def fun_l21_n835()
+ fun_l22_n407
+end
+
+def fun_l21_n836()
+ fun_l22_n705
+end
+
+def fun_l21_n837()
+ fun_l22_n785
+end
+
+def fun_l21_n838()
+ fun_l22_n13
+end
+
+def fun_l21_n839()
+ fun_l22_n490
+end
+
+def fun_l21_n840()
+ fun_l22_n835
+end
+
+def fun_l21_n841()
+ fun_l22_n410
+end
+
+def fun_l21_n842()
+ fun_l22_n411
+end
+
+def fun_l21_n843()
+ fun_l22_n315
+end
+
+def fun_l21_n844()
+ fun_l22_n830
+end
+
+def fun_l21_n845()
+ fun_l22_n417
+end
+
+def fun_l21_n846()
+ fun_l22_n66
+end
+
+def fun_l21_n847()
+ fun_l22_n484
+end
+
+def fun_l21_n848()
+ fun_l22_n398
+end
+
+def fun_l21_n849()
+ fun_l22_n191
+end
+
+def fun_l21_n850()
+ fun_l22_n939
+end
+
+def fun_l21_n851()
+ fun_l22_n233
+end
+
+def fun_l21_n852()
+ fun_l22_n554
+end
+
+def fun_l21_n853()
+ fun_l22_n205
+end
+
+def fun_l21_n854()
+ fun_l22_n86
+end
+
+def fun_l21_n855()
+ fun_l22_n396
+end
+
+def fun_l21_n856()
+ fun_l22_n815
+end
+
+def fun_l21_n857()
+ fun_l22_n286
+end
+
+def fun_l21_n858()
+ fun_l22_n874
+end
+
+def fun_l21_n859()
+ fun_l22_n274
+end
+
+def fun_l21_n860()
+ fun_l22_n517
+end
+
+def fun_l21_n861()
+ fun_l22_n295
+end
+
+def fun_l21_n862()
+ fun_l22_n576
+end
+
+def fun_l21_n863()
+ fun_l22_n745
+end
+
+def fun_l21_n864()
+ fun_l22_n842
+end
+
+def fun_l21_n865()
+ fun_l22_n180
+end
+
+def fun_l21_n866()
+ fun_l22_n817
+end
+
+def fun_l21_n867()
+ fun_l22_n663
+end
+
+def fun_l21_n868()
+ fun_l22_n298
+end
+
+def fun_l21_n869()
+ fun_l22_n328
+end
+
+def fun_l21_n870()
+ fun_l22_n863
+end
+
+def fun_l21_n871()
+ fun_l22_n669
+end
+
+def fun_l21_n872()
+ fun_l22_n494
+end
+
+def fun_l21_n873()
+ fun_l22_n483
+end
+
+def fun_l21_n874()
+ fun_l22_n977
+end
+
+def fun_l21_n875()
+ fun_l22_n797
+end
+
+def fun_l21_n876()
+ fun_l22_n258
+end
+
+def fun_l21_n877()
+ fun_l22_n701
+end
+
+def fun_l21_n878()
+ fun_l22_n791
+end
+
+def fun_l21_n879()
+ fun_l22_n201
+end
+
+def fun_l21_n880()
+ fun_l22_n994
+end
+
+def fun_l21_n881()
+ fun_l22_n678
+end
+
+def fun_l21_n882()
+ fun_l22_n653
+end
+
+def fun_l21_n883()
+ fun_l22_n339
+end
+
+def fun_l21_n884()
+ fun_l22_n701
+end
+
+def fun_l21_n885()
+ fun_l22_n188
+end
+
+def fun_l21_n886()
+ fun_l22_n607
+end
+
+def fun_l21_n887()
+ fun_l22_n108
+end
+
+def fun_l21_n888()
+ fun_l22_n190
+end
+
+def fun_l21_n889()
+ fun_l22_n581
+end
+
+def fun_l21_n890()
+ fun_l22_n283
+end
+
+def fun_l21_n891()
+ fun_l22_n743
+end
+
+def fun_l21_n892()
+ fun_l22_n861
+end
+
+def fun_l21_n893()
+ fun_l22_n998
+end
+
+def fun_l21_n894()
+ fun_l22_n752
+end
+
+def fun_l21_n895()
+ fun_l22_n762
+end
+
+def fun_l21_n896()
+ fun_l22_n41
+end
+
+def fun_l21_n897()
+ fun_l22_n820
+end
+
+def fun_l21_n898()
+ fun_l22_n510
+end
+
+def fun_l21_n899()
+ fun_l22_n974
+end
+
+def fun_l21_n900()
+ fun_l22_n524
+end
+
+def fun_l21_n901()
+ fun_l22_n771
+end
+
+def fun_l21_n902()
+ fun_l22_n376
+end
+
+def fun_l21_n903()
+ fun_l22_n684
+end
+
+def fun_l21_n904()
+ fun_l22_n595
+end
+
+def fun_l21_n905()
+ fun_l22_n934
+end
+
+def fun_l21_n906()
+ fun_l22_n228
+end
+
+def fun_l21_n907()
+ fun_l22_n685
+end
+
+def fun_l21_n908()
+ fun_l22_n549
+end
+
+def fun_l21_n909()
+ fun_l22_n374
+end
+
+def fun_l21_n910()
+ fun_l22_n934
+end
+
+def fun_l21_n911()
+ fun_l22_n660
+end
+
+def fun_l21_n912()
+ fun_l22_n756
+end
+
+def fun_l21_n913()
+ fun_l22_n32
+end
+
+def fun_l21_n914()
+ fun_l22_n660
+end
+
+def fun_l21_n915()
+ fun_l22_n52
+end
+
+def fun_l21_n916()
+ fun_l22_n750
+end
+
+def fun_l21_n917()
+ fun_l22_n239
+end
+
+def fun_l21_n918()
+ fun_l22_n290
+end
+
+def fun_l21_n919()
+ fun_l22_n914
+end
+
+def fun_l21_n920()
+ fun_l22_n257
+end
+
+def fun_l21_n921()
+ fun_l22_n307
+end
+
+def fun_l21_n922()
+ fun_l22_n949
+end
+
+def fun_l21_n923()
+ fun_l22_n344
+end
+
+def fun_l21_n924()
+ fun_l22_n479
+end
+
+def fun_l21_n925()
+ fun_l22_n306
+end
+
+def fun_l21_n926()
+ fun_l22_n361
+end
+
+def fun_l21_n927()
+ fun_l22_n429
+end
+
+def fun_l21_n928()
+ fun_l22_n145
+end
+
+def fun_l21_n929()
+ fun_l22_n874
+end
+
+def fun_l21_n930()
+ fun_l22_n127
+end
+
+def fun_l21_n931()
+ fun_l22_n909
+end
+
+def fun_l21_n932()
+ fun_l22_n784
+end
+
+def fun_l21_n933()
+ fun_l22_n966
+end
+
+def fun_l21_n934()
+ fun_l22_n789
+end
+
+def fun_l21_n935()
+ fun_l22_n787
+end
+
+def fun_l21_n936()
+ fun_l22_n325
+end
+
+def fun_l21_n937()
+ fun_l22_n666
+end
+
+def fun_l21_n938()
+ fun_l22_n630
+end
+
+def fun_l21_n939()
+ fun_l22_n321
+end
+
+def fun_l21_n940()
+ fun_l22_n634
+end
+
+def fun_l21_n941()
+ fun_l22_n991
+end
+
+def fun_l21_n942()
+ fun_l22_n978
+end
+
+def fun_l21_n943()
+ fun_l22_n583
+end
+
+def fun_l21_n944()
+ fun_l22_n835
+end
+
+def fun_l21_n945()
+ fun_l22_n968
+end
+
+def fun_l21_n946()
+ fun_l22_n88
+end
+
+def fun_l21_n947()
+ fun_l22_n484
+end
+
+def fun_l21_n948()
+ fun_l22_n82
+end
+
+def fun_l21_n949()
+ fun_l22_n343
+end
+
+def fun_l21_n950()
+ fun_l22_n369
+end
+
+def fun_l21_n951()
+ fun_l22_n565
+end
+
+def fun_l21_n952()
+ fun_l22_n307
+end
+
+def fun_l21_n953()
+ fun_l22_n573
+end
+
+def fun_l21_n954()
+ fun_l22_n363
+end
+
+def fun_l21_n955()
+ fun_l22_n853
+end
+
+def fun_l21_n956()
+ fun_l22_n132
+end
+
+def fun_l21_n957()
+ fun_l22_n13
+end
+
+def fun_l21_n958()
+ fun_l22_n819
+end
+
+def fun_l21_n959()
+ fun_l22_n124
+end
+
+def fun_l21_n960()
+ fun_l22_n898
+end
+
+def fun_l21_n961()
+ fun_l22_n942
+end
+
+def fun_l21_n962()
+ fun_l22_n917
+end
+
+def fun_l21_n963()
+ fun_l22_n199
+end
+
+def fun_l21_n964()
+ fun_l22_n651
+end
+
+def fun_l21_n965()
+ fun_l22_n80
+end
+
+def fun_l21_n966()
+ fun_l22_n415
+end
+
+def fun_l21_n967()
+ fun_l22_n230
+end
+
+def fun_l21_n968()
+ fun_l22_n929
+end
+
+def fun_l21_n969()
+ fun_l22_n889
+end
+
+def fun_l21_n970()
+ fun_l22_n620
+end
+
+def fun_l21_n971()
+ fun_l22_n588
+end
+
+def fun_l21_n972()
+ fun_l22_n284
+end
+
+def fun_l21_n973()
+ fun_l22_n767
+end
+
+def fun_l21_n974()
+ fun_l22_n568
+end
+
+def fun_l21_n975()
+ fun_l22_n687
+end
+
+def fun_l21_n976()
+ fun_l22_n640
+end
+
+def fun_l21_n977()
+ fun_l22_n739
+end
+
+def fun_l21_n978()
+ fun_l22_n81
+end
+
+def fun_l21_n979()
+ fun_l22_n216
+end
+
+def fun_l21_n980()
+ fun_l22_n347
+end
+
+def fun_l21_n981()
+ fun_l22_n228
+end
+
+def fun_l21_n982()
+ fun_l22_n947
+end
+
+def fun_l21_n983()
+ fun_l22_n563
+end
+
+def fun_l21_n984()
+ fun_l22_n839
+end
+
+def fun_l21_n985()
+ fun_l22_n759
+end
+
+def fun_l21_n986()
+ fun_l22_n138
+end
+
+def fun_l21_n987()
+ fun_l22_n269
+end
+
+def fun_l21_n988()
+ fun_l22_n239
+end
+
+def fun_l21_n989()
+ fun_l22_n254
+end
+
+def fun_l21_n990()
+ fun_l22_n802
+end
+
+def fun_l21_n991()
+ fun_l22_n368
+end
+
+def fun_l21_n992()
+ fun_l22_n854
+end
+
+def fun_l21_n993()
+ fun_l22_n463
+end
+
+def fun_l21_n994()
+ fun_l22_n722
+end
+
+def fun_l21_n995()
+ fun_l22_n770
+end
+
+def fun_l21_n996()
+ fun_l22_n635
+end
+
+def fun_l21_n997()
+ fun_l22_n207
+end
+
+def fun_l21_n998()
+ fun_l22_n271
+end
+
+def fun_l21_n999()
+ fun_l22_n815
+end
+
+def fun_l22_n0()
+ fun_l23_n781
+end
+
+def fun_l22_n1()
+ fun_l23_n330
+end
+
+def fun_l22_n2()
+ fun_l23_n493
+end
+
+def fun_l22_n3()
+ fun_l23_n513
+end
+
+def fun_l22_n4()
+ fun_l23_n515
+end
+
+def fun_l22_n5()
+ fun_l23_n746
+end
+
+def fun_l22_n6()
+ fun_l23_n739
+end
+
+def fun_l22_n7()
+ fun_l23_n270
+end
+
+def fun_l22_n8()
+ fun_l23_n918
+end
+
+def fun_l22_n9()
+ fun_l23_n425
+end
+
+def fun_l22_n10()
+ fun_l23_n361
+end
+
+def fun_l22_n11()
+ fun_l23_n696
+end
+
+def fun_l22_n12()
+ fun_l23_n344
+end
+
+def fun_l22_n13()
+ fun_l23_n446
+end
+
+def fun_l22_n14()
+ fun_l23_n487
+end
+
+def fun_l22_n15()
+ fun_l23_n94
+end
+
+def fun_l22_n16()
+ fun_l23_n206
+end
+
+def fun_l22_n17()
+ fun_l23_n10
+end
+
+def fun_l22_n18()
+ fun_l23_n221
+end
+
+def fun_l22_n19()
+ fun_l23_n185
+end
+
+def fun_l22_n20()
+ fun_l23_n869
+end
+
+def fun_l22_n21()
+ fun_l23_n788
+end
+
+def fun_l22_n22()
+ fun_l23_n173
+end
+
+def fun_l22_n23()
+ fun_l23_n73
+end
+
+def fun_l22_n24()
+ fun_l23_n486
+end
+
+def fun_l22_n25()
+ fun_l23_n631
+end
+
+def fun_l22_n26()
+ fun_l23_n849
+end
+
+def fun_l22_n27()
+ fun_l23_n429
+end
+
+def fun_l22_n28()
+ fun_l23_n365
+end
+
+def fun_l22_n29()
+ fun_l23_n429
+end
+
+def fun_l22_n30()
+ fun_l23_n411
+end
+
+def fun_l22_n31()
+ fun_l23_n229
+end
+
+def fun_l22_n32()
+ fun_l23_n921
+end
+
+def fun_l22_n33()
+ fun_l23_n705
+end
+
+def fun_l22_n34()
+ fun_l23_n660
+end
+
+def fun_l22_n35()
+ fun_l23_n264
+end
+
+def fun_l22_n36()
+ fun_l23_n395
+end
+
+def fun_l22_n37()
+ fun_l23_n722
+end
+
+def fun_l22_n38()
+ fun_l23_n402
+end
+
+def fun_l22_n39()
+ fun_l23_n686
+end
+
+def fun_l22_n40()
+ fun_l23_n833
+end
+
+def fun_l22_n41()
+ fun_l23_n573
+end
+
+def fun_l22_n42()
+ fun_l23_n299
+end
+
+def fun_l22_n43()
+ fun_l23_n397
+end
+
+def fun_l22_n44()
+ fun_l23_n387
+end
+
+def fun_l22_n45()
+ fun_l23_n385
+end
+
+def fun_l22_n46()
+ fun_l23_n341
+end
+
+def fun_l22_n47()
+ fun_l23_n862
+end
+
+def fun_l22_n48()
+ fun_l23_n109
+end
+
+def fun_l22_n49()
+ fun_l23_n583
+end
+
+def fun_l22_n50()
+ fun_l23_n126
+end
+
+def fun_l22_n51()
+ fun_l23_n563
+end
+
+def fun_l22_n52()
+ fun_l23_n947
+end
+
+def fun_l22_n53()
+ fun_l23_n329
+end
+
+def fun_l22_n54()
+ fun_l23_n903
+end
+
+def fun_l22_n55()
+ fun_l23_n11
+end
+
+def fun_l22_n56()
+ fun_l23_n520
+end
+
+def fun_l22_n57()
+ fun_l23_n815
+end
+
+def fun_l22_n58()
+ fun_l23_n224
+end
+
+def fun_l22_n59()
+ fun_l23_n144
+end
+
+def fun_l22_n60()
+ fun_l23_n513
+end
+
+def fun_l22_n61()
+ fun_l23_n572
+end
+
+def fun_l22_n62()
+ fun_l23_n33
+end
+
+def fun_l22_n63()
+ fun_l23_n39
+end
+
+def fun_l22_n64()
+ fun_l23_n360
+end
+
+def fun_l22_n65()
+ fun_l23_n6
+end
+
+def fun_l22_n66()
+ fun_l23_n244
+end
+
+def fun_l22_n67()
+ fun_l23_n425
+end
+
+def fun_l22_n68()
+ fun_l23_n472
+end
+
+def fun_l22_n69()
+ fun_l23_n88
+end
+
+def fun_l22_n70()
+ fun_l23_n888
+end
+
+def fun_l22_n71()
+ fun_l23_n215
+end
+
+def fun_l22_n72()
+ fun_l23_n408
+end
+
+def fun_l22_n73()
+ fun_l23_n753
+end
+
+def fun_l22_n74()
+ fun_l23_n4
+end
+
+def fun_l22_n75()
+ fun_l23_n623
+end
+
+def fun_l22_n76()
+ fun_l23_n602
+end
+
+def fun_l22_n77()
+ fun_l23_n430
+end
+
+def fun_l22_n78()
+ fun_l23_n223
+end
+
+def fun_l22_n79()
+ fun_l23_n631
+end
+
+def fun_l22_n80()
+ fun_l23_n931
+end
+
+def fun_l22_n81()
+ fun_l23_n84
+end
+
+def fun_l22_n82()
+ fun_l23_n541
+end
+
+def fun_l22_n83()
+ fun_l23_n329
+end
+
+def fun_l22_n84()
+ fun_l23_n174
+end
+
+def fun_l22_n85()
+ fun_l23_n649
+end
+
+def fun_l22_n86()
+ fun_l23_n503
+end
+
+def fun_l22_n87()
+ fun_l23_n336
+end
+
+def fun_l22_n88()
+ fun_l23_n126
+end
+
+def fun_l22_n89()
+ fun_l23_n556
+end
+
+def fun_l22_n90()
+ fun_l23_n793
+end
+
+def fun_l22_n91()
+ fun_l23_n276
+end
+
+def fun_l22_n92()
+ fun_l23_n374
+end
+
+def fun_l22_n93()
+ fun_l23_n638
+end
+
+def fun_l22_n94()
+ fun_l23_n614
+end
+
+def fun_l22_n95()
+ fun_l23_n851
+end
+
+def fun_l22_n96()
+ fun_l23_n422
+end
+
+def fun_l22_n97()
+ fun_l23_n716
+end
+
+def fun_l22_n98()
+ fun_l23_n521
+end
+
+def fun_l22_n99()
+ fun_l23_n484
+end
+
+def fun_l22_n100()
+ fun_l23_n155
+end
+
+def fun_l22_n101()
+ fun_l23_n863
+end
+
+def fun_l22_n102()
+ fun_l23_n5
+end
+
+def fun_l22_n103()
+ fun_l23_n667
+end
+
+def fun_l22_n104()
+ fun_l23_n633
+end
+
+def fun_l22_n105()
+ fun_l23_n392
+end
+
+def fun_l22_n106()
+ fun_l23_n859
+end
+
+def fun_l22_n107()
+ fun_l23_n930
+end
+
+def fun_l22_n108()
+ fun_l23_n858
+end
+
+def fun_l22_n109()
+ fun_l23_n266
+end
+
+def fun_l22_n110()
+ fun_l23_n567
+end
+
+def fun_l22_n111()
+ fun_l23_n116
+end
+
+def fun_l22_n112()
+ fun_l23_n221
+end
+
+def fun_l22_n113()
+ fun_l23_n650
+end
+
+def fun_l22_n114()
+ fun_l23_n309
+end
+
+def fun_l22_n115()
+ fun_l23_n290
+end
+
+def fun_l22_n116()
+ fun_l23_n305
+end
+
+def fun_l22_n117()
+ fun_l23_n655
+end
+
+def fun_l22_n118()
+ fun_l23_n390
+end
+
+def fun_l22_n119()
+ fun_l23_n561
+end
+
+def fun_l22_n120()
+ fun_l23_n977
+end
+
+def fun_l22_n121()
+ fun_l23_n920
+end
+
+def fun_l22_n122()
+ fun_l23_n662
+end
+
+def fun_l22_n123()
+ fun_l23_n453
+end
+
+def fun_l22_n124()
+ fun_l23_n331
+end
+
+def fun_l22_n125()
+ fun_l23_n135
+end
+
+def fun_l22_n126()
+ fun_l23_n822
+end
+
+def fun_l22_n127()
+ fun_l23_n726
+end
+
+def fun_l22_n128()
+ fun_l23_n93
+end
+
+def fun_l22_n129()
+ fun_l23_n309
+end
+
+def fun_l22_n130()
+ fun_l23_n303
+end
+
+def fun_l22_n131()
+ fun_l23_n907
+end
+
+def fun_l22_n132()
+ fun_l23_n616
+end
+
+def fun_l22_n133()
+ fun_l23_n266
+end
+
+def fun_l22_n134()
+ fun_l23_n920
+end
+
+def fun_l22_n135()
+ fun_l23_n972
+end
+
+def fun_l22_n136()
+ fun_l23_n510
+end
+
+def fun_l22_n137()
+ fun_l23_n40
+end
+
+def fun_l22_n138()
+ fun_l23_n598
+end
+
+def fun_l22_n139()
+ fun_l23_n491
+end
+
+def fun_l22_n140()
+ fun_l23_n590
+end
+
+def fun_l22_n141()
+ fun_l23_n400
+end
+
+def fun_l22_n142()
+ fun_l23_n47
+end
+
+def fun_l22_n143()
+ fun_l23_n669
+end
+
+def fun_l22_n144()
+ fun_l23_n471
+end
+
+def fun_l22_n145()
+ fun_l23_n749
+end
+
+def fun_l22_n146()
+ fun_l23_n5
+end
+
+def fun_l22_n147()
+ fun_l23_n895
+end
+
+def fun_l22_n148()
+ fun_l23_n92
+end
+
+def fun_l22_n149()
+ fun_l23_n940
+end
+
+def fun_l22_n150()
+ fun_l23_n254
+end
+
+def fun_l22_n151()
+ fun_l23_n521
+end
+
+def fun_l22_n152()
+ fun_l23_n482
+end
+
+def fun_l22_n153()
+ fun_l23_n576
+end
+
+def fun_l22_n154()
+ fun_l23_n657
+end
+
+def fun_l22_n155()
+ fun_l23_n897
+end
+
+def fun_l22_n156()
+ fun_l23_n679
+end
+
+def fun_l22_n157()
+ fun_l23_n894
+end
+
+def fun_l22_n158()
+ fun_l23_n496
+end
+
+def fun_l22_n159()
+ fun_l23_n575
+end
+
+def fun_l22_n160()
+ fun_l23_n751
+end
+
+def fun_l22_n161()
+ fun_l23_n357
+end
+
+def fun_l22_n162()
+ fun_l23_n665
+end
+
+def fun_l22_n163()
+ fun_l23_n653
+end
+
+def fun_l22_n164()
+ fun_l23_n904
+end
+
+def fun_l22_n165()
+ fun_l23_n127
+end
+
+def fun_l22_n166()
+ fun_l23_n737
+end
+
+def fun_l22_n167()
+ fun_l23_n710
+end
+
+def fun_l22_n168()
+ fun_l23_n285
+end
+
+def fun_l22_n169()
+ fun_l23_n804
+end
+
+def fun_l22_n170()
+ fun_l23_n766
+end
+
+def fun_l22_n171()
+ fun_l23_n442
+end
+
+def fun_l22_n172()
+ fun_l23_n392
+end
+
+def fun_l22_n173()
+ fun_l23_n512
+end
+
+def fun_l22_n174()
+ fun_l23_n752
+end
+
+def fun_l22_n175()
+ fun_l23_n856
+end
+
+def fun_l22_n176()
+ fun_l23_n840
+end
+
+def fun_l22_n177()
+ fun_l23_n445
+end
+
+def fun_l22_n178()
+ fun_l23_n483
+end
+
+def fun_l22_n179()
+ fun_l23_n676
+end
+
+def fun_l22_n180()
+ fun_l23_n619
+end
+
+def fun_l22_n181()
+ fun_l23_n132
+end
+
+def fun_l22_n182()
+ fun_l23_n600
+end
+
+def fun_l22_n183()
+ fun_l23_n399
+end
+
+def fun_l22_n184()
+ fun_l23_n199
+end
+
+def fun_l22_n185()
+ fun_l23_n152
+end
+
+def fun_l22_n186()
+ fun_l23_n848
+end
+
+def fun_l22_n187()
+ fun_l23_n50
+end
+
+def fun_l22_n188()
+ fun_l23_n524
+end
+
+def fun_l22_n189()
+ fun_l23_n472
+end
+
+def fun_l22_n190()
+ fun_l23_n146
+end
+
+def fun_l22_n191()
+ fun_l23_n115
+end
+
+def fun_l22_n192()
+ fun_l23_n701
+end
+
+def fun_l22_n193()
+ fun_l23_n916
+end
+
+def fun_l22_n194()
+ fun_l23_n362
+end
+
+def fun_l22_n195()
+ fun_l23_n546
+end
+
+def fun_l22_n196()
+ fun_l23_n983
+end
+
+def fun_l22_n197()
+ fun_l23_n898
+end
+
+def fun_l22_n198()
+ fun_l23_n93
+end
+
+def fun_l22_n199()
+ fun_l23_n587
+end
+
+def fun_l22_n200()
+ fun_l23_n84
+end
+
+def fun_l22_n201()
+ fun_l23_n919
+end
+
+def fun_l22_n202()
+ fun_l23_n813
+end
+
+def fun_l22_n203()
+ fun_l23_n481
+end
+
+def fun_l22_n204()
+ fun_l23_n806
+end
+
+def fun_l22_n205()
+ fun_l23_n329
+end
+
+def fun_l22_n206()
+ fun_l23_n873
+end
+
+def fun_l22_n207()
+ fun_l23_n922
+end
+
+def fun_l22_n208()
+ fun_l23_n125
+end
+
+def fun_l22_n209()
+ fun_l23_n861
+end
+
+def fun_l22_n210()
+ fun_l23_n50
+end
+
+def fun_l22_n211()
+ fun_l23_n737
+end
+
+def fun_l22_n212()
+ fun_l23_n55
+end
+
+def fun_l22_n213()
+ fun_l23_n594
+end
+
+def fun_l22_n214()
+ fun_l23_n786
+end
+
+def fun_l22_n215()
+ fun_l23_n33
+end
+
+def fun_l22_n216()
+ fun_l23_n332
+end
+
+def fun_l22_n217()
+ fun_l23_n72
+end
+
+def fun_l22_n218()
+ fun_l23_n619
+end
+
+def fun_l22_n219()
+ fun_l23_n994
+end
+
+def fun_l22_n220()
+ fun_l23_n94
+end
+
+def fun_l22_n221()
+ fun_l23_n562
+end
+
+def fun_l22_n222()
+ fun_l23_n742
+end
+
+def fun_l22_n223()
+ fun_l23_n397
+end
+
+def fun_l22_n224()
+ fun_l23_n641
+end
+
+def fun_l22_n225()
+ fun_l23_n233
+end
+
+def fun_l22_n226()
+ fun_l23_n876
+end
+
+def fun_l22_n227()
+ fun_l23_n13
+end
+
+def fun_l22_n228()
+ fun_l23_n524
+end
+
+def fun_l22_n229()
+ fun_l23_n738
+end
+
+def fun_l22_n230()
+ fun_l23_n34
+end
+
+def fun_l22_n231()
+ fun_l23_n391
+end
+
+def fun_l22_n232()
+ fun_l23_n930
+end
+
+def fun_l22_n233()
+ fun_l23_n714
+end
+
+def fun_l22_n234()
+ fun_l23_n755
+end
+
+def fun_l22_n235()
+ fun_l23_n826
+end
+
+def fun_l22_n236()
+ fun_l23_n797
+end
+
+def fun_l22_n237()
+ fun_l23_n890
+end
+
+def fun_l22_n238()
+ fun_l23_n586
+end
+
+def fun_l22_n239()
+ fun_l23_n924
+end
+
+def fun_l22_n240()
+ fun_l23_n704
+end
+
+def fun_l22_n241()
+ fun_l23_n547
+end
+
+def fun_l22_n242()
+ fun_l23_n581
+end
+
+def fun_l22_n243()
+ fun_l23_n402
+end
+
+def fun_l22_n244()
+ fun_l23_n719
+end
+
+def fun_l22_n245()
+ fun_l23_n471
+end
+
+def fun_l22_n246()
+ fun_l23_n750
+end
+
+def fun_l22_n247()
+ fun_l23_n33
+end
+
+def fun_l22_n248()
+ fun_l23_n304
+end
+
+def fun_l22_n249()
+ fun_l23_n847
+end
+
+def fun_l22_n250()
+ fun_l23_n814
+end
+
+def fun_l22_n251()
+ fun_l23_n724
+end
+
+def fun_l22_n252()
+ fun_l23_n105
+end
+
+def fun_l22_n253()
+ fun_l23_n863
+end
+
+def fun_l22_n254()
+ fun_l23_n282
+end
+
+def fun_l22_n255()
+ fun_l23_n586
+end
+
+def fun_l22_n256()
+ fun_l23_n524
+end
+
+def fun_l22_n257()
+ fun_l23_n772
+end
+
+def fun_l22_n258()
+ fun_l23_n641
+end
+
+def fun_l22_n259()
+ fun_l23_n962
+end
+
+def fun_l22_n260()
+ fun_l23_n737
+end
+
+def fun_l22_n261()
+ fun_l23_n941
+end
+
+def fun_l22_n262()
+ fun_l23_n432
+end
+
+def fun_l22_n263()
+ fun_l23_n400
+end
+
+def fun_l22_n264()
+ fun_l23_n19
+end
+
+def fun_l22_n265()
+ fun_l23_n485
+end
+
+def fun_l22_n266()
+ fun_l23_n210
+end
+
+def fun_l22_n267()
+ fun_l23_n961
+end
+
+def fun_l22_n268()
+ fun_l23_n953
+end
+
+def fun_l22_n269()
+ fun_l23_n987
+end
+
+def fun_l22_n270()
+ fun_l23_n855
+end
+
+def fun_l22_n271()
+ fun_l23_n789
+end
+
+def fun_l22_n272()
+ fun_l23_n708
+end
+
+def fun_l22_n273()
+ fun_l23_n645
+end
+
+def fun_l22_n274()
+ fun_l23_n924
+end
+
+def fun_l22_n275()
+ fun_l23_n496
+end
+
+def fun_l22_n276()
+ fun_l23_n763
+end
+
+def fun_l22_n277()
+ fun_l23_n937
+end
+
+def fun_l22_n278()
+ fun_l23_n679
+end
+
+def fun_l22_n279()
+ fun_l23_n678
+end
+
+def fun_l22_n280()
+ fun_l23_n756
+end
+
+def fun_l22_n281()
+ fun_l23_n198
+end
+
+def fun_l22_n282()
+ fun_l23_n377
+end
+
+def fun_l22_n283()
+ fun_l23_n352
+end
+
+def fun_l22_n284()
+ fun_l23_n211
+end
+
+def fun_l22_n285()
+ fun_l23_n137
+end
+
+def fun_l22_n286()
+ fun_l23_n257
+end
+
+def fun_l22_n287()
+ fun_l23_n878
+end
+
+def fun_l22_n288()
+ fun_l23_n182
+end
+
+def fun_l22_n289()
+ fun_l23_n969
+end
+
+def fun_l22_n290()
+ fun_l23_n622
+end
+
+def fun_l22_n291()
+ fun_l23_n473
+end
+
+def fun_l22_n292()
+ fun_l23_n767
+end
+
+def fun_l22_n293()
+ fun_l23_n496
+end
+
+def fun_l22_n294()
+ fun_l23_n463
+end
+
+def fun_l22_n295()
+ fun_l23_n600
+end
+
+def fun_l22_n296()
+ fun_l23_n262
+end
+
+def fun_l22_n297()
+ fun_l23_n353
+end
+
+def fun_l22_n298()
+ fun_l23_n235
+end
+
+def fun_l22_n299()
+ fun_l23_n680
+end
+
+def fun_l22_n300()
+ fun_l23_n169
+end
+
+def fun_l22_n301()
+ fun_l23_n764
+end
+
+def fun_l22_n302()
+ fun_l23_n105
+end
+
+def fun_l22_n303()
+ fun_l23_n616
+end
+
+def fun_l22_n304()
+ fun_l23_n143
+end
+
+def fun_l22_n305()
+ fun_l23_n612
+end
+
+def fun_l22_n306()
+ fun_l23_n30
+end
+
+def fun_l22_n307()
+ fun_l23_n946
+end
+
+def fun_l22_n308()
+ fun_l23_n590
+end
+
+def fun_l22_n309()
+ fun_l23_n374
+end
+
+def fun_l22_n310()
+ fun_l23_n640
+end
+
+def fun_l22_n311()
+ fun_l23_n156
+end
+
+def fun_l22_n312()
+ fun_l23_n689
+end
+
+def fun_l22_n313()
+ fun_l23_n684
+end
+
+def fun_l22_n314()
+ fun_l23_n915
+end
+
+def fun_l22_n315()
+ fun_l23_n536
+end
+
+def fun_l22_n316()
+ fun_l23_n408
+end
+
+def fun_l22_n317()
+ fun_l23_n644
+end
+
+def fun_l22_n318()
+ fun_l23_n401
+end
+
+def fun_l22_n319()
+ fun_l23_n312
+end
+
+def fun_l22_n320()
+ fun_l23_n280
+end
+
+def fun_l22_n321()
+ fun_l23_n901
+end
+
+def fun_l22_n322()
+ fun_l23_n411
+end
+
+def fun_l22_n323()
+ fun_l23_n709
+end
+
+def fun_l22_n324()
+ fun_l23_n829
+end
+
+def fun_l22_n325()
+ fun_l23_n353
+end
+
+def fun_l22_n326()
+ fun_l23_n408
+end
+
+def fun_l22_n327()
+ fun_l23_n786
+end
+
+def fun_l22_n328()
+ fun_l23_n980
+end
+
+def fun_l22_n329()
+ fun_l23_n60
+end
+
+def fun_l22_n330()
+ fun_l23_n367
+end
+
+def fun_l22_n331()
+ fun_l23_n617
+end
+
+def fun_l22_n332()
+ fun_l23_n155
+end
+
+def fun_l22_n333()
+ fun_l23_n537
+end
+
+def fun_l22_n334()
+ fun_l23_n759
+end
+
+def fun_l22_n335()
+ fun_l23_n998
+end
+
+def fun_l22_n336()
+ fun_l23_n361
+end
+
+def fun_l22_n337()
+ fun_l23_n64
+end
+
+def fun_l22_n338()
+ fun_l23_n992
+end
+
+def fun_l22_n339()
+ fun_l23_n312
+end
+
+def fun_l22_n340()
+ fun_l23_n91
+end
+
+def fun_l22_n341()
+ fun_l23_n73
+end
+
+def fun_l22_n342()
+ fun_l23_n443
+end
+
+def fun_l22_n343()
+ fun_l23_n453
+end
+
+def fun_l22_n344()
+ fun_l23_n723
+end
+
+def fun_l22_n345()
+ fun_l23_n429
+end
+
+def fun_l22_n346()
+ fun_l23_n437
+end
+
+def fun_l22_n347()
+ fun_l23_n406
+end
+
+def fun_l22_n348()
+ fun_l23_n110
+end
+
+def fun_l22_n349()
+ fun_l23_n862
+end
+
+def fun_l22_n350()
+ fun_l23_n247
+end
+
+def fun_l22_n351()
+ fun_l23_n367
+end
+
+def fun_l22_n352()
+ fun_l23_n401
+end
+
+def fun_l22_n353()
+ fun_l23_n245
+end
+
+def fun_l22_n354()
+ fun_l23_n777
+end
+
+def fun_l22_n355()
+ fun_l23_n362
+end
+
+def fun_l22_n356()
+ fun_l23_n703
+end
+
+def fun_l22_n357()
+ fun_l23_n627
+end
+
+def fun_l22_n358()
+ fun_l23_n542
+end
+
+def fun_l22_n359()
+ fun_l23_n830
+end
+
+def fun_l22_n360()
+ fun_l23_n508
+end
+
+def fun_l22_n361()
+ fun_l23_n814
+end
+
+def fun_l22_n362()
+ fun_l23_n147
+end
+
+def fun_l22_n363()
+ fun_l23_n581
+end
+
+def fun_l22_n364()
+ fun_l23_n394
+end
+
+def fun_l22_n365()
+ fun_l23_n366
+end
+
+def fun_l22_n366()
+ fun_l23_n723
+end
+
+def fun_l22_n367()
+ fun_l23_n544
+end
+
+def fun_l22_n368()
+ fun_l23_n231
+end
+
+def fun_l22_n369()
+ fun_l23_n727
+end
+
+def fun_l22_n370()
+ fun_l23_n459
+end
+
+def fun_l22_n371()
+ fun_l23_n290
+end
+
+def fun_l22_n372()
+ fun_l23_n901
+end
+
+def fun_l22_n373()
+ fun_l23_n738
+end
+
+def fun_l22_n374()
+ fun_l23_n733
+end
+
+def fun_l22_n375()
+ fun_l23_n85
+end
+
+def fun_l22_n376()
+ fun_l23_n469
+end
+
+def fun_l22_n377()
+ fun_l23_n599
+end
+
+def fun_l22_n378()
+ fun_l23_n78
+end
+
+def fun_l22_n379()
+ fun_l23_n499
+end
+
+def fun_l22_n380()
+ fun_l23_n527
+end
+
+def fun_l22_n381()
+ fun_l23_n185
+end
+
+def fun_l22_n382()
+ fun_l23_n93
+end
+
+def fun_l22_n383()
+ fun_l23_n233
+end
+
+def fun_l22_n384()
+ fun_l23_n292
+end
+
+def fun_l22_n385()
+ fun_l23_n716
+end
+
+def fun_l22_n386()
+ fun_l23_n81
+end
+
+def fun_l22_n387()
+ fun_l23_n740
+end
+
+def fun_l22_n388()
+ fun_l23_n351
+end
+
+def fun_l22_n389()
+ fun_l23_n488
+end
+
+def fun_l22_n390()
+ fun_l23_n631
+end
+
+def fun_l22_n391()
+ fun_l23_n477
+end
+
+def fun_l22_n392()
+ fun_l23_n541
+end
+
+def fun_l22_n393()
+ fun_l23_n816
+end
+
+def fun_l22_n394()
+ fun_l23_n737
+end
+
+def fun_l22_n395()
+ fun_l23_n839
+end
+
+def fun_l22_n396()
+ fun_l23_n249
+end
+
+def fun_l22_n397()
+ fun_l23_n472
+end
+
+def fun_l22_n398()
+ fun_l23_n150
+end
+
+def fun_l22_n399()
+ fun_l23_n13
+end
+
+def fun_l22_n400()
+ fun_l23_n476
+end
+
+def fun_l22_n401()
+ fun_l23_n373
+end
+
+def fun_l22_n402()
+ fun_l23_n879
+end
+
+def fun_l22_n403()
+ fun_l23_n140
+end
+
+def fun_l22_n404()
+ fun_l23_n662
+end
+
+def fun_l22_n405()
+ fun_l23_n935
+end
+
+def fun_l22_n406()
+ fun_l23_n113
+end
+
+def fun_l22_n407()
+ fun_l23_n731
+end
+
+def fun_l22_n408()
+ fun_l23_n488
+end
+
+def fun_l22_n409()
+ fun_l23_n35
+end
+
+def fun_l22_n410()
+ fun_l23_n872
+end
+
+def fun_l22_n411()
+ fun_l23_n651
+end
+
+def fun_l22_n412()
+ fun_l23_n53
+end
+
+def fun_l22_n413()
+ fun_l23_n329
+end
+
+def fun_l22_n414()
+ fun_l23_n215
+end
+
+def fun_l22_n415()
+ fun_l23_n125
+end
+
+def fun_l22_n416()
+ fun_l23_n722
+end
+
+def fun_l22_n417()
+ fun_l23_n102
+end
+
+def fun_l22_n418()
+ fun_l23_n648
+end
+
+def fun_l22_n419()
+ fun_l23_n122
+end
+
+def fun_l22_n420()
+ fun_l23_n998
+end
+
+def fun_l22_n421()
+ fun_l23_n730
+end
+
+def fun_l22_n422()
+ fun_l23_n148
+end
+
+def fun_l22_n423()
+ fun_l23_n773
+end
+
+def fun_l22_n424()
+ fun_l23_n737
+end
+
+def fun_l22_n425()
+ fun_l23_n383
+end
+
+def fun_l22_n426()
+ fun_l23_n423
+end
+
+def fun_l22_n427()
+ fun_l23_n655
+end
+
+def fun_l22_n428()
+ fun_l23_n573
+end
+
+def fun_l22_n429()
+ fun_l23_n717
+end
+
+def fun_l22_n430()
+ fun_l23_n617
+end
+
+def fun_l22_n431()
+ fun_l23_n575
+end
+
+def fun_l22_n432()
+ fun_l23_n62
+end
+
+def fun_l22_n433()
+ fun_l23_n31
+end
+
+def fun_l22_n434()
+ fun_l23_n812
+end
+
+def fun_l22_n435()
+ fun_l23_n332
+end
+
+def fun_l22_n436()
+ fun_l23_n380
+end
+
+def fun_l22_n437()
+ fun_l23_n5
+end
+
+def fun_l22_n438()
+ fun_l23_n668
+end
+
+def fun_l22_n439()
+ fun_l23_n439
+end
+
+def fun_l22_n440()
+ fun_l23_n878
+end
+
+def fun_l22_n441()
+ fun_l23_n974
+end
+
+def fun_l22_n442()
+ fun_l23_n919
+end
+
+def fun_l22_n443()
+ fun_l23_n597
+end
+
+def fun_l22_n444()
+ fun_l23_n894
+end
+
+def fun_l22_n445()
+ fun_l23_n791
+end
+
+def fun_l22_n446()
+ fun_l23_n999
+end
+
+def fun_l22_n447()
+ fun_l23_n427
+end
+
+def fun_l22_n448()
+ fun_l23_n109
+end
+
+def fun_l22_n449()
+ fun_l23_n151
+end
+
+def fun_l22_n450()
+ fun_l23_n870
+end
+
+def fun_l22_n451()
+ fun_l23_n624
+end
+
+def fun_l22_n452()
+ fun_l23_n336
+end
+
+def fun_l22_n453()
+ fun_l23_n891
+end
+
+def fun_l22_n454()
+ fun_l23_n433
+end
+
+def fun_l22_n455()
+ fun_l23_n392
+end
+
+def fun_l22_n456()
+ fun_l23_n593
+end
+
+def fun_l22_n457()
+ fun_l23_n852
+end
+
+def fun_l22_n458()
+ fun_l23_n675
+end
+
+def fun_l22_n459()
+ fun_l23_n589
+end
+
+def fun_l22_n460()
+ fun_l23_n348
+end
+
+def fun_l22_n461()
+ fun_l23_n137
+end
+
+def fun_l22_n462()
+ fun_l23_n551
+end
+
+def fun_l22_n463()
+ fun_l23_n236
+end
+
+def fun_l22_n464()
+ fun_l23_n266
+end
+
+def fun_l22_n465()
+ fun_l23_n622
+end
+
+def fun_l22_n466()
+ fun_l23_n174
+end
+
+def fun_l22_n467()
+ fun_l23_n79
+end
+
+def fun_l22_n468()
+ fun_l23_n189
+end
+
+def fun_l22_n469()
+ fun_l23_n746
+end
+
+def fun_l22_n470()
+ fun_l23_n917
+end
+
+def fun_l22_n471()
+ fun_l23_n344
+end
+
+def fun_l22_n472()
+ fun_l23_n410
+end
+
+def fun_l22_n473()
+ fun_l23_n844
+end
+
+def fun_l22_n474()
+ fun_l23_n998
+end
+
+def fun_l22_n475()
+ fun_l23_n969
+end
+
+def fun_l22_n476()
+ fun_l23_n853
+end
+
+def fun_l22_n477()
+ fun_l23_n691
+end
+
+def fun_l22_n478()
+ fun_l23_n147
+end
+
+def fun_l22_n479()
+ fun_l23_n983
+end
+
+def fun_l22_n480()
+ fun_l23_n384
+end
+
+def fun_l22_n481()
+ fun_l23_n624
+end
+
+def fun_l22_n482()
+ fun_l23_n852
+end
+
+def fun_l22_n483()
+ fun_l23_n403
+end
+
+def fun_l22_n484()
+ fun_l23_n878
+end
+
+def fun_l22_n485()
+ fun_l23_n998
+end
+
+def fun_l22_n486()
+ fun_l23_n435
+end
+
+def fun_l22_n487()
+ fun_l23_n637
+end
+
+def fun_l22_n488()
+ fun_l23_n283
+end
+
+def fun_l22_n489()
+ fun_l23_n444
+end
+
+def fun_l22_n490()
+ fun_l23_n121
+end
+
+def fun_l22_n491()
+ fun_l23_n478
+end
+
+def fun_l22_n492()
+ fun_l23_n856
+end
+
+def fun_l22_n493()
+ fun_l23_n209
+end
+
+def fun_l22_n494()
+ fun_l23_n752
+end
+
+def fun_l22_n495()
+ fun_l23_n146
+end
+
+def fun_l22_n496()
+ fun_l23_n986
+end
+
+def fun_l22_n497()
+ fun_l23_n912
+end
+
+def fun_l22_n498()
+ fun_l23_n302
+end
+
+def fun_l22_n499()
+ fun_l23_n813
+end
+
+def fun_l22_n500()
+ fun_l23_n140
+end
+
+def fun_l22_n501()
+ fun_l23_n968
+end
+
+def fun_l22_n502()
+ fun_l23_n125
+end
+
+def fun_l22_n503()
+ fun_l23_n595
+end
+
+def fun_l22_n504()
+ fun_l23_n95
+end
+
+def fun_l22_n505()
+ fun_l23_n571
+end
+
+def fun_l22_n506()
+ fun_l23_n639
+end
+
+def fun_l22_n507()
+ fun_l23_n481
+end
+
+def fun_l22_n508()
+ fun_l23_n538
+end
+
+def fun_l22_n509()
+ fun_l23_n469
+end
+
+def fun_l22_n510()
+ fun_l23_n563
+end
+
+def fun_l22_n511()
+ fun_l23_n839
+end
+
+def fun_l22_n512()
+ fun_l23_n764
+end
+
+def fun_l22_n513()
+ fun_l23_n960
+end
+
+def fun_l22_n514()
+ fun_l23_n125
+end
+
+def fun_l22_n515()
+ fun_l23_n776
+end
+
+def fun_l22_n516()
+ fun_l23_n78
+end
+
+def fun_l22_n517()
+ fun_l23_n681
+end
+
+def fun_l22_n518()
+ fun_l23_n959
+end
+
+def fun_l22_n519()
+ fun_l23_n565
+end
+
+def fun_l22_n520()
+ fun_l23_n889
+end
+
+def fun_l22_n521()
+ fun_l23_n377
+end
+
+def fun_l22_n522()
+ fun_l23_n744
+end
+
+def fun_l22_n523()
+ fun_l23_n848
+end
+
+def fun_l22_n524()
+ fun_l23_n223
+end
+
+def fun_l22_n525()
+ fun_l23_n81
+end
+
+def fun_l22_n526()
+ fun_l23_n764
+end
+
+def fun_l22_n527()
+ fun_l23_n667
+end
+
+def fun_l22_n528()
+ fun_l23_n657
+end
+
+def fun_l22_n529()
+ fun_l23_n343
+end
+
+def fun_l22_n530()
+ fun_l23_n526
+end
+
+def fun_l22_n531()
+ fun_l23_n570
+end
+
+def fun_l22_n532()
+ fun_l23_n3
+end
+
+def fun_l22_n533()
+ fun_l23_n501
+end
+
+def fun_l22_n534()
+ fun_l23_n571
+end
+
+def fun_l22_n535()
+ fun_l23_n245
+end
+
+def fun_l22_n536()
+ fun_l23_n834
+end
+
+def fun_l22_n537()
+ fun_l23_n454
+end
+
+def fun_l22_n538()
+ fun_l23_n163
+end
+
+def fun_l22_n539()
+ fun_l23_n598
+end
+
+def fun_l22_n540()
+ fun_l23_n277
+end
+
+def fun_l22_n541()
+ fun_l23_n482
+end
+
+def fun_l22_n542()
+ fun_l23_n202
+end
+
+def fun_l22_n543()
+ fun_l23_n525
+end
+
+def fun_l22_n544()
+ fun_l23_n971
+end
+
+def fun_l22_n545()
+ fun_l23_n258
+end
+
+def fun_l22_n546()
+ fun_l23_n220
+end
+
+def fun_l22_n547()
+ fun_l23_n762
+end
+
+def fun_l22_n548()
+ fun_l23_n431
+end
+
+def fun_l22_n549()
+ fun_l23_n171
+end
+
+def fun_l22_n550()
+ fun_l23_n633
+end
+
+def fun_l22_n551()
+ fun_l23_n275
+end
+
+def fun_l22_n552()
+ fun_l23_n665
+end
+
+def fun_l22_n553()
+ fun_l23_n266
+end
+
+def fun_l22_n554()
+ fun_l23_n440
+end
+
+def fun_l22_n555()
+ fun_l23_n463
+end
+
+def fun_l22_n556()
+ fun_l23_n2
+end
+
+def fun_l22_n557()
+ fun_l23_n536
+end
+
+def fun_l22_n558()
+ fun_l23_n323
+end
+
+def fun_l22_n559()
+ fun_l23_n838
+end
+
+def fun_l22_n560()
+ fun_l23_n431
+end
+
+def fun_l22_n561()
+ fun_l23_n920
+end
+
+def fun_l22_n562()
+ fun_l23_n250
+end
+
+def fun_l22_n563()
+ fun_l23_n871
+end
+
+def fun_l22_n564()
+ fun_l23_n324
+end
+
+def fun_l22_n565()
+ fun_l23_n454
+end
+
+def fun_l22_n566()
+ fun_l23_n308
+end
+
+def fun_l22_n567()
+ fun_l23_n629
+end
+
+def fun_l22_n568()
+ fun_l23_n791
+end
+
+def fun_l22_n569()
+ fun_l23_n55
+end
+
+def fun_l22_n570()
+ fun_l23_n791
+end
+
+def fun_l22_n571()
+ fun_l23_n674
+end
+
+def fun_l22_n572()
+ fun_l23_n749
+end
+
+def fun_l22_n573()
+ fun_l23_n106
+end
+
+def fun_l22_n574()
+ fun_l23_n931
+end
+
+def fun_l22_n575()
+ fun_l23_n165
+end
+
+def fun_l22_n576()
+ fun_l23_n649
+end
+
+def fun_l22_n577()
+ fun_l23_n99
+end
+
+def fun_l22_n578()
+ fun_l23_n609
+end
+
+def fun_l22_n579()
+ fun_l23_n165
+end
+
+def fun_l22_n580()
+ fun_l23_n530
+end
+
+def fun_l22_n581()
+ fun_l23_n545
+end
+
+def fun_l22_n582()
+ fun_l23_n453
+end
+
+def fun_l22_n583()
+ fun_l23_n128
+end
+
+def fun_l22_n584()
+ fun_l23_n200
+end
+
+def fun_l22_n585()
+ fun_l23_n712
+end
+
+def fun_l22_n586()
+ fun_l23_n668
+end
+
+def fun_l22_n587()
+ fun_l23_n903
+end
+
+def fun_l22_n588()
+ fun_l23_n704
+end
+
+def fun_l22_n589()
+ fun_l23_n864
+end
+
+def fun_l22_n590()
+ fun_l23_n98
+end
+
+def fun_l22_n591()
+ fun_l23_n674
+end
+
+def fun_l22_n592()
+ fun_l23_n577
+end
+
+def fun_l22_n593()
+ fun_l23_n969
+end
+
+def fun_l22_n594()
+ fun_l23_n634
+end
+
+def fun_l22_n595()
+ fun_l23_n111
+end
+
+def fun_l22_n596()
+ fun_l23_n866
+end
+
+def fun_l22_n597()
+ fun_l23_n353
+end
+
+def fun_l22_n598()
+ fun_l23_n223
+end
+
+def fun_l22_n599()
+ fun_l23_n229
+end
+
+def fun_l22_n600()
+ fun_l23_n958
+end
+
+def fun_l22_n601()
+ fun_l23_n802
+end
+
+def fun_l22_n602()
+ fun_l23_n124
+end
+
+def fun_l22_n603()
+ fun_l23_n945
+end
+
+def fun_l22_n604()
+ fun_l23_n911
+end
+
+def fun_l22_n605()
+ fun_l23_n410
+end
+
+def fun_l22_n606()
+ fun_l23_n754
+end
+
+def fun_l22_n607()
+ fun_l23_n429
+end
+
+def fun_l22_n608()
+ fun_l23_n529
+end
+
+def fun_l22_n609()
+ fun_l23_n15
+end
+
+def fun_l22_n610()
+ fun_l23_n634
+end
+
+def fun_l22_n611()
+ fun_l23_n608
+end
+
+def fun_l22_n612()
+ fun_l23_n509
+end
+
+def fun_l22_n613()
+ fun_l23_n352
+end
+
+def fun_l22_n614()
+ fun_l23_n706
+end
+
+def fun_l22_n615()
+ fun_l23_n172
+end
+
+def fun_l22_n616()
+ fun_l23_n268
+end
+
+def fun_l22_n617()
+ fun_l23_n275
+end
+
+def fun_l22_n618()
+ fun_l23_n265
+end
+
+def fun_l22_n619()
+ fun_l23_n101
+end
+
+def fun_l22_n620()
+ fun_l23_n402
+end
+
+def fun_l22_n621()
+ fun_l23_n953
+end
+
+def fun_l22_n622()
+ fun_l23_n682
+end
+
+def fun_l22_n623()
+ fun_l23_n745
+end
+
+def fun_l22_n624()
+ fun_l23_n343
+end
+
+def fun_l22_n625()
+ fun_l23_n147
+end
+
+def fun_l22_n626()
+ fun_l23_n39
+end
+
+def fun_l22_n627()
+ fun_l23_n483
+end
+
+def fun_l22_n628()
+ fun_l23_n787
+end
+
+def fun_l22_n629()
+ fun_l23_n643
+end
+
+def fun_l22_n630()
+ fun_l23_n40
+end
+
+def fun_l22_n631()
+ fun_l23_n834
+end
+
+def fun_l22_n632()
+ fun_l23_n220
+end
+
+def fun_l22_n633()
+ fun_l23_n293
+end
+
+def fun_l22_n634()
+ fun_l23_n144
+end
+
+def fun_l22_n635()
+ fun_l23_n602
+end
+
+def fun_l22_n636()
+ fun_l23_n248
+end
+
+def fun_l22_n637()
+ fun_l23_n524
+end
+
+def fun_l22_n638()
+ fun_l23_n639
+end
+
+def fun_l22_n639()
+ fun_l23_n217
+end
+
+def fun_l22_n640()
+ fun_l23_n193
+end
+
+def fun_l22_n641()
+ fun_l23_n158
+end
+
+def fun_l22_n642()
+ fun_l23_n894
+end
+
+def fun_l22_n643()
+ fun_l23_n189
+end
+
+def fun_l22_n644()
+ fun_l23_n877
+end
+
+def fun_l22_n645()
+ fun_l23_n299
+end
+
+def fun_l22_n646()
+ fun_l23_n71
+end
+
+def fun_l22_n647()
+ fun_l23_n290
+end
+
+def fun_l22_n648()
+ fun_l23_n557
+end
+
+def fun_l22_n649()
+ fun_l23_n151
+end
+
+def fun_l22_n650()
+ fun_l23_n297
+end
+
+def fun_l22_n651()
+ fun_l23_n991
+end
+
+def fun_l22_n652()
+ fun_l23_n11
+end
+
+def fun_l22_n653()
+ fun_l23_n465
+end
+
+def fun_l22_n654()
+ fun_l23_n802
+end
+
+def fun_l22_n655()
+ fun_l23_n778
+end
+
+def fun_l22_n656()
+ fun_l23_n877
+end
+
+def fun_l22_n657()
+ fun_l23_n773
+end
+
+def fun_l22_n658()
+ fun_l23_n385
+end
+
+def fun_l22_n659()
+ fun_l23_n151
+end
+
+def fun_l22_n660()
+ fun_l23_n553
+end
+
+def fun_l22_n661()
+ fun_l23_n626
+end
+
+def fun_l22_n662()
+ fun_l23_n715
+end
+
+def fun_l22_n663()
+ fun_l23_n675
+end
+
+def fun_l22_n664()
+ fun_l23_n884
+end
+
+def fun_l22_n665()
+ fun_l23_n875
+end
+
+def fun_l22_n666()
+ fun_l23_n510
+end
+
+def fun_l22_n667()
+ fun_l23_n727
+end
+
+def fun_l22_n668()
+ fun_l23_n530
+end
+
+def fun_l22_n669()
+ fun_l23_n869
+end
+
+def fun_l22_n670()
+ fun_l23_n385
+end
+
+def fun_l22_n671()
+ fun_l23_n66
+end
+
+def fun_l22_n672()
+ fun_l23_n335
+end
+
+def fun_l22_n673()
+ fun_l23_n287
+end
+
+def fun_l22_n674()
+ fun_l23_n426
+end
+
+def fun_l22_n675()
+ fun_l23_n657
+end
+
+def fun_l22_n676()
+ fun_l23_n411
+end
+
+def fun_l22_n677()
+ fun_l23_n982
+end
+
+def fun_l22_n678()
+ fun_l23_n747
+end
+
+def fun_l22_n679()
+ fun_l23_n305
+end
+
+def fun_l22_n680()
+ fun_l23_n767
+end
+
+def fun_l22_n681()
+ fun_l23_n177
+end
+
+def fun_l22_n682()
+ fun_l23_n115
+end
+
+def fun_l22_n683()
+ fun_l23_n625
+end
+
+def fun_l22_n684()
+ fun_l23_n154
+end
+
+def fun_l22_n685()
+ fun_l23_n871
+end
+
+def fun_l22_n686()
+ fun_l23_n921
+end
+
+def fun_l22_n687()
+ fun_l23_n194
+end
+
+def fun_l22_n688()
+ fun_l23_n12
+end
+
+def fun_l22_n689()
+ fun_l23_n464
+end
+
+def fun_l22_n690()
+ fun_l23_n44
+end
+
+def fun_l22_n691()
+ fun_l23_n265
+end
+
+def fun_l22_n692()
+ fun_l23_n256
+end
+
+def fun_l22_n693()
+ fun_l23_n937
+end
+
+def fun_l22_n694()
+ fun_l23_n656
+end
+
+def fun_l22_n695()
+ fun_l23_n986
+end
+
+def fun_l22_n696()
+ fun_l23_n774
+end
+
+def fun_l22_n697()
+ fun_l23_n907
+end
+
+def fun_l22_n698()
+ fun_l23_n763
+end
+
+def fun_l22_n699()
+ fun_l23_n290
+end
+
+def fun_l22_n700()
+ fun_l23_n121
+end
+
+def fun_l22_n701()
+ fun_l23_n605
+end
+
+def fun_l22_n702()
+ fun_l23_n415
+end
+
+def fun_l22_n703()
+ fun_l23_n431
+end
+
+def fun_l22_n704()
+ fun_l23_n65
+end
+
+def fun_l22_n705()
+ fun_l23_n997
+end
+
+def fun_l22_n706()
+ fun_l23_n859
+end
+
+def fun_l22_n707()
+ fun_l23_n768
+end
+
+def fun_l22_n708()
+ fun_l23_n570
+end
+
+def fun_l22_n709()
+ fun_l23_n458
+end
+
+def fun_l22_n710()
+ fun_l23_n964
+end
+
+def fun_l22_n711()
+ fun_l23_n484
+end
+
+def fun_l22_n712()
+ fun_l23_n440
+end
+
+def fun_l22_n713()
+ fun_l23_n133
+end
+
+def fun_l22_n714()
+ fun_l23_n789
+end
+
+def fun_l22_n715()
+ fun_l23_n176
+end
+
+def fun_l22_n716()
+ fun_l23_n380
+end
+
+def fun_l22_n717()
+ fun_l23_n115
+end
+
+def fun_l22_n718()
+ fun_l23_n652
+end
+
+def fun_l22_n719()
+ fun_l23_n210
+end
+
+def fun_l22_n720()
+ fun_l23_n347
+end
+
+def fun_l22_n721()
+ fun_l23_n72
+end
+
+def fun_l22_n722()
+ fun_l23_n426
+end
+
+def fun_l22_n723()
+ fun_l23_n123
+end
+
+def fun_l22_n724()
+ fun_l23_n321
+end
+
+def fun_l22_n725()
+ fun_l23_n582
+end
+
+def fun_l22_n726()
+ fun_l23_n434
+end
+
+def fun_l22_n727()
+ fun_l23_n543
+end
+
+def fun_l22_n728()
+ fun_l23_n794
+end
+
+def fun_l22_n729()
+ fun_l23_n474
+end
+
+def fun_l22_n730()
+ fun_l23_n412
+end
+
+def fun_l22_n731()
+ fun_l23_n898
+end
+
+def fun_l22_n732()
+ fun_l23_n833
+end
+
+def fun_l22_n733()
+ fun_l23_n77
+end
+
+def fun_l22_n734()
+ fun_l23_n728
+end
+
+def fun_l22_n735()
+ fun_l23_n397
+end
+
+def fun_l22_n736()
+ fun_l23_n40
+end
+
+def fun_l22_n737()
+ fun_l23_n501
+end
+
+def fun_l22_n738()
+ fun_l23_n817
+end
+
+def fun_l22_n739()
+ fun_l23_n792
+end
+
+def fun_l22_n740()
+ fun_l23_n435
+end
+
+def fun_l22_n741()
+ fun_l23_n264
+end
+
+def fun_l22_n742()
+ fun_l23_n285
+end
+
+def fun_l22_n743()
+ fun_l23_n756
+end
+
+def fun_l22_n744()
+ fun_l23_n836
+end
+
+def fun_l22_n745()
+ fun_l23_n179
+end
+
+def fun_l22_n746()
+ fun_l23_n375
+end
+
+def fun_l22_n747()
+ fun_l23_n631
+end
+
+def fun_l22_n748()
+ fun_l23_n232
+end
+
+def fun_l22_n749()
+ fun_l23_n215
+end
+
+def fun_l22_n750()
+ fun_l23_n118
+end
+
+def fun_l22_n751()
+ fun_l23_n721
+end
+
+def fun_l22_n752()
+ fun_l23_n378
+end
+
+def fun_l22_n753()
+ fun_l23_n613
+end
+
+def fun_l22_n754()
+ fun_l23_n368
+end
+
+def fun_l22_n755()
+ fun_l23_n748
+end
+
+def fun_l22_n756()
+ fun_l23_n0
+end
+
+def fun_l22_n757()
+ fun_l23_n90
+end
+
+def fun_l22_n758()
+ fun_l23_n895
+end
+
+def fun_l22_n759()
+ fun_l23_n0
+end
+
+def fun_l22_n760()
+ fun_l23_n486
+end
+
+def fun_l22_n761()
+ fun_l23_n568
+end
+
+def fun_l22_n762()
+ fun_l23_n525
+end
+
+def fun_l22_n763()
+ fun_l23_n106
+end
+
+def fun_l22_n764()
+ fun_l23_n607
+end
+
+def fun_l22_n765()
+ fun_l23_n729
+end
+
+def fun_l22_n766()
+ fun_l23_n781
+end
+
+def fun_l22_n767()
+ fun_l23_n79
+end
+
+def fun_l22_n768()
+ fun_l23_n313
+end
+
+def fun_l22_n769()
+ fun_l23_n764
+end
+
+def fun_l22_n770()
+ fun_l23_n348
+end
+
+def fun_l22_n771()
+ fun_l23_n809
+end
+
+def fun_l22_n772()
+ fun_l23_n891
+end
+
+def fun_l22_n773()
+ fun_l23_n806
+end
+
+def fun_l22_n774()
+ fun_l23_n173
+end
+
+def fun_l22_n775()
+ fun_l23_n960
+end
+
+def fun_l22_n776()
+ fun_l23_n186
+end
+
+def fun_l22_n777()
+ fun_l23_n863
+end
+
+def fun_l22_n778()
+ fun_l23_n860
+end
+
+def fun_l22_n779()
+ fun_l23_n122
+end
+
+def fun_l22_n780()
+ fun_l23_n114
+end
+
+def fun_l22_n781()
+ fun_l23_n910
+end
+
+def fun_l22_n782()
+ fun_l23_n20
+end
+
+def fun_l22_n783()
+ fun_l23_n384
+end
+
+def fun_l22_n784()
+ fun_l23_n56
+end
+
+def fun_l22_n785()
+ fun_l23_n833
+end
+
+def fun_l22_n786()
+ fun_l23_n31
+end
+
+def fun_l22_n787()
+ fun_l23_n679
+end
+
+def fun_l22_n788()
+ fun_l23_n8
+end
+
+def fun_l22_n789()
+ fun_l23_n425
+end
+
+def fun_l22_n790()
+ fun_l23_n615
+end
+
+def fun_l22_n791()
+ fun_l23_n220
+end
+
+def fun_l22_n792()
+ fun_l23_n977
+end
+
+def fun_l22_n793()
+ fun_l23_n913
+end
+
+def fun_l22_n794()
+ fun_l23_n714
+end
+
+def fun_l22_n795()
+ fun_l23_n885
+end
+
+def fun_l22_n796()
+ fun_l23_n289
+end
+
+def fun_l22_n797()
+ fun_l23_n205
+end
+
+def fun_l22_n798()
+ fun_l23_n826
+end
+
+def fun_l22_n799()
+ fun_l23_n335
+end
+
+def fun_l22_n800()
+ fun_l23_n754
+end
+
+def fun_l22_n801()
+ fun_l23_n588
+end
+
+def fun_l22_n802()
+ fun_l23_n689
+end
+
+def fun_l22_n803()
+ fun_l23_n731
+end
+
+def fun_l22_n804()
+ fun_l23_n962
+end
+
+def fun_l22_n805()
+ fun_l23_n283
+end
+
+def fun_l22_n806()
+ fun_l23_n692
+end
+
+def fun_l22_n807()
+ fun_l23_n554
+end
+
+def fun_l22_n808()
+ fun_l23_n365
+end
+
+def fun_l22_n809()
+ fun_l23_n684
+end
+
+def fun_l22_n810()
+ fun_l23_n848
+end
+
+def fun_l22_n811()
+ fun_l23_n283
+end
+
+def fun_l22_n812()
+ fun_l23_n378
+end
+
+def fun_l22_n813()
+ fun_l23_n83
+end
+
+def fun_l22_n814()
+ fun_l23_n260
+end
+
+def fun_l22_n815()
+ fun_l23_n382
+end
+
+def fun_l22_n816()
+ fun_l23_n701
+end
+
+def fun_l22_n817()
+ fun_l23_n177
+end
+
+def fun_l22_n818()
+ fun_l23_n703
+end
+
+def fun_l22_n819()
+ fun_l23_n105
+end
+
+def fun_l22_n820()
+ fun_l23_n874
+end
+
+def fun_l22_n821()
+ fun_l23_n952
+end
+
+def fun_l22_n822()
+ fun_l23_n37
+end
+
+def fun_l22_n823()
+ fun_l23_n478
+end
+
+def fun_l22_n824()
+ fun_l23_n164
+end
+
+def fun_l22_n825()
+ fun_l23_n505
+end
+
+def fun_l22_n826()
+ fun_l23_n353
+end
+
+def fun_l22_n827()
+ fun_l23_n799
+end
+
+def fun_l22_n828()
+ fun_l23_n330
+end
+
+def fun_l22_n829()
+ fun_l23_n979
+end
+
+def fun_l22_n830()
+ fun_l23_n842
+end
+
+def fun_l22_n831()
+ fun_l23_n912
+end
+
+def fun_l22_n832()
+ fun_l23_n579
+end
+
+def fun_l22_n833()
+ fun_l23_n123
+end
+
+def fun_l22_n834()
+ fun_l23_n864
+end
+
+def fun_l22_n835()
+ fun_l23_n369
+end
+
+def fun_l22_n836()
+ fun_l23_n145
+end
+
+def fun_l22_n837()
+ fun_l23_n414
+end
+
+def fun_l22_n838()
+ fun_l23_n261
+end
+
+def fun_l22_n839()
+ fun_l23_n88
+end
+
+def fun_l22_n840()
+ fun_l23_n427
+end
+
+def fun_l22_n841()
+ fun_l23_n847
+end
+
+def fun_l22_n842()
+ fun_l23_n734
+end
+
+def fun_l22_n843()
+ fun_l23_n895
+end
+
+def fun_l22_n844()
+ fun_l23_n765
+end
+
+def fun_l22_n845()
+ fun_l23_n647
+end
+
+def fun_l22_n846()
+ fun_l23_n862
+end
+
+def fun_l22_n847()
+ fun_l23_n360
+end
+
+def fun_l22_n848()
+ fun_l23_n922
+end
+
+def fun_l22_n849()
+ fun_l23_n914
+end
+
+def fun_l22_n850()
+ fun_l23_n408
+end
+
+def fun_l22_n851()
+ fun_l23_n248
+end
+
+def fun_l22_n852()
+ fun_l23_n812
+end
+
+def fun_l22_n853()
+ fun_l23_n288
+end
+
+def fun_l22_n854()
+ fun_l23_n885
+end
+
+def fun_l22_n855()
+ fun_l23_n164
+end
+
+def fun_l22_n856()
+ fun_l23_n231
+end
+
+def fun_l22_n857()
+ fun_l23_n428
+end
+
+def fun_l22_n858()
+ fun_l23_n527
+end
+
+def fun_l22_n859()
+ fun_l23_n419
+end
+
+def fun_l22_n860()
+ fun_l23_n348
+end
+
+def fun_l22_n861()
+ fun_l23_n580
+end
+
+def fun_l22_n862()
+ fun_l23_n437
+end
+
+def fun_l22_n863()
+ fun_l23_n486
+end
+
+def fun_l22_n864()
+ fun_l23_n2
+end
+
+def fun_l22_n865()
+ fun_l23_n733
+end
+
+def fun_l22_n866()
+ fun_l23_n50
+end
+
+def fun_l22_n867()
+ fun_l23_n391
+end
+
+def fun_l22_n868()
+ fun_l23_n451
+end
+
+def fun_l22_n869()
+ fun_l23_n86
+end
+
+def fun_l22_n870()
+ fun_l23_n426
+end
+
+def fun_l22_n871()
+ fun_l23_n279
+end
+
+def fun_l22_n872()
+ fun_l23_n41
+end
+
+def fun_l22_n873()
+ fun_l23_n241
+end
+
+def fun_l22_n874()
+ fun_l23_n601
+end
+
+def fun_l22_n875()
+ fun_l23_n187
+end
+
+def fun_l22_n876()
+ fun_l23_n98
+end
+
+def fun_l22_n877()
+ fun_l23_n145
+end
+
+def fun_l22_n878()
+ fun_l23_n327
+end
+
+def fun_l22_n879()
+ fun_l23_n928
+end
+
+def fun_l22_n880()
+ fun_l23_n666
+end
+
+def fun_l22_n881()
+ fun_l23_n152
+end
+
+def fun_l22_n882()
+ fun_l23_n930
+end
+
+def fun_l22_n883()
+ fun_l23_n842
+end
+
+def fun_l22_n884()
+ fun_l23_n865
+end
+
+def fun_l22_n885()
+ fun_l23_n16
+end
+
+def fun_l22_n886()
+ fun_l23_n402
+end
+
+def fun_l22_n887()
+ fun_l23_n711
+end
+
+def fun_l22_n888()
+ fun_l23_n206
+end
+
+def fun_l22_n889()
+ fun_l23_n991
+end
+
+def fun_l22_n890()
+ fun_l23_n852
+end
+
+def fun_l22_n891()
+ fun_l23_n602
+end
+
+def fun_l22_n892()
+ fun_l23_n998
+end
+
+def fun_l22_n893()
+ fun_l23_n740
+end
+
+def fun_l22_n894()
+ fun_l23_n643
+end
+
+def fun_l22_n895()
+ fun_l23_n872
+end
+
+def fun_l22_n896()
+ fun_l23_n689
+end
+
+def fun_l22_n897()
+ fun_l23_n119
+end
+
+def fun_l22_n898()
+ fun_l23_n230
+end
+
+def fun_l22_n899()
+ fun_l23_n345
+end
+
+def fun_l22_n900()
+ fun_l23_n805
+end
+
+def fun_l22_n901()
+ fun_l23_n850
+end
+
+def fun_l22_n902()
+ fun_l23_n930
+end
+
+def fun_l22_n903()
+ fun_l23_n652
+end
+
+def fun_l22_n904()
+ fun_l23_n772
+end
+
+def fun_l22_n905()
+ fun_l23_n219
+end
+
+def fun_l22_n906()
+ fun_l23_n592
+end
+
+def fun_l22_n907()
+ fun_l23_n177
+end
+
+def fun_l22_n908()
+ fun_l23_n552
+end
+
+def fun_l22_n909()
+ fun_l23_n334
+end
+
+def fun_l22_n910()
+ fun_l23_n764
+end
+
+def fun_l22_n911()
+ fun_l23_n482
+end
+
+def fun_l22_n912()
+ fun_l23_n73
+end
+
+def fun_l22_n913()
+ fun_l23_n854
+end
+
+def fun_l22_n914()
+ fun_l23_n215
+end
+
+def fun_l22_n915()
+ fun_l23_n736
+end
+
+def fun_l22_n916()
+ fun_l23_n91
+end
+
+def fun_l22_n917()
+ fun_l23_n506
+end
+
+def fun_l22_n918()
+ fun_l23_n775
+end
+
+def fun_l22_n919()
+ fun_l23_n171
+end
+
+def fun_l22_n920()
+ fun_l23_n414
+end
+
+def fun_l22_n921()
+ fun_l23_n185
+end
+
+def fun_l22_n922()
+ fun_l23_n190
+end
+
+def fun_l22_n923()
+ fun_l23_n696
+end
+
+def fun_l22_n924()
+ fun_l23_n175
+end
+
+def fun_l22_n925()
+ fun_l23_n29
+end
+
+def fun_l22_n926()
+ fun_l23_n729
+end
+
+def fun_l22_n927()
+ fun_l23_n279
+end
+
+def fun_l22_n928()
+ fun_l23_n2
+end
+
+def fun_l22_n929()
+ fun_l23_n44
+end
+
+def fun_l22_n930()
+ fun_l23_n399
+end
+
+def fun_l22_n931()
+ fun_l23_n957
+end
+
+def fun_l22_n932()
+ fun_l23_n513
+end
+
+def fun_l22_n933()
+ fun_l23_n607
+end
+
+def fun_l22_n934()
+ fun_l23_n488
+end
+
+def fun_l22_n935()
+ fun_l23_n308
+end
+
+def fun_l22_n936()
+ fun_l23_n959
+end
+
+def fun_l22_n937()
+ fun_l23_n373
+end
+
+def fun_l22_n938()
+ fun_l23_n759
+end
+
+def fun_l22_n939()
+ fun_l23_n985
+end
+
+def fun_l22_n940()
+ fun_l23_n971
+end
+
+def fun_l22_n941()
+ fun_l23_n493
+end
+
+def fun_l22_n942()
+ fun_l23_n884
+end
+
+def fun_l22_n943()
+ fun_l23_n636
+end
+
+def fun_l22_n944()
+ fun_l23_n423
+end
+
+def fun_l22_n945()
+ fun_l23_n406
+end
+
+def fun_l22_n946()
+ fun_l23_n92
+end
+
+def fun_l22_n947()
+ fun_l23_n11
+end
+
+def fun_l22_n948()
+ fun_l23_n112
+end
+
+def fun_l22_n949()
+ fun_l23_n489
+end
+
+def fun_l22_n950()
+ fun_l23_n829
+end
+
+def fun_l22_n951()
+ fun_l23_n438
+end
+
+def fun_l22_n952()
+ fun_l23_n622
+end
+
+def fun_l22_n953()
+ fun_l23_n133
+end
+
+def fun_l22_n954()
+ fun_l23_n734
+end
+
+def fun_l22_n955()
+ fun_l23_n745
+end
+
+def fun_l22_n956()
+ fun_l23_n743
+end
+
+def fun_l22_n957()
+ fun_l23_n299
+end
+
+def fun_l22_n958()
+ fun_l23_n952
+end
+
+def fun_l22_n959()
+ fun_l23_n841
+end
+
+def fun_l22_n960()
+ fun_l23_n317
+end
+
+def fun_l22_n961()
+ fun_l23_n506
+end
+
+def fun_l22_n962()
+ fun_l23_n823
+end
+
+def fun_l22_n963()
+ fun_l23_n330
+end
+
+def fun_l22_n964()
+ fun_l23_n899
+end
+
+def fun_l22_n965()
+ fun_l23_n994
+end
+
+def fun_l22_n966()
+ fun_l23_n625
+end
+
+def fun_l22_n967()
+ fun_l23_n74
+end
+
+def fun_l22_n968()
+ fun_l23_n911
+end
+
+def fun_l22_n969()
+ fun_l23_n215
+end
+
+def fun_l22_n970()
+ fun_l23_n845
+end
+
+def fun_l22_n971()
+ fun_l23_n813
+end
+
+def fun_l22_n972()
+ fun_l23_n784
+end
+
+def fun_l22_n973()
+ fun_l23_n727
+end
+
+def fun_l22_n974()
+ fun_l23_n62
+end
+
+def fun_l22_n975()
+ fun_l23_n790
+end
+
+def fun_l22_n976()
+ fun_l23_n918
+end
+
+def fun_l22_n977()
+ fun_l23_n658
+end
+
+def fun_l22_n978()
+ fun_l23_n621
+end
+
+def fun_l22_n979()
+ fun_l23_n731
+end
+
+def fun_l22_n980()
+ fun_l23_n728
+end
+
+def fun_l22_n981()
+ fun_l23_n558
+end
+
+def fun_l22_n982()
+ fun_l23_n501
+end
+
+def fun_l22_n983()
+ fun_l23_n794
+end
+
+def fun_l22_n984()
+ fun_l23_n162
+end
+
+def fun_l22_n985()
+ fun_l23_n700
+end
+
+def fun_l22_n986()
+ fun_l23_n875
+end
+
+def fun_l22_n987()
+ fun_l23_n58
+end
+
+def fun_l22_n988()
+ fun_l23_n55
+end
+
+def fun_l22_n989()
+ fun_l23_n491
+end
+
+def fun_l22_n990()
+ fun_l23_n613
+end
+
+def fun_l22_n991()
+ fun_l23_n587
+end
+
+def fun_l22_n992()
+ fun_l23_n311
+end
+
+def fun_l22_n993()
+ fun_l23_n305
+end
+
+def fun_l22_n994()
+ fun_l23_n348
+end
+
+def fun_l22_n995()
+ fun_l23_n679
+end
+
+def fun_l22_n996()
+ fun_l23_n245
+end
+
+def fun_l22_n997()
+ fun_l23_n419
+end
+
+def fun_l22_n998()
+ fun_l23_n456
+end
+
+def fun_l22_n999()
+ fun_l23_n146
+end
+
+def fun_l23_n0()
+ fun_l24_n409
+end
+
+def fun_l23_n1()
+ fun_l24_n825
+end
+
+def fun_l23_n2()
+ fun_l24_n349
+end
+
+def fun_l23_n3()
+ fun_l24_n560
+end
+
+def fun_l23_n4()
+ fun_l24_n949
+end
+
+def fun_l23_n5()
+ fun_l24_n108
+end
+
+def fun_l23_n6()
+ fun_l24_n149
+end
+
+def fun_l23_n7()
+ fun_l24_n224
+end
+
+def fun_l23_n8()
+ fun_l24_n418
+end
+
+def fun_l23_n9()
+ fun_l24_n819
+end
+
+def fun_l23_n10()
+ fun_l24_n269
+end
+
+def fun_l23_n11()
+ fun_l24_n158
+end
+
+def fun_l23_n12()
+ fun_l24_n487
+end
+
+def fun_l23_n13()
+ fun_l24_n561
+end
+
+def fun_l23_n14()
+ fun_l24_n292
+end
+
+def fun_l23_n15()
+ fun_l24_n996
+end
+
+def fun_l23_n16()
+ fun_l24_n399
+end
+
+def fun_l23_n17()
+ fun_l24_n585
+end
+
+def fun_l23_n18()
+ fun_l24_n691
+end
+
+def fun_l23_n19()
+ fun_l24_n884
+end
+
+def fun_l23_n20()
+ fun_l24_n933
+end
+
+def fun_l23_n21()
+ fun_l24_n139
+end
+
+def fun_l23_n22()
+ fun_l24_n770
+end
+
+def fun_l23_n23()
+ fun_l24_n894
+end
+
+def fun_l23_n24()
+ fun_l24_n418
+end
+
+def fun_l23_n25()
+ fun_l24_n695
+end
+
+def fun_l23_n26()
+ fun_l24_n800
+end
+
+def fun_l23_n27()
+ fun_l24_n580
+end
+
+def fun_l23_n28()
+ fun_l24_n1
+end
+
+def fun_l23_n29()
+ fun_l24_n121
+end
+
+def fun_l23_n30()
+ fun_l24_n757
+end
+
+def fun_l23_n31()
+ fun_l24_n461
+end
+
+def fun_l23_n32()
+ fun_l24_n534
+end
+
+def fun_l23_n33()
+ fun_l24_n795
+end
+
+def fun_l23_n34()
+ fun_l24_n286
+end
+
+def fun_l23_n35()
+ fun_l24_n200
+end
+
+def fun_l23_n36()
+ fun_l24_n513
+end
+
+def fun_l23_n37()
+ fun_l24_n340
+end
+
+def fun_l23_n38()
+ fun_l24_n385
+end
+
+def fun_l23_n39()
+ fun_l24_n432
+end
+
+def fun_l23_n40()
+ fun_l24_n990
+end
+
+def fun_l23_n41()
+ fun_l24_n966
+end
+
+def fun_l23_n42()
+ fun_l24_n237
+end
+
+def fun_l23_n43()
+ fun_l24_n249
+end
+
+def fun_l23_n44()
+ fun_l24_n182
+end
+
+def fun_l23_n45()
+ fun_l24_n718
+end
+
+def fun_l23_n46()
+ fun_l24_n902
+end
+
+def fun_l23_n47()
+ fun_l24_n963
+end
+
+def fun_l23_n48()
+ fun_l24_n337
+end
+
+def fun_l23_n49()
+ fun_l24_n615
+end
+
+def fun_l23_n50()
+ fun_l24_n729
+end
+
+def fun_l23_n51()
+ fun_l24_n240
+end
+
+def fun_l23_n52()
+ fun_l24_n309
+end
+
+def fun_l23_n53()
+ fun_l24_n697
+end
+
+def fun_l23_n54()
+ fun_l24_n260
+end
+
+def fun_l23_n55()
+ fun_l24_n11
+end
+
+def fun_l23_n56()
+ fun_l24_n630
+end
+
+def fun_l23_n57()
+ fun_l24_n983
+end
+
+def fun_l23_n58()
+ fun_l24_n678
+end
+
+def fun_l23_n59()
+ fun_l24_n95
+end
+
+def fun_l23_n60()
+ fun_l24_n63
+end
+
+def fun_l23_n61()
+ fun_l24_n43
+end
+
+def fun_l23_n62()
+ fun_l24_n679
+end
+
+def fun_l23_n63()
+ fun_l24_n671
+end
+
+def fun_l23_n64()
+ fun_l24_n377
+end
+
+def fun_l23_n65()
+ fun_l24_n939
+end
+
+def fun_l23_n66()
+ fun_l24_n3
+end
+
+def fun_l23_n67()
+ fun_l24_n230
+end
+
+def fun_l23_n68()
+ fun_l24_n622
+end
+
+def fun_l23_n69()
+ fun_l24_n339
+end
+
+def fun_l23_n70()
+ fun_l24_n736
+end
+
+def fun_l23_n71()
+ fun_l24_n116
+end
+
+def fun_l23_n72()
+ fun_l24_n373
+end
+
+def fun_l23_n73()
+ fun_l24_n891
+end
+
+def fun_l23_n74()
+ fun_l24_n954
+end
+
+def fun_l23_n75()
+ fun_l24_n967
+end
+
+def fun_l23_n76()
+ fun_l24_n205
+end
+
+def fun_l23_n77()
+ fun_l24_n802
+end
+
+def fun_l23_n78()
+ fun_l24_n480
+end
+
+def fun_l23_n79()
+ fun_l24_n935
+end
+
+def fun_l23_n80()
+ fun_l24_n84
+end
+
+def fun_l23_n81()
+ fun_l24_n40
+end
+
+def fun_l23_n82()
+ fun_l24_n559
+end
+
+def fun_l23_n83()
+ fun_l24_n16
+end
+
+def fun_l23_n84()
+ fun_l24_n494
+end
+
+def fun_l23_n85()
+ fun_l24_n580
+end
+
+def fun_l23_n86()
+ fun_l24_n72
+end
+
+def fun_l23_n87()
+ fun_l24_n33
+end
+
+def fun_l23_n88()
+ fun_l24_n742
+end
+
+def fun_l23_n89()
+ fun_l24_n10
+end
+
+def fun_l23_n90()
+ fun_l24_n33
+end
+
+def fun_l23_n91()
+ fun_l24_n306
+end
+
+def fun_l23_n92()
+ fun_l24_n960
+end
+
+def fun_l23_n93()
+ fun_l24_n573
+end
+
+def fun_l23_n94()
+ fun_l24_n145
+end
+
+def fun_l23_n95()
+ fun_l24_n730
+end
+
+def fun_l23_n96()
+ fun_l24_n703
+end
+
+def fun_l23_n97()
+ fun_l24_n772
+end
+
+def fun_l23_n98()
+ fun_l24_n664
+end
+
+def fun_l23_n99()
+ fun_l24_n582
+end
+
+def fun_l23_n100()
+ fun_l24_n144
+end
+
+def fun_l23_n101()
+ fun_l24_n950
+end
+
+def fun_l23_n102()
+ fun_l24_n449
+end
+
+def fun_l23_n103()
+ fun_l24_n416
+end
+
+def fun_l23_n104()
+ fun_l24_n453
+end
+
+def fun_l23_n105()
+ fun_l24_n159
+end
+
+def fun_l23_n106()
+ fun_l24_n483
+end
+
+def fun_l23_n107()
+ fun_l24_n69
+end
+
+def fun_l23_n108()
+ fun_l24_n142
+end
+
+def fun_l23_n109()
+ fun_l24_n968
+end
+
+def fun_l23_n110()
+ fun_l24_n760
+end
+
+def fun_l23_n111()
+ fun_l24_n600
+end
+
+def fun_l23_n112()
+ fun_l24_n821
+end
+
+def fun_l23_n113()
+ fun_l24_n527
+end
+
+def fun_l23_n114()
+ fun_l24_n661
+end
+
+def fun_l23_n115()
+ fun_l24_n15
+end
+
+def fun_l23_n116()
+ fun_l24_n807
+end
+
+def fun_l23_n117()
+ fun_l24_n143
+end
+
+def fun_l23_n118()
+ fun_l24_n962
+end
+
+def fun_l23_n119()
+ fun_l24_n83
+end
+
+def fun_l23_n120()
+ fun_l24_n755
+end
+
+def fun_l23_n121()
+ fun_l24_n645
+end
+
+def fun_l23_n122()
+ fun_l24_n479
+end
+
+def fun_l23_n123()
+ fun_l24_n639
+end
+
+def fun_l23_n124()
+ fun_l24_n528
+end
+
+def fun_l23_n125()
+ fun_l24_n782
+end
+
+def fun_l23_n126()
+ fun_l24_n200
+end
+
+def fun_l23_n127()
+ fun_l24_n60
+end
+
+def fun_l23_n128()
+ fun_l24_n396
+end
+
+def fun_l23_n129()
+ fun_l24_n600
+end
+
+def fun_l23_n130()
+ fun_l24_n397
+end
+
+def fun_l23_n131()
+ fun_l24_n921
+end
+
+def fun_l23_n132()
+ fun_l24_n979
+end
+
+def fun_l23_n133()
+ fun_l24_n849
+end
+
+def fun_l23_n134()
+ fun_l24_n302
+end
+
+def fun_l23_n135()
+ fun_l24_n77
+end
+
+def fun_l23_n136()
+ fun_l24_n249
+end
+
+def fun_l23_n137()
+ fun_l24_n912
+end
+
+def fun_l23_n138()
+ fun_l24_n661
+end
+
+def fun_l23_n139()
+ fun_l24_n500
+end
+
+def fun_l23_n140()
+ fun_l24_n590
+end
+
+def fun_l23_n141()
+ fun_l24_n942
+end
+
+def fun_l23_n142()
+ fun_l24_n299
+end
+
+def fun_l23_n143()
+ fun_l24_n272
+end
+
+def fun_l23_n144()
+ fun_l24_n747
+end
+
+def fun_l23_n145()
+ fun_l24_n88
+end
+
+def fun_l23_n146()
+ fun_l24_n524
+end
+
+def fun_l23_n147()
+ fun_l24_n931
+end
+
+def fun_l23_n148()
+ fun_l24_n712
+end
+
+def fun_l23_n149()
+ fun_l24_n661
+end
+
+def fun_l23_n150()
+ fun_l24_n426
+end
+
+def fun_l23_n151()
+ fun_l24_n693
+end
+
+def fun_l23_n152()
+ fun_l24_n585
+end
+
+def fun_l23_n153()
+ fun_l24_n451
+end
+
+def fun_l23_n154()
+ fun_l24_n333
+end
+
+def fun_l23_n155()
+ fun_l24_n792
+end
+
+def fun_l23_n156()
+ fun_l24_n840
+end
+
+def fun_l23_n157()
+ fun_l24_n643
+end
+
+def fun_l23_n158()
+ fun_l24_n120
+end
+
+def fun_l23_n159()
+ fun_l24_n86
+end
+
+def fun_l23_n160()
+ fun_l24_n352
+end
+
+def fun_l23_n161()
+ fun_l24_n761
+end
+
+def fun_l23_n162()
+ fun_l24_n412
+end
+
+def fun_l23_n163()
+ fun_l24_n156
+end
+
+def fun_l23_n164()
+ fun_l24_n909
+end
+
+def fun_l23_n165()
+ fun_l24_n394
+end
+
+def fun_l23_n166()
+ fun_l24_n973
+end
+
+def fun_l23_n167()
+ fun_l24_n31
+end
+
+def fun_l23_n168()
+ fun_l24_n545
+end
+
+def fun_l23_n169()
+ fun_l24_n180
+end
+
+def fun_l23_n170()
+ fun_l24_n446
+end
+
+def fun_l23_n171()
+ fun_l24_n965
+end
+
+def fun_l23_n172()
+ fun_l24_n102
+end
+
+def fun_l23_n173()
+ fun_l24_n161
+end
+
+def fun_l23_n174()
+ fun_l24_n571
+end
+
+def fun_l23_n175()
+ fun_l24_n451
+end
+
+def fun_l23_n176()
+ fun_l24_n947
+end
+
+def fun_l23_n177()
+ fun_l24_n906
+end
+
+def fun_l23_n178()
+ fun_l24_n356
+end
+
+def fun_l23_n179()
+ fun_l24_n84
+end
+
+def fun_l23_n180()
+ fun_l24_n798
+end
+
+def fun_l23_n181()
+ fun_l24_n500
+end
+
+def fun_l23_n182()
+ fun_l24_n419
+end
+
+def fun_l23_n183()
+ fun_l24_n797
+end
+
+def fun_l23_n184()
+ fun_l24_n459
+end
+
+def fun_l23_n185()
+ fun_l24_n795
+end
+
+def fun_l23_n186()
+ fun_l24_n478
+end
+
+def fun_l23_n187()
+ fun_l24_n742
+end
+
+def fun_l23_n188()
+ fun_l24_n262
+end
+
+def fun_l23_n189()
+ fun_l24_n37
+end
+
+def fun_l23_n190()
+ fun_l24_n340
+end
+
+def fun_l23_n191()
+ fun_l24_n314
+end
+
+def fun_l23_n192()
+ fun_l24_n595
+end
+
+def fun_l23_n193()
+ fun_l24_n769
+end
+
+def fun_l23_n194()
+ fun_l24_n637
+end
+
+def fun_l23_n195()
+ fun_l24_n377
+end
+
+def fun_l23_n196()
+ fun_l24_n77
+end
+
+def fun_l23_n197()
+ fun_l24_n486
+end
+
+def fun_l23_n198()
+ fun_l24_n992
+end
+
+def fun_l23_n199()
+ fun_l24_n546
+end
+
+def fun_l23_n200()
+ fun_l24_n386
+end
+
+def fun_l23_n201()
+ fun_l24_n301
+end
+
+def fun_l23_n202()
+ fun_l24_n867
+end
+
+def fun_l23_n203()
+ fun_l24_n948
+end
+
+def fun_l23_n204()
+ fun_l24_n163
+end
+
+def fun_l23_n205()
+ fun_l24_n618
+end
+
+def fun_l23_n206()
+ fun_l24_n560
+end
+
+def fun_l23_n207()
+ fun_l24_n147
+end
+
+def fun_l23_n208()
+ fun_l24_n474
+end
+
+def fun_l23_n209()
+ fun_l24_n99
+end
+
+def fun_l23_n210()
+ fun_l24_n994
+end
+
+def fun_l23_n211()
+ fun_l24_n594
+end
+
+def fun_l23_n212()
+ fun_l24_n101
+end
+
+def fun_l23_n213()
+ fun_l24_n510
+end
+
+def fun_l23_n214()
+ fun_l24_n965
+end
+
+def fun_l23_n215()
+ fun_l24_n460
+end
+
+def fun_l23_n216()
+ fun_l24_n455
+end
+
+def fun_l23_n217()
+ fun_l24_n783
+end
+
+def fun_l23_n218()
+ fun_l24_n466
+end
+
+def fun_l23_n219()
+ fun_l24_n60
+end
+
+def fun_l23_n220()
+ fun_l24_n486
+end
+
+def fun_l23_n221()
+ fun_l24_n819
+end
+
+def fun_l23_n222()
+ fun_l24_n909
+end
+
+def fun_l23_n223()
+ fun_l24_n446
+end
+
+def fun_l23_n224()
+ fun_l24_n80
+end
+
+def fun_l23_n225()
+ fun_l24_n276
+end
+
+def fun_l23_n226()
+ fun_l24_n638
+end
+
+def fun_l23_n227()
+ fun_l24_n200
+end
+
+def fun_l23_n228()
+ fun_l24_n665
+end
+
+def fun_l23_n229()
+ fun_l24_n814
+end
+
+def fun_l23_n230()
+ fun_l24_n214
+end
+
+def fun_l23_n231()
+ fun_l24_n719
+end
+
+def fun_l23_n232()
+ fun_l24_n62
+end
+
+def fun_l23_n233()
+ fun_l24_n523
+end
+
+def fun_l23_n234()
+ fun_l24_n470
+end
+
+def fun_l23_n235()
+ fun_l24_n338
+end
+
+def fun_l23_n236()
+ fun_l24_n929
+end
+
+def fun_l23_n237()
+ fun_l24_n982
+end
+
+def fun_l23_n238()
+ fun_l24_n391
+end
+
+def fun_l23_n239()
+ fun_l24_n631
+end
+
+def fun_l23_n240()
+ fun_l24_n473
+end
+
+def fun_l23_n241()
+ fun_l24_n25
+end
+
+def fun_l23_n242()
+ fun_l24_n720
+end
+
+def fun_l23_n243()
+ fun_l24_n139
+end
+
+def fun_l23_n244()
+ fun_l24_n859
+end
+
+def fun_l23_n245()
+ fun_l24_n154
+end
+
+def fun_l23_n246()
+ fun_l24_n272
+end
+
+def fun_l23_n247()
+ fun_l24_n248
+end
+
+def fun_l23_n248()
+ fun_l24_n719
+end
+
+def fun_l23_n249()
+ fun_l24_n436
+end
+
+def fun_l23_n250()
+ fun_l24_n935
+end
+
+def fun_l23_n251()
+ fun_l24_n513
+end
+
+def fun_l23_n252()
+ fun_l24_n0
+end
+
+def fun_l23_n253()
+ fun_l24_n104
+end
+
+def fun_l23_n254()
+ fun_l24_n551
+end
+
+def fun_l23_n255()
+ fun_l24_n317
+end
+
+def fun_l23_n256()
+ fun_l24_n225
+end
+
+def fun_l23_n257()
+ fun_l24_n685
+end
+
+def fun_l23_n258()
+ fun_l24_n647
+end
+
+def fun_l23_n259()
+ fun_l24_n489
+end
+
+def fun_l23_n260()
+ fun_l24_n252
+end
+
+def fun_l23_n261()
+ fun_l24_n333
+end
+
+def fun_l23_n262()
+ fun_l24_n179
+end
+
+def fun_l23_n263()
+ fun_l24_n68
+end
+
+def fun_l23_n264()
+ fun_l24_n119
+end
+
+def fun_l23_n265()
+ fun_l24_n840
+end
+
+def fun_l23_n266()
+ fun_l24_n683
+end
+
+def fun_l23_n267()
+ fun_l24_n897
+end
+
+def fun_l23_n268()
+ fun_l24_n323
+end
+
+def fun_l23_n269()
+ fun_l24_n667
+end
+
+def fun_l23_n270()
+ fun_l24_n538
+end
+
+def fun_l23_n271()
+ fun_l24_n597
+end
+
+def fun_l23_n272()
+ fun_l24_n582
+end
+
+def fun_l23_n273()
+ fun_l24_n19
+end
+
+def fun_l23_n274()
+ fun_l24_n331
+end
+
+def fun_l23_n275()
+ fun_l24_n528
+end
+
+def fun_l23_n276()
+ fun_l24_n766
+end
+
+def fun_l23_n277()
+ fun_l24_n742
+end
+
+def fun_l23_n278()
+ fun_l24_n318
+end
+
+def fun_l23_n279()
+ fun_l24_n143
+end
+
+def fun_l23_n280()
+ fun_l24_n910
+end
+
+def fun_l23_n281()
+ fun_l24_n953
+end
+
+def fun_l23_n282()
+ fun_l24_n655
+end
+
+def fun_l23_n283()
+ fun_l24_n804
+end
+
+def fun_l23_n284()
+ fun_l24_n539
+end
+
+def fun_l23_n285()
+ fun_l24_n697
+end
+
+def fun_l23_n286()
+ fun_l24_n258
+end
+
+def fun_l23_n287()
+ fun_l24_n194
+end
+
+def fun_l23_n288()
+ fun_l24_n420
+end
+
+def fun_l23_n289()
+ fun_l24_n253
+end
+
+def fun_l23_n290()
+ fun_l24_n858
+end
+
+def fun_l23_n291()
+ fun_l24_n831
+end
+
+def fun_l23_n292()
+ fun_l24_n798
+end
+
+def fun_l23_n293()
+ fun_l24_n662
+end
+
+def fun_l23_n294()
+ fun_l24_n900
+end
+
+def fun_l23_n295()
+ fun_l24_n408
+end
+
+def fun_l23_n296()
+ fun_l24_n151
+end
+
+def fun_l23_n297()
+ fun_l24_n660
+end
+
+def fun_l23_n298()
+ fun_l24_n233
+end
+
+def fun_l23_n299()
+ fun_l24_n412
+end
+
+def fun_l23_n300()
+ fun_l24_n347
+end
+
+def fun_l23_n301()
+ fun_l24_n360
+end
+
+def fun_l23_n302()
+ fun_l24_n150
+end
+
+def fun_l23_n303()
+ fun_l24_n995
+end
+
+def fun_l23_n304()
+ fun_l24_n623
+end
+
+def fun_l23_n305()
+ fun_l24_n404
+end
+
+def fun_l23_n306()
+ fun_l24_n898
+end
+
+def fun_l23_n307()
+ fun_l24_n736
+end
+
+def fun_l23_n308()
+ fun_l24_n301
+end
+
+def fun_l23_n309()
+ fun_l24_n929
+end
+
+def fun_l23_n310()
+ fun_l24_n795
+end
+
+def fun_l23_n311()
+ fun_l24_n434
+end
+
+def fun_l23_n312()
+ fun_l24_n796
+end
+
+def fun_l23_n313()
+ fun_l24_n71
+end
+
+def fun_l23_n314()
+ fun_l24_n294
+end
+
+def fun_l23_n315()
+ fun_l24_n540
+end
+
+def fun_l23_n316()
+ fun_l24_n137
+end
+
+def fun_l23_n317()
+ fun_l24_n523
+end
+
+def fun_l23_n318()
+ fun_l24_n472
+end
+
+def fun_l23_n319()
+ fun_l24_n141
+end
+
+def fun_l23_n320()
+ fun_l24_n552
+end
+
+def fun_l23_n321()
+ fun_l24_n587
+end
+
+def fun_l23_n322()
+ fun_l24_n308
+end
+
+def fun_l23_n323()
+ fun_l24_n929
+end
+
+def fun_l23_n324()
+ fun_l24_n944
+end
+
+def fun_l23_n325()
+ fun_l24_n472
+end
+
+def fun_l23_n326()
+ fun_l24_n450
+end
+
+def fun_l23_n327()
+ fun_l24_n376
+end
+
+def fun_l23_n328()
+ fun_l24_n70
+end
+
+def fun_l23_n329()
+ fun_l24_n486
+end
+
+def fun_l23_n330()
+ fun_l24_n391
+end
+
+def fun_l23_n331()
+ fun_l24_n133
+end
+
+def fun_l23_n332()
+ fun_l24_n31
+end
+
+def fun_l23_n333()
+ fun_l24_n462
+end
+
+def fun_l23_n334()
+ fun_l24_n521
+end
+
+def fun_l23_n335()
+ fun_l24_n706
+end
+
+def fun_l23_n336()
+ fun_l24_n511
+end
+
+def fun_l23_n337()
+ fun_l24_n932
+end
+
+def fun_l23_n338()
+ fun_l24_n133
+end
+
+def fun_l23_n339()
+ fun_l24_n296
+end
+
+def fun_l23_n340()
+ fun_l24_n591
+end
+
+def fun_l23_n341()
+ fun_l24_n581
+end
+
+def fun_l23_n342()
+ fun_l24_n41
+end
+
+def fun_l23_n343()
+ fun_l24_n256
+end
+
+def fun_l23_n344()
+ fun_l24_n772
+end
+
+def fun_l23_n345()
+ fun_l24_n642
+end
+
+def fun_l23_n346()
+ fun_l24_n110
+end
+
+def fun_l23_n347()
+ fun_l24_n987
+end
+
+def fun_l23_n348()
+ fun_l24_n33
+end
+
+def fun_l23_n349()
+ fun_l24_n913
+end
+
+def fun_l23_n350()
+ fun_l24_n581
+end
+
+def fun_l23_n351()
+ fun_l24_n594
+end
+
+def fun_l23_n352()
+ fun_l24_n484
+end
+
+def fun_l23_n353()
+ fun_l24_n969
+end
+
+def fun_l23_n354()
+ fun_l24_n966
+end
+
+def fun_l23_n355()
+ fun_l24_n122
+end
+
+def fun_l23_n356()
+ fun_l24_n907
+end
+
+def fun_l23_n357()
+ fun_l24_n980
+end
+
+def fun_l23_n358()
+ fun_l24_n557
+end
+
+def fun_l23_n359()
+ fun_l24_n216
+end
+
+def fun_l23_n360()
+ fun_l24_n936
+end
+
+def fun_l23_n361()
+ fun_l24_n476
+end
+
+def fun_l23_n362()
+ fun_l24_n154
+end
+
+def fun_l23_n363()
+ fun_l24_n785
+end
+
+def fun_l23_n364()
+ fun_l24_n967
+end
+
+def fun_l23_n365()
+ fun_l24_n697
+end
+
+def fun_l23_n366()
+ fun_l24_n610
+end
+
+def fun_l23_n367()
+ fun_l24_n415
+end
+
+def fun_l23_n368()
+ fun_l24_n432
+end
+
+def fun_l23_n369()
+ fun_l24_n505
+end
+
+def fun_l23_n370()
+ fun_l24_n581
+end
+
+def fun_l23_n371()
+ fun_l24_n350
+end
+
+def fun_l23_n372()
+ fun_l24_n202
+end
+
+def fun_l23_n373()
+ fun_l24_n757
+end
+
+def fun_l23_n374()
+ fun_l24_n336
+end
+
+def fun_l23_n375()
+ fun_l24_n323
+end
+
+def fun_l23_n376()
+ fun_l24_n670
+end
+
+def fun_l23_n377()
+ fun_l24_n535
+end
+
+def fun_l23_n378()
+ fun_l24_n901
+end
+
+def fun_l23_n379()
+ fun_l24_n218
+end
+
+def fun_l23_n380()
+ fun_l24_n733
+end
+
+def fun_l23_n381()
+ fun_l24_n820
+end
+
+def fun_l23_n382()
+ fun_l24_n229
+end
+
+def fun_l23_n383()
+ fun_l24_n49
+end
+
+def fun_l23_n384()
+ fun_l24_n469
+end
+
+def fun_l23_n385()
+ fun_l24_n904
+end
+
+def fun_l23_n386()
+ fun_l24_n652
+end
+
+def fun_l23_n387()
+ fun_l24_n863
+end
+
+def fun_l23_n388()
+ fun_l24_n356
+end
+
+def fun_l23_n389()
+ fun_l24_n558
+end
+
+def fun_l23_n390()
+ fun_l24_n263
+end
+
+def fun_l23_n391()
+ fun_l24_n593
+end
+
+def fun_l23_n392()
+ fun_l24_n882
+end
+
+def fun_l23_n393()
+ fun_l24_n128
+end
+
+def fun_l23_n394()
+ fun_l24_n855
+end
+
+def fun_l23_n395()
+ fun_l24_n269
+end
+
+def fun_l23_n396()
+ fun_l24_n858
+end
+
+def fun_l23_n397()
+ fun_l24_n34
+end
+
+def fun_l23_n398()
+ fun_l24_n447
+end
+
+def fun_l23_n399()
+ fun_l24_n323
+end
+
+def fun_l23_n400()
+ fun_l24_n624
+end
+
+def fun_l23_n401()
+ fun_l24_n397
+end
+
+def fun_l23_n402()
+ fun_l24_n755
+end
+
+def fun_l23_n403()
+ fun_l24_n477
+end
+
+def fun_l23_n404()
+ fun_l24_n396
+end
+
+def fun_l23_n405()
+ fun_l24_n177
+end
+
+def fun_l23_n406()
+ fun_l24_n964
+end
+
+def fun_l23_n407()
+ fun_l24_n640
+end
+
+def fun_l23_n408()
+ fun_l24_n82
+end
+
+def fun_l23_n409()
+ fun_l24_n224
+end
+
+def fun_l23_n410()
+ fun_l24_n750
+end
+
+def fun_l23_n411()
+ fun_l24_n301
+end
+
+def fun_l23_n412()
+ fun_l24_n32
+end
+
+def fun_l23_n413()
+ fun_l24_n839
+end
+
+def fun_l23_n414()
+ fun_l24_n724
+end
+
+def fun_l23_n415()
+ fun_l24_n663
+end
+
+def fun_l23_n416()
+ fun_l24_n682
+end
+
+def fun_l23_n417()
+ fun_l24_n409
+end
+
+def fun_l23_n418()
+ fun_l24_n769
+end
+
+def fun_l23_n419()
+ fun_l24_n538
+end
+
+def fun_l23_n420()
+ fun_l24_n558
+end
+
+def fun_l23_n421()
+ fun_l24_n524
+end
+
+def fun_l23_n422()
+ fun_l24_n464
+end
+
+def fun_l23_n423()
+ fun_l24_n889
+end
+
+def fun_l23_n424()
+ fun_l24_n656
+end
+
+def fun_l23_n425()
+ fun_l24_n805
+end
+
+def fun_l23_n426()
+ fun_l24_n428
+end
+
+def fun_l23_n427()
+ fun_l24_n793
+end
+
+def fun_l23_n428()
+ fun_l24_n192
+end
+
+def fun_l23_n429()
+ fun_l24_n443
+end
+
+def fun_l23_n430()
+ fun_l24_n481
+end
+
+def fun_l23_n431()
+ fun_l24_n203
+end
+
+def fun_l23_n432()
+ fun_l24_n607
+end
+
+def fun_l23_n433()
+ fun_l24_n871
+end
+
+def fun_l23_n434()
+ fun_l24_n436
+end
+
+def fun_l23_n435()
+ fun_l24_n376
+end
+
+def fun_l23_n436()
+ fun_l24_n936
+end
+
+def fun_l23_n437()
+ fun_l24_n153
+end
+
+def fun_l23_n438()
+ fun_l24_n994
+end
+
+def fun_l23_n439()
+ fun_l24_n777
+end
+
+def fun_l23_n440()
+ fun_l24_n341
+end
+
+def fun_l23_n441()
+ fun_l24_n50
+end
+
+def fun_l23_n442()
+ fun_l24_n1
+end
+
+def fun_l23_n443()
+ fun_l24_n320
+end
+
+def fun_l23_n444()
+ fun_l24_n116
+end
+
+def fun_l23_n445()
+ fun_l24_n202
+end
+
+def fun_l23_n446()
+ fun_l24_n433
+end
+
+def fun_l23_n447()
+ fun_l24_n151
+end
+
+def fun_l23_n448()
+ fun_l24_n581
+end
+
+def fun_l23_n449()
+ fun_l24_n498
+end
+
+def fun_l23_n450()
+ fun_l24_n575
+end
+
+def fun_l23_n451()
+ fun_l24_n161
+end
+
+def fun_l23_n452()
+ fun_l24_n78
+end
+
+def fun_l23_n453()
+ fun_l24_n863
+end
+
+def fun_l23_n454()
+ fun_l24_n269
+end
+
+def fun_l23_n455()
+ fun_l24_n956
+end
+
+def fun_l23_n456()
+ fun_l24_n485
+end
+
+def fun_l23_n457()
+ fun_l24_n106
+end
+
+def fun_l23_n458()
+ fun_l24_n641
+end
+
+def fun_l23_n459()
+ fun_l24_n434
+end
+
+def fun_l23_n460()
+ fun_l24_n308
+end
+
+def fun_l23_n461()
+ fun_l24_n192
+end
+
+def fun_l23_n462()
+ fun_l24_n401
+end
+
+def fun_l23_n463()
+ fun_l24_n62
+end
+
+def fun_l23_n464()
+ fun_l24_n38
+end
+
+def fun_l23_n465()
+ fun_l24_n732
+end
+
+def fun_l23_n466()
+ fun_l24_n143
+end
+
+def fun_l23_n467()
+ fun_l24_n799
+end
+
+def fun_l23_n468()
+ fun_l24_n486
+end
+
+def fun_l23_n469()
+ fun_l24_n161
+end
+
+def fun_l23_n470()
+ fun_l24_n838
+end
+
+def fun_l23_n471()
+ fun_l24_n526
+end
+
+def fun_l23_n472()
+ fun_l24_n421
+end
+
+def fun_l23_n473()
+ fun_l24_n967
+end
+
+def fun_l23_n474()
+ fun_l24_n822
+end
+
+def fun_l23_n475()
+ fun_l24_n939
+end
+
+def fun_l23_n476()
+ fun_l24_n36
+end
+
+def fun_l23_n477()
+ fun_l24_n539
+end
+
+def fun_l23_n478()
+ fun_l24_n759
+end
+
+def fun_l23_n479()
+ fun_l24_n979
+end
+
+def fun_l23_n480()
+ fun_l24_n685
+end
+
+def fun_l23_n481()
+ fun_l24_n548
+end
+
+def fun_l23_n482()
+ fun_l24_n348
+end
+
+def fun_l23_n483()
+ fun_l24_n922
+end
+
+def fun_l23_n484()
+ fun_l24_n185
+end
+
+def fun_l23_n485()
+ fun_l24_n138
+end
+
+def fun_l23_n486()
+ fun_l24_n678
+end
+
+def fun_l23_n487()
+ fun_l24_n44
+end
+
+def fun_l23_n488()
+ fun_l24_n820
+end
+
+def fun_l23_n489()
+ fun_l24_n447
+end
+
+def fun_l23_n490()
+ fun_l24_n455
+end
+
+def fun_l23_n491()
+ fun_l24_n145
+end
+
+def fun_l23_n492()
+ fun_l24_n441
+end
+
+def fun_l23_n493()
+ fun_l24_n354
+end
+
+def fun_l23_n494()
+ fun_l24_n324
+end
+
+def fun_l23_n495()
+ fun_l24_n231
+end
+
+def fun_l23_n496()
+ fun_l24_n775
+end
+
+def fun_l23_n497()
+ fun_l24_n815
+end
+
+def fun_l23_n498()
+ fun_l24_n491
+end
+
+def fun_l23_n499()
+ fun_l24_n437
+end
+
+def fun_l23_n500()
+ fun_l24_n112
+end
+
+def fun_l23_n501()
+ fun_l24_n174
+end
+
+def fun_l23_n502()
+ fun_l24_n683
+end
+
+def fun_l23_n503()
+ fun_l24_n243
+end
+
+def fun_l23_n504()
+ fun_l24_n236
+end
+
+def fun_l23_n505()
+ fun_l24_n106
+end
+
+def fun_l23_n506()
+ fun_l24_n781
+end
+
+def fun_l23_n507()
+ fun_l24_n427
+end
+
+def fun_l23_n508()
+ fun_l24_n410
+end
+
+def fun_l23_n509()
+ fun_l24_n903
+end
+
+def fun_l23_n510()
+ fun_l24_n40
+end
+
+def fun_l23_n511()
+ fun_l24_n559
+end
+
+def fun_l23_n512()
+ fun_l24_n152
+end
+
+def fun_l23_n513()
+ fun_l24_n175
+end
+
+def fun_l23_n514()
+ fun_l24_n305
+end
+
+def fun_l23_n515()
+ fun_l24_n814
+end
+
+def fun_l23_n516()
+ fun_l24_n676
+end
+
+def fun_l23_n517()
+ fun_l24_n448
+end
+
+def fun_l23_n518()
+ fun_l24_n573
+end
+
+def fun_l23_n519()
+ fun_l24_n66
+end
+
+def fun_l23_n520()
+ fun_l24_n893
+end
+
+def fun_l23_n521()
+ fun_l24_n460
+end
+
+def fun_l23_n522()
+ fun_l24_n238
+end
+
+def fun_l23_n523()
+ fun_l24_n200
+end
+
+def fun_l23_n524()
+ fun_l24_n61
+end
+
+def fun_l23_n525()
+ fun_l24_n365
+end
+
+def fun_l23_n526()
+ fun_l24_n360
+end
+
+def fun_l23_n527()
+ fun_l24_n17
+end
+
+def fun_l23_n528()
+ fun_l24_n594
+end
+
+def fun_l23_n529()
+ fun_l24_n494
+end
+
+def fun_l23_n530()
+ fun_l24_n188
+end
+
+def fun_l23_n531()
+ fun_l24_n288
+end
+
+def fun_l23_n532()
+ fun_l24_n348
+end
+
+def fun_l23_n533()
+ fun_l24_n254
+end
+
+def fun_l23_n534()
+ fun_l24_n457
+end
+
+def fun_l23_n535()
+ fun_l24_n742
+end
+
+def fun_l23_n536()
+ fun_l24_n28
+end
+
+def fun_l23_n537()
+ fun_l24_n856
+end
+
+def fun_l23_n538()
+ fun_l24_n345
+end
+
+def fun_l23_n539()
+ fun_l24_n455
+end
+
+def fun_l23_n540()
+ fun_l24_n39
+end
+
+def fun_l23_n541()
+ fun_l24_n667
+end
+
+def fun_l23_n542()
+ fun_l24_n555
+end
+
+def fun_l23_n543()
+ fun_l24_n983
+end
+
+def fun_l23_n544()
+ fun_l24_n71
+end
+
+def fun_l23_n545()
+ fun_l24_n733
+end
+
+def fun_l23_n546()
+ fun_l24_n889
+end
+
+def fun_l23_n547()
+ fun_l24_n152
+end
+
+def fun_l23_n548()
+ fun_l24_n998
+end
+
+def fun_l23_n549()
+ fun_l24_n519
+end
+
+def fun_l23_n550()
+ fun_l24_n723
+end
+
+def fun_l23_n551()
+ fun_l24_n931
+end
+
+def fun_l23_n552()
+ fun_l24_n866
+end
+
+def fun_l23_n553()
+ fun_l24_n598
+end
+
+def fun_l23_n554()
+ fun_l24_n522
+end
+
+def fun_l23_n555()
+ fun_l24_n317
+end
+
+def fun_l23_n556()
+ fun_l24_n712
+end
+
+def fun_l23_n557()
+ fun_l24_n381
+end
+
+def fun_l23_n558()
+ fun_l24_n167
+end
+
+def fun_l23_n559()
+ fun_l24_n136
+end
+
+def fun_l23_n560()
+ fun_l24_n136
+end
+
+def fun_l23_n561()
+ fun_l24_n422
+end
+
+def fun_l23_n562()
+ fun_l24_n75
+end
+
+def fun_l23_n563()
+ fun_l24_n609
+end
+
+def fun_l23_n564()
+ fun_l24_n324
+end
+
+def fun_l23_n565()
+ fun_l24_n49
+end
+
+def fun_l23_n566()
+ fun_l24_n312
+end
+
+def fun_l23_n567()
+ fun_l24_n514
+end
+
+def fun_l23_n568()
+ fun_l24_n773
+end
+
+def fun_l23_n569()
+ fun_l24_n386
+end
+
+def fun_l23_n570()
+ fun_l24_n688
+end
+
+def fun_l23_n571()
+ fun_l24_n857
+end
+
+def fun_l23_n572()
+ fun_l24_n821
+end
+
+def fun_l23_n573()
+ fun_l24_n986
+end
+
+def fun_l23_n574()
+ fun_l24_n785
+end
+
+def fun_l23_n575()
+ fun_l24_n226
+end
+
+def fun_l23_n576()
+ fun_l24_n527
+end
+
+def fun_l23_n577()
+ fun_l24_n703
+end
+
+def fun_l23_n578()
+ fun_l24_n908
+end
+
+def fun_l23_n579()
+ fun_l24_n794
+end
+
+def fun_l23_n580()
+ fun_l24_n521
+end
+
+def fun_l23_n581()
+ fun_l24_n519
+end
+
+def fun_l23_n582()
+ fun_l24_n474
+end
+
+def fun_l23_n583()
+ fun_l24_n980
+end
+
+def fun_l23_n584()
+ fun_l24_n564
+end
+
+def fun_l23_n585()
+ fun_l24_n599
+end
+
+def fun_l23_n586()
+ fun_l24_n730
+end
+
+def fun_l23_n587()
+ fun_l24_n132
+end
+
+def fun_l23_n588()
+ fun_l24_n54
+end
+
+def fun_l23_n589()
+ fun_l24_n725
+end
+
+def fun_l23_n590()
+ fun_l24_n24
+end
+
+def fun_l23_n591()
+ fun_l24_n879
+end
+
+def fun_l23_n592()
+ fun_l24_n857
+end
+
+def fun_l23_n593()
+ fun_l24_n468
+end
+
+def fun_l23_n594()
+ fun_l24_n299
+end
+
+def fun_l23_n595()
+ fun_l24_n62
+end
+
+def fun_l23_n596()
+ fun_l24_n415
+end
+
+def fun_l23_n597()
+ fun_l24_n440
+end
+
+def fun_l23_n598()
+ fun_l24_n550
+end
+
+def fun_l23_n599()
+ fun_l24_n636
+end
+
+def fun_l23_n600()
+ fun_l24_n905
+end
+
+def fun_l23_n601()
+ fun_l24_n147
+end
+
+def fun_l23_n602()
+ fun_l24_n882
+end
+
+def fun_l23_n603()
+ fun_l24_n410
+end
+
+def fun_l23_n604()
+ fun_l24_n963
+end
+
+def fun_l23_n605()
+ fun_l24_n749
+end
+
+def fun_l23_n606()
+ fun_l24_n318
+end
+
+def fun_l23_n607()
+ fun_l24_n177
+end
+
+def fun_l23_n608()
+ fun_l24_n138
+end
+
+def fun_l23_n609()
+ fun_l24_n142
+end
+
+def fun_l23_n610()
+ fun_l24_n671
+end
+
+def fun_l23_n611()
+ fun_l24_n702
+end
+
+def fun_l23_n612()
+ fun_l24_n715
+end
+
+def fun_l23_n613()
+ fun_l24_n356
+end
+
+def fun_l23_n614()
+ fun_l24_n719
+end
+
+def fun_l23_n615()
+ fun_l24_n496
+end
+
+def fun_l23_n616()
+ fun_l24_n131
+end
+
+def fun_l23_n617()
+ fun_l24_n614
+end
+
+def fun_l23_n618()
+ fun_l24_n508
+end
+
+def fun_l23_n619()
+ fun_l24_n848
+end
+
+def fun_l23_n620()
+ fun_l24_n119
+end
+
+def fun_l23_n621()
+ fun_l24_n372
+end
+
+def fun_l23_n622()
+ fun_l24_n672
+end
+
+def fun_l23_n623()
+ fun_l24_n248
+end
+
+def fun_l23_n624()
+ fun_l24_n425
+end
+
+def fun_l23_n625()
+ fun_l24_n875
+end
+
+def fun_l23_n626()
+ fun_l24_n371
+end
+
+def fun_l23_n627()
+ fun_l24_n362
+end
+
+def fun_l23_n628()
+ fun_l24_n139
+end
+
+def fun_l23_n629()
+ fun_l24_n540
+end
+
+def fun_l23_n630()
+ fun_l24_n979
+end
+
+def fun_l23_n631()
+ fun_l24_n243
+end
+
+def fun_l23_n632()
+ fun_l24_n799
+end
+
+def fun_l23_n633()
+ fun_l24_n711
+end
+
+def fun_l23_n634()
+ fun_l24_n834
+end
+
+def fun_l23_n635()
+ fun_l24_n173
+end
+
+def fun_l23_n636()
+ fun_l24_n465
+end
+
+def fun_l23_n637()
+ fun_l24_n986
+end
+
+def fun_l23_n638()
+ fun_l24_n24
+end
+
+def fun_l23_n639()
+ fun_l24_n925
+end
+
+def fun_l23_n640()
+ fun_l24_n829
+end
+
+def fun_l23_n641()
+ fun_l24_n361
+end
+
+def fun_l23_n642()
+ fun_l24_n884
+end
+
+def fun_l23_n643()
+ fun_l24_n132
+end
+
+def fun_l23_n644()
+ fun_l24_n277
+end
+
+def fun_l23_n645()
+ fun_l24_n616
+end
+
+def fun_l23_n646()
+ fun_l24_n122
+end
+
+def fun_l23_n647()
+ fun_l24_n194
+end
+
+def fun_l23_n648()
+ fun_l24_n678
+end
+
+def fun_l23_n649()
+ fun_l24_n119
+end
+
+def fun_l23_n650()
+ fun_l24_n430
+end
+
+def fun_l23_n651()
+ fun_l24_n46
+end
+
+def fun_l23_n652()
+ fun_l24_n653
+end
+
+def fun_l23_n653()
+ fun_l24_n279
+end
+
+def fun_l23_n654()
+ fun_l24_n943
+end
+
+def fun_l23_n655()
+ fun_l24_n480
+end
+
+def fun_l23_n656()
+ fun_l24_n81
+end
+
+def fun_l23_n657()
+ fun_l24_n782
+end
+
+def fun_l23_n658()
+ fun_l24_n986
+end
+
+def fun_l23_n659()
+ fun_l24_n951
+end
+
+def fun_l23_n660()
+ fun_l24_n918
+end
+
+def fun_l23_n661()
+ fun_l24_n524
+end
+
+def fun_l23_n662()
+ fun_l24_n949
+end
+
+def fun_l23_n663()
+ fun_l24_n688
+end
+
+def fun_l23_n664()
+ fun_l24_n606
+end
+
+def fun_l23_n665()
+ fun_l24_n358
+end
+
+def fun_l23_n666()
+ fun_l24_n948
+end
+
+def fun_l23_n667()
+ fun_l24_n254
+end
+
+def fun_l23_n668()
+ fun_l24_n410
+end
+
+def fun_l23_n669()
+ fun_l24_n612
+end
+
+def fun_l23_n670()
+ fun_l24_n693
+end
+
+def fun_l23_n671()
+ fun_l24_n454
+end
+
+def fun_l23_n672()
+ fun_l24_n182
+end
+
+def fun_l23_n673()
+ fun_l24_n556
+end
+
+def fun_l23_n674()
+ fun_l24_n994
+end
+
+def fun_l23_n675()
+ fun_l24_n927
+end
+
+def fun_l23_n676()
+ fun_l24_n624
+end
+
+def fun_l23_n677()
+ fun_l24_n149
+end
+
+def fun_l23_n678()
+ fun_l24_n561
+end
+
+def fun_l23_n679()
+ fun_l24_n250
+end
+
+def fun_l23_n680()
+ fun_l24_n69
+end
+
+def fun_l23_n681()
+ fun_l24_n599
+end
+
+def fun_l23_n682()
+ fun_l24_n145
+end
+
+def fun_l23_n683()
+ fun_l24_n785
+end
+
+def fun_l23_n684()
+ fun_l24_n181
+end
+
+def fun_l23_n685()
+ fun_l24_n646
+end
+
+def fun_l23_n686()
+ fun_l24_n109
+end
+
+def fun_l23_n687()
+ fun_l24_n316
+end
+
+def fun_l23_n688()
+ fun_l24_n816
+end
+
+def fun_l23_n689()
+ fun_l24_n302
+end
+
+def fun_l23_n690()
+ fun_l24_n976
+end
+
+def fun_l23_n691()
+ fun_l24_n508
+end
+
+def fun_l23_n692()
+ fun_l24_n158
+end
+
+def fun_l23_n693()
+ fun_l24_n110
+end
+
+def fun_l23_n694()
+ fun_l24_n581
+end
+
+def fun_l23_n695()
+ fun_l24_n375
+end
+
+def fun_l23_n696()
+ fun_l24_n121
+end
+
+def fun_l23_n697()
+ fun_l24_n920
+end
+
+def fun_l23_n698()
+ fun_l24_n827
+end
+
+def fun_l23_n699()
+ fun_l24_n757
+end
+
+def fun_l23_n700()
+ fun_l24_n932
+end
+
+def fun_l23_n701()
+ fun_l24_n249
+end
+
+def fun_l23_n702()
+ fun_l24_n375
+end
+
+def fun_l23_n703()
+ fun_l24_n976
+end
+
+def fun_l23_n704()
+ fun_l24_n903
+end
+
+def fun_l23_n705()
+ fun_l24_n326
+end
+
+def fun_l23_n706()
+ fun_l24_n732
+end
+
+def fun_l23_n707()
+ fun_l24_n150
+end
+
+def fun_l23_n708()
+ fun_l24_n849
+end
+
+def fun_l23_n709()
+ fun_l24_n341
+end
+
+def fun_l23_n710()
+ fun_l24_n194
+end
+
+def fun_l23_n711()
+ fun_l24_n773
+end
+
+def fun_l23_n712()
+ fun_l24_n665
+end
+
+def fun_l23_n713()
+ fun_l24_n467
+end
+
+def fun_l23_n714()
+ fun_l24_n554
+end
+
+def fun_l23_n715()
+ fun_l24_n160
+end
+
+def fun_l23_n716()
+ fun_l24_n65
+end
+
+def fun_l23_n717()
+ fun_l24_n155
+end
+
+def fun_l23_n718()
+ fun_l24_n930
+end
+
+def fun_l23_n719()
+ fun_l24_n13
+end
+
+def fun_l23_n720()
+ fun_l24_n756
+end
+
+def fun_l23_n721()
+ fun_l24_n174
+end
+
+def fun_l23_n722()
+ fun_l24_n675
+end
+
+def fun_l23_n723()
+ fun_l24_n847
+end
+
+def fun_l23_n724()
+ fun_l24_n277
+end
+
+def fun_l23_n725()
+ fun_l24_n580
+end
+
+def fun_l23_n726()
+ fun_l24_n65
+end
+
+def fun_l23_n727()
+ fun_l24_n507
+end
+
+def fun_l23_n728()
+ fun_l24_n325
+end
+
+def fun_l23_n729()
+ fun_l24_n642
+end
+
+def fun_l23_n730()
+ fun_l24_n607
+end
+
+def fun_l23_n731()
+ fun_l24_n683
+end
+
+def fun_l23_n732()
+ fun_l24_n139
+end
+
+def fun_l23_n733()
+ fun_l24_n719
+end
+
+def fun_l23_n734()
+ fun_l24_n768
+end
+
+def fun_l23_n735()
+ fun_l24_n927
+end
+
+def fun_l23_n736()
+ fun_l24_n346
+end
+
+def fun_l23_n737()
+ fun_l24_n457
+end
+
+def fun_l23_n738()
+ fun_l24_n347
+end
+
+def fun_l23_n739()
+ fun_l24_n26
+end
+
+def fun_l23_n740()
+ fun_l24_n696
+end
+
+def fun_l23_n741()
+ fun_l24_n177
+end
+
+def fun_l23_n742()
+ fun_l24_n414
+end
+
+def fun_l23_n743()
+ fun_l24_n937
+end
+
+def fun_l23_n744()
+ fun_l24_n576
+end
+
+def fun_l23_n745()
+ fun_l24_n560
+end
+
+def fun_l23_n746()
+ fun_l24_n398
+end
+
+def fun_l23_n747()
+ fun_l24_n476
+end
+
+def fun_l23_n748()
+ fun_l24_n758
+end
+
+def fun_l23_n749()
+ fun_l24_n955
+end
+
+def fun_l23_n750()
+ fun_l24_n130
+end
+
+def fun_l23_n751()
+ fun_l24_n673
+end
+
+def fun_l23_n752()
+ fun_l24_n269
+end
+
+def fun_l23_n753()
+ fun_l24_n917
+end
+
+def fun_l23_n754()
+ fun_l24_n738
+end
+
+def fun_l23_n755()
+ fun_l24_n238
+end
+
+def fun_l23_n756()
+ fun_l24_n910
+end
+
+def fun_l23_n757()
+ fun_l24_n912
+end
+
+def fun_l23_n758()
+ fun_l24_n288
+end
+
+def fun_l23_n759()
+ fun_l24_n206
+end
+
+def fun_l23_n760()
+ fun_l24_n519
+end
+
+def fun_l23_n761()
+ fun_l24_n365
+end
+
+def fun_l23_n762()
+ fun_l24_n493
+end
+
+def fun_l23_n763()
+ fun_l24_n222
+end
+
+def fun_l23_n764()
+ fun_l24_n933
+end
+
+def fun_l23_n765()
+ fun_l24_n164
+end
+
+def fun_l23_n766()
+ fun_l24_n606
+end
+
+def fun_l23_n767()
+ fun_l24_n494
+end
+
+def fun_l23_n768()
+ fun_l24_n869
+end
+
+def fun_l23_n769()
+ fun_l24_n339
+end
+
+def fun_l23_n770()
+ fun_l24_n55
+end
+
+def fun_l23_n771()
+ fun_l24_n149
+end
+
+def fun_l23_n772()
+ fun_l24_n926
+end
+
+def fun_l23_n773()
+ fun_l24_n884
+end
+
+def fun_l23_n774()
+ fun_l24_n599
+end
+
+def fun_l23_n775()
+ fun_l24_n74
+end
+
+def fun_l23_n776()
+ fun_l24_n633
+end
+
+def fun_l23_n777()
+ fun_l24_n859
+end
+
+def fun_l23_n778()
+ fun_l24_n895
+end
+
+def fun_l23_n779()
+ fun_l24_n559
+end
+
+def fun_l23_n780()
+ fun_l24_n712
+end
+
+def fun_l23_n781()
+ fun_l24_n275
+end
+
+def fun_l23_n782()
+ fun_l24_n485
+end
+
+def fun_l23_n783()
+ fun_l24_n958
+end
+
+def fun_l23_n784()
+ fun_l24_n905
+end
+
+def fun_l23_n785()
+ fun_l24_n761
+end
+
+def fun_l23_n786()
+ fun_l24_n869
+end
+
+def fun_l23_n787()
+ fun_l24_n542
+end
+
+def fun_l23_n788()
+ fun_l24_n676
+end
+
+def fun_l23_n789()
+ fun_l24_n708
+end
+
+def fun_l23_n790()
+ fun_l24_n298
+end
+
+def fun_l23_n791()
+ fun_l24_n362
+end
+
+def fun_l23_n792()
+ fun_l24_n938
+end
+
+def fun_l23_n793()
+ fun_l24_n414
+end
+
+def fun_l23_n794()
+ fun_l24_n376
+end
+
+def fun_l23_n795()
+ fun_l24_n530
+end
+
+def fun_l23_n796()
+ fun_l24_n1
+end
+
+def fun_l23_n797()
+ fun_l24_n333
+end
+
+def fun_l23_n798()
+ fun_l24_n750
+end
+
+def fun_l23_n799()
+ fun_l24_n254
+end
+
+def fun_l23_n800()
+ fun_l24_n278
+end
+
+def fun_l23_n801()
+ fun_l24_n314
+end
+
+def fun_l23_n802()
+ fun_l24_n275
+end
+
+def fun_l23_n803()
+ fun_l24_n848
+end
+
+def fun_l23_n804()
+ fun_l24_n883
+end
+
+def fun_l23_n805()
+ fun_l24_n483
+end
+
+def fun_l23_n806()
+ fun_l24_n706
+end
+
+def fun_l23_n807()
+ fun_l24_n622
+end
+
+def fun_l23_n808()
+ fun_l24_n551
+end
+
+def fun_l23_n809()
+ fun_l24_n680
+end
+
+def fun_l23_n810()
+ fun_l24_n426
+end
+
+def fun_l23_n811()
+ fun_l24_n418
+end
+
+def fun_l23_n812()
+ fun_l24_n163
+end
+
+def fun_l23_n813()
+ fun_l24_n309
+end
+
+def fun_l23_n814()
+ fun_l24_n308
+end
+
+def fun_l23_n815()
+ fun_l24_n992
+end
+
+def fun_l23_n816()
+ fun_l24_n863
+end
+
+def fun_l23_n817()
+ fun_l24_n58
+end
+
+def fun_l23_n818()
+ fun_l24_n995
+end
+
+def fun_l23_n819()
+ fun_l24_n158
+end
+
+def fun_l23_n820()
+ fun_l24_n568
+end
+
+def fun_l23_n821()
+ fun_l24_n595
+end
+
+def fun_l23_n822()
+ fun_l24_n121
+end
+
+def fun_l23_n823()
+ fun_l24_n395
+end
+
+def fun_l23_n824()
+ fun_l24_n322
+end
+
+def fun_l23_n825()
+ fun_l24_n178
+end
+
+def fun_l23_n826()
+ fun_l24_n470
+end
+
+def fun_l23_n827()
+ fun_l24_n243
+end
+
+def fun_l23_n828()
+ fun_l24_n970
+end
+
+def fun_l23_n829()
+ fun_l24_n41
+end
+
+def fun_l23_n830()
+ fun_l24_n468
+end
+
+def fun_l23_n831()
+ fun_l24_n457
+end
+
+def fun_l23_n832()
+ fun_l24_n104
+end
+
+def fun_l23_n833()
+ fun_l24_n735
+end
+
+def fun_l23_n834()
+ fun_l24_n935
+end
+
+def fun_l23_n835()
+ fun_l24_n693
+end
+
+def fun_l23_n836()
+ fun_l24_n937
+end
+
+def fun_l23_n837()
+ fun_l24_n720
+end
+
+def fun_l23_n838()
+ fun_l24_n969
+end
+
+def fun_l23_n839()
+ fun_l24_n251
+end
+
+def fun_l23_n840()
+ fun_l24_n120
+end
+
+def fun_l23_n841()
+ fun_l24_n24
+end
+
+def fun_l23_n842()
+ fun_l24_n692
+end
+
+def fun_l23_n843()
+ fun_l24_n663
+end
+
+def fun_l23_n844()
+ fun_l24_n84
+end
+
+def fun_l23_n845()
+ fun_l24_n612
+end
+
+def fun_l23_n846()
+ fun_l24_n169
+end
+
+def fun_l23_n847()
+ fun_l24_n708
+end
+
+def fun_l23_n848()
+ fun_l24_n825
+end
+
+def fun_l23_n849()
+ fun_l24_n821
+end
+
+def fun_l23_n850()
+ fun_l24_n593
+end
+
+def fun_l23_n851()
+ fun_l24_n788
+end
+
+def fun_l23_n852()
+ fun_l24_n757
+end
+
+def fun_l23_n853()
+ fun_l24_n104
+end
+
+def fun_l23_n854()
+ fun_l24_n370
+end
+
+def fun_l23_n855()
+ fun_l24_n925
+end
+
+def fun_l23_n856()
+ fun_l24_n312
+end
+
+def fun_l23_n857()
+ fun_l24_n262
+end
+
+def fun_l23_n858()
+ fun_l24_n459
+end
+
+def fun_l23_n859()
+ fun_l24_n296
+end
+
+def fun_l23_n860()
+ fun_l24_n37
+end
+
+def fun_l23_n861()
+ fun_l24_n865
+end
+
+def fun_l23_n862()
+ fun_l24_n435
+end
+
+def fun_l23_n863()
+ fun_l24_n6
+end
+
+def fun_l23_n864()
+ fun_l24_n589
+end
+
+def fun_l23_n865()
+ fun_l24_n247
+end
+
+def fun_l23_n866()
+ fun_l24_n889
+end
+
+def fun_l23_n867()
+ fun_l24_n461
+end
+
+def fun_l23_n868()
+ fun_l24_n949
+end
+
+def fun_l23_n869()
+ fun_l24_n951
+end
+
+def fun_l23_n870()
+ fun_l24_n214
+end
+
+def fun_l23_n871()
+ fun_l24_n44
+end
+
+def fun_l23_n872()
+ fun_l24_n241
+end
+
+def fun_l23_n873()
+ fun_l24_n643
+end
+
+def fun_l23_n874()
+ fun_l24_n918
+end
+
+def fun_l23_n875()
+ fun_l24_n940
+end
+
+def fun_l23_n876()
+ fun_l24_n642
+end
+
+def fun_l23_n877()
+ fun_l24_n859
+end
+
+def fun_l23_n878()
+ fun_l24_n535
+end
+
+def fun_l23_n879()
+ fun_l24_n956
+end
+
+def fun_l23_n880()
+ fun_l24_n212
+end
+
+def fun_l23_n881()
+ fun_l24_n691
+end
+
+def fun_l23_n882()
+ fun_l24_n306
+end
+
+def fun_l23_n883()
+ fun_l24_n769
+end
+
+def fun_l23_n884()
+ fun_l24_n194
+end
+
+def fun_l23_n885()
+ fun_l24_n46
+end
+
+def fun_l23_n886()
+ fun_l24_n409
+end
+
+def fun_l23_n887()
+ fun_l24_n799
+end
+
+def fun_l23_n888()
+ fun_l24_n367
+end
+
+def fun_l23_n889()
+ fun_l24_n454
+end
+
+def fun_l23_n890()
+ fun_l24_n405
+end
+
+def fun_l23_n891()
+ fun_l24_n547
+end
+
+def fun_l23_n892()
+ fun_l24_n998
+end
+
+def fun_l23_n893()
+ fun_l24_n942
+end
+
+def fun_l23_n894()
+ fun_l24_n937
+end
+
+def fun_l23_n895()
+ fun_l24_n33
+end
+
+def fun_l23_n896()
+ fun_l24_n354
+end
+
+def fun_l23_n897()
+ fun_l24_n1
+end
+
+def fun_l23_n898()
+ fun_l24_n142
+end
+
+def fun_l23_n899()
+ fun_l24_n514
+end
+
+def fun_l23_n900()
+ fun_l24_n869
+end
+
+def fun_l23_n901()
+ fun_l24_n126
+end
+
+def fun_l23_n902()
+ fun_l24_n713
+end
+
+def fun_l23_n903()
+ fun_l24_n568
+end
+
+def fun_l23_n904()
+ fun_l24_n433
+end
+
+def fun_l23_n905()
+ fun_l24_n864
+end
+
+def fun_l23_n906()
+ fun_l24_n129
+end
+
+def fun_l23_n907()
+ fun_l24_n255
+end
+
+def fun_l23_n908()
+ fun_l24_n896
+end
+
+def fun_l23_n909()
+ fun_l24_n997
+end
+
+def fun_l23_n910()
+ fun_l24_n849
+end
+
+def fun_l23_n911()
+ fun_l24_n120
+end
+
+def fun_l23_n912()
+ fun_l24_n165
+end
+
+def fun_l23_n913()
+ fun_l24_n637
+end
+
+def fun_l23_n914()
+ fun_l24_n624
+end
+
+def fun_l23_n915()
+ fun_l24_n120
+end
+
+def fun_l23_n916()
+ fun_l24_n637
+end
+
+def fun_l23_n917()
+ fun_l24_n863
+end
+
+def fun_l23_n918()
+ fun_l24_n202
+end
+
+def fun_l23_n919()
+ fun_l24_n844
+end
+
+def fun_l23_n920()
+ fun_l24_n226
+end
+
+def fun_l23_n921()
+ fun_l24_n726
+end
+
+def fun_l23_n922()
+ fun_l24_n277
+end
+
+def fun_l23_n923()
+ fun_l24_n375
+end
+
+def fun_l23_n924()
+ fun_l24_n601
+end
+
+def fun_l23_n925()
+ fun_l24_n118
+end
+
+def fun_l23_n926()
+ fun_l24_n661
+end
+
+def fun_l23_n927()
+ fun_l24_n360
+end
+
+def fun_l23_n928()
+ fun_l24_n627
+end
+
+def fun_l23_n929()
+ fun_l24_n238
+end
+
+def fun_l23_n930()
+ fun_l24_n372
+end
+
+def fun_l23_n931()
+ fun_l24_n768
+end
+
+def fun_l23_n932()
+ fun_l24_n848
+end
+
+def fun_l23_n933()
+ fun_l24_n540
+end
+
+def fun_l23_n934()
+ fun_l24_n848
+end
+
+def fun_l23_n935()
+ fun_l24_n688
+end
+
+def fun_l23_n936()
+ fun_l24_n9
+end
+
+def fun_l23_n937()
+ fun_l24_n362
+end
+
+def fun_l23_n938()
+ fun_l24_n151
+end
+
+def fun_l23_n939()
+ fun_l24_n79
+end
+
+def fun_l23_n940()
+ fun_l24_n673
+end
+
+def fun_l23_n941()
+ fun_l24_n575
+end
+
+def fun_l23_n942()
+ fun_l24_n368
+end
+
+def fun_l23_n943()
+ fun_l24_n264
+end
+
+def fun_l23_n944()
+ fun_l24_n502
+end
+
+def fun_l23_n945()
+ fun_l24_n483
+end
+
+def fun_l23_n946()
+ fun_l24_n623
+end
+
+def fun_l23_n947()
+ fun_l24_n445
+end
+
+def fun_l23_n948()
+ fun_l24_n560
+end
+
+def fun_l23_n949()
+ fun_l24_n152
+end
+
+def fun_l23_n950()
+ fun_l24_n211
+end
+
+def fun_l23_n951()
+ fun_l24_n777
+end
+
+def fun_l23_n952()
+ fun_l24_n623
+end
+
+def fun_l23_n953()
+ fun_l24_n410
+end
+
+def fun_l23_n954()
+ fun_l24_n456
+end
+
+def fun_l23_n955()
+ fun_l24_n35
+end
+
+def fun_l23_n956()
+ fun_l24_n134
+end
+
+def fun_l23_n957()
+ fun_l24_n768
+end
+
+def fun_l23_n958()
+ fun_l24_n827
+end
+
+def fun_l23_n959()
+ fun_l24_n8
+end
+
+def fun_l23_n960()
+ fun_l24_n339
+end
+
+def fun_l23_n961()
+ fun_l24_n580
+end
+
+def fun_l23_n962()
+ fun_l24_n570
+end
+
+def fun_l23_n963()
+ fun_l24_n308
+end
+
+def fun_l23_n964()
+ fun_l24_n531
+end
+
+def fun_l23_n965()
+ fun_l24_n378
+end
+
+def fun_l23_n966()
+ fun_l24_n632
+end
+
+def fun_l23_n967()
+ fun_l24_n465
+end
+
+def fun_l23_n968()
+ fun_l24_n318
+end
+
+def fun_l23_n969()
+ fun_l24_n36
+end
+
+def fun_l23_n970()
+ fun_l24_n408
+end
+
+def fun_l23_n971()
+ fun_l24_n225
+end
+
+def fun_l23_n972()
+ fun_l24_n105
+end
+
+def fun_l23_n973()
+ fun_l24_n736
+end
+
+def fun_l23_n974()
+ fun_l24_n735
+end
+
+def fun_l23_n975()
+ fun_l24_n811
+end
+
+def fun_l23_n976()
+ fun_l24_n495
+end
+
+def fun_l23_n977()
+ fun_l24_n563
+end
+
+def fun_l23_n978()
+ fun_l24_n511
+end
+
+def fun_l23_n979()
+ fun_l24_n158
+end
+
+def fun_l23_n980()
+ fun_l24_n222
+end
+
+def fun_l23_n981()
+ fun_l24_n568
+end
+
+def fun_l23_n982()
+ fun_l24_n936
+end
+
+def fun_l23_n983()
+ fun_l24_n932
+end
+
+def fun_l23_n984()
+ fun_l24_n872
+end
+
+def fun_l23_n985()
+ fun_l24_n70
+end
+
+def fun_l23_n986()
+ fun_l24_n602
+end
+
+def fun_l23_n987()
+ fun_l24_n364
+end
+
+def fun_l23_n988()
+ fun_l24_n904
+end
+
+def fun_l23_n989()
+ fun_l24_n98
+end
+
+def fun_l23_n990()
+ fun_l24_n907
+end
+
+def fun_l23_n991()
+ fun_l24_n435
+end
+
+def fun_l23_n992()
+ fun_l24_n24
+end
+
+def fun_l23_n993()
+ fun_l24_n790
+end
+
+def fun_l23_n994()
+ fun_l24_n249
+end
+
+def fun_l23_n995()
+ fun_l24_n12
+end
+
+def fun_l23_n996()
+ fun_l24_n956
+end
+
+def fun_l23_n997()
+ fun_l24_n539
+end
+
+def fun_l23_n998()
+ fun_l24_n935
+end
+
+def fun_l23_n999()
+ fun_l24_n964
+end
+
+def fun_l24_n0()
+ fun_l25_n193
+end
+
+def fun_l24_n1()
+ fun_l25_n802
+end
+
+def fun_l24_n2()
+ fun_l25_n936
+end
+
+def fun_l24_n3()
+ fun_l25_n672
+end
+
+def fun_l24_n4()
+ fun_l25_n506
+end
+
+def fun_l24_n5()
+ fun_l25_n598
+end
+
+def fun_l24_n6()
+ fun_l25_n368
+end
+
+def fun_l24_n7()
+ fun_l25_n4
+end
+
+def fun_l24_n8()
+ fun_l25_n396
+end
+
+def fun_l24_n9()
+ fun_l25_n772
+end
+
+def fun_l24_n10()
+ fun_l25_n986
+end
+
+def fun_l24_n11()
+ fun_l25_n182
+end
+
+def fun_l24_n12()
+ fun_l25_n663
+end
+
+def fun_l24_n13()
+ fun_l25_n460
+end
+
+def fun_l24_n14()
+ fun_l25_n78
+end
+
+def fun_l24_n15()
+ fun_l25_n590
+end
+
+def fun_l24_n16()
+ fun_l25_n205
+end
+
+def fun_l24_n17()
+ fun_l25_n848
+end
+
+def fun_l24_n18()
+ fun_l25_n270
+end
+
+def fun_l24_n19()
+ fun_l25_n491
+end
+
+def fun_l24_n20()
+ fun_l25_n740
+end
+
+def fun_l24_n21()
+ fun_l25_n800
+end
+
+def fun_l24_n22()
+ fun_l25_n859
+end
+
+def fun_l24_n23()
+ fun_l25_n300
+end
+
+def fun_l24_n24()
+ fun_l25_n705
+end
+
+def fun_l24_n25()
+ fun_l25_n917
+end
+
+def fun_l24_n26()
+ fun_l25_n890
+end
+
+def fun_l24_n27()
+ fun_l25_n700
+end
+
+def fun_l24_n28()
+ fun_l25_n448
+end
+
+def fun_l24_n29()
+ fun_l25_n774
+end
+
+def fun_l24_n30()
+ fun_l25_n13
+end
+
+def fun_l24_n31()
+ fun_l25_n427
+end
+
+def fun_l24_n32()
+ fun_l25_n159
+end
+
+def fun_l24_n33()
+ fun_l25_n180
+end
+
+def fun_l24_n34()
+ fun_l25_n721
+end
+
+def fun_l24_n35()
+ fun_l25_n539
+end
+
+def fun_l24_n36()
+ fun_l25_n808
+end
+
+def fun_l24_n37()
+ fun_l25_n123
+end
+
+def fun_l24_n38()
+ fun_l25_n428
+end
+
+def fun_l24_n39()
+ fun_l25_n678
+end
+
+def fun_l24_n40()
+ fun_l25_n821
+end
+
+def fun_l24_n41()
+ fun_l25_n170
+end
+
+def fun_l24_n42()
+ fun_l25_n115
+end
+
+def fun_l24_n43()
+ fun_l25_n72
+end
+
+def fun_l24_n44()
+ fun_l25_n280
+end
+
+def fun_l24_n45()
+ fun_l25_n950
+end
+
+def fun_l24_n46()
+ fun_l25_n572
+end
+
+def fun_l24_n47()
+ fun_l25_n125
+end
+
+def fun_l24_n48()
+ fun_l25_n607
+end
+
+def fun_l24_n49()
+ fun_l25_n704
+end
+
+def fun_l24_n50()
+ fun_l25_n125
+end
+
+def fun_l24_n51()
+ fun_l25_n179
+end
+
+def fun_l24_n52()
+ fun_l25_n77
+end
+
+def fun_l24_n53()
+ fun_l25_n247
+end
+
+def fun_l24_n54()
+ fun_l25_n828
+end
+
+def fun_l24_n55()
+ fun_l25_n461
+end
+
+def fun_l24_n56()
+ fun_l25_n686
+end
+
+def fun_l24_n57()
+ fun_l25_n222
+end
+
+def fun_l24_n58()
+ fun_l25_n394
+end
+
+def fun_l24_n59()
+ fun_l25_n535
+end
+
+def fun_l24_n60()
+ fun_l25_n199
+end
+
+def fun_l24_n61()
+ fun_l25_n543
+end
+
+def fun_l24_n62()
+ fun_l25_n304
+end
+
+def fun_l24_n63()
+ fun_l25_n520
+end
+
+def fun_l24_n64()
+ fun_l25_n167
+end
+
+def fun_l24_n65()
+ fun_l25_n604
+end
+
+def fun_l24_n66()
+ fun_l25_n685
+end
+
+def fun_l24_n67()
+ fun_l25_n134
+end
+
+def fun_l24_n68()
+ fun_l25_n913
+end
+
+def fun_l24_n69()
+ fun_l25_n899
+end
+
+def fun_l24_n70()
+ fun_l25_n872
+end
+
+def fun_l24_n71()
+ fun_l25_n466
+end
+
+def fun_l24_n72()
+ fun_l25_n352
+end
+
+def fun_l24_n73()
+ fun_l25_n624
+end
+
+def fun_l24_n74()
+ fun_l25_n464
+end
+
+def fun_l24_n75()
+ fun_l25_n513
+end
+
+def fun_l24_n76()
+ fun_l25_n310
+end
+
+def fun_l24_n77()
+ fun_l25_n129
+end
+
+def fun_l24_n78()
+ fun_l25_n770
+end
+
+def fun_l24_n79()
+ fun_l25_n96
+end
+
+def fun_l24_n80()
+ fun_l25_n519
+end
+
+def fun_l24_n81()
+ fun_l25_n495
+end
+
+def fun_l24_n82()
+ fun_l25_n789
+end
+
+def fun_l24_n83()
+ fun_l25_n676
+end
+
+def fun_l24_n84()
+ fun_l25_n877
+end
+
+def fun_l24_n85()
+ fun_l25_n17
+end
+
+def fun_l24_n86()
+ fun_l25_n428
+end
+
+def fun_l24_n87()
+ fun_l25_n282
+end
+
+def fun_l24_n88()
+ fun_l25_n313
+end
+
+def fun_l24_n89()
+ fun_l25_n638
+end
+
+def fun_l24_n90()
+ fun_l25_n543
+end
+
+def fun_l24_n91()
+ fun_l25_n63
+end
+
+def fun_l24_n92()
+ fun_l25_n398
+end
+
+def fun_l24_n93()
+ fun_l25_n726
+end
+
+def fun_l24_n94()
+ fun_l25_n645
+end
+
+def fun_l24_n95()
+ fun_l25_n163
+end
+
+def fun_l24_n96()
+ fun_l25_n228
+end
+
+def fun_l24_n97()
+ fun_l25_n346
+end
+
+def fun_l24_n98()
+ fun_l25_n56
+end
+
+def fun_l24_n99()
+ fun_l25_n258
+end
+
+def fun_l24_n100()
+ fun_l25_n730
+end
+
+def fun_l24_n101()
+ fun_l25_n216
+end
+
+def fun_l24_n102()
+ fun_l25_n370
+end
+
+def fun_l24_n103()
+ fun_l25_n17
+end
+
+def fun_l24_n104()
+ fun_l25_n892
+end
+
+def fun_l24_n105()
+ fun_l25_n977
+end
+
+def fun_l24_n106()
+ fun_l25_n285
+end
+
+def fun_l24_n107()
+ fun_l25_n922
+end
+
+def fun_l24_n108()
+ fun_l25_n62
+end
+
+def fun_l24_n109()
+ fun_l25_n103
+end
+
+def fun_l24_n110()
+ fun_l25_n644
+end
+
+def fun_l24_n111()
+ fun_l25_n467
+end
+
+def fun_l24_n112()
+ fun_l25_n543
+end
+
+def fun_l24_n113()
+ fun_l25_n180
+end
+
+def fun_l24_n114()
+ fun_l25_n186
+end
+
+def fun_l24_n115()
+ fun_l25_n685
+end
+
+def fun_l24_n116()
+ fun_l25_n754
+end
+
+def fun_l24_n117()
+ fun_l25_n842
+end
+
+def fun_l24_n118()
+ fun_l25_n759
+end
+
+def fun_l24_n119()
+ fun_l25_n372
+end
+
+def fun_l24_n120()
+ fun_l25_n874
+end
+
+def fun_l24_n121()
+ fun_l25_n332
+end
+
+def fun_l24_n122()
+ fun_l25_n91
+end
+
+def fun_l24_n123()
+ fun_l25_n229
+end
+
+def fun_l24_n124()
+ fun_l25_n485
+end
+
+def fun_l24_n125()
+ fun_l25_n322
+end
+
+def fun_l24_n126()
+ fun_l25_n750
+end
+
+def fun_l24_n127()
+ fun_l25_n466
+end
+
+def fun_l24_n128()
+ fun_l25_n936
+end
+
+def fun_l24_n129()
+ fun_l25_n172
+end
+
+def fun_l24_n130()
+ fun_l25_n389
+end
+
+def fun_l24_n131()
+ fun_l25_n789
+end
+
+def fun_l24_n132()
+ fun_l25_n165
+end
+
+def fun_l24_n133()
+ fun_l25_n756
+end
+
+def fun_l24_n134()
+ fun_l25_n1
+end
+
+def fun_l24_n135()
+ fun_l25_n362
+end
+
+def fun_l24_n136()
+ fun_l25_n323
+end
+
+def fun_l24_n137()
+ fun_l25_n656
+end
+
+def fun_l24_n138()
+ fun_l25_n463
+end
+
+def fun_l24_n139()
+ fun_l25_n392
+end
+
+def fun_l24_n140()
+ fun_l25_n43
+end
+
+def fun_l24_n141()
+ fun_l25_n788
+end
+
+def fun_l24_n142()
+ fun_l25_n212
+end
+
+def fun_l24_n143()
+ fun_l25_n597
+end
+
+def fun_l24_n144()
+ fun_l25_n885
+end
+
+def fun_l24_n145()
+ fun_l25_n470
+end
+
+def fun_l24_n146()
+ fun_l25_n945
+end
+
+def fun_l24_n147()
+ fun_l25_n884
+end
+
+def fun_l24_n148()
+ fun_l25_n492
+end
+
+def fun_l24_n149()
+ fun_l25_n466
+end
+
+def fun_l24_n150()
+ fun_l25_n548
+end
+
+def fun_l24_n151()
+ fun_l25_n574
+end
+
+def fun_l24_n152()
+ fun_l25_n920
+end
+
+def fun_l24_n153()
+ fun_l25_n530
+end
+
+def fun_l24_n154()
+ fun_l25_n90
+end
+
+def fun_l24_n155()
+ fun_l25_n531
+end
+
+def fun_l24_n156()
+ fun_l25_n848
+end
+
+def fun_l24_n157()
+ fun_l25_n116
+end
+
+def fun_l24_n158()
+ fun_l25_n25
+end
+
+def fun_l24_n159()
+ fun_l25_n432
+end
+
+def fun_l24_n160()
+ fun_l25_n978
+end
+
+def fun_l24_n161()
+ fun_l25_n383
+end
+
+def fun_l24_n162()
+ fun_l25_n678
+end
+
+def fun_l24_n163()
+ fun_l25_n785
+end
+
+def fun_l24_n164()
+ fun_l25_n504
+end
+
+def fun_l24_n165()
+ fun_l25_n682
+end
+
+def fun_l24_n166()
+ fun_l25_n649
+end
+
+def fun_l24_n167()
+ fun_l25_n498
+end
+
+def fun_l24_n168()
+ fun_l25_n805
+end
+
+def fun_l24_n169()
+ fun_l25_n215
+end
+
+def fun_l24_n170()
+ fun_l25_n444
+end
+
+def fun_l24_n171()
+ fun_l25_n585
+end
+
+def fun_l24_n172()
+ fun_l25_n22
+end
+
+def fun_l24_n173()
+ fun_l25_n214
+end
+
+def fun_l24_n174()
+ fun_l25_n942
+end
+
+def fun_l24_n175()
+ fun_l25_n763
+end
+
+def fun_l24_n176()
+ fun_l25_n852
+end
+
+def fun_l24_n177()
+ fun_l25_n591
+end
+
+def fun_l24_n178()
+ fun_l25_n498
+end
+
+def fun_l24_n179()
+ fun_l25_n111
+end
+
+def fun_l24_n180()
+ fun_l25_n286
+end
+
+def fun_l24_n181()
+ fun_l25_n808
+end
+
+def fun_l24_n182()
+ fun_l25_n402
+end
+
+def fun_l24_n183()
+ fun_l25_n222
+end
+
+def fun_l24_n184()
+ fun_l25_n646
+end
+
+def fun_l24_n185()
+ fun_l25_n550
+end
+
+def fun_l24_n186()
+ fun_l25_n284
+end
+
+def fun_l24_n187()
+ fun_l25_n832
+end
+
+def fun_l24_n188()
+ fun_l25_n554
+end
+
+def fun_l24_n189()
+ fun_l25_n982
+end
+
+def fun_l24_n190()
+ fun_l25_n10
+end
+
+def fun_l24_n191()
+ fun_l25_n843
+end
+
+def fun_l24_n192()
+ fun_l25_n126
+end
+
+def fun_l24_n193()
+ fun_l25_n332
+end
+
+def fun_l24_n194()
+ fun_l25_n145
+end
+
+def fun_l24_n195()
+ fun_l25_n657
+end
+
+def fun_l24_n196()
+ fun_l25_n636
+end
+
+def fun_l24_n197()
+ fun_l25_n875
+end
+
+def fun_l24_n198()
+ fun_l25_n160
+end
+
+def fun_l24_n199()
+ fun_l25_n682
+end
+
+def fun_l24_n200()
+ fun_l25_n556
+end
+
+def fun_l24_n201()
+ fun_l25_n154
+end
+
+def fun_l24_n202()
+ fun_l25_n105
+end
+
+def fun_l24_n203()
+ fun_l25_n958
+end
+
+def fun_l24_n204()
+ fun_l25_n998
+end
+
+def fun_l24_n205()
+ fun_l25_n356
+end
+
+def fun_l24_n206()
+ fun_l25_n531
+end
+
+def fun_l24_n207()
+ fun_l25_n62
+end
+
+def fun_l24_n208()
+ fun_l25_n320
+end
+
+def fun_l24_n209()
+ fun_l25_n725
+end
+
+def fun_l24_n210()
+ fun_l25_n790
+end
+
+def fun_l24_n211()
+ fun_l25_n740
+end
+
+def fun_l24_n212()
+ fun_l25_n73
+end
+
+def fun_l24_n213()
+ fun_l25_n949
+end
+
+def fun_l24_n214()
+ fun_l25_n526
+end
+
+def fun_l24_n215()
+ fun_l25_n881
+end
+
+def fun_l24_n216()
+ fun_l25_n43
+end
+
+def fun_l24_n217()
+ fun_l25_n284
+end
+
+def fun_l24_n218()
+ fun_l25_n252
+end
+
+def fun_l24_n219()
+ fun_l25_n973
+end
+
+def fun_l24_n220()
+ fun_l25_n264
+end
+
+def fun_l24_n221()
+ fun_l25_n55
+end
+
+def fun_l24_n222()
+ fun_l25_n731
+end
+
+def fun_l24_n223()
+ fun_l25_n274
+end
+
+def fun_l24_n224()
+ fun_l25_n748
+end
+
+def fun_l24_n225()
+ fun_l25_n990
+end
+
+def fun_l24_n226()
+ fun_l25_n243
+end
+
+def fun_l24_n227()
+ fun_l25_n607
+end
+
+def fun_l24_n228()
+ fun_l25_n352
+end
+
+def fun_l24_n229()
+ fun_l25_n238
+end
+
+def fun_l24_n230()
+ fun_l25_n252
+end
+
+def fun_l24_n231()
+ fun_l25_n534
+end
+
+def fun_l24_n232()
+ fun_l25_n330
+end
+
+def fun_l24_n233()
+ fun_l25_n915
+end
+
+def fun_l24_n234()
+ fun_l25_n106
+end
+
+def fun_l24_n235()
+ fun_l25_n59
+end
+
+def fun_l24_n236()
+ fun_l25_n829
+end
+
+def fun_l24_n237()
+ fun_l25_n563
+end
+
+def fun_l24_n238()
+ fun_l25_n334
+end
+
+def fun_l24_n239()
+ fun_l25_n828
+end
+
+def fun_l24_n240()
+ fun_l25_n530
+end
+
+def fun_l24_n241()
+ fun_l25_n831
+end
+
+def fun_l24_n242()
+ fun_l25_n922
+end
+
+def fun_l24_n243()
+ fun_l25_n822
+end
+
+def fun_l24_n244()
+ fun_l25_n369
+end
+
+def fun_l24_n245()
+ fun_l25_n977
+end
+
+def fun_l24_n246()
+ fun_l25_n797
+end
+
+def fun_l24_n247()
+ fun_l25_n883
+end
+
+def fun_l24_n248()
+ fun_l25_n964
+end
+
+def fun_l24_n249()
+ fun_l25_n490
+end
+
+def fun_l24_n250()
+ fun_l25_n903
+end
+
+def fun_l24_n251()
+ fun_l25_n154
+end
+
+def fun_l24_n252()
+ fun_l25_n74
+end
+
+def fun_l24_n253()
+ fun_l25_n955
+end
+
+def fun_l24_n254()
+ fun_l25_n709
+end
+
+def fun_l24_n255()
+ fun_l25_n154
+end
+
+def fun_l24_n256()
+ fun_l25_n940
+end
+
+def fun_l24_n257()
+ fun_l25_n33
+end
+
+def fun_l24_n258()
+ fun_l25_n450
+end
+
+def fun_l24_n259()
+ fun_l25_n592
+end
+
+def fun_l24_n260()
+ fun_l25_n430
+end
+
+def fun_l24_n261()
+ fun_l25_n650
+end
+
+def fun_l24_n262()
+ fun_l25_n891
+end
+
+def fun_l24_n263()
+ fun_l25_n803
+end
+
+def fun_l24_n264()
+ fun_l25_n622
+end
+
+def fun_l24_n265()
+ fun_l25_n401
+end
+
+def fun_l24_n266()
+ fun_l25_n493
+end
+
+def fun_l24_n267()
+ fun_l25_n240
+end
+
+def fun_l24_n268()
+ fun_l25_n654
+end
+
+def fun_l24_n269()
+ fun_l25_n839
+end
+
+def fun_l24_n270()
+ fun_l25_n889
+end
+
+def fun_l24_n271()
+ fun_l25_n770
+end
+
+def fun_l24_n272()
+ fun_l25_n860
+end
+
+def fun_l24_n273()
+ fun_l25_n634
+end
+
+def fun_l24_n274()
+ fun_l25_n365
+end
+
+def fun_l24_n275()
+ fun_l25_n321
+end
+
+def fun_l24_n276()
+ fun_l25_n628
+end
+
+def fun_l24_n277()
+ fun_l25_n669
+end
+
+def fun_l24_n278()
+ fun_l25_n815
+end
+
+def fun_l24_n279()
+ fun_l25_n647
+end
+
+def fun_l24_n280()
+ fun_l25_n920
+end
+
+def fun_l24_n281()
+ fun_l25_n620
+end
+
+def fun_l24_n282()
+ fun_l25_n609
+end
+
+def fun_l24_n283()
+ fun_l25_n45
+end
+
+def fun_l24_n284()
+ fun_l25_n632
+end
+
+def fun_l24_n285()
+ fun_l25_n961
+end
+
+def fun_l24_n286()
+ fun_l25_n261
+end
+
+def fun_l24_n287()
+ fun_l25_n348
+end
+
+def fun_l24_n288()
+ fun_l25_n687
+end
+
+def fun_l24_n289()
+ fun_l25_n359
+end
+
+def fun_l24_n290()
+ fun_l25_n306
+end
+
+def fun_l24_n291()
+ fun_l25_n487
+end
+
+def fun_l24_n292()
+ fun_l25_n59
+end
+
+def fun_l24_n293()
+ fun_l25_n353
+end
+
+def fun_l24_n294()
+ fun_l25_n553
+end
+
+def fun_l24_n295()
+ fun_l25_n704
+end
+
+def fun_l24_n296()
+ fun_l25_n691
+end
+
+def fun_l24_n297()
+ fun_l25_n332
+end
+
+def fun_l24_n298()
+ fun_l25_n665
+end
+
+def fun_l24_n299()
+ fun_l25_n407
+end
+
+def fun_l24_n300()
+ fun_l25_n182
+end
+
+def fun_l24_n301()
+ fun_l25_n716
+end
+
+def fun_l24_n302()
+ fun_l25_n55
+end
+
+def fun_l24_n303()
+ fun_l25_n946
+end
+
+def fun_l24_n304()
+ fun_l25_n448
+end
+
+def fun_l24_n305()
+ fun_l25_n959
+end
+
+def fun_l24_n306()
+ fun_l25_n23
+end
+
+def fun_l24_n307()
+ fun_l25_n327
+end
+
+def fun_l24_n308()
+ fun_l25_n317
+end
+
+def fun_l24_n309()
+ fun_l25_n2
+end
+
+def fun_l24_n310()
+ fun_l25_n168
+end
+
+def fun_l24_n311()
+ fun_l25_n171
+end
+
+def fun_l24_n312()
+ fun_l25_n138
+end
+
+def fun_l24_n313()
+ fun_l25_n974
+end
+
+def fun_l24_n314()
+ fun_l25_n981
+end
+
+def fun_l24_n315()
+ fun_l25_n382
+end
+
+def fun_l24_n316()
+ fun_l25_n590
+end
+
+def fun_l24_n317()
+ fun_l25_n613
+end
+
+def fun_l24_n318()
+ fun_l25_n119
+end
+
+def fun_l24_n319()
+ fun_l25_n431
+end
+
+def fun_l24_n320()
+ fun_l25_n595
+end
+
+def fun_l24_n321()
+ fun_l25_n406
+end
+
+def fun_l24_n322()
+ fun_l25_n771
+end
+
+def fun_l24_n323()
+ fun_l25_n693
+end
+
+def fun_l24_n324()
+ fun_l25_n442
+end
+
+def fun_l24_n325()
+ fun_l25_n164
+end
+
+def fun_l24_n326()
+ fun_l25_n630
+end
+
+def fun_l24_n327()
+ fun_l25_n31
+end
+
+def fun_l24_n328()
+ fun_l25_n422
+end
+
+def fun_l24_n329()
+ fun_l25_n204
+end
+
+def fun_l24_n330()
+ fun_l25_n304
+end
+
+def fun_l24_n331()
+ fun_l25_n398
+end
+
+def fun_l24_n332()
+ fun_l25_n903
+end
+
+def fun_l24_n333()
+ fun_l25_n841
+end
+
+def fun_l24_n334()
+ fun_l25_n662
+end
+
+def fun_l24_n335()
+ fun_l25_n247
+end
+
+def fun_l24_n336()
+ fun_l25_n348
+end
+
+def fun_l24_n337()
+ fun_l25_n378
+end
+
+def fun_l24_n338()
+ fun_l25_n197
+end
+
+def fun_l24_n339()
+ fun_l25_n897
+end
+
+def fun_l24_n340()
+ fun_l25_n792
+end
+
+def fun_l24_n341()
+ fun_l25_n655
+end
+
+def fun_l24_n342()
+ fun_l25_n352
+end
+
+def fun_l24_n343()
+ fun_l25_n853
+end
+
+def fun_l24_n344()
+ fun_l25_n202
+end
+
+def fun_l24_n345()
+ fun_l25_n420
+end
+
+def fun_l24_n346()
+ fun_l25_n146
+end
+
+def fun_l24_n347()
+ fun_l25_n766
+end
+
+def fun_l24_n348()
+ fun_l25_n245
+end
+
+def fun_l24_n349()
+ fun_l25_n772
+end
+
+def fun_l24_n350()
+ fun_l25_n789
+end
+
+def fun_l24_n351()
+ fun_l25_n180
+end
+
+def fun_l24_n352()
+ fun_l25_n982
+end
+
+def fun_l24_n353()
+ fun_l25_n837
+end
+
+def fun_l24_n354()
+ fun_l25_n515
+end
+
+def fun_l24_n355()
+ fun_l25_n688
+end
+
+def fun_l24_n356()
+ fun_l25_n85
+end
+
+def fun_l24_n357()
+ fun_l25_n918
+end
+
+def fun_l24_n358()
+ fun_l25_n104
+end
+
+def fun_l24_n359()
+ fun_l25_n797
+end
+
+def fun_l24_n360()
+ fun_l25_n488
+end
+
+def fun_l24_n361()
+ fun_l25_n970
+end
+
+def fun_l24_n362()
+ fun_l25_n82
+end
+
+def fun_l24_n363()
+ fun_l25_n815
+end
+
+def fun_l24_n364()
+ fun_l25_n81
+end
+
+def fun_l24_n365()
+ fun_l25_n70
+end
+
+def fun_l24_n366()
+ fun_l25_n686
+end
+
+def fun_l24_n367()
+ fun_l25_n8
+end
+
+def fun_l24_n368()
+ fun_l25_n835
+end
+
+def fun_l24_n369()
+ fun_l25_n473
+end
+
+def fun_l24_n370()
+ fun_l25_n637
+end
+
+def fun_l24_n371()
+ fun_l25_n314
+end
+
+def fun_l24_n372()
+ fun_l25_n857
+end
+
+def fun_l24_n373()
+ fun_l25_n496
+end
+
+def fun_l24_n374()
+ fun_l25_n182
+end
+
+def fun_l24_n375()
+ fun_l25_n730
+end
+
+def fun_l24_n376()
+ fun_l25_n370
+end
+
+def fun_l24_n377()
+ fun_l25_n289
+end
+
+def fun_l24_n378()
+ fun_l25_n12
+end
+
+def fun_l24_n379()
+ fun_l25_n73
+end
+
+def fun_l24_n380()
+ fun_l25_n514
+end
+
+def fun_l24_n381()
+ fun_l25_n947
+end
+
+def fun_l24_n382()
+ fun_l25_n368
+end
+
+def fun_l24_n383()
+ fun_l25_n997
+end
+
+def fun_l24_n384()
+ fun_l25_n542
+end
+
+def fun_l24_n385()
+ fun_l25_n564
+end
+
+def fun_l24_n386()
+ fun_l25_n213
+end
+
+def fun_l24_n387()
+ fun_l25_n748
+end
+
+def fun_l24_n388()
+ fun_l25_n147
+end
+
+def fun_l24_n389()
+ fun_l25_n437
+end
+
+def fun_l24_n390()
+ fun_l25_n844
+end
+
+def fun_l24_n391()
+ fun_l25_n747
+end
+
+def fun_l24_n392()
+ fun_l25_n68
+end
+
+def fun_l24_n393()
+ fun_l25_n746
+end
+
+def fun_l24_n394()
+ fun_l25_n816
+end
+
+def fun_l24_n395()
+ fun_l25_n865
+end
+
+def fun_l24_n396()
+ fun_l25_n235
+end
+
+def fun_l24_n397()
+ fun_l25_n961
+end
+
+def fun_l24_n398()
+ fun_l25_n8
+end
+
+def fun_l24_n399()
+ fun_l25_n741
+end
+
+def fun_l24_n400()
+ fun_l25_n639
+end
+
+def fun_l24_n401()
+ fun_l25_n419
+end
+
+def fun_l24_n402()
+ fun_l25_n381
+end
+
+def fun_l24_n403()
+ fun_l25_n674
+end
+
+def fun_l24_n404()
+ fun_l25_n238
+end
+
+def fun_l24_n405()
+ fun_l25_n75
+end
+
+def fun_l24_n406()
+ fun_l25_n10
+end
+
+def fun_l24_n407()
+ fun_l25_n672
+end
+
+def fun_l24_n408()
+ fun_l25_n154
+end
+
+def fun_l24_n409()
+ fun_l25_n844
+end
+
+def fun_l24_n410()
+ fun_l25_n578
+end
+
+def fun_l24_n411()
+ fun_l25_n535
+end
+
+def fun_l24_n412()
+ fun_l25_n742
+end
+
+def fun_l24_n413()
+ fun_l25_n587
+end
+
+def fun_l24_n414()
+ fun_l25_n967
+end
+
+def fun_l24_n415()
+ fun_l25_n290
+end
+
+def fun_l24_n416()
+ fun_l25_n958
+end
+
+def fun_l24_n417()
+ fun_l25_n19
+end
+
+def fun_l24_n418()
+ fun_l25_n983
+end
+
+def fun_l24_n419()
+ fun_l25_n206
+end
+
+def fun_l24_n420()
+ fun_l25_n317
+end
+
+def fun_l24_n421()
+ fun_l25_n847
+end
+
+def fun_l24_n422()
+ fun_l25_n409
+end
+
+def fun_l24_n423()
+ fun_l25_n584
+end
+
+def fun_l24_n424()
+ fun_l25_n667
+end
+
+def fun_l24_n425()
+ fun_l25_n559
+end
+
+def fun_l24_n426()
+ fun_l25_n503
+end
+
+def fun_l24_n427()
+ fun_l25_n775
+end
+
+def fun_l24_n428()
+ fun_l25_n828
+end
+
+def fun_l24_n429()
+ fun_l25_n375
+end
+
+def fun_l24_n430()
+ fun_l25_n342
+end
+
+def fun_l24_n431()
+ fun_l25_n382
+end
+
+def fun_l24_n432()
+ fun_l25_n978
+end
+
+def fun_l24_n433()
+ fun_l25_n290
+end
+
+def fun_l24_n434()
+ fun_l25_n367
+end
+
+def fun_l24_n435()
+ fun_l25_n485
+end
+
+def fun_l24_n436()
+ fun_l25_n299
+end
+
+def fun_l24_n437()
+ fun_l25_n343
+end
+
+def fun_l24_n438()
+ fun_l25_n620
+end
+
+def fun_l24_n439()
+ fun_l25_n627
+end
+
+def fun_l24_n440()
+ fun_l25_n955
+end
+
+def fun_l24_n441()
+ fun_l25_n330
+end
+
+def fun_l24_n442()
+ fun_l25_n37
+end
+
+def fun_l24_n443()
+ fun_l25_n437
+end
+
+def fun_l24_n444()
+ fun_l25_n879
+end
+
+def fun_l24_n445()
+ fun_l25_n532
+end
+
+def fun_l24_n446()
+ fun_l25_n701
+end
+
+def fun_l24_n447()
+ fun_l25_n936
+end
+
+def fun_l24_n448()
+ fun_l25_n503
+end
+
+def fun_l24_n449()
+ fun_l25_n275
+end
+
+def fun_l24_n450()
+ fun_l25_n77
+end
+
+def fun_l24_n451()
+ fun_l25_n265
+end
+
+def fun_l24_n452()
+ fun_l25_n727
+end
+
+def fun_l24_n453()
+ fun_l25_n547
+end
+
+def fun_l24_n454()
+ fun_l25_n796
+end
+
+def fun_l24_n455()
+ fun_l25_n18
+end
+
+def fun_l24_n456()
+ fun_l25_n328
+end
+
+def fun_l24_n457()
+ fun_l25_n672
+end
+
+def fun_l24_n458()
+ fun_l25_n803
+end
+
+def fun_l24_n459()
+ fun_l25_n590
+end
+
+def fun_l24_n460()
+ fun_l25_n798
+end
+
+def fun_l24_n461()
+ fun_l25_n823
+end
+
+def fun_l24_n462()
+ fun_l25_n258
+end
+
+def fun_l24_n463()
+ fun_l25_n569
+end
+
+def fun_l24_n464()
+ fun_l25_n541
+end
+
+def fun_l24_n465()
+ fun_l25_n313
+end
+
+def fun_l24_n466()
+ fun_l25_n994
+end
+
+def fun_l24_n467()
+ fun_l25_n925
+end
+
+def fun_l24_n468()
+ fun_l25_n277
+end
+
+def fun_l24_n469()
+ fun_l25_n862
+end
+
+def fun_l24_n470()
+ fun_l25_n241
+end
+
+def fun_l24_n471()
+ fun_l25_n203
+end
+
+def fun_l24_n472()
+ fun_l25_n950
+end
+
+def fun_l24_n473()
+ fun_l25_n774
+end
+
+def fun_l24_n474()
+ fun_l25_n699
+end
+
+def fun_l24_n475()
+ fun_l25_n415
+end
+
+def fun_l24_n476()
+ fun_l25_n100
+end
+
+def fun_l24_n477()
+ fun_l25_n97
+end
+
+def fun_l24_n478()
+ fun_l25_n439
+end
+
+def fun_l24_n479()
+ fun_l25_n276
+end
+
+def fun_l24_n480()
+ fun_l25_n761
+end
+
+def fun_l24_n481()
+ fun_l25_n980
+end
+
+def fun_l24_n482()
+ fun_l25_n927
+end
+
+def fun_l24_n483()
+ fun_l25_n276
+end
+
+def fun_l24_n484()
+ fun_l25_n402
+end
+
+def fun_l24_n485()
+ fun_l25_n169
+end
+
+def fun_l24_n486()
+ fun_l25_n928
+end
+
+def fun_l24_n487()
+ fun_l25_n931
+end
+
+def fun_l24_n488()
+ fun_l25_n807
+end
+
+def fun_l24_n489()
+ fun_l25_n258
+end
+
+def fun_l24_n490()
+ fun_l25_n385
+end
+
+def fun_l24_n491()
+ fun_l25_n846
+end
+
+def fun_l24_n492()
+ fun_l25_n872
+end
+
+def fun_l24_n493()
+ fun_l25_n169
+end
+
+def fun_l24_n494()
+ fun_l25_n77
+end
+
+def fun_l24_n495()
+ fun_l25_n775
+end
+
+def fun_l24_n496()
+ fun_l25_n744
+end
+
+def fun_l24_n497()
+ fun_l25_n666
+end
+
+def fun_l24_n498()
+ fun_l25_n607
+end
+
+def fun_l24_n499()
+ fun_l25_n603
+end
+
+def fun_l24_n500()
+ fun_l25_n821
+end
+
+def fun_l24_n501()
+ fun_l25_n83
+end
+
+def fun_l24_n502()
+ fun_l25_n331
+end
+
+def fun_l24_n503()
+ fun_l25_n20
+end
+
+def fun_l24_n504()
+ fun_l25_n115
+end
+
+def fun_l24_n505()
+ fun_l25_n437
+end
+
+def fun_l24_n506()
+ fun_l25_n679
+end
+
+def fun_l24_n507()
+ fun_l25_n424
+end
+
+def fun_l24_n508()
+ fun_l25_n745
+end
+
+def fun_l24_n509()
+ fun_l25_n389
+end
+
+def fun_l24_n510()
+ fun_l25_n762
+end
+
+def fun_l24_n511()
+ fun_l25_n289
+end
+
+def fun_l24_n512()
+ fun_l25_n944
+end
+
+def fun_l24_n513()
+ fun_l25_n601
+end
+
+def fun_l24_n514()
+ fun_l25_n660
+end
+
+def fun_l24_n515()
+ fun_l25_n975
+end
+
+def fun_l24_n516()
+ fun_l25_n815
+end
+
+def fun_l24_n517()
+ fun_l25_n208
+end
+
+def fun_l24_n518()
+ fun_l25_n736
+end
+
+def fun_l24_n519()
+ fun_l25_n189
+end
+
+def fun_l24_n520()
+ fun_l25_n490
+end
+
+def fun_l24_n521()
+ fun_l25_n452
+end
+
+def fun_l24_n522()
+ fun_l25_n96
+end
+
+def fun_l24_n523()
+ fun_l25_n772
+end
+
+def fun_l24_n524()
+ fun_l25_n930
+end
+
+def fun_l24_n525()
+ fun_l25_n322
+end
+
+def fun_l24_n526()
+ fun_l25_n419
+end
+
+def fun_l24_n527()
+ fun_l25_n997
+end
+
+def fun_l24_n528()
+ fun_l25_n475
+end
+
+def fun_l24_n529()
+ fun_l25_n511
+end
+
+def fun_l24_n530()
+ fun_l25_n909
+end
+
+def fun_l24_n531()
+ fun_l25_n33
+end
+
+def fun_l24_n532()
+ fun_l25_n923
+end
+
+def fun_l24_n533()
+ fun_l25_n201
+end
+
+def fun_l24_n534()
+ fun_l25_n444
+end
+
+def fun_l24_n535()
+ fun_l25_n327
+end
+
+def fun_l24_n536()
+ fun_l25_n982
+end
+
+def fun_l24_n537()
+ fun_l25_n969
+end
+
+def fun_l24_n538()
+ fun_l25_n514
+end
+
+def fun_l24_n539()
+ fun_l25_n707
+end
+
+def fun_l24_n540()
+ fun_l25_n571
+end
+
+def fun_l24_n541()
+ fun_l25_n407
+end
+
+def fun_l24_n542()
+ fun_l25_n848
+end
+
+def fun_l24_n543()
+ fun_l25_n457
+end
+
+def fun_l24_n544()
+ fun_l25_n374
+end
+
+def fun_l24_n545()
+ fun_l25_n875
+end
+
+def fun_l24_n546()
+ fun_l25_n166
+end
+
+def fun_l24_n547()
+ fun_l25_n951
+end
+
+def fun_l24_n548()
+ fun_l25_n213
+end
+
+def fun_l24_n549()
+ fun_l25_n148
+end
+
+def fun_l24_n550()
+ fun_l25_n479
+end
+
+def fun_l24_n551()
+ fun_l25_n130
+end
+
+def fun_l24_n552()
+ fun_l25_n823
+end
+
+def fun_l24_n553()
+ fun_l25_n507
+end
+
+def fun_l24_n554()
+ fun_l25_n227
+end
+
+def fun_l24_n555()
+ fun_l25_n811
+end
+
+def fun_l24_n556()
+ fun_l25_n203
+end
+
+def fun_l24_n557()
+ fun_l25_n626
+end
+
+def fun_l24_n558()
+ fun_l25_n965
+end
+
+def fun_l24_n559()
+ fun_l25_n871
+end
+
+def fun_l24_n560()
+ fun_l25_n752
+end
+
+def fun_l24_n561()
+ fun_l25_n89
+end
+
+def fun_l24_n562()
+ fun_l25_n970
+end
+
+def fun_l24_n563()
+ fun_l25_n956
+end
+
+def fun_l24_n564()
+ fun_l25_n871
+end
+
+def fun_l24_n565()
+ fun_l25_n610
+end
+
+def fun_l24_n566()
+ fun_l25_n43
+end
+
+def fun_l24_n567()
+ fun_l25_n176
+end
+
+def fun_l24_n568()
+ fun_l25_n10
+end
+
+def fun_l24_n569()
+ fun_l25_n798
+end
+
+def fun_l24_n570()
+ fun_l25_n141
+end
+
+def fun_l24_n571()
+ fun_l25_n205
+end
+
+def fun_l24_n572()
+ fun_l25_n870
+end
+
+def fun_l24_n573()
+ fun_l25_n324
+end
+
+def fun_l24_n574()
+ fun_l25_n765
+end
+
+def fun_l24_n575()
+ fun_l25_n775
+end
+
+def fun_l24_n576()
+ fun_l25_n232
+end
+
+def fun_l24_n577()
+ fun_l25_n36
+end
+
+def fun_l24_n578()
+ fun_l25_n260
+end
+
+def fun_l24_n579()
+ fun_l25_n84
+end
+
+def fun_l24_n580()
+ fun_l25_n279
+end
+
+def fun_l24_n581()
+ fun_l25_n292
+end
+
+def fun_l24_n582()
+ fun_l25_n472
+end
+
+def fun_l24_n583()
+ fun_l25_n630
+end
+
+def fun_l24_n584()
+ fun_l25_n695
+end
+
+def fun_l24_n585()
+ fun_l25_n974
+end
+
+def fun_l24_n586()
+ fun_l25_n263
+end
+
+def fun_l24_n587()
+ fun_l25_n959
+end
+
+def fun_l24_n588()
+ fun_l25_n76
+end
+
+def fun_l24_n589()
+ fun_l25_n897
+end
+
+def fun_l24_n590()
+ fun_l25_n416
+end
+
+def fun_l24_n591()
+ fun_l25_n225
+end
+
+def fun_l24_n592()
+ fun_l25_n194
+end
+
+def fun_l24_n593()
+ fun_l25_n338
+end
+
+def fun_l24_n594()
+ fun_l25_n565
+end
+
+def fun_l24_n595()
+ fun_l25_n301
+end
+
+def fun_l24_n596()
+ fun_l25_n101
+end
+
+def fun_l24_n597()
+ fun_l25_n876
+end
+
+def fun_l24_n598()
+ fun_l25_n127
+end
+
+def fun_l24_n599()
+ fun_l25_n608
+end
+
+def fun_l24_n600()
+ fun_l25_n45
+end
+
+def fun_l24_n601()
+ fun_l25_n833
+end
+
+def fun_l24_n602()
+ fun_l25_n43
+end
+
+def fun_l24_n603()
+ fun_l25_n136
+end
+
+def fun_l24_n604()
+ fun_l25_n916
+end
+
+def fun_l24_n605()
+ fun_l25_n686
+end
+
+def fun_l24_n606()
+ fun_l25_n574
+end
+
+def fun_l24_n607()
+ fun_l25_n164
+end
+
+def fun_l24_n608()
+ fun_l25_n983
+end
+
+def fun_l24_n609()
+ fun_l25_n883
+end
+
+def fun_l24_n610()
+ fun_l25_n957
+end
+
+def fun_l24_n611()
+ fun_l25_n592
+end
+
+def fun_l24_n612()
+ fun_l25_n684
+end
+
+def fun_l24_n613()
+ fun_l25_n333
+end
+
+def fun_l24_n614()
+ fun_l25_n465
+end
+
+def fun_l24_n615()
+ fun_l25_n297
+end
+
+def fun_l24_n616()
+ fun_l25_n738
+end
+
+def fun_l24_n617()
+ fun_l25_n953
+end
+
+def fun_l24_n618()
+ fun_l25_n27
+end
+
+def fun_l24_n619()
+ fun_l25_n577
+end
+
+def fun_l24_n620()
+ fun_l25_n595
+end
+
+def fun_l24_n621()
+ fun_l25_n408
+end
+
+def fun_l24_n622()
+ fun_l25_n161
+end
+
+def fun_l24_n623()
+ fun_l25_n263
+end
+
+def fun_l24_n624()
+ fun_l25_n557
+end
+
+def fun_l24_n625()
+ fun_l25_n708
+end
+
+def fun_l24_n626()
+ fun_l25_n879
+end
+
+def fun_l24_n627()
+ fun_l25_n235
+end
+
+def fun_l24_n628()
+ fun_l25_n551
+end
+
+def fun_l24_n629()
+ fun_l25_n46
+end
+
+def fun_l24_n630()
+ fun_l25_n718
+end
+
+def fun_l24_n631()
+ fun_l25_n419
+end
+
+def fun_l24_n632()
+ fun_l25_n370
+end
+
+def fun_l24_n633()
+ fun_l25_n322
+end
+
+def fun_l24_n634()
+ fun_l25_n912
+end
+
+def fun_l24_n635()
+ fun_l25_n445
+end
+
+def fun_l24_n636()
+ fun_l25_n850
+end
+
+def fun_l24_n637()
+ fun_l25_n233
+end
+
+def fun_l24_n638()
+ fun_l25_n230
+end
+
+def fun_l24_n639()
+ fun_l25_n188
+end
+
+def fun_l24_n640()
+ fun_l25_n267
+end
+
+def fun_l24_n641()
+ fun_l25_n840
+end
+
+def fun_l24_n642()
+ fun_l25_n786
+end
+
+def fun_l24_n643()
+ fun_l25_n737
+end
+
+def fun_l24_n644()
+ fun_l25_n725
+end
+
+def fun_l24_n645()
+ fun_l25_n200
+end
+
+def fun_l24_n646()
+ fun_l25_n173
+end
+
+def fun_l24_n647()
+ fun_l25_n50
+end
+
+def fun_l24_n648()
+ fun_l25_n460
+end
+
+def fun_l24_n649()
+ fun_l25_n959
+end
+
+def fun_l24_n650()
+ fun_l25_n397
+end
+
+def fun_l24_n651()
+ fun_l25_n108
+end
+
+def fun_l24_n652()
+ fun_l25_n426
+end
+
+def fun_l24_n653()
+ fun_l25_n208
+end
+
+def fun_l24_n654()
+ fun_l25_n989
+end
+
+def fun_l24_n655()
+ fun_l25_n73
+end
+
+def fun_l24_n656()
+ fun_l25_n710
+end
+
+def fun_l24_n657()
+ fun_l25_n707
+end
+
+def fun_l24_n658()
+ fun_l25_n276
+end
+
+def fun_l24_n659()
+ fun_l25_n920
+end
+
+def fun_l24_n660()
+ fun_l25_n735
+end
+
+def fun_l24_n661()
+ fun_l25_n937
+end
+
+def fun_l24_n662()
+ fun_l25_n544
+end
+
+def fun_l24_n663()
+ fun_l25_n663
+end
+
+def fun_l24_n664()
+ fun_l25_n571
+end
+
+def fun_l24_n665()
+ fun_l25_n682
+end
+
+def fun_l24_n666()
+ fun_l25_n79
+end
+
+def fun_l24_n667()
+ fun_l25_n759
+end
+
+def fun_l24_n668()
+ fun_l25_n128
+end
+
+def fun_l24_n669()
+ fun_l25_n895
+end
+
+def fun_l24_n670()
+ fun_l25_n258
+end
+
+def fun_l24_n671()
+ fun_l25_n12
+end
+
+def fun_l24_n672()
+ fun_l25_n397
+end
+
+def fun_l24_n673()
+ fun_l25_n967
+end
+
+def fun_l24_n674()
+ fun_l25_n960
+end
+
+def fun_l24_n675()
+ fun_l25_n867
+end
+
+def fun_l24_n676()
+ fun_l25_n438
+end
+
+def fun_l24_n677()
+ fun_l25_n692
+end
+
+def fun_l24_n678()
+ fun_l25_n161
+end
+
+def fun_l24_n679()
+ fun_l25_n122
+end
+
+def fun_l24_n680()
+ fun_l25_n344
+end
+
+def fun_l24_n681()
+ fun_l25_n285
+end
+
+def fun_l24_n682()
+ fun_l25_n838
+end
+
+def fun_l24_n683()
+ fun_l25_n80
+end
+
+def fun_l24_n684()
+ fun_l25_n81
+end
+
+def fun_l24_n685()
+ fun_l25_n811
+end
+
+def fun_l24_n686()
+ fun_l25_n998
+end
+
+def fun_l24_n687()
+ fun_l25_n739
+end
+
+def fun_l24_n688()
+ fun_l25_n660
+end
+
+def fun_l24_n689()
+ fun_l25_n965
+end
+
+def fun_l24_n690()
+ fun_l25_n124
+end
+
+def fun_l24_n691()
+ fun_l25_n879
+end
+
+def fun_l24_n692()
+ fun_l25_n669
+end
+
+def fun_l24_n693()
+ fun_l25_n428
+end
+
+def fun_l24_n694()
+ fun_l25_n143
+end
+
+def fun_l24_n695()
+ fun_l25_n103
+end
+
+def fun_l24_n696()
+ fun_l25_n738
+end
+
+def fun_l24_n697()
+ fun_l25_n188
+end
+
+def fun_l24_n698()
+ fun_l25_n657
+end
+
+def fun_l24_n699()
+ fun_l25_n258
+end
+
+def fun_l24_n700()
+ fun_l25_n878
+end
+
+def fun_l24_n701()
+ fun_l25_n927
+end
+
+def fun_l24_n702()
+ fun_l25_n9
+end
+
+def fun_l24_n703()
+ fun_l25_n41
+end
+
+def fun_l24_n704()
+ fun_l25_n925
+end
+
+def fun_l24_n705()
+ fun_l25_n473
+end
+
+def fun_l24_n706()
+ fun_l25_n321
+end
+
+def fun_l24_n707()
+ fun_l25_n778
+end
+
+def fun_l24_n708()
+ fun_l25_n951
+end
+
+def fun_l24_n709()
+ fun_l25_n91
+end
+
+def fun_l24_n710()
+ fun_l25_n297
+end
+
+def fun_l24_n711()
+ fun_l25_n185
+end
+
+def fun_l24_n712()
+ fun_l25_n822
+end
+
+def fun_l24_n713()
+ fun_l25_n817
+end
+
+def fun_l24_n714()
+ fun_l25_n558
+end
+
+def fun_l24_n715()
+ fun_l25_n15
+end
+
+def fun_l24_n716()
+ fun_l25_n106
+end
+
+def fun_l24_n717()
+ fun_l25_n173
+end
+
+def fun_l24_n718()
+ fun_l25_n565
+end
+
+def fun_l24_n719()
+ fun_l25_n832
+end
+
+def fun_l24_n720()
+ fun_l25_n798
+end
+
+def fun_l24_n721()
+ fun_l25_n333
+end
+
+def fun_l24_n722()
+ fun_l25_n631
+end
+
+def fun_l24_n723()
+ fun_l25_n135
+end
+
+def fun_l24_n724()
+ fun_l25_n826
+end
+
+def fun_l24_n725()
+ fun_l25_n878
+end
+
+def fun_l24_n726()
+ fun_l25_n612
+end
+
+def fun_l24_n727()
+ fun_l25_n302
+end
+
+def fun_l24_n728()
+ fun_l25_n636
+end
+
+def fun_l24_n729()
+ fun_l25_n308
+end
+
+def fun_l24_n730()
+ fun_l25_n633
+end
+
+def fun_l24_n731()
+ fun_l25_n596
+end
+
+def fun_l24_n732()
+ fun_l25_n948
+end
+
+def fun_l24_n733()
+ fun_l25_n93
+end
+
+def fun_l24_n734()
+ fun_l25_n175
+end
+
+def fun_l24_n735()
+ fun_l25_n590
+end
+
+def fun_l24_n736()
+ fun_l25_n168
+end
+
+def fun_l24_n737()
+ fun_l25_n861
+end
+
+def fun_l24_n738()
+ fun_l25_n890
+end
+
+def fun_l24_n739()
+ fun_l25_n355
+end
+
+def fun_l24_n740()
+ fun_l25_n166
+end
+
+def fun_l24_n741()
+ fun_l25_n397
+end
+
+def fun_l24_n742()
+ fun_l25_n665
+end
+
+def fun_l24_n743()
+ fun_l25_n436
+end
+
+def fun_l24_n744()
+ fun_l25_n274
+end
+
+def fun_l24_n745()
+ fun_l25_n44
+end
+
+def fun_l24_n746()
+ fun_l25_n765
+end
+
+def fun_l24_n747()
+ fun_l25_n916
+end
+
+def fun_l24_n748()
+ fun_l25_n735
+end
+
+def fun_l24_n749()
+ fun_l25_n745
+end
+
+def fun_l24_n750()
+ fun_l25_n813
+end
+
+def fun_l24_n751()
+ fun_l25_n26
+end
+
+def fun_l24_n752()
+ fun_l25_n223
+end
+
+def fun_l24_n753()
+ fun_l25_n256
+end
+
+def fun_l24_n754()
+ fun_l25_n852
+end
+
+def fun_l24_n755()
+ fun_l25_n400
+end
+
+def fun_l24_n756()
+ fun_l25_n973
+end
+
+def fun_l24_n757()
+ fun_l25_n900
+end
+
+def fun_l24_n758()
+ fun_l25_n884
+end
+
+def fun_l24_n759()
+ fun_l25_n171
+end
+
+def fun_l24_n760()
+ fun_l25_n155
+end
+
+def fun_l24_n761()
+ fun_l25_n310
+end
+
+def fun_l24_n762()
+ fun_l25_n706
+end
+
+def fun_l24_n763()
+ fun_l25_n324
+end
+
+def fun_l24_n764()
+ fun_l25_n260
+end
+
+def fun_l24_n765()
+ fun_l25_n247
+end
+
+def fun_l24_n766()
+ fun_l25_n750
+end
+
+def fun_l24_n767()
+ fun_l25_n236
+end
+
+def fun_l24_n768()
+ fun_l25_n956
+end
+
+def fun_l24_n769()
+ fun_l25_n736
+end
+
+def fun_l24_n770()
+ fun_l25_n510
+end
+
+def fun_l24_n771()
+ fun_l25_n101
+end
+
+def fun_l24_n772()
+ fun_l25_n189
+end
+
+def fun_l24_n773()
+ fun_l25_n391
+end
+
+def fun_l24_n774()
+ fun_l25_n212
+end
+
+def fun_l24_n775()
+ fun_l25_n500
+end
+
+def fun_l24_n776()
+ fun_l25_n95
+end
+
+def fun_l24_n777()
+ fun_l25_n30
+end
+
+def fun_l24_n778()
+ fun_l25_n99
+end
+
+def fun_l24_n779()
+ fun_l25_n427
+end
+
+def fun_l24_n780()
+ fun_l25_n659
+end
+
+def fun_l24_n781()
+ fun_l25_n665
+end
+
+def fun_l24_n782()
+ fun_l25_n992
+end
+
+def fun_l24_n783()
+ fun_l25_n180
+end
+
+def fun_l24_n784()
+ fun_l25_n546
+end
+
+def fun_l24_n785()
+ fun_l25_n618
+end
+
+def fun_l24_n786()
+ fun_l25_n615
+end
+
+def fun_l24_n787()
+ fun_l25_n126
+end
+
+def fun_l24_n788()
+ fun_l25_n383
+end
+
+def fun_l24_n789()
+ fun_l25_n429
+end
+
+def fun_l24_n790()
+ fun_l25_n95
+end
+
+def fun_l24_n791()
+ fun_l25_n47
+end
+
+def fun_l24_n792()
+ fun_l25_n582
+end
+
+def fun_l24_n793()
+ fun_l25_n209
+end
+
+def fun_l24_n794()
+ fun_l25_n925
+end
+
+def fun_l24_n795()
+ fun_l25_n746
+end
+
+def fun_l24_n796()
+ fun_l25_n330
+end
+
+def fun_l24_n797()
+ fun_l25_n964
+end
+
+def fun_l24_n798()
+ fun_l25_n241
+end
+
+def fun_l24_n799()
+ fun_l25_n136
+end
+
+def fun_l24_n800()
+ fun_l25_n10
+end
+
+def fun_l24_n801()
+ fun_l25_n255
+end
+
+def fun_l24_n802()
+ fun_l25_n481
+end
+
+def fun_l24_n803()
+ fun_l25_n697
+end
+
+def fun_l24_n804()
+ fun_l25_n275
+end
+
+def fun_l24_n805()
+ fun_l25_n389
+end
+
+def fun_l24_n806()
+ fun_l25_n540
+end
+
+def fun_l24_n807()
+ fun_l25_n182
+end
+
+def fun_l24_n808()
+ fun_l25_n894
+end
+
+def fun_l24_n809()
+ fun_l25_n339
+end
+
+def fun_l24_n810()
+ fun_l25_n409
+end
+
+def fun_l24_n811()
+ fun_l25_n106
+end
+
+def fun_l24_n812()
+ fun_l25_n297
+end
+
+def fun_l24_n813()
+ fun_l25_n477
+end
+
+def fun_l24_n814()
+ fun_l25_n431
+end
+
+def fun_l24_n815()
+ fun_l25_n507
+end
+
+def fun_l24_n816()
+ fun_l25_n311
+end
+
+def fun_l24_n817()
+ fun_l25_n350
+end
+
+def fun_l24_n818()
+ fun_l25_n486
+end
+
+def fun_l24_n819()
+ fun_l25_n872
+end
+
+def fun_l24_n820()
+ fun_l25_n21
+end
+
+def fun_l24_n821()
+ fun_l25_n108
+end
+
+def fun_l24_n822()
+ fun_l25_n383
+end
+
+def fun_l24_n823()
+ fun_l25_n389
+end
+
+def fun_l24_n824()
+ fun_l25_n901
+end
+
+def fun_l24_n825()
+ fun_l25_n94
+end
+
+def fun_l24_n826()
+ fun_l25_n122
+end
+
+def fun_l24_n827()
+ fun_l25_n399
+end
+
+def fun_l24_n828()
+ fun_l25_n424
+end
+
+def fun_l24_n829()
+ fun_l25_n59
+end
+
+def fun_l24_n830()
+ fun_l25_n477
+end
+
+def fun_l24_n831()
+ fun_l25_n766
+end
+
+def fun_l24_n832()
+ fun_l25_n340
+end
+
+def fun_l24_n833()
+ fun_l25_n925
+end
+
+def fun_l24_n834()
+ fun_l25_n993
+end
+
+def fun_l24_n835()
+ fun_l25_n444
+end
+
+def fun_l24_n836()
+ fun_l25_n580
+end
+
+def fun_l24_n837()
+ fun_l25_n997
+end
+
+def fun_l24_n838()
+ fun_l25_n651
+end
+
+def fun_l24_n839()
+ fun_l25_n991
+end
+
+def fun_l24_n840()
+ fun_l25_n850
+end
+
+def fun_l24_n841()
+ fun_l25_n563
+end
+
+def fun_l24_n842()
+ fun_l25_n175
+end
+
+def fun_l24_n843()
+ fun_l25_n77
+end
+
+def fun_l24_n844()
+ fun_l25_n300
+end
+
+def fun_l24_n845()
+ fun_l25_n510
+end
+
+def fun_l24_n846()
+ fun_l25_n871
+end
+
+def fun_l24_n847()
+ fun_l25_n437
+end
+
+def fun_l24_n848()
+ fun_l25_n609
+end
+
+def fun_l24_n849()
+ fun_l25_n505
+end
+
+def fun_l24_n850()
+ fun_l25_n989
+end
+
+def fun_l24_n851()
+ fun_l25_n595
+end
+
+def fun_l24_n852()
+ fun_l25_n917
+end
+
+def fun_l24_n853()
+ fun_l25_n39
+end
+
+def fun_l24_n854()
+ fun_l25_n795
+end
+
+def fun_l24_n855()
+ fun_l25_n242
+end
+
+def fun_l24_n856()
+ fun_l25_n220
+end
+
+def fun_l24_n857()
+ fun_l25_n537
+end
+
+def fun_l24_n858()
+ fun_l25_n790
+end
+
+def fun_l24_n859()
+ fun_l25_n160
+end
+
+def fun_l24_n860()
+ fun_l25_n685
+end
+
+def fun_l24_n861()
+ fun_l25_n665
+end
+
+def fun_l24_n862()
+ fun_l25_n448
+end
+
+def fun_l24_n863()
+ fun_l25_n75
+end
+
+def fun_l24_n864()
+ fun_l25_n293
+end
+
+def fun_l24_n865()
+ fun_l25_n721
+end
+
+def fun_l24_n866()
+ fun_l25_n113
+end
+
+def fun_l24_n867()
+ fun_l25_n565
+end
+
+def fun_l24_n868()
+ fun_l25_n95
+end
+
+def fun_l24_n869()
+ fun_l25_n373
+end
+
+def fun_l24_n870()
+ fun_l25_n351
+end
+
+def fun_l24_n871()
+ fun_l25_n151
+end
+
+def fun_l24_n872()
+ fun_l25_n489
+end
+
+def fun_l24_n873()
+ fun_l25_n882
+end
+
+def fun_l24_n874()
+ fun_l25_n415
+end
+
+def fun_l24_n875()
+ fun_l25_n237
+end
+
+def fun_l24_n876()
+ fun_l25_n59
+end
+
+def fun_l24_n877()
+ fun_l25_n747
+end
+
+def fun_l24_n878()
+ fun_l25_n897
+end
+
+def fun_l24_n879()
+ fun_l25_n746
+end
+
+def fun_l24_n880()
+ fun_l25_n695
+end
+
+def fun_l24_n881()
+ fun_l25_n924
+end
+
+def fun_l24_n882()
+ fun_l25_n933
+end
+
+def fun_l24_n883()
+ fun_l25_n702
+end
+
+def fun_l24_n884()
+ fun_l25_n107
+end
+
+def fun_l24_n885()
+ fun_l25_n333
+end
+
+def fun_l24_n886()
+ fun_l25_n536
+end
+
+def fun_l24_n887()
+ fun_l25_n908
+end
+
+def fun_l24_n888()
+ fun_l25_n84
+end
+
+def fun_l24_n889()
+ fun_l25_n622
+end
+
+def fun_l24_n890()
+ fun_l25_n466
+end
+
+def fun_l24_n891()
+ fun_l25_n344
+end
+
+def fun_l24_n892()
+ fun_l25_n271
+end
+
+def fun_l24_n893()
+ fun_l25_n461
+end
+
+def fun_l24_n894()
+ fun_l25_n297
+end
+
+def fun_l24_n895()
+ fun_l25_n415
+end
+
+def fun_l24_n896()
+ fun_l25_n419
+end
+
+def fun_l24_n897()
+ fun_l25_n374
+end
+
+def fun_l24_n898()
+ fun_l25_n976
+end
+
+def fun_l24_n899()
+ fun_l25_n888
+end
+
+def fun_l24_n900()
+ fun_l25_n540
+end
+
+def fun_l24_n901()
+ fun_l25_n491
+end
+
+def fun_l24_n902()
+ fun_l25_n178
+end
+
+def fun_l24_n903()
+ fun_l25_n197
+end
+
+def fun_l24_n904()
+ fun_l25_n474
+end
+
+def fun_l24_n905()
+ fun_l25_n371
+end
+
+def fun_l24_n906()
+ fun_l25_n960
+end
+
+def fun_l24_n907()
+ fun_l25_n808
+end
+
+def fun_l24_n908()
+ fun_l25_n89
+end
+
+def fun_l24_n909()
+ fun_l25_n892
+end
+
+def fun_l24_n910()
+ fun_l25_n457
+end
+
+def fun_l24_n911()
+ fun_l25_n105
+end
+
+def fun_l24_n912()
+ fun_l25_n787
+end
+
+def fun_l24_n913()
+ fun_l25_n554
+end
+
+def fun_l24_n914()
+ fun_l25_n615
+end
+
+def fun_l24_n915()
+ fun_l25_n61
+end
+
+def fun_l24_n916()
+ fun_l25_n162
+end
+
+def fun_l24_n917()
+ fun_l25_n354
+end
+
+def fun_l24_n918()
+ fun_l25_n388
+end
+
+def fun_l24_n919()
+ fun_l25_n660
+end
+
+def fun_l24_n920()
+ fun_l25_n705
+end
+
+def fun_l24_n921()
+ fun_l25_n990
+end
+
+def fun_l24_n922()
+ fun_l25_n725
+end
+
+def fun_l24_n923()
+ fun_l25_n800
+end
+
+def fun_l24_n924()
+ fun_l25_n368
+end
+
+def fun_l24_n925()
+ fun_l25_n986
+end
+
+def fun_l24_n926()
+ fun_l25_n509
+end
+
+def fun_l24_n927()
+ fun_l25_n706
+end
+
+def fun_l24_n928()
+ fun_l25_n777
+end
+
+def fun_l24_n929()
+ fun_l25_n223
+end
+
+def fun_l24_n930()
+ fun_l25_n972
+end
+
+def fun_l24_n931()
+ fun_l25_n868
+end
+
+def fun_l24_n932()
+ fun_l25_n170
+end
+
+def fun_l24_n933()
+ fun_l25_n176
+end
+
+def fun_l24_n934()
+ fun_l25_n667
+end
+
+def fun_l24_n935()
+ fun_l25_n312
+end
+
+def fun_l24_n936()
+ fun_l25_n680
+end
+
+def fun_l24_n937()
+ fun_l25_n183
+end
+
+def fun_l24_n938()
+ fun_l25_n880
+end
+
+def fun_l24_n939()
+ fun_l25_n634
+end
+
+def fun_l24_n940()
+ fun_l25_n716
+end
+
+def fun_l24_n941()
+ fun_l25_n16
+end
+
+def fun_l24_n942()
+ fun_l25_n227
+end
+
+def fun_l24_n943()
+ fun_l25_n423
+end
+
+def fun_l24_n944()
+ fun_l25_n268
+end
+
+def fun_l24_n945()
+ fun_l25_n947
+end
+
+def fun_l24_n946()
+ fun_l25_n675
+end
+
+def fun_l24_n947()
+ fun_l25_n575
+end
+
+def fun_l24_n948()
+ fun_l25_n280
+end
+
+def fun_l24_n949()
+ fun_l25_n698
+end
+
+def fun_l24_n950()
+ fun_l25_n769
+end
+
+def fun_l24_n951()
+ fun_l25_n225
+end
+
+def fun_l24_n952()
+ fun_l25_n171
+end
+
+def fun_l24_n953()
+ fun_l25_n464
+end
+
+def fun_l24_n954()
+ fun_l25_n662
+end
+
+def fun_l24_n955()
+ fun_l25_n621
+end
+
+def fun_l24_n956()
+ fun_l25_n391
+end
+
+def fun_l24_n957()
+ fun_l25_n340
+end
+
+def fun_l24_n958()
+ fun_l25_n634
+end
+
+def fun_l24_n959()
+ fun_l25_n31
+end
+
+def fun_l24_n960()
+ fun_l25_n132
+end
+
+def fun_l24_n961()
+ fun_l25_n867
+end
+
+def fun_l24_n962()
+ fun_l25_n946
+end
+
+def fun_l24_n963()
+ fun_l25_n339
+end
+
+def fun_l24_n964()
+ fun_l25_n497
+end
+
+def fun_l24_n965()
+ fun_l25_n289
+end
+
+def fun_l24_n966()
+ fun_l25_n842
+end
+
+def fun_l24_n967()
+ fun_l25_n583
+end
+
+def fun_l24_n968()
+ fun_l25_n52
+end
+
+def fun_l24_n969()
+ fun_l25_n177
+end
+
+def fun_l24_n970()
+ fun_l25_n935
+end
+
+def fun_l24_n971()
+ fun_l25_n963
+end
+
+def fun_l24_n972()
+ fun_l25_n779
+end
+
+def fun_l24_n973()
+ fun_l25_n457
+end
+
+def fun_l24_n974()
+ fun_l25_n480
+end
+
+def fun_l24_n975()
+ fun_l25_n333
+end
+
+def fun_l24_n976()
+ fun_l25_n191
+end
+
+def fun_l24_n977()
+ fun_l25_n670
+end
+
+def fun_l24_n978()
+ fun_l25_n822
+end
+
+def fun_l24_n979()
+ fun_l25_n302
+end
+
+def fun_l24_n980()
+ fun_l25_n272
+end
+
+def fun_l24_n981()
+ fun_l25_n467
+end
+
+def fun_l24_n982()
+ fun_l25_n209
+end
+
+def fun_l24_n983()
+ fun_l25_n603
+end
+
+def fun_l24_n984()
+ fun_l25_n134
+end
+
+def fun_l24_n985()
+ fun_l25_n639
+end
+
+def fun_l24_n986()
+ fun_l25_n843
+end
+
+def fun_l24_n987()
+ fun_l25_n576
+end
+
+def fun_l24_n988()
+ fun_l25_n7
+end
+
+def fun_l24_n989()
+ fun_l25_n93
+end
+
+def fun_l24_n990()
+ fun_l25_n351
+end
+
+def fun_l24_n991()
+ fun_l25_n932
+end
+
+def fun_l24_n992()
+ fun_l25_n987
+end
+
+def fun_l24_n993()
+ fun_l25_n796
+end
+
+def fun_l24_n994()
+ fun_l25_n202
+end
+
+def fun_l24_n995()
+ fun_l25_n125
+end
+
+def fun_l24_n996()
+ fun_l25_n404
+end
+
+def fun_l24_n997()
+ fun_l25_n750
+end
+
+def fun_l24_n998()
+ fun_l25_n50
+end
+
+def fun_l24_n999()
+ fun_l25_n71
+end
+
+def fun_l25_n0()
+ fun_l26_n73
+end
+
+def fun_l25_n1()
+ fun_l26_n572
+end
+
+def fun_l25_n2()
+ fun_l26_n639
+end
+
+def fun_l25_n3()
+ fun_l26_n292
+end
+
+def fun_l25_n4()
+ fun_l26_n865
+end
+
+def fun_l25_n5()
+ fun_l26_n618
+end
+
+def fun_l25_n6()
+ fun_l26_n84
+end
+
+def fun_l25_n7()
+ fun_l26_n351
+end
+
+def fun_l25_n8()
+ fun_l26_n534
+end
+
+def fun_l25_n9()
+ fun_l26_n483
+end
+
+def fun_l25_n10()
+ fun_l26_n589
+end
+
+def fun_l25_n11()
+ fun_l26_n450
+end
+
+def fun_l25_n12()
+ fun_l26_n948
+end
+
+def fun_l25_n13()
+ fun_l26_n819
+end
+
+def fun_l25_n14()
+ fun_l26_n845
+end
+
+def fun_l25_n15()
+ fun_l26_n544
+end
+
+def fun_l25_n16()
+ fun_l26_n254
+end
+
+def fun_l25_n17()
+ fun_l26_n71
+end
+
+def fun_l25_n18()
+ fun_l26_n640
+end
+
+def fun_l25_n19()
+ fun_l26_n885
+end
+
+def fun_l25_n20()
+ fun_l26_n725
+end
+
+def fun_l25_n21()
+ fun_l26_n798
+end
+
+def fun_l25_n22()
+ fun_l26_n838
+end
+
+def fun_l25_n23()
+ fun_l26_n835
+end
+
+def fun_l25_n24()
+ fun_l26_n170
+end
+
+def fun_l25_n25()
+ fun_l26_n3
+end
+
+def fun_l25_n26()
+ fun_l26_n910
+end
+
+def fun_l25_n27()
+ fun_l26_n575
+end
+
+def fun_l25_n28()
+ fun_l26_n834
+end
+
+def fun_l25_n29()
+ fun_l26_n767
+end
+
+def fun_l25_n30()
+ fun_l26_n375
+end
+
+def fun_l25_n31()
+ fun_l26_n781
+end
+
+def fun_l25_n32()
+ fun_l26_n173
+end
+
+def fun_l25_n33()
+ fun_l26_n382
+end
+
+def fun_l25_n34()
+ fun_l26_n974
+end
+
+def fun_l25_n35()
+ fun_l26_n14
+end
+
+def fun_l25_n36()
+ fun_l26_n730
+end
+
+def fun_l25_n37()
+ fun_l26_n253
+end
+
+def fun_l25_n38()
+ fun_l26_n405
+end
+
+def fun_l25_n39()
+ fun_l26_n903
+end
+
+def fun_l25_n40()
+ fun_l26_n621
+end
+
+def fun_l25_n41()
+ fun_l26_n309
+end
+
+def fun_l25_n42()
+ fun_l26_n572
+end
+
+def fun_l25_n43()
+ fun_l26_n857
+end
+
+def fun_l25_n44()
+ fun_l26_n769
+end
+
+def fun_l25_n45()
+ fun_l26_n371
+end
+
+def fun_l25_n46()
+ fun_l26_n866
+end
+
+def fun_l25_n47()
+ fun_l26_n279
+end
+
+def fun_l25_n48()
+ fun_l26_n360
+end
+
+def fun_l25_n49()
+ fun_l26_n80
+end
+
+def fun_l25_n50()
+ fun_l26_n101
+end
+
+def fun_l25_n51()
+ fun_l26_n32
+end
+
+def fun_l25_n52()
+ fun_l26_n815
+end
+
+def fun_l25_n53()
+ fun_l26_n599
+end
+
+def fun_l25_n54()
+ fun_l26_n999
+end
+
+def fun_l25_n55()
+ fun_l26_n264
+end
+
+def fun_l25_n56()
+ fun_l26_n941
+end
+
+def fun_l25_n57()
+ fun_l26_n735
+end
+
+def fun_l25_n58()
+ fun_l26_n563
+end
+
+def fun_l25_n59()
+ fun_l26_n439
+end
+
+def fun_l25_n60()
+ fun_l26_n326
+end
+
+def fun_l25_n61()
+ fun_l26_n577
+end
+
+def fun_l25_n62()
+ fun_l26_n174
+end
+
+def fun_l25_n63()
+ fun_l26_n839
+end
+
+def fun_l25_n64()
+ fun_l26_n238
+end
+
+def fun_l25_n65()
+ fun_l26_n953
+end
+
+def fun_l25_n66()
+ fun_l26_n940
+end
+
+def fun_l25_n67()
+ fun_l26_n349
+end
+
+def fun_l25_n68()
+ fun_l26_n675
+end
+
+def fun_l25_n69()
+ fun_l26_n376
+end
+
+def fun_l25_n70()
+ fun_l26_n653
+end
+
+def fun_l25_n71()
+ fun_l26_n377
+end
+
+def fun_l25_n72()
+ fun_l26_n977
+end
+
+def fun_l25_n73()
+ fun_l26_n487
+end
+
+def fun_l25_n74()
+ fun_l26_n722
+end
+
+def fun_l25_n75()
+ fun_l26_n18
+end
+
+def fun_l25_n76()
+ fun_l26_n539
+end
+
+def fun_l25_n77()
+ fun_l26_n825
+end
+
+def fun_l25_n78()
+ fun_l26_n990
+end
+
+def fun_l25_n79()
+ fun_l26_n554
+end
+
+def fun_l25_n80()
+ fun_l26_n715
+end
+
+def fun_l25_n81()
+ fun_l26_n67
+end
+
+def fun_l25_n82()
+ fun_l26_n143
+end
+
+def fun_l25_n83()
+ fun_l26_n99
+end
+
+def fun_l25_n84()
+ fun_l26_n703
+end
+
+def fun_l25_n85()
+ fun_l26_n277
+end
+
+def fun_l25_n86()
+ fun_l26_n283
+end
+
+def fun_l25_n87()
+ fun_l26_n74
+end
+
+def fun_l25_n88()
+ fun_l26_n680
+end
+
+def fun_l25_n89()
+ fun_l26_n269
+end
+
+def fun_l25_n90()
+ fun_l26_n255
+end
+
+def fun_l25_n91()
+ fun_l26_n974
+end
+
+def fun_l25_n92()
+ fun_l26_n109
+end
+
+def fun_l25_n93()
+ fun_l26_n672
+end
+
+def fun_l25_n94()
+ fun_l26_n418
+end
+
+def fun_l25_n95()
+ fun_l26_n75
+end
+
+def fun_l25_n96()
+ fun_l26_n500
+end
+
+def fun_l25_n97()
+ fun_l26_n286
+end
+
+def fun_l25_n98()
+ fun_l26_n890
+end
+
+def fun_l25_n99()
+ fun_l26_n161
+end
+
+def fun_l25_n100()
+ fun_l26_n16
+end
+
+def fun_l25_n101()
+ fun_l26_n742
+end
+
+def fun_l25_n102()
+ fun_l26_n592
+end
+
+def fun_l25_n103()
+ fun_l26_n600
+end
+
+def fun_l25_n104()
+ fun_l26_n665
+end
+
+def fun_l25_n105()
+ fun_l26_n721
+end
+
+def fun_l25_n106()
+ fun_l26_n461
+end
+
+def fun_l25_n107()
+ fun_l26_n818
+end
+
+def fun_l25_n108()
+ fun_l26_n132
+end
+
+def fun_l25_n109()
+ fun_l26_n245
+end
+
+def fun_l25_n110()
+ fun_l26_n511
+end
+
+def fun_l25_n111()
+ fun_l26_n386
+end
+
+def fun_l25_n112()
+ fun_l26_n77
+end
+
+def fun_l25_n113()
+ fun_l26_n329
+end
+
+def fun_l25_n114()
+ fun_l26_n157
+end
+
+def fun_l25_n115()
+ fun_l26_n220
+end
+
+def fun_l25_n116()
+ fun_l26_n880
+end
+
+def fun_l25_n117()
+ fun_l26_n799
+end
+
+def fun_l25_n118()
+ fun_l26_n879
+end
+
+def fun_l25_n119()
+ fun_l26_n639
+end
+
+def fun_l25_n120()
+ fun_l26_n257
+end
+
+def fun_l25_n121()
+ fun_l26_n921
+end
+
+def fun_l25_n122()
+ fun_l26_n115
+end
+
+def fun_l25_n123()
+ fun_l26_n569
+end
+
+def fun_l25_n124()
+ fun_l26_n504
+end
+
+def fun_l25_n125()
+ fun_l26_n962
+end
+
+def fun_l25_n126()
+ fun_l26_n854
+end
+
+def fun_l25_n127()
+ fun_l26_n619
+end
+
+def fun_l25_n128()
+ fun_l26_n657
+end
+
+def fun_l25_n129()
+ fun_l26_n389
+end
+
+def fun_l25_n130()
+ fun_l26_n515
+end
+
+def fun_l25_n131()
+ fun_l26_n253
+end
+
+def fun_l25_n132()
+ fun_l26_n311
+end
+
+def fun_l25_n133()
+ fun_l26_n587
+end
+
+def fun_l25_n134()
+ fun_l26_n802
+end
+
+def fun_l25_n135()
+ fun_l26_n29
+end
+
+def fun_l25_n136()
+ fun_l26_n324
+end
+
+def fun_l25_n137()
+ fun_l26_n892
+end
+
+def fun_l25_n138()
+ fun_l26_n871
+end
+
+def fun_l25_n139()
+ fun_l26_n748
+end
+
+def fun_l25_n140()
+ fun_l26_n7
+end
+
+def fun_l25_n141()
+ fun_l26_n77
+end
+
+def fun_l25_n142()
+ fun_l26_n948
+end
+
+def fun_l25_n143()
+ fun_l26_n624
+end
+
+def fun_l25_n144()
+ fun_l26_n908
+end
+
+def fun_l25_n145()
+ fun_l26_n362
+end
+
+def fun_l25_n146()
+ fun_l26_n653
+end
+
+def fun_l25_n147()
+ fun_l26_n806
+end
+
+def fun_l25_n148()
+ fun_l26_n959
+end
+
+def fun_l25_n149()
+ fun_l26_n677
+end
+
+def fun_l25_n150()
+ fun_l26_n697
+end
+
+def fun_l25_n151()
+ fun_l26_n12
+end
+
+def fun_l25_n152()
+ fun_l26_n67
+end
+
+def fun_l25_n153()
+ fun_l26_n451
+end
+
+def fun_l25_n154()
+ fun_l26_n887
+end
+
+def fun_l25_n155()
+ fun_l26_n908
+end
+
+def fun_l25_n156()
+ fun_l26_n382
+end
+
+def fun_l25_n157()
+ fun_l26_n977
+end
+
+def fun_l25_n158()
+ fun_l26_n62
+end
+
+def fun_l25_n159()
+ fun_l26_n307
+end
+
+def fun_l25_n160()
+ fun_l26_n583
+end
+
+def fun_l25_n161()
+ fun_l26_n291
+end
+
+def fun_l25_n162()
+ fun_l26_n736
+end
+
+def fun_l25_n163()
+ fun_l26_n954
+end
+
+def fun_l25_n164()
+ fun_l26_n414
+end
+
+def fun_l25_n165()
+ fun_l26_n945
+end
+
+def fun_l25_n166()
+ fun_l26_n947
+end
+
+def fun_l25_n167()
+ fun_l26_n639
+end
+
+def fun_l25_n168()
+ fun_l26_n875
+end
+
+def fun_l25_n169()
+ fun_l26_n994
+end
+
+def fun_l25_n170()
+ fun_l26_n855
+end
+
+def fun_l25_n171()
+ fun_l26_n539
+end
+
+def fun_l25_n172()
+ fun_l26_n108
+end
+
+def fun_l25_n173()
+ fun_l26_n806
+end
+
+def fun_l25_n174()
+ fun_l26_n838
+end
+
+def fun_l25_n175()
+ fun_l26_n688
+end
+
+def fun_l25_n176()
+ fun_l26_n696
+end
+
+def fun_l25_n177()
+ fun_l26_n979
+end
+
+def fun_l25_n178()
+ fun_l26_n261
+end
+
+def fun_l25_n179()
+ fun_l26_n266
+end
+
+def fun_l25_n180()
+ fun_l26_n907
+end
+
+def fun_l25_n181()
+ fun_l26_n622
+end
+
+def fun_l25_n182()
+ fun_l26_n42
+end
+
+def fun_l25_n183()
+ fun_l26_n840
+end
+
+def fun_l25_n184()
+ fun_l26_n125
+end
+
+def fun_l25_n185()
+ fun_l26_n402
+end
+
+def fun_l25_n186()
+ fun_l26_n401
+end
+
+def fun_l25_n187()
+ fun_l26_n410
+end
+
+def fun_l25_n188()
+ fun_l26_n552
+end
+
+def fun_l25_n189()
+ fun_l26_n528
+end
+
+def fun_l25_n190()
+ fun_l26_n171
+end
+
+def fun_l25_n191()
+ fun_l26_n787
+end
+
+def fun_l25_n192()
+ fun_l26_n453
+end
+
+def fun_l25_n193()
+ fun_l26_n107
+end
+
+def fun_l25_n194()
+ fun_l26_n171
+end
+
+def fun_l25_n195()
+ fun_l26_n159
+end
+
+def fun_l25_n196()
+ fun_l26_n801
+end
+
+def fun_l25_n197()
+ fun_l26_n569
+end
+
+def fun_l25_n198()
+ fun_l26_n899
+end
+
+def fun_l25_n199()
+ fun_l26_n434
+end
+
+def fun_l25_n200()
+ fun_l26_n943
+end
+
+def fun_l25_n201()
+ fun_l26_n455
+end
+
+def fun_l25_n202()
+ fun_l26_n239
+end
+
+def fun_l25_n203()
+ fun_l26_n892
+end
+
+def fun_l25_n204()
+ fun_l26_n332
+end
+
+def fun_l25_n205()
+ fun_l26_n95
+end
+
+def fun_l25_n206()
+ fun_l26_n735
+end
+
+def fun_l25_n207()
+ fun_l26_n517
+end
+
+def fun_l25_n208()
+ fun_l26_n41
+end
+
+def fun_l25_n209()
+ fun_l26_n827
+end
+
+def fun_l25_n210()
+ fun_l26_n557
+end
+
+def fun_l25_n211()
+ fun_l26_n184
+end
+
+def fun_l25_n212()
+ fun_l26_n123
+end
+
+def fun_l25_n213()
+ fun_l26_n476
+end
+
+def fun_l25_n214()
+ fun_l26_n346
+end
+
+def fun_l25_n215()
+ fun_l26_n720
+end
+
+def fun_l25_n216()
+ fun_l26_n905
+end
+
+def fun_l25_n217()
+ fun_l26_n911
+end
+
+def fun_l25_n218()
+ fun_l26_n317
+end
+
+def fun_l25_n219()
+ fun_l26_n930
+end
+
+def fun_l25_n220()
+ fun_l26_n539
+end
+
+def fun_l25_n221()
+ fun_l26_n173
+end
+
+def fun_l25_n222()
+ fun_l26_n441
+end
+
+def fun_l25_n223()
+ fun_l26_n345
+end
+
+def fun_l25_n224()
+ fun_l26_n463
+end
+
+def fun_l25_n225()
+ fun_l26_n568
+end
+
+def fun_l25_n226()
+ fun_l26_n783
+end
+
+def fun_l25_n227()
+ fun_l26_n359
+end
+
+def fun_l25_n228()
+ fun_l26_n523
+end
+
+def fun_l25_n229()
+ fun_l26_n895
+end
+
+def fun_l25_n230()
+ fun_l26_n159
+end
+
+def fun_l25_n231()
+ fun_l26_n259
+end
+
+def fun_l25_n232()
+ fun_l26_n373
+end
+
+def fun_l25_n233()
+ fun_l26_n471
+end
+
+def fun_l25_n234()
+ fun_l26_n448
+end
+
+def fun_l25_n235()
+ fun_l26_n139
+end
+
+def fun_l25_n236()
+ fun_l26_n795
+end
+
+def fun_l25_n237()
+ fun_l26_n492
+end
+
+def fun_l25_n238()
+ fun_l26_n292
+end
+
+def fun_l25_n239()
+ fun_l26_n253
+end
+
+def fun_l25_n240()
+ fun_l26_n870
+end
+
+def fun_l25_n241()
+ fun_l26_n504
+end
+
+def fun_l25_n242()
+ fun_l26_n315
+end
+
+def fun_l25_n243()
+ fun_l26_n542
+end
+
+def fun_l25_n244()
+ fun_l26_n368
+end
+
+def fun_l25_n245()
+ fun_l26_n954
+end
+
+def fun_l25_n246()
+ fun_l26_n589
+end
+
+def fun_l25_n247()
+ fun_l26_n102
+end
+
+def fun_l25_n248()
+ fun_l26_n839
+end
+
+def fun_l25_n249()
+ fun_l26_n493
+end
+
+def fun_l25_n250()
+ fun_l26_n90
+end
+
+def fun_l25_n251()
+ fun_l26_n974
+end
+
+def fun_l25_n252()
+ fun_l26_n878
+end
+
+def fun_l25_n253()
+ fun_l26_n205
+end
+
+def fun_l25_n254()
+ fun_l26_n485
+end
+
+def fun_l25_n255()
+ fun_l26_n976
+end
+
+def fun_l25_n256()
+ fun_l26_n397
+end
+
+def fun_l25_n257()
+ fun_l26_n593
+end
+
+def fun_l25_n258()
+ fun_l26_n925
+end
+
+def fun_l25_n259()
+ fun_l26_n223
+end
+
+def fun_l25_n260()
+ fun_l26_n491
+end
+
+def fun_l25_n261()
+ fun_l26_n441
+end
+
+def fun_l25_n262()
+ fun_l26_n472
+end
+
+def fun_l25_n263()
+ fun_l26_n357
+end
+
+def fun_l25_n264()
+ fun_l26_n90
+end
+
+def fun_l25_n265()
+ fun_l26_n124
+end
+
+def fun_l25_n266()
+ fun_l26_n607
+end
+
+def fun_l25_n267()
+ fun_l26_n484
+end
+
+def fun_l25_n268()
+ fun_l26_n448
+end
+
+def fun_l25_n269()
+ fun_l26_n456
+end
+
+def fun_l25_n270()
+ fun_l26_n108
+end
+
+def fun_l25_n271()
+ fun_l26_n268
+end
+
+def fun_l25_n272()
+ fun_l26_n250
+end
+
+def fun_l25_n273()
+ fun_l26_n354
+end
+
+def fun_l25_n274()
+ fun_l26_n234
+end
+
+def fun_l25_n275()
+ fun_l26_n833
+end
+
+def fun_l25_n276()
+ fun_l26_n404
+end
+
+def fun_l25_n277()
+ fun_l26_n296
+end
+
+def fun_l25_n278()
+ fun_l26_n640
+end
+
+def fun_l25_n279()
+ fun_l26_n633
+end
+
+def fun_l25_n280()
+ fun_l26_n119
+end
+
+def fun_l25_n281()
+ fun_l26_n272
+end
+
+def fun_l25_n282()
+ fun_l26_n4
+end
+
+def fun_l25_n283()
+ fun_l26_n217
+end
+
+def fun_l25_n284()
+ fun_l26_n923
+end
+
+def fun_l25_n285()
+ fun_l26_n911
+end
+
+def fun_l25_n286()
+ fun_l26_n332
+end
+
+def fun_l25_n287()
+ fun_l26_n83
+end
+
+def fun_l25_n288()
+ fun_l26_n396
+end
+
+def fun_l25_n289()
+ fun_l26_n423
+end
+
+def fun_l25_n290()
+ fun_l26_n182
+end
+
+def fun_l25_n291()
+ fun_l26_n69
+end
+
+def fun_l25_n292()
+ fun_l26_n348
+end
+
+def fun_l25_n293()
+ fun_l26_n85
+end
+
+def fun_l25_n294()
+ fun_l26_n727
+end
+
+def fun_l25_n295()
+ fun_l26_n488
+end
+
+def fun_l25_n296()
+ fun_l26_n629
+end
+
+def fun_l25_n297()
+ fun_l26_n92
+end
+
+def fun_l25_n298()
+ fun_l26_n737
+end
+
+def fun_l25_n299()
+ fun_l26_n68
+end
+
+def fun_l25_n300()
+ fun_l26_n148
+end
+
+def fun_l25_n301()
+ fun_l26_n292
+end
+
+def fun_l25_n302()
+ fun_l26_n836
+end
+
+def fun_l25_n303()
+ fun_l26_n992
+end
+
+def fun_l25_n304()
+ fun_l26_n894
+end
+
+def fun_l25_n305()
+ fun_l26_n850
+end
+
+def fun_l25_n306()
+ fun_l26_n63
+end
+
+def fun_l25_n307()
+ fun_l26_n321
+end
+
+def fun_l25_n308()
+ fun_l26_n497
+end
+
+def fun_l25_n309()
+ fun_l26_n757
+end
+
+def fun_l25_n310()
+ fun_l26_n331
+end
+
+def fun_l25_n311()
+ fun_l26_n522
+end
+
+def fun_l25_n312()
+ fun_l26_n815
+end
+
+def fun_l25_n313()
+ fun_l26_n545
+end
+
+def fun_l25_n314()
+ fun_l26_n78
+end
+
+def fun_l25_n315()
+ fun_l26_n474
+end
+
+def fun_l25_n316()
+ fun_l26_n329
+end
+
+def fun_l25_n317()
+ fun_l26_n19
+end
+
+def fun_l25_n318()
+ fun_l26_n85
+end
+
+def fun_l25_n319()
+ fun_l26_n548
+end
+
+def fun_l25_n320()
+ fun_l26_n435
+end
+
+def fun_l25_n321()
+ fun_l26_n607
+end
+
+def fun_l25_n322()
+ fun_l26_n610
+end
+
+def fun_l25_n323()
+ fun_l26_n218
+end
+
+def fun_l25_n324()
+ fun_l26_n664
+end
+
+def fun_l25_n325()
+ fun_l26_n869
+end
+
+def fun_l25_n326()
+ fun_l26_n110
+end
+
+def fun_l25_n327()
+ fun_l26_n811
+end
+
+def fun_l25_n328()
+ fun_l26_n70
+end
+
+def fun_l25_n329()
+ fun_l26_n852
+end
+
+def fun_l25_n330()
+ fun_l26_n772
+end
+
+def fun_l25_n331()
+ fun_l26_n367
+end
+
+def fun_l25_n332()
+ fun_l26_n34
+end
+
+def fun_l25_n333()
+ fun_l26_n470
+end
+
+def fun_l25_n334()
+ fun_l26_n962
+end
+
+def fun_l25_n335()
+ fun_l26_n957
+end
+
+def fun_l25_n336()
+ fun_l26_n608
+end
+
+def fun_l25_n337()
+ fun_l26_n632
+end
+
+def fun_l25_n338()
+ fun_l26_n960
+end
+
+def fun_l25_n339()
+ fun_l26_n584
+end
+
+def fun_l25_n340()
+ fun_l26_n500
+end
+
+def fun_l25_n341()
+ fun_l26_n317
+end
+
+def fun_l25_n342()
+ fun_l26_n772
+end
+
+def fun_l25_n343()
+ fun_l26_n741
+end
+
+def fun_l25_n344()
+ fun_l26_n584
+end
+
+def fun_l25_n345()
+ fun_l26_n221
+end
+
+def fun_l25_n346()
+ fun_l26_n809
+end
+
+def fun_l25_n347()
+ fun_l26_n28
+end
+
+def fun_l25_n348()
+ fun_l26_n111
+end
+
+def fun_l25_n349()
+ fun_l26_n499
+end
+
+def fun_l25_n350()
+ fun_l26_n35
+end
+
+def fun_l25_n351()
+ fun_l26_n885
+end
+
+def fun_l25_n352()
+ fun_l26_n516
+end
+
+def fun_l25_n353()
+ fun_l26_n394
+end
+
+def fun_l25_n354()
+ fun_l26_n792
+end
+
+def fun_l25_n355()
+ fun_l26_n741
+end
+
+def fun_l25_n356()
+ fun_l26_n851
+end
+
+def fun_l25_n357()
+ fun_l26_n483
+end
+
+def fun_l25_n358()
+ fun_l26_n464
+end
+
+def fun_l25_n359()
+ fun_l26_n886
+end
+
+def fun_l25_n360()
+ fun_l26_n479
+end
+
+def fun_l25_n361()
+ fun_l26_n31
+end
+
+def fun_l25_n362()
+ fun_l26_n154
+end
+
+def fun_l25_n363()
+ fun_l26_n178
+end
+
+def fun_l25_n364()
+ fun_l26_n390
+end
+
+def fun_l25_n365()
+ fun_l26_n597
+end
+
+def fun_l25_n366()
+ fun_l26_n85
+end
+
+def fun_l25_n367()
+ fun_l26_n614
+end
+
+def fun_l25_n368()
+ fun_l26_n796
+end
+
+def fun_l25_n369()
+ fun_l26_n627
+end
+
+def fun_l25_n370()
+ fun_l26_n581
+end
+
+def fun_l25_n371()
+ fun_l26_n63
+end
+
+def fun_l25_n372()
+ fun_l26_n708
+end
+
+def fun_l25_n373()
+ fun_l26_n858
+end
+
+def fun_l25_n374()
+ fun_l26_n143
+end
+
+def fun_l25_n375()
+ fun_l26_n742
+end
+
+def fun_l25_n376()
+ fun_l26_n54
+end
+
+def fun_l25_n377()
+ fun_l26_n299
+end
+
+def fun_l25_n378()
+ fun_l26_n465
+end
+
+def fun_l25_n379()
+ fun_l26_n207
+end
+
+def fun_l25_n380()
+ fun_l26_n3
+end
+
+def fun_l25_n381()
+ fun_l26_n648
+end
+
+def fun_l25_n382()
+ fun_l26_n7
+end
+
+def fun_l25_n383()
+ fun_l26_n586
+end
+
+def fun_l25_n384()
+ fun_l26_n884
+end
+
+def fun_l25_n385()
+ fun_l26_n731
+end
+
+def fun_l25_n386()
+ fun_l26_n60
+end
+
+def fun_l25_n387()
+ fun_l26_n600
+end
+
+def fun_l25_n388()
+ fun_l26_n162
+end
+
+def fun_l25_n389()
+ fun_l26_n229
+end
+
+def fun_l25_n390()
+ fun_l26_n60
+end
+
+def fun_l25_n391()
+ fun_l26_n617
+end
+
+def fun_l25_n392()
+ fun_l26_n823
+end
+
+def fun_l25_n393()
+ fun_l26_n546
+end
+
+def fun_l25_n394()
+ fun_l26_n783
+end
+
+def fun_l25_n395()
+ fun_l26_n616
+end
+
+def fun_l25_n396()
+ fun_l26_n131
+end
+
+def fun_l25_n397()
+ fun_l26_n744
+end
+
+def fun_l25_n398()
+ fun_l26_n344
+end
+
+def fun_l25_n399()
+ fun_l26_n529
+end
+
+def fun_l25_n400()
+ fun_l26_n314
+end
+
+def fun_l25_n401()
+ fun_l26_n571
+end
+
+def fun_l25_n402()
+ fun_l26_n329
+end
+
+def fun_l25_n403()
+ fun_l26_n334
+end
+
+def fun_l25_n404()
+ fun_l26_n232
+end
+
+def fun_l25_n405()
+ fun_l26_n864
+end
+
+def fun_l25_n406()
+ fun_l26_n882
+end
+
+def fun_l25_n407()
+ fun_l26_n153
+end
+
+def fun_l25_n408()
+ fun_l26_n770
+end
+
+def fun_l25_n409()
+ fun_l26_n199
+end
+
+def fun_l25_n410()
+ fun_l26_n799
+end
+
+def fun_l25_n411()
+ fun_l26_n306
+end
+
+def fun_l25_n412()
+ fun_l26_n957
+end
+
+def fun_l25_n413()
+ fun_l26_n519
+end
+
+def fun_l25_n414()
+ fun_l26_n445
+end
+
+def fun_l25_n415()
+ fun_l26_n272
+end
+
+def fun_l25_n416()
+ fun_l26_n119
+end
+
+def fun_l25_n417()
+ fun_l26_n143
+end
+
+def fun_l25_n418()
+ fun_l26_n964
+end
+
+def fun_l25_n419()
+ fun_l26_n574
+end
+
+def fun_l25_n420()
+ fun_l26_n215
+end
+
+def fun_l25_n421()
+ fun_l26_n144
+end
+
+def fun_l25_n422()
+ fun_l26_n345
+end
+
+def fun_l25_n423()
+ fun_l26_n121
+end
+
+def fun_l25_n424()
+ fun_l26_n77
+end
+
+def fun_l25_n425()
+ fun_l26_n112
+end
+
+def fun_l25_n426()
+ fun_l26_n992
+end
+
+def fun_l25_n427()
+ fun_l26_n320
+end
+
+def fun_l25_n428()
+ fun_l26_n980
+end
+
+def fun_l25_n429()
+ fun_l26_n442
+end
+
+def fun_l25_n430()
+ fun_l26_n422
+end
+
+def fun_l25_n431()
+ fun_l26_n164
+end
+
+def fun_l25_n432()
+ fun_l26_n778
+end
+
+def fun_l25_n433()
+ fun_l26_n330
+end
+
+def fun_l25_n434()
+ fun_l26_n535
+end
+
+def fun_l25_n435()
+ fun_l26_n149
+end
+
+def fun_l25_n436()
+ fun_l26_n411
+end
+
+def fun_l25_n437()
+ fun_l26_n465
+end
+
+def fun_l25_n438()
+ fun_l26_n231
+end
+
+def fun_l25_n439()
+ fun_l26_n542
+end
+
+def fun_l25_n440()
+ fun_l26_n720
+end
+
+def fun_l25_n441()
+ fun_l26_n883
+end
+
+def fun_l25_n442()
+ fun_l26_n258
+end
+
+def fun_l25_n443()
+ fun_l26_n633
+end
+
+def fun_l25_n444()
+ fun_l26_n715
+end
+
+def fun_l25_n445()
+ fun_l26_n844
+end
+
+def fun_l25_n446()
+ fun_l26_n837
+end
+
+def fun_l25_n447()
+ fun_l26_n161
+end
+
+def fun_l25_n448()
+ fun_l26_n389
+end
+
+def fun_l25_n449()
+ fun_l26_n246
+end
+
+def fun_l25_n450()
+ fun_l26_n570
+end
+
+def fun_l25_n451()
+ fun_l26_n678
+end
+
+def fun_l25_n452()
+ fun_l26_n243
+end
+
+def fun_l25_n453()
+ fun_l26_n430
+end
+
+def fun_l25_n454()
+ fun_l26_n193
+end
+
+def fun_l25_n455()
+ fun_l26_n666
+end
+
+def fun_l25_n456()
+ fun_l26_n881
+end
+
+def fun_l25_n457()
+ fun_l26_n989
+end
+
+def fun_l25_n458()
+ fun_l26_n450
+end
+
+def fun_l25_n459()
+ fun_l26_n675
+end
+
+def fun_l25_n460()
+ fun_l26_n315
+end
+
+def fun_l25_n461()
+ fun_l26_n40
+end
+
+def fun_l25_n462()
+ fun_l26_n639
+end
+
+def fun_l25_n463()
+ fun_l26_n380
+end
+
+def fun_l25_n464()
+ fun_l26_n680
+end
+
+def fun_l25_n465()
+ fun_l26_n54
+end
+
+def fun_l25_n466()
+ fun_l26_n37
+end
+
+def fun_l25_n467()
+ fun_l26_n910
+end
+
+def fun_l25_n468()
+ fun_l26_n50
+end
+
+def fun_l25_n469()
+ fun_l26_n925
+end
+
+def fun_l25_n470()
+ fun_l26_n385
+end
+
+def fun_l25_n471()
+ fun_l26_n860
+end
+
+def fun_l25_n472()
+ fun_l26_n547
+end
+
+def fun_l25_n473()
+ fun_l26_n31
+end
+
+def fun_l25_n474()
+ fun_l26_n338
+end
+
+def fun_l25_n475()
+ fun_l26_n706
+end
+
+def fun_l25_n476()
+ fun_l26_n81
+end
+
+def fun_l25_n477()
+ fun_l26_n532
+end
+
+def fun_l25_n478()
+ fun_l26_n781
+end
+
+def fun_l25_n479()
+ fun_l26_n588
+end
+
+def fun_l25_n480()
+ fun_l26_n658
+end
+
+def fun_l25_n481()
+ fun_l26_n344
+end
+
+def fun_l25_n482()
+ fun_l26_n914
+end
+
+def fun_l25_n483()
+ fun_l26_n319
+end
+
+def fun_l25_n484()
+ fun_l26_n138
+end
+
+def fun_l25_n485()
+ fun_l26_n927
+end
+
+def fun_l25_n486()
+ fun_l26_n409
+end
+
+def fun_l25_n487()
+ fun_l26_n721
+end
+
+def fun_l25_n488()
+ fun_l26_n197
+end
+
+def fun_l25_n489()
+ fun_l26_n654
+end
+
+def fun_l25_n490()
+ fun_l26_n298
+end
+
+def fun_l25_n491()
+ fun_l26_n763
+end
+
+def fun_l25_n492()
+ fun_l26_n729
+end
+
+def fun_l25_n493()
+ fun_l26_n532
+end
+
+def fun_l25_n494()
+ fun_l26_n508
+end
+
+def fun_l25_n495()
+ fun_l26_n725
+end
+
+def fun_l25_n496()
+ fun_l26_n665
+end
+
+def fun_l25_n497()
+ fun_l26_n21
+end
+
+def fun_l25_n498()
+ fun_l26_n314
+end
+
+def fun_l25_n499()
+ fun_l26_n823
+end
+
+def fun_l25_n500()
+ fun_l26_n983
+end
+
+def fun_l25_n501()
+ fun_l26_n477
+end
+
+def fun_l25_n502()
+ fun_l26_n502
+end
+
+def fun_l25_n503()
+ fun_l26_n731
+end
+
+def fun_l25_n504()
+ fun_l26_n427
+end
+
+def fun_l25_n505()
+ fun_l26_n949
+end
+
+def fun_l25_n506()
+ fun_l26_n566
+end
+
+def fun_l25_n507()
+ fun_l26_n407
+end
+
+def fun_l25_n508()
+ fun_l26_n427
+end
+
+def fun_l25_n509()
+ fun_l26_n423
+end
+
+def fun_l25_n510()
+ fun_l26_n394
+end
+
+def fun_l25_n511()
+ fun_l26_n584
+end
+
+def fun_l25_n512()
+ fun_l26_n35
+end
+
+def fun_l25_n513()
+ fun_l26_n89
+end
+
+def fun_l25_n514()
+ fun_l26_n369
+end
+
+def fun_l25_n515()
+ fun_l26_n483
+end
+
+def fun_l25_n516()
+ fun_l26_n897
+end
+
+def fun_l25_n517()
+ fun_l26_n39
+end
+
+def fun_l25_n518()
+ fun_l26_n904
+end
+
+def fun_l25_n519()
+ fun_l26_n264
+end
+
+def fun_l25_n520()
+ fun_l26_n806
+end
+
+def fun_l25_n521()
+ fun_l26_n206
+end
+
+def fun_l25_n522()
+ fun_l26_n417
+end
+
+def fun_l25_n523()
+ fun_l26_n235
+end
+
+def fun_l25_n524()
+ fun_l26_n192
+end
+
+def fun_l25_n525()
+ fun_l26_n62
+end
+
+def fun_l25_n526()
+ fun_l26_n295
+end
+
+def fun_l25_n527()
+ fun_l26_n998
+end
+
+def fun_l25_n528()
+ fun_l26_n898
+end
+
+def fun_l25_n529()
+ fun_l26_n705
+end
+
+def fun_l25_n530()
+ fun_l26_n571
+end
+
+def fun_l25_n531()
+ fun_l26_n883
+end
+
+def fun_l25_n532()
+ fun_l26_n198
+end
+
+def fun_l25_n533()
+ fun_l26_n893
+end
+
+def fun_l25_n534()
+ fun_l26_n849
+end
+
+def fun_l25_n535()
+ fun_l26_n540
+end
+
+def fun_l25_n536()
+ fun_l26_n509
+end
+
+def fun_l25_n537()
+ fun_l26_n889
+end
+
+def fun_l25_n538()
+ fun_l26_n981
+end
+
+def fun_l25_n539()
+ fun_l26_n477
+end
+
+def fun_l25_n540()
+ fun_l26_n908
+end
+
+def fun_l25_n541()
+ fun_l26_n455
+end
+
+def fun_l25_n542()
+ fun_l26_n547
+end
+
+def fun_l25_n543()
+ fun_l26_n487
+end
+
+def fun_l25_n544()
+ fun_l26_n365
+end
+
+def fun_l25_n545()
+ fun_l26_n853
+end
+
+def fun_l25_n546()
+ fun_l26_n591
+end
+
+def fun_l25_n547()
+ fun_l26_n298
+end
+
+def fun_l25_n548()
+ fun_l26_n529
+end
+
+def fun_l25_n549()
+ fun_l26_n191
+end
+
+def fun_l25_n550()
+ fun_l26_n118
+end
+
+def fun_l25_n551()
+ fun_l26_n82
+end
+
+def fun_l25_n552()
+ fun_l26_n874
+end
+
+def fun_l25_n553()
+ fun_l26_n924
+end
+
+def fun_l25_n554()
+ fun_l26_n683
+end
+
+def fun_l25_n555()
+ fun_l26_n163
+end
+
+def fun_l25_n556()
+ fun_l26_n935
+end
+
+def fun_l25_n557()
+ fun_l26_n657
+end
+
+def fun_l25_n558()
+ fun_l26_n17
+end
+
+def fun_l25_n559()
+ fun_l26_n578
+end
+
+def fun_l25_n560()
+ fun_l26_n105
+end
+
+def fun_l25_n561()
+ fun_l26_n280
+end
+
+def fun_l25_n562()
+ fun_l26_n130
+end
+
+def fun_l25_n563()
+ fun_l26_n824
+end
+
+def fun_l25_n564()
+ fun_l26_n376
+end
+
+def fun_l25_n565()
+ fun_l26_n942
+end
+
+def fun_l25_n566()
+ fun_l26_n771
+end
+
+def fun_l25_n567()
+ fun_l26_n245
+end
+
+def fun_l25_n568()
+ fun_l26_n361
+end
+
+def fun_l25_n569()
+ fun_l26_n328
+end
+
+def fun_l25_n570()
+ fun_l26_n718
+end
+
+def fun_l25_n571()
+ fun_l26_n918
+end
+
+def fun_l25_n572()
+ fun_l26_n592
+end
+
+def fun_l25_n573()
+ fun_l26_n690
+end
+
+def fun_l25_n574()
+ fun_l26_n689
+end
+
+def fun_l25_n575()
+ fun_l26_n571
+end
+
+def fun_l25_n576()
+ fun_l26_n106
+end
+
+def fun_l25_n577()
+ fun_l26_n917
+end
+
+def fun_l25_n578()
+ fun_l26_n954
+end
+
+def fun_l25_n579()
+ fun_l26_n842
+end
+
+def fun_l25_n580()
+ fun_l26_n277
+end
+
+def fun_l25_n581()
+ fun_l26_n511
+end
+
+def fun_l25_n582()
+ fun_l26_n834
+end
+
+def fun_l25_n583()
+ fun_l26_n992
+end
+
+def fun_l25_n584()
+ fun_l26_n711
+end
+
+def fun_l25_n585()
+ fun_l26_n366
+end
+
+def fun_l25_n586()
+ fun_l26_n960
+end
+
+def fun_l25_n587()
+ fun_l26_n229
+end
+
+def fun_l25_n588()
+ fun_l26_n208
+end
+
+def fun_l25_n589()
+ fun_l26_n758
+end
+
+def fun_l25_n590()
+ fun_l26_n98
+end
+
+def fun_l25_n591()
+ fun_l26_n452
+end
+
+def fun_l25_n592()
+ fun_l26_n526
+end
+
+def fun_l25_n593()
+ fun_l26_n92
+end
+
+def fun_l25_n594()
+ fun_l26_n108
+end
+
+def fun_l25_n595()
+ fun_l26_n250
+end
+
+def fun_l25_n596()
+ fun_l26_n186
+end
+
+def fun_l25_n597()
+ fun_l26_n603
+end
+
+def fun_l25_n598()
+ fun_l26_n828
+end
+
+def fun_l25_n599()
+ fun_l26_n610
+end
+
+def fun_l25_n600()
+ fun_l26_n280
+end
+
+def fun_l25_n601()
+ fun_l26_n158
+end
+
+def fun_l25_n602()
+ fun_l26_n386
+end
+
+def fun_l25_n603()
+ fun_l26_n869
+end
+
+def fun_l25_n604()
+ fun_l26_n483
+end
+
+def fun_l25_n605()
+ fun_l26_n682
+end
+
+def fun_l25_n606()
+ fun_l26_n175
+end
+
+def fun_l25_n607()
+ fun_l26_n991
+end
+
+def fun_l25_n608()
+ fun_l26_n165
+end
+
+def fun_l25_n609()
+ fun_l26_n303
+end
+
+def fun_l25_n610()
+ fun_l26_n812
+end
+
+def fun_l25_n611()
+ fun_l26_n563
+end
+
+def fun_l25_n612()
+ fun_l26_n635
+end
+
+def fun_l25_n613()
+ fun_l26_n256
+end
+
+def fun_l25_n614()
+ fun_l26_n96
+end
+
+def fun_l25_n615()
+ fun_l26_n8
+end
+
+def fun_l25_n616()
+ fun_l26_n963
+end
+
+def fun_l25_n617()
+ fun_l26_n860
+end
+
+def fun_l25_n618()
+ fun_l26_n316
+end
+
+def fun_l25_n619()
+ fun_l26_n388
+end
+
+def fun_l25_n620()
+ fun_l26_n427
+end
+
+def fun_l25_n621()
+ fun_l26_n519
+end
+
+def fun_l25_n622()
+ fun_l26_n780
+end
+
+def fun_l25_n623()
+ fun_l26_n142
+end
+
+def fun_l25_n624()
+ fun_l26_n271
+end
+
+def fun_l25_n625()
+ fun_l26_n617
+end
+
+def fun_l25_n626()
+ fun_l26_n968
+end
+
+def fun_l25_n627()
+ fun_l26_n880
+end
+
+def fun_l25_n628()
+ fun_l26_n831
+end
+
+def fun_l25_n629()
+ fun_l26_n616
+end
+
+def fun_l25_n630()
+ fun_l26_n213
+end
+
+def fun_l25_n631()
+ fun_l26_n91
+end
+
+def fun_l25_n632()
+ fun_l26_n295
+end
+
+def fun_l25_n633()
+ fun_l26_n314
+end
+
+def fun_l25_n634()
+ fun_l26_n174
+end
+
+def fun_l25_n635()
+ fun_l26_n668
+end
+
+def fun_l25_n636()
+ fun_l26_n962
+end
+
+def fun_l25_n637()
+ fun_l26_n1
+end
+
+def fun_l25_n638()
+ fun_l26_n361
+end
+
+def fun_l25_n639()
+ fun_l26_n947
+end
+
+def fun_l25_n640()
+ fun_l26_n381
+end
+
+def fun_l25_n641()
+ fun_l26_n388
+end
+
+def fun_l25_n642()
+ fun_l26_n5
+end
+
+def fun_l25_n643()
+ fun_l26_n759
+end
+
+def fun_l25_n644()
+ fun_l26_n454
+end
+
+def fun_l25_n645()
+ fun_l26_n596
+end
+
+def fun_l25_n646()
+ fun_l26_n639
+end
+
+def fun_l25_n647()
+ fun_l26_n156
+end
+
+def fun_l25_n648()
+ fun_l26_n395
+end
+
+def fun_l25_n649()
+ fun_l26_n424
+end
+
+def fun_l25_n650()
+ fun_l26_n21
+end
+
+def fun_l25_n651()
+ fun_l26_n285
+end
+
+def fun_l25_n652()
+ fun_l26_n72
+end
+
+def fun_l25_n653()
+ fun_l26_n25
+end
+
+def fun_l25_n654()
+ fun_l26_n381
+end
+
+def fun_l25_n655()
+ fun_l26_n166
+end
+
+def fun_l25_n656()
+ fun_l26_n850
+end
+
+def fun_l25_n657()
+ fun_l26_n794
+end
+
+def fun_l25_n658()
+ fun_l26_n674
+end
+
+def fun_l25_n659()
+ fun_l26_n934
+end
+
+def fun_l25_n660()
+ fun_l26_n164
+end
+
+def fun_l25_n661()
+ fun_l26_n325
+end
+
+def fun_l25_n662()
+ fun_l26_n514
+end
+
+def fun_l25_n663()
+ fun_l26_n489
+end
+
+def fun_l25_n664()
+ fun_l26_n268
+end
+
+def fun_l25_n665()
+ fun_l26_n4
+end
+
+def fun_l25_n666()
+ fun_l26_n330
+end
+
+def fun_l25_n667()
+ fun_l26_n749
+end
+
+def fun_l25_n668()
+ fun_l26_n324
+end
+
+def fun_l25_n669()
+ fun_l26_n228
+end
+
+def fun_l25_n670()
+ fun_l26_n740
+end
+
+def fun_l25_n671()
+ fun_l26_n240
+end
+
+def fun_l25_n672()
+ fun_l26_n145
+end
+
+def fun_l25_n673()
+ fun_l26_n170
+end
+
+def fun_l25_n674()
+ fun_l26_n222
+end
+
+def fun_l25_n675()
+ fun_l26_n680
+end
+
+def fun_l25_n676()
+ fun_l26_n115
+end
+
+def fun_l25_n677()
+ fun_l26_n359
+end
+
+def fun_l25_n678()
+ fun_l26_n482
+end
+
+def fun_l25_n679()
+ fun_l26_n251
+end
+
+def fun_l25_n680()
+ fun_l26_n95
+end
+
+def fun_l25_n681()
+ fun_l26_n587
+end
+
+def fun_l25_n682()
+ fun_l26_n689
+end
+
+def fun_l25_n683()
+ fun_l26_n317
+end
+
+def fun_l25_n684()
+ fun_l26_n913
+end
+
+def fun_l25_n685()
+ fun_l26_n943
+end
+
+def fun_l25_n686()
+ fun_l26_n770
+end
+
+def fun_l25_n687()
+ fun_l26_n204
+end
+
+def fun_l25_n688()
+ fun_l26_n690
+end
+
+def fun_l25_n689()
+ fun_l26_n745
+end
+
+def fun_l25_n690()
+ fun_l26_n640
+end
+
+def fun_l25_n691()
+ fun_l26_n34
+end
+
+def fun_l25_n692()
+ fun_l26_n296
+end
+
+def fun_l25_n693()
+ fun_l26_n900
+end
+
+def fun_l25_n694()
+ fun_l26_n619
+end
+
+def fun_l25_n695()
+ fun_l26_n81
+end
+
+def fun_l25_n696()
+ fun_l26_n748
+end
+
+def fun_l25_n697()
+ fun_l26_n395
+end
+
+def fun_l25_n698()
+ fun_l26_n518
+end
+
+def fun_l25_n699()
+ fun_l26_n338
+end
+
+def fun_l25_n700()
+ fun_l26_n238
+end
+
+def fun_l25_n701()
+ fun_l26_n445
+end
+
+def fun_l25_n702()
+ fun_l26_n732
+end
+
+def fun_l25_n703()
+ fun_l26_n378
+end
+
+def fun_l25_n704()
+ fun_l26_n858
+end
+
+def fun_l25_n705()
+ fun_l26_n944
+end
+
+def fun_l25_n706()
+ fun_l26_n543
+end
+
+def fun_l25_n707()
+ fun_l26_n750
+end
+
+def fun_l25_n708()
+ fun_l26_n191
+end
+
+def fun_l25_n709()
+ fun_l26_n483
+end
+
+def fun_l25_n710()
+ fun_l26_n614
+end
+
+def fun_l25_n711()
+ fun_l26_n944
+end
+
+def fun_l25_n712()
+ fun_l26_n375
+end
+
+def fun_l25_n713()
+ fun_l26_n464
+end
+
+def fun_l25_n714()
+ fun_l26_n429
+end
+
+def fun_l25_n715()
+ fun_l26_n251
+end
+
+def fun_l25_n716()
+ fun_l26_n401
+end
+
+def fun_l25_n717()
+ fun_l26_n230
+end
+
+def fun_l25_n718()
+ fun_l26_n855
+end
+
+def fun_l25_n719()
+ fun_l26_n63
+end
+
+def fun_l25_n720()
+ fun_l26_n453
+end
+
+def fun_l25_n721()
+ fun_l26_n698
+end
+
+def fun_l25_n722()
+ fun_l26_n691
+end
+
+def fun_l25_n723()
+ fun_l26_n949
+end
+
+def fun_l25_n724()
+ fun_l26_n838
+end
+
+def fun_l25_n725()
+ fun_l26_n962
+end
+
+def fun_l25_n726()
+ fun_l26_n159
+end
+
+def fun_l25_n727()
+ fun_l26_n958
+end
+
+def fun_l25_n728()
+ fun_l26_n915
+end
+
+def fun_l25_n729()
+ fun_l26_n925
+end
+
+def fun_l25_n730()
+ fun_l26_n841
+end
+
+def fun_l25_n731()
+ fun_l26_n710
+end
+
+def fun_l25_n732()
+ fun_l26_n606
+end
+
+def fun_l25_n733()
+ fun_l26_n502
+end
+
+def fun_l25_n734()
+ fun_l26_n275
+end
+
+def fun_l25_n735()
+ fun_l26_n2
+end
+
+def fun_l25_n736()
+ fun_l26_n912
+end
+
+def fun_l25_n737()
+ fun_l26_n908
+end
+
+def fun_l25_n738()
+ fun_l26_n599
+end
+
+def fun_l25_n739()
+ fun_l26_n586
+end
+
+def fun_l25_n740()
+ fun_l26_n675
+end
+
+def fun_l25_n741()
+ fun_l26_n33
+end
+
+def fun_l25_n742()
+ fun_l26_n94
+end
+
+def fun_l25_n743()
+ fun_l26_n512
+end
+
+def fun_l25_n744()
+ fun_l26_n38
+end
+
+def fun_l25_n745()
+ fun_l26_n479
+end
+
+def fun_l25_n746()
+ fun_l26_n191
+end
+
+def fun_l25_n747()
+ fun_l26_n520
+end
+
+def fun_l25_n748()
+ fun_l26_n800
+end
+
+def fun_l25_n749()
+ fun_l26_n401
+end
+
+def fun_l25_n750()
+ fun_l26_n355
+end
+
+def fun_l25_n751()
+ fun_l26_n622
+end
+
+def fun_l25_n752()
+ fun_l26_n48
+end
+
+def fun_l25_n753()
+ fun_l26_n620
+end
+
+def fun_l25_n754()
+ fun_l26_n932
+end
+
+def fun_l25_n755()
+ fun_l26_n204
+end
+
+def fun_l25_n756()
+ fun_l26_n875
+end
+
+def fun_l25_n757()
+ fun_l26_n458
+end
+
+def fun_l25_n758()
+ fun_l26_n364
+end
+
+def fun_l25_n759()
+ fun_l26_n621
+end
+
+def fun_l25_n760()
+ fun_l26_n800
+end
+
+def fun_l25_n761()
+ fun_l26_n297
+end
+
+def fun_l25_n762()
+ fun_l26_n262
+end
+
+def fun_l25_n763()
+ fun_l26_n810
+end
+
+def fun_l25_n764()
+ fun_l26_n518
+end
+
+def fun_l25_n765()
+ fun_l26_n192
+end
+
+def fun_l25_n766()
+ fun_l26_n733
+end
+
+def fun_l25_n767()
+ fun_l26_n410
+end
+
+def fun_l25_n768()
+ fun_l26_n161
+end
+
+def fun_l25_n769()
+ fun_l26_n546
+end
+
+def fun_l25_n770()
+ fun_l26_n863
+end
+
+def fun_l25_n771()
+ fun_l26_n442
+end
+
+def fun_l25_n772()
+ fun_l26_n733
+end
+
+def fun_l25_n773()
+ fun_l26_n340
+end
+
+def fun_l25_n774()
+ fun_l26_n371
+end
+
+def fun_l25_n775()
+ fun_l26_n253
+end
+
+def fun_l25_n776()
+ fun_l26_n607
+end
+
+def fun_l25_n777()
+ fun_l26_n859
+end
+
+def fun_l25_n778()
+ fun_l26_n142
+end
+
+def fun_l25_n779()
+ fun_l26_n504
+end
+
+def fun_l25_n780()
+ fun_l26_n145
+end
+
+def fun_l25_n781()
+ fun_l26_n561
+end
+
+def fun_l25_n782()
+ fun_l26_n442
+end
+
+def fun_l25_n783()
+ fun_l26_n70
+end
+
+def fun_l25_n784()
+ fun_l26_n233
+end
+
+def fun_l25_n785()
+ fun_l26_n680
+end
+
+def fun_l25_n786()
+ fun_l26_n195
+end
+
+def fun_l25_n787()
+ fun_l26_n760
+end
+
+def fun_l25_n788()
+ fun_l26_n951
+end
+
+def fun_l25_n789()
+ fun_l26_n247
+end
+
+def fun_l25_n790()
+ fun_l26_n58
+end
+
+def fun_l25_n791()
+ fun_l26_n926
+end
+
+def fun_l25_n792()
+ fun_l26_n424
+end
+
+def fun_l25_n793()
+ fun_l26_n404
+end
+
+def fun_l25_n794()
+ fun_l26_n98
+end
+
+def fun_l25_n795()
+ fun_l26_n568
+end
+
+def fun_l25_n796()
+ fun_l26_n665
+end
+
+def fun_l25_n797()
+ fun_l26_n138
+end
+
+def fun_l25_n798()
+ fun_l26_n362
+end
+
+def fun_l25_n799()
+ fun_l26_n366
+end
+
+def fun_l25_n800()
+ fun_l26_n667
+end
+
+def fun_l25_n801()
+ fun_l26_n171
+end
+
+def fun_l25_n802()
+ fun_l26_n620
+end
+
+def fun_l25_n803()
+ fun_l26_n88
+end
+
+def fun_l25_n804()
+ fun_l26_n60
+end
+
+def fun_l25_n805()
+ fun_l26_n411
+end
+
+def fun_l25_n806()
+ fun_l26_n994
+end
+
+def fun_l25_n807()
+ fun_l26_n341
+end
+
+def fun_l25_n808()
+ fun_l26_n364
+end
+
+def fun_l25_n809()
+ fun_l26_n253
+end
+
+def fun_l25_n810()
+ fun_l26_n689
+end
+
+def fun_l25_n811()
+ fun_l26_n325
+end
+
+def fun_l25_n812()
+ fun_l26_n573
+end
+
+def fun_l25_n813()
+ fun_l26_n122
+end
+
+def fun_l25_n814()
+ fun_l26_n487
+end
+
+def fun_l25_n815()
+ fun_l26_n461
+end
+
+def fun_l25_n816()
+ fun_l26_n851
+end
+
+def fun_l25_n817()
+ fun_l26_n322
+end
+
+def fun_l25_n818()
+ fun_l26_n472
+end
+
+def fun_l25_n819()
+ fun_l26_n773
+end
+
+def fun_l25_n820()
+ fun_l26_n801
+end
+
+def fun_l25_n821()
+ fun_l26_n454
+end
+
+def fun_l25_n822()
+ fun_l26_n179
+end
+
+def fun_l25_n823()
+ fun_l26_n207
+end
+
+def fun_l25_n824()
+ fun_l26_n464
+end
+
+def fun_l25_n825()
+ fun_l26_n188
+end
+
+def fun_l25_n826()
+ fun_l26_n831
+end
+
+def fun_l25_n827()
+ fun_l26_n918
+end
+
+def fun_l25_n828()
+ fun_l26_n336
+end
+
+def fun_l25_n829()
+ fun_l26_n960
+end
+
+def fun_l25_n830()
+ fun_l26_n767
+end
+
+def fun_l25_n831()
+ fun_l26_n149
+end
+
+def fun_l25_n832()
+ fun_l26_n454
+end
+
+def fun_l25_n833()
+ fun_l26_n756
+end
+
+def fun_l25_n834()
+ fun_l26_n937
+end
+
+def fun_l25_n835()
+ fun_l26_n841
+end
+
+def fun_l25_n836()
+ fun_l26_n210
+end
+
+def fun_l25_n837()
+ fun_l26_n633
+end
+
+def fun_l25_n838()
+ fun_l26_n665
+end
+
+def fun_l25_n839()
+ fun_l26_n502
+end
+
+def fun_l25_n840()
+ fun_l26_n38
+end
+
+def fun_l25_n841()
+ fun_l26_n487
+end
+
+def fun_l25_n842()
+ fun_l26_n101
+end
+
+def fun_l25_n843()
+ fun_l26_n522
+end
+
+def fun_l25_n844()
+ fun_l26_n501
+end
+
+def fun_l25_n845()
+ fun_l26_n759
+end
+
+def fun_l25_n846()
+ fun_l26_n161
+end
+
+def fun_l25_n847()
+ fun_l26_n823
+end
+
+def fun_l25_n848()
+ fun_l26_n687
+end
+
+def fun_l25_n849()
+ fun_l26_n41
+end
+
+def fun_l25_n850()
+ fun_l26_n580
+end
+
+def fun_l25_n851()
+ fun_l26_n728
+end
+
+def fun_l25_n852()
+ fun_l26_n464
+end
+
+def fun_l25_n853()
+ fun_l26_n846
+end
+
+def fun_l25_n854()
+ fun_l26_n708
+end
+
+def fun_l25_n855()
+ fun_l26_n847
+end
+
+def fun_l25_n856()
+ fun_l26_n295
+end
+
+def fun_l25_n857()
+ fun_l26_n569
+end
+
+def fun_l25_n858()
+ fun_l26_n367
+end
+
+def fun_l25_n859()
+ fun_l26_n937
+end
+
+def fun_l25_n860()
+ fun_l26_n116
+end
+
+def fun_l25_n861()
+ fun_l26_n889
+end
+
+def fun_l25_n862()
+ fun_l26_n392
+end
+
+def fun_l25_n863()
+ fun_l26_n70
+end
+
+def fun_l25_n864()
+ fun_l26_n82
+end
+
+def fun_l25_n865()
+ fun_l26_n4
+end
+
+def fun_l25_n866()
+ fun_l26_n286
+end
+
+def fun_l25_n867()
+ fun_l26_n594
+end
+
+def fun_l25_n868()
+ fun_l26_n917
+end
+
+def fun_l25_n869()
+ fun_l26_n385
+end
+
+def fun_l25_n870()
+ fun_l26_n149
+end
+
+def fun_l25_n871()
+ fun_l26_n893
+end
+
+def fun_l25_n872()
+ fun_l26_n832
+end
+
+def fun_l25_n873()
+ fun_l26_n962
+end
+
+def fun_l25_n874()
+ fun_l26_n196
+end
+
+def fun_l25_n875()
+ fun_l26_n841
+end
+
+def fun_l25_n876()
+ fun_l26_n334
+end
+
+def fun_l25_n877()
+ fun_l26_n680
+end
+
+def fun_l25_n878()
+ fun_l26_n858
+end
+
+def fun_l25_n879()
+ fun_l26_n530
+end
+
+def fun_l25_n880()
+ fun_l26_n331
+end
+
+def fun_l25_n881()
+ fun_l26_n287
+end
+
+def fun_l25_n882()
+ fun_l26_n995
+end
+
+def fun_l25_n883()
+ fun_l26_n663
+end
+
+def fun_l25_n884()
+ fun_l26_n352
+end
+
+def fun_l25_n885()
+ fun_l26_n787
+end
+
+def fun_l25_n886()
+ fun_l26_n176
+end
+
+def fun_l25_n887()
+ fun_l26_n303
+end
+
+def fun_l25_n888()
+ fun_l26_n610
+end
+
+def fun_l25_n889()
+ fun_l26_n860
+end
+
+def fun_l25_n890()
+ fun_l26_n35
+end
+
+def fun_l25_n891()
+ fun_l26_n599
+end
+
+def fun_l25_n892()
+ fun_l26_n334
+end
+
+def fun_l25_n893()
+ fun_l26_n904
+end
+
+def fun_l25_n894()
+ fun_l26_n999
+end
+
+def fun_l25_n895()
+ fun_l26_n394
+end
+
+def fun_l25_n896()
+ fun_l26_n901
+end
+
+def fun_l25_n897()
+ fun_l26_n348
+end
+
+def fun_l25_n898()
+ fun_l26_n59
+end
+
+def fun_l25_n899()
+ fun_l26_n67
+end
+
+def fun_l25_n900()
+ fun_l26_n887
+end
+
+def fun_l25_n901()
+ fun_l26_n27
+end
+
+def fun_l25_n902()
+ fun_l26_n635
+end
+
+def fun_l25_n903()
+ fun_l26_n627
+end
+
+def fun_l25_n904()
+ fun_l26_n47
+end
+
+def fun_l25_n905()
+ fun_l26_n256
+end
+
+def fun_l25_n906()
+ fun_l26_n498
+end
+
+def fun_l25_n907()
+ fun_l26_n831
+end
+
+def fun_l25_n908()
+ fun_l26_n723
+end
+
+def fun_l25_n909()
+ fun_l26_n29
+end
+
+def fun_l25_n910()
+ fun_l26_n842
+end
+
+def fun_l25_n911()
+ fun_l26_n762
+end
+
+def fun_l25_n912()
+ fun_l26_n706
+end
+
+def fun_l25_n913()
+ fun_l26_n472
+end
+
+def fun_l25_n914()
+ fun_l26_n825
+end
+
+def fun_l25_n915()
+ fun_l26_n210
+end
+
+def fun_l25_n916()
+ fun_l26_n682
+end
+
+def fun_l25_n917()
+ fun_l26_n793
+end
+
+def fun_l25_n918()
+ fun_l26_n768
+end
+
+def fun_l25_n919()
+ fun_l26_n631
+end
+
+def fun_l25_n920()
+ fun_l26_n188
+end
+
+def fun_l25_n921()
+ fun_l26_n115
+end
+
+def fun_l25_n922()
+ fun_l26_n587
+end
+
+def fun_l25_n923()
+ fun_l26_n998
+end
+
+def fun_l25_n924()
+ fun_l26_n439
+end
+
+def fun_l25_n925()
+ fun_l26_n306
+end
+
+def fun_l25_n926()
+ fun_l26_n810
+end
+
+def fun_l25_n927()
+ fun_l26_n183
+end
+
+def fun_l25_n928()
+ fun_l26_n868
+end
+
+def fun_l25_n929()
+ fun_l26_n733
+end
+
+def fun_l25_n930()
+ fun_l26_n931
+end
+
+def fun_l25_n931()
+ fun_l26_n747
+end
+
+def fun_l25_n932()
+ fun_l26_n126
+end
+
+def fun_l25_n933()
+ fun_l26_n299
+end
+
+def fun_l25_n934()
+ fun_l26_n994
+end
+
+def fun_l25_n935()
+ fun_l26_n76
+end
+
+def fun_l25_n936()
+ fun_l26_n606
+end
+
+def fun_l25_n937()
+ fun_l26_n874
+end
+
+def fun_l25_n938()
+ fun_l26_n333
+end
+
+def fun_l25_n939()
+ fun_l26_n601
+end
+
+def fun_l25_n940()
+ fun_l26_n503
+end
+
+def fun_l25_n941()
+ fun_l26_n819
+end
+
+def fun_l25_n942()
+ fun_l26_n414
+end
+
+def fun_l25_n943()
+ fun_l26_n839
+end
+
+def fun_l25_n944()
+ fun_l26_n655
+end
+
+def fun_l25_n945()
+ fun_l26_n61
+end
+
+def fun_l25_n946()
+ fun_l26_n368
+end
+
+def fun_l25_n947()
+ fun_l26_n481
+end
+
+def fun_l25_n948()
+ fun_l26_n674
+end
+
+def fun_l25_n949()
+ fun_l26_n755
+end
+
+def fun_l25_n950()
+ fun_l26_n940
+end
+
+def fun_l25_n951()
+ fun_l26_n918
+end
+
+def fun_l25_n952()
+ fun_l26_n833
+end
+
+def fun_l25_n953()
+ fun_l26_n81
+end
+
+def fun_l25_n954()
+ fun_l26_n12
+end
+
+def fun_l25_n955()
+ fun_l26_n598
+end
+
+def fun_l25_n956()
+ fun_l26_n10
+end
+
+def fun_l25_n957()
+ fun_l26_n552
+end
+
+def fun_l25_n958()
+ fun_l26_n536
+end
+
+def fun_l25_n959()
+ fun_l26_n291
+end
+
+def fun_l25_n960()
+ fun_l26_n535
+end
+
+def fun_l25_n961()
+ fun_l26_n593
+end
+
+def fun_l25_n962()
+ fun_l26_n834
+end
+
+def fun_l25_n963()
+ fun_l26_n527
+end
+
+def fun_l25_n964()
+ fun_l26_n403
+end
+
+def fun_l25_n965()
+ fun_l26_n246
+end
+
+def fun_l25_n966()
+ fun_l26_n278
+end
+
+def fun_l25_n967()
+ fun_l26_n948
+end
+
+def fun_l25_n968()
+ fun_l26_n989
+end
+
+def fun_l25_n969()
+ fun_l26_n312
+end
+
+def fun_l25_n970()
+ fun_l26_n674
+end
+
+def fun_l25_n971()
+ fun_l26_n592
+end
+
+def fun_l25_n972()
+ fun_l26_n413
+end
+
+def fun_l25_n973()
+ fun_l26_n774
+end
+
+def fun_l25_n974()
+ fun_l26_n148
+end
+
+def fun_l25_n975()
+ fun_l26_n437
+end
+
+def fun_l25_n976()
+ fun_l26_n749
+end
+
+def fun_l25_n977()
+ fun_l26_n938
+end
+
+def fun_l25_n978()
+ fun_l26_n662
+end
+
+def fun_l25_n979()
+ fun_l26_n327
+end
+
+def fun_l25_n980()
+ fun_l26_n665
+end
+
+def fun_l25_n981()
+ fun_l26_n516
+end
+
+def fun_l25_n982()
+ fun_l26_n27
+end
+
+def fun_l25_n983()
+ fun_l26_n624
+end
+
+def fun_l25_n984()
+ fun_l26_n451
+end
+
+def fun_l25_n985()
+ fun_l26_n120
+end
+
+def fun_l25_n986()
+ fun_l26_n220
+end
+
+def fun_l25_n987()
+ fun_l26_n201
+end
+
+def fun_l25_n988()
+ fun_l26_n67
+end
+
+def fun_l25_n989()
+ fun_l26_n484
+end
+
+def fun_l25_n990()
+ fun_l26_n98
+end
+
+def fun_l25_n991()
+ fun_l26_n133
+end
+
+def fun_l25_n992()
+ fun_l26_n642
+end
+
+def fun_l25_n993()
+ fun_l26_n933
+end
+
+def fun_l25_n994()
+ fun_l26_n410
+end
+
+def fun_l25_n995()
+ fun_l26_n415
+end
+
+def fun_l25_n996()
+ fun_l26_n513
+end
+
+def fun_l25_n997()
+ fun_l26_n41
+end
+
+def fun_l25_n998()
+ fun_l26_n517
+end
+
+def fun_l25_n999()
+ fun_l26_n485
+end
+
+def fun_l26_n0()
+ fun_l27_n229
+end
+
+def fun_l26_n1()
+ fun_l27_n178
+end
+
+def fun_l26_n2()
+ fun_l27_n76
+end
+
+def fun_l26_n3()
+ fun_l27_n247
+end
+
+def fun_l26_n4()
+ fun_l27_n564
+end
+
+def fun_l26_n5()
+ fun_l27_n204
+end
+
+def fun_l26_n6()
+ fun_l27_n196
+end
+
+def fun_l26_n7()
+ fun_l27_n57
+end
+
+def fun_l26_n8()
+ fun_l27_n836
+end
+
+def fun_l26_n9()
+ fun_l27_n195
+end
+
+def fun_l26_n10()
+ fun_l27_n149
+end
+
+def fun_l26_n11()
+ fun_l27_n784
+end
+
+def fun_l26_n12()
+ fun_l27_n242
+end
+
+def fun_l26_n13()
+ fun_l27_n771
+end
+
+def fun_l26_n14()
+ fun_l27_n263
+end
+
+def fun_l26_n15()
+ fun_l27_n486
+end
+
+def fun_l26_n16()
+ fun_l27_n351
+end
+
+def fun_l26_n17()
+ fun_l27_n612
+end
+
+def fun_l26_n18()
+ fun_l27_n61
+end
+
+def fun_l26_n19()
+ fun_l27_n119
+end
+
+def fun_l26_n20()
+ fun_l27_n419
+end
+
+def fun_l26_n21()
+ fun_l27_n265
+end
+
+def fun_l26_n22()
+ fun_l27_n70
+end
+
+def fun_l26_n23()
+ fun_l27_n868
+end
+
+def fun_l26_n24()
+ fun_l27_n969
+end
+
+def fun_l26_n25()
+ fun_l27_n355
+end
+
+def fun_l26_n26()
+ fun_l27_n558
+end
+
+def fun_l26_n27()
+ fun_l27_n522
+end
+
+def fun_l26_n28()
+ fun_l27_n704
+end
+
+def fun_l26_n29()
+ fun_l27_n196
+end
+
+def fun_l26_n30()
+ fun_l27_n834
+end
+
+def fun_l26_n31()
+ fun_l27_n187
+end
+
+def fun_l26_n32()
+ fun_l27_n324
+end
+
+def fun_l26_n33()
+ fun_l27_n233
+end
+
+def fun_l26_n34()
+ fun_l27_n559
+end
+
+def fun_l26_n35()
+ fun_l27_n331
+end
+
+def fun_l26_n36()
+ fun_l27_n71
+end
+
+def fun_l26_n37()
+ fun_l27_n572
+end
+
+def fun_l26_n38()
+ fun_l27_n918
+end
+
+def fun_l26_n39()
+ fun_l27_n866
+end
+
+def fun_l26_n40()
+ fun_l27_n909
+end
+
+def fun_l26_n41()
+ fun_l27_n861
+end
+
+def fun_l26_n42()
+ fun_l27_n440
+end
+
+def fun_l26_n43()
+ fun_l27_n213
+end
+
+def fun_l26_n44()
+ fun_l27_n675
+end
+
+def fun_l26_n45()
+ fun_l27_n490
+end
+
+def fun_l26_n46()
+ fun_l27_n579
+end
+
+def fun_l26_n47()
+ fun_l27_n25
+end
+
+def fun_l26_n48()
+ fun_l27_n180
+end
+
+def fun_l26_n49()
+ fun_l27_n346
+end
+
+def fun_l26_n50()
+ fun_l27_n761
+end
+
+def fun_l26_n51()
+ fun_l27_n336
+end
+
+def fun_l26_n52()
+ fun_l27_n124
+end
+
+def fun_l26_n53()
+ fun_l27_n485
+end
+
+def fun_l26_n54()
+ fun_l27_n24
+end
+
+def fun_l26_n55()
+ fun_l27_n666
+end
+
+def fun_l26_n56()
+ fun_l27_n957
+end
+
+def fun_l26_n57()
+ fun_l27_n790
+end
+
+def fun_l26_n58()
+ fun_l27_n475
+end
+
+def fun_l26_n59()
+ fun_l27_n915
+end
+
+def fun_l26_n60()
+ fun_l27_n313
+end
+
+def fun_l26_n61()
+ fun_l27_n148
+end
+
+def fun_l26_n62()
+ fun_l27_n185
+end
+
+def fun_l26_n63()
+ fun_l27_n468
+end
+
+def fun_l26_n64()
+ fun_l27_n549
+end
+
+def fun_l26_n65()
+ fun_l27_n29
+end
+
+def fun_l26_n66()
+ fun_l27_n601
+end
+
+def fun_l26_n67()
+ fun_l27_n3
+end
+
+def fun_l26_n68()
+ fun_l27_n363
+end
+
+def fun_l26_n69()
+ fun_l27_n721
+end
+
+def fun_l26_n70()
+ fun_l27_n76
+end
+
+def fun_l26_n71()
+ fun_l27_n265
+end
+
+def fun_l26_n72()
+ fun_l27_n771
+end
+
+def fun_l26_n73()
+ fun_l27_n660
+end
+
+def fun_l26_n74()
+ fun_l27_n714
+end
+
+def fun_l26_n75()
+ fun_l27_n495
+end
+
+def fun_l26_n76()
+ fun_l27_n133
+end
+
+def fun_l26_n77()
+ fun_l27_n753
+end
+
+def fun_l26_n78()
+ fun_l27_n999
+end
+
+def fun_l26_n79()
+ fun_l27_n527
+end
+
+def fun_l26_n80()
+ fun_l27_n767
+end
+
+def fun_l26_n81()
+ fun_l27_n444
+end
+
+def fun_l26_n82()
+ fun_l27_n160
+end
+
+def fun_l26_n83()
+ fun_l27_n799
+end
+
+def fun_l26_n84()
+ fun_l27_n631
+end
+
+def fun_l26_n85()
+ fun_l27_n480
+end
+
+def fun_l26_n86()
+ fun_l27_n800
+end
+
+def fun_l26_n87()
+ fun_l27_n168
+end
+
+def fun_l26_n88()
+ fun_l27_n191
+end
+
+def fun_l26_n89()
+ fun_l27_n832
+end
+
+def fun_l26_n90()
+ fun_l27_n522
+end
+
+def fun_l26_n91()
+ fun_l27_n747
+end
+
+def fun_l26_n92()
+ fun_l27_n50
+end
+
+def fun_l26_n93()
+ fun_l27_n472
+end
+
+def fun_l26_n94()
+ fun_l27_n778
+end
+
+def fun_l26_n95()
+ fun_l27_n130
+end
+
+def fun_l26_n96()
+ fun_l27_n735
+end
+
+def fun_l26_n97()
+ fun_l27_n130
+end
+
+def fun_l26_n98()
+ fun_l27_n95
+end
+
+def fun_l26_n99()
+ fun_l27_n171
+end
+
+def fun_l26_n100()
+ fun_l27_n121
+end
+
+def fun_l26_n101()
+ fun_l27_n789
+end
+
+def fun_l26_n102()
+ fun_l27_n124
+end
+
+def fun_l26_n103()
+ fun_l27_n836
+end
+
+def fun_l26_n104()
+ fun_l27_n785
+end
+
+def fun_l26_n105()
+ fun_l27_n586
+end
+
+def fun_l26_n106()
+ fun_l27_n220
+end
+
+def fun_l26_n107()
+ fun_l27_n783
+end
+
+def fun_l26_n108()
+ fun_l27_n239
+end
+
+def fun_l26_n109()
+ fun_l27_n838
+end
+
+def fun_l26_n110()
+ fun_l27_n563
+end
+
+def fun_l26_n111()
+ fun_l27_n955
+end
+
+def fun_l26_n112()
+ fun_l27_n889
+end
+
+def fun_l26_n113()
+ fun_l27_n967
+end
+
+def fun_l26_n114()
+ fun_l27_n19
+end
+
+def fun_l26_n115()
+ fun_l27_n637
+end
+
+def fun_l26_n116()
+ fun_l27_n914
+end
+
+def fun_l26_n117()
+ fun_l27_n684
+end
+
+def fun_l26_n118()
+ fun_l27_n352
+end
+
+def fun_l26_n119()
+ fun_l27_n698
+end
+
+def fun_l26_n120()
+ fun_l27_n669
+end
+
+def fun_l26_n121()
+ fun_l27_n52
+end
+
+def fun_l26_n122()
+ fun_l27_n485
+end
+
+def fun_l26_n123()
+ fun_l27_n468
+end
+
+def fun_l26_n124()
+ fun_l27_n340
+end
+
+def fun_l26_n125()
+ fun_l27_n414
+end
+
+def fun_l26_n126()
+ fun_l27_n994
+end
+
+def fun_l26_n127()
+ fun_l27_n601
+end
+
+def fun_l26_n128()
+ fun_l27_n679
+end
+
+def fun_l26_n129()
+ fun_l27_n720
+end
+
+def fun_l26_n130()
+ fun_l27_n66
+end
+
+def fun_l26_n131()
+ fun_l27_n921
+end
+
+def fun_l26_n132()
+ fun_l27_n385
+end
+
+def fun_l26_n133()
+ fun_l27_n88
+end
+
+def fun_l26_n134()
+ fun_l27_n164
+end
+
+def fun_l26_n135()
+ fun_l27_n269
+end
+
+def fun_l26_n136()
+ fun_l27_n371
+end
+
+def fun_l26_n137()
+ fun_l27_n786
+end
+
+def fun_l26_n138()
+ fun_l27_n464
+end
+
+def fun_l26_n139()
+ fun_l27_n96
+end
+
+def fun_l26_n140()
+ fun_l27_n494
+end
+
+def fun_l26_n141()
+ fun_l27_n341
+end
+
+def fun_l26_n142()
+ fun_l27_n646
+end
+
+def fun_l26_n143()
+ fun_l27_n959
+end
+
+def fun_l26_n144()
+ fun_l27_n645
+end
+
+def fun_l26_n145()
+ fun_l27_n825
+end
+
+def fun_l26_n146()
+ fun_l27_n416
+end
+
+def fun_l26_n147()
+ fun_l27_n994
+end
+
+def fun_l26_n148()
+ fun_l27_n875
+end
+
+def fun_l26_n149()
+ fun_l27_n406
+end
+
+def fun_l26_n150()
+ fun_l27_n857
+end
+
+def fun_l26_n151()
+ fun_l27_n348
+end
+
+def fun_l26_n152()
+ fun_l27_n611
+end
+
+def fun_l26_n153()
+ fun_l27_n831
+end
+
+def fun_l26_n154()
+ fun_l27_n412
+end
+
+def fun_l26_n155()
+ fun_l27_n530
+end
+
+def fun_l26_n156()
+ fun_l27_n892
+end
+
+def fun_l26_n157()
+ fun_l27_n70
+end
+
+def fun_l26_n158()
+ fun_l27_n756
+end
+
+def fun_l26_n159()
+ fun_l27_n587
+end
+
+def fun_l26_n160()
+ fun_l27_n796
+end
+
+def fun_l26_n161()
+ fun_l27_n470
+end
+
+def fun_l26_n162()
+ fun_l27_n290
+end
+
+def fun_l26_n163()
+ fun_l27_n723
+end
+
+def fun_l26_n164()
+ fun_l27_n660
+end
+
+def fun_l26_n165()
+ fun_l27_n0
+end
+
+def fun_l26_n166()
+ fun_l27_n223
+end
+
+def fun_l26_n167()
+ fun_l27_n341
+end
+
+def fun_l26_n168()
+ fun_l27_n128
+end
+
+def fun_l26_n169()
+ fun_l27_n367
+end
+
+def fun_l26_n170()
+ fun_l27_n487
+end
+
+def fun_l26_n171()
+ fun_l27_n574
+end
+
+def fun_l26_n172()
+ fun_l27_n437
+end
+
+def fun_l26_n173()
+ fun_l27_n182
+end
+
+def fun_l26_n174()
+ fun_l27_n607
+end
+
+def fun_l26_n175()
+ fun_l27_n252
+end
+
+def fun_l26_n176()
+ fun_l27_n996
+end
+
+def fun_l26_n177()
+ fun_l27_n904
+end
+
+def fun_l26_n178()
+ fun_l27_n505
+end
+
+def fun_l26_n179()
+ fun_l27_n425
+end
+
+def fun_l26_n180()
+ fun_l27_n610
+end
+
+def fun_l26_n181()
+ fun_l27_n734
+end
+
+def fun_l26_n182()
+ fun_l27_n427
+end
+
+def fun_l26_n183()
+ fun_l27_n918
+end
+
+def fun_l26_n184()
+ fun_l27_n376
+end
+
+def fun_l26_n185()
+ fun_l27_n445
+end
+
+def fun_l26_n186()
+ fun_l27_n227
+end
+
+def fun_l26_n187()
+ fun_l27_n129
+end
+
+def fun_l26_n188()
+ fun_l27_n139
+end
+
+def fun_l26_n189()
+ fun_l27_n142
+end
+
+def fun_l26_n190()
+ fun_l27_n388
+end
+
+def fun_l26_n191()
+ fun_l27_n24
+end
+
+def fun_l26_n192()
+ fun_l27_n369
+end
+
+def fun_l26_n193()
+ fun_l27_n984
+end
+
+def fun_l26_n194()
+ fun_l27_n342
+end
+
+def fun_l26_n195()
+ fun_l27_n722
+end
+
+def fun_l26_n196()
+ fun_l27_n846
+end
+
+def fun_l26_n197()
+ fun_l27_n59
+end
+
+def fun_l26_n198()
+ fun_l27_n471
+end
+
+def fun_l26_n199()
+ fun_l27_n626
+end
+
+def fun_l26_n200()
+ fun_l27_n973
+end
+
+def fun_l26_n201()
+ fun_l27_n525
+end
+
+def fun_l26_n202()
+ fun_l27_n412
+end
+
+def fun_l26_n203()
+ fun_l27_n284
+end
+
+def fun_l26_n204()
+ fun_l27_n383
+end
+
+def fun_l26_n205()
+ fun_l27_n414
+end
+
+def fun_l26_n206()
+ fun_l27_n448
+end
+
+def fun_l26_n207()
+ fun_l27_n795
+end
+
+def fun_l26_n208()
+ fun_l27_n708
+end
+
+def fun_l26_n209()
+ fun_l27_n318
+end
+
+def fun_l26_n210()
+ fun_l27_n284
+end
+
+def fun_l26_n211()
+ fun_l27_n100
+end
+
+def fun_l26_n212()
+ fun_l27_n702
+end
+
+def fun_l26_n213()
+ fun_l27_n611
+end
+
+def fun_l26_n214()
+ fun_l27_n106
+end
+
+def fun_l26_n215()
+ fun_l27_n667
+end
+
+def fun_l26_n216()
+ fun_l27_n822
+end
+
+def fun_l26_n217()
+ fun_l27_n502
+end
+
+def fun_l26_n218()
+ fun_l27_n284
+end
+
+def fun_l26_n219()
+ fun_l27_n472
+end
+
+def fun_l26_n220()
+ fun_l27_n907
+end
+
+def fun_l26_n221()
+ fun_l27_n115
+end
+
+def fun_l26_n222()
+ fun_l27_n6
+end
+
+def fun_l26_n223()
+ fun_l27_n872
+end
+
+def fun_l26_n224()
+ fun_l27_n145
+end
+
+def fun_l26_n225()
+ fun_l27_n63
+end
+
+def fun_l26_n226()
+ fun_l27_n295
+end
+
+def fun_l26_n227()
+ fun_l27_n160
+end
+
+def fun_l26_n228()
+ fun_l27_n72
+end
+
+def fun_l26_n229()
+ fun_l27_n750
+end
+
+def fun_l26_n230()
+ fun_l27_n386
+end
+
+def fun_l26_n231()
+ fun_l27_n110
+end
+
+def fun_l26_n232()
+ fun_l27_n497
+end
+
+def fun_l26_n233()
+ fun_l27_n586
+end
+
+def fun_l26_n234()
+ fun_l27_n435
+end
+
+def fun_l26_n235()
+ fun_l27_n849
+end
+
+def fun_l26_n236()
+ fun_l27_n47
+end
+
+def fun_l26_n237()
+ fun_l27_n673
+end
+
+def fun_l26_n238()
+ fun_l27_n435
+end
+
+def fun_l26_n239()
+ fun_l27_n295
+end
+
+def fun_l26_n240()
+ fun_l27_n466
+end
+
+def fun_l26_n241()
+ fun_l27_n76
+end
+
+def fun_l26_n242()
+ fun_l27_n679
+end
+
+def fun_l26_n243()
+ fun_l27_n772
+end
+
+def fun_l26_n244()
+ fun_l27_n137
+end
+
+def fun_l26_n245()
+ fun_l27_n582
+end
+
+def fun_l26_n246()
+ fun_l27_n344
+end
+
+def fun_l26_n247()
+ fun_l27_n944
+end
+
+def fun_l26_n248()
+ fun_l27_n657
+end
+
+def fun_l26_n249()
+ fun_l27_n354
+end
+
+def fun_l26_n250()
+ fun_l27_n467
+end
+
+def fun_l26_n251()
+ fun_l27_n436
+end
+
+def fun_l26_n252()
+ fun_l27_n923
+end
+
+def fun_l26_n253()
+ fun_l27_n252
+end
+
+def fun_l26_n254()
+ fun_l27_n404
+end
+
+def fun_l26_n255()
+ fun_l27_n421
+end
+
+def fun_l26_n256()
+ fun_l27_n422
+end
+
+def fun_l26_n257()
+ fun_l27_n787
+end
+
+def fun_l26_n258()
+ fun_l27_n173
+end
+
+def fun_l26_n259()
+ fun_l27_n930
+end
+
+def fun_l26_n260()
+ fun_l27_n625
+end
+
+def fun_l26_n261()
+ fun_l27_n18
+end
+
+def fun_l26_n262()
+ fun_l27_n763
+end
+
+def fun_l26_n263()
+ fun_l27_n641
+end
+
+def fun_l26_n264()
+ fun_l27_n114
+end
+
+def fun_l26_n265()
+ fun_l27_n556
+end
+
+def fun_l26_n266()
+ fun_l27_n127
+end
+
+def fun_l26_n267()
+ fun_l27_n229
+end
+
+def fun_l26_n268()
+ fun_l27_n901
+end
+
+def fun_l26_n269()
+ fun_l27_n234
+end
+
+def fun_l26_n270()
+ fun_l27_n444
+end
+
+def fun_l26_n271()
+ fun_l27_n156
+end
+
+def fun_l26_n272()
+ fun_l27_n35
+end
+
+def fun_l26_n273()
+ fun_l27_n725
+end
+
+def fun_l26_n274()
+ fun_l27_n983
+end
+
+def fun_l26_n275()
+ fun_l27_n845
+end
+
+def fun_l26_n276()
+ fun_l27_n324
+end
+
+def fun_l26_n277()
+ fun_l27_n813
+end
+
+def fun_l26_n278()
+ fun_l27_n331
+end
+
+def fun_l26_n279()
+ fun_l27_n66
+end
+
+def fun_l26_n280()
+ fun_l27_n471
+end
+
+def fun_l26_n281()
+ fun_l27_n635
+end
+
+def fun_l26_n282()
+ fun_l27_n180
+end
+
+def fun_l26_n283()
+ fun_l27_n563
+end
+
+def fun_l26_n284()
+ fun_l27_n199
+end
+
+def fun_l26_n285()
+ fun_l27_n238
+end
+
+def fun_l26_n286()
+ fun_l27_n789
+end
+
+def fun_l26_n287()
+ fun_l27_n413
+end
+
+def fun_l26_n288()
+ fun_l27_n358
+end
+
+def fun_l26_n289()
+ fun_l27_n923
+end
+
+def fun_l26_n290()
+ fun_l27_n443
+end
+
+def fun_l26_n291()
+ fun_l27_n706
+end
+
+def fun_l26_n292()
+ fun_l27_n752
+end
+
+def fun_l26_n293()
+ fun_l27_n231
+end
+
+def fun_l26_n294()
+ fun_l27_n185
+end
+
+def fun_l26_n295()
+ fun_l27_n604
+end
+
+def fun_l26_n296()
+ fun_l27_n10
+end
+
+def fun_l26_n297()
+ fun_l27_n758
+end
+
+def fun_l26_n298()
+ fun_l27_n417
+end
+
+def fun_l26_n299()
+ fun_l27_n303
+end
+
+def fun_l26_n300()
+ fun_l27_n524
+end
+
+def fun_l26_n301()
+ fun_l27_n198
+end
+
+def fun_l26_n302()
+ fun_l27_n127
+end
+
+def fun_l26_n303()
+ fun_l27_n971
+end
+
+def fun_l26_n304()
+ fun_l27_n4
+end
+
+def fun_l26_n305()
+ fun_l27_n333
+end
+
+def fun_l26_n306()
+ fun_l27_n782
+end
+
+def fun_l26_n307()
+ fun_l27_n158
+end
+
+def fun_l26_n308()
+ fun_l27_n414
+end
+
+def fun_l26_n309()
+ fun_l27_n730
+end
+
+def fun_l26_n310()
+ fun_l27_n912
+end
+
+def fun_l26_n311()
+ fun_l27_n343
+end
+
+def fun_l26_n312()
+ fun_l27_n885
+end
+
+def fun_l26_n313()
+ fun_l27_n682
+end
+
+def fun_l26_n314()
+ fun_l27_n126
+end
+
+def fun_l26_n315()
+ fun_l27_n680
+end
+
+def fun_l26_n316()
+ fun_l27_n884
+end
+
+def fun_l26_n317()
+ fun_l27_n483
+end
+
+def fun_l26_n318()
+ fun_l27_n601
+end
+
+def fun_l26_n319()
+ fun_l27_n265
+end
+
+def fun_l26_n320()
+ fun_l27_n109
+end
+
+def fun_l26_n321()
+ fun_l27_n436
+end
+
+def fun_l26_n322()
+ fun_l27_n209
+end
+
+def fun_l26_n323()
+ fun_l27_n669
+end
+
+def fun_l26_n324()
+ fun_l27_n680
+end
+
+def fun_l26_n325()
+ fun_l27_n844
+end
+
+def fun_l26_n326()
+ fun_l27_n729
+end
+
+def fun_l26_n327()
+ fun_l27_n882
+end
+
+def fun_l26_n328()
+ fun_l27_n99
+end
+
+def fun_l26_n329()
+ fun_l27_n586
+end
+
+def fun_l26_n330()
+ fun_l27_n328
+end
+
+def fun_l26_n331()
+ fun_l27_n694
+end
+
+def fun_l26_n332()
+ fun_l27_n259
+end
+
+def fun_l26_n333()
+ fun_l27_n364
+end
+
+def fun_l26_n334()
+ fun_l27_n944
+end
+
+def fun_l26_n335()
+ fun_l27_n483
+end
+
+def fun_l26_n336()
+ fun_l27_n570
+end
+
+def fun_l26_n337()
+ fun_l27_n348
+end
+
+def fun_l26_n338()
+ fun_l27_n565
+end
+
+def fun_l26_n339()
+ fun_l27_n402
+end
+
+def fun_l26_n340()
+ fun_l27_n890
+end
+
+def fun_l26_n341()
+ fun_l27_n486
+end
+
+def fun_l26_n342()
+ fun_l27_n387
+end
+
+def fun_l26_n343()
+ fun_l27_n239
+end
+
+def fun_l26_n344()
+ fun_l27_n433
+end
+
+def fun_l26_n345()
+ fun_l27_n918
+end
+
+def fun_l26_n346()
+ fun_l27_n524
+end
+
+def fun_l26_n347()
+ fun_l27_n475
+end
+
+def fun_l26_n348()
+ fun_l27_n749
+end
+
+def fun_l26_n349()
+ fun_l27_n61
+end
+
+def fun_l26_n350()
+ fun_l27_n735
+end
+
+def fun_l26_n351()
+ fun_l27_n582
+end
+
+def fun_l26_n352()
+ fun_l27_n519
+end
+
+def fun_l26_n353()
+ fun_l27_n234
+end
+
+def fun_l26_n354()
+ fun_l27_n868
+end
+
+def fun_l26_n355()
+ fun_l27_n109
+end
+
+def fun_l26_n356()
+ fun_l27_n898
+end
+
+def fun_l26_n357()
+ fun_l27_n541
+end
+
+def fun_l26_n358()
+ fun_l27_n328
+end
+
+def fun_l26_n359()
+ fun_l27_n954
+end
+
+def fun_l26_n360()
+ fun_l27_n219
+end
+
+def fun_l26_n361()
+ fun_l27_n776
+end
+
+def fun_l26_n362()
+ fun_l27_n402
+end
+
+def fun_l26_n363()
+ fun_l27_n169
+end
+
+def fun_l26_n364()
+ fun_l27_n395
+end
+
+def fun_l26_n365()
+ fun_l27_n852
+end
+
+def fun_l26_n366()
+ fun_l27_n668
+end
+
+def fun_l26_n367()
+ fun_l27_n0
+end
+
+def fun_l26_n368()
+ fun_l27_n660
+end
+
+def fun_l26_n369()
+ fun_l27_n703
+end
+
+def fun_l26_n370()
+ fun_l27_n946
+end
+
+def fun_l26_n371()
+ fun_l27_n522
+end
+
+def fun_l26_n372()
+ fun_l27_n57
+end
+
+def fun_l26_n373()
+ fun_l27_n228
+end
+
+def fun_l26_n374()
+ fun_l27_n25
+end
+
+def fun_l26_n375()
+ fun_l27_n433
+end
+
+def fun_l26_n376()
+ fun_l27_n557
+end
+
+def fun_l26_n377()
+ fun_l27_n542
+end
+
+def fun_l26_n378()
+ fun_l27_n341
+end
+
+def fun_l26_n379()
+ fun_l27_n28
+end
+
+def fun_l26_n380()
+ fun_l27_n591
+end
+
+def fun_l26_n381()
+ fun_l27_n139
+end
+
+def fun_l26_n382()
+ fun_l27_n303
+end
+
+def fun_l26_n383()
+ fun_l27_n369
+end
+
+def fun_l26_n384()
+ fun_l27_n124
+end
+
+def fun_l26_n385()
+ fun_l27_n459
+end
+
+def fun_l26_n386()
+ fun_l27_n338
+end
+
+def fun_l26_n387()
+ fun_l27_n246
+end
+
+def fun_l26_n388()
+ fun_l27_n248
+end
+
+def fun_l26_n389()
+ fun_l27_n182
+end
+
+def fun_l26_n390()
+ fun_l27_n176
+end
+
+def fun_l26_n391()
+ fun_l27_n307
+end
+
+def fun_l26_n392()
+ fun_l27_n782
+end
+
+def fun_l26_n393()
+ fun_l27_n576
+end
+
+def fun_l26_n394()
+ fun_l27_n777
+end
+
+def fun_l26_n395()
+ fun_l27_n962
+end
+
+def fun_l26_n396()
+ fun_l27_n993
+end
+
+def fun_l26_n397()
+ fun_l27_n592
+end
+
+def fun_l26_n398()
+ fun_l27_n710
+end
+
+def fun_l26_n399()
+ fun_l27_n644
+end
+
+def fun_l26_n400()
+ fun_l27_n11
+end
+
+def fun_l26_n401()
+ fun_l27_n774
+end
+
+def fun_l26_n402()
+ fun_l27_n190
+end
+
+def fun_l26_n403()
+ fun_l27_n15
+end
+
+def fun_l26_n404()
+ fun_l27_n47
+end
+
+def fun_l26_n405()
+ fun_l27_n802
+end
+
+def fun_l26_n406()
+ fun_l27_n659
+end
+
+def fun_l26_n407()
+ fun_l27_n295
+end
+
+def fun_l26_n408()
+ fun_l27_n120
+end
+
+def fun_l26_n409()
+ fun_l27_n438
+end
+
+def fun_l26_n410()
+ fun_l27_n443
+end
+
+def fun_l26_n411()
+ fun_l27_n860
+end
+
+def fun_l26_n412()
+ fun_l27_n285
+end
+
+def fun_l26_n413()
+ fun_l27_n457
+end
+
+def fun_l26_n414()
+ fun_l27_n942
+end
+
+def fun_l26_n415()
+ fun_l27_n425
+end
+
+def fun_l26_n416()
+ fun_l27_n54
+end
+
+def fun_l26_n417()
+ fun_l27_n675
+end
+
+def fun_l26_n418()
+ fun_l27_n739
+end
+
+def fun_l26_n419()
+ fun_l27_n709
+end
+
+def fun_l26_n420()
+ fun_l27_n643
+end
+
+def fun_l26_n421()
+ fun_l27_n473
+end
+
+def fun_l26_n422()
+ fun_l27_n452
+end
+
+def fun_l26_n423()
+ fun_l27_n942
+end
+
+def fun_l26_n424()
+ fun_l27_n270
+end
+
+def fun_l26_n425()
+ fun_l27_n711
+end
+
+def fun_l26_n426()
+ fun_l27_n27
+end
+
+def fun_l26_n427()
+ fun_l27_n120
+end
+
+def fun_l26_n428()
+ fun_l27_n565
+end
+
+def fun_l26_n429()
+ fun_l27_n182
+end
+
+def fun_l26_n430()
+ fun_l27_n641
+end
+
+def fun_l26_n431()
+ fun_l27_n227
+end
+
+def fun_l26_n432()
+ fun_l27_n59
+end
+
+def fun_l26_n433()
+ fun_l27_n599
+end
+
+def fun_l26_n434()
+ fun_l27_n448
+end
+
+def fun_l26_n435()
+ fun_l27_n562
+end
+
+def fun_l26_n436()
+ fun_l27_n201
+end
+
+def fun_l26_n437()
+ fun_l27_n929
+end
+
+def fun_l26_n438()
+ fun_l27_n275
+end
+
+def fun_l26_n439()
+ fun_l27_n339
+end
+
+def fun_l26_n440()
+ fun_l27_n519
+end
+
+def fun_l26_n441()
+ fun_l27_n98
+end
+
+def fun_l26_n442()
+ fun_l27_n581
+end
+
+def fun_l26_n443()
+ fun_l27_n840
+end
+
+def fun_l26_n444()
+ fun_l27_n904
+end
+
+def fun_l26_n445()
+ fun_l27_n468
+end
+
+def fun_l26_n446()
+ fun_l27_n6
+end
+
+def fun_l26_n447()
+ fun_l27_n877
+end
+
+def fun_l26_n448()
+ fun_l27_n609
+end
+
+def fun_l26_n449()
+ fun_l27_n218
+end
+
+def fun_l26_n450()
+ fun_l27_n869
+end
+
+def fun_l26_n451()
+ fun_l27_n184
+end
+
+def fun_l26_n452()
+ fun_l27_n7
+end
+
+def fun_l26_n453()
+ fun_l27_n647
+end
+
+def fun_l26_n454()
+ fun_l27_n470
+end
+
+def fun_l26_n455()
+ fun_l27_n547
+end
+
+def fun_l26_n456()
+ fun_l27_n277
+end
+
+def fun_l26_n457()
+ fun_l27_n302
+end
+
+def fun_l26_n458()
+ fun_l27_n355
+end
+
+def fun_l26_n459()
+ fun_l27_n805
+end
+
+def fun_l26_n460()
+ fun_l27_n201
+end
+
+def fun_l26_n461()
+ fun_l27_n16
+end
+
+def fun_l26_n462()
+ fun_l27_n156
+end
+
+def fun_l26_n463()
+ fun_l27_n219
+end
+
+def fun_l26_n464()
+ fun_l27_n507
+end
+
+def fun_l26_n465()
+ fun_l27_n527
+end
+
+def fun_l26_n466()
+ fun_l27_n307
+end
+
+def fun_l26_n467()
+ fun_l27_n654
+end
+
+def fun_l26_n468()
+ fun_l27_n699
+end
+
+def fun_l26_n469()
+ fun_l27_n772
+end
+
+def fun_l26_n470()
+ fun_l27_n761
+end
+
+def fun_l26_n471()
+ fun_l27_n736
+end
+
+def fun_l26_n472()
+ fun_l27_n104
+end
+
+def fun_l26_n473()
+ fun_l27_n720
+end
+
+def fun_l26_n474()
+ fun_l27_n418
+end
+
+def fun_l26_n475()
+ fun_l27_n403
+end
+
+def fun_l26_n476()
+ fun_l27_n625
+end
+
+def fun_l26_n477()
+ fun_l27_n541
+end
+
+def fun_l26_n478()
+ fun_l27_n441
+end
+
+def fun_l26_n479()
+ fun_l27_n287
+end
+
+def fun_l26_n480()
+ fun_l27_n746
+end
+
+def fun_l26_n481()
+ fun_l27_n205
+end
+
+def fun_l26_n482()
+ fun_l27_n771
+end
+
+def fun_l26_n483()
+ fun_l27_n778
+end
+
+def fun_l26_n484()
+ fun_l27_n284
+end
+
+def fun_l26_n485()
+ fun_l27_n475
+end
+
+def fun_l26_n486()
+ fun_l27_n449
+end
+
+def fun_l26_n487()
+ fun_l27_n485
+end
+
+def fun_l26_n488()
+ fun_l27_n124
+end
+
+def fun_l26_n489()
+ fun_l27_n4
+end
+
+def fun_l26_n490()
+ fun_l27_n270
+end
+
+def fun_l26_n491()
+ fun_l27_n596
+end
+
+def fun_l26_n492()
+ fun_l27_n279
+end
+
+def fun_l26_n493()
+ fun_l27_n226
+end
+
+def fun_l26_n494()
+ fun_l27_n718
+end
+
+def fun_l26_n495()
+ fun_l27_n324
+end
+
+def fun_l26_n496()
+ fun_l27_n430
+end
+
+def fun_l26_n497()
+ fun_l27_n196
+end
+
+def fun_l26_n498()
+ fun_l27_n509
+end
+
+def fun_l26_n499()
+ fun_l27_n282
+end
+
+def fun_l26_n500()
+ fun_l27_n61
+end
+
+def fun_l26_n501()
+ fun_l27_n995
+end
+
+def fun_l26_n502()
+ fun_l27_n75
+end
+
+def fun_l26_n503()
+ fun_l27_n158
+end
+
+def fun_l26_n504()
+ fun_l27_n551
+end
+
+def fun_l26_n505()
+ fun_l27_n936
+end
+
+def fun_l26_n506()
+ fun_l27_n23
+end
+
+def fun_l26_n507()
+ fun_l27_n799
+end
+
+def fun_l26_n508()
+ fun_l27_n25
+end
+
+def fun_l26_n509()
+ fun_l27_n533
+end
+
+def fun_l26_n510()
+ fun_l27_n325
+end
+
+def fun_l26_n511()
+ fun_l27_n375
+end
+
+def fun_l26_n512()
+ fun_l27_n18
+end
+
+def fun_l26_n513()
+ fun_l27_n497
+end
+
+def fun_l26_n514()
+ fun_l27_n51
+end
+
+def fun_l26_n515()
+ fun_l27_n680
+end
+
+def fun_l26_n516()
+ fun_l27_n152
+end
+
+def fun_l26_n517()
+ fun_l27_n495
+end
+
+def fun_l26_n518()
+ fun_l27_n956
+end
+
+def fun_l26_n519()
+ fun_l27_n187
+end
+
+def fun_l26_n520()
+ fun_l27_n292
+end
+
+def fun_l26_n521()
+ fun_l27_n663
+end
+
+def fun_l26_n522()
+ fun_l27_n178
+end
+
+def fun_l26_n523()
+ fun_l27_n323
+end
+
+def fun_l26_n524()
+ fun_l27_n222
+end
+
+def fun_l26_n525()
+ fun_l27_n652
+end
+
+def fun_l26_n526()
+ fun_l27_n519
+end
+
+def fun_l26_n527()
+ fun_l27_n102
+end
+
+def fun_l26_n528()
+ fun_l27_n361
+end
+
+def fun_l26_n529()
+ fun_l27_n201
+end
+
+def fun_l26_n530()
+ fun_l27_n129
+end
+
+def fun_l26_n531()
+ fun_l27_n438
+end
+
+def fun_l26_n532()
+ fun_l27_n387
+end
+
+def fun_l26_n533()
+ fun_l27_n641
+end
+
+def fun_l26_n534()
+ fun_l27_n111
+end
+
+def fun_l26_n535()
+ fun_l27_n548
+end
+
+def fun_l26_n536()
+ fun_l27_n446
+end
+
+def fun_l26_n537()
+ fun_l27_n302
+end
+
+def fun_l26_n538()
+ fun_l27_n438
+end
+
+def fun_l26_n539()
+ fun_l27_n816
+end
+
+def fun_l26_n540()
+ fun_l27_n759
+end
+
+def fun_l26_n541()
+ fun_l27_n318
+end
+
+def fun_l26_n542()
+ fun_l27_n895
+end
+
+def fun_l26_n543()
+ fun_l27_n309
+end
+
+def fun_l26_n544()
+ fun_l27_n35
+end
+
+def fun_l26_n545()
+ fun_l27_n785
+end
+
+def fun_l26_n546()
+ fun_l27_n846
+end
+
+def fun_l26_n547()
+ fun_l27_n191
+end
+
+def fun_l26_n548()
+ fun_l27_n414
+end
+
+def fun_l26_n549()
+ fun_l27_n251
+end
+
+def fun_l26_n550()
+ fun_l27_n982
+end
+
+def fun_l26_n551()
+ fun_l27_n516
+end
+
+def fun_l26_n552()
+ fun_l27_n724
+end
+
+def fun_l26_n553()
+ fun_l27_n473
+end
+
+def fun_l26_n554()
+ fun_l27_n808
+end
+
+def fun_l26_n555()
+ fun_l27_n617
+end
+
+def fun_l26_n556()
+ fun_l27_n306
+end
+
+def fun_l26_n557()
+ fun_l27_n701
+end
+
+def fun_l26_n558()
+ fun_l27_n941
+end
+
+def fun_l26_n559()
+ fun_l27_n60
+end
+
+def fun_l26_n560()
+ fun_l27_n132
+end
+
+def fun_l26_n561()
+ fun_l27_n685
+end
+
+def fun_l26_n562()
+ fun_l27_n619
+end
+
+def fun_l26_n563()
+ fun_l27_n407
+end
+
+def fun_l26_n564()
+ fun_l27_n29
+end
+
+def fun_l26_n565()
+ fun_l27_n53
+end
+
+def fun_l26_n566()
+ fun_l27_n267
+end
+
+def fun_l26_n567()
+ fun_l27_n79
+end
+
+def fun_l26_n568()
+ fun_l27_n170
+end
+
+def fun_l26_n569()
+ fun_l27_n469
+end
+
+def fun_l26_n570()
+ fun_l27_n67
+end
+
+def fun_l26_n571()
+ fun_l27_n794
+end
+
+def fun_l26_n572()
+ fun_l27_n641
+end
+
+def fun_l26_n573()
+ fun_l27_n224
+end
+
+def fun_l26_n574()
+ fun_l27_n415
+end
+
+def fun_l26_n575()
+ fun_l27_n235
+end
+
+def fun_l26_n576()
+ fun_l27_n425
+end
+
+def fun_l26_n577()
+ fun_l27_n335
+end
+
+def fun_l26_n578()
+ fun_l27_n251
+end
+
+def fun_l26_n579()
+ fun_l27_n421
+end
+
+def fun_l26_n580()
+ fun_l27_n20
+end
+
+def fun_l26_n581()
+ fun_l27_n795
+end
+
+def fun_l26_n582()
+ fun_l27_n831
+end
+
+def fun_l26_n583()
+ fun_l27_n666
+end
+
+def fun_l26_n584()
+ fun_l27_n664
+end
+
+def fun_l26_n585()
+ fun_l27_n383
+end
+
+def fun_l26_n586()
+ fun_l27_n587
+end
+
+def fun_l26_n587()
+ fun_l27_n515
+end
+
+def fun_l26_n588()
+ fun_l27_n410
+end
+
+def fun_l26_n589()
+ fun_l27_n379
+end
+
+def fun_l26_n590()
+ fun_l27_n467
+end
+
+def fun_l26_n591()
+ fun_l27_n557
+end
+
+def fun_l26_n592()
+ fun_l27_n444
+end
+
+def fun_l26_n593()
+ fun_l27_n629
+end
+
+def fun_l26_n594()
+ fun_l27_n55
+end
+
+def fun_l26_n595()
+ fun_l27_n581
+end
+
+def fun_l26_n596()
+ fun_l27_n106
+end
+
+def fun_l26_n597()
+ fun_l27_n896
+end
+
+def fun_l26_n598()
+ fun_l27_n180
+end
+
+def fun_l26_n599()
+ fun_l27_n471
+end
+
+def fun_l26_n600()
+ fun_l27_n28
+end
+
+def fun_l26_n601()
+ fun_l27_n195
+end
+
+def fun_l26_n602()
+ fun_l27_n562
+end
+
+def fun_l26_n603()
+ fun_l27_n367
+end
+
+def fun_l26_n604()
+ fun_l27_n609
+end
+
+def fun_l26_n605()
+ fun_l27_n699
+end
+
+def fun_l26_n606()
+ fun_l27_n300
+end
+
+def fun_l26_n607()
+ fun_l27_n28
+end
+
+def fun_l26_n608()
+ fun_l27_n362
+end
+
+def fun_l26_n609()
+ fun_l27_n188
+end
+
+def fun_l26_n610()
+ fun_l27_n320
+end
+
+def fun_l26_n611()
+ fun_l27_n974
+end
+
+def fun_l26_n612()
+ fun_l27_n226
+end
+
+def fun_l26_n613()
+ fun_l27_n723
+end
+
+def fun_l26_n614()
+ fun_l27_n406
+end
+
+def fun_l26_n615()
+ fun_l27_n60
+end
+
+def fun_l26_n616()
+ fun_l27_n921
+end
+
+def fun_l26_n617()
+ fun_l27_n141
+end
+
+def fun_l26_n618()
+ fun_l27_n781
+end
+
+def fun_l26_n619()
+ fun_l27_n279
+end
+
+def fun_l26_n620()
+ fun_l27_n159
+end
+
+def fun_l26_n621()
+ fun_l27_n396
+end
+
+def fun_l26_n622()
+ fun_l27_n365
+end
+
+def fun_l26_n623()
+ fun_l27_n128
+end
+
+def fun_l26_n624()
+ fun_l27_n143
+end
+
+def fun_l26_n625()
+ fun_l27_n553
+end
+
+def fun_l26_n626()
+ fun_l27_n695
+end
+
+def fun_l26_n627()
+ fun_l27_n526
+end
+
+def fun_l26_n628()
+ fun_l27_n623
+end
+
+def fun_l26_n629()
+ fun_l27_n589
+end
+
+def fun_l26_n630()
+ fun_l27_n328
+end
+
+def fun_l26_n631()
+ fun_l27_n959
+end
+
+def fun_l26_n632()
+ fun_l27_n586
+end
+
+def fun_l26_n633()
+ fun_l27_n163
+end
+
+def fun_l26_n634()
+ fun_l27_n821
+end
+
+def fun_l26_n635()
+ fun_l27_n981
+end
+
+def fun_l26_n636()
+ fun_l27_n221
+end
+
+def fun_l26_n637()
+ fun_l27_n752
+end
+
+def fun_l26_n638()
+ fun_l27_n252
+end
+
+def fun_l26_n639()
+ fun_l27_n74
+end
+
+def fun_l26_n640()
+ fun_l27_n694
+end
+
+def fun_l26_n641()
+ fun_l27_n761
+end
+
+def fun_l26_n642()
+ fun_l27_n877
+end
+
+def fun_l26_n643()
+ fun_l27_n480
+end
+
+def fun_l26_n644()
+ fun_l27_n627
+end
+
+def fun_l26_n645()
+ fun_l27_n586
+end
+
+def fun_l26_n646()
+ fun_l27_n820
+end
+
+def fun_l26_n647()
+ fun_l27_n485
+end
+
+def fun_l26_n648()
+ fun_l27_n230
+end
+
+def fun_l26_n649()
+ fun_l27_n698
+end
+
+def fun_l26_n650()
+ fun_l27_n700
+end
+
+def fun_l26_n651()
+ fun_l27_n536
+end
+
+def fun_l26_n652()
+ fun_l27_n343
+end
+
+def fun_l26_n653()
+ fun_l27_n453
+end
+
+def fun_l26_n654()
+ fun_l27_n780
+end
+
+def fun_l26_n655()
+ fun_l27_n402
+end
+
+def fun_l26_n656()
+ fun_l27_n749
+end
+
+def fun_l26_n657()
+ fun_l27_n248
+end
+
+def fun_l26_n658()
+ fun_l27_n326
+end
+
+def fun_l26_n659()
+ fun_l27_n819
+end
+
+def fun_l26_n660()
+ fun_l27_n968
+end
+
+def fun_l26_n661()
+ fun_l27_n123
+end
+
+def fun_l26_n662()
+ fun_l27_n467
+end
+
+def fun_l26_n663()
+ fun_l27_n855
+end
+
+def fun_l26_n664()
+ fun_l27_n861
+end
+
+def fun_l26_n665()
+ fun_l27_n335
+end
+
+def fun_l26_n666()
+ fun_l27_n805
+end
+
+def fun_l26_n667()
+ fun_l27_n284
+end
+
+def fun_l26_n668()
+ fun_l27_n283
+end
+
+def fun_l26_n669()
+ fun_l27_n471
+end
+
+def fun_l26_n670()
+ fun_l27_n479
+end
+
+def fun_l26_n671()
+ fun_l27_n938
+end
+
+def fun_l26_n672()
+ fun_l27_n288
+end
+
+def fun_l26_n673()
+ fun_l27_n0
+end
+
+def fun_l26_n674()
+ fun_l27_n856
+end
+
+def fun_l26_n675()
+ fun_l27_n490
+end
+
+def fun_l26_n676()
+ fun_l27_n88
+end
+
+def fun_l26_n677()
+ fun_l27_n584
+end
+
+def fun_l26_n678()
+ fun_l27_n138
+end
+
+def fun_l26_n679()
+ fun_l27_n998
+end
+
+def fun_l26_n680()
+ fun_l27_n259
+end
+
+def fun_l26_n681()
+ fun_l27_n913
+end
+
+def fun_l26_n682()
+ fun_l27_n697
+end
+
+def fun_l26_n683()
+ fun_l27_n102
+end
+
+def fun_l26_n684()
+ fun_l27_n726
+end
+
+def fun_l26_n685()
+ fun_l27_n655
+end
+
+def fun_l26_n686()
+ fun_l27_n264
+end
+
+def fun_l26_n687()
+ fun_l27_n603
+end
+
+def fun_l26_n688()
+ fun_l27_n331
+end
+
+def fun_l26_n689()
+ fun_l27_n760
+end
+
+def fun_l26_n690()
+ fun_l27_n105
+end
+
+def fun_l26_n691()
+ fun_l27_n554
+end
+
+def fun_l26_n692()
+ fun_l27_n287
+end
+
+def fun_l26_n693()
+ fun_l27_n592
+end
+
+def fun_l26_n694()
+ fun_l27_n22
+end
+
+def fun_l26_n695()
+ fun_l27_n794
+end
+
+def fun_l26_n696()
+ fun_l27_n196
+end
+
+def fun_l26_n697()
+ fun_l27_n848
+end
+
+def fun_l26_n698()
+ fun_l27_n589
+end
+
+def fun_l26_n699()
+ fun_l27_n267
+end
+
+def fun_l26_n700()
+ fun_l27_n562
+end
+
+def fun_l26_n701()
+ fun_l27_n563
+end
+
+def fun_l26_n702()
+ fun_l27_n909
+end
+
+def fun_l26_n703()
+ fun_l27_n92
+end
+
+def fun_l26_n704()
+ fun_l27_n140
+end
+
+def fun_l26_n705()
+ fun_l27_n330
+end
+
+def fun_l26_n706()
+ fun_l27_n734
+end
+
+def fun_l26_n707()
+ fun_l27_n994
+end
+
+def fun_l26_n708()
+ fun_l27_n414
+end
+
+def fun_l26_n709()
+ fun_l27_n931
+end
+
+def fun_l26_n710()
+ fun_l27_n82
+end
+
+def fun_l26_n711()
+ fun_l27_n341
+end
+
+def fun_l26_n712()
+ fun_l27_n9
+end
+
+def fun_l26_n713()
+ fun_l27_n868
+end
+
+def fun_l26_n714()
+ fun_l27_n249
+end
+
+def fun_l26_n715()
+ fun_l27_n393
+end
+
+def fun_l26_n716()
+ fun_l27_n835
+end
+
+def fun_l26_n717()
+ fun_l27_n975
+end
+
+def fun_l26_n718()
+ fun_l27_n110
+end
+
+def fun_l26_n719()
+ fun_l27_n700
+end
+
+def fun_l26_n720()
+ fun_l27_n396
+end
+
+def fun_l26_n721()
+ fun_l27_n973
+end
+
+def fun_l26_n722()
+ fun_l27_n898
+end
+
+def fun_l26_n723()
+ fun_l27_n418
+end
+
+def fun_l26_n724()
+ fun_l27_n342
+end
+
+def fun_l26_n725()
+ fun_l27_n783
+end
+
+def fun_l26_n726()
+ fun_l27_n86
+end
+
+def fun_l26_n727()
+ fun_l27_n556
+end
+
+def fun_l26_n728()
+ fun_l27_n777
+end
+
+def fun_l26_n729()
+ fun_l27_n729
+end
+
+def fun_l26_n730()
+ fun_l27_n156
+end
+
+def fun_l26_n731()
+ fun_l27_n458
+end
+
+def fun_l26_n732()
+ fun_l27_n580
+end
+
+def fun_l26_n733()
+ fun_l27_n764
+end
+
+def fun_l26_n734()
+ fun_l27_n295
+end
+
+def fun_l26_n735()
+ fun_l27_n850
+end
+
+def fun_l26_n736()
+ fun_l27_n881
+end
+
+def fun_l26_n737()
+ fun_l27_n416
+end
+
+def fun_l26_n738()
+ fun_l27_n996
+end
+
+def fun_l26_n739()
+ fun_l27_n347
+end
+
+def fun_l26_n740()
+ fun_l27_n607
+end
+
+def fun_l26_n741()
+ fun_l27_n749
+end
+
+def fun_l26_n742()
+ fun_l27_n564
+end
+
+def fun_l26_n743()
+ fun_l27_n217
+end
+
+def fun_l26_n744()
+ fun_l27_n375
+end
+
+def fun_l26_n745()
+ fun_l27_n487
+end
+
+def fun_l26_n746()
+ fun_l27_n86
+end
+
+def fun_l26_n747()
+ fun_l27_n765
+end
+
+def fun_l26_n748()
+ fun_l27_n569
+end
+
+def fun_l26_n749()
+ fun_l27_n461
+end
+
+def fun_l26_n750()
+ fun_l27_n633
+end
+
+def fun_l26_n751()
+ fun_l27_n89
+end
+
+def fun_l26_n752()
+ fun_l27_n841
+end
+
+def fun_l26_n753()
+ fun_l27_n499
+end
+
+def fun_l26_n754()
+ fun_l27_n947
+end
+
+def fun_l26_n755()
+ fun_l27_n690
+end
+
+def fun_l26_n756()
+ fun_l27_n531
+end
+
+def fun_l26_n757()
+ fun_l27_n766
+end
+
+def fun_l26_n758()
+ fun_l27_n853
+end
+
+def fun_l26_n759()
+ fun_l27_n65
+end
+
+def fun_l26_n760()
+ fun_l27_n884
+end
+
+def fun_l26_n761()
+ fun_l27_n235
+end
+
+def fun_l26_n762()
+ fun_l27_n39
+end
+
+def fun_l26_n763()
+ fun_l27_n868
+end
+
+def fun_l26_n764()
+ fun_l27_n202
+end
+
+def fun_l26_n765()
+ fun_l27_n360
+end
+
+def fun_l26_n766()
+ fun_l27_n450
+end
+
+def fun_l26_n767()
+ fun_l27_n590
+end
+
+def fun_l26_n768()
+ fun_l27_n635
+end
+
+def fun_l26_n769()
+ fun_l27_n314
+end
+
+def fun_l26_n770()
+ fun_l27_n68
+end
+
+def fun_l26_n771()
+ fun_l27_n858
+end
+
+def fun_l26_n772()
+ fun_l27_n51
+end
+
+def fun_l26_n773()
+ fun_l27_n524
+end
+
+def fun_l26_n774()
+ fun_l27_n13
+end
+
+def fun_l26_n775()
+ fun_l27_n451
+end
+
+def fun_l26_n776()
+ fun_l27_n682
+end
+
+def fun_l26_n777()
+ fun_l27_n736
+end
+
+def fun_l26_n778()
+ fun_l27_n250
+end
+
+def fun_l26_n779()
+ fun_l27_n810
+end
+
+def fun_l26_n780()
+ fun_l27_n979
+end
+
+def fun_l26_n781()
+ fun_l27_n102
+end
+
+def fun_l26_n782()
+ fun_l27_n955
+end
+
+def fun_l26_n783()
+ fun_l27_n610
+end
+
+def fun_l26_n784()
+ fun_l27_n301
+end
+
+def fun_l26_n785()
+ fun_l27_n389
+end
+
+def fun_l26_n786()
+ fun_l27_n754
+end
+
+def fun_l26_n787()
+ fun_l27_n717
+end
+
+def fun_l26_n788()
+ fun_l27_n77
+end
+
+def fun_l26_n789()
+ fun_l27_n401
+end
+
+def fun_l26_n790()
+ fun_l27_n430
+end
+
+def fun_l26_n791()
+ fun_l27_n310
+end
+
+def fun_l26_n792()
+ fun_l27_n839
+end
+
+def fun_l26_n793()
+ fun_l27_n682
+end
+
+def fun_l26_n794()
+ fun_l27_n648
+end
+
+def fun_l26_n795()
+ fun_l27_n281
+end
+
+def fun_l26_n796()
+ fun_l27_n749
+end
+
+def fun_l26_n797()
+ fun_l27_n502
+end
+
+def fun_l26_n798()
+ fun_l27_n201
+end
+
+def fun_l26_n799()
+ fun_l27_n851
+end
+
+def fun_l26_n800()
+ fun_l27_n249
+end
+
+def fun_l26_n801()
+ fun_l27_n119
+end
+
+def fun_l26_n802()
+ fun_l27_n519
+end
+
+def fun_l26_n803()
+ fun_l27_n157
+end
+
+def fun_l26_n804()
+ fun_l27_n53
+end
+
+def fun_l26_n805()
+ fun_l27_n765
+end
+
+def fun_l26_n806()
+ fun_l27_n48
+end
+
+def fun_l26_n807()
+ fun_l27_n127
+end
+
+def fun_l26_n808()
+ fun_l27_n418
+end
+
+def fun_l26_n809()
+ fun_l27_n650
+end
+
+def fun_l26_n810()
+ fun_l27_n918
+end
+
+def fun_l26_n811()
+ fun_l27_n878
+end
+
+def fun_l26_n812()
+ fun_l27_n244
+end
+
+def fun_l26_n813()
+ fun_l27_n611
+end
+
+def fun_l26_n814()
+ fun_l27_n82
+end
+
+def fun_l26_n815()
+ fun_l27_n6
+end
+
+def fun_l26_n816()
+ fun_l27_n486
+end
+
+def fun_l26_n817()
+ fun_l27_n711
+end
+
+def fun_l26_n818()
+ fun_l27_n792
+end
+
+def fun_l26_n819()
+ fun_l27_n974
+end
+
+def fun_l26_n820()
+ fun_l27_n480
+end
+
+def fun_l26_n821()
+ fun_l27_n460
+end
+
+def fun_l26_n822()
+ fun_l27_n520
+end
+
+def fun_l26_n823()
+ fun_l27_n803
+end
+
+def fun_l26_n824()
+ fun_l27_n734
+end
+
+def fun_l26_n825()
+ fun_l27_n336
+end
+
+def fun_l26_n826()
+ fun_l27_n657
+end
+
+def fun_l26_n827()
+ fun_l27_n20
+end
+
+def fun_l26_n828()
+ fun_l27_n83
+end
+
+def fun_l26_n829()
+ fun_l27_n452
+end
+
+def fun_l26_n830()
+ fun_l27_n973
+end
+
+def fun_l26_n831()
+ fun_l27_n79
+end
+
+def fun_l26_n832()
+ fun_l27_n327
+end
+
+def fun_l26_n833()
+ fun_l27_n36
+end
+
+def fun_l26_n834()
+ fun_l27_n186
+end
+
+def fun_l26_n835()
+ fun_l27_n946
+end
+
+def fun_l26_n836()
+ fun_l27_n776
+end
+
+def fun_l26_n837()
+ fun_l27_n33
+end
+
+def fun_l26_n838()
+ fun_l27_n966
+end
+
+def fun_l26_n839()
+ fun_l27_n961
+end
+
+def fun_l26_n840()
+ fun_l27_n181
+end
+
+def fun_l26_n841()
+ fun_l27_n103
+end
+
+def fun_l26_n842()
+ fun_l27_n500
+end
+
+def fun_l26_n843()
+ fun_l27_n359
+end
+
+def fun_l26_n844()
+ fun_l27_n316
+end
+
+def fun_l26_n845()
+ fun_l27_n921
+end
+
+def fun_l26_n846()
+ fun_l27_n745
+end
+
+def fun_l26_n847()
+ fun_l27_n555
+end
+
+def fun_l26_n848()
+ fun_l27_n306
+end
+
+def fun_l26_n849()
+ fun_l27_n462
+end
+
+def fun_l26_n850()
+ fun_l27_n369
+end
+
+def fun_l26_n851()
+ fun_l27_n489
+end
+
+def fun_l26_n852()
+ fun_l27_n276
+end
+
+def fun_l26_n853()
+ fun_l27_n509
+end
+
+def fun_l26_n854()
+ fun_l27_n524
+end
+
+def fun_l26_n855()
+ fun_l27_n421
+end
+
+def fun_l26_n856()
+ fun_l27_n845
+end
+
+def fun_l26_n857()
+ fun_l27_n600
+end
+
+def fun_l26_n858()
+ fun_l27_n961
+end
+
+def fun_l26_n859()
+ fun_l27_n506
+end
+
+def fun_l26_n860()
+ fun_l27_n106
+end
+
+def fun_l26_n861()
+ fun_l27_n525
+end
+
+def fun_l26_n862()
+ fun_l27_n515
+end
+
+def fun_l26_n863()
+ fun_l27_n506
+end
+
+def fun_l26_n864()
+ fun_l27_n283
+end
+
+def fun_l26_n865()
+ fun_l27_n189
+end
+
+def fun_l26_n866()
+ fun_l27_n181
+end
+
+def fun_l26_n867()
+ fun_l27_n338
+end
+
+def fun_l26_n868()
+ fun_l27_n965
+end
+
+def fun_l26_n869()
+ fun_l27_n219
+end
+
+def fun_l26_n870()
+ fun_l27_n604
+end
+
+def fun_l26_n871()
+ fun_l27_n211
+end
+
+def fun_l26_n872()
+ fun_l27_n225
+end
+
+def fun_l26_n873()
+ fun_l27_n776
+end
+
+def fun_l26_n874()
+ fun_l27_n723
+end
+
+def fun_l26_n875()
+ fun_l27_n653
+end
+
+def fun_l26_n876()
+ fun_l27_n157
+end
+
+def fun_l26_n877()
+ fun_l27_n321
+end
+
+def fun_l26_n878()
+ fun_l27_n684
+end
+
+def fun_l26_n879()
+ fun_l27_n270
+end
+
+def fun_l26_n880()
+ fun_l27_n575
+end
+
+def fun_l26_n881()
+ fun_l27_n201
+end
+
+def fun_l26_n882()
+ fun_l27_n772
+end
+
+def fun_l26_n883()
+ fun_l27_n610
+end
+
+def fun_l26_n884()
+ fun_l27_n117
+end
+
+def fun_l26_n885()
+ fun_l27_n706
+end
+
+def fun_l26_n886()
+ fun_l27_n245
+end
+
+def fun_l26_n887()
+ fun_l27_n173
+end
+
+def fun_l26_n888()
+ fun_l27_n679
+end
+
+def fun_l26_n889()
+ fun_l27_n725
+end
+
+def fun_l26_n890()
+ fun_l27_n481
+end
+
+def fun_l26_n891()
+ fun_l27_n632
+end
+
+def fun_l26_n892()
+ fun_l27_n20
+end
+
+def fun_l26_n893()
+ fun_l27_n649
+end
+
+def fun_l26_n894()
+ fun_l27_n560
+end
+
+def fun_l26_n895()
+ fun_l27_n861
+end
+
+def fun_l26_n896()
+ fun_l27_n565
+end
+
+def fun_l26_n897()
+ fun_l27_n864
+end
+
+def fun_l26_n898()
+ fun_l27_n590
+end
+
+def fun_l26_n899()
+ fun_l27_n413
+end
+
+def fun_l26_n900()
+ fun_l27_n833
+end
+
+def fun_l26_n901()
+ fun_l27_n948
+end
+
+def fun_l26_n902()
+ fun_l27_n946
+end
+
+def fun_l26_n903()
+ fun_l27_n211
+end
+
+def fun_l26_n904()
+ fun_l27_n367
+end
+
+def fun_l26_n905()
+ fun_l27_n893
+end
+
+def fun_l26_n906()
+ fun_l27_n710
+end
+
+def fun_l26_n907()
+ fun_l27_n655
+end
+
+def fun_l26_n908()
+ fun_l27_n830
+end
+
+def fun_l26_n909()
+ fun_l27_n649
+end
+
+def fun_l26_n910()
+ fun_l27_n195
+end
+
+def fun_l26_n911()
+ fun_l27_n474
+end
+
+def fun_l26_n912()
+ fun_l27_n362
+end
+
+def fun_l26_n913()
+ fun_l27_n199
+end
+
+def fun_l26_n914()
+ fun_l27_n426
+end
+
+def fun_l26_n915()
+ fun_l27_n123
+end
+
+def fun_l26_n916()
+ fun_l27_n734
+end
+
+def fun_l26_n917()
+ fun_l27_n646
+end
+
+def fun_l26_n918()
+ fun_l27_n603
+end
+
+def fun_l26_n919()
+ fun_l27_n907
+end
+
+def fun_l26_n920()
+ fun_l27_n500
+end
+
+def fun_l26_n921()
+ fun_l27_n30
+end
+
+def fun_l26_n922()
+ fun_l27_n393
+end
+
+def fun_l26_n923()
+ fun_l27_n981
+end
+
+def fun_l26_n924()
+ fun_l27_n318
+end
+
+def fun_l26_n925()
+ fun_l27_n979
+end
+
+def fun_l26_n926()
+ fun_l27_n439
+end
+
+def fun_l26_n927()
+ fun_l27_n398
+end
+
+def fun_l26_n928()
+ fun_l27_n301
+end
+
+def fun_l26_n929()
+ fun_l27_n778
+end
+
+def fun_l26_n930()
+ fun_l27_n318
+end
+
+def fun_l26_n931()
+ fun_l27_n835
+end
+
+def fun_l26_n932()
+ fun_l27_n90
+end
+
+def fun_l26_n933()
+ fun_l27_n321
+end
+
+def fun_l26_n934()
+ fun_l27_n600
+end
+
+def fun_l26_n935()
+ fun_l27_n731
+end
+
+def fun_l26_n936()
+ fun_l27_n318
+end
+
+def fun_l26_n937()
+ fun_l27_n229
+end
+
+def fun_l26_n938()
+ fun_l27_n997
+end
+
+def fun_l26_n939()
+ fun_l27_n105
+end
+
+def fun_l26_n940()
+ fun_l27_n122
+end
+
+def fun_l26_n941()
+ fun_l27_n680
+end
+
+def fun_l26_n942()
+ fun_l27_n814
+end
+
+def fun_l26_n943()
+ fun_l27_n350
+end
+
+def fun_l26_n944()
+ fun_l27_n363
+end
+
+def fun_l26_n945()
+ fun_l27_n82
+end
+
+def fun_l26_n946()
+ fun_l27_n82
+end
+
+def fun_l26_n947()
+ fun_l27_n638
+end
+
+def fun_l26_n948()
+ fun_l27_n677
+end
+
+def fun_l26_n949()
+ fun_l27_n931
+end
+
+def fun_l26_n950()
+ fun_l27_n151
+end
+
+def fun_l26_n951()
+ fun_l27_n862
+end
+
+def fun_l26_n952()
+ fun_l27_n984
+end
+
+def fun_l26_n953()
+ fun_l27_n471
+end
+
+def fun_l26_n954()
+ fun_l27_n859
+end
+
+def fun_l26_n955()
+ fun_l27_n127
+end
+
+def fun_l26_n956()
+ fun_l27_n963
+end
+
+def fun_l26_n957()
+ fun_l27_n859
+end
+
+def fun_l26_n958()
+ fun_l27_n900
+end
+
+def fun_l26_n959()
+ fun_l27_n957
+end
+
+def fun_l26_n960()
+ fun_l27_n443
+end
+
+def fun_l26_n961()
+ fun_l27_n826
+end
+
+def fun_l26_n962()
+ fun_l27_n303
+end
+
+def fun_l26_n963()
+ fun_l27_n766
+end
+
+def fun_l26_n964()
+ fun_l27_n420
+end
+
+def fun_l26_n965()
+ fun_l27_n873
+end
+
+def fun_l26_n966()
+ fun_l27_n285
+end
+
+def fun_l26_n967()
+ fun_l27_n490
+end
+
+def fun_l26_n968()
+ fun_l27_n46
+end
+
+def fun_l26_n969()
+ fun_l27_n451
+end
+
+def fun_l26_n970()
+ fun_l27_n157
+end
+
+def fun_l26_n971()
+ fun_l27_n981
+end
+
+def fun_l26_n972()
+ fun_l27_n969
+end
+
+def fun_l26_n973()
+ fun_l27_n644
+end
+
+def fun_l26_n974()
+ fun_l27_n753
+end
+
+def fun_l26_n975()
+ fun_l27_n306
+end
+
+def fun_l26_n976()
+ fun_l27_n617
+end
+
+def fun_l26_n977()
+ fun_l27_n258
+end
+
+def fun_l26_n978()
+ fun_l27_n511
+end
+
+def fun_l26_n979()
+ fun_l27_n267
+end
+
+def fun_l26_n980()
+ fun_l27_n42
+end
+
+def fun_l26_n981()
+ fun_l27_n153
+end
+
+def fun_l26_n982()
+ fun_l27_n77
+end
+
+def fun_l26_n983()
+ fun_l27_n658
+end
+
+def fun_l26_n984()
+ fun_l27_n605
+end
+
+def fun_l26_n985()
+ fun_l27_n40
+end
+
+def fun_l26_n986()
+ fun_l27_n375
+end
+
+def fun_l26_n987()
+ fun_l27_n273
+end
+
+def fun_l26_n988()
+ fun_l27_n290
+end
+
+def fun_l26_n989()
+ fun_l27_n507
+end
+
+def fun_l26_n990()
+ fun_l27_n537
+end
+
+def fun_l26_n991()
+ fun_l27_n373
+end
+
+def fun_l26_n992()
+ fun_l27_n39
+end
+
+def fun_l26_n993()
+ fun_l27_n356
+end
+
+def fun_l26_n994()
+ fun_l27_n875
+end
+
+def fun_l26_n995()
+ fun_l27_n112
+end
+
+def fun_l26_n996()
+ fun_l27_n209
+end
+
+def fun_l26_n997()
+ fun_l27_n690
+end
+
+def fun_l26_n998()
+ fun_l27_n19
+end
+
+def fun_l26_n999()
+ fun_l27_n962
+end
+
+def fun_l27_n0()
+ fun_l28_n602
+end
+
+def fun_l27_n1()
+ fun_l28_n911
+end
+
+def fun_l27_n2()
+ fun_l28_n797
+end
+
+def fun_l27_n3()
+ fun_l28_n261
+end
+
+def fun_l27_n4()
+ fun_l28_n172
+end
+
+def fun_l27_n5()
+ fun_l28_n430
+end
+
+def fun_l27_n6()
+ fun_l28_n397
+end
+
+def fun_l27_n7()
+ fun_l28_n388
+end
+
+def fun_l27_n8()
+ fun_l28_n218
+end
+
+def fun_l27_n9()
+ fun_l28_n71
+end
+
+def fun_l27_n10()
+ fun_l28_n424
+end
+
+def fun_l27_n11()
+ fun_l28_n454
+end
+
+def fun_l27_n12()
+ fun_l28_n388
+end
+
+def fun_l27_n13()
+ fun_l28_n909
+end
+
+def fun_l27_n14()
+ fun_l28_n655
+end
+
+def fun_l27_n15()
+ fun_l28_n355
+end
+
+def fun_l27_n16()
+ fun_l28_n319
+end
+
+def fun_l27_n17()
+ fun_l28_n137
+end
+
+def fun_l27_n18()
+ fun_l28_n929
+end
+
+def fun_l27_n19()
+ fun_l28_n887
+end
+
+def fun_l27_n20()
+ fun_l28_n571
+end
+
+def fun_l27_n21()
+ fun_l28_n480
+end
+
+def fun_l27_n22()
+ fun_l28_n431
+end
+
+def fun_l27_n23()
+ fun_l28_n918
+end
+
+def fun_l27_n24()
+ fun_l28_n673
+end
+
+def fun_l27_n25()
+ fun_l28_n550
+end
+
+def fun_l27_n26()
+ fun_l28_n256
+end
+
+def fun_l27_n27()
+ fun_l28_n624
+end
+
+def fun_l27_n28()
+ fun_l28_n245
+end
+
+def fun_l27_n29()
+ fun_l28_n303
+end
+
+def fun_l27_n30()
+ fun_l28_n260
+end
+
+def fun_l27_n31()
+ fun_l28_n174
+end
+
+def fun_l27_n32()
+ fun_l28_n147
+end
+
+def fun_l27_n33()
+ fun_l28_n590
+end
+
+def fun_l27_n34()
+ fun_l28_n691
+end
+
+def fun_l27_n35()
+ fun_l28_n739
+end
+
+def fun_l27_n36()
+ fun_l28_n530
+end
+
+def fun_l27_n37()
+ fun_l28_n20
+end
+
+def fun_l27_n38()
+ fun_l28_n147
+end
+
+def fun_l27_n39()
+ fun_l28_n362
+end
+
+def fun_l27_n40()
+ fun_l28_n250
+end
+
+def fun_l27_n41()
+ fun_l28_n579
+end
+
+def fun_l27_n42()
+ fun_l28_n557
+end
+
+def fun_l27_n43()
+ fun_l28_n639
+end
+
+def fun_l27_n44()
+ fun_l28_n309
+end
+
+def fun_l27_n45()
+ fun_l28_n213
+end
+
+def fun_l27_n46()
+ fun_l28_n178
+end
+
+def fun_l27_n47()
+ fun_l28_n974
+end
+
+def fun_l27_n48()
+ fun_l28_n500
+end
+
+def fun_l27_n49()
+ fun_l28_n814
+end
+
+def fun_l27_n50()
+ fun_l28_n930
+end
+
+def fun_l27_n51()
+ fun_l28_n329
+end
+
+def fun_l27_n52()
+ fun_l28_n385
+end
+
+def fun_l27_n53()
+ fun_l28_n214
+end
+
+def fun_l27_n54()
+ fun_l28_n934
+end
+
+def fun_l27_n55()
+ fun_l28_n645
+end
+
+def fun_l27_n56()
+ fun_l28_n311
+end
+
+def fun_l27_n57()
+ fun_l28_n15
+end
+
+def fun_l27_n58()
+ fun_l28_n499
+end
+
+def fun_l27_n59()
+ fun_l28_n919
+end
+
+def fun_l27_n60()
+ fun_l28_n659
+end
+
+def fun_l27_n61()
+ fun_l28_n921
+end
+
+def fun_l27_n62()
+ fun_l28_n306
+end
+
+def fun_l27_n63()
+ fun_l28_n128
+end
+
+def fun_l27_n64()
+ fun_l28_n871
+end
+
+def fun_l27_n65()
+ fun_l28_n434
+end
+
+def fun_l27_n66()
+ fun_l28_n775
+end
+
+def fun_l27_n67()
+ fun_l28_n311
+end
+
+def fun_l27_n68()
+ fun_l28_n959
+end
+
+def fun_l27_n69()
+ fun_l28_n648
+end
+
+def fun_l27_n70()
+ fun_l28_n893
+end
+
+def fun_l27_n71()
+ fun_l28_n669
+end
+
+def fun_l27_n72()
+ fun_l28_n121
+end
+
+def fun_l27_n73()
+ fun_l28_n102
+end
+
+def fun_l27_n74()
+ fun_l28_n887
+end
+
+def fun_l27_n75()
+ fun_l28_n326
+end
+
+def fun_l27_n76()
+ fun_l28_n48
+end
+
+def fun_l27_n77()
+ fun_l28_n636
+end
+
+def fun_l27_n78()
+ fun_l28_n804
+end
+
+def fun_l27_n79()
+ fun_l28_n838
+end
+
+def fun_l27_n80()
+ fun_l28_n859
+end
+
+def fun_l27_n81()
+ fun_l28_n683
+end
+
+def fun_l27_n82()
+ fun_l28_n752
+end
+
+def fun_l27_n83()
+ fun_l28_n244
+end
+
+def fun_l27_n84()
+ fun_l28_n727
+end
+
+def fun_l27_n85()
+ fun_l28_n818
+end
+
+def fun_l27_n86()
+ fun_l28_n451
+end
+
+def fun_l27_n87()
+ fun_l28_n9
+end
+
+def fun_l27_n88()
+ fun_l28_n738
+end
+
+def fun_l27_n89()
+ fun_l28_n589
+end
+
+def fun_l27_n90()
+ fun_l28_n140
+end
+
+def fun_l27_n91()
+ fun_l28_n615
+end
+
+def fun_l27_n92()
+ fun_l28_n973
+end
+
+def fun_l27_n93()
+ fun_l28_n668
+end
+
+def fun_l27_n94()
+ fun_l28_n299
+end
+
+def fun_l27_n95()
+ fun_l28_n358
+end
+
+def fun_l27_n96()
+ fun_l28_n319
+end
+
+def fun_l27_n97()
+ fun_l28_n165
+end
+
+def fun_l27_n98()
+ fun_l28_n67
+end
+
+def fun_l27_n99()
+ fun_l28_n494
+end
+
+def fun_l27_n100()
+ fun_l28_n107
+end
+
+def fun_l27_n101()
+ fun_l28_n985
+end
+
+def fun_l27_n102()
+ fun_l28_n239
+end
+
+def fun_l27_n103()
+ fun_l28_n64
+end
+
+def fun_l27_n104()
+ fun_l28_n676
+end
+
+def fun_l27_n105()
+ fun_l28_n852
+end
+
+def fun_l27_n106()
+ fun_l28_n668
+end
+
+def fun_l27_n107()
+ fun_l28_n523
+end
+
+def fun_l27_n108()
+ fun_l28_n15
+end
+
+def fun_l27_n109()
+ fun_l28_n619
+end
+
+def fun_l27_n110()
+ fun_l28_n440
+end
+
+def fun_l27_n111()
+ fun_l28_n792
+end
+
+def fun_l27_n112()
+ fun_l28_n771
+end
+
+def fun_l27_n113()
+ fun_l28_n263
+end
+
+def fun_l27_n114()
+ fun_l28_n180
+end
+
+def fun_l27_n115()
+ fun_l28_n615
+end
+
+def fun_l27_n116()
+ fun_l28_n319
+end
+
+def fun_l27_n117()
+ fun_l28_n970
+end
+
+def fun_l27_n118()
+ fun_l28_n946
+end
+
+def fun_l27_n119()
+ fun_l28_n121
+end
+
+def fun_l27_n120()
+ fun_l28_n655
+end
+
+def fun_l27_n121()
+ fun_l28_n68
+end
+
+def fun_l27_n122()
+ fun_l28_n406
+end
+
+def fun_l27_n123()
+ fun_l28_n535
+end
+
+def fun_l27_n124()
+ fun_l28_n951
+end
+
+def fun_l27_n125()
+ fun_l28_n366
+end
+
+def fun_l27_n126()
+ fun_l28_n192
+end
+
+def fun_l27_n127()
+ fun_l28_n106
+end
+
+def fun_l27_n128()
+ fun_l28_n21
+end
+
+def fun_l27_n129()
+ fun_l28_n339
+end
+
+def fun_l27_n130()
+ fun_l28_n824
+end
+
+def fun_l27_n131()
+ fun_l28_n921
+end
+
+def fun_l27_n132()
+ fun_l28_n678
+end
+
+def fun_l27_n133()
+ fun_l28_n925
+end
+
+def fun_l27_n134()
+ fun_l28_n55
+end
+
+def fun_l27_n135()
+ fun_l28_n726
+end
+
+def fun_l27_n136()
+ fun_l28_n110
+end
+
+def fun_l27_n137()
+ fun_l28_n559
+end
+
+def fun_l27_n138()
+ fun_l28_n879
+end
+
+def fun_l27_n139()
+ fun_l28_n332
+end
+
+def fun_l27_n140()
+ fun_l28_n167
+end
+
+def fun_l27_n141()
+ fun_l28_n123
+end
+
+def fun_l27_n142()
+ fun_l28_n707
+end
+
+def fun_l27_n143()
+ fun_l28_n423
+end
+
+def fun_l27_n144()
+ fun_l28_n659
+end
+
+def fun_l27_n145()
+ fun_l28_n322
+end
+
+def fun_l27_n146()
+ fun_l28_n227
+end
+
+def fun_l27_n147()
+ fun_l28_n679
+end
+
+def fun_l27_n148()
+ fun_l28_n376
+end
+
+def fun_l27_n149()
+ fun_l28_n327
+end
+
+def fun_l27_n150()
+ fun_l28_n328
+end
+
+def fun_l27_n151()
+ fun_l28_n408
+end
+
+def fun_l27_n152()
+ fun_l28_n141
+end
+
+def fun_l27_n153()
+ fun_l28_n728
+end
+
+def fun_l27_n154()
+ fun_l28_n207
+end
+
+def fun_l27_n155()
+ fun_l28_n836
+end
+
+def fun_l27_n156()
+ fun_l28_n71
+end
+
+def fun_l27_n157()
+ fun_l28_n390
+end
+
+def fun_l27_n158()
+ fun_l28_n277
+end
+
+def fun_l27_n159()
+ fun_l28_n960
+end
+
+def fun_l27_n160()
+ fun_l28_n705
+end
+
+def fun_l27_n161()
+ fun_l28_n445
+end
+
+def fun_l27_n162()
+ fun_l28_n570
+end
+
+def fun_l27_n163()
+ fun_l28_n878
+end
+
+def fun_l27_n164()
+ fun_l28_n714
+end
+
+def fun_l27_n165()
+ fun_l28_n933
+end
+
+def fun_l27_n166()
+ fun_l28_n480
+end
+
+def fun_l27_n167()
+ fun_l28_n308
+end
+
+def fun_l27_n168()
+ fun_l28_n604
+end
+
+def fun_l27_n169()
+ fun_l28_n892
+end
+
+def fun_l27_n170()
+ fun_l28_n901
+end
+
+def fun_l27_n171()
+ fun_l28_n524
+end
+
+def fun_l27_n172()
+ fun_l28_n533
+end
+
+def fun_l27_n173()
+ fun_l28_n761
+end
+
+def fun_l27_n174()
+ fun_l28_n97
+end
+
+def fun_l27_n175()
+ fun_l28_n944
+end
+
+def fun_l27_n176()
+ fun_l28_n627
+end
+
+def fun_l27_n177()
+ fun_l28_n720
+end
+
+def fun_l27_n178()
+ fun_l28_n366
+end
+
+def fun_l27_n179()
+ fun_l28_n353
+end
+
+def fun_l27_n180()
+ fun_l28_n441
+end
+
+def fun_l27_n181()
+ fun_l28_n682
+end
+
+def fun_l27_n182()
+ fun_l28_n581
+end
+
+def fun_l27_n183()
+ fun_l28_n974
+end
+
+def fun_l27_n184()
+ fun_l28_n522
+end
+
+def fun_l27_n185()
+ fun_l28_n702
+end
+
+def fun_l27_n186()
+ fun_l28_n941
+end
+
+def fun_l27_n187()
+ fun_l28_n665
+end
+
+def fun_l27_n188()
+ fun_l28_n148
+end
+
+def fun_l27_n189()
+ fun_l28_n91
+end
+
+def fun_l27_n190()
+ fun_l28_n679
+end
+
+def fun_l27_n191()
+ fun_l28_n929
+end
+
+def fun_l27_n192()
+ fun_l28_n828
+end
+
+def fun_l27_n193()
+ fun_l28_n872
+end
+
+def fun_l27_n194()
+ fun_l28_n152
+end
+
+def fun_l27_n195()
+ fun_l28_n593
+end
+
+def fun_l27_n196()
+ fun_l28_n438
+end
+
+def fun_l27_n197()
+ fun_l28_n390
+end
+
+def fun_l27_n198()
+ fun_l28_n354
+end
+
+def fun_l27_n199()
+ fun_l28_n547
+end
+
+def fun_l27_n200()
+ fun_l28_n249
+end
+
+def fun_l27_n201()
+ fun_l28_n562
+end
+
+def fun_l27_n202()
+ fun_l28_n571
+end
+
+def fun_l27_n203()
+ fun_l28_n763
+end
+
+def fun_l27_n204()
+ fun_l28_n961
+end
+
+def fun_l27_n205()
+ fun_l28_n368
+end
+
+def fun_l27_n206()
+ fun_l28_n219
+end
+
+def fun_l27_n207()
+ fun_l28_n414
+end
+
+def fun_l27_n208()
+ fun_l28_n130
+end
+
+def fun_l27_n209()
+ fun_l28_n911
+end
+
+def fun_l27_n210()
+ fun_l28_n94
+end
+
+def fun_l27_n211()
+ fun_l28_n966
+end
+
+def fun_l27_n212()
+ fun_l28_n271
+end
+
+def fun_l27_n213()
+ fun_l28_n372
+end
+
+def fun_l27_n214()
+ fun_l28_n845
+end
+
+def fun_l27_n215()
+ fun_l28_n924
+end
+
+def fun_l27_n216()
+ fun_l28_n220
+end
+
+def fun_l27_n217()
+ fun_l28_n653
+end
+
+def fun_l27_n218()
+ fun_l28_n960
+end
+
+def fun_l27_n219()
+ fun_l28_n343
+end
+
+def fun_l27_n220()
+ fun_l28_n255
+end
+
+def fun_l27_n221()
+ fun_l28_n206
+end
+
+def fun_l27_n222()
+ fun_l28_n190
+end
+
+def fun_l27_n223()
+ fun_l28_n753
+end
+
+def fun_l27_n224()
+ fun_l28_n530
+end
+
+def fun_l27_n225()
+ fun_l28_n198
+end
+
+def fun_l27_n226()
+ fun_l28_n604
+end
+
+def fun_l27_n227()
+ fun_l28_n685
+end
+
+def fun_l27_n228()
+ fun_l28_n268
+end
+
+def fun_l27_n229()
+ fun_l28_n344
+end
+
+def fun_l27_n230()
+ fun_l28_n850
+end
+
+def fun_l27_n231()
+ fun_l28_n612
+end
+
+def fun_l27_n232()
+ fun_l28_n598
+end
+
+def fun_l27_n233()
+ fun_l28_n766
+end
+
+def fun_l27_n234()
+ fun_l28_n994
+end
+
+def fun_l27_n235()
+ fun_l28_n566
+end
+
+def fun_l27_n236()
+ fun_l28_n306
+end
+
+def fun_l27_n237()
+ fun_l28_n592
+end
+
+def fun_l27_n238()
+ fun_l28_n814
+end
+
+def fun_l27_n239()
+ fun_l28_n319
+end
+
+def fun_l27_n240()
+ fun_l28_n619
+end
+
+def fun_l27_n241()
+ fun_l28_n631
+end
+
+def fun_l27_n242()
+ fun_l28_n240
+end
+
+def fun_l27_n243()
+ fun_l28_n714
+end
+
+def fun_l27_n244()
+ fun_l28_n651
+end
+
+def fun_l27_n245()
+ fun_l28_n760
+end
+
+def fun_l27_n246()
+ fun_l28_n925
+end
+
+def fun_l27_n247()
+ fun_l28_n537
+end
+
+def fun_l27_n248()
+ fun_l28_n541
+end
+
+def fun_l27_n249()
+ fun_l28_n963
+end
+
+def fun_l27_n250()
+ fun_l28_n630
+end
+
+def fun_l27_n251()
+ fun_l28_n124
+end
+
+def fun_l27_n252()
+ fun_l28_n894
+end
+
+def fun_l27_n253()
+ fun_l28_n307
+end
+
+def fun_l27_n254()
+ fun_l28_n485
+end
+
+def fun_l27_n255()
+ fun_l28_n272
+end
+
+def fun_l27_n256()
+ fun_l28_n994
+end
+
+def fun_l27_n257()
+ fun_l28_n48
+end
+
+def fun_l27_n258()
+ fun_l28_n374
+end
+
+def fun_l27_n259()
+ fun_l28_n508
+end
+
+def fun_l27_n260()
+ fun_l28_n936
+end
+
+def fun_l27_n261()
+ fun_l28_n43
+end
+
+def fun_l27_n262()
+ fun_l28_n297
+end
+
+def fun_l27_n263()
+ fun_l28_n205
+end
+
+def fun_l27_n264()
+ fun_l28_n234
+end
+
+def fun_l27_n265()
+ fun_l28_n560
+end
+
+def fun_l27_n266()
+ fun_l28_n124
+end
+
+def fun_l27_n267()
+ fun_l28_n912
+end
+
+def fun_l27_n268()
+ fun_l28_n545
+end
+
+def fun_l27_n269()
+ fun_l28_n266
+end
+
+def fun_l27_n270()
+ fun_l28_n917
+end
+
+def fun_l27_n271()
+ fun_l28_n971
+end
+
+def fun_l27_n272()
+ fun_l28_n305
+end
+
+def fun_l27_n273()
+ fun_l28_n158
+end
+
+def fun_l27_n274()
+ fun_l28_n241
+end
+
+def fun_l27_n275()
+ fun_l28_n667
+end
+
+def fun_l27_n276()
+ fun_l28_n857
+end
+
+def fun_l27_n277()
+ fun_l28_n207
+end
+
+def fun_l27_n278()
+ fun_l28_n258
+end
+
+def fun_l27_n279()
+ fun_l28_n410
+end
+
+def fun_l27_n280()
+ fun_l28_n868
+end
+
+def fun_l27_n281()
+ fun_l28_n976
+end
+
+def fun_l27_n282()
+ fun_l28_n519
+end
+
+def fun_l27_n283()
+ fun_l28_n165
+end
+
+def fun_l27_n284()
+ fun_l28_n790
+end
+
+def fun_l27_n285()
+ fun_l28_n825
+end
+
+def fun_l27_n286()
+ fun_l28_n844
+end
+
+def fun_l27_n287()
+ fun_l28_n450
+end
+
+def fun_l27_n288()
+ fun_l28_n913
+end
+
+def fun_l27_n289()
+ fun_l28_n418
+end
+
+def fun_l27_n290()
+ fun_l28_n63
+end
+
+def fun_l27_n291()
+ fun_l28_n306
+end
+
+def fun_l27_n292()
+ fun_l28_n233
+end
+
+def fun_l27_n293()
+ fun_l28_n274
+end
+
+def fun_l27_n294()
+ fun_l28_n292
+end
+
+def fun_l27_n295()
+ fun_l28_n504
+end
+
+def fun_l27_n296()
+ fun_l28_n769
+end
+
+def fun_l27_n297()
+ fun_l28_n404
+end
+
+def fun_l27_n298()
+ fun_l28_n782
+end
+
+def fun_l27_n299()
+ fun_l28_n788
+end
+
+def fun_l27_n300()
+ fun_l28_n727
+end
+
+def fun_l27_n301()
+ fun_l28_n187
+end
+
+def fun_l27_n302()
+ fun_l28_n568
+end
+
+def fun_l27_n303()
+ fun_l28_n195
+end
+
+def fun_l27_n304()
+ fun_l28_n696
+end
+
+def fun_l27_n305()
+ fun_l28_n293
+end
+
+def fun_l27_n306()
+ fun_l28_n722
+end
+
+def fun_l27_n307()
+ fun_l28_n911
+end
+
+def fun_l27_n308()
+ fun_l28_n827
+end
+
+def fun_l27_n309()
+ fun_l28_n767
+end
+
+def fun_l27_n310()
+ fun_l28_n423
+end
+
+def fun_l27_n311()
+ fun_l28_n60
+end
+
+def fun_l27_n312()
+ fun_l28_n466
+end
+
+def fun_l27_n313()
+ fun_l28_n270
+end
+
+def fun_l27_n314()
+ fun_l28_n993
+end
+
+def fun_l27_n315()
+ fun_l28_n231
+end
+
+def fun_l27_n316()
+ fun_l28_n514
+end
+
+def fun_l27_n317()
+ fun_l28_n57
+end
+
+def fun_l27_n318()
+ fun_l28_n646
+end
+
+def fun_l27_n319()
+ fun_l28_n17
+end
+
+def fun_l27_n320()
+ fun_l28_n964
+end
+
+def fun_l27_n321()
+ fun_l28_n1
+end
+
+def fun_l27_n322()
+ fun_l28_n956
+end
+
+def fun_l27_n323()
+ fun_l28_n273
+end
+
+def fun_l27_n324()
+ fun_l28_n370
+end
+
+def fun_l27_n325()
+ fun_l28_n81
+end
+
+def fun_l27_n326()
+ fun_l28_n765
+end
+
+def fun_l27_n327()
+ fun_l28_n506
+end
+
+def fun_l27_n328()
+ fun_l28_n327
+end
+
+def fun_l27_n329()
+ fun_l28_n362
+end
+
+def fun_l27_n330()
+ fun_l28_n852
+end
+
+def fun_l27_n331()
+ fun_l28_n876
+end
+
+def fun_l27_n332()
+ fun_l28_n531
+end
+
+def fun_l27_n333()
+ fun_l28_n426
+end
+
+def fun_l27_n334()
+ fun_l28_n295
+end
+
+def fun_l27_n335()
+ fun_l28_n929
+end
+
+def fun_l27_n336()
+ fun_l28_n693
+end
+
+def fun_l27_n337()
+ fun_l28_n724
+end
+
+def fun_l27_n338()
+ fun_l28_n784
+end
+
+def fun_l27_n339()
+ fun_l28_n752
+end
+
+def fun_l27_n340()
+ fun_l28_n809
+end
+
+def fun_l27_n341()
+ fun_l28_n269
+end
+
+def fun_l27_n342()
+ fun_l28_n33
+end
+
+def fun_l27_n343()
+ fun_l28_n778
+end
+
+def fun_l27_n344()
+ fun_l28_n974
+end
+
+def fun_l27_n345()
+ fun_l28_n843
+end
+
+def fun_l27_n346()
+ fun_l28_n86
+end
+
+def fun_l27_n347()
+ fun_l28_n594
+end
+
+def fun_l27_n348()
+ fun_l28_n111
+end
+
+def fun_l27_n349()
+ fun_l28_n317
+end
+
+def fun_l27_n350()
+ fun_l28_n238
+end
+
+def fun_l27_n351()
+ fun_l28_n447
+end
+
+def fun_l27_n352()
+ fun_l28_n954
+end
+
+def fun_l27_n353()
+ fun_l28_n846
+end
+
+def fun_l27_n354()
+ fun_l28_n124
+end
+
+def fun_l27_n355()
+ fun_l28_n445
+end
+
+def fun_l27_n356()
+ fun_l28_n957
+end
+
+def fun_l27_n357()
+ fun_l28_n365
+end
+
+def fun_l27_n358()
+ fun_l28_n136
+end
+
+def fun_l27_n359()
+ fun_l28_n372
+end
+
+def fun_l27_n360()
+ fun_l28_n487
+end
+
+def fun_l27_n361()
+ fun_l28_n493
+end
+
+def fun_l27_n362()
+ fun_l28_n905
+end
+
+def fun_l27_n363()
+ fun_l28_n146
+end
+
+def fun_l27_n364()
+ fun_l28_n523
+end
+
+def fun_l27_n365()
+ fun_l28_n876
+end
+
+def fun_l27_n366()
+ fun_l28_n67
+end
+
+def fun_l27_n367()
+ fun_l28_n746
+end
+
+def fun_l27_n368()
+ fun_l28_n264
+end
+
+def fun_l27_n369()
+ fun_l28_n470
+end
+
+def fun_l27_n370()
+ fun_l28_n240
+end
+
+def fun_l27_n371()
+ fun_l28_n928
+end
+
+def fun_l27_n372()
+ fun_l28_n574
+end
+
+def fun_l27_n373()
+ fun_l28_n756
+end
+
+def fun_l27_n374()
+ fun_l28_n244
+end
+
+def fun_l27_n375()
+ fun_l28_n46
+end
+
+def fun_l27_n376()
+ fun_l28_n940
+end
+
+def fun_l27_n377()
+ fun_l28_n430
+end
+
+def fun_l27_n378()
+ fun_l28_n879
+end
+
+def fun_l27_n379()
+ fun_l28_n560
+end
+
+def fun_l27_n380()
+ fun_l28_n231
+end
+
+def fun_l27_n381()
+ fun_l28_n283
+end
+
+def fun_l27_n382()
+ fun_l28_n438
+end
+
+def fun_l27_n383()
+ fun_l28_n207
+end
+
+def fun_l27_n384()
+ fun_l28_n185
+end
+
+def fun_l27_n385()
+ fun_l28_n40
+end
+
+def fun_l27_n386()
+ fun_l28_n572
+end
+
+def fun_l27_n387()
+ fun_l28_n975
+end
+
+def fun_l27_n388()
+ fun_l28_n117
+end
+
+def fun_l27_n389()
+ fun_l28_n329
+end
+
+def fun_l27_n390()
+ fun_l28_n311
+end
+
+def fun_l27_n391()
+ fun_l28_n653
+end
+
+def fun_l27_n392()
+ fun_l28_n522
+end
+
+def fun_l27_n393()
+ fun_l28_n452
+end
+
+def fun_l27_n394()
+ fun_l28_n137
+end
+
+def fun_l27_n395()
+ fun_l28_n606
+end
+
+def fun_l27_n396()
+ fun_l28_n901
+end
+
+def fun_l27_n397()
+ fun_l28_n434
+end
+
+def fun_l27_n398()
+ fun_l28_n863
+end
+
+def fun_l27_n399()
+ fun_l28_n117
+end
+
+def fun_l27_n400()
+ fun_l28_n473
+end
+
+def fun_l27_n401()
+ fun_l28_n638
+end
+
+def fun_l27_n402()
+ fun_l28_n71
+end
+
+def fun_l27_n403()
+ fun_l28_n423
+end
+
+def fun_l27_n404()
+ fun_l28_n362
+end
+
+def fun_l27_n405()
+ fun_l28_n537
+end
+
+def fun_l27_n406()
+ fun_l28_n975
+end
+
+def fun_l27_n407()
+ fun_l28_n424
+end
+
+def fun_l27_n408()
+ fun_l28_n613
+end
+
+def fun_l27_n409()
+ fun_l28_n606
+end
+
+def fun_l27_n410()
+ fun_l28_n782
+end
+
+def fun_l27_n411()
+ fun_l28_n445
+end
+
+def fun_l27_n412()
+ fun_l28_n362
+end
+
+def fun_l27_n413()
+ fun_l28_n837
+end
+
+def fun_l27_n414()
+ fun_l28_n335
+end
+
+def fun_l27_n415()
+ fun_l28_n258
+end
+
+def fun_l27_n416()
+ fun_l28_n832
+end
+
+def fun_l27_n417()
+ fun_l28_n102
+end
+
+def fun_l27_n418()
+ fun_l28_n202
+end
+
+def fun_l27_n419()
+ fun_l28_n624
+end
+
+def fun_l27_n420()
+ fun_l28_n118
+end
+
+def fun_l27_n421()
+ fun_l28_n247
+end
+
+def fun_l27_n422()
+ fun_l28_n768
+end
+
+def fun_l27_n423()
+ fun_l28_n879
+end
+
+def fun_l27_n424()
+ fun_l28_n650
+end
+
+def fun_l27_n425()
+ fun_l28_n545
+end
+
+def fun_l27_n426()
+ fun_l28_n854
+end
+
+def fun_l27_n427()
+ fun_l28_n722
+end
+
+def fun_l27_n428()
+ fun_l28_n637
+end
+
+def fun_l27_n429()
+ fun_l28_n295
+end
+
+def fun_l27_n430()
+ fun_l28_n504
+end
+
+def fun_l27_n431()
+ fun_l28_n939
+end
+
+def fun_l27_n432()
+ fun_l28_n52
+end
+
+def fun_l27_n433()
+ fun_l28_n613
+end
+
+def fun_l27_n434()
+ fun_l28_n165
+end
+
+def fun_l27_n435()
+ fun_l28_n948
+end
+
+def fun_l27_n436()
+ fun_l28_n995
+end
+
+def fun_l27_n437()
+ fun_l28_n572
+end
+
+def fun_l27_n438()
+ fun_l28_n919
+end
+
+def fun_l27_n439()
+ fun_l28_n843
+end
+
+def fun_l27_n440()
+ fun_l28_n826
+end
+
+def fun_l27_n441()
+ fun_l28_n328
+end
+
+def fun_l27_n442()
+ fun_l28_n330
+end
+
+def fun_l27_n443()
+ fun_l28_n819
+end
+
+def fun_l27_n444()
+ fun_l28_n949
+end
+
+def fun_l27_n445()
+ fun_l28_n505
+end
+
+def fun_l27_n446()
+ fun_l28_n306
+end
+
+def fun_l27_n447()
+ fun_l28_n731
+end
+
+def fun_l27_n448()
+ fun_l28_n232
+end
+
+def fun_l27_n449()
+ fun_l28_n251
+end
+
+def fun_l27_n450()
+ fun_l28_n807
+end
+
+def fun_l27_n451()
+ fun_l28_n808
+end
+
+def fun_l27_n452()
+ fun_l28_n672
+end
+
+def fun_l27_n453()
+ fun_l28_n0
+end
+
+def fun_l27_n454()
+ fun_l28_n659
+end
+
+def fun_l27_n455()
+ fun_l28_n955
+end
+
+def fun_l27_n456()
+ fun_l28_n314
+end
+
+def fun_l27_n457()
+ fun_l28_n539
+end
+
+def fun_l27_n458()
+ fun_l28_n394
+end
+
+def fun_l27_n459()
+ fun_l28_n48
+end
+
+def fun_l27_n460()
+ fun_l28_n434
+end
+
+def fun_l27_n461()
+ fun_l28_n54
+end
+
+def fun_l27_n462()
+ fun_l28_n108
+end
+
+def fun_l27_n463()
+ fun_l28_n80
+end
+
+def fun_l27_n464()
+ fun_l28_n255
+end
+
+def fun_l27_n465()
+ fun_l28_n273
+end
+
+def fun_l27_n466()
+ fun_l28_n227
+end
+
+def fun_l27_n467()
+ fun_l28_n764
+end
+
+def fun_l27_n468()
+ fun_l28_n210
+end
+
+def fun_l27_n469()
+ fun_l28_n68
+end
+
+def fun_l27_n470()
+ fun_l28_n178
+end
+
+def fun_l27_n471()
+ fun_l28_n500
+end
+
+def fun_l27_n472()
+ fun_l28_n374
+end
+
+def fun_l27_n473()
+ fun_l28_n98
+end
+
+def fun_l27_n474()
+ fun_l28_n232
+end
+
+def fun_l27_n475()
+ fun_l28_n35
+end
+
+def fun_l27_n476()
+ fun_l28_n483
+end
+
+def fun_l27_n477()
+ fun_l28_n282
+end
+
+def fun_l27_n478()
+ fun_l28_n512
+end
+
+def fun_l27_n479()
+ fun_l28_n755
+end
+
+def fun_l27_n480()
+ fun_l28_n299
+end
+
+def fun_l27_n481()
+ fun_l28_n899
+end
+
+def fun_l27_n482()
+ fun_l28_n872
+end
+
+def fun_l27_n483()
+ fun_l28_n558
+end
+
+def fun_l27_n484()
+ fun_l28_n700
+end
+
+def fun_l27_n485()
+ fun_l28_n949
+end
+
+def fun_l27_n486()
+ fun_l28_n272
+end
+
+def fun_l27_n487()
+ fun_l28_n808
+end
+
+def fun_l27_n488()
+ fun_l28_n36
+end
+
+def fun_l27_n489()
+ fun_l28_n698
+end
+
+def fun_l27_n490()
+ fun_l28_n386
+end
+
+def fun_l27_n491()
+ fun_l28_n745
+end
+
+def fun_l27_n492()
+ fun_l28_n26
+end
+
+def fun_l27_n493()
+ fun_l28_n148
+end
+
+def fun_l27_n494()
+ fun_l28_n300
+end
+
+def fun_l27_n495()
+ fun_l28_n292
+end
+
+def fun_l27_n496()
+ fun_l28_n892
+end
+
+def fun_l27_n497()
+ fun_l28_n824
+end
+
+def fun_l27_n498()
+ fun_l28_n89
+end
+
+def fun_l27_n499()
+ fun_l28_n248
+end
+
+def fun_l27_n500()
+ fun_l28_n19
+end
+
+def fun_l27_n501()
+ fun_l28_n600
+end
+
+def fun_l27_n502()
+ fun_l28_n210
+end
+
+def fun_l27_n503()
+ fun_l28_n27
+end
+
+def fun_l27_n504()
+ fun_l28_n866
+end
+
+def fun_l27_n505()
+ fun_l28_n231
+end
+
+def fun_l27_n506()
+ fun_l28_n622
+end
+
+def fun_l27_n507()
+ fun_l28_n381
+end
+
+def fun_l27_n508()
+ fun_l28_n997
+end
+
+def fun_l27_n509()
+ fun_l28_n799
+end
+
+def fun_l27_n510()
+ fun_l28_n18
+end
+
+def fun_l27_n511()
+ fun_l28_n60
+end
+
+def fun_l27_n512()
+ fun_l28_n287
+end
+
+def fun_l27_n513()
+ fun_l28_n478
+end
+
+def fun_l27_n514()
+ fun_l28_n562
+end
+
+def fun_l27_n515()
+ fun_l28_n779
+end
+
+def fun_l27_n516()
+ fun_l28_n585
+end
+
+def fun_l27_n517()
+ fun_l28_n464
+end
+
+def fun_l27_n518()
+ fun_l28_n304
+end
+
+def fun_l27_n519()
+ fun_l28_n189
+end
+
+def fun_l27_n520()
+ fun_l28_n959
+end
+
+def fun_l27_n521()
+ fun_l28_n5
+end
+
+def fun_l27_n522()
+ fun_l28_n866
+end
+
+def fun_l27_n523()
+ fun_l28_n14
+end
+
+def fun_l27_n524()
+ fun_l28_n644
+end
+
+def fun_l27_n525()
+ fun_l28_n725
+end
+
+def fun_l27_n526()
+ fun_l28_n18
+end
+
+def fun_l27_n527()
+ fun_l28_n9
+end
+
+def fun_l27_n528()
+ fun_l28_n0
+end
+
+def fun_l27_n529()
+ fun_l28_n154
+end
+
+def fun_l27_n530()
+ fun_l28_n313
+end
+
+def fun_l27_n531()
+ fun_l28_n478
+end
+
+def fun_l27_n532()
+ fun_l28_n139
+end
+
+def fun_l27_n533()
+ fun_l28_n913
+end
+
+def fun_l27_n534()
+ fun_l28_n113
+end
+
+def fun_l27_n535()
+ fun_l28_n685
+end
+
+def fun_l27_n536()
+ fun_l28_n275
+end
+
+def fun_l27_n537()
+ fun_l28_n556
+end
+
+def fun_l27_n538()
+ fun_l28_n276
+end
+
+def fun_l27_n539()
+ fun_l28_n283
+end
+
+def fun_l27_n540()
+ fun_l28_n694
+end
+
+def fun_l27_n541()
+ fun_l28_n396
+end
+
+def fun_l27_n542()
+ fun_l28_n181
+end
+
+def fun_l27_n543()
+ fun_l28_n231
+end
+
+def fun_l27_n544()
+ fun_l28_n228
+end
+
+def fun_l27_n545()
+ fun_l28_n958
+end
+
+def fun_l27_n546()
+ fun_l28_n91
+end
+
+def fun_l27_n547()
+ fun_l28_n878
+end
+
+def fun_l27_n548()
+ fun_l28_n180
+end
+
+def fun_l27_n549()
+ fun_l28_n13
+end
+
+def fun_l27_n550()
+ fun_l28_n161
+end
+
+def fun_l27_n551()
+ fun_l28_n603
+end
+
+def fun_l27_n552()
+ fun_l28_n101
+end
+
+def fun_l27_n553()
+ fun_l28_n825
+end
+
+def fun_l27_n554()
+ fun_l28_n370
+end
+
+def fun_l27_n555()
+ fun_l28_n983
+end
+
+def fun_l27_n556()
+ fun_l28_n888
+end
+
+def fun_l27_n557()
+ fun_l28_n610
+end
+
+def fun_l27_n558()
+ fun_l28_n630
+end
+
+def fun_l27_n559()
+ fun_l28_n345
+end
+
+def fun_l27_n560()
+ fun_l28_n376
+end
+
+def fun_l27_n561()
+ fun_l28_n409
+end
+
+def fun_l27_n562()
+ fun_l28_n717
+end
+
+def fun_l27_n563()
+ fun_l28_n66
+end
+
+def fun_l27_n564()
+ fun_l28_n228
+end
+
+def fun_l27_n565()
+ fun_l28_n485
+end
+
+def fun_l27_n566()
+ fun_l28_n252
+end
+
+def fun_l27_n567()
+ fun_l28_n444
+end
+
+def fun_l27_n568()
+ fun_l28_n253
+end
+
+def fun_l27_n569()
+ fun_l28_n839
+end
+
+def fun_l27_n570()
+ fun_l28_n216
+end
+
+def fun_l27_n571()
+ fun_l28_n797
+end
+
+def fun_l27_n572()
+ fun_l28_n127
+end
+
+def fun_l27_n573()
+ fun_l28_n335
+end
+
+def fun_l27_n574()
+ fun_l28_n141
+end
+
+def fun_l27_n575()
+ fun_l28_n536
+end
+
+def fun_l27_n576()
+ fun_l28_n463
+end
+
+def fun_l27_n577()
+ fun_l28_n925
+end
+
+def fun_l27_n578()
+ fun_l28_n707
+end
+
+def fun_l27_n579()
+ fun_l28_n530
+end
+
+def fun_l27_n580()
+ fun_l28_n678
+end
+
+def fun_l27_n581()
+ fun_l28_n234
+end
+
+def fun_l27_n582()
+ fun_l28_n803
+end
+
+def fun_l27_n583()
+ fun_l28_n530
+end
+
+def fun_l27_n584()
+ fun_l28_n131
+end
+
+def fun_l27_n585()
+ fun_l28_n512
+end
+
+def fun_l27_n586()
+ fun_l28_n550
+end
+
+def fun_l27_n587()
+ fun_l28_n528
+end
+
+def fun_l27_n588()
+ fun_l28_n214
+end
+
+def fun_l27_n589()
+ fun_l28_n801
+end
+
+def fun_l27_n590()
+ fun_l28_n69
+end
+
+def fun_l27_n591()
+ fun_l28_n519
+end
+
+def fun_l27_n592()
+ fun_l28_n909
+end
+
+def fun_l27_n593()
+ fun_l28_n981
+end
+
+def fun_l27_n594()
+ fun_l28_n108
+end
+
+def fun_l27_n595()
+ fun_l28_n762
+end
+
+def fun_l27_n596()
+ fun_l28_n838
+end
+
+def fun_l27_n597()
+ fun_l28_n311
+end
+
+def fun_l27_n598()
+ fun_l28_n428
+end
+
+def fun_l27_n599()
+ fun_l28_n111
+end
+
+def fun_l27_n600()
+ fun_l28_n600
+end
+
+def fun_l27_n601()
+ fun_l28_n996
+end
+
+def fun_l27_n602()
+ fun_l28_n439
+end
+
+def fun_l27_n603()
+ fun_l28_n379
+end
+
+def fun_l27_n604()
+ fun_l28_n959
+end
+
+def fun_l27_n605()
+ fun_l28_n287
+end
+
+def fun_l27_n606()
+ fun_l28_n893
+end
+
+def fun_l27_n607()
+ fun_l28_n384
+end
+
+def fun_l27_n608()
+ fun_l28_n815
+end
+
+def fun_l27_n609()
+ fun_l28_n733
+end
+
+def fun_l27_n610()
+ fun_l28_n875
+end
+
+def fun_l27_n611()
+ fun_l28_n343
+end
+
+def fun_l27_n612()
+ fun_l28_n605
+end
+
+def fun_l27_n613()
+ fun_l28_n968
+end
+
+def fun_l27_n614()
+ fun_l28_n703
+end
+
+def fun_l27_n615()
+ fun_l28_n50
+end
+
+def fun_l27_n616()
+ fun_l28_n807
+end
+
+def fun_l27_n617()
+ fun_l28_n261
+end
+
+def fun_l27_n618()
+ fun_l28_n887
+end
+
+def fun_l27_n619()
+ fun_l28_n165
+end
+
+def fun_l27_n620()
+ fun_l28_n62
+end
+
+def fun_l27_n621()
+ fun_l28_n437
+end
+
+def fun_l27_n622()
+ fun_l28_n267
+end
+
+def fun_l27_n623()
+ fun_l28_n739
+end
+
+def fun_l27_n624()
+ fun_l28_n624
+end
+
+def fun_l27_n625()
+ fun_l28_n845
+end
+
+def fun_l27_n626()
+ fun_l28_n844
+end
+
+def fun_l27_n627()
+ fun_l28_n541
+end
+
+def fun_l27_n628()
+ fun_l28_n175
+end
+
+def fun_l27_n629()
+ fun_l28_n295
+end
+
+def fun_l27_n630()
+ fun_l28_n600
+end
+
+def fun_l27_n631()
+ fun_l28_n250
+end
+
+def fun_l27_n632()
+ fun_l28_n167
+end
+
+def fun_l27_n633()
+ fun_l28_n7
+end
+
+def fun_l27_n634()
+ fun_l28_n75
+end
+
+def fun_l27_n635()
+ fun_l28_n208
+end
+
+def fun_l27_n636()
+ fun_l28_n53
+end
+
+def fun_l27_n637()
+ fun_l28_n132
+end
+
+def fun_l27_n638()
+ fun_l28_n859
+end
+
+def fun_l27_n639()
+ fun_l28_n925
+end
+
+def fun_l27_n640()
+ fun_l28_n34
+end
+
+def fun_l27_n641()
+ fun_l28_n226
+end
+
+def fun_l27_n642()
+ fun_l28_n916
+end
+
+def fun_l27_n643()
+ fun_l28_n893
+end
+
+def fun_l27_n644()
+ fun_l28_n100
+end
+
+def fun_l27_n645()
+ fun_l28_n526
+end
+
+def fun_l27_n646()
+ fun_l28_n113
+end
+
+def fun_l27_n647()
+ fun_l28_n786
+end
+
+def fun_l27_n648()
+ fun_l28_n995
+end
+
+def fun_l27_n649()
+ fun_l28_n968
+end
+
+def fun_l27_n650()
+ fun_l28_n705
+end
+
+def fun_l27_n651()
+ fun_l28_n581
+end
+
+def fun_l27_n652()
+ fun_l28_n112
+end
+
+def fun_l27_n653()
+ fun_l28_n475
+end
+
+def fun_l27_n654()
+ fun_l28_n264
+end
+
+def fun_l27_n655()
+ fun_l28_n44
+end
+
+def fun_l27_n656()
+ fun_l28_n302
+end
+
+def fun_l27_n657()
+ fun_l28_n830
+end
+
+def fun_l27_n658()
+ fun_l28_n551
+end
+
+def fun_l27_n659()
+ fun_l28_n811
+end
+
+def fun_l27_n660()
+ fun_l28_n476
+end
+
+def fun_l27_n661()
+ fun_l28_n547
+end
+
+def fun_l27_n662()
+ fun_l28_n709
+end
+
+def fun_l27_n663()
+ fun_l28_n435
+end
+
+def fun_l27_n664()
+ fun_l28_n727
+end
+
+def fun_l27_n665()
+ fun_l28_n630
+end
+
+def fun_l27_n666()
+ fun_l28_n514
+end
+
+def fun_l27_n667()
+ fun_l28_n939
+end
+
+def fun_l27_n668()
+ fun_l28_n198
+end
+
+def fun_l27_n669()
+ fun_l28_n165
+end
+
+def fun_l27_n670()
+ fun_l28_n415
+end
+
+def fun_l27_n671()
+ fun_l28_n316
+end
+
+def fun_l27_n672()
+ fun_l28_n602
+end
+
+def fun_l27_n673()
+ fun_l28_n776
+end
+
+def fun_l27_n674()
+ fun_l28_n681
+end
+
+def fun_l27_n675()
+ fun_l28_n131
+end
+
+def fun_l27_n676()
+ fun_l28_n812
+end
+
+def fun_l27_n677()
+ fun_l28_n666
+end
+
+def fun_l27_n678()
+ fun_l28_n209
+end
+
+def fun_l27_n679()
+ fun_l28_n953
+end
+
+def fun_l27_n680()
+ fun_l28_n797
+end
+
+def fun_l27_n681()
+ fun_l28_n317
+end
+
+def fun_l27_n682()
+ fun_l28_n43
+end
+
+def fun_l27_n683()
+ fun_l28_n673
+end
+
+def fun_l27_n684()
+ fun_l28_n701
+end
+
+def fun_l27_n685()
+ fun_l28_n961
+end
+
+def fun_l27_n686()
+ fun_l28_n684
+end
+
+def fun_l27_n687()
+ fun_l28_n677
+end
+
+def fun_l27_n688()
+ fun_l28_n213
+end
+
+def fun_l27_n689()
+ fun_l28_n22
+end
+
+def fun_l27_n690()
+ fun_l28_n296
+end
+
+def fun_l27_n691()
+ fun_l28_n235
+end
+
+def fun_l27_n692()
+ fun_l28_n148
+end
+
+def fun_l27_n693()
+ fun_l28_n756
+end
+
+def fun_l27_n694()
+ fun_l28_n989
+end
+
+def fun_l27_n695()
+ fun_l28_n993
+end
+
+def fun_l27_n696()
+ fun_l28_n646
+end
+
+def fun_l27_n697()
+ fun_l28_n860
+end
+
+def fun_l27_n698()
+ fun_l28_n872
+end
+
+def fun_l27_n699()
+ fun_l28_n122
+end
+
+def fun_l27_n700()
+ fun_l28_n678
+end
+
+def fun_l27_n701()
+ fun_l28_n480
+end
+
+def fun_l27_n702()
+ fun_l28_n888
+end
+
+def fun_l27_n703()
+ fun_l28_n60
+end
+
+def fun_l27_n704()
+ fun_l28_n15
+end
+
+def fun_l27_n705()
+ fun_l28_n529
+end
+
+def fun_l27_n706()
+ fun_l28_n137
+end
+
+def fun_l27_n707()
+ fun_l28_n643
+end
+
+def fun_l27_n708()
+ fun_l28_n432
+end
+
+def fun_l27_n709()
+ fun_l28_n446
+end
+
+def fun_l27_n710()
+ fun_l28_n170
+end
+
+def fun_l27_n711()
+ fun_l28_n507
+end
+
+def fun_l27_n712()
+ fun_l28_n650
+end
+
+def fun_l27_n713()
+ fun_l28_n952
+end
+
+def fun_l27_n714()
+ fun_l28_n629
+end
+
+def fun_l27_n715()
+ fun_l28_n578
+end
+
+def fun_l27_n716()
+ fun_l28_n754
+end
+
+def fun_l27_n717()
+ fun_l28_n431
+end
+
+def fun_l27_n718()
+ fun_l28_n340
+end
+
+def fun_l27_n719()
+ fun_l28_n580
+end
+
+def fun_l27_n720()
+ fun_l28_n976
+end
+
+def fun_l27_n721()
+ fun_l28_n830
+end
+
+def fun_l27_n722()
+ fun_l28_n746
+end
+
+def fun_l27_n723()
+ fun_l28_n139
+end
+
+def fun_l27_n724()
+ fun_l28_n152
+end
+
+def fun_l27_n725()
+ fun_l28_n956
+end
+
+def fun_l27_n726()
+ fun_l28_n152
+end
+
+def fun_l27_n727()
+ fun_l28_n252
+end
+
+def fun_l27_n728()
+ fun_l28_n856
+end
+
+def fun_l27_n729()
+ fun_l28_n862
+end
+
+def fun_l27_n730()
+ fun_l28_n261
+end
+
+def fun_l27_n731()
+ fun_l28_n28
+end
+
+def fun_l27_n732()
+ fun_l28_n873
+end
+
+def fun_l27_n733()
+ fun_l28_n989
+end
+
+def fun_l27_n734()
+ fun_l28_n657
+end
+
+def fun_l27_n735()
+ fun_l28_n259
+end
+
+def fun_l27_n736()
+ fun_l28_n1
+end
+
+def fun_l27_n737()
+ fun_l28_n964
+end
+
+def fun_l27_n738()
+ fun_l28_n215
+end
+
+def fun_l27_n739()
+ fun_l28_n939
+end
+
+def fun_l27_n740()
+ fun_l28_n644
+end
+
+def fun_l27_n741()
+ fun_l28_n335
+end
+
+def fun_l27_n742()
+ fun_l28_n844
+end
+
+def fun_l27_n743()
+ fun_l28_n493
+end
+
+def fun_l27_n744()
+ fun_l28_n25
+end
+
+def fun_l27_n745()
+ fun_l28_n690
+end
+
+def fun_l27_n746()
+ fun_l28_n561
+end
+
+def fun_l27_n747()
+ fun_l28_n682
+end
+
+def fun_l27_n748()
+ fun_l28_n476
+end
+
+def fun_l27_n749()
+ fun_l28_n626
+end
+
+def fun_l27_n750()
+ fun_l28_n607
+end
+
+def fun_l27_n751()
+ fun_l28_n655
+end
+
+def fun_l27_n752()
+ fun_l28_n481
+end
+
+def fun_l27_n753()
+ fun_l28_n634
+end
+
+def fun_l27_n754()
+ fun_l28_n971
+end
+
+def fun_l27_n755()
+ fun_l28_n372
+end
+
+def fun_l27_n756()
+ fun_l28_n701
+end
+
+def fun_l27_n757()
+ fun_l28_n383
+end
+
+def fun_l27_n758()
+ fun_l28_n295
+end
+
+def fun_l27_n759()
+ fun_l28_n58
+end
+
+def fun_l27_n760()
+ fun_l28_n870
+end
+
+def fun_l27_n761()
+ fun_l28_n902
+end
+
+def fun_l27_n762()
+ fun_l28_n352
+end
+
+def fun_l27_n763()
+ fun_l28_n421
+end
+
+def fun_l27_n764()
+ fun_l28_n870
+end
+
+def fun_l27_n765()
+ fun_l28_n604
+end
+
+def fun_l27_n766()
+ fun_l28_n615
+end
+
+def fun_l27_n767()
+ fun_l28_n644
+end
+
+def fun_l27_n768()
+ fun_l28_n304
+end
+
+def fun_l27_n769()
+ fun_l28_n87
+end
+
+def fun_l27_n770()
+ fun_l28_n40
+end
+
+def fun_l27_n771()
+ fun_l28_n80
+end
+
+def fun_l27_n772()
+ fun_l28_n62
+end
+
+def fun_l27_n773()
+ fun_l28_n912
+end
+
+def fun_l27_n774()
+ fun_l28_n808
+end
+
+def fun_l27_n775()
+ fun_l28_n978
+end
+
+def fun_l27_n776()
+ fun_l28_n499
+end
+
+def fun_l27_n777()
+ fun_l28_n299
+end
+
+def fun_l27_n778()
+ fun_l28_n852
+end
+
+def fun_l27_n779()
+ fun_l28_n126
+end
+
+def fun_l27_n780()
+ fun_l28_n578
+end
+
+def fun_l27_n781()
+ fun_l28_n177
+end
+
+def fun_l27_n782()
+ fun_l28_n621
+end
+
+def fun_l27_n783()
+ fun_l28_n833
+end
+
+def fun_l27_n784()
+ fun_l28_n991
+end
+
+def fun_l27_n785()
+ fun_l28_n419
+end
+
+def fun_l27_n786()
+ fun_l28_n723
+end
+
+def fun_l27_n787()
+ fun_l28_n915
+end
+
+def fun_l27_n788()
+ fun_l28_n73
+end
+
+def fun_l27_n789()
+ fun_l28_n725
+end
+
+def fun_l27_n790()
+ fun_l28_n883
+end
+
+def fun_l27_n791()
+ fun_l28_n469
+end
+
+def fun_l27_n792()
+ fun_l28_n524
+end
+
+def fun_l27_n793()
+ fun_l28_n813
+end
+
+def fun_l27_n794()
+ fun_l28_n8
+end
+
+def fun_l27_n795()
+ fun_l28_n776
+end
+
+def fun_l27_n796()
+ fun_l28_n328
+end
+
+def fun_l27_n797()
+ fun_l28_n324
+end
+
+def fun_l27_n798()
+ fun_l28_n428
+end
+
+def fun_l27_n799()
+ fun_l28_n806
+end
+
+def fun_l27_n800()
+ fun_l28_n397
+end
+
+def fun_l27_n801()
+ fun_l28_n680
+end
+
+def fun_l27_n802()
+ fun_l28_n18
+end
+
+def fun_l27_n803()
+ fun_l28_n955
+end
+
+def fun_l27_n804()
+ fun_l28_n566
+end
+
+def fun_l27_n805()
+ fun_l28_n824
+end
+
+def fun_l27_n806()
+ fun_l28_n860
+end
+
+def fun_l27_n807()
+ fun_l28_n411
+end
+
+def fun_l27_n808()
+ fun_l28_n925
+end
+
+def fun_l27_n809()
+ fun_l28_n394
+end
+
+def fun_l27_n810()
+ fun_l28_n70
+end
+
+def fun_l27_n811()
+ fun_l28_n672
+end
+
+def fun_l27_n812()
+ fun_l28_n53
+end
+
+def fun_l27_n813()
+ fun_l28_n574
+end
+
+def fun_l27_n814()
+ fun_l28_n407
+end
+
+def fun_l27_n815()
+ fun_l28_n86
+end
+
+def fun_l27_n816()
+ fun_l28_n611
+end
+
+def fun_l27_n817()
+ fun_l28_n950
+end
+
+def fun_l27_n818()
+ fun_l28_n595
+end
+
+def fun_l27_n819()
+ fun_l28_n411
+end
+
+def fun_l27_n820()
+ fun_l28_n286
+end
+
+def fun_l27_n821()
+ fun_l28_n683
+end
+
+def fun_l27_n822()
+ fun_l28_n706
+end
+
+def fun_l27_n823()
+ fun_l28_n587
+end
+
+def fun_l27_n824()
+ fun_l28_n908
+end
+
+def fun_l27_n825()
+ fun_l28_n641
+end
+
+def fun_l27_n826()
+ fun_l28_n792
+end
+
+def fun_l27_n827()
+ fun_l28_n714
+end
+
+def fun_l27_n828()
+ fun_l28_n594
+end
+
+def fun_l27_n829()
+ fun_l28_n154
+end
+
+def fun_l27_n830()
+ fun_l28_n102
+end
+
+def fun_l27_n831()
+ fun_l28_n819
+end
+
+def fun_l27_n832()
+ fun_l28_n285
+end
+
+def fun_l27_n833()
+ fun_l28_n665
+end
+
+def fun_l27_n834()
+ fun_l28_n896
+end
+
+def fun_l27_n835()
+ fun_l28_n495
+end
+
+def fun_l27_n836()
+ fun_l28_n284
+end
+
+def fun_l27_n837()
+ fun_l28_n747
+end
+
+def fun_l27_n838()
+ fun_l28_n388
+end
+
+def fun_l27_n839()
+ fun_l28_n274
+end
+
+def fun_l27_n840()
+ fun_l28_n236
+end
+
+def fun_l27_n841()
+ fun_l28_n336
+end
+
+def fun_l27_n842()
+ fun_l28_n805
+end
+
+def fun_l27_n843()
+ fun_l28_n196
+end
+
+def fun_l27_n844()
+ fun_l28_n772
+end
+
+def fun_l27_n845()
+ fun_l28_n679
+end
+
+def fun_l27_n846()
+ fun_l28_n703
+end
+
+def fun_l27_n847()
+ fun_l28_n743
+end
+
+def fun_l27_n848()
+ fun_l28_n941
+end
+
+def fun_l27_n849()
+ fun_l28_n903
+end
+
+def fun_l27_n850()
+ fun_l28_n149
+end
+
+def fun_l27_n851()
+ fun_l28_n924
+end
+
+def fun_l27_n852()
+ fun_l28_n638
+end
+
+def fun_l27_n853()
+ fun_l28_n480
+end
+
+def fun_l27_n854()
+ fun_l28_n580
+end
+
+def fun_l27_n855()
+ fun_l28_n184
+end
+
+def fun_l27_n856()
+ fun_l28_n757
+end
+
+def fun_l27_n857()
+ fun_l28_n233
+end
+
+def fun_l27_n858()
+ fun_l28_n315
+end
+
+def fun_l27_n859()
+ fun_l28_n182
+end
+
+def fun_l27_n860()
+ fun_l28_n696
+end
+
+def fun_l27_n861()
+ fun_l28_n155
+end
+
+def fun_l27_n862()
+ fun_l28_n648
+end
+
+def fun_l27_n863()
+ fun_l28_n148
+end
+
+def fun_l27_n864()
+ fun_l28_n40
+end
+
+def fun_l27_n865()
+ fun_l28_n665
+end
+
+def fun_l27_n866()
+ fun_l28_n646
+end
+
+def fun_l27_n867()
+ fun_l28_n158
+end
+
+def fun_l27_n868()
+ fun_l28_n159
+end
+
+def fun_l27_n869()
+ fun_l28_n617
+end
+
+def fun_l27_n870()
+ fun_l28_n637
+end
+
+def fun_l27_n871()
+ fun_l28_n234
+end
+
+def fun_l27_n872()
+ fun_l28_n591
+end
+
+def fun_l27_n873()
+ fun_l28_n207
+end
+
+def fun_l27_n874()
+ fun_l28_n136
+end
+
+def fun_l27_n875()
+ fun_l28_n565
+end
+
+def fun_l27_n876()
+ fun_l28_n152
+end
+
+def fun_l27_n877()
+ fun_l28_n309
+end
+
+def fun_l27_n878()
+ fun_l28_n275
+end
+
+def fun_l27_n879()
+ fun_l28_n355
+end
+
+def fun_l27_n880()
+ fun_l28_n441
+end
+
+def fun_l27_n881()
+ fun_l28_n427
+end
+
+def fun_l27_n882()
+ fun_l28_n249
+end
+
+def fun_l27_n883()
+ fun_l28_n764
+end
+
+def fun_l27_n884()
+ fun_l28_n183
+end
+
+def fun_l27_n885()
+ fun_l28_n302
+end
+
+def fun_l27_n886()
+ fun_l28_n857
+end
+
+def fun_l27_n887()
+ fun_l28_n73
+end
+
+def fun_l27_n888()
+ fun_l28_n702
+end
+
+def fun_l27_n889()
+ fun_l28_n430
+end
+
+def fun_l27_n890()
+ fun_l28_n57
+end
+
+def fun_l27_n891()
+ fun_l28_n994
+end
+
+def fun_l27_n892()
+ fun_l28_n951
+end
+
+def fun_l27_n893()
+ fun_l28_n268
+end
+
+def fun_l27_n894()
+ fun_l28_n629
+end
+
+def fun_l27_n895()
+ fun_l28_n505
+end
+
+def fun_l27_n896()
+ fun_l28_n790
+end
+
+def fun_l27_n897()
+ fun_l28_n213
+end
+
+def fun_l27_n898()
+ fun_l28_n133
+end
+
+def fun_l27_n899()
+ fun_l28_n472
+end
+
+def fun_l27_n900()
+ fun_l28_n212
+end
+
+def fun_l27_n901()
+ fun_l28_n386
+end
+
+def fun_l27_n902()
+ fun_l28_n405
+end
+
+def fun_l27_n903()
+ fun_l28_n807
+end
+
+def fun_l27_n904()
+ fun_l28_n76
+end
+
+def fun_l27_n905()
+ fun_l28_n295
+end
+
+def fun_l27_n906()
+ fun_l28_n860
+end
+
+def fun_l27_n907()
+ fun_l28_n185
+end
+
+def fun_l27_n908()
+ fun_l28_n762
+end
+
+def fun_l27_n909()
+ fun_l28_n493
+end
+
+def fun_l27_n910()
+ fun_l28_n309
+end
+
+def fun_l27_n911()
+ fun_l28_n920
+end
+
+def fun_l27_n912()
+ fun_l28_n284
+end
+
+def fun_l27_n913()
+ fun_l28_n355
+end
+
+def fun_l27_n914()
+ fun_l28_n177
+end
+
+def fun_l27_n915()
+ fun_l28_n901
+end
+
+def fun_l27_n916()
+ fun_l28_n858
+end
+
+def fun_l27_n917()
+ fun_l28_n337
+end
+
+def fun_l27_n918()
+ fun_l28_n872
+end
+
+def fun_l27_n919()
+ fun_l28_n550
+end
+
+def fun_l27_n920()
+ fun_l28_n458
+end
+
+def fun_l27_n921()
+ fun_l28_n739
+end
+
+def fun_l27_n922()
+ fun_l28_n394
+end
+
+def fun_l27_n923()
+ fun_l28_n695
+end
+
+def fun_l27_n924()
+ fun_l28_n455
+end
+
+def fun_l27_n925()
+ fun_l28_n958
+end
+
+def fun_l27_n926()
+ fun_l28_n395
+end
+
+def fun_l27_n927()
+ fun_l28_n645
+end
+
+def fun_l27_n928()
+ fun_l28_n668
+end
+
+def fun_l27_n929()
+ fun_l28_n880
+end
+
+def fun_l27_n930()
+ fun_l28_n743
+end
+
+def fun_l27_n931()
+ fun_l28_n411
+end
+
+def fun_l27_n932()
+ fun_l28_n457
+end
+
+def fun_l27_n933()
+ fun_l28_n852
+end
+
+def fun_l27_n934()
+ fun_l28_n3
+end
+
+def fun_l27_n935()
+ fun_l28_n637
+end
+
+def fun_l27_n936()
+ fun_l28_n35
+end
+
+def fun_l27_n937()
+ fun_l28_n671
+end
+
+def fun_l27_n938()
+ fun_l28_n996
+end
+
+def fun_l27_n939()
+ fun_l28_n545
+end
+
+def fun_l27_n940()
+ fun_l28_n714
+end
+
+def fun_l27_n941()
+ fun_l28_n527
+end
+
+def fun_l27_n942()
+ fun_l28_n272
+end
+
+def fun_l27_n943()
+ fun_l28_n62
+end
+
+def fun_l27_n944()
+ fun_l28_n206
+end
+
+def fun_l27_n945()
+ fun_l28_n115
+end
+
+def fun_l27_n946()
+ fun_l28_n654
+end
+
+def fun_l27_n947()
+ fun_l28_n218
+end
+
+def fun_l27_n948()
+ fun_l28_n315
+end
+
+def fun_l27_n949()
+ fun_l28_n656
+end
+
+def fun_l27_n950()
+ fun_l28_n901
+end
+
+def fun_l27_n951()
+ fun_l28_n60
+end
+
+def fun_l27_n952()
+ fun_l28_n886
+end
+
+def fun_l27_n953()
+ fun_l28_n888
+end
+
+def fun_l27_n954()
+ fun_l28_n640
+end
+
+def fun_l27_n955()
+ fun_l28_n766
+end
+
+def fun_l27_n956()
+ fun_l28_n506
+end
+
+def fun_l27_n957()
+ fun_l28_n757
+end
+
+def fun_l27_n958()
+ fun_l28_n204
+end
+
+def fun_l27_n959()
+ fun_l28_n531
+end
+
+def fun_l27_n960()
+ fun_l28_n982
+end
+
+def fun_l27_n961()
+ fun_l28_n762
+end
+
+def fun_l27_n962()
+ fun_l28_n701
+end
+
+def fun_l27_n963()
+ fun_l28_n866
+end
+
+def fun_l27_n964()
+ fun_l28_n488
+end
+
+def fun_l27_n965()
+ fun_l28_n793
+end
+
+def fun_l27_n966()
+ fun_l28_n969
+end
+
+def fun_l27_n967()
+ fun_l28_n35
+end
+
+def fun_l27_n968()
+ fun_l28_n54
+end
+
+def fun_l27_n969()
+ fun_l28_n746
+end
+
+def fun_l27_n970()
+ fun_l28_n437
+end
+
+def fun_l27_n971()
+ fun_l28_n601
+end
+
+def fun_l27_n972()
+ fun_l28_n477
+end
+
+def fun_l27_n973()
+ fun_l28_n854
+end
+
+def fun_l27_n974()
+ fun_l28_n76
+end
+
+def fun_l27_n975()
+ fun_l28_n145
+end
+
+def fun_l27_n976()
+ fun_l28_n156
+end
+
+def fun_l27_n977()
+ fun_l28_n719
+end
+
+def fun_l27_n978()
+ fun_l28_n389
+end
+
+def fun_l27_n979()
+ fun_l28_n482
+end
+
+def fun_l27_n980()
+ fun_l28_n369
+end
+
+def fun_l27_n981()
+ fun_l28_n42
+end
+
+def fun_l27_n982()
+ fun_l28_n975
+end
+
+def fun_l27_n983()
+ fun_l28_n995
+end
+
+def fun_l27_n984()
+ fun_l28_n880
+end
+
+def fun_l27_n985()
+ fun_l28_n688
+end
+
+def fun_l27_n986()
+ fun_l28_n796
+end
+
+def fun_l27_n987()
+ fun_l28_n291
+end
+
+def fun_l27_n988()
+ fun_l28_n158
+end
+
+def fun_l27_n989()
+ fun_l28_n389
+end
+
+def fun_l27_n990()
+ fun_l28_n582
+end
+
+def fun_l27_n991()
+ fun_l28_n108
+end
+
+def fun_l27_n992()
+ fun_l28_n280
+end
+
+def fun_l27_n993()
+ fun_l28_n842
+end
+
+def fun_l27_n994()
+ fun_l28_n637
+end
+
+def fun_l27_n995()
+ fun_l28_n934
+end
+
+def fun_l27_n996()
+ fun_l28_n451
+end
+
+def fun_l27_n997()
+ fun_l28_n22
+end
+
+def fun_l27_n998()
+ fun_l28_n733
+end
+
+def fun_l27_n999()
+ fun_l28_n984
+end
+
+def fun_l28_n0()
+ fun_l29_n189
+end
+
+def fun_l28_n1()
+ fun_l29_n12
+end
+
+def fun_l28_n2()
+ fun_l29_n850
+end
+
+def fun_l28_n3()
+ fun_l29_n360
+end
+
+def fun_l28_n4()
+ fun_l29_n510
+end
+
+def fun_l28_n5()
+ fun_l29_n541
+end
+
+def fun_l28_n6()
+ fun_l29_n913
+end
+
+def fun_l28_n7()
+ fun_l29_n652
+end
+
+def fun_l28_n8()
+ fun_l29_n378
+end
+
+def fun_l28_n9()
+ fun_l29_n476
+end
+
+def fun_l28_n10()
+ fun_l29_n644
+end
+
+def fun_l28_n11()
+ fun_l29_n484
+end
+
+def fun_l28_n12()
+ fun_l29_n52
+end
+
+def fun_l28_n13()
+ fun_l29_n294
+end
+
+def fun_l28_n14()
+ fun_l29_n387
+end
+
+def fun_l28_n15()
+ fun_l29_n331
+end
+
+def fun_l28_n16()
+ fun_l29_n578
+end
+
+def fun_l28_n17()
+ fun_l29_n783
+end
+
+def fun_l28_n18()
+ fun_l29_n838
+end
+
+def fun_l28_n19()
+ fun_l29_n5
+end
+
+def fun_l28_n20()
+ fun_l29_n909
+end
+
+def fun_l28_n21()
+ fun_l29_n671
+end
+
+def fun_l28_n22()
+ fun_l29_n626
+end
+
+def fun_l28_n23()
+ fun_l29_n685
+end
+
+def fun_l28_n24()
+ fun_l29_n22
+end
+
+def fun_l28_n25()
+ fun_l29_n925
+end
+
+def fun_l28_n26()
+ fun_l29_n816
+end
+
+def fun_l28_n27()
+ fun_l29_n714
+end
+
+def fun_l28_n28()
+ fun_l29_n863
+end
+
+def fun_l28_n29()
+ fun_l29_n475
+end
+
+def fun_l28_n30()
+ fun_l29_n83
+end
+
+def fun_l28_n31()
+ fun_l29_n854
+end
+
+def fun_l28_n32()
+ fun_l29_n616
+end
+
+def fun_l28_n33()
+ fun_l29_n574
+end
+
+def fun_l28_n34()
+ fun_l29_n745
+end
+
+def fun_l28_n35()
+ fun_l29_n921
+end
+
+def fun_l28_n36()
+ fun_l29_n639
+end
+
+def fun_l28_n37()
+ fun_l29_n695
+end
+
+def fun_l28_n38()
+ fun_l29_n527
+end
+
+def fun_l28_n39()
+ fun_l29_n691
+end
+
+def fun_l28_n40()
+ fun_l29_n409
+end
+
+def fun_l28_n41()
+ fun_l29_n788
+end
+
+def fun_l28_n42()
+ fun_l29_n671
+end
+
+def fun_l28_n43()
+ fun_l29_n855
+end
+
+def fun_l28_n44()
+ fun_l29_n364
+end
+
+def fun_l28_n45()
+ fun_l29_n231
+end
+
+def fun_l28_n46()
+ fun_l29_n852
+end
+
+def fun_l28_n47()
+ fun_l29_n596
+end
+
+def fun_l28_n48()
+ fun_l29_n804
+end
+
+def fun_l28_n49()
+ fun_l29_n513
+end
+
+def fun_l28_n50()
+ fun_l29_n498
+end
+
+def fun_l28_n51()
+ fun_l29_n548
+end
+
+def fun_l28_n52()
+ fun_l29_n641
+end
+
+def fun_l28_n53()
+ fun_l29_n784
+end
+
+def fun_l28_n54()
+ fun_l29_n803
+end
+
+def fun_l28_n55()
+ fun_l29_n384
+end
+
+def fun_l28_n56()
+ fun_l29_n304
+end
+
+def fun_l28_n57()
+ fun_l29_n894
+end
+
+def fun_l28_n58()
+ fun_l29_n233
+end
+
+def fun_l28_n59()
+ fun_l29_n344
+end
+
+def fun_l28_n60()
+ fun_l29_n652
+end
+
+def fun_l28_n61()
+ fun_l29_n912
+end
+
+def fun_l28_n62()
+ fun_l29_n266
+end
+
+def fun_l28_n63()
+ fun_l29_n228
+end
+
+def fun_l28_n64()
+ fun_l29_n31
+end
+
+def fun_l28_n65()
+ fun_l29_n679
+end
+
+def fun_l28_n66()
+ fun_l29_n902
+end
+
+def fun_l28_n67()
+ fun_l29_n907
+end
+
+def fun_l28_n68()
+ fun_l29_n830
+end
+
+def fun_l28_n69()
+ fun_l29_n849
+end
+
+def fun_l28_n70()
+ fun_l29_n551
+end
+
+def fun_l28_n71()
+ fun_l29_n586
+end
+
+def fun_l28_n72()
+ fun_l29_n126
+end
+
+def fun_l28_n73()
+ fun_l29_n75
+end
+
+def fun_l28_n74()
+ fun_l29_n706
+end
+
+def fun_l28_n75()
+ fun_l29_n82
+end
+
+def fun_l28_n76()
+ fun_l29_n194
+end
+
+def fun_l28_n77()
+ fun_l29_n761
+end
+
+def fun_l28_n78()
+ fun_l29_n439
+end
+
+def fun_l28_n79()
+ fun_l29_n53
+end
+
+def fun_l28_n80()
+ fun_l29_n889
+end
+
+def fun_l28_n81()
+ fun_l29_n743
+end
+
+def fun_l28_n82()
+ fun_l29_n545
+end
+
+def fun_l28_n83()
+ fun_l29_n88
+end
+
+def fun_l28_n84()
+ fun_l29_n697
+end
+
+def fun_l28_n85()
+ fun_l29_n160
+end
+
+def fun_l28_n86()
+ fun_l29_n895
+end
+
+def fun_l28_n87()
+ fun_l29_n475
+end
+
+def fun_l28_n88()
+ fun_l29_n330
+end
+
+def fun_l28_n89()
+ fun_l29_n464
+end
+
+def fun_l28_n90()
+ fun_l29_n772
+end
+
+def fun_l28_n91()
+ fun_l29_n241
+end
+
+def fun_l28_n92()
+ fun_l29_n838
+end
+
+def fun_l28_n93()
+ fun_l29_n322
+end
+
+def fun_l28_n94()
+ fun_l29_n328
+end
+
+def fun_l28_n95()
+ fun_l29_n475
+end
+
+def fun_l28_n96()
+ fun_l29_n523
+end
+
+def fun_l28_n97()
+ fun_l29_n621
+end
+
+def fun_l28_n98()
+ fun_l29_n646
+end
+
+def fun_l28_n99()
+ fun_l29_n803
+end
+
+def fun_l28_n100()
+ fun_l29_n121
+end
+
+def fun_l28_n101()
+ fun_l29_n432
+end
+
+def fun_l28_n102()
+ fun_l29_n14
+end
+
+def fun_l28_n103()
+ fun_l29_n358
+end
+
+def fun_l28_n104()
+ fun_l29_n257
+end
+
+def fun_l28_n105()
+ fun_l29_n985
+end
+
+def fun_l28_n106()
+ fun_l29_n392
+end
+
+def fun_l28_n107()
+ fun_l29_n11
+end
+
+def fun_l28_n108()
+ fun_l29_n254
+end
+
+def fun_l28_n109()
+ fun_l29_n17
+end
+
+def fun_l28_n110()
+ fun_l29_n146
+end
+
+def fun_l28_n111()
+ fun_l29_n20
+end
+
+def fun_l28_n112()
+ fun_l29_n189
+end
+
+def fun_l28_n113()
+ fun_l29_n838
+end
+
+def fun_l28_n114()
+ fun_l29_n251
+end
+
+def fun_l28_n115()
+ fun_l29_n331
+end
+
+def fun_l28_n116()
+ fun_l29_n816
+end
+
+def fun_l28_n117()
+ fun_l29_n338
+end
+
+def fun_l28_n118()
+ fun_l29_n745
+end
+
+def fun_l28_n119()
+ fun_l29_n301
+end
+
+def fun_l28_n120()
+ fun_l29_n647
+end
+
+def fun_l28_n121()
+ fun_l29_n71
+end
+
+def fun_l28_n122()
+ fun_l29_n371
+end
+
+def fun_l28_n123()
+ fun_l29_n586
+end
+
+def fun_l28_n124()
+ fun_l29_n868
+end
+
+def fun_l28_n125()
+ fun_l29_n519
+end
+
+def fun_l28_n126()
+ fun_l29_n877
+end
+
+def fun_l28_n127()
+ fun_l29_n716
+end
+
+def fun_l28_n128()
+ fun_l29_n184
+end
+
+def fun_l28_n129()
+ fun_l29_n797
+end
+
+def fun_l28_n130()
+ fun_l29_n801
+end
+
+def fun_l28_n131()
+ fun_l29_n278
+end
+
+def fun_l28_n132()
+ fun_l29_n562
+end
+
+def fun_l28_n133()
+ fun_l29_n999
+end
+
+def fun_l28_n134()
+ fun_l29_n128
+end
+
+def fun_l28_n135()
+ fun_l29_n134
+end
+
+def fun_l28_n136()
+ fun_l29_n62
+end
+
+def fun_l28_n137()
+ fun_l29_n923
+end
+
+def fun_l28_n138()
+ fun_l29_n870
+end
+
+def fun_l28_n139()
+ fun_l29_n279
+end
+
+def fun_l28_n140()
+ fun_l29_n971
+end
+
+def fun_l28_n141()
+ fun_l29_n843
+end
+
+def fun_l28_n142()
+ fun_l29_n537
+end
+
+def fun_l28_n143()
+ fun_l29_n584
+end
+
+def fun_l28_n144()
+ fun_l29_n961
+end
+
+def fun_l28_n145()
+ fun_l29_n383
+end
+
+def fun_l28_n146()
+ fun_l29_n44
+end
+
+def fun_l28_n147()
+ fun_l29_n291
+end
+
+def fun_l28_n148()
+ fun_l29_n639
+end
+
+def fun_l28_n149()
+ fun_l29_n751
+end
+
+def fun_l28_n150()
+ fun_l29_n504
+end
+
+def fun_l28_n151()
+ fun_l29_n884
+end
+
+def fun_l28_n152()
+ fun_l29_n505
+end
+
+def fun_l28_n153()
+ fun_l29_n932
+end
+
+def fun_l28_n154()
+ fun_l29_n414
+end
+
+def fun_l28_n155()
+ fun_l29_n121
+end
+
+def fun_l28_n156()
+ fun_l29_n313
+end
+
+def fun_l28_n157()
+ fun_l29_n620
+end
+
+def fun_l28_n158()
+ fun_l29_n412
+end
+
+def fun_l28_n159()
+ fun_l29_n119
+end
+
+def fun_l28_n160()
+ fun_l29_n431
+end
+
+def fun_l28_n161()
+ fun_l29_n943
+end
+
+def fun_l28_n162()
+ fun_l29_n499
+end
+
+def fun_l28_n163()
+ fun_l29_n494
+end
+
+def fun_l28_n164()
+ fun_l29_n716
+end
+
+def fun_l28_n165()
+ fun_l29_n558
+end
+
+def fun_l28_n166()
+ fun_l29_n864
+end
+
+def fun_l28_n167()
+ fun_l29_n13
+end
+
+def fun_l28_n168()
+ fun_l29_n165
+end
+
+def fun_l28_n169()
+ fun_l29_n129
+end
+
+def fun_l28_n170()
+ fun_l29_n478
+end
+
+def fun_l28_n171()
+ fun_l29_n124
+end
+
+def fun_l28_n172()
+ fun_l29_n945
+end
+
+def fun_l28_n173()
+ fun_l29_n574
+end
+
+def fun_l28_n174()
+ fun_l29_n916
+end
+
+def fun_l28_n175()
+ fun_l29_n213
+end
+
+def fun_l28_n176()
+ fun_l29_n68
+end
+
+def fun_l28_n177()
+ fun_l29_n66
+end
+
+def fun_l28_n178()
+ fun_l29_n979
+end
+
+def fun_l28_n179()
+ fun_l29_n909
+end
+
+def fun_l28_n180()
+ fun_l29_n509
+end
+
+def fun_l28_n181()
+ fun_l29_n663
+end
+
+def fun_l28_n182()
+ fun_l29_n407
+end
+
+def fun_l28_n183()
+ fun_l29_n692
+end
+
+def fun_l28_n184()
+ fun_l29_n569
+end
+
+def fun_l28_n185()
+ fun_l29_n950
+end
+
+def fun_l28_n186()
+ fun_l29_n266
+end
+
+def fun_l28_n187()
+ fun_l29_n48
+end
+
+def fun_l28_n188()
+ fun_l29_n244
+end
+
+def fun_l28_n189()
+ fun_l29_n428
+end
+
+def fun_l28_n190()
+ fun_l29_n893
+end
+
+def fun_l28_n191()
+ fun_l29_n581
+end
+
+def fun_l28_n192()
+ fun_l29_n210
+end
+
+def fun_l28_n193()
+ fun_l29_n81
+end
+
+def fun_l28_n194()
+ fun_l29_n295
+end
+
+def fun_l28_n195()
+ fun_l29_n471
+end
+
+def fun_l28_n196()
+ fun_l29_n967
+end
+
+def fun_l28_n197()
+ fun_l29_n318
+end
+
+def fun_l28_n198()
+ fun_l29_n15
+end
+
+def fun_l28_n199()
+ fun_l29_n696
+end
+
+def fun_l28_n200()
+ fun_l29_n702
+end
+
+def fun_l28_n201()
+ fun_l29_n737
+end
+
+def fun_l28_n202()
+ fun_l29_n776
+end
+
+def fun_l28_n203()
+ fun_l29_n623
+end
+
+def fun_l28_n204()
+ fun_l29_n537
+end
+
+def fun_l28_n205()
+ fun_l29_n353
+end
+
+def fun_l28_n206()
+ fun_l29_n156
+end
+
+def fun_l28_n207()
+ fun_l29_n690
+end
+
+def fun_l28_n208()
+ fun_l29_n408
+end
+
+def fun_l28_n209()
+ fun_l29_n388
+end
+
+def fun_l28_n210()
+ fun_l29_n721
+end
+
+def fun_l28_n211()
+ fun_l29_n46
+end
+
+def fun_l28_n212()
+ fun_l29_n238
+end
+
+def fun_l28_n213()
+ fun_l29_n722
+end
+
+def fun_l28_n214()
+ fun_l29_n827
+end
+
+def fun_l28_n215()
+ fun_l29_n496
+end
+
+def fun_l28_n216()
+ fun_l29_n10
+end
+
+def fun_l28_n217()
+ fun_l29_n689
+end
+
+def fun_l28_n218()
+ fun_l29_n962
+end
+
+def fun_l28_n219()
+ fun_l29_n364
+end
+
+def fun_l28_n220()
+ fun_l29_n92
+end
+
+def fun_l28_n221()
+ fun_l29_n246
+end
+
+def fun_l28_n222()
+ fun_l29_n624
+end
+
+def fun_l28_n223()
+ fun_l29_n482
+end
+
+def fun_l28_n224()
+ fun_l29_n992
+end
+
+def fun_l28_n225()
+ fun_l29_n746
+end
+
+def fun_l28_n226()
+ fun_l29_n44
+end
+
+def fun_l28_n227()
+ fun_l29_n389
+end
+
+def fun_l28_n228()
+ fun_l29_n278
+end
+
+def fun_l28_n229()
+ fun_l29_n336
+end
+
+def fun_l28_n230()
+ fun_l29_n415
+end
+
+def fun_l28_n231()
+ fun_l29_n670
+end
+
+def fun_l28_n232()
+ fun_l29_n132
+end
+
+def fun_l28_n233()
+ fun_l29_n669
+end
+
+def fun_l28_n234()
+ fun_l29_n815
+end
+
+def fun_l28_n235()
+ fun_l29_n642
+end
+
+def fun_l28_n236()
+ fun_l29_n59
+end
+
+def fun_l28_n237()
+ fun_l29_n175
+end
+
+def fun_l28_n238()
+ fun_l29_n862
+end
+
+def fun_l28_n239()
+ fun_l29_n570
+end
+
+def fun_l28_n240()
+ fun_l29_n65
+end
+
+def fun_l28_n241()
+ fun_l29_n286
+end
+
+def fun_l28_n242()
+ fun_l29_n467
+end
+
+def fun_l28_n243()
+ fun_l29_n580
+end
+
+def fun_l28_n244()
+ fun_l29_n195
+end
+
+def fun_l28_n245()
+ fun_l29_n571
+end
+
+def fun_l28_n246()
+ fun_l29_n987
+end
+
+def fun_l28_n247()
+ fun_l29_n87
+end
+
+def fun_l28_n248()
+ fun_l29_n331
+end
+
+def fun_l28_n249()
+ fun_l29_n405
+end
+
+def fun_l28_n250()
+ fun_l29_n142
+end
+
+def fun_l28_n251()
+ fun_l29_n652
+end
+
+def fun_l28_n252()
+ fun_l29_n788
+end
+
+def fun_l28_n253()
+ fun_l29_n591
+end
+
+def fun_l28_n254()
+ fun_l29_n613
+end
+
+def fun_l28_n255()
+ fun_l29_n171
+end
+
+def fun_l28_n256()
+ fun_l29_n836
+end
+
+def fun_l28_n257()
+ fun_l29_n420
+end
+
+def fun_l28_n258()
+ fun_l29_n326
+end
+
+def fun_l28_n259()
+ fun_l29_n790
+end
+
+def fun_l28_n260()
+ fun_l29_n515
+end
+
+def fun_l28_n261()
+ fun_l29_n650
+end
+
+def fun_l28_n262()
+ fun_l29_n388
+end
+
+def fun_l28_n263()
+ fun_l29_n56
+end
+
+def fun_l28_n264()
+ fun_l29_n288
+end
+
+def fun_l28_n265()
+ fun_l29_n187
+end
+
+def fun_l28_n266()
+ fun_l29_n461
+end
+
+def fun_l28_n267()
+ fun_l29_n194
+end
+
+def fun_l28_n268()
+ fun_l29_n870
+end
+
+def fun_l28_n269()
+ fun_l29_n425
+end
+
+def fun_l28_n270()
+ fun_l29_n731
+end
+
+def fun_l28_n271()
+ fun_l29_n763
+end
+
+def fun_l28_n272()
+ fun_l29_n128
+end
+
+def fun_l28_n273()
+ fun_l29_n693
+end
+
+def fun_l28_n274()
+ fun_l29_n775
+end
+
+def fun_l28_n275()
+ fun_l29_n769
+end
+
+def fun_l28_n276()
+ fun_l29_n491
+end
+
+def fun_l28_n277()
+ fun_l29_n799
+end
+
+def fun_l28_n278()
+ fun_l29_n506
+end
+
+def fun_l28_n279()
+ fun_l29_n607
+end
+
+def fun_l28_n280()
+ fun_l29_n988
+end
+
+def fun_l28_n281()
+ fun_l29_n290
+end
+
+def fun_l28_n282()
+ fun_l29_n389
+end
+
+def fun_l28_n283()
+ fun_l29_n133
+end
+
+def fun_l28_n284()
+ fun_l29_n631
+end
+
+def fun_l28_n285()
+ fun_l29_n285
+end
+
+def fun_l28_n286()
+ fun_l29_n537
+end
+
+def fun_l28_n287()
+ fun_l29_n911
+end
+
+def fun_l28_n288()
+ fun_l29_n297
+end
+
+def fun_l28_n289()
+ fun_l29_n585
+end
+
+def fun_l28_n290()
+ fun_l29_n535
+end
+
+def fun_l28_n291()
+ fun_l29_n570
+end
+
+def fun_l28_n292()
+ fun_l29_n19
+end
+
+def fun_l28_n293()
+ fun_l29_n444
+end
+
+def fun_l28_n294()
+ fun_l29_n44
+end
+
+def fun_l28_n295()
+ fun_l29_n252
+end
+
+def fun_l28_n296()
+ fun_l29_n623
+end
+
+def fun_l28_n297()
+ fun_l29_n398
+end
+
+def fun_l28_n298()
+ fun_l29_n716
+end
+
+def fun_l28_n299()
+ fun_l29_n607
+end
+
+def fun_l28_n300()
+ fun_l29_n105
+end
+
+def fun_l28_n301()
+ fun_l29_n438
+end
+
+def fun_l28_n302()
+ fun_l29_n308
+end
+
+def fun_l28_n303()
+ fun_l29_n301
+end
+
+def fun_l28_n304()
+ fun_l29_n577
+end
+
+def fun_l28_n305()
+ fun_l29_n537
+end
+
+def fun_l28_n306()
+ fun_l29_n375
+end
+
+def fun_l28_n307()
+ fun_l29_n211
+end
+
+def fun_l28_n308()
+ fun_l29_n227
+end
+
+def fun_l28_n309()
+ fun_l29_n275
+end
+
+def fun_l28_n310()
+ fun_l29_n122
+end
+
+def fun_l28_n311()
+ fun_l29_n983
+end
+
+def fun_l28_n312()
+ fun_l29_n844
+end
+
+def fun_l28_n313()
+ fun_l29_n865
+end
+
+def fun_l28_n314()
+ fun_l29_n27
+end
+
+def fun_l28_n315()
+ fun_l29_n933
+end
+
+def fun_l28_n316()
+ fun_l29_n89
+end
+
+def fun_l28_n317()
+ fun_l29_n11
+end
+
+def fun_l28_n318()
+ fun_l29_n107
+end
+
+def fun_l28_n319()
+ fun_l29_n604
+end
+
+def fun_l28_n320()
+ fun_l29_n768
+end
+
+def fun_l28_n321()
+ fun_l29_n638
+end
+
+def fun_l28_n322()
+ fun_l29_n513
+end
+
+def fun_l28_n323()
+ fun_l29_n61
+end
+
+def fun_l28_n324()
+ fun_l29_n776
+end
+
+def fun_l28_n325()
+ fun_l29_n377
+end
+
+def fun_l28_n326()
+ fun_l29_n768
+end
+
+def fun_l28_n327()
+ fun_l29_n573
+end
+
+def fun_l28_n328()
+ fun_l29_n719
+end
+
+def fun_l28_n329()
+ fun_l29_n878
+end
+
+def fun_l28_n330()
+ fun_l29_n995
+end
+
+def fun_l28_n331()
+ fun_l29_n32
+end
+
+def fun_l28_n332()
+ fun_l29_n647
+end
+
+def fun_l28_n333()
+ fun_l29_n570
+end
+
+def fun_l28_n334()
+ fun_l29_n194
+end
+
+def fun_l28_n335()
+ fun_l29_n182
+end
+
+def fun_l28_n336()
+ fun_l29_n463
+end
+
+def fun_l28_n337()
+ fun_l29_n677
+end
+
+def fun_l28_n338()
+ fun_l29_n524
+end
+
+def fun_l28_n339()
+ fun_l29_n221
+end
+
+def fun_l28_n340()
+ fun_l29_n120
+end
+
+def fun_l28_n341()
+ fun_l29_n633
+end
+
+def fun_l28_n342()
+ fun_l29_n428
+end
+
+def fun_l28_n343()
+ fun_l29_n510
+end
+
+def fun_l28_n344()
+ fun_l29_n576
+end
+
+def fun_l28_n345()
+ fun_l29_n423
+end
+
+def fun_l28_n346()
+ fun_l29_n412
+end
+
+def fun_l28_n347()
+ fun_l29_n315
+end
+
+def fun_l28_n348()
+ fun_l29_n809
+end
+
+def fun_l28_n349()
+ fun_l29_n195
+end
+
+def fun_l28_n350()
+ fun_l29_n724
+end
+
+def fun_l28_n351()
+ fun_l29_n438
+end
+
+def fun_l28_n352()
+ fun_l29_n229
+end
+
+def fun_l28_n353()
+ fun_l29_n113
+end
+
+def fun_l28_n354()
+ fun_l29_n58
+end
+
+def fun_l28_n355()
+ fun_l29_n105
+end
+
+def fun_l28_n356()
+ fun_l29_n371
+end
+
+def fun_l28_n357()
+ fun_l29_n397
+end
+
+def fun_l28_n358()
+ fun_l29_n441
+end
+
+def fun_l28_n359()
+ fun_l29_n765
+end
+
+def fun_l28_n360()
+ fun_l29_n752
+end
+
+def fun_l28_n361()
+ fun_l29_n255
+end
+
+def fun_l28_n362()
+ fun_l29_n981
+end
+
+def fun_l28_n363()
+ fun_l29_n612
+end
+
+def fun_l28_n364()
+ fun_l29_n268
+end
+
+def fun_l28_n365()
+ fun_l29_n573
+end
+
+def fun_l28_n366()
+ fun_l29_n202
+end
+
+def fun_l28_n367()
+ fun_l29_n477
+end
+
+def fun_l28_n368()
+ fun_l29_n353
+end
+
+def fun_l28_n369()
+ fun_l29_n244
+end
+
+def fun_l28_n370()
+ fun_l29_n348
+end
+
+def fun_l28_n371()
+ fun_l29_n96
+end
+
+def fun_l28_n372()
+ fun_l29_n421
+end
+
+def fun_l28_n373()
+ fun_l29_n685
+end
+
+def fun_l28_n374()
+ fun_l29_n408
+end
+
+def fun_l28_n375()
+ fun_l29_n971
+end
+
+def fun_l28_n376()
+ fun_l29_n372
+end
+
+def fun_l28_n377()
+ fun_l29_n852
+end
+
+def fun_l28_n378()
+ fun_l29_n872
+end
+
+def fun_l28_n379()
+ fun_l29_n981
+end
+
+def fun_l28_n380()
+ fun_l29_n939
+end
+
+def fun_l28_n381()
+ fun_l29_n13
+end
+
+def fun_l28_n382()
+ fun_l29_n381
+end
+
+def fun_l28_n383()
+ fun_l29_n291
+end
+
+def fun_l28_n384()
+ fun_l29_n465
+end
+
+def fun_l28_n385()
+ fun_l29_n309
+end
+
+def fun_l28_n386()
+ fun_l29_n53
+end
+
+def fun_l28_n387()
+ fun_l29_n525
+end
+
+def fun_l28_n388()
+ fun_l29_n756
+end
+
+def fun_l28_n389()
+ fun_l29_n347
+end
+
+def fun_l28_n390()
+ fun_l29_n517
+end
+
+def fun_l28_n391()
+ fun_l29_n275
+end
+
+def fun_l28_n392()
+ fun_l29_n973
+end
+
+def fun_l28_n393()
+ fun_l29_n538
+end
+
+def fun_l28_n394()
+ fun_l29_n429
+end
+
+def fun_l28_n395()
+ fun_l29_n219
+end
+
+def fun_l28_n396()
+ fun_l29_n823
+end
+
+def fun_l28_n397()
+ fun_l29_n676
+end
+
+def fun_l28_n398()
+ fun_l29_n319
+end
+
+def fun_l28_n399()
+ fun_l29_n784
+end
+
+def fun_l28_n400()
+ fun_l29_n741
+end
+
+def fun_l28_n401()
+ fun_l29_n876
+end
+
+def fun_l28_n402()
+ fun_l29_n648
+end
+
+def fun_l28_n403()
+ fun_l29_n231
+end
+
+def fun_l28_n404()
+ fun_l29_n459
+end
+
+def fun_l28_n405()
+ fun_l29_n350
+end
+
+def fun_l28_n406()
+ fun_l29_n398
+end
+
+def fun_l28_n407()
+ fun_l29_n692
+end
+
+def fun_l28_n408()
+ fun_l29_n91
+end
+
+def fun_l28_n409()
+ fun_l29_n120
+end
+
+def fun_l28_n410()
+ fun_l29_n337
+end
+
+def fun_l28_n411()
+ fun_l29_n963
+end
+
+def fun_l28_n412()
+ fun_l29_n16
+end
+
+def fun_l28_n413()
+ fun_l29_n956
+end
+
+def fun_l28_n414()
+ fun_l29_n255
+end
+
+def fun_l28_n415()
+ fun_l29_n309
+end
+
+def fun_l28_n416()
+ fun_l29_n430
+end
+
+def fun_l28_n417()
+ fun_l29_n374
+end
+
+def fun_l28_n418()
+ fun_l29_n559
+end
+
+def fun_l28_n419()
+ fun_l29_n393
+end
+
+def fun_l28_n420()
+ fun_l29_n547
+end
+
+def fun_l28_n421()
+ fun_l29_n500
+end
+
+def fun_l28_n422()
+ fun_l29_n771
+end
+
+def fun_l28_n423()
+ fun_l29_n429
+end
+
+def fun_l28_n424()
+ fun_l29_n839
+end
+
+def fun_l28_n425()
+ fun_l29_n871
+end
+
+def fun_l28_n426()
+ fun_l29_n333
+end
+
+def fun_l28_n427()
+ fun_l29_n652
+end
+
+def fun_l28_n428()
+ fun_l29_n87
+end
+
+def fun_l28_n429()
+ fun_l29_n472
+end
+
+def fun_l28_n430()
+ fun_l29_n911
+end
+
+def fun_l28_n431()
+ fun_l29_n305
+end
+
+def fun_l28_n432()
+ fun_l29_n569
+end
+
+def fun_l28_n433()
+ fun_l29_n869
+end
+
+def fun_l28_n434()
+ fun_l29_n203
+end
+
+def fun_l28_n435()
+ fun_l29_n804
+end
+
+def fun_l28_n436()
+ fun_l29_n878
+end
+
+def fun_l28_n437()
+ fun_l29_n984
+end
+
+def fun_l28_n438()
+ fun_l29_n990
+end
+
+def fun_l28_n439()
+ fun_l29_n860
+end
+
+def fun_l28_n440()
+ fun_l29_n866
+end
+
+def fun_l28_n441()
+ fun_l29_n625
+end
+
+def fun_l28_n442()
+ fun_l29_n534
+end
+
+def fun_l28_n443()
+ fun_l29_n232
+end
+
+def fun_l28_n444()
+ fun_l29_n447
+end
+
+def fun_l28_n445()
+ fun_l29_n958
+end
+
+def fun_l28_n446()
+ fun_l29_n343
+end
+
+def fun_l28_n447()
+ fun_l29_n128
+end
+
+def fun_l28_n448()
+ fun_l29_n760
+end
+
+def fun_l28_n449()
+ fun_l29_n204
+end
+
+def fun_l28_n450()
+ fun_l29_n912
+end
+
+def fun_l28_n451()
+ fun_l29_n395
+end
+
+def fun_l28_n452()
+ fun_l29_n721
+end
+
+def fun_l28_n453()
+ fun_l29_n699
+end
+
+def fun_l28_n454()
+ fun_l29_n950
+end
+
+def fun_l28_n455()
+ fun_l29_n436
+end
+
+def fun_l28_n456()
+ fun_l29_n431
+end
+
+def fun_l28_n457()
+ fun_l29_n644
+end
+
+def fun_l28_n458()
+ fun_l29_n638
+end
+
+def fun_l28_n459()
+ fun_l29_n967
+end
+
+def fun_l28_n460()
+ fun_l29_n83
+end
+
+def fun_l28_n461()
+ fun_l29_n141
+end
+
+def fun_l28_n462()
+ fun_l29_n37
+end
+
+def fun_l28_n463()
+ fun_l29_n485
+end
+
+def fun_l28_n464()
+ fun_l29_n826
+end
+
+def fun_l28_n465()
+ fun_l29_n774
+end
+
+def fun_l28_n466()
+ fun_l29_n561
+end
+
+def fun_l28_n467()
+ fun_l29_n809
+end
+
+def fun_l28_n468()
+ fun_l29_n298
+end
+
+def fun_l28_n469()
+ fun_l29_n367
+end
+
+def fun_l28_n470()
+ fun_l29_n517
+end
+
+def fun_l28_n471()
+ fun_l29_n30
+end
+
+def fun_l28_n472()
+ fun_l29_n970
+end
+
+def fun_l28_n473()
+ fun_l29_n686
+end
+
+def fun_l28_n474()
+ fun_l29_n183
+end
+
+def fun_l28_n475()
+ fun_l29_n176
+end
+
+def fun_l28_n476()
+ fun_l29_n87
+end
+
+def fun_l28_n477()
+ fun_l29_n81
+end
+
+def fun_l28_n478()
+ fun_l29_n836
+end
+
+def fun_l28_n479()
+ fun_l29_n898
+end
+
+def fun_l28_n480()
+ fun_l29_n49
+end
+
+def fun_l28_n481()
+ fun_l29_n468
+end
+
+def fun_l28_n482()
+ fun_l29_n314
+end
+
+def fun_l28_n483()
+ fun_l29_n242
+end
+
+def fun_l28_n484()
+ fun_l29_n647
+end
+
+def fun_l28_n485()
+ fun_l29_n167
+end
+
+def fun_l28_n486()
+ fun_l29_n245
+end
+
+def fun_l28_n487()
+ fun_l29_n723
+end
+
+def fun_l28_n488()
+ fun_l29_n576
+end
+
+def fun_l28_n489()
+ fun_l29_n481
+end
+
+def fun_l28_n490()
+ fun_l29_n154
+end
+
+def fun_l28_n491()
+ fun_l29_n271
+end
+
+def fun_l28_n492()
+ fun_l29_n671
+end
+
+def fun_l28_n493()
+ fun_l29_n70
+end
+
+def fun_l28_n494()
+ fun_l29_n14
+end
+
+def fun_l28_n495()
+ fun_l29_n108
+end
+
+def fun_l28_n496()
+ fun_l29_n464
+end
+
+def fun_l28_n497()
+ fun_l29_n7
+end
+
+def fun_l28_n498()
+ fun_l29_n372
+end
+
+def fun_l28_n499()
+ fun_l29_n202
+end
+
+def fun_l28_n500()
+ fun_l29_n208
+end
+
+def fun_l28_n501()
+ fun_l29_n640
+end
+
+def fun_l28_n502()
+ fun_l29_n977
+end
+
+def fun_l28_n503()
+ fun_l29_n287
+end
+
+def fun_l28_n504()
+ fun_l29_n905
+end
+
+def fun_l28_n505()
+ fun_l29_n847
+end
+
+def fun_l28_n506()
+ fun_l29_n18
+end
+
+def fun_l28_n507()
+ fun_l29_n889
+end
+
+def fun_l28_n508()
+ fun_l29_n527
+end
+
+def fun_l28_n509()
+ fun_l29_n137
+end
+
+def fun_l28_n510()
+ fun_l29_n256
+end
+
+def fun_l28_n511()
+ fun_l29_n449
+end
+
+def fun_l28_n512()
+ fun_l29_n252
+end
+
+def fun_l28_n513()
+ fun_l29_n42
+end
+
+def fun_l28_n514()
+ fun_l29_n398
+end
+
+def fun_l28_n515()
+ fun_l29_n655
+end
+
+def fun_l28_n516()
+ fun_l29_n208
+end
+
+def fun_l28_n517()
+ fun_l29_n883
+end
+
+def fun_l28_n518()
+ fun_l29_n401
+end
+
+def fun_l28_n519()
+ fun_l29_n825
+end
+
+def fun_l28_n520()
+ fun_l29_n380
+end
+
+def fun_l28_n521()
+ fun_l29_n277
+end
+
+def fun_l28_n522()
+ fun_l29_n165
+end
+
+def fun_l28_n523()
+ fun_l29_n373
+end
+
+def fun_l28_n524()
+ fun_l29_n378
+end
+
+def fun_l28_n525()
+ fun_l29_n70
+end
+
+def fun_l28_n526()
+ fun_l29_n975
+end
+
+def fun_l28_n527()
+ fun_l29_n34
+end
+
+def fun_l28_n528()
+ fun_l29_n346
+end
+
+def fun_l28_n529()
+ fun_l29_n322
+end
+
+def fun_l28_n530()
+ fun_l29_n429
+end
+
+def fun_l28_n531()
+ fun_l29_n20
+end
+
+def fun_l28_n532()
+ fun_l29_n155
+end
+
+def fun_l28_n533()
+ fun_l29_n896
+end
+
+def fun_l28_n534()
+ fun_l29_n860
+end
+
+def fun_l28_n535()
+ fun_l29_n602
+end
+
+def fun_l28_n536()
+ fun_l29_n573
+end
+
+def fun_l28_n537()
+ fun_l29_n448
+end
+
+def fun_l28_n538()
+ fun_l29_n637
+end
+
+def fun_l28_n539()
+ fun_l29_n890
+end
+
+def fun_l28_n540()
+ fun_l29_n200
+end
+
+def fun_l28_n541()
+ fun_l29_n405
+end
+
+def fun_l28_n542()
+ fun_l29_n656
+end
+
+def fun_l28_n543()
+ fun_l29_n974
+end
+
+def fun_l28_n544()
+ fun_l29_n711
+end
+
+def fun_l28_n545()
+ fun_l29_n206
+end
+
+def fun_l28_n546()
+ fun_l29_n677
+end
+
+def fun_l28_n547()
+ fun_l29_n125
+end
+
+def fun_l28_n548()
+ fun_l29_n576
+end
+
+def fun_l28_n549()
+ fun_l29_n923
+end
+
+def fun_l28_n550()
+ fun_l29_n86
+end
+
+def fun_l28_n551()
+ fun_l29_n827
+end
+
+def fun_l28_n552()
+ fun_l29_n76
+end
+
+def fun_l28_n553()
+ fun_l29_n143
+end
+
+def fun_l28_n554()
+ fun_l29_n435
+end
+
+def fun_l28_n555()
+ fun_l29_n75
+end
+
+def fun_l28_n556()
+ fun_l29_n23
+end
+
+def fun_l28_n557()
+ fun_l29_n658
+end
+
+def fun_l28_n558()
+ fun_l29_n814
+end
+
+def fun_l28_n559()
+ fun_l29_n833
+end
+
+def fun_l28_n560()
+ fun_l29_n101
+end
+
+def fun_l28_n561()
+ fun_l29_n513
+end
+
+def fun_l28_n562()
+ fun_l29_n43
+end
+
+def fun_l28_n563()
+ fun_l29_n576
+end
+
+def fun_l28_n564()
+ fun_l29_n131
+end
+
+def fun_l28_n565()
+ fun_l29_n920
+end
+
+def fun_l28_n566()
+ fun_l29_n299
+end
+
+def fun_l28_n567()
+ fun_l29_n216
+end
+
+def fun_l28_n568()
+ fun_l29_n547
+end
+
+def fun_l28_n569()
+ fun_l29_n728
+end
+
+def fun_l28_n570()
+ fun_l29_n349
+end
+
+def fun_l28_n571()
+ fun_l29_n927
+end
+
+def fun_l28_n572()
+ fun_l29_n328
+end
+
+def fun_l28_n573()
+ fun_l29_n790
+end
+
+def fun_l28_n574()
+ fun_l29_n397
+end
+
+def fun_l28_n575()
+ fun_l29_n423
+end
+
+def fun_l28_n576()
+ fun_l29_n867
+end
+
+def fun_l28_n577()
+ fun_l29_n529
+end
+
+def fun_l28_n578()
+ fun_l29_n825
+end
+
+def fun_l28_n579()
+ fun_l29_n51
+end
+
+def fun_l28_n580()
+ fun_l29_n482
+end
+
+def fun_l28_n581()
+ fun_l29_n395
+end
+
+def fun_l28_n582()
+ fun_l29_n771
+end
+
+def fun_l28_n583()
+ fun_l29_n118
+end
+
+def fun_l28_n584()
+ fun_l29_n348
+end
+
+def fun_l28_n585()
+ fun_l29_n895
+end
+
+def fun_l28_n586()
+ fun_l29_n956
+end
+
+def fun_l28_n587()
+ fun_l29_n251
+end
+
+def fun_l28_n588()
+ fun_l29_n216
+end
+
+def fun_l28_n589()
+ fun_l29_n837
+end
+
+def fun_l28_n590()
+ fun_l29_n956
+end
+
+def fun_l28_n591()
+ fun_l29_n309
+end
+
+def fun_l28_n592()
+ fun_l29_n706
+end
+
+def fun_l28_n593()
+ fun_l29_n58
+end
+
+def fun_l28_n594()
+ fun_l29_n244
+end
+
+def fun_l28_n595()
+ fun_l29_n281
+end
+
+def fun_l28_n596()
+ fun_l29_n748
+end
+
+def fun_l28_n597()
+ fun_l29_n109
+end
+
+def fun_l28_n598()
+ fun_l29_n730
+end
+
+def fun_l28_n599()
+ fun_l29_n590
+end
+
+def fun_l28_n600()
+ fun_l29_n331
+end
+
+def fun_l28_n601()
+ fun_l29_n700
+end
+
+def fun_l28_n602()
+ fun_l29_n606
+end
+
+def fun_l28_n603()
+ fun_l29_n331
+end
+
+def fun_l28_n604()
+ fun_l29_n695
+end
+
+def fun_l28_n605()
+ fun_l29_n355
+end
+
+def fun_l28_n606()
+ fun_l29_n449
+end
+
+def fun_l28_n607()
+ fun_l29_n728
+end
+
+def fun_l28_n608()
+ fun_l29_n248
+end
+
+def fun_l28_n609()
+ fun_l29_n949
+end
+
+def fun_l28_n610()
+ fun_l29_n473
+end
+
+def fun_l28_n611()
+ fun_l29_n244
+end
+
+def fun_l28_n612()
+ fun_l29_n790
+end
+
+def fun_l28_n613()
+ fun_l29_n983
+end
+
+def fun_l28_n614()
+ fun_l29_n76
+end
+
+def fun_l28_n615()
+ fun_l29_n792
+end
+
+def fun_l28_n616()
+ fun_l29_n195
+end
+
+def fun_l28_n617()
+ fun_l29_n559
+end
+
+def fun_l28_n618()
+ fun_l29_n269
+end
+
+def fun_l28_n619()
+ fun_l29_n152
+end
+
+def fun_l28_n620()
+ fun_l29_n507
+end
+
+def fun_l28_n621()
+ fun_l29_n165
+end
+
+def fun_l28_n622()
+ fun_l29_n779
+end
+
+def fun_l28_n623()
+ fun_l29_n182
+end
+
+def fun_l28_n624()
+ fun_l29_n76
+end
+
+def fun_l28_n625()
+ fun_l29_n585
+end
+
+def fun_l28_n626()
+ fun_l29_n943
+end
+
+def fun_l28_n627()
+ fun_l29_n25
+end
+
+def fun_l28_n628()
+ fun_l29_n200
+end
+
+def fun_l28_n629()
+ fun_l29_n590
+end
+
+def fun_l28_n630()
+ fun_l29_n631
+end
+
+def fun_l28_n631()
+ fun_l29_n610
+end
+
+def fun_l28_n632()
+ fun_l29_n197
+end
+
+def fun_l28_n633()
+ fun_l29_n608
+end
+
+def fun_l28_n634()
+ fun_l29_n585
+end
+
+def fun_l28_n635()
+ fun_l29_n987
+end
+
+def fun_l28_n636()
+ fun_l29_n440
+end
+
+def fun_l28_n637()
+ fun_l29_n808
+end
+
+def fun_l28_n638()
+ fun_l29_n208
+end
+
+def fun_l28_n639()
+ fun_l29_n382
+end
+
+def fun_l28_n640()
+ fun_l29_n631
+end
+
+def fun_l28_n641()
+ fun_l29_n107
+end
+
+def fun_l28_n642()
+ fun_l29_n682
+end
+
+def fun_l28_n643()
+ fun_l29_n57
+end
+
+def fun_l28_n644()
+ fun_l29_n375
+end
+
+def fun_l28_n645()
+ fun_l29_n855
+end
+
+def fun_l28_n646()
+ fun_l29_n200
+end
+
+def fun_l28_n647()
+ fun_l29_n820
+end
+
+def fun_l28_n648()
+ fun_l29_n363
+end
+
+def fun_l28_n649()
+ fun_l29_n991
+end
+
+def fun_l28_n650()
+ fun_l29_n342
+end
+
+def fun_l28_n651()
+ fun_l29_n740
+end
+
+def fun_l28_n652()
+ fun_l29_n646
+end
+
+def fun_l28_n653()
+ fun_l29_n743
+end
+
+def fun_l28_n654()
+ fun_l29_n438
+end
+
+def fun_l28_n655()
+ fun_l29_n198
+end
+
+def fun_l28_n656()
+ fun_l29_n45
+end
+
+def fun_l28_n657()
+ fun_l29_n54
+end
+
+def fun_l28_n658()
+ fun_l29_n5
+end
+
+def fun_l28_n659()
+ fun_l29_n30
+end
+
+def fun_l28_n660()
+ fun_l29_n77
+end
+
+def fun_l28_n661()
+ fun_l29_n231
+end
+
+def fun_l28_n662()
+ fun_l29_n515
+end
+
+def fun_l28_n663()
+ fun_l29_n327
+end
+
+def fun_l28_n664()
+ fun_l29_n188
+end
+
+def fun_l28_n665()
+ fun_l29_n976
+end
+
+def fun_l28_n666()
+ fun_l29_n482
+end
+
+def fun_l28_n667()
+ fun_l29_n106
+end
+
+def fun_l28_n668()
+ fun_l29_n339
+end
+
+def fun_l28_n669()
+ fun_l29_n445
+end
+
+def fun_l28_n670()
+ fun_l29_n708
+end
+
+def fun_l28_n671()
+ fun_l29_n846
+end
+
+def fun_l28_n672()
+ fun_l29_n142
+end
+
+def fun_l28_n673()
+ fun_l29_n567
+end
+
+def fun_l28_n674()
+ fun_l29_n875
+end
+
+def fun_l28_n675()
+ fun_l29_n107
+end
+
+def fun_l28_n676()
+ fun_l29_n243
+end
+
+def fun_l28_n677()
+ fun_l29_n580
+end
+
+def fun_l28_n678()
+ fun_l29_n75
+end
+
+def fun_l28_n679()
+ fun_l29_n230
+end
+
+def fun_l28_n680()
+ fun_l29_n72
+end
+
+def fun_l28_n681()
+ fun_l29_n429
+end
+
+def fun_l28_n682()
+ fun_l29_n816
+end
+
+def fun_l28_n683()
+ fun_l29_n896
+end
+
+def fun_l28_n684()
+ fun_l29_n933
+end
+
+def fun_l28_n685()
+ fun_l29_n432
+end
+
+def fun_l28_n686()
+ fun_l29_n547
+end
+
+def fun_l28_n687()
+ fun_l29_n670
+end
+
+def fun_l28_n688()
+ fun_l29_n952
+end
+
+def fun_l28_n689()
+ fun_l29_n137
+end
+
+def fun_l28_n690()
+ fun_l29_n532
+end
+
+def fun_l28_n691()
+ fun_l29_n608
+end
+
+def fun_l28_n692()
+ fun_l29_n264
+end
+
+def fun_l28_n693()
+ fun_l29_n220
+end
+
+def fun_l28_n694()
+ fun_l29_n499
+end
+
+def fun_l28_n695()
+ fun_l29_n244
+end
+
+def fun_l28_n696()
+ fun_l29_n952
+end
+
+def fun_l28_n697()
+ fun_l29_n700
+end
+
+def fun_l28_n698()
+ fun_l29_n415
+end
+
+def fun_l28_n699()
+ fun_l29_n712
+end
+
+def fun_l28_n700()
+ fun_l29_n209
+end
+
+def fun_l28_n701()
+ fun_l29_n759
+end
+
+def fun_l28_n702()
+ fun_l29_n786
+end
+
+def fun_l28_n703()
+ fun_l29_n858
+end
+
+def fun_l28_n704()
+ fun_l29_n328
+end
+
+def fun_l28_n705()
+ fun_l29_n201
+end
+
+def fun_l28_n706()
+ fun_l29_n317
+end
+
+def fun_l28_n707()
+ fun_l29_n335
+end
+
+def fun_l28_n708()
+ fun_l29_n483
+end
+
+def fun_l28_n709()
+ fun_l29_n1
+end
+
+def fun_l28_n710()
+ fun_l29_n962
+end
+
+def fun_l28_n711()
+ fun_l29_n158
+end
+
+def fun_l28_n712()
+ fun_l29_n591
+end
+
+def fun_l28_n713()
+ fun_l29_n849
+end
+
+def fun_l28_n714()
+ fun_l29_n149
+end
+
+def fun_l28_n715()
+ fun_l29_n653
+end
+
+def fun_l28_n716()
+ fun_l29_n173
+end
+
+def fun_l28_n717()
+ fun_l29_n21
+end
+
+def fun_l28_n718()
+ fun_l29_n384
+end
+
+def fun_l28_n719()
+ fun_l29_n601
+end
+
+def fun_l28_n720()
+ fun_l29_n388
+end
+
+def fun_l28_n721()
+ fun_l29_n866
+end
+
+def fun_l28_n722()
+ fun_l29_n261
+end
+
+def fun_l28_n723()
+ fun_l29_n412
+end
+
+def fun_l28_n724()
+ fun_l29_n77
+end
+
+def fun_l28_n725()
+ fun_l29_n395
+end
+
+def fun_l28_n726()
+ fun_l29_n863
+end
+
+def fun_l28_n727()
+ fun_l29_n780
+end
+
+def fun_l28_n728()
+ fun_l29_n400
+end
+
+def fun_l28_n729()
+ fun_l29_n495
+end
+
+def fun_l28_n730()
+ fun_l29_n813
+end
+
+def fun_l28_n731()
+ fun_l29_n330
+end
+
+def fun_l28_n732()
+ fun_l29_n479
+end
+
+def fun_l28_n733()
+ fun_l29_n446
+end
+
+def fun_l28_n734()
+ fun_l29_n354
+end
+
+def fun_l28_n735()
+ fun_l29_n88
+end
+
+def fun_l28_n736()
+ fun_l29_n296
+end
+
+def fun_l28_n737()
+ fun_l29_n457
+end
+
+def fun_l28_n738()
+ fun_l29_n611
+end
+
+def fun_l28_n739()
+ fun_l29_n412
+end
+
+def fun_l28_n740()
+ fun_l29_n290
+end
+
+def fun_l28_n741()
+ fun_l29_n935
+end
+
+def fun_l28_n742()
+ fun_l29_n833
+end
+
+def fun_l28_n743()
+ fun_l29_n296
+end
+
+def fun_l28_n744()
+ fun_l29_n249
+end
+
+def fun_l28_n745()
+ fun_l29_n567
+end
+
+def fun_l28_n746()
+ fun_l29_n707
+end
+
+def fun_l28_n747()
+ fun_l29_n633
+end
+
+def fun_l28_n748()
+ fun_l29_n303
+end
+
+def fun_l28_n749()
+ fun_l29_n971
+end
+
+def fun_l28_n750()
+ fun_l29_n784
+end
+
+def fun_l28_n751()
+ fun_l29_n88
+end
+
+def fun_l28_n752()
+ fun_l29_n782
+end
+
+def fun_l28_n753()
+ fun_l29_n322
+end
+
+def fun_l28_n754()
+ fun_l29_n362
+end
+
+def fun_l28_n755()
+ fun_l29_n894
+end
+
+def fun_l28_n756()
+ fun_l29_n848
+end
+
+def fun_l28_n757()
+ fun_l29_n617
+end
+
+def fun_l28_n758()
+ fun_l29_n103
+end
+
+def fun_l28_n759()
+ fun_l29_n625
+end
+
+def fun_l28_n760()
+ fun_l29_n592
+end
+
+def fun_l28_n761()
+ fun_l29_n597
+end
+
+def fun_l28_n762()
+ fun_l29_n118
+end
+
+def fun_l28_n763()
+ fun_l29_n366
+end
+
+def fun_l28_n764()
+ fun_l29_n609
+end
+
+def fun_l28_n765()
+ fun_l29_n710
+end
+
+def fun_l28_n766()
+ fun_l29_n563
+end
+
+def fun_l28_n767()
+ fun_l29_n324
+end
+
+def fun_l28_n768()
+ fun_l29_n783
+end
+
+def fun_l28_n769()
+ fun_l29_n512
+end
+
+def fun_l28_n770()
+ fun_l29_n0
+end
+
+def fun_l28_n771()
+ fun_l29_n60
+end
+
+def fun_l28_n772()
+ fun_l29_n18
+end
+
+def fun_l28_n773()
+ fun_l29_n741
+end
+
+def fun_l28_n774()
+ fun_l29_n862
+end
+
+def fun_l28_n775()
+ fun_l29_n183
+end
+
+def fun_l28_n776()
+ fun_l29_n148
+end
+
+def fun_l28_n777()
+ fun_l29_n703
+end
+
+def fun_l28_n778()
+ fun_l29_n251
+end
+
+def fun_l28_n779()
+ fun_l29_n84
+end
+
+def fun_l28_n780()
+ fun_l29_n85
+end
+
+def fun_l28_n781()
+ fun_l29_n632
+end
+
+def fun_l28_n782()
+ fun_l29_n28
+end
+
+def fun_l28_n783()
+ fun_l29_n123
+end
+
+def fun_l28_n784()
+ fun_l29_n66
+end
+
+def fun_l28_n785()
+ fun_l29_n266
+end
+
+def fun_l28_n786()
+ fun_l29_n860
+end
+
+def fun_l28_n787()
+ fun_l29_n769
+end
+
+def fun_l28_n788()
+ fun_l29_n921
+end
+
+def fun_l28_n789()
+ fun_l29_n513
+end
+
+def fun_l28_n790()
+ fun_l29_n455
+end
+
+def fun_l28_n791()
+ fun_l29_n589
+end
+
+def fun_l28_n792()
+ fun_l29_n557
+end
+
+def fun_l28_n793()
+ fun_l29_n827
+end
+
+def fun_l28_n794()
+ fun_l29_n561
+end
+
+def fun_l28_n795()
+ fun_l29_n891
+end
+
+def fun_l28_n796()
+ fun_l29_n938
+end
+
+def fun_l28_n797()
+ fun_l29_n157
+end
+
+def fun_l28_n798()
+ fun_l29_n691
+end
+
+def fun_l28_n799()
+ fun_l29_n20
+end
+
+def fun_l28_n800()
+ fun_l29_n737
+end
+
+def fun_l28_n801()
+ fun_l29_n675
+end
+
+def fun_l28_n802()
+ fun_l29_n385
+end
+
+def fun_l28_n803()
+ fun_l29_n206
+end
+
+def fun_l28_n804()
+ fun_l29_n366
+end
+
+def fun_l28_n805()
+ fun_l29_n107
+end
+
+def fun_l28_n806()
+ fun_l29_n425
+end
+
+def fun_l28_n807()
+ fun_l29_n371
+end
+
+def fun_l28_n808()
+ fun_l29_n241
+end
+
+def fun_l28_n809()
+ fun_l29_n168
+end
+
+def fun_l28_n810()
+ fun_l29_n201
+end
+
+def fun_l28_n811()
+ fun_l29_n600
+end
+
+def fun_l28_n812()
+ fun_l29_n251
+end
+
+def fun_l28_n813()
+ fun_l29_n10
+end
+
+def fun_l28_n814()
+ fun_l29_n428
+end
+
+def fun_l28_n815()
+ fun_l29_n850
+end
+
+def fun_l28_n816()
+ fun_l29_n276
+end
+
+def fun_l28_n817()
+ fun_l29_n196
+end
+
+def fun_l28_n818()
+ fun_l29_n623
+end
+
+def fun_l28_n819()
+ fun_l29_n441
+end
+
+def fun_l28_n820()
+ fun_l29_n724
+end
+
+def fun_l28_n821()
+ fun_l29_n958
+end
+
+def fun_l28_n822()
+ fun_l29_n449
+end
+
+def fun_l28_n823()
+ fun_l29_n408
+end
+
+def fun_l28_n824()
+ fun_l29_n74
+end
+
+def fun_l28_n825()
+ fun_l29_n124
+end
+
+def fun_l28_n826()
+ fun_l29_n991
+end
+
+def fun_l28_n827()
+ fun_l29_n576
+end
+
+def fun_l28_n828()
+ fun_l29_n743
+end
+
+def fun_l28_n829()
+ fun_l29_n343
+end
+
+def fun_l28_n830()
+ fun_l29_n376
+end
+
+def fun_l28_n831()
+ fun_l29_n216
+end
+
+def fun_l28_n832()
+ fun_l29_n358
+end
+
+def fun_l28_n833()
+ fun_l29_n567
+end
+
+def fun_l28_n834()
+ fun_l29_n415
+end
+
+def fun_l28_n835()
+ fun_l29_n984
+end
+
+def fun_l28_n836()
+ fun_l29_n367
+end
+
+def fun_l28_n837()
+ fun_l29_n299
+end
+
+def fun_l28_n838()
+ fun_l29_n718
+end
+
+def fun_l28_n839()
+ fun_l29_n241
+end
+
+def fun_l28_n840()
+ fun_l29_n736
+end
+
+def fun_l28_n841()
+ fun_l29_n582
+end
+
+def fun_l28_n842()
+ fun_l29_n994
+end
+
+def fun_l28_n843()
+ fun_l29_n301
+end
+
+def fun_l28_n844()
+ fun_l29_n597
+end
+
+def fun_l28_n845()
+ fun_l29_n141
+end
+
+def fun_l28_n846()
+ fun_l29_n37
+end
+
+def fun_l28_n847()
+ fun_l29_n216
+end
+
+def fun_l28_n848()
+ fun_l29_n286
+end
+
+def fun_l28_n849()
+ fun_l29_n607
+end
+
+def fun_l28_n850()
+ fun_l29_n503
+end
+
+def fun_l28_n851()
+ fun_l29_n321
+end
+
+def fun_l28_n852()
+ fun_l29_n179
+end
+
+def fun_l28_n853()
+ fun_l29_n802
+end
+
+def fun_l28_n854()
+ fun_l29_n742
+end
+
+def fun_l28_n855()
+ fun_l29_n300
+end
+
+def fun_l28_n856()
+ fun_l29_n453
+end
+
+def fun_l28_n857()
+ fun_l29_n520
+end
+
+def fun_l28_n858()
+ fun_l29_n911
+end
+
+def fun_l28_n859()
+ fun_l29_n209
+end
+
+def fun_l28_n860()
+ fun_l29_n921
+end
+
+def fun_l28_n861()
+ fun_l29_n653
+end
+
+def fun_l28_n862()
+ fun_l29_n347
+end
+
+def fun_l28_n863()
+ fun_l29_n733
+end
+
+def fun_l28_n864()
+ fun_l29_n824
+end
+
+def fun_l28_n865()
+ fun_l29_n497
+end
+
+def fun_l28_n866()
+ fun_l29_n256
+end
+
+def fun_l28_n867()
+ fun_l29_n884
+end
+
+def fun_l28_n868()
+ fun_l29_n937
+end
+
+def fun_l28_n869()
+ fun_l29_n894
+end
+
+def fun_l28_n870()
+ fun_l29_n258
+end
+
+def fun_l28_n871()
+ fun_l29_n45
+end
+
+def fun_l28_n872()
+ fun_l29_n640
+end
+
+def fun_l28_n873()
+ fun_l29_n909
+end
+
+def fun_l28_n874()
+ fun_l29_n586
+end
+
+def fun_l28_n875()
+ fun_l29_n600
+end
+
+def fun_l28_n876()
+ fun_l29_n636
+end
+
+def fun_l28_n877()
+ fun_l29_n972
+end
+
+def fun_l28_n878()
+ fun_l29_n627
+end
+
+def fun_l28_n879()
+ fun_l29_n381
+end
+
+def fun_l28_n880()
+ fun_l29_n664
+end
+
+def fun_l28_n881()
+ fun_l29_n350
+end
+
+def fun_l28_n882()
+ fun_l29_n611
+end
+
+def fun_l28_n883()
+ fun_l29_n355
+end
+
+def fun_l28_n884()
+ fun_l29_n945
+end
+
+def fun_l28_n885()
+ fun_l29_n462
+end
+
+def fun_l28_n886()
+ fun_l29_n723
+end
+
+def fun_l28_n887()
+ fun_l29_n500
+end
+
+def fun_l28_n888()
+ fun_l29_n166
+end
+
+def fun_l28_n889()
+ fun_l29_n779
+end
+
+def fun_l28_n890()
+ fun_l29_n151
+end
+
+def fun_l28_n891()
+ fun_l29_n757
+end
+
+def fun_l28_n892()
+ fun_l29_n782
+end
+
+def fun_l28_n893()
+ fun_l29_n108
+end
+
+def fun_l28_n894()
+ fun_l29_n122
+end
+
+def fun_l28_n895()
+ fun_l29_n815
+end
+
+def fun_l28_n896()
+ fun_l29_n742
+end
+
+def fun_l28_n897()
+ fun_l29_n861
+end
+
+def fun_l28_n898()
+ fun_l29_n738
+end
+
+def fun_l28_n899()
+ fun_l29_n765
+end
+
+def fun_l28_n900()
+ fun_l29_n648
+end
+
+def fun_l28_n901()
+ fun_l29_n923
+end
+
+def fun_l28_n902()
+ fun_l29_n269
+end
+
+def fun_l28_n903()
+ fun_l29_n626
+end
+
+def fun_l28_n904()
+ fun_l29_n100
+end
+
+def fun_l28_n905()
+ fun_l29_n587
+end
+
+def fun_l28_n906()
+ fun_l29_n841
+end
+
+def fun_l28_n907()
+ fun_l29_n239
+end
+
+def fun_l28_n908()
+ fun_l29_n87
+end
+
+def fun_l28_n909()
+ fun_l29_n765
+end
+
+def fun_l28_n910()
+ fun_l29_n216
+end
+
+def fun_l28_n911()
+ fun_l29_n110
+end
+
+def fun_l28_n912()
+ fun_l29_n96
+end
+
+def fun_l28_n913()
+ fun_l29_n946
+end
+
+def fun_l28_n914()
+ fun_l29_n762
+end
+
+def fun_l28_n915()
+ fun_l29_n697
+end
+
+def fun_l28_n916()
+ fun_l29_n44
+end
+
+def fun_l28_n917()
+ fun_l29_n257
+end
+
+def fun_l28_n918()
+ fun_l29_n195
+end
+
+def fun_l28_n919()
+ fun_l29_n886
+end
+
+def fun_l28_n920()
+ fun_l29_n432
+end
+
+def fun_l28_n921()
+ fun_l29_n746
+end
+
+def fun_l28_n922()
+ fun_l29_n756
+end
+
+def fun_l28_n923()
+ fun_l29_n33
+end
+
+def fun_l28_n924()
+ fun_l29_n720
+end
+
+def fun_l28_n925()
+ fun_l29_n629
+end
+
+def fun_l28_n926()
+ fun_l29_n144
+end
+
+def fun_l28_n927()
+ fun_l29_n225
+end
+
+def fun_l28_n928()
+ fun_l29_n556
+end
+
+def fun_l28_n929()
+ fun_l29_n436
+end
+
+def fun_l28_n930()
+ fun_l29_n380
+end
+
+def fun_l28_n931()
+ fun_l29_n478
+end
+
+def fun_l28_n932()
+ fun_l29_n949
+end
+
+def fun_l28_n933()
+ fun_l29_n811
+end
+
+def fun_l28_n934()
+ fun_l29_n589
+end
+
+def fun_l28_n935()
+ fun_l29_n961
+end
+
+def fun_l28_n936()
+ fun_l29_n413
+end
+
+def fun_l28_n937()
+ fun_l29_n941
+end
+
+def fun_l28_n938()
+ fun_l29_n507
+end
+
+def fun_l28_n939()
+ fun_l29_n364
+end
+
+def fun_l28_n940()
+ fun_l29_n100
+end
+
+def fun_l28_n941()
+ fun_l29_n254
+end
+
+def fun_l28_n942()
+ fun_l29_n272
+end
+
+def fun_l28_n943()
+ fun_l29_n420
+end
+
+def fun_l28_n944()
+ fun_l29_n132
+end
+
+def fun_l28_n945()
+ fun_l29_n907
+end
+
+def fun_l28_n946()
+ fun_l29_n784
+end
+
+def fun_l28_n947()
+ fun_l29_n938
+end
+
+def fun_l28_n948()
+ fun_l29_n780
+end
+
+def fun_l28_n949()
+ fun_l29_n584
+end
+
+def fun_l28_n950()
+ fun_l29_n258
+end
+
+def fun_l28_n951()
+ fun_l29_n754
+end
+
+def fun_l28_n952()
+ fun_l29_n582
+end
+
+def fun_l28_n953()
+ fun_l29_n278
+end
+
+def fun_l28_n954()
+ fun_l29_n870
+end
+
+def fun_l28_n955()
+ fun_l29_n664
+end
+
+def fun_l28_n956()
+ fun_l29_n375
+end
+
+def fun_l28_n957()
+ fun_l29_n613
+end
+
+def fun_l28_n958()
+ fun_l29_n530
+end
+
+def fun_l28_n959()
+ fun_l29_n933
+end
+
+def fun_l28_n960()
+ fun_l29_n298
+end
+
+def fun_l28_n961()
+ fun_l29_n507
+end
+
+def fun_l28_n962()
+ fun_l29_n526
+end
+
+def fun_l28_n963()
+ fun_l29_n508
+end
+
+def fun_l28_n964()
+ fun_l29_n227
+end
+
+def fun_l28_n965()
+ fun_l29_n999
+end
+
+def fun_l28_n966()
+ fun_l29_n489
+end
+
+def fun_l28_n967()
+ fun_l29_n789
+end
+
+def fun_l28_n968()
+ fun_l29_n304
+end
+
+def fun_l28_n969()
+ fun_l29_n343
+end
+
+def fun_l28_n970()
+ fun_l29_n560
+end
+
+def fun_l28_n971()
+ fun_l29_n610
+end
+
+def fun_l28_n972()
+ fun_l29_n606
+end
+
+def fun_l28_n973()
+ fun_l29_n592
+end
+
+def fun_l28_n974()
+ fun_l29_n135
+end
+
+def fun_l28_n975()
+ fun_l29_n513
+end
+
+def fun_l28_n976()
+ fun_l29_n522
+end
+
+def fun_l28_n977()
+ fun_l29_n323
+end
+
+def fun_l28_n978()
+ fun_l29_n26
+end
+
+def fun_l28_n979()
+ fun_l29_n737
+end
+
+def fun_l28_n980()
+ fun_l29_n705
+end
+
+def fun_l28_n981()
+ fun_l29_n405
+end
+
+def fun_l28_n982()
+ fun_l29_n891
+end
+
+def fun_l28_n983()
+ fun_l29_n155
+end
+
+def fun_l28_n984()
+ fun_l29_n814
+end
+
+def fun_l28_n985()
+ fun_l29_n70
+end
+
+def fun_l28_n986()
+ fun_l29_n940
+end
+
+def fun_l28_n987()
+ fun_l29_n427
+end
+
+def fun_l28_n988()
+ fun_l29_n478
+end
+
+def fun_l28_n989()
+ fun_l29_n432
+end
+
+def fun_l28_n990()
+ fun_l29_n320
+end
+
+def fun_l28_n991()
+ fun_l29_n422
+end
+
+def fun_l28_n992()
+ fun_l29_n917
+end
+
+def fun_l28_n993()
+ fun_l29_n391
+end
+
+def fun_l28_n994()
+ fun_l29_n950
+end
+
+def fun_l28_n995()
+ fun_l29_n635
+end
+
+def fun_l28_n996()
+ fun_l29_n392
+end
+
+def fun_l28_n997()
+ fun_l29_n311
+end
+
+def fun_l28_n998()
+ fun_l29_n320
+end
+
+def fun_l28_n999()
+ fun_l29_n916
+end
+
+def fun_l29_n0()
+ inc
+end
+
+def fun_l29_n1()
+ inc
+end
+
+def fun_l29_n2()
+ inc
+end
+
+def fun_l29_n3()
+ inc
+end
+
+def fun_l29_n4()
+ inc
+end
+
+def fun_l29_n5()
+ inc
+end
+
+def fun_l29_n6()
+ inc
+end
+
+def fun_l29_n7()
+ inc
+end
+
+def fun_l29_n8()
+ inc
+end
+
+def fun_l29_n9()
+ inc
+end
+
+def fun_l29_n10()
+ inc
+end
+
+def fun_l29_n11()
+ inc
+end
+
+def fun_l29_n12()
+ inc
+end
+
+def fun_l29_n13()
+ inc
+end
+
+def fun_l29_n14()
+ inc
+end
+
+def fun_l29_n15()
+ inc
+end
+
+def fun_l29_n16()
+ inc
+end
+
+def fun_l29_n17()
+ inc
+end
+
+def fun_l29_n18()
+ inc
+end
+
+def fun_l29_n19()
+ inc
+end
+
+def fun_l29_n20()
+ inc
+end
+
+def fun_l29_n21()
+ inc
+end
+
+def fun_l29_n22()
+ inc
+end
+
+def fun_l29_n23()
+ inc
+end
+
+def fun_l29_n24()
+ inc
+end
+
+def fun_l29_n25()
+ inc
+end
+
+def fun_l29_n26()
+ inc
+end
+
+def fun_l29_n27()
+ inc
+end
+
+def fun_l29_n28()
+ inc
+end
+
+def fun_l29_n29()
+ inc
+end
+
+def fun_l29_n30()
+ inc
+end
+
+def fun_l29_n31()
+ inc
+end
+
+def fun_l29_n32()
+ inc
+end
+
+def fun_l29_n33()
+ inc
+end
+
+def fun_l29_n34()
+ inc
+end
+
+def fun_l29_n35()
+ inc
+end
+
+def fun_l29_n36()
+ inc
+end
+
+def fun_l29_n37()
+ inc
+end
+
+def fun_l29_n38()
+ inc
+end
+
+def fun_l29_n39()
+ inc
+end
+
+def fun_l29_n40()
+ inc
+end
+
+def fun_l29_n41()
+ inc
+end
+
+def fun_l29_n42()
+ inc
+end
+
+def fun_l29_n43()
+ inc
+end
+
+def fun_l29_n44()
+ inc
+end
+
+def fun_l29_n45()
+ inc
+end
+
+def fun_l29_n46()
+ inc
+end
+
+def fun_l29_n47()
+ inc
+end
+
+def fun_l29_n48()
+ inc
+end
+
+def fun_l29_n49()
+ inc
+end
+
+def fun_l29_n50()
+ inc
+end
+
+def fun_l29_n51()
+ inc
+end
+
+def fun_l29_n52()
+ inc
+end
+
+def fun_l29_n53()
+ inc
+end
+
+def fun_l29_n54()
+ inc
+end
+
+def fun_l29_n55()
+ inc
+end
+
+def fun_l29_n56()
+ inc
+end
+
+def fun_l29_n57()
+ inc
+end
+
+def fun_l29_n58()
+ inc
+end
+
+def fun_l29_n59()
+ inc
+end
+
+def fun_l29_n60()
+ inc
+end
+
+def fun_l29_n61()
+ inc
+end
+
+def fun_l29_n62()
+ inc
+end
+
+def fun_l29_n63()
+ inc
+end
+
+def fun_l29_n64()
+ inc
+end
+
+def fun_l29_n65()
+ inc
+end
+
+def fun_l29_n66()
+ inc
+end
+
+def fun_l29_n67()
+ inc
+end
+
+def fun_l29_n68()
+ inc
+end
+
+def fun_l29_n69()
+ inc
+end
+
+def fun_l29_n70()
+ inc
+end
+
+def fun_l29_n71()
+ inc
+end
+
+def fun_l29_n72()
+ inc
+end
+
+def fun_l29_n73()
+ inc
+end
+
+def fun_l29_n74()
+ inc
+end
+
+def fun_l29_n75()
+ inc
+end
+
+def fun_l29_n76()
+ inc
+end
+
+def fun_l29_n77()
+ inc
+end
+
+def fun_l29_n78()
+ inc
+end
+
+def fun_l29_n79()
+ inc
+end
+
+def fun_l29_n80()
+ inc
+end
+
+def fun_l29_n81()
+ inc
+end
+
+def fun_l29_n82()
+ inc
+end
+
+def fun_l29_n83()
+ inc
+end
+
+def fun_l29_n84()
+ inc
+end
+
+def fun_l29_n85()
+ inc
+end
+
+def fun_l29_n86()
+ inc
+end
+
+def fun_l29_n87()
+ inc
+end
+
+def fun_l29_n88()
+ inc
+end
+
+def fun_l29_n89()
+ inc
+end
+
+def fun_l29_n90()
+ inc
+end
+
+def fun_l29_n91()
+ inc
+end
+
+def fun_l29_n92()
+ inc
+end
+
+def fun_l29_n93()
+ inc
+end
+
+def fun_l29_n94()
+ inc
+end
+
+def fun_l29_n95()
+ inc
+end
+
+def fun_l29_n96()
+ inc
+end
+
+def fun_l29_n97()
+ inc
+end
+
+def fun_l29_n98()
+ inc
+end
+
+def fun_l29_n99()
+ inc
+end
+
+def fun_l29_n100()
+ inc
+end
+
+def fun_l29_n101()
+ inc
+end
+
+def fun_l29_n102()
+ inc
+end
+
+def fun_l29_n103()
+ inc
+end
+
+def fun_l29_n104()
+ inc
+end
+
+def fun_l29_n105()
+ inc
+end
+
+def fun_l29_n106()
+ inc
+end
+
+def fun_l29_n107()
+ inc
+end
+
+def fun_l29_n108()
+ inc
+end
+
+def fun_l29_n109()
+ inc
+end
+
+def fun_l29_n110()
+ inc
+end
+
+def fun_l29_n111()
+ inc
+end
+
+def fun_l29_n112()
+ inc
+end
+
+def fun_l29_n113()
+ inc
+end
+
+def fun_l29_n114()
+ inc
+end
+
+def fun_l29_n115()
+ inc
+end
+
+def fun_l29_n116()
+ inc
+end
+
+def fun_l29_n117()
+ inc
+end
+
+def fun_l29_n118()
+ inc
+end
+
+def fun_l29_n119()
+ inc
+end
+
+def fun_l29_n120()
+ inc
+end
+
+def fun_l29_n121()
+ inc
+end
+
+def fun_l29_n122()
+ inc
+end
+
+def fun_l29_n123()
+ inc
+end
+
+def fun_l29_n124()
+ inc
+end
+
+def fun_l29_n125()
+ inc
+end
+
+def fun_l29_n126()
+ inc
+end
+
+def fun_l29_n127()
+ inc
+end
+
+def fun_l29_n128()
+ inc
+end
+
+def fun_l29_n129()
+ inc
+end
+
+def fun_l29_n130()
+ inc
+end
+
+def fun_l29_n131()
+ inc
+end
+
+def fun_l29_n132()
+ inc
+end
+
+def fun_l29_n133()
+ inc
+end
+
+def fun_l29_n134()
+ inc
+end
+
+def fun_l29_n135()
+ inc
+end
+
+def fun_l29_n136()
+ inc
+end
+
+def fun_l29_n137()
+ inc
+end
+
+def fun_l29_n138()
+ inc
+end
+
+def fun_l29_n139()
+ inc
+end
+
+def fun_l29_n140()
+ inc
+end
+
+def fun_l29_n141()
+ inc
+end
+
+def fun_l29_n142()
+ inc
+end
+
+def fun_l29_n143()
+ inc
+end
+
+def fun_l29_n144()
+ inc
+end
+
+def fun_l29_n145()
+ inc
+end
+
+def fun_l29_n146()
+ inc
+end
+
+def fun_l29_n147()
+ inc
+end
+
+def fun_l29_n148()
+ inc
+end
+
+def fun_l29_n149()
+ inc
+end
+
+def fun_l29_n150()
+ inc
+end
+
+def fun_l29_n151()
+ inc
+end
+
+def fun_l29_n152()
+ inc
+end
+
+def fun_l29_n153()
+ inc
+end
+
+def fun_l29_n154()
+ inc
+end
+
+def fun_l29_n155()
+ inc
+end
+
+def fun_l29_n156()
+ inc
+end
+
+def fun_l29_n157()
+ inc
+end
+
+def fun_l29_n158()
+ inc
+end
+
+def fun_l29_n159()
+ inc
+end
+
+def fun_l29_n160()
+ inc
+end
+
+def fun_l29_n161()
+ inc
+end
+
+def fun_l29_n162()
+ inc
+end
+
+def fun_l29_n163()
+ inc
+end
+
+def fun_l29_n164()
+ inc
+end
+
+def fun_l29_n165()
+ inc
+end
+
+def fun_l29_n166()
+ inc
+end
+
+def fun_l29_n167()
+ inc
+end
+
+def fun_l29_n168()
+ inc
+end
+
+def fun_l29_n169()
+ inc
+end
+
+def fun_l29_n170()
+ inc
+end
+
+def fun_l29_n171()
+ inc
+end
+
+def fun_l29_n172()
+ inc
+end
+
+def fun_l29_n173()
+ inc
+end
+
+def fun_l29_n174()
+ inc
+end
+
+def fun_l29_n175()
+ inc
+end
+
+def fun_l29_n176()
+ inc
+end
+
+def fun_l29_n177()
+ inc
+end
+
+def fun_l29_n178()
+ inc
+end
+
+def fun_l29_n179()
+ inc
+end
+
+def fun_l29_n180()
+ inc
+end
+
+def fun_l29_n181()
+ inc
+end
+
+def fun_l29_n182()
+ inc
+end
+
+def fun_l29_n183()
+ inc
+end
+
+def fun_l29_n184()
+ inc
+end
+
+def fun_l29_n185()
+ inc
+end
+
+def fun_l29_n186()
+ inc
+end
+
+def fun_l29_n187()
+ inc
+end
+
+def fun_l29_n188()
+ inc
+end
+
+def fun_l29_n189()
+ inc
+end
+
+def fun_l29_n190()
+ inc
+end
+
+def fun_l29_n191()
+ inc
+end
+
+def fun_l29_n192()
+ inc
+end
+
+def fun_l29_n193()
+ inc
+end
+
+def fun_l29_n194()
+ inc
+end
+
+def fun_l29_n195()
+ inc
+end
+
+def fun_l29_n196()
+ inc
+end
+
+def fun_l29_n197()
+ inc
+end
+
+def fun_l29_n198()
+ inc
+end
+
+def fun_l29_n199()
+ inc
+end
+
+def fun_l29_n200()
+ inc
+end
+
+def fun_l29_n201()
+ inc
+end
+
+def fun_l29_n202()
+ inc
+end
+
+def fun_l29_n203()
+ inc
+end
+
+def fun_l29_n204()
+ inc
+end
+
+def fun_l29_n205()
+ inc
+end
+
+def fun_l29_n206()
+ inc
+end
+
+def fun_l29_n207()
+ inc
+end
+
+def fun_l29_n208()
+ inc
+end
+
+def fun_l29_n209()
+ inc
+end
+
+def fun_l29_n210()
+ inc
+end
+
+def fun_l29_n211()
+ inc
+end
+
+def fun_l29_n212()
+ inc
+end
+
+def fun_l29_n213()
+ inc
+end
+
+def fun_l29_n214()
+ inc
+end
+
+def fun_l29_n215()
+ inc
+end
+
+def fun_l29_n216()
+ inc
+end
+
+def fun_l29_n217()
+ inc
+end
+
+def fun_l29_n218()
+ inc
+end
+
+def fun_l29_n219()
+ inc
+end
+
+def fun_l29_n220()
+ inc
+end
+
+def fun_l29_n221()
+ inc
+end
+
+def fun_l29_n222()
+ inc
+end
+
+def fun_l29_n223()
+ inc
+end
+
+def fun_l29_n224()
+ inc
+end
+
+def fun_l29_n225()
+ inc
+end
+
+def fun_l29_n226()
+ inc
+end
+
+def fun_l29_n227()
+ inc
+end
+
+def fun_l29_n228()
+ inc
+end
+
+def fun_l29_n229()
+ inc
+end
+
+def fun_l29_n230()
+ inc
+end
+
+def fun_l29_n231()
+ inc
+end
+
+def fun_l29_n232()
+ inc
+end
+
+def fun_l29_n233()
+ inc
+end
+
+def fun_l29_n234()
+ inc
+end
+
+def fun_l29_n235()
+ inc
+end
+
+def fun_l29_n236()
+ inc
+end
+
+def fun_l29_n237()
+ inc
+end
+
+def fun_l29_n238()
+ inc
+end
+
+def fun_l29_n239()
+ inc
+end
+
+def fun_l29_n240()
+ inc
+end
+
+def fun_l29_n241()
+ inc
+end
+
+def fun_l29_n242()
+ inc
+end
+
+def fun_l29_n243()
+ inc
+end
+
+def fun_l29_n244()
+ inc
+end
+
+def fun_l29_n245()
+ inc
+end
+
+def fun_l29_n246()
+ inc
+end
+
+def fun_l29_n247()
+ inc
+end
+
+def fun_l29_n248()
+ inc
+end
+
+def fun_l29_n249()
+ inc
+end
+
+def fun_l29_n250()
+ inc
+end
+
+def fun_l29_n251()
+ inc
+end
+
+def fun_l29_n252()
+ inc
+end
+
+def fun_l29_n253()
+ inc
+end
+
+def fun_l29_n254()
+ inc
+end
+
+def fun_l29_n255()
+ inc
+end
+
+def fun_l29_n256()
+ inc
+end
+
+def fun_l29_n257()
+ inc
+end
+
+def fun_l29_n258()
+ inc
+end
+
+def fun_l29_n259()
+ inc
+end
+
+def fun_l29_n260()
+ inc
+end
+
+def fun_l29_n261()
+ inc
+end
+
+def fun_l29_n262()
+ inc
+end
+
+def fun_l29_n263()
+ inc
+end
+
+def fun_l29_n264()
+ inc
+end
+
+def fun_l29_n265()
+ inc
+end
+
+def fun_l29_n266()
+ inc
+end
+
+def fun_l29_n267()
+ inc
+end
+
+def fun_l29_n268()
+ inc
+end
+
+def fun_l29_n269()
+ inc
+end
+
+def fun_l29_n270()
+ inc
+end
+
+def fun_l29_n271()
+ inc
+end
+
+def fun_l29_n272()
+ inc
+end
+
+def fun_l29_n273()
+ inc
+end
+
+def fun_l29_n274()
+ inc
+end
+
+def fun_l29_n275()
+ inc
+end
+
+def fun_l29_n276()
+ inc
+end
+
+def fun_l29_n277()
+ inc
+end
+
+def fun_l29_n278()
+ inc
+end
+
+def fun_l29_n279()
+ inc
+end
+
+def fun_l29_n280()
+ inc
+end
+
+def fun_l29_n281()
+ inc
+end
+
+def fun_l29_n282()
+ inc
+end
+
+def fun_l29_n283()
+ inc
+end
+
+def fun_l29_n284()
+ inc
+end
+
+def fun_l29_n285()
+ inc
+end
+
+def fun_l29_n286()
+ inc
+end
+
+def fun_l29_n287()
+ inc
+end
+
+def fun_l29_n288()
+ inc
+end
+
+def fun_l29_n289()
+ inc
+end
+
+def fun_l29_n290()
+ inc
+end
+
+def fun_l29_n291()
+ inc
+end
+
+def fun_l29_n292()
+ inc
+end
+
+def fun_l29_n293()
+ inc
+end
+
+def fun_l29_n294()
+ inc
+end
+
+def fun_l29_n295()
+ inc
+end
+
+def fun_l29_n296()
+ inc
+end
+
+def fun_l29_n297()
+ inc
+end
+
+def fun_l29_n298()
+ inc
+end
+
+def fun_l29_n299()
+ inc
+end
+
+def fun_l29_n300()
+ inc
+end
+
+def fun_l29_n301()
+ inc
+end
+
+def fun_l29_n302()
+ inc
+end
+
+def fun_l29_n303()
+ inc
+end
+
+def fun_l29_n304()
+ inc
+end
+
+def fun_l29_n305()
+ inc
+end
+
+def fun_l29_n306()
+ inc
+end
+
+def fun_l29_n307()
+ inc
+end
+
+def fun_l29_n308()
+ inc
+end
+
+def fun_l29_n309()
+ inc
+end
+
+def fun_l29_n310()
+ inc
+end
+
+def fun_l29_n311()
+ inc
+end
+
+def fun_l29_n312()
+ inc
+end
+
+def fun_l29_n313()
+ inc
+end
+
+def fun_l29_n314()
+ inc
+end
+
+def fun_l29_n315()
+ inc
+end
+
+def fun_l29_n316()
+ inc
+end
+
+def fun_l29_n317()
+ inc
+end
+
+def fun_l29_n318()
+ inc
+end
+
+def fun_l29_n319()
+ inc
+end
+
+def fun_l29_n320()
+ inc
+end
+
+def fun_l29_n321()
+ inc
+end
+
+def fun_l29_n322()
+ inc
+end
+
+def fun_l29_n323()
+ inc
+end
+
+def fun_l29_n324()
+ inc
+end
+
+def fun_l29_n325()
+ inc
+end
+
+def fun_l29_n326()
+ inc
+end
+
+def fun_l29_n327()
+ inc
+end
+
+def fun_l29_n328()
+ inc
+end
+
+def fun_l29_n329()
+ inc
+end
+
+def fun_l29_n330()
+ inc
+end
+
+def fun_l29_n331()
+ inc
+end
+
+def fun_l29_n332()
+ inc
+end
+
+def fun_l29_n333()
+ inc
+end
+
+def fun_l29_n334()
+ inc
+end
+
+def fun_l29_n335()
+ inc
+end
+
+def fun_l29_n336()
+ inc
+end
+
+def fun_l29_n337()
+ inc
+end
+
+def fun_l29_n338()
+ inc
+end
+
+def fun_l29_n339()
+ inc
+end
+
+def fun_l29_n340()
+ inc
+end
+
+def fun_l29_n341()
+ inc
+end
+
+def fun_l29_n342()
+ inc
+end
+
+def fun_l29_n343()
+ inc
+end
+
+def fun_l29_n344()
+ inc
+end
+
+def fun_l29_n345()
+ inc
+end
+
+def fun_l29_n346()
+ inc
+end
+
+def fun_l29_n347()
+ inc
+end
+
+def fun_l29_n348()
+ inc
+end
+
+def fun_l29_n349()
+ inc
+end
+
+def fun_l29_n350()
+ inc
+end
+
+def fun_l29_n351()
+ inc
+end
+
+def fun_l29_n352()
+ inc
+end
+
+def fun_l29_n353()
+ inc
+end
+
+def fun_l29_n354()
+ inc
+end
+
+def fun_l29_n355()
+ inc
+end
+
+def fun_l29_n356()
+ inc
+end
+
+def fun_l29_n357()
+ inc
+end
+
+def fun_l29_n358()
+ inc
+end
+
+def fun_l29_n359()
+ inc
+end
+
+def fun_l29_n360()
+ inc
+end
+
+def fun_l29_n361()
+ inc
+end
+
+def fun_l29_n362()
+ inc
+end
+
+def fun_l29_n363()
+ inc
+end
+
+def fun_l29_n364()
+ inc
+end
+
+def fun_l29_n365()
+ inc
+end
+
+def fun_l29_n366()
+ inc
+end
+
+def fun_l29_n367()
+ inc
+end
+
+def fun_l29_n368()
+ inc
+end
+
+def fun_l29_n369()
+ inc
+end
+
+def fun_l29_n370()
+ inc
+end
+
+def fun_l29_n371()
+ inc
+end
+
+def fun_l29_n372()
+ inc
+end
+
+def fun_l29_n373()
+ inc
+end
+
+def fun_l29_n374()
+ inc
+end
+
+def fun_l29_n375()
+ inc
+end
+
+def fun_l29_n376()
+ inc
+end
+
+def fun_l29_n377()
+ inc
+end
+
+def fun_l29_n378()
+ inc
+end
+
+def fun_l29_n379()
+ inc
+end
+
+def fun_l29_n380()
+ inc
+end
+
+def fun_l29_n381()
+ inc
+end
+
+def fun_l29_n382()
+ inc
+end
+
+def fun_l29_n383()
+ inc
+end
+
+def fun_l29_n384()
+ inc
+end
+
+def fun_l29_n385()
+ inc
+end
+
+def fun_l29_n386()
+ inc
+end
+
+def fun_l29_n387()
+ inc
+end
+
+def fun_l29_n388()
+ inc
+end
+
+def fun_l29_n389()
+ inc
+end
+
+def fun_l29_n390()
+ inc
+end
+
+def fun_l29_n391()
+ inc
+end
+
+def fun_l29_n392()
+ inc
+end
+
+def fun_l29_n393()
+ inc
+end
+
+def fun_l29_n394()
+ inc
+end
+
+def fun_l29_n395()
+ inc
+end
+
+def fun_l29_n396()
+ inc
+end
+
+def fun_l29_n397()
+ inc
+end
+
+def fun_l29_n398()
+ inc
+end
+
+def fun_l29_n399()
+ inc
+end
+
+def fun_l29_n400()
+ inc
+end
+
+def fun_l29_n401()
+ inc
+end
+
+def fun_l29_n402()
+ inc
+end
+
+def fun_l29_n403()
+ inc
+end
+
+def fun_l29_n404()
+ inc
+end
+
+def fun_l29_n405()
+ inc
+end
+
+def fun_l29_n406()
+ inc
+end
+
+def fun_l29_n407()
+ inc
+end
+
+def fun_l29_n408()
+ inc
+end
+
+def fun_l29_n409()
+ inc
+end
+
+def fun_l29_n410()
+ inc
+end
+
+def fun_l29_n411()
+ inc
+end
+
+def fun_l29_n412()
+ inc
+end
+
+def fun_l29_n413()
+ inc
+end
+
+def fun_l29_n414()
+ inc
+end
+
+def fun_l29_n415()
+ inc
+end
+
+def fun_l29_n416()
+ inc
+end
+
+def fun_l29_n417()
+ inc
+end
+
+def fun_l29_n418()
+ inc
+end
+
+def fun_l29_n419()
+ inc
+end
+
+def fun_l29_n420()
+ inc
+end
+
+def fun_l29_n421()
+ inc
+end
+
+def fun_l29_n422()
+ inc
+end
+
+def fun_l29_n423()
+ inc
+end
+
+def fun_l29_n424()
+ inc
+end
+
+def fun_l29_n425()
+ inc
+end
+
+def fun_l29_n426()
+ inc
+end
+
+def fun_l29_n427()
+ inc
+end
+
+def fun_l29_n428()
+ inc
+end
+
+def fun_l29_n429()
+ inc
+end
+
+def fun_l29_n430()
+ inc
+end
+
+def fun_l29_n431()
+ inc
+end
+
+def fun_l29_n432()
+ inc
+end
+
+def fun_l29_n433()
+ inc
+end
+
+def fun_l29_n434()
+ inc
+end
+
+def fun_l29_n435()
+ inc
+end
+
+def fun_l29_n436()
+ inc
+end
+
+def fun_l29_n437()
+ inc
+end
+
+def fun_l29_n438()
+ inc
+end
+
+def fun_l29_n439()
+ inc
+end
+
+def fun_l29_n440()
+ inc
+end
+
+def fun_l29_n441()
+ inc
+end
+
+def fun_l29_n442()
+ inc
+end
+
+def fun_l29_n443()
+ inc
+end
+
+def fun_l29_n444()
+ inc
+end
+
+def fun_l29_n445()
+ inc
+end
+
+def fun_l29_n446()
+ inc
+end
+
+def fun_l29_n447()
+ inc
+end
+
+def fun_l29_n448()
+ inc
+end
+
+def fun_l29_n449()
+ inc
+end
+
+def fun_l29_n450()
+ inc
+end
+
+def fun_l29_n451()
+ inc
+end
+
+def fun_l29_n452()
+ inc
+end
+
+def fun_l29_n453()
+ inc
+end
+
+def fun_l29_n454()
+ inc
+end
+
+def fun_l29_n455()
+ inc
+end
+
+def fun_l29_n456()
+ inc
+end
+
+def fun_l29_n457()
+ inc
+end
+
+def fun_l29_n458()
+ inc
+end
+
+def fun_l29_n459()
+ inc
+end
+
+def fun_l29_n460()
+ inc
+end
+
+def fun_l29_n461()
+ inc
+end
+
+def fun_l29_n462()
+ inc
+end
+
+def fun_l29_n463()
+ inc
+end
+
+def fun_l29_n464()
+ inc
+end
+
+def fun_l29_n465()
+ inc
+end
+
+def fun_l29_n466()
+ inc
+end
+
+def fun_l29_n467()
+ inc
+end
+
+def fun_l29_n468()
+ inc
+end
+
+def fun_l29_n469()
+ inc
+end
+
+def fun_l29_n470()
+ inc
+end
+
+def fun_l29_n471()
+ inc
+end
+
+def fun_l29_n472()
+ inc
+end
+
+def fun_l29_n473()
+ inc
+end
+
+def fun_l29_n474()
+ inc
+end
+
+def fun_l29_n475()
+ inc
+end
+
+def fun_l29_n476()
+ inc
+end
+
+def fun_l29_n477()
+ inc
+end
+
+def fun_l29_n478()
+ inc
+end
+
+def fun_l29_n479()
+ inc
+end
+
+def fun_l29_n480()
+ inc
+end
+
+def fun_l29_n481()
+ inc
+end
+
+def fun_l29_n482()
+ inc
+end
+
+def fun_l29_n483()
+ inc
+end
+
+def fun_l29_n484()
+ inc
+end
+
+def fun_l29_n485()
+ inc
+end
+
+def fun_l29_n486()
+ inc
+end
+
+def fun_l29_n487()
+ inc
+end
+
+def fun_l29_n488()
+ inc
+end
+
+def fun_l29_n489()
+ inc
+end
+
+def fun_l29_n490()
+ inc
+end
+
+def fun_l29_n491()
+ inc
+end
+
+def fun_l29_n492()
+ inc
+end
+
+def fun_l29_n493()
+ inc
+end
+
+def fun_l29_n494()
+ inc
+end
+
+def fun_l29_n495()
+ inc
+end
+
+def fun_l29_n496()
+ inc
+end
+
+def fun_l29_n497()
+ inc
+end
+
+def fun_l29_n498()
+ inc
+end
+
+def fun_l29_n499()
+ inc
+end
+
+def fun_l29_n500()
+ inc
+end
+
+def fun_l29_n501()
+ inc
+end
+
+def fun_l29_n502()
+ inc
+end
+
+def fun_l29_n503()
+ inc
+end
+
+def fun_l29_n504()
+ inc
+end
+
+def fun_l29_n505()
+ inc
+end
+
+def fun_l29_n506()
+ inc
+end
+
+def fun_l29_n507()
+ inc
+end
+
+def fun_l29_n508()
+ inc
+end
+
+def fun_l29_n509()
+ inc
+end
+
+def fun_l29_n510()
+ inc
+end
+
+def fun_l29_n511()
+ inc
+end
+
+def fun_l29_n512()
+ inc
+end
+
+def fun_l29_n513()
+ inc
+end
+
+def fun_l29_n514()
+ inc
+end
+
+def fun_l29_n515()
+ inc
+end
+
+def fun_l29_n516()
+ inc
+end
+
+def fun_l29_n517()
+ inc
+end
+
+def fun_l29_n518()
+ inc
+end
+
+def fun_l29_n519()
+ inc
+end
+
+def fun_l29_n520()
+ inc
+end
+
+def fun_l29_n521()
+ inc
+end
+
+def fun_l29_n522()
+ inc
+end
+
+def fun_l29_n523()
+ inc
+end
+
+def fun_l29_n524()
+ inc
+end
+
+def fun_l29_n525()
+ inc
+end
+
+def fun_l29_n526()
+ inc
+end
+
+def fun_l29_n527()
+ inc
+end
+
+def fun_l29_n528()
+ inc
+end
+
+def fun_l29_n529()
+ inc
+end
+
+def fun_l29_n530()
+ inc
+end
+
+def fun_l29_n531()
+ inc
+end
+
+def fun_l29_n532()
+ inc
+end
+
+def fun_l29_n533()
+ inc
+end
+
+def fun_l29_n534()
+ inc
+end
+
+def fun_l29_n535()
+ inc
+end
+
+def fun_l29_n536()
+ inc
+end
+
+def fun_l29_n537()
+ inc
+end
+
+def fun_l29_n538()
+ inc
+end
+
+def fun_l29_n539()
+ inc
+end
+
+def fun_l29_n540()
+ inc
+end
+
+def fun_l29_n541()
+ inc
+end
+
+def fun_l29_n542()
+ inc
+end
+
+def fun_l29_n543()
+ inc
+end
+
+def fun_l29_n544()
+ inc
+end
+
+def fun_l29_n545()
+ inc
+end
+
+def fun_l29_n546()
+ inc
+end
+
+def fun_l29_n547()
+ inc
+end
+
+def fun_l29_n548()
+ inc
+end
+
+def fun_l29_n549()
+ inc
+end
+
+def fun_l29_n550()
+ inc
+end
+
+def fun_l29_n551()
+ inc
+end
+
+def fun_l29_n552()
+ inc
+end
+
+def fun_l29_n553()
+ inc
+end
+
+def fun_l29_n554()
+ inc
+end
+
+def fun_l29_n555()
+ inc
+end
+
+def fun_l29_n556()
+ inc
+end
+
+def fun_l29_n557()
+ inc
+end
+
+def fun_l29_n558()
+ inc
+end
+
+def fun_l29_n559()
+ inc
+end
+
+def fun_l29_n560()
+ inc
+end
+
+def fun_l29_n561()
+ inc
+end
+
+def fun_l29_n562()
+ inc
+end
+
+def fun_l29_n563()
+ inc
+end
+
+def fun_l29_n564()
+ inc
+end
+
+def fun_l29_n565()
+ inc
+end
+
+def fun_l29_n566()
+ inc
+end
+
+def fun_l29_n567()
+ inc
+end
+
+def fun_l29_n568()
+ inc
+end
+
+def fun_l29_n569()
+ inc
+end
+
+def fun_l29_n570()
+ inc
+end
+
+def fun_l29_n571()
+ inc
+end
+
+def fun_l29_n572()
+ inc
+end
+
+def fun_l29_n573()
+ inc
+end
+
+def fun_l29_n574()
+ inc
+end
+
+def fun_l29_n575()
+ inc
+end
+
+def fun_l29_n576()
+ inc
+end
+
+def fun_l29_n577()
+ inc
+end
+
+def fun_l29_n578()
+ inc
+end
+
+def fun_l29_n579()
+ inc
+end
+
+def fun_l29_n580()
+ inc
+end
+
+def fun_l29_n581()
+ inc
+end
+
+def fun_l29_n582()
+ inc
+end
+
+def fun_l29_n583()
+ inc
+end
+
+def fun_l29_n584()
+ inc
+end
+
+def fun_l29_n585()
+ inc
+end
+
+def fun_l29_n586()
+ inc
+end
+
+def fun_l29_n587()
+ inc
+end
+
+def fun_l29_n588()
+ inc
+end
+
+def fun_l29_n589()
+ inc
+end
+
+def fun_l29_n590()
+ inc
+end
+
+def fun_l29_n591()
+ inc
+end
+
+def fun_l29_n592()
+ inc
+end
+
+def fun_l29_n593()
+ inc
+end
+
+def fun_l29_n594()
+ inc
+end
+
+def fun_l29_n595()
+ inc
+end
+
+def fun_l29_n596()
+ inc
+end
+
+def fun_l29_n597()
+ inc
+end
+
+def fun_l29_n598()
+ inc
+end
+
+def fun_l29_n599()
+ inc
+end
+
+def fun_l29_n600()
+ inc
+end
+
+def fun_l29_n601()
+ inc
+end
+
+def fun_l29_n602()
+ inc
+end
+
+def fun_l29_n603()
+ inc
+end
+
+def fun_l29_n604()
+ inc
+end
+
+def fun_l29_n605()
+ inc
+end
+
+def fun_l29_n606()
+ inc
+end
+
+def fun_l29_n607()
+ inc
+end
+
+def fun_l29_n608()
+ inc
+end
+
+def fun_l29_n609()
+ inc
+end
+
+def fun_l29_n610()
+ inc
+end
+
+def fun_l29_n611()
+ inc
+end
+
+def fun_l29_n612()
+ inc
+end
+
+def fun_l29_n613()
+ inc
+end
+
+def fun_l29_n614()
+ inc
+end
+
+def fun_l29_n615()
+ inc
+end
+
+def fun_l29_n616()
+ inc
+end
+
+def fun_l29_n617()
+ inc
+end
+
+def fun_l29_n618()
+ inc
+end
+
+def fun_l29_n619()
+ inc
+end
+
+def fun_l29_n620()
+ inc
+end
+
+def fun_l29_n621()
+ inc
+end
+
+def fun_l29_n622()
+ inc
+end
+
+def fun_l29_n623()
+ inc
+end
+
+def fun_l29_n624()
+ inc
+end
+
+def fun_l29_n625()
+ inc
+end
+
+def fun_l29_n626()
+ inc
+end
+
+def fun_l29_n627()
+ inc
+end
+
+def fun_l29_n628()
+ inc
+end
+
+def fun_l29_n629()
+ inc
+end
+
+def fun_l29_n630()
+ inc
+end
+
+def fun_l29_n631()
+ inc
+end
+
+def fun_l29_n632()
+ inc
+end
+
+def fun_l29_n633()
+ inc
+end
+
+def fun_l29_n634()
+ inc
+end
+
+def fun_l29_n635()
+ inc
+end
+
+def fun_l29_n636()
+ inc
+end
+
+def fun_l29_n637()
+ inc
+end
+
+def fun_l29_n638()
+ inc
+end
+
+def fun_l29_n639()
+ inc
+end
+
+def fun_l29_n640()
+ inc
+end
+
+def fun_l29_n641()
+ inc
+end
+
+def fun_l29_n642()
+ inc
+end
+
+def fun_l29_n643()
+ inc
+end
+
+def fun_l29_n644()
+ inc
+end
+
+def fun_l29_n645()
+ inc
+end
+
+def fun_l29_n646()
+ inc
+end
+
+def fun_l29_n647()
+ inc
+end
+
+def fun_l29_n648()
+ inc
+end
+
+def fun_l29_n649()
+ inc
+end
+
+def fun_l29_n650()
+ inc
+end
+
+def fun_l29_n651()
+ inc
+end
+
+def fun_l29_n652()
+ inc
+end
+
+def fun_l29_n653()
+ inc
+end
+
+def fun_l29_n654()
+ inc
+end
+
+def fun_l29_n655()
+ inc
+end
+
+def fun_l29_n656()
+ inc
+end
+
+def fun_l29_n657()
+ inc
+end
+
+def fun_l29_n658()
+ inc
+end
+
+def fun_l29_n659()
+ inc
+end
+
+def fun_l29_n660()
+ inc
+end
+
+def fun_l29_n661()
+ inc
+end
+
+def fun_l29_n662()
+ inc
+end
+
+def fun_l29_n663()
+ inc
+end
+
+def fun_l29_n664()
+ inc
+end
+
+def fun_l29_n665()
+ inc
+end
+
+def fun_l29_n666()
+ inc
+end
+
+def fun_l29_n667()
+ inc
+end
+
+def fun_l29_n668()
+ inc
+end
+
+def fun_l29_n669()
+ inc
+end
+
+def fun_l29_n670()
+ inc
+end
+
+def fun_l29_n671()
+ inc
+end
+
+def fun_l29_n672()
+ inc
+end
+
+def fun_l29_n673()
+ inc
+end
+
+def fun_l29_n674()
+ inc
+end
+
+def fun_l29_n675()
+ inc
+end
+
+def fun_l29_n676()
+ inc
+end
+
+def fun_l29_n677()
+ inc
+end
+
+def fun_l29_n678()
+ inc
+end
+
+def fun_l29_n679()
+ inc
+end
+
+def fun_l29_n680()
+ inc
+end
+
+def fun_l29_n681()
+ inc
+end
+
+def fun_l29_n682()
+ inc
+end
+
+def fun_l29_n683()
+ inc
+end
+
+def fun_l29_n684()
+ inc
+end
+
+def fun_l29_n685()
+ inc
+end
+
+def fun_l29_n686()
+ inc
+end
+
+def fun_l29_n687()
+ inc
+end
+
+def fun_l29_n688()
+ inc
+end
+
+def fun_l29_n689()
+ inc
+end
+
+def fun_l29_n690()
+ inc
+end
+
+def fun_l29_n691()
+ inc
+end
+
+def fun_l29_n692()
+ inc
+end
+
+def fun_l29_n693()
+ inc
+end
+
+def fun_l29_n694()
+ inc
+end
+
+def fun_l29_n695()
+ inc
+end
+
+def fun_l29_n696()
+ inc
+end
+
+def fun_l29_n697()
+ inc
+end
+
+def fun_l29_n698()
+ inc
+end
+
+def fun_l29_n699()
+ inc
+end
+
+def fun_l29_n700()
+ inc
+end
+
+def fun_l29_n701()
+ inc
+end
+
+def fun_l29_n702()
+ inc
+end
+
+def fun_l29_n703()
+ inc
+end
+
+def fun_l29_n704()
+ inc
+end
+
+def fun_l29_n705()
+ inc
+end
+
+def fun_l29_n706()
+ inc
+end
+
+def fun_l29_n707()
+ inc
+end
+
+def fun_l29_n708()
+ inc
+end
+
+def fun_l29_n709()
+ inc
+end
+
+def fun_l29_n710()
+ inc
+end
+
+def fun_l29_n711()
+ inc
+end
+
+def fun_l29_n712()
+ inc
+end
+
+def fun_l29_n713()
+ inc
+end
+
+def fun_l29_n714()
+ inc
+end
+
+def fun_l29_n715()
+ inc
+end
+
+def fun_l29_n716()
+ inc
+end
+
+def fun_l29_n717()
+ inc
+end
+
+def fun_l29_n718()
+ inc
+end
+
+def fun_l29_n719()
+ inc
+end
+
+def fun_l29_n720()
+ inc
+end
+
+def fun_l29_n721()
+ inc
+end
+
+def fun_l29_n722()
+ inc
+end
+
+def fun_l29_n723()
+ inc
+end
+
+def fun_l29_n724()
+ inc
+end
+
+def fun_l29_n725()
+ inc
+end
+
+def fun_l29_n726()
+ inc
+end
+
+def fun_l29_n727()
+ inc
+end
+
+def fun_l29_n728()
+ inc
+end
+
+def fun_l29_n729()
+ inc
+end
+
+def fun_l29_n730()
+ inc
+end
+
+def fun_l29_n731()
+ inc
+end
+
+def fun_l29_n732()
+ inc
+end
+
+def fun_l29_n733()
+ inc
+end
+
+def fun_l29_n734()
+ inc
+end
+
+def fun_l29_n735()
+ inc
+end
+
+def fun_l29_n736()
+ inc
+end
+
+def fun_l29_n737()
+ inc
+end
+
+def fun_l29_n738()
+ inc
+end
+
+def fun_l29_n739()
+ inc
+end
+
+def fun_l29_n740()
+ inc
+end
+
+def fun_l29_n741()
+ inc
+end
+
+def fun_l29_n742()
+ inc
+end
+
+def fun_l29_n743()
+ inc
+end
+
+def fun_l29_n744()
+ inc
+end
+
+def fun_l29_n745()
+ inc
+end
+
+def fun_l29_n746()
+ inc
+end
+
+def fun_l29_n747()
+ inc
+end
+
+def fun_l29_n748()
+ inc
+end
+
+def fun_l29_n749()
+ inc
+end
+
+def fun_l29_n750()
+ inc
+end
+
+def fun_l29_n751()
+ inc
+end
+
+def fun_l29_n752()
+ inc
+end
+
+def fun_l29_n753()
+ inc
+end
+
+def fun_l29_n754()
+ inc
+end
+
+def fun_l29_n755()
+ inc
+end
+
+def fun_l29_n756()
+ inc
+end
+
+def fun_l29_n757()
+ inc
+end
+
+def fun_l29_n758()
+ inc
+end
+
+def fun_l29_n759()
+ inc
+end
+
+def fun_l29_n760()
+ inc
+end
+
+def fun_l29_n761()
+ inc
+end
+
+def fun_l29_n762()
+ inc
+end
+
+def fun_l29_n763()
+ inc
+end
+
+def fun_l29_n764()
+ inc
+end
+
+def fun_l29_n765()
+ inc
+end
+
+def fun_l29_n766()
+ inc
+end
+
+def fun_l29_n767()
+ inc
+end
+
+def fun_l29_n768()
+ inc
+end
+
+def fun_l29_n769()
+ inc
+end
+
+def fun_l29_n770()
+ inc
+end
+
+def fun_l29_n771()
+ inc
+end
+
+def fun_l29_n772()
+ inc
+end
+
+def fun_l29_n773()
+ inc
+end
+
+def fun_l29_n774()
+ inc
+end
+
+def fun_l29_n775()
+ inc
+end
+
+def fun_l29_n776()
+ inc
+end
+
+def fun_l29_n777()
+ inc
+end
+
+def fun_l29_n778()
+ inc
+end
+
+def fun_l29_n779()
+ inc
+end
+
+def fun_l29_n780()
+ inc
+end
+
+def fun_l29_n781()
+ inc
+end
+
+def fun_l29_n782()
+ inc
+end
+
+def fun_l29_n783()
+ inc
+end
+
+def fun_l29_n784()
+ inc
+end
+
+def fun_l29_n785()
+ inc
+end
+
+def fun_l29_n786()
+ inc
+end
+
+def fun_l29_n787()
+ inc
+end
+
+def fun_l29_n788()
+ inc
+end
+
+def fun_l29_n789()
+ inc
+end
+
+def fun_l29_n790()
+ inc
+end
+
+def fun_l29_n791()
+ inc
+end
+
+def fun_l29_n792()
+ inc
+end
+
+def fun_l29_n793()
+ inc
+end
+
+def fun_l29_n794()
+ inc
+end
+
+def fun_l29_n795()
+ inc
+end
+
+def fun_l29_n796()
+ inc
+end
+
+def fun_l29_n797()
+ inc
+end
+
+def fun_l29_n798()
+ inc
+end
+
+def fun_l29_n799()
+ inc
+end
+
+def fun_l29_n800()
+ inc
+end
+
+def fun_l29_n801()
+ inc
+end
+
+def fun_l29_n802()
+ inc
+end
+
+def fun_l29_n803()
+ inc
+end
+
+def fun_l29_n804()
+ inc
+end
+
+def fun_l29_n805()
+ inc
+end
+
+def fun_l29_n806()
+ inc
+end
+
+def fun_l29_n807()
+ inc
+end
+
+def fun_l29_n808()
+ inc
+end
+
+def fun_l29_n809()
+ inc
+end
+
+def fun_l29_n810()
+ inc
+end
+
+def fun_l29_n811()
+ inc
+end
+
+def fun_l29_n812()
+ inc
+end
+
+def fun_l29_n813()
+ inc
+end
+
+def fun_l29_n814()
+ inc
+end
+
+def fun_l29_n815()
+ inc
+end
+
+def fun_l29_n816()
+ inc
+end
+
+def fun_l29_n817()
+ inc
+end
+
+def fun_l29_n818()
+ inc
+end
+
+def fun_l29_n819()
+ inc
+end
+
+def fun_l29_n820()
+ inc
+end
+
+def fun_l29_n821()
+ inc
+end
+
+def fun_l29_n822()
+ inc
+end
+
+def fun_l29_n823()
+ inc
+end
+
+def fun_l29_n824()
+ inc
+end
+
+def fun_l29_n825()
+ inc
+end
+
+def fun_l29_n826()
+ inc
+end
+
+def fun_l29_n827()
+ inc
+end
+
+def fun_l29_n828()
+ inc
+end
+
+def fun_l29_n829()
+ inc
+end
+
+def fun_l29_n830()
+ inc
+end
+
+def fun_l29_n831()
+ inc
+end
+
+def fun_l29_n832()
+ inc
+end
+
+def fun_l29_n833()
+ inc
+end
+
+def fun_l29_n834()
+ inc
+end
+
+def fun_l29_n835()
+ inc
+end
+
+def fun_l29_n836()
+ inc
+end
+
+def fun_l29_n837()
+ inc
+end
+
+def fun_l29_n838()
+ inc
+end
+
+def fun_l29_n839()
+ inc
+end
+
+def fun_l29_n840()
+ inc
+end
+
+def fun_l29_n841()
+ inc
+end
+
+def fun_l29_n842()
+ inc
+end
+
+def fun_l29_n843()
+ inc
+end
+
+def fun_l29_n844()
+ inc
+end
+
+def fun_l29_n845()
+ inc
+end
+
+def fun_l29_n846()
+ inc
+end
+
+def fun_l29_n847()
+ inc
+end
+
+def fun_l29_n848()
+ inc
+end
+
+def fun_l29_n849()
+ inc
+end
+
+def fun_l29_n850()
+ inc
+end
+
+def fun_l29_n851()
+ inc
+end
+
+def fun_l29_n852()
+ inc
+end
+
+def fun_l29_n853()
+ inc
+end
+
+def fun_l29_n854()
+ inc
+end
+
+def fun_l29_n855()
+ inc
+end
+
+def fun_l29_n856()
+ inc
+end
+
+def fun_l29_n857()
+ inc
+end
+
+def fun_l29_n858()
+ inc
+end
+
+def fun_l29_n859()
+ inc
+end
+
+def fun_l29_n860()
+ inc
+end
+
+def fun_l29_n861()
+ inc
+end
+
+def fun_l29_n862()
+ inc
+end
+
+def fun_l29_n863()
+ inc
+end
+
+def fun_l29_n864()
+ inc
+end
+
+def fun_l29_n865()
+ inc
+end
+
+def fun_l29_n866()
+ inc
+end
+
+def fun_l29_n867()
+ inc
+end
+
+def fun_l29_n868()
+ inc
+end
+
+def fun_l29_n869()
+ inc
+end
+
+def fun_l29_n870()
+ inc
+end
+
+def fun_l29_n871()
+ inc
+end
+
+def fun_l29_n872()
+ inc
+end
+
+def fun_l29_n873()
+ inc
+end
+
+def fun_l29_n874()
+ inc
+end
+
+def fun_l29_n875()
+ inc
+end
+
+def fun_l29_n876()
+ inc
+end
+
+def fun_l29_n877()
+ inc
+end
+
+def fun_l29_n878()
+ inc
+end
+
+def fun_l29_n879()
+ inc
+end
+
+def fun_l29_n880()
+ inc
+end
+
+def fun_l29_n881()
+ inc
+end
+
+def fun_l29_n882()
+ inc
+end
+
+def fun_l29_n883()
+ inc
+end
+
+def fun_l29_n884()
+ inc
+end
+
+def fun_l29_n885()
+ inc
+end
+
+def fun_l29_n886()
+ inc
+end
+
+def fun_l29_n887()
+ inc
+end
+
+def fun_l29_n888()
+ inc
+end
+
+def fun_l29_n889()
+ inc
+end
+
+def fun_l29_n890()
+ inc
+end
+
+def fun_l29_n891()
+ inc
+end
+
+def fun_l29_n892()
+ inc
+end
+
+def fun_l29_n893()
+ inc
+end
+
+def fun_l29_n894()
+ inc
+end
+
+def fun_l29_n895()
+ inc
+end
+
+def fun_l29_n896()
+ inc
+end
+
+def fun_l29_n897()
+ inc
+end
+
+def fun_l29_n898()
+ inc
+end
+
+def fun_l29_n899()
+ inc
+end
+
+def fun_l29_n900()
+ inc
+end
+
+def fun_l29_n901()
+ inc
+end
+
+def fun_l29_n902()
+ inc
+end
+
+def fun_l29_n903()
+ inc
+end
+
+def fun_l29_n904()
+ inc
+end
+
+def fun_l29_n905()
+ inc
+end
+
+def fun_l29_n906()
+ inc
+end
+
+def fun_l29_n907()
+ inc
+end
+
+def fun_l29_n908()
+ inc
+end
+
+def fun_l29_n909()
+ inc
+end
+
+def fun_l29_n910()
+ inc
+end
+
+def fun_l29_n911()
+ inc
+end
+
+def fun_l29_n912()
+ inc
+end
+
+def fun_l29_n913()
+ inc
+end
+
+def fun_l29_n914()
+ inc
+end
+
+def fun_l29_n915()
+ inc
+end
+
+def fun_l29_n916()
+ inc
+end
+
+def fun_l29_n917()
+ inc
+end
+
+def fun_l29_n918()
+ inc
+end
+
+def fun_l29_n919()
+ inc
+end
+
+def fun_l29_n920()
+ inc
+end
+
+def fun_l29_n921()
+ inc
+end
+
+def fun_l29_n922()
+ inc
+end
+
+def fun_l29_n923()
+ inc
+end
+
+def fun_l29_n924()
+ inc
+end
+
+def fun_l29_n925()
+ inc
+end
+
+def fun_l29_n926()
+ inc
+end
+
+def fun_l29_n927()
+ inc
+end
+
+def fun_l29_n928()
+ inc
+end
+
+def fun_l29_n929()
+ inc
+end
+
+def fun_l29_n930()
+ inc
+end
+
+def fun_l29_n931()
+ inc
+end
+
+def fun_l29_n932()
+ inc
+end
+
+def fun_l29_n933()
+ inc
+end
+
+def fun_l29_n934()
+ inc
+end
+
+def fun_l29_n935()
+ inc
+end
+
+def fun_l29_n936()
+ inc
+end
+
+def fun_l29_n937()
+ inc
+end
+
+def fun_l29_n938()
+ inc
+end
+
+def fun_l29_n939()
+ inc
+end
+
+def fun_l29_n940()
+ inc
+end
+
+def fun_l29_n941()
+ inc
+end
+
+def fun_l29_n942()
+ inc
+end
+
+def fun_l29_n943()
+ inc
+end
+
+def fun_l29_n944()
+ inc
+end
+
+def fun_l29_n945()
+ inc
+end
+
+def fun_l29_n946()
+ inc
+end
+
+def fun_l29_n947()
+ inc
+end
+
+def fun_l29_n948()
+ inc
+end
+
+def fun_l29_n949()
+ inc
+end
+
+def fun_l29_n950()
+ inc
+end
+
+def fun_l29_n951()
+ inc
+end
+
+def fun_l29_n952()
+ inc
+end
+
+def fun_l29_n953()
+ inc
+end
+
+def fun_l29_n954()
+ inc
+end
+
+def fun_l29_n955()
+ inc
+end
+
+def fun_l29_n956()
+ inc
+end
+
+def fun_l29_n957()
+ inc
+end
+
+def fun_l29_n958()
+ inc
+end
+
+def fun_l29_n959()
+ inc
+end
+
+def fun_l29_n960()
+ inc
+end
+
+def fun_l29_n961()
+ inc
+end
+
+def fun_l29_n962()
+ inc
+end
+
+def fun_l29_n963()
+ inc
+end
+
+def fun_l29_n964()
+ inc
+end
+
+def fun_l29_n965()
+ inc
+end
+
+def fun_l29_n966()
+ inc
+end
+
+def fun_l29_n967()
+ inc
+end
+
+def fun_l29_n968()
+ inc
+end
+
+def fun_l29_n969()
+ inc
+end
+
+def fun_l29_n970()
+ inc
+end
+
+def fun_l29_n971()
+ inc
+end
+
+def fun_l29_n972()
+ inc
+end
+
+def fun_l29_n973()
+ inc
+end
+
+def fun_l29_n974()
+ inc
+end
+
+def fun_l29_n975()
+ inc
+end
+
+def fun_l29_n976()
+ inc
+end
+
+def fun_l29_n977()
+ inc
+end
+
+def fun_l29_n978()
+ inc
+end
+
+def fun_l29_n979()
+ inc
+end
+
+def fun_l29_n980()
+ inc
+end
+
+def fun_l29_n981()
+ inc
+end
+
+def fun_l29_n982()
+ inc
+end
+
+def fun_l29_n983()
+ inc
+end
+
+def fun_l29_n984()
+ inc
+end
+
+def fun_l29_n985()
+ inc
+end
+
+def fun_l29_n986()
+ inc
+end
+
+def fun_l29_n987()
+ inc
+end
+
+def fun_l29_n988()
+ inc
+end
+
+def fun_l29_n989()
+ inc
+end
+
+def fun_l29_n990()
+ inc
+end
+
+def fun_l29_n991()
+ inc
+end
+
+def fun_l29_n992()
+ inc
+end
+
+def fun_l29_n993()
+ inc
+end
+
+def fun_l29_n994()
+ inc
+end
+
+def fun_l29_n995()
+ inc
+end
+
+def fun_l29_n996()
+ inc
+end
+
+def fun_l29_n997()
+ inc
+end
+
+def fun_l29_n998()
+ inc
+end
+
+def fun_l29_n999()
+ inc
+end
+
+@a = 0
+@b = 0
+@c = 0
+@d = 0
+@count = 0
+def inc()
+ @count += 1
+end
+1000.times do
+ fun_l0_n0
+ fun_l0_n1
+ fun_l0_n2
+ fun_l0_n3
+ fun_l0_n4
+ fun_l0_n5
+ fun_l0_n6
+ fun_l0_n7
+ fun_l0_n8
+ fun_l0_n9
+ fun_l0_n10
+ fun_l0_n11
+ fun_l0_n12
+ fun_l0_n13
+ fun_l0_n14
+ fun_l0_n15
+ fun_l0_n16
+ fun_l0_n17
+ fun_l0_n18
+ fun_l0_n19
+ fun_l0_n20
+ fun_l0_n21
+ fun_l0_n22
+ fun_l0_n23
+ fun_l0_n24
+ fun_l0_n25
+ fun_l0_n26
+ fun_l0_n27
+ fun_l0_n28
+ fun_l0_n29
+ fun_l0_n30
+ fun_l0_n31
+ fun_l0_n32
+ fun_l0_n33
+ fun_l0_n34
+ fun_l0_n35
+ fun_l0_n36
+ fun_l0_n37
+ fun_l0_n38
+ fun_l0_n39
+ fun_l0_n40
+ fun_l0_n41
+ fun_l0_n42
+ fun_l0_n43
+ fun_l0_n44
+ fun_l0_n45
+ fun_l0_n46
+ fun_l0_n47
+ fun_l0_n48
+ fun_l0_n49
+ fun_l0_n50
+ fun_l0_n51
+ fun_l0_n52
+ fun_l0_n53
+ fun_l0_n54
+ fun_l0_n55
+ fun_l0_n56
+ fun_l0_n57
+ fun_l0_n58
+ fun_l0_n59
+ fun_l0_n60
+ fun_l0_n61
+ fun_l0_n62
+ fun_l0_n63
+ fun_l0_n64
+ fun_l0_n65
+ fun_l0_n66
+ fun_l0_n67
+ fun_l0_n68
+ fun_l0_n69
+ fun_l0_n70
+ fun_l0_n71
+ fun_l0_n72
+ fun_l0_n73
+ fun_l0_n74
+ fun_l0_n75
+ fun_l0_n76
+ fun_l0_n77
+ fun_l0_n78
+ fun_l0_n79
+ fun_l0_n80
+ fun_l0_n81
+ fun_l0_n82
+ fun_l0_n83
+ fun_l0_n84
+ fun_l0_n85
+ fun_l0_n86
+ fun_l0_n87
+ fun_l0_n88
+ fun_l0_n89
+ fun_l0_n90
+ fun_l0_n91
+ fun_l0_n92
+ fun_l0_n93
+ fun_l0_n94
+ fun_l0_n95
+ fun_l0_n96
+ fun_l0_n97
+ fun_l0_n98
+ fun_l0_n99
+ fun_l0_n100
+ fun_l0_n101
+ fun_l0_n102
+ fun_l0_n103
+ fun_l0_n104
+ fun_l0_n105
+ fun_l0_n106
+ fun_l0_n107
+ fun_l0_n108
+ fun_l0_n109
+ fun_l0_n110
+ fun_l0_n111
+ fun_l0_n112
+ fun_l0_n113
+ fun_l0_n114
+ fun_l0_n115
+ fun_l0_n116
+ fun_l0_n117
+ fun_l0_n118
+ fun_l0_n119
+ fun_l0_n120
+ fun_l0_n121
+ fun_l0_n122
+ fun_l0_n123
+ fun_l0_n124
+ fun_l0_n125
+ fun_l0_n126
+ fun_l0_n127
+ fun_l0_n128
+ fun_l0_n129
+ fun_l0_n130
+ fun_l0_n131
+ fun_l0_n132
+ fun_l0_n133
+ fun_l0_n134
+ fun_l0_n135
+ fun_l0_n136
+ fun_l0_n137
+ fun_l0_n138
+ fun_l0_n139
+ fun_l0_n140
+ fun_l0_n141
+ fun_l0_n142
+ fun_l0_n143
+ fun_l0_n144
+ fun_l0_n145
+ fun_l0_n146
+ fun_l0_n147
+ fun_l0_n148
+ fun_l0_n149
+ fun_l0_n150
+ fun_l0_n151
+ fun_l0_n152
+ fun_l0_n153
+ fun_l0_n154
+ fun_l0_n155
+ fun_l0_n156
+ fun_l0_n157
+ fun_l0_n158
+ fun_l0_n159
+ fun_l0_n160
+ fun_l0_n161
+ fun_l0_n162
+ fun_l0_n163
+ fun_l0_n164
+ fun_l0_n165
+ fun_l0_n166
+ fun_l0_n167
+ fun_l0_n168
+ fun_l0_n169
+ fun_l0_n170
+ fun_l0_n171
+ fun_l0_n172
+ fun_l0_n173
+ fun_l0_n174
+ fun_l0_n175
+ fun_l0_n176
+ fun_l0_n177
+ fun_l0_n178
+ fun_l0_n179
+ fun_l0_n180
+ fun_l0_n181
+ fun_l0_n182
+ fun_l0_n183
+ fun_l0_n184
+ fun_l0_n185
+ fun_l0_n186
+ fun_l0_n187
+ fun_l0_n188
+ fun_l0_n189
+ fun_l0_n190
+ fun_l0_n191
+ fun_l0_n192
+ fun_l0_n193
+ fun_l0_n194
+ fun_l0_n195
+ fun_l0_n196
+ fun_l0_n197
+ fun_l0_n198
+ fun_l0_n199
+ fun_l0_n200
+ fun_l0_n201
+ fun_l0_n202
+ fun_l0_n203
+ fun_l0_n204
+ fun_l0_n205
+ fun_l0_n206
+ fun_l0_n207
+ fun_l0_n208
+ fun_l0_n209
+ fun_l0_n210
+ fun_l0_n211
+ fun_l0_n212
+ fun_l0_n213
+ fun_l0_n214
+ fun_l0_n215
+ fun_l0_n216
+ fun_l0_n217
+ fun_l0_n218
+ fun_l0_n219
+ fun_l0_n220
+ fun_l0_n221
+ fun_l0_n222
+ fun_l0_n223
+ fun_l0_n224
+ fun_l0_n225
+ fun_l0_n226
+ fun_l0_n227
+ fun_l0_n228
+ fun_l0_n229
+ fun_l0_n230
+ fun_l0_n231
+ fun_l0_n232
+ fun_l0_n233
+ fun_l0_n234
+ fun_l0_n235
+ fun_l0_n236
+ fun_l0_n237
+ fun_l0_n238
+ fun_l0_n239
+ fun_l0_n240
+ fun_l0_n241
+ fun_l0_n242
+ fun_l0_n243
+ fun_l0_n244
+ fun_l0_n245
+ fun_l0_n246
+ fun_l0_n247
+ fun_l0_n248
+ fun_l0_n249
+ fun_l0_n250
+ fun_l0_n251
+ fun_l0_n252
+ fun_l0_n253
+ fun_l0_n254
+ fun_l0_n255
+ fun_l0_n256
+ fun_l0_n257
+ fun_l0_n258
+ fun_l0_n259
+ fun_l0_n260
+ fun_l0_n261
+ fun_l0_n262
+ fun_l0_n263
+ fun_l0_n264
+ fun_l0_n265
+ fun_l0_n266
+ fun_l0_n267
+ fun_l0_n268
+ fun_l0_n269
+ fun_l0_n270
+ fun_l0_n271
+ fun_l0_n272
+ fun_l0_n273
+ fun_l0_n274
+ fun_l0_n275
+ fun_l0_n276
+ fun_l0_n277
+ fun_l0_n278
+ fun_l0_n279
+ fun_l0_n280
+ fun_l0_n281
+ fun_l0_n282
+ fun_l0_n283
+ fun_l0_n284
+ fun_l0_n285
+ fun_l0_n286
+ fun_l0_n287
+ fun_l0_n288
+ fun_l0_n289
+ fun_l0_n290
+ fun_l0_n291
+ fun_l0_n292
+ fun_l0_n293
+ fun_l0_n294
+ fun_l0_n295
+ fun_l0_n296
+ fun_l0_n297
+ fun_l0_n298
+ fun_l0_n299
+ fun_l0_n300
+ fun_l0_n301
+ fun_l0_n302
+ fun_l0_n303
+ fun_l0_n304
+ fun_l0_n305
+ fun_l0_n306
+ fun_l0_n307
+ fun_l0_n308
+ fun_l0_n309
+ fun_l0_n310
+ fun_l0_n311
+ fun_l0_n312
+ fun_l0_n313
+ fun_l0_n314
+ fun_l0_n315
+ fun_l0_n316
+ fun_l0_n317
+ fun_l0_n318
+ fun_l0_n319
+ fun_l0_n320
+ fun_l0_n321
+ fun_l0_n322
+ fun_l0_n323
+ fun_l0_n324
+ fun_l0_n325
+ fun_l0_n326
+ fun_l0_n327
+ fun_l0_n328
+ fun_l0_n329
+ fun_l0_n330
+ fun_l0_n331
+ fun_l0_n332
+ fun_l0_n333
+ fun_l0_n334
+ fun_l0_n335
+ fun_l0_n336
+ fun_l0_n337
+ fun_l0_n338
+ fun_l0_n339
+ fun_l0_n340
+ fun_l0_n341
+ fun_l0_n342
+ fun_l0_n343
+ fun_l0_n344
+ fun_l0_n345
+ fun_l0_n346
+ fun_l0_n347
+ fun_l0_n348
+ fun_l0_n349
+ fun_l0_n350
+ fun_l0_n351
+ fun_l0_n352
+ fun_l0_n353
+ fun_l0_n354
+ fun_l0_n355
+ fun_l0_n356
+ fun_l0_n357
+ fun_l0_n358
+ fun_l0_n359
+ fun_l0_n360
+ fun_l0_n361
+ fun_l0_n362
+ fun_l0_n363
+ fun_l0_n364
+ fun_l0_n365
+ fun_l0_n366
+ fun_l0_n367
+ fun_l0_n368
+ fun_l0_n369
+ fun_l0_n370
+ fun_l0_n371
+ fun_l0_n372
+ fun_l0_n373
+ fun_l0_n374
+ fun_l0_n375
+ fun_l0_n376
+ fun_l0_n377
+ fun_l0_n378
+ fun_l0_n379
+ fun_l0_n380
+ fun_l0_n381
+ fun_l0_n382
+ fun_l0_n383
+ fun_l0_n384
+ fun_l0_n385
+ fun_l0_n386
+ fun_l0_n387
+ fun_l0_n388
+ fun_l0_n389
+ fun_l0_n390
+ fun_l0_n391
+ fun_l0_n392
+ fun_l0_n393
+ fun_l0_n394
+ fun_l0_n395
+ fun_l0_n396
+ fun_l0_n397
+ fun_l0_n398
+ fun_l0_n399
+ fun_l0_n400
+ fun_l0_n401
+ fun_l0_n402
+ fun_l0_n403
+ fun_l0_n404
+ fun_l0_n405
+ fun_l0_n406
+ fun_l0_n407
+ fun_l0_n408
+ fun_l0_n409
+ fun_l0_n410
+ fun_l0_n411
+ fun_l0_n412
+ fun_l0_n413
+ fun_l0_n414
+ fun_l0_n415
+ fun_l0_n416
+ fun_l0_n417
+ fun_l0_n418
+ fun_l0_n419
+ fun_l0_n420
+ fun_l0_n421
+ fun_l0_n422
+ fun_l0_n423
+ fun_l0_n424
+ fun_l0_n425
+ fun_l0_n426
+ fun_l0_n427
+ fun_l0_n428
+ fun_l0_n429
+ fun_l0_n430
+ fun_l0_n431
+ fun_l0_n432
+ fun_l0_n433
+ fun_l0_n434
+ fun_l0_n435
+ fun_l0_n436
+ fun_l0_n437
+ fun_l0_n438
+ fun_l0_n439
+ fun_l0_n440
+ fun_l0_n441
+ fun_l0_n442
+ fun_l0_n443
+ fun_l0_n444
+ fun_l0_n445
+ fun_l0_n446
+ fun_l0_n447
+ fun_l0_n448
+ fun_l0_n449
+ fun_l0_n450
+ fun_l0_n451
+ fun_l0_n452
+ fun_l0_n453
+ fun_l0_n454
+ fun_l0_n455
+ fun_l0_n456
+ fun_l0_n457
+ fun_l0_n458
+ fun_l0_n459
+ fun_l0_n460
+ fun_l0_n461
+ fun_l0_n462
+ fun_l0_n463
+ fun_l0_n464
+ fun_l0_n465
+ fun_l0_n466
+ fun_l0_n467
+ fun_l0_n468
+ fun_l0_n469
+ fun_l0_n470
+ fun_l0_n471
+ fun_l0_n472
+ fun_l0_n473
+ fun_l0_n474
+ fun_l0_n475
+ fun_l0_n476
+ fun_l0_n477
+ fun_l0_n478
+ fun_l0_n479
+ fun_l0_n480
+ fun_l0_n481
+ fun_l0_n482
+ fun_l0_n483
+ fun_l0_n484
+ fun_l0_n485
+ fun_l0_n486
+ fun_l0_n487
+ fun_l0_n488
+ fun_l0_n489
+ fun_l0_n490
+ fun_l0_n491
+ fun_l0_n492
+ fun_l0_n493
+ fun_l0_n494
+ fun_l0_n495
+ fun_l0_n496
+ fun_l0_n497
+ fun_l0_n498
+ fun_l0_n499
+ fun_l0_n500
+ fun_l0_n501
+ fun_l0_n502
+ fun_l0_n503
+ fun_l0_n504
+ fun_l0_n505
+ fun_l0_n506
+ fun_l0_n507
+ fun_l0_n508
+ fun_l0_n509
+ fun_l0_n510
+ fun_l0_n511
+ fun_l0_n512
+ fun_l0_n513
+ fun_l0_n514
+ fun_l0_n515
+ fun_l0_n516
+ fun_l0_n517
+ fun_l0_n518
+ fun_l0_n519
+ fun_l0_n520
+ fun_l0_n521
+ fun_l0_n522
+ fun_l0_n523
+ fun_l0_n524
+ fun_l0_n525
+ fun_l0_n526
+ fun_l0_n527
+ fun_l0_n528
+ fun_l0_n529
+ fun_l0_n530
+ fun_l0_n531
+ fun_l0_n532
+ fun_l0_n533
+ fun_l0_n534
+ fun_l0_n535
+ fun_l0_n536
+ fun_l0_n537
+ fun_l0_n538
+ fun_l0_n539
+ fun_l0_n540
+ fun_l0_n541
+ fun_l0_n542
+ fun_l0_n543
+ fun_l0_n544
+ fun_l0_n545
+ fun_l0_n546
+ fun_l0_n547
+ fun_l0_n548
+ fun_l0_n549
+ fun_l0_n550
+ fun_l0_n551
+ fun_l0_n552
+ fun_l0_n553
+ fun_l0_n554
+ fun_l0_n555
+ fun_l0_n556
+ fun_l0_n557
+ fun_l0_n558
+ fun_l0_n559
+ fun_l0_n560
+ fun_l0_n561
+ fun_l0_n562
+ fun_l0_n563
+ fun_l0_n564
+ fun_l0_n565
+ fun_l0_n566
+ fun_l0_n567
+ fun_l0_n568
+ fun_l0_n569
+ fun_l0_n570
+ fun_l0_n571
+ fun_l0_n572
+ fun_l0_n573
+ fun_l0_n574
+ fun_l0_n575
+ fun_l0_n576
+ fun_l0_n577
+ fun_l0_n578
+ fun_l0_n579
+ fun_l0_n580
+ fun_l0_n581
+ fun_l0_n582
+ fun_l0_n583
+ fun_l0_n584
+ fun_l0_n585
+ fun_l0_n586
+ fun_l0_n587
+ fun_l0_n588
+ fun_l0_n589
+ fun_l0_n590
+ fun_l0_n591
+ fun_l0_n592
+ fun_l0_n593
+ fun_l0_n594
+ fun_l0_n595
+ fun_l0_n596
+ fun_l0_n597
+ fun_l0_n598
+ fun_l0_n599
+ fun_l0_n600
+ fun_l0_n601
+ fun_l0_n602
+ fun_l0_n603
+ fun_l0_n604
+ fun_l0_n605
+ fun_l0_n606
+ fun_l0_n607
+ fun_l0_n608
+ fun_l0_n609
+ fun_l0_n610
+ fun_l0_n611
+ fun_l0_n612
+ fun_l0_n613
+ fun_l0_n614
+ fun_l0_n615
+ fun_l0_n616
+ fun_l0_n617
+ fun_l0_n618
+ fun_l0_n619
+ fun_l0_n620
+ fun_l0_n621
+ fun_l0_n622
+ fun_l0_n623
+ fun_l0_n624
+ fun_l0_n625
+ fun_l0_n626
+ fun_l0_n627
+ fun_l0_n628
+ fun_l0_n629
+ fun_l0_n630
+ fun_l0_n631
+ fun_l0_n632
+ fun_l0_n633
+ fun_l0_n634
+ fun_l0_n635
+ fun_l0_n636
+ fun_l0_n637
+ fun_l0_n638
+ fun_l0_n639
+ fun_l0_n640
+ fun_l0_n641
+ fun_l0_n642
+ fun_l0_n643
+ fun_l0_n644
+ fun_l0_n645
+ fun_l0_n646
+ fun_l0_n647
+ fun_l0_n648
+ fun_l0_n649
+ fun_l0_n650
+ fun_l0_n651
+ fun_l0_n652
+ fun_l0_n653
+ fun_l0_n654
+ fun_l0_n655
+ fun_l0_n656
+ fun_l0_n657
+ fun_l0_n658
+ fun_l0_n659
+ fun_l0_n660
+ fun_l0_n661
+ fun_l0_n662
+ fun_l0_n663
+ fun_l0_n664
+ fun_l0_n665
+ fun_l0_n666
+ fun_l0_n667
+ fun_l0_n668
+ fun_l0_n669
+ fun_l0_n670
+ fun_l0_n671
+ fun_l0_n672
+ fun_l0_n673
+ fun_l0_n674
+ fun_l0_n675
+ fun_l0_n676
+ fun_l0_n677
+ fun_l0_n678
+ fun_l0_n679
+ fun_l0_n680
+ fun_l0_n681
+ fun_l0_n682
+ fun_l0_n683
+ fun_l0_n684
+ fun_l0_n685
+ fun_l0_n686
+ fun_l0_n687
+ fun_l0_n688
+ fun_l0_n689
+ fun_l0_n690
+ fun_l0_n691
+ fun_l0_n692
+ fun_l0_n693
+ fun_l0_n694
+ fun_l0_n695
+ fun_l0_n696
+ fun_l0_n697
+ fun_l0_n698
+ fun_l0_n699
+ fun_l0_n700
+ fun_l0_n701
+ fun_l0_n702
+ fun_l0_n703
+ fun_l0_n704
+ fun_l0_n705
+ fun_l0_n706
+ fun_l0_n707
+ fun_l0_n708
+ fun_l0_n709
+ fun_l0_n710
+ fun_l0_n711
+ fun_l0_n712
+ fun_l0_n713
+ fun_l0_n714
+ fun_l0_n715
+ fun_l0_n716
+ fun_l0_n717
+ fun_l0_n718
+ fun_l0_n719
+ fun_l0_n720
+ fun_l0_n721
+ fun_l0_n722
+ fun_l0_n723
+ fun_l0_n724
+ fun_l0_n725
+ fun_l0_n726
+ fun_l0_n727
+ fun_l0_n728
+ fun_l0_n729
+ fun_l0_n730
+ fun_l0_n731
+ fun_l0_n732
+ fun_l0_n733
+ fun_l0_n734
+ fun_l0_n735
+ fun_l0_n736
+ fun_l0_n737
+ fun_l0_n738
+ fun_l0_n739
+ fun_l0_n740
+ fun_l0_n741
+ fun_l0_n742
+ fun_l0_n743
+ fun_l0_n744
+ fun_l0_n745
+ fun_l0_n746
+ fun_l0_n747
+ fun_l0_n748
+ fun_l0_n749
+ fun_l0_n750
+ fun_l0_n751
+ fun_l0_n752
+ fun_l0_n753
+ fun_l0_n754
+ fun_l0_n755
+ fun_l0_n756
+ fun_l0_n757
+ fun_l0_n758
+ fun_l0_n759
+ fun_l0_n760
+ fun_l0_n761
+ fun_l0_n762
+ fun_l0_n763
+ fun_l0_n764
+ fun_l0_n765
+ fun_l0_n766
+ fun_l0_n767
+ fun_l0_n768
+ fun_l0_n769
+ fun_l0_n770
+ fun_l0_n771
+ fun_l0_n772
+ fun_l0_n773
+ fun_l0_n774
+ fun_l0_n775
+ fun_l0_n776
+ fun_l0_n777
+ fun_l0_n778
+ fun_l0_n779
+ fun_l0_n780
+ fun_l0_n781
+ fun_l0_n782
+ fun_l0_n783
+ fun_l0_n784
+ fun_l0_n785
+ fun_l0_n786
+ fun_l0_n787
+ fun_l0_n788
+ fun_l0_n789
+ fun_l0_n790
+ fun_l0_n791
+ fun_l0_n792
+ fun_l0_n793
+ fun_l0_n794
+ fun_l0_n795
+ fun_l0_n796
+ fun_l0_n797
+ fun_l0_n798
+ fun_l0_n799
+ fun_l0_n800
+ fun_l0_n801
+ fun_l0_n802
+ fun_l0_n803
+ fun_l0_n804
+ fun_l0_n805
+ fun_l0_n806
+ fun_l0_n807
+ fun_l0_n808
+ fun_l0_n809
+ fun_l0_n810
+ fun_l0_n811
+ fun_l0_n812
+ fun_l0_n813
+ fun_l0_n814
+ fun_l0_n815
+ fun_l0_n816
+ fun_l0_n817
+ fun_l0_n818
+ fun_l0_n819
+ fun_l0_n820
+ fun_l0_n821
+ fun_l0_n822
+ fun_l0_n823
+ fun_l0_n824
+ fun_l0_n825
+ fun_l0_n826
+ fun_l0_n827
+ fun_l0_n828
+ fun_l0_n829
+ fun_l0_n830
+ fun_l0_n831
+ fun_l0_n832
+ fun_l0_n833
+ fun_l0_n834
+ fun_l0_n835
+ fun_l0_n836
+ fun_l0_n837
+ fun_l0_n838
+ fun_l0_n839
+ fun_l0_n840
+ fun_l0_n841
+ fun_l0_n842
+ fun_l0_n843
+ fun_l0_n844
+ fun_l0_n845
+ fun_l0_n846
+ fun_l0_n847
+ fun_l0_n848
+ fun_l0_n849
+ fun_l0_n850
+ fun_l0_n851
+ fun_l0_n852
+ fun_l0_n853
+ fun_l0_n854
+ fun_l0_n855
+ fun_l0_n856
+ fun_l0_n857
+ fun_l0_n858
+ fun_l0_n859
+ fun_l0_n860
+ fun_l0_n861
+ fun_l0_n862
+ fun_l0_n863
+ fun_l0_n864
+ fun_l0_n865
+ fun_l0_n866
+ fun_l0_n867
+ fun_l0_n868
+ fun_l0_n869
+ fun_l0_n870
+ fun_l0_n871
+ fun_l0_n872
+ fun_l0_n873
+ fun_l0_n874
+ fun_l0_n875
+ fun_l0_n876
+ fun_l0_n877
+ fun_l0_n878
+ fun_l0_n879
+ fun_l0_n880
+ fun_l0_n881
+ fun_l0_n882
+ fun_l0_n883
+ fun_l0_n884
+ fun_l0_n885
+ fun_l0_n886
+ fun_l0_n887
+ fun_l0_n888
+ fun_l0_n889
+ fun_l0_n890
+ fun_l0_n891
+ fun_l0_n892
+ fun_l0_n893
+ fun_l0_n894
+ fun_l0_n895
+ fun_l0_n896
+ fun_l0_n897
+ fun_l0_n898
+ fun_l0_n899
+ fun_l0_n900
+ fun_l0_n901
+ fun_l0_n902
+ fun_l0_n903
+ fun_l0_n904
+ fun_l0_n905
+ fun_l0_n906
+ fun_l0_n907
+ fun_l0_n908
+ fun_l0_n909
+ fun_l0_n910
+ fun_l0_n911
+ fun_l0_n912
+ fun_l0_n913
+ fun_l0_n914
+ fun_l0_n915
+ fun_l0_n916
+ fun_l0_n917
+ fun_l0_n918
+ fun_l0_n919
+ fun_l0_n920
+ fun_l0_n921
+ fun_l0_n922
+ fun_l0_n923
+ fun_l0_n924
+ fun_l0_n925
+ fun_l0_n926
+ fun_l0_n927
+ fun_l0_n928
+ fun_l0_n929
+ fun_l0_n930
+ fun_l0_n931
+ fun_l0_n932
+ fun_l0_n933
+ fun_l0_n934
+ fun_l0_n935
+ fun_l0_n936
+ fun_l0_n937
+ fun_l0_n938
+ fun_l0_n939
+ fun_l0_n940
+ fun_l0_n941
+ fun_l0_n942
+ fun_l0_n943
+ fun_l0_n944
+ fun_l0_n945
+ fun_l0_n946
+ fun_l0_n947
+ fun_l0_n948
+ fun_l0_n949
+ fun_l0_n950
+ fun_l0_n951
+ fun_l0_n952
+ fun_l0_n953
+ fun_l0_n954
+ fun_l0_n955
+ fun_l0_n956
+ fun_l0_n957
+ fun_l0_n958
+ fun_l0_n959
+ fun_l0_n960
+ fun_l0_n961
+ fun_l0_n962
+ fun_l0_n963
+ fun_l0_n964
+ fun_l0_n965
+ fun_l0_n966
+ fun_l0_n967
+ fun_l0_n968
+ fun_l0_n969
+ fun_l0_n970
+ fun_l0_n971
+ fun_l0_n972
+ fun_l0_n973
+ fun_l0_n974
+ fun_l0_n975
+ fun_l0_n976
+ fun_l0_n977
+ fun_l0_n978
+ fun_l0_n979
+ fun_l0_n980
+ fun_l0_n981
+ fun_l0_n982
+ fun_l0_n983
+ fun_l0_n984
+ fun_l0_n985
+ fun_l0_n986
+ fun_l0_n987
+ fun_l0_n988
+ fun_l0_n989
+ fun_l0_n990
+ fun_l0_n991
+ fun_l0_n992
+ fun_l0_n993
+ fun_l0_n994
+ fun_l0_n995
+ fun_l0_n996
+ fun_l0_n997
+ fun_l0_n998
+ fun_l0_n999
+end
+
+@count
+
+}
diff --git a/bootstraptest/test_yjit_rust_port.rb b/bootstraptest/test_yjit_rust_port.rb
new file mode 100644
index 0000000000..e399e0e49e
--- /dev/null
+++ b/bootstraptest/test_yjit_rust_port.rb
@@ -0,0 +1,422 @@
+# Simple tests that we know we can pass
+# To keep track of what we got working during the Rust port
+# And avoid breaking/losing functionality
+#
+# Say "Thread" here to dodge WASM CI check. We use ractors here
+# which WASM doesn't support and it only greps for "Thread".
+
+# Test for opt_mod
+assert_equal '2', %q{
+ def mod(a, b)
+ a % b
+ end
+
+ mod(7, 5)
+ mod(7, 5)
+}
+
+# Test for opt_mult
+assert_equal '12', %q{
+ def mult(a, b)
+ a * b
+ end
+
+ mult(6, 2)
+ mult(6, 2)
+}
+
+# Test for opt_div
+assert_equal '3', %q{
+ def div(a, b)
+ a / b
+ end
+
+ div(6, 2)
+ div(6, 2)
+}
+
+assert_equal '5', %q{
+ def plus(a, b)
+ a + b
+ end
+
+ plus(3, 2)
+}
+
+assert_equal '1', %q{
+ def foo(a, b)
+ a - b
+ end
+
+ foo(3, 2)
+}
+
+assert_equal 'true', %q{
+ def foo(a, b)
+ a < b
+ end
+
+ foo(2, 3)
+}
+
+# Bitwise left shift
+assert_equal '4', %q{
+ def foo(a, b)
+ 1 << 2
+ end
+
+ foo(1, 2)
+}
+
+assert_equal '-7', %q{
+ def foo(a, b)
+ -7
+ end
+
+ foo(1, 2)
+}
+
+# Putstring
+assert_equal 'foo', %q{
+ def foo(a, b)
+ "foo"
+ end
+
+ foo(1, 2)
+}
+
+assert_equal '-6', %q{
+ def foo(a, b)
+ a + -7
+ end
+
+ foo(1, 2)
+}
+
+assert_equal 'true', %q{
+ def foo(a, b)
+ a == b
+ end
+
+ foo(3, 3)
+}
+
+assert_equal 'true', %q{
+ def foo(a, b)
+ a < b
+ end
+
+ foo(3, 5)
+}
+
+assert_equal '777', %q{
+ def foo(a)
+ if a
+ 777
+ else
+ 333
+ end
+ end
+
+ foo(true)
+}
+
+assert_equal '5', %q{
+ def foo(a, b)
+ while a < b
+ a += 1
+ end
+ a
+ end
+
+ foo(1, 5)
+}
+
+# opt_aref
+assert_equal '2', %q{
+ def foo(a, b)
+ a[b]
+ end
+
+ foo([0, 1, 2], 2)
+}
+
+# Simple function calls with 0, 1, 2 arguments
+assert_equal '-2', %q{
+ def bar()
+ -2
+ end
+
+ def foo(a, b)
+ bar()
+ end
+
+ foo(3, 2)
+}
+assert_equal '2', %q{
+ def bar(a)
+ a
+ end
+
+ def foo(a, b)
+ bar(b)
+ end
+
+ foo(3, 2)
+}
+assert_equal '1', %q{
+ def bar(a, b)
+ a - b
+ end
+
+ def foo(a, b)
+ bar(a, b)
+ end
+
+ foo(3, 2)
+}
+
+# Regression test for assembler bug
+assert_equal '1', %q{
+ def check_index(index)
+ if 0x40000000 < index
+ return -1
+ end
+ 1
+ end
+
+ check_index 2
+}
+
+# Setivar test
+assert_equal '2', %q{
+ class Klass
+ attr_accessor :a
+
+ def set()
+ @a = 2
+ end
+
+ def get()
+ @a
+ end
+ end
+
+ o = Klass.new
+ o.set()
+ o.a
+}
+
+# Regression for putobject bug
+assert_equal '1.5', %q{
+ def foo(x)
+ x
+ end
+
+ def bar
+ foo(1.5)
+ end
+
+ bar()
+}
+
+# Getivar with an extended ivar table
+assert_equal '3', %q{
+ class Foo
+ def initialize
+ @x1 = 1
+ @x2 = 1
+ @x3 = 1
+ @x4 = 3
+ end
+
+ def bar
+ @x4
+ end
+ end
+
+ f = Foo.new
+ f.bar
+}
+
+assert_equal 'true', %q{
+ x = [[false, true]]
+ for i, j in x
+ ;
+ end
+ j
+}
+
+# Regression for getivar
+assert_equal '[nil]', %q{
+ [TrueClass].each do |klass|
+ klass.class_eval("def foo = @foo")
+ end
+
+ [true].map do |instance|
+ instance.foo
+ end
+}
+
+# Regression for send
+assert_equal 'ok', %q{
+ def bar(baz: 2)
+ baz
+ end
+
+ def foo
+ bar(1, baz: 123)
+ end
+
+ begin
+ foo
+ foo
+ rescue ArgumentError => e
+ print "ok"
+ end
+}
+
+# Array access regression test
+assert_equal '[0, 1, 2, 3, 4, 5]', %q{
+ def expandarray_useless_splat
+ arr = [0, 1, 2, 3, 4, 5]
+ a, * = arr
+ end
+
+ expandarray_useless_splat
+}
+
+# Make sure we're correctly reading RStruct's as.ary union for embedded RStructs
+assert_equal '3,12', %q{
+ pt_struct = Struct.new(:x, :y)
+ p = pt_struct.new(3, 12)
+ def pt_inspect(pt)
+ "#{pt.x},#{pt.y}"
+ end
+
+ # Make sure pt_inspect is JITted
+ 10.times { pt_inspect(p) }
+
+ # Make sure it's returning '3,12' instead of e.g. '3,false'
+ pt_inspect(p)
+}
+
+assert_equal '2', %q{
+ def foo(s)
+ s.foo
+ end
+
+ S = Struct.new(:foo)
+ foo(S.new(1))
+ foo(S.new(2))
+}
+
+# Try to compile new method while OOM
+assert_equal 'ok', %q{
+ def foo
+ :ok
+ end
+
+ RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT)
+
+ foo
+}
+
+# test hitting a branch stub when out of memory
+assert_equal 'ok', %q{
+ def nimai(jita)
+ if jita
+ :ng
+ else
+ :ok
+ end
+ end
+
+ nimai(true)
+ nimai(true)
+
+ RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT)
+
+ nimai(false)
+}
+
+# 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 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
+}
+
+assert_equal '[1, 2, 3]', %q{
+ def foo(arr)
+ arr << 1
+ arr << 2
+ arr << 3
+ arr
+ end
+
+ def bar()
+ foo([])
+ end
+
+ bar()
+}
diff --git a/builtin.h b/builtin.h
index 5b4bda1e99..38ad5a1629 100644
--- a/builtin.h
+++ b/builtin.h
@@ -13,11 +13,11 @@ struct rb_builtin_function {
const char * const name;
// for jit
- void (*compiler)(FILE *, long, unsigned, bool);
+ void (*compiler)(VALUE, long, unsigned, bool);
};
#define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity, _compiler) {\
- .name = #_name, \
+ .name = _i < 0 ? NULL : #_name, \
.func_ptr = (void *)_fname, \
.argc = _arity, \
.index = _i, \
@@ -33,29 +33,67 @@ typedef struct rb_execution_context_struct rb_execution_context_t;
/* The following code is generated by the following Ruby script:
+typedef = proc {|i, args|
+ "typedef VALUE (*rb_builtin_arity#{i}_function_type)(rb_execution_context_t *ec, VALUE self#{args});"
+}
+puts typedef[0, ""]
+(1..15).each {|i|
+ puts typedef[i, ",\n " + (0...i).map{"VALUE"}.join(", ")]
+}
16.times{|i|
- args = (i > 0 ? ', ' : '') + (0...i).map{"VALUE"}.join(', ')
- puts "static inline void rb_builtin_function_check_arity#{i}(VALUE (*f)(rb_execution_context_t *ec, VALUE self#{args})){}"
+ puts "static inline void rb_builtin_function_check_arity#{i}(rb_builtin_arity#{i}_function_type f){}"
}
*/
-static inline void rb_builtin_function_check_arity0(VALUE (*f)(rb_execution_context_t *ec, VALUE self)){}
-static inline void rb_builtin_function_check_arity1(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE)){}
-static inline void rb_builtin_function_check_arity2(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity3(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity4(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity5(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity6(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity7(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity8(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity9(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity10(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity11(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity12(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity13(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity14(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-static inline void rb_builtin_function_check_arity15(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
-
+typedef VALUE (*rb_builtin_arity0_function_type)(rb_execution_context_t *ec, VALUE self);
+typedef VALUE (*rb_builtin_arity1_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE);
+typedef VALUE (*rb_builtin_arity2_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity3_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity4_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity5_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity6_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity7_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity8_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity9_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity10_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity11_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity12_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity13_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity14_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+typedef VALUE (*rb_builtin_arity15_function_type)(rb_execution_context_t *ec, VALUE self,
+ VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+static inline void rb_builtin_function_check_arity0(rb_builtin_arity0_function_type f){}
+static inline void rb_builtin_function_check_arity1(rb_builtin_arity1_function_type f){}
+static inline void rb_builtin_function_check_arity2(rb_builtin_arity2_function_type f){}
+static inline void rb_builtin_function_check_arity3(rb_builtin_arity3_function_type f){}
+static inline void rb_builtin_function_check_arity4(rb_builtin_arity4_function_type f){}
+static inline void rb_builtin_function_check_arity5(rb_builtin_arity5_function_type f){}
+static inline void rb_builtin_function_check_arity6(rb_builtin_arity6_function_type f){}
+static inline void rb_builtin_function_check_arity7(rb_builtin_arity7_function_type f){}
+static inline void rb_builtin_function_check_arity8(rb_builtin_arity8_function_type f){}
+static inline void rb_builtin_function_check_arity9(rb_builtin_arity9_function_type f){}
+static inline void rb_builtin_function_check_arity10(rb_builtin_arity10_function_type f){}
+static inline void rb_builtin_function_check_arity11(rb_builtin_arity11_function_type f){}
+static inline void rb_builtin_function_check_arity12(rb_builtin_arity12_function_type f){}
+static inline void rb_builtin_function_check_arity13(rb_builtin_arity13_function_type f){}
+static inline void rb_builtin_function_check_arity14(rb_builtin_arity14_function_type f){}
+static inline void rb_builtin_function_check_arity15(rb_builtin_arity15_function_type f){}
+
+PUREFUNC(VALUE rb_vm_lvar_exposed(rb_execution_context_t *ec, int index));
VALUE rb_vm_lvar_exposed(rb_execution_context_t *ec, int index);
// __builtin_inline!
diff --git a/ccan/build_assert/build_assert.h b/ccan/build_assert/build_assert.h
index a04d1d4709..b846849241 100644
--- a/ccan/build_assert/build_assert.h
+++ b/ccan/build_assert/build_assert.h
@@ -3,7 +3,7 @@
#define CCAN_BUILD_ASSERT_H
/**
- * BUILD_ASSERT - assert a build-time dependency.
+ * CCAN_BUILD_ASSERT - assert a build-time dependency.
* @cond: the compile-time condition which must be true.
*
* Your compile will fail if the condition isn't true, or can't be evaluated
@@ -15,15 +15,15 @@
* static char *foo_to_char(struct foo *foo)
* {
* // This code needs string to be at start of foo.
- * BUILD_ASSERT(offsetof(struct foo, string) == 0);
+ * CCAN_BUILD_ASSERT(offsetof(struct foo, string) == 0);
* return (char *)foo;
* }
*/
-#define BUILD_ASSERT(cond) \
+#define CCAN_BUILD_ASSERT(cond) \
do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
/**
- * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
+ * CCAN_BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
* @cond: the compile-time condition which must be true.
*
* Your compile will fail if the condition isn't true, or can't be evaluated
@@ -32,9 +32,9 @@
* Example:
* #define foo_to_char(foo) \
* ((char *)(foo) \
- * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
+ * + CCAN_BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
*/
-#define BUILD_ASSERT_OR_ZERO(cond) \
+#define CCAN_BUILD_ASSERT_OR_ZERO(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
#endif /* CCAN_BUILD_ASSERT_H */
diff --git a/ccan/check_type/check_type.h b/ccan/check_type/check_type.h
index 1f77a535e4..659e1a5a83 100644
--- a/ccan/check_type/check_type.h
+++ b/ccan/check_type/check_type.h
@@ -3,7 +3,7 @@
#define CCAN_CHECK_TYPE_H
/**
- * check_type - issue a warning or build failure if type is not correct.
+ * ccan_check_type - issue a warning or build failure if type is not correct.
* @expr: the expression whose type we should check (not evaluated).
* @type: the exact type we expect the expression to be.
*
@@ -11,7 +11,7 @@
* argument is of the expected type. No type promotion of the expression is
* done: an unsigned int is not the same as an int!
*
- * check_type() always evaluates to 0.
+ * ccan_check_type() always evaluates to 0.
*
* If your compiler does not support typeof, then the best we can do is fail
* to compile if the sizes of the types are unequal (a less complete check).
@@ -19,11 +19,11 @@
* Example:
* // They should always pass a 64-bit value to _set_some_value!
* #define set_some_value(expr) \
- * _set_some_value((check_type((expr), uint64_t), (expr)))
+ * _set_some_value((ccan_check_type((expr), uint64_t), (expr)))
*/
/**
- * check_types_match - issue a warning or build failure if types are not same.
+ * ccan_check_types_match - issue a warning or build failure if types are not same.
* @expr1: the first expression (not evaluated).
* @expr2: the second expression (not evaluated).
*
@@ -31,7 +31,7 @@
* arguments are of identical types. No type promotion of the expressions is
* done: an unsigned int is not the same as an int!
*
- * check_types_match() always evaluates to 0.
+ * ccan_check_types_match() always evaluates to 0.
*
* If your compiler does not support typeof, then the best we can do is fail
* to compile if the sizes of the types are unequal (a less complete check).
@@ -39,25 +39,25 @@
* Example:
* // Do subtraction to get to enclosing type, but make sure that
* // pointer is of correct type for that member.
- * #define container_of(mbr_ptr, encl_type, mbr) \
- * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
+ * #define ccan_container_of(mbr_ptr, encl_type, mbr) \
+ * (ccan_check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
* ((encl_type *) \
* ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
*/
-#if HAVE_TYPEOF
-#define check_type(expr, type) \
+#if defined(HAVE_TYPEOF) && HAVE_TYPEOF
+#define ccan_check_type(expr, type) \
((typeof(expr) *)0 != (type *)0)
-#define check_types_match(expr1, expr2) \
+#define ccan_check_types_match(expr1, expr2) \
((typeof(expr1) *)0 != (typeof(expr2) *)0)
#else
#include "ccan/build_assert/build_assert.h"
/* Without typeof, we can only test the sizes. */
-#define check_type(expr, type) \
- BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
+#define ccan_check_type(expr, type) \
+ CCAN_BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
-#define check_types_match(expr1, expr2) \
- BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
+#define ccan_check_types_match(expr1, expr2) \
+ CCAN_BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
#endif /* HAVE_TYPEOF */
#endif /* CCAN_CHECK_TYPE_H */
diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h
index ae3e1fc81f..872bb6ea6e 100644
--- a/ccan/container_of/container_of.h
+++ b/ccan/container_of/container_of.h
@@ -4,7 +4,7 @@
#include "ccan/check_type/check_type.h"
/**
- * container_of - get pointer to enclosing structure
+ * ccan_container_of - get pointer to enclosing structure
* @member_ptr: pointer to the structure member
* @containing_type: the type this member is within
* @member: the name of this member within the structure.
@@ -24,18 +24,18 @@
*
* static struct info *foo_to_info(struct foo *foo)
* {
- * return container_of(foo, struct info, my_foo);
+ * return ccan_container_of(foo, struct info, my_foo);
* }
*/
-#define container_of(member_ptr, containing_type, member) \
+#define ccan_container_of(member_ptr, containing_type, member) \
((containing_type *) \
((char *)(member_ptr) \
- - container_off(containing_type, member)) \
- + check_types_match(*(member_ptr), ((containing_type *)0)->member))
+ - ccan_container_off(containing_type, member)) \
+ + ccan_check_types_match(*(member_ptr), ((containing_type *)0)->member))
/**
- * container_of_or_null - get pointer to enclosing structure, or NULL
+ * ccan_container_of_or_null - get pointer to enclosing structure, or NULL
* @member_ptr: pointer to the structure member
* @containing_type: the type this member is within
* @member: the name of this member within the structure.
@@ -56,21 +56,21 @@
*
* static struct info *foo_to_info_allowing_null(struct foo *foo)
* {
- * return container_of_or_null(foo, struct info, my_foo);
+ * return ccan_container_of_or_null(foo, struct info, my_foo);
* }
*/
static inline char *container_of_or_null_(void *member_ptr, size_t offset)
{
return member_ptr ? (char *)member_ptr - offset : NULL;
}
-#define container_of_or_null(member_ptr, containing_type, member) \
+#define ccan_container_of_or_null(member_ptr, containing_type, member) \
((containing_type *) \
- container_of_or_null_(member_ptr, \
- container_off(containing_type, member)) \
- + check_types_match(*(member_ptr), ((containing_type *)0)->member))
+ ccan_container_of_or_null_(member_ptr, \
+ ccan_container_off(containing_type, member)) \
+ + ccan_check_types_match(*(member_ptr), ((containing_type *)0)->member))
/**
- * container_off - get offset to enclosing structure
+ * ccan_container_off - get offset to enclosing structure
* @containing_type: the type this member is within
* @member: the name of this member within the structure.
*
@@ -89,15 +89,15 @@ static inline char *container_of_or_null_(void *member_ptr, size_t offset)
*
* static struct info *foo_to_info(struct foo *foo)
* {
- * size_t off = container_off(struct info, my_foo);
+ * size_t off = ccan_container_off(struct info, my_foo);
* return (void *)((char *)foo - off);
* }
*/
-#define container_off(containing_type, member) \
+#define ccan_container_off(containing_type, member) \
offsetof(containing_type, member)
/**
- * container_of_var - get pointer to enclosing structure using a variable
+ * ccan_container_of_var - get pointer to enclosing structure using a variable
* @member_ptr: pointer to the structure member
* @container_var: a pointer of same type as this member's container
* @member: the name of this member within the structure.
@@ -108,21 +108,21 @@ static inline char *container_of_or_null_(void *member_ptr, size_t offset)
* Example:
* static struct info *foo_to_i(struct foo *foo)
* {
- * struct info *i = container_of_var(foo, i, my_foo);
+ * struct info *i = ccan_container_of_var(foo, i, my_foo);
* return i;
* }
*/
-#if HAVE_TYPEOF
-#define container_of_var(member_ptr, container_var, member) \
- container_of(member_ptr, typeof(*container_var), member)
+#if defined(HAVE_TYPEOF) && HAVE_TYPEOF
+#define ccan_container_of_var(member_ptr, container_var, member) \
+ ccan_container_of(member_ptr, typeof(*container_var), member)
#else
-#define container_of_var(member_ptr, container_var, member) \
+#define ccan_container_of_var(member_ptr, container_var, member) \
((void *)((char *)(member_ptr) - \
- container_off_var(container_var, member)))
+ ccan_container_off_var(container_var, member)))
#endif
/**
- * container_off_var - get offset of a field in enclosing structure
+ * ccan_container_off_var - get offset of a field in enclosing structure
* @container_var: a pointer to a container structure
* @member: the name of a member within the structure.
*
@@ -131,11 +131,11 @@ static inline char *container_of_or_null_(void *member_ptr, size_t offset)
* structure memory layout.
*
*/
-#if HAVE_TYPEOF
-#define container_off_var(var, member) \
- container_off(typeof(*var), member)
+#if defined(HAVE_TYPEOF) && HAVE_TYPEOF
+#define ccan_container_off_var(var, member) \
+ ccan_container_off(typeof(*var), member)
#else
-#define container_off_var(var, member) \
+#define ccan_container_off_var(var, member) \
((const char *)&(var)->member - (const char *)(var))
#endif
diff --git a/ccan/list/list.h b/ccan/list/list.h
index c434ad8106..30b2af04e9 100644
--- a/ccan/list/list.h
+++ b/ccan/list/list.h
@@ -7,7 +7,7 @@
#include "ccan/check_type/check_type.h"
/**
- * struct list_node - an entry in a doubly-linked list
+ * struct ccan_list_node - an entry in a doubly-linked list
* @next: next entry (self if empty)
* @prev: previous entry (self if empty)
*
@@ -16,209 +16,209 @@
* struct child {
* const char *name;
* // Linked list of all us children.
- * struct list_node list;
+ * struct ccan_list_node list;
* };
*/
-struct list_node
+struct ccan_list_node
{
- struct list_node *next, *prev;
+ struct ccan_list_node *next, *prev;
};
/**
- * struct list_head - the head of a doubly-linked list
- * @h: the list_head (containing next and prev pointers)
+ * struct ccan_list_head - the head of a doubly-linked list
+ * @h: the ccan_list_head (containing next and prev pointers)
*
* This is used as the head of a linked list.
* Example:
* struct parent {
* const char *name;
- * struct list_head children;
+ * struct ccan_list_head children;
* unsigned int num_children;
* };
*/
-struct list_head
+struct ccan_list_head
{
- struct list_node n;
+ struct ccan_list_node n;
};
-#define LIST_LOC __FILE__ ":" stringify(__LINE__)
-#define list_debug(h, loc) ((void)loc, h)
-#define list_debug_node(n, loc) ((void)loc, n)
+#define CCAN_LIST_LOC __FILE__ ":" ccan_stringify(__LINE__)
+#define ccan_list_debug(h, loc) ((void)loc, h)
+#define ccan_list_debug_node(n, loc) ((void)loc, n)
/**
- * LIST_HEAD_INIT - initializer for an empty list_head
+ * CCAN_LIST_HEAD_INIT - initializer for an empty ccan_list_head
* @name: the name of the list.
*
* Explicit initializer for an empty list.
*
* See also:
- * LIST_HEAD, list_head_init()
+ * CCAN_LIST_HEAD, ccan_list_head_init()
*
* Example:
- * static struct list_head my_list = LIST_HEAD_INIT(my_list);
+ * static struct ccan_list_head my_list = CCAN_LIST_HEAD_INIT(my_list);
*/
-#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } }
+#define CCAN_LIST_HEAD_INIT(name) { { &(name).n, &(name).n } }
/**
- * LIST_HEAD - define and initialize an empty list_head
+ * CCAN_LIST_HEAD - define and initialize an empty ccan_list_head
* @name: the name of the list.
*
- * The LIST_HEAD macro defines a list_head and initializes it to an empty
- * list. It can be prepended by "static" to define a static list_head.
+ * The CCAN_LIST_HEAD macro defines a ccan_list_head and initializes it to an empty
+ * list. It can be prepended by "static" to define a static ccan_list_head.
*
* See also:
- * LIST_HEAD_INIT, list_head_init()
+ * CCAN_LIST_HEAD_INIT, ccan_list_head_init()
*
* Example:
- * static LIST_HEAD(my_global_list);
+ * static CCAN_LIST_HEAD(my_global_list);
*/
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
+#define CCAN_LIST_HEAD(name) \
+ struct ccan_list_head name = CCAN_LIST_HEAD_INIT(name)
/**
- * list_head_init - initialize a list_head
- * @h: the list_head to set to the empty list
+ * ccan_list_head_init - initialize a ccan_list_head
+ * @h: the ccan_list_head to set to the empty list
*
* Example:
* ...
* struct parent *parent = malloc(sizeof(*parent));
*
- * list_head_init(&parent->children);
+ * ccan_list_head_init(&parent->children);
* parent->num_children = 0;
*/
-static inline void list_head_init(struct list_head *h)
+static inline void ccan_list_head_init(struct ccan_list_head *h)
{
h->n.next = h->n.prev = &h->n;
}
/**
- * list_node_init - initialize a list_node
- * @n: the list_node to link to itself.
+ * ccan_list_node_init - initialize a ccan_list_node
+ * @n: the ccan_list_node to link to itself.
*
- * You don't need to use this normally! But it lets you list_del(@n)
+ * You don't need to use this normally! But it lets you ccan_list_del(@n)
* safely.
*/
-static inline void list_node_init(struct list_node *n)
+static inline void ccan_list_node_init(struct ccan_list_node *n)
{
n->next = n->prev = n;
}
/**
- * list_add_after - add an entry after an existing node in a linked list
- * @h: the list_head to add the node to (for debugging)
- * @p: the existing list_node to add the node after
- * @n: the new list_node to add to the list.
+ * ccan_list_add_after - add an entry after an existing node in a linked list
+ * @h: the ccan_list_head to add the node to (for debugging)
+ * @p: the existing ccan_list_node to add the node after
+ * @n: the new ccan_list_node to add to the list.
*
- * The existing list_node must already be a member of the list.
- * The new list_node does not need to be initialized; it will be overwritten.
+ * The existing ccan_list_node must already be a member of the list.
+ * The new ccan_list_node does not need to be initialized; it will be overwritten.
*
* Example:
* struct child c1, c2, c3;
- * LIST_HEAD(h);
+ * CCAN_LIST_HEAD(h);
*
- * list_add_tail(&h, &c1.list);
- * list_add_tail(&h, &c3.list);
- * list_add_after(&h, &c1.list, &c2.list);
+ * ccan_list_add_tail(&h, &c1.list);
+ * ccan_list_add_tail(&h, &c3.list);
+ * ccan_list_add_after(&h, &c1.list, &c2.list);
*/
-#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC)
-static inline void list_add_after_(struct list_head *h,
- struct list_node *p,
- struct list_node *n,
+#define ccan_list_add_after(h, p, n) ccan_list_add_after_(h, p, n, CCAN_LIST_LOC)
+static inline void ccan_list_add_after_(struct ccan_list_head *h,
+ struct ccan_list_node *p,
+ struct ccan_list_node *n,
const char *abortstr)
{
n->next = p->next;
n->prev = p;
p->next->prev = n;
p->next = n;
- (void)list_debug(h, abortstr);
+ (void)ccan_list_debug(h, abortstr);
}
/**
- * list_add - add an entry at the start of a linked list.
- * @h: the list_head to add the node to
- * @n: the list_node to add to the list.
+ * ccan_list_add - add an entry at the start of a linked list.
+ * @h: the ccan_list_head to add the node to
+ * @n: the ccan_list_node to add to the list.
*
- * The list_node does not need to be initialized; it will be overwritten.
+ * The ccan_list_node does not need to be initialized; it will be overwritten.
* Example:
* struct child *child = malloc(sizeof(*child));
*
* child->name = "marvin";
- * list_add(&parent->children, &child->list);
+ * ccan_list_add(&parent->children, &child->list);
* parent->num_children++;
*/
-#define list_add(h, n) list_add_(h, n, LIST_LOC)
-static inline void list_add_(struct list_head *h,
- struct list_node *n,
+#define ccan_list_add(h, n) ccan_list_add_(h, n, CCAN_LIST_LOC)
+static inline void ccan_list_add_(struct ccan_list_head *h,
+ struct ccan_list_node *n,
const char *abortstr)
{
- list_add_after_(h, &h->n, n, abortstr);
+ ccan_list_add_after_(h, &h->n, n, abortstr);
}
/**
- * list_add_before - add an entry before an existing node in a linked list
- * @h: the list_head to add the node to (for debugging)
- * @p: the existing list_node to add the node before
- * @n: the new list_node to add to the list.
+ * ccan_list_add_before - add an entry before an existing node in a linked list
+ * @h: the ccan_list_head to add the node to (for debugging)
+ * @p: the existing ccan_list_node to add the node before
+ * @n: the new ccan_list_node to add to the list.
*
- * The existing list_node must already be a member of the list.
- * The new list_node does not need to be initialized; it will be overwritten.
+ * The existing ccan_list_node must already be a member of the list.
+ * The new ccan_list_node does not need to be initialized; it will be overwritten.
*
* Example:
- * list_head_init(&h);
- * list_add_tail(&h, &c1.list);
- * list_add_tail(&h, &c3.list);
- * list_add_before(&h, &c3.list, &c2.list);
- */
-#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC)
-static inline void list_add_before_(struct list_head *h,
- struct list_node *p,
- struct list_node *n,
+ * ccan_list_head_init(&h);
+ * ccan_list_add_tail(&h, &c1.list);
+ * ccan_list_add_tail(&h, &c3.list);
+ * ccan_list_add_before(&h, &c3.list, &c2.list);
+ */
+#define ccan_list_add_before(h, p, n) ccan_list_add_before_(h, p, n, CCAN_LIST_LOC)
+static inline void ccan_list_add_before_(struct ccan_list_head *h,
+ struct ccan_list_node *p,
+ struct ccan_list_node *n,
const char *abortstr)
{
n->next = p;
n->prev = p->prev;
p->prev->next = n;
p->prev = n;
- (void)list_debug(h, abortstr);
+ (void)ccan_list_debug(h, abortstr);
}
/**
- * list_add_tail - add an entry at the end of a linked list.
- * @h: the list_head to add the node to
- * @n: the list_node to add to the list.
+ * ccan_list_add_tail - add an entry at the end of a linked list.
+ * @h: the ccan_list_head to add the node to
+ * @n: the ccan_list_node to add to the list.
*
- * The list_node does not need to be initialized; it will be overwritten.
+ * The ccan_list_node does not need to be initialized; it will be overwritten.
* Example:
- * list_add_tail(&parent->children, &child->list);
+ * ccan_list_add_tail(&parent->children, &child->list);
* parent->num_children++;
*/
-#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC)
-static inline void list_add_tail_(struct list_head *h,
- struct list_node *n,
+#define ccan_list_add_tail(h, n) ccan_list_add_tail_(h, n, CCAN_LIST_LOC)
+static inline void ccan_list_add_tail_(struct ccan_list_head *h,
+ struct ccan_list_node *n,
const char *abortstr)
{
- list_add_before_(h, &h->n, n, abortstr);
+ ccan_list_add_before_(h, &h->n, n, abortstr);
}
/**
- * list_empty - is a list empty?
- * @h: the list_head
+ * ccan_list_empty - is a list empty?
+ * @h: the ccan_list_head
*
* If the list is empty, returns true.
*
* Example:
- * assert(list_empty(&parent->children) == (parent->num_children == 0));
+ * assert(ccan_list_empty(&parent->children) == (parent->num_children == 0));
*/
-#define list_empty(h) list_empty_(h, LIST_LOC)
-static inline int list_empty_(const struct list_head *h, const char* abortstr)
+#define ccan_list_empty(h) ccan_list_empty_(h, CCAN_LIST_LOC)
+static inline int ccan_list_empty_(const struct ccan_list_head *h, const char* abortstr)
{
- (void)list_debug(h, abortstr);
+ (void)ccan_list_debug(h, abortstr);
return h->n.next == &h->n;
}
/**
- * list_empty_nodebug - is a list empty (and don't perform debug checks)?
- * @h: the list_head
+ * ccan_list_empty_nodebug - is a list empty (and don't perform debug checks)?
+ * @h: the ccan_list_head
*
* If the list is empty, returns true.
* This differs from list_empty() in that if CCAN_LIST_DEBUG is set it
@@ -226,20 +226,20 @@ static inline int list_empty_(const struct list_head *h, const char* abortstr)
* know what you're doing.
*
* Example:
- * assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0));
+ * assert(ccan_list_empty_nodebug(&parent->children) == (parent->num_children == 0));
*/
#ifndef CCAN_LIST_DEBUG
-#define list_empty_nodebug(h) list_empty(h)
+#define ccan_list_empty_nodebug(h) ccan_list_empty(h)
#else
-static inline int list_empty_nodebug(const struct list_head *h)
+static inline int ccan_list_empty_nodebug(const struct ccan_list_head *h)
{
return h->n.next == &h->n;
}
#endif
/**
- * list_empty_nocheck - is a list empty?
- * @h: the list_head
+ * ccan_list_empty_nocheck - is a list empty?
+ * @h: the ccan_list_head
*
* If the list is empty, returns true. This doesn't perform any
* debug check for list consistency, so it can be called without
@@ -247,29 +247,29 @@ static inline int list_empty_nodebug(const struct list_head *h)
* checks where an incorrect result is not an issue (optimized
* bail out path for example).
*/
-static inline bool list_empty_nocheck(const struct list_head *h)
+static inline bool ccan_list_empty_nocheck(const struct ccan_list_head *h)
{
return h->n.next == &h->n;
}
/**
- * list_del - delete an entry from an (unknown) linked list.
- * @n: the list_node to delete from the list.
+ * ccan_list_del - delete an entry from an (unknown) linked list.
+ * @n: the ccan_list_node to delete from the list.
*
* Note that this leaves @n in an undefined state; it can be added to
* another list, but not deleted again.
*
* See also:
- * list_del_from(), list_del_init()
+ * ccan_list_del_from(), ccan_list_del_init()
*
* Example:
- * list_del(&child->list);
+ * ccan_list_del(&child->list);
* parent->num_children--;
*/
-#define list_del(n) list_del_(n, LIST_LOC)
-static inline void list_del_(struct list_node *n, const char* abortstr)
+#define ccan_list_del(n) ccan_list_del_(n, CCAN_LIST_LOC)
+static inline void ccan_list_del_(struct ccan_list_node *n, const char* abortstr)
{
- (void)list_debug_node(n, abortstr);
+ (void)ccan_list_debug_node(n, abortstr);
n->next->prev = n->prev;
n->prev->next = n->next;
#ifdef CCAN_LIST_DEBUG
@@ -279,80 +279,80 @@ static inline void list_del_(struct list_node *n, const char* abortstr)
}
/**
- * list_del_init - delete a node, and reset it so it can be deleted again.
- * @n: the list_node to be deleted.
+ * ccan_list_del_init - delete a node, and reset it so it can be deleted again.
+ * @n: the ccan_list_node to be deleted.
*
- * list_del(@n) or list_del_init() again after this will be safe,
+ * ccan_list_del(@n) or ccan_list_del_init() again after this will be safe,
* which can be useful in some cases.
*
* See also:
- * list_del_from(), list_del()
+ * ccan_list_del_from(), ccan_list_del()
*
* Example:
- * list_del_init(&child->list);
+ * ccan_list_del_init(&child->list);
* parent->num_children--;
*/
-#define list_del_init(n) list_del_init_(n, LIST_LOC)
-static inline void list_del_init_(struct list_node *n, const char *abortstr)
+#define ccan_list_del_init(n) ccan_list_del_init_(n, CCAN_LIST_LOC)
+static inline void ccan_list_del_init_(struct ccan_list_node *n, const char *abortstr)
{
- list_del_(n, abortstr);
- list_node_init(n);
+ ccan_list_del_(n, abortstr);
+ ccan_list_node_init(n);
}
/**
- * list_del_from - delete an entry from a known linked list.
- * @h: the list_head the node is in.
- * @n: the list_node to delete from the list.
+ * ccan_list_del_from - delete an entry from a known linked list.
+ * @h: the ccan_list_head the node is in.
+ * @n: the ccan_list_node to delete from the list.
*
* This explicitly indicates which list a node is expected to be in,
* which is better documentation and can catch more bugs.
*
- * See also: list_del()
+ * See also: ccan_list_del()
*
* Example:
- * list_del_from(&parent->children, &child->list);
+ * ccan_list_del_from(&parent->children, &child->list);
* parent->num_children--;
*/
-static inline void list_del_from(struct list_head *h, struct list_node *n)
+static inline void ccan_list_del_from(struct ccan_list_head *h, struct ccan_list_node *n)
{
#ifdef CCAN_LIST_DEBUG
{
/* Thorough check: make sure it was in list! */
- struct list_node *i;
+ struct ccan_list_node *i;
for (i = h->n.next; i != n; i = i->next)
assert(i != &h->n);
}
#endif /* CCAN_LIST_DEBUG */
/* Quick test that catches a surprising number of bugs. */
- assert(!list_empty(h));
- list_del(n);
+ assert(!ccan_list_empty(h));
+ ccan_list_del(n);
}
/**
- * list_swap - swap out an entry from an (unknown) linked list for a new one.
- * @o: the list_node to replace from the list.
- * @n: the list_node to insert in place of the old one.
+ * ccan_list_swap - swap out an entry from an (unknown) linked list for a new one.
+ * @o: the ccan_list_node to replace from the list.
+ * @n: the ccan_list_node to insert in place of the old one.
*
* Note that this leaves @o in an undefined state; it can be added to
* another list, but not deleted/swapped again.
*
* See also:
- * list_del()
+ * ccan_list_del()
*
* Example:
* struct child x1, x2;
- * LIST_HEAD(xh);
+ * CCAN_LIST_HEAD(xh);
*
- * list_add(&xh, &x1.list);
- * list_swap(&x1.list, &x2.list);
+ * ccan_list_add(&xh, &x1.list);
+ * ccan_list_swap(&x1.list, &x2.list);
*/
-#define list_swap(o, n) list_swap_(o, n, LIST_LOC)
-static inline void list_swap_(struct list_node *o,
- struct list_node *n,
+#define ccan_list_swap(o, n) ccan_list_swap_(o, n, CCAN_LIST_LOC)
+static inline void ccan_list_swap_(struct ccan_list_node *o,
+ struct ccan_list_node *n,
const char* abortstr)
{
- (void)list_debug_node(o, abortstr);
+ (void)ccan_list_debug_node(o, abortstr);
*n = *o;
n->next->prev = n;
n->prev->next = n;
@@ -363,135 +363,135 @@ static inline void list_swap_(struct list_node *o,
}
/**
- * list_entry - convert a list_node back into the structure containing it.
- * @n: the list_node
+ * ccan_list_entry - convert a ccan_list_node back into the structure containing it.
+ * @n: the ccan_list_node
* @type: the type of the entry
- * @member: the list_node member of the type
+ * @member: the ccan_list_node member of the type
*
* Example:
* // First list entry is children.next; convert back to child.
- * child = list_entry(parent->children.n.next, struct child, list);
+ * child = ccan_list_entry(parent->children.n.next, struct child, list);
*
* See Also:
- * list_top(), list_for_each()
+ * ccan_list_top(), ccan_list_for_each()
*/
-#define list_entry(n, type, member) container_of(n, type, member)
+#define ccan_list_entry(n, type, member) ccan_container_of(n, type, member)
/**
- * list_top - get the first entry in a list
- * @h: the list_head
+ * ccan_list_top - get the first entry in a list
+ * @h: the ccan_list_head
* @type: the type of the entry
- * @member: the list_node member of the type
+ * @member: the ccan_list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *first;
- * first = list_top(&parent->children, struct child, list);
+ * first = ccan_list_top(&parent->children, struct child, list);
* if (!first)
* printf("Empty list!\n");
*/
-#define list_top(h, type, member) \
- ((type *)list_top_((h), list_off_(type, member)))
+#define ccan_list_top(h, type, member) \
+ ((type *)ccan_list_top_((h), ccan_list_off_(type, member)))
-static inline const void *list_top_(const struct list_head *h, size_t off)
+static inline const void *ccan_list_top_(const struct ccan_list_head *h, size_t off)
{
- if (list_empty(h))
+ if (ccan_list_empty(h))
return NULL;
return (const char *)h->n.next - off;
}
/**
- * list_pop - remove the first entry in a list
- * @h: the list_head
+ * ccan_list_pop - remove the first entry in a list
+ * @h: the ccan_list_head
* @type: the type of the entry
- * @member: the list_node member of the type
+ * @member: the ccan_list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *one;
- * one = list_pop(&parent->children, struct child, list);
+ * one = ccan_list_pop(&parent->children, struct child, list);
* if (!one)
* printf("Empty list!\n");
*/
-#define list_pop(h, type, member) \
- ((type *)list_pop_((h), list_off_(type, member)))
+#define ccan_list_pop(h, type, member) \
+ ((type *)ccan_list_pop_((h), ccan_list_off_(type, member)))
-static inline const void *list_pop_(const struct list_head *h, size_t off)
+static inline const void *ccan_list_pop_(const struct ccan_list_head *h, size_t off)
{
- struct list_node *n;
+ struct ccan_list_node *n;
- if (list_empty(h))
+ if (ccan_list_empty(h))
return NULL;
n = h->n.next;
- list_del(n);
+ ccan_list_del(n);
return (const char *)n - off;
}
/**
- * list_tail - get the last entry in a list
- * @h: the list_head
+ * ccan_list_tail - get the last entry in a list
+ * @h: the ccan_list_head
* @type: the type of the entry
- * @member: the list_node member of the type
+ * @member: the ccan_list_node member of the type
*
* If the list is empty, returns NULL.
*
* Example:
* struct child *last;
- * last = list_tail(&parent->children, struct child, list);
+ * last = ccan_list_tail(&parent->children, struct child, list);
* if (!last)
* printf("Empty list!\n");
*/
-#define list_tail(h, type, member) \
- ((type *)list_tail_((h), list_off_(type, member)))
+#define ccan_list_tail(h, type, member) \
+ ((type *)ccan_list_tail_((h), ccan_list_off_(type, member)))
-static inline const void *list_tail_(const struct list_head *h, size_t off)
+static inline const void *ccan_list_tail_(const struct ccan_list_head *h, size_t off)
{
- if (list_empty(h))
+ if (ccan_list_empty(h))
return NULL;
return (const char *)h->n.prev - off;
}
/**
- * list_for_each - iterate through a list.
- * @h: the list_head (warning: evaluated multiple times!)
- * @i: the structure containing the list_node
- * @member: the list_node member of the structure
+ * ccan_list_for_each - iterate through a list.
+ * @h: the ccan_list_head (warning: evaluated multiple times!)
+ * @i: the structure containing the ccan_list_node
+ * @member: the ccan_list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list. It's
* a for loop, so you can break and continue as normal.
*
* Example:
- * list_for_each(&parent->children, child, list)
+ * ccan_list_for_each(&parent->children, child, list)
* printf("Name: %s\n", child->name);
*/
-#define list_for_each(h, i, member) \
- list_for_each_off(h, i, list_off_var_(i, member))
+#define ccan_list_for_each(h, i, member) \
+ ccan_list_for_each_off(h, i, ccan_list_off_var_(i, member))
/**
- * list_for_each_rev - iterate through a list backwards.
- * @h: the list_head
- * @i: the structure containing the list_node
- * @member: the list_node member of the structure
+ * ccan_list_for_each_rev - iterate through a list backwards.
+ * @h: the ccan_list_head
+ * @i: the structure containing the ccan_list_node
+ * @member: the ccan_list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list. It's
* a for loop, so you can break and continue as normal.
*
* Example:
- * list_for_each_rev(&parent->children, child, list)
+ * ccan_list_for_each_rev(&parent->children, child, list)
* printf("Name: %s\n", child->name);
*/
-#define list_for_each_rev(h, i, member) \
- list_for_each_rev_off(h, i, list_off_var_(i, member))
+#define ccan_list_for_each_rev(h, i, member) \
+ ccan_list_for_each_rev_off(h, i, ccan_list_off_var_(i, member))
/**
- * list_for_each_rev_safe - iterate through a list backwards,
+ * ccan_list_for_each_rev_safe - iterate through a list backwards,
* maybe during deletion
- * @h: the list_head
- * @i: the structure containing the list_node
- * @nxt: the structure containing the list_node
- * @member: the list_node member of the structure
+ * @h: the ccan_list_head
+ * @i: the structure containing the ccan_list_node
+ * @nxt: the structure containing the ccan_list_node
+ * @member: the ccan_list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list backwards.
* It's a for loop, so you can break and continue as normal. The extra
@@ -500,74 +500,74 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
*
* Example:
* struct child *next;
- * list_for_each_rev_safe(&parent->children, child, next, list) {
+ * ccan_list_for_each_rev_safe(&parent->children, child, next, list) {
* printf("Name: %s\n", child->name);
* }
*/
-#define list_for_each_rev_safe(h, i, nxt, member) \
- list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member))
+#define ccan_list_for_each_rev_safe(h, i, nxt, member) \
+ ccan_list_for_each_rev_safe_off(h, i, nxt, ccan_list_off_var_(i, member))
/**
- * list_for_each_safe - iterate through a list, maybe during deletion
- * @h: the list_head
- * @i: the structure containing the list_node
- * @nxt: the structure containing the list_node
- * @member: the list_node member of the structure
+ * ccan_list_for_each_safe - iterate through a list, maybe during deletion
+ * @h: the ccan_list_head
+ * @i: the structure containing the ccan_list_node
+ * @nxt: the structure containing the ccan_list_node
+ * @member: the ccan_list_node member of the structure
*
* This is a convenient wrapper to iterate @i over the entire list. It's
* a for loop, so you can break and continue as normal. The extra variable
* @nxt is used to hold the next element, so you can delete @i from the list.
*
* Example:
- * list_for_each_safe(&parent->children, child, next, list) {
- * list_del(&child->list);
+ * ccan_list_for_each_safe(&parent->children, child, next, list) {
+ * ccan_list_del(&child->list);
* parent->num_children--;
* }
*/
-#define list_for_each_safe(h, i, nxt, member) \
- list_for_each_safe_off(h, i, nxt, list_off_var_(i, member))
+#define ccan_list_for_each_safe(h, i, nxt, member) \
+ ccan_list_for_each_safe_off(h, i, nxt, ccan_list_off_var_(i, member))
/**
- * list_next - get the next entry in a list
- * @h: the list_head
+ * ccan_list_next - get the next entry in a list
+ * @h: the ccan_list_head
* @i: a pointer to an entry in the list.
- * @member: the list_node member of the structure
+ * @member: the ccan_list_node member of the structure
*
* If @i was the last entry in the list, returns NULL.
*
* Example:
* struct child *second;
- * second = list_next(&parent->children, first, list);
+ * second = ccan_list_next(&parent->children, first, list);
* if (!second)
* printf("No second child!\n");
*/
-#define list_next(h, i, member) \
- ((list_typeof(i))list_entry_or_null(list_debug(h, \
- __FILE__ ":" stringify(__LINE__)), \
+#define ccan_list_next(h, i, member) \
+ ((ccan_list_typeof(i))ccan_list_entry_or_null(ccan_list_debug(h, \
+ __FILE__ ":" ccan_stringify(__LINE__)), \
(i)->member.next, \
- list_off_var_((i), member)))
+ ccan_list_off_var_((i), member)))
/**
- * list_prev - get the previous entry in a list
- * @h: the list_head
+ * ccan_list_prev - get the previous entry in a list
+ * @h: the ccan_list_head
* @i: a pointer to an entry in the list.
- * @member: the list_node member of the structure
+ * @member: the ccan_list_node member of the structure
*
* If @i was the first entry in the list, returns NULL.
*
* Example:
- * first = list_prev(&parent->children, second, list);
+ * first = ccan_list_prev(&parent->children, second, list);
* if (!first)
* printf("Can't go back to first child?!\n");
*/
-#define list_prev(h, i, member) \
- ((list_typeof(i))list_entry_or_null(list_debug(h, \
- __FILE__ ":" stringify(__LINE__)), \
+#define ccan_list_prev(h, i, member) \
+ ((ccan_list_typeof(i))ccan_list_entry_or_null(ccan_list_debug(h, \
+ __FILE__ ":" ccan_stringify(__LINE__)), \
(i)->member.prev, \
- list_off_var_((i), member)))
+ ccan_list_off_var_((i), member)))
/**
- * list_append_list - empty one list onto the end of another.
+ * ccan_list_append_list - empty one list onto the end of another.
* @to: the list to append into
* @from: the list to empty.
*
@@ -575,20 +575,20 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
* @to. After this @from will be empty.
*
* Example:
- * struct list_head adopter;
+ * struct ccan_list_head adopter;
*
- * list_append_list(&adopter, &parent->children);
- * assert(list_empty(&parent->children));
+ * ccan_list_append_list(&adopter, &parent->children);
+ * assert(ccan_list_empty(&parent->children));
* parent->num_children = 0;
*/
-#define list_append_list(t, f) list_append_list_(t, f, \
- __FILE__ ":" stringify(__LINE__))
-static inline void list_append_list_(struct list_head *to,
- struct list_head *from,
+#define ccan_list_append_list(t, f) ccan_list_append_list_(t, f, \
+ __FILE__ ":" ccan_stringify(__LINE__))
+static inline void ccan_list_append_list_(struct ccan_list_head *to,
+ struct ccan_list_head *from,
const char *abortstr)
{
- struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
- struct list_node *to_tail = list_debug(to, abortstr)->n.prev;
+ struct ccan_list_node *from_tail = ccan_list_debug(from, abortstr)->n.prev;
+ struct ccan_list_node *to_tail = ccan_list_debug(to, abortstr)->n.prev;
/* Sew in head and entire list. */
to->n.prev = from_tail;
@@ -597,12 +597,12 @@ static inline void list_append_list_(struct list_head *to,
from->n.prev = to_tail;
/* Now remove head. */
- list_del(&from->n);
- list_head_init(from);
+ ccan_list_del(&from->n);
+ ccan_list_head_init(from);
}
/**
- * list_prepend_list - empty one list into the start of another.
+ * ccan_list_prepend_list - empty one list into the start of another.
* @to: the list to prepend into
* @from: the list to empty.
*
@@ -610,17 +610,17 @@ static inline void list_append_list_(struct list_head *to,
* of @to. After this @from will be empty.
*
* Example:
- * list_prepend_list(&adopter, &parent->children);
- * assert(list_empty(&parent->children));
+ * ccan_list_prepend_list(&adopter, &parent->children);
+ * assert(ccan_list_empty(&parent->children));
* parent->num_children = 0;
*/
-#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC)
-static inline void list_prepend_list_(struct list_head *to,
- struct list_head *from,
+#define ccan_list_prepend_list(t, f) ccan_list_prepend_list_(t, f, CCAN_LIST_LOC)
+static inline void ccan_list_prepend_list_(struct ccan_list_head *to,
+ struct ccan_list_head *from,
const char *abortstr)
{
- struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
- struct list_node *to_head = list_debug(to, abortstr)->n.next;
+ struct ccan_list_node *from_tail = ccan_list_debug(from, abortstr)->n.prev;
+ struct ccan_list_node *to_head = ccan_list_debug(to, abortstr)->n.next;
/* Sew in head and entire list. */
to->n.next = &from->n;
@@ -629,31 +629,31 @@ static inline void list_prepend_list_(struct list_head *to,
from_tail->next = to_head;
/* Now remove head. */
- list_del(&from->n);
- list_head_init(from);
+ ccan_list_del(&from->n);
+ ccan_list_head_init(from);
}
/* internal macros, do not use directly */
-#define list_for_each_off_dir_(h, i, off, dir) \
- for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \
+#define ccan_list_for_each_off_dir_(h, i, off, dir) \
+ for (i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \
(off)); \
- list_node_from_off_((void *)i, (off)) != &(h)->n; \
- i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \
+ ccan_list_node_from_off_((void *)i, (off)) != &(h)->n; \
+ i = ccan_list_node_to_off_(ccan_list_node_from_off_((void *)i, (off))->dir, \
(off)))
-#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \
- for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \
+#define ccan_list_for_each_safe_off_dir_(h, i, nxt, off, dir) \
+ for (i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \
(off)), \
- nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \
+ nxt = ccan_list_node_to_off_(ccan_list_node_from_off_(i, (off))->dir, \
(off)); \
- list_node_from_off_(i, (off)) != &(h)->n; \
+ ccan_list_node_from_off_(i, (off)) != &(h)->n; \
i = nxt, \
- nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \
+ nxt = ccan_list_node_to_off_(ccan_list_node_from_off_(i, (off))->dir, \
(off)))
/**
- * list_for_each_off - iterate through a list of memory regions.
- * @h: the list_head
+ * ccan_list_for_each_off - iterate through a list of memory regions.
+ * @h: the ccan_list_head
* @i: the pointer to a memory region which contains list node data.
* @off: offset(relative to @i) at which list node data resides.
*
@@ -664,125 +664,126 @@ static inline void list_prepend_list_(struct list_head *to,
* WARNING! Being the low-level macro that it is, this wrapper doesn't know
* nor care about the type of @i. The only assumption made is that @i points
* to a chunk of memory that at some @offset, relative to @i, contains a
- * properly filled `struct list_node' which in turn contains pointers to
+ * properly filled `struct ccan_list_node' which in turn contains pointers to
* memory chunks and it's turtles all the way down. With all that in mind
* remember that given the wrong pointer/offset couple this macro will
* happily churn all you memory until SEGFAULT stops it, in other words
* caveat emptor.
*
* It is worth mentioning that one of legitimate use-cases for that wrapper
- * is operation on opaque types with known offset for `struct list_node'
+ * is operation on opaque types with known offset for `struct ccan_list_node'
* member(preferably 0), because it allows you not to disclose the type of
* @i.
*
* Example:
- * list_for_each_off(&parent->children, child,
+ * ccan_list_for_each_off(&parent->children, child,
* offsetof(struct child, list))
* printf("Name: %s\n", child->name);
*/
-#define list_for_each_off(h, i, off) \
- list_for_each_off_dir_((h),(i),(off),next)
+#define ccan_list_for_each_off(h, i, off) \
+ ccan_list_for_each_off_dir_((h),(i),(off),next)
/**
- * list_for_each_rev_off - iterate through a list of memory regions backwards
- * @h: the list_head
+ * ccan_list_for_each_rev_off - iterate through a list of memory regions backwards
+ * @h: the ccan_list_head
* @i: the pointer to a memory region which contains list node data.
* @off: offset(relative to @i) at which list node data resides.
*
- * See list_for_each_off for details
+ * See ccan_list_for_each_off for details
*/
-#define list_for_each_rev_off(h, i, off) \
- list_for_each_off_dir_((h),(i),(off),prev)
+#define ccan_list_for_each_rev_off(h, i, off) \
+ ccan_list_for_each_off_dir_((h),(i),(off),prev)
/**
- * list_for_each_safe_off - iterate through a list of memory regions, maybe
+ * ccan_list_for_each_safe_off - iterate through a list of memory regions, maybe
* during deletion
- * @h: the list_head
+ * @h: the ccan_list_head
* @i: the pointer to a memory region which contains list node data.
- * @nxt: the structure containing the list_node
+ * @nxt: the structure containing the ccan_list_node
* @off: offset(relative to @i) at which list node data resides.
*
- * For details see `list_for_each_off' and `list_for_each_safe'
+ * For details see `ccan_list_for_each_off' and `ccan_list_for_each_safe'
* descriptions.
*
* Example:
- * list_for_each_safe_off(&parent->children, child,
+ * ccan_list_for_each_safe_off(&parent->children, child,
* next, offsetof(struct child, list))
* printf("Name: %s\n", child->name);
*/
-#define list_for_each_safe_off(h, i, nxt, off) \
- list_for_each_safe_off_dir_((h),(i),(nxt),(off),next)
+#define ccan_list_for_each_safe_off(h, i, nxt, off) \
+ ccan_list_for_each_safe_off_dir_((h),(i),(nxt),(off),next)
/**
- * list_for_each_rev_safe_off - iterate backwards through a list of
+ * ccan_list_for_each_rev_safe_off - iterate backwards through a list of
* memory regions, maybe during deletion
- * @h: the list_head
+ * @h: the ccan_list_head
* @i: the pointer to a memory region which contains list node data.
- * @nxt: the structure containing the list_node
+ * @nxt: the structure containing the ccan_list_node
* @off: offset(relative to @i) at which list node data resides.
*
- * For details see `list_for_each_rev_off' and `list_for_each_rev_safe'
+ * For details see `ccan_list_for_each_rev_off' and `ccan_list_for_each_rev_safe'
* descriptions.
*
* Example:
- * list_for_each_rev_safe_off(&parent->children, child,
+ * ccan_list_for_each_rev_safe_off(&parent->children, child,
* next, offsetof(struct child, list))
* printf("Name: %s\n", child->name);
*/
-#define list_for_each_rev_safe_off(h, i, nxt, off) \
- list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev)
+#define ccan_list_for_each_rev_safe_off(h, i, nxt, off) \
+ ccan_list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev)
/* Other -off variants. */
-#define list_entry_off(n, type, off) \
- ((type *)list_node_from_off_((n), (off)))
+#define ccan_list_entry_off(n, type, off) \
+ ((type *)ccan_list_node_from_off_((n), (off)))
-#define list_head_off(h, type, off) \
- ((type *)list_head_off((h), (off)))
+#define ccan_list_head_off(h, type, off) \
+ ((type *)ccan_list_head_off((h), (off)))
-#define list_tail_off(h, type, off) \
- ((type *)list_tail_((h), (off)))
+#define ccan_list_tail_off(h, type, off) \
+ ((type *)ccan_list_tail_((h), (off)))
-#define list_add_off(h, n, off) \
- list_add((h), list_node_from_off_((n), (off)))
+#define ccan_list_add_off(h, n, off) \
+ ccan_list_add((h), ccan_list_node_from_off_((n), (off)))
-#define list_del_off(n, off) \
- list_del(list_node_from_off_((n), (off)))
+#define ccan_list_del_off(n, off) \
+ ccan_list_del(ccan_list_node_from_off_((n), (off)))
-#define list_del_from_off(h, n, off) \
- list_del_from(h, list_node_from_off_((n), (off)))
+#define ccan_list_del_from_off(h, n, off) \
+ ccan_list_del_from(h, ccan_list_node_from_off_((n), (off)))
/* Offset helper functions so we only single-evaluate. */
-static inline void *list_node_to_off_(struct list_node *node, size_t off)
+static inline void *ccan_list_node_to_off_(struct ccan_list_node *node, size_t off)
{
return (void *)((char *)node - off);
}
-static inline struct list_node *list_node_from_off_(void *ptr, size_t off)
+static inline struct ccan_list_node *ccan_list_node_from_off_(void *ptr, size_t off)
{
- return (struct list_node *)((char *)ptr + off);
+ return (struct ccan_list_node *)((char *)ptr + off);
}
-/* Get the offset of the member, but make sure it's a list_node. */
-#define list_off_(type, member) \
- (container_off(type, member) + \
- check_type(((type *)0)->member, struct list_node))
+/* Get the offset of the member, but make sure it's a ccan_list_node. */
+#define ccan_list_off_(type, member) \
+ (ccan_container_off(type, member) + \
+ ccan_check_type(((type *)0)->member, struct ccan_list_node))
-#define list_off_var_(var, member) \
- (container_off_var(var, member) + \
- check_type(var->member, struct list_node))
+#define ccan_list_off_var_(var, member) \
+ (ccan_container_off_var(var, member) + \
+ ccan_check_type(var->member, struct ccan_list_node))
-#if HAVE_TYPEOF
-#define list_typeof(var) typeof(var)
+#if defined(HAVE_TYPEOF) && HAVE_TYPEOF
+#define ccan_list_typeof(var) typeof(var)
#else
-#define list_typeof(var) void *
+#define ccan_list_typeof(var) void *
#endif
/* Returns member, or NULL if at end of list. */
-static inline void *list_entry_or_null(const struct list_head *h,
- const struct list_node *n,
+static inline void *ccan_list_entry_or_null(const struct ccan_list_head *h,
+ const struct ccan_list_node *n,
size_t off)
{
if (n == &h->n)
return NULL;
return (char *)n - off;
}
+
#endif /* CCAN_LIST_H */
diff --git a/ccan/str/str.h b/ccan/str/str.h
index 9a9da9cd3f..6d4cf62423 100644
--- a/ccan/str/str.h
+++ b/ccan/str/str.h
@@ -2,15 +2,16 @@
#ifndef CCAN_STR_H
#define CCAN_STR_H
/**
- * stringify - Turn expression into a string literal
+ * ccan_stringify - Turn expression into a string literal
* @expr: any C expression
*
* Example:
* #define PRINT_COND_IF_FALSE(cond) \
- * ((cond) || printf("%s is false!", stringify(cond)))
+ * ((cond) || printf("%s is false!", ccan_stringify(cond)))
*/
-#define stringify(expr) stringify_1(expr)
+#define stringify(expr) ccan_stringify_1(expr)
+#define ccan_stringify(expr) ccan_stringify_1(expr)
/* Double-indirection required to stringify expansions */
-#define stringify_1(expr) #expr
+#define ccan_stringify_1(expr) #expr
#endif /* CCAN_STR_H */
diff --git a/class.c b/class.c
index ef3db6dab3..cf0b7b821f 100644
--- a/class.c
+++ b/class.c
@@ -10,16 +10,7 @@
**********************************************************************/
/*!
- * \defgroup class Classes and their hierarchy.
- * \par Terminology
- * - class: same as in Ruby.
- * - singleton class: class for a particular object
- * - eigenclass: = singleton class
- * - metaclass: class of a class. metaclass is a kind of singleton class.
- * - metametaclass: class of a metaclass.
- * - meta^(n)-class: class of a meta^(n-1)-class.
- * - attached object: A singleton class knows its unique instance.
- * The instance is called the attached object for the singleton class.
+ * \addtogroup class
* \{
*/
@@ -46,94 +37,122 @@
RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
-void
-rb_class_subclass_add(VALUE super, VALUE klass)
+static rb_subclass_entry_t *
+push_subclass_entry_to_list(VALUE super, VALUE klass)
{
rb_subclass_entry_t *entry, *head;
- if (super && super != Qundef) {
- entry = ALLOC(rb_subclass_entry_t);
- entry->klass = klass;
- entry->next = NULL;
+ entry = ZALLOC(rb_subclass_entry_t);
+ entry->klass = klass;
- head = RCLASS_SUBCLASSES(super);
- if (head) {
- entry->next = head;
- RCLASS_PARENT_SUBCLASSES(head->klass) = &entry->next;
- }
+ head = RCLASS_SUBCLASSES(super);
+ if (!head) {
+ head = ZALLOC(rb_subclass_entry_t);
+ RCLASS_SUBCLASSES(super) = head;
+ }
+ entry->next = head->next;
+ entry->prev = head;
+
+ if (head->next) {
+ head->next->prev = entry;
+ }
+ head->next = entry;
- RCLASS_SUBCLASSES(super) = entry;
- RCLASS_PARENT_SUBCLASSES(klass) = &RCLASS_SUBCLASSES(super);
+ return entry;
+}
+
+void
+rb_class_subclass_add(VALUE super, VALUE klass)
+{
+ if (super && !UNDEF_P(super)) {
+ rb_subclass_entry_t *entry = push_subclass_entry_to_list(super, klass);
+ RCLASS_SUBCLASS_ENTRY(klass) = entry;
}
}
static void
rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
{
- rb_subclass_entry_t *entry, *head;
+ rb_subclass_entry_t *entry = push_subclass_entry_to_list(module, iclass);
+ RCLASS_MODULE_SUBCLASS_ENTRY(iclass) = entry;
+}
- entry = ALLOC(rb_subclass_entry_t);
- entry->klass = iclass;
- entry->next = NULL;
+void
+rb_class_remove_subclass_head(VALUE klass)
+{
+ rb_subclass_entry_t *head = RCLASS_SUBCLASSES(klass);
- head = RCLASS_SUBCLASSES(module);
if (head) {
- entry->next = head;
- RCLASS_MODULE_SUBCLASSES(head->klass) = &entry->next;
+ if (head->next) {
+ head->next->prev = NULL;
+ }
+ RCLASS_SUBCLASSES(klass) = NULL;
+ xfree(head);
}
-
- RCLASS_SUBCLASSES(module) = entry;
- RCLASS_MODULE_SUBCLASSES(iclass) = &RCLASS_SUBCLASSES(module);
}
void
rb_class_remove_from_super_subclasses(VALUE klass)
{
- rb_subclass_entry_t *entry;
+ rb_subclass_entry_t *entry = RCLASS_SUBCLASS_ENTRY(klass);
- if (RCLASS_PARENT_SUBCLASSES(klass)) {
- entry = *RCLASS_PARENT_SUBCLASSES(klass);
+ if (entry) {
+ rb_subclass_entry_t *prev = entry->prev, *next = entry->next;
- *RCLASS_PARENT_SUBCLASSES(klass) = entry->next;
- if (entry->next) {
- RCLASS_PARENT_SUBCLASSES(entry->next->klass) = RCLASS_PARENT_SUBCLASSES(klass);
- }
- xfree(entry);
+ if (prev) {
+ prev->next = next;
+ }
+ if (next) {
+ next->prev = prev;
+ }
+
+ xfree(entry);
}
- RCLASS_PARENT_SUBCLASSES(klass) = NULL;
+ RCLASS_SUBCLASS_ENTRY(klass) = NULL;
}
void
rb_class_remove_from_module_subclasses(VALUE klass)
{
- rb_subclass_entry_t *entry;
+ rb_subclass_entry_t *entry = RCLASS_MODULE_SUBCLASS_ENTRY(klass);
- if (RCLASS_MODULE_SUBCLASSES(klass)) {
- entry = *RCLASS_MODULE_SUBCLASSES(klass);
- *RCLASS_MODULE_SUBCLASSES(klass) = entry->next;
+ if (entry) {
+ rb_subclass_entry_t *prev = entry->prev, *next = entry->next;
- if (entry->next) {
- RCLASS_MODULE_SUBCLASSES(entry->next->klass) = RCLASS_MODULE_SUBCLASSES(klass);
- }
+ if (prev) {
+ prev->next = next;
+ }
+ if (next) {
+ next->prev = prev;
+ }
- xfree(entry);
+ xfree(entry);
}
- RCLASS_MODULE_SUBCLASSES(klass) = NULL;
+ RCLASS_MODULE_SUBCLASS_ENTRY(klass) = NULL;
}
void
rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE arg)
{
+ // RCLASS_SUBCLASSES should always point to our head element which has NULL klass
rb_subclass_entry_t *cur = RCLASS_SUBCLASSES(klass);
+ // if we have a subclasses list, then the head is a placeholder with no valid
+ // class. So ignore it and use the next element in the list (if one exists)
+ if (cur) {
+ RUBY_ASSERT(!cur->klass);
+ cur = cur->next;
+ }
/* do not be tempted to simplify this loop into a for loop, the order of
operations is important here if `f` modifies the linked list */
while (cur) {
- VALUE curklass = cur->klass;
- cur = cur->next;
- f(curklass, arg);
+ VALUE curklass = cur->klass;
+ cur = cur->next;
+ // do not trigger GC during f, otherwise the cur will become
+ // a dangling pointer if the subclass is collected
+ f(curklass, arg);
}
}
@@ -176,23 +195,24 @@ rb_class_detach_module_subclasses(VALUE klass)
static VALUE
class_alloc(VALUE flags, VALUE klass)
{
- size_t payload_size = 0;
+ size_t alloc_size = sizeof(struct RClass);
-#if USE_RVARGC
- payload_size = sizeof(rb_classext_t);
+#if RCLASS_EXT_EMBEDDED
+ alloc_size += sizeof(rb_classext_t);
#endif
- RVARGC_NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | FL_PROMOTED1 /* start from age == 2 */ | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0), payload_size);
+ flags &= T_MASK;
+ flags |= FL_PROMOTED1 /* start from age == 2 */;
+ if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
+ RVARGC_NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size);
-#if USE_RVARGC
- obj->ptr = (rb_classext_t *)rb_rvargc_payload_data_ptr((VALUE)obj + rb_slot_size());
- RB_OBJ_WRITTEN(obj, Qundef, (VALUE)obj + rb_slot_size());
+#if RCLASS_EXT_EMBEDDED
+ memset(RCLASS_EXT(obj), 0, sizeof(rb_classext_t));
#else
obj->ptr = ZALLOC(rb_classext_t);
#endif
/* ZALLOC
- RCLASS_IV_TBL(obj) = 0;
RCLASS_CONST_TBL(obj) = 0;
RCLASS_M_TBL(obj) = 0;
RCLASS_IV_INDEX_TBL(obj) = 0;
@@ -202,7 +222,6 @@ class_alloc(VALUE flags, VALUE klass)
RCLASS_MODULE_SUBCLASSES(obj) = NULL;
*/
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
- RCLASS_SERIAL(obj) = rb_next_class_serial();
RB_OBJ_WRITE(obj, &RCLASS_REFINED_CLASS(obj), Qnil);
RCLASS_ALLOCATOR(obj) = 0;
@@ -235,53 +254,103 @@ rb_class_boot(VALUE super)
return (VALUE)klass;
}
+static VALUE *
+class_superclasses_including_self(VALUE klass)
+{
+ if (FL_TEST_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF))
+ return RCLASS_SUPERCLASSES(klass);
+
+ size_t depth = RCLASS_SUPERCLASS_DEPTH(klass);
+ VALUE *superclasses = xmalloc(sizeof(VALUE) * (depth + 1));
+ if (depth > 0)
+ memcpy(superclasses, RCLASS_SUPERCLASSES(klass), sizeof(VALUE) * depth);
+ superclasses[depth] = klass;
+
+ RCLASS_SUPERCLASSES(klass) = superclasses;
+ FL_SET_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF);
+ return superclasses;
+}
+
+void
+rb_class_update_superclasses(VALUE klass)
+{
+ VALUE super = RCLASS_SUPER(klass);
+
+ if (!RB_TYPE_P(klass, T_CLASS)) return;
+ if (UNDEF_P(super)) return;
+
+ // If the superclass array is already built
+ if (RCLASS_SUPERCLASSES(klass))
+ return;
+
+ // find the proper superclass
+ while (super != Qfalse && !RB_TYPE_P(super, T_CLASS)) {
+ super = RCLASS_SUPER(super);
+ }
+
+ // For BasicObject and uninitialized classes, depth=0 and ary=NULL
+ if (super == Qfalse)
+ return;
+
+ // Sometimes superclasses are set before the full ancestry tree is built
+ // This happens during metaclass construction
+ if (super != rb_cBasicObject && !RCLASS_SUPERCLASS_DEPTH(super)) {
+ rb_class_update_superclasses(super);
+
+ // If it is still unset we need to try later
+ if (!RCLASS_SUPERCLASS_DEPTH(super))
+ return;
+ }
+
+ RCLASS_SUPERCLASSES(klass) = class_superclasses_including_self(super);
+ RCLASS_SUPERCLASS_DEPTH(klass) = RCLASS_SUPERCLASS_DEPTH(super) + 1;
+}
-/*!
- * Ensures a class can be derived from super.
- *
- * \param super a reference to an object.
- * \exception TypeError if \a super is not a Class or \a super is a singleton class.
- */
void
rb_check_inheritable(VALUE super)
{
if (!RB_TYPE_P(super, T_CLASS)) {
rb_raise(rb_eTypeError, "superclass must be an instance of Class (given an instance of %"PRIsVALUE")",
- rb_obj_class(super));
+ rb_obj_class(super));
}
if (RBASIC(super)->flags & FL_SINGLETON) {
- rb_raise(rb_eTypeError, "can't make subclass of singleton class");
+ rb_raise(rb_eTypeError, "can't make subclass of singleton class");
}
if (super == rb_cClass) {
- rb_raise(rb_eTypeError, "can't make subclass of Class");
+ rb_raise(rb_eTypeError, "can't make subclass of Class");
}
}
-
-/*!
- * Creates a new class.
- * \param super a class from which the new class derives.
- * \exception TypeError \a super is not inheritable.
- * \exception TypeError \a super is the Class class.
- */
VALUE
rb_class_new(VALUE super)
{
Check_Type(super, T_CLASS);
rb_check_inheritable(super);
- return rb_class_boot(super);
+ VALUE klass = rb_class_boot(super);
+
+ if (super != rb_cObject && super != rb_cBasicObject) {
+ RCLASS_EXT(klass)->max_iv_count = RCLASS_EXT(super)->max_iv_count;
+ }
+
+ return klass;
+}
+
+VALUE
+rb_class_s_alloc(VALUE klass)
+{
+ return rb_class_boot(0);
}
static void
clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t *me)
{
if (me->def->type == VM_METHOD_TYPE_ISEQ) {
- rb_cref_t *new_cref;
- rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass, &new_cref);
- rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
+ rb_cref_t *new_cref;
+ rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass, &new_cref);
+ rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
}
else {
- rb_method_entry_set(new_klass, mid, me, METHOD_ENTRY_VISI(me));
+ rb_method_entry_set(new_klass, mid, me, METHOD_ENTRY_VISI(me));
}
}
@@ -325,56 +394,119 @@ static void
class_init_copy_check(VALUE clone, VALUE orig)
{
if (orig == rb_cBasicObject) {
- rb_raise(rb_eTypeError, "can't copy the root class");
+ rb_raise(rb_eTypeError, "can't copy the root class");
}
if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
- rb_raise(rb_eTypeError, "already initialized class");
+ rb_raise(rb_eTypeError, "already initialized class");
}
if (FL_TEST(orig, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "can't copy singleton class");
+ rb_raise(rb_eTypeError, "can't copy singleton class");
}
}
+struct cvc_table_copy_ctx {
+ VALUE clone;
+ struct rb_id_table * new_table;
+};
+
+static enum rb_id_table_iterator_result
+cvc_table_copy(ID id, VALUE val, void *data) {
+ struct cvc_table_copy_ctx *ctx = (struct cvc_table_copy_ctx *)data;
+ struct rb_cvar_class_tbl_entry * orig_entry;
+ orig_entry = (struct rb_cvar_class_tbl_entry *)val;
+
+ struct rb_cvar_class_tbl_entry *ent;
+
+ ent = ALLOC(struct rb_cvar_class_tbl_entry);
+ ent->class_value = ctx->clone;
+ ent->cref = orig_entry->cref;
+ ent->global_cvar_state = orig_entry->global_cvar_state;
+ rb_id_table_insert(ctx->new_table, id, (VALUE)ent);
+
+ RB_OBJ_WRITTEN(ctx->clone, Qundef, ent->cref);
+
+ return ID_TABLE_CONTINUE;
+}
+
static void
copy_tables(VALUE clone, VALUE orig)
{
- if (RCLASS_IV_TBL(clone)) {
- st_free_table(RCLASS_IV_TBL(clone));
- RCLASS_IV_TBL(clone) = 0;
- }
if (RCLASS_CONST_TBL(clone)) {
- rb_free_const_table(RCLASS_CONST_TBL(clone));
- RCLASS_CONST_TBL(clone) = 0;
+ rb_free_const_table(RCLASS_CONST_TBL(clone));
+ RCLASS_CONST_TBL(clone) = 0;
+ }
+ if (RCLASS_CVC_TBL(orig)) {
+ struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(orig);
+ struct rb_id_table *rb_cvc_tbl_dup = rb_id_table_create(rb_id_table_size(rb_cvc_tbl));
+
+ struct cvc_table_copy_ctx ctx;
+ ctx.clone = clone;
+ ctx.new_table = rb_cvc_tbl_dup;
+ rb_id_table_foreach(rb_cvc_tbl, cvc_table_copy, &ctx);
+ RCLASS_CVC_TBL(clone) = rb_cvc_tbl_dup;
}
+ rb_id_table_free(RCLASS_M_TBL(clone));
RCLASS_M_TBL(clone) = 0;
- if (RCLASS_IV_TBL(orig)) {
- st_data_t id;
+ if (!RB_TYPE_P(clone, T_ICLASS)) {
+ st_data_t id;
- rb_iv_tbl_copy(clone, orig);
- CONST_ID(id, "__tmp_classpath__");
- st_delete(RCLASS_IV_TBL(clone), &id, 0);
- CONST_ID(id, "__classpath__");
- st_delete(RCLASS_IV_TBL(clone), &id, 0);
- CONST_ID(id, "__classid__");
- st_delete(RCLASS_IV_TBL(clone), &id, 0);
+ rb_iv_tbl_copy(clone, orig);
+ CONST_ID(id, "__tmp_classpath__");
+ rb_attr_delete(clone, id);
+ CONST_ID(id, "__classpath__");
+ rb_attr_delete(clone, id);
}
if (RCLASS_CONST_TBL(orig)) {
- struct clone_const_arg arg;
+ struct clone_const_arg arg;
- arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
- arg.klass = clone;
- rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg);
+ arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
+ arg.klass = clone;
+ rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg);
}
}
static bool ensure_origin(VALUE klass);
+/**
+ * If this flag is set, that module is allocated but not initialized yet.
+ */
+enum {RMODULE_ALLOCATED_BUT_NOT_INITIALIZED = RUBY_FL_USER5};
+
+static inline bool
+RMODULE_UNINITIALIZED(VALUE module)
+{
+ return FL_TEST_RAW(module, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
+}
+
+void
+rb_module_set_initialized(VALUE mod)
+{
+ FL_UNSET_RAW(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
+ /* no more re-initialization */
+}
+
+void
+rb_module_check_initializable(VALUE mod)
+{
+ if (!RMODULE_UNINITIALIZED(mod)) {
+ rb_raise(rb_eTypeError, "already initialized module");
+ }
+}
+
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
- if (RB_TYPE_P(clone, T_CLASS)) {
+ switch (BUILTIN_TYPE(clone)) {
+ case T_CLASS:
+ case T_ICLASS:
class_init_copy_check(clone, orig);
+ break;
+ case T_MODULE:
+ rb_module_check_initializable(clone);
+ break;
+ default:
+ break;
}
if (!OBJ_INIT_COPY(clone, orig)) return clone;
@@ -386,16 +518,16 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
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);
+ rb_singleton_class_attached(METACLASS_OF(clone), (VALUE)clone);
}
RCLASS_ALLOCATOR(clone) = RCLASS_ALLOCATOR(orig);
copy_tables(clone, orig);
if (RCLASS_M_TBL(orig)) {
- struct clone_method_arg arg;
- arg.old_klass = orig;
- arg.new_klass = clone;
- RCLASS_M_TBL_INIT(clone);
- rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
+ struct clone_method_arg arg;
+ arg.old_klass = orig;
+ arg.new_klass = clone;
+ RCLASS_M_TBL_INIT(clone);
+ rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
}
if (RCLASS_ORIGIN(orig) == orig) {
@@ -405,7 +537,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
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_stack = rb_ary_hidden_new(2);
VALUE origin[2];
VALUE clone_p = 0;
long origin_len;
@@ -419,12 +551,11 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
if (BUILTIN_TYPE(p) != T_ICLASS) {
rb_bug("non iclass between module/class and origin");
}
- clone_p = class_alloc(RBASIC(p)->flags, RBASIC(p)->klass);
+ clone_p = class_alloc(RBASIC(p)->flags, METACLASS_OF(p));
RCLASS_SET_SUPER(prev_clone_p, clone_p);
prev_clone_p = clone_p;
RCLASS_M_TBL(clone_p) = RCLASS_M_TBL(p);
RCLASS_CONST_TBL(clone_p) = RCLASS_CONST_TBL(p);
- RCLASS_IV_TBL(clone_p) = RCLASS_IV_TBL(p);
RCLASS_ALLOCATOR(clone_p) = RCLASS_ALLOCATOR(p);
if (RB_TYPE_P(clone, T_CLASS)) {
RCLASS_SET_INCLUDER(clone_p, clone);
@@ -443,7 +574,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
add_subclass = FALSE;
}
if (add_subclass) {
- rb_module_add_to_subclasses_list(RBASIC(p)->klass, clone_p);
+ rb_module_add_to_subclasses_list(METACLASS_OF(p), clone_p);
}
p = RCLASS_SUPER(p);
}
@@ -465,6 +596,8 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
else {
rb_bug("no origin for class that has origin");
}
+
+ rb_class_update_superclasses(clone);
}
return clone;
@@ -480,7 +613,7 @@ rb_singleton_class_clone(VALUE obj)
VALUE
rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
{
- const VALUE klass = RBASIC(obj)->klass;
+ const VALUE klass = METACLASS_OF(obj);
// Note that `rb_singleton_class()` can create situations where `klass` is
// attached to an object other than `obj`. In which case `obj` does not have
@@ -491,61 +624,55 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
return klass;
}
else {
- /* copy singleton(unnamed) class */
+ /* copy singleton(unnamed) class */
bool klass_of_clone_is_new;
- VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
+ VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
- if (BUILTIN_TYPE(obj) == T_CLASS) {
+ if (BUILTIN_TYPE(obj) == T_CLASS) {
klass_of_clone_is_new = true;
- RBASIC_SET_CLASS(clone, clone);
- }
- else {
+ RBASIC_SET_CLASS(clone, clone);
+ }
+ else {
VALUE klass_metaclass_clone = rb_singleton_class_clone(klass);
// When `METACLASS_OF(klass) == klass_metaclass_clone`, it means the
// recursive call did not clone `METACLASS_OF(klass)`.
klass_of_clone_is_new = (METACLASS_OF(klass) != klass_metaclass_clone);
RBASIC_SET_CLASS(clone, klass_metaclass_clone);
- }
-
- RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
- RCLASS_ALLOCATOR(clone) = RCLASS_ALLOCATOR(klass);
- if (RCLASS_IV_TBL(klass)) {
- rb_iv_tbl_copy(clone, klass);
- }
- if (RCLASS_CONST_TBL(klass)) {
- struct clone_const_arg arg;
- arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
- arg.klass = clone;
- rb_id_table_foreach(RCLASS_CONST_TBL(klass), clone_const_i, &arg);
- }
- if (attach != Qundef) {
- rb_singleton_class_attached(clone, attach);
- }
- RCLASS_M_TBL_INIT(clone);
- {
- struct clone_method_arg arg;
- arg.old_klass = klass;
- arg.new_klass = clone;
- rb_id_table_foreach(RCLASS_M_TBL(klass), clone_method_i, &arg);
- }
+ }
+
+ RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
+ RCLASS_ALLOCATOR(clone) = RCLASS_ALLOCATOR(klass);
+ rb_iv_tbl_copy(clone, klass);
+ if (RCLASS_CONST_TBL(klass)) {
+ struct clone_const_arg arg;
+ arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
+ arg.klass = clone;
+ rb_id_table_foreach(RCLASS_CONST_TBL(klass), clone_const_i, &arg);
+ }
+ if (!UNDEF_P(attach)) {
+ rb_singleton_class_attached(clone, attach);
+ }
+ RCLASS_M_TBL_INIT(clone);
+ {
+ struct clone_method_arg arg;
+ arg.old_klass = klass;
+ arg.new_klass = clone;
+ rb_id_table_foreach(RCLASS_M_TBL(klass), clone_method_i, &arg);
+ }
if (klass_of_clone_is_new) {
- rb_singleton_class_attached(RBASIC(clone)->klass, clone);
+ rb_singleton_class_attached(METACLASS_OF(clone), clone);
}
- FL_SET(clone, FL_SINGLETON);
+ FL_SET(clone, FL_SINGLETON);
- return clone;
+ return clone;
}
}
-/*!
- * Attach a object to a singleton class.
- * @pre \a klass is the singleton class of \a obj.
- */
void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
if (FL_TEST(klass, FL_SINGLETON)) {
- rb_class_ivar_set(klass, id_attached, obj);
+ rb_class_ivar_set(klass, id_attached, obj);
}
}
@@ -566,7 +693,7 @@ int
rb_singleton_class_internal_p(VALUE sklass)
{
return (RB_TYPE_P(rb_attr_get(sklass, id_attached), T_CLASS) &&
- !rb_singleton_class_has_metaclass_p(sklass));
+ !rb_singleton_class_has_metaclass_p(sklass));
}
/*!
@@ -608,19 +735,22 @@ make_metaclass(VALUE klass)
rb_singleton_class_attached(metaclass, klass);
if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
- SET_METACLASS_OF(klass, metaclass);
- SET_METACLASS_OF(metaclass, metaclass);
+ SET_METACLASS_OF(klass, metaclass);
+ SET_METACLASS_OF(metaclass, metaclass);
}
else {
- VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */
- SET_METACLASS_OF(klass, metaclass);
- SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
+ VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */
+ SET_METACLASS_OF(klass, metaclass);
+ SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
}
super = RCLASS_SUPER(klass);
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
+ // Full class ancestry may not have been filled until we reach here.
+ rb_class_update_superclasses(METACLASS_OF(metaclass));
+
return metaclass;
}
@@ -633,7 +763,7 @@ make_metaclass(VALUE klass)
static inline VALUE
make_singleton_class(VALUE obj)
{
- VALUE orig_class = RBASIC(obj)->klass;
+ VALUE orig_class = METACLASS_OF(obj);
VALUE klass = rb_class_boot(orig_class);
FL_SET(klass, FL_SINGLETON);
@@ -656,6 +786,58 @@ boot_defclass(const char *name, VALUE super)
return obj;
}
+/***********************************************************************
+ *
+ * Document-class: Refinement
+ *
+ * Refinement is a class of the +self+ (current context) inside +refine+
+ * statement. It allows to import methods from other modules, see #import_methods.
+ */
+
+#if 0 /* for RDoc */
+/*
+ * Document-method: Refinement#import_methods
+ *
+ * call-seq:
+ * import_methods(module, ...) -> self
+ *
+ * Imports methods from modules. Unlike Module#include,
+ * Refinement#import_methods copies methods and adds them into the refinement,
+ * so the refinement is activated in the imported methods.
+ *
+ * Note that due to method copying, only methods defined in Ruby code can be imported.
+ *
+ * module StrUtils
+ * def indent(level)
+ * ' ' * level + self
+ * end
+ * end
+ *
+ * module M
+ * refine String do
+ * import_methods StrUtils
+ * end
+ * end
+ *
+ * using M
+ * "foo".indent(3)
+ * #=> " foo"
+ *
+ * module M
+ * refine String do
+ * import_methods Enumerable
+ * # Can't import method which is not defined with Ruby code: Enumerable#drop
+ * end
+ * end
+ *
+ */
+
+static VALUE
+refinement_import_methods(int argc, VALUE *argv, VALUE refinement)
+{
+}
+# endif
+
void
Init_class_hierarchy(void)
{
@@ -668,12 +850,21 @@ Init_class_hierarchy(void)
rb_cModule = boot_defclass("Module", rb_cObject);
rb_cClass = boot_defclass("Class", rb_cModule);
+ rb_cRefinement = boot_defclass("Refinement", rb_cModule);
+
+#if 0 /* for RDoc */
+ // we pretend it to be public, otherwise RDoc will ignore it
+ rb_define_method(rb_cRefinement, "import_methods", refinement_import_methods, -1);
+#endif
rb_const_set(rb_cObject, rb_intern_const("BasicObject"), rb_cBasicObject);
RBASIC_SET_CLASS(rb_cClass, rb_cClass);
RBASIC_SET_CLASS(rb_cModule, rb_cClass);
RBASIC_SET_CLASS(rb_cObject, rb_cClass);
+ RBASIC_SET_CLASS(rb_cRefinement, rb_cClass);
RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);
+
+ ENSURE_EIGENCLASS(rb_cRefinement);
}
@@ -691,24 +882,13 @@ VALUE
rb_make_metaclass(VALUE obj, VALUE unused)
{
if (BUILTIN_TYPE(obj) == T_CLASS) {
- return make_metaclass(obj);
+ return make_metaclass(obj);
}
else {
- return make_singleton_class(obj);
+ return make_singleton_class(obj);
}
}
-
-/*!
- * Defines a new class.
- * \param id ignored
- * \param super A class from which the new class will derive. NULL means \c Object class.
- * \return the created class
- * \throw TypeError if super is not a \c Class object.
- *
- * \note the returned class will not be associated with \a id.
- * You must explicitly set a class name if necessary.
- */
VALUE
rb_define_class_id(ID id, VALUE super)
{
@@ -716,7 +896,7 @@ rb_define_class_id(ID id, VALUE super)
if (!super) super = rb_cObject;
klass = rb_class_new(super);
- rb_make_metaclass(klass, RBASIC(super)->klass);
+ rb_make_metaclass(klass, METACLASS_OF(super));
return klass;
}
@@ -739,23 +919,6 @@ rb_class_inherited(VALUE super, VALUE klass)
return rb_funcall(super, inherited, 1, klass);
}
-
-
-/*!
- * Defines a top-level class.
- * \param name name of the class
- * \param super a class from which the new class will derive.
- * \return the created class
- * \throw TypeError if the constant name \a name is already taken but
- * the constant is not a \c Class.
- * \throw TypeError if the class is already defined but the class can not
- * be reopened because its superclass is not \a super.
- * \throw ArgumentError if the \a super is NULL.
- * \post top-level constant named \a name refers the returned class.
- *
- * \note if a class named \a name is already defined and its superclass is
- * \a super, the function just returns the defined class.
- */
VALUE
rb_define_class(const char *name, VALUE super)
{
@@ -764,21 +927,21 @@ rb_define_class(const char *name, VALUE super)
id = rb_intern(name);
if (rb_const_defined(rb_cObject, id)) {
- klass = rb_const_get(rb_cObject, id);
- if (!RB_TYPE_P(klass, T_CLASS)) {
- rb_raise(rb_eTypeError, "%s is not a class (%"PRIsVALUE")",
- name, rb_obj_class(klass));
- }
- if (rb_class_real(RCLASS_SUPER(klass)) != super) {
- rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
- }
+ klass = rb_const_get(rb_cObject, id);
+ if (!RB_TYPE_P(klass, T_CLASS)) {
+ rb_raise(rb_eTypeError, "%s is not a class (%"PRIsVALUE")",
+ name, rb_obj_class(klass));
+ }
+ if (rb_class_real(RCLASS_SUPER(klass)) != super) {
+ rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
+ }
/* Class may have been defined in Ruby and not pin-rooted */
rb_vm_add_root_module(klass);
- return klass;
+ return klass;
}
if (!super) {
- rb_raise(rb_eArgError, "no super class for `%s'", name);
+ rb_raise(rb_eArgError, "no super class for `%s'", name);
}
klass = rb_define_class_id(id, super);
rb_vm_add_root_module(klass);
@@ -788,92 +951,82 @@ rb_define_class(const char *name, VALUE super)
return klass;
}
-
-/*!
- * Defines a class under the namespace of \a outer.
- * \param outer a class which contains the new class.
- * \param name name of the new class
- * \param super a class from which the new class will derive.
- * NULL means \c Object class.
- * \return the created class
- * \throw TypeError if the constant name \a name is already taken but
- * the constant is not a \c Class.
- * \throw TypeError if the class is already defined but the class can not
- * be reopened because its superclass is not \a super.
- * \post top-level constant named \a name refers the returned class.
- *
- * \note if a class named \a name is already defined and its superclass is
- * \a super, the function just returns the defined class.
- * \note the compaction GC does not move classes returned by this function.
- */
VALUE
rb_define_class_under(VALUE outer, const char *name, VALUE super)
{
return rb_define_class_id_under(outer, rb_intern(name), super);
}
-
-/*!
- * Defines a class under the namespace of \a outer.
- * \param outer a class which contains the new class.
- * \param id name of the new class
- * \param super a class from which the new class will derive.
- * NULL means \c Object class.
- * \return the created class
- * \throw TypeError if the constant name \a name is already taken but
- * the constant is not a \c Class.
- * \throw TypeError if the class is already defined but the class can not
- * be reopened because its superclass is not \a super.
- * \post top-level constant named \a name refers the returned class.
- *
- * \note if a class named \a name is already defined and its superclass is
- * \a super, the function just returns the defined class.
- * \note the compaction GC does not move classes returned by this function.
- */
VALUE
-rb_define_class_id_under(VALUE outer, ID id, VALUE super)
+rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super)
{
VALUE klass;
if (rb_const_defined_at(outer, id)) {
- klass = rb_const_get_at(outer, id);
- if (!RB_TYPE_P(klass, T_CLASS)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE"::%"PRIsVALUE" is not a class"
- " (%"PRIsVALUE")",
- outer, rb_id2str(id), rb_obj_class(klass));
- }
- if (rb_class_real(RCLASS_SUPER(klass)) != super) {
- rb_raise(rb_eTypeError, "superclass mismatch for class "
- "%"PRIsVALUE"::%"PRIsVALUE""
- " (%"PRIsVALUE" is given but was %"PRIsVALUE")",
- outer, rb_id2str(id), RCLASS_SUPER(klass), super);
- }
- /* Class may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(klass);
+ klass = rb_const_get_at(outer, id);
+ if (!RB_TYPE_P(klass, T_CLASS)) {
+ rb_raise(rb_eTypeError, "%"PRIsVALUE"::%"PRIsVALUE" is not a class"
+ " (%"PRIsVALUE")",
+ outer, rb_id2str(id), rb_obj_class(klass));
+ }
+ if (rb_class_real(RCLASS_SUPER(klass)) != super) {
+ rb_raise(rb_eTypeError, "superclass mismatch for class "
+ "%"PRIsVALUE"::%"PRIsVALUE""
+ " (%"PRIsVALUE" is given but was %"PRIsVALUE")",
+ outer, rb_id2str(id), RCLASS_SUPER(klass), super);
+ }
- return klass;
+ return klass;
}
if (!super) {
- rb_raise(rb_eArgError, "no super class for `%"PRIsVALUE"::%"PRIsVALUE"'",
- rb_class_path(outer), rb_id2str(id));
+ rb_raise(rb_eArgError, "no super class for `%"PRIsVALUE"::%"PRIsVALUE"'",
+ rb_class_path(outer), rb_id2str(id));
}
klass = rb_define_class_id(id, super);
rb_set_class_path_string(klass, outer, rb_id2str(id));
rb_const_set(outer, id, klass);
rb_class_inherited(super, klass);
- rb_vm_add_root_module(klass);
return klass;
}
VALUE
-rb_module_new(void)
+rb_define_class_id_under(VALUE outer, ID id, VALUE super)
+{
+ VALUE klass = rb_define_class_id_under_no_pin(outer, id, super);
+ rb_vm_add_root_module(klass);
+ return klass;
+}
+
+VALUE
+rb_module_s_alloc(VALUE klass)
+{
+ VALUE mod = class_alloc(T_MODULE, klass);
+ RCLASS_M_TBL_INIT(mod);
+ FL_SET(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
+ return mod;
+}
+
+static inline VALUE
+module_new(VALUE klass)
{
- VALUE mdl = class_alloc(T_MODULE, rb_cModule);
+ VALUE mdl = class_alloc(T_MODULE, klass);
RCLASS_M_TBL_INIT(mdl);
return (VALUE)mdl;
}
+VALUE
+rb_module_new(void)
+{
+ return module_new(rb_cModule);
+}
+
+VALUE
+rb_refinement_new(void)
+{
+ return module_new(rb_cRefinement);
+}
+
// Kept for compatibility. Use rb_module_new() instead.
VALUE
rb_define_module_id(ID id)
@@ -881,9 +1034,6 @@ rb_define_module_id(ID id)
return rb_module_new();
}
-/*!
- * \note the compaction GC does not move modules returned by this function.
- */
VALUE
rb_define_module(const char *name)
{
@@ -892,14 +1042,14 @@ rb_define_module(const char *name)
id = rb_intern(name);
if (rb_const_defined(rb_cObject, id)) {
- module = rb_const_get(rb_cObject, id);
- if (!RB_TYPE_P(module, T_MODULE)) {
- rb_raise(rb_eTypeError, "%s is not a module (%"PRIsVALUE")",
- name, rb_obj_class(module));
- }
+ module = rb_const_get(rb_cObject, id);
+ if (!RB_TYPE_P(module, T_MODULE)) {
+ rb_raise(rb_eTypeError, "%s is not a module (%"PRIsVALUE")",
+ name, rb_obj_class(module));
+ }
/* Module may have been defined in Ruby and not pin-rooted */
rb_vm_add_root_module(module);
- return module;
+ return module;
}
module = rb_module_new();
rb_vm_add_root_module(module);
@@ -908,9 +1058,6 @@ rb_define_module(const char *name)
return module;
}
-/*!
- * \note the compaction GC does not move modules returned by this function.
- */
VALUE
rb_define_module_under(VALUE outer, const char *name)
{
@@ -923,15 +1070,15 @@ rb_define_module_id_under(VALUE outer, ID id)
VALUE module;
if (rb_const_defined_at(outer, id)) {
- module = rb_const_get_at(outer, id);
- if (!RB_TYPE_P(module, T_MODULE)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE"::%"PRIsVALUE" is not a module"
- " (%"PRIsVALUE")",
- outer, rb_id2str(id), rb_obj_class(module));
- }
+ module = rb_const_get_at(outer, id);
+ if (!RB_TYPE_P(module, T_MODULE)) {
+ rb_raise(rb_eTypeError, "%"PRIsVALUE"::%"PRIsVALUE" is not a module"
+ " (%"PRIsVALUE")",
+ outer, rb_id2str(id), rb_obj_class(module));
+ }
/* Module may have been defined in Ruby and not pin-rooted */
rb_gc_register_mark_object(module);
- return module;
+ return module;
}
module = rb_module_new();
rb_const_set(outer, id, module);
@@ -950,16 +1097,13 @@ rb_include_class_new(VALUE module, VALUE super)
RCLASS_SET_ORIGIN(klass, klass);
if (BUILTIN_TYPE(module) == T_ICLASS) {
- module = RBASIC(module)->klass;
+ module = METACLASS_OF(module);
}
RUBY_ASSERT(!RB_TYPE_P(module, T_ICLASS));
- if (!RCLASS_IV_TBL(module)) {
- RCLASS_IV_TBL(module) = st_init_numtable();
- }
if (!RCLASS_CONST_TBL(module)) {
- RCLASS_CONST_TBL(module) = rb_id_table_create(0);
+ RCLASS_CONST_TBL(module) = rb_id_table_create(0);
}
- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
+
RCLASS_CVC_TBL(klass) = RCLASS_CVC_TBL(module);
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
@@ -976,8 +1120,9 @@ ensure_includable(VALUE klass, VALUE module)
{
rb_class_modify_check(klass);
Check_Type(module, T_MODULE);
+ rb_module_set_initialized(module);
if (!NIL_P(rb_refinement_module_get_refined_class(module))) {
- rb_raise(rb_eArgError, "refinement module is not allowed");
+ rb_raise(rb_eArgError, "refinement module is not allowed");
}
}
@@ -990,24 +1135,37 @@ 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");
+ rb_raise(rb_eArgError, "cyclic include detected");
if (RB_TYPE_P(klass, T_MODULE)) {
rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES(klass);
- int do_include = 1;
+ // skip the placeholder subclass entry at the head of the list
+ if (iclass) {
+ RUBY_ASSERT(!iclass->klass);
+ iclass = iclass->next;
+ }
+
while (iclass) {
+ int do_include = 1;
VALUE check_class = iclass->klass;
- while (check_class) {
- if (RB_TYPE_P(check_class, T_ICLASS) &&
- (RBASIC(check_class)->klass == module)) {
- do_include = 0;
+ /* 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) {
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(check_class));
+
+ if (RB_TYPE_P(check_class, T_ICLASS) &&
+ (METACLASS_OF(check_class) == module)) {
+ do_include = 0;
+ }
+ check_class = RCLASS_SUPER(check_class);
}
- check_class = RCLASS_SUPER(check_class);
- }
- if (do_include) {
- include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE);
+ if (do_include) {
+ include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE);
+ }
}
+
iclass = iclass->next;
}
}
@@ -1042,11 +1200,20 @@ module_in_super_chain(const VALUE klass, VALUE module)
return false;
}
+// For each ID key in the class constant table, we're going to clear the VM's
+// inline constant caches associated with it.
+static enum rb_id_table_iterator_result
+clear_constant_cache_i(ID id, VALUE value, void *data)
+{
+ rb_clear_constant_cache_for_id(id);
+ return ID_TABLE_CONTINUE;
+}
+
static int
do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super, bool check_cyclic)
{
VALUE p, iclass, origin_stack = 0;
- int method_changed = 0, constant_changed = 0, add_subclass;
+ int method_changed = 0;
long origin_len;
VALUE klass_origin = RCLASS_ORIGIN(klass);
VALUE original_klass = klass;
@@ -1056,8 +1223,8 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
while (module) {
int c_seen = FALSE;
- int superclass_seen = FALSE;
- struct rb_id_table *tbl;
+ int superclass_seen = FALSE;
+ struct rb_id_table *tbl;
if (klass == c) {
c_seen = TRUE;
@@ -1107,12 +1274,11 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
}
// setup T_ICLASS for the include/prepend module
- iclass = rb_include_class_new(module, super_class);
- c = RCLASS_SET_SUPER(c, iclass);
+ 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);
+ if (!origin_stack) origin_stack = rb_ary_hidden_new(2);
VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)};
rb_ary_cat(origin_stack, origin, 2);
}
@@ -1121,31 +1287,27 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
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;
- if (add_subclass) rb_module_add_to_subclasses_list(m, iclass);
- }
+ VALUE m = module;
+ if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
+ rb_module_add_to_subclasses_list(m, iclass);
- if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
- VALUE refined_class =
- rb_refinement_module_get_refined_class(klass);
+ if (BUILTIN_TYPE(klass) == T_MODULE && FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
+ VALUE refined_class =
+ rb_refinement_module_get_refined_class(klass);
rb_id_table_foreach(RCLASS_M_TBL(module), add_refined_method_entry_i, (void *)refined_class);
- FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
- }
+ RUBY_ASSERT(BUILTIN_TYPE(c) == T_MODULE);
+ }
tbl = RCLASS_CONST_TBL(module);
- if (tbl && rb_id_table_size(tbl)) constant_changed = 1;
+ if (tbl && rb_id_table_size(tbl))
+ rb_id_table_foreach(tbl, clear_constant_cache_i, NULL);
skip:
- module = RCLASS_SUPER(module);
+ module = RCLASS_SUPER(module);
}
- if (constant_changed) rb_clear_constant_cache();
-
return method_changed;
}
@@ -1165,20 +1327,20 @@ move_refined_method(ID key, VALUE value, void *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);
+ 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_method_table_insert(klass, tbl, key, new_me);
- rb_method_entry_copy(me, orig_me);
- return ID_TABLE_CONTINUE;
- }
- else {
+ rb_method_entry_copy(me, orig_me);
+ return ID_TABLE_CONTINUE;
+ }
+ else {
rb_method_table_insert(klass, tbl, key, me);
- return ID_TABLE_DELETE;
- }
+ return ID_TABLE_DELETE;
+ }
}
else {
- return ID_TABLE_CONTINUE;
+ return ID_TABLE_CONTINUE;
}
}
@@ -1202,14 +1364,14 @@ ensure_origin(VALUE klass)
{
VALUE origin = RCLASS_ORIGIN(klass);
if (origin == klass) {
- origin = class_alloc(T_ICLASS, klass);
- RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
- RCLASS_SET_SUPER(klass, origin);
- RCLASS_SET_ORIGIN(klass, origin);
- RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
- RCLASS_M_TBL_INIT(klass);
+ origin = class_alloc(T_ICLASS, klass);
+ RCLASS_SET_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);
+ rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass);
return true;
}
return false;
@@ -1229,25 +1391,37 @@ rb_prepend_module(VALUE klass, VALUE module)
changed = do_include_modules_at(klass, klass, module, FALSE, false);
RUBY_ASSERT(changed >= 0); // already checked for cyclic prepend above
if (changed) {
- rb_vm_check_redefinition_by_prepend(klass);
+ rb_vm_check_redefinition_by_prepend(klass);
}
if (RB_TYPE_P(klass, T_MODULE)) {
rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES(klass);
+ // skip the placeholder subclass entry at the head of the list if it exists
+ if (iclass) {
+ RUBY_ASSERT(!iclass->klass);
+ iclass = iclass->next;
+ }
+
VALUE klass_origin = RCLASS_ORIGIN(klass);
struct rb_id_table *klass_m_tbl = RCLASS_M_TBL(klass);
struct rb_id_table *klass_origin_m_tbl = RCLASS_M_TBL(klass_origin);
while (iclass) {
- if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) {
- // backfill an origin iclass to handle refinements and future prepends
- rb_id_table_foreach(RCLASS_M_TBL(iclass->klass), clear_module_cache_i, (void *)iclass->klass);
- RCLASS_M_TBL(iclass->klass) = klass_m_tbl;
- VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(iclass->klass));
- RCLASS_SET_SUPER(iclass->klass, origin);
- RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(iclass->klass));
- RCLASS_SET_ORIGIN(iclass->klass, origin);
- RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
+ /* During lazy sweeping, iclass->klass could be a dead object that
+ * has not yet been swept. */
+ if (!rb_objspace_garbage_object_p(iclass->klass)) {
+ const VALUE subclass = iclass->klass;
+ if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(subclass)) {
+ // backfill an origin iclass to handle refinements and future prepends
+ rb_id_table_foreach(RCLASS_M_TBL(subclass), clear_module_cache_i, (void *)subclass);
+ RCLASS_M_TBL(subclass) = klass_m_tbl;
+ VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(subclass));
+ RCLASS_SET_SUPER(subclass, origin);
+ RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(subclass));
+ RCLASS_SET_ORIGIN(subclass, origin);
+ RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
+ }
+ include_modules_at(subclass, subclass, module, FALSE);
}
- include_modules_at(iclass->klass, iclass->klass, module, FALSE);
+
iclass = iclass->next;
}
}
@@ -1284,10 +1458,10 @@ rb_mod_included_modules(VALUE mod)
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
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);
- }
+ VALUE m = METACLASS_OF(p);
+ if (RB_TYPE_P(m, T_MODULE))
+ rb_ary_push(ary, m);
+ }
}
return ary;
}
@@ -1319,8 +1493,8 @@ rb_mod_include_p(VALUE mod, VALUE mod2)
Check_Type(mod2, T_MODULE);
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) {
- if (RBASIC(p)->klass == mod2) return Qtrue;
- }
+ if (METACLASS_OF(p) == mod2) return Qtrue;
+ }
}
return Qfalse;
}
@@ -1347,19 +1521,149 @@ VALUE
rb_mod_ancestors(VALUE mod)
{
VALUE p, ary = rb_ary_new();
+ VALUE refined_class = Qnil;
+ if (BUILTIN_TYPE(mod) == T_MODULE && FL_TEST(mod, RMODULE_IS_REFINEMENT)) {
+ refined_class = rb_refinement_module_get_refined_class(mod);
+ }
for (p = mod; p; p = RCLASS_SUPER(p)) {
+ if (p == refined_class) break;
if (p != RCLASS_ORIGIN(p)) continue;
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
+ if (BUILTIN_TYPE(p) == T_ICLASS) {
+ rb_ary_push(ary, METACLASS_OF(p));
+ }
else {
- rb_ary_push(ary, p);
- }
+ rb_ary_push(ary, p);
+ }
}
return ary;
}
+struct subclass_traverse_data
+{
+ VALUE buffer;
+ long count;
+ long maxcount;
+ bool immediate_only;
+};
+
+static void
+class_descendants_recursive(VALUE klass, VALUE v)
+{
+ struct subclass_traverse_data *data = (struct subclass_traverse_data *) v;
+
+ if (BUILTIN_TYPE(klass) == T_CLASS && !FL_TEST(klass, FL_SINGLETON)) {
+ if (data->buffer && data->count < data->maxcount && !rb_objspace_garbage_object_p(klass)) {
+ // assumes that this does not cause GC as long as the length does not exceed the capacity
+ rb_ary_push(data->buffer, klass);
+ }
+ data->count++;
+ if (!data->immediate_only) {
+ rb_class_foreach_subclass(klass, class_descendants_recursive, v);
+ }
+ }
+ else {
+ rb_class_foreach_subclass(klass, class_descendants_recursive, v);
+ }
+}
+
+static VALUE
+class_descendants(VALUE klass, bool immediate_only)
+{
+ struct subclass_traverse_data data = { Qfalse, 0, -1, immediate_only };
+
+ // estimate the count of subclasses
+ rb_class_foreach_subclass(klass, class_descendants_recursive, (VALUE) &data);
+
+ // the following allocation may cause GC which may change the number of subclasses
+ data.buffer = rb_ary_new_capa(data.count);
+ data.maxcount = data.count;
+ data.count = 0;
+
+ size_t gc_count = rb_gc_count();
+
+ // enumerate subclasses
+ rb_class_foreach_subclass(klass, class_descendants_recursive, (VALUE) &data);
+
+ if (gc_count != rb_gc_count()) {
+ rb_bug("GC must not occur during the subclass iteration of Class#descendants");
+ }
+
+ return data.buffer;
+}
+
+/*
+ * call-seq:
+ * subclasses -> array
+ *
+ * Returns an array of classes where the receiver is the
+ * direct superclass of the class, excluding singleton classes.
+ * The order of the returned array is not defined.
+ *
+ * class A; end
+ * class B < A; end
+ * class C < B; end
+ * class D < A; end
+ *
+ * A.subclasses #=> [D, B]
+ * B.subclasses #=> [C]
+ * C.subclasses #=> []
+ *
+ * Anonymous subclasses (not associated with a constant) are
+ * returned, too:
+ *
+ * c = Class.new(A)
+ * A.subclasses # => [#<Class:0x00007f003c77bd78>, D, B]
+ *
+ * Note that the parent does not hold references to subclasses
+ * and doesn't prevent them from being garbage collected. This
+ * means that the subclass might disappear when all references
+ * to it are dropped:
+ *
+ * # drop the reference to subclass, it can be garbage-collected now
+ * c = nil
+ *
+ * A.subclasses
+ * # It can be
+ * # => [#<Class:0x00007f003c77bd78>, D, B]
+ * # ...or just
+ * # => [D, B]
+ * # ...depending on whether garbage collector was run
+ */
+
+VALUE
+rb_class_subclasses(VALUE klass)
+{
+ return class_descendants(klass, true);
+}
+
+/*
+ * call-seq:
+ * attached_object -> object
+ *
+ * Returns the object for which the receiver is the singleton class.
+ *
+ * Raises an TypeError if the class is not a singleton class.
+ *
+ * class Foo; end
+ *
+ * Foo.singleton_class.attached_object #=> Foo
+ * Foo.attached_object #=> TypeError: `Foo' is not a singleton class
+ * Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
+ * TrueClass.attached_object #=> TypeError: `TrueClass' is not a singleton class
+ * NilClass.attached_object #=> TypeError: `NilClass' is not a singleton class
+ */
+
+VALUE
+rb_class_attached_object(VALUE klass)
+{
+ if (!FL_TEST(klass, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "`%"PRIsVALUE"' is not a singleton class", klass);
+ }
+
+ return rb_attr_get(klass, id_attached);
+}
+
static void
ins_methods_push(st_data_t name, st_data_t ary)
{
@@ -1372,10 +1676,10 @@ ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
switch ((rb_method_visibility_t)type) {
case METHOD_VISI_UNDEF:
case METHOD_VISI_PRIVATE:
- break;
+ break;
default: /* everything but private */
- ins_methods_push(name, ary);
- break;
+ ins_methods_push(name, ary);
+ break;
}
return ST_CONTINUE;
}
@@ -1384,7 +1688,7 @@ static int
ins_methods_type_i(st_data_t name, st_data_t type, st_data_t ary, rb_method_visibility_t visi)
{
if ((rb_method_visibility_t)type == visi) {
- ins_methods_push(name, ary);
+ ins_methods_push(name, ary);
}
return ST_CONTINUE;
}
@@ -1407,6 +1711,12 @@ ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
return ins_methods_type_i(name, type, ary, METHOD_VISI_PUBLIC);
}
+static int
+ins_methods_undef_i(st_data_t name, st_data_t type, st_data_t ary)
+{
+ return ins_methods_type_i(name, type, ary, METHOD_VISI_UNDEF);
+}
+
struct method_entry_arg {
st_table *list;
int recur;
@@ -1420,19 +1730,20 @@ method_entry_i(ID key, VALUE value, void *data)
rb_method_visibility_t type;
if (me->def->type == VM_METHOD_TYPE_REFINED) {
- VALUE owner = me->owner;
- me = rb_resolve_refined_method(Qnil, me);
- if (!me) return ID_TABLE_CONTINUE;
- if (!arg->recur && me->owner != owner) return ID_TABLE_CONTINUE;
+ VALUE owner = me->owner;
+ me = rb_resolve_refined_method(Qnil, me);
+ if (!me) return ID_TABLE_CONTINUE;
+ if (!arg->recur && me->owner != owner) return ID_TABLE_CONTINUE;
}
if (!st_is_member(arg->list, key)) {
- if (UNDEFINED_METHOD_ENTRY_P(me)) {
- type = METHOD_VISI_UNDEF; /* none */
- }
- else {
- type = METHOD_ENTRY_VISI(me);
- }
- st_add_direct(arg->list, key, (st_data_t)type);
+ if (UNDEFINED_METHOD_ENTRY_P(me)) {
+ type = METHOD_VISI_UNDEF; /* none */
+ }
+ else {
+ type = METHOD_ENTRY_VISI(me);
+ RUBY_ASSERT(type != METHOD_VISI_UNDEF);
+ }
+ st_add_direct(arg->list, key, (st_data_t)type);
}
return ID_TABLE_CONTINUE;
}
@@ -1473,14 +1784,14 @@ class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int
}
if (!recur && RCLASS_ORIGIN(mod) != mod) {
- mod = RCLASS_ORIGIN(mod);
- prepended = 1;
+ mod = RCLASS_ORIGIN(mod);
+ prepended = 1;
}
for (; mod; mod = RCLASS_SUPER(mod)) {
add_instance_method_list(mod, &me_arg);
- if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
- if (!recur) break;
+ if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
+ if (!recur) break;
}
ary = rb_ary_new2(me_arg.list->num_entries);
st_foreach(me_arg.list, func, ary);
@@ -1514,6 +1825,15 @@ class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int
* B.instance_methods(true).include?(:method1) #=> true
* C.instance_methods(false) #=> [:method3]
* C.instance_methods.include?(:method2) #=> true
+ *
+ * Note that method visibility changes in the current class, as well as aliases,
+ * are considered as methods of the current class by this method:
+ *
+ * class C < B
+ * alias method4 method2
+ * protected :method2
+ * end
+ * C.instance_methods(false).sort #=> [:method2, :method3, :method4]
*/
VALUE
@@ -1577,6 +1897,21 @@ rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod)
/*
* call-seq:
+ * mod.undefined_instance_methods -> array
+ *
+ * Returns a list of the undefined instance methods defined in <i>mod</i>.
+ * The undefined methods of any ancestors are not included.
+ */
+
+VALUE
+rb_class_undefined_instance_methods(VALUE mod)
+{
+ VALUE include_super = Qfalse;
+ return class_instance_method_list(1, &include_super, mod, 0, ins_methods_undef_i);
+}
+
+/*
+ * call-seq:
* obj.methods(regular=true) -> array
*
* Returns a list of the names of public and protected methods of
@@ -1610,7 +1945,7 @@ rb_obj_methods(int argc, const VALUE *argv, VALUE obj)
{
rb_check_arity(argc, 0, 1);
if (argc > 0 && !RTEST(argv[0])) {
- return rb_obj_singleton_methods(argc, argv, obj);
+ return rb_obj_singleton_methods(argc, argv, obj);
}
return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
}
@@ -1710,14 +2045,14 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
me_arg.list = st_init_numtable();
me_arg.recur = recur;
if (klass && FL_TEST(klass, FL_SINGLETON)) {
- if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
- klass = RCLASS_SUPER(klass);
+ if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
+ klass = RCLASS_SUPER(klass);
}
if (recur) {
- while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
- if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
- klass = RCLASS_SUPER(klass);
- }
+ while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
+ if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
+ klass = RCLASS_SUPER(klass);
+ }
}
ary = rb_ary_new2(me_arg.list->num_entries);
st_foreach(me_arg.list, ins_methods_i, ary);
@@ -1730,56 +2065,7 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
* \}
*/
/*!
- * \defgroup defmethod Defining methods
- * There are some APIs to define a method from C.
- * These API takes a C function as a method body.
- *
- * \par Method body functions
- * Method body functions must return a VALUE and
- * can be one of the following form:
- * <dl>
- * <dt>Fixed number of parameters</dt>
- * <dd>
- * This form is a normal C function, excepting it takes
- * a receiver object as the first argument.
- *
- * \code
- * static VALUE my_method(VALUE self, VALUE x, VALUE y);
- * \endcode
- * </dd>
- * <dt>argc and argv style</dt>
- * <dd>
- * This form takes three parameters: \a argc, \a argv and \a self.
- * \a self is the receiver. \a argc is the number of arguments.
- * \a argv is a pointer to an array of the arguments.
- *
- * \code
- * static VALUE my_method(int argc, VALUE *argv, VALUE self);
- * \endcode
- * </dd>
- * <dt>Ruby array style</dt>
- * <dd>
- * This form takes two parameters: self and args.
- * \a self is the receiver. \a args is an Array object which
- * contains the arguments.
- *
- * \code
- * static VALUE my_method(VALUE self, VALUE args);
- * \endcode
- * </dd>
- *
- * \par Number of parameters
- * Method defining APIs takes the number of parameters which the
- * method will takes. This number is called \a argc.
- * \a argc can be:
- * <dl>
- * <dt>zero or positive number</dt>
- * <dd>This means the method body function takes a fixed number of parameters</dd>
- * <dt>-1</dt>
- * <dd>This means the method body function is "argc and argv" style.</dd>
- * <dt>-2</dt>
- * <dd>This means the method body function is "self and args" style.</dd>
- * </dl>
+ * \addtogroup defmethod
* \{
*/
@@ -1838,7 +2124,7 @@ rb_undef_methods_from(VALUE klass, VALUE super)
{
struct rb_id_table *mtbl = RCLASS_M_TBL(super);
if (mtbl) {
- rb_id_table_foreach(mtbl, undef_method_i, (void *)klass);
+ rb_id_table_foreach(mtbl, undef_method_i, (void *)klass);
}
}
@@ -1886,15 +2172,15 @@ singleton_class_of(VALUE obj)
case T_BIGNUM:
case T_FLOAT:
case T_SYMBOL:
- rb_raise(rb_eTypeError, "can't define singleton");
+ rb_raise(rb_eTypeError, "can't define singleton");
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;
+ klass = special_singleton_class_of(obj);
+ if (NIL_P(klass))
+ rb_bug("unknown immediate %p", (void *)obj);
+ return klass;
case T_STRING:
if (FL_TEST_RAW(obj, RSTRING_FSTR)) {
@@ -1902,12 +2188,10 @@ singleton_class_of(VALUE obj)
}
}
- klass = RBASIC(obj)->klass;
+ klass = METACLASS_OF(obj);
if (!(FL_TEST(klass, FL_SINGLETON) &&
rb_attr_get(klass, id_attached) == obj)) {
- rb_serial_t serial = RCLASS_SERIAL(klass);
- klass = rb_make_metaclass(obj, klass);
- RCLASS_SERIAL(klass) = serial;
+ klass = rb_make_metaclass(obj, klass);
}
RB_FL_SET_RAW(klass, RB_OBJ_FROZEN_RAW(obj));
@@ -1920,11 +2204,11 @@ rb_freeze_singleton_class(VALUE x)
{
/* should not propagate to meta-meta-class, and so on */
if (!(RBASIC(x)->flags & FL_SINGLETON)) {
- VALUE klass = RBASIC_CLASS(x);
- if (klass && (klass = RCLASS_ORIGIN(klass)) != 0 &&
- FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) {
- OBJ_FREEZE_RAW(klass);
- }
+ VALUE klass = RBASIC_CLASS(x);
+ if (klass && // no class when hidden from ObjectSpace
+ FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) {
+ OBJ_FREEZE_RAW(klass);
+ }
}
}
@@ -1941,31 +2225,14 @@ rb_singleton_class_get(VALUE obj)
VALUE klass;
if (SPECIAL_CONST_P(obj)) {
- return rb_special_singleton_class(obj);
+ return rb_special_singleton_class(obj);
}
- klass = RBASIC(obj)->klass;
+ klass = METACLASS_OF(obj);
if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
if (rb_attr_get(klass, id_attached) != obj) return Qnil;
return klass;
}
-/*!
- * Returns the singleton class of \a obj. Creates it if necessary.
- *
- * \param obj an arbitrary object.
- * \throw TypeError if \a obj is an Integer or a Symbol.
- * \return the singleton class.
- *
- * \post \a obj has its own singleton class.
- * \post if \a obj is a class,
- * the returned singleton class also has its own
- * singleton class in order to keep consistency of the
- * inheritance structure of metaclasses.
- * \note a new singleton class will be created
- * if \a obj does not have it.
- * \note the singleton classes for nil, true and false are:
- * NilClass, TrueClass and FalseClass.
- */
VALUE
rb_singleton_class(VALUE obj)
{
@@ -1989,13 +2256,6 @@ rb_singleton_class(VALUE obj)
#ifdef rb_define_singleton_method
#undef rb_define_singleton_method
#endif
-/*!
- * Defines a singleton method for \a obj.
- * \param obj an arbitrary object
- * \param name name of the singleton method
- * \param func the method body
- * \param argc the number of parameters, or -1 or -2. see \ref defmethod.
- */
void
rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
{
@@ -2005,13 +2265,6 @@ rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS),
#ifdef rb_define_module_function
#undef rb_define_module_function
#endif
-/*!
- * Defines a module function for \a module.
- * \param module an module or a class.
- * \param name name of the function
- * \param func the method body
- * \param argc the number of parameters, or -1 or -2. see \ref defmethod.
- */
void
rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
{
@@ -2022,38 +2275,18 @@ rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS)
#ifdef rb_define_global_function
#undef rb_define_global_function
#endif
-/*!
- * Defines a global function
- * \param name name of the function
- * \param func the method body
- * \param argc the number of parameters, or -1 or -2. see \ref defmethod.
- */
void
rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_define_module_function(rb_mKernel, name, func, argc);
}
-
-/*!
- * Defines an alias of a method.
- * \param klass the class which the original method belongs to
- * \param name1 a new name for the method
- * \param name2 the original name of the method
- */
void
rb_define_alias(VALUE klass, const char *name1, const char *name2)
{
rb_alias(klass, rb_intern(name1), rb_intern(name2));
}
-/*!
- * Defines (a) public accessor method(s) for an attribute.
- * \param klass the class which the attribute will belongs to
- * \param name name of the attribute
- * \param read a getter method for the attribute will be defined if \a read is non-zero.
- * \param write a setter method for the attribute will be defined if \a write is non-zero.
- */
void
rb_define_attr(VALUE klass, const char *name, int read, int write)
{
@@ -2067,13 +2300,13 @@ rb_keyword_error_new(const char *error, VALUE keys)
VALUE error_message = rb_sprintf("%s keyword%.*s", error, len > 1, "s");
if (len > 0) {
- rb_str_cat_cstr(error_message, ": ");
- while (1) {
+ rb_str_cat_cstr(error_message, ": ");
+ while (1) {
const VALUE k = RARRAY_AREF(keys, i);
- rb_str_append(error_message, rb_inspect(k));
- if (++i >= len) break;
- rb_str_cat_cstr(error_message, ", ");
- }
+ rb_str_append(error_message, rb_inspect(k));
+ if (++i >= len) break;
+ rb_str_cat_cstr(error_message, ", ");
+ }
}
return rb_exc_new_str(rb_eArgError, error_message);
@@ -2092,7 +2325,7 @@ unknown_keyword_error(VALUE hash, const ID *table, int keywords)
{
int i;
for (i = 0; i < keywords; i++) {
- st_data_t key = ID2SYM(table[i]);
+ st_data_t key = ID2SYM(table[i]);
rb_hash_stlike_delete(hash, &key, NULL);
}
rb_keyword_error("unknown", rb_hash_keys(hash));
@@ -2116,8 +2349,8 @@ rb_extract_keywords(VALUE *orighash)
VALUE hash = *orighash;
if (RHASH_EMPTY_P(hash)) {
- *orighash = 0;
- return hash;
+ *orighash = 0;
+ return hash;
}
rb_hash_foreach(hash, separate_symbol, (st_data_t)&parthash);
*orighash = parthash[1];
@@ -2143,36 +2376,36 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V
if (NIL_P(keyword_hash)) keyword_hash = 0;
if (optional < 0) {
- rest = 1;
- optional = -1-optional;
+ rest = 1;
+ optional = -1-optional;
}
if (required) {
- for (; i < required; i++) {
- VALUE keyword = ID2SYM(table[i]);
- if (keyword_hash) {
+ for (; i < required; i++) {
+ VALUE keyword = ID2SYM(table[i]);
+ if (keyword_hash) {
if (extract_kwarg(keyword, values[i])) {
- continue;
- }
- }
- if (NIL_P(missing)) missing = rb_ary_tmp_new(1);
- rb_ary_push(missing, keyword);
- }
- if (!NIL_P(missing)) {
- rb_keyword_error("missing", missing);
- }
+ continue;
+ }
+ }
+ if (NIL_P(missing)) missing = rb_ary_hidden_new(1);
+ rb_ary_push(missing, keyword);
+ }
+ if (!NIL_P(missing)) {
+ rb_keyword_error("missing", missing);
+ }
}
j = i;
if (optional && keyword_hash) {
- for (i = 0; i < optional; i++) {
+ for (i = 0; i < optional; i++) {
if (extract_kwarg(ID2SYM(table[required+i]), values[required+i])) {
- j++;
- }
- }
+ j++;
+ }
+ }
}
if (!rest && keyword_hash) {
- if (RHASH_SIZE(keyword_hash) > (unsigned int)(values ? 0 : j)) {
- unknown_keyword_error(keyword_hash, table, required+optional);
- }
+ if (RHASH_SIZE(keyword_hash) > (unsigned int)(values ? 0 : j)) {
+ unknown_keyword_error(keyword_hash, table, required+optional);
+ }
}
if (values && !keyword_hash) {
for (i = 0; i < required + optional; i++) {
@@ -2203,30 +2436,30 @@ rb_scan_args_parse(int kw_flag, const char *fmt, struct rb_scan_args_t *arg)
if (ISDIGIT(*p)) {
arg->n_lead = *p - '0';
- p++;
- if (ISDIGIT(*p)) {
+ p++;
+ if (ISDIGIT(*p)) {
arg->n_opt = *p - '0';
- p++;
- }
+ p++;
+ }
}
if (*p == '*') {
arg->f_var = 1;
- p++;
+ p++;
}
if (ISDIGIT(*p)) {
arg->n_trail = *p - '0';
- p++;
+ p++;
}
if (*p == ':') {
arg->f_hash = 1;
- p++;
+ p++;
}
if (*p == '&') {
arg->f_block = 1;
- p++;
+ p++;
}
if (*p != '\0') {
- rb_fatal("bad scan arg format: %s", fmt);
+ rb_fatal("bad scan arg format: %s", fmt);
}
}
@@ -2262,37 +2495,37 @@ rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *con
for (i = 0; i < n_lead; i++) {
var = rb_scan_args_next_param();
if (var) *var = argv[argi];
- 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;
- }
+ 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 (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();
- }
+ 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++;
+ argi++;
}
/* capture an option hash - phase 2: assignment */
if (f_hash) {
@@ -2302,12 +2535,12 @@ rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *con
/* 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 (rb_block_given_p()) {
+ *var = rb_block_proc();
+ }
+ else {
+ *var = Qnil;
+ }
}
if (argi == argc) {
@@ -2363,12 +2596,6 @@ rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...)
return rb_scan_args_result(&arg, argc);
}
-int
-rb_class_has_methods(VALUE c)
-{
- return rb_id_table_size(RCLASS_M_TBL(c)) == 0 ? FALSE : TRUE;
-}
-
/*!
* \}
*/
diff --git a/common.mk b/common.mk
index 164d927970..126053c9c8 100644
--- a/common.mk
+++ b/common.mk
@@ -18,8 +18,10 @@ mflags = $(MFLAGS)
gnumake_recursive =
enable_shared = $(ENABLE_SHARED:no=)
-UNICODE_VERSION = 13.0.0
-UNICODE_EMOJI_VERSION = 13.1
+UNICODE_VERSION = 15.0.0
+UNICODE_EMOJI_VERSION_0 = $(UNICODE_VERSION)///
+UNICODE_EMOJI_VERSION_1 = $(UNICODE_EMOJI_VERSION_0:.0///=)
+UNICODE_EMOJI_VERSION = $(UNICODE_EMOJI_VERSION_1:///=)
UNICODE_BETA = NO
### set the following environment variable or uncomment the line if
@@ -41,14 +43,14 @@ RUN_OPTS = --disable-gems
# GITPULLOPTIONS = --no-tags
-INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(UNICODE_HDR_DIR)
+INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(UNICODE_HDR_DIR) $(incflags)
GEM_HOME =
GEM_PATH =
GEM_VENDOR =
BENCHMARK_DRIVER_GIT_URL = https://github.com/benchmark-driver/benchmark-driver
-BENCHMARK_DRIVER_GIT_REF = v0.15.17
+BENCHMARK_DRIVER_GIT_REF = v0.16.0
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
@@ -70,7 +72,9 @@ RDOCOUT = $(EXTOUT)/rdoc
HTMLOUT = $(EXTOUT)/html
CAPIOUT = doc/capi
INSTALL_DOC_OPTS = --rdoc-output="$(RDOCOUT)" --html-output="$(HTMLOUT)"
-RDOC_GEN_OPTS = --page-dir "$(srcdir)/doc" --no-force-update
+RDOC_GEN_OPTS = --page-dir "$(srcdir)/doc" --no-force-update \
+ --title "Documentation for Ruby $(RUBY_API_VERSION)" \
+ --main README.md
INITOBJS = dmyext.$(OBJEXT) dmyenc.$(OBJEXT)
NORMALMAINOBJ = main.$(OBJEXT)
@@ -80,7 +84,7 @@ EXTSOLIBS =
MINIOBJS = $(ARCHMINIOBJS) miniinit.$(OBJEXT) dmyext.$(OBJEXT)
ENC_MK = enc.mk
MAKE_ENC = -f $(ENC_MK) V="$(V)" UNICODE_HDR_DIR="$(UNICODE_HDR_DIR)" \
- RUBY="$(MINIRUBY)" MINIRUBY="$(MINIRUBY)" $(mflags)
+ RUBY="$(BOOTSTRAPRUBY)" MINIRUBY="$(BOOTSTRAPRUBY)" $(mflags)
COMMONOBJS = array.$(OBJEXT) \
ast.$(OBJEXT) \
@@ -104,13 +108,14 @@ COMMONOBJS = array.$(OBJEXT) \
hash.$(OBJEXT) \
inits.$(OBJEXT) \
io.$(OBJEXT) \
+ io_buffer.$(OBJEXT) \
iseq.$(OBJEXT) \
load.$(OBJEXT) \
marshal.$(OBJEXT) \
math.$(OBJEXT) \
memory_view.$(OBJEXT) \
mjit.$(OBJEXT) \
- mjit_compile.$(OBJEXT) \
+ mjit_c.$(OBJEXT) \
node.$(OBJEXT) \
numeric.$(OBJEXT) \
object.$(OBJEXT) \
@@ -131,6 +136,7 @@ COMMONOBJS = array.$(OBJEXT) \
regsyntax.$(OBJEXT) \
ruby.$(OBJEXT) \
scheduler.$(OBJEXT) \
+ shape.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
st.$(OBJEXT) \
@@ -150,6 +156,7 @@ COMMONOBJS = array.$(OBJEXT) \
vm_dump.$(OBJEXT) \
vm_sync.$(OBJEXT) \
vm_trace.$(OBJEXT) \
+ $(YJIT_OBJ) \
$(COROUTINE_OBJ) \
$(DTRACE_OBJ) \
$(BUILTIN_ENCOBJS) \
@@ -174,6 +181,7 @@ GOLFPRELUDES = {$(srcdir)}golf_prelude.c
SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
--extout="$(EXTOUT)" \
+ --ext-build-dir="./ext" \
--mflags="$(MFLAGS)" \
--make-flags="$(MAKEFLAGS)"
EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) \
@@ -185,10 +193,12 @@ INSTRUBY_ARGS = $(SCRIPT_ARGS) \
--data-mode=$(INSTALL_DATA_MODE) \
--prog-mode=$(INSTALL_PROG_MODE) \
--installed-list $(INSTALLED_LIST) \
- --mantype="$(MANTYPE)"
+ --mantype="$(MANTYPE)" \
+ $(INSTRUBY_OPTS)
INSTALL_PROG_MODE = 0755
INSTALL_DATA_MODE = 0644
+BOOTSTRAPRUBY_COMMAND = $(BOOTSTRAPRUBY) $(BOOTSTRAPRUBY_OPT)
TESTSDIR = $(srcdir)/test
TOOL_TESTSDIR = $(tooldir)/test
TEST_EXCLUDES = --excludes-dir=$(TESTSDIR)/excludes --name=!/memory_leak/
@@ -210,12 +220,27 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \
-e "noraise {ln(src, dest)} or" \
-e "cp(src, dest)"
+# For release builds
+YJIT_RUSTC_ARGS = --crate-name=yjit \
+ --crate-type=staticlib \
+ --edition=2021 \
+ -g \
+ -C opt-level=3 \
+ -C overflow-checks=on \
+ '--out-dir=$(CARGO_TARGET_DIR)/release/' \
+ $(top_srcdir)/yjit/src/lib.rs
all: $(SHOWFLAGS) main docs
main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs
@$(NULLCMD)
+main: $(srcdir)/lib/ruby_vm/mjit/instruction.rb
+srcs: $(srcdir)/lib/ruby_vm/mjit/instruction.rb
+$(srcdir)/lib/ruby_vm/mjit/instruction.rb: $(tooldir)/insns2vm.rb $(tooldir)/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb $(srcdir)/insns.def
+ $(ECHO) generating $@
+ $(Q) $(BASERUBY) -Ku $(tooldir)/insns2vm.rb --basedir="$(srcdir)" $(INSNS2VMOPT) $@
+
mjit-headers: $(MJIT_SUPPORT)-mjit-headers
no-mjit-headers: PHONY
yes-mjit-headers: mjit_config.h PHONY
@@ -223,6 +248,9 @@ yes-mjit-headers: mjit_config.h PHONY
mjit.$(OBJEXT): mjit_config.h
mjit_config.h: Makefile
+.PHONY: mjit-bindgen
+mjit-bindgen:
+ $(Q) $(BASERUBY) -rrubygems -C $(srcdir)/tool/mjit bindgen.rb $(CURDIR)
# These rules using MJIT_HEADER_SUFFIX must be in common.mk, not
# Makefile.in, in order to override the macro in defs/universal.mk.
@@ -232,7 +260,7 @@ mjit_config.h: Makefile
$(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time: probes.h vm.$(OBJEXT) \
$(TIMESTAMPDIR)/$(arch)/.time $(tooldir)/mjit_tabs.rb $(PREP) $(RBCONFIG)
$(ECHO) building $(@F:.time=.h)
- $(MINIRUBY) $(tooldir)/mjit_tabs.rb "$(MJIT_TABS)" \
+ $(Q)$(MINIRUBY) $(tooldir)/mjit_tabs.rb "$(MJIT_TABS)" \
$(CPP) -DMJIT_HEADER $(MJIT_HEADER_FLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/vm.c $(CPPOUTFLAG)$(@F:.time=.h).new
$(Q) $(IFCHANGE) "--timestamp=$@" $(@F:.time=.h) $(@F:.time=.h).new
@@ -243,7 +271,7 @@ $(MJIT_MIN_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h: \
$(tooldir)/transform_mjit_header.rb $(PREP) \
$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h
$(ECHO) building $@
- $(MINIRUBY) $(tooldir)/transform_mjit_header.rb "$(CC) $(CFLAGS) -w" $(MJIT_HEADER:.h=)$(MJIT_HEADER_ARCH).h $@
+ $(Q)$(MINIRUBY) $(tooldir)/transform_mjit_header.rb "$(CC) $(CFLAGS) -w" $(MJIT_HEADER:.h=)$(MJIT_HEADER_ARCH).h $@
$(Q) $(MAKEDIRS) $(MJIT_HEADER_INSTALL_DIR)
$(Q) $(MAKE_LINK) $@ $(MJIT_HEADER_INSTALL_DIR)/$(@F)
@@ -264,6 +292,8 @@ showflags:
" LC_ALL = $(LC_ALL)" \
" LC_CTYPE = $(LC_CTYPE)" \
" MFLAGS = $(MFLAGS)" \
+ " RUSTC = $(RUSTC)" \
+ " YJIT_RUSTC_ARGS = $(YJIT_RUSTC_ARGS)" \
$(MESSAGE_END)
-@$(CC_VERSION)
@@ -299,7 +329,7 @@ configure-ext: $(EXTS_MK)
build-ext: $(EXTS_MK)
$(Q)$(MAKE) -f $(EXTS_MK) $(mflags) libdir="$(libdir)" LIBRUBY_EXTS=$(LIBRUBY_EXTS) \
- EXTENCS="$(ENCOBJS)" UPDATE_LIBRARIES=no $(EXTSTATIC)
+ EXTENCS="$(ENCOBJS)" MINIRUBY="$(MINIRUBY)" UPDATE_LIBRARIES=no $(EXTSTATIC)
$(Q)$(MAKE) $(EXTS_NOTE)
exts-note: $(EXTS_MK)
@@ -376,14 +406,14 @@ $(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-gem pre-install-doc
do-install-all: pre-install-all
- $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) $(INSTALL_DOC_OPTS)
+ $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS)
post-install-all:: post-install-local post-install-ext post-install-gem post-install-doc
@$(NULLCMD)
install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc
pre-install-nodoc:: pre-install-local pre-install-ext pre-install-gem
do-install-nodoc: main pre-install-nodoc
- $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --exclude=doc
+ $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all --exclude=doc
post-install-nodoc:: post-install-local post-install-ext post-install-gem
install-local: pre-install-local do-install-local post-install-local
@@ -604,12 +634,13 @@ clear-installed-list: PHONY
clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-local clean-platform clean-spec
clean-local:: clean-runnable
- $(Q)$(RM) $(OBJS) $(MINIOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
+ $(Q)$(RM) $(OBJS) $(MINIOBJS) $(INITOBJS) $(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 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)
+ -$(Q)$(RMALL) yjit/target
+ -$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine yjit 2> $(NULL) || $(NULLCMD)
bin/clean-runnable:: PHONY
$(Q)$(CHDIR) bin 2>$(NULL) && $(RM) $(PROGRAM) $(WPROGRAM) $(GORUBY)$(EXEEXT) bin/*.$(DLEXT) 2>$(NULL) || $(NULLCMD)
@@ -681,18 +712,18 @@ realclean-platform: distclean-platform
realclean-spec: distclean-spec
realclean-rubyspec: realclean-spec
-clean-ext:: ext/clean gems/clean timestamp/clean
-distclean-ext:: ext/distclean gems/distclean timestamp/distclean
-realclean-ext:: ext/realclean gems/realclean timestamp/realclean
+clean-ext:: ext/clean .bundle/clean timestamp/clean
+distclean-ext:: ext/distclean .bundle/distclean timestamp/distclean
+realclean-ext:: ext/realclean .bundle/realclean timestamp/realclean
ext/clean.mk ext/distclean.mk ext/realclean.mk::
ext/clean:: ext/clean.mk
ext/distclean:: ext/distclean.mk
ext/realclean:: ext/realclean.mk
-timestamp/clean:: ext/clean gems/clean
-timestamp/distclean:: ext/distclean gems/distclean
-timestamp/realclean:: ext/realclean gems/realclean
+timestamp/clean:: ext/clean .bundle/clean
+timestamp/distclean:: ext/distclean .bundle/distclean
+timestamp/realclean:: ext/realclean .bundle/realclean
timestamp/clean timestamp/distclean timestamp/realclean::
$(Q)$(RM) $(TIMESTAMPDIR)/.*.time $(TIMESTAMPDIR)/$(arch)/.time
@@ -735,13 +766,13 @@ clean-spec: PHONY
-$(Q) $(RMDIRS) $(RUBYSPEC_CAPIEXT) 2> $(NULL) || $(NULLCMD)
-$(Q) $(RMALL) rubyspec_temp
-check: main test test-tool test-all test-spec
+check: main $(DOT_WAIT) test $(DOT_WAIT) test-tool $(DOT_WAIT) test-all
$(ECHO) check succeeded
-$(Q) : : "run only on sh"; \
if [ x"$(GIT)" != x ] && $(CHDIR) "$(srcdir)" && \
b=`$(GIT) symbolic-ref --short HEAD 2>&1` && \
u=`$(GIT) branch --list --format='%(upstream:short)' $$b`; then \
- set -x; $(GIT) --no-pager log --format=oneline -G "^ *# *include" $$u..HEAD --; \
+ set -x; $(GIT) --no-pager log --format=oneline -G '^ *# *include *("|<ruby)' $$u..HEAD --; \
fi
check-ruby: test test-ruby
@@ -749,29 +780,37 @@ fake: $(CROSS_COMPILING)-fake
yes-fake: $(arch)-fake.rb $(RBCONFIG) PHONY
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 $(tooldir)/generic_erb.rb version.$(OBJEXT) miniruby$(EXEEXT)
+$(HAVE_BASERUBY:no=)$(arch)-fake.rb: miniruby$(EXEEXT)
+
+# actually depending on other headers more.
+$(arch:noarch=ignore)-fake.rb: $(top_srcdir)/revision.h $(top_srcdir)/version.h $(srcdir)/version.c
+$(arch:noarch=ignore)-fake.rb: {$(VPATH)}id.h {$(VPATH)}vm_opts.h
+
+$(arch:noarch=ignore)-fake.rb: $(srcdir)/template/fake.rb.in $(tooldir)/generic_erb.rb
$(ECHO) generating $@
$(Q) $(CPP) -DRUBY_EXPORT $(INCFLAGS) $(CPPFLAGS) "$(srcdir)/version.c" | \
$(BOOTSTRAPRUBY) "$(tooldir)/generic_erb.rb" -o $@ "$(srcdir)/template/fake.rb.in" \
- i=- srcdir="$(srcdir)" BASERUBY="$(BASERUBY)"
+ i=- srcdir="$(srcdir)" BASERUBY="$(BASERUBY)" \
+ LIBPATHENV="$(LIBPATHENV)" PRELOADENV="$(PRELOADENV)" LIBRUBY_SO="$(LIBRUBY_SO)"
+
+noarch-fake.rb: # prerequisite of yes-fake
+ $(Q) exit > $@
btest: $(TEST_RUNNABLE)-btest
no-btest: PHONY
-yes-btest: fake miniruby$(EXEEXT) PHONY
+yes-btest: yes-fake miniruby$(EXEEXT) PHONY
$(ACTIONS_GROUP)
- $(Q)$(exec) $(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(BTESTRUBY) $(RUN_OPTS)" $(OPTS) $(TESTOPTS) $(BTESTS)
+ $(Q)$(gnumake_recursive)$(exec) $(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(BTESTRUBY) $(RUN_OPTS)" $(OPTS) $(TESTOPTS) $(BTESTS)
$(ACTIONS_ENDGROUP)
btest-ruby: $(TEST_RUNNABLE)-btest-ruby
no-btest-ruby: PHONY
yes-btest-ruby: prog PHONY
$(ACTIONS_GROUP)
- $(Q)$(exec) $(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) -I$(srcdir)/lib $(RUN_OPTS)" -q $(OPTS) $(TESTOPTS) $(BTESTS)
+ $(Q)$(gnumake_recursive)$(exec) $(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) -I$(srcdir)/lib $(RUN_OPTS)" $(OPTS) $(TESTOPTS) $(BTESTS)
$(ACTIONS_ENDGROUP)
-rtest: fake miniruby$(EXEEXT) PHONY
+rtest: yes-fake miniruby$(EXEEXT) PHONY
$(ACTIONS_GROUP)
$(Q)$(exec) $(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(BTESTRUBY) $(RUN_OPTS)" --sets=ractor -v
$(ACTIONS_ENDGROUP)
@@ -794,7 +833,7 @@ yes-test-knownbug: prog PHONY
test-testframework: $(TEST_RUNNABLE)-test-testframework
yes-test-testframework: prog PHONY
$(ACTIONS_GROUP)
- $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TOOL_TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TESTOPTS) testunit minitest
+ $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TOOL_TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TESTOPTS) testunit
$(ACTIONS_ENDGROUP)
no-test-testframework: PHONY
@@ -806,7 +845,7 @@ yes-test-tool: prog PHONY
no-test-tool: PHONY
test-sample: test-basic # backward compatibility for mswin-build
-test-short: btest-ruby test-knownbug test-basic
+test-short: btest-ruby $(DOT_WAIT) test-knownbug $(DOT_WAIT) test-basic
test: test-short
# $ make test-all TESTOPTS="--help" displays more detail
@@ -833,7 +872,10 @@ extconf: $(PREP)
$(Q) $(MAKEDIRS) "$(EXTCONFDIR)"
$(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
-$(RBCONFIG): $(tooldir)/mkconfig.rb config.status $(srcdir)/version.h
+rbconfig.rb: $(RBCONFIG)
+
+$(HAVE_BASERUBY:no=)$(RBCONFIG)$(HAVE_BASERUBY:no=): $(PREP)
+$(RBCONFIG): $(tooldir)/mkconfig.rb config.status $(srcdir)/version.h $(srcdir)/common.mk
$(Q)$(BOOTSTRAPRUBY) -n \
-e 'BEGIN{version=ARGV.shift;mis=ARGV.dup}' \
-e 'END{abort "UNICODE version mismatch: #{mis}" unless mis.empty?}' \
@@ -851,7 +893,7 @@ $(RBCONFIG): $(tooldir)/mkconfig.rb config.status $(srcdir)/version.h
test-rubyspec: test-spec
yes-test-rubyspec: yes-test-spec
-test-spec-precheck: programs
+test-spec-precheck: programs yes-fake
test-spec: $(TEST_RUNNABLE)-test-spec
yes-test-spec: test-spec-precheck
@@ -861,6 +903,8 @@ yes-test-spec: test-spec-precheck
$(ACTIONS_ENDGROUP)
no-test-spec:
+check: $(DOT_WAIT) test-spec
+
RUNNABLE = $(LIBRUBY_RELATIVE:no=un)-runnable
runnable: $(RUNNABLE) prog $(tooldir)/mkrunnable.rb PHONY
$(Q) $(MINIRUBY) $(tooldir)/mkrunnable.rb -v $(EXTOUT)
@@ -879,9 +923,10 @@ libtrans trans: {$(VPATH)}transdb.h
ENC_HEADERS = $(srcdir)/enc/jis/props.h
# Use MINIRUBY which loads fake.rb for cross compiling
$(ENC_MK): $(srcdir)/enc/make_encmake.rb $(srcdir)/enc/Makefile.in $(srcdir)/enc/depend \
- $(srcdir)/enc/encinit.c.erb $(ENC_HEADERS) $(srcdir)/lib/mkmf.rb $(RBCONFIG) fake
+ $(srcdir)/enc/encinit.c.erb $(ENC_HEADERS) $(srcdir)/lib/mkmf.rb $(RBCONFIG) $(HAVE_BASERUBY)-fake
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(srcdir)/enc/make_encmake.rb --builtin-encs="$(BUILTIN_ENCOBJS)" --builtin-transes="$(BUILTIN_TRANSOBJS)" --module$(ENCSTATIC) $(ENCS) $@
+ $(Q) $(BOOTSTRAPRUBY_COMMAND) $(srcdir)/enc/make_encmake.rb \
+ --builtin-encs="$(BUILTIN_ENCOBJS)" --builtin-transes="$(BUILTIN_TRANSOBJS)" --module$(ENCSTATIC) $(ENCS) $@
.PRECIOUS: $(MKFILES)
@@ -903,9 +948,7 @@ PHONY:
{$(srcdir)}.y.c:
$(ECHO) generating $@
- $(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)$(BASERUBY) $(tooldir)/id2token.rb $(SRC_FILE) > parse.tmp.y
$(Q)$(YACC) -d $(YFLAGS) -o y.tab.c parse.tmp.y
$(Q)$(RM) parse.tmp.y
$(Q)sed -f $(tooldir)/ytab.sed -e "/^#/s|parse\.tmp\.[iy]|$(SRC_FILE)|" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new
@@ -917,11 +960,11 @@ $(PLATFORM_D):
$(Q) $(MAKEDIRS) $(PLATFORM_DIR) $(@D)
@$(NULLCMD) > $@
-exe/$(PROGRAM): ruby-runner.c ruby-runner.h exe/.time miniruby$(EXEEXT) {$(VPATH)}config.h
+exe/$(PROGRAM): ruby-runner.c ruby-runner.h exe/.time $(PREP) {$(VPATH)}config.h
$(Q) $(CC) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) -DRUBY_INSTALL_NAME=$(@F) $(COUTFLAG)ruby-runner.$(OBJEXT) -c $(CSRCFLAG)$(srcdir)/ruby-runner.c
$(Q) $(PURIFY) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTFLAG)$@ ruby-runner.$(OBJEXT) $(LIBS)
$(Q) $(POSTLINK)
- $(Q) ./miniruby$(EXEEXT) \
+ $(Q) $(BOOTSTRAPRUBY) \
-e 'prog, dest, inst = ARGV; dest += "/ruby"' \
-e 'exit unless prog==inst' \
-e 'unless prog=="ruby"' \
@@ -959,23 +1002,28 @@ RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
acosh.$(OBJEXT): {$(VPATH)}acosh.c
alloca.$(OBJEXT): {$(VPATH)}alloca.c {$(VPATH)}config.h
+cbrt.$(OBJEXT): {$(VPATH)}cbrt.c
+close.$(OBJEXT): {$(VPATH)}close.c
crypt.$(OBJEXT): {$(VPATH)}crypt.c {$(VPATH)}crypt.h {$(VPATH)}missing/des_tables.c
-dup2.$(OBJEXT): {$(VPATH)}dup2.c
erf.$(OBJEXT): {$(VPATH)}erf.c
explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c
-finite.$(OBJEXT): {$(VPATH)}finite.c
+ffs.$(OBJEXT): {$(VPATH)}ffs.c
flock.$(OBJEXT): {$(VPATH)}flock.c
+hypot.$(OBJEXT): {$(VPATH)}hypot.c
+langinfo.$(OBJEXT): {$(VPATH)}langinfo.c
+lgamma_r.$(OBJEXT): {$(VPATH)}lgamma_r.c
memcmp.$(OBJEXT): {$(VPATH)}memcmp.c
memmove.$(OBJEXT): {$(VPATH)}memmove.c
-mkdir.$(OBJEXT): {$(VPATH)}mkdir.c
+nan.$(OBJEXT): {$(VPATH)}nan.c
+nextafter.$(OBJEXT): {$(VPATH)}nextafter.c
+procstat_vm.$(OBJEXT): {$(VPATH)}procstat_vm.c
setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c
strchr.$(OBJEXT): {$(VPATH)}strchr.c
-strdup.$(OBJEXT): {$(VPATH)}strdup.c
strerror.$(OBJEXT): {$(VPATH)}strerror.c
strlcat.$(OBJEXT): {$(VPATH)}strlcat.c
strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c
strstr.$(OBJEXT): {$(VPATH)}strstr.c
-nt.$(OBJEXT): {$(VPATH)}nt.c
+tgamma.$(OBJEXT): {$(VPATH)}tgamma.c
.coroutine_obj $(COROUTINE_OBJ): \
{$(VPATH)}$(COROUTINE_SRC) \
@@ -1005,7 +1053,7 @@ $(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(tooldir)/transcode-tblgen.rb
$(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 $(tooldir)/generic_erb.rb
+verconf.h: $(srcdir)/template/verconf.h.tmpl $(tooldir)/generic_erb.rb $(RBCONFIG)
$(ECHO) creating $@
$(Q) $(BOOTSTRAPRUBY) "$(tooldir)/generic_erb.rb" -o $@ $(srcdir)/template/verconf.h.tmpl
@@ -1030,11 +1078,7 @@ $(srcs_vpath)insns_info.inc: $(tooldir)/ruby_vm/views/insns_info.inc.erb $(inc_c
$(srcs_vpath)vmtc.inc: $(tooldir)/ruby_vm/views/vmtc.inc.erb $(inc_common_headers)
$(srcs_vpath)vm.inc: $(tooldir)/ruby_vm/views/vm.inc.erb $(inc_common_headers) \
$(tooldir)/ruby_vm/views/_insn_entry.erb $(tooldir)/ruby_vm/views/_trace_instruction.erb
-$(srcs_vpath)mjit_compile.inc: $(tooldir)/ruby_vm/views/mjit_compile.inc.erb $(inc_common_headers) \
- $(tooldir)/ruby_vm/views/_mjit_compile_insn.erb $(tooldir)/ruby_vm/views/_mjit_compile_send.erb \
- $(tooldir)/ruby_vm/views/_mjit_compile_ivar.erb \
- $(tooldir)/ruby_vm/views/_mjit_compile_insn_body.erb $(tooldir)/ruby_vm/views/_mjit_compile_pc_and_sp.erb \
- $(tooldir)/ruby_vm/views/_mjit_compile_invokebuiltin.erb $(tooldir)/ruby_vm/views/_mjit_compile_getinlinecache.erb
+$(srcs_vpath)mjit_sp_inc.inc: $(tooldir)/ruby_vm/views/mjit_sp_inc.inc.erb
BUILTIN_RB_SRCS = \
$(srcdir)/ast.rb \
@@ -1042,22 +1086,28 @@ BUILTIN_RB_SRCS = \
$(srcdir)/gc.rb \
$(srcdir)/numeric.rb \
$(srcdir)/io.rb \
+ $(srcdir)/marshal.rb \
+ $(srcdir)/mjit.rb \
+ $(srcdir)/mjit_c.rb \
$(srcdir)/pack.rb \
$(srcdir)/trace_point.rb \
$(srcdir)/warning.rb \
$(srcdir)/array.rb \
$(srcdir)/kernel.rb \
$(srcdir)/ractor.rb \
+ $(srcdir)/symbol.rb \
$(srcdir)/timev.rb \
+ $(srcdir)/thread_sync.rb \
$(srcdir)/nilclass.rb \
$(srcdir)/prelude.rb \
$(srcdir)/gem_prelude.rb \
+ $(srcdir)/yjit.rb \
$(empty)
BUILTIN_RB_INCS = $(BUILTIN_RB_SRCS:.rb=.rbinc)
common-srcs: $(srcs_vpath)parse.c $(srcs_vpath)lex.c $(srcs_vpath)enc/trans/newline.c $(srcs_vpath)id.c \
$(BUILTIN_RB_INCS) \
- srcs-lib srcs-ext incs
+ srcs-lib srcs-ext incs preludes
missing-srcs: $(srcdir)/missing/des_tables.c
@@ -1113,13 +1163,13 @@ node_name.inc: $(tooldir)/node_name.rb $(srcdir)/node.h
$(ECHO) generating $@
$(Q) $(BASERUBY) -n $(tooldir)/node_name.rb < $(srcdir)/node.h > $@
-encdb.h: $(PREP) $(tooldir)/generic_erb.rb $(srcdir)/template/encdb.h.tmpl
+encdb.h: $(RBCONFIG) $(tooldir)/generic_erb.rb $(srcdir)/template/encdb.h.tmpl
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/encdb.h.tmpl $(srcdir)/enc enc
+ $(Q) $(BOOTSTRAPRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/encdb.h.tmpl $(srcdir)/enc enc
-transdb.h: $(PREP) srcs-enc $(tooldir)/generic_erb.rb $(srcdir)/template/transdb.h.tmpl
+transdb.h: $(RBCONFIG) srcs-enc $(tooldir)/generic_erb.rb $(srcdir)/template/transdb.h.tmpl
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/transdb.h.tmpl $(srcdir)/enc/trans enc/trans
+ $(Q) $(BOOTSTRAPRUBY) $(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
@@ -1169,25 +1219,19 @@ builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/template/builtin_binary
$(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb
-$(srcdir)/revision.h:
-$(srcdir)/revision.h$(gnumake:yes=-nongnumake):
- $(Q)$(RM) $(@F)
- $(Q)$(NULLCMD) > $@ || $(NULLCMD) > $(@F)
-
-revision.tmp::
- $(Q) $(NULLCMD) > $@
-revision.$(HAVE_BASERUBY:yes=tmp):: $(srcdir)/version.h $(tooldir)/file2lastrev.rb $(REVISION_FORCE)
- $(Q) $(BASERUBY) $(tooldir)/file2lastrev.rb -q --revision.h --srcdir="$(srcdir)" > $@
+$(srcdir)/revision.h$(no_baseruby:no=~disabled~): $(REVISION_H)
-$(REVISION_H): revision.tmp
- $(Q)$(IFCHANGE) "--timestamp=$@" "$(srcdir)/revision.h" revision.tmp
+$(REVISION_H)$(no_baseruby:no=~disabled~):
+ $(Q) $(BASERUBY) $(tooldir)/file2lastrev.rb -q --revision.h --srcdir="$(srcdir)" --output=revision.h --timestamp=$@
+$(REVISION_H)$(yes_baseruby:yes=~disabled~):
+ $(Q) exit > $@
-$(srcdir)/ext/ripper/ripper.c: $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/parse.y id.h $(srcdir)/ext/ripper/depend
+$(srcdir)/ext/ripper/ripper.c: $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/parse.y $(srcdir)/defs/id.def $(srcdir)/ext/ripper/depend
$(ECHO) generating $@
- $(Q) VPATH=$${PWD-`pwd`} && $(CHDIR) $(@D) && \
- sed -e 's/{\$$([^(){}]*)[^{}]*}//g' -e /AUTOGENERATED/q depend | \
+ $(Q) $(CHDIR) $(@D) && \
+ $(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
- Q=$(Q) ECHO=$(ECHO) RM="$(RM)" BISON=$(YACC) top_srcdir=../.. srcdir=. VPATH="$${VPATH}" \
+ Q=$(Q) ECHO=$(ECHO) RM="$(RM1)" BISON="$(YACC)" top_srcdir=../.. srcdir=. VPATH=../.. \
RUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)" LANG=C
$(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl $(srcdir)/ext/json/parser/prereq.mk
@@ -1204,7 +1248,7 @@ $(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \
$(tooldir)/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.ac
$(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && \
- sed '/AUTOGENERATED/q' depend | \
+ $(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)" $(@F)
@@ -1212,31 +1256,34 @@ $(srcdir)/ext/rbconfig/sizeof/limits.c: $(srcdir)/ext/rbconfig/sizeof/depend \
$(tooldir)/generic_erb.rb $(srcdir)/template/limits.c.tmpl
$(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && \
- sed '/AUTOGENERATED/q' depend | \
+ $(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)" $(@F)
$(srcdir)/ext/socket/constdefs.c: $(srcdir)/ext/socket/depend
$(Q) $(CHDIR) $(@D) && \
- sed '/AUTOGENERATED/q' depend | \
+ $(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. RUBY="$(BASERUBY)"
$(srcdir)/ext/etc/constdefs.h: $(srcdir)/ext/etc/depend
$(Q) $(CHDIR) $(@D) && \
- sed '/AUTOGENERATED/q' depend | \
+ $(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. RUBY="$(BASERUBY)"
##
-run: fake miniruby$(EXEEXT) PHONY
+run: yes-fake miniruby$(EXEEXT) PHONY
$(BTESTRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
runruby: $(PROGRAM) PHONY
RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
-parse: fake miniruby$(EXEEXT) PHONY
+runirb: $(PROGRAM) PHONY
+ RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) -r irb -e 'IRB.start("make runirb")' $(RUNOPT)
+
+parse: yes-fake miniruby$(EXEEXT) PHONY
$(BTESTRUBY) --dump=parsetree_with_comment,insns $(TESTRUN_SCRIPT)
bisect: PHONY
@@ -1293,7 +1340,7 @@ lldb-ruby: $(PROGRAM) PHONY
DISTPKGS = gzip,zip,all
PKGSDIR = tmp
dist:
- $(BASERUBY) $(tooldir)/make-snapshot \
+ $(BASERUBY) $(V0:1=-v) $(tooldir)/make-snapshot \
-srcdir=$(srcdir) -packages=$(DISTPKGS) \
-unicode-version=$(UNICODE_VERSION) \
$(DISTOPTS) $(PKGSDIR) $(RELNAME)
@@ -1306,11 +1353,15 @@ up::
yes::
no::
-EXTRACT_EXTLIBS = extract-extlibs
+after-update:: common-srcs
after-update:: $(REVISION_H)
-after-update:: $(EXTRACT_EXTLIBS)
+after-update:: extract-extlibs
after-update:: extract-gems
+update-src::
+ $(Q) $(RM) $(REVISION_H) revision.h "$(srcdir)/$(REVISION_H)" "$(srcdir)/revision.h"
+ $(Q) exit > "$(srcdir)/revision.h"
+
update-remote:: update-src update-download
update-download:: $(ALWAYS_UPDATE_UNICODE:yes=update-unicode)
update-download:: update-gems
@@ -1325,8 +1376,9 @@ update-config_files: PHONY
refresh-gems: update-bundled_gems prepare-gems
prepare-gems: $(HAVE_BASERUBY:yes=update-gems) $(HAVE_BASERUBY:yes=extract-gems)
+extract-gems: $(HAVE_BASERUBY:yes=update-gems)
-update-gems$(gnumake:yes=-nongnumake): PHONY
+update-gems$(gnumake:yes=-sequential): PHONY
$(ECHO) Downloading bundled gem files...
$(Q) $(BASERUBY) -C "$(srcdir)" \
-I./tool -rdownloader -answ \
@@ -1340,39 +1392,52 @@ update-gems$(gnumake:yes=-nongnumake): PHONY
-e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})' \
gems/bundled_gems
-extract-gems$(gnumake:yes=-nongnumake): PHONY
+extract-gems$(gnumake:yes=-sequential): PHONY
$(ECHO) Extracting bundled gem files...
- $(Q) $(RUNRUBY) -C "$(srcdir)" \
- -Itool -rgem-unpack -answ \
- -e 'BEGIN {FileUtils.mkdir_p(d = ".bundle/gems")}' \
- -e 'gem, ver = *$$F' \
+ $(Q) $(BASERUBY) -C "$(srcdir)" \
+ -Itool/lib -rfileutils -rbundled_gem -answ \
+ -e 'BEGIN {d = ".bundle/gems"}' \
+ -e 'gem, ver, _, rev = *$$F' \
-e 'next if !ver or /^#/=~gem' \
-e 'g = "#{gem}-#{ver}"' \
- -e 'File.directory?("#{d}/#{g}") or Gem.unpack("gems/#{g}.gem", d)' \
+ -e 'if File.directory?("#{d}/#{g}")' \
+ -e 'elsif rev and File.exist?(gs = "gems/src/#{gem}/#{gem}.gemspec")' \
+ -e 'BundledGem.copy(gs, ".bundle")' \
+ -e 'else' \
+ -e 'BundledGem.unpack("gems/#{g}.gem", ".bundle")' \
+ -e 'end' \
gems/bundled_gems
+outdate-bundled-gems: PHONY
+ $(Q) $(BASERUBY) $(tooldir)/$@.rb --make="$(MAKE)" --mflags="$(MFLAGS)" "$(srcdir)"
+
update-bundled_gems: PHONY
$(Q) $(RUNRUBY) -rrubygems \
$(tooldir)/update-bundled_gems.rb \
"$(srcdir)/gems/bundled_gems" | \
$(IFCHANGE) "$(srcdir)/gems/bundled_gems" -
- git -C "$(srcdir)" diff --no-ext-diff --ignore-submodules --exit-code || \
- git -C "$(srcdir)" commit -m "Update bundled_gems" gems/bundled_gems
+ $(GIT) -C "$(srcdir)" diff --no-ext-diff --ignore-submodules --exit-code || \
+ $(GIT) -C "$(srcdir)" commit -m "Update bundled_gems" gems/bundled_gems
+PRECHECK_BUNDLED_GEMS = test-bundled-gems-precheck
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)
+test-bundled-gems-fetch: yes-test-bundled-gems-fetch
+yes-test-bundled-gems-fetch:
+ $(ACTIONS_GROUP)
$(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb src bundled_gems
+ $(ACTIONS_ENDGROUP)
+no-test-bundled-gems-fetch:
-test-bundled-gems-prepare: test-bundled-gems-precheck test-bundled-gems-fetch
+test-bundled-gems-prepare: $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch
test-bundled-gems-prepare: $(TEST_RUNNABLE)-test-bundled-gems-prepare
no-test-bundled-gems-prepare: no-test-bundled-gems-precheck
yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck
$(ACTIONS_GROUP)
$(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "bundler" "minitest:~> 5" "test-unit" "rake" "hoe" "yard" "pry" "packnga" "rexml" "json-schema" "rbs"
+ --install-dir .bundle --conservative "bundler" "minitest:~> 5" "test-unit" "rake" "hoe" "rexml" "json-schema:5.1.0" "test-unit-rr"
$(ACTIONS_ENDGROUP)
PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare
@@ -1385,31 +1450,62 @@ no-test-bundled-gems:
BUNDLED_GEMS =
test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS)
- $(Q) $(XRUBY) $(tooldir)/test-bundled-gems.rb $(BUNDLED_GEMS)
+ $(gnumake_recursive)$(Q) $(XRUBY) $(tooldir)/test-bundled-gems.rb $(BUNDLED_GEMS)
+
+test-syntax-suggest-precheck: $(TEST_RUNNABLE)-test-syntax-suggest-precheck
+no-test-syntax-suggest-precheck:
+yes-test-syntax-suggest-precheck: main
+
+test-syntax-suggest-prepare: $(TEST_RUNNABLE)-test-syntax-suggest-prepare
+no-test-syntax-suggest-prepare: no-test-syntax-suggest-precheck
+yes-test-syntax-suggest-prepare: yes-test-syntax-suggest-precheck
+ $(ACTIONS_GROUP)
+ $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
+ --install-dir .bundle --conservative "bundler" "rake" "rspec:~> 3" #"ruby-prof"
+ $(ACTIONS_ENDGROUP)
+
+RSPECOPTS =
+SYNTAX_SUGGEST_SPECS =
+PREPARE_SYNTAX_SUGGEST = test-syntax-suggest-prepare
+test-syntax-suggest: $(TEST_RUNNABLE)-test-syntax-suggest
+yes-test-syntax-suggest: yes-$(PREPARE_SYNTAX_SUGGEST)
+ $(XRUBY) -C $(srcdir) -Ispec/syntax_suggest .bundle/bin/rspec \
+ --require spec_helper $(RSPECOPTS) spec/syntax_suggest/$(SYNTAX_SUGGEST_SPECS)
+no-test-syntax-suggest:
+
+check: $(DOT_WAIT) $(TEST_RUNNABLE)-$(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest
test-bundler-precheck: $(TEST_RUNNABLE)-test-bundler-precheck
no-test-bundler-precheck:
-yes-test-bundler-precheck: main
+yes-test-bundler-precheck: main $(arch)-fake.rb
no-test-bundler-prepare: no-test-bundler-precheck
yes-test-bundler-prepare: yes-test-bundler-precheck
$(ACTIONS_GROUP)
- $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "rspec:~> 3.8" "rake:~> 13.0" "parallel_tests:~> 2.29"
+ $(XRUBY) -C $(srcdir) -Ilib \
+ -e 'ENV["GEM_HOME"] = File.expand_path(".bundle")' \
+ -e 'ENV["BUNDLE_APP_CONFIG"] = File.expand_path(".bundle")' \
+ -e 'ENV["BUNDLE_PATH__SYSTEM"] = "true"' \
+ -e 'ENV["BUNDLE_WITHOUT"] = "lint doc"' \
+ -e 'load "spec/bundler/support/bundle.rb"' -- install --gemfile=tool/bundler/dev_gems.rb
$(ACTIONS_ENDGROUP)
RSPECOPTS =
BUNDLER_SPECS =
test-bundler: $(TEST_RUNNABLE)-test-bundler
yes-test-bundler: yes-test-bundler-prepare
- $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec \
+ $(gnumake_recursive)$(XRUBY) \
+ -r./$(arch)-fake \
+ -e "exec(*ARGV)" -- \
+ $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec \
--require spec_helper $(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS)
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) \
+ $(gnumake_recursive)$(XRUBY) \
+ -r./$(arch)-fake \
-e "ARGV[-1] = File.expand_path(ARGV[-1])" \
-e "exec(*ARGV)" -- \
$(XRUBY) -I$(srcdir)/spec/bundler \
@@ -1421,6 +1517,12 @@ yes-test-bundler-parallel: yes-test-bundler-prepare
$(PARALLELRSPECOPTS) $(srcdir)/spec/bundler/$(BUNDLER_SPECS)
no-test-bundler-parallel:
+# The annocheck supports ELF format binaries compiled for any OS and for any
+# architecture. It is designed to be independent of the host OS and the
+# architecture. The test-annocheck.sh requires docker or podman.
+test-annocheck: $(PROGRAM)
+ $(tooldir)/test-annocheck.sh $(PROGRAM)
+
GEM = up
sync-default-gems:
$(Q) $(XRUBY) -C "$(srcdir)" tool/sync_default_gems.rb $(GEM)
@@ -1462,60 +1564,54 @@ update-unicode: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) \
$(UNICODE_AUXILIARY_FILES) $(UNICODE_UCD_EMOJI_FILES) $(UNICODE_EMOJI_FILES)
CACHE_DIR = $(srcdir)/.downloaded-cache
-UNICODE_DOWNLOAD = \
+UNICODE_DOWNLOADER_ALWAYS_UPDATE = $(ALWAYS_UPDATE_UNICODE:yes=--always)
+UNICODE_DOWNLOADER = \
$(BASERUBY) $(tooldir)/downloader.rb \
--cache-dir=$(CACHE_DIR) \
- --unicode-beta $(UNICODE_BETA) \
+ --exist $(UNICODE_DOWNLOADER_ALWAYS_UPDATE:no=) \
+ unicode --unicode-beta=$(UNICODE_BETA)
+UNICODE_DOWNLOAD = \
+ $(UNICODE_DOWNLOADER) \
-d $(UNICODE_SRC_DATA_DIR) \
- -p $(UNICODE_VERSION)/ucd \
- -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode
+ -p $(UNICODE_VERSION)/ucd
UNICODE_AUXILIARY_DOWNLOAD = \
- $(BASERUBY) $(tooldir)/downloader.rb \
- --cache-dir=$(CACHE_DIR) \
- --unicode-beta $(UNICODE_BETA) \
+ $(UNICODE_DOWNLOADER) \
-d $(UNICODE_SRC_DATA_DIR)/auxiliary \
- -p $(UNICODE_VERSION)/ucd/auxiliary \
- -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode
+ -p $(UNICODE_VERSION)/ucd/auxiliary
UNICODE_UCD_EMOJI_DOWNLOAD = \
- $(BASERUBY) $(tooldir)/downloader.rb \
- --cache-dir=$(CACHE_DIR) \
- --unicode-beta $(UNICODE_BETA) \
+ $(UNICODE_DOWNLOADER) \
-d $(UNICODE_SRC_DATA_DIR)/emoji \
- -p $(UNICODE_VERSION)/ucd/emoji \
- -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode
+ -p $(UNICODE_VERSION)/ucd/emoji
UNICODE_EMOJI_DOWNLOAD = \
- $(BASERUBY) $(tooldir)/downloader.rb \
- --cache-dir=$(CACHE_DIR) \
- --unicode-beta $(UNICODE_BETA) \
+ $(UNICODE_DOWNLOADER) \
-d $(UNICODE_SRC_EMOJI_DATA_DIR) \
- -p emoji/$(UNICODE_EMOJI_VERSION) \
- -e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode
+ -p emoji/$(UNICODE_EMOJI_VERSION)
-$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES): update-unicode-files
-update-unicode-files:
+update-unicode-files: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
+$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES):
$(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)"
$(Q) $(UNICODE_DOWNLOAD) $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
-$(UNICODE_AUXILIARY_FILES): update-unicode-auxiliary-files
-update-unicode-auxiliary-files:
+update-unicode-auxiliary-files: $(UNICODE_AUXILIARY_FILES)
+$(UNICODE_AUXILIARY_FILES):
$(ECHO) Downloading Unicode $(UNICODE_VERSION) auxiliary files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/auxiliary"
$(Q) $(UNICODE_AUXILIARY_DOWNLOAD) $(UNICODE_AUXILIARY_FILES)
-$(UNICODE_UCD_EMOJI_FILES): update-unicode-ucd-emoji-files
-update-unicode-ucd-emoji-files:
+update-unicode-ucd-emoji-files: $(UNICODE_UCD_EMOJI_FILES)
+$(UNICODE_UCD_EMOJI_FILES):
$(ECHO) Downloading Unicode UCD emoji $(UNICODE_EMOJI_VERSION) files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/emoji"
$(Q) $(UNICODE_UCD_EMOJI_DOWNLOAD) $(UNICODE_UCD_EMOJI_FILES)
-$(UNICODE_EMOJI_FILES): update-unicode-emoji-files
-update-unicode-emoji-files:
+update-unicode-emoji-files: $(UNICODE_EMOJI_FILES)
+$(UNICODE_EMOJI_FILES):
$(ECHO) Downloading Unicode emoji $(UNICODE_EMOJI_VERSION) files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_EMOJI_DATA_DIR)"
$(Q) $(UNICODE_EMOJI_DOWNLOAD) $(UNICODE_EMOJI_FILES)
-$(srcdir)/lib/unicode_normalize/$(ALWAYS_UPDATE_UNICODE:yes=tables.rb): \
+$(srcdir)/lib/unicode_normalize/tables.rb: \
$(UNICODE_SRC_DATA_DIR)/$(HAVE_BASERUBY:yes=.unicode-tables.time)
$(UNICODE_SRC_DATA_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=.unicode-tables.time): \
@@ -1524,13 +1620,25 @@ $(UNICODE_SRC_DATA_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=.unicode-tables.time): \
touch-unicode-files:
$(MAKEDIRS) $(UNICODE_SRC_DATA_DIR)
- touch $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time $(UNICODE_DATA_HEADERS)
+ $(Q) $(TOUCH) $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time $(UNICODE_DATA_HEADERS)
+UNICODE_TABLES_DATA_FILES = \
+ $(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \
+ $(UNICODE_SRC_DATA_DIR)/CompositionExclusions.txt \
+ $(empty)
+
+UNICODE_TABLES_DEPENDENTS_1 = none$(ALWAYS_UPDATE_UNICODE)
+UNICODE_TABLES_DEPENDENTS = $(UNICODE_TABLES_DEPENDENTS_1:noneyes=force)
UNICODE_TABLES_TIMESTAMP = yes
-$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: $(tooldir)/generic_erb.rb \
+$(UNICODE_SRC_DATA_DIR)/.unicode-tables.$(UNICODE_TABLES_DEPENDENTS:none=time):
+ $(Q) $(MAKEDIRS) $(@D)
+ $(Q) exit > $(@) || $(NULLCMD)
+$(UNICODE_SRC_DATA_DIR)/.unicode-tables.$(UNICODE_TABLES_DEPENDENTS:force=time): \
+ $(tooldir)/generic_erb.rb \
$(srcdir)/template/unicode_norm_gen.tmpl \
- $(ALWAYS_UPDATE_UNICODE:yes=update-unicode)
- $(Q) $(MAKE) $(@D)
+ $(UNICODE_TABLES_DATA_FILES) \
+ $(order_only) \
+ $(UNICODE_SRC_DATA_DIR)
$(Q) $(BASERUBY) $(tooldir)/generic_erb.rb \
-c $(UNICODE_TABLES_TIMESTAMP:yes=-t$@) \
-o $(srcdir)/lib/unicode_normalize/tables.rb \
@@ -1544,7 +1652,9 @@ $(UNICODE_SRC_DATA_DIR):
$(UNICODE_HDR_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=name2ctype.h): \
$(tooldir)/enc-unicode.rb \
$(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \
+ $(UNICODE_AUXILIARY_FILES) \
$(UNICODE_PROPERTY_FILES) \
+ $(UNICODE_UCD_EMOJI_FILES) \
$(UNICODE_EMOJI_FILES)
$(UNICODE_HDR_DIR)/name2ctype.h:
@@ -1554,19 +1664,19 @@ $(UNICODE_HDR_DIR)/name2ctype.h:
$(MV) $@.new $@
# the next non-comment line was:
-# $(UNICODE_HDR_DIR)/casefold.h: $(srcdir)/enc/unicode/case-folding.rb \
+# $(UNICODE_HDR_DIR)/casefold.h: $(tooldir)/enc-case-folding.rb \
# but was changed to make sure CI works on systems that don't have gperf
unicode-up: $(UNICODE_DATA_HEADERS)
$(UNICODE_HDR_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=casefold.h): \
- $(srcdir)/enc/unicode/case-folding.rb \
+ $(tooldir)/enc-case-folding.rb \
$(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \
$(UNICODE_SRC_DATA_DIR)/SpecialCasing.txt \
$(UNICODE_SRC_DATA_DIR)/CaseFolding.txt
$(UNICODE_HDR_DIR)/casefold.h:
$(MAKEDIRS) $(@D)
- $(Q) $(BASERUBY) $(srcdir)/enc/unicode/case-folding.rb \
+ $(Q) $(BASERUBY) $(tooldir)/enc-case-folding.rb \
--output-file=$@ \
--mapping-data-directory=$(UNICODE_SRC_DATA_DIR)
@@ -1626,41 +1736,45 @@ help: PHONY
" Makefile of Ruby" \
"" \
"targets:" \
- " all (default): builds all of below" \
- " miniruby: builds only miniruby" \
- " encs: builds encodings" \
- " exts: builds extensions" \
- " main: builds encodings, extensions and ruby" \
- " docs: builds documents" \
- " install-capi: builds C API documents" \
- " run: runs test.rb by miniruby" \
- " runruby: runs test.rb by ruby you just built" \
- " gdb: runs test.rb by miniruby under gdb" \
- " gdb-ruby: runs test.rb by ruby under gdb" \
- " check: equals make test test-tool test-all test-spec" \
- " test: ruby core tests [BTESTS=<bootstraptest files>]" \
- " test-all: all ruby tests [TESTOPTS=-j4 TESTS=<test files>]" \
- " test-spec: run the Ruby spec suite [SPECOPTS=<specs, opts>]" \
- " test-bundler: run the Bundler spec" \
- " test-bundled-gems: run the test suite of bundled gems" \
- " test-tool: tests under the tool/test" \
- " update-gems: download files of the bundled gems" \
- " update-bundled_gems: update the latest version of bundled gems" \
- " sync-default-gems: sync default gems from upstream [GEM=<gem_name git_ref>]" \
- " up: update local copy and autogenerated files" \
- " benchmark: benchmark this ruby and COMPARE_RUBY." \
- " gcbench: gc benchmark [GCBENCH_ITEM=<item_name>]" \
- " install: install all ruby distributions" \
- " install-nodoc: install without rdoc" \
- " install-cross: install cross compiling stuff" \
- " clean: clean for tarball" \
- " distclean: clean for repository" \
- " golf: build goruby for golfers" \
+ " all (default): builds all of below" \
+ " miniruby: builds only miniruby" \
+ " encs: builds encodings" \
+ " exts: builds extensions" \
+ " main: builds encodings, extensions and ruby" \
+ " docs: builds documents" \
+ " install-capi: builds C API documents" \
+ " run: runs test.rb by miniruby" \
+ " runruby: runs test.rb by ruby you just built" \
+ " gdb: runs test.rb by miniruby under gdb" \
+ " gdb-ruby: runs test.rb by ruby under gdb" \
+ " check: equals make test test-tool test-all test-spec" \
+ " test: ruby core tests [BTESTS=<bootstraptest files>]" \
+ " test-all: all ruby tests [TESTOPTS=-j4 TESTS=<test files>]" \
+ " test-spec: run the Ruby spec suite [SPECOPTS=<specs, opts>]" \
+ " test-bundler: run the Bundler spec" \
+ " test-bundler-parallel: run the Bundler spec with parallel" \
+ " test-bundled-gems: run the test suite of bundled gems" \
+ " test-tool: tests under the tool/test" \
+ " update-gems: download files of the bundled gems" \
+ " update-bundled_gems: update the latest version of bundled gems" \
+ " sync-default-gems: sync default gems from upstream [GEM=<gem_name git_ref>]" \
+ " up: update local copy and autogenerated files" \
+ " benchmark: benchmark this ruby and COMPARE_RUBY." \
+ " gcbench: gc benchmark [GCBENCH_ITEM=<item_name>]" \
+ " install: install all ruby distributions" \
+ " install-nodoc: install without rdoc" \
+ " install-cross: install cross compiling stuff" \
+ " clean: clean for tarball" \
+ " distclean: clean for repository" \
+ " golf: build goruby for golfers" \
$(HELP_EXTRA_TASKS) \
"see DeveloperHowto for more detail: " \
" https://bugs.ruby-lang.org/projects/ruby/wiki/DeveloperHowto" \
$(MESSAGE_END)
+$(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}mini_builtin.c
+$(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}miniprelude.c
+
# AUTOGENERATED DEPENDENCIES START
addr2line.$(OBJEXT): {$(VPATH)}addr2line.c
addr2line.$(OBJEXT): {$(VPATH)}addr2line.h
@@ -1668,7 +1782,6 @@ 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
@@ -1717,9 +1830,9 @@ addr2line.$(OBJEXT): {$(VPATH)}internal/stdbool.h
addr2line.$(OBJEXT): {$(VPATH)}internal/warning_push.h
addr2line.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
addr2line.$(OBJEXT): {$(VPATH)}missing.h
-array.$(OBJEXT): $(hdrdir)/ruby.h
array.$(OBJEXT): $(hdrdir)/ruby/ruby.h
array.$(OBJEXT): $(top_srcdir)/internal/array.h
+array.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
array.$(OBJEXT): $(top_srcdir)/internal/bignum.h
array.$(OBJEXT): $(top_srcdir)/internal/bits.h
array.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -1735,6 +1848,7 @@ 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/variable.h
array.$(OBJEXT): $(top_srcdir)/internal/vm.h
array.$(OBJEXT): $(top_srcdir)/internal/warnings.h
array.$(OBJEXT): {$(VPATH)}array.c
@@ -1751,6 +1865,7 @@ array.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
array.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
array.$(OBJEXT): {$(VPATH)}builtin.h
array.$(OBJEXT): {$(VPATH)}config.h
+array.$(OBJEXT): {$(VPATH)}constant.h
array.$(OBJEXT): {$(VPATH)}debug_counter.h
array.$(OBJEXT): {$(VPATH)}defines.h
array.$(OBJEXT): {$(VPATH)}encoding.h
@@ -1758,6 +1873,7 @@ array.$(OBJEXT): {$(VPATH)}id.h
array.$(OBJEXT): {$(VPATH)}id_table.h
array.$(OBJEXT): {$(VPATH)}intern.h
array.$(OBJEXT): {$(VPATH)}internal.h
+array.$(OBJEXT): {$(VPATH)}internal/abi.h
array.$(OBJEXT): {$(VPATH)}internal/anyargs.h
array.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
array.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -1827,6 +1943,15 @@ array.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
array.$(OBJEXT): {$(VPATH)}internal/ctype.h
array.$(OBJEXT): {$(VPATH)}internal/dllexport.h
array.$(OBJEXT): {$(VPATH)}internal/dosish.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+array.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
array.$(OBJEXT): {$(VPATH)}internal/error.h
array.$(OBJEXT): {$(VPATH)}internal/eval.h
array.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -1903,6 +2028,7 @@ array.$(OBJEXT): {$(VPATH)}oniguruma.h
array.$(OBJEXT): {$(VPATH)}probes.dmyh
array.$(OBJEXT): {$(VPATH)}probes.h
array.$(OBJEXT): {$(VPATH)}ruby_assert.h
+array.$(OBJEXT): {$(VPATH)}shape.h
array.$(OBJEXT): {$(VPATH)}st.h
array.$(OBJEXT): {$(VPATH)}subst.h
array.$(OBJEXT): {$(VPATH)}transient_heap.h
@@ -1914,6 +2040,7 @@ ast.$(OBJEXT): $(CCAN_DIR)/str/str.h
ast.$(OBJEXT): $(hdrdir)/ruby.h
ast.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ast.$(OBJEXT): $(top_srcdir)/internal/array.h
+ast.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h
ast.$(OBJEXT): $(top_srcdir)/internal/gc.h
ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h
@@ -1921,6 +2048,7 @@ 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/variable.h
ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ast.$(OBJEXT): {$(VPATH)}assert.h
@@ -1938,11 +2066,14 @@ ast.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ast.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ast.$(OBJEXT): {$(VPATH)}builtin.h
ast.$(OBJEXT): {$(VPATH)}config.h
+ast.$(OBJEXT): {$(VPATH)}constant.h
ast.$(OBJEXT): {$(VPATH)}defines.h
ast.$(OBJEXT): {$(VPATH)}encoding.h
ast.$(OBJEXT): {$(VPATH)}id.h
+ast.$(OBJEXT): {$(VPATH)}id_table.h
ast.$(OBJEXT): {$(VPATH)}intern.h
ast.$(OBJEXT): {$(VPATH)}internal.h
+ast.$(OBJEXT): {$(VPATH)}internal/abi.h
ast.$(OBJEXT): {$(VPATH)}internal/anyargs.h
ast.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -2012,6 +2143,15 @@ ast.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
ast.$(OBJEXT): {$(VPATH)}internal/ctype.h
ast.$(OBJEXT): {$(VPATH)}internal/dllexport.h
ast.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+ast.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
ast.$(OBJEXT): {$(VPATH)}internal/error.h
ast.$(OBJEXT): {$(VPATH)}internal/eval.h
ast.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -2090,6 +2230,7 @@ ast.$(OBJEXT): {$(VPATH)}onigmo.h
ast.$(OBJEXT): {$(VPATH)}oniguruma.h
ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ast.$(OBJEXT): {$(VPATH)}shape.h
ast.$(OBJEXT): {$(VPATH)}st.h
ast.$(OBJEXT): {$(VPATH)}subst.h
ast.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -2097,7 +2238,6 @@ ast.$(OBJEXT): {$(VPATH)}thread_native.h
ast.$(OBJEXT): {$(VPATH)}util.h
ast.$(OBJEXT): {$(VPATH)}vm_core.h
ast.$(OBJEXT): {$(VPATH)}vm_opts.h
-bignum.$(OBJEXT): $(hdrdir)/ruby.h
bignum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
bignum.$(OBJEXT): $(top_srcdir)/internal/bignum.h
bignum.$(OBJEXT): $(top_srcdir)/internal/bits.h
@@ -2111,7 +2251,6 @@ 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
@@ -2133,6 +2272,7 @@ bignum.$(OBJEXT): {$(VPATH)}id.h
bignum.$(OBJEXT): {$(VPATH)}id_table.h
bignum.$(OBJEXT): {$(VPATH)}intern.h
bignum.$(OBJEXT): {$(VPATH)}internal.h
+bignum.$(OBJEXT): {$(VPATH)}internal/abi.h
bignum.$(OBJEXT): {$(VPATH)}internal/anyargs.h
bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -2274,6 +2414,7 @@ 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)}shape.h
bignum.$(OBJEXT): {$(VPATH)}st.h
bignum.$(OBJEXT): {$(VPATH)}subst.h
bignum.$(OBJEXT): {$(VPATH)}thread.h
@@ -2282,14 +2423,15 @@ builtin.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
builtin.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
builtin.$(OBJEXT): $(CCAN_DIR)/list/list.h
builtin.$(OBJEXT): $(CCAN_DIR)/str/str.h
-builtin.$(OBJEXT): $(hdrdir)/ruby.h
builtin.$(OBJEXT): $(hdrdir)/ruby/ruby.h
builtin.$(OBJEXT): $(top_srcdir)/internal/array.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h
builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h
builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h
builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h
builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h
builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
builtin.$(OBJEXT): {$(VPATH)}assert.h
@@ -2307,10 +2449,13 @@ builtin.$(OBJEXT): {$(VPATH)}builtin.c
builtin.$(OBJEXT): {$(VPATH)}builtin.h
builtin.$(OBJEXT): {$(VPATH)}builtin_binary.inc
builtin.$(OBJEXT): {$(VPATH)}config.h
+builtin.$(OBJEXT): {$(VPATH)}constant.h
builtin.$(OBJEXT): {$(VPATH)}defines.h
builtin.$(OBJEXT): {$(VPATH)}id.h
+builtin.$(OBJEXT): {$(VPATH)}id_table.h
builtin.$(OBJEXT): {$(VPATH)}intern.h
builtin.$(OBJEXT): {$(VPATH)}internal.h
+builtin.$(OBJEXT): {$(VPATH)}internal/abi.h
builtin.$(OBJEXT): {$(VPATH)}internal/anyargs.h
builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -2456,6 +2601,7 @@ builtin.$(OBJEXT): {$(VPATH)}missing.h
builtin.$(OBJEXT): {$(VPATH)}node.h
builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+builtin.$(OBJEXT): {$(VPATH)}shape.h
builtin.$(OBJEXT): {$(VPATH)}st.h
builtin.$(OBJEXT): {$(VPATH)}subst.h
builtin.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -2466,12 +2612,11 @@ class.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
class.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
class.$(OBJEXT): $(CCAN_DIR)/list/list.h
class.$(OBJEXT): $(CCAN_DIR)/str/str.h
-class.$(OBJEXT): $(hdrdir)/ruby.h
class.$(OBJEXT): $(hdrdir)/ruby/ruby.h
class.$(OBJEXT): $(top_srcdir)/internal/array.h
+class.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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
@@ -2504,6 +2649,7 @@ class.$(OBJEXT): {$(VPATH)}id.h
class.$(OBJEXT): {$(VPATH)}id_table.h
class.$(OBJEXT): {$(VPATH)}intern.h
class.$(OBJEXT): {$(VPATH)}internal.h
+class.$(OBJEXT): {$(VPATH)}internal/abi.h
class.$(OBJEXT): {$(VPATH)}internal/anyargs.h
class.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
class.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -2573,6 +2719,15 @@ class.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
class.$(OBJEXT): {$(VPATH)}internal/ctype.h
class.$(OBJEXT): {$(VPATH)}internal/dllexport.h
class.$(OBJEXT): {$(VPATH)}internal/dosish.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+class.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
class.$(OBJEXT): {$(VPATH)}internal/error.h
class.$(OBJEXT): {$(VPATH)}internal/eval.h
class.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -2650,14 +2805,15 @@ 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)}shape.h
class.$(OBJEXT): {$(VPATH)}st.h
class.$(OBJEXT): {$(VPATH)}subst.h
class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
class.$(OBJEXT): {$(VPATH)}thread_native.h
class.$(OBJEXT): {$(VPATH)}vm_core.h
class.$(OBJEXT): {$(VPATH)}vm_opts.h
-compar.$(OBJEXT): $(hdrdir)/ruby.h
compar.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+compar.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
compar.$(OBJEXT): $(top_srcdir)/internal/compar.h
compar.$(OBJEXT): $(top_srcdir)/internal/compilers.h
compar.$(OBJEXT): $(top_srcdir)/internal/error.h
@@ -2682,6 +2838,7 @@ compar.$(OBJEXT): {$(VPATH)}encoding.h
compar.$(OBJEXT): {$(VPATH)}id.h
compar.$(OBJEXT): {$(VPATH)}intern.h
compar.$(OBJEXT): {$(VPATH)}internal.h
+compar.$(OBJEXT): {$(VPATH)}internal/abi.h
compar.$(OBJEXT): {$(VPATH)}internal/anyargs.h
compar.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -2751,6 +2908,15 @@ compar.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
compar.$(OBJEXT): {$(VPATH)}internal/ctype.h
compar.$(OBJEXT): {$(VPATH)}internal/dllexport.h
compar.$(OBJEXT): {$(VPATH)}internal/dosish.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+compar.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
compar.$(OBJEXT): {$(VPATH)}internal/error.h
compar.$(OBJEXT): {$(VPATH)}internal/eval.h
compar.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -2830,9 +2996,9 @@ compile.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
compile.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
compile.$(OBJEXT): $(CCAN_DIR)/list/list.h
compile.$(OBJEXT): $(CCAN_DIR)/str/str.h
-compile.$(OBJEXT): $(hdrdir)/ruby.h
compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h
compile.$(OBJEXT): $(top_srcdir)/internal/array.h
+compile.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h
compile.$(OBJEXT): $(top_srcdir)/internal/bits.h
compile.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -2884,6 +3050,7 @@ compile.$(OBJEXT): {$(VPATH)}insns.inc
compile.$(OBJEXT): {$(VPATH)}insns_info.inc
compile.$(OBJEXT): {$(VPATH)}intern.h
compile.$(OBJEXT): {$(VPATH)}internal.h
+compile.$(OBJEXT): {$(VPATH)}internal/abi.h
compile.$(OBJEXT): {$(VPATH)}internal/anyargs.h
compile.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -2954,6 +3121,15 @@ compile.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
compile.$(OBJEXT): {$(VPATH)}internal/ctype.h
compile.$(OBJEXT): {$(VPATH)}internal/dllexport.h
compile.$(OBJEXT): {$(VPATH)}internal/dosish.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+compile.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
compile.$(OBJEXT): {$(VPATH)}internal/error.h
compile.$(OBJEXT): {$(VPATH)}internal/eval.h
compile.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -3030,13 +3206,12 @@ compile.$(OBJEXT): {$(VPATH)}missing.h
compile.$(OBJEXT): {$(VPATH)}node.h
compile.$(OBJEXT): {$(VPATH)}onigmo.h
compile.$(OBJEXT): {$(VPATH)}oniguruma.h
-compile.$(OBJEXT): {$(VPATH)}opt_sc.inc
compile.$(OBJEXT): {$(VPATH)}optinsn.inc
-compile.$(OBJEXT): {$(VPATH)}optunifs.inc
compile.$(OBJEXT): {$(VPATH)}re.h
compile.$(OBJEXT): {$(VPATH)}regex.h
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+compile.$(OBJEXT): {$(VPATH)}shape.h
compile.$(OBJEXT): {$(VPATH)}st.h
compile.$(OBJEXT): {$(VPATH)}subst.h
compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -3046,27 +3221,32 @@ 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): $(CCAN_DIR)/check_type/check_type.h
+complex.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+complex.$(OBJEXT): $(CCAN_DIR)/list/list.h
+complex.$(OBJEXT): $(CCAN_DIR)/str/str.h
complex.$(OBJEXT): $(hdrdir)/ruby/ruby.h
complex.$(OBJEXT): $(top_srcdir)/internal/array.h
+complex.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
complex.$(OBJEXT): $(top_srcdir)/internal/bignum.h
complex.$(OBJEXT): $(top_srcdir)/internal/bits.h
complex.$(OBJEXT): $(top_srcdir)/internal/class.h
complex.$(OBJEXT): $(top_srcdir)/internal/compilers.h
complex.$(OBJEXT): $(top_srcdir)/internal/complex.h
-complex.$(OBJEXT): $(top_srcdir)/internal/error.h
complex.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
complex.$(OBJEXT): $(top_srcdir)/internal/gc.h
+complex.$(OBJEXT): $(top_srcdir)/internal/imemo.h
complex.$(OBJEXT): $(top_srcdir)/internal/math.h
complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h
complex.$(OBJEXT): $(top_srcdir)/internal/object.h
complex.$(OBJEXT): $(top_srcdir)/internal/rational.h
complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-complex.$(OBJEXT): $(top_srcdir)/internal/string.h
+complex.$(OBJEXT): $(top_srcdir)/internal/variable.h
complex.$(OBJEXT): $(top_srcdir)/internal/vm.h
complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h
complex.$(OBJEXT): {$(VPATH)}assert.h
+complex.$(OBJEXT): {$(VPATH)}atomic.h
complex.$(OBJEXT): {$(VPATH)}backward/2/assume.h
complex.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
complex.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -3078,12 +3258,13 @@ complex.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
complex.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
complex.$(OBJEXT): {$(VPATH)}complex.c
complex.$(OBJEXT): {$(VPATH)}config.h
+complex.$(OBJEXT): {$(VPATH)}constant.h
complex.$(OBJEXT): {$(VPATH)}defines.h
-complex.$(OBJEXT): {$(VPATH)}encoding.h
complex.$(OBJEXT): {$(VPATH)}id.h
complex.$(OBJEXT): {$(VPATH)}id_table.h
complex.$(OBJEXT): {$(VPATH)}intern.h
complex.$(OBJEXT): {$(VPATH)}internal.h
+complex.$(OBJEXT): {$(VPATH)}internal/abi.h
complex.$(OBJEXT): {$(VPATH)}internal/anyargs.h
complex.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -3223,27 +3404,37 @@ complex.$(OBJEXT): {$(VPATH)}internal/value_type.h
complex.$(OBJEXT): {$(VPATH)}internal/variable.h
complex.$(OBJEXT): {$(VPATH)}internal/warning_push.h
complex.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+complex.$(OBJEXT): {$(VPATH)}method.h
complex.$(OBJEXT): {$(VPATH)}missing.h
-complex.$(OBJEXT): {$(VPATH)}onigmo.h
-complex.$(OBJEXT): {$(VPATH)}oniguruma.h
+complex.$(OBJEXT): {$(VPATH)}node.h
complex.$(OBJEXT): {$(VPATH)}ruby_assert.h
+complex.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+complex.$(OBJEXT): {$(VPATH)}shape.h
complex.$(OBJEXT): {$(VPATH)}st.h
complex.$(OBJEXT): {$(VPATH)}subst.h
+complex.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+complex.$(OBJEXT): {$(VPATH)}thread_native.h
+complex.$(OBJEXT): {$(VPATH)}vm_core.h
+complex.$(OBJEXT): {$(VPATH)}vm_opts.h
cont.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
cont.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
cont.$(OBJEXT): $(CCAN_DIR)/list/list.h
cont.$(OBJEXT): $(CCAN_DIR)/str/str.h
cont.$(OBJEXT): $(hdrdir)/ruby.h
cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-cont.$(OBJEXT): $(top_srcdir)/include/ruby/fiber/scheduler.h
cont.$(OBJEXT): $(top_srcdir)/internal/array.h
+cont.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h
cont.$(OBJEXT): $(top_srcdir)/internal/cont.h
+cont.$(OBJEXT): $(top_srcdir)/internal/error.h
cont.$(OBJEXT): $(top_srcdir)/internal/gc.h
cont.$(OBJEXT): $(top_srcdir)/internal/imemo.h
cont.$(OBJEXT): $(top_srcdir)/internal/proc.h
+cont.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
cont.$(OBJEXT): $(top_srcdir)/internal/serial.h
cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+cont.$(OBJEXT): $(top_srcdir)/internal/string.h
+cont.$(OBJEXT): $(top_srcdir)/internal/variable.h
cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
@@ -3259,9 +3450,11 @@ cont.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
cont.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
cont.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
cont.$(OBJEXT): {$(VPATH)}config.h
+cont.$(OBJEXT): {$(VPATH)}constant.h
cont.$(OBJEXT): {$(VPATH)}cont.c
cont.$(OBJEXT): {$(VPATH)}debug_counter.h
cont.$(OBJEXT): {$(VPATH)}defines.h
+cont.$(OBJEXT): {$(VPATH)}encoding.h
cont.$(OBJEXT): {$(VPATH)}eval_intern.h
cont.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
cont.$(OBJEXT): {$(VPATH)}gc.h
@@ -3269,6 +3462,7 @@ cont.$(OBJEXT): {$(VPATH)}id.h
cont.$(OBJEXT): {$(VPATH)}id_table.h
cont.$(OBJEXT): {$(VPATH)}intern.h
cont.$(OBJEXT): {$(VPATH)}internal.h
+cont.$(OBJEXT): {$(VPATH)}internal/abi.h
cont.$(OBJEXT): {$(VPATH)}internal/anyargs.h
cont.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -3338,6 +3532,15 @@ cont.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
cont.$(OBJEXT): {$(VPATH)}internal/ctype.h
cont.$(OBJEXT): {$(VPATH)}internal/dllexport.h
cont.$(OBJEXT): {$(VPATH)}internal/dosish.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
cont.$(OBJEXT): {$(VPATH)}internal/error.h
cont.$(OBJEXT): {$(VPATH)}internal/eval.h
cont.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -3408,14 +3611,18 @@ cont.$(OBJEXT): {$(VPATH)}internal/value_type.h
cont.$(OBJEXT): {$(VPATH)}internal/variable.h
cont.$(OBJEXT): {$(VPATH)}internal/warning_push.h
cont.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+cont.$(OBJEXT): {$(VPATH)}iseq.h
cont.$(OBJEXT): {$(VPATH)}method.h
cont.$(OBJEXT): {$(VPATH)}missing.h
cont.$(OBJEXT): {$(VPATH)}mjit.h
cont.$(OBJEXT): {$(VPATH)}node.h
+cont.$(OBJEXT): {$(VPATH)}onigmo.h
+cont.$(OBJEXT): {$(VPATH)}oniguruma.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)}shape.h
cont.$(OBJEXT): {$(VPATH)}st.h
cont.$(OBJEXT): {$(VPATH)}subst.h
cont.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -3423,20 +3630,23 @@ cont.$(OBJEXT): {$(VPATH)}thread_native.h
cont.$(OBJEXT): {$(VPATH)}vm_core.h
cont.$(OBJEXT): {$(VPATH)}vm_debug.h
cont.$(OBJEXT): {$(VPATH)}vm_opts.h
+cont.$(OBJEXT): {$(VPATH)}vm_sync.h
+cont.$(OBJEXT): {$(VPATH)}yjit.h
debug.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
debug.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
debug.$(OBJEXT): $(CCAN_DIR)/list/list.h
debug.$(OBJEXT): $(CCAN_DIR)/str/str.h
-debug.$(OBJEXT): $(hdrdir)/ruby.h
debug.$(OBJEXT): $(hdrdir)/ruby/ruby.h
debug.$(OBJEXT): $(top_srcdir)/internal/array.h
+debug.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+debug.$(OBJEXT): $(top_srcdir)/internal/class.h
debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
debug.$(OBJEXT): $(top_srcdir)/internal/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/variable.h
debug.$(OBJEXT): $(top_srcdir)/internal/vm.h
debug.$(OBJEXT): $(top_srcdir)/internal/warnings.h
debug.$(OBJEXT): {$(VPATH)}assert.h
@@ -3451,9 +3661,11 @@ debug.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
debug.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
debug.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
debug.$(OBJEXT): {$(VPATH)}config.h
+debug.$(OBJEXT): {$(VPATH)}constant.h
debug.$(OBJEXT): {$(VPATH)}debug.c
debug.$(OBJEXT): {$(VPATH)}debug_counter.h
debug.$(OBJEXT): {$(VPATH)}defines.h
+debug.$(OBJEXT): {$(VPATH)}encindex.h
debug.$(OBJEXT): {$(VPATH)}encoding.h
debug.$(OBJEXT): {$(VPATH)}eval_intern.h
debug.$(OBJEXT): {$(VPATH)}gc.h
@@ -3461,6 +3673,7 @@ debug.$(OBJEXT): {$(VPATH)}id.h
debug.$(OBJEXT): {$(VPATH)}id_table.h
debug.$(OBJEXT): {$(VPATH)}intern.h
debug.$(OBJEXT): {$(VPATH)}internal.h
+debug.$(OBJEXT): {$(VPATH)}internal/abi.h
debug.$(OBJEXT): {$(VPATH)}internal/anyargs.h
debug.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -3530,6 +3743,15 @@ debug.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
debug.$(OBJEXT): {$(VPATH)}internal/ctype.h
debug.$(OBJEXT): {$(VPATH)}internal/dllexport.h
debug.$(OBJEXT): {$(VPATH)}internal/dosish.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+debug.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
debug.$(OBJEXT): {$(VPATH)}internal/error.h
debug.$(OBJEXT): {$(VPATH)}internal/eval.h
debug.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -3610,6 +3832,7 @@ 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)}shape.h
debug.$(OBJEXT): {$(VPATH)}st.h
debug.$(OBJEXT): {$(VPATH)}subst.h
debug.$(OBJEXT): {$(VPATH)}symbol.h
@@ -3620,13 +3843,11 @@ 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
@@ -3638,6 +3859,7 @@ debug_counter.$(OBJEXT): {$(VPATH)}debug_counter.h
debug_counter.$(OBJEXT): {$(VPATH)}defines.h
debug_counter.$(OBJEXT): {$(VPATH)}intern.h
debug_counter.$(OBJEXT): {$(VPATH)}internal.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/abi.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/anyargs.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -3781,9 +4003,9 @@ 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/class.h
dir.$(OBJEXT): $(top_srcdir)/internal/compilers.h
dir.$(OBJEXT): $(top_srcdir)/internal/dir.h
dir.$(OBJEXT): $(top_srcdir)/internal/encoding.h
@@ -3791,9 +4013,11 @@ dir.$(OBJEXT): $(top_srcdir)/internal/error.h
dir.$(OBJEXT): $(top_srcdir)/internal/file.h
dir.$(OBJEXT): $(top_srcdir)/internal/gc.h
dir.$(OBJEXT): $(top_srcdir)/internal/io.h
+dir.$(OBJEXT): $(top_srcdir)/internal/object.h
dir.$(OBJEXT): $(top_srcdir)/internal/serial.h
dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
dir.$(OBJEXT): $(top_srcdir)/internal/string.h
+dir.$(OBJEXT): $(top_srcdir)/internal/variable.h
dir.$(OBJEXT): $(top_srcdir)/internal/vm.h
dir.$(OBJEXT): $(top_srcdir)/internal/warnings.h
dir.$(OBJEXT): {$(VPATH)}assert.h
@@ -3808,14 +4032,17 @@ dir.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
dir.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
dir.$(OBJEXT): {$(VPATH)}builtin.h
dir.$(OBJEXT): {$(VPATH)}config.h
+dir.$(OBJEXT): {$(VPATH)}constant.h
dir.$(OBJEXT): {$(VPATH)}defines.h
dir.$(OBJEXT): {$(VPATH)}dir.c
dir.$(OBJEXT): {$(VPATH)}dir.rbinc
dir.$(OBJEXT): {$(VPATH)}encindex.h
dir.$(OBJEXT): {$(VPATH)}encoding.h
dir.$(OBJEXT): {$(VPATH)}id.h
+dir.$(OBJEXT): {$(VPATH)}id_table.h
dir.$(OBJEXT): {$(VPATH)}intern.h
dir.$(OBJEXT): {$(VPATH)}internal.h
+dir.$(OBJEXT): {$(VPATH)}internal/abi.h
dir.$(OBJEXT): {$(VPATH)}internal/anyargs.h
dir.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -3885,6 +4112,15 @@ dir.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
dir.$(OBJEXT): {$(VPATH)}internal/ctype.h
dir.$(OBJEXT): {$(VPATH)}internal/dllexport.h
dir.$(OBJEXT): {$(VPATH)}internal/dosish.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+dir.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
dir.$(OBJEXT): {$(VPATH)}internal/error.h
dir.$(OBJEXT): {$(VPATH)}internal/eval.h
dir.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -3959,11 +4195,11 @@ dir.$(OBJEXT): {$(VPATH)}io.h
dir.$(OBJEXT): {$(VPATH)}missing.h
dir.$(OBJEXT): {$(VPATH)}onigmo.h
dir.$(OBJEXT): {$(VPATH)}oniguruma.h
+dir.$(OBJEXT): {$(VPATH)}shape.h
dir.$(OBJEXT): {$(VPATH)}st.h
dir.$(OBJEXT): {$(VPATH)}subst.h
dir.$(OBJEXT): {$(VPATH)}thread.h
dir.$(OBJEXT): {$(VPATH)}util.h
-dln.$(OBJEXT): $(hdrdir)/ruby.h
dln.$(OBJEXT): $(hdrdir)/ruby/ruby.h
dln.$(OBJEXT): $(top_srcdir)/internal/compilers.h
dln.$(OBJEXT): $(top_srcdir)/internal/warnings.h
@@ -3983,6 +4219,7 @@ dln.$(OBJEXT): {$(VPATH)}dln.c
dln.$(OBJEXT): {$(VPATH)}dln.h
dln.$(OBJEXT): {$(VPATH)}intern.h
dln.$(OBJEXT): {$(VPATH)}internal.h
+dln.$(OBJEXT): {$(VPATH)}internal/abi.h
dln.$(OBJEXT): {$(VPATH)}internal/anyargs.h
dln.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -4130,7 +4367,6 @@ 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
@@ -4141,6 +4377,7 @@ dln_find.$(OBJEXT): {$(VPATH)}defines.h
dln_find.$(OBJEXT): {$(VPATH)}dln.h
dln_find.$(OBJEXT): {$(VPATH)}dln_find.c
dln_find.$(OBJEXT): {$(VPATH)}intern.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/abi.h
dln_find.$(OBJEXT): {$(VPATH)}internal/anyargs.h
dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -4288,7 +4525,6 @@ 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
@@ -4298,6 +4534,7 @@ dmydln.$(OBJEXT): {$(VPATH)}config.h
dmydln.$(OBJEXT): {$(VPATH)}defines.h
dmydln.$(OBJEXT): {$(VPATH)}dmydln.c
dmydln.$(OBJEXT): {$(VPATH)}intern.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/abi.h
dmydln.$(OBJEXT): {$(VPATH)}internal/anyargs.h
dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -4442,17 +4679,329 @@ dmydln.$(OBJEXT): {$(VPATH)}st.h
dmydln.$(OBJEXT): {$(VPATH)}subst.h
dmyenc.$(OBJEXT): {$(VPATH)}dmyenc.c
dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
+enc/ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enc/ascii.$(OBJEXT): {$(VPATH)}assert.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enc/ascii.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enc/ascii.$(OBJEXT): {$(VPATH)}config.h
enc/ascii.$(OBJEXT): {$(VPATH)}defines.h
enc/ascii.$(OBJEXT): {$(VPATH)}enc/ascii.c
enc/ascii.$(OBJEXT): {$(VPATH)}encindex.h
+enc/ascii.$(OBJEXT): {$(VPATH)}encoding.h
+enc/ascii.$(OBJEXT): {$(VPATH)}intern.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/assume.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/cast.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/config.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/error.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/eval.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/event.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/gc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/glob.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/globals.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/memory.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/method.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/module.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/value.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/variable.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enc/ascii.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enc/ascii.$(OBJEXT): {$(VPATH)}missing.h
+enc/ascii.$(OBJEXT): {$(VPATH)}onigmo.h
+enc/ascii.$(OBJEXT): {$(VPATH)}oniguruma.h
enc/ascii.$(OBJEXT): {$(VPATH)}regenc.h
+enc/ascii.$(OBJEXT): {$(VPATH)}st.h
+enc/ascii.$(OBJEXT): {$(VPATH)}subst.h
enc/trans/newline.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}assert.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enc/trans/newline.$(OBJEXT): {$(VPATH)}config.h
enc/trans/newline.$(OBJEXT): {$(VPATH)}defines.h
enc/trans/newline.$(OBJEXT): {$(VPATH)}enc/trans/newline.c
enc/trans/newline.$(OBJEXT): {$(VPATH)}intern.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/assume.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/cast.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/config.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/error.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/eval.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/event.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/gc.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/glob.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/globals.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/memory.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/method.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/module.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/value.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/variable.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enc/trans/newline.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enc/trans/newline.$(OBJEXT): {$(VPATH)}missing.h
enc/trans/newline.$(OBJEXT): {$(VPATH)}st.h
enc/trans/newline.$(OBJEXT): {$(VPATH)}subst.h
@@ -4460,34 +5009,511 @@ enc/trans/newline.$(OBJEXT): {$(VPATH)}transcode_data.h
enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/casefold.h
enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/name2ctype.h
enc/unicode.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enc/unicode.$(OBJEXT): {$(VPATH)}assert.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enc/unicode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enc/unicode.$(OBJEXT): {$(VPATH)}config.h
enc/unicode.$(OBJEXT): {$(VPATH)}defines.h
enc/unicode.$(OBJEXT): {$(VPATH)}enc/unicode.c
enc/unicode.$(OBJEXT): {$(VPATH)}intern.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/assume.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/cast.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/config.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/error.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/eval.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/event.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/gc.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/glob.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/globals.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/memory.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/method.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/module.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/value.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/variable.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enc/unicode.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enc/unicode.$(OBJEXT): {$(VPATH)}missing.h
enc/unicode.$(OBJEXT): {$(VPATH)}onigmo.h
enc/unicode.$(OBJEXT): {$(VPATH)}regenc.h
enc/unicode.$(OBJEXT): {$(VPATH)}regint.h
enc/unicode.$(OBJEXT): {$(VPATH)}st.h
enc/unicode.$(OBJEXT): {$(VPATH)}subst.h
+enc/us_ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}assert.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enc/us_ascii.$(OBJEXT): {$(VPATH)}config.h
enc/us_ascii.$(OBJEXT): {$(VPATH)}defines.h
enc/us_ascii.$(OBJEXT): {$(VPATH)}enc/us_ascii.c
enc/us_ascii.$(OBJEXT): {$(VPATH)}encindex.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}encoding.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}intern.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/assume.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/cast.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/config.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/error.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/eval.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/event.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/gc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/glob.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/globals.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/memory.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/method.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/module.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/value.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/variable.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enc/us_ascii.$(OBJEXT): {$(VPATH)}missing.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}onigmo.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}oniguruma.h
enc/us_ascii.$(OBJEXT): {$(VPATH)}regenc.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}st.h
+enc/us_ascii.$(OBJEXT): {$(VPATH)}subst.h
+enc/utf_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}assert.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enc/utf_8.$(OBJEXT): {$(VPATH)}config.h
enc/utf_8.$(OBJEXT): {$(VPATH)}defines.h
enc/utf_8.$(OBJEXT): {$(VPATH)}enc/utf_8.c
enc/utf_8.$(OBJEXT): {$(VPATH)}encindex.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}encoding.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}intern.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/assume.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/cast.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/config.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/error.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/eval.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/event.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/gc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/glob.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/globals.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/memory.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/method.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/module.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/value.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/variable.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enc/utf_8.$(OBJEXT): {$(VPATH)}missing.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}onigmo.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}oniguruma.h
enc/utf_8.$(OBJEXT): {$(VPATH)}regenc.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}st.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}subst.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/error.h
encoding.$(OBJEXT): $(top_srcdir)/internal/gc.h
encoding.$(OBJEXT): $(top_srcdir)/internal/inits.h
encoding.$(OBJEXT): $(top_srcdir)/internal/load.h
@@ -4495,6 +5521,7 @@ encoding.$(OBJEXT): $(top_srcdir)/internal/object.h
encoding.$(OBJEXT): $(top_srcdir)/internal/serial.h
encoding.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
encoding.$(OBJEXT): $(top_srcdir)/internal/string.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/variable.h
encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h
encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h
encoding.$(OBJEXT): {$(VPATH)}assert.h
@@ -4508,6 +5535,7 @@ encoding.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
encoding.$(OBJEXT): {$(VPATH)}config.h
+encoding.$(OBJEXT): {$(VPATH)}constant.h
encoding.$(OBJEXT): {$(VPATH)}debug_counter.h
encoding.$(OBJEXT): {$(VPATH)}defines.h
encoding.$(OBJEXT): {$(VPATH)}encindex.h
@@ -4516,6 +5544,7 @@ 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/abi.h
encoding.$(OBJEXT): {$(VPATH)}internal/anyargs.h
encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -4585,6 +5614,15 @@ encoding.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
encoding.$(OBJEXT): {$(VPATH)}internal/ctype.h
encoding.$(OBJEXT): {$(VPATH)}internal/dllexport.h
encoding.$(OBJEXT): {$(VPATH)}internal/dosish.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+encoding.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
encoding.$(OBJEXT): {$(VPATH)}internal/error.h
encoding.$(OBJEXT): {$(VPATH)}internal/eval.h
encoding.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -4656,19 +5694,19 @@ 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
encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h
+encoding.$(OBJEXT): {$(VPATH)}shape.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/basic_operators.h
enum.$(OBJEXT): $(top_srcdir)/internal/bignum.h
enum.$(OBJEXT): $(top_srcdir)/internal/bits.h
enum.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -4686,6 +5724,7 @@ enum.$(OBJEXT): $(top_srcdir)/internal/rational.h
enum.$(OBJEXT): $(top_srcdir)/internal/re.h
enum.$(OBJEXT): $(top_srcdir)/internal/serial.h
enum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+enum.$(OBJEXT): $(top_srcdir)/internal/variable.h
enum.$(OBJEXT): $(top_srcdir)/internal/vm.h
enum.$(OBJEXT): $(top_srcdir)/internal/warnings.h
enum.$(OBJEXT): {$(VPATH)}assert.h
@@ -4699,6 +5738,7 @@ enum.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
enum.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
enum.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enum.$(OBJEXT): {$(VPATH)}config.h
+enum.$(OBJEXT): {$(VPATH)}constant.h
enum.$(OBJEXT): {$(VPATH)}defines.h
enum.$(OBJEXT): {$(VPATH)}encoding.h
enum.$(OBJEXT): {$(VPATH)}enum.c
@@ -4706,6 +5746,7 @@ enum.$(OBJEXT): {$(VPATH)}id.h
enum.$(OBJEXT): {$(VPATH)}id_table.h
enum.$(OBJEXT): {$(VPATH)}intern.h
enum.$(OBJEXT): {$(VPATH)}internal.h
+enum.$(OBJEXT): {$(VPATH)}internal/abi.h
enum.$(OBJEXT): {$(VPATH)}internal/anyargs.h
enum.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -4775,6 +5816,15 @@ enum.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
enum.$(OBJEXT): {$(VPATH)}internal/ctype.h
enum.$(OBJEXT): {$(VPATH)}internal/dllexport.h
enum.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+enum.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
enum.$(OBJEXT): {$(VPATH)}internal/error.h
enum.$(OBJEXT): {$(VPATH)}internal/eval.h
enum.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -4849,15 +5899,21 @@ enum.$(OBJEXT): {$(VPATH)}missing.h
enum.$(OBJEXT): {$(VPATH)}onigmo.h
enum.$(OBJEXT): {$(VPATH)}oniguruma.h
enum.$(OBJEXT): {$(VPATH)}ruby_assert.h
+enum.$(OBJEXT): {$(VPATH)}shape.h
enum.$(OBJEXT): {$(VPATH)}st.h
enum.$(OBJEXT): {$(VPATH)}subst.h
enum.$(OBJEXT): {$(VPATH)}symbol.h
enum.$(OBJEXT): {$(VPATH)}util.h
-enumerator.$(OBJEXT): $(hdrdir)/ruby.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/list/list.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/str/str.h
enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/bits.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/class.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/compilers.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/enumerator.h
enumerator.$(OBJEXT): $(top_srcdir)/internal/error.h
@@ -4875,6 +5931,7 @@ 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)}atomic.h
enumerator.$(OBJEXT): {$(VPATH)}backward/2/assume.h
enumerator.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
enumerator.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -4889,8 +5946,10 @@ enumerator.$(OBJEXT): {$(VPATH)}defines.h
enumerator.$(OBJEXT): {$(VPATH)}encoding.h
enumerator.$(OBJEXT): {$(VPATH)}enumerator.c
enumerator.$(OBJEXT): {$(VPATH)}id.h
+enumerator.$(OBJEXT): {$(VPATH)}id_table.h
enumerator.$(OBJEXT): {$(VPATH)}intern.h
enumerator.$(OBJEXT): {$(VPATH)}internal.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/abi.h
enumerator.$(OBJEXT): {$(VPATH)}internal/anyargs.h
enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -4960,6 +6019,15 @@ enumerator.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
enumerator.$(OBJEXT): {$(VPATH)}internal/ctype.h
enumerator.$(OBJEXT): {$(VPATH)}internal/dllexport.h
enumerator.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
enumerator.$(OBJEXT): {$(VPATH)}internal/error.h
enumerator.$(OBJEXT): {$(VPATH)}internal/eval.h
enumerator.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -5030,19 +6098,27 @@ enumerator.$(OBJEXT): {$(VPATH)}internal/value_type.h
enumerator.$(OBJEXT): {$(VPATH)}internal/variable.h
enumerator.$(OBJEXT): {$(VPATH)}internal/warning_push.h
enumerator.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+enumerator.$(OBJEXT): {$(VPATH)}method.h
enumerator.$(OBJEXT): {$(VPATH)}missing.h
+enumerator.$(OBJEXT): {$(VPATH)}node.h
enumerator.$(OBJEXT): {$(VPATH)}onigmo.h
enumerator.$(OBJEXT): {$(VPATH)}oniguruma.h
enumerator.$(OBJEXT): {$(VPATH)}ruby_assert.h
+enumerator.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+enumerator.$(OBJEXT): {$(VPATH)}shape.h
enumerator.$(OBJEXT): {$(VPATH)}st.h
enumerator.$(OBJEXT): {$(VPATH)}subst.h
+enumerator.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+enumerator.$(OBJEXT): {$(VPATH)}thread_native.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_core.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_opts.h
error.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
error.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
error.$(OBJEXT): $(CCAN_DIR)/list/list.h
error.$(OBJEXT): $(CCAN_DIR)/str/str.h
-error.$(OBJEXT): $(hdrdir)/ruby.h
error.$(OBJEXT): $(hdrdir)/ruby/ruby.h
error.$(OBJEXT): $(top_srcdir)/internal/array.h
+error.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
error.$(OBJEXT): $(top_srcdir)/internal/class.h
error.$(OBJEXT): $(top_srcdir)/internal/compilers.h
error.$(OBJEXT): $(top_srcdir)/internal/error.h
@@ -5078,11 +6154,11 @@ 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/abi.h
error.$(OBJEXT): {$(VPATH)}internal/anyargs.h
error.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
error.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -5152,6 +6228,15 @@ error.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
error.$(OBJEXT): {$(VPATH)}internal/ctype.h
error.$(OBJEXT): {$(VPATH)}internal/dllexport.h
error.$(OBJEXT): {$(VPATH)}internal/dosish.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+error.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
error.$(OBJEXT): {$(VPATH)}internal/error.h
error.$(OBJEXT): {$(VPATH)}internal/eval.h
error.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -5231,6 +6316,7 @@ error.$(OBJEXT): {$(VPATH)}onigmo.h
error.$(OBJEXT): {$(VPATH)}oniguruma.h
error.$(OBJEXT): {$(VPATH)}ruby_assert.h
error.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+error.$(OBJEXT): {$(VPATH)}shape.h
error.$(OBJEXT): {$(VPATH)}st.h
error.$(OBJEXT): {$(VPATH)}subst.h
error.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -5244,10 +6330,11 @@ 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)/include/ruby/fiber/scheduler.h
eval.$(OBJEXT): $(top_srcdir)/internal/array.h
+eval.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
eval.$(OBJEXT): $(top_srcdir)/internal/class.h
eval.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+eval.$(OBJEXT): $(top_srcdir)/internal/cont.h
eval.$(OBJEXT): $(top_srcdir)/internal/error.h
eval.$(OBJEXT): $(top_srcdir)/internal/eval.h
eval.$(OBJEXT): $(top_srcdir)/internal/gc.h
@@ -5289,6 +6376,7 @@ eval.$(OBJEXT): {$(VPATH)}id.h
eval.$(OBJEXT): {$(VPATH)}id_table.h
eval.$(OBJEXT): {$(VPATH)}intern.h
eval.$(OBJEXT): {$(VPATH)}internal.h
+eval.$(OBJEXT): {$(VPATH)}internal/abi.h
eval.$(OBJEXT): {$(VPATH)}internal/anyargs.h
eval.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -5358,6 +6446,15 @@ eval.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
eval.$(OBJEXT): {$(VPATH)}internal/ctype.h
eval.$(OBJEXT): {$(VPATH)}internal/dllexport.h
eval.$(OBJEXT): {$(VPATH)}internal/dosish.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+eval.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
eval.$(OBJEXT): {$(VPATH)}internal/error.h
eval.$(OBJEXT): {$(VPATH)}internal/eval.h
eval.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -5443,6 +6540,7 @@ 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)}shape.h
eval.$(OBJEXT): {$(VPATH)}st.h
eval.$(OBJEXT): {$(VPATH)}subst.h
eval.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -5453,6 +6551,7 @@ 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/attr/format.h
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
@@ -5463,8 +6562,8 @@ explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/config.h
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+explicit_bzero.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
explicit_bzero.$(OBJEXT): {$(VPATH)}missing.h
-file.$(OBJEXT): $(hdrdir)/ruby.h
file.$(OBJEXT): $(hdrdir)/ruby/ruby.h
file.$(OBJEXT): $(top_srcdir)/internal/array.h
file.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -5482,6 +6581,7 @@ file.$(OBJEXT): $(top_srcdir)/internal/serial.h
file.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
file.$(OBJEXT): $(top_srcdir)/internal/string.h
file.$(OBJEXT): $(top_srcdir)/internal/thread.h
+file.$(OBJEXT): $(top_srcdir)/internal/variable.h
file.$(OBJEXT): $(top_srcdir)/internal/vm.h
file.$(OBJEXT): $(top_srcdir)/internal/warnings.h
file.$(OBJEXT): {$(VPATH)}assert.h
@@ -5495,6 +6595,7 @@ file.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
file.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
file.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
file.$(OBJEXT): {$(VPATH)}config.h
+file.$(OBJEXT): {$(VPATH)}constant.h
file.$(OBJEXT): {$(VPATH)}defines.h
file.$(OBJEXT): {$(VPATH)}dln.h
file.$(OBJEXT): {$(VPATH)}encindex.h
@@ -5504,6 +6605,7 @@ file.$(OBJEXT): {$(VPATH)}id.h
file.$(OBJEXT): {$(VPATH)}id_table.h
file.$(OBJEXT): {$(VPATH)}intern.h
file.$(OBJEXT): {$(VPATH)}internal.h
+file.$(OBJEXT): {$(VPATH)}internal/abi.h
file.$(OBJEXT): {$(VPATH)}internal/anyargs.h
file.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
file.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -5573,6 +6675,15 @@ file.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
file.$(OBJEXT): {$(VPATH)}internal/ctype.h
file.$(OBJEXT): {$(VPATH)}internal/dllexport.h
file.$(OBJEXT): {$(VPATH)}internal/dosish.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+file.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
file.$(OBJEXT): {$(VPATH)}internal/error.h
file.$(OBJEXT): {$(VPATH)}internal/eval.h
file.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -5647,6 +6758,7 @@ file.$(OBJEXT): {$(VPATH)}io.h
file.$(OBJEXT): {$(VPATH)}missing.h
file.$(OBJEXT): {$(VPATH)}onigmo.h
file.$(OBJEXT): {$(VPATH)}oniguruma.h
+file.$(OBJEXT): {$(VPATH)}shape.h
file.$(OBJEXT): {$(VPATH)}st.h
file.$(OBJEXT): {$(VPATH)}subst.h
file.$(OBJEXT): {$(VPATH)}thread.h
@@ -5658,6 +6770,7 @@ 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/basic_operators.h
gc.$(OBJEXT): $(top_srcdir)/internal/bignum.h
gc.$(OBJEXT): $(top_srcdir)/internal/bits.h
gc.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -5711,6 +6824,7 @@ gc.$(OBJEXT): {$(VPATH)}id.h
gc.$(OBJEXT): {$(VPATH)}id_table.h
gc.$(OBJEXT): {$(VPATH)}intern.h
gc.$(OBJEXT): {$(VPATH)}internal.h
+gc.$(OBJEXT): {$(VPATH)}internal/abi.h
gc.$(OBJEXT): {$(VPATH)}internal/anyargs.h
gc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -5781,6 +6895,15 @@ gc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
gc.$(OBJEXT): {$(VPATH)}internal/ctype.h
gc.$(OBJEXT): {$(VPATH)}internal/dllexport.h
gc.$(OBJEXT): {$(VPATH)}internal/dosish.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+gc.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
gc.$(OBJEXT): {$(VPATH)}internal/error.h
gc.$(OBJEXT): {$(VPATH)}internal/eval.h
gc.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -5852,6 +6975,7 @@ gc.$(OBJEXT): {$(VPATH)}internal/variable.h
gc.$(OBJEXT): {$(VPATH)}internal/warning_push.h
gc.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
gc.$(OBJEXT): {$(VPATH)}io.h
+gc.$(OBJEXT): {$(VPATH)}iseq.h
gc.$(OBJEXT): {$(VPATH)}method.h
gc.$(OBJEXT): {$(VPATH)}missing.h
gc.$(OBJEXT): {$(VPATH)}mjit.h
@@ -5868,6 +6992,7 @@ gc.$(OBJEXT): {$(VPATH)}regex.h
gc.$(OBJEXT): {$(VPATH)}regint.h
gc.$(OBJEXT): {$(VPATH)}ruby_assert.h
gc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+gc.$(OBJEXT): {$(VPATH)}shape.h
gc.$(OBJEXT): {$(VPATH)}st.h
gc.$(OBJEXT): {$(VPATH)}subst.h
gc.$(OBJEXT): {$(VPATH)}symbol.h
@@ -5888,11 +7013,13 @@ goruby.$(OBJEXT): $(CCAN_DIR)/str/str.h
goruby.$(OBJEXT): $(hdrdir)/ruby.h
goruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
goruby.$(OBJEXT): $(top_srcdir)/internal/array.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
goruby.$(OBJEXT): {$(VPATH)}assert.h
@@ -5908,13 +7035,15 @@ goruby.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
goruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
goruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
goruby.$(OBJEXT): {$(VPATH)}config.h
+goruby.$(OBJEXT): {$(VPATH)}constant.h
goruby.$(OBJEXT): {$(VPATH)}defines.h
goruby.$(OBJEXT): {$(VPATH)}golf_prelude.c
-goruby.$(OBJEXT): {$(VPATH)}golf_prelude.rb
goruby.$(OBJEXT): {$(VPATH)}goruby.c
goruby.$(OBJEXT): {$(VPATH)}id.h
+goruby.$(OBJEXT): {$(VPATH)}id_table.h
goruby.$(OBJEXT): {$(VPATH)}intern.h
goruby.$(OBJEXT): {$(VPATH)}internal.h
+goruby.$(OBJEXT): {$(VPATH)}internal/abi.h
goruby.$(OBJEXT): {$(VPATH)}internal/anyargs.h
goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -5951,6 +7080,7 @@ 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/nonstring.h
goruby.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
goruby.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
goruby.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
@@ -6061,6 +7191,7 @@ goruby.$(OBJEXT): {$(VPATH)}missing.h
goruby.$(OBJEXT): {$(VPATH)}node.h
goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+goruby.$(OBJEXT): {$(VPATH)}shape.h
goruby.$(OBJEXT): {$(VPATH)}st.h
goruby.$(OBJEXT): {$(VPATH)}subst.h
goruby.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -6068,9 +7199,13 @@ goruby.$(OBJEXT): {$(VPATH)}thread_native.h
goruby.$(OBJEXT): {$(VPATH)}vm_core.h
goruby.$(OBJEXT): {$(VPATH)}vm_debug.h
goruby.$(OBJEXT): {$(VPATH)}vm_opts.h
-hash.$(OBJEXT): $(hdrdir)/ruby.h
+hash.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+hash.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+hash.$(OBJEXT): $(CCAN_DIR)/list/list.h
+hash.$(OBJEXT): $(CCAN_DIR)/str/str.h
hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h
hash.$(OBJEXT): $(top_srcdir)/internal/array.h
+hash.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h
hash.$(OBJEXT): $(top_srcdir)/internal/bits.h
hash.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -6079,16 +7214,20 @@ hash.$(OBJEXT): $(top_srcdir)/internal/cont.h
hash.$(OBJEXT): $(top_srcdir)/internal/error.h
hash.$(OBJEXT): $(top_srcdir)/internal/gc.h
hash.$(OBJEXT): $(top_srcdir)/internal/hash.h
+hash.$(OBJEXT): $(top_srcdir)/internal/imemo.h
hash.$(OBJEXT): $(top_srcdir)/internal/object.h
hash.$(OBJEXT): $(top_srcdir)/internal/proc.h
hash.$(OBJEXT): $(top_srcdir)/internal/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/thread.h
hash.$(OBJEXT): $(top_srcdir)/internal/time.h
+hash.$(OBJEXT): $(top_srcdir)/internal/variable.h
hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
hash.$(OBJEXT): {$(VPATH)}assert.h
+hash.$(OBJEXT): {$(VPATH)}atomic.h
hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h
hash.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
hash.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -6099,6 +7238,7 @@ hash.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
hash.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
hash.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
hash.$(OBJEXT): {$(VPATH)}config.h
+hash.$(OBJEXT): {$(VPATH)}constant.h
hash.$(OBJEXT): {$(VPATH)}debug_counter.h
hash.$(OBJEXT): {$(VPATH)}defines.h
hash.$(OBJEXT): {$(VPATH)}encoding.h
@@ -6107,6 +7247,7 @@ hash.$(OBJEXT): {$(VPATH)}id.h
hash.$(OBJEXT): {$(VPATH)}id_table.h
hash.$(OBJEXT): {$(VPATH)}intern.h
hash.$(OBJEXT): {$(VPATH)}internal.h
+hash.$(OBJEXT): {$(VPATH)}internal/abi.h
hash.$(OBJEXT): {$(VPATH)}internal/anyargs.h
hash.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -6176,6 +7317,15 @@ hash.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
hash.$(OBJEXT): {$(VPATH)}internal/ctype.h
hash.$(OBJEXT): {$(VPATH)}internal/dllexport.h
hash.$(OBJEXT): {$(VPATH)}internal/dosish.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+hash.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
hash.$(OBJEXT): {$(VPATH)}internal/error.h
hash.$(OBJEXT): {$(VPATH)}internal/eval.h
hash.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -6246,17 +7396,29 @@ hash.$(OBJEXT): {$(VPATH)}internal/value_type.h
hash.$(OBJEXT): {$(VPATH)}internal/variable.h
hash.$(OBJEXT): {$(VPATH)}internal/warning_push.h
hash.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+hash.$(OBJEXT): {$(VPATH)}iseq.h
+hash.$(OBJEXT): {$(VPATH)}method.h
hash.$(OBJEXT): {$(VPATH)}missing.h
+hash.$(OBJEXT): {$(VPATH)}node.h
hash.$(OBJEXT): {$(VPATH)}onigmo.h
hash.$(OBJEXT): {$(VPATH)}oniguruma.h
hash.$(OBJEXT): {$(VPATH)}probes.dmyh
hash.$(OBJEXT): {$(VPATH)}probes.h
+hash.$(OBJEXT): {$(VPATH)}ractor.h
hash.$(OBJEXT): {$(VPATH)}ruby_assert.h
+hash.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+hash.$(OBJEXT): {$(VPATH)}shape.h
hash.$(OBJEXT): {$(VPATH)}st.h
hash.$(OBJEXT): {$(VPATH)}subst.h
hash.$(OBJEXT): {$(VPATH)}symbol.h
+hash.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+hash.$(OBJEXT): {$(VPATH)}thread_native.h
hash.$(OBJEXT): {$(VPATH)}transient_heap.h
hash.$(OBJEXT): {$(VPATH)}util.h
+hash.$(OBJEXT): {$(VPATH)}vm_core.h
+hash.$(OBJEXT): {$(VPATH)}vm_debug.h
+hash.$(OBJEXT): {$(VPATH)}vm_opts.h
+hash.$(OBJEXT): {$(VPATH)}vm_sync.h
inits.$(OBJEXT): $(hdrdir)/ruby.h
inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h
inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -6277,7 +7439,7 @@ 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/abi.h
inits.$(OBJEXT): {$(VPATH)}internal/anyargs.h
inits.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -6425,10 +7587,9 @@ io.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
io.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
io.$(OBJEXT): $(CCAN_DIR)/list/list.h
io.$(OBJEXT): $(CCAN_DIR)/str/str.h
-io.$(OBJEXT): $(hdrdir)/ruby.h
io.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-io.$(OBJEXT): $(top_srcdir)/include/ruby/fiber/scheduler.h
io.$(OBJEXT): $(top_srcdir)/internal/array.h
+io.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
io.$(OBJEXT): $(top_srcdir)/internal/bignum.h
io.$(OBJEXT): $(top_srcdir)/internal/bits.h
io.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -6474,6 +7635,7 @@ io.$(OBJEXT): {$(VPATH)}id.h
io.$(OBJEXT): {$(VPATH)}id_table.h
io.$(OBJEXT): {$(VPATH)}intern.h
io.$(OBJEXT): {$(VPATH)}internal.h
+io.$(OBJEXT): {$(VPATH)}internal/abi.h
io.$(OBJEXT): {$(VPATH)}internal/anyargs.h
io.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
io.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -6543,6 +7705,15 @@ io.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
io.$(OBJEXT): {$(VPATH)}internal/ctype.h
io.$(OBJEXT): {$(VPATH)}internal/dllexport.h
io.$(OBJEXT): {$(VPATH)}internal/dosish.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+io.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
io.$(OBJEXT): {$(VPATH)}internal/error.h
io.$(OBJEXT): {$(VPATH)}internal/eval.h
io.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -6616,6 +7787,7 @@ io.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
io.$(OBJEXT): {$(VPATH)}io.c
io.$(OBJEXT): {$(VPATH)}io.h
io.$(OBJEXT): {$(VPATH)}io.rbinc
+io.$(OBJEXT): {$(VPATH)}io/buffer.h
io.$(OBJEXT): {$(VPATH)}method.h
io.$(OBJEXT): {$(VPATH)}missing.h
io.$(OBJEXT): {$(VPATH)}node.h
@@ -6624,6 +7796,7 @@ 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)}shape.h
io.$(OBJEXT): {$(VPATH)}st.h
io.$(OBJEXT): {$(VPATH)}subst.h
io.$(OBJEXT): {$(VPATH)}thread.h
@@ -6632,6 +7805,192 @@ io.$(OBJEXT): {$(VPATH)}thread_native.h
io.$(OBJEXT): {$(VPATH)}util.h
io.$(OBJEXT): {$(VPATH)}vm_core.h
io.$(OBJEXT): {$(VPATH)}vm_opts.h
+io_buffer.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/array.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/error.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/string.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/thread.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/vm.h
+io_buffer.$(OBJEXT): {$(VPATH)}assert.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+io_buffer.$(OBJEXT): {$(VPATH)}config.h
+io_buffer.$(OBJEXT): {$(VPATH)}defines.h
+io_buffer.$(OBJEXT): {$(VPATH)}encoding.h
+io_buffer.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
+io_buffer.$(OBJEXT): {$(VPATH)}intern.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/abi.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/assume.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/cast.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/config.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/ctype.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/dosish.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/error.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/eval.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/event.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/gc.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/glob.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/globals.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/iterator.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/memory.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/method.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/module.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/newobj.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/symbol.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/value.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/value_type.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/variable.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+io_buffer.$(OBJEXT): {$(VPATH)}io.h
+io_buffer.$(OBJEXT): {$(VPATH)}io/buffer.h
+io_buffer.$(OBJEXT): {$(VPATH)}io_buffer.c
+io_buffer.$(OBJEXT): {$(VPATH)}missing.h
+io_buffer.$(OBJEXT): {$(VPATH)}onigmo.h
+io_buffer.$(OBJEXT): {$(VPATH)}oniguruma.h
+io_buffer.$(OBJEXT): {$(VPATH)}st.h
+io_buffer.$(OBJEXT): {$(VPATH)}subst.h
iseq.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
iseq.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
iseq.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -6639,6 +7998,7 @@ 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/basic_operators.h
iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h
iseq.$(OBJEXT): $(top_srcdir)/internal/class.h
iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h
@@ -6684,6 +8044,7 @@ iseq.$(OBJEXT): {$(VPATH)}insns.inc
iseq.$(OBJEXT): {$(VPATH)}insns_info.inc
iseq.$(OBJEXT): {$(VPATH)}intern.h
iseq.$(OBJEXT): {$(VPATH)}internal.h
+iseq.$(OBJEXT): {$(VPATH)}internal/abi.h
iseq.$(OBJEXT): {$(VPATH)}internal/anyargs.h
iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -6753,6 +8114,15 @@ iseq.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
iseq.$(OBJEXT): {$(VPATH)}internal/ctype.h
iseq.$(OBJEXT): {$(VPATH)}internal/dllexport.h
iseq.$(OBJEXT): {$(VPATH)}internal/dosish.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+iseq.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
iseq.$(OBJEXT): {$(VPATH)}internal/error.h
iseq.$(OBJEXT): {$(VPATH)}internal/eval.h
iseq.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -6832,8 +8202,10 @@ iseq.$(OBJEXT): {$(VPATH)}node.h
iseq.$(OBJEXT): {$(VPATH)}node_name.inc
iseq.$(OBJEXT): {$(VPATH)}onigmo.h
iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
+iseq.$(OBJEXT): {$(VPATH)}ractor.h
iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+iseq.$(OBJEXT): {$(VPATH)}shape.h
iseq.$(OBJEXT): {$(VPATH)}st.h
iseq.$(OBJEXT): {$(VPATH)}subst.h
iseq.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -6842,13 +8214,14 @@ iseq.$(OBJEXT): {$(VPATH)}util.h
iseq.$(OBJEXT): {$(VPATH)}vm_callinfo.h
iseq.$(OBJEXT): {$(VPATH)}vm_core.h
iseq.$(OBJEXT): {$(VPATH)}vm_opts.h
+iseq.$(OBJEXT): {$(VPATH)}yjit.h
load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
load.$(OBJEXT): $(CCAN_DIR)/list/list.h
load.$(OBJEXT): $(CCAN_DIR)/str/str.h
-load.$(OBJEXT): $(hdrdir)/ruby.h
load.$(OBJEXT): $(hdrdir)/ruby/ruby.h
load.$(OBJEXT): $(top_srcdir)/internal/array.h
+load.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
load.$(OBJEXT): $(top_srcdir)/internal/compilers.h
load.$(OBJEXT): $(top_srcdir)/internal/dir.h
load.$(OBJEXT): $(top_srcdir)/internal/error.h
@@ -6877,6 +8250,7 @@ load.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
load.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
load.$(OBJEXT): {$(VPATH)}config.h
load.$(OBJEXT): {$(VPATH)}constant.h
+load.$(OBJEXT): {$(VPATH)}darray.h
load.$(OBJEXT): {$(VPATH)}defines.h
load.$(OBJEXT): {$(VPATH)}dln.h
load.$(OBJEXT): {$(VPATH)}encoding.h
@@ -6885,6 +8259,7 @@ load.$(OBJEXT): {$(VPATH)}id.h
load.$(OBJEXT): {$(VPATH)}id_table.h
load.$(OBJEXT): {$(VPATH)}intern.h
load.$(OBJEXT): {$(VPATH)}internal.h
+load.$(OBJEXT): {$(VPATH)}internal/abi.h
load.$(OBJEXT): {$(VPATH)}internal/anyargs.h
load.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
load.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -6954,6 +8329,15 @@ load.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
load.$(OBJEXT): {$(VPATH)}internal/ctype.h
load.$(OBJEXT): {$(VPATH)}internal/dllexport.h
load.$(OBJEXT): {$(VPATH)}internal/dosish.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+load.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
load.$(OBJEXT): {$(VPATH)}internal/error.h
load.$(OBJEXT): {$(VPATH)}internal/eval.h
load.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -7035,6 +8419,7 @@ load.$(OBJEXT): {$(VPATH)}probes.dmyh
load.$(OBJEXT): {$(VPATH)}probes.h
load.$(OBJEXT): {$(VPATH)}ruby_assert.h
load.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+load.$(OBJEXT): {$(VPATH)}shape.h
load.$(OBJEXT): {$(VPATH)}st.h
load.$(OBJEXT): {$(VPATH)}subst.h
load.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -7049,7 +8434,6 @@ 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
@@ -7058,6 +8442,7 @@ loadpath.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
loadpath.$(OBJEXT): {$(VPATH)}config.h
loadpath.$(OBJEXT): {$(VPATH)}defines.h
loadpath.$(OBJEXT): {$(VPATH)}intern.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/abi.h
loadpath.$(OBJEXT): {$(VPATH)}internal/anyargs.h
loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -7202,13 +8587,11 @@ loadpath.$(OBJEXT): {$(VPATH)}missing.h
loadpath.$(OBJEXT): {$(VPATH)}st.h
loadpath.$(OBJEXT): {$(VPATH)}subst.h
loadpath.$(OBJEXT): {$(VPATH)}verconf.h
-localeinit.$(OBJEXT): $(hdrdir)/ruby.h
localeinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
localeinit.$(OBJEXT): {$(VPATH)}assert.h
localeinit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
localeinit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
localeinit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-localeinit.$(OBJEXT): {$(VPATH)}backward/2/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
@@ -7220,6 +8603,7 @@ localeinit.$(OBJEXT): {$(VPATH)}encindex.h
localeinit.$(OBJEXT): {$(VPATH)}encoding.h
localeinit.$(OBJEXT): {$(VPATH)}intern.h
localeinit.$(OBJEXT): {$(VPATH)}internal.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/abi.h
localeinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -7289,6 +8673,15 @@ localeinit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
localeinit.$(OBJEXT): {$(VPATH)}internal/ctype.h
localeinit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
localeinit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
localeinit.$(OBJEXT): {$(VPATH)}internal/error.h
localeinit.$(OBJEXT): {$(VPATH)}internal/eval.h
localeinit.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -7372,7 +8765,6 @@ 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
@@ -7381,6 +8773,7 @@ main.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
main.$(OBJEXT): {$(VPATH)}config.h
main.$(OBJEXT): {$(VPATH)}defines.h
main.$(OBJEXT): {$(VPATH)}intern.h
+main.$(OBJEXT): {$(VPATH)}internal/abi.h
main.$(OBJEXT): {$(VPATH)}internal/anyargs.h
main.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
main.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -7522,29 +8915,39 @@ main.$(OBJEXT): {$(VPATH)}internal/warning_push.h
main.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
main.$(OBJEXT): {$(VPATH)}main.c
main.$(OBJEXT): {$(VPATH)}missing.h
-main.$(OBJEXT): {$(VPATH)}node.h
main.$(OBJEXT): {$(VPATH)}st.h
main.$(OBJEXT): {$(VPATH)}subst.h
main.$(OBJEXT): {$(VPATH)}vm_debug.h
-marshal.$(OBJEXT): $(hdrdir)/ruby.h
+marshal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+marshal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+marshal.$(OBJEXT): $(CCAN_DIR)/list/list.h
+marshal.$(OBJEXT): $(CCAN_DIR)/str/str.h
marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
marshal.$(OBJEXT): $(top_srcdir)/internal/array.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/bits.h
marshal.$(OBJEXT): $(top_srcdir)/internal/class.h
marshal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
marshal.$(OBJEXT): $(top_srcdir)/internal/encoding.h
marshal.$(OBJEXT): $(top_srcdir)/internal/error.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
marshal.$(OBJEXT): $(top_srcdir)/internal/gc.h
marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h
marshal.$(OBJEXT): $(top_srcdir)/internal/object.h
marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/symbol.h
marshal.$(OBJEXT): $(top_srcdir)/internal/util.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/variable.h
marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
marshal.$(OBJEXT): {$(VPATH)}assert.h
+marshal.$(OBJEXT): {$(VPATH)}atomic.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/assume.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -7554,13 +8957,17 @@ marshal.$(OBJEXT): {$(VPATH)}backward/2/limits.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+marshal.$(OBJEXT): {$(VPATH)}builtin.h
marshal.$(OBJEXT): {$(VPATH)}config.h
+marshal.$(OBJEXT): {$(VPATH)}constant.h
marshal.$(OBJEXT): {$(VPATH)}defines.h
marshal.$(OBJEXT): {$(VPATH)}encindex.h
marshal.$(OBJEXT): {$(VPATH)}encoding.h
+marshal.$(OBJEXT): {$(VPATH)}id.h
marshal.$(OBJEXT): {$(VPATH)}id_table.h
marshal.$(OBJEXT): {$(VPATH)}intern.h
marshal.$(OBJEXT): {$(VPATH)}internal.h
+marshal.$(OBJEXT): {$(VPATH)}internal/abi.h
marshal.$(OBJEXT): {$(VPATH)}internal/anyargs.h
marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -7597,6 +9004,7 @@ marshal.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
marshal.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
marshal.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
marshal.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h
marshal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
marshal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
marshal.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
@@ -7630,6 +9038,15 @@ marshal.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
marshal.$(OBJEXT): {$(VPATH)}internal/ctype.h
marshal.$(OBJEXT): {$(VPATH)}internal/dllexport.h
marshal.$(OBJEXT): {$(VPATH)}internal/dosish.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+marshal.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
marshal.$(OBJEXT): {$(VPATH)}internal/error.h
marshal.$(OBJEXT): {$(VPATH)}internal/eval.h
marshal.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -7702,13 +9119,22 @@ marshal.$(OBJEXT): {$(VPATH)}internal/warning_push.h
marshal.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
marshal.$(OBJEXT): {$(VPATH)}io.h
marshal.$(OBJEXT): {$(VPATH)}marshal.c
+marshal.$(OBJEXT): {$(VPATH)}marshal.rbinc
+marshal.$(OBJEXT): {$(VPATH)}method.h
marshal.$(OBJEXT): {$(VPATH)}missing.h
+marshal.$(OBJEXT): {$(VPATH)}node.h
marshal.$(OBJEXT): {$(VPATH)}onigmo.h
marshal.$(OBJEXT): {$(VPATH)}oniguruma.h
+marshal.$(OBJEXT): {$(VPATH)}ruby_assert.h
+marshal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+marshal.$(OBJEXT): {$(VPATH)}shape.h
marshal.$(OBJEXT): {$(VPATH)}st.h
marshal.$(OBJEXT): {$(VPATH)}subst.h
+marshal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+marshal.$(OBJEXT): {$(VPATH)}thread_native.h
marshal.$(OBJEXT): {$(VPATH)}util.h
-math.$(OBJEXT): $(hdrdir)/ruby.h
+marshal.$(OBJEXT): {$(VPATH)}vm_core.h
+marshal.$(OBJEXT): {$(VPATH)}vm_opts.h
math.$(OBJEXT): $(hdrdir)/ruby/ruby.h
math.$(OBJEXT): $(top_srcdir)/internal/bignum.h
math.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -7719,6 +9145,7 @@ math.$(OBJEXT): $(top_srcdir)/internal/math.h
math.$(OBJEXT): $(top_srcdir)/internal/object.h
math.$(OBJEXT): $(top_srcdir)/internal/serial.h
math.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+math.$(OBJEXT): $(top_srcdir)/internal/variable.h
math.$(OBJEXT): $(top_srcdir)/internal/vm.h
math.$(OBJEXT): $(top_srcdir)/internal/warnings.h
math.$(OBJEXT): {$(VPATH)}assert.h
@@ -7732,10 +9159,12 @@ math.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
math.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
math.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
math.$(OBJEXT): {$(VPATH)}config.h
+math.$(OBJEXT): {$(VPATH)}constant.h
math.$(OBJEXT): {$(VPATH)}defines.h
math.$(OBJEXT): {$(VPATH)}id_table.h
math.$(OBJEXT): {$(VPATH)}intern.h
math.$(OBJEXT): {$(VPATH)}internal.h
+math.$(OBJEXT): {$(VPATH)}internal/abi.h
math.$(OBJEXT): {$(VPATH)}internal/anyargs.h
math.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
math.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -7877,12 +9306,15 @@ math.$(OBJEXT): {$(VPATH)}internal/warning_push.h
math.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
math.$(OBJEXT): {$(VPATH)}math.c
math.$(OBJEXT): {$(VPATH)}missing.h
+math.$(OBJEXT): {$(VPATH)}shape.h
math.$(OBJEXT): {$(VPATH)}st.h
math.$(OBJEXT): {$(VPATH)}subst.h
memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/util.h
memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/warnings.h
memory_view.$(OBJEXT): {$(VPATH)}assert.h
memory_view.$(OBJEXT): {$(VPATH)}backward/2/assume.h
memory_view.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
@@ -7900,6 +9332,7 @@ 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/abi.h
memory_view.$(OBJEXT): {$(VPATH)}internal/anyargs.h
memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -8042,23 +9475,26 @@ 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)}shape.h
memory_view.$(OBJEXT): {$(VPATH)}st.h
memory_view.$(OBJEXT): {$(VPATH)}subst.h
+memory_view.$(OBJEXT): {$(VPATH)}util.h
memory_view.$(OBJEXT): {$(VPATH)}vm_debug.h
memory_view.$(OBJEXT): {$(VPATH)}vm_sync.h
miniinit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
miniinit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
miniinit.$(OBJEXT): $(CCAN_DIR)/list/list.h
miniinit.$(OBJEXT): $(CCAN_DIR)/str/str.h
-miniinit.$(OBJEXT): $(hdrdir)/ruby.h
miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+miniinit.$(OBJEXT): $(srcdir)/mjit_c.rb
miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/variable.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
miniinit.$(OBJEXT): {$(VPATH)}array.rb
@@ -8076,14 +9512,17 @@ miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
miniinit.$(OBJEXT): {$(VPATH)}builtin.h
miniinit.$(OBJEXT): {$(VPATH)}config.h
+miniinit.$(OBJEXT): {$(VPATH)}constant.h
miniinit.$(OBJEXT): {$(VPATH)}defines.h
miniinit.$(OBJEXT): {$(VPATH)}dir.rb
miniinit.$(OBJEXT): {$(VPATH)}encoding.h
miniinit.$(OBJEXT): {$(VPATH)}gc.rb
miniinit.$(OBJEXT): {$(VPATH)}gem_prelude.rb
miniinit.$(OBJEXT): {$(VPATH)}id.h
+miniinit.$(OBJEXT): {$(VPATH)}id_table.h
miniinit.$(OBJEXT): {$(VPATH)}intern.h
miniinit.$(OBJEXT): {$(VPATH)}internal.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/abi.h
miniinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -8120,6 +9559,7 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h
miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
miniinit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
miniinit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
@@ -8153,6 +9593,15 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
miniinit.$(OBJEXT): {$(VPATH)}internal/ctype.h
miniinit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
miniinit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
miniinit.$(OBJEXT): {$(VPATH)}internal/error.h
miniinit.$(OBJEXT): {$(VPATH)}internal/eval.h
miniinit.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -8226,11 +9675,14 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
miniinit.$(OBJEXT): {$(VPATH)}io.rb
miniinit.$(OBJEXT): {$(VPATH)}iseq.h
miniinit.$(OBJEXT): {$(VPATH)}kernel.rb
+miniinit.$(OBJEXT): {$(VPATH)}marshal.rb
miniinit.$(OBJEXT): {$(VPATH)}method.h
miniinit.$(OBJEXT): {$(VPATH)}mini_builtin.c
miniinit.$(OBJEXT): {$(VPATH)}miniinit.c
miniinit.$(OBJEXT): {$(VPATH)}miniprelude.c
miniinit.$(OBJEXT): {$(VPATH)}missing.h
+miniinit.$(OBJEXT): {$(VPATH)}mjit.rb
+miniinit.$(OBJEXT): {$(VPATH)}mjit_c.rb
miniinit.$(OBJEXT): {$(VPATH)}nilclass.rb
miniinit.$(OBJEXT): {$(VPATH)}node.h
miniinit.$(OBJEXT): {$(VPATH)}numeric.rb
@@ -8241,47 +9693,19 @@ 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)}shape.h
miniinit.$(OBJEXT): {$(VPATH)}st.h
miniinit.$(OBJEXT): {$(VPATH)}subst.h
+miniinit.$(OBJEXT): {$(VPATH)}symbol.rb
miniinit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
miniinit.$(OBJEXT): {$(VPATH)}thread_native.h
+miniinit.$(OBJEXT): {$(VPATH)}thread_sync.rb
miniinit.$(OBJEXT): {$(VPATH)}timev.rb
miniinit.$(OBJEXT): {$(VPATH)}trace_point.rb
miniinit.$(OBJEXT): {$(VPATH)}vm_core.h
miniinit.$(OBJEXT): {$(VPATH)}vm_opts.h
miniinit.$(OBJEXT): {$(VPATH)}warning.rb
-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
+miniinit.$(OBJEXT): {$(VPATH)}yjit.rb
mjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
mjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
mjit.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -8290,7 +9714,9 @@ 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/basic_operators.h
mjit.$(OBJEXT): $(top_srcdir)/internal/class.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
mjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
mjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
mjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
@@ -8298,8 +9724,10 @@ 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/process.h
mjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
mjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
mjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
mjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
mjit.$(OBJEXT): {$(VPATH)}assert.h
@@ -8329,6 +9757,7 @@ 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/abi.h
mjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -8398,6 +9827,15 @@ mjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
mjit.$(OBJEXT): {$(VPATH)}internal/ctype.h
mjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
mjit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+mjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
mjit.$(OBJEXT): {$(VPATH)}internal/error.h
mjit.$(OBJEXT): {$(VPATH)}internal/eval.h
mjit.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -8473,13 +9911,17 @@ mjit.$(OBJEXT): {$(VPATH)}method.h
mjit.$(OBJEXT): {$(VPATH)}missing.h
mjit.$(OBJEXT): {$(VPATH)}mjit.c
mjit.$(OBJEXT): {$(VPATH)}mjit.h
+mjit.$(OBJEXT): {$(VPATH)}mjit.rbinc
+mjit.$(OBJEXT): {$(VPATH)}mjit_c.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)}ractor.h
+mjit.$(OBJEXT): {$(VPATH)}ractor_core.h
mjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
mjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+mjit.$(OBJEXT): {$(VPATH)}shape.h
mjit.$(OBJEXT): {$(VPATH)}st.h
mjit.$(OBJEXT): {$(VPATH)}subst.h
mjit.$(OBJEXT): {$(VPATH)}thread.h
@@ -8491,224 +9933,221 @@ mjit.$(OBJEXT): {$(VPATH)}vm_core.h
mjit.$(OBJEXT): {$(VPATH)}vm_debug.h
mjit.$(OBJEXT): {$(VPATH)}vm_opts.h
mjit.$(OBJEXT): {$(VPATH)}vm_sync.h
-mjit_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/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
-mjit_compile.$(OBJEXT): {$(VPATH)}mjit.h
-mjit_compile.$(OBJEXT): {$(VPATH)}mjit_compile.c
-mjit_compile.$(OBJEXT): {$(VPATH)}mjit_compile.inc
-mjit_compile.$(OBJEXT): {$(VPATH)}node.h
-mjit_compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
-mjit_compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-mjit_compile.$(OBJEXT): {$(VPATH)}st.h
-mjit_compile.$(OBJEXT): {$(VPATH)}subst.h
-mjit_compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-mjit_compile.$(OBJEXT): {$(VPATH)}thread_native.h
-mjit_compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h
-mjit_compile.$(OBJEXT): {$(VPATH)}vm_core.h
-mjit_compile.$(OBJEXT): {$(VPATH)}vm_exec.h
-mjit_compile.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
-mjit_compile.$(OBJEXT): {$(VPATH)}vm_opts.h
+mjit.$(OBJEXT): {$(VPATH)}yjit.h
+mjit_c.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+mjit_c.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+mjit_c.$(OBJEXT): $(CCAN_DIR)/list/list.h
+mjit_c.$(OBJEXT): $(CCAN_DIR)/str/str.h
+mjit_c.$(OBJEXT): $(hdrdir)/ruby.h
+mjit_c.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+mjit_c.$(OBJEXT): $(srcdir)/mjit_c.rb
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/array.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/class.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/compile.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/gc.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/hash.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/object.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/serial.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/variable.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/vm.h
+mjit_c.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+mjit_c.$(OBJEXT): {$(VPATH)}assert.h
+mjit_c.$(OBJEXT): {$(VPATH)}atomic.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+mjit_c.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+mjit_c.$(OBJEXT): {$(VPATH)}builtin.h
+mjit_c.$(OBJEXT): {$(VPATH)}config.h
+mjit_c.$(OBJEXT): {$(VPATH)}constant.h
+mjit_c.$(OBJEXT): {$(VPATH)}debug_counter.h
+mjit_c.$(OBJEXT): {$(VPATH)}defines.h
+mjit_c.$(OBJEXT): {$(VPATH)}id.h
+mjit_c.$(OBJEXT): {$(VPATH)}id_table.h
+mjit_c.$(OBJEXT): {$(VPATH)}insns.def
+mjit_c.$(OBJEXT): {$(VPATH)}insns.inc
+mjit_c.$(OBJEXT): {$(VPATH)}insns_info.inc
+mjit_c.$(OBJEXT): {$(VPATH)}intern.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/abi.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/assume.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/cast.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/config.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/ctype.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/dosish.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/error.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/eval.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/event.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/gc.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/glob.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/globals.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/iterator.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/memory.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/method.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/module.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/newobj.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/symbol.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/value.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/value_type.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/variable.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+mjit_c.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+mjit_c.$(OBJEXT): {$(VPATH)}iseq.h
+mjit_c.$(OBJEXT): {$(VPATH)}method.h
+mjit_c.$(OBJEXT): {$(VPATH)}missing.h
+mjit_c.$(OBJEXT): {$(VPATH)}mjit.h
+mjit_c.$(OBJEXT): {$(VPATH)}mjit_c.c
+mjit_c.$(OBJEXT): {$(VPATH)}mjit_c.h
+mjit_c.$(OBJEXT): {$(VPATH)}mjit_c.rb
+mjit_c.$(OBJEXT): {$(VPATH)}mjit_c.rbinc
+mjit_c.$(OBJEXT): {$(VPATH)}mjit_sp_inc.inc
+mjit_c.$(OBJEXT): {$(VPATH)}node.h
+mjit_c.$(OBJEXT): {$(VPATH)}ruby_assert.h
+mjit_c.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+mjit_c.$(OBJEXT): {$(VPATH)}shape.h
+mjit_c.$(OBJEXT): {$(VPATH)}st.h
+mjit_c.$(OBJEXT): {$(VPATH)}subst.h
+mjit_c.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+mjit_c.$(OBJEXT): {$(VPATH)}thread_native.h
+mjit_c.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+mjit_c.$(OBJEXT): {$(VPATH)}vm_core.h
+mjit_c.$(OBJEXT): {$(VPATH)}vm_exec.h
+mjit_c.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
+mjit_c.$(OBJEXT): {$(VPATH)}vm_opts.h
+mjit_c.$(OBJEXT): {$(VPATH)}yjit.h
node.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
node.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
node.$(OBJEXT): $(CCAN_DIR)/list/list.h
node.$(OBJEXT): $(CCAN_DIR)/str/str.h
-node.$(OBJEXT): $(hdrdir)/ruby.h
node.$(OBJEXT): $(hdrdir)/ruby/ruby.h
node.$(OBJEXT): $(top_srcdir)/internal/array.h
+node.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
node.$(OBJEXT): $(top_srcdir)/internal/compilers.h
node.$(OBJEXT): $(top_srcdir)/internal/gc.h
node.$(OBJEXT): $(top_srcdir)/internal/hash.h
@@ -8736,6 +10175,7 @@ node.$(OBJEXT): {$(VPATH)}id.h
node.$(OBJEXT): {$(VPATH)}id_table.h
node.$(OBJEXT): {$(VPATH)}intern.h
node.$(OBJEXT): {$(VPATH)}internal.h
+node.$(OBJEXT): {$(VPATH)}internal/abi.h
node.$(OBJEXT): {$(VPATH)}internal/anyargs.h
node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -8881,13 +10321,13 @@ node.$(OBJEXT): {$(VPATH)}node.c
node.$(OBJEXT): {$(VPATH)}node.h
node.$(OBJEXT): {$(VPATH)}ruby_assert.h
node.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+node.$(OBJEXT): {$(VPATH)}shape.h
node.$(OBJEXT): {$(VPATH)}st.h
node.$(OBJEXT): {$(VPATH)}subst.h
node.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
node.$(OBJEXT): {$(VPATH)}thread_native.h
node.$(OBJEXT): {$(VPATH)}vm_core.h
node.$(OBJEXT): {$(VPATH)}vm_opts.h
-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
@@ -8904,6 +10344,7 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/object.h
numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h
numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h
numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/string.h
numeric.$(OBJEXT): $(top_srcdir)/internal/util.h
numeric.$(OBJEXT): $(top_srcdir)/internal/variable.h
numeric.$(OBJEXT): $(top_srcdir)/internal/vm.h
@@ -8927,6 +10368,7 @@ numeric.$(OBJEXT): {$(VPATH)}id.h
numeric.$(OBJEXT): {$(VPATH)}id_table.h
numeric.$(OBJEXT): {$(VPATH)}intern.h
numeric.$(OBJEXT): {$(VPATH)}internal.h
+numeric.$(OBJEXT): {$(VPATH)}internal/abi.h
numeric.$(OBJEXT): {$(VPATH)}internal/anyargs.h
numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -8996,6 +10438,15 @@ numeric.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
numeric.$(OBJEXT): {$(VPATH)}internal/ctype.h
numeric.$(OBJEXT): {$(VPATH)}internal/dllexport.h
numeric.$(OBJEXT): {$(VPATH)}internal/dosish.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+numeric.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
numeric.$(OBJEXT): {$(VPATH)}internal/error.h
numeric.$(OBJEXT): {$(VPATH)}internal/eval.h
numeric.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9068,17 +10519,21 @@ numeric.$(OBJEXT): {$(VPATH)}internal/warning_push.h
numeric.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
numeric.$(OBJEXT): {$(VPATH)}missing.h
numeric.$(OBJEXT): {$(VPATH)}numeric.c
-numeric.$(OBJEXT): {$(VPATH)}numeric.rb
numeric.$(OBJEXT): {$(VPATH)}numeric.rbinc
numeric.$(OBJEXT): {$(VPATH)}onigmo.h
numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
+numeric.$(OBJEXT): {$(VPATH)}shape.h
numeric.$(OBJEXT): {$(VPATH)}st.h
numeric.$(OBJEXT): {$(VPATH)}subst.h
numeric.$(OBJEXT): {$(VPATH)}util.h
-object.$(OBJEXT): $(hdrdir)/ruby.h
+object.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+object.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+object.$(OBJEXT): $(CCAN_DIR)/list/list.h
+object.$(OBJEXT): $(CCAN_DIR)/str/str.h
object.$(OBJEXT): $(hdrdir)/ruby/ruby.h
object.$(OBJEXT): $(top_srcdir)/internal/array.h
+object.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
object.$(OBJEXT): $(top_srcdir)/internal/bignum.h
object.$(OBJEXT): $(top_srcdir)/internal/bits.h
object.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -9087,6 +10542,7 @@ object.$(OBJEXT): $(top_srcdir)/internal/error.h
object.$(OBJEXT): $(top_srcdir)/internal/eval.h
object.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
object.$(OBJEXT): $(top_srcdir)/internal/gc.h
+object.$(OBJEXT): $(top_srcdir)/internal/imemo.h
object.$(OBJEXT): $(top_srcdir)/internal/inits.h
object.$(OBJEXT): $(top_srcdir)/internal/numeric.h
object.$(OBJEXT): $(top_srcdir)/internal/object.h
@@ -9099,6 +10555,7 @@ object.$(OBJEXT): $(top_srcdir)/internal/variable.h
object.$(OBJEXT): $(top_srcdir)/internal/vm.h
object.$(OBJEXT): $(top_srcdir)/internal/warnings.h
object.$(OBJEXT): {$(VPATH)}assert.h
+object.$(OBJEXT): {$(VPATH)}atomic.h
object.$(OBJEXT): {$(VPATH)}backward/2/assume.h
object.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
object.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -9117,6 +10574,7 @@ object.$(OBJEXT): {$(VPATH)}id.h
object.$(OBJEXT): {$(VPATH)}id_table.h
object.$(OBJEXT): {$(VPATH)}intern.h
object.$(OBJEXT): {$(VPATH)}internal.h
+object.$(OBJEXT): {$(VPATH)}internal/abi.h
object.$(OBJEXT): {$(VPATH)}internal/anyargs.h
object.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
object.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -9186,6 +10644,15 @@ object.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
object.$(OBJEXT): {$(VPATH)}internal/ctype.h
object.$(OBJEXT): {$(VPATH)}internal/dllexport.h
object.$(OBJEXT): {$(VPATH)}internal/dosish.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+object.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
object.$(OBJEXT): {$(VPATH)}internal/error.h
object.$(OBJEXT): {$(VPATH)}internal/eval.h
object.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9256,28 +10723,35 @@ 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)}method.h
object.$(OBJEXT): {$(VPATH)}missing.h
-object.$(OBJEXT): {$(VPATH)}nilclass.rb
object.$(OBJEXT): {$(VPATH)}nilclass.rbinc
+object.$(OBJEXT): {$(VPATH)}node.h
object.$(OBJEXT): {$(VPATH)}object.c
object.$(OBJEXT): {$(VPATH)}onigmo.h
object.$(OBJEXT): {$(VPATH)}oniguruma.h
object.$(OBJEXT): {$(VPATH)}probes.dmyh
object.$(OBJEXT): {$(VPATH)}probes.h
+object.$(OBJEXT): {$(VPATH)}ruby_assert.h
+object.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+object.$(OBJEXT): {$(VPATH)}shape.h
object.$(OBJEXT): {$(VPATH)}st.h
object.$(OBJEXT): {$(VPATH)}subst.h
+object.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+object.$(OBJEXT): {$(VPATH)}thread_native.h
object.$(OBJEXT): {$(VPATH)}util.h
-pack.$(OBJEXT): $(hdrdir)/ruby.h
+object.$(OBJEXT): {$(VPATH)}variable.h
+object.$(OBJEXT): {$(VPATH)}vm_core.h
+object.$(OBJEXT): {$(VPATH)}vm_opts.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/gc.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
@@ -9298,6 +10772,7 @@ 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/abi.h
pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h
pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -9367,6 +10842,15 @@ pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
pack.$(OBJEXT): {$(VPATH)}internal/ctype.h
pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h
pack.$(OBJEXT): {$(VPATH)}internal/dosish.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+pack.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
pack.$(OBJEXT): {$(VPATH)}internal/error.h
pack.$(OBJEXT): {$(VPATH)}internal/eval.h
pack.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9442,8 +10926,10 @@ pack.$(OBJEXT): {$(VPATH)}onigmo.h
pack.$(OBJEXT): {$(VPATH)}oniguruma.h
pack.$(OBJEXT): {$(VPATH)}pack.c
pack.$(OBJEXT): {$(VPATH)}pack.rbinc
+pack.$(OBJEXT): {$(VPATH)}shape.h
pack.$(OBJEXT): {$(VPATH)}st.h
pack.$(OBJEXT): {$(VPATH)}subst.h
+pack.$(OBJEXT): {$(VPATH)}util.h
parse.$(OBJEXT): $(hdrdir)/ruby.h
parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
parse.$(OBJEXT): $(top_srcdir)/internal/array.h
@@ -9452,6 +10938,7 @@ parse.$(OBJEXT): $(top_srcdir)/internal/bits.h
parse.$(OBJEXT): $(top_srcdir)/internal/compile.h
parse.$(OBJEXT): $(top_srcdir)/internal/compilers.h
parse.$(OBJEXT): $(top_srcdir)/internal/complex.h
+parse.$(OBJEXT): $(top_srcdir)/internal/encoding.h
parse.$(OBJEXT): $(top_srcdir)/internal/error.h
parse.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
parse.$(OBJEXT): $(top_srcdir)/internal/gc.h
@@ -9467,7 +10954,6 @@ 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
@@ -9490,6 +10976,7 @@ parse.$(OBJEXT): {$(VPATH)}id.h
parse.$(OBJEXT): {$(VPATH)}id_table.h
parse.$(OBJEXT): {$(VPATH)}intern.h
parse.$(OBJEXT): {$(VPATH)}internal.h
+parse.$(OBJEXT): {$(VPATH)}internal/abi.h
parse.$(OBJEXT): {$(VPATH)}internal/anyargs.h
parse.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -9559,6 +11046,15 @@ parse.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
parse.$(OBJEXT): {$(VPATH)}internal/ctype.h
parse.$(OBJEXT): {$(VPATH)}internal/dllexport.h
parse.$(OBJEXT): {$(VPATH)}internal/dosish.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+parse.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
parse.$(OBJEXT): {$(VPATH)}internal/error.h
parse.$(OBJEXT): {$(VPATH)}internal/eval.h
parse.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9644,49 +11140,24 @@ parse.$(OBJEXT): {$(VPATH)}ractor.h
parse.$(OBJEXT): {$(VPATH)}regenc.h
parse.$(OBJEXT): {$(VPATH)}regex.h
parse.$(OBJEXT): {$(VPATH)}ruby_assert.h
+parse.$(OBJEXT): {$(VPATH)}shape.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/basic_operators.h
proc.$(OBJEXT): $(top_srcdir)/internal/class.h
proc.$(OBJEXT): $(top_srcdir)/internal/compilers.h
proc.$(OBJEXT): $(top_srcdir)/internal/error.h
proc.$(OBJEXT): $(top_srcdir)/internal/eval.h
proc.$(OBJEXT): $(top_srcdir)/internal/gc.h
+proc.$(OBJEXT): $(top_srcdir)/internal/hash.h
proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h
proc.$(OBJEXT): $(top_srcdir)/internal/object.h
proc.$(OBJEXT): $(top_srcdir)/internal/proc.h
@@ -9694,6 +11165,7 @@ proc.$(OBJEXT): $(top_srcdir)/internal/serial.h
proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
proc.$(OBJEXT): $(top_srcdir)/internal/string.h
proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+proc.$(OBJEXT): $(top_srcdir)/internal/variable.h
proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
proc.$(OBJEXT): {$(VPATH)}assert.h
@@ -9708,6 +11180,7 @@ proc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
proc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
proc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
proc.$(OBJEXT): {$(VPATH)}config.h
+proc.$(OBJEXT): {$(VPATH)}constant.h
proc.$(OBJEXT): {$(VPATH)}defines.h
proc.$(OBJEXT): {$(VPATH)}encoding.h
proc.$(OBJEXT): {$(VPATH)}eval_intern.h
@@ -9716,6 +11189,7 @@ proc.$(OBJEXT): {$(VPATH)}id.h
proc.$(OBJEXT): {$(VPATH)}id_table.h
proc.$(OBJEXT): {$(VPATH)}intern.h
proc.$(OBJEXT): {$(VPATH)}internal.h
+proc.$(OBJEXT): {$(VPATH)}internal/abi.h
proc.$(OBJEXT): {$(VPATH)}internal/anyargs.h
proc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -9785,6 +11259,15 @@ proc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
proc.$(OBJEXT): {$(VPATH)}internal/ctype.h
proc.$(OBJEXT): {$(VPATH)}internal/dllexport.h
proc.$(OBJEXT): {$(VPATH)}internal/dosish.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+proc.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
proc.$(OBJEXT): {$(VPATH)}internal/error.h
proc.$(OBJEXT): {$(VPATH)}internal/eval.h
proc.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9864,39 +11347,44 @@ proc.$(OBJEXT): {$(VPATH)}oniguruma.h
proc.$(OBJEXT): {$(VPATH)}proc.c
proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+proc.$(OBJEXT): {$(VPATH)}shape.h
proc.$(OBJEXT): {$(VPATH)}st.h
proc.$(OBJEXT): {$(VPATH)}subst.h
proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
proc.$(OBJEXT): {$(VPATH)}thread_native.h
proc.$(OBJEXT): {$(VPATH)}vm_core.h
proc.$(OBJEXT): {$(VPATH)}vm_opts.h
+proc.$(OBJEXT): {$(VPATH)}yjit.h
process.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
process.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
process.$(OBJEXT): $(CCAN_DIR)/list/list.h
process.$(OBJEXT): $(CCAN_DIR)/str/str.h
process.$(OBJEXT): $(hdrdir)/ruby.h
process.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-process.$(OBJEXT): $(top_srcdir)/include/ruby/fiber/scheduler.h
process.$(OBJEXT): $(top_srcdir)/internal/array.h
+process.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+process.$(OBJEXT): $(top_srcdir)/internal/bignum.h
process.$(OBJEXT): $(top_srcdir)/internal/bits.h
process.$(OBJEXT): $(top_srcdir)/internal/class.h
process.$(OBJEXT): $(top_srcdir)/internal/compilers.h
process.$(OBJEXT): $(top_srcdir)/internal/dir.h
process.$(OBJEXT): $(top_srcdir)/internal/error.h
process.$(OBJEXT): $(top_srcdir)/internal/eval.h
+process.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
process.$(OBJEXT): $(top_srcdir)/internal/gc.h
process.$(OBJEXT): $(top_srcdir)/internal/hash.h
process.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+process.$(OBJEXT): $(top_srcdir)/internal/numeric.h
process.$(OBJEXT): $(top_srcdir)/internal/object.h
process.$(OBJEXT): $(top_srcdir)/internal/process.h
process.$(OBJEXT): $(top_srcdir)/internal/serial.h
process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
process.$(OBJEXT): $(top_srcdir)/internal/string.h
process.$(OBJEXT): $(top_srcdir)/internal/thread.h
+process.$(OBJEXT): $(top_srcdir)/internal/time.h
process.$(OBJEXT): $(top_srcdir)/internal/variable.h
process.$(OBJEXT): $(top_srcdir)/internal/vm.h
process.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-process.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
process.$(OBJEXT): {$(VPATH)}assert.h
process.$(OBJEXT): {$(VPATH)}atomic.h
process.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -9920,6 +11408,7 @@ process.$(OBJEXT): {$(VPATH)}id.h
process.$(OBJEXT): {$(VPATH)}id_table.h
process.$(OBJEXT): {$(VPATH)}intern.h
process.$(OBJEXT): {$(VPATH)}internal.h
+process.$(OBJEXT): {$(VPATH)}internal/abi.h
process.$(OBJEXT): {$(VPATH)}internal/anyargs.h
process.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
process.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -9989,6 +11478,15 @@ process.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
process.$(OBJEXT): {$(VPATH)}internal/ctype.h
process.$(OBJEXT): {$(VPATH)}internal/dllexport.h
process.$(OBJEXT): {$(VPATH)}internal/dosish.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+process.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
process.$(OBJEXT): {$(VPATH)}internal/error.h
process.$(OBJEXT): {$(VPATH)}internal/eval.h
process.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -10070,6 +11568,7 @@ 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)}shape.h
process.$(OBJEXT): {$(VPATH)}st.h
process.$(OBJEXT): {$(VPATH)}subst.h
process.$(OBJEXT): {$(VPATH)}thread.h
@@ -10082,8 +11581,10 @@ ractor.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
ractor.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
ractor.$(OBJEXT): $(CCAN_DIR)/list/list.h
ractor.$(OBJEXT): $(CCAN_DIR)/str/str.h
+ractor.$(OBJEXT): $(hdrdir)/ruby.h
ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ractor.$(OBJEXT): $(top_srcdir)/internal/array.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h
ractor.$(OBJEXT): $(top_srcdir)/internal/bits.h
ractor.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -10100,6 +11601,7 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ractor.$(OBJEXT): $(top_srcdir)/internal/string.h
ractor.$(OBJEXT): $(top_srcdir)/internal/struct.h
ractor.$(OBJEXT): $(top_srcdir)/internal/thread.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/variable.h
ractor.$(OBJEXT): $(top_srcdir)/internal/vm.h
ractor.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ractor.$(OBJEXT): {$(VPATH)}assert.h
@@ -10116,7 +11618,6 @@ 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
@@ -10125,6 +11626,7 @@ ractor.$(OBJEXT): {$(VPATH)}id.h
ractor.$(OBJEXT): {$(VPATH)}id_table.h
ractor.$(OBJEXT): {$(VPATH)}intern.h
ractor.$(OBJEXT): {$(VPATH)}internal.h
+ractor.$(OBJEXT): {$(VPATH)}internal/abi.h
ractor.$(OBJEXT): {$(VPATH)}internal/anyargs.h
ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -10194,6 +11696,15 @@ ractor.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
ractor.$(OBJEXT): {$(VPATH)}internal/ctype.h
ractor.$(OBJEXT): {$(VPATH)}internal/dllexport.h
ractor.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+ractor.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
ractor.$(OBJEXT): {$(VPATH)}internal/error.h
ractor.$(OBJEXT): {$(VPATH)}internal/eval.h
ractor.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -10266,16 +11777,17 @@ 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)}mjit.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)}shape.h
ractor.$(OBJEXT): {$(VPATH)}st.h
ractor.$(OBJEXT): {$(VPATH)}subst.h
ractor.$(OBJEXT): {$(VPATH)}thread.h
@@ -10287,20 +11799,19 @@ 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
+ractor.$(OBJEXT): {$(VPATH)}yjit.h
random.$(OBJEXT): $(hdrdir)/ruby/ruby.h
random.$(OBJEXT): $(top_srcdir)/internal/array.h
random.$(OBJEXT): $(top_srcdir)/internal/bignum.h
random.$(OBJEXT): $(top_srcdir)/internal/bits.h
random.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-random.$(OBJEXT): $(top_srcdir)/internal/error.h
random.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+random.$(OBJEXT): $(top_srcdir)/internal/gc.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
@@ -10318,10 +11829,10 @@ 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/abi.h
random.$(OBJEXT): {$(VPATH)}internal/anyargs.h
random.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
random.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -10463,19 +11974,18 @@ 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)}shape.h
random.$(OBJEXT): {$(VPATH)}siphash.c
random.$(OBJEXT): {$(VPATH)}siphash.h
random.$(OBJEXT): {$(VPATH)}st.h
random.$(OBJEXT): {$(VPATH)}subst.h
-range.$(OBJEXT): $(hdrdir)/ruby.h
range.$(OBJEXT): $(hdrdir)/ruby/ruby.h
range.$(OBJEXT): $(top_srcdir)/internal/array.h
+range.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
range.$(OBJEXT): $(top_srcdir)/internal/bignum.h
range.$(OBJEXT): $(top_srcdir)/internal/bits.h
range.$(OBJEXT): $(top_srcdir)/internal/compar.h
@@ -10509,6 +12019,7 @@ range.$(OBJEXT): {$(VPATH)}encoding.h
range.$(OBJEXT): {$(VPATH)}id.h
range.$(OBJEXT): {$(VPATH)}intern.h
range.$(OBJEXT): {$(VPATH)}internal.h
+range.$(OBJEXT): {$(VPATH)}internal/abi.h
range.$(OBJEXT): {$(VPATH)}internal/anyargs.h
range.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
range.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -10578,6 +12089,15 @@ range.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
range.$(OBJEXT): {$(VPATH)}internal/ctype.h
range.$(OBJEXT): {$(VPATH)}internal/dllexport.h
range.$(OBJEXT): {$(VPATH)}internal/dosish.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+range.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
range.$(OBJEXT): {$(VPATH)}internal/error.h
range.$(OBJEXT): {$(VPATH)}internal/eval.h
range.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -10652,9 +12172,9 @@ range.$(OBJEXT): {$(VPATH)}missing.h
range.$(OBJEXT): {$(VPATH)}onigmo.h
range.$(OBJEXT): {$(VPATH)}oniguruma.h
range.$(OBJEXT): {$(VPATH)}range.c
+range.$(OBJEXT): {$(VPATH)}shape.h
range.$(OBJEXT): {$(VPATH)}st.h
range.$(OBJEXT): {$(VPATH)}subst.h
-rational.$(OBJEXT): $(hdrdir)/ruby.h
rational.$(OBJEXT): $(hdrdir)/ruby/ruby.h
rational.$(OBJEXT): $(top_srcdir)/internal/array.h
rational.$(OBJEXT): $(top_srcdir)/internal/bignum.h
@@ -10662,7 +12182,6 @@ 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
@@ -10670,7 +12189,7 @@ 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/variable.h
rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
rational.$(OBJEXT): {$(VPATH)}assert.h
@@ -10684,12 +12203,13 @@ rational.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
rational.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
rational.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
rational.$(OBJEXT): {$(VPATH)}config.h
+rational.$(OBJEXT): {$(VPATH)}constant.h
rational.$(OBJEXT): {$(VPATH)}defines.h
-rational.$(OBJEXT): {$(VPATH)}encoding.h
rational.$(OBJEXT): {$(VPATH)}id.h
rational.$(OBJEXT): {$(VPATH)}id_table.h
rational.$(OBJEXT): {$(VPATH)}intern.h
rational.$(OBJEXT): {$(VPATH)}internal.h
+rational.$(OBJEXT): {$(VPATH)}internal/abi.h
rational.$(OBJEXT): {$(VPATH)}internal/anyargs.h
rational.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -10830,23 +12350,28 @@ 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)}shape.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/bits.h
+re.$(OBJEXT): $(top_srcdir)/internal/class.h
re.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-re.$(OBJEXT): $(top_srcdir)/internal/error.h
+re.$(OBJEXT): $(top_srcdir)/internal/encoding.h
re.$(OBJEXT): $(top_srcdir)/internal/gc.h
re.$(OBJEXT): $(top_srcdir)/internal/hash.h
re.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+re.$(OBJEXT): $(top_srcdir)/internal/object.h
+re.$(OBJEXT): $(top_srcdir)/internal/ractor.h
re.$(OBJEXT): $(top_srcdir)/internal/re.h
+re.$(OBJEXT): $(top_srcdir)/internal/serial.h
re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
re.$(OBJEXT): $(top_srcdir)/internal/string.h
+re.$(OBJEXT): $(top_srcdir)/internal/time.h
re.$(OBJEXT): $(top_srcdir)/internal/variable.h
re.$(OBJEXT): $(top_srcdir)/internal/warnings.h
re.$(OBJEXT): {$(VPATH)}assert.h
@@ -10864,9 +12389,11 @@ re.$(OBJEXT): {$(VPATH)}constant.h
re.$(OBJEXT): {$(VPATH)}defines.h
re.$(OBJEXT): {$(VPATH)}encindex.h
re.$(OBJEXT): {$(VPATH)}encoding.h
+re.$(OBJEXT): {$(VPATH)}hrtime.h
re.$(OBJEXT): {$(VPATH)}id_table.h
re.$(OBJEXT): {$(VPATH)}intern.h
re.$(OBJEXT): {$(VPATH)}internal.h
+re.$(OBJEXT): {$(VPATH)}internal/abi.h
re.$(OBJEXT): {$(VPATH)}internal/anyargs.h
re.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
re.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -10937,6 +12464,15 @@ re.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
re.$(OBJEXT): {$(VPATH)}internal/ctype.h
re.$(OBJEXT): {$(VPATH)}internal/dllexport.h
re.$(OBJEXT): {$(VPATH)}internal/dosish.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+re.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
re.$(OBJEXT): {$(VPATH)}internal/error.h
re.$(OBJEXT): {$(VPATH)}internal/eval.h
re.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -11015,15 +12551,16 @@ re.$(OBJEXT): {$(VPATH)}re.h
re.$(OBJEXT): {$(VPATH)}regenc.h
re.$(OBJEXT): {$(VPATH)}regex.h
re.$(OBJEXT): {$(VPATH)}regint.h
+re.$(OBJEXT): {$(VPATH)}shape.h
re.$(OBJEXT): {$(VPATH)}st.h
re.$(OBJEXT): {$(VPATH)}subst.h
re.$(OBJEXT): {$(VPATH)}util.h
+regcomp.$(OBJEXT): $(hdrdir)/ruby.h
regcomp.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regcomp.$(OBJEXT): {$(VPATH)}assert.h
regcomp.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regcomp.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
regcomp.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-regcomp.$(OBJEXT): {$(VPATH)}backward/2/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
@@ -11032,6 +12569,7 @@ regcomp.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regcomp.$(OBJEXT): {$(VPATH)}config.h
regcomp.$(OBJEXT): {$(VPATH)}defines.h
regcomp.$(OBJEXT): {$(VPATH)}intern.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/abi.h
regcomp.$(OBJEXT): {$(VPATH)}internal/anyargs.h
regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -11179,12 +12717,12 @@ regcomp.$(OBJEXT): {$(VPATH)}regint.h
regcomp.$(OBJEXT): {$(VPATH)}regparse.h
regcomp.$(OBJEXT): {$(VPATH)}st.h
regcomp.$(OBJEXT): {$(VPATH)}subst.h
+regenc.$(OBJEXT): $(hdrdir)/ruby.h
regenc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regenc.$(OBJEXT): {$(VPATH)}assert.h
regenc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regenc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
regenc.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-regenc.$(OBJEXT): {$(VPATH)}backward/2/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
@@ -11193,6 +12731,7 @@ regenc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regenc.$(OBJEXT): {$(VPATH)}config.h
regenc.$(OBJEXT): {$(VPATH)}defines.h
regenc.$(OBJEXT): {$(VPATH)}intern.h
+regenc.$(OBJEXT): {$(VPATH)}internal/abi.h
regenc.$(OBJEXT): {$(VPATH)}internal/anyargs.h
regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -11339,12 +12878,12 @@ regenc.$(OBJEXT): {$(VPATH)}regenc.h
regenc.$(OBJEXT): {$(VPATH)}regint.h
regenc.$(OBJEXT): {$(VPATH)}st.h
regenc.$(OBJEXT): {$(VPATH)}subst.h
+regerror.$(OBJEXT): $(hdrdir)/ruby.h
regerror.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regerror.$(OBJEXT): {$(VPATH)}assert.h
regerror.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regerror.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
regerror.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-regerror.$(OBJEXT): {$(VPATH)}backward/2/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
@@ -11353,6 +12892,7 @@ regerror.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regerror.$(OBJEXT): {$(VPATH)}config.h
regerror.$(OBJEXT): {$(VPATH)}defines.h
regerror.$(OBJEXT): {$(VPATH)}intern.h
+regerror.$(OBJEXT): {$(VPATH)}internal/abi.h
regerror.$(OBJEXT): {$(VPATH)}internal/anyargs.h
regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -11499,12 +13039,12 @@ regerror.$(OBJEXT): {$(VPATH)}regerror.c
regerror.$(OBJEXT): {$(VPATH)}regint.h
regerror.$(OBJEXT): {$(VPATH)}st.h
regerror.$(OBJEXT): {$(VPATH)}subst.h
+regexec.$(OBJEXT): $(hdrdir)/ruby.h
regexec.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regexec.$(OBJEXT): {$(VPATH)}assert.h
regexec.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regexec.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
regexec.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-regexec.$(OBJEXT): {$(VPATH)}backward/2/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
@@ -11513,6 +13053,7 @@ regexec.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regexec.$(OBJEXT): {$(VPATH)}config.h
regexec.$(OBJEXT): {$(VPATH)}defines.h
regexec.$(OBJEXT): {$(VPATH)}intern.h
+regexec.$(OBJEXT): {$(VPATH)}internal/abi.h
regexec.$(OBJEXT): {$(VPATH)}internal/anyargs.h
regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -11659,7 +13200,11 @@ regexec.$(OBJEXT): {$(VPATH)}regexec.c
regexec.$(OBJEXT): {$(VPATH)}regint.h
regexec.$(OBJEXT): {$(VPATH)}st.h
regexec.$(OBJEXT): {$(VPATH)}subst.h
+regparse.$(OBJEXT): $(hdrdir)/ruby.h
regparse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/warnings.h
regparse.$(OBJEXT): {$(VPATH)}assert.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
@@ -11673,6 +13218,7 @@ regparse.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regparse.$(OBJEXT): {$(VPATH)}config.h
regparse.$(OBJEXT): {$(VPATH)}defines.h
regparse.$(OBJEXT): {$(VPATH)}intern.h
+regparse.$(OBJEXT): {$(VPATH)}internal/abi.h
regparse.$(OBJEXT): {$(VPATH)}internal/anyargs.h
regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -11820,12 +13366,12 @@ regparse.$(OBJEXT): {$(VPATH)}regparse.c
regparse.$(OBJEXT): {$(VPATH)}regparse.h
regparse.$(OBJEXT): {$(VPATH)}st.h
regparse.$(OBJEXT): {$(VPATH)}subst.h
+regsyntax.$(OBJEXT): $(hdrdir)/ruby.h
regsyntax.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regsyntax.$(OBJEXT): {$(VPATH)}assert.h
regsyntax.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regsyntax.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
regsyntax.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-regsyntax.$(OBJEXT): {$(VPATH)}backward/2/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
@@ -11834,6 +13380,7 @@ regsyntax.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regsyntax.$(OBJEXT): {$(VPATH)}config.h
regsyntax.$(OBJEXT): {$(VPATH)}defines.h
regsyntax.$(OBJEXT): {$(VPATH)}intern.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/abi.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/anyargs.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -12000,8 +13547,11 @@ ruby.$(OBJEXT): $(hdrdir)/ruby.h
ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ruby.$(OBJEXT): $(hdrdir)/ruby/version.h
ruby.$(OBJEXT): $(top_srcdir)/internal/array.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
ruby.$(OBJEXT): $(top_srcdir)/internal/class.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/cont.h
ruby.$(OBJEXT): $(top_srcdir)/internal/error.h
ruby.$(OBJEXT): $(top_srcdir)/internal/file.h
ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
@@ -12042,6 +13592,7 @@ ruby.$(OBJEXT): {$(VPATH)}id.h
ruby.$(OBJEXT): {$(VPATH)}id_table.h
ruby.$(OBJEXT): {$(VPATH)}intern.h
ruby.$(OBJEXT): {$(VPATH)}internal.h
+ruby.$(OBJEXT): {$(VPATH)}internal/abi.h
ruby.$(OBJEXT): {$(VPATH)}internal/anyargs.h
ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -12111,6 +13662,15 @@ ruby.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
ruby.$(OBJEXT): {$(VPATH)}internal/ctype.h
ruby.$(OBJEXT): {$(VPATH)}internal/dllexport.h
ruby.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+ruby.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
ruby.$(OBJEXT): {$(VPATH)}internal/error.h
ruby.$(OBJEXT): {$(VPATH)}internal/eval.h
ruby.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -12182,6 +13742,7 @@ ruby.$(OBJEXT): {$(VPATH)}internal/variable.h
ruby.$(OBJEXT): {$(VPATH)}internal/warning_push.h
ruby.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
ruby.$(OBJEXT): {$(VPATH)}io.h
+ruby.$(OBJEXT): {$(VPATH)}iseq.h
ruby.$(OBJEXT): {$(VPATH)}method.h
ruby.$(OBJEXT): {$(VPATH)}missing.h
ruby.$(OBJEXT): {$(VPATH)}mjit.h
@@ -12191,6 +13752,7 @@ ruby.$(OBJEXT): {$(VPATH)}oniguruma.h
ruby.$(OBJEXT): {$(VPATH)}ruby.c
ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
ruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ruby.$(OBJEXT): {$(VPATH)}shape.h
ruby.$(OBJEXT): {$(VPATH)}st.h
ruby.$(OBJEXT): {$(VPATH)}subst.h
ruby.$(OBJEXT): {$(VPATH)}thread.h
@@ -12199,18 +13761,21 @@ ruby.$(OBJEXT): {$(VPATH)}thread_native.h
ruby.$(OBJEXT): {$(VPATH)}util.h
ruby.$(OBJEXT): {$(VPATH)}vm_core.h
ruby.$(OBJEXT): {$(VPATH)}vm_opts.h
+ruby.$(OBJEXT): {$(VPATH)}yjit.h
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)/include/ruby/fiber/scheduler.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/array.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/variable.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/vm.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/warnings.h
scheduler.$(OBJEXT): {$(VPATH)}assert.h
@@ -12225,13 +13790,15 @@ scheduler.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
scheduler.$(OBJEXT): {$(VPATH)}config.h
+scheduler.$(OBJEXT): {$(VPATH)}constant.h
scheduler.$(OBJEXT): {$(VPATH)}defines.h
scheduler.$(OBJEXT): {$(VPATH)}encoding.h
scheduler.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
scheduler.$(OBJEXT): {$(VPATH)}id.h
-scheduler.$(OBJEXT): {$(VPATH)}include/ruby/fiber/scheduler.h
+scheduler.$(OBJEXT): {$(VPATH)}id_table.h
scheduler.$(OBJEXT): {$(VPATH)}intern.h
scheduler.$(OBJEXT): {$(VPATH)}internal.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/abi.h
scheduler.$(OBJEXT): {$(VPATH)}internal/anyargs.h
scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -12301,6 +13868,15 @@ scheduler.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
scheduler.$(OBJEXT): {$(VPATH)}internal/ctype.h
scheduler.$(OBJEXT): {$(VPATH)}internal/dllexport.h
scheduler.$(OBJEXT): {$(VPATH)}internal/dosish.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
scheduler.$(OBJEXT): {$(VPATH)}internal/error.h
scheduler.$(OBJEXT): {$(VPATH)}internal/eval.h
scheduler.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -12372,6 +13948,7 @@ scheduler.$(OBJEXT): {$(VPATH)}internal/variable.h
scheduler.$(OBJEXT): {$(VPATH)}internal/warning_push.h
scheduler.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
scheduler.$(OBJEXT): {$(VPATH)}io.h
+scheduler.$(OBJEXT): {$(VPATH)}io/buffer.h
scheduler.$(OBJEXT): {$(VPATH)}method.h
scheduler.$(OBJEXT): {$(VPATH)}missing.h
scheduler.$(OBJEXT): {$(VPATH)}node.h
@@ -12380,6 +13957,7 @@ 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)}shape.h
scheduler.$(OBJEXT): {$(VPATH)}st.h
scheduler.$(OBJEXT): {$(VPATH)}subst.h
scheduler.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -12392,7 +13970,6 @@ 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
@@ -12401,6 +13978,7 @@ setproctitle.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
setproctitle.$(OBJEXT): {$(VPATH)}config.h
setproctitle.$(OBJEXT): {$(VPATH)}defines.h
setproctitle.$(OBJEXT): {$(VPATH)}intern.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/abi.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/anyargs.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -12545,13 +14123,219 @@ setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c
setproctitle.$(OBJEXT): {$(VPATH)}st.h
setproctitle.$(OBJEXT): {$(VPATH)}subst.h
setproctitle.$(OBJEXT): {$(VPATH)}util.h
+shape.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+shape.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+shape.$(OBJEXT): $(CCAN_DIR)/list/list.h
+shape.$(OBJEXT): $(CCAN_DIR)/str/str.h
+shape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+shape.$(OBJEXT): $(top_srcdir)/internal/array.h
+shape.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+shape.$(OBJEXT): $(top_srcdir)/internal/class.h
+shape.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+shape.$(OBJEXT): $(top_srcdir)/internal/gc.h
+shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+shape.$(OBJEXT): $(top_srcdir)/internal/serial.h
+shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+shape.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+shape.$(OBJEXT): $(top_srcdir)/internal/variable.h
+shape.$(OBJEXT): $(top_srcdir)/internal/vm.h
+shape.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+shape.$(OBJEXT): {$(VPATH)}assert.h
+shape.$(OBJEXT): {$(VPATH)}atomic.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+shape.$(OBJEXT): {$(VPATH)}config.h
+shape.$(OBJEXT): {$(VPATH)}constant.h
+shape.$(OBJEXT): {$(VPATH)}debug_counter.h
+shape.$(OBJEXT): {$(VPATH)}defines.h
+shape.$(OBJEXT): {$(VPATH)}encoding.h
+shape.$(OBJEXT): {$(VPATH)}gc.h
+shape.$(OBJEXT): {$(VPATH)}id.h
+shape.$(OBJEXT): {$(VPATH)}id_table.h
+shape.$(OBJEXT): {$(VPATH)}intern.h
+shape.$(OBJEXT): {$(VPATH)}internal.h
+shape.$(OBJEXT): {$(VPATH)}internal/abi.h
+shape.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/assume.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+shape.$(OBJEXT): {$(VPATH)}internal/cast.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+shape.$(OBJEXT): {$(VPATH)}internal/config.h
+shape.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+shape.$(OBJEXT): {$(VPATH)}internal/core.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+shape.$(OBJEXT): {$(VPATH)}internal/ctype.h
+shape.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+shape.$(OBJEXT): {$(VPATH)}internal/dosish.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+shape.$(OBJEXT): {$(VPATH)}internal/error.h
+shape.$(OBJEXT): {$(VPATH)}internal/eval.h
+shape.$(OBJEXT): {$(VPATH)}internal/event.h
+shape.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+shape.$(OBJEXT): {$(VPATH)}internal/gc.h
+shape.$(OBJEXT): {$(VPATH)}internal/glob.h
+shape.$(OBJEXT): {$(VPATH)}internal/globals.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+shape.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+shape.$(OBJEXT): {$(VPATH)}internal/iterator.h
+shape.$(OBJEXT): {$(VPATH)}internal/memory.h
+shape.$(OBJEXT): {$(VPATH)}internal/method.h
+shape.$(OBJEXT): {$(VPATH)}internal/module.h
+shape.$(OBJEXT): {$(VPATH)}internal/newobj.h
+shape.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+shape.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+shape.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+shape.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+shape.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+shape.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+shape.$(OBJEXT): {$(VPATH)}internal/symbol.h
+shape.$(OBJEXT): {$(VPATH)}internal/value.h
+shape.$(OBJEXT): {$(VPATH)}internal/value_type.h
+shape.$(OBJEXT): {$(VPATH)}internal/variable.h
+shape.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+shape.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+shape.$(OBJEXT): {$(VPATH)}method.h
+shape.$(OBJEXT): {$(VPATH)}missing.h
+shape.$(OBJEXT): {$(VPATH)}node.h
+shape.$(OBJEXT): {$(VPATH)}onigmo.h
+shape.$(OBJEXT): {$(VPATH)}oniguruma.h
+shape.$(OBJEXT): {$(VPATH)}ruby_assert.h
+shape.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+shape.$(OBJEXT): {$(VPATH)}shape.c
+shape.$(OBJEXT): {$(VPATH)}shape.h
+shape.$(OBJEXT): {$(VPATH)}st.h
+shape.$(OBJEXT): {$(VPATH)}subst.h
+shape.$(OBJEXT): {$(VPATH)}symbol.h
+shape.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+shape.$(OBJEXT): {$(VPATH)}thread_native.h
+shape.$(OBJEXT): {$(VPATH)}variable.h
+shape.$(OBJEXT): {$(VPATH)}vm_core.h
+shape.$(OBJEXT): {$(VPATH)}vm_debug.h
+shape.$(OBJEXT): {$(VPATH)}vm_opts.h
+shape.$(OBJEXT): {$(VPATH)}vm_sync.h
signal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
signal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
signal.$(OBJEXT): $(CCAN_DIR)/list/list.h
signal.$(OBJEXT): $(CCAN_DIR)/str/str.h
-signal.$(OBJEXT): $(hdrdir)/ruby.h
signal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
signal.$(OBJEXT): $(top_srcdir)/internal/array.h
+signal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
signal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
signal.$(OBJEXT): $(top_srcdir)/internal/eval.h
signal.$(OBJEXT): $(top_srcdir)/internal/gc.h
@@ -12562,6 +14346,7 @@ signal.$(OBJEXT): $(top_srcdir)/internal/signal.h
signal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
signal.$(OBJEXT): $(top_srcdir)/internal/string.h
signal.$(OBJEXT): $(top_srcdir)/internal/thread.h
+signal.$(OBJEXT): $(top_srcdir)/internal/variable.h
signal.$(OBJEXT): $(top_srcdir)/internal/vm.h
signal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
signal.$(OBJEXT): {$(VPATH)}assert.h
@@ -12576,6 +14361,7 @@ signal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
signal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
signal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
signal.$(OBJEXT): {$(VPATH)}config.h
+signal.$(OBJEXT): {$(VPATH)}constant.h
signal.$(OBJEXT): {$(VPATH)}debug_counter.h
signal.$(OBJEXT): {$(VPATH)}defines.h
signal.$(OBJEXT): {$(VPATH)}encoding.h
@@ -12584,6 +14370,7 @@ signal.$(OBJEXT): {$(VPATH)}id.h
signal.$(OBJEXT): {$(VPATH)}id_table.h
signal.$(OBJEXT): {$(VPATH)}intern.h
signal.$(OBJEXT): {$(VPATH)}internal.h
+signal.$(OBJEXT): {$(VPATH)}internal/abi.h
signal.$(OBJEXT): {$(VPATH)}internal/anyargs.h
signal.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -12620,6 +14407,7 @@ signal.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
signal.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
signal.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
signal.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h
signal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
signal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
signal.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
@@ -12653,6 +14441,15 @@ signal.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
signal.$(OBJEXT): {$(VPATH)}internal/ctype.h
signal.$(OBJEXT): {$(VPATH)}internal/dllexport.h
signal.$(OBJEXT): {$(VPATH)}internal/dosish.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+signal.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
signal.$(OBJEXT): {$(VPATH)}internal/error.h
signal.$(OBJEXT): {$(VPATH)}internal/eval.h
signal.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -12732,6 +14529,7 @@ 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)}shape.h
signal.$(OBJEXT): {$(VPATH)}signal.c
signal.$(OBJEXT): {$(VPATH)}st.h
signal.$(OBJEXT): {$(VPATH)}subst.h
@@ -12740,7 +14538,6 @@ 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
@@ -12757,7 +14554,7 @@ 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/variable.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/vm.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/warnings.h
sprintf.$(OBJEXT): {$(VPATH)}assert.h
@@ -12771,12 +14568,14 @@ sprintf.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
sprintf.$(OBJEXT): {$(VPATH)}config.h
+sprintf.$(OBJEXT): {$(VPATH)}constant.h
sprintf.$(OBJEXT): {$(VPATH)}defines.h
sprintf.$(OBJEXT): {$(VPATH)}encoding.h
sprintf.$(OBJEXT): {$(VPATH)}id.h
sprintf.$(OBJEXT): {$(VPATH)}id_table.h
sprintf.$(OBJEXT): {$(VPATH)}intern.h
sprintf.$(OBJEXT): {$(VPATH)}internal.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/abi.h
sprintf.$(OBJEXT): {$(VPATH)}internal/anyargs.h
sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -12847,6 +14646,15 @@ sprintf.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
sprintf.$(OBJEXT): {$(VPATH)}internal/ctype.h
sprintf.$(OBJEXT): {$(VPATH)}internal/dllexport.h
sprintf.$(OBJEXT): {$(VPATH)}internal/dosish.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
sprintf.$(OBJEXT): {$(VPATH)}internal/error.h
sprintf.$(OBJEXT): {$(VPATH)}internal/eval.h
sprintf.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -12922,11 +14730,12 @@ sprintf.$(OBJEXT): {$(VPATH)}onigmo.h
sprintf.$(OBJEXT): {$(VPATH)}oniguruma.h
sprintf.$(OBJEXT): {$(VPATH)}re.h
sprintf.$(OBJEXT): {$(VPATH)}regex.h
+sprintf.$(OBJEXT): {$(VPATH)}shape.h
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c
sprintf.$(OBJEXT): {$(VPATH)}st.h
sprintf.$(OBJEXT): {$(VPATH)}subst.h
+sprintf.$(OBJEXT): {$(VPATH)}util.h
sprintf.$(OBJEXT): {$(VPATH)}vsnprintf.c
-st.$(OBJEXT): $(hdrdir)/ruby.h
st.$(OBJEXT): $(hdrdir)/ruby/ruby.h
st.$(OBJEXT): $(top_srcdir)/internal/bits.h
st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -12948,6 +14757,7 @@ st.$(OBJEXT): {$(VPATH)}config.h
st.$(OBJEXT): {$(VPATH)}defines.h
st.$(OBJEXT): {$(VPATH)}intern.h
st.$(OBJEXT): {$(VPATH)}internal.h
+st.$(OBJEXT): {$(VPATH)}internal/abi.h
st.$(OBJEXT): {$(VPATH)}internal/anyargs.h
st.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
st.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -13088,16 +14898,16 @@ st.$(OBJEXT): {$(VPATH)}internal/variable.h
st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
st.$(OBJEXT): {$(VPATH)}missing.h
+st.$(OBJEXT): {$(VPATH)}ruby_assert.h
st.$(OBJEXT): {$(VPATH)}st.c
st.$(OBJEXT): {$(VPATH)}st.h
st.$(OBJEXT): {$(VPATH)}subst.h
-strftime.$(OBJEXT): $(hdrdir)/ruby.h
strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h
strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/encoding.h
strftime.$(OBJEXT): $(top_srcdir)/internal/serial.h
strftime.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
strftime.$(OBJEXT): $(top_srcdir)/internal/string.h
-strftime.$(OBJEXT): $(top_srcdir)/internal/util.h
strftime.$(OBJEXT): $(top_srcdir)/internal/vm.h
strftime.$(OBJEXT): {$(VPATH)}assert.h
strftime.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -13114,6 +14924,7 @@ strftime.$(OBJEXT): {$(VPATH)}defines.h
strftime.$(OBJEXT): {$(VPATH)}encoding.h
strftime.$(OBJEXT): {$(VPATH)}intern.h
strftime.$(OBJEXT): {$(VPATH)}internal.h
+strftime.$(OBJEXT): {$(VPATH)}internal/abi.h
strftime.$(OBJEXT): {$(VPATH)}internal/anyargs.h
strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -13183,6 +14994,15 @@ strftime.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
strftime.$(OBJEXT): {$(VPATH)}internal/ctype.h
strftime.$(OBJEXT): {$(VPATH)}internal/dllexport.h
strftime.$(OBJEXT): {$(VPATH)}internal/dosish.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+strftime.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
strftime.$(OBJEXT): {$(VPATH)}internal/error.h
strftime.$(OBJEXT): {$(VPATH)}internal/eval.h
strftime.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -13260,9 +15080,10 @@ strftime.$(OBJEXT): {$(VPATH)}st.h
strftime.$(OBJEXT): {$(VPATH)}strftime.c
strftime.$(OBJEXT): {$(VPATH)}subst.h
strftime.$(OBJEXT): {$(VPATH)}timev.h
-string.$(OBJEXT): $(hdrdir)/ruby.h
+strftime.$(OBJEXT): {$(VPATH)}util.h
string.$(OBJEXT): $(hdrdir)/ruby/ruby.h
string.$(OBJEXT): $(top_srcdir)/internal/array.h
+string.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
string.$(OBJEXT): $(top_srcdir)/internal/bignum.h
string.$(OBJEXT): $(top_srcdir)/internal/bits.h
string.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -13281,6 +15102,7 @@ string.$(OBJEXT): $(top_srcdir)/internal/serial.h
string.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
string.$(OBJEXT): $(top_srcdir)/internal/string.h
string.$(OBJEXT): $(top_srcdir)/internal/transcode.h
+string.$(OBJEXT): $(top_srcdir)/internal/variable.h
string.$(OBJEXT): $(top_srcdir)/internal/vm.h
string.$(OBJEXT): $(top_srcdir)/internal/warnings.h
string.$(OBJEXT): {$(VPATH)}assert.h
@@ -13295,7 +15117,7 @@ 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)}constant.h
string.$(OBJEXT): {$(VPATH)}debug_counter.h
string.$(OBJEXT): {$(VPATH)}defines.h
string.$(OBJEXT): {$(VPATH)}encindex.h
@@ -13305,6 +15127,7 @@ string.$(OBJEXT): {$(VPATH)}id.h
string.$(OBJEXT): {$(VPATH)}id_table.h
string.$(OBJEXT): {$(VPATH)}intern.h
string.$(OBJEXT): {$(VPATH)}internal.h
+string.$(OBJEXT): {$(VPATH)}internal/abi.h
string.$(OBJEXT): {$(VPATH)}internal/anyargs.h
string.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
string.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -13341,6 +15164,7 @@ string.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
string.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
string.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
string.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h
string.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
string.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
string.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
@@ -13375,6 +15199,15 @@ string.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
string.$(OBJEXT): {$(VPATH)}internal/ctype.h
string.$(OBJEXT): {$(VPATH)}internal/dllexport.h
string.$(OBJEXT): {$(VPATH)}internal/dosish.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+string.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
string.$(OBJEXT): {$(VPATH)}internal/error.h
string.$(OBJEXT): {$(VPATH)}internal/eval.h
string.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -13446,7 +15279,6 @@ 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
@@ -13454,6 +15286,7 @@ string.$(OBJEXT): {$(VPATH)}probes.h
string.$(OBJEXT): {$(VPATH)}re.h
string.$(OBJEXT): {$(VPATH)}regex.h
string.$(OBJEXT): {$(VPATH)}ruby_assert.h
+string.$(OBJEXT): {$(VPATH)}shape.h
string.$(OBJEXT): {$(VPATH)}st.h
string.$(OBJEXT): {$(VPATH)}string.c
string.$(OBJEXT): {$(VPATH)}subst.h
@@ -13462,6 +15295,7 @@ string.$(OBJEXT): {$(VPATH)}util.h
string.$(OBJEXT): {$(VPATH)}vm_debug.h
string.$(OBJEXT): {$(VPATH)}vm_sync.h
strlcat.$(OBJEXT): {$(VPATH)}config.h
+strlcat.$(OBJEXT): {$(VPATH)}internal/attr/format.h
strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
@@ -13472,9 +15306,11 @@ strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
strlcat.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
strlcat.$(OBJEXT): {$(VPATH)}internal/config.h
strlcat.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+strlcat.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
strlcat.$(OBJEXT): {$(VPATH)}missing.h
strlcat.$(OBJEXT): {$(VPATH)}strlcat.c
strlcpy.$(OBJEXT): {$(VPATH)}config.h
+strlcpy.$(OBJEXT): {$(VPATH)}internal/attr/format.h
strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
@@ -13485,15 +15321,16 @@ strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
strlcpy.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
strlcpy.$(OBJEXT): {$(VPATH)}internal/config.h
strlcpy.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+strlcpy.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
strlcpy.$(OBJEXT): {$(VPATH)}missing.h
strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c
struct.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
struct.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
struct.$(OBJEXT): $(CCAN_DIR)/list/list.h
struct.$(OBJEXT): $(CCAN_DIR)/str/str.h
-struct.$(OBJEXT): $(hdrdir)/ruby.h
struct.$(OBJEXT): $(hdrdir)/ruby/ruby.h
struct.$(OBJEXT): $(top_srcdir)/internal/array.h
+struct.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
struct.$(OBJEXT): $(top_srcdir)/internal/class.h
struct.$(OBJEXT): $(top_srcdir)/internal/compilers.h
struct.$(OBJEXT): $(top_srcdir)/internal/error.h
@@ -13507,6 +15344,7 @@ struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
struct.$(OBJEXT): $(top_srcdir)/internal/string.h
struct.$(OBJEXT): $(top_srcdir)/internal/struct.h
struct.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+struct.$(OBJEXT): $(top_srcdir)/internal/variable.h
struct.$(OBJEXT): $(top_srcdir)/internal/vm.h
struct.$(OBJEXT): $(top_srcdir)/internal/warnings.h
struct.$(OBJEXT): {$(VPATH)}assert.h
@@ -13522,12 +15360,14 @@ struct.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
struct.$(OBJEXT): {$(VPATH)}builtin.h
struct.$(OBJEXT): {$(VPATH)}config.h
+struct.$(OBJEXT): {$(VPATH)}constant.h
struct.$(OBJEXT): {$(VPATH)}defines.h
struct.$(OBJEXT): {$(VPATH)}encoding.h
struct.$(OBJEXT): {$(VPATH)}id.h
struct.$(OBJEXT): {$(VPATH)}id_table.h
struct.$(OBJEXT): {$(VPATH)}intern.h
struct.$(OBJEXT): {$(VPATH)}internal.h
+struct.$(OBJEXT): {$(VPATH)}internal/abi.h
struct.$(OBJEXT): {$(VPATH)}internal/anyargs.h
struct.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -13597,6 +15437,15 @@ struct.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
struct.$(OBJEXT): {$(VPATH)}internal/ctype.h
struct.$(OBJEXT): {$(VPATH)}internal/dllexport.h
struct.$(OBJEXT): {$(VPATH)}internal/dosish.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+struct.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
struct.$(OBJEXT): {$(VPATH)}internal/error.h
struct.$(OBJEXT): {$(VPATH)}internal/eval.h
struct.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -13674,6 +15523,7 @@ 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)}shape.h
struct.$(OBJEXT): {$(VPATH)}st.h
struct.$(OBJEXT): {$(VPATH)}struct.c
struct.$(OBJEXT): {$(VPATH)}subst.h
@@ -13682,7 +15532,6 @@ struct.$(OBJEXT): {$(VPATH)}thread_native.h
struct.$(OBJEXT): {$(VPATH)}transient_heap.h
struct.$(OBJEXT): {$(VPATH)}vm_core.h
struct.$(OBJEXT): {$(VPATH)}vm_opts.h
-symbol.$(OBJEXT): $(hdrdir)/ruby.h
symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h
symbol.$(OBJEXT): $(top_srcdir)/internal/class.h
symbol.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -13694,6 +15543,7 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h
symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
symbol.$(OBJEXT): $(top_srcdir)/internal/string.h
symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/variable.h
symbol.$(OBJEXT): $(top_srcdir)/internal/vm.h
symbol.$(OBJEXT): $(top_srcdir)/internal/warnings.h
symbol.$(OBJEXT): {$(VPATH)}assert.h
@@ -13706,7 +15556,9 @@ symbol.$(OBJEXT): {$(VPATH)}backward/2/limits.h
symbol.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
symbol.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
symbol.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+symbol.$(OBJEXT): {$(VPATH)}builtin.h
symbol.$(OBJEXT): {$(VPATH)}config.h
+symbol.$(OBJEXT): {$(VPATH)}constant.h
symbol.$(OBJEXT): {$(VPATH)}debug_counter.h
symbol.$(OBJEXT): {$(VPATH)}defines.h
symbol.$(OBJEXT): {$(VPATH)}encoding.h
@@ -13717,6 +15569,7 @@ symbol.$(OBJEXT): {$(VPATH)}id_table.c
symbol.$(OBJEXT): {$(VPATH)}id_table.h
symbol.$(OBJEXT): {$(VPATH)}intern.h
symbol.$(OBJEXT): {$(VPATH)}internal.h
+symbol.$(OBJEXT): {$(VPATH)}internal/abi.h
symbol.$(OBJEXT): {$(VPATH)}internal/anyargs.h
symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -13753,6 +15606,7 @@ symbol.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
symbol.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
symbol.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
symbol.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h
symbol.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
symbol.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
symbol.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
@@ -13786,6 +15640,15 @@ symbol.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
symbol.$(OBJEXT): {$(VPATH)}internal/ctype.h
symbol.$(OBJEXT): {$(VPATH)}internal/dllexport.h
symbol.$(OBJEXT): {$(VPATH)}internal/dosish.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+symbol.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
symbol.$(OBJEXT): {$(VPATH)}internal/error.h
symbol.$(OBJEXT): {$(VPATH)}internal/eval.h
symbol.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -13857,16 +15720,18 @@ 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
symbol.$(OBJEXT): {$(VPATH)}probes.h
symbol.$(OBJEXT): {$(VPATH)}ruby_assert.h
+symbol.$(OBJEXT): {$(VPATH)}shape.h
symbol.$(OBJEXT): {$(VPATH)}st.h
symbol.$(OBJEXT): {$(VPATH)}subst.h
symbol.$(OBJEXT): {$(VPATH)}symbol.c
symbol.$(OBJEXT): {$(VPATH)}symbol.h
+symbol.$(OBJEXT): {$(VPATH)}symbol.rb
+symbol.$(OBJEXT): {$(VPATH)}symbol.rbinc
symbol.$(OBJEXT): {$(VPATH)}vm_debug.h
symbol.$(OBJEXT): {$(VPATH)}vm_sync.h
thread.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -13875,8 +15740,8 @@ 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)/include/ruby/fiber/scheduler.h
thread.$(OBJEXT): $(top_srcdir)/internal/array.h
+thread.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
thread.$(OBJEXT): $(top_srcdir)/internal/bits.h
thread.$(OBJEXT): $(top_srcdir)/internal/class.h
thread.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -13894,9 +15759,9 @@ thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
thread.$(OBJEXT): $(top_srcdir)/internal/string.h
thread.$(OBJEXT): $(top_srcdir)/internal/thread.h
thread.$(OBJEXT): $(top_srcdir)/internal/time.h
+thread.$(OBJEXT): $(top_srcdir)/internal/variable.h
thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
thread.$(OBJEXT): {$(VPATH)}assert.h
thread.$(OBJEXT): {$(VPATH)}atomic.h
thread.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -13908,7 +15773,9 @@ thread.$(OBJEXT): {$(VPATH)}backward/2/limits.h
thread.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
thread.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
thread.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+thread.$(OBJEXT): {$(VPATH)}builtin.h
thread.$(OBJEXT): {$(VPATH)}config.h
+thread.$(OBJEXT): {$(VPATH)}constant.h
thread.$(OBJEXT): {$(VPATH)}debug.h
thread.$(OBJEXT): {$(VPATH)}debug_counter.h
thread.$(OBJEXT): {$(VPATH)}defines.h
@@ -13921,6 +15788,7 @@ thread.$(OBJEXT): {$(VPATH)}id.h
thread.$(OBJEXT): {$(VPATH)}id_table.h
thread.$(OBJEXT): {$(VPATH)}intern.h
thread.$(OBJEXT): {$(VPATH)}internal.h
+thread.$(OBJEXT): {$(VPATH)}internal/abi.h
thread.$(OBJEXT): {$(VPATH)}internal/anyargs.h
thread.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -13990,6 +15858,15 @@ thread.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
thread.$(OBJEXT): {$(VPATH)}internal/ctype.h
thread.$(OBJEXT): {$(VPATH)}internal/dllexport.h
thread.$(OBJEXT): {$(VPATH)}internal/dosish.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+thread.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
thread.$(OBJEXT): {$(VPATH)}internal/error.h
thread.$(OBJEXT): {$(VPATH)}internal/eval.h
thread.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -14072,6 +15949,7 @@ 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)}shape.h
thread.$(OBJEXT): {$(VPATH)}st.h
thread.$(OBJEXT): {$(VPATH)}subst.h
thread.$(OBJEXT): {$(VPATH)}thread.c
@@ -14080,20 +15958,22 @@ thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).c
thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
thread.$(OBJEXT): {$(VPATH)}thread_native.h
thread.$(OBJEXT): {$(VPATH)}thread_sync.c
+thread.$(OBJEXT): {$(VPATH)}thread_sync.rbinc
thread.$(OBJEXT): {$(VPATH)}timev.h
thread.$(OBJEXT): {$(VPATH)}vm_core.h
thread.$(OBJEXT): {$(VPATH)}vm_debug.h
thread.$(OBJEXT): {$(VPATH)}vm_opts.h
thread.$(OBJEXT): {$(VPATH)}vm_sync.h
-time.$(OBJEXT): $(hdrdir)/ruby.h
time.$(OBJEXT): $(hdrdir)/ruby/ruby.h
time.$(OBJEXT): $(top_srcdir)/internal/array.h
+time.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
time.$(OBJEXT): $(top_srcdir)/internal/bignum.h
time.$(OBJEXT): $(top_srcdir)/internal/bits.h
time.$(OBJEXT): $(top_srcdir)/internal/compar.h
time.$(OBJEXT): $(top_srcdir)/internal/compilers.h
time.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
time.$(OBJEXT): $(top_srcdir)/internal/gc.h
+time.$(OBJEXT): $(top_srcdir)/internal/hash.h
time.$(OBJEXT): $(top_srcdir)/internal/numeric.h
time.$(OBJEXT): $(top_srcdir)/internal/rational.h
time.$(OBJEXT): $(top_srcdir)/internal/serial.h
@@ -14122,6 +16002,7 @@ time.$(OBJEXT): {$(VPATH)}id.h
time.$(OBJEXT): {$(VPATH)}id_table.h
time.$(OBJEXT): {$(VPATH)}intern.h
time.$(OBJEXT): {$(VPATH)}internal.h
+time.$(OBJEXT): {$(VPATH)}internal/abi.h
time.$(OBJEXT): {$(VPATH)}internal/anyargs.h
time.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
time.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -14191,6 +16072,15 @@ time.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
time.$(OBJEXT): {$(VPATH)}internal/ctype.h
time.$(OBJEXT): {$(VPATH)}internal/dllexport.h
time.$(OBJEXT): {$(VPATH)}internal/dosish.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+time.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
time.$(OBJEXT): {$(VPATH)}internal/error.h
time.$(OBJEXT): {$(VPATH)}internal/eval.h
time.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -14265,12 +16155,12 @@ time.$(OBJEXT): {$(VPATH)}missing.h
time.$(OBJEXT): {$(VPATH)}onigmo.h
time.$(OBJEXT): {$(VPATH)}oniguruma.h
time.$(OBJEXT): {$(VPATH)}ruby_assert.h
+time.$(OBJEXT): {$(VPATH)}shape.h
time.$(OBJEXT): {$(VPATH)}st.h
time.$(OBJEXT): {$(VPATH)}subst.h
time.$(OBJEXT): {$(VPATH)}time.c
time.$(OBJEXT): {$(VPATH)}timev.h
time.$(OBJEXT): {$(VPATH)}timev.rbinc
-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
@@ -14282,6 +16172,7 @@ transcode.$(OBJEXT): $(top_srcdir)/internal/serial.h
transcode.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
transcode.$(OBJEXT): $(top_srcdir)/internal/string.h
transcode.$(OBJEXT): $(top_srcdir)/internal/transcode.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/variable.h
transcode.$(OBJEXT): $(top_srcdir)/internal/warnings.h
transcode.$(OBJEXT): {$(VPATH)}assert.h
transcode.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -14294,12 +16185,14 @@ transcode.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
transcode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
transcode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
transcode.$(OBJEXT): {$(VPATH)}config.h
+transcode.$(OBJEXT): {$(VPATH)}constant.h
transcode.$(OBJEXT): {$(VPATH)}defines.h
transcode.$(OBJEXT): {$(VPATH)}encoding.h
transcode.$(OBJEXT): {$(VPATH)}id.h
transcode.$(OBJEXT): {$(VPATH)}id_table.h
transcode.$(OBJEXT): {$(VPATH)}intern.h
transcode.$(OBJEXT): {$(VPATH)}internal.h
+transcode.$(OBJEXT): {$(VPATH)}internal/abi.h
transcode.$(OBJEXT): {$(VPATH)}internal/anyargs.h
transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -14369,6 +16262,15 @@ transcode.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
transcode.$(OBJEXT): {$(VPATH)}internal/ctype.h
transcode.$(OBJEXT): {$(VPATH)}internal/dllexport.h
transcode.$(OBJEXT): {$(VPATH)}internal/dosish.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+transcode.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
transcode.$(OBJEXT): {$(VPATH)}internal/error.h
transcode.$(OBJEXT): {$(VPATH)}internal/eval.h
transcode.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -14442,30 +16344,22 @@ transcode.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
transcode.$(OBJEXT): {$(VPATH)}missing.h
transcode.$(OBJEXT): {$(VPATH)}onigmo.h
transcode.$(OBJEXT): {$(VPATH)}oniguruma.h
+transcode.$(OBJEXT): {$(VPATH)}shape.h
transcode.$(OBJEXT): {$(VPATH)}st.h
transcode.$(OBJEXT): {$(VPATH)}subst.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c
transcode.$(OBJEXT): {$(VPATH)}transcode_data.h
-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
@@ -14481,10 +16375,10 @@ 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/abi.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/anyargs.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -14624,22 +16518,15 @@ 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)}shape.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
@@ -14661,6 +16548,7 @@ util.$(OBJEXT): {$(VPATH)}defines.h
util.$(OBJEXT): {$(VPATH)}dtoa.c
util.$(OBJEXT): {$(VPATH)}intern.h
util.$(OBJEXT): {$(VPATH)}internal.h
+util.$(OBJEXT): {$(VPATH)}internal/abi.h
util.$(OBJEXT): {$(VPATH)}internal/anyargs.h
util.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
util.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -14810,9 +16698,9 @@ variable.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
variable.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
variable.$(OBJEXT): $(CCAN_DIR)/list/list.h
variable.$(OBJEXT): $(CCAN_DIR)/str/str.h
-variable.$(OBJEXT): $(hdrdir)/ruby.h
variable.$(OBJEXT): $(hdrdir)/ruby/ruby.h
variable.$(OBJEXT): $(top_srcdir)/internal/array.h
+variable.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
variable.$(OBJEXT): $(top_srcdir)/internal/class.h
variable.$(OBJEXT): $(top_srcdir)/internal/compilers.h
variable.$(OBJEXT): $(top_srcdir)/internal/error.h
@@ -14850,6 +16738,7 @@ variable.$(OBJEXT): {$(VPATH)}id.h
variable.$(OBJEXT): {$(VPATH)}id_table.h
variable.$(OBJEXT): {$(VPATH)}intern.h
variable.$(OBJEXT): {$(VPATH)}internal.h
+variable.$(OBJEXT): {$(VPATH)}internal/abi.h
variable.$(OBJEXT): {$(VPATH)}internal/anyargs.h
variable.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -14919,6 +16808,15 @@ variable.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
variable.$(OBJEXT): {$(VPATH)}internal/ctype.h
variable.$(OBJEXT): {$(VPATH)}internal/dllexport.h
variable.$(OBJEXT): {$(VPATH)}internal/dosish.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+variable.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
variable.$(OBJEXT): {$(VPATH)}internal/error.h
variable.$(OBJEXT): {$(VPATH)}internal/eval.h
variable.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -14998,6 +16896,7 @@ 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)}shape.h
variable.$(OBJEXT): {$(VPATH)}st.h
variable.$(OBJEXT): {$(VPATH)}subst.h
variable.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -15018,14 +16917,16 @@ version.$(OBJEXT): $(hdrdir)/ruby.h
version.$(OBJEXT): $(hdrdir)/ruby/ruby.h
version.$(OBJEXT): $(hdrdir)/ruby/version.h
version.$(OBJEXT): $(top_srcdir)/internal/array.h
+version.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
version.$(OBJEXT): $(top_srcdir)/internal/compilers.h
version.$(OBJEXT): $(top_srcdir)/internal/gc.h
version.$(OBJEXT): $(top_srcdir)/internal/imemo.h
version.$(OBJEXT): $(top_srcdir)/internal/serial.h
version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+version.$(OBJEXT): $(top_srcdir)/internal/variable.h
version.$(OBJEXT): $(top_srcdir)/internal/vm.h
version.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-version.$(OBJEXT): $(top_srcdir)/revision.h
version.$(OBJEXT): $(top_srcdir)/version.h
version.$(OBJEXT): {$(VPATH)}assert.h
version.$(OBJEXT): {$(VPATH)}atomic.h
@@ -15039,11 +16940,14 @@ version.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
version.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
version.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
version.$(OBJEXT): {$(VPATH)}config.h
+version.$(OBJEXT): {$(VPATH)}constant.h
version.$(OBJEXT): {$(VPATH)}debug_counter.h
version.$(OBJEXT): {$(VPATH)}defines.h
version.$(OBJEXT): {$(VPATH)}id.h
+version.$(OBJEXT): {$(VPATH)}id_table.h
version.$(OBJEXT): {$(VPATH)}intern.h
version.$(OBJEXT): {$(VPATH)}internal.h
+version.$(OBJEXT): {$(VPATH)}internal/abi.h
version.$(OBJEXT): {$(VPATH)}internal/anyargs.h
version.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
version.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -15187,8 +17091,10 @@ version.$(OBJEXT): {$(VPATH)}method.h
version.$(OBJEXT): {$(VPATH)}missing.h
version.$(OBJEXT): {$(VPATH)}mjit.h
version.$(OBJEXT): {$(VPATH)}node.h
+version.$(OBJEXT): {$(VPATH)}revision.h
version.$(OBJEXT): {$(VPATH)}ruby_assert.h
version.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+version.$(OBJEXT): {$(VPATH)}shape.h
version.$(OBJEXT): {$(VPATH)}st.h
version.$(OBJEXT): {$(VPATH)}subst.h
version.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -15196,6 +17102,7 @@ version.$(OBJEXT): {$(VPATH)}thread_native.h
version.$(OBJEXT): {$(VPATH)}version.c
version.$(OBJEXT): {$(VPATH)}vm_core.h
version.$(OBJEXT): {$(VPATH)}vm_opts.h
+version.$(OBJEXT): {$(VPATH)}yjit.h
vm.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -15203,6 +17110,7 @@ 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/basic_operators.h
vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h
vm.$(OBJEXT): $(top_srcdir)/internal/bits.h
vm.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -15227,6 +17135,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
vm.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm.$(OBJEXT): $(top_srcdir)/internal/string.h
+vm.$(OBJEXT): $(top_srcdir)/internal/struct.h
vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h
vm.$(OBJEXT): $(top_srcdir)/internal/thread.h
vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -15259,6 +17168,7 @@ vm.$(OBJEXT): {$(VPATH)}insns.inc
vm.$(OBJEXT): {$(VPATH)}insns_info.inc
vm.$(OBJEXT): {$(VPATH)}intern.h
vm.$(OBJEXT): {$(VPATH)}internal.h
+vm.$(OBJEXT): {$(VPATH)}internal/abi.h
vm.$(OBJEXT): {$(VPATH)}internal/anyargs.h
vm.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -15328,6 +17238,15 @@ vm.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
vm.$(OBJEXT): {$(VPATH)}internal/ctype.h
vm.$(OBJEXT): {$(VPATH)}internal/dllexport.h
vm.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
vm.$(OBJEXT): {$(VPATH)}internal/error.h
vm.$(OBJEXT): {$(VPATH)}internal/eval.h
vm.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -15412,6 +17331,7 @@ 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)}shape.h
vm.$(OBJEXT): {$(VPATH)}st.h
vm.$(OBJEXT): {$(VPATH)}subst.h
vm.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -15434,13 +17354,14 @@ vm.$(OBJEXT): {$(VPATH)}vm_method.c
vm.$(OBJEXT): {$(VPATH)}vm_opts.h
vm.$(OBJEXT): {$(VPATH)}vm_sync.h
vm.$(OBJEXT): {$(VPATH)}vmtc.inc
+vm.$(OBJEXT): {$(VPATH)}yjit.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/str/str.h
-vm_backtrace.$(OBJEXT): $(hdrdir)/ruby.h
vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h
@@ -15448,6 +17369,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h
@@ -15462,13 +17384,16 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_backtrace.$(OBJEXT): {$(VPATH)}config.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}constant.h
vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h
vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h
vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h
vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h
vm_backtrace.$(OBJEXT): {$(VPATH)}id.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}id_table.h
vm_backtrace.$(OBJEXT): {$(VPATH)}intern.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/abi.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/anyargs.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -15538,6 +17463,15 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/ctype.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/dllexport.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/error.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/eval.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -15616,6 +17550,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}shape.h
vm_backtrace.$(OBJEXT): {$(VPATH)}st.h
vm_backtrace.$(OBJEXT): {$(VPATH)}subst.h
vm_backtrace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -15627,9 +17562,9 @@ vm_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
-vm_dump.$(OBJEXT): $(hdrdir)/ruby.h
vm_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
@@ -15658,6 +17593,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}id.h
vm_dump.$(OBJEXT): {$(VPATH)}id_table.h
vm_dump.$(OBJEXT): {$(VPATH)}intern.h
vm_dump.$(OBJEXT): {$(VPATH)}internal.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/abi.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/anyargs.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -15806,6 +17742,7 @@ 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)}shape.h
vm_dump.$(OBJEXT): {$(VPATH)}st.h
vm_dump.$(OBJEXT): {$(VPATH)}subst.h
vm_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -15818,17 +17755,17 @@ 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/basic_operators.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-vm_sync.$(OBJEXT): {$(VPATH)}addr2line.h
vm_sync.$(OBJEXT): {$(VPATH)}assert.h
vm_sync.$(OBJEXT): {$(VPATH)}atomic.h
vm_sync.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -15849,6 +17786,7 @@ vm_sync.$(OBJEXT): {$(VPATH)}id.h
vm_sync.$(OBJEXT): {$(VPATH)}id_table.h
vm_sync.$(OBJEXT): {$(VPATH)}intern.h
vm_sync.$(OBJEXT): {$(VPATH)}internal.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/abi.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/anyargs.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -15866,7 +17804,6 @@ 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
@@ -15901,7 +17838,6 @@ 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
@@ -15935,7 +17871,6 @@ 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
@@ -15981,7 +17916,6 @@ 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
@@ -15990,19 +17924,16 @@ vm_sync.$(OBJEXT): {$(VPATH)}internal/symbol.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/value.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/value_type.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/variable.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/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)}shape.h
vm_sync.$(OBJEXT): {$(VPATH)}st.h
vm_sync.$(OBJEXT): {$(VPATH)}subst.h
vm_sync.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -16019,6 +17950,7 @@ vm_trace.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
@@ -16026,6 +17958,7 @@ 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/variable.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_trace.$(OBJEXT): {$(VPATH)}assert.h
@@ -16041,14 +17974,17 @@ vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_trace.$(OBJEXT): {$(VPATH)}builtin.h
vm_trace.$(OBJEXT): {$(VPATH)}config.h
+vm_trace.$(OBJEXT): {$(VPATH)}constant.h
vm_trace.$(OBJEXT): {$(VPATH)}debug.h
vm_trace.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_trace.$(OBJEXT): {$(VPATH)}defines.h
vm_trace.$(OBJEXT): {$(VPATH)}encoding.h
vm_trace.$(OBJEXT): {$(VPATH)}eval_intern.h
vm_trace.$(OBJEXT): {$(VPATH)}id.h
+vm_trace.$(OBJEXT): {$(VPATH)}id_table.h
vm_trace.$(OBJEXT): {$(VPATH)}intern.h
vm_trace.$(OBJEXT): {$(VPATH)}internal.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/abi.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/anyargs.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
@@ -16118,6 +18054,15 @@ vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/ctype.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/dllexport.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/error.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/eval.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -16198,6 +18143,7 @@ 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)}shape.h
vm_trace.$(OBJEXT): {$(VPATH)}st.h
vm_trace.$(OBJEXT): {$(VPATH)}subst.h
vm_trace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -16206,4 +18152,227 @@ vm_trace.$(OBJEXT): {$(VPATH)}trace_point.rbinc
vm_trace.$(OBJEXT): {$(VPATH)}vm_core.h
vm_trace.$(OBJEXT): {$(VPATH)}vm_opts.h
vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c
+vm_trace.$(OBJEXT): {$(VPATH)}yjit.h
+yjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+yjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+yjit.$(OBJEXT): $(CCAN_DIR)/list/list.h
+yjit.$(OBJEXT): $(CCAN_DIR)/str/str.h
+yjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/array.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/class.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/string.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+yjit.$(OBJEXT): {$(VPATH)}assert.h
+yjit.$(OBJEXT): {$(VPATH)}atomic.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+yjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+yjit.$(OBJEXT): {$(VPATH)}builtin.h
+yjit.$(OBJEXT): {$(VPATH)}config.h
+yjit.$(OBJEXT): {$(VPATH)}constant.h
+yjit.$(OBJEXT): {$(VPATH)}debug.h
+yjit.$(OBJEXT): {$(VPATH)}debug_counter.h
+yjit.$(OBJEXT): {$(VPATH)}defines.h
+yjit.$(OBJEXT): {$(VPATH)}encoding.h
+yjit.$(OBJEXT): {$(VPATH)}gc.h
+yjit.$(OBJEXT): {$(VPATH)}id.h
+yjit.$(OBJEXT): {$(VPATH)}id_table.h
+yjit.$(OBJEXT): {$(VPATH)}insns.def
+yjit.$(OBJEXT): {$(VPATH)}insns.inc
+yjit.$(OBJEXT): {$(VPATH)}insns_info.inc
+yjit.$(OBJEXT): {$(VPATH)}intern.h
+yjit.$(OBJEXT): {$(VPATH)}internal.h
+yjit.$(OBJEXT): {$(VPATH)}internal/abi.h
+yjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+yjit.$(OBJEXT): {$(VPATH)}internal/assume.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+yjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+yjit.$(OBJEXT): {$(VPATH)}internal/cast.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+yjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+yjit.$(OBJEXT): {$(VPATH)}internal/config.h
+yjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+yjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+yjit.$(OBJEXT): {$(VPATH)}internal/ctype.h
+yjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+yjit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+yjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+yjit.$(OBJEXT): {$(VPATH)}internal/error.h
+yjit.$(OBJEXT): {$(VPATH)}internal/eval.h
+yjit.$(OBJEXT): {$(VPATH)}internal/event.h
+yjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+yjit.$(OBJEXT): {$(VPATH)}internal/gc.h
+yjit.$(OBJEXT): {$(VPATH)}internal/glob.h
+yjit.$(OBJEXT): {$(VPATH)}internal/globals.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+yjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+yjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+yjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+yjit.$(OBJEXT): {$(VPATH)}internal/iterator.h
+yjit.$(OBJEXT): {$(VPATH)}internal/memory.h
+yjit.$(OBJEXT): {$(VPATH)}internal/method.h
+yjit.$(OBJEXT): {$(VPATH)}internal/module.h
+yjit.$(OBJEXT): {$(VPATH)}internal/newobj.h
+yjit.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+yjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+yjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+yjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+yjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+yjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+yjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
+yjit.$(OBJEXT): {$(VPATH)}internal/value.h
+yjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
+yjit.$(OBJEXT): {$(VPATH)}internal/variable.h
+yjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+yjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+yjit.$(OBJEXT): {$(VPATH)}iseq.h
+yjit.$(OBJEXT): {$(VPATH)}method.h
+yjit.$(OBJEXT): {$(VPATH)}missing.h
+yjit.$(OBJEXT): {$(VPATH)}node.h
+yjit.$(OBJEXT): {$(VPATH)}onigmo.h
+yjit.$(OBJEXT): {$(VPATH)}oniguruma.h
+yjit.$(OBJEXT): {$(VPATH)}probes.dmyh
+yjit.$(OBJEXT): {$(VPATH)}probes.h
+yjit.$(OBJEXT): {$(VPATH)}probes_helper.h
+yjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
+yjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+yjit.$(OBJEXT): {$(VPATH)}shape.h
+yjit.$(OBJEXT): {$(VPATH)}st.h
+yjit.$(OBJEXT): {$(VPATH)}subst.h
+yjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+yjit.$(OBJEXT): {$(VPATH)}thread_native.h
+yjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+yjit.$(OBJEXT): {$(VPATH)}vm_core.h
+yjit.$(OBJEXT): {$(VPATH)}vm_debug.h
+yjit.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
+yjit.$(OBJEXT): {$(VPATH)}vm_opts.h
+yjit.$(OBJEXT): {$(VPATH)}vm_sync.h
+yjit.$(OBJEXT): {$(VPATH)}yjit.c
+yjit.$(OBJEXT): {$(VPATH)}yjit.h
+yjit.$(OBJEXT): {$(VPATH)}yjit.rbinc
# AUTOGENERATED DEPENDENCIES END
diff --git a/compar.c b/compar.c
index 7974017e2b..040f77975e 100644
--- a/compar.c
+++ b/compar.c
@@ -30,13 +30,13 @@ rb_cmperr(VALUE x, VALUE y)
VALUE classname;
if (SPECIAL_CONST_P(y) || BUILTIN_TYPE(y) == T_FLOAT) {
- classname = rb_inspect(y);
+ classname = rb_inspect(y);
}
else {
- classname = rb_obj_class(y);
+ classname = rb_obj_class(y);
}
rb_raise(rb_eArgError, "comparison of %"PRIsVALUE" with %"PRIsVALUE" failed",
- rb_obj_class(x), classname);
+ rb_obj_class(x), classname);
}
static VALUE
@@ -50,12 +50,12 @@ VALUE
rb_invcmp(VALUE x, VALUE y)
{
VALUE invcmp = rb_exec_recursive(invcmp_recursive, x, y);
- if (invcmp == Qundef || NIL_P(invcmp)) {
- return Qnil;
+ if (NIL_OR_UNDEF_P(invcmp)) {
+ return Qnil;
}
else {
- int result = -rb_cmpint(invcmp, x, y);
- return INT2FIX(result);
+ int result = -rb_cmpint(invcmp, x, y);
+ return INT2FIX(result);
}
}
@@ -84,8 +84,7 @@ cmp_equal(VALUE x, VALUE y)
c = rb_exec_recursive_paired_outer(cmp_eq_recursive, x, y, y);
if (NIL_P(c)) return Qfalse;
- if (rb_cmpint(c, x, y) == 0) return Qtrue;
- return Qfalse;
+ return RBOOL(rb_cmpint(c, x, y) == 0);
}
static int
@@ -168,9 +167,7 @@ cmp_le(VALUE x, VALUE y)
static VALUE
cmp_between(VALUE x, VALUE min, VALUE max)
{
- if (cmpint(x, min) < 0) return Qfalse;
- if (cmpint(x, max) > 0) return Qfalse;
- return Qtrue;
+ return RBOOL((cmpint(x, min) >= 0 && cmpint(x, max) <= 0));
}
/*
@@ -232,7 +229,7 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
}
}
if (!NIL_P(min) && !NIL_P(max) && cmpint(min, max) > 0) {
- rb_raise(rb_eArgError, "min argument must be smaller than max argument");
+ rb_raise(rb_eArgError, "min argument must be smaller than max argument");
}
if (!NIL_P(min)) {
@@ -289,18 +286,18 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
*
* \Module \Comparable provides these methods, all of which use method <tt><=></tt>:
*
- * - {<}[#method-i-3C]:: Returns whether +self+ is less than the given object.
- * - {<=}[#method-i-3C-3D]:: Returns whether +self+ is less than or equal to
- * the given object.
- * - {==}[#method-i-3D-3D]:: Returns whether +self+ is equal to the given object.
- * - {>}[#method-i-3E]:: Returns whether +self+ is greater than or equal to
- * the given object.
- * - {>=}[#method-i-3E-3D]:: Returns whether +self+ is greater than the given object.
- * - #between? Returns +true+ if +self+ is between two given objects.
- * - #clamp:: For given objects +min+ and +max+, or range <tt>(min..max)</tt>, returns:
+ * - #<: Returns whether +self+ is less than the given object.
+ * - #<=: Returns whether +self+ is less than or equal to the given object.
+ * - #==: Returns whether +self+ is equal to the given object.
+ * - #>: Returns whether +self+ is greater than or equal to the given object.
+ * - #>=: Returns whether +self+ is greater than the given object.
+ * - #between?: Returns +true+ if +self+ is between two given objects.
+ * - #clamp: For given objects +min+ and +max+, or range <tt>(min..max)</tt>, returns:
+ *
* - +min+ if <tt>(self <=> min) < 0</tt>.
* - +max+ if <tt>(self <=> max) > 0</tt>.
* - +self+ otherwise.
+ *
*/
void
diff --git a/compile.c b/compile.c
index 6695a0293b..0452305923 100644
--- a/compile.c
+++ b/compile.c
@@ -52,10 +52,10 @@
typedef struct iseq_link_element {
enum {
- ISEQ_ELEMENT_ANCHOR,
- ISEQ_ELEMENT_LABEL,
- ISEQ_ELEMENT_INSN,
- ISEQ_ELEMENT_ADJUST,
+ ISEQ_ELEMENT_ANCHOR,
+ ISEQ_ELEMENT_LABEL,
+ ISEQ_ELEMENT_INSN,
+ ISEQ_ELEMENT_ADJUST,
ISEQ_ELEMENT_TRACE,
} type;
struct iseq_link_element *next;
@@ -93,9 +93,9 @@ typedef struct iseq_insn_data {
int sc_state;
VALUE *operands;
struct {
- int line_no;
+ int line_no;
int node_id;
- rb_event_flag_t events;
+ rb_event_flag_t events;
} insn_info;
} INSN;
@@ -307,13 +307,13 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NOD
((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
VALUE _e = rb_ary_new3(5, (type), \
- (VALUE)(ls) | 1, (VALUE)(le) | 1, \
- (VALUE)(iseqv), (VALUE)(lc) | 1); \
+ (VALUE)(ls) | 1, (VALUE)(le) | 1, \
+ (VALUE)(iseqv), (VALUE)(lc) | 1); \
LABEL_UNREMOVABLE(ls); \
LABEL_REF(le); \
LABEL_REF(lc); \
if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) \
- RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_tmp_new(3)); \
+ RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, rb_ary_hidden_new(3)); \
rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
} while (0)
@@ -353,9 +353,9 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NOD
/* error */
#if CPDEBUG > 0
-NORETURN(static void append_compile_error(const rb_iseq_t *iseq, int line, const char *fmt, ...));
+RBIMPL_ATTR_NORETURN()
#endif
-
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4)
static void
append_compile_error(const rb_iseq_t *iseq, int line, const char *fmt, ...)
{
@@ -368,11 +368,11 @@ append_compile_error(const rb_iseq_t *iseq, int line, const char *fmt, ...)
err = rb_syntax_error_append(err, file, line, -1, NULL, fmt, args);
va_end(args);
if (NIL_P(err_info)) {
- RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err);
- rb_set_errinfo(err);
+ RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err);
+ rb_set_errinfo(err);
}
else if (!err_info) {
- RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, Qtrue);
+ RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, Qtrue);
}
if (compile_debug) {
if (SPECIAL_CONST_P(err)) err = rb_eSyntaxError;
@@ -402,17 +402,17 @@ do { \
const NODE *error_node = (node); \
enum node_type error_type = nd_type(error_node); \
if (error_type != (ndtype)) { \
- COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
- prefix ": " #ndtype " is expected, but %s", \
- ruby_node_name(error_type)); \
- return errval; \
+ COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
+ prefix ": " #ndtype " is expected, but %s", \
+ ruby_node_name(error_type)); \
+ return errval; \
} \
} while (0)
#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
do { \
COMPILE_ERROR(ERROR_ARGS_AT(parent) \
- prefix ": must be " #ndtype ", but 0"); \
+ prefix ": must be " #ndtype ", but 0"); \
return errval; \
} while (0)
@@ -420,7 +420,7 @@ do { \
do { \
const NODE *error_node = (node); \
COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
- ruby_node_name(nd_type(error_node))); \
+ ruby_node_name(nd_type(error_node))); \
return errval; \
} while (0)
@@ -482,7 +482,7 @@ static int iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
-static int iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl);
+static int iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl);
static int iseq_set_exception_local_table(rb_iseq_t *iseq);
static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, const NODE *const node);
@@ -510,19 +510,19 @@ verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *const anchor)
list = anchor->anchor.next;
plist = &anchor->anchor;
while (list) {
- if (plist != list->prev) {
- flag += 1;
- }
- plist = list;
- list = list->next;
+ if (plist != list->prev) {
+ flag += 1;
+ }
+ plist = list;
+ list = list->next;
}
if (anchor->last != plist && anchor->last != 0) {
- flag |= 0x70000;
+ flag |= 0x70000;
}
if (flag != 0) {
- rb_bug("list verify error: %08x (%s)", flag, info);
+ rb_bug("list verify error: %08x (%s)", flag, info);
}
#endif
}
@@ -534,11 +534,9 @@ 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) {
+ while (i < ISEQ_BODY(iseq)->iseq_size) {
VALUE insn = original[i];
const char *types = insn_op_types(insn);
@@ -556,8 +554,8 @@ verify_call_cache(rb_iseq_t *iseq)
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];
+ for (unsigned int i=0; i<ISEQ_BODY(iseq)->ci_size; i++) {
+ struct rb_call_data *cd = &ISEQ_BODY(iseq)->call_data[i];
const struct rb_callinfo *ci = cd->ci;
const struct rb_callcache *cc = cd->cc;
if (cc != NULL && cc != vm_cc_empty()) {
@@ -629,7 +627,7 @@ decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type)
VALUE branches;
if (NIL_P(branch_base)) {
- branch_base = rb_ary_tmp_new(6);
+ branch_base = rb_ary_hidden_new(6);
rb_hash_aset(structure, key, branch_base);
rb_ary_push(branch_base, ID2SYM(rb_intern(type)));
rb_ary_push(branch_base, INT2FIX(first_lineno));
@@ -677,7 +675,7 @@ add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *n
long counter_idx;
if (NIL_P(branch)) {
- branch = rb_ary_tmp_new(6);
+ branch = rb_ary_hidden_new(6);
rb_hash_aset(branches, key, branch);
rb_ary_push(branch, ID2SYM(rb_intern(type)));
rb_ary_push(branch, INT2FIX(first_lineno));
@@ -707,11 +705,11 @@ validate_label(st_data_t name, st_data_t label, st_data_t arg)
rb_iseq_t *iseq = (rb_iseq_t *)arg;
LABEL *lobj = (LABEL *)label;
if (!lobj->link.next) {
- do {
- COMPILE_ERROR(iseq, lobj->position,
- "%"PRIsVALUE": undefined label",
- rb_sym2str((VALUE)name));
- } while (0);
+ do {
+ COMPILE_ERROR(iseq, lobj->position,
+ "%"PRIsVALUE": undefined label",
+ rb_sym2str((VALUE)name));
+ } while (0);
}
return ST_CONTINUE;
}
@@ -750,106 +748,108 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
if (node == 0) {
NO_CHECK(COMPILE(ret, "nil", node));
- iseq_set_local_table(iseq, 0);
+ iseq_set_local_table(iseq, 0);
}
/* assume node is T_NODE */
- else if (nd_type(node) == NODE_SCOPE) {
- /* iseq type of top, method, class, block */
- iseq_set_local_table(iseq, node->nd_tbl);
- iseq_set_arguments(iseq, ret, node->nd_args);
-
- switch (iseq->body->type) {
- case ISEQ_TYPE_BLOCK:
- {
- LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
- LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
-
- start->rescued = LABEL_RESCUE_BEG;
- end->rescued = LABEL_RESCUE_END;
-
- ADD_TRACE(ret, RUBY_EVENT_B_CALL);
- NODE dummy_line_node = generate_dummy_line_node(FIX2INT(iseq->body->location.first_lineno), -1);
- ADD_INSN (ret, &dummy_line_node, nop);
- ADD_LABEL(ret, start);
- CHECK(COMPILE(ret, "block body", node->nd_body));
- ADD_LABEL(ret, end);
- ADD_TRACE(ret, RUBY_EVENT_B_RETURN);
- ISEQ_COMPILE_DATA(iseq)->last_line = iseq->body->location.code_location.end_pos.lineno;
-
- /* wide range catch handler must put at last */
- ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
- ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
- break;
- }
- case ISEQ_TYPE_CLASS:
- {
- ADD_TRACE(ret, RUBY_EVENT_CLASS);
- CHECK(COMPILE(ret, "scoped node", node->nd_body));
- ADD_TRACE(ret, RUBY_EVENT_END);
- ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
- break;
- }
- case ISEQ_TYPE_METHOD:
- {
- ADD_TRACE(ret, RUBY_EVENT_CALL);
- CHECK(COMPILE(ret, "scoped node", node->nd_body));
- ADD_TRACE(ret, RUBY_EVENT_RETURN);
- ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
- break;
- }
- default: {
- CHECK(COMPILE(ret, "scoped node", node->nd_body));
- break;
- }
- }
+ else if (nd_type_p(node, NODE_SCOPE)) {
+ /* iseq type of top, method, class, block */
+ iseq_set_local_table(iseq, node->nd_tbl);
+ iseq_set_arguments(iseq, ret, node->nd_args);
+
+ switch (ISEQ_BODY(iseq)->type) {
+ case ISEQ_TYPE_BLOCK:
+ {
+ LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
+ LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
+
+ start->rescued = LABEL_RESCUE_BEG;
+ end->rescued = LABEL_RESCUE_END;
+
+ ADD_TRACE(ret, RUBY_EVENT_B_CALL);
+ NODE dummy_line_node = generate_dummy_line_node(ISEQ_BODY(iseq)->location.first_lineno, -1);
+ ADD_INSN (ret, &dummy_line_node, nop);
+ ADD_LABEL(ret, start);
+ CHECK(COMPILE(ret, "block body", node->nd_body));
+ ADD_LABEL(ret, end);
+ ADD_TRACE(ret, RUBY_EVENT_B_RETURN);
+ ISEQ_COMPILE_DATA(iseq)->last_line = ISEQ_BODY(iseq)->location.code_location.end_pos.lineno;
+
+ /* wide range catch handler must put at last */
+ ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
+ ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
+ break;
+ }
+ case ISEQ_TYPE_CLASS:
+ {
+ ADD_TRACE(ret, RUBY_EVENT_CLASS);
+ CHECK(COMPILE(ret, "scoped node", node->nd_body));
+ ADD_TRACE(ret, RUBY_EVENT_END);
+ ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
+ break;
+ }
+ case ISEQ_TYPE_METHOD:
+ {
+ ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body;
+ ADD_TRACE(ret, RUBY_EVENT_CALL);
+ CHECK(COMPILE(ret, "scoped node", node->nd_body));
+ ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body;
+ ADD_TRACE(ret, RUBY_EVENT_RETURN);
+ ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
+ break;
+ }
+ default: {
+ CHECK(COMPILE(ret, "scoped node", node->nd_body));
+ break;
+ }
+ }
}
else {
- const char *m;
+ const char *m;
#define INVALID_ISEQ_TYPE(type) \
- ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
- switch (iseq->body->type) {
- case INVALID_ISEQ_TYPE(METHOD);
- case INVALID_ISEQ_TYPE(CLASS);
- case INVALID_ISEQ_TYPE(BLOCK);
- case INVALID_ISEQ_TYPE(EVAL);
- case INVALID_ISEQ_TYPE(MAIN);
- case INVALID_ISEQ_TYPE(TOP);
+ ISEQ_TYPE_##type: m = #type; goto invalid_iseq_type
+ switch (ISEQ_BODY(iseq)->type) {
+ case INVALID_ISEQ_TYPE(METHOD);
+ case INVALID_ISEQ_TYPE(CLASS);
+ case INVALID_ISEQ_TYPE(BLOCK);
+ case INVALID_ISEQ_TYPE(EVAL);
+ case INVALID_ISEQ_TYPE(MAIN);
+ case INVALID_ISEQ_TYPE(TOP);
#undef INVALID_ISEQ_TYPE /* invalid iseq types end */
- case ISEQ_TYPE_RESCUE:
- iseq_set_exception_local_table(iseq);
- CHECK(COMPILE(ret, "rescue", node));
- break;
- case ISEQ_TYPE_ENSURE:
- iseq_set_exception_local_table(iseq);
- CHECK(COMPILE_POPPED(ret, "ensure", node));
- break;
- case ISEQ_TYPE_PLAIN:
- CHECK(COMPILE(ret, "ensure", node));
- break;
- default:
- COMPILE_ERROR(ERROR_ARGS "unknown scope: %d", iseq->body->type);
- return COMPILE_NG;
- invalid_iseq_type:
- COMPILE_ERROR(ERROR_ARGS "compile/ISEQ_TYPE_%s should not be reached", m);
- return COMPILE_NG;
- }
- }
-
- if (iseq->body->type == ISEQ_TYPE_RESCUE || iseq->body->type == ISEQ_TYPE_ENSURE) {
+ case ISEQ_TYPE_RESCUE:
+ iseq_set_exception_local_table(iseq);
+ CHECK(COMPILE(ret, "rescue", node));
+ break;
+ case ISEQ_TYPE_ENSURE:
+ iseq_set_exception_local_table(iseq);
+ CHECK(COMPILE_POPPED(ret, "ensure", node));
+ break;
+ case ISEQ_TYPE_PLAIN:
+ CHECK(COMPILE(ret, "ensure", node));
+ break;
+ default:
+ COMPILE_ERROR(ERROR_ARGS "unknown scope: %d", ISEQ_BODY(iseq)->type);
+ return COMPILE_NG;
+ invalid_iseq_type:
+ COMPILE_ERROR(ERROR_ARGS "compile/ISEQ_TYPE_%s should not be reached", m);
+ return COMPILE_NG;
+ }
+ }
+
+ if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_RESCUE || ISEQ_BODY(iseq)->type == ISEQ_TYPE_ENSURE) {
NODE dummy_line_node = generate_dummy_line_node(0, -1);
- ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
- ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ );
+ ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
+ ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ );
}
else {
NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1);
- ADD_INSN(ret, &dummy_line_node, leave);
+ ADD_INSN(ret, &dummy_line_node, leave);
}
#if OPT_SUPPORT_JOKE
if (ISEQ_COMPILE_DATA(iseq)->labels_table) {
- st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
- ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
- validate_labels(iseq, labels_table);
+ st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
+ ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
+ validate_labels(iseq, labels_table);
}
#endif
CHECK(iseq_setup_insn(iseq, ret));
@@ -862,13 +862,13 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
const void * const *table = rb_vm_get_insns_address_table();
unsigned int i;
- VALUE *encoded = (VALUE *)iseq->body->iseq_encoded;
+ VALUE *encoded = (VALUE *)ISEQ_BODY(iseq)->iseq_encoded;
- for (i = 0; i < iseq->body->iseq_size; /* */ ) {
- int insn = (int)iseq->body->iseq_encoded[i];
- int len = insn_len(insn);
- encoded[i] = (VALUE)table[insn];
- i += len;
+ for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; /* */ ) {
+ int insn = (int)ISEQ_BODY(iseq)->iseq_encoded[i];
+ int len = insn_len(insn);
+ encoded[i] = (VALUE)table[insn];
+ i += len;
}
FL_SET((VALUE)iseq, ISEQ_TRANSLATED);
#endif
@@ -881,20 +881,20 @@ rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */
VALUE *original_code;
if (ISEQ_ORIGINAL_ISEQ(iseq)) return ISEQ_ORIGINAL_ISEQ(iseq);
- original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, iseq->body->iseq_size);
- MEMCPY(original_code, iseq->body->iseq_encoded, VALUE, iseq->body->iseq_size);
+ original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, ISEQ_BODY(iseq)->iseq_size);
+ MEMCPY(original_code, ISEQ_BODY(iseq)->iseq_encoded, VALUE, ISEQ_BODY(iseq)->iseq_size);
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; i < iseq->body->iseq_size; /* */ ) {
- const void *addr = (const void *)original_code[i];
- const int insn = rb_vm_insn_addr2insn(addr);
+ for (i = 0; i < ISEQ_BODY(iseq)->iseq_size; /* */ ) {
+ const void *addr = (const void *)original_code[i];
+ const int insn = rb_vm_insn_addr2insn(addr);
- original_code[i] = insn;
- i += insn_len(insn);
- }
+ original_code[i] = insn;
+ i += insn_len(insn);
+ }
}
#endif
return original_code;
@@ -976,18 +976,18 @@ compile_data_alloc_with_arena(struct iseq_compile_data_storage **arena, size_t s
if (size >= INT_MAX - padding) rb_memerror();
if (storage->pos + size + padding > storage->size) {
- unsigned int alloc_size = storage->size;
-
- while (alloc_size < size + PADDING_SIZE_MAX) {
- if (alloc_size >= INT_MAX / 2) rb_memerror();
- alloc_size *= 2;
- }
- storage->next = (void *)ALLOC_N(char, alloc_size +
- offsetof(struct iseq_compile_data_storage, buff));
- storage = *arena = storage->next;
- storage->next = 0;
- storage->pos = 0;
- storage->size = alloc_size;
+ unsigned int alloc_size = storage->size;
+
+ while (alloc_size < size + PADDING_SIZE_MAX) {
+ if (alloc_size >= INT_MAX / 2) rb_memerror();
+ alloc_size *= 2;
+ }
+ storage->next = (void *)ALLOC_N(char, alloc_size +
+ offsetof(struct iseq_compile_data_storage, buff));
+ storage = *arena = storage->next;
+ storage->next = 0;
+ storage->pos = 0;
+ storage->size = alloc_size;
#ifdef STRICT_ALIGNMENT
padding = calc_padding((void *)&storage->buff[storage->pos], size);
#endif /* STRICT_ALIGNMENT */
@@ -1060,7 +1060,7 @@ ELEM_INSERT_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
elem2->prev = elem1;
elem1->next = elem2;
if (elem2->next) {
- elem2->next->prev = elem2;
+ elem2->next->prev = elem2;
}
}
@@ -1074,7 +1074,7 @@ ELEM_INSERT_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
elem2->next = elem1;
elem1->prev = elem2;
if (elem2->prev) {
- elem2->prev->next = elem2;
+ elem2->prev->next = elem2;
}
}
@@ -1087,10 +1087,10 @@ ELEM_REPLACE(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
elem2->prev = elem1->prev;
elem2->next = elem1->next;
if (elem1->prev) {
- elem1->prev->next = elem2;
+ elem1->prev->next = elem2;
}
if (elem1->next) {
- elem1->next->prev = elem2;
+ elem1->next->prev = elem2;
}
}
@@ -1099,7 +1099,7 @@ ELEM_REMOVE(LINK_ELEMENT *elem)
{
elem->prev->next = elem->next;
if (elem->next) {
- elem->next->prev = elem->prev;
+ elem->next->prev = elem->prev;
}
}
@@ -1119,13 +1119,13 @@ static LINK_ELEMENT *
ELEM_FIRST_INSN(LINK_ELEMENT *elem)
{
while (elem) {
- switch (elem->type) {
- case ISEQ_ELEMENT_INSN:
- case ISEQ_ELEMENT_ADJUST:
- return elem;
- default:
- elem = elem->next;
- }
+ switch (elem->type) {
+ case ISEQ_ELEMENT_INSN:
+ case ISEQ_ELEMENT_ADJUST:
+ return elem;
+ default:
+ elem = elem->next;
+ }
}
return NULL;
}
@@ -1135,11 +1135,11 @@ LIST_INSN_SIZE_ONE(const LINK_ANCHOR *const anchor)
{
LINK_ELEMENT *first_insn = ELEM_FIRST_INSN(FIRST_ELEMENT(anchor));
if (first_insn != NULL &&
- ELEM_FIRST_INSN(first_insn->next) == NULL) {
- return TRUE;
+ ELEM_FIRST_INSN(first_insn->next) == NULL) {
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -1147,10 +1147,10 @@ static int
LIST_INSN_SIZE_ZERO(const LINK_ANCHOR *const anchor)
{
if (ELEM_FIRST_INSN(FIRST_ELEMENT(anchor)) == NULL) {
- return TRUE;
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -1165,9 +1165,9 @@ static void
APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
{
if (anc2->anchor.next) {
- anc1->last->next = anc2->anchor.next;
- anc2->anchor.next->prev = anc1->last;
- anc1->last = anc2->last;
+ anc1->last->next = anc2->anchor.next;
+ anc2->anchor.next->prev = anc1->last;
+ anc1->last = anc2->last;
}
verify_list("append", anc1);
}
@@ -1181,12 +1181,12 @@ debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *cur)
{
LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
printf("----\n");
- printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor,
- anchor->anchor.next, anchor->last);
+ printf("anch: %p, frst: %p, last: %p\n", (void *)&anchor->anchor,
+ (void *)anchor->anchor.next, (void *)anchor->last);
while (list) {
- printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next,
- list->prev, (int)list->type);
- list = list->next;
+ printf("curr: %p, next: %p, prev: %p, type: %d\n", (void *)list, (void *)list->next,
+ (void *)list->prev, (int)list->type);
+ list = list->next;
}
printf("----\n");
@@ -1243,9 +1243,35 @@ new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
return adjust;
}
+static void
+iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE data)
+{
+ const char *types = insn_op_types(insn->insn_id);
+ for (int j = 0; types[j]; j++) {
+ char type = types[j];
+ switch (type) {
+ case TS_CDHASH:
+ case TS_ISEQ:
+ case TS_VALUE:
+ case TS_IC: // constant path array
+ case TS_CALLDATA: // ci is stored.
+ func(&OPERAND_AT(insn, j), data);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+iseq_insn_each_object_write_barrier(VALUE *obj_ptr, VALUE iseq)
+{
+ RB_OBJ_WRITTEN(iseq, Qundef, *obj_ptr);
+}
+
static INSN *
new_insn_core(rb_iseq_t *iseq, const NODE *line_node,
- int insn_id, int argc, VALUE *argv)
+ int insn_id, int argc, VALUE *argv)
{
INSN *iobj = compile_data_alloc_insn(iseq);
@@ -1260,6 +1286,9 @@ new_insn_core(rb_iseq_t *iseq, const NODE *line_node,
iobj->operands = argv;
iobj->operand_size = argc;
iobj->sc_state = 0;
+
+ iseq_insn_each_markable_object(iobj, iseq_insn_each_object_write_barrier, (VALUE)iseq);
+
return iobj;
}
@@ -1269,14 +1298,14 @@ new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_typ
VALUE *operands = 0;
va_list argv;
if (argc > 0) {
- int i;
+ int i;
va_start(argv, argc);
operands = compile_data_alloc2(iseq, sizeof(VALUE), argc);
- for (i = 0; i < argc; i++) {
- VALUE v = va_arg(argv, VALUE);
- operands[i] = v;
- }
- va_end(argv);
+ for (i = 0; i < argc; i++) {
+ VALUE v = va_arg(argv, VALUE);
+ operands[i] = v;
+ }
+ va_end(argv);
}
return new_insn_core(iseq, line_node, insn_id, argc, operands);
}
@@ -1296,8 +1325,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_cal
argc += kw_arg->keyword_len;
}
- // fprintf(stderr, "[%d] id:%s\t", (int)iseq->body->ci_size, rb_id2name(mid)); rp(iseq);
- iseq->body->ci_size++;
+ ISEQ_BODY(iseq)->ci_size++;
const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg);
RB_OBJ_WRITTEN(iseq, Qundef, ci);
return ci;
@@ -1321,20 +1349,20 @@ new_insn_send(rb_iseq_t *iseq, const NODE *const line_node, ID id, VALUE argc, c
static rb_iseq_t *
new_child_iseq(rb_iseq_t *iseq, const NODE *const node,
- VALUE name, const rb_iseq_t *parent, enum iseq_type type, int line_no)
+ VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no)
{
rb_iseq_t *ret_iseq;
rb_ast_body_t ast;
ast.root = node;
ast.compile_option = 0;
- ast.script_lines = INT2FIX(-1);
+ ast.script_lines = ISEQ_BODY(iseq)->variable.script_lines;
debugs("[new_child_iseq]> ---------------------------------------\n");
int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
ret_iseq = rb_iseq_new_with_opt(&ast, name,
- rb_iseq_path(iseq), rb_iseq_realpath(iseq),
- INT2FIX(line_no), parent,
+ rb_iseq_path(iseq), rb_iseq_realpath(iseq),
+ line_no, parent,
isolated_depth ? isolated_depth + 1 : 0,
type, ISEQ_COMPILE_DATA(iseq)->option);
debugs("[new_child_iseq]< ---------------------------------------\n");
@@ -1343,14 +1371,14 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node,
static rb_iseq_t *
new_child_iseq_with_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func *ifunc,
- VALUE name, const rb_iseq_t *parent, enum iseq_type type, int line_no)
+ VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no)
{
rb_iseq_t *ret_iseq;
debugs("[new_child_iseq_with_callback]> ---------------------------------------\n");
ret_iseq = rb_iseq_new_with_callback(ifunc, name,
- rb_iseq_path(iseq), rb_iseq_realpath(iseq),
- INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option);
+ rb_iseq_path(iseq), rb_iseq_realpath(iseq),
+ line_no, parent, type, ISEQ_COMPILE_DATA(iseq)->option);
debugs("[new_child_iseq_with_callback]< ---------------------------------------\n");
return ret_iseq;
}
@@ -1358,18 +1386,18 @@ new_child_iseq_with_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_call
static void
set_catch_except_p(struct rb_iseq_constant_body *body)
{
- body->catch_except_p = TRUE;
+ body->catch_except_p = true;
if (body->parent_iseq != NULL) {
- set_catch_except_p(body->parent_iseq->body);
+ set_catch_except_p(ISEQ_BODY(body->parent_iseq));
}
}
-/* Set body->catch_except_p to TRUE if the ISeq may catch an exception. If it is FALSE,
- JIT-ed code may be optimized. If we are extremely conservative, we should set TRUE
+/* Set body->catch_except_p to true if the ISeq may catch an exception. If it is false,
+ JIT-ed code may be optimized. If we are extremely conservative, we should set true
if catch table exists. But we want to optimize while loop, which always has catch
table entries for break/next/redo.
- So this function sets TRUE for limited ISeqs with break/next/redo catch table entries
+ So this function sets true for limited ISeqs with break/next/redo catch table entries
whose child ISeq would really raise an exception. */
static void
update_catch_except_flags(struct rb_iseq_constant_body *body)
@@ -1400,7 +1428,7 @@ update_catch_except_flags(struct rb_iseq_constant_body *body)
if (entry->type != CATCH_TYPE_BREAK
&& entry->type != CATCH_TYPE_NEXT
&& entry->type != CATCH_TYPE_REDO) {
- body->catch_except_p = TRUE;
+ body->catch_except_p = true;
break;
}
}
@@ -1419,7 +1447,7 @@ iseq_insert_nop_between_end_and_cont(rb_iseq_t *iseq)
LINK_ELEMENT *cont = (LINK_ELEMENT *)(ptr[4] & ~1);
LINK_ELEMENT *e;
- enum catch_type ct = (enum catch_type)(ptr[0] & 0xffff);
+ enum rb_catch_type ct = (enum rb_catch_type)(ptr[0] & 0xffff);
if (ct != CATCH_TYPE_BREAK
&& ct != CATCH_TYPE_NEXT
@@ -1441,31 +1469,31 @@ static int
iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
{
if (RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
- return COMPILE_NG;
+ return COMPILE_NG;
/* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
if (compile_debug > 5)
- dump_disasm_list(FIRST_ELEMENT(anchor));
+ dump_disasm_list(FIRST_ELEMENT(anchor));
debugs("[compile step 3.1 (iseq_optimize)]\n");
iseq_optimize(iseq, anchor);
if (compile_debug > 5)
- dump_disasm_list(FIRST_ELEMENT(anchor));
+ dump_disasm_list(FIRST_ELEMENT(anchor));
if (ISEQ_COMPILE_DATA(iseq)->option->instructions_unification) {
- debugs("[compile step 3.2 (iseq_insns_unification)]\n");
- iseq_insns_unification(iseq, anchor);
- if (compile_debug > 5)
- dump_disasm_list(FIRST_ELEMENT(anchor));
+ debugs("[compile step 3.2 (iseq_insns_unification)]\n");
+ iseq_insns_unification(iseq, anchor);
+ if (compile_debug > 5)
+ dump_disasm_list(FIRST_ELEMENT(anchor));
}
if (ISEQ_COMPILE_DATA(iseq)->option->stack_caching) {
- debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
- iseq_set_sequence_stackcaching(iseq, anchor);
- if (compile_debug > 5)
- dump_disasm_list(FIRST_ELEMENT(anchor));
+ debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
+ iseq_set_sequence_stackcaching(iseq, anchor);
+ if (compile_debug > 5)
+ dump_disasm_list(FIRST_ELEMENT(anchor));
}
debugs("[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
@@ -1485,7 +1513,7 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
debugs("[compile step 4.1 (iseq_set_sequence)]\n");
if (!iseq_set_sequence(iseq, anchor)) return COMPILE_NG;
if (compile_debug > 5)
- dump_disasm_list(FIRST_ELEMENT(anchor));
+ dump_disasm_list(FIRST_ELEMENT(anchor));
debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
if (!iseq_set_exception_table(iseq)) return COMPILE_NG;
@@ -1497,24 +1525,24 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
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);
+ update_catch_except_flags(ISEQ_BODY(iseq));
debugs("[compile step 6.1 (remove unused catch tables)] \n");
- if (!iseq->body->catch_except_p && iseq->body->catch_table) {
- xfree(iseq->body->catch_table);
- iseq->body->catch_table = NULL;
+ if (!ISEQ_BODY(iseq)->catch_except_p && ISEQ_BODY(iseq)->catch_table) {
+ xfree(ISEQ_BODY(iseq)->catch_table);
+ ISEQ_BODY(iseq)->catch_table = NULL;
}
#if VM_INSN_INFO_TABLE_IMPL == 2
- if (iseq->body->insns_info.succ_index_table == NULL) {
+ if (ISEQ_BODY(iseq)->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));
+ VALUE str = rb_iseq_disasm(iseq);
+ printf("%s\n", StringValueCStr(str));
}
verify_call_cache(iseq);
debugs("[compile step: finish]\n");
@@ -1525,8 +1553,8 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
static int
iseq_set_exception_local_table(rb_iseq_t *iseq)
{
- iseq->body->local_table_size = numberof(rb_iseq_shared_exc_local_tbl);
- iseq->body->local_table = rb_iseq_shared_exc_local_tbl;
+ ISEQ_BODY(iseq)->local_table_size = numberof(rb_iseq_shared_exc_local_tbl);
+ ISEQ_BODY(iseq)->local_table = rb_iseq_shared_exc_local_tbl;
return COMPILE_OK;
}
@@ -1534,9 +1562,9 @@ static int
get_lvar_level(const rb_iseq_t *iseq)
{
int lev = 0;
- while (iseq != iseq->body->local_iseq) {
- lev++;
- iseq = iseq->body->parent_iseq;
+ while (iseq != ISEQ_BODY(iseq)->local_iseq) {
+ lev++;
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
}
return lev;
}
@@ -1546,10 +1574,10 @@ get_dyna_var_idx_at_raw(const rb_iseq_t *iseq, ID id)
{
unsigned int i;
- for (i = 0; i < iseq->body->local_table_size; i++) {
- if (iseq->body->local_table[i] == id) {
- return (int)i;
- }
+ for (i = 0; i < ISEQ_BODY(iseq)->local_table_size; i++) {
+ if (ISEQ_BODY(iseq)->local_table[i] == id) {
+ return (int)i;
+ }
}
return -1;
}
@@ -1557,7 +1585,7 @@ get_dyna_var_idx_at_raw(const rb_iseq_t *iseq, ID id)
static int
get_local_var_idx(const rb_iseq_t *iseq, ID id)
{
- int idx = get_dyna_var_idx_at_raw(iseq->body->local_iseq, id);
+ int idx = get_dyna_var_idx_at_raw(ISEQ_BODY(iseq)->local_iseq, id);
if (idx < 0) {
COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq),
@@ -1574,12 +1602,12 @@ get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls)
const rb_iseq_t *const topmost_iseq = iseq;
while (iseq) {
- idx = get_dyna_var_idx_at_raw(iseq, id);
- if (idx >= 0) {
- break;
- }
- iseq = iseq->body->parent_iseq;
- lv++;
+ idx = get_dyna_var_idx_at_raw(iseq, id);
+ if (idx >= 0) {
+ break;
+ }
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
+ lv++;
}
if (idx < 0) {
@@ -1588,7 +1616,7 @@ get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls)
}
*level = lv;
- *ls = iseq->body->local_table_size;
+ *ls = ISEQ_BODY(iseq)->local_table_size;
return idx;
}
@@ -1597,17 +1625,17 @@ iseq_local_block_param_p(const rb_iseq_t *iseq, unsigned int idx, unsigned int l
{
const struct rb_iseq_constant_body *body;
while (level > 0) {
- iseq = iseq->body->parent_iseq;
- level--;
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
+ level--;
}
- body = iseq->body;
+ body = ISEQ_BODY(iseq);
if (body->local_iseq == iseq && /* local variables */
- body->param.flags.has_block &&
- body->local_table_size - body->param.block_start == idx) {
- return TRUE;
+ body->param.flags.has_block &&
+ body->local_table_size - body->param.block_start == idx) {
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -1617,12 +1645,12 @@ iseq_block_param_id_p(const rb_iseq_t *iseq, ID id, int *pidx, int *plevel)
int level, ls;
int idx = get_dyna_var_idx(iseq, id, &level, &ls);
if (iseq_local_block_param_p(iseq, ls - idx, level)) {
- *pidx = ls - idx;
- *plevel = level;
- return TRUE;
+ *pidx = ls - idx;
+ *plevel = level;
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -1633,7 +1661,7 @@ access_outer_variables(const rb_iseq_t *iseq, int level, ID id, bool write)
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));
+ COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not yield from isolated Proc");
}
else {
COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not access variable `%s' from isolated Proc", rb_id2name(id));
@@ -1642,22 +1670,22 @@ access_outer_variables(const rb_iseq_t *iseq, int level, ID id, bool write)
for (int i=0; i<level; i++) {
VALUE val;
- struct rb_id_table *ovs = iseq->body->outer_variables;
+ struct rb_id_table *ovs = ISEQ_BODY(iseq)->outer_variables;
if (!ovs) {
- ovs = iseq->body->outer_variables = rb_id_table_create(8);
+ ovs = ISEQ_BODY(iseq)->outer_variables = rb_id_table_create(8);
}
- if (rb_id_table_lookup(iseq->body->outer_variables, id, &val)) {
+ if (rb_id_table_lookup(ISEQ_BODY(iseq)->outer_variables, id, &val)) {
if (write && !val) {
- rb_id_table_insert(iseq->body->outer_variables, id, Qtrue);
+ rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables, id, Qtrue);
}
}
else {
- rb_id_table_insert(iseq->body->outer_variables, id, write ? Qtrue : Qfalse);
+ rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables, id, RBOOL(write));
}
- iseq = iseq->body->parent_iseq;
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
}
}
@@ -1665,10 +1693,10 @@ 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;
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
}
- ID id = iseq->body->local_table[iseq->body->local_table_size - idx];
+ ID id = ISEQ_BODY(iseq)->local_table[ISEQ_BODY(iseq)->local_table_size - idx];
// fprintf(stderr, "idx:%d level:%d ID:%s\n", idx, level, rb_id2name(id));
return id;
}
@@ -1677,10 +1705,10 @@ static void
iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const line_node, int idx, int level)
{
if (iseq_local_block_param_p(iseq, idx, level)) {
- ADD_INSN2(seq, line_node, getblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
+ ADD_INSN2(seq, line_node, getblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
else {
- ADD_INSN2(seq, line_node, getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
+ ADD_INSN2(seq, line_node, getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qfalse);
}
@@ -1689,10 +1717,10 @@ static void
iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const line_node, int idx, int level)
{
if (iseq_local_block_param_p(iseq, idx, level)) {
- ADD_INSN2(seq, line_node, setblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
+ ADD_INSN2(seq, line_node, setblockparam, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
else {
- ADD_INSN2(seq, line_node, setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
+ ADD_INSN2(seq, line_node, setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qtrue);
}
@@ -1702,49 +1730,49 @@ iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const lin
static void
iseq_calc_param_size(rb_iseq_t *iseq)
{
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
if (body->param.flags.has_opt ||
- body->param.flags.has_post ||
- body->param.flags.has_rest ||
- body->param.flags.has_block ||
- body->param.flags.has_kw ||
- body->param.flags.has_kwrest) {
-
- if (body->param.flags.has_block) {
- body->param.size = body->param.block_start + 1;
- }
- else if (body->param.flags.has_kwrest) {
- body->param.size = body->param.keyword->rest_start + 1;
- }
- else if (body->param.flags.has_kw) {
- body->param.size = body->param.keyword->bits_start + 1;
- }
- else if (body->param.flags.has_post) {
- body->param.size = body->param.post_start + body->param.post_num;
- }
- else if (body->param.flags.has_rest) {
- body->param.size = body->param.rest_start + 1;
- }
- else if (body->param.flags.has_opt) {
- body->param.size = body->param.lead_num + body->param.opt_num;
- }
- else {
+ body->param.flags.has_post ||
+ body->param.flags.has_rest ||
+ body->param.flags.has_block ||
+ body->param.flags.has_kw ||
+ body->param.flags.has_kwrest) {
+
+ if (body->param.flags.has_block) {
+ body->param.size = body->param.block_start + 1;
+ }
+ else if (body->param.flags.has_kwrest) {
+ body->param.size = body->param.keyword->rest_start + 1;
+ }
+ else if (body->param.flags.has_kw) {
+ body->param.size = body->param.keyword->bits_start + 1;
+ }
+ else if (body->param.flags.has_post) {
+ body->param.size = body->param.post_start + body->param.post_num;
+ }
+ else if (body->param.flags.has_rest) {
+ body->param.size = body->param.rest_start + 1;
+ }
+ else if (body->param.flags.has_opt) {
+ body->param.size = body->param.lead_num + body->param.opt_num;
+ }
+ else {
UNREACHABLE;
- }
+ }
}
else {
- body->param.size = body->param.lead_num;
+ body->param.size = body->param.lead_num;
}
}
static int
iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
- const struct rb_args_info *args, int arg_size)
+ const struct rb_args_info *args, int arg_size)
{
const NODE *node = args->kw_args;
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
struct rb_iseq_param_keyword *keyword;
- const VALUE default_values = rb_ary_tmp_new(1);
+ const VALUE default_values = rb_ary_hidden_new(1);
const VALUE complex_mark = rb_str_tmp_new(0);
int kw = 0, rkw = 0, di = 0, i;
@@ -1752,68 +1780,68 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
while (node) {
- kw++;
- node = node->nd_next;
+ kw++;
+ node = node->nd_next;
}
arg_size += kw;
keyword->bits_start = arg_size++;
node = args->kw_args;
while (node) {
- const NODE *val_node = node->nd_body->nd_value;
- VALUE dv;
+ const NODE *val_node = node->nd_body->nd_value;
+ VALUE dv;
if (val_node == NODE_SPECIAL_REQUIRED_KEYWORD) {
- ++rkw;
- }
- else {
- switch (nd_type(val_node)) {
- case NODE_LIT:
- dv = val_node->nd_lit;
- break;
- case NODE_NIL:
- dv = Qnil;
- break;
- case NODE_TRUE:
- dv = Qtrue;
- break;
- case NODE_FALSE:
- dv = Qfalse;
- break;
- default:
- NO_CHECK(COMPILE_POPPED(optargs, "kwarg", node)); /* nd_type(node) == NODE_KW_ARG */
- dv = complex_mark;
- }
-
- keyword->num = ++di;
- rb_ary_push(default_values, dv);
- }
-
- node = node->nd_next;
+ ++rkw;
+ }
+ else {
+ switch (nd_type(val_node)) {
+ case NODE_LIT:
+ dv = val_node->nd_lit;
+ break;
+ case NODE_NIL:
+ dv = Qnil;
+ break;
+ case NODE_TRUE:
+ dv = Qtrue;
+ break;
+ case NODE_FALSE:
+ dv = Qfalse;
+ break;
+ default:
+ NO_CHECK(COMPILE_POPPED(optargs, "kwarg", node)); /* nd_type_p(node, NODE_KW_ARG) */
+ dv = complex_mark;
+ }
+
+ keyword->num = ++di;
+ rb_ary_push(default_values, dv);
+ }
+
+ node = node->nd_next;
}
keyword->num = kw;
if (args->kw_rest_arg->nd_vid != 0) {
- keyword->rest_start = arg_size++;
- body->param.flags.has_kwrest = TRUE;
+ keyword->rest_start = arg_size++;
+ body->param.flags.has_kwrest = TRUE;
}
keyword->required_num = rkw;
keyword->table = &body->local_table[keyword->bits_start - keyword->num];
{
- VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values));
+ VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values));
- for (i = 0; i < RARRAY_LEN(default_values); i++) {
- VALUE dv = RARRAY_AREF(default_values, i);
- if (dv == complex_mark) dv = Qundef;
- if (!SPECIAL_CONST_P(dv)) {
- RB_OBJ_WRITTEN(iseq, Qundef, dv);
- }
- dvs[i] = dv;
- }
+ for (i = 0; i < RARRAY_LEN(default_values); i++) {
+ VALUE dv = RARRAY_AREF(default_values, i);
+ if (dv == complex_mark) dv = Qundef;
+ if (!SPECIAL_CONST_P(dv)) {
+ RB_OBJ_WRITTEN(iseq, Qundef, dv);
+ }
+ dvs[i] = dv;
+ }
- keyword->default_values = dvs;
+ keyword->default_values = dvs;
}
return arg_size;
}
@@ -1824,146 +1852,138 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
debugs("iseq_set_arguments: %s\n", node_args ? "" : "0");
if (node_args) {
- struct rb_iseq_constant_body *const body = iseq->body;
- struct rb_args_info *args = node_args->nd_ainfo;
- ID rest_id = 0;
- int last_comma = 0;
- ID block_id = 0;
- int arg_size;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ struct rb_args_info *args = node_args->nd_ainfo;
+ ID rest_id = 0;
+ int last_comma = 0;
+ ID block_id = 0;
+ int arg_size;
- EXPECT_NODE("iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
+ EXPECT_NODE("iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
body->param.flags.ruby2_keywords = args->ruby2_keywords;
- body->param.lead_num = arg_size = (int)args->pre_args_num;
- if (body->param.lead_num > 0) body->param.flags.has_lead = TRUE;
- debugs(" - argc: %d\n", body->param.lead_num);
+ body->param.lead_num = arg_size = (int)args->pre_args_num;
+ if (body->param.lead_num > 0) body->param.flags.has_lead = TRUE;
+ debugs(" - argc: %d\n", body->param.lead_num);
- rest_id = args->rest_arg;
+ rest_id = args->rest_arg;
if (rest_id == NODE_SPECIAL_EXCESSIVE_COMMA) {
- last_comma = 1;
- rest_id = 0;
- }
- block_id = args->block_arg;
-
- if (args->opt_args) {
- const NODE *node = args->opt_args;
- LABEL *label;
- VALUE labels = rb_ary_tmp_new(1);
- VALUE *opt_table;
- int i = 0, j;
-
- while (node) {
- label = NEW_LABEL(nd_line(node));
- rb_ary_push(labels, (VALUE)label | 1);
- ADD_LABEL(optargs, label);
+ last_comma = 1;
+ rest_id = 0;
+ }
+ block_id = args->block_arg;
+
+ if (args->opt_args) {
+ const NODE *node = args->opt_args;
+ LABEL *label;
+ VALUE labels = rb_ary_hidden_new(1);
+ VALUE *opt_table;
+ int i = 0, j;
+
+ while (node) {
+ label = NEW_LABEL(nd_line(node));
+ rb_ary_push(labels, (VALUE)label | 1);
+ ADD_LABEL(optargs, label);
NO_CHECK(COMPILE_POPPED(optargs, "optarg", node->nd_body));
- node = node->nd_next;
- i += 1;
- }
+ node = node->nd_next;
+ i += 1;
+ }
- /* last label */
- label = NEW_LABEL(nd_line(node_args));
- rb_ary_push(labels, (VALUE)label | 1);
- ADD_LABEL(optargs, label);
+ /* last label */
+ label = NEW_LABEL(nd_line(node_args));
+ rb_ary_push(labels, (VALUE)label | 1);
+ ADD_LABEL(optargs, label);
- opt_table = ALLOC_N(VALUE, i+1);
+ opt_table = ALLOC_N(VALUE, i+1);
MEMCPY(opt_table, RARRAY_CONST_PTR_TRANSIENT(labels), VALUE, i+1);
- for (j = 0; j < i+1; j++) {
- opt_table[j] &= ~1;
- }
- rb_ary_clear(labels);
-
- body->param.flags.has_opt = TRUE;
- body->param.opt_num = i;
- body->param.opt_table = opt_table;
- arg_size += i;
- }
-
- if (rest_id) {
- body->param.rest_start = arg_size++;
- body->param.flags.has_rest = TRUE;
- assert(body->param.rest_start != -1);
- }
-
- if (args->first_post_arg) {
- body->param.post_start = arg_size;
- body->param.post_num = args->post_args_num;
- body->param.flags.has_post = TRUE;
- arg_size += args->post_args_num;
-
- if (body->param.flags.has_rest) { /* TODO: why that? */
- body->param.post_start = body->param.rest_start + 1;
- }
- }
-
- if (args->kw_args) {
- arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
- }
- else if (args->kw_rest_arg) {
- struct rb_iseq_param_keyword *keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
- keyword->rest_start = arg_size++;
- body->param.keyword = keyword;
- body->param.flags.has_kwrest = TRUE;
- }
- else if (args->no_kwarg) {
- body->param.flags.accepts_no_kwarg = TRUE;
- }
-
- if (block_id) {
- body->param.block_start = arg_size++;
- body->param.flags.has_block = TRUE;
- }
-
- iseq_calc_param_size(iseq);
- body->param.size = arg_size;
-
- if (args->pre_init) { /* m_init */
+ for (j = 0; j < i+1; j++) {
+ opt_table[j] &= ~1;
+ }
+ rb_ary_clear(labels);
+
+ body->param.flags.has_opt = TRUE;
+ body->param.opt_num = i;
+ body->param.opt_table = opt_table;
+ arg_size += i;
+ }
+
+ if (rest_id) {
+ body->param.rest_start = arg_size++;
+ body->param.flags.has_rest = TRUE;
+ assert(body->param.rest_start != -1);
+ }
+
+ if (args->first_post_arg) {
+ body->param.post_start = arg_size;
+ body->param.post_num = args->post_args_num;
+ body->param.flags.has_post = TRUE;
+ arg_size += args->post_args_num;
+
+ if (body->param.flags.has_rest) { /* TODO: why that? */
+ body->param.post_start = body->param.rest_start + 1;
+ }
+ }
+
+ if (args->kw_args) {
+ arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
+ }
+ else if (args->kw_rest_arg) {
+ struct rb_iseq_param_keyword *keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
+ keyword->rest_start = arg_size++;
+ body->param.keyword = keyword;
+ body->param.flags.has_kwrest = TRUE;
+ }
+ else if (args->no_kwarg) {
+ body->param.flags.accepts_no_kwarg = TRUE;
+ }
+
+ if (block_id) {
+ body->param.block_start = arg_size++;
+ body->param.flags.has_block = TRUE;
+ }
+
+ iseq_calc_param_size(iseq);
+ body->param.size = arg_size;
+
+ if (args->pre_init) { /* m_init */
NO_CHECK(COMPILE_POPPED(optargs, "init arguments (m)", args->pre_init));
- }
- if (args->post_init) { /* p_init */
+ }
+ if (args->post_init) { /* p_init */
NO_CHECK(COMPILE_POPPED(optargs, "init arguments (p)", args->post_init));
- }
+ }
- if (body->type == ISEQ_TYPE_BLOCK) {
- if (body->param.flags.has_opt == FALSE &&
- body->param.flags.has_post == FALSE &&
- body->param.flags.has_rest == FALSE &&
- body->param.flags.has_kw == FALSE &&
- body->param.flags.has_kwrest == FALSE) {
+ if (body->type == ISEQ_TYPE_BLOCK) {
+ if (body->param.flags.has_opt == FALSE &&
+ body->param.flags.has_post == FALSE &&
+ body->param.flags.has_rest == FALSE &&
+ body->param.flags.has_kw == FALSE &&
+ body->param.flags.has_kwrest == FALSE) {
- if (body->param.lead_num == 1 && last_comma == 0) {
- /* {|a|} */
- body->param.flags.ambiguous_param0 = TRUE;
- }
- }
- }
+ if (body->param.lead_num == 1 && last_comma == 0) {
+ /* {|a|} */
+ body->param.flags.ambiguous_param0 = TRUE;
+ }
+ }
+ }
}
return COMPILE_OK;
}
static int
-iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl)
+iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl)
{
- unsigned int size;
-
- if (tbl) {
- size = (unsigned int)*tbl;
- tbl++;
- }
- else {
- size = 0;
- }
+ unsigned int size = tbl ? tbl->size : 0;
if (size > 0) {
- ID *ids = (ID *)ALLOC_N(ID, size);
- MEMCPY(ids, tbl, ID, size);
- iseq->body->local_table = ids;
+ ID *ids = (ID *)ALLOC_N(ID, size);
+ MEMCPY(ids, tbl->ids, ID, size);
+ ISEQ_BODY(iseq)->local_table = ids;
}
- iseq->body->local_table_size = size;
+ ISEQ_BODY(iseq)->local_table_size = size;
- debugs("iseq_set_local_table: %u\n", iseq->body->local_table_size);
+ debugs("iseq_set_local_table: %u\n", ISEQ_BODY(iseq)->local_table_size);
return COMPILE_OK;
}
@@ -2067,18 +2087,24 @@ cdhash_set_label_i(VALUE key, VALUE val, VALUE ptr)
static inline VALUE
get_ivar_ic_value(rb_iseq_t *iseq,ID id)
{
+ return INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
+}
+
+static inline VALUE
+get_cvar_ic_value(rb_iseq_t *iseq,ID id)
+{
VALUE val;
struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
if (tbl) {
- if (rb_id_table_lookup(tbl,id,&val)) {
- return val;
- }
+ if (rb_id_table_lookup(tbl,id,&val)) {
+ return val;
+ }
}
else {
- tbl = rb_id_table_create(1);
- ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
+ tbl = rb_id_table_create(1);
+ ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
}
- val = INT2FIX(iseq->body->is_size++);
+ val = INT2FIX(ISEQ_BODY(iseq)->icvarc_size++);
rb_id_table_insert(tbl,id,val);
return val;
}
@@ -2099,113 +2125,113 @@ fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
LINK_ELEMENT *list;
for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
- if (list->type == ISEQ_ELEMENT_LABEL) {
- LABEL *lobj = (LABEL *)list;
- lobj->set = TRUE;
- }
+ if (IS_LABEL(list)) {
+ LABEL *lobj = (LABEL *)list;
+ lobj->set = TRUE;
+ }
}
for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
- switch (list->type) {
- case ISEQ_ELEMENT_INSN:
- {
- int j, len, insn;
- const char *types;
- VALUE *operands;
- INSN *iobj = (INSN *)list;
-
- /* update sp */
- sp = calc_sp_depth(sp, iobj);
- if (sp < 0) {
- BADINSN_DUMP(anchor, list, NULL);
- COMPILE_ERROR(iseq, iobj->insn_info.line_no,
- "argument stack underflow (%d)", sp);
- return -1;
- }
- if (sp > stack_max) {
- stack_max = sp;
- }
-
- line = iobj->insn_info.line_no;
- /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
- operands = iobj->operands;
- insn = iobj->insn_id;
- types = insn_op_types(insn);
- len = insn_len(insn);
-
- /* operand check */
- if (iobj->operand_size != len - 1) {
- /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
- BADINSN_DUMP(anchor, list, NULL);
- COMPILE_ERROR(iseq, iobj->insn_info.line_no,
- "operand size miss! (%d for %d)",
- iobj->operand_size, len - 1);
- return -1;
- }
-
- for (j = 0; types[j]; j++) {
- if (types[j] == TS_OFFSET) {
- /* label(destination position) */
- LABEL *lobj = (LABEL *)operands[j];
- if (!lobj->set) {
- BADINSN_DUMP(anchor, list, NULL);
- COMPILE_ERROR(iseq, iobj->insn_info.line_no,
- "unknown label: "LABEL_FORMAT, lobj->label_no);
- return -1;
- }
- if (lobj->sp == -1) {
- lobj->sp = sp;
+ switch (list->type) {
+ case ISEQ_ELEMENT_INSN:
+ {
+ int j, len, insn;
+ const char *types;
+ VALUE *operands;
+ INSN *iobj = (INSN *)list;
+
+ /* update sp */
+ sp = calc_sp_depth(sp, iobj);
+ if (sp < 0) {
+ BADINSN_DUMP(anchor, list, NULL);
+ COMPILE_ERROR(iseq, iobj->insn_info.line_no,
+ "argument stack underflow (%d)", sp);
+ return -1;
+ }
+ if (sp > stack_max) {
+ stack_max = sp;
+ }
+
+ line = iobj->insn_info.line_no;
+ /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
+ operands = iobj->operands;
+ insn = iobj->insn_id;
+ types = insn_op_types(insn);
+ len = insn_len(insn);
+
+ /* operand check */
+ if (iobj->operand_size != len - 1) {
+ /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
+ BADINSN_DUMP(anchor, list, NULL);
+ COMPILE_ERROR(iseq, iobj->insn_info.line_no,
+ "operand size miss! (%d for %d)",
+ iobj->operand_size, len - 1);
+ return -1;
+ }
+
+ for (j = 0; types[j]; j++) {
+ if (types[j] == TS_OFFSET) {
+ /* label(destination position) */
+ LABEL *lobj = (LABEL *)operands[j];
+ if (!lobj->set) {
+ BADINSN_DUMP(anchor, list, NULL);
+ COMPILE_ERROR(iseq, iobj->insn_info.line_no,
+ "unknown label: "LABEL_FORMAT, lobj->label_no);
+ return -1;
+ }
+ 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;
- }
- case ISEQ_ELEMENT_LABEL:
- {
- LABEL *lobj = (LABEL *)list;
- if (lobj->sp == -1) {
- lobj->sp = sp;
- }
- else {
+ }
+ }
+ break;
+ }
+ case ISEQ_ELEMENT_LABEL:
+ {
+ LABEL *lobj = (LABEL *)list;
+ 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);
}
- sp = lobj->sp;
- }
- break;
- }
- case ISEQ_ELEMENT_TRACE:
- {
- /* ignore */
- break;
- }
- case ISEQ_ELEMENT_ADJUST:
- {
- ADJUST *adjust = (ADJUST *)list;
- int orig_sp = sp;
-
- sp = adjust->label ? adjust->label->sp : 0;
- if (adjust->line_no != -1 && orig_sp - sp < 0) {
- BADINSN_DUMP(anchor, list, NULL);
- COMPILE_ERROR(iseq, adjust->line_no,
- "iseq_set_sequence: adjust bug %d < %d",
- orig_sp, sp);
- return -1;
- }
- break;
- }
- default:
- BADINSN_DUMP(anchor, list, NULL);
- COMPILE_ERROR(iseq, line, "unknown list type: %d", list->type);
- return -1;
- }
+ sp = lobj->sp;
+ }
+ break;
+ }
+ case ISEQ_ELEMENT_TRACE:
+ {
+ /* ignore */
+ break;
+ }
+ case ISEQ_ELEMENT_ADJUST:
+ {
+ ADJUST *adjust = (ADJUST *)list;
+ int orig_sp = sp;
+
+ sp = adjust->label ? adjust->label->sp : 0;
+ if (adjust->line_no != -1 && orig_sp - sp < 0) {
+ BADINSN_DUMP(anchor, list, NULL);
+ COMPILE_ERROR(iseq, adjust->line_no,
+ "iseq_set_sequence: adjust bug %d < %d",
+ orig_sp, sp);
+ return -1;
+ }
+ break;
+ }
+ default:
+ BADINSN_DUMP(anchor, list, NULL);
+ COMPILE_ERROR(iseq, line, "unknown list type: %d", list->type);
+ return -1;
+ }
}
return stack_max;
}
@@ -2235,14 +2261,34 @@ static int
add_adjust_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions,
int insns_info_index, int code_index, const ADJUST *adjust)
{
- if (insns_info_index > 0 ||
- insns_info[insns_info_index-1].line_no != adjust->line_no) {
- insns_info[insns_info_index].line_no = adjust->line_no;
- insns_info[insns_info_index].events = 0;
- positions[insns_info_index] = code_index;
- return TRUE;
+ insns_info[insns_info_index].line_no = adjust->line_no;
+ insns_info[insns_info_index].events = 0;
+ positions[insns_info_index] = code_index;
+ return TRUE;
+}
+
+static ID *
+array_to_idlist(VALUE arr)
+{
+ RUBY_ASSERT(RB_TYPE_P(arr, T_ARRAY));
+ long size = RARRAY_LEN(arr);
+ ID *ids = (ID *)ALLOC_N(ID, size + 1);
+ for (int i = 0; i < size; i++) {
+ VALUE sym = RARRAY_AREF(arr, i);
+ ids[i] = SYM2ID(sym);
}
- return FALSE;
+ ids[size] = 0;
+ return ids;
+}
+
+static VALUE
+idlist_to_array(const ID *ids)
+{
+ VALUE arr = rb_ary_new();
+ while (*ids) {
+ rb_ary_push(arr, ID2SYM(*ids++));
+ }
+ return arr;
}
/**
@@ -2251,9 +2297,8 @@ 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;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
unsigned int *positions;
LINK_ELEMENT *list;
VALUE *generated_iseq;
@@ -2268,20 +2313,20 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
/* fix label position */
insn_num = code_index = 0;
for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
- switch (list->type) {
- case ISEQ_ELEMENT_INSN:
- {
- INSN *iobj = (INSN *)list;
- /* update sp */
- sp = calc_sp_depth(sp, iobj);
- insn_num++;
+ switch (list->type) {
+ case ISEQ_ELEMENT_INSN:
+ {
+ INSN *iobj = (INSN *)list;
+ /* update sp */
+ sp = calc_sp_depth(sp, iobj);
+ insn_num++;
events = iobj->insn_info.events |= events;
if (ISEQ_COVERAGE(iseq)) {
if (ISEQ_LINE_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_LINE) &&
!(rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES)) {
- int line = iobj->insn_info.line_no;
- if (line >= 1) {
- RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line - 1, INT2FIX(0));
+ int line = iobj->insn_info.line_no - 1;
+ if (line >= 0 && line < RARRAY_LEN(ISEQ_LINE_COVERAGE(iseq))) {
+ RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line, INT2FIX(0));
}
}
if (ISEQ_BRANCH_COVERAGE(iseq) && (events & RUBY_EVENT_COVERAGE_BRANCH)) {
@@ -2290,137 +2335,189 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
}
RARRAY_ASET(ISEQ_PC2BRANCHINDEX(iseq), code_index, INT2FIX(data));
}
- }
+ }
code_index += insn_data_length(iobj);
- events = 0;
+ events = 0;
data = 0;
- break;
- }
- case ISEQ_ELEMENT_LABEL:
- {
- LABEL *lobj = (LABEL *)list;
- lobj->position = code_index;
+ break;
+ }
+ case ISEQ_ELEMENT_LABEL:
+ {
+ 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;
- }
- case ISEQ_ELEMENT_TRACE:
- {
- TRACE *trace = (TRACE *)list;
- events |= trace->event;
+ sp = lobj->sp;
+ break;
+ }
+ case ISEQ_ELEMENT_TRACE:
+ {
+ TRACE *trace = (TRACE *)list;
+ events |= trace->event;
if (trace->event & RUBY_EVENT_COVERAGE_BRANCH) data = trace->data;
- break;
- }
- case ISEQ_ELEMENT_ADJUST:
- {
- ADJUST *adjust = (ADJUST *)list;
- if (adjust->line_no != -1) {
- int orig_sp = sp;
- sp = adjust->label ? adjust->label->sp : 0;
- if (orig_sp - sp > 0) {
- if (orig_sp - sp > 1) code_index++; /* 1 operand */
- code_index++; /* insn */
- insn_num++;
- }
- }
- break;
- }
- default: break;
- }
+ break;
+ }
+ case ISEQ_ELEMENT_ADJUST:
+ {
+ ADJUST *adjust = (ADJUST *)list;
+ if (adjust->line_no != -1) {
+ int orig_sp = sp;
+ sp = adjust->label ? adjust->label->sp : 0;
+ if (orig_sp - sp > 0) {
+ if (orig_sp - sp > 1) code_index++; /* 1 operand */
+ code_index++; /* insn */
+ insn_num++;
+ }
+ }
+ break;
+ }
+ default: break;
+ }
}
/* make instruction sequence */
generated_iseq = ALLOC_N(VALUE, code_index);
insns_info = ALLOC_N(struct iseq_insn_info_entry, insn_num);
positions = ALLOC_N(unsigned int, insn_num);
- body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, body->is_size);
+ body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(body));
body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size);
ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
+ // Calculate the bitmask buffer size.
+ // Round the generated_iseq size up to the nearest multiple
+ // of the number of bits in an unsigned long.
+
+ // Allocate enough room for the bitmask list
+ iseq_bits_t * mark_offset_bits;
+ int code_size = code_index;
+
+ iseq_bits_t tmp[1] = {0};
+ bool needs_bitmap = false;
+
+ if (ISEQ_MBITS_BUFLEN(code_index) == 1) {
+ mark_offset_bits = tmp;
+ }
+ else {
+ mark_offset_bits = ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(code_index));
+ }
+
list = FIRST_ELEMENT(anchor);
insns_info_index = code_index = sp = 0;
while (list) {
- switch (list->type) {
- case ISEQ_ELEMENT_INSN:
- {
- int j, len, insn;
- const char *types;
- VALUE *operands;
- INSN *iobj = (INSN *)list;
-
- /* update sp */
- sp = calc_sp_depth(sp, iobj);
- /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
- operands = iobj->operands;
- insn = iobj->insn_id;
- generated_iseq[code_index] = insn;
- types = insn_op_types(insn);
- len = insn_len(insn);
-
- for (j = 0; types[j]; j++) {
- char type = types[j];
- /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
- switch (type) {
- case TS_OFFSET:
- {
- /* label(destination position) */
- LABEL *lobj = (LABEL *)operands[j];
- generated_iseq[code_index + 1 + j] = lobj->position - (code_index + len);
- break;
- }
- case TS_CDHASH:
- {
- VALUE map = operands[j];
- struct cdhash_set_label_struct data;
+ switch (list->type) {
+ case ISEQ_ELEMENT_INSN:
+ {
+ int j, len, insn;
+ const char *types;
+ VALUE *operands;
+ INSN *iobj = (INSN *)list;
+
+ /* update sp */
+ sp = calc_sp_depth(sp, iobj);
+ /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
+ operands = iobj->operands;
+ insn = iobj->insn_id;
+ generated_iseq[code_index] = insn;
+ types = insn_op_types(insn);
+ len = insn_len(insn);
+
+ for (j = 0; types[j]; j++) {
+ char type = types[j];
+
+ /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
+ switch (type) {
+ case TS_OFFSET:
+ {
+ /* label(destination position) */
+ LABEL *lobj = (LABEL *)operands[j];
+ generated_iseq[code_index + 1 + j] = lobj->position - (code_index + len);
+ break;
+ }
+ case TS_CDHASH:
+ {
+ VALUE map = operands[j];
+ struct cdhash_set_label_struct data;
data.hash = map;
data.pos = code_index;
data.len = len;
- rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data);
-
- rb_hash_rehash(map);
- freeze_hide_obj(map);
- generated_iseq[code_index + 1 + j] = map;
- RB_OBJ_WRITTEN(iseq, Qundef, map);
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
- break;
- }
- case TS_LINDEX:
- case TS_NUM: /* ulong */
- generated_iseq[code_index + 1 + j] = FIX2INT(operands[j]);
- break;
- case TS_VALUE: /* VALUE */
- case TS_ISEQ: /* iseq */
- {
- VALUE v = operands[j];
- generated_iseq[code_index + 1 + j] = v;
- /* to mark ruby object */
- if (!SPECIAL_CONST_P(v)) {
- RB_OBJ_WRITTEN(iseq, Qundef, v);
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
- }
- break;
- }
- case TS_IC: /* inline cache */
- case TS_ISE: /* inline storage entry */
- case TS_IVC: /* inline ivar cache */
- {
- unsigned int ic_index = FIX2UINT(operands[j]);
- IC ic = (IC)&body->is_entries[ic_index];
- if (UNLIKELY(ic_index >= body->is_size)) {
+ rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data);
+
+ rb_hash_rehash(map);
+ freeze_hide_obj(map);
+ generated_iseq[code_index + 1 + j] = map;
+ ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
+ RB_OBJ_WRITTEN(iseq, Qundef, map);
+ needs_bitmap = true;
+ break;
+ }
+ case TS_LINDEX:
+ case TS_NUM: /* ulong */
+ generated_iseq[code_index + 1 + j] = FIX2INT(operands[j]);
+ break;
+ case TS_ISEQ: /* iseq */
+ case TS_VALUE: /* VALUE */
+ {
+ VALUE v = operands[j];
+ generated_iseq[code_index + 1 + j] = v;
+ /* to mark ruby object */
+ if (!SPECIAL_CONST_P(v)) {
+ RB_OBJ_WRITTEN(iseq, Qundef, v);
+ ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
+ needs_bitmap = true;
+ }
+ break;
+ }
+ /* [ TS_IVC | TS_ICVARC | TS_ISE | TS_IC ] */
+ case TS_IC: /* inline cache: constants */
+ {
+ unsigned int ic_index = ISEQ_COMPILE_DATA(iseq)->ic_index++;
+ IC ic = &ISEQ_IS_ENTRY_START(body, type)[ic_index].ic_cache;
+ if (UNLIKELY(ic_index >= body->ic_size)) {
BADINSN_DUMP(anchor, &iobj->link, 0);
COMPILE_ERROR(iseq, iobj->insn_info.line_no,
"iseq_set_sequence: ic_index overflow: index: %d, size: %d",
- ic_index, body->is_size);
- }
- generated_iseq[code_index + 1 + j] = (VALUE)ic;
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
- break;
- }
+ ic_index, ISEQ_IS_SIZE(body));
+ }
+
+ ic->segments = array_to_idlist(operands[j]);
+
+ generated_iseq[code_index + 1 + j] = (VALUE)ic;
+ }
+ break;
+ case TS_IVC: /* inline ivar cache */
+ {
+ unsigned int ic_index = FIX2UINT(operands[j]);
+
+ IVC cache = ((IVC)&body->is_entries[ic_index]);
+
+ if (insn == BIN(setinstancevariable)) {
+ cache->iv_set_name = SYM2ID(operands[j - 1]);
+ }
+ else {
+ cache->iv_set_name = 0;
+ }
+
+ vm_ic_attr_index_initialize(cache, INVALID_SHAPE_ID);
+ }
+ case TS_ISE: /* inline storage entry: `once` insn */
+ case TS_ICVARC: /* inline cvar cache */
+ {
+ unsigned int ic_index = FIX2UINT(operands[j]);
+ IC ic = &ISEQ_IS_ENTRY_START(body, type)[ic_index].ic_cache;
+ if (UNLIKELY(ic_index >= ISEQ_IS_SIZE(body))) {
+ BADINSN_DUMP(anchor, &iobj->link, 0);
+ COMPILE_ERROR(iseq, iobj->insn_info.line_no,
+ "iseq_set_sequence: ic_index overflow: index: %d, size: %d",
+ ic_index, ISEQ_IS_SIZE(body));
+ }
+ generated_iseq[code_index + 1 + j] = (VALUE)ic;
+
+ break;
+ }
case TS_CALLDATA:
{
const struct rb_callinfo *source_ci = (const struct rb_callinfo *)operands[j];
@@ -2431,85 +2528,105 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
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_FUNCPTR:
- generated_iseq[code_index + 1 + j] = operands[j];
- break;
+ case TS_ID: /* ID */
+ generated_iseq[code_index + 1 + j] = SYM2ID(operands[j]);
+ break;
+ case TS_FUNCPTR:
+ generated_iseq[code_index + 1 + j] = operands[j];
+ break;
case TS_BUILTIN:
generated_iseq[code_index + 1 + j] = operands[j];
break;
- default:
- BADINSN_ERROR(iseq, iobj->insn_info.line_no,
- "unknown operand type: %c", type);
- return COMPILE_NG;
- }
- }
- if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
- code_index += len;
- break;
- }
- case ISEQ_ELEMENT_LABEL:
- {
- LABEL *lobj = (LABEL *)list;
+ default:
+ BADINSN_ERROR(iseq, iobj->insn_info.line_no,
+ "unknown operand type: %c", type);
+ return COMPILE_NG;
+ }
+ }
+ if (add_insn_info(insns_info, positions, insns_info_index, code_index, iobj)) insns_info_index++;
+ code_index += len;
+ break;
+ }
+ 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;
- }
- case ISEQ_ELEMENT_ADJUST:
- {
- ADJUST *adjust = (ADJUST *)list;
- int orig_sp = sp;
-
- if (adjust->label) {
- sp = adjust->label->sp;
- }
- else {
- sp = 0;
- }
-
- if (adjust->line_no != -1) {
- const int diff = orig_sp - sp;
- if (diff > 0) {
- if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
- }
- if (diff > 1) {
- generated_iseq[code_index++] = BIN(adjuststack);
- generated_iseq[code_index++] = orig_sp - sp;
- }
- else if (diff == 1) {
- generated_iseq[code_index++] = BIN(pop);
- }
- else if (diff < 0) {
- int label_no = adjust->label ? adjust->label->label_no : -1;
- xfree(generated_iseq);
- xfree(insns_info);
- xfree(positions);
- debug_list(anchor, list);
- COMPILE_ERROR(iseq, adjust->line_no,
- "iseq_set_sequence: adjust bug to %d %d < %d",
- label_no, orig_sp, sp);
- return COMPILE_NG;
- }
- }
- break;
- }
- default:
- /* ignore */
- break;
- }
- list = list->next;
+ sp = lobj->sp;
+ break;
+ }
+ case ISEQ_ELEMENT_ADJUST:
+ {
+ ADJUST *adjust = (ADJUST *)list;
+ int orig_sp = sp;
+
+ if (adjust->label) {
+ sp = adjust->label->sp;
+ }
+ else {
+ sp = 0;
+ }
+
+ if (adjust->line_no != -1) {
+ const int diff = orig_sp - sp;
+ if (diff > 0) {
+ if (insns_info_index == 0) {
+ COMPILE_ERROR(iseq, adjust->line_no,
+ "iseq_set_sequence: adjust bug (ISEQ_ELEMENT_ADJUST must not be the first in iseq)");
+ }
+ if (add_adjust_info(insns_info, positions, insns_info_index, code_index, adjust)) insns_info_index++;
+ }
+ if (diff > 1) {
+ generated_iseq[code_index++] = BIN(adjuststack);
+ generated_iseq[code_index++] = orig_sp - sp;
+ }
+ else if (diff == 1) {
+ generated_iseq[code_index++] = BIN(pop);
+ }
+ else if (diff < 0) {
+ int label_no = adjust->label ? adjust->label->label_no : -1;
+ xfree(generated_iseq);
+ xfree(insns_info);
+ xfree(positions);
+ if (ISEQ_MBITS_BUFLEN(code_size) > 1) {
+ xfree(mark_offset_bits);
+ }
+ debug_list(anchor, list);
+ COMPILE_ERROR(iseq, adjust->line_no,
+ "iseq_set_sequence: adjust bug to %d %d < %d",
+ label_no, orig_sp, sp);
+ return COMPILE_NG;
+ }
+ }
+ break;
+ }
+ default:
+ /* ignore */
+ break;
+ }
+ list = list->next;
}
body->iseq_encoded = (void *)generated_iseq;
body->iseq_size = code_index;
body->stack_max = stack_max;
+ if (ISEQ_MBITS_BUFLEN(body->iseq_size) == 1) {
+ body->mark_bits.single = mark_offset_bits[0];
+ }
+ else {
+ if (needs_bitmap) {
+ body->mark_bits.list = mark_offset_bits;
+ }
+ else {
+ body->mark_bits.list = 0;
+ ruby_xfree(mark_offset_bits);
+ }
+ }
+
/* get rid of memory leak when REALLOC failed */
body->insns_info.body = insns_info;
body->insns_info.positions = positions;
@@ -2542,45 +2659,49 @@ iseq_set_exception_table(rb_iseq_t *iseq)
unsigned int tlen, i;
struct iseq_catch_table_entry *entry;
- 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);
+ ISEQ_BODY(iseq)->catch_table = NULL;
+
+ VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
+ if (NIL_P(catch_table_ary)) return COMPILE_OK;
+ tlen = (int)RARRAY_LEN(catch_table_ary);
+ tptr = RARRAY_CONST_PTR_TRANSIENT(catch_table_ary);
if (tlen > 0) {
- struct iseq_catch_table *table = xmalloc(iseq_catch_table_bytes(tlen));
- table->size = tlen;
+ struct iseq_catch_table *table = xmalloc(iseq_catch_table_bytes(tlen));
+ table->size = tlen;
- for (i = 0; i < table->size; i++) {
+ for (i = 0; i < table->size; i++) {
ptr = RARRAY_CONST_PTR_TRANSIENT(tptr[i]);
- entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
- entry->type = (enum catch_type)(ptr[0] & 0xffff);
- entry->start = label_get_position((LABEL *)(ptr[1] & ~1));
- entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
- entry->iseq = (rb_iseq_t *)ptr[3];
- RB_OBJ_WRITTEN(iseq, Qundef, entry->iseq);
-
- /* stack depth */
- if (ptr[4]) {
- LABEL *lobj = (LABEL *)(ptr[4] & ~1);
- entry->cont = label_get_position(lobj);
- entry->sp = label_get_sp(lobj);
-
- /* TODO: Dirty Hack! Fix me */
- if (entry->type == CATCH_TYPE_RESCUE ||
- entry->type == CATCH_TYPE_BREAK ||
- entry->type == CATCH_TYPE_NEXT) {
- entry->sp--;
- }
- }
- else {
- entry->cont = 0;
- }
- }
- iseq->body->catch_table = table;
- RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */
+ entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
+ entry->type = (enum rb_catch_type)(ptr[0] & 0xffff);
+ entry->start = label_get_position((LABEL *)(ptr[1] & ~1));
+ entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
+ entry->iseq = (rb_iseq_t *)ptr[3];
+ RB_OBJ_WRITTEN(iseq, Qundef, entry->iseq);
+
+ /* stack depth */
+ if (ptr[4]) {
+ LABEL *lobj = (LABEL *)(ptr[4] & ~1);
+ entry->cont = label_get_position(lobj);
+ entry->sp = label_get_sp(lobj);
+
+ /* TODO: Dirty Hack! Fix me */
+ if (entry->type == CATCH_TYPE_RESCUE ||
+ entry->type == CATCH_TYPE_BREAK ||
+ entry->type == CATCH_TYPE_NEXT) {
+ entry->sp--;
+ }
+ }
+ else {
+ entry->cont = 0;
+ }
+ }
+ ISEQ_BODY(iseq)->catch_table = table;
+ RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */
}
+ RB_GC_GUARD(catch_table_ary);
+
return COMPILE_OK;
}
@@ -2597,12 +2718,12 @@ static int
iseq_set_optargs_table(rb_iseq_t *iseq)
{
int i;
- VALUE *opt_table = (VALUE *)iseq->body->param.opt_table;
+ VALUE *opt_table = (VALUE *)ISEQ_BODY(iseq)->param.opt_table;
- if (iseq->body->param.flags.has_opt) {
- for (i = 0; i < iseq->body->param.opt_num + 1; i++) {
- opt_table[i] = label_get_position((LABEL *)opt_table[i]);
- }
+ if (ISEQ_BODY(iseq)->param.flags.has_opt) {
+ for (i = 0; i < ISEQ_BODY(iseq)->param.opt_num + 1; i++) {
+ opt_table[i] = label_get_position((LABEL *)opt_table[i]);
+ }
}
return COMPILE_OK;
}
@@ -2616,27 +2737,27 @@ get_destination_insn(INSN *iobj)
list = lobj->link.next;
while (list) {
- switch (list->type) {
- case ISEQ_ELEMENT_INSN:
- case ISEQ_ELEMENT_ADJUST:
- goto found;
- case ISEQ_ELEMENT_LABEL:
- /* ignore */
- break;
- case ISEQ_ELEMENT_TRACE:
- {
- TRACE *trace = (TRACE *)list;
- events |= trace->event;
- }
- break;
- default: break;
- }
- list = list->next;
+ switch (list->type) {
+ case ISEQ_ELEMENT_INSN:
+ case ISEQ_ELEMENT_ADJUST:
+ goto found;
+ case ISEQ_ELEMENT_LABEL:
+ /* ignore */
+ break;
+ case ISEQ_ELEMENT_TRACE:
+ {
+ TRACE *trace = (TRACE *)list;
+ events |= trace->event;
+ }
+ break;
+ default: break;
+ }
+ list = list->next;
}
found:
if (list && IS_INSN(list)) {
- INSN *iobj = (INSN *)list;
- iobj->insn_info.events |= events;
+ INSN *iobj = (INSN *)list;
+ iobj->insn_info.events |= events;
}
return list;
}
@@ -2647,10 +2768,10 @@ get_next_insn(INSN *iobj)
LINK_ELEMENT *list = iobj->link.next;
while (list) {
- if (IS_INSN(list) || IS_ADJUST(list)) {
- return list;
- }
- list = list->next;
+ if (IS_INSN(list) || IS_ADJUST(list)) {
+ return list;
+ }
+ list = list->next;
}
return 0;
}
@@ -2661,10 +2782,10 @@ get_prev_insn(INSN *iobj)
LINK_ELEMENT *list = iobj->link.prev;
while (list) {
- if (IS_INSN(list) || IS_ADJUST(list)) {
- return list;
- }
- list = list->prev;
+ if (IS_INSN(list) || IS_ADJUST(list)) {
+ return list;
+ }
+ list = list->prev;
}
return 0;
}
@@ -2694,9 +2815,9 @@ find_destination(INSN *i)
{
int pos, len = insn_len(i->insn_id);
for (pos = 0; pos < len; ++pos) {
- if (insn_op_types(i->insn_id)[pos] == TS_OFFSET) {
- return (LABEL *)OPERAND_AT(i, pos);
- }
+ if (insn_op_types(i->insn_id)[pos] == TS_OFFSET) {
+ return (LABEL *)OPERAND_AT(i, pos);
+ }
}
return 0;
}
@@ -2712,53 +2833,51 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
MEMZERO(unref_counts, int, nlabels);
end = i;
do {
- LABEL *lab;
- if (IS_INSN(i)) {
- if (IS_INSN_ID(i, leave)) {
- end = i;
- break;
- }
- else if ((lab = find_destination((INSN *)i)) != 0) {
- if (lab->unremovable) break;
- unref_counts[lab->label_no]++;
- }
- }
- else if (IS_LABEL(i)) {
- lab = (LABEL *)i;
- if (lab->unremovable) return 0;
- if (lab->refcnt > unref_counts[lab->label_no]) {
- if (i == first) return 0;
- break;
- }
- continue;
- }
- else if (IS_TRACE(i)) {
- /* do nothing */
- }
- else if (IS_ADJUST(i)) {
- LABEL *dest = ((ADJUST *)i)->label;
- if (dest && dest->unremovable) return 0;
- }
- end = i;
+ LABEL *lab;
+ if (IS_INSN(i)) {
+ if (IS_INSN_ID(i, leave)) {
+ end = i;
+ break;
+ }
+ else if ((lab = find_destination((INSN *)i)) != 0) {
+ unref_counts[lab->label_no]++;
+ }
+ }
+ else if (IS_LABEL(i)) {
+ lab = (LABEL *)i;
+ if (lab->unremovable) return 0;
+ if (lab->refcnt > unref_counts[lab->label_no]) {
+ if (i == first) return 0;
+ break;
+ }
+ continue;
+ }
+ else if (IS_TRACE(i)) {
+ /* do nothing */
+ }
+ else if (IS_ADJUST(i)) {
+ return 0;
+ }
+ end = i;
} while ((i = i->next) != 0);
i = first;
do {
- if (IS_INSN(i)) {
- struct rb_iseq_constant_body *body = iseq->body;
- VALUE insn = INSN_OF(i);
- int pos, len = insn_len(insn);
- for (pos = 0; pos < len; ++pos) {
- switch (insn_op_types(insn)[pos]) {
- case TS_OFFSET:
- unref_destination((INSN *)i, pos);
- break;
+ if (IS_INSN(i)) {
+ struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
+ VALUE insn = INSN_OF(i);
+ int pos, len = insn_len(insn);
+ for (pos = 0; pos < len; ++pos) {
+ switch (insn_op_types(insn)[pos]) {
+ case TS_OFFSET:
+ unref_destination((INSN *)i, pos);
+ break;
case TS_CALLDATA:
--(body->ci_size);
- break;
- }
- }
- }
- ELEM_REMOVE(i);
+ break;
+ }
+ }
+ }
+ ELEM_REMOVE(i);
} while ((i != end) && (i = i->next) != 0);
return 1;
}
@@ -2768,14 +2887,14 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj)
{
switch (OPERAND_AT(iobj, 0)) {
case INT2FIX(0): /* empty array */
- ELEM_REMOVE(&iobj->link);
- return TRUE;
+ ELEM_REMOVE(&iobj->link);
+ return TRUE;
case INT2FIX(1): /* single element array */
- ELEM_REMOVE(&iobj->link);
- return FALSE;
+ ELEM_REMOVE(&iobj->link);
+ return FALSE;
default:
- iobj->insn_id = BIN(adjuststack);
- return TRUE;
+ iobj->insn_id = BIN(adjuststack);
+ return TRUE;
}
}
@@ -2824,41 +2943,41 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
switch (INSN_OF(iobj)) {
case BIN(putstring):
- type = INT2FIX(T_STRING);
- break;
+ type = INT2FIX(T_STRING);
+ break;
case BIN(putnil):
- type = INT2FIX(T_NIL);
- break;
+ type = INT2FIX(T_NIL);
+ break;
case BIN(putobject):
- type = INT2FIX(TYPE(OPERAND_AT(iobj, 0)));
- break;
+ type = INT2FIX(TYPE(OPERAND_AT(iobj, 0)));
+ break;
default: return FALSE;
}
ciobj = (INSN *)get_next_insn(iobj);
if (IS_INSN_ID(ciobj, jump)) {
- ciobj = (INSN *)get_next_insn((INSN*)OPERAND_AT(ciobj, 0));
+ ciobj = (INSN *)get_next_insn((INSN*)OPERAND_AT(ciobj, 0));
}
if (IS_INSN_ID(ciobj, dup)) {
- ciobj = (INSN *)get_next_insn(dup = ciobj);
+ ciobj = (INSN *)get_next_insn(dup = ciobj);
}
if (!ciobj || !IS_INSN_ID(ciobj, checktype)) return FALSE;
niobj = (INSN *)get_next_insn(ciobj);
if (!niobj) {
- /* TODO: putobject true/false */
- return FALSE;
+ /* TODO: putobject true/false */
+ return FALSE;
}
switch (INSN_OF(niobj)) {
case BIN(branchif):
- if (OPERAND_AT(ciobj, 0) == type) {
- dest = (LABEL *)OPERAND_AT(niobj, 0);
- }
- break;
+ if (OPERAND_AT(ciobj, 0) == type) {
+ dest = (LABEL *)OPERAND_AT(niobj, 0);
+ }
+ break;
case BIN(branchunless):
- if (OPERAND_AT(ciobj, 0) != type) {
- dest = (LABEL *)OPERAND_AT(niobj, 0);
- }
- break;
+ if (OPERAND_AT(ciobj, 0) != type) {
+ dest = (LABEL *)OPERAND_AT(niobj, 0);
+ }
+ break;
default:
return FALSE;
}
@@ -2866,13 +2985,13 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
node_id = ciobj->insn_info.node_id;
NODE dummy_line_node = generate_dummy_line_node(line, node_id);
if (!dest) {
- if (niobj->link.next && IS_LABEL(niobj->link.next)) {
- dest = (LABEL *)niobj->link.next; /* reuse label */
- }
- else {
- dest = NEW_LABEL(line);
- ELEM_INSERT_NEXT(&niobj->link, &dest->link);
- }
+ if (niobj->link.next && IS_LABEL(niobj->link.next)) {
+ dest = (LABEL *)niobj->link.next; /* reuse label */
+ }
+ else {
+ dest = NEW_LABEL(line);
+ ELEM_INSERT_NEXT(&niobj->link, &dest->link);
+ }
}
INSERT_AFTER_INSN1(iobj, &dummy_line_node, jump, dest);
LABEL_REF(dest);
@@ -2912,112 +3031,112 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
if (IS_INSN_ID(iobj, jump)) {
INSN *niobj, *diobj, *piobj;
- diobj = (INSN *)get_destination_insn(iobj);
- niobj = (INSN *)get_next_insn(iobj);
-
- if (diobj == niobj) {
- /*
- * jump LABEL
- * LABEL:
- * =>
- * LABEL:
- */
- unref_destination(iobj, 0);
- ELEM_REMOVE(&iobj->link);
- return COMPILE_OK;
- }
+ diobj = (INSN *)get_destination_insn(iobj);
+ niobj = (INSN *)get_next_insn(iobj);
+
+ if (diobj == niobj) {
+ /*
+ * jump LABEL
+ * LABEL:
+ * =>
+ * LABEL:
+ */
+ unref_destination(iobj, 0);
+ ELEM_REMOVE(&iobj->link);
+ return COMPILE_OK;
+ }
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
- * ...
- * LABEL1:
- * jump LABEL2
- *
- * => in this case, first jump instruction should jump to
- * LABEL2 directly
- */
- replace_destination(iobj, diobj);
- remove_unreachable_chunk(iseq, iobj->link.next);
- goto again;
- }
+ /*
+ * useless jump elimination:
+ * jump LABEL1
+ * ...
+ * LABEL1:
+ * jump LABEL2
+ *
+ * => in this case, first jump instruction should jump to
+ * LABEL2 directly
+ */
+ replace_destination(iobj, diobj);
+ remove_unreachable_chunk(iseq, iobj->link.next);
+ goto again;
+ }
else if (IS_INSN_ID(diobj, leave)) {
- /*
- * jump LABEL
- * ...
- * LABEL:
- * leave
- * =>
- * leave
- * ...
- * LABEL:
- * leave
- */
- /* replace */
- unref_destination(iobj, 0);
+ /*
+ * jump LABEL
+ * ...
+ * LABEL:
+ * leave
+ * =>
+ * leave
+ * ...
+ * LABEL:
+ * leave
+ */
+ /* replace */
+ unref_destination(iobj, 0);
iobj->insn_id = BIN(leave);
- iobj->operand_size = 0;
- iobj->insn_info = diobj->insn_info;
- goto again;
- }
+ iobj->operand_size = 0;
+ iobj->insn_info = diobj->insn_info;
+ goto again;
+ }
else if (IS_INSN(iobj->link.prev) &&
(piobj = (INSN *)iobj->link.prev) &&
- (IS_INSN_ID(piobj, branchif) ||
- IS_INSN_ID(piobj, branchunless))) {
- INSN *pdiobj = (INSN *)get_destination_insn(piobj);
- if (niobj == pdiobj) {
- int refcnt = IS_LABEL(piobj->link.next) ?
- ((LABEL *)piobj->link.next)->refcnt : 0;
- /*
- * useless jump elimination (if/unless destination):
- * if L1
- * jump L2
- * L1:
- * ...
- * L2:
- *
- * ==>
- * unless L2
- * L1:
- * ...
- * L2:
- */
- piobj->insn_id = (IS_INSN_ID(piobj, branchif))
- ? BIN(branchunless) : BIN(branchif);
- replace_destination(piobj, iobj);
- if (refcnt <= 1) {
- ELEM_REMOVE(&iobj->link);
- }
- else {
- /* TODO: replace other branch destinations too */
- }
- return COMPILE_OK;
- }
- else if (diobj == pdiobj) {
- /*
- * useless jump elimination (if/unless before jump):
- * L1:
- * ...
- * if L1
- * jump L1
- *
- * ==>
- * L1:
- * ...
- * pop
- * jump L1
- */
+ (IS_INSN_ID(piobj, branchif) ||
+ IS_INSN_ID(piobj, branchunless))) {
+ INSN *pdiobj = (INSN *)get_destination_insn(piobj);
+ if (niobj == pdiobj) {
+ int refcnt = IS_LABEL(piobj->link.next) ?
+ ((LABEL *)piobj->link.next)->refcnt : 0;
+ /*
+ * useless jump elimination (if/unless destination):
+ * if L1
+ * jump L2
+ * L1:
+ * ...
+ * L2:
+ *
+ * ==>
+ * unless L2
+ * L1:
+ * ...
+ * L2:
+ */
+ piobj->insn_id = (IS_INSN_ID(piobj, branchif))
+ ? BIN(branchunless) : BIN(branchif);
+ replace_destination(piobj, iobj);
+ if (refcnt <= 1) {
+ ELEM_REMOVE(&iobj->link);
+ }
+ else {
+ /* TODO: replace other branch destinations too */
+ }
+ return COMPILE_OK;
+ }
+ else if (diobj == pdiobj) {
+ /*
+ * useless jump elimination (if/unless before jump):
+ * L1:
+ * ...
+ * if L1
+ * jump L1
+ *
+ * ==>
+ * L1:
+ * ...
+ * pop
+ * jump L1
+ */
NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
- INSN *popiobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, 0);
- ELEM_REPLACE(&piobj->link, &popiobj->link);
- }
- }
- if (remove_unreachable_chunk(iseq, iobj->link.next)) {
- goto again;
- }
+ INSN *popiobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, 0);
+ ELEM_REPLACE(&piobj->link, &popiobj->link);
+ }
+ }
+ if (remove_unreachable_chunk(iseq, iobj->link.next)) {
+ goto again;
+ }
}
/*
@@ -3038,33 +3157,49 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
is_frozen_putstring(end, &str_end) &&
(beg = (INSN *)get_prev_insn(end)) != 0 &&
is_frozen_putstring(beg, &str_beg)) {
- int excl = FIX2INT(OPERAND_AT(range, 0));
- VALUE lit_range = rb_range_new(str_beg, str_end, excl);
-
- ELEM_REMOVE(&beg->link);
- ELEM_REMOVE(&end->link);
- range->insn_id = BIN(putobject);
- OPERAND_AT(range, 0) = lit_range;
- RB_OBJ_WRITTEN(iseq, Qundef, lit_range);
- }
+ int excl = FIX2INT(OPERAND_AT(range, 0));
+ VALUE lit_range = rb_range_new(str_beg, str_end, excl);
+
+ ELEM_REMOVE(&beg->link);
+ ELEM_REMOVE(&end->link);
+ range->insn_id = BIN(putobject);
+ OPERAND_AT(range, 0) = lit_range;
+ RB_OBJ_WRITTEN(iseq, Qundef, lit_range);
+ }
}
if (IS_INSN_ID(iobj, leave)) {
- remove_unreachable_chunk(iseq, iobj->link.next);
+ remove_unreachable_chunk(iseq, iobj->link.next);
+ }
+
+ /*
+ * ...
+ * duparray [...]
+ * concatarray
+ * =>
+ * ...
+ * putobject [...]
+ * concatarray
+ */
+ if (IS_INSN_ID(iobj, duparray)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) {
+ iobj->insn_id = BIN(putobject);
+ }
}
if (IS_INSN_ID(iobj, branchif) ||
- IS_INSN_ID(iobj, branchnil) ||
- IS_INSN_ID(iobj, branchunless)) {
- /*
- * if L1
- * ...
- * L1:
- * jump L2
- * =>
- * if L2
- */
- INSN *nobj = (INSN *)get_destination_insn(iobj);
+ IS_INSN_ID(iobj, branchnil) ||
+ IS_INSN_ID(iobj, branchunless)) {
+ /*
+ * if L1
+ * ...
+ * L1:
+ * jump L2
+ * =>
+ * if L2
+ */
+ INSN *nobj = (INSN *)get_destination_insn(iobj);
/* This is super nasty hack!!!
*
@@ -3087,10 +3222,10 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* This should be fixed in future.
*/
int stop_optimization =
- ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq) &&
+ ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq) &&
nobj->link.type == ISEQ_ELEMENT_INSN &&
nobj->insn_info.events;
- if (!stop_optimization) {
+ if (!stop_optimization) {
INSN *pobj = (INSN *)iobj->link.prev;
int prev_dup = 0;
if (pobj) {
@@ -3200,231 +3335,344 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
if (IS_INSN_ID(iobj, pop)) {
- /*
- * putself / putnil / putobject obj / putstring "..."
- * pop
- * =>
- * # do nothing
- */
- LINK_ELEMENT *prev = iobj->link.prev;
- if (IS_INSN(prev)) {
- enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id;
- if (previ == BIN(putobject) || previ == BIN(putnil) ||
- previ == BIN(putself) || previ == BIN(putstring) ||
- previ == BIN(dup) ||
- previ == BIN(getlocal) ||
- previ == BIN(getblockparam) ||
- previ == BIN(getblockparamproxy) ||
- /* getinstancevariable may issue a warning */
- previ == BIN(duparray)) {
- /* just push operand or static value and pop soon, no
- * side effects */
- ELEM_REMOVE(prev);
- ELEM_REMOVE(&iobj->link);
- }
- else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (INSN*)prev)) {
- ELEM_REMOVE(&iobj->link);
- }
- else if (previ == BIN(concatarray)) {
- INSN *piobj = (INSN *)prev;
+ /*
+ * putself / putnil / putobject obj / putstring "..."
+ * pop
+ * =>
+ * # do nothing
+ */
+ LINK_ELEMENT *prev = iobj->link.prev;
+ if (IS_INSN(prev)) {
+ enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id;
+ if (previ == BIN(putobject) || previ == BIN(putnil) ||
+ previ == BIN(putself) || previ == BIN(putstring) ||
+ previ == BIN(dup) ||
+ previ == BIN(getlocal) ||
+ previ == BIN(getblockparam) ||
+ previ == BIN(getblockparamproxy) ||
+ /* getinstancevariable may issue a warning */
+ previ == BIN(duparray)) {
+ /* just push operand or static value and pop soon, no
+ * side effects */
+ ELEM_REMOVE(prev);
+ ELEM_REMOVE(&iobj->link);
+ }
+ else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (INSN*)prev)) {
+ ELEM_REMOVE(&iobj->link);
+ }
+ else if (previ == BIN(concatarray)) {
+ INSN *piobj = (INSN *)prev;
NODE dummy_line_node = generate_dummy_line_node(piobj->insn_info.line_no, piobj->insn_info.node_id);
- INSERT_BEFORE_INSN1(piobj, &dummy_line_node, splatarray, Qfalse);
- INSN_OF(piobj) = BIN(pop);
- }
- else if (previ == BIN(concatstrings)) {
- if (OPERAND_AT(prev, 0) == INT2FIX(1)) {
- ELEM_REMOVE(prev);
- }
- else {
- ELEM_REMOVE(&iobj->link);
- INSN_OF(prev) = BIN(adjuststack);
- }
- }
- }
+ INSERT_BEFORE_INSN1(piobj, &dummy_line_node, splatarray, Qfalse);
+ INSN_OF(piobj) = BIN(pop);
+ }
+ else if (previ == BIN(concatstrings)) {
+ if (OPERAND_AT(prev, 0) == INT2FIX(1)) {
+ ELEM_REMOVE(prev);
+ }
+ else {
+ ELEM_REMOVE(&iobj->link);
+ INSN_OF(prev) = BIN(adjuststack);
+ }
+ }
+ }
}
if (IS_INSN_ID(iobj, newarray) ||
- IS_INSN_ID(iobj, duparray) ||
- IS_INSN_ID(iobj, expandarray) ||
- IS_INSN_ID(iobj, concatarray) ||
- IS_INSN_ID(iobj, splatarray) ||
- 0) {
- /*
- * newarray N
- * splatarray
- * =>
- * newarray N
- * newarray always puts an array
- */
- LINK_ELEMENT *next = iobj->link.next;
- if (IS_INSN(next) && IS_INSN_ID(next, splatarray)) {
- /* remove splatarray following always-array insn */
- ELEM_REMOVE(next);
- }
- }
-
- if (IS_INSN_ID(iobj, tostring)) {
- LINK_ELEMENT *next = iobj->link.next;
- /*
- * tostring
- * concatstrings 1
- * =>
- * tostring
- */
- if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
- OPERAND_AT(next, 0) == INT2FIX(1)) {
- ELEM_REMOVE(next);
- }
+ IS_INSN_ID(iobj, duparray) ||
+ IS_INSN_ID(iobj, expandarray) ||
+ IS_INSN_ID(iobj, concatarray) ||
+ IS_INSN_ID(iobj, splatarray) ||
+ 0) {
+ /*
+ * newarray N
+ * splatarray
+ * =>
+ * newarray N
+ * newarray always puts an array
+ */
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && IS_INSN_ID(next, splatarray)) {
+ /* remove splatarray following always-array insn */
+ ELEM_REMOVE(next);
+ }
+ }
+
+ if (IS_INSN_ID(iobj, newarray)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && IS_INSN_ID(next, expandarray) &&
+ OPERAND_AT(next, 1) == INT2FIX(0)) {
+ VALUE op1, op2;
+ op1 = OPERAND_AT(iobj, 0);
+ op2 = OPERAND_AT(next, 0);
+ ELEM_REMOVE(next);
+
+ if (op1 == op2) {
+ /*
+ * newarray 2
+ * expandarray 2, 0
+ * =>
+ * swap
+ */
+ if (op1 == INT2FIX(2)) {
+ INSN_OF(iobj) = BIN(swap);
+ iobj->operand_size = 0;
+ }
+ /*
+ * newarray X
+ * expandarray X, 0
+ * =>
+ * opt_reverse X
+ */
+ else {
+ INSN_OF(iobj) = BIN(opt_reverse);
+ }
+ }
+ else {
+ NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
+ long diff = FIX2LONG(op1) - FIX2LONG(op2);
+ INSN_OF(iobj) = BIN(opt_reverse);
+ OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0);
+
+ if (op1 > op2) {
+ /* X > Y
+ * newarray X
+ * expandarray Y, 0
+ * =>
+ * pop * (Y-X)
+ * opt_reverse Y
+ */
+ for (; diff > 0; diff--) {
+ INSERT_BEFORE_INSN(iobj, &dummy_line_node, pop);
+ }
+ }
+ else { /* (op1 < op2) */
+ /* X < Y
+ * newarray X
+ * expandarray Y, 0
+ * =>
+ * putnil * (Y-X)
+ * opt_reverse Y
+ */
+ for (; diff < 0; diff++) {
+ INSERT_BEFORE_INSN(iobj, &dummy_line_node, putnil);
+ }
+ }
+ }
+ }
+ }
+
+ if (IS_INSN_ID(iobj, duparray)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ /*
+ * duparray obj
+ * expandarray X, 0
+ * =>
+ * putobject obj
+ * expandarray X, 0
+ */
+ if (IS_INSN(next) && IS_INSN_ID(next, expandarray)) {
+ INSN_OF(iobj) = BIN(putobject);
+ }
+ }
+
+ if (IS_INSN_ID(iobj, anytostring)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ /*
+ * anytostring
+ * concatstrings 1
+ * =>
+ * anytostring
+ */
+ if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
+ OPERAND_AT(next, 0) == INT2FIX(1)) {
+ ELEM_REMOVE(next);
+ }
}
if (IS_INSN_ID(iobj, putstring) ||
- (IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0), T_STRING))) {
- /*
- * putstring ""
- * concatstrings N
- * =>
- * concatstrings N-1
- */
- if (IS_NEXT_INSN_ID(&iobj->link, concatstrings) &&
- RSTRING_LEN(OPERAND_AT(iobj, 0)) == 0) {
- INSN *next = (INSN *)iobj->link.next;
- if ((OPERAND_AT(next, 0) = FIXNUM_INC(OPERAND_AT(next, 0), -1)) == INT2FIX(1)) {
- ELEM_REMOVE(&next->link);
- }
- ELEM_REMOVE(&iobj->link);
- }
+ (IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0), T_STRING))) {
+ /*
+ * putstring ""
+ * concatstrings N
+ * =>
+ * concatstrings N-1
+ */
+ if (IS_NEXT_INSN_ID(&iobj->link, concatstrings) &&
+ RSTRING_LEN(OPERAND_AT(iobj, 0)) == 0) {
+ INSN *next = (INSN *)iobj->link.next;
+ if ((OPERAND_AT(next, 0) = FIXNUM_INC(OPERAND_AT(next, 0), -1)) == INT2FIX(1)) {
+ ELEM_REMOVE(&next->link);
+ }
+ ELEM_REMOVE(&iobj->link);
+ }
}
if (IS_INSN_ID(iobj, concatstrings)) {
- /*
- * concatstrings N
- * concatstrings M
- * =>
- * concatstrings N+M-1
- */
- LINK_ELEMENT *next = iobj->link.next;
- INSN *jump = 0;
- 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)) {
- int n = FIX2INT(OPERAND_AT(iobj, 0)) + FIX2INT(OPERAND_AT(next, 0)) - 1;
- OPERAND_AT(iobj, 0) = INT2FIX(n);
- if (jump) {
- LABEL *label = ((LABEL *)OPERAND_AT(jump, 0));
- if (!--label->refcnt) {
- ELEM_REMOVE(&label->link);
- }
- else {
- label = NEW_LABEL(0);
- OPERAND_AT(jump, 0) = (VALUE)label;
- }
- label->refcnt++;
- ELEM_INSERT_NEXT(next, &label->link);
- CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt));
- }
- else {
- ELEM_REMOVE(next);
- }
- }
+ /*
+ * concatstrings N
+ * concatstrings M
+ * =>
+ * concatstrings N+M-1
+ */
+ LINK_ELEMENT *next = iobj->link.next;
+ INSN *jump = 0;
+ 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)) {
+ int n = FIX2INT(OPERAND_AT(iobj, 0)) + FIX2INT(OPERAND_AT(next, 0)) - 1;
+ OPERAND_AT(iobj, 0) = INT2FIX(n);
+ if (jump) {
+ LABEL *label = ((LABEL *)OPERAND_AT(jump, 0));
+ if (!--label->refcnt) {
+ ELEM_REMOVE(&label->link);
+ }
+ else {
+ label = NEW_LABEL(0);
+ OPERAND_AT(jump, 0) = (VALUE)label;
+ }
+ label->refcnt++;
+ ELEM_INSERT_NEXT(next, &label->link);
+ CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt));
+ }
+ else {
+ ELEM_REMOVE(next);
+ }
+ }
}
if (do_tailcallopt &&
- (IS_INSN_ID(iobj, send) ||
- IS_INSN_ID(iobj, opt_aref_with) ||
- IS_INSN_ID(iobj, opt_aset_with) ||
- IS_INSN_ID(iobj, invokesuper))) {
- /*
- * send ...
- * leave
- * =>
- * send ..., ... | VM_CALL_TAILCALL, ...
- * leave # unreachable
- */
- INSN *piobj = NULL;
- if (iobj->link.next) {
- LINK_ELEMENT *next = iobj->link.next;
- do {
- if (!IS_INSN(next)) {
- next = next->next;
- continue;
- }
- switch (INSN_OF(next)) {
- case BIN(nop):
- next = next->next;
- break;
- case BIN(jump):
- /* if cond
- * return tailcall
- * end
- */
- next = get_destination_insn((INSN *)next);
- break;
- case BIN(leave):
- piobj = iobj;
+ (IS_INSN_ID(iobj, send) ||
+ IS_INSN_ID(iobj, opt_aref_with) ||
+ IS_INSN_ID(iobj, opt_aset_with) ||
+ IS_INSN_ID(iobj, invokesuper))) {
+ /*
+ * send ...
+ * leave
+ * =>
+ * send ..., ... | VM_CALL_TAILCALL, ...
+ * leave # unreachable
+ */
+ INSN *piobj = NULL;
+ if (iobj->link.next) {
+ LINK_ELEMENT *next = iobj->link.next;
+ do {
+ if (!IS_INSN(next)) {
+ next = next->next;
+ continue;
+ }
+ switch (INSN_OF(next)) {
+ case BIN(nop):
+ next = next->next;
+ break;
+ case BIN(jump):
+ /* if cond
+ * return tailcall
+ * end
+ */
+ next = get_destination_insn((INSN *)next);
+ break;
+ case BIN(leave):
+ piobj = iobj;
/* fall through */
- default:
- next = NULL;
- break;
- }
- } while (next);
- }
-
- if (piobj) {
+ default:
+ next = NULL;
+ break;
+ }
+ } while (next);
+ }
+
+ if (piobj) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(piobj, 0);
- if (IS_INSN_ID(piobj, send) ||
+ if (IS_INSN_ID(piobj, send) ||
IS_INSN_ID(piobj, invokesuper)) {
if (OPERAND_AT(piobj, 1) == 0) { /* no blockiseq */
ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
OPERAND_AT(piobj, 0) = (VALUE)ci;
RB_OBJ_WRITTEN(iseq, Qundef, ci);
- }
- }
- else {
+ }
+ }
+ else {
ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
OPERAND_AT(piobj, 0) = (VALUE)ci;
RB_OBJ_WRITTEN(iseq, Qundef, ci);
- }
- }
+ }
+ }
}
if (IS_INSN_ID(iobj, dup)) {
- if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
- LINK_ELEMENT *set1 = iobj->link.next, *set2 = NULL;
- if (IS_NEXT_INSN_ID(set1, setlocal)) {
- set2 = set1->next;
- if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
- OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
- ELEM_REMOVE(set1);
- ELEM_REMOVE(&iobj->link);
- }
- }
- else if (IS_NEXT_INSN_ID(set1, dup) &&
- IS_NEXT_INSN_ID(set1->next, setlocal)) {
- set2 = set1->next->next;
- if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
- OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
- ELEM_REMOVE(set1->next);
- ELEM_REMOVE(set2);
- }
- }
- }
+ if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
+ LINK_ELEMENT *set1 = iobj->link.next, *set2 = NULL;
+
+ /*
+ * dup
+ * setlocal x, y
+ * setlocal x, y
+ * =>
+ * dup
+ * setlocal x, y
+ */
+ if (IS_NEXT_INSN_ID(set1, setlocal)) {
+ set2 = set1->next;
+ if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
+ OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
+ ELEM_REMOVE(set1);
+ ELEM_REMOVE(&iobj->link);
+ }
+ }
+
+ /*
+ * dup
+ * setlocal x, y
+ * dup
+ * setlocal x, y
+ * =>
+ * dup
+ * setlocal x, y
+ */
+ else if (IS_NEXT_INSN_ID(set1, dup) &&
+ IS_NEXT_INSN_ID(set1->next, setlocal)) {
+ set2 = set1->next->next;
+ if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
+ OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
+ ELEM_REMOVE(set1->next);
+ ELEM_REMOVE(set2);
+ }
+ }
+ }
}
+ /*
+ * getlocal x, y
+ * dup
+ * setlocal x, y
+ * =>
+ * dup
+ */
if (IS_INSN_ID(iobj, getlocal)) {
- LINK_ELEMENT *niobj = &iobj->link;
- if (IS_NEXT_INSN_ID(niobj, dup)) {
- niobj = niobj->next;
- }
- if (IS_NEXT_INSN_ID(niobj, setlocal)) {
- LINK_ELEMENT *set1 = niobj->next;
- if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) &&
- OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) {
- ELEM_REMOVE(set1);
- ELEM_REMOVE(niobj);
- }
- }
+ LINK_ELEMENT *niobj = &iobj->link;
+ if (IS_NEXT_INSN_ID(niobj, dup)) {
+ niobj = niobj->next;
+ }
+ if (IS_NEXT_INSN_ID(niobj, setlocal)) {
+ LINK_ELEMENT *set1 = niobj->next;
+ if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) &&
+ OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) {
+ ELEM_REMOVE(set1);
+ ELEM_REMOVE(niobj);
+ }
+ }
}
+ /*
+ * opt_invokebuiltin_delegate
+ * trace
+ * leave
+ * =>
+ * opt_invokebuiltin_delegate_leave
+ * trace
+ * leave
+ */
if (IS_INSN_ID(iobj, opt_invokebuiltin_delegate)) {
if (IS_TRACE(iobj->link.next)) {
if (IS_NEXT_INSN_ID(iobj->link.next, leave)) {
@@ -3433,6 +3681,19 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
+ /*
+ * getblockparam
+ * branchif / branchunless
+ * =>
+ * getblockparamproxy
+ * branchif / branchunless
+ */
+ if (IS_INSN_ID(iobj, getblockparam)) {
+ if (IS_NEXT_INSN_ID(&iobj->link, branchif) || IS_NEXT_INSN_ID(&iobj->link, branchunless)) {
+ iobj->insn_id = BIN(getblockparamproxy);
+ }
+ }
+
return COMPILE_OK;
}
@@ -3441,6 +3702,7 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
{
iobj->insn_id = insn_id;
iobj->operand_size = insn_len(insn_id) - 1;
+ iobj->insn_info.events |= RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN;
if (insn_id == BIN(opt_neq)) {
VALUE original_ci = iobj->operands[0];
@@ -3457,26 +3719,26 @@ static int
iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
{
if (IS_INSN_ID(iobj, newarray) && iobj->link.next &&
- IS_INSN(iobj->link.next)) {
- /*
- * [a, b, ...].max/min -> a, b, c, opt_newarray_max/min
- */
- INSN *niobj = (INSN *)iobj->link.next;
- if (IS_INSN_ID(niobj, send)) {
+ IS_INSN(iobj->link.next)) {
+ /*
+ * [a, b, ...].max/min -> a, b, c, opt_newarray_max/min
+ */
+ INSN *niobj = (INSN *)iobj->link.next;
+ if (IS_INSN_ID(niobj, send)) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0);
if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
- switch (vm_ci_mid(ci)) {
- case idMax:
- iobj->insn_id = BIN(opt_newarray_max);
- ELEM_REMOVE(&niobj->link);
- return COMPILE_OK;
- case idMin:
- iobj->insn_id = BIN(opt_newarray_min);
- ELEM_REMOVE(&niobj->link);
- return COMPILE_OK;
- }
- }
- }
+ switch (vm_ci_mid(ci)) {
+ case idMax:
+ iobj->insn_id = BIN(opt_newarray_max);
+ ELEM_REMOVE(&niobj->link);
+ return COMPILE_OK;
+ case idMin:
+ iobj->insn_id = BIN(opt_newarray_min);
+ ELEM_REMOVE(&niobj->link);
+ return COMPILE_OK;
+ }
+ }
+ }
}
if (IS_INSN_ID(iobj, send)) {
@@ -3484,50 +3746,50 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1);
#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
- if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
- switch (vm_ci_argc(ci)) {
- case 0:
- 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;
+ if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
+ switch (vm_ci_argc(ci)) {
+ case 0:
+ 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;
case idNilP: SP_INSN(nil_p); return COMPILE_OK;
- case idSucc: SP_INSN(succ); return COMPILE_OK;
- case idNot: SP_INSN(not); return COMPILE_OK;
- }
- break;
- case 1:
- 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;
- case idDIV: SP_INSN(div); return COMPILE_OK;
- case idMOD: SP_INSN(mod); return COMPILE_OK;
- case idEq: SP_INSN(eq); return COMPILE_OK;
- case idNeq: SP_INSN(neq); return COMPILE_OK;
- case idEqTilde:SP_INSN(regexpmatch2);return COMPILE_OK;
- case idLT: SP_INSN(lt); return COMPILE_OK;
- case idLE: SP_INSN(le); return COMPILE_OK;
- case idGT: SP_INSN(gt); return COMPILE_OK;
- case idGE: SP_INSN(ge); return COMPILE_OK;
- case idLTLT: SP_INSN(ltlt); return COMPILE_OK;
- case idAREF: SP_INSN(aref); return COMPILE_OK;
+ case idSucc: SP_INSN(succ); return COMPILE_OK;
+ case idNot: SP_INSN(not); return COMPILE_OK;
+ }
+ break;
+ case 1:
+ 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;
+ case idDIV: SP_INSN(div); return COMPILE_OK;
+ case idMOD: SP_INSN(mod); return COMPILE_OK;
+ case idEq: SP_INSN(eq); return COMPILE_OK;
+ case idNeq: SP_INSN(neq); return COMPILE_OK;
+ case idEqTilde:SP_INSN(regexpmatch2);return COMPILE_OK;
+ case idLT: SP_INSN(lt); return COMPILE_OK;
+ case idLE: SP_INSN(le); return COMPILE_OK;
+ case idGT: SP_INSN(gt); return COMPILE_OK;
+ case idGE: SP_INSN(ge); return COMPILE_OK;
+ case idLTLT: SP_INSN(ltlt); return COMPILE_OK;
+ case idAREF: SP_INSN(aref); return COMPILE_OK;
case idAnd: SP_INSN(and); return COMPILE_OK;
case idOr: SP_INSN(or); return COMPILE_OK;
- }
- break;
- case 2:
- switch (vm_ci_mid(ci)) {
- case idASET: SP_INSN(aset); return COMPILE_OK;
- }
- break;
- }
- }
-
- 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;
- }
+ }
+ break;
+ case 2:
+ switch (vm_ci_mid(ci)) {
+ case idASET: SP_INSN(aset); return COMPILE_OK;
+ }
+ break;
+ }
+ }
+
+ 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;
+ }
}
#undef SP_INSN
@@ -3537,17 +3799,17 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
static inline int
tailcallable_p(rb_iseq_t *iseq)
{
- switch (iseq->body->type) {
+ switch (ISEQ_BODY(iseq)->type) {
case ISEQ_TYPE_TOP:
case ISEQ_TYPE_EVAL:
case ISEQ_TYPE_MAIN:
- /* not tail callable because cfp will be over popped */
+ /* not tail callable because cfp will be over popped */
case ISEQ_TYPE_RESCUE:
case ISEQ_TYPE_ENSURE:
- /* rescue block can't tail call because of errinfo */
- return FALSE;
+ /* rescue block can't tail call because of errinfo */
+ return FALSE;
default:
- return TRUE;
+ return TRUE;
}
}
@@ -3557,7 +3819,7 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
LINK_ELEMENT *list;
const int do_peepholeopt = ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
const int do_tailcallopt = tailcallable_p(iseq) &&
- ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
+ ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
const int do_si = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction;
const int do_ou = ISEQ_COMPILE_DATA(iseq)->option->operands_unification;
int rescue_level = 0;
@@ -3567,21 +3829,21 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
int do_block_optimization = 0;
- if (iseq->body->type == ISEQ_TYPE_BLOCK && !iseq->body->catch_except_p) {
+ if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_BLOCK && !ISEQ_BODY(iseq)->catch_except_p) {
do_block_optimization = 1;
}
while (list) {
- if (IS_INSN(list)) {
- if (do_peepholeopt) {
- iseq_peephole_optimize(iseq, list, tailcallopt);
- }
- if (do_si) {
- iseq_specialized_instruction(iseq, (INSN *)list);
- }
- if (do_ou) {
- insn_operands_unification((INSN *)list);
- }
+ if (IS_INSN(list)) {
+ if (do_peepholeopt) {
+ iseq_peephole_optimize(iseq, list, tailcallopt);
+ }
+ if (do_si) {
+ iseq_specialized_instruction(iseq, (INSN *)list);
+ }
+ if (do_ou) {
+ insn_operands_unification((INSN *)list);
+ }
if (do_block_optimization) {
INSN * item = (INSN *)list;
@@ -3589,19 +3851,19 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
do_block_optimization = 0;
}
}
- }
- if (IS_LABEL(list)) {
- switch (((LABEL *)list)->rescued) {
- case LABEL_RESCUE_BEG:
- rescue_level++;
- tailcallopt = FALSE;
- break;
- case LABEL_RESCUE_END:
- if (!--rescue_level) tailcallopt = do_tailcallopt;
- break;
- }
- }
- list = list->next;
+ }
+ if (IS_LABEL(list)) {
+ switch (((LABEL *)list)->rescued) {
+ case LABEL_RESCUE_BEG:
+ rescue_level++;
+ tailcallopt = FALSE;
+ break;
+ case LABEL_RESCUE_END:
+ if (!--rescue_level) tailcallopt = do_tailcallopt;
+ break;
+ }
+ }
+ list = list->next;
}
if (do_block_optimization) {
@@ -3616,7 +3878,7 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
#if OPT_INSTRUCTIONS_UNIFICATION
static INSN *
new_unified_insn(rb_iseq_t *iseq,
- int insn_id, int size, LINK_ELEMENT *seq_list)
+ int insn_id, int size, LINK_ELEMENT *seq_list)
{
INSN *iobj = 0;
LINK_ELEMENT *list = seq_list;
@@ -3626,22 +3888,22 @@ new_unified_insn(rb_iseq_t *iseq,
/* count argc */
for (i = 0; i < size; i++) {
- iobj = (INSN *)list;
- argc += iobj->operand_size;
- list = list->next;
+ iobj = (INSN *)list;
+ argc += iobj->operand_size;
+ list = list->next;
}
if (argc > 0) {
- ptr = operands = compile_data_alloc2(iseq, sizeof(VALUE), argc);
+ ptr = operands = compile_data_alloc2(iseq, sizeof(VALUE), argc);
}
/* copy operands */
list = seq_list;
for (i = 0; i < size; i++) {
- iobj = (INSN *)list;
- MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size);
- ptr += iobj->operand_size;
- list = list->next;
+ iobj = (INSN *)list;
+ MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size);
+ ptr += iobj->operand_size;
+ list = list->next;
}
NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
@@ -3665,41 +3927,41 @@ iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
list = FIRST_ELEMENT(anchor);
while (list) {
- if (IS_INSN(list)) {
- iobj = (INSN *)list;
- id = iobj->insn_id;
- if (unified_insns_data[id] != 0) {
- const int *const *entry = unified_insns_data[id];
- for (j = 1; j < (intptr_t)entry[0]; j++) {
- const int *unified = entry[j];
- LINK_ELEMENT *li = list->next;
- for (k = 2; k < unified[1]; k++) {
- if (!IS_INSN(li) ||
- ((INSN *)li)->insn_id != unified[k]) {
- goto miss;
- }
- li = li->next;
- }
- /* matched */
- niobj =
- new_unified_insn(iseq, unified[0], unified[1] - 1,
- list);
-
- /* insert to list */
- niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev;
- niobj->link.next = li;
- if (li) {
- li->prev = (LINK_ELEMENT *)niobj;
- }
-
- list->prev->next = (LINK_ELEMENT *)niobj;
- list = (LINK_ELEMENT *)niobj;
- break;
- miss:;
- }
- }
- }
- list = list->next;
+ if (IS_INSN(list)) {
+ iobj = (INSN *)list;
+ id = iobj->insn_id;
+ if (unified_insns_data[id] != 0) {
+ const int *const *entry = unified_insns_data[id];
+ for (j = 1; j < (intptr_t)entry[0]; j++) {
+ const int *unified = entry[j];
+ LINK_ELEMENT *li = list->next;
+ for (k = 2; k < unified[1]; k++) {
+ if (!IS_INSN(li) ||
+ ((INSN *)li)->insn_id != unified[k]) {
+ goto miss;
+ }
+ li = li->next;
+ }
+ /* matched */
+ niobj =
+ new_unified_insn(iseq, unified[0], unified[1] - 1,
+ list);
+
+ /* insert to list */
+ niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev;
+ niobj->link.next = li;
+ if (li) {
+ li->prev = (LINK_ELEMENT *)niobj;
+ }
+
+ list->prev->next = (LINK_ELEMENT *)niobj;
+ list = (LINK_ELEMENT *)niobj;
+ break;
+ miss:;
+ }
+ }
+ }
+ list = list->next;
}
#endif
return COMPILE_OK;
@@ -3723,28 +3985,28 @@ insn_set_sc_state(rb_iseq_t *iseq, const LINK_ELEMENT *anchor, INSN *iobj, int s
nstate = SC_NEXT(iobj->insn_id);
if (insn_id == BIN(jump) ||
- insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
- LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
-
- if (lobj->sc_state != 0) {
- if (lobj->sc_state != nstate) {
- BADINSN_DUMP(anchor, iobj, lobj);
- COMPILE_ERROR(iseq, iobj->insn_info.line_no,
- "insn_set_sc_state error: %d at "LABEL_FORMAT
- ", %d expected\n",
- lobj->sc_state, lobj->label_no, nstate);
- return COMPILE_NG;
- }
- }
- else {
- lobj->sc_state = nstate;
- }
- if (insn_id == BIN(jump)) {
- nstate = SCS_XX;
- }
+ insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
+ LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
+
+ if (lobj->sc_state != 0) {
+ if (lobj->sc_state != nstate) {
+ BADINSN_DUMP(anchor, iobj, lobj);
+ COMPILE_ERROR(iseq, iobj->insn_info.line_no,
+ "insn_set_sc_state error: %d at "LABEL_FORMAT
+ ", %d expected\n",
+ lobj->sc_state, lobj->label_no, nstate);
+ return COMPILE_NG;
+ }
+ }
+ else {
+ lobj->sc_state = nstate;
+ }
+ if (insn_id == BIN(jump)) {
+ nstate = SCS_XX;
+ }
}
else if (insn_id == BIN(leave)) {
- nstate = SCS_XX;
+ nstate = SCS_XX;
}
return nstate;
@@ -3754,12 +4016,12 @@ static int
label_set_sc_state(LABEL *lobj, int state)
{
if (lobj->sc_state != 0) {
- if (lobj->sc_state != state) {
- state = lobj->sc_state;
- }
+ if (lobj->sc_state != state) {
+ state = lobj->sc_state;
+ }
}
else {
- lobj->sc_state = state;
+ lobj->sc_state = state;
}
return state;
@@ -3783,84 +4045,84 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
/* for each list element */
while (list) {
redo_point:
- switch (list->type) {
- case ISEQ_ELEMENT_INSN:
- {
- INSN *iobj = (INSN *)list;
- insn_id = iobj->insn_id;
-
- /* dump_disasm_list(list); */
-
- switch (insn_id) {
- case BIN(nop):
- {
- /* exception merge point */
- if (state != SCS_AX) {
+ switch (list->type) {
+ case ISEQ_ELEMENT_INSN:
+ {
+ INSN *iobj = (INSN *)list;
+ insn_id = iobj->insn_id;
+
+ /* dump_disasm_list(list); */
+
+ switch (insn_id) {
+ case BIN(nop):
+ {
+ /* exception merge point */
+ if (state != SCS_AX) {
NODE dummy_line_node = generate_dummy_line_node(0, -1);
- INSN *rpobj =
- new_insn_body(iseq, &dummy_line_node, BIN(reput), 0);
-
- /* replace this insn */
- ELEM_REPLACE(list, (LINK_ELEMENT *)rpobj);
- list = (LINK_ELEMENT *)rpobj;
- goto redo_point;
- }
- break;
- }
- case BIN(swap):
- {
- if (state == SCS_AB || state == SCS_BA) {
- state = (state == SCS_AB ? SCS_BA : SCS_AB);
-
- ELEM_REMOVE(list);
- list = list->next;
- goto redo_point;
- }
- break;
- }
- case BIN(pop):
- {
- switch (state) {
- case SCS_AX:
- case SCS_BX:
- state = SCS_XX;
- break;
- case SCS_AB:
- state = SCS_AX;
- break;
- case SCS_BA:
- state = SCS_BX;
- break;
- case SCS_XX:
- goto normal_insn;
- default:
- COMPILE_ERROR(iseq, iobj->insn_info.line_no,
- "unreachable");
- return COMPILE_NG;
- }
- /* remove useless pop */
- ELEM_REMOVE(list);
- list = list->next;
- goto redo_point;
- }
- default:;
- /* none */
- } /* end of switch */
- normal_insn:
- state = insn_set_sc_state(iseq, anchor, iobj, state);
- break;
- }
- case ISEQ_ELEMENT_LABEL:
- {
- LABEL *lobj;
- lobj = (LABEL *)list;
-
- state = label_set_sc_state(lobj, state);
- }
- default:
- break;
- }
- list = list->next;
+ INSN *rpobj =
+ new_insn_body(iseq, &dummy_line_node, BIN(reput), 0);
+
+ /* replace this insn */
+ ELEM_REPLACE(list, (LINK_ELEMENT *)rpobj);
+ list = (LINK_ELEMENT *)rpobj;
+ goto redo_point;
+ }
+ break;
+ }
+ case BIN(swap):
+ {
+ if (state == SCS_AB || state == SCS_BA) {
+ state = (state == SCS_AB ? SCS_BA : SCS_AB);
+
+ ELEM_REMOVE(list);
+ list = list->next;
+ goto redo_point;
+ }
+ break;
+ }
+ case BIN(pop):
+ {
+ switch (state) {
+ case SCS_AX:
+ case SCS_BX:
+ state = SCS_XX;
+ break;
+ case SCS_AB:
+ state = SCS_AX;
+ break;
+ case SCS_BA:
+ state = SCS_BX;
+ break;
+ case SCS_XX:
+ goto normal_insn;
+ default:
+ COMPILE_ERROR(iseq, iobj->insn_info.line_no,
+ "unreachable");
+ return COMPILE_NG;
+ }
+ /* remove useless pop */
+ ELEM_REMOVE(list);
+ list = list->next;
+ goto redo_point;
+ }
+ default:;
+ /* none */
+ } /* end of switch */
+ normal_insn:
+ state = insn_set_sc_state(iseq, anchor, iobj, state);
+ break;
+ }
+ case ISEQ_ELEMENT_LABEL:
+ {
+ LABEL *lobj;
+ lobj = (LABEL *)list;
+
+ state = label_set_sc_state(lobj, state);
+ }
+ default:
+ break;
+ }
+ list = list->next;
}
#endif
return COMPILE_OK;
@@ -3872,20 +4134,20 @@ all_string_result_p(const NODE *node)
if (!node) return FALSE;
switch (nd_type(node)) {
case NODE_STR: case NODE_DSTR:
- return TRUE;
+ return TRUE;
case NODE_IF: case NODE_UNLESS:
- if (!node->nd_body || !node->nd_else) return FALSE;
- if (all_string_result_p(node->nd_body))
- return all_string_result_p(node->nd_else);
- return FALSE;
+ if (!node->nd_body || !node->nd_else) return FALSE;
+ if (all_string_result_p(node->nd_body))
+ return all_string_result_p(node->nd_else);
+ return FALSE;
case NODE_AND: case NODE_OR:
- if (!node->nd_2nd)
- return all_string_result_p(node->nd_1st);
- if (!all_string_result_p(node->nd_1st))
- return FALSE;
- return all_string_result_p(node->nd_2nd);
+ if (!node->nd_2nd)
+ return all_string_result_p(node->nd_1st);
+ if (!all_string_result_p(node->nd_1st))
+ return FALSE;
+ return all_string_result_p(node->nd_2nd);
default:
- return FALSE;
+ return FALSE;
}
}
@@ -3899,35 +4161,35 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons
debugp_param("nd_lit", lit);
if (!NIL_P(lit)) {
- cnt++;
- if (!RB_TYPE_P(lit, T_STRING)) {
- COMPILE_ERROR(ERROR_ARGS "dstr: must be string: %s",
- rb_builtin_type_name(TYPE(lit)));
- return COMPILE_NG;
- }
- lit = rb_fstring(lit);
- ADD_INSN1(ret, node, putobject, lit);
+ cnt++;
+ if (!RB_TYPE_P(lit, T_STRING)) {
+ COMPILE_ERROR(ERROR_ARGS "dstr: must be string: %s",
+ rb_builtin_type_name(TYPE(lit)));
+ return COMPILE_NG;
+ }
+ lit = rb_fstring(lit);
+ ADD_INSN1(ret, node, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
- if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
+ if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
}
while (list) {
- const NODE *const head = list->nd_head;
- if (nd_type(head) == NODE_STR) {
- lit = rb_fstring(head->nd_lit);
- ADD_INSN1(ret, head, putobject, lit);
+ const NODE *const head = list->nd_head;
+ if (nd_type_p(head, NODE_STR)) {
+ lit = rb_fstring(head->nd_lit);
+ ADD_INSN1(ret, head, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
- lit = Qnil;
- }
- else {
- CHECK(COMPILE(ret, "each string", head));
- }
- cnt++;
- list = list->nd_next;
+ lit = Qnil;
+ }
+ else {
+ CHECK(COMPILE(ret, "each string", head));
+ }
+ cnt++;
+ list = list->nd_next;
}
if (NIL_P(lit) && first_lit) {
- ELEM_REMOVE(first_lit);
- --cnt;
+ ELEM_REMOVE(first_lit);
+ --cnt;
}
*cntp = cnt;
@@ -3935,6 +4197,20 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons
}
static int
+compile_block(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped)
+{
+ while (node && nd_type_p(node, NODE_BLOCK)) {
+ CHECK(COMPILE_(ret, "BLOCK body", node->nd_head,
+ (node->nd_next ? 1 : popped)));
+ node = node->nd_next;
+ }
+ if (node) {
+ CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped));
+ }
+ return COMPILE_OK;
+}
+
+static int
compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
{
int cnt;
@@ -3961,12 +4237,12 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
static int
compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int again,
- LABEL *then_label, LABEL *else_label)
+ LABEL *then_label, LABEL *else_label)
{
const int line = nd_line(node);
LABEL *lend = NEW_LABEL(line);
- rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(iseq->body->local_iseq)
- + VM_SVAR_FLIPFLOP_START;
+ rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(ISEQ_BODY(iseq)->local_iseq)
+ + VM_SVAR_FLIPFLOP_START;
VALUE key = INT2FIX(cnt);
ADD_INSN2(ret, node, getspecial, key, INT2FIX(0));
@@ -3978,7 +4254,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod
ADD_INSN1(ret, node, putobject, Qtrue);
ADD_INSN1(ret, node, setspecial, key);
if (!again) {
- ADD_INSNL(ret, node, jump, then_label);
+ ADD_INSNL(ret, node, jump, then_label);
}
/* *flip == 1 */
@@ -3994,67 +4270,67 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod
static int
compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond,
- LABEL *then_label, LABEL *else_label)
+ LABEL *then_label, LABEL *else_label)
{
again:
switch (nd_type(cond)) {
case NODE_AND:
- {
- LABEL *label = NEW_LABEL(nd_line(cond));
- CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
- else_label));
+ {
+ LABEL *label = NEW_LABEL(nd_line(cond));
+ CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
+ else_label));
if (!label->refcnt) {
ADD_INSN(ret, cond, putnil);
break;
}
- ADD_LABEL(ret, label);
- cond = cond->nd_2nd;
- goto again;
- }
+ ADD_LABEL(ret, label);
+ cond = cond->nd_2nd;
+ goto again;
+ }
case NODE_OR:
- {
- LABEL *label = NEW_LABEL(nd_line(cond));
- CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
- label));
+ {
+ LABEL *label = NEW_LABEL(nd_line(cond));
+ CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
+ label));
if (!label->refcnt) {
ADD_INSN(ret, cond, putnil);
break;
}
- ADD_LABEL(ret, label);
- cond = cond->nd_2nd;
- goto again;
- }
+ ADD_LABEL(ret, label);
+ cond = cond->nd_2nd;
+ goto again;
+ }
case NODE_LIT: /* NODE_LIT is always true */
case NODE_TRUE:
case NODE_STR:
case NODE_ZLIST:
case NODE_LAMBDA:
- /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
- ADD_INSNL(ret, cond, jump, then_label);
+ /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
+ ADD_INSNL(ret, cond, jump, then_label);
return COMPILE_OK;
case NODE_FALSE:
case NODE_NIL:
- /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
- ADD_INSNL(ret, cond, jump, else_label);
+ /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
+ ADD_INSNL(ret, cond, jump, else_label);
return COMPILE_OK;
case NODE_LIST:
case NODE_ARGSCAT:
case NODE_DREGX:
case NODE_DSTR:
- CHECK(COMPILE_POPPED(ret, "branch condition", cond));
- ADD_INSNL(ret, cond, jump, then_label);
+ CHECK(COMPILE_POPPED(ret, "branch condition", cond));
+ ADD_INSNL(ret, cond, jump, then_label);
return COMPILE_OK;
case NODE_FLIP2:
- CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
+ CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
return COMPILE_OK;
case NODE_FLIP3:
- CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
+ CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
return COMPILE_OK;
case NODE_DEFINED:
- CHECK(compile_defined_expr(iseq, ret, cond, Qfalse));
+ CHECK(compile_defined_expr(iseq, ret, cond, Qfalse));
break;
default:
- CHECK(COMPILE(ret, "branch condition", cond));
+ CHECK(COMPILE(ret, "branch condition", cond));
break;
}
@@ -4068,30 +4344,30 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co
static int
keyword_node_p(const NODE *const node)
{
- return nd_type(node) == NODE_HASH && (node->nd_brace & HASH_BRACE) != HASH_BRACE;
+ return nd_type_p(node, NODE_HASH) && (node->nd_brace & HASH_BRACE) != HASH_BRACE;
}
static int
compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
- const NODE *const root_node,
- struct rb_callinfo_kwarg **const kw_arg_ptr,
- unsigned int *flag)
+ const NODE *const root_node,
+ struct rb_callinfo_kwarg **const kw_arg_ptr,
+ unsigned int *flag)
{
if (kw_arg_ptr == NULL) return FALSE;
- if (root_node->nd_head && nd_type(root_node->nd_head) == NODE_LIST) {
- const NODE *node = root_node->nd_head;
+ if (root_node->nd_head && nd_type_p(root_node->nd_head, NODE_LIST)) {
+ const NODE *node = root_node->nd_head;
int seen_nodes = 0;
- while (node) {
- const NODE *key_node = node->nd_head;
+ while (node) {
+ const NODE *key_node = node->nd_head;
seen_nodes++;
- assert(nd_type(node) == NODE_LIST);
- if (key_node && nd_type(key_node) == NODE_LIT && RB_TYPE_P(key_node->nd_lit, T_SYMBOL)) {
- /* can be keywords */
- }
- else {
+ assert(nd_type_p(node, NODE_LIST));
+ if (key_node && nd_type_p(key_node, NODE_LIT) && SYMBOL_P(key_node->nd_lit)) {
+ /* can be keywords */
+ }
+ else {
if (flag) {
*flag |= VM_CALL_KW_SPLAT;
if (seen_nodes > 1 || node->nd_next->nd_next) {
@@ -4102,33 +4378,33 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
*flag |= VM_CALL_KW_SPLAT_MUT;
}
}
- return FALSE;
- }
- node = node->nd_next; /* skip value node */
- node = node->nd_next;
- }
-
- /* may be keywords */
- node = root_node->nd_head;
- {
- int len = (int)node->nd_alen / 2;
+ return FALSE;
+ }
+ node = node->nd_next; /* skip value node */
+ node = node->nd_next;
+ }
+
+ /* may be keywords */
+ node = root_node->nd_head;
+ {
+ int len = (int)node->nd_alen / 2;
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;
+ VALUE *keywords = kw_arg->keywords;
+ int i = 0;
+ kw_arg->keyword_len = len;
- *kw_arg_ptr = kw_arg;
+ *kw_arg_ptr = kw_arg;
- for (i=0; node != NULL; i++, node = node->nd_next->nd_next) {
- const NODE *key_node = node->nd_head;
- const NODE *val_node = node->nd_next->nd_head;
- keywords[i] = key_node->nd_lit;
+ for (i=0; node != NULL; i++, node = node->nd_next->nd_next) {
+ const NODE *key_node = node->nd_head;
+ const NODE *val_node = node->nd_next->nd_head;
+ keywords[i] = key_node->nd_lit;
NO_CHECK(COMPILE(ret, "keyword values", val_node));
- }
- assert(i == len);
- return TRUE;
- }
+ }
+ assert(i == len);
+ return TRUE;
+ }
}
return FALSE;
}
@@ -4163,31 +4439,29 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node,
static inline int
static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
{
- node = node->nd_head;
switch (nd_type(node)) {
case NODE_LIT:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
- return TRUE;
+ return TRUE;
case NODE_STR:
return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal;
default:
- return FALSE;
+ return FALSE;
}
}
static inline VALUE
static_literal_value(const NODE *node, rb_iseq_t *iseq)
{
- node = node->nd_head;
switch (nd_type(node)) {
case NODE_NIL:
- return Qnil;
+ return Qnil;
case NODE_TRUE:
- return Qtrue;
+ return Qtrue;
case NODE_FALSE:
- return Qfalse;
+ return Qfalse;
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
VALUE lit;
@@ -4200,7 +4474,7 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
return rb_fstring(node->nd_lit);
}
default:
- return node->nd_lit;
+ return node->nd_lit;
}
}
@@ -4209,10 +4483,10 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
{
const NODE *line_node = node;
- if (nd_type(node) == NODE_ZLIST) {
- if (!popped) {
- ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
- }
+ if (nd_type_p(node, NODE_ZLIST)) {
+ if (!popped) {
+ ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
+ }
return 0;
}
@@ -4279,19 +4553,19 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
int count = 1;
/* pre-allocation check (this branch can be omittable) */
- if (static_literal_node_p(node, iseq)) {
+ if (static_literal_node_p(node->nd_head, iseq)) {
/* count the elements that are optimizable */
const NODE *node_tmp = node->nd_next;
- for (; node_tmp && static_literal_node_p(node_tmp, iseq); node_tmp = node_tmp->nd_next)
+ for (; node_tmp && static_literal_node_p(node_tmp->nd_head, iseq); node_tmp = node_tmp->nd_next)
count++;
if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) {
/* The literal contains only optimizable elements, or the subarray is long enough */
- VALUE ary = rb_ary_tmp_new(count);
+ VALUE ary = rb_ary_hidden_new(count);
/* Create a hidden array */
for (; count; count--, node = node->nd_next)
- rb_ary_push(ary, static_literal_value(node, iseq));
+ rb_ary_push(ary, static_literal_value(node->nd_head, iseq));
OBJ_FREEZE(ary);
/* Emit optimized code */
@@ -4333,10 +4607,34 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
return 1;
}
+/* Compile an array containing the single element represented by node */
+static int
+compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node)
+{
+ if (static_literal_node_p(node, iseq)) {
+ VALUE ary = rb_ary_hidden_new(1);
+ rb_ary_push(ary, static_literal_value(node, iseq));
+ OBJ_FREEZE(ary);
+
+ ADD_INSN1(ret, node, duparray, ary);
+ }
+ else {
+ CHECK(COMPILE_(ret, "array element", node, FALSE));
+ if (keyword_node_p(node)) {
+ ADD_INSN1(ret, node, newarraykwsplat, INT2FIX(1));
+ }
+ else {
+ ADD_INSN1(ret, node, newarray, INT2FIX(1));
+ }
+ }
+
+ return 1;
+}
+
static inline int
static_literal_node_pair_p(const NODE *node, const rb_iseq_t *iseq)
{
- return node->nd_head && static_literal_node_p(node, iseq) && static_literal_node_p(node->nd_next, iseq);
+ return node->nd_head && static_literal_node_p(node->nd_head, iseq) && static_literal_node_p(node->nd_next->nd_head, iseq);
}
static int
@@ -4346,10 +4644,10 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
node = node->nd_head;
- if (!node || nd_type(node) == NODE_ZLIST) {
- if (!popped) {
- ADD_INSN1(ret, line_node, newhash, INT2FIX(0));
- }
+ if (!node || nd_type_p(node, NODE_ZLIST)) {
+ if (!popped) {
+ ADD_INSN1(ret, line_node, newhash, INT2FIX(0));
+ }
return 0;
}
@@ -4416,13 +4714,13 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_hash_len) {
/* The literal contains only optimizable elements, or the subsequence is long enough */
- VALUE ary = rb_ary_tmp_new(count);
+ VALUE ary = rb_ary_hidden_new(count);
/* Create a hidden hash */
for (; count; count--, node = node->nd_next->nd_next) {
VALUE elem[2];
- elem[0] = static_literal_value(node, iseq);
- elem[1] = static_literal_value(node->nd_next, iseq);
+ elem[0] = static_literal_value(node->nd_head, iseq);
+ elem[1] = static_literal_value(node->nd_next->nd_head, iseq);
rb_ary_cat(ary, elem, 2);
}
VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2);
@@ -4469,7 +4767,7 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
FLUSH_CHUNK();
const NODE *kw = node->nd_next->nd_head;
- int empty_kw = nd_type(kw) == NODE_LIT && RB_TYPE_P(kw->nd_lit, T_HASH); /* foo( ..., **{}, ...) */
+ int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(kw->nd_lit, T_HASH); /* foo( ..., **{}, ...) */
int first_kw = first_chunk && stack_len == 0; /* foo(1,2,3, **kw, ...) */
int last_kw = !node->nd_next->nd_next; /* foo( ..., **kw) */
int only_kw = last_kw && first_kw; /* foo(1,2,3, **kw) */
@@ -4534,62 +4832,62 @@ rb_node_case_when_optimizable_literal(const NODE *const node)
{
switch (nd_type(node)) {
case NODE_LIT: {
- VALUE v = node->nd_lit;
- double ival;
- if (RB_TYPE_P(v, T_FLOAT) &&
- modf(RFLOAT_VALUE(v), &ival) == 0.0) {
- return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
- }
+ VALUE v = node->nd_lit;
+ double ival;
+ if (RB_FLOAT_TYPE_P(v) &&
+ modf(RFLOAT_VALUE(v), &ival) == 0.0) {
+ return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
+ }
if (RB_TYPE_P(v, T_RATIONAL) || RB_TYPE_P(v, T_COMPLEX)) {
return Qundef;
}
- if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
- return v;
- }
- break;
+ if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
+ return v;
+ }
+ break;
}
case NODE_NIL:
- return Qnil;
+ return Qnil;
case NODE_TRUE:
- return Qtrue;
+ return Qtrue;
case NODE_FALSE:
- return Qfalse;
+ return Qfalse;
case NODE_STR:
- return rb_fstring(node->nd_lit);
+ return rb_fstring(node->nd_lit);
}
return Qundef;
}
static int
when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
- LABEL *l1, int only_special_literals, VALUE literals)
+ LABEL *l1, int only_special_literals, VALUE literals)
{
while (vals) {
- const NODE *val = vals->nd_head;
+ const NODE *val = vals->nd_head;
VALUE lit = rb_node_case_when_optimizable_literal(val);
- if (lit == Qundef) {
- only_special_literals = 0;
- }
+ if (UNDEF_P(lit)) {
+ only_special_literals = 0;
+ }
else if (NIL_P(rb_hash_lookup(literals, lit))) {
rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
- }
+ }
- if (nd_type(val) == NODE_STR) {
- debugp_param("nd_lit", val->nd_lit);
- lit = rb_fstring(val->nd_lit);
- ADD_INSN1(cond_seq, val, putobject, lit);
+ if (nd_type_p(val, NODE_STR)) {
+ debugp_param("nd_lit", val->nd_lit);
+ lit = rb_fstring(val->nd_lit);
+ ADD_INSN1(cond_seq, val, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
- }
- else {
- if (!COMPILE(cond_seq, "when cond", val)) return -1;
- }
+ }
+ else {
+ if (!COMPILE(cond_seq, "when cond", val)) return -1;
+ }
// Emit patern === target
ADD_INSN1(cond_seq, vals, topn, INT2FIX(1));
ADD_CALL(cond_seq, vals, idEqq, INT2FIX(1));
- ADD_INSNL(cond_seq, val, branchif, l1);
- vals = vals->nd_next;
+ ADD_INSNL(cond_seq, val, branchif, l1);
+ vals = vals->nd_next;
}
return only_special_literals;
}
@@ -4638,9 +4936,9 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
*
* In order to handle evaluation of multiple assignment such that the left hand side
* is evaluated before the right hand side, we need to process the left hand side
- * and see if there are any attributes that need to be assigned. If so, we add
- * instructions to evaluate the receiver of any assigned attributes before we
- * process the right hand side.
+ * and see if there are any attributes that need to be assigned, or constants set
+ * on explicit objects. If so, we add instructions to evaluate the receiver of
+ * any assigned attributes or constants before we process the right hand side.
*
* For a multiple assignment such as:
*
@@ -4707,7 +5005,7 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
* In order to handle this correctly, we need to keep track of the nesting
* level for each attribute assignment, as well as the attribute number
* (left hand side attributes are processed left to right) and number of
- * arguments to pass to the setter method. struct masgn_attrasgn tracks
+ * arguments to pass to the setter method. struct masgn_lhs_node tracks
* this information.
*
* We also need to track information for the entire multiple assignment, such
@@ -4718,9 +5016,9 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
* tracks this information.
*/
-struct masgn_attrasgn {
+struct masgn_lhs_node {
INSN *before_insn;
- struct masgn_attrasgn *next;
+ struct masgn_lhs_node *next;
const NODE *line_node;
int argn;
int num_args;
@@ -4728,13 +5026,44 @@ struct masgn_attrasgn {
};
struct masgn_state {
- struct masgn_attrasgn *first_memo;
- struct masgn_attrasgn *last_memo;
+ struct masgn_lhs_node *first_memo;
+ struct masgn_lhs_node *last_memo;
int lhs_level;
int num_args;
bool nested;
};
+static int
+add_masgn_lhs_node(struct masgn_state *state, int lhs_pos, const NODE *line_node, int argc, INSN *before_insn)
+{
+ if (!state) {
+ rb_bug("no masgn_state");
+ }
+
+ struct masgn_lhs_node *memo;
+ memo = malloc(sizeof(struct masgn_lhs_node));
+ if (!memo) {
+ return COMPILE_NG;
+ }
+
+ memo->before_insn = before_insn;
+ memo->line_node = line_node;
+ memo->argn = state->num_args + 1;
+ memo->num_args = argc;
+ state->num_args += argc;
+ memo->lhs_pos = lhs_pos;
+ memo->next = NULL;
+ if (!state->first_memo) {
+ state->first_memo = memo;
+ }
+ else {
+ state->last_memo->next = memo;
+ }
+ state->last_memo = memo;
+
+ return COMPILE_OK;
+}
+
static int compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs, LINK_ANCHOR *const lhs, LINK_ANCHOR *const post, const NODE *const node, struct masgn_state *state, int popped);
static int
@@ -4742,20 +5071,22 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
{
switch (nd_type(node)) {
case NODE_ATTRASGN: {
- if (!state) {
- rb_bug("no masgn_state");
- }
-
- INSN *iobj;
+ INSN *iobj;
const NODE *line_node = node;
CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node));
+ bool safenav_call = false;
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
- ELEM_REMOVE(LAST_ELEMENT(pre));
- ELEM_REMOVE((LINK_ELEMENT *)iobj);
- pre->last = iobj->link.prev;
+ ASSUME(iobj);
+ ELEM_REMOVE(insn_element);
+ if (!IS_INSN_ID(iobj, send)) {
+ safenav_call = true;
+ iobj = (INSN *)get_prev_insn(iobj);
+ ELEM_INSERT_NEXT(&iobj->link, insn_element);
+ }
+ (pre->last = iobj->link.prev)->next = 0;
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
int argc = vm_ci_argc(ci) + 1;
@@ -4770,43 +5101,31 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
ADD_INSN1(lhs, line_node, topn, INT2FIX(argc));
}
- struct masgn_attrasgn *memo;
- memo = malloc(sizeof(struct masgn_attrasgn));
- if (!memo) {
- return 0;
- }
- memo->before_insn = (INSN *)LAST_ELEMENT(lhs);
- memo->line_node = line_node;
- memo->argn = state->num_args + 1;
- memo->num_args = argc;
- state->num_args += argc;
- memo->lhs_pos = lhs_pos;
- memo->next = NULL;
- if (!state->first_memo) {
- state->first_memo = memo;
- }
- else {
- state->last_memo->next = memo;
+ if (!add_masgn_lhs_node(state, lhs_pos, line_node, argc, (INSN *)LAST_ELEMENT(lhs))) {
+ return COMPILE_NG;
}
- state->last_memo = memo;
- ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
- if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
+ iobj->link.prev = lhs->last;
+ lhs->last->next = &iobj->link;
+ for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
+ if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
int argc = vm_ci_argc(ci);
ci = ci_argc_set(iseq, ci, argc - 1);
OPERAND_AT(iobj, 0) = (VALUE)ci;
RB_OBJ_WRITTEN(iseq, Qundef, iobj);
INSERT_BEFORE_INSN1(iobj, line_node, newarray, INT2FIX(1));
- INSERT_BEFORE_INSN(iobj, line_node, concatarray);
- }
- ADD_INSN(lhs, line_node, pop);
- if (argc != 1) {
+ INSERT_BEFORE_INSN(iobj, line_node, concatarray);
+ }
+ if (!safenav_call) {
ADD_INSN(lhs, line_node, pop);
+ if (argc != 1) {
+ ADD_INSN(lhs, line_node, pop);
+ }
}
for (int i=0; i < argc; i++) {
ADD_INSN(post, line_node, pop);
}
- break;
+ break;
}
case NODE_MASGN: {
DECL_ANCHOR(nest_rhs);
@@ -4824,13 +5143,36 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
ADD_SEQ(lhs, nest_rhs);
ADD_SEQ(lhs, nest_lhs);
- break;
+ break;
}
+ case NODE_CDECL:
+ if (!node->nd_vid) {
+ /* Special handling only needed for expr::C, not for C */
+ INSN *iobj;
+
+ CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_CDECL)", node));
+
+ LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
+ iobj = (INSN *)insn_element; /* setconstant insn */
+ ELEM_REMOVE((LINK_ELEMENT *)get_prev_insn((INSN *)get_prev_insn(iobj)));
+ ELEM_REMOVE((LINK_ELEMENT *)get_prev_insn(iobj));
+ ELEM_REMOVE(insn_element);
+ pre->last = iobj->link.prev;
+ ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
+
+ if (!add_masgn_lhs_node(state, lhs_pos, node, 1, (INSN *)LAST_ELEMENT(lhs))) {
+ return COMPILE_NG;
+ }
+
+ ADD_INSN(post, node, pop);
+ break;
+ }
+ /* Fallthrough */
default: {
- DECL_ANCHOR(anchor);
- INIT_ANCHOR(anchor);
- CHECK(COMPILE_POPPED(anchor, "masgn lhs", node));
- ELEM_REMOVE(FIRST_ELEMENT(anchor));
+ DECL_ANCHOR(anchor);
+ INIT_ANCHOR(anchor);
+ CHECK(COMPILE_POPPED(anchor, "masgn lhs", node));
+ ELEM_REMOVE(FIRST_ELEMENT(anchor));
ADD_SEQ(lhs, anchor);
}
}
@@ -4842,7 +5184,7 @@ static int
compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *lhsn)
{
if (lhsn) {
- CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
+ CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, lhsn->nd_head, NULL, 0));
}
return COMPILE_OK;
@@ -4850,7 +5192,7 @@ compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *lhs
static int
compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
- const NODE *rhsn, const NODE *orig_lhsn)
+ const NODE *rhsn, const NODE *orig_lhsn)
{
VALUE mem[64];
const int memsize = numberof(mem);
@@ -4863,49 +5205,48 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
int i; \
if (memindex == memsize) return 0; \
for (i=0; i<memindex; i++) { \
- if (mem[i] == (v)) return 0; \
+ if (mem[i] == (v)) return 0; \
} \
mem[memindex++] = (v); \
}
- if (rhsn == 0 || nd_type(rhsn) != NODE_LIST) {
- return 0;
+ if (rhsn == 0 || !nd_type_p(rhsn, NODE_LIST)) {
+ return 0;
}
while (lhsn) {
- const NODE *ln = lhsn->nd_head;
- switch (nd_type(ln)) {
- case NODE_LASGN:
- MEMORY(ln->nd_vid);
- break;
- case NODE_DASGN:
- case NODE_DASGN_CURR:
- case NODE_IASGN:
- case NODE_CVASGN:
- MEMORY(ln->nd_vid);
- break;
- default:
- return 0;
- }
- lhsn = lhsn->nd_next;
- llen++;
+ const NODE *ln = lhsn->nd_head;
+ switch (nd_type(ln)) {
+ case NODE_LASGN:
+ MEMORY(ln->nd_vid);
+ break;
+ case NODE_DASGN:
+ case NODE_IASGN:
+ case NODE_CVASGN:
+ MEMORY(ln->nd_vid);
+ break;
+ default:
+ return 0;
+ }
+ lhsn = lhsn->nd_next;
+ llen++;
}
while (rhsn) {
- if (llen <= rlen) {
+ if (llen <= rlen) {
NO_CHECK(COMPILE_POPPED(ret, "masgn val (popped)", rhsn->nd_head));
- }
- else {
+ }
+ else {
NO_CHECK(COMPILE(ret, "masgn val", rhsn->nd_head));
- }
- rhsn = rhsn->nd_next;
- rlen++;
+ }
+ rhsn = rhsn->nd_next;
+ rlen++;
}
if (llen > rlen) {
- for (i=0; i<llen-rlen; i++) {
- ADD_INSN(ret, orig_lhsn, putnil);
- }
+ for (i=0; i<llen-rlen; i++) {
+ ADD_INSN(ret, orig_lhsn, putnil);
+ }
}
compile_massign_opt_lhs(iseq, ret, orig_lhsn);
@@ -4936,7 +5277,7 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
}
if (lhs_splat) {
- if (nd_type(splatn) == NODE_POSTARG) {
+ if (nd_type_p(splatn, NODE_POSTARG)) {
/*a, b, *r, p1, p2 */
const NODE *postn = splatn->nd_2nd;
const NODE *restn = splatn->nd_1st;
@@ -4996,7 +5337,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
INIT_ANCHOR(post);
int ok = compile_massign0(iseq, pre, rhs, lhs, post, node, &state, popped);
- struct masgn_attrasgn *memo = state.first_memo, *tmp_memo;
+ struct masgn_lhs_node *memo = state.first_memo, *tmp_memo;
while (memo) {
VALUE topn_arg = INT2FIX((state.num_args - memo->argn) + memo->lhs_pos);
for (int i = 0; i < memo->num_args; i++) {
@@ -5020,32 +5361,55 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
return COMPILE_OK;
}
+static VALUE
+collect_const_segments(rb_iseq_t *iseq, const NODE *node)
+{
+ VALUE arr = rb_ary_new();
+ for (;;) {
+ switch (nd_type(node)) {
+ case NODE_CONST:
+ rb_ary_unshift(arr, ID2SYM(node->nd_vid));
+ return arr;
+ case NODE_COLON3:
+ rb_ary_unshift(arr, ID2SYM(node->nd_mid));
+ rb_ary_unshift(arr, ID2SYM(idNULL));
+ return arr;
+ case NODE_COLON2:
+ rb_ary_unshift(arr, ID2SYM(node->nd_mid));
+ node = node->nd_head;
+ break;
+ default:
+ return Qfalse;
+ }
+ }
+}
+
static int
compile_const_prefix(rb_iseq_t *iseq, const NODE *const node,
- LINK_ANCHOR *const pref, LINK_ANCHOR *const body)
+ LINK_ANCHOR *const pref, LINK_ANCHOR *const body)
{
switch (nd_type(node)) {
case NODE_CONST:
- debugi("compile_const_prefix - colon", node->nd_vid);
+ debugi("compile_const_prefix - colon", node->nd_vid);
ADD_INSN1(body, node, putobject, Qtrue);
ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_vid));
- break;
+ break;
case NODE_COLON3:
- debugi("compile_const_prefix - colon3", node->nd_mid);
- ADD_INSN(body, node, pop);
- ADD_INSN1(body, node, putobject, rb_cObject);
+ debugi("compile_const_prefix - colon3", node->nd_mid);
+ ADD_INSN(body, node, pop);
+ ADD_INSN1(body, node, putobject, rb_cObject);
ADD_INSN1(body, node, putobject, Qtrue);
ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid));
- break;
+ break;
case NODE_COLON2:
- CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
- debugi("compile_const_prefix - colon2", node->nd_mid);
+ CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
+ debugi("compile_const_prefix - colon2", node->nd_mid);
ADD_INSN1(body, node, putobject, Qfalse);
ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid));
- break;
+ break;
default:
- CHECK(COMPILE(pref, "const colon2 prefix", node));
- break;
+ CHECK(COMPILE(pref, "const colon2 prefix", node));
+ break;
}
return COMPILE_OK;
}
@@ -5053,28 +5417,28 @@ compile_const_prefix(rb_iseq_t *iseq, const NODE *const node,
static int
compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath)
{
- if (nd_type(cpath) == NODE_COLON3) {
- /* toplevel class ::Foo */
- ADD_INSN1(ret, cpath, putobject, rb_cObject);
- return VM_DEFINECLASS_FLAG_SCOPED;
+ if (nd_type_p(cpath, NODE_COLON3)) {
+ /* toplevel class ::Foo */
+ ADD_INSN1(ret, cpath, putobject, rb_cObject);
+ return VM_DEFINECLASS_FLAG_SCOPED;
}
else if (cpath->nd_head) {
- /* Bar::Foo */
+ /* Bar::Foo */
NO_CHECK(COMPILE(ret, "nd_else->nd_head", cpath->nd_head));
- return VM_DEFINECLASS_FLAG_SCOPED;
+ return VM_DEFINECLASS_FLAG_SCOPED;
}
else {
- /* class at cbase Foo */
- ADD_INSN1(ret, cpath, putspecialobject,
- INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
- return 0;
+ /* class at cbase Foo */
+ ADD_INSN1(ret, cpath, putspecialobject,
+ INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
+ return 0;
}
}
static inline int
private_recv_p(const NODE *node)
{
- if (nd_type(node->nd_recv) == NODE_SELF) {
+ if (nd_type_p(node->nd_recv, NODE_SELF)) {
NODE *self = node->nd_recv;
return self->nd_state != 0;
}
@@ -5083,7 +5447,7 @@ private_recv_p(const NODE *node)
static void
defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
- const NODE *const node, LABEL **lfinish, VALUE needstr);
+ const NODE *const node, LABEL **lfinish, VALUE needstr);
static int
compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, const NODE *const line_node, int popped, bool assume_receiver);
@@ -5100,31 +5464,31 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
switch (type = nd_type(node)) {
- /* easy literals */
+ /* easy literals */
case NODE_NIL:
- expr_type = DEFINED_NIL;
- break;
+ expr_type = DEFINED_NIL;
+ break;
case NODE_SELF:
- expr_type = DEFINED_SELF;
- break;
+ expr_type = DEFINED_SELF;
+ break;
case NODE_TRUE:
- expr_type = DEFINED_TRUE;
- break;
+ expr_type = DEFINED_TRUE;
+ break;
case NODE_FALSE:
- expr_type = DEFINED_FALSE;
- break;
+ expr_type = DEFINED_FALSE;
+ break;
case NODE_LIST:{
- const NODE *vals = node;
+ const NODE *vals = node;
- do {
+ do {
defined_expr0(iseq, ret, vals->nd_head, lfinish, Qfalse, false);
- if (!lfinish[1]) {
+ if (!lfinish[1]) {
lfinish[1] = NEW_LABEL(line);
- }
+ }
ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
- } while ((vals = vals->nd_next) != NULL);
+ } while ((vals = vals->nd_next) != NULL);
}
/* fall through */
case NODE_STR:
@@ -5133,43 +5497,43 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
case NODE_AND:
case NODE_OR:
default:
- expr_type = DEFINED_EXPR;
- break;
+ expr_type = DEFINED_EXPR;
+ break;
- /* variables */
+ /* variables */
case NODE_LVAR:
case NODE_DVAR:
- expr_type = DEFINED_LVAR;
- break;
+ expr_type = DEFINED_LVAR;
+ break;
#define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type))
case NODE_IVAR:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_IVAR),
- ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_IVAR));
+ ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_IVAR));
return;
case NODE_GVAR:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_GVAR),
- ID2SYM(node->nd_entry), PUSH_VAL(DEFINED_GVAR));
+ ID2SYM(node->nd_entry), PUSH_VAL(DEFINED_GVAR));
return;
case NODE_CVAR:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CVAR),
- ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CVAR));
+ ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CVAR));
return;
case NODE_CONST:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST),
- ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CONST));
+ ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CONST));
return;
case NODE_COLON2:
- if (!lfinish[1]) {
+ if (!lfinish[1]) {
lfinish[1] = NEW_LABEL(line);
- }
+ }
defined_expr0(iseq, ret, node->nd_head, lfinish, Qfalse, false);
ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
NO_CHECK(COMPILE(ret, "defined/colon2#nd_head", node->nd_head));
@@ -5186,18 +5550,18 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
case NODE_COLON3:
ADD_INSN1(ret, line_node, putobject, rb_cObject);
ADD_INSN3(ret, line_node, defined,
- INT2FIX(DEFINED_CONST_FROM), ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST));
+ INT2FIX(DEFINED_CONST_FROM), ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST));
return;
- /* method dispatch */
+ /* method dispatch */
case NODE_CALL:
case NODE_OPCALL:
case NODE_VCALL:
case NODE_FCALL:
case NODE_ATTRASGN:{
- const int explicit_receiver =
- (type == NODE_CALL || type == NODE_OPCALL ||
- (type == NODE_ATTRASGN && !private_recv_p(node)));
+ const int explicit_receiver =
+ (type == NODE_CALL || type == NODE_OPCALL ||
+ (type == NODE_ATTRASGN && !private_recv_p(node)));
if (node->nd_args || explicit_receiver) {
if (!lfinish[1]) {
@@ -5207,11 +5571,11 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
lfinish[2] = NEW_LABEL(line);
}
}
- if (node->nd_args) {
+ if (node->nd_args) {
defined_expr0(iseq, ret, node->nd_args, lfinish, Qfalse, false);
ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
- }
- if (explicit_receiver) {
+ }
+ if (explicit_receiver) {
defined_expr0(iseq, ret, node->nd_recv, lfinish, Qfalse, true);
switch (nd_type(node->nd_recv)) {
case NODE_CALL:
@@ -5231,38 +5595,38 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
ADD_INSN(ret, line_node, dup);
}
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD),
- ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
- }
- else {
+ ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
+ }
+ else {
ADD_INSN(ret, line_node, putself);
if (keep_result) {
ADD_INSN(ret, line_node, dup);
}
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_FUNC),
- ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
- }
+ ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
+ }
return;
}
case NODE_YIELD:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_YIELD), 0,
- PUSH_VAL(DEFINED_YIELD));
+ PUSH_VAL(DEFINED_YIELD));
return;
case NODE_BACK_REF:
case NODE_NTH_REF:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_REF),
- INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)),
- PUSH_VAL(DEFINED_GVAR));
+ INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)),
+ PUSH_VAL(DEFINED_GVAR));
return;
case NODE_SUPER:
case NODE_ZSUPER:
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_ZSUPER), 0,
- PUSH_VAL(DEFINED_ZSUPER));
+ PUSH_VAL(DEFINED_ZSUPER));
return;
#undef PUSH_VAL
@@ -5273,13 +5637,12 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
- case NODE_DASGN_CURR:
case NODE_GASGN:
case NODE_IASGN:
case NODE_CDECL:
case NODE_CVASGN:
- expr_type = DEFINED_ASGN;
- break;
+ expr_type = DEFINED_ASGN;
+ break;
}
assert(expr_type != DEFINED_NOT_DEFINED);
@@ -5303,26 +5666,26 @@ build_defined_rescue_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const void *u
static void
defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
- const NODE *const node, LABEL **lfinish, VALUE needstr)
+ const NODE *const node, LABEL **lfinish, VALUE needstr)
{
LINK_ELEMENT *lcur = ret->last;
defined_expr0(iseq, ret, node, lfinish, needstr, false);
if (lfinish[1]) {
- int line = nd_line(node);
- LABEL *lstart = NEW_LABEL(line);
- LABEL *lend = NEW_LABEL(line);
- const rb_iseq_t *rescue;
+ int line = nd_line(node);
+ LABEL *lstart = NEW_LABEL(line);
+ LABEL *lend = NEW_LABEL(line);
+ const rb_iseq_t *rescue;
struct rb_iseq_new_with_callback_callback_func *ifunc =
rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq, NULL);
rescue = new_child_iseq_with_callback(iseq, ifunc,
- rb_str_concat(rb_str_new2("defined guard in "),
- iseq->body->location.label),
- iseq, ISEQ_TYPE_RESCUE, 0);
- lstart->rescued = LABEL_RESCUE_BEG;
- lend->rescued = LABEL_RESCUE_END;
- APPEND_LABEL(ret, lcur, lstart);
- ADD_LABEL(ret, lend);
- ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
+ rb_str_concat(rb_str_new2("defined guard in "),
+ ISEQ_BODY(iseq)->location.label),
+ iseq, ISEQ_TYPE_RESCUE, 0);
+ lstart->rescued = LABEL_RESCUE_BEG;
+ lend->rescued = LABEL_RESCUE_END;
+ APPEND_LABEL(ret, lcur, lstart);
+ ADD_LABEL(ret, lend);
+ ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
}
}
@@ -5332,26 +5695,26 @@ compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const
const int line = nd_line(node);
const NODE *line_node = node;
if (!node->nd_head) {
- VALUE str = rb_iseq_defined_string(DEFINED_NIL);
- ADD_INSN1(ret, line_node, putobject, str);
+ VALUE str = rb_iseq_defined_string(DEFINED_NIL);
+ ADD_INSN1(ret, line_node, putobject, str);
}
else {
LABEL *lfinish[3];
- LINK_ELEMENT *last = ret->last;
- lfinish[0] = NEW_LABEL(line);
- lfinish[1] = 0;
+ LINK_ELEMENT *last = ret->last;
+ lfinish[0] = NEW_LABEL(line);
+ lfinish[1] = 0;
lfinish[2] = 0;
- defined_expr(iseq, ret, node->nd_head, lfinish, needstr);
- if (lfinish[1]) {
- ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link);
- ADD_INSN(ret, line_node, swap);
+ defined_expr(iseq, ret, node->nd_head, lfinish, needstr);
+ if (lfinish[1]) {
+ ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link);
+ ADD_INSN(ret, line_node, swap);
if (lfinish[2]) {
ADD_LABEL(ret, lfinish[2]);
}
- ADD_INSN(ret, line_node, pop);
- ADD_LABEL(ret, lfinish[1]);
- }
- ADD_LABEL(ret, lfinish[0]);
+ ADD_INSN(ret, line_node, pop);
+ ADD_LABEL(ret, lfinish[1]);
+ }
+ ADD_LABEL(ret, lfinish[0]);
}
return COMPILE_OK;
}
@@ -5362,27 +5725,27 @@ make_name_for_block(const rb_iseq_t *orig_iseq)
int level = 1;
const rb_iseq_t *iseq = orig_iseq;
- if (orig_iseq->body->parent_iseq != 0) {
- while (orig_iseq->body->local_iseq != iseq) {
- if (iseq->body->type == ISEQ_TYPE_BLOCK) {
- level++;
- }
- iseq = iseq->body->parent_iseq;
- }
+ if (ISEQ_BODY(orig_iseq)->parent_iseq != 0) {
+ while (ISEQ_BODY(orig_iseq)->local_iseq != iseq) {
+ if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_BLOCK) {
+ level++;
+ }
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
+ }
}
if (level == 1) {
- return rb_sprintf("block in %"PRIsVALUE, iseq->body->location.label);
+ return rb_sprintf("block in %"PRIsVALUE, ISEQ_BODY(iseq)->location.label);
}
else {
- return rb_sprintf("block (%d levels) in %"PRIsVALUE, level, iseq->body->location.label);
+ return rb_sprintf("block (%d levels) in %"PRIsVALUE, level, ISEQ_BODY(iseq)->location.label);
}
}
static void
push_ensure_entry(rb_iseq_t *iseq,
- struct iseq_compile_data_ensure_node_stack *enl,
- struct ensure_range *er, const NODE *const node)
+ struct iseq_compile_data_ensure_node_stack *enl,
+ struct ensure_range *er, const NODE *const node)
{
enl->ensure_node = node;
enl->prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack; /* prev */
@@ -5392,13 +5755,13 @@ push_ensure_entry(rb_iseq_t *iseq,
static void
add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange,
- LABEL *lstart, LABEL *lend)
+ LABEL *lstart, LABEL *lend)
{
struct ensure_range *ne =
- compile_data_alloc(iseq, sizeof(struct ensure_range));
+ compile_data_alloc(iseq, sizeof(struct ensure_range));
while (erange->next != 0) {
- erange = erange->next;
+ erange = erange->next;
}
ne->next = 0;
ne->begin = lend;
@@ -5427,32 +5790,32 @@ add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return)
assert(can_add_ensure_iseq(iseq));
struct iseq_compile_data_ensure_node_stack *enlp =
- ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
+ ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
DECL_ANCHOR(ensure);
INIT_ANCHOR(ensure);
while (enlp) {
- if (enlp->erange != NULL) {
- DECL_ANCHOR(ensure_part);
- LABEL *lstart = NEW_LABEL(0);
- LABEL *lend = NEW_LABEL(0);
- INIT_ANCHOR(ensure_part);
+ if (enlp->erange != NULL) {
+ DECL_ANCHOR(ensure_part);
+ LABEL *lstart = NEW_LABEL(0);
+ LABEL *lend = NEW_LABEL(0);
+ INIT_ANCHOR(ensure_part);
- add_ensure_range(iseq, enlp->erange, lstart, lend);
+ add_ensure_range(iseq, enlp->erange, lstart, lend);
- ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->prev;
- ADD_LABEL(ensure_part, lstart);
+ ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->prev;
+ ADD_LABEL(ensure_part, lstart);
NO_CHECK(COMPILE_POPPED(ensure_part, "ensure part", enlp->ensure_node));
- ADD_LABEL(ensure_part, lend);
- ADD_SEQ(ensure, ensure_part);
- }
- else {
- if (!is_return) {
- break;
- }
- }
- enlp = enlp->prev;
+ ADD_LABEL(ensure_part, lend);
+ ADD_SEQ(ensure, ensure_part);
+ }
+ else {
+ if (!is_return) {
+ break;
+ }
+ }
+ enlp = enlp->prev;
}
ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = prev_enlp;
ADD_SEQ(ret, ensure);
@@ -5463,7 +5826,7 @@ check_keyword(const NODE *node)
{
/* This check is essentially a code clone of compile_keyword_arg. */
- if (nd_type(node) == NODE_LIST) {
+ if (nd_type_p(node, NODE_LIST)) {
while (node->nd_next) {
node = node->nd_next;
}
@@ -5481,15 +5844,15 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
switch (nd_type(argn)) {
case NODE_SPLAT: {
NO_CHECK(COMPILE(args, "args (splat)", argn->nd_head));
- ADD_INSN1(args, argn, splatarray, dup_rest ? Qtrue : Qfalse);
+ ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
if (flag) *flag |= VM_CALL_ARGS_SPLAT;
return INT2FIX(1);
}
case NODE_ARGSCAT:
case NODE_ARGSPUSH: {
- int next_is_list = (nd_type(argn->nd_head) == NODE_LIST);
+ int next_is_list = (nd_type_p(argn->nd_head, NODE_LIST));
VALUE argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL);
- if (nd_type(argn->nd_body) == NODE_LIST) {
+ if (nd_type_p(argn->nd_body, NODE_LIST)) {
/* This branch is needed to avoid "newarraykwsplat" [Bug #16442] */
int rest_len = compile_args(iseq, args, argn->nd_body, NULL, NULL);
ADD_INSN1(args, argn, newarray, INT2FIX(rest_len));
@@ -5504,7 +5867,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
if (check_keyword(argn->nd_body))
*flag |= VM_CALL_KW_SPLAT;
}
- if (nd_type(argn) == NODE_ARGSCAT) {
+ if (nd_type_p(argn, NODE_ARGSCAT)) {
if (next_is_list) {
ADD_INSN1(args, argn, splatarray, Qtrue);
return INT2FIX(FIX2INT(argc) + 1);
@@ -5535,10 +5898,10 @@ 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_callinfo_kwarg **keywords)
+ unsigned int *flag, struct rb_callinfo_kwarg **keywords)
{
VALUE ret;
- if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
+ if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) {
unsigned int dup_rest = 1;
DECL_ANCHOR(arg_block);
INIT_ANCHOR(arg_block);
@@ -5548,7 +5911,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
if (LIST_INSN_SIZE_ONE(arg_block)) {
LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block);
- if (elem->type == ISEQ_ELEMENT_INSN) {
+ if (IS_INSN(elem)) {
INSN *iobj = (INSN *)elem;
if (iobj->insn_id == BIN(getblockparam)) {
iobj->insn_id = BIN(getblockparamproxy);
@@ -5571,7 +5934,7 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *ptr)
const NODE *body = ptr;
int line = nd_line(body);
VALUE argc = INT2FIX(0);
- const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(iseq->body->parent_iseq), ISEQ_TYPE_BLOCK, line);
+ const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(ISEQ_BODY(iseq)->parent_iseq), ISEQ_TYPE_BLOCK, line);
ADD_INSN1(ret, body, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_CALL_WITH_BLOCK(ret, body, id_core_set_postexe, argc, block);
@@ -5597,44 +5960,44 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
ADD_INSNL(ret, line_node, branchunless, fail_label);
for (vars = node; vars; vars = vars->nd_next) {
- INSN *cap;
- if (vars->nd_next) {
- ADD_INSN(ret, line_node, dup);
- }
- last = ret->last;
+ INSN *cap;
+ if (vars->nd_next) {
+ ADD_INSN(ret, line_node, dup);
+ }
+ last = ret->last;
NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head));
- last = last->next; /* putobject :var */
- cap = new_insn_send(iseq, line_node, idAREF, INT2FIX(1),
- NULL, INT2FIX(0), NULL);
- ELEM_INSERT_PREV(last->next, (LINK_ELEMENT *)cap);
+ last = last->next; /* putobject :var */
+ cap = new_insn_send(iseq, line_node, idAREF, INT2FIX(1),
+ NULL, INT2FIX(0), NULL);
+ ELEM_INSERT_PREV(last->next, (LINK_ELEMENT *)cap);
#if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
- if (!vars->nd_next && vars == node) {
- /* only one name */
- DECL_ANCHOR(nom);
+ if (!vars->nd_next && vars == node) {
+ /* only one name */
+ DECL_ANCHOR(nom);
- INIT_ANCHOR(nom);
- ADD_INSNL(nom, line_node, jump, end_label);
- ADD_LABEL(nom, fail_label);
+ INIT_ANCHOR(nom);
+ ADD_INSNL(nom, line_node, jump, end_label);
+ ADD_LABEL(nom, fail_label);
# if 0 /* $~ must be MatchData or nil */
- ADD_INSN(nom, line_node, pop);
- ADD_INSN(nom, line_node, putnil);
+ ADD_INSN(nom, line_node, pop);
+ ADD_INSN(nom, line_node, putnil);
# endif
- ADD_LABEL(nom, end_label);
- (nom->last->next = cap->link.next)->prev = nom->last;
- (cap->link.next = nom->anchor.next)->prev = &cap->link;
- return;
- }
+ ADD_LABEL(nom, end_label);
+ (nom->last->next = cap->link.next)->prev = nom->last;
+ (cap->link.next = nom->anchor.next)->prev = &cap->link;
+ return;
+ }
#endif
}
ADD_INSNL(ret, line_node, jump, end_label);
ADD_LABEL(ret, fail_label);
ADD_INSN(ret, line_node, pop);
for (vars = node; vars; vars = vars->nd_next) {
- last = ret->last;
+ last = ret->last;
NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head));
- last = last->next; /* putobject :var */
- ((INSN*)last)->insn_id = BIN(putnil);
- ((INSN*)last)->operand_size = 0;
+ last = last->next; /* putobject :var */
+ ((INSN*)last)->insn_id = BIN(putnil);
+ ((INSN*)last)->operand_size = 0;
}
ADD_LABEL(ret, end_label);
}
@@ -5656,7 +6019,7 @@ optimizable_range_item_p(const NODE *n)
static int
compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
{
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const NODE *const node_body = type == NODE_IF ? node->nd_body : node->nd_else;
const NODE *const node_else = type == NODE_IF ? node->nd_else : node->nd_body;
@@ -5679,7 +6042,7 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
end_label = 0;
compile_branch_condition(iseq, cond_seq, node->nd_cond,
- then_label, else_label);
+ then_label, else_label);
ci_size = body->ci_size;
CHECK(COMPILE_(then_seq, "then", node_body, popped));
@@ -5706,44 +6069,44 @@ 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) {
- branches = decl_branch_base(iseq, node, 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_LABEL(ret, then_label);
+ if (else_label->refcnt) {
+ add_trace_branch_coverage(
iseq,
- ret,
+ ret,
node_body ? node_body : node,
0,
- type == NODE_IF ? "then" : "else",
- branches);
- end_label = NEW_LABEL(line);
- ADD_INSNL(then_seq, line_node, jump, end_label);
+ type == NODE_IF ? "then" : "else",
+ branches);
+ end_label = NEW_LABEL(line);
+ ADD_INSNL(then_seq, line_node, jump, end_label);
if (!popped) {
ADD_INSN(then_seq, line_node, pop);
}
- }
- ADD_SEQ(ret, then_seq);
+ }
+ ADD_SEQ(ret, then_seq);
}
if (else_label->refcnt) {
- ADD_LABEL(ret, else_label);
- if (then_label->refcnt) {
- add_trace_branch_coverage(
+ ADD_LABEL(ret, else_label);
+ if (then_label->refcnt) {
+ add_trace_branch_coverage(
iseq,
- ret,
+ ret,
node_else ? node_else : node,
1,
- type == NODE_IF ? "else" : "then",
- branches);
- }
- ADD_SEQ(ret, else_seq);
+ type == NODE_IF ? "else" : "then",
+ branches);
+ }
+ ADD_SEQ(ret, else_seq);
}
if (end_label) {
- ADD_LABEL(ret, end_label);
+ ADD_LABEL(ret, end_label);
}
return COMPILE_OK;
@@ -5788,74 +6151,74 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
ADD_SEQ(ret, head); /* case VAL */
while (type == NODE_WHEN) {
- LABEL *l1;
+ LABEL *l1;
- l1 = NEW_LABEL(line);
- ADD_LABEL(body_seq, l1);
- ADD_INSN(body_seq, line_node, pop);
- add_trace_branch_coverage(
+ l1 = NEW_LABEL(line);
+ ADD_LABEL(body_seq, l1);
+ ADD_INSN(body_seq, line_node, pop);
+ add_trace_branch_coverage(
iseq,
- body_seq,
+ body_seq,
node->nd_body ? node->nd_body : node,
branch_id++,
- "when",
- branches);
- CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped));
- ADD_INSNL(body_seq, line_node, jump, endlabel);
-
- vals = node->nd_head;
- if (vals) {
- switch (nd_type(vals)) {
- case NODE_LIST:
- only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
- if (only_special_literals < 0) return COMPILE_NG;
- break;
- case NODE_SPLAT:
- case NODE_ARGSCAT:
- case NODE_ARGSPUSH:
- only_special_literals = 0;
- CHECK(when_splat_vals(iseq, cond_seq, vals, l1, only_special_literals, literals));
- break;
- default:
- UNKNOWN_NODE("NODE_CASE", vals, COMPILE_NG);
- }
- }
- else {
- EXPECT_NODE_NONULL("NODE_CASE", node, NODE_LIST, COMPILE_NG);
- }
-
- node = node->nd_next;
- if (!node) {
- break;
- }
- type = nd_type(node);
- line = nd_line(node);
+ "when",
+ branches);
+ CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped));
+ ADD_INSNL(body_seq, line_node, jump, endlabel);
+
+ vals = node->nd_head;
+ if (vals) {
+ switch (nd_type(vals)) {
+ case NODE_LIST:
+ only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
+ if (only_special_literals < 0) return COMPILE_NG;
+ break;
+ case NODE_SPLAT:
+ case NODE_ARGSCAT:
+ case NODE_ARGSPUSH:
+ only_special_literals = 0;
+ CHECK(when_splat_vals(iseq, cond_seq, vals, l1, only_special_literals, literals));
+ break;
+ default:
+ UNKNOWN_NODE("NODE_CASE", vals, COMPILE_NG);
+ }
+ }
+ else {
+ EXPECT_NODE_NONULL("NODE_CASE", node, NODE_LIST, COMPILE_NG);
+ }
+
+ node = node->nd_next;
+ if (!node) {
+ break;
+ }
+ type = nd_type(node);
+ line = nd_line(node);
line_node = node;
}
/* else */
if (node) {
- ADD_LABEL(cond_seq, elselabel);
- ADD_INSN(cond_seq, line_node, pop);
- add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches);
- CHECK(COMPILE_(cond_seq, "else", node, popped));
- ADD_INSNL(cond_seq, line_node, jump, endlabel);
+ ADD_LABEL(cond_seq, elselabel);
+ ADD_INSN(cond_seq, line_node, pop);
+ add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches);
+ CHECK(COMPILE_(cond_seq, "else", node, popped));
+ ADD_INSNL(cond_seq, line_node, jump, endlabel);
}
else {
- debugs("== else (implicit)\n");
- ADD_LABEL(cond_seq, elselabel);
- ADD_INSN(cond_seq, orig_node, pop);
- add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
- if (!popped) {
- ADD_INSN(cond_seq, orig_node, putnil);
- }
- ADD_INSNL(cond_seq, orig_node, jump, endlabel);
+ debugs("== else (implicit)\n");
+ ADD_LABEL(cond_seq, elselabel);
+ ADD_INSN(cond_seq, orig_node, pop);
+ add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
+ if (!popped) {
+ ADD_INSN(cond_seq, orig_node, putnil);
+ }
+ ADD_INSNL(cond_seq, orig_node, jump, endlabel);
}
if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
- ADD_INSN(ret, orig_node, dup);
- ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel);
+ ADD_INSN(ret, orig_node, dup);
+ ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel);
RB_OBJ_WRITTEN(iseq, Qundef, literals);
- LABEL_REF(elselabel);
+ LABEL_REF(elselabel);
}
ADD_SEQ(ret, cond_seq);
@@ -5880,57 +6243,57 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
INIT_ANCHOR(body_seq);
endlabel = NEW_LABEL(nd_line(node));
- while (node && nd_type(node) == NODE_WHEN) {
- const int line = nd_line(node);
- LABEL *l1 = NEW_LABEL(line);
- ADD_LABEL(body_seq, l1);
- add_trace_branch_coverage(
+ while (node && nd_type_p(node, NODE_WHEN)) {
+ const int line = nd_line(node);
+ LABEL *l1 = NEW_LABEL(line);
+ ADD_LABEL(body_seq, l1);
+ add_trace_branch_coverage(
iseq,
- body_seq,
- node->nd_body ? node->nd_body : node,
+ body_seq,
+ node->nd_body ? node->nd_body : node,
branch_id++,
- "when",
- branches);
- CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
- ADD_INSNL(body_seq, node, jump, endlabel);
+ "when",
+ branches);
+ CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
+ ADD_INSNL(body_seq, node, jump, endlabel);
- vals = node->nd_head;
- if (!vals) {
+ vals = node->nd_head;
+ if (!vals) {
EXPECT_NODE_NONULL("NODE_WHEN", node, NODE_LIST, COMPILE_NG);
- }
- switch (nd_type(vals)) {
- case NODE_LIST:
- while (vals) {
- LABEL *lnext;
- val = vals->nd_head;
- lnext = NEW_LABEL(nd_line(val));
- debug_compile("== when2\n", (void)0);
- CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
- ADD_LABEL(ret, lnext);
- vals = vals->nd_next;
- }
- break;
- case NODE_SPLAT:
- case NODE_ARGSCAT:
- case NODE_ARGSPUSH:
- ADD_INSN(ret, vals, putnil);
- CHECK(COMPILE(ret, "when2/cond splat", vals));
- ADD_INSN1(ret, vals, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
- ADD_INSNL(ret, vals, branchif, l1);
- break;
- default:
- UNKNOWN_NODE("NODE_WHEN", vals, COMPILE_NG);
- }
- node = node->nd_next;
+ }
+ switch (nd_type(vals)) {
+ case NODE_LIST:
+ while (vals) {
+ LABEL *lnext;
+ val = vals->nd_head;
+ lnext = NEW_LABEL(nd_line(val));
+ debug_compile("== when2\n", (void)0);
+ CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
+ ADD_LABEL(ret, lnext);
+ vals = vals->nd_next;
+ }
+ break;
+ case NODE_SPLAT:
+ case NODE_ARGSCAT:
+ case NODE_ARGSPUSH:
+ ADD_INSN(ret, vals, putnil);
+ CHECK(COMPILE(ret, "when2/cond splat", vals));
+ ADD_INSN1(ret, vals, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
+ ADD_INSNL(ret, vals, branchif, l1);
+ break;
+ default:
+ UNKNOWN_NODE("NODE_WHEN", vals, COMPILE_NG);
+ }
+ node = node->nd_next;
}
/* else */
add_trace_branch_coverage(
iseq,
- ret,
+ ret,
node ? node : orig_node,
branch_id,
- "else",
- branches);
+ "else",
+ branches);
CHECK(COMPILE_(ret, "else", node, popped));
ADD_INSNL(ret, orig_node, jump, endlabel);
@@ -5939,12 +6302,22 @@ 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_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache);
-static int iseq_compile_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_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *match_failed, bool in_single_pattern, int base_index);
+static int iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, bool in_single_pattern, int base_index, bool use_deconstructed_cache);
+static int iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, int base_index);
+static int iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, VALUE pattern_length, int base_index);
+static int iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int base_index);
+
+#define CASE3_BI_OFFSET_DECONSTRUCTED_CACHE 0
+#define CASE3_BI_OFFSET_ERROR_STRING 1
+#define CASE3_BI_OFFSET_KEY_ERROR_P 2
+#define CASE3_BI_OFFSET_KEY_ERROR_MATCHEE 3
+#define CASE3_BI_OFFSET_KEY_ERROR_KEY 4
static int
-iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, int in_alt_pattern, int deconstructed_pos)
+iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache)
{
const int line = nd_line(node);
const NODE *line_node = node;
@@ -6022,31 +6395,32 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
if (use_rest_num) {
ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); /* allocate stack for rest_num */
ADD_INSN(ret, line_node, swap);
- if (deconstructed_pos) {
- deconstructed_pos++;
+ if (base_index) {
+ base_index++;
}
}
- if (node->nd_pconst) {
- ADD_INSN(ret, line_node, dup);
- CHECK(COMPILE(ret, "constant", node->nd_pconst));
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
- ADD_INSNL(ret, line_node, branchunless, match_failed);
- }
+ CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
- CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
+ CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
ADD_INSN(ret, line_node, dup);
ADD_SEND(ret, line_node, idLength, INT2FIX(0));
ADD_INSN1(ret, line_node, putobject, INT2FIX(min_argc));
- ADD_SEND(ret, line_node, apinfo->rest_arg ? idGE : idEq, INT2FIX(1));
+ ADD_SEND(ret, line_node, apinfo->rest_arg ? idGE : idEq, INT2FIX(1)); // (1)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node,
+ apinfo->rest_arg ? rb_fstring_lit("%p length mismatch (given %p, expected %p+)") :
+ rb_fstring_lit("%p length mismatch (given %p, expected %p)"),
+ INT2FIX(min_argc), base_index + 1 /* (1) */));
+ }
ADD_INSNL(ret, line_node, branchunless, match_failed);
for (i = 0; i < pre_args_num; i++) {
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, putobject, INT2FIX(i));
- ADD_SEND(ret, line_node, idAREF, INT2FIX(1));
- CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern, FALSE));
+ ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (2)
+ CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (2) */, false));
args = args->nd_next;
}
@@ -6059,9 +6433,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line_node, putobject, INT2FIX(min_argc));
ADD_SEND(ret, line_node, idMINUS, INT2FIX(1));
ADD_INSN1(ret, line_node, setn, INT2FIX(4));
- ADD_SEND(ret, line_node, idAREF, INT2FIX(2));
+ ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (3)
- CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_alt_pattern, FALSE));
+ CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (3) */, false));
}
else {
if (post_args_num > 0) {
@@ -6083,8 +6457,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line_node, topn, INT2FIX(3));
ADD_SEND(ret, line_node, idPLUS, INT2FIX(1));
- ADD_SEND(ret, line_node, idAREF, INT2FIX(1));
- CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern, FALSE));
+ ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (4)
+ CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (4) */, false));
args = args->nd_next;
}
@@ -6173,19 +6547,17 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
deconstruct = NEW_LABEL(line);
deconstructed = NEW_LABEL(line);
- if (node->nd_pconst) {
- ADD_INSN(ret, line_node, dup);
- CHECK(COMPILE(ret, "constant", node->nd_pconst));
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
- ADD_INSNL(ret, line_node, branchunless, match_failed);
- }
+ CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
- CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
+ CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
ADD_INSN(ret, line_node, dup);
ADD_SEND(ret, line_node, idLength, INT2FIX(0));
ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num));
- ADD_SEND(ret, line_node, idGE, INT2FIX(1));
+ ADD_SEND(ret, line_node, idGE, INT2FIX(1)); // (1)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node, rb_fstring_lit("%p length mismatch (given %p, expected %p+)"), INT2FIX(args_num), base_index + 1 /* (1) */));
+ }
ADD_INSNL(ret, line_node, branchunless, match_failed);
{
@@ -6196,13 +6568,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
int j;
ADD_INSN(ret, line_node, dup); /* allocate stack for len */
- ADD_SEND(ret, line_node, idLength, INT2FIX(0));
+ ADD_SEND(ret, line_node, idLength, INT2FIX(0)); // (2)
ADD_INSN(ret, line_node, dup); /* allocate stack for limit */
ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num));
- ADD_SEND(ret, line_node, idMINUS, INT2FIX(1));
+ ADD_SEND(ret, line_node, idMINUS, INT2FIX(1)); // (3)
- ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); /* allocate stack for i */
+ ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); /* allocate stack for i */ // (4)
ADD_LABEL(ret, while_begin);
@@ -6218,9 +6590,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line_node, putobject, INT2FIX(j));
ADD_SEND(ret, line_node, idPLUS, INT2FIX(1));
}
- ADD_SEND(ret, line_node, idAREF, INT2FIX(1));
+ ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (5)
- CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, next_loop, in_alt_pattern, FALSE));
+ CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (5) */, false));
args = args->nd_next;
}
@@ -6228,8 +6600,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line_node, topn, INT2FIX(3));
ADD_INSN1(ret, line_node, putobject, INT2FIX(0));
ADD_INSN1(ret, line_node, topn, INT2FIX(2));
- ADD_SEND(ret, line_node, idAREF, INT2FIX(2));
- CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->pre_rest_arg, find_failed, in_alt_pattern, FALSE));
+ ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (6)
+ CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->pre_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (6) */, false));
}
if (NODE_NAMED_REST_P(fpinfo->post_rest_arg)) {
ADD_INSN1(ret, line_node, topn, INT2FIX(3));
@@ -6237,8 +6609,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num));
ADD_SEND(ret, line_node, idPLUS, INT2FIX(1));
ADD_INSN1(ret, line_node, topn, INT2FIX(3));
- ADD_SEND(ret, line_node, idAREF, INT2FIX(2));
- CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->post_rest_arg, find_failed, in_alt_pattern, FALSE));
+ ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (7)
+ CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->post_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3),(4), (7) */, false));
}
ADD_INSNL(ret, line_node, jump, find_succeeded);
@@ -6248,16 +6620,25 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSNL(ret, line_node, jump, while_begin);
ADD_LABEL(ret, find_failed);
- ADD_INSN(ret, line_node, pop);
- ADD_INSN(ret, line_node, pop);
- ADD_INSN(ret, line_node, pop);
+ ADD_INSN1(ret, line_node, adjuststack, INT2FIX(3));
+ if (in_single_pattern) {
+ ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("%p does not match to find pattern"));
+ ADD_INSN1(ret, line_node, topn, INT2FIX(2));
+ ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(2)); // (8)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (8) */)); // (9)
+
+ ADD_INSN1(ret, line_node, putobject, Qfalse);
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (8), (9) */));
+
+ ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
+ }
ADD_INSNL(ret, line_node, jump, match_failed);
ADD_INSN1(ret, line_node, dupn, INT2FIX(3));
ADD_LABEL(ret, find_succeeded);
- ADD_INSN(ret, line_node, pop);
- ADD_INSN(ret, line_node, pop);
- ADD_INSN(ret, line_node, pop);
+ ADD_INSN1(ret, line_node, adjuststack, INT2FIX(3));
}
ADD_INSN(ret, line_node, pop);
@@ -6352,16 +6733,14 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
}
- if (node->nd_pconst) {
- ADD_INSN(ret, line_node, dup);
- CHECK(COMPILE(ret, "constant", node->nd_pconst));
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
- ADD_INSNL(ret, line_node, branchunless, match_failed);
- }
+ CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, putobject, ID2SYM(rb_intern("deconstruct_keys")));
- ADD_SEND(ret, line_node, idRespond_to, INT2FIX(1));
+ ADD_SEND(ret, line_node, idRespond_to, INT2FIX(1)); // (1)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("%p does not respond to #deconstruct_keys"), base_index + 1 /* (1) */));
+ }
ADD_INSNL(ret, line_node, branchunless, match_failed);
if (NIL_P(keys)) {
@@ -6371,7 +6750,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line_node, duparray, keys);
RB_OBJ_WRITTEN(iseq, Qundef, rb_obj_hide(keys));
}
- ADD_SEND(ret, line_node, rb_intern("deconstruct_keys"), INT2FIX(1));
+ ADD_SEND(ret, line_node, rb_intern("deconstruct_keys"), INT2FIX(1)); // (2)
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, checktype, INT2FIX(T_HASH));
@@ -6395,20 +6774,40 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
NODE *value_node = args->nd_next->nd_head;
VALUE key;
- if (nd_type(key_node) != NODE_LIT) {
+ if (!nd_type_p(key_node, NODE_LIT)) {
UNKNOWN_NODE("NODE_IN", key_node, COMPILE_NG);
}
key = key_node->nd_lit;
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, putobject, key);
- ADD_SEND(ret, line_node, rb_intern("key?"), INT2FIX(1));
+ ADD_SEND(ret, line_node, rb_intern("key?"), INT2FIX(1)); // (3)
+ if (in_single_pattern) {
+ LABEL *match_succeeded;
+ match_succeeded = NEW_LABEL(line);
+
+ ADD_INSN(ret, line_node, dup);
+ ADD_INSNL(ret, line_node, branchif, match_succeeded);
+
+ ADD_INSN1(ret, line_node, putobject, rb_str_freeze(rb_sprintf("key not found: %+"PRIsVALUE, key))); // (4)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 2 /* (3), (4) */));
+ ADD_INSN1(ret, line_node, putobject, Qtrue); // (5)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 3 /* (3), (4), (5) */));
+ ADD_INSN1(ret, line_node, topn, INT2FIX(3)); // (6)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4 /* (3), (4), (5), (6) */));
+ ADD_INSN1(ret, line_node, putobject, key); // (7)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_KEY + 5 /* (3), (4), (5), (6), (7) */));
+
+ ADD_INSN1(ret, line_node, adjuststack, INT2FIX(4));
+
+ ADD_LABEL(ret, match_succeeded);
+ }
ADD_INSNL(ret, line_node, branchunless, match_failed);
ADD_INSN(match_values, line_node, dup);
ADD_INSN1(match_values, line_node, putobject, key);
- ADD_SEND(match_values, line_node, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1));
- CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_alt_pattern, FALSE));
+ ADD_SEND(match_values, line_node, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); // (8)
+ CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (8) */, false));
args = args->nd_next->nd_next;
}
ADD_SEQ(ret, match_values);
@@ -6416,19 +6815,25 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
else {
ADD_INSN(ret, line_node, dup);
- ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0));
+ ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0)); // (9)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("%p is not empty"), base_index + 1 /* (9) */));
+ }
ADD_INSNL(ret, line_node, branchunless, match_failed);
}
if (node->nd_pkwrestarg) {
if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
ADD_INSN(ret, line_node, dup);
- ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0));
+ ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0)); // (10)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("rest of %p is not empty"), base_index + 1 /* (10) */));
+ }
ADD_INSNL(ret, line_node, branchunless, match_failed);
}
else {
- ADD_INSN(ret, line_node, dup);
- CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_alt_pattern, FALSE));
+ ADD_INSN(ret, line_node, dup); // (11)
+ CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (11) */, false));
}
}
@@ -6472,15 +6877,21 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
case NODE_COLON2:
case NODE_COLON3:
case NODE_BEGIN:
- CHECK(COMPILE(ret, "case in literal", node));
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
+ CHECK(COMPILE(ret, "case in literal", node)); // (1)
+ if (in_single_pattern) {
+ ADD_INSN1(ret, line_node, dupn, INT2FIX(2));
+ }
+ ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); // (2)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 2 /* (1), (2) */));
+ }
ADD_INSNL(ret, line_node, branchif, matched);
ADD_INSNL(ret, line_node, jump, unmatched);
break;
case NODE_LASGN: {
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
ID id = node->nd_vid;
- int idx = body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);
+ int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq, id);
if (in_alt_pattern) {
const char *name = rb_id2name(id);
@@ -6495,8 +6906,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSNL(ret, line_node, jump, matched);
break;
}
- case NODE_DASGN:
- case NODE_DASGN_CURR: {
+ case NODE_DASGN: {
int idx, lv, ls;
ID id = node->nd_vid;
@@ -6512,7 +6922,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
if (idx < 0) {
- COMPILE_ERROR(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")",
+ COMPILE_ERROR(ERROR_ARGS "NODE_DASGN: unknown id (%"PRIsVALUE")",
rb_id2str(id));
return COMPILE_NG;
}
@@ -6524,9 +6934,31 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
case NODE_UNLESS: {
LABEL *match_failed;
match_failed = unmatched;
- CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_alt_pattern, deconstructed_pos));
+ CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
CHECK(COMPILE(ret, "case in if", node->nd_cond));
- if (nd_type(node) == NODE_IF) {
+ if (in_single_pattern) {
+ LABEL *match_succeeded;
+ match_succeeded = NEW_LABEL(line);
+
+ ADD_INSN(ret, line_node, dup);
+ if (nd_type_p(node, NODE_IF)) {
+ ADD_INSNL(ret, line_node, branchif, match_succeeded);
+ }
+ else {
+ ADD_INSNL(ret, line_node, branchunless, match_succeeded);
+ }
+
+ ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("guard clause does not return true")); // (1)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2)
+ ADD_INSN1(ret, line_node, putobject, Qfalse);
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (1), (2) */));
+
+ ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
+
+ ADD_LABEL(ret, match_succeeded);
+ }
+ if (nd_type_p(node, NODE_IF)) {
ADD_INSNL(ret, line_node, branchunless, match_failed);
}
else {
@@ -6541,14 +6973,14 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
match_failed = NEW_LABEL(line);
n = node->nd_head;
- if (! (nd_type(n) == NODE_LIST && n->nd_alen == 2)) {
+ if (! (nd_type_p(n, NODE_LIST) && n->nd_alen == 2)) {
COMPILE_ERROR(ERROR_ARGS "unexpected node");
return COMPILE_NG;
}
- ADD_INSN(ret, line_node, dup);
- 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_node, dup); // (1)
+ CHECK(iseq_compile_pattern_match(iseq, ret, n->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (1) */, use_deconstructed_cache));
+ CHECK(iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index, false));
ADD_INSN(ret, line_node, putnil);
ADD_LABEL(ret, match_failed);
@@ -6561,14 +6993,14 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
match_succeeded = NEW_LABEL(line);
fin = NEW_LABEL(line);
- ADD_INSN(ret, line_node, dup);
- CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin, TRUE, deconstructed_pos ? deconstructed_pos + 1 : FALSE));
+ ADD_INSN(ret, line_node, dup); // (1)
+ CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin, in_single_pattern, true, base_index + 1 /* (1) */, use_deconstructed_cache));
ADD_LABEL(ret, match_succeeded);
ADD_INSN(ret, line_node, pop);
ADD_INSNL(ret, line_node, jump, matched);
ADD_INSN(ret, line_node, putnil);
ADD_LABEL(ret, fin);
- CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched, TRUE, deconstructed_pos));
+ CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched, in_single_pattern, true, base_index, use_deconstructed_cache));
break;
}
default:
@@ -6578,35 +7010,54 @@ 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)
+iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache)
{
LABEL *fin = NEW_LABEL(nd_line(node));
- CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_alt_pattern, deconstructed_pos));
+ CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
ADD_LABEL(ret, fin);
return COMPILE_OK;
}
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)
+iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *match_failed, bool in_single_pattern, int base_index)
+{
+ const NODE *line_node = node;
+
+ if (node->nd_pconst) {
+ ADD_INSN(ret, line_node, dup); // (1)
+ CHECK(COMPILE(ret, "constant", node->nd_pconst)); // (2)
+ if (in_single_pattern) {
+ ADD_INSN1(ret, line_node, dupn, INT2FIX(2));
+ }
+ ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); // (3)
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_eqq_errmsg(iseq, ret, node, base_index + 3 /* (1), (2), (3) */));
+ }
+ ADD_INSNL(ret, line_node, branchunless, match_failed);
+ }
+ return COMPILE_OK;
+}
+
+
+static int
+iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, bool in_single_pattern, int base_index, bool use_deconstructed_cache)
{
const NODE *line_node = node;
// NOTE: this optimization allows us to re-use the #deconstruct value
// (or its absence).
- // `deconstructed_pos` contains the distance to the stack relative location
- // where the value is stored.
- if (deconstructed_pos) {
+ if (use_deconstructed_cache) {
// If value is nil then we haven't tried to deconstruct
- ADD_INSN1(ret, line_node, topn, INT2FIX(deconstructed_pos));
+ ADD_INSN1(ret, line_node, topn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
ADD_INSNL(ret, line_node, branchnil, deconstruct);
// If false then the value is not deconstructable
- ADD_INSN1(ret, line_node, topn, INT2FIX(deconstructed_pos));
+ ADD_INSN1(ret, line_node, topn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
ADD_INSNL(ret, line_node, branchunless, match_failed);
// Drop value, add deconstructed to the stack and jump
- ADD_INSN(ret, line_node, pop);
- ADD_INSN1(ret, line_node, topn, INT2FIX(deconstructed_pos - 1));
+ ADD_INSN(ret, line_node, pop); // (1)
+ ADD_INSN1(ret, line_node, topn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE - 1 /* (1) */));
ADD_INSNL(ret, line_node, jump, deconstructed);
}
else {
@@ -6616,11 +7067,15 @@ iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NO
ADD_LABEL(ret, deconstruct);
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, putobject, ID2SYM(rb_intern("deconstruct")));
- ADD_SEND(ret, line_node, idRespond_to, INT2FIX(1));
+ ADD_SEND(ret, line_node, idRespond_to, INT2FIX(1)); // (2)
// Cache the result of respond_to? (in case it's false is stays there, if true - it's overwritten after #deconstruct)
- if (deconstructed_pos) {
- ADD_INSN1(ret, line_node, setn, INT2FIX(deconstructed_pos + 1));
+ if (use_deconstructed_cache) {
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE + 1 /* (2) */));
+ }
+
+ if (in_single_pattern) {
+ CHECK(iseq_compile_pattern_set_general_errmsg(iseq, ret, node, rb_fstring_lit("%p does not respond to #deconstruct"), base_index + 1 /* (2) */));
}
ADD_INSNL(ret, line_node, branchunless, match_failed);
@@ -6628,14 +7083,13 @@ iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NO
ADD_SEND(ret, line_node, 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_node, setn, INT2FIX(deconstructed_pos));
+ if (use_deconstructed_cache) {
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_DECONSTRUCTED_CACHE));
}
ADD_INSN(ret, line_node, dup);
ADD_INSN1(ret, line_node, checktype, INT2FIX(T_ARRAY));
ADD_INSNL(ret, line_node, branchunless, type_error);
- ADD_INSNL(ret, line_node, jump, deconstructed);
ADD_LABEL(ret, deconstructed);
@@ -6643,6 +7097,116 @@ iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NO
}
static int
+iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, int base_index)
+{
+ /*
+ * if match_succeeded?
+ * goto match_succeeded
+ * end
+ * error_string = FrozenCore.sprintf(errmsg, matchee)
+ * key_error_p = false
+ * match_succeeded:
+ */
+ const int line = nd_line(node);
+ const NODE *line_node = node;
+ LABEL *match_succeeded = NEW_LABEL(line);
+
+ ADD_INSN(ret, line_node, dup);
+ ADD_INSNL(ret, line_node, branchif, match_succeeded);
+
+ ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, line_node, putobject, errmsg);
+ ADD_INSN1(ret, line_node, topn, INT2FIX(3));
+ ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(2)); // (1)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2)
+
+ ADD_INSN1(ret, line_node, putobject, Qfalse);
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (1), (2) */));
+
+ ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
+ ADD_LABEL(ret, match_succeeded);
+
+ return COMPILE_OK;
+}
+
+static int
+iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, VALUE pattern_length, int base_index)
+{
+ /*
+ * if match_succeeded?
+ * goto match_succeeded
+ * end
+ * error_string = FrozenCore.sprintf(errmsg, matchee, matchee.length, pat.length)
+ * key_error_p = false
+ * match_succeeded:
+ */
+ const int line = nd_line(node);
+ const NODE *line_node = node;
+ LABEL *match_succeeded = NEW_LABEL(line);
+
+ ADD_INSN(ret, line_node, dup);
+ ADD_INSNL(ret, line_node, branchif, match_succeeded);
+
+ ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, line_node, putobject, errmsg);
+ ADD_INSN1(ret, line_node, topn, INT2FIX(3));
+ ADD_INSN(ret, line_node, dup);
+ ADD_SEND(ret, line_node, idLength, INT2FIX(0));
+ ADD_INSN1(ret, line_node, putobject, pattern_length);
+ ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(4)); // (1)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2)
+
+ ADD_INSN1(ret, line_node, putobject, Qfalse);
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2/* (1), (2) */));
+
+ ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
+ ADD_LABEL(ret, match_succeeded);
+
+ return COMPILE_OK;
+}
+
+static int
+iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int base_index)
+{
+ /*
+ * if match_succeeded?
+ * goto match_succeeded
+ * end
+ * error_string = FrozenCore.sprintf("%p === %p does not return true", pat, matchee)
+ * key_error_p = false
+ * match_succeeded:
+ */
+ const int line = nd_line(node);
+ const NODE *line_node = node;
+ LABEL *match_succeeded = NEW_LABEL(line);
+
+ ADD_INSN(ret, line_node, dup);
+ ADD_INSNL(ret, line_node, branchif, match_succeeded);
+
+ ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, line_node, putobject, rb_fstring_lit("%p === %p does not return true"));
+ ADD_INSN1(ret, line_node, topn, INT2FIX(3));
+ ADD_INSN1(ret, line_node, topn, INT2FIX(5));
+ ADD_SEND(ret, line_node, id_core_sprintf, INT2FIX(3)); // (1)
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_ERROR_STRING + 1 /* (1) */)); // (2)
+
+ ADD_INSN1(ret, line_node, putobject, Qfalse);
+ ADD_INSN1(ret, line_node, setn, INT2FIX(base_index + CASE3_BI_OFFSET_KEY_ERROR_P + 2 /* (1), (2) */));
+
+ ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
+
+ ADD_LABEL(ret, match_succeeded);
+ ADD_INSN1(ret, line_node, setn, INT2FIX(2));
+ ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
+
+ return COMPILE_OK;
+}
+
+static int
compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_node, int popped)
{
const NODE *pattern;
@@ -6656,6 +7220,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
const NODE *line_node;
VALUE branches = 0;
int branch_id = 0;
+ bool single_pattern;
INIT_ANCHOR(head);
INIT_ANCHOR(body_seq);
@@ -6668,10 +7233,18 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
type = nd_type(node);
line = nd_line(node);
line_node = node;
+ single_pattern = !node->nd_next;
endlabel = NEW_LABEL(line);
elselabel = NEW_LABEL(line);
+ if (single_pattern) {
+ /* allocate stack for ... */
+ ADD_INSN(head, line_node, putnil); /* key_error_key */
+ ADD_INSN(head, line_node, putnil); /* key_error_matchee */
+ ADD_INSN1(head, line_node, putobject, Qfalse); /* key_error_p */
+ ADD_INSN(head, line_node, putnil); /* error_string */
+ }
ADD_INSN(head, line_node, putnil); /* allocate stack for cached #deconstruct value */
CHECK(COMPILE(head, "case base", orig_node->nd_head));
@@ -6686,8 +7259,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
}
l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
- ADD_INSN(body_seq, line_node, pop);
- ADD_INSN(body_seq, line_node, pop); /* discard cached #deconstruct value */
+ ADD_INSN1(body_seq, line_node, adjuststack, INT2FIX(single_pattern ? 6 : 2));
add_trace_branch_coverage(
iseq,
body_seq,
@@ -6702,10 +7274,9 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
if (pattern) {
int pat_line = nd_line(pattern);
LABEL *next_pat = NEW_LABEL(pat_line);
- ADD_INSN (cond_seq, pattern, 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_INSN (cond_seq, pattern, dup); /* dup case VAL */
+ // NOTE: set base_index (it's "under" the matchee value, so it's position is 2)
+ CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat, single_pattern, false, 2, true));
ADD_LABEL(cond_seq, next_pat);
LABEL_UNREMOVABLE(next_pat);
}
@@ -6740,17 +7311,62 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
ADD_LABEL(cond_seq, elselabel);
add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternError);
- ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(2));
- ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(2));
- ADD_INSN(cond_seq, orig_node, pop);
- ADD_INSN(cond_seq, orig_node, pop);
- ADD_INSN(cond_seq, orig_node, pop); /* discard cached #deconstruct value */
+
+ if (single_pattern) {
+ /*
+ * if key_error_p
+ * FrozenCore.raise NoMatchingPatternKeyError.new(FrozenCore.sprintf("%p: %s", case_val, error_string), matchee: key_error_matchee, key: key_error_key)
+ * else
+ * FrozenCore.raise NoMatchingPatternError, FrozenCore.sprintf("%p: %s", case_val, error_string)
+ * end
+ */
+ LABEL *key_error, *fin;
+ struct rb_callinfo_kwarg *kw_arg;
+
+ key_error = NEW_LABEL(line);
+ fin = NEW_LABEL(line);
+
+ kw_arg = rb_xmalloc_mul_add(2, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg));
+ kw_arg->keyword_len = 2;
+ kw_arg->keywords[0] = ID2SYM(rb_intern("matchee"));
+ kw_arg->keywords[1] = ID2SYM(rb_intern("key"));
+
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_P + 2));
+ ADD_INSNL(cond_seq, orig_node, branchif, key_error);
+ ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternError);
+ ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit("%p: %s"));
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(4)); /* case VAL */
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
+ ADD_SEND(cond_seq, orig_node, id_core_sprintf, INT2FIX(3));
+ ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(2));
+ ADD_INSNL(cond_seq, orig_node, jump, fin);
+
+ ADD_LABEL(cond_seq, key_error);
+ ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternKeyError);
+ ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(cond_seq, orig_node, putobject, rb_fstring_lit("%p: %s"));
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(4)); /* case VAL */
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_ERROR_STRING + 6));
+ ADD_SEND(cond_seq, orig_node, id_core_sprintf, INT2FIX(3));
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_MATCHEE + 4));
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(CASE3_BI_OFFSET_KEY_ERROR_KEY + 5));
+ ADD_SEND_R(cond_seq, orig_node, rb_intern("new"), INT2FIX(1), NULL, INT2FIX(VM_CALL_KWARG), kw_arg);
+ ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(1));
+
+ ADD_LABEL(cond_seq, fin);
+ }
+ else {
+ ADD_INSN1(cond_seq, orig_node, putobject, rb_eNoMatchingPatternError);
+ ADD_INSN1(cond_seq, orig_node, topn, INT2FIX(2));
+ ADD_SEND(cond_seq, orig_node, id_core_raise, INT2FIX(2));
+ }
+ ADD_INSN1(cond_seq, orig_node, adjuststack, INT2FIX(single_pattern ? 7 : 3));
if (!popped) {
ADD_INSN(cond_seq, orig_node, putnil);
}
ADD_INSNL(cond_seq, orig_node, jump, endlabel);
- ADD_INSN(cond_seq, line_node, putnil);
+ ADD_INSN1(cond_seq, orig_node, dupn, INT2FIX(single_pattern ? 5 : 1));
if (popped) {
ADD_INSN(cond_seq, line_node, putnil);
}
@@ -6762,6 +7378,12 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
return COMPILE_OK;
}
+#undef CASE3_BI_OFFSET_DECONSTRUCTED_CACHE
+#undef CASE3_BI_OFFSET_ERROR_STRING
+#undef CASE3_BI_OFFSET_KEY_ERROR_P
+#undef CASE3_BI_OFFSET_KEY_ERROR_MATCHEE
+#undef CASE3_BI_OFFSET_KEY_ERROR_KEY
+
static int
compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
{
@@ -6789,11 +7411,11 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
push_ensure_entry(iseq, &enl, NULL, NULL);
if (node->nd_state == 1) {
- ADD_INSNL(ret, line_node, jump, next_label);
+ ADD_INSNL(ret, line_node, jump, next_label);
}
else {
- tmp_label = NEW_LABEL(line);
- ADD_INSNL(ret, line_node, jump, tmp_label);
+ tmp_label = NEW_LABEL(line);
+ ADD_INSNL(ret, line_node, jump, tmp_label);
}
ADD_LABEL(ret, adjust_label);
ADD_INSN(ret, line_node, putnil);
@@ -6806,48 +7428,48 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
branches = decl_branch_base(iseq, node, type == NODE_WHILE ? "while" : "until");
add_trace_branch_coverage(
iseq,
- ret,
+ ret,
node->nd_body ? node->nd_body : node,
0,
- "body",
- branches);
+ "body",
+ branches);
CHECK(COMPILE_POPPED(ret, "while body", node->nd_body));
ADD_LABEL(ret, next_label); /* next */
if (type == NODE_WHILE) {
- compile_branch_condition(iseq, ret, node->nd_cond,
- redo_label, end_label);
+ compile_branch_condition(iseq, ret, node->nd_cond,
+ redo_label, end_label);
}
else {
- /* until */
- compile_branch_condition(iseq, ret, node->nd_cond,
- end_label, redo_label);
+ /* until */
+ compile_branch_condition(iseq, ret, node->nd_cond,
+ end_label, redo_label);
}
ADD_LABEL(ret, end_label);
ADD_ADJUST_RESTORE(ret, adjust_label);
- if (node->nd_state == Qundef) {
- /* ADD_INSN(ret, line_node, putundef); */
- COMPILE_ERROR(ERROR_ARGS "unsupported: putundef");
- return COMPILE_NG;
+ if (UNDEF_P(node->nd_state)) {
+ /* ADD_INSN(ret, line_node, putundef); */
+ COMPILE_ERROR(ERROR_ARGS "unsupported: putundef");
+ return COMPILE_NG;
}
else {
- ADD_INSN(ret, line_node, putnil);
+ ADD_INSN(ret, line_node, putnil);
}
ADD_LABEL(ret, break_label); /* break */
if (popped) {
- ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
}
ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL,
- break_label);
+ break_label);
ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL,
- next_catch_label);
+ next_catch_label);
ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL,
- ISEQ_COMPILE_DATA(iseq)->redo_label);
+ ISEQ_COMPILE_DATA(iseq)->redo_label);
ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
@@ -6868,24 +7490,47 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
const rb_iseq_t *child_iseq;
ADD_LABEL(ret, retry_label);
- if (nd_type(node) == NODE_FOR) {
- CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter));
+ if (nd_type_p(node, NODE_FOR)) {
+ CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter));
- ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
- NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
- ISEQ_TYPE_BLOCK, line);
- ADD_SEND_WITH_BLOCK(ret, line_node, idEach, INT2FIX(0), child_iseq);
+ ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
+ NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
+ ISEQ_TYPE_BLOCK, line);
+ ADD_SEND_WITH_BLOCK(ret, line_node, idEach, INT2FIX(0), child_iseq);
}
else {
- ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
- NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
- ISEQ_TYPE_BLOCK, line);
- CHECK(COMPILE(ret, "iter caller", node->nd_iter));
+ ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
+ NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
+ ISEQ_TYPE_BLOCK, line);
+ CHECK(COMPILE(ret, "iter caller", node->nd_iter));
+ }
+
+ {
+ // We need to put the label "retry_end_l" immediately after the last "send" instruction.
+ // This because vm_throw checks if the break cont is equal to the index of next insn of the "send".
+ // (Otherwise, it is considered "break from proc-closure". See "TAG_BREAK" handling in "vm_throw_start".)
+ //
+ // Normally, "send" instruction is at the last.
+ // However, qcall under branch coverage measurement adds some instructions after the "send".
+ //
+ // Note that "invokesuper" appears instead of "send".
+ INSN *iobj;
+ LINK_ELEMENT *last_elem = LAST_ELEMENT(ret);
+ iobj = IS_INSN(last_elem) ? (INSN*) last_elem : (INSN*) get_prev_insn((INSN*) last_elem);
+ while (INSN_OF(iobj) != BIN(send) && INSN_OF(iobj) != BIN(invokesuper)) {
+ iobj = (INSN*) get_prev_insn(iobj);
+ }
+ ELEM_INSERT_NEXT(&iobj->link, (LINK_ELEMENT*) retry_end_l);
+
+ // LINK_ANCHOR has a pointer to the last element, but ELEM_INSERT_NEXT does not update it
+ // even if we add an insn to the last of LINK_ANCHOR. So this updates it manually.
+ if (&iobj->link == LAST_ELEMENT(ret)) {
+ ret->last = (LINK_ELEMENT*) retry_end_l;
+ }
}
- ADD_LABEL(ret, retry_end_l);
if (popped) {
- ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
}
ISEQ_COMPILE_DATA(iseq)->current_block = prevblock;
@@ -6932,41 +7577,41 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
unsigned long throw_flag = 0;
if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
- /* while/until */
- LABEL *splabel = NEW_LABEL(0);
- ADD_LABEL(ret, splabel);
- ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
- CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
- ISEQ_COMPILE_DATA(iseq)->loopval_popped));
- add_ensure_iseq(ret, iseq, 0);
- ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
- ADD_ADJUST_RESTORE(ret, splabel);
-
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
+ /* while/until */
+ LABEL *splabel = NEW_LABEL(0);
+ ADD_LABEL(ret, splabel);
+ ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
+ ISEQ_COMPILE_DATA(iseq)->loopval_popped));
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+
+ if (!popped) {
+ ADD_INSN(ret, line_node, putnil);
+ }
}
else {
const rb_iseq_t *ip = iseq;
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
+ }
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
throw_flag = VM_THROW_NO_ESCAPE_FLAG;
- }
- else if (ip->body->type == ISEQ_TYPE_BLOCK) {
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
throw_flag = 0;
- }
- else if (ip->body->type == ISEQ_TYPE_EVAL) {
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
return COMPILE_NG;
- }
+ }
else {
- ip = ip->body->parent_iseq;
+ ip = ISEQ_BODY(ip)->parent_iseq;
continue;
}
@@ -6977,9 +7622,9 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_INSN(ret, line_node, pop);
}
return COMPILE_OK;
- }
- COMPILE_ERROR(ERROR_ARGS "Invalid break");
- return COMPILE_NG;
+ }
+ COMPILE_ERROR(ERROR_ARGS "Invalid break");
+ return COMPILE_NG;
}
return COMPILE_OK;
}
@@ -6991,69 +7636,68 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
unsigned long throw_flag = 0;
if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
- debugs("next in while loop\n");
- ADD_LABEL(ret, splabel);
- CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
- add_ensure_iseq(ret, iseq, 0);
- ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
- ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
- ADD_ADJUST_RESTORE(ret, splabel);
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
+ LABEL *splabel = NEW_LABEL(0);
+ debugs("next in while loop\n");
+ ADD_LABEL(ret, splabel);
+ CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+ if (!popped) {
+ ADD_INSN(ret, line_node, putnil);
+ }
}
else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
- debugs("next in block\n");
- ADD_LABEL(ret, splabel);
- ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
- CHECK(COMPILE(ret, "next val", node->nd_stts));
- add_ensure_iseq(ret, iseq, 0);
- ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
- ADD_ADJUST_RESTORE(ret, splabel);
- splabel->unremovable = FALSE;
-
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
+ LABEL *splabel = NEW_LABEL(0);
+ debugs("next in block\n");
+ ADD_LABEL(ret, splabel);
+ ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
+ CHECK(COMPILE(ret, "next val", node->nd_stts));
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+
+ if (!popped) {
+ ADD_INSN(ret, line_node, putnil);
+ }
}
else {
- const rb_iseq_t *ip = iseq;
+ const rb_iseq_t *ip = iseq;
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
+ }
throw_flag = VM_THROW_NO_ESCAPE_FLAG;
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
- /* while loop */
- break;
- }
- else if (ip->body->type == ISEQ_TYPE_BLOCK) {
- break;
- }
- else if (ip->body->type == ISEQ_TYPE_EVAL) {
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ /* while loop */
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
return COMPILE_NG;
- }
+ }
- ip = ip->body->parent_iseq;
- }
- if (ip != 0) {
- CHECK(COMPILE(ret, "next val", node->nd_stts));
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ }
+ if (ip != 0) {
+ CHECK(COMPILE(ret, "next val", node->nd_stts));
ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_NEXT));
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- }
- else {
- COMPILE_ERROR(ERROR_ARGS "Invalid next");
- return COMPILE_NG;
- }
+ if (popped) {
+ ADD_INSN(ret, line_node, pop);
+ }
+ }
+ else {
+ COMPILE_ERROR(ERROR_ARGS "Invalid next");
+ return COMPILE_NG;
+ }
}
return COMPILE_OK;
}
@@ -7064,65 +7708,65 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
const NODE *line_node = node;
if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
- debugs("redo in while");
- ADD_LABEL(ret, splabel);
- ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
- add_ensure_iseq(ret, iseq, 0);
- ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
- ADD_ADJUST_RESTORE(ret, splabel);
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
- }
- else if (iseq->body->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
-
- debugs("redo in block");
- ADD_LABEL(ret, splabel);
- add_ensure_iseq(ret, iseq, 0);
- ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
- ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
- ADD_ADJUST_RESTORE(ret, splabel);
-
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
+ LABEL *splabel = NEW_LABEL(0);
+ debugs("redo in while");
+ ADD_LABEL(ret, splabel);
+ ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+ if (!popped) {
+ ADD_INSN(ret, line_node, putnil);
+ }
+ }
+ else if (ISEQ_BODY(iseq)->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
+ LABEL *splabel = NEW_LABEL(0);
+
+ debugs("redo in block");
+ ADD_LABEL(ret, splabel);
+ add_ensure_iseq(ret, iseq, 0);
+ ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
+ ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
+ ADD_ADJUST_RESTORE(ret, splabel);
+
+ if (!popped) {
+ ADD_INSN(ret, line_node, putnil);
+ }
}
else {
- const rb_iseq_t *ip = iseq;
-
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
-
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
- break;
- }
- else if (ip->body->type == ISEQ_TYPE_BLOCK) {
- break;
- }
- else if (ip->body->type == ISEQ_TYPE_EVAL) {
+ const rb_iseq_t *ip = iseq;
+
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
+ }
+
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo");
return COMPILE_NG;
- }
+ }
- ip = ip->body->parent_iseq;
- }
- if (ip != 0) {
- ADD_INSN(ret, line_node, putnil);
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ }
+ if (ip != 0) {
+ ADD_INSN(ret, line_node, putnil);
ADD_INSN1(ret, line_node, throw, INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- }
- else {
- COMPILE_ERROR(ERROR_ARGS "Invalid redo");
- return COMPILE_NG;
- }
+ if (popped) {
+ ADD_INSN(ret, line_node, pop);
+ }
+ }
+ else {
+ COMPILE_ERROR(ERROR_ARGS "Invalid redo");
+ return COMPILE_NG;
+ }
}
return COMPILE_OK;
}
@@ -7132,17 +7776,17 @@ compile_retry(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
{
const NODE *line_node = node;
- if (iseq->body->type == ISEQ_TYPE_RESCUE) {
- ADD_INSN(ret, line_node, putnil);
- ADD_INSN1(ret, line_node, throw, INT2FIX(TAG_RETRY));
+ if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_RESCUE) {
+ ADD_INSN(ret, line_node, putnil);
+ ADD_INSN1(ret, line_node, throw, INT2FIX(TAG_RETRY));
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
+ if (popped) {
+ ADD_INSN(ret, line_node, pop);
+ }
}
else {
- COMPILE_ERROR(ERROR_ARGS "Invalid retry");
- return COMPILE_NG;
+ COMPILE_ERROR(ERROR_ARGS "Invalid retry");
+ return COMPILE_NG;
}
return COMPILE_OK;
}
@@ -7156,8 +7800,9 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
LABEL *lend = NEW_LABEL(line);
LABEL *lcont = NEW_LABEL(line);
const rb_iseq_t *rescue = NEW_CHILD_ISEQ(node->nd_resq,
- rb_str_concat(rb_str_new2("rescue in "), iseq->body->location.label),
- ISEQ_TYPE_RESCUE, line);
+ rb_str_concat(rb_str_new2("rescue in "),
+ ISEQ_BODY(iseq)->location.label),
+ ISEQ_TYPE_RESCUE, line);
lstart->rescued = LABEL_RESCUE_BEG;
lend->rescued = LABEL_RESCUE_END;
@@ -7172,14 +7817,14 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
ADD_LABEL(ret, lend);
if (node->nd_else) {
- ADD_INSN(ret, line_node, pop);
- CHECK(COMPILE(ret, "rescue else", node->nd_else));
+ ADD_INSN(ret, line_node, pop);
+ CHECK(COMPILE(ret, "rescue else", node->nd_else));
}
ADD_INSN(ret, line_node, nop);
ADD_LABEL(ret, lcont);
if (popped) {
- ADD_INSN(ret, line_node, pop);
+ ADD_INSN(ret, line_node, pop);
}
/* register catch entry */
@@ -7198,48 +7843,48 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
LABEL *label_miss, *label_hit;
while (resq) {
- label_miss = NEW_LABEL(line);
- label_hit = NEW_LABEL(line);
-
- narg = resq->nd_args;
- if (narg) {
- switch (nd_type(narg)) {
- case NODE_LIST:
- while (narg) {
- ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
- CHECK(COMPILE(ret, "rescue arg", narg->nd_head));
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
- ADD_INSNL(ret, line_node, branchif, label_hit);
- narg = narg->nd_next;
- }
- break;
- case NODE_SPLAT:
- case NODE_ARGSCAT:
- case NODE_ARGSPUSH:
- ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
- CHECK(COMPILE(ret, "rescue/cond splat", narg));
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
- ADD_INSNL(ret, line_node, branchif, label_hit);
- break;
- default:
- UNKNOWN_NODE("NODE_RESBODY", narg, COMPILE_NG);
- }
- }
- else {
- ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
- ADD_INSN1(ret, line_node, putobject, rb_eStandardError);
- ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
- ADD_INSNL(ret, line_node, branchif, label_hit);
- }
- ADD_INSNL(ret, line_node, jump, label_miss);
- ADD_LABEL(ret, label_hit);
- CHECK(COMPILE(ret, "resbody body", resq->nd_body));
- if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
- ADD_INSN(ret, line_node, nop);
- }
- ADD_INSN(ret, line_node, leave);
- ADD_LABEL(ret, label_miss);
- resq = resq->nd_head;
+ label_miss = NEW_LABEL(line);
+ label_hit = NEW_LABEL(line);
+
+ narg = resq->nd_args;
+ if (narg) {
+ switch (nd_type(narg)) {
+ case NODE_LIST:
+ while (narg) {
+ ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
+ CHECK(COMPILE(ret, "rescue arg", narg->nd_head));
+ ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
+ ADD_INSNL(ret, line_node, branchif, label_hit);
+ narg = narg->nd_next;
+ }
+ break;
+ case NODE_SPLAT:
+ case NODE_ARGSCAT:
+ case NODE_ARGSPUSH:
+ ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
+ CHECK(COMPILE(ret, "rescue/cond splat", narg));
+ ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
+ ADD_INSNL(ret, line_node, branchif, label_hit);
+ break;
+ default:
+ UNKNOWN_NODE("NODE_RESBODY", narg, COMPILE_NG);
+ }
+ }
+ else {
+ ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
+ ADD_INSN1(ret, line_node, putobject, rb_eStandardError);
+ ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
+ ADD_INSNL(ret, line_node, branchif, label_hit);
+ }
+ ADD_INSNL(ret, line_node, jump, label_miss);
+ ADD_LABEL(ret, label_hit);
+ CHECK(COMPILE(ret, "resbody body", resq->nd_body));
+ if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
+ ADD_INSN(ret, line_node, nop);
+ }
+ ADD_INSN(ret, line_node, leave);
+ ADD_LABEL(ret, label_miss);
+ resq = resq->nd_head;
}
return COMPILE_OK;
}
@@ -7251,8 +7896,8 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
const NODE *line_node = node;
DECL_ANCHOR(ensr);
const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr,
- rb_str_concat(rb_str_new2 ("ensure in "), iseq->body->location.label),
- ISEQ_TYPE_ENSURE, line);
+ rb_str_concat(rb_str_new2 ("ensure in "), ISEQ_BODY(iseq)->location.label),
+ ISEQ_TYPE_ENSURE, line);
LABEL *lstart = NEW_LABEL(line);
LABEL *lend = NEW_LABEL(line);
LABEL *lcont = NEW_LABEL(line);
@@ -7282,11 +7927,11 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
if (lstart->link.next != &lend->link) {
- while (erange) {
- ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
- ensure, lcont);
- erange = erange->next;
- }
+ while (erange) {
+ ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
+ ensure, lcont);
+ erange = erange->next;
+ }
}
ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
@@ -7299,55 +7944,55 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
const NODE *line_node = node;
if (iseq) {
- enum iseq_type type = iseq->body->type;
- const rb_iseq_t *is = iseq;
- enum iseq_type t = type;
- const NODE *retval = node->nd_stts;
- LABEL *splabel = 0;
-
- while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
- if (!(is = is->body->parent_iseq)) break;
- t = is->body->type;
- }
- switch (t) {
- case ISEQ_TYPE_TOP:
- case ISEQ_TYPE_MAIN:
+ enum rb_iseq_type type = ISEQ_BODY(iseq)->type;
+ const rb_iseq_t *is = iseq;
+ enum rb_iseq_type t = type;
+ const NODE *retval = node->nd_stts;
+ LABEL *splabel = 0;
+
+ while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
+ if (!(is = ISEQ_BODY(is)->parent_iseq)) break;
+ t = ISEQ_BODY(is)->type;
+ }
+ switch (t) {
+ case ISEQ_TYPE_TOP:
+ case ISEQ_TYPE_MAIN:
if (retval) {
rb_warn("argument of top-level return is ignored");
}
- if (is == iseq) {
- /* plain top-level, leave directly */
- type = ISEQ_TYPE_METHOD;
- }
- break;
- default:
- break;
- }
-
- if (type == ISEQ_TYPE_METHOD) {
- splabel = NEW_LABEL(0);
- ADD_LABEL(ret, splabel);
- ADD_ADJUST(ret, line_node, 0);
- }
-
- CHECK(COMPILE(ret, "return nd_stts (return val)", retval));
-
- if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
- add_ensure_iseq(ret, iseq, 1);
- ADD_TRACE(ret, RUBY_EVENT_RETURN);
- ADD_INSN(ret, line_node, leave);
- ADD_ADJUST_RESTORE(ret, splabel);
-
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
- }
- else {
- ADD_INSN1(ret, line_node, throw, INT2FIX(TAG_RETURN));
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- }
+ if (is == iseq) {
+ /* plain top-level, leave directly */
+ type = ISEQ_TYPE_METHOD;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (type == ISEQ_TYPE_METHOD) {
+ splabel = NEW_LABEL(0);
+ ADD_LABEL(ret, splabel);
+ ADD_ADJUST(ret, line_node, 0);
+ }
+
+ CHECK(COMPILE(ret, "return nd_stts (return val)", retval));
+
+ if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
+ add_ensure_iseq(ret, iseq, 1);
+ ADD_TRACE(ret, RUBY_EVENT_RETURN);
+ ADD_INSN(ret, line_node, leave);
+ ADD_ADJUST_RESTORE(ret, splabel);
+
+ if (!popped) {
+ ADD_INSN(ret, line_node, putnil);
+ }
+ }
+ else {
+ ADD_INSN1(ret, line_node, throw, INT2FIX(TAG_RETURN));
+ if (popped) {
+ ADD_INSN(ret, line_node, pop);
+ }
+ }
}
return COMPILE_OK;
}
@@ -7358,17 +8003,14 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
CHECK(COMPILE_(ret, "nd_body", node, popped));
if (!popped && !all_string_result_p(node)) {
- const int line = nd_line(node);
const NODE *line_node = node;
- const unsigned int flag = VM_CALL_FCALL;
- LABEL *isstr = NEW_LABEL(line);
- ADD_INSN(ret, line_node, dup);
- ADD_INSN1(ret, line_node, checktype, INT2FIX(T_STRING));
- ADD_INSNL(ret, line_node, branchif, isstr);
- ADD_INSN(ret, line_node, dup);
- ADD_SEND_R(ret, line_node, idTo_s, INT2FIX(0), NULL, INT2FIX(flag), NULL);
- ADD_INSN(ret, line_node, tostring);
- ADD_LABEL(ret, isstr);
+ const unsigned int flag = VM_CALL_FCALL;
+
+ // Note, this dup could be removed if we are willing to change anytostring. It pops
+ // two VALUEs off the stack when it could work by replacing the top most VALUE.
+ ADD_INSN(ret, line_node, dup);
+ ADD_INSN1(ret, line_node, objtostring, new_callinfo(iseq, idTo_s, 0, flag, NULL, FALSE));
+ ADD_INSN(ret, line_node, anytostring);
}
return COMPILE_OK;
}
@@ -7376,7 +8018,7 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
static void
compile_lvar(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *line_node, ID id)
{
- int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);
+ int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size - get_local_var_idx(iseq, id);
debugs("id: %s idx: %d\n", rb_id2name(id), idx);
ADD_GETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
@@ -7414,7 +8056,7 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
/* optimization shortcut
* "literal".freeze -> opt_str_freeze("literal")
*/
- if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
+ if (node->nd_recv && nd_type_p(node->nd_recv, NODE_STR) &&
(node->nd_mid == idFreeze || node->nd_mid == idUMinus) &&
node->nd_args == NULL &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
@@ -7438,8 +8080,8 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
* obj["literal"] -> opt_aref_with(obj, "literal")
*/
if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
- nd_type(node->nd_args) == NODE_LIST && node->nd_args->nd_alen == 1 &&
- nd_type(node->nd_args->nd_head) == NODE_STR &&
+ nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 1 &&
+ nd_type_p(node->nd_args->nd_head, NODE_STR) &&
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
@@ -7519,29 +8161,29 @@ delegate_call_p(const rb_iseq_t *iseq, unsigned int argc, const LINK_ANCHOR *arg
*pstart_index = 0;
return TRUE;
}
- else if (argc <= iseq->body->local_table_size) {
+ else if (argc <= ISEQ_BODY(iseq)->local_table_size) {
unsigned int start=0;
// local_table: [p1, p2, p3, l1, l2, l3]
// arguments: [p3, l1, l2] -> 2
for (start = 0;
- argc + start <= iseq->body->local_table_size;
+ argc + start <= ISEQ_BODY(iseq)->local_table_size;
start++) {
const LINK_ELEMENT *elem = FIRST_ELEMENT(args);
for (unsigned int i=start; i-start<argc; i++) {
- if (elem->type == ISEQ_ELEMENT_INSN &&
+ if (IS_INSN(elem) &&
INSN_OF(elem) == BIN(getlocal)) {
int local_index = FIX2INT(OPERAND_AT(elem, 0));
int local_level = FIX2INT(OPERAND_AT(elem, 1));
if (local_level == 0) {
- unsigned int index = iseq->body->local_table_size - (local_index - VM_ENV_DATA_SIZE + 1);
+ unsigned int index = ISEQ_BODY(iseq)->local_table_size - (local_index - VM_ENV_DATA_SIZE + 1);
if (0) { // for debug
fprintf(stderr, "lvar:%s (%d), id:%s (%d) local_index:%d, local_size:%d\n",
- rb_id2name(iseq->body->local_table[i]), i,
- rb_id2name(iseq->body->local_table[index]), index,
- local_index, (int)iseq->body->local_table_size);
+ rb_id2name(ISEQ_BODY(iseq)->local_table[i]), i,
+ rb_id2name(ISEQ_BODY(iseq)->local_table[index]), index,
+ local_index, (int)ISEQ_BODY(iseq)->local_table_size);
}
if (i == index) {
elem = elem->next;
@@ -7577,11 +8219,11 @@ static int
compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, const NODE *line_node, int popped)
{
if (!node) goto no_arg;
- if (nd_type(node) != NODE_LIST) goto bad_arg;
+ if (!nd_type_p(node, NODE_LIST)) goto bad_arg;
if (node->nd_next) goto too_many_arg;
node = node->nd_head;
if (!node) goto no_arg;
- if (nd_type(node) != NODE_LIT) goto bad_arg;
+ if (!nd_type_p(node, NODE_LIT)) goto bad_arg;
VALUE name = node->nd_lit;
if (!SYMBOL_P(name)) goto non_symbol_arg;
if (!popped) {
@@ -7602,6 +8244,69 @@ compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, c
UNKNOWN_NODE("arg!", node, COMPILE_NG);
}
+static NODE *
+mandatory_node(const rb_iseq_t *iseq, const NODE *cond_node)
+{
+ const NODE *node = ISEQ_COMPILE_DATA(iseq)->root_node;
+ if (nd_type(node) == NODE_IF && node->nd_cond == cond_node) {
+ return node->nd_body;
+ }
+ else {
+ rb_bug("mandatory_node: can't find mandatory node");
+ }
+}
+
+static int
+compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const NODE *line_node)
+{
+ // arguments
+ struct rb_args_info args = {
+ .pre_args_num = ISEQ_BODY(iseq)->param.lead_num,
+ };
+ NODE args_node;
+ rb_node_init(&args_node, NODE_ARGS, 0, 0, (VALUE)&args);
+
+ // local table without non-mandatory parameters
+ const int skip_local_size = ISEQ_BODY(iseq)->param.size - ISEQ_BODY(iseq)->param.lead_num;
+ const int table_size = ISEQ_BODY(iseq)->local_table_size - skip_local_size;
+
+ VALUE idtmp = 0;
+ rb_ast_id_table_t *tbl = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + table_size * sizeof(ID));
+ tbl->size = table_size;
+
+ int i;
+
+ // lead parameters
+ for (i=0; i<ISEQ_BODY(iseq)->param.lead_num; i++) {
+ tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i];
+ }
+ // local variables
+ for (; i<table_size; i++) {
+ tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size];
+ }
+
+ NODE scope_node;
+ rb_node_init(&scope_node, NODE_SCOPE, (VALUE)tbl, (VALUE)mandatory_node(iseq, node), (VALUE)&args_node);
+
+ rb_ast_body_t ast = {
+ .root = &scope_node,
+ .compile_option = 0,
+ .script_lines = ISEQ_BODY(iseq)->variable.script_lines,
+ };
+
+ int prev_inline_index = GET_VM()->builtin_inline_index;
+
+ ISEQ_BODY(iseq)->mandatory_only_iseq =
+ rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq),
+ rb_iseq_path(iseq), rb_iseq_realpath(iseq),
+ nd_line(line_node), NULL, 0,
+ ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option);
+
+ GET_VM()->builtin_inline_index = prev_inline_index;
+ ALLOCV_END(idtmp);
+ return COMPILE_OK;
+}
+
static int
compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const NODE *line_node, int popped,
const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func)
@@ -7634,12 +8339,23 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD
}
else if (strcmp("attr!", builtin_func) == 0) {
// There's only "inline" attribute for now
- iseq->body->builtin_inline_p = true;
+ ISEQ_BODY(iseq)->builtin_inline_p = true;
return COMPILE_OK;
}
else if (strcmp("arg!", builtin_func) == 0) {
return compile_builtin_arg(iseq, ret, args_node, line_node, popped);
}
+ else if (strcmp("mandatory_only?", builtin_func) == 0) {
+ if (popped) {
+ rb_bug("mandatory_only? should be in if condition");
+ }
+ else if (!LIST_INSN_SIZE_ZERO(ret)) {
+ rb_bug("mandatory_only? should be put on top");
+ }
+
+ ADD_INSN1(ret, line_node, putobject, Qfalse);
+ return compile_builtin_mandatory_only_method(iseq, node, line_node);
+ }
else if (1) {
rb_bug("can't find builtin function:%s", builtin_func);
}
@@ -7713,7 +8429,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
INIT_ANCHOR(recv);
INIT_ANCHOR(args);
#if OPT_SUPPORT_JOKE
- if (nd_type(node) == NODE_VCALL) {
+ if (nd_type_p(node, NODE_VCALL)) {
ID id_bitblt;
ID id_answer;
@@ -7737,7 +8453,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
CONST_ID(goto_id, "__goto__");
CONST_ID(label_id, "__label__");
- if (nd_type(node) == NODE_FCALL &&
+ if (nd_type_p(node, NODE_FCALL) &&
(mid == goto_id || mid == label_id)) {
LABEL *label;
st_data_t data;
@@ -7748,7 +8464,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
labels_table = st_init_numtable();
ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
}
- if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
+ if (nd_type_p(node->nd_args->nd_head, NODE_LIT) &&
SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
label_name = node->nd_args->nd_head->nd_lit;
@@ -7789,7 +8505,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
int idx, level;
if (mid == idCall &&
- nd_type(node->nd_recv) == NODE_LVAR &&
+ nd_type_p(node->nd_recv, NODE_LVAR) &&
iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
ADD_INSN2(recv, node->nd_recv, getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
@@ -7842,8 +8558,844 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
return COMPILE_OK;
}
+static int
+compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ const int line = nd_line(node);
+ VALUE argc;
+ unsigned int flag = 0;
+ int asgnflag = 0;
+ ID id = node->nd_mid;
+ int boff = 0;
-static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped);
+ /*
+ * a[x] (op)= y
+ *
+ * nil # nil
+ * eval a # nil a
+ * eval x # nil a x
+ * dupn 2 # nil a x a x
+ * send :[] # nil a x a[x]
+ * eval y # nil a x a[x] y
+ * send op # nil a x ret
+ * setn 3 # ret a x ret
+ * send []= # ret ?
+ * pop # ret
+ */
+
+ /*
+ * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
+ * NODE_OP_ASGN nd_recv
+ * nd_args->nd_head
+ * nd_args->nd_body
+ * nd_mid
+ */
+
+ if (!popped) {
+ ADD_INSN(ret, node, putnil);
+ }
+ asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node);
+ CHECK(asgnflag != -1);
+ switch (nd_type(node->nd_args->nd_head)) {
+ case NODE_ZLIST:
+ argc = INT2FIX(0);
+ break;
+ case NODE_BLOCK_PASS:
+ boff = 1;
+ /* fall through */
+ default:
+ argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag, NULL);
+ CHECK(!NIL_P(argc));
+ }
+ ADD_INSN1(ret, node, dupn, FIXNUM_INC(argc, 1 + boff));
+ flag |= asgnflag;
+ ADD_SEND_WITH_FLAG(ret, node, idAREF, argc, INT2FIX(flag));
+
+ if (id == idOROP || id == idANDOP) {
+ /* a[x] ||= y or a[x] &&= y
+
+ unless/if a[x]
+ a[x]= y
+ else
+ nil
+ end
+ */
+ LABEL *label = NEW_LABEL(line);
+ LABEL *lfin = NEW_LABEL(line);
+
+ ADD_INSN(ret, node, dup);
+ if (id == idOROP) {
+ ADD_INSNL(ret, node, branchif, label);
+ }
+ else { /* idANDOP */
+ ADD_INSNL(ret, node, branchunless, label);
+ }
+ ADD_INSN(ret, node, pop);
+
+ CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
+ if (!popped) {
+ ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
+ }
+ if (flag & VM_CALL_ARGS_SPLAT) {
+ ADD_INSN1(ret, node, newarray, INT2FIX(1));
+ if (boff > 0) {
+ ADD_INSN1(ret, node, dupn, INT2FIX(3));
+ ADD_INSN(ret, node, swap);
+ ADD_INSN(ret, node, pop);
+ }
+ ADD_INSN(ret, node, concatarray);
+ if (boff > 0) {
+ ADD_INSN1(ret, node, setn, INT2FIX(3));
+ ADD_INSN(ret, node, pop);
+ ADD_INSN(ret, node, pop);
+ }
+ ADD_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag));
+ }
+ else {
+ if (boff > 0)
+ ADD_INSN(ret, node, swap);
+ ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
+ }
+ ADD_INSN(ret, node, pop);
+ ADD_INSNL(ret, node, jump, lfin);
+ ADD_LABEL(ret, label);
+ if (!popped) {
+ ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
+ }
+ ADD_INSN1(ret, node, adjuststack, FIXNUM_INC(argc, 2+boff));
+ ADD_LABEL(ret, lfin);
+ }
+ else {
+ CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
+ ADD_SEND(ret, node, id, INT2FIX(1));
+ if (!popped) {
+ ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
+ }
+ if (flag & VM_CALL_ARGS_SPLAT) {
+ ADD_INSN1(ret, node, newarray, INT2FIX(1));
+ if (boff > 0) {
+ ADD_INSN1(ret, node, dupn, INT2FIX(3));
+ ADD_INSN(ret, node, swap);
+ ADD_INSN(ret, node, pop);
+ }
+ ADD_INSN(ret, node, concatarray);
+ if (boff > 0) {
+ ADD_INSN1(ret, node, setn, INT2FIX(3));
+ ADD_INSN(ret, node, pop);
+ ADD_INSN(ret, node, pop);
+ }
+ ADD_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag));
+ }
+ else {
+ if (boff > 0)
+ ADD_INSN(ret, node, swap);
+ ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
+ }
+ ADD_INSN(ret, node, pop);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ const int line = nd_line(node);
+ ID atype = node->nd_next->nd_mid;
+ ID vid = node->nd_next->nd_vid, aid = rb_id_attrset(vid);
+ int asgnflag;
+ LABEL *lfin = NEW_LABEL(line);
+ LABEL *lcfin = NEW_LABEL(line);
+ LABEL *lskip = 0;
+ /*
+ class C; attr_accessor :c; end
+ r = C.new
+ r.a &&= v # asgn2
+
+ eval r # r
+ dup # r r
+ eval r.a # r o
+
+ # or
+ dup # r o o
+ if lcfin # r o
+ pop # r
+ eval v # r v
+ swap # v r
+ topn 1 # v r v
+ send a= # v ?
+ jump lfin # v ?
+
+ lcfin: # r o
+ swap # o r
+
+ lfin: # o ?
+ pop # o
+
+ # or (popped)
+ if lcfin # r
+ eval v # r v
+ send a= # ?
+ jump lfin # ?
+
+ lcfin: # r
+
+ lfin: # ?
+ pop #
+
+ # and
+ dup # r o o
+ unless lcfin
+ pop # r
+ eval v # r v
+ swap # v r
+ topn 1 # v r v
+ send a= # v ?
+ jump lfin # v ?
+
+ # others
+ eval v # r o v
+ send ?? # r w
+ send a= # w
+
+ */
+
+ asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node);
+ CHECK(asgnflag != -1);
+ if (node->nd_next->nd_aid) {
+ lskip = NEW_LABEL(line);
+ ADD_INSN(ret, node, dup);
+ ADD_INSNL(ret, node, branchnil, lskip);
+ }
+ ADD_INSN(ret, node, dup);
+ ADD_SEND_WITH_FLAG(ret, node, vid, INT2FIX(0), INT2FIX(asgnflag));
+
+ if (atype == idOROP || atype == idANDOP) {
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+ if (atype == idOROP) {
+ ADD_INSNL(ret, node, branchif, lcfin);
+ }
+ else { /* idANDOP */
+ ADD_INSNL(ret, node, branchunless, lcfin);
+ }
+ if (!popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
+ if (!popped) {
+ ADD_INSN(ret, node, swap);
+ ADD_INSN1(ret, node, topn, INT2FIX(1));
+ }
+ ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag));
+ ADD_INSNL(ret, node, jump, lfin);
+
+ ADD_LABEL(ret, lcfin);
+ if (!popped) {
+ ADD_INSN(ret, node, swap);
+ }
+
+ ADD_LABEL(ret, lfin);
+ }
+ else {
+ CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
+ ADD_SEND(ret, node, atype, INT2FIX(1));
+ if (!popped) {
+ ADD_INSN(ret, node, swap);
+ ADD_INSN1(ret, node, topn, INT2FIX(1));
+ }
+ ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag));
+ }
+ if (lskip && popped) {
+ ADD_LABEL(ret, lskip);
+ }
+ ADD_INSN(ret, node, pop);
+ if (lskip && !popped) {
+ ADD_LABEL(ret, lskip);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ const int line = nd_line(node);
+ LABEL *lfin = 0;
+ LABEL *lassign = 0;
+ ID mid;
+
+ switch (nd_type(node->nd_head)) {
+ case NODE_COLON3:
+ ADD_INSN1(ret, node, putobject, rb_cObject);
+ break;
+ case NODE_COLON2:
+ CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
+ break;
+ default:
+ COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
+ ruby_node_name(nd_type(node->nd_head)));
+ return COMPILE_NG;
+ }
+ mid = node->nd_head->nd_mid;
+ /* cref */
+ if (node->nd_aid == idOROP) {
+ lassign = NEW_LABEL(line);
+ ADD_INSN(ret, node, dup); /* cref cref */
+ ADD_INSN3(ret, node, defined, INT2FIX(DEFINED_CONST_FROM),
+ ID2SYM(mid), Qtrue); /* cref bool */
+ ADD_INSNL(ret, node, branchunless, lassign); /* cref */
+ }
+ ADD_INSN(ret, node, dup); /* cref cref */
+ ADD_INSN1(ret, node, putobject, Qtrue);
+ ADD_INSN1(ret, node, getconstant, ID2SYM(mid)); /* cref obj */
+
+ if (node->nd_aid == idOROP || node->nd_aid == idANDOP) {
+ lfin = NEW_LABEL(line);
+ if (!popped) ADD_INSN(ret, node, dup); /* cref [obj] obj */
+ if (node->nd_aid == idOROP)
+ ADD_INSNL(ret, node, branchif, lfin);
+ else /* idANDOP */
+ ADD_INSNL(ret, node, branchunless, lfin);
+ /* cref [obj] */
+ if (!popped) ADD_INSN(ret, node, pop); /* cref */
+ if (lassign) ADD_LABEL(ret, lassign);
+ CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
+ /* cref value */
+ if (popped)
+ ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */
+ else {
+ ADD_INSN1(ret, node, dupn, INT2FIX(2)); /* cref value cref value */
+ ADD_INSN(ret, node, swap); /* cref value value cref */
+ }
+ ADD_INSN1(ret, node, setconstant, ID2SYM(mid)); /* cref [value] */
+ ADD_LABEL(ret, lfin); /* cref [value] */
+ if (!popped) ADD_INSN(ret, node, swap); /* [value] cref */
+ ADD_INSN(ret, node, pop); /* [value] */
+ }
+ else {
+ CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
+ /* cref obj value */
+ ADD_CALL(ret, node, node->nd_aid, INT2FIX(1));
+ /* cref value */
+ ADD_INSN(ret, node, swap); /* value cref */
+ if (!popped) {
+ ADD_INSN1(ret, node, topn, INT2FIX(1)); /* value cref value */
+ ADD_INSN(ret, node, swap); /* value value cref */
+ }
+ ADD_INSN1(ret, node, setconstant, ID2SYM(mid));
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
+{
+ const int line = nd_line(node);
+ LABEL *lfin = NEW_LABEL(line);
+ LABEL *lassign;
+
+ if (type == NODE_OP_ASGN_OR && !nd_type_p(node->nd_head, NODE_IVAR)) {
+ LABEL *lfinish[2];
+ lfinish[0] = lfin;
+ lfinish[1] = 0;
+ defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
+ lassign = lfinish[1];
+ if (!lassign) {
+ lassign = NEW_LABEL(line);
+ }
+ ADD_INSNL(ret, node, branchunless, lassign);
+ }
+ else {
+ lassign = NEW_LABEL(line);
+ }
+
+ CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
+
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+
+ if (type == NODE_OP_ASGN_AND) {
+ ADD_INSNL(ret, node, branchunless, lfin);
+ }
+ else {
+ ADD_INSNL(ret, node, branchif, lfin);
+ }
+
+ if (!popped) {
+ ADD_INSN(ret, node, pop);
+ }
+
+ ADD_LABEL(ret, lassign);
+ CHECK(COMPILE_(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value, popped));
+ ADD_LABEL(ret, lfin);
+ return COMPILE_OK;
+}
+
+static int
+compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
+{
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ DECL_ANCHOR(args);
+ int argc;
+ unsigned int flag = 0;
+ struct rb_callinfo_kwarg *keywords = NULL;
+ const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
+
+ INIT_ANCHOR(args);
+ ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
+ if (type == NODE_SUPER) {
+ VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+ CHECK(!NIL_P(vargc));
+ argc = FIX2INT(vargc);
+ }
+ else {
+ /* NODE_ZSUPER */
+ int i;
+ const rb_iseq_t *liseq = body->local_iseq;
+ const struct rb_iseq_constant_body *const local_body = ISEQ_BODY(liseq);
+ const struct rb_iseq_param_keyword *const local_kwd = local_body->param.keyword;
+ int lvar_level = get_lvar_level(iseq);
+
+ argc = local_body->param.lead_num;
+
+ /* normal arguments */
+ for (i = 0; i < local_body->param.lead_num; i++) {
+ int idx = local_body->local_table_size - i;
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ }
+
+ if (local_body->param.flags.has_opt) {
+ /* optional arguments */
+ int j;
+ for (j = 0; j < local_body->param.opt_num; j++) {
+ int idx = local_body->local_table_size - (i + j);
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ }
+ i += j;
+ argc = i;
+ }
+ if (local_body->param.flags.has_rest) {
+ /* rest argument */
+ int idx = local_body->local_table_size - local_body->param.rest_start;
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ ADD_INSN1(args, node, splatarray, Qfalse);
+
+ argc = local_body->param.rest_start + 1;
+ flag |= VM_CALL_ARGS_SPLAT;
+ }
+ if (local_body->param.flags.has_post) {
+ /* post arguments */
+ int post_len = local_body->param.post_num;
+ int post_start = local_body->param.post_start;
+
+ if (local_body->param.flags.has_rest) {
+ int j;
+ for (j=0; j<post_len; j++) {
+ int idx = local_body->local_table_size - (post_start + j);
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ }
+ ADD_INSN1(args, node, newarray, INT2FIX(j));
+ ADD_INSN (args, node, concatarray);
+ /* argc is settled at above */
+ }
+ else {
+ int j;
+ for (j=0; j<post_len; j++) {
+ int idx = local_body->local_table_size - (post_start + j);
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ }
+ argc = post_len + post_start;
+ }
+ }
+
+ if (local_body->param.flags.has_kw) { /* TODO: support keywords */
+ int local_size = local_body->local_table_size;
+ argc++;
+
+ ADD_INSN1(args, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+
+ if (local_body->param.flags.has_kwrest) {
+ int idx = local_body->local_table_size - local_kwd->rest_start;
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ if (local_kwd->num > 0) {
+ ADD_SEND (args, node, rb_intern("dup"), INT2FIX(0));
+ flag |= VM_CALL_KW_SPLAT_MUT;
+ }
+ }
+ else {
+ ADD_INSN1(args, node, newhash, INT2FIX(0));
+ flag |= VM_CALL_KW_SPLAT_MUT;
+ }
+ for (i = 0; i < local_kwd->num; ++i) {
+ ID id = local_kwd->table[i];
+ int idx = local_size - get_local_var_idx(liseq, id);
+ ADD_INSN1(args, node, putobject, ID2SYM(id));
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ }
+ ADD_SEND(args, node, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
+ if (local_body->param.flags.has_rest) {
+ ADD_INSN1(args, node, newarray, INT2FIX(1));
+ ADD_INSN (args, node, concatarray);
+ --argc;
+ }
+ flag |= VM_CALL_KW_SPLAT;
+ }
+ else if (local_body->param.flags.has_kwrest) {
+ int idx = local_body->local_table_size - local_kwd->rest_start;
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+
+ if (local_body->param.flags.has_rest) {
+ ADD_INSN1(args, node, newarray, INT2FIX(1));
+ ADD_INSN (args, node, concatarray);
+ }
+ else {
+ argc++;
+ }
+ flag |= VM_CALL_KW_SPLAT;
+ }
+ }
+
+ flag |= VM_CALL_SUPER | VM_CALL_FCALL;
+ if (type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER;
+ ADD_INSN(ret, node, putself);
+ ADD_SEQ(ret, args);
+ ADD_INSN2(ret, node, invokesuper,
+ new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL),
+ parent_block);
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ DECL_ANCHOR(args);
+ VALUE argc;
+ unsigned int flag = 0;
+ struct rb_callinfo_kwarg *keywords = NULL;
+
+ INIT_ANCHOR(args);
+
+ switch (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->type) {
+ case ISEQ_TYPE_TOP:
+ case ISEQ_TYPE_MAIN:
+ case ISEQ_TYPE_CLASS:
+ COMPILE_ERROR(ERROR_ARGS "Invalid yield");
+ return COMPILE_NG;
+ default: /* valid */;
+ }
+
+ if (node->nd_head) {
+ argc = setup_args(iseq, args, node->nd_head, &flag, &keywords);
+ CHECK(!NIL_P(argc));
+ }
+ else {
+ argc = INT2FIX(0);
+ }
+
+ ADD_SEQ(ret, args);
+ ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE));
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+
+ int level = 0;
+ const rb_iseq_t *tmp_iseq = iseq;
+ for (; tmp_iseq != ISEQ_BODY(iseq)->local_iseq; level++ ) {
+ tmp_iseq = ISEQ_BODY(tmp_iseq)->parent_iseq;
+ }
+ if (level > 0) access_outer_variables(iseq, level, rb_intern("yield"), true);
+
+ return COMPILE_OK;
+}
+
+static int
+compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
+{
+ DECL_ANCHOR(recv);
+ DECL_ANCHOR(val);
+
+ INIT_ANCHOR(recv);
+ INIT_ANCHOR(val);
+ switch ((int)type) {
+ case NODE_MATCH:
+ ADD_INSN1(recv, node, putobject, node->nd_lit);
+ ADD_INSN2(val, node, getspecial, INT2FIX(0),
+ INT2FIX(0));
+ break;
+ case NODE_MATCH2:
+ CHECK(COMPILE(recv, "receiver", node->nd_recv));
+ CHECK(COMPILE(val, "value", node->nd_value));
+ break;
+ case NODE_MATCH3:
+ CHECK(COMPILE(recv, "receiver", node->nd_value));
+ CHECK(COMPILE(val, "value", node->nd_recv));
+ break;
+ }
+
+ ADD_SEQ(ret, recv);
+ ADD_SEQ(ret, val);
+ ADD_SEND(ret, node, idEqTilde, INT2FIX(1));
+
+ if (node->nd_args) {
+ compile_named_capture_assign(iseq, ret, node->nd_args);
+ }
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ if (rb_is_const_id(node->nd_mid)) {
+ /* constant */
+ VALUE segments;
+ if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache &&
+ (segments = collect_const_segments(iseq, node))) {
+ ISEQ_BODY(iseq)->ic_size++;
+ ADD_INSN1(ret, node, opt_getconstant_path, segments);
+ RB_OBJ_WRITTEN(iseq, Qundef, segments);
+ }
+ else {
+ /* constant */
+ DECL_ANCHOR(pref);
+ DECL_ANCHOR(body);
+
+ INIT_ANCHOR(pref);
+ INIT_ANCHOR(body);
+ CHECK(compile_const_prefix(iseq, node, pref, body));
+ if (LIST_INSN_SIZE_ZERO(pref)) {
+ ADD_INSN(ret, node, putnil);
+ ADD_SEQ(ret, body);
+ }
+ else {
+ ADD_SEQ(ret, pref);
+ ADD_SEQ(ret, body);
+ }
+ }
+ }
+ else {
+ /* function call */
+ ADD_CALL_RECEIVER(ret, node);
+ CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head));
+ ADD_CALL(ret, node, node->nd_mid, INT2FIX(1));
+ }
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ debugi("colon3#nd_mid", node->nd_mid);
+
+ /* add cache insn */
+ if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
+ ISEQ_BODY(iseq)->ic_size++;
+ VALUE segments = rb_ary_new_from_args(2, ID2SYM(idNULL), ID2SYM(node->nd_mid));
+ ADD_INSN1(ret, node, opt_getconstant_path, segments);
+ RB_OBJ_WRITTEN(iseq, Qundef, segments);
+ }
+ else {
+ ADD_INSN1(ret, node, putobject, rb_cObject);
+ ADD_INSN1(ret, node, putobject, Qtrue);
+ ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_mid));
+ }
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const int excl)
+{
+ VALUE flag = INT2FIX(excl);
+ const NODE *b = node->nd_beg;
+ const NODE *e = node->nd_end;
+
+ if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
+ if (!popped) {
+ VALUE bv = nd_type_p(b, NODE_LIT) ? b->nd_lit : Qnil;
+ VALUE ev = nd_type_p(e, NODE_LIT) ? e->nd_lit : Qnil;
+ VALUE val = rb_range_new(bv, ev, excl);
+ ADD_INSN1(ret, node, putobject, val);
+ RB_OBJ_WRITTEN(iseq, Qundef, val);
+ }
+ }
+ else {
+ CHECK(COMPILE_(ret, "min", b, popped));
+ CHECK(COMPILE_(ret, "max", e, popped));
+ if (!popped) {
+ ADD_INSN1(ret, node, newrange, flag);
+ }
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_errinfo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ if (!popped) {
+ if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_RESCUE) {
+ ADD_GETLOCAL(ret, node, LVAR_ERRINFO, 0);
+ }
+ else {
+ const rb_iseq_t *ip = iseq;
+ int level = 0;
+ while (ip) {
+ if (ISEQ_BODY(ip)->type == ISEQ_TYPE_RESCUE) {
+ break;
+ }
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ level++;
+ }
+ if (ip) {
+ ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level);
+ }
+ else {
+ ADD_INSN(ret, node, putnil);
+ }
+ }
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ LABEL *end_label = NEW_LABEL(nd_line(node));
+ const NODE *default_value = node->nd_body->nd_value;
+
+ if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) {
+ /* required argument. do nothing */
+ COMPILE_ERROR(ERROR_ARGS "unreachable");
+ return COMPILE_NG;
+ }
+ else if (nd_type_p(default_value, NODE_LIT) ||
+ nd_type_p(default_value, NODE_NIL) ||
+ nd_type_p(default_value, NODE_TRUE) ||
+ nd_type_p(default_value, NODE_FALSE)) {
+ COMPILE_ERROR(ERROR_ARGS "unreachable");
+ return COMPILE_NG;
+ }
+ else {
+ /* if keywordcheck(_kw_bits, nth_keyword)
+ * kw = default_value
+ * end
+ */
+ int kw_bits_idx = body->local_table_size - body->param.keyword->bits_start;
+ int keyword_idx = body->param.keyword->num;
+
+ ADD_INSN2(ret, node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx));
+ ADD_INSNL(ret, node, branchif, end_label);
+ CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body));
+ ADD_LABEL(ret, end_label);
+ }
+ return COMPILE_OK;
+}
+
+static int
+compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
+{
+ DECL_ANCHOR(recv);
+ DECL_ANCHOR(args);
+ unsigned int flag = 0;
+ ID mid = node->nd_mid;
+ VALUE argc;
+ LABEL *else_label = NULL;
+ VALUE branches = Qfalse;
+
+ /* optimization shortcut
+ * obj["literal"] = value -> opt_aset_with(obj, "literal", value)
+ */
+ if (!ISEQ_COMPILE_DATA(iseq)->in_masgn &&
+ mid == idASET && !private_recv_p(node) && node->nd_args &&
+ nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 2 &&
+ nd_type_p(node->nd_args->nd_head, NODE_STR) &&
+ ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
+ !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
+ ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
+ {
+ VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
+ CHECK(COMPILE(ret, "recv", node->nd_recv));
+ CHECK(COMPILE(ret, "value", node->nd_args->nd_next->nd_head));
+ if (!popped) {
+ ADD_INSN(ret, node, swap);
+ ADD_INSN1(ret, node, topn, INT2FIX(1));
+ }
+ ADD_INSN2(ret, node, opt_aset_with, str,
+ new_callinfo(iseq, idASET, 2, 0, NULL, FALSE));
+ RB_OBJ_WRITTEN(iseq, Qundef, str);
+ ADD_INSN(ret, node, pop);
+ return COMPILE_OK;
+ }
+
+ INIT_ANCHOR(recv);
+ INIT_ANCHOR(args);
+ argc = setup_args(iseq, args, node->nd_args, &flag, NULL);
+ CHECK(!NIL_P(argc));
+
+ int asgnflag = COMPILE_RECV(recv, "recv", node);
+ CHECK(asgnflag != -1);
+ flag |= (unsigned int)asgnflag;
+
+ debugp_param("argc", argc);
+ debugp_param("nd_mid", ID2SYM(mid));
+
+ if (!rb_is_attrset_id(mid)) {
+ /* safe nav attr */
+ mid = rb_id_attrset(mid);
+ else_label = qcall_branch_start(iseq, recv, &branches, node, node);
+ }
+ if (!popped) {
+ ADD_INSN(ret, node, putnil);
+ ADD_SEQ(ret, recv);
+ ADD_SEQ(ret, args);
+
+ if (flag & VM_CALL_ARGS_BLOCKARG) {
+ ADD_INSN1(ret, node, topn, INT2FIX(1));
+ if (flag & VM_CALL_ARGS_SPLAT) {
+ ADD_INSN1(ret, node, putobject, INT2FIX(-1));
+ ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag));
+ }
+ ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 3));
+ ADD_INSN (ret, node, pop);
+ }
+ else if (flag & VM_CALL_ARGS_SPLAT) {
+ ADD_INSN(ret, node, dup);
+ ADD_INSN1(ret, node, putobject, INT2FIX(-1));
+ ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag));
+ ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2));
+ ADD_INSN (ret, node, pop);
+ }
+ else {
+ ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 1));
+ }
+ }
+ else {
+ ADD_SEQ(ret, recv);
+ ADD_SEQ(ret, args);
+ }
+ ADD_SEND_WITH_FLAG(ret, node, mid, argc, INT2FIX(flag));
+ qcall_branch_end(iseq, ret, else_label, branches, node, node);
+ ADD_INSN(ret, node, pop);
+ return COMPILE_OK;
+}
+
+static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped);
/**
compile each node
@@ -7868,38 +9420,24 @@ 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)
-{
- switch (iseq->body->local_iseq->body->type) {
- case ISEQ_TYPE_TOP:
- case ISEQ_TYPE_MAIN:
- case ISEQ_TYPE_CLASS:
- return FALSE;
- default:
- return TRUE;
- }
-}
-
-static int
-iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped)
+iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
const int line = (int)nd_line(node);
- const NODE *line_node = node;
const enum node_type type = nd_type(node);
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
- /* ignore */
+ /* ignore */
}
else {
- if (node->flags & NODE_FL_NEWLINE) {
- int event = RUBY_EVENT_LINE;
- ISEQ_COMPILE_DATA(iseq)->last_line = line;
- if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
- event |= RUBY_EVENT_COVERAGE_LINE;
- }
- ADD_TRACE(ret, event);
- }
+ if (node->flags & NODE_FL_NEWLINE) {
+ int event = RUBY_EVENT_LINE;
+ ISEQ_COMPILE_DATA(iseq)->last_line = line;
+ if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
+ event |= RUBY_EVENT_COVERAGE_LINE;
+ }
+ ADD_TRACE(ret, event);
+ }
}
debug_node_start(node);
@@ -7907,997 +9445,469 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
#define BEFORE_RETURN debug_node_end()
switch (type) {
- case NODE_BLOCK:{
- while (node && nd_type(node) == NODE_BLOCK) {
- CHECK(COMPILE_(ret, "BLOCK body", node->nd_head,
- (node->nd_next ? 1 : popped)));
- node = node->nd_next;
- }
- if (node) {
- CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped));
- }
- break;
- }
+ case NODE_BLOCK:
+ CHECK(compile_block(iseq, ret, node, popped));
+ break;
case NODE_IF:
case NODE_UNLESS:
- CHECK(compile_if(iseq, ret, node, popped, type));
- break;
+ CHECK(compile_if(iseq, ret, node, popped, type));
+ break;
case NODE_CASE:
- CHECK(compile_case(iseq, ret, node, popped));
- break;
+ CHECK(compile_case(iseq, ret, node, popped));
+ break;
case NODE_CASE2:
- CHECK(compile_case2(iseq, ret, node, popped));
- break;
+ CHECK(compile_case2(iseq, ret, node, popped));
+ break;
case NODE_CASE3:
CHECK(compile_case3(iseq, ret, node, popped));
break;
case NODE_WHILE:
case NODE_UNTIL:
- CHECK(compile_loop(iseq, ret, node, popped, type));
- break;
+ CHECK(compile_loop(iseq, ret, node, popped, type));
+ break;
case NODE_FOR:
case NODE_ITER:
- CHECK(compile_iter(iseq, ret, node, popped));
- break;
+ CHECK(compile_iter(iseq, ret, node, popped));
+ break;
case NODE_FOR_MASGN:
- CHECK(compile_for_masgn(iseq, ret, node, popped));
- break;
+ CHECK(compile_for_masgn(iseq, ret, node, popped));
+ break;
case NODE_BREAK:
- CHECK(compile_break(iseq, ret, node, popped));
- break;
+ CHECK(compile_break(iseq, ret, node, popped));
+ break;
case NODE_NEXT:
- CHECK(compile_next(iseq, ret, node, popped));
- break;
+ CHECK(compile_next(iseq, ret, node, popped));
+ break;
case NODE_REDO:
- CHECK(compile_redo(iseq, ret, node, popped));
- break;
+ CHECK(compile_redo(iseq, ret, node, popped));
+ break;
case NODE_RETRY:
- CHECK(compile_retry(iseq, ret, node, popped));
- break;
+ CHECK(compile_retry(iseq, ret, node, popped));
+ break;
case NODE_BEGIN:{
- CHECK(COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped));
- break;
+ CHECK(COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped));
+ break;
}
case NODE_RESCUE:
- CHECK(compile_rescue(iseq, ret, node, popped));
- break;
+ CHECK(compile_rescue(iseq, ret, node, popped));
+ break;
case NODE_RESBODY:
- CHECK(compile_resbody(iseq, ret, node, popped));
- break;
+ CHECK(compile_resbody(iseq, ret, node, popped));
+ break;
case NODE_ENSURE:
- CHECK(compile_ensure(iseq, ret, node, popped));
- break;
+ CHECK(compile_ensure(iseq, ret, node, popped));
+ break;
case NODE_AND:
case NODE_OR:{
- LABEL *end_label = NEW_LABEL(line);
- CHECK(COMPILE(ret, "nd_1st", node->nd_1st));
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
- }
- if (type == NODE_AND) {
- ADD_INSNL(ret, line_node, branchunless, end_label);
- }
- else {
- ADD_INSNL(ret, line_node, branchif, end_label);
- }
- if (!popped) {
- ADD_INSN(ret, line_node, pop);
- }
- CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped));
- ADD_LABEL(ret, end_label);
- break;
+ LABEL *end_label = NEW_LABEL(line);
+ CHECK(COMPILE(ret, "nd_1st", node->nd_1st));
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+ if (type == NODE_AND) {
+ ADD_INSNL(ret, node, branchunless, end_label);
+ }
+ else {
+ ADD_INSNL(ret, node, branchif, end_label);
+ }
+ if (!popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped));
+ ADD_LABEL(ret, end_label);
+ break;
}
case NODE_MASGN:{
- compile_massign(iseq, ret, node, popped);
- break;
+ bool prev_in_masgn = ISEQ_COMPILE_DATA(iseq)->in_masgn;
+ ISEQ_COMPILE_DATA(iseq)->in_masgn = true;
+ compile_massign(iseq, ret, node, popped);
+ ISEQ_COMPILE_DATA(iseq)->in_masgn = prev_in_masgn;
+ break;
}
case NODE_LASGN:{
- ID id = node->nd_vid;
- int idx = body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);
+ ID id = node->nd_vid;
+ int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq, id);
- debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
- CHECK(COMPILE(ret, "rvalue", node->nd_value));
+ debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
+ CHECK(COMPILE(ret, "rvalue", node->nd_value));
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
- }
- ADD_SETLOCAL(ret, line_node, idx, get_lvar_level(iseq));
- break;
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+ ADD_SETLOCAL(ret, node, idx, get_lvar_level(iseq));
+ break;
}
- case NODE_DASGN:
- case NODE_DASGN_CURR:{
- int idx, lv, ls;
- ID id = node->nd_vid;
- CHECK(COMPILE(ret, "dvalue", node->nd_value));
- debugi("dassn id", rb_id2str(id) ? id : '*');
-
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
- }
-
- idx = get_dyna_var_idx(iseq, id, &lv, &ls);
-
- if (idx < 0) {
- COMPILE_ERROR(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")",
- rb_id2str(id));
- goto ng;
- }
- ADD_SETLOCAL(ret, line_node, ls - idx, lv);
- break;
+ case NODE_DASGN: {
+ int idx, lv, ls;
+ ID id = node->nd_vid;
+ CHECK(COMPILE(ret, "dvalue", node->nd_value));
+ debugi("dassn id", rb_id2str(id) ? id : '*');
+
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+
+ idx = get_dyna_var_idx(iseq, id, &lv, &ls);
+
+ if (idx < 0) {
+ COMPILE_ERROR(ERROR_ARGS "NODE_DASGN: unknown id (%"PRIsVALUE")",
+ rb_id2str(id));
+ goto ng;
+ }
+ ADD_SETLOCAL(ret, node, ls - idx, lv);
+ break;
}
case NODE_GASGN:{
- CHECK(COMPILE(ret, "lvalue", node->nd_value));
+ CHECK(COMPILE(ret, "lvalue", node->nd_value));
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
- }
- ADD_INSN1(ret, line_node, setglobal, ID2SYM(node->nd_entry));
- break;
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+ ADD_INSN1(ret, node, setglobal, ID2SYM(node->nd_entry));
+ break;
}
case NODE_IASGN:{
- CHECK(COMPILE(ret, "lvalue", node->nd_value));
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
- }
- ADD_INSN2(ret, line_node, setinstancevariable,
- ID2SYM(node->nd_vid),
- get_ivar_ic_value(iseq,node->nd_vid));
- break;
+ CHECK(COMPILE(ret, "lvalue", node->nd_value));
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+ ADD_INSN2(ret, node, setinstancevariable,
+ ID2SYM(node->nd_vid),
+ get_ivar_ic_value(iseq,node->nd_vid));
+ break;
}
case NODE_CDECL:{
- CHECK(COMPILE(ret, "lvalue", node->nd_value));
+ if (node->nd_vid) {
+ CHECK(COMPILE(ret, "lvalue", node->nd_value));
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+
+ ADD_INSN1(ret, node, putspecialobject,
+ INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
+ ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_vid));
}
+ else {
+ compile_cpath(ret, iseq, node->nd_else);
+ CHECK(COMPILE(ret, "lvalue", node->nd_value));
+ ADD_INSN(ret, node, swap);
- if (node->nd_vid) {
- ADD_INSN1(ret, line_node, putspecialobject,
- INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
- ADD_INSN1(ret, line_node, setconstant, ID2SYM(node->nd_vid));
- }
- else {
- compile_cpath(ret, iseq, node->nd_else);
- ADD_INSN1(ret, line_node, setconstant, ID2SYM(node->nd_else->nd_mid));
- }
- break;
+ if (!popped) {
+ ADD_INSN1(ret, node, topn, INT2FIX(1));
+ ADD_INSN(ret, node, swap);
+ }
+
+ ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_else->nd_mid));
+ }
+ break;
}
case NODE_CVASGN:{
- CHECK(COMPILE(ret, "cvasgn val", node->nd_value));
- if (!popped) {
- ADD_INSN(ret, line_node, dup);
- }
- ADD_INSN2(ret, line_node, setclassvariable,
+ CHECK(COMPILE(ret, "cvasgn val", node->nd_value));
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
+ ADD_INSN2(ret, node, setclassvariable,
ID2SYM(node->nd_vid),
- get_ivar_ic_value(iseq,node->nd_vid));
- break;
- }
- case NODE_OP_ASGN1: {
- VALUE argc;
- unsigned int flag = 0;
- int asgnflag = 0;
- ID id = node->nd_mid;
- int boff = 0;
-
- /*
- * a[x] (op)= y
- *
- * nil # nil
- * eval a # nil a
- * eval x # nil a x
- * dupn 2 # nil a x a x
- * send :[] # nil a x a[x]
- * eval y # nil a x a[x] y
- * send op # nil a x ret
- * setn 3 # ret a x ret
- * send []= # ret ?
- * pop # ret
- */
-
- /*
- * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
- * NODE_OP_ASGN nd_recv
- * nd_args->nd_head
- * nd_args->nd_body
- * nd_mid
- */
-
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
- asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node);
- CHECK(asgnflag != -1);
- switch (nd_type(node->nd_args->nd_head)) {
- case NODE_ZLIST:
- argc = INT2FIX(0);
- break;
- case NODE_BLOCK_PASS:
- boff = 1;
- /* fall through */
- default:
- argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag, NULL);
- CHECK(!NIL_P(argc));
- }
- ADD_INSN1(ret, line_node, dupn, FIXNUM_INC(argc, 1 + boff));
- flag |= asgnflag;
- ADD_SEND_WITH_FLAG(ret, line_node, idAREF, argc, INT2FIX(flag));
-
- if (id == idOROP || id == idANDOP) {
- /* a[x] ||= y or a[x] &&= y
-
- unless/if a[x]
- a[x]= y
- else
- nil
- end
- */
- LABEL *label = NEW_LABEL(line);
- LABEL *lfin = NEW_LABEL(line);
-
- ADD_INSN(ret, line_node, dup);
- if (id == idOROP) {
- ADD_INSNL(ret, line_node, branchif, label);
- }
- else { /* idANDOP */
- ADD_INSNL(ret, line_node, branchunless, label);
- }
- ADD_INSN(ret, line_node, pop);
-
- CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
- if (!popped) {
- ADD_INSN1(ret, line_node, setn, FIXNUM_INC(argc, 2+boff));
- }
- if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN1(ret, line_node, newarray, INT2FIX(1));
- if (boff > 0) {
- ADD_INSN1(ret, line_node, dupn, INT2FIX(3));
- ADD_INSN(ret, line_node, swap);
- ADD_INSN(ret, line_node, pop);
- }
- ADD_INSN(ret, line_node, concatarray);
- if (boff > 0) {
- ADD_INSN1(ret, line_node, setn, INT2FIX(3));
- ADD_INSN(ret, line_node, pop);
- ADD_INSN(ret, line_node, pop);
- }
- ADD_SEND_WITH_FLAG(ret, line_node, idASET, argc, INT2FIX(flag));
- }
- else {
- if (boff > 0)
- ADD_INSN(ret, line_node, swap);
- ADD_SEND_WITH_FLAG(ret, line_node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
- }
- ADD_INSN(ret, line_node, pop);
- ADD_INSNL(ret, line_node, jump, lfin);
- ADD_LABEL(ret, label);
- if (!popped) {
- ADD_INSN1(ret, line_node, setn, FIXNUM_INC(argc, 2+boff));
- }
- ADD_INSN1(ret, line_node, adjuststack, FIXNUM_INC(argc, 2+boff));
- ADD_LABEL(ret, lfin);
- }
- else {
- CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
- ADD_SEND(ret, line_node, id, INT2FIX(1));
- if (!popped) {
- ADD_INSN1(ret, line_node, setn, FIXNUM_INC(argc, 2+boff));
- }
- if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN1(ret, line_node, newarray, INT2FIX(1));
- if (boff > 0) {
- ADD_INSN1(ret, line_node, dupn, INT2FIX(3));
- ADD_INSN(ret, line_node, swap);
- ADD_INSN(ret, line_node, pop);
- }
- ADD_INSN(ret, line_node, concatarray);
- if (boff > 0) {
- ADD_INSN1(ret, line_node, setn, INT2FIX(3));
- ADD_INSN(ret, line_node, pop);
- ADD_INSN(ret, line_node, pop);
- }
- ADD_SEND_WITH_FLAG(ret, line_node, idASET, argc, INT2FIX(flag));
- }
- else {
- if (boff > 0)
- ADD_INSN(ret, line_node, swap);
- ADD_SEND_WITH_FLAG(ret, line_node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
- }
- ADD_INSN(ret, line_node, pop);
- }
-
- break;
- }
- case NODE_OP_ASGN2:{
- ID atype = node->nd_next->nd_mid;
- ID vid = node->nd_next->nd_vid, aid = rb_id_attrset(vid);
- int asgnflag;
- LABEL *lfin = NEW_LABEL(line);
- LABEL *lcfin = NEW_LABEL(line);
- LABEL *lskip = 0;
- /*
- class C; attr_accessor :c; end
- r = C.new
- r.a &&= v # asgn2
-
- eval r # r
- dup # r r
- eval r.a # r o
-
- # or
- dup # r o o
- if lcfin # r o
- pop # r
- eval v # r v
- swap # v r
- topn 1 # v r v
- send a= # v ?
- jump lfin # v ?
-
- lcfin: # r o
- swap # o r
-
- lfin: # o ?
- pop # o
-
- # and
- dup # r o o
- unless lcfin
- pop # r
- eval v # r v
- swap # v r
- topn 1 # v r v
- send a= # v ?
- jump lfin # v ?
-
- # others
- eval v # r o v
- send ?? # r w
- send a= # w
-
- */
-
- asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node);
- CHECK(asgnflag != -1);
- if (node->nd_next->nd_aid) {
- lskip = NEW_LABEL(line);
- ADD_INSN(ret, line_node, dup);
- ADD_INSNL(ret, line_node, branchnil, lskip);
- }
- ADD_INSN(ret, line_node, dup);
- ADD_SEND_WITH_FLAG(ret, line_node, vid, INT2FIX(0), INT2FIX(asgnflag));
-
- if (atype == idOROP || atype == idANDOP) {
- ADD_INSN(ret, line_node, dup);
- if (atype == idOROP) {
- ADD_INSNL(ret, line_node, branchif, lcfin);
- }
- else { /* idANDOP */
- ADD_INSNL(ret, line_node, branchunless, lcfin);
- }
- ADD_INSN(ret, line_node, pop);
- CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
- ADD_INSN(ret, line_node, swap);
- ADD_INSN1(ret, line_node, topn, INT2FIX(1));
- ADD_SEND_WITH_FLAG(ret, line_node, aid, INT2FIX(1), INT2FIX(asgnflag));
- ADD_INSNL(ret, line_node, jump, lfin);
-
- ADD_LABEL(ret, lcfin);
- ADD_INSN(ret, line_node, swap);
-
- ADD_LABEL(ret, lfin);
- ADD_INSN(ret, line_node, pop);
- if (lskip) {
- ADD_LABEL(ret, lskip);
- }
- if (popped) {
- /* we can apply more optimize */
- ADD_INSN(ret, line_node, pop);
- }
- }
- else {
- CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
- ADD_SEND(ret, line_node, atype, INT2FIX(1));
- if (!popped) {
- ADD_INSN(ret, line_node, swap);
- ADD_INSN1(ret, line_node, topn, INT2FIX(1));
- }
- ADD_SEND_WITH_FLAG(ret, line_node, aid, INT2FIX(1), INT2FIX(asgnflag));
- if (lskip && popped) {
- ADD_LABEL(ret, lskip);
- }
- ADD_INSN(ret, line_node, pop);
- if (lskip && !popped) {
- ADD_LABEL(ret, lskip);
- }
- }
- break;
- }
- case NODE_OP_CDECL: {
- LABEL *lfin = 0;
- LABEL *lassign = 0;
- ID mid;
-
- switch (nd_type(node->nd_head)) {
- case NODE_COLON3:
- ADD_INSN1(ret, line_node, putobject, rb_cObject);
- break;
- case NODE_COLON2:
- CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
- break;
- default:
- COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
- ruby_node_name(nd_type(node->nd_head)));
- goto ng;
- }
- mid = node->nd_head->nd_mid;
- /* cref */
- if (node->nd_aid == idOROP) {
- lassign = NEW_LABEL(line);
- ADD_INSN(ret, line_node, dup); /* cref cref */
- ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST_FROM),
- ID2SYM(mid), Qtrue); /* cref bool */
- ADD_INSNL(ret, line_node, branchunless, lassign); /* cref */
- }
- ADD_INSN(ret, line_node, dup); /* cref cref */
- ADD_INSN1(ret, line_node, putobject, Qtrue);
- ADD_INSN1(ret, line_node, getconstant, ID2SYM(mid)); /* cref obj */
-
- if (node->nd_aid == idOROP || node->nd_aid == idANDOP) {
- lfin = NEW_LABEL(line);
- if (!popped) ADD_INSN(ret, line_node, dup); /* cref [obj] obj */
- if (node->nd_aid == idOROP)
- ADD_INSNL(ret, line_node, branchif, lfin);
- else /* idANDOP */
- ADD_INSNL(ret, line_node, branchunless, lfin);
- /* cref [obj] */
- if (!popped) ADD_INSN(ret, line_node, pop); /* cref */
- if (lassign) ADD_LABEL(ret, lassign);
- CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
- /* cref value */
- if (popped)
- ADD_INSN1(ret, line_node, topn, INT2FIX(1)); /* cref value cref */
- else {
- ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); /* cref value cref value */
- ADD_INSN(ret, line_node, swap); /* cref value value cref */
- }
- ADD_INSN1(ret, line_node, setconstant, ID2SYM(mid)); /* cref [value] */
- ADD_LABEL(ret, lfin); /* cref [value] */
- if (!popped) ADD_INSN(ret, line_node, swap); /* [value] cref */
- ADD_INSN(ret, line_node, pop); /* [value] */
- }
- else {
- CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
- /* cref obj value */
- ADD_CALL(ret, line_node, node->nd_aid, INT2FIX(1));
- /* cref value */
- ADD_INSN(ret, line_node, swap); /* value cref */
- if (!popped) {
- ADD_INSN1(ret, line_node, topn, INT2FIX(1)); /* value cref value */
- ADD_INSN(ret, line_node, swap); /* value value cref */
- }
- ADD_INSN1(ret, line_node, setconstant, ID2SYM(mid));
- }
- break;
+ get_cvar_ic_value(iseq,node->nd_vid));
+ break;
}
+ case NODE_OP_ASGN1:
+ CHECK(compile_op_asgn1(iseq, ret, node, popped));
+ break;
+ case NODE_OP_ASGN2:
+ CHECK(compile_op_asgn2(iseq, ret, node, popped));
+ break;
+ case NODE_OP_CDECL:
+ CHECK(compile_op_cdecl(iseq, ret, node, popped));
+ break;
case NODE_OP_ASGN_AND:
- case NODE_OP_ASGN_OR:{
- LABEL *lfin = NEW_LABEL(line);
- LABEL *lassign;
-
- if (nd_type(node) == NODE_OP_ASGN_OR && nd_type(node->nd_head) != NODE_IVAR) {
- LABEL *lfinish[2];
- lfinish[0] = lfin;
- lfinish[1] = 0;
- defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
- lassign = lfinish[1];
- if (!lassign) {
- lassign = NEW_LABEL(line);
- }
- ADD_INSNL(ret, line_node, branchunless, lassign);
- }
- else {
- lassign = NEW_LABEL(line);
- }
-
- CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
- ADD_INSN(ret, line_node, dup);
-
- if (nd_type(node) == NODE_OP_ASGN_AND) {
- ADD_INSNL(ret, line_node, branchunless, lfin);
- }
- else {
- ADD_INSNL(ret, line_node, branchif, lfin);
- }
-
- ADD_INSN(ret, line_node, pop);
- ADD_LABEL(ret, lassign);
- CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
- ADD_LABEL(ret, lfin);
-
- if (popped) {
- /* we can apply more optimize */
- ADD_INSN(ret, line_node, pop);
- }
- break;
- }
+ case NODE_OP_ASGN_OR:
+ CHECK(compile_op_log(iseq, ret, node, popped, type));
+ break;
case NODE_CALL: /* obj.foo */
case NODE_OPCALL: /* foo[] */
- if (compile_call_precheck_freeze(iseq, ret, node, line_node, popped) == TRUE) {
+ if (compile_call_precheck_freeze(iseq, ret, node, node, popped) == TRUE) {
break;
}
case NODE_QCALL: /* obj&.foo */
case NODE_FCALL: /* foo() */
case NODE_VCALL: /* foo (variable or call) */
- if (compile_call(iseq, ret, node, type, line_node, popped, false) == COMPILE_NG) {
+ if (compile_call(iseq, ret, node, type, node, popped, false) == COMPILE_NG) {
goto ng;
}
break;
case NODE_SUPER:
- case NODE_ZSUPER:{
- DECL_ANCHOR(args);
- int argc;
- unsigned int flag = 0;
- struct rb_callinfo_kwarg *keywords = NULL;
- const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
-
- INIT_ANCHOR(args);
- ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
- if (type == NODE_SUPER) {
- VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
- CHECK(!NIL_P(vargc));
- argc = FIX2INT(vargc);
- }
- else {
- /* NODE_ZSUPER */
- int i;
- const rb_iseq_t *liseq = body->local_iseq;
- const struct rb_iseq_constant_body *const local_body = liseq->body;
- const struct rb_iseq_param_keyword *const local_kwd = local_body->param.keyword;
- int lvar_level = get_lvar_level(iseq);
-
- argc = local_body->param.lead_num;
-
- /* normal arguments */
- for (i = 0; i < local_body->param.lead_num; i++) {
- int idx = local_body->local_table_size - i;
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- }
-
- if (local_body->param.flags.has_opt) {
- /* optional arguments */
- int j;
- for (j = 0; j < local_body->param.opt_num; j++) {
- int idx = local_body->local_table_size - (i + j);
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- }
- i += j;
- argc = i;
- }
- if (local_body->param.flags.has_rest) {
- /* rest argument */
- int idx = local_body->local_table_size - local_body->param.rest_start;
-
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- ADD_INSN1(args, line_node, splatarray, Qfalse);
-
- argc = local_body->param.rest_start + 1;
- flag |= VM_CALL_ARGS_SPLAT;
- }
- if (local_body->param.flags.has_post) {
- /* post arguments */
- int post_len = local_body->param.post_num;
- int post_start = local_body->param.post_start;
-
- if (local_body->param.flags.has_rest) {
- int j;
- for (j=0; j<post_len; j++) {
- int idx = local_body->local_table_size - (post_start + j);
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- }
- ADD_INSN1(args, line_node, newarray, INT2FIX(j));
- ADD_INSN (args, line_node, concatarray);
- /* argc is settled at above */
- }
- else {
- int j;
- for (j=0; j<post_len; j++) {
- int idx = local_body->local_table_size - (post_start + j);
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- }
- argc = post_len + post_start;
- }
- }
-
- if (local_body->param.flags.has_kw) { /* TODO: support keywords */
- int local_size = local_body->local_table_size;
- argc++;
-
- ADD_INSN1(args, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
-
- if (local_body->param.flags.has_kwrest) {
- int idx = local_body->local_table_size - local_kwd->rest_start;
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- if (local_kwd->num > 0) {
- ADD_SEND(args, line_node, rb_intern("dup"), INT2FIX(0));
- flag |= VM_CALL_KW_SPLAT_MUT;
- }
- }
- else {
- ADD_INSN1(args, line_node, newhash, INT2FIX(0));
- flag |= VM_CALL_KW_SPLAT_MUT;
- }
- for (i = 0; i < local_kwd->num; ++i) {
- ID id = local_kwd->table[i];
- int idx = local_size - get_local_var_idx(liseq, id);
- ADD_INSN1(args, line_node, putobject, ID2SYM(id));
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
- }
- ADD_SEND(args, line_node, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
- if (local_body->param.flags.has_rest) {
- ADD_INSN1(args, line_node, newarray, INT2FIX(1));
- ADD_INSN (args, line_node, concatarray);
- --argc;
- }
- flag |= VM_CALL_KW_SPLAT;
- }
- else if (local_body->param.flags.has_kwrest) {
- int idx = local_body->local_table_size - local_kwd->rest_start;
- ADD_GETLOCAL(args, line_node, idx, lvar_level);
-
- if (local_body->param.flags.has_rest) {
- ADD_INSN1(args, line_node, newarray, INT2FIX(1));
- ADD_INSN (args, line_node, concatarray);
- }
- else {
- argc++;
- }
- flag |= VM_CALL_KW_SPLAT;
- }
- }
-
- ADD_INSN(ret, line_node, putself);
- ADD_SEQ(ret, args);
- ADD_INSN2(ret, line_node, invokesuper,
- new_callinfo(iseq, 0, argc, flag | VM_CALL_SUPER | (type == NODE_ZSUPER ? VM_CALL_ZSUPER : 0) | VM_CALL_FCALL, keywords, parent_block != NULL),
- parent_block);
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
- }
+ case NODE_ZSUPER:
+ CHECK(compile_super(iseq, ret, node, popped, type));
+ break;
case NODE_LIST:{
CHECK(compile_array(iseq, ret, node, popped) >= 0);
- break;
+ break;
}
case NODE_ZLIST:{
- if (!popped) {
- ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
- }
- break;
+ if (!popped) {
+ ADD_INSN1(ret, node, newarray, INT2FIX(0));
+ }
+ break;
}
case NODE_VALUES:{
- const NODE *n = node;
- if (popped) {
- COMPILE_ERROR(ERROR_ARGS "NODE_VALUES: must not be popped");
- }
- while (n) {
- CHECK(COMPILE(ret, "values item", n->nd_head));
- n = n->nd_next;
- }
- ADD_INSN1(ret, line_node, newarray, INT2FIX(node->nd_alen));
- break;
+ const NODE *n = node;
+ if (popped) {
+ COMPILE_ERROR(ERROR_ARGS "NODE_VALUES: must not be popped");
+ }
+ while (n) {
+ CHECK(COMPILE(ret, "values item", n->nd_head));
+ n = n->nd_next;
+ }
+ ADD_INSN1(ret, node, newarray, INT2FIX(node->nd_alen));
+ break;
}
case NODE_HASH:
CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0);
break;
case NODE_RETURN:
- CHECK(compile_return(iseq, ret, node, popped));
- break;
- case NODE_YIELD:{
- DECL_ANCHOR(args);
- VALUE argc;
- unsigned int flag = 0;
- struct rb_callinfo_kwarg *keywords = NULL;
-
- INIT_ANCHOR(args);
-
- if (check_yield_place(iseq) == FALSE) {
- COMPILE_ERROR(ERROR_ARGS "Invalid yield");
- goto ng;
- }
-
- if (node->nd_head) {
- argc = setup_args(iseq, args, node->nd_head, &flag, &keywords);
- CHECK(!NIL_P(argc));
- }
- else {
- argc = INT2FIX(0);
- }
-
- ADD_SEQ(ret, args);
- ADD_INSN1(ret, line_node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE));
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
-
- int level = 0;
- const rb_iseq_t *tmp_iseq = iseq;
- for (; tmp_iseq != iseq->body->local_iseq; level++ ) {
- tmp_iseq = tmp_iseq->body->parent_iseq;
- }
- if (level > 0) access_outer_variables(iseq, level, rb_intern("yield"), true);
- break;
- }
+ CHECK(compile_return(iseq, ret, node, popped));
+ break;
+ case NODE_YIELD:
+ CHECK(compile_yield(iseq, ret, node, popped));
+ break;
case NODE_LVAR:{
- if (!popped) {
- compile_lvar(iseq, ret, line_node, node->nd_vid);
- }
- break;
+ if (!popped) {
+ compile_lvar(iseq, ret, node, node->nd_vid);
+ }
+ break;
}
case NODE_DVAR:{
- int lv, idx, ls;
- debugi("nd_vid", node->nd_vid);
- if (!popped) {
- idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
- if (idx < 0) {
- COMPILE_ERROR(ERROR_ARGS "unknown dvar (%"PRIsVALUE")",
- rb_id2str(node->nd_vid));
- goto ng;
- }
- ADD_GETLOCAL(ret, line_node, ls - idx, lv);
- }
- break;
+ int lv, idx, ls;
+ debugi("nd_vid", node->nd_vid);
+ if (!popped) {
+ idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
+ if (idx < 0) {
+ COMPILE_ERROR(ERROR_ARGS "unknown dvar (%"PRIsVALUE")",
+ rb_id2str(node->nd_vid));
+ goto ng;
+ }
+ ADD_GETLOCAL(ret, node, ls - idx, lv);
+ }
+ break;
}
case NODE_GVAR:{
- ADD_INSN1(ret, line_node, getglobal, ID2SYM(node->nd_entry));
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ ADD_INSN1(ret, node, getglobal, ID2SYM(node->nd_entry));
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_IVAR:{
- debugi("nd_vid", node->nd_vid);
- if (!popped) {
- ADD_INSN2(ret, line_node, getinstancevariable,
- ID2SYM(node->nd_vid),
- get_ivar_ic_value(iseq,node->nd_vid));
- }
- break;
+ debugi("nd_vid", node->nd_vid);
+ if (!popped) {
+ ADD_INSN2(ret, node, getinstancevariable,
+ ID2SYM(node->nd_vid),
+ get_ivar_ic_value(iseq,node->nd_vid));
+ }
+ break;
}
case NODE_CONST:{
- debugi("nd_vid", node->nd_vid);
-
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- LABEL *lend = NEW_LABEL(line);
- int ic_index = body->is_size++;
-
- ADD_INSN2(ret, line_node, opt_getinlinecache, lend, INT2FIX(ic_index));
- ADD_INSN1(ret, line_node, putobject, Qtrue);
- ADD_INSN1(ret, line_node, getconstant, ID2SYM(node->nd_vid));
- ADD_INSN1(ret, line_node, opt_setinlinecache, INT2FIX(ic_index));
- ADD_LABEL(ret, lend);
- }
- else {
- ADD_INSN(ret, line_node, putnil);
- ADD_INSN1(ret, line_node, putobject, Qtrue);
- ADD_INSN1(ret, line_node, getconstant, ID2SYM(node->nd_vid));
- }
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ debugi("nd_vid", node->nd_vid);
+
+ if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
+ body->ic_size++;
+ VALUE segments = rb_ary_new_from_args(1, ID2SYM(node->nd_vid));
+ ADD_INSN1(ret, node, opt_getconstant_path, segments);
+ RB_OBJ_WRITTEN(iseq, Qundef, segments);
+ }
+ else {
+ ADD_INSN(ret, node, putnil);
+ ADD_INSN1(ret, node, putobject, Qtrue);
+ ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_vid));
+ }
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_CVAR:{
- if (!popped) {
- ADD_INSN2(ret, line_node, getclassvariable,
- ID2SYM(node->nd_vid),
- get_ivar_ic_value(iseq,node->nd_vid));
- }
- break;
+ if (!popped) {
+ ADD_INSN2(ret, node, getclassvariable,
+ ID2SYM(node->nd_vid),
+ get_cvar_ic_value(iseq,node->nd_vid));
+ }
+ break;
}
case NODE_NTH_REF:{
if (!popped) {
- if (!node->nd_nth) {
- ADD_INSN(ret, line_node, putnil);
- break;
- }
- ADD_INSN2(ret, line_node, getspecial, INT2FIX(1) /* '~' */,
- INT2FIX(node->nd_nth << 1));
- }
- break;
+ if (!node->nd_nth) {
+ ADD_INSN(ret, node, putnil);
+ break;
+ }
+ ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */,
+ INT2FIX(node->nd_nth << 1));
+ }
+ break;
}
case NODE_BACK_REF:{
- if (!popped) {
- ADD_INSN2(ret, line_node, getspecial, INT2FIX(1) /* '~' */,
- INT2FIX(0x01 | (node->nd_nth << 1)));
- }
- break;
+ if (!popped) {
+ ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */,
+ INT2FIX(0x01 | (node->nd_nth << 1)));
+ }
+ break;
}
case NODE_MATCH:
case NODE_MATCH2:
- case NODE_MATCH3:{
- DECL_ANCHOR(recv);
- DECL_ANCHOR(val);
-
- INIT_ANCHOR(recv);
- INIT_ANCHOR(val);
- switch (nd_type(node)) {
- case NODE_MATCH:
- ADD_INSN1(recv, line_node, putobject, node->nd_lit);
- ADD_INSN2(val, line_node, getspecial, INT2FIX(0),
- INT2FIX(0));
- break;
- case NODE_MATCH2:
- CHECK(COMPILE(recv, "receiver", node->nd_recv));
- CHECK(COMPILE(val, "value", node->nd_value));
- break;
- case NODE_MATCH3:
- CHECK(COMPILE(recv, "receiver", node->nd_value));
- CHECK(COMPILE(val, "value", node->nd_recv));
- break;
- }
-
- ADD_SEQ(ret, recv);
- ADD_SEQ(ret, val);
- ADD_SEND(ret, line_node, idEqTilde, INT2FIX(1));
-
- if (node->nd_args) {
- compile_named_capture_assign(iseq, ret, node->nd_args);
- }
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
- }
+ case NODE_MATCH3:
+ CHECK(compile_match(iseq, ret, node, popped, type));
+ break;
case NODE_LIT:{
- debugp_param("lit", node->nd_lit);
- if (!popped) {
- ADD_INSN1(ret, line_node, putobject, node->nd_lit);
+ debugp_param("lit", node->nd_lit);
+ if (!popped) {
+ if (UNLIKELY(node->nd_lit == rb_mRubyVMFrozenCore)) {
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); // [Bug #20569]
+ }
+ else {
+ ADD_INSN1(ret, node, putobject, node->nd_lit);
+ }
RB_OBJ_WRITTEN(iseq, Qundef, node->nd_lit);
- }
- break;
+ }
+ break;
}
case NODE_STR:{
- debugp_param("nd_lit", node->nd_lit);
- if (!popped) {
- VALUE lit = node->nd_lit;
- if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
- lit = rb_fstring(lit);
- ADD_INSN1(ret, line_node, putstring, lit);
+ debugp_param("nd_lit", node->nd_lit);
+ if (!popped) {
+ VALUE lit = node->nd_lit;
+ if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
+ lit = rb_fstring(lit);
+ ADD_INSN1(ret, node, putstring, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
- }
- else {
- if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
- VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
- lit = rb_str_dup(lit);
- rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
- lit = rb_str_freeze(lit);
- }
- else {
- lit = rb_fstring(lit);
- }
- ADD_INSN1(ret, line_node, putobject, lit);
+ }
+ else {
+ if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
+ VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
+ lit = rb_str_dup(lit);
+ rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
+ lit = rb_str_freeze(lit);
+ }
+ else {
+ lit = rb_fstring(lit);
+ }
+ ADD_INSN1(ret, node, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
- }
- }
- break;
+ }
+ }
+ break;
}
case NODE_DSTR:{
- compile_dstr(iseq, ret, node);
+ compile_dstr(iseq, ret, node);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_XSTR:{
- ADD_CALL_RECEIVER(ret, line_node);
+ ADD_CALL_RECEIVER(ret, node);
VALUE str = rb_fstring(node->nd_lit);
- ADD_INSN1(ret, line_node, putobject, str);
+ ADD_INSN1(ret, node, putobject, str);
RB_OBJ_WRITTEN(iseq, Qundef, str);
- ADD_CALL(ret, line_node, idBackquote, INT2FIX(1));
+ ADD_CALL(ret, node, idBackquote, INT2FIX(1));
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_DXSTR:{
- ADD_CALL_RECEIVER(ret, line_node);
- compile_dstr(iseq, ret, node);
- ADD_CALL(ret, line_node, idBackquote, INT2FIX(1));
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ ADD_CALL_RECEIVER(ret, node);
+ compile_dstr(iseq, ret, node);
+ ADD_CALL(ret, node, idBackquote, INT2FIX(1));
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_EVSTR:
- CHECK(compile_evstr(iseq, ret, node->nd_body, popped));
- break;
+ CHECK(compile_evstr(iseq, ret, node->nd_body, popped));
+ break;
case NODE_DREGX:{
- compile_dregx(iseq, ret, node);
+ compile_dregx(iseq, ret, node);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_ONCE:{
- int ic_index = body->is_size++;
- const rb_iseq_t *block_iseq;
- block_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
+ int ic_index = body->ise_size++;
+ const rb_iseq_t *block_iseq;
+ block_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
- ADD_INSN2(ret, line_node, once, block_iseq, INT2FIX(ic_index));
+ ADD_INSN2(ret, node, once, block_iseq, INT2FIX(ic_index));
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block_iseq);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_ARGSCAT:{
- if (popped) {
- CHECK(COMPILE(ret, "argscat head", node->nd_head));
- ADD_INSN1(ret, line_node, splatarray, Qfalse);
- ADD_INSN(ret, line_node, pop);
- CHECK(COMPILE(ret, "argscat body", node->nd_body));
- ADD_INSN1(ret, line_node, splatarray, Qfalse);
- ADD_INSN(ret, line_node, pop);
- }
- else {
- CHECK(COMPILE(ret, "argscat head", node->nd_head));
- CHECK(COMPILE(ret, "argscat body", node->nd_body));
- ADD_INSN(ret, line_node, concatarray);
- }
- break;
+ if (popped) {
+ CHECK(COMPILE(ret, "argscat head", node->nd_head));
+ ADD_INSN1(ret, node, splatarray, Qfalse);
+ ADD_INSN(ret, node, pop);
+ CHECK(COMPILE(ret, "argscat body", node->nd_body));
+ ADD_INSN1(ret, node, splatarray, Qfalse);
+ ADD_INSN(ret, node, pop);
+ }
+ else {
+ CHECK(COMPILE(ret, "argscat head", node->nd_head));
+ CHECK(COMPILE(ret, "argscat body", node->nd_body));
+ ADD_INSN(ret, node, concatarray);
+ }
+ break;
}
case NODE_ARGSPUSH:{
- if (popped) {
- CHECK(COMPILE(ret, "arsgpush head", node->nd_head));
- ADD_INSN1(ret, line_node, splatarray, Qfalse);
- ADD_INSN(ret, line_node, pop);
- CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
- }
- else {
- CHECK(COMPILE(ret, "arsgpush head", node->nd_head));
- CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
- ADD_INSN1(ret, line_node, newarray, INT2FIX(1));
- ADD_INSN(ret, line_node, concatarray);
- }
- break;
+ if (popped) {
+ CHECK(COMPILE(ret, "argspush head", node->nd_head));
+ ADD_INSN1(ret, node, splatarray, Qfalse);
+ ADD_INSN(ret, node, pop);
+ CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
+ }
+ else {
+ CHECK(COMPILE(ret, "argspush head", node->nd_head));
+ CHECK(compile_array_1(iseq, ret, node->nd_body));
+ ADD_INSN(ret, node, concatarray);
+ }
+ break;
}
case NODE_SPLAT:{
- CHECK(COMPILE(ret, "splat", node->nd_head));
- ADD_INSN1(ret, line_node, splatarray, Qtrue);
+ CHECK(COMPILE(ret, "splat", node->nd_head));
+ ADD_INSN1(ret, node, splatarray, Qtrue);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_DEFN:{
ID mid = node->nd_mid;
- const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
+ const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
rb_id2str(mid),
- ISEQ_TYPE_METHOD, line);
+ ISEQ_TYPE_METHOD, line);
- debugp_param("defn/iseq", rb_iseqw_new(method_iseq));
- ADD_INSN2(ret, line_node, definemethod, ID2SYM(mid), method_iseq);
+ debugp_param("defn/iseq", rb_iseqw_new(method_iseq));
+ ADD_INSN2(ret, node, definemethod, ID2SYM(mid), method_iseq);
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)method_iseq);
if (!popped) {
- ADD_INSN1(ret, line_node, putobject, ID2SYM(mid));
- }
+ ADD_INSN1(ret, node, putobject, ID2SYM(mid));
+ }
- break;
+ break;
}
case NODE_DEFS:{
ID mid = node->nd_mid;
@@ -8907,428 +9917,212 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
debugp_param("defs/iseq", rb_iseqw_new(singleton_method_iseq));
CHECK(COMPILE(ret, "defs: recv", node->nd_recv));
- ADD_INSN2(ret, line_node, definesmethod, ID2SYM(mid), singleton_method_iseq);
+ ADD_INSN2(ret, node, definesmethod, ID2SYM(mid), singleton_method_iseq);
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)singleton_method_iseq);
if (!popped) {
- ADD_INSN1(ret, line_node, putobject, ID2SYM(mid));
+ ADD_INSN1(ret, node, putobject, ID2SYM(mid));
}
- break;
+ break;
}
case NODE_ALIAS:{
- ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
- CHECK(COMPILE(ret, "alias arg1", node->nd_1st));
- CHECK(COMPILE(ret, "alias arg2", node->nd_2nd));
- ADD_SEND(ret, line_node, id_core_set_method_alias, INT2FIX(3));
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
+ CHECK(COMPILE(ret, "alias arg1", node->nd_1st));
+ CHECK(COMPILE(ret, "alias arg2", node->nd_2nd));
+ ADD_SEND(ret, node, id_core_set_method_alias, INT2FIX(3));
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_VALIAS:{
- ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_INSN1(ret, line_node, putobject, ID2SYM(node->nd_alias));
- ADD_INSN1(ret, line_node, putobject, ID2SYM(node->nd_orig));
- ADD_SEND(ret, line_node, id_core_set_variable_alias, INT2FIX(2));
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, node, putobject, ID2SYM(node->nd_alias));
+ ADD_INSN1(ret, node, putobject, ID2SYM(node->nd_orig));
+ ADD_SEND(ret, node, id_core_set_variable_alias, INT2FIX(2));
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_UNDEF:{
- ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
- CHECK(COMPILE(ret, "undef arg", node->nd_undef));
- ADD_SEND(ret, line_node, id_core_undef_method, INT2FIX(2));
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
+ CHECK(COMPILE(ret, "undef arg", node->nd_undef));
+ ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2));
+
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_CLASS:{
- const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body,
- rb_str_freeze(rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid))),
- ISEQ_TYPE_CLASS, line);
- const int flags = VM_DEFINECLASS_TYPE_CLASS |
- (node->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
- compile_cpath(ret, iseq, node->nd_cpath);
-
- CHECK(COMPILE(ret, "super", node->nd_super));
- ADD_INSN3(ret, line_node, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags));
+ const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body,
+ rb_str_freeze(rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid))),
+ ISEQ_TYPE_CLASS, line);
+ const int flags = VM_DEFINECLASS_TYPE_CLASS |
+ (node->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
+ compile_cpath(ret, iseq, node->nd_cpath);
+
+ CHECK(COMPILE(ret, "super", node->nd_super));
+ ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags));
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)class_iseq);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_MODULE:{
const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body,
- rb_str_freeze(rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid))),
- ISEQ_TYPE_CLASS, line);
- const int flags = VM_DEFINECLASS_TYPE_MODULE |
- compile_cpath(ret, iseq, node->nd_cpath);
+ rb_str_freeze(rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid))),
+ ISEQ_TYPE_CLASS, line);
+ const int flags = VM_DEFINECLASS_TYPE_MODULE |
+ compile_cpath(ret, iseq, node->nd_cpath);
- ADD_INSN (ret, line_node, putnil); /* dummy */
- ADD_INSN3(ret, line_node, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags));
+ ADD_INSN (ret, node, putnil); /* dummy */
+ ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags));
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)module_iseq);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_SCLASS:{
- ID singletonclass;
- const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_fstring_lit("singleton class"),
- ISEQ_TYPE_CLASS, line);
-
- CHECK(COMPILE(ret, "sclass#recv", node->nd_recv));
- ADD_INSN (ret, line_node, putnil);
- CONST_ID(singletonclass, "singletonclass");
- ADD_INSN3(ret, line_node, defineclass,
- ID2SYM(singletonclass), singleton_class,
- INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS));
+ ID singletonclass;
+ const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_fstring_lit("singleton class"),
+ ISEQ_TYPE_CLASS, line);
+
+ CHECK(COMPILE(ret, "sclass#recv", node->nd_recv));
+ ADD_INSN (ret, node, putnil);
+ CONST_ID(singletonclass, "singletonclass");
+ ADD_INSN3(ret, node, defineclass,
+ ID2SYM(singletonclass), singleton_class,
+ INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS));
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)singleton_class);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
- }
- case NODE_COLON2:{
- if (rb_is_const_id(node->nd_mid)) {
- /* constant */
- LABEL *lend = NEW_LABEL(line);
- int ic_index = body->is_size++;
-
- DECL_ANCHOR(pref);
- DECL_ANCHOR(body);
-
- INIT_ANCHOR(pref);
- INIT_ANCHOR(body);
- CHECK(compile_const_prefix(iseq, node, pref, body));
- if (LIST_INSN_SIZE_ZERO(pref)) {
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN2(ret, line_node, opt_getinlinecache, lend, INT2FIX(ic_index));
- }
- else {
- ADD_INSN(ret, line_node, putnil);
- }
-
- ADD_SEQ(ret, body);
-
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN1(ret, line_node, opt_setinlinecache, INT2FIX(ic_index));
- ADD_LABEL(ret, lend);
- }
- }
- else {
- ADD_SEQ(ret, pref);
- ADD_SEQ(ret, body);
- }
- }
- else {
- /* function call */
- ADD_CALL_RECEIVER(ret, line_node);
- CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head));
- ADD_CALL(ret, line_node, node->nd_mid, INT2FIX(1));
- }
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
- }
- case NODE_COLON3:{
- LABEL *lend = NEW_LABEL(line);
- int ic_index = body->is_size++;
-
- debugi("colon3#nd_mid", node->nd_mid);
-
- /* add cache insn */
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN2(ret, line_node, opt_getinlinecache, lend, INT2FIX(ic_index));
- ADD_INSN(ret, line_node, pop);
- }
-
- ADD_INSN1(ret, line_node, putobject, rb_cObject);
- ADD_INSN1(ret, line_node, putobject, Qtrue);
- ADD_INSN1(ret, line_node, getconstant, ID2SYM(node->nd_mid));
-
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN1(ret, line_node, opt_setinlinecache, INT2FIX(ic_index));
- ADD_LABEL(ret, lend);
- }
-
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
+ case NODE_COLON2:
+ CHECK(compile_colon2(iseq, ret, node, popped));
+ break;
+ case NODE_COLON3:
+ CHECK(compile_colon3(iseq, ret, node, popped));
+ break;
case NODE_DOT2:
- case NODE_DOT3:{
- int excl = type == NODE_DOT3;
- VALUE flag = INT2FIX(excl);
- const NODE *b = node->nd_beg;
- const NODE *e = node->nd_end;
-
- if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
- if (!popped) {
- 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_node, putobject, val);
- RB_OBJ_WRITTEN(iseq, Qundef, val);
- }
- }
- else {
- CHECK(COMPILE_(ret, "min", b, popped));
- CHECK(COMPILE_(ret, "max", e, popped));
- if (!popped) {
- ADD_INSN1(ret, line_node, newrange, flag);
- }
- }
- break;
- }
+ CHECK(compile_dots(iseq, ret, node, popped, FALSE));
+ break;
+ case NODE_DOT3:
+ CHECK(compile_dots(iseq, ret, node, popped, TRUE));
+ break;
case NODE_FLIP2:
case NODE_FLIP3:{
- LABEL *lend = NEW_LABEL(line);
- LABEL *ltrue = NEW_LABEL(line);
- LABEL *lfalse = NEW_LABEL(line);
- CHECK(compile_flip_flop(iseq, ret, node, type == NODE_FLIP2,
- ltrue, lfalse));
- ADD_LABEL(ret, ltrue);
- ADD_INSN1(ret, line_node, putobject, Qtrue);
- ADD_INSNL(ret, line_node, jump, lend);
- ADD_LABEL(ret, lfalse);
- ADD_INSN1(ret, line_node, putobject, Qfalse);
- ADD_LABEL(ret, lend);
- break;
+ LABEL *lend = NEW_LABEL(line);
+ LABEL *ltrue = NEW_LABEL(line);
+ LABEL *lfalse = NEW_LABEL(line);
+ CHECK(compile_flip_flop(iseq, ret, node, type == NODE_FLIP2,
+ ltrue, lfalse));
+ ADD_LABEL(ret, ltrue);
+ ADD_INSN1(ret, node, putobject, Qtrue);
+ ADD_INSNL(ret, node, jump, lend);
+ ADD_LABEL(ret, lfalse);
+ ADD_INSN1(ret, node, putobject, Qfalse);
+ ADD_LABEL(ret, lend);
+ break;
}
case NODE_SELF:{
- if (!popped) {
- ADD_INSN(ret, line_node, putself);
- }
- break;
+ if (!popped) {
+ ADD_INSN(ret, node, putself);
+ }
+ break;
}
case NODE_NIL:{
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- }
- break;
+ if (!popped) {
+ ADD_INSN(ret, node, putnil);
+ }
+ break;
}
case NODE_TRUE:{
- if (!popped) {
- ADD_INSN1(ret, line_node, putobject, Qtrue);
- }
- break;
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, Qtrue);
+ }
+ break;
}
case NODE_FALSE:{
- if (!popped) {
- ADD_INSN1(ret, line_node, putobject, Qfalse);
- }
- break;
- }
- case NODE_ERRINFO:{
- if (!popped) {
- if (body->type == ISEQ_TYPE_RESCUE) {
- ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
- }
- else {
- const rb_iseq_t *ip = iseq;
- int level = 0;
- while (ip) {
- if (ip->body->type == ISEQ_TYPE_RESCUE) {
- break;
- }
- ip = ip->body->parent_iseq;
- level++;
- }
- if (ip) {
- ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, level);
- }
- else {
- ADD_INSN(ret, line_node, putnil);
- }
- }
- }
- break;
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, Qfalse);
+ }
+ break;
}
+ case NODE_ERRINFO:
+ CHECK(compile_errinfo(iseq, ret, node, popped));
+ break;
case NODE_DEFINED:
- if (!popped) {
- CHECK(compile_defined_expr(iseq, ret, node, Qtrue));
- }
- break;
+ if (!popped) {
+ CHECK(compile_defined_expr(iseq, ret, node, Qtrue));
+ }
+ break;
case NODE_POSTEXE:{
- /* compiled to:
- * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } }
- */
- int is_index = body->is_size++;
+ /* compiled to:
+ * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } }
+ */
+ int is_index = body->ise_size++;
struct rb_iseq_new_with_callback_callback_func *ifunc =
rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body);
- const rb_iseq_t *once_iseq =
+ const rb_iseq_t *once_iseq =
new_child_iseq_with_callback(iseq, ifunc,
- rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
+ rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
- ADD_INSN2(ret, line_node, once, once_iseq, INT2FIX(is_index));
+ ADD_INSN2(ret, node, once, once_iseq, INT2FIX(is_index));
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)once_iseq);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_KW_ARG:
- {
- LABEL *end_label = NEW_LABEL(nd_line(node));
- const NODE *default_value = node->nd_body->nd_value;
-
- if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) {
- /* required argument. do nothing */
- COMPILE_ERROR(ERROR_ARGS "unreachable");
- goto ng;
- }
- else if (nd_type(default_value) == NODE_LIT ||
- nd_type(default_value) == NODE_NIL ||
- nd_type(default_value) == NODE_TRUE ||
- nd_type(default_value) == NODE_FALSE) {
- COMPILE_ERROR(ERROR_ARGS "unreachable");
- goto ng;
- }
- else {
- /* if keywordcheck(_kw_bits, nth_keyword)
- * kw = default_value
- * end
- */
- int kw_bits_idx = body->local_table_size - body->param.keyword->bits_start;
- int keyword_idx = body->param.keyword->num;
-
- ADD_INSN2(ret, line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx));
- ADD_INSNL(ret, line_node, branchif, end_label);
- CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body));
- ADD_LABEL(ret, end_label);
- }
-
- break;
- }
+ CHECK(compile_kw_arg(iseq, ret, node, popped));
+ break;
case NODE_DSYM:{
- compile_dstr(iseq, ret, node);
- if (!popped) {
- ADD_INSN(ret, line_node, intern);
- }
- else {
- ADD_INSN(ret, line_node, pop);
- }
- break;
- }
- case NODE_ATTRASGN:{
- DECL_ANCHOR(recv);
- DECL_ANCHOR(args);
- unsigned int flag = 0;
- ID mid = node->nd_mid;
- VALUE argc;
- LABEL *else_label = NULL;
- VALUE branches = Qfalse;
-
- /* optimization shortcut
- * obj["literal"] = value -> opt_aset_with(obj, "literal", value)
- */
- if (mid == idASET && !private_recv_p(node) && node->nd_args &&
- nd_type(node->nd_args) == NODE_LIST && node->nd_args->nd_alen == 2 &&
- nd_type(node->nd_args->nd_head) == NODE_STR &&
- ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
- !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
- ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
- {
- VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
- CHECK(COMPILE(ret, "recv", node->nd_recv));
- CHECK(COMPILE(ret, "value", node->nd_args->nd_next->nd_head));
- if (!popped) {
- ADD_INSN(ret, line_node, swap);
- ADD_INSN1(ret, line_node, topn, INT2FIX(1));
- }
- ADD_INSN2(ret, line_node, opt_aset_with, str,
- new_callinfo(iseq, idASET, 2, 0, NULL, FALSE));
- RB_OBJ_WRITTEN(iseq, Qundef, str);
- ADD_INSN(ret, line_node, pop);
- break;
- }
-
- INIT_ANCHOR(recv);
- INIT_ANCHOR(args);
- argc = setup_args(iseq, args, node->nd_args, &flag, NULL);
- CHECK(!NIL_P(argc));
-
- int asgnflag = COMPILE_RECV(recv, "recv", node);
- CHECK(asgnflag != -1);
- flag |= (unsigned int)asgnflag;
-
- debugp_param("argc", argc);
- debugp_param("nd_mid", ID2SYM(mid));
-
- if (!rb_is_attrset_id(mid)) {
- /* safe nav attr */
- mid = rb_id_attrset(mid);
- else_label = qcall_branch_start(iseq, recv, &branches, node, line_node);
- }
- if (!popped) {
- ADD_INSN(ret, line_node, putnil);
- ADD_SEQ(ret, recv);
- ADD_SEQ(ret, args);
-
- if (flag & VM_CALL_ARGS_BLOCKARG) {
- ADD_INSN1(ret, line_node, topn, INT2FIX(1));
- if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN1(ret, line_node, putobject, INT2FIX(-1));
- ADD_SEND_WITH_FLAG(ret, line_node, idAREF, INT2FIX(1), INT2FIX(asgnflag));
- }
- ADD_INSN1(ret, line_node, setn, FIXNUM_INC(argc, 3));
- ADD_INSN (ret, line_node, pop);
- }
- else if (flag & VM_CALL_ARGS_SPLAT) {
- ADD_INSN(ret, line_node, dup);
- ADD_INSN1(ret, line_node, putobject, INT2FIX(-1));
- ADD_SEND_WITH_FLAG(ret, line_node, idAREF, INT2FIX(1), INT2FIX(asgnflag));
- ADD_INSN1(ret, line_node, setn, FIXNUM_INC(argc, 2));
- ADD_INSN (ret, line_node, pop);
- }
- else {
- ADD_INSN1(ret, line_node, setn, FIXNUM_INC(argc, 1));
- }
- }
- else {
- ADD_SEQ(ret, recv);
- ADD_SEQ(ret, args);
- }
- ADD_SEND_WITH_FLAG(ret, line_node, mid, argc, INT2FIX(flag));
- qcall_branch_end(iseq, ret, else_label, branches, node, line_node);
- ADD_INSN(ret, line_node, pop);
-
- break;
+ compile_dstr(iseq, ret, node);
+ if (!popped) {
+ ADD_INSN(ret, node, intern);
+ }
+ else {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
+ case NODE_ATTRASGN:
+ CHECK(compile_attrasgn(iseq, ret, node, popped));
+ break;
case NODE_LAMBDA:{
- /* compile same as lambda{...} */
- const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
- VALUE argc = INT2FIX(0);
+ /* compile same as lambda{...} */
+ const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
+ VALUE argc = INT2FIX(0);
- ADD_INSN1(ret, line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_CALL_WITH_BLOCK(ret, line_node, idLambda, argc, block);
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_CALL_WITH_BLOCK(ret, node, idLambda, argc, block);
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
default:
- UNKNOWN_NODE("iseq_compile_each", node, COMPILE_NG);
+ UNKNOWN_NODE("iseq_compile_each", node, COMPILE_NG);
ng:
- debug_node_end();
- return COMPILE_NG;
+ debug_node_end();
+ return COMPILE_NG;
}
debug_node_end();
@@ -9356,15 +10150,15 @@ opobj_inspect(VALUE obj)
{
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;
+ 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);
}
@@ -9377,85 +10171,92 @@ insn_data_to_s_detail(INSN *iobj)
VALUE str = rb_sprintf("%-20s ", insn_name(iobj->insn_id));
if (iobj->operands) {
- const char *types = insn_op_types(iobj->insn_id);
- int j;
-
- for (j = 0; types[j]; j++) {
- char type = types[j];
-
- switch (type) {
- case TS_OFFSET: /* label(destination position) */
- {
- LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
- rb_str_catf(str, LABEL_FORMAT, lobj->label_no);
- break;
- }
- break;
- case TS_ISEQ: /* iseq */
- {
- rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j);
- VALUE val = Qnil;
- if (0 && iseq) { /* TODO: invalidate now */
- val = (VALUE)iseq;
- }
- rb_str_concat(str, opobj_inspect(val));
- }
- break;
- case TS_LINDEX:
- case TS_NUM: /* ulong */
- case TS_VALUE: /* VALUE */
- {
- VALUE v = OPERAND_AT(iobj, j);
+ const char *types = insn_op_types(iobj->insn_id);
+ int j;
+
+ for (j = 0; types[j]; j++) {
+ char type = types[j];
+
+ switch (type) {
+ case TS_OFFSET: /* label(destination position) */
+ {
+ LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
+ rb_str_catf(str, LABEL_FORMAT, lobj->label_no);
+ break;
+ }
+ break;
+ case TS_ISEQ: /* iseq */
+ {
+ rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j);
+ VALUE val = Qnil;
+ if (0 && iseq) { /* TODO: invalidate now */
+ val = (VALUE)iseq;
+ }
+ rb_str_concat(str, opobj_inspect(val));
+ }
+ break;
+ case TS_LINDEX:
+ case TS_NUM: /* ulong */
+ case TS_VALUE: /* VALUE */
+ {
+ VALUE v = OPERAND_AT(iobj, j);
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_IC: /* inline cache */
- case TS_IVC: /* inline ivar cache */
- case TS_ISE: /* inline storage entry */
- rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j)));
- break;
+ break;
+ }
+ case TS_ID: /* ID */
+ rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j)));
+ break;
+ case TS_IC: /* inline cache */
+ rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j)));
+ break;
+ case TS_IVC: /* inline ivar cache */
+ rb_str_catf(str, "<ivc:%d>", FIX2INT(OPERAND_AT(iobj, j)));
+ break;
+ case TS_ICVARC: /* inline cvar cache */
+ rb_str_catf(str, "<icvarc:%d>", FIX2INT(OPERAND_AT(iobj, j)));
+ break;
+ case TS_ISE: /* inline storage entry */
+ rb_str_catf(str, "<ise:%d>", FIX2INT(OPERAND_AT(iobj, j)));
+ break;
case TS_CALLDATA: /* we store these as call infos at compile time */
- {
+ {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, j);
rb_str_cat2(str, "<calldata:");
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 */
- rb_str_cat2(str, "<ch>");
- break;
- case TS_FUNCPTR:
- {
- void *func = (void *)OPERAND_AT(iobj, j);
+ break;
+ }
+ case TS_CDHASH: /* case/when condition cache */
+ rb_str_cat2(str, "<ch>");
+ break;
+ case TS_FUNCPTR:
+ {
+ void *func = (void *)OPERAND_AT(iobj, j);
#ifdef HAVE_DLADDR
- Dl_info info;
- if (dladdr(func, &info) && info.dli_sname) {
- rb_str_cat2(str, info.dli_sname);
- break;
- }
+ Dl_info info;
+ if (dladdr(func, &info) && info.dli_sname) {
+ rb_str_cat2(str, info.dli_sname);
+ break;
+ }
#endif
- rb_str_catf(str, "<%p>", func);
- }
- break;
+ rb_str_catf(str, "<%p>", func);
+ }
+ break;
case TS_BUILTIN:
rb_str_cat2(str, "<TS_BUILTIN>");
break;
- default:{
- rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
- }
- }
- if (types[j + 1]) {
- rb_str_cat2(str, ", ");
- }
- }
+ default:{
+ rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
+ }
+ }
+ if (types[j + 1]) {
+ rb_str_cat2(str, ", ");
+ }
+ }
}
return str;
}
@@ -9477,40 +10278,40 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr,
printf("-- raw disasm--------\n");
while (link) {
- if (curr) printf(curr == link ? "*" : " ");
- switch (link->type) {
- case ISEQ_ELEMENT_INSN:
- {
- iobj = (INSN *)link;
- str = insn_data_to_s_detail(iobj);
- printf(" %04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->insn_info.line_no);
- pos += insn_data_length(iobj);
- break;
- }
- case ISEQ_ELEMENT_LABEL:
- {
- lobj = (LABEL *)link;
- printf(LABEL_FORMAT" [sp: %d]%s\n", lobj->label_no, lobj->sp,
- dest == lobj ? " <---" : "");
- break;
- }
- case ISEQ_ELEMENT_TRACE:
- {
- TRACE *trace = (TRACE *)link;
- 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);
- break;
- }
- default:
- /* ignore */
- rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
- }
- link = link->next;
+ if (curr) printf(curr == link ? "*" : " ");
+ switch (link->type) {
+ case ISEQ_ELEMENT_INSN:
+ {
+ iobj = (INSN *)link;
+ str = insn_data_to_s_detail(iobj);
+ printf(" %04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->insn_info.line_no);
+ pos += insn_data_length(iobj);
+ break;
+ }
+ case ISEQ_ELEMENT_LABEL:
+ {
+ lobj = (LABEL *)link;
+ printf(LABEL_FORMAT" [sp: %d]%s\n", lobj->label_no, lobj->sp,
+ dest == lobj ? " <---" : "");
+ break;
+ }
+ case ISEQ_ELEMENT_TRACE:
+ {
+ TRACE *trace = (TRACE *)link;
+ 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);
+ break;
+ }
+ default:
+ /* ignore */
+ rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
+ }
+ link = link->next;
}
printf("---------------------\n");
fflush(stdout);
@@ -9528,7 +10329,7 @@ rb_insns_name_array(void)
VALUE ary = rb_ary_new_capa(VM_INSTRUCTION_SIZE);
int i;
for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
- rb_ary_push(ary, rb_fstring_cstr(insn_name(i)));
+ rb_ary_push(ary, rb_fstring_cstr(insn_name(i)));
}
return rb_obj_freeze(ary);
}
@@ -9541,11 +10342,11 @@ register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
obj = rb_to_symbol_type(obj);
if (st_lookup(labels_table, obj, &tmp) == 0) {
- label = NEW_LABEL(0);
- st_insert(labels_table, obj, (st_data_t)label);
+ label = NEW_LABEL(0);
+ st_insert(labels_table, obj, (st_data_t)label);
}
else {
- label = (LABEL *)tmp;
+ label = (LABEL *)tmp;
}
LABEL_REF(label);
return label;
@@ -9558,12 +10359,12 @@ get_exception_sym2type(VALUE sym)
static VALUE symBreak, symRedo, symNext;
if (symRescue == 0) {
- 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"));
+ 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;
@@ -9578,25 +10379,25 @@ get_exception_sym2type(VALUE sym)
static int
iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table,
- VALUE exception)
+ VALUE exception)
{
int i;
for (i=0; i<RARRAY_LEN(exception); i++) {
- const rb_iseq_t *eiseq;
- VALUE v, type;
- LABEL *lstart, *lend, *lcont;
- unsigned int sp;
-
- v = rb_to_array_type(RARRAY_AREF(exception, i));
- if (RARRAY_LEN(v) != 6) {
- rb_raise(rb_eSyntaxError, "wrong exception entry");
- }
+ const rb_iseq_t *eiseq;
+ VALUE v, type;
+ LABEL *lstart, *lend, *lcont;
+ unsigned int sp;
+
+ v = rb_to_array_type(RARRAY_AREF(exception, i));
+ if (RARRAY_LEN(v) != 6) {
+ rb_raise(rb_eSyntaxError, "wrong exception entry");
+ }
type = get_exception_sym2type(RARRAY_AREF(v, 0));
- if (RARRAY_AREF(v, 1) == Qnil) {
- eiseq = NULL;
- }
- else {
+ if (NIL_P(RARRAY_AREF(v, 1))) {
+ eiseq = NULL;
+ }
+ else {
eiseq = rb_iseqw_to_iseq(rb_iseq_load(RARRAY_AREF(v, 1), (VALUE)iseq, Qnil));
}
@@ -9605,18 +10406,18 @@ iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table,
lcont = register_label(iseq, labels_table, RARRAY_AREF(v, 4));
sp = NUM2UINT(RARRAY_AREF(v, 5));
- /* TODO: Dirty Hack! Fix me */
- if (type == CATCH_TYPE_RESCUE ||
- type == CATCH_TYPE_BREAK ||
- type == CATCH_TYPE_NEXT) {
- ++sp;
- }
+ /* TODO: Dirty Hack! Fix me */
+ if (type == CATCH_TYPE_RESCUE ||
+ type == CATCH_TYPE_BREAK ||
+ type == CATCH_TYPE_NEXT) {
+ ++sp;
+ }
- lcont->sp = sp;
+ lcont->sp = sp;
- ADD_CATCH_ENTRY(type, lstart, lend, eiseq, lcont);
+ ADD_CATCH_ENTRY(type, lstart, lend, eiseq, lcont);
- RB_GC_GUARD(v);
+ RB_GC_GUARD(v);
}
return COMPILE_OK;
}
@@ -9629,7 +10430,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_const(insn_name(i))), i);
+ st_insert(table, ID2SYM(rb_intern_const(insn_name(i))), i);
}
return table;
@@ -9642,13 +10443,13 @@ iseq_build_load_iseq(const rb_iseq_t *iseq, VALUE op)
const rb_iseq_t *loaded_iseq;
if (RB_TYPE_P(op, T_ARRAY)) {
- iseqw = rb_iseq_load(op, (VALUE)iseq, Qnil);
+ iseqw = rb_iseq_load(op, (VALUE)iseq, Qnil);
}
else if (CLASS_OF(op) == rb_cISeq) {
- iseqw = op;
+ iseqw = op;
}
else {
- rb_raise(rb_eSyntaxError, "ISEQ is required");
+ rb_raise(rb_eSyntaxError, "ISEQ is required");
}
loaded_iseq = rb_iseqw_to_iseq(iseqw);
@@ -9664,28 +10465,28 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
struct rb_callinfo_kwarg *kw_arg = 0;
if (!NIL_P(op)) {
- 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);
- if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc);
-
- if (!NIL_P(vkw_arg)) {
- int i;
- int len = RARRAY_LENINT(vkw_arg);
- size_t n = rb_callinfo_kwarg_bytes(len);
-
- kw_arg = xmalloc(n);
- kw_arg->keyword_len = len;
- for (i = 0; i < len; i++) {
- VALUE kw = RARRAY_AREF(vkw_arg, i);
- SYM2ID(kw); /* make immortal */
- kw_arg->keywords[i] = kw;
- }
- }
+ 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);
+ if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc);
+
+ if (!NIL_P(vkw_arg)) {
+ int i;
+ int len = RARRAY_LENINT(vkw_arg);
+ size_t n = rb_callinfo_kwarg_bytes(len);
+
+ kw_arg = xmalloc(n);
+ kw_arg->keyword_len = len;
+ for (i = 0; i < len; i++) {
+ VALUE kw = RARRAY_AREF(vkw_arg, i);
+ SYM2ID(kw); /* make immortal */
+ kw_arg->keywords[i] = kw;
+ }
+ }
}
const struct rb_callinfo *ci = new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
@@ -9697,20 +10498,20 @@ static rb_event_flag_t
event_name_to_flag(VALUE sym)
{
#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);
- CHECK_EVENT(RUBY_EVENT_CALL);
- CHECK_EVENT(RUBY_EVENT_RETURN);
- CHECK_EVENT(RUBY_EVENT_B_CALL);
- CHECK_EVENT(RUBY_EVENT_B_RETURN);
+ CHECK_EVENT(RUBY_EVENT_LINE);
+ CHECK_EVENT(RUBY_EVENT_CLASS);
+ CHECK_EVENT(RUBY_EVENT_END);
+ CHECK_EVENT(RUBY_EVENT_CALL);
+ CHECK_EVENT(RUBY_EVENT_RETURN);
+ CHECK_EVENT(RUBY_EVENT_B_CALL);
+ CHECK_EVENT(RUBY_EVENT_B_RETURN);
#undef CHECK_EVENT
return RUBY_EVENT_NONE;
}
static int
iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
- VALUE body, VALUE node_ids, VALUE labels_wrapper)
+ VALUE body, VALUE node_ids, VALUE labels_wrapper)
{
/* TODO: body should be frozen */
long i, len = RARRAY_LEN(body);
@@ -9725,52 +10526,52 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
static struct st_table *insn_table;
if (insn_table == 0) {
- insn_table = insn_make_insn_table();
+ insn_table = insn_make_insn_table();
}
for (i=0; i<len; i++) {
VALUE obj = RARRAY_AREF(body, i);
- if (SYMBOL_P(obj)) {
- rb_event_flag_t event;
- if ((event = event_name_to_flag(obj)) != RUBY_EVENT_NONE) {
- ADD_TRACE(anchor, event);
- }
- else {
- LABEL *label = register_label(iseq, labels_table, obj);
- ADD_LABEL(anchor, label);
- }
- }
- else if (FIXNUM_P(obj)) {
- line_no = NUM2INT(obj);
- }
- else if (RB_TYPE_P(obj, T_ARRAY)) {
- VALUE *argv = 0;
- int argc = RARRAY_LENINT(obj) - 1;
- st_data_t insn_id;
- VALUE insn;
+ if (SYMBOL_P(obj)) {
+ rb_event_flag_t event;
+ if ((event = event_name_to_flag(obj)) != RUBY_EVENT_NONE) {
+ ADD_TRACE(anchor, event);
+ }
+ else {
+ LABEL *label = register_label(iseq, labels_table, obj);
+ ADD_LABEL(anchor, label);
+ }
+ }
+ else if (FIXNUM_P(obj)) {
+ line_no = NUM2INT(obj);
+ }
+ else if (RB_TYPE_P(obj, T_ARRAY)) {
+ VALUE *argv = 0;
+ int argc = RARRAY_LENINT(obj) - 1;
+ st_data_t insn_id;
+ VALUE insn;
if (node_ids) {
node_id = NUM2INT(rb_ary_entry(node_ids, insn_idx++));
}
- insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0);
- if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
- /* TODO: exception */
- COMPILE_ERROR(iseq, line_no,
- "unknown instruction: %+"PRIsVALUE, insn);
- ret = COMPILE_NG;
- break;
- }
+ insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0);
+ if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
+ /* TODO: exception */
+ COMPILE_ERROR(iseq, line_no,
+ "unknown instruction: %+"PRIsVALUE, insn);
+ ret = COMPILE_NG;
+ break;
+ }
- if (argc != insn_len((VALUE)insn_id)-1) {
- COMPILE_ERROR(iseq, line_no,
- "operand size mismatch");
- ret = COMPILE_NG;
- break;
- }
+ if (argc != insn_len((VALUE)insn_id)-1) {
+ COMPILE_ERROR(iseq, line_no,
+ "operand size mismatch");
+ ret = COMPILE_NG;
+ break;
+ }
- if (argc > 0) {
+ if (argc > 0) {
argv = compile_data_calloc2(iseq, sizeof(VALUE), argc);
// add element before operand setup to make GC root
@@ -9779,94 +10580,120 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
(LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node,
(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)) {
- case TS_OFFSET: {
- LABEL *label = register_label(iseq, labels_table, op);
- argv[j] = (VALUE)label;
- break;
- }
- case TS_LINDEX:
- case TS_NUM:
- (void)NUM2INT(op);
- argv[j] = op;
- break;
- case TS_VALUE:
- argv[j] = op;
- RB_OBJ_WRITTEN(iseq, Qundef, op);
- break;
- case TS_ISEQ:
- {
- if (op != Qnil) {
- VALUE v = (VALUE)iseq_build_load_iseq(iseq, op);
- argv[j] = v;
- RB_OBJ_WRITTEN(iseq, Qundef, v);
- }
- else {
- argv[j] = 0;
- }
- }
- break;
- case TS_ISE:
- case TS_IC:
+ for (j=0; j<argc; j++) {
+ VALUE op = rb_ary_entry(obj, j+1);
+ switch (insn_op_type((VALUE)insn_id, j)) {
+ case TS_OFFSET: {
+ LABEL *label = register_label(iseq, labels_table, op);
+ argv[j] = (VALUE)label;
+ break;
+ }
+ case TS_LINDEX:
+ case TS_NUM:
+ (void)NUM2INT(op);
+ argv[j] = op;
+ break;
+ case TS_VALUE:
+ argv[j] = op;
+ RB_OBJ_WRITTEN(iseq, Qundef, op);
+ break;
+ case TS_ISEQ:
+ {
+ if (op != Qnil) {
+ VALUE v = (VALUE)iseq_build_load_iseq(iseq, op);
+ argv[j] = v;
+ RB_OBJ_WRITTEN(iseq, Qundef, v);
+ }
+ else {
+ argv[j] = 0;
+ }
+ }
+ break;
+ case TS_ISE:
+ argv[j] = op;
+ if (NUM2UINT(op) >= ISEQ_BODY(iseq)->ise_size) {
+ ISEQ_BODY(iseq)->ise_size = NUM2INT(op) + 1;
+ }
+ break;
+ case TS_IC:
+ {
+ VALUE segments = rb_ary_new();
+ op = rb_to_array_type(op);
+
+ for (int i = 0; i < RARRAY_LEN(op); i++) {
+ VALUE sym = RARRAY_AREF(op, i);
+ sym = rb_to_symbol_type(sym);
+ rb_ary_push(segments, sym);
+ }
+
+ RB_GC_GUARD(op);
+ argv[j] = segments;
+ RB_OBJ_WRITTEN(iseq, Qundef, segments);
+ ISEQ_BODY(iseq)->ic_size++;
+ }
+ break;
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;
+ argv[j] = op;
+ if (NUM2UINT(op) >= ISEQ_BODY(iseq)->ivc_size) {
+ ISEQ_BODY(iseq)->ivc_size = NUM2INT(op) + 1;
+ }
+ break;
+ case TS_ICVARC: /* inline cvar cache */
+ argv[j] = op;
+ if (NUM2UINT(op) >= ISEQ_BODY(iseq)->icvarc_size) {
+ ISEQ_BODY(iseq)->icvarc_size = NUM2INT(op) + 1;
+ }
+ break;
case TS_CALLDATA:
- argv[j] = iseq_build_callinfo_from_hash(iseq, op);
- break;
- case TS_ID:
- argv[j] = rb_to_symbol_type(op);
- break;
- case TS_CDHASH:
- {
- int i;
- VALUE map = rb_hash_new_with_size(RARRAY_LEN(op)/2);
+ argv[j] = iseq_build_callinfo_from_hash(iseq, op);
+ break;
+ case TS_ID:
+ argv[j] = rb_to_symbol_type(op);
+ break;
+ case TS_CDHASH:
+ {
+ int i;
+ VALUE map = rb_hash_new_with_size(RARRAY_LEN(op)/2);
RHASH_TBL_RAW(map)->type = &cdhash_type;
- op = rb_to_array_type(op);
- for (i=0; i<RARRAY_LEN(op); i+=2) {
- VALUE key = RARRAY_AREF(op, i);
- VALUE sym = RARRAY_AREF(op, i+1);
- LABEL *label =
- register_label(iseq, labels_table, sym);
- rb_hash_aset(map, key, (VALUE)label | 1);
- }
- RB_GC_GUARD(op);
- argv[j] = map;
- RB_OBJ_WRITTEN(iseq, Qundef, map);
- }
- break;
- case TS_FUNCPTR:
- {
+ op = rb_to_array_type(op);
+ for (i=0; i<RARRAY_LEN(op); i+=2) {
+ VALUE key = RARRAY_AREF(op, i);
+ VALUE sym = RARRAY_AREF(op, i+1);
+ LABEL *label =
+ register_label(iseq, labels_table, sym);
+ rb_hash_aset(map, key, (VALUE)label | 1);
+ }
+ RB_GC_GUARD(op);
+ argv[j] = map;
+ RB_OBJ_WRITTEN(iseq, Qundef, map);
+ }
+ break;
+ case TS_FUNCPTR:
+ {
#if SIZEOF_VALUE <= SIZEOF_LONG
- long funcptr = NUM2LONG(op);
+ long funcptr = NUM2LONG(op);
#else
- LONG_LONG funcptr = NUM2LL(op);
+ LONG_LONG funcptr = NUM2LL(op);
#endif
- argv[j] = (VALUE)funcptr;
- }
- break;
- default:
- rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type((VALUE)insn_id, j));
- }
- }
- }
+ argv[j] = (VALUE)funcptr;
+ }
+ break;
+ default:
+ rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type((VALUE)insn_id, j));
+ }
+ }
+ }
else {
NODE dummy_line_node = generate_dummy_line_node(line_no, node_id);
ADD_ELEM(anchor,
(LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node,
(enum ruby_vminsn_type)insn_id, argc, NULL));
}
- }
- else {
- rb_raise(rb_eTypeError, "unexpected object for instruction");
- }
+ }
+ else {
+ rb_raise(rb_eTypeError, "unexpected object for instruction");
+ }
}
DATA_PTR(labels_wrapper) = 0;
validate_labels(iseq, labels_table);
@@ -9882,12 +10709,12 @@ int_param(int *dst, VALUE param, VALUE sym)
{
VALUE val = rb_hash_aref(param, sym);
if (FIXNUM_P(val)) {
- *dst = FIX2INT(val);
- return TRUE;
+ *dst = FIX2INT(val);
+ return TRUE;
}
else if (!NIL_P(val)) {
- rb_raise(rb_eTypeError, "invalid %+"PRIsVALUE" Fixnum: %+"PRIsVALUE,
- sym, val);
+ rb_raise(rb_eTypeError, "invalid %+"PRIsVALUE" Fixnum: %+"PRIsVALUE,
+ sym, val);
}
return FALSE;
}
@@ -9903,31 +10730,31 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
ID *ids;
struct rb_iseq_param_keyword *keyword = ZALLOC(struct rb_iseq_param_keyword);
- iseq->body->param.flags.has_kw = TRUE;
+ ISEQ_BODY(iseq)->param.flags.has_kw = TRUE;
keyword->num = len;
#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];
+ ids = (ID *)&ISEQ_BODY(iseq)->local_table[i];
#undef SYM
/* required args */
for (i = 0; i < len; i++) {
- VALUE val = RARRAY_AREF(keywords, i);
+ VALUE val = RARRAY_AREF(keywords, i);
- if (!SYMBOL_P(val)) {
- goto default_values;
- }
- ids[i] = SYM2ID(val);
- keyword->required_num++;
+ if (!SYMBOL_P(val)) {
+ goto default_values;
+ }
+ ids[i] = SYM2ID(val);
+ keyword->required_num++;
}
default_values: /* note: we intentionally preserve `i' from previous loop */
default_len = len - i;
if (default_len == 0) {
- keyword->table = ids;
- return keyword;
+ keyword->table = ids;
+ return keyword;
}
else if (default_len < 0) {
UNREACHABLE;
@@ -9936,23 +10763,23 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
dvs = ALLOC_N(VALUE, (unsigned int)default_len);
for (j = 0; i < len; i++, j++) {
- key = RARRAY_AREF(keywords, i);
- CHECK_ARRAY(key);
-
- switch (RARRAY_LEN(key)) {
- case 1:
- sym = RARRAY_AREF(key, 0);
- default_val = Qundef;
- break;
- case 2:
- sym = RARRAY_AREF(key, 0);
- default_val = RARRAY_AREF(key, 1);
- break;
- default:
- rb_raise(rb_eTypeError, "keyword default has unsupported len %+"PRIsVALUE, key);
- }
- ids[i] = SYM2ID(sym);
- dvs[j] = default_val;
+ key = RARRAY_AREF(keywords, i);
+ CHECK_ARRAY(key);
+
+ switch (RARRAY_LEN(key)) {
+ case 1:
+ sym = RARRAY_AREF(key, 0);
+ default_val = Qundef;
+ break;
+ case 2:
+ sym = RARRAY_AREF(key, 0);
+ default_val = RARRAY_AREF(key, 1);
+ break;
+ default:
+ rb_raise(rb_eTypeError, "keyword default has unsupported len %+"PRIsVALUE, key);
+ }
+ ids[i] = SYM2ID(sym);
+ dvs[j] = default_val;
}
keyword->table = ids;
@@ -9961,6 +10788,12 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
return keyword;
}
+static void
+iseq_insn_each_object_mark(VALUE *obj_ptr, VALUE _)
+{
+ rb_gc_mark(*obj_ptr);
+}
+
void
rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage)
{
@@ -9987,28 +10820,7 @@ rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage)
iobj = (INSN *)&storage->buff[pos];
if (iobj->operands) {
- int j;
- const char *types = insn_op_types(iobj->insn_id);
-
- for (j = 0; types[j]; j++) {
- char type = types[j];
- switch (type) {
- 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;
- default:
- break;
- }
- }
+ iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark, (VALUE)0);
}
pos += (int)size;
}
@@ -10017,7 +10829,7 @@ rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage)
void
rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
- VALUE exception, VALUE body)
+ VALUE exception, VALUE body)
{
#define SYM(s) ID2SYM(rb_intern_const(#s))
int i, len;
@@ -10032,35 +10844,35 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
INIT_ANCHOR(anchor);
len = RARRAY_LENINT(locals);
- iseq->body->local_table_size = len;
- iseq->body->local_table = tbl = len > 0 ? (ID *)ALLOC_N(ID, iseq->body->local_table_size) : NULL;
+ ISEQ_BODY(iseq)->local_table_size = len;
+ ISEQ_BODY(iseq)->local_table = tbl = len > 0 ? (ID *)ALLOC_N(ID, ISEQ_BODY(iseq)->local_table_size) : NULL;
for (i = 0; i < len; i++) {
- VALUE lv = RARRAY_AREF(locals, i);
+ VALUE lv = RARRAY_AREF(locals, i);
- if (sym_arg_rest == lv) {
- tbl[i] = 0;
- }
- else {
- tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv));
- }
+ if (sym_arg_rest == lv) {
+ tbl[i] = 0;
+ }
+ else {
+ tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv));
+ }
}
-#define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F))
+#define INT_PARAM(F) int_param(&ISEQ_BODY(iseq)->param.F, params, SYM(F))
if (INT_PARAM(lead_num)) {
- iseq->body->param.flags.has_lead = TRUE;
+ ISEQ_BODY(iseq)->param.flags.has_lead = TRUE;
}
- if (INT_PARAM(post_num)) iseq->body->param.flags.has_post = TRUE;
- if (INT_PARAM(post_start)) iseq->body->param.flags.has_post = TRUE;
- if (INT_PARAM(rest_start)) iseq->body->param.flags.has_rest = TRUE;
- if (INT_PARAM(block_start)) iseq->body->param.flags.has_block = TRUE;
+ if (INT_PARAM(post_num)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
+ if (INT_PARAM(post_start)) ISEQ_BODY(iseq)->param.flags.has_post = TRUE;
+ if (INT_PARAM(rest_start)) ISEQ_BODY(iseq)->param.flags.has_rest = TRUE;
+ if (INT_PARAM(block_start)) ISEQ_BODY(iseq)->param.flags.has_block = TRUE;
#undef INT_PARAM
{
#define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
- int x;
- INT_PARAM(arg_size);
- INT_PARAM(local_size);
- INT_PARAM(stack_max);
+ int x;
+ INT_PARAM(arg_size);
+ INT_PARAM(local_size);
+ INT_PARAM(stack_max);
#undef INT_PARAM
}
@@ -10068,51 +10880,51 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
#ifdef USE_ISEQ_NODE_ID
node_ids = rb_hash_aref(misc, ID2SYM(rb_intern("node_ids")));
if (!RB_TYPE_P(node_ids, T_ARRAY)) {
- rb_raise(rb_eTypeError, "node_ids is not an array");
+ rb_raise(rb_eTypeError, "node_ids is not an array");
}
#endif
if (RB_TYPE_P(arg_opt_labels, T_ARRAY)) {
- len = RARRAY_LENINT(arg_opt_labels);
- iseq->body->param.flags.has_opt = !!(len - 1 >= 0);
+ len = RARRAY_LENINT(arg_opt_labels);
+ ISEQ_BODY(iseq)->param.flags.has_opt = !!(len - 1 >= 0);
- if (iseq->body->param.flags.has_opt) {
- VALUE *opt_table = ALLOC_N(VALUE, len);
+ if (ISEQ_BODY(iseq)->param.flags.has_opt) {
+ VALUE *opt_table = ALLOC_N(VALUE, len);
- for (i = 0; i < len; i++) {
- VALUE ent = RARRAY_AREF(arg_opt_labels, i);
- LABEL *label = register_label(iseq, labels_table, ent);
- opt_table[i] = (VALUE)label;
- }
+ for (i = 0; i < len; i++) {
+ VALUE ent = RARRAY_AREF(arg_opt_labels, i);
+ LABEL *label = register_label(iseq, labels_table, ent);
+ opt_table[i] = (VALUE)label;
+ }
- iseq->body->param.opt_num = len - 1;
- iseq->body->param.opt_table = opt_table;
- }
+ ISEQ_BODY(iseq)->param.opt_num = len - 1;
+ ISEQ_BODY(iseq)->param.opt_table = opt_table;
+ }
}
else if (!NIL_P(arg_opt_labels)) {
- rb_raise(rb_eTypeError, ":opt param is not an array: %+"PRIsVALUE,
- arg_opt_labels);
+ rb_raise(rb_eTypeError, ":opt param is not an array: %+"PRIsVALUE,
+ arg_opt_labels);
}
if (RB_TYPE_P(keywords, T_ARRAY)) {
- iseq->body->param.keyword = iseq_build_kw(iseq, params, keywords);
+ ISEQ_BODY(iseq)->param.keyword = iseq_build_kw(iseq, params, keywords);
}
else if (!NIL_P(keywords)) {
- rb_raise(rb_eTypeError, ":keywords param is not an array: %+"PRIsVALUE,
- keywords);
+ rb_raise(rb_eTypeError, ":keywords param is not an array: %+"PRIsVALUE,
+ keywords);
}
if (Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) {
- iseq->body->param.flags.ambiguous_param0 = TRUE;
+ ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE;
}
if (int_param(&i, params, SYM(kwrest))) {
- struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *)iseq->body->param.keyword;
- if (keyword == NULL) {
- iseq->body->param.keyword = keyword = ZALLOC(struct rb_iseq_param_keyword);
- }
- keyword->rest_start = i;
- iseq->body->param.flags.has_kwrest = TRUE;
+ struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword;
+ if (keyword == NULL) {
+ ISEQ_BODY(iseq)->param.keyword = keyword = ZALLOC(struct rb_iseq_param_keyword);
+ }
+ keyword->rest_start = i;
+ ISEQ_BODY(iseq)->param.flags.has_kwrest = TRUE;
}
#undef SYM
iseq_calc_param_size(iseq);
@@ -10123,9 +10935,9 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
/* body */
iseq_build_from_ary_body(iseq, anchor, body, node_ids, labels_wrapper);
- iseq->body->param.size = arg_size;
- iseq->body->local_table_size = local_size;
- iseq->body->stack_max = stack_max;
+ ISEQ_BODY(iseq)->param.size = arg_size;
+ ISEQ_BODY(iseq)->local_table_size = local_size;
+ ISEQ_BODY(iseq)->stack_max = stack_max;
}
/* for parser */
@@ -10134,23 +10946,23 @@ int
rb_dvar_defined(ID id, const rb_iseq_t *iseq)
{
if (iseq) {
- const struct rb_iseq_constant_body *body = iseq->body;
- while (body->type == ISEQ_TYPE_BLOCK ||
- body->type == ISEQ_TYPE_RESCUE ||
- body->type == ISEQ_TYPE_ENSURE ||
- body->type == ISEQ_TYPE_EVAL ||
- body->type == ISEQ_TYPE_MAIN
- ) {
- unsigned int i;
-
- for (i = 0; i < body->local_table_size; i++) {
- if (body->local_table[i] == id) {
- return 1;
- }
- }
- iseq = body->parent_iseq;
- body = iseq->body;
- }
+ const struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
+ while (body->type == ISEQ_TYPE_BLOCK ||
+ body->type == ISEQ_TYPE_RESCUE ||
+ body->type == ISEQ_TYPE_ENSURE ||
+ body->type == ISEQ_TYPE_EVAL ||
+ body->type == ISEQ_TYPE_MAIN
+ ) {
+ unsigned int i;
+
+ for (i = 0; i < body->local_table_size; i++) {
+ if (body->local_table[i] == id) {
+ return 1;
+ }
+ }
+ iseq = body->parent_iseq;
+ body = ISEQ_BODY(iseq);
+ }
}
return 0;
}
@@ -10159,113 +10971,18 @@ int
rb_local_defined(ID id, const rb_iseq_t *iseq)
{
if (iseq) {
- unsigned int i;
- const struct rb_iseq_constant_body *const body = iseq->body->local_iseq->body;
+ unsigned int i;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq);
- for (i=0; i<body->local_table_size; i++) {
- if (body->local_table[i] == id) {
- return 1;
- }
- }
+ for (i=0; i<body->local_table_size; i++) {
+ if (body->local_table[i] == id) {
+ return 1;
+ }
+ }
}
return 0;
}
-static int
-caller_location(VALUE *path, VALUE *realpath)
-{
- const rb_execution_context_t *ec = GET_EC();
- const rb_control_frame_t *const cfp =
- rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
-
- if (cfp) {
- int line = rb_vm_get_sourceline(cfp);
- *path = rb_iseq_path(cfp->iseq);
- *realpath = rb_iseq_realpath(cfp->iseq);
- return line;
- }
- else {
- *path = rb_fstring_lit("<compiled>");
- *realpath = *path;
- return 1;
- }
-}
-
-typedef struct {
- VALUE arg;
- VALUE func;
- int line;
-} accessor_args;
-
-static const rb_iseq_t *
-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 = (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);
- return rb_iseq_new_with_callback(ifunc,
- rb_sym2str(name), path, realpath,
- INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0);
-}
-
-static void
-for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a)
-{
- const accessor_args *const args = (void *)a;
- const int line = args->line;
- struct rb_iseq_constant_body *const body = iseq->body;
-
- iseq_set_local_table(iseq, 0);
- body->param.lead_num = 0;
- body->param.size = 0;
-
- NODE dummy_line_node = generate_dummy_line_node(line, -1);
- ADD_INSN1(ret, &dummy_line_node, putobject, args->arg);
- ADD_INSN1(ret, &dummy_line_node, invokebuiltin, args->func);
-}
-
-static void
-for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a)
-{
- const accessor_args *const args = (void *)a;
- const int line = args->line;
- struct rb_iseq_constant_body *const body = iseq->body;
- static const ID vars[] = {1, idUScore};
-
- iseq_set_local_table(iseq, vars);
- body->param.lead_num = 1;
- body->param.size = 1;
-
- NODE dummy_line_node = generate_dummy_line_node(line, -1);
- ADD_GETLOCAL(ret, &dummy_line_node, numberof(vars)-1, 0);
- ADD_INSN1(ret, &dummy_line_node, putobject, args->arg);
- ADD_INSN1(ret, &dummy_line_node, invokebuiltin, args->func);
-}
-
-/*
- * func (index) -> (value)
- */
-const rb_iseq_t *
-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) -> (value)
- */
-const rb_iseq_t *
-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);
-}
-
/* ISeq binary format */
#ifndef IBF_ISEQ_DEBUG
@@ -10280,8 +10997,8 @@ typedef unsigned int ibf_offset_t;
#define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
-#if RUBY_DEVEL
-#define IBF_DEVEL_VERSION 2
+#ifdef RUBY_DEVEL
+#define IBF_DEVEL_VERSION 4
#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
#else
#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
@@ -10311,8 +11028,6 @@ struct ibf_dump {
struct ibf_dump_buffer *current_buffer;
};
-rb_iseq_t * iseq_alloc(void);
-
struct ibf_load_buffer {
const char *buff;
ibf_offset_t size;
@@ -10691,7 +11406,7 @@ ibf_load_builtin(const struct ibf_load *load, ibf_offset_t *offset)
static ibf_offset_t
ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const int iseq_size = body->iseq_size;
int code_index;
const VALUE *orig_code = rb_iseq_original_iseq(iseq);
@@ -10721,16 +11436,18 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
wv = (VALUE)ibf_dump_iseq(dump, (const rb_iseq_t *)op);
break;
case TS_IC:
- case TS_IVC:
+ {
+ IC ic = (IC)op;
+ VALUE arr = idlist_to_array(ic->segments);
+ wv = ibf_dump_object(dump, arr);
+ }
+ break;
case TS_ISE:
+ case TS_IVC:
+ case TS_ICVARC:
{
- unsigned int i;
- for (i=0; i<body->is_size; i++) {
- if (op == (VALUE)&body->is_entries[i]) {
- break;
- }
- }
- wv = (VALUE)i;
+ union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)op;
+ wv = is - ISEQ_IS_ENTRY_START(body, types[op_index]);
}
break;
case TS_CALLDATA:
@@ -10767,19 +11484,34 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
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_iseq_constant_body *load_body = ISEQ_BODY(iseq);
struct rb_call_data *cd_entries = load_body->call_data;
- union iseq_inline_storage_entry *is_entries = load_body->is_entries;
+ int ic_index = 0;
+
+ iseq_bits_t * mark_offset_bits;
+
+ iseq_bits_t tmp[1] = {0};
+
+ if (ISEQ_MBITS_BUFLEN(iseq_size) == 1) {
+ mark_offset_bits = tmp;
+ }
+ else {
+ mark_offset_bits = ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(iseq_size));
+ }
+ bool needs_bitmap = false;
for (code_index=0; code_index<iseq_size;) {
/* opcode */
- const VALUE insn = code[code_index++] = ibf_load_small_value(load, &reading_pos);
+ const VALUE insn = code[code_index] = ibf_load_small_value(load, &reading_pos);
const char *types = insn_op_types(insn);
int op_index;
+ code_index++;
+
/* operands */
for (op_index=0; types[op_index]; op_index++, code_index++) {
- switch (types[op_index]) {
+ const char operand_type = types[op_index];
+ switch (operand_type) {
case TS_VALUE:
{
VALUE op = ibf_load_small_value(load, &reading_pos);
@@ -10787,7 +11519,8 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
code[code_index] = v;
if (!SPECIAL_CONST_P(v)) {
RB_OBJ_WRITTEN(iseqv, Qundef, v);
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
+ ISEQ_MBITS_SET(mark_offset_bits, code_index);
+ needs_bitmap = true;
}
break;
}
@@ -10806,8 +11539,9 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
pinned_list_store(load->current_buffer->obj_list, (long)op, v);
code[code_index] = v;
+ ISEQ_MBITS_SET(mark_offset_bits, code_index);
RB_OBJ_WRITTEN(iseqv, Qundef, v);
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
+ needs_bitmap = true;
break;
}
case TS_ISEQ:
@@ -10817,18 +11551,46 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
code[code_index] = v;
if (!SPECIAL_CONST_P(v)) {
RB_OBJ_WRITTEN(iseqv, Qundef, v);
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
+ ISEQ_MBITS_SET(mark_offset_bits, code_index);
+ needs_bitmap = true;
}
break;
}
- case TS_ISE:
case TS_IC:
- case TS_IVC:
{
VALUE op = ibf_load_small_value(load, &reading_pos);
- code[code_index] = (VALUE)&is_entries[op];
+ VALUE arr = ibf_load_object(load, op);
+
+ IC ic = &ISEQ_IS_IC_ENTRY(load_body, ic_index++);
+ ic->segments = array_to_idlist(arr);
+
+ code[code_index] = (VALUE)ic;
+ }
+ break;
+ case TS_ISE:
+ case TS_ICVARC:
+ case TS_IVC:
+ {
+ unsigned int op = (unsigned int)ibf_load_small_value(load, &reading_pos);
+
+ ISE ic = ISEQ_IS_ENTRY_START(load_body, operand_type) + op;
+ code[code_index] = (VALUE)ic;
+
+ if (operand_type == TS_IVC) {
+ IVC cache = (IVC)ic;
+
+ if (insn == BIN(setinstancevariable)) {
+ ID iv_name = (ID)code[code_index - 1];
+ cache->iv_set_name = iv_name;
+ }
+ else {
+ cache->iv_set_name = 0;
+ }
+
+ vm_ic_attr_index_initialize(cache, INVALID_SHAPE_ID);
+ }
+
}
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
break;
case TS_CALLDATA:
{
@@ -10856,9 +11618,23 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
rb_raise(rb_eRuntimeError, "operand size mismatch");
}
}
+
load_body->iseq_encoded = code;
load_body->iseq_size = code_index;
+ if (ISEQ_MBITS_BUFLEN(load_body->iseq_size) == 1) {
+ load_body->mark_bits.single = mark_offset_bits[0];
+ }
+ else {
+ if (needs_bitmap) {
+ load_body->mark_bits.list = mark_offset_bits;
+ }
+ else {
+ load_body->mark_bits.list = 0;
+ ruby_xfree(mark_offset_bits);
+ }
+ }
+
assert(code_index == iseq_size);
assert(reading_pos == bytecode_offset + bytecode_size);
return code;
@@ -10867,11 +11643,11 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
static ibf_offset_t
ibf_dump_param_opt_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- int opt_num = iseq->body->param.opt_num;
+ int opt_num = ISEQ_BODY(iseq)->param.opt_num;
if (opt_num > 0) {
IBF_W_ALIGN(VALUE);
- return ibf_dump_write(dump, iseq->body->param.opt_table, sizeof(VALUE) * (opt_num + 1));
+ return ibf_dump_write(dump, ISEQ_BODY(iseq)->param.opt_table, sizeof(VALUE) * (opt_num + 1));
}
else {
return ibf_dump_pos(dump);
@@ -10894,7 +11670,7 @@ ibf_load_param_opt_table(const struct ibf_load *load, ibf_offset_t opt_table_off
static ibf_offset_t
ibf_dump_param_keyword(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- const struct rb_iseq_param_keyword *kw = iseq->body->param.keyword;
+ const struct rb_iseq_param_keyword *kw = ISEQ_BODY(iseq)->param.keyword;
if (kw) {
struct rb_iseq_param_keyword dump_kw = *kw;
@@ -10946,10 +11722,10 @@ static ibf_offset_t
ibf_dump_insns_info_body(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
ibf_offset_t offset = ibf_dump_pos(dump);
- const struct iseq_insn_info_entry *entries = iseq->body->insns_info.body;
+ const struct iseq_insn_info_entry *entries = ISEQ_BODY(iseq)->insns_info.body;
unsigned int i;
- for (i = 0; i < iseq->body->insns_info.size; i++) {
+ for (i = 0; i < ISEQ_BODY(iseq)->insns_info.size; i++) {
ibf_dump_write_small_value(dump, entries[i].line_no);
#ifdef USE_ISEQ_NODE_ID
ibf_dump_write_small_value(dump, entries[i].node_id);
@@ -11012,7 +11788,7 @@ ibf_load_insns_info_positions(const struct ibf_load *load, ibf_offset_t position
static ibf_offset_t
ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const int size = body->local_table_size;
ID *table = ALLOCA_N(ID, size);
int i;
@@ -11045,7 +11821,7 @@ ibf_load_local_table(const struct ibf_load *load, ibf_offset_t local_table_offse
static ibf_offset_t
ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- const struct iseq_catch_table *table = iseq->body->catch_table;
+ const struct iseq_catch_table *table = ISEQ_BODY(iseq)->catch_table;
if (table) {
int *iseq_indices = ALLOCA_N(int, table->size);
@@ -11084,7 +11860,7 @@ ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offse
unsigned int i;
for (i=0; i<table->size; i++) {
int iseq_index = (int)ibf_load_small_value(load, &reading_pos);
- table->entries[i].type = (enum catch_type)ibf_load_small_value(load, &reading_pos);
+ table->entries[i].type = (enum rb_catch_type)ibf_load_small_value(load, &reading_pos);
table->entries[i].start = (unsigned int)ibf_load_small_value(load, &reading_pos);
table->entries[i].end = (unsigned int)ibf_load_small_value(load, &reading_pos);
table->entries[i].cont = (unsigned int)ibf_load_small_value(load, &reading_pos);
@@ -11102,7 +11878,7 @@ ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offse
static ibf_offset_t
ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const unsigned int ci_size = body->ci_size;
const struct rb_call_data *cds = body->call_data;
@@ -11139,6 +11915,33 @@ ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq)
return offset;
}
+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);
+
+ return ID_TABLE_CONTINUE;
+}
+
+static ibf_offset_t
+ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq)
+{
+ struct rb_id_table * ovs = ISEQ_BODY(iseq)->outer_variables;
+
+ ibf_offset_t offset = ibf_dump_pos(dump);
+
+ if (ovs) {
+ ibf_dump_write_small_value(dump, (VALUE)rb_id_table_size(ovs));
+ rb_id_table_foreach(ovs, dump_outer_variable, (void *)dump);
+ }
+ else {
+ ibf_dump_write_small_value(dump, (VALUE)0);
+ }
+
+ return offset;
+}
+
/* note that we dump out rb_call_info but load back rb_call_data */
static void
ibf_load_ci_entries(const struct ibf_load *load,
@@ -11183,6 +11986,29 @@ ibf_load_ci_entries(const struct ibf_load *load,
}
}
+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;
+
+ struct rb_id_table *tbl = NULL;
+
+ size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos);
+
+ if (table_size > 0) {
+ tbl = rb_id_table_create(table_size);
+ }
+
+ for (size_t i = 0; i < table_size; i++) {
+ ID key = ibf_load_id(load, (ID)ibf_load_small_value(load, &reading_pos));
+ VALUE value = ibf_load_small_value(load, &reading_pos);
+ if (!key) key = rb_make_temporary_id(i);
+ rb_id_table_insert(tbl, key, value);
+ }
+
+ return tbl;
+}
+
static ibf_offset_t
ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
@@ -11190,7 +12016,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
unsigned int *positions;
- const struct rb_iseq_constant_body *body = iseq->body;
+ const struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
const VALUE location_pathobj_index = ibf_dump_object(dump, body->location.pathobj); /* TODO: freeze */
const VALUE location_base_label_index = ibf_dump_object(dump, body->location.base_label);
@@ -11212,16 +12038,18 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
const ibf_offset_t param_keyword_offset = ibf_dump_param_keyword(dump, iseq);
const ibf_offset_t insns_info_body_offset = ibf_dump_insns_info_body(dump, iseq);
- positions = rb_iseq_insns_info_decode_positions(iseq->body);
+ positions = rb_iseq_insns_info_decode_positions(ISEQ_BODY(iseq));
const ibf_offset_t insns_info_positions_offset = ibf_dump_insns_info_positions(dump, positions, body->insns_info.size);
ruby_xfree(positions);
const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq);
const unsigned int catch_table_size = body->catch_table ? body->catch_table->size : 0;
const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq);
- const int parent_iseq_index = ibf_dump_iseq(dump, iseq->body->parent_iseq);
- const int local_iseq_index = ibf_dump_iseq(dump, iseq->body->local_iseq);
+ const int parent_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->parent_iseq);
+ const int local_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->local_iseq);
+ const int mandatory_only_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->mandatory_only_iseq);
const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq);
+ const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
ibf_offset_t local_obj_list_offset;
@@ -11282,10 +12110,15 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(catch_table_offset));
ibf_dump_write_small_value(dump, parent_iseq_index);
ibf_dump_write_small_value(dump, local_iseq_index);
+ ibf_dump_write_small_value(dump, mandatory_only_iseq_index);
ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset));
+ ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset));
ibf_dump_write_small_value(dump, body->variable.flip_count);
ibf_dump_write_small_value(dump, body->local_table_size);
- ibf_dump_write_small_value(dump, body->is_size);
+ ibf_dump_write_small_value(dump, body->ivc_size);
+ ibf_dump_write_small_value(dump, body->icvarc_size);
+ ibf_dump_write_small_value(dump, body->ise_size);
+ ibf_dump_write_small_value(dump, body->ic_size);
ibf_dump_write_small_value(dump, body->ci_size);
ibf_dump_write_small_value(dump, body->stack_max);
ibf_dump_write_small_value(dump, body->catch_except_p);
@@ -11328,7 +12161,7 @@ ibf_load_location_str(const struct ibf_load *load, VALUE str_index)
static void
ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
{
- struct rb_iseq_constant_body *load_body = iseq->body = rb_iseq_constant_body_alloc();
+ struct rb_iseq_constant_body *load_body = ISEQ_BODY(iseq) = rb_iseq_constant_body_alloc();
ibf_offset_t reading_pos = offset;
@@ -11374,7 +12207,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
const VALUE location_pathobj_index = ibf_load_small_value(load, &reading_pos);
const VALUE location_base_label_index = ibf_load_small_value(load, &reading_pos);
const VALUE location_label_index = ibf_load_small_value(load, &reading_pos);
- const VALUE location_first_lineno = ibf_load_small_value(load, &reading_pos);
+ const int location_first_lineno = (int)ibf_load_small_value(load, &reading_pos);
const int location_node_id = (int)ibf_load_small_value(load, &reading_pos);
const int location_code_location_beg_pos_lineno = (int)ibf_load_small_value(load, &reading_pos);
const int location_code_location_beg_pos_column = (int)ibf_load_small_value(load, &reading_pos);
@@ -11388,15 +12221,56 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
const ibf_offset_t catch_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
+ const int mandatory_only_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
+ const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos);
const unsigned int local_table_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
- const unsigned int is_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
+
+ const unsigned int ivc_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
+ const unsigned int icvarc_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
+ const unsigned int ise_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
+ const unsigned int ic_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 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);
+ // setup fname and dummy frame
+ VALUE path = ibf_load_object(load, location_pathobj_index);
+ {
+ VALUE realpath = Qnil;
+
+ if (RB_TYPE_P(path, T_STRING)) {
+ realpath = path = rb_fstring(path);
+ }
+ else if (RB_TYPE_P(path, T_ARRAY)) {
+ VALUE pathobj = path;
+ if (RARRAY_LEN(pathobj) != 2) {
+ rb_raise(rb_eRuntimeError, "path object size mismatch");
+ }
+ path = rb_fstring(RARRAY_AREF(pathobj, 0));
+ realpath = RARRAY_AREF(pathobj, 1);
+ if (!NIL_P(realpath)) {
+ if (!RB_TYPE_P(realpath, T_STRING)) {
+ rb_raise(rb_eArgError, "unexpected realpath %"PRIxVALUE
+ "(%x), path=%+"PRIsVALUE,
+ realpath, TYPE(realpath), path);
+ }
+ realpath = rb_fstring(realpath);
+ }
+ }
+ else {
+ rb_raise(rb_eRuntimeError, "unexpected path object");
+ }
+ rb_iseq_pathobj_set(iseq, path, realpath);
+ }
+
+ // push dummy frame
+ rb_execution_context_t *ec = GET_EC();
+ VALUE dummy_frame = rb_vm_push_frame_fname(ec, path);
+
#undef IBF_BODY_OFFSET
load_body->type = type;
@@ -11419,13 +12293,13 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->param.post_num = param_post_num;
load_body->param.block_start = param_block_start;
load_body->local_table_size = local_table_size;
- load_body->is_size = is_size;
load_body->ci_size = ci_size;
load_body->insns_info.size = insns_info_size;
ISEQ_COVERAGE_SET(iseq, Qnil);
ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
- iseq->body->variable.flip_count = variable_flip_count;
+ load_body->variable.flip_count = variable_flip_count;
+ load_body->variable.script_lines = Qnil;
load_body->location.first_lineno = location_first_lineno;
load_body->location.node_id = location_node_id;
@@ -11436,8 +12310,13 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
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->ivc_size = ivc_size;
+ load_body->icvarc_size = icvarc_size;
+ load_body->ise_size = ise_size;
+ load_body->ic_size = ic_size;
+ load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(load_body));
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;
@@ -11447,6 +12326,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size);
load_body->parent_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)parent_iseq_index);
load_body->local_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)local_iseq_index);
+ load_body->mandatory_only_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)mandatory_only_iseq_index);
ibf_load_code(load, iseq, bytecode_offset, bytecode_size, iseq_size);
#if VM_INSN_INFO_TABLE_IMPL == 2
@@ -11459,33 +12339,6 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load->current_buffer = &load->global_buffer;
#endif
- {
- VALUE realpath = Qnil, path = ibf_load_object(load, location_pathobj_index);
- if (RB_TYPE_P(path, T_STRING)) {
- realpath = path = rb_fstring(path);
- }
- else if (RB_TYPE_P(path, T_ARRAY)) {
- VALUE pathobj = path;
- if (RARRAY_LEN(pathobj) != 2) {
- rb_raise(rb_eRuntimeError, "path object size mismatch");
- }
- path = rb_fstring(RARRAY_AREF(pathobj, 0));
- realpath = RARRAY_AREF(pathobj, 1);
- if (!NIL_P(realpath)) {
- if (!RB_TYPE_P(realpath, T_STRING)) {
- rb_raise(rb_eArgError, "unexpected realpath %"PRIxVALUE
- "(%x), path=%+"PRIsVALUE,
- realpath, TYPE(realpath), path);
- }
- realpath = rb_fstring(realpath);
- }
- }
- else {
- rb_raise(rb_eRuntimeError, "unexpected path object");
- }
- rb_iseq_pathobj_set(iseq, path, realpath);
- }
-
RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, location_base_label_index));
RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, location_label_index));
@@ -11493,6 +12346,9 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load->current_buffer = saved_buffer;
#endif
verify_call_cache(iseq);
+
+ RB_GC_GUARD(dummy_frame);
+ rb_vm_pop_frame_no_int(ec);
}
struct ibf_dump_iseq_list_arg
@@ -11516,7 +12372,7 @@ ibf_dump_iseq_list_i(st_data_t key, st_data_t val, st_data_t ptr)
static void
ibf_dump_iseq_list(struct ibf_dump *dump, struct ibf_header *header)
{
- VALUE offset_list = rb_ary_tmp_new(dump->iseq_table->num_entries);
+ VALUE offset_list = rb_ary_hidden_new(dump->iseq_table->num_entries);
struct ibf_dump_iseq_list_arg args;
args.dump = dump;
@@ -11558,6 +12414,7 @@ enum ibf_object_class_index {
IBF_OBJECT_CLASS_STANDARD_ERROR,
IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR,
IBF_OBJECT_CLASS_TYPE_ERROR,
+ IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR,
};
struct ibf_object_regexp {
@@ -11604,7 +12461,7 @@ static const void *
ibf_load_check_offset(const struct ibf_load *load, size_t offset)
{
if (offset >= load->current_buffer->size) {
- rb_raise(rb_eIndexError, "object offset out of range: %"PRIdSIZE, offset);
+ rb_raise(rb_eIndexError, "object offset out of range: %"PRIdSIZE, offset);
}
return load->current_buffer->buff + offset;
}
@@ -11647,6 +12504,9 @@ ibf_dump_object_class(struct ibf_dump *dump, VALUE obj)
else if (obj == rb_eTypeError) {
cindex = IBF_OBJECT_CLASS_TYPE_ERROR;
}
+ else if (obj == rb_eNoMatchingPatternKeyError) {
+ cindex = IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR;
+ }
else {
rb_obj_info_dump(obj);
rb_p(obj);
@@ -11662,15 +12522,17 @@ ibf_load_object_class(const struct ibf_load *load, const struct ibf_object_heade
switch (cindex) {
case IBF_OBJECT_CLASS_OBJECT:
- return rb_cObject;
+ return rb_cObject;
case IBF_OBJECT_CLASS_ARRAY:
- return rb_cArray;
+ return rb_cArray;
case IBF_OBJECT_CLASS_STANDARD_ERROR:
- return rb_eStandardError;
+ return rb_eStandardError;
case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_ERROR:
return rb_eNoMatchingPatternError;
case IBF_OBJECT_CLASS_TYPE_ERROR:
return rb_eTypeError;
+ case IBF_OBJECT_CLASS_NO_MATCHING_PATTERN_KEY_ERROR:
+ return rb_eNoMatchingPatternKeyError;
}
rb_raise(rb_eArgError, "ibf_load_object_class: unknown class (%d)", (int)cindex);
@@ -11782,7 +12644,7 @@ ibf_load_object_array(const struct ibf_load *load, const struct ibf_object_heade
const long len = (long)ibf_load_small_value(load, &reading_pos);
- VALUE ary = rb_ary_new_capa(len);
+ VALUE ary = header->internal ? rb_ary_hidden_new(len) : rb_ary_new_capa(len);
int i;
for (i=0; i<len; i++) {
@@ -11790,8 +12652,7 @@ ibf_load_object_array(const struct ibf_load *load, const struct ibf_object_heade
rb_ary_push(ary, ibf_load_object(load, index));
}
- if (header->internal) rb_obj_hide(ary);
- if (header->frozen) rb_obj_freeze(ary);
+ if (header->frozen) rb_obj_freeze(ary);
return ary;
}
@@ -11894,7 +12755,7 @@ ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_head
int sign = bignum->slen > 0;
ssize_t len = sign > 0 ? bignum->slen : -1 * bignum->slen;
VALUE obj = rb_integer_unpack(bignum->digits, len * 2, 2, 0,
- INTEGER_PACK_LITTLE_ENDIAN | (sign == 0 ? INTEGER_PACK_NEGATIVE : 0));
+ INTEGER_PACK_LITTLE_ENDIAN | (sign == 0 ? INTEGER_PACK_NEGATIVE : 0));
if (header->internal) rb_obj_hide(obj);
if (header->frozen) rb_obj_freeze(obj);
return obj;
@@ -12059,8 +12920,8 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj)
current_offset = ibf_dump_pos(dump);
if (SPECIAL_CONST_P(obj) &&
- ! (RB_TYPE_P(obj, T_SYMBOL) ||
- RB_TYPE_P(obj, T_FLOAT))) {
+ ! (SYMBOL_P(obj) ||
+ RB_FLOAT_TYPE_P(obj))) {
obj_header.special_const = TRUE;
obj_header.frozen = TRUE;
obj_header.internal = TRUE;
@@ -12178,7 +13039,7 @@ static void
ibf_dump_object_list(struct ibf_dump *dump, ibf_offset_t *obj_list_offset, unsigned int *obj_list_size)
{
st_table *obj_table = dump->current_buffer->obj_table;
- VALUE offset_list = rb_ary_tmp_new(obj_table->num_entries);
+ VALUE offset_list = rb_ary_hidden_new(obj_table->num_entries);
struct ibf_dump_object_list_arg args;
args.dump = dump;
@@ -12238,7 +13099,7 @@ ibf_dump_memsize(const void *ptr)
static const rb_data_type_t ibf_dump_type = {
"ibf_dump",
{ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
- 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
static void
@@ -12262,8 +13123,8 @@ rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
VALUE dump_obj;
VALUE str;
- if (iseq->body->parent_iseq != NULL ||
- iseq->body->local_iseq != iseq) {
+ if (ISEQ_BODY(iseq)->parent_iseq != NULL ||
+ ISEQ_BODY(iseq)->local_iseq != iseq) {
rb_raise(rb_eRuntimeError, "should be top of iseq");
}
if (RTEST(ISEQ_COVERAGE(iseq))) {
@@ -12321,8 +13182,8 @@ rb_ibf_load_iseq_complete(rb_iseq_t *iseq)
load->iseq = iseq;
#if IBF_ISEQ_DEBUG
fprintf(stderr, "rb_ibf_load_iseq_complete: index=%#x offset=%#x size=%#x\n",
- iseq->aux.loader.index, offset,
- load->header->size);
+ iseq->aux.loader.index, offset,
+ load->header->size);
#endif
ibf_load_iseq_each(load, iseq, offset);
ISEQ_COMPILE_DATA_CLEAR(iseq);
@@ -12347,37 +13208,37 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq)
#if IBF_ISEQ_DEBUG
fprintf(stderr, "ibf_load_iseq: index_iseq=%p iseq_list=%p\n",
- (void *)index_iseq, (void *)load->iseq_list);
+ (void *)index_iseq, (void *)load->iseq_list);
#endif
if (iseq_index == -1) {
- return NULL;
+ return NULL;
}
else {
- VALUE iseqv = pinned_list_fetch(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);
+ fprintf(stderr, "ibf_load_iseq: iseqv=%p\n", (void *)iseqv);
#endif
- if (iseqv) {
- return (rb_iseq_t *)iseqv;
- }
- else {
- rb_iseq_t *iseq = iseq_imemo_alloc();
+ if (iseqv) {
+ return (rb_iseq_t *)iseqv;
+ }
+ else {
+ rb_iseq_t *iseq = iseq_imemo_alloc();
#if IBF_ISEQ_DEBUG
- fprintf(stderr, "ibf_load_iseq: new iseq=%p\n", (void *)iseq);
+ fprintf(stderr, "ibf_load_iseq: new iseq=%p\n", (void *)iseq);
#endif
- FL_SET((VALUE)iseq, ISEQ_NOT_LOADED_YET);
- iseq->aux.loader.obj = load->loader_obj;
- iseq->aux.loader.index = iseq_index;
+ 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);
+ fprintf(stderr, "ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
+ (void *)iseq, (void *)load->loader_obj, iseq_index);
#endif
- pinned_list_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
- fprintf(stderr, "ibf_load_iseq: loading iseq=%p\n", (void *)iseq);
+ fprintf(stderr, "ibf_load_iseq: loading iseq=%p\n", (void *)iseq);
#endif
rb_ibf_load_iseq_complete(iseq);
#else
@@ -12387,11 +13248,11 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq)
#endif /* !USE_LAZY_LOAD */
#if IBF_ISEQ_DEBUG
- fprintf(stderr, "ibf_load_iseq: iseq=%p loaded %p\n",
- (void *)iseq, (void *)load->iseq);
+ fprintf(stderr, "ibf_load_iseq: iseq=%p loaded %p\n",
+ (void *)iseq, (void *)load->iseq);
#endif
- return iseq;
- }
+ return iseq;
+ }
}
}
@@ -12411,18 +13272,18 @@ ibf_load_setup_bytes(struct ibf_load *load, VALUE loader_obj, const char *bytes,
load->current_buffer = &load->global_buffer;
if (size < load->header->size) {
- rb_raise(rb_eRuntimeError, "broken binary format");
+ rb_raise(rb_eRuntimeError, "broken binary format");
}
if (strncmp(load->header->magic, "YARB", 4) != 0) {
- rb_raise(rb_eRuntimeError, "unknown binary format");
+ rb_raise(rb_eRuntimeError, "unknown binary format");
}
if (load->header->major_version != IBF_MAJOR_VERSION ||
- load->header->minor_version != IBF_MINOR_VERSION) {
- rb_raise(rb_eRuntimeError, "unmatched version file (%u.%u for %u.%u)",
- load->header->major_version, load->header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION);
+ load->header->minor_version != IBF_MINOR_VERSION) {
+ rb_raise(rb_eRuntimeError, "unmatched version file (%u.%u for %u.%u)",
+ load->header->major_version, load->header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION);
}
if (strcmp(load->global_buffer.buff + sizeof(struct ibf_header), RUBY_PLATFORM) != 0) {
- rb_raise(rb_eRuntimeError, "unmatched platform");
+ rb_raise(rb_eRuntimeError, "unmatched platform");
}
if (load->header->iseq_list_offset % RUBY_ALIGNOF(ibf_offset_t)) {
rb_raise(rb_eArgError, "unaligned iseq list offset: %u",
diff --git a/complex.c b/complex.c
index 09e47f8007..a227cb0a58 100644
--- a/complex.c
+++ b/complex.c
@@ -34,10 +34,6 @@
#else
static VALUE RFLOAT_0;
#endif
-#if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
- !defined(signbit)
-extern int signbit(double);
-#endif
VALUE rb_cComplex;
@@ -54,8 +50,6 @@ static ID id_abs, id_arg,
#define id_quo idQuo
#define id_fdiv idFdiv
-#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
-
#define fun1(n) \
inline static VALUE \
f_##n(VALUE x)\
@@ -103,7 +97,7 @@ inline static VALUE
f_div(VALUE x, VALUE y)
{
if (FIXNUM_P(y) && FIX2LONG(y) == 1)
- return x;
+ return x;
return rb_funcall(x, '/', 1, y);
}
@@ -158,7 +152,7 @@ f_sub(VALUE x, VALUE y)
{
if (FIXNUM_ZERO_P(y) &&
LIKELY(rb_method_basic_definition_p(CLASS_OF(x), idMINUS))) {
- return x;
+ return x;
}
return rb_funcall(x, '-', 1, y);
}
@@ -268,7 +262,7 @@ inline static VALUE
f_to_i(VALUE x)
{
if (RB_TYPE_P(x, T_STRING))
- return rb_str_to_inum(x, 10, 0);
+ return rb_str_to_inum(x, 10, 0);
return rb_funcall(x, id_to_i, 0);
}
@@ -276,7 +270,7 @@ inline static VALUE
f_to_f(VALUE x)
{
if (RB_TYPE_P(x, T_STRING))
- return DBL2NUM(rb_str_to_dbl(x, 0));
+ return DBL2NUM(rb_str_to_dbl(x, 0));
return rb_funcall(x, id_to_f, 0);
}
@@ -286,9 +280,9 @@ inline static int
f_eqeq_p(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y))
- return x == y;
+ return x == y;
else if (RB_FLOAT_TYPE_P(x) || RB_FLOAT_TYPE_P(y))
- return NUM2DBL(x) == NUM2DBL(y);
+ return NUM2DBL(x) == NUM2DBL(y);
return (int)rb_equal(x, y);
}
@@ -322,7 +316,7 @@ f_negative_p(VALUE x)
#define f_positive_p(x) (!f_negative_p(x))
-inline static int
+inline static bool
f_zero_p(VALUE x)
{
if (RB_FLOAT_TYPE_P(x)) {
@@ -335,41 +329,41 @@ f_zero_p(VALUE x)
const VALUE num = RRATIONAL(x)->num;
return FIXNUM_ZERO_P(num);
}
- return (int)rb_equal(x, ZERO);
+ return rb_equal(x, ZERO) != 0;
}
#define f_nonzero_p(x) (!f_zero_p(x))
-VALUE rb_flo_is_finite_p(VALUE num);
+static inline bool
+always_finite_type_p(VALUE x)
+{
+ if (FIXNUM_P(x)) return true;
+ if (FLONUM_P(x)) return true; /* Infinity can't be a flonum */
+ return (RB_INTEGER_TYPE_P(x) || RB_TYPE_P(x, T_RATIONAL));
+}
+
inline static int
f_finite_p(VALUE x)
{
- if (RB_INTEGER_TYPE_P(x)) {
+ if (always_finite_type_p(x)) {
return TRUE;
}
else if (RB_FLOAT_TYPE_P(x)) {
- return (int)rb_flo_is_finite_p(x);
- }
- else if (RB_TYPE_P(x, T_RATIONAL)) {
- return TRUE;
+ return isfinite(RFLOAT_VALUE(x));
}
return RTEST(rb_funcallv(x, id_finite_p, 0, 0));
}
-VALUE rb_flo_is_infinite_p(VALUE num);
-inline static VALUE
+inline static int
f_infinite_p(VALUE x)
{
- if (RB_INTEGER_TYPE_P(x)) {
- return Qnil;
+ if (always_finite_type_p(x)) {
+ return FALSE;
}
else if (RB_FLOAT_TYPE_P(x)) {
- return rb_flo_is_infinite_p(x);
+ return isinf(RFLOAT_VALUE(x));
}
- else if (RB_TYPE_P(x, T_RATIONAL)) {
- return Qnil;
- }
- return rb_funcallv(x, id_infinite_p, 0, 0);
+ return RTEST(rb_funcallv(x, id_infinite_p, 0, 0));
}
inline static int
@@ -427,15 +421,22 @@ f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
return nucomp_s_new_internal(klass, x, y);
}
-inline static void
+WARN_UNUSED_RESULT(inline static VALUE nucomp_real_check(VALUE num));
+inline static VALUE
nucomp_real_check(VALUE num)
{
if (!RB_INTEGER_TYPE_P(num) &&
- !RB_FLOAT_TYPE_P(num) &&
- !RB_TYPE_P(num, T_RATIONAL)) {
- if (!k_numeric_p(num) || !f_real_p(num))
- rb_raise(rb_eTypeError, "not a real");
+ !RB_FLOAT_TYPE_P(num) &&
+ !RB_TYPE_P(num, T_RATIONAL)) {
+ if (RB_TYPE_P(num, T_COMPLEX) && nucomp_real_p(num)) {
+ VALUE real = RCOMPLEX(num)->real;
+ assert(!RB_TYPE_P(real, T_COMPLEX));
+ return real;
+ }
+ if (!k_numeric_p(num) || !f_real_p(num))
+ rb_raise(rb_eTypeError, "not a real");
}
+ return num;
}
inline static VALUE
@@ -445,28 +446,28 @@ nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
complex_r = RB_TYPE_P(real, T_COMPLEX);
complex_i = RB_TYPE_P(imag, T_COMPLEX);
if (!complex_r && !complex_i) {
- return nucomp_s_new_internal(klass, real, imag);
+ return nucomp_s_new_internal(klass, real, imag);
}
else if (!complex_r) {
- get_dat1(imag);
+ get_dat1(imag);
- return nucomp_s_new_internal(klass,
- f_sub(real, dat->imag),
- f_add(ZERO, dat->real));
+ return nucomp_s_new_internal(klass,
+ f_sub(real, dat->imag),
+ f_add(ZERO, dat->real));
}
else if (!complex_i) {
- get_dat1(real);
+ get_dat1(real);
- return nucomp_s_new_internal(klass,
- dat->real,
- f_add(dat->imag, imag));
+ return nucomp_s_new_internal(klass,
+ dat->real,
+ f_add(dat->imag, imag));
}
else {
- get_dat2(real, imag);
+ get_dat2(real, imag);
- return nucomp_s_new_internal(klass,
- f_sub(adat->real, bdat->imag),
- f_add(adat->imag, bdat->real));
+ return nucomp_s_new_internal(klass,
+ f_sub(adat->real, bdat->imag),
+ f_add(adat->imag, bdat->real));
}
}
@@ -486,22 +487,26 @@ nucomp_s_new(int argc, VALUE *argv, VALUE klass)
switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
- nucomp_real_check(real);
- imag = ZERO;
- break;
+ real = nucomp_real_check(real);
+ imag = ZERO;
+ break;
default:
- nucomp_real_check(real);
- nucomp_real_check(imag);
- break;
+ real = nucomp_real_check(real);
+ imag = nucomp_real_check(imag);
+ break;
}
- return nucomp_s_canonicalize_internal(klass, real, imag);
+ return nucomp_s_new_internal(klass, real, imag);
}
inline static VALUE
f_complex_new2(VALUE klass, VALUE x, VALUE y)
{
- assert(!RB_TYPE_P(x, T_COMPLEX));
+ if (RB_TYPE_P(x, T_COMPLEX)) {
+ get_dat1(x);
+ x = dat->real;
+ y = f_add(dat->imag, y);
+ }
return nucomp_s_canonicalize_internal(klass, x, y);
}
@@ -556,7 +561,7 @@ nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
if (!NIL_P(opts)) {
raise = rb_opts_exception_p(opts, raise);
}
- if (argc > 0 && CLASS_OF(a1) == rb_cComplex && a2 == Qundef) {
+ if (argc > 0 && CLASS_OF(a1) == rb_cComplex && UNDEF_P(a2)) {
return a1;
}
return nucomp_convert(rb_cComplex, a1, a2, raise);
@@ -586,14 +591,14 @@ static VALUE
m_cos(VALUE x)
{
if (!RB_TYPE_P(x, T_COMPLEX))
- return m_cos_bang(x);
+ return m_cos_bang(x);
{
- get_dat1(x);
- return f_complex_new2(rb_cComplex,
- f_mul(m_cos_bang(dat->real),
- m_cosh_bang(dat->imag)),
- f_mul(f_negate(m_sin_bang(dat->real)),
- m_sinh_bang(dat->imag)));
+ get_dat1(x);
+ return f_complex_new2(rb_cComplex,
+ f_mul(m_cos_bang(dat->real),
+ m_cosh_bang(dat->imag)),
+ f_mul(f_negate(m_sin_bang(dat->real)),
+ m_sinh_bang(dat->imag)));
}
}
@@ -601,55 +606,61 @@ static VALUE
m_sin(VALUE x)
{
if (!RB_TYPE_P(x, T_COMPLEX))
- return m_sin_bang(x);
+ return m_sin_bang(x);
{
- get_dat1(x);
- return f_complex_new2(rb_cComplex,
- f_mul(m_sin_bang(dat->real),
- m_cosh_bang(dat->imag)),
- f_mul(m_cos_bang(dat->real),
- m_sinh_bang(dat->imag)));
+ get_dat1(x);
+ return f_complex_new2(rb_cComplex,
+ f_mul(m_sin_bang(dat->real),
+ m_cosh_bang(dat->imag)),
+ f_mul(m_cos_bang(dat->real),
+ m_sinh_bang(dat->imag)));
}
}
static VALUE
-f_complex_polar(VALUE klass, VALUE x, VALUE y)
+f_complex_polar_real(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)) {
- return nucomp_s_new_internal(klass, x, RFLOAT_0);
+ 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);
- y = RFLOAT_0;
- }
- else if (arg == M_PI_2) {
- y = x;
- x = RFLOAT_0;
- }
- else if (arg == M_PI_2+M_PI) {
- y = f_negate(x);
- x = RFLOAT_0;
- }
- else if (RB_FLOAT_TYPE_P(x)) {
- const double abs = RFLOAT_VALUE(x);
- const double real = abs * cos(arg), imag = abs * sin(arg);
- x = DBL2NUM(real);
- y = DBL2NUM(imag);
- }
- else {
+ const double arg = RFLOAT_VALUE(y);
+ if (arg == M_PI) {
+ x = f_negate(x);
+ y = RFLOAT_0;
+ }
+ else if (arg == M_PI_2) {
+ y = x;
+ x = RFLOAT_0;
+ }
+ else if (arg == M_PI_2+M_PI) {
+ y = f_negate(x);
+ x = RFLOAT_0;
+ }
+ else if (RB_FLOAT_TYPE_P(x)) {
+ const double abs = RFLOAT_VALUE(x);
+ const double real = abs * cos(arg), imag = abs * sin(arg);
+ x = DBL2NUM(real);
+ y = DBL2NUM(imag);
+ }
+ else {
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);
+ }
+ return nucomp_s_new_internal(klass, x, y);
}
return nucomp_s_canonicalize_internal(klass,
- f_mul(x, m_cos(y)),
- f_mul(x, m_sin(y)));
+ f_mul(x, m_cos(y)),
+ f_mul(x, m_sin(y)));
+}
+
+static VALUE
+f_complex_polar(VALUE klass, VALUE x, VALUE y)
+{
+ x = nucomp_real_check(x);
+ y = nucomp_real_check(y);
+ return f_complex_polar_real(klass, x, y);
}
#ifdef HAVE___COSPI
@@ -671,12 +682,12 @@ rb_dbl_complex_new_polar_pi(double abs, double ang)
int pos = fr == +0.5;
if (pos || fr == -0.5) {
- if ((modf(fi / 2.0, &fi) != fr) ^ pos) abs = -abs;
- return rb_complex_new(RFLOAT_0, DBL2NUM(abs));
+ if ((modf(fi / 2.0, &fi) != fr) ^ pos) abs = -abs;
+ return rb_complex_new(RFLOAT_0, DBL2NUM(abs));
}
else if (fr == 0.0) {
- if (modf(fi / 2.0, &fi) != 0.0) abs = -abs;
- return DBL2NUM(abs);
+ if (modf(fi / 2.0, &fi) != 0.0) abs = -abs;
+ return DBL2NUM(abs);
}
else {
const double real = abs * cospi(ang), imag = abs * sinpi(ang);
@@ -700,24 +711,15 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
{
VALUE abs, arg;
- switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
- case 1:
- nucomp_real_check(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;
+ argc = rb_scan_args(argc, argv, "11", &abs, &arg);
+ abs = nucomp_real_check(abs);
+ if (argc == 2) {
+ arg = nucomp_real_check(arg);
}
- if (RB_TYPE_P(arg, T_COMPLEX)) {
- get_dat1(arg);
- arg = dat->real;
+ else {
+ arg = ZERO;
}
- return f_complex_polar(klass, abs, arg);
+ return f_complex_polar_real(klass, abs, arg);
}
/*
@@ -766,7 +768,7 @@ rb_complex_uminus(VALUE self)
{
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
- f_negate(dat->real), f_negate(dat->imag));
+ f_negate(dat->real), f_negate(dat->imag));
}
/*
@@ -785,20 +787,20 @@ VALUE
rb_complex_plus(VALUE self, VALUE other)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
- VALUE real, imag;
+ VALUE real, imag;
- get_dat2(self, other);
+ get_dat2(self, other);
- real = f_add(adat->real, bdat->real);
- imag = f_add(adat->imag, bdat->imag);
+ real = f_add(adat->real, bdat->real);
+ imag = f_add(adat->imag, bdat->imag);
- return f_complex_new2(CLASS_OF(self), real, imag);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
- get_dat1(self);
+ get_dat1(self);
- return f_complex_new2(CLASS_OF(self),
- f_add(dat->real, other), dat->imag);
+ return f_complex_new2(CLASS_OF(self),
+ f_add(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '+');
}
@@ -819,33 +821,33 @@ VALUE
rb_complex_minus(VALUE self, VALUE other)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
- VALUE real, imag;
+ VALUE real, imag;
- get_dat2(self, other);
+ get_dat2(self, other);
- real = f_sub(adat->real, bdat->real);
- imag = f_sub(adat->imag, bdat->imag);
+ real = f_sub(adat->real, bdat->real);
+ imag = f_sub(adat->imag, bdat->imag);
- return f_complex_new2(CLASS_OF(self), real, imag);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
- get_dat1(self);
+ get_dat1(self);
- return f_complex_new2(CLASS_OF(self),
- f_sub(dat->real, other), dat->imag);
+ return f_complex_new2(CLASS_OF(self),
+ f_sub(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '-');
}
static VALUE
-safe_mul(VALUE a, VALUE b, int az, int bz)
+safe_mul(VALUE a, VALUE b, bool az, bool bz)
{
double v;
if (!az && bz && RB_FLOAT_TYPE_P(a) && (v = RFLOAT_VALUE(a), !isnan(v))) {
- a = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
+ a = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
}
if (!bz && az && RB_FLOAT_TYPE_P(b) && (v = RFLOAT_VALUE(b), !isnan(v))) {
- b = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
+ b = signbit(v) ? DBL2NUM(-1.0) : DBL2NUM(1.0);
}
return f_mul(a, b);
}
@@ -853,10 +855,10 @@ safe_mul(VALUE a, VALUE b, int az, int bz)
static void
comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE *imag)
{
- int arzero = f_zero_p(areal);
- int aizero = f_zero_p(aimag);
- int brzero = f_zero_p(breal);
- int bizero = f_zero_p(bimag);
+ bool arzero = f_zero_p(areal);
+ bool aizero = f_zero_p(aimag);
+ bool brzero = f_zero_p(breal);
+ bool bizero = f_zero_p(bimag);
*real = f_sub(safe_mul(areal, breal, arzero, brzero),
safe_mul(aimag, bimag, aizero, bizero));
*imag = f_add(safe_mul(areal, bimag, arzero, bizero),
@@ -879,47 +881,47 @@ VALUE
rb_complex_mul(VALUE self, VALUE other)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
- VALUE real, imag;
- get_dat2(self, other);
+ VALUE real, imag;
+ get_dat2(self, other);
comp_mul(adat->real, adat->imag, bdat->real, bdat->imag, &real, &imag);
- return f_complex_new2(CLASS_OF(self), real, imag);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
- get_dat1(self);
+ get_dat1(self);
- return f_complex_new2(CLASS_OF(self),
- f_mul(dat->real, other),
- f_mul(dat->imag, other));
+ return f_complex_new2(CLASS_OF(self),
+ f_mul(dat->real, other),
+ f_mul(dat->imag, other));
}
return rb_num_coerce_bin(self, other, '*');
}
inline static VALUE
f_divide(VALUE self, VALUE other,
- VALUE (*func)(VALUE, VALUE), ID id)
+ VALUE (*func)(VALUE, VALUE), ID id)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
VALUE r, n, x, y;
- int flo;
- get_dat2(self, other);
+ int flo;
+ get_dat2(self, other);
- flo = (RB_FLOAT_TYPE_P(adat->real) || RB_FLOAT_TYPE_P(adat->imag) ||
- RB_FLOAT_TYPE_P(bdat->real) || RB_FLOAT_TYPE_P(bdat->imag));
+ flo = (RB_FLOAT_TYPE_P(adat->real) || RB_FLOAT_TYPE_P(adat->imag) ||
+ RB_FLOAT_TYPE_P(bdat->real) || RB_FLOAT_TYPE_P(bdat->imag));
- if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
- r = (*func)(bdat->imag, bdat->real);
- n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
+ if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
+ r = (*func)(bdat->imag, bdat->real);
+ n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
x = (*func)(f_add(adat->real, f_mul(adat->imag, r)), n);
y = (*func)(f_sub(adat->imag, f_mul(adat->real, r)), n);
- }
- else {
- r = (*func)(bdat->real, bdat->imag);
- n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
+ }
+ else {
+ r = (*func)(bdat->real, bdat->imag);
+ n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
x = (*func)(f_add(f_mul(adat->real, r), adat->imag), n);
y = (*func)(f_sub(f_mul(adat->imag, r), adat->real), n);
- }
+ }
if (!flo) {
x = rb_rational_canonicalize(x);
y = rb_rational_canonicalize(y);
@@ -928,7 +930,7 @@ f_divide(VALUE self, VALUE other,
}
if (k_numeric_p(other) && f_real_p(other)) {
VALUE x, y;
- get_dat1(self);
+ get_dat1(self);
x = rb_rational_canonicalize((*func)(dat->real, other));
y = rb_rational_canonicalize((*func)(dat->imag, other));
return f_complex_new2(CLASS_OF(self), x, y);
@@ -992,31 +994,31 @@ VALUE
rb_complex_pow(VALUE self, VALUE other)
{
if (k_numeric_p(other) && k_exact_zero_p(other))
- return f_complex_new_bang1(CLASS_OF(self), ONE);
+ return f_complex_new_bang1(CLASS_OF(self), ONE);
if (RB_TYPE_P(other, T_RATIONAL) && RRATIONAL(other)->den == LONG2FIX(1))
- other = RRATIONAL(other)->num; /* c14n */
+ other = RRATIONAL(other)->num; /* c14n */
if (RB_TYPE_P(other, T_COMPLEX)) {
- get_dat1(other);
+ get_dat1(other);
- if (k_exact_zero_p(dat->imag))
- other = dat->real; /* c14n */
+ if (k_exact_zero_p(dat->imag))
+ other = dat->real; /* c14n */
}
if (RB_TYPE_P(other, T_COMPLEX)) {
- VALUE r, theta, nr, ntheta;
+ VALUE r, theta, nr, ntheta;
- get_dat1(other);
+ get_dat1(other);
- r = f_abs(self);
- theta = f_arg(self);
+ r = f_abs(self);
+ theta = f_arg(self);
- nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
- f_mul(dat->imag, theta)));
- ntheta = f_add(f_mul(theta, dat->real),
- f_mul(dat->imag, m_log_bang(r)));
- return f_complex_polar(CLASS_OF(self), nr, ntheta);
+ nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
+ f_mul(dat->imag, theta)));
+ ntheta = f_add(f_mul(theta, dat->real),
+ f_mul(dat->imag, m_log_bang(r)));
+ return f_complex_polar(CLASS_OF(self), nr, ntheta);
}
if (FIXNUM_P(other)) {
long n = FIX2LONG(other);
@@ -1057,19 +1059,19 @@ rb_complex_pow(VALUE self, VALUE other)
}
}
return nucomp_s_new_internal(CLASS_OF(self), zr, zi);
- }
+ }
}
if (k_numeric_p(other) && f_real_p(other)) {
- VALUE r, theta;
+ VALUE r, theta;
- if (RB_TYPE_P(other, T_BIGNUM))
- rb_warn("in a**b, b may be too big");
+ if (RB_BIGNUM_TYPE_P(other))
+ rb_warn("in a**b, b may be too big");
- r = f_abs(self);
- theta = f_arg(self);
+ r = f_abs(self);
+ theta = f_arg(self);
- return f_complex_polar(CLASS_OF(self), f_expt(r, other),
- f_mul(theta, other));
+ return f_complex_polar(CLASS_OF(self), f_expt(r, other),
+ f_mul(theta, other));
}
return rb_num_coerce_bin(self, other, id_expt);
}
@@ -1090,24 +1092,24 @@ static VALUE
nucomp_eqeq_p(VALUE self, VALUE other)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
- get_dat2(self, other);
+ get_dat2(self, other);
- return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
- f_eqeq_p(adat->imag, bdat->imag));
+ return RBOOL(f_eqeq_p(adat->real, bdat->real) &&
+ f_eqeq_p(adat->imag, bdat->imag));
}
if (k_numeric_p(other) && f_real_p(other)) {
- get_dat1(self);
+ get_dat1(self);
- return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
+ return RBOOL(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
}
- return f_boolcast(f_eqeq_p(other, self));
+ return RBOOL(f_eqeq_p(other, self));
}
static bool
nucomp_real_p(VALUE self)
{
get_dat1(self);
- return(f_zero_p(dat->imag) ? true : false);
+ return f_zero_p(dat->imag);
}
/*
@@ -1127,15 +1129,26 @@ nucomp_real_p(VALUE self)
static VALUE
nucomp_cmp(VALUE self, VALUE other)
{
- if (nucomp_real_p(self) && k_numeric_p(other)) {
- if (RB_TYPE_P(other, T_COMPLEX) && nucomp_real_p(other)) {
+ if (!k_numeric_p(other)) {
+ return rb_num_coerce_cmp(self, other, idCmp);
+ }
+ if (!nucomp_real_p(self)) {
+ return Qnil;
+ }
+ if (RB_TYPE_P(other, T_COMPLEX)) {
+ if (nucomp_real_p(other)) {
get_dat2(self, other);
return rb_funcall(adat->real, idCmp, 1, bdat->real);
}
- else if (f_real_p(other)) {
- get_dat1(self);
+ }
+ else {
+ get_dat1(self);
+ if (f_real_p(other)) {
return rb_funcall(dat->real, idCmp, 1, other);
}
+ else {
+ return rb_num_coerce_cmp(dat->real, other, idCmp);
+ }
}
return Qnil;
}
@@ -1145,12 +1158,12 @@ static VALUE
nucomp_coerce(VALUE self, VALUE other)
{
if (RB_TYPE_P(other, T_COMPLEX))
- return rb_assoc_new(other, self);
+ return rb_assoc_new(other, self);
if (k_numeric_p(other) && f_real_p(other))
return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
- rb_obj_class(other), rb_obj_class(self));
+ rb_obj_class(other), rb_obj_class(self));
return Qnil;
}
@@ -1170,16 +1183,16 @@ rb_complex_abs(VALUE self)
get_dat1(self);
if (f_zero_p(dat->real)) {
- VALUE a = f_abs(dat->imag);
- if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag))
- a = f_to_f(a);
- return a;
+ VALUE a = f_abs(dat->imag);
+ if (RB_FLOAT_TYPE_P(dat->real) && !RB_FLOAT_TYPE_P(dat->imag))
+ a = f_to_f(a);
+ return a;
}
if (f_zero_p(dat->imag)) {
- VALUE a = f_abs(dat->real);
- if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag))
- a = f_to_f(a);
- return a;
+ VALUE a = f_abs(dat->real);
+ if (!RB_FLOAT_TYPE_P(dat->real) && RB_FLOAT_TYPE_P(dat->imag))
+ a = f_to_f(a);
+ return a;
}
return rb_math_hypot(dat->real, dat->imag);
}
@@ -1198,7 +1211,7 @@ nucomp_abs2(VALUE self)
{
get_dat1(self);
return f_add(f_mul(dat->real, dat->real),
- f_mul(dat->imag, dat->imag));
+ f_mul(dat->imag, dat->imag));
}
/*
@@ -1319,10 +1332,10 @@ nucomp_numerator(VALUE self)
cd = nucomp_denominator(self);
return f_complex_new2(CLASS_OF(self),
- f_mul(f_numerator(dat->real),
- f_div(cd, f_denominator(dat->real))),
- f_mul(f_numerator(dat->imag),
- f_div(cd, f_denominator(dat->imag))));
+ f_mul(f_numerator(dat->real),
+ f_div(cd, f_denominator(dat->real))),
+ f_mul(f_numerator(dat->imag),
+ f_div(cd, f_denominator(dat->imag))));
}
/* :nodoc: */
@@ -1352,11 +1365,11 @@ static VALUE
nucomp_eql_p(VALUE self, VALUE other)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
- get_dat2(self, other);
+ get_dat2(self, other);
- return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
- (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
- f_eqeq_p(self, other));
+ return RBOOL((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
+ (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
+ f_eqeq_p(self, other));
}
return Qfalse;
@@ -1366,8 +1379,8 @@ inline static int
f_signbit(VALUE x)
{
if (RB_FLOAT_TYPE_P(x)) {
- double f = RFLOAT_VALUE(x);
- return !isnan(f) && signbit(f);
+ double f = RFLOAT_VALUE(x);
+ return !isnan(f) && signbit(f);
}
return f_negative_p(x);
}
@@ -1393,7 +1406,7 @@ f_format(VALUE self, VALUE (*func)(VALUE))
rb_str_concat(s, (*func)(f_abs(dat->imag)));
if (!rb_isdigit(RSTRING_PTR(s)[RSTRING_LEN(s) - 1]))
- rb_str_cat2(s, "*");
+ rb_str_cat2(s, "*");
rb_str_cat2(s, "i");
return s;
@@ -1455,10 +1468,7 @@ rb_complex_finite_p(VALUE self)
{
get_dat1(self);
- if (f_finite_p(dat->real) && f_finite_p(dat->imag)) {
- return Qtrue;
- }
- return Qfalse;
+ return RBOOL(f_finite_p(dat->real) && f_finite_p(dat->imag));
}
/*
@@ -1478,8 +1488,8 @@ rb_complex_infinite_p(VALUE self)
{
get_dat1(self);
- if (NIL_P(f_infinite_p(dat->real)) && NIL_P(f_infinite_p(dat->imag))) {
- return Qnil;
+ if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) {
+ return Qnil;
}
return ONE;
}
@@ -1522,14 +1532,12 @@ nucomp_marshal_load(VALUE self, VALUE a)
{
Check_Type(a, T_ARRAY);
if (RARRAY_LEN(a) != 2)
- rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
+ rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
rb_ivar_set(self, id_i_real, RARRAY_AREF(a, 0));
rb_ivar_set(self, id_i_imag, RARRAY_AREF(a, 1));
return self;
}
-/* --- */
-
VALUE
rb_complex_raw(VALUE x, VALUE y)
{
@@ -1563,13 +1571,6 @@ rb_Complex(VALUE x, VALUE y)
return nucomp_s_convert(2, a, rb_cComplex);
}
-/*!
- * Creates a Complex object.
- *
- * \param real real part value
- * \param imag imaginary part value
- * \return a new Complex object
- */
VALUE
rb_dbl_complex_new(double real, double imag)
{
@@ -1593,8 +1594,8 @@ nucomp_to_i(VALUE self)
get_dat1(self);
if (!k_exact_zero_p(dat->imag)) {
- rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer",
- self);
+ rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Integer",
+ self);
}
return f_to_i(dat->real);
}
@@ -1616,8 +1617,8 @@ nucomp_to_f(VALUE self)
get_dat1(self);
if (!k_exact_zero_p(dat->imag)) {
- rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float",
- self);
+ rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float",
+ self);
}
return f_to_f(dat->real);
}
@@ -1641,8 +1642,8 @@ nucomp_to_r(VALUE self)
get_dat1(self);
if (!k_exact_zero_p(dat->imag)) {
- rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
- self);
+ rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational",
+ self);
}
return f_to_r(dat->real);
}
@@ -1721,14 +1722,14 @@ issign(int c)
static int
read_sign(const char **s,
- char **b)
+ char **b)
{
int sign = '?';
if (issign(**s)) {
- sign = **b = **s;
- (*s)++;
- (*b)++;
+ sign = **b = **s;
+ (*s)++;
+ (*b)++;
}
return sign;
}
@@ -1741,32 +1742,32 @@ isdecimal(int c)
static int
read_digits(const char **s, int strict,
- char **b)
+ char **b)
{
int us = 1;
if (!isdecimal(**s))
- return 0;
+ return 0;
while (isdecimal(**s) || **s == '_') {
- if (**s == '_') {
- if (strict) {
- if (us)
- return 0;
- }
- us = 1;
- }
- else {
- **b = **s;
- (*b)++;
- us = 0;
- }
- (*s)++;
+ if (**s == '_') {
+ if (us) {
+ if (strict) return 0;
+ break;
+ }
+ us = 1;
+ }
+ else {
+ **b = **s;
+ (*b)++;
+ us = 0;
+ }
+ (*s)++;
}
if (us)
- do {
- (*s)--;
- } while (**s == '_');
+ do {
+ (*s)--;
+ } while (**s == '_');
return 1;
}
@@ -1778,70 +1779,70 @@ islettere(int c)
static int
read_num(const char **s, int strict,
- char **b)
+ char **b)
{
if (**s != '.') {
- if (!read_digits(s, strict, b))
- return 0;
+ if (!read_digits(s, strict, b))
+ return 0;
}
if (**s == '.') {
- **b = **s;
- (*s)++;
- (*b)++;
- if (!read_digits(s, strict, b)) {
- (*b)--;
- return 0;
- }
+ **b = **s;
+ (*s)++;
+ (*b)++;
+ if (!read_digits(s, strict, b)) {
+ (*b)--;
+ return 0;
+ }
}
if (islettere(**s)) {
- **b = **s;
- (*s)++;
- (*b)++;
- read_sign(s, b);
- if (!read_digits(s, strict, b)) {
- (*b)--;
- return 0;
- }
+ **b = **s;
+ (*s)++;
+ (*b)++;
+ read_sign(s, b);
+ if (!read_digits(s, strict, b)) {
+ (*b)--;
+ return 0;
+ }
}
return 1;
}
inline static int
read_den(const char **s, int strict,
- char **b)
+ char **b)
{
if (!read_digits(s, strict, b))
- return 0;
+ return 0;
return 1;
}
static int
read_rat_nos(const char **s, int strict,
- char **b)
+ char **b)
{
if (!read_num(s, strict, b))
- return 0;
+ return 0;
if (**s == '/') {
- **b = **s;
- (*s)++;
- (*b)++;
- if (!read_den(s, strict, b)) {
- (*b)--;
- return 0;
- }
+ **b = **s;
+ (*s)++;
+ (*b)++;
+ if (!read_den(s, strict, b)) {
+ (*b)--;
+ return 0;
+ }
}
return 1;
}
static int
read_rat(const char **s, int strict,
- char **b)
+ char **b)
{
read_sign(s, b);
if (!read_rat_nos(s, strict, b))
- return 0;
+ return 0;
return 1;
}
@@ -1849,22 +1850,22 @@ inline static int
isimagunit(int c)
{
return (c == 'i' || c == 'I' ||
- c == 'j' || c == 'J');
+ c == 'j' || c == 'J');
}
static VALUE
str2num(char *s)
{
if (strchr(s, '/'))
- return rb_cstr_to_rat(s, 0);
+ return rb_cstr_to_rat(s, 0);
if (strpbrk(s, ".eE"))
- return DBL2NUM(rb_cstr_to_dbl(s, 0));
+ return DBL2NUM(rb_cstr_to_dbl(s, 0));
return rb_cstr_to_inum(s, 10, 0);
}
static int
read_comp(const char **s, int strict,
- VALUE *ret, char **b)
+ VALUE *ret, char **b)
{
char *bb;
int sign;
@@ -1875,72 +1876,72 @@ read_comp(const char **s, int strict,
sign = read_sign(s, b);
if (isimagunit(**s)) {
- (*s)++;
- num = INT2FIX((sign == '-') ? -1 : + 1);
- *ret = rb_complex_new2(ZERO, num);
- return 1; /* e.g. "i" */
+ (*s)++;
+ num = INT2FIX((sign == '-') ? -1 : + 1);
+ *ret = rb_complex_new2(ZERO, num);
+ return 1; /* e.g. "i" */
}
if (!read_rat_nos(s, strict, b)) {
- **b = '\0';
- num = str2num(bb);
- *ret = rb_complex_new2(num, ZERO);
- return 0; /* e.g. "-" */
+ **b = '\0';
+ num = str2num(bb);
+ *ret = rb_complex_new2(num, ZERO);
+ return 0; /* e.g. "-" */
}
**b = '\0';
num = str2num(bb);
if (isimagunit(**s)) {
- (*s)++;
- *ret = rb_complex_new2(ZERO, num);
- return 1; /* e.g. "3i" */
+ (*s)++;
+ *ret = rb_complex_new2(ZERO, num);
+ return 1; /* e.g. "3i" */
}
if (**s == '@') {
- int st;
-
- (*s)++;
- bb = *b;
- st = read_rat(s, strict, b);
- **b = '\0';
- if (strlen(bb) < 1 ||
- !isdecimal(*(bb + strlen(bb) - 1))) {
- *ret = rb_complex_new2(num, ZERO);
- return 0; /* e.g. "1@-" */
- }
- num2 = str2num(bb);
- *ret = rb_complex_new_polar(num, num2);
- if (!st)
- return 0; /* e.g. "1@2." */
- else
- return 1; /* e.g. "1@2" */
+ int st;
+
+ (*s)++;
+ bb = *b;
+ st = read_rat(s, strict, b);
+ **b = '\0';
+ if (strlen(bb) < 1 ||
+ !isdecimal(*(bb + strlen(bb) - 1))) {
+ *ret = rb_complex_new2(num, ZERO);
+ return 0; /* e.g. "1@-" */
+ }
+ num2 = str2num(bb);
+ *ret = rb_complex_new_polar(num, num2);
+ if (!st)
+ return 0; /* e.g. "1@2." */
+ else
+ return 1; /* e.g. "1@2" */
}
if (issign(**s)) {
- bb = *b;
- sign = read_sign(s, b);
- if (isimagunit(**s))
- num2 = INT2FIX((sign == '-') ? -1 : + 1);
- else {
- if (!read_rat_nos(s, strict, b)) {
- *ret = rb_complex_new2(num, ZERO);
- return 0; /* e.g. "1+xi" */
- }
- **b = '\0';
- num2 = str2num(bb);
- }
- if (!isimagunit(**s)) {
- *ret = rb_complex_new2(num, ZERO);
- return 0; /* e.g. "1+3x" */
- }
- (*s)++;
- *ret = rb_complex_new2(num, num2);
- return 1; /* e.g. "1+2i" */
+ bb = *b;
+ sign = read_sign(s, b);
+ if (isimagunit(**s))
+ num2 = INT2FIX((sign == '-') ? -1 : + 1);
+ else {
+ if (!read_rat_nos(s, strict, b)) {
+ *ret = rb_complex_new2(num, ZERO);
+ return 0; /* e.g. "1+xi" */
+ }
+ **b = '\0';
+ num2 = str2num(bb);
+ }
+ if (!isimagunit(**s)) {
+ *ret = rb_complex_new2(num, ZERO);
+ return 0; /* e.g. "1+3x" */
+ }
+ (*s)++;
+ *ret = rb_complex_new2(num, num2);
+ return 1; /* e.g. "1+2i" */
}
/* !(@, - or +) */
{
- *ret = rb_complex_new2(num, ZERO);
- return 1; /* e.g. "3" */
+ *ret = rb_complex_new2(num, ZERO);
+ return 1; /* e.g. "3" */
}
}
@@ -1948,7 +1949,7 @@ inline static void
skip_ws(const char **s)
{
while (isspace((unsigned char)**s))
- (*s)++;
+ (*s)++;
}
static int
@@ -1989,22 +1990,22 @@ string_to_c_strict(VALUE self, int raise)
if (!s || memchr(s, '\0', RSTRING_LEN(self))) {
if (!raise) return Qnil;
- rb_raise(rb_eArgError, "string contains null byte");
+ rb_raise(rb_eArgError, "string contains null byte");
}
if (s && s[RSTRING_LEN(self)]) {
- rb_str_modify(self);
- s = RSTRING_PTR(self);
- s[RSTRING_LEN(self)] = '\0';
+ rb_str_modify(self);
+ s = RSTRING_PTR(self);
+ s[RSTRING_LEN(self)] = '\0';
}
if (!s)
- s = (char *)"";
+ s = (char *)"";
if (!parse_comp(s, 1, &num)) {
if (!raise) return Qnil;
- rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
- self);
+ rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
+ self);
}
return num;
@@ -2031,6 +2032,12 @@ string_to_c_strict(VALUE self, int raise)
* '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i)
* 'ruby'.to_c #=> (0+0i)
*
+ * Polar form:
+ * include Math
+ * "1.0@0".to_c #=> (1+0.0i)
+ * "1.0@#{PI/2}".to_c #=> (0.0+1i)
+ * "1.0@#{PI}".to_c #=> (-1+0.0i)
+ *
* See Kernel.Complex.
*/
static VALUE
@@ -2044,13 +2051,13 @@ string_to_c(VALUE self)
s = RSTRING_PTR(self);
if (s && s[RSTRING_LEN(self)]) {
- rb_str_modify(self);
- s = RSTRING_PTR(self);
- s[RSTRING_LEN(self)] = '\0';
+ rb_str_modify(self);
+ s = RSTRING_PTR(self);
+ s[RSTRING_LEN(self)] = '\0';
}
if (!s)
- s = (char *)"";
+ s = (char *)"";
(void)parse_comp(s, 0, &num);
@@ -2068,65 +2075,68 @@ nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
{
if (NIL_P(a1) || NIL_P(a2)) {
if (!raise) return Qnil;
- rb_raise(rb_eTypeError, "can't convert nil into Complex");
+ rb_raise(rb_eTypeError, "can't convert nil into Complex");
}
if (RB_TYPE_P(a1, T_STRING)) {
- a1 = string_to_c_strict(a1, raise);
+ a1 = string_to_c_strict(a1, raise);
if (NIL_P(a1)) return Qnil;
}
if (RB_TYPE_P(a2, T_STRING)) {
- a2 = string_to_c_strict(a2, raise);
+ a2 = string_to_c_strict(a2, raise);
if (NIL_P(a2)) return Qnil;
}
if (RB_TYPE_P(a1, T_COMPLEX)) {
- {
- get_dat1(a1);
+ {
+ get_dat1(a1);
- if (k_exact_zero_p(dat->imag))
- a1 = dat->real;
- }
+ if (k_exact_zero_p(dat->imag))
+ a1 = dat->real;
+ }
}
if (RB_TYPE_P(a2, T_COMPLEX)) {
- {
- get_dat1(a2);
+ {
+ get_dat1(a2);
- if (k_exact_zero_p(dat->imag))
- a2 = dat->real;
- }
+ if (k_exact_zero_p(dat->imag))
+ a2 = dat->real;
+ }
}
if (RB_TYPE_P(a1, T_COMPLEX)) {
- if (a2 == Qundef || (k_exact_zero_p(a2)))
- return a1;
- }
-
- if (a2 == Qundef) {
- if (k_numeric_p(a1) && !f_real_p(a1))
- return a1;
- /* should raise exception for consistency */
- if (!k_numeric_p(a1)) {
- if (!raise)
- return rb_protect(to_complex, a1, NULL);
- return to_complex(a1);
+ if (UNDEF_P(a2) || (k_exact_zero_p(a2)))
+ return a1;
+ }
+
+ if (UNDEF_P(a2)) {
+ if (k_numeric_p(a1) && !f_real_p(a1))
+ return a1;
+ /* should raise exception for consistency */
+ if (!k_numeric_p(a1)) {
+ if (!raise) {
+ a1 = rb_protect(to_complex, a1, NULL);
+ rb_set_errinfo(Qnil);
+ return a1;
+ }
+ return to_complex(a1);
}
}
else {
- if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
- (!f_real_p(a1) || !f_real_p(a2)))
- return f_add(a1,
- f_mul(a2,
- f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
+ if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
+ (!f_real_p(a1) || !f_real_p(a2)))
+ return f_add(a1,
+ f_mul(a2,
+ f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
}
{
int argc;
- VALUE argv2[2];
- argv2[0] = a1;
- if (a2 == Qundef) {
+ VALUE argv2[2];
+ argv2[0] = a1;
+ if (UNDEF_P(a2)) {
argv2[1] = Qnil;
argc = 1;
}
@@ -2136,7 +2146,7 @@ nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise)
argv2[1] = a2;
argc = 2;
}
- return nucomp_s_new(argc, argv2, klass);
+ return nucomp_s_new(argc, argv2, klass);
}
}
@@ -2152,33 +2162,6 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
return nucomp_convert(klass, a1, a2, TRUE);
}
-/* --- */
-
-/*
- * call-seq:
- * num.real -> self
- *
- * Returns self.
- */
-static VALUE
-numeric_real(VALUE self)
-{
- return self;
-}
-
-/*
- * call-seq:
- * num.imag -> 0
- * num.imaginary -> 0
- *
- * Returns zero.
- */
-static VALUE
-numeric_imag(VALUE self)
-{
- return INT2FIX(0);
-}
-
/*
* call-seq:
* num.abs2 -> real
@@ -2252,19 +2235,6 @@ numeric_polar(VALUE self)
/*
* call-seq:
- * num.conj -> self
- * num.conjugate -> self
- *
- * Returns self.
- */
-static VALUE
-numeric_conj(VALUE self)
-{
- return self;
-}
-
-/*
- * call-seq:
* flo.arg -> 0 or float
* flo.angle -> 0 or float
* flo.phase -> 0 or float
@@ -2275,9 +2245,9 @@ static VALUE
float_arg(VALUE self)
{
if (isnan(RFLOAT_VALUE(self)))
- return self;
+ return self;
if (f_tpositive_p(self))
- return INT2FIX(0);
+ return INT2FIX(0);
return rb_const_get(rb_mMath, id_PI);
}
@@ -2287,6 +2257,14 @@ float_arg(VALUE self)
* and i is imaginary unit. Real a equals complex a+0i
* mathematically.
*
+ * You can create a \Complex object explicitly with:
+ *
+ * - A {complex literal}[rdoc-ref:syntax/literals.rdoc@Complex+Literals].
+ *
+ * You can convert certain objects to \Complex objects with:
+ *
+ * - \Method #Complex.
+ *
* Complex object can be created as literal, and also by using
* Kernel#Complex, Complex::rect, Complex::polar or to_c method.
*
@@ -2408,8 +2386,6 @@ Init_Complex(void)
rb_define_private_method(compat, "marshal_load", nucomp_marshal_load, 1);
rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader);
- /* --- */
-
rb_define_method(rb_cComplex, "to_i", nucomp_to_i, 0);
rb_define_method(rb_cComplex, "to_f", nucomp_to_f, 0);
rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
@@ -2422,11 +2398,6 @@ Init_Complex(void)
rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
- /* --- */
-
- rb_define_method(rb_cNumeric, "real", numeric_real, 0);
- rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
- rb_define_method(rb_cNumeric, "imag", numeric_imag, 0);
rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
@@ -2434,8 +2405,6 @@ Init_Complex(void)
rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
- rb_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
- rb_define_method(rb_cNumeric, "conj", numeric_conj, 0);
rb_define_method(rb_cFloat, "arg", float_arg, 0);
rb_define_method(rb_cFloat, "angle", float_arg, 0);
@@ -2445,7 +2414,7 @@ Init_Complex(void)
* The imaginary unit.
*/
rb_define_const(rb_cComplex, "I",
- f_complex_new_bang2(rb_cComplex, ZERO, ONE));
+ f_complex_new_bang2(rb_cComplex, ZERO, ONE));
#if !USE_FLONUM
rb_gc_register_mark_object(RFLOAT_0 = DBL2NUM(0.0));
diff --git a/configure.ac b/configure.ac
index d018e8a6f4..220392d120 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,15 +32,19 @@ m4_include([tool/m4/ruby_func_attribute.m4])dnl
m4_include([tool/m4/ruby_mingw32.m4])dnl
m4_include([tool/m4/ruby_prepend_option.m4])dnl
m4_include([tool/m4/ruby_prog_gnu_ld.m4])dnl
+m4_include([tool/m4/ruby_prog_makedirs.m4])dnl
m4_include([tool/m4/ruby_replace_funcs.m4])dnl
m4_include([tool/m4/ruby_replace_type.m4])dnl
+m4_include([tool/m4/ruby_require_funcs.m4])dnl
m4_include([tool/m4/ruby_rm_recursive.m4])dnl
m4_include([tool/m4/ruby_setjmp_type.m4])dnl
m4_include([tool/m4/ruby_stack_grow_direction.m4])dnl
+m4_include([tool/m4/ruby_thread.m4])dnl
m4_include([tool/m4/ruby_try_cflags.m4])dnl
m4_include([tool/m4/ruby_try_cxxflags.m4])dnl
m4_include([tool/m4/ruby_try_ldflags.m4])dnl
m4_include([tool/m4/ruby_universal_arch.m4])dnl
+m4_include([tool/m4/ruby_wasm_tools.m4])dnl
m4_include([tool/m4/ruby_werror_flag.m4])dnl
AC_ARG_VAR([cflags], [additional CFLAGS (ignored when CFLAGS is given)])dnl
@@ -60,14 +64,22 @@ AC_ARG_WITH(baseruby,
[
AC_PATH_PROG([BASERUBY], [ruby], [false])
])
+# BASERUBY must be >= 2.2.0. Note that `"2.2.0" > "2.2"` is true.
AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.2"' 2>/dev/null`" = 42], [
+ AS_CASE(["$build_os"], [mingw*], [
+ # Can MSys shell run a command with a drive letter?
+ RUBYOPT=- `cygpath -ma "$BASERUBY"` --disable=gems -e exit 2>/dev/null || HAVE_BASERUBY=no
+ ])
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"
HAVE_BASERUBY=no
])
+AS_IF([test "$HAVE_BASERUBY" = no], [
+ AS_IF([test "$cross_compiling" = yes], [AC_MSG_ERROR([executable host ruby is required for cross-compiling])])
+ BASERUBY="echo executable host ruby is required. use --with-baseruby option.; false"
+])
AC_SUBST(BASERUBY)
AC_SUBST(HAVE_BASERUBY)
@@ -84,7 +96,9 @@ AC_SUBST(GIT)
AC_SUBST(HAVE_GIT)
eval `sed -n -e ['s/^@%:@define RUBY_[A-Z_]*VERSION_\([A-Z][A-Z][A-Z_0-9]*\) \([0-9][0-9]*\)$/\1=\2/p'] \
+ -e ['s/^@%:@define \(RUBY_ABI_VERSION\) \([0-9][0-9]*\).*/\1=\2/p'] \
-e ['s/^@%:@define \(RUBY_PATCHLEVEL\) \(.*\)/\1=\2/p'] \
+ $srcdir/include/ruby/internal/abi.h \
$srcdir/include/ruby/version.h $srcdir/version.h`
for v in MAJOR MINOR TEENY; do
AS_IF([eval "test \"\$$v\" = ''"], [
@@ -96,6 +110,9 @@ AC_SUBST(MINOR)
AC_SUBST(TEENY)
AC_SUBST(RUBY_API_VERSION, '$(MAJOR).$(MINOR)')
AC_SUBST(RUBY_PROGRAM_VERSION, '$(MAJOR).$(MINOR).$(TEENY)')
+AS_CASE([$RUBY_PATCHLEVEL], [-*], [
+ AC_DEFINE_UNQUOTED(RUBY_ABI_VERSION, [${RUBY_ABI_VERSION}])
+], [RUBY_ABI_VERSION=])
AS_IF([test "$program_prefix" = NONE], [
program_prefix=
@@ -116,9 +133,12 @@ AC_CANONICAL_TARGET
AS_CASE(["$target_cpu-$target_os"],
[aarch64-darwin*], [
target_cpu=arm64
- AS_CASE(["$target_vendor"], [unknown], [target_vendor=apple target=${target/-unknown-/-apple-}])
- target="${target/aarch64/arm64}"
- target_alias="${target_alias/aarch64/arm64}"
+ AS_CASE(["$target_vendor"], [unknown], [
+ target_vendor=apple
+ target=${target%%-unknown-*}-apple-${target@%:@*-unknown-}
+ ])
+ target="arm64-${target@%:@aarch64-}"
+ AS_IF([test -n "$target_alias"], [target_alias="arm64-${target_alias@%:@aarch64-}"])
])
AC_ARG_PROGRAM
@@ -135,6 +155,9 @@ 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))
])
+
+RUBY_WASM_TOOLS
+
AS_CASE(["${build_os}"],
[linux*|cygwin*|msys*], [
# Naruse prefers GCC on Linux
@@ -164,38 +187,50 @@ 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
+AC_DEFUN([RUBY_CHECK_PROG_FOR_CC], [
+ rb_prog=`echo "${rb_CC}" | sed "$2"`
+ AC_CHECK_PROG([$1], [$rb_prog], [$rb_prog])
+])
AS_CASE(["/${rb_CC} "],
[*@<:@\ /@:>@"cc "*], [
# Don't try g++/clang++ when CC=cc
- AC_CHECK_TOOLS([CXX], [cl.exe CC c++])
+ AC_CHECK_PROGS([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/`])
+ RUBY_CHECK_PROG_FOR_CC([AR], [s/icc/xiar/])
+ RUBY_CHECK_PROG_FOR_CC([CXX], [s/icc/icpc/])
+ RUBY_CHECK_PROG_FOR_CC([LD], [s/icc/xild/])
],
[*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/`])
+ # Ditto for GCC.
+ RUBY_CHECK_PROG_FOR_CC([LD], [s/gcc/ld/])
+ RUBY_CHECK_PROG_FOR_CC([AR], [s/gcc/gcc-ar/])
+ RUBY_CHECK_PROG_FOR_CC([CXX], [s/gcc/g++/])
+ RUBY_CHECK_PROG_FOR_CC([NM], [s/gcc/gcc-nm/])
+ RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/gcc/gcc-ranlib/])
],
[*clang*], [
- # Dito for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode
+ # Ditto 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/`])
+
+ # Xcode has its own version tools that may be incompatible with
+ # genuine LLVM tools, use the tools in the same directory.
+
+ AS_IF([$rb_CC -E -dM -xc - < /dev/null | grep -F __apple_build_version__ > /dev/null],
+ [llvm_prefix=], [llvm_prefix=llvm-])
+ # AC_PREPROC_IFELSE cannot be used before AC_USE_SYSTEM_EXTENSIONS
+
+ RUBY_CHECK_PROG_FOR_CC([LD], [s/clang/ld/]) # ... maybe try lld ?
+ RUBY_CHECK_PROG_FOR_CC([AR], [s/clang/${llvm_prefix}ar/])
+# RUBY_CHECK_PROG_FOR_CC([AS], [s/clang/${llvm_prefix}as/])
+ RUBY_CHECK_PROG_FOR_CC([CXX], [s/clang/clang++/])
+ RUBY_CHECK_PROG_FOR_CC([NM], [s/clang/${llvm_prefix}nm/])
+ RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [s/clang/${llvm_prefix}objcopy/])
+ RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [s/clang/${llvm_prefix}objdump/])
+ RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/clang/${llvm_prefix}ranlib/])
+ RUBY_CHECK_PROG_FOR_CC([STRIP], [s/clang/${llvm_prefix}strip/])
])
AS_UNSET(rb_CC)
AS_UNSET(rb_dummy)
@@ -218,7 +253,7 @@ 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])
+m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_C99])
AC_PROG_CXX
AC_PROG_CPP
@@ -336,10 +371,9 @@ AS_CASE(["$target_os"],
[!<===== pre OS X 10.5 =====>]
@%:@endif
]])],
- [macosx_min_required=yes],
+ [AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
AC_MSG_ERROR([Unsupported OS X version is required])])
- AC_MSG_RESULT(${macosx_min_required})
])
RUBY_MINGW32
@@ -355,14 +389,21 @@ AS_IF([test "$GCC" = yes], [
icc_version=`echo =__ICC | $CC -E -xc - | sed '/^=/!d;s///;/^__ICC/d'`
test -n "$icc_version" || icc_version=0
# RUBY_APPEND_OPTIONS(XCFLAGS, ["-include ruby/config.h" "-include ruby/missing.h"])
+
+ AS_IF([test "$gcc_major" -lt 4], [
+ AC_MSG_ERROR([too old GCC: $gcc_major.$gcc_minor])
+ ])
+
+ AC_CACHE_CHECK([if thread-local storage is supported], [rb_cv_tls_supported],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[int __thread conftest;]])],
+ [rb_cv_tls_supported=yes],
+ [rb_cv_tls_supported=no])])
+ AS_IF([test x"$rb_cv_tls_supported" != xyes],
+ [AC_DEFINE(RB_THREAD_LOCAL_SPECIFIER_IS_UNSUPPORTED)])
], [
linker_flag=
])
-AS_IF([test "$GCC" = yes -a "$gcc_major" -lt 3 ], [
- AC_MSG_ERROR([too old GCC])
-])
-
RUBY_PROG_GNU_LD
RUBY_CPPOUTFILE
@@ -401,6 +442,15 @@ AS_CASE(["$build_os"],
])
rm -fr conftest*
])
+AS_CASE(["$target_os"],
+ [wasi*], [
+ # Clang linker automatically uses wasm-opt with -O if it found.
+ # https://github.com/llvm/llvm-project/blob/812828984c10857a4cd260eb638c52a4411f9143/clang/lib/Driver/ToolChains/WebAssembly.cpp#L95-L118
+ # However optimization before asyncify causes misoptimization,
+ # so wrap clang to insert our fake wasm-opt, which does nothing, in PATH.
+ CC_WRAPPER=`cd -P "${tooldir}" && pwd`/wasm-clangw
+ CC="$CC_WRAPPER $CC"
+ ])
cc_version=
for option in --version -v -V -qversion; do
@@ -450,14 +500,17 @@ AS_CASE(["$target_os"],
[[FILE* volatile f = stdin; return 0;]])],
[rb_cv_msvcrt=`$OBJDUMP -p conftest$ac_exeext |
tr A-Z a-z |
- sed -n '/^[[ ]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;}'`],
+ sed -n '/^[[ ]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;};
+ /^[[ ]]*dll name: \(ucrtbase\|api-ms-win-crt-.*\)\.dll$/{s//ucrt/p;q;}'`],
[rb_cv_msvcrt=msvcrt])
test "$rb_cv_msvcrt" = "" && rb_cv_msvcrt=msvcrt])
RT_VER=`echo "$rb_cv_msvcrt" | tr -cd [0-9]`
test "$RT_VER" = "" && RT_VER=60
+ test "$rb_cv_msvcrt" = "ucrt" && RT_VER=140
AC_DEFINE_UNQUOTED(RUBY_MSVCRT_VERSION, $RT_VER)
sysconfdir=
])
+ rb_cv_binary_elf=no
: ${enable_shared=yes}
],
[hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi <toyoda@npd.kishou.go.jp>
@@ -465,17 +518,12 @@ AS_CASE(["$target_os"],
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_INSTALL
-AC_PROG_MKDIR_P
-AS_IF([test "x$MKDIR_P" = "x -d"], [
- AS_IF([test x"$as_mkdir_p" != xfalse], [
- MKDIR_P='mkdir -p'
- echo "use 'mkdir -p' as MKDIR_P"
- ], [
- AC_MSG_ERROR([mkdir -p is required])
- ])
+
+AS_CASE(["$target_os"],[openbsd*],[
+ ac_cv_path_mkdir="mkdir"
])
-MAKEDIRS="$MKDIR_P"
-AC_SUBST(MAKEDIRS)
+
+RUBY_PROG_MAKEDIRS
AC_CHECK_PROG([DTRACE], [${ac_tool_prefix}dtrace], [${ac_tool_prefix}dtrace])
AS_IF([test "$cross_compiling:$ac_cv_prog_DTRACE" = no: -a -n "$ac_tool_prefix"], [
@@ -485,11 +533,16 @@ 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)
-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
+tool_warned=$ac_tool_warned ac_tool_warned=no
+AC_CHECK_TOOL(PKG_CONFIG, pkg-config)
+ac_tool_warned=$tool_warned
+AS_IF([test -z "$PKG_CONFIG"], [],
+["$PKG_CONFIG" --print-errors --version > /dev/null 2>&1], [],
+[
+ unset ac_cv_prog_PKG_CONFIG
+ PKG_CONFIG=
+ AC_MSG_WARN([$PKG_CONFIG does not work; ignore])
+])
AC_MSG_CHECKING([whether it is Android])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -572,23 +625,39 @@ RUBY_WERROR_FLAG([
cd .. && rm -fr tmp.$$.try_link
])
-: ${RPATHFLAG=''}
-rpathflag=''
-AS_IF([test x"${RPATHFLAG}" = x], [
- AS_CASE(["$target_os"],
- [hpux*], [AS_IF([test "$rb_cv_prog_gnu_ld" = no], [rpathflag='+b '])],
+: "rpath" && {
+ AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf,
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[
+ AS_CASE(["`head -1 conftest$EXEEXT | tr -dc '\177ELF' | tr '\177' .`"],
+ [.ELF*], [rb_cv_binary_elf=yes], [rb_cv_binary_elf=no])],
+ [rb_cv_binary_elf=no])])
+
+ rpathflag=''
+ AS_IF([test x"${RPATHFLAG=}" = x], [
+ AS_CASE(["$target_os"],
[aix*], [rpathflag='-blibpath:'],
- [for rpathflag in -R "-rpath "; do
+ [for rpathflag in "-rpath " -R; do
AS_CASE("$rpathflag",
[*" "], [AS_CASE(["${linker_flag}"],
[*,], [rpathflag=`echo "$rpathflag" | tr ' ' ,`])])
rpathflag="${linker_flag}${rpathflag}"
RUBY_TRY_LDFLAGS([${rpathflag}.], [], [rpathflag=])
- AS_IF([test "x${rpathflag}" != x], [])
+ AS_IF([test "x${rpathflag}" != x], [break])
done])
-], [
- rpathflag=`echo "$RPATHFLAG" | sed 's/%.*//'`
-])
+ ], [
+ rpathflag=`echo "$RPATHFLAG" | sed 's/%.*//'`
+ ])
+
+ AC_ARG_ENABLE(rpath,
+ AS_HELP_STRING([--enable-rpath], [embed run path into extension libraries.
+ enabled by default on ELF platforms]),
+ [enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"])
+
+ AS_IF([test "$enable_rpath:${RPATHFLAG}" = yes:], [
+ RPATHFLAG="${rpathflag:+ ${rpathflag}%1\$-s}"
+ ])
+ AS_CASE([${RPATHFLAG}],[*'%1$'*],[: ${LIBPATHFLAG=' -L%1$-s'}],[: ${LIBPATHFLAG=' -L%s'}])
+}
RUBY_TRY_LDFLAGS(-fdeclspec, [fdeclspec=yes], [fdeclspec=no])
AS_IF([test "$fdeclspec" = yes], [
@@ -601,9 +670,13 @@ AS_IF([test "$fdeclspec" = yes], [
RUBY_APPEND_OPTIONS(CXXFLAGS, -fdeclspec)
])
-AS_CASE([$RUBY_PATCHLEVEL], [-*],
- [RUBY_DEVEL=yes], [RUBY_DEVEL=no])
-particular_werror_flags=$RUBY_DEVEL
+AC_ARG_ENABLE(devel,
+ AS_HELP_STRING([--enable-devel], [enable development build]),
+ [RUBY_DEVEL=$enableval],
+ [AS_IF([test "x${RUBY_DEVEL-no}" != xyes], [RUBY_DEVEL=])]
+)dnl
+AC_SUBST(RUBY_DEVEL)
+particular_werror_flags=${RUBY_DEVEL:-no}
AC_ARG_ENABLE(werror,
AS_HELP_STRING([--disable-werror],
[don't make warnings into errors
@@ -614,10 +687,7 @@ AC_ARG_ENABLE(werror,
rb_cv_warnflags="$warnflags"
AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"],
[yes::*|yes:*:set:], [# GCC && (!warnflags || extra_warnflags)
- AS_IF([test $gcc_major -ge 4], [
- extra_warnflags="$extra_warnflags -Werror=extra-tokens"
- ])
- AS_IF([test $gcc_major -ge 5 -a $gcc_major -le 6], [
+ AS_IF([test $gcc_major -le 6], [
extra_warnflags="$extra_warnflags -Wno-maybe-uninitialized"
])
# ICC doesn't support -Werror=
@@ -625,8 +695,9 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"],
particular_werror_flags=no
])
for wflag in \
+ -Werror=extra-tokens \
-Werror=deprecated-declarations \
- -Werror=division-by-zero \
+ -Werror=division-by-zero -Werror=div-by-zero \
-Werror=duplicated-cond \
-Werror=implicit-function-declaration \
-Werror=implicit-int \
@@ -634,6 +705,7 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"],
-Werror=pointer-arith \
-Werror=shorten-64-to-32 \
-Werror=write-strings \
+ -Werror=old-style-definition \
-Wimplicit-fallthrough=0 \
-Wmissing-noreturn \
-Wno-cast-function-type \
@@ -728,7 +800,8 @@ 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([$optflags -D_FORTIFY_SOURCE=2], [RUBY_APPEND_OPTION(XCFLAGS, -D_FORTIFY_SOURCE=2)], [],
+ RUBY_TRY_CFLAGS([$optflags -D_FORTIFY_SOURCE=2],
+ [RUBY_APPEND_OPTION(XCFLAGS, -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)], [],
[@%:@include <stdio.h>])
])
@@ -736,7 +809,7 @@ AS_IF([test "$GCC" = yes], [
# -fstack-protector
AS_CASE(["$target_os"],
- [mingw*|emscripten*], [
+ [emscripten*|wasi*], [
stack_protector=no
])
AS_IF([test -z "${stack_protector+set}"], [
@@ -748,12 +821,25 @@ AS_IF([test "$GCC" = yes], [
AS_IF([test "x$stack_protector" = xyes], [stack_protector=option; break])
])
])
+ AC_MSG_CHECKING([for -fstack-protector])
+ AC_MSG_RESULT(["$stack_protector"])
AS_CASE(["$stack_protector"], [-*], [
RUBY_APPEND_OPTION(XCFLAGS, $stack_protector)
RUBY_APPEND_OPTION(XLDFLAGS, $stack_protector)
RUBY_APPEND_OPTION(LDFLAGS, $stack_protector)
])
+ # aarch64 branch protection
+ AS_CASE(["$target_cpu"], [aarch64], [
+ AS_FOR(option, opt, [-mbranch-protection=pac-ret -msign-return-address=all], [
+ RUBY_TRY_CFLAGS(option, [branch_protection=yes], [branch_protection=no])
+ AS_IF([test "x$branch_protection" = xyes], [
+ RUBY_APPEND_OPTION(XCFLAGS, option)
+ break
+ ])
+ ])
+ ])
+
AS_CASE("${compress_debug_sections:-zlib}",
[none|no], [], [
RUBY_TRY_LDFLAGS(${linker_flag}--compress-debug-sections=${compress_debug_sections:-zlib},
@@ -799,34 +885,7 @@ AS_IF([test "$GCC" = yes], [
])
],
[cygwin*|msys*|darwin*|netbsd*], [
- # need lgamma_r(), finite()
- ])
-
- # ANSI (no XCFLAGS because this is C only)
- AS_CASE(["$target_os"],
- [solaris*], [
- # Because "-std=gnu99" affects existence of functions on Solaris,
- # "-std=gnu99" will be appended to CPPFLAGS.
- for ansi_options in -std=gnu99; do
- RUBY_TRY_CFLAGS(${ansi_options}, [
- RUBY_APPEND_OPTIONS(CPPFLAGS, ${ansi_options})
- ], [ansi_options=])
- test "x${ansi_options}" = x || break
- done
- ],
- [
- # ANSI (no XCFLAGS because this is C only)
- rb_tmp_std_check=`echo $CC $CFLAGS $optflags $warnflags $debugflags | fgrep std= | tr -d '\015'`
- AS_IF([test "x$rb_tmp_std_check" = "x"],
- [
- for ansi_options in -std=gnu99; do
- RUBY_TRY_CFLAGS(${ansi_options}, [
- RUBY_APPEND_OPTIONS(warnflags, ${ansi_options})
- RUBY_APPEND_OPTIONS(strict_warnflags, ${ansi_options})
- ], [ansi_options=])
- test "x${ansi_options}" = x || break
- done
- ])
+ # need lgamma_r()
])
# suppress annoying -Wstrict-overflow warnings
@@ -837,15 +896,12 @@ AS_IF([test "$GCC" = yes], [
test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-g3, [debugflags=-g3])}
])
test $ac_cv_prog_cc_g = yes && : ${debugflags=-g}
-AS_IF([test "x$RUBY_DEVEL" = xyes], [RUBY_APPEND_OPTION(XCFLAGS, -DRUBY_DEVEL=1)])
AS_IF([test "$GCC" = ""], [
AS_CASE(["$target_os"],[aix*],[warnflags="$warnflags -qinfo=por" rb_cv_warnflags="$rb_cv_warnflags -qinfo=por"])
])
AS_IF([test "$GCC" = yes], [
- AS_IF([test "$gcc_major" -ge 4], [
- RUBY_TRY_CFLAGS(-fvisibility=hidden, [visibility_option=yes], [visibility_option=no])
- ])
+ RUBY_TRY_CFLAGS(-fvisibility=hidden, [visibility_option=yes], [visibility_option=no])
AC_SUBST(WERRORFLAG, "-Werror")
AS_IF([test "$visibility_option" = yes], [
RUBY_APPEND_OPTION(XCFLAGS, -fvisibility=hidden)
@@ -894,17 +950,35 @@ AS_CASE(["$target_cpu"], [[i[3-6]86*]], [
AS_IF([test "$rb_cv_gcc_compiler_cas" = i486], [ARCH_FLAG="-march=i486"])
])
+OPT_DIR=
+AC_ARG_WITH([gmp-dir],
+ AS_HELP_STRING([--with-gmp-dir=DIR],
+ [specify the prefix directory where gmp is installed]),
+ [OPT_DIR="${OPT_DIR:+$OPT_DIR$PATH_SEPARATOR}$withval"], [])
+AC_ARG_WITH([gmp],
+ [AS_HELP_STRING([--without-gmp],
+ [disable GNU GMP to accelerate Bignum operations])],
+ [], [with_gmp=yes])
+
AC_ARG_WITH(opt-dir,
AS_HELP_STRING([--with-opt-dir=DIR-LIST],
[add optional headers and libraries directories separated by $PATH_SEPARATOR]),
- [
- val=`echo "$PATH_SEPARATOR$withval" | sed "s|$PATH_SEPARATOR\([[^$PATH_SEPARATOR]*]\)| -I\1/include|g;s/^ //"`
- CPPFLAGS="$CPPFLAGS $val"
- val=`echo "$PATH_SEPARATOR$withval" | sed "s|$PATH_SEPARATOR\([[^$PATH_SEPARATOR]*]\)| -L\1/lib${rpathflag:+ $rpathflag\\\\1/lib}|g;s/^ //"`
- LDFLAGS="$LDFLAGS $val"
- LDFLAGS_OPTDIR="$val"
- OPT_DIR="$withval"
- ], [OPT_DIR=])
+ [OPT_DIR="${OPT_DIR:+$OPT_DIR$PATH_SEPARATOR}$withval"], [])
+
+AS_IF([test "x$OPT_DIR" != x], [
+ val=`IFS="$PATH_SEPARATOR"
+ for dir in $OPT_DIR; do
+ test -z "$dir" && continue
+ echo x ${LIBPATHFLAG} ${RPATHFLAG} |
+ sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${dir}/lib${IFS}g;s${IFS}%s${IFS}${dir}/lib${IFS}g"
+ done | tr '\012' ' ' | sed 's/ *$//'`
+ LDFLAGS="${LDFLAGS:+$LDFLAGS }$val"
+ DLDFLAGS="${DLDFLAGS:+$DLDFLAGS }$val"
+ LDFLAGS_OPTDIR="$val"
+ INCFLAGS="${INCFLAGS:+$INCFLAGS }"`echo "$OPT_DIR" | tr "${PATH_SEPARATOR}" '\012' |
+ sed '/^$/d;s|^|-I|;s|$|/include|' | tr '\012' ' ' | sed 's/ *$//'`
+])
+AC_SUBST(incflags, "$INCFLAGS")
test -z "${ac_env_CFLAGS_set}" -a -n "${cflags+set}" && eval CFLAGS="\"$cflags $ARCH_FLAG\""
test -z "${ac_env_CXXFLAGS_set}" -a -n "${cxxflags+set}" && eval CXXFLAGS="\"$cxxflags $ARCH_FLAG\""
@@ -929,26 +1003,7 @@ AS_CASE(["$target_os"],
RUBY_APPEND_OPTION(CPPFLAGS, -D__MINGW_USE_VC2005_COMPAT)
])
-AS_CASE(["$target_os"],
-[freebsd*], [
- AC_CACHE_CHECK([whether pthread should be enabled by default],
- rb_cv_enable_pthread_default,
- [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
-#include <osreldate.h>
-#if __FreeBSD_version < 502102
-#error pthread should be disabled on this platform
-#endif
- ]])],
- rb_cv_enable_pthread_default=yes,
- rb_cv_enable_pthread_default=no)])
- enable_pthread=$rb_cv_enable_pthread_default
- ],
-[mingw*], [
- enable_pthread=no
- ],
-[
- enable_pthread=yes
- ])
+RUBY_THREAD
dnl Checks for libraries.
AS_CASE(["$target_os"],[*bsd*|dragonfly*],[],[ac_cv_func_daemon=no])
@@ -986,18 +1041,11 @@ AS_CASE(["$target_os"],
])
ac_cv_func_getcontext=no
ac_cv_func_setcontext=no
- incs=`$CC -v -E -xc - < /dev/null 2>&1 | sed ['1,/^@%:@include </d;s/^ *//;s|[^./][^/]*/\.\./||g;/\/include$/!d;s||/lib|;/\/usr\/lib/d']`
- for d in `$CC -print-search-dirs | sed -e '/^libraries: */!d;s///' | tr : '\012' | fgrep -v /../ | sed -n 's|^\(/.*/lib\)/$|\1|p'`; do
- incs=`echo "$incs" | fgrep -v "$d"`
- done
- for d in $incs; do
- test -d "$d" && RUBY_APPEND_OPTIONS(LDFLAGS, "-L$d")
- done
ac_cv_type_getgroups=gid_t # getgroups() on Rosetta fills garbage
ac_cv_lib_crypt_crypt=no
ac_cv_func_fdatasync=no # Mac OS X wrongly reports it has fdatasync()
ac_cv_func_vfork=no
- AS_IF([test $gcc_major -lt 4 -o \( $gcc_major -eq 4 -a $gcc_minor -lt 3 \)], [
+ AS_IF([test $gcc_major -eq 4 -a $gcc_minor -lt 3], [
ac_cv_func___builtin_setjmp=no
])
with_setjmp_type=sigsetjmp # to hijack SIGCHLD handler
@@ -1064,8 +1112,6 @@ main()
])
cleanlibs='$(TARGET_SO).dSYM'
],
-[hpux*], [ LIBS="-lm $LIBS"
- ac_cv_c_inline=no],
[solaris*], [ LIBS="-lm $LIBS"
ac_cv_func_vfork=no
AC_MSG_CHECKING(whether _XOPEN_SOURCE is already given)
@@ -1103,9 +1149,21 @@ main()
RUBY_APPEND_OPTIONS(CXXFLAGS, -U_XOPEN_SOURCE)
])
])
+ AC_CHECK_TYPES([caddr_t],[],[],[@%:@include <sys/types.h>])
+ AC_CACHE_CHECK([whether madvise declaration is needed], rb_cv_madvice_prototype_using_caddr_t,
+ [RUBY_WERROR_FLAG([AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <sys/unistd.h>
+ @%:@include <sys/mman.h>
+ @%:@include <sys/types.h>
+ extern int madvise(caddr_t, size_t, int);
+ ]], [[]])],
+ [rb_cv_madvice_prototype_using_caddr_t=yes], [rb_cv_madvice_prototype_using_caddr_t=no])
+ ])
+ ])
+ AS_IF([test $rb_cv_madvice_prototype_using_caddr_t = yes], [AC_DEFINE(NEED_MADVICE_PROTOTYPE_USING_CADDR_T, 1)])
],
[haiku*], [
- LIBS="$LIBS -lssp" # m lib is include in root
+ LIBS="$LIBS" # m lib is include in root
],
[cygwin*|msys*], [
ac_cv_header_langinfo_h=yes
@@ -1113,7 +1171,7 @@ main()
AC_CHECK_FUNCS(cygwin_conv_path)
AC_LIBOBJ([langinfo])
],
-[mingw*], [ LIBS="-lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi $LIBS"
+[mingw*], [ LIBS="-lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi -lbcrypt $LIBS"
ac_cv_header_pwd_h=no
ac_cv_header_utime_h=no
ac_cv_header_sys_ioctl_h=no
@@ -1123,6 +1181,7 @@ main()
ac_cv_header_sys_time_h=no
ac_cv_header_sys_times_h=no
ac_cv_header_sys_socket_h=no
+ ac_cv_func_execv=yes
ac_cv_func_lstat=yes
ac_cv_func_times=yes
ac_cv_func_waitpid=yes
@@ -1132,27 +1191,24 @@ main()
ac_cv_func_lchown=yes
ac_cv_func_link=yes
ac_cv_func_readlink=yes
+ ac_cv_func_shutdown=yes
ac_cv_func_symlink=yes
ac_cv_lib_crypt_crypt=no
ac_cv_func_getpgrp_void=no
ac_cv_func_memcmp_working=yes
ac_cv_lib_dl_dlopen=no
- rb_cv_binary_elf=no
rb_cv_negative_time_t=yes
ac_cv_func_fcntl=yes
ac_cv_func_flock=yes
ac_cv_func_gmtime_r=yes
rb_cv_large_fd_select=yes
ac_cv_type_struct_timeval=yes
- ac_cv_func_clock_gettime=yes
- ac_cv_func_clock_getres=yes
ac_cv_func_malloc_usable_size=no
ac_cv_type_off_t=yes
ac_cv_sizeof_off_t=8
AS_IF([test "$target_cpu" = x64], [
ac_cv_func___builtin_setjmp=yes
ac_cv_func_round=no
- coroutine_type=yes
])
ac_cv_func_tgamma=no
AC_CHECK_TYPE([NET_LUID], [], [],
@@ -1200,6 +1256,15 @@ main()
RUBY_APPEND_OPTIONS(LDFLAGS, "-sALLOW_MEMORY_GROWTH=1")
RUBY_APPEND_OPTIONS(LDFLAGS, "-sASYNCIFY")
RUBY_APPEND_OPTIONS(LDFLAGS, "-sFORCE_FILESYSTEM=1")
+ ac_cv_func_shutdown=no
+ ],
+[wasi*],[ LIBS="-lm -lwasi-emulated-mman -lwasi-emulated-signal -lwasi-emulated-getpid -lwasi-emulated-process-clocks $LIBS"
+ RUBY_APPEND_OPTIONS(CFLAGS, -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS)
+ RUBY_APPEND_OPTIONS(CPPFLAGS, -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS)
+ POSTLINK="\$(WASMOPT) --asyncify \$(wasmoptflags) --pass-arg=asyncify-ignore-imports -o \$@ \$@${POSTLINK:+; $POSTLINK}"
+ # wasi-libc's sys/socket.h is not compatible with -std=gnu99,
+ # so re-declare shutdown in include/ruby/missing.h
+ ac_cv_func_shutdown=no
],
[ LIBS="-lm $LIBS"])
: ${ORIG_LIBS=$LIBS}
@@ -1224,7 +1289,6 @@ AS_IF([test -n "${rb_there_is_in_fact_no_gplusplus_but_autoconf_is_cheating_us}"
AC_CHECK_LIB(crypt, crypt) # glibc (GNU/Linux, GNU/Hurd, GNU/kFreeBSD)
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
-AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
AC_CHECK_LIB(socket, shutdown) # SunOS/Solaris
dnl Checks for header files.
@@ -1233,6 +1297,11 @@ dnl AC_HEADER_STDC has been checked in AC_USE_SYSTEM_EXTENSIONS
AC_HEADER_STDBOOL
AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([afunix.h], [], [],
+[#ifdef _WIN32
+# include <winsock2.h>
+#endif
+])
AC_CHECK_HEADERS(atomic.h)
AC_CHECK_HEADERS(copyfile.h)
AC_CHECK_HEADERS(direct.h)
@@ -1254,6 +1323,7 @@ AC_CHECK_HEADERS(sanitizer/asan_interface.h)
AC_CHECK_HEADERS(sanitizer/msan_interface.h)
AC_CHECK_HEADERS(setjmpex.h)
AC_CHECK_HEADERS(stdalign.h)
+AC_CHECK_HEADERS(stdio.h)
AC_CHECK_HEADERS(sys/attr.h)
AC_CHECK_HEADERS(sys/eventfd.h)
AC_CHECK_HEADERS(sys/fcntl.h)
@@ -1278,15 +1348,13 @@ AC_CHECK_HEADERS(syscall.h)
AC_CHECK_HEADERS(time.h)
AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(utime.h)
+AC_CHECK_HEADERS(stdatomic.h)
+
AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
AC_CHECK_HEADERS(x86intrin.h)
])
+RUBY_UNIVERSAL_CHECK_HEADER([x86_64, i386], x86intrin.h)
-AC_ARG_WITH([gmp],
- [AS_HELP_STRING([--without-gmp],
- [disable GNU GMP to accelerate Bignum operations])],
- [],
- [with_gmp=yes])
AS_IF([test "x$with_gmp" != xno],
[AC_CHECK_HEADERS(gmp.h)
AS_IF([test "x$ac_cv_header_gmp_h" != xno],
@@ -1298,6 +1366,8 @@ AC_ARG_WITH([jemalloc],
[with_jemalloc=$withval], [with_jemalloc=no])
AS_IF([test "x$with_jemalloc" != xno],[
# find jemalloc header first
+ save_CPPFLAGS="${CPPFLAGS}"
+ CPPFLAGS="${INCFLAGS} ${CPPFLAGS}"
malloc_header=
AC_CHECK_HEADER(jemalloc/jemalloc.h, [malloc_header=jemalloc/jemalloc.h], [
AC_CHECK_HEADER(jemalloc.h, [malloc_header=jemalloc.h])
@@ -1329,6 +1399,8 @@ AS_IF([test "x$with_jemalloc" != xno],[
done
done
])
+ CPPFLAGS="${save_CPPFLAGS}"
+ unset save_CPPFLAGS
with_jemalloc=${rb_cv_jemalloc_library}
AS_CASE(["$with_jemalloc"],
[no],
@@ -1336,6 +1408,7 @@ AS_IF([test "x$with_jemalloc" != xno],[
[-l*], [
set dummy $with_jemalloc
LIBS="$2 $LIBS"
+ DLDLIBS="$2${DLDLIBS:+ $DLDLIBS}" # probably needed also in extension libraries
])
AS_CASE(["$with_jemalloc"],
[*" with mangle"], [
@@ -1383,7 +1456,7 @@ AS_CASE(["$target_os"],
])
])
-AC_C_BIGENDIAN
+AC_C_BIGENDIAN([], [], [], [AC_DEFINE(AC_APPLE_UNIVERSAL_BUILD, 1)])
AC_C_CONST
AC_C_CHAR_UNSIGNED
AC_C_INLINE
@@ -1625,7 +1698,19 @@ AS_IF([test "$GCC" = yes], [
])
])
AS_IF([test "$rb_cv_func___builtin_unreachable" = yes], [
- AC_DEFINE_UNQUOTED(UNREACHABLE, [__builtin_unreachable()])
+ AC_DEFINE(HAVE___BUILTIN_UNREACHABLE)
+ ])
+
+ AC_CACHE_CHECK(for __assume, rb_cv_func___assume,
+ [RUBY_WERROR_FLAG([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+ [[__assume(1);]])],
+ [rb_cv_func___assume=yes],
+ [rb_cv_func___assume=no])
+ ])
+ ])
+ AS_IF([test "$rb_cv_func___assume" = yes], [
+ AC_DEFINE(HAVE___ASSUME)
])
}
@@ -1662,7 +1747,7 @@ AC_CACHE_CHECK(for function name string predefined identifier,
RUBY_WERROR_FLAG([
for func in __func__ __FUNCTION__; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include <stdio.h>]],
- [[puts($func);]])],
+ [[puts($func);]])],
[rb_cv_function_name_string=$func
break])
done
@@ -1836,7 +1921,7 @@ AS_IF([test $rb_cv_stack_end_address != no], [
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
-[powerpc-darwin*], [
+[powerpc*-darwin*], [
AC_LIBSOURCES(alloca.c)
AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
AC_DEFINE(C_ALLOCA)
@@ -1845,8 +1930,8 @@ AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
[universal-darwin*:*ppc*], [
AC_LIBSOURCES(alloca.c)
AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
- RUBY_DEFINE_IF([defined __powerpc__], C_ALLOCA, 1)
- RUBY_DEFINE_IF([defined __powerpc__], alloca, alloca)
+ RUBY_DEFINE_IF([defined __POWERPC__], C_ALLOCA, 1) # Darwin defines __POWERPC__ for ppc and ppc64 both
+ RUBY_DEFINE_IF([defined __POWERPC__], alloca, alloca)
],
[
AC_FUNC_ALLOCA
@@ -1879,12 +1964,13 @@ AS_CASE(["$target_os"],[freebsd*],[
AC_REPLACE_FUNCS(close)
])
-AC_DEFUN([RUBY_REQUIRE_FUNC], [
- AC_CHECK_FUNCS([$1])
- AS_IF([test "$ac_cv_func_[]AS_TR_SH($1)" = yes], [],
- [AC_MSG_ERROR($1[() must be supported])])
-])
-m4_map_args_w([dup dup2], [RUBY_REQUIRE_FUNC(], [)])
+# dup and dup2 are always available except for WASI
+AS_CASE(["$target_os"],
+ [wasi*], [],
+ [
+ RUBY_REQUIRE_FUNCS(dup dup2)
+ ]
+)
AC_REPLACE_FUNCS(acosh)
AC_REPLACE_FUNCS(cbrt)
@@ -1906,29 +1992,16 @@ AC_REPLACE_FUNCS(strlcpy)
AC_REPLACE_FUNCS(strstr)
AC_REPLACE_FUNCS(tgamma)
-RUBY_REPLACE_FUNC([finite], [@%:@include <math.h>])
-RUBY_REPLACE_FUNC([isinf], [@%:@include <math.h>])
-RUBY_REPLACE_FUNC([isnan], [@%:@include <math.h>])
+AC_DEFINE(HAVE_ISFINITE) # C99; backward compatibility
# for missing/setproctitle.c
AS_CASE(["$target_os"],
[aix* | k*bsd*-gnu | kopensolaris*-gnu | linux* | darwin*], [AC_DEFINE(SPT_TYPE,SPT_REUSEARGV)],
-[hpux*], [AC_DEFINE(SPT_TYPE,SPT_PSTAT) ],
[])
AC_CHECK_HEADERS(sys/pstat.h)
-AC_CACHE_CHECK(for signbit, rb_cv_have_signbit,
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#include <math.h>
-]], [[int v = signbit(-0.0);]])],
- rb_cv_have_signbit=yes,
- rb_cv_have_signbit=no)])
-AS_IF([test "$rb_cv_have_signbit" = yes], [
- AC_DEFINE(HAVE_SIGNBIT)
-], [
- AC_LIBOBJ([signbit])
-])
+AC_DEFINE(HAVE_SIGNBIT) # C99; backward compatibility
AC_FUNC_FORK
@@ -1938,6 +2011,9 @@ AC_CHECK_FUNCS(_longjmp) # used for AC_ARG_WITH(setjmp-type)
test x$ac_cv_func__longjmp = xno && ac_cv_func__setjmp=no
AC_CHECK_FUNCS(arc4random_buf)
AC_CHECK_FUNCS(atan2l atan2f)
+AC_CHECK_DECLS(atomic_signal_fence, [], [], [#include <stdatomic.h>])
+AC_CHECK_FUNCS(chmod)
+AC_CHECK_FUNCS(chown)
AC_CHECK_FUNCS(chroot)
AC_CHECK_FUNCS(chsize)
AC_CHECK_FUNCS(clock_gettime)
@@ -1953,6 +2029,10 @@ AC_CHECK_FUNCS(dup3)
AC_CHECK_FUNCS(eaccess)
AC_CHECK_FUNCS(endgrent)
AC_CHECK_FUNCS(eventfd)
+AC_CHECK_FUNCS(execl)
+AC_CHECK_FUNCS(execle)
+AC_CHECK_FUNCS(execv)
+AC_CHECK_FUNCS(execve)
AC_CHECK_FUNCS(explicit_memset)
AC_CHECK_FUNCS(fcopyfile)
AC_CHECK_FUNCS(fchmod)
@@ -1968,7 +2048,10 @@ AC_CHECK_FUNCS(ftruncate)
AC_CHECK_FUNCS(ftruncate64) # used for Win32 platform
AC_CHECK_FUNCS(getattrlist)
AC_CHECK_FUNCS(getcwd)
+AC_CHECK_FUNCS(getegid)
AC_CHECK_FUNCS(getentropy)
+AC_CHECK_FUNCS(geteuid)
+AC_CHECK_FUNCS(getgid)
AC_CHECK_FUNCS(getgidx)
AC_CHECK_FUNCS(getgrnam)
AC_CHECK_FUNCS(getgrnam_r)
@@ -1977,6 +2060,7 @@ AC_CHECK_FUNCS(getlogin)
AC_CHECK_FUNCS(getlogin_r)
AC_CHECK_FUNCS(getpgid)
AC_CHECK_FUNCS(getpgrp)
+AC_CHECK_FUNCS(getppid)
AC_CHECK_FUNCS(getpriority)
AC_CHECK_FUNCS(getpwnam)
AC_CHECK_FUNCS(getpwnam_r)
@@ -1988,6 +2072,7 @@ AC_CHECK_FUNCS(getresuid)
AC_CHECK_FUNCS(getrlimit)
AC_CHECK_FUNCS(getsid)
AC_CHECK_FUNCS(gettimeofday) # for making ac_cv_func_gettimeofday
+AC_CHECK_FUNCS(getuid)
AC_CHECK_FUNCS(getuidx)
AC_CHECK_FUNCS(gmtime_r)
AC_CHECK_FUNCS(grantpt)
@@ -1995,6 +2080,7 @@ AC_CHECK_FUNCS(initgroups)
AC_CHECK_FUNCS(ioctl)
AC_CHECK_FUNCS(isfinite)
AC_CHECK_FUNCS(issetugid)
+AC_CHECK_FUNCS(kill)
AC_CHECK_FUNCS(killpg)
AC_CHECK_FUNCS(lchmod)
AC_CHECK_FUNCS(lchown)
@@ -2016,10 +2102,15 @@ AC_CHECK_FUNCS(mkfifo)
AC_CHECK_FUNCS(mknod)
AC_CHECK_FUNCS(mktime)
AC_CHECK_FUNCS(mmap)
+AC_CHECK_FUNCS(mremap)
AC_CHECK_FUNCS(openat)
+AC_CHECK_FUNCS(pclose)
+AC_CHECK_FUNCS(pipe)
AC_CHECK_FUNCS(pipe2)
AC_CHECK_FUNCS(poll)
+AC_CHECK_FUNCS(popen)
AC_CHECK_FUNCS(posix_fadvise)
+AC_CHECK_FUNCS(posix_madvise)
AC_CHECK_FUNCS(posix_memalign)
AC_CHECK_FUNCS(ppoll)
AC_CHECK_FUNCS(pread)
@@ -2058,12 +2149,15 @@ AC_CHECK_FUNCS(spawnv)
AC_CHECK_FUNCS(symlink)
AC_CHECK_FUNCS(syscall)
AC_CHECK_FUNCS(sysconf)
+AC_CHECK_FUNCS(system)
AC_CHECK_FUNCS(tanh)
AC_CHECK_FUNCS(telldir)
AC_CHECK_FUNCS(timegm)
AC_CHECK_FUNCS(times)
AC_CHECK_FUNCS(truncate)
AC_CHECK_FUNCS(truncate64) # used for Win32
+AC_CHECK_FUNCS(tzset)
+AC_CHECK_FUNCS(umask)
AC_CHECK_FUNCS(unsetenv)
AC_CHECK_FUNCS(utimensat)
AC_CHECK_FUNCS(utimes)
@@ -2207,7 +2301,7 @@ AS_IF([test "x$rb_cv_atan2_inf_c99" = xyes], [AC_DEFINE(ATAN2_INF_C99)])
# Some platform need -lrt for clock_gettime, but the other don't.
AS_IF([test x"$ac_cv_func_clock_gettime" != xyes], [
# glibc 2.17 moves clock_* functions from librt to the main C library.
- # http://sourceware.org/ml/libc-announce/2012/msg00001.html
+ # https://sourceware.org/legacy-ml/libc-announce/2012/msg00001.html
AC_CHECK_LIB(rt, clock_gettime)
AS_IF([test x"$ac_cv_lib_rt_clock_gettime" = xyes], [
AC_DEFINE(HAVE_CLOCK_GETTIME, 1)
@@ -2305,7 +2399,7 @@ AS_IF([test "$rb_cv_negative_time_t" = yes], [
])
# [ruby-dev:40910] overflow of time on FreeBSD
-# http://www.freebsd.org/cgi/query-pr.cgi?pr=145341
+# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=145341
AC_CACHE_CHECK(for localtime(3) overflow correctly, rb_cv_localtime_overflow,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
@@ -2384,7 +2478,7 @@ AC_CHECK_TYPES([sig_t],[],[],[@%:@include <signal.h>])
AS_IF([test "$ac_cv_func_getpgid" = no], [
# AC_FUNC_GETPGRP fails when cross-compiling with old autoconf.
# autoconf is changed between 2.52d and 2.52f?
- # http://lists.gnu.org/archive/html/bug-gnu-utils/2001-09/msg00181.html
+ # https://lists.gnu.org/archive/html/bug-gnu-utils/2001-09/msg00181.html
# "autoconf cleanup for AC_FUNC_GETPGRP and GETPGRP_VOID"
AC_FUNC_GETPGRP
])
@@ -2508,6 +2602,15 @@ AS_CASE([$coroutine_type], [yes|''], [
[arm64-darwin*], [
coroutine_type=arm64
],
+ # Correct target name is powerpc*-, but Ruby seems to prefer ppc*-.
+ # Notice that Darwin PPC ABI differs from AIX and ELF.
+ # Adding PPC targets for AIX, *BSD and *Linux will require separate implementations.
+ [powerpc-darwin*|ppc-darwin*], [
+ coroutine_type=ppc
+ ],
+ [powerpc64-darwin*|ppc64-darwin*], [
+ coroutine_type=ppc64
+ ],
[x*64-linux*], [
AS_CASE(["$ac_cv_sizeof_voidp"],
[8], [ coroutine_type=amd64 ],
@@ -2518,10 +2621,10 @@ AS_CASE([$coroutine_type], [yes|''], [
[*86-linux*], [
coroutine_type=x86
],
- [x64-mingw32], [
+ [x64-mingw*], [
coroutine_type=win64
],
- [*86-mingw32], [
+ [*86-mingw*], [
coroutine_type=win32
],
[arm*-linux*], [
@@ -2536,6 +2639,24 @@ AS_CASE([$coroutine_type], [yes|''], [
[riscv64-linux*], [
coroutine_type=riscv64
],
+ [x86_64-freebsd*], [
+ coroutine_type=amd64
+ ],
+ [i386-freebsd*], [
+ coroutine_type=x86
+ ],
+ [aarch64-freebsd*], [
+ coroutine_type=arm64
+ ],
+ [x86_64-netbsd*], [
+ coroutine_type=amd64
+ ],
+ [i386-netbsd*], [
+ coroutine_type=x86
+ ],
+ [aarch64-netbsd*], [
+ coroutine_type=arm64
+ ],
[x86_64-openbsd*], [
coroutine_type=amd64
],
@@ -2545,12 +2666,18 @@ AS_CASE([$coroutine_type], [yes|''], [
[*-openbsd*], [
coroutine_type=pthread
],
+ [x86_64-dragonfly*], [
+ coroutine_type=amd64
+ ],
[*-haiku*], [
coroutine_type=pthread
],
[*-emscripten*], [
coroutine_type=emscripten
],
+ [*-wasi*], [
+ coroutine_type=asyncify
+ ],
[
AC_CHECK_FUNCS([getcontext swapcontext makecontext],
[coroutine_type=ucontext],
@@ -2564,37 +2691,14 @@ AS_CASE([$coroutine_type], [yes|''], [
COROUTINE_H=coroutine/$coroutine_type/Context.h
AS_IF([test ! -f "$srcdir/$COROUTINE_H"],
[AC_MSG_ERROR('$coroutine_type' is not supported as coroutine)])
-AS_CASE([$coroutine_type],
- [ucontext|pthread], [
- COROUTINE_SRC=coroutine/$coroutine_type/Context.c
- ],
- [
- COROUTINE_SRC=coroutine/$coroutine_type/Context.'$(ASMEXT)'
- ]
-)
+COROUTINE_SRC=coroutine/$coroutine_type/Context.c
+AS_IF([test ! -f "$srcdir/$COROUTINE_SRC"],
+ [COROUTINE_SRC=coroutine/$coroutine_type/Context.'$(ASMEXT)'])
AC_DEFINE_UNQUOTED(COROUTINE_H, ["$COROUTINE_H"])
AC_SUBST(X_COROUTINE_H, [$COROUTINE_H])
AC_SUBST(X_COROUTINE_SRC, [$COROUTINE_SRC])
-AS_IF([test x"$enable_pthread" = xyes], [
- for pthread_lib in thr pthread pthreads c c_r root; do
- AC_CHECK_LIB($pthread_lib, pthread_create,
- rb_with_pthread=yes, rb_with_pthread=no)
- AS_IF([test "$rb_with_pthread" = "yes"], [break])
- done
- AS_IF([test x"$rb_with_pthread" = xyes], [
- AC_DEFINE(_REENTRANT)
- AC_DEFINE(_THREAD_SAFE)
- AC_DEFINE(HAVE_LIBPTHREAD)
- AC_CHECK_HEADERS(pthread_np.h, [], [], [@%:@include <pthread.h>])
- AS_CASE(["$pthread_lib:$target_os"],
- [c:*], [],
- [root:*], [],
- [c_r:*|*:openbsd*|*:mirbsd*], [LIBS="-pthread $LIBS"],
- [LIBS="-l$pthread_lib $LIBS"])
- ], [
- AC_MSG_WARN("Don't know how to find pthread library on your system -- thread support disabled")
- ])
+AS_IF([test "$THREAD_MODEL" = pthread], [
AC_CACHE_CHECK([whether pthread_t is scalar type], [rb_cv_scalar_pthread_t], [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@%:@include <pthread.h>
@@ -2683,12 +2787,12 @@ AS_IF([test x"$ac_cv_header_ucontext_h" = xyes -o x"$rb_cv_ucontext_in_signal_h"
], [
AC_DEFINE_UNQUOTED(DEFINE_MCONTEXT_PTR(mc, uc), mcontext_t *mc = &(uc)->uc_mcontext)
])
- AS_IF([test x"$rb_with_pthread" = xyes], [
+ AS_IF([test x"$THREAD_MODEL" = xpthread], [
AC_CHECK_FUNCS(getcontext setcontext)
])
])
-AS_IF([test "$ac_cv_func_fork_works" = "yes" -a "$rb_with_pthread" = "yes"], [
+AS_IF([test "$ac_cv_func_fork_works" = "yes" -a x"$THREAD_MODEL" = xpthread], [
AC_CACHE_CHECK([if fork works with pthread], rb_cv_fork_with_pthread,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
@@ -2810,12 +2914,6 @@ AC_ARG_WITH(dln-a-out,
])
])
-AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[
-AS_CASE(["`head -1 conftest$EXEEXT | tr -dc '\177ELF' | tr '\177' .`"],
-[.ELF*], [rb_cv_binary_elf=yes], [rb_cv_binary_elf=no])],
-rb_cv_binary_elf=no)])
-
AS_IF([test "$rb_cv_binary_elf" = yes], [
AC_DEFINE(USE_ELF)
AC_CHECK_HEADERS([elf.h elf_abi.h])
@@ -2861,7 +2959,6 @@ AC_SUBST(CCDLFLAGS)dnl
AC_SUBST(LDSHARED)dnl
AC_SUBST(LDSHAREDXX)dnl
AC_SUBST(DLEXT)dnl
-AC_SUBST(DLEXT2)dnl
AC_SUBST(LIBEXT)dnl
AC_SUBST(ASMEXT, S)dnl
@@ -2886,7 +2983,6 @@ STATIC=
RUBY_APPEND_OPTION(CCDLFLAGS, -fPIC)])
], [
AS_CASE(["$target_os"],
- [hpux*], [CCDLFLAGS="$CCDLFLAGS +Z"],
[solaris*|irix*], [CCDLFLAGS="$CCDLFLAGS -KPIC"],
[sunos*], [CCDLFLAGS="$CCDLFLAGS -PIC"],
[esix*|uxpds*], [CCDLFLAGS="$CCDLFLAGS -KPIC"],
@@ -2894,18 +2990,25 @@ STATIC=
])
}
-: "rpath" && {
- AC_ARG_ENABLE(rpath,
- AS_HELP_STRING([--enable-rpath], [embed run path into extension libraries.
- enabled by default on ELF platforms]),
- [enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"])
+EXTSTATIC=
+AC_SUBST(EXTSTATIC)dnl
+AC_ARG_WITH(static-linked-ext,
+ AS_HELP_STRING([--with-static-linked-ext], [link external modules statically]),
+ [AS_CASE([$withval],[yes],[STATIC=;EXTSTATIC=static],[no],[],[EXTSTATIC="$withval"])])
+AS_CASE([",$EXTSTATIC,"], [,static,|*,enc,*], [
+ ENCOBJS='enc/encinit.$(OBJEXT) enc/libenc.$(LIBEXT) enc/libtrans.$(LIBEXT)'
+ EXTOBJS='ext/extinit.$(OBJEXT)'
+ AC_DEFINE_UNQUOTED(EXTSTATIC, 1)
+ AC_SUBST(ENCSTATIC, static)
+], [
+ ENCOBJS='dmyenc.$(OBJEXT)'
+ EXTOBJS='dmyext.$(OBJEXT)'
+])
+AC_SUBST(ENCOBJS)
+AC_SUBST(EXTOBJS)
- AS_CASE(["$target_os"],
- [hpux*], [ DLDFLAGS="$DLDFLAGS -E"
- : ${LDSHARED='$(LD) -b'}
- XLDFLAGS="$XLDFLAGS -Wl,-E"
- : ${LIBPATHENV=SHLIB_PATH}
- rb_cv_dlopen=yes],
+: "rpath" && {
+ AS_CASE(["$target_os"],
[solaris*], [ AS_IF([test "$GCC" = yes], [
: ${LDSHARED='$(CC) -shared'}
AS_IF([test "$rb_cv_prog_gnu_ld" = yes], [
@@ -2945,7 +3048,6 @@ STATIC=
rb_cv_dlopen=yes],
[interix*], [ : ${LDSHARED='$(CC) -shared'}
XLDFLAGS="$XLDFLAGS -Wl,-E"
- LIBPATHFLAG=" -L%1\$-s"
rb_cv_dlopen=yes],
[freebsd*|dragonfly*], [
: ${LDSHARED='$(CC) -shared'}
@@ -2964,8 +3066,16 @@ STATIC=
[darwin*], [ : ${LDSHARED='$(CC) -dynamic -bundle'}
: ${DLDSHARED='$(CC) -dynamiclib'}
: ${LDFLAGS=""}
- : ${LIBPATHENV=DYLD_FALLBACK_LIBRARY_PATH}
+ : ${LIBPATHENV=DYLD_LIBRARY_PATH}
: ${PRELOADENV=DYLD_INSERT_LIBRARIES}
+ AS_IF([test x"$enable_shared" = xyes], [
+ # Resolve symbols from libruby.dylib 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], [
@@ -2997,30 +3107,35 @@ STATIC=
[atheos*], [ : ${LDSHARED='$(CC) -shared'}
rb_cv_dlopen=yes],
[ : ${LDSHARED='$(LD)'}])
- AC_MSG_RESULT($rb_cv_dlopen)
+ AC_MSG_RESULT($rb_cv_dlopen)
+}
- AS_IF([test "$rb_cv_dlopen" = yes], [
+AS_IF([test "$rb_cv_dlopen" = yes], [
AS_CASE(["$target_os"],
- [darwin*], [
+ [darwin*], [
+ AC_SUBST(ADDITIONAL_DLDFLAGS, "")
for flag in \
- "-undefined dynamic_lookup" \
"-multiply_defined suppress" \
+ "-undefined dynamic_lookup" \
; do
- 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])
- ])
+ 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${LDSHARED@%:@*'$(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.*
done
- ])
- ])
-
- AS_IF([test "$enable_rpath:${RPATHFLAG}" = yes:], [
- AS_IF([test "x$rpathflag" != x], [
- RPATHFLAG=" ${rpathflag}%1\$-s"
- ])
- ])
-}
+ ])
+])
AS_IF([test "${LDSHAREDXX}" = ""], [
AS_CASE(["${LDSHARED}"],
@@ -3036,7 +3151,6 @@ AS_IF([test "${LDSHAREDXX}" = ""], [
[ld" "*], [
])
])
-AS_CASE([${RPATHFLAG}],[*'%1$'*],[: ${LIBPATHFLAG=' -L%1$-s'}],[: ${LIBPATHFLAG=' -L%s'}])
AC_SUBST(LINK_SO)
AC_SUBST(LIBPATHFLAG)
@@ -3045,23 +3159,6 @@ AC_SUBST(LIBPATHENV, "${LIBPATHENV-LD_LIBRARY_PATH}")
AC_SUBST(PRELOADENV, "${PRELOADENV-LD_PRELOAD}")
AC_SUBST(TRY_LINK)
-AS_IF([test "x$OPT_DIR" != x], [
- pat=`echo "${LDFLAGS_OPTDIR}" | sed ['s/[][\\.*|]/\\\\&/']`
- LDFLAGS=`echo "${LDFLAGS}" | sed "s| ${pat}||"`
- val=`IFS="$PATH_SEPARATOR"
- for dir in $OPT_DIR; do
- echo x ${LIBPATHFLAG} ${RPATHFLAG} |
- sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${dir}/lib${IFS}g;s${IFS}%s${IFS}${dir}/lib${IFS}g"
- done | tr '\012' ' ' | sed 's/ *$//'`
- AS_IF([test x"$val" != x], [
- test x"${LDFLAGS}" = x || LDFLAGS="$LDFLAGS "
- LDFLAGS="$LDFLAGS$val"
- test x"${DLDFLAGS}" = x || DLDFLAGS="$DLDFLAGS "
- DLDFLAGS="$DLDFLAGS$val"
- ])
- LDFLAGS_OPTDIR="$val"
-])
-
AS_CASE(["$target_os"],
[freebsd*], [
AC_CHECK_LIB([procstat], [procstat_open_sysctl])
@@ -3076,6 +3173,15 @@ AS_CASE(["$target_cpu-$target_os"],
AS_IF([test "x$ac_cv_header_execinfo_h" = xyes], [
AC_CHECK_LIB([execinfo], [backtrace])
AC_CHECK_HEADERS([libunwind.h])
+
+ AC_CHECK_HEADERS([mach/task.h mach/mach_init.h mach/mach_port.h])
+ AS_IF([ test \
+ "x${ac_cv_header_mach_task_h}" = xyes -a \
+ "x${ac_cv_header_mach_mach_init_h}" = xyes -a \
+ "x${ac_cv_header_mach_mach_port_h}" = xyes \
+ ], [
+ AC_DEFINE([HAVE_MACH_TASK_EXCEPTION_PORTS], [1])
+ ])
])],
[*-freebsd*|x86_64-netbsd*], [
AC_CHECK_HEADERS([execinfo.h])
@@ -3153,8 +3259,6 @@ AS_IF([test x$with_valgrind != xno],
: "dlext & soext" && {
AS_CASE(["$target_os"],
- [hpux*], [
- DLEXT=sl],
[darwin*], [
SOEXT=dylib
DLEXT=bundle],
@@ -3181,10 +3285,8 @@ AS_IF([test x"$LOAD_RELATIVE" = x1], [
len=2 # .rb
n=`expr "$DLEXT" : '.*'`; test "$n" -gt "$len" && len=$n
-n=`expr "$DLEXT2" : '.*'`; test "$n" -gt "$len" && len=$n
AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`)
test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT")
-test ".$DLEXT2" = "." || AC_DEFINE_UNQUOTED(DLEXT2, ".$DLEXT2")
AC_SUBST(DLEXT)
: "strip" && {
@@ -3209,23 +3311,6 @@ AC_ARG_WITH(ext,
AC_ARG_WITH(out-ext,
AS_HELP_STRING([--with-out-ext=EXTS],
[pass to --without-ext option of extmk.rb]))
-EXTSTATIC=
-AC_SUBST(EXTSTATIC)dnl
-AC_ARG_WITH(static-linked-ext,
- AS_HELP_STRING([--with-static-linked-ext], [link external modules statically]),
- [AS_CASE([$withval],[yes],[STATIC=;EXTSTATIC=static],[no],[],[EXTSTATIC="$withval"])])
-AS_CASE([",$EXTSTATIC,"], [,static,|*,enc,*], [
- ENCOBJS='enc/encinit.$(OBJEXT) enc/libenc.$(LIBEXT) enc/libtrans.$(LIBEXT)'
- EXTOBJS='ext/extinit.$(OBJEXT)'
- AC_DEFINE_UNQUOTED(EXTSTATIC, 1)
- AC_SUBST(ENCSTATIC, static)
-], [
- ENCOBJS='dmyenc.$(OBJEXT)'
- EXTOBJS='dmyext.$(OBJEXT)'
-])
-AC_SUBST(ENCOBJS)
-AC_SUBST(EXTOBJS)
-
AC_ARG_WITH(setup,
AS_HELP_STRING([--with-setup=SETUP], [use extension libraries setup]),
[setup=$withval])
@@ -3268,14 +3353,13 @@ AS_IF([test x"${exec_prefix}" != xNONE], [
RUBY_EXEC_PREFIX=$ac_default_prefix
])
pat=`echo "${RUBY_EXEC_PREFIX}" | tr -c '\012' .`'\(.*\)'
-for var in bindir libdir rubylibprefix; do
+for var in bindir includedir libdir rubylibprefix; do
eval val='"$'$var'"'
AS_CASE(["$val"], ["${RUBY_EXEC_PREFIX}"*], [val='${exec_prefix}'"`expr \"$val\" : \"$pat\"`"])
eval $var='"$val"'
done
BTESTRUBY='$(MINIRUBY)'
-BOOTSTRAPRUBY='$(BASERUBY)'
AS_IF([test x"$cross_compiling" = xyes], [
test x"$MINIRUBY" = x && MINIRUBY="${RUBY-$BASERUBY} -I`$CHDIR .; pwd` "-r'$(arch)-fake'
XRUBY_LIBDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["libdir"]']`
@@ -3285,6 +3369,10 @@ AS_IF([test x"$cross_compiling" = xyes], [
AC_SUBST(XRUBY_RUBYLIBDIR)
AC_SUBST(XRUBY_RUBYHDRDIR)
PREP='$(arch)-fake.rb'
+ AS_CASE(["$enable_shared:$EXTSTATIC:$target_os"], [no::darwin*], [
+ # darwin target requires miniruby for linking ext bundles
+ PREP="$PREP"' miniruby$(EXEEXT)'
+ ])
RUNRUBY_COMMAND='$(MINIRUBY) -I`cd $(srcdir)/lib; pwd`'
RUNRUBY='$(RUNRUBY_COMMAND)'
XRUBY='$(MINIRUBY)'
@@ -3298,7 +3386,6 @@ AS_IF([test x"$cross_compiling" = xyes], [
RUNRUBY_COMMAND='$(MINIRUBY) $(tooldir)/runruby.rb --extout=$(EXTOUT) $(RUNRUBYOPT)'
RUNRUBY='$(RUNRUBY_COMMAND) --'
XRUBY='$(RUNRUBY)'
- AS_CASE(["$HAVE_BASERUBY:$build_os"], [no:*|*:mingw*], [BOOTSTRAPRUBY='$(MINIRUBY)'])
TEST_RUNNABLE=yes
CROSS_COMPILING=no
])
@@ -3310,7 +3397,6 @@ AC_SUBST(PREP)
AC_SUBST(RUNRUBY_COMMAND)
AC_SUBST(RUNRUBY)
AC_SUBST(XRUBY)
-AC_SUBST(BOOTSTRAPRUBY)
AC_SUBST(EXTOUT, [${EXTOUT=.ext}])
FIRSTMAKEFILE=""
@@ -3325,7 +3411,7 @@ AS_CASE(["$target_os"],
: ${DLDLIBS=""}
],
[
- DLDLIBS="$DLDLIBS -lc"
+ DLDLIBS="${DLDLIBS:+$DLDLIBS }-lc"
])
AC_ARG_ENABLE(multiarch,
@@ -3456,11 +3542,13 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_SONAME='lib$(RUBY_SO_NAME).$(SOEXT).$(RUBY_PROGRAM_VERSION)'
LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-h${linker_flag:+,}"'$(@F)'])
- XLDFLAGS="$XLDFLAGS "'-R${libdir}'
- ],
- [hpux*], [
- XLDFLAGS="$XLDFLAGS "'-Wl,+s,+b,$(libdir)'
- LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
+ AS_IF([test "$load_relative" = yes], [
+ libprefix="'\$\$ORIGIN/../${libdir_basename}'"
+ LIBRUBY_RPATHFLAGS="-R${libprefix}"
+ LIBRUBY_RELATIVE=yes
+ ], [
+ LIBRUBY_RPATHFLAGS='-R${libdir}'
+ ])
],
[aix*], [
RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-bnoentry" "$XLDFLAGS" "$LDFLAGS_OPTDIR"])
@@ -3547,7 +3635,7 @@ AS_CASE("$cross_compiling:${LIBPATHENV}", [yes:* | no:], [], [
AC_MSG_CHECKING(whether wrapper for $LIBPATHENV is needed)
AS_IF([env ${LIBPATHENV}=/lib /bin/sh -c ': ${'${LIBPATHENV}'?}' 2>/dev/null],
[AC_MSG_RESULT(no)],
- [PREP="$PREP"' exe/$(PROGRAM)'
+ [AC_SUBST(XRUBY_LIBPATHENV_WRAPPER, 'exe/$(PROGRAM)')
AC_MSG_RESULT(yes)]
)
])
@@ -3662,27 +3750,140 @@ AS_CASE(["$RDOCTARGET:$CAPITARGET"],[nodoc:nodoc],[INSTALLDOC=nodoc],[INSTALLDOC
AC_SUBST(INSTALLDOC)
AC_ARG_ENABLE(jit-support,
- AS_HELP_STRING([--disable-jit-support], [disable JIT features]),
- [MJIT_SUPPORT=$enableval
- AS_IF([test x"$enable_jit_support" = "xyes"],
- [AC_DEFINE(USE_MJIT, 1)],
- [AC_DEFINE(USE_MJIT, 0)])],
- [MJIT_SUPPORT=yes
- AC_DEFINE(USE_MJIT, 1)])
+ AS_HELP_STRING([--disable-jit-support], [disable JIT features]),
+ [MJIT_SUPPORT=$enableval],
+ [AS_CASE(["$target_os"],
+ [wasi | mingw* | solaris*], [MJIT_SUPPORT=no],
+ [MJIT_SUPPORT=yes]
+ )])
+
+AS_IF([test x"$MJIT_SUPPORT" = "xyes"],
+ [AC_DEFINE(USE_MJIT, 1)],
+ [AC_DEFINE(USE_MJIT, 0)])
AC_SUBST(MJIT_SUPPORT)
+AC_CHECK_PROG(RUSTC, [rustc], [rustc], [no]) dnl no ac_tool_prefix
+
+dnl check if rustc is recent enough to build YJIT (rustc >= 1.58.0)
+YJIT_RUSTC_OK=no
+AS_IF([test "$RUSTC" != "no"],
+ AC_MSG_CHECKING([whether ${RUSTC} works for YJIT])
+ YJIT_TARGET_ARCH=
+ AS_CASE(["$target_cpu"],
+ [arm64|aarch64], [YJIT_TARGET_ARCH=aarch64],
+ [x86_64], [YJIT_TARGET_ARCH=x86_64],
+ )
+ dnl Fails in case rustc target doesn't match ruby target.
+ dnl Can happen on Rosetta, for example.
+ AS_IF([echo "#[cfg(target_arch = \"$YJIT_TARGET_ARCH\")] fn main() { let x = 1; format!(\"{x}\"); }" |
+ $RUSTC - --emit asm=/dev/null 2>/dev/null],
+ [YJIT_RUSTC_OK=yes]
+ )
+ AC_MSG_RESULT($YJIT_RUSTC_OK)
+)
+
+dnl check if we can build YJIT on this target platform
+dnl we can't easily cross-compile with rustc so we don't support that
+YJIT_TARGET_OK=no
+AS_IF([test "$cross_compiling" = no],
+ AS_CASE(["$target_cpu-$target_os"],
+ [*android*], [
+ YJIT_TARGET_OK=no
+ ],
+ [arm64-darwin*|aarch64-darwin*|x86_64-darwin*], [
+ YJIT_TARGET_OK=yes
+ ],
+ [arm64-*linux*|aarch64-*linux*|x86_64-*linux*], [
+ YJIT_TARGET_OK=yes
+ ],
+ [arm64-*bsd*|aarch64-*bsd*|x86_64-*bsd*], [
+ YJIT_TARGET_OK=yes
+ ]
+ )
+)
+
+dnl build YJIT in release mode if rustc >= 1.58.0 is present and we are on a supported platform
+AC_ARG_ENABLE(yjit,
+ AS_HELP_STRING([--enable-yjit],
+ [enable in-process JIT compiler that requires Rust build tools. enabled by default on supported platforms if rustc 1.58.0+ is available]),
+ [YJIT_SUPPORT=$enableval],
+ [AS_CASE(["$enable_jit_support:$YJIT_TARGET_OK:$YJIT_RUSTC_OK"],
+ [yes:yes:yes|:yes:yes], [
+ YJIT_SUPPORT=yes
+ ],
+ [YJIT_SUPPORT=no]
+ )]
+)
+
+CARGO=
+CARGO_BUILD_ARGS=
+YJIT_LIBS=
+AS_CASE(["${YJIT_SUPPORT}"],
+[yes|dev|stats|dev_nodebug], [
+ AS_IF([test x"$enable_jit_support" = "xno"],
+ AC_MSG_ERROR([--disable-jit-support but --enable-yjit. YJIT requires JIT support])
+ )
+ AS_IF([test x"$RUSTC" = "xno"],
+ AC_MSG_ERROR([rustc is required. Installation instructions available at https://www.rust-lang.org/tools/install])
+ )
+
+ AS_CASE(["${YJIT_SUPPORT}"],
+ [yes], [
+ rb_rust_target_subdir=release
+ ],
+ [dev], [
+ rb_rust_target_subdir=debug
+ CARGO_BUILD_ARGS='--features stats,disasm'
+ AC_DEFINE(RUBY_DEBUG, 1)
+ ],
+ [dev_nodebug], [
+ rb_rust_target_subdir=dev_nodebug
+ CARGO_BUILD_ARGS='--profile dev_nodebug --features stats,disasm'
+ ],
+ [stats], [
+ rb_rust_target_subdir=stats
+ CARGO_BUILD_ARGS='--profile stats --features stats'
+ AC_DEFINE(YJIT_STATS, 1)
+ ])
+
+ AS_IF([test -n "${CARGO_BUILD_ARGS}"], [
+ AC_CHECK_TOOL(CARGO, [cargo], [no])
+ AS_IF([test x"$CARGO" = "xno"],
+ AC_MSG_ERROR([cargo is required. Installation instructions available at https://www.rust-lang.org/tools/install])
+ ]))
+
+ YJIT_LIBS="yjit/target/${rb_rust_target_subdir}/libyjit.a"
+ AS_CASE(["$target_os"],[openbsd*],[
+ # Link libc++abi (which requires libpthread) for _Unwind_* functions needed by yjit
+ LDFLAGS="$LDFLAGS -lpthread -lc++abi"
+ ])
+ YJIT_OBJ='yjit.$(OBJEXT)'
+ AS_IF([test x"$YJIT_SUPPORT" != "xyes" ], [
+ AC_DEFINE_UNQUOTED(YJIT_SUPPORT, [$YJIT_SUPPORT])
+ ])
+ AC_DEFINE(USE_YJIT, 1)
+], [AC_DEFINE(USE_YJIT, 0)])
+
+dnl These variables end up in ::RbConfig::CONFIG
+AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes
+AC_SUBST(RUSTC)dnl Rust compiler command
+AC_SUBST(CARGO)dnl Cargo command for Rust builds
+AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
+AC_SUBST(YJIT_LIBS)dnl for optionally building the Rust parts of YJIT
+AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT
+
AC_ARG_ENABLE(install-static-library,
AS_HELP_STRING([--disable-install-static-library], [do not install static ruby library]),
- [INSTALL_STATIC_LIBRARY=$enableval],
+ [INSTALL_STATIC_LIBRARY=$enableval
+ AS_IF([test x"$enable_shared" = xno -a x"$INSTALL_STATIC_LIBRARY" = xno],
+ [AC_MSG_ERROR([must install either static or shared library])],
+ [])],
AS_IF([test x"$enable_shared" = xyes],
[INSTALL_STATIC_LIBRARY=no],
[INSTALL_STATIC_LIBRARY=yes]))
AC_SUBST(INSTALL_STATIC_LIBRARY)
-AS_IF([test "$rb_with_pthread" = "yes"], [
- THREAD_MODEL=pthread
-])
AC_CACHE_CHECK([for prefix of external symbols], rb_cv_symbol_prefix, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[extern void conftest_external(void) {}]], [[]])],[
rb_cv_symbol_prefix=`$NM conftest.$ac_objext |
@@ -3708,13 +3909,26 @@ AS_CASE(["$target_os"],
],
[darwin*], [
RUBY_APPEND_OPTION(CFLAGS, -pipe)
+ AC_MSG_CHECKING([whether Security framework is needed])
AC_COMPILE_IFELSE([
- AC_LANG_BOOL_COMPILE_TRY([@%:@include <AvailabilityMacros.h>],
- [MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 &&
- MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10])],
+ AC_LANG_BOOL_COMPILE_TRY([
+@%:@include <AvailabilityMacros.h>
+enum {
+ least = MAC_OS_X_VERSION_10_7, /* just fail if undefined */
+ required = MAC_OS_X_VERSION_MIN_REQUIRED,
+ upper /* bigger than MIN_REQUIRED, or */
+@%:@ifdef MAC_OS_X_VERSION_10_10
+ = MAC_OS_X_VERSION_10_10
+@%:@endif
+};],
+ [required >= least && required < upper])],
[dnl
+ AC_MSG_RESULT(yes)
RUBY_APPEND_OPTION(XLDFLAGS, [-framework Security])
RUBY_APPEND_OPTION(LIBRUBYARG_STATIC, [-framework Security])
+ ],dnl
+ [dnl
+ AC_MSG_RESULT(no)
]dnl
)
RUBY_APPEND_OPTION(XLDFLAGS, [-framework CoreFoundation])
@@ -3750,13 +3964,12 @@ AS_CASE(["$target_os"],
LIBRUBY_DLDFLAGS="${LIBRUBY_DLDFLAGS}"' $(RUBYDEF)'
])
EXPORT_PREFIX=' '
- DLDFLAGS="${DLDFLAGS}"' $(DEFFILE)'
+ EXTDLDFLAGS='$(DEFFILE)'
AC_LIBOBJ([win32/win32])
AC_LIBOBJ([win32/file])
COMMON_LIBS=m
# COMMON_MACROS="WIN32_LEAN_AND_MEAN="
COMMON_HEADERS="winsock2.h windows.h"
- THREAD_MODEL=win32
PLATFORM_DIR=win32
])
LIBRUBY_ALIASES=''
@@ -3769,21 +3982,20 @@ AS_CASE(["$target_os"],
LIBRUBYARG='-l$(RUBY_SO_NAME)'
])
],
- [hpux*], [
- AS_CASE(["$YACC"],[*yacc*], [
- XCFLAGS="$XCFLAGS -DYYMAXDEPTH=300"
- YACC="$YACC -Nl40000 -Nm40000"
- ])
+ [wasi*], [
+ FIRSTMAKEFILE=GNUmakefile:wasm/GNUmakefile.in
+ AC_LIBOBJ([wasm/missing])
+ AC_LIBOBJ([wasm/runtime])
+ AC_LIBOBJ([wasm/fiber])
+ AC_LIBOBJ([wasm/machine])
+ AC_LIBOBJ([wasm/setjmp])
+ AC_LIBOBJ([wasm/machine_core])
+ AC_LIBOBJ([wasm/setjmp_core])
+ PLATFORM_DIR=wasm
])
MINIOBJS="$MINIDLNOBJ"
-AS_CASE(["$THREAD_MODEL"],
-[pthread], [AC_CHECK_HEADERS(pthread.h)],
-[win32], [],
-[""], [AC_MSG_ERROR(thread model is missing)],
- [AC_MSG_ERROR(unknown thread model $THREAD_MODEL)])
-
AC_ARG_ENABLE(debug-env,
AS_HELP_STRING([--enable-debug-env], [enable RUBY_DEBUG environment variable]),
[AC_SUBST(ENABLE_DEBUG_ENV, yes)])
@@ -3869,7 +4081,6 @@ AS_IF([test -n "${LIBS}"], [
MAINFLAGS=`echo " $MAINLIBS " | sed "s|$libspat"'||;s/^ *//;s/ *$//'`
])
LIBRUBYARG_STATIC="${LIBRUBYARG_STATIC} \$(MAINLIBS)"
-LIBRUBYARG_SHARED="${LIBRUBYARG_SHARED} \$(MAINLIBS)"
CPPFLAGS="$CPPFLAGS "'$(DEFS)'
test -z "$CPPFLAGS" || CPPFLAGS="$CPPFLAGS "; CPPFLAGS="$CPPFLAGS"'${cppflags}'
AS_IF([test -n "${cflags+set}"], [
@@ -3925,6 +4136,7 @@ AC_SUBST(EXPORT_PREFIX)
AC_SUBST(SYMBOL_PREFIX)
AC_SUBST(MINIOBJS)
AC_SUBST(THREAD_MODEL)
+AC_SUBST(COROUTINE_TYPE, ${coroutine_type})
AC_SUBST(PLATFORM_DIR)
firstmf=`echo $FIRSTMAKEFILE | sed 's/:.*//'`
@@ -3985,6 +4197,7 @@ AS_CASE(["$ruby_version"],
AS_IF([test ${RUBY_LIB_VERSION_STYLE+set}], [
{
echo "#define RUBY_LIB_VERSION_STYLE $RUBY_LIB_VERSION_STYLE"
+ echo '@%:@include "confdefs.h"'
echo '#define STRINGIZE(x) x'
test -f revision.h -o -f "${srcdir}/revision.h" || echo '#define RUBY_REVISION 0'
echo '#include "version.h"'
@@ -4070,7 +4283,11 @@ AS_IF([test "${universal_binary-no}" = yes ], [
AC_DEFINE_UNQUOTED(RUBY_ARCH, "universal-" RUBY_PLATFORM_OS)
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "universal." RUBY_PLATFORM_CPU "-" RUBY_PLATFORM_OS)
], [
- arch="${target_cpu}-${target_os}"
+ AS_IF([test "${target_os}-${rb_cv_msvcrt}" = "mingw32-ucrt" ], [
+ arch="${target_cpu}-mingw-ucrt"
+ ], [
+ arch="${target_cpu}-${target_os}"
+ ])
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "$arch")
])
@@ -4152,6 +4369,13 @@ AS_IF([test -z "$MANTYPE"], [
])
AC_SUBST(MANTYPE)
+MKMF_VERBOSE=0
+AC_ARG_ENABLE(mkmf-verbose,
+ AS_HELP_STRING([--enable-mkmf-verbose], [enable verbose in mkmf]),
+ [MKMF_VERBOSE=1],
+ [MKMF_VERBOSE=0])
+AC_SUBST(MKMF_VERBOSE)
+
AC_ARG_ENABLE(rubygems,
AS_HELP_STRING([--disable-rubygems], [disable rubygems by default]),
[enable_rubygems="$enableval"], [enable_rubygems=yes])
@@ -4205,14 +4429,21 @@ AS_MESSAGE([$PACKAGE library version = $ruby_version])
AS_IF([test x"$CC_WRAPPER" != x], [
CC='$(CC_WRAPPER) '"${CC@%:@$CC_WRAPPER }"
CPP='$(CC_WRAPPER) '"${CPP@%:@$CC_WRAPPER }"
- CC_WRAPPER='$(rubyarchdir)/darwin-cc'
- XCC_WRAPPER='$(top_srcdir)/tool/darwin-cc'
+ XCC_WRAPPER="$CC_WRAPPER"
])
AC_SUBST(CC_WRAPPER, '')
AC_SUBST(XCC_WRAPPER)
AS_CASE([" $CPP "], [*" $CC "*], [CPP=`echo " $CPP " | sed "s| $CC |"' $(CC) |;s/^ *//;s/ *$//'`])
+AS_IF([test ! -f "$srcdir/revision.h"], [
+ AS_IF([test "x$HAVE_BASERUBY" = xyes], [
+ ${BASERUBY} -C "$srcdir" tool/file2lastrev.rb -q --revision.h > "$srcdir/revision.h"
+ ], [
+ touch "$srcdir/revision.h"
+ ])
+])
+
AS_IF([test x"$firstmf" != x], [
AC_CONFIG_FILES($firstmf:$firsttmpl, [], [firstmf="$firstmf" firsttmpl="$firsttmpl"])
])
@@ -4229,17 +4460,24 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
AS_CASE("$VCS",
['$(GIT)'|git], [VCSUP='$(VCS) pull --rebase $(GITPULLOPTIONS)'],
[VCSUP='$(VCS)'])
- sed -n \
- -e '[/^@%:@define \(RUBY_RELEASE_[A-Z]*\) \([0-9][0-9]*\)/]{' \
- -e 's//\1 = \2/' \
- -e '[s/ \([0-9]\)$/ 0\1/]' \
- -e p \
- -e '}' "$srcdir/version.h"
+ for f in "$srcdir/version.h" "$srcdir/revision.h"; do
+ test -f "$f" || continue
+ sed -n \
+ -e '[/^@%:@define \(RUBY_RELEASE_[A-Z]*\) \([0-9][0-9]*\)/]{' \
+ -e 's//\1 = \2/' \
+ -e '[s/ \([0-9]\)$/ 0\1/]' \
+ -e p \
+ -e '}' "$f"
+ done
sed '/^MISSING/s/\$U\././g;/^VCS *=/s#@VCS@#'"$VCS"'#;/^VCSUP *=/s#@VCSUP@#'"$VCSUP"'#' Makefile
echo; test x"$EXEEXT" = x || echo 'miniruby: miniruby$(EXEEXT)'
AS_IF([test "$gnumake" != yes], [
echo ['$(MKFILES): $(srcdir)/common.mk']
sed ['s/{\$([^(){}]*)[^{}]*}//g'] ${srcdir}/common.mk
+ AS_IF([test "$YJIT_SUPPORT" = yes], [
+ cat ${srcdir}/yjit/not_gmake.mk
+ echo ['$(MKFILES): ${srcdir}/yjit/not_gmake.mk']
+ ])
], [
echo 'distclean-local::; @$(RM) GNUmakefile uncommon.mk'
])
@@ -4257,7 +4495,7 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
echo 'ruby: $(PROGRAM);' >> $tmpmk
test "$tmpmk" = "$tmpgmk" || rm -f "$tmpgmk"
]) && mv -f $tmpmk Makefile],
-[EXEEXT='$EXEEXT' MAKE='${MAKE-make}' gnumake='$gnumake' GIT='$GIT'])
+[EXEEXT='$EXEEXT' MAKE='${MAKE-make}' gnumake='$gnumake' GIT='$GIT' YJIT_SUPPORT='$YJIT_SUPPORT'])
AC_ARG_WITH([ruby-pc],
AS_HELP_STRING([--with-ruby-pc=FILENAME], [pc file basename]),
@@ -4271,21 +4509,6 @@ AC_ARG_WITH(destdir,
[DESTDIR="$withval"])
AC_SUBST(DESTDIR)
-AC_CONFIG_FILES($ruby_pc:template/ruby.pc.in,
- [
- AS_IF([sed ['s/\$(\([A-Za-z_][A-Za-z0-9_]*\))/${\1}/g;s/@[A-Za-z_][A-Za-z0-9_]*@//'] $ruby_pc > ruby.tmp.pc &&
- {
- test -z "$PKG_CONFIG" ||
- PKG_CONFIG_PATH=. $PKG_CONFIG --print-errors ruby.tmp
- }],
- [
- mv -f ruby.tmp.pc $ruby_pc
- ], [
- exit 1
- ])
- ],
- [ruby_pc='$ruby_pc' PKG_CONFIG='$PKG_CONFIG'])
-
AC_OUTPUT
}
}
@@ -4323,7 +4546,7 @@ config_summary "site libraries path" "$rubysitearchprefix"
config_summary "vendor path" "$vendordir"
config_summary "target OS" "$target_os"
config_summary "compiler" "$CC"
-config_summary "with pthread" "$enable_pthread"
+config_summary "with thread" "$THREAD_MODEL"
config_summary "with coroutine" "$coroutine_type"
config_summary "enable shared libs" "$ENABLE_SHARED"
config_summary "dynamic library ext" "$DLEXT"
@@ -4336,7 +4559,8 @@ config_summary "debugflags" "$debugflags"
config_summary "warnflags" "$warnflags"
config_summary "strip command" "$STRIP"
config_summary "install doc" "$DOCTARGETS"
-config_summary "JIT support" "$MJIT_SUPPORT"
+config_summary "MJIT support" "$MJIT_SUPPORT"
+config_summary "YJIT support" "$YJIT_SUPPORT"
config_summary "man page type" "$MANTYPE"
config_summary "search path" "$search_path"
config_summary "static-linked-ext" ${EXTSTATIC:+"yes"}
diff --git a/cont.c b/cont.c
index 51d77c6d98..5375d1945b 100644
--- a/cont.c
+++ b/cont.c
@@ -16,17 +16,28 @@
#include <sys/mman.h>
#endif
+// On Solaris, madvise() is NOT declared for SUS (XPG4v2) or later,
+// but MADV_* macros are defined when __EXTENSIONS__ is defined.
+#ifdef NEED_MADVICE_PROTOTYPE_USING_CADDR_T
+#include <sys/types.h>
+extern int madvise(caddr_t, size_t, int);
+#endif
+
#include COROUTINE_H
#include "eval_intern.h"
#include "gc.h"
#include "internal.h"
#include "internal/cont.h"
+#include "internal/error.h"
#include "internal/proc.h"
+#include "internal/sanitizers.h"
#include "internal/warnings.h"
#include "ruby/fiber/scheduler.h"
#include "mjit.h"
+#include "yjit.h"
#include "vm_core.h"
+#include "vm_sync.h"
#include "id_table.h"
#include "ractor_core.h"
@@ -55,6 +66,11 @@ static VALUE rb_cFiberPool;
#define FIBER_POOL_INITIAL_SIZE 32
#define FIBER_POOL_ALLOCATION_MAXIMUM_SIZE 1024
#endif
+#ifdef RB_EXPERIMENTAL_FIBER_POOL
+#define FIBER_POOL_ALLOCATION_FREE
+#endif
+
+#define jit_cont_enabled (mjit_enabled || rb_yjit_enabled_p())
enum context_type {
CONTINUATION_CONTEXT = 0,
@@ -184,6 +200,15 @@ struct fiber_pool {
size_t vm_stack_size;
};
+// Continuation contexts used by JITs
+struct rb_jit_cont {
+ rb_execution_context_t *ec; // continuation ec
+ struct rb_jit_cont *prev, *next; // used to form lists
+};
+
+// Doubly linked list for enumerating all on-stack ISEQs.
+static struct rb_jit_cont *first_jit_cont;
+
typedef struct rb_context_struct {
enum context_type type;
int argc;
@@ -201,8 +226,7 @@ typedef struct rb_context_struct {
rb_execution_context_t saved_ec;
rb_jmpbuf_t jmpbuf;
rb_ensure_entry_t *ensure_array;
- /* Pointer to MJIT info about the continuation. */
- struct mjit_cont *mjit_cont;
+ struct rb_jit_cont *jit_cont; // Continuation contexts for JITs
} rb_context_t;
@@ -235,7 +259,7 @@ struct rb_fiber_struct {
rb_context_t cont;
VALUE first_proc;
struct rb_fiber_struct *prev;
- VALUE resuming_fiber;
+ struct rb_fiber_struct *resuming_fiber;
BITFIELD(enum fiber_status, status, 2);
/* Whether the fiber is allowed to implicitly yield. */
@@ -248,12 +272,12 @@ struct rb_fiber_struct {
static struct fiber_pool shared_fiber_pool = {NULL, NULL, 0, 0, 0, 0};
-static ID fiber_initialize_keywords[2] = {0};
+static ID fiber_initialize_keywords[3] = {0};
/*
* FreeBSD require a first (i.e. addr) argument of mmap(2) is not NULL
* if MAP_STACK is passed.
- * http://www.FreeBSD.org/cgi/query-pr.cgi?pr=158755
+ * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=158755
*/
#if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
#define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_STACK)
@@ -264,7 +288,6 @@ static ID fiber_initialize_keywords[2] = {0};
#define ERRNOMSG strerror(errno)
// Locates the stack vacancy details for the given stack.
-// Requires that fiber_pool_vacancy fits within one page.
inline static struct fiber_pool_vacancy *
fiber_pool_vacancy_pointer(void * base, size_t size)
{
@@ -275,6 +298,24 @@ fiber_pool_vacancy_pointer(void * base, size_t size)
);
}
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+// Compute the base pointer for a vacant stack, for the area which can be poisoned.
+inline static void *
+fiber_pool_stack_poison_base(struct fiber_pool_stack * stack)
+{
+ STACK_GROW_DIR_DETECTION;
+
+ return (char*)stack->base + STACK_DIR_UPPER(RB_PAGE_SIZE, 0);
+}
+
+// Compute the size of the vacant stack, for the area that can be poisoned.
+inline static size_t
+fiber_pool_stack_poison_size(struct fiber_pool_stack * stack)
+{
+ return stack->size - RB_PAGE_SIZE;
+}
+#endif
+
// Reset the current stack pointer and available size of the given stack.
inline static void
fiber_pool_stack_reset(struct fiber_pool_stack * stack)
@@ -561,7 +602,7 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation)
VM_ASSERT(allocation->used == 0);
- if (DEBUG) fprintf(stderr, "fiber_pool_allocation_free: %p base=%p count=%"PRIuSIZE"\n", allocation, allocation->base, allocation->count);
+ if (DEBUG) fprintf(stderr, "fiber_pool_allocation_free: %p base=%p count=%"PRIuSIZE"\n", (void*)allocation, allocation->base, allocation->count);
size_t i;
for (i = 0; i < allocation->count; i += 1) {
@@ -624,6 +665,10 @@ fiber_pool_stack_acquire(struct fiber_pool * fiber_pool)
VM_ASSERT(vacancy);
VM_ASSERT(vacancy->stack.base);
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ __asan_unpoison_memory_region(fiber_pool_stack_poison_base(&vacancy->stack), fiber_pool_stack_poison_size(&vacancy->stack));
+#endif
+
// Take the top item from the free list:
fiber_pool->used += 1;
@@ -649,26 +694,45 @@ fiber_pool_stack_free(struct fiber_pool_stack * stack)
if (DEBUG) fprintf(stderr, "fiber_pool_stack_free: %p+%"PRIuSIZE" [base=%p, size=%"PRIuSIZE"]\n", base, size, stack->base, stack->size);
-#if VM_CHECK_MODE > 0 && defined(MADV_DONTNEED)
+ // The pages being used by the stack can be returned back to the system.
+ // That doesn't change the page mapping, but it does allow the system to
+ // reclaim the physical memory.
+ // Since we no longer care about the data itself, we don't need to page
+ // out to disk, since that is costly. Not all systems support that, so
+ // we try our best to select the most efficient implementation.
+ // In addition, it's actually slightly desirable to not do anything here,
+ // but that results in higher memory usage.
+
+#ifdef __wasi__
+ // WebAssembly doesn't support madvise, so we just don't do anything.
+#elif VM_CHECK_MODE > 0 && defined(MADV_DONTNEED)
// This immediately discards the pages and the memory is reset to zero.
madvise(base, size, MADV_DONTNEED);
-#elif defined(POSIX_MADV_DONTNEED)
- posix_madvise(base, size, POSIX_MADV_DONTNEED);
#elif defined(MADV_FREE_REUSABLE)
+ // Darwin / macOS / iOS.
// Acknowledge the kernel down to the task info api we make this
// page reusable for future use.
// As for MADV_FREE_REUSE below we ensure in the rare occasions the task was not
// completed at the time of the call to re-iterate.
while (madvise(base, size, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN);
#elif defined(MADV_FREE)
+ // Recent Linux.
madvise(base, size, MADV_FREE);
#elif defined(MADV_DONTNEED)
+ // Old Linux.
madvise(base, size, MADV_DONTNEED);
+#elif defined(POSIX_MADV_DONTNEED)
+ // Solaris?
+ posix_madvise(base, size, POSIX_MADV_DONTNEED);
#elif defined(_WIN32)
VirtualAlloc(base, size, MEM_RESET, PAGE_READWRITE);
// Not available in all versions of Windows.
//DiscardVirtualMemory(base, size);
#endif
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ __asan_poison_memory_region(fiber_pool_stack_poison_base(stack), fiber_pool_stack_poison_size(stack));
+#endif
}
// Release and return a stack to the vacancy list.
@@ -688,7 +752,7 @@ fiber_pool_stack_release(struct fiber_pool_stack * stack)
fiber_pool_vacancy_reset(vacancy);
// Push the vacancy into the vancancies list:
- pool->vacancies = fiber_pool_vacancy_push(vacancy, stack->pool->vacancies);
+ pool->vacancies = fiber_pool_vacancy_push(vacancy, pool->vacancies);
pool->used -= 1;
#ifdef FIBER_POOL_ALLOCATION_FREE
@@ -704,7 +768,8 @@ fiber_pool_stack_release(struct fiber_pool_stack * stack)
fiber_pool_stack_free(&vacancy->stack);
}
#else
- // This is entirely optional, but clears the dirty flag from the stack memory, so it won't get swapped to disk when there is memory pressure:
+ // This is entirely optional, but clears the dirty flag from the stack
+ // memory, so it won't get swapped to disk when there is memory pressure:
if (stack->pool->free_stacks) {
fiber_pool_stack_free(&vacancy->stack);
}
@@ -741,6 +806,20 @@ static COROUTINE
fiber_entry(struct coroutine_context * from, struct coroutine_context * to)
{
rb_fiber_t *fiber = to->argument;
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ // Address sanitizer will copy the previous stack base and stack size into
+ // the "from" fiber. `coroutine_initialize_main` doesn't generally know the
+ // stack bounds (base + size). Therefore, the main fiber `stack_base` and
+ // `stack_size` will be NULL/0. It's specifically important in that case to
+ // get the (base+size) of the previous fiber and save it, so that later when
+ // we return to the main coroutine, we don't supply (NULL, 0) to
+ // __sanitizer_start_switch_fiber which royally messes up the internal state
+ // of ASAN and causes (sometimes) the following message:
+ // "WARNING: ASan is ignoring requested __asan_handle_no_return"
+ __sanitizer_finish_switch_fiber(to->fake_stack, (const void**)&from->stack_base, &from->stack_size);
+#endif
+
rb_thread_t *thread = fiber->cont.saved_ec.thread_ptr;
#ifdef COROUTINE_PTHREAD_CONTEXT
@@ -781,7 +860,8 @@ fiber_initialize_coroutine(rb_fiber_t *fiber, size_t * vm_stack_size)
return vm_stack;
}
-// Release the stack from the fiber, it's execution context, and return it to the fiber pool.
+// Release the stack from the fiber, it's execution context, and return it to
+// the fiber pool.
static void
fiber_stack_release(rb_fiber_t * fiber)
{
@@ -948,6 +1028,8 @@ fiber_is_root_p(const rb_fiber_t *fiber)
}
#endif
+static void jit_cont_free(struct rb_jit_cont *cont);
+
static void
cont_free(void *ptr)
{
@@ -968,9 +1050,9 @@ cont_free(void *ptr)
RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr);
- if (mjit_enabled) {
- VM_ASSERT(cont->mjit_cont != NULL);
- mjit_cont_free(cont->mjit_cont);
+ if (jit_cont_enabled) {
+ VM_ASSERT(cont->jit_cont != NULL);
+ jit_cont_free(cont->jit_cont);
}
/* free rb_cont_t or rb_fiber_t */
ruby_xfree(ptr);
@@ -1052,7 +1134,7 @@ fiber_free(void *ptr)
rb_fiber_t *fiber = ptr;
RUBY_FREE_ENTER("fiber");
- if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base);
+ if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", (void *)fiber, fiber->stack.base);
if (fiber->cont.saved_ec.local_storage) {
rb_id_table_free(fiber->cont.saved_ec.local_storage);
@@ -1075,7 +1157,9 @@ fiber_memsize(const void *ptr)
*/
if (saved_ec->local_storage && fiber != th->root_fiber) {
size += rb_id_table_memsize(saved_ec->local_storage);
+ size += rb_obj_memsize_of(saved_ec->storage);
}
+
size += cont_memsize(&fiber->cont);
return size;
}
@@ -1110,6 +1194,7 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
}
FLUSH_REGISTER_WINDOWS;
+ asan_unpoison_memory_region(cont->machine.stack_src, size, false);
MEMCPY(cont->machine.stack, cont->machine.stack_src, VALUE, size);
}
@@ -1134,15 +1219,112 @@ cont_save_thread(rb_context_t *cont, rb_thread_t *th)
sec->machine.stack_end = NULL;
}
+static rb_nativethread_lock_t jit_cont_lock;
+
+// Register a new continuation with execution context `ec`. Return JIT info about
+// the continuation.
+static struct rb_jit_cont *
+jit_cont_new(rb_execution_context_t *ec)
+{
+ struct rb_jit_cont *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 rb_jit_cont));
+ if (cont == NULL)
+ rb_memerror();
+ cont->ec = ec;
+
+ rb_native_mutex_lock(&jit_cont_lock);
+ if (first_jit_cont == NULL) {
+ cont->next = cont->prev = NULL;
+ }
+ else {
+ cont->prev = NULL;
+ cont->next = first_jit_cont;
+ first_jit_cont->prev = cont;
+ }
+ first_jit_cont = cont;
+ rb_native_mutex_unlock(&jit_cont_lock);
+
+ return cont;
+}
+
+// Unregister continuation `cont`.
+static void
+jit_cont_free(struct rb_jit_cont *cont)
+{
+ if (!cont) return;
+
+ rb_native_mutex_lock(&jit_cont_lock);
+ if (cont == first_jit_cont) {
+ first_jit_cont = cont->next;
+ if (first_jit_cont != NULL)
+ first_jit_cont->prev = NULL;
+ }
+ else {
+ cont->prev->next = cont->next;
+ if (cont->next != NULL)
+ cont->next->prev = cont->prev;
+ }
+ rb_native_mutex_unlock(&jit_cont_lock);
+
+ free(cont);
+}
+
+// Call a given callback against all on-stack ISEQs.
+void
+rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data)
+{
+ struct rb_jit_cont *cont;
+ for (cont = first_jit_cont; cont != NULL; cont = cont->next) {
+ if (cont->ec->vm_stack == NULL)
+ continue;
+
+ const rb_control_frame_t *cfp;
+ for (cfp = RUBY_VM_END_CONTROL_FRAME(cont->ec) - 1; ; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
+ const rb_iseq_t *iseq;
+ if (cfp->pc && (iseq = cfp->iseq) != NULL && imemo_type((VALUE)iseq) == imemo_iseq) {
+ callback(iseq, data);
+ }
+
+ if (cfp == cont->ec->cfp)
+ break; // reached the most recent cfp
+ }
+ }
+}
+
+// Finish working with jit_cont.
+void
+rb_jit_cont_finish(void)
+{
+ if (!jit_cont_enabled)
+ return;
+
+ struct rb_jit_cont *cont, *next;
+ for (cont = first_jit_cont; cont != NULL; cont = next) {
+ next = cont->next;
+ free(cont); // Don't use xfree because it's allocated by calloc.
+ }
+ rb_native_mutex_destroy(&jit_cont_lock);
+}
+
static void
-cont_init_mjit_cont(rb_context_t *cont)
+cont_init_jit_cont(rb_context_t *cont)
{
- VM_ASSERT(cont->mjit_cont == NULL);
- if (mjit_enabled) {
- cont->mjit_cont = mjit_cont_new(&(cont->saved_ec));
+ VM_ASSERT(cont->jit_cont == NULL);
+ if (jit_cont_enabled) {
+ cont->jit_cont = jit_cont_new(&(cont->saved_ec));
}
}
+struct rb_execution_context_struct *
+rb_fiberptr_get_ec(struct rb_fiber_struct *fiber)
+{
+ return &fiber->cont.saved_ec;
+}
+
static void
cont_init(rb_context_t *cont, rb_thread_t *th)
{
@@ -1152,7 +1334,7 @@ cont_init(rb_context_t *cont, rb_thread_t *th)
cont->saved_ec.local_storage = NULL;
cont->saved_ec.local_storage_recursive_hash = Qnil;
cont->saved_ec.local_storage_recursive_hash_for_trace = Qnil;
- cont_init_mjit_cont(cont);
+ cont_init_jit_cont(cont);
}
static rb_context_t *
@@ -1181,11 +1363,15 @@ 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.
+// Start working with jit_cont.
void
-rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber)
+rb_jit_cont_init(void)
{
- cont_init_mjit_cont(&fiber->cont);
+ if (!jit_cont_enabled)
+ return;
+
+ rb_native_mutex_initialize(&jit_cont_lock);
+ cont_init_jit_cont(&GET_EC()->fiber_ptr->cont);
}
#if 0
@@ -1208,17 +1394,14 @@ show_vm_pcs(const rb_control_frame_t *cfp,
while (cfp != end_of_cfp) {
int pc = 0;
if (cfp->iseq) {
- pc = cfp->pc - cfp->iseq->body->iseq_encoded;
+ pc = cfp->pc - ISEQ_BODY(cfp->iseq)->iseq_encoded;
}
fprintf(stderr, "%2d pc: %d\n", i++, pc);
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
}
#endif
-COMPILER_WARNING_PUSH
-#ifdef __clang__
-COMPILER_WARNING_IGNORED(-Wduplicate-decl-specifier)
-#endif
+
static VALUE
cont_capture(volatile int *volatile stat)
{
@@ -1262,7 +1445,7 @@ cont_capture(volatile int *volatile stat)
entry = cont->ensure_array = ALLOC_N(rb_ensure_entry_t,size+1);
for (p=th->ec->ensure_list; p; p=p->next) {
if (!p->entry.marker)
- p->entry.marker = rb_ary_tmp_new(0); /* dummy object */
+ p->entry.marker = rb_ary_hidden_new(0); /* dummy object */
*entry++ = p->entry;
}
entry->marker = 0;
@@ -1283,7 +1466,6 @@ cont_capture(volatile int *volatile stat)
return contval;
}
}
-COMPILER_WARNING_POP
static inline void
cont_restore_thread(rb_context_t *cont)
@@ -1367,11 +1549,19 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber)
/* old_fiber->machine.stack_end should be NULL */
old_fiber->cont.saved_ec.machine.stack_end = NULL;
- // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] -> %p[%p]\n", old_fiber, old_fiber->stack.base, new_fiber, new_fiber->stack.base);
+ // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] -> %p[%p]\n", (void*)old_fiber, old_fiber->stack.base, (void*)new_fiber, new_fiber->stack.base);
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ __sanitizer_start_switch_fiber(FIBER_TERMINATED_P(old_fiber) ? NULL : &old_fiber->context.fake_stack, new_fiber->context.stack_base, new_fiber->context.stack_size);
+#endif
/* swap machine context */
struct coroutine_context * from = coroutine_transfer(&old_fiber->context, &new_fiber->context);
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ __sanitizer_finish_switch_fiber(old_fiber->context.fake_stack, NULL, NULL);
+#endif
+
if (from == NULL) {
rb_syserr_fail(errno, "coroutine_transfer");
}
@@ -1380,7 +1570,7 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber)
fiber_restore_thread(th, old_fiber);
// It's possible to get here, and new_fiber is already freed.
- // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] <- %p[%p]\n", old_fiber, old_fiber->stack.base, new_fiber, new_fiber->stack.base);
+ // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] <- %p[%p]\n", (void*)old_fiber, old_fiber->stack.base, (void*)new_fiber, new_fiber->stack.base);
}
NOINLINE(NORETURN(static void cont_restore_1(rb_context_t *)));
@@ -1391,7 +1581,7 @@ cont_restore_1(rb_context_t *cont)
cont_restore_thread(cont);
/* restore machine stack */
-#ifdef _M_AMD64
+#if defined(_M_AMD64) && !defined(__MINGW64__)
{
/* workaround for x64 SEH */
jmp_buf buf;
@@ -1431,6 +1621,10 @@ cont_restore_0(rb_context_t *cont, VALUE *addr_in_prev_frame)
if (&space[0] > end) {
# ifdef HAVE_ALLOCA
volatile VALUE *sp = ALLOCA_N(VALUE, &space[0] - end);
+ // We need to make sure that the stack pointer is moved,
+ // but some compilers may remove the allocation by optimization.
+ // We hope that the following read/write will prevent such an optimization.
+ *sp = Qfalse;
space[0] = *sp;
# else
cont_restore_0(cont, &space[0]);
@@ -1642,7 +1836,7 @@ rollback_ensure_stack(VALUE self,rb_ensure_list_t *current,rb_ensure_entry_t *ta
/* push ensure stack */
for (j = 0; j < i; j++) {
func = lookup_rollback_func(target[i - j - 1].e_proc);
- if ((VALUE)func != Qundef) {
+ if (!UNDEF_P((VALUE)func)) {
(*func)(target[i - j - 1].data2);
}
}
@@ -1767,7 +1961,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
* the current thread, blocking and non-blocking fibers' behavior is identical.
*
* Ruby doesn't provide a scheduler class: it is expected to be implemented by
- * the user and correspond to Fiber::SchedulerInterface.
+ * the user and correspond to Fiber::Scheduler.
*
* There is also Fiber.schedule method, which is expected to immediately perform
* the given block in a non-blocking manner. Its actual implementation is up to
@@ -1818,11 +2012,207 @@ fiber_t_alloc(VALUE fiber_value, unsigned int blocking)
return fiber;
}
+static rb_fiber_t *
+root_fiber_alloc(rb_thread_t *th)
+{
+ VALUE fiber_value = fiber_alloc(rb_cFiber);
+ rb_fiber_t *fiber = th->ec->fiber_ptr;
+
+ VM_ASSERT(DATA_PTR(fiber_value) == NULL);
+ VM_ASSERT(fiber->cont.type == FIBER_CONTEXT);
+ VM_ASSERT(FIBER_RESUMED_P(fiber));
+
+ th->root_fiber = fiber;
+ DATA_PTR(fiber_value) = fiber;
+ fiber->cont.self = fiber_value;
+
+ coroutine_initialize_main(&fiber->context);
+
+ return fiber;
+}
+
+static inline rb_fiber_t*
+fiber_current(void)
+{
+ rb_execution_context_t *ec = GET_EC();
+ if (ec->fiber_ptr->cont.self == 0) {
+ root_fiber_alloc(rb_ec_thread_ptr(ec));
+ }
+ return ec->fiber_ptr;
+}
+
+static inline VALUE
+current_fiber_storage(void)
+{
+ rb_execution_context_t *ec = GET_EC();
+ return ec->storage;
+}
+
+static inline VALUE
+inherit_fiber_storage(void)
+{
+ return rb_obj_dup(current_fiber_storage());
+}
+
+static inline void
+fiber_storage_set(struct rb_fiber_struct *fiber, VALUE storage)
+{
+ fiber->cont.saved_ec.storage = storage;
+}
+
+static inline VALUE
+fiber_storage_get(rb_fiber_t *fiber)
+{
+ VALUE storage = fiber->cont.saved_ec.storage;
+ if (storage == Qnil) {
+ storage = rb_hash_new();
+ fiber_storage_set(fiber, storage);
+ }
+ return storage;
+}
+
+static void
+storage_access_must_be_from_same_fiber(VALUE self)
+{
+ rb_fiber_t *fiber = fiber_ptr(self);
+ rb_fiber_t *current = fiber_current();
+ if (fiber != current) {
+ rb_raise(rb_eArgError, "Fiber storage can only be accessed from the Fiber it belongs to");
+ }
+}
+
+/**
+ * call-seq: fiber.storage -> hash (dup)
+ *
+ * Returns a copy of the storage hash for the fiber. The method can only be called on the
+ * Fiber.current.
+ */
static VALUE
-fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool, unsigned int blocking)
+rb_fiber_storage_get(VALUE self)
+{
+ storage_access_must_be_from_same_fiber(self);
+ return rb_obj_dup(fiber_storage_get(fiber_ptr(self)));
+}
+
+static int
+fiber_storage_validate_each(VALUE key, VALUE value, VALUE _argument)
+{
+ Check_Type(key, T_SYMBOL);
+
+ return ST_CONTINUE;
+}
+
+static void
+fiber_storage_validate(VALUE value)
{
+ // nil is an allowed value and will be lazily initialized.
+ if (value == Qnil) return;
+
+ if (!RB_TYPE_P(value, T_HASH)) {
+ rb_raise(rb_eTypeError, "storage must be a hash");
+ }
+
+ if (RB_OBJ_FROZEN(value)) {
+ rb_raise(rb_eFrozenError, "storage must not be frozen");
+ }
+
+ rb_hash_foreach(value, fiber_storage_validate_each, Qundef);
+}
+
+/**
+ * call-seq: fiber.storage = hash
+ *
+ * Sets the storage hash for the fiber. This feature is experimental
+ * and may change in the future. The method can only be called on the
+ * Fiber.current.
+ *
+ * You should be careful about using this method as you may inadvertently clear
+ * important fiber-storage state. You should mostly prefer to assign specific
+ * keys in the storage using Fiber::[]=.
+ *
+ * You can also use <tt>Fiber.new(storage: nil)</tt> to create a fiber with an empty
+ * storage.
+ *
+ * Example:
+ *
+ * while request = request_queue.pop
+ * # Reset the per-request state:
+ * Fiber.current.storage = nil
+ * handle_request(request)
+ * end
+ */
+static VALUE
+rb_fiber_storage_set(VALUE self, VALUE value)
+{
+ if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
+ rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL,
+ "Fiber#storage= is experimental and may be removed in the future!");
+ }
+
+ storage_access_must_be_from_same_fiber(self);
+ fiber_storage_validate(value);
+
+ fiber_ptr(self)->cont.saved_ec.storage = rb_obj_dup(value);
+ return value;
+}
+
+/**
+ * call-seq: Fiber[key] -> value
+ *
+ * Returns the value of the fiber storage variable identified by +key+.
+ *
+ * The +key+ must be a symbol, and the value is set by Fiber#[]= or
+ * Fiber#store.
+ *
+ * See also Fiber::[]=.
+ */
+static VALUE
+rb_fiber_storage_aref(VALUE class, VALUE key)
+{
+ Check_Type(key, T_SYMBOL);
+
+ VALUE storage = fiber_storage_get(fiber_current());
+
+ if (storage == Qnil) return Qnil;
+
+ return rb_hash_aref(storage, key);
+}
+
+/**
+ * call-seq: Fiber[key] = value
+ *
+ * Assign +value+ to the fiber storage variable identified by +key+.
+ * The variable is created if it doesn't exist.
+ *
+ * +key+ must be a Symbol, otherwise a TypeError is raised.
+ *
+ * See also Fiber::[].
+ */
+static VALUE
+rb_fiber_storage_aset(VALUE class, VALUE key, VALUE value)
+{
+ Check_Type(key, T_SYMBOL);
+
+ VALUE storage = fiber_storage_get(fiber_current());
+
+ return rb_hash_aset(storage, key, value);
+}
+
+static VALUE
+fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool, unsigned int blocking, VALUE storage)
+{
+ if (storage == Qundef || storage == Qtrue) {
+ // The default, inherit storage (dup) from the current fiber:
+ storage = inherit_fiber_storage();
+ }
+ else /* nil, hash, etc. */ {
+ fiber_storage_validate(storage);
+ storage = rb_obj_dup(storage);
+ }
+
rb_fiber_t *fiber = fiber_t_alloc(self, blocking);
+ fiber->cont.saved_ec.storage = storage;
fiber->first_proc = proc;
fiber->stack.base = NULL;
fiber->stack.pool = fiber_pool;
@@ -1855,54 +2245,90 @@ rb_fiber_pool_default(VALUE pool)
return &shared_fiber_pool;
}
+VALUE rb_fiber_inherit_storage(struct rb_execution_context_struct *ec, struct rb_fiber_struct *fiber)
+{
+ VALUE storage = rb_obj_dup(ec->storage);
+ fiber->cont.saved_ec.storage = storage;
+ return storage;
+}
+
/* :nodoc: */
static VALUE
rb_fiber_initialize_kw(int argc, VALUE* argv, VALUE self, int kw_splat)
{
VALUE pool = Qnil;
VALUE blocking = Qfalse;
+ VALUE storage = Qundef;
if (kw_splat != RB_NO_KEYWORDS) {
VALUE options = Qnil;
- VALUE arguments[2] = {Qundef};
+ VALUE arguments[3] = {Qundef};
argc = rb_scan_args_kw(kw_splat, argc, argv, ":", &options);
- rb_get_kwargs(options, fiber_initialize_keywords, 0, 2, arguments);
+ rb_get_kwargs(options, fiber_initialize_keywords, 0, 3, arguments);
- if (arguments[0] != Qundef) {
+ if (!UNDEF_P(arguments[0])) {
blocking = arguments[0];
}
- if (arguments[1] != Qundef) {
+ if (!UNDEF_P(arguments[1])) {
pool = arguments[1];
}
+
+ storage = arguments[2];
}
- return fiber_initialize(self, rb_block_proc(), rb_fiber_pool_default(pool), RTEST(blocking));
+ return fiber_initialize(self, rb_block_proc(), rb_fiber_pool_default(pool), RTEST(blocking), storage);
}
/*
* call-seq:
- * Fiber.new(blocking: false) { |*args| ... } -> fiber
+ * Fiber.new(blocking: false, storage: true) { |*args| ... } -> fiber
*
- * Creates new Fiber. Initially, the fiber is not running and can be resumed with
- * #resume. Arguments to the first #resume call will be passed to the block:
+ * Creates new Fiber. Initially, the fiber is not running and can be resumed
+ * with #resume. Arguments to the first #resume call will be passed to the
+ * block:
*
- * f = Fiber.new do |initial|
- * current = initial
- * loop do
- * puts "current: #{current.inspect}"
- * current = Fiber.yield
- * end
- * end
- * f.resume(100) # prints: current: 100
- * f.resume(1, 2, 3) # prints: current: [1, 2, 3]
- * f.resume # prints: current: nil
- * # ... and so on ...
- *
- * If <tt>blocking: false</tt> is passed to <tt>Fiber.new</tt>, _and_ current thread
- * has a Fiber.scheduler defined, the Fiber becomes non-blocking (see "Non-blocking
- * Fibers" section in class docs).
+ * 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 <tt>Fiber.new</tt>, _and_ current
+ * thread has a Fiber.scheduler defined, the Fiber becomes non-blocking (see
+ * "Non-blocking Fibers" section in class docs).
+ *
+ * If the <tt>storage</tt> is unspecified, the default is to inherit a copy of
+ * the storage from the current fiber. This is the same as specifying
+ * <tt>storage: true</tt>.
+ *
+ * Fiber[:x] = 1
+ * Fiber.new do
+ * Fiber[:x] # => 1
+ * Fiber[:x] = 2
+ * end.resume
+ * Fiber[:x] # => 1
+ *
+ * If the given <tt>storage</tt> is <tt>nil</tt>, this function will lazy
+ * initialize the internal storage, which starts as an empty hash.
+ *
+ * Fiber[:x] = "Hello World"
+ * Fiber.new(storage: nil) do
+ * Fiber[:x] # nil
+ * end
+ *
+ * Otherwise, the given <tt>storage</tt> is used as the new fiber's storage,
+ * and it must be an instance of Hash.
+ *
+ * Explicitly using <tt>storage: true</tt> is currently experimental and may
+ * change in the future.
*/
static VALUE
rb_fiber_initialize(int argc, VALUE* argv, VALUE self)
@@ -1911,9 +2337,15 @@ rb_fiber_initialize(int argc, VALUE* argv, VALUE self)
}
VALUE
+rb_fiber_new_storage(rb_block_call_func_t func, VALUE obj, VALUE storage)
+{
+ return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 0, storage);
+}
+
+VALUE
rb_fiber_new(rb_block_call_func_t func, VALUE obj)
{
- return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 1);
+ return rb_fiber_new_storage(func, obj, Qtrue);
}
static VALUE
@@ -1924,7 +2356,7 @@ rb_fiber_s_schedule_kw(int argc, VALUE* argv, int kw_splat)
VALUE fiber = Qnil;
if (scheduler != Qnil) {
- fiber = rb_funcall_passing_block_kw(scheduler, rb_intern("fiber"), argc, argv, kw_splat);
+ fiber = rb_fiber_scheduler_fiber(scheduler, argc, argv, kw_splat);
}
else {
rb_raise(rb_eRuntimeError, "No scheduler is available!");
@@ -1967,7 +2399,7 @@ rb_fiber_s_schedule_kw(int argc, VALUE* argv, int kw_splat)
*
* 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
+ * Fiber::Scheduler#fiber method. Ruby doesn't enforce this method to
* behave in any particular way.
*
* If the scheduler is not set, the method raises
@@ -1986,7 +2418,7 @@ rb_fiber_s_schedule(int argc, VALUE *argv, VALUE obj)
*
* Returns the Fiber scheduler, that was last set for the current thread with Fiber.set_scheduler.
* Returns +nil+ if no scheduler is set (which is the default), and non-blocking fibers'
- # behavior is the same as blocking.
+ * behavior is the same as blocking.
* (see "Non-blocking fibers" section in class docs for details about the scheduler concept).
*
*/
@@ -2020,7 +2452,7 @@ rb_fiber_current_scheduler(VALUE klass)
* 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
+ * +scheduler+ can be an object of any class corresponding to Fiber::Scheduler. Its
* implementation is up to the user.
*
* See also the "Non-blocking fibers" section in class docs.
@@ -2032,7 +2464,7 @@ rb_fiber_set_scheduler(VALUE klass, VALUE scheduler)
return rb_fiber_scheduler_set(scheduler);
}
-static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err);
+NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err));
void
rb_fiber_start(rb_fiber_t *fiber)
@@ -2087,25 +2519,7 @@ rb_fiber_start(rb_fiber_t *fiber)
rb_fiber_terminate(fiber, need_interrupt, err);
}
-static rb_fiber_t *
-root_fiber_alloc(rb_thread_t *th)
-{
- VALUE fiber_value = fiber_alloc(rb_cFiber);
- rb_fiber_t *fiber = th->ec->fiber_ptr;
-
- VM_ASSERT(DATA_PTR(fiber_value) == NULL);
- VM_ASSERT(fiber->cont.type == FIBER_CONTEXT);
- VM_ASSERT(fiber->status == FIBER_RESUMED);
-
- th->root_fiber = fiber;
- DATA_PTR(fiber_value) = fiber;
- fiber->cont.self = fiber_value;
-
- coroutine_initialize_main(&fiber->context);
-
- return fiber;
-}
-
+// Set up a "root fiber", which is the fiber that every Ractor has.
void
rb_threadptr_root_fiber_setup(rb_thread_t *th)
{
@@ -2120,9 +2534,11 @@ rb_threadptr_root_fiber_setup(rb_thread_t *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);
+ // When rb_threadptr_root_fiber_setup is called for the first time, mjit_enabled and
+ // rb_yjit_enabled_p() are still false. So this does nothing and rb_jit_cont_init() that is
+ // called later will take care of it. However, you still have to call cont_init_jit_cont()
+ // here for other Ractors, which are not initialized by rb_jit_cont_init().
+ cont_init_jit_cont(&fiber->cont);
}
void
@@ -2157,16 +2573,6 @@ rb_threadptr_root_fiber_terminate(rb_thread_t *th)
}
static inline rb_fiber_t*
-fiber_current(void)
-{
- rb_execution_context_t *ec = GET_EC();
- if (ec->fiber_ptr->cont.self == 0) {
- root_fiber_alloc(rb_ec_thread_ptr(ec));
- }
- return ec->fiber_ptr;
-}
-
-static inline rb_fiber_t*
return_fiber(bool terminate)
{
rb_fiber_t *fiber = fiber_current();
@@ -2174,7 +2580,7 @@ return_fiber(bool terminate)
if (prev) {
fiber->prev = NULL;
- prev->resuming_fiber = Qnil;
+ prev->resuming_fiber = NULL;
return prev;
}
else {
@@ -2188,9 +2594,7 @@ return_fiber(bool terminate)
VM_ASSERT(root_fiber != NULL);
// search resuming fiber
- for (fiber = root_fiber;
- RTEST(fiber->resuming_fiber);
- fiber = fiber_ptr(fiber->resuming_fiber)) {
+ for (fiber = root_fiber; fiber->resuming_fiber; fiber = fiber->resuming_fiber) {
}
return fiber;
@@ -2231,7 +2635,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 kw_splat, VALUE resuming_fiber, bool yielding)
+fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, rb_fiber_t *resuming_fiber, bool yielding)
{
VALUE value;
rb_context_t *cont = &fiber->cont;
@@ -2278,8 +2682,9 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, VALUE
rb_fiber_t *current_fiber = fiber_current();
- VM_ASSERT(!RTEST(current_fiber->resuming_fiber));
- if (RTEST(resuming_fiber)) {
+ VM_ASSERT(!current_fiber->resuming_fiber);
+
+ if (resuming_fiber) {
current_fiber->resuming_fiber = resuming_fiber;
fiber->prev = fiber_current();
fiber->yielding = 0;
@@ -2302,7 +2707,7 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, VALUE
// We cannot free the stack until the pthread is joined:
#ifndef COROUTINE_PTHREAD_CONTEXT
- if (RTEST(resuming_fiber) && FIBER_TERMINATED_P(fiber)) {
+ if (resuming_fiber && FIBER_TERMINATED_P(fiber)) {
fiber_stack_release(fiber);
}
#endif
@@ -2324,7 +2729,7 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, VALUE
VALUE
rb_fiber_transfer(VALUE fiber_value, int argc, const VALUE *argv)
{
- return fiber_switch(fiber_ptr(fiber_value), argc, argv, RB_NO_KEYWORDS, Qfalse, false);
+ return fiber_switch(fiber_ptr(fiber_value), argc, argv, RB_NO_KEYWORDS, NULL, false);
}
/*
@@ -2344,7 +2749,60 @@ rb_fiber_transfer(VALUE fiber_value, int argc, const VALUE *argv)
VALUE
rb_fiber_blocking_p(VALUE fiber)
{
- return RBOOL(fiber_ptr(fiber)->blocking != 0);
+ return RBOOL(fiber_ptr(fiber)->blocking);
+}
+
+static VALUE
+fiber_blocking_yield(VALUE fiber_value)
+{
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
+ rb_thread_t * volatile th = fiber->cont.saved_ec.thread_ptr;
+
+ // fiber->blocking is `unsigned int : 1`, so we use it as a boolean:
+ fiber->blocking = 1;
+
+ // Once the fiber is blocking, and current, we increment the thread blocking state:
+ th->blocking += 1;
+
+ return rb_yield(fiber_value);
+}
+
+static VALUE
+fiber_blocking_ensure(VALUE fiber_value)
+{
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
+ rb_thread_t * volatile th = fiber->cont.saved_ec.thread_ptr;
+
+ // We are no longer blocking:
+ fiber->blocking = 0;
+ th->blocking -= 1;
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Fiber.blocking{|fiber| ...} -> result
+ *
+ * Forces the fiber to be blocking for the duration of the block. Returns the
+ * result of the block.
+ *
+ * See the "Non-blocking fibers" section in class docs for details.
+ *
+ */
+VALUE
+rb_fiber_blocking(VALUE class)
+{
+ VALUE fiber_value = rb_fiber_current();
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
+
+ // If we are already blocking, this is essentially a no-op:
+ if (fiber->blocking) {
+ return rb_yield(fiber_value);
+ }
+ else {
+ return rb_ensure(fiber_blocking_yield, fiber_value, fiber_blocking_ensure, fiber_value);
+ }
}
/*
@@ -2399,15 +2857,15 @@ rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE error)
if (need_interrupt) RUBY_VM_SET_INTERRUPT(&next_fiber->cont.saved_ec);
if (RTEST(error))
- fiber_switch(next_fiber, -1, &error, RB_NO_KEYWORDS, Qfalse, false);
+ fiber_switch(next_fiber, -1, &error, RB_NO_KEYWORDS, NULL, false);
else
- fiber_switch(next_fiber, 1, &value, RB_NO_KEYWORDS, Qfalse, false);
+ fiber_switch(next_fiber, 1, &value, RB_NO_KEYWORDS, NULL, false);
+ ruby_stop(0);
}
-VALUE
-rb_fiber_resume_kw(VALUE fiber_value, int argc, const VALUE *argv, int kw_splat)
+static VALUE
+fiber_resume_kw(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat)
{
- rb_fiber_t *fiber = fiber_ptr(fiber_value);
rb_fiber_t *current_fiber = fiber_current();
if (argc == -1 && FIBER_CREATED_P(fiber)) {
@@ -2422,7 +2880,7 @@ rb_fiber_resume_kw(VALUE fiber_value, int argc, const VALUE *argv, int kw_splat)
else if (fiber->prev != NULL) {
rb_raise(rb_eFiberError, "attempt to resume a resumed fiber (double resume)");
}
- else if (RTEST(fiber->resuming_fiber)) {
+ else if (fiber->resuming_fiber) {
rb_raise(rb_eFiberError, "attempt to resume a resuming fiber");
}
else if (fiber->prev == NULL &&
@@ -2430,27 +2888,31 @@ rb_fiber_resume_kw(VALUE fiber_value, int argc, const VALUE *argv, int kw_splat)
rb_raise(rb_eFiberError, "attempt to resume a transferring fiber");
}
- VALUE result = fiber_switch(fiber, argc, argv, kw_splat, fiber_value, false);
+ return fiber_switch(fiber, argc, argv, kw_splat, fiber, false);
+}
- return result;
+VALUE
+rb_fiber_resume_kw(VALUE self, int argc, const VALUE *argv, int kw_splat)
+{
+ return fiber_resume_kw(fiber_ptr(self), argc, argv, kw_splat);
}
VALUE
-rb_fiber_resume(VALUE fiber_value, int argc, const VALUE *argv)
+rb_fiber_resume(VALUE self, int argc, const VALUE *argv)
{
- return rb_fiber_resume_kw(fiber_value, argc, argv, RB_NO_KEYWORDS);
+ return fiber_resume_kw(fiber_ptr(self), argc, argv, RB_NO_KEYWORDS);
}
VALUE
rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat)
{
- return fiber_switch(return_fiber(false), argc, argv, kw_splat, Qfalse, true);
+ return fiber_switch(return_fiber(false), argc, argv, kw_splat, NULL, true);
}
VALUE
rb_fiber_yield(int argc, const VALUE *argv)
{
- return fiber_switch(return_fiber(false), argc, argv, RB_NO_KEYWORDS, Qfalse, true);
+ return fiber_switch(return_fiber(false), argc, argv, RB_NO_KEYWORDS, NULL, true);
}
void
@@ -2472,7 +2934,7 @@ rb_fiber_reset_root_local_storage(rb_thread_t *th)
VALUE
rb_fiber_alive_p(VALUE fiber_value)
{
- return FIBER_TERMINATED_P(fiber_ptr(fiber_value)) ? Qfalse : Qtrue;
+ return RBOOL(!FIBER_TERMINATED_P(fiber_ptr(fiber_value)));
}
/*
@@ -2498,43 +2960,6 @@ rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber)
/*
* call-seq:
- * fiber.raise -> obj
- * fiber.raise(string) -> obj
- * fiber.raise(exception [, string [, array]]) -> obj
- *
- * Raises an exception in the fiber at the point at which the last
- * +Fiber.yield+ was called. If the fiber has not been started or has
- * already run to completion, raises +FiberError+. If the fiber is
- * yielding, it is resumed. If it is transferring, it is transferred into.
- * But if it is resuming, raises +FiberError+.
- *
- * With no arguments, raises a +RuntimeError+. With a single +String+
- * argument, raises a +RuntimeError+ with the string as a message. Otherwise,
- * the first parameter should be the name of an +Exception+ class (or an
- * object that returns an +Exception+ object when sent an +exception+
- * message). The optional second parameter sets the message associated with
- * the exception, and the third parameter is an array of callback information.
- * Exceptions are caught by the +rescue+ clause of <code>begin...end</code>
- * blocks.
- */
-static VALUE
-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);
- 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
@@ -2693,22 +3118,29 @@ rb_fiber_backtrace_locations(int argc, VALUE *argv, VALUE fiber)
*
*/
static VALUE
-rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
+rb_fiber_m_transfer(int argc, VALUE *argv, VALUE self)
{
- return rb_fiber_transfer_kw(fiber_value, argc, argv, rb_keyword_given_p());
+ return rb_fiber_transfer_kw(self, argc, argv, rb_keyword_given_p());
+}
+
+static VALUE
+fiber_transfer_kw(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat)
+{
+ if (fiber->resuming_fiber) {
+ rb_raise(rb_eFiberError, "attempt to transfer to a resuming fiber");
+ }
+
+ if (fiber->yielding) {
+ rb_raise(rb_eFiberError, "attempt to transfer to a yielding fiber");
+ }
+
+ return fiber_switch(fiber, argc, argv, kw_splat, NULL, false);
}
VALUE
-rb_fiber_transfer_kw(VALUE fiber_value, int argc, const VALUE *argv, int kw_splat)
+rb_fiber_transfer_kw(VALUE self, int argc, const VALUE *argv, int kw_splat)
{
- rb_fiber_t *fiber = fiber_ptr(fiber_value);
- 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);
+ return fiber_transfer_kw(fiber_ptr(self), argc, argv, kw_splat);
}
/*
@@ -2727,6 +3159,55 @@ rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
return rb_fiber_yield_kw(argc, argv, rb_keyword_given_p());
}
+static VALUE
+fiber_raise(rb_fiber_t *fiber, int argc, const VALUE *argv)
+{
+ VALUE exception = rb_make_exception(argc, argv);
+
+ if (fiber->resuming_fiber) {
+ rb_raise(rb_eFiberError, "attempt to raise a resuming fiber");
+ }
+ else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) {
+ return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS);
+ }
+ else {
+ return fiber_resume_kw(fiber, -1, &exception, RB_NO_KEYWORDS);
+ }
+}
+
+VALUE
+rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv)
+{
+ return fiber_raise(fiber_ptr(fiber), argc, argv);
+}
+
+/*
+ * call-seq:
+ * fiber.raise -> obj
+ * fiber.raise(string) -> obj
+ * fiber.raise(exception [, string [, array]]) -> obj
+ *
+ * Raises an exception in the fiber at the point at which the last
+ * +Fiber.yield+ was called. If the fiber has not been started or has
+ * already run to completion, raises +FiberError+. If the fiber is
+ * yielding, it is resumed. If it is transferring, it is transferred into.
+ * But if it is resuming, raises +FiberError+.
+ *
+ * With no arguments, raises a +RuntimeError+. With a single +String+
+ * argument, raises a +RuntimeError+ with the string as a message. Otherwise,
+ * the first parameter should be the name of an +Exception+ class (or an
+ * object that returns an +Exception+ object when sent an +exception+
+ * message). The optional second parameter sets the message associated with
+ * the exception, and the third parameter is an array of callback information.
+ * Exceptions are caught by the +rescue+ clause of <code>begin...end</code>
+ * blocks.
+ */
+static VALUE
+rb_fiber_m_raise(int argc, VALUE *argv, VALUE self)
+{
+ return rb_fiber_raise(self, argc, argv);
+}
+
/*
* call-seq:
* Fiber.current -> fiber
@@ -2747,7 +3228,7 @@ fiber_to_s(VALUE fiber_value)
const rb_proc_t *proc;
char status_info[0x20];
- if (RTEST(fiber->resuming_fiber)) {
+ if (fiber->resuming_fiber) {
snprintf(status_info, 0x20, " (%s by resuming)", fiber_status_name(fiber->status));
}
else {
@@ -2785,7 +3266,7 @@ fiber_pool_free(void *ptr)
struct fiber_pool * fiber_pool = ptr;
RUBY_FREE_ENTER("fiber_pool");
- fiber_pool_free_allocations(fiber_pool->allocations);
+ fiber_pool_allocation_free(fiber_pool->allocations);
ruby_xfree(fiber_pool);
RUBY_FREE_LEAVE("fiber_pool");
@@ -2811,9 +3292,9 @@ static const rb_data_type_t FiberPoolDataType = {
static VALUE
fiber_pool_alloc(VALUE klass)
{
- struct fiber_pool * fiber_pool = RB_ALLOC(struct fiber_pool);
+ struct fiber_pool *fiber_pool;
- return TypedData_Wrap_Struct(klass, &FiberPoolDataType, fiber_pool);
+ return TypedData_Make_Struct(klass, struct fiber_pool, &FiberPoolDataType, fiber_pool);
}
static VALUE
@@ -2827,7 +3308,7 @@ rb_fiber_pool_initialize(int argc, VALUE* argv, VALUE self)
rb_scan_args(argc, argv, "03", &size, &count, &vm_stack_size);
if (NIL_P(size)) {
- size = INT2NUM(th->vm->default_params.fiber_machine_stack_size);
+ size = SIZET2NUM(th->vm->default_params.fiber_machine_stack_size);
}
if (NIL_P(count)) {
@@ -2835,7 +3316,7 @@ rb_fiber_pool_initialize(int argc, VALUE* argv, VALUE self)
}
if (NIL_P(vm_stack_size)) {
- vm_stack_size = INT2NUM(th->vm->default_params.fiber_vm_stack_size);
+ vm_stack_size = SIZET2NUM(th->vm->default_params.fiber_vm_stack_size);
}
TypedData_Get_Struct(self, struct fiber_pool, &FiberPoolDataType, fiber_pool);
@@ -2859,193 +3340,6 @@ rb_fiber_pool_initialize(int argc, VALUE* argv, VALUE self)
* fiber.resume #=> FiberError: dead fiber called
*/
-/*
- * Document-class: Fiber::SchedulerInterface
- *
- * This is not an existing class, but documentation of the interface that Scheduler
- * object should comply to in order to be used as argument to Fiber.scheduler and handle non-blocking
- * fibers. See also the "Non-blocking fibers" section in Fiber class docs for explanations
- * of some concepts.
- *
- * Scheduler's behavior and usage are expected to be as follows:
- *
- * * When the execution in the non-blocking Fiber reaches some blocking operation (like
- * sleep, wait for a process, or a non-ready I/O), it calls some of the scheduler's
- * hook methods, listed below.
- * * Scheduler somehow registers what the current fiber is waiting on, and yields control
- * to other fibers with Fiber.yield (so the fiber would be suspended while expecting its
- * wait to end, and other fibers in the same thread can perform)
- * * At the end of the current thread execution, the scheduler's method #close is called
- * * The scheduler runs into a wait loop, checking all the blocked fibers (which it has
- * registered on hook calls) and resuming them when the awaited resource is ready
- * (e.g. I/O ready or sleep time elapsed).
- *
- * A typical implementation would probably rely for this closing loop on a gem like
- * EventMachine[https://github.com/eventmachine/eventmachine] or
- * Async[https://github.com/socketry/async].
- *
- * This way concurrent execution will be achieved transparently for every
- * individual Fiber's code.
- *
- * Hook methods are:
- *
- * * #io_wait
- * * #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 recommended that the scheduler implements the #fiber method, which is
- * delegated to by Fiber.schedule.
- *
- * Sample _toy_ implementation of the scheduler can be found in Ruby's code, in
- * <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 return a Process::Status instance.
- */
-static VALUE
-rb_fiber_scheduler_interface_process_wait(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#io_wait
- * call-seq: io_wait(io, events, timeout)
- *
- * Invoked by IO#wait, IO#wait_readable, IO#wait_writable to ask whether the
- * specified descriptor is ready for specified events within
- * the specified +timeout+.
- *
- * +events+ is a bit mask of <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 "which fiber wait until what
- * moment", call Fiber.yield to pass control, and then in #close resume
- * the fibers whose wait period has elapsed.
- *
- */
-static VALUE
-rb_fiber_scheduler_interface_kernel_sleep(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#block
- * call-seq: block(blocker, timeout = nil)
- *
- * Invoked by methods like Thread.join, and by Mutex, to signify that current
- * Fiber is blocked until further notice (e.g. #unblock) or until +timeout+ has
- * elapsed.
- *
- * +blocker+ is what we are waiting on, informational only (for debugging and
- * logging). There are no guarantee about its value.
- *
- * Expected to return boolean, specifying whether the blocking operation was
- * successful or not.
- */
-static VALUE
-rb_fiber_scheduler_interface_block(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#unblock
- * call-seq: unblock(blocker, fiber)
- *
- * Invoked to wake up Fiber previously blocked with #block (for example, Mutex#lock
- * calls #block and Mutex#unlock calls #unblock). The scheduler should use
- * the +fiber+ parameter to understand which fiber is unblocked.
- *
- * +blocker+ is what was awaited for, but it is informational only (for debugging
- * and logging), and it is not guaranteed to be the same value as the +blocker+ for
- * #block.
- *
- */
-static VALUE
-rb_fiber_scheduler_interface_unblock(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#fiber
- * call-seq: fiber(&block)
- *
- * Implementation of the Fiber.schedule. The method is <em>expected</em> to immediately
- * run the given block of code in a separate non-blocking fiber, and to return that Fiber.
- *
- * Minimal suggested implementation is:
- *
- * def fiber(&block)
- * fiber = Fiber.new(blocking: false, &block)
- * fiber.resume
- * fiber
- * end
- */
-static VALUE
-rb_fiber_scheduler_interface_fiber(VALUE self)
-{
-}
-#endif
-
void
Init_Cont(void)
{
@@ -3067,6 +3361,7 @@ Init_Cont(void)
fiber_initialize_keywords[0] = rb_intern_const("blocking");
fiber_initialize_keywords[1] = rb_intern_const("pool");
+ fiber_initialize_keywords[2] = rb_intern_const("storage");
const char *fiber_shared_fiber_pool_free_stacks = getenv("RUBY_SHARED_FIBER_POOL_FREE_STACKS");
if (fiber_shared_fiber_pool_free_stacks) {
@@ -3078,10 +3373,16 @@ 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_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
+ rb_define_singleton_method(rb_cFiber, "blocking", rb_fiber_blocking, 0);
+ rb_define_singleton_method(rb_cFiber, "[]", rb_fiber_storage_aref, 1);
+ rb_define_singleton_method(rb_cFiber, "[]=", rb_fiber_storage_aset, 2);
+
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, "storage", rb_fiber_storage_get, 0);
+ rb_define_method(rb_cFiber, "storage=", rb_fiber_storage_set, 1);
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
- rb_define_method(rb_cFiber, "raise", rb_fiber_raise, -1);
+ rb_define_method(rb_cFiber, "raise", rb_fiber_m_raise, -1);
rb_define_method(rb_cFiber, "backtrace", rb_fiber_backtrace, -1);
rb_define_method(rb_cFiber, "backtrace_locations", rb_fiber_backtrace_locations, -1);
rb_define_method(rb_cFiber, "to_s", fiber_to_s, 0);
@@ -3096,19 +3397,8 @@ Init_Cont(void)
rb_define_singleton_method(rb_cFiber, "schedule", rb_fiber_s_schedule, -1);
-#if 0 /* for RDoc */
- rb_cFiberScheduler = rb_define_class_under(rb_cFiber, "SchedulerInterface", rb_cObject);
- rb_define_method(rb_cFiberScheduler, "close", rb_fiber_scheduler_interface_close, 0);
- rb_define_method(rb_cFiberScheduler, "process_wait", rb_fiber_scheduler_interface_process_wait, 0);
- rb_define_method(rb_cFiberScheduler, "io_wait", rb_fiber_scheduler_interface_io_wait, 0);
- rb_define_method(rb_cFiberScheduler, "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_cFiberPool = rb_define_class_under(rb_cFiber, "Pool", rb_cObject);
rb_define_alloc_func(rb_cFiberPool, fiber_pool_alloc);
rb_define_method(rb_cFiberPool, "initialize", rb_fiber_pool_initialize, -1);
#endif
diff --git a/coroutine/amd64/Context.h b/coroutine/amd64/Context.h
index f626a47225..44daa4e01a 100644
--- a/coroutine/amd64/Context.h
+++ b/coroutine/amd64/Context.h
@@ -19,10 +19,29 @@
enum {COROUTINE_REGISTERS = 6};
+#if defined(__SANITIZE_ADDRESS__)
+ #define COROUTINE_SANITIZE_ADDRESS
+#elif defined(__has_feature)
+ #if __has_feature(address_sanitizer)
+ #define COROUTINE_SANITIZE_ADDRESS
+ #endif
+#endif
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+#include <sanitizer/common_interface_defs.h>
+#include <sanitizer/asan_interface.h>
+#endif
+
struct coroutine_context
{
void **stack_pointer;
void *argument;
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ void *fake_stack;
+ void *stack_base;
+ size_t stack_size;
+#endif
};
typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
@@ -39,6 +58,12 @@ static inline void coroutine_initialize(
) {
assert(start && stack && size >= 1024);
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ context->fake_stack = NULL;
+ context->stack_base = stack;
+ context->stack_size = size;
+#endif
+
// Stack grows down. Force 16-byte alignment.
char * top = (char*)stack + size;
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h
index dbc6ac94fb..1472621f48 100644
--- a/coroutine/arm64/Context.h
+++ b/coroutine/arm64/Context.h
@@ -19,10 +19,29 @@
enum {COROUTINE_REGISTERS = 0xb0 / 8};
+#if defined(__SANITIZE_ADDRESS__)
+ #define COROUTINE_SANITIZE_ADDRESS
+#elif defined(__has_feature)
+ #if __has_feature(address_sanitizer)
+ #define COROUTINE_SANITIZE_ADDRESS
+ #endif
+#endif
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+#include <sanitizer/common_interface_defs.h>
+#include <sanitizer/asan_interface.h>
+#endif
+
struct coroutine_context
{
void **stack_pointer;
void *argument;
+
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ void *fake_stack;
+ void *stack_base;
+ size_t stack_size;
+#endif
};
typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
@@ -39,6 +58,12 @@ static inline void coroutine_initialize(
) {
assert(start && stack && size >= 1024);
+#if defined(COROUTINE_SANITIZE_ADDRESS)
+ context->fake_stack = NULL;
+ context->stack_base = stack;
+ context->stack_size = size;
+#endif
+
// Stack grows down. Force 16-byte alignment.
char * top = (char*)stack + size;
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
diff --git a/coroutine/asyncify/Context.c b/coroutine/asyncify/Context.c
new file mode 100644
index 0000000000..303e5f4429
--- /dev/null
+++ b/coroutine/asyncify/Context.c
@@ -0,0 +1,10 @@
+#include "Context.h"
+
+void coroutine_trampoline(void * _start, void * _context)
+{
+ coroutine_start start = (coroutine_start)_start;
+ struct coroutine_context * context = _context;
+ rb_wasm_set_stack_pointer(context->current_sp);
+
+ start(context->from, context);
+}
diff --git a/coroutine/asyncify/Context.h b/coroutine/asyncify/Context.h
new file mode 100644
index 0000000000..71791a4004
--- /dev/null
+++ b/coroutine/asyncify/Context.h
@@ -0,0 +1,93 @@
+#ifndef COROUTINE_ASYNCIFY_CONTEXT_H
+#define COROUTINE_ASYNCIFY_CONTEXT_H
+
+/*
+ This is a coroutine implementation based on Binaryen's Asyncify transformation for WebAssembly.
+
+ This implementation is built on low-level ucontext-like API in wasm/fiber.c
+ This file is an adapter for the common coroutine interface and for stack manipulation.
+ wasm/fiber.c doesn't take care of stack to avoid duplicate management with this adapter.
+
+ * See also: wasm/fiber.c
+*/
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "wasm/asyncify.h"
+#include "wasm/machine.h"
+#include "wasm/fiber.h"
+
+#define COROUTINE void __attribute__((__noreturn__))
+
+static const int ASYNCIFY_CORO_DEBUG = 0;
+
+struct coroutine_context
+{
+ rb_wasm_fiber_context fc;
+ void *argument;
+ struct coroutine_context *from;
+
+ void *current_sp;
+ void *stack_base;
+ size_t size;
+};
+
+typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+
+COROUTINE coroutine_trampoline(void * _start, void * _context);
+
+static inline void coroutine_initialize_main(struct coroutine_context * context)
+{
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p)\n", __func__, context);
+ // NULL fiber entry means it's the main fiber, and handled specially.
+ rb_wasm_init_context(&context->fc, NULL, NULL, NULL);
+ // mark the main fiber has already started
+ context->fc.is_started = true;
+}
+
+static inline void coroutine_initialize(struct coroutine_context *context, coroutine_start start, void *stack, size_t size)
+{
+ // Linear stack pointer must be always aligned down to 16 bytes.
+ // https://github.com/WebAssembly/tool-conventions/blob/c74267a5897c1bdc9aa60adeaf41816387d3cd12/BasicCABI.md#the-linear-stack
+ uintptr_t sp = ((uintptr_t)stack + size) & ~0xF;
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)sp);
+ rb_wasm_init_context(&context->fc, coroutine_trampoline, start, context);
+ // record the initial stack pointer position to restore it after resumption
+ context->current_sp = (char *)sp;
+ context->stack_base = stack;
+ context->size = size;
+}
+
+static inline struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target)
+{
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (current = %p, target = %p)\n", __func__, current, target);
+ struct coroutine_context * previous = target->from;
+
+ target->from = current;
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] current->current_sp = %p -> %p\n", __func__, current->current_sp, rb_wasm_get_stack_pointer());
+ // record the current stack pointer position to restore it after resumption
+ current->current_sp = rb_wasm_get_stack_pointer();
+
+ // suspend the current coroutine and resume another coroutine
+
+ rb_wasm_swapcontext(&current->fc, &target->fc);
+
+ // after the original coroutine resumed
+
+ rb_wasm_set_stack_pointer(current->current_sp);
+
+ target->from = previous;
+
+ return target;
+}
+
+static inline void coroutine_destroy(struct coroutine_context * context)
+{
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p)\n", __func__, context);
+ context->stack_base = NULL;
+ context->size = 0;
+ context->from = NULL;
+}
+
+#endif /* COROUTINE_ASYNCIFY_CONTEXT_H */
diff --git a/coroutine/ppc/Context.S b/coroutine/ppc/Context.S
new file mode 100644
index 0000000000..cdda93e179
--- /dev/null
+++ b/coroutine/ppc/Context.S
@@ -0,0 +1,90 @@
+; Based on the code by Samuel Williams. Created by Sergey Fedorov on 04/06/2022.
+; Credits to Samuel Williams, Rei Odaira and Iain Sandoe. Errors, if any, are mine.
+; Some relevant examples: https://github.com/gcc-mirror/gcc/blob/master/libphobos/libdruntime/config/powerpc/switchcontext.S
+; https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/rs6000/darwin-gpsave.S
+; https://www.ibm.com/docs/en/aix/7.2?topic=epilogs-saving-gprs-only
+; ppc32 version may be re-written compactly with stmw/lwm, but the code wonʼt be faster, see: https://github.com/ruby/ruby/pull/5927#issuecomment-1139730541
+
+; Notice that this code is only for Darwin (macOS). Darwin ABI differs from AIX and ELF.
+; To add support for AIX, *BSD or *Linux, please make separate implementations.
+
+#define TOKEN_PASTE(x,y) x##y
+#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
+
+.machine ppc7400 ; = G4, Rosetta
+.text
+
+.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
+.align 2
+
+PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+ ; Make space on the stack for caller registers
+ ; (Should we rather use red zone? See libphobos example.)
+ subi r1,r1,80
+
+ ; Get LR
+ mflr r0
+
+ ; Save caller registers
+ stw r31,0(r1)
+ stw r30,4(r1)
+ stw r29,8(r1)
+ stw r28,12(r1)
+ stw r27,16(r1)
+ stw r26,20(r1)
+ stw r25,24(r1)
+ stw r24,28(r1)
+ stw r23,32(r1)
+ stw r22,36(r1)
+ stw r21,40(r1)
+ stw r20,44(r1)
+ stw r19,48(r1)
+ stw r18,52(r1)
+ stw r17,56(r1)
+ stw r16,60(r1)
+ stw r15,64(r1)
+ stw r14,68(r1)
+ stw r13,72(r1)
+
+ ; Save return address
+ ; Possibly should rather be saved into linkage area, see libphobos and IBM docs
+ stw r0,76(r1)
+
+ ; Save stack pointer to first argument
+ stw r1,0(r3)
+
+ ; Load stack pointer from second argument
+ lwz r1,0(r4)
+
+ ; Load return address
+ lwz r0,76(r1)
+
+ ; Restore caller registers
+ lwz r13,72(r1)
+ lwz r14,68(r1)
+ lwz r15,64(r1)
+ lwz r16,60(r1)
+ lwz r17,56(r1)
+ lwz r18,52(r1)
+ lwz r19,48(r1)
+ lwz r20,44(r1)
+ lwz r21,40(r1)
+ lwz r22,36(r1)
+ lwz r23,32(r1)
+ lwz r24,28(r1)
+ lwz r25,24(r1)
+ lwz r26,20(r1)
+ lwz r27,16(r1)
+ lwz r28,12(r1)
+ lwz r29,8(r1)
+ lwz r30,4(r1)
+ lwz r31,0(r1)
+
+ ; Set LR
+ mtlr r0
+
+ ; Pop stack frame
+ addi r1,r1,80
+
+ ; Jump to return address
+ blr
diff --git a/coroutine/ppc/Context.h b/coroutine/ppc/Context.h
new file mode 100644
index 0000000000..1fce112579
--- /dev/null
+++ b/coroutine/ppc/Context.h
@@ -0,0 +1,58 @@
+#ifndef COROUTINE_PPC_CONTEXT_H
+#define COROUTINE_PPC_CONTEXT_H 1
+
+#pragma once
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#define COROUTINE __attribute__((noreturn)) void
+#define COROUTINE_LIMITED_ADDRESS_SPACE
+
+enum {
+ COROUTINE_REGISTERS =
+ 20 /* 19 general purpose registers (r13–r31) and 1 return address */
+ + 4 /* space for fiber_entry() to store the link register */
+};
+
+struct coroutine_context
+{
+ void **stack_pointer;
+ void *argument;
+};
+
+typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+
+static inline void coroutine_initialize_main(struct coroutine_context * context) {
+ context->stack_pointer = NULL;
+}
+
+static inline void coroutine_initialize(
+ struct coroutine_context *context,
+ coroutine_start start,
+ void *stack,
+ size_t size
+) {
+ assert(start && stack && size >= 1024);
+
+ // Stack grows down. Force 16-byte alignment.
+ char * top = (char*)stack + size;
+ context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
+
+ context->stack_pointer -= COROUTINE_REGISTERS;
+ memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
+
+ /* Skip a global prologue that sets the TOC register */
+ context->stack_pointer[19] = ((char*)start) + 8;
+}
+
+struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
+
+static inline void coroutine_destroy(struct coroutine_context * context)
+{
+ context->stack_pointer = NULL;
+}
+
+#endif /* COROUTINE_PPC_CONTEXT_H */
diff --git a/coroutine/ppc64/Context.S b/coroutine/ppc64/Context.S
new file mode 100644
index 0000000000..f8561e0e7d
--- /dev/null
+++ b/coroutine/ppc64/Context.S
@@ -0,0 +1,89 @@
+; Based on the code by Samuel Williams. Created by Sergey Fedorov on 04/06/2022.
+; Credits to Samuel Williams, Rei Odaira and Iain Sandoe. Errors, if any, are mine.
+; Some relevant examples: https://github.com/gcc-mirror/gcc/blob/master/libphobos/libdruntime/config/powerpc/switchcontext.S
+; https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/rs6000/darwin-gpsave.S
+; https://www.ibm.com/docs/en/aix/7.2?topic=epilogs-saving-gprs-only
+
+; Notice that this code is only for Darwin (macOS). Darwin ABI differs from AIX and ELF.
+; To add support for AIX, *BSD or *Linux, please make separate implementations.
+
+#define TOKEN_PASTE(x,y) x##y
+#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
+
+.machine ppc64 ; = G5
+.text
+
+.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
+.align 2
+
+PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+ ; Make space on the stack for caller registers
+ ; (Should we rather use red zone? See libphobos example.)
+ subi r1,r1,160
+
+ ; Get LR
+ mflr r0
+
+ ; Save caller registers
+ std r31,0(r1)
+ std r30,8(r1)
+ std r29,16(r1)
+ std r28,24(r1)
+ std r27,32(r1)
+ std r26,40(r1)
+ std r25,48(r1)
+ std r24,56(r1)
+ std r23,64(r1)
+ std r22,72(r1)
+ std r21,80(r1)
+ std r20,88(r1)
+ std r19,96(r1)
+ std r18,104(r1)
+ std r17,112(r1)
+ std r16,120(r1)
+ std r15,128(r1)
+ std r14,136(r1)
+ std r13,144(r1)
+
+ ; Save return address
+ ; Possibly should rather be saved into linkage area, see libphobos and IBM docs
+ std r0,152(r1)
+
+ ; Save stack pointer to first argument
+ std r1,0(r3)
+
+ ; Load stack pointer from second argument
+ ld r1,0(r4)
+
+ ; Load return address
+ ld r0,152(r1)
+
+ ; Restore caller registers
+ ld r13,144(r1)
+ ld r14,136(r1)
+ ld r15,128(r1)
+ ld r16,120(r1)
+ ld r17,112(r1)
+ ld r18,104(r1)
+ ld r19,96(r1)
+ ld r20,88(r1)
+ ld r21,80(r1)
+ ld r22,72(r1)
+ ld r23,64(r1)
+ ld r24,56(r1)
+ ld r25,48(r1)
+ ld r26,40(r1)
+ ld r27,32(r1)
+ ld r28,24(r1)
+ ld r29,16(r1)
+ ld r30,8(r1)
+ ld r31,0(r1)
+
+ ; Set LR
+ mtlr r0
+
+ ; Pop stack frame
+ addi r1,r1,160
+
+ ; Jump to return address
+ blr
diff --git a/coroutine/ppc64/Context.h b/coroutine/ppc64/Context.h
new file mode 100644
index 0000000000..3e6f77f55a
--- /dev/null
+++ b/coroutine/ppc64/Context.h
@@ -0,0 +1,57 @@
+#ifndef COROUTINE_PPC64_CONTEXT_H
+#define COROUTINE_PPC64_CONTEXT_H 1
+
+#pragma once
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#define COROUTINE __attribute__((noreturn)) void
+
+enum {
+ COROUTINE_REGISTERS =
+ 20 /* 19 general purpose registers (r13–r31) and 1 return address */
+ + 4 /* space for fiber_entry() to store the link register */
+};
+
+struct coroutine_context
+{
+ void **stack_pointer;
+ void *argument;
+};
+
+typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+
+static inline void coroutine_initialize_main(struct coroutine_context * context) {
+ context->stack_pointer = NULL;
+}
+
+static inline void coroutine_initialize(
+ struct coroutine_context *context,
+ coroutine_start start,
+ void *stack,
+ size_t size
+) {
+ assert(start && stack && size >= 1024);
+
+ // Stack grows down. Force 16-byte alignment.
+ char * top = (char*)stack + size;
+ context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
+
+ context->stack_pointer -= COROUTINE_REGISTERS;
+ memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
+
+ /* Skip a global prologue that sets the TOC register */
+ context->stack_pointer[19] = ((char*)start) + 8;
+}
+
+struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
+
+static inline void coroutine_destroy(struct coroutine_context * context)
+{
+ context->stack_pointer = NULL;
+}
+
+#endif /* COROUTINE_PPC64_CONTEXT_H */
diff --git a/coroutine/universal/Context.S b/coroutine/universal/Context.S
index 0fd8c01e7f..11c80a7927 100644
--- a/coroutine/universal/Context.S
+++ b/coroutine/universal/Context.S
@@ -3,7 +3,11 @@
# include "coroutine/amd64/Context.S"
#elif defined __i386__
# include "coroutine/x86/Context.S"
-#elif defined __ppc64__
+#elif defined __ppc__
+# include "coroutine/ppc/Context.S"
+#elif defined __ppc64__ && defined(WORDS_BIGENDIAN)
+# include "coroutine/ppc64/Context.S"
+#elif defined __ppc64__ && !defined(WORDS_BIGENDIAN)
# include "coroutine/ppc64le/Context.S"
#elif defined __arm64__
# include "coroutine/arm64/Context.S"
diff --git a/coroutine/universal/Context.h b/coroutine/universal/Context.h
index 9a2ef425db..ec4d2f484a 100644
--- a/coroutine/universal/Context.h
+++ b/coroutine/universal/Context.h
@@ -6,7 +6,11 @@
# include "coroutine/amd64/Context.h"
#elif defined __i386__
# include "coroutine/x86/Context.h"
-#elif defined __ppc64__
+#elif defined __ppc__
+# include "coroutine/ppc/Context.h"
+#elif defined __ppc64__ && defined(WORDS_BIGENDIAN)
+# include "coroutine/ppc64/Context.h"
+#elif defined __ppc64__ && !defined(WORDS_BIGENDIAN)
# include "coroutine/ppc64le/Context.h"
#elif defined __arm64__
# include "coroutine/arm64/Context.h"
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index 095d9d8d1e..f342d2fcf7 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -2,20 +2,25 @@ gnumake = yes
include Makefile
-ENABLE_SHARED=@ENABLE_SHARED@
-DLLWRAP = @DLLWRAP@ --target=@target_os@ --driver-name="$(CC)"
+MUNICODE_FLAG := $(if $(filter mingw%,$(target_os)),-municode)
+override EXE_LDFLAGS += $(MUNICODE_FLAG)
+
+DLLWRAP = @DLLWRAP@ --target=$(target_os) --driver-name="$(CC)"
windres-cpp := $(CPP) -xc
windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \
$(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp)))
WINDRES = @WINDRES@ $(windres-cpp) -DRC_INVOKED
STRIP = @STRIP@
-ifeq (@target_os@,cygwin)
+ifeq ($(target_os),cygwin)
DLL_BASE_NAME := $(LIBRUBY_SO:.dll=)
else
DLL_BASE_NAME := $(RUBY_SO_NAME)
DLLWRAP += -mno-cygwin
VPATH := $(VPATH):$(srcdir)/win32
+ ifneq ($(filter -flto%,$(LDFLAGS)),)
+ miniruby$(EXEEXT): XLDFLAGS += -Wno-maybe-uninitialized
+ endif
endif
ifneq ($(ENABLE_SHARED),yes)
@@ -35,7 +40,7 @@ WPROGRAM = $(RUBYW_INSTALL_NAME)$(EXEEXT)
include $(srcdir)/template/GNUmakefile.in
-SOLIBS := $(DLL_BASE_NAME).res.@OBJEXT@ $(SOLIBS)
+SOLIBS := $(DLL_BASE_NAME).res.$(OBJEXT) $(SOLIBS)
override EXTOBJS += $(if $(filter-out $(RUBYW_INSTALL_NAME),$(@:$(EXEEXT)=)),$(RUBY_INSTALL_NAME),$(@:$(EXEEXT)=)).res.$(OBJEXT)
RCFILES = $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(DLL_BASE_NAME).rc
RUBYDEF = $(DLL_BASE_NAME).def
@@ -44,26 +49,26 @@ ruby: $(PROGRAM)
rubyw: $(WPROGRAM)
$(LIBRUBY): $(RUBY_EXP) $(LIBRUBY_SO)
-$(RUBY_EXP) $(LIBRUBY_SO): $(DLL_BASE_NAME).res.@OBJEXT@
+$(RUBY_EXP) $(LIBRUBY_SO): $(DLL_BASE_NAME).res.$(OBJEXT)
-%.res.@OBJEXT@: %.rc
+%.res.$(OBJEXT): %.rc
$(ECHO) compiling $@
$(Q) $(WINDRES) --include-dir . --include-dir $(<D) --include-dir $(srcdir)/win32 $< $@
-%.rc: $(RBCONFIG) $(srcdir)/revision.h $(srcdir)/win32/resource.rb
+%.rc: $(BOOTSTRAPRUBY_FAKE) $(RBCONFIG) $(srcdir)/revision.h $(srcdir)/win32/resource.rb
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(srcdir)/win32/resource.rb \
+ $(Q) $(BOOTSTRAPRUBY_COMMAND) $(srcdir)/win32/resource.rb \
-ruby_name=$(RUBY_INSTALL_NAME) -rubyw_name=$(RUBYW_INSTALL_NAME) \
-so_name=$(DLL_BASE_NAME) -output=$(*F) \
. $(icondirs) $(srcdir)/win32
-$(PROGRAM): $(RUBY_INSTALL_NAME).res.@OBJEXT@
-$(WPROGRAM): $(RUBYW_INSTALL_NAME).res.@OBJEXT@
+$(PROGRAM): $(RUBY_INSTALL_NAME).res.$(OBJEXT)
+$(WPROGRAM): $(RUBYW_INSTALL_NAME).res.$(OBJEXT)
@rm -f $@
$(ECHO) linking $@
- $(Q) $(PURIFY) $(CC) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \
+ $(Q) $(PURIFY) $(CC) $(MUNICODE_FLAG) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \
$(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
-$(STUBPROGRAM): $(RUBY_INSTALL_NAME).res.@OBJEXT@
+$(STUBPROGRAM): $(RUBY_INSTALL_NAME).res.$(OBJEXT)
$(RUBY_EXP): $(LIBRUBY_A)
$(ECHO) creating $@
@@ -75,7 +80,7 @@ $(RUBY_EXP): $(LIBRUBY_A)
GNUmakefile: $(srcdir)/cygwin/GNUmakefile.in
-ifeq (@target_os@,mingw32)
+ifeq ($(target_os),mingw32)
$(OBJS) $(MAINOBJ): win32.h
dir.$(OBJEXT) win32/win32.$(OBJEXT): win32/dir.h
@@ -86,16 +91,17 @@ MSYS2_ARG_CONV_EXCL_PARAM = --exclude=;--name=
yes-test-ruby: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
yes-test-all: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
yes-test-almost: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
+test/% spec/%/ spec/%_spec.rb: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
endif
$(LIBRUBY_SO): $(RUBYDEF)
-$(RUBYDEF): $(LIBRUBY_A) $(PREP) $(RBCONFIG)
+$(RUBYDEF): $(LIBRUBY_A) $(PREP) $(BOOTSTRAPRUBY_FAKE) $(RBCONFIG)
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(srcdir)/win32/mkexports.rb -output=$@ $(LIBRUBY_A)
+ $(Q) $(BOOTSTRAPRUBY_COMMAND) $(srcdir)/win32/mkexports.rb -output=$@ $(LIBRUBY_A)
clean-local::
@$(RM) $(RUBYDEF)
- @$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.@OBJEXT@)
+ @$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.$(OBJEXT))
@$(RM) $(RCFILES)
diff --git a/darray.h b/darray.h
new file mode 100644
index 0000000000..c9a53f1e01
--- /dev/null
+++ b/darray.h
@@ -0,0 +1,179 @@
+#ifndef RUBY_DARRAY_H
+#define RUBY_DARRAY_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+// Type for a dynamic array. Use to declare a dynamic array.
+// It is a pointer so it fits in st_table nicely. Designed
+// to be fairly type-safe.
+//
+// NULL is a valid empty dynamic array.
+//
+// Example:
+// rb_darray(char) char_array = NULL;
+// rb_darray_append(&char_array, 'e');
+// printf("pushed %c\n", *rb_darray_ref(char_array, 0));
+// rb_darray_free(char_array);
+//
+#define rb_darray(T) struct { rb_darray_meta_t meta; T data[]; } *
+
+// Copy an element out of the array. Warning: not bounds checked.
+//
+// T rb_darray_get(rb_darray(T) ary, size_t idx);
+//
+#define rb_darray_get(ary, idx) ((ary)->data[(idx)])
+
+// Assign to an element. Warning: not bounds checked.
+//
+// void rb_darray_set(rb_darray(T) ary, size_t idx, T element);
+//
+#define rb_darray_set(ary, idx, element) ((ary)->data[(idx)] = (element))
+
+// Get a pointer to an element. Warning: not bounds checked.
+//
+// T *rb_darray_ref(rb_darray(T) ary, size_t idx);
+//
+#define rb_darray_ref(ary, idx) (&((ary)->data[(idx)]))
+
+// Copy a new element into the array. ptr_to_ary is evaluated multiple times.
+//
+// void rb_darray_append(rb_darray(T) *ptr_to_ary, T element);
+//
+#define rb_darray_append(ptr_to_ary, element) do { \
+ rb_darray_ensure_space((ptr_to_ary), sizeof(**(ptr_to_ary)), \
+ sizeof((*(ptr_to_ary))->data[0])); \
+ rb_darray_set(*(ptr_to_ary), \
+ (*(ptr_to_ary))->meta.size, \
+ (element)); \
+ (*(ptr_to_ary))->meta.size++; \
+} while (0)
+
+
+// Last element of the array
+//
+#define rb_darray_back(ary) ((ary)->data[(ary)->meta.size - 1])
+
+// Remove the last element of the array.
+//
+#define rb_darray_pop_back(ary) ((ary)->meta.size--)
+
+// Remove element at idx and replace it by the last element
+#define rb_darray_remove_unordered(ary, idx) do { \
+ rb_darray_set(ary, idx, rb_darray_back(ary)); \
+ rb_darray_pop_back(ary); \
+} while (0);
+
+// Iterate over items of the array in a for loop
+//
+#define rb_darray_foreach(ary, idx_name, elem_ptr_var) \
+ for (size_t idx_name = 0; idx_name < rb_darray_size(ary) && ((elem_ptr_var) = rb_darray_ref(ary, idx_name)); ++idx_name)
+
+// Iterate over valid indicies in the array in a for loop
+//
+#define rb_darray_for(ary, idx_name) \
+ for (size_t idx_name = 0; idx_name < rb_darray_size(ary); ++idx_name)
+
+// Make a dynamic array of a certain size. All bytes backing the elements are set to zero.
+//
+// Note that NULL is a valid empty dynamic array.
+//
+// void rb_darray_make(rb_darray(T) *ptr_to_ary, size_t size);
+//
+#define rb_darray_make(ptr_to_ary, size) \
+ rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \
+ sizeof((*(ptr_to_ary))->data[0]))
+
+#define rb_darray_data_ptr(ary) ((ary)->data)
+
+// Set the size of the array to zero without freeing the backing memory.
+// Allows reusing the same array.
+//
+#define rb_darray_clear(ary) (ary->meta.size = 0)
+
+typedef struct rb_darray_meta {
+ size_t size;
+ size_t capa;
+} rb_darray_meta_t;
+
+// Get the size of the dynamic array.
+//
+static inline size_t
+rb_darray_size(const void *ary)
+{
+ const rb_darray_meta_t *meta = ary;
+ return meta ? meta->size : 0;
+}
+
+// Get the capacity of the dynamic array.
+//
+static inline size_t
+rb_darray_capa(const void *ary)
+{
+ const rb_darray_meta_t *meta = ary;
+ return meta ? meta->capa : 0;
+}
+
+// Free the dynamic array.
+//
+static inline void
+rb_darray_free(void *ary)
+{
+ rb_darray_meta_t *meta = ary;
+ ruby_sized_xfree(ary, meta->capa);
+}
+
+// Internal function
+// Ensure there is space for one more element.
+// Note: header_size can be bigger than sizeof(rb_darray_meta_t) when T is __int128_t, for example.
+static inline void
+rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size)
+{
+ rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
+ rb_darray_meta_t *meta = *ptr_to_ptr_to_meta;
+ size_t current_capa = rb_darray_capa(meta);
+ if (rb_darray_size(meta) < current_capa) return;
+
+ // Double the capacity
+ size_t new_capa = current_capa == 0 ? 1 : current_capa * 2;
+
+ rb_darray_meta_t *doubled_ary = rb_xrealloc_mul_add(meta, new_capa, element_size, header_size);
+ // rb_xrealloc functions guarantee that NULL is not returned
+ assert(doubled_ary != NULL);
+
+ if (meta == NULL) {
+ // First allocation. Initialize size. On subsequence allocations
+ // realloc takes care of carrying over the size.
+ doubled_ary->size = 0;
+ }
+
+ doubled_ary->capa = new_capa;
+
+ // We don't have access to the type of the dynamic array in function context.
+ // Write out result with memcpy to avoid strict aliasing issue.
+ memcpy(ptr_to_ary, &doubled_ary, sizeof(doubled_ary));
+}
+
+static inline void
+rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, size_t element_size)
+{
+ rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
+ if (array_size == 0) {
+ *ptr_to_ptr_to_meta = NULL;
+ return;
+ }
+
+ rb_darray_meta_t *meta = rb_xcalloc_mul_add(array_size, element_size, header_size);
+ // rb_xcalloc functions guarantee that NULL is not returned
+ assert(meta != NULL);
+
+ meta->size = array_size;
+ meta->capa = array_size;
+
+ // We don't have access to the type of the dynamic array in function context.
+ // Write out result with memcpy to avoid strict aliasing issue.
+ memcpy(ptr_to_ary, &meta, sizeof(meta));
+}
+
+#endif /* RUBY_DARRAY_H */
diff --git a/debug.c b/debug.c
index 75d4cc6569..3dd0f71906 100644
--- a/debug.c
+++ b/debug.c
@@ -14,9 +14,9 @@
#include <stdio.h>
#include "eval_intern.h"
+#include "encindex.h"
#include "id.h"
#include "internal/signal.h"
-#include "internal/util.h"
#include "ruby/encoding.h"
#include "ruby/io.h"
#include "ruby/ruby.h"
@@ -51,31 +51,36 @@ const union {
enum ruby_coderange_type enc_coderange_types;
enum ruby_econv_flag_type econv_flag_types;
rb_econv_result_t econv_result;
+ enum ruby_preserved_encindex encoding_index;
enum ruby_robject_flags robject_flags;
+#if !USE_RVARGC
enum ruby_robject_consts robject_consts;
+#endif
enum ruby_rmodule_flags rmodule_flags;
enum ruby_rstring_flags rstring_flags;
+#if !USE_RVARGC
enum ruby_rstring_consts rstring_consts;
+#endif
enum ruby_rarray_flags rarray_flags;
enum ruby_rarray_consts rarray_consts;
enum {
- RUBY_FMODE_READABLE = FMODE_READABLE,
- RUBY_FMODE_WRITABLE = FMODE_WRITABLE,
- RUBY_FMODE_READWRITE = FMODE_READWRITE,
- RUBY_FMODE_BINMODE = FMODE_BINMODE,
- RUBY_FMODE_SYNC = FMODE_SYNC,
- RUBY_FMODE_TTY = FMODE_TTY,
- RUBY_FMODE_DUPLEX = FMODE_DUPLEX,
- RUBY_FMODE_APPEND = FMODE_APPEND,
- RUBY_FMODE_CREATE = FMODE_CREATE,
- RUBY_FMODE_NOREVLOOKUP = 0x00000100,
- RUBY_FMODE_TRUNC = FMODE_TRUNC,
- RUBY_FMODE_TEXTMODE = FMODE_TEXTMODE,
- RUBY_FMODE_PREP = 0x00010000,
- RUBY_FMODE_SETENC_BY_BOM = FMODE_SETENC_BY_BOM,
- RUBY_FMODE_UNIX = 0x00200000,
- RUBY_FMODE_INET = 0x00400000,
- RUBY_FMODE_INET6 = 0x00800000,
+ RUBY_FMODE_READABLE = FMODE_READABLE,
+ RUBY_FMODE_WRITABLE = FMODE_WRITABLE,
+ RUBY_FMODE_READWRITE = FMODE_READWRITE,
+ RUBY_FMODE_BINMODE = FMODE_BINMODE,
+ RUBY_FMODE_SYNC = FMODE_SYNC,
+ RUBY_FMODE_TTY = FMODE_TTY,
+ RUBY_FMODE_DUPLEX = FMODE_DUPLEX,
+ RUBY_FMODE_APPEND = FMODE_APPEND,
+ RUBY_FMODE_CREATE = FMODE_CREATE,
+ RUBY_FMODE_NOREVLOOKUP = 0x00000100,
+ RUBY_FMODE_TRUNC = FMODE_TRUNC,
+ RUBY_FMODE_TEXTMODE = FMODE_TEXTMODE,
+ RUBY_FMODE_PREP = 0x00010000,
+ RUBY_FMODE_SETENC_BY_BOM = FMODE_SETENC_BY_BOM,
+ RUBY_FMODE_UNIX = 0x00200000,
+ RUBY_FMODE_INET = 0x00400000,
+ RUBY_FMODE_INET6 = 0x00800000,
RUBY_NODE_TYPESHIFT = NODE_TYPESHIFT,
RUBY_NODE_TYPEMASK = NODE_TYPEMASK,
@@ -83,9 +88,9 @@ const union {
RUBY_NODE_FL_NEWLINE = NODE_FL_NEWLINE
} various;
union {
- enum imemo_type types;
- enum {RUBY_IMEMO_MASK = IMEMO_MASK} mask;
- struct RIMemo *ptr;
+ enum imemo_type types;
+ enum {RUBY_IMEMO_MASK = IMEMO_MASK} mask;
+ struct RIMemo *ptr;
} imemo;
struct RSymbol *symbol_ptr;
enum vm_call_flag_bits vm_call_flags;
@@ -97,9 +102,9 @@ int
ruby_debug_print_indent(int level, int debug_level, int indent_level)
{
if (level < debug_level) {
- fprintf(stderr, "%*s", indent_level, "");
- fflush(stderr);
- return TRUE;
+ fprintf(stderr, "%*s", indent_level, "");
+ fflush(stderr);
+ return TRUE;
}
return FALSE;
}
@@ -119,11 +124,11 @@ VALUE
ruby_debug_print_value(int level, int debug_level, const char *header, VALUE obj)
{
if (level < debug_level) {
- char buff[0x100];
- rb_raw_obj_info(buff, 0x100, obj);
+ char buff[0x100];
+ rb_raw_obj_info(buff, 0x100, obj);
- fprintf(stderr, "DBG> %s: %s\n", header, buff);
- fflush(stderr);
+ fprintf(stderr, "DBG> %s: %s\n", header, buff);
+ fflush(stderr);
}
return obj;
}
@@ -138,8 +143,8 @@ ID
ruby_debug_print_id(int level, int debug_level, const char *header, ID id)
{
if (level < debug_level) {
- fprintf(stderr, "DBG> %s: %s\n", header, rb_id2name(id));
- fflush(stderr);
+ fprintf(stderr, "DBG> %s: %s\n", header, rb_id2name(id));
+ fflush(stderr);
}
return id;
}
@@ -148,8 +153,8 @@ NODE *
ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node)
{
if (level < debug_level) {
- fprintf(stderr, "DBG> %s: %s (%u)\n", header,
- ruby_node_name(nd_type(node)), nd_line(node));
+ fprintf(stderr, "DBG> %s: %s (%u)\n", header,
+ ruby_node_name(nd_type(node)), nd_line(node));
}
return (NODE *)node;
}
@@ -179,11 +184,11 @@ ruby_env_debug_option(const char *str, int len, void *arg)
size_t retlen;
unsigned long n;
#define SET_WHEN(name, var, val) do { \
- if (len == sizeof(name) - 1 && \
- strncmp(str, (name), len) == 0) { \
- (var) = (val); \
- return 1; \
- } \
+ if (len == sizeof(name) - 1 && \
+ strncmp(str, (name), len) == 0) { \
+ (var) = (val); \
+ return 1; \
+ } \
} while (0)
#define NAME_MATCH_VALUE(name) \
((size_t)len >= sizeof(name)-1 && \
@@ -192,24 +197,24 @@ ruby_env_debug_option(const char *str, int len, void *arg)
(str[sizeof(name)-1] == '=' && \
(str += sizeof(name), len -= sizeof(name), 1))))
#define SET_UINT(val) do { \
- n = ruby_scan_digits(str, len, 10, &retlen, &ov); \
- if (!ov && retlen) { \
- val = (unsigned int)n; \
- } \
- str += retlen; \
- len -= retlen; \
+ n = ruby_scan_digits(str, len, 10, &retlen, &ov); \
+ if (!ov && retlen) { \
+ val = (unsigned int)n; \
+ } \
+ str += retlen; \
+ len -= retlen; \
} while (0)
#define SET_UINT_LIST(name, vals, num) do { \
- int i; \
- for (i = 0; i < (num); ++i) { \
- SET_UINT((vals)[i]); \
- if (!len || *str != ':') break; \
- ++str; \
- --len; \
- } \
- if (len > 0) { \
- fprintf(stderr, "ignored "name" option: `%.*s'\n", len, str); \
- } \
+ int i; \
+ for (i = 0; i < (num); ++i) { \
+ SET_UINT((vals)[i]); \
+ if (!len || *str != ':') break; \
+ ++str; \
+ --len; \
+ } \
+ if (len > 0) { \
+ fprintf(stderr, "ignored "name" option: `%.*s'\n", len, str); \
+ } \
} while (0)
#define SET_WHEN_UINT(name, vals, num, req) \
if (NAME_MATCH_VALUE(name)) SET_UINT_LIST(name, vals, num);
@@ -218,9 +223,9 @@ ruby_env_debug_option(const char *str, int len, void *arg)
SET_WHEN("core", ruby_enable_coredump, 1);
SET_WHEN("ci", ruby_on_ci, 1);
if (NAME_MATCH_VALUE("rgengc")) {
- if (!len) ruby_rgengc_debug = 1;
- else SET_UINT_LIST("rgengc", &ruby_rgengc_debug, 1);
- return 1;
+ if (!len) ruby_rgengc_debug = 1;
+ else SET_UINT_LIST("rgengc", &ruby_rgengc_debug, 1);
+ return 1;
}
#if defined _WIN32
# if RUBY_MSVCRT_VERSION >= 80
@@ -229,9 +234,9 @@ ruby_env_debug_option(const char *str, int len, void *arg)
#endif
#if defined _WIN32 || defined __CYGWIN__
if (NAME_MATCH_VALUE("codepage")) {
- if (!len) fprintf(stderr, "missing codepage argument");
- else SET_UINT_LIST("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage));
- return 1;
+ if (!len) fprintf(stderr, "missing codepage argument");
+ else SET_UINT_LIST("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage));
+ return 1;
}
#endif
return 0;
@@ -241,15 +246,11 @@ static void
set_debug_option(const char *str, int len, void *arg)
{
if (!ruby_env_debug_option(str, len, arg)) {
- fprintf(stderr, "unexpected debug option: %.*s\n", len, str);
+ fprintf(stderr, "unexpected debug option: %.*s\n", len, str);
}
}
-#ifdef USE_RUBY_DEBUG_LOG
-STATIC_ASSERT(USE_RUBY_DEBUG_LOG, USE_RUBY_DEBUG_LOG ? RUBY_DEVEL : 1);
-#endif
-
-#if RUBY_DEVEL
+#if USE_RUBY_DEBUG_LOG
static void setup_debug_log(void);
#else
#define setup_debug_log()
@@ -262,21 +263,38 @@ ruby_set_debug_option(const char *str)
setup_debug_log();
}
-#if RUBY_DEVEL
+#if USE_RUBY_DEBUG_LOG
// 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
+#define MAX_DEBUG_LOG_FILTER_LEN 0x0020
+#define MAX_DEBUG_LOG_FILTER_NUM 0x0010
enum ruby_debug_log_mode ruby_debug_log_mode;
+struct debug_log_filter {
+ enum debug_log_filter_type {
+ dlf_all,
+ dlf_file, // "file:..."
+ dlf_func, // "func:..."
+ } type;
+ bool negative;
+ char str[MAX_DEBUG_LOG_FILTER_LEN];
+};
+
+static const char *dlf_type_names[] = {
+ "all",
+ "file",
+ "func",
+};
+
static struct {
char *mem;
unsigned int cnt;
- char filters[MAX_DEBUG_LOG_FILTER][MAX_DEBUG_LOG_FILTER];
+ struct debug_log_filter filters[MAX_DEBUG_LOG_FILTER_NUM];
unsigned int filters_num;
rb_nativethread_lock_t lock;
FILE *output;
@@ -288,15 +306,86 @@ RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index)
return &debug_log.mem[MAX_DEBUG_LOG_MESSAGE_LEN * index];
}
+static enum debug_log_filter_type
+filter_type(const char *str, int *skiplen)
+{
+ if (strncmp(str, "file:", 5) == 0) {
+ *skiplen = 5;
+ return dlf_file;
+ }
+ else if(strncmp(str, "func:", 5) == 0) {
+ *skiplen = 5;
+ return dlf_func;
+ }
+ else {
+ *skiplen = 0;
+ return dlf_all;
+ }
+}
+
+static void
+setup_debug_log_filter(void)
+{
+ 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_NUM && filter_config; i++) {
+ size_t len;
+ const char *str = filter_config;
+ const char *p;
+
+ if ((p = strchr(str, ',')) == NULL) {
+ len = strlen(str);
+ filter_config = NULL;
+ }
+ else {
+ len = p - str - 1; // 1 is ','
+ filter_config = p + 1;
+ }
+
+ // positive/negative
+ if (*str == '-') {
+ debug_log.filters[i].negative = true;
+ str++;
+ }
+ else if (*str == '+') {
+ // negative is false on default.
+ str++;
+ }
+
+ // type
+ int skiplen;
+ debug_log.filters[i].type = filter_type(str, &skiplen);
+ len -= skiplen;
+
+ if (len >= MAX_DEBUG_LOG_FILTER_LEN) {
+ fprintf(stderr, "too long: %s (max:%d)\n", str, MAX_DEBUG_LOG_FILTER_LEN - 1);
+ exit(1);
+ }
+
+ // body
+ strncpy(debug_log.filters[i].str, str + skiplen, len);
+ debug_log.filters[i].str[len] = 0;
+ }
+ debug_log.filters_num = i;
+
+ for (i=0; i<debug_log.filters_num; i++) {
+ fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s (%s%s)\n", i,
+ debug_log.filters[i].str,
+ debug_log.filters[i].negative ? "-" : "",
+ dlf_type_names[debug_log.filters[i].type]);
+ }
+ }
+}
+
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) {
+ if (log_config && strlen(log_config) > 0) {
+ 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");
@@ -316,51 +405,83 @@ setup_debug_log(void)
setvbuf(debug_log.output, NULL, _IONBF, 0);
}
+ fprintf(stderr, "RUBY_DEBUG_LOG=%s %s%s%s\n", log_config,
+ (ruby_debug_log_mode & ruby_debug_log_memory) ? "[mem]" : "",
+ (ruby_debug_log_mode & ruby_debug_log_stderr) ? "[stderr]" : "",
+ (ruby_debug_log_mode & ruby_debug_log_file) ? "[file]" : "");
rb_nativethread_lock_initialize(&debug_log.lock);
+
+ setup_debug_log_filter();
}
+}
- // 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;
- }
+static bool
+check_filter(const char *str, const struct debug_log_filter *filter, bool *state)
+{
+ if (filter->negative) {
+ if (strstr(str, filter->str) == NULL) {
+ *state = true;
+ return false;
}
- 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]);
+ else {
+ *state = false;
+ return true;
+ }
+ }
+ else {
+ if (strstr(str, filter->str) != NULL) {
+ *state = true;
+ return true;
+ }
+ else {
+ *state = false;
+ return false;
}
}
}
+//
+// RUBY_DEBUG_LOG_FILTER=-foo,-bar,baz,boo
+// returns true if
+// (func_name or file_name) doesn't contain foo
+// and
+// (func_name or file_name) doesn't contain bar
+// and
+// (func_name or file_name) contains baz or boo
+//
+// RUBY_DEBUG_LOG_FILTER=foo,bar,-baz,-boo
+// retunrs true if
+// (func_name or file_name) contains foo or bar
+// or
+// (func_name or file_name) doesn't contain baz and
+// (func_name or file_name) doesn't contain boo and
+//
+// You can specify "file:" (ex file:foo) or "func:" (ex func:foo)
+// prefixes to specify the filter for.
+//
bool
-ruby_debug_log_filter(const char *func_name)
+ruby_debug_log_filter(const char *func_name, const char *file_name)
{
if (debug_log.filters_num > 0) {
+ bool state = false;
+
for (unsigned int i = 0; i<debug_log.filters_num; i++) {
- if (strstr(func_name, debug_log.filters[i]) != NULL) {
- return true;
+ const struct debug_log_filter *filter = &debug_log.filters[i];
+
+ switch (filter->type) {
+ case dlf_all:
+ if (check_filter(func_name, filter, &state)) return state;
+ if (check_filter(file_name, filter, &state)) return state;
+ break;
+ case dlf_func:
+ if (check_filter(func_name, filter, &state)) return state;
+ break;
+ case dlf_file:
+ if (check_filter(file_name, filter, &state)) return state;
+ break;
}
}
- return false;
+ return state;
}
else {
return true;
@@ -378,6 +499,7 @@ pretty_filename(const char *path)
return path;
}
+#undef ruby_debug_log
void
ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...)
{
@@ -411,36 +533,36 @@ ruby_debug_log(const char *file, int line, const char *func_name, const char *fm
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 (rb_current_execution_context(false)) {
+ // 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;
}
- }
- // thread information
- if (!rb_thread_alone()) {
+ // 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
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);
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\tth:%u", rb_th_serial(th));
if (r < 0) rb_bug("ruby_debug_log returns %d\n", r);
len += r;
}
@@ -508,4 +630,4 @@ ruby_debug_log_dump(const char *fname, unsigned int n)
fclose(fp);
}
}
-#endif // #if RUBY_DEVEL
+#endif // #if USE_RUBY_DEBUG_LOG
diff --git a/debug_counter.c b/debug_counter.c
index e7b0bb0acd..463bebf849 100644
--- a/debug_counter.c
+++ b/debug_counter.c
@@ -16,19 +16,21 @@
#if USE_DEBUG_COUNTER
-static const char *const debug_counter_names[] = {
- ""
+const char *const rb_debug_counter_names[] = {
+#define DEBUG_COUNTER_NAME_EMPTY "" /* Suppress -Wstring-concatenation */
+ DEBUG_COUNTER_NAME_EMPTY
+#undef DEBUG_COUNTER_NAME_EMPTY
#define RB_DEBUG_COUNTER(name) #name,
#include "debug_counter.h"
#undef RB_DEBUG_COUNTER
};
MJIT_SYMBOL_EXPORT_BEGIN
-size_t rb_debug_counter[numberof(debug_counter_names)];
+size_t rb_debug_counter[numberof(rb_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;
+static rb_nativethread_lock_t debug_counter_lock;
__attribute__((constructor))
static void
@@ -47,24 +49,14 @@ rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add)
rb_nativethread_lock_unlock(&debug_counter_lock);
}
-int debug_counter_disable_show_at_exit = 0;
+static int debug_counter_disable_show_at_exit = 0;
// note that this operation is not atomic.
void
ruby_debug_counter_reset(void)
{
for (int i = 0; i < RB_DEBUG_COUNTER_MAX; i++) {
- switch (i) {
- case RB_DEBUG_COUNTER_mjit_length_unit_queue:
- case RB_DEBUG_COUNTER_mjit_length_active_units:
- case RB_DEBUG_COUNTER_mjit_length_compact_units:
- case RB_DEBUG_COUNTER_mjit_length_stale_units:
- // These counters may be decreased and should not be reset.
- break;
- default:
- rb_debug_counter[i] = 0;
- break;
- }
+ rb_debug_counter[i] = 0;
}
}
@@ -75,7 +67,7 @@ ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr)
int i;
if (names_ptr != NULL) {
for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
- names_ptr[i] = debug_counter_names[i];
+ names_ptr[i] = rb_debug_counter_names[i];
}
}
if (counters_ptr != NULL) {
@@ -101,13 +93,13 @@ rb_debug_counter_show_results(const char *msg)
setlocale(LC_NUMERIC, "");
if (env == NULL || strcmp("1", env) != 0) {
- int i;
+ int i;
fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%d %s\n", getpid(), msg);
- for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
+ for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%-30s\t%'14"PRIuSIZE"\n",
- debug_counter_names[i],
- rb_debug_counter[i]);
- }
+ rb_debug_counter_names[i],
+ rb_debug_counter[i]);
+ }
}
}
diff --git a/debug_counter.h b/debug_counter.h
index 3cf80cc188..6e0b8dee60 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -97,6 +97,8 @@ RB_DEBUG_COUNTER(ccf_bmethod)
RB_DEBUG_COUNTER(ccf_opt_send)
RB_DEBUG_COUNTER(ccf_opt_call)
RB_DEBUG_COUNTER(ccf_opt_block_call)
+RB_DEBUG_COUNTER(ccf_opt_struct_aref)
+RB_DEBUG_COUNTER(ccf_opt_struct_aset)
RB_DEBUG_COUNTER(ccf_super_method)
/*
@@ -128,7 +130,6 @@ RB_DEBUG_COUNTER(frame_C2R)
/* instance variable counts
*
* * ivar_get_ic_hit/miss: ivar_get inline cache (ic) hit/miss counts (VM insn)
- * * ivar_get_ic_miss_serial: ivar_get ic miss reason by serial (VM insn)
* * ivar_get_ic_miss_unset: ... by unset (VM insn)
* * ivar_get_ic_miss_noobject: ... by "not T_OBJECT" (VM insn)
* * ivar_set_...: same counts with ivar_set (VM insn)
@@ -138,17 +139,17 @@ RB_DEBUG_COUNTER(frame_C2R)
*/
RB_DEBUG_COUNTER(ivar_get_ic_hit)
RB_DEBUG_COUNTER(ivar_get_ic_miss)
-RB_DEBUG_COUNTER(ivar_get_ic_miss_serial)
-RB_DEBUG_COUNTER(ivar_get_ic_miss_unset)
RB_DEBUG_COUNTER(ivar_get_ic_miss_noobject)
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_iv_hit)
RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject)
RB_DEBUG_COUNTER(ivar_get_base)
RB_DEBUG_COUNTER(ivar_set_base)
+RB_DEBUG_COUNTER(ivar_get_ic_miss_set)
+RB_DEBUG_COUNTER(ivar_get_cc_miss_set)
+RB_DEBUG_COUNTER(ivar_get_ic_miss_unset)
+RB_DEBUG_COUNTER(ivar_get_cc_miss_unset)
/* local variable counts
*
@@ -242,6 +243,7 @@ RB_DEBUG_COUNTER(obj_wb_unprotect)
RB_DEBUG_COUNTER(obj_obj_embed)
RB_DEBUG_COUNTER(obj_obj_transient)
RB_DEBUG_COUNTER(obj_obj_ptr)
+RB_DEBUG_COUNTER(obj_obj_too_complex)
RB_DEBUG_COUNTER(obj_str_ptr)
RB_DEBUG_COUNTER(obj_str_embed)
@@ -345,41 +347,6 @@ 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_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)
-RB_DEBUG_COUNTER(mjit_frame_JT2JT)
-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)
-RB_DEBUG_COUNTER(mjit_length_active_units)
-RB_DEBUG_COUNTER(mjit_length_compact_units)
-RB_DEBUG_COUNTER(mjit_length_stale_units)
-
-/* Other MJIT counters */
-RB_DEBUG_COUNTER(mjit_compile_failures)
-
/* load (not implemented yet) */
/*
RB_DEBUG_COUNTER(load_files)
diff --git a/defs/gmake.mk b/defs/gmake.mk
index 11e677a2d1..54fef6685f 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -7,15 +7,19 @@ MSPECOPT += $(if $(filter -j%,$(MFLAGS)),-j)
nproc = $(subst -j,,$(filter -j%,$(MFLAGS)))
ifeq ($(GITHUB_ACTIONS),true)
-override ACTIONS_GROUP = @echo "\#\#[group]$(@:yes-=)"
+override ACTIONS_GROUP = @echo "\#\#[group]$(patsubst yes-%,%,$@)"
override ACTIONS_ENDGROUP = @echo "\#\#[endgroup]"
endif
-ifneq ($(filter %darwin%,$(arch)),)
-INSTRUBY_ENV += SDKROOT=/
+ifneq ($(filter darwin%,$(target_os)),)
+# Remove debug option not to generate thousands of .dSYM
+MJIT_DEBUGFLAGS := $(filter-out -g%,$(MJIT_DEBUGFLAGS))
+
+INSTRUBY_ENV += SDKROOT=
endif
INSTRUBY_ARGS += --gnumake
+ifeq ($(DOT_WAIT),)
CHECK_TARGETS := great exam love check test check% test% btest%
# expand test targets, and those dependents
TEST_TARGETS := $(filter $(CHECK_TARGETS),$(MAKECMDGOALS))
@@ -23,7 +27,7 @@ TEST_DEPENDS := $(filter-out commit $(TEST_TARGETS),$(MAKECMDGOALS))
TEST_TARGETS := $(patsubst great,exam,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out great $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst exam,check,$(TEST_TARGETS))
-TEST_TARGETS := $(patsubst check,test-spec test-all test-tool test-short,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst check,test-syntax-suggest test-spec test-all test-tool test-short,$(TEST_TARGETS))
TEST_TARGETS := $(patsubst test-rubyspec,test-spec,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out exam check test-spec $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst love,check,$(TEST_TARGETS))
@@ -33,15 +37,16 @@ TEST_DEPENDS := $(filter-out test-all $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst test,test-short,$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out test $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_TARGETS := $(patsubst test-short,btest-ruby test-knownbug test-basic,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-run,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems-run,test-bundled-gems-run $(PREPARE_BUNDLED_GEMS),$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-bundled-gems-prepare,test-bundled-gems-prepare $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch,$(TEST_TARGETS))
+TEST_TARGETS := $(patsubst test-syntax-suggest,test-syntax-suggest $(PREPARE_SYNTAX_SUGGEST),$(TEST_TARGETS))
TEST_DEPENDS := $(filter-out test-short $(TEST_TARGETS),$(TEST_DEPENDS))
TEST_DEPENDS += $(if $(filter great exam love check,$(MAKECMDGOALS)),all exts)
+endif
in-srcdir := $(if $(filter-out .,$(srcdir)),$(CHDIR) $(srcdir) &&)
-ifneq ($(filter -O0 -Od,$(optflags)),)
-override XCFLAGS := $(filter-out -D_FORTIFY_SOURCE=%,$(XCFLAGS))
-endif
-
ifeq ($(if $(filter all main exts enc trans libencs libenc libtrans \
prog program ruby ruby$(EXEEXT) \
wprogram rubyw rubyw$(EXEEXT) \
@@ -69,6 +74,7 @@ $(foreach arch,$(arch_flags),\
$(eval $(call archcmd,$(patsubst -arch=%,%,$(value arch)),$(patsubst -arch=%,-arch %,$(value arch)))))
endif
+ifeq ($(DOT_WAIT),)
.PHONY: $(addprefix yes-,$(TEST_TARGETS))
ifneq ($(filter-out btest%,$(TEST_TARGETS)),)
@@ -78,12 +84,16 @@ 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-bundler-parallel \
+ test-spec test-syntax-suggest-prepare test-syntax-suggest \
+ test-bundler-prepare test-bundler test-bundler-parallel \
+ test-bundled-gems-precheck test-bundled-gems-fetch \
+ test-bundled-gems-prepare test-bundled-gems-run \
)
prev_test := $(if $(filter test-spec,$(ORDERED_TEST_TARGETS)),test-spec-precheck)
$(foreach test,$(ORDERED_TEST_TARGETS), \
$(eval yes-$(value test) no-$(value test): $(value prev_test)); \
$(eval prev_test := $(value test)))
+endif
ifneq ($(if $(filter install,$(MAKECMDGOALS)),$(filter uninstall,$(MAKECMDGOALS))),)
install-targets := $(filter install uninstall,$(MAKECMDGOALS))
@@ -129,7 +139,7 @@ config.status: $(wildcard config.cache)
STUBPROGRAM = rubystub$(EXEEXT)
IGNOREDPATTERNS = %~ .% %.orig %.rej \#%\#
SCRIPTBINDIR := $(if $(EXEEXT),,exec/)
-SCRIPTPROGRAMS = $(addprefix $(SCRIPTBINDIR),$(addsuffix $(EXEEXT),$(filter-out $(IGNOREDPATTERNS),$(notdir $(wildcard $(srcdir)/libexec/*)))))
+SCRIPTPROGRAMS = $(addprefix $(SCRIPTBINDIR),$(addsuffix $(EXEEXT),$(filter-out $(IGNOREDPATTERNS),$(notdir $(wildcard $(srcdir)/bin/*)))))
stub: $(STUBPROGRAM)
scriptbin: $(SCRIPTPROGRAMS)
@@ -155,9 +165,8 @@ $(SCRIPTBINDIR)%$(EXEEXT): bin/% $(STUBPROGRAM) \
$(Q) chmod +x $@
$(Q) $(POSTLINK)
-$(TIMESTAMPDIR)/.exec.time:
- $(Q) mkdir exec
- $(Q) exit > $@
+$(SCRIPTBINDIR):
+ $(Q) mkdir $@
.PHONY: commit
commit: $(if $(filter commit,$(MAKECMDGOALS)),$(filter-out commit,$(MAKECMDGOALS))) up
@@ -175,8 +184,8 @@ commit: $(if $(filter commit,$(MAKECMDGOALS)),$(filter-out commit,$(MAKECMDGOALS
GITHUB_RUBY_URL = https://github.com/ruby/ruby
PR =
-COMMIT_GPG_SIGN = $(shell git -C "$(srcdir)" config commit.gpgsign)
-REMOTE_GITHUB_URL = $(shell git -C "$(srcdir)" config remote.github.url)
+COMMIT_GPG_SIGN = $(shell $(GIT) -C "$(srcdir)" config commit.gpgsign)
+REMOTE_GITHUB_URL = $(shell $(GIT) -C "$(srcdir)" config remote.github.url)
COMMITS_NOTES = commits
.PHONY: fetch-github
@@ -189,21 +198,21 @@ define fetch-github
exit 1; \
)
$(eval REMOTE_GITHUB_URL := $(REMOTE_GITHUB_URL))
- $(if $(REMOTE_GITHUB_URL),, \
- echo adding $(GITHUB_RUBY_URL) as remote github; \
- git -C "$(srcdir)" remote add github $(GITHUB_RUBY_URL); \
- git -C "$(srcdir)" config --add remote.github.fetch +refs/notes/$(COMMITS_NOTES):refs/notes/$(COMMITS_NOTES)
- $(eval REMOTE_GITHUB_URL := $(GITHUB_RUBY_URL)) \
+ $(if $(REMOTE_GITHUB_URL),,
+ echo adding $(GITHUB_RUBY_URL) as remote github
+ $(GIT) -C "$(srcdir)" remote add github $(GITHUB_RUBY_URL)
+ $(GIT) -C "$(srcdir)" config --add remote.github.fetch +refs/notes/$(COMMITS_NOTES):refs/notes/$(COMMITS_NOTES)
+ $(eval REMOTE_GITHUB_URL := $(GITHUB_RUBY_URL))
)
- $(if $(git -C "$(srcdir)" rev-parse "github/pull/$(1)/head" -- 2> /dev/null), \
- git -C "$(srcdir)" branch -f "gh-$(1)" "github/pull/$(1)/head", \
- git -C "$(srcdir)" fetch -f github "pull/$(1)/head:gh-$(1)" \
+ $(if $(shell $(GIT) -C "$(srcdir)" rev-parse "github/pull/$(1)/head" -- 2> /dev/null),
+ $(GIT) -C "$(srcdir)" branch -f "gh-$(1)" "github/pull/$(1)/head",
+ $(GIT) -C "$(srcdir)" fetch -f github "pull/$(1)/head:gh-$(1)"
)
endef
.PHONY: checkout-github
checkout-github: fetch-github
- git -C "$(srcdir)" checkout "gh-$(PR)"
+ $(GIT) -C "$(srcdir)" checkout "gh-$(PR)"
.PHONY: update-github
update-github: fetch-github
@@ -216,30 +225,31 @@ update-github: fetch-github
$(eval PR_BRANCH := $(word 2,$(PULL_REQUEST_FORK_BRANCH)))
$(eval GITHUB_UPDATE_WORKTREE := $(shell mktemp -d "$(srcdir)/gh-$(PR)-XXXXXX"))
- git -C "$(srcdir)" worktree add $(notdir $(GITHUB_UPDATE_WORKTREE)) "gh-$(PR)"
- git -C "$(GITHUB_UPDATE_WORKTREE)" merge master --no-edit
+ $(GIT) -C "$(srcdir)" worktree add $(notdir $(GITHUB_UPDATE_WORKTREE)) "gh-$(PR)"
+ $(GIT) -C "$(GITHUB_UPDATE_WORKTREE)" merge master --no-edit
@$(BASERUBY) -e 'print "Are you sure to push this to PR=$(PR)? [Y/n]: "; exit(gets.chomp != "n")'
- git -C "$(srcdir)" remote add fork-$(PR) git@github.com:$(FORK_REPO).git
- git -C "$(GITHUB_UPDATE_WORKTREE)" push fork-$(PR) gh-$(PR):$(PR_BRANCH)
- git -C "$(srcdir)" remote rm fork-$(PR)
- git -C "$(srcdir)" worktree remove $(notdir $(GITHUB_UPDATE_WORKTREE))
- git -C "$(srcdir)" branch -D gh-$(PR)
+ $(GIT) -C "$(srcdir)" remote add fork-$(PR) git@github.com:$(FORK_REPO).git
+ $(GIT) -C "$(GITHUB_UPDATE_WORKTREE)" push fork-$(PR) gh-$(PR):$(PR_BRANCH)
+ $(GIT) -C "$(srcdir)" remote rm fork-$(PR)
+ $(GIT) -C "$(srcdir)" worktree remove $(notdir $(GITHUB_UPDATE_WORKTREE))
+ $(GIT) -C "$(srcdir)" branch -D gh-$(PR)
.PHONY: pull-github
pull-github: fetch-github
$(call pull-github,$(PR))
define pull-github
- $(eval GITHUB_MERGE_BASE := $(shell git -C "$(srcdir)" log -1 --format=format:%H))
- $(eval GITHUB_MERGE_BRANCH := $(shell git -C "$(srcdir)" symbolic-ref --short HEAD))
+ $(eval GITHUB_MERGE_BASE := $(shell $(GIT) -C "$(srcdir)" log -1 --format=format:%H))
+ $(eval GITHUB_MERGE_BRANCH := $(shell $(GIT) -C "$(srcdir)" symbolic-ref --short HEAD))
$(eval GITHUB_MERGE_WORKTREE := $(shell mktemp -d "$(srcdir)/gh-$(1)-XXXXXX"))
- git -C "$(srcdir)" worktree add $(notdir $(GITHUB_MERGE_WORKTREE)) "gh-$(1)"
- git -C "$(GITHUB_MERGE_WORKTREE)" rebase $(GITHUB_MERGE_BRANCH)
+ $(GIT) -C "$(srcdir)" worktree prune
+ $(GIT) -C "$(srcdir)" worktree add $(notdir $(GITHUB_MERGE_WORKTREE)) "gh-$(1)"
+ $(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase $(GITHUB_MERGE_BRANCH)
$(eval COMMIT_GPG_SIGN := $(COMMIT_GPG_SIGN))
$(if $(filter true,$(COMMIT_GPG_SIGN)), \
- git -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "git commit --amend --no-edit -S" "$(GITHUB_MERGE_BASE)"; \
+ $(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "$(GIT) commit --amend --no-edit -S" "$(GITHUB_MERGE_BASE)"; \
)
- git -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "git notes add --message 'Merged: $(GITHUB_RUBY_URL)/pull/$(1)'" "$(GITHUB_MERGE_BASE)"
+ $(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase --exec "$(GIT) notes add --message 'Merged: $(GITHUB_RUBY_URL)/pull/$(1)'" "$(GITHUB_MERGE_BASE)"
endef
.PHONY: fetch-github-%
@@ -248,23 +258,46 @@ fetch-github-%:
.PHONY: checkout-github-%
checkout-github-%: fetch-github-%
- git -C "$(srcdir)" checkout "gh-$*"
+ $(GIT) -C "$(srcdir)" checkout "gh-$*"
.PHONY: pr-% pull-github-%
pr-% pull-github-%: fetch-github-%
$(call pull-github,$*)
HELP_EXTRA_TASKS = \
- " checkout-github: checkout GitHub Pull Request [PR=1234]" \
- " pull-github: rebase GitHub Pull Request to new worktree [PR=1234]" \
- " update-github: merge master branch and push it to Pull Request [PR=1234]" \
+ " checkout-github: checkout GitHub Pull Request [PR=1234]" \
+ " pull-github: rebase GitHub Pull Request to new worktree [PR=1234]" \
+ " update-github: merge master branch and push it to Pull Request [PR=1234]" \
""
-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))
+# 1. squeeze spaces
+# 2. strip and skip comment/empty lines
+# 3. "gem x.y.z URL xxxxxx" -> "gem|x.y.z|xxxxxx|URL"
+# 4. "gem x.y.z URL" -> "gem-x.y.z"
+bundled-gems := $(shell sed \
+ -e 's/[ ][ ]*/ /g' \
+ -e 's/^ //;/\#/d;s/ *$$//;/^$$/d' \
+ $(if $(filter yes,$(HAVE_GIT)), \
+ -e 's/^\(.*\) \(.*\) \(.*\) \(.*\)/\1|\2|\4|\3/' \
+ ) \
+ -e 's/ /-/;s/ .*//' \
+ $(srcdir)/gems/bundled_gems)
+
+bundled-gems-rev := $(filter-out $(subst |,,$(bundled-gems)),$(bundled-gems))
+bundled-gems := $(filter-out $(bundled-gems-rev),$(bundled-gems))
+
+# calls $(1) with name, version, revision, URL
+foreach-bundled-gems-rev = \
+ $(foreach g,$(bundled-gems-rev),$(call foreach-bundled-gems-rev-0,$(1),$(subst |, ,$(value g))))
+foreach-bundled-gems-rev-0 = \
+ $(call $(1),$(word 1,$(2)),$(word 2,$(2)),$(word 3,$(2)),$(word 4,$(2)))
+bundled-gem-gemfile = $(srcdir)/gems/$(1)-$(2).gem
+bundled-gem-srcdir = $(srcdir)/gems/src/$(1)
+bundled-gem-extracted = $(srcdir)/.bundle/gems/$(1)-$(2)
+
+update-gems: | $(patsubst %,$(srcdir)/gems/%.gem,$(bundled-gems))
+update-gems: | $(call foreach-bundled-gems-rev,bundled-gem-gemfile)
+update-gems: | $(call foreach-bundled-gems-rev,bundled-gem-srcdir)
test-bundler-precheck: | $(srcdir)/.bundle/cache
@@ -272,7 +305,7 @@ $(srcdir)/.bundle/cache:
$(MAKEDIRS) $(@D) $(CACHE_DIR)
$(LN_S) ../.downloaded-cache $@
-gems/%.gem:
+$(srcdir)/gems/%.gem:
$(ECHO) Downloading bundled gem $*...
$(Q) $(BASERUBY) -C "$(srcdir)" \
-I./tool -rdownloader \
@@ -283,13 +316,39 @@ gems/%.gem:
-e 'File.unlink(*old) and' \
-e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})'
-extract-gems: | $(patsubst %,.bundle/gems/%,$(bundled-gems))
+extract-gems: | $(patsubst %,$(srcdir)/.bundle/gems/%,$(bundled-gems))
+extract-gems: | $(call foreach-bundled-gems-rev,bundled-gem-extracted)
-.bundle/gems/%: gems/%.gem | .bundle/gems
+$(srcdir)/.bundle/gems/%: $(srcdir)/gems/%.gem | .bundle/gems
$(ECHO) Extracting bundle gem $*...
$(Q) $(BASERUBY) -C "$(srcdir)" \
- -Itool -rgem-unpack \
- -e 'Gem.unpack("gems/$(@F).gem", ".bundle/gems")'
+ -Itool/lib -rbundled_gem \
+ -e 'BundledGem.unpack("gems/$(@F).gem", ".bundle")'
+
+define copy-gem
+$(srcdir)/gems/src/$(1): | $(srcdir)/gems/src
+ $(ECHO) Cloning $(4)
+ $(Q) $(GIT) clone $(4) $$(@)
+
+$(srcdir)/.bundle/gems/$(1)-$(2): | $(srcdir)/gems/src/$(1) .bundle/gems
+ $(ECHO) Copying $(1)@$(3) to $$(@F)
+ $(Q) $(CHDIR) "$(srcdir)/gems/src/$(1)" && \
+ $(GIT) fetch origin $(3) && \
+ $(GIT) checkout --detach $(3) && \
+ :
+ $(Q) $(BASERUBY) -C "$(srcdir)" \
+ -Itool/lib -rbundled_gem \
+ -e 'BundledGem.copy("gems/src/$(1)/$(1).gemspec", ".bundle")'
+
+endef
+define copy-gem-0
+$(eval $(call copy-gem,$(1),$(2),$(3),$(4)))
+endef
+
+$(call foreach-bundled-gems-rev,copy-gem-0)
+
+$(srcdir)/gems/src:
+ $(MAKEDIRS) $@
$(srcdir)/.bundle/gems:
$(MAKEDIRS) $@
@@ -326,25 +385,26 @@ $(MJIT_MIN_HEADER): $(mjit_min_headers) $(PREP)
endif
-ifeq ($(if $(wildcard $(filter-out .,$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES))),,\
- $(wildcard $(srcdir)/lib/unicode_normalize/tables.rb)),)
-# Needs the dependency when any Unicode data file exists, or
-# normalization tables script doesn't. Otherwise, when the target
-# only exists, use it as-is.
-.PHONY: $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time
-UNICODE_TABLES_TIMESTAMP =
-$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: \
- $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
-endif
+.SECONDARY: update-unicode-files
+.SECONDARY: update-unicode-auxiliary-files
+.SECONDARY: update-unicode-ucd-emoji-files
+.SECONDARY: update-unicode-emoji-files
-REVISION_IN_HEADER := $(shell sed -n 's/^\#define RUBY_FULL_REVISION "\(.*\)"/\1/p' $(srcdir)/revision.h 2>/dev/null)
-REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && git log -1 --format=%H 2>/dev/null)
+ifeq ($(HAVE_GIT),yes)
+REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) log -1 --format=%H 2>/dev/null)
+else
+REVISION_LATEST := update
+endif
+REVISION_IN_HEADER := $(shell sed -n 's/^\#define RUBY_FULL_REVISION "\(.*\)"/\1/p' $(wildcard $(srcdir)/revision.h revision.h) /dev/null 2>/dev/null)
+ifeq ($(REVISION_IN_HEADER),)
+REVISION_IN_HEADER := none
+endif
ifneq ($(REVISION_IN_HEADER),$(REVISION_LATEST))
-# GNU make treat the target as unmodified when its dependents get
-# updated but it is not updated, while others may not.
-$(srcdir)/revision.h: $(REVISION_H)
+$(REVISION_H): PHONY
endif
+include $(top_srcdir)/yjit/yjit.mk
+
# Query on the generated rdoc
#
# $ make rdoc:Integer#+
@@ -360,8 +420,11 @@ spec/bundler/%: PHONY
spec/bundler: test-bundler-parallel
$(Q)$(NULLCMD)
-spec/%/ spec/%_spec.rb: programs exts PHONY
- +$(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@)
+# workaround to avoid matching non ruby files with "spec/%/" under GNU make 3.81
+spec/%_spec.c:
+ $(empty)
+$(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h:
+ $(empty)
benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY
$(Q)$(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \
@@ -384,26 +447,26 @@ endif
update-deps:
$(eval update_deps := $(shell date +update-deps-%Y%m%d))
$(eval deps_dir := $(shell mktemp -d)/$(update_deps))
- $(eval GIT_DIR := $(shell git -C $(srcdir) rev-parse --absolute-git-dir))
- git --git-dir=$(GIT_DIR) worktree add $(deps_dir)
+ $(eval GIT_DIR := $(shell $(GIT) -C $(srcdir) rev-parse --absolute-git-dir))
+ $(GIT) --git-dir=$(GIT_DIR) worktree add $(deps_dir)
cp $(tooldir)/config.guess $(tooldir)/config.sub $(deps_dir)/tool
[ -f config.status ] && cp config.status $(deps_dir)
cd $(deps_dir) && autoconf && \
exec ./configure -q -C --enable-load-relative --disable-install-doc --disable-rubygems 'optflags=-O0' 'debugflags=-save-temps=obj -g'
$(RUNRUBY) -C $(deps_dir) tool/update-deps --fix
- git -C $(deps_dir) diff --no-ext-diff --ignore-submodules --exit-code || \
- git -C $(deps_dir) commit --all --message='Update dependencies'
- git --git-dir=$(GIT_DIR) worktree remove $(deps_dir)
+ $(GIT) -C $(deps_dir) diff --no-ext-diff --ignore-submodules --exit-code || \
+ $(GIT) -C $(deps_dir) commit --all --message='Update dependencies'
+ $(GIT) --git-dir=$(GIT_DIR) worktree remove $(deps_dir)
$(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)
+ $(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)
+$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h $(RUBY_H_INCLUDES) $(LIBRUBY)
$(ECHO) building $@
$(Q) $(MAKEDIRS) $(@D)
- $(Q) $(DLDSHARED) $(XDLDFLAGS) $(XLDFLAGS) $(ARCH_FLAG) $(ARCH_FLAG) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBY_SO)
+ $(Q) $(DLDSHARED) $(XDLDFLAGS) $(XLDFLAGS) $(LDFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBYARG)
$(Q) $(RMALL) $@.*
rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c)))
@@ -412,3 +475,8 @@ rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildc
ifeq ($(ENABLE_SHARED),yes)
exts: rubyspec-capiext
endif
+
+spec/%/ spec/%_spec.rb: programs exts PHONY
+ +$(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@)
+
+ruby.pc: $(filter-out ruby.pc,$(ruby_pc))
diff --git a/defs/id.def b/defs/id.def
index 506dc95050..ebf00506ea 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -7,6 +7,7 @@ firstline, predefined = __LINE__+1, %[\
inspect
intern
object_id
+ const_added
const_missing
method_missing MethodMissing
method_added
@@ -57,6 +58,7 @@ firstline, predefined = __LINE__+1, %[\
quo
name
nil
+ path
_ UScore
@@ -74,6 +76,7 @@ firstline, predefined = __LINE__+1, %[\
"/*NULL*/" NULL
empty?
eql?
+ default
respond_to? Respond_to
respond_to_missing? Respond_to_missing
<IFUNC>
@@ -87,6 +90,7 @@ firstline, predefined = __LINE__+1, %[\
core#hash_merge_ptr
core#hash_merge_kwd
core#raise
+ core#sprintf
- debug#created_info
@@ -192,13 +196,14 @@ predefined.split(/^/).each_with_index do |line, num|
end << token
predefined_ids[token] = name
end
+index = 127
token_ops.split(/^/).each do |line|
next if /^#/ =~ line
line.sub!(/\s+#.*/, '')
id, op, token = line.split
next unless id and op
token ||= (id unless /\A\W\z/ =~ op)
- token_op_ids << [id, op, token]
+ token_op_ids << [id, op, token, (index += 1 if token)]
end
{
"LOCAL" => local_ids,
@@ -210,4 +215,5 @@ end
:preserved => preserved_ids,
:predefined => predefined_ids,
:token_op => token_op_ids,
+ :last_token => index,
}
diff --git a/defs/keywords b/defs/keywords
index fc30ec2d15..a1b1f4f60f 100644
--- a/defs/keywords
+++ b/defs/keywords
@@ -2,7 +2,7 @@
struct kwtable {short name, id[2], state;};
const struct kwtable *rb_reserved_word(const char *, unsigned int);
#ifndef RIPPER
-static const struct kwtable *reserved_word(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/);
+static const struct kwtable *reserved_word(register const char *str, register size_t len);
#define rb_reserved_word(str, len) reserved_word(str, len)
%}
diff --git a/defs/lex.c.src b/defs/lex.c.src
index fc30ec2d15..a1b1f4f60f 100644
--- a/defs/lex.c.src
+++ b/defs/lex.c.src
@@ -2,7 +2,7 @@
struct kwtable {short name, id[2], state;};
const struct kwtable *rb_reserved_word(const char *, unsigned int);
#ifndef RIPPER
-static const struct kwtable *reserved_word(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/);
+static const struct kwtable *reserved_word(register const char *str, register size_t len);
#define rb_reserved_word(str, len) reserved_word(str, len)
%}
diff --git a/dir.c b/dir.c
index 8ac10d2360..3f73f83fc5 100644
--- a/dir.c
+++ b/dir.c
@@ -77,9 +77,9 @@ char *strchr(char*,char);
#endif
#define USE_NAME_ON_FS_REAL_BASENAME 1 /* platform dependent APIs to
- * get real basenames */
+ * get real basenames */
#define USE_NAME_ON_FS_BY_FNMATCH 2 /* select the matching
- * basename by fnmatch */
+ * basename by fnmatch */
#ifdef HAVE_GETATTRLIST
# define USE_NAME_ON_FS USE_NAME_ON_FS_REAL_BASENAME
@@ -112,6 +112,7 @@ char *strchr(char*,char);
#include "internal/file.h"
#include "internal/gc.h"
#include "internal/io.h"
+#include "internal/object.h"
#include "internal/vm.h"
#include "ruby/encoding.h"
#include "ruby/ruby.h"
@@ -159,12 +160,12 @@ need_normalization(DIR *dirp, const char *path)
int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0);
# endif
if (!ret) {
- const fsobj_tag_t *tag = (void *)(attrbuf+1);
- switch (*tag) {
- case VT_HFS:
- case VT_CIFS:
- return TRUE;
- }
+ const fsobj_tag_t *tag = (void *)(attrbuf+1);
+ switch (*tag) {
+ case VT_HFS:
+ case VT_CIFS:
+ return TRUE;
+ }
}
# endif
return FALSE;
@@ -174,9 +175,9 @@ static inline int
has_nonascii(const char *ptr, size_t len)
{
while (len > 0) {
- if (!ISASCII(*ptr)) return 1;
- ptr++;
- --len;
+ if (!ISASCII(*ptr)) return 1;
+ ptr++;
+ --len;
}
return 0;
}
@@ -186,12 +187,18 @@ has_nonascii(const char *ptr, size_t len)
# define IF_NORMALIZE_UTF8PATH(something) /* nothing */
#endif
-#ifndef IFTODT
+#if defined(IFTODT) && defined(DT_UNKNOWN)
+# define EMULATE_IFTODT 0
+#else
+# define EMULATE_IFTODT 1
+#endif
+
+#if EMULATE_IFTODT
# define IFTODT(m) (((m) & S_IFMT) / ((~S_IFMT & (S_IFMT-1)) + 1))
#endif
typedef enum {
-#ifdef DT_UNKNOWN
+#if !EMULATE_IFTODT
path_exist = DT_UNKNOWN,
path_directory = DT_DIR,
path_regular = DT_REG,
@@ -247,53 +254,53 @@ bracket(
if (p >= pend) return NULL;
if (*p == '!' || *p == '^') {
- not = 1;
- p++;
+ not = 1;
+ p++;
}
while (*p != ']') {
- const char *t1 = p;
- if (escape && *t1 == '\\')
- t1++;
- if (!*t1)
- return NULL;
- p = t1 + (r = rb_enc_mbclen(t1, pend, enc));
- if (p >= pend) return NULL;
- if (p[0] == '-' && p[1] != ']') {
- const char *t2 = p + 1;
- int r2;
- if (escape && *t2 == '\\')
- t2++;
- if (!*t2)
- return NULL;
- p = t2 + (r2 = rb_enc_mbclen(t2, pend, enc));
- if (ok) continue;
- if ((r <= (send-s) && memcmp(t1, s, r) == 0) ||
- (r2 <= (send-s) && memcmp(t2, s, r2) == 0)) {
- ok = 1;
- continue;
- }
- c1 = rb_enc_codepoint(s, send, enc);
- if (nocase) c1 = rb_enc_toupper(c1, enc);
- c2 = rb_enc_codepoint(t1, pend, enc);
- if (nocase) c2 = rb_enc_toupper(c2, enc);
- if (c1 < c2) continue;
- c2 = rb_enc_codepoint(t2, pend, enc);
- if (nocase) c2 = rb_enc_toupper(c2, enc);
- if (c1 > c2) continue;
- }
- else {
- if (ok) continue;
- if (r <= (send-s) && memcmp(t1, s, r) == 0) {
- ok = 1;
- continue;
- }
- if (!nocase) continue;
- c1 = rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc);
- c2 = rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc);
- if (c1 != c2) continue;
- }
- ok = 1;
+ const char *t1 = p;
+ if (escape && *t1 == '\\')
+ t1++;
+ if (!*t1)
+ return NULL;
+ p = t1 + (r = rb_enc_mbclen(t1, pend, enc));
+ if (p >= pend) return NULL;
+ if (p[0] == '-' && p[1] != ']') {
+ const char *t2 = p + 1;
+ int r2;
+ if (escape && *t2 == '\\')
+ t2++;
+ if (!*t2)
+ return NULL;
+ p = t2 + (r2 = rb_enc_mbclen(t2, pend, enc));
+ if (ok) continue;
+ if ((r <= (send-s) && memcmp(t1, s, r) == 0) ||
+ (r2 <= (send-s) && memcmp(t2, s, r2) == 0)) {
+ ok = 1;
+ continue;
+ }
+ c1 = rb_enc_codepoint(s, send, enc);
+ if (nocase) c1 = rb_enc_toupper(c1, enc);
+ c2 = rb_enc_codepoint(t1, pend, enc);
+ if (nocase) c2 = rb_enc_toupper(c2, enc);
+ if (c1 < c2) continue;
+ c2 = rb_enc_codepoint(t2, pend, enc);
+ if (nocase) c2 = rb_enc_toupper(c2, enc);
+ if (c1 > c2) continue;
+ }
+ else {
+ if (ok) continue;
+ if (r <= (send-s) && memcmp(t1, s, r) == 0) {
+ ok = 1;
+ continue;
+ }
+ if (!nocase) continue;
+ c1 = rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc);
+ c2 = rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc);
+ if (c1 != c2) continue;
+ }
+ ok = 1;
}
return ok == not ? NULL : (char *)p + 1;
@@ -331,72 +338,72 @@ fnmatch_helper(
int r;
if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
- RETURN(FNM_NOMATCH);
+ RETURN(FNM_NOMATCH);
while (1) {
- switch (*p) {
- case '*':
- do { p++; } while (*p == '*');
- if (ISEND(UNESCAPE(p))) {
- p = UNESCAPE(p);
- RETURN(0);
- }
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- ptmp = p;
- stmp = s;
- continue;
-
- case '?':
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- p++;
- Inc(s, send, enc);
- continue;
-
- case '[': {
- const char *t;
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- if ((t = bracket(p + 1, pend, s, send, flags, enc)) != 0) {
- p = t;
- Inc(s, send, enc);
- continue;
- }
- goto failed;
- }
- }
-
- /* ordinary */
- p = UNESCAPE(p);
- if (ISEND(s))
- RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
- if (ISEND(p))
- goto failed;
- r = rb_enc_precise_mbclen(p, pend, enc);
- if (!MBCLEN_CHARFOUND_P(r))
- goto failed;
- if (r <= (send-s) && memcmp(p, s, r) == 0) {
- p += r;
- s += r;
- continue;
- }
- if (!nocase) goto failed;
- if (rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc) !=
- rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc))
- goto failed;
- p += r;
- Inc(s, send, enc);
- continue;
+ switch (*p) {
+ case '*':
+ do { p++; } while (*p == '*');
+ if (ISEND(UNESCAPE(p))) {
+ p = UNESCAPE(p);
+ RETURN(0);
+ }
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ ptmp = p;
+ stmp = s;
+ continue;
+
+ case '?':
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ p++;
+ Inc(s, send, enc);
+ continue;
+
+ case '[': {
+ const char *t;
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ if ((t = bracket(p + 1, pend, s, send, flags, enc)) != 0) {
+ p = t;
+ Inc(s, send, enc);
+ continue;
+ }
+ goto failed;
+ }
+ }
+
+ /* ordinary */
+ p = UNESCAPE(p);
+ if (ISEND(s))
+ RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
+ if (ISEND(p))
+ goto failed;
+ r = rb_enc_precise_mbclen(p, pend, enc);
+ if (!MBCLEN_CHARFOUND_P(r))
+ goto failed;
+ if (r <= (send-s) && memcmp(p, s, r) == 0) {
+ p += r;
+ s += r;
+ continue;
+ }
+ if (!nocase) goto failed;
+ if (rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc) !=
+ rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc))
+ goto failed;
+ p += r;
+ Inc(s, send, enc);
+ continue;
failed: /* try next '*' position */
- if (ptmp && stmp) {
- p = ptmp;
- Inc(stmp, send, enc); /* !ISEND(*stmp) */
- s = stmp;
- continue;
- }
- RETURN(FNM_NOMATCH);
+ if (ptmp && stmp) {
+ p = ptmp;
+ Inc(stmp, send, enc); /* !ISEND(*stmp) */
+ s = stmp;
+ continue;
+ }
+ RETURN(FNM_NOMATCH);
}
}
@@ -417,37 +424,37 @@ fnmatch(
const char *stmp = 0;
if (pathname) {
- while (1) {
- if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
- do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
- ptmp = p;
- stmp = s;
- }
- if (fnmatch_helper(&p, &s, flags, enc) == 0) {
- while (*s && *s != '/') Inc(s, send, enc);
- if (*p && *s) {
- p++;
- s++;
- continue;
- }
- if (!*p && !*s)
- return 0;
- }
- /* failed : try next recursion */
- if (ptmp && stmp && !(period && *stmp == '.')) {
- while (*stmp && *stmp != '/') Inc(stmp, send, enc);
- if (*stmp) {
- p = ptmp;
- stmp++;
- s = stmp;
- continue;
- }
- }
- return FNM_NOMATCH;
- }
+ while (1) {
+ if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
+ do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
+ ptmp = p;
+ stmp = s;
+ }
+ if (fnmatch_helper(&p, &s, flags, enc) == 0) {
+ while (*s && *s != '/') Inc(s, send, enc);
+ if (*p && *s) {
+ p++;
+ s++;
+ continue;
+ }
+ if (!*p && !*s)
+ return 0;
+ }
+ /* failed : try next recursion */
+ if (ptmp && stmp && !(period && *stmp == '.')) {
+ while (*stmp && *stmp != '/') Inc(stmp, send, enc);
+ if (*stmp) {
+ p = ptmp;
+ stmp++;
+ s = stmp;
+ continue;
+ }
+ }
+ return FNM_NOMATCH;
+ }
}
else
- return fnmatch_helper(&p, &s, flags, enc);
+ return fnmatch_helper(&p, &s, flags, enc);
}
VALUE rb_cDir;
@@ -513,14 +520,14 @@ static DIR *
opendir_without_gvl(const char *path)
{
if (vm_initialized) {
- union { const void *in; void *out; } u;
+ union { const void *in; void *out; } u;
- u.in = path;
+ u.in = path;
- return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0);
+ return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0);
}
else
- return opendir(path);
+ return opendir(path);
}
static VALUE
@@ -544,23 +551,23 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
path = RSTRING_PTR(dirname);
dp->dir = opendir_without_gvl(path);
if (dp->dir == NULL) {
- int e = errno;
- if (rb_gc_for_fd(e)) {
- dp->dir = opendir_without_gvl(path);
- }
+ int e = errno;
+ if (rb_gc_for_fd(e)) {
+ dp->dir = opendir_without_gvl(path);
+ }
#ifdef HAVE_GETATTRLIST
- else if (e == EIO) {
- u_int32_t attrbuf[1];
- struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
- dp->dir = opendir_without_gvl(path);
- }
- }
-#endif
- if (dp->dir == NULL) {
- RB_GC_GUARD(dirname);
- rb_syserr_fail_path(e, orig);
- }
+ else if (e == EIO) {
+ u_int32_t attrbuf[1];
+ struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
+ if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
+ dp->dir = opendir_without_gvl(path);
+ }
+ }
+#endif
+ if (dp->dir == NULL) {
+ RB_GC_GUARD(dirname);
+ rb_syserr_fail_path(e, orig);
+ }
}
RB_OBJ_WRITE(dir, &dp->path, orig);
@@ -623,12 +630,12 @@ dir_inspect(VALUE dir)
TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
if (!NIL_P(dirp->path)) {
- VALUE str = rb_str_new_cstr("#<");
- rb_str_append(str, rb_class_name(CLASS_OF(dir)));
- rb_str_cat2(str, ":");
- rb_str_append(str, dirp->path);
- rb_str_cat2(str, ">");
- return str;
+ VALUE str = rb_str_new_cstr("#<");
+ rb_str_append(str, rb_class_name(CLASS_OF(dir)));
+ rb_str_cat2(str, ":");
+ rb_str_append(str, dirp->path);
+ rb_str_cat2(str, ">");
+ return str;
}
return rb_funcallv(dir, idTo_s, 0, 0);
}
@@ -670,7 +677,7 @@ dir_fileno(VALUE dir)
GetDIR(dir, dirp);
fd = dirfd(dirp->dir);
if (fd == -1)
- rb_sys_fail("dirfd");
+ rb_sys_fail("dirfd");
return INT2NUM(fd);
}
#else
@@ -702,12 +709,12 @@ static int
fundamental_encoding_p(rb_encoding *enc)
{
switch (rb_enc_to_index(enc)) {
- case ENCINDEX_ASCII:
+ case ENCINDEX_ASCII_8BIT:
case ENCINDEX_US_ASCII:
case ENCINDEX_UTF_8:
- return TRUE;
+ return TRUE;
default:
- return FALSE;
+ return FALSE;
}
}
# define READDIR(dir, enc) rb_w32_readdir((dir), (enc))
@@ -724,11 +731,11 @@ to_be_skipped(const struct dirent *dp)
#ifdef HAVE_DIRENT_NAMLEN
switch (NAMLEN(dp)) {
case 2:
- if (name[1] != '.') return FALSE;
+ if (name[1] != '.') return FALSE;
case 1:
- return TRUE;
+ return TRUE;
default:
- break;
+ break;
}
#else
if (!name[1]) return TRUE;
@@ -759,12 +766,12 @@ dir_read(VALUE dir)
GetDIR(dir, dirp);
errno = 0;
if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
- return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
+ return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
}
else {
- int e = errno;
- if (e != 0) rb_syserr_fail(e, 0);
- return Qnil; /* end of stream */
+ int e = errno;
+ if (e != 0) rb_syserr_fail(e, 0);
+ return Qnil; /* end of stream */
}
}
@@ -814,23 +821,23 @@ dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE), VALUE arg, int children_o
rewinddir(dirp->dir);
IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp->dir, RSTRING_PTR(dirp->path)));
while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
- const char *name = dp->d_name;
- size_t namlen = NAMLEN(dp);
- VALUE path;
-
- if (children_only && name[0] == '.') {
- if (namlen == 1) continue; /* current directory */
- if (namlen == 2 && name[1] == '.') continue; /* parent directory */
- }
+ const char *name = dp->d_name;
+ size_t namlen = NAMLEN(dp);
+ VALUE path;
+
+ if (children_only && name[0] == '.') {
+ if (namlen == 1) continue; /* current directory */
+ if (namlen == 2 && name[1] == '.') continue; /* parent directory */
+ }
#if NORMALIZE_UTF8PATH
- if (norm_p && has_nonascii(name, namlen) &&
- !NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
- path = rb_external_str_with_enc(path, dirp->enc);
- }
- else
+ if (norm_p && has_nonascii(name, namlen) &&
+ !NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
+ path = rb_external_str_with_enc(path, dirp->enc);
+ }
+ else
#endif
- path = rb_external_str_new_with_enc(name, namlen, dirp->enc);
- (*each)(arg, path);
+ path = rb_external_str_new_with_enc(name, namlen, dirp->enc);
+ (*each)(arg, path);
}
return dir;
}
@@ -971,7 +978,7 @@ static void
dir_chdir(VALUE path)
{
if (chdir(RSTRING_PTR(path)) < 0)
- rb_sys_fail_path(path);
+ rb_sys_fail_path(path);
}
static int chdir_blocking = 0;
@@ -989,8 +996,8 @@ chdir_yield(VALUE v)
dir_chdir(args->new_path);
args->done = TRUE;
chdir_blocking++;
- if (chdir_thread == Qnil)
- chdir_thread = rb_thread_current();
+ if (NIL_P(chdir_thread))
+ chdir_thread = rb_thread_current();
return rb_yield(args->new_path);
}
@@ -999,10 +1006,10 @@ chdir_restore(VALUE v)
{
struct chdir_data *args = (void *)v;
if (args->done) {
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
- dir_chdir(args->old_path);
+ chdir_blocking--;
+ if (chdir_blocking == 0)
+ chdir_thread = Qnil;
+ dir_chdir(args->old_path);
}
return Qnil;
}
@@ -1056,35 +1063,35 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj)
path = rb_str_encode_ospath(rb_get_path(argv[0]));
}
else {
- const char *dist = getenv("HOME");
- if (!dist) {
- dist = getenv("LOGDIR");
- if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
- }
- path = rb_str_new2(dist);
+ const char *dist = getenv("HOME");
+ if (!dist) {
+ dist = getenv("LOGDIR");
+ if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
+ }
+ path = rb_str_new2(dist);
}
if (chdir_blocking > 0) {
- if (rb_thread_current() != chdir_thread)
+ if (rb_thread_current() != chdir_thread)
rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
if (!rb_block_given_p())
rb_warn("conflicting chdir during another chdir block");
}
if (rb_block_given_p()) {
- struct chdir_data args;
+ struct chdir_data args;
- args.old_path = rb_str_encode_ospath(rb_dir_getwd());
- args.new_path = path;
- args.done = FALSE;
- return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
+ args.old_path = rb_str_encode_ospath(rb_dir_getwd());
+ args.new_path = path;
+ args.done = FALSE;
+ return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
}
else {
- char *p = RSTRING_PTR(path);
- int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p,
- RUBY_UBF_IO, 0);
- if (r < 0)
- rb_sys_fail_path(path);
+ char *p = RSTRING_PTR(path);
+ int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p,
+ RUBY_UBF_IO, 0);
+ if (r < 0)
+ rb_sys_fail_path(path);
}
return INT2FIX(0);
@@ -1124,12 +1131,12 @@ rb_dir_getwd(void)
switch (fsenc) {
case ENCINDEX_US_ASCII:
- fsenc = ENCINDEX_ASCII;
- case ENCINDEX_ASCII:
- break;
+ fsenc = ENCINDEX_ASCII_8BIT;
+ case ENCINDEX_ASCII_8BIT:
+ break;
#if defined _WIN32 || defined __APPLE__
default:
- return rb_str_conv_enc(cwd, NULL, fs);
+ return rb_str_conv_enc(cwd, NULL, fs);
#endif
}
return rb_enc_associate_index(cwd, fsenc);
@@ -1167,8 +1174,8 @@ check_dirname(VALUE dir)
pend = path + len;
pend = rb_enc_path_end(rb_enc_path_skip_prefix(path, pend, enc), pend, enc);
if (pend - path < len) {
- d = rb_str_subseq(d, 0, pend - path);
- StringValueCStr(d);
+ d = rb_str_subseq(d, 0, pend - path);
+ StringValueCStr(d);
}
return rb_str_encode_ospath(d);
}
@@ -1188,7 +1195,7 @@ dir_s_chroot(VALUE dir, VALUE path)
{
path = check_dirname(path);
if (chroot(RSTRING_PTR(path)) == -1)
- rb_sys_fail_path(path);
+ rb_sys_fail_path(path);
return INT2FIX(0);
}
@@ -1231,17 +1238,17 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
int r;
if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
- m.mode = NUM2MODET(vmode);
+ m.mode = NUM2MODET(vmode);
}
else {
- m.mode = 0777;
+ m.mode = 0777;
}
path = check_dirname(path);
m.path = RSTRING_PTR(path);
r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0);
if (r < 0)
- rb_sys_fail_path(path);
+ rb_sys_fail_path(path);
return INT2FIX(0);
}
@@ -1273,7 +1280,7 @@ dir_s_rmdir(VALUE obj, VALUE dir)
p = RSTRING_PTR(dir);
r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0);
if (r < 0)
- rb_sys_fail_path(dir);
+ rb_sys_fail_path(dir);
return INT2FIX(0);
}
@@ -1379,8 +1386,8 @@ at_subpath(int fd, size_t baselen, const char *path)
{
#if USE_OPENDIR_AT
if (fd != (int)AT_FDCWD && baselen > 0) {
- path += baselen;
- if (*path == '/') ++path;
+ path += baselen;
+ if (*path == '/') ++path;
}
#endif
return *path ? path : ".";
@@ -1396,7 +1403,7 @@ do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, r
int ret = STAT(path, pst);
#endif
if (ret < 0 && !to_be_ignored(errno))
- sys_warning(path, enc);
+ sys_warning(path, enc);
return ret;
}
@@ -1411,7 +1418,7 @@ do_lstat(int fd, size_t baselen, const char *path, struct stat *pst, int flags,
int ret = lstat(path, pst);
#endif
if (ret < 0 && !to_be_ignored(errno))
- sys_warning(path, enc);
+ sys_warning(path, enc);
return ret;
}
@@ -1429,16 +1436,16 @@ with_gvl_gc_for_fd(void *ptr)
{
int *e = ptr;
- return (void *)(rb_gc_for_fd(*e) ? Qtrue : Qfalse);
+ return (void *)RBOOL(rb_gc_for_fd(*e));
}
static int
gc_for_fd_with_gvl(int e)
{
if (vm_initialized)
- return (int)(VALUE)rb_thread_call_with_gvl(with_gvl_gc_for_fd, &e);
+ return (int)(VALUE)rb_thread_call_with_gvl(with_gvl_gc_for_fd, &e);
else
- return rb_gc_for_fd(e) ? Qtrue : Qfalse;
+ return RBOOL(rb_gc_for_fd(e));
}
static void *
@@ -1450,32 +1457,32 @@ nogvl_opendir_at(void *ptr)
#if USE_OPENDIR_AT
const int opendir_flags = (O_RDONLY|O_CLOEXEC|
# ifdef O_DIRECTORY
- O_DIRECTORY|
+ O_DIRECTORY|
# endif /* O_DIRECTORY */
- 0);
+ 0);
int fd = openat(oaa->basefd, oaa->path, opendir_flags);
dirp = fd >= 0 ? fdopendir(fd) : 0;
if (!dirp) {
- int e = errno;
-
- switch (gc_for_fd_with_gvl(e)) {
- default:
- if (fd < 0) fd = openat(oaa->basefd, oaa->path, opendir_flags);
- if (fd >= 0) dirp = fdopendir(fd);
- if (dirp) return dirp;
-
- e = errno;
- /* fallthrough*/
- case 0:
- if (fd >= 0) close(fd);
- errno = e;
- }
+ int e = errno;
+
+ switch (gc_for_fd_with_gvl(e)) {
+ default:
+ if (fd < 0) fd = openat(oaa->basefd, oaa->path, opendir_flags);
+ if (fd >= 0) dirp = fdopendir(fd);
+ if (dirp) return dirp;
+
+ e = errno;
+ /* fallthrough*/
+ case 0:
+ if (fd >= 0) close(fd);
+ errno = e;
+ }
}
#else /* !USE_OPENDIR_AT */
dirp = opendir(oaa->path);
if (!dirp && gc_for_fd_with_gvl(errno))
- dirp = opendir(oaa->path);
+ dirp = opendir(oaa->path);
#endif /* !USE_OPENDIR_AT */
return dirp;
@@ -1490,37 +1497,37 @@ opendir_at(int basefd, const char *path)
oaa.path = path;
if (vm_initialized)
- return rb_thread_call_without_gvl(nogvl_opendir_at, &oaa, RUBY_UBF_IO, 0);
+ return rb_thread_call_without_gvl(nogvl_opendir_at, &oaa, RUBY_UBF_IO, 0);
else
- return nogvl_opendir_at(&oaa);
+ return nogvl_opendir_at(&oaa);
}
static DIR *
do_opendir(const int basefd, size_t baselen, const char *path, int flags, rb_encoding *enc,
- ruby_glob_errfunc *errfunc, VALUE arg, int *status)
+ ruby_glob_errfunc *errfunc, VALUE arg, int *status)
{
DIR *dirp;
#ifdef _WIN32
VALUE tmp = 0;
if (!fundamental_encoding_p(enc)) {
- tmp = rb_enc_str_new(path, strlen(path), enc);
- tmp = rb_str_encode_ospath(tmp);
- path = RSTRING_PTR(tmp);
+ tmp = rb_enc_str_new(path, strlen(path), enc);
+ tmp = rb_str_encode_ospath(tmp);
+ path = RSTRING_PTR(tmp);
}
#endif
dirp = opendir_at(basefd, at_subpath(basefd, baselen, path));
if (!dirp) {
- int e = errno;
-
- *status = 0;
- if (!to_be_ignored(e)) {
- if (errfunc) {
- *status = (*errfunc)(path, arg, enc, e);
- }
- else {
- sys_warning(path, enc);
- }
- }
+ int e = errno;
+
+ *status = 0;
+ if (!to_be_ignored(e)) {
+ if (errfunc) {
+ *status = (*errfunc)(path, arg, enc, e);
+ }
+ else {
+ sys_warning(path, enc);
+ }
+ }
}
#ifdef _WIN32
if (tmp) rb_str_resize(tmp, 0); /* GC guard */
@@ -1543,37 +1550,37 @@ has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
register char c;
while (p < pend && (c = *p++) != 0) {
- switch (c) {
- case '{':
- return BRACE;
+ switch (c) {
+ case '{':
+ return BRACE;
- case '*':
- case '?':
- case '[':
- hasmagical = 1;
- break;
+ case '*':
+ case '?':
+ case '[':
+ hasmagical = 1;
+ break;
- case '\\':
- if (escape && p++ >= pend)
- continue;
- break;
+ case '\\':
+ if (escape && p++ >= pend)
+ continue;
+ break;
#ifdef _WIN32
- case '.':
- break;
+ case '.':
+ break;
- case '~':
- hasalpha = 1;
- break;
+ case '~':
+ hasalpha = 1;
+ break;
#endif
- default:
- if (IS_WIN32 || ISALPHA(c)) {
- hasalpha = 1;
- }
- break;
- }
+ default:
+ if (IS_WIN32 || ISALPHA(c)) {
+ hasalpha = 1;
+ }
+ break;
+ }
- p = Next(p-1, pend, enc);
+ p = Next(p-1, pend, enc);
}
return hasmagical ? MAGICAL : hasalpha ? ALPHA : PLAIN;
@@ -1589,33 +1596,33 @@ find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc)
int open = 0;
while ((c = *p++) != 0) {
- switch (c) {
- case '[':
- open = 1;
- continue;
- case ']':
- open = 0;
- continue;
-
- case '{':
- open = 1;
- continue;
- case '}':
- open = 0;
- continue;
-
- case '/':
- if (!open)
- return (char *)p-1;
- continue;
-
- case '\\':
- if (escape && !(c = *p++))
- return (char *)p-1;
- continue;
- }
-
- p = Next(p-1, pend, enc);
+ switch (c) {
+ case '[':
+ open = 1;
+ continue;
+ case ']':
+ open = 0;
+ continue;
+
+ case '{':
+ open = 1;
+ continue;
+ case '}':
+ open = 0;
+ continue;
+
+ case '/':
+ if (!open)
+ return (char *)p-1;
+ continue;
+
+ case '\\':
+ if (escape && !(c = *p++))
+ return (char *)p-1;
+ continue;
+ }
+
+ p = Next(p-1, pend, enc);
}
return (char *)p-1;
@@ -1629,20 +1636,20 @@ remove_backslashes(char *p, register const char *pend, rb_encoding *enc)
char *s = p;
while (*p) {
- if (*p == '\\') {
- if (t != s)
- memmove(t, s, p - s);
- t += p - s;
- s = ++p;
- if (!*p) break;
- }
- Inc(p, pend, enc);
+ if (*p == '\\') {
+ if (t != s)
+ memmove(t, s, p - s);
+ t += p - s;
+ s = ++p;
+ if (!*p) break;
+ }
+ Inc(p, pend, enc);
}
while (*p++);
if (t != s)
- memmove(t, s, p - s); /* move '\0' too */
+ memmove(t, s, p - s); /* move '\0' too */
return p;
}
@@ -1663,49 +1670,49 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
int recursive = 0;
while (p < e && *p) {
- tmp = GLOB_ALLOC(struct glob_pattern);
- if (!tmp) goto error;
- if (p + 2 < e && p[0] == '*' && p[1] == '*' && p[2] == '/') {
- /* fold continuous RECURSIVEs (needed in glob_helper) */
- do { p += 3; while (*p == '/') p++; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
- tmp->type = RECURSIVE;
- tmp->str = 0;
- dirsep = 1;
- recursive = 1;
- }
- else {
- const char *m = find_dirsep(p, e, flags, enc);
- const enum glob_pattern_type magic = has_magic(p, m, flags, enc);
- const enum glob_pattern_type non_magic = (USE_NAME_ON_FS || FNM_SYSCASE) ? PLAIN : ALPHA;
- char *buf;
-
- if (!(FNM_SYSCASE || magic > non_magic) && !recursive && *m) {
- const char *m2;
- while (has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) <= non_magic &&
- *m2) {
- m = m2;
- }
- }
- buf = GLOB_ALLOC_N(char, m-p+1);
- if (!buf) {
- GLOB_FREE(tmp);
- goto error;
- }
- memcpy(buf, p, m-p);
- buf[m-p] = '\0';
- tmp->type = magic > MAGICAL ? MAGICAL : magic > non_magic ? magic : PLAIN;
- tmp->str = buf;
- if (*m) {
- dirsep = 1;
- p = m + 1;
- }
- else {
- dirsep = 0;
- p = m;
- }
- }
- *tail = tmp;
- tail = &tmp->next;
+ tmp = GLOB_ALLOC(struct glob_pattern);
+ if (!tmp) goto error;
+ if (p + 2 < e && p[0] == '*' && p[1] == '*' && p[2] == '/') {
+ /* fold continuous RECURSIVEs (needed in glob_helper) */
+ do { p += 3; while (*p == '/') p++; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
+ tmp->type = RECURSIVE;
+ tmp->str = 0;
+ dirsep = 1;
+ recursive = 1;
+ }
+ else {
+ const char *m = find_dirsep(p, e, flags, enc);
+ const enum glob_pattern_type magic = has_magic(p, m, flags, enc);
+ const enum glob_pattern_type non_magic = (USE_NAME_ON_FS || FNM_SYSCASE) ? PLAIN : ALPHA;
+ char *buf;
+
+ if (!(FNM_SYSCASE || magic > non_magic) && !recursive && *m) {
+ const char *m2;
+ while (has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) <= non_magic &&
+ *m2) {
+ m = m2;
+ }
+ }
+ buf = GLOB_ALLOC_N(char, m-p+1);
+ if (!buf) {
+ GLOB_FREE(tmp);
+ goto error;
+ }
+ memcpy(buf, p, m-p);
+ buf[m-p] = '\0';
+ tmp->type = magic > MAGICAL ? MAGICAL : magic > non_magic ? magic : PLAIN;
+ tmp->str = buf;
+ if (*m) {
+ dirsep = 1;
+ p = m + 1;
+ }
+ else {
+ dirsep = 0;
+ p = m;
+ }
+ }
+ *tail = tmp;
+ tail = &tmp->next;
}
tmp = GLOB_ALLOC(struct glob_pattern);
@@ -1729,11 +1736,11 @@ static void
glob_free_pattern(struct glob_pattern *list)
{
while (list) {
- struct glob_pattern *tmp = list;
- list = list->next;
- if (tmp->str)
- GLOB_FREE(tmp->str);
- GLOB_FREE(tmp);
+ struct glob_pattern *tmp = list;
+ list = list->next;
+ if (tmp->str)
+ GLOB_FREE(tmp->str);
+ GLOB_FREE(tmp);
}
}
@@ -1745,7 +1752,7 @@ join_path(const char *path, size_t len, int dirsep, const char *name, size_t nam
if (!buf) return 0;
memcpy(buf, path, len);
if (dirsep) {
- buf[len++] = '/';
+ buf[len++] = '/';
}
memcpy(buf+len, name, namlen);
buf[len+namlen] = '\0';
@@ -1762,8 +1769,8 @@ static int
is_case_sensitive(DIR *dirp, const char *path)
{
struct {
- u_int32_t length;
- vol_capabilities_attr_t cap[1];
+ u_int32_t length;
+ vol_capabilities_attr_t cap[1];
} __attribute__((aligned(4), packed)) attrbuf[1];
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, 0, ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES};
const vol_capabilities_attr_t *const cap = attrbuf[0].cap;
@@ -1772,13 +1779,13 @@ is_case_sensitive(DIR *dirp, const char *path)
# if defined HAVE_FGETATTRLIST
if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
- return -1;
+ return -1;
# else
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
- return -1;
+ return -1;
# endif
if (!(cap->valid[idx] & mask))
- return -1;
+ return -1;
return (cap->capabilities[idx] & mask) != 0;
}
@@ -1786,10 +1793,10 @@ static char *
replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int flags, rb_pathtype_t *type)
{
struct {
- u_int32_t length;
- attrreference_t ref[1];
- fsobj_type_t objtype;
- char path[MAXPATHLEN * 3];
+ u_int32_t length;
+ attrreference_t ref[1];
+ fsobj_type_t objtype;
+ char path[MAXPATHLEN * 3];
} __attribute__((aligned(4), packed)) attrbuf[1];
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME|ATTR_CMN_OBJTYPE};
const attrreference_t *const ar = attrbuf[0].ref;
@@ -1800,9 +1807,9 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
*type = path_noent;
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) {
- if (!to_be_ignored(errno))
- sys_warning(path, enc);
- return path;
+ if (!to_be_ignored(errno))
+ sys_warning(path, enc);
+ return path;
}
switch (attrbuf[0].objtype) {
@@ -1814,21 +1821,21 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
name = (char *)ar + ar->attr_dataoffset;
len = (long)ar->attr_length - 1;
if (name + len > (char *)attrbuf + sizeof(attrbuf))
- return path;
+ return path;
# if NORMALIZE_UTF8PATH
if (norm_p && has_nonascii(name, len)) {
- if (!NIL_P(utf8str = rb_str_normalize_ospath(name, len))) {
- RSTRING_GETMEM(utf8str, name, len);
- }
+ if (!NIL_P(utf8str = rb_str_normalize_ospath(name, len))) {
+ RSTRING_GETMEM(utf8str, name, len);
+ }
}
# endif
tmp = GLOB_REALLOC(path, base + len + 1);
if (tmp) {
- path = tmp;
- memcpy(path + base, name, len);
- path[base + len] = '\0';
+ path = tmp;
+ memcpy(path + base, name, len);
+ path[base + len] = '\0';
}
IF_NORMALIZE_UTF8PATH(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
return path;
@@ -1849,62 +1856,62 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
long wlen;
int e = 0;
if (!fundamental_encoding_p(enc)) {
- tmp = rb_enc_str_new_cstr(plainname, enc);
- tmp = rb_str_encode_ospath(tmp);
- plainname = RSTRING_PTR(tmp);
+ tmp = rb_enc_str_new_cstr(plainname, enc);
+ tmp = rb_str_encode_ospath(tmp);
+ plainname = RSTRING_PTR(tmp);
}
wplain = rb_w32_mbstr_to_wstr(CP_UTF8, plainname, -1, &wlen);
if (tmp) rb_str_resize(tmp, 0);
if (!wplain) return path;
if (GetFileAttributesExW(wplain, GetFileExInfoStandard, &fa)) {
- h = FindFirstFileW(wplain, &fd);
- e = rb_w32_map_errno(GetLastError());
+ h = FindFirstFileW(wplain, &fd);
+ e = rb_w32_map_errno(GetLastError());
}
if (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- if (!rb_w32_reparse_symlink_p(wplain))
- fa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
+ if (!rb_w32_reparse_symlink_p(wplain))
+ fa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
}
free(wplain);
if (h == INVALID_HANDLE_VALUE) {
- *type = path_noent;
- if (e && !to_be_ignored(e)) {
- errno = e;
- sys_warning(path, enc);
- }
- return path;
+ *type = path_noent;
+ if (e && !to_be_ignored(e)) {
+ errno = e;
+ sys_warning(path, enc);
+ }
+ return path;
}
FindClose(h);
*type =
- (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? path_symlink :
- (fa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? path_directory :
- path_regular;
+ (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? path_symlink :
+ (fa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? path_directory :
+ path_regular;
if (tmp) {
- char *buf;
- tmp = rb_w32_conv_from_wchar(fd.cFileName, enc);
- wlen = RSTRING_LEN(tmp);
- buf = GLOB_REALLOC(path, base + wlen + 1);
- if (buf) {
- path = buf;
- memcpy(path + base, RSTRING_PTR(tmp), wlen);
- path[base + wlen] = 0;
- }
- rb_str_resize(tmp, 0);
+ char *buf;
+ tmp = rb_w32_conv_from_wchar(fd.cFileName, enc);
+ wlen = RSTRING_LEN(tmp);
+ buf = GLOB_REALLOC(path, base + wlen + 1);
+ if (buf) {
+ path = buf;
+ memcpy(path + base, RSTRING_PTR(tmp), wlen);
+ path[base + wlen] = 0;
+ }
+ rb_str_resize(tmp, 0);
}
else {
- char *utf8filename;
- wlen = WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, NULL, 0, NULL, NULL);
- utf8filename = GLOB_REALLOC(0, wlen);
- if (utf8filename) {
- char *buf;
- WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, utf8filename, wlen, NULL, NULL);
- buf = GLOB_REALLOC(path, base + wlen + 1);
- if (buf) {
- path = buf;
- memcpy(path + base, utf8filename, wlen);
- path[base + wlen] = 0;
- }
- GLOB_FREE(utf8filename);
- }
+ char *utf8filename;
+ wlen = WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, NULL, 0, NULL, NULL);
+ utf8filename = GLOB_REALLOC(0, wlen);
+ if (utf8filename) {
+ char *buf;
+ WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, utf8filename, wlen, NULL, NULL);
+ buf = GLOB_REALLOC(path, base + wlen + 1);
+ if (buf) {
+ path = buf;
+ memcpy(path + base, utf8filename, wlen);
+ path[base + wlen] = 0;
+ }
+ GLOB_FREE(utf8filename);
+ }
}
return path;
}
@@ -1991,8 +1998,12 @@ rb_glob_error(const char *path, VALUE a, const void *enc, int error)
struct glob_error_args args;
VALUE (*errfunc)(VALUE) = glob_func_error;
- if (error == EACCES) {
- errfunc = glob_func_warning;
+ switch (error) {
+ case EACCES:
+#ifdef ENOTCAPABLE
+ case ENOTCAPABLE:
+#endif
+ errfunc = glob_func_warning;
}
args.path = path;
args.enc = enc;
@@ -2016,7 +2027,7 @@ dirent_match(const char *pat, rb_encoding *enc, const char *name, const rb_diren
if (fnmatch(pat, enc, name, flags) == 0) return 1;
#ifdef _WIN32
if (dp->d_altname && (flags & FNM_SHORTNAME)) {
- if (fnmatch(pat, enc, dp->d_altname, flags) == 0) return 1;
+ if (fnmatch(pat, enc, dp->d_altname, flags) == 0) return 1;
}
#endif
return 0;
@@ -2057,39 +2068,39 @@ join_path_from_pattern(struct glob_pattern **beg)
size_t path_len = 0;
for (p = *beg; p; p = p->next) {
- const char *str;
- switch (p->type) {
- case RECURSIVE:
- str = "**";
- break;
- case MATCH_DIR:
- /* append last slash */
- str = "";
- break;
- default:
- str = p->str;
- if (!str) continue;
- }
- if (!path) {
- path_len = strlen(str);
- path = GLOB_ALLOC_N(char, path_len + 1);
+ const char *str;
+ switch (p->type) {
+ case RECURSIVE:
+ str = "**";
+ break;
+ case MATCH_DIR:
+ /* append last slash */
+ str = "";
+ break;
+ default:
+ str = p->str;
+ if (!str) continue;
+ }
+ if (!path) {
+ path_len = strlen(str);
+ path = GLOB_ALLOC_N(char, path_len + 1);
if (path) {
memcpy(path, str, path_len);
path[path_len] = '\0';
}
}
else {
- size_t len = strlen(str);
- char *tmp;
- tmp = GLOB_REALLOC(path, path_len + len + 2);
- if (tmp) {
- path = tmp;
- path[path_len++] = '/';
- memcpy(path + path_len, str, len);
- path_len += len;
- path[path_len] = '\0';
- }
- }
+ size_t len = strlen(str);
+ char *tmp;
+ tmp = GLOB_REALLOC(path, path_len + len + 2);
+ if (tmp) {
+ path = tmp;
+ path[path_len++] = '/';
+ memcpy(path + path_len, str, len);
+ path_len += len;
+ path[path_len] = '\0';
+ }
+ }
}
return path;
}
@@ -2097,7 +2108,7 @@ join_path_from_pattern(struct glob_pattern **beg)
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);
+ rb_encoding *enc, VALUE var);
static const size_t rb_dirent_name_offset =
offsetof(rb_dirent_t, d_type) + sizeof(uint8_t);
@@ -2137,7 +2148,7 @@ dirent_copy(const struct dirent *dp, rb_dirent_t *rdp)
newrdp->d_altname = dp->d_altname;
#endif
}
-#ifdef DT_UNKNOWN
+#if !EMULATE_IFTODT
newrdp->d_type = dp->d_type;
#else
newrdp->d_type = 0;
@@ -2205,7 +2216,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc)
ent->sort.entries = newp;
}
#endif
- while ((dp = READDIR(dirp, enc)) != NULL) {
+ while ((dp = READDIR(dirp, enc)) != NULL) {
rb_dirent_t *rdp = dirent_copy(dp, NULL);
if (!rdp) {
goto nomem;
@@ -2277,133 +2288,133 @@ glob_helper(
rb_check_stack_overflow();
for (cur = beg; cur < end; ++cur) {
- struct glob_pattern *p = *cur;
- if (p->type == RECURSIVE) {
- recursive = 1;
- p = p->next;
- }
- switch (p->type) {
- case PLAIN:
- plain = 1;
- break;
- case ALPHA:
+ struct glob_pattern *p = *cur;
+ if (p->type == RECURSIVE) {
+ recursive = 1;
+ p = p->next;
+ }
+ switch (p->type) {
+ case PLAIN:
+ plain = 1;
+ break;
+ case ALPHA:
#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
- plain = 1;
+ plain = 1;
#else
- magical = 1;
-#endif
- break;
- case BRACE:
- if (!recursive) {
- brace = 1;
- }
- break;
- case MAGICAL:
- magical = 2;
- break;
- case MATCH_ALL:
- match_all = 1;
- break;
- case MATCH_DIR:
- match_dir = 1;
- break;
- case RECURSIVE:
- rb_bug("continuous RECURSIVEs");
- }
+ magical = 1;
+#endif
+ break;
+ case BRACE:
+ if (!recursive || strchr(p->str, '/')) {
+ brace = 1;
+ }
+ break;
+ case MAGICAL:
+ magical = 2;
+ break;
+ case MATCH_ALL:
+ match_all = 1;
+ break;
+ case MATCH_DIR:
+ match_dir = 1;
+ break;
+ case RECURSIVE:
+ rb_bug("continuous RECURSIVEs");
+ }
}
if (brace) {
- struct push_glob_args args;
- char* brace_path = join_path_from_pattern(beg);
- if (!brace_path) return -1;
- args.fd = fd;
- args.path = path;
- args.baselen = baselen;
- args.namelen = namelen;
- args.dirsep = dirsep;
- args.pathtype = pathtype;
- args.flags = flags;
- args.funcs = funcs;
- args.arg = arg;
- status = ruby_brace_expand(brace_path, flags, push_caller, (VALUE)&args, enc, Qfalse);
- GLOB_FREE(brace_path);
- return status;
+ struct push_glob_args args;
+ char* brace_path = join_path_from_pattern(beg);
+ if (!brace_path) return -1;
+ args.fd = fd;
+ args.path = path;
+ args.baselen = baselen;
+ args.namelen = namelen;
+ args.dirsep = dirsep;
+ args.pathtype = pathtype;
+ args.flags = flags;
+ args.funcs = funcs;
+ args.arg = arg;
+ status = ruby_brace_expand(brace_path, flags, push_caller, (VALUE)&args, enc, Qfalse);
+ GLOB_FREE(brace_path);
+ return status;
}
if (*path) {
- if (match_all && pathtype == path_unknown) {
- if (do_lstat(fd, baselen, path, &st, flags, enc) == 0) {
- pathtype = IFTODT(st.st_mode);
- }
- else {
- pathtype = path_noent;
- }
- }
- if (match_dir && (pathtype == path_unknown || pathtype == path_symlink)) {
- if (do_stat(fd, baselen, path, &st, flags, enc) == 0) {
- pathtype = IFTODT(st.st_mode);
- }
- else {
- pathtype = path_noent;
- }
- }
- if (match_all && pathtype > path_noent) {
- const char *subpath = path + baselen + (baselen && path[baselen] == '/');
- status = glob_call_func(funcs->match, subpath, arg, enc);
- if (status) return status;
- }
- if (match_dir && pathtype == path_directory) {
- int seplen = (baselen && path[baselen] == '/');
- const char *subpath = path + baselen + seplen;
- char *tmp = join_path(subpath, namelen - seplen, dirsep, "", 0);
- if (!tmp) return -1;
- status = glob_call_func(funcs->match, tmp, arg, enc);
- GLOB_FREE(tmp);
- if (status) return status;
- }
+ if (match_all && pathtype == path_unknown) {
+ if (do_lstat(fd, baselen, path, &st, flags, enc) == 0) {
+ pathtype = IFTODT(st.st_mode);
+ }
+ else {
+ pathtype = path_noent;
+ }
+ }
+ if (match_dir && (pathtype == path_unknown || pathtype == path_symlink)) {
+ if (do_stat(fd, baselen, path, &st, flags, enc) == 0) {
+ pathtype = IFTODT(st.st_mode);
+ }
+ else {
+ pathtype = path_noent;
+ }
+ }
+ if (match_all && pathtype > path_noent) {
+ const char *subpath = path + baselen + (baselen && path[baselen] == '/');
+ status = glob_call_func(funcs->match, subpath, arg, enc);
+ if (status) return status;
+ }
+ if (match_dir && pathtype == path_directory) {
+ int seplen = (baselen && path[baselen] == '/');
+ const char *subpath = path + baselen + seplen;
+ char *tmp = join_path(subpath, namelen - seplen, dirsep, "", 0);
+ if (!tmp) return -1;
+ status = glob_call_func(funcs->match, tmp, arg, enc);
+ GLOB_FREE(tmp);
+ if (status) return status;
+ }
}
if (pathtype == path_noent) return 0;
if (magical || recursive) {
- rb_dirent_t *dp;
- DIR *dirp;
+ rb_dirent_t *dp;
+ DIR *dirp;
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
- char *plainname = 0;
+ char *plainname = 0;
# endif
- IF_NORMALIZE_UTF8PATH(int norm_p);
+ IF_NORMALIZE_UTF8PATH(int norm_p);
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
- if (cur + 1 == end && (*cur)->type <= ALPHA) {
- plainname = join_path(path, pathlen, dirsep, (*cur)->str, strlen((*cur)->str));
- if (!plainname) return -1;
- dirp = do_opendir(fd, basename, plainname, flags, enc, funcs->error, arg, &status);
- GLOB_FREE(plainname);
- }
- else
+ if (cur + 1 == end && (*cur)->type <= ALPHA) {
+ plainname = join_path(path, pathlen, dirsep, (*cur)->str, strlen((*cur)->str));
+ if (!plainname) return -1;
+ dirp = do_opendir(fd, basename, plainname, flags, enc, funcs->error, arg, &status);
+ GLOB_FREE(plainname);
+ }
+ else
# else
- ;
+ ;
# endif
- dirp = do_opendir(fd, baselen, path, flags, enc, funcs->error, arg, &status);
- if (dirp == NULL) {
+ dirp = do_opendir(fd, baselen, path, flags, enc, funcs->error, arg, &status);
+ if (dirp == NULL) {
# if FNM_SYSCASE || NORMALIZE_UTF8PATH
- if ((magical < 2) && !recursive && (errno == EACCES)) {
- /* no read permission, fallback */
- goto literally;
- }
+ if ((magical < 2) && !recursive && (errno == EACCES)) {
+ /* no read permission, fallback */
+ goto literally;
+ }
# endif
- return status;
- }
- IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp, *path ? path : "."));
+ return status;
+ }
+ IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp, *path ? path : "."));
# if NORMALIZE_UTF8PATH
- if (!(norm_p || magical || recursive)) {
- closedir(dirp);
- goto literally;
- }
+ if (!(norm_p || magical || recursive)) {
+ closedir(dirp);
+ goto literally;
+ }
# endif
# ifdef HAVE_GETATTRLIST
- if (is_case_sensitive(dirp, path) == 0)
- flags |= FNM_CASEFOLD;
+ if (is_case_sensitive(dirp, path) == 0)
+ flags |= FNM_CASEFOLD;
# endif
ruby_glob_entries_t globent;
if (!glob_opendir(&globent, dirp, flags, enc)) {
@@ -2417,182 +2428,182 @@ glob_helper(
return status;
}
- int skipdot = (flags & FNM_GLOB_SKIPDOT);
- flags |= FNM_GLOB_SKIPDOT;
-
- while ((dp = glob_getent(&globent, flags, enc)) != NULL) {
- char *buf;
- rb_pathtype_t new_pathtype = path_unknown;
- const char *name;
- size_t namlen;
- int dotfile = 0;
- IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
-
- name = dp->d_name;
- namlen = dp->d_namlen;
- if (name[0] == '.') {
- ++dotfile;
- if (namlen == 1) {
- /* unless DOTMATCH, skip current directories not to recurse infinitely */
- if (recursive && !(flags & FNM_DOTMATCH)) continue;
- if (skipdot) continue;
- ++dotfile;
- new_pathtype = path_directory; /* force to skip stat/lstat */
- }
- else if (namlen == 2 && name[1] == '.') {
- /* always skip parent directories not to recurse infinitely */
- continue;
- }
- }
+ int skipdot = (flags & FNM_GLOB_SKIPDOT);
+ flags |= FNM_GLOB_SKIPDOT;
+
+ while ((dp = glob_getent(&globent, flags, enc)) != NULL) {
+ char *buf;
+ rb_pathtype_t new_pathtype = path_unknown;
+ const char *name;
+ size_t namlen;
+ int dotfile = 0;
+ IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
+
+ name = dp->d_name;
+ namlen = dp->d_namlen;
+ if (name[0] == '.') {
+ ++dotfile;
+ if (namlen == 1) {
+ /* unless DOTMATCH, skip current directories not to recurse infinitely */
+ if (recursive && !(flags & FNM_DOTMATCH)) continue;
+ if (skipdot) continue;
+ ++dotfile;
+ new_pathtype = path_directory; /* force to skip stat/lstat */
+ }
+ else if (namlen == 2 && name[1] == '.') {
+ /* always skip parent directories not to recurse infinitely */
+ continue;
+ }
+ }
# if NORMALIZE_UTF8PATH
- if (norm_p && has_nonascii(name, namlen)) {
- if (!NIL_P(utf8str = rb_str_normalize_ospath(name, namlen))) {
- RSTRING_GETMEM(utf8str, name, namlen);
- }
- }
+ if (norm_p && has_nonascii(name, namlen)) {
+ if (!NIL_P(utf8str = rb_str_normalize_ospath(name, namlen))) {
+ RSTRING_GETMEM(utf8str, name, namlen);
+ }
+ }
# endif
- buf = join_path(path, pathlen, dirsep, name, namlen);
- IF_NORMALIZE_UTF8PATH(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
- if (!buf) {
- status = -1;
- break;
- }
- name = buf + pathlen + (dirsep != 0);
-#ifdef DT_UNKNOWN
- if (dp->d_type != DT_UNKNOWN) {
- /* Got it. We need no more lstat. */
- new_pathtype = dp->d_type;
- }
-#endif
- if (recursive && dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1) &&
- new_pathtype == path_unknown) {
- /* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
- if (do_lstat(fd, baselen, buf, &st, flags, enc) == 0)
- new_pathtype = IFTODT(st.st_mode);
- else
- new_pathtype = path_noent;
- }
-
- new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
- if (!new_beg) {
- GLOB_FREE(buf);
- status = -1;
- break;
- }
-
- for (cur = beg; cur < end; ++cur) {
- struct glob_pattern *p = *cur;
- struct dirent_brace_args args;
- if (p->type == RECURSIVE) {
- if (new_pathtype == path_directory || /* not symlink but real directory */
- new_pathtype == path_exist) {
- if (dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1))
- *new_end++ = p; /* append recursive pattern */
- }
- p = p->next; /* 0 times recursion */
- }
- switch (p->type) {
- case BRACE:
- args.name = name;
- args.dp = dp;
- args.flags = flags;
- if (ruby_brace_expand(p->str, flags, dirent_match_brace,
- (VALUE)&args, enc, Qfalse) > 0)
- *new_end++ = p->next;
- break;
- case ALPHA:
+ buf = join_path(path, pathlen, dirsep, name, namlen);
+ IF_NORMALIZE_UTF8PATH(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
+ if (!buf) {
+ status = -1;
+ break;
+ }
+ name = buf + pathlen + (dirsep != 0);
+#if !EMULATE_IFTODT
+ if (dp->d_type != DT_UNKNOWN) {
+ /* Got it. We need no more lstat. */
+ new_pathtype = dp->d_type;
+ }
+#endif
+ if (recursive && dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1) &&
+ new_pathtype == path_unknown) {
+ /* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
+ if (do_lstat(fd, baselen, buf, &st, flags, enc) == 0)
+ new_pathtype = IFTODT(st.st_mode);
+ else
+ new_pathtype = path_noent;
+ }
+
+ new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
+ if (!new_beg) {
+ GLOB_FREE(buf);
+ status = -1;
+ break;
+ }
+
+ for (cur = beg; cur < end; ++cur) {
+ struct glob_pattern *p = *cur;
+ struct dirent_brace_args args;
+ if (p->type == RECURSIVE) {
+ if (new_pathtype == path_directory || /* not symlink but real directory */
+ new_pathtype == path_exist) {
+ if (dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1))
+ *new_end++ = p; /* append recursive pattern */
+ }
+ p = p->next; /* 0 times recursion */
+ }
+ switch (p->type) {
+ case BRACE:
+ args.name = name;
+ args.dp = dp;
+ args.flags = flags;
+ if (ruby_brace_expand(p->str, flags, dirent_match_brace,
+ (VALUE)&args, enc, Qfalse) > 0)
+ *new_end++ = p->next;
+ break;
+ case ALPHA:
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
- if (plainname) {
- *new_end++ = p->next;
- break;
- }
+ if (plainname) {
+ *new_end++ = p->next;
+ break;
+ }
# endif
- case PLAIN:
- case MAGICAL:
- if (dirent_match(p->str, enc, name, dp, flags))
- *new_end++ = p->next;
- default:
- break;
- }
- }
-
- status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1,
- new_pathtype, new_beg, new_end,
- flags, funcs, arg, enc);
- GLOB_FREE(buf);
- GLOB_FREE(new_beg);
- if (status) break;
- }
+ case PLAIN:
+ case MAGICAL:
+ if (dirent_match(p->str, enc, name, dp, flags))
+ *new_end++ = p->next;
+ default:
+ break;
+ }
+ }
+
+ status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1,
+ new_pathtype, new_beg, new_end,
+ flags, funcs, arg, enc);
+ GLOB_FREE(buf);
+ GLOB_FREE(new_beg);
+ if (status) break;
+ }
glob_dir_finish(&globent, flags);
}
else if (plain) {
- struct glob_pattern **copy_beg, **copy_end, **cur2;
+ struct glob_pattern **copy_beg, **copy_end, **cur2;
# if FNM_SYSCASE || NORMALIZE_UTF8PATH
literally:
# endif
- copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
- if (!copy_beg) return -1;
- for (cur = beg; cur < end; ++cur)
- *copy_end++ = (*cur)->type <= ALPHA ? *cur : 0;
-
- for (cur = copy_beg; cur < copy_end; ++cur) {
- if (*cur) {
- rb_pathtype_t new_pathtype = path_unknown;
- char *buf;
- char *name;
- size_t len = strlen((*cur)->str) + 1;
- name = GLOB_ALLOC_N(char, len);
- if (!name) {
- status = -1;
- break;
- }
- memcpy(name, (*cur)->str, len);
- if (escape)
- len = remove_backslashes(name, name+len-1, enc) - name;
-
- new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
- if (!new_beg) {
- GLOB_FREE(name);
- status = -1;
- break;
- }
- *new_end++ = (*cur)->next;
- for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
- if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
- *new_end++ = (*cur2)->next;
- *cur2 = 0;
- }
- }
-
- buf = join_path(path, pathlen, dirsep, name, len);
- GLOB_FREE(name);
- if (!buf) {
- GLOB_FREE(new_beg);
- status = -1;
- break;
- }
+ copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
+ if (!copy_beg) return -1;
+ for (cur = beg; cur < end; ++cur)
+ *copy_end++ = (*cur)->type <= ALPHA ? *cur : 0;
+
+ for (cur = copy_beg; cur < copy_end; ++cur) {
+ if (*cur) {
+ rb_pathtype_t new_pathtype = path_unknown;
+ char *buf;
+ char *name;
+ size_t len = strlen((*cur)->str) + 1;
+ name = GLOB_ALLOC_N(char, len);
+ if (!name) {
+ status = -1;
+ break;
+ }
+ memcpy(name, (*cur)->str, len);
+ if (escape)
+ len = remove_backslashes(name, name+len-1, enc) - name;
+
+ new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
+ if (!new_beg) {
+ GLOB_FREE(name);
+ status = -1;
+ break;
+ }
+ *new_end++ = (*cur)->next;
+ for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
+ if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
+ *new_end++ = (*cur2)->next;
+ *cur2 = 0;
+ }
+ }
+
+ buf = join_path(path, pathlen, dirsep, name, len);
+ GLOB_FREE(name);
+ if (!buf) {
+ GLOB_FREE(new_beg);
+ status = -1;
+ break;
+ }
#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
- if ((*cur)->type == ALPHA) {
- buf = replace_real_basename(buf, pathlen + (dirsep != 0), enc,
- IF_NORMALIZE_UTF8PATH(1)+0,
- flags, &new_pathtype);
- if (!buf) break;
- }
-#endif
- status = glob_helper(fd, buf, baselen,
- namelen + strlen(buf + pathlen), 1,
- new_pathtype, new_beg, new_end,
- flags, funcs, arg, enc);
- GLOB_FREE(buf);
- GLOB_FREE(new_beg);
- if (status) break;
- }
- }
-
- GLOB_FREE(copy_beg);
+ if ((*cur)->type == ALPHA) {
+ buf = replace_real_basename(buf, pathlen + (dirsep != 0), enc,
+ IF_NORMALIZE_UTF8PATH(1)+0,
+ flags, &new_pathtype);
+ if (!buf) break;
+ }
+#endif
+ status = glob_helper(fd, buf, baselen,
+ namelen + strlen(buf + pathlen), 1,
+ new_pathtype, new_beg, new_end,
+ flags, funcs, arg, enc);
+ GLOB_FREE(buf);
+ GLOB_FREE(new_beg);
+ if (status) break;
+ }
+ }
+
+ GLOB_FREE(copy_beg);
}
return status;
@@ -2607,11 +2618,11 @@ push_caller(const char *path, VALUE val, void *enc)
list = glob_make_pattern(path, path + strlen(path), arg->flags, enc);
if (!list) {
- return -1;
+ return -1;
}
status = glob_helper(arg->fd, arg->path, arg->baselen, arg->namelen, arg->dirsep,
- arg->pathtype, &list, &list + 1, arg->flags, arg->funcs,
- arg->arg, enc);
+ arg->pathtype, &list, &list + 1, arg->flags, arg->funcs,
+ arg->arg, enc);
glob_free_pattern(list);
return status;
}
@@ -2636,8 +2647,8 @@ push_glob0_caller(const char *path, VALUE val, void *enc)
static int
ruby_glob0(const char *path, int fd, const char *base, int flags,
- const ruby_glob_funcs_t *funcs, VALUE arg,
- rb_encoding *enc)
+ const ruby_glob_funcs_t *funcs, VALUE arg,
+ rb_encoding *enc)
{
struct glob_pattern *list;
const char *root, *start;
@@ -2666,10 +2677,10 @@ ruby_glob0(const char *path, int fd, const char *base, int flags,
n = root - start;
if (!n && base) {
- n = strlen(base);
- baselen = n;
- start = base;
- dirsep = TRUE;
+ n = strlen(base);
+ baselen = n;
+ start = base;
+ dirsep = TRUE;
}
buf = GLOB_ALLOC_N(char, n + 1);
if (!buf) return -1;
@@ -2678,12 +2689,12 @@ ruby_glob0(const char *path, int fd, const char *base, int flags,
list = glob_make_pattern(root, root + strlen(root), flags, enc);
if (!list) {
- GLOB_FREE(buf);
- return -1;
+ GLOB_FREE(buf);
+ return -1;
}
status = glob_helper(fd, buf, baselen, n-baselen, dirsep,
- path_unknown, &list, &list + 1,
- flags, funcs, arg, enc);
+ path_unknown, &list, &list + 1,
+ flags, funcs, arg, enc);
glob_free_pattern(list);
GLOB_FREE(buf);
@@ -2697,7 +2708,7 @@ ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
funcs.match = func;
funcs.error = 0;
return ruby_glob0(path, AT_FDCWD, 0, flags & ~GLOB_VERBOSE,
- &funcs, arg, rb_ascii8bit_encoding());
+ &funcs, arg, rb_ascii8bit_encoding());
}
static int
@@ -2726,7 +2737,7 @@ rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg)
args.enc = rb_ascii8bit_encoding();
status = ruby_glob0(path, AT_FDCWD, 0, GLOB_VERBOSE, &rb_glob_funcs,
- (VALUE)&args, args.enc);
+ (VALUE)&args, args.enc);
if (status) GLOB_JUMP_TAG(status);
}
@@ -2745,7 +2756,7 @@ push_pattern(const char *path, VALUE ary, void *enc)
static int
ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
- rb_encoding *enc, VALUE var)
+ rb_encoding *enc, VALUE var)
{
const int escape = !(flags & FNM_NOESCAPE);
const char *p = str;
@@ -2755,48 +2766,48 @@ ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
int nest = 0, status = 0;
while (*p) {
- if (*p == '{' && nest++ == 0) {
- lbrace = p;
- }
- if (*p == '}' && lbrace && --nest == 0) {
- rbrace = p;
- break;
- }
- if (*p == '\\' && escape) {
- if (!*++p) break;
- }
- Inc(p, pend, enc);
+ if (*p == '{' && nest++ == 0) {
+ lbrace = p;
+ }
+ if (*p == '}' && lbrace && --nest == 0) {
+ rbrace = p;
+ break;
+ }
+ if (*p == '\\' && escape) {
+ if (!*++p) break;
+ }
+ Inc(p, pend, enc);
}
if (lbrace && rbrace) {
- size_t len = strlen(s) + 1;
- char *buf = GLOB_ALLOC_N(char, len);
- long shift;
-
- if (!buf) return -1;
- memcpy(buf, s, lbrace-s);
- shift = (lbrace-s);
- p = lbrace;
- while (p < rbrace) {
- const char *t = ++p;
- nest = 0;
- while (p < rbrace && !(*p == ',' && nest == 0)) {
- if (*p == '{') nest++;
- if (*p == '}') nest--;
- if (*p == '\\' && escape) {
- if (++p == rbrace) break;
- }
- Inc(p, pend, enc);
- }
- memcpy(buf+shift, t, p-t);
- strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
- status = ruby_brace_expand(buf, flags, func, arg, enc, var);
- if (status) break;
- }
- GLOB_FREE(buf);
+ size_t len = strlen(s) + 1;
+ char *buf = GLOB_ALLOC_N(char, len);
+ long shift;
+
+ if (!buf) return -1;
+ memcpy(buf, s, lbrace-s);
+ shift = (lbrace-s);
+ p = lbrace;
+ while (p < rbrace) {
+ const char *t = ++p;
+ nest = 0;
+ while (p < rbrace && !(*p == ',' && nest == 0)) {
+ if (*p == '{') nest++;
+ if (*p == '}') nest--;
+ if (*p == '\\' && escape) {
+ if (++p == rbrace) break;
+ }
+ Inc(p, pend, enc);
+ }
+ memcpy(buf+shift, t, p-t);
+ strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
+ status = ruby_brace_expand(buf, flags, func, arg, enc, var);
+ if (status) break;
+ }
+ GLOB_FREE(buf);
}
else if (!lbrace && !rbrace) {
- status = glob_call_func(func, s, arg, enc);
+ status = glob_call_func(func, s, arg, enc);
}
RB_GC_GUARD(var);
@@ -2847,9 +2858,9 @@ push_glob(VALUE ary, VALUE str, VALUE base, int flags)
str = rb_str_encode_ospath(str);
#endif
if (rb_enc_to_index(enc) == ENCINDEX_US_ASCII)
- enc = rb_filesystem_encoding();
+ enc = rb_filesystem_encoding();
if (rb_enc_to_index(enc) == ENCINDEX_US_ASCII)
- enc = rb_ascii8bit_encoding();
+ enc = rb_ascii8bit_encoding();
flags |= GLOB_VERBOSE;
args.func = push_pattern;
args.value = ary;
@@ -2857,23 +2868,23 @@ push_glob(VALUE ary, VALUE str, VALUE base, int flags)
args.base = 0;
fd = AT_FDCWD;
if (!NIL_P(base)) {
- if (!RB_TYPE_P(base, T_STRING) || !rb_enc_check(str, base)) {
- struct dir_data *dirp = DATA_PTR(base);
- if (!dirp->dir) dir_closed();
+ if (!RB_TYPE_P(base, T_STRING) || !rb_enc_check(str, base)) {
+ struct dir_data *dirp = DATA_PTR(base);
+ if (!dirp->dir) dir_closed();
#ifdef HAVE_DIRFD
- if ((fd = dirfd(dirp->dir)) == -1)
- rb_sys_fail_path(dir_inspect(base));
+ if ((fd = dirfd(dirp->dir)) == -1)
+ rb_sys_fail_path(dir_inspect(base));
#endif
- base = dirp->path;
- }
- args.base = RSTRING_PTR(base);
+ base = dirp->path;
+ }
+ args.base = RSTRING_PTR(base);
}
#if defined _WIN32 || defined __APPLE__
enc = rb_utf8_encoding();
#endif
return ruby_glob0(RSTRING_PTR(str), fd, args.base, flags, &rb_glob_funcs,
- (VALUE)&args, enc);
+ (VALUE)&args, enc);
}
static VALUE
@@ -2884,13 +2895,13 @@ rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */
/* can contain null bytes as separators */
if (!RB_TYPE_P(str, T_STRING)) {
- FilePathValue(str);
+ FilePathValue(str);
}
else if (!rb_str_to_cstr(str)) {
rb_raise(rb_eArgError, "nul-separated glob pattern is deprecated");
}
else {
- rb_enc_check(str, rb_enc_from_encoding(rb_usascii_encoding()));
+ rb_enc_check(str, rb_enc_from_encoding(rb_usascii_encoding()));
}
ary = rb_ary_new();
@@ -2907,11 +2918,11 @@ dir_globs(VALUE args, VALUE base, int flags)
long i;
for (i = 0; i < RARRAY_LEN(args); ++i) {
- int status;
- VALUE str = RARRAY_AREF(args, i);
- FilePathValue(str);
- status = push_glob(ary, str, base, flags);
- if (status) GLOB_JUMP_TAG(status);
+ int status;
+ 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);
@@ -2921,12 +2932,12 @@ dir_globs(VALUE args, VALUE base, int flags)
static VALUE
dir_glob_option_base(VALUE base)
{
- if (base == Qundef || NIL_P(base)) {
- return Qnil;
+ if (NIL_OR_UNDEF_P(base)) {
+ return Qnil;
}
#if USE_OPENDIR_AT
if (rb_typeddata_is_kind_of(base, &dir_data_type)) {
- return base;
+ return base;
}
#endif
FilePathValue(base);
@@ -2937,7 +2948,7 @@ dir_glob_option_base(VALUE base)
static int
dir_glob_option_sort(VALUE sort)
{
- return (sort ? 0 : FNM_GLOB_NOSORT);
+ return (rb_bool_expected(sort, "sort", TRUE) ? 0 : FNM_GLOB_NOSORT);
}
static VALUE
@@ -2946,7 +2957,7 @@ dir_s_aref(rb_execution_context_t *ec, VALUE obj, VALUE args, VALUE base, VALUE
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 rb_push_glob(RARRAY_AREF(args, 0), base, flags);
}
return dir_globs(args, base, flags);
}
@@ -2958,15 +2969,15 @@ dir_s_glob(rb_execution_context_t *ec, VALUE obj, VALUE str, VALUE rflags, VALUE
const int flags = (NUM2INT(rflags) | dir_glob_option_sort(sort)) & ~FNM_CASEFOLD;
base = dir_glob_option_base(base);
if (NIL_P(ary)) {
- ary = rb_push_glob(str, base, flags);
+ ary = rb_push_glob(str, base, flags);
}
else {
ary = dir_globs(ary, base, flags);
}
if (rb_block_given_p()) {
- rb_ary_each(ary);
- return Qnil;
+ rb_ary_each(ary);
+ return Qnil;
}
return ary;
}
@@ -3163,19 +3174,19 @@ fnmatch_brace(const char *pattern, VALUE val, void *enc)
rb_encoding *enc_path = rb_enc_get(path);
if (enc_pattern != enc_path) {
- if (!rb_enc_asciicompat(enc_pattern))
- return FNM_NOMATCH;
- if (!rb_enc_asciicompat(enc_path))
- return FNM_NOMATCH;
- if (!rb_enc_str_asciionly_p(path)) {
- int cr = ENC_CODERANGE_7BIT;
- long len = strlen(pattern);
- if (rb_str_coderange_scan_restartable(pattern, pattern + len,
- enc_pattern, &cr) != len)
- return FNM_NOMATCH;
- if (cr != ENC_CODERANGE_7BIT)
- return FNM_NOMATCH;
- }
+ if (!rb_enc_asciicompat(enc_pattern))
+ return FNM_NOMATCH;
+ if (!rb_enc_asciicompat(enc_path))
+ return FNM_NOMATCH;
+ if (!rb_enc_str_asciionly_p(path)) {
+ int cr = ENC_CODERANGE_7BIT;
+ long len = strlen(pattern);
+ if (rb_str_coderange_scan_restartable(pattern, pattern + len,
+ enc_pattern, &cr) != len)
+ return FNM_NOMATCH;
+ if (cr != ENC_CODERANGE_7BIT)
+ return FNM_NOMATCH;
+ }
}
return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0);
}
@@ -3189,27 +3200,27 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
int flags;
if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
- flags = NUM2INT(rflags);
+ flags = NUM2INT(rflags);
else
- flags = 0;
+ flags = 0;
StringValueCStr(pattern);
FilePathStringValue(path);
if (flags & FNM_EXTGLOB) {
- struct brace_args args;
+ struct brace_args args;
- args.value = path;
- args.flags = flags;
- if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
- (VALUE)&args, rb_enc_get(pattern), pattern) > 0)
- return Qtrue;
+ args.value = path;
+ args.flags = flags;
+ if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
+ (VALUE)&args, rb_enc_get(pattern), pattern) > 0)
+ return Qtrue;
}
else {
- rb_encoding *enc = rb_enc_compatible(pattern, path);
- if (!enc) return Qfalse;
- if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
- return Qtrue;
+ rb_encoding *enc = rb_enc_compatible(pattern, path);
+ if (!enc) return Qfalse;
+ if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
+ return Qtrue;
}
RB_GC_GUARD(pattern);
@@ -3233,12 +3244,12 @@ dir_s_home(int argc, VALUE *argv, VALUE obj)
rb_check_arity(argc, 0, 1);
user = (argc > 0) ? argv[0] : Qnil;
if (!NIL_P(user)) {
- SafeStringValue(user);
- rb_must_asciicompat(user);
- u = StringValueCStr(user);
- if (*u) {
- return rb_home_dir_of(user, rb_str_new(0, 0));
- }
+ SafeStringValue(user);
+ rb_must_asciicompat(user);
+ u = StringValueCStr(user);
+ if (*u) {
+ return rb_home_dir_of(user, rb_str_new(0, 0));
+ }
}
return rb_default_home_dir(rb_str_new(0, 0));
@@ -3259,14 +3270,6 @@ rb_file_directory_p(void)
}
#endif
-/* :nodoc: */
-static VALUE
-rb_dir_exists_p(VALUE obj, VALUE fname)
-{
- rb_warn_deprecated("Dir.exists?", "Dir.exist?");
- return rb_file_directory_p(obj, fname);
-}
-
static void *
nogvl_dir_empty_p(void *ptr)
{
@@ -3276,24 +3279,24 @@ nogvl_dir_empty_p(void *ptr)
VALUE result = Qtrue;
if (!dir) {
- int e = errno;
- switch (gc_for_fd_with_gvl(e)) {
- default:
- dir = opendir(path);
- if (dir) break;
- e = errno;
- /* fall through */
- case 0:
- if (e == ENOTDIR) return (void *)Qfalse;
- errno = e; /* for rb_sys_fail_path */
- return (void *)Qundef;
- }
+ int e = errno;
+ switch (gc_for_fd_with_gvl(e)) {
+ default:
+ dir = opendir(path);
+ if (dir) break;
+ e = errno;
+ /* fall through */
+ case 0:
+ if (e == ENOTDIR) return (void *)Qfalse;
+ errno = e; /* for rb_sys_fail_path */
+ return (void *)Qundef;
+ }
}
while ((dp = READDIR(dir, NULL)) != NULL) {
- if (!to_be_skipped(dp)) {
- result = Qfalse;
- break;
- }
+ if (!to_be_skipped(dp)) {
+ result = Qfalse;
+ break;
+ }
}
closedir(dir);
return (void *)result;
@@ -3321,27 +3324,27 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname)
#if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT
{
- u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
- struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0)
- rb_sys_fail_path(orig);
- if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
- al.commonattr = 0;
- al.dirattr = ATTR_DIR_ENTRYCOUNT;
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) {
- if (attrbuf[0] >= 2 * sizeof(u_int32_t))
- return attrbuf[1] ? Qfalse : Qtrue;
- if (false_on_notdir) return Qfalse;
- }
- rb_sys_fail_path(orig);
- }
+ u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
+ struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
+ if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0)
+ rb_sys_fail_path(orig);
+ if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
+ al.commonattr = 0;
+ al.dirattr = ATTR_DIR_ENTRYCOUNT;
+ if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) {
+ if (attrbuf[0] >= 2 * sizeof(u_int32_t))
+ return RBOOL(attrbuf[1] == 0);
+ if (false_on_notdir) return Qfalse;
+ }
+ rb_sys_fail_path(orig);
+ }
}
#endif
result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path,
- RUBY_UBF_IO, 0);
- if (result == Qundef) {
- rb_sys_fail_path(orig);
+ RUBY_UBF_IO, 0);
+ if (UNDEF_P(result)) {
+ rb_sys_fail_path(orig);
}
return result;
}
@@ -3385,7 +3388,6 @@ Init_Dir(void)
rb_define_singleton_method(rb_cDir,"home", dir_s_home, -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);
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
diff --git a/dir.rb b/dir.rb
index 4d27b0093e..2e426b0881 100644
--- a/dir.rb
+++ b/dir.rb
@@ -9,72 +9,79 @@
#
# == What's Here
#
-# \Class \Dir provides methods that are useful for:
+# First, what's elsewhere. \Class \Dir:
#
-# - {Reading}[#class-Dir-label-Reading]
-# - {Setting}[#class-Dir-label-Setting]
-# - {Querying}[#class-Dir-label-Querying]
-# - {Iterating}[#class-Dir-label-Iterating]
-# - {Other}[#class-Dir-label-Other]
+# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+# - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
+# which provides dozens of additional methods.
+#
+# Here, class \Dir provides methods that are useful for:
+#
+# - {Reading}[rdoc-ref:Dir@Reading]
+# - {Setting}[rdoc-ref:Dir@Setting]
+# - {Querying}[rdoc-ref:Dir@Querying]
+# - {Iterating}[rdoc-ref:Dir@Iterating]
+# - {Other}[rdoc-ref:Dir@Other]
#
# === Reading
#
-# - #close:: Closes the directory stream for +self+.
-# - #pos=:: Sets the position in the directory stream for +self+.
-# - #read:: Reads and returns the next entry in the directory stream for +self+.
-# - #rewind:: Sets the position in the directory stream for +self+ to the first entry.
-# - #seek:: Sets the position in the directory stream for +self+
-# the entry at the given offset.
+# - #close: Closes the directory stream for +self+.
+# - #pos=: Sets the position in the directory stream for +self+.
+# - #read: Reads and returns the next entry in the directory stream for +self+.
+# - #rewind: Sets the position in the directory stream for +self+ to the first entry.
+# - #seek: Sets the position in the directory stream for +self+
+# the entry at the given offset.
#
# === Setting
#
-# - ::chdir:: Changes the working directory of the current process
-# to the given directory.
-# - ::chroot:: Changes the file-system root for the current process
-# to the given directory.
+# - ::chdir: Changes the working directory of the current process
+# to the given directory.
+# - ::chroot: Changes the file-system root for the current process
+# to the given directory.
#
# === Querying
#
-# - ::[]:: Same as ::glob without the ability to pass flags.
-# - ::children:: Returns an array of names of the children
-# (both files and directories) of the given directory,
-# but not including <tt>.</tt> or <tt>..</tt>.
-# - ::empty?:: Returns whether the given path is an empty directory.
-# - ::entries:: Returns an array of names of the children
-# (both files and directories) of the given directory,
-# including <tt>.</tt> and <tt>..</tt>.
-# - ::exist?:: Returns whether the given path is a directory.
-# - ::getwd (aliased as #pwd):: Returns the path to the current working directory.
-# - ::glob:: Returns an array of file paths matching the given pattern and flags.
-# - ::home:: Returns the home directory path for a given user or the current user.
-# - #children:: Returns an array of names of the children
-# (both files and directories) of +self+,
-# but not including <tt>.</tt> or <tt>..</tt>.
-# - #fileno:: Returns the integer file descriptor for +self+.
-# - #path (aliased as #to_path):: Returns the path used to create +self+.
-# - #tell (aliased as #pos):: Returns the integer position
-# in the directory stream for +self+.
+# - ::[]: Same as ::glob without the ability to pass flags.
+# - ::children: Returns an array of names of the children
+# (both files and directories) of the given directory,
+# but not including <tt>.</tt> or <tt>..</tt>.
+# - ::empty?: Returns whether the given path is an empty directory.
+# - ::entries: Returns an array of names of the children
+# (both files and directories) of the given directory,
+# including <tt>.</tt> and <tt>..</tt>.
+# - ::exist?: Returns whether the given path is a directory.
+# - ::getwd (aliased as #pwd): Returns the path to the current working directory.
+# - ::glob: Returns an array of file paths matching the given pattern and flags.
+# - ::home: Returns the home directory path for a given user or the current user.
+# - #children: Returns an array of names of the children
+# (both files and directories) of +self+,
+# but not including <tt>.</tt> or <tt>..</tt>.
+# - #fileno: Returns the integer file descriptor for +self+.
+# - #path (aliased as #to_path): Returns the path used to create +self+.
+# - #tell (aliased as #pos): Returns the integer position
+# in the directory stream for +self+.
#
# === Iterating
#
-# - ::each_child:: Calls the given block with each entry in the given directory,
-# but not including <tt>.</tt> or <tt>..</tt>.
-# - ::foreach:: Calls the given block with each entryin the given directory,
-# including <tt>.</tt> and <tt>..</tt>.
-# - #each:: Calls the given block with each entry in +self+,
-# including <tt>.</tt> and <tt>..</tt>.
-# - #each_child:: Calls the given block with each entry in +self+,
-# but not including <tt>.</tt> or <tt>..</tt>.
+# - ::each_child: Calls the given block with each entry in the given directory,
+# but not including <tt>.</tt> or <tt>..</tt>.
+# - ::foreach: Calls the given block with each entry in the given directory,
+# including <tt>.</tt> and <tt>..</tt>.
+# - #each: Calls the given block with each entry in +self+,
+# including <tt>.</tt> and <tt>..</tt>.
+# - #each_child: Calls the given block with each entry in +self+,
+# but not including <tt>.</tt> or <tt>..</tt>.
#
# === Other
#
-# - ::mkdir:: Creates a directory at the given path, with optional permissions.
-# - ::new:: Returns a new \Dir for the given path, with optional encoding.
-# - ::open:: Same as ::new, but if a block is given, yields the \Dir to the block,
-# closing it upon block exit.
-# - ::unlink (aliased as ::delete and ::rmdir):: Removes the given directory.
-# - #inspect:: Returns a string description of +self+.
+# - ::mkdir: Creates a directory at the given path, with optional permissions.
+# - ::new: Returns a new \Dir for the given path, with optional encoding.
+# - ::open: Same as ::new, but if a block is given, yields the \Dir to the block,
+# closing it upon block exit.
+# - ::unlink (aliased as ::delete and ::rmdir): Removes the given directory.
+# - #inspect: Returns a string description of +self+.
class Dir
+ # call-seq:
# Dir.open( string ) -> aDir
# Dir.open( string, encoding: enc ) -> aDir
# Dir.open( string ) {| aDir | block } -> anObject
@@ -100,6 +107,7 @@ class Dir
end
end
+ # call-seq:
# Dir.new( string ) -> aDir
# Dir.new( string, encoding: enc ) -> aDir
#
@@ -111,6 +119,7 @@ class Dir
Primitive.dir_initialize(name, encoding)
end
+ # call-seq:
# Dir[ string [, string ...] [, base: path] [, sort: true] ] -> array
#
# Equivalent to calling
@@ -119,6 +128,7 @@ class Dir
Primitive.dir_s_aref(args, base, sort)
end
+ # call-seq:
# Dir.glob( pattern, [flags], [base: path] [, sort: true] ) -> array
# Dir.glob( pattern, [flags], [base: path] [, sort: true] ) { |filename| block } -> nil
#
@@ -134,13 +144,13 @@ class Dir
# paths.
#
# The results which matched single wildcard or character set are sorted in
- # binary ascending order, unless false is given as the optional +sort+
+ # 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).
+ # 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.
@@ -190,7 +200,7 @@ class Dir
# 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("*", File::FNM_DOTMATCH) #=> [".", "config.h", "main.rb"]
# Dir.glob(["*.rb", "*.h"]) #=> ["main.rb", "config.h"]
#
# Dir.glob("**/*.rb") #=> ["main.rb",
@@ -224,13 +234,13 @@ class << File
# Matches any file. Can be restricted by other values in the glob.
# Equivalent to <code>/.*/x</code> in regexp.
#
- # <code>*</code>:: Matches all files regular files
+ # <code>*</code>:: Matches all regular 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>:: Matches all files that have <code>c</code> in them
# (including at the beginning or end).
#
- # To match hidden files (that start with a <code>.</code> set the
+ # To match hidden files (that start with a <code>.</code>) set the
# File::FNM_DOTMATCH flag.
#
# <code>**</code>::
diff --git a/dln.c b/dln.c
index ac09430492..0edd709bbe 100644
--- a/dln.c
+++ b/dln.c
@@ -15,14 +15,17 @@
#define dln_memerror rb_memerror
#define dln_exit rb_exit
#define dln_loaderror rb_loaderror
+#define dln_fatalerror rb_fatal
#else
#define dln_notimplement --->>> dln not implemented <<<---
#define dln_memerror abort
#define dln_exit exit
static void dln_loaderror(const char *format, ...);
+#define dln_fatalerror dln_loaderror
#endif
#include "dln.h"
#include "internal.h"
+#include "internal/compilers.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
@@ -38,6 +41,10 @@ static void dln_loaderror(const char *format, ...);
# include <strings.h>
#endif
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
+#endif
+
#ifndef xmalloc
void *xmalloc();
void *xcalloc();
@@ -55,7 +62,7 @@ void *xrealloc();
#include <sys/stat.h>
#ifndef S_ISDIR
-# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifdef HAVE_SYS_PARAM_H
@@ -69,19 +76,6 @@ void *xrealloc();
# include <unistd.h>
#endif
-#ifndef _WIN32
-char *getenv();
-#endif
-
-#ifdef __APPLE__
-# if defined(HAVE_DLOPEN)
- /* Mac OS X with dlopen (10.3 or later) */
-# define MACOSX_DLOPEN
-# else
-# define MACOSX_DYLD
-# endif
-#endif
-
#ifndef dln_loaderror
static void
dln_loaderror(const char *format, ...)
@@ -94,12 +88,12 @@ dln_loaderror(const char *format, ...)
}
#endif
-#if defined(HAVE_DLOPEN) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP)
+#if defined(HAVE_DLOPEN) && !defined(_AIX) && !defined(_UNICOSMP)
/* dynamic load with dlopen() */
# define USE_DLN_DLOPEN
#endif
-#if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(NeXT) || defined(MACOSX_DYLD)
+#if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(NeXT)
# define EXTERNAL_PREFIX "_"
#else
# define EXTERNAL_PREFIX ""
@@ -112,6 +106,7 @@ dln_loaderror(const char *format, ...)
#define isdirsep(x) ((x) == '/')
#endif
+#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
static size_t
init_funcname_len(const char **file)
{
@@ -119,8 +114,8 @@ init_funcname_len(const char **file)
/* Load the file as an object one */
for (base = p; *p; p++) { /* Find position of last '/' */
- if (*p == '.' && !dot) dot = p;
- if (isdirsep(*p)) base = p+1, dot = NULL;
+ if (*p == '.' && !dot) dot = p;
+ if (isdirsep(*p)) base = p+1, dot = NULL;
}
*file = base;
/* Delete suffix if it exists */
@@ -135,23 +130,19 @@ static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX
const size_t plen = sizeof(funcname_prefix);\
char *const tmp = ALLOCA_N(char, plen+flen+1);\
if (!tmp) {\
- dln_memerror();\
+ dln_memerror();\
}\
memcpy(tmp, funcname_prefix, plen);\
memcpy(tmp+plen, base, flen);\
tmp[plen+flen] = '\0';\
*(buf) = tmp;\
} while (0)
+#endif
#ifdef USE_DLN_DLOPEN
# include <dlfcn.h>
#endif
-#ifdef __hpux
-#include <errno.h>
-#include "dl.h"
-#endif
-
#if defined(_AIX)
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
@@ -167,10 +158,6 @@ static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX
#define NSLINKMODULE_OPTION_BINDNOW 1
#endif
#endif
-#else
-#ifdef MACOSX_DYLD
-#include <mach-o/dyld.h>
-#endif
#endif
#ifdef _WIN32
@@ -187,25 +174,23 @@ dln_strerror(char *message, size_t size)
size_t len = snprintf(message, size, "%d: ", error);
#define format_message(sublang) FormatMessage(\
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
- NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
- message + len, size - len, NULL)
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
+ NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
+ message + len, size - len, NULL)
if (format_message(SUBLANG_ENGLISH_US) == 0)
- format_message(SUBLANG_DEFAULT);
+ format_message(SUBLANG_DEFAULT);
for (p = message + len; *p; p++) {
- if (*p == '\n' || *p == '\r')
- *p = ' ';
+ if (*p == '\n' || *p == '\r')
+ *p = ' ';
}
return message;
}
#define dln_strerror() dln_strerror(message, sizeof message)
-#elif ! defined _AIX
+#elif defined USE_DLN_DLOPEN
static const char *
dln_strerror(void)
{
-#ifdef USE_DLN_DLOPEN
return (char*)dlerror();
-#endif
}
#endif
@@ -219,18 +204,18 @@ aix_loaderror(const char *pathname)
snprintf(errbuf, sizeof(errbuf), "load failed - %s. ", pathname);
if (loadquery(L_GETMESSAGES, &message[0], sizeof(message)) != -1) {
- ERRBUF_APPEND("Please issue below command for detailed reasons:\n\t");
- ERRBUF_APPEND("/usr/sbin/execerror ruby ");
- for (i=0; message[i]; i++) {
- ERRBUF_APPEND("\"");
- ERRBUF_APPEND(message[i]);
- ERRBUF_APPEND("\" ");
- }
- ERRBUF_APPEND("\n");
+ ERRBUF_APPEND("Please issue below command for detailed reasons:\n\t");
+ ERRBUF_APPEND("/usr/sbin/execerror ruby ");
+ for (i=0; message[i]; i++) {
+ ERRBUF_APPEND("\"");
+ ERRBUF_APPEND(message[i]);
+ ERRBUF_APPEND("\" ");
+ }
+ ERRBUF_APPEND("\n");
}
else {
- ERRBUF_APPEND(strerror(errno));
- ERRBUF_APPEND("[loadquery failed]");
+ ERRBUF_APPEND(strerror(errno));
+ ERRBUF_APPEND("[loadquery failed]");
}
dln_loaderror("%s", errbuf);
}
@@ -248,22 +233,22 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine)
desc = ImageDirectoryEntryToData(ext, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
if (!desc) return 0;
while (desc->Name) {
- PIMAGE_THUNK_DATA pint = (PIMAGE_THUNK_DATA)((char *)ext + desc->Characteristics);
- PIMAGE_THUNK_DATA piat = (PIMAGE_THUNK_DATA)((char *)ext + desc->FirstThunk);
- for (; piat->u1.Function; piat++, pint++) {
- static const char prefix[] = "rb_";
- PIMAGE_IMPORT_BY_NAME pii;
- const char *name;
-
- if (IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal)) continue;
- pii = (PIMAGE_IMPORT_BY_NAME)((char *)ext + (size_t)pint->u1.AddressOfData);
- name = (const char *)pii->Name;
- if (strncmp(name, prefix, sizeof(prefix) - 1) == 0) {
- FARPROC addr = GetProcAddress(mine, name);
- if (addr) return (FARPROC)piat->u1.Function == addr;
- }
- }
- desc++;
+ PIMAGE_THUNK_DATA pint = (PIMAGE_THUNK_DATA)((char *)ext + desc->Characteristics);
+ PIMAGE_THUNK_DATA piat = (PIMAGE_THUNK_DATA)((char *)ext + desc->FirstThunk);
+ for (; piat->u1.Function; piat++, pint++) {
+ static const char prefix[] = "rb_";
+ PIMAGE_IMPORT_BY_NAME pii;
+ const char *name;
+
+ if (IMAGE_SNAP_BY_ORDINAL(pint->u1.Ordinal)) continue;
+ pii = (PIMAGE_IMPORT_BY_NAME)((char *)ext + (size_t)pint->u1.AddressOfData);
+ name = (const char *)pii->Name;
+ if (strncmp(name, prefix, sizeof(prefix) - 1) == 0) {
+ FARPROC addr = GetProcAddress(mine, name);
+ if (addr) return (FARPROC)piat->u1.Function == addr;
+ }
+ }
+ desc++;
}
return 1;
}
@@ -271,11 +256,11 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine)
#if defined(DLN_NEEDS_ALT_SEPARATOR) && DLN_NEEDS_ALT_SEPARATOR
#define translit_separator(src) do { \
- char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
- do { \
- *p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
- } while (c); \
- (src) = tmp; \
+ char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
+ do { \
+ *p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
+ } while (c); \
+ (src) = tmp; \
} while (0)
#else
#define translit_separator(str) (void)(str)
@@ -284,44 +269,79 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine)
#ifdef USE_DLN_DLOPEN
# include "ruby/internal/stdbool.h"
# include "internal/warnings.h"
+static bool
+dln_incompatible_func(void *handle, const char *funcname, void *const fp, const char **libname)
+{
+ Dl_info dli;
+ void *ex = dlsym(handle, funcname);
+ if (!ex) return false;
+ if (ex == fp) return false;
+ if (dladdr(ex, &dli)) {
+ *libname = dli.dli_fname;
+ }
+ return true;
+}
+
COMPILER_WARNING_PUSH
#if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0)
COMPILER_WARNING_IGNORED(-Wpedantic)
#endif
static bool
-dln_incompatible_library_p(void *handle)
+dln_incompatible_library_p(void *handle, const char **libname)
{
- void *ex = dlsym(handle, EXTERNAL_PREFIX"ruby_xmalloc");
- void *const fp = (void *)ruby_xmalloc;
- return ex && ex != fp;
+#define check_func(func) \
+ if (dln_incompatible_func(handle, EXTERNAL_PREFIX #func, (void *)&func, libname)) \
+ return true
+ check_func(ruby_xmalloc);
+ return false;
}
COMPILER_WARNING_POP
#endif
-void*
-dln_load(const char *file)
+#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED)
+/* assume others than old Mac OS X have no problem */
+# define dln_disable_dlclose() false
+
+#elif !defined(MAC_OS_X_VERSION_10_11) || \
+ (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11)
+/* targeting older versions only */
+# define dln_disable_dlclose() true
+
+#elif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
+/* targeting newer versions only */
+# define dln_disable_dlclose() false
+
+#else
+/* support both versions, and check at runtime */
+# include <sys/sysctl.h>
+
+static bool
+dln_disable_dlclose(void)
{
-#if (defined _WIN32 || defined USE_DLN_DLOPEN) && defined RUBY_EXPORT
- static const char incompatible[] = "incompatible library version";
-#endif
-#if !defined(_AIX) && !defined(NeXT)
- const char *error = 0;
+ int mib[] = {CTL_KERN, KERN_OSREV};
+ int32_t rev;
+ size_t size = sizeof(rev);
+ if (sysctl(mib, numberof(mib), &rev, &size, NULL, 0)) return true;
+ if (rev < MAC_OS_X_VERSION_10_11) return true;
+ return false;
+}
#endif
-#if defined _WIN32
- HINSTANCE handle;
- WCHAR *winfile;
- char message[1024];
- void (*init_fct)(void);
- char *buf;
+#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
+static void *
+dln_open(const char *file)
+{
+ static const char incompatible[] = "incompatible library version";
+ const char *error = NULL;
+ void *handle;
- /* Load the file as an object one */
- init_funcname(&buf, file);
+#if defined(_WIN32)
+ char message[1024];
/* Convert the file path to wide char */
- winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
+ WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) {
- dln_memerror();
+ dln_memerror();
}
/* Load file */
@@ -329,174 +349,146 @@ dln_load(const char *file)
free(winfile);
if (!handle) {
- error = dln_strerror();
- goto failed;
+ error = dln_strerror();
+ goto failed;
}
-#if defined _WIN32 && defined RUBY_EXPORT
+# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
- FreeLibrary(handle);
- error = incompatible;
- goto failed;
- }
-#endif
-
- if ((init_fct = (void(*)(void))GetProcAddress(handle, buf)) == NULL) {
- dln_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
+ FreeLibrary(handle);
+ error = incompatible;
+ goto failed;
}
+# endif
- /* Call the init code */
- (*init_fct)();
- return handle;
-#else
- char *buf;
- /* Load the file as an object one */
- init_funcname(&buf, file);
- translit_separator(file);
+#elif defined(USE_DLN_DLOPEN)
-#ifdef USE_DLN_DLOPEN
-#define DLN_DEFINED
- {
- void *handle;
- void (*init_fct)(void);
-
-#ifndef RTLD_LAZY
-# define RTLD_LAZY 1
-#endif
-#ifdef __INTERIX
-# undef RTLD_GLOBAL
-#endif
-#ifndef RTLD_GLOBAL
-# define RTLD_GLOBAL 0
-#endif
-
- /* Load file */
- if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
- error = dln_strerror();
- goto failed;
- }
-# if defined RUBY_EXPORT
- {
- if (dln_incompatible_library_p(handle)) {
-
-# if defined __APPLE__ && \
- defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
- (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11)
- /* dlclose() segfaults */
- rb_fatal("%s - %s", incompatible, file);
-# else
- dlclose(handle);
- error = incompatible;
- goto failed;
-# endif
- }
- }
+# ifndef RTLD_LAZY
+# define RTLD_LAZY 1
+# endif
+# ifdef __INTERIX
+# undef RTLD_GLOBAL
+# endif
+# ifndef RTLD_GLOBAL
+# define RTLD_GLOBAL 0
# endif
- init_fct = (void(*)(void))(VALUE)dlsym(handle, buf);
- if (init_fct == NULL) {
- const size_t errlen = strlen(error = dln_strerror()) + 1;
- error = memcpy(ALLOCA_N(char, errlen), error, errlen);
- dlclose(handle);
- goto failed;
- }
- /* Call the init code */
- (*init_fct)();
-
- return handle;
+ /* Load file */
+ handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
+ if (handle == NULL) {
+ error = dln_strerror();
+ goto failed;
}
-#endif /* USE_DLN_DLOPEN */
-#ifdef __hpux
-#define DLN_DEFINED
+# if defined(RUBY_EXPORT)
{
- shl_t lib = NULL;
- int flags;
- void (*init_fct)(void);
-
- flags = BIND_DEFERRED;
- lib = shl_load(file, flags, 0);
- if (lib == NULL) {
- extern int errno;
- dln_loaderror("%s - %s", strerror(errno), file);
- }
- shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
- if (init_fct == NULL) {
- shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
- if (init_fct == NULL) {
- errno = ENOSYM;
- dln_loaderror("%s - %s", strerror(ENOSYM), file);
- }
- }
- (*init_fct)();
- return (void*)lib;
+ const char *libruby_name = NULL;
+ if (dln_incompatible_library_p(handle, &libruby_name)) {
+ if (dln_disable_dlclose()) {
+ /* dlclose() segfaults */
+ if (libruby_name) {
+ dln_fatalerror("linked to incompatible %s - %s", libruby_name, file);
+ }
+ dln_fatalerror("%s - %s", incompatible, file);
+ }
+ else {
+ dlclose(handle);
+ if (libruby_name) {
+ dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
+ }
+ error = incompatible;
+ goto failed;
+ }
+ }
}
-#endif /* hpux */
+# endif
+#endif
-#if defined(_AIX)
-#define DLN_DEFINED
- {
- void (*init_fct)(void);
-
- init_fct = (void(*)(void))load((char*)file, 1, 0);
- if (init_fct == NULL) {
- aix_loaderror(file);
- }
- if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
- aix_loaderror(file);
- }
- (*init_fct)();
- return (void*)init_fct;
- }
-#endif /* _AIX */
-
-#if defined(MACOSX_DYLD)
-#define DLN_DEFINED
-/*----------------------------------------------------
- By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
-
- Special Thanks...
- Yu tomoak-i@is.aist-nara.ac.jp,
- Mi hisho@tasihara.nest.or.jp,
- sunshine@sunshineco.com,
- and... Miss ARAI Akino(^^;)
- ----------------------------------------------------*/
- {
- int dyld_result;
- NSObjectFileImage obj_file; /* handle, but not use it */
- /* "file" is module file name .
- "buf" is pointer to initial function name with "_" . */
+ return handle;
- void (*init_fct)(void);
+ failed:
+ dln_loaderror("%s - %s", error, file);
+}
+static void *
+dln_sym(void *handle, const char *symbol)
+{
+ void *func;
+ const char *error;
- dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
+#if defined(_WIN32)
+ char message[1024];
- if (dyld_result != NSObjectFileImageSuccess) {
- dln_loaderror("Failed to load %.200s", file);
- }
+ func = GetProcAddress(handle, symbol);
+ if (func == NULL) {
+ error = dln_strerror();
+ goto failed;
+ }
- NSLinkModule(obj_file, file, NSLINKMODULE_OPTION_BINDNOW);
+#elif defined(USE_DLN_DLOPEN)
+ func = dlsym(handle, symbol);
+ if (func == NULL) {
+ const size_t errlen = strlen(error = dln_strerror()) + 1;
+ error = memcpy(ALLOCA_N(char, errlen), error, errlen);
+ goto failed;
+ }
+#endif
- /* lookup the initial function */
- if (!NSIsSymbolNameDefined(buf)) {
- dln_loaderror("Failed to lookup Init function %.200s",file);
- }
- init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
- (*init_fct)();
+ return func;
- return (void*)init_fct;
- }
+ failed:
+ dln_loaderror("%s - %s", error, symbol);
+}
#endif
-#ifndef DLN_DEFINED
- dln_notimplement();
+#if defined(RUBY_DLN_CHECK_ABI) && defined(USE_DLN_DLOPEN)
+static bool
+abi_check_enabled_p(void)
+{
+ const char *val = getenv("RUBY_ABI_CHECK");
+ return val == NULL || !(val[0] == '0' && val[1] == '\0');
+}
#endif
+void *
+dln_load(const char *file)
+{
+#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
+ void *handle = dln_open(file);
+
+#ifdef RUBY_DLN_CHECK_ABI
+ unsigned long long (*abi_version_fct)(void) = (unsigned long long(*)(void))dln_sym(handle, "ruby_abi_version");
+ unsigned long long binary_abi_version = (*abi_version_fct)();
+ if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) {
+ dln_loaderror("incompatible ABI version of binary - %s", file);
+ }
#endif
-#if !defined(_AIX) && !defined(NeXT)
- failed:
- dln_loaderror("%s - %s", error, file);
+
+ char *init_fct_name;
+ init_funcname(&init_fct_name, file);
+ void (*init_fct)(void) = (void(*)(void))dln_sym(handle, init_fct_name);
+
+ /* Call the init code */
+ (*init_fct)();
+
+ return handle;
+
+#elif defined(_AIX)
+ {
+ void (*init_fct)(void);
+
+ init_fct = (void(*)(void))load((char*)file, 1, 0);
+ if (init_fct == NULL) {
+ aix_loaderror(file);
+ }
+ if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
+ aix_loaderror(file);
+ }
+ (*init_fct)();
+ return (void*)init_fct;
+ }
+#else
+ dln_notimplement();
#endif
return 0; /* dummy return */
diff --git a/dln_find.c b/dln_find.c
index 96e06d34c4..5d380f5d39 100644
--- a/dln_find.c
+++ b/dln_find.c
@@ -53,26 +53,26 @@ char *getenv();
#endif
static char *dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag
- DLN_FIND_EXTRA_ARG_DECL);
+ DLN_FIND_EXTRA_ARG_DECL);
char *
dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size
- DLN_FIND_EXTRA_ARG_DECL)
+ DLN_FIND_EXTRA_ARG_DECL)
{
char *envpath = 0;
if (!path) {
- path = getenv(PATH_ENV);
- if (path) path = envpath = strdup(path);
+ path = getenv(PATH_ENV);
+ if (path) path = envpath = strdup(path);
}
if (!path) {
- path =
- "/usr/local/bin" PATH_SEP
- "/usr/ucb" PATH_SEP
- "/usr/bin" PATH_SEP
- "/bin" PATH_SEP
- ".";
+ path =
+ "/usr/local/bin" PATH_SEP
+ "/usr/ucb" PATH_SEP
+ "/usr/bin" PATH_SEP
+ "/bin" PATH_SEP
+ ".";
}
buf = dln_find_1(fname, path, buf, size, 1 DLN_FIND_EXTRA_ARG);
if (envpath) free(envpath);
@@ -81,7 +81,7 @@ dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size
char *
dln_find_file_r(const char *fname, const char *path, char *buf, size_t size
- DLN_FIND_EXTRA_ARG_DECL)
+ DLN_FIND_EXTRA_ARG_DECL)
{
if (!path) path = ".";
return dln_find_1(fname, path, buf, size, 0 DLN_FIND_EXTRA_ARG);
@@ -89,8 +89,8 @@ dln_find_file_r(const char *fname, const char *path, char *buf, size_t size
static char *
dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
- int exe_flag /* non 0 if looking for executable. */
- DLN_FIND_EXTRA_ARG_DECL)
+ int exe_flag /* non 0 if looking for executable. */
+ DLN_FIND_EXTRA_ARG_DECL)
{
register const char *dp;
register const char *ep;
@@ -99,7 +99,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
size_t i, fnlen, fspace;
#ifdef DOSISH
static const char extension[][5] = {
- EXECUTABLE_EXTS,
+ EXECUTABLE_EXTS,
};
size_t j;
int is_abs = 0, has_path = 0;
@@ -110,21 +110,21 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
static const char pathname_too_long[] = "openpath: pathname too long (ignored)\n\
\tDirectory \"%.*s\"%s\n\tFile \"%.*s\"%s\n";
#define PATHNAME_TOO_LONG() dln_warning(dln_warning_arg pathname_too_long, \
- ((bp - fbuf) > 100 ? 100 : (int)(bp - fbuf)), fbuf, \
- ((bp - fbuf) > 100 ? "..." : ""), \
- (fnlen > 100 ? 100 : (int)fnlen), fname, \
- (fnlen > 100 ? "..." : ""))
+ ((bp - fbuf) > 100 ? 100 : (int)(bp - fbuf)), fbuf, \
+ ((bp - fbuf) > 100 ? "..." : ""), \
+ (fnlen > 100 ? 100 : (int)fnlen), fname, \
+ (fnlen > 100 ? "..." : ""))
#define RETURN_IF(expr) if (expr) return (char *)fname;
RETURN_IF(!fname);
fnlen = strlen(fname);
if (fnlen >= size) {
- dln_warning(dln_warning_arg
- "openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n",
- (fnlen > 100 ? 100 : (int)fnlen), fname,
- (fnlen > 100 ? "..." : ""));
- return NULL;
+ dln_warning(dln_warning_arg
+ "openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n",
+ (fnlen > 100 ? 100 : (int)fnlen), fname,
+ (fnlen > 100 ? "..." : ""));
+ return NULL;
}
#ifdef DOSISH
# ifndef CharNext
@@ -132,52 +132,52 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
# endif
# ifdef DOSISH_DRIVE_LETTER
if (((p[0] | 0x20) - 'a') < 26 && p[1] == ':') {
- p += 2;
- is_abs = 1;
+ p += 2;
+ is_abs = 1;
}
# endif
switch (*p) {
case '/': case '\\':
- is_abs = 1;
- p++;
+ is_abs = 1;
+ p++;
}
has_path = is_abs;
while (*p) {
- switch (*p) {
- case '/': case '\\':
- has_path = 1;
- ext = 0;
- p++;
- break;
- case '.':
- ext = p;
- p++;
- break;
- default:
- p = CharNext(p);
- }
+ switch (*p) {
+ case '/': case '\\':
+ has_path = 1;
+ ext = 0;
+ p++;
+ break;
+ case '.':
+ ext = p;
+ p++;
+ break;
+ default:
+ p = CharNext(p);
+ }
}
if (ext) {
- for (j = 0; STRCASECMP(ext, extension[j]); ) {
- if (++j == sizeof(extension) / sizeof(extension[0])) {
- ext = 0;
- break;
- }
- }
+ for (j = 0; STRCASECMP(ext, extension[j]); ) {
+ if (++j == sizeof(extension) / sizeof(extension[0])) {
+ ext = 0;
+ break;
+ }
+ }
}
ep = bp = 0;
if (!exe_flag) {
- RETURN_IF(is_abs);
+ RETURN_IF(is_abs);
}
else if (has_path) {
- RETURN_IF(ext);
- i = p - fname;
- if (i + 1 > size) goto toolong;
- fspace = size - i - 1;
- bp = fbuf;
- ep = p;
- memcpy(fbuf, fname, i + 1);
- goto needs_extension;
+ RETURN_IF(ext);
+ i = p - fname;
+ if (i + 1 > size) goto toolong;
+ fspace = size - i - 1;
+ bp = fbuf;
+ ep = p;
+ memcpy(fbuf, fname, i + 1);
+ goto needs_extension;
}
p = fname;
#endif
@@ -189,85 +189,85 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
#undef RETURN_IF
for (dp = path;; dp = ++ep) {
- register size_t l;
-
- /* extract a component */
- ep = strchr(dp, PATH_SEP[0]);
- if (ep == NULL)
- ep = dp+strlen(dp);
-
- /* find the length of that component */
- l = ep - dp;
- bp = fbuf;
- fspace = size - 2;
- if (l > 0) {
- /*
- ** If the length of the component is zero length,
- ** start from the current directory. If the
- ** component begins with "~", start from the
- ** user's $HOME environment variable. Otherwise
- ** take the path literally.
- */
-
- if (*dp == '~' && (l == 1 ||
+ register size_t l;
+
+ /* extract a component */
+ ep = strchr(dp, PATH_SEP[0]);
+ if (ep == NULL)
+ ep = dp+strlen(dp);
+
+ /* find the length of that component */
+ l = ep - dp;
+ bp = fbuf;
+ fspace = size - 2;
+ if (l > 0) {
+ /*
+ ** If the length of the component is zero length,
+ ** start from the current directory. If the
+ ** component begins with "~", start from the
+ ** user's $HOME environment variable. Otherwise
+ ** take the path literally.
+ */
+
+ if (*dp == '~' && (l == 1 ||
#if defined(DOSISH)
- dp[1] == '\\' ||
+ dp[1] == '\\' ||
#endif
- dp[1] == '/')) {
- const char *home;
-
- home = getenv("HOME");
- if (home != NULL) {
- i = strlen(home);
- if (fspace < i)
- goto toolong;
- fspace -= i;
- memcpy(bp, home, i);
- bp += i;
- }
- dp++;
- l--;
- }
- if (l > 0) {
- if (fspace < l)
- goto toolong;
- fspace -= l;
- memcpy(bp, dp, l);
- bp += l;
- }
-
- /* add a "/" between directory and filename */
- if (ep[-1] != '/')
- *bp++ = '/';
- }
-
- /* now append the file name */
- i = fnlen;
- if (fspace < i) {
+ dp[1] == '/')) {
+ const char *home;
+
+ home = getenv("HOME");
+ if (home != NULL) {
+ i = strlen(home);
+ if (fspace < i)
+ goto toolong;
+ fspace -= i;
+ memcpy(bp, home, i);
+ bp += i;
+ }
+ dp++;
+ l--;
+ }
+ if (l > 0) {
+ if (fspace < l)
+ goto toolong;
+ fspace -= l;
+ memcpy(bp, dp, l);
+ bp += l;
+ }
+
+ /* add a "/" between directory and filename */
+ if (ep[-1] != '/')
+ *bp++ = '/';
+ }
+
+ /* now append the file name */
+ i = fnlen;
+ if (fspace < i) {
goto toolong;
- }
- fspace -= i;
- memcpy(bp, fname, i + 1);
+ }
+ fspace -= i;
+ memcpy(bp, fname, i + 1);
#if defined(DOSISH)
- if (exe_flag && !ext) {
+ if (exe_flag && !ext) {
goto needs_extension;
- }
+ }
#endif
#ifndef S_ISREG
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
- if (stat(fbuf, &st) == 0 && S_ISREG(st.st_mode)) {
- if (exe_flag == 0) return fbuf;
- /* looking for executable */
- if (eaccess(fbuf, X_OK) == 0) return fbuf;
- }
+ if (stat(fbuf, &st) == 0 && S_ISREG(st.st_mode)) {
+ if (exe_flag == 0) return fbuf;
+ /* looking for executable */
+ if (eaccess(fbuf, X_OK) == 0) return fbuf;
+ }
next:
- /* if not, and no other alternatives, life is bleak */
- if (*ep == '\0') {
- return NULL;
- }
+ /* if not, and no other alternatives, life is bleak */
+ if (*ep == '\0') {
+ return NULL;
+ }
continue;
toolong:
@@ -287,6 +287,6 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
}
goto next;
#endif
- /* otherwise try the next component in the search path */
+ /* otherwise try the next component in the search path */
}
}
diff --git a/dmyenc.c b/dmyenc.c
index 7e006e826c..75b8a2da43 100644
--- a/dmyenc.c
+++ b/dmyenc.c
@@ -5,6 +5,6 @@ void
Init_enc(void)
{
if (require("enc/encdb.so") == 1) {
- require("enc/trans/transdb.so");
+ require("enc/trans/transdb.so");
}
}
diff --git a/doc/.document b/doc/.document
index ad17aada6d..f589dda07c 100644
--- a/doc/.document
+++ b/doc/.document
@@ -1,4 +1,9 @@
*.md
+*.rb
*.rdoc
-NEWS-*
+contributing
+NEWS
syntax
+optparse
+rdoc
+yjit
diff --git a/doc/ChangeLog-0.60_to_1.1 b/doc/ChangeLog-0.60_to_1.1
index bd5f140dc3..59d195e780 100644
--- a/doc/ChangeLog-0.60_to_1.1
+++ b/doc/ChangeLog-0.60_to_1.1
@@ -28,7 +28,7 @@ Fri Aug 8 11:16:50 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
Thu Aug 7 11:40:01 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
- * variable.c (mod_constants): lists constants defiend in the
+ * variable.c (mod_constants): lists constants defined in the
modules/classes.
* variable.c (rb_const_set): no longer warns about constant
@@ -49,7 +49,7 @@ Mon Aug 4 11:50:28 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
classes (or modules) dynamically.
* variable.c (rb_class_path): scan class constants for anonymous
- classes/modules to make up pathes.
+ classes/modules to make up paths.
Wed Jul 30 08:45:12 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -76,7 +76,7 @@ Wed Jul 23 09:56:55 1997 Yukihiro Matsumoto <matz@caelum.co.jp>
specified object.
* class.c (mod_instance_methods): returns list of method names of
- the class instnace.
+ the class instance.
Fri Jul 11 22:38:55 1997 Yukihiro Matsumoto <matz@caelum.co.jp>
@@ -538,7 +538,7 @@ Wed Mar 12 10:20:30 1997 Yukihiro Matsumoto <matz@caelum.co.jp>
Mon Mar 10 20:44:22 1997 Yukihiro Matsumoto <matz@caelum.co.jp>
* re.c (reg_regsub): \& for substitution. \`, \', and \+ are
- avaiable also.
+ available also.
Thu Mar 6 01:47:03 1997 Yukihiro Matsumoto <matz@caelum.co.jp>
@@ -3573,7 +3573,7 @@ Fri Mar 17 15:56:44 1995 Yukihiro Matsumoto (matz@ix-02)
* dln.c: dlopenのあるマシンではそちらを使うように.ただし,ちゃん
と動いているかどうかは自信がない.
- * regex.c: virtual concatinationをやめた.
+ * regex.c: virtual concatenationをやめた.
Thu Mar 16 11:32:57 1995 Yukihiro Matsumoto (matz@ix-02)
diff --git a/doc/ChangeLog-1.9.3 b/doc/ChangeLog-1.9.3
index d6aaea7f19..0f80eed2d5 100644
--- a/doc/ChangeLog-1.9.3
+++ b/doc/ChangeLog-1.9.3
@@ -5746,7 +5746,7 @@ Wed Mar 2 14:06:01 2011 NARUSE, Yui <naruse@ruby-lang.org>
Wed Mar 2 14:02:29 2011 Shota Fukumori <sorah@tubusu.net>
* test/testunit/test_parallel.rb(TestParallel#spawn_runner):
- Fix outputing empty line in running test.
+ Fix outputting empty line in running test.
* test/testunit/tests_for_parallel/test_third.rb: Remove `sleep`
@@ -5765,7 +5765,7 @@ Tue Mar 1 21:48:22 2011 Shota Fukumori <sorah@tubusu.net>
* test/testunit/test_parallel.rb(TestParallelWorker#test_quit_in_test):
Fix for above specification change.
* test/testunit/test_parallel.rb(TestParallel#spawn_runner):
- Fix outputing empty line in running test.
+ Fix outputting empty line in running test.
Tue Mar 1 20:51:57 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
@@ -7541,7 +7541,7 @@ Tue Jan 11 20:32:59 2011 Tanaka Akira <akr@fsij.org>
Tue Jan 11 13:06:38 2011 NAKAMURA Usaku <usa@ruby-lang.org>
- * array.c (rb_ary_resize): should care of embeded array when extending
+ * array.c (rb_ary_resize): should care of embedded array when extending
the array.
* array.c (rb_ary_resize): need to set capa when changing the real
@@ -9563,7 +9563,7 @@ Wed Nov 17 16:09:52 2010 Yuki Sonoda (Yugui) <yugui@yugui.jp>
Wed Nov 17 16:04:23 2010 Yuki Sonoda (Yugui) <yugui@yugui.jp>
- * test/ruby/envutil.rb (Test::Unit::Assersions#assert_warn):
+ * test/ruby/envutil.rb (Test::Unit::Assertions#assert_warn):
new assertion to assert that a particular warning message is
displayed.
forward port from branches/ruby_1_9_2@29795.
@@ -9781,7 +9781,7 @@ Wed Nov 10 07:20:10 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
Tue Nov 9 21:57:45 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* dln.c (init_funcname): allocate and build initialization
- funciton name at once.
+ function name at once.
Tue Nov 9 21:14:54 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -23228,7 +23228,7 @@ Fri Sep 11 10:38:33 2009 URABE Shyouhei <shyouhei@ruby-lang.org>
* lib/net/http.rb (Net::HTTPHeader::encode_kvpair): also call to_s
to k. A patch from swdyh <youhei@gmail.com>
- http://github.com/swdyh/ruby/tree/c847f43c2ccb679b9ff728f8b1b16c6ceeb57f39
+ https://github.com/swdyh/ruby/tree/c847f43c2ccb679b9ff728f8b1b16c6ceeb57f39
Fri Sep 11 09:45:11 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -62969,7 +62969,7 @@ Thu Jul 12 12:24:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
Thu Jul 12 10:30:46 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * thread.c (thread_start_func_2): moved prototye from thread_*.ci.
+ * thread.c (thread_start_func_2): moved prototype from thread_*.ci.
* thread_pthread.ci (thread_start_func_2): not use a directive
inside a macro argument. [ruby-talk:258763]
@@ -73273,7 +73273,7 @@ Fri Nov 18 17:35:09 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/multi-tk.rb: add restriction to access the entried
command table and manipulate other IPs (for reason of security).
- Now, a IP object can be controlled by only its master IP or the
+ Now, an IP object can be controlled by only its master IP or the
default IP.
* ext/tk/lib/remote-tk.rb: add restriction to manipulate.
@@ -76346,7 +76346,7 @@ Tue Jul 5 14:52:56 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/tk/validation.rb: ditto.
- * ext/tk/lib/tk/namespace.rb: arguemnts for TclTkIp#_merge_tklist
+ * ext/tk/lib/tk/namespace.rb: arguments for TclTkIp#_merge_tklist
should be UTF-8 strings.
Mon Jul 4 19:29:32 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
@@ -77285,7 +77285,7 @@ Sun May 15 09:57:30 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
Sat May 14 23:59:11 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
* error.c (exc_exception, {exit,name_err,syserr}_initialize): call
- Execption#initialize. fixed: [ruby-talk:142593]
+ Exception#initialize. fixed: [ruby-talk:142593]
Sat May 14 23:56:41 2005 Erik Huelsmann <ehuels@gmail.com>
@@ -77435,7 +77435,7 @@ Sat Apr 30 06:57:39 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
(suggested by Tatsuki Sugiura)
* lib/webrick/cgi.rb
- (WEBrick::CGI#initalize): set a dummy to @config[:ServerSoftware]
+ (WEBrick::CGI#initialize): set a dummy to @config[:ServerSoftware]
if SERVER_SOFTWARE environment variable is not given.
(WEBrick::CGI#start): req.path_info must be a String.
(WEBrick::CGI::Socket#request_line): treat REQUEST_METHOD, PATH_INFO
@@ -82696,7 +82696,7 @@ Tue Sep 14 20:24:49 2004 Minero Aoki <aamine@loveruby.net>
* ext/ripper/depend: Borland make does not accept pipes in
Makefile rules. [ruby-dev:24589]
- * ext/ripper/depend: separate rules for developpers.
+ * ext/ripper/depend: separate rules for developers.
* ext/ripper/Makefile.dev: new file.
@@ -82931,7 +82931,7 @@ Wed Sep 8 18:44:03 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
Wed Sep 8 15:19:49 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
- * ext/tcltklib/tcltklib.c (ip_init): cannot create a IP at level 4
+ * ext/tcltklib/tcltklib.c (ip_init): cannot create an IP at level 4
* ext/tk/lib/multi-tk.rb: improve 'exit' operation, security check,
and error treatment
@@ -88452,7 +88452,7 @@ Tue Dec 16 03:17:29 2003 why the lucky stiff <why@ruby-lang.org>
Tue Dec 16 01:14:44 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * eval.c (catch_timer): check rb_thread_crtical in main native
+ * eval.c (catch_timer): check rb_thread_critical in main native
thread.
* eval.c (thread_timer): just sends signals periodically, to
@@ -92616,7 +92616,7 @@ Fri Aug 8 03:22:28 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
Thu Aug 7 14:40:37 2003 WATANABE Hirofumi <eban@ruby-lang.org>
- * cygwin/GNUmakefile: better --disbale-shared option support.
+ * cygwin/GNUmakefile: better --disable-shared option support.
* cygwin/GNUmakefile: add forwarding DLL target for cygwin.
diff --git a/doc/ChangeLog-2.0.0 b/doc/ChangeLog-2.0.0
index b51d742203..9e654db189 100644
--- a/doc/ChangeLog-2.0.0
+++ b/doc/ChangeLog-2.0.0
@@ -16451,7 +16451,7 @@ Mon Mar 5 17:11:44 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
Exception#initialize doesn't use visible instance variable for
the exception message, so call the method with the message.
patched by Jingwen Owen Ou <jingweno AT gmail.com>.
- http://github.com/ruby/ruby/pull/41
+ https://github.com/ruby/ruby/pull/41
Mon Mar 5 16:50:22 2012 NAKAMURA Usaku <usa@ruby-lang.org>
@@ -16858,13 +16858,13 @@ Fri Feb 24 13:54:33 2012 Aaron Patterson <aaron@tenderlovemaking.com>
Fri Feb 24 12:07:34 2012 Ayumu AIZAWA <ayumu.aizawa@gmail.com>
* lib/net/http.rb: Fix documentation. Patched from Florian Mhun
- via http://github.com/ruby/ruby/pull/96
+ via https://github.com/ruby/ruby/pull/96
Fri Feb 24 11:48:07 2012 Ayumu AIZAWA <ayumu.aizawa@gmail.com>
* string.c (rb_str_prepend): Fix documentation for String#prepend.
- Patched from Franck Verrot via http://github.com/ruby/ruby/pull/98
- and Andrew Horsman via http://github.com/ruby/ruby/pull/55
+ Patched from Franck Verrot via https://github.com/ruby/ruby/pull/98
+ and Andrew Horsman via https://github.com/ruby/ruby/pull/55
Fri Feb 24 10:08:33 2012 Eric Hodel <drbrain@segment7.net>
diff --git a/doc/ChangeLog-2.3.0 b/doc/ChangeLog-2.3.0
index 7f3c4e672a..94996cffd0 100644
--- a/doc/ChangeLog-2.3.0
+++ b/doc/ChangeLog-2.3.0
@@ -170,7 +170,7 @@ Tue Dec 22 14:31:28 2015 Toru Iwase <tietew@tietew.net>
should return unfrozen new string.
[ruby-core:72426] [Bug #11858]
-Tue Dec 22 05:39:58 2015 Takashi Kokubun <takashikkbn@gmail.com>
+Tue Dec 22 05:39:58 2015 Takashi Kokubun <k0kubun@ruby-lang.org>
* ext/cgi/escape/escape.c (preserve_original_state): Preserve
original state for tainted and frozen. [Fix GH-1166]
@@ -208,7 +208,7 @@ Mon Dec 21 09:33:17 2015 Karol Bucek <kares@users.noreply.github.com>
* ext/openssl/lib/openssl/ssl.rb (OpenSSL::SSL::SSLSocket): fix
NotImplementedError typo. [Fix GH-1165]
-Sun Dec 20 20:54:51 2015 Takashi Kokubun <takashikkbn@gmail.com>
+Sun Dec 20 20:54:51 2015 Takashi Kokubun <k0kubun@ruby-lang.org>
* cgi/escape/escape.c: Optimize CGI.escapeHTML for
ASCII-compatible encodings. [Fix GH-1164]
@@ -476,7 +476,7 @@ Tue Dec 15 17:57:57 2015 Martin Duerst <duerst@it.aoyama.ac.jp>
to the correct one in the IANA registry (IBM037)
and added an alias (ebcdic-cp-us)
-Tue Dec 15 16:19:26 2015 Takashi Kokubun <takashikkbn@gmail.com>
+Tue Dec 15 16:19:26 2015 Takashi Kokubun <k0kubun@ruby-lang.org>
* lib/erb.rb: Render erb with array buffer for function call optimization.
[fix GH-1143]
@@ -488,7 +488,7 @@ Tue Dec 15 13:50:05 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* string.c (rb_str_oct): [DOC] mention radix indicators.
[ruby-core:71310] [Bug #11648]
-Tue Dec 15 12:20:30 2015 Takashi Kokubun <takashikkbn@gmail.com>
+Tue Dec 15 12:20:30 2015 Takashi Kokubun <k0kubun@ruby-lang.org>
* lib/erb.rb: Simplify regexp to optimize erb scanner.
[fix GH-1144]
@@ -2670,7 +2670,7 @@ Sat Nov 7 09:51:38 2015 Koichi Sasada <ko1@atdot.net>
* vm_trace.c (rb_threadptr_exec_event_hooks_orig):
maintain trace_running counter on internal events.
- This patch is made by Takashi Kokubun <takashikkbn@gmail.com>.
+ This patch is made by Takashi Kokubun <k0kubun@ruby-lang.org>.
[Bug #11603] https://github.com/ruby/ruby/pull/1059
Sat Nov 7 03:32:27 2015 Koichi Sasada <ko1@atdot.net>
@@ -5283,7 +5283,7 @@ Sat Aug 1 06:54:36 2015 Aaron Patterson <tenderlove@ruby-lang.org>
* ext/openssl/ossl_ssl.c (Init_ossl_ssl): OpenSSL declares these
constants as longs, so we should follow that and use LONG2NUM.
- http://git.io/vOqxD
+ https://github.com/openssl/openssl/blob/34750dc25d74e3db4c1ba43cd219d3f4825e4c65/include/openssl/ssl.h#L391
Sat Aug 1 04:06:29 2015 Aaron Patterson <tenderlove@ruby-lang.org>
@@ -6754,7 +6754,8 @@ Thu Jul 2 09:51:44 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
Thu Jul 2 06:49:44 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* lib/rubygems: Update to RubyGems HEAD(c202db2).
- this version contains many enhancements see http://git.io/vtNwF
+ this version contains many enhancements see
+ https://github.com/rubygems/rubygems/blob/c202db2d681eb3c3a02f187d346fbb2e8d733b26/History.txt#L3
* test/rubygems: ditto.
Wed Jul 1 23:50:34 2015 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
diff --git a/doc/ChangeLog-2.4.0 b/doc/ChangeLog-2.4.0
index 96b5ecb077..a297a579d1 100644
--- a/doc/ChangeLog-2.4.0
+++ b/doc/ChangeLog-2.4.0
@@ -792,7 +792,7 @@ Wed Oct 5 12:57:21 2016 Richard Schneeman <richard.schneeman+foo@gmail.com>
Wed Oct 5 11:47:19 2016 SHIBATA Hiroshi <hsbt@ruby-lang.org>
- * io.c: Fixed equivalent ruby code with core implemention.
+ * io.c: Fixed equivalent ruby code with core implementation.
[fix GH-1429][ci skip] Patch by @sos4nt
Wed Oct 5 11:36:21 2016 SHIBATA Hiroshi <hsbt@ruby-lang.org>
@@ -888,7 +888,7 @@ Sun Oct 2 02:03:06 2016 NAKAMURA Usaku <usa@ruby-lang.org>
Sat Oct 1 23:08:47 2016 NAKAMURA Usaku <usa@ruby-lang.org>
- * ext/date/date_parse.c (date_zone_to_diff): it's nonsence and really
+ * ext/date/date_parse.c (date_zone_to_diff): it's nonsense and really
harm that to use unary minus operator with unsigned value.
get rid of test failures introduced at r56312.
diff --git a/doc/ChangeLog-YARV b/doc/ChangeLog-YARV
index a8b999dff2..83df05c52c 100644
--- a/doc/ChangeLog-YARV
+++ b/doc/ChangeLog-YARV
@@ -493,7 +493,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* thread.c : remove some line break
- * yarvcore.c : reoder initialize sequence to mark main thread
+ * yarvcore.c : reorder initialize sequence to mark main thread
2006-08-18(Fri) 16:51:34 +0900 Koichi Sasada <ko1@atdot.net>
@@ -1481,7 +1481,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* yarvcore.c : ditto
- * yarvtest/test_thread.rb : separete assersions to tests
+ * yarvtest/test_thread.rb : separate assertions to tests
2006-02-21(Tue) 02:13:33 +900 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -1503,7 +1503,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* yarvcore.c : support Proc#dup/clone, Binding#dup/clone
- * sample/test.rb : remove unsupport features (Proc as Binding)
+ * sample/test.rb : remove unsupported features (Proc as Binding)
2006-02-20(Mon) 16:28:59 +0900 Koichi Sasada <ko1@atdot.net>
@@ -1560,7 +1560,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* yarvtest/test_thread.rb : add a test for above
* vm.h, vm.c, vm_dump.c, insns.def : add FRAME_MAGIC_LAMBDA and
- support return from lambda (especially retrun from method defined
+ support return from lambda (especially return from method defined
by "define_method")
* yarvtest/test_method.rb : add a test for above
@@ -1606,7 +1606,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* vm.c : "return" from lambda{} break block
- * eval.c : Unsupport Proc as Binding
+ * eval.c : Unsupported Proc as Binding
* test/ruby/test_eval.rb : apply above changes
@@ -3816,7 +3816,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
2005-12-29(Thu) 12:27:12 +0900 Koichi Sasada <ko1@atdot.net>
* compile.c, yarvcore.h :
- remvoe needless yarv_iseq_t#rewind_frame_size
+ remove needless yarv_iseq_t#rewind_frame_size
2005-12-29(Thu) 11:17:58 +0900 Koichi Sasada <ko1@atdot.net>
@@ -4530,7 +4530,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* vm.c : fix return process
- * vm_macro.def : fix option prameters
+ * vm_macro.def : fix option parameters
* yarvtest/test_method.rb : add tests for above
@@ -4555,7 +4555,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* eval_intern.h : fix PASS_PASSED_BLOCK()
- * eval_load.c : fix re-enter require (temporalily)
+ * eval_load.c : fix re-enter require (temporarily)
* insns.def : permit re-open class when superclass is same
@@ -4729,7 +4729,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* eval.c, eval_intern.h, vm.c, eval_jump.h, yarvcore.h :
re-define PUSH/POP/EXEC/JUMP_TAG to use thread local tag
- * inits.c, yarvcore.c : fix boostrap
+ * inits.c, yarvcore.c : fix bootstrap
2005-10-03(Mon) 22:28:24 +0900 Koichi Sasada <ko1@atdot.net>
@@ -4909,7 +4909,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
2005-09-14(Wed) 06:11:43 +0900 Koichi Sasada <ko1@atdot.net>
* yarvcore.h, vm_evalbody.h, vm.h, vm_dump.c,
- compile.c, yarvcore.c : use #ifdef insted of #if for recognize
+ compile.c, yarvcore.c : use #ifdef instead of #if for recognize
vm options
* vm_opts.h : fix default options
@@ -4973,13 +4973,13 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* common.mk : rule test -> test2, test1 -> test
- * compile.c : fix when clause bug and splat arugment
+ * compile.c : fix when clause bug and splat argument
2005-08-17(Wed) 05:22:31 +0900 Koichi Sasada <ko1@atdot.net>
* compile.c : fix block local parameter setting routine and support
- massign in block parameter initialze
+ massign in block parameter initialize
* yarvtest/test_yield.rb : add tests for above
@@ -5394,7 +5394,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* tmpl/vmtc.inc.tmpl : add const prefix
- * /rb/asm_parse.rb, extconf.rb : added and make assembler analised output
+ * /rb/asm_parse.rb, extconf.rb : added and make assembler analysed output
* opt_operand.def : add send operands unification
@@ -5654,7 +5654,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
2005-03-01(Tue) 13:50:04 +0900 Koichi Sasada <ko1@atdot.net>
* yarvcore.c (yarvcore_eval_parsed) : added
- (separeted from yarvcore_eval)
+ (separated from yarvcore_eval)
* yarvcore.c, compile.c : iseq_translate_direct_threaded_code
is moved to compile.c
@@ -5806,7 +5806,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* compiled.c : add constant pool
- * vm_evalbody.inc, call_cfunc.inc, vm.c : separeted from vm.c
+ * vm_evalbody.inc, call_cfunc.inc, vm.c : separated from vm.c
* insns.def : fix return val
@@ -5840,7 +5840,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* depend : fixed for above
- * extconf.rb : add option --(enable|disalbe)-opt-insns-unification
+ * extconf.rb : add option --(enable|disable)-opt-insns-unification
2005-02-11(Fri) 12:14:39 +0900 Koichi Sasada <ko1@atdot.net>
@@ -5957,7 +5957,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* evalc.patch : fix for above
- * benchmark/bm_lists.rb : fix (unsupport block passing)
+ * benchmark/bm_lists.rb : fix (unsupported block passing)
* benchmark/run.rb : use full path to ruby
@@ -6014,7 +6014,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* test/test_block.rb (test_ifunc) : test for above
- * vm.c (get_block_objec, thread_make_env_object) : fixed bugs
+ * vm.c (get_block_object, thread_make_env_object) : fixed bugs
* test/test_bin.rb (test_xstr) : remove `ls` test
@@ -6067,7 +6067,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
2005-01-04(Tue) 06:25:45 +0900 Koichi Sasada <ko1@atdot.net>
- * compile.h : COMPILE_ERROR break contol (instead of return)
+ * compile.h : COMPILE_ERROR break control (instead of return)
* compile.c : support NODE_MASGN
@@ -6108,7 +6108,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* insns.def : support super, zsuper (currently, super can't
handle with block)
- * test/test_bin.rb : add test for op_asgin2, op_assgin_and/or
+ * test/test_bin.rb : add test for op_assign2, op_assign_and/or
* test/test_class.rb : add test for super, zsuper
@@ -6272,7 +6272,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* opt_operand.def : add unification insn send
* rb/insns2vm.rb : define symbol instead of declare const
- variable (for more optmize on VC)
+ variable (for more optimize on VC)
* insns.def : move enter point in send
@@ -6322,7 +6322,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
2004-12-02(Thu) 13:20:41 +0900 Koichi Sasada <ko1@atdot.net>
* yarvcore.c, vm.h, vm.c, insns.def, insnhelper.h, yarvutil.rb :
- add usage analisys framework
+ add usage analysis framework
* disasm.c : insn_operand_intern to separate function
@@ -6489,7 +6489,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
2004-11-01(Mon) 04:45:54 +0900 Koichi Sasada <ko1@atdot.net>
* yarvcore.h, compile.c, debug.c, version.h :
- redesgin gc debug scheme (GC_CHECK())
+ redesign gc debug scheme (GC_CHECK())
* yarvcore.c : mark iseqobj->current_block on GC
@@ -6820,7 +6820,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* depend : add tbench rule
- * yarvcore.h : add 'exten ID idBackquote'
+ * yarvcore.h : add 'extern ID idBackquote'
2004-05-18(Tue) 00:09:48 +0900 Koichi Sasada <ko1@atdot.net>
diff --git a/doc/NEWS-1.8.7 b/doc/NEWS/NEWS-1.8.7
index 5da39ff265..5da39ff265 100644
--- a/doc/NEWS-1.8.7
+++ b/doc/NEWS/NEWS-1.8.7
diff --git a/doc/NEWS-1.9.1 b/doc/NEWS/NEWS-1.9.1
index fb11026d60..fb11026d60 100644
--- a/doc/NEWS-1.9.1
+++ b/doc/NEWS/NEWS-1.9.1
diff --git a/doc/NEWS-1.9.2 b/doc/NEWS/NEWS-1.9.2
index 430c6cc4f5..430c6cc4f5 100644
--- a/doc/NEWS-1.9.2
+++ b/doc/NEWS/NEWS-1.9.2
diff --git a/doc/NEWS-1.9.3 b/doc/NEWS/NEWS-1.9.3
index 484660f420..484660f420 100644
--- a/doc/NEWS-1.9.3
+++ b/doc/NEWS/NEWS-1.9.3
diff --git a/doc/NEWS-2.0.0 b/doc/NEWS/NEWS-2.0.0
index 712d3a693b..e070b19976 100644
--- a/doc/NEWS-2.0.0
+++ b/doc/NEWS/NEWS-2.0.0
@@ -376,7 +376,7 @@ with all sufficient information, see the ChangeLog file.
:TLSv1_2, :TLSv1_2_server, :TLSv1_2_client or :TLSv1_1, :TLSv1_1_server
:TLSv1_1_client. The version being effectively used can be queried
with OpenSSL::SSL#ssl_version. Furthermore, it is also possible to
- blacklist the new TLS versions with OpenSSL::SSL:OP_NO_TLSv1_1 and
+ blacklist the new TLS versions with OpenSSL::SSL::OP_NO_TLSv1_1 and
OpenSSL::SSL::OP_NO_TLSv1_2.
* Added OpenSSL::SSL::SSLContext#renegotiation_cb. A user-defined callback
may be set which gets called whenever a new handshake is negotiated. This
diff --git a/doc/NEWS-2.1.0 b/doc/NEWS/NEWS-2.1.0
index 26f2374e94..26f2374e94 100644
--- a/doc/NEWS-2.1.0
+++ b/doc/NEWS/NEWS-2.1.0
diff --git a/doc/NEWS-2.2.0 b/doc/NEWS/NEWS-2.2.0
index 8b2bd0ba0a..8b2bd0ba0a 100644
--- a/doc/NEWS-2.2.0
+++ b/doc/NEWS/NEWS-2.2.0
diff --git a/doc/NEWS-2.3.0 b/doc/NEWS/NEWS-2.3.0
index 065515257e..065515257e 100644
--- a/doc/NEWS-2.3.0
+++ b/doc/NEWS/NEWS-2.3.0
diff --git a/doc/NEWS-2.4.0 b/doc/NEWS/NEWS-2.4.0
index 8a02f03809..8a02f03809 100644
--- a/doc/NEWS-2.4.0
+++ b/doc/NEWS/NEWS-2.4.0
diff --git a/doc/NEWS-2.5.0 b/doc/NEWS/NEWS-2.5.0
index c891317b61..af7f3ada01 100644
--- a/doc/NEWS-2.5.0
+++ b/doc/NEWS/NEWS-2.5.0
@@ -466,7 +466,7 @@ with all sufficient information, see the ChangeLog file or Redmine
=== Compatibility issues (excluding feature bug fixes)
-* Socket
+* BasicSocket
* BasicSocket#read_nonblock and BasicSocket#write_nonblock no
longer set the O_NONBLOCK file description flag as side effect
diff --git a/doc/NEWS-2.6.0 b/doc/NEWS/NEWS-2.6.0
index 6e70696de2..6e70696de2 100644
--- a/doc/NEWS-2.6.0
+++ b/doc/NEWS/NEWS-2.6.0
diff --git a/doc/NEWS-2.7.0 b/doc/NEWS/NEWS-2.7.0
index 184b47fb8b..7607a473de 100644
--- a/doc/NEWS-2.7.0
+++ b/doc/NEWS/NEWS-2.7.0
@@ -357,6 +357,16 @@ See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outsta
can be directly passed to another method as a block
argument. [Feature #15618]
+ * Added Enumerator::Lazy#with_index be lazy
+ Previously, Enumerator::Lazy#with_index was not defined, so it
+ picked up the default implementation from Enumerator, which was
+ not lazy. [Bug #7877]
+
+ ("a"..).lazy.with_index(1) { |it, index| puts "#{index}:#{it}" }.take(3).force
+ # => 1:a
+ # 2:b
+ # 3:c
+
[Fiber]
[New method]
diff --git a/doc/NEWS-3.0.0.md b/doc/NEWS/NEWS-3.0.0.md
index 6ec5a09d79..bdbd47327b 100644
--- a/doc/NEWS-3.0.0.md
+++ b/doc/NEWS/NEWS-3.0.0.md
@@ -86,7 +86,7 @@ Note that each entry is kept to a minimum, see links for details.
`# 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.
+ See {Magic Comments}[rdoc-ref:syntax/comments.rdoc@Magic+Comments] for more details.
[[Feature #17273]]
* A {static analysis}[rdoc-label:label-Static+analysis] foundation is
@@ -512,6 +512,18 @@ Outstanding ones only.
* This version is Ractor compatible.
+* URI
+
+ * URI.escape and URI.unescape have been removed.
+ Instead, use the following methods depending on your specific use case.
+
+ * CGI.escape
+ * URI.encode_www_form
+ * URI.encode_www_form_component
+ * CGI.unescape
+ * URI.decode_www_form
+ * URI.decode_www_form_component
+
## Compatibility issues
Excluding feature bug fixes.
diff --git a/doc/NEWS/NEWS-3.1.0.md b/doc/NEWS/NEWS-3.1.0.md
new file mode 100644
index 0000000000..fe292fc414
--- /dev/null
+++ b/doc/NEWS/NEWS-3.1.0.md
@@ -0,0 +1,660 @@
+# NEWS for Ruby 3.1.0
+
+This document is a list of user-visible feature changes
+since the **3.0.0** release, except for bug fixes.
+
+Note that each entry is kept to a minimum, see links for details.
+
+## Language changes
+
+* The block argument can now be anonymous if the block will
+ only be passed to another method. [[Feature #11256]]
+
+ ```ruby
+ def foo(&)
+ bar(&)
+ end
+ ```
+
+* Pin operator now takes an expression. [[Feature #17411]]
+
+ ```ruby
+ Prime.each_cons(2).lazy.find_all{_1 in [n, ^(n + 2)]}.take(3).to_a
+ #=> [[3, 5], [5, 7], [11, 13]]
+ ```
+
+* Pin operator now supports instance, class, and global variables.
+ [[Feature #17724]]
+
+ ```ruby
+ @n = 5
+ Prime.each_cons(2).lazy.find{_1 in [n, ^@n]}
+ #=> [3, 5]
+ ```
+
+* One-line pattern matching is no longer experimental.
+
+* Parentheses can be omitted in one-line pattern matching.
+ [[Feature #16182]]
+
+ ```ruby
+ [0, 1] => _, x
+ {y: 2} => y:
+ x #=> 1
+ y #=> 2
+ ```
+
+* Multiple assignment evaluation order has been made consistent with
+ single assignment evaluation order. With single assignment, Ruby
+ uses a left-to-right evaluation order. With this code:
+
+ ```ruby
+ foo[0] = bar
+ ```
+
+ The following evaluation order is used:
+
+ 1. `foo`
+ 2. `bar`
+ 3. `[]=` called on the result of `foo`
+
+ In Ruby before 3.1.0, multiple assignment did not follow this
+ evaluation order. With this code:
+
+ ```ruby
+ foo[0], bar.baz = a, b
+ ```
+
+ Versions of Ruby before 3.1.0 would evaluate in the following
+ order
+
+ 1. `a`
+ 2. `b`
+ 3. `foo`
+ 4. `[]=` called on the result of `foo`
+ 5. `bar`
+ 6. `baz=` called on the result of `bar`
+
+ Starting in Ruby 3.1.0, the evaluation order is now consistent with
+ single assignment, with the left-hand side being evaluated before
+ the right-hand side:
+
+ 1. `foo`
+ 2. `bar`
+ 3. `a`
+ 4. `b`
+ 5. `[]=` called on the result of `foo`
+ 6. `baz=` called on the result of `bar`
+
+ [[Bug #4443]]
+
+* Values in Hash literals and keyword arguments can be omitted.
+ [[Feature #14579]]
+
+ For example,
+
+ * `{x:, y:}` is a syntax sugar of `{x: x, y: y}`.
+ * `foo(x:, y:)` is a syntax sugar of `foo(x: x, y: y)`.
+
+ Constant names, local variable names, and method names are allowed as
+ key names. Note that a reserved word is considered as a local
+ variable or method name even if it's a pseudo variable name such as
+ `self`.
+
+* Non main-Ractors can get instance variables (ivars) of classes/modules
+ if ivars refer to shareable objects.
+ [[Feature #17592]]
+
+* A command syntax is allowed in endless method definitions, i.e.,
+ you can now write `def foo = puts "Hello"`.
+ Note that `private def foo = puts "Hello"` does not parse.
+ [[Feature #17398]]
+
+## Command line options
+
+* `--disable-gems` is now explicitly declared as "just for debugging".
+ Never use it in any real-world codebase.
+ [[Feature #17684]]
+
+## Core classes updates
+
+Note: We're only listing outstanding class updates.
+
+* Array
+
+ * Array#intersect? is added. [[Feature #15198]]
+
+* Class
+
+ * Class#subclasses, which returns an array of classes
+ directly inheriting from the receiver, not
+ including singleton classes.
+ [[Feature #18273]]
+
+ ```ruby
+ class A; end
+ class B < A; end
+ class C < B; end
+ class D < A; end
+ A.subclasses #=> [D, B]
+ B.subclasses #=> [C]
+ C.subclasses #=> []
+ ```
+
+* Enumerable
+
+ * Enumerable#compact is added. [[Feature #17312]]
+
+ * Enumerable#tally now accepts an optional hash to count. [[Feature #17744]]
+
+ * Enumerable#each_cons and each_slice to return a receiver. [[GH-1509]]
+
+ ```ruby
+ [1, 2, 3].each_cons(2){}
+ # 3.0 => nil
+ # 3.1 => [1, 2, 3]
+
+ [1, 2, 3].each_slice(2){}
+ # 3.0 => nil
+ # 3.1 => [1, 2, 3]
+ ```
+
+* Enumerator::Lazy
+
+ * Enumerator::Lazy#compact is added. [[Feature #17312]]
+
+* File
+
+ * File.dirname now accepts an optional argument for the level to
+ strip path components. [[Feature #12194]]
+
+* GC
+
+ * "GC.measure_total_time = true" enables the measurement of GC.
+ Measurement can introduce overhead. It is enabled by default.
+ GC.measure_total_time returns the current setting.
+ GC.stat[:time] or GC.stat(:time) returns measured time
+ in milli-seconds. [[[Feature #10917]]]
+
+ * GC.total_time returns measured time in nano-seconds. [[[Feature #10917]]]
+
+* Integer
+
+ * Integer.try_convert is added. [[Feature #15211]]
+
+* Kernel
+
+ * Kernel#load now accepts a module as the second argument,
+ and will load the file using the given module as the
+ top-level module. [[Feature #6210]]
+
+* Marshal
+
+ * Marshal.load now accepts a `freeze: true` option.
+ All returned objects are frozen except for `Class` and
+ `Module` instances. Strings are deduplicated. [[Feature #18148]]
+
+* MatchData
+
+ * MatchData#match is added [[Feature #18172]]
+
+ * MatchData#match_length is added [[Feature #18172]]
+
+* Method / UnboundMethod
+
+ * Method#public?, Method#private?, Method#protected?,
+ UnboundMethod#public?, UnboundMethod#private?,
+ UnboundMethod#protected? have been added. [[Feature #11689]]
+
+* Module
+
+ * Module#prepend now modifies the ancestor chain if the receiver
+ already includes the argument. Module#prepend still does not
+ modify the ancestor chain if the receiver has already prepended
+ the argument. [[Bug #17423]]
+
+ * Module#private, #public, #protected, and #module_function will
+ now return their arguments. If a single argument is given, it
+ is returned. If no arguments are given, nil is returned. If
+ multiple arguments are given, they are returned as an array.
+ [[Feature #12495]]
+
+* Process
+
+ * Process.\_fork is added. This is a core method for fork(2).
+ Do not call this method directly; it is called by existing
+ fork methods: Kernel.#fork, Process.fork, and IO.popen("-").
+ Application monitoring libraries can overwrite this method to
+ hook fork events. [[Feature #17795]]
+
+* Struct
+
+ * Passing only keyword arguments to Struct#initialize is warned.
+ You need to use a Hash literal to set a Hash to a first member.
+ [[Feature #16806]]
+
+ * StructClass#keyword_init? is added [[Feature #18008]]
+
+* String
+
+ * Update Unicode version to 13.0.0 [[Feature #17750]]
+ and Emoji version to 13.0 [[Feature #18029]]
+
+ * String#unpack and String#unpack1 now accept an `offset:` keyword
+ argument to start the unpacking after an arbitrary number of bytes
+ have been skipped. If `offset` is outside of the string bounds
+ `ArgumentError` is raised. [[Feature #18254]]
+
+* Thread
+
+ * Thread#native_thread_id is added. [[Feature #17853]]
+
+* Thread::Backtrace
+
+ * Thread::Backtrace.limit, which returns the value to limit backtrace
+ length set by `--backtrace-limit` command line option, is added.
+ [[Feature #17479]]
+
+* Thread::Queue
+
+ * Thread::Queue.new now accepts an Enumerable of initial values.
+ [[Feature #17327]]
+
+* Time
+
+ * Time.new now accepts optional `in:` keyword argument for the
+ timezone, as well as `Time.at` and `Time.now`, so that is now
+ you can omit minor arguments to `Time.new`. [[Feature #17485]]
+
+ ```ruby
+ Time.new(2021, 12, 25, in: "+07:00")
+ #=> 2021-12-25 00:00:00 +0700
+ ```
+
+ At the same time, time component strings are converted to
+ integers more strictly now.
+
+ ```ruby
+ Time.new(2021, 12, 25, "+07:30")
+ #=> invalid value for Integer(): "+07:30" (ArgumentError)
+ ```
+
+ Ruby 3.0 or earlier returned probably unexpected result
+ `2021-12-25 07:00:00`, not `2021-12-25 07:30:00` nor
+ `2021-12-25 00:00:00 +07:30`.
+
+ * Time#strftime supports RFC 3339 UTC for unknown offset local
+ time, `-0000`, as `%-z`. [[Feature #17544]]
+
+* TracePoint
+
+ * TracePoint.allow_reentry is added to allow reenter while TracePoint
+ callback.
+ [[Feature #15912]]
+
+* $LOAD_PATH
+
+ * $LOAD_PATH.resolve_feature_path does not raise. [[Feature #16043]]
+
+* Fiber Scheduler
+
+ * Add support for `Addrinfo.getaddrinfo` using `address_resolve` hook.
+ [[Feature #17370]]
+
+ * Introduce non-blocking `Timeout.timeout` using `timeout_after` hook.
+ [[Feature #17470]]
+
+ * Introduce new scheduler hooks `io_read` and `io_write` along with a
+ low level `IO::Buffer` for zero-copy read/write. [[Feature #18020]]
+
+ * IO hooks `io_wait`, `io_read`, `io_write`, receive the original IO object
+ where possible. [[Bug #18003]]
+
+ * Make `Monitor` fiber-safe. [[Bug #17827]]
+
+ * Replace copy coroutine with pthread implementation. [[Feature #18015]]
+
+* Refinement
+
+ * New class which represents a module created by Module#refine.
+ `include` and `prepend` are deprecated, and `import_methods` is added
+ instead. [[Bug #17429]]
+
+## Stdlib updates
+
+* The following default gem are updated.
+ * RubyGems 3.3.3
+ * base64 0.1.1
+ * benchmark 0.2.0
+ * bigdecimal 3.1.1
+ * bundler 2.3.3
+ * cgi 0.3.1
+ * csv 3.2.2
+ * date 3.2.2
+ * did_you_mean 1.6.1
+ * digest 3.1.0
+ * drb 2.1.0
+ * erb 2.2.3
+ * error_highlight 0.3.0
+ * etc 1.3.0
+ * fcntl 1.0.1
+ * fiddle 1.1.0
+ * fileutils 1.6.0
+ * find 0.1.1
+ * io-console 0.5.10
+ * io-wait 0.2.1
+ * ipaddr 1.2.3
+ * irb 1.4.1
+ * json 2.6.1
+ * logger 1.5.0
+ * net-http 0.2.0
+ * net-protocol 0.1.2
+ * nkf 0.1.1
+ * open-uri 0.2.0
+ * openssl 3.0.0
+ * optparse 0.2.0
+ * ostruct 0.5.2
+ * pathname 0.2.0
+ * pp 0.3.0
+ * prettyprint 0.1.1
+ * psych 4.0.3
+ * racc 1.6.0
+ * rdoc 6.4.0
+ * readline 0.0.3
+ * readline-ext 0.1.4
+ * reline 0.3.0
+ * resolv 0.2.1
+ * rinda 0.1.1
+ * ruby2_keywords 0.0.5
+ * securerandom 0.1.1
+ * set 1.0.2
+ * stringio 3.0.1
+ * strscan 3.0.1
+ * tempfile 0.1.2
+ * time 0.2.0
+ * timeout 0.2.0
+ * tmpdir 0.1.2
+ * un 0.2.0
+ * uri 0.11.0
+ * yaml 0.2.0
+ * zlib 2.1.1
+* The following bundled gems are updated.
+ * minitest 5.15.0
+ * power_assert 2.0.1
+ * rake 13.0.6
+ * test-unit 3.5.3
+ * rexml 3.2.5
+ * rbs 2.0.0
+ * typeprof 0.21.1
+* The following default gems are now bundled gems.
+ * net-ftp 0.1.3
+ * net-imap 0.2.2
+ * net-pop 0.1.1
+ * net-smtp 0.3.1
+ * matrix 0.4.2
+ * prime 0.1.2
+ * debug 1.4.0
+* The following gems has been removed from the Ruby standard library.
+ * dbm
+ * gdbm
+ * tracer
+
+* Coverage measurement now supports suspension. You can use `Coverage.suspend`
+ to stop the measurement temporarily, and `Coverage.resume` to restart it.
+ See [[Feature #18176]] in detail.
+
+* Random::Formatter is moved to random/formatter.rb, so that you can
+ use `Random#hex`, `Random#base64`, and so on without SecureRandom.
+ [[Feature #18190]]
+
+## Compatibility issues
+
+Note: Excluding feature bug fixes.
+
+* `rb_io_wait_readable`, `rb_io_wait_writable` and `rb_wait_for_single_fd` are
+ deprecated in favour of `rb_io_maybe_wait_readable`,
+ `rb_io_maybe_wait_writable` and `rb_io_maybe_wait` respectively.
+ `rb_thread_wait_fd` and `rb_thread_fd_writable` are deprecated. [[Bug #18003]]
+
+## Stdlib compatibility issues
+
+* `ERB#initialize` warns `safe_level` and later arguments even without -w.
+ [[Feature #14256]]
+
+* `lib/debug.rb` is replaced with `debug.gem`
+
+* `Kernel#pp` in `lib/pp.rb` uses the width of `IO#winsize` by default.
+ This means that the output width is automatically changed depending on
+ your terminal size. [[Feature #12913]]
+
+* Psych 4.0 changes `Psych.load` as `safe_load` by the default.
+ You may need to use Psych 3.3.2 for migrating to this behavior.
+ [[Bug #17866]]
+
+## C API updates
+
+* Documented. [[GH-4815]]
+
+* `rb_gc_force_recycle` is deprecated and has been changed to a no-op.
+ [[Feature #18290]]
+
+## Implementation improvements
+
+* Inline cache mechanism is introduced for reading class variables.
+ [[Feature #17763]]
+
+* `instance_eval` and `instance_exec` now only allocate a singleton class when
+ required, avoiding extra objects and improving performance. [[GH-5146]]
+
+* The performance of `Struct` accessors is improved. [[GH-5131]]
+
+* `mandatory_only?` builtin special form to improve performance on
+ builtin methods. [[GH-5112]]
+
+* Experimental feature Variable Width Allocation in the garbage collector.
+ This feature is turned off by default and can be enabled by compiling Ruby
+ with flag `USE_RVARGC=1` set. [[Feature #18045]] [[Feature #18239]]
+
+## JIT
+
+* Rename Ruby 3.0's `--jit` to `--mjit`, and alias `--jit` to `--yjit`
+ on non-Windows x86-64 platforms and to `--mjit` on others.
+
+### MJIT
+
+* The default `--mjit-max-cache` is changed from 100 to 10000.
+
+* JIT-ed code is no longer cancelled when a TracePoint for class events
+ is enabled.
+
+* The JIT compiler no longer skips compilation of methods longer than
+ 1000 instructions.
+
+* `--mjit-verbose` and `--mjit-warning` output "JIT cancel" when JIT-ed
+ code is disabled because TracePoint or GC.compact is used.
+
+### YJIT: New experimental in-process JIT compiler
+
+New JIT compiler available as an experimental feature. [[Feature #18229]]
+
+See [this blog post](https://shopify.engineering/yjit-just-in-time-compiler-cruby
+) introducing the project.
+
+* Disabled by default, use `--yjit` command-line option to enable YJIT.
+
+* Performance improvements on benchmarks based on real-world software,
+ up to 22% on railsbench, 39% on liquid-render.
+
+* Fast warm-up times.
+
+* Limited to Unix-like x86-64 platforms for now.
+
+## Static analysis
+
+### RBS
+
+* Generics type parameters can be bounded ([PR](https://github.com/ruby/rbs/pull/844)).
+
+ ```rbs
+ # `T` must be compatible with the `_Output` interface.
+ # `PrettyPrint[String]` is ok, but `PrettyPrint[Integer]` is a type error.
+ class PrettyPrint[T < _Output]
+ interface _Output
+ def <<: (String) -> void
+ end
+
+ attr_reader output: T
+
+ def initialize: (T output) -> void
+ end
+ ```
+
+* Type aliases can be generic. ([PR](https://github.com/ruby/rbs/pull/823))
+
+ ```rbs
+ # Defines a generic type `list`.
+ type list[T] = [ T, list[T] ]
+ | nil
+
+ type str_list = list[String]
+ type int_list = list[Integer]
+ ```
+
+* [rbs collection](https://github.com/ruby/rbs/blob/cdd6a3a896001e25bd1feda3eab7f470bae935c1/docs/collection.md) has been introduced to manage gems’ RBSs.
+
+* Many signatures for built-in and standard libraries have been added/updated.
+
+* It includes many bug fixes and performance improvements too.
+
+See the [CHANGELOG.md](https://github.com/ruby/rbs/blob/cdd6a3a896001e25bd1feda3eab7f470bae935c1/CHANGELOG.md) for more information.
+
+### TypeProf
+
+* [Experimental IDE support](https://github.com/ruby/typeprof/blob/ca15c5dae9bd62668463165f8409bd66ce7de223/doc/ide.md) has been implemented.
+* Many bug fixes and performance improvements since Ruby 3.0.0.
+
+## Debugger
+
+* A new debugger [debug.gem](https://github.com/ruby/debug) is bundled.
+ debug.gem is a fast debugger implementation, and it provides many features
+ like remote debugging, colorful REPL, IDE (VSCode) integration, and more.
+ It replaces `lib/debug.rb` standard library.
+
+* `rdbg` command is also installed into `bin/` directory to start and control
+ debugging execution.
+
+## error_highlight
+
+A built-in gem called error_highlight has been introduced.
+It shows fine-grained error locations in the backtrace.
+
+Example: `title = json[:article][:title]`
+
+If `json` is nil, it shows:
+
+```
+$ ruby test.rb
+test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
+
+title = json[:article][:title]
+ ^^^^^^^^^^
+```
+
+If `json[:article]` returns nil, it shows:
+
+```
+$ ruby test.rb
+test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
+
+title = json[:article][:title]
+ ^^^^^^^^
+```
+
+This feature is enabled by default.
+You can disable it by using a command-line option `--disable-error_highlight`.
+See [the repository](https://github.com/ruby/error_highlight) in detail.
+
+## IRB Autocomplete and Document Display
+
+The IRB now has an autocomplete feature, where you can just type in the code, and the completion candidates dialog will appear. You can use Tab and Shift+Tab to move up and down.
+
+If documents are installed when you select a completion candidate, the documentation dialog will appear next to the completion candidates dialog, showing part of the content. You can read the full document by pressing Alt+d.
+
+## Miscellaneous changes
+
+* lib/objspace/trace.rb is added, which is a tool for tracing the object
+ allocation. Just by requiring this file, tracing is started *immediately*.
+ Just by `Kernel#p`, you can investigate where an object was created.
+ Note that just requiring this file brings a large performance overhead.
+ This is only for debugging purposes. Do not use this in production.
+ [[Feature #17762]]
+
+* Now exceptions raised in finalizers will be printed to `STDERR`, unless
+ `$VERBOSE` is `nil`. [[Feature #17798]]
+
+* `ruby -run -e httpd` displays URLs to access. [[Feature #17847]]
+
+* Add `ruby -run -e colorize` to colorize Ruby code using
+ `IRB::Color.colorize_code`.
+
+[Bug #4443]: https://bugs.ruby-lang.org/issues/4443
+[Feature #6210]: https://bugs.ruby-lang.org/issues/6210
+[Feature #10917]: https://bugs.ruby-lang.org/issues/10917
+[Feature #11256]: https://bugs.ruby-lang.org/issues/11256
+[Feature #11689]: https://bugs.ruby-lang.org/issues/11689
+[Feature #12194]: https://bugs.ruby-lang.org/issues/12194
+[Feature #12495]: https://bugs.ruby-lang.org/issues/12495
+[Feature #12913]: https://bugs.ruby-lang.org/issues/12913
+[Feature #14256]: https://bugs.ruby-lang.org/issues/14256
+[Feature #14579]: https://bugs.ruby-lang.org/issues/14579
+[Feature #15198]: https://bugs.ruby-lang.org/issues/15198
+[Feature #15211]: https://bugs.ruby-lang.org/issues/15211
+[Feature #15912]: https://bugs.ruby-lang.org/issues/15912
+[Feature #16043]: https://bugs.ruby-lang.org/issues/16043
+[Feature #16182]: https://bugs.ruby-lang.org/issues/16182
+[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
+[Feature #17312]: https://bugs.ruby-lang.org/issues/17312
+[Feature #17327]: https://bugs.ruby-lang.org/issues/17327
+[Feature #17370]: https://bugs.ruby-lang.org/issues/17370
+[Feature #17398]: https://bugs.ruby-lang.org/issues/17398
+[Feature #17411]: https://bugs.ruby-lang.org/issues/17411
+[Bug #17423]: https://bugs.ruby-lang.org/issues/17423
+[Bug #17429]: https://bugs.ruby-lang.org/issues/17429
+[Feature #17470]: https://bugs.ruby-lang.org/issues/17470
+[Feature #17479]: https://bugs.ruby-lang.org/issues/17479
+[Feature #17485]: https://bugs.ruby-lang.org/issues/17485
+[Feature #17544]: https://bugs.ruby-lang.org/issues/17544
+[Feature #17592]: https://bugs.ruby-lang.org/issues/17592
+[Feature #17684]: https://bugs.ruby-lang.org/issues/17684
+[Feature #17724]: https://bugs.ruby-lang.org/issues/17724
+[Feature #17744]: https://bugs.ruby-lang.org/issues/17744
+[Feature #17750]: https://bugs.ruby-lang.org/issues/17750
+[Feature #17762]: https://bugs.ruby-lang.org/issues/17762
+[Feature #17763]: https://bugs.ruby-lang.org/issues/17763
+[Feature #17795]: https://bugs.ruby-lang.org/issues/17795
+[Feature #17798]: https://bugs.ruby-lang.org/issues/17798
+[Bug #17827]: https://bugs.ruby-lang.org/issues/17827
+[Feature #17847]: https://bugs.ruby-lang.org/issues/17847
+[Feature #17853]: https://bugs.ruby-lang.org/issues/17853
+[Bug #17866]: https://bugs.ruby-lang.org/issues/17866
+[Bug #18003]: https://bugs.ruby-lang.org/issues/18003
+[Feature #18008]: https://bugs.ruby-lang.org/issues/18008
+[Feature #18015]: https://bugs.ruby-lang.org/issues/18015
+[Feature #18020]: https://bugs.ruby-lang.org/issues/18020
+[Feature #18029]: https://bugs.ruby-lang.org/issues/18029
+[Feature #18045]: https://bugs.ruby-lang.org/issues/18045
+[Feature #18148]: https://bugs.ruby-lang.org/issues/18148
+[Feature #18172]: https://bugs.ruby-lang.org/issues/18172
+[Feature #18176]: https://bugs.ruby-lang.org/issues/18176
+[Feature #18190]: https://bugs.ruby-lang.org/issues/18190
+[Feature #18229]: https://bugs.ruby-lang.org/issues/18229
+[Feature #18239]: https://bugs.ruby-lang.org/issues/18239
+[Feature #18254]: https://bugs.ruby-lang.org/issues/18254
+[Feature #18273]: https://bugs.ruby-lang.org/issues/18273
+[Feature #18290]: https://bugs.ruby-lang.org/issues/18290
+
+[GH-1509]: https://github.com/ruby/ruby/pull/1509
+[GH-4815]: https://github.com/ruby/ruby/pull/4815
+[GH-5112]: https://github.com/ruby/ruby/pull/5112
+[GH-5131]: https://github.com/ruby/ruby/pull/5131
+[GH-5146]: https://github.com/ruby/ruby/pull/5146
diff --git a/doc/bsearch.rdoc b/doc/bsearch.rdoc
new file mode 100644
index 0000000000..ca8091fc0d
--- /dev/null
+++ b/doc/bsearch.rdoc
@@ -0,0 +1,120 @@
+== Binary Searching
+
+A few Ruby methods support binary searching in a collection:
+
+Array#bsearch:: Returns an element selected via a binary search
+ as determined by a given block.
+Array#bsearch_index:: Returns the index of an element selected via a binary search
+ as determined by a given block.
+Range#bsearch:: Returns an element selected via a binary search
+ as determined by a given block.
+
+Each of these methods returns an enumerator if no block is given.
+
+Given a block, each of these methods returns an element (or element index) from +self+
+as determined by a binary search.
+The search finds an element of +self+ which meets
+the given condition in <tt>O(log n)</tt> operations, where +n+ is the count of elements.
++self+ should be sorted, but this is not checked.
+
+There are two search modes:
+
+Find-minimum mode:: method +bsearch+ returns the first element for which
+ the block returns +true+;
+ the block must return +true+ or +false+.
+Find-any mode:: method +bsearch+ some element, if any, for which
+ the block returns zero.
+ the block must return a numeric value.
+
+The block should not mix the modes by sometimes returning +true+ or +false+
+and other times returning a numeric value, but this is not checked.
+
+<b>Find-Minimum Mode</b>
+
+In find-minimum mode, the block must return +true+ or +false+.
+The further requirement (though not checked) is that
+there are no indexes +i+ and +j+ such that:
+
+- <tt>0 <= i < j <= self.size</tt>.
+- The block returns +true+ for <tt>self[i]</tt> and +false+ for <tt>self[j]</tt>.
+
+Less formally: the block is such that all +false+-evaluating elements
+precede all +true+-evaluating elements.
+
+In find-minimum mode, method +bsearch+ returns the first element
+for which the block returns +true+.
+
+Examples:
+
+ a = [0, 4, 7, 10, 12]
+ a.bsearch {|x| x >= 4 } # => 4
+ a.bsearch {|x| x >= 6 } # => 7
+ a.bsearch {|x| x >= -1 } # => 0
+ a.bsearch {|x| x >= 100 } # => nil
+
+ r = (0...a.size)
+ r.bsearch {|i| a[i] >= 4 } #=> 1
+ r.bsearch {|i| a[i] >= 6 } #=> 2
+ r.bsearch {|i| a[i] >= 8 } #=> 3
+ r.bsearch {|i| a[i] >= 100 } #=> nil
+ r = (0.0...Float::INFINITY)
+ r.bsearch {|x| Math.log(x) >= 0 } #=> 1.0
+
+These blocks make sense in find-minimum mode:
+
+ a = [0, 4, 7, 10, 12]
+ a.map {|x| x >= 4 } # => [false, true, true, true, true]
+ a.map {|x| x >= 6 } # => [false, false, true, true, true]
+ a.map {|x| x >= -1 } # => [true, true, true, true, true]
+ a.map {|x| x >= 100 } # => [false, false, false, false, false]
+
+This would not make sense:
+
+ a.map {|x| x == 7 } # => [false, false, true, false, false]
+
+<b>Find-Any Mode</b>
+
+In find-any mode, the block must return a numeric value.
+The further requirement (though not checked) is that
+there are no indexes +i+ and +j+ such that:
+
+- <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>.
+
+Less formally: the block is such that:
+
+- All positive-evaluating elements precede all zero-evaluating elements.
+- All positive-evaluating elements precede all negative-evaluating elements.
+- All zero-evaluating elements precede all negative-evaluating elements.
+
+In find-any mode, method +bsearch+ returns some element
+for which the block returns zero, or +nil+ if no such element is found.
+
+Examples:
+
+ a = [0, 4, 7, 10, 12]
+ a.bsearch {|element| 7 <=> element } # => 7
+ a.bsearch {|element| -1 <=> element } # => nil
+ a.bsearch {|element| 5 <=> element } # => nil
+ a.bsearch {|element| 15 <=> element } # => nil
+
+ a = [0, 100, 100, 100, 200]
+ r = (0..4)
+ r.bsearch {|i| 100 - a[i] } #=> 1, 2 or 3
+ r.bsearch {|i| 300 - a[i] } #=> nil
+ r.bsearch {|i| 50 - a[i] } #=> nil
+
+These blocks make sense in find-any mode:
+
+ a = [0, 4, 7, 10, 12]
+ a.map {|element| 7 <=> element } # => [1, 1, 0, -1, -1]
+ a.map {|element| -1 <=> element } # => [-1, -1, -1, -1, -1]
+ a.map {|element| 5 <=> element } # => [1, 1, -1, -1, -1]
+ a.map {|element| 15 <=> element } # => [1, 1, 1, 1, 1]
+
+This would not make sense:
+
+ a.map {|element| element <=> 7 } # => [-1, -1, 0, 1, 1]
diff --git a/doc/case_mapping.rdoc b/doc/case_mapping.rdoc
new file mode 100644
index 0000000000..3c42154973
--- /dev/null
+++ b/doc/case_mapping.rdoc
@@ -0,0 +1,116 @@
+== Case Mapping
+
+Some string-oriented methods use case mapping.
+
+In String:
+
+- String#capitalize
+- String#capitalize!
+- String#casecmp
+- String#casecmp?
+- String#downcase
+- String#downcase!
+- String#swapcase
+- String#swapcase!
+- String#upcase
+- String#upcase!
+
+In Symbol:
+
+- Symbol#capitalize
+- Symbol#casecmp
+- Symbol#casecmp?
+- Symbol#downcase
+- Symbol#swapcase
+- Symbol#upcase
+
+=== Default Case Mapping
+
+By default, all of these methods use full Unicode case mapping,
+which is suitable for most languages.
+See {Section 3.13 (Default Case Algorithms) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf].
+
+Non-ASCII case mapping and folding are supported for UTF-8,
+UTF-16BE/LE, UTF-32BE/LE, and ISO-8859-1~16 Strings/Symbols.
+
+Context-dependent case mapping as described in
+{Table 3-17 (Context Specification for Casing) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf]
+is currently not supported.
+
+In most cases, case conversions of a string have the same number of characters.
+There are exceptions (see also +:fold+ below):
+
+ s = "\u00DF" # => "ß"
+ s.upcase # => "SS"
+ s = "\u0149" # => "ʼn"
+ s.upcase # => "ʼN"
+
+Case mapping may also depend on locale (see also +:turkic+ below):
+
+ s = "\u0049" # => "I"
+ s.downcase # => "i" # Dot above.
+ s.downcase(:turkic) # => "ı" # No dot above.
+
+Case changes may not be reversible:
+
+ s = 'Hello World!' # => "Hello World!"
+ s.downcase # => "hello world!"
+ s.downcase.upcase # => "HELLO WORLD!" # Different from original s.
+
+Case changing methods may not maintain Unicode normalization.
+See String#unicode_normalize).
+
+=== Options for Case Mapping
+
+Except for +casecmp+ and +casecmp?+,
+each of the case-mapping methods listed above
+accepts optional arguments, <tt>*options</tt>.
+
+The arguments may be:
+
+- +:ascii+ only.
+- +:fold+ only.
+- +:turkic+ or +:lithuanian+ or both.
+
+The options:
+
+- +:ascii+:
+ ASCII-only mapping:
+ uppercase letters ('A'..'Z') are mapped to lowercase letters ('a'..'z);
+ other characters are not changed
+
+ s = "Foo \u00D8 \u00F8 Bar" # => "Foo Ø ø Bar"
+ s.upcase # => "FOO Ø Ø BAR"
+ s.downcase # => "foo ø ø bar"
+ s.upcase(:ascii) # => "FOO Ø ø BAR"
+ s.downcase(:ascii) # => "foo Ø ø bar"
+
+- +:turkic+:
+ Full Unicode case mapping, adapted for the Turkic languages
+ that distinguish dotted and dotless I, for example Turkish and Azeri.
+
+ s = 'Türkiye' # => "Türkiye"
+ s.upcase # => "TÜRKIYE"
+ s.upcase(:turkic) # => "TÜRKİYE" # Dot above.
+
+ s = 'TÜRKIYE' # => "TÜRKIYE"
+ s.downcase # => "türkiye"
+ s.downcase(:turkic) # => "türkıye" # No dot above.
+
+- +:lithuanian+:
+ Not yet implemented.
+
+- +:fold+ (available only for String#downcase, String#downcase!,
+ and Symbol#downcase):
+ Unicode case folding,
+ which is more far-reaching than Unicode case mapping.
+
+ s = "\u00DF" # => "ß"
+ s.downcase # => "ß"
+ s.downcase(:fold) # => "ss"
+ s.upcase # => "SS"
+
+ s = "\uFB04" # => "ffl"
+ s.downcase # => "ffl"
+ s.upcase # => "FFL"
+ s.downcase(:fold) # => "ffl"
diff --git a/doc/character_selectors.rdoc b/doc/character_selectors.rdoc
new file mode 100644
index 0000000000..e01b0e6a25
--- /dev/null
+++ b/doc/character_selectors.rdoc
@@ -0,0 +1,97 @@
+== Character Selectors
+
+=== Character Selector
+
+A _character_ _selector_ is a string argument accepted by certain Ruby methods.
+Each of these instance methods accepts one or more character selectors:
+
+- String#tr(selector, replacements): returns a new string.
+- String#tr!(selector, replacements): returns +self+ or +nil+.
+- String#tr_s(selector, replacements): returns a new string.
+- String#tr_s!(selector, replacements): returns +self+ or +nil+.
+- String#count(*selectors): returns the count of the specified characters.
+- String#delete(*selectors): returns a new string.
+- String#delete!(*selectors): returns +self+ or +nil+.
+- String#squeeze(*selectors): returns a new string.
+- String#squeeze!(*selectors): returns +self+ or +nil+.
+
+A character selector identifies zero or more characters in +self+
+that are to be operands for the method.
+
+In this section, we illustrate using method String#delete(selector),
+which deletes the selected characters.
+
+In the simplest case, the characters selected are exactly those
+contained in the selector itself:
+
+ 'abracadabra'.delete('a') # => "brcdbr"
+ 'abracadabra'.delete('ab') # => "rcdr"
+ 'abracadabra'.delete('abc') # => "rdr"
+ '0123456789'.delete('258') # => "0134679"
+ '!@#$%&*()_+'.delete('+&#') # => "!@$%*()_"
+ 'тест'.delete('т') # => "ес"
+ 'こんにちは'.delete('に') # => "こんちは"
+
+Note that order and repetitions do not matter:
+
+ 'abracadabra'.delete('dcab') # => "rr"
+ 'abracadabra'.delete('aaaa') # => "brcdbr"
+
+In a character selector, these three characters get special treatment:
+
+- A leading caret (<tt>'^'</tt>) functions as a "not" operator
+ for the characters to its right:
+
+ 'abracadabra'.delete('^bc') # => "bcb"
+ '0123456789'.delete('^852') # => "258"
+
+- A hyphen (<tt>'-'</tt>) between two other characters
+ defines a range of characters instead of a plain string of characters:
+
+ 'abracadabra'.delete('a-d') # => "rr"
+ '0123456789'.delete('4-7') # => "012389"
+ '!@#$%&*()_+'.delete(' -/') # => "@^_"
+
+ # May contain more than one range.
+ 'abracadabra'.delete('a-cq-t') # => "d"
+
+ # Ranges may be mixed with plain characters.
+ '0123456789'.delete('67-950-23') # => "4"
+
+ # Ranges may be mixed with negations.
+ 'abracadabra'.delete('^a-c') # => "abacaaba"
+
+- A backslash (<tt>'\'</tt>) acts as an escape for a caret, a hyphen,
+ or another backslash:
+
+ 'abracadabra^'.delete('\^bc') # => "araadara"
+ 'abracadabra-'.delete('a\-d') # => "brcbr"
+ "hello\r\nworld".delete("\r") # => "hello\nworld"
+ "hello\r\nworld".delete("\\r") # => "hello\r\nwold"
+ "hello\r\nworld".delete("\\\r") # => "hello\nworld"
+
+=== Multiple Character Selectors
+
+These instance methods accept multiple character selectors:
+
+- String#count(*selectors): returns the count of the specified characters.
+- String#delete(*selectors): returns a new string.
+- String#delete!(*selectors): returns +self+ or +nil+.
+- String#squeeze(*selectors): returns a new string.
+- String#squeeze!(*selectors): returns +self+ or +nil+.
+
+In effect, the given selectors are formed into a single selector
+consisting of only those characters common to _all_ of the given selectors.
+
+All forms of selectors may be used, including negations, ranges, and escapes.
+
+Each of these pairs of method calls is equivalent:
+
+ s.delete('abcde', 'dcbfg')
+ s.delete('bcd')
+
+ s.delete('^abc', '^def')
+ s.delete('^abcdef')
+
+ s.delete('a-e', 'c-g')
+ s.delete('cde')
diff --git a/doc/command_injection.rdoc b/doc/command_injection.rdoc
new file mode 100644
index 0000000000..af09be23f0
--- /dev/null
+++ b/doc/command_injection.rdoc
@@ -0,0 +1,29 @@
+== Command Injection
+
+Some Ruby core methods accept string data
+that includes text to be executed as a system command.
+
+They should not be called with unknown or unsanitized commands.
+
+These methods include:
+
+- Kernel.system
+- {\`command` (backtick method)}[rdoc-ref:Kernel#`]
+ (also called by the expression <tt>%x[command]</tt>).
+- IO.popen(command).
+- IO.read(command).
+- IO.write(command).
+- IO.binread(command).
+- IO.binwrite(command).
+- IO.readlines(command).
+- IO.foreach(command).
+
+Note that some of these methods do not execute commands when called
+from subclass \File:
+
+- File.read(path).
+- File.write(path).
+- File.binread(path).
+- File.binwrite(path).
+- File.readlines(path).
+- File.foreach(path).
diff --git a/doc/contributing.md b/doc/contributing.md
new file mode 100644
index 0000000000..a6c63de9b2
--- /dev/null
+++ b/doc/contributing.md
@@ -0,0 +1,12 @@
+# Contributing to Ruby
+
+This guide outlines ways to get started with contributing to Ruby:
+
+* [Reporting issues](contributing/reporting_issues.md): How to report issues, how to request features, and how backporting works
+* [Building Ruby](contributing/building_ruby.md): How to build Ruby on your local machine for development
+* [Testing Ruby](contributing/testing_ruby.md): How to test Ruby on your local machine once you've built it
+* [Making changes to Ruby](contributing/making_changes_to_ruby.md): How to submit pull requests
+ to change Ruby's documentation, code, test suite, or standard libraries
+* [Making changes to Ruby standard libraries](contributing/making_changes_to_stdlibs.md): How to build, test, and contribute to Ruby standard libraries
+* [Making changes to Ruby documentation](contributing/documentation_guide.md): How to make changes to Ruby documentation
+* [Benchmarking Ruby](https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark): How to benchmark Ruby
diff --git a/doc/contributing.rdoc b/doc/contributing.rdoc
deleted file mode 100644
index d7395627ca..0000000000
--- a/doc/contributing.rdoc
+++ /dev/null
@@ -1,428 +0,0 @@
-= Contributing to Ruby
-
-Ruby has a vast and friendly community with hundreds of people contributing to
-a thriving open-source ecosystem. This guide is designed to cover ways for
-participating in the development of CRuby.
-
-There are plenty of ways for you to help even if you're not ready to write
-code or documentation. You can help by reporting issues, testing patches, and
-trying out beta releases with your applications.
-
-== How To Report
-
-If you've encountered a bug in Ruby please report it to the redmine issue
-tracker available at {bugs.ruby-lang.org}[https://bugs.ruby-lang.org/]. Do not
-report security vulnerabilities here, there is a {separate
-channel}[rdoc-label:label-Reporting+Security+Issues] for them.
-
-There are a few simple steps you should follow in order to receive feedback
-on your ticket.
-
-* If you haven't already,
- {sign up for an account}[https://bugs.ruby-lang.org/account/register] on the
- bug tracker.
-* Try the latest version.
-
- If you aren't already using the latest version, try installing a newer
- 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-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-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
- (<code>ruby -v</code>).
-* Attach any logs or reproducible programs to provide additional information.
- Reproducible scripts should be as small as possible.
-* Briefly describe your problem. A 2-3 sentence description will help give a
- quick response.
-* Pick a category, such as core for common problems, or lib for a standard
- library.
-* Check the {Maintainers
- list}[https://bugs.ruby-lang.org/projects/ruby/wiki/Maintainers] and assign
- the ticket if there is an active maintainer for the library or feature.
-* If the ticket doesn't have any replies after 10 days, you can send a
- reminder.
-* Please reply to feedback requests. If a bug report doesn't get any feedback,
- it'll eventually get rejected.
-
-=== Reporting to downstream distributions
-
-You can report downstream issues for the following distributions via their bug tracker:
-
-* {debian}[https://bugs.debian.org/cgi-bin/pkgreport.cgi?src=ruby-defaults]
-* {freebsd}[http://www.freebsd.org/cgi/query-pr-summary.cgi?text=ruby]
-* {redhat}[https://bugzilla.redhat.com/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=MODIFIED]
-* {macports}[https://trac.macports.org/query?status=assigned&status=new&status=reopened&port=~ruby]
-* etc (add your distribution bug tracker here)
-
-=== Platform Maintainers
-
-For platform specific bugs in Ruby, you can assign your ticket to the current
-maintainer for a specific platform.
-
-The current active platform maintainers are as follows:
-
-[mswin64 (Microsoft Windows)]
- NAKAMURA Usaku (usa)
-[mingw32 (Minimalist GNU for Windows)]
- Nobuyoshi Nakada (nobu)
-[AIX]
- Yutaka Kanemoto (kanemoto)
-[FreeBSD]
- Akinori MUSHA (knu)
-[Solaris]
- Naohisa Goto (ngoto)
-[RHEL, CentOS]
- KOSAKI Motohiro (kosaki)
-[macOS]
- Kenta Murata (mrkn)
-[OpenBSD]
- Jeremy Evans (jeremyevans0)
-[cygwin, ...]
- none. (Maintainer WANTED)
-
-== Reporting Security Issues
-
-Security vulnerabilities receive special treatment since they may negatively
-affect many users. There is a private mailing list that all security issues
-should be reported to and will be handled discretely. Email the
-mailto:security@ruby-lang.org list and the problem will be published after
-fixes have been released. You can also encrypt the issue using {the PGP public
-key}[https://www.ruby-lang.org/security.asc] for the list.
-
-== Reporting Other Issues
-
-If you're having an issue with the website, or maybe the mailing list, you can
-contact the webmaster to help resolve the problem.
-
-The current webmaster is:
-
-* Hiroshi SHIBATA (hsbt)
-
-You can also report issues with the ruby-lang.org website on the issue tracker:
-
-* {issue tracker}[https://github.com/ruby/www.ruby-lang.org/issues]
-
-== Resolve Existing Issues
-
-As a next step beyond reporting issues you can help the core team resolve
-existing issues. If you check the Everyone's Issues list in GitHub Issues,
-you will find a lot of issues already requiring attention. What can you do for
-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-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
-issue on your own and comment if you still experience the bug. Some issues
-lack attention because of too much ambiguity, to help you can narrow down the
-problem and provide more specific details or instructions to reproduce the
-bug. You might also try contributing a failing test in the form of a patch,
-which we will cover later in this guide.
-
-It may also help to try out patches other contributors have submitted to
-redmine, if gone without notice. In this case the +patch+ command is your
-friend, see <code>man patch</code> for more information. Basically this would
-go something like this:
-
- cd path/to/ruby
- patch -p0 < path/to/patch
-
-You will then be prompted to apply the patch with the associated files. After
-building ruby again, you should try to run the tests and verify if the change
-actually worked or fixed the bug. It's important to provide valuable feedback
-on the patch that can help reach the overall goal, try to answer some of these
-questions:
-
-* What do you like about this change?
-* What would you do differently?
-* Are there any other edge cases not tested?
-* Is there any documentation that would be affected by this change?
-
-If you can answer some or all of these questions, you're on the right track.
-If your comment simply says "+1", then odds are that other reviewers aren't
-going to take it too seriously. Show that you took the time to review the
-patch.
-
-== How To Request Features
-
-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-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].
-
-When writing a proposal be sure to check for previous discussions on the
-topic and have a solid use case. You will need to be persuasive and convince
-Matz on your new feature. You should also consider the potential compatibility
-issues that this new feature might raise.
-
-Consider making your feature into a gem, and if there are enough people who
-benefit from your feature it could help persuade ruby-core. Although feature
-requests can seem like an alluring way to contribute to Ruby, often these
-discussions can lead nowhere and exhaust time and energy that could be better
-spent fixing bugs. Choose your battles.
-
-A good template for a feature proposal should look something like this:
-
-[Abstract]
- Summary of your feature
-[Background]
- Describe current behavior and why it is problem. Related work, such as
- solutions in other language helps us to understand the problem.
-[Proposal]
- Describe your proposal in details
-[Details]
- If it has complicated feature, describe it
-[Usecase]
- How would your feature be used? Who will benefit from it?
-[Discussion]
- Discuss about this proposal. A list of pros and cons will help start
- discussion.
-[Limitation]
- Limitation of your proposal
-[Another alternative proposal]
- If there are alternative proposals, show them.
-[See also]
- Links to the other related resources
-
-== Backport Requests
-
-When a new version of Ruby is released, it starts at patch level 0 (p0), and
-bugs will be fixed first on the master branch. If it's determined that a bug
-exists in a previous version of Ruby that is still in the bug fix stage of
-maintenance, then a patch will be backported. After the maintenance stage of a
-particular Ruby version ends, it goes into "security fix only" mode which
-means only security related vulnerabilities will be backported. Versions in
-End-of-life (EOL) will not receive any updates and it is recommended you
-upgrade as soon as possible.
-
-If a major security issue is found or after a certain amount of time since the
-last patch level release, a new patch-level release will be made.
-
-When submitting a backport request please confirm the bug has been fixed in
-newer versions and exists in maintenance mode versions. There is a backport
-tracker for each major version still in maintenance where you can request a
-particular revision merged in the affected version of Ruby.
-
-Each major version of Ruby has a release manager that should be assigned to
-handle backport requests. You can find the list of release managers on the
-{wiki}[https://bugs.ruby-lang.org/projects/ruby/wiki/ReleaseEngineering].
-
-=== Branches
-
-Status and maintainers of branches are listed on the
-{wiki}[https://bugs.ruby-lang.org/projects/ruby/wiki/ReleaseEngineering].
-
-== Running tests
-
-In order to help resolve existing issues and contributing patches to Ruby you
-need to be able to run the test suite.
-
-CRuby uses git for source control, the {git homepage}[https://git-scm.com/]
-has installation instructions with links to documentation for learning more
-about git. There is a mirror of the repository on {github}[https://github.com/ruby/ruby].
-For other resources see the {ruby-core documentation on
-ruby-lang.org}[https://www.ruby-lang.org/en/community/ruby-core/].
-
-Install the prerequisite dependencies for building the CRuby interpreter to
-run tests.
-
-* C compiler
-* 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.
- 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:
-
-* NDBM/QDBM
-* GDBM
-* OpenSSL/LibreSSL
-* readline/editline(libedit)
-* zlib
-* libffi
-* libyaml
-* libexecinfo (FreeBSD)
-
-Now let's build CRuby:
-
-* Checkout the CRuby source code:
-
- git clone https://github.com/ruby/ruby.git ruby-master
-
-* Generate the configuration files and build:
-
- cd ruby-master
- autoconf
- mkdir build && cd build # its good practice to build outside of source dir
- mkdir ~/.rubies # we will install to .rubies/ruby-master in our home dir
- ../configure --prefix="${HOME}/.rubies/ruby-master"
- make up && make install
-
-After adding Ruby to your PATH, you should be ready to run the test suite:
-
- make test
-
-You can also use +test-all+ to run all of the tests with the RUNRUBY
-interpreter just built. Use TESTS or RUNRUBYOPT to pass parameters, such as:
-
- make test-all TESTS=-v
-
-This is also how you can run a specific test from our build dir:
-
- make test-all TESTS=drb/test_drb.rb
-
-You can run +test+ and +test-all+ at once by +check+ .
-
- make check
-
-For older versions of Ruby you will need to run the build setup again after
-checking out the associated branch in git, for example if you wanted to
-checkout 1.9.3:
-
- git clone https://github.com/ruby/ruby.git --branch ruby_1_9_3
-
-Once you checked out the source code, you can update the local copy by:
-
- make up
-
-Or, update, build, install and check, by just:
-
- make love
-
-== Contributing Documentation
-
-If you're interested in contributing documentation directly to CRuby there is
-some information available at
-{Contributing}[https://github.com/ruby/ruby#contributing].
-
-There is also the {Ruby Reference
-Manual}[https://github.com/rurema/doctree/wiki] in Japanese.
-
-== Contributing A Patch
-
-=== Deciding what to patch
-
-Before you submit a patch, there are a few things you should know:
-
-* Pay attention to the maintenance policy for stable and maintained versions of Ruby.
-* Released versions in security mode will not merge feature changes.
-* Search for previous discussions on ruby-core to verify the maintenance policy
-* Patches must be distributed under Ruby's license.
-* This license may change in the future, you must join the discussion if you don't agree to the change
-
-To improve the chance your patch will be accepted please follow these simple rules:
-
-* Bug fixes should be committed on master first
-* Format of the patch file must be a unified diff (ie: diff -pu, svn diff, or git diff)
-* Don't introduce cosmetic changes
-* Follow the original coding style of the code
-* Don't mix different changes in one commit
-
-First thing you should do is check out the code if you haven't already:
-
- git clone https://github.com/ruby/ruby.git ruby-master
-
-Now create a dedicated branch:
-
- cd ruby-master
- git checkout -b my_new_branch
-
-The name of your branch doesn't really matter because it will only exist on
-your local computer and won't be part of the official Ruby repository. It will
-be used to create patches based on the differences between your branch and
-master, or edge Ruby.
-
-=== Coding style
-
-Here are some general rules to follow when writing Ruby and C code for CRuby:
-
-* Indent 4 spaces for C without tabs (old codes might use tabs for eight-space indentation,
- but newer codes recommend to use spaces only)
-* Indent 2 space tabs for Ruby
-* Do not use TABs in ruby codes
-* ANSI C style for 1.9+ for function declarations
-* Follow C90 (not C99) Standard
-* PascalStyle for class/module names.
-* UNDERSCORE_SEPARATED_UPPER_CASE for other constants.
-* Capitalize words.
-* ABBRs should be all upper case.
-* Do as others do
-
-=== Commit messages
-
-When you're ready to commit:
-
- git commit path/to/files
-
-This will open your editor in which you write your commit message.
-Use the following style for commit messages:
-
-* Use a succinct subject line.
-* Include reasoning behind the change in the commit message, focusing on why
- the change is being made.
-* Refer to redmine issue (such as Fixes [Bug #1234] or Implements
- [Feature #3456]), or discussion on the mailing list
- (such as [ruby-core:12345]).
-* For GitHub issues, use [GH-#] (such as [Fixes GH-234]).
-* Follow the style used by other committers.
-
-=== Contributing your code
-
-Now that you've got some code you want to contribute, let's get set up to
-generate a patch. Start by forking the github mirror, check the {github docs on
-forking}[https://help.github.com/articles/fork-a-repo] if you get stuck here.
-You will only need a github account if you intend to host your repository
-on github.
-
-Next copy the writable url for your fork and add it as a git remote, replace
-"my_username" with your github account name:
-
- git remote add my_fork git@github.com:my_username/ruby.git
- # Now we can push our branch to our fork
- git push my_fork my_new_branch
-
-In order to generate a patch that you can upload to the bug tracker, we can use
-the github interface to review our changes just visit
-https://github.com/my_username/ruby/compare/master...my_new_branch
-
-Next, you can simply add '.patch' to the end of this URL and it will generate
-the patch for you, save the file to your computer and upload it to the bug
-tracker. Alternatively you can submit a pull request, but for the best chances
-to receive feedback add it is recommended you add it to redmine.
-
-Since git is a distributed system, you are welcome to host your git repository
-on any {publicly accessible hosting
-site}[https://git.wiki.kernel.org/index.php/GitHosting], including {hosting your
-own}[https://www.kernel.org/pub/software/scm/git/docs/user-manual.html#public-repositories]
-You may use the {'git format-patch'}[https://git-scm.com/docs/git-format-patch]
-command to generate patch files to upload to redmine. You may also use
-the {'git request-pull'}[https://git-scm.com/docs/git-request-pull] command for
-formatting pull request messages to redmine.
-
-=== Updating the official repository
-
-If you are a committer, you can push changes directly into the official
-repository:
-
- git push origin your-branch-name:master
-
-However, it is likely will have become outdated, and you will have to
-update it. In that case, run:
-
- git fetch origin
- git rebase remotes/origin/master
-
-and then try pushing your changes again.
diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md
new file mode 100644
index 0000000000..469c9d8361
--- /dev/null
+++ b/doc/contributing/building_ruby.md
@@ -0,0 +1,172 @@
+# Building Ruby
+
+## Quick start guide
+
+1. Install the prerequisite dependencies for building the CRuby interpreter:
+
+ * C compiler
+ * autoconf - 2.67 or later
+ * bison - 3.0 or later
+ * gperf - 3.0.3 or later
+ * ruby - 2.7 or later
+
+2. Install optional, recommended dependencies:
+
+ * OpenSSL/LibreSSL
+ * readline/editline (libedit)
+ * zlib
+ * libffi
+ * libyaml
+ * libexecinfo (FreeBSD)
+ * rustc - 1.58.0 or later (if you wish to build [YJIT](/doc/yjit/yjit.md))
+
+3. Checkout the CRuby source code:
+
+ ```
+ git clone https://github.com/ruby/ruby.git
+ ```
+
+4. Generate the configure file:
+
+ ```
+ ./autogen.sh
+ ```
+
+5. Create a `build` directory outside of the source directory:
+
+ ```
+ mkdir build && cd build
+ ```
+
+ While it's not necessary to build in a separate directory, it's good practice to do so.
+
+6. We'll install Ruby in `~/.rubies/ruby-master`, so create the directory:
+
+ ```
+ mkdir ~/.rubies
+ ```
+
+7. Run configure:
+
+ ```
+ ../configure --prefix="${HOME}/.rubies/ruby-master"
+ ```
+
+ - If you are frequently building Ruby, add the `--disable-install-doc` flag to not build documentation which will speed up the build process.
+
+8. Build Ruby:
+
+ ```
+ make install
+ ```
+
+ - If you're on macOS and installed \OpenSSL through Homebrew, you may encounter failure to build \OpenSSL that look like this:
+
+ ```
+ openssl:
+ Could not be configured. It will not be installed.
+ ruby/ext/openssl/extconf.rb: OpenSSL library could not be found. You might want to use --with-openssl-dir=<dir> option to specify the prefix where OpenSSL is installed.
+ Check ext/openssl/mkmf.log for more details.
+ ```
+
+ Adding `--with-openssl-dir=$(brew --prefix openssl)` to the list of options passed to configure may solve the issue.
+
+ Remember to delete your `build` directory and start again from the configure step.
+
+9. [Run tests](testing_ruby.md) to confirm your build succeeded.
+
+### Unexplainable Build Errors
+
+If you are having unexplainable build errors, after saving all your work, try running `git clean -xfd` in the source root to remove all git ignored local files. If you are working from a source directory that's been updated several times, you may have temporary build artifacts from previous releases which can cause build failures.
+
+## More details
+
+If you're interested in continuing development on Ruby, here are more details
+about Ruby's build to help out.
+
+### Running make scripts in parallel
+
+In GNU make and BSD make implementations, to run a specific make script in parallel, pass the flag `-j<number of processes>`. For instance,
+to run tests on 8 processes, use:
+
+```
+make test-all -j8
+```
+
+We can also set `MAKEFLAGS` to run _all_ `make` commands in parallel.
+
+Having the right `--jobs` flag will ensure all processors are utilized when building software projects. To do this effectively, you can set `MAKEFLAGS` in your shell configuration/profile:
+
+``` shell
+# On macOS with Fish shell:
+export MAKEFLAGS="--jobs "(sysctl -n hw.ncpu)
+
+# On macOS with Bash/ZSH shell:
+export MAKEFLAGS="--jobs $(sysctl -n hw.ncpu)"
+
+# On Linux with Fish shell:
+export MAKEFLAGS="--jobs "(nproc)
+
+# On Linux with Bash/ZSH shell:
+export MAKEFLAGS="--jobs $(nproc)"
+```
+
+### Miniruby vs Ruby
+
+Miniruby is a version of Ruby which has no external dependencies and lacks certain features.
+It can be useful in Ruby development because it allows for faster build times. Miniruby is
+built before Ruby. A functional Miniruby is required to build Ruby. To build Miniruby:
+
+```
+make miniruby
+```
+
+## Debugging
+
+You can use either lldb or gdb for debugging. Before debugging, you need to create a `test.rb`
+with the Ruby script you'd like to run. You can use the following make targets:
+
+* `make run`: Runs `test.rb` using Miniruby
+* `make lldb`: Runs `test.rb` using Miniruby in lldb
+* `make gdb`: Runs `test.rb` using Miniruby in gdb
+* `make runruby`: Runs `test.rb` using Ruby
+* `make lldb-ruby`: Runs `test.rb` using Ruby in lldb
+* `make gdb-ruby`: Runs `test.rb` using Ruby in gdb
+
+### Building with Address Sanitizer
+
+Using the address sanitizer is a great way to detect memory issues.
+
+``` shell
+./autogen.sh
+mkdir build && cd build
+export ASAN_OPTIONS="halt_on_error=0:use_sigaltstack=0:detect_leaks=0"
+../configure cppflags="-fsanitize=address -fno-omit-frame-pointer" optflags=-O0 LDFLAGS="-fsanitize=address -fno-omit-frame-pointer"
+make
+```
+
+On Linux it is important to specify `-O0` when debugging. This is especially true for ASAN which sometimes works incorrectly at higher optimisation levels.
+
+## How to measure coverage of C and Ruby code
+
+You need to be able to use gcc (gcov) and lcov visualizer.
+
+```
+./autogen.sh
+./configure --enable-gcov
+make
+make update-coverage
+rm -f test-coverage.dat
+make test-all COVERAGE=true
+make lcov
+open lcov-out/index.html
+```
+
+If you need only C code coverage, you can remove `COVERAGE=true` from the above process.
+You can also use `gcov` command directly to get per-file coverage.
+
+If you need only Ruby code coverage, you can remove `--enable-gcov`.
+Note that `test-coverage.dat` accumulates all runs of `make test-all`.
+Make sure that you remove the file if you want to measure one test run.
+
+You can see the coverage result of CI: https://rubyci.org/coverage
diff --git a/doc/contributing/documentation_guide.md b/doc/contributing/documentation_guide.md
new file mode 100644
index 0000000000..9cfd59d629
--- /dev/null
+++ b/doc/contributing/documentation_guide.md
@@ -0,0 +1,435 @@
+# Documentation Guide
+
+This guide discusses recommendations for documenting
+classes, modules, and methods
+in the Ruby core and in the Ruby standard library.
+
+## Generating documentation
+
+Most Ruby documentation lives in the source files and is written in
+[RDoc format](rdoc-ref:RDoc::Markup).
+
+Some pages live under the `doc` folder and can be written in either
+`.rdoc` or `.md` format, determined by the file extension.
+
+To generate the output of documentation changes in HTML in the
+`{build folder}/.ext/html` directory, run the following inside your
+build directory:
+
+```sh
+make html
+```
+
+Then you can preview your changes by opening
+`{build folder}/.ext/html/index.html` file in your browser.
+
+
+## Goal
+
+The goal of Ruby documentation is to impart the most important
+and relevant in the shortest time.
+The reader should be able to quickly understand the usefulness
+of the subject code and how to use it.
+
+Providing too little information is bad, but providing unimportant
+information or unnecessary examples is not good either.
+Use your judgment about what the user needs to know.
+
+## General Guidelines
+
+- Keep in mind that the reader may not be fluent in \English.
+- Write short declarative or imperative sentences.
+- Group sentences into (ideally short) paragraphs,
+ each covering a single topic.
+- Organize material with [headers](rdoc-ref:RDoc::Markup@Headers).
+- Refer to authoritative and relevant sources using
+ [links](rdoc-ref:RDoc::Markup@Links).
+- Use simple verb tenses: simple present, simple past, simple future.
+- Use simple sentence structure, not compound or complex structure.
+- Avoid:
+ - Excessive comma-separated phrases;
+ consider a [list](rdoc-ref:RDoc::Markup@Simple+Lists).
+ - Idioms and culture-specific references.
+ - Overuse of headers.
+ - Using US-ASCII-incompatible characters in C source files;
+ see [Characters](#label-Characters) below.
+
+### Characters
+
+Use only US-ASCII-compatible characters in a C source file.
+(If you use other characters, the Ruby CI will gently let you know.)
+
+If want to put ASCII-incompatible characters into the documentation
+for a C-coded class, module, or method, there are workarounds
+involving new files `doc/*.rdoc`:
+
+- For class `Foo` (defined in file `foo.c`),
+ create file `doc/foo.rdoc`, declare `class Foo; end`,
+ and place the class documentation above that declaration:
+
+ ```ruby
+ # Documentation for class Foo goes here.
+ class Foo; end
+ ```
+
+- Similarly, for module `Bar` (defined in file `bar.c`,
+ create file `doc/bar.rdoc`, declare `module Bar; end`,
+ and place the module documentation above that declaration:
+
+ ```ruby
+ # Documentation for module Bar goes here.
+ module Bar; end
+ ```
+
+- For a method, things are different.
+ Documenting a method as above disables the "click to toggle source" feature
+ in the rendered documentation.
+
+ Therefore it's best to use file inclusion:
+
+ - Retain the `call-seq` in the C code.
+ - Use file inclusion (`:include:`) to include text from an .rdoc file.
+
+ Example:
+
+ ```
+ /*
+ * call-seq:
+ * each_byte {|byte| ... } -> self
+ * each_byte -> enumerator
+ *
+ * :include: doc/string/each_byte.rdoc
+ *
+ */
+ ```
+
+### \RDoc
+
+Ruby is documented using RDoc.
+For information on \RDoc syntax and features, see the
+[RDoc Markup Reference](rdoc-ref:RDoc::Markup@RDoc+Markup+Reference).
+
+### Output from `irb`
+
+For code examples, consider using interactive Ruby,
+[irb](https://ruby-doc.org/stdlib/libdoc/irb/rdoc/IRB.html).
+
+For a code example that includes `irb` output,
+consider aligning `# => ...` in successive lines.
+Alignment may sometimes aid readability:
+
+```ruby
+a = [1, 2, 3] #=> [1, 2, 3]
+a.shuffle! #=> [2, 3, 1]
+a #=> [2, 3, 1]
+```
+
+### Headers
+
+Organize a long discussion with [headers](rdoc-ref:RDoc::Markup@Headers).
+
+### Blank Lines
+
+A blank line begins a new paragraph.
+
+A [code block](rdoc-ref:RDoc::Markup@Paragraphs+and+Verbatim)
+or [list](rdoc-ref:RDoc::Markup@Simple+Lists)
+should be preceded by and followed by a blank line.
+This is unnecessary for the HTML output, but helps in the `ri` output.
+
+### \Method Names
+
+For a method name in text:
+
+- For a method in the current class or module,
+ use a double-colon for a singleton method,
+ or a hash mark for an instance method:
+ <tt>::bar</tt>, <tt>#baz</tt>.
+- Otherwise, include the class or module name
+ and use a dot for a singleton method,
+ or a hash mark for an instance method:
+ <tt>Foo.bar</tt>, <tt>Foo#baz</tt>.
+
+### Auto-Linking
+
+In general, \RDoc's auto-linking should not be suppressed.
+For example, we should write `Array`, not `\Array`.
+
+We might consider whether to suppress when:
+
+- The word in question does not refer to a Ruby entity
+ (e.g., some uses of _Class_ or _English_).
+- The reference is to the current class document
+ (e.g., _Array_ in the documentation for class `Array`).
+- The same reference is repeated many times
+ (e.g., _RDoc_ on this page).
+
+### HTML Tags
+
+In general, avoid using HTML tags (even in formats where it's allowed)
+because `ri` (the Ruby Interactive reference tool)
+may not render them properly.
+
+### Tables
+
+In particular, avoid building tables with HTML tags
+(<tt><table></tt>, etc.).
+
+Alternatives are:
+
+- The GFM (GitHub Flavored Markdown) table extension,
+ which is enabled by default. See
+ {GFM tables extension}[https://github.github.com/gfm/#tables-extension-].
+
+- A {verbatim text block}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks],
+ using spaces and punctuation to format the text.
+ Note that {text markup}[rdoc-ref:RDoc::MarkupReference@Text+Markup]
+ will not be honored.
+
+## Documenting Classes and Modules
+
+The general structure of the class or module documentation should be:
+
+- Synopsis
+- Common uses, with examples
+- "What's Here" summary (optional)
+
+### Synopsis
+
+The synopsis is a short description of what the class or module does
+and why the reader might want to use it.
+Avoid details in the synopsis.
+
+### Common Uses
+
+Show common uses of the class or module.
+Depending on the class or module, this section may vary greatly
+in both length and complexity.
+
+### What's Here Summary
+
+The documentation for a class or module may include a "What's Here" section.
+
+Guidelines:
+
+- The section title is `What's Here`.
+- Consider listing the parent class and any included modules; consider
+ [links](rdoc-ref:RDoc::Markup@Links)
+ to their "What's Here" sections if those exist.
+- List methods as a bullet list:
+
+ - Begin each item with the method name, followed by a colon
+ and a short description.
+ - If the method has aliases, mention them in parentheses before the colon
+ (and do not list the aliases separately).
+ - Check the rendered documentation to determine whether \RDoc has recognized
+ the method and linked to it; if not, manually insert a
+ [link](rdoc-ref:RDoc::Markup@Links).
+
+- If there are numerous entries, consider grouping them into subsections with headers.
+- If there are more than a few such subsections,
+ consider adding a table of contents just below the main section title.
+
+## Documenting Methods
+
+### General Structure
+
+The general structure of the method documentation should be:
+
+- Calling sequence (for methods written in C).
+- Synopsis (short description).
+- Details and examples.
+- Argument description (if necessary).
+- Corner cases and exceptions.
+- Aliases.
+- Related methods (optional).
+
+### Calling Sequence (for methods written in C)
+
+For methods written in Ruby, \RDoc documents the calling sequence automatically.
+
+For methods written in C, \RDoc cannot determine what arguments
+the method accepts, so those need to be documented using \RDoc directive
+[`call-seq:`](rdoc-ref:RDoc::Markup@Method+arguments).
+
+For a singleton method, use the form:
+
+```
+class_name.method_name(method_args) {|block_args| ... } -> return_type
+```
+
+Example:
+
+```
+* call-seq:
+* Hash.new(default_value = nil) -> new_hash
+* Hash.new {|hash, key| ... } -> new_hash
+```
+
+For an instance method, use the form
+(omitting any prefix, just as RDoc does for a Ruby-coded method):
+
+```
+method_name(method_args) {|block_args| ... } -> return_type
+```
+For example, in Array, use:
+
+```
+* call-seq:
+* count -> integer
+* count(obj) -> integer
+* count {|element| ... } -> integer
+```
+
+```
+* call-seq:
+* <=> other -> -1, 0, 1, or nil
+```
+
+Arguments:
+
+- If the method does not accept arguments, omit the parentheses.
+- If the method accepts optional arguments:
+
+ - Separate each argument name and its default value with ` = `
+ (equal-sign with surrounding spaces).
+ - If the method has the same behavior with either an omitted
+ or an explicit argument, use a `call-seq` with optional arguments.
+ For example, use:
+
+ ```
+ respond_to?(symbol, include_all = false) -> true or false
+ ```
+
+ - If the behavior is different with an omitted or an explicit argument,
+ use a `call-seq` with separate lines.
+ For example, in Enumerable, use:
+
+ ```
+ * max -> element
+ * max(n) -> array
+ ```
+
+Block:
+
+- If the method does not accept a block, omit the block.
+- If the method accepts a block, the `call-seq` should have `{|args| ... }`,
+ not `{|args| block }` or `{|args| code }`.
+
+Return types:
+
+- If the method can return multiple different types,
+ separate the types with "or" and, if necessary, commas.
+- If the method can return multiple types, use +object+.
+- If the method returns the receiver, use +self+.
+- If the method returns an object of the same class,
+ prefix `new_` if an only if the object is not +self+;
+ example: `new_array`.
+
+Aliases:
+
+- Omit aliases from the `call-seq`, but mention them near the end (see below).
+
+### Synopsis
+
+The synopsis comes next, and is a short description of what the
+method does and why you would want to use it. Ideally, this
+is a single sentence, but for more complex methods it may require
+an entire paragraph.
+
+For `Array#count`, the synopsis is:
+
+```
+Returns a count of specified elements.
+```
+
+This is great as it is short and descriptive. Avoid documenting
+too much in the synopsis, stick to the most important information
+for the benefit of the reader.
+
+### Details and Examples
+
+Most non-trivial methods benefit from examples, as well as details
+beyond what is given in the synopsis. In the details and examples
+section, you can document how the method handles different types
+of arguments, and provides examples on proper usage. In this
+section, focus on how to use the method properly, not on how the
+method handles improper arguments or corner cases.
+
+Not every behavior of a method requires an example. If the method
+is documented to return `self`, you don't need to provide an example
+showing the return value is the same as the receiver. If the method
+is documented to return `nil`, you don't need to provide an example
+showing that it returns `nil`. If the details mention that for a
+certain argument type, an empty array is returned, you don't need
+to provide an example for that.
+
+Only add an example if it provides the user additional information,
+do not add an example if it provides the same information given
+in the synopsis or details. The purpose of examples is not to prove
+what the details are stating.
+
+### Argument Description (if necessary)
+
+For methods that require arguments, if not obvious and not explicitly
+mentioned in the details or implicitly shown in the examples, you can
+provide details about the types of arguments supported. When discussing
+the types of arguments, use simple language even if less-precise, such
+as "level must be an integer", not "level must be an Integer-convertible
+object". The vast majority of use will be with the expected type, not an
+argument that is explicitly convertible to the expected type, and
+documenting the difference is not important.
+
+For methods that take blocks, it can be useful to document the type of
+argument passed if it is not obvious, not explicitly mentioned in the
+details, and not implicitly shown in the examples.
+
+If there is more than one argument or block argument, use a
+[labeled list](rdoc-ref:RDoc::Markup@Labeled+Lists).
+
+### Corner Cases and Exceptions
+
+For corner cases of methods, such as atypical usage, briefly mention
+the behavior, but do not provide any examples.
+
+Only document exceptions raised if they are not obvious. For example,
+if you have stated earlier than an argument type must be an integer,
+you do not need to document that a `TypeError` is raised if a non-integer
+is passed. Do not provide examples of exceptions being raised unless
+that is a common case, such as `Hash#fetch` raising a `KeyError`.
+
+### Aliases
+
+Mention aliases in the form
+
+```
+// Array#find_index is an alias for Array#index.
+```
+
+### Related Methods (optional)
+
+In some cases, it is useful to document which methods are related to
+the current method. For example, documentation for `Hash#[]` might
+mention `Hash#fetch` as a related method, and `Hash#merge` might mention
+`Hash#merge!` as a related method.
+
+- Consider which methods may be related
+ to the current method, and if you think the reader would benefit it,
+ at the end of the method documentation, add a line starting with
+ "Related: " (e.g. "Related: #fetch.").
+- Don't list more than three related methods.
+ If you think more than three methods are related,
+ list the three you think are most important.
+- Consider adding:
+
+ - A phrase suggesting how the related method is similar to,
+ or different from,the current method.
+ See an example at Time#getutc.
+ - Example code that illustrates the similarities and differences.
+ See examples at Time#ctime, Time#inspect, Time#to_s.
+
+### Methods Accepting Multiple Argument Types
+
+For methods that accept multiple argument types, in some cases it can
+be useful to document the different argument types separately. It's
+best to use a separate paragraph for each case you are discussing.
diff --git a/doc/contributing/making_changes_to_ruby.md b/doc/contributing/making_changes_to_ruby.md
new file mode 100644
index 0000000000..260fadb7e3
--- /dev/null
+++ b/doc/contributing/making_changes_to_ruby.md
@@ -0,0 +1,28 @@
+# Contributing a pull request
+
+## Code style
+
+Here are some general rules to follow when writing Ruby and C code for CRuby:
+
+* Do not change code unrelated to your pull request (including style fixes)
+* Indent 4 spaces for C without tabs (tabs are two levels of indentation, equivalent to 8 spaces)
+* Indent 2 spaces for Ruby without tabs
+* ANSI C style for function declarations
+* Follow C99 Standard
+* PascalStyle for class/module names
+* UNDERSCORE_SEPARATED_UPPER_CASE for other constants
+* Abbreviations should be all upper case
+
+## Commit messages
+
+Use the following style for commit messages:
+
+* Use a succinct subject line
+* Include reasoning behind the change in the commit message, focusing on why the change is being made
+* Refer to issue (such as `Fixes [Bug #1234]` or `Implements [Feature #3456]`), or discussion on the mailing list (such as [ruby-core:12345])
+
+## CI
+
+GitHub actions will run on each pull request.
+
+There is [a CI that runs on master](https://rubyci.org/). It has broad coverage of different systems and architectures, such as Solaris SPARC and macOS.
diff --git a/doc/contributing/making_changes_to_stdlibs.md b/doc/contributing/making_changes_to_stdlibs.md
new file mode 100644
index 0000000000..ef3811ea12
--- /dev/null
+++ b/doc/contributing/making_changes_to_stdlibs.md
@@ -0,0 +1,49 @@
+# Making Changes To Standard Libraries
+
+Everything in the [lib](https://github.com/ruby/ruby/tree/master/lib) directory is mirrored from a standalone repository into the Ruby repository.
+If you'd like to make contributions to standard libraries, do so in the standalone repositories, and the
+changes will be automatically mirrored into the Ruby repository.
+
+For example, CSV lives in [a separate repository](https://github.com/ruby/csv) and is mirrored into [Ruby](https://github.com/ruby/ruby/tree/master/lib/csv).
+
+## Maintainers
+
+You can find the list of maintainers [here](https://docs.ruby-lang.org/en/master/maintainers_rdoc.html#label-Maintainers).
+
+## Build
+
+First, install its dependencies using:
+
+```
+bundle install
+```
+
+### Libraries with C-extension
+
+If the library has a `/ext` directory, it has C files that you need to compile with:
+
+```
+bundle exec rake compile
+```
+
+## Running tests
+
+All standard libraries use [test-unit](https://github.com/test-unit/test-unit) as the test framework.
+
+To run all tests:
+
+```
+bundle exec rake test
+```
+
+To run a single test file:
+
+```
+bundle exec rake test TEST="test/test_foo.rb"
+```
+
+To run a single test case:
+
+```
+bundle exec rake test TEST="test/test_foo.rb" TESTOPS="--name=/test_mytest/"
+```
diff --git a/doc/contributing/reporting_issues.md b/doc/contributing/reporting_issues.md
new file mode 100644
index 0000000000..25516ffc6b
--- /dev/null
+++ b/doc/contributing/reporting_issues.md
@@ -0,0 +1,91 @@
+# Reporting Issues
+## Reporting security issues
+
+If you've found a security vulnerability, please follow
+[these instructions](https://www.ruby-lang.org/en/security/).
+
+## Reporting bugs
+
+If you've encountered a bug in Ruby, please report it to the Redmine issue
+tracker available at [bugs.ruby-lang.org](https://bugs.ruby-lang.org/), by
+following these steps:
+
+* Check if anyone has already reported your issue by
+ searching [the Redmine issue tracker](https://bugs.ruby-lang.org/projects/ruby-master/issues).
+* If you haven't already,
+ [sign up for an account](https://bugs.ruby-lang.org/account/register) on the
+ Redmine issue tracker.
+* If you can't find a ticket addressing your issue, please [create a new issue](https://bugs.ruby-lang.org/projects/ruby-master/issues/new). You will need to fill in the subject, description and Ruby version.
+
+ * Ensure the issue exists on Ruby master by trying to replicate your bug on
+ the head of master (see ["making changes to Ruby"](making_changes_to_ruby.md)).
+ * Write a concise subject and briefly describe your problem in the description section. If
+ your issue affects [a released version of Ruby](#label-Backport+requests), please say so.
+ * Fill in the Ruby version you're using when experiencing this issue
+ (the output of running `ruby -v`).
+ * Attach any logs or reproducible programs to provide additional information.
+ Any scripts should be as small as possible.
+* If the ticket doesn't have any replies after 10 days, you can send a
+ reminder.
+* Please reply to feedback requests. If a bug report doesn't get any feedback,
+ it'll eventually get rejected.
+
+### Reporting website issues
+
+If you're having an issue with the bug tracker or the mailing list, you can
+contact the webmaster, Hiroshi SHIBATA (hsbt@ruby-lang.org).
+
+You can report issues with ruby-lang.org on the
+[repo's issue tracker](https://github.com/ruby/www.ruby-lang.org/issues).
+
+## Requesting features
+
+If there's a new feature that you want to see added to Ruby, you will need to
+write a proposal on [the Redmine issue tracker](https://bugs.ruby-lang.org/projects/ruby-master/issues/new).
+When you open the issue, select `Feature` in the Tracker dropdown.
+
+When writing a proposal, be sure to check for previous discussions on the
+topic and have a solid use case. You should also consider the potential
+compatibility issues that this new feature might raise. Consider making
+your feature into a gem, and if there are enough people who benefit from
+your feature it could help persuade Ruby core.
+
+Here is a template you can use for a feature proposal:
+
+```
+[Abstract]
+ Briefly summarize your feature
+[Background]
+ Describe current behavior
+[Proposal]
+ Describe your feature in detail
+[Use cases]
+ Give specific example uses of your feature
+[Discussion]
+ Describe why this feature is necessary and better than using existing features
+[See also]
+ Link to other related resources (such as implementations in other languages)
+```
+
+## Backport requests
+
+If a bug exists in a released version of Ruby, please report this in the issue.
+Once this bug is fixed, the fix can be backported if deemed necessary. Only Ruby
+committers can request backporting, and backporting is done by the backport manager.
+New patch versions are released at the discretion of the backport manager.
+
+[Ruby versions](https://www.ruby-lang.org/en/downloads/) can be in one of three maintenance states:
+
+* Stable releases: backport any bug fixes
+* Security maintenance: only backport security fixes
+* End of life: no backports, please upgrade your Ruby version
+
+## Add context to existing issues
+
+There are several ways you can help with a bug that aren't directly
+resolving it. These include:
+
+* Verifying or reproducing the existing issue and reporting it
+* Adding more specific reproduction instructions
+* Contributing a failing test as a patch (see ["making changes to Ruby"](making_changes_to_ruby.md))
+* Testing patches that others have submitted (see ["making changes to Ruby"](making_changes_to_ruby.md))
diff --git a/doc/contributing/testing_ruby.md b/doc/contributing/testing_ruby.md
new file mode 100644
index 0000000000..6247686efc
--- /dev/null
+++ b/doc/contributing/testing_ruby.md
@@ -0,0 +1,138 @@
+# Testing Ruby
+
+## Test suites
+
+There are several test suites in the Ruby codebase:
+
+We can run any of the make scripts [in parallel](building_ruby.md#label-Running+make+scripts+in+parallel) to speed them up.
+
+1. [bootstraptest/](https://github.com/ruby/ruby/tree/master/bootstraptest)
+
+ This is a small test suite that runs on Miniruby (see [building Ruby](building_ruby.md#label-Miniruby+vs+Ruby)). We can run it with:
+
+ ```
+ make btest
+ ```
+
+ To run it with logs, we can use:
+
+ ```
+ make btest OPTS=-v
+ ```
+
+ To run individual bootstrap tests, we can either specify a list of filenames or use the `--sets` flag in the variable `BTESTS`:
+
+ ```
+ make btest BTESTS="bootstraptest/test_fork.rb bootstraptest/tes_gc.rb"
+ make btest BTESTS="--sets=fork,gc"
+ ```
+
+ If we want to run the bootstrap test suite on Ruby (not Miniruby), we can use:
+
+ ```
+ make test
+ ```
+
+ To run it with logs, we can use:
+
+ ```
+ make test OPTS=-v
+ ```
+
+ To run a file or directory with GNU make, we can use:
+
+ ```
+ make test/ruby/test_foo.rb
+ make test/ruby/test_foo.rb TESTOPTS="-n /test_bar/"
+ ```
+
+2. [test/](https://github.com/ruby/ruby/tree/master/test)
+
+ This is a more comprehensive test suite that runs on Ruby. We can run it with:
+
+ ```
+ make test-all
+ ```
+
+ We can run a specific test directory in this suite using the `TESTS` option, for example:
+
+ ```
+ make test-all TESTS=test/rubygems
+ ```
+
+ We can run a specific test file in this suite by also using the `TESTS` option, for example:
+
+ ```
+ make test-all TESTS=test/ruby/test_array.rb
+ ```
+
+ We can run a specific test in this suite using the `TESTS` option, specifying
+ first the file name, and then the test name, prefixed with `--name`. For example:
+
+ ```
+ make test-all TESTS="../test/ruby/test_alias.rb --name=/test_alias_with_zsuper_method/"
+ ```
+
+ To run these specs with logs, we can use:
+
+ ```
+ make test-all TESTS=-v
+ ```
+
+ If we would like to run both the `test/` and `bootstraptest/` test suites, we can run
+
+ ```
+ make check
+ ```
+
+3. [spec/ruby](https://github.com/ruby/ruby/tree/master/spec/ruby)
+
+ This is a test suite that exists in [the Ruby spec repository](https://github.com/ruby/spec) and is mirrored into the `spec/ruby` directory in the Ruby repository. It tests the behavior of the Ruby programming language. We can run this using:
+
+ ```
+ make test-spec
+ ```
+
+ To run a specific directory, we can use `MSPECOPT` to specify the directory:
+
+ ```
+ make test-spec MSPECOPT=spec/ruby/core/array
+ ```
+
+ To run a specific file, we can also use `MSPECOPT` to specify the file:
+
+ ```
+ make test-spec MSPECOPT=spec/ruby/core/array/any_spec.rb
+ ```
+
+ To run a specific test, we can use the `--example` flag to match against the test name:
+
+ ```
+ make test-spec MSPECOPT="../spec/ruby/core/array/any_spec.rb --example='is false if the array is empty'"
+ ```
+
+ To run these specs with logs, we can use:
+
+ ```
+ make test-spec MSPECOPT=-Vfs
+ ```
+
+ To run a ruby-spec file or directory with GNU make, we can use
+
+ ```
+ make spec/ruby/core/foo/bar_spec.rb
+ ```
+
+4. [spec/bundler](https://github.com/ruby/ruby/tree/master/spec/bundler)
+
+ The bundler test suite exists in [the RubyGems repository](https://github.com/rubygems/rubygems/tree/master/bundler/spec) and is mirrored into the `spec/bundler` directory in the Ruby repository. We can run this using:
+
+ ```
+ make test-bundler
+ ```
+
+ To run a specific bundler spec file, we can use `BUNDLER_SPECS` as follows:
+
+ ```
+ $ make test-bundler BUNDLER_SPECS=commands/exec_spec.rb
+ ```
diff --git a/doc/date/calendars.rdoc b/doc/date/calendars.rdoc
new file mode 100644
index 0000000000..b8690841b1
--- /dev/null
+++ b/doc/date/calendars.rdoc
@@ -0,0 +1,62 @@
+== Julian and Gregorian Calendars
+
+The difference between the
+{Julian calendar}[https://en.wikipedia.org/wiki/Julian_calendar]
+and the
+{Gregorian calendar}[https://en.wikipedia.org/wiki/Gregorian_calendar]
+may matter to your program if it uses dates before the switchovers.
+
+- October 15, 1582.
+- September 14, 1752.
+
+A date will be different in the two calendars, in general.
+
+=== Different switchover dates
+
+The reasons for the difference are religious/political histories.
+
+- On October 15, 1582, several countries changed
+ from the Julian calendar to the Gregorian calendar;
+ these included Italy, Poland, Portugal, and Spain.
+ Other contries in the Western world retained the Julian calendar.
+- On September 14, 1752, most of the British empire
+ changed from the Julian calendar to the Gregorian calendar.
+
+When your code uses a date before these switchover dates,
+it will matter whether it considers the switchover date
+to be the earlier date or the later date (or neither).
+
+See also {a concrete example here}[rdoc-ref:DateTime@When+should+you+use+DateTime+and+when+should+you+use+Time-3F].
+
+=== Argument +start+
+
+Certain methods in class \Date handle differences in the
+{Julian and Gregorian calendars}[rdoc-ref:calendars.rdoc@Julian+and+Gregorian+Calendars]
+by accepting an optional argument +start+, whose value may be:
+
+- Date::ITALY (the default): the created date is Julian
+ if before October 15, 1582, Gregorian otherwise:
+
+ d = Date.new(1582, 10, 15)
+ d.prev_day.julian? # => true
+ d.julian? # => false
+ d.gregorian? # => true
+
+- Date::ENGLAND: the created date is Julian if before September 14, 1752,
+ Gregorian otherwise:
+
+ d = Date.new(1752, 9, 14, Date::ENGLAND)
+ d.prev_day.julian? # => true
+ d.julian? # => false
+ d.gregorian? # => true
+
+- Date::JULIAN: the created date is Julian regardless of its value:
+
+ d = Date.new(1582, 10, 15, Date::JULIAN)
+ d.julian? # => true
+
+- Date::GREGORIAN: the created date is Gregorian regardless of its value:
+
+ d = Date.new(1752, 9, 14, Date::GREGORIAN)
+ d.prev_day.gregorian? # => true
+
diff --git a/doc/documentation_guide.rdoc b/doc/documentation_guide.rdoc
deleted file mode 100644
index 38438e94b4..0000000000
--- a/doc/documentation_guide.rdoc
+++ /dev/null
@@ -1,281 +0,0 @@
-= Documentation Guide
-
-This guide discusses recommendations for documenting
-classes, modules, and methods
-in the Ruby core and in the Ruby standard library.
-
-== Goal
-
-The goal of Ruby documentation is to impart the most important
-and relevant in the shortest time.
-The reader should be able to quickly understand the usefulness
-of the subject code and how to use it.
-
-Providing too little information is bad, but providing unimportant
-information or unnecessary examples is not good either.
-Use your judgment about what the user needs to know.
-
-== General Guidelines
-
-- Keep in mind that the reader may not be fluent in \English.
-- Write short declarative or imperative sentences.
-- Group sentences into (ideally short) paragraphs,
- each covering a single topic.
-- Organize material with
- {headers}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Headers].
-- Refer to authoritative and relevant sources using
- {links}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links].
-- Use simple verb tenses: simple present, simple past, simple future.
-- Use simple sentence structure, not compound or complex structure.
-- Avoid:
-
- - Excessive comma-separated phrases;
- consider a {list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Simple+Lists].
- - Idioms and culture-specific references.
- - Overuse of headers.
-
-=== \RDoc
-
-Ruby is documented using RDoc.
-For information on \RDoc syntax and features, see the
-{RDoc Markup Reference}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-RDoc+Markup+Reference].
-
-=== Output from <tt>irb</tt>
-
-For code examples, consider using interactive Ruby,
-{irb}[https://ruby-doc.org/stdlib/libdoc/irb/rdoc/IRB.html].
-
-For a code example that includes +irb+ output,
-consider aligning <tt># => ...</tt> in successive lines.
-Alignment may sometimes aid readability:
-
- a = [1, 2, 3] #=> [1, 2, 3]
- a.shuffle! #=> [2, 3, 1]
- a #=> [2, 3, 1]
-
-=== Headers
-
-Organize a long discussion with
-{headers}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Headers].
-
-=== Blank Lines
-
-A blank line begins a new paragraph.
-
-A {code block}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Paragraphs+and+Verbatim]
-or {list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Simple+Lists]
-should be preceded by and followed by a blank line.
-This is unnecessary for the HTML output, but helps in the +ri+ output.
-
-=== Auto-Linking
-
-In general, \RDoc's auto-linking should not be suppressed.
-For example, we should write +Array+, not <tt>\Array</tt>.
-
-We might consider whether to suppress when:
-
-- The word in question does not refer to a Ruby entity
- (e.g., some uses of _Class_ or _English_).
-- The reference is to the current class document
- (e.g., _Array_ in the documentation for class +Array+).
-- The same reference is repeated many times
- (e.g., _RDoc_ on this page).
-
-== Documenting Classes and Modules
-
-The general structure of the class or module documentation should be:
-
-* Synopsis
-* Common uses, with examples
-* "What's Here" summary (optional)
-
-=== Synopsis
-
-The synopsis is a short description of what the class or module does
-and why the reader might want to use it.
-Avoid details in the synopsis.
-
-=== Common Uses
-
-Show common uses of the class or module.
-Depending on the class or module, this section may vary greatly
-in both length and complexity.
-
-=== What's Here Summary
-
-The documentation for a class or module may include a "What's Here" section.
-
-Guidelines:
-
-- The section title is <tt>What's Here</tt>.
-- Consider listing the parent class and any included modules; consider
- {links}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links]
- to their "What's Here" sections if those exist.
-- List methods as a {labeled list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Labeled+Lists].
-- Each list entry's label is a method name;
- if the method has aliases, include those with the "base" method method,
- and do not list them separately.
-- Check the rendered documentation to determine whether \RDoc has recognized
- the method and linked to it; if not, manually insert a
- {link}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Links].
-- Each entry's description is a 1-line synopsis for the method.
-- Keep the description short.
-- If there are more entries, consider gouping them into subsections with headers.
-- If there are more than a few such subsections,
- consider adding a table of contents just below the main section title.
-
-== Documenting Methods
-
-=== General Structure
-
-The general structure of the method documentation should be:
-
-* Calling sequence (for methods written in C).
-* Synopsis (short description).
-* Details and examples.
-* Argument description (if necessary).
-* Corner cases and exceptions.
-* Aliases.
-* Related methods (optional).
-
-=== Calling Sequence (for methods written in C)
-
-For methods written in Ruby, \RDoc documents the calling sequence automatically.
-
-For methods written in C, \RDoc cannot determine what arguments
-the method accepts, so those need to be documented using \RDoc directive
-{:call-seq:}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Method+arguments].
-
-Example:
-
- * call-seq:
- * array.count -> integer
- * array.count(obj) -> integer
- * array.count {|element| ... } -> integer
-
-When creating the <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, but mention them near the end (see below).
-
-
-A +call-seq+ block should have <tt>{|x| ... }</tt>, not <tt>{|x| block }</tt> or <tt>{|x| code }</tt>.
-
-A +call-seq+ output should:
-
-- Have +self+, not +receiver+ or +array+.
-- Begin with +new_+ if and only if the output object is a new instance
- of the receiver's class, to emphasize that the output object is not +self+.
-
-=== Synopsis
-
-The synopsis comes next, and is a short description of what the
-method does and why you would want to use it. Ideally, this
-is a single sentence, but for more complex methods it may require
-an entire paragraph.
-
-For <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 a
-{labeled list}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-Labeled+Lists]}
-
-=== Corner Cases and Exceptions
-
-For corner cases of methods, such as atypical usage, briefly mention
-the behavior, but do not provide any examples.
-
-Only document exceptions raised if they are not obvious. For example,
-if you have stated earlier than an argument type must be an integer,
-you do not need to document that a \TypeError is raised if a non-integer
-is passed. Do not provide examples of exceptions being raised unless
-that is a common case, such as \Hash#fetch raising a \KeyError.
-
-=== Aliases
-
-Mention aliases in the form
-
- Array#find_index is an alias for Array#index.
-
-=== Related Methods (optional)
-
-In some cases, it is useful to document which methods are related to
-the current method. For example, documentation for \Hash#[] might
-mention \Hash#fetch as a related method, and \Hash#merge might mention
-\Hash#merge! as a related method. Consider which methods may be related
-to the current method, and if you think the reader would benefit it,
-at the end of the method documentation, add a line starting with
-"Related: " (e.g. "Related: #fetch"). Don't list more than three
-related methods. If you think more than three methods are related,
-pick the three you think are most important and list those three.
-
-=== Methods Accepting Multiple Argument Types
-
-For methods that accept multiple argument types, in some cases it can
-be useful to document the different argument types separately. It's
-best to use a separate paragraph for each case you are discussing.
diff --git a/doc/encodings.rdoc b/doc/encodings.rdoc
new file mode 100644
index 0000000000..1f3c54d740
--- /dev/null
+++ b/doc/encodings.rdoc
@@ -0,0 +1,479 @@
+== Encodings
+
+=== The Basics
+
+A {character encoding}[https://en.wikipedia.org/wiki/Character_encoding],
+often shortened to _encoding_, is a mapping between:
+
+- A sequence of 8-bit bytes (each byte in the range <tt>0..255</tt>).
+- Characters in a specific character set.
+
+Some character sets contain only 1-byte characters;
+{US-ASCII}[https://en.wikipedia.org/wiki/ASCII], for example, has 256 1-byte characters.
+This string, encoded in US-ASCII, has six characters that are stored as six bytes:
+
+ s = 'Hello!'.encode('US-ASCII') # => "Hello!"
+ s.encoding # => #<Encoding:US-ASCII>
+ s.bytes # => [72, 101, 108, 108, 111, 33]
+
+Other encodings may involve multi-byte characters.
+{UTF-8}[https://en.wikipedia.org/wiki/UTF-8], for example,
+encodes more than one million characters, encoding each in one to four bytes.
+The lowest-valued of these characters correspond to ASCII characters,
+and so are 1-byte characters:
+
+ s = 'Hello!' # => "Hello!"
+ s.bytes # => [72, 101, 108, 108, 111, 33]
+
+Other characters, such as the Euro symbol, are multi-byte:
+
+ s = "\u20ac" # => "€"
+ s.bytes # => [226, 130, 172]
+
+=== The \Encoding \Class
+
+==== \Encoding Objects
+
+Ruby encodings are defined by constants in class \Encoding.
+There can be only one instance of \Encoding for each of these constants.
+\Method Encoding.list returns an array of \Encoding objects (one for each constant):
+
+ Encoding.list.size # => 103
+ Encoding.list.first.class # => Encoding
+ Encoding.list.take(3)
+ # => [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>, #<Encoding:US-ASCII>]
+
+==== Names and Aliases
+
+\Method Encoding#name returns the name of an \Encoding:
+
+ Encoding::ASCII_8BIT.name # => "ASCII-8BIT"
+ Encoding::WINDOWS_31J.name # => "Windows-31J"
+
+An \Encoding object has zero or more aliases;
+method Encoding#names returns an array containing the name and all aliases:
+
+ Encoding::ASCII_8BIT.names
+ # => ["ASCII-8BIT", "BINARY"]
+ Encoding::WINDOWS_31J.names
+ #=> ["Windows-31J", "CP932", "csWindows31J", "SJIS", "PCK"]
+
+\Method Encoding.aliases returns a hash of all alias/name pairs:
+
+ Encoding.aliases.size # => 71
+ Encoding.aliases.take(3)
+ # => [["BINARY", "ASCII-8BIT"], ["CP437", "IBM437"], ["CP720", "IBM720"]]
+
+\Method Encoding.name_list returns an array of all the encoding names and aliases:
+
+ Encoding.name_list.size # => 175
+ Encoding.name_list.take(3)
+ # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
+
+\Method +name_list+ returns more entries than method +list+
+because it includes both the names and their aliases.
+
+\Method Encoding.find returns the \Encoding for a given name or alias, if it exists:
+
+ Encoding.find("US-ASCII") # => #<Encoding:US-ASCII>
+ Encoding.find("US-ASCII").class # => Encoding
+
+==== Default Encodings
+
+\Method Encoding.find, above, also returns a default \Encoding
+for each of these special names:
+
+- +external+: the default external \Encoding:
+
+ Encoding.find("external") # => #<Encoding:UTF-8>
+
+- +internal+: the default internal \Encoding (may be +nil+):
+
+ Encoding.find("internal") # => nil
+
+- +locale+: the default \Encoding for a string from the environment:
+
+ Encoding.find("locale") # => #<Encoding:UTF-8> # Linux
+ Encoding.find("locale") # => #<Encoding:IBM437> # Windows
+
+- +filesystem+: the default \Encoding for a string from the filesystem:
+
+ Encoding.find("filesystem") # => #<Encoding:UTF-8>
+
+\Method Encoding.default_external returns the default external \Encoding:
+
+ Encoding.default_external # => #<Encoding:UTF-8>
+
+\Method Encoding.default_external= sets that value:
+
+ Encoding.default_external = 'US-ASCII' # => "US-ASCII"
+ Encoding.default_external # => #<Encoding:US-ASCII>
+
+\Method Encoding.default_internal returns the default internal \Encoding:
+
+ Encoding.default_internal # => nil
+
+\Method Encoding.default_internal= sets the default internal \Encoding:
+
+ Encoding.default_internal = 'US-ASCII' # => "US-ASCII"
+ Encoding.default_internal # => #<Encoding:US-ASCII>
+
+==== Compatible Encodings
+
+\Method Encoding.compatible? returns whether two given objects are encoding-compatible
+(that is, whether they can be concatenated);
+returns the \Encoding of the concatenated string, or +nil+ if incompatible:
+
+ rus = "\u{442 435 441 442}"
+ eng = 'text'
+ Encoding.compatible?(rus, eng) # => #<Encoding:UTF-8>
+
+ s0 = "\xa1\xa1".force_encoding('iso-8859-1') # => "\xA1\xA1"
+ s1 = "\xa1\xa1".force_encoding('euc-jp') # => "\x{A1A1}"
+ Encoding.compatible?(s0, s1) # => nil
+
+=== \String \Encoding
+
+A Ruby String object has an encoding that is an instance of class \Encoding.
+The encoding may be retrieved by method String#encoding.
+
+The default encoding for a string literal is the script encoding
+(see Encoding@Script+encoding):
+
+ 's'.encoding # => #<Encoding:UTF-8>
+
+The default encoding for a string created with method String.new is:
+
+- For a \String object argument, the encoding of that string.
+- For a string literal, the script encoding (see Encoding@Script+encoding).
+
+In either case, any encoding may be specified:
+
+ s = String.new(encoding: 'UTF-8') # => ""
+ s.encoding # => #<Encoding:UTF-8>
+ s = String.new('foo', encoding: 'ASCII-8BIT') # => "foo"
+ s.encoding # => #<Encoding:ASCII-8BIT>
+
+The encoding for a string may be changed:
+
+ s = "R\xC3\xA9sum\xC3\xA9" # => "Résumé"
+ s.encoding # => #<Encoding:UTF-8>
+ s.force_encoding('ISO-8859-1') # => "R\xC3\xA9sum\xC3\xA9"
+ s.encoding # => #<Encoding:ISO-8859-1>
+
+Changing the assigned encoding does not alter the content of the string;
+it changes only the way the content is to be interpreted:
+
+ s # => "R\xC3\xA9sum\xC3\xA9"
+ s.force_encoding('UTF-8') # => "Résumé"
+
+The actual content of a string may also be altered;
+see {Transcoding a String}[#label-Transcoding+a+String].
+
+Here are a couple of useful query methods:
+
+ s = "abc".force_encoding("UTF-8") # => "abc"
+ s.ascii_only? # => true
+ s = "abc\u{6666}".force_encoding("UTF-8") # => "abc晦"
+ s.ascii_only? # => false
+
+ s = "\xc2\xa1".force_encoding("UTF-8") # => "¡"
+ s.valid_encoding? # => true
+ s = "\xc2".force_encoding("UTF-8") # => "\xC2"
+ s.valid_encoding? # => false
+
+=== \Symbol and \Regexp Encodings
+
+The string stored in a Symbol or Regexp object also has an encoding;
+the encoding may be retrieved by method Symbol#encoding or Regexp#encoding.
+
+The default encoding for these, however, is:
+
+- US-ASCII, if all characters are US-ASCII.
+- The script encoding, otherwise (see Encoding@Script+encoding).
+
+=== Filesystem \Encoding
+
+The filesystem encoding is the default \Encoding for a string from the filesystem:
+
+ Encoding.find("filesystem") # => #<Encoding:UTF-8>
+
+=== Locale \Encoding
+
+The locale encoding is the default encoding for a string from the environment,
+other than from the filesystem:
+
+ Encoding.find('locale') # => #<Encoding:IBM437>
+
+=== Stream Encodings
+
+Certain stream objects can have two encodings; these objects include instances of:
+
+- IO.
+- File.
+- ARGF.
+- StringIO.
+
+The two encodings are:
+
+- An _external_ _encoding_, which identifies the encoding of the stream.
+- An _internal_ _encoding_, which (if not +nil+) specifies the encoding
+ to be used for the string constructed from the stream.
+
+==== External \Encoding
+
+The external encoding, which is an \Encoding object, specifies how bytes read
+from the stream are to be interpreted as characters.
+
+The default external encoding is:
+
+- UTF-8 for a text stream.
+- ASCII-8BIT for a binary stream.
+
+The default external encoding is returned by method Encoding.default_external,
+and may be set by:
+
+- Ruby command-line options <tt>--external_encoding</tt> or <tt>-E</tt>.
+
+You can also set the default external encoding using method Encoding.default_external=,
+but doing so may cause problems; strings created before and after the change
+may have a different encodings.
+
+For an \IO or \File object, the external encoding may be set by:
+
+- Open options +external_encoding+ or +encoding+, when the object is created;
+ see {Open Options}[rdoc-ref:IO@Open+Options].
+
+For an \IO, \File, \ARGF, or \StringIO object, the external encoding may be set by:
+
+- \Methods +set_encoding+ or (except for \ARGF) +set_encoding_by_bom+.
+
+==== Internal \Encoding
+
+The internal encoding, which is an \Encoding object or +nil+,
+specifies how characters read from the stream
+are to be converted to characters in the internal encoding;
+those characters become a string whose encoding is set to the internal encoding.
+
+The default internal encoding is +nil+ (no conversion).
+It is returned by method Encoding.default_internal,
+and may be set by:
+
+- Ruby command-line options <tt>--internal_encoding</tt> or <tt>-E</tt>.
+
+You can also set the default internal encoding using method Encoding.default_internal=,
+but doing so may cause problems; strings created before and after the change
+may have a different encodings.
+
+For an \IO or \File object, the internal encoding may be set by:
+
+- Open options +internal_encoding+ or +encoding+, when the object is created;
+ see {Open Options}[rdoc-ref:IO@Open+Options].
+
+For an \IO, \File, \ARGF, or \StringIO object, the internal encoding may be set by:
+
+- \Method +set_encoding+.
+
+=== Script \Encoding
+
+A Ruby script has a script encoding, which may be retrieved by:
+
+ __ENCODING__ # => #<Encoding:UTF-8>
+
+The default script encoding is UTF-8;
+a Ruby source file may set its script encoding with a magic comment
+on the first line of the file (or second line, if there is a shebang on the first).
+The comment must contain the word +coding+ or +encoding+,
+followed by a colon, space and the Encoding name or alias:
+
+ # encoding: ISO-8859-1
+ __ENCODING__ #=> #<Encoding:ISO-8859-1>
+
+=== Transcoding
+
+_Transcoding_ is the process of changing a sequence of characters
+from one encoding to another.
+
+As far as possible, the characters remain the same,
+but the bytes that represent them may change.
+
+The handling for characters that cannot be represented in the destination encoding
+may be specified by @Encoding+Options.
+
+==== Transcoding a \String
+
+Each of these methods transcodes a string:
+
+- String#encode: Transcodes +self+ into a new string
+ according to given encodings and options.
+- String#encode!: Like String#encode, but transcodes +self+ in place.
+- String#scrub: Transcodes +self+ into a new string
+ by replacing invalid byte sequences with a given or default replacement string.
+- String#scrub!: Like String#scrub, but transcodes +self+ in place.
+- String#unicode_normalize: Transcodes +self+ into a new string
+ according to Unicode normalization.
+- String#unicode_normalize!: Like String#unicode_normalize,
+ but transcodes +self+ in place.
+
+=== Transcoding a Stream
+
+Each of these methods may transcode a stream;
+whether it does so depends on the external and internal encodings:
+
+- IO.foreach: Yields each line of given stream to the block.
+- IO.new: Creates and returns a new \IO object for the given integer file descriptor.
+- IO.open: Creates a new \IO object.
+- IO.pipe: Creates a connected pair of reader and writer \IO objects.
+- IO.popen: Creates an \IO object to interact with a subprocess.
+- IO.read: Returns a string with all or a subset of bytes from the given stream.
+- IO.readlines: Returns an array of strings, which are the lines from the given stream.
+- IO.write: Writes a given string to the given stream.
+
+This example writes a string to a file, encoding it as ISO-8859-1,
+then reads the file into a new string, encoding it as UTF-8:
+
+ s = "R\u00E9sum\u00E9"
+ path = 't.tmp'
+ ext_enc = 'ISO-8859-1'
+ int_enc = 'UTF-8'
+
+ File.write(path, s, external_encoding: ext_enc)
+ raw_text = File.binread(path)
+
+ transcoded_text = File.read(path, external_encoding: ext_enc, internal_encoding: int_enc)
+
+ p raw_text
+ p transcoded_text
+
+Output:
+
+ "R\xE9sum\xE9"
+ "Résumé"
+
+=== \Encoding Options
+
+A number of methods in the Ruby core accept keyword arguments as encoding options.
+
+Some of the options specify or utilize a _replacement_ _string_, to be used
+in certain transcoding operations.
+A replacement string may be in any encoding that can be converted
+to the encoding of the destination string.
+
+These keyword-value pairs specify encoding options:
+
+- For an invalid byte sequence:
+
+ - <tt>:invalid: nil</tt> (default): Raise exception.
+ - <tt>:invalid: :replace</tt>: Replace each invalid byte sequence
+ with the replacement string.
+
+ Examples:
+
+ s = "\x80foo\x80"
+ s.encode('ISO-8859-3') # Raises Encoding::InvalidByteSequenceError.
+ s.encode('ISO-8859-3', invalid: :replace) # => "?foo?"
+
+- For an undefined character:
+
+ - <tt>:undef: nil</tt> (default): Raise exception.
+ - <tt>:undef: :replace</tt>: Replace each undefined character
+ with the replacement string.
+
+ Examples:
+
+ s = "\x80foo\x80"
+ "\x80".encode('UTF-8', 'ASCII-8BIT') # Raises Encoding::UndefinedConversionError.
+ s.encode('UTF-8', 'ASCII-8BIT', undef: :replace) # => "�foo�"
+
+
+- Replacement string:
+
+ - <tt>:replace: nil</tt> (default): Set replacement string to default value:
+ <tt>"\uFFFD"</tt> ("�") for a Unicode encoding, <tt>'?'</tt> otherwise.
+ - <tt>:replace: _some_string_</tt>: Set replacement string to the given +some_string+;
+ overrides +:fallback+.
+
+ Examples:
+
+ s = "\xA5foo\xA5"
+ options = {:undef => :replace, :replace => 'xyzzy'}
+ s.encode('UTF-8', 'ISO-8859-3', **options) # => "xyzzyfooxyzzy"
+
+- Replacement fallback:
+
+ One of these may be specified:
+
+ - <tt>:fallback: nil</tt> (default): No replacement fallback.
+ - <tt>:fallback: _hash_like_object_</tt>: Set replacement fallback to the given
+ +hash_like_object+; the replacement string is <tt>_hash_like_object_[X]</tt>.
+ - <tt>:fallback: _method_</tt>: Set replacement fallback to the given
+ +method+; the replacement string is <tt>_method_(X)</tt>.
+ - <tt>:fallback: _proc_</tt>: Set replacement fallback to the given
+ +proc+; the replacement string is <tt>_proc_[X]</tt>.
+
+ Examples:
+
+ s = "\u3042foo\u3043"
+
+ hash = {"\u3042" => 'xyzzy'}
+ hash.default = 'XYZZY'
+ s.encode('ASCII', fallback: h) # => "xyzzyfooXYZZY"
+
+ def (fallback = "U+%.4X").escape(x)
+ self % x.unpack("U")
+ end
+ "\u{3042}".encode("US-ASCII", fallback: fallback.method(:escape)) # => "U+3042"
+
+ proc = Proc.new {|x| x == "\u3042" ? 'xyzzy' : 'XYZZY' }
+ s.encode('ASCII', fallback: proc) # => "XYZZYfooXYZZY"
+
+- XML entities:
+
+ One of these may be specified:
+
+ - <tt>:xml: nil</tt> (default): No handling for XML entities.
+ - <tt>:xml: :text</tt>: Treat source text as XML;
+ replace each undefined character
+ with its upper-case hexdecimal numeric character reference,
+ except that:
+
+ - <tt>&</tt> is replaced with <tt>&amp;</tt>.
+ - <tt><</tt> is replaced with <tt>&lt;</tt>.
+ - <tt>></tt> is replaced with <tt>&gt;</tt>.
+
+ - <tt>:xml: :attr</tt>: Treat source text as XML attribute value;
+ replace each undefined character
+ with its upper-case hexdecimal numeric character reference,
+ except that:
+
+ - The replacement string <tt>r</tt> is double-quoted (<tt>"r"</tt>).
+ - Each embedded double-quote is replaced with <tt>&quot;</tt>.
+ - <tt>&</tt> is replaced with <tt>&amp;</tt>.
+ - <tt><</tt> is replaced with <tt>&lt;</tt>.
+ - <tt>></tt> is replaced with <tt>&gt;</tt>.
+
+ Examples:
+
+ s = 'foo"<&>"bar' + "\u3042"
+ s.encode('ASCII', xml: :text) # => "foo\"&lt;&amp;&gt;\"bar&#x3042;"
+ s.encode('ASCII', xml: :attr) # => "\"foo&quot;&lt;&amp;&gt;&quot;bar&#x3042;\""
+
+
+- Newlines:
+
+ One of these may be specified:
+
+ - <tt>:cr_newline: true</tt>: Replace each line-feed character (<tt>"\n"</tt>)
+ with a carriage-return character (<tt>"\r"</tt>).
+ - <tt>:crlf_newline: true</tt>: Replace each line-feed character (<tt>"\n"</tt>)
+ with a carriage-return/line-feed string (<tt>"\r\n"</tt>).
+ - <tt>:universal_newline: true</tt>: Replace each carriage-return
+ character (<tt>"\r"</tt>) and each carriage-return/line-feed string
+ (<tt>"\r\n"</tt>) with a line-feed character (<tt>"\n"</tt>).
+
+ Examples:
+
+ s = "\n \r \r\n" # => "\n \r \r\n"
+ s.encode('ASCII', cr_newline: true) # => "\r \r \r\r"
+ s.encode('ASCII', crlf_newline: true) # => "\r\n \r \r\r\n"
+ s.encode('ASCII', universal_newline: true) # => "\n \n \n"
diff --git a/doc/examples/files.rdoc b/doc/examples/files.rdoc
new file mode 100644
index 0000000000..f736132770
--- /dev/null
+++ b/doc/examples/files.rdoc
@@ -0,0 +1,26 @@
+# English text with newlines.
+text = <<~EOT
+ First line
+ Second line
+
+ Fourth line
+ Fifth line
+EOT
+
+# Russian text.
+russian = "\u{442 435 441 442}" # => "тест"
+
+# Binary data.
+data = "\u9990\u9991\u9992\u9993\u9994"
+
+# Text file.
+File.write('t.txt', text)
+
+# File with Russian text.
+File.write('t.rus', russian)
+
+# File with binary data.
+f = File.new('t.dat', 'wb:UTF-16')
+f.write(data)
+f.close
+
diff --git a/doc/extension.ja.rdoc b/doc/extension.ja.rdoc
index a6f7719792..93f5753cd1 100644
--- a/doc/extension.ja.rdoc
+++ b/doc/extension.ja.rdoc
@@ -617,12 +617,14 @@ C言語とRubyの間で情報を共有する方法について解説します.
Qtrue ::
Qfalse ::
- 真偽値.QfalseはC言語でも偽とみなされます(つまり0).
+ 真偽値.C言語から見た「true」と「false」.
Qnil ::
C言語から見た「nil」.
+RTEST(obj)というマクロはobjがQfalseかQnilのとき0を返します.
+
=== CとRubyで共有される大域変数
CとRubyで大域変数を使って情報を共有できます.共有できる大域
@@ -697,30 +699,28 @@ Cの世界で定義されたデータ(構造体)をRubyのオブジェクトと
このマクロの戻り値は生成されたオブジェクトを表すVALUE値です.
-klassはこのオブジェクトのクラスです.data_typeはこの構造体を
-Rubyが管理するための情報を記述したconst rb_data_type_t型への
-ポインタです.
+klassはこのオブジェクトのクラスです.klassは, Objectクラスか
+ら派生し, 必ずrb_define_alloc_funcかrb_undef_alloc_funcを呼
+び出してallocatorを設定してください.
-なお, klassは, Objectや他のクラスではなくData (rb_cData)とい
-う特別なクラスから派生することが推奨されます.
-Dataから派生しない場合には, 必ずrb_undef_alloc_func(klass)
-を呼び出してください.
+data_typeはこの構造体をRubyが管理するための情報を記述した
+const rb_data_type_t型へのポインタです.
rb_data_type_tは次のように定義されています.
typedef struct rb_data_type_struct rb_data_type_t;
struct rb_data_type_struct {
- const char *wrap_struct_name;
- struct {
- void (*dmark)(void*);
- void (*dfree)(void*);
- size_t (*dsize)(const void *);
- void *reserved[2];
- } function;
- const rb_data_type_t *parent;
- void *data;
- VALUE flags;
+ const char *wrap_struct_name;
+ struct {
+ void (*dmark)(void*);
+ void (*dfree)(void*);
+ size_t (*dsize)(const void *);
+ void *reserved[2];
+ } function;
+ const rb_data_type_t *parent;
+ void *data;
+ VALUE flags;
};
wrap_struct_nameはこの構造体を識別する名前です.主に統計情報
@@ -743,8 +743,8 @@ dmarkはガーベージコレクタがオブジェクトへの参照をマーク
++
dfreeはこの構造体がもう不要になった時に呼ばれる関数です.こ
-の関数がガーベージコレクタから呼ばれます.これが-1の場合は,
-単純に構造体が解放されます.
+の関数がガーベージコレクタから呼ばれます.これが
+RUBY_DEFAULT_FREEの場合は,単純に構造体が解放されます.
dsizeは構造体が消費しているメモリのバイト数を返す関数です.
引数として構造体へのポインタが渡されます.実装困難であれば0
@@ -1066,6 +1066,20 @@ Rubyのソースはいくつかに分類することが出来ます.このう
ています.これらのソースは今までの説明でほとんど理解できると
思います.
+=== Rubyのヘッダファイル
+
+<tt>$repo_root/include/ruby</tt>以下はすべて<tt>make
+install</tt>でインストールされます.拡張ライブラリからは,
+<tt>#include <ruby.h></tt>でインクルードする必要があります.
++rbimpl_+,+RBIMPL_+のプレフィックスが付いた実装の詳細のため
+のシンボルを除き,すべてのシンボルは公開APIです.
+
+拡張ライブラリで直接インクルードできるのは,
+<tt>$repo_root/include/ruby/*.h</tt>のうち,対応する
+<tt>HAVE_RUBY_*_H</tt>マクロが
+<tt>$repo_root/include/ruby.h</tt>ヘッダーで定義されているも
+のです.
+
=== Ruby言語のコア
class.c :: クラスとモジュール
@@ -1681,6 +1695,9 @@ HAVE_RUBY_*_H ::
を意味する.たとえば,HAVE_RUBY_ST_H が定義されている場合は
単なる st.h ではなく ruby/st.h を使用する.
+ これらのマクロに対応するヘッダーファイルは,拡張ライブラリ
+ から直接インクルードしてもよい.
+
RB_EVENT_HOOKS_HAVE_CALLBACK_DATA ::
rb_add_event_hook() がフック関数に渡す data を第3引数として
@@ -1757,6 +1774,14 @@ check_sizeof(type, header) ::
`SIZEOF_{TYPE}` を定義し,そのサイズを返す.定義されていな
いときはnilを返す.
+append_cppflags(array-of-flags[, opt])
+append_cflags(array-of-flags[, opt])
+append_ldflags(array-of-flags[, opt])
+
+ 各flagが使用可能であれば,それぞれ$CPPFLAGS, $CFLAGS,
+ $LDFLAGSに追加する.コンパイラのフラグには移植性がないので,
+ 変数に直接追加せずこれらを使うことが望ましい.
+
create_makefile(target[, target_prefix]) ::
拡張ライブラリ用のMakefileを生成する.この関数を呼ばなけれ
diff --git a/doc/extension.rdoc b/doc/extension.rdoc
index f8e0a1ec3d..ad9ae641d2 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -93,7 +93,9 @@ There are also faster check macros for fixnums and nil.
The data for type T_NIL, T_FALSE, T_TRUE are nil, false, true
respectively. They are singletons for the data type.
The equivalent C constants are: Qnil, Qfalse, Qtrue.
-Note that Qfalse is false in C also (i.e. 0), but not Qnil.
+RTEST() will return true if a VALUE is neither Qfalse nor Qnil.
+If you need to differentiate Qfalse from Qnil,
+specifically test against Qfalse.
The T_FIXNUM data is a 31bit or 63bit length fixed integer.
This size depends on the size of long: if long is 32bit then
@@ -450,7 +452,7 @@ you may rely on:
To specify whether keyword arguments are passed when calling super:
- VALUE rb_call_super(int argc, const VALUE *argv, int kw_splat)
+ VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
+kw_splat+ can have these possible values (used by all methods that accept
+kw_splat+ argument):
@@ -657,8 +659,10 @@ with the next macro.
TypedData_Wrap_Struct() returns a created Ruby object as a VALUE.
-The klass argument is the class for the object. It is recommended
-that klass derives from rb_cObject.
+The klass argument is the class for the object. The klass should
+derive from rb_cObject, and the allocator must be set by calling
+rb_define_alloc_func or rb_undef_alloc_func.
+
data_type is a pointer to a const rb_data_type_t which describes
how Ruby should manage the struct.
@@ -668,17 +672,17 @@ member of the struct.
typedef struct rb_data_type_struct rb_data_type_t;
struct rb_data_type_struct {
- const char *wrap_struct_name;
- struct {
- void (*dmark)(void*);
- void (*dfree)(void*);
- size_t (*dsize)(const void *);
- void (*dcompact)(void*);
- void *reserved[1];
- } function;
- const rb_data_type_t *parent;
- void *data;
- VALUE flags;
+ const char *wrap_struct_name;
+ struct {
+ void (*dmark)(void*);
+ void (*dfree)(void*);
+ size_t (*dsize)(const void *);
+ void (*dcompact)(void*);
+ void *reserved[1];
+ } function;
+ const rb_data_type_t *parent;
+ void *data;
+ VALUE flags;
};
wrap_struct_name is an identifier of this instance of the struct.
@@ -699,7 +703,7 @@ Note that it is recommended to avoid such a reference.
++
dfree is a function to free the pointer allocation.
-If this is -1, the pointer will be just freed.
+If this is RUBY_DEFAULT_FREE, the pointer will be just freed.
dsize calculates memory consumption in bytes by the struct.
Its parameter is a pointer to your struct.
@@ -811,6 +815,7 @@ the library.
Here's the example of an initializing function.
+ #include <ruby.h>
void
Init_dbm(void)
{
@@ -951,6 +956,9 @@ need to put
at the top of the file. You can use the functions below to check
various conditions.
+ append_cppflags(array-of-flags[, opt]): append each flag to $CPPFLAGS if usable
+ append_cflags(array-of-flags[, opt]): append each flag to $CFLAGS if usable
+ append_ldflags(array-of-flags[, opt]): append each flag to $LDFLAGS if usable
have_macro(macro[, headers[, opt]]): check whether macro is defined
have_library(lib[, func[, headers[, opt]]]): check whether library containing function exists
find_library(lib[, func, *paths]): find library from paths
@@ -979,6 +987,10 @@ The value of the variables below will affect the Makefile.
$LDFLAGS: included in LDFLAGS make variable (such as -L)
$objs: list of object file names
+Compiler/linker flags are not portable usually, you should use
++append_cppflags+, +append_cpflags+ and +append_ldflags+ respectively
+instead of appending the above variables directly.
+
Normally, the object files list is automatically generated by searching
source files, but you must define them explicitly if any sources will
be generated while building.
@@ -1032,7 +1044,24 @@ You can do anything you want with your library. The author of Ruby
will not claim any restrictions on your code depending on the Ruby API.
Feel free to use, modify, distribute or sell your program.
-== Appendix A. Ruby Source Files Overview
+== Appendix A. Ruby Header and Source Files Overview
+
+=== Ruby Header Files
+
+Everything under <tt>$repo_root/include/ruby</tt> is installed with
+<tt>make install</tt>.
+It should be included per <tt>#include <ruby.h></tt> from C extensions.
+All symbols are public API with the exception of symbols prefixed with
++rbimpl_+ or +RBIMPL_+. They are implementation details and shouldn't
+be used by C extensions.
+
+Only <tt>$repo_root/include/ruby/*.h</tt> whose corresponding macros
+are defined in the <tt>$repo_root/include/ruby.h</tt> header are
+allowed to be <tt>#include</tt>-d by C extensions.
+
+Header files under <tt>$repo_root/internal/</tt> or directly under the
+root <tt>$repo_root/*.h</tt> are not make-installed.
+They are internal headers with only internal APIs.
=== Ruby Language Core
@@ -1903,6 +1932,9 @@ HAVE_RUBY_*_H ::
instance, when HAVE_RUBY_ST_H is defined you should use ruby/st.h not
mere st.h.
+ Header files corresponding to these macros may be <tt>#include</tt>
+ directly from extension libraries.
+
RB_EVENT_HOOKS_HAVE_CALLBACK_DATA ::
Means that rb_add_event_hook() takes the third argument `data', to be
@@ -2105,24 +2137,20 @@ keyword in C. RB_GC_GUARD has the following advantages:
== 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.
+Ractor(s) are the parallel execution mechanism introduced in Ruby 3.0. All
+ractors can run in parallel on a different OS thread (using an underlying system
+provided thread), so the C extension should be thread-safe. A C extension that
+can run in multiple ractors is called "Ractor-safe".
-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".
+Ractor safety around C extensions has the following properties:
+1. By default, all C extensions are recognized as Ractor-unsafe.
+2. Ractor-unsafe C-methods may only be called from the main Ractor. If invoked
+ by a non-main Ractor, then a Ractor::UnsafeError is raised.
+3. If an extension desires to be marked as Ractor-safe the extension should
+ call rb_ext_ractor_safe(true) at the Init_ function for the extension, and
+ all defined methods will be marked as Ractor-safe.
-To make "Ractor-safe" C extension, we need to check the following points:
+To make a "Ractor-safe" C extension, we need to check the following points:
(1) Do not share unshareable objects between ractors
@@ -2160,15 +2188,16 @@ 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.
+With Ractors, all objects given as method parameters and the receiver (self)
+are guaranteed to be from the current Ractor or to be shareable. As a
+consequence, it is easier to make code ractor-safe than to make code generally
+thread-safe. For example, we don't need to lock an array object to access the
+element of it.
-(3) Check the thread-safety of using library
+(3) Check the thread-safety of any used library
-If an extension relies on the external library libfoo and the function
-foo(), the function foo() should be thread safe.
+If the extension relies on an external library, such as a function foo() from
+a library libfoo, the function libfoo foo() should be thread safe.
(4) Make an object shareable
@@ -2183,8 +2212,9 @@ 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.
+There are possibly other points or requirements which must be considered in the
+making of a Ractor-safe extension. This document will be extended as they are
+discovered.
:enddoc: Local variables:
:enddoc: fill-column: 70
diff --git a/doc/fiber.md b/doc/fiber.md
index 9baab4e4d1..a334faf739 100644
--- a/doc/fiber.md
+++ b/doc/fiber.md
@@ -48,6 +48,14 @@ When the thread exits, there is an implicit call to `set_scheduler`:
Fiber.set_scheduler(nil)
```
+### Design
+
+The scheduler interface is designed to be a un-opinionated light-weight layer
+between user code and blocking operations. The scheduler hooks should avoid
+translating or converting arguments or return values. Ideally, the exact same
+arguments from the user code are provided directly to the scheduler hook with
+no changes.
+
### Interface
This is the interface you need to implement.
@@ -65,7 +73,7 @@ class Scheduler
end.value
end
- # Wait for the given file descriptor to match the specified events within
+ # Wait for the given io readiness to match the specified events within
# the specified timeout.
# @parameter event [Integer] A bit mask of `IO::READABLE`,
# `IO::WRITABLE` and `IO::PRIORITY`.
@@ -74,6 +82,22 @@ class Scheduler
def io_wait(io, events, timeout)
end
+ # Read from the given io into the specified buffer.
+ # WARNING: Experimental hook! Do not use in production code!
+ # @parameter io [IO] The io to read from.
+ # @parameter buffer [IO::Buffer] The buffer to read into.
+ # @parameter length [Integer] The minimum amount to read.
+ def io_read(io, buffer, length)
+ end
+
+ # Write from the given buffer into the specified IO.
+ # WARNING: Experimental hook! Do not use in production code!
+ # @parameter io [IO] The io to write to.
+ # @parameter buffer [IO::Buffer] The buffer to write from.
+ # @parameter length [Integer] The minimum amount to write.
+ def io_write(io, buffer, length)
+ end
+
# Sleep the current task for the specified duration, or forever if not
# specified.
# @parameter duration [Numeric] The amount of time to sleep in seconds.
diff --git a/doc/format_specifications.rdoc b/doc/format_specifications.rdoc
new file mode 100644
index 0000000000..e589524f27
--- /dev/null
+++ b/doc/format_specifications.rdoc
@@ -0,0 +1,348 @@
+== Format Specifications
+
+Several Ruby core classes have instance method +printf+ or +sprintf+:
+
+- ARGF#printf
+- IO#printf
+- Kernel#printf
+- Kernel#sprintf
+
+Each of these methods takes:
+
+- Argument +format_string+, which has zero or more
+ embedded _format_ _specifications_ (see below).
+- Arguments <tt>*arguments</tt>, which are zero or more objects to be formatted.
+
+Each of these methods prints or returns the string
+resulting from replacing each
+format specification embedded in +format_string+ with a string form
+of the corresponding argument among +arguments+.
+
+A simple example:
+
+ sprintf('Name: %s; value: %d', 'Foo', 0) # => "Name: Foo; value: 0"
+
+A format specification has the form:
+
+ %[flags][width][.precision]type
+
+It consists of:
+
+- A leading percent character.
+- Zero or more _flags_ (each is a character).
+- An optional _width_ _specifier_ (an integer).
+- An optional _precision_ _specifier_ (a period followed by a non-negative integer).
+- A _type_ _specifier_ (a character).
+
+Except for the leading percent character,
+the only required part is the type specifier, so we begin with that.
+
+=== Type Specifiers
+
+This section provides a brief explanation of each type specifier.
+The links lead to the details and examples.
+
+==== \Integer Type Specifiers
+
+- +b+ or +B+: Format +argument+ as a binary integer.
+ See {Specifiers b and B}[rdoc-ref:format_specifications.rdoc@Specifiers+b+and+B].
+- +d+, +i+, or +u+ (all are identical):
+ Format +argument+ as a decimal integer.
+ See {Specifier d}[rdoc-ref:format_specifications.rdoc@Specifier+d].
+- +o+: Format +argument+ as an octal integer.
+ See {Specifier o}[rdoc-ref:format_specifications.rdoc@Specifier+o].
+- +x+ or +X+: Format +argument+ as a hexadecimal integer.
+ See {Specifiers x and X}[rdoc-ref:format_specifications.rdoc@Specifiers+x+and+X].
+
+==== Floating-Point Type Specifiers
+
+- +a+ or +A+: Format +argument+ as hexadecimal floating-point number.
+ See {Specifiers a and A}[rdoc-ref:format_specifications.rdoc@Specifiers+a+and+A].
+- +e+ or +E+: Format +argument+ in scientific notation.
+ See {Specifiers e and E}[rdoc-ref:format_specifications.rdoc@Specifiers+e+and+E].
+- +f+: Format +argument+ as a decimal floating-point number.
+ See {Specifier f}[rdoc-ref:format_specifications.rdoc@Specifier+f].
+- +g+ or +G+: Format +argument+ in a "general" format.
+ See {Specifiers g and G}[rdoc-ref:format_specifications.rdoc@Specifiers+g+and+G].
+
+==== Other Type Specifiers
+
+- +c+: Format +argument+ as a character.
+ See {Specifier c}[rdoc-ref:format_specifications.rdoc@Specifier+c].
+- +p+: Format +argument+ as a string via <tt>argument.inspect</tt>.
+ See {Specifier p}[rdoc-ref:format_specifications.rdoc@Specifier+p].
+- +s+: Format +argument+ as a string via <tt>argument.to_s</tt>.
+ See {Specifier s}[rdoc-ref:format_specifications.rdoc@Specifier+s].
+- <tt>%</tt>: Format +argument+ (<tt>'%'</tt>) as a single percent character.
+ See {Specifier %}[rdoc-ref:format_specifications.rdoc@Specifier+-25].
+
+=== Flags
+
+The effect of a flag may vary greatly among type specifiers.
+These remarks are general in nature.
+See {type-specific details}[rdoc-ref:format_specifications.rdoc@Type+Specifier+Details+and+Examples].
+
+Multiple flags may be given with single type specifier;
+order does not matter.
+
+==== <tt>' '</tt> Flag
+
+Insert a space before a non-negative number:
+
+ sprintf('%d', 10) # => "10"
+ sprintf('% d', 10) # => " 10"
+
+Insert a minus sign for negative value:
+
+ sprintf('%d', -10) # => "-10"
+ sprintf('% d', -10) # => "-10"
+
+==== <tt>'#'</tt> Flag
+
+Use an alternate format; varies among types:
+
+ sprintf('%x', 100) # => "64"
+ sprintf('%#x', 100) # => "0x64"
+
+==== <tt>'+'</tt> Flag
+
+Add a leading plus sign for a non-negative number:
+
+ sprintf('%x', 100) # => "64"
+ sprintf('%+x', 100) # => "+64"
+
+==== <tt>'-'</tt> Flag
+
+Left justify the value in its field:
+
+ sprintf('%6d', 100) # => " 100"
+ sprintf('%-6d', 100) # => "100 "
+
+==== <tt>'0'</tt> Flag
+
+Left-pad with zeros instead of spaces:
+
+ sprintf('%6d', 100) # => " 100"
+ sprintf('%06d', 100) # => "000100"
+
+==== <tt>'*'</tt> Flag
+
+Use the next argument as the field width:
+
+ sprintf('%d', 20, 14) # => "20"
+ sprintf('%*d', 20, 14) # => " 14"
+
+==== <tt>'n$'</tt> Flag
+
+Format the (1-based) <tt>n</tt>th argument into this field:
+
+ sprintf("%s %s", 'world', 'hello') # => "world hello"
+ sprintf("%2$s %1$s", 'world', 'hello') # => "hello world"
+
+=== Width Specifier
+
+In general, a width specifier determines the minimum width (in characters)
+of the formatted field:
+
+ sprintf('%10d', 100) # => " 100"
+
+ # Left-justify if negative.
+ sprintf('%-10d', 100) # => "100 "
+
+ # Ignore if too small.
+ sprintf('%1d', 100) # => "100"
+
+=== Precision Specifier
+
+A precision specifier is a decimal point followed by zero or more
+decimal digits.
+
+For integer type specifiers, the precision specifies the minimum number of
+digits to be written. If the precision is shorter than the integer, the result is
+padded with leading zeros. There is no modification or truncation of the result
+if the integer is longer than the precision:
+
+ sprintf('%.3d', 1) # => "001"
+ sprintf('%.3d', 1000) # => "1000"
+
+ # If the precision is 0 and the value is 0, nothing is written
+ sprintf('%.d', 0) # => ""
+ sprintf('%.0d', 0) # => ""
+
+For the +a+/+A+, +e+/+E+, +f+/+F+ specifiers, the precision specifies
+the number of digits after the decimal point to be written:
+
+ sprintf('%.2f', 3.14159) # => "3.14"
+ sprintf('%.10f', 3.14159) # => "3.1415900000"
+
+ # With no precision specifier, defaults to 6-digit precision.
+ sprintf('%f', 3.14159) # => "3.141590"
+
+For the +g+/+G+ specifiers, the precision specifies
+the number of significant digits to be written:
+
+ sprintf('%.2g', 123.45) # => "1.2e+02"
+ sprintf('%.3g', 123.45) # => "123"
+ sprintf('%.10g', 123.45) # => "123.45"
+
+ # With no precision specifier, defaults to 6 significant digits.
+ sprintf('%g', 123.456789) # => "123.457"
+
+For the +s+, +p+ specifiers, the precision specifies
+the number of characters to write:
+
+ sprintf('%s', Time.now) # => "2022-05-04 11:59:16 -0400"
+ sprintf('%.10s', Time.now) # => "2022-05-04"
+
+=== Type Specifier Details and Examples
+
+==== Specifiers +a+ and +A+
+
+Format +argument+ as hexadecimal floating-point number:
+
+ sprintf('%a', 3.14159) # => "0x1.921f9f01b866ep+1"
+ sprintf('%a', -3.14159) # => "-0x1.921f9f01b866ep+1"
+ sprintf('%a', 4096) # => "0x1p+12"
+ sprintf('%a', -4096) # => "-0x1p+12"
+
+ # Capital 'A' means that alphabetical characters are printed in upper case.
+ sprintf('%A', 4096) # => "0X1P+12"
+ sprintf('%A', -4096) # => "-0X1P+12"
+
+==== Specifiers +b+ and +B+
+
+The two specifiers +b+ and +B+ behave identically
+except when flag <tt>'#'</tt>+ is used.
+
+Format +argument+ as a binary integer:
+
+ sprintf('%b', 1) # => "1"
+ sprintf('%b', 4) # => "100"
+
+ # Prefix '..' for negative value.
+ sprintf('%b', -4) # => "..100"
+
+ # Alternate format.
+ sprintf('%#b', 4) # => "0b100"
+ sprintf('%#B', 4) # => "0B100"
+
+==== Specifier +c+
+
+Format +argument+ as a single character:
+
+ sprintf('%c', 'A') # => "A"
+ sprintf('%c', 65) # => "A"
+
+==== Specifier +d+
+
+Format +argument+ as a decimal integer:
+
+ sprintf('%d', 100) # => "100"
+ sprintf('%d', -100) # => "-100"
+
+Flag <tt>'#'</tt> does not apply.
+
+==== Specifiers +e+ and +E+
+
+Format +argument+ in
+{scientific notation}[https://en.wikipedia.org/wiki/Scientific_notation]:
+
+ sprintf('%e', 3.14159) # => "3.141590e+00"
+ sprintf('%E', -3.14159) # => "-3.141590E+00"
+
+==== Specifier +f+
+
+Format +argument+ as a floating-point number:
+
+ sprintf('%f', 3.14159) # => "3.141590"
+ sprintf('%f', -3.14159) # => "-3.141590"
+
+Flag <tt>'#'</tt> does not apply.
+
+==== Specifiers +g+ and +G+
+
+Format +argument+ using exponential form (+e+/+E+ specifier)
+if the exponent is less than -4 or greater than or equal to the precision.
+Otherwise format +argument+ using floating-point form (+f+ specifier):
+
+ sprintf('%g', 100) # => "100"
+ sprintf('%g', 100.0) # => "100"
+ sprintf('%g', 3.14159) # => "3.14159"
+ sprintf('%g', 100000000000) # => "1e+11"
+ sprintf('%g', 0.000000000001) # => "1e-12"
+
+ # Capital 'G' means use capital 'E'.
+ sprintf('%G', 100000000000) # => "1E+11"
+ sprintf('%G', 0.000000000001) # => "1E-12"
+
+ # Alternate format.
+ sprintf('%#g', 100000000000) # => "1.00000e+11"
+ sprintf('%#g', 0.000000000001) # => "1.00000e-12"
+ sprintf('%#G', 100000000000) # => "1.00000E+11"
+ sprintf('%#G', 0.000000000001) # => "1.00000E-12"
+
+==== Specifier +o+
+
+Format +argument+ as an octal integer.
+If +argument+ is negative, it will be formatted as a two's complement
+prefixed with +..7+:
+
+ sprintf('%o', 16) # => "20"
+
+ # Prefix '..7' for negative value.
+ sprintf('%o', -16) # => "..760"
+
+ # Prefix zero for alternate format if positive.
+ sprintf('%#o', 16) # => "020"
+ sprintf('%#o', -16) # => "..760"
+
+==== Specifier +p+
+
+Format +argument+ as a string via <tt>argument.inspect</tt>:
+
+ t = Time.now
+ sprintf('%p', t) # => "2022-05-01 13:42:07.1645683 -0500"
+
+==== Specifier +s+
+
+Format +argument+ as a string via <tt>argument.to_s</tt>:
+
+ t = Time.now
+ sprintf('%s', t) # => "2022-05-01 13:42:07 -0500"
+
+Flag <tt>'#'</tt> does not apply.
+
+==== Specifiers +x+ and +X+
+
+Format +argument+ as a hexadecimal integer.
+If +argument+ is negative, it will be formatted as a two's complement
+prefixed with +..f+:
+
+ sprintf('%x', 100) # => "64"
+
+ # Prefix '..f' for negative value.
+ sprintf('%x', -100) # => "..f9c"
+
+ # Use alternate format.
+ sprintf('%#x', 100) # => "0x64"
+
+ # Alternate format for negative value.
+ sprintf('%#x', -100) # => "0x..f9c"
+
+==== Specifier <tt>%</tt>
+
+Format +argument+ (<tt>'%'</tt>) as a single percent character:
+
+ sprintf('%d %%', 100) # => "100 %"
+
+Flags do not apply.
+
+=== Reference by Name
+
+For more complex formatting, Ruby supports a reference by name.
+%<name>s style uses format style, but %{name} style doesn't.
+
+Examples:
+
+ sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 }) # => 1 : 2.000000
+ sprintf("%{foo}f", { :foo => 1 }) # => "1f"
diff --git a/doc/implicit_conversion.rdoc b/doc/implicit_conversion.rdoc
index 0c2a1d4971..ba15fa4bf4 100644
--- a/doc/implicit_conversion.rdoc
+++ b/doc/implicit_conversion.rdoc
@@ -2,6 +2,7 @@
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.
@@ -17,10 +18,15 @@ a specific conversion method:
=== 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 Ruby core class that satisfies these requirements is:
+
+* Array
+
The examples in this section use method <tt>Array#replace</tt>,
which accepts an Array-convertible argument.
@@ -66,10 +72,15 @@ This class is not Array-convertible (method +to_ary+ returns non-Array):
=== 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 Ruby core class that satisfies these requirements is:
+
+* Hash
+
The examples in this section use method <tt>Hash#merge</tt>,
which accepts a Hash-convertible argument.
@@ -115,10 +126,18 @@ This class is not Hash-convertible (method +to_hash+ returns non-Hash):
=== 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 Ruby core classes that satisfy these requirements are:
+
+* Integer
+* Float
+* Complex
+* Rational
+
The examples in this section use method <tt>Array.new</tt>,
which accepts an Integer-convertible argument.
@@ -159,6 +178,10 @@ A <i>String-convertible object</i> is an object that:
* The method accepts no arguments.
* The method returns an object +obj+ for which <tt>obj.kind_of?(String)</tt> returns +true+.
+The Ruby core class that satisfies these requirements is:
+
+* String
+
The examples in this section use method <tt>String::new</tt>,
which accepts a String-convertible argument.
diff --git a/doc/irb/irb.rd.ja b/doc/irb/irb.rd.ja
index 9d03651a8e..633c08cbd4 100644
--- a/doc/irb/irb.rd.ja
+++ b/doc/irb/irb.rd.ja
@@ -51,6 +51,12 @@ irbの使い方は, Rubyさえ知っていればいたって簡単です. 基本
オブジェクトの作成方法を 0 から 3 のいずれかに設定する.
--echo 実行結果を表示する(デフォルト).
--noecho 実行結果を表示しない.
+ --echo-on-assignment
+ 代入時に実行結果を表示する.
+ --noecho-on-assignment
+ 代入時に実行結果を表示しない.
+ --truncate-echo-on-assignment
+ 代入時に省略された実行結果を表示する(デフォルト).
--inspect 結果出力にinspectを用いる.
--noinspect 結果出力にinspectを用いない.
--singleline シングルラインエディタを利用する.
@@ -59,7 +65,10 @@ irbの使い方は, Rubyさえ知っていればいたって簡単です. 基本
用しようとする.
--colorize 色付けを利用する.
--nocolorize 色付けを利用しない.
- --prompt prompt-mode/--prompt-mode prompt-mode
+ --autocomplete オートコンプリートを利用する.
+ --noautocomplete オートコンプリートを利用しない.
+ --prompt prompt-mode
+ --prompt-mode prompt-mode
プロンプトモードを切替えます. 現在定義されているプ
ロンプトモードは, default, simple, xmp, inf-rubyが
用意されています.
diff --git a/doc/maintainers.rdoc b/doc/maintainers.rdoc
index dc893ecdf1..7e0c35194f 100644
--- a/doc/maintainers.rdoc
+++ b/doc/maintainers.rdoc
@@ -119,6 +119,10 @@ Yukihiro Matsumoto (matz)
Masatoshi SEKI (seki), Takashi Kokubun (k0kubun)
https://github.com/ruby/erb
https://rubygems.org/gems/erb
+[lib/error_highlight.rb, lib/error_highlight/*]
+ Yusuke Endoh (mame)
+ https://github.com/ruby/error_highlight
+ https://rubygems.org/gems/error_highlight
[lib/fileutils.rb]
_unmaintained_
https://github.com/ruby/fileutils
@@ -209,6 +213,10 @@ Yukihiro Matsumoto (matz)
Eric Hodel (drbrain), Hiroshi SHIBATA (hsbt)
https://github.com/ruby/rdoc
https://rubygems.org/gems/rdoc
+[lib/readline.rb]
+ aycabta
+ https://github.com/ruby/readline
+ https://rubygems.org/gems/readline
[lib/reline.rb, lib/reline/*]
aycabta
https://github.com/ruby/reline
@@ -391,3 +399,26 @@ Yukihiro Matsumoto (matz)
https://github.com/ruby/rbs
[typeprof]
https://github.com/ruby/typeprof
+
+=== Platform Maintainers
+
+[mswin64 (Microsoft Windows)]
+ NAKAMURA Usaku (usa)
+[mingw32 (Minimalist GNU for Windows)]
+ Nobuyoshi Nakada (nobu)
+[AIX]
+ Yutaka Kanemoto (kanemoto)
+[FreeBSD]
+ Akinori MUSHA (knu)
+[Solaris]
+ Naohisa Goto (ngoto)
+[RHEL, CentOS]
+ KOSAKI Motohiro (kosaki)
+[macOS]
+ Kenta Murata (mrkn)
+[OpenBSD]
+ Jeremy Evans (jeremyevans0)
+[cygwin, ...]
+ none. (Maintainer WANTED)
+[WebAssembly/WASI]
+ Yuta Saito (katei)
diff --git a/doc/make_cheatsheet.md b/doc/make_cheatsheet.md
deleted file mode 100644
index bf245bea03..0000000000
--- a/doc/make_cheatsheet.md
+++ /dev/null
@@ -1,124 +0,0 @@
-# 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 78a3d29d4a..abf9467262 100644
--- a/doc/marshal.rdoc
+++ b/doc/marshal.rdoc
@@ -83,7 +83,7 @@ The first byte has the following special values:
of stream objects full precision may be used.
"\xfc"::
- The total size of the integer is two bytes. The following four bytes are a
+ The total size of the integer is five bytes. The following four bytes are a
negative little-endian integer. For compatibility with 32 bit ruby,
only Fixnums greater than -10737341824 should be represented this way. For
sizes of stream objects full precision may be used.
diff --git a/doc/matchdata/begin.rdoc b/doc/matchdata/begin.rdoc
new file mode 100644
index 0000000000..8046dd9d55
--- /dev/null
+++ b/doc/matchdata/begin.rdoc
@@ -0,0 +1,30 @@
+Returns the offset (in characters) of the beginning of the specified match.
+
+When non-negative integer argument +n+ is given,
+returns the offset of the beginning of the <tt>n</tt>th match:
+
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ m[0] # => "HX1138"
+ m.begin(0) # => 1
+ m[3] # => "113"
+ m.begin(3) # => 3
+
+ m = /(т)(е)(с)/.match('тест')
+ # => #<MatchData "тес" 1:"т" 2:"е" 3:"с">
+ m[0] # => "тес"
+ m.begin(0) # => 0
+ m[3] # => "с"
+ m.begin(3) # => 2
+
+When string or symbol argument +name+ is given,
+returns the offset of the beginning for the named match:
+
+ m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
+ # => #<MatchData "hog" foo:"h" bar:"g">
+ m[:foo] # => "h"
+ m.begin('foo') # => 0
+ m[:bar] # => "g"
+ m.begin(:bar) # => 2
+
+Related: MatchData#end, MatchData#offset, MatchData#byteoffset.
diff --git a/doc/matchdata/end.rdoc b/doc/matchdata/end.rdoc
new file mode 100644
index 0000000000..0209b2d2fc
--- /dev/null
+++ b/doc/matchdata/end.rdoc
@@ -0,0 +1,30 @@
+Returns the offset (in characters) of the end of the specified match.
+
+When non-negative integer argument +n+ is given,
+returns the offset of the end of the <tt>n</tt>th match:
+
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ m[0] # => "HX1138"
+ m.end(0) # => 7
+ m[3] # => "113"
+ m.end(3) # => 6
+
+ m = /(т)(е)(с)/.match('тест')
+ # => #<MatchData "тес" 1:"т" 2:"е" 3:"с">
+ m[0] # => "тес"
+ m.end(0) # => 3
+ m[3] # => "с"
+ m.end(3) # => 3
+
+When string or symbol argument +name+ is given,
+returns the offset of the end for the named match:
+
+ m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
+ # => #<MatchData "hog" foo:"h" bar:"g">
+ m[:foo] # => "h"
+ m.end('foo') # => 1
+ m[:bar] # => "g"
+ m.end(:bar) # => 3
+
+Related: MatchData#begin, MatchData#offset, MatchData#byteoffset.
diff --git a/doc/matchdata/offset.rdoc b/doc/matchdata/offset.rdoc
new file mode 100644
index 0000000000..0985316d76
--- /dev/null
+++ b/doc/matchdata/offset.rdoc
@@ -0,0 +1,31 @@
+Returns a 2-element array containing the beginning and ending
+offsets (in characters) of the specified match.
+
+When non-negative integer argument +n+ is given,
+returns the starting and ending offsets of the <tt>n</tt>th match:
+
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ m[0] # => "HX1138"
+ m.offset(0) # => [1, 7]
+ m[3] # => "113"
+ m.offset(3) # => [3, 6]
+
+ m = /(т)(е)(с)/.match('тест')
+ # => #<MatchData "тес" 1:"т" 2:"е" 3:"с">
+ m[0] # => "тес"
+ m.offset(0) # => [0, 3]
+ m[3] # => "с"
+ m.offset(3) # => [2, 3]
+
+When string or symbol argument +name+ is given,
+returns the starting and ending offsets for the named match:
+
+ m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
+ # => #<MatchData "hog" foo:"h" bar:"g">
+ m[:foo] # => "h"
+ m.offset('foo') # => [0, 1]
+ m[:bar] # => "g"
+ m.offset(:bar) # => [2, 3]
+
+Related: MatchData#byteoffset, MatchData#begin, MatchData#end.
diff --git a/doc/math/math.rdoc b/doc/math/math.rdoc
new file mode 100644
index 0000000000..7a89df951c
--- /dev/null
+++ b/doc/math/math.rdoc
@@ -0,0 +1,117 @@
+\Module \Math provides methods for basic trigonometric,
+logarithmic, and transcendental functions, and for extracting roots.
+
+You can write its constants and method calls thus:
+
+ Math::PI # => 3.141592653589793
+ Math::E # => 2.718281828459045
+ Math.sin(0.0) # => 0.0
+ Math.cos(0.0) # => 1.0
+
+If you include module \Math, you can write simpler forms:
+
+ include Math
+ PI # => 3.141592653589793
+ E # => 2.718281828459045
+ sin(0.0) # => 0.0
+ cos(0.0) # => 1.0
+
+For simplicity, the examples here assume:
+
+ include Math
+ INFINITY = Float::INFINITY
+
+The domains and ranges for the methods
+are denoted by open or closed intervals,
+using, respectively, parentheses or square brackets:
+
+- An open interval does not include the endpoints:
+
+ (-INFINITY, INFINITY)
+
+- A closed interval includes the endpoints:
+
+ [-1.0, 1.0]
+
+- A half-open interval includes one endpoint, but not the other:
+
+ [1.0, INFINITY)
+
+Many values returned by \Math methods are numerical approximations.
+This is because many such values are, in mathematics,
+of infinite precision, while in numerical computation
+the precision is finite.
+
+Thus, in mathematics, <i>cos(π/2)</i> is exactly zero,
+but in our computation <tt>cos(PI/2)</tt> is a number very close to zero:
+
+ cos(PI/2) # => 6.123031769111886e-17
+
+For very large and very small returned values,
+we have added formatted numbers for clarity:
+
+ tan(PI/2) # => 1.633123935319537e+16 # 16331239353195370.0
+ tan(PI) # => -1.2246467991473532e-16 # -0.0000000000000001
+
+See class Float for the constants
+that affect Ruby's floating-point arithmetic.
+
+=== What's Here
+
+==== Trigonometric Functions
+
+- ::cos: Returns the cosine of the given argument.
+- ::sin: Returns the sine of the given argument.
+- ::tan: Returns the tangent of the given argument.
+
+==== Inverse Trigonometric Functions
+
+- ::acos: Returns the arc cosine of the given argument.
+- ::asin: Returns the arc sine of the given argument.
+- ::atan: Returns the arc tangent of the given argument.
+- ::atan2: Returns the arg tangent of two given arguments.
+
+==== Hyperbolic Trigonometric Functions
+
+- ::cosh: Returns the hyperbolic cosine of the given argument.
+- ::sinh: Returns the hyperbolic sine of the given argument.
+- ::tanh: Returns the hyperbolic tangent of the given argument.
+
+==== Inverse Hyperbolic Trigonometric Functions
+
+- ::acosh: Returns the inverse hyperbolic cosine of the given argument.
+- ::asinh: Returns the inverse hyperbolic sine of the given argument.
+- ::atanh: Returns the inverse hyperbolic tangent of the given argument.
+
+==== Exponentiation and Logarithmic Functions
+
+- ::exp: Returns the value of a given value raised to a given power.
+- ::log: Returns the logarithm of a given value in a given base.
+- ::log10: Returns the base 10 logarithm of the given argument.
+- ::log2: Returns the base 2 logarithm of the given argument.
+
+==== Fraction and Exponent Functions
+
+- ::frexp: Returns the fraction and exponent of the given argument.
+- ::ldexp: Returns the value for a given fraction and exponent.
+
+==== Root Functions
+
+- ::cbrt: Returns the cube root of the given argument.
+- ::sqrt: Returns the square root of the given argument.
+
+==== Error Functions
+
+- ::erf: Returns the value of the Gauss error function for the given argument.
+- ::erfc: Returns the value of the complementary error function
+ for the given argument.
+
+==== Gamma Functions
+
+- ::gamma: Returns the value of the gamma function for the given argument.
+- ::lgamma: Returns the value of the logarithmic gamma function
+ for the given argument.
+
+==== Hypotenuse Function
+
+- ::hypot: Returns <tt>sqrt(a**2 + b**2)</tt> for the given +a+ and +b+.
diff --git a/doc/memory_view.md b/doc/memory_view.md
index 646a35423a..0b1369163d 100644
--- a/doc/memory_view.md
+++ b/doc/memory_view.md
@@ -48,7 +48,7 @@ The MemoryView structure consists of the following members.
- `ssize_t byte_size`
- The numbero f bytes in the memory pointed by `data`.
+ The number of bytes in the memory pointed by `data`.
- `bool readonly`
@@ -56,7 +56,7 @@ The MemoryView structure consists of the following members.
- `const char *format`
- A string to describeth e format of an element, or NULL for unsigned byte.
+ A string to describe the format of an element, or NULL for unsigned byte.
- `ssize_t item_size`
@@ -89,7 +89,7 @@ The MemoryView structure consists of the following members.
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`
+- `void *private_data`
The private data that MemoryView provider uses internally.
This can be `NULL` when any private data is unnecessary.
diff --git a/doc/mjit/mjit.md b/doc/mjit/mjit.md
new file mode 100644
index 0000000000..6f19ab3ea7
--- /dev/null
+++ b/doc/mjit/mjit.md
@@ -0,0 +1,39 @@
+# MJIT
+
+This document has some tips that might be useful when you work on MJIT.
+
+## Supported platforms
+
+The following platforms are either tested on CI or assumed to work.
+
+* OS: Linux, macOS
+* Arch: x86\_64, aarch64, arm64, i686, i386
+
+### Not supported
+
+The MJIT support for the following platforms is no longer maintained.
+
+* OS: Windows (mswin, MinGW), Solaris
+* Arch: SPARC, s390x
+
+## Developing MJIT
+
+### Bindgen
+
+If you see an "MJIT bindgen" GitHub Actions failure, please commit the `git diff` shown on the failed job.
+
+For doing the same thing locally, run `make mjit-bindgen` after installing libclang.
+macOS seems to have libclang by default. On Ubuntu, you can install it with `apt install libclang1`.
+
+### Always run make install
+
+Always run `make install` before running MJIT. It could easily cause a SEGV if you don't.
+MJIT looks for the installed header for security reasons.
+
+### --mjit-debug vs --mjit-debug=-ggdb3
+
+`--mjit-debug=[flags]` allows you to specify arbitrary flags while keeping other compiler flags like `-O3`,
+which is useful for profiling benchmarks.
+
+`--mjit-debug` alone, on the other hand, disables `-O3` and adds debug flags.
+If you're debugging MJIT, what you need to use is not `--mjit-debug=-ggdb3` but `--mjit-debug`.
diff --git a/doc/net-http/examples.rdoc b/doc/net-http/examples.rdoc
new file mode 100644
index 0000000000..c1366e7ad1
--- /dev/null
+++ b/doc/net-http/examples.rdoc
@@ -0,0 +1,31 @@
+Examples here assume that <tt>net/http</tt> has been required
+(which also requires +uri+):
+
+ require 'net/http'
+
+Many code examples here use these example websites:
+
+- https://jsonplaceholder.typicode.com.
+- http://example.com.
+
+Some examples also assume these variables:
+
+ uri = URI('https://jsonplaceholder.typicode.com/')
+ uri.freeze # Examples may not modify.
+ hostname = uri.hostname # => "jsonplaceholder.typicode.com"
+ path = uri.path # => "/"
+ port = uri.port # => 443
+
+So that example requests may be written as:
+
+ Net::HTTP.get(uri)
+ Net::HTTP.get(hostname, '/index.html')
+ Net::HTTP.start(hostname) do |http|
+ http.get('/todos/1')
+ http.get('/todos/2')
+ end
+
+An example that needs a modified URI first duplicates +uri+, then modifies the duplicate:
+
+ _uri = uri.dup
+ _uri.path = '/todos/1'
diff --git a/doc/net-http/included_getters.rdoc b/doc/net-http/included_getters.rdoc
new file mode 100644
index 0000000000..7ac327f4b4
--- /dev/null
+++ b/doc/net-http/included_getters.rdoc
@@ -0,0 +1,3 @@
+This class also includes (indirectly) module Net::HTTPHeader,
+which gives access to its
+{methods for getting headers}[rdoc-ref:Net::HTTPHeader@Getters].
diff --git a/doc/optparse/.document b/doc/optparse/.document
new file mode 100644
index 0000000000..96dfc7779f
--- /dev/null
+++ b/doc/optparse/.document
@@ -0,0 +1 @@
+*.rdoc
diff --git a/doc/optparse/creates_option.rdoc b/doc/optparse/creates_option.rdoc
index 131c877971..ab672d5124 100644
--- a/doc/optparse/creates_option.rdoc
+++ b/doc/optparse/creates_option.rdoc
@@ -1,7 +1,7 @@
Creates an option from the given parameters +params+.
-See {Parameters for New Options}[./doc/optparse/option_params_rdoc.html].
+See {Parameters for New Options}[optparse/option_params.rdoc].
The block, if given, is the handler for the created option.
When the option is encountered during command-line parsing,
the block is called with the argument given for the option, if any.
-See {Option Handlers}[./option_params_rdoc.html#label-Option+Handlers].
+See {Option Handlers}[optparse/option_params.rdoc#label-Option+Handlers].
diff --git a/doc/optparse/option_params.rdoc b/doc/optparse/option_params.rdoc
index 3e6cb1be41..ace2c4283f 100644
--- a/doc/optparse/option_params.rdoc
+++ b/doc/optparse/option_params.rdoc
@@ -410,7 +410,7 @@ from the default \String to an instance of another class.
There are a number of built-in converters.
You can also define custom converters.
-See {Argument Converters}[./argument_converters_rdoc.html].
+See {Argument Converters}[./argument_converters.rdoc].
=== Descriptions
@@ -418,7 +418,7 @@ A description parameter is any string parameter
that is not recognized as an
{option name}[#label-Option+Names] or a
{terminator}[#label-Terminators];
-in other words, it does not begin with a hypnen.
+in other words, it does not begin with a hyphen.
You may give any number of description parameters;
each becomes a line in the text generated by option <tt>--help</tt>.
@@ -453,7 +453,7 @@ when the option is encountered. The handler may be:
==== Handler Blocks
-An option hadler may be a block.
+An option handler may be a block.
File +block.rb+ defines an option that has a handler block.
diff --git a/doc/optparse/tutorial.rdoc b/doc/optparse/tutorial.rdoc
index 1d7c52b19e..b95089826d 100644
--- a/doc/optparse/tutorial.rdoc
+++ b/doc/optparse/tutorial.rdoc
@@ -541,7 +541,7 @@ Executions:
[#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, Date]
You can also define custom converters.
-See {Argument Converters}[./argument_converters_rdoc.html]
+See {Argument Converters}[./argument_converters.rdoc]
for both built-in and custom converters.
=== Help
@@ -657,7 +657,7 @@ Though you may never need to call it directly,
here's the core method for defining an option:
- \Method \OptionParser#make_switch accepts an array of parameters and a block.
- See {Parameters for New Options}[./option_params_rdoc.html].
+ See {Parameters for New Options}[optparse/option_params.rdoc].
This method is unlike others here in that it:
- Accepts an <em>array of parameters</em>;
others accept a <em>sequence of parameter arguments</em>.
diff --git a/doc/packed_data.rdoc b/doc/packed_data.rdoc
new file mode 100644
index 0000000000..ec13b24c69
--- /dev/null
+++ b/doc/packed_data.rdoc
@@ -0,0 +1,590 @@
+== Packed \Data
+
+Certain Ruby core methods deal with packing and unpacking data:
+
+- \Method Array#pack:
+ Formats each element in array +self+ into a binary string;
+ returns that string.
+- \Method String#unpack:
+ Extracts data from string +self+,
+ forming objects that become the elements of a new array;
+ returns that array.
+- \Method String#unpack1:
+ Does the same, but unpacks and returns only the first extracted object.
+
+Each of these methods accepts a string +template+,
+consisting of zero or more _directive_ characters,
+each followed by zero or more _modifier_ characters.
+
+Examples (directive <tt>'C'</tt> specifies 'unsigned character'):
+
+ [65].pack('C') # => "A" # One element, one directive.
+ [65, 66].pack('CC') # => "AB" # Two elements, two directives.
+ [65, 66].pack('C') # => "A" # Extra element is ignored.
+ [65].pack('') # => "" # No directives.
+ [65].pack('CC') # Extra directive raises ArgumentError.
+
+ 'A'.unpack('C') # => [65] # One character, one directive.
+ 'AB'.unpack('CC') # => [65, 66] # Two characters, two directives.
+ 'AB'.unpack('C') # => [65] # Extra character is ignored.
+ 'A'.unpack('CC') # => [65, nil] # Extra directive generates nil.
+ 'AB'.unpack('') # => [] # No directives.
+
+The string +template+ may contain any mixture of valid directives
+(directive <tt>'c'</tt> specifies 'signed character'):
+
+ [65, -1].pack('cC') # => "A\xFF"
+ "A\xFF".unpack('cC') # => [65, 255]
+
+The string +template+ may contain whitespace (which is ignored)
+and comments, each of which begins with character <tt>'#'</tt>
+and continues up to and including the next following newline:
+
+ [0,1].pack(" C #foo \n C ") # => "\x00\x01"
+ "\0\1".unpack(" C #foo \n C ") # => [0, 1]
+
+Any directive may be followed by either of these modifiers:
+
+- <tt>'*'</tt> - The directive is to be applied as many times as needed:
+
+ [65, 66].pack('C*') # => "AB"
+ 'AB'.unpack('C*') # => [65, 66]
+
+- Integer +count+ - The directive is to be applied +count+ times:
+
+ [65, 66].pack('C2') # => "AB"
+ [65, 66].pack('C3') # Raises ArgumentError.
+ 'AB'.unpack('C2') # => [65, 66]
+ 'AB'.unpack('C3') # => [65, 66, nil]
+
+ Note: Directives in <tt>%w[A a Z m]</tt> use +count+ differently;
+ see {String Directives}[rdoc-ref:packed_data.rdoc@String+Directives].
+
+If elements don't fit the provided directive, only least significant bits are encoded:
+
+ [257].pack("C").unpack("C") # => [1]
+
+=== Packing \Method
+
+\Method Array#pack accepts optional keyword argument
++buffer+ that specifies the target string (instead of a new string):
+
+ [65, 66].pack('C*', buffer: 'foo') # => "fooAB"
+
+The method can accept a block:
+
+ # Packed string is passed to the block.
+ [65, 66].pack('C*') {|s| p s } # => "AB"
+
+=== Unpacking Methods
+
+Methods String#unpack and String#unpack1 each accept
+an optional keyword argument +offset+ that specifies an offset
+into the string:
+
+ 'ABC'.unpack('C*', offset: 1) # => [66, 67]
+ 'ABC'.unpack1('C*', offset: 1) # => 66
+
+Both methods can accept a block:
+
+ # Each unpacked object is passed to the block.
+ ret = []
+ "ABCD".unpack("C*") {|c| ret << c }
+ ret # => [65, 66, 67, 68]
+
+ # The single unpacked object is passed to the block.
+ 'AB'.unpack1('C*') {|ele| p ele } # => 65
+
+=== \Integer Directives
+
+Each integer directive specifies the packing or unpacking
+for one element in the input or output array.
+
+==== 8-Bit \Integer Directives
+
+- <tt>'c'</tt> - 8-bit signed integer
+ (like C <tt>signed char</tt>):
+
+ [0, 1, 255].pack('c*') # => "\x00\x01\xFF"
+ s = [0, 1, -1].pack('c*') # => "\x00\x01\xFF"
+ s.unpack('c*') # => [0, 1, -1]
+
+- <tt>'C'</tt> - 8-bit signed integer
+ (like C <tt>unsigned char</tt>):
+
+ [0, 1, 255].pack('C*') # => "\x00\x01\xFF"
+ s = [0, 1, -1].pack('C*') # => "\x00\x01\xFF"
+ s.unpack('C*') # => [0, 1, 255]
+
+==== 16-Bit \Integer Directives
+
+- <tt>'s'</tt> - 16-bit signed integer, native-endian
+ (like C <tt>int16_t</tt>):
+
+ [513, -514].pack('s*') # => "\x01\x02\xFE\xFD"
+ s = [513, 65022].pack('s*') # => "\x01\x02\xFE\xFD"
+ s.unpack('s*') # => [513, -514]
+
+- <tt>'S'</tt> - 16-bit unsigned integer, native-endian
+ (like C <tt>uint16_t</tt>):
+
+ [513, -514].pack('S*') # => "\x01\x02\xFE\xFD"
+ s = [513, 65022].pack('S*') # => "\x01\x02\xFE\xFD"
+ s.unpack('S*') # => [513, 65022]
+
+- <tt>'n'</tt> - 16-bit network integer, big-endian:
+
+ s = [0, 1, -1, 32767, -32768, 65535].pack('n*')
+ # => "\x00\x00\x00\x01\xFF\xFF\x7F\xFF\x80\x00\xFF\xFF"
+ s.unpack('n*')
+ # => [0, 1, 65535, 32767, 32768, 65535]
+
+- <tt>'v'</tt> - 16-bit VAX integer, little-endian:
+
+ s = [0, 1, -1, 32767, -32768, 65535].pack('v*')
+ # => "\x00\x00\x01\x00\xFF\xFF\xFF\x7F\x00\x80\xFF\xFF"
+ s.unpack('v*')
+ # => [0, 1, 65535, 32767, 32768, 65535]
+
+==== 32-Bit \Integer Directives
+
+- <tt>'l'</tt> - 32-bit signed integer, native-endian
+ (like C <tt>int32_t</tt>):
+
+ s = [67305985, -50462977].pack('l*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('l*')
+ # => [67305985, -50462977]
+
+- <tt>'L'</tt> - 32-bit unsigned integer, native-endian
+ (like C <tt>uint32_t</tt>):
+
+ s = [67305985, 4244504319].pack('L*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('L*')
+ # => [67305985, 4244504319]
+
+- <tt>'N'</tt> - 32-bit network integer, big-endian:
+
+ s = [0,1,-1].pack('N*')
+ # => "\x00\x00\x00\x00\x00\x00\x00\x01\xFF\xFF\xFF\xFF"
+ s.unpack('N*')
+ # => [0, 1, 4294967295]
+
+- <tt>'V'</tt> - 32-bit VAX integer, little-endian:
+
+ s = [0,1,-1].pack('V*')
+ # => "\x00\x00\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF"
+ s.unpack('v*')
+ # => [0, 0, 1, 0, 65535, 65535]
+
+==== 64-Bit \Integer Directives
+
+- <tt>'q'</tt> - 64-bit signed integer, native-endian
+ (like C <tt>int64_t</tt>):
+
+ s = [578437695752307201, -506097522914230529].pack('q*')
+ # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8"
+ s.unpack('q*')
+ # => [578437695752307201, -506097522914230529]
+
+- <tt>'Q'</tt> - 64-bit unsigned integer, native-endian
+ (like C <tt>uint64_t</tt>):
+
+ s = [578437695752307201, 17940646550795321087].pack('Q*')
+ # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8"
+ s.unpack('Q*')
+ # => [578437695752307201, 17940646550795321087]
+
+==== Platform-Dependent \Integer Directives
+
+- <tt>'i'</tt> - Platform-dependent width signed integer,
+ native-endian (like C <tt>int</tt>):
+
+ s = [67305985, -50462977].pack('i*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('i*')
+ # => [67305985, -50462977]
+
+- <tt>'I'</tt> - Platform-dependent width unsigned integer,
+ native-endian (like C <tt>unsigned int</tt>):
+
+ s = [67305985, -50462977].pack('I*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('I*')
+ # => [67305985, 4244504319]
+
+==== Pointer Directives
+
+- <tt>'j'</tt> - 64-bit pointer-width signed integer,
+ native-endian (like C <tt>intptr_t</tt>):
+
+ s = [67305985, -50462977].pack('j*')
+ # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\xFF\xFF\xFF\xFF"
+ s.unpack('j*')
+ # => [67305985, -50462977]
+
+- <tt>'j'</tt> - 64-bit pointer-width unsigned integer,
+ native-endian (like C <tt>uintptr_t</tt>):
+
+ s = [67305985, 4244504319].pack('J*')
+ # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\x00\x00\x00\x00"
+ s.unpack('J*')
+ # => [67305985, 4244504319]
+
+==== Other \Integer Directives
+:
+- <tt>'U'</tt> - UTF-8 character:
+
+ s = [4194304].pack('U*')
+ # => "\xF8\x90\x80\x80\x80"
+ s.unpack('U*')
+ # => [4194304]
+
+- <tt>'w'</tt> - BER-encoded integer
+ (see {BER enocding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]):
+
+ s = [1073741823].pack('w*')
+ # => "\x83\xFF\xFF\xFF\x7F"
+ s.unpack('w*')
+ # => [1073741823]
+
+==== Modifiers for \Integer Directives
+
+For directives in
+<tt>'i'</tt>,
+<tt>'I'</tt>,
+<tt>'s'</tt>,
+<tt>'S'</tt>,
+<tt>'l'</tt>,
+<tt>'L'</tt>,
+<tt>'q'</tt>,
+<tt>'Q'</tt>,
+<tt>'j'</tt>, and
+<tt>'J'</tt>,
+these modifiers may be suffixed:
+
+- <tt>'!'</tt> or <tt>'_'</tt> - Underlying platform’s native size.
+- <tt>'>'</tt> - Big-endian.
+- <tt>'<'</tt> - Little-endian.
+
+=== \Float Directives
+
+Each float directive specifies the packing or unpacking
+for one element in the input or output array.
+
+==== Single-Precision \Float Directives
+
+- <tt>'F'</tt> or <tt>'f'</tt> - Native format:
+
+ s = [3.0].pack('F') # => "\x00\x00@@"
+ s.unpack('F') # => [3.0]
+
+- <tt>'e'</tt> - Little-endian:
+
+ s = [3.0].pack('e') # => "\x00\x00@@"
+ s.unpack('e') # => [3.0]
+
+- <tt>'g'</tt> - Big-endian:
+
+ s = [3.0].pack('g') # => "@@\x00\x00"
+ s.unpack('g') # => [3.0]
+
+==== Double-Precision \Float Directives
+
+- <tt>'D'</tt> or <tt>'d'</tt> - Native format:
+
+ s = [3.0].pack('D') # => "\x00\x00\x00\x00\x00\x00\b@"
+ s.unpack('D') # => [3.0]
+
+- <tt>'E'</tt> - Little-endian:
+
+ s = [3.0].pack('E') # => "\x00\x00\x00\x00\x00\x00\b@"
+ s.unpack('E') # => [3.0]
+
+- <tt>'G'</tt> - Big-endian:
+
+ s = [3.0].pack('G') # => "@\b\x00\x00\x00\x00\x00\x00"
+ s.unpack('G') # => [3.0]
+
+A float directive may be infinity or not-a-number:
+
+ inf = 1.0/0.0 # => Infinity
+ [inf].pack('f') # => "\x00\x00\x80\x7F"
+ "\x00\x00\x80\x7F".unpack('f') # => [Infinity]
+
+ nan = inf/inf # => NaN
+ [nan].pack('f') # => "\x00\x00\xC0\x7F"
+ "\x00\x00\xC0\x7F".unpack('f') # => [NaN]
+
+=== \String Directives
+
+Each string directive specifies the packing or unpacking
+for one byte in the input or output string.
+
+==== Binary \String Directives
+
+- <tt>'A'</tt> - Arbitrary binary string (space padded; count is width);
+ +nil+ is treated as the empty string:
+
+ ['foo'].pack('A') # => "f"
+ ['foo'].pack('A*') # => "foo"
+ ['foo'].pack('A2') # => "fo"
+ ['foo'].pack('A4') # => "foo "
+ [nil].pack('A') # => " "
+ [nil].pack('A*') # => ""
+ [nil].pack('A2') # => " "
+ [nil].pack('A4') # => " "
+
+ "foo\0".unpack('A') # => ["f"]
+ "foo\0".unpack('A4') # => ["foo"]
+ "foo\0bar".unpack('A10') # => ["foo\x00bar"] # Reads past "\0".
+ "foo ".unpack('A') # => ["f"]
+ "foo ".unpack('A4') # => ["foo"]
+ "foo".unpack('A4') # => ["foo"]
+
+ russian = "\u{442 435 441 442}" # => "тест"
+ russian.size # => 4
+ russian.bytesize # => 8
+ [russian].pack('A') # => "\xD1"
+ [russian].pack('A*') # => "\xD1\x82\xD0\xB5\xD1\x81\xD1\x82"
+ russian.unpack('A') # => ["\xD1"]
+ russian.unpack('A2') # => ["\xD1\x82"]
+ russian.unpack('A4') # => ["\xD1\x82\xD0\xB5"]
+ russian.unpack('A*') # => ["\xD1\x82\xD0\xB5\xD1\x81\xD1\x82"]
+
+- <tt>'a'</tt> - Arbitrary binary string (null padded; count is width):
+
+ ["foo"].pack('a') # => "f"
+ ["foo"].pack('a*') # => "foo"
+ ["foo"].pack('a2') # => "fo"
+ ["foo\0"].pack('a4') # => "foo\x00"
+ [nil].pack('a') # => "\x00"
+ [nil].pack('a*') # => ""
+ [nil].pack('a2') # => "\x00\x00"
+ [nil].pack('a4') # => "\x00\x00\x00\x00"
+
+ "foo\0".unpack('a') # => ["f"]
+ "foo\0".unpack('a4') # => ["foo\x00"]
+ "foo ".unpack('a4') # => ["foo "]
+ "foo".unpack('a4') # => ["foo"]
+ "foo\0bar".unpack('a4') # => ["foo\x00"] # Reads past "\0".
+
+- <tt>'Z'</tt> - Same as <tt>'a'</tt>,
+ except that null is added or ignored with <tt>'*'</tt>:
+
+ ["foo"].pack('Z*') # => "foo\x00"
+ [nil].pack('Z*') # => "\x00"
+
+ "foo\0".unpack('Z*') # => ["foo"]
+ "foo".unpack('Z*') # => ["foo"]
+ "foo\0bar".unpack('Z*') # => ["foo"] # Does not read past "\0".
+
+==== Bit \String Directives
+
+- <tt>'B'</tt> - Bit string (high byte first):
+
+ ['11111111' + '00000000'].pack('B*') # => "\xFF\x00"
+ ['10000000' + '01000000'].pack('B*') # => "\x80@"
+
+ ['1'].pack('B0') # => ""
+ ['1'].pack('B1') # => "\x80"
+ ['1'].pack('B2') # => "\x80\x00"
+ ['1'].pack('B3') # => "\x80\x00"
+ ['1'].pack('B4') # => "\x80\x00\x00"
+ ['1'].pack('B5') # => "\x80\x00\x00"
+ ['1'].pack('B6') # => "\x80\x00\x00\x00"
+
+ "\xff\x00".unpack("B*") # => ["1111111100000000"]
+ "\x01\x02".unpack("B*") # => ["0000000100000010"]
+
+ "".unpack("B0") # => [""]
+ "\x80".unpack("B1") # => ["1"]
+ "\x80".unpack("B2") # => ["10"]
+ "\x80".unpack("B3") # => ["100"]
+
+- <tt>'b'</tt> - Bit string (low byte first):
+
+ ['11111111' + '00000000'].pack('b*') # => "\xFF\x00"
+ ['10000000' + '01000000'].pack('b*') # => "\x01\x02"
+
+ ['1'].pack('b0') # => ""
+ ['1'].pack('b1') # => "\x01"
+ ['1'].pack('b2') # => "\x01\x00"
+ ['1'].pack('b3') # => "\x01\x00"
+ ['1'].pack('b4') # => "\x01\x00\x00"
+ ['1'].pack('b5') # => "\x01\x00\x00"
+ ['1'].pack('b6') # => "\x01\x00\x00\x00"
+
+ "\xff\x00".unpack("b*") # => ["1111111100000000"]
+ "\x01\x02".unpack("b*") # => ["1000000001000000"]
+
+ "".unpack("b0") # => [""]
+ "\x01".unpack("b1") # => ["1"]
+ "\x01".unpack("b2") # => ["10"]
+ "\x01".unpack("b3") # => ["100"]
+
+==== Hex \String Directives
+
+- <tt>'H'</tt> - Hex string (high nibble first):
+
+ ['10ef'].pack('H*') # => "\x10\xEF"
+ ['10ef'].pack('H0') # => ""
+ ['10ef'].pack('H3') # => "\x10\xE0"
+ ['10ef'].pack('H5') # => "\x10\xEF\x00"
+
+ ['fff'].pack('H3') # => "\xFF\xF0"
+ ['fff'].pack('H4') # => "\xFF\xF0"
+ ['fff'].pack('H5') # => "\xFF\xF0\x00"
+ ['fff'].pack('H6') # => "\xFF\xF0\x00"
+ ['fff'].pack('H7') # => "\xFF\xF0\x00\x00"
+ ['fff'].pack('H8') # => "\xFF\xF0\x00\x00"
+
+ "\x10\xef".unpack('H*') # => ["10ef"]
+ "\x10\xef".unpack('H0') # => [""]
+ "\x10\xef".unpack('H1') # => ["1"]
+ "\x10\xef".unpack('H2') # => ["10"]
+ "\x10\xef".unpack('H3') # => ["10e"]
+ "\x10\xef".unpack('H4') # => ["10ef"]
+ "\x10\xef".unpack('H5') # => ["10ef"]
+
+- <tt>'h'</tt> - Hex string (low nibble first):
+
+ ['10ef'].pack('h*') # => "\x01\xFE"
+ ['10ef'].pack('h0') # => ""
+ ['10ef'].pack('h3') # => "\x01\x0E"
+ ['10ef'].pack('h5') # => "\x01\xFE\x00"
+
+ ['fff'].pack('h3') # => "\xFF\x0F"
+ ['fff'].pack('h4') # => "\xFF\x0F"
+ ['fff'].pack('h5') # => "\xFF\x0F\x00"
+ ['fff'].pack('h6') # => "\xFF\x0F\x00"
+ ['fff'].pack('h7') # => "\xFF\x0F\x00\x00"
+ ['fff'].pack('h8') # => "\xFF\x0F\x00\x00"
+
+ "\x01\xfe".unpack('h*') # => ["10ef"]
+ "\x01\xfe".unpack('h0') # => [""]
+ "\x01\xfe".unpack('h1') # => ["1"]
+ "\x01\xfe".unpack('h2') # => ["10"]
+ "\x01\xfe".unpack('h3') # => ["10e"]
+ "\x01\xfe".unpack('h4') # => ["10ef"]
+ "\x01\xfe".unpack('h5') # => ["10ef"]
+
+==== Pointer \String Directives
+
+- <tt>'P'</tt> - Pointer to a structure (fixed-length string):
+
+ s = ['abc'].pack('P') # => "\xE0O\x7F\xE5\xA1\x01\x00\x00"
+ s.unpack('P*') # => ["abc"]
+ ".".unpack("P") # => []
+ ("\0" * 8).unpack("P") # => [nil]
+ [nil].pack("P") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
+
+- <tt>'p'</tt> - Pointer to a null-terminated string:
+
+ s = ['abc'].pack('p') # => "(\xE4u\xE5\xA1\x01\x00\x00"
+ s.unpack('p*') # => ["abc"]
+ ".".unpack("p") # => []
+ ("\0" * 8).unpack("p") # => [nil]
+ [nil].pack("p") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
+
+==== Other \String Directives
+
+- <tt>'M'</tt> - Quoted printable, MIME encoding;
+ text mode, but input must use LF and output LF;
+ (see {RFC 2045}[https://www.ietf.org/rfc/rfc2045.txt]):
+
+ ["a b c\td \ne"].pack('M') # => "a b c\td =\n\ne=\n"
+ ["\0"].pack('M') # => "=00=\n"
+
+ ["a"*1023].pack('M') == ("a"*73+"=\n")*14+"a=\n" # => true
+ ("a"*73+"=\na=\n").unpack('M') == ["a"*74] # => true
+ (("a"*73+"=\n")*14+"a=\n").unpack('M') == ["a"*1023] # => true
+
+ "a b c\td =\n\ne=\n".unpack('M') # => ["a b c\td \ne"]
+ "=00=\n".unpack('M') # => ["\x00"]
+
+ "pre=31=32=33after".unpack('M') # => ["pre123after"]
+ "pre=\nafter".unpack('M') # => ["preafter"]
+ "pre=\r\nafter".unpack('M') # => ["preafter"]
+ "pre=".unpack('M') # => ["pre="]
+ "pre=\r".unpack('M') # => ["pre=\r"]
+ "pre=hoge".unpack('M') # => ["pre=hoge"]
+ "pre==31after".unpack('M') # => ["pre==31after"]
+ "pre===31after".unpack('M') # => ["pre===31after"]
+
+- <tt>'m'</tt> - Base64 encoded string;
+ count specifies input bytes between each newline,
+ rounded down to nearest multiple of 3;
+ if count is zero, no newlines are added;
+ (see {RFC 4648}[https://www.ietf.org/rfc/rfc4648.txt]):
+
+ [""].pack('m') # => ""
+ ["\0"].pack('m') # => "AA==\n"
+ ["\0\0"].pack('m') # => "AAA=\n"
+ ["\0\0\0"].pack('m') # => "AAAA\n"
+ ["\377"].pack('m') # => "/w==\n"
+ ["\377\377"].pack('m') # => "//8=\n"
+ ["\377\377\377"].pack('m') # => "////\n"
+
+ "".unpack('m') # => [""]
+ "AA==\n".unpack('m') # => ["\x00"]
+ "AAA=\n".unpack('m') # => ["\x00\x00"]
+ "AAAA\n".unpack('m') # => ["\x00\x00\x00"]
+ "/w==\n".unpack('m') # => ["\xFF"]
+ "//8=\n".unpack('m') # => ["\xFF\xFF"]
+ "////\n".unpack('m') # => ["\xFF\xFF\xFF"]
+ "A\n".unpack('m') # => [""]
+ "AA\n".unpack('m') # => ["\x00"]
+ "AA=\n".unpack('m') # => ["\x00"]
+ "AAA\n".unpack('m') # => ["\x00\x00"]
+
+ [""].pack('m0') # => ""
+ ["\0"].pack('m0') # => "AA=="
+ ["\0\0"].pack('m0') # => "AAA="
+ ["\0\0\0"].pack('m0') # => "AAAA"
+ ["\377"].pack('m0') # => "/w=="
+ ["\377\377"].pack('m0') # => "//8="
+ ["\377\377\377"].pack('m0') # => "////"
+
+ "".unpack('m0') # => [""]
+ "AA==".unpack('m0') # => ["\x00"]
+ "AAA=".unpack('m0') # => ["\x00\x00"]
+ "AAAA".unpack('m0') # => ["\x00\x00\x00"]
+ "/w==".unpack('m0') # => ["\xFF"]
+ "//8=".unpack('m0') # => ["\xFF\xFF"]
+ "////".unpack('m0') # => ["\xFF\xFF\xFF"]
+
+- <tt>'u'</tt> - UU-encoded string:
+
+ [0].pack("U") # => "\u0000"
+ [0x3fffffff].pack("U") # => "\xFC\xBF\xBF\xBF\xBF\xBF"
+ [0x40000000].pack("U") # => "\xFD\x80\x80\x80\x80\x80"
+ [0x7fffffff].pack("U") # => "\xFD\xBF\xBF\xBF\xBF\xBF"
+
+=== Offset Directives
+
+- <tt>'@'</tt> - Begin packing at the given byte offset;
+ for packing, null fill if necessary:
+
+ [1, 2].pack("C@0C") # => "\x02"
+ [1, 2].pack("C@1C") # => "\x01\x02"
+ [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02"
+
+ "\x01\x00\x00\x02".unpack("C@3C") # => [1, 2]
+ "\x00".unpack("@1C") # => [nil]
+
+- <tt>'X'</tt> - Back up a byte:
+
+ [0, 1, 2].pack("CCXC") # => "\x00\x02"
+ [0, 1, 2].pack("CCX2C") # => "\x02"
+ "\x00\x02".unpack("CCXC") # => [0, 2, 2]
+
+=== Null Byte Direcive
+
+- <tt>'x'</tt> - Null byte:
+
+ [].pack("x0") # => ""
+ [].pack("x") # => "\x00"
+ [].pack("x8") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x02".unpack("CxC") # => [0, 2]
diff --git a/doc/ractor.md b/doc/ractor.md
index 1c77f50e36..843754c263 100644
--- a/doc/ractor.md
+++ b/doc/ractor.md
@@ -179,7 +179,7 @@ end
Communication between Ractors is achieved by sending and receiving messages. There are two ways to communicate with each other.
* (1) Message sending/receiving
- * (1-1) push type send/receive (sender knows receiver). similar to the Actor model.
+ * (1-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))
@@ -202,7 +202,7 @@ For message sending and receiving, there are two types of APIs: push type and pu
* 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
+* There are 3 ways to send an object as a message
* (1) Send a reference: Sending a shareable object, send only a reference to the object (fast)
* (2) Copy an object: Sending an unshareable object by copying an object deeply (slow). Note that you can not send an object which does not support deep copy. Some `T_DATA` objects are not supported.
* (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copies references of sending object to moved object.
@@ -565,27 +565,48 @@ Note that some special global variables are ractor-local, like `$stdin`, `$stdou
### Instance variables of shareable objects
-Only the main Ractor can access instance variables of shareable objects.
+Instance variables of classes/modules can be get from non-main Ractors if the referring values are shareable objects.
```ruby
class C
- @iv = 'str'
+ @iv = 1
end
-r = Ractor.new do
+p Ractor.new do
class C
- p @iv
+ @iv
end
-end
+end.take #=> 1
+```
+Otherwise, only the main Ractor can access instance variables of shareable objects.
-begin
- r.take
-rescue => e
- e.class #=> Ractor::IsolationError
+```ruby
+class C
+ @iv = [] # unshareable object
end
+
+Ractor.new do
+ class C
+ begin
+ p @iv
+ rescue Ractor::IsolationError
+ p $!.message
+ #=> "can not get unshareable values from instance variables of classes/modules from non-main Ractors"
+ end
+
+ begin
+ @iv = 42
+ rescue Ractor::IsolationError
+ p $!.message
+ #=> "can not set instance variables of classes/modules by non-main Ractors"
+ end
+ end
+end.take
```
+
+
```ruby
shared = Ractor.new{}
shared.instance_variable_set(:@iv, 'str')
@@ -674,7 +695,7 @@ TABLE = Ractor.make_shareable( {a: 'ko1', b: 'ko2', c: 'ko3'} )
To make it easy, Ruby 3.0 introduced new `shareable_constant_value` Directive.
```ruby
-shareable_constant_value: literal
+# shareable_constant_value: literal
TABLE = {a: 'ko1', b: 'ko2', c: 'ko3'}
#=> Same as: TABLE = Ractor.make_shareable( {a: 'ko1', b: 'ko2', c: 'ko3'} )
diff --git a/doc/rdoc/markup_reference.rb b/doc/rdoc/markup_reference.rb
new file mode 100644
index 0000000000..66ec6786c0
--- /dev/null
+++ b/doc/rdoc/markup_reference.rb
@@ -0,0 +1,1257 @@
+require 'rdoc'
+
+# \Class \RDoc::MarkupReference exists only to provide a suitable home
+# for a reference document for \RDoc markup.
+#
+# All objects defined in this class -- classes, modules, methods, aliases,
+# attributes, and constants -- are solely for illustrating \RDoc markup,
+# and have no other legitimate use.
+#
+# = \RDoc Markup Reference
+#
+# Notes:
+#
+# - Examples in this reference are Ruby code and comments;
+# certain differences from other sources
+# (such as C code and comments) are noted.
+# - An example that shows rendered HTML output
+# displays that output in a blockquote:
+#
+# Rendered HTML:
+# >>>
+# Some stuff
+#
+# \RDoc-generated documentation is derived from and controlled by:
+#
+# - Single-line or multi-line comments that precede certain definitions;
+# see {Markup in Comments}[rdoc-ref:RDoc::MarkupReference@Markup+in+Comments].
+# - \RDoc directives in trailing comments (on the same line as code);
+# see <tt>:nodoc:</tt>, <tt>:doc:</tt>, and <tt>:notnew</tt>.
+# - \RDoc directives in single-line comments;
+# see other {Directives}[rdoc-ref:RDoc::MarkupReference@Directives].
+# - The Ruby code itself (but not from C code);
+# see {Documentation Derived from Ruby Code}[rdoc-ref:RDoc::MarkupReference@Documentation+Derived+from+Ruby+Code].
+#
+# == Markup in Comments
+#
+# The treatment of markup in comments varies according to the type of file:
+#
+# - <tt>.rb</tt> (Ruby code file): markup is parsed from Ruby comments.
+# - <tt>.c</tt> (C code file): markup is parsed from C comments.
+# - <tt>.rdoc</tt> (RDoc text file): markup is parsed from the entire file.
+#
+# The comment associated with
+# a Ruby class, module, method, alias, constant, or attribute
+# becomes the documentation for that defined object:
+#
+# - In a Ruby file, that comment immediately precedes
+# the definition of the object.
+# - In a C file, that comment immediately precedes
+# the function that implements a method,
+# or otherwise immediately precedes the definition of the object.
+#
+# In either a Ruby or a C file,
+# \RDoc ignores comments that do not precede object definitions.
+#
+# In an \RDoc file, the text is not associated with any code object,
+# but may (depending on how the documentation is built),
+# become a separate page.
+#
+# Almost all examples on this page are all RDoc-like;
+# that is, they have no comment markers like Ruby <tt>#</tt>
+# or C <tt>/* ... */</tt>.
+#
+# === Margins
+#
+# In a multi-line comment,
+# \RDoc looks for the comment's natural left margin,
+# which becomes the <em>base margin</em> for the comment
+# and is the initial <em>current margin</em> for for the comment.
+#
+# The current margin can change, and does so, for example in a list.
+#
+# === Blocks
+#
+# It's convenient to think of \RDoc markup input as a sequence of _blocks_
+# of various types (details at the links):
+#
+# - {Paragraph}[rdoc-ref:RDoc::MarkupReference@Paragraphs]:
+# an ordinary paragraph.
+# - {Verbatim text block}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks]:
+# a block of text to be rendered literally.
+# - {Code block}[rdoc-ref:RDoc::MarkupReference@Code+Blocks]:
+# a verbatim text block containing Ruby code,
+# to be rendered with code highlighting.
+# - {Block quote}[rdoc-ref:RDoc::MarkupReference@Block+Quotes]:
+# a longish quoted passage, to be rendered with indentation
+# instead of quote marks.
+# - {List}[rdoc-ref:RDoc::MarkupReference@Lists]: items for
+# a bullet list, numbered list, lettered list, or labeled list.
+# - {Heading}[rdoc-ref:RDoc::MarkupReference@Headings]:
+# a section heading.
+# - {Horizontal rule}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]:
+# a line across the rendered page.
+# - {Directive}[rdoc-ref:RDoc::MarkupReference@Directives]:
+# various special directions for the rendering.
+# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]:
+# text to be rendered in a special way.
+#
+# About the blocks:
+#
+# - Except for a paragraph, a block is distinguished by its indentation,
+# or by unusual initial or embedded characters.
+# - Any block may appear independently
+# (that is, not nested in another block);
+# some blocks may be nested, as detailed below.
+#
+# ==== Paragraphs
+#
+# A paragraph consists of one or more non-empty lines of ordinary text,
+# each beginning at the current margin.
+#
+# Note: Here, <em>ordinary text</em> means text that is <em>not identified</em>
+# by indentation, or by unusual initial or embedded characters.
+# See below.
+#
+# Paragraphs are separated by one or more empty lines.
+#
+# Example input:
+#
+# \RDoc produces HTML and command-line documentation for Ruby projects.
+# \RDoc includes the rdoc and ri tools for generating and displaying
+# documentation from the command-line.
+#
+# You'll love it.
+#
+# Rendered HTML:
+# >>>
+# \RDoc produces HTML and command-line documentation for Ruby projects.
+# \RDoc includes the rdoc and ri tools for generating and displaying
+# documentation from the command-line.
+#
+# You'll love it.
+#
+# A paragraph may contain nested blocks, including:
+#
+# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks].
+# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks].
+# - {Block quotes}[rdoc-ref:RDoc::MarkupReference@Block+Quotes].
+# - {Lists}[rdoc-ref:RDoc::MarkupReference@Lists].
+# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings].
+# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules].
+# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
+#
+# ==== Verbatim Text Blocks
+#
+# Text indented farther than the current margin becomes a <em>verbatim text block</em>
+# (or a code block, described next).
+# In the rendered HTML, such text:
+#
+# - Is indented.
+# - Has a contrasting background color.
+#
+# The verbatim text block ends at the first line beginning at the current margin.
+#
+# Example input:
+#
+# This is not verbatim text.
+#
+# This is verbatim text.
+# Whitespace is honored. # See?
+# Whitespace is honored. # See?
+#
+# This is still the same verbatim text block.
+#
+# This is not verbatim text.
+#
+# Rendered HTML:
+# >>>
+# This is not verbatim text.
+#
+# This is verbatim text.
+# Whitespace is honored. # See?
+# Whitespace is honored. # See?
+#
+# This is still the same verbatim text block.
+#
+# This is not verbatim text.
+#
+# A verbatim text block may not contain nested blocks of any kind
+# -- it's verbatim.
+#
+# ==== Code Blocks
+#
+# A special case of verbatim text is the <em>code block</em>,
+# which is merely verbatim text that \RDoc recognizes as Ruby code:
+#
+# In the rendered HTML, the code block:
+#
+# - Is indented.
+# - Has a contrasting background color.
+# - Has syntax highlighting.
+#
+# Example input:
+#
+# Consider this method:
+#
+# def foo(name = '', value = 0)
+# @name = name # Whitespace is still honored.
+# @value = value
+# end
+#
+#
+# Rendered HTML:
+# >>>
+# Consider this method:
+#
+# def foo(name = '', value = 0)
+# @name = name # Whitespace is still honored.
+# @value = value
+# end
+#
+# Pro tip: If your indented Ruby code does not get highlighted,
+# it may contain a syntax error.
+#
+# A code block may not contain nested blocks of any kind
+# -- it's verbatim.
+#
+# ==== Block Quotes
+#
+# You can use the characters <tt>>>></tt> (unindented),
+# followed by indented text, to treat the text
+# as a {block quote}[https://en.wikipedia.org/wiki/Block_quotation]:
+#
+# Example input:
+#
+# Here's a block quote:
+# >>>
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
+# commodo quam iaculis massa posuere, dictum fringilla justo pulvinar.
+# Quisque turpis erat, pharetra eu dui at, sollicitudin accumsan nulla.
+#
+# Aenean congue ligula eu ligula molestie, eu pellentesque purus
+# faucibus. In id leo non ligula condimentum lobortis. Duis vestibulum,
+# diam in pellentesque aliquet, mi tellus placerat sapien, id euismod
+# purus magna ut tortor.
+#
+# Rendered HTML:
+#
+# >>>
+# Here's a block quote:
+# >>>
+# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
+# commodo quam iaculis massa posuere, dictum fringilla justo pulvinar.
+# Quisque turpis erat, pharetra eu dui at, sollicitudin accumsan nulla.
+#
+# Aenean congue ligula eu ligula molestie, eu pellentesque purus
+# faucibus. In id leo non ligula condimentum lobortis. Duis vestibulum,
+# diam in pellentesque aliquet, mi tellus placerat sapien, id euismod
+# purus magna ut tortor.
+#
+# Note that, unlike verbatim text, single newlines are not honored,
+# but that a double newline begins a new paragraph in the block quote.
+#
+# A block quote may contain nested blocks, including:
+#
+# - Other block quotes.
+# - {Paragraphs}[rdoc-ref:RDoc::MarkupReference@Paragraphs].
+# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks].
+# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks].
+# - {Lists}[rdoc-ref:RDoc::MarkupReference@Lists].
+# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings].
+# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules].
+# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
+#
+# ==== Lists
+#
+# Each type of list item is marked by a special beginning:
+#
+# - Bullet list item: Begins with a hyphen or asterisk.
+# - Numbered list item: Begins with digits and a period.
+# - Lettered list item: Begins with an alphabetic character and a period.
+# - Labeled list item: Begins with one of:
+# - Square-bracketed text.
+# - A word followed by two colons.
+#
+# A list begins with a list item and continues, even across blank lines,
+# as long as list items of the same type are found at the same indentation level.
+#
+# A new list resets the current margin inward.
+# Additional lines of text aligned at that margin
+# are part of the continuing list item.
+#
+# A list item may be continued on additional lines that are aligned
+# with the first line. See examples below.
+#
+# A list item may contain nested blocks, including:
+#
+# - Other lists of any type.
+# - {Paragraphs}[rdoc-ref:RDoc::MarkupReference@Paragraphs].
+# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks].
+# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks].
+# - {Block quotes}[rdoc-ref:RDoc::MarkupReference@Block+Quotes].
+# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings].
+# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules].
+# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
+#
+# ===== Bullet Lists
+#
+# A bullet list item begins with a hyphen or asterisk.
+#
+# Example input:
+#
+# - An item.
+# - Another.
+# - An item spanning
+# multiple lines.
+#
+# * Yet another.
+# - Last one.
+#
+# Rendered HTML:
+# >>>
+# - An item.
+# - Another.
+# - An item spanning
+# multiple lines.
+#
+# * Yet another.
+# - Last one.
+#
+# ===== Numbered Lists
+#
+# A numbered list item begins with digits and a period.
+#
+# The items are automatically re-numbered.
+#
+# Example input:
+#
+# 100. An item.
+# 10. Another.
+# 1. An item spanning
+# multiple lines.
+#
+# 1. Yet another.
+# 1000. Last one.
+#
+# Rendered HTML:
+# >>>
+# 100. An item.
+# 10. Another.
+# 1. An item spanning
+# multiple lines.
+#
+# 1. Yet another.
+# 1000. Last one.
+#
+# ===== Lettered Lists
+#
+# A numbered list item begins with a letters and a period.
+#
+# The items are automatically "re-lettered."
+#
+# Example input:
+#
+# z. An item.
+# y. Another.
+# x. An item spanning
+# multiple lines.
+#
+# x. Yet another.
+# a. Last one.
+#
+# Rendered HTML:
+# >>>
+# z. An item.
+# y. Another.
+#
+# x. Yet another.
+# a. Last one.
+#
+# ===== Labeled Lists
+#
+# A labeled list item begins with one of:
+#
+# - Square-bracketed text: the label and text are on two lines.
+# - A word followed by two colons: the label and text are on the same line.
+#
+# Example input:
+#
+# [foo] An item.
+# bat:: Another.
+# [bag] An item spanning
+# multiple lines.
+#
+# [bar baz] Yet another.
+# bam:: Last one.
+#
+# Rendered HTML:
+# >>>
+# [foo] An item.
+# bat:: Another.
+# [bag] An item spanning
+# multiple lines.
+#
+# [bar baz] Yet another.
+# bam:: Last one.
+#
+# ==== Headings
+#
+# A heading begins with up to six equal-signs, followed by heading text.
+# Whitespace between those and the heading text is optional.
+#
+# Examples:
+#
+# = Section 1
+# == Section 1.1
+# === Section 1.1.1
+# === Section 1.1.2
+# == Section 1.2
+# = Section 2
+# = Foo
+# == Bar
+# === Baz
+# ==== Bam
+# ===== Bat
+# ====== Bad
+# ============Still a Heading (Level 6)
+# \== Not a Heading
+#
+# A heading may contain only one type of nested block:
+#
+# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
+#
+# ==== Horizontal Rules
+#
+# A horizontal rule consists of a line with three or more hyphens
+# and nothing more.
+#
+# Example input:
+#
+# ---
+# --- Not a horizontal rule.
+#
+# -- Also not a horizontal rule.
+# ---
+#
+# Rendered HTML:
+# >>>
+# ---
+# --- Not a horizontal rule.
+#
+# -- Also not a horizontal rule.
+# ---
+#
+# ==== Directives
+#
+# ===== Directives for Allowing or Suppressing Documentation
+#
+# - <tt># :stopdoc:</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies that \RDoc should ignore markup
+# until next <tt>:startdoc:</tt> directive or end-of-file.
+#
+# - <tt># :startdoc:</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies that \RDoc should resume parsing markup.
+#
+# - <tt># :enddoc:</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies that \RDoc should ignore markup to end-of-file
+# regardless of other directives.
+#
+# - <tt># :nodoc:</tt>:
+#
+# - Appended to a line of code
+# that defines a class, module, method, alias, constant, or attribute.
+# - Specifies that the defined object should not be documented.
+#
+# - <tt># :nodoc: all</tt>:
+#
+# - Appended to a line of code
+# that defines a class or module.
+# - Specifies that the class or module should not be documented.
+# By default, however, a nested class or module _will_ be documented.
+#
+# - <tt># :doc:</tt>:
+#
+# - Appended to a line of code
+# that defines a class, module, method, alias, constant, or attribute.
+# - Specifies the defined object should be documented, even if otherwise
+# would not be documented.
+#
+# - <tt># :notnew:</tt> (aliased as <tt>:not_new:</tt> and <tt>:not-new:</tt>):
+#
+# - Appended to a line of code
+# that defines instance method +initialize+.
+# - Specifies that singleton method +new+ should not be documented.
+# By default, Ruby fakes a corresponding singleton method +new+,
+# which \RDoc includes in the documentation.
+# Note that instance method +initialize+ is private, and so by default
+# is not documented.
+#
+# For Ruby code, but not for other \RDoc sources,
+# there is a shorthand for <tt>:stopdoc:</tt> and <tt>:startdoc:</tt>:
+#
+# # Documented.
+# #--
+# # Not documented.
+# #++
+# # Documented.
+#
+# For C code, any of directives <tt>:startdoc:</tt>, <tt>:enddoc:</tt>,
+# and <tt>:nodoc:</tt> may appear in a stand-alone comment:
+#
+# /* :startdoc: */
+# /* :stopdoc: */
+# /* :enddoc: */
+#
+# ===== Directive for Specifying \RDoc Source Format
+#
+# - <tt># :markup: _type_</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies the format for the \RDoc input;
+# parameter +type+ is one of +markdown+, +rd+, +rdoc+, +tomdoc+.
+#
+# ===== Directives for HTML Output
+#
+# - <tt># :title: _text_</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies the title for the HTML output.
+#
+# - <tt># :main: _filename_</tt>:
+# - Appears on a line by itself.
+# - Specifies the HTML file to be displayed first.
+#
+# ===== Directives for Method Documentation
+#
+# - <tt># :call-seq:</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies the calling sequence to be reported in the HTML,
+# overriding the actual calling sequence in the code.
+# See method #call_seq_directive.
+#
+# Note that \RDoc can build the calling sequence for a Ruby-coded method,
+# but not for other languages.
+# You may want to override that by explicitly giving a <tt>:call-seq:</tt>
+# directive if you want to include:
+#
+# - A return type, which is not automatically inferred.
+# - Multiple calling sequences.
+#
+# For C code, the directive may appear in a stand-alone comment.
+#
+# - <tt># :args: _arg_names_</tt> (aliased as <tt>:arg:</tt>):
+#
+# - Appears on a line by itself.
+# - Specifies the arguments to be reported in the HTML,
+# overriding the actual arguments in the code.
+# See method #args_directive.
+#
+# - <tt># :yields: _arg_names_</tt> (aliased as <tt>:yield:</tt>):
+#
+# - Appears on a line by itself.
+# - Specifies the yield arguments to be reported in the HTML,
+# overriding the actual yield in the code.
+# See method #yields_directive.
+#
+# ===== Directives for Organizing Documentation
+#
+# By default, \RDoc groups:
+#
+# - Singleton methods together in alphabetical order.
+# - Instance methods and their aliases together in alphabetical order.
+# - Attributes and their aliases together in alphabetical order.
+#
+# You can use directives to modify those behaviors.
+#
+# - <tt># :section: _section_title_</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies that following methods are to be grouped into the section
+# with the given <em>section_title</em>,
+# or into the default section if no title is given.
+# The directive remains in effect until another such directive is given,
+# but may be temporarily overridden by directive <tt>:category:</tt>.
+# See below.
+#
+# The comment block containing this directive:
+#
+# - Must be separated by a blank line from the documentation for the next item.
+# - May have one or more lines preceding the directive.
+# These will be removed, along with any trailing lines that match them.
+# Such lines may be visually helpful.
+# - Lines of text that are not so removed become the descriptive text
+# for the section.
+#
+# Example:
+#
+# # ----------------------------------------
+# # :section: My Section
+# # This is the section that I wrote.
+# # See it glisten in the noon-day sun.
+# # ----------------------------------------
+#
+# ##
+# # Comment for some_method
+# def some_method
+# # ...
+# end
+#
+# You can use directive <tt>:category:</tt> to temporarily
+# override the current section.
+#
+# - <tt># :category: _section_title_</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies that just one following method is to be included
+# in the given section, or in the default section if no title is given.
+# Subsequent methods are to be grouped into the current section.
+#
+# ===== Directive for Including a File
+#
+# - <tt># :include: _filepath_</tt>:
+#
+# - Appears on a line by itself.
+# - Specifies that the contents of the given file
+# are to be included at this point.
+# The file content is shifted to have the same indentation as the colon
+# at the start of the directive.
+#
+# The file is searched for in the directories
+# given with the <tt>--include</tt> command-line option,
+# or by default in the current directory.
+#
+# For C code, the directive may appear in a stand-alone comment
+#
+# ==== Text Markup
+#
+# Text markup is metatext that affects HTML rendering:
+#
+# - Typeface: italic, bold, monofont.
+# - Character conversions: copyright, trademark, certain punctuation.
+# - Links.
+# - Escapes: marking text as "not markup."
+#
+# ===== Typeface Markup
+#
+# Typeface markup can specify that text is to be rendered
+# as italic, bold, or monofont.
+#
+# Typeface markup may contain only one type of nested block:
+#
+# - More typeface markup:
+# italic, bold, monofont.
+#
+# ====== Italic
+#
+# Text may be marked as italic via HTML tag <tt><i></tt> or <tt><em></tt>.
+#
+# Example input:
+#
+# <i>Italicized words</i> in a paragraph.
+#
+# >>>
+# <i>Italicized words in a block quote</i>.
+#
+# - <i>Italicized words</i> in a list item.
+#
+# ====== <i>Italicized words</i> in a Heading
+#
+# <i>Italicized passage containing *bold* and +monofont+.</i>
+#
+# Rendered HTML:
+# >>>
+# <i>Italicized words</i> in a paragraph.
+#
+# >>>
+# <i>Italicized words in a block quote</i>.
+#
+# - <i>Italicized words</i> in a list item.
+#
+# ====== <i>Italicized words</i> in a Heading
+#
+# <i>Italicized passage containing *bold* and +monofont+.</i>
+#
+# A single word may be italicized via a shorthand:
+# prefixed and suffixed underscores.
+#
+# Example input:
+#
+# _Italic_ in a paragraph.
+#
+# >>>
+# _Italic_ in a block quote.
+#
+# - _Italic_ in a list item.
+#
+# ====== _Italic_ in a Heading
+#
+# Rendered HTML:
+# >>>
+# _Italic_ in a paragraph.
+#
+# >>>
+# _Italic_ in a block quote.
+#
+# - _Italic_ in a list item.
+#
+# ====== _Italic_ in a Heading
+#
+# ====== Bold
+#
+# Text may be marked as bold via HTML tag <tt><b></tt>.
+#
+# Example input:
+#
+# <b>Bold words</b> in a paragraph.
+#
+# >>>
+# <b>Bold words</b> in a block quote.
+#
+# - <b>Bold words</b> in a list item.
+#
+# ====== <b>Bold words</b> in a Heading
+#
+# <b>Bold passage containing _italics_ and +monofont+.</b>
+#
+# Rendered HTML:
+#
+# >>>
+# <b>Bold words</b> in a paragraph.
+#
+# >>>
+# <b>Bold words</b> in a block quote.
+#
+# - <b>Bold words</b> in a list item.
+#
+# ====== <b>Bold words</b> in a Heading
+#
+# <b>Bold passage containing _italics_ and +monofont+.</b>
+#
+# A single word may be made bold via a shorthand:
+# prefixed and suffixed asterisks.
+#
+# Example input:
+#
+# *Bold* in a paragraph.
+#
+# >>>
+# *Bold* in a block quote.
+#
+# - *Bold* in a list item.
+#
+# ===== *Bold* in a Heading
+#
+# Rendered HTML:
+#
+# >>>
+# *Bold* in a paragraph.
+#
+# >>>
+# *Bold* in a block quote.
+#
+# - *Bold* in a list item.
+#
+# ===== *Bold* in a Heading
+#
+# ====== Monofont
+#
+# Text may be marked as monofont
+# -- sometimes called 'typewriter font' --
+# via HTML tag <tt><tt></tt> or <tt><code></tt>.
+#
+# Example input:
+#
+# <tt>Monofont words</tt> in a paragraph.
+#
+# >>>
+# <tt>Monofont words</tt> in a block quote.
+#
+# - <tt>Monofont words</tt> in a list item.
+#
+# ====== <tt>Monofont words</tt> in heading
+#
+# <tt>Monofont passage containing _italics_ and *bold*.</tt>
+#
+# Rendered HTML:
+#
+# >>>
+# <tt>Monofont words</tt> in a paragraph.
+#
+# >>>
+# <tt>Monofont words</tt> in a block quote.
+#
+# - <tt>Monofont words</tt> in a list item.
+#
+# ====== <tt>Monofont words</tt> in heading
+#
+# <tt>Monofont passage containing _italics_ and *bold*.</tt>
+#
+# A single word may be made monofont by a shorthand:
+# prefixed and suffixed plus-signs.
+#
+# Example input:
+#
+# +Monofont+ in a paragraph.
+#
+# >>>
+# +Monofont+ in a block quote.
+#
+# - +Monofont+ in a list item.
+#
+# ====== +Monofont+ in a Heading
+#
+# Rendered HTML:
+#
+# >>>
+# +Monofont+ in a paragraph.
+#
+# >>>
+# +Monofont+ in a block quote.
+#
+# - +Monofont+ in a list item.
+#
+# ====== +Monofont+ in a Heading
+#
+# ==== Character Conversions
+#
+# Certain combinations of characters may be converted to special characters;
+# whether the conversion occurs depends on whether the special character
+# is available in the current encoding.
+#
+# - <tt>(c)</tt> converts to (c) (copyright character); must be lowercase.
+#
+# - <tt>(r)</tt> converts to (r) (registered trademark character); must be lowercase.
+#
+# - <tt>'foo'</tt> converts to 'foo' (smart single-quotes).
+#
+# - <tt>"foo"</tt> converts to "foo" (smart double-quotes).
+#
+# - <tt>foo ... bar</tt> converts to foo ... bar (1-character ellipsis).
+#
+# - <tt>foo -- bar</tt> converts to foo -- bar (1-character en-dash).
+#
+# - <tt>foo --- bar</tt> converts to foo --- bar (1-character em-dash).
+#
+# ==== Links
+#
+# Certain strings in \RDoc text are converted to links.
+# Any such link may be suppressed by prefixing a backslash.
+# This section shows how to link to various
+# targets.
+#
+# [Class]
+#
+# - On-page: <tt>DummyClass</tt> links to DummyClass.
+# - Off-page: <tt>RDoc::Alias</tt> links to RDoc::Alias.
+#
+# [Module]
+#
+# - On-page: <tt>DummyModule</tt> links to DummyModule.
+# - Off-page: <tt>RDoc</tt> links to RDoc.
+#
+# [Constant]
+#
+# - On-page: <tt>DUMMY_CONSTANT</tt> links to DUMMY_CONSTANT.
+# - Off-page: <tt>RDoc::Text::MARKUP_FORMAT</tt> links to RDoc::Text::MARKUP_FORMAT.
+#
+# [Singleton Method]
+#
+# - On-page: <tt>::dummy_singleton_method</tt> links to ::dummy_singleton_method.
+# - Off-page<tt>RDoc::TokenStream::to_html</tt> links to RDoc::TokenStream::to_html.
+#
+# Note: Occasionally \RDoc is not linked to a method whose name
+# has only special characters. Check whether the links you were expecting
+# are actually there. If not, you'll need to put in an explicit link;
+# see below.
+#
+# Pro tip: The link to any method is available in the alphabetical table of contents
+# at the top left of the page for the class or module.
+#
+# [Instance Method]
+#
+# - On-page: <tt>#dummy_instance_method</tt> links to #dummy_instance_method.
+# - Off-page: <tt>RDoc::Alias#html_name</tt> links to RDoc::Alias#html_name.
+#
+# See the Note and Pro Tip immediately above.
+#
+# [Attribute]
+#
+# - On-page: <tt>#dummy_attribute</tt> links to #dummy_attribute.
+# - Off-page: <tt>RDoc::Alias#name</tt> links to RDoc::Alias#name.
+#
+# [Alias]
+#
+# - On-page: <tt>#dummy_instance_alias</tt> links to #dummy_instance_alias.
+# - Off-page: <tt>RDoc::Alias#new_name</tt> links to RDoc::Alias#new_name.
+#
+# [Protocol +http+]
+#
+# - Linked: <tt>http://yahoo.com</tt> links to http://yahoo.com.
+#
+# [Protocol +https+]
+#
+# - Linked: <tt>https://github.com</tt> links to https://github.com.
+#
+# [Protocol +www+]
+#
+# - Linked: <tt>www.yahoo.com</tt> links to www.yahoo.com.
+#
+# [Protocol +ftp+]
+#
+# - Linked: <tt>ftp://nosuch.site</tt> links to ftp://nosuch.site.
+#
+# [Protocol +mailto+]
+#
+# - Linked: <tt>mailto:/foo@bar.com</tt> links to mailto://foo@bar.com.
+#
+# [Protocol +irc+]
+#
+# - link: <tt>irc://irc.freenode.net/ruby</tt> links to irc://irc.freenode.net/ruby.
+#
+# [Image Filename Extensions]
+#
+# - Link: <tt>https://www.ruby-lang.org/images/header-ruby-logo@2x.png</tt> is
+# converted to an in-line HTML +img+ tag, which displays the image in the HTML:
+#
+# https://www.ruby-lang.org/images/header-ruby-logo@2x.png
+#
+# Also works for +bmp+, +gif+, +jpeg+, and +jpg+ files.
+#
+# Note: Works only for a fully qualified URL.
+#
+# [Heading]
+#
+# - Link: <tt>RDoc::RD@LICENSE</tt> links to RDoc::RDoc::RD@LICENSE.
+#
+# Note that spaces in the actual heading are represented by <tt>+</tt> characters
+# in the linkable text.
+#
+# - Link: <tt>RDoc::Options@Saved+Options</tt>
+# links to RDoc::Options@Saved+Options.
+#
+# Punctuation and other special characters must be escaped like CGI.escape.
+#
+# Pro tip: The link to any heading is available in the alphabetical table of contents
+# at the top left of the page for the class or module.
+#
+# [Section]
+#
+# See {Directives for Organizing Documentation}[#class-RDoc::MarkupReference-label-Directives+for+Organizing+Documentation].
+#
+# - Link: <tt>RDoc::Markup::ToHtml@Visitor</tt> links to RDoc::Markup::ToHtml@Visitor.
+#
+# If a section and a heading share the same name, the link target is the section.
+#
+# [Single-Word Text Link]
+#
+# Use square brackets to create single-word text link:
+#
+# - <tt>GitHub[https://github.com]</tt> links to GitHub[https://github.com].
+#
+# [Multi-Word Text Link]
+#
+# Use square brackets and curly braces to create a multi-word text link.
+#
+# - <tt>{GitHub home page}[https://github.com]</tt> links to
+# {GitHub home page}[https://github.com].
+#
+# [<tt>rdoc-ref</tt> Scheme]
+#
+# A link with the <tt>rdoc-ref:</tt> scheme links to the referenced item,
+# if that item exists.
+# The referenced item may be a class, module, method, file, etc.
+#
+# - Class: <tt>Alias[rdoc-ref:RDoc::Alias]</tt> links to Alias[rdoc-ref:RDoc::Alias].
+# - Module: <tt>RDoc[rdoc-ref:RDoc]</tt> links to RDoc[rdoc-ref:RDoc].
+# - Method: <tt>foo[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]</tt>
+# links to foo[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK].
+# - Constant: <tt>bar[rdoc-ref:RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML]</tt>
+# links to bar[rdoc-ref:RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML].
+# - Attribute: <tt>baz[rdoc-ref:RDoc::Markup::ToHtml#code_object]</tt>
+# links to baz[rdoc-ref:RDoc::Markup::ToHtml#code_object].
+# - Alias: <tt>bad[rdoc-ref:RDoc::MarkupReference#dummy_instance_alias]</tt> links to
+# bad[rdoc-ref:RDoc::MarkupReference#dummy_instance_alias].
+#
+# If the referenced item does not exist, no link is generated
+# and entire <tt>rdoc-ref:</tt> square-bracketed clause is removed
+# from the resulting text.
+#
+# - <tt>Nosuch[rdoc-ref:RDoc::Nosuch]</tt> is rendered as
+# Nosuch[rdoc-ref:RDoc::Nosuch].
+#
+#
+# [<tt>rdoc-label</tt> Scheme]
+#
+# [Simple]
+#
+# You can specify a link target using this form,
+# where the second part cites the id of an HTML element.
+#
+# This link refers to the constant +DUMMY_CONSTANT+ on this page:
+#
+# - <tt>{DUMMY_CONSTANT}[rdoc-label:DUMMY_CONSTANT]</tt>
+#
+# Thus:
+#
+# {DUMMY_CONSTANT}[rdoc-label:DUMMY_CONSTANT]
+#
+# [With Return]
+#
+# You can specify both a link target and a local label
+# that can be used as the target for a return link.
+# These two links refer to each other:
+#
+# - <tt>{go to addressee}[rdoc-label:addressee:sender]</tt>
+# - <tt>{return to sender}[rdoc-label:sender:addressee]</tt>
+#
+# Thus:
+#
+# {go to addressee}[rdoc-label:addressee:sender]
+#
+# Some text.
+#
+# {return to sender}[rdoc-label:sender:addressee]
+#
+# [<tt>link:</tt> Scheme]
+#
+# - <tt>link:README_rdoc.html</tt> links to link:README_rdoc.html.
+#
+# [<tt>rdoc-image</tt> Scheme]
+#
+# Use the <tt>rdoc-image</tt> scheme to display an image that is also a link:
+#
+# # {rdoc-image:path/to/image}[link_target]
+#
+# - Link: <tt>{rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[https://www.ruby-lang.org]</tt>
+# displays image <tt>https://www.ruby-lang.org/images/header-ruby-logo@2x.png</tt>
+# as a link to <tt>https://www.ruby-lang.org</tt>.
+#
+# {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[https://www.ruby-lang.org]
+#
+# A relative path as the target also works:
+#
+# - Link: <tt>{rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[./Alias.html]</tt> links to <tt>./Alias.html</tt>
+#
+# {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[./Alias.html]
+#
+# === Escaping Text
+#
+# Text that would otherwise be interpreted as markup
+# can be "escaped," so that it is not interpreted as markup;
+# the escape character is the backslash (<tt>'\\'</tt>).
+#
+# In a verbatim text block or a code block,
+# the escape character is always preserved:
+#
+# Example input:
+#
+# This is not verbatim text.
+#
+# This is verbatim text, with an escape character \.
+#
+# This is not a code block.
+#
+# def foo
+# 'String with an escape character.'
+# end
+#
+# Rendered HTML:
+#
+# >>>
+# This is not verbatim text.
+#
+# This is verbatim text, with an escape character \.
+#
+# This is not a code block.
+#
+# def foo
+# 'This is a code block with an escape character \.'
+# end
+#
+# In typeface markup (italic, bold, or monofont),
+# an escape character is preserved unless it is immediately
+# followed by nested typeface markup.
+#
+# Example input:
+#
+# This list is about escapes; it contains:
+#
+# - <tt>Monofont text with unescaped nested _italic_</tt>.
+# - <tt>Monofont text with escaped nested \_italic_</tt>.
+# - <tt>Monofont text with an escape character \</tt>.
+#
+# Rendered HTML:
+#
+# >>>
+# This list is about escapes; it contains:
+#
+# - <tt>Monofont text with unescaped nested _italic_</tt>.
+# - <tt>Monofont text with escaped nested \_italic_</tt>.
+# - <tt>Monofont text with an escape character \ </tt>.
+#
+# In other text-bearing blocks
+# (paragraphs, block quotes, list items, headings):
+#
+# - A single escape character immediately followed by markup
+# escapes the markup.
+# - A single escape character followed by whitespace is preserved.
+# - A single escape character anywhere else is ignored.
+# - A double escape character is rendered as a single backslash.
+#
+# Example input:
+#
+# This list is about escapes; it contains:
+#
+# - An unescaped class name, RDoc, that will become a link.
+# - An escaped class name, \RDoc, that will not become a link.
+# - An escape character followed by whitespace \ .
+# - An escape character \that is ignored.
+# - A double escape character \\ that is rendered
+# as a single backslash.
+#
+# Rendered HTML:
+#
+# >>>
+# This list is about escapes; it contains:
+#
+# - An unescaped class name, RDoc, that will become a link.
+# - An escaped class name, \RDoc, that will not become a link.
+# - An escape character followed by whitespace \ .
+# - An escape character \that is ignored.
+# - A double escape character \\ that is rendered
+# as a single backslash.
+#
+# == Documentation Derived from Ruby Code
+#
+# [Class]
+#
+# By default, \RDoc documents:
+#
+# - \Class name.
+# - Parent class.
+# - Singleton methods.
+# - Instance methods.
+# - Aliases.
+# - Constants.
+# - Attributes.
+#
+# [Module]
+#
+# By default, \RDoc documents:
+#
+# - \Module name.
+# - \Singleton methods.
+# - Instance methods.
+# - Aliases.
+# - Constants.
+# - Attributes.
+#
+# [Method]
+#
+# By default, \RDoc documents:
+#
+# - \Method name.
+# - Arguments.
+# - Yielded values.
+#
+# See #method.
+#
+# [Alias]
+#
+# By default, \RDoc documents:
+#
+# - Alias name.
+# - Aliased name.
+#
+# See #dummy_instance_alias and #dummy_instance_method.
+#
+# [Constant]
+#
+# By default, \RDoc documents:
+#
+# - \Constant name.
+#
+# See DUMMY_CONSTANT.
+#
+# [Attribute]
+#
+# By default, \RDoc documents:
+#
+# - Attribute name.
+# - Attribute type (<tt>[R]</tt>, <tt>[W]</tt>, or <tt>[RW]</tt>)
+#
+# See #dummy_attribute.
+#
+class RDoc::MarkupReference
+
+ class DummyClass; end
+ module DummyModule; end
+ def self.dummy_singleton_method(foo, bar); end
+ def dummy_instance_method(foo, bar); end;
+ alias dummy_instance_alias dummy_instance_method
+ attr_accessor :dummy_attribute
+ alias dummy_attribute_alias dummy_attribute
+ DUMMY_CONSTANT = ''
+
+ # :call-seq:
+ # call_seq_directive(foo, bar)
+ # Can be anything -> bar
+ # Also anything more -> baz or bat
+ #
+ # The <tt>:call-seq:</tt> directive overrides the actual calling sequence
+ # found in the Ruby code.
+ #
+ # - It can specify anything at all.
+ # - It can have multiple calling sequences.
+ #
+ # This one includes <tt>Can be anything -> foo</tt>, which is nonsense.
+ #
+ # Note that the "arrow" is two characters, hyphen and right angle-bracket,
+ # which is made into a single character in the HTML.
+ #
+ # Click on the calling sequence to see the code.
+ #
+ # Here is the <tt>:call-seq:</tt> directive given for the method:
+ #
+ # :call-seq:
+ # call_seq_directive(foo, bar)
+ # Can be anything -> bar
+ # Also anything more -> baz or bat
+ #
+ def call_seq_directive
+ nil
+ end
+
+ # The <tt>:args:</tt> directive overrides the actual arguments found in the Ruby code.
+ #
+ # Click on the calling sequence to see the code.
+ #
+ def args_directive(foo, bar) # :args: baz
+ nil
+ end
+
+ # The <tt>:yields:</tt> directive overrides the actual yield found in the Ruby code.
+ #
+ # Click on the calling sequence to see the code.
+ #
+ def yields_directive(foo, bar) # :yields: 'bat'
+ yield 'baz'
+ end
+
+ # This method is documented only by \RDoc, except for these comments.
+ #
+ # Click on the calling sequence to see the code.
+ #
+ def method(foo, bar)
+ yield 'baz'
+ end
+
+end
diff --git a/doc/regexp.rdoc b/doc/regexp.rdoc
index 23fe7113b9..92c7ecf66e 100644
--- a/doc/regexp.rdoc
+++ b/doc/regexp.rdoc
@@ -27,12 +27,22 @@ Here 'haystack' contains the pattern 'hay', so it matches:
Specifically, <tt>/st/</tt> requires that the string contains the letter
_s_ followed by the letter _t_, so it matches _haystack_, also.
+Note that any Regexp matching will raise a RuntimeError if timeout is set and
+exceeded. See {"Timeout"}[#label-Timeout] section in detail.
+
+== \Regexp Interpolation
+
+A regexp may contain interpolated strings; trivially:
+
+ foo = 'bar'
+ /#{foo}/ # => /bar/
+
== <tt>=~</tt> and Regexp#match
Pattern matching may be achieved by using <tt>=~</tt> operator or Regexp#match
method.
-=== <tt>=~</tt> operator
+=== <tt>=~</tt> Operator
<tt>=~</tt> is Ruby's basic pattern-matching operator. When one operand is a
regular expression and the other is a string then the regular expression is
@@ -51,7 +61,7 @@ Using <tt>=~</tt> operator with a String and Regexp the <tt>$~</tt> global
variable is set after a successful match. <tt>$~</tt> holds a MatchData
object. Regexp.last_match is equivalent to <tt>$~</tt>.
-=== Regexp#match method
+=== Regexp#match Method
The #match method returns a MatchData object:
@@ -190,7 +200,7 @@ At least one uppercase character ('H'), at least one lowercase character
"Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> #<MatchData "Hello">
-=== Greedy match
+=== Greedy Match
Repetition is <i>greedy</i> by default: as many occurrences as possible
are matched while still allowing the overall match to succeed. By
@@ -208,7 +218,7 @@ Both patterns below match the string. The first uses a greedy quantifier so
/<.+>/.match("<a><b>") #=> #<MatchData "<a><b>">
/<.+?>/.match("<a><b>") #=> #<MatchData "<a>">
-=== Possessive match
+=== Possessive Match
A quantifier followed by <tt>+</tt> matches <i>possessively</i>: once it
has matched it does not backtrack. They behave like greedy quantifiers,
@@ -253,7 +263,7 @@ this backreference when doing substitution:
"The cat sat in the hat".gsub(/[csh]at/, '\0s')
# => "The cats sats in the hats"
-=== Named captures
+=== Named Captures
Capture groups can be referred to by name when defined with the
<tt>(?<</tt><i>name</i><tt>>)</tt> or <tt>(?'</tt><i>name</i><tt>')</tt>
@@ -405,6 +415,7 @@ much like POSIX bracket classes.
* <tt>/\p{Blank}/</tt> - Space or tab
* <tt>/\p{Cntrl}/</tt> - Control character
* <tt>/\p{Digit}/</tt> - Digit
+* <tt>/\p{Emoji}/</tt> - Unicode emoji
* <tt>/\p{Graph}/</tt> - Non-blank character (excludes spaces, control
characters, and similar)
* <tt>/\p{Lower}/</tt> - Lowercase alphabetical character
@@ -539,12 +550,16 @@ characters, <i>anchoring</i> the match to a specific position.
* <tt>(?<!</tt><i>pat</i><tt>)</tt> - <i>Negative lookbehind</i>
assertion: ensures that the preceding characters do not match
<i>pat</i>, but doesn't include those characters in the matched text
-* <tt>\K</tt> - Uses an positive lookbehind of the content preceding
- <tt>\K</tt> in the regexp. For example, the following two regexps are
- almost equivalent:
- /ab\Kc/
- /(?<=ab)c/
+* <tt>\K</tt> - <i>Match reset</i>: the matched content preceding
+ <tt>\K</tt> in the regexp is excluded from the result. For example,
+ the following two regexps are almost equivalent:
+
+ /ab\Kc/ =~ "abc" #=> 0
+ /(?<=ab)c/ =~ "abc" #=> 2
+
+ These match same string and <i>$&</i> equals <tt>"c"</tt>, while the
+ matched position is different.
As are the following two regexps:
@@ -609,6 +624,11 @@ Options may also be used with <tt>Regexp.new</tt>:
Regexp.new("abc # Comment", Regexp::EXTENDED) #=> /abc # Comment/x
Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi
+ Regexp.new("abc", "i") #=> /abc/i
+ Regexp.new("abc", "m") #=> /abc/m
+ Regexp.new("abc # Comment", "x") #=> /abc # Comment/x
+ Regexp.new("abc", "im") #=> /abc/mi
+
== Free-Spacing Mode and Comments
As mentioned above, the <tt>x</tt> option enables <i>free-spacing</i>
@@ -668,9 +688,10 @@ regexp's encoding can be explicitly fixed by supplying
# raises Encoding::CompatibilityError: incompatible encoding regexp match
# (ISO-8859-1 regexp with UTF-8 string)
-== Special global variables
+== \Regexp Global Variables
Pattern matching sets some global variables :
+
* <tt>$~</tt> is equivalent to Regexp.last_match;
* <tt>$&</tt> contains the complete matched text;
* <tt>$`</tt> contains string before match;
@@ -758,3 +779,23 @@ with <i>a{0,29}</i>:
Regexp.new('a{0,29}' + 'a' * 29) =~ 'a' * 29
+== Timeout
+
+There are two APIs to set timeout. One is Regexp.timeout=, which is
+process-global configuration of timeout for Regexp matching.
+
+ Regexp.timeout = 3
+ s = 'a' * 25 + 'd' + 'a' * 4 + 'c'
+ /(b|a+)*c/ =~ s #=> This raises an exception in three seconds
+
+The other is timeout keyword of Regexp.new.
+
+ re = Regexp.new("(b|a+)*c", timeout: 3)
+ s = 'a' * 25 + 'd' + 'a' * 4 + 'c'
+ /(b|a+)*c/ =~ s #=> This raises an exception in three seconds
+
+When using Regexps to process untrusted input, you should use the timeout
+feature to avoid excessive backtracking. Otherwise, a malicious user can
+provide input to Regexp causing Denial-of-Service attack.
+Note that the timeout is not set by default because an appropriate limit
+highly depends on an application requirement and context.
diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc
index 1d3580163e..7c9938c5b0 100644
--- a/doc/standard_library.rdoc
+++ b/doc/standard_library.rdoc
@@ -31,12 +31,12 @@ 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
+ErrorHighlight:: Highlight error location in your code
FileUtils:: Several file utility methods for copying, moving, removing, etc
Find:: This module supports top-down traversal of a set of file paths
Forwardable:: Provides delegation of specified methods to a designated object
@@ -54,6 +54,8 @@ OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP
PP:: Provides a PrettyPrinter for Ruby objects
PrettyPrinter:: Implements a pretty printing algorithm for readable structure
PStore:: Implements a file based persistence mechanism based on a Hash
+Readline:: Wrapper for Readline extencion and Reline
+Reline:: GNU Readline and Editline by pure Ruby implementation.
Resolv:: Thread-aware DNS resolver library in Ruby
resolv-replace.rb:: Replace Socket DNS with Resolv
RDoc:: Produces HTML and command-line documentation for Ruby
@@ -113,3 +115,4 @@ Matrix:: Represents a mathematical matrix.
Prime:: Prime numbers and factorization library
RBS:: RBS is a language to describe the structure of Ruby programs
TypeProf:: A type analysis tool for Ruby code based on abstract interpretation
+DEBUGGER__:: Debugging functionality for Ruby
diff --git a/doc/strftime_formatting.rdoc b/doc/strftime_formatting.rdoc
new file mode 100644
index 0000000000..30a629bf68
--- /dev/null
+++ b/doc/strftime_formatting.rdoc
@@ -0,0 +1,527 @@
+== Formats for Dates and Times
+
+Several Ruby time-related classes have instance method +strftime+,
+which returns a formatted string representing all or part of a date or time:
+
+- Date#strftime.
+- DateTime#strftime.
+- Time#strftime.
+
+Each of these methods takes optional argument +format+,
+which has zero or more embedded _format_ _specifications_ (see below).
+
+Each of these methods returns the string resulting from replacing each
+format specification embedded in +format+ with a string form
+of one or more parts of the date or time.
+
+A simple example:
+
+ Time.now.strftime('%H:%M:%S') # => "14:02:07"
+
+A format specification has the form:
+
+ %[flags][width]conversion
+
+It consists of:
+
+- A leading percent character.
+- Zero or more _flags_ (each is a character).
+- An optional _width_ _specifier_ (an integer).
+- A _conversion_ _specifier_ (a character).
+
+Except for the leading percent character,
+the only required part is the conversion specifier, so we begin with that.
+
+=== Conversion Specifiers
+
+==== \Date (Year, Month, Day)
+
+- <tt>%Y</tt> - Year including century, zero-padded:
+
+ Time.now.strftime('%Y') # => "2022"
+ Time.new(-1000).strftime('%Y') # => "-1000" # Before common era.
+ Time.new(10000).strftime('%Y') # => "10000" # Far future.
+ Time.new(10).strftime('%Y') # => "0010" # Zero-padded by default.
+
+- <tt>%y</tt> - Year without century, in range (0.99), zero-padded:
+
+ Time.now.strftime('%y') # => "22"
+ Time.new(1).strftime('%y') # => "01" # Zero-padded by default.
+
+- <tt>%C</tt> - Century, zero-padded:
+
+ Time.now.strftime('%C') # => "20"
+ Time.new(-1000).strftime('%C') # => "-10" # Before common era.
+ Time.new(10000).strftime('%C') # => "100" # Far future.
+ Time.new(100).strftime('%C') # => "01" # Zero-padded by default.
+
+- <tt>%m</tt> - Month of the year, in range (1..12), zero-padded:
+
+ Time.new(2022, 1).strftime('%m') # => "01" # Zero-padded by default.
+ Time.new(2022, 12).strftime('%m') # => "12"
+
+- <tt>%B</tt> - Full month name, capitalized:
+
+ Time.new(2022, 1).strftime('%B') # => "January"
+ Time.new(2022, 12).strftime('%B') # => "December"
+
+- <tt>%b</tt> - Abbreviated month name, capitalized:
+
+ Time.new(2022, 1).strftime('%b') # => "Jan"
+ Time.new(2022, 12).strftime('%h') # => "Dec"
+
+- <tt>%h</tt> - Same as <tt>%b</tt>.
+
+- <tt>%d</tt> - Day of the month, in range (1..31), zero-padded:
+
+ Time.new(2002, 1, 1).strftime('%d') # => "01"
+ Time.new(2002, 1, 31).strftime('%d') # => "31"
+
+- <tt>%e</tt> - Day of the month, in range (1..31), blank-padded:
+
+ Time.new(2002, 1, 1).strftime('%e') # => " 1"
+ Time.new(2002, 1, 31).strftime('%e') # => "31"
+
+- <tt>%j</tt> - Day of the year, in range (1..366), zero-padded:
+
+ Time.new(2002, 1, 1).strftime('%j') # => "001"
+ Time.new(2002, 12, 31).strftime('%j') # => "365"
+
+==== \Time (Hour, Minute, Second, Subsecond)
+
+- <tt>%H</tt> - Hour of the day, in range (0..23), zero-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%H') # => "01"
+ Time.new(2022, 1, 1, 13).strftime('%H') # => "13"
+
+- <tt>%k</tt> - Hour of the day, in range (0..23), blank-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%k') # => " 1"
+ Time.new(2022, 1, 1, 13).strftime('%k') # => "13"
+
+- <tt>%I</tt> - Hour of the day, in range (1..12), zero-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%I') # => "01"
+ Time.new(2022, 1, 1, 13).strftime('%I') # => "01"
+
+- <tt>%l</tt> - Hour of the day, in range (1..12), blank-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%l') # => " 1"
+ Time.new(2022, 1, 1, 13).strftime('%l') # => " 1"
+
+- <tt>%P</tt> - Meridian indicator, lowercase:
+
+ Time.new(2022, 1, 1, 1).strftime('%P') # => "am"
+ Time.new(2022, 1, 1, 13).strftime('%P') # => "pm"
+
+- <tt>%p</tt> - Meridian indicator, uppercase:
+
+ Time.new(2022, 1, 1, 1).strftime('%p') # => "AM"
+ Time.new(2022, 1, 1, 13).strftime('%p') # => "PM"
+
+- <tt>%M</tt> - Minute of the hour, in range (0..59), zero-padded:
+
+ Time.new(2022, 1, 1, 1, 0, 0).strftime('%M') # => "00"
+
+- <tt>%S</tt> - Second of the minute in range (0..59), zero-padded:
+
+ Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%S') # => "00"
+
+- <tt>%L</tt> - Millisecond of the second, in range (0..999), zero-padded:
+
+ Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%L') # => "000"
+
+- <tt>%N</tt> - Fractional seconds, default width is 9 digits (nanoseconds):
+
+ t = Time.now # => 2022-06-29 07:10:20.3230914 -0500
+ t.strftime('%N') # => "323091400" # Default.
+
+ Use {width specifiers}[rdoc-ref:strftime_formatting.rdoc@Width+Specifiers]
+ to adjust units:
+
+ t.strftime('%3N') # => "323" # Milliseconds.
+ t.strftime('%6N') # => "323091" # Microseconds.
+ t.strftime('%9N') # => "323091400" # Nanoseconds.
+ t.strftime('%12N') # => "323091400000" # Picoseconds.
+ t.strftime('%15N') # => "323091400000000" # Femptoseconds.
+ t.strftime('%18N') # => "323091400000000000" # Attoseconds.
+ t.strftime('%21N') # => "323091400000000000000" # Zeptoseconds.
+ t.strftime('%24N') # => "323091400000000000000000" # Yoctoseconds.
+
+- <tt>%s</tt> - Number of seconds since the epoch:
+
+ Time.now.strftime('%s') # => "1656505136"
+
+==== Timezone
+
+- <tt>%z</tt> - Timezone as hour and minute offset from UTC:
+
+ Time.now.strftime('%z') # => "-0500"
+
+- <tt>%Z</tt> - Timezone name (platform-dependent):
+
+ Time.now.strftime('%Z') # => "Central Daylight Time"
+
+==== Weekday
+
+- <tt>%A</tt> - Full weekday name:
+
+ Time.now.strftime('%A') # => "Wednesday"
+
+- <tt>%a</tt> - Abbreviated weekday name:
+
+ Time.now.strftime('%a') # => "Wed"
+
+- <tt>%u</tt> - Day of the week, in range (1..7), Monday is 1:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%u') # => "7"
+
+- <tt>%w</tt> - Day of the week, in range (0..6), Sunday is 0:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%w') # => "0"
+
+==== Week Number
+
+- <tt>%U</tt> - Week number of the year, in range (0..53), zero-padded,
+ where each week begins on a Sunday:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%U') # => "26"
+
+- <tt>%W</tt> - Week number of the year, in range (0..53), zero-padded,
+ where each week begins on a Monday:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%W') # => "25"
+
+==== Week Dates
+
+See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates].
+
+ t0 = Time.new(2023, 1, 1) # => 2023-01-01 00:00:00 -0600
+ t1 = Time.new(2024, 1, 1) # => 2024-01-01 00:00:00 -0600
+
+- <tt>%G</tt> - Week-based year:
+
+ t0.strftime('%G') # => "2022"
+ t1.strftime('%G') # => "2024"
+
+- <tt>%g</tt> - Week-based year without century, in range (0..99), zero-padded:
+
+ t0.strftime('%g') # => "22"
+ t1.strftime('%g') # => "24"
+
+- <tt>%V</tt> - Week number of the week-based year, in range (1..53),
+ zero-padded:
+
+ t0.strftime('%V') # => "52"
+ t1.strftime('%V') # => "01"
+
+==== Literals
+
+- <tt>%n</tt> - Newline character "\n":
+
+ Time.now.strftime('%n') # => "\n"
+
+- <tt>%t</tt> - Tab character "\t":
+
+ Time.now.strftime('%t') # => "\t"
+
+- <tt>%%</tt> - Percent character '%':
+
+ Time.now.strftime('%%') # => "%"
+
+==== Shorthand Conversion Specifiers
+
+Each shorthand specifier here is shown with its corresponding
+longhand specifier.
+
+- <tt>%c</tt> - \Date and time:
+
+ Time.now.strftime('%c') # => "Wed Jun 29 08:01:41 2022"
+ Time.now.strftime('%a %b %e %T %Y') # => "Wed Jun 29 08:02:07 2022"
+
+- <tt>%D</tt> - \Date:
+
+ Time.now.strftime('%D') # => "06/29/22"
+ Time.now.strftime('%m/%d/%y') # => "06/29/22"
+
+- <tt>%F</tt> - ISO 8601 date:
+
+ Time.now.strftime('%F') # => "2022-06-29"
+ Time.now.strftime('%Y-%m-%d') # => "2022-06-29"
+
+- <tt>%v</tt> - VMS date:
+
+ Time.now.strftime('%v') # => "29-JUN-2022"
+ Time.now.strftime('%e-%^b-%4Y') # => "29-JUN-2022"
+
+- <tt>%x</tt> - Same as <tt>%D</tt>.
+
+- <tt>%X</tt> - Same as <tt>%T</tt>.
+
+- <tt>%r</tt> - 12-hour time:
+
+ Time.new(2022, 1, 1, 1).strftime('%r') # => "01:00:00 AM"
+ Time.new(2022, 1, 1, 1).strftime('%I:%M:%S %p') # => "01:00:00 AM"
+ Time.new(2022, 1, 1, 13).strftime('%r') # => "01:00:00 PM"
+ Time.new(2022, 1, 1, 13).strftime('%I:%M:%S %p') # => "01:00:00 PM"
+
+- <tt>%R</tt> - 24-hour time:
+
+ Time.new(2022, 1, 1, 1).strftime('%R') # => "01:00"
+ Time.new(2022, 1, 1, 1).strftime('%H:%M') # => "01:00"
+ Time.new(2022, 1, 1, 13).strftime('%R') # => "13:00"
+ Time.new(2022, 1, 1, 13).strftime('%H:%M') # => "13:00"
+
+- <tt>%T</tt> - 24-hour time:
+
+ Time.new(2022, 1, 1, 1).strftime('%T') # => "01:00:00"
+ Time.new(2022, 1, 1, 1).strftime('%H:%M:%S') # => "01:00:00"
+ Time.new(2022, 1, 1, 13).strftime('%T') # => "13:00:00"
+ Time.new(2022, 1, 1, 13).strftime('%H:%M:%S') # => "13:00:00"
+
+- <tt>%+</tt> (not supported in Time#strftime) - \Date and time:
+
+ DateTime.now.strftime('%+')
+ # => "Wed Jun 29 08:31:53 -05:00 2022"
+ DateTime.now.strftime('%a %b %e %H:%M:%S %Z %Y')
+ # => "Wed Jun 29 08:32:18 -05:00 2022"
+
+=== Flags
+
+Flags may affect certain formatting specifications.
+
+Multiple flags may be given with a single conversion specified;
+order does not matter.
+
+==== Padding Flags
+
+- <tt>0</tt> - Pad with zeroes:
+
+ Time.new(10).strftime('%0Y') # => "0010"
+
+- <tt>_</tt> - Pad with blanks:
+
+ Time.new(10).strftime('%_Y') # => " 10"
+
+- <tt>-</tt> - Don't pad:
+
+ Time.new(10).strftime('%-Y') # => "10"
+
+==== Casing Flags
+
+- <tt>^</tt> - Upcase result:
+
+ Time.new(2022, 1).strftime('%B') # => "January" # No casing flag.
+ Time.new(2022, 1).strftime('%^B') # => "JANUARY"
+
+- <tt>#</tt> - Swapcase result:
+
+ Time.now.strftime('%p') # => "AM"
+ Time.now.strftime('%^p') # => "AM"
+ Time.now.strftime('%#p') # => "am"
+
+==== Timezone Flags
+
+- <tt>:</tt> - Put timezone as colon-separated hours and minutes:
+
+ Time.now.strftime('%:z') # => "-05:00"
+
+- <tt>::</tt> - Put timezone as colon-separated hours, minutes, and seconds:
+
+ Time.now.strftime('%::z') # => "-05:00:00"
+
+=== Width Specifiers
+
+The integer width specifier gives a minimum width for the returned string:
+
+ Time.new(2002).strftime('%Y') # => "2002" # No width specifier.
+ Time.new(2002).strftime('%10Y') # => "0000002002"
+ Time.new(2002, 12).strftime('%B') # => "December" # No width specifier.
+ Time.new(2002, 12).strftime('%10B') # => " December"
+ Time.new(2002, 12).strftime('%3B') # => "December" # Ignored if too small.
+
+== Specialized Format Strings
+
+Here are a few specialized format strings,
+each based on an external standard.
+
+=== HTTP Format
+
+The HTTP date format is based on
+{RFC 2616}[https://datatracker.ietf.org/doc/html/rfc2616],
+and treats dates in the format <tt>'%a, %d %b %Y %T GMT'</tt>:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return HTTP-formatted string.
+ httpdate = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ # Return new date parsed from HTTP-formatted string.
+ Date.httpdate(httpdate) # => #<Date: 2001-02-03>
+ # Return hash parsed from HTTP-formatted string.
+ Date._httpdate(httpdate)
+ # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}
+
+=== RFC 3339 Format
+
+The RFC 3339 date format is based on
+{RFC 3339}[https://datatracker.ietf.org/doc/html/rfc3339]:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return 3339-formatted string.
+ rfc3339 = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ # Return new date parsed from 3339-formatted string.
+ Date.rfc3339(rfc3339) # => #<Date: 2001-02-03>
+ # Return hash parsed from 3339-formatted string.
+ Date._rfc3339(rfc3339)
+ # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}
+
+=== RFC 2822 Format
+
+The RFC 2822 date format is based on
+{RFC 2822}[https://datatracker.ietf.org/doc/html/rfc2822],
+and treats dates in the format <tt>'%a, %-d %b %Y %T %z'</tt>]:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return 2822-formatted string.
+ rfc2822 = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ # Return new date parsed from 2822-formatted string.
+ Date.rfc2822(rfc2822) # => #<Date: 2001-02-03>
+ # Return hash parsed from 2822-formatted string.
+ Date._rfc2822(rfc2822)
+ # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}
+
+=== JIS X 0301 Format
+
+The JIS X 0301 format includes the
+{Japanese era name}[https://en.wikipedia.org/wiki/Japanese_era_name],
+and treats dates in the format <tt>'%Y-%m-%d'</tt>
+with the first letter of the romanized era name prefixed:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return 0301-formatted string.
+ jisx0301 = d.jisx0301 # => "H13.02.03"
+ # Return new date parsed from 0301-formatted string.
+ Date.jisx0301(jisx0301) # => #<Date: 2001-02-03>
+ # Return hash parsed from 0301-formatted string.
+ Date._jisx0301(jisx0301) # => {:year=>2001, :mon=>2, :mday=>3}
+
+=== ISO 8601 Format Specifications
+
+This section shows format specifications that are compatible with
+{ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601].
+Details for various formats may be seen at the links.
+
+Examples in this section assume:
+
+ t = Time.now # => 2022-06-29 16:49:25.465246 -0500
+
+==== Dates
+
+See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates].
+
+- {Years}[https://en.wikipedia.org/wiki/ISO_8601#Years]:
+
+ - Basic year (+YYYY+):
+
+ t.strftime('%Y') # => "2022"
+
+ - Expanded year (<tt>±YYYYY</tt>):
+
+ t.strftime('+%5Y') # => "+02022"
+ t.strftime('-%5Y') # => "-02022"
+
+- {Calendar dates}[https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates]:
+
+ - Basic date (+YYYYMMDD+):
+
+ t.strftime('%Y%m%d') # => "20220629"
+
+ - Extended date (<tt>YYYY-MM-DD</tt>):
+
+ t.strftime('%Y-%m-%d') # => "2022-06-29"
+
+ - Reduced extended date (<tt>YYYY-MM</tt>):
+
+ t.strftime('%Y-%m') # => "2022-06"
+
+- {Week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates]:
+
+ - Basic date (+YYYYWww+ or +YYYYWwwD+):
+
+ t.strftime('%Y%Ww') # => "202226w"
+ t.strftime('%Y%Ww%u') # => "202226w3"
+
+ - Extended date (<tt>YYYY-Www</tt> or <tt>YYYY-Www-D<tt>):
+
+ t.strftime('%Y-%Ww') # => "2022-26w"
+ t.strftime('%Y-%Ww-%u') # => "2022-26w-3"
+
+- {Ordinal dates}[https://en.wikipedia.org/wiki/ISO_8601#Ordinal_dates]:
+
+ - Basic date (+YYYYDDD+):
+
+ t.strftime('%Y%j') # => "2022180"
+
+ - Extended date (<tt>YYYY-DDD</tt>):
+
+ t.strftime('%Y-%j') # => "2022-180"
+
+==== Times
+
+See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times].
+
+- Times:
+
+ - Basic time (+Thhmmss.sss+, +Thhmmss+, +Thhmm+, or +Thh+):
+
+ t.strftime('T%H%M%S.%L') # => "T164925.465"
+ t.strftime('T%H%M%S') # => "T164925"
+ t.strftime('T%H%M') # => "T1649"
+ t.strftime('T%H') # => "T16"
+
+ - Extended time (+Thh:mm:ss.sss+, +Thh:mm:ss+, or +Thh:mm+):
+
+ t.strftime('T%H:%M:%S.%L') # => "T16:49:25.465"
+ t.strftime('T%H:%M:%S') # => "T16:49:25"
+ t.strftime('T%H:%M') # => "T16:49"
+
+- {Time zone designators}[https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators]:
+
+ - Timezone (+time+ represents a valid time,
+ +hh+ represents a valid 2-digit hour,
+ and +mm+ represents a valid 2-digit minute):
+
+ - Basic timezone (<tt>time±hhmm</tt>, <tt>time±hh</tt>, or +timeZ+):
+
+ t.strftime('T%H%M%S%z') # => "T164925-0500"
+ t.strftime('T%H%M%S%z').slice(0..-3) # => "T164925-05"
+ t.strftime('T%H%M%SZ') # => "T164925Z"
+
+ - Extended timezone (<tt>time±hh:mm</tt>):
+
+ t.strftime('T%H:%M:%S%z') # => "T16:49:25-0500"
+
+ - See also:
+
+ - {Local time (unqualified)}[https://en.wikipedia.org/wiki/ISO_8601#Local_time_(unqualified)].
+ - {Coordinated Universal Time (UTC)}[https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)].
+ - {Time offsets from UTC}[https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC].
+
+==== Combined \Date and \Time
+
+See {ISO 8601 Combined date and time representations}[https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations].
+
+An ISO 8601 combined date and time representation may be any
+ISO 8601 date and any ISO 8601 time,
+separated by the letter +T+.
+
+For the relevant +strftime+ formats, see
+{Dates}[rdoc-ref:strftime_formatting.rdoc@Dates]
+and {Times}[rdoc-ref:strftime_formatting.rdoc@Times] above.
diff --git a/doc/string/b.rdoc b/doc/string/b.rdoc
new file mode 100644
index 0000000000..f8ad2910b4
--- /dev/null
+++ b/doc/string/b.rdoc
@@ -0,0 +1,14 @@
+Returns a copy of +self+ that has ASCII-8BIT encoding;
+the underlying bytes are not modified:
+
+ s = "\x99"
+ s.encoding # => #<Encoding:UTF-8>
+ t = s.b # => "\x99"
+ t.encoding # => #<Encoding:ASCII-8BIT>
+
+ s = "\u4095" # => "䂕"
+ s.encoding # => #<Encoding:UTF-8>
+ s.bytes # => [228, 130, 149]
+ t = s.b # => "\xE4\x82\x95"
+ t.encoding # => #<Encoding:ASCII-8BIT>
+ t.bytes # => [228, 130, 149]
diff --git a/doc/string/bytes.rdoc b/doc/string/bytes.rdoc
new file mode 100644
index 0000000000..a9e89f1cd1
--- /dev/null
+++ b/doc/string/bytes.rdoc
@@ -0,0 +1,6 @@
+Returns an array of the bytes in +self+:
+
+ 'hello'.bytes # => [104, 101, 108, 108, 111]
+ 'тест'.bytes # => [209, 130, 208, 181, 209, 129, 209, 130]
+ 'こんにちは'.bytes
+ # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
diff --git a/doc/string/bytesize.rdoc b/doc/string/bytesize.rdoc
new file mode 100644
index 0000000000..b0567ff67b
--- /dev/null
+++ b/doc/string/bytesize.rdoc
@@ -0,0 +1,11 @@
+Returns the count of bytes (not characters) in +self+:
+
+ 'foo'.bytesize # => 3
+ 'тест'.bytesize # => 8
+ 'こんにちは'.bytesize # => 15
+
+Contrast with String#length:
+
+ 'foo'.length # => 3
+ 'тест'.length # => 4
+ 'こんにちは'.length # => 5
diff --git a/doc/string/center.rdoc b/doc/string/center.rdoc
new file mode 100644
index 0000000000..d53d921ad5
--- /dev/null
+++ b/doc/string/center.rdoc
@@ -0,0 +1,16 @@
+Returns a centered copy of +self+.
+
+If integer argument +size+ is greater than the size (in characters) of +self+,
+returns a new string of length +size+ that is a copy of +self+,
+centered and padded on both ends with +pad_string+:
+
+ 'hello'.center(10) # => " hello "
+ ' hello'.center(10) # => " hello "
+ 'hello'.center(10, 'ab') # => "abhelloaba"
+ 'тест'.center(10) # => " тест "
+ 'こんにちは'.center(10) # => " こんにちは "
+
+If +size+ is not greater than the size of +self+, returns a copy of +self+:
+
+ 'hello'.center(5) # => "hello"
+ 'hello'.center(1) # => "hello"
diff --git a/doc/string/chars.rdoc b/doc/string/chars.rdoc
new file mode 100644
index 0000000000..d24a1cc3a9
--- /dev/null
+++ b/doc/string/chars.rdoc
@@ -0,0 +1,5 @@
+Returns an array of the characters in +self+:
+
+ 'hello'.chars # => ["h", "e", "l", "l", "o"]
+ 'тест'.chars # => ["т", "е", "с", "т"]
+ 'こんにちは'.chars # => ["こ", "ん", "に", "ち", "は"]
diff --git a/doc/string/chomp.rdoc b/doc/string/chomp.rdoc
new file mode 100644
index 0000000000..b6fb9ff38c
--- /dev/null
+++ b/doc/string/chomp.rdoc
@@ -0,0 +1,29 @@
+Returns a new string copied from +self+, with trailing characters possibly removed:
+
+When +line_sep+ is <tt>"\n"</tt>, removes the last one or two characters
+if they are <tt>"\r"</tt>, <tt>"\n"</tt>, or <tt>"\r\n"</tt>
+(but not <tt>"\n\r"</tt>):
+
+ $/ # => "\n"
+ "abc\r".chomp # => "abc"
+ "abc\n".chomp # => "abc"
+ "abc\r\n".chomp # => "abc"
+ "abc\n\r".chomp # => "abc\n"
+ "тест\r\n".chomp # => "тест"
+ "こんにちは\r\n".chomp # => "こんにちは"
+
+When +line_sep+ is <tt>''</tt> (an empty string),
+removes multiple trailing occurrences of <tt>"\n"</tt> or <tt>"\r\n"</tt>
+(but not <tt>"\r"</tt> or <tt>"\n\r"</tt>):
+
+ "abc\n\n\n".chomp('') # => "abc"
+ "abc\r\n\r\n\r\n".chomp('') # => "abc"
+ "abc\n\n\r\n\r\n\n\n".chomp('') # => "abc"
+ "abc\n\r\n\r\n\r".chomp('') # => "abc\n\r\n\r\n\r"
+ "abc\r\r\r".chomp('') # => "abc\r\r\r"
+
+When +line_sep+ is neither <tt>"\n"</tt> nor <tt>''</tt>,
+removes a single trailing line separator if there is one:
+
+ 'abcd'.chomp('d') # => "abc"
+ 'abcdd'.chomp('d') # => "abcd"
diff --git a/doc/string/chop.rdoc b/doc/string/chop.rdoc
new file mode 100644
index 0000000000..8ef82f8a49
--- /dev/null
+++ b/doc/string/chop.rdoc
@@ -0,0 +1,16 @@
+Returns a new string copied from +self+, with trailing characters possibly removed.
+
+Removes <tt>"\r\n"</tt> if those are the last two characters.
+
+ "abc\r\n".chop # => "abc"
+ "тест\r\n".chop # => "тест"
+ "こんにちは\r\n".chop # => "こんにちは"
+
+Otherwise removes the last character if it exists.
+
+ 'abcd'.chop # => "abc"
+ 'тест'.chop # => "тес"
+ 'こんにちは'.chop # => "こんにち"
+ ''.chop # => ""
+
+If you only need to remove the newline separator at the end of the string, String#chomp is a better alternative.
diff --git a/doc/string/codepoints.rdoc b/doc/string/codepoints.rdoc
new file mode 100644
index 0000000000..0c55d3f4b9
--- /dev/null
+++ b/doc/string/codepoints.rdoc
@@ -0,0 +1,6 @@
+Returns an array of the codepoints in +self+;
+each codepoint is the integer value for a character:
+
+ 'hello'.codepoints # => [104, 101, 108, 108, 111]
+ 'тест'.codepoints # => [1090, 1077, 1089, 1090]
+ 'こんにちは'.codepoints # => [12371, 12435, 12395, 12385, 12399]
diff --git a/doc/string/delete_prefix.rdoc b/doc/string/delete_prefix.rdoc
new file mode 100644
index 0000000000..fa9d8abd38
--- /dev/null
+++ b/doc/string/delete_prefix.rdoc
@@ -0,0 +1,8 @@
+Returns a copy of +self+ with leading substring <tt>prefix</tt> removed:
+
+ 'hello'.delete_prefix('hel') # => "lo"
+ 'hello'.delete_prefix('llo') # => "hello"
+ 'тест'.delete_prefix('те') # => "ст"
+ 'こんにちは'.delete_prefix('こん') # => "にちは"
+
+Related: String#delete_prefix!, String#delete_suffix.
diff --git a/doc/string/delete_suffix.rdoc b/doc/string/delete_suffix.rdoc
new file mode 100644
index 0000000000..4862b725cf
--- /dev/null
+++ b/doc/string/delete_suffix.rdoc
@@ -0,0 +1,8 @@
+Returns a copy of +self+ with trailing substring <tt>suffix</tt> removed:
+
+ 'hello'.delete_suffix('llo') # => "he"
+ 'hello'.delete_suffix('hel') # => "hello"
+ 'тест'.delete_suffix('ст') # => "те"
+ 'こんにちは'.delete_suffix('ちは') # => "こんに"
+
+Related: String#delete_suffix!, String#delete_prefix.
diff --git a/doc/string/each_byte.rdoc b/doc/string/each_byte.rdoc
new file mode 100644
index 0000000000..643118fea3
--- /dev/null
+++ b/doc/string/each_byte.rdoc
@@ -0,0 +1,17 @@
+Calls the given block with each successive byte from +self+;
+returns +self+:
+
+ 'hello'.each_byte {|byte| print byte, ' ' }
+ print "\n"
+ 'тест'.each_byte {|byte| print byte, ' ' }
+ print "\n"
+ 'こんにちは'.each_byte {|byte| print byte, ' ' }
+ print "\n"
+
+Output:
+
+ 104 101 108 108 111
+ 209 130 208 181 209 129 209 130
+ 227 129 147 227 130 147 227 129 171 227 129 161 227 129 175
+
+Returns an enumerator if no block is given.
diff --git a/doc/string/each_char.rdoc b/doc/string/each_char.rdoc
new file mode 100644
index 0000000000..e5ae5a1812
--- /dev/null
+++ b/doc/string/each_char.rdoc
@@ -0,0 +1,17 @@
+Calls the given block with each successive character from +self+;
+returns +self+:
+
+ 'hello'.each_char {|char| print char, ' ' }
+ print "\n"
+ 'тест'.each_char {|char| print char, ' ' }
+ print "\n"
+ 'こんにちは'.each_char {|char| print char, ' ' }
+ print "\n"
+
+Output:
+
+ h e l l o
+ т е с т
+ こ ん に ち は
+
+Returns an enumerator if no block is given.
diff --git a/doc/string/each_codepoint.rdoc b/doc/string/each_codepoint.rdoc
new file mode 100644
index 0000000000..88bfcbd1c0
--- /dev/null
+++ b/doc/string/each_codepoint.rdoc
@@ -0,0 +1,18 @@
+Calls the given block with each successive codepoint from +self+;
+each codepoint is the integer value for a character;
+returns +self+:
+
+ 'hello'.each_codepoint {|codepoint| print codepoint, ' ' }
+ print "\n"
+ 'тест'.each_codepoint {|codepoint| print codepoint, ' ' }
+ print "\n"
+ 'こんにちは'.each_codepoint {|codepoint| print codepoint, ' ' }
+ print "\n"
+
+Output:
+
+ 104 101 108 108 111
+ 1090 1077 1089 1090
+ 12371 12435 12395 12385 12399
+
+Returns an enumerator if no block is given.
diff --git a/doc/string/each_grapheme_cluster.rdoc b/doc/string/each_grapheme_cluster.rdoc
new file mode 100644
index 0000000000..40be95fcac
--- /dev/null
+++ b/doc/string/each_grapheme_cluster.rdoc
@@ -0,0 +1,12 @@
+Calls the given block with each successive grapheme cluster from +self+
+(see {Unicode Grapheme Cluster Boundaries}[https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries]);
+returns +self+:
+
+ s = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
+ s.each_grapheme_cluster {|gc| print gc, ' ' }
+
+Output:
+
+ ä - p q r - b̈ - x y z - c̈
+
+Returns an enumerator if no block is given.
diff --git a/doc/string/each_line.rdoc b/doc/string/each_line.rdoc
new file mode 100644
index 0000000000..e254c22d40
--- /dev/null
+++ b/doc/string/each_line.rdoc
@@ -0,0 +1,60 @@
+With a block given, forms the substrings ("lines")
+that are the result of splitting +self+
+at each occurrence of the given line separator +line_sep+;
+passes each line to the block;
+returns +self+:
+
+ s = <<~EOT
+ This is the first line.
+ This is line two.
+
+ This is line four.
+ This is line five.
+ EOT
+
+ s.each_line {|line| p line }
+
+Output:
+
+ "This is the first line.\n"
+ "This is line two.\n"
+ "\n"
+ "This is line four.\n"
+ "This is line five.\n"
+
+With a different +line_sep+:
+
+ s.each_line(' is ') {|line| p line }
+
+Output:
+
+ "This is "
+ "the first line.\nThis is "
+ "line two.\n\nThis is "
+ "line four.\nThis is "
+ "line five.\n"
+
+With +chomp+ as +true+, removes the trailing +line_sep+ from each line:
+
+ s.each_line(chomp: true) {|line| p line }
+
+Output:
+
+ "This is the first line."
+ "This is line two."
+ ""
+ "This is line four."
+ "This is line five."
+
+With an empty string as +line_sep+,
+forms and passes "paragraphs" by splitting at each occurrence
+of two or more newlines:
+
+ s.each_line('') {|line| p line }
+
+Output:
+
+ "This is the first line.\nThis is line two.\n\n"
+ "This is line four.\nThis is line five.\n"
+
+With no block given, returns an enumerator.
diff --git a/doc/string/end_with_p.rdoc b/doc/string/end_with_p.rdoc
new file mode 100644
index 0000000000..f959cf7aaa
--- /dev/null
+++ b/doc/string/end_with_p.rdoc
@@ -0,0 +1,11 @@
+Returns whether +self+ ends with any of the given +strings+.
+
+Returns +true+ if any given string matches the end, +false+ otherwise:
+
+ 'hello'.end_with?('ello') #=> true
+ 'hello'.end_with?('heaven', 'ello') #=> true
+ 'hello'.end_with?('heaven', 'paradise') #=> false
+ 'тест'.end_with?('т') # => true
+ 'こんにちは'.end_with?('は') # => true
+
+Related: String#start_with?.
diff --git a/doc/string/force_encoding.rdoc b/doc/string/force_encoding.rdoc
new file mode 100644
index 0000000000..fd9615caaa
--- /dev/null
+++ b/doc/string/force_encoding.rdoc
@@ -0,0 +1,20 @@
+Changes the encoding of +self+ to +encoding+,
+which may be a string encoding name or an Encoding object;
+returns self:
+
+ s = 'łał'
+ s.bytes # => [197, 130, 97, 197, 130]
+ s.encoding # => #<Encoding:UTF-8>
+ s.force_encoding('ascii') # => "\xC5\x82a\xC5\x82"
+ s.encoding # => #<Encoding:US-ASCII>
+
+Does not change the underlying bytes:
+
+ s.bytes # => [197, 130, 97, 197, 130]
+
+Makes the change even if the given +encoding+ is invalid
+for +self+ (as is the change above):
+
+ s.valid_encoding? # => false
+ s.force_encoding(Encoding::UTF_8) # => "łał"
+ s.valid_encoding? # => true
diff --git a/doc/string/grapheme_clusters.rdoc b/doc/string/grapheme_clusters.rdoc
new file mode 100644
index 0000000000..8c7f5a7259
--- /dev/null
+++ b/doc/string/grapheme_clusters.rdoc
@@ -0,0 +1,6 @@
+Returns an array of the grapheme clusters in +self+
+(see {Unicode Grapheme Cluster Boundaries}[https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries]):
+
+ s = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
+ s.grapheme_clusters
+ # => ["ä", "-", "p", "q", "r", "-", "b̈", "-", "x", "y", "z", "-", "c̈"]
diff --git a/doc/string/index.rdoc b/doc/string/index.rdoc
new file mode 100644
index 0000000000..ce09a37bdf
--- /dev/null
+++ b/doc/string/index.rdoc
@@ -0,0 +1,38 @@
+Returns the integer index of the first match for the given argument,
+or +nil+ if none found;
+the search of +self+ is forward, and begins at position +offset+ (in characters).
+
+With string argument +substring+,
+returns the index of the first matching substring in +self+:
+
+ 'foo'.index('f') # => 0
+ 'foo'.index('o') # => 1
+ 'foo'.index('oo') # => 1
+ 'foo'.index('ooo') # => nil
+ 'тест'.index('с') # => 2
+ 'こんにちは'.index('ち') # => 3
+
+With Regexp argument +regexp+, returns the index of the first match in +self+:
+
+ 'foo'.index(/o./) # => 1
+ 'foo'.index(/.o/) # => 0
+
+With positive integer +offset+, begins the search at position +offset+:
+
+ 'foo'.index('o', 1) # => 1
+ 'foo'.index('o', 2) # => 2
+ 'foo'.index('o', 3) # => nil
+ 'тест'.index('с', 1) # => 2
+ 'こんにちは'.index('ち', 2) # => 3
+
+With negative integer +offset+, selects the search position by counting 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
+ 'foo'.index(/o./, -2) # => 1
+ 'foo'.index(/.o/, -2) # => 1
+
+Related: String#rindex.
diff --git a/doc/string/length.rdoc b/doc/string/length.rdoc
new file mode 100644
index 0000000000..0a7e17f7dc
--- /dev/null
+++ b/doc/string/length.rdoc
@@ -0,0 +1,13 @@
+Returns the count of characters (not bytes) in +self+:
+
+ 'foo'.length # => 3
+ 'тест'.length # => 4
+ 'こんにちは'.length # => 5
+
+Contrast with String#bytesize:
+
+ 'foo'.bytesize # => 3
+ 'тест'.bytesize # => 8
+ 'こんにちは'.bytesize # => 15
+
+String#size is an alias for String#length.
diff --git a/doc/string/ljust.rdoc b/doc/string/ljust.rdoc
new file mode 100644
index 0000000000..8e23c1fc8f
--- /dev/null
+++ b/doc/string/ljust.rdoc
@@ -0,0 +1,16 @@
+Returns a left-justified copy of +self+.
+
+If integer argument +size+ is greater than the size (in characters) of +self+,
+returns a new string of length +size+ that is a copy of +self+,
+left justified and padded on the right with +pad_string+:
+
+ 'hello'.ljust(10) # => "hello "
+ ' hello'.ljust(10) # => " hello "
+ 'hello'.ljust(10, 'ab') # => "helloababa"
+ 'тест'.ljust(10) # => "тест "
+ 'こんにちは'.ljust(10) # => "こんにちは "
+
+If +size+ is not greater than the size of +self+, returns a copy of +self+:
+
+ 'hello'.ljust(5) # => "hello"
+ 'hello'.ljust(1) # => "hello"
diff --git a/doc/string/new.rdoc b/doc/string/new.rdoc
new file mode 100644
index 0000000000..d955e61c87
--- /dev/null
+++ b/doc/string/new.rdoc
@@ -0,0 +1,51 @@
+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 optional argument +string+ and no keyword arguments,
+returns a copy of +string+ with the same encoding:
+
+ String.new('foo') # => "foo"
+ String.new('тест') # => "тест"
+ String.new('こんにちは') # => "こんにちは"
+
+(Unlike \String.new,
+a {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals] like <tt>''</tt> or a
+{here document literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals]
+always has {script encoding}[rdoc-ref:encodings.rdoc@Script+Encoding].)
+
+With optional keyword argument +encoding+, returns a copy of +string+
+with the specified encoding;
+the +encoding+ may be an Encoding object, an encoding name,
+or an encoding name alias:
+
+ String.new('foo', encoding: Encoding::US_ASCII).encoding # => #<Encoding:US-ASCII>
+ String.new('foo', encoding: 'US-ASCII').encoding # => #<Encoding:US-ASCII>
+ String.new('foo', encoding: 'ASCII').encoding # => #<Encoding:US-ASCII>
+
+The given encoding need not be valid for the string's content,
+and that validity is not checked:
+
+ s = String.new('こんにちは', encoding: 'ascii')
+ s.valid_encoding? # => false
+
+But the given +encoding+ itself is checked:
+
+ String.new('foo', encoding: 'bar') # Raises ArgumentError.
+
+With optional keyword argument +capacity+, returns a copy of +string+
+(or an empty string, if +string+ is not given);
+the given +capacity+ is advisory only,
+and may or may not set the size of the internal buffer,
+which may in turn affect performance:
+
+ String.new(capacity: 1)
+ String.new('foo', capacity: 4096)
+
+The +string+, +encoding+, and +capacity+ arguments may all be used together:
+
+ String.new('hello', encoding: 'UTF-8', capacity: 25)
diff --git a/doc/string/ord.rdoc b/doc/string/ord.rdoc
new file mode 100644
index 0000000000..d586363d44
--- /dev/null
+++ b/doc/string/ord.rdoc
@@ -0,0 +1,6 @@
+Returns the integer ordinal of the first character of +self+:
+
+ 'h'.ord # => 104
+ 'hello'.ord # => 104
+ 'тест'.ord # => 1090
+ 'こんにちは'.ord # => 12371
diff --git a/doc/string/partition.rdoc b/doc/string/partition.rdoc
new file mode 100644
index 0000000000..ebe575e8eb
--- /dev/null
+++ b/doc/string/partition.rdoc
@@ -0,0 +1,24 @@
+Returns a 3-element array of substrings of +self+.
+
+Matches a pattern against +self+, scanning from the beginning.
+The pattern is:
+
+- +string_or_regexp+ itself, if it is a Regexp.
+- <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
+
+If the pattern is matched, returns pre-match, first-match, post-match:
+
+ 'hello'.partition('l') # => ["he", "l", "lo"]
+ 'hello'.partition('ll') # => ["he", "ll", "o"]
+ 'hello'.partition('h') # => ["", "h", "ello"]
+ 'hello'.partition('o') # => ["hell", "o", ""]
+ 'hello'.partition(/l+/) #=> ["he", "ll", "o"]
+ 'hello'.partition('') # => ["", "", "hello"]
+ 'тест'.partition('т') # => ["", "т", "ест"]
+ 'こんにちは'.partition('に') # => ["こん", "に", "ちは"]
+
+If the pattern is not matched, returns a copy of +self+ and two empty strings:
+
+ 'hello'.partition('x') # => ["hello", "", ""]
+
+Related: String#rpartition, String#split.
diff --git a/doc/string/rjust.rdoc b/doc/string/rjust.rdoc
new file mode 100644
index 0000000000..24e7bf3159
--- /dev/null
+++ b/doc/string/rjust.rdoc
@@ -0,0 +1,16 @@
+Returns a right-justified copy of +self+.
+
+If integer argument +size+ is greater than the size (in characters) of +self+,
+returns a new string of length +size+ that is a copy of +self+,
+right justified and padded on the left with +pad_string+:
+
+ 'hello'.rjust(10) # => " hello"
+ 'hello '.rjust(10) # => " hello "
+ 'hello'.rjust(10, 'ab') # => "ababahello"
+ 'тест'.rjust(10) # => " тест"
+ 'こんにちは'.rjust(10) # => " こんにちは"
+
+If +size+ is not greater than the size of +self+, returns a copy of +self+:
+
+ 'hello'.rjust(5, 'ab') # => "hello"
+ 'hello'.rjust(1, 'ab') # => "hello"
diff --git a/doc/string/rpartition.rdoc b/doc/string/rpartition.rdoc
new file mode 100644
index 0000000000..d24106fb9f
--- /dev/null
+++ b/doc/string/rpartition.rdoc
@@ -0,0 +1,24 @@
+Returns a 3-element array of substrings of +self+.
+
+Matches a pattern against +self+, scanning backwards from the end.
+The pattern is:
+
+- +string_or_regexp+ itself, if it is a Regexp.
+- <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
+
+If the pattern is matched, returns pre-match, last-match, post-match:
+
+ 'hello'.rpartition('l') # => ["hel", "l", "o"]
+ 'hello'.rpartition('ll') # => ["he", "ll", "o"]
+ 'hello'.rpartition('h') # => ["", "h", "ello"]
+ 'hello'.rpartition('o') # => ["hell", "o", ""]
+ 'hello'.rpartition(/l+/) # => ["hel", "l", "o"]
+ 'hello'.rpartition('') # => ["hello", "", ""]
+ 'тест'.rpartition('т') # => ["тес", "т", ""]
+ 'こんにちは'.rpartition('に') # => ["こん", "に", "ちは"]
+
+If the pattern is not matched, returns two empty strings and a copy of +self+:
+
+ 'hello'.rpartition('x') # => ["", "", "hello"]
+
+Related: String#partition, String#split.
diff --git a/doc/string/scrub.rdoc b/doc/string/scrub.rdoc
new file mode 100644
index 0000000000..1a5b1c79d0
--- /dev/null
+++ b/doc/string/scrub.rdoc
@@ -0,0 +1,25 @@
+Returns a copy of +self+ with each invalid byte sequence replaced
+by the given +replacement_string+.
+
+With no block given and no argument, replaces each invalid sequence
+with the default replacement string
+(<tt>"�"</tt> for a Unicode encoding, <tt>'?'</tt> otherwise):
+
+ s = "foo\x81\x81bar"
+ s.scrub # => "foo��bar"
+
+With no block given and argument +replacement_string+ given,
+replaces each invalid sequence with that string:
+
+ "foo\x81\x81bar".scrub('xyzzy') # => "fooxyzzyxyzzybar"
+
+With a block given, replaces each invalid sequence with the value
+of the block:
+
+ "foo\x81\x81bar".scrub {|bytes| p bytes; 'XYZZY' }
+ # => "fooXYZZYXYZZYbar"
+
+Output:
+
+ "\x81"
+ "\x81"
diff --git a/doc/string/split.rdoc b/doc/string/split.rdoc
new file mode 100644
index 0000000000..2b5e14ddb6
--- /dev/null
+++ b/doc/string/split.rdoc
@@ -0,0 +1,86 @@
+Returns an array of substrings of +self+
+that are the result of splitting +self+
+at each occurrence of the given field separator +field_sep+.
+
+When +field_sep+ is <tt>$;</tt>:
+
+- If <tt>$;</tt> is +nil+ (its default value),
+ the split occurs just as if +field_sep+ were given as a space character
+ (see below).
+
+- If <tt>$;</tt> is a string,
+ the split ocurs just as if +field_sep+ were given as that string
+ (see below).
+
+When +field_sep+ is <tt>' '</tt> and +limit+ is +nil+,
+the split occurs at each sequence of whitespace:
+
+ 'abc def ghi'.split(' ') => ["abc", "def", "ghi"]
+ "abc \n\tdef\t\n ghi".split(' ') # => ["abc", "def", "ghi"]
+ 'abc def ghi'.split(' ') => ["abc", "def", "ghi"]
+ ''.split(' ') => []
+
+When +field_sep+ is a string different from <tt>' '</tt>
+and +limit+ is +nil+,
+the split occurs at each occurrence of +field_sep+;
+trailing empty substrings are not returned:
+
+ 'abracadabra'.split('ab') => ["", "racad", "ra"]
+ 'aaabcdaaa'.split('a') => ["", "", "", "bcd"]
+ ''.split('a') => []
+ '3.14159'.split('1') => ["3.", "4", "59"]
+ '!@#$%^$&*($)_+'.split('$') # => ["!@#", "%^", "&*(", ")_+"]
+ 'тест'.split('т') => ["", "ес"]
+ 'こんにちは'.split('に') => ["こん", "ちは"]
+
+When +field_sep+ is a Regexp and +limit+ is +nil+,
+the split occurs at each occurrence of a match;
+trailing empty substrings are not returned:
+
+ 'abracadabra'.split(/ab/) # => ["", "racad", "ra"]
+ 'aaabcdaaa'.split(/a/) => ["", "", "", "bcd"]
+ 'aaabcdaaa'.split(//) => ["a", "a", "a", "b", "c", "d", "a", "a", "a"]
+ '1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"]
+
+If the \Regexp contains groups, their matches are also included
+in the returned array:
+
+ '1:2:3'.split(/(:)()()/, 2) # => ["1", ":", "", "", "2:3"]
+
+As seen above, if +limit+ is +nil+,
+trailing empty substrings are not returned;
+the same is true if +limit+ is zero:
+
+ 'aaabcdaaa'.split('a') => ["", "", "", "bcd"]
+ 'aaabcdaaa'.split('a', 0) # => ["", "", "", "bcd"]
+
+If +limit+ is positive integer +n+, no more than <tt>n - 1-</tt>
+splits occur, so that at most +n+ substrings are returned,
+and trailing empty substrings are included:
+
+ 'aaabcdaaa'.split('a', 1) # => ["aaabcdaaa"]
+ 'aaabcdaaa'.split('a', 2) # => ["", "aabcdaaa"]
+ 'aaabcdaaa'.split('a', 5) # => ["", "", "", "bcd", "aa"]
+ 'aaabcdaaa'.split('a', 7) # => ["", "", "", "bcd", "", "", ""]
+ 'aaabcdaaa'.split('a', 8) # => ["", "", "", "bcd", "", "", ""]
+
+Note that if +field_sep+ is a \Regexp containing groups,
+their matches are in the returned array, but do not count toward the limit.
+
+If +limit+ is negative, it behaves the same as if +limit+ was +nil+,
+meaning that there is no limit,
+and trailing empty substrings are included:
+
+ 'aaabcdaaa'.split('a', -1) # => ["", "", "", "bcd", "", "", ""]
+
+If a block is given, it is called with each substring:
+
+ 'abc def ghi'.split(' ') {|substring| p substring }
+
+Output:
+
+ "abc"
+ "def"
+ "ghi"
+
+Related: String#partition, String#rpartition.
diff --git a/doc/string/start_with_p.rdoc b/doc/string/start_with_p.rdoc
new file mode 100644
index 0000000000..5d1f9f9543
--- /dev/null
+++ b/doc/string/start_with_p.rdoc
@@ -0,0 +1,18 @@
+Returns whether +self+ starts with any of the given +string_or_regexp+.
+
+Matches patterns against the beginning of +self+.
+For each given +string_or_regexp+, the pattern is:
+
+- +string_or_regexp+ itself, if it is a Regexp.
+- <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
+
+Returns +true+ if any pattern matches the beginning, +false+ otherwise:
+
+ 'hello'.start_with?('hell') # => true
+ 'hello'.start_with?(/H/i) # => true
+ 'hello'.start_with?('heaven', 'hell') # => true
+ 'hello'.start_with?('heaven', 'paradise') # => false
+ 'тест'.start_with?('т') # => true
+ 'こんにちは'.start_with?('こ') # => true
+
+Related: String#end_with?.
diff --git a/doc/string/sum.rdoc b/doc/string/sum.rdoc
new file mode 100644
index 0000000000..5de24e6402
--- /dev/null
+++ b/doc/string/sum.rdoc
@@ -0,0 +1,11 @@
+Returns a basic +n+-bit checksum of the characters in +self+;
+the checksum is the sum of the binary value of each byte in +self+,
+modulo <tt>2**n - 1</tt>:
+
+ 'hello'.sum # => 532
+ 'hello'.sum(4) # => 4
+ 'hello'.sum(64) # => 532
+ 'тест'.sum # => 1405
+ 'こんにちは'.sum # => 2582
+
+This is not a particularly strong checksum.
diff --git a/doc/symbol/casecmp.rdoc b/doc/symbol/casecmp.rdoc
new file mode 100644
index 0000000000..9c286070b7
--- /dev/null
+++ b/doc/symbol/casecmp.rdoc
@@ -0,0 +1,27 @@
+Like Symbol#<=>, but case-insensitive;
+equivalent to <tt>self.to_s.casecmp(object.to_s)</tt>:
+
+ lower = :abc
+ upper = :ABC
+ upper.casecmp(lower) # => 0
+ lower.casecmp(lower) # => 0
+ lower.casecmp(upper) # => 0
+
+Returns nil if +self+ and +object+ have incompatible encodings,
+or if +object+ is not a symbol:
+
+ sym = 'äöü'.encode("ISO-8859-1").to_sym
+ other_sym = 'ÄÖÜ'
+ sym.casecmp(other_sym) # => nil
+ :foo.casecmp(2) # => nil
+
+Unlike Symbol#casecmp?,
+case-insensitivity does not work for characters outside of 'A'..'Z' and 'a'..'z':
+
+ lower = :äöü
+ upper = :ÄÖÜ
+ upper.casecmp(lower) # => -1
+ lower.casecmp(lower) # => 0
+ lower.casecmp(upper) # => 1
+
+Related: Symbol#casecmp?, String#casecmp.
diff --git a/doc/symbol/casecmp_p.rdoc b/doc/symbol/casecmp_p.rdoc
new file mode 100644
index 0000000000..7102b54289
--- /dev/null
+++ b/doc/symbol/casecmp_p.rdoc
@@ -0,0 +1,26 @@
+Returns +true+ if +self+ and +object+ are equal after Unicode case folding,
+otherwise +false+:
+
+ lower = :abc
+ upper = :ABC
+ upper.casecmp?(lower) # => true
+ lower.casecmp?(lower) # => true
+ lower.casecmp?(upper) # => true
+
+Returns nil if +self+ and +object+ have incompatible encodings,
+or if +object+ is not a symbol:
+
+ sym = 'äöü'.encode("ISO-8859-1").to_sym
+ other_sym = 'ÄÖÜ'
+ sym.casecmp?(other_sym) # => nil
+ :foo.casecmp?(2) # => nil
+
+Unlike Symbol#casecmp, works for characters outside of 'A'..'Z' and 'a'..'z':
+
+ lower = :äöü
+ upper = :ÄÖÜ
+ upper.casecmp?(lower) # => true
+ lower.casecmp?(lower) # => true
+ lower.casecmp?(upper) # => true
+
+Related: Symbol#casecmp, String#casecmp?.
diff --git a/doc/syntax/assignment.rdoc b/doc/syntax/assignment.rdoc
index a1806e4c48..1321bbf3ac 100644
--- a/doc/syntax/assignment.rdoc
+++ b/doc/syntax/assignment.rdoc
@@ -8,6 +8,9 @@ example assigns the number five to the local variable +v+:
Assignment creates a local variable if the variable was not previously
referenced.
+An assignment expression result is always the assigned value, including
+{assignment methods}[rdoc-ref:syntax/assignment.rdoc@Assignment+Methods].
+
== Local Variable Names
A local variable name must start with a lowercase US-ASCII letter or a
@@ -342,6 +345,9 @@ This prints:
local_variables:
@value: 42
+Note that the value returned by an assignment method is ignored whatever,
+since an assignment expression result is always the assignment value.
+
== Abbreviated Assignment
You can mix several of the operators and assignment. To add 1 to an object
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
index fc806d5c31..da061dbfdb 100644
--- a/doc/syntax/calling_methods.rdoc
+++ b/doc/syntax/calling_methods.rdoc
@@ -210,6 +210,24 @@ definition. If a keyword argument is given that the method did not list,
and the method definition does not accept arbitrary keyword arguments, an
ArgumentError will be raised.
+Keyword argument value can be omitted, meaning the value will be be fetched
+from the context by the name of the key
+
+ keyword1 = 'some value'
+ my_method(positional1, keyword1:)
+ # ...is the same as
+ my_method(positional1, keyword1: keyword1)
+
+Be aware that when method parenthesis are omitted, too, the parsing order might
+be unexpected:
+
+ my_method positional1, keyword1:
+
+ some_other_expression
+
+ # ...is actually parsed as
+ my_method(positional1, keyword1: some_other_expression)
+
=== Block Argument
The block argument sends a closure from the calling scope to the method.
diff --git a/doc/syntax/comments.rdoc b/doc/syntax/comments.rdoc
index b361e077b6..dbc7816984 100644
--- a/doc/syntax/comments.rdoc
+++ b/doc/syntax/comments.rdoc
@@ -41,8 +41,7 @@ syntax error:
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>.
+Top-level magic comments must appear in the first comment section of a file.
NOTE: Magic comments affect only the file in which they appear;
other files are unaffected.
@@ -74,7 +73,8 @@ regexp literals and <code>__ENCODING__</code>:
Default encoding is UTF-8.
-It must appear in the first comment section of a file.
+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>.
The word "coding" may be used instead of "encoding".
diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc
index e91b03e72d..df3b5ced38 100644
--- a/doc/syntax/control_expressions.rdoc
+++ b/doc/syntax/control_expressions.rdoc
@@ -513,9 +513,9 @@ and modifier +if+ has lower precedence than <code>=</code>.
== Flip-Flop
-The flip-flop is a rarely seen conditional expression. It's primary use is
-for processing text from ruby one-line programs used with <code>ruby -n</code>
-or <code>ruby -p</code>.
+The flip-flop is a slightly special conditional expression. One of its
+typical uses is processing text from ruby one-line programs used with
+<code>ruby -n</code> or <code>ruby -p</code>.
The form of the flip-flop is an expression that indicates when the
flip-flop turns on, <code>..</code> (or <code>...</code>), then an expression
@@ -524,7 +524,6 @@ will continue to evaluate to +true+, and +false+ when off.
Here is an example:
-
selected = []
0.upto 10 do |value|
@@ -533,15 +532,16 @@ Here is an example:
p selected # prints [2, 3, 4, 5, 6, 7, 8]
-In the above example, the on condition is <code>n==2</code>. The flip-flop
-is initially off (false) for 0 and 1, but becomes on (true) for 2 and remains
-on through 8. After 8 it turns off and remains off for 9 and 10.
+In the above example, the `on' condition is <code>n==2</code>. The flip-flop
+is initially `off' (false) for 0 and 1, but becomes `on' (true) for 2 and
+remains `on' through 8. After 8 it turns off and remains `off' for 9 and 10.
-The flip-flop must be used inside a conditional such as +if+, +while+,
-+unless+, +until+ etc. including the modifier forms.
+The flip-flop must be used inside a conditional such as <code>!</code>,
+<code>? :</code>, +not+, +if+, +while+, +unless+, +until+ etc. including the
+modifier forms.
-When you use an inclusive range (<code>..</code>), the off condition is
-evaluated when the on condition changes:
+When you use an inclusive range (<code>..</code>), the `off' condition is
+evaluated when the `on' condition changes:
selected = []
@@ -555,7 +555,7 @@ Here, both sides of the flip-flop are evaluated so the flip-flop turns on and
off only when +value+ equals 2. Since the flip-flop turned on in the
iteration it returns true.
-When you use an exclusive range (<code>...</code>), the off condition is
+When you use an exclusive range (<code>...</code>), the `off' condition is
evaluated on the following iteration:
selected = []
@@ -567,5 +567,5 @@ evaluated on the following iteration:
p selected # prints [2, 3, 4, 5]
Here, the flip-flop turns on when +value+ equals 2, but doesn't turn off on the
-same iteration. The off condition isn't evaluated until the following
+same iteration. The `off' condition isn't evaluated until the following
iteration and +value+ will never be two again.
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
index cfdbb71700..b641433249 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -2,17 +2,33 @@
Literals create objects you can use in your program. Literals include:
-* Booleans and nil
-* Numbers
-* Strings
-* Symbols
-* Arrays
-* Hashes
-* Ranges
-* Regular Expressions
-* Procs
-
-== Booleans and nil
+* {Boolean and Nil Literals}[#label-Boolean+and+Nil+Literals]
+* {Number Literals}[#label-Number+Literals]
+
+ * {Integer Literals}[#label-Integer+Literals]
+ * {Float Literals}[#label-Float+Literals]
+ * {Rational Literals}[#label-Rational+Literals]
+ * {Complex Literals}[#label-Complex+Literals]
+
+* {String Literals}[#label-String+Literals]
+* {Here Document Literals}[#label-Here+Document+Literals]
+* {Symbol Literals}[#label-Symbol+Literals]
+* {Array Literals}[#label-Array+Literals]
+* {Hash Literals}[#label-Hash+Literals]
+* {Range Literals}[#label-Range+Literals]
+* {Regexp Literals}[#label-Regexp+Literals]
+* {Lambda Proc Literals}[#label-Lambda+Proc+Literals]
+* {Percent Literals}[#label-Percent+Literals]
+
+ * {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
+ * {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+ * {%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals]
+ * {%i and %I: Symbol-Array Literals}[#label-25i+and+-25I-3A+Symbol-Array+Literals]
+ * {%r: Regexp Literals}[#label-25r-3A+Regexp+Literals]
+ * {%s: Symbol Literals}[#label-25s-3A+Symbol+Literals]
+ * {%x: Backtick Literals}[#label-25x-3A+Backtick+Literals]
+
+== Boolean and Nil Literals
+nil+ and +false+ are both false values. +nil+ is sometimes used to indicate
"no value" or "unknown" but evaluates to +false+ in conditional expressions.
@@ -20,7 +36,9 @@ Literals create objects you can use in your program. Literals include:
+true+ is a true value. All objects except +nil+ and +false+ evaluate to a
true value in conditional expressions.
-== Numbers
+== Number Literals
+
+=== \Integer Literals
You can write integers of any size as follows:
@@ -31,15 +49,6 @@ These numbers have the same value, 1,234. The underscore may be used to
enhance readability for humans. You may place an underscore anywhere in the
number.
-Floating point numbers may be written as follows:
-
- 12.34
- 1234e-2
- 1.234E1
-
-These numbers have the same value, 12.34. You may use underscores in floating
-point numbers as well.
-
You can use a special prefix to write numbers in decimal, hexadecimal, octal
or binary formats. For decimal numbers use a prefix of <tt>0d</tt>, for
hexadecimal numbers use a prefix of <tt>0x</tt>, for octal numbers use a
@@ -68,35 +77,69 @@ Examples:
All these numbers have the same decimal value, 170. Like integers and floats
you may use an underscore for readability.
-=== Rational numbers
+=== \Float Literals
+
+Floating-point numbers may be written as follows:
+
+ 12.34
+ 1234e-2
+ 1.234E1
+
+These numbers have the same value, 12.34. You may use underscores in floating
+point numbers as well.
+
+=== \Rational Literals
+
+You can write a Rational literal using a special suffix, <tt>'r'</tt>.
-Numbers suffixed by +r+ are Rational numbers.
+Examples:
+
+ 1r # => (1/1)
+ 2/3r # => (2/3) # With denominator.
+ -1r # => (-1/1) # With signs.
+ -2/3r # => (-2/3)
+ 2/-3r # => (-2/3)
+ -2/-3r # => (2/3)
+ +1/+3r # => (1/3)
+ 1.2r # => (6/5) # With fractional part.
+ 1_1/2_1r # => (11/21) # With embedded underscores.
+ 2/4r # => (1/2) # Automatically reduced.
- 12r #=> (12/1)
- 12.3r #=> (123/10)
+Syntax:
-Rational numbers are exact, whereas Float numbers are inexact.
+ <rational-literal> = <numerator> [ '/' <denominator> ] 'r'
+ <numerator> = [ <sign> ] <digits> [ <fractional-part> ]
+ <fractional-part> = '.' <digits>
+ <denominator> = [ sign ] <digits>
+ <sign> = '-' | '+'
+ <digits> = <digit> { <digit> | '_' <digit> }
+ <digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
- 0.1r + 0.2r #=> (3/10)
- 0.1 + 0.2 #=> 0.30000000000000004
+Note this, which is parsed as \Float numerator <tt>1.2</tt>
+divided by \Rational denominator <tt>3r</tt>,
+resulting in a \Float:
-=== Complex numbers
+ 1.2/3r # => 0.39999999999999997
-Numbers suffixed by +i+ are Complex (or imaginary) numbers.
+=== \Complex Literals
+
+You can write a Complex number as follows (suffixed +i+):
1i #=> (0+1i)
1i * 1i #=> (-1+0i)
-Also Rational numbers may be imaginary numbers.
+Also \Rational numbers may be imaginary numbers.
12.3ri #=> (0+(123/10)*i)
-+i+ must be placed after +r+, the opposite is not allowed.
++i+ must be placed after +r+; the opposite is not allowed.
- 12.3ir #=> syntax error
+ 12.3ir #=> Syntax error
== Strings
+=== \String Literals
+
The most common way of writing strings is using <tt>"</tt>:
"This is a string."
@@ -156,15 +199,6 @@ In addition to disabling interpolation, single-quoted strings also disable all
escape sequences except for the single-quote (<tt>\'</tt>) and backslash
(<tt>\\\\</tt>).
-You may also create strings using <tt>%</tt>:
-
- %(1 + 1 is #{1 + 1}) #=> "1 + 1 is 2"
-
-There are two different types of <tt>%</tt> strings <tt>%q(...)</tt> behaves
-like a single-quote string (no interpolation or character escaping), while
-<tt>%Q</tt> behaves as a double-quote string. See Percent Strings below for
-more discussion of the syntax of percent strings.
-
Adjacent string literals are automatically concatenated by the interpreter:
"con" "cat" "en" "at" "ion" #=> "concatenation"
@@ -194,7 +228,12 @@ a single codepoint in the script encoding:
?\C-\M-a #=> "\x81", same as above
?あ #=> "あ"
-=== Here Documents (heredocs)
+See also:
+
+* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
+* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+
+=== Here Document Literals
If you are writing a large block of text you may use a "here document" or
"heredoc":
@@ -238,6 +277,12 @@ the content. Note that empty lines and lines consisting solely of literal tabs
and spaces will be ignored for the purposes of determining indentation, but
escaped tabs and spaces are considered non-indentation characters.
+For the purpose of measuring an indentation, a horizontal tab is regarded as a
+sequence of one to eight spaces such that the column position corresponding to
+its end is a multiple of eight. The amount to be removed is counted in terms
+of the number of spaces. If the boundary appears in the middle of a tab, that
+tab is not removed.
+
A heredoc allows interpolation and escaped characters. You may disable
interpolation and escaping by surrounding the opening identifier with single
quotes:
@@ -274,7 +319,7 @@ read:
content for heredoc two
TWO
-== Symbols
+== \Symbol Literals
A Symbol represents a name inside the ruby interpreter. See Symbol for more
details on what symbols are and when ruby creates them internally.
@@ -293,7 +338,12 @@ Like strings, a single-quote may be used to disable interpolation:
When creating a Hash, there is a special syntax for referencing a Symbol as
well.
-== Arrays
+See also:
+
+* {%s: Symbol Literals}[#label-25s-3A+Symbol+Literals]
+
+
+== \Array Literals
An array is created using the objects between <tt>[</tt> and <tt>]</tt>:
@@ -304,9 +354,14 @@ You may place expressions inside the array:
[1, 1 + 1, 1 + 2]
[1, [1 + 1, [1 + 2]]]
+See also:
+
+* {%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals]
+* {%i and %I: Symbol-Array Literals}[#label-25i+and+-25I-3A+Symbol-Array+Literals]
+
See Array for the methods you may use with an array.
-== Hashes
+== \Hash Literals
A hash is created using key-value pairs between <tt>{</tt> and <tt>}</tt>:
@@ -328,9 +383,17 @@ is equal to
{ :"a 1" => 1, :"b 2" => 2 }
+Hash values can be omitted, meaning that value will be fetched from the context
+by the name of the key:
+
+ x = 100
+ y = 200
+ h = { x:, y: }
+ #=> {:x=>100, :y=>200}
+
See Hash for the methods you may use with a hash.
-== Ranges
+== \Range Literals
A range represents an interval of values. The range may include or exclude
its ending value.
@@ -343,25 +406,29 @@ its ending value.
You may create a range of any object. See the Range documentation for details
on the methods you need to implement.
-== Regular Expressions
+== \Regexp Literals
-A regular expression is created using "/":
+A regular expression may be created using leading and trailing
+slash (<tt>'/'</tt>) characters:
- /my regular expression/
+ re = /foo/ # => /foo/
+ re.class # => Regexp
-The regular expression may be followed by flags which adjust the matching
-behavior of the regular expression. The "i" flag makes the regular expression
-case-insensitive:
-
- /my regular expression/i
+The trailing slash may be followed by one or more _flag_ characters
+that modify the behavior.
+See {Regexp options}[rdoc-ref:Regexp@Options] for details.
Interpolation may be used inside regular expressions along with escaped
characters. Note that a regular expression may require additional escaped
characters than a string.
+See also:
+
+* {%r: Regexp Literals}[#label-25r-3A+Regexp+Literals]
+
See Regexp for a description of the syntax of regular expressions.
-== Procs
+== Lambda Proc Literals
A lambda proc can be created with <tt>-></tt>:
@@ -375,27 +442,93 @@ You can require arguments for the proc as follows:
This proc will add one to its argument.
-== Percent Strings
+== Percent Literals
+
+Each of the literals in described in this section
+may use these paired delimiters:
+
+* <tt>[</tt> and <tt>]</tt>.
+* <tt>(</tt> and <tt>)</tt>.
+* <tt>{</tt> and <tt>}</tt>.
+* <tt><</tt> and <tt>></tt>.
+* Any other character, as both beginning and ending delimiters.
+
+These are demonstrated in the next section.
+
+=== <tt>%q</tt>: Non-Interpolable String Literals
+
+You can write a non-interpolable string with <tt>%q</tt>.
+The created string is the same as if you created it with single quotes:
+
+ %[foo bar baz] # => "foo bar baz" # Using [].
+ %(foo bar baz) # => "foo bar baz" # Using ().
+ %{foo bar baz} # => "foo bar baz" # Using {}.
+ %<foo bar baz> # => "foo bar baz" # Using <>.
+ %|foo bar baz| # => "foo bar baz" # Using two |.
+ %:foo bar baz: # => "foo bar baz" # Using two :.
+ %q(1 + 1 is #{1 + 1}) # => "1 + 1 is \#{1 + 1}" # No interpolation.
+
+=== <tt>% and %Q</tt>: Interpolable String Literals
+
+You can write an interpolable string with <tt>%Q</tt>
+or with its alias <tt>%</tt>:
+
+ %[foo bar baz] # => "foo bar baz"
+ %(1 + 1 is #{1 + 1}) # => "1 + 1 is 2" # Interpolation.
+
+=== <tt>%w and %W</tt>: String-Array Literals
+
+You can write an array of strings with <tt>%w</tt> (non-interpolable)
+or <tt>%W</tt> (interpolable):
+
+ %w[foo bar baz] # => ["foo", "bar", "baz"]
+ %w[1 % *] # => ["1", "%", "*"]
+ # Use backslash to embed spaces in the strings.
+ %w[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
+ %w(#{1 + 1}) # => ["\#{1", "+", "1}"]
+ %W(#{1 + 1}) # => ["2"]
+
+=== <tt>%i and %I</tt>: Symbol-Array Literals
+
+You can write an array of symbols with <tt>%i</tt> (non-interpolable)
+or <tt>%I</tt> (interpolable):
+
+ %i[foo bar baz] # => [:foo, :bar, :baz]
+ %i[1 % *] # => [:"1", :%, :*]
+ # Use backslash to embed spaces in the symbols.
+ %i[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
+ %i(#{1 + 1}) # => [:"\#{1", :+, :"1}"]
+ %I(#{1 + 1}) # => [:"2"]
+
+=== <tt>%s</tt>: Symbol Literals
+
+You can write a symbol with <tt>%s</tt>:
+
+ %s[foo] # => :foo
+ %s[foo bar] # => :"foo bar"
+
+=== <tt>%r</tt>: Regexp Literals
+
+You can write a regular expression with <tt>%r</tt>;
+the character used as the leading and trailing delimiter
+may be (almost) any character:
+
+ %r/foo/ # => /foo/
+ %r:name/value pair: # => /name\/value pair/
-Besides <tt>%(...)</tt> which creates a String, the <tt>%</tt> may create
-other types of object. As with strings, an uppercase letter allows
-interpolation and escaped characters while a lowercase letter disables them.
+A few "symmetrical" character pairs may be used as delimiters:
-These are the types of percent strings in ruby:
+ %r[foo] # => /foo/
+ %r{foo} # => /foo/
+ %r(foo) # => /foo/
+ %r<foo> # => /foo/
-<tt>%i</tt> :: Array of Symbols
-<tt>%q</tt> :: String
-<tt>%r</tt> :: Regular Expression
-<tt>%s</tt> :: Symbol
-<tt>%w</tt> :: Array of Strings
-<tt>%x</tt> :: Backtick (capture subshell result)
+The trailing delimiter may be followed by one or more _flag_ characters
+that modify the behavior.
+See {Regexp options}[rdoc-ref:Regexp@Options] for details.
-For the two array forms of percent string, if you wish to include a space in
-one of the array entries you must escape it with a "\\" character:
+=== <tt>%x</tt>: Backtick Literals
- %w[one one-hundred\ one]
- #=> ["one", "one-hundred one"]
+You can write and execute a shell command with <tt>%x</tt>:
-If you are using "(", "[", "{", "<" you must close it with ")", "]", "}", ">"
-respectively. You may use most other non-alphanumeric characters for percent
-string delimiters such as "%", "|", "^", etc.
+ %x(echo 1) # => "1\n"
diff --git a/doc/syntax/methods.rdoc b/doc/syntax/methods.rdoc
index e86cc2c00c..8dafa6bb0c 100644
--- a/doc/syntax/methods.rdoc
+++ b/doc/syntax/methods.rdoc
@@ -441,6 +441,13 @@ Also, note that a bare <code>*</code> can be used to ignore arguments:
def ignore_arguments(*)
end
+You can also use a bare <code>*</code> when calling a method to pass the
+arguments directly to another method:
+
+ def delegate_arguments(*)
+ other_method(*)
+ end
+
=== Keyword Arguments
Keyword arguments are similar to positional arguments with default values:
@@ -481,6 +488,13 @@ Also, note that <code>**</code> can be used to ignore keyword arguments:
def ignore_keywords(**)
end
+You can also use <code>**</code> when calling a method to delegate
+keyword arguments to another method:
+
+ def delegate_keywords(**)
+ other_method(**)
+ end
+
To mark a method as accepting keywords, but not actually accepting
keywords, you can use the <code>**nil</code>:
@@ -515,8 +529,15 @@ Most frequently the block argument is used to pass a block to another method:
@items.each(&block)
end
+You are not required to give a name to the block if you will just be passing
+it to another method:
+
+ def each_item(&)
+ @items.each(&)
+ end
+
If you are only going to call the block and will not otherwise manipulate it
-or send it to another method using <code>yield</code> without an explicit
+or send it to another method, using <code>yield</code> without an explicit
block parameter is preferred. This method is equivalent to the first method
in this section:
diff --git a/doc/syntax/modules_and_classes.rdoc b/doc/syntax/modules_and_classes.rdoc
index 6122f6e08e..024815a5a6 100644
--- a/doc/syntax/modules_and_classes.rdoc
+++ b/doc/syntax/modules_and_classes.rdoc
@@ -155,8 +155,8 @@ Ruby has three types of visibility. The default is +public+. A public method
may be called from any other object.
The second visibility is +protected+. When calling a protected method the
-sender must be a subclass of the receiver or the receiver must be a subclass of
-the sender. Otherwise a NoMethodError will be raised.
+sender must inherit the Class or Module which defines the method. Otherwise a
+NoMethodError will be raised.
Protected visibility is most frequently used to define <code>==</code> and
other comparison methods where the author does not wish to expose an object's
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
index f80703d5c6..b7d614770c 100644
--- a/doc/syntax/pattern_matching.rdoc
+++ b/doc/syntax/pattern_matching.rdoc
@@ -140,7 +140,7 @@ Both array and hash patterns support "rest" specification:
end
#=> "matched"
-In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around both kinds of patterns could be omitted:
+Parentheses around both kinds of patterns could be omitted:
case [1, 2]
in Integer, Integer
@@ -158,6 +158,12 @@ In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around
end
#=> "matched"
+ [1, 2] => a, b
+ [1, 2] in a, b
+
+ {a: 1, b: 2, c: 3} => a:
+ {a: 1, b: 2, c: 3} in a:
+
Find pattern is similar to array pattern but it can be used to check if the given object has any elements that match the pattern:
case ["a", 1, "b", "c", 2]
diff --git a/doc/syntax/precedence.rdoc b/doc/syntax/precedence.rdoc
index f64691ab1f..f0ca92b571 100644
--- a/doc/syntax/precedence.rdoc
+++ b/doc/syntax/precedence.rdoc
@@ -55,7 +55,7 @@ keywords. For example, this is a modifier-unless statement:
Note that <code>(a if b rescue c)</code> is parsed as <code>((a if b) rescue
c)</code> due to reasons not related to precedence. See {modifier
-statements}[control_expressions_rdoc.html#label-Modifier+Statements].
+statements}[control_expressions.rdoc#label-Modifier+Statements].
<code>{ ... }</code> blocks have priority below all listed operations, but
<code>do ... end</code> blocks have lower priority.
diff --git a/doc/time/in.rdoc b/doc/time/in.rdoc
deleted file mode 100644
index f47db76a35..0000000000
--- a/doc/time/in.rdoc
+++ /dev/null
@@ -1,7 +0,0 @@
-- <tt>in: zone</tt>: a timezone _zone_, which may be:
- - A string offset from UTC.
- - A single letter offset from UTC, in the range <tt>'A'..'Z'</tt>,
- <tt>'J'</tt> (the so-called military timezone) excluded.
- - An integer number of seconds.
- - A timezone object;
- see {Timezone Argument}[#class-Time-label-Timezone+Argument] for details.
diff --git a/doc/time/mon-min.rdoc b/doc/time/mon-min.rdoc
deleted file mode 100644
index 5bd430c74a..0000000000
--- a/doc/time/mon-min.rdoc
+++ /dev/null
@@ -1,8 +0,0 @@
-- +month+: a month value, which may be:
- - An integer month in the range <tt>1..12</tt>.
- - A 3-character string that matches regular expression
- <tt>/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/i</tt>.
-- +day+: an integer day in the range <tt>1..31</tt>
- (less than 31 for some months).
-- +hour+: an integer hour in the range <tt>0..23</tt>.
-- +min+: an integer minute in the range <tt>0..59</tt>.
diff --git a/doc/time/msec.rdoc b/doc/time/msec.rdoc
deleted file mode 100644
index ce5d1e6145..0000000000
--- a/doc/time/msec.rdoc
+++ /dev/null
@@ -1,2 +0,0 @@
-- +msec+ is the number of milliseconds (Integer, Float, or Rational)
- in the range <tt>0..1000</tt>.
diff --git a/doc/time/nsec.rdoc b/doc/time/nsec.rdoc
deleted file mode 100644
index a2dfe2d608..0000000000
--- a/doc/time/nsec.rdoc
+++ /dev/null
@@ -1,2 +0,0 @@
-- +nsec+ is the number of nanoseconds (Integer, Float, or Rational)
- in the range <tt>0..1000000000</tt>.
diff --git a/doc/time/sec.rdoc b/doc/time/sec.rdoc
deleted file mode 100644
index 049c712110..0000000000
--- a/doc/time/sec.rdoc
+++ /dev/null
@@ -1,2 +0,0 @@
-- +sec+ is the number of seconds (Integer, Float, or Rational)
- in the range <tt>0..60</tt>.
diff --git a/doc/time/sec_i.rdoc b/doc/time/sec_i.rdoc
deleted file mode 100644
index 99c8eddc65..0000000000
--- a/doc/time/sec_i.rdoc
+++ /dev/null
@@ -1 +0,0 @@
-- +isec_i+ is the integer number of seconds in the range <tt>0..60</tt>.
diff --git a/doc/time/usec.rdoc b/doc/time/usec.rdoc
deleted file mode 100644
index bb5a46419a..0000000000
--- a/doc/time/usec.rdoc
+++ /dev/null
@@ -1,2 +0,0 @@
-- +usec+ is the number of microseconds (Integer, Float, or Rational)
- in the range <tt>0..1000000</tt>.
diff --git a/doc/time/year.rdoc b/doc/time/year.rdoc
deleted file mode 100644
index 2222b830d7..0000000000
--- a/doc/time/year.rdoc
+++ /dev/null
@@ -1 +0,0 @@
-- +year+: an integer year.
diff --git a/doc/time/zone_and_in.rdoc b/doc/time/zone_and_in.rdoc
deleted file mode 100644
index e09e22874b..0000000000
--- a/doc/time/zone_and_in.rdoc
+++ /dev/null
@@ -1,8 +0,0 @@
-- +zone+: a timezone, which may be:
- - A string offset from UTC.
- - A single letter offset from UTC, in the range <tt>'A'..'Z'</tt>,
- <tt>'J'</tt> (the so-called military timezone) excluded.
- - An integer number of seconds.
- - A timezone object;
- see {Timezone Argument}[#class-Time-label-Timezone+Argument] for details.
-- <tt>in: zone</tt>: a timezone _zone_, which may be as above.
diff --git a/doc/timezones.rdoc b/doc/timezones.rdoc
new file mode 100644
index 0000000000..c3aae88fde
--- /dev/null
+++ b/doc/timezones.rdoc
@@ -0,0 +1,108 @@
+== Timezones
+
+=== Timezone Specifiers
+
+Certain \Time methods accept arguments that specify timezones:
+
+- Time.at: keyword argument +in:+.
+- Time.new: positional argument +zone+ or keyword argument +in:+.
+- Time.now: keyword argument +in:+.
+- Time#getlocal: positional argument +zone+.
+- Time#localtime: positional argument +zone+.
+
+The value given with any of these must be one of the following
+(each detailed below):
+
+- {Hours/minutes offset}[rdoc-ref:timezones.rdoc@Hours-2FMinutes+Offsets].
+- {Single-letter offset}[rdoc-ref:timezones.rdoc@Single-Letter+Offsets].
+- {Integer offset}[rdoc-ref:timezones.rdoc@Integer+Offsets].
+- {Timezone object}[rdoc-ref:timezones.rdoc@Timezone+Objects].
+
+==== Hours/Minutes Offsets
+
+The zone value may be a string offset from UTC
+in the form <tt>'+HH:MM'</tt> or <tt>'-HH:MM'</tt>,
+where:
+
+- +HH+ is the 2-digit hour in the range <tt>0..23</tt>.
+- +MM+ is the 2-digit minute in the range <tt>0..59</tt>.
+
+Examples:
+
+ t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
+ Time.at(t, in: '-23:59') # => 1999-12-31 20:16:01 -2359
+ Time.at(t, in: '+23:59') # => 2000-01-02 20:14:01 +2359
+
+==== Single-Letter Offsets
+
+The zone value may be a letter in the range <tt>'A'..'I'</tt>
+or <tt>'K'..'Z'</tt>;
+see {List of military time zones}[https://en.wikipedia.org/wiki/List_of_military_time_zones]:
+
+ t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
+ Time.at(t, in: 'A') # => 2000-01-01 21:15:01 +0100
+ Time.at(t, in: 'I') # => 2000-01-02 05:15:01 +0900
+ Time.at(t, in: 'K') # => 2000-01-02 06:15:01 +1000
+ Time.at(t, in: 'Y') # => 2000-01-01 08:15:01 -1200
+ Time.at(t, in: 'Z') # => 2000-01-01 20:15:01 UTC
+
+==== \Integer Offsets
+
+The zone value may be an integer number of seconds
+in the range <tt>-86399..86399</tt>:
+
+ t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
+ Time.at(t, in: -86399) # => 1999-12-31 20:15:02 -235959
+ Time.at(t, in: 86399) # => 2000-01-02 20:15:00 +235959
+
+==== Timezone Objects
+
+In most cases, the zone value may be an object
+responding to certain timezone methods.
+
+\Exceptions (timezone object not allowed):
+
+- Time.new with positional argument +zone+.
+- Time.now with keyword argument +in:+.
+
+The timezone methods are:
+
+- +local_to_utc+:
+
+ - Called when Time.new is invoked with +tz+
+ as the value of positional argument +zone+ or keyword argument +in:+.
+ - Argument: a <tt>Time::tm</tt> object.
+ - Returns: a \Time-like object in the UTC timezone.
+
+- +utc_to_local+:
+
+ - Called when Time.at or Time.now is invoked with +tz+
+ as the value for keyword argument +in:+,
+ and when Time#getlocal or Time#localtime is called with +tz+
+ as the value for positional argument +zone+.
+ - Argument: a <tt>Time::tm</tt> object.
+ - Returns: a \Time-like object in the local timezone.
+
+A custom timezone class may have these instance methods,
+which will be called if defined:
+
+- +abbr+:
+
+ - Called when Time#strftime is invoked with a format involving <tt>%Z</tt>.
+ - Argument: a <tt>Time::tm</tt> object.
+ - Returns: a string abbreviation for the timezone name.
+
+- +dst?+:
+
+ - Called when Time.at or Time.now is invoked with +tz+
+ as the value for keyword argument +in:+,
+ and when Time#getlocal or Time#localtime is called with +tz+
+ as the value for positional argument +zone+.
+ - Argument: a <tt>Time::tm</tt> object.
+ - Returns: whether the time is daylight saving time.
+
+- +name+:
+
+ - Called when <tt>Marshal.dump(t) is invoked
+ - Argument: none.
+ - Returns: the string name of the timezone.
diff --git a/doc/transcode.rdoc b/doc/transcode.rdoc
new file mode 100644
index 0000000000..4f15dff94a
--- /dev/null
+++ b/doc/transcode.rdoc
@@ -0,0 +1,52 @@
+# :markup: ruby
+
+class String
+ # call-seq:
+ # encode(dst_encoding = Encoding.default_internal, **enc_opts) -> string
+ # encode(dst_encoding, src_encoding, **enc_opts) -> string
+ #
+ # Returns a copy of +self+ transcoded as determined by +dst_encoding+.
+ # By default, raises an exception if +self+
+ # contains an invalid byte or a character not defined in +dst_encoding+;
+ # that behavior may be modified by encoding options; see below.
+ #
+ # With no arguments:
+ #
+ # - Uses the same encoding if <tt>Encoding.default_internal</tt> is +nil+
+ # (the default):
+ #
+ # Encoding.default_internal # => nil
+ # s = "Ruby\x99".force_encoding('Windows-1252')
+ # s.encoding # => #<Encoding:Windows-1252>
+ # s.bytes # => [82, 117, 98, 121, 153]
+ # t = s.encode # => "Ruby\x99"
+ # t.encoding # => #<Encoding:Windows-1252>
+ # t.bytes # => [82, 117, 98, 121, 226, 132, 162]
+ #
+ # - Otherwise, uses the encoding <tt>Encoding.default_internal</tt>:
+ #
+ # Encoding.default_internal = 'UTF-8'
+ # t = s.encode # => "Ruby™"
+ # t.encoding # => #<Encoding:UTF-8>
+ #
+ # With only argument +dst_encoding+ given, uses that encoding:
+ #
+ # s = "Ruby\x99".force_encoding('Windows-1252')
+ # s.encoding # => #<Encoding:Windows-1252>
+ # t = s.encode('UTF-8') # => "Ruby™"
+ # t.encoding # => #<Encoding:UTF-8>
+ #
+ # With arguments +dst_encoding+ and +src_encoding+ given,
+ # interprets +self+ using +src_encoding+, encodes the new string using +dst_encoding+:
+ #
+ # s = "Ruby\x99"
+ # t = s.encode('UTF-8', 'Windows-1252') # => "Ruby™"
+ # t.encoding # => #<Encoding:UTF-8>
+ #
+ # Optional keyword arguments +enc_opts+ specify encoding options;
+ # see {Encoding Options}[rdoc-ref:encodings.rdoc@Encoding+Options].
+ def encode(dst_encoding = Encoding.default_internal, **enc_opts)
+ # Pseudo code
+ Primitive.str_encode(...)
+ end
+end
diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md
new file mode 100644
index 0000000000..67b2ffa5f0
--- /dev/null
+++ b/doc/yjit/yjit.md
@@ -0,0 +1,417 @@
+<p align="center">
+ <a href="https://yjit.org/" target="_blank" rel="noopener noreferrer">
+ <img src="https://user-images.githubusercontent.com/224488/131155756-aa8fb528-a813-4dfd-99ac-8785c3d5eed7.png" width="400">
+ </a>
+</p>
+
+
+YJIT - Yet Another Ruby JIT
+===========================
+
+YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby.
+It lazily compiles code using a Basic Block Versioning (BBV) architecture.
+The target use case is that of servers running Ruby on Rails.
+YJIT is currently supported for macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs.
+This project is open source and falls under the same license as CRuby.
+
+<p align="center"><b>
+ If you're using YJIT in production, please
+ <a href="mailto:maxime.chevalierboisvert@shopify.com">share your success stories with us!</a>
+ </b></p>
+
+If you wish to learn more about the approach taken, here are some conference talks and publications:
+- RubyKaigi 2022 keynote: [Stories from developing YJIT](https://www.youtube.com/watch?v=EMchdR9C8XM)
+- RubyKaigi 2022 talk: [Building a Lightweight IR and Backend for YJIT](https://www.youtube.com/watch?v=BbLGqTxTRp0)
+- RubyKaigi 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=PBVLf3yfMs8)
+- Blog post: [YJIT: Building a New JIT Compiler Inside CRuby](https://pointersgonewild.com/2021/06/02/yjit-building-a-new-jit-compiler-inside-cruby/)
+- VMIL 2021 paper: [YJIT: A Basic Block Versioning JIT Compiler for CRuby](https://dl.acm.org/doi/10.1145/3486606.3486781)
+- MoreVMs 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=vucLAqv7qpc)
+- ECOOP 2016 talk: [Interprocedural Type Specialization of JavaScript Programs Without Type Analysis](https://www.youtube.com/watch?v=sRNBY7Ss97A)
+- ECOOP 2016 paper: [Interprocedural Type Specialization of JavaScript Programs Without Type Analysis](https://drops.dagstuhl.de/opus/volltexte/2016/6101/pdf/LIPIcs-ECOOP-2016-7.pdf)
+- ECOOP 2015 talk: [Simple and Effective Type Check Removal through Lazy Basic Block Versioning](https://www.youtube.com/watch?v=S-aHBuoiYE0)
+- ECOOP 2015 paper: [Simple and Effective Type Check Removal through Lazy Basic Block Versioning](https://arxiv.org/pdf/1411.0352.pdf)
+
+To cite YJIT in your publications, please cite the VMIL 2021 paper:
+
+```
+@inproceedings{yjit_vmil2021,
+author = {Chevalier-Boisvert, Maxime and Gibbs, Noah and Boussier, Jean and Wu, Si Xing (Alan) and Patterson, Aaron and Newton, Kevin and Hawthorn, John},
+title = {YJIT: A Basic Block Versioning JIT Compiler for CRuby},
+year = {2021},
+isbn = {9781450391092},
+publisher = {Association for Computing Machinery},
+address = {New York, NY, USA},
+url = {https://doi.org/10.1145/3486606.3486781},
+doi = {10.1145/3486606.3486781},
+booktitle = {Proceedings of the 13th ACM SIGPLAN International Workshop on Virtual Machines and Intermediate Languages},
+pages = {25–32},
+numpages = {8},
+keywords = {ruby, dynamically typed, compiler, optimization, just-in-time, bytecode},
+location = {Chicago, IL, USA},
+series = {VMIL 2021}
+}
+```
+
+## Current Limitations
+
+YJIT may not be suitable for certain applications. It currently only supports macOS and Linux on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information.
+You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options). There is a slight performance tradeoff because allocating less executable memory could result in the generated machine code being collected more often.
+
+## Installation
+
+### Requirements
+
+You will need to install:
+- A C compiler such as GCC or Clang
+- GNU Make and Autoconf
+- The Rust compiler `rustc` and Cargo (if you want to build in dev/debug mode)
+ - The Rust version must be [>= 1.58.0](../../yjit/Cargo.toml).
+
+To install the Rust build toolchain, we suggest following the [recommended installation method][rust-install]. Rust also provides first class [support][editor-tools] for many source code editors.
+
+[rust-install]: https://www.rust-lang.org/tools/install
+[editor-tools]: https://www.rust-lang.org/tools
+
+### Building YJIT
+
+Start by cloning the `ruby/ruby` repository:
+
+```sh
+git clone https://github.com/ruby/ruby yjit
+cd yjit
+```
+
+The YJIT `ruby` binary can be built with either GCC or Clang. It can be built either in dev (debug) mode or in release mode. For maximum performance, compile YJIT in release mode with GCC. More detailed build instructions are provided in the [Ruby README](https://github.com/ruby/ruby#how-to-build).
+
+```sh
+# Configure in release mode for maximum performance, build and install
+./autogen.sh
+./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
+```
+
+or
+
+```sh
+# Configure in lower-performance dev (debug) mode for development, build and install
+./autogen.sh
+./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
+```
+
+Dev mode includes extended YJIT statistics, but can be slow. For only statistics you can configure in stats mode:
+
+```sh
+# Configure in extended-stats mode without slow runtime checks, build and install
+./autogen.sh
+./configure --enable-yjit=stats --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
+```
+
+On macOS, you may need to specify where to find some libraries:
+
+```sh
+# Install dependencies
+brew install openssl readline libyaml
+
+# Configure in dev (debug) mode for development, build and install
+./autogen.sh
+./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)"
+make -j && make install
+```
+
+Typically configure will choose the default C compiler. To specify the C compiler, use
+
+```sh
+# Choosing a specific c compiler
+export CC=/path/to/my/chosen/c/compiler
+```
+
+before running `./configure`.
+
+You can test that YJIT works correctly by running:
+
+```sh
+# Quick tests found in /bootstraptest
+make btest
+
+# Complete set of tests
+make -j test-all
+```
+
+## Usage
+
+### Examples
+
+Once YJIT is built, you can either use `./miniruby` from within your build directory, or switch to the YJIT version of `ruby`
+by using the `chruby` tool:
+
+```sh
+chruby ruby-yjit
+ruby myscript.rb
+```
+
+You can dump statistics about compilation and execution by running YJIT with the `--yjit-stats` command-line option:
+
+```sh
+./miniruby --yjit-stats myscript.rb
+```
+
+The machine code generated for a given method can be printed by adding `puts RubyVM::YJIT.disasm(method(:method_name))` to a Ruby script. Note that no code will be generated if the method is not compiled.
+
+### Command-Line Options
+
+YJIT supports all command-line options supported by upstream CRuby, but also adds a few YJIT-specific options:
+
+- `--yjit`: enable YJIT (disabled by default)
+- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function (default 30)
+- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 64 MiB)
+- `--yjit-stats`: print statistics after the execution of a program (incurs a run-time cost)
+- `--yjit-trace-exits`: produce a Marshal dump of backtraces from specific exits. Automatically enables `--yjit-stats`
+
+Note that there is also an environment variable `RUBY_YJIT_ENABLE` which can be used to enable YJIT.
+This can be useful for some deployment scripts where specifying an extra command-line option to Ruby is not practical.
+
+### Benchmarking
+
+We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible. Please kindly note that we are at an early stage in this project.
+
+## Performance Tips for Production Deployments
+
+While YJIT options default to what we think would work well for most workloads,
+they might not necessarily be the best configuration for your application.
+
+This section covers tips on improving YJIT performance in case YJIT does not
+speed up your application in production.
+
+### Increasing --yjit-exec-mem-size
+
+When JIT code size (`RubyVM::YJIT.runtime_stats[:code_region_size]`) reaches this value,
+YJIT triggers "code GC" that frees all JIT code and starts recompiling everything.
+Compiling code takes some time, so scheduling code GC too frequently slows down your application.
+Increasing `--yjit-exec-mem-size` may speed up your application if `RubyVM::YJIT.runtime_stats[:code_gc_count]` is not 0 or 1.
+
+### Running workers as long as possible
+
+It's helpful to call the same code as many times as possible before a process restarts.
+If a process is killed too frequently, the time taken for compiling methods may outweigh
+the speedup obtained by compiling them.
+
+You should monitor the number of requests each process has served.
+If you're periodically killing worker processes, e.g. with `unicorn-worker-killer` or `puma_worker_killer`,
+you may want to reduce the killing frequency or increase the limit.
+
+## Saving YJIT Memory Usage
+
+YJIT allocates memory for JIT code and metadata. Enabling YJIT generally results in more memory usage.
+
+This section goes over tips on minimizing YJIT memory usage in case it uses more than your capacity.
+
+### Increasing --yjit-call-threshold
+
+As of Ruby 3.2, `--yjit-call-threshold` defaults to 30. With this default, some applications end up
+compiling methods that are used only during the application boot. Increasing this option may help
+you reduce the size of JIT code and metadata. It's worth trying different values like `--yjit-call-threshold=100`.
+
+Note that increasing the value too much may result in compiling code too late.
+You should monitor how many requests each worker processes before it's restarted. For example,
+if each process only handles 1000 requests, `--yjit-call-threshold=1000` might be too large for your application.
+
+### Decreasing --yjit-exec-mem-size
+
+`--yjit-exec-mem-size` specifies the JIT code size, but YJIT also uses memory for its metadata,
+which often consumes more memory than JIT code. Generally, YJIT adds memory overhead by roughly
+3-4x of `--yjit-exec-mem-size` in production as of Ruby 3.2. You should multiply that by the number
+of worker processes to estimate the worst case memory overhead.
+
+Running code GC adds overhead, but it could be still faster than recovering from a whole process killed by OOM.
+
+## Code Optimization Tips
+
+This section contains tips on writing Ruby code that will run as fast as possible on YJIT. Some of this advice is based on current limitations of YJIT, while other advice is broadly applicable. It probably won't be practical to apply these tips everywhere in your codebase. You should ideally start by profiling your application using a tool such as [stackprof](https://github.com/tmm1/stackprof) so that you can determine which methods make up most of the execution time. You can then refactor the specific methods that make up the largest fractions of the execution time. We do not recommend modifying your entire codebase based on the current limitations of YJIT.
+
+- Avoid using `OpenStruct`
+- Avoid redefining basic integer operations (i.e. +, -, <, >, etc.)
+- Avoid redefining the meaning of `nil`, equality, etc.
+- Avoid allocating objects in the hot parts of your code
+- Minimize layers of indirection
+ - Avoid classes that wrap objects if you can
+ - Avoid methods that just call another method, trivial one liner methods
+- Try to write code so that the same variables always have the same type
+- Use `while` loops if you can, instead of C methods like `Array#each`
+ - This is not idiomatic Ruby, but could help in hot methods
+- CRuby method calls are costly. Avoid things such as methods that only return a value from a hash or return a constant.
+
+You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code.
+
+### Other Statistics
+
+If you run `ruby` with `--yjit --yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`.
+
+```rb
+$ RUBYOPT="--yjit --yjit-stats" irb
+irb(main):001:0> RubyVM::YJIT.runtime_stats
+=>
+{:inline_code_size=>340745,
+ :outlined_code_size=>297664,
+ :all_stats=>true,
+ :exec_instruction=>1547816,
+ :send_callsite_not_simple=>7267,
+ :send_kw_splat=>7,
+ :send_ivar_set_method=>72,
+...
+```
+
+Some of the counters include:
+
+* :exec_instruction - how many Ruby bytecode instructions have been executed
+* :binding_allocations - number of bindings allocated
+* :binding_set - number of variables set via a binding
+* :code_gc_count - number of garbage collections of compiled code since process start
+* :vm_insns_count - number of instructions executed by the Ruby interpreter
+* :compiled_iseq_count - number of bytecode sequences compiled
+* :inline_code_size - size in bytes of compiled YJIT blocks
+* :outline_code_size - size in bytes of YJIT error-handling compiled code
+* :side_exit_count - number of side exits taken at runtime
+* :total_exit_count - number of exits, including side exits, taken at runtime
+* :avg_len_in_yjit - avg. number of instructions in compiled blocks before exiting to interpreter
+
+Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.) See yjit_hacking.md for more details.
+
+Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what one does, it's usually best to search the source code for it &mdash; but it may change in a later Ruby version.
+
+The printed text after a --yjit-stats run includes other information that may be named differently than the information in runtime_stats.
+
+## Contributing
+
+We welcome open source contributors. You should feel free to open new issues to report bugs or just to ask questions.
+Suggestions on how to make this readme file more helpful for new contributors are most welcome.
+
+Bug fixes and bug reports are very valuable to us. If you find a bug in YJIT, it's very possible be that nobody has reported it before,
+or that we don't have a good reproduction for it, so please open an issue and provide as much information as you can about your configuration and a description of how you encountered the problem. List the commands you used to run YJIT so that we can easily reproduce the issue on our end and investigate it. If you are able to produce a small program reproducing the error to help us track it down, that is very much appreciated as well.
+
+If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on this repository so that
+we can have an active discussion. A common problem is that sometimes people submit large pull requests to open source projects
+without prior communication, and we have to reject them because the work they implemented does not fit within the design of the
+project. We want to save you time and frustration, so please reach out and we can have a productive discussion as to how
+you can contribute things we will want to merge into YJIT.
+
+### Source Code Organization
+
+The YJIT source code is divided between:
+- `yjit.c`: code YJIT uses to interface with the rest of CRuby
+- `yjit.h`: C definitions YJIT exposes to the rest of the CRuby
+- `yjit.rb`: `YJIT` Ruby module that is exposed to Ruby
+- `yjit/src/asm/*`: in-memory assembler we use to generate machine code
+- `yjit/src/codegen.rs`: logic for translating Ruby bytecode to machine code
+- `yjit/src/core.rb`: basic block versioning logic, core structure of YJIT
+- `yjit/src/stats.rs`: gathering of run-time statistics
+- `yjit/src/options.rs`: handling of command-line options
+- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen
+- `yjit/src/cruby.rs`: C bindings manually exposed to the Rust codebase
+
+The core of CRuby's interpreter logic is found in:
+- `insns.def`: defines Ruby's bytecode instructions (gets compiled into `vm.inc`)
+- `vm_insnshelper.c`: logic used by Ruby's bytecode instructions
+- `vm_exec.c`: Ruby interpreter loop
+
+### Generating C bindings with bindgen
+
+In order to expose C functions to the Rust codebase, you will need to generate C bindings:
+
+```sh
+CC=clang ./configure --enable-yjit=dev
+make -j yjit-bindgen
+```
+
+This uses the bindgen tools to generate/update `yjit/src/cruby_bindings.inc.rs` based on the
+bindings listed in `yjit/bindgen/src/main.rs`. Avoid manually editing this file
+as it could be automatically regenerated at a later time. If you need to manually add C bindings,
+add them to `yjit/cruby.rs` instead.
+
+### Coding & Debugging Protips
+
+There are 3 test suites:
+- `make btest` (see `/bootstraptest`)
+- `make test-all`
+- `make test-spec`
+- `make check` runs all of the above
+
+The tests can be run in parallel like this:
+
+```sh
+make -j test-all RUN_OPTS="--yjit-call-threshold=1"
+```
+
+Or single-threaded like this, to more easily identify which specific test is failing:
+
+```sh
+make test-all TESTOPTS=--verbose RUN_OPTS="--yjit-call-threshold=1"
+```
+
+To debug a single test in `test-all`:
+
+```sh
+make test-all TESTS='test/-ext-/marshal/test_usrmarshal.rb' RUNRUBYOPT=--debugger=lldb RUN_OPTS="--yjit-call-threshold=1"
+```
+
+You can also run one specific test in `btest`:
+
+```sh
+make btest BTESTS=bootstraptest/test_ractor.rb RUN_OPTS="--yjit-call-threshold=1"
+```
+
+There are shortcuts to run/debug your own test/repro in `test.rb`:
+
+```sh
+make run # runs ./miniruby test.rb
+make lldb # launches ./miniruby test.rb in lldb
+```
+
+You can use the Intel syntax for disassembly in LLDB, keeping it consistent with YJIT's disassembly:
+
+```sh
+echo "settings set target.x86-disassembly-flavor intel" >> ~/.lldbinit
+```
+
+## Running x86 YJIT on Apple's Rosetta
+
+For development purposes, it is possible to run x86 YJIT on an Apple M1 via Rosetta. You can find basic
+instructions below, but there are a few caveats listed further down.
+
+First, install Rosetta:
+
+```sh
+$ softwareupdate --install-rosetta
+```
+
+Now any command can be run with Rosetta via the `arch` command line tool.
+
+Then you can start your shell in an x86 environment:
+
+```sh
+$ arch -x86_64 zsh
+```
+
+You can double check your current architecture via the `arch` command:
+
+```sh
+$ arch -x86_64 zsh
+$ arch
+i386
+```
+
+You may need to set the default target for `rustc` to x86-64, e.g.
+
+```sh
+$ rustup default stable-x86_64-apple-darwin
+```
+
+While in your i386 shell, install Cargo and Homebrew, then hack away!
+
+### Rosetta Caveats
+
+1. You must install a version of Homebrew for each architecture
+2. Cargo will install in $HOME/.cargo by default, and I don't know a good way to change architectures after install
+
+If you use Fish shell you can [read this link](https://tenderlovemaking.com/2022/01/07/homebrew-rosetta-and-ruby.html) for information on making the dev environment easier.
diff --git a/doc/yjit/yjit_hacking.md b/doc/yjit/yjit_hacking.md
new file mode 100644
index 0000000000..4c4d742b73
--- /dev/null
+++ b/doc/yjit/yjit_hacking.md
@@ -0,0 +1,75 @@
+# YJIT Hacking
+
+## Code Generation and Assembly Language
+
+YJIT’s basic purpose is to take ISEQs and generate machine code.
+
+Documentation on each Ruby bytecode can be found in insns.def.
+
+YJIT uses those bytecodes as the “Basic Blocks” in Lazy Basic Block Versioning (LBBV.) For more deep details of LBBV, see yjit.md in this directory.
+
+Current YJIT has a simple assembler as a backend. Each method that generates code does it by emitting machine code:
+
+```
+# Excerpt of yjit_gen_exit() from yjit_codegen.c, Sept 2021
+// Generate an exit to return to the interpreter
+static uint32_t
+yjit_gen_exit(VALUE *exit_pc, ctx_t *ctx, codeblock_t *cb)
+{
+ const uint32_t code_pos = cb->write_pos;
+
+ ADD_COMMENT(cb, "exit to interpreter");
+
+ // Generate the code to exit to the interpreters
+ // Write the adjusted SP back into the CFP
+ if (ctx->sp_offset != 0) {
+ x86opnd_t stack_pointer = ctx_sp_opnd(ctx, 0);
+ lea(cb, REG_SP, stack_pointer);
+ mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG_SP);
+ }
+
+ // Update CFP->PC
+ mov(cb, RAX, const_ptr_opnd(exit_pc));
+ mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX);
+```
+
+Later there will be a more complex backend.
+
+## Code Generation vs Code Execution
+
+When you see lea() call above (“load effective address,”) it’s not running the LEA x86 instruction. It’s generating an LEA instruction to the codeblock pointer in the first argument. It will execute that instruction later, when the codeblock gets executed.
+
+This is subtle because YJIT will often wait to compile the method until you’re about to run it -- that’s when it knows the most about what types of arguments the method will receive. So it’s a compile-time instruction, but often it will defer compile-time until just barely before runtime.
+
+The ctx structure tracks what is known at compile time about the arguments being passed into the Ruby bytecode. Often YJIT will “peek” at an expected type before it generates machine code.
+
+## Inlined and Outlined Code
+
+When YJIT is generating code, it needs a code pointer. In many cases it needs two, usually called “cb” (codeblock) and “ocb” (out-of-line codeblock.)
+
+cb is for “inlined” normal code and ocb is for “outline” code such as exits. Inlined code is normal generated code for Ruby operations, while outlined code is for unusual and error conditions, such as encountering an unexpected parameter type and exiting to the interpreter.
+
+The purpose of the outlined code block is to keep things we believe are going to be infrequent somewhere else. That way we can keep the code in the inline block more linear and compact. Linear code, with as few branches as possible, is more easily predicted by the CPU. An exception or unsupported operation will cause YJIT to generate outlined code to handle it.
+
+If you search for ocb in yjit_codegen.c, you can see some places where out-of-line code is generated.
+
+YJIT statistics are only gathered when RUBY_DEBUG or YJIT_STATS is true. In some cases the code to increment YJIT statistics will be generated out-of-line, especially if those statistics are gathered when a side exit happens.
+
+## Statistics and Comments
+
+When RUBY_DEBUG is defined to a true value, YJIT will emit comments into the generated machine code. This can make disassemblies a lot more readable. When RUBY_DEBUG or YJIT_STATS is defined and stats are active (--yjit-stats or export YJIT_STATS=1), code will be generated to collect statistics during the run, and a report will be printed when the process exits.
+
+## Entering and Exiting the Interpreter
+
+YJIT won’t generate machine code for an ISEQ until it’s been run a certain number of times (10 by default.) Then, the next time the interpreter would call that ISEQ, it will call the generated machine code version instead. If YJIT hits an unexpected or unsupported operation, it will return to the normal interpreter.
+
+If YJIT returns to the interpreter, the behaviour will be correct but slower. YJIT only optimises part of some operations - for instance, YJIT will not optimise a BMETHOD call yet.
+
+When the interpreter calls to a YJIT-optimised method again, control will return to YJIT’s generated machine code. The more time that’s spent in YJIT-generated code (“ratio in YJIT,”) the more CPU time YJIT can save with its optimisations.
+
+## Side Exits
+
+When YJIT has compiled an ISEQ and is running it later, sometimes it will hit an unexpected condition. It might see a parameter of a different type than before, or square-brackets might be used on a hash when they were first used on an array. In those cases, the generated code will contain a call to return to the interpreter at runtime, called a “side exit.”
+
+Side exits are generated as out-of-line code.
+
diff --git a/enc/Makefile.in b/enc/Makefile.in
index 5e5d39cd76..9d0c367134 100644
--- a/enc/Makefile.in
+++ b/enc/Makefile.in
@@ -22,6 +22,7 @@ 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
@@ -35,6 +36,7 @@ RUBY_SO_NAME = @RUBY_SO_NAME@
LIBRUBY = @LIBRUBY@
LIBRUBYARG_SHARED = @LIBRUBYARG_SHARED@
LIBRUBYARG_STATIC = $(LIBRUBYARG_SHARED)
+BUILTRUBY = $(topdir)/miniruby$(EXEEXT)
empty =
AR = @AR@
@@ -49,7 +51,7 @@ optflags = @optflags@
debugflags = @debugflags@
warnflags = @warnflags@
CCDLFLAGS = @CCDLFLAGS@
-INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir)
+INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir) @incflags@
DEFS = @DEFS@
CPPFLAGS = @CPPFLAGS@ -DONIG_ENC_REGISTER=rb_enc_register
LDFLAGS = @LDFLAGS@
diff --git a/enc/ascii.c b/enc/ascii.c
index a2fef2f879..ae7db97f25 100644
--- a/enc/ascii.c
+++ b/enc/ascii.c
@@ -33,8 +33,8 @@
# include "encindex.h"
#endif
-#ifndef ENCINDEX_ASCII
-# define ENCINDEX_ASCII 0
+#ifndef ENCINDEX_ASCII_8BIT
+# define ENCINDEX_ASCII_8BIT 0
#endif
OnigEncodingDefine(ascii, ASCII) = {
@@ -55,7 +55,7 @@ OnigEncodingDefine(ascii, ASCII) = {
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
onigenc_single_byte_ascii_only_case_map,
- ENCINDEX_ASCII,
+ ENCINDEX_ASCII_8BIT,
ONIGENC_FLAG_NONE,
};
ENC_ALIAS("BINARY", "ASCII-8BIT")
diff --git a/enc/cesu_8.c b/enc/cesu_8.c
index decbb928f4..75f62df280 100644
--- a/enc/cesu_8.c
+++ b/enc/cesu_8.c
@@ -42,6 +42,8 @@
#define VALID_CODE_LIMIT 0x0010ffff
#define utf8_islead(c) ((UChar )((c) & 0xc0) != 0x80)
+#define utf16_is_high_surrogate(v) ((v >> 10) == 0x36)
+#define utf16_is_low_surrogate(v) ((v >> 10) == 0x37)
static const int EncLen_CESU8[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -283,6 +285,12 @@ is_mbc_newline(const UChar* p, const UChar* end, OnigEncoding enc)
return 0;
}
+static int
+utf8_decode_3byte_sequence(const UChar* p)
+{
+ return ((p[0] & 0xF) << 12) | ((p[1] & 0x3f) << 6) | (p[2] & 0x3f);
+}
+
static OnigCodePoint
mbc_to_code(const UChar* p, const UChar* end, OnigEncoding enc)
{
@@ -295,11 +303,11 @@ mbc_to_code(const UChar* p, const UChar* end, OnigEncoding enc)
case 2:
return ((p[0] & 0x1F) << 6) | (p[1] & 0x3f);
case 3:
- return ((p[0] & 0xF) << 12) | ((p[1] & 0x3f) << 6) | (p[2] & 0x3f);
+ return utf8_decode_3byte_sequence(p);
case 6:
{
- int high = ((p[0] & 0xF) << 12) | ((p[1] & 0x3f) << 6) | (p[2] & 0x3f);
- int low = ((p[3] & 0xF) << 12) | ((p[4] & 0x3f) << 6) | (p[5] & 0x3f);
+ int high = utf8_decode_3byte_sequence(p);
+ int low = utf8_decode_3byte_sequence(p + 3);
return ((high & 0x03ff) << 10) + (low & 0x03ff) + 0x10000;
}
}
@@ -410,7 +418,6 @@ get_ctype_code_range(OnigCtype ctype, OnigCodePoint *sb_out,
return onigenc_unicode_ctype_code_range(ctype, ranges);
}
-
static UChar*
left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc ARG_UNUSED)
{
@@ -420,6 +427,14 @@ left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, Onig
p = s;
while (!utf8_islead(*p) && p > start) p--;
+
+ if (p > start && s - p == 2 && utf16_is_low_surrogate(utf8_decode_3byte_sequence(p))) {
+ const UChar *p_surrogate_pair = p - 1;
+ while (!utf8_islead(*p_surrogate_pair) && p_surrogate_pair > start) p_surrogate_pair--;
+ if (p - p_surrogate_pair == 3 && utf16_is_high_surrogate(utf8_decode_3byte_sequence(p_surrogate_pair))) {
+ return (UChar* )p_surrogate_pair;
+ }
+ }
return (UChar* )p;
}
diff --git a/enc/depend b/enc/depend
index 7034d9c762..973ad93010 100644
--- a/enc/depend
+++ b/enc/depend
@@ -178,9 +178,25 @@ clean-srcs:
<%# vim: set ft=eruby noexpandtab ts=8 sw=2 : -%>
# AUTOGENERATED DEPENDENCIES START
+enc/ascii.$(OBJEXT): $(hdrdir)/ruby.h
enc/ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/ascii.$(OBJEXT): $(top_srcdir)/encindex.h
enc/ascii.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/ascii.$(OBJEXT): assert.h
+enc/ascii.$(OBJEXT): backward/2/assume.h
+enc/ascii.$(OBJEXT): backward/2/attributes.h
+enc/ascii.$(OBJEXT): backward/2/bool.h
+enc/ascii.$(OBJEXT): backward/2/inttypes.h
+enc/ascii.$(OBJEXT): backward/2/limits.h
+enc/ascii.$(OBJEXT): backward/2/long_long.h
+enc/ascii.$(OBJEXT): backward/2/stdalign.h
+enc/ascii.$(OBJEXT): backward/2/stdarg.h
+enc/ascii.$(OBJEXT): config.h
+enc/ascii.$(OBJEXT): defines.h
+enc/ascii.$(OBJEXT): enc/ascii.c
+enc/ascii.$(OBJEXT): encoding.h
+enc/ascii.$(OBJEXT): intern.h
+enc/ascii.$(OBJEXT): internal/abi.h
enc/ascii.$(OBJEXT): internal/anyargs.h
enc/ascii.$(OBJEXT): internal/arithmetic.h
enc/ascii.$(OBJEXT): internal/arithmetic/char.h
@@ -250,6 +266,15 @@ enc/ascii.$(OBJEXT): internal/core/rtypeddata.h
enc/ascii.$(OBJEXT): internal/ctype.h
enc/ascii.$(OBJEXT): internal/dllexport.h
enc/ascii.$(OBJEXT): internal/dosish.h
+enc/ascii.$(OBJEXT): internal/encoding/coderange.h
+enc/ascii.$(OBJEXT): internal/encoding/ctype.h
+enc/ascii.$(OBJEXT): internal/encoding/encoding.h
+enc/ascii.$(OBJEXT): internal/encoding/pathname.h
+enc/ascii.$(OBJEXT): internal/encoding/re.h
+enc/ascii.$(OBJEXT): internal/encoding/sprintf.h
+enc/ascii.$(OBJEXT): internal/encoding/string.h
+enc/ascii.$(OBJEXT): internal/encoding/symbol.h
+enc/ascii.$(OBJEXT): internal/encoding/transcode.h
enc/ascii.$(OBJEXT): internal/error.h
enc/ascii.$(OBJEXT): internal/eval.h
enc/ascii.$(OBJEXT): internal/event.h
@@ -320,36 +345,61 @@ 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): $(hdrdir)/ruby.h
+enc/big5.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/big5.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/big5.$(OBJEXT): assert.h
+enc/big5.$(OBJEXT): backward.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/inttypes.h
+enc/big5.$(OBJEXT): backward/2/limits.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): intern.h
+enc/big5.$(OBJEXT): internal/abi.h
+enc/big5.$(OBJEXT): internal/anyargs.h
+enc/big5.$(OBJEXT): internal/arithmetic.h
+enc/big5.$(OBJEXT): internal/arithmetic/char.h
+enc/big5.$(OBJEXT): internal/arithmetic/double.h
+enc/big5.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/big5.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/int.h
+enc/big5.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/long.h
+enc/big5.$(OBJEXT): internal/arithmetic/long_long.h
+enc/big5.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/off_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/short.h
+enc/big5.$(OBJEXT): internal/arithmetic/size_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/big5.$(OBJEXT): internal/arithmetic/uid_t.h
enc/big5.$(OBJEXT): internal/assume.h
enc/big5.$(OBJEXT): internal/attr/alloc_size.h
+enc/big5.$(OBJEXT): internal/attr/artificial.h
enc/big5.$(OBJEXT): internal/attr/cold.h
enc/big5.$(OBJEXT): internal/attr/const.h
+enc/big5.$(OBJEXT): internal/attr/constexpr.h
enc/big5.$(OBJEXT): internal/attr/deprecated.h
+enc/big5.$(OBJEXT): internal/attr/diagnose_if.h
+enc/big5.$(OBJEXT): internal/attr/enum_extensibility.h
enc/big5.$(OBJEXT): internal/attr/error.h
+enc/big5.$(OBJEXT): internal/attr/flag_enum.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/noalias.h
enc/big5.$(OBJEXT): internal/attr/nodiscard.h
enc/big5.$(OBJEXT): internal/attr/noexcept.h
enc/big5.$(OBJEXT): internal/attr/noinline.h
@@ -359,6 +409,7 @@ 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/attr/weakref.h
enc/big5.$(OBJEXT): internal/cast.h
enc/big5.$(OBJEXT): internal/compiler_is.h
enc/big5.$(OBJEXT): internal/compiler_is/apple.h
@@ -369,8 +420,30 @@ 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/constant_p.h
+enc/big5.$(OBJEXT): internal/core.h
+enc/big5.$(OBJEXT): internal/core/rarray.h
+enc/big5.$(OBJEXT): internal/core/rbasic.h
+enc/big5.$(OBJEXT): internal/core/rbignum.h
+enc/big5.$(OBJEXT): internal/core/rclass.h
+enc/big5.$(OBJEXT): internal/core/rdata.h
+enc/big5.$(OBJEXT): internal/core/rfile.h
+enc/big5.$(OBJEXT): internal/core/rhash.h
+enc/big5.$(OBJEXT): internal/core/robject.h
+enc/big5.$(OBJEXT): internal/core/rregexp.h
+enc/big5.$(OBJEXT): internal/core/rstring.h
+enc/big5.$(OBJEXT): internal/core/rstruct.h
+enc/big5.$(OBJEXT): internal/core/rtypeddata.h
+enc/big5.$(OBJEXT): internal/ctype.h
enc/big5.$(OBJEXT): internal/dllexport.h
enc/big5.$(OBJEXT): internal/dosish.h
+enc/big5.$(OBJEXT): internal/error.h
+enc/big5.$(OBJEXT): internal/eval.h
+enc/big5.$(OBJEXT): internal/event.h
+enc/big5.$(OBJEXT): internal/fl_type.h
+enc/big5.$(OBJEXT): internal/gc.h
+enc/big5.$(OBJEXT): internal/glob.h
+enc/big5.$(OBJEXT): internal/globals.h
enc/big5.$(OBJEXT): internal/has/attribute.h
enc/big5.$(OBJEXT): internal/has/builtin.h
enc/big5.$(OBJEXT): internal/has/c_attribute.h
@@ -379,26 +452,85 @@ 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/intern/array.h
+enc/big5.$(OBJEXT): internal/intern/bignum.h
+enc/big5.$(OBJEXT): internal/intern/class.h
+enc/big5.$(OBJEXT): internal/intern/compar.h
+enc/big5.$(OBJEXT): internal/intern/complex.h
+enc/big5.$(OBJEXT): internal/intern/cont.h
+enc/big5.$(OBJEXT): internal/intern/dir.h
+enc/big5.$(OBJEXT): internal/intern/enum.h
+enc/big5.$(OBJEXT): internal/intern/enumerator.h
+enc/big5.$(OBJEXT): internal/intern/error.h
+enc/big5.$(OBJEXT): internal/intern/eval.h
+enc/big5.$(OBJEXT): internal/intern/file.h
+enc/big5.$(OBJEXT): internal/intern/gc.h
+enc/big5.$(OBJEXT): internal/intern/hash.h
+enc/big5.$(OBJEXT): internal/intern/io.h
+enc/big5.$(OBJEXT): internal/intern/load.h
+enc/big5.$(OBJEXT): internal/intern/marshal.h
+enc/big5.$(OBJEXT): internal/intern/numeric.h
+enc/big5.$(OBJEXT): internal/intern/object.h
+enc/big5.$(OBJEXT): internal/intern/parse.h
+enc/big5.$(OBJEXT): internal/intern/proc.h
+enc/big5.$(OBJEXT): internal/intern/process.h
+enc/big5.$(OBJEXT): internal/intern/random.h
+enc/big5.$(OBJEXT): internal/intern/range.h
+enc/big5.$(OBJEXT): internal/intern/rational.h
+enc/big5.$(OBJEXT): internal/intern/re.h
+enc/big5.$(OBJEXT): internal/intern/ruby.h
+enc/big5.$(OBJEXT): internal/intern/select.h
+enc/big5.$(OBJEXT): internal/intern/select/largesize.h
+enc/big5.$(OBJEXT): internal/intern/signal.h
+enc/big5.$(OBJEXT): internal/intern/sprintf.h
+enc/big5.$(OBJEXT): internal/intern/string.h
+enc/big5.$(OBJEXT): internal/intern/struct.h
+enc/big5.$(OBJEXT): internal/intern/thread.h
+enc/big5.$(OBJEXT): internal/intern/time.h
+enc/big5.$(OBJEXT): internal/intern/variable.h
+enc/big5.$(OBJEXT): internal/intern/vm.h
+enc/big5.$(OBJEXT): internal/interpreter.h
+enc/big5.$(OBJEXT): internal/iterator.h
+enc/big5.$(OBJEXT): internal/memory.h
+enc/big5.$(OBJEXT): internal/method.h
+enc/big5.$(OBJEXT): internal/module.h
+enc/big5.$(OBJEXT): internal/newobj.h
+enc/big5.$(OBJEXT): internal/rgengc.h
+enc/big5.$(OBJEXT): internal/scan_args.h
+enc/big5.$(OBJEXT): internal/special_consts.h
+enc/big5.$(OBJEXT): internal/static_assert.h
enc/big5.$(OBJEXT): internal/stdalign.h
enc/big5.$(OBJEXT): internal/stdbool.h
+enc/big5.$(OBJEXT): internal/symbol.h
+enc/big5.$(OBJEXT): internal/value.h
+enc/big5.$(OBJEXT): internal/value_type.h
+enc/big5.$(OBJEXT): internal/variable.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/big5.$(OBJEXT): st.h
+enc/big5.$(OBJEXT): subst.h
+enc/cesu_8.$(OBJEXT): $(hdrdir)/ruby.h
enc/cesu_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/cesu_8.$(OBJEXT): $(top_srcdir)/encindex.h
enc/cesu_8.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/cesu_8.$(OBJEXT): assert.h
+enc/cesu_8.$(OBJEXT): backward.h
+enc/cesu_8.$(OBJEXT): backward/2/assume.h
+enc/cesu_8.$(OBJEXT): backward/2/attributes.h
+enc/cesu_8.$(OBJEXT): backward/2/bool.h
+enc/cesu_8.$(OBJEXT): backward/2/inttypes.h
+enc/cesu_8.$(OBJEXT): backward/2/limits.h
+enc/cesu_8.$(OBJEXT): backward/2/long_long.h
+enc/cesu_8.$(OBJEXT): backward/2/stdalign.h
+enc/cesu_8.$(OBJEXT): backward/2/stdarg.h
+enc/cesu_8.$(OBJEXT): config.h
+enc/cesu_8.$(OBJEXT): defines.h
+enc/cesu_8.$(OBJEXT): enc/cesu_8.c
+enc/cesu_8.$(OBJEXT): encoding.h
+enc/cesu_8.$(OBJEXT): intern.h
+enc/cesu_8.$(OBJEXT): internal/abi.h
enc/cesu_8.$(OBJEXT): internal/anyargs.h
enc/cesu_8.$(OBJEXT): internal/arithmetic.h
enc/cesu_8.$(OBJEXT): internal/arithmetic/char.h
@@ -468,6 +600,15 @@ enc/cesu_8.$(OBJEXT): internal/core/rtypeddata.h
enc/cesu_8.$(OBJEXT): internal/ctype.h
enc/cesu_8.$(OBJEXT): internal/dllexport.h
enc/cesu_8.$(OBJEXT): internal/dosish.h
+enc/cesu_8.$(OBJEXT): internal/encoding/coderange.h
+enc/cesu_8.$(OBJEXT): internal/encoding/ctype.h
+enc/cesu_8.$(OBJEXT): internal/encoding/encoding.h
+enc/cesu_8.$(OBJEXT): internal/encoding/pathname.h
+enc/cesu_8.$(OBJEXT): internal/encoding/re.h
+enc/cesu_8.$(OBJEXT): internal/encoding/sprintf.h
+enc/cesu_8.$(OBJEXT): internal/encoding/string.h
+enc/cesu_8.$(OBJEXT): internal/encoding/symbol.h
+enc/cesu_8.$(OBJEXT): internal/encoding/transcode.h
enc/cesu_8.$(OBJEXT): internal/error.h
enc/cesu_8.$(OBJEXT): internal/eval.h
enc/cesu_8.$(OBJEXT): internal/event.h
@@ -538,37 +679,61 @@ 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): $(hdrdir)/ruby.h
+enc/cp949.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/cp949.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/cp949.$(OBJEXT): assert.h
+enc/cp949.$(OBJEXT): backward.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/inttypes.h
+enc/cp949.$(OBJEXT): backward/2/limits.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): intern.h
+enc/cp949.$(OBJEXT): internal/abi.h
+enc/cp949.$(OBJEXT): internal/anyargs.h
+enc/cp949.$(OBJEXT): internal/arithmetic.h
+enc/cp949.$(OBJEXT): internal/arithmetic/char.h
+enc/cp949.$(OBJEXT): internal/arithmetic/double.h
+enc/cp949.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/cp949.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/int.h
+enc/cp949.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/long.h
+enc/cp949.$(OBJEXT): internal/arithmetic/long_long.h
+enc/cp949.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/off_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/short.h
+enc/cp949.$(OBJEXT): internal/arithmetic/size_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/cp949.$(OBJEXT): internal/arithmetic/uid_t.h
enc/cp949.$(OBJEXT): internal/assume.h
enc/cp949.$(OBJEXT): internal/attr/alloc_size.h
+enc/cp949.$(OBJEXT): internal/attr/artificial.h
enc/cp949.$(OBJEXT): internal/attr/cold.h
enc/cp949.$(OBJEXT): internal/attr/const.h
+enc/cp949.$(OBJEXT): internal/attr/constexpr.h
enc/cp949.$(OBJEXT): internal/attr/deprecated.h
+enc/cp949.$(OBJEXT): internal/attr/diagnose_if.h
+enc/cp949.$(OBJEXT): internal/attr/enum_extensibility.h
enc/cp949.$(OBJEXT): internal/attr/error.h
+enc/cp949.$(OBJEXT): internal/attr/flag_enum.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/noalias.h
enc/cp949.$(OBJEXT): internal/attr/nodiscard.h
enc/cp949.$(OBJEXT): internal/attr/noexcept.h
enc/cp949.$(OBJEXT): internal/attr/noinline.h
@@ -578,6 +743,7 @@ 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/attr/weakref.h
enc/cp949.$(OBJEXT): internal/cast.h
enc/cp949.$(OBJEXT): internal/compiler_is.h
enc/cp949.$(OBJEXT): internal/compiler_is/apple.h
@@ -588,8 +754,30 @@ 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/constant_p.h
+enc/cp949.$(OBJEXT): internal/core.h
+enc/cp949.$(OBJEXT): internal/core/rarray.h
+enc/cp949.$(OBJEXT): internal/core/rbasic.h
+enc/cp949.$(OBJEXT): internal/core/rbignum.h
+enc/cp949.$(OBJEXT): internal/core/rclass.h
+enc/cp949.$(OBJEXT): internal/core/rdata.h
+enc/cp949.$(OBJEXT): internal/core/rfile.h
+enc/cp949.$(OBJEXT): internal/core/rhash.h
+enc/cp949.$(OBJEXT): internal/core/robject.h
+enc/cp949.$(OBJEXT): internal/core/rregexp.h
+enc/cp949.$(OBJEXT): internal/core/rstring.h
+enc/cp949.$(OBJEXT): internal/core/rstruct.h
+enc/cp949.$(OBJEXT): internal/core/rtypeddata.h
+enc/cp949.$(OBJEXT): internal/ctype.h
enc/cp949.$(OBJEXT): internal/dllexport.h
enc/cp949.$(OBJEXT): internal/dosish.h
+enc/cp949.$(OBJEXT): internal/error.h
+enc/cp949.$(OBJEXT): internal/eval.h
+enc/cp949.$(OBJEXT): internal/event.h
+enc/cp949.$(OBJEXT): internal/fl_type.h
+enc/cp949.$(OBJEXT): internal/gc.h
+enc/cp949.$(OBJEXT): internal/glob.h
+enc/cp949.$(OBJEXT): internal/globals.h
enc/cp949.$(OBJEXT): internal/has/attribute.h
enc/cp949.$(OBJEXT): internal/has/builtin.h
enc/cp949.$(OBJEXT): internal/has/c_attribute.h
@@ -598,33 +786,115 @@ 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/intern/array.h
+enc/cp949.$(OBJEXT): internal/intern/bignum.h
+enc/cp949.$(OBJEXT): internal/intern/class.h
+enc/cp949.$(OBJEXT): internal/intern/compar.h
+enc/cp949.$(OBJEXT): internal/intern/complex.h
+enc/cp949.$(OBJEXT): internal/intern/cont.h
+enc/cp949.$(OBJEXT): internal/intern/dir.h
+enc/cp949.$(OBJEXT): internal/intern/enum.h
+enc/cp949.$(OBJEXT): internal/intern/enumerator.h
+enc/cp949.$(OBJEXT): internal/intern/error.h
+enc/cp949.$(OBJEXT): internal/intern/eval.h
+enc/cp949.$(OBJEXT): internal/intern/file.h
+enc/cp949.$(OBJEXT): internal/intern/gc.h
+enc/cp949.$(OBJEXT): internal/intern/hash.h
+enc/cp949.$(OBJEXT): internal/intern/io.h
+enc/cp949.$(OBJEXT): internal/intern/load.h
+enc/cp949.$(OBJEXT): internal/intern/marshal.h
+enc/cp949.$(OBJEXT): internal/intern/numeric.h
+enc/cp949.$(OBJEXT): internal/intern/object.h
+enc/cp949.$(OBJEXT): internal/intern/parse.h
+enc/cp949.$(OBJEXT): internal/intern/proc.h
+enc/cp949.$(OBJEXT): internal/intern/process.h
+enc/cp949.$(OBJEXT): internal/intern/random.h
+enc/cp949.$(OBJEXT): internal/intern/range.h
+enc/cp949.$(OBJEXT): internal/intern/rational.h
+enc/cp949.$(OBJEXT): internal/intern/re.h
+enc/cp949.$(OBJEXT): internal/intern/ruby.h
+enc/cp949.$(OBJEXT): internal/intern/select.h
+enc/cp949.$(OBJEXT): internal/intern/select/largesize.h
+enc/cp949.$(OBJEXT): internal/intern/signal.h
+enc/cp949.$(OBJEXT): internal/intern/sprintf.h
+enc/cp949.$(OBJEXT): internal/intern/string.h
+enc/cp949.$(OBJEXT): internal/intern/struct.h
+enc/cp949.$(OBJEXT): internal/intern/thread.h
+enc/cp949.$(OBJEXT): internal/intern/time.h
+enc/cp949.$(OBJEXT): internal/intern/variable.h
+enc/cp949.$(OBJEXT): internal/intern/vm.h
+enc/cp949.$(OBJEXT): internal/interpreter.h
+enc/cp949.$(OBJEXT): internal/iterator.h
+enc/cp949.$(OBJEXT): internal/memory.h
+enc/cp949.$(OBJEXT): internal/method.h
+enc/cp949.$(OBJEXT): internal/module.h
+enc/cp949.$(OBJEXT): internal/newobj.h
+enc/cp949.$(OBJEXT): internal/rgengc.h
+enc/cp949.$(OBJEXT): internal/scan_args.h
+enc/cp949.$(OBJEXT): internal/special_consts.h
+enc/cp949.$(OBJEXT): internal/static_assert.h
enc/cp949.$(OBJEXT): internal/stdalign.h
enc/cp949.$(OBJEXT): internal/stdbool.h
+enc/cp949.$(OBJEXT): internal/symbol.h
+enc/cp949.$(OBJEXT): internal/value.h
+enc/cp949.$(OBJEXT): internal/value_type.h
+enc/cp949.$(OBJEXT): internal/variable.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/cp949.$(OBJEXT): st.h
+enc/cp949.$(OBJEXT): subst.h
+enc/emacs_mule.$(OBJEXT): $(hdrdir)/ruby.h
+enc/emacs_mule.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/emacs_mule.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/emacs_mule.$(OBJEXT): assert.h
+enc/emacs_mule.$(OBJEXT): backward.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/inttypes.h
+enc/emacs_mule.$(OBJEXT): backward/2/limits.h
+enc/emacs_mule.$(OBJEXT): backward/2/long_long.h
+enc/emacs_mule.$(OBJEXT): backward/2/stdalign.h
+enc/emacs_mule.$(OBJEXT): backward/2/stdarg.h
+enc/emacs_mule.$(OBJEXT): config.h
+enc/emacs_mule.$(OBJEXT): defines.h
+enc/emacs_mule.$(OBJEXT): enc/emacs_mule.c
+enc/emacs_mule.$(OBJEXT): intern.h
+enc/emacs_mule.$(OBJEXT): internal/abi.h
+enc/emacs_mule.$(OBJEXT): internal/anyargs.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/char.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/double.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/int.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/long.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/long_long.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/off_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/short.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/size_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/emacs_mule.$(OBJEXT): internal/arithmetic/uid_t.h
enc/emacs_mule.$(OBJEXT): internal/assume.h
enc/emacs_mule.$(OBJEXT): internal/attr/alloc_size.h
+enc/emacs_mule.$(OBJEXT): internal/attr/artificial.h
enc/emacs_mule.$(OBJEXT): internal/attr/cold.h
enc/emacs_mule.$(OBJEXT): internal/attr/const.h
+enc/emacs_mule.$(OBJEXT): internal/attr/constexpr.h
enc/emacs_mule.$(OBJEXT): internal/attr/deprecated.h
+enc/emacs_mule.$(OBJEXT): internal/attr/diagnose_if.h
+enc/emacs_mule.$(OBJEXT): internal/attr/enum_extensibility.h
enc/emacs_mule.$(OBJEXT): internal/attr/error.h
+enc/emacs_mule.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -634,6 +904,7 @@ 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/attr/weakref.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
@@ -644,8 +915,30 @@ 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/constant_p.h
+enc/emacs_mule.$(OBJEXT): internal/core.h
+enc/emacs_mule.$(OBJEXT): internal/core/rarray.h
+enc/emacs_mule.$(OBJEXT): internal/core/rbasic.h
+enc/emacs_mule.$(OBJEXT): internal/core/rbignum.h
+enc/emacs_mule.$(OBJEXT): internal/core/rclass.h
+enc/emacs_mule.$(OBJEXT): internal/core/rdata.h
+enc/emacs_mule.$(OBJEXT): internal/core/rfile.h
+enc/emacs_mule.$(OBJEXT): internal/core/rhash.h
+enc/emacs_mule.$(OBJEXT): internal/core/robject.h
+enc/emacs_mule.$(OBJEXT): internal/core/rregexp.h
+enc/emacs_mule.$(OBJEXT): internal/core/rstring.h
+enc/emacs_mule.$(OBJEXT): internal/core/rstruct.h
+enc/emacs_mule.$(OBJEXT): internal/core/rtypeddata.h
+enc/emacs_mule.$(OBJEXT): internal/ctype.h
enc/emacs_mule.$(OBJEXT): internal/dllexport.h
enc/emacs_mule.$(OBJEXT): internal/dosish.h
+enc/emacs_mule.$(OBJEXT): internal/error.h
+enc/emacs_mule.$(OBJEXT): internal/eval.h
+enc/emacs_mule.$(OBJEXT): internal/event.h
+enc/emacs_mule.$(OBJEXT): internal/fl_type.h
+enc/emacs_mule.$(OBJEXT): internal/gc.h
+enc/emacs_mule.$(OBJEXT): internal/glob.h
+enc/emacs_mule.$(OBJEXT): internal/globals.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
@@ -654,27 +947,84 @@ 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/intern/array.h
+enc/emacs_mule.$(OBJEXT): internal/intern/bignum.h
+enc/emacs_mule.$(OBJEXT): internal/intern/class.h
+enc/emacs_mule.$(OBJEXT): internal/intern/compar.h
+enc/emacs_mule.$(OBJEXT): internal/intern/complex.h
+enc/emacs_mule.$(OBJEXT): internal/intern/cont.h
+enc/emacs_mule.$(OBJEXT): internal/intern/dir.h
+enc/emacs_mule.$(OBJEXT): internal/intern/enum.h
+enc/emacs_mule.$(OBJEXT): internal/intern/enumerator.h
+enc/emacs_mule.$(OBJEXT): internal/intern/error.h
+enc/emacs_mule.$(OBJEXT): internal/intern/eval.h
+enc/emacs_mule.$(OBJEXT): internal/intern/file.h
+enc/emacs_mule.$(OBJEXT): internal/intern/gc.h
+enc/emacs_mule.$(OBJEXT): internal/intern/hash.h
+enc/emacs_mule.$(OBJEXT): internal/intern/io.h
+enc/emacs_mule.$(OBJEXT): internal/intern/load.h
+enc/emacs_mule.$(OBJEXT): internal/intern/marshal.h
+enc/emacs_mule.$(OBJEXT): internal/intern/numeric.h
+enc/emacs_mule.$(OBJEXT): internal/intern/object.h
+enc/emacs_mule.$(OBJEXT): internal/intern/parse.h
+enc/emacs_mule.$(OBJEXT): internal/intern/proc.h
+enc/emacs_mule.$(OBJEXT): internal/intern/process.h
+enc/emacs_mule.$(OBJEXT): internal/intern/random.h
+enc/emacs_mule.$(OBJEXT): internal/intern/range.h
+enc/emacs_mule.$(OBJEXT): internal/intern/rational.h
+enc/emacs_mule.$(OBJEXT): internal/intern/re.h
+enc/emacs_mule.$(OBJEXT): internal/intern/ruby.h
+enc/emacs_mule.$(OBJEXT): internal/intern/select.h
+enc/emacs_mule.$(OBJEXT): internal/intern/select/largesize.h
+enc/emacs_mule.$(OBJEXT): internal/intern/signal.h
+enc/emacs_mule.$(OBJEXT): internal/intern/sprintf.h
+enc/emacs_mule.$(OBJEXT): internal/intern/string.h
+enc/emacs_mule.$(OBJEXT): internal/intern/struct.h
+enc/emacs_mule.$(OBJEXT): internal/intern/thread.h
+enc/emacs_mule.$(OBJEXT): internal/intern/time.h
+enc/emacs_mule.$(OBJEXT): internal/intern/variable.h
+enc/emacs_mule.$(OBJEXT): internal/intern/vm.h
+enc/emacs_mule.$(OBJEXT): internal/interpreter.h
+enc/emacs_mule.$(OBJEXT): internal/iterator.h
+enc/emacs_mule.$(OBJEXT): internal/memory.h
+enc/emacs_mule.$(OBJEXT): internal/method.h
+enc/emacs_mule.$(OBJEXT): internal/module.h
+enc/emacs_mule.$(OBJEXT): internal/newobj.h
+enc/emacs_mule.$(OBJEXT): internal/rgengc.h
+enc/emacs_mule.$(OBJEXT): internal/scan_args.h
+enc/emacs_mule.$(OBJEXT): internal/special_consts.h
+enc/emacs_mule.$(OBJEXT): internal/static_assert.h
enc/emacs_mule.$(OBJEXT): internal/stdalign.h
enc/emacs_mule.$(OBJEXT): internal/stdbool.h
+enc/emacs_mule.$(OBJEXT): internal/symbol.h
+enc/emacs_mule.$(OBJEXT): internal/value.h
+enc/emacs_mule.$(OBJEXT): internal/value_type.h
+enc/emacs_mule.$(OBJEXT): internal/variable.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
enc/emacs_mule.$(OBJEXT): missing.h
enc/emacs_mule.$(OBJEXT): onigmo.h
-enc/encdb.$(OBJEXT): $(hdrdir)/ruby.h
+enc/emacs_mule.$(OBJEXT): st.h
+enc/emacs_mule.$(OBJEXT): subst.h
enc/encdb.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-enc/encdb.$(OBJEXT): $(top_srcdir)/internal.h
enc/encdb.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+enc/encdb.$(OBJEXT): assert.h
+enc/encdb.$(OBJEXT): backward.h
+enc/encdb.$(OBJEXT): backward/2/assume.h
+enc/encdb.$(OBJEXT): backward/2/attributes.h
+enc/encdb.$(OBJEXT): backward/2/bool.h
+enc/encdb.$(OBJEXT): backward/2/inttypes.h
+enc/encdb.$(OBJEXT): backward/2/limits.h
+enc/encdb.$(OBJEXT): backward/2/long_long.h
+enc/encdb.$(OBJEXT): backward/2/stdalign.h
+enc/encdb.$(OBJEXT): backward/2/stdarg.h
+enc/encdb.$(OBJEXT): config.h
+enc/encdb.$(OBJEXT): defines.h
+enc/encdb.$(OBJEXT): enc/encdb.c
+enc/encdb.$(OBJEXT): encdb.h
+enc/encdb.$(OBJEXT): encoding.h
+enc/encdb.$(OBJEXT): intern.h
+enc/encdb.$(OBJEXT): internal/abi.h
enc/encdb.$(OBJEXT): internal/anyargs.h
enc/encdb.$(OBJEXT): internal/arithmetic.h
enc/encdb.$(OBJEXT): internal/arithmetic/char.h
@@ -744,6 +1094,15 @@ enc/encdb.$(OBJEXT): internal/core/rtypeddata.h
enc/encdb.$(OBJEXT): internal/ctype.h
enc/encdb.$(OBJEXT): internal/dllexport.h
enc/encdb.$(OBJEXT): internal/dosish.h
+enc/encdb.$(OBJEXT): internal/encoding/coderange.h
+enc/encdb.$(OBJEXT): internal/encoding/ctype.h
+enc/encdb.$(OBJEXT): internal/encoding/encoding.h
+enc/encdb.$(OBJEXT): internal/encoding/pathname.h
+enc/encdb.$(OBJEXT): internal/encoding/re.h
+enc/encdb.$(OBJEXT): internal/encoding/sprintf.h
+enc/encdb.$(OBJEXT): internal/encoding/string.h
+enc/encdb.$(OBJEXT): internal/encoding/symbol.h
+enc/encdb.$(OBJEXT): internal/encoding/transcode.h
enc/encdb.$(OBJEXT): internal/error.h
enc/encdb.$(OBJEXT): internal/eval.h
enc/encdb.$(OBJEXT): internal/event.h
@@ -814,38 +1173,63 @@ 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): $(hdrdir)/ruby.h
+enc/euc_jp.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/euc_jp.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/euc_jp.$(OBJEXT): assert.h
+enc/euc_jp.$(OBJEXT): backward.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/inttypes.h
+enc/euc_jp.$(OBJEXT): backward/2/limits.h
+enc/euc_jp.$(OBJEXT): backward/2/long_long.h
+enc/euc_jp.$(OBJEXT): backward/2/stdalign.h
+enc/euc_jp.$(OBJEXT): backward/2/stdarg.h
+enc/euc_jp.$(OBJEXT): config.h
+enc/euc_jp.$(OBJEXT): defines.h
+enc/euc_jp.$(OBJEXT): enc/euc_jp.c
+enc/euc_jp.$(OBJEXT): enc/jis/props.h
+enc/euc_jp.$(OBJEXT): enc/jis/props.kwd
+enc/euc_jp.$(OBJEXT): intern.h
+enc/euc_jp.$(OBJEXT): internal/abi.h
+enc/euc_jp.$(OBJEXT): internal/anyargs.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/char.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/double.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/int.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/long.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/long_long.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/off_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/short.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/size_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/euc_jp.$(OBJEXT): internal/arithmetic/uid_t.h
enc/euc_jp.$(OBJEXT): internal/assume.h
enc/euc_jp.$(OBJEXT): internal/attr/alloc_size.h
+enc/euc_jp.$(OBJEXT): internal/attr/artificial.h
enc/euc_jp.$(OBJEXT): internal/attr/cold.h
enc/euc_jp.$(OBJEXT): internal/attr/const.h
+enc/euc_jp.$(OBJEXT): internal/attr/constexpr.h
enc/euc_jp.$(OBJEXT): internal/attr/deprecated.h
+enc/euc_jp.$(OBJEXT): internal/attr/diagnose_if.h
+enc/euc_jp.$(OBJEXT): internal/attr/enum_extensibility.h
enc/euc_jp.$(OBJEXT): internal/attr/error.h
+enc/euc_jp.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -855,6 +1239,7 @@ 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/attr/weakref.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
@@ -865,8 +1250,30 @@ 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/constant_p.h
+enc/euc_jp.$(OBJEXT): internal/core.h
+enc/euc_jp.$(OBJEXT): internal/core/rarray.h
+enc/euc_jp.$(OBJEXT): internal/core/rbasic.h
+enc/euc_jp.$(OBJEXT): internal/core/rbignum.h
+enc/euc_jp.$(OBJEXT): internal/core/rclass.h
+enc/euc_jp.$(OBJEXT): internal/core/rdata.h
+enc/euc_jp.$(OBJEXT): internal/core/rfile.h
+enc/euc_jp.$(OBJEXT): internal/core/rhash.h
+enc/euc_jp.$(OBJEXT): internal/core/robject.h
+enc/euc_jp.$(OBJEXT): internal/core/rregexp.h
+enc/euc_jp.$(OBJEXT): internal/core/rstring.h
+enc/euc_jp.$(OBJEXT): internal/core/rstruct.h
+enc/euc_jp.$(OBJEXT): internal/core/rtypeddata.h
+enc/euc_jp.$(OBJEXT): internal/ctype.h
enc/euc_jp.$(OBJEXT): internal/dllexport.h
enc/euc_jp.$(OBJEXT): internal/dosish.h
+enc/euc_jp.$(OBJEXT): internal/error.h
+enc/euc_jp.$(OBJEXT): internal/eval.h
+enc/euc_jp.$(OBJEXT): internal/event.h
+enc/euc_jp.$(OBJEXT): internal/fl_type.h
+enc/euc_jp.$(OBJEXT): internal/gc.h
+enc/euc_jp.$(OBJEXT): internal/glob.h
+enc/euc_jp.$(OBJEXT): internal/globals.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
@@ -875,35 +1282,115 @@ 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/intern/array.h
+enc/euc_jp.$(OBJEXT): internal/intern/bignum.h
+enc/euc_jp.$(OBJEXT): internal/intern/class.h
+enc/euc_jp.$(OBJEXT): internal/intern/compar.h
+enc/euc_jp.$(OBJEXT): internal/intern/complex.h
+enc/euc_jp.$(OBJEXT): internal/intern/cont.h
+enc/euc_jp.$(OBJEXT): internal/intern/dir.h
+enc/euc_jp.$(OBJEXT): internal/intern/enum.h
+enc/euc_jp.$(OBJEXT): internal/intern/enumerator.h
+enc/euc_jp.$(OBJEXT): internal/intern/error.h
+enc/euc_jp.$(OBJEXT): internal/intern/eval.h
+enc/euc_jp.$(OBJEXT): internal/intern/file.h
+enc/euc_jp.$(OBJEXT): internal/intern/gc.h
+enc/euc_jp.$(OBJEXT): internal/intern/hash.h
+enc/euc_jp.$(OBJEXT): internal/intern/io.h
+enc/euc_jp.$(OBJEXT): internal/intern/load.h
+enc/euc_jp.$(OBJEXT): internal/intern/marshal.h
+enc/euc_jp.$(OBJEXT): internal/intern/numeric.h
+enc/euc_jp.$(OBJEXT): internal/intern/object.h
+enc/euc_jp.$(OBJEXT): internal/intern/parse.h
+enc/euc_jp.$(OBJEXT): internal/intern/proc.h
+enc/euc_jp.$(OBJEXT): internal/intern/process.h
+enc/euc_jp.$(OBJEXT): internal/intern/random.h
+enc/euc_jp.$(OBJEXT): internal/intern/range.h
+enc/euc_jp.$(OBJEXT): internal/intern/rational.h
+enc/euc_jp.$(OBJEXT): internal/intern/re.h
+enc/euc_jp.$(OBJEXT): internal/intern/ruby.h
+enc/euc_jp.$(OBJEXT): internal/intern/select.h
+enc/euc_jp.$(OBJEXT): internal/intern/select/largesize.h
+enc/euc_jp.$(OBJEXT): internal/intern/signal.h
+enc/euc_jp.$(OBJEXT): internal/intern/sprintf.h
+enc/euc_jp.$(OBJEXT): internal/intern/string.h
+enc/euc_jp.$(OBJEXT): internal/intern/struct.h
+enc/euc_jp.$(OBJEXT): internal/intern/thread.h
+enc/euc_jp.$(OBJEXT): internal/intern/time.h
+enc/euc_jp.$(OBJEXT): internal/intern/variable.h
+enc/euc_jp.$(OBJEXT): internal/intern/vm.h
+enc/euc_jp.$(OBJEXT): internal/interpreter.h
+enc/euc_jp.$(OBJEXT): internal/iterator.h
+enc/euc_jp.$(OBJEXT): internal/memory.h
+enc/euc_jp.$(OBJEXT): internal/method.h
+enc/euc_jp.$(OBJEXT): internal/module.h
+enc/euc_jp.$(OBJEXT): internal/newobj.h
+enc/euc_jp.$(OBJEXT): internal/rgengc.h
+enc/euc_jp.$(OBJEXT): internal/scan_args.h
+enc/euc_jp.$(OBJEXT): internal/special_consts.h
+enc/euc_jp.$(OBJEXT): internal/static_assert.h
enc/euc_jp.$(OBJEXT): internal/stdalign.h
enc/euc_jp.$(OBJEXT): internal/stdbool.h
+enc/euc_jp.$(OBJEXT): internal/symbol.h
+enc/euc_jp.$(OBJEXT): internal/value.h
+enc/euc_jp.$(OBJEXT): internal/value_type.h
+enc/euc_jp.$(OBJEXT): internal/variable.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
-enc/euc_jp.$(OBJEXT): enc/jis/props.h
-enc/euc_jp.$(OBJEXT): enc/jis/props.kwd
enc/euc_jp.$(OBJEXT): missing.h
enc/euc_jp.$(OBJEXT): onigmo.h
+enc/euc_jp.$(OBJEXT): st.h
+enc/euc_jp.$(OBJEXT): subst.h
+enc/euc_kr.$(OBJEXT): $(hdrdir)/ruby.h
+enc/euc_kr.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/euc_kr.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/euc_kr.$(OBJEXT): assert.h
+enc/euc_kr.$(OBJEXT): backward.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/inttypes.h
+enc/euc_kr.$(OBJEXT): backward/2/limits.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): intern.h
+enc/euc_kr.$(OBJEXT): internal/abi.h
+enc/euc_kr.$(OBJEXT): internal/anyargs.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/char.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/double.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/int.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/long.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/long_long.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/off_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/short.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/size_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/euc_kr.$(OBJEXT): internal/arithmetic/uid_t.h
enc/euc_kr.$(OBJEXT): internal/assume.h
enc/euc_kr.$(OBJEXT): internal/attr/alloc_size.h
+enc/euc_kr.$(OBJEXT): internal/attr/artificial.h
enc/euc_kr.$(OBJEXT): internal/attr/cold.h
enc/euc_kr.$(OBJEXT): internal/attr/const.h
+enc/euc_kr.$(OBJEXT): internal/attr/constexpr.h
enc/euc_kr.$(OBJEXT): internal/attr/deprecated.h
+enc/euc_kr.$(OBJEXT): internal/attr/diagnose_if.h
+enc/euc_kr.$(OBJEXT): internal/attr/enum_extensibility.h
enc/euc_kr.$(OBJEXT): internal/attr/error.h
+enc/euc_kr.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -913,6 +1400,7 @@ 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/attr/weakref.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
@@ -923,8 +1411,30 @@ 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/constant_p.h
+enc/euc_kr.$(OBJEXT): internal/core.h
+enc/euc_kr.$(OBJEXT): internal/core/rarray.h
+enc/euc_kr.$(OBJEXT): internal/core/rbasic.h
+enc/euc_kr.$(OBJEXT): internal/core/rbignum.h
+enc/euc_kr.$(OBJEXT): internal/core/rclass.h
+enc/euc_kr.$(OBJEXT): internal/core/rdata.h
+enc/euc_kr.$(OBJEXT): internal/core/rfile.h
+enc/euc_kr.$(OBJEXT): internal/core/rhash.h
+enc/euc_kr.$(OBJEXT): internal/core/robject.h
+enc/euc_kr.$(OBJEXT): internal/core/rregexp.h
+enc/euc_kr.$(OBJEXT): internal/core/rstring.h
+enc/euc_kr.$(OBJEXT): internal/core/rstruct.h
+enc/euc_kr.$(OBJEXT): internal/core/rtypeddata.h
+enc/euc_kr.$(OBJEXT): internal/ctype.h
enc/euc_kr.$(OBJEXT): internal/dllexport.h
enc/euc_kr.$(OBJEXT): internal/dosish.h
+enc/euc_kr.$(OBJEXT): internal/error.h
+enc/euc_kr.$(OBJEXT): internal/eval.h
+enc/euc_kr.$(OBJEXT): internal/event.h
+enc/euc_kr.$(OBJEXT): internal/fl_type.h
+enc/euc_kr.$(OBJEXT): internal/gc.h
+enc/euc_kr.$(OBJEXT): internal/glob.h
+enc/euc_kr.$(OBJEXT): internal/globals.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
@@ -933,33 +1443,115 @@ 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/intern/array.h
+enc/euc_kr.$(OBJEXT): internal/intern/bignum.h
+enc/euc_kr.$(OBJEXT): internal/intern/class.h
+enc/euc_kr.$(OBJEXT): internal/intern/compar.h
+enc/euc_kr.$(OBJEXT): internal/intern/complex.h
+enc/euc_kr.$(OBJEXT): internal/intern/cont.h
+enc/euc_kr.$(OBJEXT): internal/intern/dir.h
+enc/euc_kr.$(OBJEXT): internal/intern/enum.h
+enc/euc_kr.$(OBJEXT): internal/intern/enumerator.h
+enc/euc_kr.$(OBJEXT): internal/intern/error.h
+enc/euc_kr.$(OBJEXT): internal/intern/eval.h
+enc/euc_kr.$(OBJEXT): internal/intern/file.h
+enc/euc_kr.$(OBJEXT): internal/intern/gc.h
+enc/euc_kr.$(OBJEXT): internal/intern/hash.h
+enc/euc_kr.$(OBJEXT): internal/intern/io.h
+enc/euc_kr.$(OBJEXT): internal/intern/load.h
+enc/euc_kr.$(OBJEXT): internal/intern/marshal.h
+enc/euc_kr.$(OBJEXT): internal/intern/numeric.h
+enc/euc_kr.$(OBJEXT): internal/intern/object.h
+enc/euc_kr.$(OBJEXT): internal/intern/parse.h
+enc/euc_kr.$(OBJEXT): internal/intern/proc.h
+enc/euc_kr.$(OBJEXT): internal/intern/process.h
+enc/euc_kr.$(OBJEXT): internal/intern/random.h
+enc/euc_kr.$(OBJEXT): internal/intern/range.h
+enc/euc_kr.$(OBJEXT): internal/intern/rational.h
+enc/euc_kr.$(OBJEXT): internal/intern/re.h
+enc/euc_kr.$(OBJEXT): internal/intern/ruby.h
+enc/euc_kr.$(OBJEXT): internal/intern/select.h
+enc/euc_kr.$(OBJEXT): internal/intern/select/largesize.h
+enc/euc_kr.$(OBJEXT): internal/intern/signal.h
+enc/euc_kr.$(OBJEXT): internal/intern/sprintf.h
+enc/euc_kr.$(OBJEXT): internal/intern/string.h
+enc/euc_kr.$(OBJEXT): internal/intern/struct.h
+enc/euc_kr.$(OBJEXT): internal/intern/thread.h
+enc/euc_kr.$(OBJEXT): internal/intern/time.h
+enc/euc_kr.$(OBJEXT): internal/intern/variable.h
+enc/euc_kr.$(OBJEXT): internal/intern/vm.h
+enc/euc_kr.$(OBJEXT): internal/interpreter.h
+enc/euc_kr.$(OBJEXT): internal/iterator.h
+enc/euc_kr.$(OBJEXT): internal/memory.h
+enc/euc_kr.$(OBJEXT): internal/method.h
+enc/euc_kr.$(OBJEXT): internal/module.h
+enc/euc_kr.$(OBJEXT): internal/newobj.h
+enc/euc_kr.$(OBJEXT): internal/rgengc.h
+enc/euc_kr.$(OBJEXT): internal/scan_args.h
+enc/euc_kr.$(OBJEXT): internal/special_consts.h
+enc/euc_kr.$(OBJEXT): internal/static_assert.h
enc/euc_kr.$(OBJEXT): internal/stdalign.h
enc/euc_kr.$(OBJEXT): internal/stdbool.h
+enc/euc_kr.$(OBJEXT): internal/symbol.h
+enc/euc_kr.$(OBJEXT): internal/value.h
+enc/euc_kr.$(OBJEXT): internal/value_type.h
+enc/euc_kr.$(OBJEXT): internal/variable.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_kr.$(OBJEXT): st.h
+enc/euc_kr.$(OBJEXT): subst.h
+enc/euc_tw.$(OBJEXT): $(hdrdir)/ruby.h
+enc/euc_tw.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/euc_tw.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/euc_tw.$(OBJEXT): assert.h
+enc/euc_tw.$(OBJEXT): backward.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/inttypes.h
+enc/euc_tw.$(OBJEXT): backward/2/limits.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): intern.h
+enc/euc_tw.$(OBJEXT): internal/abi.h
+enc/euc_tw.$(OBJEXT): internal/anyargs.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/char.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/double.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/int.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/long.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/long_long.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/off_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/short.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/size_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/euc_tw.$(OBJEXT): internal/arithmetic/uid_t.h
enc/euc_tw.$(OBJEXT): internal/assume.h
enc/euc_tw.$(OBJEXT): internal/attr/alloc_size.h
+enc/euc_tw.$(OBJEXT): internal/attr/artificial.h
enc/euc_tw.$(OBJEXT): internal/attr/cold.h
enc/euc_tw.$(OBJEXT): internal/attr/const.h
+enc/euc_tw.$(OBJEXT): internal/attr/constexpr.h
enc/euc_tw.$(OBJEXT): internal/attr/deprecated.h
+enc/euc_tw.$(OBJEXT): internal/attr/diagnose_if.h
+enc/euc_tw.$(OBJEXT): internal/attr/enum_extensibility.h
enc/euc_tw.$(OBJEXT): internal/attr/error.h
+enc/euc_tw.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -969,6 +1561,7 @@ 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/attr/weakref.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
@@ -979,8 +1572,30 @@ 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/constant_p.h
+enc/euc_tw.$(OBJEXT): internal/core.h
+enc/euc_tw.$(OBJEXT): internal/core/rarray.h
+enc/euc_tw.$(OBJEXT): internal/core/rbasic.h
+enc/euc_tw.$(OBJEXT): internal/core/rbignum.h
+enc/euc_tw.$(OBJEXT): internal/core/rclass.h
+enc/euc_tw.$(OBJEXT): internal/core/rdata.h
+enc/euc_tw.$(OBJEXT): internal/core/rfile.h
+enc/euc_tw.$(OBJEXT): internal/core/rhash.h
+enc/euc_tw.$(OBJEXT): internal/core/robject.h
+enc/euc_tw.$(OBJEXT): internal/core/rregexp.h
+enc/euc_tw.$(OBJEXT): internal/core/rstring.h
+enc/euc_tw.$(OBJEXT): internal/core/rstruct.h
+enc/euc_tw.$(OBJEXT): internal/core/rtypeddata.h
+enc/euc_tw.$(OBJEXT): internal/ctype.h
enc/euc_tw.$(OBJEXT): internal/dllexport.h
enc/euc_tw.$(OBJEXT): internal/dosish.h
+enc/euc_tw.$(OBJEXT): internal/error.h
+enc/euc_tw.$(OBJEXT): internal/eval.h
+enc/euc_tw.$(OBJEXT): internal/event.h
+enc/euc_tw.$(OBJEXT): internal/fl_type.h
+enc/euc_tw.$(OBJEXT): internal/gc.h
+enc/euc_tw.$(OBJEXT): internal/glob.h
+enc/euc_tw.$(OBJEXT): internal/globals.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
@@ -989,33 +1604,115 @@ 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/intern/array.h
+enc/euc_tw.$(OBJEXT): internal/intern/bignum.h
+enc/euc_tw.$(OBJEXT): internal/intern/class.h
+enc/euc_tw.$(OBJEXT): internal/intern/compar.h
+enc/euc_tw.$(OBJEXT): internal/intern/complex.h
+enc/euc_tw.$(OBJEXT): internal/intern/cont.h
+enc/euc_tw.$(OBJEXT): internal/intern/dir.h
+enc/euc_tw.$(OBJEXT): internal/intern/enum.h
+enc/euc_tw.$(OBJEXT): internal/intern/enumerator.h
+enc/euc_tw.$(OBJEXT): internal/intern/error.h
+enc/euc_tw.$(OBJEXT): internal/intern/eval.h
+enc/euc_tw.$(OBJEXT): internal/intern/file.h
+enc/euc_tw.$(OBJEXT): internal/intern/gc.h
+enc/euc_tw.$(OBJEXT): internal/intern/hash.h
+enc/euc_tw.$(OBJEXT): internal/intern/io.h
+enc/euc_tw.$(OBJEXT): internal/intern/load.h
+enc/euc_tw.$(OBJEXT): internal/intern/marshal.h
+enc/euc_tw.$(OBJEXT): internal/intern/numeric.h
+enc/euc_tw.$(OBJEXT): internal/intern/object.h
+enc/euc_tw.$(OBJEXT): internal/intern/parse.h
+enc/euc_tw.$(OBJEXT): internal/intern/proc.h
+enc/euc_tw.$(OBJEXT): internal/intern/process.h
+enc/euc_tw.$(OBJEXT): internal/intern/random.h
+enc/euc_tw.$(OBJEXT): internal/intern/range.h
+enc/euc_tw.$(OBJEXT): internal/intern/rational.h
+enc/euc_tw.$(OBJEXT): internal/intern/re.h
+enc/euc_tw.$(OBJEXT): internal/intern/ruby.h
+enc/euc_tw.$(OBJEXT): internal/intern/select.h
+enc/euc_tw.$(OBJEXT): internal/intern/select/largesize.h
+enc/euc_tw.$(OBJEXT): internal/intern/signal.h
+enc/euc_tw.$(OBJEXT): internal/intern/sprintf.h
+enc/euc_tw.$(OBJEXT): internal/intern/string.h
+enc/euc_tw.$(OBJEXT): internal/intern/struct.h
+enc/euc_tw.$(OBJEXT): internal/intern/thread.h
+enc/euc_tw.$(OBJEXT): internal/intern/time.h
+enc/euc_tw.$(OBJEXT): internal/intern/variable.h
+enc/euc_tw.$(OBJEXT): internal/intern/vm.h
+enc/euc_tw.$(OBJEXT): internal/interpreter.h
+enc/euc_tw.$(OBJEXT): internal/iterator.h
+enc/euc_tw.$(OBJEXT): internal/memory.h
+enc/euc_tw.$(OBJEXT): internal/method.h
+enc/euc_tw.$(OBJEXT): internal/module.h
+enc/euc_tw.$(OBJEXT): internal/newobj.h
+enc/euc_tw.$(OBJEXT): internal/rgengc.h
+enc/euc_tw.$(OBJEXT): internal/scan_args.h
+enc/euc_tw.$(OBJEXT): internal/special_consts.h
+enc/euc_tw.$(OBJEXT): internal/static_assert.h
enc/euc_tw.$(OBJEXT): internal/stdalign.h
enc/euc_tw.$(OBJEXT): internal/stdbool.h
+enc/euc_tw.$(OBJEXT): internal/symbol.h
+enc/euc_tw.$(OBJEXT): internal/value.h
+enc/euc_tw.$(OBJEXT): internal/value_type.h
+enc/euc_tw.$(OBJEXT): internal/variable.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/euc_tw.$(OBJEXT): st.h
+enc/euc_tw.$(OBJEXT): subst.h
+enc/gb18030.$(OBJEXT): $(hdrdir)/ruby.h
+enc/gb18030.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/gb18030.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/gb18030.$(OBJEXT): assert.h
+enc/gb18030.$(OBJEXT): backward.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/inttypes.h
+enc/gb18030.$(OBJEXT): backward/2/limits.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): intern.h
+enc/gb18030.$(OBJEXT): internal/abi.h
+enc/gb18030.$(OBJEXT): internal/anyargs.h
+enc/gb18030.$(OBJEXT): internal/arithmetic.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/char.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/double.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/int.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/long.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/long_long.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/off_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/short.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/size_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/gb18030.$(OBJEXT): internal/arithmetic/uid_t.h
enc/gb18030.$(OBJEXT): internal/assume.h
enc/gb18030.$(OBJEXT): internal/attr/alloc_size.h
+enc/gb18030.$(OBJEXT): internal/attr/artificial.h
enc/gb18030.$(OBJEXT): internal/attr/cold.h
enc/gb18030.$(OBJEXT): internal/attr/const.h
+enc/gb18030.$(OBJEXT): internal/attr/constexpr.h
enc/gb18030.$(OBJEXT): internal/attr/deprecated.h
+enc/gb18030.$(OBJEXT): internal/attr/diagnose_if.h
+enc/gb18030.$(OBJEXT): internal/attr/enum_extensibility.h
enc/gb18030.$(OBJEXT): internal/attr/error.h
+enc/gb18030.$(OBJEXT): internal/attr/flag_enum.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/noalias.h
enc/gb18030.$(OBJEXT): internal/attr/nodiscard.h
enc/gb18030.$(OBJEXT): internal/attr/noexcept.h
enc/gb18030.$(OBJEXT): internal/attr/noinline.h
@@ -1025,6 +1722,7 @@ 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/attr/weakref.h
enc/gb18030.$(OBJEXT): internal/cast.h
enc/gb18030.$(OBJEXT): internal/compiler_is.h
enc/gb18030.$(OBJEXT): internal/compiler_is/apple.h
@@ -1035,8 +1733,30 @@ 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/constant_p.h
+enc/gb18030.$(OBJEXT): internal/core.h
+enc/gb18030.$(OBJEXT): internal/core/rarray.h
+enc/gb18030.$(OBJEXT): internal/core/rbasic.h
+enc/gb18030.$(OBJEXT): internal/core/rbignum.h
+enc/gb18030.$(OBJEXT): internal/core/rclass.h
+enc/gb18030.$(OBJEXT): internal/core/rdata.h
+enc/gb18030.$(OBJEXT): internal/core/rfile.h
+enc/gb18030.$(OBJEXT): internal/core/rhash.h
+enc/gb18030.$(OBJEXT): internal/core/robject.h
+enc/gb18030.$(OBJEXT): internal/core/rregexp.h
+enc/gb18030.$(OBJEXT): internal/core/rstring.h
+enc/gb18030.$(OBJEXT): internal/core/rstruct.h
+enc/gb18030.$(OBJEXT): internal/core/rtypeddata.h
+enc/gb18030.$(OBJEXT): internal/ctype.h
enc/gb18030.$(OBJEXT): internal/dllexport.h
enc/gb18030.$(OBJEXT): internal/dosish.h
+enc/gb18030.$(OBJEXT): internal/error.h
+enc/gb18030.$(OBJEXT): internal/eval.h
+enc/gb18030.$(OBJEXT): internal/event.h
+enc/gb18030.$(OBJEXT): internal/fl_type.h
+enc/gb18030.$(OBJEXT): internal/gc.h
+enc/gb18030.$(OBJEXT): internal/glob.h
+enc/gb18030.$(OBJEXT): internal/globals.h
enc/gb18030.$(OBJEXT): internal/has/attribute.h
enc/gb18030.$(OBJEXT): internal/has/builtin.h
enc/gb18030.$(OBJEXT): internal/has/c_attribute.h
@@ -1045,33 +1765,115 @@ 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/intern/array.h
+enc/gb18030.$(OBJEXT): internal/intern/bignum.h
+enc/gb18030.$(OBJEXT): internal/intern/class.h
+enc/gb18030.$(OBJEXT): internal/intern/compar.h
+enc/gb18030.$(OBJEXT): internal/intern/complex.h
+enc/gb18030.$(OBJEXT): internal/intern/cont.h
+enc/gb18030.$(OBJEXT): internal/intern/dir.h
+enc/gb18030.$(OBJEXT): internal/intern/enum.h
+enc/gb18030.$(OBJEXT): internal/intern/enumerator.h
+enc/gb18030.$(OBJEXT): internal/intern/error.h
+enc/gb18030.$(OBJEXT): internal/intern/eval.h
+enc/gb18030.$(OBJEXT): internal/intern/file.h
+enc/gb18030.$(OBJEXT): internal/intern/gc.h
+enc/gb18030.$(OBJEXT): internal/intern/hash.h
+enc/gb18030.$(OBJEXT): internal/intern/io.h
+enc/gb18030.$(OBJEXT): internal/intern/load.h
+enc/gb18030.$(OBJEXT): internal/intern/marshal.h
+enc/gb18030.$(OBJEXT): internal/intern/numeric.h
+enc/gb18030.$(OBJEXT): internal/intern/object.h
+enc/gb18030.$(OBJEXT): internal/intern/parse.h
+enc/gb18030.$(OBJEXT): internal/intern/proc.h
+enc/gb18030.$(OBJEXT): internal/intern/process.h
+enc/gb18030.$(OBJEXT): internal/intern/random.h
+enc/gb18030.$(OBJEXT): internal/intern/range.h
+enc/gb18030.$(OBJEXT): internal/intern/rational.h
+enc/gb18030.$(OBJEXT): internal/intern/re.h
+enc/gb18030.$(OBJEXT): internal/intern/ruby.h
+enc/gb18030.$(OBJEXT): internal/intern/select.h
+enc/gb18030.$(OBJEXT): internal/intern/select/largesize.h
+enc/gb18030.$(OBJEXT): internal/intern/signal.h
+enc/gb18030.$(OBJEXT): internal/intern/sprintf.h
+enc/gb18030.$(OBJEXT): internal/intern/string.h
+enc/gb18030.$(OBJEXT): internal/intern/struct.h
+enc/gb18030.$(OBJEXT): internal/intern/thread.h
+enc/gb18030.$(OBJEXT): internal/intern/time.h
+enc/gb18030.$(OBJEXT): internal/intern/variable.h
+enc/gb18030.$(OBJEXT): internal/intern/vm.h
+enc/gb18030.$(OBJEXT): internal/interpreter.h
+enc/gb18030.$(OBJEXT): internal/iterator.h
+enc/gb18030.$(OBJEXT): internal/memory.h
+enc/gb18030.$(OBJEXT): internal/method.h
+enc/gb18030.$(OBJEXT): internal/module.h
+enc/gb18030.$(OBJEXT): internal/newobj.h
+enc/gb18030.$(OBJEXT): internal/rgengc.h
+enc/gb18030.$(OBJEXT): internal/scan_args.h
+enc/gb18030.$(OBJEXT): internal/special_consts.h
+enc/gb18030.$(OBJEXT): internal/static_assert.h
enc/gb18030.$(OBJEXT): internal/stdalign.h
enc/gb18030.$(OBJEXT): internal/stdbool.h
+enc/gb18030.$(OBJEXT): internal/symbol.h
+enc/gb18030.$(OBJEXT): internal/value.h
+enc/gb18030.$(OBJEXT): internal/value_type.h
+enc/gb18030.$(OBJEXT): internal/variable.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/gb18030.$(OBJEXT): st.h
+enc/gb18030.$(OBJEXT): subst.h
+enc/gb2312.$(OBJEXT): $(hdrdir)/ruby.h
+enc/gb2312.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/gb2312.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/gb2312.$(OBJEXT): assert.h
+enc/gb2312.$(OBJEXT): backward.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/inttypes.h
+enc/gb2312.$(OBJEXT): backward/2/limits.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): intern.h
+enc/gb2312.$(OBJEXT): internal/abi.h
+enc/gb2312.$(OBJEXT): internal/anyargs.h
+enc/gb2312.$(OBJEXT): internal/arithmetic.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/char.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/double.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/int.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/long.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/long_long.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/off_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/short.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/size_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/gb2312.$(OBJEXT): internal/arithmetic/uid_t.h
enc/gb2312.$(OBJEXT): internal/assume.h
enc/gb2312.$(OBJEXT): internal/attr/alloc_size.h
+enc/gb2312.$(OBJEXT): internal/attr/artificial.h
enc/gb2312.$(OBJEXT): internal/attr/cold.h
enc/gb2312.$(OBJEXT): internal/attr/const.h
+enc/gb2312.$(OBJEXT): internal/attr/constexpr.h
enc/gb2312.$(OBJEXT): internal/attr/deprecated.h
+enc/gb2312.$(OBJEXT): internal/attr/diagnose_if.h
+enc/gb2312.$(OBJEXT): internal/attr/enum_extensibility.h
enc/gb2312.$(OBJEXT): internal/attr/error.h
+enc/gb2312.$(OBJEXT): internal/attr/flag_enum.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/noalias.h
enc/gb2312.$(OBJEXT): internal/attr/nodiscard.h
enc/gb2312.$(OBJEXT): internal/attr/noexcept.h
enc/gb2312.$(OBJEXT): internal/attr/noinline.h
@@ -1081,6 +1883,7 @@ 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/attr/weakref.h
enc/gb2312.$(OBJEXT): internal/cast.h
enc/gb2312.$(OBJEXT): internal/compiler_is.h
enc/gb2312.$(OBJEXT): internal/compiler_is/apple.h
@@ -1091,8 +1894,30 @@ 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/constant_p.h
+enc/gb2312.$(OBJEXT): internal/core.h
+enc/gb2312.$(OBJEXT): internal/core/rarray.h
+enc/gb2312.$(OBJEXT): internal/core/rbasic.h
+enc/gb2312.$(OBJEXT): internal/core/rbignum.h
+enc/gb2312.$(OBJEXT): internal/core/rclass.h
+enc/gb2312.$(OBJEXT): internal/core/rdata.h
+enc/gb2312.$(OBJEXT): internal/core/rfile.h
+enc/gb2312.$(OBJEXT): internal/core/rhash.h
+enc/gb2312.$(OBJEXT): internal/core/robject.h
+enc/gb2312.$(OBJEXT): internal/core/rregexp.h
+enc/gb2312.$(OBJEXT): internal/core/rstring.h
+enc/gb2312.$(OBJEXT): internal/core/rstruct.h
+enc/gb2312.$(OBJEXT): internal/core/rtypeddata.h
+enc/gb2312.$(OBJEXT): internal/ctype.h
enc/gb2312.$(OBJEXT): internal/dllexport.h
enc/gb2312.$(OBJEXT): internal/dosish.h
+enc/gb2312.$(OBJEXT): internal/error.h
+enc/gb2312.$(OBJEXT): internal/eval.h
+enc/gb2312.$(OBJEXT): internal/event.h
+enc/gb2312.$(OBJEXT): internal/fl_type.h
+enc/gb2312.$(OBJEXT): internal/gc.h
+enc/gb2312.$(OBJEXT): internal/glob.h
+enc/gb2312.$(OBJEXT): internal/globals.h
enc/gb2312.$(OBJEXT): internal/has/attribute.h
enc/gb2312.$(OBJEXT): internal/has/builtin.h
enc/gb2312.$(OBJEXT): internal/has/c_attribute.h
@@ -1101,33 +1926,115 @@ 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/intern/array.h
+enc/gb2312.$(OBJEXT): internal/intern/bignum.h
+enc/gb2312.$(OBJEXT): internal/intern/class.h
+enc/gb2312.$(OBJEXT): internal/intern/compar.h
+enc/gb2312.$(OBJEXT): internal/intern/complex.h
+enc/gb2312.$(OBJEXT): internal/intern/cont.h
+enc/gb2312.$(OBJEXT): internal/intern/dir.h
+enc/gb2312.$(OBJEXT): internal/intern/enum.h
+enc/gb2312.$(OBJEXT): internal/intern/enumerator.h
+enc/gb2312.$(OBJEXT): internal/intern/error.h
+enc/gb2312.$(OBJEXT): internal/intern/eval.h
+enc/gb2312.$(OBJEXT): internal/intern/file.h
+enc/gb2312.$(OBJEXT): internal/intern/gc.h
+enc/gb2312.$(OBJEXT): internal/intern/hash.h
+enc/gb2312.$(OBJEXT): internal/intern/io.h
+enc/gb2312.$(OBJEXT): internal/intern/load.h
+enc/gb2312.$(OBJEXT): internal/intern/marshal.h
+enc/gb2312.$(OBJEXT): internal/intern/numeric.h
+enc/gb2312.$(OBJEXT): internal/intern/object.h
+enc/gb2312.$(OBJEXT): internal/intern/parse.h
+enc/gb2312.$(OBJEXT): internal/intern/proc.h
+enc/gb2312.$(OBJEXT): internal/intern/process.h
+enc/gb2312.$(OBJEXT): internal/intern/random.h
+enc/gb2312.$(OBJEXT): internal/intern/range.h
+enc/gb2312.$(OBJEXT): internal/intern/rational.h
+enc/gb2312.$(OBJEXT): internal/intern/re.h
+enc/gb2312.$(OBJEXT): internal/intern/ruby.h
+enc/gb2312.$(OBJEXT): internal/intern/select.h
+enc/gb2312.$(OBJEXT): internal/intern/select/largesize.h
+enc/gb2312.$(OBJEXT): internal/intern/signal.h
+enc/gb2312.$(OBJEXT): internal/intern/sprintf.h
+enc/gb2312.$(OBJEXT): internal/intern/string.h
+enc/gb2312.$(OBJEXT): internal/intern/struct.h
+enc/gb2312.$(OBJEXT): internal/intern/thread.h
+enc/gb2312.$(OBJEXT): internal/intern/time.h
+enc/gb2312.$(OBJEXT): internal/intern/variable.h
+enc/gb2312.$(OBJEXT): internal/intern/vm.h
+enc/gb2312.$(OBJEXT): internal/interpreter.h
+enc/gb2312.$(OBJEXT): internal/iterator.h
+enc/gb2312.$(OBJEXT): internal/memory.h
+enc/gb2312.$(OBJEXT): internal/method.h
+enc/gb2312.$(OBJEXT): internal/module.h
+enc/gb2312.$(OBJEXT): internal/newobj.h
+enc/gb2312.$(OBJEXT): internal/rgengc.h
+enc/gb2312.$(OBJEXT): internal/scan_args.h
+enc/gb2312.$(OBJEXT): internal/special_consts.h
+enc/gb2312.$(OBJEXT): internal/static_assert.h
enc/gb2312.$(OBJEXT): internal/stdalign.h
enc/gb2312.$(OBJEXT): internal/stdbool.h
+enc/gb2312.$(OBJEXT): internal/symbol.h
+enc/gb2312.$(OBJEXT): internal/value.h
+enc/gb2312.$(OBJEXT): internal/value_type.h
+enc/gb2312.$(OBJEXT): internal/variable.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/gb2312.$(OBJEXT): st.h
+enc/gb2312.$(OBJEXT): subst.h
+enc/gbk.$(OBJEXT): $(hdrdir)/ruby.h
+enc/gbk.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/gbk.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/gbk.$(OBJEXT): assert.h
+enc/gbk.$(OBJEXT): backward.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/inttypes.h
+enc/gbk.$(OBJEXT): backward/2/limits.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): intern.h
+enc/gbk.$(OBJEXT): internal/abi.h
+enc/gbk.$(OBJEXT): internal/anyargs.h
+enc/gbk.$(OBJEXT): internal/arithmetic.h
+enc/gbk.$(OBJEXT): internal/arithmetic/char.h
+enc/gbk.$(OBJEXT): internal/arithmetic/double.h
+enc/gbk.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/gbk.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/int.h
+enc/gbk.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/long.h
+enc/gbk.$(OBJEXT): internal/arithmetic/long_long.h
+enc/gbk.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/off_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/short.h
+enc/gbk.$(OBJEXT): internal/arithmetic/size_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/gbk.$(OBJEXT): internal/arithmetic/uid_t.h
enc/gbk.$(OBJEXT): internal/assume.h
enc/gbk.$(OBJEXT): internal/attr/alloc_size.h
+enc/gbk.$(OBJEXT): internal/attr/artificial.h
enc/gbk.$(OBJEXT): internal/attr/cold.h
enc/gbk.$(OBJEXT): internal/attr/const.h
+enc/gbk.$(OBJEXT): internal/attr/constexpr.h
enc/gbk.$(OBJEXT): internal/attr/deprecated.h
+enc/gbk.$(OBJEXT): internal/attr/diagnose_if.h
+enc/gbk.$(OBJEXT): internal/attr/enum_extensibility.h
enc/gbk.$(OBJEXT): internal/attr/error.h
+enc/gbk.$(OBJEXT): internal/attr/flag_enum.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/noalias.h
enc/gbk.$(OBJEXT): internal/attr/nodiscard.h
enc/gbk.$(OBJEXT): internal/attr/noexcept.h
enc/gbk.$(OBJEXT): internal/attr/noinline.h
@@ -1137,6 +2044,7 @@ 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/attr/weakref.h
enc/gbk.$(OBJEXT): internal/cast.h
enc/gbk.$(OBJEXT): internal/compiler_is.h
enc/gbk.$(OBJEXT): internal/compiler_is/apple.h
@@ -1147,8 +2055,30 @@ 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/constant_p.h
+enc/gbk.$(OBJEXT): internal/core.h
+enc/gbk.$(OBJEXT): internal/core/rarray.h
+enc/gbk.$(OBJEXT): internal/core/rbasic.h
+enc/gbk.$(OBJEXT): internal/core/rbignum.h
+enc/gbk.$(OBJEXT): internal/core/rclass.h
+enc/gbk.$(OBJEXT): internal/core/rdata.h
+enc/gbk.$(OBJEXT): internal/core/rfile.h
+enc/gbk.$(OBJEXT): internal/core/rhash.h
+enc/gbk.$(OBJEXT): internal/core/robject.h
+enc/gbk.$(OBJEXT): internal/core/rregexp.h
+enc/gbk.$(OBJEXT): internal/core/rstring.h
+enc/gbk.$(OBJEXT): internal/core/rstruct.h
+enc/gbk.$(OBJEXT): internal/core/rtypeddata.h
+enc/gbk.$(OBJEXT): internal/ctype.h
enc/gbk.$(OBJEXT): internal/dllexport.h
enc/gbk.$(OBJEXT): internal/dosish.h
+enc/gbk.$(OBJEXT): internal/error.h
+enc/gbk.$(OBJEXT): internal/eval.h
+enc/gbk.$(OBJEXT): internal/event.h
+enc/gbk.$(OBJEXT): internal/fl_type.h
+enc/gbk.$(OBJEXT): internal/gc.h
+enc/gbk.$(OBJEXT): internal/glob.h
+enc/gbk.$(OBJEXT): internal/globals.h
enc/gbk.$(OBJEXT): internal/has/attribute.h
enc/gbk.$(OBJEXT): internal/has/builtin.h
enc/gbk.$(OBJEXT): internal/has/c_attribute.h
@@ -1157,33 +2087,116 @@ 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/intern/array.h
+enc/gbk.$(OBJEXT): internal/intern/bignum.h
+enc/gbk.$(OBJEXT): internal/intern/class.h
+enc/gbk.$(OBJEXT): internal/intern/compar.h
+enc/gbk.$(OBJEXT): internal/intern/complex.h
+enc/gbk.$(OBJEXT): internal/intern/cont.h
+enc/gbk.$(OBJEXT): internal/intern/dir.h
+enc/gbk.$(OBJEXT): internal/intern/enum.h
+enc/gbk.$(OBJEXT): internal/intern/enumerator.h
+enc/gbk.$(OBJEXT): internal/intern/error.h
+enc/gbk.$(OBJEXT): internal/intern/eval.h
+enc/gbk.$(OBJEXT): internal/intern/file.h
+enc/gbk.$(OBJEXT): internal/intern/gc.h
+enc/gbk.$(OBJEXT): internal/intern/hash.h
+enc/gbk.$(OBJEXT): internal/intern/io.h
+enc/gbk.$(OBJEXT): internal/intern/load.h
+enc/gbk.$(OBJEXT): internal/intern/marshal.h
+enc/gbk.$(OBJEXT): internal/intern/numeric.h
+enc/gbk.$(OBJEXT): internal/intern/object.h
+enc/gbk.$(OBJEXT): internal/intern/parse.h
+enc/gbk.$(OBJEXT): internal/intern/proc.h
+enc/gbk.$(OBJEXT): internal/intern/process.h
+enc/gbk.$(OBJEXT): internal/intern/random.h
+enc/gbk.$(OBJEXT): internal/intern/range.h
+enc/gbk.$(OBJEXT): internal/intern/rational.h
+enc/gbk.$(OBJEXT): internal/intern/re.h
+enc/gbk.$(OBJEXT): internal/intern/ruby.h
+enc/gbk.$(OBJEXT): internal/intern/select.h
+enc/gbk.$(OBJEXT): internal/intern/select/largesize.h
+enc/gbk.$(OBJEXT): internal/intern/signal.h
+enc/gbk.$(OBJEXT): internal/intern/sprintf.h
+enc/gbk.$(OBJEXT): internal/intern/string.h
+enc/gbk.$(OBJEXT): internal/intern/struct.h
+enc/gbk.$(OBJEXT): internal/intern/thread.h
+enc/gbk.$(OBJEXT): internal/intern/time.h
+enc/gbk.$(OBJEXT): internal/intern/variable.h
+enc/gbk.$(OBJEXT): internal/intern/vm.h
+enc/gbk.$(OBJEXT): internal/interpreter.h
+enc/gbk.$(OBJEXT): internal/iterator.h
+enc/gbk.$(OBJEXT): internal/memory.h
+enc/gbk.$(OBJEXT): internal/method.h
+enc/gbk.$(OBJEXT): internal/module.h
+enc/gbk.$(OBJEXT): internal/newobj.h
+enc/gbk.$(OBJEXT): internal/rgengc.h
+enc/gbk.$(OBJEXT): internal/scan_args.h
+enc/gbk.$(OBJEXT): internal/special_consts.h
+enc/gbk.$(OBJEXT): internal/static_assert.h
enc/gbk.$(OBJEXT): internal/stdalign.h
enc/gbk.$(OBJEXT): internal/stdbool.h
+enc/gbk.$(OBJEXT): internal/symbol.h
+enc/gbk.$(OBJEXT): internal/value.h
+enc/gbk.$(OBJEXT): internal/value_type.h
+enc/gbk.$(OBJEXT): internal/variable.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/gbk.$(OBJEXT): st.h
+enc/gbk.$(OBJEXT): subst.h
+enc/iso_8859_1.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_1.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_1.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_1.$(OBJEXT): assert.h
+enc/iso_8859_1.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_1.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_1.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_1.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_1.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_1.$(OBJEXT): config.h
+enc/iso_8859_1.$(OBJEXT): defines.h
+enc/iso_8859_1.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_1.$(OBJEXT): enc/iso_8859_1.c
+enc/iso_8859_1.$(OBJEXT): intern.h
+enc/iso_8859_1.$(OBJEXT): internal/abi.h
+enc/iso_8859_1.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_1.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_1.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_1.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1193,6 +2206,7 @@ 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/attr/weakref.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
@@ -1203,8 +2217,30 @@ 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/constant_p.h
+enc/iso_8859_1.$(OBJEXT): internal/core.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_1.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_1.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_1.$(OBJEXT): internal/ctype.h
enc/iso_8859_1.$(OBJEXT): internal/dllexport.h
enc/iso_8859_1.$(OBJEXT): internal/dosish.h
+enc/iso_8859_1.$(OBJEXT): internal/error.h
+enc/iso_8859_1.$(OBJEXT): internal/eval.h
+enc/iso_8859_1.$(OBJEXT): internal/event.h
+enc/iso_8859_1.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_1.$(OBJEXT): internal/gc.h
+enc/iso_8859_1.$(OBJEXT): internal/glob.h
+enc/iso_8859_1.$(OBJEXT): internal/globals.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
@@ -1213,34 +2249,116 @@ 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/intern/array.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_1.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_1.$(OBJEXT): internal/iterator.h
+enc/iso_8859_1.$(OBJEXT): internal/memory.h
+enc/iso_8859_1.$(OBJEXT): internal/method.h
+enc/iso_8859_1.$(OBJEXT): internal/module.h
+enc/iso_8859_1.$(OBJEXT): internal/newobj.h
+enc/iso_8859_1.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_1.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_1.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_1.$(OBJEXT): internal/static_assert.h
enc/iso_8859_1.$(OBJEXT): internal/stdalign.h
enc/iso_8859_1.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_1.$(OBJEXT): internal/symbol.h
+enc/iso_8859_1.$(OBJEXT): internal/value.h
+enc/iso_8859_1.$(OBJEXT): internal/value_type.h
+enc/iso_8859_1.$(OBJEXT): internal/variable.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
-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_1.$(OBJEXT): st.h
+enc/iso_8859_1.$(OBJEXT): subst.h
+enc/iso_8859_10.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_10.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_10.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_10.$(OBJEXT): assert.h
+enc/iso_8859_10.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_10.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_10.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_10.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_10.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_10.$(OBJEXT): config.h
+enc/iso_8859_10.$(OBJEXT): defines.h
+enc/iso_8859_10.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_10.$(OBJEXT): enc/iso_8859_10.c
+enc/iso_8859_10.$(OBJEXT): intern.h
+enc/iso_8859_10.$(OBJEXT): internal/abi.h
+enc/iso_8859_10.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_10.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_10.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_10.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1250,6 +2368,7 @@ 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/attr/weakref.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
@@ -1260,8 +2379,30 @@ 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/constant_p.h
+enc/iso_8859_10.$(OBJEXT): internal/core.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_10.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_10.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_10.$(OBJEXT): internal/ctype.h
enc/iso_8859_10.$(OBJEXT): internal/dllexport.h
enc/iso_8859_10.$(OBJEXT): internal/dosish.h
+enc/iso_8859_10.$(OBJEXT): internal/error.h
+enc/iso_8859_10.$(OBJEXT): internal/eval.h
+enc/iso_8859_10.$(OBJEXT): internal/event.h
+enc/iso_8859_10.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_10.$(OBJEXT): internal/gc.h
+enc/iso_8859_10.$(OBJEXT): internal/glob.h
+enc/iso_8859_10.$(OBJEXT): internal/globals.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
@@ -1270,34 +2411,115 @@ 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/intern/array.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_10.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_10.$(OBJEXT): internal/iterator.h
+enc/iso_8859_10.$(OBJEXT): internal/memory.h
+enc/iso_8859_10.$(OBJEXT): internal/method.h
+enc/iso_8859_10.$(OBJEXT): internal/module.h
+enc/iso_8859_10.$(OBJEXT): internal/newobj.h
+enc/iso_8859_10.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_10.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_10.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_10.$(OBJEXT): internal/static_assert.h
enc/iso_8859_10.$(OBJEXT): internal/stdalign.h
enc/iso_8859_10.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_10.$(OBJEXT): internal/symbol.h
+enc/iso_8859_10.$(OBJEXT): internal/value.h
+enc/iso_8859_10.$(OBJEXT): internal/value_type.h
+enc/iso_8859_10.$(OBJEXT): internal/variable.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
-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_10.$(OBJEXT): st.h
+enc/iso_8859_10.$(OBJEXT): subst.h
+enc/iso_8859_11.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_11.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_11.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_11.$(OBJEXT): assert.h
+enc/iso_8859_11.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_11.$(OBJEXT): backward/2/limits.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): intern.h
+enc/iso_8859_11.$(OBJEXT): internal/abi.h
+enc/iso_8859_11.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_11.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_11.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_11.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1307,6 +2529,7 @@ 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/attr/weakref.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
@@ -1317,8 +2540,30 @@ 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/constant_p.h
+enc/iso_8859_11.$(OBJEXT): internal/core.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_11.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_11.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_11.$(OBJEXT): internal/ctype.h
enc/iso_8859_11.$(OBJEXT): internal/dllexport.h
enc/iso_8859_11.$(OBJEXT): internal/dosish.h
+enc/iso_8859_11.$(OBJEXT): internal/error.h
+enc/iso_8859_11.$(OBJEXT): internal/eval.h
+enc/iso_8859_11.$(OBJEXT): internal/event.h
+enc/iso_8859_11.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_11.$(OBJEXT): internal/gc.h
+enc/iso_8859_11.$(OBJEXT): internal/glob.h
+enc/iso_8859_11.$(OBJEXT): internal/globals.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
@@ -1327,33 +2572,116 @@ 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/intern/array.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_11.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_11.$(OBJEXT): internal/iterator.h
+enc/iso_8859_11.$(OBJEXT): internal/memory.h
+enc/iso_8859_11.$(OBJEXT): internal/method.h
+enc/iso_8859_11.$(OBJEXT): internal/module.h
+enc/iso_8859_11.$(OBJEXT): internal/newobj.h
+enc/iso_8859_11.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_11.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_11.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_11.$(OBJEXT): internal/static_assert.h
enc/iso_8859_11.$(OBJEXT): internal/stdalign.h
enc/iso_8859_11.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_11.$(OBJEXT): internal/symbol.h
+enc/iso_8859_11.$(OBJEXT): internal/value.h
+enc/iso_8859_11.$(OBJEXT): internal/value_type.h
+enc/iso_8859_11.$(OBJEXT): internal/variable.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_11.$(OBJEXT): st.h
+enc/iso_8859_11.$(OBJEXT): subst.h
+enc/iso_8859_13.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_13.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_13.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_13.$(OBJEXT): assert.h
+enc/iso_8859_13.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_13.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_13.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_13.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_13.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_13.$(OBJEXT): config.h
+enc/iso_8859_13.$(OBJEXT): defines.h
+enc/iso_8859_13.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_13.$(OBJEXT): enc/iso_8859_13.c
+enc/iso_8859_13.$(OBJEXT): intern.h
+enc/iso_8859_13.$(OBJEXT): internal/abi.h
+enc/iso_8859_13.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_13.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_13.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_13.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1363,6 +2691,7 @@ 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/attr/weakref.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
@@ -1373,8 +2702,30 @@ 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/constant_p.h
+enc/iso_8859_13.$(OBJEXT): internal/core.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_13.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_13.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_13.$(OBJEXT): internal/ctype.h
enc/iso_8859_13.$(OBJEXT): internal/dllexport.h
enc/iso_8859_13.$(OBJEXT): internal/dosish.h
+enc/iso_8859_13.$(OBJEXT): internal/error.h
+enc/iso_8859_13.$(OBJEXT): internal/eval.h
+enc/iso_8859_13.$(OBJEXT): internal/event.h
+enc/iso_8859_13.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_13.$(OBJEXT): internal/gc.h
+enc/iso_8859_13.$(OBJEXT): internal/glob.h
+enc/iso_8859_13.$(OBJEXT): internal/globals.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
@@ -1383,34 +2734,116 @@ 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/intern/array.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_13.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_13.$(OBJEXT): internal/iterator.h
+enc/iso_8859_13.$(OBJEXT): internal/memory.h
+enc/iso_8859_13.$(OBJEXT): internal/method.h
+enc/iso_8859_13.$(OBJEXT): internal/module.h
+enc/iso_8859_13.$(OBJEXT): internal/newobj.h
+enc/iso_8859_13.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_13.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_13.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_13.$(OBJEXT): internal/static_assert.h
enc/iso_8859_13.$(OBJEXT): internal/stdalign.h
enc/iso_8859_13.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_13.$(OBJEXT): internal/symbol.h
+enc/iso_8859_13.$(OBJEXT): internal/value.h
+enc/iso_8859_13.$(OBJEXT): internal/value_type.h
+enc/iso_8859_13.$(OBJEXT): internal/variable.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
-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_13.$(OBJEXT): st.h
+enc/iso_8859_13.$(OBJEXT): subst.h
+enc/iso_8859_14.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_14.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_14.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_14.$(OBJEXT): assert.h
+enc/iso_8859_14.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_14.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_14.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_14.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_14.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_14.$(OBJEXT): config.h
+enc/iso_8859_14.$(OBJEXT): defines.h
+enc/iso_8859_14.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_14.$(OBJEXT): enc/iso_8859_14.c
+enc/iso_8859_14.$(OBJEXT): intern.h
+enc/iso_8859_14.$(OBJEXT): internal/abi.h
+enc/iso_8859_14.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_14.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_14.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_14.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1420,6 +2853,7 @@ 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/attr/weakref.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
@@ -1430,8 +2864,30 @@ 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/constant_p.h
+enc/iso_8859_14.$(OBJEXT): internal/core.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_14.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_14.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_14.$(OBJEXT): internal/ctype.h
enc/iso_8859_14.$(OBJEXT): internal/dllexport.h
enc/iso_8859_14.$(OBJEXT): internal/dosish.h
+enc/iso_8859_14.$(OBJEXT): internal/error.h
+enc/iso_8859_14.$(OBJEXT): internal/eval.h
+enc/iso_8859_14.$(OBJEXT): internal/event.h
+enc/iso_8859_14.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_14.$(OBJEXT): internal/gc.h
+enc/iso_8859_14.$(OBJEXT): internal/glob.h
+enc/iso_8859_14.$(OBJEXT): internal/globals.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
@@ -1440,34 +2896,116 @@ 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/intern/array.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_14.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_14.$(OBJEXT): internal/iterator.h
+enc/iso_8859_14.$(OBJEXT): internal/memory.h
+enc/iso_8859_14.$(OBJEXT): internal/method.h
+enc/iso_8859_14.$(OBJEXT): internal/module.h
+enc/iso_8859_14.$(OBJEXT): internal/newobj.h
+enc/iso_8859_14.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_14.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_14.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_14.$(OBJEXT): internal/static_assert.h
enc/iso_8859_14.$(OBJEXT): internal/stdalign.h
enc/iso_8859_14.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_14.$(OBJEXT): internal/symbol.h
+enc/iso_8859_14.$(OBJEXT): internal/value.h
+enc/iso_8859_14.$(OBJEXT): internal/value_type.h
+enc/iso_8859_14.$(OBJEXT): internal/variable.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
-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_14.$(OBJEXT): st.h
+enc/iso_8859_14.$(OBJEXT): subst.h
+enc/iso_8859_15.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_15.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_15.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_15.$(OBJEXT): assert.h
+enc/iso_8859_15.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_15.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_15.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_15.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_15.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_15.$(OBJEXT): config.h
+enc/iso_8859_15.$(OBJEXT): defines.h
+enc/iso_8859_15.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_15.$(OBJEXT): enc/iso_8859_15.c
+enc/iso_8859_15.$(OBJEXT): intern.h
+enc/iso_8859_15.$(OBJEXT): internal/abi.h
+enc/iso_8859_15.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_15.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_15.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_15.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1477,6 +3015,7 @@ 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/attr/weakref.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
@@ -1487,8 +3026,30 @@ 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/constant_p.h
+enc/iso_8859_15.$(OBJEXT): internal/core.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_15.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_15.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_15.$(OBJEXT): internal/ctype.h
enc/iso_8859_15.$(OBJEXT): internal/dllexport.h
enc/iso_8859_15.$(OBJEXT): internal/dosish.h
+enc/iso_8859_15.$(OBJEXT): internal/error.h
+enc/iso_8859_15.$(OBJEXT): internal/eval.h
+enc/iso_8859_15.$(OBJEXT): internal/event.h
+enc/iso_8859_15.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_15.$(OBJEXT): internal/gc.h
+enc/iso_8859_15.$(OBJEXT): internal/glob.h
+enc/iso_8859_15.$(OBJEXT): internal/globals.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
@@ -1497,34 +3058,116 @@ 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/intern/array.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_15.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_15.$(OBJEXT): internal/iterator.h
+enc/iso_8859_15.$(OBJEXT): internal/memory.h
+enc/iso_8859_15.$(OBJEXT): internal/method.h
+enc/iso_8859_15.$(OBJEXT): internal/module.h
+enc/iso_8859_15.$(OBJEXT): internal/newobj.h
+enc/iso_8859_15.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_15.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_15.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_15.$(OBJEXT): internal/static_assert.h
enc/iso_8859_15.$(OBJEXT): internal/stdalign.h
enc/iso_8859_15.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_15.$(OBJEXT): internal/symbol.h
+enc/iso_8859_15.$(OBJEXT): internal/value.h
+enc/iso_8859_15.$(OBJEXT): internal/value_type.h
+enc/iso_8859_15.$(OBJEXT): internal/variable.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
-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_15.$(OBJEXT): st.h
+enc/iso_8859_15.$(OBJEXT): subst.h
+enc/iso_8859_16.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_16.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_16.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_16.$(OBJEXT): assert.h
+enc/iso_8859_16.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_16.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_16.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_16.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_16.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_16.$(OBJEXT): config.h
+enc/iso_8859_16.$(OBJEXT): defines.h
+enc/iso_8859_16.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_16.$(OBJEXT): enc/iso_8859_16.c
+enc/iso_8859_16.$(OBJEXT): intern.h
+enc/iso_8859_16.$(OBJEXT): internal/abi.h
+enc/iso_8859_16.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_16.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_16.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_16.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1534,6 +3177,7 @@ 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/attr/weakref.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
@@ -1544,8 +3188,30 @@ 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/constant_p.h
+enc/iso_8859_16.$(OBJEXT): internal/core.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_16.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_16.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_16.$(OBJEXT): internal/ctype.h
enc/iso_8859_16.$(OBJEXT): internal/dllexport.h
enc/iso_8859_16.$(OBJEXT): internal/dosish.h
+enc/iso_8859_16.$(OBJEXT): internal/error.h
+enc/iso_8859_16.$(OBJEXT): internal/eval.h
+enc/iso_8859_16.$(OBJEXT): internal/event.h
+enc/iso_8859_16.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_16.$(OBJEXT): internal/gc.h
+enc/iso_8859_16.$(OBJEXT): internal/glob.h
+enc/iso_8859_16.$(OBJEXT): internal/globals.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
@@ -1554,34 +3220,116 @@ 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/intern/array.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_16.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_16.$(OBJEXT): internal/iterator.h
+enc/iso_8859_16.$(OBJEXT): internal/memory.h
+enc/iso_8859_16.$(OBJEXT): internal/method.h
+enc/iso_8859_16.$(OBJEXT): internal/module.h
+enc/iso_8859_16.$(OBJEXT): internal/newobj.h
+enc/iso_8859_16.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_16.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_16.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_16.$(OBJEXT): internal/static_assert.h
enc/iso_8859_16.$(OBJEXT): internal/stdalign.h
enc/iso_8859_16.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_16.$(OBJEXT): internal/symbol.h
+enc/iso_8859_16.$(OBJEXT): internal/value.h
+enc/iso_8859_16.$(OBJEXT): internal/value_type.h
+enc/iso_8859_16.$(OBJEXT): internal/variable.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
-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_16.$(OBJEXT): st.h
+enc/iso_8859_16.$(OBJEXT): subst.h
+enc/iso_8859_2.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_2.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_2.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_2.$(OBJEXT): assert.h
+enc/iso_8859_2.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_2.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_2.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_2.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_2.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_2.$(OBJEXT): config.h
+enc/iso_8859_2.$(OBJEXT): defines.h
+enc/iso_8859_2.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_2.$(OBJEXT): enc/iso_8859_2.c
+enc/iso_8859_2.$(OBJEXT): intern.h
+enc/iso_8859_2.$(OBJEXT): internal/abi.h
+enc/iso_8859_2.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_2.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_2.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_2.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1591,6 +3339,7 @@ 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/attr/weakref.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
@@ -1601,8 +3350,30 @@ 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/constant_p.h
+enc/iso_8859_2.$(OBJEXT): internal/core.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_2.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_2.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_2.$(OBJEXT): internal/ctype.h
enc/iso_8859_2.$(OBJEXT): internal/dllexport.h
enc/iso_8859_2.$(OBJEXT): internal/dosish.h
+enc/iso_8859_2.$(OBJEXT): internal/error.h
+enc/iso_8859_2.$(OBJEXT): internal/eval.h
+enc/iso_8859_2.$(OBJEXT): internal/event.h
+enc/iso_8859_2.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_2.$(OBJEXT): internal/gc.h
+enc/iso_8859_2.$(OBJEXT): internal/glob.h
+enc/iso_8859_2.$(OBJEXT): internal/globals.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
@@ -1611,34 +3382,116 @@ 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/intern/array.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_2.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_2.$(OBJEXT): internal/iterator.h
+enc/iso_8859_2.$(OBJEXT): internal/memory.h
+enc/iso_8859_2.$(OBJEXT): internal/method.h
+enc/iso_8859_2.$(OBJEXT): internal/module.h
+enc/iso_8859_2.$(OBJEXT): internal/newobj.h
+enc/iso_8859_2.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_2.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_2.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_2.$(OBJEXT): internal/static_assert.h
enc/iso_8859_2.$(OBJEXT): internal/stdalign.h
enc/iso_8859_2.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_2.$(OBJEXT): internal/symbol.h
+enc/iso_8859_2.$(OBJEXT): internal/value.h
+enc/iso_8859_2.$(OBJEXT): internal/value_type.h
+enc/iso_8859_2.$(OBJEXT): internal/variable.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
-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_2.$(OBJEXT): st.h
+enc/iso_8859_2.$(OBJEXT): subst.h
+enc/iso_8859_3.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_3.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_3.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_3.$(OBJEXT): assert.h
+enc/iso_8859_3.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_3.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_3.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_3.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_3.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_3.$(OBJEXT): config.h
+enc/iso_8859_3.$(OBJEXT): defines.h
+enc/iso_8859_3.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_3.$(OBJEXT): enc/iso_8859_3.c
+enc/iso_8859_3.$(OBJEXT): intern.h
+enc/iso_8859_3.$(OBJEXT): internal/abi.h
+enc/iso_8859_3.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_3.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_3.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_3.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1648,6 +3501,7 @@ 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/attr/weakref.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
@@ -1658,8 +3512,30 @@ 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/constant_p.h
+enc/iso_8859_3.$(OBJEXT): internal/core.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_3.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_3.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_3.$(OBJEXT): internal/ctype.h
enc/iso_8859_3.$(OBJEXT): internal/dllexport.h
enc/iso_8859_3.$(OBJEXT): internal/dosish.h
+enc/iso_8859_3.$(OBJEXT): internal/error.h
+enc/iso_8859_3.$(OBJEXT): internal/eval.h
+enc/iso_8859_3.$(OBJEXT): internal/event.h
+enc/iso_8859_3.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_3.$(OBJEXT): internal/gc.h
+enc/iso_8859_3.$(OBJEXT): internal/glob.h
+enc/iso_8859_3.$(OBJEXT): internal/globals.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
@@ -1668,34 +3544,116 @@ 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/intern/array.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_3.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_3.$(OBJEXT): internal/iterator.h
+enc/iso_8859_3.$(OBJEXT): internal/memory.h
+enc/iso_8859_3.$(OBJEXT): internal/method.h
+enc/iso_8859_3.$(OBJEXT): internal/module.h
+enc/iso_8859_3.$(OBJEXT): internal/newobj.h
+enc/iso_8859_3.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_3.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_3.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_3.$(OBJEXT): internal/static_assert.h
enc/iso_8859_3.$(OBJEXT): internal/stdalign.h
enc/iso_8859_3.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_3.$(OBJEXT): internal/symbol.h
+enc/iso_8859_3.$(OBJEXT): internal/value.h
+enc/iso_8859_3.$(OBJEXT): internal/value_type.h
+enc/iso_8859_3.$(OBJEXT): internal/variable.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
-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_3.$(OBJEXT): st.h
+enc/iso_8859_3.$(OBJEXT): subst.h
+enc/iso_8859_4.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_4.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_4.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_4.$(OBJEXT): assert.h
+enc/iso_8859_4.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_4.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_4.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_4.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_4.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_4.$(OBJEXT): config.h
+enc/iso_8859_4.$(OBJEXT): defines.h
+enc/iso_8859_4.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_4.$(OBJEXT): enc/iso_8859_4.c
+enc/iso_8859_4.$(OBJEXT): intern.h
+enc/iso_8859_4.$(OBJEXT): internal/abi.h
+enc/iso_8859_4.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_4.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_4.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_4.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1705,6 +3663,7 @@ 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/attr/weakref.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
@@ -1715,8 +3674,30 @@ 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/constant_p.h
+enc/iso_8859_4.$(OBJEXT): internal/core.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_4.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_4.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_4.$(OBJEXT): internal/ctype.h
enc/iso_8859_4.$(OBJEXT): internal/dllexport.h
enc/iso_8859_4.$(OBJEXT): internal/dosish.h
+enc/iso_8859_4.$(OBJEXT): internal/error.h
+enc/iso_8859_4.$(OBJEXT): internal/eval.h
+enc/iso_8859_4.$(OBJEXT): internal/event.h
+enc/iso_8859_4.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_4.$(OBJEXT): internal/gc.h
+enc/iso_8859_4.$(OBJEXT): internal/glob.h
+enc/iso_8859_4.$(OBJEXT): internal/globals.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
@@ -1725,34 +3706,115 @@ 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/intern/array.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_4.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_4.$(OBJEXT): internal/iterator.h
+enc/iso_8859_4.$(OBJEXT): internal/memory.h
+enc/iso_8859_4.$(OBJEXT): internal/method.h
+enc/iso_8859_4.$(OBJEXT): internal/module.h
+enc/iso_8859_4.$(OBJEXT): internal/newobj.h
+enc/iso_8859_4.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_4.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_4.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_4.$(OBJEXT): internal/static_assert.h
enc/iso_8859_4.$(OBJEXT): internal/stdalign.h
enc/iso_8859_4.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_4.$(OBJEXT): internal/symbol.h
+enc/iso_8859_4.$(OBJEXT): internal/value.h
+enc/iso_8859_4.$(OBJEXT): internal/value_type.h
+enc/iso_8859_4.$(OBJEXT): internal/variable.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
-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_4.$(OBJEXT): st.h
+enc/iso_8859_4.$(OBJEXT): subst.h
+enc/iso_8859_5.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_5.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_5.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_5.$(OBJEXT): assert.h
+enc/iso_8859_5.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_5.$(OBJEXT): backward/2/limits.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): intern.h
+enc/iso_8859_5.$(OBJEXT): internal/abi.h
+enc/iso_8859_5.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_5.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_5.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_5.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1762,6 +3824,7 @@ 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/attr/weakref.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
@@ -1772,8 +3835,30 @@ 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/constant_p.h
+enc/iso_8859_5.$(OBJEXT): internal/core.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_5.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_5.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_5.$(OBJEXT): internal/ctype.h
enc/iso_8859_5.$(OBJEXT): internal/dllexport.h
enc/iso_8859_5.$(OBJEXT): internal/dosish.h
+enc/iso_8859_5.$(OBJEXT): internal/error.h
+enc/iso_8859_5.$(OBJEXT): internal/eval.h
+enc/iso_8859_5.$(OBJEXT): internal/event.h
+enc/iso_8859_5.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_5.$(OBJEXT): internal/gc.h
+enc/iso_8859_5.$(OBJEXT): internal/glob.h
+enc/iso_8859_5.$(OBJEXT): internal/globals.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
@@ -1782,33 +3867,115 @@ 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/intern/array.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_5.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_5.$(OBJEXT): internal/iterator.h
+enc/iso_8859_5.$(OBJEXT): internal/memory.h
+enc/iso_8859_5.$(OBJEXT): internal/method.h
+enc/iso_8859_5.$(OBJEXT): internal/module.h
+enc/iso_8859_5.$(OBJEXT): internal/newobj.h
+enc/iso_8859_5.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_5.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_5.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_5.$(OBJEXT): internal/static_assert.h
enc/iso_8859_5.$(OBJEXT): internal/stdalign.h
enc/iso_8859_5.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_5.$(OBJEXT): internal/symbol.h
+enc/iso_8859_5.$(OBJEXT): internal/value.h
+enc/iso_8859_5.$(OBJEXT): internal/value_type.h
+enc/iso_8859_5.$(OBJEXT): internal/variable.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_5.$(OBJEXT): st.h
+enc/iso_8859_5.$(OBJEXT): subst.h
+enc/iso_8859_6.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_6.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_6.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_6.$(OBJEXT): assert.h
+enc/iso_8859_6.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_6.$(OBJEXT): backward/2/limits.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): intern.h
+enc/iso_8859_6.$(OBJEXT): internal/abi.h
+enc/iso_8859_6.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_6.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_6.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_6.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1818,6 +3985,7 @@ 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/attr/weakref.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
@@ -1828,8 +3996,30 @@ 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/constant_p.h
+enc/iso_8859_6.$(OBJEXT): internal/core.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_6.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_6.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_6.$(OBJEXT): internal/ctype.h
enc/iso_8859_6.$(OBJEXT): internal/dllexport.h
enc/iso_8859_6.$(OBJEXT): internal/dosish.h
+enc/iso_8859_6.$(OBJEXT): internal/error.h
+enc/iso_8859_6.$(OBJEXT): internal/eval.h
+enc/iso_8859_6.$(OBJEXT): internal/event.h
+enc/iso_8859_6.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_6.$(OBJEXT): internal/gc.h
+enc/iso_8859_6.$(OBJEXT): internal/glob.h
+enc/iso_8859_6.$(OBJEXT): internal/globals.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
@@ -1838,33 +4028,115 @@ 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/intern/array.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_6.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_6.$(OBJEXT): internal/iterator.h
+enc/iso_8859_6.$(OBJEXT): internal/memory.h
+enc/iso_8859_6.$(OBJEXT): internal/method.h
+enc/iso_8859_6.$(OBJEXT): internal/module.h
+enc/iso_8859_6.$(OBJEXT): internal/newobj.h
+enc/iso_8859_6.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_6.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_6.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_6.$(OBJEXT): internal/static_assert.h
enc/iso_8859_6.$(OBJEXT): internal/stdalign.h
enc/iso_8859_6.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_6.$(OBJEXT): internal/symbol.h
+enc/iso_8859_6.$(OBJEXT): internal/value.h
+enc/iso_8859_6.$(OBJEXT): internal/value_type.h
+enc/iso_8859_6.$(OBJEXT): internal/variable.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_6.$(OBJEXT): st.h
+enc/iso_8859_6.$(OBJEXT): subst.h
+enc/iso_8859_7.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_7.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_7.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_7.$(OBJEXT): assert.h
+enc/iso_8859_7.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_7.$(OBJEXT): backward/2/limits.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): intern.h
+enc/iso_8859_7.$(OBJEXT): internal/abi.h
+enc/iso_8859_7.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_7.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_7.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_7.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1874,6 +4146,7 @@ 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/attr/weakref.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
@@ -1884,8 +4157,30 @@ 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/constant_p.h
+enc/iso_8859_7.$(OBJEXT): internal/core.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_7.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_7.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_7.$(OBJEXT): internal/ctype.h
enc/iso_8859_7.$(OBJEXT): internal/dllexport.h
enc/iso_8859_7.$(OBJEXT): internal/dosish.h
+enc/iso_8859_7.$(OBJEXT): internal/error.h
+enc/iso_8859_7.$(OBJEXT): internal/eval.h
+enc/iso_8859_7.$(OBJEXT): internal/event.h
+enc/iso_8859_7.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_7.$(OBJEXT): internal/gc.h
+enc/iso_8859_7.$(OBJEXT): internal/glob.h
+enc/iso_8859_7.$(OBJEXT): internal/globals.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
@@ -1894,33 +4189,115 @@ 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/intern/array.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_7.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_7.$(OBJEXT): internal/iterator.h
+enc/iso_8859_7.$(OBJEXT): internal/memory.h
+enc/iso_8859_7.$(OBJEXT): internal/method.h
+enc/iso_8859_7.$(OBJEXT): internal/module.h
+enc/iso_8859_7.$(OBJEXT): internal/newobj.h
+enc/iso_8859_7.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_7.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_7.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_7.$(OBJEXT): internal/static_assert.h
enc/iso_8859_7.$(OBJEXT): internal/stdalign.h
enc/iso_8859_7.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_7.$(OBJEXT): internal/symbol.h
+enc/iso_8859_7.$(OBJEXT): internal/value.h
+enc/iso_8859_7.$(OBJEXT): internal/value_type.h
+enc/iso_8859_7.$(OBJEXT): internal/variable.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_7.$(OBJEXT): st.h
+enc/iso_8859_7.$(OBJEXT): subst.h
+enc/iso_8859_8.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_8.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_8.$(OBJEXT): assert.h
+enc/iso_8859_8.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_8.$(OBJEXT): backward/2/limits.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): intern.h
+enc/iso_8859_8.$(OBJEXT): internal/abi.h
+enc/iso_8859_8.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_8.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_8.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_8.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1930,6 +4307,7 @@ 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/attr/weakref.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
@@ -1940,8 +4318,30 @@ 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/constant_p.h
+enc/iso_8859_8.$(OBJEXT): internal/core.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_8.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_8.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_8.$(OBJEXT): internal/ctype.h
enc/iso_8859_8.$(OBJEXT): internal/dllexport.h
enc/iso_8859_8.$(OBJEXT): internal/dosish.h
+enc/iso_8859_8.$(OBJEXT): internal/error.h
+enc/iso_8859_8.$(OBJEXT): internal/eval.h
+enc/iso_8859_8.$(OBJEXT): internal/event.h
+enc/iso_8859_8.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_8.$(OBJEXT): internal/gc.h
+enc/iso_8859_8.$(OBJEXT): internal/glob.h
+enc/iso_8859_8.$(OBJEXT): internal/globals.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
@@ -1950,33 +4350,116 @@ 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/intern/array.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_8.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_8.$(OBJEXT): internal/iterator.h
+enc/iso_8859_8.$(OBJEXT): internal/memory.h
+enc/iso_8859_8.$(OBJEXT): internal/method.h
+enc/iso_8859_8.$(OBJEXT): internal/module.h
+enc/iso_8859_8.$(OBJEXT): internal/newobj.h
+enc/iso_8859_8.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_8.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_8.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_8.$(OBJEXT): internal/static_assert.h
enc/iso_8859_8.$(OBJEXT): internal/stdalign.h
enc/iso_8859_8.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_8.$(OBJEXT): internal/symbol.h
+enc/iso_8859_8.$(OBJEXT): internal/value.h
+enc/iso_8859_8.$(OBJEXT): internal/value_type.h
+enc/iso_8859_8.$(OBJEXT): internal/variable.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_8.$(OBJEXT): st.h
+enc/iso_8859_8.$(OBJEXT): subst.h
+enc/iso_8859_9.$(OBJEXT): $(hdrdir)/ruby.h
+enc/iso_8859_9.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/iso_8859_9.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_9.$(OBJEXT): assert.h
+enc/iso_8859_9.$(OBJEXT): backward.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/inttypes.h
+enc/iso_8859_9.$(OBJEXT): backward/2/limits.h
+enc/iso_8859_9.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_9.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_9.$(OBJEXT): backward/2/stdarg.h
+enc/iso_8859_9.$(OBJEXT): config.h
+enc/iso_8859_9.$(OBJEXT): defines.h
+enc/iso_8859_9.$(OBJEXT): enc/iso_8859.h
+enc/iso_8859_9.$(OBJEXT): enc/iso_8859_9.c
+enc/iso_8859_9.$(OBJEXT): intern.h
+enc/iso_8859_9.$(OBJEXT): internal/abi.h
+enc/iso_8859_9.$(OBJEXT): internal/anyargs.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/char.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/double.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/int.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/long.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/long_long.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/off_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/short.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/size_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/iso_8859_9.$(OBJEXT): internal/arithmetic/uid_t.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/artificial.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/constexpr.h
enc/iso_8859_9.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/diagnose_if.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/enum_extensibility.h
enc/iso_8859_9.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -1986,6 +4469,7 @@ 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/attr/weakref.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
@@ -1996,8 +4480,30 @@ 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/constant_p.h
+enc/iso_8859_9.$(OBJEXT): internal/core.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rarray.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rbasic.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rbignum.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rclass.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rdata.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rfile.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rhash.h
+enc/iso_8859_9.$(OBJEXT): internal/core/robject.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rregexp.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rstring.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rstruct.h
+enc/iso_8859_9.$(OBJEXT): internal/core/rtypeddata.h
+enc/iso_8859_9.$(OBJEXT): internal/ctype.h
enc/iso_8859_9.$(OBJEXT): internal/dllexport.h
enc/iso_8859_9.$(OBJEXT): internal/dosish.h
+enc/iso_8859_9.$(OBJEXT): internal/error.h
+enc/iso_8859_9.$(OBJEXT): internal/eval.h
+enc/iso_8859_9.$(OBJEXT): internal/event.h
+enc/iso_8859_9.$(OBJEXT): internal/fl_type.h
+enc/iso_8859_9.$(OBJEXT): internal/gc.h
+enc/iso_8859_9.$(OBJEXT): internal/glob.h
+enc/iso_8859_9.$(OBJEXT): internal/globals.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
@@ -2006,34 +4512,115 @@ 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/intern/array.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/bignum.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/class.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/compar.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/complex.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/cont.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/dir.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/enum.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/enumerator.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/error.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/eval.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/file.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/gc.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/hash.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/io.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/load.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/marshal.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/numeric.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/object.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/parse.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/proc.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/process.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/random.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/range.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/rational.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/re.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/ruby.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/select.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/signal.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/sprintf.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/string.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/struct.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/thread.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/time.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/variable.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/vm.h
+enc/iso_8859_9.$(OBJEXT): internal/interpreter.h
+enc/iso_8859_9.$(OBJEXT): internal/iterator.h
+enc/iso_8859_9.$(OBJEXT): internal/memory.h
+enc/iso_8859_9.$(OBJEXT): internal/method.h
+enc/iso_8859_9.$(OBJEXT): internal/module.h
+enc/iso_8859_9.$(OBJEXT): internal/newobj.h
+enc/iso_8859_9.$(OBJEXT): internal/rgengc.h
+enc/iso_8859_9.$(OBJEXT): internal/scan_args.h
+enc/iso_8859_9.$(OBJEXT): internal/special_consts.h
+enc/iso_8859_9.$(OBJEXT): internal/static_assert.h
enc/iso_8859_9.$(OBJEXT): internal/stdalign.h
enc/iso_8859_9.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_9.$(OBJEXT): internal/symbol.h
+enc/iso_8859_9.$(OBJEXT): internal/value.h
+enc/iso_8859_9.$(OBJEXT): internal/value_type.h
+enc/iso_8859_9.$(OBJEXT): internal/variable.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
-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/iso_8859_9.$(OBJEXT): st.h
+enc/iso_8859_9.$(OBJEXT): subst.h
+enc/koi8_r.$(OBJEXT): $(hdrdir)/ruby.h
+enc/koi8_r.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/koi8_r.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/koi8_r.$(OBJEXT): assert.h
+enc/koi8_r.$(OBJEXT): backward.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/inttypes.h
+enc/koi8_r.$(OBJEXT): backward/2/limits.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): intern.h
+enc/koi8_r.$(OBJEXT): internal/abi.h
+enc/koi8_r.$(OBJEXT): internal/anyargs.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/char.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/double.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/int.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/long.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/long_long.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/off_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/short.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/size_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/koi8_r.$(OBJEXT): internal/arithmetic/uid_t.h
enc/koi8_r.$(OBJEXT): internal/assume.h
enc/koi8_r.$(OBJEXT): internal/attr/alloc_size.h
+enc/koi8_r.$(OBJEXT): internal/attr/artificial.h
enc/koi8_r.$(OBJEXT): internal/attr/cold.h
enc/koi8_r.$(OBJEXT): internal/attr/const.h
+enc/koi8_r.$(OBJEXT): internal/attr/constexpr.h
enc/koi8_r.$(OBJEXT): internal/attr/deprecated.h
+enc/koi8_r.$(OBJEXT): internal/attr/diagnose_if.h
+enc/koi8_r.$(OBJEXT): internal/attr/enum_extensibility.h
enc/koi8_r.$(OBJEXT): internal/attr/error.h
+enc/koi8_r.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -2043,6 +4630,7 @@ 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/attr/weakref.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
@@ -2053,8 +4641,30 @@ 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/constant_p.h
+enc/koi8_r.$(OBJEXT): internal/core.h
+enc/koi8_r.$(OBJEXT): internal/core/rarray.h
+enc/koi8_r.$(OBJEXT): internal/core/rbasic.h
+enc/koi8_r.$(OBJEXT): internal/core/rbignum.h
+enc/koi8_r.$(OBJEXT): internal/core/rclass.h
+enc/koi8_r.$(OBJEXT): internal/core/rdata.h
+enc/koi8_r.$(OBJEXT): internal/core/rfile.h
+enc/koi8_r.$(OBJEXT): internal/core/rhash.h
+enc/koi8_r.$(OBJEXT): internal/core/robject.h
+enc/koi8_r.$(OBJEXT): internal/core/rregexp.h
+enc/koi8_r.$(OBJEXT): internal/core/rstring.h
+enc/koi8_r.$(OBJEXT): internal/core/rstruct.h
+enc/koi8_r.$(OBJEXT): internal/core/rtypeddata.h
+enc/koi8_r.$(OBJEXT): internal/ctype.h
enc/koi8_r.$(OBJEXT): internal/dllexport.h
enc/koi8_r.$(OBJEXT): internal/dosish.h
+enc/koi8_r.$(OBJEXT): internal/error.h
+enc/koi8_r.$(OBJEXT): internal/eval.h
+enc/koi8_r.$(OBJEXT): internal/event.h
+enc/koi8_r.$(OBJEXT): internal/fl_type.h
+enc/koi8_r.$(OBJEXT): internal/gc.h
+enc/koi8_r.$(OBJEXT): internal/glob.h
+enc/koi8_r.$(OBJEXT): internal/globals.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
@@ -2063,33 +4673,115 @@ 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/intern/array.h
+enc/koi8_r.$(OBJEXT): internal/intern/bignum.h
+enc/koi8_r.$(OBJEXT): internal/intern/class.h
+enc/koi8_r.$(OBJEXT): internal/intern/compar.h
+enc/koi8_r.$(OBJEXT): internal/intern/complex.h
+enc/koi8_r.$(OBJEXT): internal/intern/cont.h
+enc/koi8_r.$(OBJEXT): internal/intern/dir.h
+enc/koi8_r.$(OBJEXT): internal/intern/enum.h
+enc/koi8_r.$(OBJEXT): internal/intern/enumerator.h
+enc/koi8_r.$(OBJEXT): internal/intern/error.h
+enc/koi8_r.$(OBJEXT): internal/intern/eval.h
+enc/koi8_r.$(OBJEXT): internal/intern/file.h
+enc/koi8_r.$(OBJEXT): internal/intern/gc.h
+enc/koi8_r.$(OBJEXT): internal/intern/hash.h
+enc/koi8_r.$(OBJEXT): internal/intern/io.h
+enc/koi8_r.$(OBJEXT): internal/intern/load.h
+enc/koi8_r.$(OBJEXT): internal/intern/marshal.h
+enc/koi8_r.$(OBJEXT): internal/intern/numeric.h
+enc/koi8_r.$(OBJEXT): internal/intern/object.h
+enc/koi8_r.$(OBJEXT): internal/intern/parse.h
+enc/koi8_r.$(OBJEXT): internal/intern/proc.h
+enc/koi8_r.$(OBJEXT): internal/intern/process.h
+enc/koi8_r.$(OBJEXT): internal/intern/random.h
+enc/koi8_r.$(OBJEXT): internal/intern/range.h
+enc/koi8_r.$(OBJEXT): internal/intern/rational.h
+enc/koi8_r.$(OBJEXT): internal/intern/re.h
+enc/koi8_r.$(OBJEXT): internal/intern/ruby.h
+enc/koi8_r.$(OBJEXT): internal/intern/select.h
+enc/koi8_r.$(OBJEXT): internal/intern/select/largesize.h
+enc/koi8_r.$(OBJEXT): internal/intern/signal.h
+enc/koi8_r.$(OBJEXT): internal/intern/sprintf.h
+enc/koi8_r.$(OBJEXT): internal/intern/string.h
+enc/koi8_r.$(OBJEXT): internal/intern/struct.h
+enc/koi8_r.$(OBJEXT): internal/intern/thread.h
+enc/koi8_r.$(OBJEXT): internal/intern/time.h
+enc/koi8_r.$(OBJEXT): internal/intern/variable.h
+enc/koi8_r.$(OBJEXT): internal/intern/vm.h
+enc/koi8_r.$(OBJEXT): internal/interpreter.h
+enc/koi8_r.$(OBJEXT): internal/iterator.h
+enc/koi8_r.$(OBJEXT): internal/memory.h
+enc/koi8_r.$(OBJEXT): internal/method.h
+enc/koi8_r.$(OBJEXT): internal/module.h
+enc/koi8_r.$(OBJEXT): internal/newobj.h
+enc/koi8_r.$(OBJEXT): internal/rgengc.h
+enc/koi8_r.$(OBJEXT): internal/scan_args.h
+enc/koi8_r.$(OBJEXT): internal/special_consts.h
+enc/koi8_r.$(OBJEXT): internal/static_assert.h
enc/koi8_r.$(OBJEXT): internal/stdalign.h
enc/koi8_r.$(OBJEXT): internal/stdbool.h
+enc/koi8_r.$(OBJEXT): internal/symbol.h
+enc/koi8_r.$(OBJEXT): internal/value.h
+enc/koi8_r.$(OBJEXT): internal/value_type.h
+enc/koi8_r.$(OBJEXT): internal/variable.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_r.$(OBJEXT): st.h
+enc/koi8_r.$(OBJEXT): subst.h
+enc/koi8_u.$(OBJEXT): $(hdrdir)/ruby.h
+enc/koi8_u.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/koi8_u.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/koi8_u.$(OBJEXT): assert.h
+enc/koi8_u.$(OBJEXT): backward.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/inttypes.h
+enc/koi8_u.$(OBJEXT): backward/2/limits.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): intern.h
+enc/koi8_u.$(OBJEXT): internal/abi.h
+enc/koi8_u.$(OBJEXT): internal/anyargs.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/char.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/double.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/int.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/long.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/long_long.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/off_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/short.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/size_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/koi8_u.$(OBJEXT): internal/arithmetic/uid_t.h
enc/koi8_u.$(OBJEXT): internal/assume.h
enc/koi8_u.$(OBJEXT): internal/attr/alloc_size.h
+enc/koi8_u.$(OBJEXT): internal/attr/artificial.h
enc/koi8_u.$(OBJEXT): internal/attr/cold.h
enc/koi8_u.$(OBJEXT): internal/attr/const.h
+enc/koi8_u.$(OBJEXT): internal/attr/constexpr.h
enc/koi8_u.$(OBJEXT): internal/attr/deprecated.h
+enc/koi8_u.$(OBJEXT): internal/attr/diagnose_if.h
+enc/koi8_u.$(OBJEXT): internal/attr/enum_extensibility.h
enc/koi8_u.$(OBJEXT): internal/attr/error.h
+enc/koi8_u.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -2099,6 +4791,7 @@ 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/attr/weakref.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
@@ -2109,8 +4802,30 @@ 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/constant_p.h
+enc/koi8_u.$(OBJEXT): internal/core.h
+enc/koi8_u.$(OBJEXT): internal/core/rarray.h
+enc/koi8_u.$(OBJEXT): internal/core/rbasic.h
+enc/koi8_u.$(OBJEXT): internal/core/rbignum.h
+enc/koi8_u.$(OBJEXT): internal/core/rclass.h
+enc/koi8_u.$(OBJEXT): internal/core/rdata.h
+enc/koi8_u.$(OBJEXT): internal/core/rfile.h
+enc/koi8_u.$(OBJEXT): internal/core/rhash.h
+enc/koi8_u.$(OBJEXT): internal/core/robject.h
+enc/koi8_u.$(OBJEXT): internal/core/rregexp.h
+enc/koi8_u.$(OBJEXT): internal/core/rstring.h
+enc/koi8_u.$(OBJEXT): internal/core/rstruct.h
+enc/koi8_u.$(OBJEXT): internal/core/rtypeddata.h
+enc/koi8_u.$(OBJEXT): internal/ctype.h
enc/koi8_u.$(OBJEXT): internal/dllexport.h
enc/koi8_u.$(OBJEXT): internal/dosish.h
+enc/koi8_u.$(OBJEXT): internal/error.h
+enc/koi8_u.$(OBJEXT): internal/eval.h
+enc/koi8_u.$(OBJEXT): internal/event.h
+enc/koi8_u.$(OBJEXT): internal/fl_type.h
+enc/koi8_u.$(OBJEXT): internal/gc.h
+enc/koi8_u.$(OBJEXT): internal/glob.h
+enc/koi8_u.$(OBJEXT): internal/globals.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
@@ -2119,33 +4834,118 @@ 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/intern/array.h
+enc/koi8_u.$(OBJEXT): internal/intern/bignum.h
+enc/koi8_u.$(OBJEXT): internal/intern/class.h
+enc/koi8_u.$(OBJEXT): internal/intern/compar.h
+enc/koi8_u.$(OBJEXT): internal/intern/complex.h
+enc/koi8_u.$(OBJEXT): internal/intern/cont.h
+enc/koi8_u.$(OBJEXT): internal/intern/dir.h
+enc/koi8_u.$(OBJEXT): internal/intern/enum.h
+enc/koi8_u.$(OBJEXT): internal/intern/enumerator.h
+enc/koi8_u.$(OBJEXT): internal/intern/error.h
+enc/koi8_u.$(OBJEXT): internal/intern/eval.h
+enc/koi8_u.$(OBJEXT): internal/intern/file.h
+enc/koi8_u.$(OBJEXT): internal/intern/gc.h
+enc/koi8_u.$(OBJEXT): internal/intern/hash.h
+enc/koi8_u.$(OBJEXT): internal/intern/io.h
+enc/koi8_u.$(OBJEXT): internal/intern/load.h
+enc/koi8_u.$(OBJEXT): internal/intern/marshal.h
+enc/koi8_u.$(OBJEXT): internal/intern/numeric.h
+enc/koi8_u.$(OBJEXT): internal/intern/object.h
+enc/koi8_u.$(OBJEXT): internal/intern/parse.h
+enc/koi8_u.$(OBJEXT): internal/intern/proc.h
+enc/koi8_u.$(OBJEXT): internal/intern/process.h
+enc/koi8_u.$(OBJEXT): internal/intern/random.h
+enc/koi8_u.$(OBJEXT): internal/intern/range.h
+enc/koi8_u.$(OBJEXT): internal/intern/rational.h
+enc/koi8_u.$(OBJEXT): internal/intern/re.h
+enc/koi8_u.$(OBJEXT): internal/intern/ruby.h
+enc/koi8_u.$(OBJEXT): internal/intern/select.h
+enc/koi8_u.$(OBJEXT): internal/intern/select/largesize.h
+enc/koi8_u.$(OBJEXT): internal/intern/signal.h
+enc/koi8_u.$(OBJEXT): internal/intern/sprintf.h
+enc/koi8_u.$(OBJEXT): internal/intern/string.h
+enc/koi8_u.$(OBJEXT): internal/intern/struct.h
+enc/koi8_u.$(OBJEXT): internal/intern/thread.h
+enc/koi8_u.$(OBJEXT): internal/intern/time.h
+enc/koi8_u.$(OBJEXT): internal/intern/variable.h
+enc/koi8_u.$(OBJEXT): internal/intern/vm.h
+enc/koi8_u.$(OBJEXT): internal/interpreter.h
+enc/koi8_u.$(OBJEXT): internal/iterator.h
+enc/koi8_u.$(OBJEXT): internal/memory.h
+enc/koi8_u.$(OBJEXT): internal/method.h
+enc/koi8_u.$(OBJEXT): internal/module.h
+enc/koi8_u.$(OBJEXT): internal/newobj.h
+enc/koi8_u.$(OBJEXT): internal/rgengc.h
+enc/koi8_u.$(OBJEXT): internal/scan_args.h
+enc/koi8_u.$(OBJEXT): internal/special_consts.h
+enc/koi8_u.$(OBJEXT): internal/static_assert.h
enc/koi8_u.$(OBJEXT): internal/stdalign.h
enc/koi8_u.$(OBJEXT): internal/stdbool.h
+enc/koi8_u.$(OBJEXT): internal/symbol.h
+enc/koi8_u.$(OBJEXT): internal/value.h
+enc/koi8_u.$(OBJEXT): internal/value_type.h
+enc/koi8_u.$(OBJEXT): internal/variable.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/koi8_u.$(OBJEXT): st.h
+enc/koi8_u.$(OBJEXT): subst.h
+enc/shift_jis.$(OBJEXT): $(hdrdir)/ruby.h
+enc/shift_jis.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/shift_jis.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/shift_jis.$(OBJEXT): assert.h
+enc/shift_jis.$(OBJEXT): backward.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/inttypes.h
+enc/shift_jis.$(OBJEXT): backward/2/limits.h
+enc/shift_jis.$(OBJEXT): backward/2/long_long.h
+enc/shift_jis.$(OBJEXT): backward/2/stdalign.h
+enc/shift_jis.$(OBJEXT): backward/2/stdarg.h
+enc/shift_jis.$(OBJEXT): config.h
+enc/shift_jis.$(OBJEXT): defines.h
+enc/shift_jis.$(OBJEXT): enc/jis/props.h
+enc/shift_jis.$(OBJEXT): enc/jis/props.kwd
+enc/shift_jis.$(OBJEXT): enc/shift_jis.c
+enc/shift_jis.$(OBJEXT): enc/shift_jis.h
+enc/shift_jis.$(OBJEXT): intern.h
+enc/shift_jis.$(OBJEXT): internal/abi.h
+enc/shift_jis.$(OBJEXT): internal/anyargs.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/char.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/double.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/int.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/long.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/long_long.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/off_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/short.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/size_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/shift_jis.$(OBJEXT): internal/arithmetic/uid_t.h
enc/shift_jis.$(OBJEXT): internal/assume.h
enc/shift_jis.$(OBJEXT): internal/attr/alloc_size.h
+enc/shift_jis.$(OBJEXT): internal/attr/artificial.h
enc/shift_jis.$(OBJEXT): internal/attr/cold.h
enc/shift_jis.$(OBJEXT): internal/attr/const.h
+enc/shift_jis.$(OBJEXT): internal/attr/constexpr.h
enc/shift_jis.$(OBJEXT): internal/attr/deprecated.h
+enc/shift_jis.$(OBJEXT): internal/attr/diagnose_if.h
+enc/shift_jis.$(OBJEXT): internal/attr/enum_extensibility.h
enc/shift_jis.$(OBJEXT): internal/attr/error.h
+enc/shift_jis.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -2155,6 +4955,7 @@ 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/attr/weakref.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
@@ -2165,8 +4966,30 @@ 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/constant_p.h
+enc/shift_jis.$(OBJEXT): internal/core.h
+enc/shift_jis.$(OBJEXT): internal/core/rarray.h
+enc/shift_jis.$(OBJEXT): internal/core/rbasic.h
+enc/shift_jis.$(OBJEXT): internal/core/rbignum.h
+enc/shift_jis.$(OBJEXT): internal/core/rclass.h
+enc/shift_jis.$(OBJEXT): internal/core/rdata.h
+enc/shift_jis.$(OBJEXT): internal/core/rfile.h
+enc/shift_jis.$(OBJEXT): internal/core/rhash.h
+enc/shift_jis.$(OBJEXT): internal/core/robject.h
+enc/shift_jis.$(OBJEXT): internal/core/rregexp.h
+enc/shift_jis.$(OBJEXT): internal/core/rstring.h
+enc/shift_jis.$(OBJEXT): internal/core/rstruct.h
+enc/shift_jis.$(OBJEXT): internal/core/rtypeddata.h
+enc/shift_jis.$(OBJEXT): internal/ctype.h
enc/shift_jis.$(OBJEXT): internal/dllexport.h
enc/shift_jis.$(OBJEXT): internal/dosish.h
+enc/shift_jis.$(OBJEXT): internal/error.h
+enc/shift_jis.$(OBJEXT): internal/eval.h
+enc/shift_jis.$(OBJEXT): internal/event.h
+enc/shift_jis.$(OBJEXT): internal/fl_type.h
+enc/shift_jis.$(OBJEXT): internal/gc.h
+enc/shift_jis.$(OBJEXT): internal/glob.h
+enc/shift_jis.$(OBJEXT): internal/globals.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
@@ -2175,28 +4998,82 @@ 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/intern/array.h
+enc/shift_jis.$(OBJEXT): internal/intern/bignum.h
+enc/shift_jis.$(OBJEXT): internal/intern/class.h
+enc/shift_jis.$(OBJEXT): internal/intern/compar.h
+enc/shift_jis.$(OBJEXT): internal/intern/complex.h
+enc/shift_jis.$(OBJEXT): internal/intern/cont.h
+enc/shift_jis.$(OBJEXT): internal/intern/dir.h
+enc/shift_jis.$(OBJEXT): internal/intern/enum.h
+enc/shift_jis.$(OBJEXT): internal/intern/enumerator.h
+enc/shift_jis.$(OBJEXT): internal/intern/error.h
+enc/shift_jis.$(OBJEXT): internal/intern/eval.h
+enc/shift_jis.$(OBJEXT): internal/intern/file.h
+enc/shift_jis.$(OBJEXT): internal/intern/gc.h
+enc/shift_jis.$(OBJEXT): internal/intern/hash.h
+enc/shift_jis.$(OBJEXT): internal/intern/io.h
+enc/shift_jis.$(OBJEXT): internal/intern/load.h
+enc/shift_jis.$(OBJEXT): internal/intern/marshal.h
+enc/shift_jis.$(OBJEXT): internal/intern/numeric.h
+enc/shift_jis.$(OBJEXT): internal/intern/object.h
+enc/shift_jis.$(OBJEXT): internal/intern/parse.h
+enc/shift_jis.$(OBJEXT): internal/intern/proc.h
+enc/shift_jis.$(OBJEXT): internal/intern/process.h
+enc/shift_jis.$(OBJEXT): internal/intern/random.h
+enc/shift_jis.$(OBJEXT): internal/intern/range.h
+enc/shift_jis.$(OBJEXT): internal/intern/rational.h
+enc/shift_jis.$(OBJEXT): internal/intern/re.h
+enc/shift_jis.$(OBJEXT): internal/intern/ruby.h
+enc/shift_jis.$(OBJEXT): internal/intern/select.h
+enc/shift_jis.$(OBJEXT): internal/intern/select/largesize.h
+enc/shift_jis.$(OBJEXT): internal/intern/signal.h
+enc/shift_jis.$(OBJEXT): internal/intern/sprintf.h
+enc/shift_jis.$(OBJEXT): internal/intern/string.h
+enc/shift_jis.$(OBJEXT): internal/intern/struct.h
+enc/shift_jis.$(OBJEXT): internal/intern/thread.h
+enc/shift_jis.$(OBJEXT): internal/intern/time.h
+enc/shift_jis.$(OBJEXT): internal/intern/variable.h
+enc/shift_jis.$(OBJEXT): internal/intern/vm.h
+enc/shift_jis.$(OBJEXT): internal/interpreter.h
+enc/shift_jis.$(OBJEXT): internal/iterator.h
+enc/shift_jis.$(OBJEXT): internal/memory.h
+enc/shift_jis.$(OBJEXT): internal/method.h
+enc/shift_jis.$(OBJEXT): internal/module.h
+enc/shift_jis.$(OBJEXT): internal/newobj.h
+enc/shift_jis.$(OBJEXT): internal/rgengc.h
+enc/shift_jis.$(OBJEXT): internal/scan_args.h
+enc/shift_jis.$(OBJEXT): internal/special_consts.h
+enc/shift_jis.$(OBJEXT): internal/static_assert.h
enc/shift_jis.$(OBJEXT): internal/stdalign.h
enc/shift_jis.$(OBJEXT): internal/stdbool.h
+enc/shift_jis.$(OBJEXT): internal/symbol.h
+enc/shift_jis.$(OBJEXT): internal/value.h
+enc/shift_jis.$(OBJEXT): internal/value_type.h
+enc/shift_jis.$(OBJEXT): internal/variable.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
-enc/shift_jis.$(OBJEXT): enc/jis/props.kwd
-enc/shift_jis.$(OBJEXT): enc/shift_jis.c
-enc/shift_jis.$(OBJEXT): enc/shift_jis.h
enc/shift_jis.$(OBJEXT): missing.h
enc/shift_jis.$(OBJEXT): onigmo.h
+enc/shift_jis.$(OBJEXT): st.h
+enc/shift_jis.$(OBJEXT): subst.h
enc/trans/big5.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/big5.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/big5.$(OBJEXT): assert.h
+enc/trans/big5.$(OBJEXT): backward.h
+enc/trans/big5.$(OBJEXT): backward/2/assume.h
+enc/trans/big5.$(OBJEXT): backward/2/attributes.h
+enc/trans/big5.$(OBJEXT): backward/2/bool.h
+enc/trans/big5.$(OBJEXT): backward/2/inttypes.h
+enc/trans/big5.$(OBJEXT): backward/2/limits.h
+enc/trans/big5.$(OBJEXT): backward/2/long_long.h
+enc/trans/big5.$(OBJEXT): backward/2/stdalign.h
+enc/trans/big5.$(OBJEXT): backward/2/stdarg.h
+enc/trans/big5.$(OBJEXT): config.h
+enc/trans/big5.$(OBJEXT): defines.h
+enc/trans/big5.$(OBJEXT): enc/trans/big5.c
+enc/trans/big5.$(OBJEXT): intern.h
+enc/trans/big5.$(OBJEXT): internal/abi.h
enc/trans/big5.$(OBJEXT): internal/anyargs.h
enc/trans/big5.$(OBJEXT): internal/arithmetic.h
enc/trans/big5.$(OBJEXT): internal/arithmetic/char.h
@@ -2336,26 +5213,26 @@ 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
-enc/trans/big5.$(OBJEXT): intern.h
enc/trans/big5.$(OBJEXT): missing.h
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): assert.h
+enc/trans/cesu_8.$(OBJEXT): backward.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/assume.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/attributes.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/bool.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/inttypes.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/limits.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/long_long.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/stdalign.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/stdarg.h
+enc/trans/cesu_8.$(OBJEXT): config.h
+enc/trans/cesu_8.$(OBJEXT): defines.h
+enc/trans/cesu_8.$(OBJEXT): enc/trans/cesu_8.c
+enc/trans/cesu_8.$(OBJEXT): intern.h
+enc/trans/cesu_8.$(OBJEXT): internal/abi.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
@@ -2495,26 +5372,26 @@ 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
-enc/trans/cesu_8.$(OBJEXT): intern.h
enc/trans/cesu_8.$(OBJEXT): missing.h
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): assert.h
+enc/trans/chinese.$(OBJEXT): backward.h
+enc/trans/chinese.$(OBJEXT): backward/2/assume.h
+enc/trans/chinese.$(OBJEXT): backward/2/attributes.h
+enc/trans/chinese.$(OBJEXT): backward/2/bool.h
+enc/trans/chinese.$(OBJEXT): backward/2/inttypes.h
+enc/trans/chinese.$(OBJEXT): backward/2/limits.h
+enc/trans/chinese.$(OBJEXT): backward/2/long_long.h
+enc/trans/chinese.$(OBJEXT): backward/2/stdalign.h
+enc/trans/chinese.$(OBJEXT): backward/2/stdarg.h
+enc/trans/chinese.$(OBJEXT): config.h
+enc/trans/chinese.$(OBJEXT): defines.h
+enc/trans/chinese.$(OBJEXT): enc/trans/chinese.c
+enc/trans/chinese.$(OBJEXT): intern.h
+enc/trans/chinese.$(OBJEXT): internal/abi.h
enc/trans/chinese.$(OBJEXT): internal/anyargs.h
enc/trans/chinese.$(OBJEXT): internal/arithmetic.h
enc/trans/chinese.$(OBJEXT): internal/arithmetic/char.h
@@ -2654,26 +5531,26 @@ 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
-enc/trans/chinese.$(OBJEXT): intern.h
enc/trans/chinese.$(OBJEXT): missing.h
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): assert.h
+enc/trans/ebcdic.$(OBJEXT): backward.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/assume.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/attributes.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/bool.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/inttypes.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/limits.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/long_long.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/stdalign.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/stdarg.h
+enc/trans/ebcdic.$(OBJEXT): config.h
+enc/trans/ebcdic.$(OBJEXT): defines.h
+enc/trans/ebcdic.$(OBJEXT): enc/trans/ebcdic.c
+enc/trans/ebcdic.$(OBJEXT): intern.h
+enc/trans/ebcdic.$(OBJEXT): internal/abi.h
enc/trans/ebcdic.$(OBJEXT): internal/anyargs.h
enc/trans/ebcdic.$(OBJEXT): internal/arithmetic.h
enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/char.h
@@ -2813,26 +5690,26 @@ 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
-enc/trans/ebcdic.$(OBJEXT): intern.h
enc/trans/ebcdic.$(OBJEXT): missing.h
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): assert.h
+enc/trans/emoji.$(OBJEXT): backward.h
+enc/trans/emoji.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji.$(OBJEXT): backward/2/stdarg.h
+enc/trans/emoji.$(OBJEXT): config.h
+enc/trans/emoji.$(OBJEXT): defines.h
+enc/trans/emoji.$(OBJEXT): enc/trans/emoji.c
+enc/trans/emoji.$(OBJEXT): intern.h
+enc/trans/emoji.$(OBJEXT): internal/abi.h
enc/trans/emoji.$(OBJEXT): internal/anyargs.h
enc/trans/emoji.$(OBJEXT): internal/arithmetic.h
enc/trans/emoji.$(OBJEXT): internal/arithmetic/char.h
@@ -2972,26 +5849,26 @@ 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
-enc/trans/emoji.$(OBJEXT): intern.h
enc/trans/emoji.$(OBJEXT): missing.h
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): assert.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/stdarg.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): config.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): defines.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): enc/trans/emoji_iso2022_kddi.c
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): intern.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/abi.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
@@ -3131,26 +6008,26 @@ 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
-enc/trans/emoji_iso2022_kddi.$(OBJEXT): intern.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): missing.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): st.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): subst.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): assert.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/stdarg.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): config.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): defines.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): enc/trans/emoji_sjis_docomo.c
+enc/trans/emoji_sjis_docomo.$(OBJEXT): intern.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/abi.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
@@ -3290,26 +6167,26 @@ 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
-enc/trans/emoji_sjis_docomo.$(OBJEXT): intern.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): missing.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): st.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): subst.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): assert.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/stdarg.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): config.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): defines.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): enc/trans/emoji_sjis_kddi.c
+enc/trans/emoji_sjis_kddi.$(OBJEXT): intern.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/abi.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
@@ -3449,26 +6326,26 @@ 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
-enc/trans/emoji_sjis_kddi.$(OBJEXT): intern.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): missing.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): st.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): subst.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): assert.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/stdarg.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): config.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): defines.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): enc/trans/emoji_sjis_softbank.c
+enc/trans/emoji_sjis_softbank.$(OBJEXT): intern.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/abi.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
@@ -3608,26 +6485,26 @@ 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
-enc/trans/emoji_sjis_softbank.$(OBJEXT): intern.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): missing.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): st.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): subst.h
enc/trans/escape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/escape.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/escape.$(OBJEXT): assert.h
+enc/trans/escape.$(OBJEXT): backward.h
+enc/trans/escape.$(OBJEXT): backward/2/assume.h
+enc/trans/escape.$(OBJEXT): backward/2/attributes.h
+enc/trans/escape.$(OBJEXT): backward/2/bool.h
+enc/trans/escape.$(OBJEXT): backward/2/inttypes.h
+enc/trans/escape.$(OBJEXT): backward/2/limits.h
+enc/trans/escape.$(OBJEXT): backward/2/long_long.h
+enc/trans/escape.$(OBJEXT): backward/2/stdalign.h
+enc/trans/escape.$(OBJEXT): backward/2/stdarg.h
+enc/trans/escape.$(OBJEXT): config.h
+enc/trans/escape.$(OBJEXT): defines.h
+enc/trans/escape.$(OBJEXT): enc/trans/escape.c
+enc/trans/escape.$(OBJEXT): intern.h
+enc/trans/escape.$(OBJEXT): internal/abi.h
enc/trans/escape.$(OBJEXT): internal/anyargs.h
enc/trans/escape.$(OBJEXT): internal/arithmetic.h
enc/trans/escape.$(OBJEXT): internal/arithmetic/char.h
@@ -3767,26 +6644,26 @@ 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
-enc/trans/escape.$(OBJEXT): intern.h
enc/trans/escape.$(OBJEXT): missing.h
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): assert.h
+enc/trans/gb18030.$(OBJEXT): backward.h
+enc/trans/gb18030.$(OBJEXT): backward/2/assume.h
+enc/trans/gb18030.$(OBJEXT): backward/2/attributes.h
+enc/trans/gb18030.$(OBJEXT): backward/2/bool.h
+enc/trans/gb18030.$(OBJEXT): backward/2/inttypes.h
+enc/trans/gb18030.$(OBJEXT): backward/2/limits.h
+enc/trans/gb18030.$(OBJEXT): backward/2/long_long.h
+enc/trans/gb18030.$(OBJEXT): backward/2/stdalign.h
+enc/trans/gb18030.$(OBJEXT): backward/2/stdarg.h
+enc/trans/gb18030.$(OBJEXT): config.h
+enc/trans/gb18030.$(OBJEXT): defines.h
+enc/trans/gb18030.$(OBJEXT): enc/trans/gb18030.c
+enc/trans/gb18030.$(OBJEXT): intern.h
+enc/trans/gb18030.$(OBJEXT): internal/abi.h
enc/trans/gb18030.$(OBJEXT): internal/anyargs.h
enc/trans/gb18030.$(OBJEXT): internal/arithmetic.h
enc/trans/gb18030.$(OBJEXT): internal/arithmetic/char.h
@@ -3926,26 +6803,26 @@ 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
-enc/trans/gb18030.$(OBJEXT): intern.h
enc/trans/gb18030.$(OBJEXT): missing.h
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): assert.h
+enc/trans/gbk.$(OBJEXT): backward.h
+enc/trans/gbk.$(OBJEXT): backward/2/assume.h
+enc/trans/gbk.$(OBJEXT): backward/2/attributes.h
+enc/trans/gbk.$(OBJEXT): backward/2/bool.h
+enc/trans/gbk.$(OBJEXT): backward/2/inttypes.h
+enc/trans/gbk.$(OBJEXT): backward/2/limits.h
+enc/trans/gbk.$(OBJEXT): backward/2/long_long.h
+enc/trans/gbk.$(OBJEXT): backward/2/stdalign.h
+enc/trans/gbk.$(OBJEXT): backward/2/stdarg.h
+enc/trans/gbk.$(OBJEXT): config.h
+enc/trans/gbk.$(OBJEXT): defines.h
+enc/trans/gbk.$(OBJEXT): enc/trans/gbk.c
+enc/trans/gbk.$(OBJEXT): intern.h
+enc/trans/gbk.$(OBJEXT): internal/abi.h
enc/trans/gbk.$(OBJEXT): internal/anyargs.h
enc/trans/gbk.$(OBJEXT): internal/arithmetic.h
enc/trans/gbk.$(OBJEXT): internal/arithmetic/char.h
@@ -4085,26 +6962,26 @@ 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
-enc/trans/gbk.$(OBJEXT): intern.h
enc/trans/gbk.$(OBJEXT): missing.h
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): assert.h
+enc/trans/iso2022.$(OBJEXT): backward.h
+enc/trans/iso2022.$(OBJEXT): backward/2/assume.h
+enc/trans/iso2022.$(OBJEXT): backward/2/attributes.h
+enc/trans/iso2022.$(OBJEXT): backward/2/bool.h
+enc/trans/iso2022.$(OBJEXT): backward/2/inttypes.h
+enc/trans/iso2022.$(OBJEXT): backward/2/limits.h
+enc/trans/iso2022.$(OBJEXT): backward/2/long_long.h
+enc/trans/iso2022.$(OBJEXT): backward/2/stdalign.h
+enc/trans/iso2022.$(OBJEXT): backward/2/stdarg.h
+enc/trans/iso2022.$(OBJEXT): config.h
+enc/trans/iso2022.$(OBJEXT): defines.h
+enc/trans/iso2022.$(OBJEXT): enc/trans/iso2022.c
+enc/trans/iso2022.$(OBJEXT): intern.h
+enc/trans/iso2022.$(OBJEXT): internal/abi.h
enc/trans/iso2022.$(OBJEXT): internal/anyargs.h
enc/trans/iso2022.$(OBJEXT): internal/arithmetic.h
enc/trans/iso2022.$(OBJEXT): internal/arithmetic/char.h
@@ -4141,6 +7018,7 @@ enc/trans/iso2022.$(OBJEXT): internal/attr/nodiscard.h
enc/trans/iso2022.$(OBJEXT): internal/attr/noexcept.h
enc/trans/iso2022.$(OBJEXT): internal/attr/noinline.h
enc/trans/iso2022.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/nonstring.h
enc/trans/iso2022.$(OBJEXT): internal/attr/noreturn.h
enc/trans/iso2022.$(OBJEXT): internal/attr/pure.h
enc/trans/iso2022.$(OBJEXT): internal/attr/restrict.h
@@ -4244,26 +7122,26 @@ 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
-enc/trans/iso2022.$(OBJEXT): intern.h
enc/trans/iso2022.$(OBJEXT): missing.h
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): assert.h
+enc/trans/japanese.$(OBJEXT): backward.h
+enc/trans/japanese.$(OBJEXT): backward/2/assume.h
+enc/trans/japanese.$(OBJEXT): backward/2/attributes.h
+enc/trans/japanese.$(OBJEXT): backward/2/bool.h
+enc/trans/japanese.$(OBJEXT): backward/2/inttypes.h
+enc/trans/japanese.$(OBJEXT): backward/2/limits.h
+enc/trans/japanese.$(OBJEXT): backward/2/long_long.h
+enc/trans/japanese.$(OBJEXT): backward/2/stdalign.h
+enc/trans/japanese.$(OBJEXT): backward/2/stdarg.h
+enc/trans/japanese.$(OBJEXT): config.h
+enc/trans/japanese.$(OBJEXT): defines.h
+enc/trans/japanese.$(OBJEXT): enc/trans/japanese.c
+enc/trans/japanese.$(OBJEXT): intern.h
+enc/trans/japanese.$(OBJEXT): internal/abi.h
enc/trans/japanese.$(OBJEXT): internal/anyargs.h
enc/trans/japanese.$(OBJEXT): internal/arithmetic.h
enc/trans/japanese.$(OBJEXT): internal/arithmetic/char.h
@@ -4403,26 +7281,26 @@ 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
-enc/trans/japanese.$(OBJEXT): intern.h
enc/trans/japanese.$(OBJEXT): missing.h
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): assert.h
+enc/trans/japanese_euc.$(OBJEXT): backward.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/assume.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/attributes.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/bool.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/inttypes.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/limits.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/long_long.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/stdalign.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/stdarg.h
+enc/trans/japanese_euc.$(OBJEXT): config.h
+enc/trans/japanese_euc.$(OBJEXT): defines.h
+enc/trans/japanese_euc.$(OBJEXT): enc/trans/japanese_euc.c
+enc/trans/japanese_euc.$(OBJEXT): intern.h
+enc/trans/japanese_euc.$(OBJEXT): internal/abi.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
@@ -4562,26 +7440,26 @@ 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
-enc/trans/japanese_euc.$(OBJEXT): intern.h
enc/trans/japanese_euc.$(OBJEXT): missing.h
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): assert.h
+enc/trans/japanese_sjis.$(OBJEXT): backward.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/assume.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/attributes.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/bool.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/inttypes.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/limits.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/long_long.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/stdalign.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/stdarg.h
+enc/trans/japanese_sjis.$(OBJEXT): config.h
+enc/trans/japanese_sjis.$(OBJEXT): defines.h
+enc/trans/japanese_sjis.$(OBJEXT): enc/trans/japanese_sjis.c
+enc/trans/japanese_sjis.$(OBJEXT): intern.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/abi.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
@@ -4721,26 +7599,26 @@ 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
-enc/trans/japanese_sjis.$(OBJEXT): intern.h
enc/trans/japanese_sjis.$(OBJEXT): missing.h
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): assert.h
+enc/trans/korean.$(OBJEXT): backward.h
+enc/trans/korean.$(OBJEXT): backward/2/assume.h
+enc/trans/korean.$(OBJEXT): backward/2/attributes.h
+enc/trans/korean.$(OBJEXT): backward/2/bool.h
+enc/trans/korean.$(OBJEXT): backward/2/inttypes.h
+enc/trans/korean.$(OBJEXT): backward/2/limits.h
+enc/trans/korean.$(OBJEXT): backward/2/long_long.h
+enc/trans/korean.$(OBJEXT): backward/2/stdalign.h
+enc/trans/korean.$(OBJEXT): backward/2/stdarg.h
+enc/trans/korean.$(OBJEXT): config.h
+enc/trans/korean.$(OBJEXT): defines.h
+enc/trans/korean.$(OBJEXT): enc/trans/korean.c
+enc/trans/korean.$(OBJEXT): intern.h
+enc/trans/korean.$(OBJEXT): internal/abi.h
enc/trans/korean.$(OBJEXT): internal/anyargs.h
enc/trans/korean.$(OBJEXT): internal/arithmetic.h
enc/trans/korean.$(OBJEXT): internal/arithmetic/char.h
@@ -4880,26 +7758,25 @@ 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
-enc/trans/korean.$(OBJEXT): intern.h
enc/trans/korean.$(OBJEXT): missing.h
enc/trans/korean.$(OBJEXT): st.h
enc/trans/korean.$(OBJEXT): subst.h
enc/trans/newline.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/newline.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/newline.$(OBJEXT): assert.h
+enc/trans/newline.$(OBJEXT): backward/2/assume.h
+enc/trans/newline.$(OBJEXT): backward/2/attributes.h
+enc/trans/newline.$(OBJEXT): backward/2/bool.h
+enc/trans/newline.$(OBJEXT): backward/2/inttypes.h
+enc/trans/newline.$(OBJEXT): backward/2/limits.h
+enc/trans/newline.$(OBJEXT): backward/2/long_long.h
+enc/trans/newline.$(OBJEXT): backward/2/stdalign.h
+enc/trans/newline.$(OBJEXT): backward/2/stdarg.h
+enc/trans/newline.$(OBJEXT): config.h
+enc/trans/newline.$(OBJEXT): defines.h
+enc/trans/newline.$(OBJEXT): enc/trans/newline.c
+enc/trans/newline.$(OBJEXT): intern.h
+enc/trans/newline.$(OBJEXT): internal/abi.h
enc/trans/newline.$(OBJEXT): internal/anyargs.h
enc/trans/newline.$(OBJEXT): internal/arithmetic.h
enc/trans/newline.$(OBJEXT): internal/arithmetic/char.h
@@ -5039,25 +7916,26 @@ 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
-enc/trans/newline.$(OBJEXT): intern.h
enc/trans/newline.$(OBJEXT): missing.h
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): assert.h
+enc/trans/single_byte.$(OBJEXT): backward.h
+enc/trans/single_byte.$(OBJEXT): backward/2/assume.h
+enc/trans/single_byte.$(OBJEXT): backward/2/attributes.h
+enc/trans/single_byte.$(OBJEXT): backward/2/bool.h
+enc/trans/single_byte.$(OBJEXT): backward/2/inttypes.h
+enc/trans/single_byte.$(OBJEXT): backward/2/limits.h
+enc/trans/single_byte.$(OBJEXT): backward/2/long_long.h
+enc/trans/single_byte.$(OBJEXT): backward/2/stdalign.h
+enc/trans/single_byte.$(OBJEXT): backward/2/stdarg.h
+enc/trans/single_byte.$(OBJEXT): config.h
+enc/trans/single_byte.$(OBJEXT): defines.h
+enc/trans/single_byte.$(OBJEXT): enc/trans/single_byte.c
+enc/trans/single_byte.$(OBJEXT): intern.h
+enc/trans/single_byte.$(OBJEXT): internal/abi.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
@@ -5197,28 +8075,186 @@ 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
-enc/trans/single_byte.$(OBJEXT): intern.h
enc/trans/single_byte.$(OBJEXT): missing.h
enc/trans/single_byte.$(OBJEXT): st.h
enc/trans/single_byte.$(OBJEXT): subst.h
+enc/trans/transdb.$(OBJEXT): $(hdrdir)/ruby.h
+enc/trans/transdb.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enc/trans/transdb.$(OBJEXT): assert.h
+enc/trans/transdb.$(OBJEXT): backward.h
+enc/trans/transdb.$(OBJEXT): backward/2/assume.h
+enc/trans/transdb.$(OBJEXT): backward/2/attributes.h
+enc/trans/transdb.$(OBJEXT): backward/2/bool.h
+enc/trans/transdb.$(OBJEXT): backward/2/inttypes.h
+enc/trans/transdb.$(OBJEXT): backward/2/limits.h
+enc/trans/transdb.$(OBJEXT): backward/2/long_long.h
+enc/trans/transdb.$(OBJEXT): backward/2/stdalign.h
+enc/trans/transdb.$(OBJEXT): backward/2/stdarg.h
+enc/trans/transdb.$(OBJEXT): config.h
+enc/trans/transdb.$(OBJEXT): defines.h
enc/trans/transdb.$(OBJEXT): enc/trans/transdb.c
+enc/trans/transdb.$(OBJEXT): intern.h
+enc/trans/transdb.$(OBJEXT): internal/abi.h
+enc/trans/transdb.$(OBJEXT): internal/anyargs.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/transdb.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/transdb.$(OBJEXT): internal/assume.h
+enc/trans/transdb.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/transdb.$(OBJEXT): internal/attr/artificial.h
+enc/trans/transdb.$(OBJEXT): internal/attr/cold.h
+enc/trans/transdb.$(OBJEXT): internal/attr/const.h
+enc/trans/transdb.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/transdb.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/transdb.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/transdb.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/transdb.$(OBJEXT): internal/attr/error.h
+enc/trans/transdb.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/transdb.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/transdb.$(OBJEXT): internal/attr/format.h
+enc/trans/transdb.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/transdb.$(OBJEXT): internal/attr/noalias.h
+enc/trans/transdb.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/transdb.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/transdb.$(OBJEXT): internal/attr/noinline.h
+enc/trans/transdb.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/transdb.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/transdb.$(OBJEXT): internal/attr/pure.h
+enc/trans/transdb.$(OBJEXT): internal/attr/restrict.h
+enc/trans/transdb.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/transdb.$(OBJEXT): internal/attr/warning.h
+enc/trans/transdb.$(OBJEXT): internal/attr/weakref.h
+enc/trans/transdb.$(OBJEXT): internal/cast.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/transdb.$(OBJEXT): internal/compiler_since.h
+enc/trans/transdb.$(OBJEXT): internal/config.h
+enc/trans/transdb.$(OBJEXT): internal/constant_p.h
+enc/trans/transdb.$(OBJEXT): internal/core.h
+enc/trans/transdb.$(OBJEXT): internal/core/rarray.h
+enc/trans/transdb.$(OBJEXT): internal/core/rbasic.h
+enc/trans/transdb.$(OBJEXT): internal/core/rbignum.h
+enc/trans/transdb.$(OBJEXT): internal/core/rclass.h
+enc/trans/transdb.$(OBJEXT): internal/core/rdata.h
+enc/trans/transdb.$(OBJEXT): internal/core/rfile.h
+enc/trans/transdb.$(OBJEXT): internal/core/rhash.h
+enc/trans/transdb.$(OBJEXT): internal/core/robject.h
+enc/trans/transdb.$(OBJEXT): internal/core/rregexp.h
+enc/trans/transdb.$(OBJEXT): internal/core/rstring.h
+enc/trans/transdb.$(OBJEXT): internal/core/rstruct.h
+enc/trans/transdb.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/transdb.$(OBJEXT): internal/ctype.h
+enc/trans/transdb.$(OBJEXT): internal/dllexport.h
+enc/trans/transdb.$(OBJEXT): internal/dosish.h
+enc/trans/transdb.$(OBJEXT): internal/error.h
+enc/trans/transdb.$(OBJEXT): internal/eval.h
+enc/trans/transdb.$(OBJEXT): internal/event.h
+enc/trans/transdb.$(OBJEXT): internal/fl_type.h
+enc/trans/transdb.$(OBJEXT): internal/gc.h
+enc/trans/transdb.$(OBJEXT): internal/glob.h
+enc/trans/transdb.$(OBJEXT): internal/globals.h
+enc/trans/transdb.$(OBJEXT): internal/has/attribute.h
+enc/trans/transdb.$(OBJEXT): internal/has/builtin.h
+enc/trans/transdb.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/transdb.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/transdb.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/transdb.$(OBJEXT): internal/has/extension.h
+enc/trans/transdb.$(OBJEXT): internal/has/feature.h
+enc/trans/transdb.$(OBJEXT): internal/has/warning.h
+enc/trans/transdb.$(OBJEXT): internal/intern/array.h
+enc/trans/transdb.$(OBJEXT): internal/intern/bignum.h
+enc/trans/transdb.$(OBJEXT): internal/intern/class.h
+enc/trans/transdb.$(OBJEXT): internal/intern/compar.h
+enc/trans/transdb.$(OBJEXT): internal/intern/complex.h
+enc/trans/transdb.$(OBJEXT): internal/intern/cont.h
+enc/trans/transdb.$(OBJEXT): internal/intern/dir.h
+enc/trans/transdb.$(OBJEXT): internal/intern/enum.h
+enc/trans/transdb.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/transdb.$(OBJEXT): internal/intern/error.h
+enc/trans/transdb.$(OBJEXT): internal/intern/eval.h
+enc/trans/transdb.$(OBJEXT): internal/intern/file.h
+enc/trans/transdb.$(OBJEXT): internal/intern/gc.h
+enc/trans/transdb.$(OBJEXT): internal/intern/hash.h
+enc/trans/transdb.$(OBJEXT): internal/intern/io.h
+enc/trans/transdb.$(OBJEXT): internal/intern/load.h
+enc/trans/transdb.$(OBJEXT): internal/intern/marshal.h
+enc/trans/transdb.$(OBJEXT): internal/intern/numeric.h
+enc/trans/transdb.$(OBJEXT): internal/intern/object.h
+enc/trans/transdb.$(OBJEXT): internal/intern/parse.h
+enc/trans/transdb.$(OBJEXT): internal/intern/proc.h
+enc/trans/transdb.$(OBJEXT): internal/intern/process.h
+enc/trans/transdb.$(OBJEXT): internal/intern/random.h
+enc/trans/transdb.$(OBJEXT): internal/intern/range.h
+enc/trans/transdb.$(OBJEXT): internal/intern/rational.h
+enc/trans/transdb.$(OBJEXT): internal/intern/re.h
+enc/trans/transdb.$(OBJEXT): internal/intern/ruby.h
+enc/trans/transdb.$(OBJEXT): internal/intern/select.h
+enc/trans/transdb.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/transdb.$(OBJEXT): internal/intern/signal.h
+enc/trans/transdb.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/transdb.$(OBJEXT): internal/intern/string.h
+enc/trans/transdb.$(OBJEXT): internal/intern/struct.h
+enc/trans/transdb.$(OBJEXT): internal/intern/thread.h
+enc/trans/transdb.$(OBJEXT): internal/intern/time.h
+enc/trans/transdb.$(OBJEXT): internal/intern/variable.h
+enc/trans/transdb.$(OBJEXT): internal/intern/vm.h
+enc/trans/transdb.$(OBJEXT): internal/interpreter.h
+enc/trans/transdb.$(OBJEXT): internal/iterator.h
+enc/trans/transdb.$(OBJEXT): internal/memory.h
+enc/trans/transdb.$(OBJEXT): internal/method.h
+enc/trans/transdb.$(OBJEXT): internal/module.h
+enc/trans/transdb.$(OBJEXT): internal/newobj.h
+enc/trans/transdb.$(OBJEXT): internal/rgengc.h
+enc/trans/transdb.$(OBJEXT): internal/scan_args.h
+enc/trans/transdb.$(OBJEXT): internal/special_consts.h
+enc/trans/transdb.$(OBJEXT): internal/static_assert.h
+enc/trans/transdb.$(OBJEXT): internal/stdalign.h
+enc/trans/transdb.$(OBJEXT): internal/stdbool.h
+enc/trans/transdb.$(OBJEXT): internal/symbol.h
+enc/trans/transdb.$(OBJEXT): internal/value.h
+enc/trans/transdb.$(OBJEXT): internal/value_type.h
+enc/trans/transdb.$(OBJEXT): internal/variable.h
+enc/trans/transdb.$(OBJEXT): internal/warning_push.h
+enc/trans/transdb.$(OBJEXT): internal/xmalloc.h
+enc/trans/transdb.$(OBJEXT): missing.h
+enc/trans/transdb.$(OBJEXT): st.h
+enc/trans/transdb.$(OBJEXT): subst.h
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): assert.h
+enc/trans/utf8_mac.$(OBJEXT): backward.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/assume.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/attributes.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/bool.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/inttypes.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/limits.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/long_long.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/stdalign.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/stdarg.h
+enc/trans/utf8_mac.$(OBJEXT): config.h
+enc/trans/utf8_mac.$(OBJEXT): defines.h
+enc/trans/utf8_mac.$(OBJEXT): enc/trans/utf8_mac.c
+enc/trans/utf8_mac.$(OBJEXT): intern.h
+enc/trans/utf8_mac.$(OBJEXT): internal/abi.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
@@ -5358,26 +8394,26 @@ 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
-enc/trans/utf8_mac.$(OBJEXT): intern.h
enc/trans/utf8_mac.$(OBJEXT): missing.h
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): assert.h
+enc/trans/utf_16_32.$(OBJEXT): backward.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/assume.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/attributes.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/bool.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/inttypes.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/limits.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/long_long.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/stdalign.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/stdarg.h
+enc/trans/utf_16_32.$(OBJEXT): config.h
+enc/trans/utf_16_32.$(OBJEXT): defines.h
+enc/trans/utf_16_32.$(OBJEXT): enc/trans/utf_16_32.c
+enc/trans/utf_16_32.$(OBJEXT): intern.h
+enc/trans/utf_16_32.$(OBJEXT): internal/abi.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
@@ -5517,29 +8553,29 @@ 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
-enc/trans/utf_16_32.$(OBJEXT): intern.h
enc/trans/utf_16_32.$(OBJEXT): missing.h
enc/trans/utf_16_32.$(OBJEXT): st.h
enc/trans/utf_16_32.$(OBJEXT): subst.h
enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/casefold.h
enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/name2ctype.h
+enc/unicode.$(OBJEXT): $(hdrdir)/ruby.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): assert.h
+enc/unicode.$(OBJEXT): backward/2/assume.h
+enc/unicode.$(OBJEXT): backward/2/attributes.h
+enc/unicode.$(OBJEXT): backward/2/bool.h
+enc/unicode.$(OBJEXT): backward/2/inttypes.h
+enc/unicode.$(OBJEXT): backward/2/limits.h
+enc/unicode.$(OBJEXT): backward/2/long_long.h
+enc/unicode.$(OBJEXT): backward/2/stdalign.h
+enc/unicode.$(OBJEXT): backward/2/stdarg.h
+enc/unicode.$(OBJEXT): config.h
+enc/unicode.$(OBJEXT): defines.h
+enc/unicode.$(OBJEXT): enc/unicode.c
+enc/unicode.$(OBJEXT): intern.h
+enc/unicode.$(OBJEXT): internal/abi.h
enc/unicode.$(OBJEXT): internal/anyargs.h
enc/unicode.$(OBJEXT): internal/arithmetic.h
enc/unicode.$(OBJEXT): internal/arithmetic/char.h
@@ -5679,27 +8715,29 @@ 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
-enc/unicode.$(OBJEXT): intern.h
enc/unicode.$(OBJEXT): missing.h
enc/unicode.$(OBJEXT): onigmo.h
enc/unicode.$(OBJEXT): st.h
enc/unicode.$(OBJEXT): subst.h
+enc/us_ascii.$(OBJEXT): $(hdrdir)/ruby.h
enc/us_ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/us_ascii.$(OBJEXT): $(top_srcdir)/encindex.h
enc/us_ascii.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/us_ascii.$(OBJEXT): assert.h
+enc/us_ascii.$(OBJEXT): backward/2/assume.h
+enc/us_ascii.$(OBJEXT): backward/2/attributes.h
+enc/us_ascii.$(OBJEXT): backward/2/bool.h
+enc/us_ascii.$(OBJEXT): backward/2/inttypes.h
+enc/us_ascii.$(OBJEXT): backward/2/limits.h
+enc/us_ascii.$(OBJEXT): backward/2/long_long.h
+enc/us_ascii.$(OBJEXT): backward/2/stdalign.h
+enc/us_ascii.$(OBJEXT): backward/2/stdarg.h
+enc/us_ascii.$(OBJEXT): config.h
+enc/us_ascii.$(OBJEXT): defines.h
+enc/us_ascii.$(OBJEXT): enc/us_ascii.c
+enc/us_ascii.$(OBJEXT): encoding.h
+enc/us_ascii.$(OBJEXT): intern.h
+enc/us_ascii.$(OBJEXT): internal/abi.h
enc/us_ascii.$(OBJEXT): internal/anyargs.h
enc/us_ascii.$(OBJEXT): internal/arithmetic.h
enc/us_ascii.$(OBJEXT): internal/arithmetic/char.h
@@ -5769,6 +8807,15 @@ enc/us_ascii.$(OBJEXT): internal/core/rtypeddata.h
enc/us_ascii.$(OBJEXT): internal/ctype.h
enc/us_ascii.$(OBJEXT): internal/dllexport.h
enc/us_ascii.$(OBJEXT): internal/dosish.h
+enc/us_ascii.$(OBJEXT): internal/encoding/coderange.h
+enc/us_ascii.$(OBJEXT): internal/encoding/ctype.h
+enc/us_ascii.$(OBJEXT): internal/encoding/encoding.h
+enc/us_ascii.$(OBJEXT): internal/encoding/pathname.h
+enc/us_ascii.$(OBJEXT): internal/encoding/re.h
+enc/us_ascii.$(OBJEXT): internal/encoding/sprintf.h
+enc/us_ascii.$(OBJEXT): internal/encoding/string.h
+enc/us_ascii.$(OBJEXT): internal/encoding/symbol.h
+enc/us_ascii.$(OBJEXT): internal/encoding/transcode.h
enc/us_ascii.$(OBJEXT): internal/error.h
enc/us_ascii.$(OBJEXT): internal/eval.h
enc/us_ascii.$(OBJEXT): internal/event.h
@@ -5839,36 +8886,62 @@ 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): $(hdrdir)/ruby.h
+enc/utf_16be.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/utf_16be.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_16be.$(OBJEXT): assert.h
+enc/utf_16be.$(OBJEXT): backward.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/inttypes.h
+enc/utf_16be.$(OBJEXT): backward/2/limits.h
+enc/utf_16be.$(OBJEXT): backward/2/long_long.h
+enc/utf_16be.$(OBJEXT): backward/2/stdalign.h
+enc/utf_16be.$(OBJEXT): backward/2/stdarg.h
+enc/utf_16be.$(OBJEXT): config.h
+enc/utf_16be.$(OBJEXT): defines.h
+enc/utf_16be.$(OBJEXT): enc/iso_8859.h
+enc/utf_16be.$(OBJEXT): enc/utf_16be.c
+enc/utf_16be.$(OBJEXT): intern.h
+enc/utf_16be.$(OBJEXT): internal/abi.h
+enc/utf_16be.$(OBJEXT): internal/anyargs.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/char.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/double.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/int.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/long.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/long_long.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/off_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/short.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/size_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/utf_16be.$(OBJEXT): internal/arithmetic/uid_t.h
enc/utf_16be.$(OBJEXT): internal/assume.h
enc/utf_16be.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_16be.$(OBJEXT): internal/attr/artificial.h
enc/utf_16be.$(OBJEXT): internal/attr/cold.h
enc/utf_16be.$(OBJEXT): internal/attr/const.h
+enc/utf_16be.$(OBJEXT): internal/attr/constexpr.h
enc/utf_16be.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_16be.$(OBJEXT): internal/attr/diagnose_if.h
+enc/utf_16be.$(OBJEXT): internal/attr/enum_extensibility.h
enc/utf_16be.$(OBJEXT): internal/attr/error.h
+enc/utf_16be.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -5878,6 +8951,7 @@ 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/attr/weakref.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
@@ -5888,8 +8962,30 @@ 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/constant_p.h
+enc/utf_16be.$(OBJEXT): internal/core.h
+enc/utf_16be.$(OBJEXT): internal/core/rarray.h
+enc/utf_16be.$(OBJEXT): internal/core/rbasic.h
+enc/utf_16be.$(OBJEXT): internal/core/rbignum.h
+enc/utf_16be.$(OBJEXT): internal/core/rclass.h
+enc/utf_16be.$(OBJEXT): internal/core/rdata.h
+enc/utf_16be.$(OBJEXT): internal/core/rfile.h
+enc/utf_16be.$(OBJEXT): internal/core/rhash.h
+enc/utf_16be.$(OBJEXT): internal/core/robject.h
+enc/utf_16be.$(OBJEXT): internal/core/rregexp.h
+enc/utf_16be.$(OBJEXT): internal/core/rstring.h
+enc/utf_16be.$(OBJEXT): internal/core/rstruct.h
+enc/utf_16be.$(OBJEXT): internal/core/rtypeddata.h
+enc/utf_16be.$(OBJEXT): internal/ctype.h
enc/utf_16be.$(OBJEXT): internal/dllexport.h
enc/utf_16be.$(OBJEXT): internal/dosish.h
+enc/utf_16be.$(OBJEXT): internal/error.h
+enc/utf_16be.$(OBJEXT): internal/eval.h
+enc/utf_16be.$(OBJEXT): internal/event.h
+enc/utf_16be.$(OBJEXT): internal/fl_type.h
+enc/utf_16be.$(OBJEXT): internal/gc.h
+enc/utf_16be.$(OBJEXT): internal/glob.h
+enc/utf_16be.$(OBJEXT): internal/globals.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
@@ -5898,34 +8994,116 @@ 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/intern/array.h
+enc/utf_16be.$(OBJEXT): internal/intern/bignum.h
+enc/utf_16be.$(OBJEXT): internal/intern/class.h
+enc/utf_16be.$(OBJEXT): internal/intern/compar.h
+enc/utf_16be.$(OBJEXT): internal/intern/complex.h
+enc/utf_16be.$(OBJEXT): internal/intern/cont.h
+enc/utf_16be.$(OBJEXT): internal/intern/dir.h
+enc/utf_16be.$(OBJEXT): internal/intern/enum.h
+enc/utf_16be.$(OBJEXT): internal/intern/enumerator.h
+enc/utf_16be.$(OBJEXT): internal/intern/error.h
+enc/utf_16be.$(OBJEXT): internal/intern/eval.h
+enc/utf_16be.$(OBJEXT): internal/intern/file.h
+enc/utf_16be.$(OBJEXT): internal/intern/gc.h
+enc/utf_16be.$(OBJEXT): internal/intern/hash.h
+enc/utf_16be.$(OBJEXT): internal/intern/io.h
+enc/utf_16be.$(OBJEXT): internal/intern/load.h
+enc/utf_16be.$(OBJEXT): internal/intern/marshal.h
+enc/utf_16be.$(OBJEXT): internal/intern/numeric.h
+enc/utf_16be.$(OBJEXT): internal/intern/object.h
+enc/utf_16be.$(OBJEXT): internal/intern/parse.h
+enc/utf_16be.$(OBJEXT): internal/intern/proc.h
+enc/utf_16be.$(OBJEXT): internal/intern/process.h
+enc/utf_16be.$(OBJEXT): internal/intern/random.h
+enc/utf_16be.$(OBJEXT): internal/intern/range.h
+enc/utf_16be.$(OBJEXT): internal/intern/rational.h
+enc/utf_16be.$(OBJEXT): internal/intern/re.h
+enc/utf_16be.$(OBJEXT): internal/intern/ruby.h
+enc/utf_16be.$(OBJEXT): internal/intern/select.h
+enc/utf_16be.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_16be.$(OBJEXT): internal/intern/signal.h
+enc/utf_16be.$(OBJEXT): internal/intern/sprintf.h
+enc/utf_16be.$(OBJEXT): internal/intern/string.h
+enc/utf_16be.$(OBJEXT): internal/intern/struct.h
+enc/utf_16be.$(OBJEXT): internal/intern/thread.h
+enc/utf_16be.$(OBJEXT): internal/intern/time.h
+enc/utf_16be.$(OBJEXT): internal/intern/variable.h
+enc/utf_16be.$(OBJEXT): internal/intern/vm.h
+enc/utf_16be.$(OBJEXT): internal/interpreter.h
+enc/utf_16be.$(OBJEXT): internal/iterator.h
+enc/utf_16be.$(OBJEXT): internal/memory.h
+enc/utf_16be.$(OBJEXT): internal/method.h
+enc/utf_16be.$(OBJEXT): internal/module.h
+enc/utf_16be.$(OBJEXT): internal/newobj.h
+enc/utf_16be.$(OBJEXT): internal/rgengc.h
+enc/utf_16be.$(OBJEXT): internal/scan_args.h
+enc/utf_16be.$(OBJEXT): internal/special_consts.h
+enc/utf_16be.$(OBJEXT): internal/static_assert.h
enc/utf_16be.$(OBJEXT): internal/stdalign.h
enc/utf_16be.$(OBJEXT): internal/stdbool.h
+enc/utf_16be.$(OBJEXT): internal/symbol.h
+enc/utf_16be.$(OBJEXT): internal/value.h
+enc/utf_16be.$(OBJEXT): internal/value_type.h
+enc/utf_16be.$(OBJEXT): internal/variable.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
-enc/utf_16be.$(OBJEXT): enc/utf_16be.c
enc/utf_16be.$(OBJEXT): missing.h
enc/utf_16be.$(OBJEXT): onigmo.h
+enc/utf_16be.$(OBJEXT): st.h
+enc/utf_16be.$(OBJEXT): subst.h
+enc/utf_16le.$(OBJEXT): $(hdrdir)/ruby.h
+enc/utf_16le.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/utf_16le.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_16le.$(OBJEXT): assert.h
+enc/utf_16le.$(OBJEXT): backward.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/inttypes.h
+enc/utf_16le.$(OBJEXT): backward/2/limits.h
+enc/utf_16le.$(OBJEXT): backward/2/long_long.h
+enc/utf_16le.$(OBJEXT): backward/2/stdalign.h
+enc/utf_16le.$(OBJEXT): backward/2/stdarg.h
+enc/utf_16le.$(OBJEXT): config.h
+enc/utf_16le.$(OBJEXT): defines.h
+enc/utf_16le.$(OBJEXT): enc/iso_8859.h
+enc/utf_16le.$(OBJEXT): enc/utf_16le.c
+enc/utf_16le.$(OBJEXT): intern.h
+enc/utf_16le.$(OBJEXT): internal/abi.h
+enc/utf_16le.$(OBJEXT): internal/anyargs.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/char.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/double.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/int.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/long.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/long_long.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/off_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/short.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/size_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/utf_16le.$(OBJEXT): internal/arithmetic/uid_t.h
enc/utf_16le.$(OBJEXT): internal/assume.h
enc/utf_16le.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_16le.$(OBJEXT): internal/attr/artificial.h
enc/utf_16le.$(OBJEXT): internal/attr/cold.h
enc/utf_16le.$(OBJEXT): internal/attr/const.h
+enc/utf_16le.$(OBJEXT): internal/attr/constexpr.h
enc/utf_16le.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_16le.$(OBJEXT): internal/attr/diagnose_if.h
+enc/utf_16le.$(OBJEXT): internal/attr/enum_extensibility.h
enc/utf_16le.$(OBJEXT): internal/attr/error.h
+enc/utf_16le.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -5935,6 +9113,7 @@ 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/attr/weakref.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
@@ -5945,8 +9124,30 @@ 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/constant_p.h
+enc/utf_16le.$(OBJEXT): internal/core.h
+enc/utf_16le.$(OBJEXT): internal/core/rarray.h
+enc/utf_16le.$(OBJEXT): internal/core/rbasic.h
+enc/utf_16le.$(OBJEXT): internal/core/rbignum.h
+enc/utf_16le.$(OBJEXT): internal/core/rclass.h
+enc/utf_16le.$(OBJEXT): internal/core/rdata.h
+enc/utf_16le.$(OBJEXT): internal/core/rfile.h
+enc/utf_16le.$(OBJEXT): internal/core/rhash.h
+enc/utf_16le.$(OBJEXT): internal/core/robject.h
+enc/utf_16le.$(OBJEXT): internal/core/rregexp.h
+enc/utf_16le.$(OBJEXT): internal/core/rstring.h
+enc/utf_16le.$(OBJEXT): internal/core/rstruct.h
+enc/utf_16le.$(OBJEXT): internal/core/rtypeddata.h
+enc/utf_16le.$(OBJEXT): internal/ctype.h
enc/utf_16le.$(OBJEXT): internal/dllexport.h
enc/utf_16le.$(OBJEXT): internal/dosish.h
+enc/utf_16le.$(OBJEXT): internal/error.h
+enc/utf_16le.$(OBJEXT): internal/eval.h
+enc/utf_16le.$(OBJEXT): internal/event.h
+enc/utf_16le.$(OBJEXT): internal/fl_type.h
+enc/utf_16le.$(OBJEXT): internal/gc.h
+enc/utf_16le.$(OBJEXT): internal/glob.h
+enc/utf_16le.$(OBJEXT): internal/globals.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
@@ -5955,34 +9156,116 @@ 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/intern/array.h
+enc/utf_16le.$(OBJEXT): internal/intern/bignum.h
+enc/utf_16le.$(OBJEXT): internal/intern/class.h
+enc/utf_16le.$(OBJEXT): internal/intern/compar.h
+enc/utf_16le.$(OBJEXT): internal/intern/complex.h
+enc/utf_16le.$(OBJEXT): internal/intern/cont.h
+enc/utf_16le.$(OBJEXT): internal/intern/dir.h
+enc/utf_16le.$(OBJEXT): internal/intern/enum.h
+enc/utf_16le.$(OBJEXT): internal/intern/enumerator.h
+enc/utf_16le.$(OBJEXT): internal/intern/error.h
+enc/utf_16le.$(OBJEXT): internal/intern/eval.h
+enc/utf_16le.$(OBJEXT): internal/intern/file.h
+enc/utf_16le.$(OBJEXT): internal/intern/gc.h
+enc/utf_16le.$(OBJEXT): internal/intern/hash.h
+enc/utf_16le.$(OBJEXT): internal/intern/io.h
+enc/utf_16le.$(OBJEXT): internal/intern/load.h
+enc/utf_16le.$(OBJEXT): internal/intern/marshal.h
+enc/utf_16le.$(OBJEXT): internal/intern/numeric.h
+enc/utf_16le.$(OBJEXT): internal/intern/object.h
+enc/utf_16le.$(OBJEXT): internal/intern/parse.h
+enc/utf_16le.$(OBJEXT): internal/intern/proc.h
+enc/utf_16le.$(OBJEXT): internal/intern/process.h
+enc/utf_16le.$(OBJEXT): internal/intern/random.h
+enc/utf_16le.$(OBJEXT): internal/intern/range.h
+enc/utf_16le.$(OBJEXT): internal/intern/rational.h
+enc/utf_16le.$(OBJEXT): internal/intern/re.h
+enc/utf_16le.$(OBJEXT): internal/intern/ruby.h
+enc/utf_16le.$(OBJEXT): internal/intern/select.h
+enc/utf_16le.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_16le.$(OBJEXT): internal/intern/signal.h
+enc/utf_16le.$(OBJEXT): internal/intern/sprintf.h
+enc/utf_16le.$(OBJEXT): internal/intern/string.h
+enc/utf_16le.$(OBJEXT): internal/intern/struct.h
+enc/utf_16le.$(OBJEXT): internal/intern/thread.h
+enc/utf_16le.$(OBJEXT): internal/intern/time.h
+enc/utf_16le.$(OBJEXT): internal/intern/variable.h
+enc/utf_16le.$(OBJEXT): internal/intern/vm.h
+enc/utf_16le.$(OBJEXT): internal/interpreter.h
+enc/utf_16le.$(OBJEXT): internal/iterator.h
+enc/utf_16le.$(OBJEXT): internal/memory.h
+enc/utf_16le.$(OBJEXT): internal/method.h
+enc/utf_16le.$(OBJEXT): internal/module.h
+enc/utf_16le.$(OBJEXT): internal/newobj.h
+enc/utf_16le.$(OBJEXT): internal/rgengc.h
+enc/utf_16le.$(OBJEXT): internal/scan_args.h
+enc/utf_16le.$(OBJEXT): internal/special_consts.h
+enc/utf_16le.$(OBJEXT): internal/static_assert.h
enc/utf_16le.$(OBJEXT): internal/stdalign.h
enc/utf_16le.$(OBJEXT): internal/stdbool.h
+enc/utf_16le.$(OBJEXT): internal/symbol.h
+enc/utf_16le.$(OBJEXT): internal/value.h
+enc/utf_16le.$(OBJEXT): internal/value_type.h
+enc/utf_16le.$(OBJEXT): internal/variable.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
-enc/utf_16le.$(OBJEXT): enc/utf_16le.c
enc/utf_16le.$(OBJEXT): missing.h
enc/utf_16le.$(OBJEXT): onigmo.h
+enc/utf_16le.$(OBJEXT): st.h
+enc/utf_16le.$(OBJEXT): subst.h
+enc/utf_32be.$(OBJEXT): $(hdrdir)/ruby.h
+enc/utf_32be.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/utf_32be.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_32be.$(OBJEXT): assert.h
+enc/utf_32be.$(OBJEXT): backward.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/inttypes.h
+enc/utf_32be.$(OBJEXT): backward/2/limits.h
+enc/utf_32be.$(OBJEXT): backward/2/long_long.h
+enc/utf_32be.$(OBJEXT): backward/2/stdalign.h
+enc/utf_32be.$(OBJEXT): backward/2/stdarg.h
+enc/utf_32be.$(OBJEXT): config.h
+enc/utf_32be.$(OBJEXT): defines.h
+enc/utf_32be.$(OBJEXT): enc/iso_8859.h
+enc/utf_32be.$(OBJEXT): enc/utf_32be.c
+enc/utf_32be.$(OBJEXT): intern.h
+enc/utf_32be.$(OBJEXT): internal/abi.h
+enc/utf_32be.$(OBJEXT): internal/anyargs.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/char.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/double.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/int.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/long.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/long_long.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/off_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/short.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/size_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/utf_32be.$(OBJEXT): internal/arithmetic/uid_t.h
enc/utf_32be.$(OBJEXT): internal/assume.h
enc/utf_32be.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_32be.$(OBJEXT): internal/attr/artificial.h
enc/utf_32be.$(OBJEXT): internal/attr/cold.h
enc/utf_32be.$(OBJEXT): internal/attr/const.h
+enc/utf_32be.$(OBJEXT): internal/attr/constexpr.h
enc/utf_32be.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_32be.$(OBJEXT): internal/attr/diagnose_if.h
+enc/utf_32be.$(OBJEXT): internal/attr/enum_extensibility.h
enc/utf_32be.$(OBJEXT): internal/attr/error.h
+enc/utf_32be.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -5992,6 +9275,7 @@ 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/attr/weakref.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
@@ -6002,8 +9286,30 @@ 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/constant_p.h
+enc/utf_32be.$(OBJEXT): internal/core.h
+enc/utf_32be.$(OBJEXT): internal/core/rarray.h
+enc/utf_32be.$(OBJEXT): internal/core/rbasic.h
+enc/utf_32be.$(OBJEXT): internal/core/rbignum.h
+enc/utf_32be.$(OBJEXT): internal/core/rclass.h
+enc/utf_32be.$(OBJEXT): internal/core/rdata.h
+enc/utf_32be.$(OBJEXT): internal/core/rfile.h
+enc/utf_32be.$(OBJEXT): internal/core/rhash.h
+enc/utf_32be.$(OBJEXT): internal/core/robject.h
+enc/utf_32be.$(OBJEXT): internal/core/rregexp.h
+enc/utf_32be.$(OBJEXT): internal/core/rstring.h
+enc/utf_32be.$(OBJEXT): internal/core/rstruct.h
+enc/utf_32be.$(OBJEXT): internal/core/rtypeddata.h
+enc/utf_32be.$(OBJEXT): internal/ctype.h
enc/utf_32be.$(OBJEXT): internal/dllexport.h
enc/utf_32be.$(OBJEXT): internal/dosish.h
+enc/utf_32be.$(OBJEXT): internal/error.h
+enc/utf_32be.$(OBJEXT): internal/eval.h
+enc/utf_32be.$(OBJEXT): internal/event.h
+enc/utf_32be.$(OBJEXT): internal/fl_type.h
+enc/utf_32be.$(OBJEXT): internal/gc.h
+enc/utf_32be.$(OBJEXT): internal/glob.h
+enc/utf_32be.$(OBJEXT): internal/globals.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
@@ -6012,34 +9318,116 @@ 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/intern/array.h
+enc/utf_32be.$(OBJEXT): internal/intern/bignum.h
+enc/utf_32be.$(OBJEXT): internal/intern/class.h
+enc/utf_32be.$(OBJEXT): internal/intern/compar.h
+enc/utf_32be.$(OBJEXT): internal/intern/complex.h
+enc/utf_32be.$(OBJEXT): internal/intern/cont.h
+enc/utf_32be.$(OBJEXT): internal/intern/dir.h
+enc/utf_32be.$(OBJEXT): internal/intern/enum.h
+enc/utf_32be.$(OBJEXT): internal/intern/enumerator.h
+enc/utf_32be.$(OBJEXT): internal/intern/error.h
+enc/utf_32be.$(OBJEXT): internal/intern/eval.h
+enc/utf_32be.$(OBJEXT): internal/intern/file.h
+enc/utf_32be.$(OBJEXT): internal/intern/gc.h
+enc/utf_32be.$(OBJEXT): internal/intern/hash.h
+enc/utf_32be.$(OBJEXT): internal/intern/io.h
+enc/utf_32be.$(OBJEXT): internal/intern/load.h
+enc/utf_32be.$(OBJEXT): internal/intern/marshal.h
+enc/utf_32be.$(OBJEXT): internal/intern/numeric.h
+enc/utf_32be.$(OBJEXT): internal/intern/object.h
+enc/utf_32be.$(OBJEXT): internal/intern/parse.h
+enc/utf_32be.$(OBJEXT): internal/intern/proc.h
+enc/utf_32be.$(OBJEXT): internal/intern/process.h
+enc/utf_32be.$(OBJEXT): internal/intern/random.h
+enc/utf_32be.$(OBJEXT): internal/intern/range.h
+enc/utf_32be.$(OBJEXT): internal/intern/rational.h
+enc/utf_32be.$(OBJEXT): internal/intern/re.h
+enc/utf_32be.$(OBJEXT): internal/intern/ruby.h
+enc/utf_32be.$(OBJEXT): internal/intern/select.h
+enc/utf_32be.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_32be.$(OBJEXT): internal/intern/signal.h
+enc/utf_32be.$(OBJEXT): internal/intern/sprintf.h
+enc/utf_32be.$(OBJEXT): internal/intern/string.h
+enc/utf_32be.$(OBJEXT): internal/intern/struct.h
+enc/utf_32be.$(OBJEXT): internal/intern/thread.h
+enc/utf_32be.$(OBJEXT): internal/intern/time.h
+enc/utf_32be.$(OBJEXT): internal/intern/variable.h
+enc/utf_32be.$(OBJEXT): internal/intern/vm.h
+enc/utf_32be.$(OBJEXT): internal/interpreter.h
+enc/utf_32be.$(OBJEXT): internal/iterator.h
+enc/utf_32be.$(OBJEXT): internal/memory.h
+enc/utf_32be.$(OBJEXT): internal/method.h
+enc/utf_32be.$(OBJEXT): internal/module.h
+enc/utf_32be.$(OBJEXT): internal/newobj.h
+enc/utf_32be.$(OBJEXT): internal/rgengc.h
+enc/utf_32be.$(OBJEXT): internal/scan_args.h
+enc/utf_32be.$(OBJEXT): internal/special_consts.h
+enc/utf_32be.$(OBJEXT): internal/static_assert.h
enc/utf_32be.$(OBJEXT): internal/stdalign.h
enc/utf_32be.$(OBJEXT): internal/stdbool.h
+enc/utf_32be.$(OBJEXT): internal/symbol.h
+enc/utf_32be.$(OBJEXT): internal/value.h
+enc/utf_32be.$(OBJEXT): internal/value_type.h
+enc/utf_32be.$(OBJEXT): internal/variable.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
-enc/utf_32be.$(OBJEXT): enc/utf_32be.c
enc/utf_32be.$(OBJEXT): missing.h
enc/utf_32be.$(OBJEXT): onigmo.h
+enc/utf_32be.$(OBJEXT): st.h
+enc/utf_32be.$(OBJEXT): subst.h
+enc/utf_32le.$(OBJEXT): $(hdrdir)/ruby.h
+enc/utf_32le.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/utf_32le.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_32le.$(OBJEXT): assert.h
+enc/utf_32le.$(OBJEXT): backward.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/inttypes.h
+enc/utf_32le.$(OBJEXT): backward/2/limits.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): intern.h
+enc/utf_32le.$(OBJEXT): internal/abi.h
+enc/utf_32le.$(OBJEXT): internal/anyargs.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/char.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/double.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/int.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/long.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/long_long.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/off_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/short.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/size_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/utf_32le.$(OBJEXT): internal/arithmetic/uid_t.h
enc/utf_32le.$(OBJEXT): internal/assume.h
enc/utf_32le.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_32le.$(OBJEXT): internal/attr/artificial.h
enc/utf_32le.$(OBJEXT): internal/attr/cold.h
enc/utf_32le.$(OBJEXT): internal/attr/const.h
+enc/utf_32le.$(OBJEXT): internal/attr/constexpr.h
enc/utf_32le.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_32le.$(OBJEXT): internal/attr/diagnose_if.h
+enc/utf_32le.$(OBJEXT): internal/attr/enum_extensibility.h
enc/utf_32le.$(OBJEXT): internal/attr/error.h
+enc/utf_32le.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6049,6 +9437,7 @@ 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/attr/weakref.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
@@ -6059,8 +9448,30 @@ 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/constant_p.h
+enc/utf_32le.$(OBJEXT): internal/core.h
+enc/utf_32le.$(OBJEXT): internal/core/rarray.h
+enc/utf_32le.$(OBJEXT): internal/core/rbasic.h
+enc/utf_32le.$(OBJEXT): internal/core/rbignum.h
+enc/utf_32le.$(OBJEXT): internal/core/rclass.h
+enc/utf_32le.$(OBJEXT): internal/core/rdata.h
+enc/utf_32le.$(OBJEXT): internal/core/rfile.h
+enc/utf_32le.$(OBJEXT): internal/core/rhash.h
+enc/utf_32le.$(OBJEXT): internal/core/robject.h
+enc/utf_32le.$(OBJEXT): internal/core/rregexp.h
+enc/utf_32le.$(OBJEXT): internal/core/rstring.h
+enc/utf_32le.$(OBJEXT): internal/core/rstruct.h
+enc/utf_32le.$(OBJEXT): internal/core/rtypeddata.h
+enc/utf_32le.$(OBJEXT): internal/ctype.h
enc/utf_32le.$(OBJEXT): internal/dllexport.h
enc/utf_32le.$(OBJEXT): internal/dosish.h
+enc/utf_32le.$(OBJEXT): internal/error.h
+enc/utf_32le.$(OBJEXT): internal/eval.h
+enc/utf_32le.$(OBJEXT): internal/event.h
+enc/utf_32le.$(OBJEXT): internal/fl_type.h
+enc/utf_32le.$(OBJEXT): internal/gc.h
+enc/utf_32le.$(OBJEXT): internal/glob.h
+enc/utf_32le.$(OBJEXT): internal/globals.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
@@ -6069,27 +9480,84 @@ 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/intern/array.h
+enc/utf_32le.$(OBJEXT): internal/intern/bignum.h
+enc/utf_32le.$(OBJEXT): internal/intern/class.h
+enc/utf_32le.$(OBJEXT): internal/intern/compar.h
+enc/utf_32le.$(OBJEXT): internal/intern/complex.h
+enc/utf_32le.$(OBJEXT): internal/intern/cont.h
+enc/utf_32le.$(OBJEXT): internal/intern/dir.h
+enc/utf_32le.$(OBJEXT): internal/intern/enum.h
+enc/utf_32le.$(OBJEXT): internal/intern/enumerator.h
+enc/utf_32le.$(OBJEXT): internal/intern/error.h
+enc/utf_32le.$(OBJEXT): internal/intern/eval.h
+enc/utf_32le.$(OBJEXT): internal/intern/file.h
+enc/utf_32le.$(OBJEXT): internal/intern/gc.h
+enc/utf_32le.$(OBJEXT): internal/intern/hash.h
+enc/utf_32le.$(OBJEXT): internal/intern/io.h
+enc/utf_32le.$(OBJEXT): internal/intern/load.h
+enc/utf_32le.$(OBJEXT): internal/intern/marshal.h
+enc/utf_32le.$(OBJEXT): internal/intern/numeric.h
+enc/utf_32le.$(OBJEXT): internal/intern/object.h
+enc/utf_32le.$(OBJEXT): internal/intern/parse.h
+enc/utf_32le.$(OBJEXT): internal/intern/proc.h
+enc/utf_32le.$(OBJEXT): internal/intern/process.h
+enc/utf_32le.$(OBJEXT): internal/intern/random.h
+enc/utf_32le.$(OBJEXT): internal/intern/range.h
+enc/utf_32le.$(OBJEXT): internal/intern/rational.h
+enc/utf_32le.$(OBJEXT): internal/intern/re.h
+enc/utf_32le.$(OBJEXT): internal/intern/ruby.h
+enc/utf_32le.$(OBJEXT): internal/intern/select.h
+enc/utf_32le.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_32le.$(OBJEXT): internal/intern/signal.h
+enc/utf_32le.$(OBJEXT): internal/intern/sprintf.h
+enc/utf_32le.$(OBJEXT): internal/intern/string.h
+enc/utf_32le.$(OBJEXT): internal/intern/struct.h
+enc/utf_32le.$(OBJEXT): internal/intern/thread.h
+enc/utf_32le.$(OBJEXT): internal/intern/time.h
+enc/utf_32le.$(OBJEXT): internal/intern/variable.h
+enc/utf_32le.$(OBJEXT): internal/intern/vm.h
+enc/utf_32le.$(OBJEXT): internal/interpreter.h
+enc/utf_32le.$(OBJEXT): internal/iterator.h
+enc/utf_32le.$(OBJEXT): internal/memory.h
+enc/utf_32le.$(OBJEXT): internal/method.h
+enc/utf_32le.$(OBJEXT): internal/module.h
+enc/utf_32le.$(OBJEXT): internal/newobj.h
+enc/utf_32le.$(OBJEXT): internal/rgengc.h
+enc/utf_32le.$(OBJEXT): internal/scan_args.h
+enc/utf_32le.$(OBJEXT): internal/special_consts.h
+enc/utf_32le.$(OBJEXT): internal/static_assert.h
enc/utf_32le.$(OBJEXT): internal/stdalign.h
enc/utf_32le.$(OBJEXT): internal/stdbool.h
+enc/utf_32le.$(OBJEXT): internal/symbol.h
+enc/utf_32le.$(OBJEXT): internal/value.h
+enc/utf_32le.$(OBJEXT): internal/value_type.h
+enc/utf_32le.$(OBJEXT): internal/variable.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_32le.$(OBJEXT): st.h
+enc/utf_32le.$(OBJEXT): subst.h
+enc/utf_8.$(OBJEXT): $(hdrdir)/ruby.h
enc/utf_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/utf_8.$(OBJEXT): $(top_srcdir)/encindex.h
enc/utf_8.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_8.$(OBJEXT): assert.h
+enc/utf_8.$(OBJEXT): backward/2/assume.h
+enc/utf_8.$(OBJEXT): backward/2/attributes.h
+enc/utf_8.$(OBJEXT): backward/2/bool.h
+enc/utf_8.$(OBJEXT): backward/2/inttypes.h
+enc/utf_8.$(OBJEXT): backward/2/limits.h
+enc/utf_8.$(OBJEXT): backward/2/long_long.h
+enc/utf_8.$(OBJEXT): backward/2/stdalign.h
+enc/utf_8.$(OBJEXT): backward/2/stdarg.h
+enc/utf_8.$(OBJEXT): config.h
+enc/utf_8.$(OBJEXT): defines.h
+enc/utf_8.$(OBJEXT): enc/utf_8.c
+enc/utf_8.$(OBJEXT): encoding.h
+enc/utf_8.$(OBJEXT): intern.h
+enc/utf_8.$(OBJEXT): internal/abi.h
enc/utf_8.$(OBJEXT): internal/anyargs.h
enc/utf_8.$(OBJEXT): internal/arithmetic.h
enc/utf_8.$(OBJEXT): internal/arithmetic/char.h
@@ -6159,6 +9627,15 @@ enc/utf_8.$(OBJEXT): internal/core/rtypeddata.h
enc/utf_8.$(OBJEXT): internal/ctype.h
enc/utf_8.$(OBJEXT): internal/dllexport.h
enc/utf_8.$(OBJEXT): internal/dosish.h
+enc/utf_8.$(OBJEXT): internal/encoding/coderange.h
+enc/utf_8.$(OBJEXT): internal/encoding/ctype.h
+enc/utf_8.$(OBJEXT): internal/encoding/encoding.h
+enc/utf_8.$(OBJEXT): internal/encoding/pathname.h
+enc/utf_8.$(OBJEXT): internal/encoding/re.h
+enc/utf_8.$(OBJEXT): internal/encoding/sprintf.h
+enc/utf_8.$(OBJEXT): internal/encoding/string.h
+enc/utf_8.$(OBJEXT): internal/encoding/symbol.h
+enc/utf_8.$(OBJEXT): internal/encoding/transcode.h
enc/utf_8.$(OBJEXT): internal/error.h
enc/utf_8.$(OBJEXT): internal/eval.h
enc/utf_8.$(OBJEXT): internal/event.h
@@ -6229,36 +9706,62 @@ 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): $(hdrdir)/ruby.h
+enc/windows_1250.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_1250.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1250.$(OBJEXT): assert.h
+enc/windows_1250.$(OBJEXT): backward.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/inttypes.h
+enc/windows_1250.$(OBJEXT): backward/2/limits.h
+enc/windows_1250.$(OBJEXT): backward/2/long_long.h
+enc/windows_1250.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1250.$(OBJEXT): backward/2/stdarg.h
+enc/windows_1250.$(OBJEXT): config.h
+enc/windows_1250.$(OBJEXT): defines.h
+enc/windows_1250.$(OBJEXT): enc/iso_8859.h
+enc/windows_1250.$(OBJEXT): enc/windows_1250.c
+enc/windows_1250.$(OBJEXT): intern.h
+enc/windows_1250.$(OBJEXT): internal/abi.h
+enc/windows_1250.$(OBJEXT): internal/anyargs.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_1250.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_1250.$(OBJEXT): internal/assume.h
enc/windows_1250.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1250.$(OBJEXT): internal/attr/artificial.h
enc/windows_1250.$(OBJEXT): internal/attr/cold.h
enc/windows_1250.$(OBJEXT): internal/attr/const.h
+enc/windows_1250.$(OBJEXT): internal/attr/constexpr.h
enc/windows_1250.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1250.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_1250.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_1250.$(OBJEXT): internal/attr/error.h
+enc/windows_1250.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6268,6 +9771,7 @@ 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/attr/weakref.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
@@ -6278,8 +9782,30 @@ 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/constant_p.h
+enc/windows_1250.$(OBJEXT): internal/core.h
+enc/windows_1250.$(OBJEXT): internal/core/rarray.h
+enc/windows_1250.$(OBJEXT): internal/core/rbasic.h
+enc/windows_1250.$(OBJEXT): internal/core/rbignum.h
+enc/windows_1250.$(OBJEXT): internal/core/rclass.h
+enc/windows_1250.$(OBJEXT): internal/core/rdata.h
+enc/windows_1250.$(OBJEXT): internal/core/rfile.h
+enc/windows_1250.$(OBJEXT): internal/core/rhash.h
+enc/windows_1250.$(OBJEXT): internal/core/robject.h
+enc/windows_1250.$(OBJEXT): internal/core/rregexp.h
+enc/windows_1250.$(OBJEXT): internal/core/rstring.h
+enc/windows_1250.$(OBJEXT): internal/core/rstruct.h
+enc/windows_1250.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_1250.$(OBJEXT): internal/ctype.h
enc/windows_1250.$(OBJEXT): internal/dllexport.h
enc/windows_1250.$(OBJEXT): internal/dosish.h
+enc/windows_1250.$(OBJEXT): internal/error.h
+enc/windows_1250.$(OBJEXT): internal/eval.h
+enc/windows_1250.$(OBJEXT): internal/event.h
+enc/windows_1250.$(OBJEXT): internal/fl_type.h
+enc/windows_1250.$(OBJEXT): internal/gc.h
+enc/windows_1250.$(OBJEXT): internal/glob.h
+enc/windows_1250.$(OBJEXT): internal/globals.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
@@ -6288,34 +9814,115 @@ 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/intern/array.h
+enc/windows_1250.$(OBJEXT): internal/intern/bignum.h
+enc/windows_1250.$(OBJEXT): internal/intern/class.h
+enc/windows_1250.$(OBJEXT): internal/intern/compar.h
+enc/windows_1250.$(OBJEXT): internal/intern/complex.h
+enc/windows_1250.$(OBJEXT): internal/intern/cont.h
+enc/windows_1250.$(OBJEXT): internal/intern/dir.h
+enc/windows_1250.$(OBJEXT): internal/intern/enum.h
+enc/windows_1250.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_1250.$(OBJEXT): internal/intern/error.h
+enc/windows_1250.$(OBJEXT): internal/intern/eval.h
+enc/windows_1250.$(OBJEXT): internal/intern/file.h
+enc/windows_1250.$(OBJEXT): internal/intern/gc.h
+enc/windows_1250.$(OBJEXT): internal/intern/hash.h
+enc/windows_1250.$(OBJEXT): internal/intern/io.h
+enc/windows_1250.$(OBJEXT): internal/intern/load.h
+enc/windows_1250.$(OBJEXT): internal/intern/marshal.h
+enc/windows_1250.$(OBJEXT): internal/intern/numeric.h
+enc/windows_1250.$(OBJEXT): internal/intern/object.h
+enc/windows_1250.$(OBJEXT): internal/intern/parse.h
+enc/windows_1250.$(OBJEXT): internal/intern/proc.h
+enc/windows_1250.$(OBJEXT): internal/intern/process.h
+enc/windows_1250.$(OBJEXT): internal/intern/random.h
+enc/windows_1250.$(OBJEXT): internal/intern/range.h
+enc/windows_1250.$(OBJEXT): internal/intern/rational.h
+enc/windows_1250.$(OBJEXT): internal/intern/re.h
+enc/windows_1250.$(OBJEXT): internal/intern/ruby.h
+enc/windows_1250.$(OBJEXT): internal/intern/select.h
+enc/windows_1250.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1250.$(OBJEXT): internal/intern/signal.h
+enc/windows_1250.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_1250.$(OBJEXT): internal/intern/string.h
+enc/windows_1250.$(OBJEXT): internal/intern/struct.h
+enc/windows_1250.$(OBJEXT): internal/intern/thread.h
+enc/windows_1250.$(OBJEXT): internal/intern/time.h
+enc/windows_1250.$(OBJEXT): internal/intern/variable.h
+enc/windows_1250.$(OBJEXT): internal/intern/vm.h
+enc/windows_1250.$(OBJEXT): internal/interpreter.h
+enc/windows_1250.$(OBJEXT): internal/iterator.h
+enc/windows_1250.$(OBJEXT): internal/memory.h
+enc/windows_1250.$(OBJEXT): internal/method.h
+enc/windows_1250.$(OBJEXT): internal/module.h
+enc/windows_1250.$(OBJEXT): internal/newobj.h
+enc/windows_1250.$(OBJEXT): internal/rgengc.h
+enc/windows_1250.$(OBJEXT): internal/scan_args.h
+enc/windows_1250.$(OBJEXT): internal/special_consts.h
+enc/windows_1250.$(OBJEXT): internal/static_assert.h
enc/windows_1250.$(OBJEXT): internal/stdalign.h
enc/windows_1250.$(OBJEXT): internal/stdbool.h
+enc/windows_1250.$(OBJEXT): internal/symbol.h
+enc/windows_1250.$(OBJEXT): internal/value.h
+enc/windows_1250.$(OBJEXT): internal/value_type.h
+enc/windows_1250.$(OBJEXT): internal/variable.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
-enc/windows_1250.$(OBJEXT): enc/windows_1250.c
enc/windows_1250.$(OBJEXT): missing.h
enc/windows_1250.$(OBJEXT): onigmo.h
+enc/windows_1250.$(OBJEXT): st.h
+enc/windows_1250.$(OBJEXT): subst.h
+enc/windows_1251.$(OBJEXT): $(hdrdir)/ruby.h
+enc/windows_1251.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_1251.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1251.$(OBJEXT): assert.h
+enc/windows_1251.$(OBJEXT): backward.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/inttypes.h
+enc/windows_1251.$(OBJEXT): backward/2/limits.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): intern.h
+enc/windows_1251.$(OBJEXT): internal/abi.h
+enc/windows_1251.$(OBJEXT): internal/anyargs.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_1251.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_1251.$(OBJEXT): internal/assume.h
enc/windows_1251.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1251.$(OBJEXT): internal/attr/artificial.h
enc/windows_1251.$(OBJEXT): internal/attr/cold.h
enc/windows_1251.$(OBJEXT): internal/attr/const.h
+enc/windows_1251.$(OBJEXT): internal/attr/constexpr.h
enc/windows_1251.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1251.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_1251.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_1251.$(OBJEXT): internal/attr/error.h
+enc/windows_1251.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6325,6 +9932,7 @@ 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/attr/weakref.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
@@ -6335,8 +9943,30 @@ 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/constant_p.h
+enc/windows_1251.$(OBJEXT): internal/core.h
+enc/windows_1251.$(OBJEXT): internal/core/rarray.h
+enc/windows_1251.$(OBJEXT): internal/core/rbasic.h
+enc/windows_1251.$(OBJEXT): internal/core/rbignum.h
+enc/windows_1251.$(OBJEXT): internal/core/rclass.h
+enc/windows_1251.$(OBJEXT): internal/core/rdata.h
+enc/windows_1251.$(OBJEXT): internal/core/rfile.h
+enc/windows_1251.$(OBJEXT): internal/core/rhash.h
+enc/windows_1251.$(OBJEXT): internal/core/robject.h
+enc/windows_1251.$(OBJEXT): internal/core/rregexp.h
+enc/windows_1251.$(OBJEXT): internal/core/rstring.h
+enc/windows_1251.$(OBJEXT): internal/core/rstruct.h
+enc/windows_1251.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_1251.$(OBJEXT): internal/ctype.h
enc/windows_1251.$(OBJEXT): internal/dllexport.h
enc/windows_1251.$(OBJEXT): internal/dosish.h
+enc/windows_1251.$(OBJEXT): internal/error.h
+enc/windows_1251.$(OBJEXT): internal/eval.h
+enc/windows_1251.$(OBJEXT): internal/event.h
+enc/windows_1251.$(OBJEXT): internal/fl_type.h
+enc/windows_1251.$(OBJEXT): internal/gc.h
+enc/windows_1251.$(OBJEXT): internal/glob.h
+enc/windows_1251.$(OBJEXT): internal/globals.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
@@ -6345,33 +9975,116 @@ 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/intern/array.h
+enc/windows_1251.$(OBJEXT): internal/intern/bignum.h
+enc/windows_1251.$(OBJEXT): internal/intern/class.h
+enc/windows_1251.$(OBJEXT): internal/intern/compar.h
+enc/windows_1251.$(OBJEXT): internal/intern/complex.h
+enc/windows_1251.$(OBJEXT): internal/intern/cont.h
+enc/windows_1251.$(OBJEXT): internal/intern/dir.h
+enc/windows_1251.$(OBJEXT): internal/intern/enum.h
+enc/windows_1251.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_1251.$(OBJEXT): internal/intern/error.h
+enc/windows_1251.$(OBJEXT): internal/intern/eval.h
+enc/windows_1251.$(OBJEXT): internal/intern/file.h
+enc/windows_1251.$(OBJEXT): internal/intern/gc.h
+enc/windows_1251.$(OBJEXT): internal/intern/hash.h
+enc/windows_1251.$(OBJEXT): internal/intern/io.h
+enc/windows_1251.$(OBJEXT): internal/intern/load.h
+enc/windows_1251.$(OBJEXT): internal/intern/marshal.h
+enc/windows_1251.$(OBJEXT): internal/intern/numeric.h
+enc/windows_1251.$(OBJEXT): internal/intern/object.h
+enc/windows_1251.$(OBJEXT): internal/intern/parse.h
+enc/windows_1251.$(OBJEXT): internal/intern/proc.h
+enc/windows_1251.$(OBJEXT): internal/intern/process.h
+enc/windows_1251.$(OBJEXT): internal/intern/random.h
+enc/windows_1251.$(OBJEXT): internal/intern/range.h
+enc/windows_1251.$(OBJEXT): internal/intern/rational.h
+enc/windows_1251.$(OBJEXT): internal/intern/re.h
+enc/windows_1251.$(OBJEXT): internal/intern/ruby.h
+enc/windows_1251.$(OBJEXT): internal/intern/select.h
+enc/windows_1251.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1251.$(OBJEXT): internal/intern/signal.h
+enc/windows_1251.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_1251.$(OBJEXT): internal/intern/string.h
+enc/windows_1251.$(OBJEXT): internal/intern/struct.h
+enc/windows_1251.$(OBJEXT): internal/intern/thread.h
+enc/windows_1251.$(OBJEXT): internal/intern/time.h
+enc/windows_1251.$(OBJEXT): internal/intern/variable.h
+enc/windows_1251.$(OBJEXT): internal/intern/vm.h
+enc/windows_1251.$(OBJEXT): internal/interpreter.h
+enc/windows_1251.$(OBJEXT): internal/iterator.h
+enc/windows_1251.$(OBJEXT): internal/memory.h
+enc/windows_1251.$(OBJEXT): internal/method.h
+enc/windows_1251.$(OBJEXT): internal/module.h
+enc/windows_1251.$(OBJEXT): internal/newobj.h
+enc/windows_1251.$(OBJEXT): internal/rgengc.h
+enc/windows_1251.$(OBJEXT): internal/scan_args.h
+enc/windows_1251.$(OBJEXT): internal/special_consts.h
+enc/windows_1251.$(OBJEXT): internal/static_assert.h
enc/windows_1251.$(OBJEXT): internal/stdalign.h
enc/windows_1251.$(OBJEXT): internal/stdbool.h
+enc/windows_1251.$(OBJEXT): internal/symbol.h
+enc/windows_1251.$(OBJEXT): internal/value.h
+enc/windows_1251.$(OBJEXT): internal/value_type.h
+enc/windows_1251.$(OBJEXT): internal/variable.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_1251.$(OBJEXT): st.h
+enc/windows_1251.$(OBJEXT): subst.h
+enc/windows_1252.$(OBJEXT): $(hdrdir)/ruby.h
+enc/windows_1252.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_1252.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1252.$(OBJEXT): assert.h
+enc/windows_1252.$(OBJEXT): backward.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/inttypes.h
+enc/windows_1252.$(OBJEXT): backward/2/limits.h
+enc/windows_1252.$(OBJEXT): backward/2/long_long.h
+enc/windows_1252.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1252.$(OBJEXT): backward/2/stdarg.h
+enc/windows_1252.$(OBJEXT): config.h
+enc/windows_1252.$(OBJEXT): defines.h
+enc/windows_1252.$(OBJEXT): enc/iso_8859.h
+enc/windows_1252.$(OBJEXT): enc/windows_1252.c
+enc/windows_1252.$(OBJEXT): intern.h
+enc/windows_1252.$(OBJEXT): internal/abi.h
+enc/windows_1252.$(OBJEXT): internal/anyargs.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_1252.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_1252.$(OBJEXT): internal/assume.h
enc/windows_1252.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1252.$(OBJEXT): internal/attr/artificial.h
enc/windows_1252.$(OBJEXT): internal/attr/cold.h
enc/windows_1252.$(OBJEXT): internal/attr/const.h
+enc/windows_1252.$(OBJEXT): internal/attr/constexpr.h
enc/windows_1252.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1252.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_1252.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_1252.$(OBJEXT): internal/attr/error.h
+enc/windows_1252.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6381,6 +10094,7 @@ 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/attr/weakref.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
@@ -6391,8 +10105,30 @@ 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/constant_p.h
+enc/windows_1252.$(OBJEXT): internal/core.h
+enc/windows_1252.$(OBJEXT): internal/core/rarray.h
+enc/windows_1252.$(OBJEXT): internal/core/rbasic.h
+enc/windows_1252.$(OBJEXT): internal/core/rbignum.h
+enc/windows_1252.$(OBJEXT): internal/core/rclass.h
+enc/windows_1252.$(OBJEXT): internal/core/rdata.h
+enc/windows_1252.$(OBJEXT): internal/core/rfile.h
+enc/windows_1252.$(OBJEXT): internal/core/rhash.h
+enc/windows_1252.$(OBJEXT): internal/core/robject.h
+enc/windows_1252.$(OBJEXT): internal/core/rregexp.h
+enc/windows_1252.$(OBJEXT): internal/core/rstring.h
+enc/windows_1252.$(OBJEXT): internal/core/rstruct.h
+enc/windows_1252.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_1252.$(OBJEXT): internal/ctype.h
enc/windows_1252.$(OBJEXT): internal/dllexport.h
enc/windows_1252.$(OBJEXT): internal/dosish.h
+enc/windows_1252.$(OBJEXT): internal/error.h
+enc/windows_1252.$(OBJEXT): internal/eval.h
+enc/windows_1252.$(OBJEXT): internal/event.h
+enc/windows_1252.$(OBJEXT): internal/fl_type.h
+enc/windows_1252.$(OBJEXT): internal/gc.h
+enc/windows_1252.$(OBJEXT): internal/glob.h
+enc/windows_1252.$(OBJEXT): internal/globals.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
@@ -6401,34 +10137,115 @@ 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/intern/array.h
+enc/windows_1252.$(OBJEXT): internal/intern/bignum.h
+enc/windows_1252.$(OBJEXT): internal/intern/class.h
+enc/windows_1252.$(OBJEXT): internal/intern/compar.h
+enc/windows_1252.$(OBJEXT): internal/intern/complex.h
+enc/windows_1252.$(OBJEXT): internal/intern/cont.h
+enc/windows_1252.$(OBJEXT): internal/intern/dir.h
+enc/windows_1252.$(OBJEXT): internal/intern/enum.h
+enc/windows_1252.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_1252.$(OBJEXT): internal/intern/error.h
+enc/windows_1252.$(OBJEXT): internal/intern/eval.h
+enc/windows_1252.$(OBJEXT): internal/intern/file.h
+enc/windows_1252.$(OBJEXT): internal/intern/gc.h
+enc/windows_1252.$(OBJEXT): internal/intern/hash.h
+enc/windows_1252.$(OBJEXT): internal/intern/io.h
+enc/windows_1252.$(OBJEXT): internal/intern/load.h
+enc/windows_1252.$(OBJEXT): internal/intern/marshal.h
+enc/windows_1252.$(OBJEXT): internal/intern/numeric.h
+enc/windows_1252.$(OBJEXT): internal/intern/object.h
+enc/windows_1252.$(OBJEXT): internal/intern/parse.h
+enc/windows_1252.$(OBJEXT): internal/intern/proc.h
+enc/windows_1252.$(OBJEXT): internal/intern/process.h
+enc/windows_1252.$(OBJEXT): internal/intern/random.h
+enc/windows_1252.$(OBJEXT): internal/intern/range.h
+enc/windows_1252.$(OBJEXT): internal/intern/rational.h
+enc/windows_1252.$(OBJEXT): internal/intern/re.h
+enc/windows_1252.$(OBJEXT): internal/intern/ruby.h
+enc/windows_1252.$(OBJEXT): internal/intern/select.h
+enc/windows_1252.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1252.$(OBJEXT): internal/intern/signal.h
+enc/windows_1252.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_1252.$(OBJEXT): internal/intern/string.h
+enc/windows_1252.$(OBJEXT): internal/intern/struct.h
+enc/windows_1252.$(OBJEXT): internal/intern/thread.h
+enc/windows_1252.$(OBJEXT): internal/intern/time.h
+enc/windows_1252.$(OBJEXT): internal/intern/variable.h
+enc/windows_1252.$(OBJEXT): internal/intern/vm.h
+enc/windows_1252.$(OBJEXT): internal/interpreter.h
+enc/windows_1252.$(OBJEXT): internal/iterator.h
+enc/windows_1252.$(OBJEXT): internal/memory.h
+enc/windows_1252.$(OBJEXT): internal/method.h
+enc/windows_1252.$(OBJEXT): internal/module.h
+enc/windows_1252.$(OBJEXT): internal/newobj.h
+enc/windows_1252.$(OBJEXT): internal/rgengc.h
+enc/windows_1252.$(OBJEXT): internal/scan_args.h
+enc/windows_1252.$(OBJEXT): internal/special_consts.h
+enc/windows_1252.$(OBJEXT): internal/static_assert.h
enc/windows_1252.$(OBJEXT): internal/stdalign.h
enc/windows_1252.$(OBJEXT): internal/stdbool.h
+enc/windows_1252.$(OBJEXT): internal/symbol.h
+enc/windows_1252.$(OBJEXT): internal/value.h
+enc/windows_1252.$(OBJEXT): internal/value_type.h
+enc/windows_1252.$(OBJEXT): internal/variable.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
-enc/windows_1252.$(OBJEXT): enc/windows_1252.c
enc/windows_1252.$(OBJEXT): missing.h
enc/windows_1252.$(OBJEXT): onigmo.h
+enc/windows_1252.$(OBJEXT): st.h
+enc/windows_1252.$(OBJEXT): subst.h
+enc/windows_1253.$(OBJEXT): $(hdrdir)/ruby.h
+enc/windows_1253.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_1253.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1253.$(OBJEXT): assert.h
+enc/windows_1253.$(OBJEXT): backward.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/inttypes.h
+enc/windows_1253.$(OBJEXT): backward/2/limits.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): intern.h
+enc/windows_1253.$(OBJEXT): internal/abi.h
+enc/windows_1253.$(OBJEXT): internal/anyargs.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_1253.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_1253.$(OBJEXT): internal/assume.h
enc/windows_1253.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1253.$(OBJEXT): internal/attr/artificial.h
enc/windows_1253.$(OBJEXT): internal/attr/cold.h
enc/windows_1253.$(OBJEXT): internal/attr/const.h
+enc/windows_1253.$(OBJEXT): internal/attr/constexpr.h
enc/windows_1253.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1253.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_1253.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_1253.$(OBJEXT): internal/attr/error.h
+enc/windows_1253.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6438,6 +10255,7 @@ 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/attr/weakref.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
@@ -6448,8 +10266,30 @@ 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/constant_p.h
+enc/windows_1253.$(OBJEXT): internal/core.h
+enc/windows_1253.$(OBJEXT): internal/core/rarray.h
+enc/windows_1253.$(OBJEXT): internal/core/rbasic.h
+enc/windows_1253.$(OBJEXT): internal/core/rbignum.h
+enc/windows_1253.$(OBJEXT): internal/core/rclass.h
+enc/windows_1253.$(OBJEXT): internal/core/rdata.h
+enc/windows_1253.$(OBJEXT): internal/core/rfile.h
+enc/windows_1253.$(OBJEXT): internal/core/rhash.h
+enc/windows_1253.$(OBJEXT): internal/core/robject.h
+enc/windows_1253.$(OBJEXT): internal/core/rregexp.h
+enc/windows_1253.$(OBJEXT): internal/core/rstring.h
+enc/windows_1253.$(OBJEXT): internal/core/rstruct.h
+enc/windows_1253.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_1253.$(OBJEXT): internal/ctype.h
enc/windows_1253.$(OBJEXT): internal/dllexport.h
enc/windows_1253.$(OBJEXT): internal/dosish.h
+enc/windows_1253.$(OBJEXT): internal/error.h
+enc/windows_1253.$(OBJEXT): internal/eval.h
+enc/windows_1253.$(OBJEXT): internal/event.h
+enc/windows_1253.$(OBJEXT): internal/fl_type.h
+enc/windows_1253.$(OBJEXT): internal/gc.h
+enc/windows_1253.$(OBJEXT): internal/glob.h
+enc/windows_1253.$(OBJEXT): internal/globals.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
@@ -6458,33 +10298,116 @@ 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/intern/array.h
+enc/windows_1253.$(OBJEXT): internal/intern/bignum.h
+enc/windows_1253.$(OBJEXT): internal/intern/class.h
+enc/windows_1253.$(OBJEXT): internal/intern/compar.h
+enc/windows_1253.$(OBJEXT): internal/intern/complex.h
+enc/windows_1253.$(OBJEXT): internal/intern/cont.h
+enc/windows_1253.$(OBJEXT): internal/intern/dir.h
+enc/windows_1253.$(OBJEXT): internal/intern/enum.h
+enc/windows_1253.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_1253.$(OBJEXT): internal/intern/error.h
+enc/windows_1253.$(OBJEXT): internal/intern/eval.h
+enc/windows_1253.$(OBJEXT): internal/intern/file.h
+enc/windows_1253.$(OBJEXT): internal/intern/gc.h
+enc/windows_1253.$(OBJEXT): internal/intern/hash.h
+enc/windows_1253.$(OBJEXT): internal/intern/io.h
+enc/windows_1253.$(OBJEXT): internal/intern/load.h
+enc/windows_1253.$(OBJEXT): internal/intern/marshal.h
+enc/windows_1253.$(OBJEXT): internal/intern/numeric.h
+enc/windows_1253.$(OBJEXT): internal/intern/object.h
+enc/windows_1253.$(OBJEXT): internal/intern/parse.h
+enc/windows_1253.$(OBJEXT): internal/intern/proc.h
+enc/windows_1253.$(OBJEXT): internal/intern/process.h
+enc/windows_1253.$(OBJEXT): internal/intern/random.h
+enc/windows_1253.$(OBJEXT): internal/intern/range.h
+enc/windows_1253.$(OBJEXT): internal/intern/rational.h
+enc/windows_1253.$(OBJEXT): internal/intern/re.h
+enc/windows_1253.$(OBJEXT): internal/intern/ruby.h
+enc/windows_1253.$(OBJEXT): internal/intern/select.h
+enc/windows_1253.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1253.$(OBJEXT): internal/intern/signal.h
+enc/windows_1253.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_1253.$(OBJEXT): internal/intern/string.h
+enc/windows_1253.$(OBJEXT): internal/intern/struct.h
+enc/windows_1253.$(OBJEXT): internal/intern/thread.h
+enc/windows_1253.$(OBJEXT): internal/intern/time.h
+enc/windows_1253.$(OBJEXT): internal/intern/variable.h
+enc/windows_1253.$(OBJEXT): internal/intern/vm.h
+enc/windows_1253.$(OBJEXT): internal/interpreter.h
+enc/windows_1253.$(OBJEXT): internal/iterator.h
+enc/windows_1253.$(OBJEXT): internal/memory.h
+enc/windows_1253.$(OBJEXT): internal/method.h
+enc/windows_1253.$(OBJEXT): internal/module.h
+enc/windows_1253.$(OBJEXT): internal/newobj.h
+enc/windows_1253.$(OBJEXT): internal/rgengc.h
+enc/windows_1253.$(OBJEXT): internal/scan_args.h
+enc/windows_1253.$(OBJEXT): internal/special_consts.h
+enc/windows_1253.$(OBJEXT): internal/static_assert.h
enc/windows_1253.$(OBJEXT): internal/stdalign.h
enc/windows_1253.$(OBJEXT): internal/stdbool.h
+enc/windows_1253.$(OBJEXT): internal/symbol.h
+enc/windows_1253.$(OBJEXT): internal/value.h
+enc/windows_1253.$(OBJEXT): internal/value_type.h
+enc/windows_1253.$(OBJEXT): internal/variable.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_1253.$(OBJEXT): st.h
+enc/windows_1253.$(OBJEXT): subst.h
+enc/windows_1254.$(OBJEXT): $(hdrdir)/ruby.h
+enc/windows_1254.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_1254.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1254.$(OBJEXT): assert.h
+enc/windows_1254.$(OBJEXT): backward.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/inttypes.h
+enc/windows_1254.$(OBJEXT): backward/2/limits.h
+enc/windows_1254.$(OBJEXT): backward/2/long_long.h
+enc/windows_1254.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1254.$(OBJEXT): backward/2/stdarg.h
+enc/windows_1254.$(OBJEXT): config.h
+enc/windows_1254.$(OBJEXT): defines.h
+enc/windows_1254.$(OBJEXT): enc/iso_8859.h
+enc/windows_1254.$(OBJEXT): enc/windows_1254.c
+enc/windows_1254.$(OBJEXT): intern.h
+enc/windows_1254.$(OBJEXT): internal/abi.h
+enc/windows_1254.$(OBJEXT): internal/anyargs.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_1254.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_1254.$(OBJEXT): internal/assume.h
enc/windows_1254.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1254.$(OBJEXT): internal/attr/artificial.h
enc/windows_1254.$(OBJEXT): internal/attr/cold.h
enc/windows_1254.$(OBJEXT): internal/attr/const.h
+enc/windows_1254.$(OBJEXT): internal/attr/constexpr.h
enc/windows_1254.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1254.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_1254.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_1254.$(OBJEXT): internal/attr/error.h
+enc/windows_1254.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6494,6 +10417,7 @@ 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/attr/weakref.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
@@ -6504,8 +10428,30 @@ 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/constant_p.h
+enc/windows_1254.$(OBJEXT): internal/core.h
+enc/windows_1254.$(OBJEXT): internal/core/rarray.h
+enc/windows_1254.$(OBJEXT): internal/core/rbasic.h
+enc/windows_1254.$(OBJEXT): internal/core/rbignum.h
+enc/windows_1254.$(OBJEXT): internal/core/rclass.h
+enc/windows_1254.$(OBJEXT): internal/core/rdata.h
+enc/windows_1254.$(OBJEXT): internal/core/rfile.h
+enc/windows_1254.$(OBJEXT): internal/core/rhash.h
+enc/windows_1254.$(OBJEXT): internal/core/robject.h
+enc/windows_1254.$(OBJEXT): internal/core/rregexp.h
+enc/windows_1254.$(OBJEXT): internal/core/rstring.h
+enc/windows_1254.$(OBJEXT): internal/core/rstruct.h
+enc/windows_1254.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_1254.$(OBJEXT): internal/ctype.h
enc/windows_1254.$(OBJEXT): internal/dllexport.h
enc/windows_1254.$(OBJEXT): internal/dosish.h
+enc/windows_1254.$(OBJEXT): internal/error.h
+enc/windows_1254.$(OBJEXT): internal/eval.h
+enc/windows_1254.$(OBJEXT): internal/event.h
+enc/windows_1254.$(OBJEXT): internal/fl_type.h
+enc/windows_1254.$(OBJEXT): internal/gc.h
+enc/windows_1254.$(OBJEXT): internal/glob.h
+enc/windows_1254.$(OBJEXT): internal/globals.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
@@ -6514,34 +10460,116 @@ 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/intern/array.h
+enc/windows_1254.$(OBJEXT): internal/intern/bignum.h
+enc/windows_1254.$(OBJEXT): internal/intern/class.h
+enc/windows_1254.$(OBJEXT): internal/intern/compar.h
+enc/windows_1254.$(OBJEXT): internal/intern/complex.h
+enc/windows_1254.$(OBJEXT): internal/intern/cont.h
+enc/windows_1254.$(OBJEXT): internal/intern/dir.h
+enc/windows_1254.$(OBJEXT): internal/intern/enum.h
+enc/windows_1254.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_1254.$(OBJEXT): internal/intern/error.h
+enc/windows_1254.$(OBJEXT): internal/intern/eval.h
+enc/windows_1254.$(OBJEXT): internal/intern/file.h
+enc/windows_1254.$(OBJEXT): internal/intern/gc.h
+enc/windows_1254.$(OBJEXT): internal/intern/hash.h
+enc/windows_1254.$(OBJEXT): internal/intern/io.h
+enc/windows_1254.$(OBJEXT): internal/intern/load.h
+enc/windows_1254.$(OBJEXT): internal/intern/marshal.h
+enc/windows_1254.$(OBJEXT): internal/intern/numeric.h
+enc/windows_1254.$(OBJEXT): internal/intern/object.h
+enc/windows_1254.$(OBJEXT): internal/intern/parse.h
+enc/windows_1254.$(OBJEXT): internal/intern/proc.h
+enc/windows_1254.$(OBJEXT): internal/intern/process.h
+enc/windows_1254.$(OBJEXT): internal/intern/random.h
+enc/windows_1254.$(OBJEXT): internal/intern/range.h
+enc/windows_1254.$(OBJEXT): internal/intern/rational.h
+enc/windows_1254.$(OBJEXT): internal/intern/re.h
+enc/windows_1254.$(OBJEXT): internal/intern/ruby.h
+enc/windows_1254.$(OBJEXT): internal/intern/select.h
+enc/windows_1254.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1254.$(OBJEXT): internal/intern/signal.h
+enc/windows_1254.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_1254.$(OBJEXT): internal/intern/string.h
+enc/windows_1254.$(OBJEXT): internal/intern/struct.h
+enc/windows_1254.$(OBJEXT): internal/intern/thread.h
+enc/windows_1254.$(OBJEXT): internal/intern/time.h
+enc/windows_1254.$(OBJEXT): internal/intern/variable.h
+enc/windows_1254.$(OBJEXT): internal/intern/vm.h
+enc/windows_1254.$(OBJEXT): internal/interpreter.h
+enc/windows_1254.$(OBJEXT): internal/iterator.h
+enc/windows_1254.$(OBJEXT): internal/memory.h
+enc/windows_1254.$(OBJEXT): internal/method.h
+enc/windows_1254.$(OBJEXT): internal/module.h
+enc/windows_1254.$(OBJEXT): internal/newobj.h
+enc/windows_1254.$(OBJEXT): internal/rgengc.h
+enc/windows_1254.$(OBJEXT): internal/scan_args.h
+enc/windows_1254.$(OBJEXT): internal/special_consts.h
+enc/windows_1254.$(OBJEXT): internal/static_assert.h
enc/windows_1254.$(OBJEXT): internal/stdalign.h
enc/windows_1254.$(OBJEXT): internal/stdbool.h
+enc/windows_1254.$(OBJEXT): internal/symbol.h
+enc/windows_1254.$(OBJEXT): internal/value.h
+enc/windows_1254.$(OBJEXT): internal/value_type.h
+enc/windows_1254.$(OBJEXT): internal/variable.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
-enc/windows_1254.$(OBJEXT): enc/windows_1254.c
enc/windows_1254.$(OBJEXT): missing.h
enc/windows_1254.$(OBJEXT): onigmo.h
+enc/windows_1254.$(OBJEXT): st.h
+enc/windows_1254.$(OBJEXT): subst.h
+enc/windows_1257.$(OBJEXT): $(hdrdir)/ruby.h
+enc/windows_1257.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_1257.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1257.$(OBJEXT): assert.h
+enc/windows_1257.$(OBJEXT): backward.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/inttypes.h
+enc/windows_1257.$(OBJEXT): backward/2/limits.h
+enc/windows_1257.$(OBJEXT): backward/2/long_long.h
+enc/windows_1257.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1257.$(OBJEXT): backward/2/stdarg.h
+enc/windows_1257.$(OBJEXT): config.h
+enc/windows_1257.$(OBJEXT): defines.h
+enc/windows_1257.$(OBJEXT): enc/iso_8859.h
+enc/windows_1257.$(OBJEXT): enc/windows_1257.c
+enc/windows_1257.$(OBJEXT): intern.h
+enc/windows_1257.$(OBJEXT): internal/abi.h
+enc/windows_1257.$(OBJEXT): internal/anyargs.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_1257.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_1257.$(OBJEXT): internal/assume.h
enc/windows_1257.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1257.$(OBJEXT): internal/attr/artificial.h
enc/windows_1257.$(OBJEXT): internal/attr/cold.h
enc/windows_1257.$(OBJEXT): internal/attr/const.h
+enc/windows_1257.$(OBJEXT): internal/attr/constexpr.h
enc/windows_1257.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1257.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_1257.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_1257.$(OBJEXT): internal/attr/error.h
+enc/windows_1257.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6551,6 +10579,7 @@ 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/attr/weakref.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
@@ -6561,8 +10590,30 @@ 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/constant_p.h
+enc/windows_1257.$(OBJEXT): internal/core.h
+enc/windows_1257.$(OBJEXT): internal/core/rarray.h
+enc/windows_1257.$(OBJEXT): internal/core/rbasic.h
+enc/windows_1257.$(OBJEXT): internal/core/rbignum.h
+enc/windows_1257.$(OBJEXT): internal/core/rclass.h
+enc/windows_1257.$(OBJEXT): internal/core/rdata.h
+enc/windows_1257.$(OBJEXT): internal/core/rfile.h
+enc/windows_1257.$(OBJEXT): internal/core/rhash.h
+enc/windows_1257.$(OBJEXT): internal/core/robject.h
+enc/windows_1257.$(OBJEXT): internal/core/rregexp.h
+enc/windows_1257.$(OBJEXT): internal/core/rstring.h
+enc/windows_1257.$(OBJEXT): internal/core/rstruct.h
+enc/windows_1257.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_1257.$(OBJEXT): internal/ctype.h
enc/windows_1257.$(OBJEXT): internal/dllexport.h
enc/windows_1257.$(OBJEXT): internal/dosish.h
+enc/windows_1257.$(OBJEXT): internal/error.h
+enc/windows_1257.$(OBJEXT): internal/eval.h
+enc/windows_1257.$(OBJEXT): internal/event.h
+enc/windows_1257.$(OBJEXT): internal/fl_type.h
+enc/windows_1257.$(OBJEXT): internal/gc.h
+enc/windows_1257.$(OBJEXT): internal/glob.h
+enc/windows_1257.$(OBJEXT): internal/globals.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
@@ -6571,34 +10622,118 @@ 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/intern/array.h
+enc/windows_1257.$(OBJEXT): internal/intern/bignum.h
+enc/windows_1257.$(OBJEXT): internal/intern/class.h
+enc/windows_1257.$(OBJEXT): internal/intern/compar.h
+enc/windows_1257.$(OBJEXT): internal/intern/complex.h
+enc/windows_1257.$(OBJEXT): internal/intern/cont.h
+enc/windows_1257.$(OBJEXT): internal/intern/dir.h
+enc/windows_1257.$(OBJEXT): internal/intern/enum.h
+enc/windows_1257.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_1257.$(OBJEXT): internal/intern/error.h
+enc/windows_1257.$(OBJEXT): internal/intern/eval.h
+enc/windows_1257.$(OBJEXT): internal/intern/file.h
+enc/windows_1257.$(OBJEXT): internal/intern/gc.h
+enc/windows_1257.$(OBJEXT): internal/intern/hash.h
+enc/windows_1257.$(OBJEXT): internal/intern/io.h
+enc/windows_1257.$(OBJEXT): internal/intern/load.h
+enc/windows_1257.$(OBJEXT): internal/intern/marshal.h
+enc/windows_1257.$(OBJEXT): internal/intern/numeric.h
+enc/windows_1257.$(OBJEXT): internal/intern/object.h
+enc/windows_1257.$(OBJEXT): internal/intern/parse.h
+enc/windows_1257.$(OBJEXT): internal/intern/proc.h
+enc/windows_1257.$(OBJEXT): internal/intern/process.h
+enc/windows_1257.$(OBJEXT): internal/intern/random.h
+enc/windows_1257.$(OBJEXT): internal/intern/range.h
+enc/windows_1257.$(OBJEXT): internal/intern/rational.h
+enc/windows_1257.$(OBJEXT): internal/intern/re.h
+enc/windows_1257.$(OBJEXT): internal/intern/ruby.h
+enc/windows_1257.$(OBJEXT): internal/intern/select.h
+enc/windows_1257.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1257.$(OBJEXT): internal/intern/signal.h
+enc/windows_1257.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_1257.$(OBJEXT): internal/intern/string.h
+enc/windows_1257.$(OBJEXT): internal/intern/struct.h
+enc/windows_1257.$(OBJEXT): internal/intern/thread.h
+enc/windows_1257.$(OBJEXT): internal/intern/time.h
+enc/windows_1257.$(OBJEXT): internal/intern/variable.h
+enc/windows_1257.$(OBJEXT): internal/intern/vm.h
+enc/windows_1257.$(OBJEXT): internal/interpreter.h
+enc/windows_1257.$(OBJEXT): internal/iterator.h
+enc/windows_1257.$(OBJEXT): internal/memory.h
+enc/windows_1257.$(OBJEXT): internal/method.h
+enc/windows_1257.$(OBJEXT): internal/module.h
+enc/windows_1257.$(OBJEXT): internal/newobj.h
+enc/windows_1257.$(OBJEXT): internal/rgengc.h
+enc/windows_1257.$(OBJEXT): internal/scan_args.h
+enc/windows_1257.$(OBJEXT): internal/special_consts.h
+enc/windows_1257.$(OBJEXT): internal/static_assert.h
enc/windows_1257.$(OBJEXT): internal/stdalign.h
enc/windows_1257.$(OBJEXT): internal/stdbool.h
+enc/windows_1257.$(OBJEXT): internal/symbol.h
+enc/windows_1257.$(OBJEXT): internal/value.h
+enc/windows_1257.$(OBJEXT): internal/value_type.h
+enc/windows_1257.$(OBJEXT): internal/variable.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
-enc/windows_1257.$(OBJEXT): enc/windows_1257.c
enc/windows_1257.$(OBJEXT): missing.h
enc/windows_1257.$(OBJEXT): onigmo.h
+enc/windows_1257.$(OBJEXT): st.h
+enc/windows_1257.$(OBJEXT): subst.h
+enc/windows_31j.$(OBJEXT): $(hdrdir)/ruby.h
+enc/windows_31j.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/windows_31j.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_31j.$(OBJEXT): assert.h
+enc/windows_31j.$(OBJEXT): backward.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/inttypes.h
+enc/windows_31j.$(OBJEXT): backward/2/limits.h
+enc/windows_31j.$(OBJEXT): backward/2/long_long.h
+enc/windows_31j.$(OBJEXT): backward/2/stdalign.h
+enc/windows_31j.$(OBJEXT): backward/2/stdarg.h
+enc/windows_31j.$(OBJEXT): config.h
+enc/windows_31j.$(OBJEXT): defines.h
+enc/windows_31j.$(OBJEXT): enc/jis/props.h
+enc/windows_31j.$(OBJEXT): enc/jis/props.kwd
+enc/windows_31j.$(OBJEXT): enc/shift_jis.h
+enc/windows_31j.$(OBJEXT): enc/windows_31j.c
+enc/windows_31j.$(OBJEXT): intern.h
+enc/windows_31j.$(OBJEXT): internal/abi.h
+enc/windows_31j.$(OBJEXT): internal/anyargs.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/char.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/double.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/int.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/long.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/long_long.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/off_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/short.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/size_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/windows_31j.$(OBJEXT): internal/arithmetic/uid_t.h
enc/windows_31j.$(OBJEXT): internal/assume.h
enc/windows_31j.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_31j.$(OBJEXT): internal/attr/artificial.h
enc/windows_31j.$(OBJEXT): internal/attr/cold.h
enc/windows_31j.$(OBJEXT): internal/attr/const.h
+enc/windows_31j.$(OBJEXT): internal/attr/constexpr.h
enc/windows_31j.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_31j.$(OBJEXT): internal/attr/diagnose_if.h
+enc/windows_31j.$(OBJEXT): internal/attr/enum_extensibility.h
enc/windows_31j.$(OBJEXT): internal/attr/error.h
+enc/windows_31j.$(OBJEXT): internal/attr/flag_enum.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/noalias.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
@@ -6608,6 +10743,7 @@ 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/attr/weakref.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
@@ -6618,8 +10754,30 @@ 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/constant_p.h
+enc/windows_31j.$(OBJEXT): internal/core.h
+enc/windows_31j.$(OBJEXT): internal/core/rarray.h
+enc/windows_31j.$(OBJEXT): internal/core/rbasic.h
+enc/windows_31j.$(OBJEXT): internal/core/rbignum.h
+enc/windows_31j.$(OBJEXT): internal/core/rclass.h
+enc/windows_31j.$(OBJEXT): internal/core/rdata.h
+enc/windows_31j.$(OBJEXT): internal/core/rfile.h
+enc/windows_31j.$(OBJEXT): internal/core/rhash.h
+enc/windows_31j.$(OBJEXT): internal/core/robject.h
+enc/windows_31j.$(OBJEXT): internal/core/rregexp.h
+enc/windows_31j.$(OBJEXT): internal/core/rstring.h
+enc/windows_31j.$(OBJEXT): internal/core/rstruct.h
+enc/windows_31j.$(OBJEXT): internal/core/rtypeddata.h
+enc/windows_31j.$(OBJEXT): internal/ctype.h
enc/windows_31j.$(OBJEXT): internal/dllexport.h
enc/windows_31j.$(OBJEXT): internal/dosish.h
+enc/windows_31j.$(OBJEXT): internal/error.h
+enc/windows_31j.$(OBJEXT): internal/eval.h
+enc/windows_31j.$(OBJEXT): internal/event.h
+enc/windows_31j.$(OBJEXT): internal/fl_type.h
+enc/windows_31j.$(OBJEXT): internal/gc.h
+enc/windows_31j.$(OBJEXT): internal/glob.h
+enc/windows_31j.$(OBJEXT): internal/globals.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
@@ -6628,24 +10786,63 @@ 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/intern/array.h
+enc/windows_31j.$(OBJEXT): internal/intern/bignum.h
+enc/windows_31j.$(OBJEXT): internal/intern/class.h
+enc/windows_31j.$(OBJEXT): internal/intern/compar.h
+enc/windows_31j.$(OBJEXT): internal/intern/complex.h
+enc/windows_31j.$(OBJEXT): internal/intern/cont.h
+enc/windows_31j.$(OBJEXT): internal/intern/dir.h
+enc/windows_31j.$(OBJEXT): internal/intern/enum.h
+enc/windows_31j.$(OBJEXT): internal/intern/enumerator.h
+enc/windows_31j.$(OBJEXT): internal/intern/error.h
+enc/windows_31j.$(OBJEXT): internal/intern/eval.h
+enc/windows_31j.$(OBJEXT): internal/intern/file.h
+enc/windows_31j.$(OBJEXT): internal/intern/gc.h
+enc/windows_31j.$(OBJEXT): internal/intern/hash.h
+enc/windows_31j.$(OBJEXT): internal/intern/io.h
+enc/windows_31j.$(OBJEXT): internal/intern/load.h
+enc/windows_31j.$(OBJEXT): internal/intern/marshal.h
+enc/windows_31j.$(OBJEXT): internal/intern/numeric.h
+enc/windows_31j.$(OBJEXT): internal/intern/object.h
+enc/windows_31j.$(OBJEXT): internal/intern/parse.h
+enc/windows_31j.$(OBJEXT): internal/intern/proc.h
+enc/windows_31j.$(OBJEXT): internal/intern/process.h
+enc/windows_31j.$(OBJEXT): internal/intern/random.h
+enc/windows_31j.$(OBJEXT): internal/intern/range.h
+enc/windows_31j.$(OBJEXT): internal/intern/rational.h
+enc/windows_31j.$(OBJEXT): internal/intern/re.h
+enc/windows_31j.$(OBJEXT): internal/intern/ruby.h
+enc/windows_31j.$(OBJEXT): internal/intern/select.h
+enc/windows_31j.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_31j.$(OBJEXT): internal/intern/signal.h
+enc/windows_31j.$(OBJEXT): internal/intern/sprintf.h
+enc/windows_31j.$(OBJEXT): internal/intern/string.h
+enc/windows_31j.$(OBJEXT): internal/intern/struct.h
+enc/windows_31j.$(OBJEXT): internal/intern/thread.h
+enc/windows_31j.$(OBJEXT): internal/intern/time.h
+enc/windows_31j.$(OBJEXT): internal/intern/variable.h
+enc/windows_31j.$(OBJEXT): internal/intern/vm.h
+enc/windows_31j.$(OBJEXT): internal/interpreter.h
+enc/windows_31j.$(OBJEXT): internal/iterator.h
+enc/windows_31j.$(OBJEXT): internal/memory.h
+enc/windows_31j.$(OBJEXT): internal/method.h
+enc/windows_31j.$(OBJEXT): internal/module.h
+enc/windows_31j.$(OBJEXT): internal/newobj.h
+enc/windows_31j.$(OBJEXT): internal/rgengc.h
+enc/windows_31j.$(OBJEXT): internal/scan_args.h
+enc/windows_31j.$(OBJEXT): internal/special_consts.h
+enc/windows_31j.$(OBJEXT): internal/static_assert.h
enc/windows_31j.$(OBJEXT): internal/stdalign.h
enc/windows_31j.$(OBJEXT): internal/stdbool.h
+enc/windows_31j.$(OBJEXT): internal/symbol.h
+enc/windows_31j.$(OBJEXT): internal/value.h
+enc/windows_31j.$(OBJEXT): internal/value_type.h
+enc/windows_31j.$(OBJEXT): internal/variable.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
-enc/windows_31j.$(OBJEXT): enc/jis/props.kwd
-enc/windows_31j.$(OBJEXT): enc/shift_jis.h
-enc/windows_31j.$(OBJEXT): enc/windows_31j.c
enc/windows_31j.$(OBJEXT): missing.h
enc/windows_31j.$(OBJEXT): onigmo.h
+enc/windows_31j.$(OBJEXT): st.h
+enc/windows_31j.$(OBJEXT): subst.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/enc/encdb.c b/enc/encdb.c
index a1936df804..8247e9ff6a 100644
--- a/enc/encdb.c
+++ b/enc/encdb.c
@@ -17,7 +17,7 @@
#define ENC_DEFINE(name) rb_encdb_declare(name)
#define ENC_SET_BASE(name, orig) rb_enc_set_base((name), (orig))
#define ENC_SET_DUMMY(name, orig) rb_enc_set_dummy(name)
-#define ENC_DUMMY_UNICODE(name) rb_encdb_set_unicode(rb_enc_set_dummy(ENC_REPLICATE((name), name "BE")))
+#define ENC_DUMMY_UNICODE(name) ENC_DUMMY(name)
void
Init_encdb(void)
diff --git a/enc/encinit.c.erb b/enc/encinit.c.erb
index 70c2a1934c..120408f8e3 100644
--- a/enc/encinit.c.erb
+++ b/enc/encinit.c.erb
@@ -2,6 +2,7 @@
* Author: yugui@google.com (Yugui Sonoda)
*/
#include <stdio.h>
+#include "ruby.h"
#define init(func, name) { \
extern void func(void); \
diff --git a/enc/jis/props.h.blt b/enc/jis/props.h.blt
index 54aa94f8bc..508a084449 100644
--- a/enc/jis/props.h.blt
+++ b/enc/jis/props.h.blt
@@ -69,7 +69,7 @@ struct enc_property {
unsigned char ctype;
};
-static const struct enc_property *onig_jis_property(/*const char *str, unsigned int len*/);
+static const struct enc_property *onig_jis_property(register const char *str, register size_t len);
#line 43 "enc/jis/props.kwd"
struct enc_property;
@@ -82,7 +82,7 @@ struct enc_property;
#ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1
-static unsigned char gperf_downcase[256] =
+static const unsigned char gperf_downcase[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
diff --git a/enc/jis/props.kwd b/enc/jis/props.kwd
index 659cf0aff4..9606828459 100644
--- a/enc/jis/props.kwd
+++ b/enc/jis/props.kwd
@@ -37,7 +37,7 @@ struct enc_property {
unsigned char ctype;
};
-static const struct enc_property *onig_jis_property(/*!ANSI{*/const char *str, unsigned int len/*}!ANSI*/);
+static const struct enc_property *onig_jis_property(register const char *str, register size_t len);
%}
struct enc_property;
diff --git a/enc/jis/props.src b/enc/jis/props.src
index 659cf0aff4..9606828459 100644
--- a/enc/jis/props.src
+++ b/enc/jis/props.src
@@ -37,7 +37,7 @@ struct enc_property {
unsigned char ctype;
};
-static const struct enc_property *onig_jis_property(/*!ANSI{*/const char *str, unsigned int len/*}!ANSI*/);
+static const struct enc_property *onig_jis_property(register const char *str, register size_t len);
%}
struct enc_property;
diff --git a/enc/make_encmake.rb b/enc/make_encmake.rb
index bc0597e3f4..fcfc2c9267 100755
--- a/enc/make_encmake.rb
+++ b/enc/make_encmake.rb
@@ -134,7 +134,7 @@ else
end
mkin = File.read(File.join($srcdir, "Makefile.in"))
mkin.gsub!(/@(#{CONFIG.keys.join('|')})@/) {CONFIG[$1]}
-open(ARGV[0], 'wb') {|f|
+File.open(ARGV[0], 'wb') {|f|
f.puts mkin, dep
}
if MODULE_TYPE == :static
diff --git a/enc/trans/newline.trans b/enc/trans/newline.trans
index 9e763407f9..95e082f5bd 100644
--- a/enc/trans/newline.trans
+++ b/enc/trans/newline.trans
@@ -17,10 +17,16 @@
map_cr["0a"] = "0d"
transcode_generate_node(ActionMap.parse(map_cr), "cr_newline")
+
+ map_normalize = {}
+ map_normalize["{00-ff}"] = :func_so
+
+ transcode_generate_node(ActionMap.parse(map_normalize), "lf_newline")
%>
<%= transcode_generated_code %>
+#define lf_newline universal_newline
#define STATE (sp[0])
#define NORMAL 0
#define JUST_AFTER_CR 1
@@ -126,10 +132,24 @@ rb_cr_newline = {
0, 0, 0, 0
};
+static const rb_transcoder
+rb_lf_newline = {
+ "", "lf_newline", lf_newline,
+ TRANSCODE_TABLE_INFO,
+ 1, /* input_unit_length */
+ 1, /* max_input */
+ 2, /* max_output */
+ asciicompat_converter, /* asciicompat_type */
+ 2, universal_newline_init, universal_newline_init, /* state_size, state_init, state_fini */
+ 0, 0, 0, fun_so_universal_newline,
+ universal_newline_finish
+};
+
void
Init_newline(void)
{
rb_register_transcoder(&rb_universal_newline);
rb_register_transcoder(&rb_crlf_newline);
rb_register_transcoder(&rb_cr_newline);
+ rb_register_transcoder(&rb_lf_newline);
}
diff --git a/enc/trans/transdb.c b/enc/trans/transdb.c
index d6ac41e967..7caf8d845d 100644
--- a/enc/trans/transdb.c
+++ b/enc/trans/transdb.c
@@ -9,6 +9,8 @@
**********************************************************************/
+#include "ruby.h"
+
void rb_declare_transcoder(const char *enc1, const char *enc2, const char *lib);
void
diff --git a/enc/unicode/13.0.0/casefold.h b/enc/unicode/15.0.0/casefold.h
index 39f22604c4..51120d867d 100644
--- a/enc/unicode/13.0.0/casefold.h
+++ b/enc/unicode/15.0.0/casefold.h
@@ -1,20 +1,20 @@
/* DO NOT EDIT THIS FILE. */
-/* Generated by enc/unicode/case-folding.rb */
+/* Generated by enc-case-folding.rb */
#if defined ONIG_UNICODE_VERSION_STRING && !( \
- ONIG_UNICODE_VERSION_MAJOR == 13 && \
+ ONIG_UNICODE_VERSION_MAJOR == 15 && \
ONIG_UNICODE_VERSION_MINOR == 0 && \
ONIG_UNICODE_VERSION_TEENY == 0 && \
1)
# error ONIG_UNICODE_VERSION_STRING mismatch
#endif
-#define ONIG_UNICODE_VERSION_STRING "13.0.0"
-#define ONIG_UNICODE_VERSION_MAJOR 13
+#define ONIG_UNICODE_VERSION_STRING "15.0.0"
+#define ONIG_UNICODE_VERSION_MAJOR 15
#define ONIG_UNICODE_VERSION_MINOR 0
#define ONIG_UNICODE_VERSION_TEENY 0
static const CaseFold_11_Type CaseFold_11_Table[] = {
-#define CaseFold (*(CaseFold_11_Type (*)[1488])(CaseFold_11_Table+0))
+#define CaseFold (*(CaseFold_11_Type (*)[1528])(CaseFold_11_Table+0))
{0x0041, {1|F|D, {0x0061}}},
{0x0042, {1|F|D, {0x0062}}},
{0x0043, {1|F|D, {0x0063}}},
@@ -973,6 +973,7 @@ static const CaseFold_11_Type CaseFold_11_Table[] = {
{0x2c2c, {1|F|D, {0x2c5c}}},
{0x2c2d, {1|F|D, {0x2c5d}}},
{0x2c2e, {1|F|D, {0x2c5e}}},
+ {0x2c2f, {1|F|D, {0x2c5f}}},
{0x2c60, {1|F|D, {0x2c61}}},
{0x2c62, {1|F|D, {0x026b}}},
{0x2c63, {1|F|D, {0x1d7d}}},
@@ -1153,12 +1154,16 @@ static const CaseFold_11_Type CaseFold_11_Table[] = {
{0xa7ba, {1|F|D, {0xa7bb}}},
{0xa7bc, {1|F|D, {0xa7bd}}},
{0xa7be, {1|F|D, {0xa7bf}}},
+ {0xa7c0, {1|F|D, {0xa7c1}}},
{0xa7c2, {1|F|D, {0xa7c3}}},
{0xa7c4, {1|F|D, {0xa794}}},
{0xa7c5, {1|F|D, {0x0282}}},
{0xa7c6, {1|F|D, {0x1d8e}}},
{0xa7c7, {1|F|D, {0xa7c8}}},
{0xa7c9, {1|F|D, {0xa7ca}}},
+ {0xa7d0, {1|F|D, {0xa7d1}}},
+ {0xa7d6, {1|F|D, {0xa7d7}}},
+ {0xa7d8, {1|F|D, {0xa7d9}}},
{0xa7f5, {1|F|D, {0xa7f6}}},
{0xab70, {1|F|U, {0x13a0}}},
{0xab71, {1|F|U, {0x13a1}}},
@@ -1354,6 +1359,41 @@ static const CaseFold_11_Type CaseFold_11_Table[] = {
{0x104d1, {1|F|D, {0x104f9}}},
{0x104d2, {1|F|D, {0x104fa}}},
{0x104d3, {1|F|D, {0x104fb}}},
+ {0x10570, {1|F|D, {0x10597}}},
+ {0x10571, {1|F|D, {0x10598}}},
+ {0x10572, {1|F|D, {0x10599}}},
+ {0x10573, {1|F|D, {0x1059a}}},
+ {0x10574, {1|F|D, {0x1059b}}},
+ {0x10575, {1|F|D, {0x1059c}}},
+ {0x10576, {1|F|D, {0x1059d}}},
+ {0x10577, {1|F|D, {0x1059e}}},
+ {0x10578, {1|F|D, {0x1059f}}},
+ {0x10579, {1|F|D, {0x105a0}}},
+ {0x1057a, {1|F|D, {0x105a1}}},
+ {0x1057c, {1|F|D, {0x105a3}}},
+ {0x1057d, {1|F|D, {0x105a4}}},
+ {0x1057e, {1|F|D, {0x105a5}}},
+ {0x1057f, {1|F|D, {0x105a6}}},
+ {0x10580, {1|F|D, {0x105a7}}},
+ {0x10581, {1|F|D, {0x105a8}}},
+ {0x10582, {1|F|D, {0x105a9}}},
+ {0x10583, {1|F|D, {0x105aa}}},
+ {0x10584, {1|F|D, {0x105ab}}},
+ {0x10585, {1|F|D, {0x105ac}}},
+ {0x10586, {1|F|D, {0x105ad}}},
+ {0x10587, {1|F|D, {0x105ae}}},
+ {0x10588, {1|F|D, {0x105af}}},
+ {0x10589, {1|F|D, {0x105b0}}},
+ {0x1058a, {1|F|D, {0x105b1}}},
+ {0x1058c, {1|F|D, {0x105b3}}},
+ {0x1058d, {1|F|D, {0x105b4}}},
+ {0x1058e, {1|F|D, {0x105b5}}},
+ {0x1058f, {1|F|D, {0x105b6}}},
+ {0x10590, {1|F|D, {0x105b7}}},
+ {0x10591, {1|F|D, {0x105b8}}},
+ {0x10592, {1|F|D, {0x105b9}}},
+ {0x10594, {1|F|D, {0x105bb}}},
+ {0x10595, {1|F|D, {0x105bc}}},
{0x10c80, {1|F|D, {0x10cc0}}},
{0x10c81, {1|F|D, {0x10cc1}}},
{0x10c82, {1|F|D, {0x10cc2}}},
@@ -1503,7 +1543,7 @@ static const CaseFold_11_Type CaseFold_11_Table[] = {
{0x1e91f, {1|F|D, {0x1e941}}},
{0x1e920, {1|F|D, {0x1e942}}},
{0x1e921, {1|F|D, {0x1e943}}},
-#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1488))
+#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1528))
{0x0049, {1|F|D, {0x0069}}},
{0x0130, {2|F|D, {0x0069, 0x0307}}},
};
@@ -1511,7 +1551,7 @@ static const CaseFold_11_Type CaseFold_11_Table[] = {
/* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseFold_11_hash -N onigenc_unicode_CaseFold_11_lookup -n */
-/* maximum key range = 3677, duplicates = 0 */
+/* maximum key range = 3080, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -1526,27 +1566,27 @@ onigenc_unicode_CaseFold_11_hash(const OnigCodePoint code)
{
static const unsigned short asso_values[] =
{
- 1, 3681, 2, 7, 3, 416, 200, 59, 83, 50,
- 2, 288, 142, 5, 3681, 3681, 3681, 3681, 3681, 3681,
- 3681, 3681, 3681, 3681, 3681, 3681, 3681, 30, 3681, 3681,
- 3681, 3681, 3681, 3681, 3681, 127, 3681, 3681, 3681, 3681,
- 3681, 19, 3681, 3681, 3681, 3681, 3681, 3681, 3681, 3681,
- 3681, 459, 3681, 3681, 3681, 3681, 3681, 3681, 3681, 190,
- 3681, 3681, 14, 13, 297, 1, 3681, 3681, 300, 5,
- 3681, 3681, 3681, 3681, 3681, 179, 3681, 3681, 205, 792,
- 431, 28, 1935, 486, 235, 442, 2030, 113, 1663, 5,
- 11, 22, 1884, 649, 743, 397, 1558, 96, 1958, 130,
- 1745, 279, 1900, 79, 1345, 45, 1785, 62, 1708, 342,
- 1679, 262, 1857, 147, 1364, 532, 1639, 197, 1612, 180,
- 519, 587, 1332, 380, 1044, 546, 1578, 464, 431, 698,
- 1701, 573, 1593, 768, 1893, 737, 1735, 643, 1552, 669,
- 1807, 794, 1633, 704, 1821, 1313, 1630, 1064, 1283, 1001,
- 1321, 1119, 1307, 1040, 948, 864, 1697, 1015, 1338, 1174,
- 1945, 1153, 1002, 1109, 1280, 1245, 812, 1095, 286, 1261,
- 512, 1210, 372, 1496, 98, 1494, 31, 1526, 14, 1136,
- 77, 1476, 5, 1511, 68, 1425, 9, 1418, 205, 1387,
- 209, 1358, 60, 1834, 12, 1564, 39, 2015, 128, 916,
- 88, 1275, 2, 1019, 333, 665, 346, 1365, 174
+ 1, 3085, 2, 20, 3, 307, 200, 8, 31, 159,
+ 2, 253, 33, 967, 3085, 3085, 3085, 3085, 3085, 3085,
+ 3085, 3085, 3085, 3085, 3085, 3085, 3085, 30, 3085, 3085,
+ 3085, 3085, 3085, 3085, 3085, 352, 3085, 3085, 3085, 3085,
+ 3085, 93, 3085, 3085, 3085, 3085, 3085, 3085, 3085, 3085,
+ 3085, 407, 3085, 3085, 3085, 3085, 3085, 3085, 3085, 201,
+ 3085, 3085, 14, 13, 373, 1, 3085, 3085, 503, 19,
+ 3085, 3085, 3085, 3085, 3085, 325, 3085, 3085, 290, 1064,
+ 484, 28, 1906, 447, 272, 414, 2002, 79, 905, 5,
+ 11, 22, 2024, 623, 761, 617, 1893, 45, 1874, 113,
+ 1856, 255, 1823, 96, 1463, 62, 1841, 130, 1798, 331,
+ 1771, 238, 1977, 147, 1387, 464, 1691, 187, 1639, 181,
+ 366, 580, 1331, 508, 1287, 547, 1583, 541, 400, 783,
+ 1944, 657, 1850, 932, 1785, 858, 1645, 681, 1412, 722,
+ 1622, 972, 1306, 807, 1942, 1282, 283, 1218, 1557, 1055,
+ 1406, 1258, 1401, 1168, 1327, 864, 893, 1123, 1714, 1195,
+ 1885, 1083, 2016, 1232, 823, 678, 1420, 1017, 155, 1261,
+ 86, 1351, 794, 1929, 51, 1525, 50, 221, 4, 1383,
+ 196, 325, 1, 1562, 102, 1441, 3, 1356, 226, 1304,
+ 271, 1516, 68, 1752, 37, 1469, 51, 1920, 143, 2059,
+ 198, 2095, 370, 2069, 137, 718, 407, 1926, 136
};
return asso_values[bits_of(code, 2)+81] + asso_values[bits_of(code, 1)+2] + asso_values[bits_of(code, 0)];
}
@@ -1558,2006 +1598,2021 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
{
MIN_CODE_VALUE = 0x41,
MAX_CODE_VALUE = 0x1e921,
- TOTAL_KEYWORDS = 1490,
+ TOTAL_KEYWORDS = 1530,
MIN_WORD_LENGTH = 3,
MAX_WORD_LENGTH = 3,
- MIN_HASH_VALUE = 4,
- MAX_HASH_VALUE = 3680
+ MIN_HASH_VALUE = 5,
+ MAX_HASH_VALUE = 3084
};
static const short wordlist[] =
{
- -1, -1, -1, -1,
- /*0x1ff9*/ 860,
+ -1, -1, -1, -1, -1,
+ /*0x1fe9*/ 850,
-1,
- /*0x0179*/ 117,
/*0x1f88*/ 775,
/*0x0408*/ 305,
/*0x0108*/ 61,
- /*0x10408*/ 1271,
- /*0x1fe9*/ 850,
- /*0xab88*/ 1169,
+ /*0x10408*/ 1276,
+ -1,
+ /*0xab88*/ 1174,
/*0x1f89*/ 776,
/*0x0409*/ 306,
- -1,
- /*0x10409*/ 1272,
+ /*0x2c69*/ 964,
+ /*0x10409*/ 1277,
/*0x2c08*/ 919,
- /*0xab89*/ 1170,
+ /*0xab89*/ 1175,
/*0x1e88*/ 653,
/*0x1e08*/ 589,
- /*0x2c69*/ 963,
- /*0x13f9*/ 525,
+ -1, -1,
/*0x2c09*/ 920,
/*0x1f8a*/ 777,
/*0x040a*/ 307,
/*0x010a*/ 62,
- /*0x1040a*/ 1273,
- /*0x2c88*/ 977,
- /*0xab8a*/ 1171,
+ /*0x1040a*/ 1278,
+ /*0x2c88*/ 978,
+ /*0xab8a*/ 1176,
/*0x1f80*/ 767,
/*0x0400*/ 297,
/*0x0100*/ 57,
- /*0x10400*/ 1263,
+ /*0x10400*/ 1268,
/*0x2c0a*/ 921,
- /*0xab80*/ 1161,
+ /*0xab80*/ 1166,
/*0x1e8a*/ 654,
/*0x1e0a*/ 590,
- /*0x10c88*/ 1347,
- /*0x00df*/ 56,
+ /*0x10c88*/ 1387,
+ /*0x0508*/ 425,
/*0x2c00*/ 911,
- /*0x1ff3*/ 855,
+ -1,
/*0x1e80*/ 649,
/*0x1e00*/ 585,
- /*0x10c89*/ 1348,
- /*0x2c8a*/ 978,
- -1,
- /*0x1f98*/ 791,
- /*0x0418*/ 321,
- /*0x0118*/ 69,
- /*0x10418*/ 1287,
- /*0x2c80*/ 973,
- /*0xab98*/ 1185,
- /*0x03f9*/ 292,
- -1,
- /*0x10c8a*/ 1349,
- /*0x0388*/ 235,
- /*0x2c18*/ 935,
- /*0xa780*/ 1105,
- /*0x1e98*/ 662,
- /*0x1e18*/ 597,
- /*0x10c80*/ 1339,
- /*0x0389*/ 236,
- /*0x03f1*/ 288,
- /*0x1f9a*/ 793,
- /*0x041a*/ 323,
- /*0x011a*/ 70,
- /*0x1041a*/ 1289,
- /*0x2c98*/ 985,
- /*0xab9a*/ 1187,
- /*0x1fe7*/ 848,
- -1,
- /*0x2c6f*/ 967,
- /*0x038a*/ 237,
- /*0x2c1a*/ 937,
- /*0xa798*/ 1114,
- /*0x1e9a*/ 664,
- /*0x1e1a*/ 598,
- /*0x10c98*/ 1363,
- /*0x1fe3*/ 845,
- /*0x2c67*/ 962,
- /*0x1f96*/ 789,
- /*0x0416*/ 319,
- /*0x0116*/ 68,
- /*0x10416*/ 1285,
- /*0x2c9a*/ 986,
- /*0xab96*/ 1183,
- -1, -1,
- /*0x2c63*/ 960,
- /*0x1ff7*/ 858,
- /*0x2c16*/ 933,
- /*0xa79a*/ 1115,
- /*0x1e96*/ 660,
- /*0x1e16*/ 596,
- /*0x10c9a*/ 1365,
- /*0x0398*/ 249,
+ /*0x10c89*/ 1388,
+ /*0x2c8a*/ 979,
-1,
/*0x1f90*/ 783,
/*0x0410*/ 313,
/*0x0110*/ 65,
- /*0x10410*/ 1279,
- /*0x2c96*/ 984,
- /*0xab90*/ 1177,
- -1, -1,
- /*0x00dd*/ 54,
+ /*0x10410*/ 1284,
+ /*0x2c80*/ 974,
+ /*0xab90*/ 1182,
+ /*0x1ff3*/ 855,
-1,
+ /*0x10c8a*/ 1389,
+ /*0x050a*/ 426,
/*0x2c10*/ 927,
- /*0xa796*/ 1113,
+ /*0xa780*/ 1106,
/*0x1e90*/ 657,
/*0x1e10*/ 593,
- /*0x10c96*/ 1361,
- /*0x039a*/ 251,
+ /*0x10c80*/ 1379,
+ /*0x0500*/ 421,
-1,
+ /*0x1f98*/ 791,
+ /*0x0418*/ 321,
+ /*0x0118*/ 69,
+ /*0x10418*/ 1292,
+ /*0x2c90*/ 982,
+ /*0xab98*/ 1190,
+ -1,
+ /*0x00df*/ 56,
+ /*0x00dd*/ 54,
+ /*0x10571*/ 1345,
+ /*0x2c18*/ 935,
+ /*0xa790*/ 1112,
+ /*0x1e98*/ 662,
+ /*0x1e18*/ 597,
+ /*0x10c90*/ 1395,
+ /*0x0510*/ 429,
+ /*0x2c6f*/ 968,
/*0x1f86*/ 773,
/*0x0406*/ 303,
/*0x0106*/ 60,
- /*0x10406*/ 1269,
- /*0x2c90*/ 981,
- /*0xab86*/ 1167,
- -1, -1, -1, -1,
+ /*0x10406*/ 1274,
+ /*0x2c98*/ 986,
+ /*0xab86*/ 1172,
+ /*0x10573*/ 1347,
+ /*0x1fd9*/ 841,
+ /*0x0059*/ 23,
+ -1,
/*0x2c06*/ 917,
- /*0xa790*/ 1111,
+ /*0xa798*/ 1115,
/*0x1e86*/ 652,
/*0x1e06*/ 588,
- /*0x10c90*/ 1355,
- /*0x0396*/ 247,
+ /*0x10c98*/ 1403,
+ /*0x0518*/ 433,
-1,
+ /*0x1f96*/ 789,
+ /*0x0416*/ 319,
+ /*0x0116*/ 68,
+ /*0x10416*/ 1290,
+ /*0x2c86*/ 977,
+ /*0xab96*/ 1188,
+ /*0x1fe7*/ 848,
+ -1, -1,
+ /*0x00d9*/ 50,
+ /*0x2c16*/ 933,
+ /*0xa786*/ 1109,
+ /*0x1e96*/ 660,
+ /*0x1e16*/ 596,
+ /*0x10c86*/ 1385,
+ /*0x0506*/ 424,
+ /*0x2c67*/ 963,
/*0x1f92*/ 785,
/*0x0412*/ 315,
/*0x0112*/ 66,
- /*0x10412*/ 1281,
- /*0x2c86*/ 976,
- /*0xab92*/ 1179,
- -1,
- /*0x03f7*/ 291,
- /*0x2c75*/ 970,
- -1,
+ /*0x10412*/ 1286,
+ /*0x2c96*/ 985,
+ /*0xab92*/ 1184,
+ -1, -1, -1, -1,
/*0x2c12*/ 929,
- /*0xa786*/ 1108,
+ /*0xa796*/ 1114,
/*0x1e92*/ 658,
/*0x1e12*/ 594,
- /*0x10c86*/ 1345,
- /*0x0390*/ 241,
- /*0x0508*/ 425,
+ /*0x10c96*/ 1401,
+ /*0x0516*/ 432,
+ -1,
+ /*0x1f9a*/ 793,
+ /*0x041a*/ 323,
+ /*0x011a*/ 70,
+ /*0x1041a*/ 1294,
+ /*0x2c92*/ 983,
+ /*0xab9a*/ 1192,
+ -1,
+ /*0x1ffb*/ 862,
+ /*0x017f*/ 120,
+ /*0x017b*/ 118,
+ /*0x2c1a*/ 937,
+ /*0xa792*/ 1113,
+ /*0x1e9a*/ 664,
+ /*0x1e1a*/ 598,
+ /*0x10c92*/ 1397,
+ /*0x0512*/ 430,
+ /*0x2c7f*/ 973,
/*0x1fa0*/ 799,
/*0x0420*/ 329,
/*0x0120*/ 73,
- /*0x10420*/ 1295,
- /*0x2c92*/ 982,
- /*0xaba0*/ 1193,
- -1, -1, -1,
- /*0xa7f5*/ 1144,
+ /*0x10420*/ 1300,
+ /*0x2c9a*/ 987,
+ /*0xaba0*/ 1198,
+ /*0x2c75*/ 971,
+ -1,
+ /*0x1fd7*/ 839,
+ /*0x0057*/ 21,
/*0x2c20*/ 943,
- /*0xa792*/ 1112,
+ /*0xa79a*/ 1116,
/*0x1ea0*/ 667,
/*0x1e20*/ 601,
- /*0x10c92*/ 1357,
- /*0x0386*/ 234,
- /*0x050a*/ 426,
- -1, -1, -1, -1,
- /*0x2ca0*/ 989,
- /*0x0500*/ 421,
- -1, -1, -1, -1, -1,
- /*0xa7a0*/ 1118,
- /*0x017f*/ 120,
- /*0x03f5*/ 290,
- /*0x10ca0*/ 1371,
- /*0x0392*/ 243,
+ /*0x10c9a*/ 1405,
+ /*0x051a*/ 434,
+ /*0x0388*/ 235,
+ -1, -1,
+ /*0x037f*/ 233,
+ -1,
+ /*0x2ca0*/ 990,
+ /*0x0389*/ 236,
+ /*0x1057f*/ 1358,
+ /*0xa7f5*/ 1149,
+ -1, -1, -1,
+ /*0xa7a0*/ 1119,
+ -1,
+ /*0x10575*/ 1349,
+ /*0x10ca0*/ 1411,
+ /*0x0520*/ 437,
+ /*0x038a*/ 237,
/*0x1fa6*/ 805,
/*0x0426*/ 335,
/*0x0126*/ 76,
- /*0x10426*/ 1301,
- /*0x2c7f*/ 972,
- /*0xaba6*/ 1199,
- /*0x0518*/ 433,
- -1, -1, -1,
- /*0x2c26*/ 949,
- -1,
- /*0x1ea6*/ 670,
- /*0x1e26*/ 604,
- /*0x1c88*/ 538,
+ /*0x10426*/ 1306,
-1,
- /*0x03a0*/ 257,
+ /*0xaba6*/ 1204,
/*0x1fa4*/ 803,
/*0x0424*/ 333,
/*0x0124*/ 75,
- /*0x10424*/ 1299,
- /*0x2ca6*/ 992,
- /*0xaba4*/ 1197,
- /*0x051a*/ 434,
- /*0x0208*/ 194,
- /*0x1feb*/ 852,
- -1,
+ /*0x10424*/ 1304,
+ /*0x2c26*/ 949,
+ /*0xaba4*/ 1202,
+ /*0x1ea6*/ 670,
+ /*0x1e26*/ 604,
+ /*0x03f1*/ 288,
+ /*0x1fe3*/ 845,
/*0x2c24*/ 947,
- /*0xa7a6*/ 1121,
+ /*0x1ff7*/ 858,
/*0x1ea4*/ 669,
/*0x1e24*/ 603,
- /*0x10ca6*/ 1377,
- -1, -1, -1,
- /*0x2c6b*/ 964,
-1,
- /*0x1c80*/ 530,
- /*0x2ca4*/ 991,
- /*0x2c6d*/ 965,
- /*0x0516*/ 432,
- /*0x020a*/ 195,
+ /*0x2ca6*/ 993,
+ /*0x0390*/ 241,
+ /*0x0208*/ 194,
+ /*0x1c88*/ 538,
+ /*0x2c63*/ 961,
-1,
- /*0x03ff*/ 296,
+ /*0x2ca4*/ 992,
+ /*0xa7a6*/ 1122,
+ -1, -1,
+ /*0x10ca6*/ 1417,
+ /*0x0526*/ 440,
-1,
- /*0xa7a4*/ 1120,
- /*0x2ceb*/ 1023,
- /*0x0200*/ 190,
- /*0x10ca4*/ 1375,
- /*0x03a6*/ 262,
- /*0x2ced*/ 1024,
- -1, -1, -1,
- /*0x1c98*/ 547,
- /*0x1f83*/ 770,
- /*0x0403*/ 300,
- /*0x0510*/ 429,
- /*0x10403*/ 1266,
- /*0x2183*/ 884,
- /*0xab83*/ 1164,
- -1, -1, -1,
- /*0x0218*/ 202,
- /*0x2c03*/ 914,
- /*0x03a4*/ 260,
- -1, -1, -1, -1,
- /*0x1c9a*/ 549,
+ /*0xa7a4*/ 1121,
-1, -1,
- /*0x0506*/ 424,
+ /*0x10ca4*/ 1415,
+ /*0x0524*/ 439,
+ /*0x0398*/ 249,
+ /*0x020a*/ 195,
+ /*0x0460*/ 345,
+ /*0x0160*/ 104,
+ -1, -1,
+ /*0x1feb*/ 852,
+ /*0x0200*/ 190,
+ /*0x1c80*/ 530,
+ /*0x13fb*/ 527,
-1,
- /*0x037f*/ 233,
- -1, -1, -1, -1,
- /*0x021a*/ 203,
+ /*0x2c60*/ 959,
+ /*0x10577*/ 1351,
+ /*0x1ee0*/ 699,
+ /*0x1e60*/ 633,
+ -1,
+ /*0x2c6b*/ 965,
+ /*0x0386*/ 234,
/*0x1f9e*/ 797,
/*0x041e*/ 327,
/*0x011e*/ 72,
- /*0x1041e*/ 1293,
- /*0x10c83*/ 1342,
- /*0xab9e*/ 1191,
- /*0x1c96*/ 545,
- -1, -1,
- /*0x0512*/ 430,
+ /*0x1041e*/ 1298,
+ /*0x2ce0*/ 1022,
+ /*0xab9e*/ 1196,
+ /*0x0210*/ 198,
+ /*0x1c90*/ 539,
+ -1,
+ /*0x2ceb*/ 1024,
/*0x2c1e*/ 941,
- /*0x10a0*/ 484,
+ -1,
/*0x1e9e*/ 666,
/*0x1e1e*/ 600,
-1, -1,
- /*0x0216*/ 201,
+ /*0x0396*/ 247,
/*0x1f94*/ 787,
/*0x0414*/ 317,
/*0x0114*/ 67,
- /*0x10414*/ 1283,
- /*0x2c9e*/ 988,
- /*0xab94*/ 1181,
- /*0x1c90*/ 539,
- /*0x1fd7*/ 839,
- /*0x0057*/ 21,
- /*0x0520*/ 437,
+ /*0x10414*/ 1288,
+ /*0x2c9e*/ 989,
+ /*0xab94*/ 1186,
+ /*0x0218*/ 202,
+ /*0x1c98*/ 547,
+ -1, -1,
/*0x2c14*/ 931,
- /*0xa79e*/ 1117,
+ /*0xa79e*/ 1118,
/*0x1e94*/ 659,
/*0x1e14*/ 595,
- /*0x10c9e*/ 1369,
- -1,
- /*0x0210*/ 198,
- -1,
- /*0x1e908*/ 1462,
- -1, -1,
- /*0x2c94*/ 983,
- /*0x1f08*/ 715,
- /*0x1c86*/ 536,
- /*0x1e909*/ 1463,
- /*0x2165*/ 873,
- /*0x1f69*/ 760,
- /*0x10a6*/ 490,
- /*0x1f09*/ 716,
- /*0x2169*/ 877,
+ /*0x10c9e*/ 1409,
+ /*0x051e*/ 436,
+ /*0x0392*/ 243,
+ /*0x1f83*/ 770,
+ /*0x0403*/ 300,
/*0x048a*/ 362,
- /*0x10c94*/ 1359,
- /*0x039e*/ 255,
+ /*0x10403*/ 1271,
+ /*0x2c94*/ 984,
+ /*0xab83*/ 1169,
/*0x0206*/ 193,
- /*0x2161*/ 869,
- /*0x1e90a*/ 1464,
+ /*0x1c86*/ 536,
/*0x0480*/ 361,
+ /*0x2c6d*/ 966,
+ /*0x2c03*/ 914,
+ /*0x1e908*/ 1502,
+ /*0x0041*/ 0,
+ /*0x0141*/ 88,
+ /*0x10c94*/ 1399,
+ /*0x0514*/ 431,
+ /*0x039a*/ 251,
+ /*0x1e909*/ 1503,
+ /*0x2183*/ 884,
+ -1,
+ /*0x2ced*/ 1025,
+ -1,
+ /*0x03ff*/ 296,
+ /*0x0216*/ 201,
+ /*0x1c96*/ 545,
+ /*0x0490*/ 365,
-1, -1,
- /*0x1f0a*/ 717,
- /*0x1c92*/ 541,
- /*0x1e900*/ 1454,
- /*0x0526*/ 440,
+ /*0x1e90a*/ 1504,
+ /*0x03f5*/ 290,
+ /*0x00c1*/ 27,
+ /*0x10c83*/ 1382,
-1,
- /*0x10a4*/ 488,
- -1, -1, -1,
- /*0x1f5f*/ 758,
- /*0x0394*/ 245,
+ /*0x03a0*/ 257,
+ /*0x1e900*/ 1494,
+ -1, -1, -1, -1, -1,
/*0x0212*/ 199,
- -1, -1,
+ /*0x1c92*/ 541,
/*0x0498*/ 369,
- /*0x1ffb*/ 862,
+ /*0x0541*/ 461,
-1,
- /*0x017b*/ 118,
- /*0x1ca0*/ 555,
- /*0x1e918*/ 1478,
- /*0x0524*/ 439,
- -1, -1,
- /*0x1f18*/ 723,
+ /*0x0189*/ 126,
+ -1, -1, -1, -1, -1,
+ /*0x1e910*/ 1510,
+ -1,
+ /*0x1fe4*/ 846,
+ /*0x0464*/ 347,
+ /*0x0164*/ 106,
+ /*0x018a*/ 127,
+ /*0x021a*/ 203,
+ /*0x1c9a*/ 549,
/*0x1f9c*/ 795,
/*0x041c*/ 325,
/*0x011c*/ 71,
- /*0x1041c*/ 1291,
- /*0x0220*/ 206,
- /*0xab9c*/ 1189,
- /*0x017d*/ 119,
- /*0x049a*/ 370,
- -1,
- /*0x13fb*/ 527,
+ /*0x1041c*/ 1296,
+ /*0x2c64*/ 962,
+ /*0xab9c*/ 1194,
+ /*0x1ee4*/ 701,
+ /*0x1e64*/ 635,
+ /*0x03a6*/ 262,
+ /*0x1e918*/ 1518,
/*0x2c1c*/ 939,
-1,
- /*0x1e91a*/ 1480,
+ /*0x01f1*/ 181,
/*0x1e1c*/ 599,
- /*0x1f6f*/ 766,
- -1,
- /*0x1f1a*/ 725,
- /*0x216f*/ 883,
- -1, -1, -1,
- /*0x2c9c*/ 987,
- /*0x13fd*/ 529,
- -1,
+ /*0x03a4*/ 260,
+ /*0x0220*/ 206,
+ /*0x1ca0*/ 555,
/*0x0496*/ 368,
- /*0x2167*/ 875,
+ -1, -1,
+ /*0x0190*/ 131,
+ /*0x2c9c*/ 988,
+ -1, -1, -1,
+ /*0x03f7*/ 291,
+ /*0x1e906*/ 1500,
-1,
- /*0x1ca6*/ 561,
- /*0xa79c*/ 1116,
- /*0x1e916*/ 1476,
- /*0x1fdb*/ 843,
- /*0x10c9c*/ 1367,
+ /*0xa79c*/ 1117,
-1, -1,
- /*0x2163*/ 871,
+ /*0x10c9c*/ 1407,
+ /*0x051c*/ 435,
-1,
- /*0x00db*/ 52,
- /*0x0226*/ 209,
- /*0x1faa*/ 809,
- /*0x042a*/ 339,
- /*0x012a*/ 78,
- /*0x0490*/ 365,
+ /*0x0492*/ 366,
+ /*0x1fa7*/ 806,
+ /*0x0427*/ 336,
+ /*0x0198*/ 137,
+ /*0x10427*/ 1307,
+ /*0x1ff9*/ 860,
+ /*0xaba7*/ 1205,
+ /*0x0179*/ 117,
-1,
- /*0xabaa*/ 1203,
- /*0x1ca4*/ 559,
+ /*0x1e916*/ 1516,
+ /*0x1f69*/ 760,
+ /*0x2c27*/ 950,
+ /*0x1f08*/ 715,
-1,
- /*0x1e910*/ 1470,
+ /*0x03e0*/ 279,
+ /*0x0226*/ 209,
+ /*0x1ca6*/ 561,
+ /*0x049a*/ 370,
+ /*0x1f09*/ 716,
-1,
- /*0x2c2a*/ 953,
- /*0x039c*/ 253,
- /*0x1eaa*/ 672,
- /*0x1e2a*/ 606,
- /*0x1f5d*/ 757,
- /*0x03fd*/ 294,
+ /*0x0186*/ 124,
/*0x0224*/ 208,
- /*0x1f8e*/ 781,
- /*0x040e*/ 311,
- /*0x010e*/ 64,
- /*0x1040e*/ 1277,
- /*0x2caa*/ 994,
- /*0xab8e*/ 1175,
- /*0x051e*/ 436,
- -1,
- /*0x1e906*/ 1460,
- -1,
- /*0x2c0e*/ 925,
- /*0xa7aa*/ 1123,
- /*0x1e8e*/ 656,
- /*0x1e0e*/ 592,
- /*0x10caa*/ 1381,
- -1, -1, -1, -1, -1,
- /*0x0492*/ 366,
- /*0x2c8e*/ 980,
- -1,
- /*0x0514*/ 431,
- -1,
- /*0x1e912*/ 1472,
+ /*0x1ca4*/ 559,
+ -1, -1, -1,
+ /*0x1e912*/ 1512,
+ /*0x01d9*/ 169,
-1,
- /*0x1c83*/ 533,
+ /*0x1f0a*/ 717,
-1,
- /*0x0189*/ 126,
- /*0x01f1*/ 181,
- /*0x10c8e*/ 1353,
- /*0x03aa*/ 266,
+ /*0x039e*/ 255,
+ /*0x10ca7*/ 1418,
-1,
+ /*0x04a0*/ 373,
/*0x1faf*/ 814,
/*0x042f*/ 344,
- /*0xa779*/ 1101,
- /*0x04a0*/ 373,
- -1,
- /*0xabaf*/ 1208,
- /*0x018a*/ 127,
+ /*0x0196*/ 135,
-1,
- /*0x1e920*/ 1486,
+ /*0x10579*/ 1353,
+ /*0xabaf*/ 1213,
-1, -1,
+ /*0x1e91a*/ 1520,
+ /*0x017d*/ 119,
+ /*0x2c2f*/ 958,
+ -1,
+ /*0xfb00*/ 1230,
+ /*0x0394*/ 245,
/*0x1f84*/ 771,
/*0x0404*/ 301,
/*0x0104*/ 59,
- /*0x10404*/ 1267,
- /*0x038e*/ 239,
- /*0xab84*/ 1165,
- -1, -1, -1,
- /*0x1c9e*/ 553,
- /*0x2c04*/ 915,
+ /*0x10404*/ 1272,
-1,
+ /*0xab84*/ 1170,
+ -1, -1,
+ /*0x1f5f*/ 758,
+ /*0x1f5d*/ 757,
+ /*0x2c04*/ 915,
+ /*0x1e920*/ 1526,
/*0x1e84*/ 651,
/*0x1e04*/ 587,
- -1, -1, -1, -1,
- /*0x0198*/ 137,
- /*0x021e*/ 205,
- /*0x10caf*/ 1386,
- /*0x2c84*/ 975,
- /*0x1fae*/ 813,
- /*0x042e*/ 343,
- /*0x012e*/ 80,
+ -1, -1, -1,
+ /*0x10caf*/ 1426,
+ -1,
/*0x04a6*/ 376,
- /*0x1c94*/ 543,
- /*0xabae*/ 1207,
- /*0xa784*/ 1107,
- -1, -1,
- /*0x10c84*/ 1343,
- /*0x2c2e*/ 957,
+ /*0x1f18*/ 723,
+ /*0x2c84*/ 976,
-1,
- /*0x1eae*/ 674,
- /*0x1e2e*/ 608,
- /*0x0214*/ 200,
- /*0x2126*/ 864,
- -1, -1, -1,
- /*0x051c*/ 435,
+ /*0x021e*/ 205,
+ /*0x1c9e*/ 553,
/*0x04a4*/ 375,
- /*0x2cae*/ 996,
+ /*0x1f6f*/ 766,
+ /*0x1057d*/ 1356,
+ /*0xa784*/ 1108,
+ -1, -1,
+ /*0x10c84*/ 1383,
+ /*0x0504*/ 423,
/*0x1f82*/ 769,
/*0x0402*/ 299,
/*0x0102*/ 58,
- /*0x10402*/ 1265,
+ /*0x10402*/ 1270,
-1,
- /*0xab82*/ 1163,
- /*0xa7ae*/ 1127,
+ /*0xab82*/ 1168,
+ /*0x01a0*/ 141,
+ /*0x0214*/ 200,
+ /*0x1c94*/ 543,
-1,
- /*0x0196*/ 135,
- /*0x10cae*/ 1385,
/*0x2c02*/ 913,
- -1,
+ /*0x1f59*/ 755,
/*0x1e82*/ 650,
/*0x1e02*/ 586,
+ /*0x01d7*/ 168,
+ /*0x13f9*/ 525,
+ /*0xfb06*/ 1236,
+ /*0x1fa2*/ 801,
+ /*0x0422*/ 331,
+ /*0x0122*/ 74,
+ /*0x10422*/ 1302,
+ /*0x2c82*/ 975,
+ /*0xaba2*/ 1200,
+ -1, -1,
+ /*0x1c83*/ 533,
+ /*0x04e0*/ 405,
+ /*0x2c22*/ 945,
+ /*0xa782*/ 1107,
+ /*0x1ea2*/ 668,
+ /*0x1e22*/ 602,
+ /*0x10c82*/ 1381,
+ /*0x0502*/ 422,
+ /*0xfb16*/ 1240,
-1,
- /*0x1f6b*/ 762,
+ /*0x0241*/ 220,
+ /*0x03e4*/ 281,
-1,
- /*0x01f7*/ 185,
- /*0x216b*/ 879,
- /*0x1f6d*/ 764,
- /*0x10aa*/ 494,
- /*0x2c82*/ 974,
- /*0x216d*/ 881,
- -1, -1,
- /*0x0190*/ 131,
- /*0x1fd9*/ 841,
- /*0x0059*/ 23,
- /*0xa782*/ 1106,
+ /*0x2ca2*/ 991,
+ -1,
+ /*0x01a6*/ 144,
+ -1,
+ /*0x039c*/ 253,
+ /*0x049e*/ 372,
+ -1,
+ /*0xa7a2*/ 1120,
+ /*0x01a4*/ 143,
+ -1,
+ /*0x10ca2*/ 1413,
+ /*0x0522*/ 438,
+ -1,
+ /*0x10a0*/ 484,
+ /*0x13fd*/ 529,
-1, -1,
- /*0x10c82*/ 1341,
- /*0x00d9*/ 50,
- /*0x1fa7*/ 806,
- /*0x0427*/ 336,
- /*0x052a*/ 442,
- /*0x10427*/ 1302,
+ /*0x1f1a*/ 725,
+ /*0x2165*/ 873,
+ /*0x01f7*/ 185,
+ /*0x2169*/ 877,
+ /*0x2161*/ 869,
+ /*0x0494*/ 367,
+ /*0x1faa*/ 809,
+ /*0x042a*/ 339,
+ /*0x012a*/ 78,
+ /*0xa660*/ 1043,
-1,
- /*0xaba7*/ 1200,
+ /*0xabaa*/ 1208,
-1, -1,
- /*0x1e903*/ 1457,
- /*0x0186*/ 124,
- /*0x2c27*/ 950,
+ /*0x1e91e*/ 1524,
-1,
- /*0x1c9c*/ 551,
- /*0x1fa2*/ 801,
- /*0x0422*/ 331,
- /*0x0122*/ 74,
- /*0x10422*/ 1297,
+ /*0x2c2a*/ 953,
-1,
- /*0xaba2*/ 1195,
- /*0x050e*/ 428,
+ /*0x1eaa*/ 672,
+ /*0x1e2a*/ 606,
+ -1, -1,
+ /*0x03a7*/ 263,
-1, -1,
+ /*0x01e0*/ 172,
+ /*0x03f9*/ 292,
+ /*0x2caa*/ 995,
/*0x021c*/ 204,
- /*0x2c22*/ 945,
+ /*0x1c9c*/ 551,
+ /*0x10a6*/ 490,
+ /*0x1e914*/ 1514,
-1,
- /*0x1ea2*/ 668,
- /*0x1e22*/ 602,
+ /*0x04c1*/ 390,
+ /*0xa7aa*/ 1124,
+ /*0x104c1*/ 1325,
+ /*0x10a4*/ 488,
+ /*0x10caa*/ 1421,
+ /*0x052a*/ 442,
+ /*0x1fae*/ 813,
+ /*0x042e*/ 343,
+ /*0x012e*/ 80,
+ -1, -1,
+ /*0xabae*/ 1212,
/*0x1fac*/ 811,
/*0x042c*/ 341,
/*0x012c*/ 79,
- /*0x049e*/ 372,
- /*0x10ca7*/ 1378,
- /*0xabac*/ 1205,
- /*0xfb00*/ 1225,
- /*0x2ca2*/ 990,
- /*0x1e91e*/ 1484,
+ /*0x1e903*/ 1497,
+ /*0x2c2e*/ 957,
+ /*0xabac*/ 1210,
+ /*0x1eae*/ 674,
+ /*0x1e2e*/ 608,
+ /*0x118a0*/ 1430,
-1,
/*0x2c2c*/ 955,
- /*0x10af*/ 499,
+ -1,
/*0x1eac*/ 673,
/*0x1e2c*/ 607,
- /*0xa7a2*/ 1119,
- -1,
- /*0x01a0*/ 141,
- /*0x10ca2*/ 1373,
+ /*0x0194*/ 134,
+ /*0x2cae*/ 997,
-1, -1,
- /*0x0494*/ 367,
- /*0x2cac*/ 995,
- /*0x03a7*/ 263,
- /*0x1caa*/ 565,
+ /*0x03fd*/ 294,
+ /*0x1ca7*/ 562,
-1,
- /*0x1e914*/ 1474,
+ /*0x2cac*/ 996,
+ /*0xa7ae*/ 1128,
+ /*0x216f*/ 883,
-1,
- /*0x1fb2*/ 815,
- /*0xa7ac*/ 1125,
- /*0x0132*/ 81,
+ /*0x10cae*/ 1425,
+ /*0x052e*/ 444,
-1,
- /*0x10cac*/ 1383,
- /*0xabb2*/ 1211,
- /*0x022a*/ 211,
- -1, -1, -1,
- /*0x0504*/ 423,
+ /*0xa7ac*/ 1126,
-1,
- /*0x1eb2*/ 676,
- /*0x1e32*/ 610,
+ /*0x04e4*/ 407,
+ /*0x10cac*/ 1423,
+ /*0x052c*/ 443,
/*0x1fa8*/ 807,
/*0x0428*/ 337,
/*0x0128*/ 77,
- /*0x10ae*/ 498,
- -1,
- /*0xaba8*/ 1201,
+ /*0x049c*/ 371,
-1,
- /*0x2cb2*/ 998,
- /*0x01a6*/ 144,
- /*0x020e*/ 197,
+ /*0xaba8*/ 1206,
+ -1, -1, -1,
+ /*0x118a6*/ 1436,
/*0x2c28*/ 951,
-1,
/*0x1ea8*/ 671,
/*0x1e28*/ 605,
- /*0xa7b2*/ 1130,
- -1,
- /*0xfb16*/ 1235,
- /*0x10cb2*/ 1389,
- /*0x052e*/ 444,
-1,
- /*0x118a0*/ 1390,
- /*0x2ca8*/ 993,
+ /*0x118a4*/ 1434,
-1, -1,
- /*0xa726*/ 1065,
- /*0x01a4*/ 143,
+ /*0x1f6b*/ 762,
+ /*0xff26*/ 1247,
+ /*0x1caf*/ 570,
+ /*0x2ca8*/ 994,
-1, -1,
- /*0xa7a8*/ 1122,
- /*0xff26*/ 1242,
- -1,
- /*0x10ca8*/ 1379,
+ /*0x2167*/ 875,
+ /*0xff24*/ 1245,
-1,
- /*0x1caf*/ 570,
- -1, -1, -1, -1, -1, -1,
- /*0x0502*/ 422,
- /*0xa724*/ 1064,
- /*0x049c*/ 371,
+ /*0x24c1*/ 896,
+ /*0xa7a8*/ 1123,
+ /*0x1e91c*/ 1522,
-1,
+ /*0x10ca8*/ 1419,
+ /*0x0528*/ 441,
+ /*0x0204*/ 192,
/*0x1c84*/ 534,
+ /*0xa664*/ 1045,
-1,
- /*0xff24*/ 1240,
- /*0x1e91c*/ 1482,
+ /*0x1f8e*/ 781,
+ /*0x040e*/ 311,
+ /*0x010e*/ 64,
+ /*0x1040e*/ 1282,
+ /*0xa77b*/ 1103,
+ /*0xab8e*/ 1180,
+ /*0x1f8c*/ 779,
+ /*0x040c*/ 309,
+ /*0x010c*/ 63,
+ /*0x1040c*/ 1280,
+ /*0x2c0e*/ 925,
+ /*0xab8c*/ 1178,
+ /*0x1e8e*/ 656,
+ /*0x1e0e*/ 592,
+ /*0x01e4*/ 174,
-1,
- /*0x03a8*/ 264,
- /*0xfb06*/ 1231,
- /*0x1f1c*/ 727,
+ /*0x2c0c*/ 923,
+ /*0x10c1*/ 517,
+ /*0x1e8c*/ 655,
+ /*0x1e0c*/ 591,
+ /*0x019c*/ 138,
+ /*0x2c8e*/ 981,
+ /*0xfb14*/ 1238,
+ -1, -1, -1,
+ /*0x1f6d*/ 764,
+ /*0x2c8c*/ 980,
-1,
- /*0x118a6*/ 1396,
- /*0x0204*/ 192,
+ /*0x0202*/ 191,
+ /*0x1c82*/ 532,
+ /*0x10c8e*/ 1393,
+ /*0x050e*/ 428,
+ -1, -1, -1, -1,
+ /*0x10c8c*/ 1391,
+ /*0x050c*/ 427,
+ /*0xfb03*/ 1233,
+ /*0x1fb2*/ 815,
-1,
+ /*0x0132*/ 81,
+ -1, -1,
+ /*0xabb2*/ 1216,
+ /*0x0222*/ 207,
+ /*0x1ca2*/ 557,
+ /*0xa726*/ 1066,
+ /*0x03aa*/ 266,
+ -1, -1,
+ /*0x1eb2*/ 676,
+ /*0x1e32*/ 610,
+ /*0xa724*/ 1065,
+ /*0x01a7*/ 145,
+ -1, -1, -1, -1, -1,
+ /*0x2cb2*/ 999,
+ /*0x0054*/ 18,
+ /*0x0154*/ 98,
/*0x1fb8*/ 820,
-1,
- /*0x10a7*/ 491,
- -1, -1,
- /*0xabb8*/ 1217,
- /*0x1f8c*/ 779,
- /*0x040c*/ 309,
- /*0x010c*/ 63,
- /*0x1040c*/ 1275,
- /*0x1cae*/ 569,
- /*0xab8c*/ 1173,
+ /*0x2126*/ 864,
+ -1,
+ /*0xa7b2*/ 1131,
+ /*0xabb8*/ 1222,
+ -1,
+ /*0x10cb2*/ 1429,
+ /*0x0532*/ 446,
+ /*0x1ed4*/ 693,
+ /*0x1e54*/ 627,
+ /*0x1e904*/ 1498,
/*0x1eb8*/ 679,
/*0x1e38*/ 613,
- /*0x118a4*/ 1394,
- /*0x10a2*/ 486,
- /*0x2c0c*/ 923,
+ -1, -1,
+ /*0x00d4*/ 46,
+ /*0x2163*/ 871,
+ /*0x2cd4*/ 1016,
+ -1, -1,
+ /*0x2cb8*/ 1002,
+ /*0x1f1c*/ 727,
-1,
- /*0x1e8c*/ 655,
- /*0x1e0c*/ 591,
- /*0x022e*/ 213,
- /*0x2cb8*/ 1001,
+ /*0xa760*/ 1094,
+ /*0x01af*/ 149,
+ /*0x022a*/ 211,
+ /*0x1caa*/ 565,
+ /*0xa7b8*/ 1135,
+ /*0x0554*/ 480,
+ -1, -1,
+ /*0x0538*/ 452,
+ -1, -1,
+ /*0x04a2*/ 374,
+ /*0x10a7*/ 491,
/*0x1ffc*/ 863,
/*0x047c*/ 359,
- /*0x04aa*/ 378,
- /*0x1f5b*/ 756,
+ /*0x0184*/ 123,
+ -1,
/*0x1fba*/ 822,
- /*0x2c8c*/ 979,
- /*0xa7b8*/ 1134,
- /*0x10ac*/ 496,
- /*0x0522*/ 438,
- /*0xabba*/ 1219,
- /*0x1c82*/ 532,
- /*0x1f2a*/ 731,
+ /*0x2160*/ 868,
+ -1,
+ /*0x1e902*/ 1496,
+ -1,
+ /*0xabba*/ 1224,
+ /*0x216b*/ 879,
+ -1,
/*0x1efc*/ 713,
/*0x1e7c*/ 647,
- /*0x212a*/ 865,
- /*0x10c8c*/ 1351,
+ -1, -1,
/*0x1eba*/ 680,
/*0x1e3a*/ 614,
- /*0x13fc*/ 528,
- /*0x048e*/ 364,
- /*0x0202*/ 191,
+ -1, -1,
+ /*0x03a8*/ 264,
-1,
- /*0x052c*/ 443,
+ /*0x022e*/ 213,
+ /*0x1cae*/ 569,
-1,
- /*0x1e90e*/ 1468,
- /*0x2cba*/ 1002,
+ /*0x2cba*/ 1003,
-1, -1,
- /*0x1f0e*/ 721,
- /*0x0194*/ 134,
+ /*0x022c*/ 212,
+ /*0x1cac*/ 567,
-1, -1,
- /*0xa7ba*/ 1135,
- /*0x038c*/ 238,
- /*0x10b2*/ 502,
- /*0x0130*/ 1489,
- /*0x01d7*/ 168,
+ /*0xa7ba*/ 1136,
+ /*0x10af*/ 499,
+ /*0x1057c*/ 1355,
+ /*0x0182*/ 122,
+ /*0x053a*/ 454,
+ -1, -1, -1, -1, -1,
+ /*0x04aa*/ 378,
+ /*0x1f8d*/ 780,
+ /*0x040d*/ 310,
-1,
- /*0xabb0*/ 1209,
- /*0x1fbe*/ 825,
+ /*0x1040d*/ 1281,
+ -1,
+ /*0xab8d*/ 1179,
-1, -1, -1,
- /*0x1ca7*/ 562,
- /*0xabbe*/ 1223,
+ /*0x01a2*/ 142,
+ /*0x2c0d*/ 924,
+ /*0x1f2f*/ 736,
+ /*0x216d*/ 881,
+ /*0x118a7*/ 1437,
+ /*0x038e*/ 239,
+ -1, -1, -1,
+ /*0x0228*/ 210,
+ /*0x1ca8*/ 563,
+ /*0x038c*/ 238,
+ -1, -1,
+ /*0xff27*/ 1248,
+ /*0x0130*/ 1529,
+ -1, -1,
+ /*0xabb0*/ 1214,
+ /*0xa78d*/ 1111,
+ -1, -1,
+ /*0x10c8d*/ 1392,
+ /*0x04ae*/ 380,
+ /*0x1fdb*/ 843,
/*0x1eb0*/ 675,
/*0x1e30*/ 609,
-1,
- /*0x10a8*/ 492,
- /*0x0532*/ 446,
+ /*0xfb04*/ 1234,
+ /*0x04ac*/ 379,
+ -1, -1, -1, -1,
+ /*0x2cb0*/ 998,
+ -1, -1,
+ /*0x1fbe*/ 825,
+ /*0x118af*/ 1445,
+ /*0xa764*/ 1096,
+ /*0x13fc*/ 528,
+ /*0xa7b0*/ 1129,
+ /*0xabbe*/ 1228,
+ /*0x00db*/ 52,
+ /*0x10cb0*/ 1427,
+ /*0x10a2*/ 486,
+ /*0x020e*/ 197,
-1,
+ /*0xff2f*/ 1256,
/*0x1ebe*/ 682,
/*0x1e3e*/ 616,
-1,
- /*0x2cb0*/ 997,
- -1,
- /*0x1ca2*/ 557,
+ /*0x020c*/ 196,
+ /*0x1fd3*/ 837,
+ /*0x0053*/ 17,
+ -1, -1,
+ /*0x2164*/ 872,
+ /*0x2cbe*/ 1005,
+ -1, -1,
+ /*0xfb02*/ 1232,
+ /*0x04a8*/ 377,
+ -1, -1,
+ /*0xa7be*/ 1138,
-1, -1, -1,
- /*0x2cbe*/ 1004,
- /*0xa7b0*/ 1128,
- /*0x1f2f*/ 736,
- /*0x0528*/ 441,
- /*0x10cb0*/ 1387,
- -1,
- /*0x0222*/ 207,
- /*0xa7be*/ 1137,
- -1,
- /*0x1e904*/ 1458,
- /*0x1cac*/ 567,
- -1,
+ /*0x053e*/ 458,
+ -1, -1,
+ /*0x00d3*/ 45,
+ -1, -1, -1, -1,
+ /*0x01ae*/ 148,
+ -1, -1, -1, -1, -1,
+ /*0x01ac*/ 147,
+ /*0xa779*/ 1102,
+ /*0x0553*/ 479,
+ /*0x0232*/ 215,
+ /*0x1cb2*/ 573,
/*0x1fb6*/ 818,
- -1,
+ /*0x10aa*/ 494,
/*0x0136*/ 83,
-1, -1,
- /*0xabb6*/ 1215,
- /*0x1f8d*/ 780,
- /*0x040d*/ 310,
- /*0x022c*/ 212,
- /*0x1040d*/ 1276,
- /*0x03b0*/ 268,
- /*0xab8d*/ 1174,
+ /*0xabb6*/ 1220,
+ /*0x1fca*/ 833,
+ /*0x004a*/ 8,
+ /*0x014a*/ 93,
+ -1, -1,
+ /*0x048e*/ 364,
/*0x1eb6*/ 678,
/*0x1e36*/ 612,
- /*0x04ae*/ 380,
+ /*0x118a2*/ 1432,
+ -1, -1,
+ /*0x048c*/ 363,
+ /*0x1eca*/ 688,
+ /*0x1e4a*/ 622,
-1,
- /*0x2c0d*/ 924,
- -1, -1, -1,
- /*0x019c*/ 138,
- /*0x2cb6*/ 1000,
- /*0xfb03*/ 1228,
- /*0x1f2e*/ 735,
+ /*0x2cb6*/ 1001,
+ /*0x1f2a*/ 731,
+ /*0x1cb8*/ 579,
+ /*0xff22*/ 1243,
+ /*0x00ca*/ 36,
-1,
- /*0x1cb2*/ 573,
+ /*0x2cca*/ 1011,
+ /*0xa7b6*/ 1134,
+ -1, -1, -1,
+ /*0x0536*/ 450,
+ /*0xa77d*/ 1104,
+ /*0x10ae*/ 498,
+ /*0x1fcb*/ 834,
+ /*0x004b*/ 9,
+ /*0x1e90e*/ 1508,
+ /*0x054a*/ 470,
-1,
- /*0xa77b*/ 1102,
- /*0xa7b6*/ 1133,
+ /*0x10ac*/ 496,
-1, -1,
- /*0x1fb4*/ 817,
- /*0x10b8*/ 508,
- /*0x0134*/ 82,
- /*0xa78d*/ 1110,
- /*0x0232*/ 215,
- /*0xabb4*/ 1213,
- /*0x10c8d*/ 1352,
+ /*0x1e90c*/ 1506,
+ -1, -1, -1,
+ /*0x1f87*/ 774,
+ /*0x0407*/ 304,
-1,
- /*0x1ca8*/ 563,
- /*0xa77d*/ 1103,
- /*0x1e902*/ 1456,
+ /*0x10407*/ 1275,
+ /*0x04b2*/ 382,
+ /*0xab87*/ 1173,
+ /*0x104b2*/ 1310,
+ /*0x00cb*/ 37,
+ /*0x1f2e*/ 735,
-1,
- /*0x1eb4*/ 677,
- /*0x1e34*/ 611,
+ /*0x2c07*/ 918,
+ /*0x118aa*/ 1440,
-1, -1,
- /*0x0538*/ 452,
+ /*0x1f2c*/ 733,
-1,
- /*0x0228*/ 210,
- /*0x01db*/ 170,
+ /*0x023a*/ 216,
+ /*0x1cba*/ 581,
+ /*0x018e*/ 129,
-1,
- /*0x2cb4*/ 999,
- /*0x050c*/ 427,
+ /*0x054b*/ 471,
+ /*0xff2a*/ 1251,
-1, -1, -1,
- /*0x1fbc*/ 824,
- /*0x10ba*/ 510,
- /*0xa7b4*/ 1132,
- /*0xa688*/ 1053,
- -1,
- /*0xabbc*/ 1221,
+ /*0x04d4*/ 399,
+ /*0x10a8*/ 492,
+ /*0x1fb4*/ 817,
+ /*0x04b8*/ 385,
+ /*0x0134*/ 82,
+ /*0x104b8*/ 1316,
+ /*0x10c87*/ 1386,
+ /*0xabb4*/ 1218,
-1, -1, -1,
- /*0xfb14*/ 1233,
- -1, -1,
- /*0x1ebc*/ 681,
- /*0x1e3c*/ 615,
- /*0x1f59*/ 755,
- -1,
- /*0x053a*/ 454,
- /*0xa72a*/ 1067,
- /*0x018e*/ 129,
- /*0x0055*/ 19,
- /*0xa68a*/ 1054,
- /*0x2cbc*/ 1003,
- /*0xff2a*/ 1246,
- -1,
- /*0x00d5*/ 47,
- /*0x04a2*/ 374,
- /*0xa680*/ 1049,
- /*0x24b8*/ 887,
- /*0xa7bc*/ 1136,
- -1,
- /*0x10b0*/ 500,
- -1, -1, -1, -1, -1,
- /*0x10be*/ 514,
+ /*0x03b0*/ 268,
+ /*0xab71*/ 1151,
-1,
- /*0x1cb8*/ 579,
- /*0x04ac*/ 379,
- -1, -1, -1,
- /*0xa698*/ 1061,
+ /*0x1eb4*/ 677,
+ /*0x1e34*/ 611,
+ -1, -1,
+ /*0xa722*/ 1064,
+ /*0x118ae*/ 1444,
-1, -1,
- /*0x118aa*/ 1400,
+ /*0x1f28*/ 729,
+ /*0x2cb4*/ 1000,
-1,
- /*0x1f2c*/ 733,
+ /*0x118ac*/ 1442,
+ /*0xab73*/ 1153,
-1, -1,
- /*0x053e*/ 458,
- /*0x01af*/ 149,
- /*0x24ba*/ 889,
- /*0x020c*/ 196,
- -1, -1, -1, -1, -1,
- /*0xa69a*/ 1062,
+ /*0xff2e*/ 1255,
+ /*0xa7b4*/ 1133,
-1, -1,
- /*0x0184*/ 123,
- /*0x1cba*/ 581,
+ /*0x01b2*/ 151,
+ /*0x0534*/ 448,
+ /*0xff2c*/ 1253,
+ -1, -1,
+ /*0xa654*/ 1037,
-1,
- /*0x04b2*/ 382,
- /*0x03d5*/ 273,
- /*0x104b2*/ 1305,
- /*0x10b6*/ 506,
- /*0x1fca*/ 833,
- /*0x004a*/ 8,
- /*0x014a*/ 93,
- /*0xff2f*/ 1251,
- /*0x023a*/ 216,
+ /*0x04fc*/ 419,
-1,
- /*0x00ca*/ 36,
- /*0xa696*/ 1060,
- /*0x2132*/ 867,
+ /*0x1fbc*/ 824,
+ /*0x10588*/ 1367,
+ /*0x04ba*/ 386,
-1,
- /*0x04a8*/ 377,
+ /*0x104ba*/ 1318,
+ /*0xabbc*/ 1226,
-1,
- /*0x1eca*/ 688,
- /*0x1e4a*/ 622,
- /*0x0536*/ 450,
- /*0x01ae*/ 148,
+ /*0x10589*/ 1368,
-1, -1,
- /*0x24be*/ 893,
- /*0x1f28*/ 729,
+ /*0x0230*/ 214,
+ /*0x1cb0*/ 571,
+ /*0x1ebc*/ 681,
+ /*0x1e3c*/ 615,
-1,
- /*0x2cca*/ 1010,
+ /*0x01b8*/ 155,
+ /*0x118a8*/ 1438,
+ /*0x1f0e*/ 721,
+ /*0x1058a*/ 1369,
-1,
- /*0x1cb0*/ 571,
- /*0xa690*/ 1057,
- -1, -1,
- /*0x118af*/ 1405,
+ /*0xa72a*/ 1068,
+ /*0x2cbc*/ 1004,
-1,
- /*0x1cbe*/ 583,
- /*0x10b4*/ 504,
- /*0xa72e*/ 1069,
+ /*0x1f0c*/ 719,
+ /*0x10580*/ 1359,
-1,
- /*0x0230*/ 214,
- -1, -1,
- /*0xff2e*/ 1250,
- /*0x0182*/ 122,
+ /*0xff28*/ 1249,
-1,
+ /*0xa7bc*/ 1137,
+ -1, -1, -1,
+ /*0x053c*/ 456,
+ /*0x24b8*/ 887,
/*0x023e*/ 219,
+ /*0x1cbe*/ 583,
+ /*0x10b2*/ 502,
-1,
- /*0xa686*/ 1052,
+ /*0x212a*/ 865,
+ -1, -1,
+ /*0x10590*/ 1374,
-1, -1, -1,
- /*0x0534*/ 448,
- -1, -1, -1, -1, -1,
- /*0x24b6*/ 885,
- /*0x1ff6*/ 857,
- /*0x0476*/ 356,
- /*0x0176*/ 115,
- -1,
- /*0x10bc*/ 512,
+ /*0x1fd6*/ 838,
+ /*0x0056*/ 20,
+ /*0x0156*/ 99,
+ -1, -1, -1, -1,
+ /*0x01fc*/ 188,
+ /*0xa72e*/ 1070,
+ -1, -1, -1,
+ /*0x1ed6*/ 694,
+ /*0x1e56*/ 628,
+ /*0xa72c*/ 1069,
+ /*0x10b8*/ 508,
+ -1, -1,
+ /*0x04b0*/ 381,
+ /*0x00d6*/ 48,
+ /*0x104b0*/ 1308,
+ /*0x2cd6*/ 1017,
+ /*0x1e90d*/ 1507,
-1,
- /*0xa692*/ 1058,
+ /*0xab7f*/ 1165,
+ /*0xab7b*/ 1161,
+ -1, -1,
+ /*0xa7d6*/ 1147,
+ /*0x24ba*/ 889,
+ /*0x10586*/ 1365,
+ /*0xab75*/ 1155,
+ /*0x0556*/ 482,
+ /*0x1f54*/ 753,
+ -1, -1,
+ /*0x1f38*/ 737,
-1,
- /*0x118ae*/ 1404,
+ /*0x1fc4*/ 828,
+ /*0x0044*/ 3,
-1,
/*0x1cb6*/ 577,
- /*0x01d9*/ 169,
- /*0x1ef6*/ 710,
- /*0x1e76*/ 644,
- /*0x04b8*/ 385,
+ /*0x04be*/ 388,
-1,
- /*0x104b8*/ 1311,
+ /*0x104be*/ 1322,
-1,
- /*0x01a7*/ 145,
- /*0x053c*/ 456,
- /*0x048c*/ 363,
- -1, -1,
- /*0x1f38*/ 737,
+ /*0x024a*/ 226,
+ /*0xa728*/ 1067,
+ /*0x118b2*/ 1448,
-1,
- /*0x1e90c*/ 1466,
+ /*0x1ec4*/ 685,
+ /*0x1e44*/ 619,
+ /*0xa688*/ 1054,
-1, -1, -1,
- /*0x1f0c*/ 719,
+ /*0x10ba*/ 510,
+ /*0x00c4*/ 30,
+ /*0xff32*/ 1259,
+ /*0x2cc4*/ 1008,
+ /*0x104d3*/ 1343,
+ -1, -1, -1,
+ /*0x10592*/ 1376,
-1,
- /*0x01a2*/ 142,
- /*0x1fc9*/ 832,
- /*0x0049*/ 1488,
- /*0x0149*/ 92,
+ /*0xa7c4*/ 1141,
+ /*0x0050*/ 14,
+ /*0x0150*/ 96,
+ /*0xa68a*/ 1055,
+ /*0x0544*/ 464,
-1,
- /*0x04fc*/ 419,
- /*0x0555*/ 481,
- /*0x00c9*/ 35,
- /*0xff27*/ 1243,
- /*0x04ba*/ 386,
- /*0x1cb4*/ 575,
- /*0x104ba*/ 1313,
+ /*0x118b8*/ 1454,
-1, -1,
- /*0x01ac*/ 147,
- -1,
- /*0xa722*/ 1063,
+ /*0xa680*/ 1050,
-1,
/*0x1f3a*/ 739,
- /*0xfb04*/ 1229,
- -1,
- /*0xff22*/ 1238,
- -1, -1, -1,
- /*0x24bc*/ 891,
- -1, -1, -1,
- /*0xa7c9*/ 1143,
- /*0xa72c*/ 1068,
- -1,
- /*0x118a7*/ 1397,
- -1, -1,
- /*0xff2c*/ 1248,
+ /*0x1ed0*/ 691,
+ /*0x1e50*/ 625,
-1, -1,
- /*0x04b0*/ 381,
+ /*0xff38*/ 1265,
+ /*0x01db*/ 170,
-1,
- /*0x104b0*/ 1303,
- /*0x01b2*/ 151,
+ /*0x00d0*/ 42,
+ /*0xab77*/ 1157,
+ /*0x2cd0*/ 1014,
+ /*0x1c87*/ 537,
+ -1, -1, -1,
+ /*0xa690*/ 1058,
+ /*0x04b6*/ 384,
+ /*0xa7d0*/ 1146,
+ /*0x104b6*/ 1314,
-1, -1,
- /*0x04be*/ 388,
- /*0x118a2*/ 1392,
- /*0x104be*/ 1317,
+ /*0x0550*/ 476,
+ /*0x16e5f*/ 1493,
+ /*0x16e5d*/ 1491,
+ /*0x104ca*/ 1334,
-1, -1, -1, -1,
- /*0x0376*/ 232,
- -1,
- /*0x1f3e*/ 743,
- /*0x1fc4*/ 828,
- /*0x0044*/ 3,
- /*0x0051*/ 15,
- /*0xa732*/ 1070,
- /*0x054a*/ 470,
- /*0x118ac*/ 1402,
- /*0x00c4*/ 30,
- /*0x00d1*/ 43,
- /*0xff32*/ 1254,
- /*0xfb02*/ 1227,
- -1, -1,
- /*0x1ec4*/ 685,
- /*0x1e44*/ 619,
/*0x1fcc*/ 835,
/*0x004c*/ 10,
/*0x014c*/ 94,
- /*0xa728*/ 1066,
- /*0x1ffa*/ 861,
- /*0x047a*/ 358,
- /*0x00cc*/ 38,
- /*0x2cc4*/ 1007,
- /*0xff28*/ 1244,
- /*0x04b6*/ 384,
- -1,
- /*0x104b6*/ 1309,
+ /*0xa698*/ 1062,
+ -1, -1,
+ /*0x01d3*/ 166,
+ /*0x118ba*/ 1456,
+ /*0x24be*/ 893,
+ /*0x1cb4*/ 575,
+ /*0x1f0d*/ 720,
+ /*0x10b0*/ 500,
/*0x1ecc*/ 689,
/*0x1e4c*/ 623,
- /*0xa7c4*/ 1139,
+ -1, -1, -1,
+ /*0xff3a*/ 1267,
+ /*0xa732*/ 1071,
+ /*0x00cc*/ 38,
+ /*0xa686*/ 1053,
+ /*0x2ccc*/ 1012,
+ /*0x04cb*/ 395,
-1,
- /*0x1efa*/ 712,
- /*0x1e7a*/ 646,
- /*0x118b2*/ 1408,
+ /*0x104cb*/ 1335,
+ -1, -1, -1, -1,
+ /*0x16e59*/ 1487,
-1,
- /*0x1e90d*/ 1467,
- /*0x2ccc*/ 1011,
- /*0x13fa*/ 526,
+ /*0xa64a*/ 1032,
+ /*0x054c*/ 472,
+ -1, -1,
+ /*0x10be*/ 514,
+ /*0x2132*/ 867,
+ /*0xa696*/ 1061,
+ -1,
+ /*0xa754*/ 1088,
+ -1, -1,
+ /*0xa738*/ 1074,
+ /*0x1f5b*/ 756,
-1,
- /*0x1f0d*/ 720,
/*0x1fc8*/ 831,
/*0x0048*/ 7,
- /*0x24ca*/ 905,
- -1,
- /*0x1fab*/ 810,
- /*0x042b*/ 340,
- /*0x00c8*/ 34,
- /*0x118a8*/ 1398,
+ /*0x01ca*/ 161,
+ -1, -1, -1, -1,
+ /*0x03d6*/ 274,
-1,
- /*0xabab*/ 1204,
+ /*0xa692*/ 1059,
-1,
- /*0x03d1*/ 272,
+ /*0x1f3e*/ 743,
/*0x1ec8*/ 687,
/*0x1e48*/ 621,
- /*0x2c2b*/ 954,
+ /*0x24b6*/ 885,
+ /*0x1e907*/ 1501,
/*0x04b4*/ 383,
-1,
- /*0x104b4*/ 1307,
- /*0x01b8*/ 155,
- -1, -1,
- /*0x2cc8*/ 1009,
+ /*0x104b4*/ 1312,
+ /*0x00c8*/ 34,
+ /*0x24ca*/ 905,
+ /*0x2cc8*/ 1010,
-1,
- /*0x024a*/ 226,
- /*0x1fc2*/ 826,
- /*0x0042*/ 1,
+ /*0x118b0*/ 1446,
-1, -1,
- /*0x03fa*/ 293,
- /*0xa64a*/ 1031,
- /*0x00c2*/ 28,
- /*0xa694*/ 1059,
- /*0xa7ab*/ 1124,
- -1,
- /*0xa738*/ 1073,
- /*0x10cab*/ 1382,
- /*0x1ec2*/ 684,
- /*0x1e42*/ 618,
- -1,
- /*0xff38*/ 1260,
- /*0x01fc*/ 188,
- /*0x04bc*/ 387,
- -1,
- /*0x104bc*/ 1315,
+ /*0xa69a*/ 1063,
-1,
- /*0x2cc2*/ 1006,
- -1, -1, -1,
- /*0x0549*/ 469,
- /*0x1f3c*/ 741,
+ /*0x004e*/ 12,
+ /*0x014e*/ 95,
-1,
- /*0xa7c2*/ 1138,
- /*0x03ab*/ 267,
+ /*0x01cb*/ 162,
+ /*0x0548*/ 468,
+ /*0xff30*/ 1257,
+ -1, -1, -1, -1,
+ /*0xa73a*/ 1075,
+ /*0x1ece*/ 690,
+ /*0x1e4e*/ 624,
+ /*0x10b6*/ 506,
-1,
- /*0x1fd6*/ 838,
- /*0x0056*/ 20,
- /*0x0156*/ 99,
+ /*0x0187*/ 125,
-1, -1,
- /*0xa73a*/ 1074,
- /*0x00d6*/ 48,
+ /*0x00ce*/ 40,
+ /*0x118be*/ 1460,
+ /*0x2cce*/ 1013,
+ /*0x24cb*/ 906,
+ /*0x1fc2*/ 826,
+ /*0x0042*/ 1,
-1,
- /*0x118b8*/ 1414,
+ /*0x16e57*/ 1485,
-1,
- /*0xff3a*/ 1262,
+ /*0x10594*/ 1377,
+ /*0x04bc*/ 387,
-1,
- /*0x1ed6*/ 694,
- /*0x1e56*/ 628,
+ /*0x104bc*/ 1320,
+ /*0x054e*/ 474,
+ -1, -1,
+ /*0x1ec2*/ 684,
+ /*0x1e42*/ 618,
/*0x1fd2*/ 836,
/*0x0052*/ 16,
/*0x0152*/ 97,
-1,
- /*0x03c2*/ 269,
+ /*0x1f4a*/ 747,
+ /*0x00c2*/ 28,
-1,
- /*0x00d2*/ 44,
- /*0x2cd6*/ 1016,
+ /*0x2cc2*/ 1007,
+ /*0x10583*/ 1362,
+ /*0x03d0*/ 271,
-1, -1,
- /*0x1fc6*/ 829,
- /*0x0046*/ 5,
/*0x1ed2*/ 692,
/*0x1e52*/ 626,
- -1, -1,
- /*0x00c6*/ 32,
- /*0x24c9*/ 904,
- /*0x10c4*/ 520,
+ /*0xa7c2*/ 1140,
+ -1, -1, -1,
+ /*0x0542*/ 462,
+ /*0x00d2*/ 44,
+ -1,
+ /*0x2cd2*/ 1015,
+ /*0x0244*/ 222,
+ -1, -1, -1,
+ /*0x1fc6*/ 829,
+ /*0x0046*/ 5,
-1,
- /*0x118ba*/ 1416,
- /*0x2cd2*/ 1014,
+ /*0x1fd8*/ 840,
+ /*0x0058*/ 22,
+ /*0x0158*/ 100,
+ /*0x0552*/ 478,
+ /*0x1f4b*/ 748,
+ /*0x118b6*/ 1452,
+ -1, -1,
+ /*0x04d6*/ 400,
/*0x1ec6*/ 686,
/*0x1e46*/ 620,
-1,
- /*0xff30*/ 1252,
- /*0xa73e*/ 1076,
- /*0x1fe2*/ 844,
- /*0x0462*/ 346,
- /*0x0162*/ 105,
- -1,
- /*0x2cc6*/ 1008,
+ /*0x1ed8*/ 695,
+ /*0x1e58*/ 629,
+ /*0xab79*/ 1159,
+ /*0xff36*/ 1263,
+ /*0x00c6*/ 32,
+ /*0x01bc*/ 156,
+ /*0x2cc6*/ 1009,
+ /*0x00d8*/ 49,
-1,
- /*0x0544*/ 464,
- /*0x0551*/ 477,
- /*0x03d6*/ 274,
+ /*0x2cd8*/ 1018,
+ /*0x10b4*/ 504,
+ -1, -1,
+ /*0xa7c6*/ 1143,
+ /*0x1fab*/ 810,
+ /*0x042b*/ 340,
+ /*0xa7d8*/ 1148,
+ /*0x0546*/ 466,
+ /*0xa73e*/ 1077,
+ /*0xabab*/ 1209,
-1,
- /*0x2c62*/ 959,
- /*0xa7c6*/ 1141,
- /*0x1ee2*/ 700,
- /*0x1e62*/ 634,
- -1, -1, -1,
- /*0x104ca*/ 1329,
- /*0x0050*/ 14,
- /*0x0150*/ 96,
- /*0x054c*/ 472,
- /*0x2ce2*/ 1022,
- /*0x118b0*/ 1406,
- /*0x00d0*/ 42,
- /*0x1f4a*/ 747,
+ /*0x1ec0*/ 683,
+ /*0x1e40*/ 617,
+ /*0x24bc*/ 891,
+ /*0x2c2b*/ 954,
-1, -1, -1,
- /*0x118be*/ 1420,
- /*0x1ed0*/ 691,
- /*0x1e50*/ 625,
+ /*0x00c0*/ 26,
-1,
- /*0xa736*/ 1072,
+ /*0x2cc0*/ 1006,
+ /*0x1fec*/ 853,
+ /*0x046c*/ 351,
+ /*0x016c*/ 110,
+ /*0xa656*/ 1038,
+ /*0x013d*/ 86,
+ /*0x104c4*/ 1328,
+ /*0xa7c0*/ 1139,
+ /*0xabbd*/ 1227,
+ /*0xab7d*/ 1163,
-1,
- /*0x10ab*/ 495,
- -1, -1,
- /*0xff36*/ 1258,
- /*0x2cd0*/ 1013,
- /*0x004e*/ 12,
- /*0x014e*/ 95,
+ /*0x0540*/ 460,
+ /*0xa7ab*/ 1125,
+ /*0x1eec*/ 705,
+ /*0x1e6c*/ 639,
+ /*0x10cab*/ 1422,
+ /*0xa694*/ 1060,
-1, -1,
- /*0x24c4*/ 899,
- /*0x00ce*/ 40,
- /*0x0548*/ 468,
+ /*0x024c*/ 227,
+ /*0x10bc*/ 512,
-1, -1, -1,
- /*0x03e2*/ 280,
- /*0x1ece*/ 690,
- /*0x1e4e*/ 624,
- /*0x16e5f*/ 1453,
- /*0xa68e*/ 1056,
- /*0x10c2*/ 518,
- -1, -1,
- /*0x24cc*/ 907,
+ /*0x1fc9*/ 832,
+ /*0x0049*/ 1528,
+ /*0x0149*/ 92,
-1,
- /*0x2cce*/ 1012,
+ /*0x1fa9*/ 808,
+ /*0x0429*/ 338,
+ -1, -1,
+ /*0x04d0*/ 397,
+ /*0xaba9*/ 1207,
+ /*0x104d0*/ 1340,
+ /*0x053d*/ 457,
-1,
- /*0x118b6*/ 1412,
+ /*0x118b4*/ 1450,
+ /*0x2c29*/ 952,
+ /*0xa736*/ 1073,
-1,
- /*0xa734*/ 1071,
- /*0x0244*/ 222,
+ /*0x1f3c*/ 741,
+ /*0xa644*/ 1029,
+ /*0x00c9*/ 35,
-1,
- /*0x03d0*/ 271,
- /*0x04f6*/ 416,
- /*0xff34*/ 1256,
- /*0x0542*/ 462,
- /*0xa644*/ 1028,
- -1, -1,
- /*0x01bc*/ 156,
+ /*0xa74a*/ 1083,
+ /*0x16e41*/ 1463,
+ /*0xff34*/ 1261,
/*0x1fda*/ 842,
/*0x005a*/ 24,
/*0x015a*/ 101,
-1,
- /*0x024c*/ 227,
- -1,
- /*0x00da*/ 51,
- -1,
- /*0x24c8*/ 903,
- -1,
- /*0xa64c*/ 1032,
+ /*0xa7c9*/ 1145,
+ /*0x1fea*/ 851,
+ /*0x046a*/ 350,
+ /*0x016a*/ 109,
+ /*0x0549*/ 469,
-1,
+ /*0x01c4*/ 157,
+ /*0x10ca9*/ 1420,
/*0x1eda*/ 696,
/*0x1e5a*/ 630,
- -1,
- /*0xa73c*/ 1075,
- -1,
- /*0x01d5*/ 167,
- /*0x118b4*/ 1410,
-1, -1,
- /*0x2cda*/ 1018,
- -1,
- /*0x1cab*/ 566,
- /*0xa684*/ 1051,
- /*0x04c9*/ 394,
- /*0x0556*/ 482,
- /*0x104c9*/ 1328,
- -1,
/*0x0248*/ 225,
- -1, -1,
- /*0x24c2*/ 897,
+ /*0x1eea*/ 704,
+ /*0x1e6a*/ 638,
+ /*0x00da*/ 51,
-1,
- /*0x1f49*/ 746,
- /*0xa648*/ 1030,
- /*0x0054*/ 18,
- /*0x0154*/ 98,
- -1, -1,
- /*0x0552*/ 478,
- /*0x00d4*/ 46,
+ /*0x2cda*/ 1019,
+ /*0xa650*/ 1035,
-1, -1,
- /*0x118bc*/ 1418,
- /*0x16e5d*/ 1451,
+ /*0x03c2*/ 269,
+ /*0x104cc*/ 1336,
-1,
- /*0x1ed4*/ 693,
- /*0x1e54*/ 627,
- /*0x03da*/ 276,
- /*0x0546*/ 466,
- /*0x1fd8*/ 840,
- /*0x0058*/ 22,
- /*0x0158*/ 100,
- -1, -1,
- /*0x2cd4*/ 1015,
- /*0x00d8*/ 49,
+ /*0x24c4*/ 899,
+ /*0x118bc*/ 1458,
-1,
- /*0xa642*/ 1027,
- -1, -1, -1,
- /*0x1ed8*/ 695,
- /*0x1e58*/ 629,
- /*0x1ff8*/ 859,
- /*0x0478*/ 357,
- /*0x0178*/ 116,
- /*0xa682*/ 1050,
- /*0x01ca*/ 161,
- /*0x1fd3*/ 837,
- /*0x0053*/ 17,
- /*0x2cd8*/ 1017,
- /*0x1fc3*/ 827,
- /*0x0043*/ 2,
- /*0x0143*/ 89,
- /*0x00d3*/ 45,
- /*0x1ef8*/ 711,
- /*0x1e78*/ 645,
- /*0x00c3*/ 29,
- /*0x104c4*/ 1323,
- /*0x104d1*/ 1336,
+ /*0x10584*/ 1363,
+ /*0x1fe2*/ 844,
+ /*0x0462*/ 346,
+ /*0x0162*/ 105,
-1,
- /*0x13f8*/ 524,
- /*0x0550*/ 476,
- /*0xa74a*/ 1082,
+ /*0x1fa1*/ 800,
+ /*0x0421*/ 330,
+ /*0x1f56*/ 754,
+ /*0x10421*/ 1301,
-1,
- /*0x24c6*/ 901,
- -1, -1,
- /*0xa656*/ 1037,
+ /*0xaba1*/ 1199,
+ /*0x2c62*/ 960,
+ /*0x024e*/ 228,
+ /*0x1ee2*/ 700,
+ /*0x1e62*/ 634,
+ /*0x2c21*/ 944,
-1, -1, -1,
- /*0x104cc*/ 1331,
- -1,
- /*0x04fa*/ 418,
/*0x1fc7*/ 830,
/*0x0047*/ 6,
/*0x0147*/ 91,
- /*0x03d8*/ 275,
- /*0x1f4c*/ 749,
+ /*0x2ce2*/ 1023,
-1,
- /*0x00c7*/ 33,
- /*0xa652*/ 1035,
- /*0x054e*/ 474,
- -1, -1,
- /*0x0246*/ 224,
- /*0x00c0*/ 26,
- -1, -1,
+ /*0x10c4*/ 520,
/*0x0045*/ 4,
/*0x0145*/ 90,
- /*0xa646*/ 1029,
- /*0x1ec0*/ 683,
- /*0x1e40*/ 617,
+ -1, -1, -1,
+ /*0x1fb9*/ 821,
+ /*0xa64c*/ 1033,
+ /*0x0139*/ 84,
+ /*0x10582*/ 1361,
+ /*0xa734*/ 1072,
+ /*0xabb9*/ 1223,
+ /*0x10ca1*/ 1412,
+ /*0x03d8*/ 275,
+ /*0x00c7*/ 33,
+ /*0x0055*/ 19,
+ /*0x104c8*/ 1332,
+ -1, -1,
/*0x00c5*/ 31,
+ -1, -1, -1,
+ /*0xa7c7*/ 1144,
+ -1, -1, -1,
+ /*0x0547*/ 467,
+ /*0xa7c5*/ 1142,
-1,
- /*0x104c8*/ 1327,
+ /*0x0345*/ 229,
-1,
- /*0x01f6*/ 184,
- /*0x1fa9*/ 808,
- /*0x0429*/ 338,
- /*0x2cc0*/ 1005,
- /*0xa7c7*/ 1142,
- /*0x1f48*/ 745,
- /*0xaba9*/ 1202,
+ /*0x0545*/ 465,
+ /*0x00d5*/ 47,
-1,
- /*0x004d*/ 11,
- /*0x1f2b*/ 732,
- /*0xa662*/ 1043,
- /*0x2c29*/ 952,
- /*0x212b*/ 866,
- /*0x00cd*/ 39,
+ /*0x1fe8*/ 849,
+ /*0x0468*/ 349,
+ /*0x0168*/ 108,
+ /*0x0539*/ 453,
+ /*0x03ab*/ 267,
+ -1,
+ /*0x24cc*/ 907,
+ -1,
+ /*0x104ce*/ 1338,
+ -1, -1,
+ /*0x0555*/ 481,
+ /*0x1ee8*/ 703,
+ /*0x1e68*/ 637,
+ /*0x1f50*/ 751,
+ /*0xa73c*/ 1076,
+ /*0x0246*/ 224,
+ /*0xa648*/ 1031,
+ -1, -1, -1,
+ /*0x03ec*/ 285,
/*0x1f97*/ 790,
/*0x0417*/ 320,
-1,
- /*0x10417*/ 1286,
- /*0xa7c5*/ 1140,
- /*0xab97*/ 1184,
- -1,
- /*0x24ce*/ 909,
- /*0x104c2*/ 1321,
+ /*0x10417*/ 1291,
-1,
+ /*0xab97*/ 1189,
+ /*0x1ff2*/ 854,
+ /*0x0472*/ 354,
+ /*0x0172*/ 113,
+ /*0x104c2*/ 1326,
/*0x2c17*/ 934,
- -1,
+ /*0x01c8*/ 160,
/*0x1e97*/ 661,
- /*0xa650*/ 1034,
- /*0x046e*/ 352,
- /*0x016e*/ 111,
-1, -1,
- /*0x10ca9*/ 1380,
- /*0x1fa1*/ 800,
- /*0x0421*/ 330,
- /*0x047e*/ 360,
- /*0x10421*/ 1296,
- /*0x2c6e*/ 966,
- /*0xaba1*/ 1194,
- /*0x1eee*/ 706,
- /*0x1e6e*/ 640,
+ /*0xa684*/ 1052,
+ /*0x2c72*/ 970,
-1,
- /*0x024e*/ 228,
- /*0x2c21*/ 944,
- /*0x2c7e*/ 971,
- /*0x10c97*/ 1362,
- /*0x1efe*/ 714,
- /*0x1e7e*/ 648,
- /*0xa64e*/ 1033,
- -1,
- /*0x03a9*/ 265,
- /*0x04d6*/ 400,
- -1, -1, -1,
- /*0x0554*/ 480,
- /*0x1fec*/ 853,
- /*0x046c*/ 351,
- /*0x016c*/ 110,
+ /*0x1ef2*/ 708,
+ /*0x1e72*/ 642,
-1,
- /*0x1f56*/ 754,
- -1, -1,
- /*0x0397*/ 248,
- /*0x10ca1*/ 1372,
/*0x04d2*/ 398,
+ /*0xa64e*/ 1034,
+ /*0x104d2*/ 1342,
+ /*0x1cab*/ 566,
-1,
- /*0x104d2*/ 1337,
- /*0x1eec*/ 705,
- /*0x1e6c*/ 639,
- -1, -1,
- /*0x0345*/ 229,
+ /*0x03a9*/ 265,
+ /*0x2cf2*/ 1026,
-1,
- /*0x1f52*/ 752,
+ /*0x24c8*/ 903,
-1,
- /*0x03ee*/ 286,
- /*0x104c6*/ 1325,
- /*0x10c3*/ 519,
+ /*0x10c97*/ 1402,
+ /*0x1f4c*/ 749,
-1, -1, -1,
- /*0x03a1*/ 258,
- /*0x03fe*/ 295,
- /*0xa65a*/ 1039,
- /*0x01c4*/ 157,
- /*0x01d1*/ 165,
- /*0x1fea*/ 851,
- /*0x046a*/ 350,
- /*0x016a*/ 109,
- /*0x0553*/ 479,
+ /*0x0372*/ 231,
-1,
- /*0x04e2*/ 406,
- /*0x0543*/ 463,
- /*0x1fe8*/ 849,
- /*0x0468*/ 349,
- /*0x0168*/ 108,
- -1, -1,
- /*0x1eea*/ 704,
- /*0x1e6a*/ 638,
- /*0xa744*/ 1079,
- /*0x10c7*/ 522,
- /*0x01fa*/ 187,
- /*0x2162*/ 870,
- /*0x03ec*/ 285,
- /*0x1ee8*/ 703,
- /*0x1e68*/ 637,
- /*0x10c0*/ 516,
- /*0x04d0*/ 397,
- /*0xa68c*/ 1055,
- /*0x104d0*/ 1335,
- /*0x16e57*/ 1445,
- -1, -1,
- /*0xa74c*/ 1083,
- /*0x10c5*/ 521,
- /*0x0547*/ 467,
- /*0x1f50*/ 751,
- /*0xa654*/ 1036,
- -1, -1, -1,
- /*0x0540*/ 460,
- /*0x01c8*/ 160,
- -1, -1,
- /*0x10a9*/ 493,
- -1, -1,
- /*0x24c3*/ 898,
- /*0x0545*/ 465,
- /*0x104ce*/ 1333,
- /*0x10cd*/ 523,
+ /*0xa756*/ 1089,
-1,
- /*0xa658*/ 1038,
- /*0x03ea*/ 284,
- -1, -1, -1,
- /*0xa748*/ 1081,
- -1, -1,
- /*0x03e8*/ 283,
+ /*0x10572*/ 1346,
-1,
- /*0x1fe4*/ 846,
- /*0x0464*/ 347,
- /*0x0164*/ 106,
- /*0x054d*/ 473,
- /*0xff2b*/ 1247,
+ /*0x023d*/ 218,
+ /*0x1cbd*/ 582,
-1,
- /*0x0243*/ 221,
- -1, -1,
- /*0x24c7*/ 902,
- /*0x2c64*/ 961,
+ /*0xa642*/ 1028,
+ /*0x03da*/ 276,
-1,
- /*0x1ee4*/ 701,
- /*0x1e64*/ 635,
- /*0x10a1*/ 485,
- /*0x24c0*/ 895,
+ /*0xa682*/ 1051,
+ /*0x104c6*/ 1330,
+ /*0x04d8*/ 401,
+ /*0x03ea*/ 284,
+ -1, -1,
+ /*0x046e*/ 352,
+ /*0x016e*/ 111,
+ /*0x24ce*/ 909,
+ -1, -1,
+ /*0xa652*/ 1036,
-1, -1, -1,
- /*0xa742*/ 1078,
+ /*0x2c6e*/ 967,
/*0x015e*/ 103,
- /*0x04da*/ 402,
- /*0x015c*/ 102,
- /*0x24c5*/ 900,
- /*0x00de*/ 55,
- -1,
- /*0x00dc*/ 53,
+ /*0x1eee*/ 706,
+ /*0x1e6e*/ 640,
-1,
- /*0x118ab*/ 1401,
+ /*0x1ca9*/ 564,
+ -1, -1,
+ /*0x04c0*/ 389,
-1,
+ /*0x104c0*/ 1324,
/*0x1ede*/ 698,
/*0x1e5e*/ 632,
- /*0x1edc*/ 697,
- /*0x1e5c*/ 631,
+ /*0xa744*/ 1080,
+ /*0x1f48*/ 745,
+ /*0x03e2*/ 280,
+ /*0x24c2*/ 897,
+ -1,
+ /*0x00de*/ 55,
+ /*0x03a1*/ 258,
+ /*0x2cde*/ 1021,
+ -1,
+ /*0xa646*/ 1030,
+ -1, -1,
+ /*0xa658*/ 1039,
+ -1, -1, -1, -1,
+ /*0x04ec*/ 411,
+ /*0x1fc3*/ 827,
+ /*0x0043*/ 2,
+ /*0x0143*/ 89,
+ /*0x104bd*/ 1321,
-1,
/*0x1fe6*/ 847,
/*0x0466*/ 348,
/*0x0166*/ 107,
+ -1, -1,
+ /*0xa750*/ 1086,
-1,
- /*0x2cde*/ 1020,
- /*0x24cd*/ 908,
- /*0x2cdc*/ 1019,
- /*0xa640*/ 1026,
- -1,
- /*0x0245*/ 223,
- /*0x1ca9*/ 564,
+ /*0x10c2*/ 518,
+ -1, -1,
+ /*0xa640*/ 1027,
-1,
/*0x1ee6*/ 702,
/*0x1e66*/ 636,
- /*0x03e4*/ 281,
- /*0xa756*/ 1088,
- /*0x0460*/ 345,
- /*0x0160*/ 104,
- /*0x16e5b*/ 1449,
- -1, -1,
- /*0x04d4*/ 399,
+ /*0x00c3*/ 29,
-1,
- /*0x1c97*/ 546,
+ /*0x03d5*/ 273,
+ /*0x04c9*/ 394,
-1,
- /*0x2c60*/ 958,
+ /*0x104c9*/ 1333,
+ /*0x24c6*/ 901,
+ /*0x1fad*/ 812,
+ /*0x042d*/ 342,
+ /*0x1058e*/ 1372,
-1,
- /*0x1ee0*/ 699,
- /*0x1e60*/ 633,
- /*0xa752*/ 1086,
- /*0x1f54*/ 753,
+ /*0x1ca1*/ 556,
+ /*0xabad*/ 1211,
+ /*0x0543*/ 463,
-1,
- /*0x03de*/ 278,
+ /*0x1058c*/ 1370,
-1,
- /*0x03dc*/ 277,
+ /*0x2c2d*/ 956,
+ /*0xa66c*/ 1049,
+ -1, -1, -1, -1,
+ /*0x03e8*/ 283,
+ -1, -1, -1,
+ /*0x04da*/ 402,
+ /*0x1f52*/ 752,
+ /*0x0245*/ 223,
+ /*0x24c0*/ 895,
+ /*0xa74c*/ 1084,
+ /*0x04ea*/ 410,
-1,
- /*0x2ce0*/ 1021,
- /*0x04d8*/ 401,
+ /*0x01ec*/ 178,
+ /*0xa7ad*/ 1127,
+ /*0x1cb9*/ 580,
-1,
- /*0xa746*/ 1080,
- /*0x01e2*/ 173,
- /*0x1fb9*/ 821,
- /*0x1ca1*/ 556,
- /*0x0139*/ 84,
+ /*0x10cad*/ 1424,
+ -1, -1, -1, -1, -1, -1,
+ /*0x0397*/ 248,
+ /*0x1fbb*/ 823,
+ /*0xab7c*/ 1162,
+ /*0x013b*/ 85,
-1, -1,
- /*0xabb9*/ 1218,
- /*0x1f8f*/ 782,
- /*0x040f*/ 312,
- /*0x03e6*/ 282,
- /*0x1040f*/ 1278,
- /*0x04f8*/ 417,
- /*0xab8f*/ 1176,
- /*0x1ff2*/ 854,
- /*0x0472*/ 354,
- /*0x0172*/ 113,
- /*0xa762*/ 1094,
- /*0x2c0f*/ 926,
- /*0x104d3*/ 1338,
- /*0x04c3*/ 391,
- -1,
- /*0x104c3*/ 1322,
- -1,
- /*0x2c72*/ 969,
- /*0x03e0*/ 279,
- /*0x1ef2*/ 708,
- /*0x1e72*/ 642,
- /*0x1fad*/ 812,
- /*0x042d*/ 342,
- -1, -1, -1,
- /*0xabad*/ 1206,
- /*0xa750*/ 1085,
- /*0x2cf2*/ 1025,
+ /*0xabbb*/ 1225,
-1, -1,
- /*0x2c2d*/ 956,
- /*0x10c8f*/ 1354,
+ /*0x24bd*/ 892,
-1, -1,
- /*0xa66c*/ 1048,
- /*0x1fb3*/ 816,
- /*0x04c7*/ 393,
- -1,
- /*0x104c7*/ 1326,
+ /*0x10c0*/ 516,
-1,
- /*0xabb3*/ 1212,
+ /*0x04e2*/ 406,
-1,
- /*0x04c0*/ 389,
+ /*0x01a9*/ 146,
+ /*0x10ab*/ 495,
+ /*0x1fa5*/ 804,
+ /*0x0425*/ 334,
+ /*0xa65a*/ 1040,
+ /*0x10425*/ 1305,
-1,
- /*0x104c0*/ 1319,
+ /*0xaba5*/ 1203,
+ /*0x1fb7*/ 819,
+ /*0xa66a*/ 1048,
-1, -1,
- /*0xa74e*/ 1084,
- /*0xa7ad*/ 1126,
- /*0x038f*/ 240,
- /*0x04c5*/ 392,
- /*0x10cad*/ 1384,
- /*0x104c5*/ 1324,
+ /*0x2c25*/ 948,
+ /*0xabb7*/ 1221,
+ /*0x24c9*/ 904,
+ /*0xa748*/ 1082,
+ /*0x04c7*/ 393,
+ /*0x053b*/ 455,
+ /*0x104c7*/ 1331,
-1,
- /*0x1fa5*/ 804,
- /*0x0425*/ 334,
+ /*0x10bd*/ 513,
+ /*0x04c5*/ 392,
+ /*0x1f2b*/ 732,
+ /*0x104c5*/ 1329,
-1,
- /*0x10425*/ 1300,
+ /*0x01ea*/ 177,
+ /*0x1c97*/ 546,
-1,
- /*0xaba5*/ 1198,
+ /*0x1e921*/ 1527,
+ /*0x104b9*/ 1317,
-1, -1, -1,
- /*0xa7b3*/ 1131,
- /*0x2c25*/ 948,
- /*0xa66a*/ 1047,
+ /*0x10ca5*/ 1416,
+ -1, -1,
+ /*0xa662*/ 1044,
+ /*0x03ee*/ 286,
-1,
- /*0x04cd*/ 396,
+ /*0x1f6c*/ 763,
+ /*0x0537*/ 451,
+ /*0x1f3d*/ 742,
+ /*0xa74e*/ 1085,
-1,
- /*0x104cd*/ 1332,
- /*0x1f29*/ 730,
+ /*0xa68e*/ 1057,
+ /*0x10a9*/ 493,
+ /*0x03de*/ 278,
+ -1, -1, -1,
+ /*0xa68c*/ 1056,
-1,
- /*0xa668*/ 1046,
- /*0x0041*/ 0,
- /*0x0141*/ 88,
+ /*0x01e2*/ 173,
-1,
- /*0x1f4d*/ 750,
- /*0x013d*/ 86,
- /*0x00c1*/ 27,
- /*0x1e917*/ 1477,
- /*0xabbd*/ 1222,
/*0x1fa3*/ 802,
/*0x0423*/ 332,
- /*0xa75a*/ 1090,
- /*0x10423*/ 1298,
- /*0x10ca5*/ 1376,
- /*0xaba3*/ 1196,
- /*0x04ee*/ 412,
- /*0x0372*/ 231,
+ /*0x04e8*/ 409,
+ /*0x10423*/ 1303,
+ /*0x118ab*/ 1441,
+ /*0xaba3*/ 1201,
-1, -1,
+ /*0x1f49*/ 746,
+ -1,
/*0x2c23*/ 946,
- -1, -1,
- /*0x04fe*/ 420,
+ /*0xa742*/ 1079,
+ /*0x1f29*/ 730,
-1,
- /*0x1f6e*/ 765,
+ /*0xff2b*/ 1252,
-1,
- /*0x1e921*/ 1487,
- /*0x216e*/ 882,
+ /*0x01c7*/ 159,
+ -1, -1, -1, -1,
+ /*0x01c5*/ 158,
+ -1,
+ /*0x118bd*/ 1459,
+ /*0x004d*/ 11,
+ /*0xa752*/ 1087,
-1, -1, -1,
- /*0x03a5*/ 261,
+ /*0x03e6*/ 282,
+ /*0x04f2*/ 414,
+ /*0x10ca3*/ 1414,
+ -1, -1,
+ /*0x24c7*/ 902,
+ /*0x01d5*/ 167,
-1,
- /*0x1f87*/ 774,
- /*0x0407*/ 304,
- /*0xab79*/ 1154,
- /*0x10407*/ 1270,
- /*0x0587*/ 483,
- /*0xab87*/ 1168,
- /*0x16e59*/ 1447,
- /*0x10ca3*/ 1374,
+ /*0x1f6a*/ 761,
+ /*0x1058d*/ 1371,
+ /*0x24c5*/ 900,
+ /*0xa668*/ 1047,
+ -1,
+ /*0x00cd*/ 39,
-1, -1,
- /*0x2c07*/ 918,
- /*0x04ec*/ 411,
- /*0xab71*/ 1146,
- /*0xa754*/ 1087,
+ /*0x24b9*/ 888,
+ -1,
+ /*0x10a1*/ 485,
+ /*0x118a9*/ 1439,
+ -1,
+ /*0x1e917*/ 1517,
+ /*0xa746*/ 1081,
+ -1,
+ /*0x16e54*/ 1482,
+ /*0xa758*/ 1090,
+ /*0x054d*/ 473,
+ /*0x01e8*/ 176,
+ -1,
+ /*0xff29*/ 1250,
+ -1, -1,
+ /*0x10c7*/ 522,
+ /*0x0470*/ 353,
+ /*0x0170*/ 112,
-1,
+ /*0x0243*/ 221,
+ /*0x10c5*/ 521,
+ -1, -1, -1, -1,
+ /*0x2c70*/ 969,
/*0x10b9*/ 509,
+ /*0x1ef0*/ 707,
+ /*0x1e70*/ 641,
+ /*0xa740*/ 1078,
+ -1,
+ /*0x04ee*/ 412,
+ /*0x0197*/ 136,
+ -1,
/*0x1f9d*/ 796,
/*0x041d*/ 326,
- /*0xa664*/ 1044,
- /*0x1041d*/ 1292,
- /*0x1f6c*/ 763,
- /*0xab9d*/ 1190,
- -1,
- /*0x216c*/ 880,
-1,
- /*0x03a3*/ 259,
+ /*0x1041d*/ 1297,
+ /*0x01f2*/ 182,
+ /*0xab9d*/ 1195,
+ /*0x04de*/ 404,
+ -1, -1, -1,
/*0x2c1d*/ 940,
- /*0x01f8*/ 186,
+ /*0x0370*/ 230,
+ /*0x1cad*/ 568,
+ /*0x1f39*/ 738,
-1,
- /*0xa758*/ 1089,
- /*0x0539*/ 453,
- /*0x10c87*/ 1346,
- /*0x01d3*/ 166,
+ /*0x10570*/ 1344,
-1,
- /*0x1fcb*/ 834,
- /*0x004b*/ 9,
- /*0xa65e*/ 1041,
- -1,
- /*0xa65c*/ 1040,
- /*0xab73*/ 1148,
- /*0x00cb*/ 37,
- /*0x10ad*/ 497,
- /*0x04ea*/ 410,
- /*0xabb1*/ 1210,
+ /*0xa76c*/ 1100,
+ /*0x212b*/ 866,
+ /*0xabb5*/ 1219,
+ -1, -1, -1, -1,
+ /*0x118a1*/ 1431,
-1,
+ /*0x03a5*/ 261,
/*0x1f9b*/ 794,
/*0x041b*/ 324,
- /*0x10c9d*/ 1368,
- /*0x1041b*/ 1290,
- /*0x04e8*/ 409,
- /*0xab9b*/ 1188,
- /*0x1f6a*/ 761,
-1,
- /*0xa666*/ 1045,
- /*0x216a*/ 878,
+ /*0x1041b*/ 1295,
+ /*0x10c9d*/ 1408,
+ /*0xab9b*/ 1193,
+ /*0x00b5*/ 25,
+ /*0xff21*/ 1242,
+ /*0x216c*/ 880,
+ -1,
/*0x2c1b*/ 938,
- /*0x10b3*/ 503,
+ /*0x04c3*/ 391,
/*0x1e9b*/ 665,
- /*0x1f68*/ 759,
- /*0x01c7*/ 159,
- -1,
- /*0x2168*/ 876,
- -1, -1, -1,
- /*0x039d*/ 254,
- /*0xa7b1*/ 1129,
- /*0x24b9*/ 888,
- /*0xa660*/ 1042,
- /*0x10cb1*/ 1388,
+ /*0x104c3*/ 1327,
-1,
- /*0x0533*/ 447,
- /*0x1fb7*/ 819,
- /*0x01c5*/ 158,
+ /*0x1f68*/ 759,
+ /*0x04e6*/ 408,
+ /*0xa65e*/ 1042,
-1,
- /*0x10a5*/ 489,
- /*0x10c9b*/ 1366,
- /*0xabb7*/ 1216,
- /*0x1cb9*/ 580,
+ /*0x0535*/ 449,
-1, -1,
- /*0xa740*/ 1077,
- /*0x1f93*/ 786,
- /*0x0413*/ 316,
- /*0x01a9*/ 146,
- /*0x10413*/ 1282,
- -1,
- /*0xab93*/ 1180,
- /*0xab77*/ 1152,
- -1,
- /*0x01cd*/ 163,
+ /*0x118b9*/ 1455,
+ /*0x023b*/ 217,
+ /*0x01ee*/ 179,
+ /*0x1f95*/ 788,
+ /*0x0415*/ 318,
-1,
- /*0x2c13*/ 930,
- /*0x10c1*/ 517,
- /*0x039b*/ 252,
+ /*0x10415*/ 1289,
-1,
- /*0x10bd*/ 513,
- /*0x0197*/ 136,
- -1, -1,
- /*0x04e4*/ 407,
- -1,
- /*0x10a3*/ 487,
+ /*0xab95*/ 1187,
+ /*0x10c9b*/ 1406,
+ /*0xff39*/ 1266,
+ /*0x01de*/ 171,
-1,
- /*0x1cad*/ 568,
- /*0xff29*/ 1245,
- -1, -1,
- /*0x0541*/ 461,
+ /*0x2c15*/ 932,
-1,
- /*0x01ee*/ 179,
- /*0x053d*/ 457,
- /*0x2164*/ 872,
- /*0x10c93*/ 1358,
+ /*0xa75a*/ 1091,
-1, -1, -1,
- /*0x01fe*/ 189,
- /*0x04de*/ 404,
- /*0x1cb3*/ 574,
- /*0x04dc*/ 403,
- -1,
+ /*0x1ca5*/ 560,
+ /*0xa76a*/ 1099,
/*0x1f99*/ 792,
/*0x0419*/ 322,
-1,
- /*0x10419*/ 1288,
- /*0xa76e*/ 1100,
- /*0xab99*/ 1186,
- /*0xab75*/ 1150,
- /*0x118a9*/ 1399,
+ /*0x10419*/ 1293,
+ /*0x1cb7*/ 578,
+ /*0xab99*/ 1191,
+ /*0xfb17*/ 1241,
-1,
- /*0x0393*/ 244,
+ /*0x03a3*/ 259,
+ /*0x1fb3*/ 816,
/*0x2c19*/ 936,
- /*0xa77e*/ 1104,
+ /*0xa666*/ 1046,
/*0x1e99*/ 663,
- /*0x04e6*/ 408,
- -1,
- /*0xff21*/ 1237,
- /*0x1ca5*/ 560,
- /*0x01ec*/ 178,
+ /*0x10c95*/ 1400,
+ /*0xabb3*/ 1217,
+ /*0x1f93*/ 786,
+ /*0x0413*/ 316,
+ /*0x216a*/ 878,
+ /*0x10413*/ 1287,
+ /*0x16e5b*/ 1489,
+ /*0xab93*/ 1185,
-1, -1, -1, -1,
- /*0x1fbb*/ 823,
- /*0x24c1*/ 896,
- /*0x013b*/ 85,
- /*0x2166*/ 874,
- /*0x24bd*/ 892,
- /*0xabbb*/ 1220,
- /*0x04e0*/ 405,
- -1, -1,
- /*0x10c99*/ 1364,
- -1,
- /*0xa76c*/ 1099,
- -1, -1, -1,
- /*0x1cbd*/ 582,
- /*0x013f*/ 87,
- /*0x118a1*/ 1391,
- /*0x2160*/ 868,
- /*0xabbf*/ 1224,
- /*0x10b1*/ 501,
- /*0x1ca3*/ 558,
- /*0x0241*/ 220,
+ /*0x2c13*/ 930,
+ /*0xa762*/ 1095,
+ /*0x01e6*/ 175,
-1, -1,
- /*0x023d*/ 218,
- /*0x01ea*/ 177,
- /*0x0399*/ 250,
- /*0x0470*/ 353,
- /*0x0170*/ 112,
- /*0xab7f*/ 1160,
- /*0x054b*/ 471,
+ /*0x0587*/ 483,
+ /*0x10c99*/ 1404,
+ /*0x10587*/ 1366,
+ /*0x1f91*/ 784,
+ /*0x0411*/ 314,
+ /*0x104bb*/ 1319,
+ /*0x10411*/ 1285,
+ /*0xa7b3*/ 1132,
+ /*0xab91*/ 1183,
-1,
- /*0x01e8*/ 176,
- /*0x104b9*/ 1312,
- /*0x0531*/ 445,
+ /*0x24c3*/ 898,
+ /*0x0533*/ 447,
-1,
- /*0x2c70*/ 968,
+ /*0x2c11*/ 928,
+ /*0x2162*/ 870,
+ /*0x004f*/ 13,
+ /*0x10c93*/ 1398,
+ /*0x1f6e*/ 765,
+ /*0x16e53*/ 1481,
-1,
- /*0x1ef0*/ 707,
- /*0x1e70*/ 641,
- /*0x1f39*/ 738,
- /*0xa76a*/ 1098,
- /*0x1e90f*/ 1469,
- /*0x04f2*/ 414,
- /*0x1c87*/ 537,
+ /*0x1ca3*/ 558,
-1,
- /*0x1f0f*/ 722,
+ /*0x1f8f*/ 782,
+ /*0x040f*/ 312,
-1,
- /*0xa768*/ 1097,
- /*0x1f9f*/ 798,
- /*0x041f*/ 328,
+ /*0x1040f*/ 1283,
-1,
- /*0x1041f*/ 1294,
- /*0x10b7*/ 507,
- /*0xab9f*/ 1192,
- -1, -1, -1, -1,
- /*0x2c1f*/ 942,
- /*0x1c9d*/ 552,
- /*0xfb17*/ 1236,
- -1, -1, -1, -1,
- /*0x1f2d*/ 734,
- /*0x24cb*/ 906,
- /*0x0537*/ 451,
- -1, -1, -1, -1, -1,
- /*0x104b3*/ 1306,
+ /*0xab8f*/ 1181,
+ /*0x104b7*/ 1315,
+ -1, -1, -1,
+ /*0x2c0f*/ 926,
+ /*0x00cf*/ 41,
+ /*0x10c91*/ 1396,
+ /*0x1f81*/ 768,
+ /*0x0401*/ 298,
+ /*0x10c3*/ 519,
+ /*0x10401*/ 1269,
/*0x03f0*/ 287,
- /*0x1f8b*/ 778,
- /*0x040b*/ 308,
- -1,
- /*0x1040b*/ 1274,
- /*0x10c9f*/ 1370,
- /*0xab8b*/ 1172,
- /*0x1cb1*/ 572,
- /*0x01e4*/ 174,
- -1, -1,
- /*0x2c0b*/ 922,
+ /*0xab81*/ 1167,
+ -1, -1, -1, -1,
+ /*0x2c01*/ 912,
+ /*0x054f*/ 475,
-1, -1,
- /*0x1c9b*/ 550,
- /*0xabb5*/ 1214,
- /*0x00b5*/ 25,
- /*0x1f95*/ 788,
- /*0x0415*/ 318,
+ /*0x1ff4*/ 856,
+ /*0x0474*/ 355,
+ /*0x0174*/ 114,
-1,
- /*0x10415*/ 1284,
+ /*0x10c8f*/ 1394,
+ /*0xa768*/ 1098,
-1,
- /*0xab95*/ 1182,
- /*0x039f*/ 256,
- /*0xa764*/ 1095,
+ /*0x047e*/ 360,
-1,
- /*0x01de*/ 171,
- /*0x2c15*/ 932,
+ /*0x039d*/ 254,
+ /*0x16e4a*/ 1472,
+ /*0x015c*/ 102,
+ /*0x1ef4*/ 709,
+ /*0x1e74*/ 643,
+ /*0x10ad*/ 497,
+ -1,
+ /*0x2c7e*/ 972,
+ /*0x10c81*/ 1380,
+ /*0x1efe*/ 714,
+ /*0x1e7e*/ 648,
+ -1,
+ /*0x1edc*/ 697,
+ /*0x1e5c*/ 631,
+ /*0x2168*/ 876,
+ /*0x013f*/ 87,
+ -1,
+ /*0x24bb*/ 890,
+ /*0xabbf*/ 1229,
+ /*0x00dc*/ 53,
+ /*0xabb1*/ 1215,
+ /*0x2cdc*/ 1020,
+ /*0x01b7*/ 154,
+ -1, -1,
+ /*0x10574*/ 1348,
+ /*0x1f2d*/ 734,
+ /*0x039b*/ 252,
+ -1, -1,
+ /*0x16e4b*/ 1473,
+ /*0x1057e*/ 1357,
+ -1, -1, -1, -1, -1,
+ /*0x04cd*/ 396,
-1,
- /*0xa78b*/ 1109,
+ /*0x104cd*/ 1337,
/*0x24b7*/ 886,
-1,
- /*0x10c8b*/ 1350,
- /*0x0370*/ 230,
- /*0x04c1*/ 390,
+ /*0x1c9d*/ 552,
+ /*0xa7b1*/ 1130,
+ /*0x10bb*/ 511,
+ /*0x053f*/ 459,
+ /*0x10cb1*/ 1428,
+ /*0x0531*/ 445,
+ /*0x1f9f*/ 798,
+ /*0x041f*/ 328,
-1,
- /*0x104c1*/ 1320,
+ /*0x1041f*/ 1299,
+ /*0x0395*/ 246,
+ /*0xab9f*/ 1197,
-1, -1,
- /*0x104bd*/ 1316,
+ /*0x1cb5*/ 576,
-1,
- /*0x1cb7*/ 578,
- /*0xa75e*/ 1092,
- /*0x01e6*/ 175,
- /*0xa75c*/ 1091,
+ /*0x2c1f*/ 942,
+ -1, -1,
+ /*0x10a5*/ 489,
+ /*0x118ad*/ 1443,
+ -1, -1,
+ /*0x1f3b*/ 740,
-1,
- /*0x1f3d*/ 742,
+ /*0x10b7*/ 507,
-1,
- /*0x10c95*/ 1360,
+ /*0x1c9b*/ 550,
+ /*0x0399*/ 250,
+ /*0xa76e*/ 1101,
+ /*0xff2d*/ 1254,
+ /*0x1f85*/ 772,
+ /*0x0405*/ 302,
+ /*0x04f0*/ 413,
+ /*0x10405*/ 1273,
-1,
- /*0x10bb*/ 511,
- /*0x1c93*/ 542,
- /*0x1f81*/ 768,
- /*0x0401*/ 298,
+ /*0xab85*/ 1171,
+ /*0x10c9f*/ 1410,
+ /*0xa75e*/ 1093,
+ -1, -1,
+ /*0x2c05*/ 916,
-1,
- /*0x10401*/ 1264,
+ /*0x0393*/ 244,
+ -1, -1,
+ /*0x0051*/ 15,
+ /*0x216e*/ 882,
-1,
- /*0xab81*/ 1162,
- /*0x01e0*/ 172,
- /*0xa766*/ 1096,
+ /*0x01cd*/ 163,
-1, -1,
- /*0x2c01*/ 912,
- /*0x004f*/ 13,
- /*0x10bf*/ 515,
- /*0x053b*/ 455,
- /*0x0395*/ 246,
+ /*0x1c95*/ 544,
+ /*0x1f8b*/ 778,
+ /*0x040b*/ 308,
-1,
- /*0x00cf*/ 41,
- -1, -1, -1,
- /*0x1e907*/ 1461,
+ /*0x1040b*/ 1279,
-1,
- /*0xa760*/ 1093,
- /*0x1f91*/ 784,
- /*0x0411*/ 314,
+ /*0xab8b*/ 1177,
+ /*0x118bb*/ 1457,
-1,
- /*0x10411*/ 1280,
- /*0x053f*/ 459,
- /*0xab91*/ 1178,
+ /*0x0391*/ 242,
+ /*0x10c85*/ 1384,
+ /*0x2c0b*/ 922,
+ /*0x00d1*/ 43,
-1, -1,
- /*0x10c81*/ 1340,
+ /*0x24cd*/ 908,
+ /*0x104b5*/ 1313,
-1,
- /*0x2c11*/ 928,
- /*0x16e55*/ 1443,
+ /*0x1c99*/ 548,
+ /*0x10a3*/ 487,
+ /*0x03cf*/ 270,
+ -1, -1,
+ /*0xa766*/ 1097,
+ /*0x118a5*/ 1435,
+ /*0x0551*/ 477,
+ /*0x1e91d*/ 1523,
+ /*0x1cb3*/ 574,
+ /*0x038f*/ 240,
+ /*0xa78b*/ 1110,
+ /*0x118b7*/ 1453,
-1,
- /*0x1e91d*/ 1483,
+ /*0x10c8b*/ 1390,
+ /*0x1c93*/ 542,
+ /*0xff25*/ 1246,
+ /*0x01f0*/ 180,
+ /*0x1ff6*/ 857,
+ /*0x0476*/ 356,
+ /*0x0176*/ 115,
-1,
- /*0x018f*/ 130,
- /*0x1c99*/ 548,
- /*0x1f1d*/ 728,
+ /*0xff37*/ 1264,
+ /*0x2166*/ 874,
+ /*0x10cd*/ 523,
-1, -1, -1,
- /*0x01f2*/ 182,
- -1, -1, -1, -1,
- /*0x04cb*/ 395,
- /*0x24bb*/ 890,
- /*0x104cb*/ 1330,
+ /*0x1ffa*/ 861,
+ /*0x047a*/ 358,
+ /*0x1ef6*/ 710,
+ /*0x1e76*/ 644,
-1,
- /*0xff39*/ 1261,
- /*0x10c91*/ 1356,
- /*0x104b1*/ 1304,
- -1, -1,
- /*0x1f4b*/ 748,
- /*0x03cf*/ 270,
+ /*0x1c91*/ 540,
-1,
- /*0xab7b*/ 1156,
+ /*0x1e91b*/ 1521,
+ /*0x019d*/ 139,
+ /*0x03f4*/ 289,
-1, -1,
- /*0x24bf*/ 894,
- /*0x1e91b*/ 1481,
- -1, -1, -1,
- /*0x1f1b*/ 726,
+ /*0x1efa*/ 712,
+ /*0x1e7a*/ 646,
+ /*0x16e56*/ 1484,
+ /*0x03fe*/ 295,
-1,
- /*0x023b*/ 217,
- /*0x0391*/ 242,
- /*0x01b3*/ 152,
- /*0xab7d*/ 1158,
- /*0x1cbf*/ 584,
+ /*0x1f4d*/ 750,
+ /*0x03dc*/ 277,
-1,
- /*0x118b9*/ 1415,
+ /*0x0376*/ 232,
-1,
- /*0xff2d*/ 1249,
- /*0x1ff4*/ 856,
- /*0x0474*/ 355,
- /*0x0174*/ 114,
+ /*0x01b5*/ 153,
-1,
- /*0x10b5*/ 505,
+ /*0x10576*/ 1350,
-1,
- /*0x16e4a*/ 1432,
- -1, -1,
- /*0x104b7*/ 1310,
- -1, -1,
- /*0x1ef4*/ 709,
- /*0x1e74*/ 643,
- /*0xff33*/ 1255,
- /*0x1f85*/ 772,
- /*0x0405*/ 302,
+ /*0x1ff8*/ 859,
+ /*0x0478*/ 357,
+ /*0x0178*/ 116,
-1,
- /*0x10405*/ 1268,
- /*0x0535*/ 449,
- /*0xab85*/ 1166,
+ /*0x118a3*/ 1433,
-1,
- /*0x1e913*/ 1473,
- /*0x118ad*/ 1403,
+ /*0x1e915*/ 1515,
-1,
- /*0x2c05*/ 916,
- -1, -1, -1, -1, -1,
- /*0x1c9f*/ 554,
+ /*0x1057a*/ 1354,
+ /*0x104b3*/ 1311,
-1,
- /*0xff25*/ 1241,
- -1, -1, -1, -1,
- /*0x118b3*/ 1409,
+ /*0x1c81*/ 531,
+ /*0x1ef8*/ 711,
+ /*0x1e78*/ 645,
+ /*0xff23*/ 1244,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x1e919*/ 1519,
+ -1,
+ /*0x16e44*/ 1466,
-1, -1, -1, -1, -1, -1,
-1,
- /*0x10c85*/ 1344,
+ /*0x10578*/ 1352,
+ -1, -1, -1, -1,
+ /*0x1e913*/ 1513,
+ /*0x039f*/ 256,
+ /*0x10b5*/ 505,
-1, -1,
- /*0x03f4*/ 289,
+ /*0x104cf*/ 1339,
+ -1, -1,
+ /*0x1cbf*/ 584,
+ /*0x1f1d*/ 728,
+ /*0x1cb1*/ 572,
+ -1, -1, -1, -1,
+ /*0x16e50*/ 1478,
+ -1, -1,
+ /*0x1e911*/ 1511,
+ -1, -1, -1,
+ /*0x01b3*/ 152,
+ -1, -1, -1, -1,
+ /*0x13fa*/ 526,
+ /*0x0193*/ 133,
-1, -1, -1, -1, -1, -1,
-1,
- /*0x118a5*/ 1395,
+ /*0x1f1b*/ 726,
+ /*0x1e90f*/ 1509,
+ /*0x04f4*/ 415,
+ -1,
+ /*0x03d1*/ 272,
-1, -1,
- /*0xff23*/ 1239,
+ /*0x1c9f*/ 554,
+ /*0x04fe*/ 420,
-1,
- /*0x1e919*/ 1479,
- /*0x0187*/ 125,
+ /*0x0191*/ 132,
+ /*0x04dc*/ 403,
-1, -1,
- /*0x1f19*/ 724,
- /*0x1cb5*/ 576,
- -1, -1, -1,
- /*0x054f*/ 475,
+ /*0x1e901*/ 1495,
-1, -1,
- /*0x1c95*/ 544,
- -1, -1, -1,
- /*0x118bd*/ 1419,
- /*0x019d*/ 139,
+ /*0x13f8*/ 524,
+ -1,
+ /*0x16e4c*/ 1474,
-1,
- /*0x104bb*/ 1314,
+ /*0x01cf*/ 164,
+ -1,
+ /*0x118b5*/ 1451,
-1, -1,
- /*0x118a3*/ 1393,
- -1, -1, -1,
- /*0x1f3b*/ 740,
+ /*0x104bf*/ 1323,
-1,
- /*0x16e49*/ 1431,
- -1, -1, -1, -1,
- /*0x104bf*/ 1318,
+ /*0x104b1*/ 1309,
+ /*0x018f*/ 130,
-1,
- /*0x01cb*/ 162,
- -1, -1, -1,
- /*0x01b1*/ 150,
- /*0x1f3f*/ 744,
+ /*0x10b3*/ 503,
+ /*0x1c85*/ 535,
+ /*0xff35*/ 1262,
-1, -1, -1,
- /*0x04f0*/ 413,
+ /*0xfb15*/ 1239,
-1,
/*0x24cf*/ 910,
- /*0x1c81*/ 531,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xff31*/ 1253,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x1c91*/ 540,
- -1,
- /*0x1e91f*/ 1485,
- /*0x01b7*/ 154,
+ -1, -1,
+ /*0x0181*/ 121,
+ /*0x1f19*/ 724,
+ -1, -1, -1, -1, -1,
+ /*0xa65c*/ 1041,
-1, -1, -1, -1, -1, -1,
+ /*0x01f4*/ 183,
+ /*0x03fa*/ 293,
+ -1, -1, -1, -1,
+ /*0x01fe*/ 189,
-1,
- /*0x16e44*/ 1426,
- /*0x16e51*/ 1439,
- /*0x0193*/ 133,
- /*0x118b1*/ 1407,
+ /*0x16e48*/ 1470,
+ -1, -1, -1, -1, -1,
+ /*0xfb13*/ 1237,
-1, -1, -1, -1, -1, -1,
-1, -1, -1,
- /*0xff37*/ 1259,
- /*0x16e4c*/ 1434,
- -1, -1, -1,
- /*0x1e90b*/ 1465,
+ /*0x01b1*/ 150,
+ -1, -1, -1, -1,
+ /*0x1e91f*/ 1525,
+ -1, -1,
+ /*0x118b3*/ 1449,
+ -1, -1,
+ /*0x16e4e*/ 1476,
-1, -1, -1,
- /*0x1f0b*/ 718,
+ /*0x1f0f*/ 722,
+ /*0x24bf*/ 894,
-1,
- /*0x104b5*/ 1308,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x1e915*/ 1475,
- -1, -1,
- /*0x118b7*/ 1413,
+ /*0xff33*/ 1260,
-1,
- /*0x16e48*/ 1430,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
+ /*0x104d1*/ 1341,
-1, -1, -1, -1, -1, -1,
-1, -1, -1,
- /*0x1c85*/ 535,
- -1,
- /*0x16e42*/ 1424,
+ /*0x1e905*/ 1499,
+ -1, -1,
+ /*0x019f*/ 140,
+ /*0x16e42*/ 1464,
-1, -1, -1, -1, -1,
- /*0x1e901*/ 1455,
- -1, -1, -1, -1, -1, -1,
- /*0x104cf*/ 1334,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
+ /*0xfb01*/ 1231,
-1, -1,
- /*0x01f0*/ 180,
- /*0x1e911*/ 1471,
- -1,
- /*0x16e56*/ 1444,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x16e52*/ 1440,
- /*0x118bb*/ 1417,
+ /*0x10bf*/ 515,
-1,
- /*0xfb13*/ 1232,
+ /*0x10b1*/ 501,
-1, -1,
- /*0x019f*/ 140,
+ /*0x16e52*/ 1480,
-1, -1, -1,
- /*0x16e46*/ 1428,
- -1, -1, -1, -1,
- /*0x118bf*/ 1421,
- -1, -1, -1, -1, -1, -1,
+ /*0x1e90b*/ 1505,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x018b*/ 128,
-1, -1,
- /*0x04f4*/ 415,
- -1, -1, -1, -1, -1,
- /*0x01b5*/ 153,
- -1,
- /*0x16e50*/ 1438,
+ /*0x04f6*/ 416,
+ -1, -1,
+ /*0x1f3f*/ 744,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x1e905*/ 1459,
- -1, -1, -1, -1, -1,
- /*0xab7c*/ 1157,
- /*0xff35*/ 1257,
+ /*0x04fa*/ 418,
+ /*0x01d1*/ 165,
-1,
- /*0x16e4e*/ 1436,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0x0181*/ 121,
+ /*0x16e46*/ 1468,
-1, -1,
- /*0x118b5*/ 1411,
- -1, -1, -1, -1, -1, -1,
- /*0x01cf*/ 164,
- -1, -1, -1, -1, -1, -1,
- /*0x16e5a*/ 1448,
- -1, -1, -1, -1, -1,
- /*0x0191*/ 132,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
+ /*0x16e58*/ 1486,
+ -1, -1,
+ /*0x018b*/ 128,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1,
- /*0x16e54*/ 1442,
- -1, -1, -1, -1, -1, -1,
+ /*0x04f8*/ 417,
+ /*0x16e40*/ 1462,
+ -1,
+ /*0x118bf*/ 1461,
+ -1,
+ /*0x118b1*/ 1447,
-1, -1, -1, -1, -1, -1,
-1, -1, -1,
- /*0x16e58*/ 1446,
- -1, -1, -1, -1, -1,
- /*0xfb15*/ 1234,
- -1, -1, -1, -1, -1,
- /*0x01f4*/ 183,
- -1, -1, -1, -1, -1, -1,
- /*0x16e53*/ 1441,
+ /*0xff31*/ 1258,
-1, -1,
- /*0x16e43*/ 1425,
- -1, -1, -1, -1, -1, -1,
+ /*0x01f6*/ 184,
-1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0xab72*/ 1152,
+ /*0x01fa*/ 187,
-1, -1, -1, -1, -1, -1,
- /*0xfb01*/ 1226,
-1, -1, -1, -1,
- /*0x16e47*/ 1429,
- -1, -1, -1, -1, -1,
- /*0x16e40*/ 1422,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x16e45*/ 1427,
- -1, -1, -1, -1, -1, -1,
+ /*0xfb05*/ 1235,
-1, -1, -1, -1, -1, -1,
+ /*0x16e49*/ 1471,
+ -1, -1,
+ /*0x1f0b*/ 718,
-1, -1, -1, -1,
- /*0x16e4d*/ 1435,
+ /*0x01f8*/ 186,
-1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0xa77e*/ 1105,
+ -1, -1,
+ /*0xa75c*/ 1092,
+ -1, -1, -1,
+ /*0x16e5a*/ 1488,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
@@ -3566,34 +3621,14 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x16e47*/ 1469,
-1, -1, -1, -1,
- /*0xfb05*/ 1230,
+ /*0x16e45*/ 1467,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xab76*/ 1151,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x16e5e*/ 1452,
-1,
- /*0x16e5c*/ 1450,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0xab7a*/ 1155,
+ /*0x16e55*/ 1483,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
@@ -3612,19 +3647,21 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1,
- /*0x16e41*/ 1423,
- -1, -1, -1, -1, -1, -1,
+ /*0x16e5e*/ 1492,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x16e43*/ 1465,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- /*0x16e4b*/ 1433,
+ -1, -1, -1,
+ /*0xab70*/ 1150,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
@@ -3638,9 +3675,6 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0xab78*/ 1153,
- -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
@@ -3648,80 +3682,30 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x16e4d*/ 1475,
-1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0x10595*/ 1378,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0xab74*/ 1154,
-1, -1, -1, -1, -1,
- /*0xab7e*/ 1159,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x16e4f*/ 1437,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
+ /*0xab7e*/ 1164,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1,
- /*0xab72*/ 1147,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
+ /*0x10591*/ 1375,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ /*0x1058f*/ 1373,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ /*0x10581*/ 1360,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
@@ -3734,27 +3718,22 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0x16e4f*/ 1477,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ /*0xab76*/ 1156,
-1, -1, -1, -1, -1,
- /*0xab70*/ 1145,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
+ /*0x10585*/ 1364,
+ -1, -1, -1,
+ /*0xab7a*/ 1160,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x16e5c*/ 1490,
+ -1, -1, -1, -1,
+ /*0xab78*/ 1158,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
@@ -3768,7 +3747,8 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- /*0xab74*/ 1149
+ -1, -1, -1,
+ /*0x16e51*/ 1479
};
if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE)
@@ -3787,7 +3767,7 @@ onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
}
static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
-#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1355])(CaseUnfold_11_Table+0))
+#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1395])(CaseUnfold_11_Table+0))
{0x0061, {1|U, {0x0041}}},
{0x0062, {1|U, {0x0042}}},
{0x0063, {1|U, {0x0043}}},
@@ -4684,6 +4664,7 @@ static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
{0x2c5c, {1|U, {0x2c2c}}},
{0x2c5d, {1|U, {0x2c2d}}},
{0x2c5e, {1|U, {0x2c2e}}},
+ {0x2c5f, {1|U, {0x2c2f}}},
{0x2c61, {1|U, {0x2c60}}},
{0x2c65, {1|U, {0x023a}}},
{0x2c66, {1|U, {0x023e}}},
@@ -4887,9 +4868,13 @@ static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
{0xa7bb, {1|U, {0xa7ba}}},
{0xa7bd, {1|U, {0xa7bc}}},
{0xa7bf, {1|U, {0xa7be}}},
+ {0xa7c1, {1|U, {0xa7c0}}},
{0xa7c3, {1|U, {0xa7c2}}},
{0xa7c8, {1|U, {0xa7c7}}},
{0xa7ca, {1|U, {0xa7c9}}},
+ {0xa7d1, {1|U, {0xa7d0}}},
+ {0xa7d7, {1|U, {0xa7d6}}},
+ {0xa7d9, {1|U, {0xa7d8}}},
{0xa7f6, {1|U, {0xa7f5}}},
{0xab53, {1|U, {0xa7b3}}},
{0xff41, {1|U, {0xff21}}},
@@ -4994,6 +4979,41 @@ static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
{0x104f9, {1|U, {0x104d1}}},
{0x104fa, {1|U, {0x104d2}}},
{0x104fb, {1|U, {0x104d3}}},
+ {0x10597, {1|U, {0x10570}}},
+ {0x10598, {1|U, {0x10571}}},
+ {0x10599, {1|U, {0x10572}}},
+ {0x1059a, {1|U, {0x10573}}},
+ {0x1059b, {1|U, {0x10574}}},
+ {0x1059c, {1|U, {0x10575}}},
+ {0x1059d, {1|U, {0x10576}}},
+ {0x1059e, {1|U, {0x10577}}},
+ {0x1059f, {1|U, {0x10578}}},
+ {0x105a0, {1|U, {0x10579}}},
+ {0x105a1, {1|U, {0x1057a}}},
+ {0x105a3, {1|U, {0x1057c}}},
+ {0x105a4, {1|U, {0x1057d}}},
+ {0x105a5, {1|U, {0x1057e}}},
+ {0x105a6, {1|U, {0x1057f}}},
+ {0x105a7, {1|U, {0x10580}}},
+ {0x105a8, {1|U, {0x10581}}},
+ {0x105a9, {1|U, {0x10582}}},
+ {0x105aa, {1|U, {0x10583}}},
+ {0x105ab, {1|U, {0x10584}}},
+ {0x105ac, {1|U, {0x10585}}},
+ {0x105ad, {1|U, {0x10586}}},
+ {0x105ae, {1|U, {0x10587}}},
+ {0x105af, {1|U, {0x10588}}},
+ {0x105b0, {1|U, {0x10589}}},
+ {0x105b1, {1|U, {0x1058a}}},
+ {0x105b3, {1|U, {0x1058c}}},
+ {0x105b4, {1|U, {0x1058d}}},
+ {0x105b5, {1|U, {0x1058e}}},
+ {0x105b6, {1|U, {0x1058f}}},
+ {0x105b7, {1|U, {0x10590}}},
+ {0x105b8, {1|U, {0x10591}}},
+ {0x105b9, {1|U, {0x10592}}},
+ {0x105bb, {1|U, {0x10594}}},
+ {0x105bc, {1|U, {0x10595}}},
{0x10cc0, {1|U, {0x10c80}}},
{0x10cc1, {1|U, {0x10c81}}},
{0x10cc2, {1|U, {0x10c82}}},
@@ -5143,14 +5163,14 @@ static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
{0x1e941, {1|U, {0x1e91f}}},
{0x1e942, {1|U, {0x1e920}}},
{0x1e943, {1|U, {0x1e921}}},
-#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1355))
+#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1395))
{0x0069, {1|U, {0x0049}}},
};
/* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_11_hash -N onigenc_unicode_CaseUnfold_11_lookup -n */
-/* maximum key range = 2461, duplicates = 0 */
+/* maximum key range = 2771, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -5165,26 +5185,26 @@ onigenc_unicode_CaseUnfold_11_hash(const OnigCodePoint code)
{
static const unsigned short asso_values[] =
{
- 1, 2464, 2, 7, 4, 582, 9, 308, 197, 674,
- 456, 20, 2, 3, 303, 351, 2464, 2464, 2464, 2464,
- 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, 112,
- 2464, 2464, 2464, 2464, 2464, 2464, 2464, 120, 2464, 2464,
- 2464, 2464, 2464, 1, 2464, 2464, 2464, 2464, 2464, 2464,
- 2464, 2464, 2464, 278, 2464, 2464, 2464, 2464, 2464, 2464,
- 2464, 2464, 12, 1, 7, 8, 218, 878, 222, 1178,
- 480, 1102, 54, 1282, 153, 1579, 8, 15, 151, 1607,
- 225, 854, 87, 490, 106, 1416, 5, 1351, 3, 1502,
- 11, 1215, 377, 10, 441, 599, 152, 1722, 127, 1334,
- 717, 841, 594, 827, 123, 916, 146, 1118, 117, 1363,
- 254, 812, 249, 1096, 1512, 945, 437, 745, 1682, 718,
- 1676, 704, 152, 1005, 383, 1064, 1561, 975, 236, 676,
- 761, 579, 1017, 557, 1241, 628, 1276, 614, 1195, 464,
- 1659, 535, 1627, 513, 1159, 423, 1026, 276, 1506, 291,
- 1460, 392, 1453, 201, 1483, 85, 1412, 70, 1430, 100,
- 1552, 129, 1427, 1, 1386, 25, 1382, 35, 656, 55,
- 1188, 45, 1201, 160, 687, 227, 355, 175, 1373, 328,
- 1030, 367, 1405, 414, 1230, 1166, 1531, 783, 994, 937,
- 1217, 959, 1023, 967
+ 1, 2774, 2, 2, 4, 421, 9, 371, 231, 463,
+ 37, 20, 2, 3, 419, 408, 2774, 2774, 2774, 2774,
+ 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774, 112,
+ 2774, 2774, 2774, 2774, 2774, 2774, 2774, 120, 2774, 2774,
+ 2774, 2774, 2774, 1, 2774, 2774, 2774, 2774, 2774, 2774,
+ 2774, 2774, 2774, 355, 2774, 2774, 2774, 2774, 2774, 2774,
+ 2774, 2774, 10, 9, 7, 8, 244, 689, 226, 993,
+ 561, 710, 104, 1429, 36, 1190, 28, 15, 114, 1768,
+ 241, 1003, 87, 285, 26, 1399, 78, 1360, 7, 1455,
+ 90, 1076, 113, 10, 724, 1460, 167, 1727, 155, 1040,
+ 67, 754, 66, 705, 246, 886, 331, 1140, 430, 1251,
+ 864, 768, 643, 1064, 1591, 865, 834, 720, 1700, 671,
+ 1581, 657, 1794, 842, 1782, 1050, 1537, 1024, 1760, 814,
+ 975, 440, 1187, 407, 1440, 951, 1384, 909, 1320, 555,
+ 1567, 541, 1723, 525, 383, 501, 1179, 250, 1596, 342,
+ 1575, 352, 1501, 194, 1559, 70, 1512, 85, 1509, 129,
+ 467, 100, 1413, 1, 1485, 25, 1351, 35, 1088, 55,
+ 1262, 45, 1277, 160, 1245, 317, 118, 220, 1300, 596,
+ 1100, 373, 1632, 617, 1337, 1236, 1500, 1152, 148, 793,
+ 1538, 979, 385, 1228
};
return asso_values[bits_of(code, 2)+66] + asso_values[bits_of(code, 1)+4] + asso_values[bits_of(code, 0)];
}
@@ -5196,11 +5216,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
{
MIN_CODE_VALUE = 0x61,
MAX_CODE_VALUE = 0x1e943,
- TOTAL_KEYWORDS = 1356,
+ TOTAL_KEYWORDS = 1396,
MIN_WORD_LENGTH = 3,
MAX_WORD_LENGTH = 3,
MIN_HASH_VALUE = 3,
- MAX_HASH_VALUE = 2463
+ MAX_HASH_VALUE = 2773
};
static const short wordlist[] =
@@ -5211,11 +5231,11 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
/*0x04e1*/ 400,
/*0x0061*/ 0,
-1,
- /*0x104e1*/ 1179,
+ /*0x104e1*/ 1184,
/*0x1e61*/ 661,
/*0x1ee1*/ 720,
/*0x0161*/ 102,
- /*0x2ce1*/ 952,
+ /*0x2ce1*/ 953,
-1,
/*0x049b*/ 365,
-1, -1,
@@ -5223,28 +5243,28 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
/*0x1e1b*/ 626,
/*0x048b*/ 357,
/*0x011b*/ 69,
- /*0x2c9b*/ 917,
+ /*0x2c9b*/ 918,
/*0x03e1*/ 280,
/*0x1e0b*/ 618,
/*0x1e8b*/ 682,
/*0x010b*/ 61,
- /*0x2c8b*/ 909,
+ /*0x2c8b*/ 910,
/*0x13e3*/ 591,
/*0x0463*/ 341,
/*0x04e3*/ 401,
/*0x0063*/ 2,
-1,
- /*0x104e3*/ 1181,
+ /*0x104e3*/ 1186,
/*0x1e63*/ 662,
/*0x1ee3*/ 721,
/*0x0163*/ 103,
- /*0x2ce3*/ 953,
+ /*0x2ce3*/ 954,
/*0x13e5*/ 593,
/*0x0465*/ 342,
/*0x04e5*/ 402,
/*0x0065*/ 4,
/*0x24e3*/ 842,
- /*0x104e5*/ 1183,
+ /*0x104e5*/ 1188,
/*0x1e65*/ 663,
/*0x1ee5*/ 722,
/*0x0165*/ 104,
@@ -5252,9 +5272,9 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
/*0x13e9*/ 597,
/*0x0469*/ 344,
/*0x04e9*/ 404,
- /*0x0069*/ 1355,
+ /*0x0069*/ 1395,
/*0x24e5*/ 844,
- /*0x104e9*/ 1187,
+ /*0x104e9*/ 1192,
/*0x1e69*/ 665,
/*0x1ee9*/ 724,
/*0x0169*/ 106,
@@ -5264,1798 +5284,1893 @@ onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
/*0x04e7*/ 403,
/*0x0067*/ 6,
/*0x24e9*/ 848,
- /*0x104e7*/ 1185,
+ /*0x104e7*/ 1190,
/*0x1e67*/ 664,
/*0x1ee7*/ 723,
/*0x0167*/ 105,
/*0x03e9*/ 284,
- -1, -1, -1, -1,
- /*0x24e7*/ 846,
- /*0x13db*/ 583,
- /*0x045b*/ 335,
- /*0x04db*/ 397,
-1,
- /*0x03e7*/ 283,
- /*0x104db*/ 1173,
- /*0x1e5b*/ 658,
- /*0x1edb*/ 717,
- /*0x015b*/ 99,
- /*0x2cdb*/ 949,
- -1, -1, -1, -1,
- /*0x24db*/ 834,
+ /*0x13a4*/ 528,
+ /*0x13a2*/ 526,
+ -1,
+ /*0x24e7*/ 846,
/*0x13d9*/ 581,
/*0x0459*/ 333,
/*0x04d9*/ 396,
- /*0xa761*/ 1064,
- /*0x03db*/ 277,
- /*0x104d9*/ 1171,
+ -1,
+ /*0x03e7*/ 283,
+ /*0x104d9*/ 1176,
/*0x1e59*/ 657,
/*0x1ed9*/ 716,
/*0x0159*/ 98,
- /*0x2cd9*/ 948,
+ /*0x2cd9*/ 949,
-1, -1, -1, -1,
/*0x24d9*/ 832,
- /*0x13dd*/ 585,
- /*0x045d*/ 337,
- /*0x04dd*/ 398,
- -1,
+ /*0x13db*/ 583,
+ /*0x045b*/ 335,
+ /*0x04db*/ 397,
+ /*0xa761*/ 1065,
/*0x03d9*/ 276,
- /*0x104dd*/ 1175,
- /*0x1e5d*/ 659,
- /*0x1edd*/ 718,
- /*0x015d*/ 100,
- /*0x2cdd*/ 950,
- -1, -1,
- /*0xa763*/ 1065,
- -1,
- /*0x24dd*/ 836,
- /*0x10ce1*/ 1239,
- -1,
- /*0x13aa*/ 534,
- -1,
- /*0x03dd*/ 278,
- /*0x10e1*/ 495,
- /*0x1042a*/ 1132,
- /*0xa765*/ 1066,
- /*0x13a6*/ 530,
- -1, -1, -1,
- /*0x13a0*/ 524,
- -1,
+ /*0x104db*/ 1178,
+ /*0x1e5b*/ 658,
+ /*0x1edb*/ 717,
+ /*0x015b*/ 99,
+ /*0x2cdb*/ 950,
+ -1, -1, -1, -1,
+ /*0x24db*/ 834,
/*0x13df*/ 587,
/*0x045f*/ 339,
/*0x04df*/ 399,
- /*0xa769*/ 1068,
-1,
- /*0x104df*/ 1177,
+ /*0x03db*/ 277,
+ /*0x104df*/ 1182,
/*0x1e5f*/ 660,
/*0x1edf*/ 719,
/*0x015f*/ 101,
- /*0x2cdf*/ 951,
- /*0x10ce3*/ 1241,
+ /*0x2cdf*/ 952,
-1, -1,
- /*0xa767*/ 1067,
+ /*0xa763*/ 1066,
+ /*0x2c61*/ 897,
/*0x24df*/ 838,
- /*0x10e3*/ 497,
+ /*0x10ce1*/ 1279,
+ -1, -1,
+ /*0x13ee*/ 602,
+ /*0x03df*/ 279,
+ /*0x10e1*/ 495,
+ /*0x006e*/ 12,
+ /*0xa765*/ 1067,
+ /*0x104ee*/ 1197,
+ -1, -1, -1,
+ /*0x2cee*/ 956,
-1,
- /*0x13a8*/ 532,
+ /*0x13dd*/ 585,
+ /*0x045d*/ 337,
+ /*0x04dd*/ 398,
+ /*0xa769*/ 1069,
-1,
- /*0x03df*/ 279,
- /*0x10ce5*/ 1243,
- /*0x10428*/ 1130,
+ /*0x104dd*/ 1180,
+ /*0x1e5d*/ 659,
+ /*0x1edd*/ 718,
+ /*0x015d*/ 100,
+ /*0x2cdd*/ 951,
+ /*0x10ce3*/ 1281,
+ -1, -1,
+ /*0xa767*/ 1068,
+ /*0x24dd*/ 836,
+ /*0x10e3*/ 497,
+ -1, -1,
+ /*0x2c65*/ 898,
+ /*0x03dd*/ 278,
+ /*0x10ce5*/ 1283,
-1,
- /*0x13b8*/ 548,
- /*0x0438*/ 300,
- /*0x10e5*/ 499,
+ /*0x007a*/ 24,
-1,
- /*0x10438*/ 1146,
- /*0xa75b*/ 1061,
+ /*0x104fa*/ 1209,
+ /*0x10e5*/ 499,
+ /*0x13a0*/ 524,
+ /*0x017a*/ 114,
+ /*0xa759*/ 1061,
-1,
- /*0x10ce9*/ 1247,
+ /*0x10ce9*/ 1287,
/*0x13eb*/ 599,
/*0x046b*/ 345,
/*0x04eb*/ 405,
/*0x006b*/ 9,
/*0x10e9*/ 503,
- /*0x104eb*/ 1189,
+ /*0x104eb*/ 1194,
/*0x1e6b*/ 666,
/*0x1eeb*/ 725,
/*0x016b*/ 107,
- /*0x10ce7*/ 1245,
- -1,
- /*0x03b8*/ 253,
- /*0xa759*/ 1060,
+ /*0x10ce7*/ 1285,
+ -1, -1,
+ /*0xa75b*/ 1062,
-1,
/*0x10e7*/ 501,
- /*0x13ef*/ 603,
- /*0x046f*/ 347,
- /*0x04ef*/ 407,
- /*0x006f*/ 13,
+ -1, -1, -1, -1,
/*0x03eb*/ 285,
- /*0x104ef*/ 1193,
- /*0x1e6f*/ 668,
- /*0x1eef*/ 727,
- /*0x016f*/ 109,
- /*0x10cdb*/ 1233,
-1, -1,
- /*0xa75d*/ 1062,
+ /*0x2c59*/ 890,
-1,
- /*0x10db*/ 489,
- -1, -1, -1, -1,
- /*0x03ef*/ 287,
+ /*0x10cd9*/ 1271,
-1, -1,
- /*0x0261*/ 210,
- -1,
- /*0x10cd9*/ 1231,
+ /*0xa75f*/ 1064,
-1,
+ /*0x10d9*/ 487,
+ -1, -1, -1, -1,
/*0x13d7*/ 579,
/*0x0457*/ 331,
/*0x04d7*/ 395,
- /*0x10d9*/ 487,
+ /*0x2c5b*/ 892,
-1,
- /*0x021b*/ 178,
+ /*0x10cdb*/ 1273,
/*0x1e57*/ 656,
/*0x1ed7*/ 715,
/*0x0157*/ 97,
- /*0x2cd7*/ 947,
- /*0x020b*/ 170,
- -1, -1,
- /*0x10cdd*/ 1235,
+ /*0x2cd7*/ 948,
+ /*0x10db*/ 489,
+ -1, -1, -1,
/*0x24d7*/ 830,
- /*0xa75f*/ 1063,
- -1,
- /*0x1f61*/ 777,
- /*0x10dd*/ 491,
+ -1, -1, -1,
+ /*0x2c5f*/ 896,
/*0x03d7*/ 275,
- /*0x0263*/ 211,
- /*0x1f14*/ 748,
- -1, -1,
- /*0x1d8e*/ 612,
- /*0xa661*/ 1013,
- /*0x13ed*/ 601,
- /*0x046d*/ 346,
- /*0x04ed*/ 406,
- /*0x006d*/ 11,
- /*0x0265*/ 212,
- /*0x104ed*/ 1191,
- /*0x1e6d*/ 667,
- /*0x1eed*/ 726,
- /*0x016d*/ 108,
- /*0x13be*/ 554,
- /*0x043e*/ 306,
- -1, -1,
- /*0x1043e*/ 1152,
- /*0x0269*/ 215,
- /*0x1f63*/ 779,
- /*0x10cdf*/ 1237,
- /*0x013e*/ 85,
+ /*0x10cdf*/ 1277,
-1,
- /*0x03ed*/ 286,
- /*0xa76b*/ 1069,
+ /*0xa75d*/ 1063,
+ -1, -1,
/*0x10df*/ 493,
- /*0x13ae*/ 538,
- /*0xa663*/ 1014,
+ /*0x13ef*/ 603,
+ /*0x046f*/ 347,
+ /*0x04ef*/ 407,
+ /*0x006f*/ 13,
-1,
- /*0x1f65*/ 781,
- /*0x1042e*/ 1136,
- /*0x13ac*/ 536,
- /*0x03be*/ 259,
+ /*0x104ef*/ 1198,
+ /*0x1e6f*/ 668,
+ /*0x1eef*/ 727,
+ /*0x016f*/ 109,
-1, -1,
- /*0x1042c*/ 1134,
- -1,
- /*0xa665*/ 1015,
- -1,
- /*0xa76f*/ 1071,
- -1, -1, -1,
- /*0x025b*/ 207,
- -1,
- /*0x03ae*/ 244,
+ /*0x0261*/ 210,
+ /*0x10cee*/ 1292,
+ -1, -1,
+ /*0xa77a*/ 1073,
-1,
- /*0xa669*/ 1017,
- /*0x1f06*/ 742,
- /*0x1f67*/ 783,
- /*0x03ac*/ 242,
- /*0x10ceb*/ 1249,
+ /*0x10ee*/ 508,
-1,
+ /*0x03ef*/ 287,
+ /*0x021b*/ 178,
+ /*0x2c5d*/ 894,
+ /*0xa661*/ 1014,
+ /*0x10cdd*/ 1275,
+ /*0x1f61*/ 777,
+ /*0x020b*/ 170,
+ /*0x13a6*/ 530,
+ /*0xa76b*/ 1070,
+ /*0x10dd*/ 491,
+ /*0x1d8e*/ 612,
/*0x13d1*/ 573,
/*0x0451*/ 325,
/*0x04d1*/ 392,
- /*0x10eb*/ 505,
- /*0xa667*/ 1016,
- /*0x0259*/ 206,
+ -1, -1,
+ /*0x0263*/ 211,
/*0x1e51*/ 653,
/*0x1ed1*/ 712,
/*0x0151*/ 94,
- /*0x2cd1*/ 944,
- -1, -1,
- /*0xa757*/ 1059,
- /*0x10cef*/ 1253,
+ /*0x2cd1*/ 945,
+ -1, -1, -1, -1,
/*0x24d1*/ 824,
- /*0x13d3*/ 575,
- /*0x0453*/ 327,
- /*0x04d3*/ 393,
- /*0x10ef*/ 509,
- /*0xa65b*/ 1010,
- -1,
- /*0x1e53*/ 654,
- /*0x1ed3*/ 713,
- /*0x0153*/ 95,
- /*0x2cd3*/ 945,
+ /*0x0265*/ 212,
+ /*0xa663*/ 1015,
+ /*0x10fa*/ 520,
+ /*0x1f63*/ 779,
+ /*0x1f12*/ 746,
+ -1, -1, -1, -1,
+ /*0x10ceb*/ 1289,
+ /*0x0269*/ 215,
+ /*0xa665*/ 1016,
-1,
- /*0xab53*/ 1103,
- /*0x0561*/ 440,
- /*0x1f10*/ 744,
- /*0x24d3*/ 826,
- -1, -1,
- /*0x01e1*/ 151,
+ /*0x1f65*/ 781,
+ /*0x10eb*/ 505,
-1,
- /*0xa659*/ 1009,
+ /*0xa757*/ 1060,
+ -1, -1, -1, -1,
+ /*0xa669*/ 1018,
+ /*0x0491*/ 360,
+ -1, -1, -1,
+ /*0x1e11*/ 621,
+ /*0x1e91*/ 685,
+ /*0x0111*/ 64,
+ /*0x2c91*/ 913,
+ /*0xa79b*/ 1086,
+ /*0xa667*/ 1017,
-1,
- /*0x051b*/ 429,
+ /*0x1f67*/ 783,
-1,
- /*0xa76d*/ 1070,
- /*0x10cd7*/ 1229,
+ /*0x0259*/ 206,
+ -1, -1, -1, -1, -1,
+ /*0x2c57*/ 888,
+ /*0xa76f*/ 1072,
+ /*0x10cd7*/ 1269,
+ /*0x1f24*/ 754,
+ /*0x1f22*/ 752,
+ /*0xa659*/ 1010,
-1,
- /*0x050b*/ 421,
- -1, -1,
/*0x10d7*/ 485,
- -1, -1,
- /*0x1f12*/ 746,
-1,
- /*0xa65d*/ 1011,
+ /*0x025b*/ 207,
-1,
- /*0x0563*/ 442,
- /*0x13f1*/ 605,
- /*0x0471*/ 348,
- /*0x04f1*/ 408,
- /*0x0071*/ 15,
- /*0x01e3*/ 152,
- /*0x104f1*/ 1195,
- /*0x1e71*/ 669,
- /*0x1ef1*/ 728,
- /*0x0171*/ 110,
- /*0x0565*/ 444,
+ /*0x13ed*/ 601,
+ /*0x046d*/ 346,
+ /*0x04ed*/ 406,
+ /*0x006d*/ 11,
+ /*0x1f14*/ 748,
+ /*0x104ed*/ 1196,
+ /*0x1e6d*/ 667,
+ /*0x1eed*/ 726,
+ /*0x016d*/ 108,
+ /*0xa65b*/ 1011,
+ -1, -1, -1,
+ /*0x1f10*/ 744,
+ /*0x13a8*/ 532,
-1, -1,
- /*0x1f26*/ 756,
- /*0x10ced*/ 1251,
- /*0x01e5*/ 153,
+ /*0x10cef*/ 1293,
+ /*0x10428*/ 1135,
+ /*0x03ed*/ 286,
+ /*0xa751*/ 1057,
-1,
- /*0x1f20*/ 750,
+ /*0x10ef*/ 509,
-1,
- /*0x10ed*/ 507,
- /*0x0569*/ 448,
+ /*0xa65f*/ 1013,
+ /*0x13d3*/ 575,
+ /*0x0453*/ 327,
+ /*0x04d3*/ 393,
-1, -1,
- /*0x118db*/ 1284,
- -1,
- /*0x01e9*/ 155,
- -1,
- /*0xa65f*/ 1012,
- /*0x13ee*/ 602,
- /*0x026b*/ 217,
- /*0x0567*/ 446,
- /*0x006e*/ 12,
+ /*0x1f06*/ 742,
+ /*0x1e53*/ 654,
+ /*0x1ed3*/ 713,
+ /*0x0153*/ 95,
+ /*0x2cd3*/ 946,
+ /*0x13d5*/ 577,
+ /*0x0455*/ 329,
+ /*0x04d5*/ 394,
+ /*0xa7d9*/ 1106,
+ /*0x24d3*/ 826,
-1,
- /*0x104ee*/ 1192,
+ /*0x1e55*/ 655,
+ /*0x1ed5*/ 714,
+ /*0x0155*/ 96,
+ /*0x2cd5*/ 947,
+ /*0x2c51*/ 882,
+ /*0xa794*/ 1083,
+ /*0x10cd1*/ 1263,
-1,
- /*0x01e7*/ 154,
- /*0xa751*/ 1056,
- /*0x2cee*/ 955,
- /*0x118d9*/ 1282,
+ /*0x24d5*/ 828,
+ -1, -1,
+ /*0x10d1*/ 479,
+ /*0xa65d*/ 1012,
+ /*0x01e1*/ 151,
-1,
/*0x13f3*/ 607,
/*0x0473*/ 349,
/*0x04f3*/ 409,
/*0x0073*/ 17,
- /*0x026f*/ 219,
- /*0x104f3*/ 1197,
+ -1,
+ /*0x104f3*/ 1202,
/*0x1e73*/ 670,
/*0x1ef3*/ 729,
/*0x0173*/ 111,
- /*0x2cf3*/ 956,
- /*0x2c61*/ 896,
- /*0xa753*/ 1057,
+ /*0x2cf3*/ 957,
+ /*0x13ce*/ 570,
+ /*0x044e*/ 322,
+ /*0x04ce*/ 390,
-1,
- /*0x118dd*/ 1286,
+ /*0x1044e*/ 1173,
-1, -1,
- /*0x13ba*/ 550,
- /*0x043a*/ 302,
- /*0xa66b*/ 1018,
+ /*0x026b*/ 217,
+ /*0x1f7a*/ 794,
/*0x03f3*/ 289,
- /*0x1043a*/ 1148,
- -1, -1,
- /*0x10cd1*/ 1223,
- /*0x013a*/ 83,
- /*0x13d5*/ 577,
- /*0x0455*/ 329,
- /*0x04d5*/ 394,
- /*0x10d1*/ 479,
+ /*0x017e*/ 116,
-1,
- /*0x0257*/ 205,
- /*0x1e55*/ 655,
- /*0x1ed5*/ 714,
- /*0x0155*/ 96,
- /*0x2cd5*/ 946,
- /*0x03ba*/ 255,
+ /*0x01e3*/ 152,
+ /*0x0192*/ 122,
-1,
- /*0x0586*/ 477,
- /*0x10cd3*/ 1225,
- /*0x24d5*/ 828,
- /*0x01dd*/ 149,
+ /*0x1f20*/ 750,
+ /*0xa78c*/ 1080,
-1,
- /*0x118df*/ 1288,
- /*0x10d3*/ 481,
- /*0x2c65*/ 897,
+ /*0xa66b*/ 1019,
+ /*0x03ce*/ 274,
-1,
- /*0x0192*/ 122,
- /*0x13f5*/ 609,
- /*0x0475*/ 350,
- /*0x04f5*/ 410,
- /*0x0075*/ 19,
- /*0x1f57*/ 775,
- /*0x104f5*/ 1199,
- /*0x1e75*/ 671,
- /*0x1ef5*/ 730,
- /*0x0175*/ 112,
- /*0x13cf*/ 571,
- /*0x044f*/ 323,
- /*0x04cf*/ 391,
- /*0xa657*/ 1008,
- /*0x1044f*/ 1169,
- /*0x1e92a*/ 1329,
- /*0x1e4f*/ 652,
- /*0x1ecf*/ 711,
- /*0x014f*/ 93,
- /*0x2ccf*/ 943,
+ /*0xa76d*/ 1071,
+ /*0x01e5*/ 153,
+ /*0x0188*/ 120,
+ /*0x13c3*/ 559,
+ /*0x0443*/ 311,
+ /*0x0373*/ 237,
-1,
- /*0x1e926*/ 1325,
- /*0x1f00*/ 736,
- /*0x01df*/ 150,
- /*0x13b2*/ 542,
- /*0x0432*/ 294,
- /*0x1f02*/ 738,
+ /*0x10443*/ 1162,
-1,
- /*0x10432*/ 1140,
- /*0x10cf1*/ 1255,
- /*0x2d16*/ 979,
+ /*0x1e43*/ 646,
+ /*0x1ec3*/ 705,
+ /*0x01e9*/ 155,
+ /*0x2cc3*/ 938,
+ -1, -1,
+ /*0x0561*/ 440,
+ /*0x1059b*/ 1215,
+ /*0x00e1*/ 26,
+ -1, -1,
+ /*0x0257*/ 205,
+ /*0x01e7*/ 154,
+ /*0x03c3*/ 263,
+ /*0x118d9*/ 1322,
+ /*0x051b*/ 429,
+ /*0xa753*/ 1058,
+ /*0x13aa*/ 534,
+ /*0x10ced*/ 1291,
+ /*0xab53*/ 1108,
+ /*0x050b*/ 421,
+ /*0x1042a*/ 1137,
+ /*0xa657*/ 1009,
+ /*0x10ed*/ 507,
+ /*0x1f57*/ 775,
-1,
- /*0x2d14*/ 977,
- /*0x2c5b*/ 892,
- /*0x10f1*/ 511,
- /*0x2d0a*/ 967,
+ /*0xa755*/ 1059,
+ /*0x13c1*/ 557,
+ /*0x0441*/ 309,
+ /*0x118db*/ 1324,
+ /*0x0563*/ 442,
+ /*0x10441*/ 1160,
+ /*0x00e3*/ 28,
+ /*0x1e41*/ 645,
+ /*0x1ec1*/ 704,
-1,
- /*0x2d1b*/ 984,
- /*0x2d18*/ 981,
- /*0xa66d*/ 1019,
- /*0x01a8*/ 130,
+ /*0x2cc1*/ 937,
+ /*0x026f*/ 219,
+ -1, -1,
+ /*0x0565*/ 444,
+ /*0x2c53*/ 884,
+ /*0x00e5*/ 30,
+ /*0x10cd3*/ 1265,
+ /*0x118df*/ 1328,
-1,
- /*0x2d0b*/ 968,
- /*0x03b2*/ 247,
- /*0x1e928*/ 1327,
- /*0x018c*/ 121,
- /*0x019e*/ 126,
- /*0x0188*/ 120,
- /*0x2c59*/ 890,
- /*0x056b*/ 450,
- /*0x1e938*/ 1343,
- /*0x13c9*/ 565,
- /*0x0449*/ 317,
+ /*0x03c1*/ 262,
-1,
- /*0x01eb*/ 156,
- /*0x10449*/ 1163,
- /*0x10cee*/ 1252,
- /*0x1e49*/ 649,
- /*0x1ec9*/ 708,
- /*0x0251*/ 200,
- /*0x2cc9*/ 940,
- /*0x10ee*/ 508,
+ /*0x10d3*/ 481,
-1,
- /*0x2c5d*/ 894,
- /*0x056f*/ 454,
+ /*0x0569*/ 448,
+ /*0x2c55*/ 886,
+ /*0x00e9*/ 34,
+ /*0x10cd5*/ 1267,
+ /*0x13de*/ 586,
+ /*0x045e*/ 338,
+ /*0x1f02*/ 738,
+ /*0x01df*/ 150,
+ /*0x10d5*/ 483,
+ /*0x104de*/ 1181,
+ /*0x0567*/ 446,
-1,
- /*0xa755*/ 1058,
+ /*0x00e7*/ 32,
+ /*0x105a4*/ 1223,
+ /*0x028b*/ 231,
-1,
- /*0x118d7*/ 1280,
- /*0x01ef*/ 158,
- /*0x03c9*/ 269,
- -1, -1,
+ /*0xa7d7*/ 1105,
+ /*0x0251*/ 200,
+ /*0x24de*/ 837,
+ -1,
+ /*0x019a*/ 125,
+ /*0x018c*/ 121,
+ /*0x2c73*/ 903,
+ /*0x118dd*/ 1326,
+ /*0x1f00*/ 736,
+ /*0x0292*/ 233,
+ /*0x1f26*/ 756,
+ /*0x028a*/ 230,
+ /*0xa651*/ 1006,
/*0x10f3*/ 513,
- /*0x0253*/ 202,
- -1, -1, -1, -1,
- /*0x0491*/ 360,
/*0x1f51*/ 772,
- /*0x2d06*/ 963,
- /*0xa794*/ 1082,
- /*0x1e11*/ 621,
- /*0x1e91*/ 685,
- /*0x0111*/ 64,
- /*0x2c91*/ 912,
- /*0xa79b*/ 1085,
- /*0xa651*/ 1005,
- -1, -1, -1, -1,
- /*0x10cd5*/ 1227,
+ /*0xa743*/ 1050,
+ /*0x2c4e*/ 879,
-1,
- /*0x1f53*/ 773,
+ /*0x10cce*/ 1260,
+ /*0x0288*/ 228,
+ /*0x01dd*/ 149,
+ /*0x10598*/ 1212,
+ /*0x13cf*/ 571,
+ /*0x044f*/ 323,
+ /*0x04cf*/ 391,
+ /*0x10fe*/ 522,
+ /*0x1044f*/ 1174,
-1,
- /*0xa74f*/ 1055,
- /*0x10d5*/ 483,
+ /*0x1e4f*/ 652,
+ /*0x1ecf*/ 711,
+ /*0x014f*/ 93,
+ /*0x2ccf*/ 944,
+ /*0x0586*/ 477,
-1,
- /*0x13cd*/ 569,
- /*0x044d*/ 321,
+ /*0x1e924*/ 1363,
+ /*0x1e922*/ 1361,
+ /*0x0211*/ 173,
+ -1, -1, -1,
+ /*0x2c43*/ 868,
-1,
- /*0xa653*/ 1006,
- /*0x1044d*/ 1167,
+ /*0x10cc3*/ 1249,
-1,
+ /*0x1059a*/ 1214,
+ -1,
+ /*0x13cd*/ 569,
+ /*0x044d*/ 321,
+ /*0xa741*/ 1049,
+ /*0x1f11*/ 745,
+ /*0x1044d*/ 1172,
+ /*0x01eb*/ 156,
/*0x1e4d*/ 651,
/*0x1ecd*/ 710,
/*0x014d*/ 92,
- /*0x2ccd*/ 942,
- -1,
- /*0x0271*/ 220,
- /*0x0180*/ 117,
- -1,
- /*0x2d10*/ 973,
- /*0x2c38*/ 857,
- /*0x056d*/ 452,
+ /*0x2ccd*/ 943,
+ /*0xa7d1*/ 1104,
+ /*0x056e*/ 453,
+ /*0x019e*/ 126,
+ /*0x00ee*/ 39,
-1, -1,
- /*0x03cd*/ 273,
- /*0x10f5*/ 515,
- /*0x01ed*/ 157,
/*0x13cb*/ 567,
/*0x044b*/ 319,
- /*0x10ccf*/ 1221,
-1,
- /*0x1044b*/ 1165,
+ /*0x03cd*/ 273,
+ /*0x1044b*/ 1170,
-1,
/*0x1e4b*/ 650,
/*0x1ecb*/ 709,
/*0x014b*/ 91,
- /*0x2ccb*/ 941,
- /*0x1f71*/ 785,
- /*0x2d12*/ 975,
- /*0x1e93e*/ 1349,
- -1, -1, -1,
- /*0xa749*/ 1052,
- -1, -1,
- /*0x03cb*/ 271,
+ /*0x2ccb*/ 942,
+ /*0x118d7*/ 1320,
+ /*0x2c41*/ 866,
-1,
- /*0x118d1*/ 1274,
- /*0x13c3*/ 559,
- /*0x0443*/ 311,
+ /*0x10cc1*/ 1247,
+ /*0x13c9*/ 565,
+ /*0x0449*/ 317,
-1,
- /*0x1e92e*/ 1333,
- /*0x10443*/ 1157,
+ /*0xa66d*/ 1020,
+ /*0x10449*/ 1168,
+ /*0x03cb*/ 271,
+ /*0x1e49*/ 649,
+ /*0x1ec9*/ 708,
-1,
- /*0x1e43*/ 646,
- /*0x1ec3*/ 705,
- /*0x1e92c*/ 1331,
- /*0x2cc3*/ 937,
- /*0x2d20*/ 989,
- /*0x0580*/ 471,
- -1, -1,
- /*0x118d3*/ 1276,
- /*0x0582*/ 473,
- -1, -1, -1,
- /*0x03c3*/ 263,
- /*0x2c57*/ 888,
- /*0x10cc9*/ 1215,
- /*0x13c1*/ 557,
- /*0x0441*/ 309,
+ /*0x2cc9*/ 941,
+ /*0x105a0*/ 1220,
+ /*0x057a*/ 465,
-1,
- /*0x00e1*/ 26,
- /*0x10441*/ 1155,
- /*0x1f73*/ 787,
- /*0x1e41*/ 645,
- /*0x1ec1*/ 704,
+ /*0x00fa*/ 50,
-1,
- /*0x2cc1*/ 936,
- -1, -1,
- /*0x2d0c*/ 969,
- /*0x2d1e*/ 987,
- /*0x2d08*/ 965,
- /*0x13a4*/ 528,
- -1, -1, -1,
- /*0x03c1*/ 262,
+ /*0xa791*/ 1081,
-1,
- /*0xa74d*/ 1054,
- /*0x049d*/ 366,
- -1, -1, -1,
- /*0x1e1d*/ 627,
- /*0x00e3*/ 28,
- /*0x011d*/ 70,
- /*0x2c9d*/ 918,
- /*0x1f55*/ 774,
- /*0x0275*/ 222,
+ /*0x0253*/ 202,
-1,
- /*0x2c3e*/ 863,
+ /*0x03c9*/ 269,
-1,
- /*0x13c7*/ 563,
- /*0x0447*/ 315,
- /*0x00e5*/ 30,
- /*0xa655*/ 1007,
- /*0x10447*/ 1161,
- /*0x024f*/ 198,
- /*0x1e47*/ 648,
- /*0x1ec7*/ 707,
- /*0xa74b*/ 1053,
- /*0x2cc7*/ 939,
- -1, -1,
- /*0x00e9*/ 34,
- /*0x10ccd*/ 1219,
- /*0x13c5*/ 561,
- /*0x0445*/ 313,
- /*0x0571*/ 456,
- /*0x1f75*/ 789,
- /*0x10445*/ 1159,
- /*0x03c7*/ 267,
- /*0x1e45*/ 647,
- /*0x1ec5*/ 706,
- /*0x00e7*/ 32,
- /*0x2cc5*/ 938,
- -1, -1, -1,
- /*0xa78c*/ 1079,
- -1, -1,
- /*0xa743*/ 1049,
- -1, -1,
- /*0x03c5*/ 265,
- /*0xa64f*/ 1004,
- /*0x10ccb*/ 1217,
- -1, -1,
- /*0x2c51*/ 882,
+ /*0x028c*/ 232,
+ /*0x1059e*/ 1218,
+ /*0x056b*/ 450,
+ /*0x2c5e*/ 895,
+ /*0x00eb*/ 36,
+ /*0x10cde*/ 1276,
-1,
- /*0x1f32*/ 760,
+ /*0xa653*/ 1007,
-1,
- /*0x13e6*/ 594,
- /*0x056e*/ 453,
- /*0x2d00*/ 957,
- /*0x0066*/ 5,
- /*0x0249*/ 195,
- /*0x104e6*/ 1184,
- /*0x2d02*/ 959,
+ /*0x1f53*/ 773,
+ /*0x10de*/ 492,
+ /*0x16e61*/ 1330,
+ /*0xa74f*/ 1056,
+ -1,
+ /*0x01ef*/ 158,
-1, -1,
- /*0x2d0e*/ 971,
- /*0xa741*/ 1048,
- /*0x2c53*/ 884,
+ /*0xa655*/ 1008,
-1,
- /*0x0573*/ 458,
- /*0x24e6*/ 845,
- /*0x10cc3*/ 1209,
- /*0x118d5*/ 1278,
+ /*0x1f55*/ 774,
+ /*0x13f1*/ 605,
+ /*0x0471*/ 348,
+ /*0x04f1*/ 408,
+ /*0x0071*/ 15,
-1,
- /*0x01f3*/ 159,
+ /*0x104f1*/ 1200,
+ /*0x1e71*/ 669,
+ /*0x1ef1*/ 728,
+ /*0x0171*/ 110,
+ -1, -1,
+ /*0x118d1*/ 1314,
+ -1, -1, -1,
+ /*0x16e63*/ 1332,
+ /*0xa74d*/ 1055,
+ /*0x2c4f*/ 880,
+ /*0x0180*/ 117,
+ /*0x10ccf*/ 1261,
+ /*0x1f73*/ 787,
+ /*0x13f5*/ 609,
+ /*0x0475*/ 350,
+ /*0x04f5*/ 410,
+ /*0x0075*/ 19,
+ /*0x16e65*/ 1334,
+ /*0x104f5*/ 1204,
+ /*0x1e75*/ 671,
+ /*0x1ef5*/ 730,
+ /*0x0175*/ 112,
+ -1, -1,
+ /*0xa74b*/ 1054,
+ /*0x029e*/ 235,
-1,
- /*0x13bf*/ 555,
- /*0x043f*/ 307,
- /*0x04bf*/ 383,
+ /*0x16e69*/ 1338,
+ /*0x0371*/ 236,
+ /*0x0582*/ 473,
+ -1, -1, -1,
+ /*0x2c4d*/ 878,
+ /*0x056f*/ 454,
+ /*0x10ccd*/ 1259,
+ /*0x00ef*/ 40,
+ /*0x16e67*/ 1336,
+ /*0xa749*/ 1053,
+ /*0x13ae*/ 538,
+ -1, -1, -1,
+ /*0x1042e*/ 1141,
+ /*0xa643*/ 999,
-1,
- /*0x1043f*/ 1153,
- /*0x028a*/ 230,
- /*0x1e3f*/ 644,
- /*0x1ebf*/ 703,
- /*0x019a*/ 125,
- /*0x2cbf*/ 935,
- /*0x0211*/ 173,
- /*0x13ec*/ 600,
- /*0x028b*/ 231,
- /*0xa649*/ 1001,
- /*0x006c*/ 10,
+ /*0x1f43*/ 769,
+ /*0x0580*/ 471,
-1,
- /*0x104ec*/ 1190,
- /*0x10cc1*/ 1207,
- /*0x1e93a*/ 1345,
- /*0x03bf*/ 260,
- /*0x2cec*/ 954,
- /*0x1f04*/ 740,
- -1, -1, -1,
- /*0xa747*/ 1051,
+ /*0x2c4b*/ 876,
-1,
- /*0x118cf*/ 1272,
+ /*0x10ccb*/ 1257,
+ /*0x105a6*/ 1225,
/*0x13b7*/ 547,
/*0x0437*/ 299,
/*0x04b7*/ 379,
- /*0x1f11*/ 745,
- /*0x10437*/ 1145,
- /*0x024d*/ 197,
+ -1,
+ /*0x10437*/ 1150,
+ /*0x03ae*/ 244,
/*0x1e37*/ 640,
/*0x1eb7*/ 699,
/*0x0137*/ 82,
- /*0x2cb7*/ 931,
+ /*0x2cb7*/ 932,
+ /*0x2c49*/ 874,
+ -1,
+ /*0x10cc9*/ 1255,
-1,
- /*0xa745*/ 1050,
- /*0x0575*/ 460,
- /*0x13a2*/ 526,
/*0x13b5*/ 545,
/*0x0435*/ 297,
/*0x04b5*/ 378,
- /*0x01f5*/ 160,
- /*0x10435*/ 1143,
+ -1,
+ /*0x10435*/ 1148,
/*0x03b7*/ 252,
/*0x1e35*/ 639,
/*0x1eb5*/ 698,
/*0x0135*/ 81,
- /*0x2cb5*/ 930,
- /*0x10cc7*/ 1213,
- -1, -1,
- /*0x024b*/ 196,
+ /*0x2cb5*/ 931,
+ /*0xa641*/ 998,
-1,
- /*0x16e61*/ 1290,
+ /*0x1f41*/ 767,
-1, -1, -1,
+ /*0x01ed*/ 157,
+ /*0x0282*/ 225,
+ /*0x1fe1*/ 803,
/*0x03b5*/ 250,
- /*0xa64d*/ 1003,
- -1, -1,
- /*0x00eb*/ 36,
- /*0x10cc5*/ 1211,
- /*0x2c73*/ 902,
- /*0x118c9*/ 1266,
+ /*0x0481*/ 356,
+ /*0xa7c3*/ 1101,
+ /*0x1e926*/ 1365,
+ -1,
+ /*0x1e01*/ 613,
+ /*0x1e81*/ 677,
+ /*0x0101*/ 56,
+ /*0x2c81*/ 905,
+ /*0x118d3*/ 1316,
+ -1,
+ /*0x01a8*/ 130,
+ -1,
+ /*0x0511*/ 424,
+ /*0x16e6e*/ 1343,
+ /*0x13a5*/ 529,
+ /*0x0280*/ 224,
+ /*0x04a5*/ 370,
+ /*0x217a*/ 816,
+ /*0x118d5*/ 1318,
+ /*0x10cf1*/ 1295,
+ /*0x1e25*/ 631,
+ /*0x1ea5*/ 690,
+ /*0x0125*/ 74,
+ /*0x2ca5*/ 923,
+ /*0x10f1*/ 511,
+ /*0x1e05*/ 615,
+ /*0x1e85*/ 679,
+ /*0x0105*/ 58,
+ /*0x2c85*/ 907,
/*0x13b3*/ 543,
/*0x0433*/ 295,
/*0x04b3*/ 377,
- /*0x1e932*/ 1337,
- /*0x10433*/ 1141,
- -1,
+ /*0x1fe5*/ 804,
+ /*0x10433*/ 1146,
+ /*0xa7c1*/ 1100,
/*0x1e33*/ 638,
/*0x1eb3*/ 697,
/*0x0133*/ 80,
- /*0x2cb3*/ 929,
- -1,
- /*0x00ef*/ 40,
- /*0x16e63*/ 1292,
+ /*0x2cb3*/ 930,
+ /*0x2d16*/ 980,
+ /*0x024f*/ 198,
-1,
- /*0x2c3a*/ 859,
- /*0xa64b*/ 1002,
- /*0x13c0*/ 556,
- /*0x0440*/ 308,
- /*0xa73f*/ 1047,
+ /*0x2d1b*/ 985,
+ /*0x16e7a*/ 1355,
+ /*0x056d*/ 452,
+ /*0x10f5*/ 515,
+ /*0x00ed*/ 38,
+ /*0x2d0b*/ 969,
/*0x03b3*/ 248,
- /*0x10440*/ 1154,
+ /*0x118ce*/ 1311,
+ /*0x105a8*/ 1227,
+ /*0xa64f*/ 1005,
+ /*0x01f3*/ 159,
+ /*0xa737*/ 1044,
-1,
- /*0x16e65*/ 1294,
- /*0x2c55*/ 886,
- /*0x0140*/ 86,
- /*0x10ce6*/ 1244,
- /*0x01c9*/ 139,
+ /*0x16e6b*/ 1340,
-1, -1,
- /*0x1f43*/ 769,
- /*0x10e6*/ 500,
+ /*0x2d12*/ 976,
-1,
- /*0x16e69*/ 1298,
+ /*0x2d0a*/ 968,
-1,
- /*0x0292*/ 233,
- /*0x03c0*/ 261,
+ /*0x01ce*/ 141,
+ /*0x13a3*/ 527,
+ /*0x024d*/ 197,
+ /*0x04a3*/ 369,
-1,
- /*0xa643*/ 998,
- /*0x0371*/ 236,
- /*0x0479*/ 352,
- /*0x04f9*/ 412,
- /*0x0079*/ 23,
- /*0x16e67*/ 1296,
- /*0x104f9*/ 1203,
- /*0x1e79*/ 673,
- /*0x1ef9*/ 732,
- /*0xa737*/ 1043,
- /*0x0511*/ 424,
- /*0x118cd*/ 1270,
- /*0x1d79*/ 610,
- /*0x021d*/ 179,
- /*0x1f41*/ 767,
- -1, -1,
- /*0x2c4f*/ 880,
+ /*0xa735*/ 1043,
+ /*0x2d08*/ 966,
+ /*0x1e23*/ 630,
+ /*0x1ea3*/ 689,
+ /*0x0123*/ 73,
+ /*0x2ca3*/ 922,
+ /*0x118c3*/ 1300,
-1,
- /*0x10cec*/ 1250,
- -1, -1,
- /*0xa641*/ 997,
- /*0xa735*/ 1042,
- /*0x10ec*/ 506,
- /*0x2171*/ 807,
- /*0x00ed*/ 38,
+ /*0xa64d*/ 1004,
-1,
- /*0x0247*/ 194,
- /*0x1f24*/ 754,
/*0x13ad*/ 537,
- /*0x2c32*/ 851,
+ /*0x2c37*/ 856,
/*0x04ad*/ 374,
- /*0x118cb*/ 1268,
- /*0x1042d*/ 1135,
- /*0x2d1a*/ 983,
+ /*0x024b*/ 196,
+ /*0x1042d*/ 1140,
+ -1,
/*0x1e2d*/ 635,
/*0x1ead*/ 694,
/*0x012d*/ 78,
- /*0x2cad*/ 926,
- /*0x0373*/ 237,
+ /*0x2cad*/ 927,
+ /*0x1e928*/ 1367,
+ -1, -1, -1,
+ /*0xa64b*/ 1003,
+ /*0x2c35*/ 854,
-1,
- /*0x028c*/ 232,
- /*0x029e*/ 235,
- /*0x0288*/ 228,
- /*0x13a5*/ 529,
+ /*0x0249*/ 195,
-1,
- /*0x04a5*/ 370,
- /*0x0584*/ 475,
/*0x03ad*/ 243,
- /*0xa733*/ 1041,
- /*0x1e25*/ 631,
- /*0x1ea5*/ 690,
- /*0x0125*/ 74,
- /*0x2ca5*/ 922,
- /*0x118c3*/ 1260,
-1,
- /*0xa647*/ 1000,
- /*0x2c49*/ 874,
- /*0x13a3*/ 527,
- -1,
- /*0x04a3*/ 369,
- -1,
- /*0x1f45*/ 771,
- /*0x2173*/ 809,
- /*0x1e23*/ 630,
- /*0x1ea3*/ 689,
- /*0x0123*/ 73,
- /*0x2ca3*/ 921,
- /*0xff59*/ 1128,
- /*0x0266*/ 213,
- /*0xa645*/ 999,
- -1, -1,
- /*0x048f*/ 359,
- -1, -1,
- /*0x118c1*/ 1258,
- /*0x1e0f*/ 620,
- /*0x1e8f*/ 684,
- /*0x010f*/ 63,
- /*0x2c8f*/ 911,
- /*0xa69b*/ 1033,
- -1, -1, -1,
- /*0x1e943*/ 1354,
- /*0xa68b*/ 1025,
- -1, -1,
- /*0x023f*/ 191,
- /*0x1f66*/ 782,
+ /*0x2d24*/ 994,
+ /*0x2d22*/ 992,
+ /*0x0573*/ 458,
+ /*0xa725*/ 1036,
+ /*0x00f3*/ 44,
+ /*0x047b*/ 353,
+ /*0x04fb*/ 413,
+ /*0xa649*/ 1002,
+ /*0x118c1*/ 1298,
+ /*0x104fb*/ 1210,
+ /*0x1e7b*/ 674,
+ /*0x1efb*/ 733,
+ /*0x2d14*/ 978,
-1,
- /*0x10cc0*/ 1206,
+ /*0x057e*/ 469,
+ /*0x1f04*/ 740,
+ /*0x00fe*/ 54,
+ /*0x16e6f*/ 1344,
+ /*0xa733*/ 1042,
-1, -1,
- /*0x1fe1*/ 803,
+ /*0x2d10*/ 974,
-1,
- /*0x0481*/ 356,
- /*0x2d1c*/ 985,
+ /*0x03fb*/ 291,
+ /*0x2d18*/ 982,
+ /*0x13bf*/ 555,
+ /*0x043f*/ 307,
+ /*0x04bf*/ 383,
-1,
- /*0x026c*/ 218,
- /*0x1e01*/ 613,
- /*0x1e81*/ 677,
- /*0x0101*/ 56,
- /*0x2c81*/ 904,
+ /*0x1043f*/ 1158,
-1,
- /*0x2c4d*/ 878,
- /*0x1e941*/ 1352,
- /*0x0280*/ 224,
- /*0x16e6b*/ 1300,
- /*0x2175*/ 811,
- /*0x118c7*/ 1264,
- /*0x0282*/ 225,
- -1, -1, -1,
- /*0xa72d*/ 1039,
+ /*0x1e3f*/ 644,
+ /*0x1ebf*/ 703,
-1,
- /*0x051d*/ 430,
- /*0x10f9*/ 519,
- -1, -1,
- /*0x1e924*/ 1323,
+ /*0x2cbf*/ 936,
+ /*0x118de*/ 1327,
-1,
- /*0x16e6f*/ 1304,
- /*0x118c5*/ 1262,
- /*0x00f1*/ 42,
- -1,
- /*0x2c4b*/ 876,
- /*0x1fe5*/ 804,
+ /*0x0271*/ 220,
+ /*0x2d06*/ 964,
-1,
- /*0xa725*/ 1035,
+ /*0x037b*/ 239,
+ -1, -1,
+ /*0x2c33*/ 852,
+ /*0x03bf*/ 260,
+ /*0x13b2*/ 542,
+ /*0x0432*/ 294,
+ /*0x2d1a*/ 984,
+ /*0x2d0c*/ 970,
+ /*0x10432*/ 1145,
+ /*0x1f71*/ 785,
+ /*0x105aa*/ 1229,
+ /*0xa723*/ 1035,
+ /*0x13b9*/ 549,
+ /*0x0439*/ 301,
+ /*0x04b9*/ 380,
-1,
- /*0x13a7*/ 531,
+ /*0x10439*/ 1152,
+ /*0x0275*/ 222,
+ /*0x1e39*/ 641,
+ /*0x1eb9*/ 700,
-1,
- /*0x04a7*/ 371,
+ /*0x2cb9*/ 933,
-1,
- /*0x2d04*/ 961,
- /*0x1f37*/ 765,
- /*0x1e27*/ 632,
- /*0x1ea7*/ 691,
- /*0x0127*/ 75,
- /*0x2ca7*/ 923,
+ /*0x03b2*/ 247,
+ /*0x1e943*/ 1394,
+ /*0xa72d*/ 1040,
-1, -1,
- /*0xa723*/ 1034,
+ /*0x118cf*/ 1312,
-1,
- /*0x2d11*/ 974,
+ /*0x1f75*/ 789,
+ /*0x03b9*/ 254,
-1, -1,
- /*0x2c43*/ 868,
- /*0x1f22*/ 752,
- /*0x1f35*/ 763,
- /*0x00ee*/ 39,
- -1,
- /*0x047b*/ 353,
- /*0x04fb*/ 413,
- -1,
- /*0x0233*/ 189,
- /*0x104fb*/ 1205,
- /*0x1e7b*/ 674,
- /*0x1efb*/ 733,
+ /*0x13ac*/ 536,
/*0x13b1*/ 541,
/*0x0431*/ 293,
/*0x04b1*/ 376,
- /*0x00f3*/ 44,
- /*0x10431*/ 1139,
+ /*0x1042c*/ 1139,
+ /*0x10431*/ 1144,
-1,
/*0x1e31*/ 637,
/*0x1eb1*/ 696,
-1,
- /*0x2cb1*/ 928,
- /*0x2c41*/ 866,
- /*0x03fb*/ 291,
- /*0x0240*/ 192,
- /*0x0566*/ 445,
- /*0x16e6d*/ 1302,
- /*0x047d*/ 354,
- /*0x04fd*/ 414,
- /*0x1f33*/ 761,
- -1,
- /*0x03b1*/ 246,
- /*0x1e7d*/ 675,
- /*0x1efd*/ 734,
- /*0xff57*/ 1126,
- /*0x047f*/ 355,
- /*0x04ff*/ 415,
- /*0x1d7d*/ 611,
- -1, -1,
- /*0x1e7f*/ 676,
- /*0x1eff*/ 735,
- /*0x13bd*/ 553,
- /*0x043d*/ 305,
- /*0x04bd*/ 382,
- /*0x1f40*/ 766,
- /*0x1043d*/ 1151,
- /*0xa791*/ 1080,
- /*0x1e3d*/ 643,
- /*0x1ebd*/ 702,
- /*0x01bf*/ 137,
- /*0x2cbd*/ 934,
+ /*0x2cb1*/ 929,
-1, -1,
- /*0x1e93f*/ 1350,
- -1,
- /*0x056c*/ 451,
- /*0x2c47*/ 872,
+ /*0x1e92a*/ 1369,
+ /*0x2d20*/ 990,
-1, -1, -1,
- /*0x03bd*/ 258,
- /*0x00f5*/ 46,
+ /*0x118cd*/ 1310,
+ /*0x03ac*/ 242,
+ /*0x03b1*/ 246,
-1,
- /*0x007a*/ 24,
+ /*0x13a7*/ 531,
+ /*0x1e941*/ 1392,
+ /*0x04a7*/ 371,
-1,
- /*0x104fa*/ 1204,
- /*0x1f79*/ 793,
+ /*0x2d1e*/ 988,
-1,
- /*0x017a*/ 114,
- /*0xa727*/ 1036,
- /*0x2c45*/ 870,
- /*0x13b9*/ 549,
- /*0x0439*/ 301,
- /*0x04b9*/ 380,
- /*0x022d*/ 186,
- /*0x10439*/ 1147,
+ /*0x1e27*/ 632,
+ /*0x1ea7*/ 691,
+ /*0x0127*/ 75,
+ /*0x2ca7*/ 924,
+ -1, -1,
+ /*0x118cb*/ 1308,
-1,
- /*0x1e39*/ 641,
- /*0x1eb9*/ 700,
+ /*0x1f37*/ 765,
+ /*0xa73f*/ 1048,
-1,
- /*0x2cb9*/ 932,
- /*0x1e937*/ 1342,
+ /*0x16e6d*/ 1342,
+ -1, -1, -1, -1, -1,
+ /*0x13c7*/ 563,
+ /*0x0447*/ 315,
-1,
- /*0x13c2*/ 558,
- /*0x0442*/ 310,
- /*0x04c2*/ 384,
+ /*0x118c9*/ 1306,
+ /*0x10447*/ 1166,
+ /*0x1f35*/ 763,
+ /*0x1e47*/ 648,
+ /*0x1ec7*/ 707,
-1,
- /*0x10442*/ 1156,
+ /*0x2cc7*/ 940,
+ /*0x0201*/ 165,
+ -1, -1, -1, -1, -1,
+ /*0x01c9*/ 139,
+ /*0x2c3f*/ 864,
+ -1,
+ /*0x03c7*/ 267,
+ /*0xa739*/ 1045,
+ -1, -1,
+ /*0x1f01*/ 737,
+ /*0x2173*/ 809,
-1,
/*0x0225*/ 182,
- /*0x03b9*/ 254,
- /*0x0142*/ 87,
- /*0x13d0*/ 572,
- /*0x0450*/ 324,
- /*0x1e922*/ 1321,
- /*0x1e935*/ 1340,
- /*0x13f2*/ 606,
- /*0x017e*/ 116,
- /*0x2c66*/ 898,
- /*0x0072*/ 16,
- /*0x2d24*/ 993,
- /*0x104f2*/ 1196,
+ -1, -1,
+ /*0x1fd1*/ 801,
-1,
- /*0x0223*/ 181,
+ /*0x0205*/ 167,
-1,
- /*0x2d1d*/ 986,
- /*0x24d0*/ 823,
- /*0x118c0*/ 1257,
- /*0xff51*/ 1120,
+ /*0xa7b7*/ 1095,
+ /*0x214e*/ 805,
+ -1,
+ /*0x217e*/ 820,
+ /*0x2c32*/ 851,
-1,
/*0x1f25*/ 755,
+ /*0x2d02*/ 960,
+ /*0x0233*/ 189,
+ /*0x13c5*/ 561,
+ /*0x0445*/ 313,
+ /*0x1f05*/ 741,
+ /*0x2c39*/ 858,
+ /*0x10445*/ 1164,
+ /*0xa7b5*/ 1094,
+ /*0x1e45*/ 647,
+ /*0x1ec5*/ 706,
+ /*0x16e73*/ 1348,
+ /*0x2cc5*/ 939,
+ -1, -1,
+ /*0x1f33*/ 761,
+ /*0x2d0e*/ 972,
-1, -1,
- /*0xa7c3*/ 1099,
+ /*0x2d00*/ 958,
+ /*0x0584*/ 475,
-1,
- /*0x03f2*/ 288,
- /*0x020f*/ 172,
+ /*0x03c5*/ 265,
+ /*0x16e7e*/ 1359,
-1,
- /*0x2c3f*/ 864,
+ /*0xa727*/ 1037,
+ /*0xa781*/ 1076,
+ /*0x13c0*/ 556,
+ /*0x0440*/ 308,
+ /*0x2c31*/ 850,
-1,
- /*0xa77f*/ 1074,
+ /*0x10440*/ 1159,
+ /*0x047d*/ 354,
+ /*0x04fd*/ 414,
-1,
- /*0x1e933*/ 1338,
- /*0xff53*/ 1122,
+ /*0x0140*/ 86,
+ /*0x0223*/ 181,
+ /*0x1e7d*/ 675,
+ /*0x1efd*/ 734,
+ /*0x01f5*/ 160,
+ /*0x1d7d*/ 611,
+ -1,
+ /*0xa7a5*/ 1091,
+ -1, -1, -1,
+ /*0x03c0*/ 261,
+ /*0xa785*/ 1078,
+ /*0xa747*/ 1052,
/*0x1f23*/ 753,
+ /*0x022d*/ 186,
+ /*0x1e03*/ 614,
+ /*0x1e83*/ 678,
+ /*0x0103*/ 57,
+ /*0x2c83*/ 906,
+ -1, -1,
+ /*0x048f*/ 359,
+ -1, -1,
+ /*0x2d11*/ 975,
+ /*0x1e0f*/ 620,
+ /*0x1e8f*/ 684,
+ /*0x010f*/ 63,
+ /*0x2c8f*/ 912,
+ /*0xa69b*/ 1034,
+ /*0x0571*/ 456,
+ /*0x037d*/ 241,
+ /*0x00f1*/ 42,
+ -1,
+ /*0xa68b*/ 1026,
+ -1, -1,
+ /*0x2c47*/ 872,
+ -1,
+ /*0x10cc7*/ 1253,
+ /*0x13bd*/ 553,
+ /*0x043d*/ 305,
+ /*0x04bd*/ 382,
-1,
- /*0x16e71*/ 1306,
+ /*0x1043d*/ 1156,
+ -1,
+ /*0x1e3d*/ 643,
+ /*0x1ebd*/ 702,
+ -1,
+ /*0x2cbd*/ 935,
+ -1,
+ /*0x0575*/ 460,
+ /*0x1f7b*/ 795,
+ /*0x00f5*/ 46,
+ /*0xa745*/ 1051,
+ /*0xa7a3*/ 1090,
+ /*0x13a1*/ 525,
-1,
- /*0xa73d*/ 1046,
- /*0x2c6c*/ 901,
+ /*0x04a1*/ 368,
+ /*0x03bd*/ 258,
+ /*0x023f*/ 191,
+ /*0xff59*/ 1133,
+ /*0x1e21*/ 629,
+ /*0x1ea1*/ 688,
+ /*0x0121*/ 72,
+ /*0x2ca1*/ 921,
/*0x13bb*/ 551,
/*0x043b*/ 303,
/*0x04bb*/ 381,
- -1,
- /*0x1043b*/ 1149,
+ /*0x105ae*/ 1233,
+ /*0x1043b*/ 1154,
-1,
/*0x1e3b*/ 642,
/*0x1ebb*/ 701,
- /*0x1e940*/ 1351,
- /*0x2cbb*/ 933,
- /*0x0201*/ 165,
+ -1,
+ /*0x2cbb*/ 934,
-1, -1, -1,
- /*0x10fd*/ 521,
+ /*0x2c45*/ 870,
+ /*0x13af*/ 539,
+ /*0x10cc5*/ 1251,
+ /*0x04af*/ 375,
+ /*0x105b7*/ 1241,
+ /*0x1042f*/ 1142,
+ /*0x03bb*/ 256,
+ /*0x1e2f*/ 636,
+ /*0x1eaf*/ 695,
+ /*0x012f*/ 79,
+ /*0x2caf*/ 928,
-1,
- /*0x2c37*/ 856,
- /*0xa77a*/ 1072,
+ /*0x01a5*/ 129,
-1,
- /*0x03bb*/ 256,
+ /*0x1f32*/ 760,
+ /*0x0499*/ 364,
-1,
- /*0x0579*/ 464,
- /*0x10ff*/ 523,
- /*0x16e6e*/ 1303,
+ /*0x0185*/ 119,
+ /*0x105b5*/ 1239,
+ /*0x1e19*/ 625,
+ /*0x03af*/ 245,
+ /*0x0119*/ 68,
+ /*0x2c99*/ 917,
-1,
- /*0xa79d*/ 1086,
- /*0x01f9*/ 161,
+ /*0x2c40*/ 865,
+ /*0x13e6*/ 594,
+ /*0x10cc0*/ 1246,
+ /*0x1e92e*/ 1373,
+ /*0x0066*/ 5,
-1,
- /*0xa739*/ 1044,
+ /*0x104e6*/ 1189,
-1,
- /*0x2c35*/ 854,
- /*0x1f01*/ 737,
- /*0x13af*/ 539,
+ /*0x0231*/ 188,
+ /*0x0581*/ 472,
-1,
- /*0x04af*/ 375,
- /*0x16e73*/ 1308,
- /*0x1042f*/ 1137,
+ /*0x10fd*/ 521,
+ /*0xa7bf*/ 1099,
+ /*0x13f2*/ 606,
-1,
- /*0x1e2f*/ 636,
- /*0x1eaf*/ 695,
- /*0x012f*/ 79,
- /*0x2caf*/ 927,
+ /*0x24e6*/ 845,
+ /*0x0072*/ 16,
+ /*0x1e937*/ 1382,
+ /*0x104f2*/ 1201,
+ -1,
+ /*0x0501*/ 416,
+ /*0x1f31*/ 759,
-1, -1,
- /*0x1e05*/ 615,
- /*0x1e85*/ 679,
- /*0x0105*/ 58,
- /*0x2c85*/ 906,
+ /*0xa73d*/ 1047,
+ -1, -1, -1,
+ /*0x105a5*/ 1224,
/*0x0227*/ 183,
- /*0x10fa*/ 520,
- /*0x052d*/ 438,
- /*0x03af*/ 245,
+ /*0x0585*/ 476,
+ /*0x1e935*/ 1380,
+ /*0x03f2*/ 288,
+ -1, -1, -1,
+ /*0x0525*/ 434,
+ /*0x01a3*/ 128,
-1, -1,
- /*0x13a9*/ 533,
+ /*0xa7b9*/ 1096,
+ /*0x0505*/ 418,
+ /*0x1f27*/ 757,
+ /*0x105b3*/ 1237,
+ -1, -1, -1,
+ /*0x1059c*/ 1216,
+ -1,
+ /*0x2c3d*/ 862,
+ /*0xa73b*/ 1046,
/*0x01ad*/ 131,
+ /*0x0247*/ 194,
+ /*0x13a9*/ 533,
+ -1,
/*0x04a9*/ 372,
- /*0x2c33*/ 852,
- /*0x10429*/ 1131,
- /*0x1e92d*/ 1332,
+ -1,
+ /*0x10429*/ 1136,
+ -1,
/*0x1e29*/ 633,
/*0x1ea9*/ 692,
/*0x0129*/ 76,
- /*0x2ca9*/ 924,
- -1,
- /*0x0525*/ 434,
- -1,
- /*0x10cc2*/ 1208,
+ /*0x2ca9*/ 925,
+ /*0xa647*/ 1001,
+ /*0xa72f*/ 1041,
+ /*0x1e925*/ 1364,
+ /*0x0479*/ 352,
+ /*0x04f9*/ 412,
+ /*0x0079*/ 23,
+ /*0x2171*/ 807,
+ /*0x104f9*/ 1208,
+ /*0x1e79*/ 673,
+ /*0x1ef9*/ 732,
-1,
- /*0x1f27*/ 757,
- /*0x01a5*/ 129,
+ /*0x1d79*/ 610,
+ /*0x2c3b*/ 860,
+ /*0x01fb*/ 162,
+ /*0x105a3*/ 1222,
-1, -1,
- /*0x2c40*/ 865,
- /*0x1e925*/ 1324,
+ /*0x1e933*/ 1378,
-1,
- /*0x10cd0*/ 1222,
- /*0x0231*/ 188,
- /*0x10fe*/ 522,
+ /*0xff57*/ 1131,
+ -1,
+ /*0xa7a7*/ 1092,
/*0x0523*/ 433,
- /*0x10cf2*/ 1256,
- /*0x10d0*/ 478,
- /*0x16e75*/ 1310,
+ -1, -1, -1, -1,
+ /*0x2175*/ 811,
+ /*0x105ad*/ 1232,
+ /*0x13d0*/ 572,
+ /*0x0450*/ 324,
-1,
- /*0x01a3*/ 128,
- /*0x10f2*/ 512,
+ /*0x16e71*/ 1346,
+ -1,
+ /*0x01bf*/ 137,
+ -1,
+ /*0x052d*/ 438,
+ /*0x13c2*/ 558,
+ /*0x0442*/ 310,
+ /*0x04c2*/ 384,
+ -1,
+ /*0x10442*/ 1161,
+ /*0xa645*/ 1000,
+ /*0x24d0*/ 823,
+ /*0x1f45*/ 771,
+ /*0x0142*/ 87,
+ /*0x1e09*/ 617,
+ /*0x1e89*/ 681,
+ /*0x0109*/ 60,
+ /*0x2c89*/ 909,
+ /*0x2c66*/ 899,
+ /*0x1e923*/ 1362,
+ /*0x10ce6*/ 1284,
+ /*0x16e75*/ 1350,
+ -1,
+ /*0x0240*/ 192,
+ -1,
+ /*0x10e6*/ 500,
-1,
- /*0xa73b*/ 1045,
- /*0x1e923*/ 1322,
- /*0x1fd1*/ 801,
- /*0x1f7b*/ 795,
/*0x027d*/ 223,
- /*0x050f*/ 423,
- /*0x2d22*/ 991,
- /*0xff55*/ 1124,
- /*0x13ce*/ 570,
- /*0x044e*/ 322,
- /*0x04ce*/ 390,
- /*0x1f31*/ 759,
- /*0x1044e*/ 1168,
+ -1,
+ /*0x057b*/ 466,
+ /*0x01b9*/ 135,
+ /*0x00fb*/ 51,
+ /*0x10cf2*/ 1296,
+ /*0x1e92d*/ 1372,
+ -1, -1,
+ /*0x1f40*/ 766,
+ /*0x10f2*/ 512,
+ -1, -1,
+ /*0x1f7d*/ 797,
+ /*0x0203*/ 166,
+ -1,
+ /*0xff51*/ 1125,
+ -1,
+ /*0xa729*/ 1038,
+ -1,
+ /*0x047f*/ 355,
+ /*0x04ff*/ 415,
-1, -1,
- /*0xa7bf*/ 1098,
+ /*0x020f*/ 172,
+ /*0x1e7f*/ 676,
+ /*0x1eff*/ 735,
+ /*0x1f03*/ 739,
/*0x0477*/ 351,
/*0x04f7*/ 411,
/*0x0077*/ 21,
-1,
- /*0x104f7*/ 1201,
+ /*0x104f7*/ 1206,
/*0x1e77*/ 672,
/*0x1ef7*/ 731,
/*0x0177*/ 113,
+ /*0x13ec*/ 600,
+ -1, -1,
+ /*0x006c*/ 10,
-1,
- /*0x1f7d*/ 797,
+ /*0x104ec*/ 1195,
+ /*0x13ab*/ 535,
+ /*0x105b9*/ 1243,
+ /*0x04ab*/ 373,
+ /*0x2cec*/ 955,
+ /*0x1042b*/ 1138,
-1,
- /*0x03ce*/ 274,
+ /*0x1e2b*/ 634,
+ /*0x1eab*/ 693,
+ /*0x012b*/ 77,
+ /*0x2cab*/ 926,
+ /*0x1e93f*/ 1390,
+ /*0x13e8*/ 596,
+ -1, -1,
+ /*0x0068*/ 7,
+ /*0x118c7*/ 1304,
+ /*0x104e8*/ 1191,
+ -1, -1,
+ /*0x2184*/ 822,
+ /*0x10f9*/ 519,
+ /*0x0377*/ 238,
-1,
- /*0x0501*/ 416,
+ /*0x105ac*/ 1231,
+ /*0x105b1*/ 1236,
+ /*0x24e8*/ 847,
+ /*0x13ea*/ 598,
+ /*0xa783*/ 1077,
+ -1,
+ /*0x006a*/ 8,
+ /*0x1e932*/ 1377,
+ /*0x104ea*/ 1193,
+ /*0x1f21*/ 751,
+ /*0x2d04*/ 962,
+ -1, -1, -1,
+ /*0xa691*/ 1029,
+ /*0x1e939*/ 1384,
+ -1,
+ /*0x2c50*/ 881,
+ -1,
+ /*0x10cd0*/ 1262,
+ /*0x022f*/ 187,
+ -1,
+ /*0x105a7*/ 1226,
+ -1,
+ /*0x10d0*/ 478,
+ /*0x2c42*/ 867,
+ /*0x13f0*/ 604,
+ /*0x10cc2*/ 1248,
+ -1,
+ /*0x0070*/ 14,
+ /*0x0527*/ 435,
+ /*0x104f0*/ 1199,
+ /*0x0219*/ 177,
+ -1,
+ /*0x118c5*/ 1302,
+ /*0xa7bd*/ 1098,
+ -1,
+ /*0x1e92c*/ 1371,
+ /*0x1e931*/ 1376,
-1, -1,
- /*0xa72f*/ 1040,
- /*0x1e03*/ 614,
- /*0x1e83*/ 678,
- /*0x0103*/ 57,
- /*0x2c83*/ 905,
- /*0x13e8*/ 596,
- /*0xff4f*/ 1118,
+ /*0xa77f*/ 1075,
-1,
- /*0x0068*/ 7,
+ /*0xff53*/ 1127,
+ /*0x0266*/ 213,
-1,
- /*0x104e8*/ 1186,
- /*0xa7b7*/ 1094,
/*0x13c8*/ 564,
/*0x0448*/ 316,
/*0x04c8*/ 387,
-1,
- /*0x10448*/ 1162,
+ /*0x10448*/ 1167,
+ /*0xa7a1*/ 1089,
-1,
- /*0x13ea*/ 598,
- /*0x24e8*/ 847,
+ /*0xff55*/ 1129,
/*0x0148*/ 90,
- /*0x006a*/ 8,
- /*0xa729*/ 1037,
- /*0x104ea*/ 1188,
-1,
- /*0xa7b5*/ 1093,
- -1, -1,
- /*0x1f7a*/ 794,
- -1,
- /*0x0242*/ 193,
- /*0x03c8*/ 268,
- -1, -1,
- /*0x0499*/ 364,
- /*0x0527*/ 435,
- -1, -1,
- /*0x1e19*/ 625,
- /*0x0250*/ 199,
- /*0x0119*/ 68,
- /*0x2c99*/ 916,
- /*0x017c*/ 115,
/*0x0272*/ 221,
- /*0x1e927*/ 1326,
- /*0x0581*/ 472,
+ /*0x1f66*/ 782,
+ /*0x118c0*/ 1297,
+ /*0x1e927*/ 1366,
-1,
- /*0xff49*/ 1112,
+ /*0xa7bb*/ 1097,
-1, -1,
+ /*0xa72b*/ 1039,
+ /*0x03c8*/ 268,
/*0x0076*/ 20,
- /*0x1f42*/ 768,
- /*0x104f6*/ 1200,
-1,
- /*0x00e6*/ 31,
+ /*0x104f6*/ 1205,
+ /*0x1f72*/ 786,
+ -1, -1, -1,
+ /*0x10ff*/ 523,
-1,
- /*0x057b*/ 466,
+ /*0x01fd*/ 163,
-1,
- /*0x13c4*/ 560,
- /*0x0444*/ 312,
- /*0x04c4*/ 385,
- /*0x01fb*/ 162,
- /*0x10444*/ 1158,
+ /*0x13e4*/ 592,
-1,
- /*0x1f72*/ 786,
+ /*0x217b*/ 817,
+ /*0x0064*/ 3,
+ /*0x10f7*/ 517,
+ /*0x104e4*/ 1187,
+ /*0x2c6c*/ 902,
+ /*0xff4e*/ 1122,
+ /*0x10cec*/ 1290,
-1,
- /*0x0144*/ 88,
- -1, -1,
- /*0x2d2d*/ 996,
- -1, -1, -1,
- /*0x1e931*/ 1336,
- -1, -1, -1,
- /*0x03c4*/ 264,
- /*0x057d*/ 468,
- /*0x2179*/ 815,
+ /*0xa799*/ 1085,
+ /*0x0495*/ 362,
+ /*0x0183*/ 118,
+ /*0x10ec*/ 506,
+ /*0x24e4*/ 843,
+ /*0x1e15*/ 623,
+ /*0x1e95*/ 687,
+ /*0x0115*/ 66,
+ /*0x2c95*/ 915,
+ /*0x0229*/ 184,
-1, -1, -1,
- /*0x01fd*/ 163,
- /*0x2d25*/ 994,
- /*0x00ec*/ 37,
- /*0x057f*/ 470,
+ /*0x2c68*/ 900,
+ -1,
+ /*0x10ce8*/ 1286,
-1, -1,
- /*0x029d*/ 234,
- /*0x10cce*/ 1220,
- /*0x01ff*/ 164,
+ /*0x16e7b*/ 1356,
+ -1,
+ /*0x10e8*/ 502,
+ /*0xff43*/ 1111,
-1,
/*0x13c6*/ 562,
/*0x0446*/ 314,
/*0x04c6*/ 386,
- /*0xff4d*/ 1116,
- /*0x10446*/ 1160,
- /*0x2d23*/ 992,
- /*0x01bd*/ 136,
-1,
+ /*0x10446*/ 1165,
+ /*0x2c6a*/ 901,
+ -1,
+ /*0x10cea*/ 1288,
/*0x0146*/ 89,
- /*0x10f7*/ 517,
- /*0x1e93d*/ 1348,
-1,
- /*0x1e07*/ 616,
- /*0x1e87*/ 680,
- /*0x0107*/ 59,
- /*0x2c87*/ 907,
- /*0x022f*/ 187,
+ /*0x01bd*/ 136,
+ /*0x1f79*/ 793,
+ /*0x10ea*/ 504,
+ /*0x057d*/ 468,
-1,
- /*0x2d0f*/ 972,
- /*0x03c6*/ 266,
- /*0x057a*/ 465,
- /*0x118c2*/ 1259,
- /*0x0205*/ 167,
- -1, -1,
- /*0xff4b*/ 1114,
- /*0x10ce8*/ 1246,
+ /*0x00fd*/ 53,
+ /*0x0583*/ 474,
+ /*0x0493*/ 361,
-1,
- /*0xa77c*/ 1073,
+ /*0x03c6*/ 266,
-1,
- /*0x118d0*/ 1273,
- /*0x10e8*/ 502,
+ /*0x1e13*/ 622,
+ /*0x1e93*/ 686,
+ /*0x0113*/ 65,
+ /*0x2c93*/ 914,
+ /*0x0250*/ 199,
+ /*0x01a1*/ 127,
+ /*0x0503*/ 417,
+ /*0x2d01*/ 959,
+ /*0x13e0*/ 588,
+ /*0x10cf0*/ 1294,
+ /*0xff41*/ 1109,
-1,
- /*0x10cc8*/ 1214,
+ /*0x0242*/ 193,
+ /*0x104e0*/ 1183,
+ /*0x10f0*/ 510,
+ /*0x0209*/ 169,
+ /*0x050f*/ 423,
+ /*0x1e940*/ 1391,
-1, -1,
- /*0x01b9*/ 135,
+ /*0xa7a9*/ 1093,
-1,
- /*0x0229*/ 184,
- /*0x10cea*/ 1248,
- /*0x1e939*/ 1344,
- /*0xa7a5*/ 1090,
- /*0x2d01*/ 958,
- /*0x1f05*/ 741,
- /*0x10ea*/ 504,
- /*0x2c31*/ 850,
+ /*0x24e0*/ 839,
+ /*0x2d25*/ 995,
-1,
- /*0xff43*/ 1106,
+ /*0x1f42*/ 768,
-1,
- /*0x057e*/ 469,
- -1, -1,
- /*0x1e942*/ 1353,
- -1, -1,
- /*0xa7a3*/ 1089,
- /*0x0572*/ 457,
- /*0x01d0*/ 142,
- /*0x13a1*/ 525,
+ /*0x2c48*/ 873,
+ /*0x2d05*/ 963,
+ /*0x10cc8*/ 1254,
+ /*0x1e07*/ 616,
+ /*0x1e87*/ 680,
+ /*0x0107*/ 59,
+ /*0x2c87*/ 908,
-1,
- /*0x04a1*/ 368,
- -1, -1, -1,
- /*0x1e21*/ 629,
- /*0x1ea1*/ 688,
- /*0x0121*/ 72,
- /*0x2ca1*/ 920,
- /*0xa691*/ 1028,
- /*0xff41*/ 1104,
- -1, -1, -1,
- /*0x10f6*/ 516,
+ /*0x13c4*/ 560,
+ /*0x0444*/ 312,
+ /*0x04c4*/ 385,
-1,
- /*0x2c3d*/ 862,
+ /*0x10444*/ 1163,
-1,
- /*0x0495*/ 362,
+ /*0x0199*/ 124,
+ /*0x2d1c*/ 986,
+ /*0x0144*/ 88,
+ /*0x2c76*/ 904,
+ /*0x105a1*/ 1221,
+ -1, -1, -1, -1,
+ /*0x0283*/ 226,
+ /*0x10f6*/ 516,
+ /*0x0497*/ 363,
+ /*0x0521*/ 432,
+ /*0x03c4*/ 264,
+ /*0x105bb*/ 1244,
+ /*0x1e17*/ 624,
+ /*0x049d*/ 366,
+ /*0x0117*/ 67,
+ /*0x2c97*/ 916,
+ /*0x10ce4*/ 1282,
+ /*0x1e1d*/ 627,
-1,
- /*0x10cc4*/ 1210,
- /*0x2d27*/ 995,
- /*0x1e15*/ 623,
- /*0x1e95*/ 687,
- /*0x0115*/ 66,
- /*0x2c95*/ 914,
+ /*0x011d*/ 70,
+ /*0x2c9d*/ 919,
+ /*0x10e4*/ 498,
+ /*0x1e93d*/ 1388,
-1, -1,
- /*0x13ab*/ 535,
- /*0x00f9*/ 49,
- /*0x04ab*/ 373,
- -1,
- /*0x1042b*/ 1133,
- /*0xa781*/ 1075,
- /*0x1e2b*/ 634,
- /*0x1eab*/ 693,
- /*0x012b*/ 77,
- /*0x2cab*/ 925,
- /*0x13f0*/ 604,
- /*0x0203*/ 166,
- /*0x1e93b*/ 1346,
- /*0x0070*/ 14,
- -1,
- /*0x104f0*/ 1194,
+ /*0x105af*/ 1234,
+ /*0x026c*/ 218,
+ /*0xff4f*/ 1123,
+ /*0x2d23*/ 993,
-1,
- /*0xff47*/ 1110,
- /*0x2c39*/ 858,
- /*0x13e4*/ 592,
/*0x1f77*/ 791,
- /*0x0268*/ 214,
- /*0x0064*/ 3,
- /*0x13e2*/ 590,
- /*0x104e4*/ 1182,
- /*0x16e66*/ 1295,
- /*0x0062*/ 1,
- /*0x10cc6*/ 1212,
- /*0x104e2*/ 1180,
- /*0x037b*/ 239,
- /*0x2c42*/ 867,
- /*0xff45*/ 1108,
- /*0x1f03*/ 739,
- /*0x24e4*/ 843,
- /*0x026a*/ 216,
- /*0x052f*/ 439,
-1,
- /*0x24e2*/ 841,
+ /*0x022b*/ 185,
+ /*0x052f*/ 439,
+ -1, -1,
+ /*0x13e2*/ 590,
+ /*0x10599*/ 1213,
-1,
- /*0x2c50*/ 881,
+ /*0x0062*/ 1,
-1,
- /*0x0505*/ 418,
- /*0x13f4*/ 608,
- /*0xa7a7*/ 1091,
- /*0x1e92f*/ 1334,
- /*0x0074*/ 18,
- /*0x0185*/ 119,
- /*0x104f4*/ 1198,
- /*0x0219*/ 177,
- /*0x13da*/ 582,
- /*0x045a*/ 334,
- /*0x037d*/ 241,
+ /*0x104e2*/ 1185,
+ /*0x2d2d*/ 997,
+ /*0x0268*/ 214,
-1,
- /*0x217b*/ 817,
- /*0x104da*/ 1172,
- /*0x0493*/ 361,
- /*0x16e6c*/ 1301,
- /*0x0529*/ 436,
+ /*0x0519*/ 428,
-1,
- /*0x1e13*/ 622,
- /*0x1e93*/ 686,
- /*0x0113*/ 65,
- /*0x2c93*/ 913,
- /*0x24da*/ 833,
- /*0x13e0*/ 588,
+ /*0x2c46*/ 871,
+ /*0x1e93b*/ 1386,
+ /*0x10cc6*/ 1252,
+ /*0x24e2*/ 841,
+ /*0xff4d*/ 1121,
+ /*0x13d6*/ 578,
+ /*0x0456*/ 330,
+ /*0x0078*/ 22,
-1,
- /*0x1e929*/ 1328,
+ /*0x104f8*/ 1207,
+ /*0x0566*/ 445,
+ /*0x026a*/ 216,
+ /*0x00e6*/ 31,
/*0x13dc*/ 584,
/*0x045c*/ 336,
- /*0x104e0*/ 1178,
+ /*0x1e92f*/ 1374,
+ /*0x13da*/ 582,
+ /*0x045a*/ 334,
+ /*0x104dc*/ 1179,
+ /*0x24d6*/ 829,
+ /*0xff4b*/ 1119,
+ /*0x104da*/ 1177,
+ /*0x0572*/ 457,
+ /*0x03f8*/ 290,
+ /*0x00f2*/ 43,
-1,
- /*0x1f7c*/ 796,
- /*0x104dc*/ 1174,
- -1, -1,
- /*0x217d*/ 819,
- /*0x118ce*/ 1271,
- /*0x2c3b*/ 860,
- /*0x24e0*/ 839,
- -1, -1,
+ /*0x01f9*/ 161,
/*0x24dc*/ 835,
- -1,
- /*0x217f*/ 821,
- /*0x1f76*/ 790,
-1, -1,
- /*0xa72b*/ 1038,
+ /*0x24da*/ 833,
+ /*0x10ce0*/ 1278,
+ -1, -1,
+ /*0xff49*/ 1117,
-1,
- /*0x0585*/ 476,
- /*0x13d6*/ 578,
- /*0x0456*/ 330,
+ /*0x10e0*/ 494,
-1, -1, -1,
- /*0x1f44*/ 770,
+ /*0x118d0*/ 1313,
+ /*0x13bc*/ 552,
+ /*0x043c*/ 304,
+ /*0x217d*/ 819,
-1,
- /*0x13d4*/ 576,
- /*0x0454*/ 328,
- -1, -1, -1,
- /*0xa7bd*/ 1097,
- /*0x01ce*/ 141,
- /*0x24d6*/ 829,
- /*0x0577*/ 462,
- -1, -1, -1, -1,
- /*0x217a*/ 816,
- /*0x24d4*/ 827,
- /*0x118c8*/ 1265,
- -1, -1,
- /*0x0207*/ 168,
+ /*0x1043c*/ 1155,
-1,
- /*0x0503*/ 417,
+ /*0x1f70*/ 784,
+ /*0x118c2*/ 1299,
+ /*0x013c*/ 84,
+ /*0x017c*/ 115,
-1, -1,
- /*0x13d8*/ 580,
- /*0x0458*/ 332,
- /*0x0183*/ 118,
+ /*0x01d0*/ 142,
+ /*0x105a9*/ 1228,
-1,
- /*0x10cf0*/ 1254,
- /*0x104d8*/ 1170,
+ /*0x2c44*/ 869,
+ /*0x1fb1*/ 799,
+ /*0x10cc4*/ 1250,
-1,
- /*0x0568*/ 447,
+ /*0x03bc*/ 257,
-1,
- /*0x10f0*/ 510,
- -1, -1,
- /*0xa7b9*/ 1095,
- /*0x10ce4*/ 1242,
+ /*0x0529*/ 436,
+ /*0x13d8*/ 580,
+ /*0x0458*/ 332,
+ -1, -1, -1,
+ /*0x104d8*/ 1175,
+ /*0x16e7d*/ 1358,
+ -1,
+ /*0x13ca*/ 566,
+ /*0x044a*/ 318,
+ /*0x04ca*/ 388,
+ /*0x0579*/ 464,
+ /*0x1044a*/ 1169,
+ /*0x00f9*/ 49,
/*0x24d8*/ 831,
+ /*0x037c*/ 240,
+ /*0x13d4*/ 576,
+ /*0x0454*/ 328,
+ -1, -1, -1,
+ /*0x1f76*/ 790,
+ /*0x13b6*/ 546,
+ /*0x0436*/ 298,
+ -1, -1,
+ /*0x10436*/ 1149,
+ /*0x03ca*/ 270,
+ /*0x1e929*/ 1368,
-1,
- /*0x1f07*/ 743,
- /*0x10ce2*/ 1240,
- /*0x10e4*/ 498,
- /*0x217e*/ 820,
- /*0x056a*/ 449,
- /*0x0497*/ 363,
- /*0x10e2*/ 496,
- /*0x13d2*/ 574,
- /*0x0452*/ 326,
- /*0x1e17*/ 624,
- /*0x2172*/ 808,
- /*0x0117*/ 67,
- /*0x2c97*/ 915,
+ /*0x24d4*/ 827,
+ /*0x0215*/ 175,
/*0x13b0*/ 540,
/*0x0430*/ 292,
-1,
- /*0x16e79*/ 1314,
- /*0x10430*/ 1138,
- /*0x0519*/ 428,
- /*0x00fb*/ 51,
- /*0x057c*/ 467,
+ /*0x1f64*/ 780,
+ /*0x10430*/ 1143,
+ /*0x13d2*/ 574,
+ /*0x0452*/ 326,
+ /*0x01ff*/ 164,
+ /*0x10ce2*/ 1280,
+ /*0x03b6*/ 251,
+ -1, -1,
+ /*0x1f15*/ 749,
+ /*0x10e2*/ 496,
+ /*0xa7c8*/ 1102,
+ -1, -1,
+ /*0x0509*/ 420,
+ /*0x2d27*/ 996,
/*0x24d2*/ 825,
- /*0x118c4*/ 1261,
- /*0x0199*/ 124,
+ -1, -1,
+ /*0x2c56*/ 887,
-1,
- /*0x10f4*/ 514,
+ /*0x10cd6*/ 1268,
+ -1, -1, -1,
+ /*0x10f8*/ 518,
+ /*0x10d6*/ 484,
+ /*0x2c5c*/ 893,
+ /*0xa7f6*/ 1107,
+ /*0x10cdc*/ 1274,
+ /*0x2c5a*/ 891,
+ /*0xa77c*/ 1074,
+ /*0x10cda*/ 1272,
-1,
- /*0x10cda*/ 1232,
+ /*0x10dc*/ 490,
+ /*0x0213*/ 174,
-1,
- /*0x0583*/ 474,
- -1, -1,
/*0x10da*/ 488,
- /*0x0576*/ 461,
+ /*0x13f4*/ 608,
-1,
- /*0x0078*/ 22,
- /*0x2c4e*/ 879,
- /*0x104f8*/ 1202,
- -1, -1, -1,
- /*0x00fd*/ 53,
- /*0x10ce0*/ 1238,
- /*0x2d05*/ 962,
+ /*0x1e942*/ 1393,
+ /*0x0074*/ 18,
-1,
- /*0x10cdc*/ 1234,
+ /*0x104f4*/ 1203,
+ -1, -1, -1, -1,
+ /*0x1f13*/ 747,
+ /*0x0260*/ 209,
+ -1, -1,
+ /*0x057f*/ 470,
-1,
- /*0x10e0*/ 494,
- /*0x0215*/ 175,
/*0x00ff*/ 55,
- /*0x10dc*/ 490,
- /*0x03f8*/ 290,
- /*0x1f21*/ 751,
- /*0x13de*/ 586,
- /*0x045e*/ 338,
- /*0xa7bb*/ 1096,
- -1,
- /*0x118c6*/ 1263,
- /*0x104de*/ 1176,
+ /*0x2c3c*/ 861,
+ -1, -1,
+ /*0x0289*/ 229,
-1,
- /*0x022b*/ 185,
+ /*0x0577*/ 462,
-1,
- /*0x13bc*/ 552,
- /*0x043c*/ 304,
+ /*0x1f60*/ 776,
+ -1, -1,
+ /*0x0207*/ 168,
+ /*0x2172*/ 808,
+ /*0x105ab*/ 1230,
-1,
- /*0x2c68*/ 899,
- /*0x1043c*/ 1150,
- /*0x24de*/ 837,
- /*0x10cd6*/ 1228,
- /*0x1f15*/ 749,
- /*0x013c*/ 84,
+ /*0x056c*/ 451,
-1,
- /*0x2c48*/ 873,
- /*0x10d6*/ 484,
+ /*0x00ec*/ 37,
+ -1, -1, -1,
+ /*0x052b*/ 437,
-1,
- /*0x10cd4*/ 1226,
- /*0x00fa*/ 50,
+ /*0x2c58*/ 889,
+ /*0x1f07*/ 743,
+ /*0x10cd8*/ 1270,
+ /*0x16e66*/ 1335,
+ -1, -1,
+ /*0x118c8*/ 1305,
+ /*0x10d8*/ 486,
+ /*0x2c4a*/ 875,
+ /*0x0568*/ 447,
+ /*0x10cca*/ 1256,
+ /*0x00e8*/ 33,
+ /*0x1f44*/ 770,
+ /*0xa793*/ 1082,
+ /*0x0217*/ 176,
+ /*0x16e72*/ 1347,
+ /*0x2c54*/ 885,
-1,
- /*0x2c6a*/ 900,
+ /*0x10cd4*/ 1266,
+ /*0x021d*/ 179,
-1,
+ /*0xa681*/ 1021,
+ /*0x2c36*/ 855,
/*0x10d4*/ 482,
- /*0x03bc*/ 257,
- /*0x2184*/ 822,
+ /*0x056a*/ 449,
-1,
- /*0x01c6*/ 138,
- /*0x0507*/ 419,
- /*0x1e09*/ 617,
- /*0x1e89*/ 681,
- /*0x0109*/ 60,
- /*0x2c89*/ 908,
+ /*0x00ea*/ 35,
+ /*0x1e92b*/ 1370,
-1,
- /*0x1f70*/ 784,
+ /*0x13b4*/ 544,
+ /*0x0434*/ 296,
-1,
- /*0xa785*/ 1077,
- -1, -1, -1, -1,
- /*0x10cd8*/ 1230,
+ /*0x2c30*/ 849,
+ /*0x10434*/ 1147,
+ -1, -1, -1,
+ /*0x2c52*/ 883,
-1,
- /*0x1f64*/ 780,
- -1, -1,
- /*0x10d8*/ 486,
- /*0x1f62*/ 778,
- /*0x00fe*/ 54,
+ /*0x10cd2*/ 1264,
-1,
- /*0x2c76*/ 903,
+ /*0x2179*/ 815,
+ /*0xa685*/ 1023,
+ /*0xa787*/ 1079,
+ /*0x10d2*/ 480,
+ /*0x2d03*/ 961,
-1,
- /*0xa7a9*/ 1092,
- /*0x048d*/ 358,
+ /*0x0570*/ 455,
+ /*0x03b4*/ 249,
+ /*0x00f0*/ 41,
+ -1, -1,
+ /*0x13cc*/ 568,
+ /*0x044c*/ 320,
+ /*0x04cc*/ 389,
+ /*0x2d0f*/ 973,
+ /*0x1044c*/ 1171,
+ /*0x1f62*/ 778,
+ /*0x049f*/ 367,
+ /*0x0195*/ 123,
+ /*0x0256*/ 204,
-1,
- /*0x00f2*/ 43,
- /*0x0213*/ 174,
- /*0x1e0d*/ 619,
- /*0x1e8d*/ 683,
- /*0x010d*/ 62,
- /*0x2c8d*/ 910,
- /*0x2c44*/ 869,
- /*0x2d03*/ 960,
+ /*0x1e1f*/ 628,
-1,
- /*0x10cd2*/ 1224,
- /*0x0377*/ 238,
- /*0x1f74*/ 788,
- /*0x0260*/ 209,
+ /*0x011f*/ 71,
+ /*0x2c9f*/ 920,
-1,
- /*0x10d2*/ 480,
+ /*0x16e79*/ 1354,
/*0x025c*/ 208,
- /*0x13cc*/ 568,
- /*0x044c*/ 320,
- /*0x04cc*/ 389,
+ /*0xa797*/ 1084,
+ /*0x118c6*/ 1303,
+ /*0x03cc*/ 272,
+ /*0x1f78*/ 792,
-1,
- /*0x1044c*/ 1166,
+ /*0xa79d*/ 1087,
+ -1, -1, -1, -1, -1,
+ /*0x10f4*/ 514,
+ -1, -1,
+ /*0x01c6*/ 138,
+ /*0x0576*/ 461,
-1,
- /*0x1f13*/ 747,
+ /*0x00f6*/ 47,
-1, -1,
- /*0x0521*/ 432,
+ /*0x13be*/ 554,
+ /*0x043e*/ 306,
-1,
- /*0x214e*/ 805,
+ /*0x2d21*/ 991,
+ /*0x1043e*/ 1157,
-1, -1,
- /*0x01a1*/ 127,
+ /*0x023c*/ 190,
+ /*0x013e*/ 85,
+ /*0x0564*/ 443,
+ /*0x048d*/ 358,
+ /*0x00e4*/ 29,
-1, -1,
- /*0x1f60*/ 776,
- /*0x2177*/ 813,
- /*0x03cc*/ 272,
+ /*0x1e0d*/ 619,
+ /*0x1e8d*/ 683,
+ /*0x010d*/ 62,
+ /*0x2c8d*/ 911,
+ /*0x0515*/ 426,
+ /*0x03be*/ 259,
+ -1,
+ /*0x1f7c*/ 796,
+ /*0x13ba*/ 550,
+ /*0x043a*/ 302,
-1, -1,
- /*0x0256*/ 204,
- /*0x10f8*/ 518,
+ /*0x1043a*/ 1153,
-1,
- /*0x2c46*/ 871,
- /*0x0515*/ 426,
+ /*0x217f*/ 821,
-1,
- /*0x2d19*/ 982,
- /*0x0254*/ 203,
+ /*0x013a*/ 83,
+ -1, -1, -1,
+ /*0x13b8*/ 548,
+ /*0x0438*/ 300,
+ /*0x2177*/ 813,
+ /*0x118c4*/ 1301,
+ /*0x10438*/ 1151,
+ /*0x2d19*/ 983,
-1,
- /*0x0195*/ 123,
- /*0x13ca*/ 566,
- /*0x044a*/ 318,
- /*0x04ca*/ 388,
+ /*0x03ba*/ 255,
+ -1, -1, -1,
+ /*0x0254*/ 203,
+ -1, -1, -1, -1, -1, -1,
+ /*0x2c34*/ 853,
+ /*0x03b8*/ 253,
+ /*0x16e7f*/ 1360,
+ -1, -1,
+ /*0x0513*/ 425,
+ -1, -1, -1, -1,
+ /*0x16e77*/ 1352,
-1,
- /*0x1044a*/ 1164,
+ /*0x1f36*/ 764,
-1,
- /*0x052b*/ 437,
- /*0x10cde*/ 1236,
+ /*0x0252*/ 201,
+ -1, -1, -1, -1,
+ /*0x16e6c*/ 1341,
-1,
- /*0xa783*/ 1076,
- /*0x16e7b*/ 1316,
+ /*0x00e0*/ 25,
+ /*0x1f30*/ 758,
+ /*0x2c4c*/ 877,
-1,
- /*0x10de*/ 492,
- /*0x037c*/ 240,
+ /*0x10ccc*/ 1258,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x0507*/ 419,
+ /*0x16e68*/ 1337,
+ -1, -1, -1,
+ /*0xa7ca*/ 1103,
+ -1, -1, -1, -1, -1,
+ /*0x118d6*/ 1319,
-1,
- /*0x1e92b*/ 1330,
- /*0x0570*/ 455,
- /*0x13b6*/ 546,
- /*0x0436*/ 298,
- /*0x03ca*/ 270,
+ /*0x2170*/ 806,
+ -1, -1,
+ /*0x16e6a*/ 1339,
-1,
- /*0x10436*/ 1144,
+ /*0x10597*/ 1211,
+ /*0x118dc*/ 1325,
+ /*0x1fd0*/ 800,
-1,
- /*0x13b4*/ 544,
- /*0x0434*/ 296,
- /*0x0564*/ 443,
- /*0xa7c8*/ 1100,
- /*0x10434*/ 1142,
+ /*0x118da*/ 1323,
+ /*0x1059d*/ 1217,
+ /*0x01d6*/ 145,
+ /*0x2c3e*/ 863,
+ /*0x0517*/ 427,
-1,
- /*0x0562*/ 441,
+ /*0x1f74*/ 788,
-1, -1,
- /*0x16e7d*/ 1318,
- /*0x118da*/ 1283,
+ /*0x051d*/ 430,
+ /*0x01dc*/ 148,
-1, -1,
- /*0x03b6*/ 251,
- /*0x217c*/ 818,
+ /*0x01da*/ 147,
-1,
- /*0x0217*/ 176,
- /*0x16e7f*/ 1320,
+ /*0xff47*/ 1115,
-1,
- /*0x03b4*/ 249,
- /*0x0252*/ 201,
+ /*0x16e70*/ 1345,
+ -1, -1, -1, -1,
+ /*0x0287*/ 227,
+ -1, -1,
+ /*0x2c3a*/ 859,
-1, -1,
- /*0xa799*/ 1084,
- -1,
- /*0x0574*/ 459,
- /*0xa68f*/ 1027,
/*0x2176*/ 812,
- /*0x118dc*/ 1285,
- -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x0562*/ 441,
-1,
- /*0x0513*/ 425,
- /*0x01da*/ 147,
- /*0xa7f6*/ 1102,
+ /*0x00e2*/ 27,
+ /*0x2c38*/ 857,
+ -1, -1, -1, -1, -1, -1,
+ /*0x2d09*/ 967,
+ -1, -1,
+ /*0x118d8*/ 1321,
-1,
- /*0x2d07*/ 964,
+ /*0x0578*/ 463,
-1,
- /*0x049f*/ 367,
+ /*0x00f8*/ 48,
-1,
- /*0x16e7a*/ 1315,
+ /*0x029d*/ 234,
+ /*0x16e76*/ 1351,
+ /*0x118ca*/ 1307,
-1,
- /*0x1e1f*/ 628,
- /*0x1f30*/ 758,
- /*0x011f*/ 71,
- /*0x2c9f*/ 919,
- /*0xa681*/ 1020,
- /*0x118d6*/ 1279,
- -1, -1, -1,
- /*0x01dc*/ 148,
+ /*0xff45*/ 1113,
-1, -1,
- /*0x118d4*/ 1277,
- /*0x10ccc*/ 1218,
- -1, -1, -1, -1, -1, -1,
- /*0x1f78*/ 792,
- -1, -1, -1, -1, -1, -1,
- /*0x16e7e*/ 1319,
- -1,
- /*0x023c*/ 190,
+ /*0x01d8*/ 146,
-1, -1,
- /*0x01d6*/ 145,
+ /*0x118d4*/ 1317,
+ -1, -1, -1, -1,
+ /*0x16e64*/ 1333,
+ -1, -1, -1, -1, -1,
+ /*0x1f34*/ 762,
-1,
- /*0x16e72*/ 1307,
- /*0x118d8*/ 1281,
- -1, -1, -1,
/*0x01d4*/ 144,
-1,
- /*0x00e8*/ 33,
+ /*0x105bc*/ 1245,
+ -1, -1, -1,
+ /*0x01b6*/ 134,
+ -1,
+ /*0x118d2*/ 1315,
-1, -1,
- /*0xa787*/ 1078,
- /*0x10cca*/ 1216,
- /*0x2d21*/ 990,
- /*0x0209*/ 169,
- -1, -1, -1, -1, -1, -1,
- /*0x00ea*/ 35,
- /*0xff42*/ 1105,
+ /*0x057c*/ 467,
+ /*0x021f*/ 180,
+ /*0x00fc*/ 52,
-1, -1,
- /*0x118d2*/ 1275,
- -1,
- /*0x2c5a*/ 891,
- -1,
- /*0x01d8*/ 146,
- /*0x2d15*/ 978,
- /*0xff50*/ 1119,
+ /*0x01b0*/ 132,
+ -1, -1, -1, -1,
+ /*0x01d2*/ 143,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1,
- /*0x00fc*/ 52,
+ /*0x1e93c*/ 1387,
+ -1, -1, -1, -1, -1, -1,
+ /*0x105b6*/ 1240,
-1, -1, -1, -1,
+ /*0xa683*/ 1022,
+ -1,
/*0x020d*/ 171,
- /*0x0517*/ 427,
+ /*0x16e60*/ 1329,
-1,
- /*0x2c5c*/ 893,
+ /*0x105b0*/ 1235,
-1, -1, -1, -1,
- /*0x00f6*/ 47,
- -1,
- /*0x01d2*/ 143,
+ /*0xa68f*/ 1028,
-1, -1, -1, -1, -1,
- /*0x01b0*/ 132,
- -1, -1,
- /*0x1fb1*/ 799,
- /*0x1e930*/ 1335,
- /*0xa7a1*/ 1088,
- -1, -1, -1, -1,
- /*0x2c56*/ 887,
- -1, -1,
- /*0x118de*/ 1287,
- /*0x0578*/ 463,
- -1, -1,
- /*0x2c54*/ 885,
+ /*0xa79f*/ 1088,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x0283*/ 226,
- /*0x2170*/ 806,
-1, -1, -1,
- /*0x2d13*/ 976,
- -1, -1,
- /*0x2c58*/ 889,
+ /*0x1e936*/ 1381,
-1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x1e930*/ 1375,
-1, -1, -1, -1, -1, -1,
- /*0x1e93c*/ 1347,
+ -1, -1, -1, -1, -1,
+ /*0x0574*/ 459,
+ -1,
+ /*0x00f4*/ 45,
-1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x0509*/ 420,
- /*0x2c52*/ 883,
-1,
- /*0x2174*/ 810,
- -1, -1, -1,
- /*0x2c30*/ 849,
- -1, -1, -1, -1,
- /*0x1f36*/ 764,
- -1, -1, -1, -1,
- /*0x16e77*/ 1312,
- /*0x1f34*/ 762,
+ /*0x2178*/ 814,
+ -1, -1, -1, -1, -1, -1,
-1, -1, -1,
- /*0x1fd0*/ 800,
- -1, -1,
- /*0xa793*/ 1081,
- /*0x118cc*/ 1269,
- -1,
- /*0x050d*/ 422,
+ /*0x01b4*/ 133,
+ /*0x16e62*/ 1331,
-1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x021f*/ 180,
-1,
- /*0x16e68*/ 1297,
- -1, -1, -1, -1,
- /*0xff4e*/ 1117,
- -1, -1,
- /*0x2c5e*/ 895,
- -1, -1, -1, -1,
- /*0x16e6a*/ 1299,
- /*0x01cc*/ 140,
+ /*0xa699*/ 1033,
+ /*0x118cc*/ 1309,
-1, -1,
- /*0x2c3c*/ 861,
- -1,
- /*0x118ca*/ 1267,
+ /*0x2d15*/ 979,
-1, -1,
- /*0x2d17*/ 980,
+ /*0x16e78*/ 1353,
-1, -1, -1, -1, -1, -1,
- /*0x16e7c*/ 1317,
- -1, -1, -1, -1,
- /*0x00f0*/ 41,
- /*0x0287*/ 227,
- /*0xa685*/ 1022,
+ /*0x01cc*/ 140,
-1, -1, -1, -1,
- /*0xff48*/ 1111,
- /*0x16e76*/ 1311,
- /*0x00e4*/ 29,
- -1, -1, -1,
- /*0x00e2*/ 27,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x01b6*/ 134,
+ /*0x217c*/ 818,
-1, -1,
- /*0x00f4*/ 45,
- /*0x1e936*/ 1341,
- -1,
- /*0x01b4*/ 133,
+ /*0x1fe0*/ 802,
+ -1, -1, -1, -1, -1, -1,
-1, -1,
- /*0xa797*/ 1083,
- /*0x1e934*/ 1339,
+ /*0x105b4*/ 1238,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x2c4c*/ 877,
- -1, -1, -1,
- /*0xff44*/ 1107,
- /*0x00e0*/ 25,
+ -1, -1, -1, -1, -1,
+ /*0x2d13*/ 977,
-1,
- /*0x2178*/ 814,
+ /*0x16e7c*/ 1357,
-1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x2d09*/ 966,
- -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1059f*/ 1219,
+ -1, -1, -1, -1, -1, -1,
+ -1,
/*0x051f*/ 431,
+ -1,
+ /*0x1e934*/ 1379,
+ -1, -1, -1, -1,
+ /*0x2d07*/ 965,
+ -1,
+ /*0xff50*/ 1124,
-1, -1, -1, -1, -1, -1,
-1,
- /*0xa683*/ 1021,
+ /*0xff42*/ 1110,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x2d17*/ 981,
+ -1, -1, -1, -1,
+ /*0x2d1d*/ 987,
-1, -1,
- /*0x2c4a*/ 875,
+ /*0x050d*/ 422,
+ -1, -1, -1, -1, -1,
+ /*0x2174*/ 810,
+ /*0xa689*/ 1025,
-1, -1, -1, -1, -1, -1,
- /*0xff46*/ 1109,
-1, -1, -1, -1,
- /*0x2d0d*/ 970,
+ /*0x105b8*/ 1242,
+ -1, -1,
+ /*0x1e93e*/ 1389,
+ -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1,
- /*0x2c36*/ 855,
- -1, -1, -1, -1, -1,
- /*0x2c34*/ 853,
+ /*0x16e74*/ 1349,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1,
- /*0xa699*/ 1032,
+ /*0x1e93a*/ 1385,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x1e938*/ 1383,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x16e70*/ 1305,
-1, -1, -1, -1, -1, -1,
- /*0x00f8*/ 48,
-1,
- /*0x16e64*/ 1293,
+ /*0x1fb0*/ 798,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
-1, -1, -1,
- /*0x16e62*/ 1291,
+ /*0xff48*/ 1116,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0xa687*/ 1023,
- /*0x16e74*/ 1309,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0xa7ca*/ 1101,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x16e60*/ 1289,
- -1, -1,
- /*0x2d1f*/ 988,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xff5a*/ 1129,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0xa695*/ 1030,
+ -1, -1, -1,
+ /*0xff46*/ 1114,
+ -1, -1, -1,
+ /*0xa695*/ 1031,
-1, -1, -1, -1, -1, -1,
- /*0xa79f*/ 1087,
-1, -1, -1, -1, -1, -1,
- /*0xff56*/ 1125,
-1, -1, -1, -1, -1, -1,
- /*0xff54*/ 1123,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0xff58*/ 1127,
-1, -1,
- /*0x0289*/ 229,
+ /*0xa693*/ 1030,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xff44*/ 1112,
+ -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1,
- /*0x16e78*/ 1313,
+ /*0xa687*/ 1024,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x2d1f*/ 989,
-1, -1, -1, -1, -1, -1,
- /*0xa693*/ 1029,
-1,
- /*0xff52*/ 1121,
+ /*0xa697*/ 1032,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0xff56*/ 1130,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0xff5a*/ 1134,
+ -1, -1, -1,
+ /*0x2d0d*/ 971,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xff58*/ 1132,
+ -1, -1, -1, -1, -1, -1,
-1,
- /*0x1fe0*/ 802,
+ /*0xff4a*/ 1118,
-1, -1, -1, -1, -1, -1,
+ -1,
+ /*0xff54*/ 1128,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0xff52*/ 1126,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xa697*/ 1031,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x1fb0*/ 798,
- -1, -1, -1,
- /*0xff4c*/ 1115,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1,
- /*0xff4a*/ 1113,
-1, -1, -1, -1, -1, -1,
- -1,
- /*0xa689*/ 1024,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xa68d*/ 1026
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xff4c*/ 1120,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xa68d*/ 1027
};
if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE)
diff --git a/enc/unicode/13.0.0/name2ctype.h b/enc/unicode/15.0.0/name2ctype.h
index e8997c7d2e..a2c996423d 100644
--- a/enc/unicode/13.0.0/name2ctype.h
+++ b/enc/unicode/15.0.0/name2ctype.h
@@ -43,7 +43,7 @@ static const OnigCodePoint CR_NEWLINE[] = {
/* 'Alpha': [[:Alpha:]] */
static const OnigCodePoint CR_Alpha[] = {
- 695,
+ 732,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -96,8 +96,9 @@ static const OnigCodePoint CR_Alpha[] = {
0x081a, 0x082c,
0x0840, 0x0858,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x08a0, 0x08c9,
0x08d4, 0x08df,
0x08e3, 0x08e9,
0x08f0, 0x093b,
@@ -177,8 +178,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x0bca, 0x0bcc,
0x0bd0, 0x0bd0,
0x0bd7, 0x0bd7,
- 0x0c00, 0x0c03,
- 0x0c05, 0x0c0c,
+ 0x0c00, 0x0c0c,
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
@@ -187,6 +187,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x0c4a, 0x0c4c,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c80, 0x0c83,
0x0c85, 0x0c8c,
@@ -198,9 +199,9 @@ static const OnigCodePoint CR_Alpha[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccc,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d3a,
@@ -238,7 +239,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x0f00, 0x0f00,
0x0f40, 0x0f47,
0x0f49, 0x0f6c,
- 0x0f71, 0x0f81,
+ 0x0f71, 0x0f83,
0x0f88, 0x0f97,
0x0f99, 0x0fbc,
0x1000, 0x1036,
@@ -274,9 +275,8 @@ static const OnigCodePoint CR_Alpha[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1713,
- 0x1720, 0x1733,
+ 0x1700, 0x1713,
+ 0x171f, 0x1733,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -300,9 +300,10 @@ static const OnigCodePoint CR_Alpha[] = {
0x1a61, 0x1a74,
0x1aa7, 0x1aa7,
0x1abf, 0x1ac0,
+ 0x1acc, 0x1ace,
0x1b00, 0x1b33,
0x1b35, 0x1b43,
- 0x1b45, 0x1b4b,
+ 0x1b45, 0x1b4c,
0x1b80, 0x1ba9,
0x1bac, 0x1baf,
0x1bba, 0x1be5,
@@ -356,9 +357,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x214e, 0x214e,
0x2160, 0x2188,
0x24b6, 0x24e9,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
0x2d00, 0x2d25,
@@ -390,8 +389,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa61f,
@@ -401,9 +399,11 @@ static const OnigCodePoint CR_Alpha[] = {
0xa67f, 0xa6ef,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa805,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa805,
0xa807, 0xa827,
0xa840, 0xa873,
0xa880, 0xa8c3,
@@ -485,9 +485,20 @@ static const OnigCodePoint CR_Alpha[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -525,10 +536,13 @@ static const OnigCodePoint CR_Alpha[] = {
0x10f00, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11000, 0x11045,
- 0x11082, 0x110b8,
+ 0x11071, 0x11075,
+ 0x11080, 0x110b8,
+ 0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x11100, 0x11132,
0x11144, 0x11147,
@@ -542,7 +556,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x11200, 0x11211,
0x11213, 0x11234,
0x11237, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -579,6 +593,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x116b8, 0x116b8,
0x11700, 0x1171a,
0x1171d, 0x1172a,
+ 0x11740, 0x11746,
0x11800, 0x11838,
0x118a0, 0x118df,
0x118ff, 0x11906,
@@ -598,7 +613,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x11a35, 0x11a3e,
0x11a50, 0x11a97,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c3e,
@@ -621,14 +636,20 @@ static const OnigCodePoint CR_Alpha[] = {
0x11d93, 0x11d96,
0x11d98, 0x11d98,
0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f40,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
0x16ad0, 0x16aed,
0x16b00, 0x16b2f,
0x16b40, 0x16b43,
@@ -644,8 +665,13 @@ static const OnigCodePoint CR_Alpha[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -683,15 +709,25 @@ static const OnigCodePoint CR_Alpha[] = {
0x1d78a, 0x1d7a8,
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e900, 0x1e943,
0x1e947, 0x1e947,
@@ -732,13 +768,14 @@ static const OnigCodePoint CR_Alpha[] = {
0x1f130, 0x1f149,
0x1f150, 0x1f169,
0x1f170, 0x1f189,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Alpha */
/* 'Blank': [[:Blank:]] */
@@ -763,7 +800,7 @@ static const OnigCodePoint CR_Cntrl[] = {
/* 'Digit': [[:Digit:]] */
static const OnigCodePoint CR_Digit[] = {
- 61,
+ 64,
0x0030, 0x0039,
0x0660, 0x0669,
0x06f0, 0x06f9,
@@ -818,18 +855,21 @@ static const OnigCodePoint CR_Digit[] = {
0x11c50, 0x11c59,
0x11d50, 0x11d59,
0x11da0, 0x11da9,
+ 0x11f50, 0x11f59,
0x16a60, 0x16a69,
+ 0x16ac0, 0x16ac9,
0x16b50, 0x16b59,
0x1d7ce, 0x1d7ff,
0x1e140, 0x1e149,
0x1e2f0, 0x1e2f9,
+ 0x1e4f0, 0x1e4f9,
0x1e950, 0x1e959,
0x1fbf0, 0x1fbf9,
}; /* CR_Digit */
/* 'Graph': [[:Graph:]] */
static const OnigCodePoint CR_Graph[] = {
- 682,
+ 712,
0x0021, 0x007e,
0x00a1, 0x0377,
0x037a, 0x037f,
@@ -843,8 +883,7 @@ static const OnigCodePoint CR_Graph[] = {
0x0591, 0x05c7,
0x05d0, 0x05ea,
0x05ef, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
+ 0x0600, 0x070d,
0x070f, 0x074a,
0x074d, 0x07b1,
0x07c0, 0x07fa,
@@ -853,9 +892,9 @@ static const OnigCodePoint CR_Graph[] = {
0x0840, 0x085b,
0x085e, 0x085e,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x0983,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
0x0985, 0x098c,
0x098f, 0x0990,
0x0993, 0x09a8,
@@ -933,11 +972,12 @@ static const OnigCodePoint CR_Graph[] = {
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c77, 0x0c8c,
@@ -949,10 +989,10 @@ static const OnigCodePoint CR_Graph[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -982,7 +1022,7 @@ static const OnigCodePoint CR_Graph[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f47,
@@ -1017,9 +1057,8 @@ static const OnigCodePoint CR_Graph[] = {
0x1400, 0x167f,
0x1681, 0x169c,
0x16a0, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
+ 0x1700, 0x1715,
+ 0x171f, 0x1736,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -1027,8 +1066,7 @@ static const OnigCodePoint CR_Graph[] = {
0x1780, 0x17dd,
0x17e0, 0x17e9,
0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
+ 0x1800, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x18b0, 0x18f5,
@@ -1047,9 +1085,9 @@ static const OnigCodePoint CR_Graph[] = {
0x1a7f, 0x1a89,
0x1a90, 0x1a99,
0x1aa0, 0x1aad,
- 0x1ab0, 0x1ac0,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
+ 0x1ab0, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
0x1b80, 0x1bf3,
0x1bfc, 0x1c37,
0x1c3b, 0x1c49,
@@ -1057,8 +1095,7 @@ static const OnigCodePoint CR_Graph[] = {
0x1c90, 0x1cba,
0x1cbd, 0x1cc7,
0x1cd0, 0x1cfa,
- 0x1d00, 0x1df9,
- 0x1dfb, 0x1f15,
+ 0x1d00, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
0x1f48, 0x1f4d,
@@ -1081,16 +1118,14 @@ static const OnigCodePoint CR_Graph[] = {
0x2066, 0x2071,
0x2074, 0x208e,
0x2090, 0x209c,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0x20d0, 0x20f0,
0x2100, 0x218b,
0x2190, 0x2426,
0x2440, 0x244a,
0x2460, 0x2b73,
0x2b76, 0x2b95,
- 0x2b97, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2cf3,
+ 0x2b97, 0x2cf3,
0x2cf9, 0x2d25,
0x2d27, 0x2d27,
0x2d2d, 0x2d2d,
@@ -1105,7 +1140,7 @@ static const OnigCodePoint CR_Graph[] = {
0x2dc8, 0x2dce,
0x2dd0, 0x2dd6,
0x2dd8, 0x2dde,
- 0x2de0, 0x2e52,
+ 0x2de0, 0x2e5d,
0x2e80, 0x2e99,
0x2e9b, 0x2ef3,
0x2f00, 0x2fd5,
@@ -1117,14 +1152,15 @@ static const OnigCodePoint CR_Graph[] = {
0x3131, 0x318e,
0x3190, 0x31e3,
0x31f0, 0x321e,
- 0x3220, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x3220, 0xa48c,
0xa490, 0xa4c6,
0xa4d0, 0xa62b,
0xa640, 0xa6f7,
- 0xa700, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa82c,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa82c,
0xa830, 0xa839,
0xa840, 0xa877,
0xa880, 0xa8c5,
@@ -1159,12 +1195,11 @@ static const OnigCodePoint CR_Graph[] = {
0xfb3e, 0xfb3e,
0xfb40, 0xfb41,
0xfb43, 0xfb44,
- 0xfb46, 0xfbc1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
+ 0xfb46, 0xfbc2,
+ 0xfbd3, 0xfd8f,
0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
- 0xfe00, 0xfe19,
+ 0xfdcf, 0xfdcf,
+ 0xfdf0, 0xfe19,
0xfe20, 0xfe52,
0xfe54, 0xfe66,
0xfe68, 0xfe6b,
@@ -1207,10 +1242,20 @@ static const OnigCodePoint CR_Graph[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
- 0x1056f, 0x1056f,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -1252,13 +1297,14 @@ static const OnigCodePoint CR_Graph[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10ead,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
+ 0x10efd, 0x10f27,
0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
0x10fb0, 0x10fcb,
0x10fe0, 0x10ff6,
0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
0x110cd, 0x110cd,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
@@ -1268,7 +1314,7 @@ static const OnigCodePoint CR_Graph[] = {
0x11180, 0x111df,
0x111e1, 0x111f4,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -1300,11 +1346,11 @@ static const OnigCodePoint CR_Graph[] = {
0x11600, 0x11644,
0x11650, 0x11659,
0x11660, 0x1166c,
- 0x11680, 0x116b8,
+ 0x11680, 0x116b9,
0x116c0, 0x116c9,
0x11700, 0x1171a,
0x1171d, 0x1172b,
- 0x11730, 0x1173f,
+ 0x11730, 0x11746,
0x11800, 0x1183b,
0x118a0, 0x118f2,
0x118ff, 0x11906,
@@ -1320,7 +1366,8 @@ static const OnigCodePoint CR_Graph[] = {
0x119da, 0x119e4,
0x11a00, 0x11a47,
0x11a50, 0x11aa2,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c45,
@@ -1342,19 +1389,23 @@ static const OnigCodePoint CR_Graph[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
0x12400, 0x1246e,
0x12470, 0x12474,
0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af0, 0x16af5,
0x16b00, 0x16b45,
@@ -1371,8 +1422,13 @@ static const OnigCodePoint CR_Graph[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -1380,10 +1436,14 @@ static const OnigCodePoint CR_Graph[] = {
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
- 0x1d129, 0x1d1e8,
+ 0x1d129, 0x1d1ea,
0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -1410,17 +1470,27 @@ static const OnigCodePoint CR_Graph[] = {
0x1d7ce, 0x1da8b,
0x1da9b, 0x1da9f,
0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e130, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8c7, 0x1e8d6,
0x1e900, 0x1e94b,
@@ -1475,38 +1545,38 @@ static const OnigCodePoint CR_Graph[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0001, 0xe0001,
0xe0020, 0xe007f,
0xe0100, 0xe01ef,
@@ -1516,7 +1586,7 @@ static const OnigCodePoint CR_Graph[] = {
/* 'Lower': [[:Lower:]] */
static const OnigCodePoint CR_Lower[] = {
- 652,
+ 671,
0x0061, 0x007a,
0x00aa, 0x00aa,
0x00b5, 0x00b5,
@@ -1793,7 +1863,7 @@ static const OnigCodePoint CR_Lower[] = {
0x052f, 0x052f,
0x0560, 0x0588,
0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
+ 0x10fc, 0x10ff,
0x13f8, 0x13fd,
0x1c80, 0x1c88,
0x1d00, 0x1dbf,
@@ -1956,7 +2026,7 @@ static const OnigCodePoint CR_Lower[] = {
0x2170, 0x217f,
0x2184, 0x2184,
0x24d0, 0x24e9,
- 0x2c30, 0x2c5e,
+ 0x2c30, 0x2c5f,
0x2c61, 0x2c61,
0x2c65, 0x2c66,
0x2c68, 0x2c68,
@@ -2124,19 +2194,34 @@ static const OnigCodePoint CR_Lower[] = {
0xa7bb, 0xa7bb,
0xa7bd, 0xa7bd,
0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
0xa7c3, 0xa7c3,
0xa7c8, 0xa7c8,
0xa7ca, 0xa7ca,
+ 0xa7d1, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d5,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
+ 0xa7f2, 0xa7f4,
0xa7f6, 0xa7f6,
0xa7f8, 0xa7fa,
0xab30, 0xab5a,
- 0xab5c, 0xab68,
+ 0xab5c, 0xab69,
0xab70, 0xabbf,
0xfb00, 0xfb06,
0xfb13, 0xfb17,
0xff41, 0xff5a,
0x10428, 0x1044f,
0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10cc0, 0x10cf2,
0x118c0, 0x118df,
0x16e60, 0x16e7f,
@@ -2168,12 +2253,16 @@ static const OnigCodePoint CR_Lower[] = {
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7c9,
0x1d7cb, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e922, 0x1e943,
}; /* CR_Lower */
/* 'Print': [[:Print:]] */
static const OnigCodePoint CR_Print[] = {
- 679,
+ 709,
0x0020, 0x007e,
0x00a0, 0x0377,
0x037a, 0x037f,
@@ -2187,8 +2276,7 @@ static const OnigCodePoint CR_Print[] = {
0x0591, 0x05c7,
0x05d0, 0x05ea,
0x05ef, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
+ 0x0600, 0x070d,
0x070f, 0x074a,
0x074d, 0x07b1,
0x07c0, 0x07fa,
@@ -2197,9 +2285,9 @@ static const OnigCodePoint CR_Print[] = {
0x0840, 0x085b,
0x085e, 0x085e,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x0983,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
0x0985, 0x098c,
0x098f, 0x0990,
0x0993, 0x09a8,
@@ -2277,11 +2365,12 @@ static const OnigCodePoint CR_Print[] = {
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c77, 0x0c8c,
@@ -2293,10 +2382,10 @@ static const OnigCodePoint CR_Print[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -2326,7 +2415,7 @@ static const OnigCodePoint CR_Print[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f47,
@@ -2360,9 +2449,8 @@ static const OnigCodePoint CR_Print[] = {
0x13f8, 0x13fd,
0x1400, 0x169c,
0x16a0, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
+ 0x1700, 0x1715,
+ 0x171f, 0x1736,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -2370,8 +2458,7 @@ static const OnigCodePoint CR_Print[] = {
0x1780, 0x17dd,
0x17e0, 0x17e9,
0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
+ 0x1800, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x18b0, 0x18f5,
@@ -2390,9 +2477,9 @@ static const OnigCodePoint CR_Print[] = {
0x1a7f, 0x1a89,
0x1a90, 0x1a99,
0x1aa0, 0x1aad,
- 0x1ab0, 0x1ac0,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
+ 0x1ab0, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
0x1b80, 0x1bf3,
0x1bfc, 0x1c37,
0x1c3b, 0x1c49,
@@ -2400,8 +2487,7 @@ static const OnigCodePoint CR_Print[] = {
0x1c90, 0x1cba,
0x1cbd, 0x1cc7,
0x1cd0, 0x1cfa,
- 0x1d00, 0x1df9,
- 0x1dfb, 0x1f15,
+ 0x1d00, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
0x1f48, 0x1f4d,
@@ -2422,16 +2508,14 @@ static const OnigCodePoint CR_Print[] = {
0x2066, 0x2071,
0x2074, 0x208e,
0x2090, 0x209c,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0x20d0, 0x20f0,
0x2100, 0x218b,
0x2190, 0x2426,
0x2440, 0x244a,
0x2460, 0x2b73,
0x2b76, 0x2b95,
- 0x2b97, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2cf3,
+ 0x2b97, 0x2cf3,
0x2cf9, 0x2d25,
0x2d27, 0x2d27,
0x2d2d, 0x2d2d,
@@ -2446,7 +2530,7 @@ static const OnigCodePoint CR_Print[] = {
0x2dc8, 0x2dce,
0x2dd0, 0x2dd6,
0x2dd8, 0x2dde,
- 0x2de0, 0x2e52,
+ 0x2de0, 0x2e5d,
0x2e80, 0x2e99,
0x2e9b, 0x2ef3,
0x2f00, 0x2fd5,
@@ -2458,14 +2542,15 @@ static const OnigCodePoint CR_Print[] = {
0x3131, 0x318e,
0x3190, 0x31e3,
0x31f0, 0x321e,
- 0x3220, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x3220, 0xa48c,
0xa490, 0xa4c6,
0xa4d0, 0xa62b,
0xa640, 0xa6f7,
- 0xa700, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa82c,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa82c,
0xa830, 0xa839,
0xa840, 0xa877,
0xa880, 0xa8c5,
@@ -2500,12 +2585,11 @@ static const OnigCodePoint CR_Print[] = {
0xfb3e, 0xfb3e,
0xfb40, 0xfb41,
0xfb43, 0xfb44,
- 0xfb46, 0xfbc1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
+ 0xfb46, 0xfbc2,
+ 0xfbd3, 0xfd8f,
0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
- 0xfe00, 0xfe19,
+ 0xfdcf, 0xfdcf,
+ 0xfdf0, 0xfe19,
0xfe20, 0xfe52,
0xfe54, 0xfe66,
0xfe68, 0xfe6b,
@@ -2548,10 +2632,20 @@ static const OnigCodePoint CR_Print[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
- 0x1056f, 0x1056f,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -2593,13 +2687,14 @@ static const OnigCodePoint CR_Print[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10ead,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
+ 0x10efd, 0x10f27,
0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
0x10fb0, 0x10fcb,
0x10fe0, 0x10ff6,
0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
0x110cd, 0x110cd,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
@@ -2609,7 +2704,7 @@ static const OnigCodePoint CR_Print[] = {
0x11180, 0x111df,
0x111e1, 0x111f4,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -2641,11 +2736,11 @@ static const OnigCodePoint CR_Print[] = {
0x11600, 0x11644,
0x11650, 0x11659,
0x11660, 0x1166c,
- 0x11680, 0x116b8,
+ 0x11680, 0x116b9,
0x116c0, 0x116c9,
0x11700, 0x1171a,
0x1171d, 0x1172b,
- 0x11730, 0x1173f,
+ 0x11730, 0x11746,
0x11800, 0x1183b,
0x118a0, 0x118f2,
0x118ff, 0x11906,
@@ -2661,7 +2756,8 @@ static const OnigCodePoint CR_Print[] = {
0x119da, 0x119e4,
0x11a00, 0x11a47,
0x11a50, 0x11aa2,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c45,
@@ -2683,19 +2779,23 @@ static const OnigCodePoint CR_Print[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
0x12400, 0x1246e,
0x12470, 0x12474,
0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af0, 0x16af5,
0x16b00, 0x16b45,
@@ -2712,8 +2812,13 @@ static const OnigCodePoint CR_Print[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -2721,10 +2826,14 @@ static const OnigCodePoint CR_Print[] = {
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
- 0x1d129, 0x1d1e8,
+ 0x1d129, 0x1d1ea,
0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -2751,17 +2860,27 @@ static const OnigCodePoint CR_Print[] = {
0x1d7ce, 0x1da8b,
0x1da9b, 0x1da9f,
0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e130, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8c7, 0x1e8d6,
0x1e900, 0x1e94b,
@@ -2816,38 +2935,38 @@ static const OnigCodePoint CR_Print[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0001, 0xe0001,
0xe0020, 0xe007f,
0xe0100, 0xe01ef,
@@ -2857,7 +2976,7 @@ static const OnigCodePoint CR_Print[] = {
/* 'XPosixPunct': [[:Punct:]] */
static const OnigCodePoint CR_XPosixPunct[] = {
- 180,
+ 186,
0x0021, 0x002f,
0x003a, 0x0040,
0x005b, 0x0060,
@@ -2880,7 +2999,7 @@ static const OnigCodePoint CR_XPosixPunct[] = {
0x0609, 0x060a,
0x060c, 0x060d,
0x061b, 0x061b,
- 0x061e, 0x061f,
+ 0x061d, 0x061f,
0x066a, 0x066d,
0x06d4, 0x06d4,
0x0700, 0x070d,
@@ -2919,6 +3038,7 @@ static const OnigCodePoint CR_XPosixPunct[] = {
0x1aa0, 0x1aa6,
0x1aa8, 0x1aad,
0x1b5a, 0x1b60,
+ 0x1b7d, 0x1b7e,
0x1bfc, 0x1bff,
0x1c3b, 0x1c3f,
0x1c7e, 0x1c7f,
@@ -2943,7 +3063,7 @@ static const OnigCodePoint CR_XPosixPunct[] = {
0x2d70, 0x2d70,
0x2e00, 0x2e2e,
0x2e30, 0x2e4f,
- 0x2e52, 0x2e52,
+ 0x2e52, 0x2e5d,
0x3001, 0x3003,
0x3008, 0x3011,
0x3014, 0x301f,
@@ -2999,6 +3119,7 @@ static const OnigCodePoint CR_XPosixPunct[] = {
0x10b99, 0x10b9c,
0x10ead, 0x10ead,
0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
0x11047, 0x1104d,
0x110bb, 0x110bc,
0x110be, 0x110c1,
@@ -3017,6 +3138,7 @@ static const OnigCodePoint CR_XPosixPunct[] = {
0x115c1, 0x115d7,
0x11641, 0x11643,
0x11660, 0x1166c,
+ 0x116b9, 0x116b9,
0x1173c, 0x1173e,
0x1183b, 0x1183b,
0x11944, 0x11946,
@@ -3024,11 +3146,14 @@ static const OnigCodePoint CR_XPosixPunct[] = {
0x11a3f, 0x11a46,
0x11a9a, 0x11a9c,
0x11a9e, 0x11aa2,
+ 0x11b00, 0x11b09,
0x11c41, 0x11c45,
0x11c70, 0x11c71,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f4f,
0x11fff, 0x11fff,
0x12470, 0x12474,
+ 0x12ff1, 0x12ff2,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
0x16b37, 0x16b3b,
@@ -3057,7 +3182,7 @@ static const OnigCodePoint CR_Space[] = {
/* 'Upper': [[:Upper:]] */
static const OnigCodePoint CR_Upper[] = {
- 643,
+ 651,
0x0041, 0x005a,
0x00c0, 0x00d6,
0x00d8, 0x00de,
@@ -3491,7 +3616,7 @@ static const OnigCodePoint CR_Upper[] = {
0x2160, 0x216f,
0x2183, 0x2183,
0x24b6, 0x24cf,
- 0x2c00, 0x2c2e,
+ 0x2c00, 0x2c2f,
0x2c60, 0x2c60,
0x2c62, 0x2c64,
0x2c67, 0x2c67,
@@ -3656,13 +3781,21 @@ static const OnigCodePoint CR_Upper[] = {
0xa7ba, 0xa7ba,
0xa7bc, 0xa7bc,
0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
0xa7c2, 0xa7c2,
0xa7c4, 0xa7c7,
0xa7c9, 0xa7c9,
+ 0xa7d0, 0xa7d0,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
0xa7f5, 0xa7f5,
0xff21, 0xff3a,
0x10400, 0x10427,
0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
0x10c80, 0x10cb2,
0x118a0, 0x118bf,
0x16e40, 0x16e5f,
@@ -3713,7 +3846,7 @@ static const OnigCodePoint CR_XDigit[] = {
/* 'Word': [[:Word:]] */
static const OnigCodePoint CR_Word[] = {
- 732,
+ 770,
0x0030, 0x0039,
0x0041, 0x005a,
0x005f, 0x005f,
@@ -3764,9 +3897,9 @@ static const OnigCodePoint CR_Word[] = {
0x0800, 0x082d,
0x0840, 0x085b,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x08e1,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x0898, 0x08e1,
0x08e3, 0x0963,
0x0966, 0x096f,
0x0971, 0x0983,
@@ -3850,11 +3983,12 @@ static const OnigCodePoint CR_Word[] = {
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c80, 0x0c83,
@@ -3867,10 +4001,10 @@ static const OnigCodePoint CR_Word[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -3903,7 +4037,7 @@ static const OnigCodePoint CR_Word[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f00,
@@ -3949,9 +4083,8 @@ static const OnigCodePoint CR_Word[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1734,
+ 0x1700, 0x1715,
+ 0x171f, 0x1734,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -3961,7 +4094,7 @@ static const OnigCodePoint CR_Word[] = {
0x17dc, 0x17dd,
0x17e0, 0x17e9,
0x180b, 0x180d,
- 0x1810, 0x1819,
+ 0x180f, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x18b0, 0x18f5,
@@ -3979,8 +4112,8 @@ static const OnigCodePoint CR_Word[] = {
0x1a7f, 0x1a89,
0x1a90, 0x1a99,
0x1aa7, 0x1aa7,
- 0x1ab0, 0x1ac0,
- 0x1b00, 0x1b4b,
+ 0x1ab0, 0x1ace,
+ 0x1b00, 0x1b4c,
0x1b50, 0x1b59,
0x1b6b, 0x1b73,
0x1b80, 0x1bf3,
@@ -3992,8 +4125,7 @@ static const OnigCodePoint CR_Word[] = {
0x1cbd, 0x1cbf,
0x1cd0, 0x1cd2,
0x1cd4, 0x1cfa,
- 0x1d00, 0x1df9,
- 0x1dfb, 0x1f15,
+ 0x1d00, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
0x1f48, 0x1f4d,
@@ -4033,9 +4165,7 @@ static const OnigCodePoint CR_Word[] = {
0x214e, 0x214e,
0x2160, 0x2188,
0x24b6, 0x24e9,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cf3,
0x2d00, 0x2d25,
0x2d27, 0x2d27,
@@ -4067,8 +4197,7 @@ static const OnigCodePoint CR_Word[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa62b,
@@ -4077,9 +4206,11 @@ static const OnigCodePoint CR_Word[] = {
0xa67f, 0xa6f1,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa827,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa827,
0xa82c, 0xa82c,
0xa840, 0xa873,
0xa880, 0xa8c5,
@@ -4168,9 +4299,20 @@ static const OnigCodePoint CR_Word[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -4208,14 +4350,16 @@ static const OnigCodePoint CR_Word[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10eac,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
+ 0x10efd, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f50,
+ 0x10f70, 0x10f85,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11000, 0x11046,
- 0x11066, 0x1106f,
+ 0x11066, 0x11075,
0x1107f, 0x110ba,
+ 0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
0x11100, 0x11134,
@@ -4229,7 +4373,7 @@ static const OnigCodePoint CR_Word[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -4269,6 +4413,7 @@ static const OnigCodePoint CR_Word[] = {
0x11700, 0x1171a,
0x1171d, 0x1172b,
0x11730, 0x11739,
+ 0x11740, 0x11746,
0x11800, 0x1183a,
0x118a0, 0x118e9,
0x118ff, 0x11906,
@@ -4287,7 +4432,7 @@ static const OnigCodePoint CR_Word[] = {
0x11a47, 0x11a47,
0x11a50, 0x11a99,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c40,
@@ -4309,15 +4454,23 @@ static const OnigCodePoint CR_Word[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f50, 0x11f59,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af0, 0x16af4,
0x16b00, 0x16b36,
@@ -4335,8 +4488,13 @@ static const OnigCodePoint CR_Word[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -4344,6 +4502,8 @@ static const OnigCodePoint CR_Word[] = {
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d165, 0x1d169,
0x1d16d, 0x1d172,
0x1d17b, 0x1d182,
@@ -4387,16 +4547,26 @@ static const OnigCodePoint CR_Word[] = {
0x1da84, 0x1da84,
0x1da9b, 0x1da9f,
0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e130, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8d0, 0x1e8d6,
0x1e900, 0x1e94b,
@@ -4438,19 +4608,20 @@ static const OnigCodePoint CR_Word[] = {
0x1f150, 0x1f169,
0x1f170, 0x1f189,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0100, 0xe01ef,
}; /* CR_Word */
/* 'Alnum': [[:Alnum:]] */
static const OnigCodePoint CR_Alnum[] = {
- 732,
+ 772,
0x0030, 0x0039,
0x0041, 0x005a,
0x0061, 0x007a,
@@ -4503,8 +4674,9 @@ static const OnigCodePoint CR_Alnum[] = {
0x081a, 0x082c,
0x0840, 0x0858,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x08a0, 0x08c9,
0x08d4, 0x08df,
0x08e3, 0x08e9,
0x08f0, 0x093b,
@@ -4588,8 +4760,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x0bd0, 0x0bd0,
0x0bd7, 0x0bd7,
0x0be6, 0x0bef,
- 0x0c00, 0x0c03,
- 0x0c05, 0x0c0c,
+ 0x0c00, 0x0c0c,
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
@@ -4598,6 +4769,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x0c4a, 0x0c4c,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c80, 0x0c83,
@@ -4610,10 +4782,10 @@ static const OnigCodePoint CR_Alnum[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccc,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d3a,
@@ -4656,7 +4828,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x0f20, 0x0f29,
0x0f40, 0x0f47,
0x0f49, 0x0f6c,
- 0x0f71, 0x0f81,
+ 0x0f71, 0x0f83,
0x0f88, 0x0f97,
0x0f99, 0x0fbc,
0x1000, 0x1036,
@@ -4691,9 +4863,8 @@ static const OnigCodePoint CR_Alnum[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1713,
- 0x1720, 0x1733,
+ 0x1700, 0x1713,
+ 0x171f, 0x1733,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -4722,9 +4893,10 @@ static const OnigCodePoint CR_Alnum[] = {
0x1a90, 0x1a99,
0x1aa7, 0x1aa7,
0x1abf, 0x1ac0,
+ 0x1acc, 0x1ace,
0x1b00, 0x1b33,
0x1b35, 0x1b43,
- 0x1b45, 0x1b4b,
+ 0x1b45, 0x1b4c,
0x1b50, 0x1b59,
0x1b80, 0x1ba9,
0x1bac, 0x1be5,
@@ -4778,9 +4950,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x214e, 0x214e,
0x2160, 0x2188,
0x24b6, 0x24e9,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
0x2d00, 0x2d25,
@@ -4812,8 +4982,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa62b,
@@ -4822,9 +4991,11 @@ static const OnigCodePoint CR_Alnum[] = {
0xa67f, 0xa6ef,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa805,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa805,
0xa807, 0xa827,
0xa840, 0xa873,
0xa880, 0xa8c3,
@@ -4909,9 +5080,20 @@ static const OnigCodePoint CR_Alnum[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -4950,11 +5132,14 @@ static const OnigCodePoint CR_Alnum[] = {
0x10f00, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11000, 0x11045,
0x11066, 0x1106f,
- 0x11082, 0x110b8,
+ 0x11071, 0x11075,
+ 0x11080, 0x110b8,
+ 0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
0x11100, 0x11132,
@@ -4969,7 +5154,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x11200, 0x11211,
0x11213, 0x11234,
0x11237, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -5012,6 +5197,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x11700, 0x1171a,
0x1171d, 0x1172a,
0x11730, 0x11739,
+ 0x11740, 0x11746,
0x11800, 0x11838,
0x118a0, 0x118e9,
0x118ff, 0x11906,
@@ -5032,7 +5218,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x11a35, 0x11a3e,
0x11a50, 0x11a97,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c3e,
@@ -5058,15 +5244,23 @@ static const OnigCodePoint CR_Alnum[] = {
0x11d98, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f40,
+ 0x11f50, 0x11f59,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16b00, 0x16b2f,
0x16b40, 0x16b43,
@@ -5083,8 +5277,13 @@ static const OnigCodePoint CR_Alnum[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -5123,17 +5322,28 @@ static const OnigCodePoint CR_Alnum[] = {
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
0x1d7ce, 0x1d7ff,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
0x1e2f0, 0x1e2f9,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e4f0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e900, 0x1e943,
0x1e947, 0x1e947,
@@ -5176,13 +5386,14 @@ static const OnigCodePoint CR_Alnum[] = {
0x1f150, 0x1f169,
0x1f170, 0x1f189,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Alnum */
/* 'ASCII': [[:ASCII:]] */
@@ -5193,7 +5404,7 @@ static const OnigCodePoint CR_ASCII[] = {
/* 'Punct' */
static const OnigCodePoint CR_Punct[] = {
- 185,
+ 191,
0x0021, 0x0023,
0x0025, 0x002a,
0x002c, 0x002f,
@@ -5221,7 +5432,7 @@ static const OnigCodePoint CR_Punct[] = {
0x0609, 0x060a,
0x060c, 0x060d,
0x061b, 0x061b,
- 0x061e, 0x061f,
+ 0x061d, 0x061f,
0x066a, 0x066d,
0x06d4, 0x06d4,
0x0700, 0x070d,
@@ -5260,6 +5471,7 @@ static const OnigCodePoint CR_Punct[] = {
0x1aa0, 0x1aa6,
0x1aa8, 0x1aad,
0x1b5a, 0x1b60,
+ 0x1b7d, 0x1b7e,
0x1bfc, 0x1bff,
0x1c3b, 0x1c3f,
0x1c7e, 0x1c7f,
@@ -5284,7 +5496,7 @@ static const OnigCodePoint CR_Punct[] = {
0x2d70, 0x2d70,
0x2e00, 0x2e2e,
0x2e30, 0x2e4f,
- 0x2e52, 0x2e52,
+ 0x2e52, 0x2e5d,
0x3001, 0x3003,
0x3008, 0x3011,
0x3014, 0x301f,
@@ -5340,6 +5552,7 @@ static const OnigCodePoint CR_Punct[] = {
0x10b99, 0x10b9c,
0x10ead, 0x10ead,
0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
0x11047, 0x1104d,
0x110bb, 0x110bc,
0x110be, 0x110c1,
@@ -5358,6 +5571,7 @@ static const OnigCodePoint CR_Punct[] = {
0x115c1, 0x115d7,
0x11641, 0x11643,
0x11660, 0x1166c,
+ 0x116b9, 0x116b9,
0x1173c, 0x1173e,
0x1183b, 0x1183b,
0x11944, 0x11946,
@@ -5365,11 +5579,14 @@ static const OnigCodePoint CR_Punct[] = {
0x11a3f, 0x11a46,
0x11a9a, 0x11a9c,
0x11a9e, 0x11aa2,
+ 0x11b00, 0x11b09,
0x11c41, 0x11c45,
0x11c70, 0x11c71,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f4f,
0x11fff, 0x11fff,
0x12470, 0x12474,
+ 0x12ff1, 0x12ff2,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
0x16b37, 0x16b3b,
@@ -5390,7 +5607,7 @@ static const OnigCodePoint CR_Any[] = {
/* 'Assigned': - */
static const OnigCodePoint CR_Assigned[] = {
- 677,
+ 707,
0x0000, 0x0377,
0x037a, 0x037f,
0x0384, 0x038a,
@@ -5403,8 +5620,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x0591, 0x05c7,
0x05d0, 0x05ea,
0x05ef, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
+ 0x0600, 0x070d,
0x070f, 0x074a,
0x074d, 0x07b1,
0x07c0, 0x07fa,
@@ -5413,9 +5629,9 @@ static const OnigCodePoint CR_Assigned[] = {
0x0840, 0x085b,
0x085e, 0x085e,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x0983,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
0x0985, 0x098c,
0x098f, 0x0990,
0x0993, 0x09a8,
@@ -5493,11 +5709,12 @@ static const OnigCodePoint CR_Assigned[] = {
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c77, 0x0c8c,
@@ -5509,10 +5726,10 @@ static const OnigCodePoint CR_Assigned[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -5542,7 +5759,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f47,
@@ -5576,9 +5793,8 @@ static const OnigCodePoint CR_Assigned[] = {
0x13f8, 0x13fd,
0x1400, 0x169c,
0x16a0, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
+ 0x1700, 0x1715,
+ 0x171f, 0x1736,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -5586,8 +5802,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x1780, 0x17dd,
0x17e0, 0x17e9,
0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
+ 0x1800, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x18b0, 0x18f5,
@@ -5606,9 +5821,9 @@ static const OnigCodePoint CR_Assigned[] = {
0x1a7f, 0x1a89,
0x1a90, 0x1a99,
0x1aa0, 0x1aad,
- 0x1ab0, 0x1ac0,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
+ 0x1ab0, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
0x1b80, 0x1bf3,
0x1bfc, 0x1c37,
0x1c3b, 0x1c49,
@@ -5616,8 +5831,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x1c90, 0x1cba,
0x1cbd, 0x1cc7,
0x1cd0, 0x1cfa,
- 0x1d00, 0x1df9,
- 0x1dfb, 0x1f15,
+ 0x1d00, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
0x1f48, 0x1f4d,
@@ -5637,16 +5851,14 @@ static const OnigCodePoint CR_Assigned[] = {
0x2066, 0x2071,
0x2074, 0x208e,
0x2090, 0x209c,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0x20d0, 0x20f0,
0x2100, 0x218b,
0x2190, 0x2426,
0x2440, 0x244a,
0x2460, 0x2b73,
0x2b76, 0x2b95,
- 0x2b97, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2cf3,
+ 0x2b97, 0x2cf3,
0x2cf9, 0x2d25,
0x2d27, 0x2d27,
0x2d2d, 0x2d2d,
@@ -5661,7 +5873,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x2dc8, 0x2dce,
0x2dd0, 0x2dd6,
0x2dd8, 0x2dde,
- 0x2de0, 0x2e52,
+ 0x2de0, 0x2e5d,
0x2e80, 0x2e99,
0x2e9b, 0x2ef3,
0x2f00, 0x2fd5,
@@ -5673,14 +5885,15 @@ static const OnigCodePoint CR_Assigned[] = {
0x3131, 0x318e,
0x3190, 0x31e3,
0x31f0, 0x321e,
- 0x3220, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x3220, 0xa48c,
0xa490, 0xa4c6,
0xa4d0, 0xa62b,
0xa640, 0xa6f7,
- 0xa700, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa82c,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa82c,
0xa830, 0xa839,
0xa840, 0xa877,
0xa880, 0xa8c5,
@@ -5715,12 +5928,11 @@ static const OnigCodePoint CR_Assigned[] = {
0xfb3e, 0xfb3e,
0xfb40, 0xfb41,
0xfb43, 0xfb44,
- 0xfb46, 0xfbc1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
+ 0xfb46, 0xfbc2,
+ 0xfbd3, 0xfd8f,
0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
- 0xfe00, 0xfe19,
+ 0xfdcf, 0xfdcf,
+ 0xfdf0, 0xfe19,
0xfe20, 0xfe52,
0xfe54, 0xfe66,
0xfe68, 0xfe6b,
@@ -5763,10 +5975,20 @@ static const OnigCodePoint CR_Assigned[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
- 0x1056f, 0x1056f,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -5808,13 +6030,14 @@ static const OnigCodePoint CR_Assigned[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10ead,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
+ 0x10efd, 0x10f27,
0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
0x10fb0, 0x10fcb,
0x10fe0, 0x10ff6,
0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
0x110cd, 0x110cd,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
@@ -5824,7 +6047,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x11180, 0x111df,
0x111e1, 0x111f4,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -5856,11 +6079,11 @@ static const OnigCodePoint CR_Assigned[] = {
0x11600, 0x11644,
0x11650, 0x11659,
0x11660, 0x1166c,
- 0x11680, 0x116b8,
+ 0x11680, 0x116b9,
0x116c0, 0x116c9,
0x11700, 0x1171a,
0x1171d, 0x1172b,
- 0x11730, 0x1173f,
+ 0x11730, 0x11746,
0x11800, 0x1183b,
0x118a0, 0x118f2,
0x118ff, 0x11906,
@@ -5876,7 +6099,8 @@ static const OnigCodePoint CR_Assigned[] = {
0x119da, 0x119e4,
0x11a00, 0x11a47,
0x11a50, 0x11aa2,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c45,
@@ -5898,19 +6122,23 @@ static const OnigCodePoint CR_Assigned[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
0x12400, 0x1246e,
0x12470, 0x12474,
0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af0, 0x16af5,
0x16b00, 0x16b45,
@@ -5927,8 +6155,13 @@ static const OnigCodePoint CR_Assigned[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -5936,10 +6169,14 @@ static const OnigCodePoint CR_Assigned[] = {
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
- 0x1d129, 0x1d1e8,
+ 0x1d129, 0x1d1ea,
0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -5966,17 +6203,27 @@ static const OnigCodePoint CR_Assigned[] = {
0x1d7ce, 0x1da8b,
0x1da9b, 0x1da9f,
0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e130, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8c7, 0x1e8d6,
0x1e900, 0x1e94b,
@@ -6031,38 +6278,38 @@ static const OnigCodePoint CR_Assigned[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0001, 0xe0001,
0xe0020, 0xe007f,
0xe0100, 0xe01ef,
@@ -6072,7 +6319,7 @@ static const OnigCodePoint CR_Assigned[] = {
/* 'C': Major Category */
static const OnigCodePoint CR_C[] = {
- 679,
+ 712,
0x0000, 0x001f,
0x007f, 0x009f,
0x00ad, 0x00ad,
@@ -6088,7 +6335,7 @@ static const OnigCodePoint CR_C[] = {
0x05c8, 0x05cf,
0x05eb, 0x05ee,
0x05f5, 0x0605,
- 0x061c, 0x061d,
+ 0x061c, 0x061c,
0x06dd, 0x06dd,
0x070e, 0x070f,
0x074b, 0x074c,
@@ -6098,9 +6345,8 @@ static const OnigCodePoint CR_C[] = {
0x083f, 0x083f,
0x085c, 0x085d,
0x085f, 0x085f,
- 0x086b, 0x089f,
- 0x08b5, 0x08b5,
- 0x08c8, 0x08d2,
+ 0x086b, 0x086f,
+ 0x088f, 0x0897,
0x08e2, 0x08e2,
0x0984, 0x0984,
0x098d, 0x098e,
@@ -6179,12 +6425,13 @@ static const OnigCodePoint CR_C[] = {
0x0c0d, 0x0c0d,
0x0c11, 0x0c11,
0x0c29, 0x0c29,
- 0x0c3a, 0x0c3c,
+ 0x0c3a, 0x0c3b,
0x0c45, 0x0c45,
0x0c49, 0x0c49,
0x0c4e, 0x0c54,
0x0c57, 0x0c57,
- 0x0c5b, 0x0c5f,
+ 0x0c5b, 0x0c5c,
+ 0x0c5e, 0x0c5f,
0x0c64, 0x0c65,
0x0c70, 0x0c76,
0x0c8d, 0x0c8d,
@@ -6195,11 +6442,11 @@ static const OnigCodePoint CR_C[] = {
0x0cc5, 0x0cc5,
0x0cc9, 0x0cc9,
0x0cce, 0x0cd4,
- 0x0cd7, 0x0cdd,
+ 0x0cd7, 0x0cdc,
0x0cdf, 0x0cdf,
0x0ce4, 0x0ce5,
0x0cf0, 0x0cf0,
- 0x0cf3, 0x0cff,
+ 0x0cf4, 0x0cff,
0x0d0d, 0x0d0d,
0x0d11, 0x0d11,
0x0d45, 0x0d45,
@@ -6229,7 +6476,7 @@ static const OnigCodePoint CR_C[] = {
0x0ebe, 0x0ebf,
0x0ec5, 0x0ec5,
0x0ec7, 0x0ec7,
- 0x0ece, 0x0ecf,
+ 0x0ecf, 0x0ecf,
0x0eda, 0x0edb,
0x0ee0, 0x0eff,
0x0f48, 0x0f48,
@@ -6263,8 +6510,7 @@ static const OnigCodePoint CR_C[] = {
0x13fe, 0x13ff,
0x169d, 0x169f,
0x16f9, 0x16ff,
- 0x170d, 0x170d,
- 0x1715, 0x171f,
+ 0x1716, 0x171e,
0x1737, 0x173f,
0x1754, 0x175f,
0x176d, 0x176d,
@@ -6273,7 +6519,7 @@ static const OnigCodePoint CR_C[] = {
0x17de, 0x17df,
0x17ea, 0x17ef,
0x17fa, 0x17ff,
- 0x180e, 0x180f,
+ 0x180e, 0x180e,
0x181a, 0x181f,
0x1879, 0x187f,
0x18ab, 0x18af,
@@ -6293,9 +6539,9 @@ static const OnigCodePoint CR_C[] = {
0x1a8a, 0x1a8f,
0x1a9a, 0x1a9f,
0x1aae, 0x1aaf,
- 0x1ac1, 0x1aff,
- 0x1b4c, 0x1b4f,
- 0x1b7d, 0x1b7f,
+ 0x1acf, 0x1aff,
+ 0x1b4d, 0x1b4f,
+ 0x1b7f, 0x1b7f,
0x1bf4, 0x1bfb,
0x1c38, 0x1c3a,
0x1c4a, 0x1c4c,
@@ -6303,7 +6549,6 @@ static const OnigCodePoint CR_C[] = {
0x1cbb, 0x1cbc,
0x1cc8, 0x1ccf,
0x1cfb, 0x1cff,
- 0x1dfa, 0x1dfa,
0x1f16, 0x1f17,
0x1f1e, 0x1f1f,
0x1f46, 0x1f47,
@@ -6326,15 +6571,13 @@ static const OnigCodePoint CR_C[] = {
0x2072, 0x2073,
0x208f, 0x208f,
0x209d, 0x209f,
- 0x20c0, 0x20cf,
+ 0x20c1, 0x20cf,
0x20f1, 0x20ff,
0x218c, 0x218f,
0x2427, 0x243f,
0x244b, 0x245f,
0x2b74, 0x2b75,
0x2b96, 0x2b96,
- 0x2c2f, 0x2c2f,
- 0x2c5f, 0x2c5f,
0x2cf4, 0x2cf8,
0x2d26, 0x2d26,
0x2d28, 0x2d2c,
@@ -6350,7 +6593,7 @@ static const OnigCodePoint CR_C[] = {
0x2dcf, 0x2dcf,
0x2dd7, 0x2dd7,
0x2ddf, 0x2ddf,
- 0x2e53, 0x2e7f,
+ 0x2e5e, 0x2e7f,
0x2e9a, 0x2e9a,
0x2ef4, 0x2eff,
0x2fd6, 0x2fef,
@@ -6362,13 +6605,14 @@ static const OnigCodePoint CR_C[] = {
0x318f, 0x318f,
0x31e4, 0x31ef,
0x321f, 0x321f,
- 0x9ffd, 0x9fff,
0xa48d, 0xa48f,
0xa4c7, 0xa4cf,
0xa62c, 0xa63f,
0xa6f8, 0xa6ff,
- 0xa7c0, 0xa7c1,
- 0xa7cb, 0xa7f4,
+ 0xa7cb, 0xa7cf,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7da, 0xa7f1,
0xa82d, 0xa82f,
0xa83a, 0xa83f,
0xa878, 0xa87f,
@@ -6404,11 +6648,10 @@ static const OnigCodePoint CR_C[] = {
0xfb3f, 0xfb3f,
0xfb42, 0xfb42,
0xfb45, 0xfb45,
- 0xfbc2, 0xfbd2,
- 0xfd40, 0xfd4f,
+ 0xfbc3, 0xfbd2,
0xfd90, 0xfd91,
- 0xfdc8, 0xfdef,
- 0xfdfe, 0xfdff,
+ 0xfdc8, 0xfdce,
+ 0xfdd0, 0xfdef,
0xfe1a, 0xfe1f,
0xfe53, 0xfe53,
0xfe67, 0xfe67,
@@ -6451,10 +6694,20 @@ static const OnigCodePoint CR_C[] = {
0x104fc, 0x104ff,
0x10528, 0x1052f,
0x10564, 0x1056e,
- 0x10570, 0x105ff,
+ 0x1057b, 0x1057b,
+ 0x1058b, 0x1058b,
+ 0x10593, 0x10593,
+ 0x10596, 0x10596,
+ 0x105a2, 0x105a2,
+ 0x105b2, 0x105b2,
+ 0x105ba, 0x105ba,
+ 0x105bd, 0x105ff,
0x10737, 0x1073f,
0x10756, 0x1075f,
- 0x10768, 0x107ff,
+ 0x10768, 0x1077f,
+ 0x10786, 0x10786,
+ 0x107b1, 0x107b1,
+ 0x107bb, 0x107ff,
0x10806, 0x10807,
0x10809, 0x10809,
0x10836, 0x10836,
@@ -6495,15 +6748,16 @@ static const OnigCodePoint CR_C[] = {
0x10e7f, 0x10e7f,
0x10eaa, 0x10eaa,
0x10eae, 0x10eaf,
- 0x10eb2, 0x10eff,
+ 0x10eb2, 0x10efc,
0x10f28, 0x10f2f,
- 0x10f5a, 0x10faf,
+ 0x10f5a, 0x10f6f,
+ 0x10f8a, 0x10faf,
0x10fcc, 0x10fdf,
0x10ff7, 0x10fff,
0x1104e, 0x11051,
- 0x11070, 0x1107e,
+ 0x11076, 0x1107e,
0x110bd, 0x110bd,
- 0x110c2, 0x110cf,
+ 0x110c3, 0x110cf,
0x110e9, 0x110ef,
0x110fa, 0x110ff,
0x11135, 0x11135,
@@ -6512,7 +6766,7 @@ static const OnigCodePoint CR_C[] = {
0x111e0, 0x111e0,
0x111f5, 0x111ff,
0x11212, 0x11212,
- 0x1123f, 0x1127f,
+ 0x11242, 0x1127f,
0x11287, 0x11287,
0x11289, 0x11289,
0x1128e, 0x1128e,
@@ -6544,11 +6798,11 @@ static const OnigCodePoint CR_C[] = {
0x11645, 0x1164f,
0x1165a, 0x1165f,
0x1166d, 0x1167f,
- 0x116b9, 0x116bf,
+ 0x116ba, 0x116bf,
0x116ca, 0x116ff,
0x1171b, 0x1171c,
0x1172c, 0x1172f,
- 0x11740, 0x117ff,
+ 0x11747, 0x117ff,
0x1183c, 0x1189f,
0x118f3, 0x118fe,
0x11907, 0x11908,
@@ -6563,8 +6817,9 @@ static const OnigCodePoint CR_C[] = {
0x119d8, 0x119d9,
0x119e5, 0x119ff,
0x11a48, 0x11a4f,
- 0x11aa3, 0x11abf,
- 0x11af9, 0x11bff,
+ 0x11aa3, 0x11aaf,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11bff,
0x11c09, 0x11c09,
0x11c37, 0x11c37,
0x11c46, 0x11c4f,
@@ -6585,19 +6840,25 @@ static const OnigCodePoint CR_C[] = {
0x11d92, 0x11d92,
0x11d99, 0x11d9f,
0x11daa, 0x11edf,
- 0x11ef9, 0x11faf,
+ 0x11ef9, 0x11eff,
+ 0x11f11, 0x11f11,
+ 0x11f3b, 0x11f3d,
+ 0x11f5a, 0x11faf,
0x11fb1, 0x11fbf,
0x11ff2, 0x11ffe,
0x1239a, 0x123ff,
0x1246f, 0x1246f,
0x12475, 0x1247f,
- 0x12544, 0x12fff,
- 0x1342f, 0x143ff,
+ 0x12544, 0x12f8f,
+ 0x12ff3, 0x12fff,
+ 0x13430, 0x1343f,
+ 0x13456, 0x143ff,
0x14647, 0x167ff,
0x16a39, 0x16a3f,
0x16a5f, 0x16a5f,
0x16a6a, 0x16a6d,
- 0x16a70, 0x16acf,
+ 0x16abf, 0x16abf,
+ 0x16aca, 0x16acf,
0x16aee, 0x16aef,
0x16af6, 0x16aff,
0x16b46, 0x16b4f,
@@ -6613,21 +6874,30 @@ static const OnigCodePoint CR_C[] = {
0x16ff2, 0x16fff,
0x187f8, 0x187ff,
0x18cd6, 0x18cff,
- 0x18d09, 0x1afff,
- 0x1b11f, 0x1b14f,
- 0x1b153, 0x1b163,
+ 0x18d09, 0x1afef,
+ 0x1aff4, 0x1aff4,
+ 0x1affc, 0x1affc,
+ 0x1afff, 0x1afff,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
0x1b168, 0x1b16f,
0x1b2fc, 0x1bbff,
0x1bc6b, 0x1bc6f,
0x1bc7d, 0x1bc7f,
0x1bc89, 0x1bc8f,
0x1bc9a, 0x1bc9b,
- 0x1bca0, 0x1cfff,
+ 0x1bca0, 0x1ceff,
+ 0x1cf2e, 0x1cf2f,
+ 0x1cf47, 0x1cf4f,
+ 0x1cfc4, 0x1cfff,
0x1d0f6, 0x1d0ff,
0x1d127, 0x1d128,
0x1d173, 0x1d17a,
- 0x1d1e9, 0x1d1ff,
- 0x1d246, 0x1d2df,
+ 0x1d1eb, 0x1d1ff,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
0x1d2f4, 0x1d2ff,
0x1d357, 0x1d35f,
0x1d379, 0x1d3ff,
@@ -6653,18 +6923,28 @@ static const OnigCodePoint CR_C[] = {
0x1d7cc, 0x1d7cd,
0x1da8c, 0x1da9a,
0x1daa0, 0x1daa0,
- 0x1dab0, 0x1dfff,
+ 0x1dab0, 0x1deff,
+ 0x1df1f, 0x1df24,
+ 0x1df2b, 0x1dfff,
0x1e007, 0x1e007,
0x1e019, 0x1e01a,
0x1e022, 0x1e022,
0x1e025, 0x1e025,
- 0x1e02b, 0x1e0ff,
+ 0x1e02b, 0x1e02f,
+ 0x1e06e, 0x1e08e,
+ 0x1e090, 0x1e0ff,
0x1e12d, 0x1e12f,
0x1e13e, 0x1e13f,
0x1e14a, 0x1e14d,
- 0x1e150, 0x1e2bf,
+ 0x1e150, 0x1e28f,
+ 0x1e2af, 0x1e2bf,
0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e7ff,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e7df,
+ 0x1e7e7, 0x1e7e7,
+ 0x1e7ec, 0x1e7ec,
+ 0x1e7ef, 0x1e7ef,
+ 0x1e7ff, 0x1e7ff,
0x1e8c5, 0x1e8c6,
0x1e8d7, 0x1e8ff,
0x1e94c, 0x1e94f,
@@ -6718,39 +6998,39 @@ static const OnigCodePoint CR_C[] = {
0x1f249, 0x1f24f,
0x1f252, 0x1f25f,
0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6df,
+ 0x1f6d8, 0x1f6db,
0x1f6ed, 0x1f6ef,
0x1f6fd, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d9, 0x1f7df,
- 0x1f7ec, 0x1f7ff,
+ 0x1f777, 0x1f77a,
+ 0x1f7da, 0x1f7df,
+ 0x1f7ec, 0x1f7ef,
+ 0x1f7f1, 0x1f7ff,
0x1f80c, 0x1f80f,
0x1f848, 0x1f84f,
0x1f85a, 0x1f85f,
0x1f888, 0x1f88f,
0x1f8ae, 0x1f8af,
0x1f8b2, 0x1f8ff,
- 0x1f979, 0x1f979,
- 0x1f9cc, 0x1f9cc,
0x1fa54, 0x1fa5f,
0x1fa6e, 0x1fa6f,
- 0x1fa75, 0x1fa77,
- 0x1fa7b, 0x1fa7f,
- 0x1fa87, 0x1fa8f,
- 0x1faa9, 0x1faaf,
- 0x1fab7, 0x1fabf,
- 0x1fac3, 0x1facf,
- 0x1fad7, 0x1faff,
+ 0x1fa7d, 0x1fa7f,
+ 0x1fa89, 0x1fa8f,
+ 0x1fabe, 0x1fabe,
+ 0x1fac6, 0x1facd,
+ 0x1fadc, 0x1fadf,
+ 0x1fae9, 0x1faef,
+ 0x1faf9, 0x1faff,
0x1fb93, 0x1fb93,
0x1fbcb, 0x1fbef,
0x1fbfa, 0x1ffff,
- 0x2a6de, 0x2a6ff,
- 0x2b735, 0x2b73f,
+ 0x2a6e0, 0x2a6ff,
+ 0x2b73a, 0x2b73f,
0x2b81e, 0x2b81f,
0x2cea2, 0x2ceaf,
0x2ebe1, 0x2f7ff,
0x2fa1e, 0x2ffff,
- 0x3134b, 0xe00ff,
+ 0x3134b, 0x3134f,
+ 0x323b0, 0xe00ff,
0xe01f0, 0x10ffff,
}; /* CR_C */
@@ -6759,12 +7039,13 @@ static const OnigCodePoint CR_C[] = {
/* 'Cf': General Category */
static const OnigCodePoint CR_Cf[] = {
- 20,
+ 21,
0x00ad, 0x00ad,
0x0600, 0x0605,
0x061c, 0x061c,
0x06dd, 0x06dd,
0x070f, 0x070f,
+ 0x0890, 0x0891,
0x08e2, 0x08e2,
0x180e, 0x180e,
0x200b, 0x200f,
@@ -6775,7 +7056,7 @@ static const OnigCodePoint CR_Cf[] = {
0xfff9, 0xfffb,
0x110bd, 0x110bd,
0x110cd, 0x110cd,
- 0x13430, 0x13438,
+ 0x13430, 0x1343f,
0x1bca0, 0x1bca3,
0x1d173, 0x1d17a,
0xe0001, 0xe0001,
@@ -6784,7 +7065,7 @@ static const OnigCodePoint CR_Cf[] = {
/* 'Cn': General Category */
static const OnigCodePoint CR_Cn[] = {
- 677,
+ 707,
0x0378, 0x0379,
0x0380, 0x0383,
0x038b, 0x038b,
@@ -6797,7 +7078,6 @@ static const OnigCodePoint CR_Cn[] = {
0x05c8, 0x05cf,
0x05eb, 0x05ee,
0x05f5, 0x05ff,
- 0x061d, 0x061d,
0x070e, 0x070e,
0x074b, 0x074c,
0x07b2, 0x07bf,
@@ -6806,9 +7086,9 @@ static const OnigCodePoint CR_Cn[] = {
0x083f, 0x083f,
0x085c, 0x085d,
0x085f, 0x085f,
- 0x086b, 0x089f,
- 0x08b5, 0x08b5,
- 0x08c8, 0x08d2,
+ 0x086b, 0x086f,
+ 0x088f, 0x088f,
+ 0x0892, 0x0897,
0x0984, 0x0984,
0x098d, 0x098e,
0x0991, 0x0992,
@@ -6886,12 +7166,13 @@ static const OnigCodePoint CR_Cn[] = {
0x0c0d, 0x0c0d,
0x0c11, 0x0c11,
0x0c29, 0x0c29,
- 0x0c3a, 0x0c3c,
+ 0x0c3a, 0x0c3b,
0x0c45, 0x0c45,
0x0c49, 0x0c49,
0x0c4e, 0x0c54,
0x0c57, 0x0c57,
- 0x0c5b, 0x0c5f,
+ 0x0c5b, 0x0c5c,
+ 0x0c5e, 0x0c5f,
0x0c64, 0x0c65,
0x0c70, 0x0c76,
0x0c8d, 0x0c8d,
@@ -6902,11 +7183,11 @@ static const OnigCodePoint CR_Cn[] = {
0x0cc5, 0x0cc5,
0x0cc9, 0x0cc9,
0x0cce, 0x0cd4,
- 0x0cd7, 0x0cdd,
+ 0x0cd7, 0x0cdc,
0x0cdf, 0x0cdf,
0x0ce4, 0x0ce5,
0x0cf0, 0x0cf0,
- 0x0cf3, 0x0cff,
+ 0x0cf4, 0x0cff,
0x0d0d, 0x0d0d,
0x0d11, 0x0d11,
0x0d45, 0x0d45,
@@ -6936,7 +7217,7 @@ static const OnigCodePoint CR_Cn[] = {
0x0ebe, 0x0ebf,
0x0ec5, 0x0ec5,
0x0ec7, 0x0ec7,
- 0x0ece, 0x0ecf,
+ 0x0ecf, 0x0ecf,
0x0eda, 0x0edb,
0x0ee0, 0x0eff,
0x0f48, 0x0f48,
@@ -6970,8 +7251,7 @@ static const OnigCodePoint CR_Cn[] = {
0x13fe, 0x13ff,
0x169d, 0x169f,
0x16f9, 0x16ff,
- 0x170d, 0x170d,
- 0x1715, 0x171f,
+ 0x1716, 0x171e,
0x1737, 0x173f,
0x1754, 0x175f,
0x176d, 0x176d,
@@ -6980,7 +7260,6 @@ static const OnigCodePoint CR_Cn[] = {
0x17de, 0x17df,
0x17ea, 0x17ef,
0x17fa, 0x17ff,
- 0x180f, 0x180f,
0x181a, 0x181f,
0x1879, 0x187f,
0x18ab, 0x18af,
@@ -7000,9 +7279,9 @@ static const OnigCodePoint CR_Cn[] = {
0x1a8a, 0x1a8f,
0x1a9a, 0x1a9f,
0x1aae, 0x1aaf,
- 0x1ac1, 0x1aff,
- 0x1b4c, 0x1b4f,
- 0x1b7d, 0x1b7f,
+ 0x1acf, 0x1aff,
+ 0x1b4d, 0x1b4f,
+ 0x1b7f, 0x1b7f,
0x1bf4, 0x1bfb,
0x1c38, 0x1c3a,
0x1c4a, 0x1c4c,
@@ -7010,7 +7289,6 @@ static const OnigCodePoint CR_Cn[] = {
0x1cbb, 0x1cbc,
0x1cc8, 0x1ccf,
0x1cfb, 0x1cff,
- 0x1dfa, 0x1dfa,
0x1f16, 0x1f17,
0x1f1e, 0x1f1f,
0x1f46, 0x1f47,
@@ -7031,15 +7309,13 @@ static const OnigCodePoint CR_Cn[] = {
0x2072, 0x2073,
0x208f, 0x208f,
0x209d, 0x209f,
- 0x20c0, 0x20cf,
+ 0x20c1, 0x20cf,
0x20f1, 0x20ff,
0x218c, 0x218f,
0x2427, 0x243f,
0x244b, 0x245f,
0x2b74, 0x2b75,
0x2b96, 0x2b96,
- 0x2c2f, 0x2c2f,
- 0x2c5f, 0x2c5f,
0x2cf4, 0x2cf8,
0x2d26, 0x2d26,
0x2d28, 0x2d2c,
@@ -7055,7 +7331,7 @@ static const OnigCodePoint CR_Cn[] = {
0x2dcf, 0x2dcf,
0x2dd7, 0x2dd7,
0x2ddf, 0x2ddf,
- 0x2e53, 0x2e7f,
+ 0x2e5e, 0x2e7f,
0x2e9a, 0x2e9a,
0x2ef4, 0x2eff,
0x2fd6, 0x2fef,
@@ -7067,13 +7343,14 @@ static const OnigCodePoint CR_Cn[] = {
0x318f, 0x318f,
0x31e4, 0x31ef,
0x321f, 0x321f,
- 0x9ffd, 0x9fff,
0xa48d, 0xa48f,
0xa4c7, 0xa4cf,
0xa62c, 0xa63f,
0xa6f8, 0xa6ff,
- 0xa7c0, 0xa7c1,
- 0xa7cb, 0xa7f4,
+ 0xa7cb, 0xa7cf,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7da, 0xa7f1,
0xa82d, 0xa82f,
0xa83a, 0xa83f,
0xa878, 0xa87f,
@@ -7109,11 +7386,10 @@ static const OnigCodePoint CR_Cn[] = {
0xfb3f, 0xfb3f,
0xfb42, 0xfb42,
0xfb45, 0xfb45,
- 0xfbc2, 0xfbd2,
- 0xfd40, 0xfd4f,
+ 0xfbc3, 0xfbd2,
0xfd90, 0xfd91,
- 0xfdc8, 0xfdef,
- 0xfdfe, 0xfdff,
+ 0xfdc8, 0xfdce,
+ 0xfdd0, 0xfdef,
0xfe1a, 0xfe1f,
0xfe53, 0xfe53,
0xfe67, 0xfe67,
@@ -7157,10 +7433,20 @@ static const OnigCodePoint CR_Cn[] = {
0x104fc, 0x104ff,
0x10528, 0x1052f,
0x10564, 0x1056e,
- 0x10570, 0x105ff,
+ 0x1057b, 0x1057b,
+ 0x1058b, 0x1058b,
+ 0x10593, 0x10593,
+ 0x10596, 0x10596,
+ 0x105a2, 0x105a2,
+ 0x105b2, 0x105b2,
+ 0x105ba, 0x105ba,
+ 0x105bd, 0x105ff,
0x10737, 0x1073f,
0x10756, 0x1075f,
- 0x10768, 0x107ff,
+ 0x10768, 0x1077f,
+ 0x10786, 0x10786,
+ 0x107b1, 0x107b1,
+ 0x107bb, 0x107ff,
0x10806, 0x10807,
0x10809, 0x10809,
0x10836, 0x10836,
@@ -7201,14 +7487,15 @@ static const OnigCodePoint CR_Cn[] = {
0x10e7f, 0x10e7f,
0x10eaa, 0x10eaa,
0x10eae, 0x10eaf,
- 0x10eb2, 0x10eff,
+ 0x10eb2, 0x10efc,
0x10f28, 0x10f2f,
- 0x10f5a, 0x10faf,
+ 0x10f5a, 0x10f6f,
+ 0x10f8a, 0x10faf,
0x10fcc, 0x10fdf,
0x10ff7, 0x10fff,
0x1104e, 0x11051,
- 0x11070, 0x1107e,
- 0x110c2, 0x110cc,
+ 0x11076, 0x1107e,
+ 0x110c3, 0x110cc,
0x110ce, 0x110cf,
0x110e9, 0x110ef,
0x110fa, 0x110ff,
@@ -7218,7 +7505,7 @@ static const OnigCodePoint CR_Cn[] = {
0x111e0, 0x111e0,
0x111f5, 0x111ff,
0x11212, 0x11212,
- 0x1123f, 0x1127f,
+ 0x11242, 0x1127f,
0x11287, 0x11287,
0x11289, 0x11289,
0x1128e, 0x1128e,
@@ -7250,11 +7537,11 @@ static const OnigCodePoint CR_Cn[] = {
0x11645, 0x1164f,
0x1165a, 0x1165f,
0x1166d, 0x1167f,
- 0x116b9, 0x116bf,
+ 0x116ba, 0x116bf,
0x116ca, 0x116ff,
0x1171b, 0x1171c,
0x1172c, 0x1172f,
- 0x11740, 0x117ff,
+ 0x11747, 0x117ff,
0x1183c, 0x1189f,
0x118f3, 0x118fe,
0x11907, 0x11908,
@@ -7269,8 +7556,9 @@ static const OnigCodePoint CR_Cn[] = {
0x119d8, 0x119d9,
0x119e5, 0x119ff,
0x11a48, 0x11a4f,
- 0x11aa3, 0x11abf,
- 0x11af9, 0x11bff,
+ 0x11aa3, 0x11aaf,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11bff,
0x11c09, 0x11c09,
0x11c37, 0x11c37,
0x11c46, 0x11c4f,
@@ -7291,20 +7579,24 @@ static const OnigCodePoint CR_Cn[] = {
0x11d92, 0x11d92,
0x11d99, 0x11d9f,
0x11daa, 0x11edf,
- 0x11ef9, 0x11faf,
+ 0x11ef9, 0x11eff,
+ 0x11f11, 0x11f11,
+ 0x11f3b, 0x11f3d,
+ 0x11f5a, 0x11faf,
0x11fb1, 0x11fbf,
0x11ff2, 0x11ffe,
0x1239a, 0x123ff,
0x1246f, 0x1246f,
0x12475, 0x1247f,
- 0x12544, 0x12fff,
- 0x1342f, 0x1342f,
- 0x13439, 0x143ff,
+ 0x12544, 0x12f8f,
+ 0x12ff3, 0x12fff,
+ 0x13456, 0x143ff,
0x14647, 0x167ff,
0x16a39, 0x16a3f,
0x16a5f, 0x16a5f,
0x16a6a, 0x16a6d,
- 0x16a70, 0x16acf,
+ 0x16abf, 0x16abf,
+ 0x16aca, 0x16acf,
0x16aee, 0x16aef,
0x16af6, 0x16aff,
0x16b46, 0x16b4f,
@@ -7320,20 +7612,29 @@ static const OnigCodePoint CR_Cn[] = {
0x16ff2, 0x16fff,
0x187f8, 0x187ff,
0x18cd6, 0x18cff,
- 0x18d09, 0x1afff,
- 0x1b11f, 0x1b14f,
- 0x1b153, 0x1b163,
+ 0x18d09, 0x1afef,
+ 0x1aff4, 0x1aff4,
+ 0x1affc, 0x1affc,
+ 0x1afff, 0x1afff,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
0x1b168, 0x1b16f,
0x1b2fc, 0x1bbff,
0x1bc6b, 0x1bc6f,
0x1bc7d, 0x1bc7f,
0x1bc89, 0x1bc8f,
0x1bc9a, 0x1bc9b,
- 0x1bca4, 0x1cfff,
+ 0x1bca4, 0x1ceff,
+ 0x1cf2e, 0x1cf2f,
+ 0x1cf47, 0x1cf4f,
+ 0x1cfc4, 0x1cfff,
0x1d0f6, 0x1d0ff,
0x1d127, 0x1d128,
- 0x1d1e9, 0x1d1ff,
- 0x1d246, 0x1d2df,
+ 0x1d1eb, 0x1d1ff,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
0x1d2f4, 0x1d2ff,
0x1d357, 0x1d35f,
0x1d379, 0x1d3ff,
@@ -7359,18 +7660,28 @@ static const OnigCodePoint CR_Cn[] = {
0x1d7cc, 0x1d7cd,
0x1da8c, 0x1da9a,
0x1daa0, 0x1daa0,
- 0x1dab0, 0x1dfff,
+ 0x1dab0, 0x1deff,
+ 0x1df1f, 0x1df24,
+ 0x1df2b, 0x1dfff,
0x1e007, 0x1e007,
0x1e019, 0x1e01a,
0x1e022, 0x1e022,
0x1e025, 0x1e025,
- 0x1e02b, 0x1e0ff,
+ 0x1e02b, 0x1e02f,
+ 0x1e06e, 0x1e08e,
+ 0x1e090, 0x1e0ff,
0x1e12d, 0x1e12f,
0x1e13e, 0x1e13f,
0x1e14a, 0x1e14d,
- 0x1e150, 0x1e2bf,
+ 0x1e150, 0x1e28f,
+ 0x1e2af, 0x1e2bf,
0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e7ff,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e7df,
+ 0x1e7e7, 0x1e7e7,
+ 0x1e7ec, 0x1e7ec,
+ 0x1e7ef, 0x1e7ef,
+ 0x1e7ff, 0x1e7ff,
0x1e8c5, 0x1e8c6,
0x1e8d7, 0x1e8ff,
0x1e94c, 0x1e94f,
@@ -7424,39 +7735,39 @@ static const OnigCodePoint CR_Cn[] = {
0x1f249, 0x1f24f,
0x1f252, 0x1f25f,
0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6df,
+ 0x1f6d8, 0x1f6db,
0x1f6ed, 0x1f6ef,
0x1f6fd, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d9, 0x1f7df,
- 0x1f7ec, 0x1f7ff,
+ 0x1f777, 0x1f77a,
+ 0x1f7da, 0x1f7df,
+ 0x1f7ec, 0x1f7ef,
+ 0x1f7f1, 0x1f7ff,
0x1f80c, 0x1f80f,
0x1f848, 0x1f84f,
0x1f85a, 0x1f85f,
0x1f888, 0x1f88f,
0x1f8ae, 0x1f8af,
0x1f8b2, 0x1f8ff,
- 0x1f979, 0x1f979,
- 0x1f9cc, 0x1f9cc,
0x1fa54, 0x1fa5f,
0x1fa6e, 0x1fa6f,
- 0x1fa75, 0x1fa77,
- 0x1fa7b, 0x1fa7f,
- 0x1fa87, 0x1fa8f,
- 0x1faa9, 0x1faaf,
- 0x1fab7, 0x1fabf,
- 0x1fac3, 0x1facf,
- 0x1fad7, 0x1faff,
+ 0x1fa7d, 0x1fa7f,
+ 0x1fa89, 0x1fa8f,
+ 0x1fabe, 0x1fabe,
+ 0x1fac6, 0x1facd,
+ 0x1fadc, 0x1fadf,
+ 0x1fae9, 0x1faef,
+ 0x1faf9, 0x1faff,
0x1fb93, 0x1fb93,
0x1fbcb, 0x1fbef,
0x1fbfa, 0x1ffff,
- 0x2a6de, 0x2a6ff,
- 0x2b735, 0x2b73f,
+ 0x2a6e0, 0x2a6ff,
+ 0x2b73a, 0x2b73f,
0x2b81e, 0x2b81f,
0x2cea2, 0x2ceaf,
0x2ebe1, 0x2f7ff,
0x2fa1e, 0x2ffff,
- 0x3134b, 0xe0000,
+ 0x3134b, 0x3134f,
+ 0x323b0, 0xe0000,
0xe0002, 0xe001f,
0xe0080, 0xe00ff,
0xe01f0, 0xeffff,
@@ -7480,7 +7791,7 @@ static const OnigCodePoint CR_Cs[] = {
/* 'L': Major Category */
static const OnigCodePoint CR_L[] = {
- 622,
+ 659,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -7530,8 +7841,9 @@ static const OnigCodePoint CR_L[] = {
0x0828, 0x0828,
0x0840, 0x0858,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x08a0, 0x08c9,
0x0904, 0x0939,
0x093d, 0x093d,
0x0950, 0x0950,
@@ -7596,6 +7908,7 @@ static const OnigCodePoint CR_L[] = {
0x0c2a, 0x0c39,
0x0c3d, 0x0c3d,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c61,
0x0c80, 0x0c80,
0x0c85, 0x0c8c,
@@ -7604,7 +7917,7 @@ static const OnigCodePoint CR_L[] = {
0x0caa, 0x0cb3,
0x0cb5, 0x0cb9,
0x0cbd, 0x0cbd,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce1,
0x0cf1, 0x0cf2,
0x0d04, 0x0d0c,
@@ -7675,9 +7988,8 @@ static const OnigCodePoint CR_L[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16f1, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1711,
- 0x1720, 0x1731,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
0x1740, 0x1751,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -7698,7 +8010,7 @@ static const OnigCodePoint CR_L[] = {
0x1a20, 0x1a54,
0x1aa7, 0x1aa7,
0x1b05, 0x1b33,
- 0x1b45, 0x1b4b,
+ 0x1b45, 0x1b4c,
0x1b83, 0x1ba0,
0x1bae, 0x1baf,
0x1bba, 0x1be5,
@@ -7749,9 +8061,7 @@ static const OnigCodePoint CR_L[] = {
0x2145, 0x2149,
0x214e, 0x214e,
0x2183, 0x2184,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
0x2d00, 0x2d25,
@@ -7781,8 +8091,7 @@ static const OnigCodePoint CR_L[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa61f,
@@ -7792,9 +8101,11 @@ static const OnigCodePoint CR_L[] = {
0xa6a0, 0xa6e5,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa801,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa801,
0xa803, 0xa805,
0xa807, 0xa80a,
0xa80c, 0xa822,
@@ -7882,9 +8193,20 @@ static const OnigCodePoint CR_L[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -7920,9 +8242,12 @@ static const OnigCodePoint CR_L[] = {
0x10f00, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
0x11083, 0x110af,
0x110d0, 0x110e8,
0x11103, 0x11126,
@@ -7936,6 +8261,7 @@ static const OnigCodePoint CR_L[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -7964,6 +8290,7 @@ static const OnigCodePoint CR_L[] = {
0x11680, 0x116aa,
0x116b8, 0x116b8,
0x11700, 0x1171a,
+ 0x11740, 0x11746,
0x11800, 0x1182b,
0x118a0, 0x118df,
0x118ff, 0x11906,
@@ -7983,7 +8310,7 @@ static const OnigCodePoint CR_L[] = {
0x11a50, 0x11a50,
0x11a5c, 0x11a89,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c2e,
0x11c40, 0x11c40,
@@ -7997,13 +8324,19 @@ static const OnigCodePoint CR_L[] = {
0x11d6a, 0x11d89,
0x11d98, 0x11d98,
0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
0x16ad0, 0x16aed,
0x16b00, 0x16b2f,
0x16b40, 0x16b43,
@@ -8018,8 +8351,13 @@ static const OnigCodePoint CR_L[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -8056,10 +8394,19 @@ static const OnigCodePoint CR_L[] = {
0x1d78a, 0x1d7a8,
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e900, 0x1e943,
0x1e94b, 0x1e94b,
@@ -8096,18 +8443,19 @@ static const OnigCodePoint CR_L[] = {
0x1eea1, 0x1eea3,
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_L */
/* 'LC': General Category */
static const OnigCodePoint CR_LC[] = {
- 132,
+ 143,
0x0041, 0x005a,
0x0061, 0x007a,
0x00b5, 0x00b5,
@@ -8177,9 +8525,7 @@ static const OnigCodePoint CR_LC[] = {
0x2145, 0x2149,
0x214e, 0x214e,
0x2183, 0x2184,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2c7b,
+ 0x2c00, 0x2c7b,
0x2c7e, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
@@ -8191,8 +8537,10 @@ static const OnigCodePoint CR_LC[] = {
0xa722, 0xa76f,
0xa771, 0xa787,
0xa78b, 0xa78e,
- 0xa790, 0xa7bf,
- 0xa7c2, 0xa7ca,
+ 0xa790, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
0xa7f5, 0xa7f6,
0xa7fa, 0xa7fa,
0xab30, 0xab5a,
@@ -8205,6 +8553,14 @@ static const OnigCodePoint CR_LC[] = {
0x10400, 0x1044f,
0x104b0, 0x104d3,
0x104d8, 0x104fb,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10c80, 0x10cb2,
0x10cc0, 0x10cf2,
0x118a0, 0x118df,
@@ -8239,12 +8595,15 @@ static const OnigCodePoint CR_LC[] = {
0x1d78a, 0x1d7a8,
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e900, 0x1e943,
}; /* CR_LC */
/* 'Ll': General Category */
static const OnigCodePoint CR_Ll[] = {
- 645,
+ 658,
0x0061, 0x007a,
0x00b5, 0x00b5,
0x00df, 0x00f6,
@@ -8676,7 +9035,7 @@ static const OnigCodePoint CR_Ll[] = {
0x2146, 0x2149,
0x214e, 0x214e,
0x2184, 0x2184,
- 0x2c30, 0x2c5e,
+ 0x2c30, 0x2c5f,
0x2c61, 0x2c61,
0x2c65, 0x2c66,
0x2c68, 0x2c68,
@@ -8845,9 +9204,15 @@ static const OnigCodePoint CR_Ll[] = {
0xa7bb, 0xa7bb,
0xa7bd, 0xa7bd,
0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
0xa7c3, 0xa7c3,
0xa7c8, 0xa7c8,
0xa7ca, 0xa7ca,
+ 0xa7d1, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d5,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
0xa7f6, 0xa7f6,
0xa7fa, 0xa7fa,
0xab30, 0xab5a,
@@ -8858,6 +9223,10 @@ static const OnigCodePoint CR_Ll[] = {
0xff41, 0xff5a,
0x10428, 0x1044f,
0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10cc0, 0x10cf2,
0x118c0, 0x118df,
0x16e60, 0x16e7f,
@@ -8889,12 +9258,15 @@ static const OnigCodePoint CR_Ll[] = {
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7c9,
0x1d7cb, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e922, 0x1e943,
}; /* CR_Ll */
/* 'Lm': General Category */
static const OnigCodePoint CR_Lm[] = {
- 61,
+ 71,
0x02b0, 0x02c1,
0x02c6, 0x02d1,
0x02e0, 0x02e4,
@@ -8910,6 +9282,7 @@ static const OnigCodePoint CR_Lm[] = {
0x081a, 0x081a,
0x0824, 0x0824,
0x0828, 0x0828,
+ 0x08c9, 0x08c9,
0x0971, 0x0971,
0x0e46, 0x0e46,
0x0ec6, 0x0ec6,
@@ -8940,6 +9313,7 @@ static const OnigCodePoint CR_Lm[] = {
0xa717, 0xa71f,
0xa770, 0xa770,
0xa788, 0xa788,
+ 0xa7f2, 0xa7f4,
0xa7f8, 0xa7f9,
0xa9cf, 0xa9cf,
0xa9e6, 0xa9e6,
@@ -8950,17 +9324,25 @@ static const OnigCodePoint CR_Lm[] = {
0xab69, 0xab69,
0xff70, 0xff70,
0xff9e, 0xff9f,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x16b40, 0x16b43,
0x16f93, 0x16f9f,
0x16fe0, 0x16fe1,
0x16fe3, 0x16fe3,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1e030, 0x1e06d,
0x1e137, 0x1e13d,
+ 0x1e4eb, 0x1e4eb,
0x1e94b, 0x1e94b,
}; /* CR_Lm */
/* 'Lo': General Category */
static const OnigCodePoint CR_Lo[] = {
- 489,
+ 510,
0x00aa, 0x00aa,
0x00ba, 0x00ba,
0x01bb, 0x01bb,
@@ -8984,8 +9366,9 @@ static const OnigCodePoint CR_Lo[] = {
0x0800, 0x0815,
0x0840, 0x0858,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x08a0, 0x08c8,
0x0904, 0x0939,
0x093d, 0x093d,
0x0950, 0x0950,
@@ -9050,6 +9433,7 @@ static const OnigCodePoint CR_Lo[] = {
0x0c2a, 0x0c39,
0x0c3d, 0x0c3d,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c61,
0x0c80, 0x0c80,
0x0c85, 0x0c8c,
@@ -9058,7 +9442,7 @@ static const OnigCodePoint CR_Lo[] = {
0x0caa, 0x0cb3,
0x0cb5, 0x0cb9,
0x0cbd, 0x0cbd,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce1,
0x0cf1, 0x0cf2,
0x0d04, 0x0d0c,
@@ -9122,9 +9506,8 @@ static const OnigCodePoint CR_Lo[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16f1, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1711,
- 0x1720, 0x1731,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
0x1740, 0x1751,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -9144,7 +9527,7 @@ static const OnigCodePoint CR_Lo[] = {
0x1a00, 0x1a16,
0x1a20, 0x1a54,
0x1b05, 0x1b33,
- 0x1b45, 0x1b4b,
+ 0x1b45, 0x1b4c,
0x1b83, 0x1ba0,
0x1bae, 0x1baf,
0x1bba, 0x1be5,
@@ -9177,8 +9560,7 @@ static const OnigCodePoint CR_Lo[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa014,
+ 0x4e00, 0xa014,
0xa016, 0xa48c,
0xa4d0, 0xa4f7,
0xa500, 0xa60b,
@@ -9306,9 +9688,12 @@ static const OnigCodePoint CR_Lo[] = {
0x10f00, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
0x11083, 0x110af,
0x110d0, 0x110e8,
0x11103, 0x11126,
@@ -9322,6 +9707,7 @@ static const OnigCodePoint CR_Lo[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -9350,6 +9736,7 @@ static const OnigCodePoint CR_Lo[] = {
0x11680, 0x116aa,
0x116b8, 0x116b8,
0x11700, 0x1171a,
+ 0x11740, 0x11746,
0x11800, 0x1182b,
0x118ff, 0x11906,
0x11909, 0x11909,
@@ -9368,7 +9755,7 @@ static const OnigCodePoint CR_Lo[] = {
0x11a50, 0x11a50,
0x11a5c, 0x11a89,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c2e,
0x11c40, 0x11c40,
@@ -9382,13 +9769,19 @@ static const OnigCodePoint CR_Lo[] = {
0x11d6a, 0x11d89,
0x11d98, 0x11d98,
0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
0x16ad0, 0x16aed,
0x16b00, 0x16b2f,
0x16b63, 0x16b77,
@@ -9398,17 +9791,26 @@ static const OnigCodePoint CR_Lo[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
0x1bc70, 0x1bc7c,
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
+ 0x1df0a, 0x1df0a,
0x1e100, 0x1e12c,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4ea,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1ee00, 0x1ee03,
0x1ee05, 0x1ee1f,
@@ -9443,13 +9845,14 @@ static const OnigCodePoint CR_Lo[] = {
0x1eea1, 0x1eea3,
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Lo */
/* 'Lt': General Category */
@@ -9469,7 +9872,7 @@ static const OnigCodePoint CR_Lt[] = {
/* 'Lu': General Category */
static const OnigCodePoint CR_Lu[] = {
- 638,
+ 646,
0x0041, 0x005a,
0x00c0, 0x00d6,
0x00d8, 0x00de,
@@ -9901,7 +10304,7 @@ static const OnigCodePoint CR_Lu[] = {
0x213e, 0x213f,
0x2145, 0x2145,
0x2183, 0x2183,
- 0x2c00, 0x2c2e,
+ 0x2c00, 0x2c2f,
0x2c60, 0x2c60,
0x2c62, 0x2c64,
0x2c67, 0x2c67,
@@ -10066,13 +10469,21 @@ static const OnigCodePoint CR_Lu[] = {
0xa7ba, 0xa7ba,
0xa7bc, 0xa7bc,
0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
0xa7c2, 0xa7c2,
0xa7c4, 0xa7c7,
0xa7c9, 0xa7c9,
+ 0xa7d0, 0xa7d0,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
0xa7f5, 0xa7f5,
0xff21, 0xff3a,
0x10400, 0x10427,
0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
0x10c80, 0x10cb2,
0x118a0, 0x118bf,
0x16e40, 0x16e5f,
@@ -10112,7 +10523,7 @@ static const OnigCodePoint CR_Lu[] = {
/* 'M': Major Category */
static const OnigCodePoint CR_M[] = {
- 290,
+ 310,
0x0300, 0x036f,
0x0483, 0x0489,
0x0591, 0x05bd,
@@ -10137,7 +10548,8 @@ static const OnigCodePoint CR_M[] = {
0x0825, 0x0827,
0x0829, 0x082d,
0x0859, 0x085b,
- 0x08d3, 0x08e1,
+ 0x0898, 0x089f,
+ 0x08ca, 0x08e1,
0x08e3, 0x0903,
0x093a, 0x093c,
0x093e, 0x094f,
@@ -10179,6 +10591,7 @@ static const OnigCodePoint CR_M[] = {
0x0bca, 0x0bcd,
0x0bd7, 0x0bd7,
0x0c00, 0x0c04,
+ 0x0c3c, 0x0c3c,
0x0c3e, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
@@ -10191,6 +10604,7 @@ static const OnigCodePoint CR_M[] = {
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
0x0ce2, 0x0ce3,
+ 0x0cf3, 0x0cf3,
0x0d00, 0x0d03,
0x0d3b, 0x0d3c,
0x0d3e, 0x0d44,
@@ -10209,7 +10623,7 @@ static const OnigCodePoint CR_M[] = {
0x0e47, 0x0e4e,
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -10230,13 +10644,14 @@ static const OnigCodePoint CR_M[] = {
0x108f, 0x108f,
0x109a, 0x109d,
0x135d, 0x135f,
- 0x1712, 0x1714,
+ 0x1712, 0x1715,
0x1732, 0x1734,
0x1752, 0x1753,
0x1772, 0x1773,
0x17b4, 0x17d3,
0x17dd, 0x17dd,
0x180b, 0x180d,
+ 0x180f, 0x180f,
0x1885, 0x1886,
0x18a9, 0x18a9,
0x1920, 0x192b,
@@ -10245,7 +10660,7 @@ static const OnigCodePoint CR_M[] = {
0x1a55, 0x1a5e,
0x1a60, 0x1a7c,
0x1a7f, 0x1a7f,
- 0x1ab0, 0x1ac0,
+ 0x1ab0, 0x1ace,
0x1b00, 0x1b04,
0x1b34, 0x1b44,
0x1b6b, 0x1b73,
@@ -10258,8 +10673,7 @@ static const OnigCodePoint CR_M[] = {
0x1ced, 0x1ced,
0x1cf4, 0x1cf4,
0x1cf7, 0x1cf9,
- 0x1dc0, 0x1df9,
- 0x1dfb, 0x1dff,
+ 0x1dc0, 0x1dff,
0x20d0, 0x20f0,
0x2cef, 0x2cf1,
0x2d7f, 0x2d7f,
@@ -10311,11 +10725,16 @@ static const OnigCodePoint CR_M[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
0x11000, 0x11002,
0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
0x1107f, 0x11082,
0x110b0, 0x110ba,
+ 0x110c2, 0x110c2,
0x11100, 0x11102,
0x11127, 0x11134,
0x11145, 0x11146,
@@ -10326,6 +10745,7 @@ static const OnigCodePoint CR_M[] = {
0x111ce, 0x111cf,
0x1122c, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112ea,
0x11300, 0x11303,
0x1133b, 0x1133c,
@@ -10373,6 +10793,12 @@ static const OnigCodePoint CR_M[] = {
0x11d90, 0x11d91,
0x11d93, 0x11d97,
0x11ef3, 0x11ef6,
+ 0x11f00, 0x11f01,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16f4f, 0x16f4f,
@@ -10381,6 +10807,8 @@ static const OnigCodePoint CR_M[] = {
0x16fe4, 0x16fe4,
0x16ff0, 0x16ff1,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d165, 0x1d169,
0x1d16d, 0x1d172,
0x1d17b, 0x1d182,
@@ -10398,8 +10826,11 @@ static const OnigCodePoint CR_M[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
0x1e8d0, 0x1e8d6,
0x1e944, 0x1e94a,
0xe0100, 0xe01ef,
@@ -10407,7 +10838,7 @@ static const OnigCodePoint CR_M[] = {
/* 'Mc': General Category */
static const OnigCodePoint CR_Mc[] = {
- 175,
+ 182,
0x0903, 0x0903,
0x093b, 0x093b,
0x093e, 0x0940,
@@ -10443,6 +10874,7 @@ static const OnigCodePoint CR_Mc[] = {
0x0cc7, 0x0cc8,
0x0cca, 0x0ccb,
0x0cd5, 0x0cd6,
+ 0x0cf3, 0x0cf3,
0x0d02, 0x0d03,
0x0d3e, 0x0d40,
0x0d46, 0x0d48,
@@ -10465,6 +10897,8 @@ static const OnigCodePoint CR_Mc[] = {
0x1087, 0x108c,
0x108f, 0x108f,
0x109a, 0x109c,
+ 0x1715, 0x1715,
+ 0x1734, 0x1734,
0x17b6, 0x17b6,
0x17be, 0x17c5,
0x17c7, 0x17c8,
@@ -10579,6 +11013,10 @@ static const OnigCodePoint CR_Mc[] = {
0x11d93, 0x11d94,
0x11d96, 0x11d96,
0x11ef5, 0x11ef6,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f35,
+ 0x11f3e, 0x11f3f,
+ 0x11f41, 0x11f41,
0x16f51, 0x16f87,
0x16ff0, 0x16ff1,
0x1d165, 0x1d166,
@@ -10597,7 +11035,7 @@ static const OnigCodePoint CR_Me[] = {
/* 'Mn': General Category */
static const OnigCodePoint CR_Mn[] = {
- 327,
+ 346,
0x0300, 0x036f,
0x0483, 0x0487,
0x0591, 0x05bd,
@@ -10622,7 +11060,8 @@ static const OnigCodePoint CR_Mn[] = {
0x0825, 0x0827,
0x0829, 0x082d,
0x0859, 0x085b,
- 0x08d3, 0x08e1,
+ 0x0898, 0x089f,
+ 0x08ca, 0x08e1,
0x08e3, 0x0902,
0x093a, 0x093a,
0x093c, 0x093c,
@@ -10663,6 +11102,7 @@ static const OnigCodePoint CR_Mn[] = {
0x0bcd, 0x0bcd,
0x0c00, 0x0c00,
0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
0x0c3e, 0x0c40,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
@@ -10688,7 +11128,7 @@ static const OnigCodePoint CR_Mn[] = {
0x0e47, 0x0e4e,
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -10712,7 +11152,7 @@ static const OnigCodePoint CR_Mn[] = {
0x109d, 0x109d,
0x135d, 0x135f,
0x1712, 0x1714,
- 0x1732, 0x1734,
+ 0x1732, 0x1733,
0x1752, 0x1753,
0x1772, 0x1773,
0x17b4, 0x17b5,
@@ -10721,6 +11161,7 @@ static const OnigCodePoint CR_Mn[] = {
0x17c9, 0x17d3,
0x17dd, 0x17dd,
0x180b, 0x180d,
+ 0x180f, 0x180f,
0x1885, 0x1886,
0x18a9, 0x18a9,
0x1920, 0x1922,
@@ -10737,7 +11178,7 @@ static const OnigCodePoint CR_Mn[] = {
0x1a73, 0x1a7c,
0x1a7f, 0x1a7f,
0x1ab0, 0x1abd,
- 0x1abf, 0x1ac0,
+ 0x1abf, 0x1ace,
0x1b00, 0x1b03,
0x1b34, 0x1b34,
0x1b36, 0x1b3a,
@@ -10760,8 +11201,7 @@ static const OnigCodePoint CR_Mn[] = {
0x1ced, 0x1ced,
0x1cf4, 0x1cf4,
0x1cf8, 0x1cf9,
- 0x1dc0, 0x1df9,
- 0x1dfb, 0x1dff,
+ 0x1dc0, 0x1dff,
0x20d0, 0x20dc,
0x20e1, 0x20e1,
0x20e5, 0x20f0,
@@ -10819,12 +11259,17 @@ static const OnigCodePoint CR_Mn[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
0x11001, 0x11001,
0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
0x1107f, 0x11081,
0x110b3, 0x110b6,
0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
0x11100, 0x11102,
0x11127, 0x1112b,
0x1112d, 0x11134,
@@ -10837,6 +11282,7 @@ static const OnigCodePoint CR_Mn[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -10898,12 +11344,20 @@ static const OnigCodePoint CR_Mn[] = {
0x11d95, 0x11d95,
0x11d97, 0x11d97,
0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f40,
+ 0x11f42, 0x11f42,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16f4f, 0x16f4f,
0x16f8f, 0x16f92,
0x16fe4, 0x16fe4,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d167, 0x1d169,
0x1d17b, 0x1d182,
0x1d185, 0x1d18b,
@@ -10920,8 +11374,11 @@ static const OnigCodePoint CR_Mn[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
0x1e8d0, 0x1e8d6,
0x1e944, 0x1e94a,
0xe0100, 0xe01ef,
@@ -10929,7 +11386,7 @@ static const OnigCodePoint CR_Mn[] = {
/* 'N': Major Category */
static const OnigCodePoint CR_N[] = {
- 133,
+ 137,
0x0030, 0x0039,
0x00b2, 0x00b3,
0x00b9, 0x00b9,
@@ -11043,17 +11500,21 @@ static const OnigCodePoint CR_N[] = {
0x11c50, 0x11c6c,
0x11d50, 0x11d59,
0x11da0, 0x11da9,
+ 0x11f50, 0x11f59,
0x11fc0, 0x11fd4,
0x12400, 0x1246e,
0x16a60, 0x16a69,
+ 0x16ac0, 0x16ac9,
0x16b50, 0x16b59,
0x16b5b, 0x16b61,
0x16e80, 0x16e96,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d360, 0x1d378,
0x1d7ce, 0x1d7ff,
0x1e140, 0x1e149,
0x1e2f0, 0x1e2f9,
+ 0x1e4f0, 0x1e4f9,
0x1e8c7, 0x1e8cf,
0x1e950, 0x1e959,
0x1ec71, 0x1ecab,
@@ -11087,7 +11548,7 @@ static const OnigCodePoint CR_Nl[] = {
/* 'No': General Category */
static const OnigCodePoint CR_No[] = {
- 71,
+ 72,
0x00b2, 0x00b3,
0x00b9, 0x00b9,
0x00bc, 0x00be,
@@ -11150,6 +11611,7 @@ static const OnigCodePoint CR_No[] = {
0x11fc0, 0x11fd4,
0x16b5b, 0x16b61,
0x16e80, 0x16e96,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d360, 0x1d378,
0x1e8c7, 0x1e8cf,
@@ -11177,7 +11639,7 @@ static const OnigCodePoint CR_Pc[] = {
/* 'Pd': General Category */
static const OnigCodePoint CR_Pd[] = {
- 18,
+ 19,
0x002d, 0x002d,
0x058a, 0x058a,
0x05be, 0x05be,
@@ -11188,6 +11650,7 @@ static const OnigCodePoint CR_Pd[] = {
0x2e1a, 0x2e1a,
0x2e3a, 0x2e3b,
0x2e40, 0x2e40,
+ 0x2e5d, 0x2e5d,
0x301c, 0x301c,
0x3030, 0x3030,
0x30a0, 0x30a0,
@@ -11200,7 +11663,7 @@ static const OnigCodePoint CR_Pd[] = {
/* 'Pe': General Category */
static const OnigCodePoint CR_Pe[] = {
- 72,
+ 76,
0x0029, 0x0029,
0x005d, 0x005d,
0x007d, 0x007d,
@@ -11244,6 +11707,10 @@ static const OnigCodePoint CR_Pe[] = {
0x2e25, 0x2e25,
0x2e27, 0x2e27,
0x2e29, 0x2e29,
+ 0x2e56, 0x2e56,
+ 0x2e58, 0x2e58,
+ 0x2e5a, 0x2e5a,
+ 0x2e5c, 0x2e5c,
0x3009, 0x3009,
0x300b, 0x300b,
0x300d, 0x300d,
@@ -11308,7 +11775,7 @@ static const OnigCodePoint CR_Pi[] = {
/* 'Po': General Category */
static const OnigCodePoint CR_Po[] = {
- 181,
+ 187,
0x0021, 0x0023,
0x0025, 0x0027,
0x002a, 0x002a,
@@ -11332,7 +11799,7 @@ static const OnigCodePoint CR_Po[] = {
0x0609, 0x060a,
0x060c, 0x060d,
0x061b, 0x061b,
- 0x061e, 0x061f,
+ 0x061d, 0x061f,
0x066a, 0x066d,
0x06d4, 0x06d4,
0x0700, 0x070d,
@@ -11369,6 +11836,7 @@ static const OnigCodePoint CR_Po[] = {
0x1aa0, 0x1aa6,
0x1aa8, 0x1aad,
0x1b5a, 0x1b60,
+ 0x1b7d, 0x1b7e,
0x1bfc, 0x1bff,
0x1c3b, 0x1c3f,
0x1c7e, 0x1c7f,
@@ -11397,7 +11865,7 @@ static const OnigCodePoint CR_Po[] = {
0x2e3c, 0x2e3f,
0x2e41, 0x2e41,
0x2e43, 0x2e4f,
- 0x2e52, 0x2e52,
+ 0x2e52, 0x2e54,
0x3001, 0x3003,
0x303d, 0x303d,
0x30fb, 0x30fb,
@@ -11451,6 +11919,7 @@ static const OnigCodePoint CR_Po[] = {
0x10b39, 0x10b3f,
0x10b99, 0x10b9c,
0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
0x11047, 0x1104d,
0x110bb, 0x110bc,
0x110be, 0x110c1,
@@ -11469,6 +11938,7 @@ static const OnigCodePoint CR_Po[] = {
0x115c1, 0x115d7,
0x11641, 0x11643,
0x11660, 0x1166c,
+ 0x116b9, 0x116b9,
0x1173c, 0x1173e,
0x1183b, 0x1183b,
0x11944, 0x11946,
@@ -11476,11 +11946,14 @@ static const OnigCodePoint CR_Po[] = {
0x11a3f, 0x11a46,
0x11a9a, 0x11a9c,
0x11a9e, 0x11aa2,
+ 0x11b00, 0x11b09,
0x11c41, 0x11c45,
0x11c70, 0x11c71,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f4f,
0x11fff, 0x11fff,
0x12470, 0x12474,
+ 0x12ff1, 0x12ff2,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
0x16b37, 0x16b3b,
@@ -11494,7 +11967,7 @@ static const OnigCodePoint CR_Po[] = {
/* 'Ps': General Category */
static const OnigCodePoint CR_Ps[] = {
- 75,
+ 79,
0x0028, 0x0028,
0x005b, 0x005b,
0x007b, 0x007b,
@@ -11541,6 +12014,10 @@ static const OnigCodePoint CR_Ps[] = {
0x2e26, 0x2e26,
0x2e28, 0x2e28,
0x2e42, 0x2e42,
+ 0x2e55, 0x2e55,
+ 0x2e57, 0x2e57,
+ 0x2e59, 0x2e59,
+ 0x2e5b, 0x2e5b,
0x3008, 0x3008,
0x300a, 0x300a,
0x300c, 0x300c,
@@ -11574,7 +12051,7 @@ static const OnigCodePoint CR_Ps[] = {
/* 'S': Major Category */
static const OnigCodePoint CR_S[] = {
- 229,
+ 232,
0x0024, 0x0024,
0x002b, 0x002b,
0x003c, 0x003e,
@@ -11608,6 +12085,7 @@ static const OnigCodePoint CR_S[] = {
0x06fd, 0x06fe,
0x07f6, 0x07f6,
0x07fe, 0x07ff,
+ 0x0888, 0x0888,
0x09f2, 0x09f3,
0x09fa, 0x09fb,
0x0af1, 0x0af1,
@@ -11646,7 +12124,7 @@ static const OnigCodePoint CR_S[] = {
0x2052, 0x2052,
0x207a, 0x207c,
0x208a, 0x208c,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0x2100, 0x2101,
0x2103, 0x2106,
0x2108, 0x2109,
@@ -11708,8 +12186,10 @@ static const OnigCodePoint CR_S[] = {
0xab5b, 0xab5b,
0xab6a, 0xab6b,
0xfb29, 0xfb29,
- 0xfbb2, 0xfbc1,
- 0xfdfc, 0xfdfd,
+ 0xfbb2, 0xfbc2,
+ 0xfd40, 0xfd4f,
+ 0xfdcf, 0xfdcf,
+ 0xfdfc, 0xfdff,
0xfe62, 0xfe62,
0xfe64, 0xfe66,
0xfe69, 0xfe69,
@@ -11736,13 +12216,14 @@ static const OnigCodePoint CR_S[] = {
0x16b3c, 0x16b3f,
0x16b45, 0x16b45,
0x1bc9c, 0x1bc9c,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
0x1d129, 0x1d164,
0x1d16a, 0x1d16c,
0x1d183, 0x1d184,
0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1e8,
+ 0x1d1ae, 0x1d1ea,
0x1d200, 0x1d241,
0x1d245, 0x1d245,
0x1d300, 0x1d356,
@@ -11780,28 +12261,27 @@ static const OnigCodePoint CR_S[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
}; /* CR_S */
@@ -11820,7 +12300,7 @@ static const OnigCodePoint CR_Sc[] = {
0x0bf9, 0x0bf9,
0x0e3f, 0x0e3f,
0x17db, 0x17db,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0xa838, 0xa838,
0xfdfc, 0xfdfc,
0xfe69, 0xfe69,
@@ -11834,7 +12314,7 @@ static const OnigCodePoint CR_Sc[] = {
/* 'Sk': General Category */
static const OnigCodePoint CR_Sk[] = {
- 30,
+ 31,
0x005e, 0x005e,
0x0060, 0x0060,
0x00a8, 0x00a8,
@@ -11848,6 +12328,7 @@ static const OnigCodePoint CR_Sk[] = {
0x02ef, 0x02ff,
0x0375, 0x0375,
0x0384, 0x0385,
+ 0x0888, 0x0888,
0x1fbd, 0x1fbd,
0x1fbf, 0x1fc1,
0x1fcd, 0x1fcf,
@@ -11860,7 +12341,7 @@ static const OnigCodePoint CR_Sk[] = {
0xa789, 0xa78a,
0xab5b, 0xab5b,
0xab6a, 0xab6b,
- 0xfbb2, 0xfbc1,
+ 0xfbb2, 0xfbc2,
0xff3e, 0xff3e,
0xff40, 0xff40,
0xffe3, 0xffe3,
@@ -11938,7 +12419,7 @@ static const OnigCodePoint CR_Sm[] = {
/* 'So': General Category */
static const OnigCodePoint CR_So[] = {
- 182,
+ 184,
0x00a6, 0x00a6,
0x00a9, 0x00a9,
0x00ae, 0x00ae,
@@ -12046,7 +12527,9 @@ static const OnigCodePoint CR_So[] = {
0xa836, 0xa837,
0xa839, 0xa839,
0xaa77, 0xaa79,
- 0xfdfd, 0xfdfd,
+ 0xfd40, 0xfd4f,
+ 0xfdcf, 0xfdcf,
+ 0xfdfd, 0xfdff,
0xffe4, 0xffe4,
0xffe8, 0xffe8,
0xffed, 0xffee,
@@ -12065,13 +12548,14 @@ static const OnigCodePoint CR_So[] = {
0x16b3c, 0x16b3f,
0x16b45, 0x16b45,
0x1bc9c, 0x1bc9c,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
0x1d129, 0x1d164,
0x1d16a, 0x1d16c,
0x1d183, 0x1d184,
0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1e8,
+ 0x1d1ae, 0x1d1ea,
0x1d200, 0x1d241,
0x1d245, 0x1d245,
0x1d300, 0x1d356,
@@ -12097,28 +12581,27 @@ static const OnigCodePoint CR_So[] = {
0x1f260, 0x1f265,
0x1f300, 0x1f3fa,
0x1f400, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
}; /* CR_So */
@@ -12314,7 +12797,7 @@ static const OnigCodePoint CR_Math[] = {
/* 'Cased': Derived Property */
static const OnigCodePoint CR_Cased[] = {
- 141,
+ 157,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -12346,7 +12829,7 @@ static const OnigCodePoint CR_Cased[] = {
0x10c7, 0x10c7,
0x10cd, 0x10cd,
0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
+ 0x10fc, 0x10ff,
0x13a0, 0x13f5,
0x13f8, 0x13fd,
0x1c80, 0x1c88,
@@ -12392,9 +12875,7 @@ static const OnigCodePoint CR_Cased[] = {
0x2160, 0x217f,
0x2183, 0x2184,
0x24b6, 0x24e9,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
0x2d00, 0x2d25,
@@ -12404,12 +12885,14 @@ static const OnigCodePoint CR_Cased[] = {
0xa680, 0xa69d,
0xa722, 0xa787,
0xa78b, 0xa78e,
- 0xa790, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa7f6,
+ 0xa790, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa7f6,
0xa7f8, 0xa7fa,
0xab30, 0xab5a,
- 0xab5c, 0xab68,
+ 0xab5c, 0xab69,
0xab70, 0xabbf,
0xfb00, 0xfb06,
0xfb13, 0xfb17,
@@ -12418,6 +12901,18 @@ static const OnigCodePoint CR_Cased[] = {
0x10400, 0x1044f,
0x104b0, 0x104d3,
0x104d8, 0x104fb,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10c80, 0x10cb2,
0x10cc0, 0x10cf2,
0x118a0, 0x118df,
@@ -12452,6 +12947,10 @@ static const OnigCodePoint CR_Cased[] = {
0x1d78a, 0x1d7a8,
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e900, 0x1e943,
0x1f130, 0x1f149,
0x1f150, 0x1f169,
@@ -12460,7 +12959,7 @@ static const OnigCodePoint CR_Cased[] = {
/* 'Case_Ignorable': Derived Property */
static const OnigCodePoint CR_Case_Ignorable[] = {
- 410,
+ 437,
0x0027, 0x0027,
0x002e, 0x002e,
0x003a, 0x003a,
@@ -12503,7 +13002,10 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x07fd, 0x07fd,
0x0816, 0x082d,
0x0859, 0x085b,
- 0x08d3, 0x0902,
+ 0x0888, 0x0888,
+ 0x0890, 0x0891,
+ 0x0898, 0x089f,
+ 0x08c9, 0x0902,
0x093a, 0x093a,
0x093c, 0x093c,
0x0941, 0x0948,
@@ -12544,6 +13046,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x0bcd, 0x0bcd,
0x0c00, 0x0c00,
0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
0x0c3e, 0x0c40,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
@@ -12570,7 +13073,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -12595,7 +13098,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x10fc, 0x10fc,
0x135d, 0x135f,
0x1712, 0x1714,
- 0x1732, 0x1734,
+ 0x1732, 0x1733,
0x1752, 0x1753,
0x1772, 0x1773,
0x17b4, 0x17b5,
@@ -12604,7 +13107,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x17c9, 0x17d3,
0x17d7, 0x17d7,
0x17dd, 0x17dd,
- 0x180b, 0x180e,
+ 0x180b, 0x180f,
0x1843, 0x1843,
0x1885, 0x1886,
0x18a9, 0x18a9,
@@ -12622,7 +13125,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x1a73, 0x1a7c,
0x1a7f, 0x1a7f,
0x1aa7, 0x1aa7,
- 0x1ab0, 0x1ac0,
+ 0x1ab0, 0x1ace,
0x1b00, 0x1b03,
0x1b34, 0x1b34,
0x1b36, 0x1b3a,
@@ -12648,8 +13151,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x1cf8, 0x1cf9,
0x1d2c, 0x1d6a,
0x1d78, 0x1d78,
- 0x1d9b, 0x1df9,
- 0x1dfb, 0x1dff,
+ 0x1d9b, 0x1dff,
0x1fbd, 0x1fbd,
0x1fbf, 0x1fc1,
0x1fcd, 0x1fcf,
@@ -12690,6 +13192,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0xa700, 0xa721,
0xa770, 0xa770,
0xa788, 0xa78a,
+ 0xa7f2, 0xa7f4,
0xa7f8, 0xa7f9,
0xa802, 0xa802,
0xa806, 0xa806,
@@ -12729,7 +13232,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0xabe8, 0xabe8,
0xabed, 0xabed,
0xfb1e, 0xfb1e,
- 0xfbb2, 0xfbc1,
+ 0xfbb2, 0xfbc2,
0xfe00, 0xfe0f,
0xfe13, 0xfe13,
0xfe20, 0xfe2f,
@@ -12748,6 +13251,9 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x101fd, 0x101fd,
0x102e0, 0x102e0,
0x10376, 0x1037a,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10a01, 0x10a03,
0x10a05, 0x10a06,
0x10a0c, 0x10a0f,
@@ -12756,13 +13262,18 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
0x11001, 0x11001,
0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
0x1107f, 0x11081,
0x110b3, 0x110b6,
0x110b9, 0x110ba,
0x110bd, 0x110bd,
+ 0x110c2, 0x110c2,
0x110cd, 0x110cd,
0x11100, 0x11102,
0x11127, 0x1112b,
@@ -12776,6 +13287,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -12837,7 +13349,12 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x11d95, 0x11d95,
0x11d97, 0x11d97,
0x11ef3, 0x11ef4,
- 0x13430, 0x13438,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f40,
+ 0x11f42, 0x11f42,
+ 0x13430, 0x13440,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16b40, 0x16b43,
@@ -12845,8 +13362,13 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x16f8f, 0x16f9f,
0x16fe0, 0x16fe1,
0x16fe3, 0x16fe4,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
0x1bc9d, 0x1bc9e,
0x1bca0, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d167, 0x1d169,
0x1d173, 0x1d182,
0x1d185, 0x1d18b,
@@ -12863,8 +13385,12 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e130, 0x1e13d,
+ 0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
+ 0x1e4eb, 0x1e4ef,
0x1e8d0, 0x1e8d6,
0x1e944, 0x1e94b,
0x1f3fb, 0x1f3ff,
@@ -12875,7 +13401,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
/* 'Changes_When_Lowercased': Derived Property */
static const OnigCodePoint CR_Changes_When_Lowercased[] = {
- 601,
+ 609,
0x0041, 0x005a,
0x00c0, 0x00d6,
0x00d8, 0x00de,
@@ -13301,7 +13827,7 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = {
0x2160, 0x216f,
0x2183, 0x2183,
0x24b6, 0x24cf,
- 0x2c00, 0x2c2e,
+ 0x2c00, 0x2c2f,
0x2c60, 0x2c60,
0x2c62, 0x2c64,
0x2c67, 0x2c67,
@@ -13466,13 +13992,21 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = {
0xa7ba, 0xa7ba,
0xa7bc, 0xa7bc,
0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
0xa7c2, 0xa7c2,
0xa7c4, 0xa7c7,
0xa7c9, 0xa7c9,
+ 0xa7d0, 0xa7d0,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
0xa7f5, 0xa7f5,
0xff21, 0xff3a,
0x10400, 0x10427,
0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
0x10c80, 0x10cb2,
0x118a0, 0x118bf,
0x16e40, 0x16e5f,
@@ -13481,7 +14015,7 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = {
/* 'Changes_When_Uppercased': Derived Property */
static const OnigCodePoint CR_Changes_When_Uppercased[] = {
- 619,
+ 627,
0x0061, 0x007a,
0x00b5, 0x00b5,
0x00df, 0x00f6,
@@ -13921,7 +14455,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = {
0x2170, 0x217f,
0x2184, 0x2184,
0x24d0, 0x24e9,
- 0x2c30, 0x2c5e,
+ 0x2c30, 0x2c5f,
0x2c61, 0x2c61,
0x2c65, 0x2c66,
0x2c68, 0x2c68,
@@ -14086,9 +14620,13 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = {
0xa7bb, 0xa7bb,
0xa7bd, 0xa7bd,
0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
0xa7c3, 0xa7c3,
0xa7c8, 0xa7c8,
0xa7ca, 0xa7ca,
+ 0xa7d1, 0xa7d1,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
0xa7f6, 0xa7f6,
0xab53, 0xab53,
0xab70, 0xabbf,
@@ -14097,6 +14635,10 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = {
0xff41, 0xff5a,
0x10428, 0x1044f,
0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10cc0, 0x10cf2,
0x118c0, 0x118df,
0x16e60, 0x16e7f,
@@ -14105,7 +14647,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = {
/* 'Changes_When_Titlecased': Derived Property */
static const OnigCodePoint CR_Changes_When_Titlecased[] = {
- 618,
+ 626,
0x0061, 0x007a,
0x00b5, 0x00b5,
0x00df, 0x00f6,
@@ -14544,7 +15086,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = {
0x2170, 0x217f,
0x2184, 0x2184,
0x24d0, 0x24e9,
- 0x2c30, 0x2c5e,
+ 0x2c30, 0x2c5f,
0x2c61, 0x2c61,
0x2c65, 0x2c66,
0x2c68, 0x2c68,
@@ -14709,9 +15251,13 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = {
0xa7bb, 0xa7bb,
0xa7bd, 0xa7bd,
0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
0xa7c3, 0xa7c3,
0xa7c8, 0xa7c8,
0xa7ca, 0xa7ca,
+ 0xa7d1, 0xa7d1,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
0xa7f6, 0xa7f6,
0xab53, 0xab53,
0xab70, 0xabbf,
@@ -14720,6 +15266,10 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = {
0xff41, 0xff5a,
0x10428, 0x1044f,
0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10cc0, 0x10cf2,
0x118c0, 0x118df,
0x16e60, 0x16e7f,
@@ -14728,7 +15278,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = {
/* 'Changes_When_Casefolded': Derived Property */
static const OnigCodePoint CR_Changes_When_Casefolded[] = {
- 614,
+ 622,
0x0041, 0x005a,
0x00b5, 0x00b5,
0x00c0, 0x00d6,
@@ -15164,7 +15714,7 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = {
0x2160, 0x216f,
0x2183, 0x2183,
0x24b6, 0x24cf,
- 0x2c00, 0x2c2e,
+ 0x2c00, 0x2c2f,
0x2c60, 0x2c60,
0x2c62, 0x2c64,
0x2c67, 0x2c67,
@@ -15329,9 +15879,13 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = {
0xa7ba, 0xa7ba,
0xa7bc, 0xa7bc,
0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
0xa7c2, 0xa7c2,
0xa7c4, 0xa7c7,
0xa7c9, 0xa7c9,
+ 0xa7d0, 0xa7d0,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
0xa7f5, 0xa7f5,
0xab70, 0xabbf,
0xfb00, 0xfb06,
@@ -15339,6 +15893,10 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = {
0xff21, 0xff3a,
0x10400, 0x10427,
0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
0x10c80, 0x10cb2,
0x118a0, 0x118bf,
0x16e40, 0x16e5f,
@@ -15347,7 +15905,7 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = {
/* 'Changes_When_Casemapped': Derived Property */
static const OnigCodePoint CR_Changes_When_Casemapped[] = {
- 124,
+ 131,
0x0041, 0x005a,
0x0061, 0x007a,
0x00b5, 0x00b5,
@@ -15436,9 +15994,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = {
0x2160, 0x217f,
0x2183, 0x2184,
0x24b6, 0x24e9,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2c70,
+ 0x2c00, 0x2c70,
0x2c72, 0x2c73,
0x2c75, 0x2c76,
0x2c7e, 0x2ce3,
@@ -15455,8 +16011,9 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = {
0xa78b, 0xa78d,
0xa790, 0xa794,
0xa796, 0xa7ae,
- 0xa7b0, 0xa7bf,
- 0xa7c2, 0xa7ca,
+ 0xa7b0, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d6, 0xa7d9,
0xa7f5, 0xa7f6,
0xab53, 0xab53,
0xab70, 0xabbf,
@@ -15467,6 +16024,14 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = {
0x10400, 0x1044f,
0x104b0, 0x104d3,
0x104d8, 0x104fb,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10c80, 0x10cb2,
0x10cc0, 0x10cf2,
0x118a0, 0x118df,
@@ -15476,7 +16041,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = {
/* 'ID_Start': Derived Property */
static const OnigCodePoint CR_ID_Start[] = {
- 622,
+ 659,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -15526,8 +16091,9 @@ static const OnigCodePoint CR_ID_Start[] = {
0x0828, 0x0828,
0x0840, 0x0858,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x08a0, 0x08c9,
0x0904, 0x0939,
0x093d, 0x093d,
0x0950, 0x0950,
@@ -15592,6 +16158,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x0c2a, 0x0c39,
0x0c3d, 0x0c3d,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c61,
0x0c80, 0x0c80,
0x0c85, 0x0c8c,
@@ -15600,7 +16167,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x0caa, 0x0cb3,
0x0cb5, 0x0cb9,
0x0cbd, 0x0cbd,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce1,
0x0cf1, 0x0cf2,
0x0d04, 0x0d0c,
@@ -15671,9 +16238,8 @@ static const OnigCodePoint CR_ID_Start[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1711,
- 0x1720, 0x1731,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
0x1740, 0x1751,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -15693,7 +16259,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x1a20, 0x1a54,
0x1aa7, 0x1aa7,
0x1b05, 0x1b33,
- 0x1b45, 0x1b4b,
+ 0x1b45, 0x1b4c,
0x1b83, 0x1ba0,
0x1bae, 0x1baf,
0x1bba, 0x1be5,
@@ -15743,9 +16309,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x2145, 0x2149,
0x214e, 0x214e,
0x2160, 0x2188,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
0x2d00, 0x2d25,
@@ -15775,8 +16339,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa61f,
@@ -15786,9 +16349,11 @@ static const OnigCodePoint CR_ID_Start[] = {
0xa6a0, 0xa6ef,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa801,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa801,
0xa803, 0xa805,
0xa807, 0xa80a,
0xa80c, 0xa822,
@@ -15877,9 +16442,20 @@ static const OnigCodePoint CR_ID_Start[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -15915,9 +16491,12 @@ static const OnigCodePoint CR_ID_Start[] = {
0x10f00, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
0x11083, 0x110af,
0x110d0, 0x110e8,
0x11103, 0x11126,
@@ -15931,6 +16510,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -15959,6 +16539,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x11680, 0x116aa,
0x116b8, 0x116b8,
0x11700, 0x1171a,
+ 0x11740, 0x11746,
0x11800, 0x1182b,
0x118a0, 0x118df,
0x118ff, 0x11906,
@@ -15978,7 +16559,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x11a50, 0x11a50,
0x11a5c, 0x11a89,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c2e,
0x11c40, 0x11c40,
@@ -15992,14 +16573,20 @@ static const OnigCodePoint CR_ID_Start[] = {
0x11d6a, 0x11d89,
0x11d98, 0x11d98,
0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
0x16ad0, 0x16aed,
0x16b00, 0x16b2f,
0x16b40, 0x16b43,
@@ -16014,8 +16601,13 @@ static const OnigCodePoint CR_ID_Start[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -16052,10 +16644,19 @@ static const OnigCodePoint CR_ID_Start[] = {
0x1d78a, 0x1d7a8,
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e900, 0x1e943,
0x1e94b, 0x1e94b,
@@ -16092,18 +16693,19 @@ static const OnigCodePoint CR_ID_Start[] = {
0x1eea1, 0x1eea3,
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_ID_Start */
/* 'ID_Continue': Derived Property */
static const OnigCodePoint CR_ID_Continue[] = {
- 730,
+ 768,
0x0030, 0x0039,
0x0041, 0x005a,
0x005f, 0x005f,
@@ -16155,9 +16757,9 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x0800, 0x082d,
0x0840, 0x085b,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x08e1,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x0898, 0x08e1,
0x08e3, 0x0963,
0x0966, 0x096f,
0x0971, 0x0983,
@@ -16241,11 +16843,12 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c80, 0x0c83,
@@ -16258,10 +16861,10 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -16294,7 +16897,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f00,
@@ -16341,9 +16944,8 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1734,
+ 0x1700, 0x1715,
+ 0x171f, 0x1734,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -16353,7 +16955,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x17dc, 0x17dd,
0x17e0, 0x17e9,
0x180b, 0x180d,
- 0x1810, 0x1819,
+ 0x180f, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x18b0, 0x18f5,
@@ -16372,8 +16974,8 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1a90, 0x1a99,
0x1aa7, 0x1aa7,
0x1ab0, 0x1abd,
- 0x1abf, 0x1ac0,
- 0x1b00, 0x1b4b,
+ 0x1abf, 0x1ace,
+ 0x1b00, 0x1b4c,
0x1b50, 0x1b59,
0x1b6b, 0x1b73,
0x1b80, 0x1bf3,
@@ -16385,8 +16987,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1cbd, 0x1cbf,
0x1cd0, 0x1cd2,
0x1cd4, 0x1cfa,
- 0x1d00, 0x1df9,
- 0x1dfb, 0x1f15,
+ 0x1d00, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
0x1f48, 0x1f4d,
@@ -16426,9 +17027,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x2145, 0x2149,
0x214e, 0x214e,
0x2160, 0x2188,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cf3,
0x2d00, 0x2d25,
0x2d27, 0x2d27,
@@ -16458,8 +17057,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa62b,
@@ -16468,9 +17066,11 @@ static const OnigCodePoint CR_ID_Continue[] = {
0xa67f, 0xa6f1,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa827,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa827,
0xa82c, 0xa82c,
0xa840, 0xa873,
0xa880, 0xa8c5,
@@ -16559,9 +17159,20 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -16599,14 +17210,16 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10eac,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
+ 0x10efd, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f50,
+ 0x10f70, 0x10f85,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11000, 0x11046,
- 0x11066, 0x1106f,
+ 0x11066, 0x11075,
0x1107f, 0x110ba,
+ 0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
0x11100, 0x11134,
@@ -16620,7 +17233,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -16660,6 +17273,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x11700, 0x1171a,
0x1171d, 0x1172b,
0x11730, 0x11739,
+ 0x11740, 0x11746,
0x11800, 0x1183a,
0x118a0, 0x118e9,
0x118ff, 0x11906,
@@ -16678,7 +17292,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x11a47, 0x11a47,
0x11a50, 0x11a99,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c40,
@@ -16700,15 +17314,23 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f50, 0x11f59,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af0, 0x16af4,
0x16b00, 0x16b36,
@@ -16726,8 +17348,13 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -16735,6 +17362,8 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d165, 0x1d169,
0x1d16d, 0x1d172,
0x1d17b, 0x1d182,
@@ -16778,16 +17407,26 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1da84, 0x1da84,
0x1da9b, 0x1da9f,
0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e130, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8d0, 0x1e8d6,
0x1e900, 0x1e94b,
@@ -16826,19 +17465,20 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0100, 0xe01ef,
}; /* CR_ID_Continue */
/* 'XID_Start': Derived Property */
static const OnigCodePoint CR_XID_Start[] = {
- 629,
+ 666,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -16888,8 +17528,9 @@ static const OnigCodePoint CR_XID_Start[] = {
0x0828, 0x0828,
0x0840, 0x0858,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x08a0, 0x08c9,
0x0904, 0x0939,
0x093d, 0x093d,
0x0950, 0x0950,
@@ -16954,6 +17595,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x0c2a, 0x0c39,
0x0c3d, 0x0c3d,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c61,
0x0c80, 0x0c80,
0x0c85, 0x0c8c,
@@ -16962,7 +17604,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x0caa, 0x0cb3,
0x0cb5, 0x0cb9,
0x0cbd, 0x0cbd,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce1,
0x0cf1, 0x0cf2,
0x0d04, 0x0d0c,
@@ -17033,9 +17675,8 @@ static const OnigCodePoint CR_XID_Start[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1711,
- 0x1720, 0x1731,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
0x1740, 0x1751,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -17055,7 +17696,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x1a20, 0x1a54,
0x1aa7, 0x1aa7,
0x1b05, 0x1b33,
- 0x1b45, 0x1b4b,
+ 0x1b45, 0x1b4c,
0x1b83, 0x1ba0,
0x1bae, 0x1baf,
0x1bba, 0x1be5,
@@ -17105,9 +17746,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x2145, 0x2149,
0x214e, 0x214e,
0x2160, 0x2188,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cee,
0x2cf2, 0x2cf3,
0x2d00, 0x2d25,
@@ -17137,8 +17776,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa61f,
@@ -17148,9 +17786,11 @@ static const OnigCodePoint CR_XID_Start[] = {
0xa6a0, 0xa6ef,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa801,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa801,
0xa803, 0xa805,
0xa807, 0xa80a,
0xa80c, 0xa822,
@@ -17246,9 +17886,20 @@ static const OnigCodePoint CR_XID_Start[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -17284,9 +17935,12 @@ static const OnigCodePoint CR_XID_Start[] = {
0x10f00, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
0x11083, 0x110af,
0x110d0, 0x110e8,
0x11103, 0x11126,
@@ -17300,6 +17954,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -17328,6 +17983,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x11680, 0x116aa,
0x116b8, 0x116b8,
0x11700, 0x1171a,
+ 0x11740, 0x11746,
0x11800, 0x1182b,
0x118a0, 0x118df,
0x118ff, 0x11906,
@@ -17347,7 +18003,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x11a50, 0x11a50,
0x11a5c, 0x11a89,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c2e,
0x11c40, 0x11c40,
@@ -17361,14 +18017,20 @@ static const OnigCodePoint CR_XID_Start[] = {
0x11d6a, 0x11d89,
0x11d98, 0x11d98,
0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
0x16ad0, 0x16aed,
0x16b00, 0x16b2f,
0x16b40, 0x16b43,
@@ -17383,8 +18045,13 @@ static const OnigCodePoint CR_XID_Start[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -17421,10 +18088,19 @@ static const OnigCodePoint CR_XID_Start[] = {
0x1d78a, 0x1d7a8,
0x1d7aa, 0x1d7c2,
0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e900, 0x1e943,
0x1e94b, 0x1e94b,
@@ -17461,18 +18137,19 @@ static const OnigCodePoint CR_XID_Start[] = {
0x1eea1, 0x1eea3,
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_XID_Start */
/* 'XID_Continue': Derived Property */
static const OnigCodePoint CR_XID_Continue[] = {
- 737,
+ 775,
0x0030, 0x0039,
0x0041, 0x005a,
0x005f, 0x005f,
@@ -17524,9 +18201,9 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x0800, 0x082d,
0x0840, 0x085b,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x08e1,
+ 0x0870, 0x0887,
+ 0x0889, 0x088e,
+ 0x0898, 0x08e1,
0x08e3, 0x0963,
0x0966, 0x096f,
0x0971, 0x0983,
@@ -17610,11 +18287,12 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c80, 0x0c83,
@@ -17627,10 +18305,10 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -17663,7 +18341,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f00,
@@ -17710,9 +18388,8 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1681, 0x169a,
0x16a0, 0x16ea,
0x16ee, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1734,
+ 0x1700, 0x1715,
+ 0x171f, 0x1734,
0x1740, 0x1753,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -17722,7 +18399,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x17dc, 0x17dd,
0x17e0, 0x17e9,
0x180b, 0x180d,
- 0x1810, 0x1819,
+ 0x180f, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x18b0, 0x18f5,
@@ -17741,8 +18418,8 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1a90, 0x1a99,
0x1aa7, 0x1aa7,
0x1ab0, 0x1abd,
- 0x1abf, 0x1ac0,
- 0x1b00, 0x1b4b,
+ 0x1abf, 0x1ace,
+ 0x1b00, 0x1b4c,
0x1b50, 0x1b59,
0x1b6b, 0x1b73,
0x1b80, 0x1bf3,
@@ -17754,8 +18431,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1cbd, 0x1cbf,
0x1cd0, 0x1cd2,
0x1cd4, 0x1cfa,
- 0x1d00, 0x1df9,
- 0x1dfb, 0x1f15,
+ 0x1d00, 0x1f15,
0x1f18, 0x1f1d,
0x1f20, 0x1f45,
0x1f48, 0x1f4d,
@@ -17795,9 +18471,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x2145, 0x2149,
0x214e, 0x214e,
0x2160, 0x2188,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2ce4,
+ 0x2c00, 0x2ce4,
0x2ceb, 0x2cf3,
0x2d00, 0x2d25,
0x2d27, 0x2d27,
@@ -17828,8 +18502,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x31a0, 0x31bf,
0x31f0, 0x31ff,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x4e00, 0xa48c,
0xa4d0, 0xa4fd,
0xa500, 0xa60c,
0xa610, 0xa62b,
@@ -17838,9 +18511,11 @@ static const OnigCodePoint CR_XID_Continue[] = {
0xa67f, 0xa6f1,
0xa717, 0xa71f,
0xa722, 0xa788,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa827,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa827,
0xa82c, 0xa82c,
0xa840, 0xa873,
0xa880, 0xa8c5,
@@ -17935,9 +18610,20 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -17975,14 +18661,16 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10eac,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
+ 0x10efd, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f50,
+ 0x10f70, 0x10f85,
0x10fb0, 0x10fc4,
0x10fe0, 0x10ff6,
0x11000, 0x11046,
- 0x11066, 0x1106f,
+ 0x11066, 0x11075,
0x1107f, 0x110ba,
+ 0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
0x11100, 0x11134,
@@ -17996,7 +18684,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -18036,6 +18724,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x11700, 0x1171a,
0x1171d, 0x1172b,
0x11730, 0x11739,
+ 0x11740, 0x11746,
0x11800, 0x1183a,
0x118a0, 0x118e9,
0x118ff, 0x11906,
@@ -18054,7 +18743,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x11a47, 0x11a47,
0x11a50, 0x11a99,
0x11a9d, 0x11a9d,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c40,
@@ -18076,15 +18765,23 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f50, 0x11f59,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12400, 0x1246e,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af0, 0x16af4,
0x16b00, 0x16b36,
@@ -18102,8 +18799,13 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -18111,6 +18813,8 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1bc80, 0x1bc88,
0x1bc90, 0x1bc99,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d165, 0x1d169,
0x1d16d, 0x1d172,
0x1d17b, 0x1d182,
@@ -18154,16 +18858,26 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1da84, 0x1da84,
0x1da9b, 0x1da9f,
0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
0x1e100, 0x1e12c,
0x1e130, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8d0, 0x1e8d6,
0x1e900, 0x1e94b,
@@ -18202,13 +18916,14 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0100, 0xe01ef,
}; /* CR_XID_Continue */
@@ -18220,7 +18935,7 @@ static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = {
0x061c, 0x061c,
0x115f, 0x1160,
0x17b4, 0x17b5,
- 0x180b, 0x180e,
+ 0x180b, 0x180f,
0x200b, 0x200f,
0x202a, 0x202e,
0x2060, 0x206f,
@@ -18236,7 +18951,7 @@ static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = {
/* 'Grapheme_Extend': Derived Property */
static const OnigCodePoint CR_Grapheme_Extend[] = {
- 344,
+ 363,
0x0300, 0x036f,
0x0483, 0x0489,
0x0591, 0x05bd,
@@ -18261,7 +18976,8 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x0825, 0x0827,
0x0829, 0x082d,
0x0859, 0x085b,
- 0x08d3, 0x08e1,
+ 0x0898, 0x089f,
+ 0x08ca, 0x08e1,
0x08e3, 0x0902,
0x093a, 0x093a,
0x093c, 0x093c,
@@ -18306,6 +19022,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x0bd7, 0x0bd7,
0x0c00, 0x0c00,
0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
0x0c3e, 0x0c40,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
@@ -18337,7 +19054,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x0e47, 0x0e4e,
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -18361,7 +19078,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x109d, 0x109d,
0x135d, 0x135f,
0x1712, 0x1714,
- 0x1732, 0x1734,
+ 0x1732, 0x1733,
0x1752, 0x1753,
0x1772, 0x1773,
0x17b4, 0x17b5,
@@ -18370,6 +19087,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x17c9, 0x17d3,
0x17dd, 0x17dd,
0x180b, 0x180d,
+ 0x180f, 0x180f,
0x1885, 0x1886,
0x18a9, 0x18a9,
0x1920, 0x1922,
@@ -18385,7 +19103,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x1a65, 0x1a6c,
0x1a73, 0x1a7c,
0x1a7f, 0x1a7f,
- 0x1ab0, 0x1ac0,
+ 0x1ab0, 0x1ace,
0x1b00, 0x1b03,
0x1b34, 0x1b3a,
0x1b3c, 0x1b3c,
@@ -18407,8 +19125,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x1ced, 0x1ced,
0x1cf4, 0x1cf4,
0x1cf8, 0x1cf9,
- 0x1dc0, 0x1df9,
- 0x1dfb, 0x1dff,
+ 0x1dc0, 0x1dff,
0x200c, 0x200c,
0x20d0, 0x20f0,
0x2cef, 0x2cf1,
@@ -18466,12 +19183,17 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
0x11001, 0x11001,
0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
0x1107f, 0x11081,
0x110b3, 0x110b6,
0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
0x11100, 0x11102,
0x11127, 0x1112b,
0x1112d, 0x11134,
@@ -18484,6 +19206,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -18551,12 +19274,20 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x11d95, 0x11d95,
0x11d97, 0x11d97,
0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f40,
+ 0x11f42, 0x11f42,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16f4f, 0x16f4f,
0x16f8f, 0x16f92,
0x16fe4, 0x16fe4,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d165, 0x1d165,
0x1d167, 0x1d169,
0x1d16e, 0x1d172,
@@ -18575,8 +19306,11 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
0x1e8d0, 0x1e8d6,
0x1e944, 0x1e94a,
0xe0020, 0xe007f,
@@ -18585,7 +19319,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
/* 'Grapheme_Base': Derived Property */
static const OnigCodePoint CR_Grapheme_Base[] = {
- 834,
+ 875,
0x0020, 0x007e,
0x00a0, 0x00ac,
0x00ae, 0x02ff,
@@ -18607,7 +19341,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x05ef, 0x05f4,
0x0606, 0x060f,
0x061b, 0x061b,
- 0x061e, 0x064a,
+ 0x061d, 0x064a,
0x0660, 0x066f,
0x0671, 0x06d5,
0x06de, 0x06de,
@@ -18628,8 +19362,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x0840, 0x0858,
0x085e, 0x085e,
0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
+ 0x0870, 0x088e,
+ 0x08a0, 0x08c9,
0x0903, 0x0939,
0x093b, 0x093b,
0x093d, 0x0940,
@@ -18718,6 +19452,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x0c3d, 0x0c3d,
0x0c41, 0x0c44,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c61,
0x0c66, 0x0c6f,
0x0c77, 0x0c80,
@@ -18731,10 +19466,10 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x0cc3, 0x0cc4,
0x0cc7, 0x0cc8,
0x0cca, 0x0ccb,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce1,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d02, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d3a,
@@ -18820,10 +19555,10 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x13f8, 0x13fd,
0x1400, 0x169c,
0x16a0, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1711,
- 0x1720, 0x1731,
- 0x1735, 0x1736,
+ 0x1700, 0x1711,
+ 0x1715, 0x1715,
+ 0x171f, 0x1731,
+ 0x1734, 0x1736,
0x1740, 0x1751,
0x1760, 0x176c,
0x176e, 0x1770,
@@ -18865,9 +19600,9 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1b04, 0x1b33,
0x1b3b, 0x1b3b,
0x1b3d, 0x1b41,
- 0x1b43, 0x1b4b,
+ 0x1b43, 0x1b4c,
0x1b50, 0x1b6a,
- 0x1b74, 0x1b7c,
+ 0x1b74, 0x1b7e,
0x1b82, 0x1ba1,
0x1ba6, 0x1ba7,
0x1baa, 0x1baa,
@@ -18911,15 +19646,13 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x2070, 0x2071,
0x2074, 0x208e,
0x2090, 0x209c,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0x2100, 0x218b,
0x2190, 0x2426,
0x2440, 0x244a,
0x2460, 0x2b73,
0x2b76, 0x2b95,
- 0x2b97, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2cee,
+ 0x2b97, 0x2cee,
0x2cf2, 0x2cf3,
0x2cf9, 0x2d25,
0x2d27, 0x2d27,
@@ -18935,7 +19668,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x2dc8, 0x2dce,
0x2dd0, 0x2dd6,
0x2dd8, 0x2dde,
- 0x2e00, 0x2e52,
+ 0x2e00, 0x2e5d,
0x2e80, 0x2e99,
0x2e9b, 0x2ef3,
0x2f00, 0x2fd5,
@@ -18948,8 +19681,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x3131, 0x318e,
0x3190, 0x31e3,
0x31f0, 0x321e,
- 0x3220, 0x9ffc,
- 0xa000, 0xa48c,
+ 0x3220, 0xa48c,
0xa490, 0xa4c6,
0xa4d0, 0xa62b,
0xa640, 0xa66e,
@@ -18957,9 +19689,11 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0xa67e, 0xa69d,
0xa6a0, 0xa6ef,
0xa6f2, 0xa6f7,
- 0xa700, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa801,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa801,
0xa803, 0xa805,
0xa807, 0xa80a,
0xa80c, 0xa824,
@@ -19019,11 +19753,11 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0xfb3e, 0xfb3e,
0xfb40, 0xfb41,
0xfb43, 0xfb44,
- 0xfb46, 0xfbc1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
+ 0xfb46, 0xfbc2,
+ 0xfbd3, 0xfd8f,
0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
+ 0xfdcf, 0xfdcf,
+ 0xfdf0, 0xfdff,
0xfe10, 0xfe19,
0xfe30, 0xfe52,
0xfe54, 0xfe66,
@@ -19067,10 +19801,20 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x104d8, 0x104fb,
0x10500, 0x10527,
0x10530, 0x10563,
- 0x1056f, 0x1056f,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10800, 0x10805,
0x10808, 0x10808,
0x1080a, 0x10835,
@@ -19113,12 +19857,16 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x10f00, 0x10f27,
0x10f30, 0x10f45,
0x10f51, 0x10f59,
+ 0x10f70, 0x10f81,
+ 0x10f86, 0x10f89,
0x10fb0, 0x10fcb,
0x10fe0, 0x10ff6,
0x11000, 0x11000,
0x11002, 0x11037,
0x11047, 0x1104d,
0x11052, 0x1106f,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
0x11082, 0x110b2,
0x110b7, 0x110b8,
0x110bb, 0x110bc,
@@ -19140,6 +19888,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x11232, 0x11233,
0x11235, 0x11235,
0x11238, 0x1123d,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -19191,12 +19940,12 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x116ac, 0x116ac,
0x116ae, 0x116af,
0x116b6, 0x116b6,
- 0x116b8, 0x116b8,
+ 0x116b8, 0x116b9,
0x116c0, 0x116c9,
0x11700, 0x1171a,
0x11720, 0x11721,
0x11726, 0x11726,
- 0x11730, 0x1173f,
+ 0x11730, 0x11746,
0x11800, 0x1182e,
0x11838, 0x11838,
0x1183b, 0x1183b,
@@ -19225,7 +19974,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x11a5c, 0x11a89,
0x11a97, 0x11a97,
0x11a9a, 0x11aa2,
- 0x11ac0, 0x11af8,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c2f,
0x11c3e, 0x11c3e,
@@ -19249,18 +19999,26 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x11da0, 0x11da9,
0x11ee0, 0x11ef2,
0x11ef5, 0x11ef8,
+ 0x11f02, 0x11f10,
+ 0x11f12, 0x11f35,
+ 0x11f3e, 0x11f3f,
+ 0x11f41, 0x11f41,
+ 0x11f43, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
0x12400, 0x1246e,
0x12470, 0x12474,
0x12480, 0x12543,
- 0x13000, 0x1342e,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
0x16ad0, 0x16aed,
0x16af5, 0x16af5,
0x16b00, 0x16b2f,
@@ -19278,8 +20036,13 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x17000, 0x187f7,
0x18800, 0x18cd5,
0x18d00, 0x18d08,
- 0x1b000, 0x1b11e,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -19288,6 +20051,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1bc90, 0x1bc99,
0x1bc9c, 0x1bc9c,
0x1bc9f, 0x1bc9f,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
0x1d129, 0x1d164,
@@ -19295,9 +20059,10 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1d16a, 0x1d16d,
0x1d183, 0x1d184,
0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1e8,
+ 0x1d1ae, 0x1d1ea,
0x1d200, 0x1d241,
0x1d245, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -19326,13 +20091,23 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1da6d, 0x1da74,
0x1da76, 0x1da83,
0x1da85, 0x1da8b,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e140, 0x1e149,
0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
0x1e2f0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e4f0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
0x1e800, 0x1e8c4,
0x1e8c7, 0x1e8cf,
0x1e900, 0x1e943,
@@ -19388,43 +20163,43 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Grapheme_Base */
/* 'Grapheme_Link': Derived Property */
static const OnigCodePoint CR_Grapheme_Link[] = {
- 54,
+ 56,
0x094d, 0x094d,
0x09cd, 0x09cd,
0x0a4d, 0x0a4d,
@@ -19440,7 +20215,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = {
0x0eba, 0x0eba,
0x0f84, 0x0f84,
0x1039, 0x103a,
- 0x1714, 0x1714,
+ 0x1714, 0x1715,
0x1734, 0x1734,
0x17d2, 0x17d2,
0x1a60, 0x1a60,
@@ -19457,6 +20232,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = {
0xabed, 0xabed,
0x10a3f, 0x10a3f,
0x11046, 0x11046,
+ 0x11070, 0x11070,
0x1107f, 0x1107f,
0x110b9, 0x110b9,
0x11133, 0x11134,
@@ -19479,6 +20255,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = {
0x11c3f, 0x11c3f,
0x11d44, 0x11d45,
0x11d97, 0x11d97,
+ 0x11f41, 0x11f42,
}; /* CR_Grapheme_Link */
/* 'Common': Script */
@@ -19524,7 +20301,7 @@ static const OnigCodePoint CR_Common[] = {
0x2066, 0x2070,
0x2074, 0x207e,
0x2080, 0x208e,
- 0x20a0, 0x20bf,
+ 0x20a0, 0x20c0,
0x2100, 0x2125,
0x2127, 0x2129,
0x212c, 0x2131,
@@ -19537,7 +20314,7 @@ static const OnigCodePoint CR_Common[] = {
0x2900, 0x2b73,
0x2b76, 0x2b95,
0x2b97, 0x2bff,
- 0x2e00, 0x2e52,
+ 0x2e00, 0x2e5d,
0x2ff0, 0x2ffb,
0x3000, 0x3004,
0x3006, 0x3006,
@@ -19581,15 +20358,16 @@ static const OnigCodePoint CR_Common[] = {
0x10190, 0x1019c,
0x101d0, 0x101fc,
0x102e1, 0x102fb,
- 0x16fe2, 0x16fe3,
0x1bca0, 0x1bca3,
+ 0x1cf50, 0x1cfc3,
0x1d000, 0x1d0f5,
0x1d100, 0x1d126,
0x1d129, 0x1d166,
0x1d16a, 0x1d17a,
0x1d183, 0x1d184,
0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1e8,
+ 0x1d1ae, 0x1d1ea,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -19630,28 +20408,27 @@ static const OnigCodePoint CR_Common[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6e0, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
0x1f810, 0x1f847,
0x1f850, 0x1f859,
0x1f860, 0x1f887,
0x1f890, 0x1f8ad,
0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1fa53,
+ 0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
@@ -19661,7 +20438,7 @@ static const OnigCodePoint CR_Common[] = {
/* 'Latin': Script */
static const OnigCodePoint CR_Latin[] = {
- 32,
+ 39,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -19685,15 +20462,22 @@ static const OnigCodePoint CR_Latin[] = {
0x2160, 0x2188,
0x2c60, 0x2c7f,
0xa722, 0xa787,
- 0xa78b, 0xa7bf,
- 0xa7c2, 0xa7ca,
- 0xa7f5, 0xa7ff,
+ 0xa78b, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa7ff,
0xab30, 0xab5a,
0xab5c, 0xab64,
0xab66, 0xab69,
0xfb00, 0xfb06,
0xff21, 0xff3a,
0xff41, 0xff5a,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
}; /* CR_Latin */
/* 'Greek': Script */
@@ -19739,7 +20523,7 @@ static const OnigCodePoint CR_Greek[] = {
/* 'Cyrillic': Script */
static const OnigCodePoint CR_Cyrillic[] = {
- 8,
+ 10,
0x0400, 0x0484,
0x0487, 0x052f,
0x1c80, 0x1c88,
@@ -19748,6 +20532,8 @@ static const OnigCodePoint CR_Cyrillic[] = {
0x2de0, 0x2dff,
0xa640, 0xa69f,
0xfe2e, 0xfe2f,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
}; /* CR_Cyrillic */
/* 'Armenian': Script */
@@ -19775,30 +20561,31 @@ static const OnigCodePoint CR_Hebrew[] = {
/* 'Arabic': Script */
static const OnigCodePoint CR_Arabic[] = {
- 57,
+ 58,
0x0600, 0x0604,
0x0606, 0x060b,
0x060d, 0x061a,
- 0x061c, 0x061c,
- 0x061e, 0x061e,
+ 0x061c, 0x061e,
0x0620, 0x063f,
0x0641, 0x064a,
0x0656, 0x066f,
0x0671, 0x06dc,
0x06de, 0x06ff,
0x0750, 0x077f,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08c7,
- 0x08d3, 0x08e1,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x08e1,
0x08e3, 0x08ff,
- 0xfb50, 0xfbc1,
+ 0xfb50, 0xfbc2,
0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
+ 0xfd40, 0xfd8f,
0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfd,
+ 0xfdcf, 0xfdcf,
+ 0xfdf0, 0xfdff,
0xfe70, 0xfe74,
0xfe76, 0xfefc,
0x10e60, 0x10e7e,
+ 0x10efd, 0x10eff,
0x1ee00, 0x1ee03,
0x1ee05, 0x1ee1f,
0x1ee21, 0x1ee22,
@@ -19852,11 +20639,12 @@ static const OnigCodePoint CR_Thaana[] = {
/* 'Devanagari': Script */
static const OnigCodePoint CR_Devanagari[] = {
- 4,
+ 5,
0x0900, 0x0950,
0x0955, 0x0963,
0x0966, 0x097f,
0xa8e0, 0xa8ff,
+ 0x11b00, 0x11b09,
}; /* CR_Devanagari */
/* 'Bengali': Script */
@@ -19962,16 +20750,17 @@ static const OnigCodePoint CR_Tamil[] = {
/* 'Telugu': Script */
static const OnigCodePoint CR_Telugu[] = {
- 12,
+ 13,
0x0c00, 0x0c0c,
0x0c0e, 0x0c10,
0x0c12, 0x0c28,
0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
+ 0x0c3c, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
0x0c55, 0x0c56,
0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
0x0c60, 0x0c63,
0x0c66, 0x0c6f,
0x0c77, 0x0c7f,
@@ -19989,10 +20778,10 @@ static const OnigCodePoint CR_Kannada[] = {
0x0cc6, 0x0cc8,
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
+ 0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
}; /* CR_Kannada */
/* 'Malayalam': Script */
@@ -20043,7 +20832,7 @@ static const OnigCodePoint CR_Lao[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
}; /* CR_Lao */
@@ -20104,7 +20893,7 @@ static const OnigCodePoint CR_Hangul[] = {
/* 'Ethiopic': Script */
static const OnigCodePoint CR_Ethiopic[] = {
- 32,
+ 36,
0x1200, 0x1248,
0x124a, 0x124d,
0x1250, 0x1256,
@@ -20137,6 +20926,10 @@ static const OnigCodePoint CR_Ethiopic[] = {
0xab11, 0xab16,
0xab20, 0xab26,
0xab28, 0xab2e,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
}; /* CR_Ethiopic */
/* 'Cherokee': Script */
@@ -20149,9 +20942,10 @@ static const OnigCodePoint CR_Cherokee[] = {
/* 'Canadian_Aboriginal': Script */
static const OnigCodePoint CR_Canadian_Aboriginal[] = {
- 2,
+ 3,
0x1400, 0x167f,
0x18b0, 0x18f5,
+ 0x11ab0, 0x11abf,
}; /* CR_Canadian_Aboriginal */
/* 'Ogham': Script */
@@ -20178,11 +20972,10 @@ static const OnigCodePoint CR_Khmer[] = {
/* 'Mongolian': Script */
static const OnigCodePoint CR_Mongolian[] = {
- 7,
+ 6,
0x1800, 0x1801,
0x1804, 0x1804,
- 0x1806, 0x180e,
- 0x1810, 0x1819,
+ 0x1806, 0x1819,
0x1820, 0x1878,
0x1880, 0x18aa,
0x11660, 0x1166c,
@@ -20190,17 +20983,18 @@ static const OnigCodePoint CR_Mongolian[] = {
/* 'Hiragana': Script */
static const OnigCodePoint CR_Hiragana[] = {
- 5,
+ 6,
0x3041, 0x3096,
0x309d, 0x309f,
- 0x1b001, 0x1b11e,
+ 0x1b001, 0x1b11f,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
0x1f200, 0x1f200,
}; /* CR_Hiragana */
/* 'Katakana': Script */
static const OnigCodePoint CR_Katakana[] = {
- 9,
+ 14,
0x30a1, 0x30fa,
0x30fd, 0x30ff,
0x31f0, 0x31ff,
@@ -20208,7 +21002,12 @@ static const OnigCodePoint CR_Katakana[] = {
0x3300, 0x3357,
0xff66, 0xff6f,
0xff71, 0xff9d,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
0x1b000, 0x1b000,
+ 0x1b120, 0x1b122,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
}; /* CR_Katakana */
@@ -20222,7 +21021,7 @@ static const OnigCodePoint CR_Bopomofo[] = {
/* 'Han': Script */
static const OnigCodePoint CR_Han[] = {
- 19,
+ 21,
0x2e80, 0x2e99,
0x2e9b, 0x2ef3,
0x2f00, 0x2fd5,
@@ -20231,17 +21030,19 @@ static const OnigCodePoint CR_Han[] = {
0x3021, 0x3029,
0x3038, 0x303b,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
+ 0x4e00, 0x9fff,
0xf900, 0xfa6d,
0xfa70, 0xfad9,
+ 0x16fe2, 0x16fe3,
0x16ff0, 0x16ff1,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Han */
/* 'Yi': Script */
@@ -20272,21 +21073,20 @@ static const OnigCodePoint CR_Deseret[] = {
/* 'Inherited': Script */
static const OnigCodePoint CR_Inherited[] = {
- 28,
+ 29,
0x0300, 0x036f,
0x0485, 0x0486,
0x064b, 0x0655,
0x0670, 0x0670,
0x0951, 0x0954,
- 0x1ab0, 0x1ac0,
+ 0x1ab0, 0x1ace,
0x1cd0, 0x1cd2,
0x1cd4, 0x1ce0,
0x1ce2, 0x1ce8,
0x1ced, 0x1ced,
0x1cf4, 0x1cf4,
0x1cf8, 0x1cf9,
- 0x1dc0, 0x1df9,
- 0x1dfb, 0x1dff,
+ 0x1dc0, 0x1dff,
0x200c, 0x200d,
0x20d0, 0x20f0,
0x302a, 0x302d,
@@ -20296,6 +21096,8 @@ static const OnigCodePoint CR_Inherited[] = {
0x101fd, 0x101fd,
0x102e0, 0x102e0,
0x1133b, 0x1133b,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d167, 0x1d169,
0x1d17b, 0x1d182,
0x1d185, 0x1d18b,
@@ -20306,8 +21108,8 @@ static const OnigCodePoint CR_Inherited[] = {
/* 'Tagalog': Script */
static const OnigCodePoint CR_Tagalog[] = {
2,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
+ 0x1700, 0x1715,
+ 0x171f, 0x171f,
}; /* CR_Tagalog */
/* 'Hanunoo': Script */
@@ -20422,9 +21224,8 @@ static const OnigCodePoint CR_New_Tai_Lue[] = {
/* 'Glagolitic': Script */
static const OnigCodePoint CR_Glagolitic[] = {
- 7,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
+ 6,
+ 0x2c00, 0x2c5f,
0x1e000, 0x1e006,
0x1e008, 0x1e018,
0x1e01b, 0x1e021,
@@ -20469,8 +21270,8 @@ static const OnigCodePoint CR_Kharoshthi[] = {
/* 'Balinese': Script */
static const OnigCodePoint CR_Balinese[] = {
2,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
}; /* CR_Balinese */
/* 'Cuneiform': Script */
@@ -20604,9 +21405,8 @@ static const OnigCodePoint CR_Avestan[] = {
/* 'Egyptian_Hieroglyphs': Script */
static const OnigCodePoint CR_Egyptian_Hieroglyphs[] = {
- 2,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 1,
+ 0x13000, 0x13455,
}; /* CR_Egyptian_Hieroglyphs */
/* 'Samaritan': Script */
@@ -20682,7 +21482,7 @@ static const OnigCodePoint CR_Old_Turkic[] = {
/* 'Kaithi': Script */
static const OnigCodePoint CR_Kaithi[] = {
2,
- 0x11080, 0x110c1,
+ 0x11080, 0x110c2,
0x110cd, 0x110cd,
}; /* CR_Kaithi */
@@ -20697,7 +21497,7 @@ static const OnigCodePoint CR_Batak[] = {
static const OnigCodePoint CR_Brahmi[] = {
3,
0x11000, 0x1104d,
- 0x11052, 0x1106f,
+ 0x11052, 0x11075,
0x1107f, 0x1107f,
}; /* CR_Brahmi */
@@ -20753,7 +21553,7 @@ static const OnigCodePoint CR_Sora_Sompeng[] = {
/* 'Takri': Script */
static const OnigCodePoint CR_Takri[] = {
2,
- 0x11680, 0x116b8,
+ 0x11680, 0x116b9,
0x116c0, 0x116c9,
}; /* CR_Takri */
@@ -20821,7 +21621,7 @@ static const OnigCodePoint CR_Pahawh_Hmong[] = {
static const OnigCodePoint CR_Khojki[] = {
2,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
}; /* CR_Khojki */
/* 'Linear_A': Script */
@@ -20939,7 +21739,7 @@ static const OnigCodePoint CR_Ahom[] = {
3,
0x11700, 0x1171a,
0x1171d, 0x1172b,
- 0x11730, 0x1173f,
+ 0x11730, 0x11746,
}; /* CR_Ahom */
/* 'Anatolian_Hieroglyphs': Script */
@@ -21173,6 +21973,58 @@ static const OnigCodePoint CR_Yezidi[] = {
0x10eb0, 0x10eb1,
}; /* CR_Yezidi */
+/* 'Cypro_Minoan': Script */
+static const OnigCodePoint CR_Cypro_Minoan[] = {
+ 1,
+ 0x12f90, 0x12ff2,
+}; /* CR_Cypro_Minoan */
+
+/* 'Old_Uyghur': Script */
+static const OnigCodePoint CR_Old_Uyghur[] = {
+ 1,
+ 0x10f70, 0x10f89,
+}; /* CR_Old_Uyghur */
+
+/* 'Tangsa': Script */
+static const OnigCodePoint CR_Tangsa[] = {
+ 2,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
+}; /* CR_Tangsa */
+
+/* 'Toto': Script */
+static const OnigCodePoint CR_Toto[] = {
+ 1,
+ 0x1e290, 0x1e2ae,
+}; /* CR_Toto */
+
+/* 'Vithkuqi': Script */
+static const OnigCodePoint CR_Vithkuqi[] = {
+ 8,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+}; /* CR_Vithkuqi */
+
+/* 'Kawi': Script */
+static const OnigCodePoint CR_Kawi[] = {
+ 3,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
+}; /* CR_Kawi */
+
+/* 'Nag_Mundari': Script */
+static const OnigCodePoint CR_Nag_Mundari[] = {
+ 1,
+ 0x1e4d0, 0x1e4f9,
+}; /* CR_Nag_Mundari */
+
/* 'White_Space': Binary Property */
#define CR_White_Space CR_Space
@@ -21193,7 +22045,7 @@ static const OnigCodePoint CR_Join_Control[] = {
/* 'Dash': Binary Property */
static const OnigCodePoint CR_Dash[] = {
- 22,
+ 23,
0x002d, 0x002d,
0x058a, 0x058a,
0x05be, 0x05be,
@@ -21208,6 +22060,7 @@ static const OnigCodePoint CR_Dash[] = {
0x2e1a, 0x2e1a,
0x2e3a, 0x2e3b,
0x2e40, 0x2e40,
+ 0x2e5d, 0x2e5d,
0x301c, 0x301c,
0x3030, 0x3030,
0x30a0, 0x30a0,
@@ -21253,7 +22106,7 @@ static const OnigCodePoint CR_Quotation_Mark[] = {
/* 'Terminal_Punctuation': Binary Property */
static const OnigCodePoint CR_Terminal_Punctuation[] = {
- 104,
+ 108,
0x0021, 0x0021,
0x002c, 0x002c,
0x002e, 0x002e,
@@ -21265,7 +22118,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = {
0x05c3, 0x05c3,
0x060c, 0x060c,
0x061b, 0x061b,
- 0x061e, 0x061f,
+ 0x061d, 0x061f,
0x06d4, 0x06d4,
0x0700, 0x070a,
0x070c, 0x070c,
@@ -21289,6 +22142,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = {
0x1aa8, 0x1aab,
0x1b5a, 0x1b5b,
0x1b5d, 0x1b5f,
+ 0x1b7d, 0x1b7e,
0x1c3b, 0x1c3f,
0x1c7e, 0x1c7f,
0x203c, 0x203d,
@@ -21298,6 +22152,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = {
0x2e41, 0x2e41,
0x2e4c, 0x2e4c,
0x2e4e, 0x2e4f,
+ 0x2e53, 0x2e54,
0x3001, 0x3002,
0xa4fe, 0xa4ff,
0xa60d, 0xa60f,
@@ -21328,6 +22183,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = {
0x10b3a, 0x10b3f,
0x10b99, 0x10b9c,
0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
0x11047, 0x1104d,
0x110be, 0x110c1,
0x11141, 0x11143,
@@ -21350,6 +22206,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = {
0x11c41, 0x11c43,
0x11c71, 0x11c71,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f44,
0x12470, 0x12474,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
@@ -21515,7 +22372,7 @@ static const OnigCodePoint CR_Hex_Digit[] = {
/* 'Other_Alphabetic': Binary Property */
static const OnigCodePoint CR_Other_Alphabetic[] = {
- 230,
+ 240,
0x0345, 0x0345,
0x05b0, 0x05bd,
0x05bf, 0x05bf,
@@ -21575,7 +22432,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x0bc6, 0x0bc8,
0x0bca, 0x0bcc,
0x0bd7, 0x0bd7,
- 0x0c00, 0x0c03,
+ 0x0c00, 0x0c04,
0x0c3e, 0x0c44,
0x0c46, 0x0c48,
0x0c4a, 0x0c4c,
@@ -21587,6 +22444,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x0cca, 0x0ccc,
0x0cd5, 0x0cd6,
0x0ce2, 0x0ce3,
+ 0x0cf3, 0x0cf3,
0x0d00, 0x0d03,
0x0d3e, 0x0d44,
0x0d46, 0x0d48,
@@ -21605,7 +22463,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x0eb4, 0x0eb9,
0x0ebb, 0x0ebc,
0x0ecd, 0x0ecd,
- 0x0f71, 0x0f81,
+ 0x0f71, 0x0f83,
0x0f8d, 0x0f97,
0x0f99, 0x0fbc,
0x102b, 0x1036,
@@ -21632,6 +22490,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x1a55, 0x1a5e,
0x1a61, 0x1a74,
0x1abf, 0x1ac0,
+ 0x1acc, 0x1ace,
0x1b00, 0x1b04,
0x1b35, 0x1b43,
0x1b80, 0x1b82,
@@ -21676,8 +22535,10 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x10eab, 0x10eac,
0x11000, 0x11002,
0x11038, 0x11045,
- 0x11082, 0x11082,
+ 0x11073, 0x11074,
+ 0x11080, 0x11082,
0x110b0, 0x110b8,
+ 0x110c2, 0x110c2,
0x11100, 0x11102,
0x11127, 0x11132,
0x11145, 0x11146,
@@ -21687,6 +22548,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x1122c, 0x11234,
0x11237, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112e8,
0x11300, 0x11303,
0x1133e, 0x11344,
@@ -21732,6 +22594,10 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x11d90, 0x11d91,
0x11d93, 0x11d96,
0x11ef3, 0x11ef6,
+ 0x11f00, 0x11f01,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f3a,
+ 0x11f3e, 0x11f40,
0x16f4f, 0x16f4f,
0x16f51, 0x16f87,
0x16f8f, 0x16f92,
@@ -21742,6 +22608,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
0x1e947, 0x1e947,
0x1f130, 0x1f149,
0x1f150, 0x1f169,
@@ -21750,12 +22617,12 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
/* 'Ideographic': Binary Property */
static const OnigCodePoint CR_Ideographic[] = {
- 19,
+ 20,
0x3006, 0x3007,
0x3021, 0x3029,
0x3038, 0x303a,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
+ 0x4e00, 0x9fff,
0xf900, 0xfa6d,
0xfa70, 0xfad9,
0x16fe4, 0x16fe4,
@@ -21763,18 +22630,19 @@ static const OnigCodePoint CR_Ideographic[] = {
0x18800, 0x18cd5,
0x18d00, 0x18d08,
0x1b170, 0x1b2fb,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Ideographic */
/* 'Diacritic': Binary Property */
static const OnigCodePoint CR_Diacritic[] = {
- 176,
+ 195,
0x005e, 0x005e,
0x0060, 0x0060,
0x00a8, 0x00a8,
@@ -21803,6 +22671,8 @@ static const OnigCodePoint CR_Diacritic[] = {
0x07a6, 0x07b0,
0x07eb, 0x07f5,
0x0818, 0x0819,
+ 0x0898, 0x089f,
+ 0x08c9, 0x08d2,
0x08e3, 0x08fe,
0x093c, 0x093c,
0x094d, 0x094d,
@@ -21819,6 +22689,7 @@ static const OnigCodePoint CR_Diacritic[] = {
0x0b4d, 0x0b4d,
0x0b55, 0x0b55,
0x0bcd, 0x0bcd,
+ 0x0c3c, 0x0c3c,
0x0c4d, 0x0c4d,
0x0cbc, 0x0cbc,
0x0ccd, 0x0ccd,
@@ -21845,12 +22716,14 @@ static const OnigCodePoint CR_Diacritic[] = {
0x108f, 0x108f,
0x109a, 0x109b,
0x135d, 0x135f,
+ 0x1714, 0x1715,
0x17c9, 0x17d3,
0x17dd, 0x17dd,
0x1939, 0x193b,
0x1a75, 0x1a7c,
0x1a7f, 0x1a7f,
- 0x1ab0, 0x1abd,
+ 0x1ab0, 0x1abe,
+ 0x1ac1, 0x1acb,
0x1b34, 0x1b34,
0x1b44, 0x1b44,
0x1b6b, 0x1b73,
@@ -21863,8 +22736,7 @@ static const OnigCodePoint CR_Diacritic[] = {
0x1cf7, 0x1cf9,
0x1d2c, 0x1d6a,
0x1dc4, 0x1dcf,
- 0x1df5, 0x1df9,
- 0x1dfd, 0x1dff,
+ 0x1df5, 0x1dff,
0x1fbd, 0x1fbd,
0x1fbf, 0x1fc1,
0x1fcd, 0x1fcf,
@@ -21905,9 +22777,16 @@ static const OnigCodePoint CR_Diacritic[] = {
0xff9e, 0xff9f,
0xffe3, 0xffe3,
0x102e0, 0x102e0,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10ae5, 0x10ae6,
0x10d22, 0x10d27,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11046, 0x11046,
+ 0x11070, 0x11070,
0x110b9, 0x110ba,
0x11133, 0x11134,
0x11173, 0x11173,
@@ -21937,16 +22816,24 @@ static const OnigCodePoint CR_Diacritic[] = {
0x11d42, 0x11d42,
0x11d44, 0x11d45,
0x11d97, 0x11d97,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16f8f, 0x16f9f,
0x16ff0, 0x16ff1,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d167, 0x1d169,
0x1d16d, 0x1d172,
0x1d17b, 0x1d182,
0x1d185, 0x1d18b,
0x1d1aa, 0x1d1ad,
+ 0x1e030, 0x1e06d,
0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
0x1e8d0, 0x1e8d6,
0x1e944, 0x1e946,
@@ -21955,7 +22842,7 @@ static const OnigCodePoint CR_Diacritic[] = {
/* 'Extender': Binary Property */
static const OnigCodePoint CR_Extender[] = {
- 32,
+ 33,
0x00b7, 0x00b7,
0x02d0, 0x02d1,
0x0640, 0x0640,
@@ -21980,6 +22867,7 @@ static const OnigCodePoint CR_Extender[] = {
0xaadd, 0xaadd,
0xaaf3, 0xaaf4,
0xff70, 0xff70,
+ 0x10781, 0x10782,
0x1135d, 0x1135d,
0x115c6, 0x115c8,
0x11a98, 0x11a98,
@@ -21992,7 +22880,7 @@ static const OnigCodePoint CR_Extender[] = {
/* 'Other_Lowercase': Binary Property */
static const OnigCodePoint CR_Other_Lowercase[] = {
- 20,
+ 28,
0x00aa, 0x00aa,
0x00ba, 0x00ba,
0x02b0, 0x02b8,
@@ -22000,6 +22888,7 @@ static const OnigCodePoint CR_Other_Lowercase[] = {
0x02e0, 0x02e4,
0x0345, 0x0345,
0x037a, 0x037a,
+ 0x10fc, 0x10fc,
0x1d2c, 0x1d6a,
0x1d78, 0x1d78,
0x1d9b, 0x1dbf,
@@ -22011,8 +22900,15 @@ static const OnigCodePoint CR_Other_Lowercase[] = {
0x2c7c, 0x2c7d,
0xa69c, 0xa69d,
0xa770, 0xa770,
+ 0xa7f2, 0xa7f4,
0xa7f8, 0xa7f9,
0xab5c, 0xab5f,
+ 0xab69, 0xab69,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x1e030, 0x1e06d,
}; /* CR_Other_Lowercase */
/* 'Other_Uppercase': Binary Property */
@@ -22101,9 +22997,9 @@ static const OnigCodePoint CR_Radical[] = {
/* 'Unified_Ideograph': Binary Property */
static const OnigCodePoint CR_Unified_Ideograph[] = {
- 15,
+ 16,
0x3400, 0x4dbf,
- 0x4e00, 0x9ffc,
+ 0x4e00, 0x9fff,
0xfa0e, 0xfa0f,
0xfa11, 0xfa11,
0xfa13, 0xfa14,
@@ -22111,12 +23007,13 @@ static const OnigCodePoint CR_Unified_Ideograph[] = {
0xfa21, 0xfa21,
0xfa23, 0xfa24,
0xfa27, 0xfa29,
- 0x20000, 0x2a6dd,
- 0x2a700, 0x2b734,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Unified_Ideograph */
/* 'Other_Default_Ignorable_Code_Point': Binary Property */
@@ -22150,7 +23047,7 @@ static const OnigCodePoint CR_Deprecated[] = {
/* 'Soft_Dotted': Binary Property */
static const OnigCodePoint CR_Soft_Dotted[] = {
- 31,
+ 34,
0x0069, 0x006a,
0x012f, 0x012f,
0x0249, 0x0249,
@@ -22182,6 +23079,9 @@ static const OnigCodePoint CR_Soft_Dotted[] = {
0x1d62a, 0x1d62b,
0x1d65e, 0x1d65f,
0x1d692, 0x1d693,
+ 0x1df1a, 0x1df1a,
+ 0x1e04c, 0x1e04d,
+ 0x1e068, 0x1e068,
}; /* CR_Soft_Dotted */
/* 'Logical_Order_Exception': Binary Property */
@@ -22216,12 +23116,12 @@ static const OnigCodePoint CR_Other_ID_Continue[] = {
/* 'Sentence_Terminal': Binary Property */
static const OnigCodePoint CR_Sentence_Terminal[] = {
- 76,
+ 80,
0x0021, 0x0021,
0x002e, 0x002e,
0x003f, 0x003f,
0x0589, 0x0589,
- 0x061e, 0x061f,
+ 0x061d, 0x061f,
0x06d4, 0x06d4,
0x0700, 0x0702,
0x07f9, 0x07f9,
@@ -22240,12 +23140,14 @@ static const OnigCodePoint CR_Sentence_Terminal[] = {
0x1aa8, 0x1aab,
0x1b5a, 0x1b5b,
0x1b5e, 0x1b5f,
+ 0x1b7d, 0x1b7e,
0x1c3b, 0x1c3c,
0x1c7e, 0x1c7f,
0x203c, 0x203d,
0x2047, 0x2049,
0x2e2e, 0x2e2e,
0x2e3c, 0x2e3c,
+ 0x2e53, 0x2e54,
0x3002, 0x3002,
0xa4ff, 0xa4ff,
0xa60e, 0xa60f,
@@ -22266,6 +23168,7 @@ static const OnigCodePoint CR_Sentence_Terminal[] = {
0xff61, 0xff61,
0x10a56, 0x10a57,
0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
0x11047, 0x11048,
0x110be, 0x110c1,
0x11141, 0x11143,
@@ -22286,6 +23189,7 @@ static const OnigCodePoint CR_Sentence_Terminal[] = {
0x11a9b, 0x11a9c,
0x11c41, 0x11c42,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f44,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
0x16b37, 0x16b38,
@@ -22297,8 +23201,9 @@ static const OnigCodePoint CR_Sentence_Terminal[] = {
/* 'Variation_Selector': Binary Property */
static const OnigCodePoint CR_Variation_Selector[] = {
- 3,
+ 4,
0x180b, 0x180d,
+ 0x180f, 0x180f,
0xfe00, 0xfe0f,
0xe0100, 0xe01ef,
}; /* CR_Variation_Selector */
@@ -22348,10 +23253,11 @@ static const OnigCodePoint CR_Pattern_Syntax[] = {
/* 'Prepended_Concatenation_Mark': Binary Property */
static const OnigCodePoint CR_Prepended_Concatenation_Mark[] = {
- 6,
+ 7,
0x0600, 0x0605,
0x06dd, 0x06dd,
0x070f, 0x070f,
+ 0x0890, 0x0891,
0x08e2, 0x08e2,
0x110bd, 0x110bd,
0x110cd, 0x110cd,
@@ -22365,7 +23271,7 @@ static const OnigCodePoint CR_Regional_Indicator[] = {
/* 'Emoji': Emoji */
static const OnigCodePoint CR_Emoji[] = {
- 152,
+ 151,
0x0023, 0x0023,
0x002a, 0x002a,
0x0030, 0x0039,
@@ -22500,24 +23406,23 @@ static const OnigCodePoint CR_Emoji[] = {
0x1f680, 0x1f6c5,
0x1f6cb, 0x1f6d2,
0x1f6d5, 0x1f6d7,
- 0x1f6e0, 0x1f6e5,
+ 0x1f6dc, 0x1f6e5,
0x1f6e9, 0x1f6e9,
0x1f6eb, 0x1f6ec,
0x1f6f0, 0x1f6f0,
0x1f6f3, 0x1f6fc,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f90c, 0x1f93a,
0x1f93c, 0x1f945,
- 0x1f947, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1f9ff,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1f947, 0x1f9ff,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
}; /* CR_Emoji */
/* 'Emoji_Presentation': Emoji */
@@ -22589,21 +23494,21 @@ static const OnigCodePoint CR_Emoji_Presentation[] = {
0x1f6cc, 0x1f6cc,
0x1f6d0, 0x1f6d2,
0x1f6d5, 0x1f6d7,
+ 0x1f6dc, 0x1f6df,
0x1f6eb, 0x1f6ec,
0x1f6f4, 0x1f6fc,
0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
0x1f90c, 0x1f93a,
0x1f93c, 0x1f945,
- 0x1f947, 0x1f978,
- 0x1f97a, 0x1f9cb,
- 0x1f9cd, 0x1f9ff,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faa8,
- 0x1fab0, 0x1fab6,
- 0x1fac0, 0x1fac2,
- 0x1fad0, 0x1fad6,
+ 0x1f947, 0x1f9ff,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
}; /* CR_Emoji_Presentation */
/* 'Emoji_Modifier': Emoji */
@@ -22614,7 +23519,7 @@ static const OnigCodePoint CR_Emoji_Modifier[] = {
/* 'Emoji_Modifier_Base': Emoji */
static const OnigCodePoint CR_Emoji_Modifier_Base[] = {
- 38,
+ 40,
0x261d, 0x261d,
0x26f9, 0x26f9,
0x270a, 0x270d,
@@ -22653,6 +23558,8 @@ static const OnigCodePoint CR_Emoji_Modifier_Base[] = {
0x1f9bb, 0x1f9bb,
0x1f9cd, 0x1f9cf,
0x1f9d1, 0x1f9dd,
+ 0x1fac3, 0x1fac5,
+ 0x1faf0, 0x1faf8,
}; /* CR_Emoji_Modifier_Base */
/* 'Emoji_Component': Emoji */
@@ -22755,7 +23662,7 @@ static const OnigCodePoint CR_Extended_Pictographic[] = {
/* 'Unknown': Script */
static const OnigCodePoint CR_Unknown[] = {
- 675,
+ 705,
0x0378, 0x0379,
0x0380, 0x0383,
0x038b, 0x038b,
@@ -22768,7 +23675,6 @@ static const OnigCodePoint CR_Unknown[] = {
0x05c8, 0x05cf,
0x05eb, 0x05ee,
0x05f5, 0x05ff,
- 0x061d, 0x061d,
0x070e, 0x070e,
0x074b, 0x074c,
0x07b2, 0x07bf,
@@ -22777,9 +23683,9 @@ static const OnigCodePoint CR_Unknown[] = {
0x083f, 0x083f,
0x085c, 0x085d,
0x085f, 0x085f,
- 0x086b, 0x089f,
- 0x08b5, 0x08b5,
- 0x08c8, 0x08d2,
+ 0x086b, 0x086f,
+ 0x088f, 0x088f,
+ 0x0892, 0x0897,
0x0984, 0x0984,
0x098d, 0x098e,
0x0991, 0x0992,
@@ -22857,12 +23763,13 @@ static const OnigCodePoint CR_Unknown[] = {
0x0c0d, 0x0c0d,
0x0c11, 0x0c11,
0x0c29, 0x0c29,
- 0x0c3a, 0x0c3c,
+ 0x0c3a, 0x0c3b,
0x0c45, 0x0c45,
0x0c49, 0x0c49,
0x0c4e, 0x0c54,
0x0c57, 0x0c57,
- 0x0c5b, 0x0c5f,
+ 0x0c5b, 0x0c5c,
+ 0x0c5e, 0x0c5f,
0x0c64, 0x0c65,
0x0c70, 0x0c76,
0x0c8d, 0x0c8d,
@@ -22873,11 +23780,11 @@ static const OnigCodePoint CR_Unknown[] = {
0x0cc5, 0x0cc5,
0x0cc9, 0x0cc9,
0x0cce, 0x0cd4,
- 0x0cd7, 0x0cdd,
+ 0x0cd7, 0x0cdc,
0x0cdf, 0x0cdf,
0x0ce4, 0x0ce5,
0x0cf0, 0x0cf0,
- 0x0cf3, 0x0cff,
+ 0x0cf4, 0x0cff,
0x0d0d, 0x0d0d,
0x0d11, 0x0d11,
0x0d45, 0x0d45,
@@ -22907,7 +23814,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x0ebe, 0x0ebf,
0x0ec5, 0x0ec5,
0x0ec7, 0x0ec7,
- 0x0ece, 0x0ecf,
+ 0x0ecf, 0x0ecf,
0x0eda, 0x0edb,
0x0ee0, 0x0eff,
0x0f48, 0x0f48,
@@ -22941,8 +23848,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x13fe, 0x13ff,
0x169d, 0x169f,
0x16f9, 0x16ff,
- 0x170d, 0x170d,
- 0x1715, 0x171f,
+ 0x1716, 0x171e,
0x1737, 0x173f,
0x1754, 0x175f,
0x176d, 0x176d,
@@ -22951,7 +23857,6 @@ static const OnigCodePoint CR_Unknown[] = {
0x17de, 0x17df,
0x17ea, 0x17ef,
0x17fa, 0x17ff,
- 0x180f, 0x180f,
0x181a, 0x181f,
0x1879, 0x187f,
0x18ab, 0x18af,
@@ -22971,9 +23876,9 @@ static const OnigCodePoint CR_Unknown[] = {
0x1a8a, 0x1a8f,
0x1a9a, 0x1a9f,
0x1aae, 0x1aaf,
- 0x1ac1, 0x1aff,
- 0x1b4c, 0x1b4f,
- 0x1b7d, 0x1b7f,
+ 0x1acf, 0x1aff,
+ 0x1b4d, 0x1b4f,
+ 0x1b7f, 0x1b7f,
0x1bf4, 0x1bfb,
0x1c38, 0x1c3a,
0x1c4a, 0x1c4c,
@@ -22981,7 +23886,6 @@ static const OnigCodePoint CR_Unknown[] = {
0x1cbb, 0x1cbc,
0x1cc8, 0x1ccf,
0x1cfb, 0x1cff,
- 0x1dfa, 0x1dfa,
0x1f16, 0x1f17,
0x1f1e, 0x1f1f,
0x1f46, 0x1f47,
@@ -23002,15 +23906,13 @@ static const OnigCodePoint CR_Unknown[] = {
0x2072, 0x2073,
0x208f, 0x208f,
0x209d, 0x209f,
- 0x20c0, 0x20cf,
+ 0x20c1, 0x20cf,
0x20f1, 0x20ff,
0x218c, 0x218f,
0x2427, 0x243f,
0x244b, 0x245f,
0x2b74, 0x2b75,
0x2b96, 0x2b96,
- 0x2c2f, 0x2c2f,
- 0x2c5f, 0x2c5f,
0x2cf4, 0x2cf8,
0x2d26, 0x2d26,
0x2d28, 0x2d2c,
@@ -23026,7 +23928,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x2dcf, 0x2dcf,
0x2dd7, 0x2dd7,
0x2ddf, 0x2ddf,
- 0x2e53, 0x2e7f,
+ 0x2e5e, 0x2e7f,
0x2e9a, 0x2e9a,
0x2ef4, 0x2eff,
0x2fd6, 0x2fef,
@@ -23038,13 +23940,14 @@ static const OnigCodePoint CR_Unknown[] = {
0x318f, 0x318f,
0x31e4, 0x31ef,
0x321f, 0x321f,
- 0x9ffd, 0x9fff,
0xa48d, 0xa48f,
0xa4c7, 0xa4cf,
0xa62c, 0xa63f,
0xa6f8, 0xa6ff,
- 0xa7c0, 0xa7c1,
- 0xa7cb, 0xa7f4,
+ 0xa7cb, 0xa7cf,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7da, 0xa7f1,
0xa82d, 0xa82f,
0xa83a, 0xa83f,
0xa878, 0xa87f,
@@ -23080,11 +23983,10 @@ static const OnigCodePoint CR_Unknown[] = {
0xfb3f, 0xfb3f,
0xfb42, 0xfb42,
0xfb45, 0xfb45,
- 0xfbc2, 0xfbd2,
- 0xfd40, 0xfd4f,
+ 0xfbc3, 0xfbd2,
0xfd90, 0xfd91,
- 0xfdc8, 0xfdef,
- 0xfdfe, 0xfdff,
+ 0xfdc8, 0xfdce,
+ 0xfdd0, 0xfdef,
0xfe1a, 0xfe1f,
0xfe53, 0xfe53,
0xfe67, 0xfe67,
@@ -23128,10 +24030,20 @@ static const OnigCodePoint CR_Unknown[] = {
0x104fc, 0x104ff,
0x10528, 0x1052f,
0x10564, 0x1056e,
- 0x10570, 0x105ff,
+ 0x1057b, 0x1057b,
+ 0x1058b, 0x1058b,
+ 0x10593, 0x10593,
+ 0x10596, 0x10596,
+ 0x105a2, 0x105a2,
+ 0x105b2, 0x105b2,
+ 0x105ba, 0x105ba,
+ 0x105bd, 0x105ff,
0x10737, 0x1073f,
0x10756, 0x1075f,
- 0x10768, 0x107ff,
+ 0x10768, 0x1077f,
+ 0x10786, 0x10786,
+ 0x107b1, 0x107b1,
+ 0x107bb, 0x107ff,
0x10806, 0x10807,
0x10809, 0x10809,
0x10836, 0x10836,
@@ -23172,14 +24084,15 @@ static const OnigCodePoint CR_Unknown[] = {
0x10e7f, 0x10e7f,
0x10eaa, 0x10eaa,
0x10eae, 0x10eaf,
- 0x10eb2, 0x10eff,
+ 0x10eb2, 0x10efc,
0x10f28, 0x10f2f,
- 0x10f5a, 0x10faf,
+ 0x10f5a, 0x10f6f,
+ 0x10f8a, 0x10faf,
0x10fcc, 0x10fdf,
0x10ff7, 0x10fff,
0x1104e, 0x11051,
- 0x11070, 0x1107e,
- 0x110c2, 0x110cc,
+ 0x11076, 0x1107e,
+ 0x110c3, 0x110cc,
0x110ce, 0x110cf,
0x110e9, 0x110ef,
0x110fa, 0x110ff,
@@ -23189,7 +24102,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x111e0, 0x111e0,
0x111f5, 0x111ff,
0x11212, 0x11212,
- 0x1123f, 0x1127f,
+ 0x11242, 0x1127f,
0x11287, 0x11287,
0x11289, 0x11289,
0x1128e, 0x1128e,
@@ -23221,11 +24134,11 @@ static const OnigCodePoint CR_Unknown[] = {
0x11645, 0x1164f,
0x1165a, 0x1165f,
0x1166d, 0x1167f,
- 0x116b9, 0x116bf,
+ 0x116ba, 0x116bf,
0x116ca, 0x116ff,
0x1171b, 0x1171c,
0x1172c, 0x1172f,
- 0x11740, 0x117ff,
+ 0x11747, 0x117ff,
0x1183c, 0x1189f,
0x118f3, 0x118fe,
0x11907, 0x11908,
@@ -23240,8 +24153,9 @@ static const OnigCodePoint CR_Unknown[] = {
0x119d8, 0x119d9,
0x119e5, 0x119ff,
0x11a48, 0x11a4f,
- 0x11aa3, 0x11abf,
- 0x11af9, 0x11bff,
+ 0x11aa3, 0x11aaf,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11bff,
0x11c09, 0x11c09,
0x11c37, 0x11c37,
0x11c46, 0x11c4f,
@@ -23262,20 +24176,24 @@ static const OnigCodePoint CR_Unknown[] = {
0x11d92, 0x11d92,
0x11d99, 0x11d9f,
0x11daa, 0x11edf,
- 0x11ef9, 0x11faf,
+ 0x11ef9, 0x11eff,
+ 0x11f11, 0x11f11,
+ 0x11f3b, 0x11f3d,
+ 0x11f5a, 0x11faf,
0x11fb1, 0x11fbf,
0x11ff2, 0x11ffe,
0x1239a, 0x123ff,
0x1246f, 0x1246f,
0x12475, 0x1247f,
- 0x12544, 0x12fff,
- 0x1342f, 0x1342f,
- 0x13439, 0x143ff,
+ 0x12544, 0x12f8f,
+ 0x12ff3, 0x12fff,
+ 0x13456, 0x143ff,
0x14647, 0x167ff,
0x16a39, 0x16a3f,
0x16a5f, 0x16a5f,
0x16a6a, 0x16a6d,
- 0x16a70, 0x16acf,
+ 0x16abf, 0x16abf,
+ 0x16aca, 0x16acf,
0x16aee, 0x16aef,
0x16af6, 0x16aff,
0x16b46, 0x16b4f,
@@ -23291,20 +24209,29 @@ static const OnigCodePoint CR_Unknown[] = {
0x16ff2, 0x16fff,
0x187f8, 0x187ff,
0x18cd6, 0x18cff,
- 0x18d09, 0x1afff,
- 0x1b11f, 0x1b14f,
- 0x1b153, 0x1b163,
+ 0x18d09, 0x1afef,
+ 0x1aff4, 0x1aff4,
+ 0x1affc, 0x1affc,
+ 0x1afff, 0x1afff,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
0x1b168, 0x1b16f,
0x1b2fc, 0x1bbff,
0x1bc6b, 0x1bc6f,
0x1bc7d, 0x1bc7f,
0x1bc89, 0x1bc8f,
0x1bc9a, 0x1bc9b,
- 0x1bca4, 0x1cfff,
+ 0x1bca4, 0x1ceff,
+ 0x1cf2e, 0x1cf2f,
+ 0x1cf47, 0x1cf4f,
+ 0x1cfc4, 0x1cfff,
0x1d0f6, 0x1d0ff,
0x1d127, 0x1d128,
- 0x1d1e9, 0x1d1ff,
- 0x1d246, 0x1d2df,
+ 0x1d1eb, 0x1d1ff,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
0x1d2f4, 0x1d2ff,
0x1d357, 0x1d35f,
0x1d379, 0x1d3ff,
@@ -23330,18 +24257,28 @@ static const OnigCodePoint CR_Unknown[] = {
0x1d7cc, 0x1d7cd,
0x1da8c, 0x1da9a,
0x1daa0, 0x1daa0,
- 0x1dab0, 0x1dfff,
+ 0x1dab0, 0x1deff,
+ 0x1df1f, 0x1df24,
+ 0x1df2b, 0x1dfff,
0x1e007, 0x1e007,
0x1e019, 0x1e01a,
0x1e022, 0x1e022,
0x1e025, 0x1e025,
- 0x1e02b, 0x1e0ff,
+ 0x1e02b, 0x1e02f,
+ 0x1e06e, 0x1e08e,
+ 0x1e090, 0x1e0ff,
0x1e12d, 0x1e12f,
0x1e13e, 0x1e13f,
0x1e14a, 0x1e14d,
- 0x1e150, 0x1e2bf,
+ 0x1e150, 0x1e28f,
+ 0x1e2af, 0x1e2bf,
0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e7ff,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e7df,
+ 0x1e7e7, 0x1e7e7,
+ 0x1e7ec, 0x1e7ec,
+ 0x1e7ef, 0x1e7ef,
+ 0x1e7ff, 0x1e7ff,
0x1e8c5, 0x1e8c6,
0x1e8d7, 0x1e8ff,
0x1e94c, 0x1e94f,
@@ -23395,39 +24332,39 @@ static const OnigCodePoint CR_Unknown[] = {
0x1f249, 0x1f24f,
0x1f252, 0x1f25f,
0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6df,
+ 0x1f6d8, 0x1f6db,
0x1f6ed, 0x1f6ef,
0x1f6fd, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d9, 0x1f7df,
- 0x1f7ec, 0x1f7ff,
+ 0x1f777, 0x1f77a,
+ 0x1f7da, 0x1f7df,
+ 0x1f7ec, 0x1f7ef,
+ 0x1f7f1, 0x1f7ff,
0x1f80c, 0x1f80f,
0x1f848, 0x1f84f,
0x1f85a, 0x1f85f,
0x1f888, 0x1f88f,
0x1f8ae, 0x1f8af,
0x1f8b2, 0x1f8ff,
- 0x1f979, 0x1f979,
- 0x1f9cc, 0x1f9cc,
0x1fa54, 0x1fa5f,
0x1fa6e, 0x1fa6f,
- 0x1fa75, 0x1fa77,
- 0x1fa7b, 0x1fa7f,
- 0x1fa87, 0x1fa8f,
- 0x1faa9, 0x1faaf,
- 0x1fab7, 0x1fabf,
- 0x1fac3, 0x1facf,
- 0x1fad7, 0x1faff,
+ 0x1fa7d, 0x1fa7f,
+ 0x1fa89, 0x1fa8f,
+ 0x1fabe, 0x1fabe,
+ 0x1fac6, 0x1facd,
+ 0x1fadc, 0x1fadf,
+ 0x1fae9, 0x1faef,
+ 0x1faf9, 0x1faff,
0x1fb93, 0x1fb93,
0x1fbcb, 0x1fbef,
0x1fbfa, 0x1ffff,
- 0x2a6de, 0x2a6ff,
- 0x2b735, 0x2b73f,
+ 0x2a6e0, 0x2a6ff,
+ 0x2b73a, 0x2b73f,
0x2b81e, 0x2b81f,
0x2cea2, 0x2ceaf,
0x2ebe1, 0x2f7ff,
0x2fa1e, 0x2ffff,
- 0x3134b, 0xe0000,
+ 0x3134b, 0x3134f,
+ 0x323b0, 0xe0000,
0xe0002, 0xe001f,
0xe0080, 0xe00ff,
0xe01f0, 0x10ffff,
@@ -35266,13 +36203,1445 @@ static const OnigCodePoint CR_Age_13_0[] = {
0xefffe, 0x10ffff,
}; /* CR_Age_13_0 */
+/* 'Age_14_0': Derived Age 14.0 */
+static const OnigCodePoint CR_Age_14_0[] = {
+ 706,
+ 0x0000, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f4,
+ 0x0600, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a76,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0ae6, 0x0af1,
+ 0x0af9, 0x0aff,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b55, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b63,
+ 0x0b66, 0x0b77,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd0, 0x0bd0,
+ 0x0bd7, 0x0bd7,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdd, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fce, 0x0fda,
+ 0x1000, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x1248,
+ 0x124a, 0x124d,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125a, 0x125d,
+ 0x1260, 0x1288,
+ 0x128a, 0x128d,
+ 0x1290, 0x12b0,
+ 0x12b2, 0x12b5,
+ 0x12b8, 0x12be,
+ 0x12c0, 0x12c0,
+ 0x12c2, 0x12c5,
+ 0x12c8, 0x12d6,
+ 0x12d8, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x135a,
+ 0x135d, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f8,
+ 0x1700, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19da,
+ 0x19de, 0x1a1b,
+ 0x1a1e, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa0, 0x1aad,
+ 0x1ab0, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x2064,
+ 0x2066, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20c0,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b97, 0x2cf3,
+ 0x2cf9, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d70,
+ 0x2d7f, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa82c,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c5,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaac2,
+ 0xaadb, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab6b,
+ 0xab70, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xd800, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbc2,
+ 0xfbd3, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdcf, 0xfe19,
+ 0xfe20, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfff9, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10100, 0x10102,
+ 0x10107, 0x10133,
+ 0x10137, 0x1018e,
+ 0x10190, 0x1019c,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102fb,
+ 0x10300, 0x10323,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1089e,
+ 0x108a7, 0x108af,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x108fb, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10980, 0x109b7,
+ 0x109bc, 0x109cf,
+ 0x109d2, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a48,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a9f,
+ 0x10ac0, 0x10ae6,
+ 0x10aeb, 0x10af6,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b91,
+ 0x10b99, 0x10b9c,
+ 0x10ba9, 0x10baf,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10cfa, 0x10d27,
+ 0x10d30, 0x10d39,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10f00, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x1123e,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a9,
+ 0x112b0, 0x112ea,
+ 0x112f0, 0x112f9,
+ 0x11300, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133b, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 0x11800, 0x1183b,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x11946,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119e4,
+ 0x11a00, 0x11a47,
+ 0x11a50, 0x11aa2,
+ 0x11ab0, 0x11af8,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c45,
+ 0x11c50, 0x11c6c,
+ 0x11c70, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d47,
+ 0x11d50, 0x11d59,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d98,
+ 0x11da0, 0x11da9,
+ 0x11ee0, 0x11ef8,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x1342e,
+ 0x13430, 0x13438,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16e40, 0x16e9a,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x17000, 0x187f7,
+ 0x18800, 0x18cd5,
+ 0x18d00, 0x18d08,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b150, 0x1b152,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 0x1e95e, 0x1e95f,
+ 0x1ec71, 0x1ecb4,
+ 0x1ed01, 0x1ed3d,
+ 0x1ee00, 0x1ee03,
+ 0x1ee05, 0x1ee1f,
+ 0x1ee21, 0x1ee22,
+ 0x1ee24, 0x1ee24,
+ 0x1ee27, 0x1ee27,
+ 0x1ee29, 0x1ee32,
+ 0x1ee34, 0x1ee37,
+ 0x1ee39, 0x1ee39,
+ 0x1ee3b, 0x1ee3b,
+ 0x1ee42, 0x1ee42,
+ 0x1ee47, 0x1ee47,
+ 0x1ee49, 0x1ee49,
+ 0x1ee4b, 0x1ee4b,
+ 0x1ee4d, 0x1ee4f,
+ 0x1ee51, 0x1ee52,
+ 0x1ee54, 0x1ee54,
+ 0x1ee57, 0x1ee57,
+ 0x1ee59, 0x1ee59,
+ 0x1ee5b, 0x1ee5b,
+ 0x1ee5d, 0x1ee5d,
+ 0x1ee5f, 0x1ee5f,
+ 0x1ee61, 0x1ee62,
+ 0x1ee64, 0x1ee64,
+ 0x1ee67, 0x1ee6a,
+ 0x1ee6c, 0x1ee72,
+ 0x1ee74, 0x1ee77,
+ 0x1ee79, 0x1ee7c,
+ 0x1ee7e, 0x1ee7e,
+ 0x1ee80, 0x1ee89,
+ 0x1ee8b, 0x1ee9b,
+ 0x1eea1, 0x1eea3,
+ 0x1eea5, 0x1eea9,
+ 0x1eeab, 0x1eebb,
+ 0x1eef0, 0x1eef1,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0bf,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0f5,
+ 0x1f100, 0x1f1ad,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d7,
+ 0x1f6dd, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d8,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8b1,
+ 0x1f900, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa74,
+ 0x1fa78, 0x1fa7c,
+ 0x1fa80, 0x1fa86,
+ 0x1fa90, 0x1faac,
+ 0x1fab0, 0x1faba,
+ 0x1fac0, 0x1fac5,
+ 0x1fad0, 0x1fad9,
+ 0x1fae0, 0x1fae7,
+ 0x1faf0, 0x1faf6,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbca,
+ 0x1fbf0, 0x1fbf9,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b738,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x3134a,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_14_0 */
+
+/* 'Age_15_0': Derived Age 15.0 */
+static const OnigCodePoint CR_Age_15_0[] = {
+ 715,
+ 0x0000, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f4,
+ 0x0600, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a76,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0ae6, 0x0af1,
+ 0x0af9, 0x0aff,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b55, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b63,
+ 0x0b66, 0x0b77,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd0, 0x0bd0,
+ 0x0bd7, 0x0bd7,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdd, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fce, 0x0fda,
+ 0x1000, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x1248,
+ 0x124a, 0x124d,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125a, 0x125d,
+ 0x1260, 0x1288,
+ 0x128a, 0x128d,
+ 0x1290, 0x12b0,
+ 0x12b2, 0x12b5,
+ 0x12b8, 0x12be,
+ 0x12c0, 0x12c0,
+ 0x12c2, 0x12c5,
+ 0x12c8, 0x12d6,
+ 0x12d8, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x135a,
+ 0x135d, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f8,
+ 0x1700, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19da,
+ 0x19de, 0x1a1b,
+ 0x1a1e, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa0, 0x1aad,
+ 0x1ab0, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x2064,
+ 0x2066, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20c0,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b97, 0x2cf3,
+ 0x2cf9, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d70,
+ 0x2d7f, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 0xa82c,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c5,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaac2,
+ 0xaadb, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab6b,
+ 0xab70, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xd800, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbc2,
+ 0xfbd3, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdcf, 0xfe19,
+ 0xfe20, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfff9, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10100, 0x10102,
+ 0x10107, 0x10133,
+ 0x10137, 0x1018e,
+ 0x10190, 0x1019c,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102fb,
+ 0x10300, 0x10323,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1089e,
+ 0x108a7, 0x108af,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x108fb, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10980, 0x109b7,
+ 0x109bc, 0x109cf,
+ 0x109d2, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a48,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a9f,
+ 0x10ac0, 0x10ae6,
+ 0x10aeb, 0x10af6,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b91,
+ 0x10b99, 0x10b9c,
+ 0x10ba9, 0x10baf,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10cfa, 0x10d27,
+ 0x10d30, 0x10d39,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10efd, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a9,
+ 0x112b0, 0x112ea,
+ 0x112f0, 0x112f9,
+ 0x11300, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133b, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 0x11800, 0x1183b,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x11946,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119e4,
+ 0x11a00, 0x11a47,
+ 0x11a50, 0x11aa2,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c45,
+ 0x11c50, 0x11c6c,
+ 0x11c70, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d47,
+ 0x11d50, 0x11d59,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d98,
+ 0x11da0, 0x11da9,
+ 0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16e40, 0x16e9a,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x17000, 0x187f7,
+ 0x18800, 0x18cd5,
+ 0x18d00, 0x18d08,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 0x1e95e, 0x1e95f,
+ 0x1ec71, 0x1ecb4,
+ 0x1ed01, 0x1ed3d,
+ 0x1ee00, 0x1ee03,
+ 0x1ee05, 0x1ee1f,
+ 0x1ee21, 0x1ee22,
+ 0x1ee24, 0x1ee24,
+ 0x1ee27, 0x1ee27,
+ 0x1ee29, 0x1ee32,
+ 0x1ee34, 0x1ee37,
+ 0x1ee39, 0x1ee39,
+ 0x1ee3b, 0x1ee3b,
+ 0x1ee42, 0x1ee42,
+ 0x1ee47, 0x1ee47,
+ 0x1ee49, 0x1ee49,
+ 0x1ee4b, 0x1ee4b,
+ 0x1ee4d, 0x1ee4f,
+ 0x1ee51, 0x1ee52,
+ 0x1ee54, 0x1ee54,
+ 0x1ee57, 0x1ee57,
+ 0x1ee59, 0x1ee59,
+ 0x1ee5b, 0x1ee5b,
+ 0x1ee5d, 0x1ee5d,
+ 0x1ee5f, 0x1ee5f,
+ 0x1ee61, 0x1ee62,
+ 0x1ee64, 0x1ee64,
+ 0x1ee67, 0x1ee6a,
+ 0x1ee6c, 0x1ee72,
+ 0x1ee74, 0x1ee77,
+ 0x1ee79, 0x1ee7c,
+ 0x1ee7e, 0x1ee7e,
+ 0x1ee80, 0x1ee89,
+ 0x1ee8b, 0x1ee9b,
+ 0x1eea1, 0x1eea3,
+ 0x1eea5, 0x1eea9,
+ 0x1eeab, 0x1eebb,
+ 0x1eef0, 0x1eef1,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0bf,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0f5,
+ 0x1f100, 0x1f1ad,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d7,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8b1,
+ 0x1f900, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbca,
+ 0x1fbf0, 0x1fbf9,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b739,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x3134a,
+ 0x31350, 0x323af,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_15_0 */
+
#endif /* USE_UNICODE_AGE_PROPERTIES */
/* 'Grapheme_Cluster_Break_Prepend': Grapheme_Cluster_Break=Prepend */
static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = {
- 13,
+ 15,
0x0600, 0x0605,
0x06dd, 0x06dd,
0x070f, 0x070f,
+ 0x0890, 0x0891,
0x08e2, 0x08e2,
0x0d4e, 0x0d4e,
0x110bd, 0x110bd,
@@ -35283,6 +37652,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = {
0x11a3a, 0x11a3a,
0x11a84, 0x11a89,
0x11d46, 0x11d46,
+ 0x11f02, 0x11f02,
}; /* CR_Grapheme_Cluster_Break_Prepend */
/* 'Grapheme_Cluster_Break_CR': Grapheme_Cluster_Break=CR */
@@ -35310,7 +37680,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Control[] = {
0x2060, 0x206f,
0xfeff, 0xfeff,
0xfff0, 0xfffb,
- 0x13430, 0x13438,
+ 0x13430, 0x1343f,
0x1bca0, 0x1bca3,
0x1d173, 0x1d17a,
0xe0000, 0xe001f,
@@ -35320,7 +37690,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Control[] = {
/* 'Grapheme_Cluster_Break_Extend': Grapheme_Cluster_Break=Extend */
static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
- 345,
+ 364,
0x0300, 0x036f,
0x0483, 0x0489,
0x0591, 0x05bd,
@@ -35345,7 +37715,8 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x0825, 0x0827,
0x0829, 0x082d,
0x0859, 0x085b,
- 0x08d3, 0x08e1,
+ 0x0898, 0x089f,
+ 0x08ca, 0x08e1,
0x08e3, 0x0902,
0x093a, 0x093a,
0x093c, 0x093c,
@@ -35390,6 +37761,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x0bd7, 0x0bd7,
0x0c00, 0x0c00,
0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
0x0c3e, 0x0c40,
0x0c46, 0x0c48,
0x0c4a, 0x0c4d,
@@ -35421,7 +37793,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x0e47, 0x0e4e,
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -35445,7 +37817,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x109d, 0x109d,
0x135d, 0x135f,
0x1712, 0x1714,
- 0x1732, 0x1734,
+ 0x1732, 0x1733,
0x1752, 0x1753,
0x1772, 0x1773,
0x17b4, 0x17b5,
@@ -35454,6 +37826,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x17c9, 0x17d3,
0x17dd, 0x17dd,
0x180b, 0x180d,
+ 0x180f, 0x180f,
0x1885, 0x1886,
0x18a9, 0x18a9,
0x1920, 0x1922,
@@ -35469,7 +37842,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x1a65, 0x1a6c,
0x1a73, 0x1a7c,
0x1a7f, 0x1a7f,
- 0x1ab0, 0x1ac0,
+ 0x1ab0, 0x1ace,
0x1b00, 0x1b03,
0x1b34, 0x1b3a,
0x1b3c, 0x1b3c,
@@ -35491,8 +37864,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x1ced, 0x1ced,
0x1cf4, 0x1cf4,
0x1cf8, 0x1cf9,
- 0x1dc0, 0x1df9,
- 0x1dfb, 0x1dff,
+ 0x1dc0, 0x1dff,
0x200c, 0x200c,
0x20d0, 0x20f0,
0x2cef, 0x2cf1,
@@ -35550,12 +37922,17 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
0x11001, 0x11001,
0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
0x1107f, 0x11081,
0x110b3, 0x110b6,
0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
0x11100, 0x11102,
0x11127, 0x1112b,
0x1112d, 0x11134,
@@ -35568,6 +37945,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -35635,12 +38013,20 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x11d95, 0x11d95,
0x11d97, 0x11d97,
0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f40,
+ 0x11f42, 0x11f42,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16f4f, 0x16f4f,
0x16f8f, 0x16f92,
0x16fe4, 0x16fe4,
0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
0x1d165, 0x1d165,
0x1d167, 0x1d169,
0x1d16e, 0x1d172,
@@ -35659,8 +38045,11 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
0x1e8d0, 0x1e8d6,
0x1e944, 0x1e94a,
0x1f3fb, 0x1f3ff,
@@ -35673,7 +38062,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
/* 'Grapheme_Cluster_Break_SpacingMark': Grapheme_Cluster_Break=SpacingMark */
static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
- 159,
+ 165,
0x0903, 0x0903,
0x093b, 0x093b,
0x093e, 0x0940,
@@ -35705,6 +38094,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
0x0cc3, 0x0cc4,
0x0cc7, 0x0cc8,
0x0cca, 0x0ccb,
+ 0x0cf3, 0x0cf3,
0x0d02, 0x0d03,
0x0d3f, 0x0d40,
0x0d46, 0x0d48,
@@ -35721,6 +38111,8 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
0x103b, 0x103c,
0x1056, 0x1057,
0x1084, 0x1084,
+ 0x1715, 0x1715,
+ 0x1734, 0x1734,
0x17b6, 0x17b6,
0x17be, 0x17c5,
0x17c7, 0x17c8,
@@ -35805,7 +38197,6 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
0x116ac, 0x116ac,
0x116ae, 0x116af,
0x116b6, 0x116b6,
- 0x11720, 0x11721,
0x11726, 0x11726,
0x1182c, 0x1182e,
0x11838, 0x11838,
@@ -35829,6 +38220,10 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
0x11d93, 0x11d94,
0x11d96, 0x11d96,
0x11ef5, 0x11ef6,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f35,
+ 0x11f3e, 0x11f3f,
+ 0x11f41, 0x11f41,
0x16f51, 0x16f87,
0x16ff0, 0x16ff1,
0x1d166, 0x1d166,
@@ -36787,6 +39182,12 @@ static const OnigCodePoint CR_In_Syriac_Supplement[] = {
0x0860, 0x086f,
}; /* CR_In_Syriac_Supplement */
+/* 'In_Arabic_Extended_B': Block */
+static const OnigCodePoint CR_In_Arabic_Extended_B[] = {
+ 1,
+ 0x0870, 0x089f,
+}; /* CR_In_Arabic_Extended_B */
+
/* 'In_Arabic_Extended_A': Block */
static const OnigCodePoint CR_In_Arabic_Extended_A[] = {
1,
@@ -37753,12 +40154,24 @@ static const OnigCodePoint CR_In_Caucasian_Albanian[] = {
0x10530, 0x1056f,
}; /* CR_In_Caucasian_Albanian */
+/* 'In_Vithkuqi': Block */
+static const OnigCodePoint CR_In_Vithkuqi[] = {
+ 1,
+ 0x10570, 0x105bf,
+}; /* CR_In_Vithkuqi */
+
/* 'In_Linear_A': Block */
static const OnigCodePoint CR_In_Linear_A[] = {
1,
0x10600, 0x1077f,
}; /* CR_In_Linear_A */
+/* 'In_Latin_Extended_F': Block */
+static const OnigCodePoint CR_In_Latin_Extended_F[] = {
+ 1,
+ 0x10780, 0x107bf,
+}; /* CR_In_Latin_Extended_F */
+
/* 'In_Cypriot_Syllabary': Block */
static const OnigCodePoint CR_In_Cypriot_Syllabary[] = {
1,
@@ -37879,6 +40292,12 @@ static const OnigCodePoint CR_In_Yezidi[] = {
0x10e80, 0x10ebf,
}; /* CR_In_Yezidi */
+/* 'In_Arabic_Extended_C': Block */
+static const OnigCodePoint CR_In_Arabic_Extended_C[] = {
+ 1,
+ 0x10ec0, 0x10eff,
+}; /* CR_In_Arabic_Extended_C */
+
/* 'In_Old_Sogdian': Block */
static const OnigCodePoint CR_In_Old_Sogdian[] = {
1,
@@ -37891,6 +40310,12 @@ static const OnigCodePoint CR_In_Sogdian[] = {
0x10f30, 0x10f6f,
}; /* CR_In_Sogdian */
+/* 'In_Old_Uyghur': Block */
+static const OnigCodePoint CR_In_Old_Uyghur[] = {
+ 1,
+ 0x10f70, 0x10faf,
+}; /* CR_In_Old_Uyghur */
+
/* 'In_Chorasmian': Block */
static const OnigCodePoint CR_In_Chorasmian[] = {
1,
@@ -38005,7 +40430,7 @@ static const OnigCodePoint CR_In_Takri[] = {
/* 'In_Ahom': Block */
static const OnigCodePoint CR_In_Ahom[] = {
1,
- 0x11700, 0x1173f,
+ 0x11700, 0x1174f,
}; /* CR_In_Ahom */
/* 'In_Dogra': Block */
@@ -38044,12 +40469,24 @@ static const OnigCodePoint CR_In_Soyombo[] = {
0x11a50, 0x11aaf,
}; /* CR_In_Soyombo */
+/* 'In_Unified_Canadian_Aboriginal_Syllabics_Extended_A': Block */
+static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A[] = {
+ 1,
+ 0x11ab0, 0x11abf,
+}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A */
+
/* 'In_Pau_Cin_Hau': Block */
static const OnigCodePoint CR_In_Pau_Cin_Hau[] = {
1,
0x11ac0, 0x11aff,
}; /* CR_In_Pau_Cin_Hau */
+/* 'In_Devanagari_Extended_A': Block */
+static const OnigCodePoint CR_In_Devanagari_Extended_A[] = {
+ 1,
+ 0x11b00, 0x11b5f,
+}; /* CR_In_Devanagari_Extended_A */
+
/* 'In_Bhaiksuki': Block */
static const OnigCodePoint CR_In_Bhaiksuki[] = {
1,
@@ -38080,6 +40517,12 @@ static const OnigCodePoint CR_In_Makasar[] = {
0x11ee0, 0x11eff,
}; /* CR_In_Makasar */
+/* 'In_Kawi': Block */
+static const OnigCodePoint CR_In_Kawi[] = {
+ 1,
+ 0x11f00, 0x11f5f,
+}; /* CR_In_Kawi */
+
/* 'In_Lisu_Supplement': Block */
static const OnigCodePoint CR_In_Lisu_Supplement[] = {
1,
@@ -38110,6 +40553,12 @@ static const OnigCodePoint CR_In_Early_Dynastic_Cuneiform[] = {
0x12480, 0x1254f,
}; /* CR_In_Early_Dynastic_Cuneiform */
+/* 'In_Cypro_Minoan': Block */
+static const OnigCodePoint CR_In_Cypro_Minoan[] = {
+ 1,
+ 0x12f90, 0x12fff,
+}; /* CR_In_Cypro_Minoan */
+
/* 'In_Egyptian_Hieroglyphs': Block */
static const OnigCodePoint CR_In_Egyptian_Hieroglyphs[] = {
1,
@@ -38119,7 +40568,7 @@ static const OnigCodePoint CR_In_Egyptian_Hieroglyphs[] = {
/* 'In_Egyptian_Hieroglyph_Format_Controls': Block */
static const OnigCodePoint CR_In_Egyptian_Hieroglyph_Format_Controls[] = {
1,
- 0x13430, 0x1343f,
+ 0x13430, 0x1345f,
}; /* CR_In_Egyptian_Hieroglyph_Format_Controls */
/* 'In_Anatolian_Hieroglyphs': Block */
@@ -38140,6 +40589,12 @@ static const OnigCodePoint CR_In_Mro[] = {
0x16a40, 0x16a6f,
}; /* CR_In_Mro */
+/* 'In_Tangsa': Block */
+static const OnigCodePoint CR_In_Tangsa[] = {
+ 1,
+ 0x16a70, 0x16acf,
+}; /* CR_In_Tangsa */
+
/* 'In_Bassa_Vah': Block */
static const OnigCodePoint CR_In_Bassa_Vah[] = {
1,
@@ -38191,9 +40646,15 @@ static const OnigCodePoint CR_In_Khitan_Small_Script[] = {
/* 'In_Tangut_Supplement': Block */
static const OnigCodePoint CR_In_Tangut_Supplement[] = {
1,
- 0x18d00, 0x18d8f,
+ 0x18d00, 0x18d7f,
}; /* CR_In_Tangut_Supplement */
+/* 'In_Kana_Extended_B': Block */
+static const OnigCodePoint CR_In_Kana_Extended_B[] = {
+ 1,
+ 0x1aff0, 0x1afff,
+}; /* CR_In_Kana_Extended_B */
+
/* 'In_Kana_Supplement': Block */
static const OnigCodePoint CR_In_Kana_Supplement[] = {
1,
@@ -38230,6 +40691,12 @@ static const OnigCodePoint CR_In_Shorthand_Format_Controls[] = {
0x1bca0, 0x1bcaf,
}; /* CR_In_Shorthand_Format_Controls */
+/* 'In_Znamenny_Musical_Notation': Block */
+static const OnigCodePoint CR_In_Znamenny_Musical_Notation[] = {
+ 1,
+ 0x1cf00, 0x1cfcf,
+}; /* CR_In_Znamenny_Musical_Notation */
+
/* 'In_Byzantine_Musical_Symbols': Block */
static const OnigCodePoint CR_In_Byzantine_Musical_Symbols[] = {
1,
@@ -38248,6 +40715,12 @@ static const OnigCodePoint CR_In_Ancient_Greek_Musical_Notation[] = {
0x1d200, 0x1d24f,
}; /* CR_In_Ancient_Greek_Musical_Notation */
+/* 'In_Kaktovik_Numerals': Block */
+static const OnigCodePoint CR_In_Kaktovik_Numerals[] = {
+ 1,
+ 0x1d2c0, 0x1d2df,
+}; /* CR_In_Kaktovik_Numerals */
+
/* 'In_Mayan_Numerals': Block */
static const OnigCodePoint CR_In_Mayan_Numerals[] = {
1,
@@ -38278,24 +40751,54 @@ static const OnigCodePoint CR_In_Sutton_SignWriting[] = {
0x1d800, 0x1daaf,
}; /* CR_In_Sutton_SignWriting */
+/* 'In_Latin_Extended_G': Block */
+static const OnigCodePoint CR_In_Latin_Extended_G[] = {
+ 1,
+ 0x1df00, 0x1dfff,
+}; /* CR_In_Latin_Extended_G */
+
/* 'In_Glagolitic_Supplement': Block */
static const OnigCodePoint CR_In_Glagolitic_Supplement[] = {
1,
0x1e000, 0x1e02f,
}; /* CR_In_Glagolitic_Supplement */
+/* 'In_Cyrillic_Extended_D': Block */
+static const OnigCodePoint CR_In_Cyrillic_Extended_D[] = {
+ 1,
+ 0x1e030, 0x1e08f,
+}; /* CR_In_Cyrillic_Extended_D */
+
/* 'In_Nyiakeng_Puachue_Hmong': Block */
static const OnigCodePoint CR_In_Nyiakeng_Puachue_Hmong[] = {
1,
0x1e100, 0x1e14f,
}; /* CR_In_Nyiakeng_Puachue_Hmong */
+/* 'In_Toto': Block */
+static const OnigCodePoint CR_In_Toto[] = {
+ 1,
+ 0x1e290, 0x1e2bf,
+}; /* CR_In_Toto */
+
/* 'In_Wancho': Block */
static const OnigCodePoint CR_In_Wancho[] = {
1,
0x1e2c0, 0x1e2ff,
}; /* CR_In_Wancho */
+/* 'In_Nag_Mundari': Block */
+static const OnigCodePoint CR_In_Nag_Mundari[] = {
+ 1,
+ 0x1e4d0, 0x1e4ff,
+}; /* CR_In_Nag_Mundari */
+
+/* 'In_Ethiopic_Extended_B': Block */
+static const OnigCodePoint CR_In_Ethiopic_Extended_B[] = {
+ 1,
+ 0x1e7e0, 0x1e7ff,
+}; /* CR_In_Ethiopic_Extended_B */
+
/* 'In_Mende_Kikakui': Block */
static const OnigCodePoint CR_In_Mende_Kikakui[] = {
1,
@@ -38464,6 +40967,12 @@ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_G[] = {
0x30000, 0x3134f,
}; /* CR_In_CJK_Unified_Ideographs_Extension_G */
+/* 'In_CJK_Unified_Ideographs_Extension_H': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_H[] = {
+ 1,
+ 0x31350, 0x323af,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_H */
+
/* 'In_Tags': Block */
static const OnigCodePoint CR_In_Tags[] = {
1,
@@ -38490,49 +40999,46 @@ static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_B[] = {
/* 'In_No_Block': Block */
static const OnigCodePoint CR_In_No_Block[] = {
- 54,
- 0x0870, 0x089f,
+ 51,
0x2fe0, 0x2fef,
0x10200, 0x1027f,
0x103e0, 0x103ff,
- 0x10570, 0x105ff,
- 0x10780, 0x107ff,
+ 0x105c0, 0x105ff,
+ 0x107c0, 0x107ff,
0x108b0, 0x108df,
0x10940, 0x1097f,
0x10aa0, 0x10abf,
0x10bb0, 0x10bff,
0x10c50, 0x10c7f,
0x10d40, 0x10e5f,
- 0x10ec0, 0x10eff,
- 0x10f70, 0x10faf,
0x11250, 0x1127f,
0x11380, 0x113ff,
0x114e0, 0x1157f,
0x116d0, 0x116ff,
- 0x11740, 0x117ff,
+ 0x11750, 0x117ff,
0x11850, 0x1189f,
0x11960, 0x1199f,
- 0x11ab0, 0x11abf,
- 0x11b00, 0x11bff,
+ 0x11b60, 0x11bff,
0x11cc0, 0x11cff,
0x11db0, 0x11edf,
- 0x11f00, 0x11faf,
- 0x12550, 0x12fff,
- 0x13440, 0x143ff,
+ 0x11f60, 0x11faf,
+ 0x12550, 0x12f8f,
+ 0x13460, 0x143ff,
0x14680, 0x167ff,
- 0x16a70, 0x16acf,
0x16b90, 0x16e3f,
0x16ea0, 0x16eff,
0x16fa0, 0x16fdf,
- 0x18d90, 0x1afff,
+ 0x18d80, 0x1afef,
0x1b300, 0x1bbff,
- 0x1bcb0, 0x1cfff,
- 0x1d250, 0x1d2df,
+ 0x1bcb0, 0x1ceff,
+ 0x1cfd0, 0x1cfff,
+ 0x1d250, 0x1d2bf,
0x1d380, 0x1d3ff,
- 0x1dab0, 0x1dfff,
- 0x1e030, 0x1e0ff,
- 0x1e150, 0x1e2bf,
- 0x1e300, 0x1e7ff,
+ 0x1dab0, 0x1deff,
+ 0x1e090, 0x1e0ff,
+ 0x1e150, 0x1e28f,
+ 0x1e300, 0x1e4cf,
+ 0x1e500, 0x1e7df,
0x1e8e0, 0x1e8ff,
0x1e960, 0x1ec6f,
0x1ecc0, 0x1ecff,
@@ -38542,7 +41048,7 @@ static const OnigCodePoint CR_In_No_Block[] = {
0x2a6e0, 0x2a6ff,
0x2ebf0, 0x2f7ff,
0x2fa20, 0x2ffff,
- 0x31350, 0xdffff,
+ 0x323b0, 0xdffff,
0xe0080, 0xe00ff,
0xe01f0, 0xeffff,
}; /* CR_In_No_Block */
@@ -38781,6 +41287,13 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_Dives_Akuru,
CR_Khitan_Small_Script,
CR_Yezidi,
+ CR_Cypro_Minoan,
+ CR_Old_Uyghur,
+ CR_Tangsa,
+ CR_Toto,
+ CR_Vithkuqi,
+ CR_Kawi,
+ CR_Nag_Mundari,
CR_White_Space,
CR_Bidi_Control,
CR_Join_Control,
@@ -38846,6 +41359,8 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_Age_12_0,
CR_Age_12_1,
CR_Age_13_0,
+ CR_Age_14_0,
+ CR_Age_15_0,
#endif /* USE_UNICODE_AGE_PROPERTIES */
CR_Grapheme_Cluster_Break_Prepend,
CR_Grapheme_Cluster_Break_CR,
@@ -38880,6 +41395,7 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_In_Samaritan,
CR_In_Mandaic,
CR_In_Syriac_Supplement,
+ CR_In_Arabic_Extended_B,
CR_In_Arabic_Extended_A,
CR_In_Devanagari,
CR_In_Bengali,
@@ -39043,7 +41559,9 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_In_Osage,
CR_In_Elbasan,
CR_In_Caucasian_Albanian,
+ CR_In_Vithkuqi,
CR_In_Linear_A,
+ CR_In_Latin_Extended_F,
CR_In_Cypriot_Syllabary,
CR_In_Imperial_Aramaic,
CR_In_Palmyrene,
@@ -39066,8 +41584,10 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_In_Hanifi_Rohingya,
CR_In_Rumi_Numeral_Symbols,
CR_In_Yezidi,
+ CR_In_Arabic_Extended_C,
CR_In_Old_Sogdian,
CR_In_Sogdian,
+ CR_In_Old_Uyghur,
CR_In_Chorasmian,
CR_In_Elymaic,
CR_In_Brahmi,
@@ -39094,22 +41614,27 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_In_Nandinagari,
CR_In_Zanabazar_Square,
CR_In_Soyombo,
+ CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A,
CR_In_Pau_Cin_Hau,
+ CR_In_Devanagari_Extended_A,
CR_In_Bhaiksuki,
CR_In_Marchen,
CR_In_Masaram_Gondi,
CR_In_Gunjala_Gondi,
CR_In_Makasar,
+ CR_In_Kawi,
CR_In_Lisu_Supplement,
CR_In_Tamil_Supplement,
CR_In_Cuneiform,
CR_In_Cuneiform_Numbers_and_Punctuation,
CR_In_Early_Dynastic_Cuneiform,
+ CR_In_Cypro_Minoan,
CR_In_Egyptian_Hieroglyphs,
CR_In_Egyptian_Hieroglyph_Format_Controls,
CR_In_Anatolian_Hieroglyphs,
CR_In_Bamum_Supplement,
CR_In_Mro,
+ CR_In_Tangsa,
CR_In_Bassa_Vah,
CR_In_Pahawh_Hmong,
CR_In_Medefaidrin,
@@ -39119,23 +41644,31 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_In_Tangut_Components,
CR_In_Khitan_Small_Script,
CR_In_Tangut_Supplement,
+ CR_In_Kana_Extended_B,
CR_In_Kana_Supplement,
CR_In_Kana_Extended_A,
CR_In_Small_Kana_Extension,
CR_In_Nushu,
CR_In_Duployan,
CR_In_Shorthand_Format_Controls,
+ CR_In_Znamenny_Musical_Notation,
CR_In_Byzantine_Musical_Symbols,
CR_In_Musical_Symbols,
CR_In_Ancient_Greek_Musical_Notation,
+ CR_In_Kaktovik_Numerals,
CR_In_Mayan_Numerals,
CR_In_Tai_Xuan_Jing_Symbols,
CR_In_Counting_Rod_Numerals,
CR_In_Mathematical_Alphanumeric_Symbols,
CR_In_Sutton_SignWriting,
+ CR_In_Latin_Extended_G,
CR_In_Glagolitic_Supplement,
+ CR_In_Cyrillic_Extended_D,
CR_In_Nyiakeng_Puachue_Hmong,
+ CR_In_Toto,
CR_In_Wancho,
+ CR_In_Nag_Mundari,
+ CR_In_Ethiopic_Extended_B,
CR_In_Mende_Kikakui,
CR_In_Adlam,
CR_In_Indic_Siyaq_Numbers,
@@ -39164,6 +41697,7 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_In_CJK_Unified_Ideographs_Extension_F,
CR_In_CJK_Compatibility_Ideographs_Supplement,
CR_In_CJK_Unified_Ideographs_Extension_G,
+ CR_In_CJK_Unified_Ideographs_Extension_H,
CR_In_Tags,
CR_In_Variation_Selectors_Supplement,
CR_In_Supplementary_Private_Use_Area_A,
@@ -39177,32 +41711,26 @@ struct uniname2ctype_struct {
};
#define uniname2ctype_offset(str) offsetof(struct uniname2ctype_pool_t, uniname2ctype_pool_##str)
-static const struct uniname2ctype_struct *uniname2ctype_p(
-#if !(1+0) /* if ANSI, old style not to conflict with generated prototype */
- const char *, unsigned int
-#endif
-);
+static const struct uniname2ctype_struct *uniname2ctype_p(register const char *str, register size_t len);
#ifndef USE_UNICODE_PROPERTIES
#define TOTAL_KEYWORDS 15
#define MIN_WORD_LENGTH 4
#define MAX_WORD_LENGTH 11
+#define MIN_HASH_VALUE 6
+#define MAX_HASH_VALUE 20
+/* maximum key range = 15, duplicates = 0 */
#else /* USE_UNICODE_PROPERTIES */
#ifndef USE_UNICODE_AGE_PROPERTIES
-#define TOTAL_KEYWORDS 835
+#define TOTAL_KEYWORDS 866
#else /* USE_UNICODE_AGE_PROPERTIES */
-#define TOTAL_KEYWORDS 858
+#define TOTAL_KEYWORDS 891
#endif /* USE_UNICODE_AGE_PROPERTIES */
#define MIN_WORD_LENGTH 1
-#define MAX_WORD_LENGTH 44
-#endif /* USE_UNICODE_PROPERTIES */
-#define MIN_HASH_VALUE 6
-#ifndef USE_UNICODE_PROPERTIES
-#define MAX_HASH_VALUE 20
-/* maximum key range = 15, duplicates = 0 */
-#else /* USE_UNICODE_PROPERTIES */
+#define MAX_WORD_LENGTH 45
+#define MIN_HASH_VALUE 11
#define MAX_HASH_VALUE 6098
-/* maximum key range = 6093, duplicates = 0 */
+/* maximum key range = 6088, duplicates = 0 */
#endif /* USE_UNICODE_PROPERTIES */
#ifdef __GNUC__
@@ -39244,16 +41772,16 @@ uniname2ctype_hash (register const char *str, register size_t len)
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
#else /* USE_UNICODE_AGE_PROPERTIES */
- 6099, 6099, 6099, 6099, 6099, 6099, 20, 6099, 3, 1,
- 4, 7, 20, 16, 11, 10, 6, 1, 6099, 6099,
+ 6099, 6099, 6099, 6099, 6099, 6099, 12, 6099, 3, 1,
+ 4, 8, 32, 26, 14, 17, 10, 7, 6099, 6099,
#endif /* USE_UNICODE_AGE_PROPERTIES */
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 1, 1425, 113,
- 437, 37, 117, 1071, 1051, 4, 1488, 9, 500, 88,
- 8, 18, 1371, 1287, 54, 203, 310, 619, 1635, 649,
- 161, 1624, 4, 2, 1, 6099, 6099, 6099, 6099, 6099
+ 437, 37, 1086, 1071, 1051, 4, 1984, 9, 500, 88,
+ 8, 18, 1371, 1287, 54, 203, 310, 619, 1958, 603,
+ 275, 1624, 44, 1, 22, 6099, 6099, 6099, 6099, 6099
#endif /* USE_UNICODE_PROPERTIES */
};
#ifndef USE_UNICODE_PROPERTIES
@@ -39317,10 +41845,8 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str19[sizeof("digit")];
char uniname2ctype_pool_str20[sizeof("blank")];
#else /* USE_UNICODE_PROPERTIES */
- char uniname2ctype_pool_str6[sizeof("z")];
- char uniname2ctype_pool_str12[sizeof("yi")];
- char uniname2ctype_pool_str17[sizeof("zzzz")];
- char uniname2ctype_pool_str18[sizeof("yiii")];
+ char uniname2ctype_pool_str11[sizeof("yi")];
+ char uniname2ctype_pool_str17[sizeof("yiii")];
char uniname2ctype_pool_str22[sizeof("lana")];
char uniname2ctype_pool_str25[sizeof("lina")];
char uniname2ctype_pool_str33[sizeof("maka")];
@@ -39331,15 +41857,16 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str47[sizeof("ci")];
char uniname2ctype_pool_str48[sizeof("lao")];
char uniname2ctype_pool_str49[sizeof("laoo")];
- char uniname2ctype_pool_str51[sizeof("yezi")];
char uniname2ctype_pool_str52[sizeof("inkannada")];
char uniname2ctype_pool_str55[sizeof("cn")];
char uniname2ctype_pool_str64[sizeof("pi")];
char uniname2ctype_pool_str66[sizeof("innko")];
+ char uniname2ctype_pool_str67[sizeof("z")];
char uniname2ctype_pool_str71[sizeof("gran")];
char uniname2ctype_pool_str75[sizeof("co")];
char uniname2ctype_pool_str83[sizeof("lineara")];
char uniname2ctype_pool_str86[sizeof("mark")];
+ char uniname2ctype_pool_str90[sizeof("yezi")];
char uniname2ctype_pool_str92[sizeof("po")];
char uniname2ctype_pool_str94[sizeof("me")];
char uniname2ctype_pool_str100[sizeof("cari")];
@@ -39354,13 +41881,10 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str117[sizeof("geor")];
char uniname2ctype_pool_str118[sizeof("greek")];
char uniname2ctype_pool_str122[sizeof("gonm")];
- char uniname2ctype_pool_str126[sizeof("dia")];
- char uniname2ctype_pool_str127[sizeof("di")];
char uniname2ctype_pool_str129[sizeof("mendekikakui")];
char uniname2ctype_pool_str130[sizeof("pe")];
char uniname2ctype_pool_str131[sizeof("mero")];
char uniname2ctype_pool_str134[sizeof("inosmanya")];
- char uniname2ctype_pool_str135[sizeof("diak")];
char uniname2ctype_pool_str139[sizeof("cakm")];
char uniname2ctype_pool_str145[sizeof("inmanichaean")];
char uniname2ctype_pool_str146[sizeof("inmro")];
@@ -39369,9 +41893,8 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str151[sizeof("c")];
char uniname2ctype_pool_str152[sizeof("mandaic")];
char uniname2ctype_pool_str153[sizeof("meeteimayek")];
+ char uniname2ctype_pool_str158[sizeof("zzzz")];
char uniname2ctype_pool_str161[sizeof("inarmenian")];
- char uniname2ctype_pool_str173[sizeof("vai")];
- char uniname2ctype_pool_str174[sizeof("vaii")];
char uniname2ctype_pool_str177[sizeof("inmyanmar")];
char uniname2ctype_pool_str178[sizeof("inmakasar")];
char uniname2ctype_pool_str183[sizeof("common")];
@@ -39397,19 +41920,18 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str267[sizeof("armn")];
char uniname2ctype_pool_str268[sizeof("incherokee")];
char uniname2ctype_pool_str270[sizeof("prependedconcatenationmark")];
- char uniname2ctype_pool_str273[sizeof("cf")];
char uniname2ctype_pool_str274[sizeof("incuneiform")];
char uniname2ctype_pool_str275[sizeof("inavestan")];
char uniname2ctype_pool_str281[sizeof("inipaextensions")];
char uniname2ctype_pool_str282[sizeof("pc")];
char uniname2ctype_pool_str283[sizeof("armenian")];
char uniname2ctype_pool_str285[sizeof("insharada")];
+ char uniname2ctype_pool_str287[sizeof("vai")];
+ char uniname2ctype_pool_str288[sizeof("vaii")];
char uniname2ctype_pool_str289[sizeof("inmarchen")];
- char uniname2ctype_pool_str290[sizeof("pf")];
char uniname2ctype_pool_str293[sizeof("makasar")];
char uniname2ctype_pool_str297[sizeof("masaramgondi")];
char uniname2ctype_pool_str301[sizeof("inarrows")];
- char uniname2ctype_pool_str302[sizeof("diacritic")];
char uniname2ctype_pool_str311[sizeof("incyrillic")];
char uniname2ctype_pool_str313[sizeof("incham")];
char uniname2ctype_pool_str315[sizeof("qmark")];
@@ -39420,7 +41942,6 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str335[sizeof("inmasaramgondi")];
char uniname2ctype_pool_str338[sizeof("inthaana")];
char uniname2ctype_pool_str340[sizeof("latin")];
- char uniname2ctype_pool_str341[sizeof("inzanabazarsquare")];
char uniname2ctype_pool_str342[sizeof("inthai")];
char uniname2ctype_pool_str345[sizeof("lineseparator")];
char uniname2ctype_pool_str346[sizeof("pcm")];
@@ -39429,16 +41950,16 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str362[sizeof("inscriptionalparthian")];
char uniname2ctype_pool_str366[sizeof("initialpunctuation")];
char uniname2ctype_pool_str373[sizeof("mtei")];
+ char uniname2ctype_pool_str381[sizeof("inzanabazarsquare")];
char uniname2ctype_pool_str386[sizeof("inkhmersymbols")];
char uniname2ctype_pool_str399[sizeof("insyriac")];
char uniname2ctype_pool_str401[sizeof("intakri")];
char uniname2ctype_pool_str404[sizeof("arabic")];
- char uniname2ctype_pool_str409[sizeof("zs")];
char uniname2ctype_pool_str418[sizeof("katakana")];
char uniname2ctype_pool_str426[sizeof("prti")];
+ char uniname2ctype_pool_str430[sizeof("zs")];
char uniname2ctype_pool_str442[sizeof("ascii")];
char uniname2ctype_pool_str445[sizeof("cs")];
- char uniname2ctype_pool_str460[sizeof("decimalnumber")];
char uniname2ctype_pool_str462[sizeof("ps")];
char uniname2ctype_pool_str468[sizeof("mand")];
char uniname2ctype_pool_str470[sizeof("privateuse")];
@@ -39448,26 +41969,24 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str486[sizeof("incjkcompatibilityforms")];
char uniname2ctype_pool_str488[sizeof("inkanaextendeda")];
char uniname2ctype_pool_str491[sizeof("incjkcompatibilityideographs")];
- char uniname2ctype_pool_str494[sizeof("yezidi")];
char uniname2ctype_pool_str500[sizeof("brai")];
char uniname2ctype_pool_str504[sizeof("mend")];
char uniname2ctype_pool_str505[sizeof("ideo")];
char uniname2ctype_pool_str506[sizeof("letter")];
char uniname2ctype_pool_str509[sizeof("l")];
char uniname2ctype_pool_str511[sizeof("inmeeteimayek")];
- char uniname2ctype_pool_str519[sizeof("xidcontinue")];
char uniname2ctype_pool_str520[sizeof("inideographicdescriptioncharacters")];
+ char uniname2ctype_pool_str533[sizeof("yezidi")];
char uniname2ctype_pool_str538[sizeof("knda")];
char uniname2ctype_pool_str541[sizeof("innandinagari")];
char uniname2ctype_pool_str543[sizeof("kannada")];
char uniname2ctype_pool_str556[sizeof("inmodi")];
char uniname2ctype_pool_str558[sizeof("inlao")];
+ char uniname2ctype_pool_str559[sizeof("xidcontinue")];
char uniname2ctype_pool_str560[sizeof("inoldnortharabian")];
- char uniname2ctype_pool_str562[sizeof("xidc")];
char uniname2ctype_pool_str565[sizeof("intransportandmapsymbols")];
char uniname2ctype_pool_str566[sizeof("letternumber")];
char uniname2ctype_pool_str568[sizeof("gothic")];
- char uniname2ctype_pool_str569[sizeof("vs")];
char uniname2ctype_pool_str572[sizeof("inlineara")];
char uniname2ctype_pool_str577[sizeof("inmendekikakui")];
char uniname2ctype_pool_str579[sizeof("mongolian")];
@@ -39478,33 +41997,34 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str596[sizeof("inemoticons")];
char uniname2ctype_pool_str597[sizeof("kali")];
char uniname2ctype_pool_str600[sizeof("inolditalic")];
+ char uniname2ctype_pool_str602[sizeof("xidc")];
char uniname2ctype_pool_str604[sizeof("inmedefaidrin")];
char uniname2ctype_pool_str605[sizeof("inchesssymbols")];
char uniname2ctype_pool_str608[sizeof("incjkcompatibilityideographssupplement")];
char uniname2ctype_pool_str609[sizeof("kits")];
- char uniname2ctype_pool_str613[sizeof("medf")];
char uniname2ctype_pool_str614[sizeof("inadlam")];
char uniname2ctype_pool_str624[sizeof("psalterpahlavi")];
char uniname2ctype_pool_str625[sizeof("incommonindicnumberforms")];
- char uniname2ctype_pool_str629[sizeof("medefaidrin")];
char uniname2ctype_pool_str630[sizeof("lt")];
- char uniname2ctype_pool_str631[sizeof("patternsyntax")];
- char uniname2ctype_pool_str638[sizeof("inshorthandformatcontrols")];
+ char uniname2ctype_pool_str636[sizeof("innewa")];
char uniname2ctype_pool_str639[sizeof("sk")];
char uniname2ctype_pool_str642[sizeof("control")];
+ char uniname2ctype_pool_str643[sizeof("inkawi")];
char uniname2ctype_pool_str645[sizeof("inancientsymbols")];
char uniname2ctype_pool_str647[sizeof("palm")];
char uniname2ctype_pool_str650[sizeof("inlycian")];
- char uniname2ctype_pool_str652[sizeof("xids")];
char uniname2ctype_pool_str657[sizeof("so")];
char uniname2ctype_pool_str660[sizeof("patternwhitespace")];
char uniname2ctype_pool_str672[sizeof("inmandaic")];
char uniname2ctype_pool_str675[sizeof("idc")];
char uniname2ctype_pool_str678[sizeof("meroiticcursive")];
- char uniname2ctype_pool_str682[sizeof("innewa")];
- char uniname2ctype_pool_str688[sizeof("dsrt")];
+ char uniname2ctype_pool_str679[sizeof("intoto")];
+ char uniname2ctype_pool_str683[sizeof("vs")];
+ char uniname2ctype_pool_str692[sizeof("xids")];
+ char uniname2ctype_pool_str695[sizeof("inwarangciti")];
char uniname2ctype_pool_str696[sizeof("sora")];
char uniname2ctype_pool_str697[sizeof("inopticalcharacterrecognition")];
+ char uniname2ctype_pool_str700[sizeof("kawi")];
char uniname2ctype_pool_str703[sizeof("inoldsogdian")];
char uniname2ctype_pool_str705[sizeof("inmalayalam")];
char uniname2ctype_pool_str707[sizeof("bamum")];
@@ -39513,27 +42033,25 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str720[sizeof("grext")];
char uniname2ctype_pool_str737[sizeof("print")];
char uniname2ctype_pool_str738[sizeof("intaitham")];
- char uniname2ctype_pool_str741[sizeof("inwarangciti")];
+ char uniname2ctype_pool_str742[sizeof("lower")];
+ char uniname2ctype_pool_str745[sizeof("patternsyntax")];
char uniname2ctype_pool_str753[sizeof("joinc")];
char uniname2ctype_pool_str755[sizeof("inoldsoutharabian")];
char uniname2ctype_pool_str760[sizeof("incjkstrokes")];
char uniname2ctype_pool_str761[sizeof("batk")];
- char uniname2ctype_pool_str765[sizeof("deseret")];
char uniname2ctype_pool_str766[sizeof("samr")];
+ char uniname2ctype_pool_str767[sizeof("inwancho")];
char uniname2ctype_pool_str771[sizeof("batak")];
char uniname2ctype_pool_str776[sizeof("patws")];
char uniname2ctype_pool_str783[sizeof("samaritan")];
char uniname2ctype_pool_str787[sizeof("idsbinaryoperator")];
- char uniname2ctype_pool_str788[sizeof("lower")];
char uniname2ctype_pool_str791[sizeof("pauc")];
char uniname2ctype_pool_str794[sizeof("insmallkanaextension")];
char uniname2ctype_pool_str797[sizeof("sm")];
char uniname2ctype_pool_str799[sizeof("indominotiles")];
char uniname2ctype_pool_str802[sizeof("alnum")];
- char uniname2ctype_pool_str806[sizeof("incyrillicextendeda")];
+ char uniname2ctype_pool_str803[sizeof("inznamennymusicalnotation")];
char uniname2ctype_pool_str809[sizeof("insylotinagri")];
- char uniname2ctype_pool_str811[sizeof("intaixuanjingsymbols")];
- char uniname2ctype_pool_str813[sizeof("inwancho")];
char uniname2ctype_pool_str814[sizeof("inugaritic")];
char uniname2ctype_pool_str818[sizeof("incontrolpictures")];
char uniname2ctype_pool_str821[sizeof("inlinearbideograms")];
@@ -39543,23 +42061,22 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str825[sizeof("inmodifiertoneletters")];
char uniname2ctype_pool_str828[sizeof("inancientgreekmusicalnotation")];
char uniname2ctype_pool_str838[sizeof("lisu")];
+ char uniname2ctype_pool_str842[sizeof("lowercase")];
+ char uniname2ctype_pool_str845[sizeof("cwcm")];
char uniname2ctype_pool_str847[sizeof("sc")];
char uniname2ctype_pool_str848[sizeof("bass")];
char uniname2ctype_pool_str855[sizeof("ids")];
char uniname2ctype_pool_str857[sizeof("inlatinextendeda")];
char uniname2ctype_pool_str875[sizeof("intaile")];
- char uniname2ctype_pool_str882[sizeof("cuneiform")];
char uniname2ctype_pool_str886[sizeof("inmiscellaneoussymbols")];
- char uniname2ctype_pool_str888[sizeof("lowercase")];
- char uniname2ctype_pool_str891[sizeof("cwcm")];
char uniname2ctype_pool_str895[sizeof("inmiscellaneoussymbolsandarrows")];
char uniname2ctype_pool_str898[sizeof("incaucasianalbanian")];
char uniname2ctype_pool_str900[sizeof("inmiscellaneoussymbolsandpictographs")];
char uniname2ctype_pool_str906[sizeof("inoldturkic")];
char uniname2ctype_pool_str907[sizeof("insaurashtra")];
- char uniname2ctype_pool_str918[sizeof("incyrillicextendedc")];
- char uniname2ctype_pool_str920[sizeof("cwcf")];
+ char uniname2ctype_pool_str920[sizeof("incyrillicextendeda")];
char uniname2ctype_pool_str924[sizeof("idcontinue")];
+ char uniname2ctype_pool_str925[sizeof("intaixuanjingsymbols")];
char uniname2ctype_pool_str926[sizeof("intamil")];
char uniname2ctype_pool_str928[sizeof("inmultani")];
char uniname2ctype_pool_str929[sizeof("inlatinextendede")];
@@ -39567,42 +42084,43 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str946[sizeof("bali")];
char uniname2ctype_pool_str961[sizeof("blank")];
char uniname2ctype_pool_str963[sizeof("idst")];
- char uniname2ctype_pool_str972[sizeof("modifierletter")];
char uniname2ctype_pool_str974[sizeof("inlydian")];
- char uniname2ctype_pool_str991[sizeof("xsux")];
+ char uniname2ctype_pool_str986[sizeof("innewtailue")];
char uniname2ctype_pool_str994[sizeof("bengali")];
char uniname2ctype_pool_str995[sizeof("runr")];
- char uniname2ctype_pool_str1003[sizeof("zl")];
- char uniname2ctype_pool_str1005[sizeof("inunifiedcanadianaboriginalsyllabics")];
char uniname2ctype_pool_str1010[sizeof("ll")];
char uniname2ctype_pool_str1013[sizeof("indeseret")];
char uniname2ctype_pool_str1015[sizeof("inancientgreeknumbers")];
char uniname2ctype_pool_str1021[sizeof("idstart")];
+ char uniname2ctype_pool_str1024[sizeof("zl")];
char uniname2ctype_pool_str1025[sizeof("inmeeteimayekextensions")];
char uniname2ctype_pool_str1028[sizeof("balinese")];
- char uniname2ctype_pool_str1032[sizeof("innewtailue")];
+ char uniname2ctype_pool_str1032[sizeof("incyrillicextendedc")];
char uniname2ctype_pool_str1035[sizeof("inspacingmodifierletters")];
char uniname2ctype_pool_str1036[sizeof("inearlydynasticcuneiform")];
char uniname2ctype_pool_str1049[sizeof("plrd")];
char uniname2ctype_pool_str1067[sizeof("canadianaboriginal")];
- char uniname2ctype_pool_str1068[sizeof("zinh")];
char uniname2ctype_pool_str1072[sizeof("sind")];
- char uniname2ctype_pool_str1074[sizeof("xidstart")];
- char uniname2ctype_pool_str1075[sizeof("xdigit")];
char uniname2ctype_pool_str1081[sizeof("inlatinextendedc")];
+ char uniname2ctype_pool_str1085[sizeof("uideo")];
char uniname2ctype_pool_str1087[sizeof("incountingrodnumerals")];
+ char uniname2ctype_pool_str1089[sizeof("zinh")];
+ char uniname2ctype_pool_str1095[sizeof("dia")];
+ char uniname2ctype_pool_str1096[sizeof("di")];
char uniname2ctype_pool_str1097[sizeof("inkhudawadi")];
char uniname2ctype_pool_str1102[sizeof("inhanifirohingya")];
+ char uniname2ctype_pool_str1104[sizeof("diak")];
char uniname2ctype_pool_str1105[sizeof("gong")];
char uniname2ctype_pool_str1107[sizeof("ingrantha")];
char uniname2ctype_pool_str1109[sizeof("bidic")];
- char uniname2ctype_pool_str1116[sizeof("variationselector")];
+ char uniname2ctype_pool_str1114[sizeof("xidstart")];
+ char uniname2ctype_pool_str1115[sizeof("xdigit")];
char uniname2ctype_pool_str1119[sizeof("mong")];
char uniname2ctype_pool_str1120[sizeof("cased")];
- char uniname2ctype_pool_str1131[sizeof("uideo")];
char uniname2ctype_pool_str1134[sizeof("inhiragana")];
char uniname2ctype_pool_str1140[sizeof("sinhala")];
char uniname2ctype_pool_str1142[sizeof("adlm")];
+ char uniname2ctype_pool_str1145[sizeof("xsux")];
char uniname2ctype_pool_str1146[sizeof("glagolitic")];
char uniname2ctype_pool_str1147[sizeof("sterm")];
char uniname2ctype_pool_str1149[sizeof("bamu")];
@@ -39610,6 +42128,7 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1151[sizeof("inosage")];
char uniname2ctype_pool_str1152[sizeof("gunjalagondi")];
char uniname2ctype_pool_str1153[sizeof("phoenician")];
+ char uniname2ctype_pool_str1156[sizeof("inolduyghur")];
char uniname2ctype_pool_str1157[sizeof("multani")];
char uniname2ctype_pool_str1158[sizeof("kaithi")];
char uniname2ctype_pool_str1164[sizeof("joincontrol")];
@@ -39617,6 +42136,7 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1170[sizeof("ingeneralpunctuation")];
char uniname2ctype_pool_str1171[sizeof("inmahajani")];
char uniname2ctype_pool_str1174[sizeof("incyrillicsupplement")];
+ char uniname2ctype_pool_str1175[sizeof("lowercaseletter")];
char uniname2ctype_pool_str1176[sizeof("marchen")];
char uniname2ctype_pool_str1177[sizeof("graphemelink")];
char uniname2ctype_pool_str1178[sizeof("ingeorgian")];
@@ -39625,18 +42145,20 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1182[sizeof("inogham")];
char uniname2ctype_pool_str1183[sizeof("cher")];
char uniname2ctype_pool_str1185[sizeof("chakma")];
+ char uniname2ctype_pool_str1186[sizeof("inkaktoviknumerals")];
char uniname2ctype_pool_str1190[sizeof("emoji")];
char uniname2ctype_pool_str1191[sizeof("insiddham")];
char uniname2ctype_pool_str1197[sizeof("cherokee")];
char uniname2ctype_pool_str1198[sizeof("khar")];
char uniname2ctype_pool_str1203[sizeof("inmongolian")];
+ char uniname2ctype_pool_str1204[sizeof("innagmundari")];
char uniname2ctype_pool_str1207[sizeof("incherokeesupplement")];
char uniname2ctype_pool_str1209[sizeof("manichaean")];
char uniname2ctype_pool_str1212[sizeof("inolchiki")];
- char uniname2ctype_pool_str1213[sizeof("dogra")];
- char uniname2ctype_pool_str1221[sizeof("lowercaseletter")];
char uniname2ctype_pool_str1223[sizeof("inkhitansmallscript")];
char uniname2ctype_pool_str1227[sizeof("quotationmark")];
+ char uniname2ctype_pool_str1229[sizeof("vithkuqi")];
+ char uniname2ctype_pool_str1230[sizeof("variationselector")];
char uniname2ctype_pool_str1231[sizeof("adlam")];
char uniname2ctype_pool_str1232[sizeof("inethiopic")];
char uniname2ctype_pool_str1233[sizeof("graphemebase")];
@@ -39645,41 +42167,56 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1235[sizeof("age=12.1")];
char uniname2ctype_pool_str1236[sizeof("age=10.0")];
char uniname2ctype_pool_str1237[sizeof("age=12.0")];
- char uniname2ctype_pool_str1240[sizeof("age=13.0")];
+ char uniname2ctype_pool_str1241[sizeof("age=13.0")];
+ char uniname2ctype_pool_str1242[sizeof("age=1.1")];
#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1243[sizeof("casedletter")];
char uniname2ctype_pool_str1244[sizeof("ingurmukhi")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1245[sizeof("age=2.1")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1246[sizeof("incjkunifiedideographsextensiona")];
- char uniname2ctype_pool_str1247[sizeof("inunifiedcanadianaboriginalsyllabicsextended")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1247[sizeof("age=2.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1248[sizeof("lu")];
#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1250[sizeof("age=1.1")];
- char uniname2ctype_pool_str1252[sizeof("age=9.0")];
- char uniname2ctype_pool_str1253[sizeof("age=2.1")];
+ char uniname2ctype_pool_str1249[sizeof("age=3.1")];
+ char uniname2ctype_pool_str1250[sizeof("age=9.0")];
+ char uniname2ctype_pool_str1251[sizeof("age=3.0")];
+ char uniname2ctype_pool_str1252[sizeof("age=3.2")];
+ char uniname2ctype_pool_str1253[sizeof("age=8.0")];
#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1254[sizeof("intamilsupplement")];
#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1255[sizeof("age=2.0")];
- char uniname2ctype_pool_str1256[sizeof("age=3.1")];
- char uniname2ctype_pool_str1257[sizeof("age=8.0")];
- char uniname2ctype_pool_str1258[sizeof("age=3.0")];
- char uniname2ctype_pool_str1259[sizeof("age=3.2")];
- char uniname2ctype_pool_str1260[sizeof("age=6.1")];
- char uniname2ctype_pool_str1261[sizeof("age=7.0")];
- char uniname2ctype_pool_str1262[sizeof("age=6.0")];
- char uniname2ctype_pool_str1263[sizeof("age=6.2")];
+ char uniname2ctype_pool_str1255[sizeof("age=6.1")];
#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1264[sizeof("dogr")];
+ char uniname2ctype_pool_str1256[sizeof("unknown")];
#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1265[sizeof("age=5.1")];
- char uniname2ctype_pool_str1266[sizeof("age=6.3")];
- char uniname2ctype_pool_str1267[sizeof("age=5.0")];
- char uniname2ctype_pool_str1268[sizeof("age=5.2")];
- char uniname2ctype_pool_str1269[sizeof("age=4.1")];
- char uniname2ctype_pool_str1271[sizeof("age=4.0")];
+ char uniname2ctype_pool_str1257[sizeof("age=6.0")];
+ char uniname2ctype_pool_str1258[sizeof("age=6.2")];
+ char uniname2ctype_pool_str1259[sizeof("age=15.0")];
+ char uniname2ctype_pool_str1260[sizeof("age=7.0")];
+ char uniname2ctype_pool_str1262[sizeof("age=6.3")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1263[sizeof("cwt")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1265[sizeof("age=14.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1266[sizeof("unassigned")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1267[sizeof("age=5.1")];
+ char uniname2ctype_pool_str1269[sizeof("age=5.0")];
+ char uniname2ctype_pool_str1270[sizeof("age=5.2")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1271[sizeof("diacritic")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1273[sizeof("age=4.1")];
#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1274[sizeof("ahom")];
- char uniname2ctype_pool_str1278[sizeof("phnx")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1275[sizeof("age=4.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1282[sizeof("incjkunifiedideographsextensione")];
char uniname2ctype_pool_str1285[sizeof("khmr")];
char uniname2ctype_pool_str1289[sizeof("insinhala")];
@@ -39688,65 +42225,61 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1300[sizeof("guru")];
char uniname2ctype_pool_str1301[sizeof("sundanese")];
char uniname2ctype_pool_str1306[sizeof("punct")];
- char uniname2ctype_pool_str1309[sizeof("cwt")];
- char uniname2ctype_pool_str1312[sizeof("unassigned")];
char uniname2ctype_pool_str1314[sizeof("paucinhau")];
char uniname2ctype_pool_str1317[sizeof("gurmukhi")];
char uniname2ctype_pool_str1328[sizeof("chorasmian")];
char uniname2ctype_pool_str1331[sizeof("logicalorderexception")];
char uniname2ctype_pool_str1340[sizeof("khmer")];
char uniname2ctype_pool_str1343[sizeof("limbu")];
- char uniname2ctype_pool_str1348[sizeof("unknown")];
char uniname2ctype_pool_str1349[sizeof("chrs")];
char uniname2ctype_pool_str1352[sizeof("oriya")];
char uniname2ctype_pool_str1354[sizeof("inscriptionalpahlavi")];
+ char uniname2ctype_pool_str1356[sizeof("incyrillicextendedd")];
char uniname2ctype_pool_str1358[sizeof("incjkunifiedideographsextensionc")];
char uniname2ctype_pool_str1360[sizeof("cntrl")];
- char uniname2ctype_pool_str1362[sizeof("incjkunifiedideographsextensionf")];
char uniname2ctype_pool_str1365[sizeof("inlatinextendedadditional")];
- char uniname2ctype_pool_str1366[sizeof("ahex")];
char uniname2ctype_pool_str1367[sizeof("insorasompeng")];
char uniname2ctype_pool_str1369[sizeof("radical")];
char uniname2ctype_pool_str1373[sizeof("emojimodifier")];
char uniname2ctype_pool_str1375[sizeof("kharoshthi")];
- char uniname2ctype_pool_str1376[sizeof("dash")];
char uniname2ctype_pool_str1380[sizeof("n")];
char uniname2ctype_pool_str1384[sizeof("math")];
char uniname2ctype_pool_str1387[sizeof("goth")];
+ char uniname2ctype_pool_str1392[sizeof("phnx")];
char uniname2ctype_pool_str1400[sizeof("anatolianhieroglyphs")];
char uniname2ctype_pool_str1401[sizeof("inenclosedalphanumerics")];
char uniname2ctype_pool_str1407[sizeof("nandinagari")];
char uniname2ctype_pool_str1409[sizeof("no")];
+ char uniname2ctype_pool_str1415[sizeof("intangsa")];
char uniname2ctype_pool_str1419[sizeof("nko")];
char uniname2ctype_pool_str1420[sizeof("nkoo")];
char uniname2ctype_pool_str1422[sizeof("ingreekandcoptic")];
char uniname2ctype_pool_str1426[sizeof("p")];
char uniname2ctype_pool_str1428[sizeof("grantha")];
- char uniname2ctype_pool_str1434[sizeof("xpeo")];
+ char uniname2ctype_pool_str1429[sizeof("decimalnumber")];
char uniname2ctype_pool_str1438[sizeof("incjkunifiedideographs")];
- char uniname2ctype_pool_str1439[sizeof("zanb")];
char uniname2ctype_pool_str1442[sizeof("intirhuta")];
char uniname2ctype_pool_str1448[sizeof("inhatran")];
char uniname2ctype_pool_str1449[sizeof("linb")];
char uniname2ctype_pool_str1451[sizeof("mult")];
char uniname2ctype_pool_str1454[sizeof("saurashtra")];
char uniname2ctype_pool_str1457[sizeof("kthi")];
+ char uniname2ctype_pool_str1460[sizeof("zanb")];
char uniname2ctype_pool_str1462[sizeof("inbhaiksuki")];
char uniname2ctype_pool_str1470[sizeof("innabataean")];
char uniname2ctype_pool_str1471[sizeof("inphoenician")];
+ char uniname2ctype_pool_str1474[sizeof("xpeo")];
char uniname2ctype_pool_str1475[sizeof("inkanbun")];
char uniname2ctype_pool_str1476[sizeof("inmeroitichieroglyphs")];
+ char uniname2ctype_pool_str1480[sizeof("ahex")];
char uniname2ctype_pool_str1489[sizeof("enclosingmark")];
char uniname2ctype_pool_str1495[sizeof("sd")];
char uniname2ctype_pool_str1497[sizeof("inelbasan")];
char uniname2ctype_pool_str1499[sizeof("inenclosedideographicsupplement")];
char uniname2ctype_pool_str1501[sizeof("sidd")];
- char uniname2ctype_pool_str1505[sizeof("hani")];
char uniname2ctype_pool_str1507[sizeof("linearb")];
- char uniname2ctype_pool_str1508[sizeof("han")];
- char uniname2ctype_pool_str1509[sizeof("intifinagh")];
+ char uniname2ctype_pool_str1508[sizeof("cpmn")];
char uniname2ctype_pool_str1517[sizeof("inenclosedalphanumericsupplement")];
- char uniname2ctype_pool_str1519[sizeof("hano")];
char uniname2ctype_pool_str1520[sizeof("bidicontrol")];
char uniname2ctype_pool_str1524[sizeof("inphaistosdisc")];
char uniname2ctype_pool_str1529[sizeof("limb")];
@@ -39754,21 +42287,22 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1533[sizeof("lepc")];
char uniname2ctype_pool_str1536[sizeof("braille")];
char uniname2ctype_pool_str1537[sizeof("regionalindicator")];
- char uniname2ctype_pool_str1544[sizeof("inkhojki")];
+ char uniname2ctype_pool_str1542[sizeof("inlowsurrogates")];
char uniname2ctype_pool_str1547[sizeof("brah")];
- char uniname2ctype_pool_str1548[sizeof("hanunoo")];
char uniname2ctype_pool_str1549[sizeof("inoldhungarian")];
- char uniname2ctype_pool_str1551[sizeof("hira")];
char uniname2ctype_pool_str1557[sizeof("beng")];
char uniname2ctype_pool_str1563[sizeof("emojimodifierbase")];
char uniname2ctype_pool_str1565[sizeof("inarabic")];
char uniname2ctype_pool_str1570[sizeof("osage")];
char uniname2ctype_pool_str1572[sizeof("inherited")];
+ char uniname2ctype_pool_str1577[sizeof("incyprominoan")];
char uniname2ctype_pool_str1580[sizeof("glag")];
+ char uniname2ctype_pool_str1582[sizeof("medf")];
char uniname2ctype_pool_str1583[sizeof("osma")];
char uniname2ctype_pool_str1587[sizeof("indogra")];
- char uniname2ctype_pool_str1588[sizeof("inlowsurrogates")];
char uniname2ctype_pool_str1597[sizeof("arab")];
+ char uniname2ctype_pool_str1598[sizeof("medefaidrin")];
+ char uniname2ctype_pool_str1607[sizeof("inshorthandformatcontrols")];
char uniname2ctype_pool_str1613[sizeof("phli")];
char uniname2ctype_pool_str1617[sizeof("inimperialaramaic")];
char uniname2ctype_pool_str1618[sizeof("emod")];
@@ -39776,14 +42310,13 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1623[sizeof("inanatolianhieroglyphs")];
char uniname2ctype_pool_str1629[sizeof("punctuation")];
char uniname2ctype_pool_str1635[sizeof("graphemeextend")];
+ char uniname2ctype_pool_str1643[sizeof("cwl")];
+ char uniname2ctype_pool_str1644[sizeof("vith")];
char uniname2ctype_pool_str1654[sizeof("ingeometricshapes")];
char uniname2ctype_pool_str1655[sizeof("emojicomponent")];
- char uniname2ctype_pool_str1656[sizeof("softdotted")];
- char uniname2ctype_pool_str1658[sizeof("takri")];
- char uniname2ctype_pool_str1661[sizeof("inyezidi")];
+ char uniname2ctype_pool_str1657[sizeof("dsrt")];
char uniname2ctype_pool_str1662[sizeof("coptic")];
char uniname2ctype_pool_str1664[sizeof("inkayahli")];
- char uniname2ctype_pool_str1665[sizeof("invai")];
char uniname2ctype_pool_str1671[sizeof("inoriya")];
char uniname2ctype_pool_str1675[sizeof("inarabicpresentationformsa")];
char uniname2ctype_pool_str1677[sizeof("inbasiclatin")];
@@ -39791,21 +42324,20 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1684[sizeof("wara")];
char uniname2ctype_pool_str1686[sizeof("sinh")];
char uniname2ctype_pool_str1687[sizeof("sund")];
- char uniname2ctype_pool_str1689[sizeof("cwl")];
char uniname2ctype_pool_str1691[sizeof("shavian")];
char uniname2ctype_pool_str1699[sizeof("insundanesesupplement")];
- char uniname2ctype_pool_str1703[sizeof("takr")];
+ char uniname2ctype_pool_str1701[sizeof("inyezidi")];
char uniname2ctype_pool_str1704[sizeof("bhks")];
char uniname2ctype_pool_str1714[sizeof("bhaiksuki")];
- char uniname2ctype_pool_str1719[sizeof("taile")];
char uniname2ctype_pool_str1722[sizeof("inhanunoo")];
char uniname2ctype_pool_str1724[sizeof("intangut")];
- char uniname2ctype_pool_str1727[sizeof("inethiopicextendeda")];
char uniname2ctype_pool_str1728[sizeof("sogdian")];
char uniname2ctype_pool_str1729[sizeof("inlatinextendedd")];
char uniname2ctype_pool_str1730[sizeof("sogo")];
char uniname2ctype_pool_str1731[sizeof("insinhalaarchaicnumbers")];
char uniname2ctype_pool_str1732[sizeof("ideographic")];
+ char uniname2ctype_pool_str1733[sizeof("ugar")];
+ char uniname2ctype_pool_str1734[sizeof("deseret")];
char uniname2ctype_pool_str1735[sizeof("odi")];
char uniname2ctype_pool_str1740[sizeof("copt")];
char uniname2ctype_pool_str1742[sizeof("imperialaramaic")];
@@ -39819,223 +42351,220 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1768[sizeof("lycian")];
char uniname2ctype_pool_str1769[sizeof("inbatak")];
char uniname2ctype_pool_str1776[sizeof("cprt")];
- char uniname2ctype_pool_str1779[sizeof("ugar")];
+ char uniname2ctype_pool_str1781[sizeof("inunifiedcanadianaboriginalsyllabicsextendeda")];
char uniname2ctype_pool_str1788[sizeof("mymr")];
char uniname2ctype_pool_str1793[sizeof("myanmar")];
- char uniname2ctype_pool_str1794[sizeof("deva")];
char uniname2ctype_pool_str1806[sizeof("intibetan")];
char uniname2ctype_pool_str1810[sizeof("intags")];
char uniname2ctype_pool_str1811[sizeof("asciihexdigit")];
- char uniname2ctype_pool_str1812[sizeof("devanagari")];
char uniname2ctype_pool_str1813[sizeof("sentenceterminal")];
- char uniname2ctype_pool_str1816[sizeof("defaultignorablecodepoint")];
- char uniname2ctype_pool_str1817[sizeof("digit")];
- char uniname2ctype_pool_str1818[sizeof("term")];
char uniname2ctype_pool_str1821[sizeof("nand")];
- char uniname2ctype_pool_str1822[sizeof("hatran")];
char uniname2ctype_pool_str1828[sizeof("inblockelements")];
char uniname2ctype_pool_str1838[sizeof("inornamentaldingbats")];
+ char uniname2ctype_pool_str1841[sizeof("inethiopicextendeda")];
char uniname2ctype_pool_str1842[sizeof("innumberforms")];
+ char uniname2ctype_pool_str1843[sizeof("cwcf")];
char uniname2ctype_pool_str1845[sizeof("oidc")];
char uniname2ctype_pool_str1848[sizeof("bopo")];
- char uniname2ctype_pool_str1850[sizeof("hex")];
- char uniname2ctype_pool_str1855[sizeof("ext")];
- char uniname2ctype_pool_str1857[sizeof("hatr")];
+ char uniname2ctype_pool_str1851[sizeof("cuneiform")];
char uniname2ctype_pool_str1866[sizeof("caseignorable")];
char uniname2ctype_pool_str1871[sizeof("inoldpersian")];
- char uniname2ctype_pool_str1873[sizeof("inshavian")];
- char uniname2ctype_pool_str1876[sizeof("inbyzantinemusicalsymbols")];
- char uniname2ctype_pool_str1879[sizeof("xposixpunct")];
+ char uniname2ctype_pool_str1881[sizeof("cwu")];
char uniname2ctype_pool_str1888[sizeof("inelymaic")];
char uniname2ctype_pool_str1889[sizeof("insoyombo")];
char uniname2ctype_pool_str1896[sizeof("ingeometricshapesextended")];
char uniname2ctype_pool_str1902[sizeof("incjkcompatibility")];
char uniname2ctype_pool_str1904[sizeof("inmyanmarextendedb")];
char uniname2ctype_pool_str1905[sizeof("innushu")];
+ char uniname2ctype_pool_str1912[sizeof("inkanaextendedb")];
char uniname2ctype_pool_str1913[sizeof("olck")];
+ char uniname2ctype_pool_str1916[sizeof("inbyzantinemusicalsymbols")];
char uniname2ctype_pool_str1924[sizeof("olchiki")];
- char uniname2ctype_pool_str1927[sizeof("cwu")];
char uniname2ctype_pool_str1929[sizeof("inkatakanaphoneticextensions")];
char uniname2ctype_pool_str1932[sizeof("incoptic")];
char uniname2ctype_pool_str1935[sizeof("oids")];
char uniname2ctype_pool_str1936[sizeof("inarabicextendeda")];
+ char uniname2ctype_pool_str1941[sizeof("modifierletter")];
char uniname2ctype_pool_str1950[sizeof("incjksymbolsandpunctuation")];
char uniname2ctype_pool_str1956[sizeof("olower")];
char uniname2ctype_pool_str1958[sizeof("bopomofo")];
char uniname2ctype_pool_str1964[sizeof("inlisu")];
char uniname2ctype_pool_str1967[sizeof("inoldpermic")];
char uniname2ctype_pool_str1968[sizeof("innoblock")];
- char uniname2ctype_pool_str1976[sizeof("extpict")];
+ char uniname2ctype_pool_str1969[sizeof("ext")];
+ char uniname2ctype_pool_str1974[sizeof("inunifiedcanadianaboriginalsyllabics")];
+ char uniname2ctype_pool_str1981[sizeof("takri")];
char uniname2ctype_pool_str1985[sizeof("inbraillepatterns")];
+ char uniname2ctype_pool_str1988[sizeof("invai")];
char uniname2ctype_pool_str1991[sizeof("alpha")];
char uniname2ctype_pool_str1993[sizeof("inbalinese")];
char uniname2ctype_pool_str1994[sizeof("sorasompeng")];
char uniname2ctype_pool_str1996[sizeof("closepunctuation")];
- char uniname2ctype_pool_str1998[sizeof("taiviet")];
- char uniname2ctype_pool_str2001[sizeof("inphoneticextensions")];
+ char uniname2ctype_pool_str2001[sizeof("hani")];
char uniname2ctype_pool_str2002[sizeof("inmayannumerals")];
+ char uniname2ctype_pool_str2004[sizeof("han")];
char uniname2ctype_pool_str2006[sizeof("inmiscellaneousmathematicalsymbolsb")];
char uniname2ctype_pool_str2010[sizeof("inlepcha")];
char uniname2ctype_pool_str2011[sizeof("patsyn")];
char uniname2ctype_pool_str2012[sizeof("inlisusupplement")];
char uniname2ctype_pool_str2014[sizeof("insyriacsupplement")];
+ char uniname2ctype_pool_str2015[sizeof("hano")];
+ char uniname2ctype_pool_str2016[sizeof("newa")];
char uniname2ctype_pool_str2023[sizeof("spacingmark")];
char uniname2ctype_pool_str2024[sizeof("inpalmyrene")];
+ char uniname2ctype_pool_str2026[sizeof("takr")];
+ char uniname2ctype_pool_str2033[sizeof("xposixpunct")];
+ char uniname2ctype_pool_str2040[sizeof("inkhojki")];
+ char uniname2ctype_pool_str2042[sizeof("taile")];
char uniname2ctype_pool_str2043[sizeof("assigned")];
- char uniname2ctype_pool_str2049[sizeof("extender")];
- char uniname2ctype_pool_str2062[sizeof("newa")];
+ char uniname2ctype_pool_str2044[sizeof("hanunoo")];
+ char uniname2ctype_pool_str2047[sizeof("hira")];
+ char uniname2ctype_pool_str2048[sizeof("inarabicextendedc")];
+ char uniname2ctype_pool_str2062[sizeof("newtailue")];
char uniname2ctype_pool_str2070[sizeof("space")];
char uniname2ctype_pool_str2073[sizeof("intelugu")];
char uniname2ctype_pool_str2077[sizeof("lydi")];
char uniname2ctype_pool_str2078[sizeof("idsb")];
+ char uniname2ctype_pool_str2090[sizeof("extpict")];
char uniname2ctype_pool_str2092[sizeof("lydian")];
char uniname2ctype_pool_str2095[sizeof("inethiopicsupplement")];
char uniname2ctype_pool_str2103[sizeof("sarb")];
- char uniname2ctype_pool_str2107[sizeof("zanabazarsquare")];
- char uniname2ctype_pool_str2108[sizeof("newtailue")];
- char uniname2ctype_pool_str2110[sizeof("indevanagari")];
- char uniname2ctype_pool_str2111[sizeof("avestan")];
+ char uniname2ctype_pool_str2110[sizeof("ugaritic")];
char uniname2ctype_pool_str2114[sizeof("inyiradicals")];
+ char uniname2ctype_pool_str2115[sizeof("inphoneticextensions")];
char uniname2ctype_pool_str2117[sizeof("sharada")];
- char uniname2ctype_pool_str2118[sizeof("inphoneticextensionssupplement")];
- char uniname2ctype_pool_str2122[sizeof("deprecated")];
+ char uniname2ctype_pool_str2128[sizeof("zanabazarsquare")];
char uniname2ctype_pool_str2135[sizeof("bugi")];
char uniname2ctype_pool_str2137[sizeof("word")];
- char uniname2ctype_pool_str2141[sizeof("java")];
+ char uniname2ctype_pool_str2141[sizeof("term")];
char uniname2ctype_pool_str2145[sizeof("separator")];
char uniname2ctype_pool_str2146[sizeof("ingeorgiansupplement")];
char uniname2ctype_pool_str2149[sizeof("sogd")];
- char uniname2ctype_pool_str2156[sizeof("ugaritic")];
- char uniname2ctype_pool_str2162[sizeof("inethiopicextended")];
+ char uniname2ctype_pool_str2163[sizeof("extender")];
char uniname2ctype_pool_str2165[sizeof("shrd")];
char uniname2ctype_pool_str2166[sizeof("graph")];
- char uniname2ctype_pool_str2169[sizeof("gujr")];
- char uniname2ctype_pool_str2177[sizeof("tale")];
- char uniname2ctype_pool_str2178[sizeof("gujarati")];
+ char uniname2ctype_pool_str2174[sizeof("tnsa")];
+ char uniname2ctype_pool_str2178[sizeof("tangsa")];
char uniname2ctype_pool_str2181[sizeof("phag")];
- char uniname2ctype_pool_str2188[sizeof("terminalpunctuation")];
+ char uniname2ctype_pool_str2182[sizeof("dogra")];
char uniname2ctype_pool_str2195[sizeof("inhanguljamo")];
+ char uniname2ctype_pool_str2196[sizeof("inshavian")];
char uniname2ctype_pool_str2207[sizeof("siddham")];
- char uniname2ctype_pool_str2213[sizeof("ingeorgianextended")];
+ char uniname2ctype_pool_str2211[sizeof("cf")];
+ char uniname2ctype_pool_str2216[sizeof("inunifiedcanadianaboriginalsyllabicsextended")];
char uniname2ctype_pool_str2217[sizeof("buginese")];
char uniname2ctype_pool_str2218[sizeof("inmongoliansupplement")];
char uniname2ctype_pool_str2219[sizeof("cyrl")];
char uniname2ctype_pool_str2224[sizeof("inhanguljamoextendeda")];
- char uniname2ctype_pool_str2226[sizeof("javanese")];
- char uniname2ctype_pool_str2228[sizeof("taml")];
+ char uniname2ctype_pool_str2228[sizeof("pf")];
char uniname2ctype_pool_str2229[sizeof("number")];
- char uniname2ctype_pool_str2230[sizeof("incyrillicextendedb")];
+ char uniname2ctype_pool_str2232[sizeof("inphoneticextensionssupplement")];
+ char uniname2ctype_pool_str2233[sizeof("dogr")];
char uniname2ctype_pool_str2234[sizeof("mlym")];
char uniname2ctype_pool_str2235[sizeof("incopticepactnumbers")];
char uniname2ctype_pool_str2241[sizeof("malayalam")];
char uniname2ctype_pool_str2244[sizeof("inbamum")];
char uniname2ctype_pool_str2247[sizeof("nd")];
char uniname2ctype_pool_str2248[sizeof("insuttonsignwriting")];
- char uniname2ctype_pool_str2249[sizeof("invariationselectors")];
- char uniname2ctype_pool_str2252[sizeof("inverticalforms")];
- char uniname2ctype_pool_str2265[sizeof("avst")];
+ char uniname2ctype_pool_str2276[sizeof("inethiopicextended")];
+ char uniname2ctype_pool_str2278[sizeof("shaw")];
char uniname2ctype_pool_str2279[sizeof("palmyrene")];
char uniname2ctype_pool_str2283[sizeof("soyo")];
- char uniname2ctype_pool_str2285[sizeof("intaiviet")];
+ char uniname2ctype_pool_str2296[sizeof("incjkunifiedideographsextensionh")];
+ char uniname2ctype_pool_str2305[sizeof("sgnw")];
+ char uniname2ctype_pool_str2308[sizeof("toto")];
char uniname2ctype_pool_str2312[sizeof("caucasianalbanian")];
char uniname2ctype_pool_str2315[sizeof("inmathematicalalphanumericsymbols")];
char uniname2ctype_pool_str2316[sizeof("incjkunifiedideographsextensiong")];
+ char uniname2ctype_pool_str2318[sizeof("hatran")];
+ char uniname2ctype_pool_str2321[sizeof("taiviet")];
char uniname2ctype_pool_str2323[sizeof("meroitichieroglyphs")];
- char uniname2ctype_pool_str2324[sizeof("shaw")];
- char uniname2ctype_pool_str2329[sizeof("invedicextensions")];
+ char uniname2ctype_pool_str2327[sizeof("ingeorgianextended")];
+ char uniname2ctype_pool_str2331[sizeof("incjkunifiedideographsextensionf")];
char uniname2ctype_pool_str2333[sizeof("oldpersian")];
char uniname2ctype_pool_str2343[sizeof("induployan")];
- char uniname2ctype_pool_str2351[sizeof("sgnw")];
+ char uniname2ctype_pool_str2344[sizeof("incyrillicextendedb")];
+ char uniname2ctype_pool_str2345[sizeof("dash")];
+ char uniname2ctype_pool_str2353[sizeof("hatr")];
char uniname2ctype_pool_str2361[sizeof("innyiakengpuachuehmong")];
char uniname2ctype_pool_str2364[sizeof("incombiningdiacriticalmarks")];
- char uniname2ctype_pool_str2366[sizeof("invariationselectorssupplement")];
char uniname2ctype_pool_str2373[sizeof("nl")];
char uniname2ctype_pool_str2374[sizeof("incombiningdiacriticalmarksforsymbols")];
+ char uniname2ctype_pool_str2375[sizeof("khudawadi")];
char uniname2ctype_pool_str2397[sizeof("incjkradicalssupplement")];
char uniname2ctype_pool_str2398[sizeof("inglagolitic")];
char uniname2ctype_pool_str2405[sizeof("orkh")];
char uniname2ctype_pool_str2414[sizeof("syrc")];
- char uniname2ctype_pool_str2421[sizeof("khudawadi")];
char uniname2ctype_pool_str2427[sizeof("surrogate")];
- char uniname2ctype_pool_str2431[sizeof("extendedpictographic")];
+ char uniname2ctype_pool_str2433[sizeof("indevanagari")];
+ char uniname2ctype_pool_str2434[sizeof("avestan")];
char uniname2ctype_pool_str2437[sizeof("oldpermic")];
char uniname2ctype_pool_str2440[sizeof("ethi")];
char uniname2ctype_pool_str2451[sizeof("ogam")];
char uniname2ctype_pool_str2454[sizeof("rohg")];
char uniname2ctype_pool_str2460[sizeof("idstrinaryoperator")];
+ char uniname2ctype_pool_str2464[sizeof("java")];
char uniname2ctype_pool_str2470[sizeof("inphagspa")];
char uniname2ctype_pool_str2475[sizeof("lepcha")];
- char uniname2ctype_pool_str2478[sizeof("titlecaseletter")];
+ char uniname2ctype_pool_str2476[sizeof("indevanagariextendeda")];
+ char uniname2ctype_pool_str2478[sizeof("intifinagh")];
char uniname2ctype_pool_str2479[sizeof("intagalog")];
char uniname2ctype_pool_str2481[sizeof("incombiningdiacriticalmarkssupplement")];
- char uniname2ctype_pool_str2485[sizeof("inmeroiticcursive")];
+ char uniname2ctype_pool_str2500[sizeof("tale")];
char uniname2ctype_pool_str2506[sizeof("inbrahmi")];
+ char uniname2ctype_pool_str2511[sizeof("terminalpunctuation")];
char uniname2ctype_pool_str2513[sizeof("insymbolsandpictographsextendeda")];
char uniname2ctype_pool_str2530[sizeof("syriac")];
- char uniname2ctype_pool_str2533[sizeof("modifiersymbol")];
char uniname2ctype_pool_str2534[sizeof("inbengali")];
- char uniname2ctype_pool_str2536[sizeof("inhalfwidthandfullwidthforms")];
+ char uniname2ctype_pool_str2535[sizeof("nagm")];
+ char uniname2ctype_pool_str2545[sizeof("extendedpictographic")];
char uniname2ctype_pool_str2548[sizeof("buhd")];
- char uniname2ctype_pool_str2562[sizeof("mahj")];
+ char uniname2ctype_pool_str2549[sizeof("javanese")];
+ char uniname2ctype_pool_str2551[sizeof("taml")];
char uniname2ctype_pool_str2564[sizeof("inbuginese")];
char uniname2ctype_pool_str2567[sizeof("inlatin1supplement")];
char uniname2ctype_pool_str2570[sizeof("ingothic")];
- char uniname2ctype_pool_str2571[sizeof("mahajani")];
- char uniname2ctype_pool_str2572[sizeof("hang")];
+ char uniname2ctype_pool_str2572[sizeof("invariationselectors")];
+ char uniname2ctype_pool_str2574[sizeof("hex")];
+ char uniname2ctype_pool_str2575[sizeof("inverticalforms")];
char uniname2ctype_pool_str2576[sizeof("ebase")];
- char uniname2ctype_pool_str2579[sizeof("insmallformvariants")];
char uniname2ctype_pool_str2582[sizeof("incurrencysymbols")];
- char uniname2ctype_pool_str2588[sizeof("indevanagariextended")];
- char uniname2ctype_pool_str2589[sizeof("divesakuru")];
- char uniname2ctype_pool_str2591[sizeof("ingujarati")];
+ char uniname2ctype_pool_str2588[sizeof("avst")];
char uniname2ctype_pool_str2602[sizeof("osge")];
char uniname2ctype_pool_str2606[sizeof("incombiningdiacriticalmarksextended")];
+ char uniname2ctype_pool_str2608[sizeof("intaiviet")];
char uniname2ctype_pool_str2609[sizeof("spaceseparator")];
- char uniname2ctype_pool_str2610[sizeof("ingunjalagondi")];
- char uniname2ctype_pool_str2611[sizeof("dupl")];
- char uniname2ctype_pool_str2627[sizeof("hiragana")];
- char uniname2ctype_pool_str2630[sizeof("tirhuta")];
- char uniname2ctype_pool_str2639[sizeof("inrejang")];
- char uniname2ctype_pool_str2644[sizeof("dashpunctuation")];
+ char uniname2ctype_pool_str2625[sizeof("softdotted")];
char uniname2ctype_pool_str2648[sizeof("nchar")];
- char uniname2ctype_pool_str2649[sizeof("khoj")];
+ char uniname2ctype_pool_str2652[sizeof("invedicextensions")];
char uniname2ctype_pool_str2656[sizeof("inlimbu")];
char uniname2ctype_pool_str2657[sizeof("olditalic")];
- char uniname2ctype_pool_str2659[sizeof("hmng")];
+ char uniname2ctype_pool_str2665[sizeof("gujr")];
char uniname2ctype_pool_str2666[sizeof("mathsymbol")];
char uniname2ctype_pool_str2670[sizeof("incjkunifiedideographsextensionb")];
+ char uniname2ctype_pool_str2674[sizeof("gujarati")];
char uniname2ctype_pool_str2688[sizeof("phagspa")];
- char uniname2ctype_pool_str2692[sizeof("thaa")];
+ char uniname2ctype_pool_str2689[sizeof("invariationselectorssupplement")];
char uniname2ctype_pool_str2694[sizeof("currencysymbol")];
- char uniname2ctype_pool_str2695[sizeof("thai")];
- char uniname2ctype_pool_str2697[sizeof("inenclosedcjklettersandmonths")];
- char uniname2ctype_pool_str2703[sizeof("thaana")];
- char uniname2ctype_pool_str2704[sizeof("hanifirohingya")];
char uniname2ctype_pool_str2705[sizeof("inlinearbsyllabary")];
- char uniname2ctype_pool_str2719[sizeof("tang")];
- char uniname2ctype_pool_str2725[sizeof("tagbanwa")];
char uniname2ctype_pool_str2726[sizeof("wancho")];
- char uniname2ctype_pool_str2729[sizeof("tamil")];
- char uniname2ctype_pool_str2745[sizeof("zp")];
- char uniname2ctype_pool_str2748[sizeof("tirh")];
char uniname2ctype_pool_str2750[sizeof("inpaucinhau")];
- char uniname2ctype_pool_str2759[sizeof("talu")];
char uniname2ctype_pool_str2761[sizeof("other")];
char uniname2ctype_pool_str2762[sizeof("otheridcontinue")];
char uniname2ctype_pool_str2765[sizeof("sylo")];
+ char uniname2ctype_pool_str2766[sizeof("zp")];
char uniname2ctype_pool_str2769[sizeof("inaegeannumbers")];
char uniname2ctype_pool_str2772[sizeof("warangciti")];
char uniname2ctype_pool_str2775[sizeof("othernumber")];
- char uniname2ctype_pool_str2787[sizeof("taitham")];
+ char uniname2ctype_pool_str2786[sizeof("digit")];
char uniname2ctype_pool_str2793[sizeof("nonspacingmark")];
- char uniname2ctype_pool_str2795[sizeof("telu")];
+ char uniname2ctype_pool_str2801[sizeof("titlecaseletter")];
+ char uniname2ctype_pool_str2808[sizeof("inmeroiticcursive")];
char uniname2ctype_pool_str2810[sizeof("wcho")];
char uniname2ctype_pool_str2816[sizeof("graphemeclusterbreak=spacingmark")];
char uniname2ctype_pool_str2821[sizeof("inletterlikesymbols")];
- char uniname2ctype_pool_str2824[sizeof("tifinagh")];
char uniname2ctype_pool_str2830[sizeof("inottomansiyaqnumbers")];
char uniname2ctype_pool_str2834[sizeof("intagbanwa")];
- char uniname2ctype_pool_str2835[sizeof("tfng")];
char uniname2ctype_pool_str2836[sizeof("cyrillic")];
char uniname2ctype_pool_str2847[sizeof("oalpha")];
char uniname2ctype_pool_str2852[sizeof("graphemeclusterbreak=cr")];
@@ -40046,18 +42575,15 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2868[sizeof("otheralphabetic")];
char uniname2ctype_pool_str2871[sizeof("noncharactercodepoint")];
char uniname2ctype_pool_str2879[sizeof("oldhungarian")];
- char uniname2ctype_pool_str2881[sizeof("rjng")];
- char uniname2ctype_pool_str2885[sizeof("changeswhencasefolded")];
char uniname2ctype_pool_str2886[sizeof("insymbolsforlegacycomputing")];
- char uniname2ctype_pool_str2889[sizeof("tangut")];
- char uniname2ctype_pool_str2899[sizeof("dep")];
+ char uniname2ctype_pool_str2902[sizeof("insmallformvariants")];
char uniname2ctype_pool_str2904[sizeof("inhangulsyllables")];
char uniname2ctype_pool_str2905[sizeof("emojipresentation")];
char uniname2ctype_pool_str2907[sizeof("epres")];
char uniname2ctype_pool_str2909[sizeof("inbassavah")];
- char uniname2ctype_pool_str2915[sizeof("graphemeclusterbreak=lf")];
+ char uniname2ctype_pool_str2911[sizeof("indevanagariextended")];
char uniname2ctype_pool_str2941[sizeof("inbuhid")];
- char uniname2ctype_pool_str2959[sizeof("hmnp")];
+ char uniname2ctype_pool_str2953[sizeof("tirhuta")];
char uniname2ctype_pool_str2964[sizeof("inpsalterpahlavi")];
char uniname2ctype_pool_str2966[sizeof("whitespace")];
char uniname2ctype_pool_str2967[sizeof("finalpunctuation")];
@@ -40067,31 +42593,53 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2986[sizeof("buhid")];
char uniname2ctype_pool_str2987[sizeof("paragraphseparator")];
char uniname2ctype_pool_str2988[sizeof("inalphabeticpresentationforms")];
+ char uniname2ctype_pool_str2997[sizeof("inlatinextendedg")];
char uniname2ctype_pool_str3001[sizeof("elba")];
char uniname2ctype_pool_str3002[sizeof("changeswhentitlecased")];
char uniname2ctype_pool_str3005[sizeof("incombininghalfmarks")];
char uniname2ctype_pool_str3006[sizeof("intangutcomponents")];
- char uniname2ctype_pool_str3008[sizeof("hebr")];
+ char uniname2ctype_pool_str3015[sizeof("thaa")];
+ char uniname2ctype_pool_str3018[sizeof("thai")];
char uniname2ctype_pool_str3019[sizeof("oldturkic")];
+ char uniname2ctype_pool_str3026[sizeof("thaana")];
+ char uniname2ctype_pool_str3027[sizeof("inlatinextendedf")];
+ char uniname2ctype_pool_str3035[sizeof("ougr")];
+ char uniname2ctype_pool_str3042[sizeof("tang")];
char uniname2ctype_pool_str3045[sizeof("inarabicmathematicalalphabeticsymbols")];
+ char uniname2ctype_pool_str3048[sizeof("tagbanwa")];
+ char uniname2ctype_pool_str3052[sizeof("tamil")];
char uniname2ctype_pool_str3053[sizeof("khitansmallscript")];
+ char uniname2ctype_pool_str3058[sizeof("mahj")];
+ char uniname2ctype_pool_str3067[sizeof("mahajani")];
+ char uniname2ctype_pool_str3068[sizeof("hang")];
+ char uniname2ctype_pool_str3071[sizeof("tirh")];
char uniname2ctype_pool_str3072[sizeof("sylotinagri")];
- char uniname2ctype_pool_str3079[sizeof("hexdigit")];
- char uniname2ctype_pool_str3082[sizeof("inprivateusearea")];
+ char uniname2ctype_pool_str3082[sizeof("talu")];
+ char uniname2ctype_pool_str3084[sizeof("nagmundari")];
+ char uniname2ctype_pool_str3086[sizeof("deva")];
+ char uniname2ctype_pool_str3087[sizeof("ingujarati")];
+ char uniname2ctype_pool_str3091[sizeof("deprecated")];
char uniname2ctype_pool_str3099[sizeof("inarabicpresentationformsb")];
+ char uniname2ctype_pool_str3104[sizeof("devanagari")];
+ char uniname2ctype_pool_str3106[sizeof("ingunjalagondi")];
char uniname2ctype_pool_str3107[sizeof("graphemeclusterbreak=t")];
char uniname2ctype_pool_str3109[sizeof("graphemeclusterbreak=lvt")];
+ char uniname2ctype_pool_str3110[sizeof("taitham")];
char uniname2ctype_pool_str3111[sizeof("nbat")];
- char uniname2ctype_pool_str3122[sizeof("hangul")];
+ char uniname2ctype_pool_str3118[sizeof("telu")];
+ char uniname2ctype_pool_str3123[sizeof("hiragana")];
char uniname2ctype_pool_str3125[sizeof("nabataean")];
+ char uniname2ctype_pool_str3135[sizeof("inrejang")];
char uniname2ctype_pool_str3142[sizeof("intangutsupplement")];
+ char uniname2ctype_pool_str3145[sizeof("khoj")];
+ char uniname2ctype_pool_str3155[sizeof("hmng")];
+ char uniname2ctype_pool_str3157[sizeof("cyprominoan")];
+ char uniname2ctype_pool_str3158[sizeof("inhebrew")];
char uniname2ctype_pool_str3176[sizeof("inmathematicaloperators")];
char uniname2ctype_pool_str3180[sizeof("inarabicsupplement")];
- char uniname2ctype_pool_str3188[sizeof("injavanese")];
- char uniname2ctype_pool_str3190[sizeof("hung")];
- char uniname2ctype_pool_str3199[sizeof("ogrext")];
- char uniname2ctype_pool_str3204[sizeof("inhebrew")];
+ char uniname2ctype_pool_str3193[sizeof("inenclosedcjklettersandmonths")];
char uniname2ctype_pool_str3209[sizeof("changeswhenlowercased")];
+ char uniname2ctype_pool_str3212[sizeof("tangut")];
char uniname2ctype_pool_str3215[sizeof("elbasan")];
char uniname2ctype_pool_str3218[sizeof("osmanya")];
char uniname2ctype_pool_str3237[sizeof("insuperscriptsandsubscripts")];
@@ -40099,85 +42647,110 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str3240[sizeof("graphemeclusterbreak=prepend")];
char uniname2ctype_pool_str3248[sizeof("nshu")];
char uniname2ctype_pool_str3254[sizeof("otherlowercase")];
- char uniname2ctype_pool_str3260[sizeof("hluw")];
+ char uniname2ctype_pool_str3265[sizeof("inethiopicextendedb")];
char uniname2ctype_pool_str3267[sizeof("otherletter")];
char uniname2ctype_pool_str3275[sizeof("kayahli")];
char uniname2ctype_pool_str3284[sizeof("inplayingcards")];
char uniname2ctype_pool_str3287[sizeof("elym")];
char uniname2ctype_pool_str3297[sizeof("graphemeclusterbreak=l")];
char uniname2ctype_pool_str3303[sizeof("graphemeclusterbreak=control")];
+ char uniname2ctype_pool_str3313[sizeof("ogrext")];
char uniname2ctype_pool_str3320[sizeof("elymaic")];
char uniname2ctype_pool_str3328[sizeof("changeswhenuppercased")];
char uniname2ctype_pool_str3329[sizeof("inalchemicalsymbols")];
char uniname2ctype_pool_str3331[sizeof("oldsogdian")];
- char uniname2ctype_pool_str3336[sizeof("bassavah")];
char uniname2ctype_pool_str3338[sizeof("otheridstart")];
char uniname2ctype_pool_str3348[sizeof("insupplementalarrowsa")];
+ char uniname2ctype_pool_str3350[sizeof("invithkuqi")];
char uniname2ctype_pool_str3355[sizeof("symbol")];
- char uniname2ctype_pool_str3361[sizeof("inmahjongtiles")];
+ char uniname2ctype_pool_str3360[sizeof("inarabicextendedb")];
char uniname2ctype_pool_str3371[sizeof("cypriot")];
char uniname2ctype_pool_str3372[sizeof("any")];
char uniname2ctype_pool_str3373[sizeof("otheruppercase")];
- char uniname2ctype_pool_str3376[sizeof("indivesakuru")];
- char uniname2ctype_pool_str3378[sizeof("tibt")];
- char uniname2ctype_pool_str3390[sizeof("tibetan")];
+ char uniname2ctype_pool_str3377[sizeof("rjng")];
char uniname2ctype_pool_str3391[sizeof("wspace")];
char uniname2ctype_pool_str3396[sizeof("inindicsiyaqnumbers")];
+ char uniname2ctype_pool_str3405[sizeof("inprivateusearea")];
char uniname2ctype_pool_str3416[sizeof("othersymbol")];
char uniname2ctype_pool_str3428[sizeof("oupper")];
+ char uniname2ctype_pool_str3433[sizeof("signwriting")];
char uniname2ctype_pool_str3436[sizeof("nushu")];
- char uniname2ctype_pool_str3448[sizeof("inyijinghexagramsymbols")];
+ char uniname2ctype_pool_str3455[sizeof("hmnp")];
+ char uniname2ctype_pool_str3458[sizeof("upper")];
char uniname2ctype_pool_str3460[sizeof("insupplementalarrowsc")];
- char uniname2ctype_pool_str3479[sizeof("signwriting")];
char uniname2ctype_pool_str3483[sizeof("omath")];
- char uniname2ctype_pool_str3504[sizeof("upper")];
+ char uniname2ctype_pool_str3502[sizeof("modifiersymbol")];
+ char uniname2ctype_pool_str3504[sizeof("hebr")];
+ char uniname2ctype_pool_str3505[sizeof("inhalfwidthandfullwidthforms")];
char uniname2ctype_pool_str3511[sizeof("insupplementalmathematicaloperators")];
char uniname2ctype_pool_str3532[sizeof("inpahawhhmong")];
char uniname2ctype_pool_str3533[sizeof("alphabetic")];
- char uniname2ctype_pool_str3585[sizeof("tavt")];
+ char uniname2ctype_pool_str3558[sizeof("uppercase")];
+ char uniname2ctype_pool_str3580[sizeof("dupl")];
char uniname2ctype_pool_str3590[sizeof("ogham")];
- char uniname2ctype_pool_str3604[sizeof("uppercase")];
+ char uniname2ctype_pool_str3613[sizeof("dashpunctuation")];
+ char uniname2ctype_pool_str3618[sizeof("hangul")];
char uniname2ctype_pool_str3648[sizeof("inhanguljamoextendedb")];
+ char uniname2ctype_pool_str3659[sizeof("bassavah")];
char uniname2ctype_pool_str3664[sizeof("aghb")];
+ char uniname2ctype_pool_str3686[sizeof("hung")];
+ char uniname2ctype_pool_str3689[sizeof("hexdigit")];
char uniname2ctype_pool_str3698[sizeof("incypriotsyllabary")];
+ char uniname2ctype_pool_str3699[sizeof("indivesakuru")];
+ char uniname2ctype_pool_str3701[sizeof("tibt")];
char uniname2ctype_pool_str3705[sizeof("inlatinextendedb")];
+ char uniname2ctype_pool_str3710[sizeof("hluw")];
+ char uniname2ctype_pool_str3713[sizeof("tibetan")];
char uniname2ctype_pool_str3721[sizeof("inyisyllables")];
char uniname2ctype_pool_str3744[sizeof("oldnortharabian")];
- char uniname2ctype_pool_str3765[sizeof("duployan")];
+ char uniname2ctype_pool_str3754[sizeof("defaultignorablecodepoint")];
char uniname2ctype_pool_str3766[sizeof("inhighprivateusesurrogates")];
char uniname2ctype_pool_str3799[sizeof("soyombo")];
char uniname2ctype_pool_str3807[sizeof("otherdefaultignorablecodepoint")];
+ char uniname2ctype_pool_str3842[sizeof("pahawhhmong")];
+ char uniname2ctype_pool_str3845[sizeof("unifiedideograph")];
char uniname2ctype_pool_str3850[sizeof("othermath")];
- char uniname2ctype_pool_str3884[sizeof("inbopomofoextended")];
- char uniname2ctype_pool_str3888[sizeof("pahawhhmong")];
- char uniname2ctype_pool_str3891[sizeof("unifiedideograph")];
+ char uniname2ctype_pool_str3854[sizeof("changeswhencasefolded")];
+ char uniname2ctype_pool_str3857[sizeof("inmahjongtiles")];
+ char uniname2ctype_pool_str3868[sizeof("dep")];
+ char uniname2ctype_pool_str3881[sizeof("divesakuru")];
+ char uniname2ctype_pool_str3884[sizeof("graphemeclusterbreak=lf")];
+ char uniname2ctype_pool_str3891[sizeof("uppercaseletter")];
char uniname2ctype_pool_str3924[sizeof("insupplementalpunctuation")];
- char uniname2ctype_pool_str3937[sizeof("uppercaseletter")];
char uniname2ctype_pool_str3942[sizeof("ethiopic")];
+ char uniname2ctype_pool_str3944[sizeof("inyijinghexagramsymbols")];
char uniname2ctype_pool_str3949[sizeof("ecomp")];
char uniname2ctype_pool_str3976[sizeof("inglagoliticsupplement")];
- char uniname2ctype_pool_str3991[sizeof("rejang")];
+ char uniname2ctype_pool_str3998[sizeof("inbopomofoextended")];
+ char uniname2ctype_pool_str4007[sizeof("injavanese")];
char uniname2ctype_pool_str4106[sizeof("otherpunctuation")];
- char uniname2ctype_pool_str4136[sizeof("tagb")];
- char uniname2ctype_pool_str4194[sizeof("inboxdrawing")];
- char uniname2ctype_pool_str4281[sizeof("tglg")];
- char uniname2ctype_pool_str4287[sizeof("graphemeclusterbreak=zwj")];
- char uniname2ctype_pool_str4291[sizeof("hebrew")];
- char uniname2ctype_pool_str4303[sizeof("tagalog")];
+ char uniname2ctype_pool_str4116[sizeof("tifinagh")];
+ char uniname2ctype_pool_str4127[sizeof("tfng")];
+ char uniname2ctype_pool_str4169[sizeof("hanifirohingya")];
+ char uniname2ctype_pool_str4231[sizeof("tavt")];
+ char uniname2ctype_pool_str4308[sizeof("inboxdrawing")];
char uniname2ctype_pool_str4309[sizeof("oldsoutharabian")];
char uniname2ctype_pool_str4348[sizeof("inegyptianhieroglyphs")];
char uniname2ctype_pool_str4361[sizeof("inegyptianhieroglyphformatcontrols")];
- char uniname2ctype_pool_str4432[sizeof("graphemeclusterbreak=v")];
- char uniname2ctype_pool_str4433[sizeof("graphemeclusterbreak=lv")];
- char uniname2ctype_pool_str4487[sizeof("telugu")];
- char uniname2ctype_pool_str4542[sizeof("hyphen")];
+ char uniname2ctype_pool_str4459[sizeof("tagb")];
+ char uniname2ctype_pool_str4487[sizeof("rejang")];
+ char uniname2ctype_pool_str4604[sizeof("tglg")];
+ char uniname2ctype_pool_str4626[sizeof("tagalog")];
char uniname2ctype_pool_str4627[sizeof("othergraphemeextend")];
char uniname2ctype_pool_str4674[sizeof("insupplementaryprivateuseareaa")];
char uniname2ctype_pool_str4683[sizeof("inhighsurrogates")];
+ char uniname2ctype_pool_str4695[sizeof("hebrew")];
+ char uniname2ctype_pool_str4734[sizeof("duployan")];
+ char uniname2ctype_pool_str4755[sizeof("graphemeclusterbreak=v")];
+ char uniname2ctype_pool_str4756[sizeof("graphemeclusterbreak=lv")];
char uniname2ctype_pool_str4772[sizeof("insupplementalarrowsb")];
- char uniname2ctype_pool_str4877[sizeof("zyyy")];
+ char uniname2ctype_pool_str4783[sizeof("graphemeclusterbreak=zwj")];
+ char uniname2ctype_pool_str4810[sizeof("telugu")];
+ char uniname2ctype_pool_str4898[sizeof("zyyy")];
+ char uniname2ctype_pool_str4982[sizeof("olduyghur")];
char uniname2ctype_pool_str4986[sizeof("inhangulcompatibilityjamo")];
char uniname2ctype_pool_str5018[sizeof("openpunctuation")];
+ char uniname2ctype_pool_str5038[sizeof("hyphen")];
char uniname2ctype_pool_str5134[sizeof("insupplementalsymbolsandpictographs")];
char uniname2ctype_pool_str5141[sizeof("egyp")];
char uniname2ctype_pool_str5300[sizeof("nyiakengpuachuehmong")];
@@ -40190,9 +42763,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
#ifndef USE_UNICODE_PROPERTIES
"word",
#else /* USE_UNICODE_PROPERTIES */
- "z",
"yi",
- "zzzz",
"yiii",
"lana",
"lina",
@@ -40204,15 +42775,16 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"ci",
"lao",
"laoo",
- "yezi",
"inkannada",
"cn",
"pi",
"innko",
+ "z",
"gran",
"co",
"lineara",
"mark",
+ "yezi",
"po",
"me",
"cari",
@@ -40227,13 +42799,10 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"geor",
"greek",
"gonm",
- "dia",
- "di",
"mendekikakui",
"pe",
"mero",
"inosmanya",
- "diak",
"cakm",
"inmanichaean",
"inmro",
@@ -40242,9 +42811,8 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"c",
"mandaic",
"meeteimayek",
+ "zzzz",
"inarmenian",
- "vai",
- "vaii",
"inmyanmar",
"inmakasar",
"common",
@@ -40270,19 +42838,18 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"armn",
"incherokee",
"prependedconcatenationmark",
- "cf",
"incuneiform",
"inavestan",
"inipaextensions",
"pc",
"armenian",
"insharada",
+ "vai",
+ "vaii",
"inmarchen",
- "pf",
"makasar",
"masaramgondi",
"inarrows",
- "diacritic",
"incyrillic",
"incham",
"qmark",
@@ -40293,7 +42860,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inmasaramgondi",
"inthaana",
"latin",
- "inzanabazarsquare",
"inthai",
"lineseparator",
"pcm",
@@ -40302,16 +42868,16 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inscriptionalparthian",
"initialpunctuation",
"mtei",
+ "inzanabazarsquare",
"inkhmersymbols",
"insyriac",
"intakri",
"arabic",
- "zs",
"katakana",
"prti",
+ "zs",
"ascii",
"cs",
- "decimalnumber",
"ps",
"mand",
"privateuse",
@@ -40321,26 +42887,24 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"incjkcompatibilityforms",
"inkanaextendeda",
"incjkcompatibilityideographs",
- "yezidi",
"brai",
"mend",
"ideo",
"letter",
"l",
"inmeeteimayek",
- "xidcontinue",
"inideographicdescriptioncharacters",
+ "yezidi",
"knda",
"innandinagari",
"kannada",
"inmodi",
"inlao",
+ "xidcontinue",
"inoldnortharabian",
- "xidc",
"intransportandmapsymbols",
"letternumber",
"gothic",
- "vs",
"inlineara",
"inmendekikakui",
"mongolian",
@@ -40351,33 +42915,34 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inemoticons",
"kali",
"inolditalic",
+ "xidc",
"inmedefaidrin",
"inchesssymbols",
"incjkcompatibilityideographssupplement",
"kits",
- "medf",
"inadlam",
"psalterpahlavi",
"incommonindicnumberforms",
- "medefaidrin",
"lt",
- "patternsyntax",
- "inshorthandformatcontrols",
+ "innewa",
"sk",
"control",
+ "inkawi",
"inancientsymbols",
"palm",
"inlycian",
- "xids",
"so",
"patternwhitespace",
"inmandaic",
"idc",
"meroiticcursive",
- "innewa",
- "dsrt",
+ "intoto",
+ "vs",
+ "xids",
+ "inwarangciti",
"sora",
"inopticalcharacterrecognition",
+ "kawi",
"inoldsogdian",
"inmalayalam",
"bamum",
@@ -40391,18 +42956,18 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"alpha",
#else /* USE_UNICODE_PROPERTIES */
"intaitham",
- "inwarangciti",
+ "lower",
+ "patternsyntax",
"joinc",
"inoldsoutharabian",
"incjkstrokes",
"batk",
- "deseret",
"samr",
+ "inwancho",
"batak",
"patws",
"samaritan",
"idsbinaryoperator",
- "lower",
"pauc",
"insmallkanaextension",
"sm",
@@ -40410,10 +42975,8 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
#endif /* USE_UNICODE_PROPERTIES */
"alnum",
#ifdef USE_UNICODE_PROPERTIES
- "incyrillicextendeda",
+ "inznamennymusicalnotation",
"insylotinagri",
- "intaixuanjingsymbols",
- "inwancho",
"inugaritic",
"incontrolpictures",
"inlinearbideograms",
@@ -40423,23 +42986,22 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inmodifiertoneletters",
"inancientgreekmusicalnotation",
"lisu",
+ "lowercase",
+ "cwcm",
"sc",
"bass",
"ids",
"inlatinextendeda",
"intaile",
- "cuneiform",
"inmiscellaneoussymbols",
- "lowercase",
- "cwcm",
"inmiscellaneoussymbolsandarrows",
"incaucasianalbanian",
"inmiscellaneoussymbolsandpictographs",
"inoldturkic",
"insaurashtra",
- "incyrillicextendedc",
- "cwcf",
+ "incyrillicextendeda",
"idcontinue",
+ "intaixuanjingsymbols",
"intamil",
"inmultani",
"inlatinextendede",
@@ -40447,47 +43009,48 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"bali",
"blank",
"idst",
- "modifierletter",
"inlydian",
- "xsux",
+ "innewtailue",
"bengali",
"runr",
- "zl",
- "inunifiedcanadianaboriginalsyllabics",
"ll",
"indeseret",
"inancientgreeknumbers",
"idstart",
+ "zl",
"inmeeteimayekextensions",
"balinese",
- "innewtailue",
+ "incyrillicextendedc",
"inspacingmodifierletters",
"inearlydynasticcuneiform",
"plrd",
"canadianaboriginal",
- "zinh",
"sind",
- "xidstart",
-#endif /* USE_UNICODE_PROPERTIES */
- "xdigit",
-#ifndef USE_UNICODE_PROPERTIES
- "upper",
- "ascii",
-#else /* USE_UNICODE_PROPERTIES */
"inlatinextendedc",
+ "uideo",
"incountingrodnumerals",
+ "zinh",
+ "dia",
+ "di",
"inkhudawadi",
"inhanifirohingya",
+ "diak",
"gong",
"ingrantha",
"bidic",
- "variationselector",
+ "xidstart",
+#endif /* USE_UNICODE_PROPERTIES */
+ "xdigit",
+#ifndef USE_UNICODE_PROPERTIES
+ "upper",
+ "ascii",
+#else /* USE_UNICODE_PROPERTIES */
"mong",
"cased",
- "uideo",
"inhiragana",
"sinhala",
"adlm",
+ "xsux",
"glagolitic",
"sterm",
"bamu",
@@ -40495,6 +43058,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inosage",
"gunjalagondi",
"phoenician",
+ "inolduyghur",
"multani",
"kaithi",
"joincontrol",
@@ -40502,6 +43066,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"ingeneralpunctuation",
"inmahajani",
"incyrillicsupplement",
+ "lowercaseletter",
"marchen",
"graphemelink",
"ingeorgian",
@@ -40510,18 +43075,20 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inogham",
"cher",
"chakma",
+ "inkaktoviknumerals",
"emoji",
"insiddham",
"cherokee",
"khar",
"inmongolian",
+ "innagmundari",
"incherokeesupplement",
"manichaean",
"inolchiki",
- "dogra",
- "lowercaseletter",
"inkhitansmallscript",
"quotationmark",
+ "vithkuqi",
+ "variationselector",
"adlam",
"inethiopic",
"graphemebase",
@@ -40531,40 +43098,55 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"age=10.0",
"age=12.0",
"age=13.0",
+ "age=1.1",
#endif /* USE_UNICODE_AGE_PROPERTIES */
"casedletter",
"ingurmukhi",
- "incjkunifiedideographsextensiona",
- "inunifiedcanadianaboriginalsyllabicsextended",
- "lu",
#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=1.1",
- "age=9.0",
"age=2.1",
#endif /* USE_UNICODE_AGE_PROPERTIES */
- "intamilsupplement",
+ "incjkunifiedideographsextensiona",
#ifdef USE_UNICODE_AGE_PROPERTIES
"age=2.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "lu",
+#ifdef USE_UNICODE_AGE_PROPERTIES
"age=3.1",
- "age=8.0",
+ "age=9.0",
"age=3.0",
"age=3.2",
+ "age=8.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "intamilsupplement",
+#ifdef USE_UNICODE_AGE_PROPERTIES
"age=6.1",
- "age=7.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "unknown",
+#ifdef USE_UNICODE_AGE_PROPERTIES
"age=6.0",
"age=6.2",
+ "age=15.0",
+ "age=7.0",
+ "age=6.3",
#endif /* USE_UNICODE_AGE_PROPERTIES */
- "dogr",
+ "cwt",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=14.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "unassigned",
#ifdef USE_UNICODE_AGE_PROPERTIES
"age=5.1",
- "age=6.3",
"age=5.0",
"age=5.2",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "diacritic",
+#ifdef USE_UNICODE_AGE_PROPERTIES
"age=4.1",
- "age=4.0",
#endif /* USE_UNICODE_AGE_PROPERTIES */
"ahom",
- "phnx",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=4.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
"incjkunifiedideographsextensione",
"khmr",
"insinhala",
@@ -40573,69 +43155,65 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"guru",
"sundanese",
"punct",
- "cwt",
- "unassigned",
"paucinhau",
"gurmukhi",
"chorasmian",
"logicalorderexception",
"khmer",
"limbu",
- "unknown",
"chrs",
"oriya",
"inscriptionalpahlavi",
+ "incyrillicextendedd",
"incjkunifiedideographsextensionc",
#endif /* USE_UNICODE_PROPERTIES */
"cntrl",
#ifndef USE_UNICODE_PROPERTIES
"space",
#else /* USE_UNICODE_PROPERTIES */
- "incjkunifiedideographsextensionf",
"inlatinextendedadditional",
- "ahex",
"insorasompeng",
"radical",
"emojimodifier",
"kharoshthi",
- "dash",
"n",
"math",
"goth",
+ "phnx",
"anatolianhieroglyphs",
"inenclosedalphanumerics",
"nandinagari",
"no",
+ "intangsa",
"nko",
"nkoo",
"ingreekandcoptic",
"p",
"grantha",
- "xpeo",
+ "decimalnumber",
"incjkunifiedideographs",
- "zanb",
"intirhuta",
"inhatran",
"linb",
"mult",
"saurashtra",
"kthi",
+ "zanb",
"inbhaiksuki",
"innabataean",
"inphoenician",
+ "xpeo",
"inkanbun",
"inmeroitichieroglyphs",
+ "ahex",
"enclosingmark",
"sd",
"inelbasan",
"inenclosedideographicsupplement",
"sidd",
- "hani",
"linearb",
- "han",
- "intifinagh",
+ "cpmn",
"inenclosedalphanumericsupplement",
- "hano",
"bidicontrol",
"inphaistosdisc",
"limb",
@@ -40643,21 +43221,22 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"lepc",
"braille",
"regionalindicator",
- "inkhojki",
+ "inlowsurrogates",
"brah",
- "hanunoo",
"inoldhungarian",
- "hira",
"beng",
"emojimodifierbase",
"inarabic",
"osage",
"inherited",
+ "incyprominoan",
"glag",
+ "medf",
"osma",
"indogra",
- "inlowsurrogates",
"arab",
+ "medefaidrin",
+ "inshorthandformatcontrols",
"phli",
"inimperialaramaic",
"emod",
@@ -40665,14 +43244,13 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inanatolianhieroglyphs",
"punctuation",
"graphemeextend",
+ "cwl",
+ "vith",
"ingeometricshapes",
"emojicomponent",
- "softdotted",
- "takri",
- "inyezidi",
+ "dsrt",
"coptic",
"inkayahli",
- "invai",
"inoriya",
"inarabicpresentationformsa",
"inbasiclatin",
@@ -40680,21 +43258,20 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"wara",
"sinh",
"sund",
- "cwl",
"shavian",
"insundanesesupplement",
- "takr",
+ "inyezidi",
"bhks",
"bhaiksuki",
- "taile",
"inhanunoo",
"intangut",
- "inethiopicextendeda",
"sogdian",
"inlatinextendedd",
"sogo",
"insinhalaarchaicnumbers",
"ideographic",
+ "ugar",
+ "deseret",
"odi",
"copt",
"imperialaramaic",
@@ -40708,232 +43285,230 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"lycian",
"inbatak",
"cprt",
- "ugar",
+ "inunifiedcanadianaboriginalsyllabicsextendeda",
"mymr",
"myanmar",
- "deva",
"intibetan",
"intags",
"asciihexdigit",
- "devanagari",
"sentenceterminal",
- "defaultignorablecodepoint",
- "digit",
- "term",
"nand",
- "hatran",
"inblockelements",
"inornamentaldingbats",
+ "inethiopicextendeda",
"innumberforms",
+ "cwcf",
"oidc",
"bopo",
- "hex",
- "ext",
- "hatr",
+ "cuneiform",
"caseignorable",
"inoldpersian",
- "inshavian",
- "inbyzantinemusicalsymbols",
-#endif /* USE_UNICODE_PROPERTIES */
- "xposixpunct",
-#ifndef USE_UNICODE_PROPERTIES
- "lower",
-#else /* USE_UNICODE_PROPERTIES */
+ "cwu",
"inelymaic",
"insoyombo",
"ingeometricshapesextended",
"incjkcompatibility",
"inmyanmarextendedb",
"innushu",
+ "inkanaextendedb",
"olck",
+ "inbyzantinemusicalsymbols",
"olchiki",
- "cwu",
"inkatakanaphoneticextensions",
"incoptic",
"oids",
"inarabicextendeda",
+ "modifierletter",
"incjksymbolsandpunctuation",
"olower",
"bopomofo",
"inlisu",
"inoldpermic",
"innoblock",
- "extpict",
+ "ext",
+ "inunifiedcanadianaboriginalsyllabics",
+ "takri",
"inbraillepatterns",
+ "invai",
"alpha",
"inbalinese",
"sorasompeng",
"closepunctuation",
- "taiviet",
- "inphoneticextensions",
+ "hani",
"inmayannumerals",
+ "han",
"inmiscellaneousmathematicalsymbolsb",
"inlepcha",
"patsyn",
"inlisusupplement",
"insyriacsupplement",
+ "hano",
+ "newa",
"spacingmark",
"inpalmyrene",
+ "takr",
+#endif /* USE_UNICODE_PROPERTIES */
+ "xposixpunct",
+#ifndef USE_UNICODE_PROPERTIES
+ "lower",
+#else /* USE_UNICODE_PROPERTIES */
+ "inkhojki",
+ "taile",
"assigned",
- "extender",
- "newa",
+ "hanunoo",
+ "hira",
+ "inarabicextendedc",
+ "newtailue",
"space",
"intelugu",
"lydi",
"idsb",
+ "extpict",
"lydian",
"inethiopicsupplement",
"sarb",
- "zanabazarsquare",
- "newtailue",
- "indevanagari",
- "avestan",
+ "ugaritic",
"inyiradicals",
+ "inphoneticextensions",
"sharada",
- "inphoneticextensionssupplement",
- "deprecated",
+ "zanabazarsquare",
"bugi",
"word",
- "java",
+ "term",
"separator",
"ingeorgiansupplement",
"sogd",
- "ugaritic",
- "inethiopicextended",
+ "extender",
"shrd",
#endif /* USE_UNICODE_PROPERTIES */
"graph",
-#ifndef USE_UNICODE_PROPERTIES
- "digit",
- "blank"
-#else /* USE_UNICODE_PROPERTIES */
- "gujr",
- "tale",
- "gujarati",
+#ifdef USE_UNICODE_PROPERTIES
+ "tnsa",
+ "tangsa",
"phag",
- "terminalpunctuation",
+ "dogra",
"inhanguljamo",
+ "inshavian",
"siddham",
- "ingeorgianextended",
+ "cf",
+ "inunifiedcanadianaboriginalsyllabicsextended",
"buginese",
"inmongoliansupplement",
"cyrl",
"inhanguljamoextendeda",
- "javanese",
- "taml",
+ "pf",
"number",
- "incyrillicextendedb",
+ "inphoneticextensionssupplement",
+ "dogr",
"mlym",
"incopticepactnumbers",
"malayalam",
"inbamum",
"nd",
"insuttonsignwriting",
- "invariationselectors",
- "inverticalforms",
- "avst",
+ "inethiopicextended",
+ "shaw",
"palmyrene",
"soyo",
- "intaiviet",
+ "incjkunifiedideographsextensionh",
+ "sgnw",
+ "toto",
"caucasianalbanian",
"inmathematicalalphanumericsymbols",
"incjkunifiedideographsextensiong",
+ "hatran",
+ "taiviet",
"meroitichieroglyphs",
- "shaw",
- "invedicextensions",
+ "ingeorgianextended",
+ "incjkunifiedideographsextensionf",
"oldpersian",
"induployan",
- "sgnw",
+ "incyrillicextendedb",
+ "dash",
+ "hatr",
"innyiakengpuachuehmong",
"incombiningdiacriticalmarks",
- "invariationselectorssupplement",
"nl",
"incombiningdiacriticalmarksforsymbols",
+ "khudawadi",
"incjkradicalssupplement",
"inglagolitic",
"orkh",
"syrc",
- "khudawadi",
"surrogate",
- "extendedpictographic",
+ "indevanagari",
+ "avestan",
"oldpermic",
"ethi",
"ogam",
"rohg",
"idstrinaryoperator",
+ "java",
"inphagspa",
"lepcha",
- "titlecaseletter",
+ "indevanagariextendeda",
+ "intifinagh",
"intagalog",
"incombiningdiacriticalmarkssupplement",
- "inmeroiticcursive",
+ "tale",
"inbrahmi",
+ "terminalpunctuation",
"insymbolsandpictographsextendeda",
"syriac",
- "modifiersymbol",
"inbengali",
- "inhalfwidthandfullwidthforms",
+ "nagm",
+ "extendedpictographic",
"buhd",
- "mahj",
+ "javanese",
+ "taml",
"inbuginese",
"inlatin1supplement",
"ingothic",
- "mahajani",
- "hang",
+ "invariationselectors",
+ "hex",
+ "inverticalforms",
"ebase",
- "insmallformvariants",
"incurrencysymbols",
- "indevanagariextended",
- "divesakuru",
- "ingujarati",
+ "avst",
"osge",
"incombiningdiacriticalmarksextended",
+ "intaiviet",
"spaceseparator",
- "ingunjalagondi",
- "dupl",
- "hiragana",
- "tirhuta",
- "inrejang",
- "dashpunctuation",
+ "softdotted",
"nchar",
- "khoj",
+ "invedicextensions",
"inlimbu",
"olditalic",
- "hmng",
+ "gujr",
"mathsymbol",
"incjkunifiedideographsextensionb",
+ "gujarati",
"phagspa",
- "thaa",
+ "invariationselectorssupplement",
"currencysymbol",
- "thai",
- "inenclosedcjklettersandmonths",
- "thaana",
- "hanifirohingya",
"inlinearbsyllabary",
- "tang",
- "tagbanwa",
"wancho",
- "tamil",
- "zp",
- "tirh",
"inpaucinhau",
- "talu",
"other",
"otheridcontinue",
"sylo",
+ "zp",
"inaegeannumbers",
"warangciti",
"othernumber",
- "taitham",
+#endif /* USE_UNICODE_PROPERTIES */
+ "digit",
+#ifndef USE_UNICODE_PROPERTIES
+ "blank"
+#else /* USE_UNICODE_PROPERTIES */
"nonspacingmark",
- "telu",
+ "titlecaseletter",
+ "inmeroiticcursive",
"wcho",
"graphemeclusterbreak=spacingmark",
"inletterlikesymbols",
- "tifinagh",
"inottomansiyaqnumbers",
"intagbanwa",
- "tfng",
"cyrillic",
"oalpha",
"graphemeclusterbreak=cr",
@@ -40944,18 +43519,15 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"otheralphabetic",
"noncharactercodepoint",
"oldhungarian",
- "rjng",
- "changeswhencasefolded",
"insymbolsforlegacycomputing",
- "tangut",
- "dep",
+ "insmallformvariants",
"inhangulsyllables",
"emojipresentation",
"epres",
"inbassavah",
- "graphemeclusterbreak=lf",
+ "indevanagariextended",
"inbuhid",
- "hmnp",
+ "tirhuta",
"inpsalterpahlavi",
"whitespace",
"finalpunctuation",
@@ -40965,31 +43537,53 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"buhid",
"paragraphseparator",
"inalphabeticpresentationforms",
+ "inlatinextendedg",
"elba",
"changeswhentitlecased",
"incombininghalfmarks",
"intangutcomponents",
- "hebr",
+ "thaa",
+ "thai",
"oldturkic",
+ "thaana",
+ "inlatinextendedf",
+ "ougr",
+ "tang",
"inarabicmathematicalalphabeticsymbols",
+ "tagbanwa",
+ "tamil",
"khitansmallscript",
+ "mahj",
+ "mahajani",
+ "hang",
+ "tirh",
"sylotinagri",
- "hexdigit",
- "inprivateusearea",
+ "talu",
+ "nagmundari",
+ "deva",
+ "ingujarati",
+ "deprecated",
"inarabicpresentationformsb",
+ "devanagari",
+ "ingunjalagondi",
"graphemeclusterbreak=t",
"graphemeclusterbreak=lvt",
+ "taitham",
"nbat",
- "hangul",
+ "telu",
+ "hiragana",
"nabataean",
+ "inrejang",
"intangutsupplement",
+ "khoj",
+ "hmng",
+ "cyprominoan",
+ "inhebrew",
"inmathematicaloperators",
"inarabicsupplement",
- "injavanese",
- "hung",
- "ogrext",
- "inhebrew",
+ "inenclosedcjklettersandmonths",
"changeswhenlowercased",
+ "tangut",
"elbasan",
"osmanya",
"insuperscriptsandsubscripts",
@@ -40997,85 +43591,110 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"graphemeclusterbreak=prepend",
"nshu",
"otherlowercase",
- "hluw",
+ "inethiopicextendedb",
"otherletter",
"kayahli",
"inplayingcards",
"elym",
"graphemeclusterbreak=l",
"graphemeclusterbreak=control",
+ "ogrext",
"elymaic",
"changeswhenuppercased",
"inalchemicalsymbols",
"oldsogdian",
- "bassavah",
"otheridstart",
"insupplementalarrowsa",
+ "invithkuqi",
"symbol",
- "inmahjongtiles",
+ "inarabicextendedb",
"cypriot",
"any",
"otheruppercase",
- "indivesakuru",
- "tibt",
- "tibetan",
+ "rjng",
"wspace",
"inindicsiyaqnumbers",
+ "inprivateusearea",
"othersymbol",
"oupper",
+ "signwriting",
"nushu",
- "inyijinghexagramsymbols",
+ "hmnp",
+ "upper",
"insupplementalarrowsc",
- "signwriting",
"omath",
- "upper",
+ "modifiersymbol",
+ "hebr",
+ "inhalfwidthandfullwidthforms",
"insupplementalmathematicaloperators",
"inpahawhhmong",
"alphabetic",
- "tavt",
- "ogham",
"uppercase",
+ "dupl",
+ "ogham",
+ "dashpunctuation",
+ "hangul",
"inhanguljamoextendedb",
+ "bassavah",
"aghb",
+ "hung",
+ "hexdigit",
"incypriotsyllabary",
+ "indivesakuru",
+ "tibt",
"inlatinextendedb",
+ "hluw",
+ "tibetan",
"inyisyllables",
"oldnortharabian",
- "duployan",
+ "defaultignorablecodepoint",
"inhighprivateusesurrogates",
"soyombo",
"otherdefaultignorablecodepoint",
- "othermath",
- "inbopomofoextended",
"pahawhhmong",
"unifiedideograph",
- "insupplementalpunctuation",
+ "othermath",
+ "changeswhencasefolded",
+ "inmahjongtiles",
+ "dep",
+ "divesakuru",
+ "graphemeclusterbreak=lf",
"uppercaseletter",
+ "insupplementalpunctuation",
"ethiopic",
+ "inyijinghexagramsymbols",
"ecomp",
"inglagoliticsupplement",
- "rejang",
+ "inbopomofoextended",
+ "injavanese",
"otherpunctuation",
- "tagb",
+ "tifinagh",
+ "tfng",
+ "hanifirohingya",
+ "tavt",
"inboxdrawing",
- "tglg",
- "graphemeclusterbreak=zwj",
- "hebrew",
- "tagalog",
"oldsoutharabian",
"inegyptianhieroglyphs",
"inegyptianhieroglyphformatcontrols",
- "graphemeclusterbreak=v",
- "graphemeclusterbreak=lv",
- "telugu",
- "hyphen",
+ "tagb",
+ "rejang",
+ "tglg",
+ "tagalog",
"othergraphemeextend",
"insupplementaryprivateuseareaa",
"inhighsurrogates",
+ "hebrew",
+ "duployan",
+ "graphemeclusterbreak=v",
+ "graphemeclusterbreak=lv",
"insupplementalarrowsb",
+ "graphemeclusterbreak=zwj",
+ "telugu",
"zyyy",
+ "olduyghur",
"inhangulcompatibilityjamo",
"openpunctuation",
+ "hyphen",
"insupplementalsymbolsandpictographs",
"egyp",
"nyiakengpuachuehmong",
@@ -41089,31 +43708,13 @@ uniname2ctype_p (register const char *str, register size_t len)
{
static const struct uniname2ctype_struct wordlist[] =
{
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#ifndef USE_UNICODE_PROPERTIES
- {uniname2ctype_offset(str6), 12},
- {uniname2ctype_offset(str7), 7},
- {uniname2ctype_offset(str8), 15},
- {uniname2ctype_offset(str9), 1},
- {uniname2ctype_offset(str10), 13},
- {uniname2ctype_offset(str11), 11},
- {uniname2ctype_offset(str12), 10},
- {uniname2ctype_offset(str13), 14},
- {uniname2ctype_offset(str14), 3},
- {uniname2ctype_offset(str15), 9},
- {uniname2ctype_offset(str16), 8},
- {uniname2ctype_offset(str17), 6},
- {uniname2ctype_offset(str18), 5},
- {uniname2ctype_offset(str19), 4},
- {uniname2ctype_offset(str20), 2}
-#else /* USE_UNICODE_PROPERTIES */
- {uniname2ctype_offset(str6), 52},
+#ifdef USE_UNICODE_PROPERTIES
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str11), 111},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str12), 111},
+ {uniname2ctype_offset(str17), 111},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str17), 271},
- {uniname2ctype_offset(str18), 111},
- {-1}, {-1}, {-1},
{uniname2ctype_offset(str22), 152},
{-1}, {-1},
{uniname2ctype_offset(str25), 184},
@@ -41128,16 +43729,16 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str47), 61},
{uniname2ctype_offset(str48), 95},
{uniname2ctype_offset(str49), 95},
- {-1},
- {uniname2ctype_offset(str51), 230},
- {uniname2ctype_offset(str52), 336},
+ {-1}, {-1},
+ {uniname2ctype_offset(str52), 346},
{-1}, {-1},
{uniname2ctype_offset(str55), 21},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str64), 44},
{-1},
- {uniname2ctype_offset(str66), 324},
- {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str66), 333},
+ {uniname2ctype_offset(str67), 52},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str71), 181},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str75), 22},
@@ -41145,15 +43746,17 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str83), 184},
{-1}, {-1},
{uniname2ctype_offset(str86), 31},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str90), 230},
+ {-1},
{uniname2ctype_offset(str92), 45},
{-1},
{uniname2ctype_offset(str94), 33},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str100), 149},
- {uniname2ctype_offset(str101), 501},
+ {uniname2ctype_offset(str101), 513},
{uniname2ctype_offset(str102), 108},
- {uniname2ctype_offset(str103), 256},
+ {uniname2ctype_offset(str103), 263},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str107), 31},
{uniname2ctype_offset(str108), 77},
@@ -41167,37 +43770,32 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str118), 77},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str122), 212},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str126), 243},
- {uniname2ctype_offset(str127), 71},
- {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str129), 187},
{uniname2ctype_offset(str130), 42},
{uniname2ctype_offset(str131), 172},
{-1}, {-1},
- {uniname2ctype_offset(str134), 487},
- {uniname2ctype_offset(str135), 228},
- {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str134), 497},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str139), 170},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str145), 504},
- {uniname2ctype_offset(str146), 557},
+ {uniname2ctype_offset(str145), 516},
+ {uniname2ctype_offset(str146), 575},
{-1},
- {uniname2ctype_offset(str148), 561},
- {uniname2ctype_offset(str149), 521},
+ {uniname2ctype_offset(str148), 580},
+ {uniname2ctype_offset(str149), 535},
{-1},
{uniname2ctype_offset(str151), 18},
{uniname2ctype_offset(str152), 169},
{uniname2ctype_offset(str153), 160},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str161), 318},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str173), 144},
- {uniname2ctype_offset(str174), 144},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str158), 278},
{-1}, {-1},
- {uniname2ctype_offset(str177), 342},
- {uniname2ctype_offset(str178), 547},
+ {uniname2ctype_offset(str161), 327},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str177), 352},
+ {uniname2ctype_offset(str178), 563},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str183), 75},
{-1}, {-1},
@@ -41206,19 +43804,19 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str190), 208},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str203), 350},
- {uniname2ctype_offset(str204), 478},
+ {uniname2ctype_offset(str203), 360},
+ {uniname2ctype_offset(str204), 488},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str210), 562},
+ {uniname2ctype_offset(str210), 581},
{-1},
- {uniname2ctype_offset(str212), 355},
+ {uniname2ctype_offset(str212), 365},
{uniname2ctype_offset(str213), 115},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str218), 535},
+ {uniname2ctype_offset(str218), 549},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str226), 171},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str230), 516},
+ {uniname2ctype_offset(str230), 530},
{uniname2ctype_offset(str231), 31},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str236), 25},
@@ -41230,321 +43828,312 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1},
{uniname2ctype_offset(str253), 102},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str260), 551},
+ {uniname2ctype_offset(str260), 568},
{-1}, {-1},
{uniname2ctype_offset(str263), 161},
{-1},
{uniname2ctype_offset(str265), 19},
{-1},
{uniname2ctype_offset(str267), 79},
- {uniname2ctype_offset(str268), 347},
+ {uniname2ctype_offset(str268), 357},
{-1},
- {uniname2ctype_offset(str270), 263},
- {-1}, {-1},
- {uniname2ctype_offset(str273), 20},
- {uniname2ctype_offset(str274), 550},
- {uniname2ctype_offset(str275), 505},
+ {uniname2ctype_offset(str270), 270},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str274), 567},
+ {uniname2ctype_offset(str275), 517},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str281), 312},
+ {uniname2ctype_offset(str281), 321},
{uniname2ctype_offset(str282), 40},
{uniname2ctype_offset(str283), 79},
{-1},
- {uniname2ctype_offset(str285), 523},
+ {uniname2ctype_offset(str285), 537},
+ {-1},
+ {uniname2ctype_offset(str287), 144},
+ {uniname2ctype_offset(str288), 144},
+ {uniname2ctype_offset(str289), 560},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str289), 544},
- {uniname2ctype_offset(str290), 43},
- {-1}, {-1},
{uniname2ctype_offset(str293), 218},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str297), 212},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str301), 385},
- {uniname2ctype_offset(str302), 243},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str311), 316},
+ {uniname2ctype_offset(str301), 395},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str311), 325},
{-1},
- {uniname2ctype_offset(str313), 446},
+ {uniname2ctype_offset(str313), 456},
{-1},
- {uniname2ctype_offset(str315), 236},
+ {uniname2ctype_offset(str315), 243},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str320), 264},
+ {uniname2ctype_offset(str320), 271},
{-1},
{uniname2ctype_offset(str322), 129},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str328), 325},
+ {uniname2ctype_offset(str328), 334},
{-1}, {-1},
{uniname2ctype_offset(str331), 76},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str335), 545},
+ {uniname2ctype_offset(str335), 561},
{-1}, {-1},
- {uniname2ctype_offset(str338), 323},
+ {uniname2ctype_offset(str338), 332},
{-1},
{uniname2ctype_offset(str340), 76},
- {uniname2ctype_offset(str341), 540},
- {uniname2ctype_offset(str342), 339},
+ {-1},
+ {uniname2ctype_offset(str342), 349},
{-1}, {-1},
{uniname2ctype_offset(str345), 53},
- {uniname2ctype_offset(str346), 263},
+ {uniname2ctype_offset(str346), 270},
{-1},
- {uniname2ctype_offset(str348), 416},
+ {uniname2ctype_offset(str348), 426},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str352), 519},
+ {uniname2ctype_offset(str352), 533},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str362), 163},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str366), 44},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str373), 160},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str381), 554},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str386), 371},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str386), 361},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str399), 321},
+ {uniname2ctype_offset(str399), 330},
{-1},
- {uniname2ctype_offset(str401), 534},
+ {uniname2ctype_offset(str401), 548},
{-1}, {-1},
{uniname2ctype_offset(str404), 81},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str409), 55},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str418), 108},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str426), 163},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str430), 55},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
{uniname2ctype_offset(str442), 14},
{-1}, {-1},
{uniname2ctype_offset(str445), 23},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str460), 36},
- {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str462), 46},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str468), 169},
{-1},
{uniname2ctype_offset(str470), 22},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str475), 512},
+ {uniname2ctype_offset(str475), 524},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str480), 447},
+ {uniname2ctype_offset(str480), 457},
{uniname2ctype_offset(str481), 188},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str486), 466},
+ {uniname2ctype_offset(str486), 476},
{-1},
- {uniname2ctype_offset(str488), 568},
- {-1}, {-1},
- {uniname2ctype_offset(str491), 460},
+ {uniname2ctype_offset(str488), 588},
{-1}, {-1},
- {uniname2ctype_offset(str494), 230},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str491), 470},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str500), 127},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str504), 187},
- {uniname2ctype_offset(str505), 242},
+ {uniname2ctype_offset(str505), 249},
{uniname2ctype_offset(str506), 24},
{-1}, {-1},
{uniname2ctype_offset(str509), 24},
{-1},
- {uniname2ctype_offset(str511), 453},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str519), 70},
- {uniname2ctype_offset(str520), 413},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str511), 463},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str520), 423},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str533), 230},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str538), 91},
{-1}, {-1},
- {uniname2ctype_offset(str541), 539},
+ {uniname2ctype_offset(str541), 553},
{-1},
{uniname2ctype_offset(str543), 91},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str556), 532},
+ {uniname2ctype_offset(str556), 546},
{-1},
- {uniname2ctype_offset(str558), 340},
- {-1},
- {uniname2ctype_offset(str560), 503},
- {-1},
- {uniname2ctype_offset(str562), 70},
- {-1}, {-1},
- {uniname2ctype_offset(str565), 597},
+ {uniname2ctype_offset(str558), 350},
+ {uniname2ctype_offset(str559), 70},
+ {uniname2ctype_offset(str560), 515},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str565), 624},
{uniname2ctype_offset(str566), 37},
{-1},
{uniname2ctype_offset(str568), 113},
- {uniname2ctype_offset(str569), 260},
- {-1}, {-1},
- {uniname2ctype_offset(str572), 491},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str572), 502},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str577), 584},
+ {uniname2ctype_offset(str577), 611},
{-1},
{uniname2ctype_offset(str579), 106},
{-1}, {-1},
- {uniname2ctype_offset(str582), 396},
- {uniname2ctype_offset(str583), 470},
+ {uniname2ctype_offset(str582), 406},
+ {uniname2ctype_offset(str583), 480},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str590), 74},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str594), 168},
{-1},
- {uniname2ctype_offset(str596), 595},
+ {uniname2ctype_offset(str596), 622},
{uniname2ctype_offset(str597), 146},
{-1}, {-1},
- {uniname2ctype_offset(str600), 480},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str604), 560},
- {uniname2ctype_offset(str605), 602},
+ {uniname2ctype_offset(str600), 490},
+ {-1},
+ {uniname2ctype_offset(str602), 70},
+ {-1},
+ {uniname2ctype_offset(str604), 579},
+ {uniname2ctype_offset(str605), 629},
{-1}, {-1},
- {uniname2ctype_offset(str608), 610},
+ {uniname2ctype_offset(str608), 637},
{uniname2ctype_offset(str609), 229},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str613), 219},
- {uniname2ctype_offset(str614), 585},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str614), 612},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str624), 195},
- {uniname2ctype_offset(str625), 437},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str629), 219},
+ {uniname2ctype_offset(str625), 447},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str630), 29},
- {uniname2ctype_offset(str631), 262},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str638), 572},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str636), 543},
+ {-1}, {-1},
{uniname2ctype_offset(str639), 49},
{-1}, {-1},
{uniname2ctype_offset(str642), 19},
- {-1}, {-1},
- {uniname2ctype_offset(str645), 475},
+ {uniname2ctype_offset(str643), 564},
+ {-1},
+ {uniname2ctype_offset(str645), 485},
{-1},
{uniname2ctype_offset(str647), 192},
{-1}, {-1},
- {uniname2ctype_offset(str650), 477},
- {-1},
- {uniname2ctype_offset(str652), 69},
- {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str650), 487},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str657), 51},
{-1}, {-1},
- {uniname2ctype_offset(str660), 261},
+ {uniname2ctype_offset(str660), 268},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str672), 326},
+ {uniname2ctype_offset(str672), 335},
{-1}, {-1},
{uniname2ctype_offset(str675), 68},
{-1}, {-1},
{uniname2ctype_offset(str678), 171},
+ {uniname2ctype_offset(str679), 607},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str682), 529},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str688), 114},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str683), 267},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str692), 69},
+ {-1}, {-1},
+ {uniname2ctype_offset(str695), 551},
{uniname2ctype_offset(str696), 175},
- {uniname2ctype_offset(str697), 389},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str703), 514},
+ {uniname2ctype_offset(str697), 399},
+ {-1}, {-1},
+ {uniname2ctype_offset(str700), 236},
+ {-1}, {-1},
+ {uniname2ctype_offset(str703), 527},
{-1},
- {uniname2ctype_offset(str705), 337},
+ {uniname2ctype_offset(str705), 347},
{-1},
{uniname2ctype_offset(str707), 158},
- {uniname2ctype_offset(str708), 567},
+ {uniname2ctype_offset(str708), 587},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str713), 366},
+ {uniname2ctype_offset(str713), 376},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str720), 72},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str737), 7},
- {uniname2ctype_offset(str738), 363},
- {-1}, {-1},
- {uniname2ctype_offset(str741), 537},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str738), 373},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str742), 6},
{-1}, {-1},
- {uniname2ctype_offset(str753), 233},
+ {uniname2ctype_offset(str745), 269},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str753), 240},
{-1},
- {uniname2ctype_offset(str755), 502},
+ {uniname2ctype_offset(str755), 514},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str760), 421},
+ {uniname2ctype_offset(str760), 431},
{uniname2ctype_offset(str761), 167},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str765), 114},
- {uniname2ctype_offset(str766), 156},
{-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str766), 156},
+ {uniname2ctype_offset(str767), 608},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str771), 167},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str776), 261},
+ {uniname2ctype_offset(str776), 268},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str783), 156},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str787), 249},
- {uniname2ctype_offset(str788), 6},
- {-1}, {-1},
+ {uniname2ctype_offset(str787), 256},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str791), 193},
{-1}, {-1},
- {uniname2ctype_offset(str794), 569},
+ {uniname2ctype_offset(str794), 589},
{-1}, {-1},
{uniname2ctype_offset(str797), 50},
{-1},
- {uniname2ctype_offset(str799), 590},
+ {uniname2ctype_offset(str799), 617},
{-1}, {-1},
{uniname2ctype_offset(str802), 13},
+ {uniname2ctype_offset(str803), 593},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str809), 446},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str814), 493},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str806), 409},
- {-1}, {-1},
- {uniname2ctype_offset(str809), 436},
- {-1},
- {uniname2ctype_offset(str811), 577},
- {-1},
- {uniname2ctype_offset(str813), 583},
- {uniname2ctype_offset(str814), 483},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str818), 388},
+ {uniname2ctype_offset(str818), 398},
{-1}, {-1},
- {uniname2ctype_offset(str821), 472},
- {uniname2ctype_offset(str822), 574},
+ {uniname2ctype_offset(str821), 482},
+ {uniname2ctype_offset(str822), 595},
{uniname2ctype_offset(str823), 47},
{uniname2ctype_offset(str824), 112},
- {uniname2ctype_offset(str825), 434},
+ {uniname2ctype_offset(str825), 444},
{-1}, {-1},
- {uniname2ctype_offset(str828), 575},
+ {uniname2ctype_offset(str828), 596},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str838), 157},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str842), 58},
+ {-1}, {-1},
+ {uniname2ctype_offset(str845), 66},
+ {-1},
{uniname2ctype_offset(str847), 48},
{uniname2ctype_offset(str848), 178},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str855), 67},
{-1},
- {uniname2ctype_offset(str857), 310},
+ {uniname2ctype_offset(str857), 319},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str875), 359},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str882), 137},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str886), 394},
+ {uniname2ctype_offset(str875), 369},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str888), 58},
- {-1}, {-1},
- {uniname2ctype_offset(str891), 66},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str895), 402},
+ {uniname2ctype_offset(str886), 404},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str895), 412},
{-1}, {-1},
- {uniname2ctype_offset(str898), 490},
+ {uniname2ctype_offset(str898), 500},
{-1},
- {uniname2ctype_offset(str900), 594},
+ {uniname2ctype_offset(str900), 621},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str906), 509},
- {uniname2ctype_offset(str907), 439},
+ {uniname2ctype_offset(str906), 521},
+ {uniname2ctype_offset(str907), 449},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str918), 370},
- {-1},
- {uniname2ctype_offset(str920), 65},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str920), 419},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str924), 68},
+ {uniname2ctype_offset(str925), 599},
+ {uniname2ctype_offset(str926), 344},
{-1},
- {uniname2ctype_offset(str926), 334},
- {-1},
- {uniname2ctype_offset(str928), 526},
- {uniname2ctype_offset(str929), 451},
+ {uniname2ctype_offset(str928), 540},
+ {uniname2ctype_offset(str929), 461},
{uniname2ctype_offset(str930), 41},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -41553,199 +44142,226 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str961), 2},
{-1},
- {uniname2ctype_offset(str963), 250},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str972), 27},
+ {uniname2ctype_offset(str963), 257},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str974), 498},
+ {uniname2ctype_offset(str974), 510},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str991), 137},
{-1}, {-1},
+ {uniname2ctype_offset(str986), 370},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str994), 85},
{uniname2ctype_offset(str995), 104},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1003), 53},
- {-1},
- {uniname2ctype_offset(str1005), 348},
- {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1010), 26},
{-1}, {-1},
- {uniname2ctype_offset(str1013), 485},
+ {uniname2ctype_offset(str1013), 495},
{-1},
- {uniname2ctype_offset(str1015), 474},
+ {uniname2ctype_offset(str1015), 484},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1021), 67},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1025), 449},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1024), 53},
+ {uniname2ctype_offset(str1025), 459},
{-1}, {-1},
{uniname2ctype_offset(str1028), 136},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1032), 360},
+ {uniname2ctype_offset(str1032), 380},
{-1}, {-1},
- {uniname2ctype_offset(str1035), 313},
- {uniname2ctype_offset(str1036), 552},
+ {uniname2ctype_offset(str1035), 322},
+ {uniname2ctype_offset(str1036), 569},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1049), 173},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1067), 102},
- {uniname2ctype_offset(str1068), 115},
- {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1072), 197},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1081), 414},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1085), 259},
{-1},
- {uniname2ctype_offset(str1074), 69},
- {uniname2ctype_offset(str1075), 11},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1081), 404},
+ {uniname2ctype_offset(str1087), 600},
+ {-1},
+ {uniname2ctype_offset(str1089), 115},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1087), 578},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1097), 527},
+ {uniname2ctype_offset(str1095), 250},
+ {uniname2ctype_offset(str1096), 71},
+ {uniname2ctype_offset(str1097), 541},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1102), 511},
- {-1}, {-1},
+ {uniname2ctype_offset(str1102), 523},
+ {-1},
+ {uniname2ctype_offset(str1104), 228},
{uniname2ctype_offset(str1105), 217},
{-1},
- {uniname2ctype_offset(str1107), 528},
+ {uniname2ctype_offset(str1107), 542},
{-1},
- {uniname2ctype_offset(str1109), 232},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1116), 260},
- {-1}, {-1},
+ {uniname2ctype_offset(str1109), 239},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1114), 69},
+ {uniname2ctype_offset(str1115), 11},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str1119), 106},
{uniname2ctype_offset(str1120), 60},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str1131), 252},
- {-1}, {-1},
- {uniname2ctype_offset(str1134), 415},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1134), 425},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1140), 93},
{-1},
{uniname2ctype_offset(str1142), 206},
- {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1145), 137},
{uniname2ctype_offset(str1146), 131},
- {uniname2ctype_offset(str1147), 259},
+ {uniname2ctype_offset(str1147), 266},
{-1},
{uniname2ctype_offset(str1149), 158},
{uniname2ctype_offset(str1150), 98},
- {uniname2ctype_offset(str1151), 488},
+ {uniname2ctype_offset(str1151), 498},
{uniname2ctype_offset(str1152), 217},
{uniname2ctype_offset(str1153), 138},
- {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1156), 529},
{uniname2ctype_offset(str1157), 203},
{uniname2ctype_offset(str1158), 166},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1164), 233},
+ {uniname2ctype_offset(str1164), 240},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1168), 104},
{-1},
- {uniname2ctype_offset(str1170), 379},
- {uniname2ctype_offset(str1171), 522},
+ {uniname2ctype_offset(str1170), 389},
+ {uniname2ctype_offset(str1171), 536},
{-1}, {-1},
- {uniname2ctype_offset(str1174), 317},
- {-1},
+ {uniname2ctype_offset(str1174), 326},
+ {uniname2ctype_offset(str1175), 26},
{uniname2ctype_offset(str1176), 208},
{uniname2ctype_offset(str1177), 74},
- {uniname2ctype_offset(str1178), 343},
+ {uniname2ctype_offset(str1178), 353},
{-1},
{uniname2ctype_offset(str1180), 183},
{uniname2ctype_offset(str1181), 151},
- {uniname2ctype_offset(str1182), 349},
+ {uniname2ctype_offset(str1182), 359},
{uniname2ctype_offset(str1183), 101},
{-1},
{uniname2ctype_offset(str1185), 170},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1190), 265},
- {uniname2ctype_offset(str1191), 531},
+ {uniname2ctype_offset(str1186), 597},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1190), 272},
+ {uniname2ctype_offset(str1191), 545},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1197), 101},
{uniname2ctype_offset(str1198), 135},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1203), 356},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1207), 452},
+ {uniname2ctype_offset(str1203), 366},
+ {uniname2ctype_offset(str1204), 609},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1207), 462},
{-1},
{uniname2ctype_offset(str1209), 186},
{-1}, {-1},
- {uniname2ctype_offset(str1212), 369},
- {uniname2ctype_offset(str1213), 216},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1221), 26},
+ {uniname2ctype_offset(str1212), 379},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str1223), 565},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1227), 236},
+ {uniname2ctype_offset(str1223), 584},
{-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1227), 243},
+ {-1},
+ {uniname2ctype_offset(str1229), 235},
+ {uniname2ctype_offset(str1230), 267},
{uniname2ctype_offset(str1231), 206},
- {uniname2ctype_offset(str1232), 345},
+ {uniname2ctype_offset(str1232), 355},
{uniname2ctype_offset(str1233), 73},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1234), 291},
- {uniname2ctype_offset(str1235), 293},
- {uniname2ctype_offset(str1236), 290},
- {uniname2ctype_offset(str1237), 292},
- {-1}, {-1},
- {uniname2ctype_offset(str1240), 294},
- {-1}, {-1},
+ {uniname2ctype_offset(str1234), 298},
+ {uniname2ctype_offset(str1235), 300},
+ {uniname2ctype_offset(str1236), 297},
+ {uniname2ctype_offset(str1237), 299},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1241), 301},
+ {uniname2ctype_offset(str1242), 279},
#endif /* USE_UNICODE_AGE_PROPERTIES */
{uniname2ctype_offset(str1243), 25},
- {uniname2ctype_offset(str1244), 331},
+ {uniname2ctype_offset(str1244), 341},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1245), 281},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1246), 435},
+#ifndef USE_UNICODE_AGE_PROPERTIES
{-1},
- {uniname2ctype_offset(str1246), 425},
- {uniname2ctype_offset(str1247), 357},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1247), 280},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
{uniname2ctype_offset(str1248), 30},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1}, {-1}, {-1}, {-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1249), 283},
+ {uniname2ctype_offset(str1250), 296},
+ {uniname2ctype_offset(str1251), 282},
+ {uniname2ctype_offset(str1252), 284},
+ {uniname2ctype_offset(str1253), 295},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1254), 566},
+#ifndef USE_UNICODE_AGE_PROPERTIES
{-1},
- {uniname2ctype_offset(str1250), 272},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1255), 291},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1256), 278},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1257), 290},
+ {uniname2ctype_offset(str1258), 292},
+ {uniname2ctype_offset(str1259), 303},
+ {uniname2ctype_offset(str1260), 294},
{-1},
- {uniname2ctype_offset(str1252), 289},
- {uniname2ctype_offset(str1253), 274},
+ {uniname2ctype_offset(str1262), 293},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1254), 549},
+ {uniname2ctype_offset(str1263), 64},
#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1255), 273},
- {uniname2ctype_offset(str1256), 276},
- {uniname2ctype_offset(str1257), 288},
- {uniname2ctype_offset(str1258), 275},
- {uniname2ctype_offset(str1259), 277},
- {uniname2ctype_offset(str1260), 284},
- {uniname2ctype_offset(str1261), 287},
- {uniname2ctype_offset(str1262), 283},
- {uniname2ctype_offset(str1263), 285},
+ {-1},
+ {uniname2ctype_offset(str1265), 302},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1264), 216},
+ {uniname2ctype_offset(str1266), 21},
#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1265), 281},
- {uniname2ctype_offset(str1266), 286},
- {uniname2ctype_offset(str1267), 280},
- {uniname2ctype_offset(str1268), 282},
- {uniname2ctype_offset(str1269), 279},
+ {uniname2ctype_offset(str1267), 288},
{-1},
- {uniname2ctype_offset(str1271), 278},
+ {uniname2ctype_offset(str1269), 287},
+ {uniname2ctype_offset(str1270), 289},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1271), 250},
+#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {-1},
+ {uniname2ctype_offset(str1273), 286},
#endif /* USE_UNICODE_AGE_PROPERTIES */
{uniname2ctype_offset(str1274), 200},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1278), 138},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1282), 608},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1275), 285},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1282), 635},
{-1}, {-1},
{uniname2ctype_offset(str1285), 105},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1289), 338},
+ {uniname2ctype_offset(str1289), 348},
{-1}, {-1},
- {uniname2ctype_offset(str1292), 387},
+ {uniname2ctype_offset(str1292), 397},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1297), 145},
{-1}, {-1},
@@ -41753,11 +44369,7 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str1301), 141},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1306), 15},
- {-1}, {-1},
- {uniname2ctype_offset(str1309), 64},
- {-1}, {-1},
- {uniname2ctype_offset(str1312), 21},
- {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1314), 193},
{-1}, {-1},
{uniname2ctype_offset(str1317), 86},
@@ -41765,67 +44377,66 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1},
{uniname2ctype_offset(str1328), 227},
{-1}, {-1},
- {uniname2ctype_offset(str1331), 256},
+ {uniname2ctype_offset(str1331), 263},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1340), 105},
{-1}, {-1},
{uniname2ctype_offset(str1343), 120},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1348), 271},
+ {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1349), 227},
{-1}, {-1},
{uniname2ctype_offset(str1352), 88},
{-1},
{uniname2ctype_offset(str1354), 164},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1358), 606},
+ {-1},
+ {uniname2ctype_offset(str1356), 605},
+ {-1},
+ {uniname2ctype_offset(str1358), 633},
{-1},
{uniname2ctype_offset(str1360), 3},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1365), 387},
{-1},
- {uniname2ctype_offset(str1362), 609},
- {-1}, {-1},
- {uniname2ctype_offset(str1365), 377},
- {uniname2ctype_offset(str1366), 240},
- {uniname2ctype_offset(str1367), 520},
+ {uniname2ctype_offset(str1367), 534},
{-1},
- {uniname2ctype_offset(str1369), 251},
+ {uniname2ctype_offset(str1369), 258},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1373), 267},
+ {uniname2ctype_offset(str1373), 274},
{-1},
{uniname2ctype_offset(str1375), 135},
- {uniname2ctype_offset(str1376), 234},
- {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1380), 35},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1384), 56},
{-1}, {-1},
{uniname2ctype_offset(str1387), 113},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1392), 138},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1400), 201},
- {uniname2ctype_offset(str1401), 390},
+ {uniname2ctype_offset(str1401), 400},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1407), 224},
{-1},
{uniname2ctype_offset(str1409), 38},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1415), 576},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str1419), 140},
{uniname2ctype_offset(str1420), 140},
{-1},
- {uniname2ctype_offset(str1422), 315},
+ {uniname2ctype_offset(str1422), 324},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1426), 39},
{-1},
{uniname2ctype_offset(str1428), 181},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1434), 134},
+ {uniname2ctype_offset(str1429), 36},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1438), 437},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1438), 427},
- {uniname2ctype_offset(str1439), 215},
- {-1}, {-1},
- {uniname2ctype_offset(str1442), 530},
+ {uniname2ctype_offset(str1442), 544},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1448), 496},
+ {uniname2ctype_offset(str1448), 508},
{uniname2ctype_offset(str1449), 122},
{-1},
{uniname2ctype_offset(str1451), 203},
@@ -41833,419 +44444,426 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str1454), 145},
{-1}, {-1},
{uniname2ctype_offset(str1457), 166},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1462), 543},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1460), 215},
+ {-1},
+ {uniname2ctype_offset(str1462), 559},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1470), 495},
- {uniname2ctype_offset(str1471), 497},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1475), 419},
- {uniname2ctype_offset(str1476), 499},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1470), 507},
+ {uniname2ctype_offset(str1471), 509},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1474), 134},
+ {uniname2ctype_offset(str1475), 429},
+ {uniname2ctype_offset(str1476), 511},
{-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1480), 247},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1489), 33},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1495), 255},
+ {uniname2ctype_offset(str1495), 262},
{-1},
- {uniname2ctype_offset(str1497), 489},
+ {uniname2ctype_offset(str1497), 499},
{-1},
- {uniname2ctype_offset(str1499), 593},
+ {uniname2ctype_offset(str1499), 620},
{-1},
{uniname2ctype_offset(str1501), 196},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1505), 110},
- {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1507), 122},
- {uniname2ctype_offset(str1508), 110},
- {uniname2ctype_offset(str1509), 407},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1517), 592},
- {-1},
- {uniname2ctype_offset(str1519), 117},
- {uniname2ctype_offset(str1520), 232},
+ {uniname2ctype_offset(str1508), 231},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1517), 619},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1520), 239},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1524), 476},
+ {uniname2ctype_offset(str1524), 486},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1529), 120},
{-1},
- {uniname2ctype_offset(str1531), 412},
+ {uniname2ctype_offset(str1531), 422},
{-1},
{uniname2ctype_offset(str1533), 142},
{-1}, {-1},
{uniname2ctype_offset(str1536), 127},
- {uniname2ctype_offset(str1537), 264},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1544), 525},
- {-1}, {-1},
+ {uniname2ctype_offset(str1537), 271},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1542), 468},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1547), 168},
- {uniname2ctype_offset(str1548), 117},
- {uniname2ctype_offset(str1549), 510},
{-1},
- {uniname2ctype_offset(str1551), 107},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1549), 522},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1557), 85},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1563), 268},
+ {uniname2ctype_offset(str1563), 275},
{-1},
- {uniname2ctype_offset(str1565), 320},
+ {uniname2ctype_offset(str1565), 329},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1570), 210},
{-1},
{uniname2ctype_offset(str1572), 115},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1580), 131},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1577), 570},
{-1}, {-1},
+ {uniname2ctype_offset(str1580), 131},
+ {-1},
+ {uniname2ctype_offset(str1582), 219},
{uniname2ctype_offset(str1583), 125},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1587), 536},
- {uniname2ctype_offset(str1588), 458},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1597), 81},
+ {uniname2ctype_offset(str1587), 550},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1597), 81},
+ {uniname2ctype_offset(str1598), 219},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1607), 592},
+ {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1613), 164},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1617), 493},
- {uniname2ctype_offset(str1618), 267},
+ {uniname2ctype_offset(str1617), 505},
+ {uniname2ctype_offset(str1618), 274},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1622), 378},
- {uniname2ctype_offset(str1623), 555},
+ {uniname2ctype_offset(str1622), 388},
+ {uniname2ctype_offset(str1623), 573},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1629), 39},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1635), 72},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1643), 62},
+ {uniname2ctype_offset(str1644), 235},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1654), 393},
- {uniname2ctype_offset(str1655), 269},
- {uniname2ctype_offset(str1656), 255},
+ {uniname2ctype_offset(str1654), 403},
+ {uniname2ctype_offset(str1655), 276},
{-1},
- {uniname2ctype_offset(str1658), 176},
- {-1}, {-1},
- {uniname2ctype_offset(str1661), 513},
+ {uniname2ctype_offset(str1657), 114},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1662), 129},
{-1},
- {uniname2ctype_offset(str1664), 441},
- {uniname2ctype_offset(str1665), 431},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1671), 333},
+ {uniname2ctype_offset(str1664), 451},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1671), 343},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1675), 462},
+ {uniname2ctype_offset(str1675), 472},
{-1},
- {uniname2ctype_offset(str1677), 308},
+ {uniname2ctype_offset(str1677), 317},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1682), 607},
+ {uniname2ctype_offset(str1682), 634},
{-1},
{uniname2ctype_offset(str1684), 199},
{-1},
{uniname2ctype_offset(str1686), 93},
{uniname2ctype_offset(str1687), 141},
- {-1},
- {uniname2ctype_offset(str1689), 62},
- {-1},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str1691), 124},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1699), 372},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1703), 176},
+ {uniname2ctype_offset(str1699), 382},
+ {-1},
+ {uniname2ctype_offset(str1701), 525},
+ {-1}, {-1},
{uniname2ctype_offset(str1704), 207},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1714), 207},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1719), 121},
- {-1}, {-1},
- {uniname2ctype_offset(str1722), 352},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1722), 362},
{-1},
- {uniname2ctype_offset(str1724), 563},
- {-1}, {-1},
- {uniname2ctype_offset(str1727), 450},
+ {uniname2ctype_offset(str1724), 582},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str1728), 221},
- {uniname2ctype_offset(str1729), 435},
+ {uniname2ctype_offset(str1729), 445},
{uniname2ctype_offset(str1730), 222},
- {uniname2ctype_offset(str1731), 524},
- {uniname2ctype_offset(str1732), 242},
- {-1}, {-1},
- {uniname2ctype_offset(str1735), 253},
+ {uniname2ctype_offset(str1731), 538},
+ {uniname2ctype_offset(str1732), 249},
+ {uniname2ctype_offset(str1733), 123},
+ {uniname2ctype_offset(str1734), 114},
+ {uniname2ctype_offset(str1735), 260},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1740), 129},
{-1},
{uniname2ctype_offset(str1742), 161},
{-1}, {-1},
- {uniname2ctype_offset(str1745), 515},
- {uniname2ctype_offset(str1746), 395},
+ {uniname2ctype_offset(str1745), 528},
+ {uniname2ctype_offset(str1746), 405},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1750), 20},
{-1},
- {uniname2ctype_offset(str1752), 507},
+ {uniname2ctype_offset(str1752), 519},
{uniname2ctype_offset(str1753), 148},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1757), 506},
+ {uniname2ctype_offset(str1757), 518},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1766), 73},
{-1},
{uniname2ctype_offset(str1768), 148},
- {uniname2ctype_offset(str1769), 367},
+ {uniname2ctype_offset(str1769), 377},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1776), 126},
- {-1}, {-1},
- {uniname2ctype_offset(str1779), 123},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1781), 556},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1788), 97},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1793), 97},
- {uniname2ctype_offset(str1794), 84},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str1806), 341},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1810), 612},
- {uniname2ctype_offset(str1811), 240},
- {uniname2ctype_offset(str1812), 84},
- {uniname2ctype_offset(str1813), 259},
- {-1}, {-1},
- {uniname2ctype_offset(str1816), 71},
- {uniname2ctype_offset(str1817), 4},
- {uniname2ctype_offset(str1818), 237},
- {-1}, {-1},
+ {uniname2ctype_offset(str1806), 351},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1810), 640},
+ {uniname2ctype_offset(str1811), 247},
+ {-1},
+ {uniname2ctype_offset(str1813), 266},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1821), 224},
- {uniname2ctype_offset(str1822), 202},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1828), 392},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1828), 402},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1838), 596},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1842), 384},
+ {uniname2ctype_offset(str1838), 623},
{-1}, {-1},
- {uniname2ctype_offset(str1845), 258},
+ {uniname2ctype_offset(str1841), 460},
+ {uniname2ctype_offset(str1842), 394},
+ {uniname2ctype_offset(str1843), 65},
+ {-1},
+ {uniname2ctype_offset(str1845), 265},
{-1}, {-1},
{uniname2ctype_offset(str1848), 109},
- {-1},
- {uniname2ctype_offset(str1850), 239},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1855), 244},
- {-1},
- {uniname2ctype_offset(str1857), 202},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1851), 137},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1866), 61},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1871), 484},
- {-1},
- {uniname2ctype_offset(str1873), 486},
- {-1}, {-1},
- {uniname2ctype_offset(str1876), 573},
- {-1}, {-1},
- {uniname2ctype_offset(str1879), 8},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1888), 517},
- {uniname2ctype_offset(str1889), 541},
+ {uniname2ctype_offset(str1871), 494},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1881), 63},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1888), 531},
+ {uniname2ctype_offset(str1889), 555},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1896), 599},
+ {uniname2ctype_offset(str1896), 626},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1902), 424},
+ {uniname2ctype_offset(str1902), 434},
{-1},
- {uniname2ctype_offset(str1904), 445},
- {uniname2ctype_offset(str1905), 570},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1904), 455},
+ {uniname2ctype_offset(str1905), 590},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1912), 586},
{uniname2ctype_offset(str1913), 143},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str1924), 143},
{-1}, {-1},
- {uniname2ctype_offset(str1927), 63},
- {-1},
- {uniname2ctype_offset(str1929), 422},
+ {uniname2ctype_offset(str1916), 594},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1924), 143},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1929), 432},
{-1}, {-1},
- {uniname2ctype_offset(str1932), 405},
+ {uniname2ctype_offset(str1932), 415},
{-1}, {-1},
- {uniname2ctype_offset(str1935), 257},
- {uniname2ctype_offset(str1936), 328},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1935), 264},
+ {uniname2ctype_offset(str1936), 338},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1950), 414},
+ {uniname2ctype_offset(str1941), 27},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1950), 424},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1956), 245},
+ {uniname2ctype_offset(str1956), 252},
{-1},
{uniname2ctype_offset(str1958), 109},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1964), 430},
+ {uniname2ctype_offset(str1964), 440},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1967), 492},
+ {uniname2ctype_offset(str1968), 644},
+ {uniname2ctype_offset(str1969), 251},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1974), 358},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1981), 176},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1985), 408},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1988), 441},
{-1}, {-1},
- {uniname2ctype_offset(str1967), 482},
- {uniname2ctype_offset(str1968), 616},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1976), 270},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1985), 398},
- {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1991), 1},
{-1},
- {uniname2ctype_offset(str1993), 365},
+ {uniname2ctype_offset(str1993), 375},
{uniname2ctype_offset(str1994), 175},
{-1},
{uniname2ctype_offset(str1996), 42},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2001), 110},
+ {uniname2ctype_offset(str2002), 598},
{-1},
- {uniname2ctype_offset(str1998), 153},
- {-1}, {-1},
- {uniname2ctype_offset(str2001), 374},
- {uniname2ctype_offset(str2002), 576},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2006), 400},
+ {uniname2ctype_offset(str2004), 110},
+ {-1},
+ {uniname2ctype_offset(str2006), 410},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2010), 368},
- {uniname2ctype_offset(str2011), 262},
- {uniname2ctype_offset(str2012), 548},
+ {uniname2ctype_offset(str2010), 378},
+ {uniname2ctype_offset(str2011), 269},
+ {uniname2ctype_offset(str2012), 565},
{-1},
- {uniname2ctype_offset(str2014), 327},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2014), 336},
+ {uniname2ctype_offset(str2015), 117},
+ {uniname2ctype_offset(str2016), 209},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2023), 32},
- {uniname2ctype_offset(str2024), 494},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2024), 506},
+ {-1},
+ {uniname2ctype_offset(str2026), 176},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2033), 8},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2040), 539},
+ {-1},
+ {uniname2ctype_offset(str2042), 121},
{uniname2ctype_offset(str2043), 17},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2049), 244},
+ {uniname2ctype_offset(str2044), 117},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2047), 107},
+ {uniname2ctype_offset(str2048), 526},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2062), 209},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2062), 130},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2070), 9},
{-1}, {-1},
- {uniname2ctype_offset(str2073), 335},
+ {uniname2ctype_offset(str2073), 345},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2077), 150},
- {uniname2ctype_offset(str2078), 249},
+ {uniname2ctype_offset(str2078), 256},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2090), 277},
+ {-1},
{uniname2ctype_offset(str2092), 150},
{-1}, {-1},
- {uniname2ctype_offset(str2095), 346},
+ {uniname2ctype_offset(str2095), 356},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2103), 162},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2110), 123},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2107), 215},
- {uniname2ctype_offset(str2108), 130},
+ {uniname2ctype_offset(str2114), 439},
+ {uniname2ctype_offset(str2115), 384},
{-1},
- {uniname2ctype_offset(str2110), 329},
- {uniname2ctype_offset(str2111), 154},
- {-1}, {-1},
- {uniname2ctype_offset(str2114), 429},
- {-1}, {-1},
{uniname2ctype_offset(str2117), 174},
- {uniname2ctype_offset(str2118), 375},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2122), 254},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str2128), 215},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2135), 128},
{-1},
{uniname2ctype_offset(str2137), 12},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2141), 159},
+ {uniname2ctype_offset(str2141), 244},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2145), 52},
- {uniname2ctype_offset(str2146), 406},
+ {uniname2ctype_offset(str2146), 416},
{-1}, {-1},
{uniname2ctype_offset(str2149), 221},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2156), 123},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2162), 408},
- {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2163), 251},
+ {-1},
{uniname2ctype_offset(str2165), 174},
{uniname2ctype_offset(str2166), 5},
- {-1}, {-1},
- {uniname2ctype_offset(str2169), 87},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2177), 121},
- {uniname2ctype_offset(str2178), 87},
+ {uniname2ctype_offset(str2174), 233},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2178), 233},
{-1}, {-1},
{uniname2ctype_offset(str2181), 139},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2188), 237},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2195), 344},
+ {uniname2ctype_offset(str2182), 216},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2195), 354},
+ {uniname2ctype_offset(str2196), 496},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
{uniname2ctype_offset(str2207), 196},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2213), 371},
{-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2211), 20},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2216), 367},
{uniname2ctype_offset(str2217), 128},
- {uniname2ctype_offset(str2218), 533},
+ {uniname2ctype_offset(str2218), 547},
{uniname2ctype_offset(str2219), 78},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2224), 443},
- {-1},
- {uniname2ctype_offset(str2226), 159},
- {-1},
- {uniname2ctype_offset(str2228), 89},
- {uniname2ctype_offset(str2229), 35},
- {uniname2ctype_offset(str2230), 432},
+ {uniname2ctype_offset(str2224), 453},
{-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2228), 43},
+ {uniname2ctype_offset(str2229), 35},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2232), 385},
+ {uniname2ctype_offset(str2233), 216},
{uniname2ctype_offset(str2234), 92},
- {uniname2ctype_offset(str2235), 479},
+ {uniname2ctype_offset(str2235), 489},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2241), 92},
{-1}, {-1},
- {uniname2ctype_offset(str2244), 433},
+ {uniname2ctype_offset(str2244), 443},
{-1}, {-1},
{uniname2ctype_offset(str2247), 36},
- {uniname2ctype_offset(str2248), 580},
- {uniname2ctype_offset(str2249), 463},
- {-1}, {-1},
- {uniname2ctype_offset(str2252), 464},
+ {uniname2ctype_offset(str2248), 602},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2265), 154},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2276), 418},
+ {-1},
+ {uniname2ctype_offset(str2278), 124},
{uniname2ctype_offset(str2279), 192},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2283), 214},
- {-1},
- {uniname2ctype_offset(str2285), 448},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2296), 639},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2305), 205},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2308), 234},
+ {-1}, {-1}, {-1},
{uniname2ctype_offset(str2312), 177},
{-1}, {-1},
- {uniname2ctype_offset(str2315), 579},
- {uniname2ctype_offset(str2316), 611},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2315), 601},
+ {uniname2ctype_offset(str2316), 638},
+ {-1},
+ {uniname2ctype_offset(str2318), 202},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2321), 153},
+ {-1},
{uniname2ctype_offset(str2323), 172},
- {uniname2ctype_offset(str2324), 124},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2329), 373},
{-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2327), 381},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2331), 636},
+ {-1},
{uniname2ctype_offset(str2333), 134},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2343), 571},
+ {uniname2ctype_offset(str2343), 591},
+ {uniname2ctype_offset(str2344), 442},
+ {uniname2ctype_offset(str2345), 241},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2351), 205},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2361), 582},
+ {uniname2ctype_offset(str2353), 202},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2361), 606},
{-1}, {-1},
- {uniname2ctype_offset(str2364), 314},
- {-1},
- {uniname2ctype_offset(str2366), 613},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2364), 323},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2373), 37},
- {uniname2ctype_offset(str2374), 382},
+ {uniname2ctype_offset(str2374), 392},
+ {uniname2ctype_offset(str2375), 197},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2397), 411},
- {uniname2ctype_offset(str2398), 403},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2397), 421},
+ {uniname2ctype_offset(str2398), 413},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2405), 165},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2414), 82},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2421), 197},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2427), 23},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2431), 270},
+ {uniname2ctype_offset(str2427), 23},
{-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2433), 339},
+ {uniname2ctype_offset(str2434), 154},
+ {-1}, {-1},
{uniname2ctype_offset(str2437), 194},
{-1}, {-1},
{uniname2ctype_offset(str2440), 100},
@@ -42255,441 +44873,478 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1},
{uniname2ctype_offset(str2454), 220},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2460), 250},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2470), 438},
+ {uniname2ctype_offset(str2460), 257},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2464), 159},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2470), 448},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2475), 142},
- {-1}, {-1},
- {uniname2ctype_offset(str2478), 29},
- {uniname2ctype_offset(str2479), 351},
+ {uniname2ctype_offset(str2476), 558},
{-1},
- {uniname2ctype_offset(str2481), 376},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2485), 500},
+ {uniname2ctype_offset(str2478), 417},
+ {uniname2ctype_offset(str2479), 361},
+ {-1},
+ {uniname2ctype_offset(str2481), 386},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2506), 518},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2513), 603},
+ {uniname2ctype_offset(str2500), 121},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2506), 532},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2511), 244},
+ {-1},
+ {uniname2ctype_offset(str2513), 630},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2530), 82},
- {-1}, {-1},
- {uniname2ctype_offset(str2533), 49},
- {uniname2ctype_offset(str2534), 330},
- {-1},
- {uniname2ctype_offset(str2536), 469},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2534), 340},
+ {uniname2ctype_offset(str2535), 237},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2545), 277},
{-1}, {-1},
{uniname2ctype_offset(str2548), 118},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2562), 185},
+ {uniname2ctype_offset(str2549), 159},
{-1},
- {uniname2ctype_offset(str2564), 362},
- {-1}, {-1},
- {uniname2ctype_offset(str2567), 309},
- {-1}, {-1},
- {uniname2ctype_offset(str2570), 481},
- {uniname2ctype_offset(str2571), 185},
- {uniname2ctype_offset(str2572), 99},
+ {uniname2ctype_offset(str2551), 89},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2576), 268},
+ {uniname2ctype_offset(str2564), 372},
{-1}, {-1},
- {uniname2ctype_offset(str2579), 467},
+ {uniname2ctype_offset(str2567), 318},
{-1}, {-1},
- {uniname2ctype_offset(str2582), 381},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2588), 440},
- {uniname2ctype_offset(str2589), 228},
+ {uniname2ctype_offset(str2570), 491},
{-1},
- {uniname2ctype_offset(str2591), 332},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2572), 473},
{-1},
+ {uniname2ctype_offset(str2574), 246},
+ {uniname2ctype_offset(str2575), 474},
+ {uniname2ctype_offset(str2576), 275},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2582), 391},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2588), 154},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2602), 210},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2606), 364},
- {-1}, {-1},
+ {uniname2ctype_offset(str2606), 374},
+ {-1},
+ {uniname2ctype_offset(str2608), 458},
{uniname2ctype_offset(str2609), 55},
- {uniname2ctype_offset(str2610), 546},
- {uniname2ctype_offset(str2611), 179},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2627), 107},
- {-1}, {-1},
- {uniname2ctype_offset(str2630), 198},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2639), 442},
+ {uniname2ctype_offset(str2625), 262},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2644), 41},
+ {uniname2ctype_offset(str2648), 254},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2648), 247},
- {uniname2ctype_offset(str2649), 183},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2656), 358},
+ {uniname2ctype_offset(str2652), 383},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2656), 368},
{uniname2ctype_offset(str2657), 112},
- {-1},
- {uniname2ctype_offset(str2659), 182},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2665), 87},
{uniname2ctype_offset(str2666), 50},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2670), 605},
+ {uniname2ctype_offset(str2670), 632},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2674), 87},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2688), 139},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2692), 83},
- {-1},
+ {uniname2ctype_offset(str2689), 641},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2694), 48},
- {uniname2ctype_offset(str2695), 94},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str2697), 423},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2703), 83},
- {uniname2ctype_offset(str2704), 220},
- {uniname2ctype_offset(str2705), 471},
+ {uniname2ctype_offset(str2705), 481},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2719), 211},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2725), 119},
- {uniname2ctype_offset(str2726), 226},
- {-1}, {-1},
- {uniname2ctype_offset(str2729), 89},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2745), 54},
{-1}, {-1},
- {uniname2ctype_offset(str2748), 198},
- {-1},
- {uniname2ctype_offset(str2750), 542},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2759), 130},
+ {uniname2ctype_offset(str2726), 226},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2750), 557},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
{uniname2ctype_offset(str2761), 18},
- {uniname2ctype_offset(str2762), 258},
+ {uniname2ctype_offset(str2762), 265},
{-1}, {-1},
{uniname2ctype_offset(str2765), 133},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2769), 473},
+ {uniname2ctype_offset(str2766), 54},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2769), 483},
{-1}, {-1},
{uniname2ctype_offset(str2772), 199},
{-1}, {-1},
{uniname2ctype_offset(str2775), 38},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2787), 152},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str2786), 4},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2793), 34},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2801), 29},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2808), 512},
{-1},
- {uniname2ctype_offset(str2795), 90},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2810), 226},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2816), 301},
+ {uniname2ctype_offset(str2816), 310},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2821), 383},
- {-1}, {-1},
- {uniname2ctype_offset(str2824), 132},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2830), 587},
+ {uniname2ctype_offset(str2821), 393},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2830), 614},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2834), 354},
- {uniname2ctype_offset(str2835), 132},
+ {uniname2ctype_offset(str2834), 364},
+ {-1},
{uniname2ctype_offset(str2836), 78},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str2847), 241},
+ {uniname2ctype_offset(str2847), 248},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2852), 296},
+ {uniname2ctype_offset(str2852), 305},
{-1}, {-1},
{uniname2ctype_offset(str2855), 190},
{uniname2ctype_offset(str2856), 66},
{-1}, {-1},
- {uniname2ctype_offset(str2859), 417},
+ {uniname2ctype_offset(str2859), 427},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2867), 300},
- {uniname2ctype_offset(str2868), 241},
+ {uniname2ctype_offset(str2867), 309},
+ {uniname2ctype_offset(str2868), 248},
{-1}, {-1},
- {uniname2ctype_offset(str2871), 247},
+ {uniname2ctype_offset(str2871), 254},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2879), 204},
- {-1},
- {uniname2ctype_offset(str2881), 147},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2885), 65},
- {uniname2ctype_offset(str2886), 604},
- {-1}, {-1},
- {uniname2ctype_offset(str2889), 211},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2886), 631},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2899), 254},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2904), 454},
- {uniname2ctype_offset(str2905), 266},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2902), 477},
{-1},
- {uniname2ctype_offset(str2907), 266},
+ {uniname2ctype_offset(str2904), 464},
+ {uniname2ctype_offset(str2905), 273},
{-1},
- {uniname2ctype_offset(str2909), 558},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2915), 297},
+ {uniname2ctype_offset(str2907), 273},
+ {-1},
+ {uniname2ctype_offset(str2909), 577},
+ {-1},
+ {uniname2ctype_offset(str2911), 450},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2941), 353},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2959), 225},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2964), 508},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2941), 363},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2953), 198},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str2964), 520},
{-1},
- {uniname2ctype_offset(str2966), 231},
+ {uniname2ctype_offset(str2966), 238},
{uniname2ctype_offset(str2967), 43},
{-1}, {-1},
{uniname2ctype_offset(str2970), 88},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2980), 195},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2984), 556},
+ {uniname2ctype_offset(str2984), 574},
{-1},
{uniname2ctype_offset(str2986), 118},
{uniname2ctype_offset(str2987), 54},
- {uniname2ctype_offset(str2988), 461},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2988), 471},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2997), 603},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str3001), 180},
{uniname2ctype_offset(str3002), 64},
{-1}, {-1},
- {uniname2ctype_offset(str3005), 465},
- {uniname2ctype_offset(str3006), 564},
- {-1},
- {uniname2ctype_offset(str3008), 80},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
+ {uniname2ctype_offset(str3005), 475},
+ {uniname2ctype_offset(str3006), 583},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3015), 83},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3018), 94},
{uniname2ctype_offset(str3019), 165},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3045), 588},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3026), 83},
+ {uniname2ctype_offset(str3027), 503},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3053), 229},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3072), 133},
+ {uniname2ctype_offset(str3035), 232},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3079), 239},
+ {uniname2ctype_offset(str3042), 211},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3045), 615},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3048), 119},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3052), 89},
+ {uniname2ctype_offset(str3053), 229},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3058), 185},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3067), 185},
+ {uniname2ctype_offset(str3068), 99},
{-1}, {-1},
- {uniname2ctype_offset(str3082), 459},
+ {uniname2ctype_offset(str3071), 198},
+ {uniname2ctype_offset(str3072), 133},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3082), 130},
+ {-1},
+ {uniname2ctype_offset(str3084), 237},
+ {-1},
+ {uniname2ctype_offset(str3086), 84},
+ {uniname2ctype_offset(str3087), 342},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3091), 261},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3099), 468},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3107), 304},
+ {uniname2ctype_offset(str3099), 478},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3104), 84},
{-1},
- {uniname2ctype_offset(str3109), 306},
+ {uniname2ctype_offset(str3106), 562},
+ {uniname2ctype_offset(str3107), 313},
{-1},
+ {uniname2ctype_offset(str3109), 315},
+ {uniname2ctype_offset(str3110), 152},
{uniname2ctype_offset(str3111), 191},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3118), 90},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3123), 107},
{-1},
- {uniname2ctype_offset(str3122), 99},
- {-1}, {-1},
{uniname2ctype_offset(str3125), 191},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3142), 566},
+ {uniname2ctype_offset(str3135), 452},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3142), 585},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3145), 183},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3155), 182},
+ {-1},
+ {uniname2ctype_offset(str3157), 231},
+ {uniname2ctype_offset(str3158), 328},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3176), 396},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3180), 331},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3176), 386},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str3180), 322},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3188), 444},
- {-1},
- {uniname2ctype_offset(str3190), 204},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3199), 248},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3204), 319},
- {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3193), 433},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3209), 62},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3212), 211},
+ {-1}, {-1},
{uniname2ctype_offset(str3215), 180},
{-1}, {-1},
{uniname2ctype_offset(str3218), 125},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3237), 380},
+ {uniname2ctype_offset(str3237), 390},
{-1},
- {uniname2ctype_offset(str3239), 299},
- {uniname2ctype_offset(str3240), 295},
+ {uniname2ctype_offset(str3239), 308},
+ {uniname2ctype_offset(str3240), 304},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3248), 213},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3254), 245},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3260), 201},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3254), 252},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str3265), 610},
+ {-1},
{uniname2ctype_offset(str3267), 28},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3275), 146},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3284), 591},
+ {uniname2ctype_offset(str3284), 618},
{-1}, {-1},
{uniname2ctype_offset(str3287), 223},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3297), 302},
+ {uniname2ctype_offset(str3297), 311},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3303), 298},
+ {uniname2ctype_offset(str3303), 307},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3313), 255},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3320), 223},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3328), 63},
- {uniname2ctype_offset(str3329), 598},
+ {uniname2ctype_offset(str3329), 625},
{-1},
{uniname2ctype_offset(str3331), 222},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3336), 178},
- {-1},
- {uniname2ctype_offset(str3338), 257},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3348), 397},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3338), 264},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3348), 407},
+ {-1},
+ {uniname2ctype_offset(str3350), 501},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3355), 47},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3361), 589},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3360), 337},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
{uniname2ctype_offset(str3371), 126},
{uniname2ctype_offset(str3372), 16},
- {uniname2ctype_offset(str3373), 246},
- {-1}, {-1},
- {uniname2ctype_offset(str3376), 538},
- {-1},
- {uniname2ctype_offset(str3378), 96},
+ {uniname2ctype_offset(str3373), 253},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3377), 147},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3390), 96},
- {uniname2ctype_offset(str3391), 231},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3396), 586},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3391), 238},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3396), 613},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3405), 469},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
{uniname2ctype_offset(str3416), 51},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str3428), 246},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3428), 253},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3433), 205},
+ {-1}, {-1},
{uniname2ctype_offset(str3436), 213},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3448), 426},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3455), 225},
{-1}, {-1},
- {uniname2ctype_offset(str3460), 600},
+ {uniname2ctype_offset(str3458), 10},
+ {-1},
+ {uniname2ctype_offset(str3460), 627},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3479), 205},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3483), 238},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3483), 245},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3504), 10},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3511), 401},
+ {uniname2ctype_offset(str3502), 49},
+ {-1},
+ {uniname2ctype_offset(str3504), 80},
+ {uniname2ctype_offset(str3505), 479},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3511), 411},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str3532), 559},
+ {uniname2ctype_offset(str3532), 578},
{uniname2ctype_offset(str3533), 57},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3558), 59},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3580), 179},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3585), 153},
- {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3590), 103},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3604), 59},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3613), 41},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3618), 99},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3648), 455},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3648), 465},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str3659), 178},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3664), 177},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3698), 492},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3705), 311},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3721), 428},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3686), 204},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3689), 246},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3698), 504},
+ {uniname2ctype_offset(str3699), 552},
+ {-1},
+ {uniname2ctype_offset(str3701), 96},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3705), 320},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3710), 201},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3713), 96},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3721), 438},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3744), 190},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3754), 71},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str3765), 179},
- {uniname2ctype_offset(str3766), 457},
+ {uniname2ctype_offset(str3766), 467},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3799), 214},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3807), 253},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3807), 260},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3850), 238},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3842), 182},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3845), 259},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3850), 245},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3854), 65},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3857), 616},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str3868), 261},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3884), 420},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str3888), 182},
+ {uniname2ctype_offset(str3881), 228},
{-1}, {-1},
- {uniname2ctype_offset(str3891), 252},
+ {uniname2ctype_offset(str3884), 306},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3891), 30},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3924), 410},
+ {uniname2ctype_offset(str3924), 420},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3937), 30},
- {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3942), 100},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3949), 269},
+ {-1},
+ {uniname2ctype_offset(str3944), 436},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3949), 276},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3976), 581},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3991), 147},
+ {uniname2ctype_offset(str3976), 604},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3998), 430},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4007), 454},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42700,23 +45355,27 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str4106), 45},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4116), 132},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str4127), 132},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4136), 119},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4169), 220},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4194), 391},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4231), 153},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42724,26 +45383,19 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4281), 116},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4287), 307},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4291), 80},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4303), 116},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4308), 401},
{uniname2ctype_offset(str4309), 162},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str4348), 553},
+ {uniname2ctype_offset(str4348), 571},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str4361), 554},
+ {uniname2ctype_offset(str4361), 572},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42751,23 +45403,20 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4432), 303},
- {uniname2ctype_offset(str4433), 305},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4459), 119},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4487), 90},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4487), 147},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4542), 235},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42775,46 +45424,57 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4604), 116},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str4627), 248},
+ {uniname2ctype_offset(str4626), 116},
+ {uniname2ctype_offset(str4627), 255},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str4674), 614},
+ {uniname2ctype_offset(str4674), 642},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4683), 456},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4683), 466},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4695), 80},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4734), 179},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4772), 399},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4755), 312},
+ {uniname2ctype_offset(str4756), 314},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4772), 409},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str4783), 316},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4810), 90},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4877), 75},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4898), 75},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42824,7 +45484,10 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4986), 418},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4982), 232},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4986), 428},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42832,6 +45495,8 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str5018), 46},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str5038), 242},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42842,9 +45507,27 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str5134), 601},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str5134), 628},
+#endif /* USE_UNICODE_PROPERTIES */
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#ifndef USE_UNICODE_PROPERTIES
+ {uniname2ctype_offset(str6), 12},
+ {uniname2ctype_offset(str7), 7},
+ {uniname2ctype_offset(str8), 15},
+ {uniname2ctype_offset(str9), 1},
+ {uniname2ctype_offset(str10), 13},
+ {uniname2ctype_offset(str11), 11},
+ {uniname2ctype_offset(str12), 10},
+ {uniname2ctype_offset(str13), 14},
+ {uniname2ctype_offset(str14), 3},
+ {uniname2ctype_offset(str15), 9},
+ {uniname2ctype_offset(str16), 8},
+ {uniname2ctype_offset(str17), 6},
+ {uniname2ctype_offset(str18), 5},
+ {uniname2ctype_offset(str19), 4},
+ {uniname2ctype_offset(str20), 2}
+#else /* USE_UNICODE_PROPERTIES */
{uniname2ctype_offset(str5141), 155},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42955,7 +45638,7 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str6098), 615}
+ {uniname2ctype_offset(str6098), 643}
#endif /* USE_UNICODE_PROPERTIES */
};
@@ -42986,22 +45669,22 @@ uniname2ctype(const UChar *name, unsigned int len)
return -1;
}
#if defined ONIG_UNICODE_VERSION_STRING && !( \
- ONIG_UNICODE_VERSION_MAJOR == 13 && \
+ ONIG_UNICODE_VERSION_MAJOR == 15 && \
ONIG_UNICODE_VERSION_MINOR == 0 && \
ONIG_UNICODE_VERSION_TEENY == 0 && \
1)
# error ONIG_UNICODE_VERSION_STRING mismatch
#endif
-#define ONIG_UNICODE_VERSION_STRING "13.0.0"
-#define ONIG_UNICODE_VERSION_MAJOR 13
+#define ONIG_UNICODE_VERSION_STRING "15.0.0"
+#define ONIG_UNICODE_VERSION_MAJOR 15
#define ONIG_UNICODE_VERSION_MINOR 0
#define ONIG_UNICODE_VERSION_TEENY 0
#if defined ONIG_UNICODE_EMOJI_VERSION_STRING && !( \
- ONIG_UNICODE_EMOJI_VERSION_MAJOR == 13 && \
+ ONIG_UNICODE_EMOJI_VERSION_MAJOR == 15 && \
ONIG_UNICODE_EMOJI_VERSION_MINOR == 0 && \
1)
# error ONIG_UNICODE_EMOJI_VERSION_STRING mismatch
#endif
-#define ONIG_UNICODE_EMOJI_VERSION_STRING "13.0"
-#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 13
+#define ONIG_UNICODE_EMOJI_VERSION_STRING "15.0"
+#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 15
#define ONIG_UNICODE_EMOJI_VERSION_MINOR 0
diff --git a/enc/utf_16_32.h b/enc/utf_16_32.h
index 9f9216d8ff..4d669019bf 100644
--- a/enc/utf_16_32.h
+++ b/enc/utf_16_32.h
@@ -1,5 +1,5 @@
#include "regenc.h"
/* dummy for unsupported, stateful encoding */
-#define ENC_DUMMY_UNICODE(name) ENC_REPLICATE(name, name "BE")
+#define ENC_DUMMY_UNICODE(name) ENC_DUMMY(name)
ENC_DUMMY_UNICODE("UTF-16");
ENC_DUMMY_UNICODE("UTF-32");
diff --git a/encindex.h b/encindex.h
index 8457a7b39f..e6ddb1b0c2 100644
--- a/encindex.h
+++ b/encindex.h
@@ -20,7 +20,7 @@ extern "C" {
#endif
enum ruby_preserved_encindex {
- RUBY_ENCINDEX_ASCII,
+ RUBY_ENCINDEX_ASCII_8BIT,
RUBY_ENCINDEX_UTF_8,
RUBY_ENCINDEX_US_ASCII,
@@ -40,7 +40,7 @@ enum ruby_preserved_encindex {
RUBY_ENCINDEX_BUILTIN_MAX
};
-#define ENCINDEX_ASCII RUBY_ENCINDEX_ASCII
+#define ENCINDEX_ASCII_8BIT RUBY_ENCINDEX_ASCII_8BIT
#define ENCINDEX_UTF_8 RUBY_ENCINDEX_UTF_8
#define ENCINDEX_US_ASCII RUBY_ENCINDEX_US_ASCII
#define ENCINDEX_UTF_16BE RUBY_ENCINDEX_UTF_16BE
@@ -54,7 +54,7 @@ enum ruby_preserved_encindex {
#define ENCINDEX_Windows_31J RUBY_ENCINDEX_Windows_31J
#define ENCINDEX_BUILTIN_MAX RUBY_ENCINDEX_BUILTIN_MAX
-#define rb_ascii8bit_encindex() RUBY_ENCINDEX_ASCII
+#define rb_ascii8bit_encindex() RUBY_ENCINDEX_ASCII_8BIT
#define rb_utf8_encindex() RUBY_ENCINDEX_UTF_8
#define rb_usascii_encindex() RUBY_ENCINDEX_US_ASCII
diff --git a/encoding.c b/encoding.c
index 0f3f7f2c53..2f4b47bdfa 100644
--- a/encoding.c
+++ b/encoding.c
@@ -17,6 +17,7 @@
#include "internal.h"
#include "internal/enc.h"
#include "internal/encoding.h"
+#include "internal/error.h"
#include "internal/inits.h"
#include "internal/load.h"
#include "internal/object.h"
@@ -49,16 +50,14 @@ void rb_encdb_declare(const char *name);
int rb_encdb_replicate(const char *name, const char *orig);
int rb_encdb_dummy(const char *name);
int rb_encdb_alias(const char *alias, const char *orig);
-void rb_encdb_set_unicode(int index);
#pragma GCC visibility pop
#endif
static ID id_encoding;
VALUE rb_cEncoding;
-#define DEFAULT_ENCODING_LIST_CAPA 128
-static VALUE rb_default_encoding_list;
-static VALUE rb_additional_encoding_list;
+#define ENCODING_LIST_CAPA 256
+static VALUE rb_encoding_list;
struct rb_encoding_entry {
const char *name;
@@ -67,9 +66,8 @@ struct rb_encoding_entry {
};
static struct enc_table {
- struct rb_encoding_entry *list;
+ struct rb_encoding_entry list[ENCODING_LIST_CAPA];
int count;
- int size;
st_table *names;
} global_enc_table;
@@ -128,47 +126,25 @@ enc_new(rb_encoding *encoding)
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();
+ RUBY_ASSERT(index < ENCODING_LIST_CAPA);
+
+ VALUE list = rb_encoding_list;
+ if (list && NIL_P(rb_ary_entry(list, index))) {
+ /* initialize encoding data */
+ rb_ary_store(list, index, enc_new(encoding));
}
}
static VALUE
enc_list_lookup(int idx)
{
- VALUE list, enc;
+ VALUE list, enc = Qnil;
- 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);
- }
+ if (idx < ENCODING_LIST_CAPA) {
+ list = rb_encoding_list;
+ RUBY_ASSERT(list);
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);
@@ -210,7 +186,7 @@ check_encoding(rb_encoding *enc)
{
int index = rb_enc_to_index(enc);
if (rb_enc_from_index(index) != enc)
- return -1;
+ return -1;
if (rb_enc_autoload_p(enc)) {
index = rb_enc_autoload(enc);
}
@@ -221,7 +197,7 @@ static int
enc_check_encoding(VALUE obj)
{
if (!is_obj_encoding(obj)) {
- return -1;
+ return -1;
}
return check_encoding(RDATA(obj)->data);
}
@@ -231,7 +207,7 @@ static void
not_encoding(VALUE enc)
{
rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Encoding)",
- rb_obj_class(enc));
+ rb_obj_class(enc));
}
static rb_encoding *
@@ -239,7 +215,7 @@ must_encoding(VALUE enc)
{
int index = enc_check_encoding(enc);
if (index < 0) {
- not_encoding(enc);
+ not_encoding(enc);
}
return DATA_PTR(enc);
}
@@ -249,16 +225,16 @@ must_encindex(int index)
{
rb_encoding *enc = rb_enc_from_index(index);
if (!enc) {
- rb_raise(rb_eEncodingError, "encoding index out of bound: %d",
- index);
+ rb_raise(rb_eEncodingError, "encoding index out of bound: %d",
+ index);
}
if (ENC_TO_ENCINDEX(enc) != (int)(index & ENC_INDEX_MASK)) {
- rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)",
- index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc));
+ rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)",
+ index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc));
}
if (rb_enc_autoload_p(enc) && rb_enc_autoload(enc) == -1) {
- rb_loaderror("failed to load encoding (%s)",
- rb_enc_name(enc));
+ rb_loaderror("failed to load encoding (%s)",
+ rb_enc_name(enc));
}
return enc;
}
@@ -271,16 +247,16 @@ rb_to_encoding_index(VALUE enc)
idx = enc_check_encoding(enc);
if (idx >= 0) {
- return idx;
+ return idx;
}
else if (NIL_P(enc = rb_check_string_type(enc))) {
- return -1;
+ return -1;
}
if (!rb_enc_asciicompat(rb_enc_get(enc))) {
- return -1;
+ return -1;
}
if (!(name = rb_str_to_cstr(enc))) {
- return -1;
+ return -1;
}
return rb_enc_find_index(name);
}
@@ -292,10 +268,10 @@ name_for_encoding(volatile VALUE *enc)
const char *n;
if (!rb_enc_asciicompat(rb_enc_get(name))) {
- rb_raise(rb_eArgError, "invalid encoding name (non ASCII)");
+ 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)");
+ rb_raise(rb_eArgError, "invalid encoding name (NUL byte)");
}
return n;
}
@@ -314,7 +290,7 @@ str_to_encindex(VALUE enc)
{
int idx = str_find_encindex(enc);
if (idx < 0) {
- rb_raise(rb_eArgError, "unknown encoding name - %"PRIsVALUE, enc);
+ rb_raise(rb_eArgError, "unknown encoding name - %"PRIsVALUE, enc);
}
return idx;
}
@@ -345,16 +321,10 @@ rb_find_encoding(VALUE enc)
static int
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;
- 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;
- return count;
+ if (newsize > ENCODING_LIST_CAPA) {
+ rb_raise(rb_eEncodingError, "too many encoding (> %d)", ENCODING_LIST_CAPA);
+ }
+ return newsize;
}
static int
@@ -365,20 +335,20 @@ enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_enc
if (!valid_encoding_name_p(name)) return -1;
if (!ent->name) {
- ent->name = name = strdup(name);
+ ent->name = name = strdup(name);
}
else if (STRCASECMP(name, ent->name)) {
- return -1;
+ return -1;
}
encoding = (rb_raw_encoding *)ent->enc;
if (!encoding) {
- encoding = xmalloc(sizeof(rb_encoding));
+ encoding = xmalloc(sizeof(rb_encoding));
}
if (base_encoding) {
- *encoding = *base_encoding;
+ *encoding = *base_encoding;
}
else {
- memset(encoding, 0, sizeof(*ent->enc));
+ memset(encoding, 0, sizeof(*ent->enc));
}
encoding->name = name;
encoding->ruby_encoding_index = index;
@@ -405,7 +375,7 @@ 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 0;
}
return enc_table->list[index].enc;
}
@@ -413,17 +383,7 @@ enc_from_index(struct enc_table *enc_table, int index)
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;
- }
+ return enc_from_index(&global_enc_table, index);
}
int
@@ -462,9 +422,9 @@ 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 (!enc_table->names) return -1;
if (st_lookup(enc_table->names, (st_data_t)name, &idx)) {
- return (int)idx;
+ return (int)idx;
}
return -1;
}
@@ -484,10 +444,13 @@ rb_encdb_declare(const char *name)
}
static void
-enc_check_duplication(struct enc_table *enc_table, const char *name)
+enc_check_addable(struct enc_table *enc_table, const char *name)
{
if (enc_registered(enc_table, name) >= 0) {
- rb_raise(rb_eArgError, "encoding %s is already registered", name);
+ rb_raise(rb_eArgError, "encoding %s is already registered", name);
+ }
+ else if (!valid_encoding_name_p(name)) {
+ rb_raise(rb_eArgError, "invalid encoding name: %s", name);
}
}
@@ -496,6 +459,7 @@ set_base_encoding(struct enc_table *enc_table, int index, rb_encoding *base)
{
rb_encoding *enc = enc_table->list[index].enc;
+ ASSUME(enc);
enc_table->list[index].base = base;
if (ENC_DUMMY_P(base)) ENC_SET_DUMMY((rb_raw_encoding *)enc);
return enc;
@@ -523,11 +487,7 @@ rb_enc_set_base(const char *name, const char *orig)
int
rb_enc_set_dummy(int index)
{
- rb_encoding *enc;
-
- GLOBAL_ENC_TABLE_EVAL(enc_table,
- enc = enc_table->list[index].enc);
-
+ rb_encoding *enc = global_enc_table.list[index].enc;
ENC_SET_DUMMY((rb_raw_encoding *)enc);
return index;
}
@@ -537,7 +497,7 @@ enc_replicate(struct enc_table *enc_table, const char *name, rb_encoding *encodi
{
int idx;
- enc_check_duplication(enc_table, name);
+ enc_check_addable(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);
@@ -568,7 +528,10 @@ rb_enc_replicate(const char *name, rb_encoding *encoding)
static VALUE
enc_replicate_m(VALUE encoding, VALUE name)
{
- int idx = rb_enc_replicate(name_for_encoding(&name), rb_to_encoding(encoding));
+ int idx;
+ rb_warn_deprecated_to_remove("3.3", "Encoding#replicate", "the original encoding");
+
+ idx = rb_enc_replicate(name_for_encoding(&name), rb_to_encoding(encoding));
RB_GC_GUARD(name);
return rb_enc_from_encoding_index(idx);
}
@@ -580,11 +543,11 @@ enc_replicate_with_index(struct enc_table *enc_table, const char *name, rb_encod
idx = enc_register(enc_table, name, origenc);
}
else {
- idx = enc_register_at(enc_table, idx, name, origenc);
+ idx = enc_register_at(enc_table, idx, name, origenc);
}
if (idx >= 0) {
- set_base_encoding(enc_table, idx, origenc);
- set_encoding_const(name, rb_enc_from_index(idx));
+ set_base_encoding(enc_table, idx, origenc);
+ set_encoding_const(name, rb_enc_from_index(idx));
}
else {
rb_raise(rb_eArgError, "failed to replicate encoding");
@@ -704,7 +667,7 @@ static int
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,
- enc_dup_name);
+ enc_dup_name);
}
static int
@@ -712,7 +675,7 @@ enc_alias(struct enc_table *enc_table, const char *alias, int idx)
{
if (!valid_encoding_name_p(alias)) return -1;
if (!enc_alias_internal(enc_table, alias, idx))
- set_encoding_const(alias, enc_from_index(enc_table, idx));
+ set_encoding_const(alias, enc_from_index(enc_table, idx));
return idx;
}
@@ -723,7 +686,7 @@ rb_enc_alias(const char *alias, const char *orig)
GLOBAL_ENC_TABLE_ENTER(enc_table);
{
- enc_check_duplication(enc_table, alias);
+ enc_check_addable(enc_table, alias);
if ((idx = rb_enc_find_index(orig)) < 0) {
r = -1;
}
@@ -755,27 +718,23 @@ rb_encdb_alias(const char *alias, const char *orig)
return r;
}
-void
-rb_encdb_set_unicode(int index)
-{
- ((rb_raw_encoding *)rb_enc_from_index(index))->flags |= ONIGENC_FLAG_UNICODE;
-}
-
static void
rb_enc_init(struct enc_table *enc_table)
{
enc_table_expand(enc_table, ENCODING_COUNT + 1);
if (!enc_table->names) {
- enc_table->names = st_init_strcasetable();
+ enc_table->names = st_init_strcasetable_with_size(ENCODING_LIST_CAPA);
}
+#define OnigEncodingASCII_8BIT OnigEncodingASCII
#define ENC_REGISTER(enc) enc_register_at(enc_table, ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc)
- ENC_REGISTER(ASCII);
+ ENC_REGISTER(ASCII_8BIT);
ENC_REGISTER(UTF_8);
ENC_REGISTER(US_ASCII);
- global_enc_ascii = enc_table->list[ENCINDEX_ASCII].enc;
+ global_enc_ascii = enc_table->list[ENCINDEX_ASCII_8BIT].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
+#undef OnigEncodingASCII_8BIT
#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);
@@ -797,11 +756,12 @@ rb_enc_get_from_index(int index)
return must_encindex(index);
}
+int rb_require_internal_silent(VALUE fname);
+
static int
load_encoding(const char *name)
{
VALUE enclib = rb_sprintf("enc/%s.so", name);
- VALUE verbose = ruby_verbose;
VALUE debug = ruby_debug;
VALUE errinfo;
char *s = RSTRING_PTR(enclib) + 4, *e = RSTRING_END(enclib) - 3;
@@ -809,16 +769,14 @@ load_encoding(const char *name)
int idx;
while (s < e) {
- if (!ISALNUM(*s)) *s = '_';
- else if (ISUPPER(*s)) *s = (char)TOLOWER(*s);
- ++s;
+ if (!ISALNUM(*s)) *s = '_';
+ else if (ISUPPER(*s)) *s = (char)TOLOWER(*s);
+ ++s;
}
enclib = rb_fstring(enclib);
- ruby_verbose = Qfalse;
ruby_debug = Qfalse;
errinfo = rb_errinfo();
- loaded = rb_require_internal(enclib);
- ruby_verbose = verbose;
+ loaded = rb_require_internal_silent(enclib);
ruby_debug = debug;
rb_set_errinfo(errinfo);
@@ -846,16 +804,16 @@ enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc)
if (base) {
int i = 0;
- do {
- if (i >= enc_table->count) return -1;
- } while (enc_table->list[i].enc != base && (++i, 1));
- if (rb_enc_autoload_p(base)) {
- if (rb_enc_autoload(base) < 0) return -1;
- }
- i = enc->ruby_encoding_index;
- enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base);
+ do {
+ if (i >= enc_table->count) return -1;
+ } while (enc_table->list[i].enc != base && (++i, 1));
+ if (rb_enc_autoload_p(base)) {
+ if (rb_enc_autoload(base) < 0) return -1;
+ }
+ i = enc->ruby_encoding_index;
+ enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base);
((rb_raw_encoding *)enc)->ruby_encoding_index = i;
- i &= ENC_INDEX_MASK;
+ i &= ENC_INDEX_MASK;
return i;
}
else {
@@ -878,25 +836,23 @@ rb_enc_autoload(rb_encoding *enc)
int
rb_enc_find_index(const char *name)
{
- int i;
+ int i = enc_registered(&global_enc_table, name);
rb_encoding *enc;
- GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_registered(enc_table, name));
-
if (i < 0) {
- i = load_encoding(name);
+ i = load_encoding(name);
}
else if (!(enc = rb_enc_from_index(i))) {
- if (i != UNSPECIFIED_ENCODING) {
- rb_raise(rb_eArgError, "encoding %s is not registered", name);
- }
+ if (i != UNSPECIFIED_ENCODING) {
+ rb_raise(rb_eArgError, "encoding %s is not registered", name);
+ }
}
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;
- }
+ if (rb_enc_autoload(enc) < 0) {
+ rb_warn("failed to load encoding (%s); use ASCII-8BIT instead",
+ name);
+ return 0;
+ }
}
return i;
}
@@ -929,11 +885,11 @@ enc_capable(VALUE obj)
case T_REGEXP:
case T_FILE:
case T_SYMBOL:
- return TRUE;
+ return TRUE;
case T_DATA:
- if (is_data_encoding(obj)) return TRUE;
+ if (is_data_encoding(obj)) return TRUE;
default:
- return FALSE;
+ return FALSE;
}
}
@@ -955,11 +911,11 @@ enc_get_index_str(VALUE str)
{
int i = ENCODING_GET_INLINED(str);
if (i == ENCODING_INLINE_MAX) {
- VALUE iv;
+ VALUE iv;
#if 0
- iv = rb_ivar_get(str, rb_id_encoding());
- i = NUM2INT(iv);
+ iv = rb_ivar_get(str, rb_id_encoding());
+ i = NUM2INT(iv);
#else
/*
* Tentatively, assume ASCII-8BIT, if encoding index instance
@@ -967,7 +923,7 @@ enc_get_index_str(VALUE str)
* all instance variables are removed in `obj_free`.
*/
iv = rb_attr_get(str, rb_id_encoding());
- i = NIL_P(iv) ? ENCINDEX_ASCII : NUM2INT(iv);
+ i = NIL_P(iv) ? ENCINDEX_ASCII_8BIT : NUM2INT(iv);
#endif
}
return i;
@@ -980,31 +936,31 @@ rb_enc_get_index(VALUE obj)
VALUE tmp;
if (SPECIAL_CONST_P(obj)) {
- if (!SYMBOL_P(obj)) return -1;
- obj = rb_sym2str(obj);
+ if (!SYMBOL_P(obj)) return -1;
+ obj = rb_sym2str(obj);
}
switch (BUILTIN_TYPE(obj)) {
case T_STRING:
case T_SYMBOL:
case T_REGEXP:
- i = enc_get_index_str(obj);
- break;
+ i = enc_get_index_str(obj);
+ break;
case T_FILE:
- tmp = rb_funcallv(obj, rb_intern("internal_encoding"), 0, 0);
- if (NIL_P(tmp)) {
- tmp = rb_funcallv(obj, rb_intern("external_encoding"), 0, 0);
- }
- if (is_obj_encoding(tmp)) {
- i = enc_check_encoding(tmp);
- }
- break;
+ tmp = rb_funcallv(obj, rb_intern("internal_encoding"), 0, 0);
+ if (NIL_P(tmp)) {
+ tmp = rb_funcallv(obj, rb_intern("external_encoding"), 0, 0);
+ }
+ if (is_obj_encoding(tmp)) {
+ i = enc_check_encoding(tmp);
+ }
+ break;
case T_DATA:
- if (is_data_encoding(obj)) {
- i = enc_check_encoding(obj);
- }
- break;
+ if (is_data_encoding(obj)) {
+ i = enc_check_encoding(obj);
+ }
+ break;
default:
- break;
+ break;
}
return i;
}
@@ -1017,8 +973,8 @@ enc_set_index(VALUE obj, int idx)
}
if (idx < ENCODING_INLINE_MAX) {
- ENCODING_SET_INLINED(obj, idx);
- return;
+ ENCODING_SET_INLINED(obj, idx);
+ return;
}
ENCODING_SET_INLINED(obj, ENCODING_INLINE_MAX);
rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx));
@@ -1042,19 +998,19 @@ rb_enc_associate_index(VALUE obj, int idx)
rb_check_frozen(obj);
oldidx = rb_enc_get_index(obj);
if (oldidx == idx)
- return obj;
+ return obj;
if (SPECIAL_CONST_P(obj)) {
- rb_raise(rb_eArgError, "cannot set encoding");
+ rb_raise(rb_eArgError, "cannot set encoding");
}
enc = must_encindex(idx);
if (!ENC_CODERANGE_ASCIIONLY(obj) ||
- !rb_enc_asciicompat(enc)) {
- ENC_CODERANGE_CLEAR(obj);
+ !rb_enc_asciicompat(enc)) {
+ ENC_CODERANGE_CLEAR(obj);
}
termlen = rb_enc_mbminlen(enc);
oldtermlen = rb_enc_mbminlen(rb_enc_from_index(oldidx));
if (oldtermlen != termlen && RB_TYPE_P(obj, T_STRING)) {
- rb_str_change_terminator_length(obj, oldtermlen, termlen);
+ rb_str_change_terminator_length(obj, oldtermlen, termlen);
}
enc_set_index(obj, idx);
return obj;
@@ -1072,28 +1028,30 @@ rb_enc_get(VALUE obj)
return rb_enc_from_index(rb_enc_get_index(obj));
}
+static rb_encoding*
+rb_encoding_check(rb_encoding* enc, VALUE str1, VALUE str2)
+{
+ if (!enc)
+ rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
+ rb_enc_name(rb_enc_get(str1)),
+ rb_enc_name(rb_enc_get(str2)));
+ return enc;
+}
+
static rb_encoding* enc_compatible_str(VALUE str1, VALUE str2);
rb_encoding*
rb_enc_check_str(VALUE str1, VALUE str2)
{
rb_encoding *enc = enc_compatible_str(MUST_STRING(str1), MUST_STRING(str2));
- if (!enc)
- rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(rb_enc_get(str1)),
- rb_enc_name(rb_enc_get(str2)));
- return enc;
+ return rb_encoding_check(enc, str1, str2);
}
rb_encoding*
rb_enc_check(VALUE str1, VALUE str2)
{
rb_encoding *enc = rb_enc_compatible(str1, str2);
- if (!enc)
- rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(rb_enc_get(str1)),
- rb_enc_name(rb_enc_get(str2)));
- return enc;
+ return rb_encoding_check(enc, str1, str2);
}
static rb_encoding*
@@ -1105,48 +1063,48 @@ enc_compatible_latter(VALUE str1, VALUE str2, int idx1, int idx2)
isstr2 = RB_TYPE_P(str2, T_STRING);
if (isstr2 && RSTRING_LEN(str2) == 0)
- return enc1;
+ return enc1;
isstr1 = RB_TYPE_P(str1, T_STRING);
if (isstr1 && isstr2 && RSTRING_LEN(str1) == 0)
- return (rb_enc_asciicompat(enc1) && rb_enc_str_asciionly_p(str2)) ? enc1 : enc2;
+ return (rb_enc_asciicompat(enc1) && rb_enc_str_asciionly_p(str2)) ? enc1 : enc2;
if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
- return 0;
+ return 0;
}
/* objects whose encoding is the same of contents */
if (!isstr2 && idx2 == ENCINDEX_US_ASCII)
- return enc1;
+ return enc1;
if (!isstr1 && idx1 == ENCINDEX_US_ASCII)
- return enc2;
+ return enc2;
if (!isstr1) {
- VALUE tmp = str1;
- int idx0 = idx1;
- str1 = str2;
- str2 = tmp;
- idx1 = idx2;
- idx2 = idx0;
- idx0 = isstr1;
- isstr1 = isstr2;
- isstr2 = idx0;
+ VALUE tmp = str1;
+ int idx0 = idx1;
+ str1 = str2;
+ str2 = tmp;
+ idx1 = idx2;
+ idx2 = idx0;
+ idx0 = isstr1;
+ isstr1 = isstr2;
+ isstr2 = idx0;
}
if (isstr1) {
- int cr1, cr2;
-
- cr1 = rb_enc_str_coderange(str1);
- if (isstr2) {
- cr2 = rb_enc_str_coderange(str2);
- if (cr1 != cr2) {
- /* may need to handle ENC_CODERANGE_BROKEN */
- if (cr1 == ENC_CODERANGE_7BIT) return enc2;
- if (cr2 == ENC_CODERANGE_7BIT) return enc1;
- }
- if (cr2 == ENC_CODERANGE_7BIT) {
- return enc1;
- }
- }
- if (cr1 == ENC_CODERANGE_7BIT)
- return enc2;
+ int cr1, cr2;
+
+ cr1 = rb_enc_str_coderange(str1);
+ if (isstr2) {
+ cr2 = rb_enc_str_coderange(str2);
+ if (cr1 != cr2) {
+ /* may need to handle ENC_CODERANGE_BROKEN */
+ if (cr1 == ENC_CODERANGE_7BIT) return enc2;
+ if (cr2 == ENC_CODERANGE_7BIT) return enc1;
+ }
+ if (cr2 == ENC_CODERANGE_7BIT) {
+ return enc1;
+ }
+ }
+ if (cr1 == ENC_CODERANGE_7BIT)
+ return enc2;
}
return 0;
}
@@ -1161,10 +1119,10 @@ enc_compatible_str(VALUE str1, VALUE str2)
return 0;
if (idx1 == idx2) {
- return rb_enc_from_index(idx1);
+ return rb_enc_from_index(idx1);
}
else {
- return enc_compatible_latter(str1, str2, idx1, idx2);
+ return enc_compatible_latter(str1, str2, idx1, idx2);
}
}
@@ -1178,7 +1136,7 @@ rb_enc_compatible(VALUE str1, VALUE str2)
return 0;
if (idx1 == idx2) {
- return rb_enc_from_index(idx1);
+ return rb_enc_from_index(idx1);
}
return enc_compatible_latter(str1, str2, idx1, idx2);
@@ -1203,7 +1161,7 @@ rb_obj_encoding(VALUE obj)
{
int idx = rb_enc_get_index(obj);
if (idx < 0) {
- rb_raise(rb_eTypeError, "unknown encoding");
+ rb_raise(rb_eTypeError, "unknown encoding");
}
return rb_enc_from_encoding_index(idx & ENC_INDEX_MASK);
}
@@ -1270,36 +1228,22 @@ rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
rb_raise(rb_eArgError, "empty string");
r = rb_enc_precise_mbclen(p, e, enc);
if (!MBCLEN_CHARFOUND_P(r)) {
- rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
}
if (len_p) *len_p = MBCLEN_CHARFOUND_LEN(r);
return rb_enc_mbc_to_codepoint(p, e, enc);
}
-#undef rb_enc_codepoint
-unsigned int
-rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
-{
- return rb_enc_codepoint_len(p, e, 0, enc);
-}
-
int
rb_enc_codelen(int c, rb_encoding *enc)
{
int n = ONIGENC_CODE_TO_MBCLEN(enc,c);
if (n == 0) {
- rb_raise(rb_eArgError, "invalid codepoint 0x%x in %s", c, rb_enc_name(enc));
+ rb_raise(rb_eArgError, "invalid codepoint 0x%x in %s", c, rb_enc_name(enc));
}
return n;
}
-#undef rb_enc_code_to_mbclen
-int
-rb_enc_code_to_mbclen(int code, rb_encoding *enc)
-{
- return ONIGENC_CODE_TO_MBCLEN(enc, code);
-}
-
int
rb_enc_toupper(int c, rb_encoding *enc)
{
@@ -1327,16 +1271,16 @@ enc_inspect(VALUE self)
rb_encoding *enc;
if (!is_data_encoding(self)) {
- not_encoding(self);
+ not_encoding(self);
}
if (!(enc = DATA_PTR(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
- rb_raise(rb_eTypeError, "broken Encoding");
+ rb_raise(rb_eTypeError, "broken Encoding");
}
return rb_enc_sprintf(rb_usascii_encoding(),
- "#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self),
- rb_enc_name(enc),
- (ENC_DUMMY_P(enc) ? " (dummy)" : ""),
- rb_enc_autoload_p(enc) ? " (autoload)" : "");
+ "#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self),
+ rb_enc_name(enc),
+ (ENC_DUMMY_P(enc) ? " (dummy)" : ""),
+ rb_enc_autoload_p(enc) ? " (autoload)" : "");
}
/*
@@ -1360,8 +1304,8 @@ enc_names_i(st_data_t name, st_data_t idx, st_data_t args)
VALUE *arg = (VALUE *)args;
if ((int)idx == (int)arg[0]) {
- VALUE str = rb_fstring_cstr((char *)name);
- rb_ary_push(arg[1], str);
+ VALUE str = rb_fstring_cstr((char *)name);
+ rb_ary_push(arg[1], str);
}
return ST_CONTINUE;
}
@@ -1381,10 +1325,7 @@ enc_names(VALUE self)
args[0] = (VALUE)rb_to_encoding_index(self);
args[1] = rb_ary_new2(0);
-
- GLOBAL_ENC_TABLE_EVAL(enc_table,
- st_foreach(enc_table->names, enc_names_i, (st_data_t)args));
-
+ st_foreach(global_enc_table.names, enc_names_i, (st_data_t)args);
return args[1];
}
@@ -1410,14 +1351,7 @@ static VALUE
enc_list(VALUE klass)
{
VALUE ary = rb_ary_new2(0);
-
- RB_VM_LOCK_ENTER();
- {
- rb_ary_replace(ary, rb_default_encoding_list);
- rb_ary_concat(ary, rb_additional_encoding_list);
- }
- RB_VM_LOCK_LEAVE();
-
+ rb_ary_replace(ary, rb_encoding_list);
return ary;
}
@@ -1448,7 +1382,7 @@ enc_find(VALUE klass, VALUE enc)
{
int idx;
if (is_obj_encoding(enc))
- return enc;
+ return enc;
idx = str_to_encindex(enc);
if (idx == UNSPECIFIED_ENCODING) return Qnil;
return rb_enc_from_encoding_index(idx);
@@ -1530,7 +1464,7 @@ rb_ascii8bit_encoding(void)
int
rb_ascii8bit_encindex(void)
{
- return ENCINDEX_ASCII;
+ return ENCINDEX_ASCII_8BIT;
}
rb_encoding *
@@ -1566,15 +1500,17 @@ rb_locale_encindex(void)
if (idx < 0) idx = ENCINDEX_UTF_8;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- if (enc_registered(enc_table, "locale") < 0) {
+ if (enc_registered(&global_enc_table, "locale") < 0) {
# if defined _WIN32
- void Init_w32_codepage(void);
- Init_w32_codepage();
+ void Init_w32_codepage(void);
+ Init_w32_codepage();
# endif
- enc_alias_internal(enc_table, "locale", idx);
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ enc_alias_internal(enc_table, "locale", idx);
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
}
- GLOBAL_ENC_TABLE_LEAVE();
return idx;
}
@@ -1588,13 +1524,8 @@ rb_locale_encoding(void)
int
rb_filesystem_encindex(void)
{
- int idx;
-
- GLOBAL_ENC_TABLE_EVAL(enc_table,
- idx = enc_registered(enc_table, "filesystem"));
-
- if (idx < 0)
- idx = ENCINDEX_ASCII;
+ int idx = enc_registered(&global_enc_table, "filesystem");
+ if (idx < 0) idx = ENCINDEX_ASCII_8BIT;
return idx;
}
@@ -1617,15 +1548,22 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha
int overridden = FALSE;
if (def->index != -2)
- /* Already set */
- overridden = TRUE;
+ /* Already set */
+ overridden = TRUE;
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),
+ char *name_dup = strdup(name);
+
+ st_data_t existing_name = (st_data_t)name_dup;
+ if (st_delete(enc_table->names, &existing_name, NULL)) {
+ xfree((void *)existing_name);
+ }
+
+ st_insert(enc_table->names, (st_data_t)name_dup,
(st_data_t)UNSPECIFIED_ENCODING);
}
else {
@@ -1817,45 +1755,45 @@ set_encoding_const(const char *name, rb_encoding *enc)
if (ISDIGIT(*s)) return;
if (ISUPPER(*s)) {
- hasupper = 1;
- while (*++s && (ISALNUM(*s) || *s == '_')) {
- if (ISLOWER(*s)) haslower = 1;
- }
+ hasupper = 1;
+ while (*++s && (ISALNUM(*s) || *s == '_')) {
+ if (ISLOWER(*s)) haslower = 1;
+ }
}
if (!*s) {
- if (s - name > ENCODING_NAMELEN_MAX) return;
- valid = 1;
- rb_define_const(rb_cEncoding, name, encoding);
+ if (s - name > ENCODING_NAMELEN_MAX) return;
+ valid = 1;
+ rb_define_const(rb_cEncoding, name, encoding);
}
if (!valid || haslower) {
- size_t len = s - name;
- if (len > ENCODING_NAMELEN_MAX) return;
- if (!haslower || !hasupper) {
- do {
- if (ISLOWER(*s)) haslower = 1;
- if (ISUPPER(*s)) hasupper = 1;
- } while (*++s && (!haslower || !hasupper));
- len = s - name;
- }
- len += strlen(s);
- if (len++ > ENCODING_NAMELEN_MAX) return;
- MEMCPY(s = ALLOCA_N(char, len), name, char, len);
- name = s;
- if (!valid) {
- if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
- for (; *s; ++s) {
- if (!ISALNUM(*s)) *s = '_';
- }
- if (hasupper) {
- rb_define_const(rb_cEncoding, name, encoding);
- }
- }
- if (haslower) {
- for (s = (char *)name; *s; ++s) {
- if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
- }
- rb_define_const(rb_cEncoding, name, encoding);
- }
+ size_t len = s - name;
+ if (len > ENCODING_NAMELEN_MAX) return;
+ if (!haslower || !hasupper) {
+ do {
+ if (ISLOWER(*s)) haslower = 1;
+ if (ISUPPER(*s)) hasupper = 1;
+ } while (*++s && (!haslower || !hasupper));
+ len = s - name;
+ }
+ len += strlen(s);
+ if (len++ > ENCODING_NAMELEN_MAX) return;
+ MEMCPY(s = ALLOCA_N(char, len), name, char, len);
+ name = s;
+ if (!valid) {
+ if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
+ for (; *s; ++s) {
+ if (!ISALNUM(*s)) *s = '_';
+ }
+ if (hasupper) {
+ rb_define_const(rb_cEncoding, name, encoding);
+ }
+ }
+ if (haslower) {
+ for (s = (char *)name; *s; ++s) {
+ if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
+ }
+ rb_define_const(rb_cEncoding, name, encoding);
+ }
}
}
@@ -1885,15 +1823,8 @@ 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;
-
- 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();
-
+ VALUE ary = rb_ary_new2(global_enc_table.names->num_entries);
+ st_foreach(global_enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
return ary;
}
@@ -1906,14 +1837,14 @@ rb_enc_aliases_enc_i(st_data_t name, st_data_t orig, st_data_t arg)
VALUE key, str = rb_ary_entry(ary, idx);
if (NIL_P(str)) {
- rb_encoding *enc = rb_enc_from_index(idx);
+ rb_encoding *enc = rb_enc_from_index(idx);
- if (!enc) return ST_CONTINUE;
- if (STRCASECMP((char*)name, rb_enc_name(enc)) == 0) {
- return ST_CONTINUE;
- }
- str = rb_fstring_cstr(rb_enc_name(enc));
- rb_ary_store(ary, idx, str);
+ if (!enc) return ST_CONTINUE;
+ if (STRCASECMP((char*)name, rb_enc_name(enc)) == 0) {
+ return ST_CONTINUE;
+ }
+ str = rb_fstring_cstr(rb_enc_name(enc));
+ rb_ary_store(ary, idx, str);
}
key = rb_fstring_cstr((char *)name);
rb_hash_aset(aliases, key, str);
@@ -1939,210 +1870,39 @@ rb_enc_aliases(VALUE klass)
aliases[0] = rb_hash_new();
aliases[1] = rb_ary_new();
- GLOBAL_ENC_TABLE_EVAL(enc_table,
- st_foreach(enc_table->names, rb_enc_aliases_enc_i, (st_data_t)aliases));
+ st_foreach(global_enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
return aliases[0];
}
/*
- * An Encoding instance represents a character encoding usable in Ruby. It is
- * defined as a constant under the Encoding namespace. It has a name and
- * optionally, aliases:
- *
- * Encoding::ISO_8859_1.name
- * #=> "ISO-8859-1"
- *
- * Encoding::ISO_8859_1.names
- * #=> ["ISO-8859-1", "ISO8859-1"]
- *
- * Ruby methods dealing with encodings return or accept Encoding instances as
- * arguments (when a method accepts an Encoding instance as an argument, it
- * can be passed an Encoding name or alias instead).
- *
- * "some string".encoding
- * #=> #<Encoding:UTF-8>
- *
- * string = "some string".encode(Encoding::ISO_8859_1)
- * #=> "some string"
- * string.encoding
- * #=> #<Encoding:ISO-8859-1>
- *
- * "some string".encode "ISO-8859-1"
- * #=> "some string"
- *
- * Encoding::ASCII_8BIT is a special encoding that is usually used for
- * a byte string, not a character string. But as the name insists, its
- * characters in the range of ASCII are considered as ASCII
- * characters. This is useful when you use ASCII-8BIT characters with
- * other ASCII compatible characters.
- *
- * == Changing an encoding
- *
- * The associated Encoding of a String can be changed in two different ways.
- *
- * First, it is possible to set the Encoding of a string to a new Encoding
- * without changing the internal byte representation of the string, with
- * String#force_encoding. This is how you can tell Ruby the correct encoding
- * of a string.
- *
- * string
- * #=> "R\xC3\xA9sum\xC3\xA9"
- * string.encoding
- * #=> #<Encoding:ISO-8859-1>
- * string.force_encoding(Encoding::UTF_8)
- * #=> "R\u00E9sum\u00E9"
- *
- * Second, it is possible to transcode a string, i.e. translate its internal
- * byte representation to another encoding. Its associated encoding is also
- * set to the other encoding. See String#encode for the various forms of
- * transcoding, and the Encoding::Converter class for additional control over
- * the transcoding process.
+ * An \Encoding instance represents a character encoding usable in Ruby.
+ * It is defined as a constant under the \Encoding namespace.
+ * It has a name and, optionally, aliases:
*
- * string
- * #=> "R\u00E9sum\u00E9"
- * string.encoding
- * #=> #<Encoding:UTF-8>
- * string = string.encode!(Encoding::ISO_8859_1)
- * #=> "R\xE9sum\xE9"
- * string.encoding
- * #=> #<Encoding::ISO-8859-1>
+ * Encoding::US_ASCII.name # => "US-ASCII"
+ * Encoding::US_ASCII.names # => ["US-ASCII", "ASCII", "ANSI_X3.4-1968", "646"]
*
- * == Script encoding
+ * A Ruby method that accepts an encoding as an argument will accept:
*
- * All Ruby script code has an associated Encoding which any String literal
- * created in the source code will be associated to.
+ * - An \Encoding object.
+ * - The name of an encoding.
+ * - An alias for an encoding name.
*
- * The default script encoding is Encoding::UTF_8 after v2.0, but it
- * can be changed by a magic comment on the first line of the source
- * code file (or second line, if there is a shebang line on the
- * first). The comment must contain the word <code>coding</code> or
- * <code>encoding</code>, followed by a colon, space and the Encoding
- * name or alias:
+ * These are equivalent:
*
- * # encoding: UTF-8
+ * 'foo'.encode(Encoding::US_ASCII) # Encoding object.
+ * 'foo'.encode('US-ASCII') # Encoding name.
+ * 'foo'.encode('ASCII') # Encoding alias.
*
- * "some string".encoding
- * #=> #<Encoding:UTF-8>
+ * For a full discussion of encodings and their uses,
+ * see {the Encodings document}[rdoc-ref:encodings.rdoc].
*
- * The <code>__ENCODING__</code> keyword returns the script encoding of the file
- * which the keyword is written:
- *
- * # encoding: ISO-8859-1
- *
- * __ENCODING__
- * #=> #<Encoding:ISO-8859-1>
- *
- * <code>ruby -K</code> will change the default locale encoding, but this is
- * not recommended. Ruby source files should declare its script encoding by a
- * magic comment even when they only depend on US-ASCII strings or regular
- * expressions.
- *
- * == Locale encoding
- *
- * The default encoding of the environment. Usually derived from locale.
- *
- * see Encoding.locale_charmap, Encoding.find('locale')
- *
- * == Filesystem encoding
- *
- * The default encoding of strings from the filesystem of the environment.
- * This is used for strings of file names or paths.
- *
- * see Encoding.find('filesystem')
- *
- * == External encoding
- *
- * Each IO object has an external encoding which indicates the encoding that
- * Ruby will use to read its data. By default Ruby sets the external encoding
- * of an IO object to the default external encoding. The default external
- * encoding is set by locale encoding or the interpreter <code>-E</code> option.
- * Encoding.default_external returns the current value of the external
- * encoding.
- *
- * ENV["LANG"]
- * #=> "UTF-8"
- * Encoding.default_external
- * #=> #<Encoding:UTF-8>
- *
- * $ ruby -E ISO-8859-1 -e "p Encoding.default_external"
- * #<Encoding:ISO-8859-1>
- *
- * $ LANG=C ruby -e 'p Encoding.default_external'
- * #<Encoding:US-ASCII>
- *
- * The default external encoding may also be set through
- * Encoding.default_external=, but you should not do this as strings created
- * before and after the change will have inconsistent encodings. Instead use
- * <code>ruby -E</code> to invoke ruby with the correct external encoding.
- *
- * When you know that the actual encoding of the data of an IO object is not
- * the default external encoding, you can reset its external encoding with
- * IO#set_encoding or set it at IO object creation (see IO.new options).
- *
- * == Internal encoding
- *
- * To process the data of an IO object which has an encoding different
- * from its external encoding, you can set its internal encoding. Ruby will use
- * this internal encoding to transcode the data when it is read from the IO
- * object.
- *
- * Conversely, when data is written to the IO object it is transcoded from the
- * internal encoding to the external encoding of the IO object.
- *
- * The internal encoding of an IO object can be set with
- * IO#set_encoding or at IO object creation (see IO.new options).
- *
- * The internal encoding is optional and when not set, the Ruby default
- * internal encoding is used. If not explicitly set this default internal
- * encoding is +nil+ meaning that by default, no transcoding occurs.
- *
- * The default internal encoding can be set with the interpreter option
- * <code>-E</code>. Encoding.default_internal returns the current internal
- * encoding.
- *
- * $ ruby -e 'p Encoding.default_internal'
- * nil
- *
- * $ ruby -E ISO-8859-1:UTF-8 -e "p [Encoding.default_external, \
- * Encoding.default_internal]"
- * [#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>]
- *
- * The default internal encoding may also be set through
- * Encoding.default_internal=, but you should not do this as strings created
- * before and after the change will have inconsistent encodings. Instead use
- * <code>ruby -E</code> to invoke ruby with the correct internal encoding.
- *
- * == IO encoding example
- *
- * In the following example a UTF-8 encoded string "R\u00E9sum\u00E9" is transcoded for
- * output to ISO-8859-1 encoding, then read back in and transcoded to UTF-8:
- *
- * string = "R\u00E9sum\u00E9"
- *
- * open("transcoded.txt", "w:ISO-8859-1") do |io|
- * io.write(string)
- * end
- *
- * puts "raw text:"
- * p File.binread("transcoded.txt")
- * puts
- *
- * open("transcoded.txt", "r:ISO-8859-1:UTF-8") do |io|
- * puts "transcoded text:"
- * p io.read
- * end
- *
- * While writing the file, the internal encoding is not specified as it is
- * only necessary for reading. While reading the file both the internal and
- * external encoding must be specified to obtain the correct result.
- *
- * $ ruby t.rb
- * raw text:
- * "R\xE9sum\xE9"
- *
- * transcoded text:
- * "R\u00E9sum\u00E9"
+ * Encoding::ASCII_8BIT is a special-purpose encoding that is usually used for
+ * a string of bytes, not a string of characters.
+ * But as the name indicates, its characters in the ASCII range
+ * are considered as ASCII characters.
+ * This is useful when you use other ASCII-compatible encodings.
*
*/
@@ -2179,18 +1939,12 @@ Init_Encoding(void)
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);
+ list = rb_encoding_list = rb_ary_new2(ENCODING_LIST_CAPA);
RBASIC_CLEAR_CLASS(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));
+ rb_ary_push(list, enc_new(enc_table->list[i].enc));
}
rb_marshal_define_compat(rb_cEncoding, Qnil, 0, enc_m_loader);
@@ -2207,5 +1961,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)
{
- GLOBAL_ENC_TABLE_EVAL(enc_table, st_foreach(enc_table->names, func, arg));
+ st_foreach(global_enc_table.names, func, arg);
}
diff --git a/enum.c b/enum.c
index c576ba7306..b3c715e0a1 100644
--- a/enum.c
+++ b/enum.c
@@ -65,9 +65,9 @@ static VALUE
enum_yield(int argc, VALUE ary)
{
if (argc > 1)
- return rb_yield_force_blockarg(ary);
+ return rb_yield_force_blockarg(ary);
if (argc == 1)
- return rb_yield(ary);
+ return rb_yield(ary);
return rb_yield_values2(0, 0);
}
@@ -77,9 +77,9 @@ enum_yield_array(VALUE ary)
long len = RARRAY_LEN(ary);
if (len > 1)
- return rb_yield_force_blockarg(ary);
+ return rb_yield_force_blockarg(ary);
if (len == 1)
- return rb_yield(RARRAY_AREF(ary, 0));
+ return rb_yield(RARRAY_AREF(ary, 0));
return rb_yield_values2(0, 0);
}
@@ -90,7 +90,7 @@ grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
- rb_ary_push(memo->v2, i);
+ rb_ary_push(memo->v2, i);
}
return Qnil;
}
@@ -106,7 +106,7 @@ grep_regexp_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
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);
+ rb_ary_push(memo->v2, i);
}
return Qnil;
}
@@ -118,7 +118,7 @@ grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
- rb_ary_push(memo->v2, enum_yield(argc, i));
+ rb_ary_push(memo->v2, enum_yield(argc, i));
}
return Qnil;
}
@@ -130,14 +130,14 @@ enum_grep0(VALUE obj, VALUE pat, VALUE test)
struct MEMO *memo = MEMO_NEW(pat, ary, test);
rb_block_call_func_t fn;
if (rb_block_given_p()) {
- fn = grep_iter_i;
+ 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;
+ fn = grep_regexp_i;
}
else {
- fn = grep_i;
+ fn = grep_i;
}
rb_block_call(obj, id_each, 0, 0, fn, (VALUE)memo);
@@ -214,13 +214,13 @@ static void
imemo_count_up(struct MEMO *memo)
{
if (memo->flags & COUNT_BIGNUM) {
- MEMO_V3_SET(memo, rb_int_succ(memo->u3.value));
+ MEMO_V3_SET(memo, rb_int_succ(memo->u3.value));
}
else if (++memo->u3.cnt == 0) {
- /* overflow */
- unsigned long buf[2] = {0, 1};
- MEMO_V3_SET(memo, rb_big_unpack(buf, 2));
- memo->flags |= COUNT_BIGNUM;
+ /* overflow */
+ unsigned long buf[2] = {0, 1};
+ MEMO_V3_SET(memo, rb_big_unpack(buf, 2));
+ memo->flags |= COUNT_BIGNUM;
}
}
@@ -228,10 +228,10 @@ static VALUE
imemo_count_value(struct MEMO *memo)
{
if (memo->flags & COUNT_BIGNUM) {
- return memo->u3.value;
+ return memo->u3.value;
}
else {
- return ULONG2NUM(memo->u3.cnt);
+ return ULONG2NUM(memo->u3.cnt);
}
}
@@ -243,7 +243,7 @@ count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
ENUM_WANT_SVALUE();
if (rb_equal(i, memo->v1)) {
- imemo_count_up(memo);
+ imemo_count_up(memo);
}
return Qnil;
}
@@ -254,7 +254,7 @@ count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
struct MEMO *memo = MEMO_CAST(memop);
if (RTEST(rb_yield_values2(argc, argv))) {
- imemo_count_up(memo);
+ imemo_count_up(memo);
}
return Qnil;
}
@@ -302,18 +302,18 @@ enum_count(int argc, VALUE *argv, VALUE obj)
rb_block_call_func *func;
if (argc == 0) {
- if (rb_block_given_p()) {
- func = count_iter_i;
- }
- else {
- func = count_all_i;
- }
+ if (rb_block_given_p()) {
+ func = count_iter_i;
+ }
+ else {
+ func = count_all_i;
+ }
}
else {
- rb_scan_args(argc, argv, "1", &item);
- if (rb_block_given_p()) {
- rb_warn("given block not used");
- }
+ rb_scan_args(argc, argv, "1", &item);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
func = count_i;
}
@@ -328,10 +328,10 @@ find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
ENUM_WANT_SVALUE();
if (RTEST(enum_yield(argc, i))) {
- struct MEMO *memo = MEMO_CAST(memop);
- MEMO_V1_SET(memo, i);
- memo->u3.cnt = 1;
- rb_iter_break();
+ struct MEMO *memo = MEMO_CAST(memop);
+ MEMO_V1_SET(memo, i);
+ memo->u3.cnt = 1;
+ rb_iter_break();
}
return Qnil;
}
@@ -368,10 +368,10 @@ enum_find(int argc, VALUE *argv, VALUE obj)
memo = MEMO_NEW(Qundef, 0, 0);
rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
if (memo->u3.cnt) {
- return memo->v1;
+ return memo->v1;
}
if (!NIL_P(if_none)) {
- return rb_funcallv(if_none, id_call, 0, 0);
+ return rb_funcallv(if_none, id_call, 0, 0);
}
return Qnil;
}
@@ -384,8 +384,8 @@ find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
ENUM_WANT_SVALUE();
if (rb_equal(i, memo->v2)) {
- MEMO_V1_SET(memo, imemo_count_value(memo));
- rb_iter_break();
+ MEMO_V1_SET(memo, imemo_count_value(memo));
+ rb_iter_break();
}
imemo_count_up(memo);
return Qnil;
@@ -397,8 +397,8 @@ find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
struct MEMO *memo = MEMO_CAST(memop);
if (RTEST(rb_yield_values2(argc, argv))) {
- MEMO_V1_SET(memo, imemo_count_value(memo));
- rb_iter_break();
+ MEMO_V1_SET(memo, imemo_count_value(memo));
+ rb_iter_break();
}
imemo_count_up(memo);
return Qnil;
@@ -440,10 +440,10 @@ enum_find_index(int argc, VALUE *argv, VALUE obj)
func = find_index_iter_i;
}
else {
- rb_scan_args(argc, argv, "1", &condition_value);
- if (rb_block_given_p()) {
- rb_warn("given block not used");
- }
+ rb_scan_args(argc, argv, "1", &condition_value);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
func = find_index_i;
}
@@ -458,7 +458,7 @@ find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
ENUM_WANT_SVALUE();
if (RTEST(enum_yield(argc, i))) {
- rb_ary_push(ary, i);
+ rb_ary_push(ary, i);
}
return Qnil;
}
@@ -566,7 +566,7 @@ reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
ENUM_WANT_SVALUE();
if (!RTEST(enum_yield(argc, i))) {
- rb_ary_push(ary, i);
+ rb_ary_push(ary, i);
}
return Qnil;
}
@@ -658,10 +658,10 @@ flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
tmp = rb_check_array_type(i);
if (NIL_P(tmp)) {
- rb_ary_push(ary, i);
+ rb_ary_push(ary, i);
}
else {
- rb_ary_concat(ary, tmp);
+ rb_ary_concat(ary, tmp);
}
return Qnil;
}
@@ -700,23 +700,20 @@ enum_flat_map(VALUE obj)
/*
* call-seq:
- * enum.to_a(*args) -> array
- * enum.entries(*args) -> array
+ * to_a -> array
*
- * Returns an array containing the items in <i>enum</i>.
+ * Returns an array containing the items in +self+:
*
- * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
- * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
+ * (0..4).to_a # => [0, 1, 2, 3, 4]
*
- * require 'prime'
- * Prime.entries 10 #=> [2, 3, 5, 7]
+ * Enumerable#entries is an alias for Enumerable#to_a.
*/
static VALUE
enum_to_a(int argc, VALUE *argv, VALUE obj)
{
VALUE ary = rb_ary_new();
- rb_block_call(obj, id_each, argc, argv, collect_all, ary);
+ rb_block_call_kw(obj, id_each, argc, argv, collect_all, ary, RB_PASS_CALLED_KEYWORDS);
return ary;
}
@@ -749,20 +746,23 @@ enum_to_h_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
/*
* call-seq:
- * enum.to_h(*args) -> hash
- * enum.to_h(*args) {...} -> hash
+ * to_h -> hash
+ * to_h {|element| ... } -> hash
+ *
+ * When +self+ consists of 2-element arrays,
+ * returns a hash each of whose entries is the key-value pair
+ * formed from one of those arrays:
*
- * Returns the result of interpreting <i>enum</i> as a list of
- * <tt>[key, value]</tt> pairs.
+ * [[:foo, 0], [:bar, 1], [:baz, 2]].to_h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * %i[hello world].each_with_index.to_h
- * # => {:hello => 0, :world => 1}
+ * When a block is given, the block is called with each element of +self+;
+ * the block should return a 2-element array which becomes a key-value pair
+ * in the returned hash:
*
- * If a block is given, the results of the block on each element of
- * the enum will be used as pairs.
+ * (0..3).to_h {|i| [i, i ** 2]} # => {0=>0, 1=>1, 2=>4, 3=>9}
*
- * (1..5).to_h {|x| [x, x ** 2]}
- * #=> {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}
+ * Raises an exception if an element of +self+ is not a 2-element array,
+ * and a block is not passed.
*/
static VALUE
@@ -779,11 +779,11 @@ inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
ENUM_WANT_SVALUE();
- if (memo->v1 == Qundef) {
- MEMO_V1_SET(memo, i);
+ if (UNDEF_P(memo->v1)) {
+ MEMO_V1_SET(memo, i);
}
else {
- MEMO_V1_SET(memo, rb_yield_values(2, memo->v1, i));
+ MEMO_V1_SET(memo, rb_yield_values(2, memo->v1, i));
}
return Qnil;
}
@@ -796,18 +796,18 @@ inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
ENUM_WANT_SVALUE();
- if (memo->v1 == Qundef) {
- MEMO_V1_SET(memo, i);
+ if (UNDEF_P(memo->v1)) {
+ MEMO_V1_SET(memo, i);
}
else if (SYMBOL_P(name = memo->u3.value)) {
- const ID mid = SYM2ID(name);
- MEMO_V1_SET(memo, rb_funcallv_public(memo->v1, mid, 1, &i));
+ const ID mid = SYM2ID(name);
+ MEMO_V1_SET(memo, rb_funcallv_public(memo->v1, mid, 1, &i));
}
else {
- VALUE args[2];
- args[0] = name;
- args[1] = i;
- MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
+ VALUE args[2];
+ args[0] = name;
+ args[1] = i;
+ MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
}
return Qnil;
}
@@ -820,9 +820,9 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
long i, n;
if (RARRAY_LEN(ary) == 0)
- return init == Qundef ? Qnil : init;
+ return UNDEF_P(init) ? Qnil : init;
- if (init == Qundef) {
+ if (UNDEF_P(init)) {
v = RARRAY_AREF(ary, 0);
i = 1;
if (RARRAY_LEN(ary) == 1)
@@ -835,9 +835,9 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
id = SYM2ID(op);
if (id == idPLUS) {
- if (RB_INTEGER_TYPE_P(v) &&
- rb_method_basic_definition_p(rb_cInteger, idPLUS) &&
- rb_obj_respond_to(v, idPLUS, FALSE)) {
+ if (RB_INTEGER_TYPE_P(v) &&
+ rb_method_basic_definition_p(rb_cInteger, idPLUS) &&
+ rb_obj_respond_to(v, idPLUS, FALSE)) {
n = 0;
for (; i < RARRAY_LEN(ary); i++) {
e = RARRAY_AREF(ary, i);
@@ -848,7 +848,7 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
n = 0;
}
}
- else if (RB_TYPE_P(e, T_BIGNUM))
+ else if (RB_BIGNUM_TYPE_P(e))
v = rb_big_plus(e, v);
else
goto not_integer;
@@ -871,48 +871,136 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op)
/*
* call-seq:
- * enum.inject(initial, sym) -> obj
- * enum.inject(sym) -> obj
- * enum.inject(initial) { |memo, obj| block } -> obj
- * enum.inject { |memo, obj| block } -> obj
- * enum.reduce(initial, sym) -> obj
- * enum.reduce(sym) -> obj
- * enum.reduce(initial) { |memo, obj| block } -> obj
- * enum.reduce { |memo, obj| block } -> obj
- *
- * Combines all elements of <i>enum</i> by applying a binary
- * operation, specified by a block or a symbol that names a
- * method or operator.
- *
- * The <i>inject</i> and <i>reduce</i> methods are aliases. There
- * is no performance benefit to either.
- *
- * If you specify a block, then for each element in <i>enum</i>
- * the block is passed an accumulator value (<i>memo</i>) and the element.
- * If you specify a symbol instead, then each element in the collection
- * will be passed to the named method of <i>memo</i>.
- * In either case, the result becomes the new value for <i>memo</i>.
- * At the end of the iteration, the final value of <i>memo</i> is the
- * return value for the method.
- *
- * If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
- * then the first element of collection is used as the initial value
- * of <i>memo</i>.
- *
- *
- * # Sum some numbers
- * (5..10).reduce(:+) #=> 45
- * # Same using a block and inject
- * (5..10).inject { |sum, n| sum + n } #=> 45
- * # Multiply some numbers
- * (5..10).reduce(1, :*) #=> 151200
- * # Same using a block
- * (5..10).inject(1) { |product, n| product * n } #=> 151200
- * # find the longest word
- * longest = %w{ cat sheep bear }.inject do |memo, word|
- * memo.length > word.length ? memo : word
- * end
- * longest #=> "sheep"
+ * inject(symbol) -> object
+ * inject(initial_operand, symbol) -> object
+ * inject {|memo, operand| ... } -> object
+ * inject(initial_operand) {|memo, operand| ... } -> object
+ *
+ * Returns an object formed from operands via either:
+ *
+ * - A method named by +symbol+.
+ * - A block to which each operand is passed.
+ *
+ * With method-name argument +symbol+,
+ * combines operands using the method:
+ *
+ * # Sum, without initial_operand.
+ * (1..4).inject(:+) # => 10
+ * # Sum, with initial_operand.
+ * (1..4).inject(10, :+) # => 20
+ *
+ * With a block, passes each operand to the block:
+ *
+ * # Sum of squares, without initial_operand.
+ * (1..4).inject {|sum, n| sum + n*n } # => 30
+ * # Sum of squares, with initial_operand.
+ * (1..4).inject(2) {|sum, n| sum + n*n } # => 32
+ *
+ * <b>Operands</b>
+ *
+ * If argument +initial_operand+ is not given,
+ * the operands for +inject+ are simply the elements of +self+.
+ * Example calls and their operands:
+ *
+ * - <tt>(1..4).inject(:+)</tt>:: <tt>[1, 2, 3, 4]</tt>.
+ * - <tt>(1...4).inject(:+)</tt>:: <tt>[1, 2, 3]</tt>.
+ * - <tt>('a'..'d').inject(:+)</tt>:: <tt>['a', 'b', 'c', 'd']</tt>.
+ * - <tt>('a'...'d').inject(:+)</tt>:: <tt>['a', 'b', 'c']</tt>.
+ *
+ * Examples with first operand (which is <tt>self.first</tt>) of various types:
+ *
+ * # Integer.
+ * (1..4).inject(:+) # => 10
+ * # Float.
+ * [1.0, 2, 3, 4].inject(:+) # => 10.0
+ * # Character.
+ * ('a'..'d').inject(:+) # => "abcd"
+ * # Complex.
+ * [Complex(1, 2), 3, 4].inject(:+) # => (8+2i)
+ *
+ * If argument +initial_operand+ is given,
+ * the operands for +inject+ are that value plus the elements of +self+.
+ * Example calls their operands:
+ *
+ * - <tt>(1..4).inject(10, :+)</tt>:: <tt>[10, 1, 2, 3, 4]</tt>.
+ * - <tt>(1...4).inject(10, :+)</tt>:: <tt>[10, 1, 2, 3]</tt>.
+ * - <tt>('a'..'d').inject('e', :+)</tt>:: <tt>['e', 'a', 'b', 'c', 'd']</tt>.
+ * - <tt>('a'...'d').inject('e', :+)</tt>:: <tt>['e', 'a', 'b', 'c']</tt>.
+ *
+ * Examples with +initial_operand+ of various types:
+ *
+ * # Integer.
+ * (1..4).inject(2, :+) # => 12
+ * # Float.
+ * (1..4).inject(2.0, :+) # => 12.0
+ * # String.
+ * ('a'..'d').inject('foo', :+) # => "fooabcd"
+ * # Array.
+ * %w[a b c].inject(['x'], :push) # => ["x", "a", "b", "c"]
+ * # Complex.
+ * (1..4).inject(Complex(2, 2), :+) # => (12+2i)
+ *
+ * <b>Combination by Given \Method</b>
+ *
+ * If the method-name argument +symbol+ is given,
+ * the operands are combined by that method:
+ *
+ * - The first and second operands are combined.
+ * - That result is combined with the third operand.
+ * - That result is combined with the fourth operand.
+ * - And so on.
+ *
+ * The return value from +inject+ is the result of the last combination.
+ *
+ * This call to +inject+ computes the sum of the operands:
+ *
+ * (1..4).inject(:+) # => 10
+ *
+ * Examples with various methods:
+ *
+ * # Integer addition.
+ * (1..4).inject(:+) # => 10
+ * # Integer multiplication.
+ * (1..4).inject(:*) # => 24
+ * # Character range concatenation.
+ * ('a'..'d').inject('', :+) # => "abcd"
+ * # String array concatenation.
+ * %w[foo bar baz].inject('', :+) # => "foobarbaz"
+ * # Hash update.
+ * h = [{foo: 0, bar: 1}, {baz: 2}, {bat: 3}].inject(:update)
+ * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
+ * # Hash conversion to nested arrays.
+ * h = {foo: 0, bar: 1}.inject([], :push)
+ * h # => [[:foo, 0], [:bar, 1]]
+ *
+ * <b>Combination by Given Block</b>
+ *
+ * If a block is given, the operands are passed to the block:
+ *
+ * - The first call passes the first and second operands.
+ * - The second call passes the result of the first call,
+ * along with the third operand.
+ * - The third call passes the result of the second call,
+ * along with the fourth operand.
+ * - And so on.
+ *
+ * The return value from +inject+ is the return value from the last block call.
+ *
+ * This call to +inject+ gives a block
+ * that writes the memo and element, and also sums the elements:
+ *
+ * (1..4).inject do |memo, element|
+ * p "Memo: #{memo}; element: #{element}"
+ * memo + element
+ * end # => 10
+ *
+ * Output:
+ *
+ * "Memo: 1; element: 2"
+ * "Memo: 3; element: 3"
+ * "Memo: 6; element: 4"
+ *
+ * Enumerable#reduce is an alias for Enumerable#inject.
*
*/
static VALUE
@@ -922,28 +1010,36 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
VALUE init, op;
rb_block_call_func *iter = inject_i;
ID id;
+ int num_args;
+
+ if (rb_block_given_p()) {
+ num_args = rb_scan_args(argc, argv, "02", &init, &op);
+ }
+ else {
+ num_args = rb_scan_args(argc, argv, "11", &init, &op);
+ }
- switch (rb_scan_args(argc, argv, "02", &init, &op)) {
+ switch (num_args) {
case 0:
- init = Qundef;
- break;
+ init = Qundef;
+ break;
case 1:
- if (rb_block_given_p()) {
- break;
- }
- id = rb_check_id(&init);
- op = id ? ID2SYM(id) : init;
- init = Qundef;
- iter = inject_op_i;
- break;
+ if (rb_block_given_p()) {
+ break;
+ }
+ id = rb_check_id(&init);
+ op = id ? ID2SYM(id) : init;
+ init = Qundef;
+ iter = inject_op_i;
+ break;
case 2:
- if (rb_block_given_p()) {
- rb_warning("given block not used");
- }
- id = rb_check_id(&op);
- if (id) op = ID2SYM(id);
- iter = inject_op_i;
- break;
+ if (rb_block_given_p()) {
+ rb_warning("given block not used");
+ }
+ id = rb_check_id(&op);
+ if (id) op = ID2SYM(id);
+ iter = inject_op_i;
+ break;
}
if (iter == inject_op_i &&
@@ -955,7 +1051,7 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
memo = MEMO_NEW(init, Qnil, op);
rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
- if (memo->v1 == Qundef) return Qnil;
+ if (UNDEF_P(memo->v1)) return Qnil;
return memo->v1;
}
@@ -967,10 +1063,10 @@ partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
ENUM_WANT_SVALUE();
if (RTEST(enum_yield(argc, i))) {
- ary = memo->v1;
+ ary = memo->v1;
}
else {
- ary = memo->v2;
+ ary = memo->v2;
}
rb_ary_push(ary, i);
return Qnil;
@@ -978,16 +1074,29 @@ partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
/*
* call-seq:
- * enum.partition { |obj| block } -> [ true_array, false_array ]
- * enum.partition -> an_enumerator
+ * partition {|element| ... } -> [true_array, false_array]
+ * partition -> enumerator
+ *
+ * With a block given, returns an array of two arrays:
+ *
+ * - The first having those elements for which the block returns a truthy value.
+ * - The other having all other elements.
*
- * Returns two arrays, the first containing the elements of
- * <i>enum</i> for which the block evaluates to true, the second
- * containing the rest.
+ * Examples:
*
- * If no block is given, an enumerator is returned instead.
+ * p = (1..4).partition {|i| i.even? }
+ * p # => [[2, 4], [1, 3]]
+ * p = ('a'..'d').partition {|c| c < 'c' }
+ * p # => [["a", "b"], ["c", "d"]]
+ * h = {foo: 0, bar: 1, baz: 2, bat: 3}
+ * p = h.partition {|key, value| key.start_with?('b') }
+ * p # => [[[:bar, 1], [:baz, 2], [:bat, 3]], [[:foo, 0]]]
+ * p = h.partition {|key, value| value < 2 }
+ * p # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]]]
*
- * (1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
+ * With no block given, returns an Enumerator.
+ *
+ * Related: Enumerable#group_by.
*
*/
@@ -1015,27 +1124,34 @@ group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
group = enum_yield(argc, i);
values = rb_hash_aref(hash, group);
if (!RB_TYPE_P(values, T_ARRAY)) {
- values = rb_ary_new3(1, i);
- rb_hash_aset(hash, group, values);
+ values = rb_ary_new3(1, i);
+ rb_hash_aset(hash, group, values);
}
else {
- rb_ary_push(values, i);
+ rb_ary_push(values, i);
}
return Qnil;
}
/*
* call-seq:
- * enum.group_by { |obj| block } -> a_hash
- * enum.group_by -> an_enumerator
+ * group_by {|element| ... } -> hash
+ * group_by -> enumerator
+ *
+ * With a block given returns a hash:
*
- * Groups the collection by result of the block. Returns a hash where the
- * keys are the evaluated result from the block and the values are
- * arrays of elements in the collection that correspond to the key.
+ * - Each key is a return value from the block.
+ * - Each value is an array of those elements for which the block returned that key.
*
- * If no block is given an enumerator is returned.
+ * Examples:
*
- * (1..6).group_by { |i| i%3 } #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+ * g = (1..6).group_by {|i| i%3 }
+ * g # => {1=>[1, 4], 2=>[2, 5], 0=>[3, 6]}
+ * h = {foo: 0, bar: 1, baz: 0, bat: 1}
+ * g = h.group_by {|key, value| value }
+ * g # => {0=>[[:foo, 0], [:baz, 0]], 1=>[[:bar, 1], [:bat, 1]]}
+ *
+ * With no block given, returns an Enumerator.
*
*/
@@ -1085,18 +1201,30 @@ tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
/*
* call-seq:
- * enum.tally -> a_hash
- * enum.tally(a_hash) -> a_hash
+ * tally -> new_hash
+ * tally(hash) -> hash
+ *
+ * Returns a hash containing the counts of equal elements:
*
- * Tallies the collection, i.e., counts the occurrences of each element.
- * Returns a hash with the elements of the collection as keys and the
- * corresponding counts as values.
+ * - Each key is an element of +self+.
+ * - Each value is the number elements equal to that key.
*
- * ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
+ * With no argument:
+ *
+ * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}
+ *
+ * With a hash argument, that hash is used for the tally (instead of a new hash),
+ * and is returned;
+ * this may be useful for accumulating tallies across multiple enumerables:
+ *
+ * hash = {}
+ * hash = %w[a c d b c a].tally(hash)
+ * hash # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1}
+ * hash = %w[b a z].tally(hash)
+ * hash # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1}
+ * hash = %w[b a m].tally(hash)
+ * hash # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=> 1}
*
- * If a hash is given, the number of occurrences is added to each value
- * in the hash, and the hash is returned. The value corresponding to
- * each element must be an integer.
*/
static VALUE
@@ -1104,7 +1232,7 @@ enum_tally(int argc, VALUE *argv, VALUE obj)
{
VALUE hash;
if (rb_check_arity(argc, 0, 1)) {
- hash = rb_convert_type(argv[0], T_HASH, "Hash", "to_hash");
+ hash = rb_to_hash_type(argv[0]);
rb_check_frozen(hash);
}
else {
@@ -1131,18 +1259,26 @@ static VALUE enum_take(VALUE obj, VALUE n);
/*
* call-seq:
- * enum.first -> obj or nil
- * enum.first(n) -> an_array
+ * first -> element or nil
+ * first(n) -> array
+ *
+ * Returns the first element or elements.
+ *
+ * With no argument, returns the first element, or +nil+ if there is none:
*
- * Returns the first element, or the first +n+ elements, of the enumerable.
- * If the enumerable is empty, the first form returns <code>nil</code>, and the
- * second form returns an empty array.
+ * (1..4).first # => 1
+ * %w[a b c].first # => "a"
+ * {foo: 1, bar: 1, baz: 2}.first # => [:foo, 1]
+ * [].first # => nil
*
- * %w[foo bar baz].first #=> "foo"
- * %w[foo bar baz].first(2) #=> ["foo", "bar"]
- * %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
- * [].first #=> nil
- * [].first(10) #=> []
+ * With integer argument +n+, returns an array
+ * containing the first +n+ elements that exist:
+ *
+ * (1..4).first(2) # => [1, 2]
+ * %w[a b c d].first(3) # => ["a", "b", "c"]
+ * %w[a b c d].first(50) # => ["a", "b", "c", "d"]
+ * {foo: 1, bar: 1, baz: 2}.first(2) # => [[:foo, 1], [:bar, 1]]
+ * [].first(2) # => []
*
*/
@@ -1152,37 +1288,44 @@ enum_first(int argc, VALUE *argv, VALUE obj)
struct MEMO *memo;
rb_check_arity(argc, 0, 1);
if (argc > 0) {
- return enum_take(obj, argv[0]);
+ return enum_take(obj, argv[0]);
}
else {
- memo = MEMO_NEW(Qnil, 0, 0);
- rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
- return memo->v1;
+ memo = MEMO_NEW(Qnil, 0, 0);
+ rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
+ return memo->v1;
}
}
-
/*
* call-seq:
- * enum.sort -> array
- * enum.sort { |a, b| block } -> array
+ * sort -> array
+ * sort {|a, b| ... } -> array
+ *
+ * Returns an array containing the sorted elements of +self+.
+ * The ordering of equal elements is indeterminate and may be unstable.
+ *
+ * With no block given, the sort compares
+ * using the elements' own method <tt><=></tt>:
*
- * Returns an array containing the items in <i>enum</i> sorted.
+ * %w[b c a d].sort # => ["a", "b", "c", "d"]
+ * {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]]
*
- * Comparisons for the sort will be done using the items' own
- * <code><=></code> operator or using an optional code block.
+ * With a block given, comparisons in the block determine the ordering.
+ * The block is called with two elements +a+ and +b+, and must return:
*
- * The block must implement a comparison between +a+ and +b+ and return
- * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
- * are equivalent, or an integer greater than 0 when +a+ follows +b+.
+ * - A negative integer if <tt>a < b</tt>.
+ * - Zero if <tt>a == b</tt>.
+ * - A positive integer if <tt>a > b</tt>.
*
- * The result is not guaranteed to be stable. When the comparison of two
- * elements returns +0+, the order of the elements is unpredictable.
+ * Examples:
*
- * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
- * (1..10).sort { |a, b| b <=> a } #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
+ * a = %w[b c a d]
+ * a.sort {|a, b| b <=> a } # => ["d", "c", "b", "a"]
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.sort {|a, b| b <=> a } # => [[:foo, 0], [:baz, 2], [:bar, 1]]
*
- * See also Enumerable#sort_by. It implements a Schwartzian transform
+ * See also #sort_by. It implements a Schwartzian transform
* which is useful when key computation or comparison is expensive.
*/
@@ -1211,18 +1354,18 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
v = enum_yield(argc, i);
if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort_by reentered");
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
}
if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
- rb_raise(rb_eRuntimeError, "sort_by reentered");
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
}
RARRAY_ASET(data->buf, data->n*2, v);
RARRAY_ASET(data->buf, data->n*2+1, i);
data->n++;
if (data->n == SORT_BY_BUFSIZE) {
- rb_ary_concat(ary, data->buf);
- data->n = 0;
+ rb_ary_concat(ary, data->buf);
+ data->n = 0;
}
return Qnil;
}
@@ -1230,36 +1373,39 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
static int
sort_by_cmp(const void *ap, const void *bp, void *data)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE a;
VALUE b;
VALUE ary = (VALUE)data;
if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort_by reentered");
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
}
a = *(VALUE *)ap;
b = *(VALUE *)bp;
- return OPTIMIZED_CMP(a, b, cmp_opt);
+ return OPTIMIZED_CMP(a, b);
}
/*
* call-seq:
- * enum.sort_by { |obj| block } -> array
- * enum.sort_by -> an_enumerator
+ * sort_by {|element| ... } -> array
+ * sort_by -> enumerator
*
- * Sorts <i>enum</i> using a set of keys generated by mapping the
- * values in <i>enum</i> through the given block.
+ * With a block given, returns an array of elements of +self+,
+ * sorted according to the value returned by the block for each element.
+ * The ordering of equal elements is indeterminate and may be unstable.
*
- * The result is not guaranteed to be stable. When two keys are equal,
- * the order of the corresponding elements is unpredictable.
+ * Examples:
*
- * If no block is given, an enumerator is returned instead.
+ * a = %w[xx xxx x xxxx]
+ * a.sort_by {|s| s.size } # => ["x", "xx", "xxx", "xxxx"]
+ * a.sort_by {|s| -s.size } # => ["xxxx", "xxx", "xx", "x"]
+ * h = {foo: 2, bar: 1, baz: 0}
+ * h.sort_by{|key, value| value } # => [[:baz, 0], [:bar, 1], [:foo, 2]]
+ * h.sort_by{|key, value| key } # => [[:bar, 1], [:baz, 0], [:foo, 2]]
*
- * %w{apple pear fig}.sort_by { |word| word.length }
- * #=> ["fig", "pear", "apple"]
+ * With no block given, returns an Enumerator.
*
* The current implementation of #sort_by generates an array of
* tuples containing the original collection element and the mapped
@@ -1334,13 +1480,13 @@ enum_sort_by(VALUE obj)
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
- ary = rb_ary_new2(RARRAY_LEN(obj)*2);
+ ary = rb_ary_new2(RARRAY_LEN(obj)*2);
}
else {
- ary = rb_ary_new();
+ ary = rb_ary_new();
}
RBASIC_CLEAR_CLASS(ary);
- buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
+ buf = rb_ary_hidden_new(SORT_BY_BUFSIZE*2);
rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
memo = MEMO_NEW(0, 0, 0);
data = (struct sort_by_data *)&memo->v1;
@@ -1351,8 +1497,8 @@ enum_sort_by(VALUE obj)
ary = data->ary;
buf = data->buf;
if (data->n) {
- rb_ary_resize(buf, data->n*2);
- rb_ary_concat(ary, buf);
+ rb_ary_resize(buf, data->n*2);
+ rb_ary_concat(ary, buf);
}
if (RARRAY_LEN(ary) > 2) {
RARRAY_PTR_USE(ary, ptr,
@@ -1360,10 +1506,10 @@ enum_sort_by(VALUE obj)
sort_by_cmp, (void *)ary));
}
if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort_by reentered");
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
}
for (i=1; i<RARRAY_LEN(ary); i+=2) {
- RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
+ RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
}
rb_ary_resize(ary, RARRAY_LEN(ary)/2);
RBASIC_SET_CLASS_RAW(ary, rb_cArray);
@@ -1409,33 +1555,52 @@ enum_##name##_func(VALUE result, struct MEMO *memo)
DEFINE_ENUMFUNCS(all)
{
if (!RTEST(result)) {
- MEMO_V1_SET(memo, Qfalse);
- rb_iter_break();
+ MEMO_V1_SET(memo, Qfalse);
+ rb_iter_break();
}
return Qnil;
}
/*
* call-seq:
- * enum.all? [{ |obj| block } ] -> true or false
- * enum.all?(pattern) -> true or false
- *
- * Passes each element of the collection to the given block. The method
- * returns <code>true</code> if the block never returns
- * <code>false</code> or <code>nil</code>. If the block is not given,
- * Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
- * cause #all? to return +true+ when none of the collection members are
- * +false+ or +nil+.
- *
- * If instead a pattern is supplied, the method returns whether
- * <code>pattern === element</code> for every collection member.
- *
- * %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
- * %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
- * %w[ant bear cat].all?(/t/) #=> false
- * [1, 2i, 3.14].all?(Numeric) #=> true
- * [nil, true, 99].all? #=> false
- * [].all? #=> true
+ * all? -> true or false
+ * all?(pattern) -> true or false
+ * all? {|element| ... } -> true or false
+ *
+ * Returns whether every element meets a given criterion.
+ *
+ * With no argument and no block,
+ * returns whether every element is truthy:
+ *
+ * (1..4).all? # => true
+ * %w[a b c d].all? # => true
+ * [1, 2, nil].all? # => false
+ * ['a','b', false].all? # => false
+ * [].all? # => true
+ *
+ * With argument +pattern+ and no block,
+ * returns whether for each element +element+,
+ * <tt>pattern === element</tt>:
+ *
+ * (1..4).all?(Integer) # => true
+ * (1..4).all?(Numeric) # => true
+ * (1..4).all?(Float) # => false
+ * %w[bar baz bat bam].all?(/ba/) # => true
+ * %w[bar baz bat bam].all?(/bar/) # => false
+ * %w[bar baz bat bam].all?('ba') # => false
+ * {foo: 0, bar: 1, baz: 2}.all?(Array) # => true
+ * {foo: 0, bar: 1, baz: 2}.all?(Hash) # => false
+ * [].all?(Integer) # => true
+ *
+ * With a block given, returns whether the block returns a truthy value
+ * for every element:
+ *
+ * (1..4).all? {|element| element < 5 } # => true
+ * (1..4).all? {|element| element < 4 } # => false
+ * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 3 } # => true
+ * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 2 } # => false
+ *
+ * Related: #any?, #none? #one?.
*
*/
@@ -1451,34 +1616,52 @@ enum_all(int argc, VALUE *argv, VALUE obj)
DEFINE_ENUMFUNCS(any)
{
if (RTEST(result)) {
- MEMO_V1_SET(memo, Qtrue);
- rb_iter_break();
+ MEMO_V1_SET(memo, Qtrue);
+ rb_iter_break();
}
return Qnil;
}
/*
* call-seq:
- * enum.any? [{ |obj| block }] -> true or false
- * enum.any?(pattern) -> true or false
- *
- * Passes each element of the collection to the given block. The method
- * returns <code>true</code> if the block ever returns a value other
- * than <code>false</code> or <code>nil</code>. If the block is not
- * given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
- * will cause #any? to return +true+ if at least one of the collection
- * members is not +false+ or +nil+.
- *
- * If instead a pattern is supplied, the method returns whether
- * <code>pattern === element</code> for any collection member.
- *
- * %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
- * %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
- * %w[ant bear cat].any?(/d/) #=> false
- * [nil, true, 99].any?(Integer) #=> true
- * [nil, true, 99].any? #=> true
- * [].any? #=> false
+ * any? -> true or false
+ * any?(pattern) -> true or false
+ * any? {|element| ... } -> true or false
*
+ * Returns whether any element meets a given criterion.
+ *
+ * With no argument and no block,
+ * returns whether any element is truthy:
+ *
+ * (1..4).any? # => true
+ * %w[a b c d].any? # => true
+ * [1, false, nil].any? # => true
+ * [].any? # => false
+ *
+ * With argument +pattern+ and no block,
+ * returns whether for any element +element+,
+ * <tt>pattern === element</tt>:
+ *
+ * [nil, false, 0].any?(Integer) # => true
+ * [nil, false, 0].any?(Numeric) # => true
+ * [nil, false, 0].any?(Float) # => false
+ * %w[bar baz bat bam].any?(/m/) # => true
+ * %w[bar baz bat bam].any?(/foo/) # => false
+ * %w[bar baz bat bam].any?('ba') # => false
+ * {foo: 0, bar: 1, baz: 2}.any?(Array) # => true
+ * {foo: 0, bar: 1, baz: 2}.any?(Hash) # => false
+ * [].any?(Integer) # => false
+ *
+ * With a block given, returns whether the block returns a truthy value
+ * for any element:
+ *
+ * (1..4).any? {|element| element < 2 } # => true
+ * (1..4).any? {|element| element < 1 } # => false
+ * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 1 } # => true
+ * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 0 } # => false
+ *
+ *
+ * Related: #all?, #none?, #one?.
*/
static VALUE
@@ -1493,13 +1676,13 @@ enum_any(int argc, VALUE *argv, VALUE obj)
DEFINE_ENUMFUNCS(one)
{
if (RTEST(result)) {
- if (memo->v1 == Qundef) {
- MEMO_V1_SET(memo, Qtrue);
- }
- else if (memo->v1 == Qtrue) {
- MEMO_V1_SET(memo, Qfalse);
- rb_iter_break();
- }
+ if (UNDEF_P(memo->v1)) {
+ MEMO_V1_SET(memo, Qtrue);
+ }
+ else if (memo->v1 == Qtrue) {
+ MEMO_V1_SET(memo, Qfalse);
+ rb_iter_break();
+ }
}
return Qnil;
}
@@ -1529,11 +1712,10 @@ cmpint_reenter_check(struct nmin_data *data, VALUE val)
static int
nmin_cmp(const void *ap, const void *bp, void *_data)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
struct nmin_data *data = (struct nmin_data *)_data;
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
#define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
- return OPTIMIZED_CMP(a, b, cmp_opt);
+ return OPTIMIZED_CMP(a, b);
#undef rb_cmpint
}
@@ -1561,7 +1743,7 @@ nmin_filter(struct nmin_data *data)
long i, j;
if (data->curlen <= data->n)
- return;
+ return;
n = data->n;
beg = RARRAY_PTR(data->buf);
@@ -1581,46 +1763,46 @@ nmin_filter(struct nmin_data *data)
} while (0)
while (1) {
- long pivot_index = left + (right-left)/2;
- long num_pivots = 1;
-
- SWAP(pivot_index, right);
- pivot_index = right;
-
- store_index = left;
- i = left;
- while (i <= right-num_pivots) {
- int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
- if (data->rev)
- c = -c;
- if (c == 0) {
- SWAP(i, right-num_pivots);
- num_pivots++;
- continue;
- }
- if (c < 0) {
- SWAP(i, store_index);
- store_index++;
- }
- i++;
- }
- j = store_index;
- for (i = right; right-num_pivots < i; i--) {
- if (i <= j)
- break;
- SWAP(j, i);
- j++;
- }
-
- if (store_index <= n && n <= store_index+num_pivots)
- break;
-
- if (n < store_index) {
- right = store_index-1;
- }
- else {
- left = store_index+num_pivots;
- }
+ long pivot_index = left + (right-left)/2;
+ long num_pivots = 1;
+
+ SWAP(pivot_index, right);
+ pivot_index = right;
+
+ store_index = left;
+ i = left;
+ while (i <= right-num_pivots) {
+ int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
+ if (data->rev)
+ c = -c;
+ if (c == 0) {
+ SWAP(i, right-num_pivots);
+ num_pivots++;
+ continue;
+ }
+ if (c < 0) {
+ SWAP(i, store_index);
+ store_index++;
+ }
+ i++;
+ }
+ j = store_index;
+ for (i = right; right-num_pivots < i; i--) {
+ if (i <= j)
+ break;
+ SWAP(j, i);
+ j++;
+ }
+
+ if (store_index <= n && n <= store_index+num_pivots)
+ break;
+
+ if (n < store_index) {
+ right = store_index-1;
+ }
+ else {
+ left = store_index+num_pivots;
+ }
}
#undef GETPTR
#undef SWAP
@@ -1639,11 +1821,11 @@ nmin_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
ENUM_WANT_SVALUE();
if (data->by)
- cmpv = enum_yield(argc, i);
+ cmpv = enum_yield(argc, i);
else
- cmpv = i;
+ cmpv = i;
- if (data->limit != Qundef) {
+ if (!UNDEF_P(data->limit)) {
int c = data->cmpfunc(&cmpv, &data->limit, data);
if (data->rev)
c = -c;
@@ -1652,13 +1834,13 @@ nmin_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
}
if (data->by)
- rb_ary_push(data->buf, cmpv);
+ rb_ary_push(data->buf, cmpv);
rb_ary_push(data->buf, i);
data->curlen++;
if (data->curlen == data->bufmax) {
- nmin_filter(data);
+ nmin_filter(data);
}
return Qnil;
@@ -1679,28 +1861,28 @@ rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
rb_raise(rb_eArgError, "too big size");
data.bufmax = data.n * 4;
data.curlen = 0;
- data.buf = rb_ary_tmp_new(data.bufmax * (by ? 2 : 1));
+ data.buf = rb_ary_hidden_new(data.bufmax * (by ? 2 : 1));
data.limit = Qundef;
data.cmpfunc = by ? nmin_cmp :
rb_block_given_p() ? nmin_block_cmp :
- nmin_cmp;
+ nmin_cmp;
data.rev = rev;
data.by = by;
if (ary) {
- long i;
- for (i = 0; i < RARRAY_LEN(obj); i++) {
- VALUE args[1];
- args[0] = RARRAY_AREF(obj, i);
+ long i;
+ for (i = 0; i < RARRAY_LEN(obj); i++) {
+ VALUE args[1];
+ args[0] = RARRAY_AREF(obj, i);
nmin_i(obj, (VALUE)&data, 1, args, Qundef);
- }
+ }
}
else {
- rb_block_call(obj, id_each, 0, 0, nmin_i, (VALUE)&data);
+ rb_block_call(obj, id_each, 0, 0, nmin_i, (VALUE)&data);
}
nmin_filter(&data);
result = data.buf;
if (by) {
- long i;
+ long i;
RARRAY_PTR_USE(result, ptr, {
ruby_qsort(ptr,
RARRAY_LEN(result)/2,
@@ -1710,7 +1892,7 @@ rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
ptr[i/2] = ptr[i];
}
});
- rb_ary_resize(result, RARRAY_LEN(result)/2);
+ rb_ary_resize(result, RARRAY_LEN(result)/2);
}
else {
RARRAY_PTR_USE(result, ptr, {
@@ -1728,26 +1910,45 @@ rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
/*
* call-seq:
- * enum.one? [{ |obj| block }] -> true or false
- * enum.one?(pattern) -> true or false
- *
- * Passes each element of the collection to the given block. The method
- * returns <code>true</code> if the block returns <code>true</code>
- * exactly once. If the block is not given, <code>one?</code> will return
- * <code>true</code> only if exactly one of the collection members is
- * true.
- *
- * If instead a pattern is supplied, the method returns whether
- * <code>pattern === element</code> for exactly one collection member.
- *
- * %w{ant bear cat}.one? { |word| word.length == 4 } #=> true
- * %w{ant bear cat}.one? { |word| word.length > 4 } #=> false
- * %w{ant bear cat}.one? { |word| word.length < 4 } #=> false
- * %w{ant bear cat}.one?(/t/) #=> false
- * [ nil, true, 99 ].one? #=> false
- * [ nil, true, false ].one? #=> true
- * [ nil, true, 99 ].one?(Integer) #=> true
- * [].one? #=> false
+ * one? -> true or false
+ * one?(pattern) -> true or false
+ * one? {|element| ... } -> true or false
+ *
+ * Returns whether exactly one element meets a given criterion.
+ *
+ * With no argument and no block,
+ * returns whether exactly one element is truthy:
+ *
+ * (1..1).one? # => true
+ * [1, nil, false].one? # => true
+ * (1..4).one? # => false
+ * {foo: 0}.one? # => true
+ * {foo: 0, bar: 1}.one? # => false
+ * [].one? # => false
+ *
+ * With argument +pattern+ and no block,
+ * returns whether for exactly one element +element+,
+ * <tt>pattern === element</tt>:
+ *
+ * [nil, false, 0].one?(Integer) # => true
+ * [nil, false, 0].one?(Numeric) # => true
+ * [nil, false, 0].one?(Float) # => false
+ * %w[bar baz bat bam].one?(/m/) # => true
+ * %w[bar baz bat bam].one?(/foo/) # => false
+ * %w[bar baz bat bam].one?('ba') # => false
+ * {foo: 0, bar: 1, baz: 2}.one?(Array) # => false
+ * {foo: 0}.one?(Array) # => true
+ * [].one?(Integer) # => false
+ *
+ * With a block given, returns whether the block returns a truthy value
+ * for exactly one element:
+ *
+ * (1..4).one? {|element| element < 2 } # => true
+ * (1..4).one? {|element| element < 1 } # => false
+ * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 1 } # => true
+ * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 2 } # => false
+ *
+ * Related: #none?, #all?, #any?.
*
*/
static VALUE
@@ -1759,40 +1960,58 @@ enum_one(int argc, VALUE *argv, VALUE obj)
WARN_UNUSED_BLOCK(argc);
rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
result = memo->v1;
- if (result == Qundef) return Qfalse;
+ if (UNDEF_P(result)) return Qfalse;
return result;
}
DEFINE_ENUMFUNCS(none)
{
if (RTEST(result)) {
- MEMO_V1_SET(memo, Qfalse);
- rb_iter_break();
+ MEMO_V1_SET(memo, Qfalse);
+ rb_iter_break();
}
return Qnil;
}
/*
* call-seq:
- * enum.none? [{ |obj| block }] -> true or false
- * enum.none?(pattern) -> true or false
- *
- * Passes each element of the collection to the given block. The method
- * returns <code>true</code> if the block never returns <code>true</code>
- * for all elements. If the block is not given, <code>none?</code> will return
- * <code>true</code> only if none of the collection members is true.
- *
- * If instead a pattern is supplied, the method returns whether
- * <code>pattern === element</code> for none of the collection members.
- *
- * %w{ant bear cat}.none? { |word| word.length == 5 } #=> true
- * %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
- * %w{ant bear cat}.none?(/d/) #=> true
- * [1, 3.14, 42].none?(Float) #=> false
- * [].none? #=> true
- * [nil].none? #=> true
- * [nil, false].none? #=> true
- * [nil, false, true].none? #=> false
+ * none? -> true or false
+ * none?(pattern) -> true or false
+ * none? {|element| ... } -> true or false
+ *
+ * Returns whether no element meets a given criterion.
+ *
+ * With no argument and no block,
+ * returns whether no element is truthy:
+ *
+ * (1..4).none? # => false
+ * [nil, false].none? # => true
+ * {foo: 0}.none? # => false
+ * {foo: 0, bar: 1}.none? # => false
+ * [].none? # => true
+ *
+ * With argument +pattern+ and no block,
+ * returns whether for no element +element+,
+ * <tt>pattern === element</tt>:
+ *
+ * [nil, false, 1.1].none?(Integer) # => true
+ * %w[bar baz bat bam].none?(/m/) # => false
+ * %w[bar baz bat bam].none?(/foo/) # => true
+ * %w[bar baz bat bam].none?('ba') # => true
+ * {foo: 0, bar: 1, baz: 2}.none?(Hash) # => true
+ * {foo: 0}.none?(Array) # => false
+ * [].none?(Integer) # => true
+ *
+ * With a block given, returns whether the block returns a truthy value
+ * for no element:
+ *
+ * (1..4).none? {|element| element < 1 } # => true
+ * (1..4).none? {|element| element < 2 } # => false
+ * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 0 } # => true
+ * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 1 } # => false
+ *
+ * Related: #one?, #all?, #any?.
+ *
*/
static VALUE
enum_none(int argc, VALUE *argv, VALUE obj)
@@ -1806,7 +2025,6 @@ enum_none(int argc, VALUE *argv, VALUE obj)
struct min_t {
VALUE min;
- struct cmp_opt_data cmp_opt;
};
static VALUE
@@ -1816,13 +2034,13 @@ min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
- if (memo->min == Qundef) {
- memo->min = i;
+ if (UNDEF_P(memo->min)) {
+ memo->min = i;
}
else {
- if (OPTIMIZED_CMP(i, memo->min, memo->cmp_opt) < 0) {
- memo->min = i;
- }
+ if (OPTIMIZED_CMP(i, memo->min) < 0) {
+ memo->min = i;
+ }
}
return Qnil;
}
@@ -1835,14 +2053,14 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
- if (memo->min == Qundef) {
- memo->min = i;
+ if (UNDEF_P(memo->min)) {
+ memo->min = i;
}
else {
- cmp = rb_yield_values(2, i, memo->min);
- if (rb_cmpint(cmp, i, memo->min) < 0) {
- memo->min = i;
- }
+ cmp = rb_yield_values(2, i, memo->min);
+ if (rb_cmpint(cmp, i, memo->min) < 0) {
+ memo->min = i;
+ }
}
return Qnil;
}
@@ -1850,33 +2068,66 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
/*
* call-seq:
- * enum.min -> obj
- * enum.min { |a, b| block } -> obj
- * enum.min(n) -> array
- * enum.min(n) { |a, b| block } -> array
- *
- * Returns the object in _enum_ with the minimum value. The
- * first form assumes all objects implement <code><=></code>;
- * the second uses the block to return <em>a <=> b</em>.
- *
- * a = %w(albatross dog horse)
- * a.min #=> "albatross"
- * a.min { |a, b| a.length <=> b.length } #=> "dog"
- *
- * If the +n+ argument is given, minimum +n+ elements are returned
- * as a sorted array.
- *
- * a = %w[albatross dog horse]
- * a.min(2) #=> ["albatross", "dog"]
- * a.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"]
- * [5, 1, 3, 4, 2].min(3) #=> [1, 2, 3]
+ * min -> element
+ * min(n) -> array
+ * min {|a, b| ... } -> element
+ * min(n) {|a, b| ... } -> array
+ *
+ * Returns the element with the minimum element according to a given criterion.
+ * The ordering of equal elements is indeterminate and may be unstable.
+ *
+ * With no argument and no block, returns the minimum element,
+ * using the elements' own method <tt><=></tt> for comparison:
+ *
+ * (1..4).min # => 1
+ * (-4..-1).min # => -4
+ * %w[d c b a].min # => "a"
+ * {foo: 0, bar: 1, baz: 2}.min # => [:bar, 1]
+ * [].min # => nil
+ *
+ * With positive integer argument +n+ given, and no block,
+ * returns an array containing the first +n+ minimum elements that exist:
+ *
+ * (1..4).min(2) # => [1, 2]
+ * (-4..-1).min(2) # => [-4, -3]
+ * %w[d c b a].min(2) # => ["a", "b"]
+ * {foo: 0, bar: 1, baz: 2}.min(2) # => [[:bar, 1], [:baz, 2]]
+ * [].min(2) # => []
+ *
+ * With a block given, the block determines the minimum elements.
+ * The block is called with two elements +a+ and +b+, and must return:
+ *
+ * - A negative integer if <tt>a < b</tt>.
+ * - Zero if <tt>a == b</tt>.
+ * - A positive integer if <tt>a > b</tt>.
+ *
+ * With a block given and no argument,
+ * returns the minimum element as determined by the block:
+ *
+ * %w[xxx x xxxx xx].min {|a, b| a.size <=> b.size } # => "x"
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.min {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:foo, 0]
+ * [].min {|a, b| a <=> b } # => nil
+ *
+ * With a block given and positive integer argument +n+ given,
+ * returns an array containing the first +n+ minimum elements that exist,
+ * as determined by the block.
+ *
+ * %w[xxx x xxxx xx].min(2) {|a, b| a.size <=> b.size } # => ["x", "xx"]
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.min(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
+ * # => [[:foo, 0], [:bar, 1]]
+ * [].min(2) {|a, b| a <=> b } # => []
+ *
+ * Related: #min_by, #minmax, #max.
+ *
*/
static VALUE
enum_min(int argc, VALUE *argv, VALUE obj)
{
VALUE memo;
- struct min_t *m = NEW_CMP_OPT_MEMO(struct min_t, memo);
+ struct min_t *m = NEW_MEMO_FOR(struct min_t, memo);
VALUE result;
VALUE num;
@@ -1884,22 +2135,19 @@ enum_min(int argc, VALUE *argv, VALUE obj)
return rb_nmin_run(obj, num, 0, 0, 0);
m->min = Qundef;
- m->cmp_opt.opt_methods = 0;
- m->cmp_opt.opt_inited = 0;
if (rb_block_given_p()) {
- rb_block_call(obj, id_each, 0, 0, min_ii, memo);
+ rb_block_call(obj, id_each, 0, 0, min_ii, memo);
}
else {
- rb_block_call(obj, id_each, 0, 0, min_i, memo);
+ rb_block_call(obj, id_each, 0, 0, min_i, memo);
}
result = m->min;
- if (result == Qundef) return Qnil;
+ if (UNDEF_P(result)) return Qnil;
return result;
}
struct max_t {
VALUE max;
- struct cmp_opt_data cmp_opt;
};
static VALUE
@@ -1909,13 +2157,13 @@ max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
- if (memo->max == Qundef) {
- memo->max = i;
+ if (UNDEF_P(memo->max)) {
+ memo->max = i;
}
else {
- if (OPTIMIZED_CMP(i, memo->max, memo->cmp_opt) > 0) {
- memo->max = i;
- }
+ if (OPTIMIZED_CMP(i, memo->max) > 0) {
+ memo->max = i;
+ }
}
return Qnil;
}
@@ -1928,47 +2176,80 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
- if (memo->max == Qundef) {
- memo->max = i;
+ if (UNDEF_P(memo->max)) {
+ memo->max = i;
}
else {
- cmp = rb_yield_values(2, i, memo->max);
- if (rb_cmpint(cmp, i, memo->max) > 0) {
- memo->max = i;
- }
+ cmp = rb_yield_values(2, i, memo->max);
+ if (rb_cmpint(cmp, i, memo->max) > 0) {
+ memo->max = i;
+ }
}
return Qnil;
}
/*
* call-seq:
- * enum.max -> obj
- * enum.max { |a, b| block } -> obj
- * enum.max(n) -> array
- * enum.max(n) { |a, b| block } -> array
- *
- * Returns the object in _enum_ with the maximum value. The
- * first form assumes all objects implement <code><=></code>;
- * the second uses the block to return <em>a <=> b</em>.
- *
- * a = %w(albatross dog horse)
- * a.max #=> "horse"
- * a.max { |a, b| a.length <=> b.length } #=> "albatross"
- *
- * If the +n+ argument is given, maximum +n+ elements are returned
- * as an array, sorted in descending order.
- *
- * a = %w[albatross dog horse]
- * a.max(2) #=> ["horse", "dog"]
- * a.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"]
- * [5, 1, 3, 4, 2].max(3) #=> [5, 4, 3]
+ * max -> element
+ * max(n) -> array
+ * max {|a, b| ... } -> element
+ * max(n) {|a, b| ... } -> array
+ *
+ * Returns the element with the maximum element according to a given criterion.
+ * The ordering of equal elements is indeterminate and may be unstable.
+ *
+ * With no argument and no block, returns the maximum element,
+ * using the elements' own method <tt><=></tt> for comparison:
+ *
+ * (1..4).max # => 4
+ * (-4..-1).max # => -1
+ * %w[d c b a].max # => "d"
+ * {foo: 0, bar: 1, baz: 2}.max # => [:foo, 0]
+ * [].max # => nil
+ *
+ * With positive integer argument +n+ given, and no block,
+ * returns an array containing the first +n+ maximum elements that exist:
+ *
+ * (1..4).max(2) # => [4, 3]
+ * (-4..-1).max(2) # => [-1, -2]
+ * %w[d c b a].max(2) # => ["d", "c"]
+ * {foo: 0, bar: 1, baz: 2}.max(2) # => [[:foo, 0], [:baz, 2]]
+ * [].max(2) # => []
+ *
+ * With a block given, the block determines the maximum elements.
+ * The block is called with two elements +a+ and +b+, and must return:
+ *
+ * - A negative integer if <tt>a < b</tt>.
+ * - Zero if <tt>a == b</tt>.
+ * - A positive integer if <tt>a > b</tt>.
+ *
+ * With a block given and no argument,
+ * returns the maximum element as determined by the block:
+ *
+ * %w[xxx x xxxx xx].max {|a, b| a.size <=> b.size } # => "xxxx"
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.max {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:baz, 2]
+ * [].max {|a, b| a <=> b } # => nil
+ *
+ * With a block given and positive integer argument +n+ given,
+ * returns an array containing the first +n+ maximum elements that exist,
+ * as determined by the block.
+ *
+ * %w[xxx x xxxx xx].max(2) {|a, b| a.size <=> b.size } # => ["xxxx", "xxx"]
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.max(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
+ * # => [[:baz, 2], [:bar, 1]]
+ * [].max(2) {|a, b| a <=> b } # => []
+ *
+ * Related: #min, #minmax, #max_by.
+ *
*/
static VALUE
enum_max(int argc, VALUE *argv, VALUE obj)
{
VALUE memo;
- struct max_t *m = NEW_CMP_OPT_MEMO(struct max_t, memo);
+ struct max_t *m = NEW_MEMO_FOR(struct max_t, memo);
VALUE result;
VALUE num;
@@ -1976,16 +2257,14 @@ enum_max(int argc, VALUE *argv, VALUE obj)
return rb_nmin_run(obj, num, 0, 1, 0);
m->max = Qundef;
- m->cmp_opt.opt_methods = 0;
- m->cmp_opt.opt_inited = 0;
if (rb_block_given_p()) {
- rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
}
else {
- rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
}
result = m->max;
- if (result == Qundef) return Qnil;
+ if (UNDEF_P(result)) return Qnil;
return result;
}
@@ -1993,7 +2272,6 @@ struct minmax_t {
VALUE min;
VALUE max;
VALUE last;
- struct cmp_opt_data cmp_opt;
};
static void
@@ -2001,19 +2279,19 @@ minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
{
int n;
- if (memo->min == Qundef) {
- memo->min = i;
- memo->max = j;
+ if (UNDEF_P(memo->min)) {
+ memo->min = i;
+ memo->max = j;
}
else {
- n = OPTIMIZED_CMP(i, memo->min, memo->cmp_opt);
- if (n < 0) {
- memo->min = i;
- }
- n = OPTIMIZED_CMP(j, memo->max, memo->cmp_opt);
- if (n > 0) {
- memo->max = j;
- }
+ n = OPTIMIZED_CMP(i, memo->min);
+ if (n < 0) {
+ memo->min = i;
+ }
+ n = OPTIMIZED_CMP(j, memo->max);
+ if (n > 0) {
+ memo->max = j;
+ }
}
}
@@ -2026,14 +2304,14 @@ minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
ENUM_WANT_SVALUE();
- if (memo->last == Qundef) {
+ if (UNDEF_P(memo->last)) {
memo->last = i;
return Qnil;
}
j = memo->last;
memo->last = Qundef;
- n = OPTIMIZED_CMP(j, i, memo->cmp_opt);
+ n = OPTIMIZED_CMP(j, i);
if (n == 0)
i = j;
else if (n < 0) {
@@ -2053,19 +2331,19 @@ minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
{
int n;
- if (memo->min == Qundef) {
- memo->min = i;
- memo->max = j;
+ if (UNDEF_P(memo->min)) {
+ memo->min = i;
+ memo->max = j;
}
else {
- n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
- if (n < 0) {
- memo->min = i;
- }
- n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
- if (n > 0) {
- memo->max = j;
- }
+ n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
+ if (n < 0) {
+ memo->min = i;
+ }
+ n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
+ if (n > 0) {
+ memo->max = j;
+ }
}
}
@@ -2078,7 +2356,7 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
ENUM_WANT_SVALUE();
- if (memo->last == Qundef) {
+ if (UNDEF_P(memo->last)) {
memo->last = i;
return Qnil;
}
@@ -2102,41 +2380,55 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
/*
* call-seq:
- * enum.minmax -> [min, max]
- * enum.minmax { |a, b| block } -> [min, max]
+ * minmax -> [minimum, maximum]
+ * minmax {|a, b| ... } -> [minimum, maximum]
+ *
+ * Returns a 2-element array containing the minimum and maximum elements
+ * according to a given criterion.
+ * The ordering of equal elements is indeterminate and may be unstable.
+ *
+ * With no argument and no block, returns the minimum and maximum elements,
+ * using the elements' own method <tt><=></tt> for comparison:
+ *
+ * (1..4).minmax # => [1, 4]
+ * (-4..-1).minmax # => [-4, -1]
+ * %w[d c b a].minmax # => ["a", "d"]
+ * {foo: 0, bar: 1, baz: 2}.minmax # => [[:bar, 1], [:foo, 0]]
+ * [].minmax # => [nil, nil]
*
- * Returns a two element array which contains the minimum and the
- * maximum value in the enumerable. The first form assumes all
- * objects implement <code><=></code>; the second uses the
- * block to return <em>a <=> b</em>.
+ * With a block given, returns the minimum and maximum elements
+ * as determined by the block:
+ *
+ * %w[xxx x xxxx xx].minmax {|a, b| a.size <=> b.size } # => ["x", "xxxx"]
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.minmax {|pair1, pair2| pair1[1] <=> pair2[1] }
+ * # => [[:foo, 0], [:baz, 2]]
+ * [].minmax {|a, b| a <=> b } # => [nil, nil]
+ *
+ * Related: #min, #max, #minmax_by.
*
- * a = %w(albatross dog horse)
- * a.minmax #=> ["albatross", "horse"]
- * a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
*/
static VALUE
enum_minmax(VALUE obj)
{
VALUE memo;
- struct minmax_t *m = NEW_CMP_OPT_MEMO(struct minmax_t, memo);
+ struct minmax_t *m = NEW_MEMO_FOR(struct minmax_t, memo);
m->min = Qundef;
m->last = Qundef;
- m->cmp_opt.opt_methods = 0;
- m->cmp_opt.opt_inited = 0;
if (rb_block_given_p()) {
- rb_block_call(obj, id_each, 0, 0, minmax_ii, memo);
- if (m->last != Qundef)
- minmax_ii_update(m->last, m->last, m);
+ rb_block_call(obj, id_each, 0, 0, minmax_ii, memo);
+ if (!UNDEF_P(m->last))
+ minmax_ii_update(m->last, m->last, m);
}
else {
- rb_block_call(obj, id_each, 0, 0, minmax_i, memo);
- if (m->last != Qundef)
- minmax_i_update(m->last, m->last, m);
+ rb_block_call(obj, id_each, 0, 0, minmax_i, memo);
+ if (!UNDEF_P(m->last))
+ minmax_i_update(m->last, m->last, m);
}
- if (m->min != Qundef) {
- return rb_assoc_new(m->min, m->max);
+ if (!UNDEF_P(m->min)) {
+ return rb_assoc_new(m->min, m->max);
}
return rb_assoc_new(Qnil, Qnil);
}
@@ -2144,45 +2436,57 @@ enum_minmax(VALUE obj)
static VALUE
min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
struct MEMO *memo = MEMO_CAST(args);
VALUE v;
ENUM_WANT_SVALUE();
v = enum_yield(argc, i);
- if (memo->v1 == Qundef) {
- MEMO_V1_SET(memo, v);
- MEMO_V2_SET(memo, i);
+ if (UNDEF_P(memo->v1)) {
+ MEMO_V1_SET(memo, v);
+ MEMO_V2_SET(memo, i);
}
- else if (OPTIMIZED_CMP(v, memo->v1, cmp_opt) < 0) {
- MEMO_V1_SET(memo, v);
- MEMO_V2_SET(memo, i);
+ else if (OPTIMIZED_CMP(v, memo->v1) < 0) {
+ MEMO_V1_SET(memo, v);
+ MEMO_V2_SET(memo, i);
}
return Qnil;
}
/*
* call-seq:
- * enum.min_by {|obj| block } -> obj
- * enum.min_by -> an_enumerator
- * enum.min_by(n) {|obj| block } -> array
- * enum.min_by(n) -> an_enumerator
+ * min_by {|element| ... } -> element
+ * min_by(n) {|element| ... } -> array
+ * min_by -> enumerator
+ * min_by(n) -> enumerator
+ *
+ * Returns the elements for which the block returns the minimum values.
+ *
+ * With a block given and no argument,
+ * returns the element for which the block returns the minimum value:
+ *
+ * (1..4).min_by {|element| -element } # => 4
+ * %w[a b c d].min_by {|element| -element.ord } # => "d"
+ * {foo: 0, bar: 1, baz: 2}.min_by {|key, value| -value } # => [:baz, 2]
+ * [].min_by {|element| -element } # => nil
*
- * Returns the object in <i>enum</i> that gives the minimum
- * value from the given block.
+ * With a block given and positive integer argument +n+ given,
+ * returns an array containing the +n+ elements
+ * for which the block returns minimum values:
*
- * If no block is given, an enumerator is returned instead.
+ * (1..4).min_by(2) {|element| -element }
+ * # => [4, 3]
+ * %w[a b c d].min_by(2) {|element| -element.ord }
+ * # => ["d", "c"]
+ * {foo: 0, bar: 1, baz: 2}.min_by(2) {|key, value| -value }
+ * # => [[:baz, 2], [:bar, 1]]
+ * [].min_by(2) {|element| -element }
+ * # => []
*
- * a = %w(albatross dog horse)
- * a.min_by { |x| x.length } #=> "dog"
+ * Returns an Enumerator if no block is given.
*
- * If the +n+ argument is given, minimum +n+ elements are returned
- * as an array. These +n+ elements are sorted by the value from the
- * given block.
+ * Related: #min, #minmax, #max_by.
*
- * a = %w[albatross dog horse]
- * p a.min_by(2) {|x| x.length } #=> ["dog", "horse"]
*/
static VALUE
@@ -2206,89 +2510,56 @@ enum_min_by(int argc, VALUE *argv, VALUE obj)
static VALUE
max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
struct MEMO *memo = MEMO_CAST(args);
VALUE v;
ENUM_WANT_SVALUE();
v = enum_yield(argc, i);
- if (memo->v1 == Qundef) {
- MEMO_V1_SET(memo, v);
- MEMO_V2_SET(memo, i);
+ if (UNDEF_P(memo->v1)) {
+ MEMO_V1_SET(memo, v);
+ MEMO_V2_SET(memo, i);
}
- else if (OPTIMIZED_CMP(v, memo->v1, cmp_opt) > 0) {
- MEMO_V1_SET(memo, v);
- MEMO_V2_SET(memo, i);
+ else if (OPTIMIZED_CMP(v, memo->v1) > 0) {
+ MEMO_V1_SET(memo, v);
+ MEMO_V2_SET(memo, i);
}
return Qnil;
}
/*
* call-seq:
- * enum.max_by {|obj| block } -> obj
- * enum.max_by -> an_enumerator
- * enum.max_by(n) {|obj| block } -> obj
- * enum.max_by(n) -> an_enumerator
- *
- * Returns the object in <i>enum</i> that gives the maximum
- * value from the given block.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * a = %w(albatross dog horse)
- * a.max_by { |x| x.length } #=> "albatross"
- *
- * If the +n+ argument is given, maximum +n+ elements are returned
- * as an array. These +n+ elements are sorted by the value from the
- * given block, in descending order.
- *
- * a = %w[albatross dog horse]
- * a.max_by(2) {|x| x.length } #=> ["albatross", "horse"]
- *
- * enum.max_by(n) can be used to implement weighted random sampling.
- * Following example implements and use Enumerable#wsample.
- *
- * module Enumerable
- * # weighted random sampling.
- * #
- * # Pavlos S. Efraimidis, Paul G. Spirakis
- * # Weighted random sampling with a reservoir
- * # Information Processing Letters
- * # Volume 97, Issue 5 (16 March 2006)
- * def wsample(n)
- * self.max_by(n) {|v| rand ** (1.0/yield(v)) }
- * end
- * end
- * e = (-20..20).to_a*10000
- * a = e.wsample(20000) {|x|
- * Math.exp(-(x/5.0)**2) # normal distribution
- * }
- * # a is 20000 samples from e.
- * p a.length #=> 20000
- * h = a.group_by {|x| x }
- * -10.upto(10) {|x| puts "*" * (h[x].length/30.0).to_i if h[x] }
- * #=> *
- * # ***
- * # ******
- * # ***********
- * # ******************
- * # *****************************
- * # *****************************************
- * # ****************************************************
- * # ***************************************************************
- * # ********************************************************************
- * # ***********************************************************************
- * # ***********************************************************************
- * # **************************************************************
- * # ****************************************************
- * # ***************************************
- * # ***************************
- * # ******************
- * # ***********
- * # *******
- * # ***
- * # *
+ * max_by {|element| ... } -> element
+ * max_by(n) {|element| ... } -> array
+ * max_by -> enumerator
+ * max_by(n) -> enumerator
+ *
+ * Returns the elements for which the block returns the maximum values.
+ *
+ * With a block given and no argument,
+ * returns the element for which the block returns the maximum value:
+ *
+ * (1..4).max_by {|element| -element } # => 1
+ * %w[a b c d].max_by {|element| -element.ord } # => "a"
+ * {foo: 0, bar: 1, baz: 2}.max_by {|key, value| -value } # => [:foo, 0]
+ * [].max_by {|element| -element } # => nil
+ *
+ * With a block given and positive integer argument +n+ given,
+ * returns an array containing the +n+ elements
+ * for which the block returns maximum values:
+ *
+ * (1..4).max_by(2) {|element| -element }
+ * # => [1, 2]
+ * %w[a b c d].max_by(2) {|element| -element.ord }
+ * # => ["a", "b"]
+ * {foo: 0, bar: 1, baz: 2}.max_by(2) {|key, value| -value }
+ * # => [[:foo, 0], [:bar, 1]]
+ * [].max_by(2) {|element| -element }
+ * # => []
+ *
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: #max, #minmax, #min_by.
*
*/
@@ -2322,30 +2593,27 @@ struct minmax_by_t {
static void
minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
-
- if (memo->min_bv == Qundef) {
- memo->min_bv = v1;
- memo->max_bv = v2;
- memo->min = i1;
- memo->max = i2;
+ if (UNDEF_P(memo->min_bv)) {
+ memo->min_bv = v1;
+ memo->max_bv = v2;
+ memo->min = i1;
+ memo->max = i2;
}
else {
- if (OPTIMIZED_CMP(v1, memo->min_bv, cmp_opt) < 0) {
- memo->min_bv = v1;
- memo->min = i1;
- }
- if (OPTIMIZED_CMP(v2, memo->max_bv, cmp_opt) > 0) {
- memo->max_bv = v2;
- memo->max = i2;
- }
+ if (OPTIMIZED_CMP(v1, memo->min_bv) < 0) {
+ memo->min_bv = v1;
+ memo->min = i1;
+ }
+ if (OPTIMIZED_CMP(v2, memo->max_bv) > 0) {
+ memo->max_bv = v2;
+ memo->max = i2;
+ }
}
}
static VALUE
minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
VALUE vi, vj, j;
int n;
@@ -2354,7 +2622,7 @@ minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
vi = enum_yield(argc, i);
- if (memo->last_bv == Qundef) {
+ if (UNDEF_P(memo->last_bv)) {
memo->last_bv = vi;
memo->last = i;
return Qnil;
@@ -2363,7 +2631,7 @@ minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
j = memo->last;
memo->last_bv = Qundef;
- n = OPTIMIZED_CMP(vj, vi, cmp_opt);
+ n = OPTIMIZED_CMP(vj, vi);
if (n == 0) {
i = j;
vi = vj;
@@ -2385,17 +2653,25 @@ minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
/*
* call-seq:
- * enum.minmax_by { |obj| block } -> [min, max]
- * enum.minmax_by -> an_enumerator
+ * minmax_by {|element| ... } -> [minimum, maximum]
+ * minmax_by -> enumerator
*
- * Returns a two element array containing the objects in
- * <i>enum</i> that correspond to the minimum and maximum values respectively
- * from the given block.
+ * Returns a 2-element array containing the elements
+ * for which the block returns minimum and maximum values:
*
- * If no block is given, an enumerator is returned instead.
+ * (1..4).minmax_by {|element| -element }
+ * # => [4, 1]
+ * %w[a b c d].minmax_by {|element| -element.ord }
+ * # => ["d", "a"]
+ * {foo: 0, bar: 1, baz: 2}.minmax_by {|key, value| -value }
+ * # => [[:baz, 2], [:foo, 0]]
+ * [].minmax_by {|element| -element }
+ * # => [nil, nil]
+ *
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: #max_by, #minmax, #min_by.
*
- * a = %w(albatross dog horse)
- * a.minmax_by { |x| x.length } #=> ["dog", "albatross"]
*/
static VALUE
@@ -2413,7 +2689,7 @@ enum_minmax_by(VALUE obj)
m->last_bv = Qundef;
m->last = Qundef;
rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
- if (m->last_bv != Qundef)
+ if (!UNDEF_P(m->last_bv))
minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
m = MEMO_FOR(struct minmax_by_t, memo);
return rb_assoc_new(m->min, m->max);
@@ -2425,24 +2701,28 @@ member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
struct MEMO *memo = MEMO_CAST(args);
if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
- MEMO_V2_SET(memo, Qtrue);
- rb_iter_break();
+ MEMO_V2_SET(memo, Qtrue);
+ rb_iter_break();
}
return Qnil;
}
/*
* call-seq:
- * enum.include?(obj) -> true or false
- * enum.member?(obj) -> true or false
+ * include?(object) -> true or false
+ *
+ * Returns whether for any element <tt>object == element</tt>:
*
- * Returns <code>true</code> if any member of <i>enum</i> equals
- * <i>obj</i>. Equality is tested using <code>==</code>.
+ * (1..4).include?(2) # => true
+ * (1..4).include?(5) # => false
+ * (1..4).include?('2') # => false
+ * %w[a b c d].include?('b') # => true
+ * %w[a b c d].include?('2') # => false
+ * {foo: 0, bar: 1, baz: 2}.include?(:foo) # => true
+ * {foo: 0, bar: 1, baz: 2}.include?('foo') # => false
+ * {foo: 0, bar: 1, baz: 2}.include?(0) # => false
*
- * (1..10).include? 5 #=> true
- * (1..10).include? 15 #=> false
- * (1..10).member? 5 #=> true
- * (1..10).member? 15 #=> false
+ * Enumerable#member? is an alias for Enumerable#include?.
*
*/
@@ -2467,20 +2747,28 @@ each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
/*
* call-seq:
- * enum.each_with_index(*args) { |obj, i| block } -> enum
- * enum.each_with_index(*args) -> an_enumerator
+ * each_with_index(*args) {|element, i| ..... } -> self
+ * each_with_index(*args) -> enumerator
*
- * Calls <em>block</em> with two arguments, the item and its index,
- * for each item in <i>enum</i>. Given arguments are passed through
- * to #each().
+ * With a block given, calls the block with each element and its index;
+ * returns +self+:
*
- * If no block is given, an enumerator is returned instead.
+ * h = {}
+ * (1..4).each_with_index {|element, i| h[element] = i } # => 1..4
+ * h # => {1=>0, 2=>1, 3=>2, 4=>3}
*
- * hash = Hash.new
- * %w(cat dog wombat).each_with_index { |item, index|
- * hash[item] = index
- * }
- * hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
+ * h = {}
+ * %w[a b c d].each_with_index {|element, i| h[element] = i }
+ * # => ["a", "b", "c", "d"]
+ * h # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3}
+ *
+ * a = []
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.each_with_index {|element, i| a.push([i, element]) }
+ * # => {:foo=>0, :bar=>1, :baz=>2}
+ * a # => [[0, [:foo, 0]], [1, [:bar, 1]], [2, [:baz, 2]]]
+ *
+ * With no block given, returns an Enumerator.
*
*/
@@ -2499,20 +2787,28 @@ enum_each_with_index(int argc, VALUE *argv, VALUE obj)
/*
* call-seq:
- * enum.reverse_each(*args) { |item| block } -> enum
- * enum.reverse_each(*args) -> an_enumerator
+ * reverse_each(*args) {|element| ... } -> self
+ * reverse_each(*args) -> enumerator
+ *
+ * With a block given, calls the block with each element,
+ * but in reverse order; returns +self+:
*
- * Builds a temporary array and traverses that array in reverse order.
+ * a = []
+ * (1..4).reverse_each {|element| a.push(-element) } # => 1..4
+ * a # => [-4, -3, -2, -1]
*
- * If no block is given, an enumerator is returned instead.
+ * a = []
+ * %w[a b c d].reverse_each {|element| a.push(element) }
+ * # => ["a", "b", "c", "d"]
+ * a # => ["d", "c", "b", "a"]
*
- * (1..3).reverse_each { |v| p v }
+ * a = []
+ * h.reverse_each {|element| a.push(element) }
+ * # => {:foo=>0, :bar=>1, :baz=>2}
+ * a # => [[:baz, 2], [:bar, 1], [:foo, 0]]
*
- * produces:
+ * With no block given, returns an Enumerator.
*
- * 3
- * 2
- * 1
*/
static VALUE
@@ -2549,30 +2845,39 @@ each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
/*
* call-seq:
- * enum.each_entry { |obj| block } -> enum
- * enum.each_entry -> an_enumerator
- *
- * Calls <i>block</i> once for each element in +self+, passing that
- * element as a parameter, converting multiple values from yield to an
- * array.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * class Foo
- * include Enumerable
- * def each
- * yield 1
- * yield 1, 2
- * yield
- * end
- * end
- * Foo.new.each_entry{ |o| p o }
+ * each_entry(*args) {|element| ... } -> self
+ * each_entry(*args) -> enumerator
+ *
+ * Calls the given block with each element,
+ * converting multiple values from yield to an array; returns +self+:
*
- * produces:
+ * a = []
+ * (1..4).each_entry {|element| a.push(element) } # => 1..4
+ * a # => [1, 2, 3, 4]
*
- * 1
- * [1, 2]
- * nil
+ * a = []
+ * h = {foo: 0, bar: 1, baz:2}
+ * h.each_entry {|element| a.push(element) }
+ * # => {:foo=>0, :bar=>1, :baz=>2}
+ * a # => [[:foo, 0], [:bar, 1], [:baz, 2]]
+ *
+ * class Foo
+ * include Enumerable
+ * def each
+ * yield 1
+ * yield 1, 2
+ * yield
+ * end
+ * end
+ * Foo.new.each_entry {|yielded| p yielded }
+ *
+ * Output:
+ *
+ * 1
+ * [1, 2]
+ * nil
+ *
+ * With no block given, returns an Enumerator.
*
*/
@@ -2614,14 +2919,14 @@ each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
rb_ary_push(ary, i);
if (RARRAY_LEN(ary) == size) {
- v = rb_yield(ary);
+ v = rb_yield(ary);
- if (memo->v2) {
- MEMO_V1_SET(memo, rb_ary_new2(size));
- }
- else {
- rb_ary_clear(ary);
- }
+ if (memo->v2) {
+ MEMO_V1_SET(memo, rb_ary_new2(size));
+ }
+ else {
+ rb_ary_clear(ary);
+ }
}
return v;
@@ -2637,7 +2942,7 @@ enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
size = enum_size(obj, 0, 0);
- if (size == Qnil) return Qnil;
+ if (NIL_P(size)) return Qnil;
if (RB_FLOAT_TYPE_P(size) && RTEST(rb_funcall(size, infinite_p, 0))) {
return size;
}
@@ -2648,18 +2953,22 @@ enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
/*
* call-seq:
- * enum.each_slice(n) { ... } -> nil
- * enum.each_slice(n) -> an_enumerator
+ * each_slice(n) { ... } -> self
+ * each_slice(n) -> enumerator
+ *
+ * Calls the block with each successive disjoint +n+-tuple of elements;
+ * returns +self+:
*
- * Iterates the given block for each slice of <n> elements. If no
- * block is given, returns an enumerator.
+ * a = []
+ * (1..10).each_slice(3) {|tuple| a.push(tuple) }
+ * a # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
*
- * (1..10).each_slice(3) { |a| p a }
- * # outputs below
- * [1, 2, 3]
- * [4, 5, 6]
- * [7, 8, 9]
- * [10]
+ * a = []
+ * h = {foo: 0, bar: 1, baz: 2, bat: 3, bam: 4}
+ * h.each_slice(2) {|tuple| a.push(tuple) }
+ * a # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]], [[:bam, 4]]]
+ *
+ * With no block given, returns an Enumerator.
*
*/
static VALUE
@@ -2680,7 +2989,7 @@ enum_each_slice(VALUE obj, VALUE n)
ary = memo->v1;
if (RARRAY_LEN(ary) > 0) rb_yield(ary);
- return Qnil;
+ return obj;
}
static VALUE
@@ -2693,14 +3002,14 @@ each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
if (RARRAY_LEN(ary) == size) {
- rb_ary_shift(ary);
+ rb_ary_shift(ary);
}
rb_ary_push(ary, i);
if (RARRAY_LEN(ary) == size) {
- if (memo->v2) {
- ary = rb_ary_dup(ary);
- }
- v = rb_yield(ary);
+ if (memo->v2) {
+ ary = rb_ary_dup(ary);
+ }
+ v = rb_yield(ary);
}
return v;
}
@@ -2708,38 +3017,36 @@ each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
static VALUE
enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
const VALUE zero = LONG2FIX(0);
VALUE n, size;
long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
size = enum_size(obj, 0, 0);
- if (size == Qnil) return Qnil;
+ if (NIL_P(size)) return Qnil;
n = add_int(size, 1 - cons_size);
- return (OPTIMIZED_CMP(n, zero, cmp_opt) == -1) ? zero : n;
+ return (OPTIMIZED_CMP(n, zero) == -1) ? zero : n;
}
/*
* call-seq:
- * enum.each_cons(n) { ... } -> nil
- * enum.each_cons(n) -> an_enumerator
- *
- * Iterates the given block for each array of consecutive <n>
- * elements. If no block is given, returns an enumerator.
- *
- * e.g.:
- * (1..10).each_cons(3) { |a| p a }
- * # outputs below
- * [1, 2, 3]
- * [2, 3, 4]
- * [3, 4, 5]
- * [4, 5, 6]
- * [5, 6, 7]
- * [6, 7, 8]
- * [7, 8, 9]
- * [8, 9, 10]
+ * each_cons(n) { ... } -> self
+ * each_cons(n) -> enumerator
+ *
+ * Calls the block with each successive overlapped +n+-tuple of elements;
+ * returns +self+:
+ *
+ * a = []
+ * (1..5).each_cons(3) {|element| a.push(element) }
+ * a # => [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
+ *
+ * a = []
+ * h = {foo: 0, bar: 1, baz: 2, bam: 3}
+ * h.each_cons(2) {|element| a.push(element) }
+ * a # => [[[:foo, 0], [:bar, 1]], [[:bar, 1], [:baz, 2]], [[:baz, 2], [:bam, 3]]]
+ *
+ * With no block given, returns an Enumerator.
*
*/
static VALUE
@@ -2752,11 +3059,11 @@ enum_each_cons(VALUE obj, VALUE n)
if (size <= 0) rb_raise(rb_eArgError, "invalid size");
RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
arity = rb_block_arity();
- if (enum_size_over_p(obj, size)) return Qnil;
+ if (enum_size_over_p(obj, size)) return obj;
memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
- return Qnil;
+ return obj;
}
static VALUE
@@ -2768,16 +3075,19 @@ each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
/*
* call-seq:
- * enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
- * enum.each_with_object(obj) -> an_enumerator
+ * each_with_object(object) { |(*args), memo_object| ... } -> object
+ * each_with_object(object) -> enumerator
*
- * Iterates the given block for each element with an arbitrary
- * object given, and returns the initially given object.
+ * Calls the block once for each element, passing both the element
+ * and the given object:
*
- * If no block is given, returns an enumerator.
+ * (1..4).each_with_object([]) {|i, a| a.push(i**2) }
+ * # => [1, 4, 9, 16]
*
- * evens = (1..10).each_with_object([]) { |i, a| a << i*2 }
- * #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
+ * {foo: 0, bar: 1, baz: 2}.each_with_object({}) {|(k, v), h| h[v] = k }
+ * # => {0=>:foo, 1=>:bar, 2=>:baz}
+ *
+ * With no block given, returns an Enumerator.
*
*/
static VALUE
@@ -2803,20 +3113,20 @@ zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
for (i=0; i<RARRAY_LEN(args); i++) {
- VALUE e = RARRAY_AREF(args, i);
+ VALUE e = RARRAY_AREF(args, i);
- if (RARRAY_LEN(e) <= n) {
- rb_ary_push(tmp, Qnil);
- }
- else {
- rb_ary_push(tmp, RARRAY_AREF(e, n));
- }
+ if (RARRAY_LEN(e) <= n) {
+ rb_ary_push(tmp, Qnil);
+ }
+ else {
+ rb_ary_push(tmp, RARRAY_AREF(e, n));
+ }
}
if (NIL_P(result)) {
- enum_yield_array(tmp);
+ enum_yield_array(tmp);
}
else {
- rb_ary_push(result, tmp);
+ rb_ary_push(result, tmp);
}
RB_GC_GUARD(args);
@@ -2850,26 +3160,26 @@ zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
for (i=0; i<RARRAY_LEN(args); i++) {
- if (NIL_P(RARRAY_AREF(args, i))) {
- rb_ary_push(tmp, Qnil);
- }
- else {
- VALUE v[2];
-
- v[1] = RARRAY_AREF(args, i);
- rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
- if (v[0] == Qundef) {
- RARRAY_ASET(args, i, Qnil);
- v[0] = Qnil;
- }
- rb_ary_push(tmp, v[0]);
- }
+ if (NIL_P(RARRAY_AREF(args, i))) {
+ rb_ary_push(tmp, Qnil);
+ }
+ else {
+ VALUE v[2];
+
+ v[1] = RARRAY_AREF(args, i);
+ rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
+ if (UNDEF_P(v[0])) {
+ RARRAY_ASET(args, i, Qnil);
+ v[0] = Qnil;
+ }
+ rb_ary_push(tmp, v[0]);
+ }
}
if (NIL_P(result)) {
- enum_yield_array(tmp);
+ enum_yield_array(tmp);
}
else {
- rb_ary_push(result, tmp);
+ rb_ary_push(result, tmp);
}
RB_GC_GUARD(args);
@@ -2879,29 +3189,68 @@ zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
/*
* call-seq:
- * enum.zip(arg, ...) -> an_array_of_array
- * enum.zip(arg, ...) { |arr| block } -> nil
- *
- * Takes one element from <i>enum</i> and merges corresponding
- * elements from each <i>args</i>. This generates a sequence of
- * <em>n</em>-element arrays, where <em>n</em> is one more than the
- * count of arguments. The length of the resulting sequence will be
- * <code>enum#size</code>. If the size of any argument is less than
- * <code>enum#size</code>, <code>nil</code> values are supplied. If
- * a block is given, it is invoked for each output array, otherwise
- * an array of arrays is returned.
- *
- * a = [ 4, 5, 6 ]
- * b = [ 7, 8, 9 ]
- *
- * a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
- * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
- * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
- *
- * c = []
- * a.zip(b) { |x, y| c << x + y } #=> nil
- * c #=> [11, 13, 15]
+ * zip(*other_enums) -> array
+ * zip(*other_enums) {|array| ... } -> nil
+ *
+ * With no block given, returns a new array +new_array+ of size self.size
+ * whose elements are arrays.
+ * Each nested array <tt>new_array[n]</tt>
+ * is of size <tt>other_enums.size+1</tt>, and contains:
+ *
+ * - The +n+-th element of self.
+ * - The +n+-th element of each of the +other_enums+.
+ *
+ * If all +other_enums+ and self are the same size,
+ * all elements are included in the result, and there is no +nil+-filling:
+ *
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2, :b3]
+ * c = [:c0, :c1, :c2, :c3]
+ * d = a.zip(b, c)
+ * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
+ *
+ * f = {foo: 0, bar: 1, baz: 2}
+ * g = {goo: 3, gar: 4, gaz: 5}
+ * h = {hoo: 6, har: 7, haz: 8}
+ * d = f.zip(g, h)
+ * d # => [
+ * # [[:foo, 0], [:goo, 3], [:hoo, 6]],
+ * # [[:bar, 1], [:gar, 4], [:har, 7]],
+ * # [[:baz, 2], [:gaz, 5], [:haz, 8]]
+ * # ]
+ *
+ * If any enumerable in other_enums is smaller than self,
+ * fills to <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 enumerable in other_enums is larger than self,
+ * its trailing elements are ignored:
+ *
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2, :b3, :b4]
+ * c = [:c0, :c1, :c2, :c3, :c4, :c5]
+ * d = a.zip(b, c)
+ * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
+ *
+ * When a block is given, calls the block with each of the sub-arrays
+ * (formed as above); returns nil:
+ *
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2, :b3]
+ * c = [:c0, :c1, :c2, :c3]
+ * a.zip(b, c) {|sub_array| p sub_array} # => nil
+ *
+ * Output:
+ *
+ * [:a0, :b0, :c0]
+ * [:a1, :b1, :c1]
+ * [:a2, :b2, :c2]
+ * [:a3, :b3, :c3]
*
*/
@@ -2917,26 +3266,26 @@ enum_zip(int argc, VALUE *argv, VALUE obj)
argv = RARRAY_PTR(args);
for (i=0; i<argc; i++) {
- VALUE ary = rb_check_array_type(argv[i]);
- if (NIL_P(ary)) {
- allary = FALSE;
- break;
- }
- argv[i] = ary;
+ VALUE ary = rb_check_array_type(argv[i]);
+ if (NIL_P(ary)) {
+ allary = FALSE;
+ break;
+ }
+ argv[i] = ary;
}
if (!allary) {
- static const VALUE sym_each = STATIC_ID2SYM(id_each);
- CONST_ID(conv, "to_enum");
- for (i=0; i<argc; i++) {
- if (!rb_respond_to(argv[i], id_each)) {
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
- rb_obj_class(argv[i]));
+ static const VALUE sym_each = STATIC_ID2SYM(id_each);
+ CONST_ID(conv, "to_enum");
+ for (i=0; i<argc; i++) {
+ if (!rb_respond_to(argv[i], id_each)) {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
+ rb_obj_class(argv[i]));
}
- argv[i] = rb_funcallv(argv[i], conv, 1, &sym_each);
- }
+ argv[i] = rb_funcallv(argv[i], conv, 1, &sym_each);
+ }
}
if (!rb_block_given_p()) {
- result = rb_ary_new();
+ result = rb_ary_new();
}
/* TODO: use NODE_DOT2 as memo(v, v, -) */
@@ -2957,13 +3306,16 @@ take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
/*
* call-seq:
- * enum.take(n) -> array
+ * take(n) -> array
*
- * Returns first n elements from <i>enum</i>.
+ * For non-negative integer +n+, returns the first +n+ elements:
*
- * a = [1, 2, 3, 4, 5, 0]
- * a.take(3) #=> [1, 2, 3]
- * a.take(30) #=> [1, 2, 3, 4, 5, 0]
+ * r = (1..4)
+ * r.take(2) # => [1, 2]
+ * r.take(0) # => []
+ *
+ * h = {foo: 0, bar: 1, baz: 2, bat: 3}
+ * h.take(2) # => [[:foo, 0], [:bar, 1]]
*
*/
@@ -2975,7 +3327,7 @@ enum_take(VALUE obj, VALUE n)
long len = NUM2LONG(n);
if (len < 0) {
- rb_raise(rb_eArgError, "attempt to take negative size");
+ rb_raise(rb_eArgError, "attempt to take negative size");
}
if (len == 0) return rb_ary_new2(0);
@@ -2996,16 +3348,20 @@ take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
/*
* call-seq:
- * enum.take_while { |obj| block } -> array
- * enum.take_while -> an_enumerator
+ * take_while {|element| ... } -> array
+ * take_while -> enumerator
+ *
+ * Calls the block with successive elements as long as the block
+ * returns a truthy value;
+ * returns an array of all elements up to that point:
*
- * 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.
+ * (1..4).take_while{|i| i < 3 } # => [1, 2]
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.take_while{|element| key, value = *element; value < 2 }
+ * # => [[:foo, 0], [:bar, 1]]
*
- * a = [1, 2, 3, 4, 5, 0]
- * a.take_while { |i| i < 3 } #=> [1, 2]
+ * With no block given, returns an Enumerator.
*
*/
@@ -3025,23 +3381,30 @@ drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
{
struct MEMO *memo = MEMO_CAST(args);
if (memo->u3.cnt == 0) {
- rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
+ rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
}
else {
- memo->u3.cnt--;
+ memo->u3.cnt--;
}
return Qnil;
}
/*
* call-seq:
- * enum.drop(n) -> array
+ * drop(n) -> array
*
- * Drops first n elements from <i>enum</i>, and returns rest elements
- * in an array.
+ * For positive integer +n+, returns an array containing
+ * all but the first +n+ elements:
*
- * a = [1, 2, 3, 4, 5, 0]
- * a.drop(3) #=> [4, 5, 0]
+ * r = (1..4)
+ * r.drop(3) # => [4]
+ * r.drop(2) # => [3, 4]
+ * r.drop(1) # => [2, 3, 4]
+ * r.drop(0) # => [1, 2, 3, 4]
+ * r.drop(50) # => []
+ *
+ * h = {foo: 0, bar: 1, baz: 2, bat: 3}
+ * h.drop(2) # => [[:baz, 2], [:bat, 3]]
*
*/
@@ -3053,7 +3416,7 @@ enum_drop(VALUE obj, VALUE n)
long len = NUM2LONG(n);
if (len < 0) {
- rb_raise(rb_eArgError, "attempt to drop negative size");
+ rb_raise(rb_eArgError, "attempt to drop negative size");
}
result = rb_ary_new();
@@ -3070,27 +3433,30 @@ drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
ENUM_WANT_SVALUE();
if (!memo->u3.state && !RTEST(enum_yield(argc, i))) {
- memo->u3.state = TRUE;
+ memo->u3.state = TRUE;
}
if (memo->u3.state) {
- rb_ary_push(memo->v1, i);
+ rb_ary_push(memo->v1, i);
}
return Qnil;
}
/*
* call-seq:
- * enum.drop_while { |obj| block } -> array
- * enum.drop_while -> an_enumerator
+ * drop_while {|element| ... } -> array
+ * drop_while -> enumerator
+ *
+ * Calls the block with successive elements as long as the block
+ * returns a truthy value;
+ * returns an array of all elements after that point:
*
- * Drops elements up to, but not including, the first element for
- * which the block returns +nil+ or +false+ and returns an array
- * containing the remaining elements.
*
- * If no block is given, an enumerator is returned instead.
+ * (1..4).drop_while{|i| i < 3 } # => [3, 4]
+ * h = {foo: 0, bar: 1, baz: 2}
+ * a = h.drop_while{|element| key, value = *element; value < 2 }
+ * a # => [[:baz, 2]]
*
- * a = [1, 2, 3, 4, 5, 0]
- * a.drop_while { |i| i < 3 } #=> [3, 4, 5, 0]
+ * With no block given, returns an Enumerator.
*
*/
@@ -3125,8 +3491,8 @@ enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
VALUE size;
if (args && (RARRAY_LEN(args) > 0)) {
- n = RARRAY_AREF(args, 0);
- if (!NIL_P(n)) mul = NUM2LONG(n);
+ n = RARRAY_AREF(args, 0);
+ if (!NIL_P(n)) mul = NUM2LONG(n);
}
size = enum_size(self, args, 0);
@@ -3140,22 +3506,28 @@ enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
/*
* call-seq:
- * enum.cycle(n=nil) { |obj| block } -> nil
- * enum.cycle(n=nil) -> an_enumerator
+ * cycle(n = nil) {|element| ...} -> nil
+ * cycle(n = nil) -> enumerator
*
- * Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
- * times or forever if none or +nil+ is given. If a non-positive
- * number is given or the collection is empty, does nothing. Returns
- * +nil+ if the loop has finished without getting interrupted.
+ * When called with positive integer argument +n+ and a block,
+ * calls the block with each element, then does so again,
+ * until it has done so +n+ times; returns +nil+:
*
- * Enumerable#cycle saves elements in an internal array so changes
- * to <i>enum</i> after the first pass have no effect.
+ * a = []
+ * (1..4).cycle(3) {|element| a.push(element) } # => nil
+ * a # => [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
+ * a = []
+ * ('a'..'d').cycle(2) {|element| a.push(element) }
+ * a # => ["a", "b", "c", "d", "a", "b", "c", "d"]
+ * a = []
+ * {foo: 0, bar: 1, baz: 2}.cycle(2) {|element| a.push(element) }
+ * a # => [[:foo, 0], [:bar, 1], [:baz, 2], [:foo, 0], [:bar, 1], [:baz, 2]]
*
- * If no block is given, an enumerator is returned instead.
+ * If count is zero or negative, does not call the block.
*
- * a = ["a", "b", "c"]
- * a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
- * a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
+ * When called with a block and +n+ is +nil+, cycles forever.
+ *
+ * When no block is given, returns an Enumerator.
*
*/
@@ -3183,7 +3555,7 @@ enum_cycle(int argc, VALUE *argv, VALUE obj)
if (len == 0) return Qnil;
while (n < 0 || 0 < --n) {
for (i=0; i<len; i++) {
- enum_yield_array(RARRAY_AREF(ary, i));
+ enum_yield_array(RARRAY_AREF(ary, i));
}
}
return Qnil;
@@ -3210,22 +3582,22 @@ chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
if (v == alone) {
if (!NIL_P(argp->prev_value)) {
- s = rb_assoc_new(argp->prev_value, argp->prev_elts);
+ s = rb_assoc_new(argp->prev_value, argp->prev_elts);
rb_funcallv(argp->yielder, id_lshift, 1, &s);
argp->prev_value = argp->prev_elts = Qnil;
}
- v = rb_assoc_new(v, rb_ary_new3(1, i));
+ v = rb_assoc_new(v, rb_ary_new3(1, i));
rb_funcallv(argp->yielder, id_lshift, 1, &v);
}
else if (NIL_P(v) || v == separator) {
if (!NIL_P(argp->prev_value)) {
- v = rb_assoc_new(argp->prev_value, argp->prev_elts);
+ v = rb_assoc_new(argp->prev_value, argp->prev_elts);
rb_funcallv(argp->yielder, id_lshift, 1, &v);
argp->prev_value = argp->prev_elts = Qnil;
}
}
else if (SYMBOL_P(v) && (s = rb_sym2str(v), RSTRING_PTR(s)[0] == '_')) {
- rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
+ rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
}
else {
if (NIL_P(argp->prev_value)) {
@@ -3237,7 +3609,7 @@ chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
rb_ary_push(argp->prev_elts, i);
}
else {
- s = rb_assoc_new(argp->prev_value, argp->prev_elts);
+ s = rb_assoc_new(argp->prev_value, argp->prev_elts);
rb_funcallv(argp->yielder, id_lshift, 1, &s);
argp->prev_value = v;
argp->prev_elts = rb_ary_new3(1, i);
@@ -3263,58 +3635,86 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
memo = MEMO_FOR(struct chunk_arg, arg);
if (!NIL_P(memo->prev_elts)) {
- arg = rb_assoc_new(memo->prev_value, memo->prev_elts);
- rb_funcallv(memo->yielder, id_lshift, 1, &arg);
+ arg = rb_assoc_new(memo->prev_value, memo->prev_elts);
+ rb_funcallv(memo->yielder, id_lshift, 1, &arg);
}
return Qnil;
}
/*
* call-seq:
- * enum.chunk { |elt| ... } -> an_enumerator
+ * chunk {|array| ... } -> enumerator
*
- * Enumerates over the items, chunking them together based on the return
- * value of the block.
+ * Each element in the returned enumerator is a 2-element array consisting of:
*
- * Consecutive elements which return the same block value are chunked together.
+ * - A value returned by the block.
+ * - An array ("chunk") containing the element for which that value was returned,
+ * and all following elements for which the block returned the same value:
*
- * For example, consecutive even numbers and odd numbers can be
- * chunked as follows.
+ * So that:
*
- * [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
- * n.even?
- * }.each { |even, ary|
- * p [even, ary]
- * }
- * #=> [false, [3, 1]]
- * # [true, [4]]
- * # [false, [1, 5, 9]]
- * # [true, [2, 6]]
- * # [false, [5, 3, 5]]
+ * - Each block return value that is different from its predecessor
+ * begins a new chunk.
+ * - Each block return value that is the same as its predecessor
+ * continues the same chunk.
+ *
+ * Example:
+ *
+ * e = (0..10).chunk {|i| (i / 3).floor } # => #<Enumerator: ...>
+ * # The enumerator elements.
+ * e.next # => [0, [0, 1, 2]]
+ * e.next # => [1, [3, 4, 5]]
+ * e.next # => [2, [6, 7, 8]]
+ * e.next # => [3, [9, 10]]
+ *
+ * \Method +chunk+ is especially useful for an enumerable that is already sorted.
+ * This example counts words for each initial letter in a large array of words:
+ *
+ * # Get sorted words from a web page.
+ * url = 'https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt'
+ * words = URI::open(url).readlines
+ * # Make chunks, one for each letter.
+ * e = words.chunk {|word| word.upcase[0] } # => #<Enumerator: ...>
+ * # Display 'A' through 'F'.
+ * e.each {|c, words| p [c, words.length]; break if c == 'F' }
*
- * This method is especially useful for sorted series of elements.
- * The following example counts words for each initial letter.
+ * Output:
*
- * open("/usr/share/dict/words", "r:iso-8859-1") { |f|
- * f.chunk { |line| line.upcase.ord }.each { |ch, lines| p [ch.chr, lines.length] }
+ * ["A", 17096]
+ * ["B", 11070]
+ * ["C", 19901]
+ * ["D", 10896]
+ * ["E", 8736]
+ * ["F", 6860]
+ *
+ * You can use the special symbol <tt>:_alone</tt> to force an element
+ * into its own separate chuck:
+ *
+ * a = [0, 0, 1, 1]
+ * e = a.chunk{|i| i.even? ? :_alone : true }
+ * e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]]
+ *
+ * For example, you can put each line that contains a URL into its own chunk:
+ *
+ * pattern = /http/
+ * open(filename) { |f|
+ * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
+ * pp lines
+ * }
* }
- * #=> ["\n", 1]
- * # ["A", 1327]
- * # ["B", 1372]
- * # ["C", 1507]
- * # ["D", 791]
- * # ...
*
- * The following key values have special meaning:
- * - +nil+ and +:_separator+ specifies that the elements should be dropped.
- * - +:_alone+ specifies that the element should be chunked by itself.
+ * You can use the special symbol <tt>:_separator</tt> or +nil+
+ * to force an element to be ignored (not included in any chunk):
*
- * Any other symbols that begin with an underscore will raise an error:
+ * a = [0, 0, -1, 1, 1]
+ * e = a.chunk{|i| i < 0 ? :_separator : true }
+ * e.to_a # => [[true, [0, 0]], [true, [1, 1]]]
*
- * items.chunk { |item| :_underscore }
- * #=> RuntimeError: symbols beginning with an underscore are reserved
+ * Note that the separator does end the chunk:
*
- * +nil+ and +:_separator+ can be used to ignore some elements.
+ * a = [0, 0, -1, 1, -1, 1]
+ * e = a.chunk{|i| i < 0 ? :_separator : true }
+ * e.to_a # => [[true, [0, 0]], [true, [1]], [true, [1]]]
*
* For example, the sequence of hyphens in svn log can be eliminated as follows:
*
@@ -3344,18 +3744,6 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
* pp lines
* }
*
- * +:_alone+ can be used to force items into their own chunk.
- * For example, you can put lines that contain a URL by themselves,
- * and chunk the rest of the lines together, like this:
- *
- * pattern = /http/
- * open(filename) { |f|
- * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
- * pp lines
- * }
- * }
- *
- * If no block is given, an enumerator to `chunk` is returned instead.
*/
static VALUE
enum_chunk(VALUE enumerable)
@@ -3428,24 +3816,41 @@ slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
/*
* call-seq:
- * enum.slice_before(pattern) -> an_enumerator
- * enum.slice_before { |elt| bool } -> an_enumerator
+ * slice_before(pattern) -> enumerator
+ * slice_before {|elt| ... } -> enumerator
*
- * Creates an enumerator for each chunked elements.
- * The beginnings of chunks are defined by _pattern_ and the block.
-
- * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
- * returns <code>true</code> for the element, the element is beginning of a
- * chunk.
-
- * The <code>===</code> and _block_ is called from the first element to the last
- * element of _enum_. The result for the first element is ignored.
-
- * The result enumerator yields the chunked elements as an array.
- * So +each+ method can be called as follows:
+ * With argument +pattern+, returns an enumerator that uses the pattern
+ * to partition elements into arrays ("slices").
+ * An element begins a new slice if <tt>element === pattern</tt>
+ * (or if it is the first element).
+ *
+ * a = %w[foo bar fop for baz fob fog bam foy]
+ * e = a.slice_before(/ba/) # => #<Enumerator: ...>
+ * e.each {|array| p array }
+ *
+ * Output:
+ *
+ * ["foo"]
+ * ["bar", "fop", "for"]
+ * ["baz", "fob", "fog"]
+ * ["bam", "foy"]
*
- * enum.slice_before(pattern).each { |ary| ... }
- * enum.slice_before { |elt| bool }.each { |ary| ... }
+ * With a block, returns an enumerator that uses the block
+ * to partition elements into arrays.
+ * An element begins a new slice if its block return is a truthy value
+ * (or if it is the first element):
+ *
+ * e = (1..20).slice_before {|i| i % 4 == 2 } # => #<Enumerator: ...>
+ * e.each {|array| p array }
+ *
+ * Output:
+ *
+ * [1]
+ * [2, 3, 4, 5]
+ * [6, 7, 8, 9]
+ * [10, 11, 12, 13]
+ * [14, 15, 16, 17]
+ * [18, 19, 20]
*
* Other methods of the Enumerator class and Enumerable module,
* such as +to_a+, +map+, etc., are also usable.
@@ -3463,7 +3868,6 @@ slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
* f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
* }
*
- *
* "svn proplist -R" produces multiline output for each file.
* They can be chunked as follows:
*
@@ -3734,15 +4138,15 @@ slicewhen_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
ENUM_WANT_SVALUE();
- if (memo->prev_elt == Qundef) {
+ if (UNDEF_P(memo->prev_elt)) {
/* The first element */
memo->prev_elt = i;
memo->prev_elts = rb_ary_new3(1, i);
}
else {
- VALUE args[2];
- args[0] = memo->prev_elt;
- args[1] = i;
+ VALUE args[2];
+ args[0] = memo->prev_elt;
+ args[1] = i;
split_p = RTEST(rb_funcallv(memo->pred, id_call, 2, args));
UPDATE_MEMO;
@@ -3771,7 +4175,7 @@ slicewhen_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
VALUE enumerable;
VALUE arg;
struct slicewhen_arg *memo =
- NEW_PARTIAL_MEMO_FOR(struct slicewhen_arg, arg, inverted);
+ NEW_PARTIAL_MEMO_FOR(struct slicewhen_arg, arg, inverted);
enumerable = rb_ivar_get(enumerator, id_slicewhen_enum);
memo->pred = rb_attr_get(enumerator, id_slicewhen_pred);
@@ -3974,7 +4378,7 @@ sum_iter_bignum(VALUE i, struct enum_sum_memo *memo)
static void
sum_iter_rational(VALUE i, struct enum_sum_memo *memo)
{
- if (memo->r == Qundef) {
+ if (UNDEF_P(memo->r)) {
memo->r = i;
}
else {
@@ -4055,7 +4459,7 @@ sum_iter(VALUE i, struct enum_sum_memo *memo)
}
else switch (TYPE(memo->v)) {
default: sum_iter_some_value(i, memo); return;
- case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return;
+ case T_FLOAT:
case T_FIXNUM:
case T_BIGNUM:
case T_RATIONAL:
@@ -4124,36 +4528,35 @@ int_range_sum(VALUE beg, VALUE end, int excl, VALUE init)
}
/*
- * call-seq:
- * enum.sum(init=0) -> number
- * enum.sum(init=0) {|e| expr } -> number
- *
- * Returns the sum of elements in an Enumerable.
+ * call-seq:
+ * sum(initial_value = 0) -> number
+ * sum(initial_value = 0) {|element| ... } -> object
*
- * If a block is given, the block is applied to each element
- * before addition.
+ * With no block given,
+ * returns the sum of +initial_value+ and the elements:
*
- * If <i>enum</i> is empty, it returns <i>init</i>.
+ * (1..100).sum # => 5050
+ * (1..100).sum(1) # => 5051
+ * ('a'..'d').sum('foo') # => "fooabcd"
*
- * For example:
+ * Generally, the sum is computed using methods <tt>+</tt> and +each+;
+ * for performance optimizations, those methods may not be used,
+ * and so any redefinition of those methods may not have effect here.
*
- * { 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
- * (1..10).sum #=> 55
- * (1..10).sum {|v| v * 2 } #=> 110
- * ('a'..'z').sum #=> TypeError
+ * One such optimization: When possible, computes using Gauss's summation
+ * formula <em>n(n+1)/2</em>:
*
- * This method can be used for non-numeric objects by
- * explicit <i>init</i> argument.
+ * 100 * (100 + 1) / 2 # => 5050
*
- * { 1 => 10, 2 => 20 }.sum([]) #=> [1, 10, 2, 20]
- * "a\nb\nc".each_line.lazy.map(&:chomp).sum("") #=> "abc"
+ * With a block given, calls the block with each element;
+ * returns the sum of +initial_value+ and the block return values:
*
- * If the method is applied to an Integer range without a block,
- * the sum is not done by iteration, but instead using Gauss's summation
- * formula.
+ * (1..4).sum {|i| i*i } # => 30
+ * (1..4).sum(100) {|i| i*i } # => 130
+ * h = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5}
+ * h.sum {|key, value| value.odd? ? value : 0 } # => 9
+ * ('a'..'f').sum('x') {|c| c < 'd' ? c : '' } # => "xabc"
*
- * Enumerable#sum method may not respect method redefinition of "+"
- * methods such as Integer#+, or "each" methods such as Range#each.
*/
static VALUE
enum_sum(int argc, VALUE* argv, VALUE obj)
@@ -4178,8 +4581,8 @@ enum_sum(int argc, VALUE* argv, VALUE obj)
if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
if (!memo.block_given && !memo.float_value &&
- (FIXNUM_P(beg) || RB_TYPE_P(beg, T_BIGNUM)) &&
- (FIXNUM_P(end) || RB_TYPE_P(end, T_BIGNUM))) {
+ (FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
+ (FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
return int_range_sum(beg, end, excl, memo.v);
}
}
@@ -4196,7 +4599,7 @@ enum_sum(int argc, VALUE* argv, VALUE obj)
else {
if (memo.n != 0)
memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
- if (memo.r != Qundef) {
+ if (!UNDEF_P(memo.r)) {
memo.v = rb_rational_plus(memo.r, memo.v);
}
return memo.v;
@@ -4221,12 +4624,23 @@ uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
/*
* call-seq:
- * enum.uniq -> new_ary
- * enum.uniq { |item| ... } -> new_ary
+ * uniq -> array
+ * uniq {|element| ... } -> array
+ *
+ * With no block, returns a new array containing only unique elements;
+ * the array has no two elements +e0+ and +e1+ such that <tt>e0.eql?(e1)</tt>:
+ *
+ * %w[a b c c b a a b c].uniq # => ["a", "b", "c"]
+ * [0, 1, 2, 2, 1, 0, 0, 1, 2].uniq # => [0, 1, 2]
*
- * Returns a new array by removing duplicate values in +self+.
+ * With a block, returns a new array containing only for which the block
+ * returns a unique value:
+ *
+ * a = [0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1]
+ * a.uniq {|i| i.even? ? i : 0 } # => [0, 2, 4]
+ * a = %w[a b c d e e d c b a a b c d e]
+ a.uniq {|c| c < 'c' } # => ["a", "c"]
*
- * See also Array#uniq.
*/
static VALUE
@@ -4234,7 +4648,7 @@ enum_uniq(VALUE obj)
{
VALUE hash, ret;
rb_block_call_func *const func =
- rb_block_given_p() ? uniq_iter : uniq_func;
+ rb_block_given_p() ? uniq_iter : uniq_func;
hash = rb_obj_hide(rb_hash_new());
rb_block_call(obj, id_each, 0, 0, func, hash);
@@ -4256,21 +4670,13 @@ compact_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
/*
* call-seq:
- * enum.compact -> array
- *
- * Returns an array of all non-+nil+ elements from enumeration.
+ * compact -> array
*
- * def with_nils
- * yield 1
- * yield 2
- * yield nil
- * yield 3
- * end
+ * Returns an array of all non-+nil+ elements:
*
- * to_enum(:with_nils).compact
- * # => [1, 2, 3]
+ * a = [nil, 0, nil, 'a', false, nil, false, nil, 'a', nil, 0, nil]
+ * a.compact # => [0, "a", false, false, "a", 0]
*
- * See also Array#compact.
*/
static VALUE
@@ -4289,132 +4695,173 @@ enum_compact(VALUE obj)
* == What's Here
*
* \Module \Enumerable provides methods that are useful to a collection class for:
- * - {Querying}[#module-Enumerable-label-Methods+for+Querying]
- * - {Fetching}[#module-Enumerable-label-Methods+for+Fetching]
- * - {Searching}[#module-Enumerable-label-Methods+for+Searching]
- * - {Sorting}[#module-Enumerable-label-Methods+for+Sorting]
- * - {Iterating}[#module-Enumerable-label-Methods+for+Iterating]
- * - {And more....}[#module-Enumerable-label-Other+Methods]
+ *
+ * - {Querying}[rdoc-ref:Enumerable@Methods+for+Querying]
+ * - {Fetching}[rdoc-ref:Enumerable@Methods+for+Fetching]
+ * - {Searching}[rdoc-ref:Enumerable@Methods+for+Searching]
+ * - {Sorting}[rdoc-ref:Enumerable@Methods+for+Sorting]
+ * - {Iterating}[rdoc-ref:Enumerable@Methods+for+Iterating]
+ * - {And more....}[rdoc-ref:Enumerable@Other+Methods]
*
* === Methods for Querying
*
* These methods return information about the \Enumerable other than the elements themselves:
*
- * #include?, #member?:: Returns +true+ if self == object, +false+ otherwise.
- * #all?:: Returns +true+ if all elements meet a specified criterion; +false+ otherwise.
- * #any?:: Returns +true+ if any element meets a specified criterion; +false+ otherwise.
- * #none?:: Returns +true+ if no element meets a specified criterion; +false+ otherwise.
- * #one?:: Returns +true+ if exactly one element meets a specified criterion; +false+ otherwise.
- * #count:: Returns the count of elements,
- * based on an argument or block criterion, if given.
- * #tally:: Returns a new \Hash containing the counts of occurrences of each element.
+ * - #include?, #member?: Returns +true+ if <tt>self == object</tt>, +false+ otherwise.
+ * - #all?: Returns +true+ if all elements meet a specified criterion; +false+ otherwise.
+ * - #any?: Returns +true+ if any element meets a specified criterion; +false+ otherwise.
+ * - #none?: Returns +true+ if no element meets a specified criterion; +false+ otherwise.
+ * - #one?: Returns +true+ if exactly one element meets a specified criterion; +false+ otherwise.
+ * - #count: Returns the count of elements,
+ * based on an argument or block criterion, if given.
+ * - #tally: Returns a new \Hash containing the counts of occurrences of each element.
*
* === Methods for Fetching
*
* These methods return entries from the \Enumerable, without modifying it:
*
* <i>Leading, trailing, or all elements</i>:
- * #entries, #to_a:: Returns all elements.
- * #first:: Returns the first element or leading elements.
- * #take:: Returns a specified number of leading elements.
- * #drop:: Returns a specified number of trailing elements.
- * #take_while:: Returns leading elements as specified by the given block.
- * #drop_while:: Returns trailing elements as specified by the given block.
+ *
+ * - #entries, #to_a: Returns all elements.
+ * - #first: Returns the first element or leading elements.
+ * - #take: Returns a specified number of leading elements.
+ * - #drop: Returns a specified number of trailing elements.
+ * - #take_while: Returns leading elements as specified by the given block.
+ * - #drop_while: Returns trailing elements as specified by the given block.
*
* <i>Minimum and maximum value elements</i>:
- * #min:: Returns the elements whose values are smallest among the elements,
- * as determined by <tt><=></tt> or a given block.
- * #max:: Returns the elements whose values are largest among the elements,
- * as determined by <tt><=></tt> or a given block.
- * #minmax:: Returns a 2-element \Array containing the smallest and largest elements.
- * #min_by:: Returns the smallest element, as determined by the given block.
- * #max_by:: Returns the largest element, as determined by the given block.
- * #minmax_by:: Returns the smallest and largest elements, as determined by the given block.
+ *
+ * - #min: Returns the elements whose values are smallest among the elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #max: Returns the elements whose values are largest among the elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #minmax: Returns a 2-element \Array containing the smallest and largest elements.
+ * - #min_by: Returns the smallest element, as determined by the given block.
+ * - #max_by: Returns the largest element, as determined by the given block.
+ * - #minmax_by: Returns the smallest and largest elements, as determined by the given block.
*
* <i>Groups, slices, and partitions</i>:
- * #group_by:: Returns a \Hash that partitions the elements into groups.
- * #partition:: Returns elements partitioned into two new Arrays, as determined by the given block.
- * #slice_after:: Returns a new \Enumerator whose entries are a partition of +self+,
- based either on a given +object+ or a given block.
- * #slice_before:: Returns a new \Enumerator whose entries are a partition of +self+,
- based either on a given +object+ or a given block.
- * #slice_when:: Returns a new \Enumerator whose entries are a partition of +self+
- based on the given block.
- * #chunk:: Returns elements organized into chunks as specified by the given block.
- * #chunk_while:: Returns elements organized into chunks as specified by the given block.
+ *
+ * - #group_by: Returns a \Hash that partitions the elements into groups.
+ * - #partition: Returns elements partitioned into two new Arrays, as determined by the given block.
+ * - #slice_after: Returns a new \Enumerator whose entries are a partition of +self+,
+ based either on a given +object+ or a given block.
+ * - #slice_before: Returns a new \Enumerator whose entries are a partition of +self+,
+ based either on a given +object+ or a given block.
+ * - #slice_when: Returns a new \Enumerator whose entries are a partition of +self+
+ based on the given block.
+ * - #chunk: Returns elements organized into chunks as specified by the given block.
+ * - #chunk_while: Returns elements organized into chunks as specified by the given block.
*
* === Methods for Searching and Filtering
*
- * These methods return elements that meet a specified criterion.
+ * These methods return elements that meet a specified criterion:
*
- * #find, #detect:: Returns an element selected by the block.
- * #find_all, #filter, #select:: Returns elements selected by the block.
- * #find_index:: Returns the index of an element selected by a given object or block.
- * #reject:: Returns elements not rejected by the block.
- * #uniq:: Returns elements that are not duplicates.
+ * - #find, #detect: Returns an element selected by the block.
+ * - #find_all, #filter, #select: Returns elements selected by the block.
+ * - #find_index: Returns the index of an element selected by a given object or block.
+ * - #reject: Returns elements not rejected by the block.
+ * - #uniq: Returns elements that are not duplicates.
*
* === Methods for Sorting
*
- * These methods return elements in sorted order.
+ * These methods return elements in sorted order:
*
- * #sort:: Returns the elements, sorted by <tt><=></tt> or the given block.
- * #sort_by:: Returns the elements, sorted by the given block.
+ * - #sort: Returns the elements, sorted by <tt><=></tt> or the given block.
+ * - #sort_by: Returns the elements, sorted by the given block.
*
* === Methods for Iterating
*
- * #each_entry:: Calls the block with each successive element
- * (slightly different from #each).
- * #each_with_index:: Calls the block with each successive element and its index.
- * #each_with_object:: Calls the block with each successive element and a given object.
- * #each_slice:: Calls the block with successive non-overlapping slices.
- * #each_cons:: Calls the block with successive overlapping slices.
- * (different from #each_slice).
- * #reverse_each:: Calls the block with each successive element, in reverse order.
+ * - #each_entry: Calls the block with each successive element
+ * (slightly different from #each).
+ * - #each_with_index: Calls the block with each successive element and its index.
+ * - #each_with_object: Calls the block with each successive element and a given object.
+ * - #each_slice: Calls the block with successive non-overlapping slices.
+ * - #each_cons: Calls the block with successive overlapping slices.
+ * (different from #each_slice).
+ * - #reverse_each: Calls the block with each successive element, in reverse order.
*
* === Other Methods
*
- * #map, #collect:: Returns objects returned by the block.
- * #filter_map:: Returns truthy objects returned by the block.
- * #flat_map, #collect_concat:: Returns flattened objects returned by the block.
- * #grep:: Returns elements selected by a given object
- * or objects returned by a given block.
- * #grep_v:: Returns elements selected by a given object
- * or objects returned by a given block.
- * #reduce, #inject:: Returns the object formed by combining all elements.
- * #sum:: Returns the sum of the elements, using method +++.
- * #zip:: Combines each element with elements from other enumerables;
- * returns the n-tuples or calls the block with each.
- * #cycle:: Calls the block with each element, cycling repeatedly.
+ * - #map, #collect: Returns objects returned by the block.
+ * - #filter_map: Returns truthy objects returned by the block.
+ * - #flat_map, #collect_concat: Returns flattened objects returned by the block.
+ * - #grep: Returns elements selected by a given object
+ * or objects returned by a given block.
+ * - #grep_v: Returns elements selected by a given object
+ * or objects returned by a given block.
+ * - #reduce, #inject: Returns the object formed by combining all elements.
+ * - #sum: Returns the sum of the elements, using method <tt>+</tt>.
+ * - #zip: Combines each element with elements from other enumerables;
+ * returns the n-tuples or calls the block with each.
+ * - #cycle: Calls the block with each element, cycling repeatedly.
*
* == Usage
*
* To use module \Enumerable in a collection class:
+ *
* - Include it:
+ *
* include Enumerable
+ *
* - Implement method <tt>#each</tt>
* which must yield successive elements of the collection.
- * This method will be called by almost any \Enumerable method.
+ * The method will be called by almost any \Enumerable method.
+ *
+ * Example:
*
- * == \Enumerable in Ruby Core Classes
- * Some Ruby classes include \Enumerable:
+ * class Foo
+ * include Enumerable
+ * def each
+ * yield 1
+ * yield 1, 2
+ * yield
+ * end
+ * end
+ * Foo.new.each_entry{ |element| p element }
+ *
+ * Output:
+ *
+ * 1
+ * [1, 2]
+ * nil
+ *
+ * == \Enumerable in Ruby Classes
+ *
+ * These Ruby core classes include (or extend) \Enumerable:
+ *
+ * - ARGF
* - Array
* - Dir
+ * - Enumerator
+ * - ENV (extends)
* - Hash
* - IO
* - Range
- * - Set
* - Struct
+ *
+ * These Ruby standard library classes include \Enumerable:
+ *
+ * - CSV
+ * - CSV::Table
+ * - CSV::Row
+ * - Set
+ *
* Virtually all methods in \Enumerable call method +#each+ in the including class:
+ *
* - <tt>Hash#each</tt> yields the next key-value pair as a 2-element \Array.
* - <tt>Struct#each</tt> yields the next name-value pair as a 2-element \Array.
* - For the other classes above, +#each+ yields the next object from the collection.
*
* == About the Examples
+ *
* The example code snippets for the \Enumerable methods:
+ *
* - Always show the use of one or more \Array-like classes (often \Array itself).
* - Sometimes show the use of a \Hash-like class.
* For some methods, though, the usage would not make sense,
* and so it is not shown. Example: #tally would find exactly one of each \Hash entry.
+ *
*/
void
diff --git a/enumerator.c b/enumerator.c
index 9c91e999b8..d587b63d32 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -20,6 +20,7 @@
#include "id.h"
#include "internal.h"
+#include "internal/class.h"
#include "internal/enumerator.h"
#include "internal/error.h"
#include "internal/hash.h"
@@ -72,6 +73,8 @@
* puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
* # => ["0:foo", "1:bar", "2:baz"]
*
+ * == External Iteration
+ *
* An Enumerator can also be used as an external iterator.
* For example, Enumerator#next returns the next value of the iterator
* or raises StopIteration if the Enumerator is at the end.
@@ -82,15 +85,44 @@
* 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.
+ * +next+, +next_values+, +peek+ and +peek_values+ are the only methods
+ * which use external iteration (and Array#zip(Enumerable-not-Array) which uses +next+).
+ *
+ * These methods do not affect other internal enumeration methods,
+ * unless the underlying iteration method itself has side-effect, e.g. IO#each_line.
+ *
+ * External iteration differs *significantly* from internal iteration
+ * due to using a Fiber:
+ * - The Fiber adds some overhead compared to internal enumeration.
+ * - The stacktrace will only include the stack from the Enumerator, not above.
+ * - Fiber-local variables are *not* inherited inside the Enumerator Fiber,
+ * which instead starts with no Fiber-local variables.
+ * - Fiber storage variables *are* inherited and are designed
+ * to handle Enumerator Fibers. Assigning to a Fiber storage variable
+ * only affects the current Fiber, so if you want to change state
+ * in the caller Fiber of the Enumerator Fiber, you need to use an
+ * extra indirection (e.g., use some object in the Fiber storage
+ * variable and mutate some ivar of it).
+ *
+ * Concretely:
+ * Thread.current[:fiber_local] = 1
+ * Fiber[:storage_var] = 1
+ * e = Enumerator.new do |y|
+ * p Thread.current[:fiber_local] # for external iteration: nil, for internal iteration: 1
+ * p Fiber[:storage_var] # => 1, inherited
+ * Fiber[:storage_var] += 1
+ * y << 42
+ * end
+ *
+ * p e.next # => 42
+ * p Fiber[:storage_var] # => 1 (it ran in a different Fiber)
*
- * Moreover, implementation typically uses fibers so performance could be
- * slower and exception stacktraces different than expected.
+ * e.each { p _1 }
+ * p Fiber[:storage_var] # => 2 (it ran in the same Fiber/"stack" as the current Fiber)
*
- * You can use this to implement an internal iterator as follows:
+ * == Convert External Iteration to Internal Iteration
+ *
+ * You can use an external iterator to implement an internal iterator as follows:
*
* def ext_each(e)
* while true
@@ -125,14 +157,17 @@
*/
VALUE rb_cEnumerator;
static VALUE rb_cLazy;
-static ID id_rewind, id_new, id_to_enum;
+static ID id_rewind, id_new, id_to_enum, id_each_entry;
static ID id_next, id_result, id_receiver, id_arguments, id_memo, id_method, id_force;
static ID id_begin, id_end, id_step, id_exclude_end;
static VALUE sym_each, sym_cycle, sym_yield;
static VALUE lazy_use_super_method;
+extern ID ruby_static_id_cause;
+
#define id_call idCall
+#define id_cause ruby_static_id_cause
#define id_each idEach
#define id_eqq idEqq
#define id_initialize idInitialize
@@ -173,9 +208,11 @@ struct producer {
typedef struct MEMO *lazyenum_proc_func(VALUE, struct MEMO *, VALUE, long);
typedef VALUE lazyenum_size_func(VALUE, VALUE);
+typedef int lazyenum_precheck_func(VALUE proc_entry);
typedef struct {
lazyenum_proc_func *proc;
lazyenum_size_func *size;
+ lazyenum_precheck_func *precheck;
} lazyenum_funcs;
struct proc_entry {
@@ -194,6 +231,12 @@ struct enum_chain {
long pos;
};
+static VALUE rb_cEnumProduct;
+
+struct enum_product {
+ VALUE enums;
+};
+
VALUE rb_cArithSeq;
/*
@@ -240,9 +283,9 @@ enumerator_memsize(const void *p)
static const rb_data_type_t enumerator_data_type = {
"enumerator",
{
- enumerator_mark,
- enumerator_free,
- enumerator_memsize,
+ enumerator_mark,
+ enumerator_free,
+ enumerator_memsize,
enumerator_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
@@ -254,8 +297,8 @@ enumerator_ptr(VALUE obj)
struct enumerator *ptr;
TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr);
- if (!ptr || ptr->obj == Qundef) {
- rb_raise(rb_eArgError, "uninitialized enumerator");
+ if (!ptr || UNDEF_P(ptr->obj)) {
+ rb_raise(rb_eArgError, "uninitialized enumerator");
}
return ptr;
}
@@ -287,9 +330,9 @@ proc_entry_memsize(const void *p)
static const rb_data_type_t proc_entry_data_type = {
"proc_entry",
{
- proc_entry_mark,
- proc_entry_free,
- proc_entry_memsize,
+ proc_entry_mark,
+ proc_entry_free,
+ proc_entry_memsize,
proc_entry_compact,
},
};
@@ -371,12 +414,12 @@ obj_to_enum(int argc, VALUE *argv, VALUE obj)
VALUE enumerator, meth = sym_each;
if (argc > 0) {
- --argc;
- meth = *argv++;
+ --argc;
+ meth = *argv++;
}
enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
if (rb_block_given_p()) {
- enumerator_ptr(enumerator)->size = rb_block_proc();
+ enumerator_ptr(enumerator)->size = rb_block_proc();
}
return enumerator;
}
@@ -402,7 +445,7 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
TypedData_Get_Struct(enum_obj, struct enumerator, &enumerator_data_type, ptr);
if (!ptr) {
- rb_raise(rb_eArgError, "unallocated enumerator");
+ rb_raise(rb_eArgError, "unallocated enumerator");
}
ptr->obj = obj;
@@ -482,14 +525,14 @@ enumerator_init_copy(VALUE obj, VALUE orig)
if (!OBJ_INIT_COPY(obj, orig)) return obj;
ptr0 = enumerator_ptr(orig);
if (ptr0->fib) {
- /* Fibers cannot be copied */
- rb_raise(rb_eTypeError, "can't copy execution context");
+ /* Fibers cannot be copied */
+ rb_raise(rb_eTypeError, "can't copy execution context");
}
TypedData_Get_Struct(obj, struct enumerator, &enumerator_data_type, ptr1);
if (!ptr1) {
- rb_raise(rb_eArgError, "unallocated enumerator");
+ rb_raise(rb_eArgError, "unallocated enumerator");
}
ptr1->obj = ptr0->obj;
@@ -513,8 +556,8 @@ rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
return rb_enumeratorize_with_size(obj, meth, argc, argv, 0);
}
-static VALUE
-lazy_to_enum_i(VALUE self, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat);
+static VALUE lazy_to_enum_i(VALUE self, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat);
+static int lazy_precheck(VALUE procs);
VALUE
rb_enumeratorize_with_size_kw(VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, int kw_splat)
@@ -547,8 +590,8 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
ID meth = e->meth;
if (e->args) {
- argc = RARRAY_LENINT(e->args);
- argv = RARRAY_CONST_PTR(e->args);
+ argc = RARRAY_LENINT(e->args);
+ argv = RARRAY_CONST_PTR(e->args);
}
return rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat);
}
@@ -592,25 +635,29 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg)
static VALUE
enumerator_each(int argc, VALUE *argv, VALUE obj)
{
+ struct enumerator *e = enumerator_ptr(obj);
+
if (argc > 0) {
- struct enumerator *e = enumerator_ptr(obj = rb_obj_dup(obj));
- VALUE args = e->args;
- if (args) {
+ VALUE args = (e = enumerator_ptr(obj = rb_obj_dup(obj)))->args;
+ if (args) {
#if SIZEOF_INT < SIZEOF_LONG
- /* check int range overflow */
- rb_long2int(RARRAY_LEN(args) + argc);
+ /* check int range overflow */
+ rb_long2int(RARRAY_LEN(args) + argc);
#endif
- args = rb_ary_dup(args);
- rb_ary_cat(args, argv, argc);
- }
- else {
- args = rb_ary_new4(argc, argv);
- }
- e->args = args;
+ args = rb_ary_dup(args);
+ rb_ary_cat(args, argv, argc);
+ }
+ else {
+ args = rb_ary_new4(argc, argv);
+ }
+ e->args = args;
e->size = Qnil;
e->size_fn = 0;
}
if (!rb_block_given_p()) return obj;
+
+ if (!lazy_precheck(e->procs)) return Qnil;
+
return enumerator_block_call(obj, 0, obj);
}
@@ -622,7 +669,7 @@ enumerator_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
MEMO_V1_SET(memo, rb_int_succ(idx));
if (argc <= 1)
- return rb_yield_values(2, val, idx);
+ return rb_yield_values(2, val, idx);
return rb_yield_values(2, rb_ary_new4(argc, argv), idx);
}
@@ -679,7 +726,7 @@ static VALUE
enumerator_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memo))
{
if (argc <= 1)
- return rb_yield_values(2, val, memo);
+ return rb_yield_values(2, val, memo);
return rb_yield_values(2, rb_ary_new4(argc, argv), memo);
}
@@ -729,7 +776,7 @@ next_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, obj))
VALUE feedvalue = Qnil;
VALUE args = rb_ary_new4(argc, argv);
rb_fiber_yield(1, &args);
- if (e->feedvalue != Qundef) {
+ if (!UNDEF_P(e->feedvalue)) {
feedvalue = e->feedvalue;
e->feedvalue = Qundef;
}
@@ -763,22 +810,30 @@ get_next_values(VALUE obj, struct enumerator *e)
{
VALUE curr, vs;
- if (e->stop_exc)
- rb_exc_raise(e->stop_exc);
+ if (e->stop_exc) {
+ VALUE exc = e->stop_exc;
+ VALUE result = rb_attr_get(exc, id_result);
+ VALUE mesg = rb_attr_get(exc, idMesg);
+ if (!NIL_P(mesg)) mesg = rb_str_dup(mesg);
+ VALUE stop_exc = rb_exc_new_str(rb_eStopIteration, mesg);
+ rb_ivar_set(stop_exc, id_cause, exc);
+ rb_ivar_set(stop_exc, id_result, result);
+ rb_exc_raise(stop_exc);
+ }
curr = rb_fiber_current();
if (!e->fib || !rb_fiber_alive_p(e->fib)) {
- next_init(obj, e);
+ next_init(obj, e);
}
vs = rb_fiber_resume(e->fib, 1, &curr);
if (e->stop_exc) {
- e->fib = 0;
- e->dst = Qnil;
- e->lookahead = Qundef;
- e->feedvalue = Qundef;
- rb_exc_raise(e->stop_exc);
+ e->fib = 0;
+ e->dst = Qnil;
+ e->lookahead = Qundef;
+ e->feedvalue = Qundef;
+ rb_exc_raise(e->stop_exc);
}
return vs;
}
@@ -834,7 +889,7 @@ enumerator_next_values(VALUE obj)
struct enumerator *e = enumerator_ptr(obj);
VALUE vs;
- if (e->lookahead != Qundef) {
+ if (!UNDEF_P(e->lookahead)) {
vs = e->lookahead;
e->lookahead = Qundef;
return vs;
@@ -895,7 +950,7 @@ enumerator_peek_values(VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
- if (e->lookahead == Qundef) {
+ if (UNDEF_P(e->lookahead)) {
e->lookahead = get_next_values(obj, e);
}
return e->lookahead;
@@ -1019,8 +1074,8 @@ enumerator_feed(VALUE obj, VALUE v)
{
struct enumerator *e = enumerator_ptr(obj);
- if (e->feedvalue != Qundef) {
- rb_raise(rb_eTypeError, "feed value already set");
+ if (!UNDEF_P(e->feedvalue)) {
+ rb_raise(rb_eTypeError, "feed value already set");
}
e->feedvalue = v;
@@ -1064,37 +1119,37 @@ inspect_enumerator(VALUE obj, VALUE dummy, int recur)
cname = rb_obj_class(obj);
- if (!e || e->obj == Qundef) {
- return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(cname));
+ if (!e || UNDEF_P(e->obj)) {
+ return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(cname));
}
if (recur) {
- str = rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(cname));
- return str;
+ str = rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(cname));
+ return str;
}
if (e->procs) {
- long i;
-
- eobj = generator_ptr(e->obj)->obj;
- /* In case procs chained enumerator traversing all proc entries manually */
- if (rb_obj_class(eobj) == cname) {
- str = rb_inspect(eobj);
- }
- else {
- str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(cname), eobj);
- }
- for (i = 0; i < RARRAY_LEN(e->procs); i++) {
- str = rb_sprintf("#<%"PRIsVALUE": %"PRIsVALUE, cname, str);
- append_method(RARRAY_AREF(e->procs, i), str, e->meth, e->args);
- rb_str_buf_cat2(str, ">");
- }
- return str;
+ long i;
+
+ eobj = generator_ptr(e->obj)->obj;
+ /* In case procs chained enumerator traversing all proc entries manually */
+ if (rb_obj_class(eobj) == cname) {
+ str = rb_inspect(eobj);
+ }
+ else {
+ str = rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(cname), eobj);
+ }
+ for (i = 0; i < RARRAY_LEN(e->procs); i++) {
+ str = rb_sprintf("#<%"PRIsVALUE": %"PRIsVALUE, cname, str);
+ append_method(RARRAY_AREF(e->procs, i), str, e->meth, e->args);
+ rb_str_buf_cat2(str, ">");
+ }
+ return str;
}
eobj = rb_attr_get(obj, id_receiver);
if (NIL_P(eobj)) {
- eobj = e->obj;
+ eobj = e->obj;
}
/* (1..100).each_cons(2) => "#<Enumerator: 1..100:each_cons(2)>" */
@@ -1129,48 +1184,48 @@ append_method(VALUE obj, VALUE str, ID default_method, VALUE default_args)
method = rb_attr_get(obj, id_method);
if (method != Qfalse) {
- if (!NIL_P(method)) {
- Check_Type(method, T_SYMBOL);
- method = rb_sym2str(method);
- }
- else {
- method = rb_id2str(default_method);
- }
- rb_str_buf_cat2(str, ":");
- rb_str_buf_append(str, method);
+ if (!NIL_P(method)) {
+ Check_Type(method, T_SYMBOL);
+ method = rb_sym2str(method);
+ }
+ else {
+ method = rb_id2str(default_method);
+ }
+ rb_str_buf_cat2(str, ":");
+ rb_str_buf_append(str, method);
}
eargs = rb_attr_get(obj, id_arguments);
if (NIL_P(eargs)) {
- eargs = default_args;
+ eargs = default_args;
}
if (eargs != Qfalse) {
- long argc = RARRAY_LEN(eargs);
- const VALUE *argv = RARRAY_CONST_PTR(eargs); /* WB: no new reference */
+ long argc = RARRAY_LEN(eargs);
+ const VALUE *argv = RARRAY_CONST_PTR(eargs); /* WB: no new reference */
- if (argc > 0) {
- VALUE kwds = Qnil;
+ if (argc > 0) {
+ VALUE kwds = Qnil;
- rb_str_buf_cat2(str, "(");
+ rb_str_buf_cat2(str, "(");
if (RB_TYPE_P(argv[argc-1], T_HASH) && !RHASH_EMPTY_P(argv[argc-1])) {
- int all_key = TRUE;
- rb_hash_foreach(argv[argc-1], key_symbol_p, (VALUE)&all_key);
- if (all_key) kwds = argv[--argc];
- }
+ int all_key = TRUE;
+ rb_hash_foreach(argv[argc-1], key_symbol_p, (VALUE)&all_key);
+ if (all_key) kwds = argv[--argc];
+ }
- while (argc--) {
- VALUE arg = *argv++;
+ while (argc--) {
+ VALUE arg = *argv++;
- rb_str_append(str, rb_inspect(arg));
- rb_str_buf_cat2(str, ", ");
- }
- if (!NIL_P(kwds)) {
- rb_hash_foreach(kwds, kwd_append, str);
- }
- rb_str_set_len(str, RSTRING_LEN(str)-2);
- rb_str_buf_cat2(str, ")");
- }
+ rb_str_append(str, rb_inspect(arg));
+ rb_str_buf_cat2(str, ", ");
+ }
+ if (!NIL_P(kwds)) {
+ rb_hash_foreach(kwds, kwd_append, str);
+ }
+ rb_str_set_len(str, RSTRING_LEN(str)-2);
+ rb_str_buf_cat2(str, ")");
+ }
}
return str;
@@ -1209,31 +1264,31 @@ enumerator_size(VALUE obj)
VALUE size;
if (e->procs) {
- struct generator *g = generator_ptr(e->obj);
- VALUE receiver = rb_check_funcall(g->obj, id_size, 0, 0);
- long i = 0;
-
- for (i = 0; i < RARRAY_LEN(e->procs); i++) {
- VALUE proc = RARRAY_AREF(e->procs, i);
- struct proc_entry *entry = proc_entry_ptr(proc);
- lazyenum_size_func *size_fn = entry->fn->size;
- if (!size_fn) {
- return Qnil;
- }
- receiver = (*size_fn)(proc, receiver);
- }
- return receiver;
+ struct generator *g = generator_ptr(e->obj);
+ VALUE receiver = rb_check_funcall(g->obj, id_size, 0, 0);
+ long i = 0;
+
+ for (i = 0; i < RARRAY_LEN(e->procs); i++) {
+ VALUE proc = RARRAY_AREF(e->procs, i);
+ struct proc_entry *entry = proc_entry_ptr(proc);
+ lazyenum_size_func *size_fn = entry->fn->size;
+ if (!size_fn) {
+ return Qnil;
+ }
+ receiver = (*size_fn)(proc, receiver);
+ }
+ return receiver;
}
if (e->size_fn) {
- return (*e->size_fn)(e->obj, e->args, obj);
+ return (*e->size_fn)(e->obj, e->args, obj);
}
if (e->args) {
- argc = (int)RARRAY_LEN(e->args);
- argv = RARRAY_CONST_PTR(e->args);
+ argc = (int)RARRAY_LEN(e->args);
+ argv = RARRAY_CONST_PTR(e->args);
}
size = rb_check_funcall_kw(e->size, id_call, argc, argv, e->kw_splat);
- if (size != Qundef) return size;
+ if (!UNDEF_P(size)) return size;
return e->size;
}
@@ -1265,9 +1320,9 @@ yielder_memsize(const void *p)
static const rb_data_type_t yielder_data_type = {
"yielder",
{
- yielder_mark,
- yielder_free,
- yielder_memsize,
+ yielder_mark,
+ yielder_free,
+ yielder_memsize,
yielder_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
@@ -1279,8 +1334,8 @@ yielder_ptr(VALUE obj)
struct yielder *ptr;
TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
- if (!ptr || ptr->proc == Qundef) {
- rb_raise(rb_eArgError, "uninitialized yielder");
+ if (!ptr || UNDEF_P(ptr->proc)) {
+ rb_raise(rb_eArgError, "uninitialized yielder");
}
return ptr;
}
@@ -1306,7 +1361,7 @@ yielder_init(VALUE obj, VALUE proc)
TypedData_Get_Struct(obj, struct yielder, &yielder_data_type, ptr);
if (!ptr) {
- rb_raise(rb_eArgError, "unallocated yielder");
+ rb_raise(rb_eArgError, "unallocated yielder");
}
ptr->proc = proc;
@@ -1405,9 +1460,9 @@ generator_memsize(const void *p)
static const rb_data_type_t generator_data_type = {
"generator",
{
- generator_mark,
- generator_free,
- generator_memsize,
+ generator_mark,
+ generator_free,
+ generator_memsize,
generator_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
@@ -1419,8 +1474,8 @@ generator_ptr(VALUE obj)
struct generator *ptr;
TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
- if (!ptr || ptr->proc == Qundef) {
- rb_raise(rb_eArgError, "uninitialized generator");
+ if (!ptr || UNDEF_P(ptr->proc)) {
+ rb_raise(rb_eArgError, "uninitialized generator");
}
return ptr;
}
@@ -1447,7 +1502,7 @@ generator_init(VALUE obj, VALUE proc)
TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr);
if (!ptr) {
- rb_raise(rb_eArgError, "unallocated generator");
+ rb_raise(rb_eArgError, "unallocated generator");
}
ptr->proc = proc;
@@ -1462,21 +1517,21 @@ generator_initialize(int argc, VALUE *argv, VALUE obj)
VALUE proc;
if (argc == 0) {
- rb_need_block();
+ rb_need_block();
- proc = rb_block_proc();
+ proc = rb_block_proc();
}
else {
- rb_scan_args(argc, argv, "1", &proc);
+ rb_scan_args(argc, argv, "1", &proc);
- if (!rb_obj_is_proc(proc))
- rb_raise(rb_eTypeError,
- "wrong argument type %"PRIsVALUE" (expected Proc)",
- rb_obj_class(proc));
+ if (!rb_obj_is_proc(proc))
+ rb_raise(rb_eTypeError,
+ "wrong argument type %"PRIsVALUE" (expected Proc)",
+ rb_obj_class(proc));
- if (rb_block_given_p()) {
- rb_warn("given block not used");
- }
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
}
return generator_init(obj, proc);
@@ -1495,7 +1550,7 @@ generator_init_copy(VALUE obj, VALUE orig)
TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1);
if (!ptr1) {
- rb_raise(rb_eArgError, "unallocated generator");
+ rb_raise(rb_eArgError, "unallocated generator");
}
ptr1->proc = ptr0->proc;
@@ -1512,7 +1567,7 @@ generator_each(int argc, VALUE *argv, VALUE obj)
rb_ary_push(args, yielder_new());
if (argc > 0) {
- rb_ary_cat(args, argv, argc);
+ rb_ary_cat(args, argv, argc);
}
return rb_proc_call_kw(ptr->proc, args, RB_PASS_CALLED_KEYWORDS);
@@ -1523,7 +1578,7 @@ static VALUE
enum_size(VALUE self)
{
VALUE r = rb_check_funcall(self, id_size, 0, 0);
- return (r == Qundef) ? Qnil : r;
+ return UNDEF_P(r) ? Qnil : r;
}
static VALUE
@@ -1539,24 +1594,24 @@ lazy_init_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
{
VALUE result;
if (argc == 1) {
- VALUE args[2];
- args[0] = m;
- args[1] = val;
- result = rb_yield_values2(2, args);
+ VALUE args[2];
+ args[0] = m;
+ args[1] = val;
+ result = rb_yield_values2(2, args);
}
else {
- VALUE args;
- int len = rb_long2int((long)argc + 1);
- VALUE *nargv = ALLOCV_N(VALUE, args, len);
-
- nargv[0] = m;
- if (argc > 0) {
- MEMCPY(nargv + 1, argv, VALUE, argc);
- }
- result = rb_yield_values2(len, nargv);
- ALLOCV_END(args);
- }
- if (result == Qundef) rb_iter_break();
+ VALUE args;
+ int len = rb_long2int((long)argc + 1);
+ VALUE *nargv = ALLOCV_N(VALUE, args, len);
+
+ nargv[0] = m;
+ if (argc > 0) {
+ MEMCPY(nargv + 1, argv, VALUE, argc);
+ }
+ result = rb_yield_values2(len, nargv);
+ ALLOCV_END(args);
+ }
+ if (UNDEF_P(result)) rb_iter_break();
return Qnil;
}
@@ -1590,7 +1645,7 @@ lazy_init_yielder(RB_BLOCK_CALL_FUNC_ARGLIST(_, m))
struct MEMO *result;
result = MEMO_NEW(m, rb_enum_values_pack(argc, argv),
- argc > 1 ? LAZY_MEMO_PACKED : 0);
+ argc > 1 ? LAZY_MEMO_PACKED : 0);
return lazy_yielder_result(result, yielder, procs_array, memos, 0);
}
@@ -1615,19 +1670,19 @@ lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE
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)) {
- cont = 0;
- break;
- }
+ VALUE proc = RARRAY_AREF(procs_array, i);
+ struct proc_entry *entry = proc_entry_ptr(proc);
+ if (!(*entry->fn->proc)(proc, result, memos, i)) {
+ cont = 0;
+ break;
+ }
}
if (cont) {
- rb_funcall2(yielder, idLTLT, 1, &(result->memo_value));
+ rb_funcall2(yielder, idLTLT, 1, &(result->memo_value));
}
if (LAZY_MEMO_BREAK_P(result)) {
- rb_iter_break();
+ rb_iter_break();
}
return result->memo_value;
}
@@ -1639,7 +1694,7 @@ lazy_init_block(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
rb_ivar_set(val, id_memo, rb_ary_new2(RARRAY_LEN(procs)));
rb_block_call(RARRAY_AREF(m, 0), id_each, 0, 0,
- lazy_init_yielder, rb_ary_new3(2, val, procs));
+ lazy_init_yielder, rb_ary_new3(2, val, procs));
return Qnil;
}
@@ -1652,17 +1707,17 @@ lazy_generator_init(VALUE enumerator, VALUE procs)
struct enumerator *e = enumerator_ptr(enumerator);
if (RARRAY_LEN(procs) > 0) {
- struct generator *old_gen_ptr = generator_ptr(e->obj);
- obj = old_gen_ptr->obj;
+ struct generator *old_gen_ptr = generator_ptr(e->obj);
+ obj = old_gen_ptr->obj;
}
else {
- obj = enumerator;
+ obj = enumerator;
}
generator = generator_allocate(rb_cGenerator);
rb_block_call(generator, id_initialize, 0, 0,
- lazy_init_block, rb_ary_new3(2, obj, procs));
+ lazy_init_block, rb_ary_new3(2, obj, procs));
gen_ptr = generator_ptr(generator);
gen_ptr->obj = obj;
@@ -1670,6 +1725,22 @@ lazy_generator_init(VALUE enumerator, VALUE procs)
return generator;
}
+static int
+lazy_precheck(VALUE procs)
+{
+ if (RTEST(procs)) {
+ long num_procs = RARRAY_LEN(procs), i = num_procs;
+ while (i-- > 0) {
+ VALUE proc = RARRAY_AREF(procs, i);
+ struct proc_entry *entry = proc_entry_ptr(proc);
+ lazyenum_precheck_func *precheck = entry->fn->precheck;
+ if (precheck && !precheck(proc)) return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
/*
* Document-class: Enumerator::Lazy
*
@@ -1767,11 +1838,11 @@ lazy_initialize(int argc, VALUE *argv, VALUE self)
rb_check_arity(argc, 1, 2);
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy new without a block");
+ rb_raise(rb_eArgError, "tried to call lazy new without a block");
}
obj = argv[0];
if (argc > 1) {
- size = argv[1];
+ size = argv[1];
}
generator = generator_allocate(rb_cGenerator);
rb_block_call(generator, id_initialize, 0, 0, lazy_init_block_i, obj);
@@ -1790,7 +1861,8 @@ lazy_initialize(int argc, VALUE *argv, VALUE self)
* Expands +lazy+ enumerator to an array.
* See Enumerable#to_a.
*/
-static VALUE lazy_to_a(VALUE self)
+static VALUE
+lazy_to_a(VALUE self)
{
}
#endif
@@ -1801,11 +1873,11 @@ lazy_set_args(VALUE lazy, VALUE args)
ID id = rb_frame_this_func();
rb_ivar_set(lazy, id_method, ID2SYM(id));
if (NIL_P(args)) {
- /* Qfalse indicates that the arguments are empty */
- rb_ivar_set(lazy, id_arguments, Qfalse);
+ /* Qfalse indicates that the arguments are empty */
+ rb_ivar_set(lazy, id_arguments, Qfalse);
}
else {
- rb_ivar_set(lazy, id_arguments, args);
+ rb_ivar_set(lazy, id_arguments, args);
}
}
@@ -1822,7 +1894,7 @@ lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn)
static VALUE
lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
- const lazyenum_funcs *fn)
+ const lazyenum_funcs *fn)
{
struct enumerator *new_e;
VALUE new_obj;
@@ -1831,9 +1903,9 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
struct enumerator *e = enumerator_ptr(obj);
struct proc_entry *entry;
VALUE entry_obj = TypedData_Make_Struct(rb_cObject, struct proc_entry,
- &proc_entry_data_type, entry);
+ &proc_entry_data_type, entry);
if (rb_block_given_p()) {
- entry->proc = rb_block_proc();
+ entry->proc = rb_block_proc();
}
entry->fn = fn;
entry->memo = args;
@@ -1850,11 +1922,11 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
new_e->procs = new_procs;
if (argc > 0) {
- new_e->meth = rb_to_id(*argv++);
- --argc;
+ new_e->meth = rb_to_id(*argv++);
+ --argc;
}
else {
- new_e->meth = id_each;
+ new_e->meth = id_each;
}
new_e->args = rb_ary_new4(argc, argv);
return new_obj;
@@ -1934,15 +2006,15 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self)
VALUE lazy, meth = sym_each, super_meth;
if (argc > 0) {
- --argc;
- meth = *argv++;
+ --argc;
+ meth = *argv++;
}
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, rb_keyword_given_p());
if (rb_block_given_p()) {
- enumerator_ptr(lazy)->size = rb_block_proc();
+ enumerator_ptr(lazy)->size = rb_block_proc();
}
return lazy;
}
@@ -1981,9 +2053,9 @@ lazyenum_yield_values(VALUE proc_entry, struct MEMO *result)
int argc = 1;
const VALUE *argv = &result->memo_value;
if (LAZY_MEMO_PACKED_P(result)) {
- const VALUE args = *argv;
- argc = RARRAY_LENINT(args);
- argv = RARRAY_CONST_PTR(args);
+ const VALUE args = *argv;
+ argc = RARRAY_LENINT(args);
+ argv = RARRAY_CONST_PTR(args);
}
return rb_proc_call_with_block(entry->proc, argc, argv, Qnil);
}
@@ -2024,7 +2096,7 @@ static VALUE
lazy_map(VALUE obj)
{
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy map without a block");
+ rb_raise(rb_eArgError, "tried to call lazy map without a block");
}
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs);
@@ -2109,7 +2181,7 @@ static VALUE
lazy_flat_map(VALUE obj)
{
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
+ rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
}
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs);
@@ -2139,7 +2211,7 @@ static VALUE
lazy_select(VALUE obj)
{
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy select without a block");
+ rb_raise(rb_eArgError, "tried to call lazy select without a block");
}
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs);
@@ -2202,7 +2274,7 @@ static VALUE
lazy_reject(VALUE obj)
{
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy reject without a block");
+ rb_raise(rb_eArgError, "tried to call lazy reject without a block");
}
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_reject_funcs);
@@ -2251,7 +2323,7 @@ static VALUE
lazy_grep(VALUE obj, VALUE pattern)
{
const lazyenum_funcs *const funcs = rb_block_given_p() ?
- &lazy_grep_iter_funcs : &lazy_grep_funcs;
+ &lazy_grep_iter_funcs : &lazy_grep_funcs;
return lazy_add_method(obj, 0, 0, pattern, rb_ary_new3(1, pattern), funcs);
}
@@ -2325,7 +2397,7 @@ lazy_zip_arrays_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long me
ary = rb_ary_new2(RARRAY_LEN(arrays) + 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_ary_push(ary, rb_ary_entry(RARRAY_AREF(arrays, i), count));
}
LAZY_MEMO_SET_VALUE(result, ary);
LAZY_MEMO_SET_PACKED(result);
@@ -2343,19 +2415,19 @@ lazy_zip_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_inde
long i;
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_ary_store(memos, memo_index, 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_ary_store(memos, memo_index, arg);
}
ary = rb_ary_new2(RARRAY_LEN(arg) + 1);
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);
+ v = rb_rescue2(call_next, RARRAY_AREF(arg, i), next_stopped, 0,
+ rb_eStopIteration, (VALUE)0);
+ rb_ary_push(ary, v);
}
LAZY_MEMO_SET_VALUE(result, ary);
LAZY_MEMO_SET_PACKED(result);
@@ -2383,24 +2455,24 @@ lazy_zip(int argc, VALUE *argv, VALUE obj)
const lazyenum_funcs *funcs = &lazy_zip_funcs[1];
if (rb_block_given_p()) {
- return rb_call_super(argc, argv);
+ return rb_call_super(argc, argv);
}
ary = rb_ary_new2(argc);
for (i = 0; i < argc; i++) {
- v = rb_check_array_type(argv[i]);
- if (NIL_P(v)) {
- for (; i < argc; i++) {
- if (!rb_respond_to(argv[i], id_each)) {
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
- rb_obj_class(argv[i]));
- }
- }
- ary = rb_ary_new4(argc, argv);
- funcs = &lazy_zip_funcs[0];
- break;
- }
- rb_ary_push(ary, v);
+ v = rb_check_array_type(argv[i]);
+ if (NIL_P(v)) {
+ for (; i < argc; i++) {
+ if (!rb_respond_to(argv[i], id_each)) {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
+ rb_obj_class(argv[i]));
+ }
+ }
+ ary = rb_ary_new4(argc, argv);
+ funcs = &lazy_zip_funcs[0];
+ break;
+ }
+ rb_ary_push(ary, v);
}
return lazy_add_method(obj, 0, 0, ary, ary, funcs);
@@ -2414,17 +2486,12 @@ lazy_take_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_ind
VALUE memo = rb_ary_entry(memos, memo_index);
if (NIL_P(memo)) {
- memo = entry->memo;
+ memo = entry->memo;
}
remain = NUM2LONG(memo);
- if (remain == 0) {
- LAZY_MEMO_SET_BREAK(result);
- }
- else {
- if (--remain == 0) LAZY_MEMO_SET_BREAK(result);
- rb_ary_store(memos, memo_index, LONG2NUM(remain));
- }
+ if (--remain == 0) LAZY_MEMO_SET_BREAK(result);
+ rb_ary_store(memos, memo_index, LONG2NUM(remain));
return result;
}
@@ -2433,12 +2500,19 @@ lazy_take_size(VALUE entry, VALUE receiver)
{
long len = NUM2LONG(RARRAY_AREF(rb_ivar_get(entry, id_arguments), 0));
if (NIL_P(receiver) || (FIXNUM_P(receiver) && FIX2LONG(receiver) < len))
- return receiver;
+ return receiver;
return LONG2NUM(len);
}
+static int
+lazy_take_precheck(VALUE proc_entry)
+{
+ struct proc_entry *entry = proc_entry_ptr(proc_entry);
+ return entry->memo != INT2FIX(0);
+}
+
static const lazyenum_funcs lazy_take_funcs = {
- lazy_take_proc, lazy_take_size,
+ lazy_take_proc, lazy_take_size, lazy_take_precheck,
};
/*
@@ -2452,20 +2526,14 @@ static VALUE
lazy_take(VALUE obj, VALUE n)
{
long len = NUM2LONG(n);
- int argc = 0;
- VALUE argv[2];
if (len < 0) {
- rb_raise(rb_eArgError, "attempt to take negative size");
+ rb_raise(rb_eArgError, "attempt to take negative size");
}
- if (len == 0) {
- argv[0] = sym_cycle;
- argv[1] = INT2NUM(0);
- argc = 2;
- }
+ n = LONG2NUM(len); /* no more conversion */
- return lazy_add_method(obj, argc, argv, n, rb_ary_new3(1, n), &lazy_take_funcs);
+ return lazy_add_method(obj, 0, 0, n, rb_ary_new3(1, n), &lazy_take_funcs);
}
static struct MEMO *
@@ -2473,8 +2541,8 @@ lazy_take_while_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long me
{
VALUE take = lazyenum_yield_values(proc_entry, result);
if (!RTEST(take)) {
- LAZY_MEMO_SET_BREAK(result);
- return 0;
+ LAZY_MEMO_SET_BREAK(result);
+ return 0;
}
return result;
}
@@ -2494,7 +2562,7 @@ static VALUE
lazy_take_while(VALUE obj)
{
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
+ rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
}
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_take_while_funcs);
@@ -2505,10 +2573,10 @@ lazy_drop_size(VALUE proc_entry, VALUE receiver)
{
long len = NUM2LONG(RARRAY_AREF(rb_ivar_get(proc_entry, id_arguments), 0));
if (NIL_P(receiver))
- return receiver;
+ return receiver;
if (FIXNUM_P(receiver)) {
- len = FIX2LONG(receiver) - len;
- return LONG2FIX(len < 0 ? 0 : len);
+ len = FIX2LONG(receiver) - len;
+ return LONG2FIX(len < 0 ? 0 : len);
}
return rb_funcall(receiver, '-', 1, LONG2NUM(len));
}
@@ -2521,13 +2589,13 @@ lazy_drop_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_ind
VALUE memo = rb_ary_entry(memos, memo_index);
if (NIL_P(memo)) {
- memo = entry->memo;
+ memo = entry->memo;
}
remain = NUM2LONG(memo);
if (remain > 0) {
- --remain;
- rb_ary_store(memos, memo_index, LONG2NUM(remain));
- return 0;
+ --remain;
+ rb_ary_store(memos, memo_index, LONG2NUM(remain));
+ return 0;
}
return result;
@@ -2553,7 +2621,7 @@ lazy_drop(VALUE obj, VALUE n)
argv[1] = n;
if (len < 0) {
- rb_raise(rb_eArgError, "attempt to drop negative size");
+ rb_raise(rb_eArgError, "attempt to drop negative size");
}
return lazy_add_method(obj, 2, argv, n, rb_ary_new3(1, n), &lazy_drop_funcs);
@@ -2566,13 +2634,13 @@ lazy_drop_while_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long me
VALUE memo = rb_ary_entry(memos, memo_index);
if (NIL_P(memo)) {
- memo = entry->memo;
+ memo = entry->memo;
}
if (!RTEST(memo)) {
- VALUE drop = lazyenum_yield_values(proc_entry, result);
- if (RTEST(drop)) return 0;
- rb_ary_store(memos, memo_index, Qtrue);
+ VALUE drop = lazyenum_yield_values(proc_entry, result);
+ if (RTEST(drop)) return 0;
+ rb_ary_store(memos, memo_index, Qtrue);
}
return result;
}
@@ -2592,7 +2660,7 @@ static VALUE
lazy_drop_while(VALUE obj)
{
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
+ rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
}
return lazy_add_method(obj, 0, 0, Qfalse, Qnil, &lazy_drop_while_funcs);
@@ -2747,7 +2815,8 @@ lazy_with_index(int argc, VALUE *argv, VALUE obj)
*
* Like Enumerable#chunk, but chains operation to be lazy-evaluated.
*/
-static VALUE lazy_chunk(VALUE self)
+static VALUE
+lazy_chunk(VALUE self)
{
}
@@ -2757,7 +2826,8 @@ static VALUE lazy_chunk(VALUE self)
*
* Like Enumerable#chunk_while, but chains operation to be lazy-evaluated.
*/
-static VALUE lazy_chunk_while(VALUE self)
+static VALUE
+lazy_chunk_while(VALUE self)
{
}
@@ -2768,7 +2838,8 @@ static VALUE lazy_chunk_while(VALUE self)
*
* Like Enumerable#slice_after, but chains operation to be lazy-evaluated.
*/
-static VALUE lazy_slice_after(VALUE self)
+static VALUE
+lazy_slice_after(VALUE self)
{
}
@@ -2779,7 +2850,8 @@ static VALUE lazy_slice_after(VALUE self)
*
* Like Enumerable#slice_before, but chains operation to be lazy-evaluated.
*/
-static VALUE lazy_slice_before(VALUE self)
+static VALUE
+lazy_slice_before(VALUE self)
{
}
@@ -2789,7 +2861,8 @@ static VALUE lazy_slice_before(VALUE self)
*
* Like Enumerable#slice_when, but chains operation to be lazy-evaluated.
*/
-static VALUE lazy_slice_when(VALUE self)
+static VALUE
+lazy_slice_when(VALUE self)
{
}
# endif
@@ -2911,7 +2984,7 @@ producer_ptr(VALUE obj)
struct producer *ptr;
TypedData_Get_Struct(obj, struct producer, &producer_data_type, ptr);
- if (!ptr || ptr->proc == Qundef) {
+ if (!ptr || UNDEF_P(ptr->proc)) {
rb_raise(rb_eArgError, "uninitialized producer");
}
return ptr;
@@ -2966,7 +3039,7 @@ producer_each_i(VALUE obj)
init = ptr->init;
proc = ptr->proc;
- if (init == Qundef) {
+ if (UNDEF_P(init)) {
curr = Qnil;
}
else {
@@ -3097,7 +3170,7 @@ enum_chain_ptr(VALUE obj)
struct enum_chain *ptr;
TypedData_Get_Struct(obj, struct enum_chain, &enum_chain_data_type, ptr);
- if (!ptr || ptr->enums == Qundef) {
+ if (!ptr || UNDEF_P(ptr->enums)) {
rb_raise(rb_eArgError, "uninitialized chain");
}
return ptr;
@@ -3187,7 +3260,7 @@ enum_chain_total_size(VALUE enums)
for (i = 0; i < RARRAY_LEN(enums); i++) {
VALUE size = enum_size(RARRAY_AREF(enums, i));
- if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) {
+ if (NIL_P(size) || (RB_FLOAT_TYPE_P(size) && isinf(NUM2DBL(size)))) {
return size;
}
if (!RB_INTEGER_TYPE_P(size)) {
@@ -3290,7 +3363,7 @@ inspect_enum_chain(VALUE obj, VALUE dummy, int recur)
TypedData_Get_Struct(obj, struct enum_chain, &enum_chain_data_type, ptr);
- if (!ptr || ptr->enums == Qundef) {
+ if (!ptr || UNDEF_P(ptr->enums)) {
return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(klass));
}
@@ -3348,6 +3421,356 @@ enumerator_plus(VALUE obj, VALUE eobj)
}
/*
+ * Document-class: Enumerator::Product
+ *
+ * Enumerator::Product generates a Cartesian product of any number of
+ * enumerable objects. Iterating over the product of enumerable
+ * objects is roughly equivalent to nested each_entry loops where the
+ * loop for the rightmost object is put innermost.
+ *
+ * innings = Enumerator::Product.new(1..9, ['top', 'bottom'])
+ *
+ * innings.each do |i, h|
+ * p [i, h]
+ * end
+ * # [1, "top"]
+ * # [1, "bottom"]
+ * # [2, "top"]
+ * # [2, "bottom"]
+ * # [3, "top"]
+ * # [3, "bottom"]
+ * # ...
+ * # [9, "top"]
+ * # [9, "bottom"]
+ *
+ * The method used against each enumerable object is `each_entry`
+ * instead of `each` so that the product of N enumerable objects
+ * yields an array of exactly N elements in each iteration.
+ *
+ * When no enumerator is given, it calls a given block once yielding
+ * an empty argument list.
+ *
+ * This type of objects can be created by Enumerator.product.
+ */
+
+static void
+enum_product_mark(void *p)
+{
+ struct enum_product *ptr = p;
+ rb_gc_mark_movable(ptr->enums);
+}
+
+static void
+enum_product_compact(void *p)
+{
+ struct enum_product *ptr = p;
+ ptr->enums = rb_gc_location(ptr->enums);
+}
+
+#define enum_product_free RUBY_TYPED_DEFAULT_FREE
+
+static size_t
+enum_product_memsize(const void *p)
+{
+ return sizeof(struct enum_product);
+}
+
+static const rb_data_type_t enum_product_data_type = {
+ "product",
+ {
+ enum_product_mark,
+ enum_product_free,
+ enum_product_memsize,
+ enum_product_compact,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static struct enum_product *
+enum_product_ptr(VALUE obj)
+{
+ struct enum_product *ptr;
+
+ TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);
+ if (!ptr || UNDEF_P(ptr->enums)) {
+ rb_raise(rb_eArgError, "uninitialized product");
+ }
+ return ptr;
+}
+
+/* :nodoc: */
+static VALUE
+enum_product_allocate(VALUE klass)
+{
+ struct enum_product *ptr;
+ VALUE obj;
+
+ obj = TypedData_Make_Struct(klass, struct enum_product, &enum_product_data_type, ptr);
+ ptr->enums = Qundef;
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * Enumerator::Product.new(*enums) -> enum
+ *
+ * Generates a new enumerator object that generates a Cartesian
+ * product of given enumerable objects.
+ *
+ * e = Enumerator::Product.new(1..3, [4, 5])
+ * e.to_a #=> [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
+ * e.size #=> 6
+ */
+static VALUE
+enum_product_initialize(int argc, VALUE *argv, VALUE obj)
+{
+ struct enum_product *ptr;
+ VALUE enums = Qnil, options = Qnil;
+
+ rb_scan_args(argc, argv, "*:", &enums, &options);
+
+ if (!NIL_P(options) && !RHASH_EMPTY_P(options)) {
+ rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options)));
+ }
+
+ rb_check_frozen(obj);
+ TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);
+
+ if (!ptr) rb_raise(rb_eArgError, "unallocated product");
+
+ ptr->enums = rb_obj_freeze(enums);
+
+ return obj;
+}
+
+/* :nodoc: */
+static VALUE
+enum_product_init_copy(VALUE obj, VALUE orig)
+{
+ struct enum_product *ptr0, *ptr1;
+
+ if (!OBJ_INIT_COPY(obj, orig)) return obj;
+ ptr0 = enum_product_ptr(orig);
+
+ TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr1);
+
+ if (!ptr1) rb_raise(rb_eArgError, "unallocated product");
+
+ ptr1->enums = ptr0->enums;
+
+ return obj;
+}
+
+static VALUE
+enum_product_total_size(VALUE enums)
+{
+ VALUE total = INT2FIX(1);
+ long i;
+
+ for (i = 0; i < RARRAY_LEN(enums); i++) {
+ VALUE size = enum_size(RARRAY_AREF(enums, i));
+
+ if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) {
+ return size;
+ }
+ if (!RB_INTEGER_TYPE_P(size)) {
+ return Qnil;
+ }
+
+ total = rb_funcall(total, '*', 1, size);
+ }
+
+ return total;
+}
+
+/*
+ * call-seq:
+ * obj.size -> int, Float::INFINITY or nil
+ *
+ * Returns the total size of the enumerator product calculated by
+ * multiplying the sizes of enumerables in the product. If any of the
+ * enumerables reports its size as nil or Float::INFINITY, that value
+ * is returned as the size.
+ */
+static VALUE
+enum_product_size(VALUE obj)
+{
+ return enum_product_total_size(enum_product_ptr(obj)->enums);
+}
+
+static VALUE
+enum_product_enum_size(VALUE obj, VALUE args, VALUE eobj)
+{
+ return enum_product_size(obj);
+}
+
+struct product_state {
+ VALUE obj;
+ VALUE block;
+ int argc;
+ VALUE *argv;
+ int index;
+};
+
+static VALUE product_each(VALUE, struct product_state *);
+
+static VALUE
+product_each_i(RB_BLOCK_CALL_FUNC_ARGLIST(value, state))
+{
+ struct product_state *pstate = (struct product_state *)state;
+ pstate->argv[pstate->index++] = value;
+
+ VALUE val = product_each(pstate->obj, pstate);
+ pstate->index--;
+ return val;
+}
+
+static VALUE
+product_each(VALUE obj, struct product_state *pstate)
+{
+ struct enum_product *ptr = enum_product_ptr(obj);
+ VALUE enums = ptr->enums;
+
+ if (pstate->index < pstate->argc) {
+ VALUE eobj = RARRAY_AREF(enums, pstate->index);
+
+ rb_block_call(eobj, id_each_entry, 0, NULL, product_each_i, (VALUE)pstate);
+ }
+ else {
+ rb_funcall(pstate->block, id_call, 1, rb_ary_new_from_values(pstate->argc, pstate->argv));
+ }
+
+ return obj;
+}
+
+static VALUE
+enum_product_run(VALUE obj, VALUE block)
+{
+ struct enum_product *ptr = enum_product_ptr(obj);
+ int argc = RARRAY_LENINT(ptr->enums);
+ struct product_state state = {
+ .obj = obj,
+ .block = block,
+ .index = 0,
+ .argc = argc,
+ .argv = ALLOCA_N(VALUE, argc),
+ };
+
+ return product_each(obj, &state);
+}
+
+/*
+ * call-seq:
+ * obj.each { |...| ... } -> obj
+ * obj.each -> enumerator
+ *
+ * Iterates over the elements of the first enumerable by calling the
+ * "each_entry" method on it with the given arguments, then proceeds
+ * to the following enumerables in sequence until all of the
+ * enumerables are exhausted.
+ *
+ * If no block is given, returns an enumerator. Otherwise, returns self.
+ */
+static VALUE
+enum_product_each(VALUE obj)
+{
+ RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_product_enum_size);
+
+ return enum_product_run(obj, rb_block_proc());
+}
+
+/*
+ * call-seq:
+ * obj.rewind -> obj
+ *
+ * Rewinds the product enumerator by calling the "rewind" method on
+ * each enumerable in reverse order. Each call is performed only if
+ * the enumerable responds to the method.
+ */
+static VALUE
+enum_product_rewind(VALUE obj)
+{
+ struct enum_product *ptr = enum_product_ptr(obj);
+ VALUE enums = ptr->enums;
+ long i;
+
+ for (i = 0; i < RARRAY_LEN(enums); i++) {
+ rb_check_funcall(RARRAY_AREF(enums, i), id_rewind, 0, 0);
+ }
+
+ return obj;
+}
+
+static VALUE
+inspect_enum_product(VALUE obj, VALUE dummy, int recur)
+{
+ VALUE klass = rb_obj_class(obj);
+ struct enum_product *ptr;
+
+ TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);
+
+ if (!ptr || UNDEF_P(ptr->enums)) {
+ return rb_sprintf("#<%"PRIsVALUE": uninitialized>", rb_class_path(klass));
+ }
+
+ if (recur) {
+ return rb_sprintf("#<%"PRIsVALUE": ...>", rb_class_path(klass));
+ }
+
+ return rb_sprintf("#<%"PRIsVALUE": %+"PRIsVALUE">", rb_class_path(klass), ptr->enums);
+}
+
+/*
+ * call-seq:
+ * obj.inspect -> string
+ *
+ * Returns a printable version of the product enumerator.
+ */
+static VALUE
+enum_product_inspect(VALUE obj)
+{
+ return rb_exec_recursive(inspect_enum_product, obj, 0);
+}
+
+/*
+ * call-seq:
+ * Enumerator.product(*enums) -> enumerator
+ * Enumerator.product(*enums) { |elts| ... } -> enumerator
+ *
+ * Generates a new enumerator object that generates a Cartesian
+ * product of given enumerable objects. This is equivalent to
+ * Enumerator::Product.new.
+ *
+ * e = Enumerator.product(1..3, [4, 5])
+ * e.to_a #=> [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
+ * e.size #=> 6
+ *
+ * When a block is given, calls the block with each N-element array
+ * generated and returns +nil+.
+ */
+static VALUE
+enumerator_s_product(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE enums = Qnil, options = Qnil, block = Qnil;
+
+ rb_scan_args(argc, argv, "*:&", &enums, &options, &block);
+
+ if (!NIL_P(options) && !RHASH_EMPTY_P(options)) {
+ rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options)));
+ }
+
+ VALUE obj = enum_product_initialize(argc, argv, enum_product_allocate(rb_cEnumProduct));
+
+ if (!NIL_P(block)) {
+ enum_product_run(obj, block);
+ return Qnil;
+ }
+
+ return obj;
+}
+
+/*
* Document-class: Enumerator::ArithmeticSequence
*
* Enumerator::ArithmeticSequence is a subclass of Enumerator,
@@ -3369,7 +3792,7 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
rb_ivar_set(aseq, id_begin, beg);
rb_ivar_set(aseq, id_end, end);
rb_ivar_set(aseq, id_step, step);
- rb_ivar_set(aseq, id_exclude_end, excl ? Qtrue : Qfalse);
+ rb_ivar_set(aseq, id_exclude_end, RBOOL(excl));
return aseq;
}
@@ -3446,9 +3869,9 @@ rb_arithmetic_sequence_extract(VALUE obj, rb_arithmetic_sequence_components_t *c
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);
+ RBIMPL_NONNULL_ARG(begp);
+ RBIMPL_NONNULL_ARG(lenp);
+ RBIMPL_NONNULL_ARG(stepp);
rb_arithmetic_sequence_components_t aseq;
if (!rb_arithmetic_sequence_extract(obj, &aseq)) {
@@ -3459,6 +3882,13 @@ rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *ste
*stepp = step;
if (step < 0) {
+ if (aseq.exclude_end && !NIL_P(aseq.end)) {
+ /* Handle exclusion before range reversal */
+ aseq.end = LONG2NUM(NUM2LONG(aseq.end) + 1);
+
+ /* Don't exclude the previous beginning */
+ aseq.exclude_end = 0;
+ }
VALUE tmp = aseq.begin;
aseq.begin = aseq.end;
aseq.end = tmp;
@@ -4214,6 +4644,22 @@ InitVM_Enumerator(void)
rb_undef_method(rb_cEnumChain, "peek");
rb_undef_method(rb_cEnumChain, "peek_values");
+ /* Product */
+ rb_cEnumProduct = rb_define_class_under(rb_cEnumerator, "Product", rb_cEnumerator);
+ rb_define_alloc_func(rb_cEnumProduct, enum_product_allocate);
+ rb_define_method(rb_cEnumProduct, "initialize", enum_product_initialize, -1);
+ rb_define_method(rb_cEnumProduct, "initialize_copy", enum_product_init_copy, 1);
+ rb_define_method(rb_cEnumProduct, "each", enum_product_each, 0);
+ rb_define_method(rb_cEnumProduct, "size", enum_product_size, 0);
+ rb_define_method(rb_cEnumProduct, "rewind", enum_product_rewind, 0);
+ rb_define_method(rb_cEnumProduct, "inspect", enum_product_inspect, 0);
+ rb_undef_method(rb_cEnumProduct, "feed");
+ rb_undef_method(rb_cEnumProduct, "next");
+ rb_undef_method(rb_cEnumProduct, "next_values");
+ rb_undef_method(rb_cEnumProduct, "peek");
+ rb_undef_method(rb_cEnumProduct, "peek_values");
+ rb_define_singleton_method(rb_cEnumerator, "product", enumerator_s_product, -1);
+
/* ArithmeticSequence */
rb_cArithSeq = rb_define_class_under(rb_cEnumerator, "ArithmeticSequence", rb_cEnumerator);
rb_undef_alloc_func(rb_cArithSeq);
@@ -4249,6 +4695,7 @@ Init_Enumerator(void)
id_method = rb_intern_const("method");
id_force = rb_intern_const("force");
id_to_enum = rb_intern_const("to_enum");
+ id_each_entry = rb_intern_const("each_entry");
id_begin = rb_intern_const("begin");
id_end = rb_intern_const("end");
id_step = rb_intern_const("step");
diff --git a/error.c b/error.c
index f231c7458c..726f57a4c0 100644
--- a/error.c
+++ b/error.c
@@ -34,6 +34,7 @@
#include "internal/io.h"
#include "internal/load.h"
#include "internal/object.h"
+#include "internal/string.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/variable.h"
@@ -45,7 +46,7 @@
#include "builtin.h"
/*!
- * \defgroup exception Exception handlings
+ * \addtogroup exception
* \{
*/
@@ -77,11 +78,12 @@ static ID id_category;
static ID id_deprecated;
static ID id_experimental;
static VALUE sym_category;
+static VALUE sym_highlight;
static struct {
st_table *id2enum, *enum2id;
} warning_categories;
-extern const char ruby_description[];
+extern const char *rb_dynamic_description;
static const char *
rb_strerrno(int err)
@@ -98,53 +100,48 @@ static int
err_position_0(char *buf, long len, const char *file, int line)
{
if (!file) {
- return 0;
+ return 0;
}
else if (line == 0) {
- return snprintf(buf, len, "%s: ", file);
+ return snprintf(buf, len, "%s: ", file);
}
else {
- return snprintf(buf, len, "%s:%d: ", file, line);
+ return snprintf(buf, len, "%s:%d: ", file, line);
}
}
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 0)
static VALUE
err_vcatf(VALUE str, const char *pre, const char *file, int line,
- const char *fmt, va_list args)
+ const char *fmt, va_list args)
{
if (file) {
- rb_str_cat2(str, file);
- if (line) rb_str_catf(str, ":%d", line);
- rb_str_cat2(str, ": ");
+ rb_str_cat2(str, file);
+ if (line) rb_str_catf(str, ":%d", line);
+ rb_str_cat2(str, ": ");
}
if (pre) rb_str_cat2(str, pre);
rb_str_vcatf(str, fmt, args);
return str;
}
+static VALUE syntax_error_with_path(VALUE, VALUE, VALUE*, rb_encoding*);
+
VALUE
rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
- rb_encoding *enc, const char *fmt, va_list args)
+ rb_encoding *enc, const char *fmt, va_list args)
{
const char *fn = NIL_P(file) ? NULL : RSTRING_PTR(file);
if (!exc) {
- VALUE mesg = rb_enc_str_new(0, 0, enc);
- err_vcatf(mesg, NULL, fn, line, fmt, args);
- rb_str_cat2(mesg, "\n");
- rb_write_error_str(mesg);
+ VALUE mesg = rb_enc_str_new(0, 0, enc);
+ err_vcatf(mesg, NULL, fn, line, fmt, args);
+ rb_str_cat2(mesg, "\n");
+ rb_write_error_str(mesg);
}
else {
- VALUE mesg;
- if (NIL_P(exc)) {
- mesg = rb_enc_str_new(0, 0, enc);
- exc = rb_class_new_instance(1, &mesg, rb_eSyntaxError);
- }
- else {
- mesg = rb_attr_get(exc, idMesg);
- if (RSTRING_LEN(mesg) > 0 && *(RSTRING_END(mesg)-1) != '\n')
- rb_str_cat_cstr(mesg, "\n");
- }
- err_vcatf(mesg, NULL, fn, line, fmt, args);
+ VALUE mesg;
+ exc = syntax_error_with_path(exc, file, &mesg, enc);
+ err_vcatf(mesg, NULL, fn, line, fmt, args);
}
return exc;
@@ -316,7 +313,8 @@ rb_warning_warn(VALUE mod, VALUE str)
static int
rb_warning_warn_arity(void)
{
- return rb_method_entry_arity(rb_method_entry(rb_singleton_class(rb_mWarning), id_warn));
+ 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
@@ -344,6 +342,7 @@ rb_write_warning_str(VALUE str)
rb_warning_warn(rb_mWarning, str);
}
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 0)
static VALUE
warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args)
{
@@ -353,49 +352,45 @@ warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_
return rb_str_cat2(str, "\n");
}
+#define with_warn_vsprintf(file, line, fmt) \
+ VALUE str; \
+ va_list args; \
+ va_start(args, fmt); \
+ str = warn_vsprintf(NULL, file, line, fmt, args); \
+ va_end(args);
+
void
rb_compile_warn(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_write_warning_str(str);
+ if (!NIL_P(ruby_verbose)) {
+ with_warn_vsprintf(file, line, fmt) {
+ rb_write_warning_str(str);
+ }
+ }
}
/* rb_compile_warning() reports only in verbose mode */
void
rb_compile_warning(const char *file, int line, const char *fmt, ...)
{
- VALUE str;
- va_list args;
-
- if (!RTEST(ruby_verbose)) return;
-
- va_start(args, fmt);
- str = warn_vsprintf(NULL, file, line, fmt, args);
- va_end(args);
- rb_write_warning_str(str);
+ if (RTEST(ruby_verbose)) {
+ with_warn_vsprintf(file, line, fmt) {
+ rb_write_warning_str(str);
+ }
+ }
}
void
rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...)
{
- VALUE str;
- va_list args;
-
- if (NIL_P(ruby_verbose)) return;
-
- va_start(args, fmt);
- str = warn_vsprintf(NULL, file, line, fmt, args);
- va_end(args);
- rb_warn_category(str, rb_warning_category_to_name(category));
+ if (!NIL_P(ruby_verbose)) {
+ with_warn_vsprintf(file, line, fmt) {
+ rb_warn_category(str, rb_warning_category_to_name(category));
+ }
+ }
}
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
static VALUE
warning_string(rb_encoding *enc, const char *fmt, va_list args)
{
@@ -405,8 +400,10 @@ warning_string(rb_encoding *enc, const char *fmt, va_list args)
}
#define with_warning_string(mesg, enc, fmt) \
+ with_warning_string_from(mesg, enc, fmt, fmt)
+#define with_warning_string_from(mesg, enc, fmt, last_arg) \
VALUE mesg; \
- va_list args; va_start(args, fmt); \
+ va_list args; va_start(args, last_arg); \
mesg = warning_string(enc, fmt, args); \
va_end(args);
@@ -414,16 +411,16 @@ void
rb_warn(const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- with_warning_string(mesg, 0, fmt) {
- rb_write_warning_str(mesg);
- }
+ with_warning_string(mesg, 0, fmt) {
+ rb_write_warning_str(mesg);
+ }
}
}
void
rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
{
- if (!NIL_P(ruby_verbose)) {
+ if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
@@ -434,9 +431,9 @@ void
rb_enc_warn(rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- with_warning_string(mesg, enc, fmt) {
- rb_write_warning_str(mesg);
- }
+ with_warning_string(mesg, enc, fmt) {
+ rb_write_warning_str(mesg);
+ }
}
}
@@ -445,9 +442,9 @@ void
rb_warning(const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- with_warning_string(mesg, 0, fmt) {
- rb_write_warning_str(mesg);
- }
+ with_warning_string(mesg, 0, fmt) {
+ rb_write_warning_str(mesg);
+ }
}
}
@@ -455,7 +452,7 @@ rb_warning(const char *fmt, ...)
void
rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
{
- if (RTEST(ruby_verbose)) {
+ if (RTEST(ruby_verbose) && rb_warning_category_enabled_p(category)) {
with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
@@ -475,9 +472,9 @@ void
rb_enc_warning(rb_encoding *enc, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- with_warning_string(mesg, enc, fmt) {
- rb_write_warning_str(mesg);
- }
+ with_warning_string(mesg, enc, fmt) {
+ rb_write_warning_str(mesg);
+ }
}
}
#endif
@@ -508,12 +505,9 @@ rb_warn_deprecated(const char *fmt, const char *suggest, ...)
{
if (!deprecation_warning_enabled()) return;
- va_list args;
- va_start(args, suggest);
- VALUE mesg = warning_string(0, fmt, args);
- va_end(args);
-
- warn_deprecated(mesg, NULL, suggest);
+ with_warning_string_from(mesg, 0, fmt, suggest) {
+ warn_deprecated(mesg, NULL, suggest);
+ }
}
void
@@ -521,19 +515,16 @@ rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *s
{
if (!deprecation_warning_enabled()) return;
- va_list args;
- va_start(args, suggest);
- VALUE mesg = warning_string(0, fmt, args);
- va_end(args);
-
- warn_deprecated(mesg, removal, suggest);
+ with_warning_string_from(mesg, 0, fmt, suggest) {
+ warn_deprecated(mesg, removal, suggest);
+ }
}
static inline int
end_with_asciichar(VALUE str, int c)
{
return RB_TYPE_P(str, T_STRING) &&
- rb_str_end_with_asciichar(str, c);
+ rb_str_end_with_asciichar(str, c);
}
/* :nodoc: */
@@ -541,7 +532,7 @@ static VALUE
warning_write(int argc, VALUE *argv, VALUE buf)
{
while (argc-- > 0) {
- rb_str_append(buf, *argv++);
+ rb_str_append(buf, *argv++);
}
return buf;
}
@@ -566,38 +557,38 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALU
if (!NIL_P(location)) {
location = rb_ary_entry(location, 0);
}
- }
- if (argc > 1 || !NIL_P(uplevel) || !end_with_asciichar(str, '\n')) {
- VALUE path;
- if (NIL_P(uplevel)) {
- str = rb_str_tmp_new(0);
- }
- else if (NIL_P(location) ||
- NIL_P(path = rb_funcall(location, rb_intern("path"), 0))) {
- str = rb_str_new_cstr("warning: ");
- }
- else {
- str = rb_sprintf("%s:%ld: warning: ",
- rb_string_value_ptr(&path),
- NUM2LONG(rb_funcall(location, rb_intern("lineno"), 0)));
- }
- RBASIC_SET_CLASS(str, rb_cWarningBuffer);
- rb_io_puts(argc, argv, str);
- RBASIC_SET_CLASS(str, rb_cString);
- }
+ }
+ if (argc > 1 || !NIL_P(uplevel) || !end_with_asciichar(str, '\n')) {
+ VALUE path;
+ if (NIL_P(uplevel)) {
+ str = rb_str_tmp_new(0);
+ }
+ else if (NIL_P(location) ||
+ NIL_P(path = rb_funcall(location, rb_intern("path"), 0))) {
+ str = rb_str_new_cstr("warning: ");
+ }
+ else {
+ str = rb_sprintf("%s:%ld: warning: ",
+ rb_string_value_ptr(&path),
+ NUM2LONG(rb_funcall(location, rb_intern("lineno"), 0)));
+ }
+ RBASIC_SET_CLASS(str, rb_cWarningBuffer);
+ rb_io_puts(argc, argv, str);
+ RBASIC_SET_CLASS(str, rb_cString);
+ }
if (!NIL_P(category)) {
category = rb_to_symbol_type(category);
rb_warning_category_from_name(category);
}
- if (exc == rb_mWarning) {
- rb_must_asciicompat(str);
- rb_write_error_str(str);
- }
- else {
+ if (exc == rb_mWarning) {
+ rb_must_asciicompat(str);
+ rb_write_error_str(str);
+ }
+ else {
rb_warn_category(str, category);
- }
+ }
}
return Qnil;
}
@@ -616,7 +607,7 @@ rb_bug_reporter_add(void (*func)(FILE *, void *), void *data)
{
struct bug_reporters *reporter;
if (bug_reporters_size >= MAX_BUG_REPORTERS) {
- return 0; /* failed to register */
+ return 0; /* failed to register */
}
reporter = &bug_reporters[bug_reporters_size++];
reporter->func = func;
@@ -635,7 +626,7 @@ bug_report_file(const char *file, int line)
int len = err_position_0(buf, sizeof(buf), file, line);
if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len ||
- (ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) {
+ (ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) {
return out;
}
@@ -652,40 +643,45 @@ bug_important_message(FILE *out, const char *const msg, size_t len)
if (!len) return;
if (isatty(fileno(out))) {
- static const char red[] = "\033[;31;1;7m";
- static const char green[] = "\033[;32;7m";
- static const char reset[] = "\033[m";
- const char *e = strchr(p, '\n');
- const int w = (int)(e - p);
- do {
- int i = (int)(e - p);
- fputs(*p == ' ' ? green : red, out);
- fwrite(p, 1, e - p, out);
- for (; i < w; ++i) fputc(' ', out);
- fputs(reset, out);
- fputc('\n', out);
- } while ((p = e + 1) < endmsg && (e = strchr(p, '\n')) != 0 && e > p + 1);
+ static const char red[] = "\033[;31;1;7m";
+ static const char green[] = "\033[;32;7m";
+ static const char reset[] = "\033[m";
+ const char *e = strchr(p, '\n');
+ const int w = (int)(e - p);
+ do {
+ int i = (int)(e - p);
+ fputs(*p == ' ' ? green : red, out);
+ fwrite(p, 1, e - p, out);
+ for (; i < w; ++i) fputc(' ', out);
+ fputs(reset, out);
+ fputc('\n', out);
+ } while ((p = e + 1) < endmsg && (e = strchr(p, '\n')) != 0 && e > p + 1);
}
fwrite(p, 1, endmsg - p, out);
}
+#undef CRASH_REPORTER_MAY_BE_CREATED
+#if defined(__APPLE__) && \
+ (!defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 || defined(__POWERPC__)) /* 10.6 PPC case */
+# define CRASH_REPORTER_MAY_BE_CREATED
+#endif
static void
preface_dump(FILE *out)
{
#if defined __APPLE__
static const char msg[] = ""
- "-- Crash Report log information "
- "--------------------------------------------\n"
- " See Crash Report log file in one of the following locations:\n"
-# if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- " * ~/Library/Logs/CrashReporter\n"
- " * /Library/Logs/CrashReporter\n"
+ "-- Crash Report log information "
+ "--------------------------------------------\n"
+ " See Crash Report log file in one of the following locations:\n"
+# ifdef CRASH_REPORTER_MAY_BE_CREATED
+ " * ~/Library/Logs/CrashReporter\n"
+ " * /Library/Logs/CrashReporter\n"
# endif
- " * ~/Library/Logs/DiagnosticReports\n"
- " * /Library/Logs/DiagnosticReports\n"
- " for more details.\n"
- "Don't forget to include the above Crash Report log file in bug reports.\n"
- "\n";
+ " * ~/Library/Logs/DiagnosticReports\n"
+ " * /Library/Logs/DiagnosticReports\n"
+ " for more details.\n"
+ "Don't forget to include the above Crash Report log file in bug reports.\n"
+ "\n";
const size_t msglen = sizeof(msg) - 1;
#else
const char *msg = NULL;
@@ -699,15 +695,15 @@ postscript_dump(FILE *out)
{
#if defined __APPLE__
static const char msg[] = ""
- "[IMPORTANT]"
- /*" ------------------------------------------------"*/
- "\n""Don't forget to include the Crash Report log file under\n"
-# if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- "CrashReporter or "
+ "[IMPORTANT]"
+ /*" ------------------------------------------------"*/
+ "\n""Don't forget to include the Crash Report log file under\n"
+# ifdef CRASH_REPORTER_MAY_BE_CREATED
+ "CrashReporter or "
# endif
- "DiagnosticReports directory in bug reports.\n"
- /*"------------------------------------------------------------\n"*/
- "\n";
+ "DiagnosticReports directory in bug reports.\n"
+ /*"------------------------------------------------------------\n"*/
+ "\n";
const size_t msglen = sizeof(msg) - 1;
#else
const char *msg = NULL;
@@ -716,6 +712,7 @@ postscript_dump(FILE *out)
bug_important_message(out, msg, msglen);
}
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
static void
bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
{
@@ -724,7 +721,7 @@ bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
fputs("[BUG] ", out);
vsnprintf(buf, sizeof(buf), fmt, args);
fputs(buf, out);
- snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description);
+ snprintf(buf, sizeof(buf), "\n%s\n\n", rb_dynamic_description);
fputs(buf, out);
preface_dump(out);
}
@@ -741,11 +738,11 @@ bug_report_end(FILE *out)
{
/* call additional bug reporters */
{
- int i;
- for (i=0; i<bug_reporters_size; i++) {
- struct bug_reporters *reporter = &bug_reporters[i];
- (*reporter->func)(out, reporter->data);
- }
+ int i;
+ for (i=0; i<bug_reporters_size; i++) {
+ struct bug_reporters *reporter = &bug_reporters[i];
+ (*reporter->func)(out, reporter->data);
+ }
}
postscript_dump(out);
}
@@ -753,18 +750,18 @@ bug_report_end(FILE *out)
#define report_bug(file, line, fmt, ctx) do { \
FILE *out = bug_report_file(file, line); \
if (out) { \
- bug_report_begin(out, fmt); \
- rb_vm_bugreport(ctx); \
- bug_report_end(out); \
+ bug_report_begin(out, fmt); \
+ rb_vm_bugreport(ctx); \
+ bug_report_end(out); \
} \
} while (0) \
#define report_bug_valist(file, line, fmt, ctx, args) do { \
FILE *out = bug_report_file(file, line); \
if (out) { \
- bug_report_begin_valist(out, fmt, args); \
- rb_vm_bugreport(ctx); \
- bug_report_end(out); \
+ bug_report_begin_valist(out, fmt, args); \
+ rb_vm_bugreport(ctx); \
+ bug_report_end(out); \
} \
} while (0) \
@@ -779,6 +776,7 @@ die(void)
abort();
}
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
void
rb_bug_without_die(const char *fmt, va_list args)
{
@@ -809,7 +807,7 @@ rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const voi
int line = 0;
if (GET_EC()) {
- file = rb_source_location_cstr(&line);
+ file = rb_source_location_cstr(&line);
}
report_bug(file, line, fmt, ctx);
@@ -849,17 +847,17 @@ rb_async_bug_errno(const char *mesg, int errno_arg)
WRITE_CONST(2, "\n");
if (errno_arg == 0) {
- WRITE_CONST(2, "errno == 0 (NOERROR)\n");
+ WRITE_CONST(2, "errno == 0 (NOERROR)\n");
}
else {
- const char *errno_str = rb_strerrno(errno_arg);
+ const char *errno_str = rb_strerrno(errno_arg);
- if (!errno_str)
- errno_str = "undefined errno";
- write_or_abort(2, errno_str, strlen(errno_str));
+ if (!errno_str)
+ errno_str = "undefined errno";
+ write_or_abort(2, errno_str, strlen(errno_str));
}
WRITE_CONST(2, "\n\n");
- write_or_abort(2, ruby_description, strlen(ruby_description));
+ write_or_abort(2, rb_dynamic_description, strlen(rb_dynamic_description));
abort();
}
@@ -875,7 +873,7 @@ rb_assert_failure(const char *file, int line, const char *name, const char *expr
FILE *out = stderr;
fprintf(out, "Assertion Failed: %s:%d:", file, line);
if (name) fprintf(out, "%s:", name);
- fprintf(out, "%s\n%s\n\n", expr, ruby_description);
+ fprintf(out, "%s\n%s\n\n", expr, rb_dynamic_description);
preface_dump(out);
rb_vm_bugreport(NULL);
bug_report_end(out);
@@ -941,22 +939,22 @@ builtin_class_name(VALUE x)
const char *etype;
if (NIL_P(x)) {
- etype = "nil";
+ etype = "nil";
}
else if (FIXNUM_P(x)) {
- etype = "Integer";
+ etype = "Integer";
}
else if (SYMBOL_P(x)) {
- etype = "Symbol";
+ etype = "Symbol";
}
else if (RB_TYPE_P(x, T_TRUE)) {
- etype = "true";
+ etype = "true";
}
else if (RB_TYPE_P(x, T_FALSE)) {
- etype = "false";
+ etype = "false";
}
else {
- etype = NULL;
+ etype = NULL;
}
return etype;
}
@@ -967,7 +965,7 @@ rb_builtin_class_name(VALUE x)
const char *etype = builtin_class_name(x);
if (!etype) {
- etype = rb_obj_classname(x);
+ etype = rb_obj_classname(x);
}
return etype;
}
@@ -984,14 +982,14 @@ unexpected_type(VALUE x, int xt, int t)
if (tname) {
mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
displaying_class_of(x), tname);
- exc = rb_eTypeError;
+ exc = rb_eTypeError;
}
else if (xt > T_MASK && xt <= 0x3f) {
- mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
- " from extension library for ruby 1.8)", t, xt);
+ mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
+ " from extension library for ruby 1.8)", t, xt);
}
else {
- mesg = rb_sprintf("unknown type 0x%x (0x%x given)", t, xt);
+ mesg = rb_sprintf("unknown type 0x%x (0x%x given)", t, xt);
}
rb_exc_raise(rb_exc_new_str(exc, mesg));
}
@@ -1001,8 +999,8 @@ rb_check_type(VALUE x, int t)
{
int xt;
- if (RB_UNLIKELY(x == Qundef)) {
- rb_bug(UNDEF_LEAKED);
+ if (RB_UNLIKELY(UNDEF_P(x))) {
+ rb_bug(UNDEF_LEAKED);
}
xt = TYPE(x);
@@ -1015,15 +1013,15 @@ rb_check_type(VALUE x, int t)
* So it is not enough to just check `T_DATA`, it must be
* identified by its `type` using `Check_TypedStruct` instead.
*/
- unexpected_type(x, xt, t);
+ unexpected_type(x, xt, t);
}
}
void
rb_unexpected_type(VALUE x, int t)
{
- if (RB_UNLIKELY(x == Qundef)) {
- rb_bug(UNDEF_LEAKED);
+ if (RB_UNLIKELY(UNDEF_P(x))) {
+ rb_bug(UNDEF_LEAKED);
}
unexpected_type(x, TYPE(x), t);
@@ -1033,8 +1031,8 @@ int
rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
{
while (child) {
- if (child == parent) return 1;
- child = child->parent;
+ if (child == parent) return 1;
+ child = child->parent;
}
return 0;
}
@@ -1043,8 +1041,8 @@ int
rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
{
if (!RB_TYPE_P(obj, T_DATA) ||
- !RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
- return 0;
+ !RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
+ return 0;
}
return 1;
}
@@ -1104,6 +1102,7 @@ VALUE rb_eNotImpError;
VALUE rb_eNoMemError;
VALUE rb_cNameErrorMesg;
VALUE rb_eNoMatchingPatternError;
+VALUE rb_eNoMatchingPatternKeyError;
VALUE rb_eScriptError;
VALUE rb_eSyntaxError;
@@ -1115,8 +1114,8 @@ static VALUE rb_eNOERROR;
ID ruby_static_id_cause;
#define id_cause ruby_static_id_cause
-static ID id_message, id_backtrace;
-static ID id_key, id_args, id_Errno, id_errno, id_i_path;
+static ID id_message, id_detailed_message, id_backtrace;
+static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path;
static ID id_receiver, id_recv, id_iseq, id_local_variables;
static ID id_private_call_p, id_top, id_bottom;
#define id_bt idBt
@@ -1217,13 +1216,28 @@ exc_to_s(VALUE exc)
}
/* FIXME: Include eval_error.c */
-void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse);
+void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VALUE highlight, VALUE reverse);
VALUE
rb_get_message(VALUE exc)
{
VALUE e = rb_check_funcall(exc, id_message, 0, 0);
- if (e == Qundef) return Qnil;
+ if (UNDEF_P(e)) return Qnil;
+ if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
+ return e;
+}
+
+VALUE
+rb_get_detailed_message(VALUE exc, VALUE opt)
+{
+ VALUE e;
+ if (NIL_P(opt)) {
+ e = rb_check_funcall(exc, id_detailed_message, 0, 0);
+ }
+ else {
+ e = rb_check_funcall_kw(exc, id_detailed_message, 1, &opt, 1);
+ }
+ if (UNDEF_P(e)) return Qnil;
if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
return e;
}
@@ -1240,6 +1254,56 @@ exc_s_to_tty_p(VALUE self)
return RBOOL(rb_stderr_tty_p());
}
+static VALUE
+check_highlight_keyword(VALUE opt, int auto_tty_detect)
+{
+ VALUE highlight = Qnil;
+
+ if (!NIL_P(opt)) {
+ highlight = rb_hash_lookup(opt, sym_highlight);
+
+ switch (highlight) {
+ default:
+ rb_bool_expected(highlight, "highlight", TRUE);
+ UNREACHABLE;
+ case Qtrue: case Qfalse: case Qnil: break;
+ }
+ }
+
+ if (NIL_P(highlight)) {
+ highlight = RBOOL(auto_tty_detect && rb_stderr_tty_p());
+ }
+
+ return highlight;
+}
+
+static VALUE
+check_order_keyword(VALUE opt)
+{
+ VALUE order = Qnil;
+
+ if (!NIL_P(opt)) {
+ static VALUE kw_order;
+ if (!kw_order) kw_order = ID2SYM(rb_intern_const("order"));
+
+ order = rb_hash_lookup(opt, kw_order);
+
+ if (order != Qnil) {
+ ID id = rb_check_id(&order);
+ if (id == id_bottom) order = Qtrue;
+ else if (id == id_top) order = Qfalse;
+ else {
+ rb_raise(rb_eArgError, "expected :top or :bottom as "
+ "order: %+"PRIsVALUE, order);
+ }
+ }
+ }
+
+ if (NIL_P(order)) order = Qfalse;
+
+ return order;
+}
+
/*
* call-seq:
* exception.full_message(highlight: bool, order: [:top or :bottom]) -> string
@@ -1262,44 +1326,23 @@ static VALUE
exc_full_message(int argc, VALUE *argv, VALUE exc)
{
VALUE opt, str, emesg, errat;
- enum {kw_highlight, kw_order, kw_max_};
- static ID kw[kw_max_];
- VALUE args[kw_max_] = {Qnil, Qnil};
+ VALUE highlight, order;
rb_scan_args(argc, argv, "0:", &opt);
- if (!NIL_P(opt)) {
- if (!kw[0]) {
-#define INIT_KW(n) kw[kw_##n] = rb_intern_const(#n)
- INIT_KW(highlight);
- INIT_KW(order);
-#undef INIT_KW
- }
- rb_get_kwargs(opt, kw, 0, kw_max_, args);
- switch (args[kw_highlight]) {
- default:
- rb_bool_expected(args[kw_highlight], "highlight");
- UNREACHABLE;
- case Qundef: args[kw_highlight] = Qnil; break;
- case Qtrue: case Qfalse: case Qnil: break;
- }
- if (args[kw_order] == Qundef) {
- args[kw_order] = Qnil;
- }
- else {
- ID id = rb_check_id(&args[kw_order]);
- if (id == id_bottom) args[kw_order] = Qtrue;
- else if (id == id_top) args[kw_order] = Qfalse;
- else {
- rb_raise(rb_eArgError, "expected :top or :bottom as "
- "order: %+"PRIsVALUE, args[kw_order]);
- }
- }
+
+ highlight = check_highlight_keyword(opt, 1);
+ order = check_order_keyword(opt);
+
+ {
+ if (NIL_P(opt)) opt = rb_hash_new();
+ rb_hash_aset(opt, sym_highlight, highlight);
}
+
str = rb_str_new2("");
errat = rb_get_backtrace(exc);
- emesg = rb_get_message(exc);
+ emesg = rb_get_detailed_message(exc, opt);
- rb_error_write(exc, emesg, errat, str, args[kw_highlight], args[kw_order]);
+ rb_error_write(exc, emesg, errat, str, opt, highlight, order);
return str;
}
@@ -1319,6 +1362,60 @@ exc_message(VALUE exc)
/*
* call-seq:
+ * exception.detailed_message(highlight: bool, **opt) -> string
+ *
+ * Processes a string returned by #message.
+ *
+ * It may add the class name of the exception to the end of the first line.
+ * Also, when +highlight+ keyword is true, it adds ANSI escape sequences to
+ * make the message bold.
+ *
+ * If you override this method, it must be tolerant for unknown keyword
+ * arguments. All keyword arguments passed to #full_message are delegated
+ * to this method.
+ *
+ * This method is overridden by did_you_mean and error_highlight to add
+ * their information.
+ *
+ * A user-defined exception class can also define their own
+ * +detailed_message+ method to add supplemental information.
+ * When +highlight+ is true, it can return a string containing escape
+ * sequences, but use widely-supported ones. It is recommended to limit
+ * the following codes:
+ *
+ * - Reset (+\e[0m+)
+ * - Bold (+\e[1m+)
+ * - Underline (+\e[4m+)
+ * - Foreground color except white and black
+ * - Red (+\e[31m+)
+ * - Green (+\e[32m+)
+ * - Yellow (+\e[33m+)
+ * - Blue (+\e[34m+)
+ * - Magenta (+\e[35m+)
+ * - Cyan (+\e[36m+)
+ *
+ * Use escape sequences carefully even if +highlight+ is true.
+ * Do not use escape sequences to express essential information;
+ * the message should be readable even if all escape sequences are
+ * ignored.
+ */
+
+static VALUE
+exc_detailed_message(int argc, VALUE *argv, VALUE exc)
+{
+ VALUE opt;
+
+ rb_scan_args(argc, argv, "0:", &opt);
+
+ VALUE highlight = check_highlight_keyword(opt, 0);
+
+ extern VALUE rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight);
+
+ return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight));
+}
+
+/*
+ * call-seq:
* exception.inspect -> string
*
* Return this exception's class name and message.
@@ -1338,8 +1435,15 @@ exc_inspect(VALUE exc)
str = rb_str_buf_new2("#<");
klass = rb_class_name(klass);
rb_str_buf_append(str, klass);
- rb_str_buf_cat(str, ": ", 2);
- rb_str_buf_append(str, exc);
+
+ if (RTEST(rb_str_include(exc, rb_str_new2("\n")))) {
+ rb_str_catf(str, ":%+"PRIsVALUE, exc);
+ }
+ else {
+ rb_str_buf_cat(str, ": ", 2);
+ rb_str_buf_append(str, exc);
+ }
+
rb_str_buf_cat(str, ">", 1);
return str;
@@ -1388,8 +1492,8 @@ exc_backtrace(VALUE exc)
obj = rb_attr_get(exc, id_bt);
if (rb_backtrace_p(obj)) {
- obj = rb_backtrace_to_str_ary(obj);
- /* rb_ivar_set(exc, id_bt, obj); */
+ obj = rb_backtrace_to_str_ary(obj);
+ /* rb_ivar_set(exc, id_bt, obj); */
}
return obj;
@@ -1403,16 +1507,16 @@ rb_get_backtrace(VALUE exc)
ID mid = id_backtrace;
VALUE info;
if (rb_method_basic_definition_p(CLASS_OF(exc), id_backtrace)) {
- VALUE klass = rb_eException;
- rb_execution_context_t *ec = GET_EC();
- if (NIL_P(exc))
- return Qnil;
- EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
- info = exc_backtrace(exc);
- EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
+ VALUE klass = rb_eException;
+ rb_execution_context_t *ec = GET_EC();
+ if (NIL_P(exc))
+ return Qnil;
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, exc, mid, mid, klass, Qundef);
+ info = exc_backtrace(exc);
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, exc, mid, mid, klass, info);
}
else {
- info = rb_funcallv(exc, mid, 0, 0);
+ info = rb_funcallv(exc, mid, 0, 0);
}
if (NIL_P(info)) return Qnil;
return rb_check_backtrace(info);
@@ -1435,7 +1539,7 @@ exc_backtrace_locations(VALUE exc)
obj = rb_attr_get(exc, id_bt_locations);
if (!NIL_P(obj)) {
- obj = rb_backtrace_to_location_ary(obj);
+ obj = rb_backtrace_to_location_ary(obj);
}
return obj;
}
@@ -1447,17 +1551,17 @@ rb_check_backtrace(VALUE bt)
static const char err[] = "backtrace must be Array of String";
if (!NIL_P(bt)) {
- if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
- if (rb_backtrace_p(bt)) return bt;
- if (!RB_TYPE_P(bt, T_ARRAY)) {
- rb_raise(rb_eTypeError, err);
- }
- for (i=0;i<RARRAY_LEN(bt);i++) {
- VALUE e = RARRAY_AREF(bt, i);
- if (!RB_TYPE_P(e, T_STRING)) {
- rb_raise(rb_eTypeError, err);
- }
- }
+ if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt);
+ if (rb_backtrace_p(bt)) return bt;
+ if (!RB_TYPE_P(bt, T_ARRAY)) {
+ rb_raise(rb_eTypeError, err);
+ }
+ for (i=0;i<RARRAY_LEN(bt);i++) {
+ VALUE e = RARRAY_AREF(bt, i);
+ if (!RB_TYPE_P(e, T_STRING)) {
+ rb_raise(rb_eTypeError, err);
+ }
+ }
}
return bt;
}
@@ -1522,29 +1626,27 @@ exc_equal(VALUE exc, VALUE obj)
if (exc == obj) return Qtrue;
if (rb_obj_class(exc) != rb_obj_class(obj)) {
- int state;
-
- obj = rb_protect(try_convert_to_exception, obj, &state);
- if (state || obj == Qundef) {
- rb_set_errinfo(Qnil);
- return Qfalse;
- }
- if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
- mesg = rb_check_funcall(obj, id_message, 0, 0);
- if (mesg == Qundef) return Qfalse;
- backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
- if (backtrace == Qundef) return Qfalse;
+ int state;
+
+ obj = rb_protect(try_convert_to_exception, obj, &state);
+ if (state || UNDEF_P(obj)) {
+ rb_set_errinfo(Qnil);
+ return Qfalse;
+ }
+ if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
+ mesg = rb_check_funcall(obj, id_message, 0, 0);
+ if (UNDEF_P(mesg)) return Qfalse;
+ backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
+ if (UNDEF_P(backtrace)) return Qfalse;
}
else {
- mesg = rb_attr_get(obj, id_mesg);
- backtrace = exc_backtrace(obj);
+ mesg = rb_attr_get(obj, id_mesg);
+ backtrace = exc_backtrace(obj);
}
if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
- return Qfalse;
- if (!rb_equal(exc_backtrace(exc), backtrace))
- return Qfalse;
- return Qtrue;
+ return Qfalse;
+ return rb_equal(exc_backtrace(exc), backtrace);
}
/*
@@ -1564,37 +1666,37 @@ exit_initialize(int argc, VALUE *argv, VALUE exc)
{
VALUE status;
if (argc > 0) {
- status = *argv;
-
- switch (status) {
- case Qtrue:
- status = INT2FIX(EXIT_SUCCESS);
- ++argv;
- --argc;
- break;
- case Qfalse:
- status = INT2FIX(EXIT_FAILURE);
- ++argv;
- --argc;
- break;
- default:
- status = rb_check_to_int(status);
- if (NIL_P(status)) {
- status = INT2FIX(EXIT_SUCCESS);
- }
- else {
+ status = *argv;
+
+ switch (status) {
+ case Qtrue:
+ status = INT2FIX(EXIT_SUCCESS);
+ ++argv;
+ --argc;
+ break;
+ case Qfalse:
+ status = INT2FIX(EXIT_FAILURE);
+ ++argv;
+ --argc;
+ break;
+ default:
+ status = rb_check_to_int(status);
+ if (NIL_P(status)) {
+ status = INT2FIX(EXIT_SUCCESS);
+ }
+ else {
#if EXIT_SUCCESS != 0
- if (status == INT2FIX(0))
- status = INT2FIX(EXIT_SUCCESS);
+ if (status == INT2FIX(0))
+ status = INT2FIX(EXIT_SUCCESS);
#endif
- ++argv;
- --argc;
- }
- break;
- }
+ ++argv;
+ --argc;
+ }
+ break;
+ }
}
else {
- status = INT2FIX(EXIT_SUCCESS);
+ status = INT2FIX(EXIT_SUCCESS);
}
rb_call_super(argc, argv);
rb_ivar_set(exc, id_status, status);
@@ -1630,18 +1732,15 @@ exit_success_p(VALUE exc)
int status;
if (NIL_P(status_val))
- return Qtrue;
+ return Qtrue;
status = NUM2INT(status_val);
- if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
- return Qtrue;
-
- return Qfalse;
+ return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
}
static VALUE
err_init_recv(VALUE exc, VALUE recv)
{
- if (recv != Qundef) rb_ivar_set(exc, id_recv, recv);
+ if (!UNDEF_P(recv)) rb_ivar_set(exc, id_recv, recv);
return exc;
}
@@ -1719,7 +1818,9 @@ name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
rb_ivar_set(exc, id_name, method);
err_init_recv(exc, recv);
- if (cfp) rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
+ if (cfp && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
+ rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
+ }
return exc;
}
@@ -1796,10 +1897,10 @@ name_err_local_variables(VALUE self)
VALUE vars = rb_attr_get(self, id_local_variables);
if (NIL_P(vars)) {
- VALUE iseqw = rb_attr_get(self, id_iseq);
- if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
- if (NIL_P(vars)) vars = rb_ary_new();
- rb_ivar_set(self, id_local_variables, vars);
+ VALUE iseqw = rb_attr_get(self, id_iseq);
+ if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
+ if (NIL_P(vars)) vars = rb_ary_new();
+ rb_ivar_set(self, id_local_variables, vars);
}
return vars;
}
@@ -1875,9 +1976,9 @@ name_err_mesg_memsize(const void *p)
static const rb_data_type_t name_err_mesg_data_type = {
"name_err_mesg",
{
- name_err_mesg_mark,
- name_err_mesg_free,
- name_err_mesg_memsize,
+ name_err_mesg_mark,
+ name_err_mesg_free,
+ name_err_mesg_memsize,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -1934,13 +2035,13 @@ name_err_mesg_equal(VALUE obj1, VALUE obj2)
if (obj1 == obj2) return Qtrue;
if (rb_obj_class(obj2) != rb_cNameErrorMesg)
- return Qfalse;
+ return Qfalse;
TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
for (i=0; i<NAME_ERR_MESG_COUNT; i++) {
- if (!rb_equal(ptr1[i], ptr2[i]))
- return Qfalse;
+ if (!rb_equal(ptr1[i], ptr2[i]))
+ return Qfalse;
}
return Qtrue;
}
@@ -1966,49 +2067,49 @@ name_err_mesg_to_str(VALUE obj)
mesg = ptr[NAME_ERR_MESG__MESG];
if (NIL_P(mesg)) return Qnil;
else {
- struct RString s_str, d_str;
- VALUE c, s, d = 0, args[4];
- int state = 0, singleton = 0;
- rb_encoding *usascii = rb_usascii_encoding();
+ struct RString s_str, d_str;
+ VALUE c, s, d = 0, args[4];
+ int state = 0, singleton = 0;
+ rb_encoding *usascii = rb_usascii_encoding();
#define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii)
- obj = ptr[NAME_ERR_MESG__RECV];
- switch (obj) {
- case Qnil:
- d = FAKE_CSTR(&d_str, "nil");
- break;
- case Qtrue:
- d = FAKE_CSTR(&d_str, "true");
- break;
- case Qfalse:
- d = FAKE_CSTR(&d_str, "false");
- break;
- default:
- 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);
- }
- 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] == '#');
- break;
- }
- if (!singleton) {
- s = FAKE_CSTR(&s_str, ":");
- c = rb_class_name(CLASS_OF(obj));
- }
- else {
- c = s = FAKE_CSTR(&s_str, "");
- }
+ obj = ptr[NAME_ERR_MESG__RECV];
+ switch (obj) {
+ case Qnil:
+ d = FAKE_CSTR(&d_str, "nil");
+ break;
+ case Qtrue:
+ d = FAKE_CSTR(&d_str, "true");
+ break;
+ case Qfalse:
+ d = FAKE_CSTR(&d_str, "false");
+ break;
+ default:
+ d = rb_protect(name_err_mesg_receiver_name, obj, &state);
+ if (state || NIL_OR_UNDEF_P(d))
+ d = rb_protect(rb_inspect, obj, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ }
+ 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] == '#');
+ break;
+ }
+ if (!singleton) {
+ s = FAKE_CSTR(&s_str, ":");
+ c = rb_class_name(CLASS_OF(obj));
+ }
+ else {
+ c = s = FAKE_CSTR(&s_str, "");
+ }
args[0] = rb_obj_as_string(ptr[NAME_ERR_MESG__NAME]);
- args[1] = d;
- args[2] = s;
- args[3] = c;
- mesg = rb_str_format(4, args, mesg);
+ args[1] = d;
+ args[2] = s;
+ args[3] = c;
+ mesg = rb_str_format(4, args, mesg);
}
return mesg;
}
@@ -2040,11 +2141,11 @@ name_err_receiver(VALUE self)
VALUE *ptr, recv, mesg;
recv = rb_ivar_lookup(self, id_recv, Qundef);
- if (recv != Qundef) return recv;
+ if (!UNDEF_P(recv)) return recv;
mesg = rb_attr_get(self, id_mesg);
if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) {
- rb_raise(rb_eArgError, "no receiver is available");
+ rb_raise(rb_eArgError, "no receiver is available");
}
ptr = DATA_PTR(mesg);
return ptr[NAME_ERR_MESG__RECV];
@@ -2098,7 +2199,7 @@ key_err_receiver(VALUE self)
VALUE recv;
recv = rb_ivar_lookup(self, id_receiver, Qundef);
- if (recv != Qundef) return recv;
+ if (!UNDEF_P(recv)) return recv;
rb_raise(rb_eArgError, "no receiver is available");
}
@@ -2115,7 +2216,7 @@ key_err_key(VALUE self)
VALUE key;
key = rb_ivar_lookup(self, id_key, Qundef);
- if (key != Qundef) return key;
+ if (!UNDEF_P(key)) return key;
rb_raise(rb_eArgError, "no key is available");
}
@@ -2146,22 +2247,89 @@ key_err_initialize(int argc, VALUE *argv, VALUE self)
rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
if (!NIL_P(options)) {
- ID keywords[2];
- VALUE values[numberof(keywords)];
- int i;
- keywords[0] = id_receiver;
- keywords[1] = id_key;
- rb_get_kwargs(options, keywords, 0, numberof(values), values);
- for (i = 0; i < numberof(values); ++i) {
- if (values[i] != Qundef) {
- rb_ivar_set(self, keywords[i], values[i]);
- }
- }
+ ID keywords[2];
+ VALUE values[numberof(keywords)];
+ int i;
+ keywords[0] = id_receiver;
+ keywords[1] = id_key;
+ rb_get_kwargs(options, keywords, 0, numberof(values), values);
+ for (i = 0; i < numberof(values); ++i) {
+ if (!UNDEF_P(values[i])) {
+ rb_ivar_set(self, keywords[i], values[i]);
+ }
+ }
+ }
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * no_matching_pattern_key_error.matchee -> object
+ *
+ * Return the matchee associated with this NoMatchingPatternKeyError exception.
+ */
+
+static VALUE
+no_matching_pattern_key_err_matchee(VALUE self)
+{
+ VALUE matchee;
+
+ matchee = rb_ivar_lookup(self, id_matchee, Qundef);
+ if (!UNDEF_P(matchee)) return matchee;
+ rb_raise(rb_eArgError, "no matchee is available");
+}
+
+/*
+ * call-seq:
+ * no_matching_pattern_key_error.key -> object
+ *
+ * Return the key caused this NoMatchingPatternKeyError exception.
+ */
+
+static VALUE
+no_matching_pattern_key_err_key(VALUE self)
+{
+ VALUE key;
+
+ key = rb_ivar_lookup(self, id_key, Qundef);
+ if (!UNDEF_P(key)) return key;
+ rb_raise(rb_eArgError, "no key is available");
+}
+
+/*
+ * call-seq:
+ * NoMatchingPatternKeyError.new(message=nil, matchee: nil, key: nil) -> no_matching_pattern_key_error
+ *
+ * Construct a new +NoMatchingPatternKeyError+ exception with the given message,
+ * matchee and key.
+ */
+
+static VALUE
+no_matching_pattern_key_err_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE options;
+
+ rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);
+
+ if (!NIL_P(options)) {
+ ID keywords[2];
+ VALUE values[numberof(keywords)];
+ int i;
+ keywords[0] = id_matchee;
+ keywords[1] = id_key;
+ rb_get_kwargs(options, keywords, 0, numberof(values), values);
+ for (i = 0; i < numberof(values); ++i) {
+ if (!UNDEF_P(values[i])) {
+ rb_ivar_set(self, keywords[i], values[i]);
+ }
+ }
}
return self;
}
+
/*
* call-seq:
* SyntaxError.new([msg]) -> syntax_error
@@ -2174,13 +2342,32 @@ syntax_error_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE mesg;
if (argc == 0) {
- mesg = rb_fstring_lit("compile error");
- argc = 1;
- argv = &mesg;
+ mesg = rb_fstring_lit("compile error");
+ argc = 1;
+ argv = &mesg;
}
return rb_call_super(argc, argv);
}
+static VALUE
+syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
+{
+ if (NIL_P(exc)) {
+ *mesg = rb_enc_str_new(0, 0, enc);
+ exc = rb_class_new_instance(1, mesg, rb_eSyntaxError);
+ rb_ivar_set(exc, id_i_path, path);
+ }
+ else {
+ if (rb_attr_get(exc, id_i_path) != path) {
+ rb_raise(rb_eArgError, "SyntaxError#path changed");
+ }
+ VALUE s = *mesg = rb_attr_get(exc, idMesg);
+ if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n')
+ rb_str_cat_cstr(s, "\n");
+ }
+ return exc;
+}
+
/*
* Document-module: Errno
*
@@ -2219,30 +2406,30 @@ set_syserr(int n, const char *name)
st_data_t error;
if (!st_lookup(syserr_tbl, n, &error)) {
- error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
+ error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
- /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
- switch (n) {
- case EAGAIN:
- rb_eEAGAIN = error;
+ /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */
+ switch (n) {
+ case EAGAIN:
+ rb_eEAGAIN = error;
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- break;
- case EWOULDBLOCK:
+ break;
+ case EWOULDBLOCK:
#endif
- rb_eEWOULDBLOCK = error;
- break;
- case EINPROGRESS:
- rb_eEINPROGRESS = error;
- break;
- }
+ rb_eEWOULDBLOCK = error;
+ break;
+ case EINPROGRESS:
+ rb_eEINPROGRESS = error;
+ break;
+ }
- rb_define_const(error, "Errno", INT2NUM(n));
- st_add_direct(syserr_tbl, n, error);
+ rb_define_const(error, "Errno", INT2NUM(n));
+ st_add_direct(syserr_tbl, n, error);
}
else {
- rb_define_const(rb_mErrno, name, error);
+ rb_define_const(rb_mErrno, name, error);
}
return error;
}
@@ -2253,10 +2440,10 @@ get_syserr(int n)
st_data_t error;
if (!st_lookup(syserr_tbl, n, &error)) {
- char name[8]; /* some Windows' errno have 5 digits. */
+ char name[8]; /* some Windows' errno have 5 digits. */
- snprintf(name, sizeof(name), "E%03d", n);
- error = set_syserr(n, name);
+ snprintf(name, sizeof(name), "E%03d", n);
+ error = set_syserr(n, name);
}
return error;
}
@@ -2274,41 +2461,38 @@ get_syserr(int n)
static VALUE
syserr_initialize(int argc, VALUE *argv, VALUE self)
{
-#if !defined(_WIN32)
- char *strerror();
-#endif
const char *err;
VALUE mesg, error, func, errmsg;
VALUE klass = rb_obj_class(self);
if (klass == rb_eSystemCallError) {
- st_data_t data = (st_data_t)klass;
- rb_scan_args(argc, argv, "12", &mesg, &error, &func);
- if (argc == 1 && FIXNUM_P(mesg)) {
- error = mesg; mesg = Qnil;
- }
- if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
- klass = (VALUE)data;
- /* change class */
- if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
- rb_raise(rb_eTypeError, "invalid instance type");
- }
- RBASIC_SET_CLASS(self, klass);
- }
+ st_data_t data = (st_data_t)klass;
+ rb_scan_args(argc, argv, "12", &mesg, &error, &func);
+ if (argc == 1 && FIXNUM_P(mesg)) {
+ error = mesg; mesg = Qnil;
+ }
+ if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &data)) {
+ klass = (VALUE)data;
+ /* change class */
+ if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
+ rb_raise(rb_eTypeError, "invalid instance type");
+ }
+ RBASIC_SET_CLASS(self, klass);
+ }
}
else {
- rb_scan_args(argc, argv, "02", &mesg, &func);
- error = rb_const_get(klass, id_Errno);
+ rb_scan_args(argc, argv, "02", &mesg, &func);
+ error = rb_const_get(klass, id_Errno);
}
if (!NIL_P(error)) err = strerror(NUM2INT(error));
else err = "unknown error";
errmsg = rb_enc_str_new_cstr(err, rb_locale_encoding());
if (!NIL_P(mesg)) {
- VALUE str = StringValue(mesg);
+ VALUE str = StringValue(mesg);
- if (!NIL_P(func)) rb_str_catf(errmsg, " @ %"PRIsVALUE, func);
- rb_str_catf(errmsg, " - %"PRIsVALUE, str);
+ if (!NIL_P(func)) rb_str_catf(errmsg, " @ %"PRIsVALUE, func);
+ rb_str_catf(errmsg, " - %"PRIsVALUE, str);
}
mesg = errmsg;
@@ -2344,18 +2528,16 @@ syserr_eqq(VALUE self, VALUE exc)
VALUE num, e;
if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
- if (!rb_respond_to(exc, id_errno)) return Qfalse;
+ if (!rb_respond_to(exc, id_errno)) return Qfalse;
}
else if (self == rb_eSystemCallError) return Qtrue;
num = rb_attr_get(exc, id_errno);
if (NIL_P(num)) {
- num = rb_funcallv(exc, id_errno, 0, 0);
+ num = rb_funcallv(exc, id_errno, 0, 0);
}
e = rb_const_get(self, id_Errno);
- if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
- return Qtrue;
- return Qfalse;
+ return RBOOL(FIXNUM_P(num) ? num == e : rb_equal(num, e));
}
@@ -2779,6 +2961,8 @@ ivar_copy_i(st_data_t key, st_data_t val, st_data_t exc)
return ST_CONTINUE;
}
+void rb_exc_check_circular_cause(VALUE exc);
+
static VALUE
exception_loader(VALUE exc, VALUE obj)
{
@@ -2793,6 +2977,8 @@ exception_loader(VALUE exc, VALUE obj)
rb_ivar_foreach(obj, ivar_copy_i, exc);
+ rb_exc_check_circular_cause(exc);
+
if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) {
rb_ivar_set(exc, id_bt_locations, Qnil);
}
@@ -2813,6 +2999,7 @@ Init_Exception(void)
rb_define_method(rb_eException, "==", exc_equal, 1);
rb_define_method(rb_eException, "to_s", exc_to_s, 0);
rb_define_method(rb_eException, "message", exc_message, 0);
+ rb_define_method(rb_eException, "detailed_message", exc_detailed_message, -1);
rb_define_method(rb_eException, "full_message", exc_full_message, -1);
rb_define_method(rb_eException, "inspect", exc_inspect, 0);
rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
@@ -2843,9 +3030,16 @@ Init_Exception(void)
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);
+ /* RDoc will use literal name value while parsing rb_attr,
+ * and will render `idPath` as an attribute name without this trick */
+ ID path = idPath;
+
+ /* the path failed to parse */
+ rb_attr(rb_eSyntaxError, path, TRUE, FALSE, FALSE);
+
rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
/* the path failed to load */
- rb_attr(rb_eLoadError, rb_intern_const("path"), 1, 0, Qfalse);
+ rb_attr(rb_eLoadError, path, TRUE, FALSE, FALSE);
rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
@@ -2875,6 +3069,10 @@ Init_Exception(void)
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_eStandardError);
+ rb_eNoMatchingPatternKeyError = rb_define_class("NoMatchingPatternKeyError", rb_eNoMatchingPatternError);
+ rb_define_method(rb_eNoMatchingPatternKeyError, "initialize", no_matching_pattern_key_err_initialize, -1);
+ rb_define_method(rb_eNoMatchingPatternKeyError, "matchee", no_matching_pattern_key_err_matchee, 0);
+ rb_define_method(rb_eNoMatchingPatternKeyError, "key", no_matching_pattern_key_err_key, 0);
syserr_tbl = st_init_numtable();
rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
@@ -2896,8 +3094,10 @@ Init_Exception(void)
id_cause = rb_intern_const("cause");
id_message = rb_intern_const("message");
+ id_detailed_message = rb_intern_const("detailed_message");
id_backtrace = rb_intern_const("backtrace");
id_key = rb_intern_const("key");
+ id_matchee = rb_intern_const("matchee");
id_args = rb_intern_const("args");
id_receiver = rb_intern_const("receiver");
id_private_call_p = rb_intern_const("private_call?");
@@ -2915,6 +3115,7 @@ Init_Exception(void)
id_recv = rb_make_internal_id();
sym_category = ID2SYM(id_category);
+ sym_highlight = ID2SYM(rb_intern_const("highlight"));
warning_categories.id2enum = rb_init_identtable();
st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED);
@@ -2992,8 +3193,8 @@ void
rb_notimplement(void)
{
rb_raise(rb_eNotImpError,
- "%"PRIsVALUE"() function is unimplemented on this machine",
- rb_id2str(rb_frame_this_func()));
+ "%"PRIsVALUE"() function is unimplemented on this machine",
+ rb_id2str(rb_frame_this_func()));
}
void
@@ -3024,7 +3225,7 @@ make_errno_exc(const char *mesg)
errno = 0;
if (n == 0) {
- rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
+ rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
}
return rb_syserr_new(n, mesg);
}
@@ -3037,8 +3238,8 @@ make_errno_exc_str(VALUE mesg)
errno = 0;
if (!mesg) mesg = Qnil;
if (n == 0) {
- const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
- rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
+ const char *s = !NIL_P(mesg) ? RSTRING_PTR(mesg) : "";
+ rb_bug("rb_sys_fail_str(%s) - errno == 0", s);
}
return rb_syserr_new_str(n, mesg);
}
@@ -3104,10 +3305,10 @@ rb_syserr_new_path_in(const char *func_name, int n, VALUE path)
if (!path) path = Qnil;
if (n == 0) {
- const char *s = !NIL_P(path) ? RSTRING_PTR(path) : "";
- if (!func_name) func_name = "(null)";
- rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
- func_name, s);
+ const char *s = !NIL_P(path) ? RSTRING_PTR(path) : "";
+ if (!func_name) func_name = "(null)";
+ rb_bug("rb_sys_fail_path_in(%s, %s) - errno == 0",
+ func_name, s);
}
args[0] = path;
args[1] = rb_str_new_cstr(func_name);
@@ -3115,36 +3316,41 @@ rb_syserr_new_path_in(const char *func_name, int n, VALUE path)
}
#endif
+NORETURN(static void rb_mod_exc_raise(VALUE exc, VALUE mod));
+
+static void
+rb_mod_exc_raise(VALUE exc, VALUE mod)
+{
+ rb_extend_object(exc, mod);
+ rb_exc_raise(exc);
+}
+
void
rb_mod_sys_fail(VALUE mod, const char *mesg)
{
VALUE exc = make_errno_exc(mesg);
- rb_extend_object(exc, mod);
- rb_exc_raise(exc);
+ rb_mod_exc_raise(exc, mod);
}
void
rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
{
VALUE exc = make_errno_exc_str(mesg);
- rb_extend_object(exc, mod);
- rb_exc_raise(exc);
+ rb_mod_exc_raise(exc, mod);
}
void
rb_mod_syserr_fail(VALUE mod, int e, const char *mesg)
{
VALUE exc = rb_syserr_new(e, mesg);
- rb_extend_object(exc, mod);
- rb_exc_raise(exc);
+ rb_mod_exc_raise(exc, mod);
}
void
rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
{
VALUE exc = rb_syserr_new_str(e, mesg);
- rb_extend_object(exc, mod);
- rb_exc_raise(exc);
+ rb_mod_exc_raise(exc, mod);
}
static void
@@ -3160,11 +3366,11 @@ void
rb_sys_warn(const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- int errno_save = errno;
- with_warning_string(mesg, 0, fmt) {
- syserr_warning(mesg, errno_save);
- }
- errno = errno_save;
+ int errno_save = errno;
+ with_warning_string(mesg, 0, fmt) {
+ syserr_warning(mesg, errno_save);
+ }
+ errno = errno_save;
}
}
@@ -3172,9 +3378,9 @@ void
rb_syserr_warn(int err, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- with_warning_string(mesg, 0, fmt) {
- syserr_warning(mesg, err);
- }
+ with_warning_string(mesg, 0, fmt) {
+ syserr_warning(mesg, err);
+ }
}
}
@@ -3182,11 +3388,11 @@ void
rb_sys_enc_warn(rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- int errno_save = errno;
- with_warning_string(mesg, enc, fmt) {
- syserr_warning(mesg, errno_save);
- }
- errno = errno_save;
+ int errno_save = errno;
+ with_warning_string(mesg, enc, fmt) {
+ syserr_warning(mesg, errno_save);
+ }
+ errno = errno_save;
}
}
@@ -3194,9 +3400,9 @@ void
rb_syserr_enc_warn(int err, rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
- with_warning_string(mesg, enc, fmt) {
- syserr_warning(mesg, err);
- }
+ with_warning_string(mesg, enc, fmt) {
+ syserr_warning(mesg, err);
+ }
}
}
#endif
@@ -3205,11 +3411,11 @@ void
rb_sys_warning(const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- int errno_save = errno;
- with_warning_string(mesg, 0, fmt) {
- syserr_warning(mesg, errno_save);
- }
- errno = errno_save;
+ int errno_save = errno;
+ with_warning_string(mesg, 0, fmt) {
+ syserr_warning(mesg, errno_save);
+ }
+ errno = errno_save;
}
}
@@ -3218,9 +3424,9 @@ void
rb_syserr_warning(int err, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- with_warning_string(mesg, 0, fmt) {
- syserr_warning(mesg, err);
- }
+ with_warning_string(mesg, 0, fmt) {
+ syserr_warning(mesg, err);
+ }
}
}
#endif
@@ -3229,11 +3435,11 @@ void
rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- int errno_save = errno;
- with_warning_string(mesg, enc, fmt) {
- syserr_warning(mesg, errno_save);
- }
- errno = errno_save;
+ int errno_save = errno;
+ with_warning_string(mesg, enc, fmt) {
+ syserr_warning(mesg, errno_save);
+ }
+ errno = errno_save;
}
}
@@ -3241,9 +3447,9 @@ void
rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...)
{
if (RTEST(ruby_verbose)) {
- with_warning_string(mesg, enc, fmt) {
- syserr_warning(mesg, err);
- }
+ with_warning_string(mesg, enc, fmt) {
+ syserr_warning(mesg, err);
+ }
}
}
@@ -3301,8 +3507,8 @@ rb_error_frozen_object(VALUE frozen_obj)
rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg);
if (!NIL_P(debug_info = rb_attr_get(frozen_obj, created_info))) {
- VALUE path = rb_ary_entry(debug_info, 0);
- VALUE line = rb_ary_entry(debug_info, 1);
+ VALUE path = rb_ary_entry(debug_info, 0);
+ VALUE line = rb_ary_entry(debug_info, 1);
rb_str_catf(mesg, ", created at %"PRIsVALUE":%"PRIsVALUE, path, line);
}
@@ -3317,19 +3523,6 @@ rb_check_frozen(VALUE obj)
}
void
-rb_error_untrusted(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "rb_error_untrusted", NULL);
-}
-
-#undef rb_check_trusted
-void
-rb_check_trusted(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "rb_check_trusted", NULL);
-}
-
-void
rb_check_copyable(VALUE obj, VALUE orig)
{
if (!FL_ABLE(obj)) return;
diff --git a/eval.c b/eval.c
index 885e1ae782..a61dfb1289 100644
--- a/eval.c
+++ b/eval.c
@@ -21,6 +21,7 @@
#include "gc.h"
#include "internal.h"
#include "internal/class.h"
+#include "internal/cont.h"
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/hash.h"
@@ -42,7 +43,7 @@ NORETURN(static void rb_raise_jump(VALUE, VALUE));
void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
void rb_ec_clear_all_trace_func(const rb_execution_context_t *ec);
-static int rb_ec_cleanup(rb_execution_context_t *ec, int ex);
+static int rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex);
static int rb_ec_exec_node(rb_execution_context_t *ec, void *n);
VALUE rb_eLocalJumpError;
@@ -61,18 +62,13 @@ extern ID ruby_static_id_cause;
(!SPECIAL_CONST_P(obj) && \
(BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
-/*!
- * Initializes the VM and builtin libraries.
- * @retval 0 if succeeded.
- * @retval non-zero an error occurred.
- */
int
ruby_setup(void)
{
enum ruby_tag_type state;
if (GET_VM())
- return 0;
+ return 0;
ruby_init_stack((void *)&state);
@@ -90,41 +86,28 @@ ruby_setup(void)
EC_PUSH_TAG(GET_EC());
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- rb_call_inits();
- ruby_prog_init();
- GET_VM()->running = 1;
+ rb_call_inits();
+ ruby_prog_init();
+ GET_VM()->running = 1;
}
EC_POP_TAG();
return state;
}
-/*!
- * Calls ruby_setup() and check error.
- *
- * Prints errors and calls exit(3) if an error occurred.
- */
void
ruby_init(void)
{
int state = ruby_setup();
if (state) {
- if (RTEST(ruby_debug))
- error_print(GET_EC());
- exit(EXIT_FAILURE);
+ if (RTEST(ruby_debug)) {
+ rb_execution_context_t *ec = GET_EC();
+ rb_ec_error_print(ec, ec->errinfo);
+ }
+ exit(EXIT_FAILURE);
}
}
-/*! Processes command line arguments and compiles the Ruby source to execute.
- *
- * This function does:
- * \li Processes the given command line flags and arguments for ruby(1)
- * \li compiles the source code from the given argument, -e or stdin, and
- * \li returns the compiled source as an opaque pointer to an internal data structure
- *
- * @return an opaque pointer to the compiled source or an internal special value.
- * @sa ruby_executable_node().
- */
void *
ruby_options(int argc, char **argv)
{
@@ -135,12 +118,13 @@ ruby_options(int argc, char **argv)
ruby_init_stack((void *)&iseq);
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
+ SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
}
else {
rb_ec_clear_current_thread_trace_func(ec);
- state = error_handle(ec, state);
- iseq = (void *)INT2FIX(state);
+ int exitcode = error_handle(ec, ec->errinfo, state);
+ ec->errinfo = Qnil; /* just been handled */
+ iseq = (void *)INT2FIX(exitcode);
}
EC_POP_TAG();
return iseq;
@@ -156,7 +140,7 @@ rb_ec_fiber_scheduler_finalize(rb_execution_context_t *ec)
rb_fiber_scheduler_set(Qnil);
}
else {
- state = error_handle(ec, state);
+ state = error_handle(ec, ec->errinfo, state);
}
EC_POP_TAG();
}
@@ -184,13 +168,6 @@ rb_ec_finalize(rb_execution_context_t *ec)
rb_objspace_call_finalizer(rb_ec_vm_ptr(ec)->objspace);
}
-/** Runs the VM finalization processes.
- *
- * <code>END{}</code> and procs registered by <code>Kernel.#at_exit</code> are
- * executed here. See the Ruby language spec for more details.
- *
- * @note This function is allowed to raise an exception if an error occurred.
- */
void
ruby_finalize(void)
{
@@ -199,33 +176,24 @@ ruby_finalize(void)
rb_ec_finalize(ec);
}
-/** Destructs the VM.
- *
- * Runs the VM finalization processes as well as ruby_finalize(), and frees
- * resources used by the VM.
- *
- * @param ex Default value to the return value.
- * @return If an error occurred returns a non-zero. If otherwise, returns the
- * given ex.
- * @note This function does not raise any exception.
- */
int
ruby_cleanup(int ex)
{
- return rb_ec_cleanup(GET_EC(), ex);
+ return rb_ec_cleanup(GET_EC(), (enum ruby_tag_type)ex);
}
static int
-rb_ec_cleanup(rb_execution_context_t *ec, int ex0)
+rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex)
{
int state;
- volatile VALUE errs[2] = { Qundef, Qundef };
- int nerr;
+ volatile VALUE save_error = Qundef;
+ volatile int sysex = EXIT_SUCCESS;
+ volatile int signaled = 0;
rb_thread_t *th = rb_ec_thread_ptr(ec);
rb_thread_t *const volatile th0 = th;
- volatile int sysex = EXIT_SUCCESS;
volatile int step = 0;
- volatile int ex = ex0;
+ volatile VALUE message = Qnil;
+ VALUE buf;
rb_threadptr_interrupt(th);
rb_threadptr_check_signal(th);
@@ -235,60 +203,61 @@ rb_ec_cleanup(rb_execution_context_t *ec, int ex0)
SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(ec); });
step_0: step++;
- errs[1] = ec->errinfo;
+ save_error = ec->errinfo;
if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil;
- ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
+ ruby_init_stack(&message);
+ /* exits with failure but silently when an exception raised
+ * here */
SAVE_ROOT_JMPBUF(th, rb_ec_teardown(ec));
step_1: step++;
- /* protect from Thread#raise */
- th->status = THREAD_KILLED;
+ VALUE err = ec->errinfo;
+ volatile int mode0 = 0, mode1 = 0;
+ if (err != save_error && !NIL_P(err)) {
+ mode0 = exiting_split(err, &sysex, &signaled);
+ }
+
+ /* exceptions after here will be ignored */
+
+ /* build error message including causes */
+ err = ATOMIC_VALUE_EXCHANGE(save_error, Qnil);
+
+ if (!NIL_P(err) && !THROW_DATA_P(err)) {
+ mode1 = exiting_split(err, (mode0 & EXITING_WITH_STATUS) ? NULL : &sysex, &signaled);
+ if (mode1 & EXITING_WITH_MESSAGE) {
+ buf = rb_str_new(NULL, 0);
+ SAVE_ROOT_JMPBUF(th, rb_ec_error_print_detailed(ec, err, buf, Qundef));
+ message = buf;
+ }
+ }
+
+ step_2: step++;
+ /* protect from Thread#raise */
+ th->status = THREAD_KILLED;
- errs[0] = ec->errinfo;
- SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all());
+ SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all());
+
+ step_3: step++;
+ if (!NIL_P(buf = message)) {
+ warn_print_str(buf);
+ }
+ else if (!NIL_OR_UNDEF_P(err = save_error) ||
+ (ex != TAG_NONE && !((mode0|mode1) & EXITING_WITH_STATUS))) {
+ sysex = error_handle(ec, err, ex);
+ }
}
else {
th = th0;
- switch (step) {
- case 0: goto step_0;
- case 1: goto step_1;
- }
- if (ex == 0) ex = state;
- }
- ec->errinfo = errs[1];
- sysex = error_handle(ec, ex);
-
- state = 0;
- for (nerr = 0; nerr < numberof(errs); ++nerr) {
- VALUE err = ATOMIC_VALUE_EXCHANGE(errs[nerr], Qnil);
- VALUE sig;
-
- if (!RTEST(err)) continue;
-
- /* ec->errinfo contains a NODE while break'ing */
- if (THROW_DATA_P(err)) continue;
-
- if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
- sysex = sysexit_status(err);
- break;
- }
- else if (rb_obj_is_kind_of(err, rb_eSignal)) {
- VALUE sig = rb_ivar_get(err, id_signo);
- 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;
+ switch (step) {
+ case 0: goto step_0;
+ case 1: goto step_1;
+ case 2: goto step_2;
+ case 3: goto step_3;
}
- else if (sysex == EXIT_SUCCESS) {
- sysex = EXIT_FAILURE;
- }
}
- mjit_finish(true); // We still need ISeqs here.
+ mjit_finish(true); // We still need ISeqs here, so it's before rb_ec_finalize().
rb_ec_finalize(ec);
@@ -299,7 +268,10 @@ rb_ec_cleanup(rb_execution_context_t *ec, int ex0)
th = th0;
rb_thread_stop_timer_thread();
ruby_vm_destruct(th->vm);
- if (state) ruby_default_signal(state);
+ // For YJIT, call this after ruby_vm_destruct() frees jit_cont for the root fiber.
+ rb_jit_cont_finish();
+
+ if (signaled) ruby_default_signal(signaled);
return sysex;
}
@@ -314,33 +286,20 @@ rb_ec_exec_node(rb_execution_context_t *ec, void *n)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
rb_thread_t *const th = rb_ec_thread_ptr(ec);
- SAVE_ROOT_JMPBUF(th, {
- rb_iseq_eval_main(iseq);
- });
+ SAVE_ROOT_JMPBUF(th, {
+ rb_iseq_eval_main(iseq);
+ });
}
EC_POP_TAG();
return state;
}
-/*! Calls ruby_cleanup() and exits the process */
void
ruby_stop(int ex)
{
exit(ruby_cleanup(ex));
}
-/*! Checks the return value of ruby_options().
- * @param n return value of ruby_options().
- * @param status pointer to the exit status of this process.
- *
- * ruby_options() sometimes returns a special value to indicate this process
- * should immediately exit. This function checks if the case. Also stores the
- * exit status that the caller have to pass to exit(3) into
- * <code>*status</code>.
- *
- * @retval non-zero if the given opaque pointer is actually a compiled source.
- * @retval 0 if the given value is such a special value.
- */
int
ruby_executable_node(void *n, int *status)
{
@@ -351,31 +310,26 @@ ruby_executable_node(void *n, int *status)
case Qtrue: s = EXIT_SUCCESS; break;
case Qfalse: s = EXIT_FAILURE; break;
default:
- if (!FIXNUM_P(v)) return TRUE;
- s = FIX2INT(v);
+ if (!FIXNUM_P(v)) return TRUE;
+ s = FIX2INT(v);
}
if (status) *status = s;
return FALSE;
}
-/*! Runs the given compiled source and exits this process.
- * @retval 0 if successfully run the source
- * @retval non-zero if an error occurred.
-*/
int
ruby_run_node(void *n)
{
rb_execution_context_t *ec = GET_EC();
int status;
if (!ruby_executable_node(n, &status)) {
- rb_ec_cleanup(ec, 0);
- return status;
+ rb_ec_cleanup(ec, (NIL_P(ec->errinfo) ? TAG_NONE : TAG_RAISE));
+ return status;
}
ruby_init_stack((void *)&status);
return rb_ec_cleanup(ec, rb_ec_exec_node(ec, n));
}
-/*! Runs the given compiled source */
int
ruby_exec_node(void *n)
{
@@ -405,12 +359,12 @@ rb_mod_nesting(VALUE _)
const rb_cref_t *cref = rb_vm_cref();
while (cref && CREF_NEXT(cref)) {
- VALUE klass = CREF_CLASS(cref);
- if (!CREF_PUSHED_BY_EVAL(cref) &&
- !NIL_P(klass)) {
- rb_ary_push(ary, klass);
- }
- cref = CREF_NEXT(cref);
+ VALUE klass = CREF_CLASS(cref);
+ if (!CREF_PUSHED_BY_EVAL(cref) &&
+ !NIL_P(klass)) {
+ rb_ary_push(ary, klass);
+ }
+ cref = CREF_NEXT(cref);
}
return ary;
}
@@ -446,23 +400,23 @@ rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
void *data = 0;
if (argc > 0 || mod != rb_cModule) {
- return rb_mod_constants(argc, argv, mod);
+ return rb_mod_constants(argc, argv, mod);
}
while (cref) {
- klass = CREF_CLASS(cref);
- if (!CREF_PUSHED_BY_EVAL(cref) &&
- !NIL_P(klass)) {
- data = rb_mod_const_at(CREF_CLASS(cref), data);
- if (!cbase) {
- cbase = klass;
- }
- }
- cref = CREF_NEXT(cref);
+ klass = CREF_CLASS(cref);
+ if (!CREF_PUSHED_BY_EVAL(cref) &&
+ !NIL_P(klass)) {
+ data = rb_mod_const_at(CREF_CLASS(cref), data);
+ if (!cbase) {
+ cbase = klass;
+ }
+ }
+ cref = CREF_NEXT(cref);
}
if (cbase) {
- data = rb_mod_const_of(cbase, data);
+ data = rb_mod_const_of(cbase, data);
}
return rb_const_list(data);
}
@@ -477,42 +431,45 @@ void
rb_class_modify_check(VALUE klass)
{
if (SPECIAL_CONST_P(klass)) {
- Check_Type(klass, T_CLASS);
+ Check_Type(klass, T_CLASS);
+ }
+ if (RB_TYPE_P(klass, T_MODULE)) {
+ rb_module_set_initialized(klass);
}
if (OBJ_FROZEN(klass)) {
- const char *desc;
-
- if (FL_TEST(klass, FL_SINGLETON)) {
- desc = "object";
- klass = rb_ivar_get(klass, id__attached__);
- if (!SPECIAL_CONST_P(klass)) {
- switch (BUILTIN_TYPE(klass)) {
- case T_MODULE:
- case T_ICLASS:
- desc = "Module";
- break;
- case T_CLASS:
- desc = "Class";
- break;
+ const char *desc;
+
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ desc = "object";
+ klass = rb_ivar_get(klass, id__attached__);
+ if (!SPECIAL_CONST_P(klass)) {
+ switch (BUILTIN_TYPE(klass)) {
+ case T_MODULE:
+ case T_ICLASS:
+ desc = "Module";
+ break;
+ case T_CLASS:
+ desc = "Class";
+ break;
default:
break;
- }
- }
- }
- else {
- switch (BUILTIN_TYPE(klass)) {
- case T_MODULE:
- case T_ICLASS:
- desc = "module";
- break;
- case T_CLASS:
- desc = "class";
- break;
- default:
+ }
+ }
+ }
+ else {
+ switch (BUILTIN_TYPE(klass)) {
+ case T_MODULE:
+ case T_ICLASS:
+ desc = "module";
+ break;
+ case T_CLASS:
+ desc = "class";
+ break;
+ default:
Check_Type(klass, T_CLASS);
UNREACHABLE;
- }
- }
+ }
+ }
rb_frozen_error_raise(klass, "can't modify frozen %s: %"PRIsVALUE, desc, klass);
}
}
@@ -526,23 +483,23 @@ exc_setup_cause(VALUE exc, VALUE cause)
{
#if OPT_SUPPORT_JOKE
if (NIL_P(cause)) {
- ID id_true_cause;
- CONST_ID(id_true_cause, "true_cause");
-
- cause = rb_attr_get(rb_eFatal, id_true_cause);
- if (NIL_P(cause)) {
- cause = rb_exc_new_cstr(rb_eFatal, "because using such Ruby");
- rb_ivar_set(cause, id_cause, INT2FIX(42)); /* the answer */
- OBJ_FREEZE(cause);
- rb_ivar_set(rb_eFatal, id_true_cause, cause);
- }
+ ID id_true_cause;
+ CONST_ID(id_true_cause, "true_cause");
+
+ cause = rb_attr_get(rb_eFatal, id_true_cause);
+ if (NIL_P(cause)) {
+ cause = rb_exc_new_cstr(rb_eFatal, "because using such Ruby");
+ rb_ivar_set(cause, id_cause, INT2FIX(42)); /* the answer */
+ OBJ_FREEZE(cause);
+ rb_ivar_set(rb_eFatal, id_true_cause, cause);
+ }
}
#endif
if (!NIL_P(cause) && cause != exc) {
- rb_ivar_set(exc, id_cause, cause);
- if (!rb_ivar_defined(cause, id_cause)) {
- rb_ivar_set(cause, id_cause, Qnil);
- }
+ rb_ivar_set(exc, id_cause, cause);
+ if (!rb_ivar_defined(cause, id_cause)) {
+ rb_ivar_set(cause, id_cause, Qnil);
+ }
}
return exc;
}
@@ -554,23 +511,23 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause)
int nocircular = 0;
if (NIL_P(mesg)) {
- mesg = ec->errinfo;
- if (INTERNAL_EXCEPTION_P(mesg)) EC_JUMP_TAG(ec, TAG_FATAL);
- nocause = 1;
+ mesg = ec->errinfo;
+ if (INTERNAL_EXCEPTION_P(mesg)) EC_JUMP_TAG(ec, TAG_FATAL);
+ nocause = 1;
}
if (NIL_P(mesg)) {
- mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
- nocause = 0;
+ mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
+ nocause = 0;
nocircular = 1;
}
- if (*cause == Qundef) {
- if (nocause) {
- *cause = Qnil;
+ if (UNDEF_P(*cause)) {
+ if (nocause) {
+ *cause = Qnil;
nocircular = 1;
- }
- else if (!rb_ivar_defined(mesg, id_cause)) {
- *cause = get_ec_errinfo(ec);
- }
+ }
+ else if (!rb_ivar_defined(mesg, id_cause)) {
+ *cause = get_ec_errinfo(ec);
+ }
else {
nocircular = 1;
}
@@ -579,13 +536,17 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause)
rb_raise(rb_eTypeError, "exception object expected");
}
- if (!nocircular && !NIL_P(*cause) && *cause != Qundef && *cause != mesg) {
+ if (!nocircular && !NIL_P(*cause) && !UNDEF_P(*cause) && *cause != mesg) {
+#if 0 /* maybe critical for some cases */
+ rb_exc_check_circular_cause(*cause);
+#else
VALUE c = *cause;
while (!NIL_P(c = rb_attr_get(c, id_cause))) {
if (c == mesg) {
rb_raise(rb_eArgError, "circular causes");
}
}
+#endif
}
return mesg;
}
@@ -598,68 +559,68 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE
const char *file = rb_source_location_cstr(&line);
const char *const volatile file0 = file;
- if ((file && !NIL_P(mesg)) || (cause != Qundef)) {
- volatile int state = 0;
-
- EC_PUSH_TAG(ec);
- if (EC_EXEC_TAG() == TAG_NONE && !(state = rb_ec_set_raised(ec))) {
- VALUE bt = rb_get_backtrace(mesg);
- if (!NIL_P(bt) || cause == Qundef) {
- if (OBJ_FROZEN(mesg)) {
- mesg = rb_obj_dup(mesg);
- }
- }
- if (cause != Qundef && !THROW_DATA_P(cause)) {
- exc_setup_cause(mesg, cause);
- }
- if (NIL_P(bt)) {
- VALUE at = rb_ec_backtrace_object(ec);
- rb_ivar_set(mesg, idBt_locations, at);
- set_backtrace(mesg, at);
- }
- rb_ec_reset_raised(ec);
- }
- EC_POP_TAG();
+ if ((file && !NIL_P(mesg)) || !UNDEF_P(cause)) {
+ volatile int state = 0;
+
+ EC_PUSH_TAG(ec);
+ if (EC_EXEC_TAG() == TAG_NONE && !(state = rb_ec_set_raised(ec))) {
+ VALUE bt = rb_get_backtrace(mesg);
+ if (!NIL_P(bt) || UNDEF_P(cause)) {
+ if (OBJ_FROZEN(mesg)) {
+ mesg = rb_obj_dup(mesg);
+ }
+ }
+ if (!UNDEF_P(cause) && !THROW_DATA_P(cause)) {
+ exc_setup_cause(mesg, cause);
+ }
+ if (NIL_P(bt)) {
+ VALUE at = rb_ec_backtrace_object(ec);
+ rb_ivar_set(mesg, idBt_locations, at);
+ set_backtrace(mesg, at);
+ }
+ rb_ec_reset_raised(ec);
+ }
+ EC_POP_TAG();
file = file0;
- if (state) goto fatal;
+ if (state) goto fatal;
}
if (!NIL_P(mesg)) {
- ec->errinfo = mesg;
+ ec->errinfo = mesg;
}
if (RTEST(ruby_debug) && !NIL_P(e = ec->errinfo) &&
- !rb_obj_is_kind_of(e, rb_eSystemExit)) {
- enum ruby_tag_type state;
-
- mesg = e;
- EC_PUSH_TAG(ec);
- if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- ec->errinfo = Qnil;
- e = rb_obj_as_string(mesg);
- ec->errinfo = mesg;
- if (file && line) {
- e = rb_sprintf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
- rb_obj_class(mesg), file, line, e);
- }
- else if (file) {
- e = rb_sprintf("Exception `%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
- rb_obj_class(mesg), file, e);
- }
- else {
- e = rb_sprintf("Exception `%"PRIsVALUE"' - %"PRIsVALUE"\n",
- rb_obj_class(mesg), e);
- }
- warn_print_str(e);
- }
- EC_POP_TAG();
- if (state == TAG_FATAL && ec->errinfo == exception_error) {
- ec->errinfo = mesg;
- }
- else if (state) {
- rb_ec_reset_raised(ec);
- EC_JUMP_TAG(ec, state);
- }
+ !rb_obj_is_kind_of(e, rb_eSystemExit)) {
+ enum ruby_tag_type state;
+
+ mesg = e;
+ EC_PUSH_TAG(ec);
+ if ((state = EC_EXEC_TAG()) == TAG_NONE) {
+ ec->errinfo = Qnil;
+ e = rb_obj_as_string(mesg);
+ ec->errinfo = mesg;
+ if (file && line) {
+ e = rb_sprintf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n",
+ rb_obj_class(mesg), file, line, e);
+ }
+ else if (file) {
+ e = rb_sprintf("Exception `%"PRIsVALUE"' at %s - %"PRIsVALUE"\n",
+ rb_obj_class(mesg), file, e);
+ }
+ else {
+ e = rb_sprintf("Exception `%"PRIsVALUE"' - %"PRIsVALUE"\n",
+ rb_obj_class(mesg), e);
+ }
+ warn_print_str(e);
+ }
+ EC_POP_TAG();
+ if (state == TAG_FATAL && ec->errinfo == exception_error) {
+ ec->errinfo = mesg;
+ }
+ else if (state) {
+ rb_ec_reset_raised(ec);
+ EC_JUMP_TAG(ec, state);
+ }
}
if (rb_ec_set_raised(ec)) {
@@ -667,8 +628,8 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE
}
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);
+ RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(ec->errinfo));
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_RAISE, ec->cfp->self, 0, 0, 0, mesg);
}
return;
@@ -682,11 +643,15 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE
void
rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause)
{
- if (cause == Qundef) {
- cause = get_ec_errinfo(ec);
+ if (UNDEF_P(cause)) {
+ cause = get_ec_errinfo(ec);
}
if (cause != mesg) {
- rb_ivar_set(mesg, id_cause, cause);
+ if (THROW_DATA_P(cause)) {
+ cause = Qnil;
+ }
+
+ rb_ivar_set(mesg, id_cause, cause);
}
}
@@ -707,7 +672,7 @@ static void
rb_exc_exception(VALUE mesg, int tag, VALUE cause)
{
if (!NIL_P(mesg)) {
- mesg = make_exception(1, &mesg, FALSE);
+ mesg = make_exception(1, &mesg, FALSE);
}
rb_longjmp(GET_EC(), tag, mesg, cause);
}
@@ -738,10 +703,6 @@ rb_exc_fatal(VALUE mesg)
rb_exc_exception(mesg, TAG_FATAL, Qnil);
}
-/*!
- * Raises an \c Interrupt exception.
- * \ingroup exception
- */
void
rb_interrupt(void)
{
@@ -751,23 +712,24 @@ rb_interrupt(void)
enum {raise_opt_cause, raise_max_opt}; /*< \private */
static int
-extract_raise_opts(int argc, const VALUE *argv, VALUE *opts)
+extract_raise_opts(int argc, VALUE *argv, VALUE *opts)
{
int i;
if (argc > 0) {
- VALUE opt = argv[argc-1];
- if (RB_TYPE_P(opt, T_HASH)) {
- if (!RHASH_EMPTY_P(opt)) {
- ID keywords[1];
- CONST_ID(keywords[0], "cause");
- rb_get_kwargs(opt, keywords, 0, -1-raise_max_opt, opts);
- if (RHASH_EMPTY_P(opt)) --argc;
- return argc;
- }
- }
+ VALUE opt;
+ argc = rb_scan_args(argc, argv, "*:", NULL, &opt);
+ if (!NIL_P(opt)) {
+ if (!RHASH_EMPTY_P(opt)) {
+ ID keywords[1];
+ CONST_ID(keywords[0], "cause");
+ rb_get_kwargs(opt, keywords, 0, -1-raise_max_opt, opts);
+ if (!RHASH_EMPTY_P(opt)) argv[argc++] = opt;
+ return argc;
+ }
+ }
}
for (i = 0; i < raise_max_opt; ++i) {
- opts[i] = Qundef;
+ opts[i] = Qundef;
}
return argc;
}
@@ -780,7 +742,7 @@ rb_f_raise(int argc, VALUE *argv)
argc = extract_raise_opts(argc, argv, opts);
if (argc == 0) {
- if (*cause != Qundef) {
+ if (!UNDEF_P(*cause)) {
rb_raise(rb_eArgError, "only cause is given with no arguments");
}
err = get_errinfo();
@@ -839,24 +801,24 @@ make_exception(int argc, const VALUE *argv, int isstr)
case 0:
return Qnil;
case 1:
- exc = argv[0];
+ exc = argv[0];
if (isstr &&! NIL_P(exc)) {
- mesg = rb_check_string_type(exc);
- if (!NIL_P(mesg)) {
+ mesg = rb_check_string_type(exc);
+ if (!NIL_P(mesg)) {
return rb_exc_new3(rb_eRuntimeError, mesg);
- }
- }
+ }
+ }
case 2:
case 3:
- break;
+ break;
default:
rb_error_arity(argc, 0, 3);
}
if (NIL_P(mesg)) {
mesg = rb_check_funcall(argv[0], idException, argc != 1, &argv[1]);
}
- if (mesg == Qundef) {
+ if (UNDEF_P(mesg)) {
rb_raise(rb_eTypeError, "exception class/object expected");
}
if (!rb_obj_is_kind_of(mesg, rb_eException)) {
@@ -869,26 +831,6 @@ make_exception(int argc, const VALUE *argv, int isstr)
return mesg;
}
-/*!
- * Make an \c Exception object from the list of arguments in a manner
- * similar to \c Kernel\#raise.
- *
- * \param[in] argc the number of arguments
- * \param[in] argv a pointer to the array of arguments.
- *
- * The first form of this function takes a \c String argument. Then
- * it returns a \c RuntimeError whose error message is the given value.
- *
- * The second from of this function takes an \c Exception object. Then
- * it just returns the given value.
- *
- * The last form takes an exception class, an optional error message and
- * an optional array of backtrace. Then it passes the optional arguments
- * to \c #exception method of the exception class.
- *
- * \return the exception object, or \c Qnil if \c argc is 0.
- * \ingroup exception
- */
VALUE
rb_make_exception(int argc, const VALUE *argv)
{
@@ -913,36 +855,23 @@ rb_raise_jump(VALUE mesg, VALUE cause)
rb_longjmp(ec, TAG_RAISE, mesg, cause);
}
-/*!
- * Continues the exception caught by rb_protect() and rb_eval_string_protect().
- *
- * This function never return to the caller.
- * \param[in] the value of \c *state which the protect function has set to the
- * their last parameter.
- * \ingroup exception
- */
void
rb_jump_tag(int tag)
{
if (UNLIKELY(tag < TAG_RETURN || tag > TAG_FATAL)) {
- unknown_longjmp_status(tag);
+ unknown_longjmp_status(tag);
}
EC_JUMP_TAG(GET_EC(), tag);
}
-/*! Determines if the current method is given a block.
- * \retval zero if not given
- * \retval non-zero if given
- * \ingroup defmethod
- */
int
rb_block_given_p(void)
{
if (rb_vm_frame_block_handler(GET_EC()->cfp) == VM_BLOCK_HANDLER_NONE) {
- return FALSE;
+ return FALSE;
}
else {
- return TRUE;
+ return TRUE;
}
}
@@ -956,41 +885,14 @@ rb_keyword_given_p(void)
VALUE rb_eThreadError;
-/*! Declares that the current method needs a block.
- *
- * Raises a \c LocalJumpError if not given a block.
- * \ingroup defmethod
- */
void
rb_need_block(void)
{
if (!rb_block_given_p()) {
- rb_vm_localjump_error("no block given", Qnil, 0);
+ rb_vm_localjump_error("no block given", Qnil, 0);
}
}
-/*! An equivalent of \c rescue clause.
- *
- * Equivalent to <code>begin .. rescue err_type .. end</code>
- *
- * \param[in] b_proc a function which potentially raises an exception.
- * \param[in] data1 the argument of \a b_proc
- * \param[in] r_proc a function which rescues an exception in \a b_proc.
- * \param[in] data2 the first argument of \a r_proc
- * \param[in] ... 1 or more exception classes. Must be terminated by \c (VALUE)0.
- *
- * First it calls the function \a b_proc, with \a data1 as the argument.
- * When \a b_proc raises an exception, it calls \a r_proc with \a data2 and
- * the exception object if the exception is a kind of one of the given
- * exception classes.
- *
- * \return the return value of \a b_proc if no exception occurs,
- * or the return value of \a r_proc if otherwise.
- * \sa rb_rescue
- * \sa rb_ensure
- * \sa rb_protect
- * \ingroup exception
- */
VALUE
rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...)
@@ -1002,10 +904,6 @@ rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
return ret;
}
-/*!
- * \copydoc rb_rescue2
- * \param[in] args exception classes, terminated by (VALUE)0.
- */
VALUE
rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
VALUE (* r_proc) (VALUE, VALUE), VALUE data2,
@@ -1020,91 +918,60 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
retry_entry:
- result = (*b_proc) (data1);
+ result = (*b_proc) (data1);
}
else if (result) {
- /* escape from r_proc */
- if (state == TAG_RETRY) {
- state = TAG_NONE;
- ec->errinfo = Qnil;
- result = Qfalse;
- goto retry_entry;
- }
+ /* escape from r_proc */
+ if (state == TAG_RETRY) {
+ state = TAG_NONE;
+ ec->errinfo = Qnil;
+ result = Qfalse;
+ goto retry_entry;
+ }
}
else {
- rb_vm_rewind_cfp(ec, cfp);
-
- if (state == TAG_RAISE) {
- int handle = FALSE;
- VALUE eclass;
- va_list ap;
-
- 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) {
- state = TAG_NONE;
- if (r_proc) {
- result = (*r_proc) (data2, ec->errinfo);
- }
- ec->errinfo = e_info;
- }
- }
+ rb_vm_rewind_cfp(ec, cfp);
+
+ if (state == TAG_RAISE) {
+ int handle = FALSE;
+ VALUE eclass;
+ va_list ap;
+
+ 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) {
+ state = TAG_NONE;
+ if (r_proc) {
+ result = (*r_proc) (data2, ec->errinfo);
+ }
+ ec->errinfo = e_info;
+ }
+ }
}
EC_POP_TAG();
if (state)
- EC_JUMP_TAG(ec, state);
+ EC_JUMP_TAG(ec, state);
return result;
}
-/*! An equivalent of \c rescue clause.
- *
- * Equivalent to <code>begin .. rescue .. end</code>.
- *
- * It is the same as
- * \code{cpp}
- * rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0);
- * \endcode
- *
- * \sa rb_rescue2
- * \sa rb_ensure
- * \sa rb_protect
- * \ingroup exception
- */
VALUE
rb_rescue(VALUE (* b_proc)(VALUE), VALUE data1,
VALUE (* r_proc)(VALUE, VALUE), VALUE data2)
{
return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
- (VALUE)0);
+ (VALUE)0);
}
-/*! Protects a function call from potential global escapes from the function.
- *
- * Such global escapes include exceptions, \c Kernel\#throw, \c break in
- * an iterator, for example.
- * It first calls the function func with arg as the argument.
- * If no exception occurred during func, it returns the result of func and
- * *state is zero.
- * Otherwise, it returns Qnil and sets *state to nonzero.
- * If state is NULL, it is not set in both cases.
- *
- * You have to clear the error info with rb_set_errinfo(Qnil) when
- * ignoring the caught exception.
- * \ingroup exception
- * \sa rb_rescue
- * \sa rb_rescue2
- * \sa rb_ensure
- */
VALUE
rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
{
@@ -1115,10 +982,10 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- SAVE_ROOT_JMPBUF(rb_ec_thread_ptr(ec), result = (*proc) (data));
+ SAVE_ROOT_JMPBUF(rb_ec_thread_ptr(ec), result = (*proc) (data));
}
else {
- rb_vm_rewind_cfp(ec, cfp);
+ rb_vm_rewind_cfp(ec, cfp);
}
EC_POP_TAG();
@@ -1126,20 +993,6 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
return result;
}
-/*!
- * An equivalent to \c ensure clause.
- *
- * Equivalent to <code>begin .. ensure .. end</code>.
- *
- * Calls the function \a b_proc with \a data1 as the argument,
- * then calls \a e_proc with \a data2 when execution terminated.
- * \return The return value of \a b_proc if no exception occurred,
- * or \c Qnil if otherwise.
- * \sa rb_rescue
- * \sa rb_rescue2
- * \sa rb_protect
- * \ingroup exception
- */
VALUE
rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
{
@@ -1155,18 +1008,18 @@ rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE dat
ec->ensure_list = &ensure_list;
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- result = (*b_proc) (data1);
+ result = (*b_proc) (data1);
}
EC_POP_TAG();
errinfo = ec->errinfo;
if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) {
- ec->errinfo = Qnil;
+ ec->errinfo = Qnil;
}
ec->ensure_list=ensure_list.next;
(*ensure_list.entry.e_proc)(ensure_list.entry.data2);
ec->errinfo = errinfo;
if (state)
- EC_JUMP_TAG(ec, state);
+ EC_JUMP_TAG(ec, state);
return result;
}
@@ -1176,10 +1029,10 @@ frame_func_id(const rb_control_frame_t *cfp)
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
if (me) {
- return me->def->original_id;
+ return me->def->original_id;
}
else {
- return 0;
+ return 0;
}
}
@@ -1189,42 +1042,19 @@ frame_called_id(rb_control_frame_t *cfp)
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
if (me) {
- return me->called_id;
+ return me->called_id;
}
else {
- return 0;
+ return 0;
}
}
-/*!
- * The original name of the current method.
- *
- * The function returns the original name of the method even if
- * an alias of the method is called.
- * The function can also return 0 if it is not in a method. This
- * case can happen in a toplevel of a source file, for example.
- *
- * \returns the ID of the name or 0
- * \sa rb_frame_callee
- * \ingroup defmethod
- */
ID
rb_frame_this_func(void)
{
return frame_func_id(GET_EC()->cfp);
}
-/*!
- * The name of the current method.
- *
- * The function returns the alias if an alias of the method is called.
- * The function can also return 0 if it is not in a method. This
- * case can happen in a toplevel of a source file, for example.
- *
- * \returns the ID of the name or 0.
- * \sa rb_frame_this_func
- * \ingroup defmethod
- */
ID
rb_frame_callee(void)
{
@@ -1272,8 +1102,8 @@ rb_frame_last_func(void)
ID mid;
while (!(mid = frame_func_id(cfp)) &&
- (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
- !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)));
+ (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp),
+ !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)));
return mid;
}
@@ -1293,7 +1123,7 @@ static VALUE
rb_mod_append_features(VALUE module, VALUE include)
{
if (!CLASS_OR_MODULE_P(include)) {
- Check_Type(include, T_CLASS);
+ Check_Type(include, T_CLASS);
}
rb_include_module(include, module);
@@ -1316,12 +1146,20 @@ rb_mod_include(int argc, VALUE *argv, VALUE module)
CONST_ID(id_append_features, "append_features");
CONST_ID(id_included, "included");
+ if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
+ rb_raise(rb_eTypeError, "Refinement#include has been removed");
+ }
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
- for (i = 0; i < argc; i++)
- Check_Type(argv[i], T_MODULE);
+ for (i = 0; i < argc; i++) {
+ Check_Type(argv[i], T_MODULE);
+ if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
+ rb_raise(rb_eTypeError, "Cannot include refinement");
+ }
+ }
while (argc--) {
- rb_funcall(argv[argc], id_append_features, 1, module);
- rb_funcall(argv[argc], id_included, 1, module);
+ rb_funcall(argv[argc], id_append_features, 1, module);
+ rb_funcall(argv[argc], id_included, 1, module);
}
return module;
}
@@ -1342,7 +1180,7 @@ static VALUE
rb_mod_prepend_features(VALUE module, VALUE prepend)
{
if (!CLASS_OR_MODULE_P(prepend)) {
- Check_Type(prepend, T_CLASS);
+ Check_Type(prepend, T_CLASS);
}
rb_prepend_module(prepend, module);
@@ -1362,15 +1200,23 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module)
int i;
ID id_prepend_features, id_prepended;
+ if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
+ rb_raise(rb_eTypeError, "Refinement#prepend has been removed");
+ }
+
CONST_ID(id_prepend_features, "prepend_features");
CONST_ID(id_prepended, "prepended");
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
- for (i = 0; i < argc; i++)
- Check_Type(argv[i], T_MODULE);
+ for (i = 0; i < argc; i++) {
+ Check_Type(argv[i], T_MODULE);
+ if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
+ rb_raise(rb_eTypeError, "Cannot prepend refinement");
+ }
+ }
while (argc--) {
- rb_funcall(argv[argc], id_prepend_features, 1, module);
- rb_funcall(argv[argc], id_prepended, 1, module);
+ rb_funcall(argv[argc], id_prepend_features, 1, module);
+ rb_funcall(argv[argc], id_prepended, 1, module);
}
return module;
}
@@ -1379,9 +1225,9 @@ static void
ensure_class_or_module(VALUE obj)
{
if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
- rb_raise(rb_eTypeError,
- "wrong argument type %"PRIsVALUE" (expected Class or Module)",
- rb_obj_class(obj));
+ rb_raise(rb_eTypeError,
+ "wrong argument type %"PRIsVALUE" (expected Class or Module)",
+ rb_obj_class(obj));
}
}
@@ -1398,11 +1244,11 @@ static VALUE
refinement_superclass(VALUE superclass)
{
if (RB_TYPE_P(superclass, T_MODULE)) {
- /* FIXME: Should ancestors of superclass be used here? */
+ /* FIXME: Should ancestors of superclass be used here? */
return rb_include_class_new(RCLASS_ORIGIN(superclass), rb_cBasicObject);
}
else {
- return superclass;
+ return superclass;
}
}
@@ -1417,25 +1263,24 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
ensure_class_or_module(klass);
Check_Type(module, T_MODULE);
if (NIL_P(CREF_REFINEMENTS(cref))) {
- CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
+ CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
}
else {
- if (CREF_OMOD_SHARED(cref)) {
- CREF_REFINEMENTS_SET(cref, rb_hash_dup(CREF_REFINEMENTS(cref)));
- CREF_OMOD_SHARED_UNSET(cref);
- }
- if (!NIL_P(c = rb_hash_lookup(CREF_REFINEMENTS(cref), klass))) {
- superclass = c;
- while (c && RB_TYPE_P(c, T_ICLASS)) {
- if (RBASIC(c)->klass == module) {
- /* already used refinement */
- return;
- }
- c = RCLASS_SUPER(c);
- }
- }
- }
- FL_SET(module, RMODULE_IS_OVERLAID);
+ if (CREF_OMOD_SHARED(cref)) {
+ CREF_REFINEMENTS_SET(cref, rb_hash_dup(CREF_REFINEMENTS(cref)));
+ CREF_OMOD_SHARED_UNSET(cref);
+ }
+ if (!NIL_P(c = rb_hash_lookup(CREF_REFINEMENTS(cref), klass))) {
+ superclass = c;
+ while (c && RB_TYPE_P(c, T_ICLASS)) {
+ if (RBASIC(c)->klass == module) {
+ /* already used refinement */
+ return;
+ }
+ c = RCLASS_SUPER(c);
+ }
+ }
+ }
superclass = refinement_superclass(superclass);
c = iclass = rb_include_class_new(module, superclass);
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
@@ -1444,8 +1289,7 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
module = RCLASS_SUPER(module);
while (module && module != klass) {
- FL_SET(module, RMODULE_IS_OVERLAID);
- c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
+ c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
module = RCLASS_SUPER(module);
}
@@ -1469,21 +1313,21 @@ using_module_recursive(const rb_cref_t *cref, VALUE klass)
super = RCLASS_SUPER(klass);
if (super) {
- using_module_recursive(cref, super);
+ using_module_recursive(cref, super);
}
switch (BUILTIN_TYPE(klass)) {
case T_MODULE:
- module = klass;
- break;
+ module = klass;
+ break;
case T_ICLASS:
- module = RBASIC(klass)->klass;
- break;
+ module = RBASIC(klass)->klass;
+ break;
default:
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)",
- rb_obj_classname(klass));
- break;
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)",
+ rb_obj_classname(klass));
+ break;
}
CONST_ID(id_refinements, "__refinements__");
refinements = rb_attr_get(module, id_refinements);
@@ -1502,7 +1346,12 @@ rb_using_module(const rb_cref_t *cref, VALUE module)
rb_clear_method_cache_all();
}
-/*! \private */
+/*
+ * call-seq:
+ * refined_class -> class
+ *
+ * Return the class refined by the receiver.
+ */
VALUE
rb_refinement_module_get_refined_class(VALUE module)
{
@@ -1514,30 +1363,28 @@ rb_refinement_module_get_refined_class(VALUE module)
static void
add_activated_refinement(VALUE activated_refinements,
- VALUE klass, VALUE refinement)
+ VALUE klass, VALUE refinement)
{
VALUE iclass, c, superclass = klass;
if (!NIL_P(c = rb_hash_lookup(activated_refinements, klass))) {
- superclass = c;
- while (c && RB_TYPE_P(c, T_ICLASS)) {
- if (RBASIC(c)->klass == refinement) {
- /* already used refinement */
- return;
- }
- c = RCLASS_SUPER(c);
- }
- }
- FL_SET(refinement, RMODULE_IS_OVERLAID);
+ superclass = c;
+ while (c && RB_TYPE_P(c, T_ICLASS)) {
+ if (RBASIC(c)->klass == refinement) {
+ /* already used refinement */
+ return;
+ }
+ c = RCLASS_SUPER(c);
+ }
+ }
superclass = refinement_superclass(superclass);
c = iclass = rb_include_class_new(refinement, superclass);
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
refinement = RCLASS_SUPER(refinement);
while (refinement && refinement != klass) {
- FL_SET(refinement, RMODULE_IS_OVERLAID);
- c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
+ c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
- refinement = RCLASS_SUPER(refinement);
+ refinement = RCLASS_SUPER(refinement);
}
rb_hash_aset(activated_refinements, klass, iclass);
}
@@ -1562,38 +1409,39 @@ rb_mod_refine(VALUE module, VALUE klass)
VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp);
if (block_handler == VM_BLOCK_HANDLER_NONE) {
- rb_raise(rb_eArgError, "no block given");
+ rb_raise(rb_eArgError, "no block given");
}
if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
- rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
+ rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
}
ensure_class_or_module(klass);
CONST_ID(id_refinements, "__refinements__");
refinements = rb_attr_get(module, id_refinements);
if (NIL_P(refinements)) {
- refinements = hidden_identity_hash_new();
- rb_ivar_set(module, id_refinements, refinements);
+ refinements = hidden_identity_hash_new();
+ rb_ivar_set(module, id_refinements, refinements);
}
CONST_ID(id_activated_refinements, "__activated_refinements__");
activated_refinements = rb_attr_get(module, id_activated_refinements);
if (NIL_P(activated_refinements)) {
- activated_refinements = hidden_identity_hash_new();
- rb_ivar_set(module, id_activated_refinements,
- activated_refinements);
+ activated_refinements = hidden_identity_hash_new();
+ rb_ivar_set(module, id_activated_refinements,
+ activated_refinements);
}
refinement = rb_hash_lookup(refinements, klass);
if (NIL_P(refinement)) {
- VALUE superclass = refinement_superclass(klass);
- refinement = rb_module_new();
- RCLASS_SET_SUPER(refinement, superclass);
- FL_SET(refinement, RMODULE_IS_REFINEMENT);
- CONST_ID(id_refined_class, "__refined_class__");
- rb_ivar_set(refinement, id_refined_class, klass);
- CONST_ID(id_defined_at, "__defined_at__");
- rb_ivar_set(refinement, id_defined_at, module);
- rb_hash_aset(refinements, klass, refinement);
- add_activated_refinement(activated_refinements, klass, refinement);
+ VALUE superclass = refinement_superclass(klass);
+ refinement = rb_refinement_new();
+ RCLASS_SET_SUPER(refinement, superclass);
+ RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE);
+ FL_SET(refinement, RMODULE_IS_REFINEMENT);
+ CONST_ID(id_refined_class, "__refined_class__");
+ rb_ivar_set(refinement, id_refined_class, klass);
+ CONST_ID(id_defined_at, "__defined_at__");
+ rb_ivar_set(refinement, id_defined_at, module);
+ rb_hash_aset(refinements, klass, refinement);
+ add_activated_refinement(activated_refinements, klass, refinement);
}
rb_yield_refine_block(refinement, activated_refinements);
return refinement;
@@ -1605,7 +1453,7 @@ ignored_block(VALUE module, const char *klass)
const char *anon = "";
Check_Type(module, T_MODULE);
if (!RTEST(rb_search_class_path(module))) {
- anon = ", maybe for Module.new";
+ anon = ", maybe for Module.new";
}
rb_warn("%s""using doesn't call the given block""%s.", klass, anon);
}
@@ -1624,27 +1472,62 @@ mod_using(VALUE self, VALUE module)
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
if (prev_frame_func()) {
- rb_raise(rb_eRuntimeError,
- "Module#using is not permitted in methods");
+ rb_raise(rb_eRuntimeError,
+ "Module#using is not permitted in methods");
}
if (prev_cfp && prev_cfp->self != self) {
- rb_raise(rb_eRuntimeError, "Module#using is not called on self");
+ rb_raise(rb_eRuntimeError, "Module#using is not called on self");
}
if (rb_block_given_p()) {
- ignored_block(module, "Module#");
+ ignored_block(module, "Module#");
}
rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
return self;
}
+
+/*
+ * call-seq:
+ * refinements -> array
+ *
+ * Returns an array of modules defined within the receiver.
+ *
+ * module A
+ * refine Integer do
+ * end
+ *
+ * refine String do
+ * end
+ * end
+ *
+ * p A.refinements
+ *
+ * <em>produces:</em>
+ *
+ * [#<refinement:Integer@A>, #<refinement:String@A>]
+ */
+static VALUE
+mod_refinements(VALUE self)
+{
+ ID id_refinements;
+ VALUE refinements;
+
+ CONST_ID(id_refinements, "__refinements__");
+ refinements = rb_attr_get(self, id_refinements);
+ if (NIL_P(refinements)) {
+ return rb_ary_new();
+ }
+ return rb_hash_values(refinements);
+}
+
static int
used_modules_i(VALUE _, VALUE mod, VALUE ary)
{
ID id_defined_at;
CONST_ID(id_defined_at, "__defined_at__");
- while (FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
- rb_ary_push(ary, rb_attr_get(rb_class_of(mod), id_defined_at));
- mod = RCLASS_SUPER(mod);
+ while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
+ rb_ary_push(ary, rb_attr_get(rb_class_of(mod), id_defined_at));
+ mod = RCLASS_SUPER(mod);
}
return ST_CONTINUE;
}
@@ -1681,25 +1564,118 @@ rb_mod_s_used_modules(VALUE _)
VALUE ary = rb_ary_new();
while (cref) {
- if (!NIL_P(CREF_REFINEMENTS(cref))) {
- rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary);
- }
- cref = CREF_NEXT(cref);
+ if (!NIL_P(CREF_REFINEMENTS(cref))) {
+ rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary);
+ }
+ cref = CREF_NEXT(cref);
}
return rb_funcall(ary, rb_intern("uniq"), 0);
}
-/*!
- * Calls \c #initialize method of \a obj with the given arguments.
+static int
+used_refinements_i(VALUE _, VALUE mod, VALUE ary)
+{
+ while (BUILTIN_TYPE(rb_class_of(mod)) == T_MODULE && FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
+ rb_ary_push(ary, rb_class_of(mod));
+ mod = RCLASS_SUPER(mod);
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * used_refinements -> array
+ *
+ * Returns an array of all modules used in the current scope. The ordering
+ * of modules in the resulting array is not defined.
+ *
+ * module A
+ * refine Object do
+ * end
+ * end
+ *
+ * module B
+ * refine Object do
+ * end
+ * end
+ *
+ * using A
+ * using B
+ * p Module.used_refinements
*
- * It also forwards the given block to \c #initialize if given.
+ * <em>produces:</em>
*
- * \param[in] obj the receiver object
- * \param[in] argc the number of arguments
- * \param[in] argv a pointer to the array of arguments
- * \ingroup object
+ * [#<refinement:Object@B>, #<refinement:Object@A>]
*/
+static VALUE
+rb_mod_s_used_refinements(VALUE _)
+{
+ const rb_cref_t *cref = rb_vm_cref();
+ VALUE ary = rb_ary_new();
+
+ while (cref) {
+ if (!NIL_P(CREF_REFINEMENTS(cref))) {
+ rb_hash_foreach(CREF_REFINEMENTS(cref), used_refinements_i, ary);
+ }
+ cref = CREF_NEXT(cref);
+ }
+
+ return ary;
+}
+
+struct refinement_import_methods_arg {
+ rb_cref_t *cref;
+ VALUE refinement;
+ VALUE module;
+};
+
+/* vm.c */
+rb_cref_t *rb_vm_cref_dup_without_refinements(const rb_cref_t *cref);
+
+static enum rb_id_table_iterator_result
+refinement_import_methods_i(ID key, VALUE value, void *data)
+{
+ const rb_method_entry_t *me = (const rb_method_entry_t *)value;
+ struct refinement_import_methods_arg *arg = (struct refinement_import_methods_arg *)data;
+
+ if (me->def->type != VM_METHOD_TYPE_ISEQ) {
+ rb_raise(rb_eArgError, "Can't import method which is not defined with Ruby code: %"PRIsVALUE"#%"PRIsVALUE, rb_class_path(arg->module), rb_id2str(key));
+ }
+ rb_cref_t *new_cref = rb_vm_cref_dup_without_refinements(me->def->body.iseq.cref);
+ CREF_REFINEMENTS_SET(new_cref, CREF_REFINEMENTS(arg->cref));
+ rb_add_method_iseq(arg->refinement, key, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
+ return ID_TABLE_CONTINUE;
+}
+
+/*
+ * Note: docs for the method are in class.c
+ */
+
+static VALUE
+refinement_import_methods(int argc, VALUE *argv, VALUE refinement)
+{
+ int i;
+ struct refinement_import_methods_arg arg;
+
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
+ for (i = 0; i < argc; i++) {
+ Check_Type(argv[i], T_MODULE);
+ if (RCLASS_SUPER(argv[i])) {
+ rb_warn("%"PRIsVALUE" has ancestors, but Refinement#import_methods doesn't import their methods", rb_class_path(argv[i]));
+ }
+ }
+ arg.cref = rb_vm_cref_replace_with_duplicated_cref();
+ arg.refinement = refinement;
+ for (i = 0; i < argc; i++) {
+ arg.module = argv[i];
+ struct rb_id_table *m_tbl = RCLASS_M_TBL(argv[i]);
+ if (!m_tbl) continue;
+ rb_id_table_foreach(m_tbl, refinement_import_methods_i, &arg);
+ }
+ return refinement;
+}
+
void
rb_obj_call_init(VALUE obj, int argc, const VALUE *argv)
{
@@ -1713,12 +1689,6 @@ rb_obj_call_init_kw(VALUE obj, int argc, const VALUE *argv, int kw_splat)
rb_funcallv_kw(obj, idInitialize, argc, argv, kw_splat);
}
-/*!
- * Extend the object with the module.
- *
- * Same as \c Module\#extend_object.
- * \ingroup class
- */
void
rb_extend_object(VALUE obj, VALUE module)
{
@@ -1794,15 +1764,29 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj)
CONST_ID(id_extended, "extended");
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
- for (i = 0; i < argc; i++)
- Check_Type(argv[i], T_MODULE);
+ for (i = 0; i < argc; i++) {
+ Check_Type(argv[i], T_MODULE);
+ if (FL_TEST(argv[i], RMODULE_IS_REFINEMENT)) {
+ rb_raise(rb_eTypeError, "Cannot extend object with refinement");
+ }
+ }
while (argc--) {
- rb_funcall(argv[argc], id_extend_object, 1, obj);
- rb_funcall(argv[argc], id_extended, 1, obj);
+ rb_funcall(argv[argc], id_extend_object, 1, obj);
+ rb_funcall(argv[argc], id_extended, 1, obj);
}
return obj;
}
+VALUE
+rb_top_main_class(const char *method)
+{
+ VALUE klass = GET_THREAD()->top_wrapper;
+
+ if (!klass) return rb_cObject;
+ rb_warning("main.%s in the wrapped load is effective only in wrapper module", method);
+ return klass;
+}
+
/*
* call-seq:
* include(module, ...) -> self
@@ -1815,13 +1799,7 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj)
static VALUE
top_include(int argc, VALUE *argv, VALUE self)
{
- rb_thread_t *th = GET_THREAD();
-
- if (th->top_wrapper) {
- rb_warning("main.include in the wrapped load is effective only in wrapper module");
- return rb_mod_include(argc, argv, th->top_wrapper);
- }
- return rb_mod_include(argc, argv, rb_cObject);
+ return rb_mod_include(argc, argv, rb_top_main_class("include"));
}
/*
@@ -1835,14 +1813,16 @@ top_include(int argc, VALUE *argv, VALUE self)
static VALUE
top_using(VALUE self, VALUE module)
{
- const rb_cref_t *cref = rb_vm_cref();
+ const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());;
rb_control_frame_t *prev_cfp = previous_frame(GET_EC());
+ rb_thread_t *th = GET_THREAD();
- if (CREF_NEXT(cref) || (prev_cfp && rb_vm_frame_method_entry(prev_cfp))) {
- rb_raise(rb_eRuntimeError, "main.using is permitted only at toplevel");
+ if ((th->top_wrapper ? CREF_NEXT(cref) : cref) ||
+ (prev_cfp && rb_vm_frame_method_entry(prev_cfp))) {
+ rb_raise(rb_eRuntimeError, "main.using is permitted only at toplevel");
}
if (rb_block_given_p()) {
- ignored_block(module, "main.");
+ ignored_block(module, "main.");
}
rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
return self;
@@ -1855,17 +1835,17 @@ errinfo_place(const rb_execution_context_t *ec)
const rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
- if (VM_FRAME_RUBYFRAME_P(cfp)) {
- if (cfp->iseq->body->type == ISEQ_TYPE_RESCUE) {
- return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
- }
- else if (cfp->iseq->body->type == ISEQ_TYPE_ENSURE &&
- !THROW_DATA_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR]) &&
- !FIXNUM_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR])) {
- return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
- }
- }
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ if (VM_FRAME_RUBYFRAME_P(cfp)) {
+ if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE) {
+ return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
+ }
+ else if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_ENSURE &&
+ !THROW_DATA_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR]) &&
+ !FIXNUM_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR])) {
+ return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
+ }
+ }
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
return 0;
}
@@ -1875,10 +1855,10 @@ rb_ec_get_errinfo(const rb_execution_context_t *ec)
{
const VALUE *ptr = errinfo_place(ec);
if (ptr) {
- return *ptr;
+ return *ptr;
}
else {
- return ec->errinfo;
+ return ec->errinfo;
}
}
@@ -1894,31 +1874,17 @@ errinfo_getter(ID id, VALUE *_)
return get_errinfo();
}
-/*! The current exception in the current thread.
- *
- * Same as \c $! in Ruby.
- * \return the current exception or \c Qnil
- * \ingroup exception
- */
VALUE
rb_errinfo(void)
{
return GET_EC()->errinfo;
}
-/*! Sets the current exception (\c $!) to the given value
- *
- * \param[in] err an \c Exception object or \c Qnil.
- * \exception TypeError if \a err is neither an exception nor \c nil.
- * \note this function does not raise the exception.
- * Use \c rb_raise() when you want to raise.
- * \ingroup exception
- */
void
rb_set_errinfo(VALUE err)
{
if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
- rb_raise(rb_eTypeError, "assigning non-exception to $!");
+ rb_raise(rb_eTypeError, "assigning non-exception to $!");
}
GET_EC()->errinfo = err;
}
@@ -1928,10 +1894,10 @@ errat_getter(ID id, VALUE *_)
{
VALUE err = get_errinfo();
if (!NIL_P(err)) {
- return rb_get_backtrace(err);
+ return rb_get_backtrace(err);
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -1940,7 +1906,7 @@ errat_setter(VALUE val, ID id, VALUE *var)
{
VALUE err = get_errinfo();
if (NIL_P(err)) {
- rb_raise(rb_eArgError, "$! not set");
+ rb_raise(rb_eArgError, "$! not set");
}
set_backtrace(err, val);
}
@@ -1961,10 +1927,10 @@ rb_f_method_name(VALUE _)
ID fname = prev_frame_func(); /* need *method* ID */
if (fname) {
- return ID2SYM(fname);
+ return ID2SYM(fname);
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -1983,10 +1949,10 @@ rb_f_callee_name(VALUE _)
ID fname = prev_frame_callee(); /* need *callee* ID */
if (fname) {
- return ID2SYM(fname);
+ return ID2SYM(fname);
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -2005,7 +1971,7 @@ f_current_dirname(VALUE _)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
- return Qnil;
+ return Qnil;
}
base = rb_file_dirname(base);
return base;
@@ -2100,9 +2066,17 @@ Init_eval(void)
rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
rb_define_private_method(rb_cModule, "using", mod_using, 1);
+ rb_define_method(rb_cModule, "refinements", mod_refinements, 0);
rb_define_singleton_method(rb_cModule, "used_modules",
- rb_mod_s_used_modules, 0);
+ rb_mod_s_used_modules, 0);
+ rb_define_singleton_method(rb_cModule, "used_refinements",
+ rb_mod_s_used_refinements, 0);
rb_undef_method(rb_cClass, "refine");
+ rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1);
+ rb_define_method(rb_cRefinement, "refined_class", rb_refinement_module_get_refined_class, 0);
+ rb_undef_method(rb_cRefinement, "append_features");
+ rb_undef_method(rb_cRefinement, "prepend_features");
+ rb_undef_method(rb_cRefinement, "extend_object");
rb_undef_method(rb_cClass, "module_function");
@@ -2113,9 +2087,9 @@ Init_eval(void)
rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
- "include", top_include, -1);
+ "include", top_include, -1);
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
- "using", top_using, 1);
+ "using", top_using, 1);
rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
diff --git a/eval_error.c b/eval_error.c
index 98b8a22485..9806683000 100644
--- a/eval_error.c
+++ b/eval_error.c
@@ -10,8 +10,8 @@
#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
#define warn_print(x) RB_GNUC_EXTENSION_BLOCK( \
(__builtin_constant_p(x)) ? \
- rb_write_error2((x), (long)strlen(x)) : \
- rb_write_error(x) \
+ rb_write_error2((x), (long)strlen(x)) : \
+ rb_write_error(x) \
)
#else
#define warn_print(x) rb_write_error(x)
@@ -29,7 +29,7 @@ error_pos(const VALUE str)
{
VALUE pos = error_pos_str();
if (!NIL_P(pos)) {
- write_warn_str(str, pos);
+ write_warn_str(str, pos);
}
}
@@ -40,18 +40,18 @@ error_pos_str(void)
VALUE sourcefile = rb_source_location(&sourceline);
if (!NIL_P(sourcefile)) {
- ID caller_name;
- if (sourceline == 0) {
- return rb_sprintf("%"PRIsVALUE": ", sourcefile);
- }
- else if ((caller_name = rb_frame_callee()) != 0) {
- return rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"': ",
- sourcefile, sourceline,
- rb_id2str(caller_name));
- }
- else {
- return rb_sprintf("%"PRIsVALUE":%d: ", sourcefile, sourceline);
- }
+ ID caller_name;
+ if (sourceline == 0) {
+ return rb_sprintf("%"PRIsVALUE": ", sourcefile);
+ }
+ else if ((caller_name = rb_frame_callee()) != 0) {
+ return rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"': ",
+ sourcefile, sourceline,
+ rb_id2str(caller_name));
+ }
+ else {
+ return rb_sprintf("%"PRIsVALUE":%d: ", sourcefile, sourceline);
+ }
}
return Qnil;
}
@@ -62,62 +62,15 @@ set_backtrace(VALUE info, VALUE bt)
ID set_backtrace = rb_intern("set_backtrace");
if (rb_backtrace_p(bt)) {
- if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
- rb_exc_set_backtrace(info, bt);
- return;
- }
- else {
- bt = rb_backtrace_to_str_ary(bt);
- }
- }
- rb_check_funcall(info, set_backtrace, 1, &bt);
-}
-
-static void
-error_print(rb_execution_context_t *ec)
-{
- rb_ec_error_print(ec, ec->errinfo);
-}
-
-static void
-write_warnq(VALUE out, VALUE str, const char *ptr, long len)
-{
- if (NIL_P(out)) {
- const char *beg = ptr;
- const long olen = len;
- for (; len > 0; --len, ++ptr) {
- unsigned char c = *ptr;
- switch (c) {
- case '\n': case '\t': continue;
- }
- if (rb_iscntrl(c)) {
- char buf[5];
- const char *cc = 0;
- if (ptr > beg) rb_write_error2(beg, ptr - beg);
- beg = ptr + 1;
- cc = ruby_escaped_char(c);
- if (cc) {
- rb_write_error2(cc, strlen(cc));
- }
- else {
- rb_write_error2(buf, snprintf(buf, sizeof(buf), "\\x%02X", c));
- }
- }
- else if (c == '\\') {
- rb_write_error2(beg, ptr - beg + 1);
- beg = ptr;
- }
+ if (rb_method_basic_definition_p(CLASS_OF(info), set_backtrace)) {
+ rb_exc_set_backtrace(info, bt);
+ return;
}
- if (ptr > beg) {
- if (beg == RSTRING_PTR(str) && olen == RSTRING_LEN(str))
- rb_write_error_str(str);
- else
- rb_write_error2(beg, ptr - beg);
+ else {
+ bt = rb_backtrace_to_str_ary(bt);
}
}
- else {
- rb_str_cat(out, ptr, len);
- }
+ rb_check_funcall(info, set_backtrace, 1, &bt);
}
#define CSI_BEGIN "\033["
@@ -130,114 +83,141 @@ static const char reset[] = CSI_BEGIN""CSI_SGR;
static void
print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VALUE str, int highlight)
{
- const char *einfo = "";
long elen = 0;
VALUE mesg;
- if (emesg != Qundef) {
- if (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
- NIL_P(mesg = RARRAY_AREF(errat, 0))) {
- error_pos(str);
- }
- else {
- write_warn_str(str, mesg);
- write_warn(str, ": ");
- }
-
- if (!NIL_P(emesg)) {
- einfo = RSTRING_PTR(emesg);
- elen = RSTRING_LEN(emesg);
- }
+ if (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
+ NIL_P(mesg = RARRAY_AREF(errat, 0))) {
+ error_pos(str);
+ }
+ else {
+ write_warn_str(str, mesg);
+ write_warn(str, ": ");
+ }
+
+ if (!NIL_P(emesg)) {
+ elen = RSTRING_LEN(emesg);
+ }
+
+ if (eclass == rb_eRuntimeError && elen == 0) {
+ if (highlight) write_warn(str, underline);
+ write_warn(str, "unhandled exception");
+ if (highlight) write_warn(str, reset);
+ write_warn2(str, "\n", 1);
+ }
+ else {
+ VALUE epath;
+
+ epath = rb_class_name(eclass);
+ if (elen == 0) {
+ if (highlight) write_warn(str, underline);
+ write_warn_str(str, epath);
+ if (highlight) write_warn(str, reset);
+ write_warn(str, "\n");
+ }
+ else {
+ write_warn_str(str, emesg);
+ write_warn(str, "\n");
+ }
}
+}
+VALUE
+rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
+{
+ const char *einfo = "";
+ long elen = 0;
+
+ VALUE str = rb_str_new2("");
+
+ if (!NIL_P(emesg)) {
+ einfo = RSTRING_PTR(emesg);
+ elen = RSTRING_LEN(emesg);
+ }
if (eclass == rb_eRuntimeError && elen == 0) {
- if (highlight) write_warn(str, underline);
- write_warn(str, "unhandled exception");
- if (highlight) write_warn(str, reset);
- write_warn2(str, "\n", 1);
+ if (highlight) write_warn(str, underline);
+ write_warn(str, "unhandled exception");
+ if (highlight) write_warn(str, reset);
}
else {
- VALUE epath;
-
- epath = rb_class_name(eclass);
- if (elen == 0) {
- if (highlight) write_warn(str, underline);
- write_warn_str(str, epath);
- if (highlight) write_warn(str, reset);
- write_warn(str, "\n");
- }
- else {
+ VALUE epath;
+
+ epath = rb_class_name(eclass);
+ if (elen == 0) {
+ if (highlight) write_warn(str, underline);
+ write_warn_str(str, epath);
+ if (highlight) write_warn(str, reset);
+ }
+ else {
/* emesg is a String instance */
- const char *tail = 0;
+ const char *tail = 0;
if (highlight) write_warn(str, bold);
- if (RSTRING_PTR(epath)[0] == '#')
- epath = 0;
- if ((tail = memchr(einfo, '\n', elen)) != 0) {
- write_warnq(str, emesg, einfo, tail - einfo);
- tail++; /* skip newline */
- }
- else {
- write_warnq(str, emesg, einfo, elen);
- }
- if (epath) {
- write_warn(str, " (");
- if (highlight) write_warn(str, underline);
+ if (RSTRING_PTR(epath)[0] == '#')
+ epath = 0;
+ if ((tail = memchr(einfo, '\n', elen)) != 0) {
+ write_warn2(str, einfo, tail - einfo);
+ tail++; /* skip newline */
+ }
+ else {
+ write_warn_str(str, emesg);
+ }
+ if (epath) {
+ write_warn(str, " (");
+ if (highlight) write_warn(str, underline);
write_warn_str(str, epath);
- if (highlight) {
- write_warn(str, reset);
- write_warn(str, bold);
- }
- write_warn2(str, ")", 1);
- if (highlight) write_warn(str, reset);
- write_warn2(str, "\n", 1);
- }
- if (tail && einfo+elen > tail) {
- if (!highlight) {
- write_warnq(str, emesg, tail, einfo+elen-tail);
- if (einfo[elen-1] != '\n') write_warn2(str, "\n", 1);
- }
- else {
- elen -= tail - einfo;
- einfo = tail;
- while (elen > 0) {
- tail = memchr(einfo, '\n', elen);
- if (!tail || tail > einfo) {
- write_warn(str, bold);
- write_warnq(str, emesg, einfo, tail ? tail-einfo : elen);
- write_warn(str, reset);
- if (!tail) {
- write_warn2(str, "\n", 1);
- break;
- }
- }
- elen -= tail - einfo;
- einfo = tail;
- do ++tail; while (tail < einfo+elen && *tail == '\n');
- write_warnq(str, emesg, einfo, tail-einfo);
- elen -= tail - einfo;
- einfo = tail;
- }
- }
- }
- else if (!epath) {
- write_warn2(str, "\n", 1);
- }
- }
+ if (highlight) {
+ write_warn(str, reset);
+ write_warn(str, bold);
+ }
+ write_warn2(str, ")", 1);
+ if (highlight) write_warn(str, reset);
+ }
+ if (tail && einfo+elen > tail) {
+ if (!highlight) {
+ write_warn2(str, "\n", 1);
+ write_warn2(str, tail, einfo+elen-tail);
+ }
+ else {
+ elen -= tail - einfo;
+ einfo = tail;
+ write_warn2(str, "\n", 1);
+ while (elen > 0) {
+ tail = memchr(einfo, '\n', elen);
+ if (!tail || tail > einfo) {
+ write_warn(str, bold);
+ write_warn2(str, einfo, tail ? tail-einfo : elen);
+ write_warn(str, reset);
+ if (!tail) {
+ break;
+ }
+ }
+ elen -= tail - einfo;
+ einfo = tail;
+ do ++tail; while (tail < einfo+elen && *tail == '\n');
+ write_warn2(str, einfo, tail-einfo);
+ elen -= tail - einfo;
+ einfo = tail;
+ }
+ }
+ }
+ }
}
+
+ return str;
}
static void
print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reverse, long backtrace_limit)
{
if (!NIL_P(errat)) {
- long i;
- long len = RARRAY_LEN(errat);
- const int threshold = 1000000000;
+ long i;
+ long len = RARRAY_LEN(errat);
+ 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);
+ ((len - 1) / threshold) :
+ len - 1)) +
+ (len < threshold ? 0 : 9) + 1);
long skip_start = -1, skip_len = 0;
@@ -258,23 +238,23 @@ print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reve
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;
+ 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));
- }
- }
+ }
+ 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));
+ }
+ }
}
}
-VALUE rb_get_message(VALUE exc);
+VALUE rb_get_detailed_message(VALUE exc, VALUE opt);
static int
shown_cause_p(VALUE cause, VALUE *shown_causes)
@@ -289,98 +269,108 @@ shown_cause_p(VALUE cause, VALUE *shown_causes)
}
static void
-show_cause(VALUE errinfo, VALUE str, VALUE highlight, VALUE reverse, long backtrace_limit, VALUE *shown_causes)
+show_cause(VALUE errinfo, VALUE str, VALUE opt, VALUE highlight, VALUE reverse, long backtrace_limit, VALUE *shown_causes)
{
VALUE cause = rb_attr_get(errinfo, id_cause);
if (!NIL_P(cause) && rb_obj_is_kind_of(cause, rb_eException) &&
!shown_cause_p(cause, shown_causes)) {
volatile VALUE eclass = CLASS_OF(cause);
VALUE errat = rb_get_backtrace(cause);
- VALUE emesg = rb_get_message(cause);
+ VALUE emesg = rb_get_detailed_message(cause, opt);
if (reverse) {
- show_cause(cause, str, highlight, reverse, backtrace_limit, shown_causes);
+ show_cause(cause, str, opt, highlight, reverse, backtrace_limit, shown_causes);
print_backtrace(eclass, errat, str, TRUE, backtrace_limit);
- print_errinfo(eclass, errat, emesg, str, highlight!=0);
+ print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
}
else {
- print_errinfo(eclass, errat, emesg, str, highlight!=0);
+ print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
- show_cause(cause, str, highlight, reverse, backtrace_limit, shown_causes);
+ show_cause(cause, str, opt, highlight, reverse, backtrace_limit, shown_causes);
}
}
}
void
-rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse)
+rb_exc_check_circular_cause(VALUE exc)
+{
+ VALUE cause = exc, shown_causes = 0;
+ do {
+ if (shown_cause_p(cause, &shown_causes)) {
+ rb_raise(rb_eArgError, "circular causes");
+ }
+ } while (!NIL_P(cause = rb_attr_get(cause, id_cause)));
+}
+
+void
+rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VALUE highlight, VALUE reverse)
{
volatile VALUE eclass;
VALUE shown_causes = 0;
long backtrace_limit = rb_backtrace_length_limit;
if (NIL_P(errinfo))
- return;
+ return;
- if (errat == Qundef) {
- errat = Qnil;
+ if (UNDEF_P(errat)) {
+ errat = Qnil;
}
eclass = CLASS_OF(errinfo);
- if (NIL_P(reverse)) reverse = Qfalse;
- if (NIL_P(highlight)) {
- VALUE tty = (VALUE)rb_stderr_tty_p();
- if (NIL_P(highlight)) highlight = tty;
- }
if (reverse) {
- static const char traceback[] = "Traceback "
- "(most recent call last):\n";
- const int bold_part = rb_strlen_lit("Traceback");
- char buff[sizeof(traceback)+sizeof(bold)+sizeof(reset)-2], *p = buff;
- const char *msg = traceback;
- long len = sizeof(traceback) - 1;
- if (highlight) {
+ static const char traceback[] = "Traceback "
+ "(most recent call last):\n";
+ const int bold_part = rb_strlen_lit("Traceback");
+ char buff[sizeof(traceback)+sizeof(bold)+sizeof(reset)-2], *p = buff;
+ const char *msg = traceback;
+ long len = sizeof(traceback) - 1;
+ if (RTEST(highlight)) {
#define APPEND(s, l) (memcpy(p, s, l), p += (l))
- APPEND(bold, sizeof(bold)-1);
- APPEND(traceback, bold_part);
- APPEND(reset, sizeof(reset)-1);
- APPEND(traceback + bold_part, sizeof(traceback)-bold_part-1);
+ APPEND(bold, sizeof(bold)-1);
+ APPEND(traceback, bold_part);
+ APPEND(reset, sizeof(reset)-1);
+ APPEND(traceback + bold_part, sizeof(traceback)-bold_part-1);
#undef APPEND
- len = p - (msg = buff);
- }
- write_warn2(str, msg, len);
- show_cause(errinfo, str, highlight, reverse, backtrace_limit, &shown_causes);
- print_backtrace(eclass, errat, str, TRUE, backtrace_limit);
- print_errinfo(eclass, errat, emesg, str, highlight!=0);
+ len = p - (msg = buff);
+ }
+ write_warn2(str, msg, len);
+ show_cause(errinfo, str, opt, highlight, reverse, backtrace_limit, &shown_causes);
+ print_backtrace(eclass, errat, str, TRUE, backtrace_limit);
+ print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
}
else {
- print_errinfo(eclass, errat, emesg, str, highlight!=0);
- print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
- show_cause(errinfo, str, highlight, reverse, backtrace_limit, &shown_causes);
+ print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
+ print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
+ show_cause(errinfo, str, opt, highlight, reverse, backtrace_limit, &shown_causes);
}
}
-void
-rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo)
+static void
+rb_ec_error_print_detailed(rb_execution_context_t *const ec, const VALUE errinfo, const VALUE str, VALUE emesg0)
{
volatile uint8_t raised_flag = ec->raised_flag;
volatile VALUE errat = Qundef;
- volatile VALUE emesg = Qundef;
volatile bool written = false;
+ volatile VALUE emesg = emesg0;
+
+ VALUE opt = rb_hash_new();
+ VALUE highlight = rb_stderr_tty_p() ? Qtrue : Qfalse;
+ rb_hash_aset(opt, ID2SYM(rb_intern_const("highlight")), highlight);
if (NIL_P(errinfo))
- return;
+ return;
rb_ec_raised_clear(ec);
EC_PUSH_TAG(ec);
if (EC_EXEC_TAG() == TAG_NONE) {
- errat = rb_get_backtrace(errinfo);
+ errat = rb_get_backtrace(errinfo);
}
- if (emesg == Qundef) {
- emesg = Qnil;
- emesg = rb_get_message(errinfo);
+ if (UNDEF_P(emesg)) {
+ emesg = Qnil;
+ emesg = rb_get_detailed_message(errinfo, opt);
}
if (!written) {
written = true;
- rb_error_write(errinfo, emesg, errat, Qnil, Qnil, Qfalse);
+ rb_error_write(errinfo, emesg, errat, str, opt, highlight, Qfalse);
}
EC_POP_TAG();
@@ -388,11 +378,17 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo)
rb_ec_raised_set(ec, raised_flag);
}
+void
+rb_ec_error_print(rb_execution_context_t *volatile ec, volatile VALUE errinfo)
+{
+ rb_ec_error_print_detailed(ec, errinfo, Qnil, Qundef);
+}
+
#define undef_mesg_for(v, k) rb_fstring_lit("undefined"v" method `%1$s' for "k" `%2$s'")
#define undef_mesg(v) ( \
- is_mod ? \
- undef_mesg_for(v, "module") : \
- undef_mesg_for(v, "class"))
+ is_mod ? \
+ undef_mesg_for(v, "module") : \
+ undef_mesg_for(v, "class"))
void
rb_print_undef(VALUE klass, ID id, rb_method_visibility_t visi)
@@ -418,9 +414,9 @@ rb_print_undef_str(VALUE klass, VALUE name)
#define inaccessible_mesg_for(v, k) rb_fstring_lit("method `%1$s' for "k" `%2$s' is "v)
#define inaccessible_mesg(v) ( \
- is_mod ? \
- inaccessible_mesg_for(v, "module") : \
- inaccessible_mesg_for(v, "class"))
+ is_mod ? \
+ inaccessible_mesg_for(v, "module") : \
+ inaccessible_mesg_for(v, "class"))
void
rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi)
@@ -430,8 +426,8 @@ rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi)
switch (visi & METHOD_VISI_MASK) {
case METHOD_VISI_UNDEF:
case METHOD_VISI_PUBLIC: mesg = inaccessible_mesg(""); break;
- case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg(" private"); break;
- case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg(" protected"); break;
+ case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg("private"); break;
+ case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg("protected"); break;
default: UNREACHABLE;
}
rb_name_err_raise_str(mesg, klass, ID2SYM(id));
@@ -444,70 +440,109 @@ sysexit_status(VALUE err)
return NUM2INT(st);
}
+enum {
+ EXITING_WITH_MESSAGE = 1,
+ EXITING_WITH_STATUS = 2,
+ EXITING_WITH_SIGNAL = 4
+};
+static int
+exiting_split(VALUE errinfo, volatile int *exitcode, volatile int *sigstatus)
+{
+ int ex = EXIT_SUCCESS;
+ VALUE signo;
+ int sig = 0;
+ int result = 0;
+
+ if (NIL_P(errinfo)) return 0;
+
+ if (THROW_DATA_P(errinfo)) {
+ int throw_state = ((const struct vm_throw_data *)errinfo)->throw_state;
+ ex = throw_state & VM_THROW_STATE_MASK;
+ result |= EXITING_WITH_STATUS;
+ }
+ else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
+ ex = sysexit_status(errinfo);
+ result |= EXITING_WITH_STATUS;
+ }
+ else if (rb_obj_is_kind_of(errinfo, rb_eSignal)) {
+ signo = rb_ivar_get(errinfo, id_signo);
+ sig = FIX2INT(signo);
+ result |= EXITING_WITH_SIGNAL;
+ /* no message when exiting by signal */
+ if (signo == INT2FIX(SIGSEGV) || !rb_obj_is_instance_of(errinfo, rb_eSignal))
+ /* except for SEGV and subclasses */
+ result |= EXITING_WITH_MESSAGE;
+ }
+ else if (rb_obj_is_kind_of(errinfo, rb_eSystemCallError) &&
+ FIXNUM_P(signo = rb_attr_get(errinfo, id_signo))) {
+ sig = FIX2INT(signo);
+ result |= EXITING_WITH_SIGNAL;
+ /* no message when exiting by error to be mapped to signal */
+ }
+ else {
+ ex = EXIT_FAILURE;
+ result |= EXITING_WITH_STATUS | EXITING_WITH_MESSAGE;
+ }
+
+ if (exitcode && (result & EXITING_WITH_STATUS))
+ *exitcode = ex;
+ if (sigstatus && (result & EXITING_WITH_SIGNAL))
+ *sigstatus = sig;
+
+ return result;
+}
+
#define unknown_longjmp_status(status) \
rb_bug("Unknown longjmp status %d", status)
static int
-error_handle(rb_execution_context_t *ec, int ex)
+error_handle(rb_execution_context_t *ec, VALUE errinfo, enum ruby_tag_type ex)
{
int status = EXIT_FAILURE;
if (rb_ec_set_raised(ec))
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
switch (ex & TAG_MASK) {
case 0:
- status = EXIT_SUCCESS;
- break;
+ status = EXIT_SUCCESS;
+ break;
case TAG_RETURN:
- error_pos(Qnil);
- warn_print("unexpected return\n");
- break;
+ error_pos(Qnil);
+ warn_print("unexpected return\n");
+ break;
case TAG_NEXT:
- error_pos(Qnil);
- warn_print("unexpected next\n");
- break;
+ error_pos(Qnil);
+ warn_print("unexpected next\n");
+ break;
case TAG_BREAK:
- error_pos(Qnil);
- warn_print("unexpected break\n");
- break;
+ error_pos(Qnil);
+ warn_print("unexpected break\n");
+ break;
case TAG_REDO:
- error_pos(Qnil);
- warn_print("unexpected redo\n");
- break;
+ error_pos(Qnil);
+ warn_print("unexpected redo\n");
+ break;
case TAG_RETRY:
- error_pos(Qnil);
- warn_print("retry outside of rescue clause\n");
- break;
+ error_pos(Qnil);
+ warn_print("retry outside of rescue clause\n");
+ break;
case TAG_THROW:
- /* TODO: fix me */
- error_pos(Qnil);
- warn_print("unexpected throw\n");
- break;
- case TAG_RAISE: {
- VALUE errinfo = ec->errinfo;
- if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
- status = sysexit_status(errinfo);
- }
- else if (rb_obj_is_instance_of(errinfo, rb_eSignal) &&
- 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 */
+ /* TODO: fix me */
+ error_pos(Qnil);
+ warn_print("unexpected throw\n");
+ break;
+ case TAG_RAISE:
+ if (!(exiting_split(errinfo, &status, NULL) & EXITING_WITH_MESSAGE)) {
+ break;
}
- else {
- rb_ec_error_print(ec, errinfo);
- }
- break;
- }
+ /* fallthrough */
case TAG_FATAL:
- error_print(ec);
- break;
+ rb_ec_error_print(ec, errinfo);
+ break;
default:
- unknown_longjmp_status(ex);
- break;
+ unknown_longjmp_status(ex);
+ break;
}
rb_ec_reset_raised(ec);
return status;
diff --git a/eval_intern.h b/eval_intern.h
index 58400b5f25..6cbaa51361 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -33,7 +33,11 @@ pass_passed_block_handler(rb_execution_context_t *ec)
#endif
#include <stdio.h>
-#include <setjmp.h>
+#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
+# include "wasm/setjmp.h"
+#else
+# include <setjmp.h>
+#endif
#ifdef __APPLE__
# ifdef HAVE_CRT_EXTERNS_H
@@ -173,11 +177,30 @@ rb_ec_tag_jump(const rb_execution_context_t *ec, enum ruby_tag_type st)
#define CREF_FL_PUSHED_BY_EVAL IMEMO_FL_USER1
#define CREF_FL_OMOD_SHARED IMEMO_FL_USER2
+#define CREF_FL_SINGLETON IMEMO_FL_USER3
+
+static inline int CREF_SINGLETON(const rb_cref_t *cref);
static inline VALUE
CREF_CLASS(const rb_cref_t *cref)
{
- return cref->klass;
+ if (CREF_SINGLETON(cref)) {
+ return CLASS_OF(cref->klass_or_self);
+ }
+ else {
+ return cref->klass_or_self;
+ }
+}
+
+static inline VALUE
+CREF_CLASS_FOR_DEFINITION(const rb_cref_t *cref)
+{
+ if (CREF_SINGLETON(cref)) {
+ return rb_singleton_class(cref->klass_or_self);
+ }
+ else {
+ return cref->klass_or_self;
+ }
}
static inline rb_cref_t *
@@ -217,6 +240,18 @@ CREF_PUSHED_BY_EVAL_SET(rb_cref_t *cref)
}
static inline int
+CREF_SINGLETON(const rb_cref_t *cref)
+{
+ return cref->flags & CREF_FL_SINGLETON;
+}
+
+static inline void
+CREF_SINGLETON_SET(rb_cref_t *cref)
+{
+ cref->flags |= CREF_FL_SINGLETON;
+}
+
+static inline int
CREF_OMOD_SHARED(const rb_cref_t *cref)
{
return cref->flags & CREF_FL_OMOD_SHARED;
@@ -252,7 +287,7 @@ VALUE rb_make_exception(int argc, const VALUE *argv);
NORETURN(void rb_method_name_error(VALUE, VALUE));
-void rb_fiber_start(rb_fiber_t*);
+NORETURN(void rb_fiber_start(rb_fiber_t*));
NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t));
NORETURN(void rb_print_undef_str(VALUE, VALUE));
@@ -294,9 +329,9 @@ static inline void
translit_char(char *p, int from, int to)
{
while (*p) {
- if ((unsigned char)*p == from)
- *p = to;
- p = CharNext(p);
+ if ((unsigned char)*p == from)
+ *p = to;
+ p = CharNext(p);
}
}
#endif
diff --git a/eval_jump.c b/eval_jump.c
index 2ea73b0da3..e8e74f4e70 100644
--- a/eval_jump.c
+++ b/eval_jump.c
@@ -40,7 +40,7 @@ rb_f_at_exit(VALUE _)
VALUE proc;
if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "called without a block");
+ rb_raise(rb_eArgError, "called without a block");
}
proc = rb_block_proc();
rb_set_end_proc(rb_call_end_proc, proc);
@@ -63,10 +63,10 @@ rb_set_end_proc(void (*func)(VALUE), VALUE data)
rb_thread_t *th = GET_THREAD();
if (th->top_wrapper) {
- list = &ephemeral_end_procs;
+ list = &ephemeral_end_procs;
}
else {
- list = &end_procs;
+ list = &end_procs;
}
link->next = *list;
link->func = func;
@@ -81,13 +81,13 @@ rb_mark_end_proc(void)
link = end_procs;
while (link) {
- rb_gc_mark(link->data);
- link = link->next;
+ rb_gc_mark(link->data);
+ link = link->next;
}
link = ephemeral_end_procs;
while (link) {
- rb_gc_mark(link->data);
- link = link->next;
+ rb_gc_mark(link->data);
+ link = link->next;
}
}
@@ -99,11 +99,11 @@ exec_end_procs_chain(struct end_proc_data *volatile *procs, VALUE *errp)
VALUE errinfo = *errp;
while ((link = *procs) != 0) {
- *procs = link->next;
- endproc = *link;
- xfree(link);
- (*endproc.func) (endproc.data);
- *errp = errinfo;
+ *procs = link->next;
+ endproc = *link;
+ xfree(link);
+ (*endproc.func) (endproc.data);
+ *errp = errinfo;
}
}
@@ -116,15 +116,15 @@ rb_ec_exec_end_proc(rb_execution_context_t * ec)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
again:
- exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo);
- exec_end_procs_chain(&end_procs, &ec->errinfo);
+ exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo);
+ exec_end_procs_chain(&end_procs, &ec->errinfo);
}
else {
- EC_TMPPOP_TAG();
- error_handle(ec, state);
- if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo;
- EC_REPUSH_TAG();
- goto again;
+ EC_TMPPOP_TAG();
+ error_handle(ec, ec->errinfo, state);
+ if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo;
+ EC_REPUSH_TAG();
+ goto again;
}
EC_POP_TAG();
diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend
index 14dac0974c..21ef8c6dd0 100644
--- a/ext/-test-/RUBY_ALIGNOF/depend
+++ b/ext/-test-/RUBY_ALIGNOF/depend
@@ -7,7 +7,6 @@ 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
@@ -15,6 +14,7 @@ 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/abi.h
c.o: $(hdrdir)/ruby/internal/anyargs.h
c.o: $(hdrdir)/ruby/internal/arithmetic.h
c.o: $(hdrdir)/ruby/internal/arithmetic/char.h
diff --git a/ext/-test-/abi/abi.c b/ext/-test-/abi/abi.c
new file mode 100644
index 0000000000..923e0f67b8
--- /dev/null
+++ b/ext/-test-/abi/abi.c
@@ -0,0 +1,11 @@
+#include <limits.h>
+
+unsigned long long
+ruby_abi_version(void)
+{
+ return ULONG_MAX;
+}
+
+void
+Init_abi(void)
+{}
diff --git a/ext/-test-/abi/extconf.rb b/ext/-test-/abi/extconf.rb
new file mode 100644
index 0000000000..3b090b7553
--- /dev/null
+++ b/ext/-test-/abi/extconf.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: false
+return unless RUBY_PATCHLEVEL < 0
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/arith_seq/beg_len_step/beg_len_step.c b/ext/-test-/arith_seq/beg_len_step/beg_len_step.c
new file mode 100644
index 0000000000..40c8cbee82
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/beg_len_step.c
@@ -0,0 +1,19 @@
+#include "ruby/ruby.h"
+
+static VALUE
+arith_seq_s_beg_len_step(VALUE mod, VALUE obj, VALUE len, VALUE err)
+{
+ VALUE r;
+ long beg, len2, step;
+
+ r = rb_arithmetic_sequence_beg_len_step(obj, &beg, &len2, &step, NUM2LONG(len), NUM2INT(err));
+
+ return rb_ary_new_from_args(4, r, LONG2NUM(beg), LONG2NUM(len2), LONG2NUM(step));
+}
+
+void
+Init_beg_len_step(void)
+{
+ VALUE cArithSeq = rb_path2class("Enumerator::ArithmeticSequence");
+ rb_define_singleton_method(cArithSeq, "__beg_len_step__", arith_seq_s_beg_len_step, 3);
+}
diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend
new file mode 100644
index 0000000000..36a2c4c71b
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/depend
@@ -0,0 +1,161 @@
+# AUTOGENERATED DEPENDENCIES START
+beg_len_step.o: $(RUBY_EXTCONF_H)
+beg_len_step.o: $(arch_hdrdir)/ruby/config.h
+beg_len_step.o: $(hdrdir)/ruby/assert.h
+beg_len_step.o: $(hdrdir)/ruby/backward.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/assume.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/attributes.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/bool.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/inttypes.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/limits.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/long_long.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/stdalign.h
+beg_len_step.o: $(hdrdir)/ruby/backward/2/stdarg.h
+beg_len_step.o: $(hdrdir)/ruby/defines.h
+beg_len_step.o: $(hdrdir)/ruby/intern.h
+beg_len_step.o: $(hdrdir)/ruby/internal/abi.h
+beg_len_step.o: $(hdrdir)/ruby/internal/anyargs.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+beg_len_step.o: $(hdrdir)/ruby/internal/assume.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/artificial.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/cold.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/const.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/format.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noalias.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noinline.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/pure.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/restrict.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/warning.h
+beg_len_step.o: $(hdrdir)/ruby/internal/attr/weakref.h
+beg_len_step.o: $(hdrdir)/ruby/internal/cast.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+beg_len_step.o: $(hdrdir)/ruby/internal/compiler_since.h
+beg_len_step.o: $(hdrdir)/ruby/internal/config.h
+beg_len_step.o: $(hdrdir)/ruby/internal/constant_p.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rarray.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rbasic.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rbignum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rclass.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rdata.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rfile.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rhash.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/robject.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rregexp.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rstring.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rstruct.h
+beg_len_step.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+beg_len_step.o: $(hdrdir)/ruby/internal/ctype.h
+beg_len_step.o: $(hdrdir)/ruby/internal/dllexport.h
+beg_len_step.o: $(hdrdir)/ruby/internal/dosish.h
+beg_len_step.o: $(hdrdir)/ruby/internal/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/eval.h
+beg_len_step.o: $(hdrdir)/ruby/internal/event.h
+beg_len_step.o: $(hdrdir)/ruby/internal/fl_type.h
+beg_len_step.o: $(hdrdir)/ruby/internal/gc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/glob.h
+beg_len_step.o: $(hdrdir)/ruby/internal/globals.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/builtin.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/extension.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/feature.h
+beg_len_step.o: $(hdrdir)/ruby/internal/has/warning.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/array.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/bignum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/class.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/compar.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/complex.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/cont.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/dir.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/enum.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/error.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/eval.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/file.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/gc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/hash.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/io.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/load.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/marshal.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/numeric.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/object.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/parse.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/proc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/process.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/random.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/range.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/rational.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/re.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/ruby.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/select.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/signal.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/string.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/struct.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/thread.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/time.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/variable.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/vm.h
+beg_len_step.o: $(hdrdir)/ruby/internal/interpreter.h
+beg_len_step.o: $(hdrdir)/ruby/internal/iterator.h
+beg_len_step.o: $(hdrdir)/ruby/internal/memory.h
+beg_len_step.o: $(hdrdir)/ruby/internal/method.h
+beg_len_step.o: $(hdrdir)/ruby/internal/module.h
+beg_len_step.o: $(hdrdir)/ruby/internal/newobj.h
+beg_len_step.o: $(hdrdir)/ruby/internal/rgengc.h
+beg_len_step.o: $(hdrdir)/ruby/internal/scan_args.h
+beg_len_step.o: $(hdrdir)/ruby/internal/special_consts.h
+beg_len_step.o: $(hdrdir)/ruby/internal/static_assert.h
+beg_len_step.o: $(hdrdir)/ruby/internal/stdalign.h
+beg_len_step.o: $(hdrdir)/ruby/internal/stdbool.h
+beg_len_step.o: $(hdrdir)/ruby/internal/symbol.h
+beg_len_step.o: $(hdrdir)/ruby/internal/value.h
+beg_len_step.o: $(hdrdir)/ruby/internal/value_type.h
+beg_len_step.o: $(hdrdir)/ruby/internal/variable.h
+beg_len_step.o: $(hdrdir)/ruby/internal/warning_push.h
+beg_len_step.o: $(hdrdir)/ruby/internal/xmalloc.h
+beg_len_step.o: $(hdrdir)/ruby/missing.h
+beg_len_step.o: $(hdrdir)/ruby/ruby.h
+beg_len_step.o: $(hdrdir)/ruby/st.h
+beg_len_step.o: $(hdrdir)/ruby/subst.h
+beg_len_step.o: beg_len_step.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/arith_seq/beg_len_step/extconf.rb b/ext/-test-/arith_seq/beg_len_step/extconf.rb
new file mode 100644
index 0000000000..e72b3ad01f
--- /dev/null
+++ b/ext/-test-/arith_seq/beg_len_step/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/arith_seq/beg_len_step")
diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend
index 8bf12c5f47..57cbaa9a0c 100644
--- a/ext/-test-/arith_seq/extract/depend
+++ b/ext/-test-/arith_seq/extract/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
extract.o: $(RUBY_EXTCONF_H)
extract.o: $(arch_hdrdir)/ruby/config.h
+extract.o: $(hdrdir)/ruby/assert.h
+extract.o: $(hdrdir)/ruby/backward.h
+extract.o: $(hdrdir)/ruby/backward/2/assume.h
+extract.o: $(hdrdir)/ruby/backward/2/attributes.h
+extract.o: $(hdrdir)/ruby/backward/2/bool.h
+extract.o: $(hdrdir)/ruby/backward/2/inttypes.h
+extract.o: $(hdrdir)/ruby/backward/2/limits.h
+extract.o: $(hdrdir)/ruby/backward/2/long_long.h
+extract.o: $(hdrdir)/ruby/backward/2/stdalign.h
+extract.o: $(hdrdir)/ruby/backward/2/stdarg.h
+extract.o: $(hdrdir)/ruby/defines.h
+extract.o: $(hdrdir)/ruby/intern.h
+extract.o: $(hdrdir)/ruby/internal/abi.h
extract.o: $(hdrdir)/ruby/internal/anyargs.h
extract.o: $(hdrdir)/ruby/internal/arithmetic.h
extract.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
extract.o: $(hdrdir)/ruby/ruby.h
extract.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend
new file mode 100644
index 0000000000..79c833738e
--- /dev/null
+++ b/ext/-test-/array/concat/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+to_ary_concat.o: $(RUBY_EXTCONF_H)
+to_ary_concat.o: $(arch_hdrdir)/ruby/config.h
+to_ary_concat.o: $(hdrdir)/ruby.h
+to_ary_concat.o: $(hdrdir)/ruby/assert.h
+to_ary_concat.o: $(hdrdir)/ruby/backward.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/assume.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/attributes.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/bool.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/limits.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/long_long.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+to_ary_concat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+to_ary_concat.o: $(hdrdir)/ruby/defines.h
+to_ary_concat.o: $(hdrdir)/ruby/intern.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/abi.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/anyargs.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/assume.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/cold.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/const.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/error.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/format.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/pure.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/warning.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/cast.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/compiler_since.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/config.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/constant_p.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rarray.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rclass.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rdata.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rfile.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rhash.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/robject.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rstring.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/ctype.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/dllexport.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/dosish.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/error.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/eval.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/event.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/fl_type.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/gc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/glob.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/globals.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/builtin.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/extension.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/feature.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/has/warning.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/array.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/class.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/compar.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/complex.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/cont.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/dir.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/enum.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/error.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/eval.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/file.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/gc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/hash.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/io.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/load.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/object.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/parse.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/proc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/process.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/random.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/range.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/rational.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/re.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/signal.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/string.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/struct.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/thread.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/time.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/variable.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/vm.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/interpreter.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/iterator.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/memory.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/method.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/module.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/newobj.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/rgengc.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/scan_args.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/special_consts.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/static_assert.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/stdalign.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/stdbool.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/symbol.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/value.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/value_type.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/variable.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/warning_push.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/xmalloc.h
+to_ary_concat.o: $(hdrdir)/ruby/missing.h
+to_ary_concat.o: $(hdrdir)/ruby/ruby.h
+to_ary_concat.o: $(hdrdir)/ruby/st.h
+to_ary_concat.o: $(hdrdir)/ruby/subst.h
+to_ary_concat.o: to_ary_concat.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/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_concat.c b/ext/-test-/array/concat/to_ary_concat.c
new file mode 100644
index 0000000000..07a96d3907
--- /dev/null
+++ b/ext/-test-/array/concat/to_ary_concat.c
@@ -0,0 +1,38 @@
+#include "ruby.h"
+
+// Bar
+
+typedef struct {
+ int dummy;
+} Bar;
+
+static rb_data_type_t Bar_type = {
+ "Bar",
+ {NULL, RUBY_TYPED_DEFAULT_FREE, NULL },
+};
+
+static VALUE
+Bar_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &Bar_type, NULL);
+}
+
+static VALUE
+Bar_to_ary(VALUE _self)
+{
+ VALUE ary = rb_ary_new2(2);
+ VALUE foo = rb_ary_new2(0);
+ rb_ary_push(ary, foo);
+ rb_ary_push(ary, foo);
+ rb_ary_push(ary, foo);
+ return ary;
+}
+
+void
+Init_to_ary_concat(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE bar = rb_define_class_under(mBug, "Bar", rb_cObject);
+ rb_define_alloc_func(bar, Bar_alloc);
+ rb_define_method(bar, "to_ary", Bar_to_ary, 0);
+}
diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend
index cf0c2320ae..49e0f346d3 100644
--- a/ext/-test-/array/resize/depend
+++ b/ext/-test-/array/resize/depend
@@ -1,6 +1,19 @@
# 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/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/abi.h
resize.o: $(hdrdir)/ruby/internal/anyargs.h
resize.o: $(hdrdir)/ruby/internal/arithmetic.h
resize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
resize.o: $(hdrdir)/ruby/ruby.h
resize.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/auto_ext.rb b/ext/-test-/auto_ext.rb
index 71606a9dd1..58c49c177b 100644
--- a/ext/-test-/auto_ext.rb
+++ b/ext/-test-/auto_ext.rb
@@ -6,5 +6,6 @@ def auto_ext(feat = $0[%r[/ext/(-test-/.*)/extconf.rb\z], 1], inc: false)
inits.delete("init")
inits.map! {|s|"X(#{s})"}
$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
+ create_header
create_makefile(feat)
end
diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend
index ddc1e63570..d4072fb35c 100644
--- a/ext/-test-/bignum/depend
+++ b/ext/-test-/bignum/depend
@@ -1,7 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
big2str.o: $(RUBY_EXTCONF_H)
big2str.o: $(arch_hdrdir)/ruby/config.h
-big2str.o: $(hdrdir)/ruby.h
+big2str.o: $(hdrdir)/ruby/assert.h
+big2str.o: $(hdrdir)/ruby/backward.h
+big2str.o: $(hdrdir)/ruby/backward/2/assume.h
+big2str.o: $(hdrdir)/ruby/backward/2/attributes.h
+big2str.o: $(hdrdir)/ruby/backward/2/bool.h
+big2str.o: $(hdrdir)/ruby/backward/2/inttypes.h
+big2str.o: $(hdrdir)/ruby/backward/2/limits.h
+big2str.o: $(hdrdir)/ruby/backward/2/long_long.h
+big2str.o: $(hdrdir)/ruby/backward/2/stdalign.h
+big2str.o: $(hdrdir)/ruby/backward/2/stdarg.h
+big2str.o: $(hdrdir)/ruby/defines.h
+big2str.o: $(hdrdir)/ruby/intern.h
+big2str.o: $(hdrdir)/ruby/internal/abi.h
big2str.o: $(hdrdir)/ruby/internal/anyargs.h
big2str.o: $(hdrdir)/ruby/internal/arithmetic.h
big2str.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,29 +153,27 @@ 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
big2str.o: $(hdrdir)/ruby/ruby.h
big2str.o: $(hdrdir)/ruby/st.h
big2str.o: $(hdrdir)/ruby/subst.h
-big2str.o: $(top_srcdir)/internal.h
big2str.o: $(top_srcdir)/internal/bignum.h
big2str.o: big2str.c
bigzero.o: $(RUBY_EXTCONF_H)
bigzero.o: $(arch_hdrdir)/ruby/config.h
-bigzero.o: $(hdrdir)/ruby.h
+bigzero.o: $(hdrdir)/ruby/assert.h
+bigzero.o: $(hdrdir)/ruby/backward.h
+bigzero.o: $(hdrdir)/ruby/backward/2/assume.h
+bigzero.o: $(hdrdir)/ruby/backward/2/attributes.h
+bigzero.o: $(hdrdir)/ruby/backward/2/bool.h
+bigzero.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bigzero.o: $(hdrdir)/ruby/backward/2/limits.h
+bigzero.o: $(hdrdir)/ruby/backward/2/long_long.h
+bigzero.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bigzero.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bigzero.o: $(hdrdir)/ruby/defines.h
+bigzero.o: $(hdrdir)/ruby/intern.h
+bigzero.o: $(hdrdir)/ruby/internal/abi.h
bigzero.o: $(hdrdir)/ruby/internal/anyargs.h
bigzero.o: $(hdrdir)/ruby/internal/arithmetic.h
bigzero.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -303,29 +313,27 @@ 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
bigzero.o: $(hdrdir)/ruby/ruby.h
bigzero.o: $(hdrdir)/ruby/st.h
bigzero.o: $(hdrdir)/ruby/subst.h
-bigzero.o: $(top_srcdir)/internal.h
bigzero.o: $(top_srcdir)/internal/bignum.h
bigzero.o: bigzero.c
div.o: $(RUBY_EXTCONF_H)
div.o: $(arch_hdrdir)/ruby/config.h
-div.o: $(hdrdir)/ruby.h
+div.o: $(hdrdir)/ruby/assert.h
+div.o: $(hdrdir)/ruby/backward.h
+div.o: $(hdrdir)/ruby/backward/2/assume.h
+div.o: $(hdrdir)/ruby/backward/2/attributes.h
+div.o: $(hdrdir)/ruby/backward/2/bool.h
+div.o: $(hdrdir)/ruby/backward/2/inttypes.h
+div.o: $(hdrdir)/ruby/backward/2/limits.h
+div.o: $(hdrdir)/ruby/backward/2/long_long.h
+div.o: $(hdrdir)/ruby/backward/2/stdalign.h
+div.o: $(hdrdir)/ruby/backward/2/stdarg.h
+div.o: $(hdrdir)/ruby/defines.h
+div.o: $(hdrdir)/ruby/intern.h
+div.o: $(hdrdir)/ruby/internal/abi.h
div.o: $(hdrdir)/ruby/internal/anyargs.h
div.o: $(hdrdir)/ruby/internal/arithmetic.h
div.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -465,29 +473,28 @@ 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
div.o: $(hdrdir)/ruby/ruby.h
div.o: $(hdrdir)/ruby/st.h
div.o: $(hdrdir)/ruby/subst.h
-div.o: $(top_srcdir)/internal.h
div.o: $(top_srcdir)/internal/bignum.h
div.o: div.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -627,19 +634,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -647,7 +641,19 @@ init.o: $(hdrdir)/ruby/subst.h
init.o: init.c
intpack.o: $(RUBY_EXTCONF_H)
intpack.o: $(arch_hdrdir)/ruby/config.h
-intpack.o: $(hdrdir)/ruby.h
+intpack.o: $(hdrdir)/ruby/assert.h
+intpack.o: $(hdrdir)/ruby/backward.h
+intpack.o: $(hdrdir)/ruby/backward/2/assume.h
+intpack.o: $(hdrdir)/ruby/backward/2/attributes.h
+intpack.o: $(hdrdir)/ruby/backward/2/bool.h
+intpack.o: $(hdrdir)/ruby/backward/2/inttypes.h
+intpack.o: $(hdrdir)/ruby/backward/2/limits.h
+intpack.o: $(hdrdir)/ruby/backward/2/long_long.h
+intpack.o: $(hdrdir)/ruby/backward/2/stdalign.h
+intpack.o: $(hdrdir)/ruby/backward/2/stdarg.h
+intpack.o: $(hdrdir)/ruby/defines.h
+intpack.o: $(hdrdir)/ruby/intern.h
+intpack.o: $(hdrdir)/ruby/internal/abi.h
intpack.o: $(hdrdir)/ruby/internal/anyargs.h
intpack.o: $(hdrdir)/ruby/internal/arithmetic.h
intpack.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -787,29 +793,27 @@ 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
intpack.o: $(hdrdir)/ruby/ruby.h
intpack.o: $(hdrdir)/ruby/st.h
intpack.o: $(hdrdir)/ruby/subst.h
-intpack.o: $(top_srcdir)/internal.h
intpack.o: $(top_srcdir)/internal/bignum.h
intpack.o: intpack.c
mul.o: $(RUBY_EXTCONF_H)
mul.o: $(arch_hdrdir)/ruby/config.h
-mul.o: $(hdrdir)/ruby.h
+mul.o: $(hdrdir)/ruby/assert.h
+mul.o: $(hdrdir)/ruby/backward.h
+mul.o: $(hdrdir)/ruby/backward/2/assume.h
+mul.o: $(hdrdir)/ruby/backward/2/attributes.h
+mul.o: $(hdrdir)/ruby/backward/2/bool.h
+mul.o: $(hdrdir)/ruby/backward/2/inttypes.h
+mul.o: $(hdrdir)/ruby/backward/2/limits.h
+mul.o: $(hdrdir)/ruby/backward/2/long_long.h
+mul.o: $(hdrdir)/ruby/backward/2/stdalign.h
+mul.o: $(hdrdir)/ruby/backward/2/stdarg.h
+mul.o: $(hdrdir)/ruby/defines.h
+mul.o: $(hdrdir)/ruby/intern.h
+mul.o: $(hdrdir)/ruby/internal/abi.h
mul.o: $(hdrdir)/ruby/internal/anyargs.h
mul.o: $(hdrdir)/ruby/internal/arithmetic.h
mul.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -949,29 +953,27 @@ 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
mul.o: $(hdrdir)/ruby/ruby.h
mul.o: $(hdrdir)/ruby/st.h
mul.o: $(hdrdir)/ruby/subst.h
-mul.o: $(top_srcdir)/internal.h
mul.o: $(top_srcdir)/internal/bignum.h
mul.o: mul.c
str2big.o: $(RUBY_EXTCONF_H)
str2big.o: $(arch_hdrdir)/ruby/config.h
-str2big.o: $(hdrdir)/ruby.h
+str2big.o: $(hdrdir)/ruby/assert.h
+str2big.o: $(hdrdir)/ruby/backward.h
+str2big.o: $(hdrdir)/ruby/backward/2/assume.h
+str2big.o: $(hdrdir)/ruby/backward/2/attributes.h
+str2big.o: $(hdrdir)/ruby/backward/2/bool.h
+str2big.o: $(hdrdir)/ruby/backward/2/inttypes.h
+str2big.o: $(hdrdir)/ruby/backward/2/limits.h
+str2big.o: $(hdrdir)/ruby/backward/2/long_long.h
+str2big.o: $(hdrdir)/ruby/backward/2/stdalign.h
+str2big.o: $(hdrdir)/ruby/backward/2/stdarg.h
+str2big.o: $(hdrdir)/ruby/defines.h
+str2big.o: $(hdrdir)/ruby/intern.h
+str2big.o: $(hdrdir)/ruby/internal/abi.h
str2big.o: $(hdrdir)/ruby/internal/anyargs.h
str2big.o: $(hdrdir)/ruby/internal/arithmetic.h
str2big.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1111,24 +1113,10 @@ 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
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-/bug-14834/depend b/ext/-test-/bug-14834/depend
index 5bbaf17089..7bac8409e8 100644
--- a/ext/-test-/bug-14834/depend
+++ b/ext/-test-/bug-14834/depend
@@ -1,6 +1,20 @@
# AUTOGENERATED DEPENDENCIES START
bug-14384.o: $(RUBY_EXTCONF_H)
bug-14384.o: $(arch_hdrdir)/ruby/config.h
+bug-14384.o: $(hdrdir)/ruby/assert.h
+bug-14384.o: $(hdrdir)/ruby/backward.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/assume.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/bool.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/limits.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug-14384.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug-14384.o: $(hdrdir)/ruby/debug.h
+bug-14384.o: $(hdrdir)/ruby/defines.h
+bug-14384.o: $(hdrdir)/ruby/intern.h
+bug-14384.o: $(hdrdir)/ruby/internal/abi.h
bug-14384.o: $(hdrdir)/ruby/internal/anyargs.h
bug-14384.o: $(hdrdir)/ruby/internal/arithmetic.h
bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,20 +154,6 @@ 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
bug-14384.o: $(hdrdir)/ruby/missing.h
bug-14384.o: $(hdrdir)/ruby/ruby.h
bug-14384.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend
index 506795a137..2303f47594 100644
--- a/ext/-test-/bug-3571/depend
+++ b/ext/-test-/bug-3571/depend
@@ -2,6 +2,19 @@
bug.o: $(RUBY_EXTCONF_H)
bug.o: $(arch_hdrdir)/ruby/config.h
bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/assert.h
+bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug.o: $(hdrdir)/ruby/defines.h
+bug.o: $(hdrdir)/ruby/intern.h
+bug.o: $(hdrdir)/ruby/internal/abi.h
bug.o: $(hdrdir)/ruby/internal/anyargs.h
bug.o: $(hdrdir)/ruby/internal/arithmetic.h
bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
bug.o: $(hdrdir)/ruby/ruby.h
bug.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend
index 506795a137..2303f47594 100644
--- a/ext/-test-/bug-5832/depend
+++ b/ext/-test-/bug-5832/depend
@@ -2,6 +2,19 @@
bug.o: $(RUBY_EXTCONF_H)
bug.o: $(arch_hdrdir)/ruby/config.h
bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/assert.h
+bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug.o: $(hdrdir)/ruby/defines.h
+bug.o: $(hdrdir)/ruby/intern.h
+bug.o: $(hdrdir)/ruby/internal/abi.h
bug.o: $(hdrdir)/ruby/internal/anyargs.h
bug.o: $(hdrdir)/ruby/internal/arithmetic.h
bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
bug.o: $(hdrdir)/ruby/ruby.h
bug.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend
index 0eadef5d82..603dd53ebf 100644
--- a/ext/-test-/bug_reporter/depend
+++ b/ext/-test-/bug_reporter/depend
@@ -2,6 +2,19 @@
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/assert.h
+bug_reporter.o: $(hdrdir)/ruby/backward.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/assume.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/bool.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/limits.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug_reporter.o: $(hdrdir)/ruby/defines.h
+bug_reporter.o: $(hdrdir)/ruby/intern.h
+bug_reporter.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
bug_reporter.o: $(hdrdir)/ruby/ruby.h
bug_reporter.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend
index 69138c6175..a615eacd74 100644
--- a/ext/-test-/class/depend
+++ b/ext/-test-/class/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
class2name.o: $(RUBY_EXTCONF_H)
class2name.o: $(arch_hdrdir)/ruby/config.h
+class2name.o: $(hdrdir)/ruby/assert.h
+class2name.o: $(hdrdir)/ruby/backward.h
+class2name.o: $(hdrdir)/ruby/backward/2/assume.h
+class2name.o: $(hdrdir)/ruby/backward/2/attributes.h
+class2name.o: $(hdrdir)/ruby/backward/2/bool.h
+class2name.o: $(hdrdir)/ruby/backward/2/inttypes.h
+class2name.o: $(hdrdir)/ruby/backward/2/limits.h
+class2name.o: $(hdrdir)/ruby/backward/2/long_long.h
+class2name.o: $(hdrdir)/ruby/backward/2/stdalign.h
+class2name.o: $(hdrdir)/ruby/backward/2/stdarg.h
+class2name.o: $(hdrdir)/ruby/defines.h
+class2name.o: $(hdrdir)/ruby/intern.h
+class2name.o: $(hdrdir)/ruby/internal/abi.h
class2name.o: $(hdrdir)/ruby/internal/anyargs.h
class2name.o: $(hdrdir)/ruby/internal/arithmetic.h
class2name.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
class2name.o: $(hdrdir)/ruby/ruby.h
class2name.o: $(hdrdir)/ruby/st.h
@@ -161,6 +161,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -300,19 +313,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/cxxanyargs/depend b/ext/-test-/cxxanyargs/depend
index ca821409a2..fc3d8e45d9 100644
--- a/ext/-test-/cxxanyargs/depend
+++ b/ext/-test-/cxxanyargs/depend
@@ -10,16 +10,4 @@ $(TARGET_SO) $(STATIC_LIB): $(FAILURES:.cpp=.failed)
-e "File.write(t, err)" $@ $(MAKE) $(*F).o
# AUTOGENERATED DEPENDENCIES START
-cxxanyargs.o: $(RUBY_EXTCONF_H)
-cxxanyargs.o: $(arch_hdrdir)/ruby/config.h
-cxxanyargs.o: $(hdrdir)/ruby/assert.h
-cxxanyargs.o: $(hdrdir)/ruby/backward.h
-cxxanyargs.o: $(hdrdir)/ruby/backward/cxxanyargs.hpp
-cxxanyargs.o: $(hdrdir)/ruby/defines.h
-cxxanyargs.o: $(hdrdir)/ruby/intern.h
-cxxanyargs.o: $(hdrdir)/ruby/missing.h
-cxxanyargs.o: $(hdrdir)/ruby/ruby.h
-cxxanyargs.o: $(hdrdir)/ruby/st.h
-cxxanyargs.o: $(hdrdir)/ruby/subst.h
-cxxanyargs.o: cxxanyargs.cpp
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend
index 6c1c736d61..c3a0c278aa 100644
--- a/ext/-test-/debug/depend
+++ b/ext/-test-/debug/depend
@@ -2,6 +2,19 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -161,6 +161,20 @@ 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/assert.h
+inspector.o: $(hdrdir)/ruby/backward.h
+inspector.o: $(hdrdir)/ruby/backward/2/assume.h
+inspector.o: $(hdrdir)/ruby/backward/2/attributes.h
+inspector.o: $(hdrdir)/ruby/backward/2/bool.h
+inspector.o: $(hdrdir)/ruby/backward/2/inttypes.h
+inspector.o: $(hdrdir)/ruby/backward/2/limits.h
+inspector.o: $(hdrdir)/ruby/backward/2/long_long.h
+inspector.o: $(hdrdir)/ruby/backward/2/stdalign.h
+inspector.o: $(hdrdir)/ruby/backward/2/stdarg.h
+inspector.o: $(hdrdir)/ruby/debug.h
+inspector.o: $(hdrdir)/ruby/defines.h
+inspector.o: $(hdrdir)/ruby/intern.h
+inspector.o: $(hdrdir)/ruby/internal/abi.h
inspector.o: $(hdrdir)/ruby/internal/anyargs.h
inspector.o: $(hdrdir)/ruby/internal/arithmetic.h
inspector.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -300,20 +314,6 @@ 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
inspector.o: $(hdrdir)/ruby/missing.h
inspector.o: $(hdrdir)/ruby/ruby.h
inspector.o: $(hdrdir)/ruby/st.h
@@ -321,6 +321,20 @@ 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/assert.h
+profile_frames.o: $(hdrdir)/ruby/backward.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/assume.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/attributes.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/bool.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/inttypes.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/limits.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/long_long.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/stdalign.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/stdarg.h
+profile_frames.o: $(hdrdir)/ruby/debug.h
+profile_frames.o: $(hdrdir)/ruby/defines.h
+profile_frames.o: $(hdrdir)/ruby/intern.h
+profile_frames.o: $(hdrdir)/ruby/internal/abi.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
@@ -460,20 +474,6 @@ 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
profile_frames.o: $(hdrdir)/ruby/missing.h
profile_frames.o: $(hdrdir)/ruby/ruby.h
profile_frames.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/debug/inspector.c b/ext/-test-/debug/inspector.c
index f0c58e59f9..25f9d894d3 100644
--- a/ext/-test-/debug/inspector.c
+++ b/ext/-test-/debug/inspector.c
@@ -8,13 +8,13 @@ callback(const rb_debug_inspector_t *dbg_context, void *data)
long i, len = RARRAY_LEN(locs);
VALUE binds = rb_ary_new();
for (i = 0; i < len; ++i) {
- VALUE entry = rb_ary_new();
- rb_ary_push(binds, entry);
- rb_ary_push(entry, rb_debug_inspector_frame_self_get(dbg_context, i));
- rb_ary_push(entry, rb_debug_inspector_frame_binding_get(dbg_context, i));
- rb_ary_push(entry, rb_debug_inspector_frame_class_get(dbg_context, i));
- rb_ary_push(entry, rb_debug_inspector_frame_iseq_get(dbg_context, i));
- rb_ary_push(entry, rb_ary_entry(locs, i));
+ VALUE entry = rb_ary_new();
+ rb_ary_push(binds, entry);
+ rb_ary_push(entry, rb_debug_inspector_frame_self_get(dbg_context, i));
+ rb_ary_push(entry, rb_debug_inspector_frame_binding_get(dbg_context, i));
+ rb_ary_push(entry, rb_debug_inspector_frame_class_get(dbg_context, i));
+ rb_ary_push(entry, rb_debug_inspector_frame_iseq_get(dbg_context, i));
+ rb_ary_push(entry, rb_ary_entry(locs, i));
}
return binds;
}
diff --git a/ext/-test-/debug/profile_frames.c b/ext/-test-/debug/profile_frames.c
index 1656ff7d4b..d2bba7d183 100644
--- a/ext/-test-/debug/profile_frames.c
+++ b/ext/-test-/debug/profile_frames.c
@@ -18,19 +18,20 @@ profile_frames(VALUE self, VALUE start_v, VALUE num_v)
collected_size = rb_profile_frames(start, buff_size, buff, lines);
for (i=0; i<collected_size; i++) {
- VALUE ary = rb_ary_new();
- rb_ary_push(ary, rb_profile_frame_path(buff[i]));
- rb_ary_push(ary, rb_profile_frame_absolute_path(buff[i]));
- rb_ary_push(ary, rb_profile_frame_label(buff[i]));
- rb_ary_push(ary, rb_profile_frame_base_label(buff[i]));
- rb_ary_push(ary, rb_profile_frame_full_label(buff[i]));
- rb_ary_push(ary, rb_profile_frame_first_lineno(buff[i]));
- rb_ary_push(ary, rb_profile_frame_classpath(buff[i]));
- rb_ary_push(ary, rb_profile_frame_singleton_method_p(buff[i]));
- rb_ary_push(ary, rb_profile_frame_method_name(buff[i]));
- rb_ary_push(ary, rb_profile_frame_qualified_method_name(buff[i]));
-
- rb_ary_push(result, ary);
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, rb_profile_frame_path(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_absolute_path(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_label(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_base_label(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_full_label(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_first_lineno(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_classpath(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_singleton_method_p(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_method_name(buff[i]));
+ rb_ary_push(ary, rb_profile_frame_qualified_method_name(buff[i]));
+ rb_ary_push(ary, INT2NUM(lines[i]));
+
+ rb_ary_push(result, ary);
}
return result;
diff --git a/ext/-test-/dln/empty/depend b/ext/-test-/dln/empty/depend
index 99151fa055..e16082a7dc 100644
--- a/ext/-test-/dln/empty/depend
+++ b/ext/-test-/dln/empty/depend
@@ -1,3 +1,162 @@
# AUTOGENERATED DEPENDENCIES START
+empty.o: $(RUBY_EXTCONF_H)
+empty.o: $(arch_hdrdir)/ruby/config.h
+empty.o: $(hdrdir)/ruby.h
+empty.o: $(hdrdir)/ruby/assert.h
+empty.o: $(hdrdir)/ruby/backward.h
+empty.o: $(hdrdir)/ruby/backward/2/assume.h
+empty.o: $(hdrdir)/ruby/backward/2/attributes.h
+empty.o: $(hdrdir)/ruby/backward/2/bool.h
+empty.o: $(hdrdir)/ruby/backward/2/inttypes.h
+empty.o: $(hdrdir)/ruby/backward/2/limits.h
+empty.o: $(hdrdir)/ruby/backward/2/long_long.h
+empty.o: $(hdrdir)/ruby/backward/2/stdalign.h
+empty.o: $(hdrdir)/ruby/backward/2/stdarg.h
+empty.o: $(hdrdir)/ruby/defines.h
+empty.o: $(hdrdir)/ruby/intern.h
+empty.o: $(hdrdir)/ruby/internal/abi.h
+empty.o: $(hdrdir)/ruby/internal/anyargs.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+empty.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+empty.o: $(hdrdir)/ruby/internal/assume.h
+empty.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+empty.o: $(hdrdir)/ruby/internal/attr/artificial.h
+empty.o: $(hdrdir)/ruby/internal/attr/cold.h
+empty.o: $(hdrdir)/ruby/internal/attr/const.h
+empty.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+empty.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+empty.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+empty.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+empty.o: $(hdrdir)/ruby/internal/attr/error.h
+empty.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+empty.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+empty.o: $(hdrdir)/ruby/internal/attr/format.h
+empty.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+empty.o: $(hdrdir)/ruby/internal/attr/noalias.h
+empty.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+empty.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+empty.o: $(hdrdir)/ruby/internal/attr/noinline.h
+empty.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+empty.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+empty.o: $(hdrdir)/ruby/internal/attr/pure.h
+empty.o: $(hdrdir)/ruby/internal/attr/restrict.h
+empty.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+empty.o: $(hdrdir)/ruby/internal/attr/warning.h
+empty.o: $(hdrdir)/ruby/internal/attr/weakref.h
+empty.o: $(hdrdir)/ruby/internal/cast.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+empty.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+empty.o: $(hdrdir)/ruby/internal/compiler_since.h
+empty.o: $(hdrdir)/ruby/internal/config.h
+empty.o: $(hdrdir)/ruby/internal/constant_p.h
+empty.o: $(hdrdir)/ruby/internal/core.h
+empty.o: $(hdrdir)/ruby/internal/core/rarray.h
+empty.o: $(hdrdir)/ruby/internal/core/rbasic.h
+empty.o: $(hdrdir)/ruby/internal/core/rbignum.h
+empty.o: $(hdrdir)/ruby/internal/core/rclass.h
+empty.o: $(hdrdir)/ruby/internal/core/rdata.h
+empty.o: $(hdrdir)/ruby/internal/core/rfile.h
+empty.o: $(hdrdir)/ruby/internal/core/rhash.h
+empty.o: $(hdrdir)/ruby/internal/core/robject.h
+empty.o: $(hdrdir)/ruby/internal/core/rregexp.h
+empty.o: $(hdrdir)/ruby/internal/core/rstring.h
+empty.o: $(hdrdir)/ruby/internal/core/rstruct.h
+empty.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+empty.o: $(hdrdir)/ruby/internal/ctype.h
+empty.o: $(hdrdir)/ruby/internal/dllexport.h
+empty.o: $(hdrdir)/ruby/internal/dosish.h
+empty.o: $(hdrdir)/ruby/internal/error.h
+empty.o: $(hdrdir)/ruby/internal/eval.h
+empty.o: $(hdrdir)/ruby/internal/event.h
+empty.o: $(hdrdir)/ruby/internal/fl_type.h
+empty.o: $(hdrdir)/ruby/internal/gc.h
+empty.o: $(hdrdir)/ruby/internal/glob.h
+empty.o: $(hdrdir)/ruby/internal/globals.h
+empty.o: $(hdrdir)/ruby/internal/has/attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/builtin.h
+empty.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+empty.o: $(hdrdir)/ruby/internal/has/extension.h
+empty.o: $(hdrdir)/ruby/internal/has/feature.h
+empty.o: $(hdrdir)/ruby/internal/has/warning.h
+empty.o: $(hdrdir)/ruby/internal/intern/array.h
+empty.o: $(hdrdir)/ruby/internal/intern/bignum.h
+empty.o: $(hdrdir)/ruby/internal/intern/class.h
+empty.o: $(hdrdir)/ruby/internal/intern/compar.h
+empty.o: $(hdrdir)/ruby/internal/intern/complex.h
+empty.o: $(hdrdir)/ruby/internal/intern/cont.h
+empty.o: $(hdrdir)/ruby/internal/intern/dir.h
+empty.o: $(hdrdir)/ruby/internal/intern/enum.h
+empty.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+empty.o: $(hdrdir)/ruby/internal/intern/error.h
+empty.o: $(hdrdir)/ruby/internal/intern/eval.h
+empty.o: $(hdrdir)/ruby/internal/intern/file.h
+empty.o: $(hdrdir)/ruby/internal/intern/gc.h
+empty.o: $(hdrdir)/ruby/internal/intern/hash.h
+empty.o: $(hdrdir)/ruby/internal/intern/io.h
+empty.o: $(hdrdir)/ruby/internal/intern/load.h
+empty.o: $(hdrdir)/ruby/internal/intern/marshal.h
+empty.o: $(hdrdir)/ruby/internal/intern/numeric.h
+empty.o: $(hdrdir)/ruby/internal/intern/object.h
+empty.o: $(hdrdir)/ruby/internal/intern/parse.h
+empty.o: $(hdrdir)/ruby/internal/intern/proc.h
+empty.o: $(hdrdir)/ruby/internal/intern/process.h
+empty.o: $(hdrdir)/ruby/internal/intern/random.h
+empty.o: $(hdrdir)/ruby/internal/intern/range.h
+empty.o: $(hdrdir)/ruby/internal/intern/rational.h
+empty.o: $(hdrdir)/ruby/internal/intern/re.h
+empty.o: $(hdrdir)/ruby/internal/intern/ruby.h
+empty.o: $(hdrdir)/ruby/internal/intern/select.h
+empty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+empty.o: $(hdrdir)/ruby/internal/intern/signal.h
+empty.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+empty.o: $(hdrdir)/ruby/internal/intern/string.h
+empty.o: $(hdrdir)/ruby/internal/intern/struct.h
+empty.o: $(hdrdir)/ruby/internal/intern/thread.h
+empty.o: $(hdrdir)/ruby/internal/intern/time.h
+empty.o: $(hdrdir)/ruby/internal/intern/variable.h
+empty.o: $(hdrdir)/ruby/internal/intern/vm.h
+empty.o: $(hdrdir)/ruby/internal/interpreter.h
+empty.o: $(hdrdir)/ruby/internal/iterator.h
+empty.o: $(hdrdir)/ruby/internal/memory.h
+empty.o: $(hdrdir)/ruby/internal/method.h
+empty.o: $(hdrdir)/ruby/internal/module.h
+empty.o: $(hdrdir)/ruby/internal/newobj.h
+empty.o: $(hdrdir)/ruby/internal/rgengc.h
+empty.o: $(hdrdir)/ruby/internal/scan_args.h
+empty.o: $(hdrdir)/ruby/internal/special_consts.h
+empty.o: $(hdrdir)/ruby/internal/static_assert.h
+empty.o: $(hdrdir)/ruby/internal/stdalign.h
+empty.o: $(hdrdir)/ruby/internal/stdbool.h
+empty.o: $(hdrdir)/ruby/internal/symbol.h
+empty.o: $(hdrdir)/ruby/internal/value.h
+empty.o: $(hdrdir)/ruby/internal/value_type.h
+empty.o: $(hdrdir)/ruby/internal/variable.h
+empty.o: $(hdrdir)/ruby/internal/warning_push.h
+empty.o: $(hdrdir)/ruby/internal/xmalloc.h
+empty.o: $(hdrdir)/ruby/missing.h
+empty.o: $(hdrdir)/ruby/ruby.h
+empty.o: $(hdrdir)/ruby/st.h
+empty.o: $(hdrdir)/ruby/subst.h
empty.o: empty.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/dln/empty/empty.c b/ext/-test-/dln/empty/empty.c
index c4f94f1644..2b4fd42cd2 100644
--- a/ext/-test-/dln/empty/empty.c
+++ b/ext/-test-/dln/empty/empty.c
@@ -1,3 +1,5 @@
+#include "ruby.h"
+
void
Init_empty(void)
{
diff --git a/ext/-test-/econv/append.c b/ext/-test-/econv/append.c
new file mode 100644
index 0000000000..724cd136c0
--- /dev/null
+++ b/ext/-test-/econv/append.c
@@ -0,0 +1,15 @@
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE
+econv_append(VALUE self, VALUE src, VALUE dst)
+{
+ rb_econv_t *ec = DATA_PTR(self);
+ return rb_econv_str_append(ec, src, dst, 0);
+}
+
+void
+Init_econv_append(VALUE klass)
+{
+ rb_define_method(klass, "append", econv_append, 2);
+}
diff --git a/ext/-test-/econv/extconf.rb b/ext/-test-/econv/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/econv/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/econv/init.c b/ext/-test-/econv/init.c
new file mode 100644
index 0000000000..9772ebe71c
--- /dev/null
+++ b/ext/-test-/econv/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_econv_##n(VALUE klass); Init_econv_##n(klass);}
+
+void
+Init_econv(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_class_under(mBug, "EConv", rb_path2class("Encoding::Converter"));
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend
index 482863a288..14a9557e41 100644
--- a/ext/-test-/enumerator_kw/depend
+++ b/ext/-test-/enumerator_kw/depend
@@ -2,6 +2,19 @@
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/assert.h
+enumerator_kw.o: $(hdrdir)/ruby/backward.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/assume.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/attributes.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/bool.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/limits.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/long_long.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enumerator_kw.o: $(hdrdir)/ruby/defines.h
+enumerator_kw.o: $(hdrdir)/ruby/intern.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
enumerator_kw.o: $(hdrdir)/ruby/ruby.h
enumerator_kw.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/enumerator_kw/enumerator_kw.c b/ext/-test-/enumerator_kw/enumerator_kw.c
index 947d2b37e6..9104c51869 100644
--- a/ext/-test-/enumerator_kw/enumerator_kw.c
+++ b/ext/-test-/enumerator_kw/enumerator_kw.c
@@ -14,7 +14,8 @@ enumerator_kw(int argc, VALUE *argv, VALUE self)
}
void
-Init_enumerator_kw(void) {
+Init_enumerator_kw(void)
+{
VALUE module = rb_define_module("Bug");
module = rb_define_module_under(module, "EnumeratorKw");
rb_define_method(module, "m", enumerator_kw, -1);
diff --git a/ext/-test-/eval/eval.c b/ext/-test-/eval/eval.c
new file mode 100644
index 0000000000..983468fc34
--- /dev/null
+++ b/ext/-test-/eval/eval.c
@@ -0,0 +1,13 @@
+#include "ruby/ruby.h"
+
+static VALUE
+eval_string(VALUE self, VALUE str)
+{
+ return rb_eval_string(StringValueCStr(str));
+}
+
+void
+Init_eval(void)
+{
+ rb_define_global_function("rb_eval_string", eval_string, 1);
+}
diff --git a/ext/-test-/eval/extconf.rb b/ext/-test-/eval/extconf.rb
new file mode 100644
index 0000000000..cdbf6a8597
--- /dev/null
+++ b/ext/-test-/eval/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('-test-/eval')
diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend
index d921c68120..e00f0b279d 100644
--- a/ext/-test-/exception/depend
+++ b/ext/-test-/exception/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
dataerror.o: $(RUBY_EXTCONF_H)
dataerror.o: $(arch_hdrdir)/ruby/config.h
+dataerror.o: $(hdrdir)/ruby/assert.h
+dataerror.o: $(hdrdir)/ruby/backward.h
+dataerror.o: $(hdrdir)/ruby/backward/2/assume.h
+dataerror.o: $(hdrdir)/ruby/backward/2/attributes.h
+dataerror.o: $(hdrdir)/ruby/backward/2/bool.h
+dataerror.o: $(hdrdir)/ruby/backward/2/inttypes.h
+dataerror.o: $(hdrdir)/ruby/backward/2/limits.h
+dataerror.o: $(hdrdir)/ruby/backward/2/long_long.h
+dataerror.o: $(hdrdir)/ruby/backward/2/stdalign.h
+dataerror.o: $(hdrdir)/ruby/backward/2/stdarg.h
+dataerror.o: $(hdrdir)/ruby/defines.h
+dataerror.o: $(hdrdir)/ruby/intern.h
+dataerror.o: $(hdrdir)/ruby/internal/abi.h
dataerror.o: $(hdrdir)/ruby/internal/anyargs.h
dataerror.o: $(hdrdir)/ruby/internal/arithmetic.h
dataerror.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
dataerror.o: $(hdrdir)/ruby/ruby.h
dataerror.o: $(hdrdir)/ruby/st.h
@@ -161,6 +161,20 @@ 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/assert.h
+enc_raise.o: $(hdrdir)/ruby/backward.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/stdarg.h
+enc_raise.o: $(hdrdir)/ruby/defines.h
+enc_raise.o: $(hdrdir)/ruby/encoding.h
+enc_raise.o: $(hdrdir)/ruby/intern.h
+enc_raise.o: $(hdrdir)/ruby/internal/abi.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
@@ -230,6 +244,15 @@ enc_raise.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
enc_raise.o: $(hdrdir)/ruby/internal/ctype.h
enc_raise.o: $(hdrdir)/ruby/internal/dllexport.h
enc_raise.o: $(hdrdir)/ruby/internal/dosish.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_raise.o: $(hdrdir)/ruby/internal/encoding/transcode.h
enc_raise.o: $(hdrdir)/ruby/internal/error.h
enc_raise.o: $(hdrdir)/ruby/internal/eval.h
enc_raise.o: $(hdrdir)/ruby/internal/event.h
@@ -300,20 +323,6 @@ 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
enc_raise.o: $(hdrdir)/ruby/missing.h
enc_raise.o: $(hdrdir)/ruby/onigmo.h
enc_raise.o: $(hdrdir)/ruby/oniguruma.h
@@ -324,6 +333,19 @@ 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/assert.h
+ensured.o: $(hdrdir)/ruby/backward.h
+ensured.o: $(hdrdir)/ruby/backward/2/assume.h
+ensured.o: $(hdrdir)/ruby/backward/2/attributes.h
+ensured.o: $(hdrdir)/ruby/backward/2/bool.h
+ensured.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ensured.o: $(hdrdir)/ruby/backward/2/limits.h
+ensured.o: $(hdrdir)/ruby/backward/2/long_long.h
+ensured.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ensured.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ensured.o: $(hdrdir)/ruby/defines.h
+ensured.o: $(hdrdir)/ruby/intern.h
+ensured.o: $(hdrdir)/ruby/internal/abi.h
ensured.o: $(hdrdir)/ruby/internal/anyargs.h
ensured.o: $(hdrdir)/ruby/internal/arithmetic.h
ensured.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -463,19 +485,6 @@ 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
ensured.o: $(hdrdir)/ruby/ruby.h
ensured.o: $(hdrdir)/ruby/st.h
@@ -484,6 +493,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -623,19 +645,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend
index 79ac18fd9f..5b1adb6607 100644
--- a/ext/-test-/fatal/depend
+++ b/ext/-test-/fatal/depend
@@ -2,6 +2,19 @@
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/assert.h
+rb_fatal.o: $(hdrdir)/ruby/backward.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_fatal.o: $(hdrdir)/ruby/defines.h
+rb_fatal.o: $(hdrdir)/ruby/intern.h
+rb_fatal.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
rb_fatal.o: $(hdrdir)/ruby/ruby.h
rb_fatal.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend
index 26f4f82899..f0fffc2485 100644
--- a/ext/-test-/file/depend
+++ b/ext/-test-/file/depend
@@ -1,6 +1,20 @@
# AUTOGENERATED DEPENDENCIES START
fs.o: $(RUBY_EXTCONF_H)
fs.o: $(arch_hdrdir)/ruby/config.h
+fs.o: $(hdrdir)/ruby/assert.h
+fs.o: $(hdrdir)/ruby/backward.h
+fs.o: $(hdrdir)/ruby/backward/2/assume.h
+fs.o: $(hdrdir)/ruby/backward/2/attributes.h
+fs.o: $(hdrdir)/ruby/backward/2/bool.h
+fs.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fs.o: $(hdrdir)/ruby/backward/2/limits.h
+fs.o: $(hdrdir)/ruby/backward/2/long_long.h
+fs.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fs.o: $(hdrdir)/ruby/backward/2/stdarg.h
+fs.o: $(hdrdir)/ruby/defines.h
+fs.o: $(hdrdir)/ruby/encoding.h
+fs.o: $(hdrdir)/ruby/intern.h
+fs.o: $(hdrdir)/ruby/internal/abi.h
fs.o: $(hdrdir)/ruby/internal/anyargs.h
fs.o: $(hdrdir)/ruby/internal/arithmetic.h
fs.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -70,6 +84,15 @@ fs.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
fs.o: $(hdrdir)/ruby/internal/ctype.h
fs.o: $(hdrdir)/ruby/internal/dllexport.h
fs.o: $(hdrdir)/ruby/internal/dosish.h
+fs.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+fs.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+fs.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+fs.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+fs.o: $(hdrdir)/ruby/internal/encoding/re.h
+fs.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+fs.o: $(hdrdir)/ruby/internal/encoding/string.h
+fs.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+fs.o: $(hdrdir)/ruby/internal/encoding/transcode.h
fs.o: $(hdrdir)/ruby/internal/error.h
fs.o: $(hdrdir)/ruby/internal/eval.h
fs.o: $(hdrdir)/ruby/internal/event.h
@@ -140,20 +163,6 @@ 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
fs.o: $(hdrdir)/ruby/io.h
fs.o: $(hdrdir)/ruby/missing.h
fs.o: $(hdrdir)/ruby/onigmo.h
@@ -165,6 +174,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -304,19 +326,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -324,6 +333,20 @@ 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/assert.h
+stat.o: $(hdrdir)/ruby/backward.h
+stat.o: $(hdrdir)/ruby/backward/2/assume.h
+stat.o: $(hdrdir)/ruby/backward/2/attributes.h
+stat.o: $(hdrdir)/ruby/backward/2/bool.h
+stat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stat.o: $(hdrdir)/ruby/backward/2/limits.h
+stat.o: $(hdrdir)/ruby/backward/2/long_long.h
+stat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stat.o: $(hdrdir)/ruby/defines.h
+stat.o: $(hdrdir)/ruby/encoding.h
+stat.o: $(hdrdir)/ruby/intern.h
+stat.o: $(hdrdir)/ruby/internal/abi.h
stat.o: $(hdrdir)/ruby/internal/anyargs.h
stat.o: $(hdrdir)/ruby/internal/arithmetic.h
stat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -393,6 +416,15 @@ stat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
stat.o: $(hdrdir)/ruby/internal/ctype.h
stat.o: $(hdrdir)/ruby/internal/dllexport.h
stat.o: $(hdrdir)/ruby/internal/dosish.h
+stat.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+stat.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+stat.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+stat.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+stat.o: $(hdrdir)/ruby/internal/encoding/re.h
+stat.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+stat.o: $(hdrdir)/ruby/internal/encoding/string.h
+stat.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+stat.o: $(hdrdir)/ruby/internal/encoding/transcode.h
stat.o: $(hdrdir)/ruby/internal/error.h
stat.o: $(hdrdir)/ruby/internal/eval.h
stat.o: $(hdrdir)/ruby/internal/event.h
@@ -463,20 +495,6 @@ 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
stat.o: $(hdrdir)/ruby/io.h
stat.o: $(hdrdir)/ruby/missing.h
stat.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/-test-/file/fs.c b/ext/-test-/file/fs.c
index 63d2356d76..eb17e9768e 100644
--- a/ext/-test-/file/fs.c
+++ b/ext/-test-/file/fs.c
@@ -28,7 +28,7 @@ typedef struct statvfs statfs_t;
# if defined HAVE_STRUCT_STATVFS_F_TYPE
# define HAVE_STRUCT_STATFS_T_F_TYPE 1
# endif
-#elif defined(HAVE_STRUCT_STATVFS_F_BASETYPE) /* AIX, HP-UX, Solaris */
+#elif defined(HAVE_STRUCT_STATVFS_F_BASETYPE) /* AIX, Solaris */
typedef struct statvfs statfs_t;
# define STATFS(f, s) statvfs((f), (s))
# define HAVE_STRUCT_STATFS_T_F_FSTYPENAME 1
@@ -54,24 +54,24 @@ get_fsname(VALUE self, VALUE str)
FilePathValue(str);
str = rb_str_encode_ospath(str);
if (STATFS(StringValueCStr(str), &st) == -1) {
- rb_sys_fail_str(str);
+ rb_sys_fail_str(str);
}
# ifdef HAVE_STRUCT_STATFS_T_F_FSTYPENAME
if (st.f_fstypename[0])
- return CSTR(st.f_fstypename);
+ return CSTR(st.f_fstypename);
# endif
# ifdef HAVE_STRUCT_STATFS_T_F_TYPE
switch (st.f_type) {
case 0x9123683E: /* BTRFS_SUPER_MAGIC */
- return CSTR("btrfs");
+ return CSTR("btrfs");
case 0x7461636f: /* OCFS2_SUPER_MAGIC */
- return CSTR("ocfs");
+ return CSTR("ocfs");
case 0xEF53: /* EXT2_SUPER_MAGIC EXT3_SUPER_MAGIC EXT4_SUPER_MAGIC */
- return CSTR("ext4");
+ return CSTR("ext4");
case 0x58465342: /* XFS_SUPER_MAGIC */
- return CSTR("xfs");
+ return CSTR("xfs");
case 0x01021994: /* TMPFS_MAGIC */
- return CSTR("tmpfs");
+ return CSTR("tmpfs");
}
# endif
#endif
diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend
index 55b014e8a0..9391a445a3 100644
--- a/ext/-test-/float/depend
+++ b/ext/-test-/float/depend
@@ -5,6 +5,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -144,19 +157,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -165,6 +165,19 @@ 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/assert.h
+nextafter.o: $(hdrdir)/ruby/backward.h
+nextafter.o: $(hdrdir)/ruby/backward/2/assume.h
+nextafter.o: $(hdrdir)/ruby/backward/2/attributes.h
+nextafter.o: $(hdrdir)/ruby/backward/2/bool.h
+nextafter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nextafter.o: $(hdrdir)/ruby/backward/2/limits.h
+nextafter.o: $(hdrdir)/ruby/backward/2/long_long.h
+nextafter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nextafter.o: $(hdrdir)/ruby/backward/2/stdarg.h
+nextafter.o: $(hdrdir)/ruby/defines.h
+nextafter.o: $(hdrdir)/ruby/intern.h
+nextafter.o: $(hdrdir)/ruby/internal/abi.h
nextafter.o: $(hdrdir)/ruby/internal/anyargs.h
nextafter.o: $(hdrdir)/ruby/internal/arithmetic.h
nextafter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -304,19 +317,6 @@ 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
nextafter.o: $(hdrdir)/ruby/ruby.h
nextafter.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend
index 412ad522d5..24e8c54bd9 100644
--- a/ext/-test-/funcall/depend
+++ b/ext/-test-/funcall/depend
@@ -2,6 +2,19 @@
funcall.o: $(RUBY_EXTCONF_H)
funcall.o: $(arch_hdrdir)/ruby/config.h
funcall.o: $(hdrdir)/ruby.h
+funcall.o: $(hdrdir)/ruby/assert.h
+funcall.o: $(hdrdir)/ruby/backward.h
+funcall.o: $(hdrdir)/ruby/backward/2/assume.h
+funcall.o: $(hdrdir)/ruby/backward/2/attributes.h
+funcall.o: $(hdrdir)/ruby/backward/2/bool.h
+funcall.o: $(hdrdir)/ruby/backward/2/inttypes.h
+funcall.o: $(hdrdir)/ruby/backward/2/limits.h
+funcall.o: $(hdrdir)/ruby/backward/2/long_long.h
+funcall.o: $(hdrdir)/ruby/backward/2/stdalign.h
+funcall.o: $(hdrdir)/ruby/backward/2/stdarg.h
+funcall.o: $(hdrdir)/ruby/defines.h
+funcall.o: $(hdrdir)/ruby/intern.h
+funcall.o: $(hdrdir)/ruby/internal/abi.h
funcall.o: $(hdrdir)/ruby/internal/anyargs.h
funcall.o: $(hdrdir)/ruby/internal/arithmetic.h
funcall.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
funcall.o: $(hdrdir)/ruby/ruby.h
funcall.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/funcall/funcall.c b/ext/-test-/funcall/funcall.c
index 43521bf2e9..a68d6de255 100644
--- a/ext/-test-/funcall/funcall.c
+++ b/ext/-test-/funcall/funcall.c
@@ -47,17 +47,17 @@ Init_funcall(void)
VALUE cRelay = rb_define_module_under(cTestFuncall, "Relay");
rb_define_singleton_method(cRelay,
- "with_funcall2",
- with_funcall2,
- -1);
+ "with_funcall2",
+ with_funcall2,
+ -1);
rb_define_singleton_method(cRelay,
"with_funcall_passing_block_kw",
with_funcall_passing_block_kw,
-1);
rb_define_singleton_method(cRelay,
- "with_funcall_passing_block",
- with_funcall_passing_block,
- -1);
+ "with_funcall_passing_block",
+ with_funcall_passing_block,
+ -1);
rb_define_singleton_method(cRelay,
"with_funcallv_public_kw",
with_funcallv_public_kw,
diff --git a/ext/-test-/gvl/call_without_gvl/call_without_gvl.c b/ext/-test-/gvl/call_without_gvl/call_without_gvl.c
index 233635421b..97946e925d 100644
--- a/ext/-test-/gvl/call_without_gvl/call_without_gvl.c
+++ b/ext/-test-/gvl/call_without_gvl/call_without_gvl.c
@@ -17,7 +17,7 @@ thread_runnable_sleep(VALUE thread, VALUE timeout)
struct timeval timeval;
if (NIL_P(timeout)) {
- rb_raise(rb_eArgError, "timeout must be non nil");
+ rb_raise(rb_eArgError, "timeout must be non nil");
}
timeval = rb_time_interval(timeout);
diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend
index e6ecd43ef7..cd184aa01c 100644
--- a/ext/-test-/gvl/call_without_gvl/depend
+++ b/ext/-test-/gvl/call_without_gvl/depend
@@ -1,6 +1,19 @@
# 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/assert.h
+call_without_gvl.o: $(hdrdir)/ruby/backward.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/assume.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/attributes.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/bool.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/limits.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/long_long.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+call_without_gvl.o: $(hdrdir)/ruby/defines.h
+call_without_gvl.o: $(hdrdir)/ruby/intern.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/abi.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
@@ -140,19 +153,6 @@ 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
call_without_gvl.o: $(hdrdir)/ruby/ruby.h
call_without_gvl.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend
index fe52e9bb1a..a8bc47e640 100644
--- a/ext/-test-/hash/depend
+++ b/ext/-test-/hash/depend
@@ -2,6 +2,19 @@
delete.o: $(RUBY_EXTCONF_H)
delete.o: $(arch_hdrdir)/ruby/config.h
delete.o: $(hdrdir)/ruby.h
+delete.o: $(hdrdir)/ruby/assert.h
+delete.o: $(hdrdir)/ruby/backward.h
+delete.o: $(hdrdir)/ruby/backward/2/assume.h
+delete.o: $(hdrdir)/ruby/backward/2/attributes.h
+delete.o: $(hdrdir)/ruby/backward/2/bool.h
+delete.o: $(hdrdir)/ruby/backward/2/inttypes.h
+delete.o: $(hdrdir)/ruby/backward/2/limits.h
+delete.o: $(hdrdir)/ruby/backward/2/long_long.h
+delete.o: $(hdrdir)/ruby/backward/2/stdalign.h
+delete.o: $(hdrdir)/ruby/backward/2/stdarg.h
+delete.o: $(hdrdir)/ruby/defines.h
+delete.o: $(hdrdir)/ruby/intern.h
+delete.o: $(hdrdir)/ruby/internal/abi.h
delete.o: $(hdrdir)/ruby/internal/anyargs.h
delete.o: $(hdrdir)/ruby/internal/arithmetic.h
delete.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
delete.o: $(hdrdir)/ruby/ruby.h
delete.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -301,19 +314,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend
index 825110658b..b12159f308 100644
--- a/ext/-test-/integer/depend
+++ b/ext/-test-/integer/depend
@@ -1,7 +1,20 @@
# AUTOGENERATED DEPENDENCIES START
core_ext.o: $(RUBY_EXTCONF_H)
core_ext.o: $(arch_hdrdir)/ruby/config.h
-core_ext.o: $(hdrdir)/ruby.h
+core_ext.o: $(hdrdir)/ruby/assert.h
+core_ext.o: $(hdrdir)/ruby/backward.h
+core_ext.o: $(hdrdir)/ruby/backward/2/assume.h
+core_ext.o: $(hdrdir)/ruby/backward/2/attributes.h
+core_ext.o: $(hdrdir)/ruby/backward/2/bool.h
+core_ext.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+core_ext.o: $(hdrdir)/ruby/backward/2/inttypes.h
+core_ext.o: $(hdrdir)/ruby/backward/2/limits.h
+core_ext.o: $(hdrdir)/ruby/backward/2/long_long.h
+core_ext.o: $(hdrdir)/ruby/backward/2/stdalign.h
+core_ext.o: $(hdrdir)/ruby/backward/2/stdarg.h
+core_ext.o: $(hdrdir)/ruby/defines.h
+core_ext.o: $(hdrdir)/ruby/intern.h
+core_ext.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,24 +154,10 @@ 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
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
@@ -171,6 +170,19 @@ core_ext.o: core_ext.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -310,19 +322,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -331,6 +330,19 @@ 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/assert.h
+my_integer.o: $(hdrdir)/ruby/backward.h
+my_integer.o: $(hdrdir)/ruby/backward/2/assume.h
+my_integer.o: $(hdrdir)/ruby/backward/2/attributes.h
+my_integer.o: $(hdrdir)/ruby/backward/2/bool.h
+my_integer.o: $(hdrdir)/ruby/backward/2/inttypes.h
+my_integer.o: $(hdrdir)/ruby/backward/2/limits.h
+my_integer.o: $(hdrdir)/ruby/backward/2/long_long.h
+my_integer.o: $(hdrdir)/ruby/backward/2/stdalign.h
+my_integer.o: $(hdrdir)/ruby/backward/2/stdarg.h
+my_integer.o: $(hdrdir)/ruby/defines.h
+my_integer.o: $(hdrdir)/ruby/intern.h
+my_integer.o: $(hdrdir)/ruby/internal/abi.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
@@ -470,19 +482,6 @@ 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
my_integer.o: $(hdrdir)/ruby/ruby.h
my_integer.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend
index 26d4c01aa2..308956550c 100644
--- a/ext/-test-/iseq_load/depend
+++ b/ext/-test-/iseq_load/depend
@@ -2,6 +2,19 @@
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/assert.h
+iseq_load.o: $(hdrdir)/ruby/backward.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/assume.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/attributes.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/bool.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/inttypes.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/limits.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/long_long.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/stdalign.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/stdarg.h
+iseq_load.o: $(hdrdir)/ruby/defines.h
+iseq_load.o: $(hdrdir)/ruby/intern.h
+iseq_load.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
iseq_load.o: $(hdrdir)/ruby/ruby.h
iseq_load.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend
index 85ca8be992..d14c164cd4 100644
--- a/ext/-test-/iter/depend
+++ b/ext/-test-/iter/depend
@@ -2,6 +2,19 @@
break.o: $(RUBY_EXTCONF_H)
break.o: $(arch_hdrdir)/ruby/config.h
break.o: $(hdrdir)/ruby.h
+break.o: $(hdrdir)/ruby/assert.h
+break.o: $(hdrdir)/ruby/backward.h
+break.o: $(hdrdir)/ruby/backward/2/assume.h
+break.o: $(hdrdir)/ruby/backward/2/attributes.h
+break.o: $(hdrdir)/ruby/backward/2/bool.h
+break.o: $(hdrdir)/ruby/backward/2/inttypes.h
+break.o: $(hdrdir)/ruby/backward/2/limits.h
+break.o: $(hdrdir)/ruby/backward/2/long_long.h
+break.o: $(hdrdir)/ruby/backward/2/stdalign.h
+break.o: $(hdrdir)/ruby/backward/2/stdarg.h
+break.o: $(hdrdir)/ruby/defines.h
+break.o: $(hdrdir)/ruby/intern.h
+break.o: $(hdrdir)/ruby/internal/abi.h
break.o: $(hdrdir)/ruby/internal/anyargs.h
break.o: $(hdrdir)/ruby/internal/arithmetic.h
break.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
break.o: $(hdrdir)/ruby/ruby.h
break.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -301,19 +314,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -322,6 +322,19 @@ 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/assert.h
+yield.o: $(hdrdir)/ruby/backward.h
+yield.o: $(hdrdir)/ruby/backward/2/assume.h
+yield.o: $(hdrdir)/ruby/backward/2/attributes.h
+yield.o: $(hdrdir)/ruby/backward/2/bool.h
+yield.o: $(hdrdir)/ruby/backward/2/inttypes.h
+yield.o: $(hdrdir)/ruby/backward/2/limits.h
+yield.o: $(hdrdir)/ruby/backward/2/long_long.h
+yield.o: $(hdrdir)/ruby/backward/2/stdalign.h
+yield.o: $(hdrdir)/ruby/backward/2/stdarg.h
+yield.o: $(hdrdir)/ruby/defines.h
+yield.o: $(hdrdir)/ruby/intern.h
+yield.o: $(hdrdir)/ruby/internal/abi.h
yield.o: $(hdrdir)/ruby/internal/anyargs.h
yield.o: $(hdrdir)/ruby/internal/arithmetic.h
yield.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -461,19 +474,6 @@ 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
yield.o: $(hdrdir)/ruby/ruby.h
yield.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/load/dot.dot/depend b/ext/-test-/load/dot.dot/depend
index a0445e288b..d8b8937c3c 100644
--- a/ext/-test-/load/dot.dot/depend
+++ b/ext/-test-/load/dot.dot/depend
@@ -1,3 +1,162 @@
# AUTOGENERATED DEPENDENCIES START
+dot.dot.o: $(RUBY_EXTCONF_H)
+dot.dot.o: $(arch_hdrdir)/ruby/config.h
+dot.dot.o: $(hdrdir)/ruby.h
+dot.dot.o: $(hdrdir)/ruby/assert.h
+dot.dot.o: $(hdrdir)/ruby/backward.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/assume.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/attributes.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/bool.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/inttypes.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/limits.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/long_long.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/stdalign.h
+dot.dot.o: $(hdrdir)/ruby/backward/2/stdarg.h
+dot.dot.o: $(hdrdir)/ruby/defines.h
+dot.dot.o: $(hdrdir)/ruby/intern.h
+dot.dot.o: $(hdrdir)/ruby/internal/abi.h
+dot.dot.o: $(hdrdir)/ruby/internal/anyargs.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+dot.dot.o: $(hdrdir)/ruby/internal/assume.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/artificial.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/cold.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/const.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/error.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/format.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noalias.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noinline.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/pure.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/restrict.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/warning.h
+dot.dot.o: $(hdrdir)/ruby/internal/attr/weakref.h
+dot.dot.o: $(hdrdir)/ruby/internal/cast.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+dot.dot.o: $(hdrdir)/ruby/internal/compiler_since.h
+dot.dot.o: $(hdrdir)/ruby/internal/config.h
+dot.dot.o: $(hdrdir)/ruby/internal/constant_p.h
+dot.dot.o: $(hdrdir)/ruby/internal/core.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rarray.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rbasic.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rbignum.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rclass.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rdata.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rfile.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rhash.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/robject.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rregexp.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rstring.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rstruct.h
+dot.dot.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+dot.dot.o: $(hdrdir)/ruby/internal/ctype.h
+dot.dot.o: $(hdrdir)/ruby/internal/dllexport.h
+dot.dot.o: $(hdrdir)/ruby/internal/dosish.h
+dot.dot.o: $(hdrdir)/ruby/internal/error.h
+dot.dot.o: $(hdrdir)/ruby/internal/eval.h
+dot.dot.o: $(hdrdir)/ruby/internal/event.h
+dot.dot.o: $(hdrdir)/ruby/internal/fl_type.h
+dot.dot.o: $(hdrdir)/ruby/internal/gc.h
+dot.dot.o: $(hdrdir)/ruby/internal/glob.h
+dot.dot.o: $(hdrdir)/ruby/internal/globals.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/builtin.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/extension.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/feature.h
+dot.dot.o: $(hdrdir)/ruby/internal/has/warning.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/array.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/bignum.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/class.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/compar.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/complex.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/cont.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/dir.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/enum.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/error.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/eval.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/file.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/gc.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/hash.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/io.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/load.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/marshal.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/numeric.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/object.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/parse.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/proc.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/process.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/random.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/range.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/rational.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/re.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/ruby.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/select.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/signal.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/string.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/struct.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/thread.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/time.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/variable.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/vm.h
+dot.dot.o: $(hdrdir)/ruby/internal/interpreter.h
+dot.dot.o: $(hdrdir)/ruby/internal/iterator.h
+dot.dot.o: $(hdrdir)/ruby/internal/memory.h
+dot.dot.o: $(hdrdir)/ruby/internal/method.h
+dot.dot.o: $(hdrdir)/ruby/internal/module.h
+dot.dot.o: $(hdrdir)/ruby/internal/newobj.h
+dot.dot.o: $(hdrdir)/ruby/internal/rgengc.h
+dot.dot.o: $(hdrdir)/ruby/internal/scan_args.h
+dot.dot.o: $(hdrdir)/ruby/internal/special_consts.h
+dot.dot.o: $(hdrdir)/ruby/internal/static_assert.h
+dot.dot.o: $(hdrdir)/ruby/internal/stdalign.h
+dot.dot.o: $(hdrdir)/ruby/internal/stdbool.h
+dot.dot.o: $(hdrdir)/ruby/internal/symbol.h
+dot.dot.o: $(hdrdir)/ruby/internal/value.h
+dot.dot.o: $(hdrdir)/ruby/internal/value_type.h
+dot.dot.o: $(hdrdir)/ruby/internal/variable.h
+dot.dot.o: $(hdrdir)/ruby/internal/warning_push.h
+dot.dot.o: $(hdrdir)/ruby/internal/xmalloc.h
+dot.dot.o: $(hdrdir)/ruby/missing.h
+dot.dot.o: $(hdrdir)/ruby/ruby.h
+dot.dot.o: $(hdrdir)/ruby/st.h
+dot.dot.o: $(hdrdir)/ruby/subst.h
dot.dot.o: dot.dot.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/dot.dot/dot.dot.c b/ext/-test-/load/dot.dot/dot.dot.c
index 936d28931a..ce7563bf8d 100644
--- a/ext/-test-/load/dot.dot/dot.dot.c
+++ b/ext/-test-/load/dot.dot/dot.dot.c
@@ -1 +1,3 @@
+#include "ruby.h"
+
void Init_dot(void) {}
diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend
index 6eb2ea987b..dd4ee71b62 100644
--- a/ext/-test-/load/protect/depend
+++ b/ext/-test-/load/protect/depend
@@ -2,6 +2,19 @@
protect.o: $(RUBY_EXTCONF_H)
protect.o: $(arch_hdrdir)/ruby/config.h
protect.o: $(hdrdir)/ruby.h
+protect.o: $(hdrdir)/ruby/assert.h
+protect.o: $(hdrdir)/ruby/backward.h
+protect.o: $(hdrdir)/ruby/backward/2/assume.h
+protect.o: $(hdrdir)/ruby/backward/2/attributes.h
+protect.o: $(hdrdir)/ruby/backward/2/bool.h
+protect.o: $(hdrdir)/ruby/backward/2/inttypes.h
+protect.o: $(hdrdir)/ruby/backward/2/limits.h
+protect.o: $(hdrdir)/ruby/backward/2/long_long.h
+protect.o: $(hdrdir)/ruby/backward/2/stdalign.h
+protect.o: $(hdrdir)/ruby/backward/2/stdarg.h
+protect.o: $(hdrdir)/ruby/defines.h
+protect.o: $(hdrdir)/ruby/intern.h
+protect.o: $(hdrdir)/ruby/internal/abi.h
protect.o: $(hdrdir)/ruby/internal/anyargs.h
protect.o: $(hdrdir)/ruby/internal/arithmetic.h
protect.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
protect.o: $(hdrdir)/ruby/ruby.h
protect.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend
index 1fca7a7baf..2c3ecf1ab9 100644
--- a/ext/-test-/marshal/compat/depend
+++ b/ext/-test-/marshal/compat/depend
@@ -2,6 +2,19 @@
usrcompat.o: $(RUBY_EXTCONF_H)
usrcompat.o: $(arch_hdrdir)/ruby/config.h
usrcompat.o: $(hdrdir)/ruby.h
+usrcompat.o: $(hdrdir)/ruby/assert.h
+usrcompat.o: $(hdrdir)/ruby/backward.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/assume.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/attributes.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/bool.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/limits.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/long_long.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+usrcompat.o: $(hdrdir)/ruby/defines.h
+usrcompat.o: $(hdrdir)/ruby/intern.h
+usrcompat.o: $(hdrdir)/ruby/internal/abi.h
usrcompat.o: $(hdrdir)/ruby/internal/anyargs.h
usrcompat.o: $(hdrdir)/ruby/internal/arithmetic.h
usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
usrcompat.o: $(hdrdir)/ruby/ruby.h
usrcompat.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend
index 2b0f44c0d0..cacb54a1a7 100644
--- a/ext/-test-/marshal/internal_ivar/depend
+++ b/ext/-test-/marshal/internal_ivar/depend
@@ -2,6 +2,19 @@
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/assert.h
+internal_ivar.o: $(hdrdir)/ruby/backward.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/assume.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/attributes.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/bool.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/inttypes.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/limits.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/long_long.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/stdalign.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/stdarg.h
+internal_ivar.o: $(hdrdir)/ruby/defines.h
+internal_ivar.o: $(hdrdir)/ruby/intern.h
+internal_ivar.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
internal_ivar.o: $(hdrdir)/ruby/ruby.h
internal_ivar.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/marshal/internal_ivar/internal_ivar.c b/ext/-test-/marshal/internal_ivar/internal_ivar.c
index de0cf711aa..b2188f737a 100644
--- a/ext/-test-/marshal/internal_ivar/internal_ivar.c
+++ b/ext/-test-/marshal/internal_ivar/internal_ivar.c
@@ -36,10 +36,7 @@ Init_internal_ivar(void)
VALUE newclass = rb_define_class_under(mMarshal, "InternalIVar", rb_cObject);
id_normal_ivar = rb_intern_const("normal");
-#if 0
- /* leave id_internal_ivar being 0 */
- id_internal_ivar = rb_make_internal_id();
-#endif
+ id_internal_ivar = rb_intern_const("K");
id_encoding_short = rb_intern_const("E");
rb_define_method(newclass, "initialize", init, 3);
rb_define_method(newclass, "normal", get_normal, 0);
diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend
index 239798bacf..717101cbcf 100644
--- a/ext/-test-/marshal/usr/depend
+++ b/ext/-test-/marshal/usr/depend
@@ -2,6 +2,19 @@
usrmarshal.o: $(RUBY_EXTCONF_H)
usrmarshal.o: $(arch_hdrdir)/ruby/config.h
usrmarshal.o: $(hdrdir)/ruby.h
+usrmarshal.o: $(hdrdir)/ruby/assert.h
+usrmarshal.o: $(hdrdir)/ruby/backward.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/assume.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/attributes.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/bool.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/limits.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/long_long.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/stdarg.h
+usrmarshal.o: $(hdrdir)/ruby/defines.h
+usrmarshal.o: $(hdrdir)/ruby/intern.h
+usrmarshal.o: $(hdrdir)/ruby/internal/abi.h
usrmarshal.o: $(hdrdir)/ruby/internal/anyargs.h
usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic.h
usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
usrmarshal.o: $(hdrdir)/ruby/ruby.h
usrmarshal.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/memory_status/depend b/ext/-test-/memory_status/depend
index f8652cb316..a65fe66ae3 100644
--- a/ext/-test-/memory_status/depend
+++ b/ext/-test-/memory_status/depend
@@ -7,7 +7,6 @@ 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
@@ -15,6 +14,7 @@ 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/abi.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
diff --git a/ext/-test-/memory_status/memory_status.c b/ext/-test-/memory_status/memory_status.c
index afacbee785..f124c97ca1 100644
--- a/ext/-test-/memory_status/memory_status.c
+++ b/ext/-test-/memory_status/memory_status.c
@@ -34,7 +34,7 @@ read_status(VALUE self)
taskinfo.virtual_size = 0;
taskinfo.resident_size = 0;
error = task_info(mach_task_self(), flavor,
- (task_info_t)&taskinfo, &out_count);
+ (task_info_t)&taskinfo, &out_count);
if (error != KERN_SUCCESS) return Qnil;
#ifndef ULL2NUM
/* "long long" does not exist here, use size_t instead. */
@@ -50,7 +50,7 @@ read_status(VALUE self)
PROCESS_MEMORY_COUNTERS c;
c.cb = sizeof(c);
if (!GetProcessMemoryInfo(GetCurrentProcess(), &c, c.cb))
- return Qnil;
+ return Qnil;
size = SIZET2NUM(c.PagefileUsage);
rss = SIZET2NUM(c.WorkingSetSize);
peak = SIZET2NUM(c.PeakWorkingSetSize);
@@ -68,13 +68,13 @@ Init_memory_status(void)
{
VALUE mMemory = rb_define_module("Memory");
cMemoryStatus =
- rb_struct_define_under(mMemory, "Status", "size",
+ rb_struct_define_under(mMemory, "Status", "size",
#ifdef HAVE_RSS
- "rss",
+ "rss",
#endif
#ifdef HAVE_PEAK
- "peak",
+ "peak",
#endif
- (char *)NULL);
+ (char *)NULL);
rb_define_method(cMemoryStatus, "_update", read_status, 0);
}
diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend
index 1219888768..7ce2d0374c 100644
--- a/ext/-test-/memory_view/depend
+++ b/ext/-test-/memory_view/depend
@@ -7,7 +7,6 @@ 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
@@ -15,6 +14,7 @@ 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/abi.h
memory_view.o: $(hdrdir)/ruby/internal/anyargs.h
memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h
memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h
diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend
index 1aef2cd182..85cf4d174a 100644
--- a/ext/-test-/method/depend
+++ b/ext/-test-/method/depend
@@ -2,6 +2,19 @@
arity.o: $(RUBY_EXTCONF_H)
arity.o: $(arch_hdrdir)/ruby/config.h
arity.o: $(hdrdir)/ruby.h
+arity.o: $(hdrdir)/ruby/assert.h
+arity.o: $(hdrdir)/ruby/backward.h
+arity.o: $(hdrdir)/ruby/backward/2/assume.h
+arity.o: $(hdrdir)/ruby/backward/2/attributes.h
+arity.o: $(hdrdir)/ruby/backward/2/bool.h
+arity.o: $(hdrdir)/ruby/backward/2/inttypes.h
+arity.o: $(hdrdir)/ruby/backward/2/limits.h
+arity.o: $(hdrdir)/ruby/backward/2/long_long.h
+arity.o: $(hdrdir)/ruby/backward/2/stdalign.h
+arity.o: $(hdrdir)/ruby/backward/2/stdarg.h
+arity.o: $(hdrdir)/ruby/defines.h
+arity.o: $(hdrdir)/ruby/intern.h
+arity.o: $(hdrdir)/ruby/internal/abi.h
arity.o: $(hdrdir)/ruby/internal/anyargs.h
arity.o: $(hdrdir)/ruby/internal/arithmetic.h
arity.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
arity.o: $(hdrdir)/ruby/ruby.h
arity.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -301,19 +314,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend
index 506795a137..2303f47594 100644
--- a/ext/-test-/notimplement/depend
+++ b/ext/-test-/notimplement/depend
@@ -2,6 +2,19 @@
bug.o: $(RUBY_EXTCONF_H)
bug.o: $(arch_hdrdir)/ruby/config.h
bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/assert.h
+bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug.o: $(hdrdir)/ruby/defines.h
+bug.o: $(hdrdir)/ruby/intern.h
+bug.o: $(hdrdir)/ruby/internal/abi.h
bug.o: $(hdrdir)/ruby/internal/anyargs.h
bug.o: $(hdrdir)/ruby/internal/arithmetic.h
bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
bug.o: $(hdrdir)/ruby/ruby.h
bug.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend
index 692423ac63..a3283838dd 100644
--- a/ext/-test-/num2int/depend
+++ b/ext/-test-/num2int/depend
@@ -2,6 +2,19 @@
num2int.o: $(RUBY_EXTCONF_H)
num2int.o: $(arch_hdrdir)/ruby/config.h
num2int.o: $(hdrdir)/ruby.h
+num2int.o: $(hdrdir)/ruby/assert.h
+num2int.o: $(hdrdir)/ruby/backward.h
+num2int.o: $(hdrdir)/ruby/backward/2/assume.h
+num2int.o: $(hdrdir)/ruby/backward/2/attributes.h
+num2int.o: $(hdrdir)/ruby/backward/2/bool.h
+num2int.o: $(hdrdir)/ruby/backward/2/inttypes.h
+num2int.o: $(hdrdir)/ruby/backward/2/limits.h
+num2int.o: $(hdrdir)/ruby/backward/2/long_long.h
+num2int.o: $(hdrdir)/ruby/backward/2/stdalign.h
+num2int.o: $(hdrdir)/ruby/backward/2/stdarg.h
+num2int.o: $(hdrdir)/ruby/defines.h
+num2int.o: $(hdrdir)/ruby/intern.h
+num2int.o: $(hdrdir)/ruby/internal/abi.h
num2int.o: $(hdrdir)/ruby/internal/anyargs.h
num2int.o: $(hdrdir)/ruby/internal/arithmetic.h
num2int.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
num2int.o: $(hdrdir)/ruby/ruby.h
num2int.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/num2int/num2int.c b/ext/-test-/num2int/num2int.c
index 3aec3ccf3b..63a441fda6 100644
--- a/ext/-test-/num2int/num2int.c
+++ b/ext/-test-/num2int/num2int.c
@@ -4,7 +4,7 @@ static VALUE
test_num2short(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%d", NUM2SHORT(num));
+ snprintf(buf, sizeof(buf), "%d", NUM2SHORT(num));
return rb_str_new_cstr(buf);
}
@@ -12,7 +12,7 @@ static VALUE
test_num2ushort(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%u", NUM2USHORT(num));
+ snprintf(buf, sizeof(buf), "%u", NUM2USHORT(num));
return rb_str_new_cstr(buf);
}
@@ -20,7 +20,7 @@ static VALUE
test_num2int(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%d", NUM2INT(num));
+ snprintf(buf, sizeof(buf), "%d", NUM2INT(num));
return rb_str_new_cstr(buf);
}
@@ -28,7 +28,7 @@ static VALUE
test_num2uint(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%u", NUM2UINT(num));
+ snprintf(buf, sizeof(buf), "%u", NUM2UINT(num));
return rb_str_new_cstr(buf);
}
@@ -36,7 +36,7 @@ static VALUE
test_num2long(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%ld", NUM2LONG(num));
+ snprintf(buf, sizeof(buf), "%ld", NUM2LONG(num));
return rb_str_new_cstr(buf);
}
@@ -44,7 +44,7 @@ static VALUE
test_num2ulong(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%lu", NUM2ULONG(num));
+ snprintf(buf, sizeof(buf), "%lu", NUM2ULONG(num));
return rb_str_new_cstr(buf);
}
@@ -53,7 +53,7 @@ static VALUE
test_num2ll(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%"PRI_LL_PREFIX"d", NUM2LL(num));
+ snprintf(buf, sizeof(buf), "%"PRI_LL_PREFIX"d", NUM2LL(num));
return rb_str_new_cstr(buf);
}
@@ -61,7 +61,7 @@ static VALUE
test_num2ull(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%"PRI_LL_PREFIX"u", NUM2ULL(num));
+ snprintf(buf, sizeof(buf), "%"PRI_LL_PREFIX"u", NUM2ULL(num));
return rb_str_new_cstr(buf);
}
#endif
@@ -70,7 +70,7 @@ static VALUE
test_fix2short(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%d", FIX2SHORT(num));
+ snprintf(buf, sizeof(buf), "%d", FIX2SHORT(num));
return rb_str_new_cstr(buf);
}
@@ -78,7 +78,7 @@ static VALUE
test_fix2int(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%d", FIX2INT(num));
+ snprintf(buf, sizeof(buf), "%d", FIX2INT(num));
return rb_str_new_cstr(buf);
}
@@ -86,7 +86,7 @@ static VALUE
test_fix2uint(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%u", FIX2UINT(num));
+ snprintf(buf, sizeof(buf), "%u", FIX2UINT(num));
return rb_str_new_cstr(buf);
}
@@ -94,7 +94,7 @@ static VALUE
test_fix2long(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%ld", FIX2LONG(num));
+ snprintf(buf, sizeof(buf), "%ld", FIX2LONG(num));
return rb_str_new_cstr(buf);
}
@@ -102,7 +102,7 @@ static VALUE
test_fix2ulong(VALUE obj, VALUE num)
{
char buf[128];
- sprintf(buf, "%lu", FIX2ULONG(num));
+ snprintf(buf, sizeof(buf), "%lu", FIX2ULONG(num));
return rb_str_new_cstr(buf);
}
diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend
index e2bc971e4e..17f8e957c3 100644
--- a/ext/-test-/path_to_class/depend
+++ b/ext/-test-/path_to_class/depend
@@ -2,6 +2,19 @@
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/assert.h
+path_to_class.o: $(hdrdir)/ruby/backward.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/assume.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/attributes.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/bool.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/inttypes.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/limits.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/long_long.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/stdalign.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/stdarg.h
+path_to_class.o: $(hdrdir)/ruby/defines.h
+path_to_class.o: $(hdrdir)/ruby/intern.h
+path_to_class.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
path_to_class.o: $(hdrdir)/ruby/ruby.h
path_to_class.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend
index e36a6c9568..22da87f2fe 100644
--- a/ext/-test-/popen_deadlock/depend
+++ b/ext/-test-/popen_deadlock/depend
@@ -1,6 +1,20 @@
# 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/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/internal/abi.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
@@ -140,19 +154,6 @@ 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
infinite_loop_dlsym.o: $(hdrdir)/ruby/ruby.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend
index acabceb0fb..35aca7f2b0 100644
--- a/ext/-test-/postponed_job/depend
+++ b/ext/-test-/postponed_job/depend
@@ -2,6 +2,20 @@
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/assert.h
+postponed_job.o: $(hdrdir)/ruby/backward.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/assume.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/attributes.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/bool.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/inttypes.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/limits.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/long_long.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/stdalign.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/stdarg.h
+postponed_job.o: $(hdrdir)/ruby/debug.h
+postponed_job.o: $(hdrdir)/ruby/defines.h
+postponed_job.o: $(hdrdir)/ruby/intern.h
+postponed_job.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,20 +155,6 @@ 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
postponed_job.o: $(hdrdir)/ruby/missing.h
postponed_job.o: $(hdrdir)/ruby/ruby.h
postponed_job.o: $(hdrdir)/ruby/st.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 d238610d21..6dfe1fe03d 100644
--- a/ext/-test-/printf/depend
+++ b/ext/-test-/printf/depend
@@ -2,6 +2,20 @@
printf.o: $(RUBY_EXTCONF_H)
printf.o: $(arch_hdrdir)/ruby/config.h
printf.o: $(hdrdir)/ruby.h
+printf.o: $(hdrdir)/ruby/assert.h
+printf.o: $(hdrdir)/ruby/backward.h
+printf.o: $(hdrdir)/ruby/backward/2/assume.h
+printf.o: $(hdrdir)/ruby/backward/2/attributes.h
+printf.o: $(hdrdir)/ruby/backward/2/bool.h
+printf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+printf.o: $(hdrdir)/ruby/backward/2/limits.h
+printf.o: $(hdrdir)/ruby/backward/2/long_long.h
+printf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+printf.o: $(hdrdir)/ruby/backward/2/stdarg.h
+printf.o: $(hdrdir)/ruby/defines.h
+printf.o: $(hdrdir)/ruby/encoding.h
+printf.o: $(hdrdir)/ruby/intern.h
+printf.o: $(hdrdir)/ruby/internal/abi.h
printf.o: $(hdrdir)/ruby/internal/anyargs.h
printf.o: $(hdrdir)/ruby/internal/arithmetic.h
printf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ printf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
printf.o: $(hdrdir)/ruby/internal/ctype.h
printf.o: $(hdrdir)/ruby/internal/dllexport.h
printf.o: $(hdrdir)/ruby/internal/dosish.h
+printf.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+printf.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+printf.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+printf.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+printf.o: $(hdrdir)/ruby/internal/encoding/re.h
+printf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+printf.o: $(hdrdir)/ruby/internal/encoding/string.h
+printf.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+printf.o: $(hdrdir)/ruby/internal/encoding/transcode.h
printf.o: $(hdrdir)/ruby/internal/error.h
printf.o: $(hdrdir)/ruby/internal/eval.h
printf.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
printf.o: $(hdrdir)/ruby/missing.h
printf.o: $(hdrdir)/ruby/onigmo.h
printf.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/-test-/printf/printf.c b/ext/-test-/printf/printf.c
index e793bb7a48..889c0d9f0d 100644
--- a/ext/-test-/printf/printf.c
+++ b/ext/-test-/printf/printf.c
@@ -25,7 +25,7 @@ uint_to_str(char *p, char *e, unsigned int x)
char *e0 = e;
if (e <= p) return p;
do {
- *--e = x % 10 + '0';
+ *--e = x % 10 + '0';
} while ((x /= 10) != 0 && e > p);
memmove(p, e, e0 - e);
return p + (e0 - e);
@@ -44,48 +44,48 @@ printf_test_call(int argc, VALUE *argv, VALUE self)
if (RSTRING_LEN(type) != 1) rb_raise(rb_eArgError, "wrong length(%ld)", RSTRING_LEN(type));
switch (cnv = RSTRING_PTR(type)[0]) {
case 'd': case 'x': case 'o': case 'X':
- n = NUM2INT(num);
- break;
+ n = NUM2INT(num);
+ break;
case 's':
- s = StringValueCStr(num);
- break;
+ s = StringValueCStr(num);
+ break;
default: rb_raise(rb_eArgError, "wrong conversion(%c)", cnv);
}
*p++ = '%';
if (!NIL_P(opt)) {
- VALUE v;
- Check_Type(opt, T_HASH);
- if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("space"))))) {
- *p++ = ' ';
- }
- if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("hash"))))) {
- *p++ = '#';
- }
- if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("plus"))))) {
- *p++ = '+';
- }
- if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("minus"))))) {
- *p++ = '-';
- }
- if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("zero"))))) {
- *p++ = '0';
- }
- if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("width"))))) {
- p = uint_to_str(p, format + sizeof(format), NUM2UINT(v));
- }
- if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("prec"))))) {
- *p++ = '.';
- if (FIXNUM_P(v))
- p = uint_to_str(p, format + sizeof(format), NUM2UINT(v));
- }
+ VALUE v;
+ Check_Type(opt, T_HASH);
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("space"))))) {
+ *p++ = ' ';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("hash"))))) {
+ *p++ = '#';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("plus"))))) {
+ *p++ = '+';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("minus"))))) {
+ *p++ = '-';
+ }
+ if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("zero"))))) {
+ *p++ = '0';
+ }
+ if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("width"))))) {
+ p = uint_to_str(p, format + sizeof(format), NUM2UINT(v));
+ }
+ if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("prec"))))) {
+ *p++ = '.';
+ if (FIXNUM_P(v))
+ p = uint_to_str(p, format + sizeof(format), NUM2UINT(v));
+ }
}
*p++ = cnv;
*p++ = '\0';
if (cnv == 's') {
- result = rb_enc_sprintf(rb_usascii_encoding(), format, s);
+ result = rb_enc_sprintf(rb_usascii_encoding(), format, s);
}
else {
- result = rb_enc_sprintf(rb_usascii_encoding(), format, n);
+ result = rb_enc_sprintf(rb_usascii_encoding(), format, n);
}
return rb_assoc_new(result, rb_usascii_str_new_cstr(format));
}
diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend
index 929b4927dc..e3f1cf6ce9 100644
--- a/ext/-test-/proc/depend
+++ b/ext/-test-/proc/depend
@@ -2,6 +2,19 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+receiver.o: $(hdrdir)/ruby/backward.h
+receiver.o: $(hdrdir)/ruby/backward/2/assume.h
+receiver.o: $(hdrdir)/ruby/backward/2/attributes.h
+receiver.o: $(hdrdir)/ruby/backward/2/bool.h
+receiver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+receiver.o: $(hdrdir)/ruby/backward/2/limits.h
+receiver.o: $(hdrdir)/ruby/backward/2/long_long.h
+receiver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+receiver.o: $(hdrdir)/ruby/backward/2/stdarg.h
+receiver.o: $(hdrdir)/ruby/defines.h
+receiver.o: $(hdrdir)/ruby/intern.h
+receiver.o: $(hdrdir)/ruby/internal/abi.h
receiver.o: $(hdrdir)/ruby/internal/anyargs.h
receiver.o: $(hdrdir)/ruby/internal/arithmetic.h
receiver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -301,19 +314,6 @@ 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
receiver.o: $(hdrdir)/ruby/ruby.h
receiver.o: $(hdrdir)/ruby/st.h
@@ -322,6 +322,19 @@ 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/assert.h
+super.o: $(hdrdir)/ruby/backward.h
+super.o: $(hdrdir)/ruby/backward/2/assume.h
+super.o: $(hdrdir)/ruby/backward/2/attributes.h
+super.o: $(hdrdir)/ruby/backward/2/bool.h
+super.o: $(hdrdir)/ruby/backward/2/inttypes.h
+super.o: $(hdrdir)/ruby/backward/2/limits.h
+super.o: $(hdrdir)/ruby/backward/2/long_long.h
+super.o: $(hdrdir)/ruby/backward/2/stdalign.h
+super.o: $(hdrdir)/ruby/backward/2/stdarg.h
+super.o: $(hdrdir)/ruby/defines.h
+super.o: $(hdrdir)/ruby/intern.h
+super.o: $(hdrdir)/ruby/internal/abi.h
super.o: $(hdrdir)/ruby/internal/anyargs.h
super.o: $(hdrdir)/ruby/internal/arithmetic.h
super.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -461,19 +474,6 @@ 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
super.o: $(hdrdir)/ruby/ruby.h
super.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/proc/super.c b/ext/-test-/proc/super.c
index dbe8af08f1..816520e1df 100644
--- a/ext/-test-/proc/super.c
+++ b/ext/-test-/proc/super.c
@@ -9,7 +9,7 @@ bug_proc_call_super(RB_BLOCK_CALL_FUNC_ARGLIST(yieldarg, procarg))
args[1] = procarg;
ret = rb_call_super(2, args);
if (!NIL_P(blockarg)) {
- ret = rb_proc_call(blockarg, ret);
+ ret = rb_proc_call(blockarg, ret);
}
return ret;
}
diff --git a/ext/-test-/random/bad_version.c b/ext/-test-/random/bad_version.c
new file mode 100644
index 0000000000..dae63a6d19
--- /dev/null
+++ b/ext/-test-/random/bad_version.c
@@ -0,0 +1,135 @@
+#include "ruby/random.h"
+
+#if RUBY_RANDOM_INTERFACE_VERSION_MAJOR < RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX
+# define DEFINE_VERSION_MAX 1
+#else
+# define DEFINE_VERSION_MAX 0
+#endif
+
+NORETURN(static void must_not_reach(void));
+static void
+must_not_reach(void)
+{
+ rb_raise(rb_eTypeError, "must not reach");
+}
+
+NORETURN(static void bad_version_init(rb_random_t *, const uint32_t *, size_t));
+static void
+bad_version_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
+{
+ must_not_reach();
+}
+
+NORETURN(static void bad_version_init_int32(rb_random_t *, uint32_t));
+RB_RANDOM_DEFINE_INIT_INT32_FUNC(bad_version)
+
+NORETURN(static void bad_version_get_bytes(rb_random_t *, void *, size_t));
+static void
+bad_version_get_bytes(rb_random_t *rnd, void *p, size_t n)
+{
+ must_not_reach();
+}
+
+NORETURN(static uint32_t bad_version_get_int32(rb_random_t *));
+static uint32_t
+bad_version_get_int32(rb_random_t *rnd)
+{
+ must_not_reach();
+ UNREACHABLE_RETURN(0);
+}
+
+static VALUE
+bad_version_alloc(VALUE klass, const rb_data_type_t *type)
+{
+ rb_random_t *rnd;
+ VALUE obj = TypedData_Make_Struct(klass, rb_random_t, type, rnd);
+ rb_random_base_init(rnd);
+ return obj;
+}
+
+/* version 0 */
+static const rb_random_interface_t random_version_zero_if;
+
+static rb_random_data_type_t version_zero_type = {
+ "random/version_zero",
+ {
+ rb_random_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ },
+ RB_RANDOM_PARENT,
+ (void *)&random_version_zero_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+version_zero_alloc(VALUE klass)
+{
+ return bad_version_alloc(klass, &version_zero_type);
+}
+
+static void
+init_version_zero(VALUE mod, VALUE base)
+{
+ VALUE c = rb_define_class_under(mod, "VersionZero", base);
+ rb_define_alloc_func(c, version_zero_alloc);
+ RB_RANDOM_DATA_INIT_PARENT(version_zero_type);
+}
+
+#if DEFINE_VERSION_MAX
+/* version max */
+static const rb_random_interface_t random_version_max_if;
+static rb_random_data_type_t version_max_type = {
+ "random/version_max",
+ {
+ rb_random_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ },
+ RB_RANDOM_PARENT,
+ (void *)&random_version_max_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+version_max_alloc(VALUE klass)
+{
+ return bad_version_alloc(klass, &version_max_type);
+}
+
+static void
+init_version_max(VALUE mod, VALUE base)
+{
+ VALUE c = rb_define_class_under(mod, "VersionMax", base);
+ rb_define_alloc_func(c, version_max_alloc);
+ RB_RANDOM_DATA_INIT_PARENT(version_max_type);
+}
+#else
+static void
+init_version_max(mod, base)
+{
+}
+#endif
+
+void
+Init_random_bad_version(VALUE mod, VALUE base)
+{
+ init_version_zero(mod, base);
+ init_version_max(mod, base);
+}
+
+#undef RUBY_RANDOM_INTERFACE_VERSION_MAJOR
+
+#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR 0
+static const rb_random_interface_t random_version_zero_if = {
+ 0,
+ RB_RANDOM_INTERFACE_DEFINE(bad_version)
+};
+#undef RUBY_RANDOM_INTERFACE_VERSION_MAJOR
+
+#if DEFINE_VERSION_MAX
+#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX
+static const rb_random_interface_t random_version_max_if = {
+ 0,
+ RB_RANDOM_INTERFACE_DEFINE(bad_version)
+};
+#undef RUBY_RANDOM_INTERFACE_VERSION_MAJOR
+#endif
diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend
index 799b563075..f2cbf7fc14 100644
--- a/ext/-test-/random/depend
+++ b/ext/-test-/random/depend
@@ -1,4 +1,164 @@
# AUTOGENERATED DEPENDENCIES START
+bad_version.o: $(RUBY_EXTCONF_H)
+bad_version.o: $(arch_hdrdir)/ruby/config.h
+bad_version.o: $(hdrdir)/ruby/assert.h
+bad_version.o: $(hdrdir)/ruby/backward.h
+bad_version.o: $(hdrdir)/ruby/backward/2/assume.h
+bad_version.o: $(hdrdir)/ruby/backward/2/attributes.h
+bad_version.o: $(hdrdir)/ruby/backward/2/bool.h
+bad_version.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bad_version.o: $(hdrdir)/ruby/backward/2/limits.h
+bad_version.o: $(hdrdir)/ruby/backward/2/long_long.h
+bad_version.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bad_version.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bad_version.o: $(hdrdir)/ruby/defines.h
+bad_version.o: $(hdrdir)/ruby/intern.h
+bad_version.o: $(hdrdir)/ruby/internal/abi.h
+bad_version.o: $(hdrdir)/ruby/internal/anyargs.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bad_version.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bad_version.o: $(hdrdir)/ruby/internal/assume.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/cold.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/const.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/error.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/format.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/pure.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/warning.h
+bad_version.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bad_version.o: $(hdrdir)/ruby/internal/cast.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bad_version.o: $(hdrdir)/ruby/internal/compiler_since.h
+bad_version.o: $(hdrdir)/ruby/internal/config.h
+bad_version.o: $(hdrdir)/ruby/internal/constant_p.h
+bad_version.o: $(hdrdir)/ruby/internal/core.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rarray.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rclass.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rdata.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rfile.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rhash.h
+bad_version.o: $(hdrdir)/ruby/internal/core/robject.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rstring.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bad_version.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bad_version.o: $(hdrdir)/ruby/internal/ctype.h
+bad_version.o: $(hdrdir)/ruby/internal/dllexport.h
+bad_version.o: $(hdrdir)/ruby/internal/dosish.h
+bad_version.o: $(hdrdir)/ruby/internal/error.h
+bad_version.o: $(hdrdir)/ruby/internal/eval.h
+bad_version.o: $(hdrdir)/ruby/internal/event.h
+bad_version.o: $(hdrdir)/ruby/internal/fl_type.h
+bad_version.o: $(hdrdir)/ruby/internal/gc.h
+bad_version.o: $(hdrdir)/ruby/internal/glob.h
+bad_version.o: $(hdrdir)/ruby/internal/globals.h
+bad_version.o: $(hdrdir)/ruby/internal/has/attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/builtin.h
+bad_version.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bad_version.o: $(hdrdir)/ruby/internal/has/extension.h
+bad_version.o: $(hdrdir)/ruby/internal/has/feature.h
+bad_version.o: $(hdrdir)/ruby/internal/has/warning.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/array.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/class.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/compar.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/complex.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/cont.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/dir.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/enum.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/error.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/eval.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/file.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/gc.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/hash.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/io.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/load.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/object.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/parse.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/proc.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/process.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/random.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/range.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/rational.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/re.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/select.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/signal.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/string.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/struct.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/thread.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/time.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/variable.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/vm.h
+bad_version.o: $(hdrdir)/ruby/internal/interpreter.h
+bad_version.o: $(hdrdir)/ruby/internal/iterator.h
+bad_version.o: $(hdrdir)/ruby/internal/memory.h
+bad_version.o: $(hdrdir)/ruby/internal/method.h
+bad_version.o: $(hdrdir)/ruby/internal/module.h
+bad_version.o: $(hdrdir)/ruby/internal/newobj.h
+bad_version.o: $(hdrdir)/ruby/internal/rgengc.h
+bad_version.o: $(hdrdir)/ruby/internal/scan_args.h
+bad_version.o: $(hdrdir)/ruby/internal/special_consts.h
+bad_version.o: $(hdrdir)/ruby/internal/static_assert.h
+bad_version.o: $(hdrdir)/ruby/internal/stdalign.h
+bad_version.o: $(hdrdir)/ruby/internal/stdbool.h
+bad_version.o: $(hdrdir)/ruby/internal/symbol.h
+bad_version.o: $(hdrdir)/ruby/internal/value.h
+bad_version.o: $(hdrdir)/ruby/internal/value_type.h
+bad_version.o: $(hdrdir)/ruby/internal/variable.h
+bad_version.o: $(hdrdir)/ruby/internal/warning_push.h
+bad_version.o: $(hdrdir)/ruby/internal/xmalloc.h
+bad_version.o: $(hdrdir)/ruby/missing.h
+bad_version.o: $(hdrdir)/ruby/random.h
+bad_version.o: $(hdrdir)/ruby/ruby.h
+bad_version.o: $(hdrdir)/ruby/st.h
+bad_version.o: $(hdrdir)/ruby/subst.h
+bad_version.o: bad_version.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
@@ -7,16 +167,14 @@ 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/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -168,16 +326,14 @@ 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/abi.h
loop.o: $(hdrdir)/ruby/internal/anyargs.h
loop.o: $(hdrdir)/ruby/internal/arithmetic.h
loop.o: $(hdrdir)/ruby/internal/arithmetic/char.h
diff --git a/ext/-test-/random/loop.c b/ext/-test-/random/loop.c
index 0572096403..b789ab1d01 100644
--- a/ext/-test-/random/loop.c
+++ b/ext/-test-/random/loop.c
@@ -13,6 +13,7 @@ static const rb_random_interface_t random_loop_if = {
RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop)
};
+RB_RANDOM_DEFINE_INIT_INT32_FUNC(loop)
static size_t
random_loop_memsize(const void *ptr)
{
diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend
index 67ac3c6f90..ce977821b8 100644
--- a/ext/-test-/rational/depend
+++ b/ext/-test-/rational/depend
@@ -5,7 +5,20 @@ rat.o: rat.c $(top_srcdir)/internal.h
# AUTOGENERATED DEPENDENCIES START
rat.o: $(RUBY_EXTCONF_H)
rat.o: $(arch_hdrdir)/ruby/config.h
-rat.o: $(hdrdir)/ruby.h
+rat.o: $(hdrdir)/ruby/assert.h
+rat.o: $(hdrdir)/ruby/backward.h
+rat.o: $(hdrdir)/ruby/backward/2/assume.h
+rat.o: $(hdrdir)/ruby/backward/2/attributes.h
+rat.o: $(hdrdir)/ruby/backward/2/bool.h
+rat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rat.o: $(hdrdir)/ruby/backward/2/limits.h
+rat.o: $(hdrdir)/ruby/backward/2/long_long.h
+rat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rat.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rat.o: $(hdrdir)/ruby/defines.h
+rat.o: $(hdrdir)/ruby/intern.h
+rat.o: $(hdrdir)/ruby/internal/abi.h
rat.o: $(hdrdir)/ruby/internal/anyargs.h
rat.o: $(hdrdir)/ruby/internal/arithmetic.h
rat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -145,24 +158,10 @@ 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
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
@@ -175,5 +174,6 @@ 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: $(top_srcdir)/shape.h
rat.o: rat.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend
index 25725f9a9a..3512a081c9 100644
--- a/ext/-test-/rb_call_super_kw/depend
+++ b/ext/-test-/rb_call_super_kw/depend
@@ -2,6 +2,19 @@
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/assert.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_call_super_kw.o: $(hdrdir)/ruby/defines.h
+rb_call_super_kw.o: $(hdrdir)/ruby/intern.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
rb_call_super_kw.o: $(hdrdir)/ruby/ruby.h
rb_call_super_kw.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/rb_call_super_kw/rb_call_super_kw.c b/ext/-test-/rb_call_super_kw/rb_call_super_kw.c
index 7f094545d2..61681ed733 100644
--- a/ext/-test-/rb_call_super_kw/rb_call_super_kw.c
+++ b/ext/-test-/rb_call_super_kw/rb_call_super_kw.c
@@ -7,7 +7,8 @@ rb_call_super_kw_m(int argc, VALUE *argv, VALUE self)
}
void
-Init_rb_call_super_kw(void) {
+Init_rb_call_super_kw(void)
+{
VALUE module = rb_define_module("Bug");
module = rb_define_module_under(module, "RbCallSuperKw");
rb_define_method(module, "m", rb_call_super_kw_m, -1);
diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend
index 14bfbfca4e..e499f95e73 100644
--- a/ext/-test-/recursion/depend
+++ b/ext/-test-/recursion/depend
@@ -2,6 +2,19 @@
recursion.o: $(RUBY_EXTCONF_H)
recursion.o: $(arch_hdrdir)/ruby/config.h
recursion.o: $(hdrdir)/ruby.h
+recursion.o: $(hdrdir)/ruby/assert.h
+recursion.o: $(hdrdir)/ruby/backward.h
+recursion.o: $(hdrdir)/ruby/backward/2/assume.h
+recursion.o: $(hdrdir)/ruby/backward/2/attributes.h
+recursion.o: $(hdrdir)/ruby/backward/2/bool.h
+recursion.o: $(hdrdir)/ruby/backward/2/inttypes.h
+recursion.o: $(hdrdir)/ruby/backward/2/limits.h
+recursion.o: $(hdrdir)/ruby/backward/2/long_long.h
+recursion.o: $(hdrdir)/ruby/backward/2/stdalign.h
+recursion.o: $(hdrdir)/ruby/backward/2/stdarg.h
+recursion.o: $(hdrdir)/ruby/defines.h
+recursion.o: $(hdrdir)/ruby/intern.h
+recursion.o: $(hdrdir)/ruby/internal/abi.h
recursion.o: $(hdrdir)/ruby/internal/anyargs.h
recursion.o: $(hdrdir)/ruby/internal/arithmetic.h
recursion.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
recursion.o: $(hdrdir)/ruby/ruby.h
recursion.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend
index 1e2b225316..fa431e013a 100644
--- a/ext/-test-/regexp/depend
+++ b/ext/-test-/regexp/depend
@@ -2,6 +2,19 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/assume.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/attributes.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/bool.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/inttypes.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/limits.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/long_long.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdalign.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdarg.h
+parse_depth_limit.o: $(hdrdir)/ruby/defines.h
+parse_depth_limit.o: $(hdrdir)/ruby/intern.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/abi.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
@@ -301,19 +314,6 @@ 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
parse_depth_limit.o: $(hdrdir)/ruby/onigmo.h
parse_depth_limit.o: $(hdrdir)/ruby/ruby.h
diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend
index e01de3124e..2194936b04 100644
--- a/ext/-test-/scan_args/depend
+++ b/ext/-test-/scan_args/depend
@@ -2,6 +2,19 @@
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/assert.h
+scan_args.o: $(hdrdir)/ruby/backward.h
+scan_args.o: $(hdrdir)/ruby/backward/2/assume.h
+scan_args.o: $(hdrdir)/ruby/backward/2/attributes.h
+scan_args.o: $(hdrdir)/ruby/backward/2/bool.h
+scan_args.o: $(hdrdir)/ruby/backward/2/inttypes.h
+scan_args.o: $(hdrdir)/ruby/backward/2/limits.h
+scan_args.o: $(hdrdir)/ruby/backward/2/long_long.h
+scan_args.o: $(hdrdir)/ruby/backward/2/stdalign.h
+scan_args.o: $(hdrdir)/ruby/backward/2/stdarg.h
+scan_args.o: $(hdrdir)/ruby/defines.h
+scan_args.o: $(hdrdir)/ruby/intern.h
+scan_args.o: $(hdrdir)/ruby/internal/abi.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
@@ -141,19 +154,6 @@ 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
scan_args.o: $(hdrdir)/ruby/ruby.h
scan_args.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend
index d9c0f56d11..0464ee3c53 100644
--- a/ext/-test-/st/foreach/depend
+++ b/ext/-test-/st/foreach/depend
@@ -2,6 +2,19 @@
foreach.o: $(RUBY_EXTCONF_H)
foreach.o: $(arch_hdrdir)/ruby/config.h
foreach.o: $(hdrdir)/ruby.h
+foreach.o: $(hdrdir)/ruby/assert.h
+foreach.o: $(hdrdir)/ruby/backward.h
+foreach.o: $(hdrdir)/ruby/backward/2/assume.h
+foreach.o: $(hdrdir)/ruby/backward/2/attributes.h
+foreach.o: $(hdrdir)/ruby/backward/2/bool.h
+foreach.o: $(hdrdir)/ruby/backward/2/inttypes.h
+foreach.o: $(hdrdir)/ruby/backward/2/limits.h
+foreach.o: $(hdrdir)/ruby/backward/2/long_long.h
+foreach.o: $(hdrdir)/ruby/backward/2/stdalign.h
+foreach.o: $(hdrdir)/ruby/backward/2/stdarg.h
+foreach.o: $(hdrdir)/ruby/defines.h
+foreach.o: $(hdrdir)/ruby/intern.h
+foreach.o: $(hdrdir)/ruby/internal/abi.h
foreach.o: $(hdrdir)/ruby/internal/anyargs.h
foreach.o: $(hdrdir)/ruby/internal/arithmetic.h
foreach.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
foreach.o: $(hdrdir)/ruby/ruby.h
foreach.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/st/foreach/foreach.c b/ext/-test-/st/foreach/foreach.c
index 27ac18046f..cde49fb26d 100644
--- a/ext/-test-/st/foreach/foreach.c
+++ b/ext/-test-/st/foreach/foreach.c
@@ -12,22 +12,22 @@ static void
force_unpack_check(struct checker *c, st_data_t key, st_data_t val)
{
if (c->nr == 0) {
- st_data_t i;
+ st_data_t i;
- if (c->tbl->bins != NULL) rb_bug("should be packed\n");
+ if (c->tbl->bins != NULL) rb_bug("should be packed\n");
- /* force unpacking during iteration: */
- for (i = 1; i < expect_size; i++)
- st_add_direct(c->tbl, i, i);
+ /* force unpacking during iteration: */
+ for (i = 1; i < expect_size; i++)
+ st_add_direct(c->tbl, i, i);
- if (c->tbl->bins == NULL) rb_bug("should be unpacked\n");
+ if (c->tbl->bins == NULL) rb_bug("should be unpacked\n");
}
if (key != c->nr) {
- rb_bug("unexpected key: %"PRIuVALUE" (expected %"PRIuVALUE")\n", (VALUE)key, (VALUE)c->nr);
+ rb_bug("unexpected key: %"PRIuVALUE" (expected %"PRIuVALUE")\n", (VALUE)key, (VALUE)c->nr);
}
if (val != c->nr) {
- rb_bug("unexpected val: %"PRIuVALUE" (expected %"PRIuVALUE")\n", (VALUE)val, (VALUE)c->nr);
+ rb_bug("unexpected val: %"PRIuVALUE" (expected %"PRIuVALUE")\n", (VALUE)val, (VALUE)c->nr);
}
c->nr++;
@@ -39,34 +39,34 @@ unp_fec_i(st_data_t key, st_data_t val, st_data_t args, int error)
struct checker *c = (struct checker *)args;
if (error) {
- if (c->test == ID2SYM(rb_intern("delete2")))
- return ST_STOP;
+ if (c->test == ID2SYM(rb_intern("delete2")))
+ return ST_STOP;
- rb_bug("unexpected error");
+ rb_bug("unexpected error");
}
force_unpack_check(c, key, val);
if (c->test == ID2SYM(rb_intern("check"))) {
- return ST_CHECK;
+ return ST_CHECK;
}
if (c->test == ID2SYM(rb_intern("delete1"))) {
- if (c->nr == 1) return ST_DELETE;
- return ST_CHECK;
+ if (c->nr == 1) return ST_DELETE;
+ return ST_CHECK;
}
if (c->test == ID2SYM(rb_intern("delete2"))) {
- if (c->nr == 1) {
- st_data_t k = 0;
- st_data_t v;
-
- if (!st_delete(c->tbl, &k, &v)) {
- rb_bug("failed to delete\n");
- }
- if (v != 0) {
- rb_bug("unexpected value deleted: %"PRIuVALUE" (expected 0)", (VALUE)v);
- }
- }
- return ST_CHECK;
+ if (c->nr == 1) {
+ st_data_t k = 0;
+ st_data_t v;
+
+ if (!st_delete(c->tbl, &k, &v)) {
+ rb_bug("failed to delete\n");
+ }
+ if (v != 0) {
+ rb_bug("unexpected value deleted: %"PRIuVALUE" (expected 0)", (VALUE)v);
+ }
+ }
+ return ST_CHECK;
}
rb_raise(rb_eArgError, "unexpected arg: %+"PRIsVALUE, c->test);
@@ -89,13 +89,13 @@ unp_fec(VALUE self, VALUE test)
st_foreach_check(tbl, unp_fec_i, (st_data_t)&c, -1);
if (c.test == ID2SYM(rb_intern("delete2"))) {
- if (c.nr != 1) {
- rb_bug("mismatched iteration: %"PRIuVALUE" (expected 1)\n", (VALUE)c.nr);
- }
+ if (c.nr != 1) {
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected 1)\n", (VALUE)c.nr);
+ }
}
else if (c.nr != expect_size) {
- rb_bug("mismatched iteration: %"PRIuVALUE" (expected %"PRIuVALUE")\n",
- (VALUE)c.nr, (VALUE)expect_size);
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected %"PRIuVALUE")\n",
+ (VALUE)c.nr, (VALUE)expect_size);
}
if (tbl->bins == NULL) rb_bug("should be unpacked\n");
@@ -112,22 +112,22 @@ unp_fe_i(st_data_t key, st_data_t val, st_data_t args)
force_unpack_check(c, key, val);
if (c->test == ID2SYM(rb_intern("unpacked"))) {
- return ST_CONTINUE;
+ return ST_CONTINUE;
}
else if (c->test == ID2SYM(rb_intern("unpack_delete"))) {
- if (c->nr == 1) {
- st_data_t k = 0;
- st_data_t v;
-
- if (!st_delete(c->tbl, &k, &v)) {
- rb_bug("failed to delete\n");
- }
- if (v != 0) {
- rb_bug("unexpected value deleted: %"PRIuVALUE" (expected 0)", (VALUE)v);
- }
- return ST_CONTINUE;
- }
- rb_bug("should never get here\n");
+ if (c->nr == 1) {
+ st_data_t k = 0;
+ st_data_t v;
+
+ if (!st_delete(c->tbl, &k, &v)) {
+ rb_bug("failed to delete\n");
+ }
+ if (v != 0) {
+ rb_bug("unexpected value deleted: %"PRIuVALUE" (expected 0)", (VALUE)v);
+ }
+ return ST_CONTINUE;
+ }
+ rb_bug("should never get here\n");
}
rb_raise(rb_eArgError, "unexpected arg: %+"PRIsVALUE, c->test);
@@ -150,13 +150,13 @@ unp_fe(VALUE self, VALUE test)
st_foreach(tbl, unp_fe_i, (st_data_t)&c);
if (c.test == ID2SYM(rb_intern("unpack_delete"))) {
- if (c.nr != 1) {
- rb_bug("mismatched iteration: %"PRIuVALUE" (expected 1)\n", (VALUE)c.nr);
- }
+ if (c.nr != 1) {
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected 1)\n", (VALUE)c.nr);
+ }
}
else if (c.nr != expect_size) {
- rb_bug("mismatched iteration: %"PRIuVALUE" (expected %"PRIuVALUE"o)\n",
- (VALUE)c.nr, (VALUE)expect_size);
+ rb_bug("mismatched iteration: %"PRIuVALUE" (expected %"PRIuVALUE"o)\n",
+ (VALUE)c.nr, (VALUE)expect_size);
}
if (tbl->bins == NULL) rb_bug("should be unpacked\n");
diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend
index 8df4fed3e4..9665ed6e39 100644
--- a/ext/-test-/st/numhash/depend
+++ b/ext/-test-/st/numhash/depend
@@ -2,6 +2,19 @@
numhash.o: $(RUBY_EXTCONF_H)
numhash.o: $(arch_hdrdir)/ruby/config.h
numhash.o: $(hdrdir)/ruby.h
+numhash.o: $(hdrdir)/ruby/assert.h
+numhash.o: $(hdrdir)/ruby/backward.h
+numhash.o: $(hdrdir)/ruby/backward/2/assume.h
+numhash.o: $(hdrdir)/ruby/backward/2/attributes.h
+numhash.o: $(hdrdir)/ruby/backward/2/bool.h
+numhash.o: $(hdrdir)/ruby/backward/2/inttypes.h
+numhash.o: $(hdrdir)/ruby/backward/2/limits.h
+numhash.o: $(hdrdir)/ruby/backward/2/long_long.h
+numhash.o: $(hdrdir)/ruby/backward/2/stdalign.h
+numhash.o: $(hdrdir)/ruby/backward/2/stdarg.h
+numhash.o: $(hdrdir)/ruby/defines.h
+numhash.o: $(hdrdir)/ruby/intern.h
+numhash.o: $(hdrdir)/ruby/internal/abi.h
numhash.o: $(hdrdir)/ruby/internal/anyargs.h
numhash.o: $(hdrdir)/ruby/internal/arithmetic.h
numhash.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
numhash.o: $(hdrdir)/ruby/ruby.h
numhash.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c
index aa8015e86c..7e8d5d9fe2 100644
--- a/ext/-test-/st/numhash/numhash.c
+++ b/ext/-test-/st/numhash/numhash.c
@@ -42,7 +42,7 @@ numhash_aref(VALUE self, VALUE key)
st_table *tbl = (st_table *)Check_TypedStruct(self, &numhash_type);
if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
if (st_lookup(tbl, (st_data_t)key, &data))
- return (VALUE)data;
+ return (VALUE)data;
return Qnil;
}
@@ -79,12 +79,12 @@ update_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
VALUE ret = rb_yield_values(existing ? 2 : 1, (VALUE)*key, (VALUE)*value);
switch (ret) {
case Qfalse:
- return ST_STOP;
+ return ST_STOP;
case Qnil:
- return ST_DELETE;
+ return ST_DELETE;
default:
- *value = ret;
- return ST_CONTINUE;
+ *value = ret;
+ return ST_CONTINUE;
}
}
@@ -93,9 +93,9 @@ numhash_update(VALUE self, VALUE key)
{
st_table *table = (st_table *)Check_TypedStruct(self, &numhash_type);
if (st_update(table, (st_data_t)key, update_func, 0))
- return Qtrue;
+ return Qtrue;
else
- return Qfalse;
+ return Qfalse;
}
#if SIZEOF_LONG == SIZEOF_VOIDP
@@ -117,7 +117,7 @@ numhash_delete_safe(VALUE self, VALUE key)
st_table *table = (st_table *)Check_TypedStruct(self, &numhash_type);
st_data_t val, k = (st_data_t)key;
if (st_delete_safe(table, &k, &val, (st_data_t)self)) {
- return val;
+ return val;
}
return Qnil;
}
diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend
index b840e67f3b..01960df965 100644
--- a/ext/-test-/st/update/depend
+++ b/ext/-test-/st/update/depend
@@ -2,6 +2,19 @@
update.o: $(RUBY_EXTCONF_H)
update.o: $(arch_hdrdir)/ruby/config.h
update.o: $(hdrdir)/ruby.h
+update.o: $(hdrdir)/ruby/assert.h
+update.o: $(hdrdir)/ruby/backward.h
+update.o: $(hdrdir)/ruby/backward/2/assume.h
+update.o: $(hdrdir)/ruby/backward/2/attributes.h
+update.o: $(hdrdir)/ruby/backward/2/bool.h
+update.o: $(hdrdir)/ruby/backward/2/inttypes.h
+update.o: $(hdrdir)/ruby/backward/2/limits.h
+update.o: $(hdrdir)/ruby/backward/2/long_long.h
+update.o: $(hdrdir)/ruby/backward/2/stdalign.h
+update.o: $(hdrdir)/ruby/backward/2/stdarg.h
+update.o: $(hdrdir)/ruby/defines.h
+update.o: $(hdrdir)/ruby/intern.h
+update.o: $(hdrdir)/ruby/internal/abi.h
update.o: $(hdrdir)/ruby/internal/anyargs.h
update.o: $(hdrdir)/ruby/internal/arithmetic.h
update.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
update.o: $(hdrdir)/ruby/ruby.h
update.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/st/update/update.c b/ext/-test-/st/update/update.c
index 979ad3e334..ea7fab12e1 100644
--- a/ext/-test-/st/update/update.c
+++ b/ext/-test-/st/update/update.c
@@ -7,12 +7,12 @@ update_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
VALUE ret = rb_yield_values(existing ? 2 : 1, (VALUE)*key, (VALUE)*value);
switch (ret) {
case Qfalse:
- return ST_STOP;
+ return ST_STOP;
case Qnil:
- return ST_DELETE;
+ return ST_DELETE;
default:
- *value = ret;
- return ST_CONTINUE;
+ *value = ret;
+ return ST_CONTINUE;
}
}
@@ -20,9 +20,9 @@ static VALUE
test_st_update(VALUE self, VALUE key)
{
if (st_update(RHASH_TBL(self), (st_data_t)key, update_func, 0))
- return Qtrue;
+ return Qtrue;
else
- return Qfalse;
+ return Qfalse;
}
void
diff --git a/ext/-test-/string/capacity.c b/ext/-test-/string/capacity.c
index cb8d2c2b3a..33b2023fd3 100644
--- a/ext/-test-/string/capacity.c
+++ b/ext/-test-/string/capacity.c
@@ -4,10 +4,11 @@
static VALUE
bug_str_capacity(VALUE klass, VALUE str)
{
- return
- STR_EMBED_P(str) ? INT2FIX(RSTRING_EMBED_LEN_MAX) : \
- STR_SHARED_P(str) ? INT2FIX(0) : \
- LONG2FIX(RSTRING(str)->as.heap.aux.capa);
+ if (!STR_EMBED_P(str) && STR_SHARED_P(str)) {
+ return INT2FIX(0);
+ }
+
+ return LONG2FIX(rb_str_capacity(str));
}
void
diff --git a/ext/-test-/string/coderange.c b/ext/-test-/string/coderange.c
index bc998ca372..4197ecca9f 100644
--- a/ext/-test-/string/coderange.c
+++ b/ext/-test-/string/coderange.c
@@ -8,13 +8,13 @@ coderange_int2sym(int coderange)
{
switch (coderange) {
case ENC_CODERANGE_7BIT:
- return sym_7bit;
+ return sym_7bit;
case ENC_CODERANGE_VALID:
- return sym_valid;
+ return sym_valid;
case ENC_CODERANGE_UNKNOWN:
- return sym_unknown;
+ return sym_unknown;
case ENC_CODERANGE_BROKEN:
- return sym_broken;
+ return sym_broken;
}
rb_bug("wrong condition of coderange");
UNREACHABLE_RETURN(Qnil);
diff --git a/ext/-test-/string/cstr.c b/ext/-test-/string/cstr.c
index 4f837998d7..468ee7a3b1 100644
--- a/ext/-test-/string/cstr.c
+++ b/ext/-test-/string/cstr.c
@@ -42,11 +42,11 @@ bug_str_cstr_term_char(VALUE str)
len = rb_enc_mbminlen(enc);
c = rb_enc_precise_mbclen(s, s + len, enc);
if (!MBCLEN_CHARFOUND_P(c)) {
- c = (unsigned char)*s;
+ c = (unsigned char)*s;
}
else {
- c = rb_enc_mbc_to_codepoint(s, s + len, enc);
- if (!c) return Qnil;
+ c = rb_enc_mbc_to_codepoint(s, s + len, enc);
+ if (!c) return Qnil;
}
return rb_enc_uint_chr((unsigned int)c, enc);
}
@@ -62,13 +62,17 @@ bug_str_unterminated_substring(VALUE str, VALUE vbeg, VALUE vlen)
if (RSTRING_LEN(str) < beg + len) rb_raise(rb_eIndexError, "end: %ld", beg + len);
str = rb_str_new_shared(str);
if (STR_EMBED_P(str)) {
- RSTRING(str)->basic.flags &= ~RSTRING_EMBED_LEN_MASK;
- RSTRING(str)->basic.flags |= len << RSTRING_EMBED_LEN_SHIFT;
- memmove(RSTRING(str)->as.ary, RSTRING(str)->as.ary + beg, len);
+#if USE_RVARGC
+ RSTRING(str)->as.embed.len = (short)len;
+#else
+ RSTRING(str)->basic.flags &= ~RSTRING_EMBED_LEN_MASK;
+ RSTRING(str)->basic.flags |= len << RSTRING_EMBED_LEN_SHIFT;
+#endif
+ memmove(RSTRING(str)->as.embed.ary, RSTRING(str)->as.embed.ary + beg, len);
}
else {
- RSTRING(str)->as.heap.ptr += beg;
- RSTRING(str)->as.heap.len = len;
+ RSTRING(str)->as.heap.ptr += beg;
+ RSTRING(str)->as.heap.len = len;
}
return str;
}
@@ -100,7 +104,7 @@ bug_str_s_cstr_term_char(VALUE self, VALUE str)
const int term_fill_len = (termlen);\
*term_fill_ptr = '\0';\
if (UNLIKELY(term_fill_len > 1))\
- memset(term_fill_ptr, 0, term_fill_len);\
+ memset(term_fill_ptr, 0, term_fill_len);\
} while (0)
static VALUE
@@ -112,7 +116,11 @@ bug_str_s_cstr_noembed(VALUE self, VALUE str)
Check_Type(str, T_STRING);
FL_SET((str2), STR_NOEMBED);
memcpy(buf, RSTRING_PTR(str), capacity);
+#if USE_RVARGC
+ RBASIC(str2)->flags &= ~(STR_SHARED | FL_USER5 | FL_USER6);
+#else
RBASIC(str2)->flags &= ~RSTRING_EMBED_LEN_MASK;
+#endif
RSTRING(str2)->as.heap.aux.capa = capacity;
RSTRING(str2)->as.heap.ptr = buf;
RSTRING(str2)->as.heap.len = RSTRING_LEN(str);
diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend
index 66071abfec..773231047e 100644
--- a/ext/-test-/string/depend
+++ b/ext/-test-/string/depend
@@ -16,6 +16,7 @@ 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/abi.h
capacity.o: $(hdrdir)/ruby/internal/anyargs.h
capacity.o: $(hdrdir)/ruby/internal/arithmetic.h
capacity.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -85,6 +86,15 @@ capacity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
capacity.o: $(hdrdir)/ruby/internal/ctype.h
capacity.o: $(hdrdir)/ruby/internal/dllexport.h
capacity.o: $(hdrdir)/ruby/internal/dosish.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/re.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/string.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+capacity.o: $(hdrdir)/ruby/internal/encoding/transcode.h
capacity.o: $(hdrdir)/ruby/internal/error.h
capacity.o: $(hdrdir)/ruby/internal/eval.h
capacity.o: $(hdrdir)/ruby/internal/event.h
@@ -161,7 +171,6 @@ 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
@@ -172,7 +181,6 @@ 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
@@ -181,6 +189,7 @@ 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/abi.h
coderange.o: $(hdrdir)/ruby/internal/anyargs.h
coderange.o: $(hdrdir)/ruby/internal/arithmetic.h
coderange.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -250,6 +259,15 @@ coderange.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
coderange.o: $(hdrdir)/ruby/internal/ctype.h
coderange.o: $(hdrdir)/ruby/internal/dllexport.h
coderange.o: $(hdrdir)/ruby/internal/dosish.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/re.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/string.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+coderange.o: $(hdrdir)/ruby/internal/encoding/transcode.h
coderange.o: $(hdrdir)/ruby/internal/error.h
coderange.o: $(hdrdir)/ruby/internal/eval.h
coderange.o: $(hdrdir)/ruby/internal/event.h
@@ -329,7 +347,6 @@ coderange.o: $(hdrdir)/ruby/subst.h
coderange.o: coderange.c
cstr.o: $(RUBY_EXTCONF_H)
cstr.o: $(arch_hdrdir)/ruby/config.h
-cstr.o: $(hdrdir)/ruby.h
cstr.o: $(hdrdir)/ruby/assert.h
cstr.o: $(hdrdir)/ruby/backward.h
cstr.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -344,6 +361,7 @@ 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/abi.h
cstr.o: $(hdrdir)/ruby/internal/anyargs.h
cstr.o: $(hdrdir)/ruby/internal/arithmetic.h
cstr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -413,6 +431,15 @@ cstr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
cstr.o: $(hdrdir)/ruby/internal/ctype.h
cstr.o: $(hdrdir)/ruby/internal/dllexport.h
cstr.o: $(hdrdir)/ruby/internal/dosish.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/re.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/string.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+cstr.o: $(hdrdir)/ruby/internal/encoding/transcode.h
cstr.o: $(hdrdir)/ruby/internal/error.h
cstr.o: $(hdrdir)/ruby/internal/eval.h
cstr.o: $(hdrdir)/ruby/internal/event.h
@@ -491,7 +518,6 @@ 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)
@@ -502,7 +528,6 @@ 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
@@ -510,6 +535,7 @@ 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/abi.h
ellipsize.o: $(hdrdir)/ruby/internal/anyargs.h
ellipsize.o: $(hdrdir)/ruby/internal/arithmetic.h
ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -662,7 +688,6 @@ 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
@@ -671,6 +696,7 @@ 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/abi.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
@@ -740,6 +766,15 @@ enc_associate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
enc_associate.o: $(hdrdir)/ruby/internal/ctype.h
enc_associate.o: $(hdrdir)/ruby/internal/dllexport.h
enc_associate.o: $(hdrdir)/ruby/internal/dosish.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_associate.o: $(hdrdir)/ruby/internal/encoding/transcode.h
enc_associate.o: $(hdrdir)/ruby/internal/error.h
enc_associate.o: $(hdrdir)/ruby/internal/eval.h
enc_associate.o: $(hdrdir)/ruby/internal/event.h
@@ -824,7 +859,6 @@ 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
@@ -833,6 +867,7 @@ 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/abi.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
@@ -902,6 +937,15 @@ enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/ctype.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dllexport.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dosish.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/re.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/string.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/encoding/transcode.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/error.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/eval.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/event.h
@@ -987,7 +1031,6 @@ 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
@@ -996,6 +1039,7 @@ 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/abi.h
fstring.o: $(hdrdir)/ruby/internal/anyargs.h
fstring.o: $(hdrdir)/ruby/internal/arithmetic.h
fstring.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1065,6 +1109,15 @@ fstring.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
fstring.o: $(hdrdir)/ruby/internal/ctype.h
fstring.o: $(hdrdir)/ruby/internal/dllexport.h
fstring.o: $(hdrdir)/ruby/internal/dosish.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/re.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/string.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+fstring.o: $(hdrdir)/ruby/internal/encoding/transcode.h
fstring.o: $(hdrdir)/ruby/internal/error.h
fstring.o: $(hdrdir)/ruby/internal/eval.h
fstring.o: $(hdrdir)/ruby/internal/event.h
@@ -1150,7 +1203,6 @@ 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
@@ -1158,6 +1210,7 @@ init.o: $(hdrdir)/ruby/backward/2/stdalign.h
init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1310,7 +1363,6 @@ 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
@@ -1318,6 +1370,7 @@ 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/abi.h
modify.o: $(hdrdir)/ruby/internal/anyargs.h
modify.o: $(hdrdir)/ruby/internal/arithmetic.h
modify.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1470,7 +1523,6 @@ 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
@@ -1479,6 +1531,7 @@ 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/abi.h
new.o: $(hdrdir)/ruby/internal/anyargs.h
new.o: $(hdrdir)/ruby/internal/arithmetic.h
new.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1548,6 +1601,15 @@ new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
new.o: $(hdrdir)/ruby/internal/ctype.h
new.o: $(hdrdir)/ruby/internal/dllexport.h
new.o: $(hdrdir)/ruby/internal/dosish.h
+new.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+new.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+new.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+new.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+new.o: $(hdrdir)/ruby/internal/encoding/re.h
+new.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+new.o: $(hdrdir)/ruby/internal/encoding/string.h
+new.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+new.o: $(hdrdir)/ruby/internal/encoding/transcode.h
new.o: $(hdrdir)/ruby/internal/error.h
new.o: $(hdrdir)/ruby/internal/eval.h
new.o: $(hdrdir)/ruby/internal/event.h
@@ -1633,7 +1695,6 @@ 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
@@ -1641,6 +1702,7 @@ 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/abi.h
nofree.o: $(hdrdir)/ruby/internal/anyargs.h
nofree.o: $(hdrdir)/ruby/internal/arithmetic.h
nofree.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1787,13 +1849,11 @@ nofree.o: $(hdrdir)/ruby/subst.h
nofree.o: nofree.c
normalize.o: $(RUBY_EXTCONF_H)
normalize.o: $(arch_hdrdir)/ruby/config.h
-normalize.o: $(hdrdir)/ruby.h
normalize.o: $(hdrdir)/ruby/assert.h
normalize.o: $(hdrdir)/ruby/backward.h
normalize.o: $(hdrdir)/ruby/backward/2/assume.h
normalize.o: $(hdrdir)/ruby/backward/2/attributes.h
normalize.o: $(hdrdir)/ruby/backward/2/bool.h
-normalize.o: $(hdrdir)/ruby/backward/2/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
@@ -1802,6 +1862,7 @@ 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/abi.h
normalize.o: $(hdrdir)/ruby/internal/anyargs.h
normalize.o: $(hdrdir)/ruby/internal/arithmetic.h
normalize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1871,6 +1932,15 @@ normalize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
normalize.o: $(hdrdir)/ruby/internal/ctype.h
normalize.o: $(hdrdir)/ruby/internal/dllexport.h
normalize.o: $(hdrdir)/ruby/internal/dosish.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/re.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/string.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+normalize.o: $(hdrdir)/ruby/internal/encoding/transcode.h
normalize.o: $(hdrdir)/ruby/internal/error.h
normalize.o: $(hdrdir)/ruby/internal/eval.h
normalize.o: $(hdrdir)/ruby/internal/event.h
@@ -1947,7 +2017,6 @@ 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)
@@ -1958,7 +2027,6 @@ 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
@@ -1967,6 +2035,7 @@ 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/abi.h
qsort.o: $(hdrdir)/ruby/internal/anyargs.h
qsort.o: $(hdrdir)/ruby/internal/arithmetic.h
qsort.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -2036,6 +2105,15 @@ qsort.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
qsort.o: $(hdrdir)/ruby/internal/ctype.h
qsort.o: $(hdrdir)/ruby/internal/dllexport.h
qsort.o: $(hdrdir)/ruby/internal/dosish.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/re.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/string.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+qsort.o: $(hdrdir)/ruby/internal/encoding/transcode.h
qsort.o: $(hdrdir)/ruby/internal/error.h
qsort.o: $(hdrdir)/ruby/internal/eval.h
qsort.o: $(hdrdir)/ruby/internal/event.h
@@ -2122,7 +2200,6 @@ 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
@@ -2130,6 +2207,7 @@ 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/abi.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
@@ -2282,7 +2360,6 @@ 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
@@ -2290,6 +2367,7 @@ 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/abi.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
@@ -2442,7 +2520,6 @@ 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
@@ -2450,6 +2527,7 @@ 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/abi.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
diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c
index 2374319fe3..64f079251d 100644
--- a/ext/-test-/string/fstring.c
+++ b/ext/-test-/string/fstring.c
@@ -12,13 +12,13 @@ bug_s_fstring(VALUE self, VALUE str)
VALUE
bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
{
- return rb_enc_interned_str("foo", 3, RDATA(encoding)->data);
+ return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
}
VALUE
bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
{
- return rb_enc_str_new("foo", 3, RDATA(encoding)->data);
+ return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
}
void
diff --git a/ext/-test-/string/qsort.c b/ext/-test-/string/qsort.c
index fb7ea3d8cb..4a641e74e3 100644
--- a/ext/-test-/string/qsort.c
+++ b/ext/-test-/string/qsort.c
@@ -35,22 +35,22 @@ bug_str_qsort_bang(int argc, VALUE *argv, VALUE str)
rb_scan_args(argc, argv, "03", &beg, &len, &size);
l = RSTRING_LEN(str);
if (!NIL_P(beg) && (b = NUM2INT(beg)) < 0 && (b += l) < 0) {
- rb_raise(rb_eArgError, "out of bounds");
+ rb_raise(rb_eArgError, "out of bounds");
}
if (!NIL_P(size) && (s = NUM2INT(size)) < 0) {
- rb_raise(rb_eArgError, "negative size");
+ rb_raise(rb_eArgError, "negative size");
}
if (NIL_P(len) ||
- (((n = NUM2INT(len)) < 0) ?
- (rb_raise(rb_eArgError, "negative length"), 0) :
- (b + n * s > l))) {
- n = (l - b) / s;
+ (((n = NUM2INT(len)) < 0) ?
+ (rb_raise(rb_eArgError, "negative length"), 0) :
+ (b + n * s > l))) {
+ n = (l - b) / s;
}
rb_str_modify(str);
d.enc = rb_enc_get(str);
d.elsize = s;
ruby_qsort(RSTRING_PTR(str) + b, n, s,
- rb_block_given_p() ? cmp_1 : cmp_2, &d);
+ rb_block_given_p() ? cmp_1 : cmp_2, &d);
return str;
}
diff --git a/ext/-test-/string/set_len.c b/ext/-test-/string/set_len.c
index 219cea404c..049da2cdb5 100644
--- a/ext/-test-/string/set_len.c
+++ b/ext/-test-/string/set_len.c
@@ -7,8 +7,18 @@ bug_str_set_len(VALUE str, VALUE len)
return str;
}
+static VALUE
+bug_str_append(VALUE str, VALUE addendum)
+{
+ StringValue(addendum);
+ rb_str_modify_expand(str, RSTRING_LEN(addendum));
+ memcpy(RSTRING_END(str), RSTRING_PTR(addendum), RSTRING_LEN(addendum));
+ return str;
+}
+
void
Init_string_set_len(VALUE klass)
{
rb_define_method(klass, "set_len", bug_str_set_len, 1);
+ rb_define_method(klass, "append", bug_str_append, 1);
}
diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend
index aebf9a88b7..920a065216 100644
--- a/ext/-test-/struct/depend
+++ b/ext/-test-/struct/depend
@@ -2,6 +2,19 @@
duplicate.o: $(RUBY_EXTCONF_H)
duplicate.o: $(arch_hdrdir)/ruby/config.h
duplicate.o: $(hdrdir)/ruby.h
+duplicate.o: $(hdrdir)/ruby/assert.h
+duplicate.o: $(hdrdir)/ruby/backward.h
+duplicate.o: $(hdrdir)/ruby/backward/2/assume.h
+duplicate.o: $(hdrdir)/ruby/backward/2/attributes.h
+duplicate.o: $(hdrdir)/ruby/backward/2/bool.h
+duplicate.o: $(hdrdir)/ruby/backward/2/inttypes.h
+duplicate.o: $(hdrdir)/ruby/backward/2/limits.h
+duplicate.o: $(hdrdir)/ruby/backward/2/long_long.h
+duplicate.o: $(hdrdir)/ruby/backward/2/stdalign.h
+duplicate.o: $(hdrdir)/ruby/backward/2/stdarg.h
+duplicate.o: $(hdrdir)/ruby/defines.h
+duplicate.o: $(hdrdir)/ruby/intern.h
+duplicate.o: $(hdrdir)/ruby/internal/abi.h
duplicate.o: $(hdrdir)/ruby/internal/anyargs.h
duplicate.o: $(hdrdir)/ruby/internal/arithmetic.h
duplicate.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
duplicate.o: $(hdrdir)/ruby/ruby.h
duplicate.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -301,19 +314,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -322,6 +322,19 @@ 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/assert.h
+len.o: $(hdrdir)/ruby/backward.h
+len.o: $(hdrdir)/ruby/backward/2/assume.h
+len.o: $(hdrdir)/ruby/backward/2/attributes.h
+len.o: $(hdrdir)/ruby/backward/2/bool.h
+len.o: $(hdrdir)/ruby/backward/2/inttypes.h
+len.o: $(hdrdir)/ruby/backward/2/limits.h
+len.o: $(hdrdir)/ruby/backward/2/long_long.h
+len.o: $(hdrdir)/ruby/backward/2/stdalign.h
+len.o: $(hdrdir)/ruby/backward/2/stdarg.h
+len.o: $(hdrdir)/ruby/defines.h
+len.o: $(hdrdir)/ruby/intern.h
+len.o: $(hdrdir)/ruby/internal/abi.h
len.o: $(hdrdir)/ruby/internal/anyargs.h
len.o: $(hdrdir)/ruby/internal/arithmetic.h
len.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -461,19 +474,6 @@ 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
len.o: $(hdrdir)/ruby/ruby.h
len.o: $(hdrdir)/ruby/st.h
@@ -482,6 +482,19 @@ 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/assert.h
+member.o: $(hdrdir)/ruby/backward.h
+member.o: $(hdrdir)/ruby/backward/2/assume.h
+member.o: $(hdrdir)/ruby/backward/2/attributes.h
+member.o: $(hdrdir)/ruby/backward/2/bool.h
+member.o: $(hdrdir)/ruby/backward/2/inttypes.h
+member.o: $(hdrdir)/ruby/backward/2/limits.h
+member.o: $(hdrdir)/ruby/backward/2/long_long.h
+member.o: $(hdrdir)/ruby/backward/2/stdalign.h
+member.o: $(hdrdir)/ruby/backward/2/stdarg.h
+member.o: $(hdrdir)/ruby/defines.h
+member.o: $(hdrdir)/ruby/intern.h
+member.o: $(hdrdir)/ruby/internal/abi.h
member.o: $(hdrdir)/ruby/internal/anyargs.h
member.o: $(hdrdir)/ruby/internal/arithmetic.h
member.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -621,19 +634,6 @@ 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
member.o: $(hdrdir)/ruby/ruby.h
member.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/struct/member.c b/ext/-test-/struct/member.c
index 1d404039b4..f5400fe477 100644
--- a/ext/-test-/struct/member.c
+++ b/ext/-test-/struct/member.c
@@ -6,7 +6,7 @@ bug_struct_get(VALUE obj, VALUE name)
ID id = rb_check_id(&name);
if (!id) {
- rb_name_error_str(name, "`%"PRIsVALUE"' is not a struct member", name);
+ rb_name_error_str(name, "`%"PRIsVALUE"' is not a struct member", name);
}
return rb_struct_getmember(obj, id);
}
diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend
index 9b75e866da..b94e4ce821 100644
--- a/ext/-test-/symbol/depend
+++ b/ext/-test-/symbol/depend
@@ -2,6 +2,19 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,19 @@ 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/assert.h
+type.o: $(hdrdir)/ruby/backward.h
+type.o: $(hdrdir)/ruby/backward/2/assume.h
+type.o: $(hdrdir)/ruby/backward/2/attributes.h
+type.o: $(hdrdir)/ruby/backward/2/bool.h
+type.o: $(hdrdir)/ruby/backward/2/inttypes.h
+type.o: $(hdrdir)/ruby/backward/2/limits.h
+type.o: $(hdrdir)/ruby/backward/2/long_long.h
+type.o: $(hdrdir)/ruby/backward/2/stdalign.h
+type.o: $(hdrdir)/ruby/backward/2/stdarg.h
+type.o: $(hdrdir)/ruby/defines.h
+type.o: $(hdrdir)/ruby/intern.h
+type.o: $(hdrdir)/ruby/internal/abi.h
type.o: $(hdrdir)/ruby/internal/anyargs.h
type.o: $(hdrdir)/ruby/internal/arithmetic.h
type.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -301,19 +314,6 @@ 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
type.o: $(hdrdir)/ruby/ruby.h
type.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/symbol/type.c b/ext/-test-/symbol/type.c
index e51e09eb26..8d0e647340 100644
--- a/ext/-test-/symbol/type.c
+++ b/ext/-test-/symbol/type.c
@@ -2,12 +2,12 @@
#ifdef HAVE_RB_IS_CONST_NAME
# define get_symbol_type(type, t, name) do { \
- ID id = rb_check_id(&name); \
- t = (id ? rb_is_##type##_id(id) : rb_is_##type##_name(name)); \
+ ID id = rb_check_id(&name); \
+ t = (id ? rb_is_##type##_id(id) : rb_is_##type##_name(name)); \
} while (0)
#else
# define get_symbol_type(type, t, name) do { \
- t = rb_is_##type##_id(rb_to_id(name)); \
+ t = rb_is_##type##_id(rb_to_id(name)); \
} while (0)
#endif
diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend
new file mode 100644
index 0000000000..e2fcd060d8
--- /dev/null
+++ b/ext/-test-/thread/instrumentation/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+instrumentation.o: $(RUBY_EXTCONF_H)
+instrumentation.o: $(arch_hdrdir)/ruby/config.h
+instrumentation.o: $(hdrdir)/ruby/assert.h
+instrumentation.o: $(hdrdir)/ruby/atomic.h
+instrumentation.o: $(hdrdir)/ruby/backward.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/assume.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/attributes.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/bool.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/inttypes.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/limits.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/long_long.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/stdalign.h
+instrumentation.o: $(hdrdir)/ruby/backward/2/stdarg.h
+instrumentation.o: $(hdrdir)/ruby/defines.h
+instrumentation.o: $(hdrdir)/ruby/intern.h
+instrumentation.o: $(hdrdir)/ruby/internal/abi.h
+instrumentation.o: $(hdrdir)/ruby/internal/anyargs.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+instrumentation.o: $(hdrdir)/ruby/internal/assume.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/artificial.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/cold.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/const.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/error.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/format.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noalias.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noinline.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/pure.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/restrict.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/warning.h
+instrumentation.o: $(hdrdir)/ruby/internal/attr/weakref.h
+instrumentation.o: $(hdrdir)/ruby/internal/cast.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+instrumentation.o: $(hdrdir)/ruby/internal/compiler_since.h
+instrumentation.o: $(hdrdir)/ruby/internal/config.h
+instrumentation.o: $(hdrdir)/ruby/internal/constant_p.h
+instrumentation.o: $(hdrdir)/ruby/internal/core.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rarray.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rbasic.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rbignum.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rclass.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rdata.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rfile.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rhash.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/robject.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rregexp.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rstring.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rstruct.h
+instrumentation.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+instrumentation.o: $(hdrdir)/ruby/internal/ctype.h
+instrumentation.o: $(hdrdir)/ruby/internal/dllexport.h
+instrumentation.o: $(hdrdir)/ruby/internal/dosish.h
+instrumentation.o: $(hdrdir)/ruby/internal/error.h
+instrumentation.o: $(hdrdir)/ruby/internal/eval.h
+instrumentation.o: $(hdrdir)/ruby/internal/event.h
+instrumentation.o: $(hdrdir)/ruby/internal/fl_type.h
+instrumentation.o: $(hdrdir)/ruby/internal/gc.h
+instrumentation.o: $(hdrdir)/ruby/internal/glob.h
+instrumentation.o: $(hdrdir)/ruby/internal/globals.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/builtin.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/extension.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/feature.h
+instrumentation.o: $(hdrdir)/ruby/internal/has/warning.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/array.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/bignum.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/class.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/compar.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/complex.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/cont.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/dir.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/enum.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/error.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/eval.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/file.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/gc.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/hash.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/io.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/load.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/marshal.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/numeric.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/object.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/parse.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/proc.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/process.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/random.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/range.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/rational.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/re.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/ruby.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/select.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/signal.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/string.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/struct.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/thread.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/time.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/variable.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/vm.h
+instrumentation.o: $(hdrdir)/ruby/internal/interpreter.h
+instrumentation.o: $(hdrdir)/ruby/internal/iterator.h
+instrumentation.o: $(hdrdir)/ruby/internal/memory.h
+instrumentation.o: $(hdrdir)/ruby/internal/method.h
+instrumentation.o: $(hdrdir)/ruby/internal/module.h
+instrumentation.o: $(hdrdir)/ruby/internal/newobj.h
+instrumentation.o: $(hdrdir)/ruby/internal/rgengc.h
+instrumentation.o: $(hdrdir)/ruby/internal/scan_args.h
+instrumentation.o: $(hdrdir)/ruby/internal/special_consts.h
+instrumentation.o: $(hdrdir)/ruby/internal/static_assert.h
+instrumentation.o: $(hdrdir)/ruby/internal/stdalign.h
+instrumentation.o: $(hdrdir)/ruby/internal/stdbool.h
+instrumentation.o: $(hdrdir)/ruby/internal/symbol.h
+instrumentation.o: $(hdrdir)/ruby/internal/value.h
+instrumentation.o: $(hdrdir)/ruby/internal/value_type.h
+instrumentation.o: $(hdrdir)/ruby/internal/variable.h
+instrumentation.o: $(hdrdir)/ruby/internal/warning_push.h
+instrumentation.o: $(hdrdir)/ruby/internal/xmalloc.h
+instrumentation.o: $(hdrdir)/ruby/missing.h
+instrumentation.o: $(hdrdir)/ruby/ruby.h
+instrumentation.o: $(hdrdir)/ruby/st.h
+instrumentation.o: $(hdrdir)/ruby/subst.h
+instrumentation.o: $(hdrdir)/ruby/thread.h
+instrumentation.o: $(hdrdir)/ruby/thread_native.h
+instrumentation.o: instrumentation.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread/instrumentation/extconf.rb b/ext/-test-/thread/instrumentation/extconf.rb
new file mode 100644
index 0000000000..a48ba3c045
--- /dev/null
+++ b/ext/-test-/thread/instrumentation/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/thread/instrumentation")
diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c
new file mode 100644
index 0000000000..d2a2c2740b
--- /dev/null
+++ b/ext/-test-/thread/instrumentation/instrumentation.c
@@ -0,0 +1,141 @@
+#include "ruby/ruby.h"
+#include "ruby/atomic.h"
+#include "ruby/thread.h"
+
+static rb_atomic_t started_count = 0;
+static rb_atomic_t ready_count = 0;
+static rb_atomic_t resumed_count = 0;
+static rb_atomic_t suspended_count = 0;
+static rb_atomic_t exited_count = 0;
+
+#if __STDC_VERSION__ >= 201112
+ #define RB_THREAD_LOCAL_SPECIFIER _Thread_local
+#elif defined(__GNUC__) && !defined(RB_THREAD_LOCAL_SPECIFIER_IS_UNSUPPORTED)
+ /* note that ICC (linux) and Clang are covered by __GNUC__ */
+ #define RB_THREAD_LOCAL_SPECIFIER __thread
+#else
+ #define RB_THREAD_LOCAL_SPECIFIER
+#endif
+
+static RB_THREAD_LOCAL_SPECIFIER unsigned int local_ready_count = 0;
+static RB_THREAD_LOCAL_SPECIFIER unsigned int local_resumed_count = 0;
+static RB_THREAD_LOCAL_SPECIFIER unsigned int local_suspended_count = 0;
+
+static void
+ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data)
+{
+ switch (event) {
+ case RUBY_INTERNAL_THREAD_EVENT_STARTED:
+ RUBY_ATOMIC_INC(started_count);
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_READY:
+ RUBY_ATOMIC_INC(ready_count);
+ local_ready_count++;
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_RESUMED:
+ RUBY_ATOMIC_INC(resumed_count);
+ local_resumed_count++;
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED:
+ RUBY_ATOMIC_INC(suspended_count);
+ local_suspended_count++;
+ break;
+ case RUBY_INTERNAL_THREAD_EVENT_EXITED:
+ RUBY_ATOMIC_INC(exited_count);
+ break;
+ }
+}
+
+static rb_internal_thread_event_hook_t * single_hook = NULL;
+
+static VALUE
+thread_counters(VALUE thread)
+{
+ VALUE array = rb_ary_new2(5);
+ rb_ary_push(array, UINT2NUM(started_count));
+ rb_ary_push(array, UINT2NUM(ready_count));
+ rb_ary_push(array, UINT2NUM(resumed_count));
+ rb_ary_push(array, UINT2NUM(suspended_count));
+ rb_ary_push(array, UINT2NUM(exited_count));
+ return array;
+}
+
+static VALUE
+thread_local_counters(VALUE thread)
+{
+ VALUE array = rb_ary_new2(3);
+ rb_ary_push(array, UINT2NUM(local_ready_count));
+ rb_ary_push(array, UINT2NUM(local_resumed_count));
+ rb_ary_push(array, UINT2NUM(local_suspended_count));
+ return array;
+}
+
+static VALUE
+thread_reset_counters(VALUE thread)
+{
+ RUBY_ATOMIC_SET(started_count, 0);
+ RUBY_ATOMIC_SET(ready_count, 0);
+ RUBY_ATOMIC_SET(resumed_count, 0);
+ RUBY_ATOMIC_SET(suspended_count, 0);
+ RUBY_ATOMIC_SET(exited_count, 0);
+ local_ready_count = 0;
+ local_resumed_count = 0;
+ local_suspended_count = 0;
+ return Qtrue;
+}
+
+static VALUE
+thread_register_callback(VALUE thread)
+{
+ single_hook = rb_internal_thread_add_event_hook(
+ ex_callback,
+ RUBY_INTERNAL_THREAD_EVENT_STARTED |
+ RUBY_INTERNAL_THREAD_EVENT_READY |
+ RUBY_INTERNAL_THREAD_EVENT_RESUMED |
+ RUBY_INTERNAL_THREAD_EVENT_SUSPENDED |
+ RUBY_INTERNAL_THREAD_EVENT_EXITED,
+ NULL
+ );
+
+ return Qnil;
+}
+
+static VALUE
+thread_unregister_callback(VALUE thread)
+{
+ if (single_hook) {
+ rb_internal_thread_remove_event_hook(single_hook);
+ single_hook = NULL;
+ }
+
+ return Qnil;
+}
+
+static VALUE
+thread_register_and_unregister_callback(VALUE thread)
+{
+ rb_internal_thread_event_hook_t * hooks[5];
+ for (int i = 0; i < 5; i++) {
+ hooks[i] = rb_internal_thread_add_event_hook(ex_callback, RUBY_INTERNAL_THREAD_EVENT_READY, NULL);
+ }
+
+ if (!rb_internal_thread_remove_event_hook(hooks[4])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[0])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[3])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[2])) return Qfalse;
+ if (!rb_internal_thread_remove_event_hook(hooks[1])) return Qfalse;
+ return Qtrue;
+}
+
+void
+Init_instrumentation(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation");
+ rb_define_singleton_method(klass, "counters", thread_counters, 0);
+ rb_define_singleton_method(klass, "local_counters", thread_local_counters, 0);
+ rb_define_singleton_method(klass, "reset_counters", thread_reset_counters, 0);
+ rb_define_singleton_method(klass, "register_callback", thread_register_callback, 0);
+ rb_define_singleton_method(klass, "unregister_callback", thread_unregister_callback, 0);
+ rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_callback, 0);
+}
diff --git a/ext/-test-/thread_fd/depend b/ext/-test-/thread_fd/depend
index ad6f66f312..ecf738108a 100644
--- a/ext/-test-/thread_fd/depend
+++ b/ext/-test-/thread_fd/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
thread_fd.o: $(RUBY_EXTCONF_H)
thread_fd.o: $(arch_hdrdir)/ruby/config.h
+thread_fd.o: $(hdrdir)/ruby/assert.h
+thread_fd.o: $(hdrdir)/ruby/backward.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/assume.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/attributes.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/bool.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/inttypes.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/limits.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/long_long.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/stdalign.h
+thread_fd.o: $(hdrdir)/ruby/backward/2/stdarg.h
+thread_fd.o: $(hdrdir)/ruby/defines.h
+thread_fd.o: $(hdrdir)/ruby/intern.h
+thread_fd.o: $(hdrdir)/ruby/internal/abi.h
thread_fd.o: $(hdrdir)/ruby/internal/anyargs.h
thread_fd.o: $(hdrdir)/ruby/internal/arithmetic.h
thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ thread_fd.o: $(hdrdir)/ruby/internal/value_type.h
thread_fd.o: $(hdrdir)/ruby/internal/variable.h
thread_fd.o: $(hdrdir)/ruby/internal/warning_push.h
thread_fd.o: $(hdrdir)/ruby/internal/xmalloc.h
-thread_fd.o: $(hdrdir)/ruby/assert.h
-thread_fd.o: $(hdrdir)/ruby/backward.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/assume.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/attributes.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/bool.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/inttypes.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/limits.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/long_long.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/stdalign.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/stdarg.h
-thread_fd.o: $(hdrdir)/ruby/defines.h
-thread_fd.o: $(hdrdir)/ruby/intern.h
thread_fd.o: $(hdrdir)/ruby/missing.h
thread_fd.o: $(hdrdir)/ruby/ruby.h
thread_fd.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend
index 48b41dd678..b7d1a2b114 100644
--- a/ext/-test-/time/depend
+++ b/ext/-test-/time/depend
@@ -2,6 +2,19 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -162,6 +162,20 @@ 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/assert.h
+leap_second.o: $(hdrdir)/ruby/backward.h
+leap_second.o: $(hdrdir)/ruby/backward/2/assume.h
+leap_second.o: $(hdrdir)/ruby/backward/2/attributes.h
+leap_second.o: $(hdrdir)/ruby/backward/2/bool.h
+leap_second.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+leap_second.o: $(hdrdir)/ruby/backward/2/inttypes.h
+leap_second.o: $(hdrdir)/ruby/backward/2/limits.h
+leap_second.o: $(hdrdir)/ruby/backward/2/long_long.h
+leap_second.o: $(hdrdir)/ruby/backward/2/stdalign.h
+leap_second.o: $(hdrdir)/ruby/backward/2/stdarg.h
+leap_second.o: $(hdrdir)/ruby/defines.h
+leap_second.o: $(hdrdir)/ruby/intern.h
+leap_second.o: $(hdrdir)/ruby/internal/abi.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
@@ -301,19 +315,6 @@ 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
@@ -326,6 +327,19 @@ leap_second.o: leap_second.c
new.o: $(RUBY_EXTCONF_H)
new.o: $(arch_hdrdir)/ruby/config.h
new.o: $(hdrdir)/ruby.h
+new.o: $(hdrdir)/ruby/assert.h
+new.o: $(hdrdir)/ruby/backward.h
+new.o: $(hdrdir)/ruby/backward/2/assume.h
+new.o: $(hdrdir)/ruby/backward/2/attributes.h
+new.o: $(hdrdir)/ruby/backward/2/bool.h
+new.o: $(hdrdir)/ruby/backward/2/inttypes.h
+new.o: $(hdrdir)/ruby/backward/2/limits.h
+new.o: $(hdrdir)/ruby/backward/2/long_long.h
+new.o: $(hdrdir)/ruby/backward/2/stdalign.h
+new.o: $(hdrdir)/ruby/backward/2/stdarg.h
+new.o: $(hdrdir)/ruby/defines.h
+new.o: $(hdrdir)/ruby/intern.h
+new.o: $(hdrdir)/ruby/internal/abi.h
new.o: $(hdrdir)/ruby/internal/anyargs.h
new.o: $(hdrdir)/ruby/internal/arithmetic.h
new.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -465,19 +479,6 @@ 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
new.o: $(hdrdir)/ruby/ruby.h
new.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend
index dac1bb278e..8e2aa7eab6 100644
--- a/ext/-test-/tracepoint/depend
+++ b/ext/-test-/tracepoint/depend
@@ -1,6 +1,20 @@
# AUTOGENERATED DEPENDENCIES START
gc_hook.o: $(RUBY_EXTCONF_H)
gc_hook.o: $(arch_hdrdir)/ruby/config.h
+gc_hook.o: $(hdrdir)/ruby/assert.h
+gc_hook.o: $(hdrdir)/ruby/backward.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/assume.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/attributes.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/bool.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/inttypes.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/limits.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/long_long.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/stdalign.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/stdarg.h
+gc_hook.o: $(hdrdir)/ruby/debug.h
+gc_hook.o: $(hdrdir)/ruby/defines.h
+gc_hook.o: $(hdrdir)/ruby/intern.h
+gc_hook.o: $(hdrdir)/ruby/internal/abi.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
@@ -140,20 +154,6 @@ 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
gc_hook.o: $(hdrdir)/ruby/missing.h
gc_hook.o: $(hdrdir)/ruby/ruby.h
gc_hook.o: $(hdrdir)/ruby/st.h
@@ -161,6 +161,20 @@ 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/assert.h
+tracepoint.o: $(hdrdir)/ruby/backward.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/assume.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/attributes.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/bool.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/limits.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/long_long.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/stdarg.h
+tracepoint.o: $(hdrdir)/ruby/debug.h
+tracepoint.o: $(hdrdir)/ruby/defines.h
+tracepoint.o: $(hdrdir)/ruby/intern.h
+tracepoint.o: $(hdrdir)/ruby/internal/abi.h
tracepoint.o: $(hdrdir)/ruby/internal/anyargs.h
tracepoint.o: $(hdrdir)/ruby/internal/arithmetic.h
tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -300,20 +314,6 @@ 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
tracepoint.o: $(hdrdir)/ruby/missing.h
tracepoint.o: $(hdrdir)/ruby/ruby.h
tracepoint.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/tracepoint/gc_hook.c b/ext/-test-/tracepoint/gc_hook.c
index 5fd46fa518..a3f4e7f68a 100644
--- a/ext/-test-/tracepoint/gc_hook.c
+++ b/ext/-test-/tracepoint/gc_hook.c
@@ -28,12 +28,12 @@ static void
gc_start_end_i(VALUE tpval, void *data)
{
if (0) {
- rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
- fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end");
+ rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
+ fprintf(stderr, "trace: %s\n", rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_GC_START ? "gc_start" : "gc_end");
}
if (invoking == 0) {
- rb_postponed_job_register(0, invoke_proc, data);
+ rb_postponed_job_register(0, invoke_proc, data);
}
}
@@ -45,19 +45,19 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_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);
+ RTEST(tpval = rb_ivar_get(module, tp_key))) {
+ rb_tracepoint_disable(tpval);
+ rb_ivar_set(module, tp_key, Qnil);
}
if (RTEST(proc)) {
- if (!rb_obj_is_proc(proc)) {
- rb_raise(rb_eTypeError, "trace_func needs to be Proc");
- }
+ if (!rb_obj_is_proc(proc)) {
+ rb_raise(rb_eTypeError, "trace_func needs to be Proc");
+ }
- tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc);
- rb_ivar_set(module, tp_key, tpval);
- rb_tracepoint_enable(tpval);
+ tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc);
+ rb_ivar_set(module, tp_key, tpval);
+ rb_tracepoint_enable(tpval);
}
return proc;
@@ -67,7 +67,7 @@ static VALUE
set_after_gc_start(VALUE module, VALUE proc)
{
return set_gc_hook(module, proc, RUBY_INTERNAL_EVENT_GC_START,
- "__set_after_gc_start_tpval__", "__set_after_gc_start_proc__");
+ "__set_after_gc_start_tpval__", "__set_after_gc_start_proc__");
}
static VALUE
diff --git a/ext/-test-/tracepoint/tracepoint.c b/ext/-test-/tracepoint/tracepoint.c
index aa8c212f99..2826cc038c 100644
--- a/ext/-test-/tracepoint/tracepoint.c
+++ b/ext/-test-/tracepoint/tracepoint.c
@@ -21,35 +21,35 @@ tracepoint_track_objspace_events_i(VALUE tpval, void *data)
switch (rb_tracearg_event_flag(tparg)) {
case RUBY_INTERNAL_EVENT_NEWOBJ:
- {
- VALUE obj = rb_tracearg_object(tparg);
- if (track->objects_count < objects_max)
- track->objects[track->objects_count++] = obj;
- track->newobj_count++;
- break;
- }
+ {
+ VALUE obj = rb_tracearg_object(tparg);
+ if (track->objects_count < objects_max)
+ track->objects[track->objects_count++] = obj;
+ track->newobj_count++;
+ break;
+ }
case RUBY_INTERNAL_EVENT_FREEOBJ:
- {
- track->free_count++;
- break;
- }
+ {
+ track->free_count++;
+ break;
+ }
case RUBY_INTERNAL_EVENT_GC_START:
- {
- track->gc_start_count++;
- break;
- }
+ {
+ track->gc_start_count++;
+ break;
+ }
case RUBY_INTERNAL_EVENT_GC_END_MARK:
- {
- track->gc_end_mark_count++;
- break;
- }
+ {
+ track->gc_end_mark_count++;
+ break;
+ }
case RUBY_INTERNAL_EVENT_GC_END_SWEEP:
- {
- track->gc_end_sweep_count++;
- break;
- }
+ {
+ track->gc_end_sweep_count++;
+ break;
+ }
default:
- rb_raise(rb_eRuntimeError, "unknown event");
+ rb_raise(rb_eRuntimeError, "unknown event");
}
}
@@ -58,9 +58,9 @@ tracepoint_track_objspace_events(VALUE self)
{
struct tracepoint_track track = {0, 0, 0, 0, 0,};
VALUE tpval = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREEOBJ |
- RUBY_INTERNAL_EVENT_GC_START | RUBY_INTERNAL_EVENT_GC_END_MARK |
- RUBY_INTERNAL_EVENT_GC_END_SWEEP,
- tracepoint_track_objspace_events_i, &track);
+ RUBY_INTERNAL_EVENT_GC_START | RUBY_INTERNAL_EVENT_GC_END_MARK |
+ RUBY_INTERNAL_EVENT_GC_END_SWEEP,
+ tracepoint_track_objspace_events_i, &track);
VALUE result = rb_ary_new();
rb_tracepoint_enable(tpval);
diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend
index 6204fb0524..02f6de6e20 100644
--- a/ext/-test-/typeddata/depend
+++ b/ext/-test-/typeddata/depend
@@ -2,6 +2,19 @@
typeddata.o: $(RUBY_EXTCONF_H)
typeddata.o: $(arch_hdrdir)/ruby/config.h
typeddata.o: $(hdrdir)/ruby.h
+typeddata.o: $(hdrdir)/ruby/assert.h
+typeddata.o: $(hdrdir)/ruby/backward.h
+typeddata.o: $(hdrdir)/ruby/backward/2/assume.h
+typeddata.o: $(hdrdir)/ruby/backward/2/attributes.h
+typeddata.o: $(hdrdir)/ruby/backward/2/bool.h
+typeddata.o: $(hdrdir)/ruby/backward/2/inttypes.h
+typeddata.o: $(hdrdir)/ruby/backward/2/limits.h
+typeddata.o: $(hdrdir)/ruby/backward/2/long_long.h
+typeddata.o: $(hdrdir)/ruby/backward/2/stdalign.h
+typeddata.o: $(hdrdir)/ruby/backward/2/stdarg.h
+typeddata.o: $(hdrdir)/ruby/defines.h
+typeddata.o: $(hdrdir)/ruby/intern.h
+typeddata.o: $(hdrdir)/ruby/internal/abi.h
typeddata.o: $(hdrdir)/ruby/internal/anyargs.h
typeddata.o: $(hdrdir)/ruby/internal/arithmetic.h
typeddata.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
typeddata.o: $(hdrdir)/ruby/ruby.h
typeddata.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/typeddata/typeddata.c b/ext/-test-/typeddata/typeddata.c
index 2adfd56ae8..cf3178fd18 100644
--- a/ext/-test-/typeddata/typeddata.c
+++ b/ext/-test-/typeddata/typeddata.c
@@ -27,7 +27,7 @@ test_make(VALUE klass, VALUE num)
unsigned long i, n = NUM2UINT(num);
for (i = 0; i < n; i++) {
- test_alloc(klass);
+ test_alloc(klass);
}
return Qnil;
diff --git a/ext/-test-/vm/at_exit.c b/ext/-test-/vm/at_exit.c
index 6cfbfafa9e..efc439b26a 100644
--- a/ext/-test-/vm/at_exit.c
+++ b/ext/-test-/vm/at_exit.c
@@ -23,14 +23,14 @@ register_at_exit(VALUE self, VALUE t)
{
switch (t) {
case Qtrue:
- ruby_vm_at_exit(print_begin);
- break;
+ ruby_vm_at_exit(print_begin);
+ break;
case Qfalse:
- ruby_vm_at_exit(print_end);
- break;
+ ruby_vm_at_exit(print_end);
+ break;
default:
- ruby_vm_at_exit(do_nothing);
- break;
+ ruby_vm_at_exit(do_nothing);
+ break;
}
return self;
}
diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend
index 6669e52d4c..7f110d48eb 100644
--- a/ext/-test-/vm/depend
+++ b/ext/-test-/vm/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
at_exit.o: $(RUBY_EXTCONF_H)
at_exit.o: $(arch_hdrdir)/ruby/config.h
+at_exit.o: $(hdrdir)/ruby/assert.h
+at_exit.o: $(hdrdir)/ruby/backward.h
+at_exit.o: $(hdrdir)/ruby/backward/2/assume.h
+at_exit.o: $(hdrdir)/ruby/backward/2/attributes.h
+at_exit.o: $(hdrdir)/ruby/backward/2/bool.h
+at_exit.o: $(hdrdir)/ruby/backward/2/inttypes.h
+at_exit.o: $(hdrdir)/ruby/backward/2/limits.h
+at_exit.o: $(hdrdir)/ruby/backward/2/long_long.h
+at_exit.o: $(hdrdir)/ruby/backward/2/stdalign.h
+at_exit.o: $(hdrdir)/ruby/backward/2/stdarg.h
+at_exit.o: $(hdrdir)/ruby/defines.h
+at_exit.o: $(hdrdir)/ruby/intern.h
+at_exit.o: $(hdrdir)/ruby/internal/abi.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
@@ -140,19 +153,6 @@ 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
at_exit.o: $(hdrdir)/ruby/ruby.h
at_exit.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/wait/depend b/ext/-test-/wait/depend
index 5e3e04692a..e71bda9968 100644
--- a/ext/-test-/wait/depend
+++ b/ext/-test-/wait/depend
@@ -6,7 +6,6 @@ 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
@@ -15,6 +14,7 @@ wait.o: $(hdrdir)/ruby/backward/2/stdarg.h
wait.o: $(hdrdir)/ruby/defines.h
wait.o: $(hdrdir)/ruby/encoding.h
wait.o: $(hdrdir)/ruby/intern.h
+wait.o: $(hdrdir)/ruby/internal/abi.h
wait.o: $(hdrdir)/ruby/internal/anyargs.h
wait.o: $(hdrdir)/ruby/internal/arithmetic.h
wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -84,6 +84,15 @@ wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
wait.o: $(hdrdir)/ruby/internal/ctype.h
wait.o: $(hdrdir)/ruby/internal/dllexport.h
wait.o: $(hdrdir)/ruby/internal/dosish.h
+wait.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+wait.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+wait.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+wait.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+wait.o: $(hdrdir)/ruby/internal/encoding/re.h
+wait.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/encoding/string.h
+wait.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+wait.o: $(hdrdir)/ruby/internal/encoding/transcode.h
wait.o: $(hdrdir)/ruby/internal/error.h
wait.o: $(hdrdir)/ruby/internal/eval.h
wait.o: $(hdrdir)/ruby/internal/event.h
@@ -162,167 +171,4 @@ wait.o: $(hdrdir)/ruby/ruby.h
wait.o: $(hdrdir)/ruby/st.h
wait.o: $(hdrdir)/ruby/subst.h
wait.o: wait.c
-wait_for_single_fd.o: $(RUBY_EXTCONF_H)
-wait_for_single_fd.o: $(arch_hdrdir)/ruby/config.h
-wait_for_single_fd.o: $(hdrdir)/ruby/assert.h
-wait_for_single_fd.o: $(hdrdir)/ruby/backward.h
-wait_for_single_fd.o: $(hdrdir)/ruby/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
-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/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/io.h
-wait_for_single_fd.o: $(hdrdir)/ruby/missing.h
-wait_for_single_fd.o: $(hdrdir)/ruby/onigmo.h
-wait_for_single_fd.o: $(hdrdir)/ruby/oniguruma.h
-wait_for_single_fd.o: $(hdrdir)/ruby/ruby.h
-wait_for_single_fd.o: $(hdrdir)/ruby/st.h
-wait_for_single_fd.o: $(hdrdir)/ruby/subst.h
-wait_for_single_fd.o: wait_for_single_fd.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/win32/console/attribute.c b/ext/-test-/win32/console/attribute.c
index e3e80a199f..b43ba23a5c 100644
--- a/ext/-test-/win32/console/attribute.c
+++ b/ext/-test-/win32/console/attribute.c
@@ -19,13 +19,13 @@ console_info(VALUE klass, VALUE io)
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (!GetConsoleScreenBufferInfo(h, &csbi))
- rb_syserr_fail(rb_w32_map_errno(GetLastError()), "not console");
+ rb_syserr_fail(rb_w32_map_errno(GetLastError()), "not console");
return rb_struct_new(rb_cConsoleScreenBufferInfo,
- INT2FIX(csbi.dwSize.X),
- INT2FIX(csbi.dwSize.Y),
- INT2FIX(csbi.dwCursorPosition.X),
- INT2FIX(csbi.dwCursorPosition.Y),
- INT2FIX(csbi.wAttributes));
+ INT2FIX(csbi.dwSize.X),
+ INT2FIX(csbi.dwSize.Y),
+ INT2FIX(csbi.dwCursorPosition.X),
+ INT2FIX(csbi.dwCursorPosition.Y),
+ INT2FIX(csbi.wAttributes));
}
static VALUE
@@ -44,9 +44,9 @@ void
Init_attribute(VALUE m)
{
rb_cConsoleScreenBufferInfo = rb_struct_define_under(m, "ConsoleScreenBufferInfo",
- "size_x", "size_y",
- "cur_x", "cur_y",
- "attr", NULL);
+ "size_x", "size_y",
+ "cur_x", "cur_y",
+ "attr", NULL);
rb_define_singleton_method(m, "console_info", console_info, 1);
rb_define_singleton_method(m, "console_attribute", console_set_attribute, 2);
diff --git a/ext/-test-/win32/fd_setsize/fd_setsize.c b/ext/-test-/win32/fd_setsize/fd_setsize.c
index 8da8b1eaa0..e29114a0ca 100644
--- a/ext/-test-/win32/fd_setsize/fd_setsize.c
+++ b/ext/-test-/win32/fd_setsize/fd_setsize.c
@@ -37,11 +37,11 @@ test_fdset(VALUE self)
FD_ZERO(&set);
for (i = 0; i < FD_SETSIZE * 2; i++) {
- int sd = socket(AF_INET, SOCK_DGRAM, 0);
- FD_SET(sd, &set);
- if (set.fd_count > FD_SETSIZE) {
- return Qfalse;
- }
+ int sd = socket(AF_INET, SOCK_DGRAM, 0);
+ FD_SET(sd, &set);
+ if (set.fd_count > FD_SETSIZE) {
+ return Qfalse;
+ }
}
return Qtrue;
}
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 65e7c864e2..d6ea35c615 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -7,9 +7,7 @@
*/
/* #define BIGDECIMAL_DEBUG 1 */
-#ifdef BIGDECIMAL_DEBUG
-# define BIGDECIMAL_ENABLE_VPRINT 1
-#endif
+
#include "bigdecimal.h"
#include "ruby/util.h"
@@ -61,6 +59,13 @@ static ID id_to_r;
static ID id_eq;
static ID id_half;
+#define RBD_NUM_ROUNDING_MODES 11
+
+static struct {
+ ID id;
+ uint8_t mode;
+} rbd_rounding_modes[RBD_NUM_ROUNDING_MODES];
+
/* MACRO's to guard objects from GC by keeping them in stack */
#ifdef RBIMPL_ATTR_MAYBE_UNUSED
#define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
@@ -102,10 +107,164 @@ static ID id_half;
# define RB_OBJ_STRING(obj) StringValueCStr(obj)
#endif
+#ifndef MAYBE_UNUSED
+# define MAYBE_UNUSED(x) x
+#endif
+
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
/*
+ * ================== Memory allocation ============================
+ */
+
+#ifdef BIGDECIMAL_DEBUG
+static size_t rbd_allocation_count = 0; /* Memory allocation counter */
+static inline void
+atomic_allocation_count_inc(void)
+{
+ RUBY_ATOMIC_SIZE_INC(rbd_allocation_count);
+}
+static inline void
+atomic_allocation_count_dec_nounderflow(void)
+{
+ if (rbd_allocation_count == 0) return;
+ RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count);
+}
+static void
+check_allocation_count_nonzero(void)
+{
+ if (rbd_allocation_count != 0) return;
+ rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls");
+}
+#else
+# define atomic_allocation_count_inc() /* nothing */
+# define atomic_allocation_count_dec_nounderflow() /* nothing */
+# define check_allocation_count_nonzero() /* nothing */
+#endif /* BIGDECIMAL_DEBUG */
+
+PUREFUNC(static inline size_t rbd_struct_size(size_t const));
+
+static inline size_t
+rbd_struct_size(size_t const internal_digits)
+{
+ size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits;
+ return offsetof(Real, frac) + frac_len * sizeof(DECDIG);
+}
+
+static inline Real *
+rbd_allocate_struct(size_t const internal_digits)
+{
+ size_t const size = rbd_struct_size(internal_digits);
+ Real *real = ruby_xcalloc(1, size);
+ atomic_allocation_count_inc();
+ real->MaxPrec = internal_digits;
+ return real;
+}
+
+static size_t
+rbd_calculate_internal_digits(size_t const digits, bool limit_precision)
+{
+ size_t const len = roomof(digits, BASE_FIG);
+ if (limit_precision) {
+ size_t const prec_limit = VpGetPrecLimit();
+ if (prec_limit > 0) {
+ /* NOTE: 2 more digits for rounding and division */
+ size_t const max_len = roomof(prec_limit, BASE_FIG) + 2;
+ if (len > max_len)
+ return max_len;
+ }
+ }
+
+ return len;
+}
+
+static inline Real *
+rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision)
+{
+ size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision);
+ return rbd_allocate_struct(internal_digits);
+}
+
+static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
+
+static Real *
+rbd_reallocate_struct(Real *real, size_t const internal_digits)
+{
+ size_t const size = rbd_struct_size(internal_digits);
+ VALUE obj = real ? real->obj : 0;
+ Real *new_real = (Real *)ruby_xrealloc(real, size);
+ new_real->MaxPrec = internal_digits;
+ if (obj) {
+ new_real->obj = 0;
+ BigDecimal_wrap_struct(obj, new_real);
+ }
+ return new_real;
+}
+
+static void
+rbd_free_struct(Real *real)
+{
+ if (real != NULL) {
+ check_allocation_count_nonzero();
+ ruby_xfree(real);
+ atomic_allocation_count_dec_nounderflow();
+ }
+}
+
+#define NewZero rbd_allocate_struct_zero
+static Real *
+rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision)
+{
+ Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
+ VpSetZero(real, sign);
+ return real;
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited(int sign, size_t const digits));
+#define NewZeroLimited rbd_allocate_struct_zero_limited
+static inline Real *
+rbd_allocate_struct_zero_limited(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_zero(sign, digits, true);
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit(int sign, size_t const digits));
+#define NewZeroNolimit rbd_allocate_struct_zero_nolimit
+static inline Real *
+rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_zero(sign, digits, false);
+}
+
+#define NewOne rbd_allocate_struct_one
+static Real *
+rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision)
+{
+ Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision);
+ VpSetOne(real);
+ if (sign < 0)
+ VpSetSign(real, VP_SIGN_NEGATIVE_FINITE);
+ return real;
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited(int sign, size_t const digits));
+#define NewOneLimited rbd_allocate_struct_one_limited
+static inline Real *
+rbd_allocate_struct_one_limited(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_one(sign, digits, true);
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit(int sign, size_t const digits));
+#define NewOneNolimit rbd_allocate_struct_one_nolimit
+static inline Real *
+rbd_allocate_struct_one_nolimit(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_one(sign, digits, false);
+}
+
+/*
* ================== Ruby Interface part ==========================
*/
#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
@@ -115,13 +274,12 @@ static ID id_half;
*/
static unsigned short VpGetException(void);
static void VpSetException(unsigned short f);
+static void VpCheckException(Real *p, bool always);
+static VALUE VpCheckGetValue(Real *p);
static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
static int VpLimitRound(Real *c, size_t ixDigit);
static Real *VpCopy(Real *pv, Real const* const x);
-
-#ifdef BIGDECIMAL_ENABLE_VPRINT
static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
-#endif
/*
* **** BigDecimal part ****
@@ -136,7 +294,7 @@ static VALUE BigDecimal_negative_zero(void);
static void
BigDecimal_delete(void *pv)
{
- VpFree(pv);
+ rbd_free_struct(pv);
}
static size_t
@@ -159,31 +317,64 @@ static const rb_data_type_t BigDecimal_data_type = {
#endif
};
-static inline int
-is_kind_of_BigDecimal(VALUE const v)
+static Real *
+rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
{
- return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
+ Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
+ if (real != NULL) {
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
+ BigDecimal_wrap_struct(obj, real);
+ }
+ return real;
}
-static void
-VpCheckException(Real *p, bool always)
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits));
+#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
+static inline Real *
+rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
{
- if (VpIsNaN(p)) {
- VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", always);
- }
- else if (VpIsPosInf(p)) {
- VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", always);
- }
- else if (VpIsNegInf(p)) {
- VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", always);
+ return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits));
+#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
+static inline Real *
+rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
+}
+
+static Real *
+rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
+{
+ Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
+ if (real != NULL) {
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
+ BigDecimal_wrap_struct(obj, real);
}
+ return real;
}
-static VALUE
-VpCheckGetValue(Real *p)
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits));
+#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
+static inline Real *
+rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
{
- VpCheckException(p, false);
- return p->obj;
+ return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits));
+#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
+static inline Real *
+rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
+}
+
+static inline int
+is_kind_of_BigDecimal(VALUE const v)
+{
+ return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
}
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
@@ -233,7 +424,7 @@ GetVpValueWithPrec(VALUE v, long prec, int must)
case T_FIXNUM: {
char szD[128];
- sprintf(szD, "%ld", FIX2LONG(v));
+ snprintf(szD, 128, "%ld", FIX2LONG(v));
v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
break;
}
@@ -268,27 +459,29 @@ SomeOneMayDoIt:
return NULL; /* NULL means to coerce */
}
-static Real*
+static inline Real*
GetVpValue(VALUE v, int must)
{
return GetVpValueWithPrec(v, -1, must);
}
/* call-seq:
- * BigDecimal.double_fig
+ * BigDecimal.double_fig -> integer
+ *
+ * Returns the number of digits a Float object is allowed to have;
+ * the result is system-dependent:
+ *
+ * BigDecimal.double_fig # => 16
*
- * The BigDecimal.double_fig class method returns the number of digits a
- * Float number is allowed to have. The result depends upon the CPU and OS
- * in use.
*/
-static VALUE
+static inline VALUE
BigDecimal_double_fig(VALUE self)
{
return INT2FIX(VpDblFig());
}
/* call-seq:
- * big_decimal.precs -> array
+ * precs -> array
*
* Returns an Array of two Integer values that represent platform-dependent
* internal storage properties.
@@ -298,7 +491,6 @@ BigDecimal_double_fig(VALUE self)
* significant digits in scientific notation, and BigDecimal#precision for
* obtaining the number of digits in decimal notation.
*
- * BigDecimal('5').precs #=> [9, 18]
*/
static VALUE
@@ -318,73 +510,202 @@ BigDecimal_prec(VALUE self)
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)
+static void
+BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale)
{
ENTER(1);
+ if (out_precision == NULL && out_scale == NULL)
+ return;
+
Real *p;
GUARD_OBJ(p, GetVpValue(self, 1));
+ if (VpIsZero(p) || !VpIsDef(p)) {
+ zero:
+ if (out_precision) *out_precision = 0;
+ if (out_scale) *out_scale = 0;
+ return;
+ }
+
+ DECDIG x;
+
+ ssize_t n = p->Prec; /* The length of frac without zeros. */
+ while (n > 0 && p->frac[n-1] == 0) --n;
+ if (n == 0) goto zero;
+
+ int nlz = BASE_FIG;
+ for (x = p->frac[0]; x > 0; x /= 10) --nlz;
+
+ int ntz = 0;
+ for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
/*
- * 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].
+ * Calculate the precision and the scale
+ * -------------------------------------
+ *
+ * The most significant digit is frac[0], and the least significant digit
+ * is frac[Prec-1]. When the exponent is zero, the decimal point is
+ * located just before frac[0].
+ *
* When the exponent is negative, the decimal point moves to leftward.
- * Conversely, when the exponent is positive, the decimal point moves to rightward.
+ * In this case, the precision can be calculated by
+ *
+ * precision = BASE_FIG * (-exponent + n) - ntz,
*
- * | frac[0] frac[1] frac[2] . frac[3] frac[4] ... frac[Prec-1]
- * |------------------------> exponent == 3
+ * and the scale is the same as precision.
+ *
+ * 0 . 0000 0000 | frac[0] ... frac[n-1] |
+ * |<----------| exponent == -2 |
+ * |---------------------------------->| precision
+ * |---------------------------------->| scale
+ *
+ *
+ * Conversely, when the exponent is positive, the decimal point moves to
+ * rightward. In this case, the scale equals to
+ *
+ * BASE_FIG * (n - exponent) - ntz.
+ *
+ * the precision equals to
+ *
+ * scale + BASE_FIG * exponent - nlz.
+ *
+ * | frac[0] frac[1] . frac[2] ... frac[n-1] |
+ * |---------------->| exponent == 2 |
+ * | |---------------------->| scale
+ * |---------------------------------------->| precision
*/
ssize_t ex = p->exponent;
- ssize_t precision = 0;
+
+ /* Count the number of decimal digits before frac[1]. */
+ ssize_t n_digits_head = BASE_FIG;
if (ex < 0) {
- precision = (-ex + 1) * BASE_FIG; /* 1 is for p->frac[0] */
- ex = 0;
+ n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */
+ ex = 0;
}
- else if (p->Prec > 0) {
- DECDIG x = p->frac[0];
- for (precision = 0; x > 0; x /= 10) {
- ++precision;
- }
+ else if (ex > 0) {
+ /* Count the number of decimal digits without the leading zeros in
+ * the most significant digit in the integral part.
+ */
+ n_digits_head -= nlz; /* Make the number of digits */
}
- if (ex > (ssize_t)p->Prec) {
- precision += (ex - 1) * BASE_FIG;
+ if (out_precision) {
+ ssize_t precision = n_digits_head;
+
+ /* Count the number of decimal digits after frac[0]. */
+ if (ex > (ssize_t)n) {
+ /* In this case the number is an integer with some trailing zeros. */
+ precision += (ex - 1) * BASE_FIG;
+ }
+ else if (n > 0) {
+ precision += (n - 1) * BASE_FIG;
+
+ if (ex < (ssize_t)n) {
+ precision -= ntz;
+ }
+ }
+
+ *out_precision = precision;
}
- 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 (out_scale) {
+ ssize_t scale = 0;
- if (ex < (ssize_t)p->Prec) {
- DECDIG x = p->frac[n];
- for (; x > 0 && x % 10 == 0; x /= 10) {
- --precision;
- }
+ if (p->exponent < 0) {
+ scale = n_digits_head + (n - 1) * BASE_FIG - ntz;
+ }
+ else if (n > p->exponent) {
+ scale = (n - p->exponent) * BASE_FIG - ntz;
}
+
+ *out_scale = scale;
}
+}
+/*
+ * call-seq:
+ * precision -> integer
+ *
+ * Returns the number of decimal digits in +self+:
+ *
+ * BigDecimal("0").precision # => 0
+ * BigDecimal("1").precision # => 1
+ * BigDecimal("1.1").precision # => 2
+ * BigDecimal("3.1415").precision # => 5
+ * BigDecimal("-1e20").precision # => 21
+ * BigDecimal("1e-20").precision # => 20
+ * BigDecimal("Infinity").precision # => 0
+ * BigDecimal("-Infinity").precision # => 0
+ * BigDecimal("NaN").precision # => 0
+ *
+ */
+static VALUE
+BigDecimal_precision(VALUE self)
+{
+ ssize_t precision;
+ BigDecimal_count_precision_and_scale(self, &precision, NULL);
return SSIZET2NUM(precision);
}
+/*
+ * call-seq:
+ * scale -> integer
+ *
+ * Returns the number of decimal digits following the decimal digits in +self+.
+ *
+ * BigDecimal("0").scale # => 0
+ * BigDecimal("1").scale # => 1
+ * BigDecimal("1.1").scale # => 1
+ * BigDecimal("3.1415").scale # => 4
+ * BigDecimal("-1e20").precision # => 0
+ * BigDecimal("1e-20").precision # => 20
+ * BigDecimal("Infinity").scale # => 0
+ * BigDecimal("-Infinity").scale # => 0
+ * BigDecimal("NaN").scale # => 0
+ */
+static VALUE
+BigDecimal_scale(VALUE self)
+{
+ ssize_t scale;
+ BigDecimal_count_precision_and_scale(self, NULL, &scale);
+ return SSIZET2NUM(scale);
+}
+
+/*
+ * call-seq:
+ * precision_scale -> [integer, integer]
+ *
+ * Returns a 2-length array; the first item is the result of
+ * BigDecimal#precision and the second one is of BigDecimal#scale.
+ *
+ * See BigDecimal#precision.
+ * See BigDecimal#scale.
+ */
+static VALUE
+BigDecimal_precision_scale(VALUE self)
+{
+ ssize_t precision, scale;
+ BigDecimal_count_precision_and_scale(self, &precision, &scale);
+ return rb_assoc_new(SSIZET2NUM(precision), SSIZET2NUM(scale));
+}
+
+/*
+ * call-seq:
+ * n_significant_digits -> integer
+ *
+ * Returns the number of decimal significant digits in +self+.
+ *
+ * BigDecimal("0").n_significant_digits # => 0
+ * BigDecimal("1").n_significant_digits # => 1
+ * BigDecimal("1.1").n_significant_digits # => 2
+ * BigDecimal("3.1415").n_significant_digits # => 5
+ * BigDecimal("-1e20").n_significant_digits # => 1
+ * BigDecimal("1e-20").n_significant_digits # => 1
+ * BigDecimal("Infinity").n_significant_digits # => 0
+ * BigDecimal("-Infinity").n_significant_digits # => 0
+ * BigDecimal("NaN").n_significant_digits # => 0
+ */
static VALUE
BigDecimal_n_significant_digits(VALUE self)
{
@@ -392,32 +713,38 @@ BigDecimal_n_significant_digits(VALUE self)
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) {
+ if (VpIsZero(p) || !VpIsDef(p)) {
return INT2FIX(0);
}
- int nlz, ntz;
+ ssize_t n = p->Prec; /* The length of frac without trailing zeros. */
+ for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n);
+ if (n == 0) return INT2FIX(0);
- DECDIG x = p->frac[0];
- for (nlz = BASE_FIG; x > 0; x /= 10) --nlz;
+ DECDIG x;
+ int nlz = BASE_FIG;
+ for (x = p->frac[0]; x > 0; x /= 10) --nlz;
- x = p->frac[n-1];
- for (ntz = 0; x > 0 && x % 10 == 0; x /= 10) ++ntz;
+ int ntz = 0;
+ for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
- ssize_t n_digits = BASE_FIG * n - nlz - ntz;
- return SSIZET2NUM(n_digits);
+ ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
+ return SSIZET2NUM(n_significant_digits);
}
/*
- * call-seq: hash
+ * call-seq:
+ * hash -> integer
+ *
+ * Returns the integer hash value for +self+.
*
- * Creates a hash for this BigDecimal.
+ * Two instances of \BigDecimal have the same hash value if and only if
+ * they have equal:
+ *
+ * - Sign.
+ * - Fractional part.
+ * - Exponent.
*
- * Two BigDecimals with equal sign,
- * fractional part and exponent have the same hash.
*/
static VALUE
BigDecimal_hash(VALUE self)
@@ -437,16 +764,16 @@ BigDecimal_hash(VALUE self)
}
/*
- * call-seq: _dump
+ * call-seq:
+ * _dump -> string
*
- * Method used to provide marshalling support.
+ * Returns a string representing the marshalling of +self+.
+ * See module Marshal.
*
- * inf = BigDecimal('Infinity')
- * #=> Infinity
- * BigDecimal._load(inf._dump)
- * #=> Infinity
+ * inf = BigDecimal('Infinity') # => Infinity
+ * dumped = inf._dump # => "9:Infinity"
+ * BigDecimal._load(dumped) # => Infinity
*
- * See the Marshal module.
*/
static VALUE
BigDecimal_dump(int argc, VALUE *argv, VALUE self)
@@ -456,13 +783,15 @@ BigDecimal_dump(int argc, VALUE *argv, VALUE self)
char *psz;
VALUE dummy;
volatile VALUE dump;
+ size_t len;
rb_scan_args(argc, argv, "01", &dummy);
GUARD_OBJ(vp,GetVpValue(self, 1));
dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
psz = RSTRING_PTR(dump);
- sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
- VpToString(vp, psz+strlen(psz), 0, 0);
+ snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
+ len = strlen(psz);
+ VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0);
rb_str_resize(dump, strlen(psz));
return dump;
}
@@ -506,18 +835,19 @@ check_rounding_mode_option(VALUE const opts)
assert(RB_TYPE_P(opts, T_HASH));
if (NIL_P(opts))
- goto noopt;
+ goto no_opt;
mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
if (mode == Qundef || NIL_P(mode))
- goto noopt;
+ goto no_opt;
if (SYMBOL_P(mode))
mode = rb_sym2str(mode);
else if (!RB_TYPE_P(mode, T_STRING)) {
- VALUE str_mode = rb_check_string_type(mode);
- if (NIL_P(str_mode)) goto invalid;
- mode = str_mode;
+ VALUE str_mode = rb_check_string_type(mode);
+ if (NIL_P(str_mode))
+ goto invalid;
+ mode = str_mode;
}
s = RSTRING_PTR(mode);
l = RSTRING_LEN(mode);
@@ -535,13 +865,11 @@ check_rounding_mode_option(VALUE const opts)
default:
break;
}
+
invalid:
- if (NIL_P(mode))
- rb_raise(rb_eArgError, "invalid rounding mode: nil");
- else
- rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
+ rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode);
- noopt:
+ no_opt:
return VpGetRoundMode();
}
@@ -550,72 +878,185 @@ check_rounding_mode(VALUE const v)
{
unsigned short sw;
ID id;
- switch (TYPE(v)) {
- case T_SYMBOL:
- id = SYM2ID(v);
- if (id == id_up)
- return VP_ROUND_UP;
- if (id == id_down || id == id_truncate)
- return VP_ROUND_DOWN;
- if (id == id_half_up || id == id_default)
- return VP_ROUND_HALF_UP;
- if (id == id_half_down)
- return VP_ROUND_HALF_DOWN;
- if (id == id_half_even || id == id_banker)
- return VP_ROUND_HALF_EVEN;
- if (id == id_ceiling || id == id_ceil)
- return VP_ROUND_CEIL;
- if (id == id_floor)
- return VP_ROUND_FLOOR;
- rb_raise(rb_eArgError, "invalid rounding mode");
-
- default:
- break;
+ if (RB_TYPE_P(v, T_SYMBOL)) {
+ int i;
+ id = SYM2ID(v);
+ for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) {
+ if (rbd_rounding_modes[i].id == id) {
+ return rbd_rounding_modes[i].mode;
+ }
+ }
+ rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
}
-
- sw = NUM2USHORT(v);
- if (!VpIsRoundMode(sw)) {
- rb_raise(rb_eArgError, "invalid rounding mode");
+ else {
+ sw = NUM2USHORT(v);
+ if (!VpIsRoundMode(sw)) {
+ rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v);
+ }
+ return sw;
}
- return sw;
}
-/* call-seq:
- * BigDecimal.mode(mode, value)
- *
- * Controls handling of arithmetic exceptions and rounding. If no value
- * is supplied, the current value is returned.
- *
- * Six values of the mode parameter control the handling of arithmetic
- * exceptions:
- *
- * BigDecimal::EXCEPTION_NaN
- * BigDecimal::EXCEPTION_INFINITY
- * BigDecimal::EXCEPTION_UNDERFLOW
- * BigDecimal::EXCEPTION_OVERFLOW
- * BigDecimal::EXCEPTION_ZERODIVIDE
- * BigDecimal::EXCEPTION_ALL
- *
- * For each mode parameter above, if the value set is false, computation
- * continues after an arithmetic exception of the appropriate type.
- * When computation continues, results are as follows:
- *
- * EXCEPTION_NaN:: NaN
- * EXCEPTION_INFINITY:: +Infinity or -Infinity
- * EXCEPTION_UNDERFLOW:: 0
- * EXCEPTION_OVERFLOW:: +Infinity or -Infinity
- * EXCEPTION_ZERODIVIDE:: +Infinity or -Infinity
- *
- * One value of the mode parameter controls the rounding of numeric values:
- * BigDecimal::ROUND_MODE. The values it can take are:
- *
- * ROUND_UP, :up:: round away from zero
- * ROUND_DOWN, :down, :truncate:: round towards zero (truncate)
- * ROUND_HALF_UP, :half_up, :default:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round away from zero. (default)
- * ROUND_HALF_DOWN, :half_down:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards zero.
- * ROUND_HALF_EVEN, :half_even, :banker:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards the even neighbor (Banker's rounding)
- * ROUND_CEILING, :ceiling, :ceil:: round towards positive infinity (ceil)
- * ROUND_FLOOR, :floor:: round towards negative infinity (floor)
+/* call-seq:
+ * BigDecimal.mode(mode, setting = nil) -> integer
+ *
+ * Returns an integer representing the mode settings
+ * for exception handling and rounding.
+ *
+ * These modes control exception handling:
+ *
+ * - \BigDecimal::EXCEPTION_NaN.
+ * - \BigDecimal::EXCEPTION_INFINITY.
+ * - \BigDecimal::EXCEPTION_UNDERFLOW.
+ * - \BigDecimal::EXCEPTION_OVERFLOW.
+ * - \BigDecimal::EXCEPTION_ZERODIVIDE.
+ * - \BigDecimal::EXCEPTION_ALL.
+ *
+ * Values for +setting+ for exception handling:
+ *
+ * - +true+: sets the given +mode+ to +true+.
+ * - +false+: sets the given +mode+ to +false+.
+ * - +nil+: does not modify the mode settings.
+ *
+ * You can use method BigDecimal.save_exception_mode
+ * to temporarily change, and then automatically restore, exception modes.
+ *
+ * For clarity, some examples below begin by setting all
+ * exception modes to +false+.
+ *
+ * This mode controls the way rounding is to be performed:
+ *
+ * - \BigDecimal::ROUND_MODE
+ *
+ * You can use method BigDecimal.save_rounding_mode
+ * to temporarily change, and then automatically restore, the rounding mode.
+ *
+ * <b>NaNs</b>
+ *
+ * Mode \BigDecimal::EXCEPTION_NaN controls behavior
+ * when a \BigDecimal NaN is created.
+ *
+ * Settings:
+ *
+ * - +false+ (default): Returns <tt>BigDecimal('NaN')</tt>.
+ * - +true+: Raises FloatDomainError.
+ *
+ * Examples:
+ *
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
+ * BigDecimal('NaN') # => NaN
+ * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2
+ * BigDecimal('NaN') # Raises FloatDomainError
+ *
+ * <b>Infinities</b>
+ *
+ * Mode \BigDecimal::EXCEPTION_INFINITY controls behavior
+ * when a \BigDecimal Infinity or -Infinity is created.
+ * Settings:
+ *
+ * - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
+ * or <tt>BigDecimal('-Infinity')</tt>.
+ * - +true+: Raises FloatDomainError.
+ *
+ * Examples:
+ *
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
+ * BigDecimal('Infinity') # => Infinity
+ * BigDecimal('-Infinity') # => -Infinity
+ * BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1
+ * BigDecimal('Infinity') # Raises FloatDomainError
+ * BigDecimal('-Infinity') # Raises FloatDomainError
+ *
+ * <b>Underflow</b>
+ *
+ * Mode \BigDecimal::EXCEPTION_UNDERFLOW controls behavior
+ * when a \BigDecimal underflow occurs.
+ * Settings:
+ *
+ * - +false+ (default): Returns <tt>BigDecimal('0')</tt>
+ * or <tt>BigDecimal('-Infinity')</tt>.
+ * - +true+: Raises FloatDomainError.
+ *
+ * Examples:
+ *
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
+ * def flow_under
+ * x = BigDecimal('0.1')
+ * 100.times { x *= x }
+ * end
+ * flow_under # => 100
+ * BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4
+ * flow_under # Raises FloatDomainError
+ *
+ * <b>Overflow</b>
+ *
+ * Mode \BigDecimal::EXCEPTION_OVERFLOW controls behavior
+ * when a \BigDecimal overflow occurs.
+ * Settings:
+ *
+ * - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
+ * or <tt>BigDecimal('-Infinity')</tt>.
+ * - +true+: Raises FloatDomainError.
+ *
+ * Examples:
+ *
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
+ * def flow_over
+ * x = BigDecimal('10')
+ * 100.times { x *= x }
+ * end
+ * flow_over # => 100
+ * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1
+ * flow_over # Raises FloatDomainError
+ *
+ * <b>Zero Division</b>
+ *
+ * Mode \BigDecimal::EXCEPTION_ZERODIVIDE controls behavior
+ * when a zero-division occurs.
+ * Settings:
+ *
+ * - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
+ * or <tt>BigDecimal('-Infinity')</tt>.
+ * - +true+: Raises FloatDomainError.
+ *
+ * Examples:
+ *
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
+ * one = BigDecimal('1')
+ * zero = BigDecimal('0')
+ * one / zero # => Infinity
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16
+ * one / zero # Raises FloatDomainError
+ *
+ * <b>All Exceptions</b>
+ *
+ * Mode \BigDecimal::EXCEPTION_ALL controls all of the above:
+ *
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
+ * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23
+ *
+ * <b>Rounding</b>
+ *
+ * Mode \BigDecimal::ROUND_MODE controls the way rounding is to be performed;
+ * its +setting+ values are:
+ *
+ * - +ROUND_UP+: Round away from zero.
+ * Aliased as +:up+.
+ * - +ROUND_DOWN+: Round toward zero.
+ * Aliased as +:down+ and +:truncate+.
+ * - +ROUND_HALF_UP+: Round toward the nearest neighbor;
+ * if the neighbors are equidistant, round away from zero.
+ * Aliased as +:half_up+ and +:default+.
+ * - +ROUND_HALF_DOWN+: Round toward the nearest neighbor;
+ * if the neighbors are equidistant, round toward zero.
+ * Aliased as +:half_down+.
+ * - +ROUND_HALF_EVEN+ (Banker's rounding): Round toward the nearest neighbor;
+ * if the neighbors are equidistant, round toward the even neighbor.
+ * Aliased as +:half_even+ and +:banker+.
+ * - +ROUND_CEILING+: Round toward positive infinity.
+ * Aliased as +:ceiling+ and +:ceil+.
+ * - +ROUND_FLOOR+: Round toward negative infinity.
+ * Aliased as +:floor:+.
*
*/
static VALUE
@@ -692,11 +1133,17 @@ GetAddSubPrec(Real *a, Real *b)
return mx;
}
-static SIGNED_VALUE
-GetPrecisionInt(VALUE v)
+static inline SIGNED_VALUE
+check_int_precision(VALUE v)
{
SIGNED_VALUE n;
- n = NUM2INT(v);
+#if SIZEOF_VALUE <= SIZEOF_LONG
+ n = (SIGNED_VALUE)NUM2LONG(v);
+#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
+ n = (SIGNED_VALUE)NUM2LL(v);
+#else
+# error SIZEOF_VALUE is too large
+#endif
if (n < 0) {
rb_raise(rb_eArgError, "negative precision");
}
@@ -738,15 +1185,12 @@ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
}
-#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(DECDIG))
-#define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(DECDIG))
-
static Real *
VpCopy(Real *pv, Real const* const x)
{
assert(x != NULL);
- pv = VpReallocReal(pv, x->MaxPrec);
+ pv = rbd_reallocate_struct(pv, x->MaxPrec);
pv->MaxPrec = x->MaxPrec;
pv->Prec = x->Prec;
pv->exponent = x->exponent;
@@ -867,7 +1311,7 @@ BigDecimal_to_f(VALUE self)
str = rb_str_new(0, VpNumOfChars(p, "E"));
buf = RSTRING_PTR(str);
- VpToString(p, buf, 0, 0);
+ VpToString(p, buf, RSTRING_LEN(str), 0, 0);
errno = 0;
d = strtod(buf, 0);
if (errno == ERANGE) {
@@ -966,12 +1410,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
}
/*
- * call-seq:
- * +big_decimal -> big_decimal
+ * call-seq:
+ * +big_decimal -> self
*
- * Return self.
+ * Returns +self+:
+ *
+ * +BigDecimal(5) # => 0.5e1
+ * +BigDecimal(-5) # => -0.5e1
*
- * +BigDecimal('5') #=> 0.5e1
*/
static VALUE
@@ -981,22 +1427,21 @@ BigDecimal_uplus(VALUE self)
}
/*
- * Document-method: BigDecimal#add
- * Document-method: BigDecimal#+
+ * call-seq:
+ * self + value -> bigdecimal
*
- * call-seq:
- * add(value, digits)
+ * Returns the \BigDecimal sum of +self+ and +value+:
*
- * Add the specified value.
+ * b = BigDecimal('111111.111') # => 0.111111111e6
+ * b + 2 # => 0.111113111e6
+ * b + 2.0 # => 0.111113111e6
+ * b + Rational(2, 1) # => 0.111113111e6
+ * b + Complex(2, 0) # => (0.111113111e6+0i)
*
- * e.g.
- * c = a.add(b,n)
- * c = a + b
+ * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
*
- * digits:: If specified and less than the number of significant digits of the
- * result, the result is rounded to that number of digits, according
- * to BigDecimal.mode.
*/
+
static VALUE
BigDecimal_add(VALUE self, VALUE r)
{
@@ -1023,36 +1468,33 @@ BigDecimal_add(VALUE self, VALUE r)
mx = GetAddSubPrec(a, b);
if (mx == (size_t)-1L) {
- GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
- VpAddSub(c, a, b, 1);
+ GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
+ VpAddSub(c, a, b, 1);
}
else {
- GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
- if(!mx) {
- VpSetInf(c, VpGetSign(a));
- }
- else {
- VpAddSub(c, a, b, 1);
- }
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
+ if (!mx) {
+ VpSetInf(c, VpGetSign(a));
+ }
+ else {
+ VpAddSub(c, a, b, 1);
+ }
}
return VpCheckGetValue(c);
}
- /* call-seq:
- * a - b -> bigdecimal
- *
- * Subtract the specified value.
+ /* call-seq:
+ * self - value -> bigdecimal
*
- * e.g.
- * c = a - b
+ * Returns the \BigDecimal difference of +self+ and +value+:
*
- * The precision of the result value depends on the type of +b+.
+ * b = BigDecimal('333333.333') # => 0.333333333e6
+ * b - 2 # => 0.333331333e6
+ * b - 2.0 # => 0.333331333e6
+ * b - Rational(2, 1) # => 0.333331333e6
+ * b - Complex(2, 0) # => (0.333331333e6+0i)
*
- * If +b+ is a Float, the precision of the result is Float::DIG+1.
- *
- * If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
- * internal representation from platform. So, it's return value is platform
- * dependent.
+ * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
*
*/
static VALUE
@@ -1081,17 +1523,17 @@ BigDecimal_sub(VALUE self, VALUE r)
mx = GetAddSubPrec(a,b);
if (mx == (size_t)-1L) {
- GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
- VpAddSub(c, a, b, -1);
+ GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1));
+ VpAddSub(c, a, b, -1);
}
else {
- GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
- if (!mx) {
- VpSetInf(c,VpGetSign(a));
- }
- else {
- VpAddSub(c, a, b, -1);
- }
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1)));
+ if (!mx) {
+ VpSetInf(c,VpGetSign(a));
+ }
+ else {
+ VpAddSub(c, a, b, -1);
+ }
}
return VpCheckGetValue(c);
}
@@ -1231,12 +1673,19 @@ BigDecimal_eq(VALUE self, VALUE r)
return BigDecimalCmp(self, r, '=');
}
-/* call-seq:
- * a < b
+/* call-seq:
+ * self < other -> true or false
+ *
+ * Returns +true+ if +self+ is less than +other+, +false+ otherwise:
*
- * Returns true if a is less than b.
+ * b = BigDecimal('1.5') # => 0.15e1
+ * b < 2 # => true
+ * b < 2.0 # => true
+ * b < Rational(2, 1) # => true
+ * b < 1.5 # => false
+ *
+ * Raises an exception if the comparison cannot be made.
*
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
*/
static VALUE
BigDecimal_lt(VALUE self, VALUE r)
@@ -1244,12 +1693,20 @@ BigDecimal_lt(VALUE self, VALUE r)
return BigDecimalCmp(self, r, '<');
}
-/* call-seq:
- * a <= b
+/* call-seq:
+ * self <= other -> true or false
+ *
+ * Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise:
+ *
+ * b = BigDecimal('1.5') # => 0.15e1
+ * b <= 2 # => true
+ * b <= 2.0 # => true
+ * b <= Rational(2, 1) # => true
+ * b <= 1.5 # => true
+ * b < 1 # => false
*
- * Returns true if a is less than or equal to b.
+ * Raises an exception if the comparison cannot be made.
*
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
*/
static VALUE
BigDecimal_le(VALUE self, VALUE r)
@@ -1257,12 +1714,19 @@ BigDecimal_le(VALUE self, VALUE r)
return BigDecimalCmp(self, r, 'L');
}
-/* call-seq:
- * a > b
+/* call-seq:
+ * self > other -> true or false
+ *
+ * Returns +true+ if +self+ is greater than +other+, +false+ otherwise:
+ *
+ * b = BigDecimal('1.5')
+ * b > 1 # => true
+ * b > 1.0 # => true
+ * b > Rational(1, 1) # => true
+ * b > 2 # => false
*
- * Returns true if a is greater than b.
+ * Raises an exception if the comparison cannot be made.
*
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
*/
static VALUE
BigDecimal_gt(VALUE self, VALUE r)
@@ -1270,12 +1734,20 @@ BigDecimal_gt(VALUE self, VALUE r)
return BigDecimalCmp(self, r, '>');
}
-/* call-seq:
- * a >= b
+/* call-seq:
+ * self >= other -> true or false
+ *
+ * Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise:
*
- * Returns true if a is greater than or equal to b.
+ * b = BigDecimal('1.5')
+ * b >= 1 # => true
+ * b >= 1.0 # => true
+ * b >= Rational(1, 1) # => true
+ * b >= 1.5 # => true
+ * b > 2 # => false
+ *
+ * Raises an exception if the comparison cannot be made.
*
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
*/
static VALUE
BigDecimal_ge(VALUE self, VALUE r)
@@ -1285,11 +1757,14 @@ BigDecimal_ge(VALUE self, VALUE r)
/*
* call-seq:
- * -big_decimal -> big_decimal
+ * -self -> bigdecimal
+ *
+ * Returns the \BigDecimal negation of self:
*
- * Return the negation of self.
+ * b0 = BigDecimal('1.5')
+ * b1 = -b0 # => -0.15e1
+ * b2 = -b1 # => 0.15e1
*
- * -BigDecimal('5') #=> -0.5e1
*/
static VALUE
@@ -1298,26 +1773,11 @@ BigDecimal_neg(VALUE self)
ENTER(5);
Real *c, *a;
GUARD_OBJ(a, GetVpValue(self, 1));
- GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1)));
VpAsgn(c, a, -1);
return VpCheckGetValue(c);
}
- /*
- * Document-method: BigDecimal#mult
- *
- * call-seq: mult(value, digits)
- *
- * Multiply by the specified value.
- *
- * e.g.
- * c = a.mult(b,n)
- * c = a * b
- *
- * digits:: If specified and less than the number of significant digits of the
- * result, the result is rounded to that number of digits, according
- * to BigDecimal.mode.
- */
static VALUE
BigDecimal_mult(VALUE self, VALUE r)
{
@@ -1340,7 +1800,7 @@ BigDecimal_mult(VALUE self, VALUE r)
SAVE(b);
mx = a->Prec + b->Prec;
- GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1)));
VpMult(c, a, b);
return VpCheckGetValue(c);
}
@@ -1351,6 +1811,7 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
{
ENTER(5);
Real *a, *b;
+ ssize_t a_prec, b_prec;
size_t mx;
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
@@ -1376,26 +1837,35 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
SAVE(b);
-
*div = b;
- mx = a->Prec + vabs(a->exponent);
- if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
- mx++; /* NOTE: An additional digit is needed for the compatibility to
- the version 1.2.1 and the former. */
- mx = (mx + 1) * VpBaseFig();
- GUARD_OBJ((*c), VpCreateRbObject(mx, "#0", true));
- GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true));
+
+ BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
+ BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
+ mx = (a_prec > b_prec) ? a_prec : b_prec;
+ mx *= 2;
+
+ if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
+ mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
+
+ GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG));
+ GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG));
VpDivd(*c, *res, a, b);
+
return Qnil;
}
+static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod);
+
/* call-seq:
- * a / b -> bigdecimal
- * quo(value) -> bigdecimal
+ * a / b -> bigdecimal
*
* Divide by the specified value.
*
+ * The result precision will be the precision of the larger operand,
+ * but its minimum is 2*Float::DIG.
+ *
* See BigDecimal#div.
+ * See BigDecimal#quo.
*/
static VALUE
BigDecimal_div(VALUE self, VALUE r)
@@ -1417,6 +1887,45 @@ BigDecimal_div(VALUE self, VALUE r)
return VpCheckGetValue(c);
}
+static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self);
+
+/* call-seq:
+ * quo(value) -> bigdecimal
+ * quo(value, digits) -> bigdecimal
+ *
+ * Divide by the specified value.
+ *
+ * digits:: If specified and less than the number of significant digits of
+ * the result, the result is rounded to the given number of digits,
+ * according to the rounding mode indicated by BigDecimal.mode.
+ *
+ * If digits is 0 or omitted, the result is the same as for the
+ * / operator.
+ *
+ * See BigDecimal#/.
+ * See BigDecimal#div.
+ */
+static VALUE
+BigDecimal_quo(int argc, VALUE *argv, VALUE self)
+{
+ VALUE value, digits, result;
+ SIGNED_VALUE n = -1;
+
+ argc = rb_scan_args(argc, argv, "11", &value, &digits);
+ if (argc > 1) {
+ n = check_int_precision(digits);
+ }
+
+ if (n > 0) {
+ result = BigDecimal_div2(self, value, digits);
+ }
+ else {
+ result = BigDecimal_div(self, value);
+ }
+
+ return result;
+}
+
/*
* %: mod = a%b = a - (a.to_f/b).floor * b
* div = (a.to_f/b).floor
@@ -1427,6 +1936,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
ENTER(8);
Real *c=NULL, *d=NULL, *res=NULL;
Real *a, *b;
+ ssize_t a_prec, b_prec;
size_t mx;
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
@@ -1484,26 +1994,39 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
return Qtrue;
}
- mx = a->Prec + vabs(a->exponent);
- if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
- mx = (mx + 1) * VpBaseFig();
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
- GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true));
+ BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
+ BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
+
+ mx = (a_prec > b_prec) ? a_prec : b_prec;
+ mx *= 2;
+
+ if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
+ mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
+
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
VpDivd(c, res, a, b);
- mx = c->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
+
+ mx = c->Prec * BASE_FIG;
+ GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
+
VpMult(res, d, b);
VpAddSub(c, a, res, -1);
+
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
- VpAddSub(res, d, VpOne(), -1);
- GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0", true));
- VpAddSub(d, c, b, 1);
- *div = res;
- *mod = d;
- } else {
- *div = d;
- *mod = c;
+ /* result adjustment for negative case */
+ res = rbd_reallocate_struct(res, d->MaxPrec);
+ res->MaxPrec = d->MaxPrec;
+ VpAddSub(res, d, VpOne(), -1);
+ GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
+ VpAddSub(d, c, b, 1);
+ *div = res;
+ *mod = d;
+ }
+ else {
+ *div = d;
+ *mod = c;
}
return Qtrue;
@@ -1560,17 +2083,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
SAVE(b);
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
- GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
- GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
- GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
+ GUARD_OBJ(rr, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
+ GUARD_OBJ(ff, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1)));
VpDivd(c, res, a, b);
mx = c->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
- GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
+ GUARD_OBJ(f, NewZeroWrapLimited(1, mx));
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
@@ -1655,7 +2178,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
}
/* div in BigDecimal sense */
- ix = GetPrecisionInt(n);
+ ix = check_int_precision(n);
if (ix == 0) {
return BigDecimal_div(self, b);
}
@@ -1663,14 +2186,21 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
Real *res = NULL;
Real *av = NULL, *bv = NULL, *cv = NULL;
size_t mx = ix + VpBaseFig()*2;
+ size_t b_prec = ix;
size_t pl = VpSetPrecLimit(0);
- GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
+ GUARD_OBJ(cv, NewZeroWrapLimited(1, mx + VpBaseFig()));
GUARD_OBJ(av, GetVpValue(self, 1));
- GUARD_OBJ(bv, GetVpValue(b, 1));
+ /* TODO: I want to refactor this precision control for a float value later
+ * by introducing an implicit conversion function instead of
+ * GetVpValueWithPrec. */
+ if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) {
+ b_prec = BIGDECIMAL_DOUBLE_FIGURES;
+ }
+ GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
mx = av->Prec + bv->Prec + 2;
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
- GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig()));
VpDivd(cv, res, av, bv);
VpSetPrecLimit(pl);
VpLeftRound(cv, VpGetRoundMode(), ix);
@@ -1682,6 +2212,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
* Document-method: BigDecimal#div
*
* call-seq:
+ * div(value) -> integer
* div(value, digits) -> bigdecimal or integer
*
* Divide by the specified value.
@@ -1696,6 +2227,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
* If digits is not specified, the result is an integer,
* by analogy with Float#div; see also BigDecimal#divmod.
*
+ * See BigDecimal#/.
+ * See BigDecimal#quo.
+ *
* Examples:
*
* a = BigDecimal("4")
@@ -1719,12 +2253,37 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self)
return BigDecimal_div2(self, b, n);
}
+ /*
+ * call-seq:
+ * add(value, ndigits) -> new_bigdecimal
+ *
+ * Returns the \BigDecimal sum of +self+ and +value+
+ * with a precision of +ndigits+ decimal digits.
+ *
+ * When +ndigits+ is less than the number of significant digits
+ * in the sum, the sum is rounded to that number of digits,
+ * according to the current rounding mode; see BigDecimal.mode.
+ *
+ * Examples:
+ *
+ * # Set the rounding mode.
+ * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
+ * b = BigDecimal('111111.111')
+ * b.add(1, 0) # => 0.111112111e6
+ * b.add(1, 3) # => 0.111e6
+ * b.add(1, 6) # => 0.111112e6
+ * b.add(1, 15) # => 0.111112111e6
+ * b.add(1.0, 15) # => 0.111112111e6
+ * b.add(Rational(1, 1), 15) # => 0.111112111e6
+ *
+ */
+
static VALUE
BigDecimal_add2(VALUE self, VALUE b, VALUE n)
{
ENTER(2);
Real *cv;
- SIGNED_VALUE mx = GetPrecisionInt(n);
+ SIGNED_VALUE mx = check_int_precision(n);
if (mx == 0) return BigDecimal_add(self, b);
else {
size_t pl = VpSetPrecLimit(0);
@@ -1754,7 +2313,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
{
ENTER(2);
Real *cv;
- SIGNED_VALUE mx = GetPrecisionInt(n);
+ SIGNED_VALUE mx = check_int_precision(n);
if (mx == 0) return BigDecimal_sub(self, b);
else {
size_t pl = VpSetPrecLimit(0);
@@ -1766,13 +2325,38 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
}
}
+ /*
+ * call-seq:
+ * mult(other, ndigits) -> bigdecimal
+ *
+ * Returns the \BigDecimal product of +self+ and +value+
+ * with a precision of +ndigits+ decimal digits.
+ *
+ * When +ndigits+ is less than the number of significant digits
+ * in the sum, the sum is rounded to that number of digits,
+ * according to the current rounding mode; see BigDecimal.mode.
+ *
+ * Examples:
+ *
+ * # Set the rounding mode.
+ * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
+ * b = BigDecimal('555555.555')
+ * b.mult(3, 0) # => 0.1666666665e7
+ * b.mult(3, 3) # => 0.167e7
+ * b.mult(3, 6) # => 0.166667e7
+ * b.mult(3, 15) # => 0.1666666665e7
+ * b.mult(3.0, 0) # => 0.1666666665e7
+ * b.mult(Rational(3, 1), 0) # => 0.1666666665e7
+ * b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i)
+ *
+ */
static VALUE
BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
{
ENTER(2);
Real *cv;
- SIGNED_VALUE mx = GetPrecisionInt(n);
+ SIGNED_VALUE mx = check_int_precision(n);
if (mx == 0) return BigDecimal_mult(self, b);
else {
size_t pl = VpSetPrecLimit(0);
@@ -1786,12 +2370,13 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
/*
* call-seq:
- * big_decimal.abs -> big_decimal
+ * abs -> bigdecimal
+ *
+ * Returns the \BigDecimal absolute value of +self+:
*
- * Returns the absolute value, as a BigDecimal.
+ * BigDecimal('5').abs # => 0.5e1
+ * BigDecimal('-3').abs # => 0.3e1
*
- * BigDecimal('5').abs #=> 0.5e1
- * BigDecimal('-3').abs #=> 0.3e1
*/
static VALUE
@@ -1803,7 +2388,7 @@ BigDecimal_abs(VALUE self)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpAsgn(c, a, 1);
VpChangeSign(c, 1);
return VpCheckGetValue(c);
@@ -1826,9 +2411,10 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec * (VpBaseFig() + 1);
- n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
+ n = check_int_precision(nFig);
+ n += VpDblFig() + VpBaseFig();
if (mx <= n) mx = n;
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpSqrt(c, a);
return VpCheckGetValue(c);
}
@@ -1844,7 +2430,7 @@ BigDecimal_fix(VALUE self)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec *(VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
return VpCheckGetValue(c);
}
@@ -1917,7 +2503,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
pl = VpSetPrecLimit(0);
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpSetPrecLimit(pl);
VpActiveRound(c, a, sw, iLoc);
if (round_to_int) {
@@ -1963,7 +2549,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpSetPrecLimit(pl);
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
if (argc == 0) {
@@ -1983,7 +2569,7 @@ BigDecimal_frac(VALUE self)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpFrac(c, a);
return VpCheckGetValue(c);
}
@@ -2023,7 +2609,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpSetPrecLimit(pl);
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
#ifdef BIGDECIMAL_DEBUG
@@ -2069,7 +2655,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(a, GetVpValue(self, 1));
mx = a->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx));
VpSetPrecLimit(pl);
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
if (argc == 0) {
@@ -2173,10 +2759,10 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
psz = RSTRING_PTR(str);
if (fmt) {
- VpToFString(vp, psz, mc, fPlus);
+ VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus);
}
else {
- VpToString (vp, psz, mc, fPlus);
+ VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus);
}
rb_str_resize(str, strlen(psz));
return str;
@@ -2218,7 +2804,7 @@ BigDecimal_split(VALUE self)
GUARD_OBJ(vp, GetVpValue(self, 1));
str = rb_str_new(0, VpNumOfChars(vp, "E"));
psz1 = RSTRING_PTR(str);
- VpSzMantissa(vp, psz1);
+ VpSzMantissa(vp, psz1, RSTRING_LEN(str));
s = 1;
if(psz1[0] == '-') {
size_t len = strlen(psz1 + 1);
@@ -2267,7 +2853,7 @@ BigDecimal_inspect(VALUE self)
nc = VpNumOfChars(vp, "E");
str = rb_str_new(0, nc);
- VpToString(vp, RSTRING_PTR(str), 0, 0);
+ VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0);
rb_str_resize(str, strlen(RSTRING_PTR(str)));
return str;
}
@@ -2377,7 +2963,7 @@ bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
volatile VALUE obj = exp->obj;
if (VpIsZero(exp)) {
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
}
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
@@ -2415,9 +3001,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
if (VpIsNaN(x)) {
- y = VpCreateRbObject(n, "0", true);
- RB_GC_GUARD(y->obj);
- VpSetNaN(y);
+ y = NewZeroWrapLimited(1, n);
+ VpSetNaN(y);
+ RB_GC_GUARD(y->obj);
return VpCheckGetValue(y);
}
@@ -2486,136 +3072,126 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
if (VpIsZero(x)) {
- if (is_negative(vexp)) {
- y = VpCreateRbObject(n, "#0", true);
- RB_GC_GUARD(y->obj);
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- if (is_integer(vexp)) {
- if (is_even(vexp)) {
- /* (-0) ** (-even_integer) -> Infinity */
- VpSetPosInf(y);
- }
- else {
- /* (-0) ** (-odd_integer) -> -Infinity */
- VpSetNegInf(y);
- }
- }
- else {
- /* (-0) ** (-non_integer) -> Infinity */
- VpSetPosInf(y);
- }
- }
- else {
- /* (+0) ** (-num) -> Infinity */
- VpSetPosInf(y);
- }
+ if (is_negative(vexp)) {
+ y = NewZeroWrapNolimit(1, n);
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
+ if (is_integer(vexp)) {
+ if (is_even(vexp)) {
+ /* (-0) ** (-even_integer) -> Infinity */
+ VpSetPosInf(y);
+ }
+ else {
+ /* (-0) ** (-odd_integer) -> -Infinity */
+ VpSetNegInf(y);
+ }
+ }
+ else {
+ /* (-0) ** (-non_integer) -> Infinity */
+ VpSetPosInf(y);
+ }
+ }
+ else {
+ /* (+0) ** (-num) -> Infinity */
+ VpSetPosInf(y);
+ }
+ RB_GC_GUARD(y->obj);
return VpCheckGetValue(y);
- }
- else if (is_zero(vexp)) {
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
- }
- else {
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
- }
+ }
+ else if (is_zero(vexp)) {
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
+ }
+ else {
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
+ }
}
if (is_zero(vexp)) {
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
}
else if (is_one(vexp)) {
- return self;
+ return self;
}
if (VpIsInf(x)) {
- if (is_negative(vexp)) {
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- if (is_integer(vexp)) {
- if (is_even(vexp)) {
- /* (-Infinity) ** (-even_integer) -> +0 */
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
- }
- else {
- /* (-Infinity) ** (-odd_integer) -> -0 */
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
- }
- }
- else {
- /* (-Infinity) ** (-non_integer) -> -0 */
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
- }
- }
- else {
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
- }
- }
- else {
- y = VpCreateRbObject(n, "0", true);
- if (BIGDECIMAL_NEGATIVE_P(x)) {
- if (is_integer(vexp)) {
- if (is_even(vexp)) {
- VpSetPosInf(y);
- }
- else {
- VpSetNegInf(y);
- }
- }
- else {
- /* TODO: support complex */
- rb_raise(rb_eMathDomainError,
- "a non-integral exponent for a negative base");
- }
- }
- else {
- VpSetPosInf(y);
- }
+ if (is_negative(vexp)) {
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
+ if (is_integer(vexp)) {
+ if (is_even(vexp)) {
+ /* (-Infinity) ** (-even_integer) -> +0 */
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
+ }
+ else {
+ /* (-Infinity) ** (-odd_integer) -> -0 */
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
+ }
+ }
+ else {
+ /* (-Infinity) ** (-non_integer) -> -0 */
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
+ }
+ }
+ else {
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
+ }
+ }
+ else {
+ y = NewZeroWrapLimited(1, n);
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
+ if (is_integer(vexp)) {
+ if (is_even(vexp)) {
+ VpSetPosInf(y);
+ }
+ else {
+ VpSetNegInf(y);
+ }
+ }
+ else {
+ /* TODO: support complex */
+ rb_raise(rb_eMathDomainError,
+ "a non-integral exponent for a negative base");
+ }
+ }
+ else {
+ VpSetPosInf(y);
+ }
return VpCheckGetValue(y);
- }
+ }
}
if (exp != NULL) {
- return bigdecimal_power_by_bigdecimal(x, exp, n);
+ return bigdecimal_power_by_bigdecimal(x, exp, n);
}
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
- VALUE abs_value = BigDecimal_abs(self);
- if (is_one(abs_value)) {
- return VpCheckGetValue(VpCreateRbObject(n, "1", true));
- }
- else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
- if (is_negative(vexp)) {
- y = VpCreateRbObject(n, "0", true);
- if (is_even(vexp)) {
- VpSetInf(y, VpGetSign(x));
- }
- else {
- VpSetInf(y, -VpGetSign(x));
- }
+ VALUE abs_value = BigDecimal_abs(self);
+ if (is_one(abs_value)) {
+ return VpCheckGetValue(NewOneWrapLimited(1, n));
+ }
+ else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
+ if (is_negative(vexp)) {
+ y = NewZeroWrapLimited(1, n);
+ VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
return VpCheckGetValue(y);
- }
- else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
- }
- else {
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
- }
- }
- else {
- if (is_positive(vexp)) {
- y = VpCreateRbObject(n, "0", true);
- if (is_even(vexp)) {
- VpSetInf(y, VpGetSign(x));
- }
- else {
- VpSetInf(y, -VpGetSign(x));
- }
+ }
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
+ }
+ else {
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
+ }
+ }
+ else {
+ if (is_positive(vexp)) {
+ y = NewZeroWrapLimited(1, n);
+ VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x));
return VpCheckGetValue(y);
- }
- else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
- return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
- }
- else {
- return VpCheckGetValue(VpCreateRbObject(n, "0", true));
- }
- }
+ }
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
+ return VpCheckGetValue(NewZeroWrapLimited(-1, n));
+ }
+ else {
+ return VpCheckGetValue(NewZeroWrapLimited(1, n));
+ }
+ }
}
int_exp = FIX2LONG(vexp);
@@ -2624,25 +3200,31 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
if (ma == 0) ma = 1;
if (VpIsDef(x)) {
- mp = x->Prec * (VpBaseFig() + 1);
- GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
+ mp = x->Prec * (VpBaseFig() + 1);
+ GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1)));
}
else {
- GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
+ GUARD_OBJ(y, NewZeroWrapLimited(1, 1));
}
VpPowerByInt(y, x, int_exp);
if (!NIL_P(prec) && VpIsDef(y)) {
- VpMidRound(y, VpGetRoundMode(), n);
+ VpMidRound(y, VpGetRoundMode(), n);
}
return VpCheckGetValue(y);
}
-/* call-seq:
- * a ** n -> bigdecimal
+/* call-seq:
+ * self ** other -> bigdecimal
*
- * Returns the value raised to the power of n.
+ * Returns the \BigDecimal value of +self+ raised to power +other+:
+ *
+ * b = BigDecimal('3.14')
+ * b ** 2 # => 0.98596e1
+ * b ** 2.0 # => 0.98596e1
+ * b ** Rational(2, 1) # => 0.98596e1
+ *
+ * Related: BigDecimal#power.
*
- * See BigDecimal#power.
*/
static VALUE
BigDecimal_power_op(VALUE self, VALUE exp)
@@ -2715,7 +3297,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
Real *vp;
if (uval == 0) {
- vp = VpAllocReal(1);
+ vp = rbd_allocate_struct(1);
vp->MaxPrec = 1;
vp->Prec = 1;
vp->exponent = 1;
@@ -2723,7 +3305,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
vp->frac[0] = 0;
}
else if (uval < BASE) {
- vp = VpAllocReal(1);
+ vp = rbd_allocate_struct(1);
vp->MaxPrec = 1;
vp->Prec = 1;
vp->exponent = 1;
@@ -2732,21 +3314,29 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
}
else {
DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,};
- size_t exp = 0, ntz = 0;
- for (; uval > 0; ++exp) {
- DECDIG r = uval % BASE;
- if (r == 0) ++ntz;
- buf[BIGDECIMAL_INT64_MAX_LENGTH - exp - 1] = r;
+ DECDIG r = uval % BASE;
+ size_t len = 0, ntz = 0;
+ if (r == 0) {
+ // Count and skip trailing zeros
+ for (; r == 0 && uval > 0; ++ntz) {
+ uval /= BASE;
+ r = uval % BASE;
+ }
+ }
+ for (; uval > 0; ++len) {
+ // Store digits
+ buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r;
uval /= BASE;
+ r = uval % BASE;
}
- const size_t len = exp - ntz;
- vp = VpAllocReal(len);
+ const size_t exp = len + ntz;
+ vp = rbd_allocate_struct(len);
vp->MaxPrec = len;
vp->Prec = len;
vp->exponent = exp;
VpSetSign(vp, 1);
- MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - exp, DECDIG, len);
+ MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len);
}
return BigDecimal_wrap_struct(obj, vp);
@@ -2770,8 +3360,12 @@ rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_ex
{
assert(RB_TYPE_P(val, T_BIGNUM));
- size_t size = rb_absint_size(val, NULL);
+ int leading_zeros;
+ size_t size = rb_absint_size(val, &leading_zeros);
int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0)));
+ if (sign < 0 && leading_zeros == 0) {
+ size += 1;
+ }
if (size <= sizeof(long)) {
if (sign < 0) {
return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception);
@@ -2870,7 +3464,7 @@ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
VALUE inum;
size_t RB_UNUSED_VAR(prec) = 0;
- size_t exp = 0;
+ SIGNED_VALUE exp = 0;
if (decpt > 0) {
if (decpt < len10) {
/*
@@ -3078,50 +3672,52 @@ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
return rb_str_convert_to_BigDecimal(str, digs, raise_exception);
}
-/* call-seq:
- * BigDecimal(arg, exception: true)
- * BigDecimal(arg, digits, exception: true)
+/* call-seq:
+ * BigDecimal(value, exception: true) -> bigdecimal
+ * BigDecimal(value, ndigits, exception: true) -> bigdecimal
*
- * Returns <i>arg</i> converted to a BigDecimal. Numeric types are converted
- * directly. Other types except for String are first converted to String
- * by <code>to_str</code>. Strings can be converted when it has appropriate
- * forms of decimal numbers. Exceptions can be suppressed by passing
- * <code>exception: false</code>.
+ * Returns the \BigDecimal converted from +value+
+ * with a precision of +ndigits+ decimal digits.
*
- * When <i>arg</i> is a Float and <i>digits</i> is <code>0</code>, the number
- * of digits is determined by the algorithm of <code>dtoa</code> function
- * written by David M. Gay. That algorithm is based on "How to Print Floating-
- * Point Numbers Accurately" by Guy L. Steele, Jr. and Jon L. White [Proc. ACM
- * SIGPLAN '90, pp. 112-126].
+ * When +ndigits+ is less than the number of significant digits
+ * in the value, the result is rounded to that number of digits,
+ * according to the current rounding mode; see BigDecimal.mode.
*
- * arg:: The value converted to a BigDecimal.
+ * When +ndigits+ is 0, the number of digits to correctly represent a float number
+ * is determined automatically.
*
- * If it is a String, spaces are ignored and unrecognized characters
- * terminate the value.
+ * Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
*
- * digits:: The number of significant digits, as an Integer. If omitted,
- * the number of significant digits is determined from <i>arg</i>.
+ * - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
*
- * The actual number of significant digits used in computation is
- * usually larger than the specified number.
+ * # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given.
+ * BigDecimal(2) # => 0.2e1
+ * BigDecimal(Complex(2, 0)) # => 0.2e1
+ * BigDecimal(BigDecimal(2)) # => 0.2e1
+ * # Float or Rational value requires ndigits.
+ * BigDecimal(2.0, 0) # => 0.2e1
+ * BigDecimal(Rational(2, 1), 0) # => 0.2e1
*
- * exception:: Whether an exception should be raised on invalid arguments.
- * +true+ by default, if passed +false+, just returns +nil+
- * for invalid.
+ * - String: converted by parsing if it contains an integer or floating-point literal;
+ * leading and trailing whitespace is ignored:
*
+ * # String does not require ndigits; ignored if given.
+ * BigDecimal('2') # => 0.2e1
+ * BigDecimal('2.0') # => 0.2e1
+ * BigDecimal('0.2e1') # => 0.2e1
+ * BigDecimal(' 2.0 ') # => 0.2e1
*
- * ==== Exceptions
+ * - Other type that responds to method <tt>:to_str</tt>:
+ * first converted to a string, then converted to a \BigDecimal, as above.
*
- * TypeError:: If the +initial+ type is neither Integer, Float,
- * Rational, nor BigDecimal, this exception is raised.
+ * - Other type:
*
- * TypeError:: If the +digits+ is not an Integer, this exception is raised.
+ * - Raises an exception if keyword argument +exception+ is +true+.
+ * - Returns +nil+ if keyword argument +exception+ is +true+.
*
- * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
- * Float::DIG + 1, this exception is raised.
+ * Raises an exception if +value+ evaluates to a Float
+ * and +digits+ is larger than Float::DIG + 1.
*
- * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
- * value is omitted, this exception is raised.
*/
static VALUE
f_BigDecimal(int argc, VALUE *argv, VALUE self)
@@ -3196,8 +3792,10 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
/* Returns the sign of the value.
*
- * Returns a positive value if > 0, a negative value if < 0, and a
- * zero if == 0.
+ * Returns a positive value if > 0, a negative value if < 0.
+ * It behaves the same with zeros -
+ * it returns a positive value for a positive zero (BigDecimal('0')) and
+ * a negative value for a negative zero (BigDecimal('-0')).
*
* The specific value returned indicates the type and sign of the BigDecimal,
* as follows:
@@ -3361,18 +3959,16 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
}
else {
- Real* vy;
- vy = VpCreateRbObject(prec, "#0", true);
+ Real* vy = NewZeroWrapNolimit(1, prec);
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
RB_GC_GUARD(vy->obj);
return VpCheckGetValue(vy);
}
}
else if (nan) {
- Real* vy;
- vy = VpCreateRbObject(prec, "#0", true);
- VpSetNaN(vy);
- RB_GC_GUARD(vy->obj);
+ Real* vy = NewZeroWrapNolimit(1, prec);
+ VpSetNaN(vy);
+ RB_GC_GUARD(vy->obj);
return VpCheckGetValue(vy);
}
else if (vx == NULL) {
@@ -3390,7 +3986,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
VpSetSign(vx, 1);
}
- one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
+ one = VpCheckGetValue(NewOneWrapLimited(1, 1));
y = one;
d = y;
i = 1;
@@ -3517,15 +4113,13 @@ get_vp_value:
break;
}
if (infinite && !negative) {
- Real* vy;
- vy = VpCreateRbObject(prec, "#0", true);
+ Real *vy = NewZeroWrapNolimit(1, prec);
RB_GC_GUARD(vy->obj);
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
return VpCheckGetValue(vy);
}
else if (nan) {
- Real* vy;
- vy = VpCreateRbObject(prec, "#0", true);
+ Real* vy = NewZeroWrapNolimit(1, prec);
RB_GC_GUARD(vy->obj);
VpSetNaN(vy);
return VpCheckGetValue(vy);
@@ -3539,7 +4133,7 @@ get_vp_value:
}
x = VpCheckGetValue(vx);
- RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
+ RB_GC_GUARD(one) = VpCheckGetValue(NewOneWrapLimited(1, 1));
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
@@ -3671,6 +4265,18 @@ BigDecimal_negative_zero(void)
*
* (1.2 - 1.0) == 0.2 #=> false
*
+ * == A Note About Precision
+ *
+ * For a calculation using a \BigDecimal and another +value+,
+ * the precision of the result depends on the type of +value+:
+ *
+ * - If +value+ is a \Float,
+ * the precision is Float::DIG + 1.
+ * - If +value+ is a \Rational, the precision is larger than Float::DIG + 1.
+ * - If +value+ is a \BigDecimal, the precision is +value+'s precision in the
+ * internal representation, which is platform-dependent.
+ * - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+.
+ *
* == Special features of accurate decimal arithmetic
*
* Because BigDecimal is more accurate than normal binary floating point
@@ -3931,6 +4537,8 @@ Init_bigdecimal(void)
/* instance methods */
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
+ rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0);
+ rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0);
rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
@@ -3949,7 +4557,7 @@ Init_bigdecimal(void)
rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
- rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
+ rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
@@ -3990,20 +4598,31 @@ Init_bigdecimal(void)
rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
- id_up = rb_intern_const("up");
- id_down = rb_intern_const("down");
- id_truncate = rb_intern_const("truncate");
- id_half_up = rb_intern_const("half_up");
- id_default = rb_intern_const("default");
- id_half_down = rb_intern_const("half_down");
- id_half_even = rb_intern_const("half_even");
- id_banker = rb_intern_const("banker");
- id_ceiling = rb_intern_const("ceiling");
- id_ceil = rb_intern_const("ceil");
- id_floor = rb_intern_const("floor");
+#define ROUNDING_MODE(i, name, value) \
+ id_##name = rb_intern_const(#name); \
+ rbd_rounding_modes[i].id = id_##name; \
+ rbd_rounding_modes[i].mode = value;
+
+ ROUNDING_MODE(0, up, RBD_ROUND_UP);
+ ROUNDING_MODE(1, down, RBD_ROUND_DOWN);
+ ROUNDING_MODE(2, half_up, RBD_ROUND_HALF_UP);
+ ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN);
+ ROUNDING_MODE(4, ceil, RBD_ROUND_CEIL);
+ ROUNDING_MODE(5, floor, RBD_ROUND_FLOOR);
+ ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN);
+
+ ROUNDING_MODE(7, default, RBD_ROUND_DEFAULT);
+ ROUNDING_MODE(8, truncate, RBD_ROUND_TRUNCATE);
+ ROUNDING_MODE(9, banker, RBD_ROUND_BANKER);
+ ROUNDING_MODE(10, ceiling, RBD_ROUND_CEILING);
+
+#undef ROUNDING_MODE
+
id_to_r = rb_intern_const("to_r");
id_eq = rb_intern_const("==");
id_half = rb_intern_const("half");
+
+ (void)VPrint; /* suppress unused warning */
}
/*
@@ -4023,7 +4642,7 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
#endif /* BIGDECIMAL_DEBUG */
static Real *VpConstOne; /* constant 1.0 */
-static Real *VpPt5; /* constant 0.5 */
+static Real *VpConstPt5; /* constant 0.5 */
#define maxnr 100UL /* Maximum iterations for calculating sqrt. */
/* used in VpSqrt() */
@@ -4054,42 +4673,6 @@ static int VpRdup(Real *m, size_t ind_m);
static int gnAlloc = 0; /* Memory allocation counter */
#endif /* BIGDECIMAL_DEBUG */
-VP_EXPORT void *
-VpMemAlloc(size_t mb)
-{
- void *p = xmalloc(mb);
- memset(p, 0, mb);
-#ifdef BIGDECIMAL_DEBUG
- gnAlloc++; /* Count allocation call */
-#endif /* BIGDECIMAL_DEBUG */
- return p;
-}
-
-VP_EXPORT void *
-VpMemRealloc(void *ptr, size_t mb)
-{
- return xrealloc(ptr, mb);
-}
-
-VP_EXPORT void
-VpFree(Real *pv)
-{
- if (pv != NULL) {
- xfree(pv);
-#ifdef BIGDECIMAL_DEBUG
- gnAlloc--; /* Decrement allocation count */
- if (gnAlloc == 0) {
- printf(" *************** All memories allocated freed ****************\n");
- /*getchar();*/
- }
- if (gnAlloc < 0) {
- printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
- /*getchar();*/
- }
-#endif /* BIGDECIMAL_DEBUG */
- }
-}
-
/*
* EXCEPTION Handling.
*/
@@ -4123,6 +4706,27 @@ VpSetException(unsigned short f)
bigdecimal_set_thread_local_exception_mode(f);
}
+static void
+VpCheckException(Real *p, bool always)
+{
+ if (VpIsNaN(p)) {
+ VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always);
+ }
+ else if (VpIsPosInf(p)) {
+ VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always);
+ }
+ else if (VpIsNegInf(p)) {
+ VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always);
+ }
+}
+
+static VALUE
+VpCheckGetValue(Real *p)
+{
+ VpCheckException(p, false);
+ return p->obj;
+}
+
/*
* Precision limit.
*/
@@ -4457,9 +5061,13 @@ VpInit(DECDIG BaseVal)
/* Setup +/- Inf NaN -0 */
VpGetDoubleNegZero();
- /* Allocates Vp constants. */
- VpConstOne = VpAlloc(1UL, "1", 1, 1);
- VpPt5 = VpAlloc(1UL, ".5", 1, 1);
+ /* Const 1.0 */
+ VpConstOne = NewOneNolimit(1, 1);
+
+ /* Const 0.5 */
+ VpConstPt5 = NewOneNolimit(1, 1);
+ VpConstPt5->exponent = 0;
+ VpConstPt5->frac[0] = 5*BASE1;
#ifdef BIGDECIMAL_DEBUG
gnAlloc = 0;
@@ -4548,7 +5156,7 @@ bigdecimal_parse_special_string(const char *str)
p = str + table[i].len;
while (*p && ISSPACE(*p)) ++p;
if (*p == '\0') {
- Real *vp = VpAllocReal(1);
+ Real *vp = rbd_allocate_struct(1);
vp->MaxPrec = 1;
switch (table[i].sign) {
default:
@@ -4572,11 +5180,11 @@ bigdecimal_parse_special_string(const char *str)
/*
* Allocates variable.
* [Input]
- * mx ... allocation unit, if zero then mx is determined by szVal.
- * The mx is the number of effective digits can to be stored.
- * szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
- * If szVal[0]=='#' then Max. Prec. will not be considered(1.1.7),
- * full precision specified by szVal is allocated.
+ * mx ... The number of decimal digits to be allocated, if zero then mx is determined by szVal.
+ * The mx will be the number of significant digits can to be stored.
+ * szVal ... The value assigned(char). If szVal==NULL, then zero is assumed.
+ * If szVal[0]=='#' then MaxPrec is not affected by the precision limit
+ * so that the full precision specified by szVal is allocated.
*
* [Returns]
* Pointer to the newly allocated variable, or
@@ -4587,48 +5195,40 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
{
const char *orig_szVal = szVal;
size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
+ size_t len;
char v, *psz;
int sign=1;
Real *vp = NULL;
- size_t mf = VpGetPrecLimit();
VALUE buf;
- mx = (mx + BASE_FIG - 1) / BASE_FIG; /* Determine allocation unit. */
- if (mx == 0) ++mx;
-
- if (szVal) {
- /* Skipping leading spaces */
- while (ISSPACE(*szVal)) szVal++;
-
- /* Processing the leading one `#` */
- if (*szVal != '#') {
- if (mf) {
- mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
- if (mx > mf) {
- mx = mf;
- }
- }
- }
- else {
- ++szVal;
- }
- }
- else {
+ if (szVal == NULL) {
return_zero:
/* necessary to be able to store */
/* at least mx digits. */
/* szVal==NULL ==> allocate zero value. */
- vp = VpAllocReal(mx);
- vp->MaxPrec = mx; /* set max precision */
+ vp = rbd_allocate_struct(mx);
+ vp->MaxPrec = rbd_calculate_internal_digits(mx, false); /* Must false */
VpSetZero(vp, 1); /* initialize vp to zero. */
return vp;
}
+ /* Skipping leading spaces */
+ while (ISSPACE(*szVal)) szVal++;
+
/* Check on Inf & NaN */
if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
return vp;
}
+ /* Processing the leading one `#` */
+ if (*szVal != '#') {
+ len = rbd_calculate_internal_digits(mx, true);
+ }
+ else {
+ len = rbd_calculate_internal_digits(mx, false);
+ ++szVal;
+ }
+
/* Scanning digits */
/* A buffer for keeping scanned digits */
@@ -4790,11 +5390,11 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
/* units for szVal[] */
- if (mx == 0) mx = 1;
- nalloc = Max(nalloc, mx);
- mx = nalloc;
- vp = VpAllocReal(mx);
- vp->MaxPrec = mx; /* set max precision */
+ if (len == 0) len = 1;
+ nalloc = Max(nalloc, len);
+ len = nalloc;
+ vp = rbd_allocate_struct(len);
+ vp->MaxPrec = len; /* set max precision */
VpSetZero(vp, sign);
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
rb_str_resize(buf, 0);
@@ -5359,7 +5959,7 @@ VpMult(Real *c, Real *a, Real *b)
if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
w = c;
- c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
+ c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG));
MxIndC = MxIndAB;
}
@@ -5367,8 +5967,8 @@ VpMult(Real *c, Real *a, Real *b)
c->exponent = a->exponent; /* set exponent */
if (!AddExponent(c, b->exponent)) {
- if (w) VpFree(c);
- return 0;
+ if (w) rbd_free_struct(c);
+ return 0;
}
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
carry = 0;
@@ -5418,10 +6018,10 @@ VpMult(Real *c, Real *a, Real *b)
}
}
if (w != NULL) { /* free work variable */
- VpNmlz(c);
- VpAsgn(w, c, 1);
- VpFree(c);
- c = w;
+ VpNmlz(c);
+ VpAsgn(w, c, 1);
+ rbd_free_struct(c);
+ c = w;
}
else {
VpLimitRound(c,0);
@@ -5486,18 +6086,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
word_c = c->MaxPrec;
word_r = r->MaxPrec;
- ind_c = 0;
- ind_r = 1;
-
if (word_a >= word_r) goto space_error;
+ ind_r = 1;
r->frac[0] = 0;
while (ind_r <= word_a) {
r->frac[ind_r] = a->frac[ind_r - 1];
++ind_r;
}
-
while (ind_r < word_r) r->frac[ind_r++] = 0;
+
+ ind_c = 0;
while (ind_c < word_c) c->frac[ind_c++] = 0;
/* initial procedure */
@@ -5791,7 +6390,6 @@ Exit:
* Note: % must not appear more than once
* a ... VP variable to be printed
*/
-#ifdef BIGDECIMAL_ENABLE_VPRINT
static int
VPrint(FILE *fp, const char *cntl_chr, Real *a)
{
@@ -5804,95 +6402,94 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
/* nc : number of characters printed */
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
while (*(cntl_chr + j)) {
- if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
- nc = 0;
- if (VpIsNaN(a)) {
- fprintf(fp, SZ_NaN);
- nc += 8;
- }
- else if (VpIsPosInf(a)) {
- fprintf(fp, SZ_INF);
- nc += 8;
- }
- else if (VpIsNegInf(a)) {
- fprintf(fp, SZ_NINF);
- nc += 9;
- }
- else if (!VpIsZero(a)) {
- if (BIGDECIMAL_NEGATIVE_P(a)) {
- fprintf(fp, "-");
- ++nc;
- }
- nc += fprintf(fp, "0.");
- switch (*(cntl_chr + j + 1)) {
- default:
- break;
+ if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
+ nc = 0;
+ if (VpIsNaN(a)) {
+ fprintf(fp, SZ_NaN);
+ nc += 8;
+ }
+ else if (VpIsPosInf(a)) {
+ fprintf(fp, SZ_INF);
+ nc += 8;
+ }
+ else if (VpIsNegInf(a)) {
+ fprintf(fp, SZ_NINF);
+ nc += 9;
+ }
+ else if (!VpIsZero(a)) {
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
+ fprintf(fp, "-");
+ ++nc;
+ }
+ nc += fprintf(fp, "0.");
+ switch (*(cntl_chr + j + 1)) {
+ default:
+ break;
- case '0': case 'z':
- ZeroSup = 0;
- ++j;
- sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
- break;
- }
- for (i = 0; i < a->Prec; ++i) {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- if (!ZeroSup || nn) {
- nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
- /* as 0.00xx will not */
- /* be printed. */
- ++nd;
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- if (nd >= sep) { /* print ' ' after every 10 digits */
- nd = 0;
- nc += fprintf(fp, " ");
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
- nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
- }
- else {
- nc += fprintf(fp, "0.0");
- }
- }
- else {
- ++nc;
- if (*(cntl_chr + j) == '\\') {
- switch (*(cntl_chr + j + 1)) {
- case 'n':
- fprintf(fp, "\n");
- ++j;
- break;
- case 't':
- fprintf(fp, "\t");
- ++j;
- break;
- case 'b':
- fprintf(fp, "\n");
- ++j;
- break;
- default:
- fprintf(fp, "%c", *(cntl_chr + j));
- break;
- }
- }
- else {
- fprintf(fp, "%c", *(cntl_chr + j));
- if (*(cntl_chr + j) == '%') ++j;
- }
- }
- j++;
+ case '0': case 'z':
+ ZeroSup = 0;
+ ++j;
+ sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
+ break;
+ }
+ for (i = 0; i < a->Prec; ++i) {
+ m = BASE1;
+ e = a->frac[i];
+ while (m) {
+ nn = e / m;
+ if (!ZeroSup || nn) {
+ nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
+ /* as 0.00xx will not */
+ /* be printed. */
+ ++nd;
+ ZeroSup = 0; /* Set to print succeeding zeros */
+ }
+ if (nd >= sep) { /* print ' ' after every 10 digits */
+ nd = 0;
+ nc += fprintf(fp, " ");
+ }
+ e = e - nn * m;
+ m /= 10;
+ }
+ }
+ nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
+ nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
+ }
+ else {
+ nc += fprintf(fp, "0.0");
+ }
+ }
+ else {
+ ++nc;
+ if (*(cntl_chr + j) == '\\') {
+ switch (*(cntl_chr + j + 1)) {
+ case 'n':
+ fprintf(fp, "\n");
+ ++j;
+ break;
+ case 't':
+ fprintf(fp, "\t");
+ ++j;
+ break;
+ case 'b':
+ fprintf(fp, "\n");
+ ++j;
+ break;
+ default:
+ fprintf(fp, "%c", *(cntl_chr + j));
+ break;
+ }
+ }
+ else {
+ fprintf(fp, "%c", *(cntl_chr + j));
+ if (*(cntl_chr + j) == '%') ++j;
+ }
+ }
+ j++;
}
return (int)nc;
}
-#endif
static void
VpFormatSt(char *psz, size_t fFmt)
@@ -5937,188 +6534,254 @@ VpExponent10(Real *a)
}
VP_EXPORT void
-VpSzMantissa(Real *a,char *psz)
+VpSzMantissa(Real *a, char *buf, size_t buflen)
{
size_t i, n, ZeroSup;
DECDIG_DBL m, e, nn;
if (VpIsNaN(a)) {
- sprintf(psz, SZ_NaN);
- return;
+ snprintf(buf, buflen, SZ_NaN);
+ return;
}
if (VpIsPosInf(a)) {
- sprintf(psz, SZ_INF);
+ snprintf(buf, buflen, SZ_INF);
return;
}
if (VpIsNegInf(a)) {
- sprintf(psz, SZ_NINF);
+ snprintf(buf, buflen, SZ_NINF);
return;
}
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
if (!VpIsZero(a)) {
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
- n = a->Prec;
- for (i = 0; i < n; ++i) {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- if (!ZeroSup || nn) {
- sprintf(psz, "%lu", (unsigned long)nn); /* The leading zero(s) */
- psz += strlen(psz);
- /* as 0.00xx will be ignored. */
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- e = e - nn * m;
- m /= 10;
- }
- }
- *psz = 0;
- while (psz[-1] == '0') *(--psz) = 0;
+ if (BIGDECIMAL_NEGATIVE_P(a)) *buf++ = '-';
+ n = a->Prec;
+ for (i = 0; i < n; ++i) {
+ m = BASE1;
+ e = a->frac[i];
+ while (m) {
+ nn = e / m;
+ if (!ZeroSup || nn) {
+ snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */
+ buf += strlen(buf);
+ /* as 0.00xx will be ignored. */
+ ZeroSup = 0; /* Set to print succeeding zeros */
+ }
+ e = e - nn * m;
+ m /= 10;
+ }
+ }
+ *buf = 0;
+ while (buf[-1] == '0') *(--buf) = 0;
}
else {
- if (VpIsPosZero(a)) sprintf(psz, "0");
- else sprintf(psz, "-0");
+ if (VpIsPosZero(a)) snprintf(buf, buflen, "0");
+ else snprintf(buf, buflen, "-0");
}
}
VP_EXPORT int
-VpToSpecialString(Real *a,char *psz,int fPlus)
+VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
{
if (VpIsNaN(a)) {
- sprintf(psz,SZ_NaN);
- return 1;
+ snprintf(buf, buflen, SZ_NaN);
+ return 1;
}
if (VpIsPosInf(a)) {
- if (fPlus == 1) {
- *psz++ = ' ';
- }
- else if (fPlus == 2) {
- *psz++ = '+';
- }
- sprintf(psz, SZ_INF);
- return 1;
+ if (fPlus == 1) {
+ *buf++ = ' ';
+ }
+ else if (fPlus == 2) {
+ *buf++ = '+';
+ }
+ snprintf(buf, buflen, SZ_INF);
+ return 1;
}
if (VpIsNegInf(a)) {
- sprintf(psz, SZ_NINF);
- return 1;
+ snprintf(buf, buflen, SZ_NINF);
+ return 1;
}
if (VpIsZero(a)) {
- if (VpIsPosZero(a)) {
- if (fPlus == 1) sprintf(psz, " 0.0");
- else if (fPlus == 2) sprintf(psz, "+0.0");
- else sprintf(psz, "0.0");
- }
- else sprintf(psz, "-0.0");
- return 1;
+ if (VpIsPosZero(a)) {
+ if (fPlus == 1) snprintf(buf, buflen, " 0.0");
+ else if (fPlus == 2) snprintf(buf, buflen, "+0.0");
+ else snprintf(buf, buflen, "0.0");
+ }
+ else snprintf(buf, buflen, "-0.0");
+ return 1;
}
return 0;
}
VP_EXPORT void
-VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
+VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
{
size_t i, n, ZeroSup;
DECDIG shift, m, e, nn;
- char *pszSav = psz;
+ char *p = buf;
+ size_t plen = buflen;
ssize_t ex;
- if (VpToSpecialString(a, psz, fPlus)) return;
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
- else if (fPlus == 1) *psz++ = ' ';
- else if (fPlus == 2) *psz++ = '+';
+#define ADVANCE(n) do { \
+ if (plen < n) goto overflow; \
+ p += n; \
+ plen -= n; \
+} while (0)
+
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
+ *p = '-';
+ ADVANCE(1);
+ }
+ else if (fPlus == 1) {
+ *p = ' ';
+ ADVANCE(1);
+ }
+ else if (fPlus == 2) {
+ *p = '+';
+ ADVANCE(1);
+ }
+
+ *p = '0'; ADVANCE(1);
+ *p = '.'; ADVANCE(1);
- *psz++ = '0';
- *psz++ = '.';
n = a->Prec;
for (i = 0; i < n; ++i) {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- if (!ZeroSup || nn) {
- sprintf(psz, "%lu", (unsigned long)nn); /* The reading zero(s) */
- psz += strlen(psz);
- /* as 0.00xx will be ignored. */
- ZeroSup = 0; /* Set to print succeeding zeros */
- }
- e = e - nn * m;
- m /= 10;
- }
+ m = BASE1;
+ e = a->frac[i];
+ while (m) {
+ nn = e / m;
+ if (!ZeroSup || nn) {
+ /* The reading zero(s) */
+ size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn);
+ if (n > plen) goto overflow;
+ ADVANCE(n);
+ /* as 0.00xx will be ignored. */
+ ZeroSup = 0; /* Set to print succeeding zeros */
+ }
+ e = e - nn * m;
+ m /= 10;
+ }
}
+
ex = a->exponent * (ssize_t)BASE_FIG;
shift = BASE1;
while (a->frac[0] / shift == 0) {
- --ex;
- shift /= 10;
+ --ex;
+ shift /= 10;
}
- while (psz[-1] == '0') {
- *(--psz) = 0;
+ while (p - 1 > buf && p[-1] == '0') {
+ *(--p) = '\0';
+ ++plen;
}
- sprintf(psz, "e%"PRIdSIZE, ex);
- if (fFmt) VpFormatSt(pszSav, fFmt);
+ snprintf(p, plen, "e%"PRIdSIZE, ex);
+ if (fFmt) VpFormatSt(buf, fFmt);
+
+ overflow:
+ return;
+#undef ADVANCE
}
VP_EXPORT void
-VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
+VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
{
size_t i, n;
DECDIG m, e, nn;
- char *pszSav = psz;
+ char *p = buf;
+ size_t plen = buflen;
ssize_t ex;
- if (VpToSpecialString(a, psz, fPlus)) return;
+ if (VpToSpecialString(a, buf, buflen, fPlus)) return;
- if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
- else if (fPlus == 1) *psz++ = ' ';
- else if (fPlus == 2) *psz++ = '+';
+#define ADVANCE(n) do { \
+ if (plen < n) goto overflow; \
+ p += n; \
+ plen -= n; \
+} while (0)
+
+
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
+ *p = '-';
+ ADVANCE(1);
+ }
+ else if (fPlus == 1) {
+ *p = ' ';
+ ADVANCE(1);
+ }
+ else if (fPlus == 2) {
+ *p = '+';
+ ADVANCE(1);
+ }
n = a->Prec;
ex = a->exponent;
if (ex <= 0) {
- *psz++ = '0';*psz++ = '.';
- while (ex < 0) {
- for (i=0; i < BASE_FIG; ++i) *psz++ = '0';
- ++ex;
- }
- ex = -1;
+ *p = '0'; ADVANCE(1);
+ *p = '.'; ADVANCE(1);
+ while (ex < 0) {
+ for (i=0; i < BASE_FIG; ++i) {
+ *p = '0'; ADVANCE(1);
+ }
+ ++ex;
+ }
+ ex = -1;
}
for (i = 0; i < n; ++i) {
- --ex;
- if (i == 0 && ex >= 0) {
- sprintf(psz, "%lu", (unsigned long)a->frac[i]);
- psz += strlen(psz);
- }
- else {
- m = BASE1;
- e = a->frac[i];
- while (m) {
- nn = e / m;
- *psz++ = (char)(nn + '0');
- e = e - nn * m;
- m /= 10;
- }
- }
- if (ex == 0) *psz++ = '.';
+ --ex;
+ if (i == 0 && ex >= 0) {
+ size_t n = snprintf(p, plen, "%lu", (unsigned long)a->frac[i]);
+ if (n > plen) goto overflow;
+ ADVANCE(n);
+ }
+ else {
+ m = BASE1;
+ e = a->frac[i];
+ while (m) {
+ nn = e / m;
+ *p = (char)(nn + '0');
+ ADVANCE(1);
+ e = e - nn * m;
+ m /= 10;
+ }
+ }
+ if (ex == 0) {
+ *p = '.';
+ ADVANCE(1);
+ }
}
while (--ex>=0) {
- m = BASE;
- while (m /= 10) *psz++ = '0';
- if (ex == 0) *psz++ = '.';
+ m = BASE;
+ while (m /= 10) {
+ *p = '0';
+ ADVANCE(1);
+ }
+ if (ex == 0) {
+ *p = '.';
+ ADVANCE(1);
+ }
+ }
+
+ *p = '\0';
+ while (p - 1 > buf && p[-1] == '0') {
+ *(--p) = '\0';
+ ++plen;
}
- *psz = 0;
- while (psz[-1] == '0') *(--psz) = 0;
- if (psz[-1] == '.') sprintf(psz, "0");
- if (fFmt) VpFormatSt(pszSav, fFmt);
+ if (p - 1 > buf && p[-1] == '.') {
+ snprintf(p, plen, "0");
+ }
+ if (fFmt) VpFormatSt(buf, fFmt);
+
+ overflow:
+ return;
+#undef ADVANCE
}
/*
@@ -6527,8 +7190,9 @@ VpSqrt(Real *y, Real *x)
if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
/* allocate temporally variables */
- f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
- r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
+ /* TODO: reconsider MaxPrec of f and r */
+ f = NewOneNolimit(1, y->MaxPrec * (BASE_FIG + 2));
+ r = NewOneNolimit(1, (n + n) * (BASE_FIG + 2));
nr = 0;
y_prec = y->MaxPrec;
@@ -6553,16 +7217,21 @@ VpSqrt(Real *y, Real *x)
f->MaxPrec = y->MaxPrec + 1;
n = (SIGNED_VALUE)(y_prec * BASE_FIG);
if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
+
+ /*
+ * Perform: y_{n+1} = (y_n - x/y_n) / 2
+ */
do {
- y->MaxPrec *= 2;
- if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
- f->MaxPrec = y->MaxPrec;
- VpDivd(f, r, x, y); /* f = x/y */
- VpAddSub(r, f, y, -1); /* r = f - y */
- VpMult(f, VpPt5, r); /* f = 0.5*r */
- if (VpIsZero(f)) goto converge;
- VpAddSub(r, f, y, 1); /* r = y + f */
- VpAsgn(y, r, 1); /* y = r */
+ y->MaxPrec *= 2;
+ if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
+ f->MaxPrec = y->MaxPrec;
+ VpDivd(f, r, x, y); /* f = x/y */
+ VpAddSub(r, f, y, -1); /* r = f - y */
+ VpMult(f, VpConstPt5, r); /* f = 0.5*r */
+ if (VpIsZero(f))
+ goto converge;
+ VpAddSub(r, f, y, 1); /* r = y + f */
+ VpAsgn(y, r, 1); /* y = r */
} while (++nr < n);
#ifdef BIGDECIMAL_DEBUG
@@ -6587,8 +7256,8 @@ converge:
y->MaxPrec = y_prec;
Exit:
- VpFree(f);
- VpFree(r);
+ rbd_free_struct(f);
+ rbd_free_struct(r);
return 1;
}
@@ -6979,9 +7648,10 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
}
/* Allocate working variables */
+ /* TODO: reconsider MaxPrec of w1 and w2 */
+ w1 = NewZeroNolimit(1, (y->MaxPrec + 2) * BASE_FIG);
+ w2 = NewZeroNolimit(1, (w1->MaxPrec * 2 + 1) * BASE_FIG);
- w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
- w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
/* calculation start */
VpAsgn(y, x, 1);
@@ -7010,8 +7680,8 @@ Exit:
printf(" n=%"PRIdVALUE"\n", n);
}
#endif /* BIGDECIMAL_DEBUG */
- VpFree(w2);
- VpFree(w1);
+ rbd_free_struct(w2);
+ rbd_free_struct(w1);
return 1;
}
diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec
index 79009aa19b..d215757188 100644
--- a/ext/bigdecimal/bigdecimal.gemspec
+++ b/ext/bigdecimal/bigdecimal.gemspec
@@ -1,17 +1,15 @@
# coding: utf-8
-bigdecimal_version = '3.0.0'
-
Gem::Specification.new do |s|
s.name = "bigdecimal"
- s.version = bigdecimal_version
+ s.version = "3.1.3"
s.authors = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"]
s.email = ["mrkn@mrkn.jp"]
s.summary = "Arbitrary-precision decimal floating-point number library."
s.description = "This library provides arbitrary-precision decimal floating-point number class."
s.homepage = "https://github.com/ruby/bigdecimal"
- s.license = "Ruby"
+ s.licenses = ["Ruby", "bsd-2-clause"]
s.require_paths = %w[lib]
s.extensions = %w[ext/bigdecimal/extconf.rb]
@@ -36,11 +34,5 @@ Gem::Specification.new do |s|
sample/pi.rb
]
- s.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
-
- s.add_development_dependency "fiddle"
- 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 "irb"
+ s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
end
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
index bd1c46743e..54fed811fb 100644
--- a/ext/bigdecimal/bigdecimal.h
+++ b/ext/bigdecimal/bigdecimal.h
@@ -102,7 +102,7 @@ extern VALUE rb_cBigDecimal;
*/
#define VP_EXPORT static
-/* Exception codes */
+/* Exception mode */
#define VP_EXCEPTION_ALL ((unsigned short)0x00FF)
#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001)
#define VP_EXCEPTION_NaN ((unsigned short)0x0002)
@@ -115,18 +115,36 @@ extern VALUE rb_cBigDecimal;
#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U
-/* Computation mode */
+/* This is used in BigDecimal#mode */
#define VP_ROUND_MODE ((unsigned short)0x0100)
-#define VP_ROUND_UP 1
-#define VP_ROUND_DOWN 2
-#define VP_ROUND_HALF_UP 3
-#define VP_ROUND_HALF_DOWN 4
-#define VP_ROUND_CEIL 5
-#define VP_ROUND_FLOOR 6
-#define VP_ROUND_HALF_EVEN 7
+
+/* Rounding mode */
+#define VP_ROUND_UP RBD_ROUND_UP
+#define VP_ROUND_DOWN RBD_ROUND_DOWN
+#define VP_ROUND_HALF_UP RBD_ROUND_HALF_UP
+#define VP_ROUND_HALF_DOWN RBD_ROUND_HALF_DOWN
+#define VP_ROUND_CEIL RBD_ROUND_CEIL
+#define VP_ROUND_FLOOR RBD_ROUND_FLOOR
+#define VP_ROUND_HALF_EVEN RBD_ROUND_HALF_EVEN
+
+enum rbd_rounding_mode {
+ RBD_ROUND_UP = 1,
+ RBD_ROUND_DOWN = 2,
+ RBD_ROUND_HALF_UP = 3,
+ RBD_ROUND_HALF_DOWN = 4,
+ RBD_ROUND_CEIL = 5,
+ RBD_ROUND_FLOOR = 6,
+ RBD_ROUND_HALF_EVEN = 7,
+
+ RBD_ROUND_DEFAULT = RBD_ROUND_HALF_UP,
+ RBD_ROUND_TRUNCATE = RBD_ROUND_DOWN,
+ RBD_ROUND_BANKER = RBD_ROUND_HALF_EVEN,
+ RBD_ROUND_CEILING = RBD_ROUND_CEIL
+};
#define BIGDECIMAL_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
+/* Sign flag */
#define VP_SIGN_NaN 0 /* NaN */
#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */
@@ -135,6 +153,7 @@ extern VALUE rb_cBigDecimal;
#define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */
#define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */
+/* The size of fraction part array */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define FLEXIBLE_ARRAY_SIZE /* */
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
@@ -205,9 +224,6 @@ VP_EXPORT int VpIsNegDoubleZero(double v);
#endif
VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
VP_EXPORT size_t VpInit(DECDIG BaseVal);
-VP_EXPORT void *VpMemAlloc(size_t mb);
-VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
-VP_EXPORT void VpFree(Real *pv);
VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc);
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
@@ -215,10 +231,10 @@ VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b);
VP_EXPORT int VpComp(Real *a,Real *b);
VP_EXPORT ssize_t VpExponent10(Real *a);
-VP_EXPORT void VpSzMantissa(Real *a,char *psz);
-VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus);
-VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus);
-VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus);
+VP_EXPORT void VpSzMantissa(Real *a, char *buf, size_t bufsize);
+VP_EXPORT int VpToSpecialString(Real *a, char *buf, size_t bufsize, int fPlus);
+VP_EXPORT void VpToString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus);
+VP_EXPORT void VpToFString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus);
VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne);
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m);
VP_EXPORT void VpDtoV(Real *m,double d);
diff --git a/ext/bigdecimal/depend b/ext/bigdecimal/depend
index d54de7c3c7..ee892162f2 100644
--- a/ext/bigdecimal/depend
+++ b/ext/bigdecimal/depend
@@ -8,7 +8,6 @@ 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
@@ -16,6 +15,7 @@ bigdecimal.o: $(hdrdir)/ruby/backward/2/stdalign.h
bigdecimal.o: $(hdrdir)/ruby/backward/2/stdarg.h
bigdecimal.o: $(hdrdir)/ruby/defines.h
bigdecimal.o: $(hdrdir)/ruby/intern.h
+bigdecimal.o: $(hdrdir)/ruby/internal/abi.h
bigdecimal.o: $(hdrdir)/ruby/internal/anyargs.h
bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic.h
bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -174,7 +174,6 @@ missing.o: $(hdrdir)/ruby/backward.h
missing.o: $(hdrdir)/ruby/backward/2/assume.h
missing.o: $(hdrdir)/ruby/backward/2/attributes.h
missing.o: $(hdrdir)/ruby/backward/2/bool.h
-missing.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
missing.o: $(hdrdir)/ruby/backward/2/inttypes.h
missing.o: $(hdrdir)/ruby/backward/2/limits.h
missing.o: $(hdrdir)/ruby/backward/2/long_long.h
@@ -182,6 +181,7 @@ missing.o: $(hdrdir)/ruby/backward/2/stdalign.h
missing.o: $(hdrdir)/ruby/backward/2/stdarg.h
missing.o: $(hdrdir)/ruby/defines.h
missing.o: $(hdrdir)/ruby/intern.h
+missing.o: $(hdrdir)/ruby/internal/abi.h
missing.o: $(hdrdir)/ruby/internal/anyargs.h
missing.o: $(hdrdir)/ruby/internal/arithmetic.h
missing.o: $(hdrdir)/ruby/internal/arithmetic/char.h
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
index c92aacb3f2..17e7905dd6 100644
--- a/ext/bigdecimal/extconf.rb
+++ b/ext/bigdecimal/extconf.rb
@@ -3,10 +3,7 @@ require 'mkmf'
def check_bigdecimal_version(gemspec_path)
message "checking RUBY_BIGDECIMAL_VERSION... "
-
- bigdecimal_version =
- IO.readlines(gemspec_path)
- .grep(/\Abigdecimal_version\s+=\s+/)[0][/\'([^\']+)\'/, 1]
+ bigdecimal_version = File.read(gemspec_path).match(/^\s*s\.version\s+=\s+['"]([^'"]+)['"]\s*$/)[1]
version_components = bigdecimal_version.split('.')
bigdecimal_version = version_components[0, 3].join('.')
@@ -70,14 +67,10 @@ have_header("ruby/atomic.h")
have_header("ruby/internal/has/builtin.h")
have_header("ruby/internal/static_assert.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")
diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
index 5e29304299..4448024c74 100644
--- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb
+++ b/ext/bigdecimal/lib/bigdecimal/jacobian.rb
@@ -42,8 +42,8 @@ module Jacobian
end
- # Computes the derivative of f[i] at x[i].
- # fx is the value of f at x.
+ # Computes the derivative of +f[i]+ at +x[i]+.
+ # +fx+ is the value of +f+ at +x+.
def dfdxi(f,fx,x,i)
nRetry = 0
n = x.size
@@ -75,7 +75,7 @@ module Jacobian
deriv
end
- # Computes the Jacobian of f at x. fx is the value of f at x.
+ # Computes the Jacobian of +f+ at +x+. +fx+ is the value of +f+ at +x+.
def jacobian(f,fx,x)
n = x.size
dfdx = Array.new(n*n)
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
index cb645d2a71..ad92f7cfe6 100644
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ b/ext/bigdecimal/lib/bigdecimal/util.rb
@@ -33,12 +33,16 @@ class Float < Numeric
#
# Returns the value of +float+ as a BigDecimal.
# The +precision+ parameter is used to determine the number of
- # significant digits for the result (the default is Float::DIG).
+ # significant digits for the result. When +precision+ is set to +0+,
+ # the number of digits to represent the float being converted is determined
+ # automatically.
+ # The default +precision+ is +0+.
#
# require 'bigdecimal'
# require 'bigdecimal/util'
#
# 0.5.to_d # => 0.5e0
+ # 1.234.to_d # => 0.1234e1
# 1.234.to_d(2) # => 0.12e1
#
# See also BigDecimal::new.
diff --git a/ext/bigdecimal/missing.h b/ext/bigdecimal/missing.h
index 7969849158..325554b5f5 100644
--- a/ext/bigdecimal/missing.h
+++ b/ext/bigdecimal/missing.h
@@ -35,10 +35,10 @@ extern "C" {
#endif /* RB_UNUSED_VAR */
#if defined(_MSC_VER) && _MSC_VER >= 1310
-# define HAVE___ASSUME
+# define HAVE___ASSUME 1
#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1300
-# define HAVE___ASSUME
+# define HAVE___ASSUME 1
#endif
#ifndef UNREACHABLE
@@ -126,7 +126,7 @@ char *BigDecimal_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, c
static inline VALUE
rb_rational_num(VALUE rat)
{
-#ifdef HAVE_TYPE_STRUCT_RRATIONAL
+#ifdef RRATIONAL
return RRATIONAL(rat)->num;
#else
return rb_funcall(rat, rb_intern("numerator"), 0);
@@ -138,7 +138,7 @@ rb_rational_num(VALUE rat)
static inline VALUE
rb_rational_den(VALUE rat)
{
-#ifdef HAVE_TYPE_STRUCT_RRATIONAL
+#ifdef RRATIONAL
return RRATIONAL(rat)->den;
#else
return rb_funcall(rat, rb_intern("denominator"), 0);
@@ -152,7 +152,7 @@ rb_rational_den(VALUE rat)
static inline VALUE
rb_complex_real(VALUE cmp)
{
-#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
+#ifdef RCOMPLEX
return RCOMPLEX(cmp)->real;
#else
return rb_funcall(cmp, rb_intern("real"), 0);
@@ -164,7 +164,7 @@ rb_complex_real(VALUE cmp)
static inline VALUE
rb_complex_imag(VALUE cmp)
{
-# ifdef HAVE_TYPE_STRUCT_RCOMPLEX
+# ifdef RCOMPLEX
return RCOMPLEX(cmp)->imag;
# else
return rb_funcall(cmp, rb_intern("imag"), 0);
@@ -172,45 +172,6 @@ rb_complex_imag(VALUE cmp)
}
#endif
-/* array */
-
-#ifndef FIX_CONST_VALUE_PTR
-# if defined(__fcc__) || defined(__fcc_version) || \
- defined(__FCC__) || defined(__FCC_VERSION)
-/* workaround for old version of Fujitsu C Compiler (fcc) */
-# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
-# else
-# define FIX_CONST_VALUE_PTR(x) (x)
-# endif
-#endif
-
-#ifndef HAVE_RB_ARRAY_CONST_PTR
-static inline const VALUE *
-rb_array_const_ptr(VALUE a)
-{
- return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ?
- RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr);
-}
-#endif
-
-#ifndef RARRAY_CONST_PTR
-# define RARRAY_CONST_PTR(a) rb_array_const_ptr(a)
-#endif
-
-#ifndef RARRAY_AREF
-# define RARRAY_AREF(a, i) (RARRAY_CONST_PTR(a)[i])
-#endif
-
-/* symbol */
-
-#ifndef HAVE_RB_SYM2STR
-static inline VALUE
-rb_sym2str(VALUE sym)
-{
- return rb_id2str(SYM2ID(sym));
-}
-#endif
-
/* st */
#ifndef ST2FIX
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend
index a11dbb674d..e3904d0695 100644
--- a/ext/cgi/escape/depend
+++ b/ext/cgi/escape/depend
@@ -2,6 +2,20 @@
escape.o: $(RUBY_EXTCONF_H)
escape.o: $(arch_hdrdir)/ruby/config.h
escape.o: $(hdrdir)/ruby.h
+escape.o: $(hdrdir)/ruby/assert.h
+escape.o: $(hdrdir)/ruby/backward.h
+escape.o: $(hdrdir)/ruby/backward/2/assume.h
+escape.o: $(hdrdir)/ruby/backward/2/attributes.h
+escape.o: $(hdrdir)/ruby/backward/2/bool.h
+escape.o: $(hdrdir)/ruby/backward/2/inttypes.h
+escape.o: $(hdrdir)/ruby/backward/2/limits.h
+escape.o: $(hdrdir)/ruby/backward/2/long_long.h
+escape.o: $(hdrdir)/ruby/backward/2/stdalign.h
+escape.o: $(hdrdir)/ruby/backward/2/stdarg.h
+escape.o: $(hdrdir)/ruby/defines.h
+escape.o: $(hdrdir)/ruby/encoding.h
+escape.o: $(hdrdir)/ruby/intern.h
+escape.o: $(hdrdir)/ruby/internal/abi.h
escape.o: $(hdrdir)/ruby/internal/anyargs.h
escape.o: $(hdrdir)/ruby/internal/arithmetic.h
escape.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ escape.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
escape.o: $(hdrdir)/ruby/internal/ctype.h
escape.o: $(hdrdir)/ruby/internal/dllexport.h
escape.o: $(hdrdir)/ruby/internal/dosish.h
+escape.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+escape.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+escape.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+escape.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+escape.o: $(hdrdir)/ruby/internal/encoding/re.h
+escape.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+escape.o: $(hdrdir)/ruby/internal/encoding/string.h
+escape.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+escape.o: $(hdrdir)/ruby/internal/encoding/transcode.h
escape.o: $(hdrdir)/ruby/internal/error.h
escape.o: $(hdrdir)/ruby/internal/eval.h
escape.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
escape.o: $(hdrdir)/ruby/missing.h
escape.o: $(hdrdir)/ruby/onigmo.h
escape.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
index 3a7837e4df..c5b76de596 100644
--- a/ext/cgi/escape/escape.c
+++ b/ext/cgi/escape/escape.c
@@ -32,11 +32,21 @@ preserve_original_state(VALUE orig, VALUE dest)
rb_enc_associate(dest, rb_enc_get(orig));
}
+static inline long
+escaped_length(VALUE str)
+{
+ const long len = RSTRING_LEN(str);
+ if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
+ }
+ return len * HTML_ESCAPE_MAX_LEN;
+}
+
static VALUE
optimized_escape_html(VALUE str)
{
VALUE vbuf;
- char *buf = ALLOCV_N(char, vbuf, RSTRING_LEN(str) * HTML_ESCAPE_MAX_LEN);
+ char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
const char *cstr = RSTRING_PTR(str);
const char *end = cstr + RSTRING_LEN(str);
@@ -71,8 +81,8 @@ optimized_unescape_html(VALUE str)
enum {UNICODE_MAX = 0x10ffff};
rb_encoding *enc = rb_enc_get(str);
unsigned long charlimit = (strcasecmp(rb_enc_name(enc), "UTF-8") == 0 ? UNICODE_MAX :
- strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 :
- 128);
+ strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 :
+ 128);
long i, len, beg = 0;
size_t clen, plen;
int overflow;
@@ -84,89 +94,89 @@ optimized_unescape_html(VALUE str)
cstr = RSTRING_PTR(str);
for (i = 0; i < len; i++) {
- unsigned long cc;
- char c = cstr[i];
- if (c != '&') continue;
- plen = i - beg;
- if (++i >= len) break;
- c = (unsigned char)cstr[i];
+ unsigned long cc;
+ char c = cstr[i];
+ if (c != '&') continue;
+ plen = i - beg;
+ if (++i >= len) break;
+ c = (unsigned char)cstr[i];
#define MATCH(s) (len - i >= (int)rb_strlen_lit(s) && \
- memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \
- (i += rb_strlen_lit(s) - 1, 1))
- switch (c) {
- case 'a':
- ++i;
- if (MATCH("pos;")) {
- c = '\'';
- }
- else if (MATCH("mp;")) {
- c = '&';
- }
- else continue;
- break;
- case 'q':
- ++i;
- if (MATCH("uot;")) {
- c = '"';
- }
- else continue;
- break;
- case 'g':
- ++i;
- if (MATCH("t;")) {
- c = '>';
- }
- else continue;
- break;
- case 'l':
- ++i;
- if (MATCH("t;")) {
- c = '<';
- }
- else continue;
- break;
- case '#':
- if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
- cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow);
- }
- else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) {
- cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow);
- }
- else continue;
- i += clen;
- if (overflow || cc >= charlimit || cstr[i] != ';') continue;
- if (!dest) {
- dest = rb_str_buf_new(len);
- }
- rb_str_cat(dest, cstr + beg, plen);
- if (charlimit > 256) {
- rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc));
- }
- else {
- c = (unsigned char)cc;
- rb_str_cat(dest, &c, 1);
- }
- beg = i + 1;
- continue;
- default:
- --i;
- continue;
- }
- if (!dest) {
- dest = rb_str_buf_new(len);
- }
- rb_str_cat(dest, cstr + beg, plen);
- rb_str_cat(dest, &c, 1);
- beg = i + 1;
+ memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \
+ (i += rb_strlen_lit(s) - 1, 1))
+ switch (c) {
+ case 'a':
+ ++i;
+ if (MATCH("pos;")) {
+ c = '\'';
+ }
+ else if (MATCH("mp;")) {
+ c = '&';
+ }
+ else continue;
+ break;
+ case 'q':
+ ++i;
+ if (MATCH("uot;")) {
+ c = '"';
+ }
+ else continue;
+ break;
+ case 'g':
+ ++i;
+ if (MATCH("t;")) {
+ c = '>';
+ }
+ else continue;
+ break;
+ case 'l':
+ ++i;
+ if (MATCH("t;")) {
+ c = '<';
+ }
+ else continue;
+ break;
+ case '#':
+ if (len - ++i >= 2 && ISDIGIT(cstr[i])) {
+ cc = ruby_scan_digits(&cstr[i], len-i, 10, &clen, &overflow);
+ }
+ else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) {
+ cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow);
+ }
+ else continue;
+ i += clen;
+ if (overflow || cc >= charlimit || cstr[i] != ';') continue;
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+ rb_str_cat(dest, cstr + beg, plen);
+ if (charlimit > 256) {
+ rb_str_cat(dest, buf, rb_enc_mbcput((OnigCodePoint)cc, buf, enc));
+ }
+ else {
+ c = (unsigned char)cc;
+ rb_str_cat(dest, &c, 1);
+ }
+ beg = i + 1;
+ continue;
+ default:
+ --i;
+ continue;
+ }
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+ rb_str_cat(dest, cstr + beg, plen);
+ rb_str_cat(dest, &c, 1);
+ beg = i + 1;
}
if (dest) {
- rb_str_cat(dest, cstr + beg, len - beg);
- preserve_original_state(str, dest);
- return dest;
+ rb_str_cat(dest, cstr + beg, len - beg);
+ preserve_original_state(str, dest);
+ return dest;
}
else {
- return rb_str_dup(str);
+ return rb_str_dup(str);
}
}
@@ -190,7 +200,7 @@ url_unreserved_char(unsigned char c)
}
static VALUE
-optimized_escape(VALUE str)
+optimized_escape(VALUE str, int plus_escape)
{
long i, len, beg = 0;
VALUE dest = 0;
@@ -201,38 +211,38 @@ optimized_escape(VALUE str)
cstr = RSTRING_PTR(str);
for (i = 0; i < len; ++i) {
- const unsigned char c = (unsigned char)cstr[i];
- if (!url_unreserved_char(c)) {
- if (!dest) {
- dest = rb_str_buf_new(len);
- }
-
- rb_str_cat(dest, cstr + beg, i - beg);
- beg = i + 1;
-
- if (c == ' ') {
- rb_str_cat_cstr(dest, "+");
- }
- else {
- buf[1] = upper_hexdigits[(c >> 4) & 0xf];
- buf[2] = upper_hexdigits[c & 0xf];
- rb_str_cat(dest, buf, 3);
- }
- }
+ const unsigned char c = (unsigned char)cstr[i];
+ if (!url_unreserved_char(c)) {
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+
+ rb_str_cat(dest, cstr + beg, i - beg);
+ beg = i + 1;
+
+ if (plus_escape && c == ' ') {
+ rb_str_cat_cstr(dest, "+");
+ }
+ else {
+ buf[1] = upper_hexdigits[(c >> 4) & 0xf];
+ buf[2] = upper_hexdigits[c & 0xf];
+ rb_str_cat(dest, buf, 3);
+ }
+ }
}
if (dest) {
- rb_str_cat(dest, cstr + beg, len - beg);
- preserve_original_state(str, dest);
- return dest;
+ rb_str_cat(dest, cstr + beg, len - beg);
+ preserve_original_state(str, dest);
+ return dest;
}
else {
- return rb_str_dup(str);
+ return rb_str_dup(str);
}
}
static VALUE
-optimized_unescape(VALUE str, VALUE encoding)
+optimized_unescape(VALUE str, VALUE encoding, int unescape_plus)
{
long i, len, beg = 0;
VALUE dest = 0;
@@ -244,52 +254,52 @@ optimized_unescape(VALUE str, VALUE encoding)
cstr = RSTRING_PTR(str);
for (i = 0; i < len; ++i) {
- char buf[1];
- const char c = cstr[i];
- int clen = 0;
- if (c == '%') {
- if (i + 3 > len) break;
- if (!ISXDIGIT(cstr[i+1])) continue;
- if (!ISXDIGIT(cstr[i+2])) continue;
- buf[0] = ((char_to_number(cstr[i+1]) << 4)
- | char_to_number(cstr[i+2]));
- clen = 2;
- }
- else if (c == '+') {
- buf[0] = ' ';
- }
- else {
- continue;
- }
-
- if (!dest) {
- dest = rb_str_buf_new(len);
- }
-
- rb_str_cat(dest, cstr + beg, i - beg);
- i += clen;
- beg = i + 1;
-
- rb_str_cat(dest, buf, 1);
+ char buf[1];
+ const char c = cstr[i];
+ int clen = 0;
+ if (c == '%') {
+ if (i + 3 > len) break;
+ if (!ISXDIGIT(cstr[i+1])) continue;
+ if (!ISXDIGIT(cstr[i+2])) continue;
+ buf[0] = ((char_to_number(cstr[i+1]) << 4)
+ | char_to_number(cstr[i+2]));
+ clen = 2;
+ }
+ else if (unescape_plus && c == '+') {
+ buf[0] = ' ';
+ }
+ else {
+ continue;
+ }
+
+ if (!dest) {
+ dest = rb_str_buf_new(len);
+ }
+
+ rb_str_cat(dest, cstr + beg, i - beg);
+ i += clen;
+ beg = i + 1;
+
+ rb_str_cat(dest, buf, 1);
}
if (dest) {
- rb_str_cat(dest, cstr + beg, len - beg);
- preserve_original_state(str, dest);
- cr = ENC_CODERANGE_UNKNOWN;
+ rb_str_cat(dest, cstr + beg, len - beg);
+ preserve_original_state(str, dest);
+ cr = ENC_CODERANGE_UNKNOWN;
}
else {
- dest = rb_str_dup(str);
- cr = ENC_CODERANGE(str);
+ dest = rb_str_dup(str);
+ cr = ENC_CODERANGE(str);
}
origenc = rb_enc_get_index(str);
if (origenc != encidx) {
- rb_enc_associate_index(dest, encidx);
- if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) {
- rb_enc_associate_index(dest, origenc);
- if (cr != ENC_CODERANGE_UNKNOWN)
- ENC_CODERANGE_SET(dest, cr);
- }
+ rb_enc_associate_index(dest, encidx);
+ if (!ENC_CODERANGE_CLEAN_P(rb_enc_str_coderange(dest))) {
+ rb_enc_associate_index(dest, origenc);
+ if (cr != ENC_CODERANGE_UNKNOWN)
+ ENC_CODERANGE_SET(dest, cr);
+ }
}
return dest;
}
@@ -307,10 +317,10 @@ cgiesc_escape_html(VALUE self, VALUE str)
StringValue(str);
if (rb_enc_str_asciicompat_p(str)) {
- return optimized_escape_html(str);
+ return optimized_escape_html(str);
}
else {
- return rb_call_super(1, &str);
+ return rb_call_super(1, &str);
}
}
@@ -327,10 +337,10 @@ cgiesc_unescape_html(VALUE self, VALUE str)
StringValue(str);
if (rb_enc_str_asciicompat_p(str)) {
- return optimized_unescape_html(str);
+ return optimized_unescape_html(str);
}
else {
- return rb_call_super(1, &str);
+ return rb_call_super(1, &str);
}
}
@@ -338,7 +348,7 @@ cgiesc_unescape_html(VALUE self, VALUE str)
* call-seq:
* CGI.escape(string) -> string
*
- * Returns URL-escaped string.
+ * Returns URL-escaped string (+application/x-www-form-urlencoded+).
*
*/
static VALUE
@@ -347,10 +357,10 @@ cgiesc_escape(VALUE self, VALUE str)
StringValue(str);
if (rb_enc_str_asciicompat_p(str)) {
- return optimized_escape(str);
+ return optimized_escape(str, 1);
}
else {
- return rb_call_super(1, &str);
+ return rb_call_super(1, &str);
}
}
@@ -358,7 +368,7 @@ static VALUE
accept_charset(int argc, VALUE *argv, VALUE self)
{
if (argc > 0)
- return argv[0];
+ return argv[0];
return rb_cvar_get(CLASS_OF(self), id_accept_charset);
}
@@ -366,7 +376,7 @@ accept_charset(int argc, VALUE *argv, VALUE self)
* call-seq:
* CGI.unescape(string, encoding=@@accept_charset) -> string
*
- * Returns URL-unescaped string.
+ * Returns URL-unescaped string (+application/x-www-form-urlencoded+).
*
*/
static VALUE
@@ -377,11 +387,54 @@ cgiesc_unescape(int argc, VALUE *argv, VALUE self)
StringValue(str);
if (rb_enc_str_asciicompat_p(str)) {
- VALUE enc = accept_charset(argc-1, argv+1, self);
- return optimized_unescape(str, enc);
+ VALUE enc = accept_charset(argc-1, argv+1, self);
+ return optimized_unescape(str, enc, 1);
+ }
+ else {
+ return rb_call_super(argc, argv);
+ }
+}
+
+/*
+ * call-seq:
+ * CGI.escapeURIComponent(string) -> string
+ *
+ * Returns URL-escaped string following RFC 3986.
+ *
+ */
+static VALUE
+cgiesc_escape_uri_component(VALUE self, VALUE str)
+{
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_escape(str, 0);
+ }
+ else {
+ return rb_call_super(1, &str);
+ }
+}
+
+/*
+ * call-seq:
+ * CGI.unescapeURIComponent(string, encoding=@@accept_charset) -> string
+ *
+ * Returns URL-unescaped string following RFC 3986.
+ *
+ */
+static VALUE
+cgiesc_unescape_uri_component(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str = (rb_check_arity(argc, 1, 2), argv[0]);
+
+ StringValue(str);
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ VALUE enc = accept_charset(argc-1, argv+1, self);
+ return optimized_unescape(str, enc, 0);
}
else {
- return rb_call_super(argc, argv);
+ return rb_call_super(argc, argv);
}
}
@@ -404,6 +457,8 @@ InitVM_escape(void)
rb_mUtil = rb_define_module_under(rb_cCGI, "Util");
rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1);
rb_define_method(rb_mEscape, "unescapeHTML", cgiesc_unescape_html, 1);
+ rb_define_method(rb_mEscape, "escapeURIComponent", cgiesc_escape_uri_component, 1);
+ rb_define_method(rb_mEscape, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1);
rb_define_method(rb_mEscape, "unescape", cgiesc_unescape, -1);
rb_prepend_module(rb_mUtil, rb_mEscape);
diff --git a/ext/continuation/depend b/ext/continuation/depend
index c8e55b0b1c..81218f9965 100644
--- a/ext/continuation/depend
+++ b/ext/continuation/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
continuation.o: $(RUBY_EXTCONF_H)
continuation.o: $(arch_hdrdir)/ruby/config.h
+continuation.o: $(hdrdir)/ruby/assert.h
+continuation.o: $(hdrdir)/ruby/backward.h
+continuation.o: $(hdrdir)/ruby/backward/2/assume.h
+continuation.o: $(hdrdir)/ruby/backward/2/attributes.h
+continuation.o: $(hdrdir)/ruby/backward/2/bool.h
+continuation.o: $(hdrdir)/ruby/backward/2/inttypes.h
+continuation.o: $(hdrdir)/ruby/backward/2/limits.h
+continuation.o: $(hdrdir)/ruby/backward/2/long_long.h
+continuation.o: $(hdrdir)/ruby/backward/2/stdalign.h
+continuation.o: $(hdrdir)/ruby/backward/2/stdarg.h
+continuation.o: $(hdrdir)/ruby/defines.h
+continuation.o: $(hdrdir)/ruby/intern.h
+continuation.o: $(hdrdir)/ruby/internal/abi.h
continuation.o: $(hdrdir)/ruby/internal/anyargs.h
continuation.o: $(hdrdir)/ruby/internal/arithmetic.h
continuation.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
continuation.o: $(hdrdir)/ruby/ruby.h
continuation.o: $(hdrdir)/ruby/st.h
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
index 0af5579ffc..4578de54e4 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -15,65 +15,156 @@
#include "ruby.h"
#include "vm_core.h"
+static enum {
+ IDLE,
+ SUSPENDED,
+ RUNNING
+} current_state = IDLE;
static int current_mode;
static VALUE me2counter = Qnil;
/*
+ * call-seq: Coverage.supported?(mode) -> true or false
+ *
+ * Returns true if coverage measurement is supported for the given mode.
+ *
+ * The mode should be one of the following symbols:
+ * +:lines+, +:branches+, +:methods+, +:eval+.
+ *
+ * Example:
+ *
+ * Coverage.supported?(:lines) #=> true
+ * Coverage.supported?(:all) #=> false
+ */
+static VALUE
+rb_coverage_supported(VALUE self, VALUE _mode)
+{
+ ID mode = RB_SYM2ID(_mode);
+
+ return RBOOL(
+ mode == rb_intern("lines") ||
+ mode == rb_intern("branches") ||
+ mode == rb_intern("methods") ||
+ mode == rb_intern("eval")
+ );
+}
+
+/*
* call-seq:
- * Coverage.start => nil
+ * Coverage.setup => nil
+ * Coverage.setup(:all) => nil
+ * Coverage.setup(lines: bool, branches: bool, methods: bool, eval: bool) => nil
+ * Coverage.setup(oneshot_lines: true) => nil
+ *
+ * Set up the coverage measurement.
+ *
+ * Note that this method does not start the measurement itself.
+ * Use Coverage.resume to start the measurement.
*
- * Enables coverage measurement.
+ * You may want to use Coverage.start to setup and then start the measurement.
*/
static VALUE
-rb_coverage_start(int argc, VALUE *argv, VALUE klass)
+rb_coverage_setup(int argc, VALUE *argv, VALUE klass)
{
VALUE coverages, opt;
int mode;
+ if (current_state != IDLE) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is already setup");
+ }
+
rb_scan_args(argc, argv, "01", &opt);
if (argc == 0) {
- mode = 0; /* compatible mode */
+ mode = 0; /* compatible mode */
}
else if (opt == ID2SYM(rb_intern("all"))) {
- mode = COVERAGE_TARGET_LINES | COVERAGE_TARGET_BRANCHES | COVERAGE_TARGET_METHODS;
+ mode = COVERAGE_TARGET_LINES | COVERAGE_TARGET_BRANCHES | COVERAGE_TARGET_METHODS | COVERAGE_TARGET_EVAL;
}
else {
- mode = 0;
- opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash");
-
- if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("lines")))))
- mode |= COVERAGE_TARGET_LINES;
- if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("branches")))))
- mode |= COVERAGE_TARGET_BRANCHES;
- if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("methods")))))
- mode |= COVERAGE_TARGET_METHODS;
+ mode = 0;
+ opt = rb_convert_type(opt, T_HASH, "Hash", "to_hash");
+
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("lines")))))
+ mode |= COVERAGE_TARGET_LINES;
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("branches")))))
+ mode |= COVERAGE_TARGET_BRANCHES;
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("methods")))))
+ mode |= COVERAGE_TARGET_METHODS;
if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("oneshot_lines"))))) {
if (mode & COVERAGE_TARGET_LINES)
rb_raise(rb_eRuntimeError, "cannot enable lines and oneshot_lines simultaneously");
mode |= COVERAGE_TARGET_LINES;
mode |= COVERAGE_TARGET_ONESHOT_LINES;
}
+ if (RTEST(rb_hash_lookup(opt, ID2SYM(rb_intern("eval")))))
+ mode |= COVERAGE_TARGET_EVAL;
}
if (mode & COVERAGE_TARGET_METHODS) {
me2counter = rb_ident_hash_new();
}
else {
- me2counter = Qnil;
+ me2counter = Qnil;
}
coverages = rb_get_coverages();
if (!RTEST(coverages)) {
- coverages = rb_hash_new();
- rb_obj_hide(coverages);
- current_mode = mode;
- if (mode == 0) mode = COVERAGE_TARGET_LINES;
- rb_set_coverages(coverages, mode, me2counter);
+ coverages = rb_hash_new();
+ rb_obj_hide(coverages);
+ current_mode = mode;
+ if (mode == 0) mode = COVERAGE_TARGET_LINES;
+ rb_set_coverages(coverages, mode, me2counter);
+ current_state = SUSPENDED;
}
else if (current_mode != mode) {
- rb_raise(rb_eRuntimeError, "cannot change the measuring target during coverage measurement");
+ rb_raise(rb_eRuntimeError, "cannot change the measuring target during coverage measurement");
}
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Coverage.resume => nil
+ *
+ * Start/resume the coverage measurement.
+ *
+ * Caveat: Currently, only process-global coverage measurement is supported.
+ * You cannot measure per-thread coverage. If your process has multiple thread,
+ * using Coverage.resume/suspend to capture code coverage executed from only
+ * a limited code block, may yield misleading results.
+ */
+VALUE
+rb_coverage_resume(VALUE klass)
+{
+ if (current_state == IDLE) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not set up yet");
+ }
+ if (current_state == RUNNING) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is already running");
+ }
+ rb_resume_coverages();
+ current_state = RUNNING;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Coverage.start => nil
+ * Coverage.start(:all) => nil
+ * Coverage.start(lines: bool, branches: bool, methods: bool, eval: bool) => nil
+ * Coverage.start(oneshot_lines: true) => nil
+ *
+ * Enables the coverage measurement.
+ * See the documentation of Coverage class in detail.
+ * This is equivalent to Coverage.setup and Coverage.resume.
+ */
+static VALUE
+rb_coverage_start(int argc, VALUE *argv, VALUE klass)
+{
+ rb_coverage_setup(argc, argv, klass);
+ rb_coverage_resume(klass);
return Qnil;
}
@@ -154,45 +245,45 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
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;
- VALUE data[5], ncoverage, methods;
- VALUE methods_id = ID2SYM(rb_intern("methods"));
- VALUE klass;
- const rb_method_entry_t *me2 = rb_resolve_me_location(me, data);
- if (me != me2) continue;
- klass = me->owner;
- if (RB_TYPE_P(klass, T_ICLASS)) {
- rb_bug("T_ICLASS");
- }
- path = data[0];
- first_lineno = data[1];
- first_column = data[2];
- last_lineno = data[3];
- last_column = data[4];
- if (FIX2LONG(first_lineno) <= 0) continue;
- ncoverage = rb_hash_aref(ncoverages, path);
- if (NIL_P(ncoverage)) continue;
- methods = rb_hash_aref(ncoverage, methods_id);
-
- {
- VALUE method_id = ID2SYM(me->def->original_id);
- VALUE rcount = rb_hash_aref(me2counter, (VALUE) me);
- VALUE key = rb_ary_new_from_args(6, klass, method_id, first_lineno, first_column, last_lineno, last_column);
- VALUE rcount2 = rb_hash_aref(methods, key);
-
- if (NIL_P(rcount)) rcount = LONG2FIX(0);
- if (NIL_P(rcount2)) rcount2 = LONG2FIX(0);
- if (!POSFIXABLE(FIX2LONG(rcount) + FIX2LONG(rcount2))) {
- rcount = LONG2FIX(FIXNUM_MAX);
- }
- else {
- rcount = LONG2FIX(FIX2LONG(rcount) + FIX2LONG(rcount2));
- }
- rb_hash_aset(methods, key, rcount);
- }
- }
+ 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;
+ VALUE data[5], ncoverage, methods;
+ VALUE methods_id = ID2SYM(rb_intern("methods"));
+ VALUE klass;
+ const rb_method_entry_t *me2 = rb_resolve_me_location(me, data);
+ if (me != me2) continue;
+ klass = me->owner;
+ if (RB_TYPE_P(klass, T_ICLASS)) {
+ rb_bug("T_ICLASS");
+ }
+ path = data[0];
+ first_lineno = data[1];
+ first_column = data[2];
+ last_lineno = data[3];
+ last_column = data[4];
+ if (FIX2LONG(first_lineno) <= 0) continue;
+ ncoverage = rb_hash_aref(ncoverages, path);
+ if (NIL_P(ncoverage)) continue;
+ methods = rb_hash_aref(ncoverage, methods_id);
+
+ {
+ VALUE method_id = ID2SYM(me->def->original_id);
+ VALUE rcount = rb_hash_aref(me2counter, (VALUE) me);
+ VALUE key = rb_ary_new_from_args(6, klass, method_id, first_lineno, first_column, last_lineno, last_column);
+ VALUE rcount2 = rb_hash_aref(methods, key);
+
+ if (NIL_P(rcount)) rcount = LONG2FIX(0);
+ if (NIL_P(rcount2)) rcount2 = LONG2FIX(0);
+ if (!POSFIXABLE(FIX2LONG(rcount) + FIX2LONG(rcount2))) {
+ rcount = LONG2FIX(FIXNUM_MAX);
+ }
+ else {
+ rcount = LONG2FIX(FIX2LONG(rcount) + FIX2LONG(rcount2));
+ }
+ rb_hash_aset(methods, key, rcount);
+ }
+ }
if (poisoned) {
asan_poison_object(v);
@@ -208,32 +299,32 @@ coverage_peek_result_i(st_data_t key, st_data_t val, st_data_t h)
VALUE coverage = (VALUE)val;
VALUE coverages = (VALUE)h;
if (current_mode == 0) {
- /* compatible mode */
- VALUE lines = rb_ary_dup(RARRAY_AREF(coverage, COVERAGE_INDEX_LINES));
- rb_ary_freeze(lines);
- coverage = lines;
+ /* compatible mode */
+ VALUE lines = rb_ary_dup(RARRAY_AREF(coverage, COVERAGE_INDEX_LINES));
+ rb_ary_freeze(lines);
+ coverage = lines;
}
else {
- VALUE h = rb_hash_new();
+ VALUE h = rb_hash_new();
- if (current_mode & COVERAGE_TARGET_LINES) {
- VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
+ if (current_mode & COVERAGE_TARGET_LINES) {
+ VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
const char *kw = (current_mode & COVERAGE_TARGET_ONESHOT_LINES) ? "oneshot_lines" : "lines";
- lines = rb_ary_dup(lines);
- rb_ary_freeze(lines);
+ lines = rb_ary_dup(lines);
+ rb_ary_freeze(lines);
rb_hash_aset(h, ID2SYM(rb_intern(kw)), lines);
- }
+ }
- if (current_mode & COVERAGE_TARGET_BRANCHES) {
- VALUE branches = RARRAY_AREF(coverage, COVERAGE_INDEX_BRANCHES);
- rb_hash_aset(h, ID2SYM(rb_intern("branches")), branch_coverage(branches));
- }
+ if (current_mode & COVERAGE_TARGET_BRANCHES) {
+ VALUE branches = RARRAY_AREF(coverage, COVERAGE_INDEX_BRANCHES);
+ rb_hash_aset(h, ID2SYM(rb_intern("branches")), branch_coverage(branches));
+ }
- if (current_mode & COVERAGE_TARGET_METHODS) {
- rb_hash_aset(h, ID2SYM(rb_intern("methods")), rb_hash_new());
- }
+ if (current_mode & COVERAGE_TARGET_METHODS) {
+ rb_hash_aset(h, ID2SYM(rb_intern("methods")), rb_hash_new());
+ }
- coverage = h;
+ coverage = h;
}
rb_hash_aset(coverages, path, coverage);
@@ -258,13 +349,13 @@ rb_coverage_peek_result(VALUE klass)
VALUE coverages = rb_get_coverages();
VALUE ncoverages = rb_hash_new();
if (!RTEST(coverages)) {
- rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
+ rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
}
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);
+ rb_objspace_each_objects(method_coverage_i, &ncoverages);
}
rb_hash_freeze(ncoverages);
@@ -280,6 +371,24 @@ clear_me2counter_i(VALUE key, VALUE value, VALUE unused)
}
/*
+ * call-seq:
+ * Coverage.suspend => nil
+ *
+ * Suspend the coverage measurement.
+ * You can use Coverage.resume to restart the measurement.
+ */
+VALUE
+rb_coverage_suspend(VALUE klass)
+{
+ if (current_state != RUNNING) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not running");
+ }
+ rb_suspend_coverages();
+ current_state = SUSPENDED;
+ return Qnil;
+}
+
+/*
* call-seq:
* Coverage.result(stop: true, clear: true) => hash
*
@@ -294,6 +403,10 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass)
VALUE opt;
int stop = 1, clear = 1;
+ if (current_state == IDLE) {
+ rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
+ }
+
rb_scan_args(argc, argv, "01", &opt);
if (argc == 1) {
@@ -312,8 +425,12 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass)
if (!NIL_P(me2counter)) rb_hash_foreach(me2counter, clear_me2counter_i, Qnil);
}
if (stop) {
+ if (current_state == RUNNING) {
+ rb_coverage_suspend(klass);
+ }
rb_reset_coverages();
me2counter = Qnil;
+ current_state = IDLE;
}
return ncoverages;
}
@@ -321,6 +438,23 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
+ * Coverage.state => :idle, :suspended, :running
+ *
+ * Returns the state of the coverage measurement.
+ */
+static VALUE
+rb_coverage_state(VALUE klass)
+{
+ switch (current_state) {
+ case IDLE: return ID2SYM(rb_intern("idle"));
+ case SUSPENDED: return ID2SYM(rb_intern("suspended"));
+ case RUNNING: return ID2SYM(rb_intern("running"));
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
* Coverage.running? => bool
*
* Returns true if coverage stats are currently being collected (after
@@ -329,13 +463,15 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass)
static VALUE
rb_coverage_running(VALUE klass)
{
- VALUE coverages = rb_get_coverages();
- return RTEST(coverages) ? Qtrue : Qfalse;
+ return current_state == RUNNING ? Qtrue : Qfalse;
}
/* Coverage provides coverage measurement feature for Ruby.
* This feature is experimental, so these APIs may be changed in future.
*
+ * Caveat: Currently, only process-global coverage measurement is supported.
+ * You cannot measure per-thread coverage.
+ *
* = Usage
*
* 1. require "coverage"
@@ -480,9 +616,16 @@ void
Init_coverage(void)
{
VALUE rb_mCoverage = rb_define_module("Coverage");
+
+ rb_define_singleton_method(rb_mCoverage, "supported?", rb_coverage_supported, 1);
+
+ rb_define_module_function(rb_mCoverage, "setup", rb_coverage_setup, -1);
rb_define_module_function(rb_mCoverage, "start", rb_coverage_start, -1);
+ rb_define_module_function(rb_mCoverage, "resume", rb_coverage_resume, 0);
+ rb_define_module_function(rb_mCoverage, "suspend", rb_coverage_suspend, 0);
rb_define_module_function(rb_mCoverage, "result", rb_coverage_result, -1);
rb_define_module_function(rb_mCoverage, "peek_result", rb_coverage_peek_result, 0);
+ rb_define_module_function(rb_mCoverage, "state", rb_coverage_state, 0);
rb_define_module_function(rb_mCoverage, "running?", rb_coverage_running, 0);
rb_global_variable(&me2counter);
}
diff --git a/ext/coverage/depend b/ext/coverage/depend
index 0beb2a2347..e7fab16484 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -16,6 +16,7 @@ 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/abi.h
coverage.o: $(hdrdir)/ruby/internal/anyargs.h
coverage.o: $(hdrdir)/ruby/internal/arithmetic.h
coverage.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -164,9 +165,12 @@ coverage.o: $(top_srcdir)/ccan/check_type/check_type.h
coverage.o: $(top_srcdir)/ccan/container_of/container_of.h
coverage.o: $(top_srcdir)/ccan/list/list.h
coverage.o: $(top_srcdir)/ccan/str/str.h
+coverage.o: $(top_srcdir)/constant.h
coverage.o: $(top_srcdir)/gc.h
+coverage.o: $(top_srcdir)/id_table.h
coverage.o: $(top_srcdir)/internal.h
coverage.o: $(top_srcdir)/internal/array.h
+coverage.o: $(top_srcdir)/internal/basic_operators.h
coverage.o: $(top_srcdir)/internal/compilers.h
coverage.o: $(top_srcdir)/internal/gc.h
coverage.o: $(top_srcdir)/internal/hash.h
@@ -175,12 +179,14 @@ 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/variable.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
coverage.o: $(top_srcdir)/ruby_atomic.h
+coverage.o: $(top_srcdir)/shape.h
coverage.o: $(top_srcdir)/thread_pthread.h
coverage.o: $(top_srcdir)/vm_core.h
coverage.o: $(top_srcdir)/vm_opts.h
diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec
index 6b775d6f7e..660353ebc5 100644
--- a/ext/date/date.gemspec
+++ b/ext/date/date.gemspec
@@ -1,18 +1,31 @@
# frozen_string_literal: true
+
+version = File.foreach(File.expand_path("../lib/date.rb", __FILE__)).find do |line|
+ /^\s*VERSION\s*=\s*["'](.*)["']/ =~ line and break $1
+end
+
Gem::Specification.new do |s|
s.name = "date"
- s.version = '3.1.1'
+ s.version = version
s.summary = "A subclass of Object includes Comparable module for handling dates."
s.description = "A subclass of Object includes Comparable module for handling dates."
- s.require_path = %w{lib}
- s.files = [
- "lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c",
- "ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk",
- "ext/date/zonetab.h", "ext/date/zonetab.list"
- ]
- s.extensions = "ext/date/extconf.rb"
- s.required_ruby_version = ">= 2.4.0"
+ if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby'
+ s.platform = 'java'
+ # No files shipped, no require path, no-op for now on JRuby
+ else
+ s.require_path = %w{lib}
+
+ s.files = [
+ "README.md",
+ "lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c",
+ "ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk",
+ "ext/date/zonetab.h", "ext/date/zonetab.list"
+ ]
+ s.extensions = "ext/date/extconf.rb"
+ end
+
+ s.required_ruby_version = ">= 2.6.0"
s.authors = ["Tadayoshi Funaba"]
s.email = [nil]
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index f1017d22e9..21367c0ddf 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -27,6 +27,10 @@ static VALUE eDateError;
static VALUE half_days_in_day, day_in_nanoseconds;
static double positive_inf, negative_inf;
+// used by deconstruct_keys
+static VALUE sym_year, sym_month, sym_day, sym_yday, sym_wday;
+static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone;
+
#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
#define f_abs(x) rb_funcall(x, rb_intern("abs"), 0)
@@ -60,7 +64,8 @@ static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
#define RETURN_FALSE_UNLESS_NUMERIC(obj) if(!RTEST(rb_obj_is_kind_of((obj), rb_cNumeric))) return Qfalse
inline static void
-check_numeric(VALUE obj, const char* field) {
+check_numeric(VALUE obj, const char* field)
+{
if(!RTEST(rb_obj_is_kind_of(obj, rb_cNumeric))) {
rb_raise(rb_eTypeError, "invalid %s (not numeric)", field);
}
@@ -465,6 +470,7 @@ c_find_ldoy(int y, double sg, int *rjd, int *ns)
}
#ifndef NDEBUG
+/* :nodoc: */
static int
c_find_fdom(int y, int m, double sg, int *rjd, int *ns)
{
@@ -621,6 +627,7 @@ c_jd_to_weeknum(int jd, int f, double sg, int *ry, int *rw, int *rd)
}
#ifndef NDEBUG
+/* :nodoc: */
static void
c_nth_kday_to_jd(int y, int m, int n, int k, double sg, int *rjd, int *ns)
{
@@ -646,6 +653,7 @@ c_jd_to_wday(int jd)
}
#ifndef NDEBUG
+/* :nodoc: */
static void
c_jd_to_nth_kday(int jd, double sg, int *ry, int *rm, int *rn, int *rk)
{
@@ -758,6 +766,8 @@ c_valid_civil_p(int y, int m, int d, double sg,
if (m < 0)
m += 13;
+ if (m < 1 || m > 12)
+ return 0;
if (d < 0) {
if (!c_find_ldom(y, m, sg, rjd, ns))
return 0;
@@ -822,6 +832,7 @@ c_valid_weeknum_p(int y, int w, int d, int f, double sg,
}
#ifndef NDEBUG
+/* :nodoc: */
static int
c_valid_nth_kday_p(int y, int m, int n, int k, double sg,
int *rm, int *rn, int *rk, int *rjd, int *ns)
@@ -963,6 +974,7 @@ ns_to_day(VALUE n)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
ms_to_sec(VALUE m)
{
@@ -981,6 +993,7 @@ ns_to_sec(VALUE n)
}
#ifndef NDEBUG
+/* :nodoc: */
inline static VALUE
ins_to_day(int n)
{
@@ -1016,6 +1029,7 @@ day_to_sec(VALUE d)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
day_to_ns(VALUE d)
{
@@ -1040,6 +1054,7 @@ sec_to_ns(VALUE s)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
isec_to_ns(int s)
{
@@ -1066,6 +1081,7 @@ div_df(VALUE d, VALUE *f)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
div_sf(VALUE s, VALUE *f)
{
@@ -1500,6 +1516,7 @@ m_df(union DateData *x)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
m_df_in_day(union DateData *x)
{
@@ -1997,6 +2014,7 @@ expect_numeric(VALUE x)
}
#ifndef NDEBUG
+/* :nodoc: */
static void
civil_to_jd(VALUE y, int m, int d, double sg,
VALUE *nth, int *ry,
@@ -2309,6 +2327,7 @@ valid_weeknum_p(VALUE y, int w, int d, int f, double sg,
}
#ifndef NDEBUG
+/* :nodoc: */
static int
valid_nth_kday_p(VALUE y, int m, int n, int k, double sg,
VALUE *nth, int *ry,
@@ -2446,6 +2465,7 @@ valid_jd_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2466,13 +2486,16 @@ date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.valid_jd?(jd[, start=Date::ITALY]) -> bool
+ * Date.valid_jd?(jd, start = Date::ITALY) -> true
+ *
+ * Implemented for compatibility;
+ * returns +true+ unless +jd+ is invalid (i.e., not a Numeric).
*
- * Just returns true. It's nonsense, but is for symmetry.
+ * Date.valid_jd?(2451944) # => true
*
- * Date.valid_jd?(2451944) #=> true
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * See also ::jd.
+ * Related: Date.jd.
*/
static VALUE
date_s_valid_jd_p(int argc, VALUE *argv, VALUE klass)
@@ -2532,6 +2555,7 @@ valid_civil_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2554,18 +2578,20 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.valid_civil?(year, month, mday[, start=Date::ITALY]) -> bool
- * Date.valid_date?(year, month, mday[, start=Date::ITALY]) -> bool
+ * Date.valid_civil?(year, month, mday, start = Date::ITALY) -> true or false
+ *
+ * Returns +true+ if the arguments define a valid ordinal date,
+ * +false+ otherwise:
+ *
+ * Date.valid_date?(2001, 2, 3) # => true
+ * Date.valid_date?(2001, 2, 29) # => false
+ * Date.valid_date?(2001, 2, -1) # => true
*
- * Returns true if the given calendar date is valid, and false if not.
- * Valid in this context is whether the arguments passed to this
- * method would be accepted by ::new.
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * Date.valid_date?(2001,2,3) #=> true
- * Date.valid_date?(2001,2,29) #=> false
- * Date.valid_date?(2001,2,-1) #=> true
+ * Date.valid_date? is an alias for Date.valid_civil?.
*
- * See also ::jd and ::civil.
+ * Related: Date.jd, Date.new.
*/
static VALUE
date_s_valid_civil_p(int argc, VALUE *argv, VALUE klass)
@@ -2621,6 +2647,7 @@ valid_ordinal_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2642,14 +2669,17 @@ date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.valid_ordinal?(year, yday[, start=Date::ITALY]) -> bool
+ * Date.valid_ordinal?(year, yday, start = Date::ITALY) -> true or false
+ *
+ * Returns +true+ if the arguments define a valid ordinal date,
+ * +false+ otherwise:
*
- * Returns true if the given ordinal date is valid, and false if not.
+ * Date.valid_ordinal?(2001, 34) # => true
+ * Date.valid_ordinal?(2001, 366) # => false
*
- * Date.valid_ordinal?(2001,34) #=> true
- * Date.valid_ordinal?(2001,366) #=> false
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * See also ::jd and ::ordinal.
+ * Related: Date.jd, Date.ordinal.
*/
static VALUE
date_s_valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
@@ -2704,6 +2734,7 @@ valid_commercial_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2726,14 +2757,19 @@ date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.valid_commercial?(cwyear, cweek, cwday[, start=Date::ITALY]) -> bool
+ * Date.valid_commercial?(cwyear, cweek, cwday, start = Date::ITALY) -> true or false
*
- * Returns true if the given week date is valid, and false if not.
+ * Returns +true+ if the arguments define a valid commercial date,
+ * +false+ otherwise:
*
- * Date.valid_commercial?(2001,5,6) #=> true
- * Date.valid_commercial?(2001,5,8) #=> false
+ * Date.valid_commercial?(2001, 5, 6) # => true
+ * Date.valid_commercial?(2001, 5, 8) # => false
*
- * See also ::jd and ::commercial.
+ * See Date.commercial.
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.commercial.
*/
static VALUE
date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
@@ -2760,6 +2796,7 @@ date_s_valid_commercial_p(int argc, VALUE *argv, VALUE klass)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
{
@@ -2791,6 +2828,7 @@ valid_weeknum_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
}
}
+/* :nodoc: */
static VALUE
date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2811,6 +2849,7 @@ date_s__valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
return valid_weeknum_sub(5, argv2, klass, 1);
}
+/* :nodoc: */
static VALUE
date_s_valid_weeknum_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2862,6 +2901,7 @@ valid_nth_kday_sub(int argc, VALUE *argv, VALUE klass, int need_jd)
}
}
+/* :nodoc: */
static VALUE
date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2882,6 +2922,7 @@ date_s__valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
return valid_nth_kday_sub(5, argv2, klass, 1);
}
+/* :nodoc: */
static VALUE
date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
{
@@ -2904,6 +2945,7 @@ date_s_valid_nth_kday_p(int argc, VALUE *argv, VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static VALUE
date_s_zone_to_diff(VALUE klass, VALUE str)
{
@@ -2913,13 +2955,15 @@ date_s_zone_to_diff(VALUE klass, VALUE str)
/*
* call-seq:
- * Date.julian_leap?(year) -> bool
+ * Date.julian_leap?(year) -> true or false
+ *
+ * Returns +true+ if the given year is a leap year
+ * in the {proleptic Julian calendar}[https://en.wikipedia.org/wiki/Proleptic_Julian_calendar], +false+ otherwise:
*
- * Returns true if the given year is a leap year of the proleptic
- * Julian calendar.
+ * Date.julian_leap?(1900) # => true
+ * Date.julian_leap?(1901) # => false
*
- * Date.julian_leap?(1900) #=> true
- * Date.julian_leap?(1901) #=> false
+ * Related: Date.gregorian_leap?.
*/
static VALUE
date_s_julian_leap_p(VALUE klass, VALUE y)
@@ -2934,14 +2978,17 @@ date_s_julian_leap_p(VALUE klass, VALUE y)
/*
* call-seq:
- * Date.gregorian_leap?(year) -> bool
- * Date.leap?(year) -> bool
+ * Date.gregorian_leap?(year) -> true or false
*
- * Returns true if the given year is a leap year of the proleptic
- * Gregorian calendar.
+ * Returns +true+ if the given year is a leap year
+ * in the {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar], +false+ otherwise:
*
- * Date.gregorian_leap?(1900) #=> false
- * Date.gregorian_leap?(2000) #=> true
+ * Date.gregorian_leap?(2000) # => true
+ * Date.gregorian_leap?(2001) # => false
+ *
+ * Date.leap? is an alias for Date.gregorian_leap?.
+ *
+ * Related: Date.julian_leap?.
*/
static VALUE
date_s_gregorian_leap_p(VALUE klass, VALUE y)
@@ -3094,6 +3141,7 @@ old_to_new(VALUE ajd, VALUE of, VALUE sg,
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
date_s_new_bang(int argc, VALUE *argv, VALUE klass)
{
@@ -3281,16 +3329,29 @@ static VALUE d_lite_plus(VALUE, VALUE);
/*
* call-seq:
- * Date.jd([jd=0[, start=Date::ITALY]]) -> date
+ * Date.jd(jd = 0, start = Date::ITALY) -> date
*
- * Creates a date object denoting the given chronological Julian day
- * number.
+ * Returns a new \Date object formed from the arguments:
*
- * Date.jd(2451944) #=> #<Date: 2001-02-03 ...>
- * Date.jd(2451945) #=> #<Date: 2001-02-04 ...>
- * Date.jd(0) #=> #<Date: -4712-01-01 ...>
+ * Date.jd(2451944).to_s # => "2001-02-03"
+ * Date.jd(2451945).to_s # => "2001-02-04"
+ * Date.jd(0).to_s # => "-4712-01-01"
*
- * See also ::new.
+ * The returned date is:
+ *
+ * - Gregorian, if the argument is greater than or equal to +start+:
+ *
+ * Date::ITALY # => 2299161
+ * Date.jd(Date::ITALY).gregorian? # => true
+ * Date.jd(Date::ITALY + 1).gregorian? # => true
+ *
+ * - Julian, otherwise
+ *
+ * Date.jd(Date::ITALY - 1).julian? # => true
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * Related: Date.new.
*/
static VALUE
date_s_jd(int argc, VALUE *argv, VALUE klass)
@@ -3329,19 +3390,33 @@ date_s_jd(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.ordinal([year=-4712[, yday=1[, start=Date::ITALY]]]) -> date
+ * Date.ordinal(year = -4712, yday = 1, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object formed fom the arguments.
+ *
+ * With no arguments, returns the date for January 1, -4712:
+ *
+ * Date.ordinal.to_s # => "-4712-01-01"
+ *
+ * With argument +year+, returns the date for January 1 of that year:
+ *
+ * Date.ordinal(2001).to_s # => "2001-01-01"
+ * Date.ordinal(-2001).to_s # => "-2001-01-01"
+ *
+ * With positive argument +yday+ == +n+,
+ * returns the date for the +nth+ day of the given year:
*
- * Creates a date object denoting the given ordinal date.
+ * Date.ordinal(2001, 14).to_s # => "2001-01-14"
*
- * The day of year should be a negative or a positive number (as a
- * relative day from the end of year when negative). It should not be
- * zero.
+ * With negative argument +yday+, counts backward from the end of the year:
*
- * Date.ordinal(2001) #=> #<Date: 2001-01-01 ...>
- * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...>
- * Date.ordinal(2001,-1) #=> #<Date: 2001-12-31 ...>
+ * Date.ordinal(2001, -14).to_s # => "2001-12-18"
*
- * See also ::jd and ::new.
+ * Raises an exception if +yday+ is zero or out of range.
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.new.
*/
static VALUE
date_s_ordinal(int argc, VALUE *argv, VALUE klass)
@@ -3389,29 +3464,7 @@ date_s_ordinal(int argc, VALUE *argv, VALUE klass)
}
/*
- * call-seq:
- * Date.civil([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date
- * Date.new([year=-4712[, month=1[, mday=1[, start=Date::ITALY]]]]) -> date
- *
- * Creates a date object denoting the given calendar date.
- *
- * In this class, BCE years are counted astronomically. Thus, the
- * year before the year 1 is the year zero, and the year preceding the
- * year zero is the year -1. The month and the day of month should be
- * a negative or a positive number (as a relative month/day from the
- * end of year/month when negative). They should not be zero.
- *
- * The last argument should be a Julian day number which denotes the
- * day of calendar reform. Date::ITALY (2299161=1582-10-15),
- * Date::ENGLAND (2361222=1752-09-14), Date::GREGORIAN (the proleptic
- * Gregorian calendar) and Date::JULIAN (the proleptic Julian
- * calendar) can be specified as a day of calendar reform.
- *
- * Date.new(2001) #=> #<Date: 2001-01-01 ...>
- * Date.new(2001,2,3) #=> #<Date: 2001-02-03 ...>
- * Date.new(2001,2,-1) #=> #<Date: 2001-02-28 ...>
- *
- * See also ::jd.
+ * Same as Date.new.
*/
static VALUE
date_s_civil(int argc, VALUE *argv, VALUE klass)
@@ -3419,6 +3472,31 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
return date_initialize(argc, argv, d_lite_s_alloc_simple(klass));
}
+/*
+ * call-seq:
+ * Date.new(year = -4712, month = 1, mday = 1, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object constructed from the given arguments:
+ *
+ * Date.new(2022).to_s # => "2022-01-01"
+ * Date.new(2022, 2).to_s # => "2022-02-01"
+ * Date.new(2022, 2, 4).to_s # => "2022-02-04"
+ *
+ * Argument +month+ should be in range (1..12) or range (-12..-1);
+ * when the argument is negative, counts backward from the end of the year:
+ *
+ * Date.new(2022, -11, 4).to_s # => "2022-02-04"
+ *
+ * Argument +mday+ should be in range (1..n) or range (-n..-1)
+ * where +n+ is the number of days in the month;
+ * when the argument is negative, counts backward from the end of the month.
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * Date.civil is an alias for Date.new.
+ *
+ * Related: Date.jd.
+ */
static VALUE
date_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -3483,19 +3561,47 @@ date_initialize(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * Date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) -> date
+ * Date.commercial(cwyear = -4712, cweek = 1, cwday = 1, start = Date::ITALY) -> date
+ *
+ * Returns a new \Date object constructed from the arguments.
+ *
+ * Argument +cwyear+ gives the year, and should be an integer.
+ *
+ * Argument +cweek+ gives the index of the week within the year,
+ * and should be in range (1..53) or (-53..-1);
+ * in some years, 53 or -53 will be out-of-range;
+ * if negative, counts backward from the end of the year:
+ *
+ * Date.commercial(2022, 1, 1).to_s # => "2022-01-03"
+ * Date.commercial(2022, 52, 1).to_s # => "2022-12-26"
+ *
+ * Argument +cwday+ gives the indes of the weekday within the week,
+ * and should be in range (1..7) or (-7..-1);
+ * 1 or -7 is Monday;
+ * if negative, counts backward from the end of the week:
*
- * Creates a date object denoting the given week date.
+ * Date.commercial(2022, 1, 1).to_s # => "2022-01-03"
+ * Date.commercial(2022, 1, -7).to_s # => "2022-01-03"
*
- * The week and the day of week should be a negative or a positive
- * number (as a relative week/day from the end of year/week when
- * negative). They should not be zero.
+ * When +cweek+ is 1:
*
- * Date.commercial(2001) #=> #<Date: 2001-01-01 ...>
- * Date.commercial(2002) #=> #<Date: 2001-12-31 ...>
- * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...>
+ * - If January 1 is a Friday, Saturday, or Sunday,
+ * the first week begins in the week after:
*
- * See also ::jd and ::new.
+ * Date::ABBR_DAYNAMES[Date.new(2023, 1, 1).wday] # => "Sun"
+ * Date.commercial(2023, 1, 1).to_s # => "2023-01-02"
+ Date.commercial(2023, 1, 7).to_s # => "2023-01-08"
+ *
+ * - Otherwise, the first week is the week of January 1,
+ * which may mean some of the days fall on the year before:
+ *
+ * Date::ABBR_DAYNAMES[Date.new(2020, 1, 1).wday] # => "Wed"
+ * Date.commercial(2020, 1, 1).to_s # => "2019-12-30"
+ Date.commercial(2020, 1, 7).to_s # => "2020-01-05"
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * Related: Date.jd, Date.new, Date.ordinal.
*/
static VALUE
date_s_commercial(int argc, VALUE *argv, VALUE klass)
@@ -3547,6 +3653,7 @@ date_s_commercial(int argc, VALUE *argv, VALUE klass)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
date_s_weeknum(int argc, VALUE *argv, VALUE klass)
{
@@ -3596,6 +3703,7 @@ date_s_weeknum(int argc, VALUE *argv, VALUE klass)
return ret;
}
+/* :nodoc: */
static VALUE
date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
{
@@ -3670,11 +3778,14 @@ static void set_sg(union DateData *, double);
/*
* call-seq:
- * Date.today([start=Date::ITALY]) -> date
+ * Date.today(start = Date::ITALY) -> date
*
- * Creates a date object denoting the present day.
+ * Returns a new \Date object constructed from the present date:
+ *
+ * Date.today.to_s # => "2022-07-06"
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * Date.today #=> #<Date: 2011-06-11 ...>
*/
static VALUE
date_s_today(int argc, VALUE *argv, VALUE klass)
@@ -4265,16 +4376,20 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
/*
* call-seq:
- * Date._strptime(string[, format='%F']) -> hash
+ * Date._strptime(string, format = '%F') -> hash
*
- * Parses the given representation of date and time with the given
- * template, and returns a hash of parsed elements. _strptime does
- * not support specification of flags and width unlike strftime.
+ * Returns a hash of values parsed from +string+
+ * according to the given +format+:
*
- * Date._strptime('2001-02-03', '%Y-%m-%d')
- * #=> {:year=>2001, :mon=>2, :mday=>3}
+ * Date._strptime('2001-02-03', '%Y-%m-%d') # => {:year=>2001, :mon=>2, :mday=>3}
*
- * See also strptime(3) and #strftime.
+ * For other formats, see
+ * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc].
+ * (Unlike Date.strftime, does not support flags and width.)
+ *
+ * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html].
+ *
+ * Related: Date.strptime (returns a \Date object).
*/
static VALUE
date_s__strptime(int argc, VALUE *argv, VALUE klass)
@@ -4284,21 +4399,28 @@ date_s__strptime(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.strptime([string='-4712-01-01'[, format='%F'[, start=Date::ITALY]]]) -> date
+ * Date.strptime(string = '-4712-01-01', format = '%F', start = Date::ITALY) -> date
*
- * Parses the given representation of date and time with the given
- * template, and creates a date object. strptime does not support
- * specification of flags and width unlike strftime.
+ * Returns a new \Date object with values parsed from +string+,
+ * according to the given +format+:
*
- * Date.strptime('2001-02-03', '%Y-%m-%d') #=> #<Date: 2001-02-03 ...>
- * Date.strptime('03-02-2001', '%d-%m-%Y') #=> #<Date: 2001-02-03 ...>
- * Date.strptime('2001-034', '%Y-%j') #=> #<Date: 2001-02-03 ...>
- * Date.strptime('2001-W05-6', '%G-W%V-%u') #=> #<Date: 2001-02-03 ...>
- * Date.strptime('2001 04 6', '%Y %U %w') #=> #<Date: 2001-02-03 ...>
- * Date.strptime('2001 05 6', '%Y %W %u') #=> #<Date: 2001-02-03 ...>
- * Date.strptime('sat3feb01', '%a%d%b%y') #=> #<Date: 2001-02-03 ...>
+ * Date.strptime('2001-02-03', '%Y-%m-%d') # => #<Date: 2001-02-03>
+ * Date.strptime('03-02-2001', '%d-%m-%Y') # => #<Date: 2001-02-03>
+ * Date.strptime('2001-034', '%Y-%j') # => #<Date: 2001-02-03>
+ * Date.strptime('2001-W05-6', '%G-W%V-%u') # => #<Date: 2001-02-03>
+ * Date.strptime('2001 04 6', '%Y %U %w') # => #<Date: 2001-02-03>
+ * Date.strptime('2001 05 6', '%Y %W %u') # => #<Date: 2001-02-03>
+ * Date.strptime('sat3feb01', '%a%d%b%y') # => #<Date: 2001-02-03>
*
- * See also strptime(3) and #strftime.
+ * For other formats, see
+ * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc].
+ * (Unlike Date.strftime, does not support flags and width.)
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html].
+ *
+ * Related: Date._strptime (returns a hash).
*/
static VALUE
date_s_strptime(int argc, VALUE *argv, VALUE klass)
@@ -4328,12 +4450,49 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass)
VALUE date__parse(VALUE str, VALUE comp);
+static size_t
+get_limit(VALUE opt)
+{
+ if (!NIL_P(opt)) {
+ VALUE limit = rb_hash_aref(opt, ID2SYM(rb_intern("limit")));
+ if (NIL_P(limit)) return SIZE_MAX;
+ return NUM2SIZET(limit);
+ }
+ return 128;
+}
+
+#ifndef HAVE_RB_CATEGORY_WARN
+#define rb_category_warn(category, fmt) rb_warn(fmt)
+#endif
+
+static void
+check_limit(VALUE str, VALUE opt)
+{
+ size_t slen, limit;
+ if (NIL_P(str)) return;
+ if (SYMBOL_P(str)) {
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
+ "The ability to parse Symbol is an unintentional bug and is deprecated");
+ str = rb_sym2str(str);
+ }
+
+ StringValue(str);
+ slen = RSTRING_LEN(str);
+ limit = get_limit(opt);
+ if (slen > limit) {
+ rb_raise(rb_eArgError,
+ "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
+ }
+}
+
static VALUE
date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
{
- VALUE vstr, vcomp, hash;
+ VALUE vstr, vcomp, hash, opt;
- rb_scan_args(argc, argv, "11", &vstr, &vcomp);
+ rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
+ if (!NIL_P(opt)) argc--;
+ check_limit(vstr, opt);
StringValue(vstr);
if (!rb_enc_str_asciicompat_p(vstr))
rb_raise(rb_eArgError,
@@ -4348,21 +4507,32 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._parse(string[, comp=true]) -> hash
+ * Date._parse(string, comp = true, limit: 128) -> hash
*
- * Parses the given representation of date and time, and returns a
- * hash of parsed elements.
+ * <b>Note</b>:
+ * This method recognizes many forms in +string+,
+ * but it is not a validator.
+ * For formats, see
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
*
- * 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 +string+ does not specify a valid date,
+ * the result is unpredictable;
+ * consider using Date._strptime instead.
*
- * If the optional second argument is true and the detected year is in
- * the range "00" to "99", considers the year a 2-digit form and makes
- * it full.
+ * Returns a hash of values parsed from +string+:
+ *
+ * Date._parse('2001-02-03') # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * If +comp+ is +true+ and the given year is in the range <tt>(0..99)</tt>,
+ * the current century is supplied;
+ * otherwise, the year is taken as given:
+ *
+ * Date._parse('01-02-03', true) # => {:year=>2001, :mon=>2, :mday=>3}
+ * Date._parse('01-02-03', false) # => {:year=>1, :mon=>2, :mday=>3}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
*
- * Date._parse('2001-02-03') #=> {:year=>2001, :mon=>2, :mday=>3}
+ * Related: Date.parse(returns a \Date object).
*/
static VALUE
date_s__parse(int argc, VALUE *argv, VALUE klass)
@@ -4372,30 +4542,44 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]]) -> date
+ * Date.parse(string = '-4712-01-01', comp = true, start = Date::ITALY, limit: 128) -> date
*
- * Parses the given representation of date and time, and creates a
- * date object.
+ * <b>Note</b>:
+ * This method recognizes many forms in +string+,
+ * but it is not a validator.
+ * For formats, see
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
+ * If +string+ does not specify a valid date,
+ * the result is unpredictable;
+ * consider using Date._strptime instead.
*
- * 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.
+ * Returns a new \Date object with values parsed from +string+:
*
- * If the optional second argument is true and the detected year is in
- * the range "00" to "99", considers the year a 2-digit form and makes
- * it full.
+ * Date.parse('2001-02-03') # => #<Date: 2001-02-03>
+ * Date.parse('20010203') # => #<Date: 2001-02-03>
+ * Date.parse('3rd Feb 2001') # => #<Date: 2001-02-03>
+ *
+ * If +comp+ is +true+ and the given year is in the range <tt>(0..99)</tt>,
+ * the current century is supplied;
+ * otherwise, the year is taken as given:
+ *
+ * Date.parse('01-02-03', true) # => #<Date: 2001-02-03>
+ * Date.parse('01-02-03', false) # => #<Date: 0001-02-03>
*
- * Date.parse('2001-02-03') #=> #<Date: 2001-02-03 ...>
- * Date.parse('20010203') #=> #<Date: 2001-02-03 ...>
- * Date.parse('3rd Feb 2001') #=> #<Date: 2001-02-03 ...>
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._parse (returns a hash).
*/
static VALUE
date_s_parse(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, comp, sg;
+ VALUE str, comp, sg, opt;
- rb_scan_args(argc, argv, "03", &str, &comp, &sg);
+ rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -4407,11 +4591,12 @@ date_s_parse(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE argv2[2], hash;
-
- argv2[0] = str;
- argv2[1] = comp;
- hash = date_s__parse(2, argv2, klass);
+ int argc2 = 2;
+ VALUE argv2[3], hash;
+ argv2[0] = str;
+ argv2[1] = comp;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__parse(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
@@ -4425,33 +4610,56 @@ VALUE date__jisx0301(VALUE);
/*
* call-seq:
- * Date._iso8601(string) -> hash
+ * Date._iso8601(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should contain
+ * an {ISO 8601 formatted date}[rdoc-ref:strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
*
- * Returns a hash of parsed elements.
+ * d = Date.new(2001, 2, 3)
+ * s = d.iso8601 # => "2001-02-03"
+ * Date._iso8601(s) # => {:mday=>3, :year=>2001, :mon=>2}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.iso8601 (returns a \Date object).
*/
static VALUE
-date_s__iso8601(VALUE klass, VALUE str)
+date_s__iso8601(int argc, VALUE *argv, VALUE klass)
{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ check_limit(str, opt);
+
return date__iso8601(str);
}
/*
* call-seq:
- * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY]) -> date
+ * Date.iso8601(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
*
- * Creates a new Date object by parsing from a string according to
- * some typical ISO 8601 formats.
+ * Returns a new \Date object with values parsed from +string+,
+ * which should contain
+ * an {ISO 8601 formatted date}[rdoc-ref:strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.iso8601 # => "2001-02-03"
+ * Date.iso8601(s) # => #<Date: 2001-02-03>
*
- * Date.iso8601('2001-02-03') #=> #<Date: 2001-02-03 ...>
- * Date.iso8601('20010203') #=> #<Date: 2001-02-03 ...>
- * Date.iso8601('2001-W05-6') #=> #<Date: 2001-02-03 ...>
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._iso8601 (returns a hash).
*/
static VALUE
date_s_iso8601(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -4461,38 +4669,68 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__iso8601(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__iso8601(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * Date._rfc3339(string) -> hash
+ * Date._rfc3339(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {RFC 3339 format}[rdoc-ref:strftime_formatting.rdoc@RFC+3339+Format]:
*
- * Returns a hash of parsed elements.
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ * Date._rfc3339(s)
+ * # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.rfc3339 (returns a \Date object).
*/
static VALUE
-date_s__rfc3339(VALUE klass, VALUE str)
+date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ check_limit(str, opt);
+
return date__rfc3339(str);
}
/*
* call-seq:
- * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> date
+ * Date.rfc3339(string = '-4712-01-01T00:00:00+00:00', start = Date::ITALY, limit: 128) -> date
*
- * Creates a new Date object by parsing from a string according to
- * some typical RFC 3339 formats.
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid
+ * {RFC 3339 format}[rdoc-ref:strftime_formatting.rdoc@RFC+3339+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ * Date.rfc3339(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
- * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...>
+ * Related: Date._rfc3339 (returns a hash).
*/
static VALUE
date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -4502,38 +4740,66 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__rfc3339(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__rfc3339(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * Date._xmlschema(string) -> hash
+ * Date._xmlschema(string, limit: 128) -> hash
*
- * Returns a hash of parsed elements.
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * XML date format:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.xmlschema # => "2001-02-03"
+ * Date._xmlschema(s) # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.xmlschema (returns a \Date object).
*/
static VALUE
-date_s__xmlschema(VALUE klass, VALUE str)
+date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ check_limit(str, opt);
+
return date__xmlschema(str);
}
/*
* call-seq:
- * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY]) -> date
+ * Date.xmlschema(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
*
- * Creates a new Date object by parsing from a string according to
- * some typical XML Schema formats.
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid XML date format:
*
- * Date.xmlschema('2001-02-03') #=> #<Date: 2001-02-03 ...>
+ * d = Date.new(2001, 2, 3)
+ * s = d.xmlschema # => "2001-02-03"
+ * Date.xmlschema(s) # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._xmlschema (returns a hash).
*/
static VALUE
date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -4543,41 +4809,71 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__xmlschema(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__xmlschema(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * Date._rfc2822(string) -> hash
- * Date._rfc822(string) -> hash
+ * Date._rfc2822(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {RFC 2822 date format}[rdoc-ref:strftime_formatting.rdoc@RFC+2822+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ * Date._rfc2822(s)
+ * # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
*
- * Returns a hash of parsed elements.
+ * Date._rfc822 is an alias for Date._rfc2822.
+ *
+ * Related: Date.rfc2822 (returns a \Date object).
*/
static VALUE
-date_s__rfc2822(VALUE klass, VALUE str)
+date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ check_limit(str, opt);
+
return date__rfc2822(str);
}
/*
* call-seq:
- * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
- * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> date
+ * Date.rfc2822(string = 'Mon, 1 Jan -4712 00:00:00 +0000', start = Date::ITALY, limit: 128) -> date
*
- * Creates a new Date object by parsing from a string according to
- * some typical RFC 2822 formats.
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid
+ * {RFC 2822 date format}[rdoc-ref:strftime_formatting.rdoc@RFC+2822+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ * Date.rfc2822(s) # => #<Date: 2001-02-03>
+ *
+ * See:
*
- * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
- * #=> #<Date: 2001-02-03 ...>
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Date.rfc822 is an alias for Date.rfc2822.
+ *
+ * Related: Date._rfc2822 (returns a hash).
*/
static VALUE
date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
@@ -4587,39 +4883,65 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__rfc2822(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__rfc2822(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * Date._httpdate(string) -> hash
+ * Date._httpdate(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {HTTP date format}[rdoc-ref:strftime_formatting.rdoc@HTTP+Format]:
*
- * Returns a hash of parsed elements.
+ * d = Date.new(2001, 2, 3)
+ * s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ * Date._httpdate(s)
+ * # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}
+ *
+ * Related: Date.httpdate (returns a \Date object).
*/
static VALUE
-date_s__httpdate(VALUE klass, VALUE str)
+date_s__httpdate(int argc, VALUE *argv, VALUE klass)
{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ check_limit(str, opt);
+
return date__httpdate(str);
}
/*
* call-seq:
- * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) -> date
+ * Date.httpdate(string = 'Mon, 01 Jan -4712 00:00:00 GMT', start = Date::ITALY, limit: 128) -> date
*
- * Creates a new Date object by parsing from a string according to
- * some RFC 2616 format.
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid
+ * {HTTP date format}[rdoc-ref:strftime_formatting.rdoc@HTTP+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ Date.httpdate(s) # => #<Date: 2001-02-03>
+ *
+ * See:
*
- * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
- * #=> #<Date: 2001-02-03 ...>
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._httpdate (returns a hash).
*/
static VALUE
date_s_httpdate(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
@@ -4629,42 +4951,70 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__httpdate(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__httpdate(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * Date._jisx0301(string) -> hash
+ * Date._jisx0301(string, limit: 128) -> hash
+ *
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {JIS X 0301 date format}[rdoc-ref:strftime_formatting.rdoc@JIS+X+0301+Format]:
+ *
+ * d = Date.new(2001, 2, 3)
+ * s = d.jisx0301 # => "H13.02.03"
+ * Date._jisx0301(s) # => {:year=>2001, :mon=>2, :mday=>3}
*
- * Returns a hash of parsed elements.
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.jisx0301 (returns a \Date object).
*/
static VALUE
-date_s__jisx0301(VALUE klass, VALUE str)
+date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
{
+ VALUE str, opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ check_limit(str, opt);
+
return date__jisx0301(str);
}
/*
* call-seq:
- * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY]) -> date
+ * Date.jisx0301(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
*
- * Creates a new Date object by parsing from a string according to
- * some typical JIS X 0301 formats.
+ * Returns a new \Date object with values parsed from +string+,
+ * which should be a valid {JIS X 0301 format}[rdoc-ref:strftime_formatting.rdoc@JIS+X+0301+Format]:
*
- * Date.jisx0301('H13.02.03') #=> #<Date: 2001-02-03 ...>
+ * d = Date.new(2001, 2, 3)
+ * s = d.jisx0301 # => "H13.02.03"
+ * Date.jisx0301(s) # => #<Date: 2001-02-03>
*
* For no-era year, legacy format, Heisei is assumed.
*
- * Date.jisx0301('13.02.03') #=> #<Date: 2001-02-03 ...>
+ * Date.jisx0301('13.02.03') # => #<Date: 2001-02-03>
+ *
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._jisx0301 (returns a hash).
*/
static VALUE
date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -4674,7 +5024,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__jisx0301(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ if (!NIL_P(opt)) argv2[argc2++] = opt;
+ hash = date_s__jisx0301(argc2, argv2, klass);
return d_new_by_frags(klass, hash, sg);
}
}
@@ -4844,6 +5198,7 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
d_lite_fill(VALUE self)
{
@@ -4933,12 +5288,15 @@ d_lite_mjd(VALUE self)
/*
* call-seq:
- * d.ld -> integer
+ * ld -> integer
*
- * Returns the Lilian day number. This is a whole number, which is
- * adjusted by the offset as the local time.
+ * Returns the
+ * {Lilian day number}[https://en.wikipedia.org/wiki/Lilian_date],
+ * which is the number of days since the beginning of the Gregorian
+ * calendar, October 15, 1582.
+ *
+ * Date.new(2001, 2, 3).ld # => 152784
*
- * Date.new(2001,2,3).ld #=> 152784
*/
static VALUE
d_lite_ld(VALUE self)
@@ -4949,12 +5307,13 @@ d_lite_ld(VALUE self)
/*
* call-seq:
- * d.year -> integer
+ * year -> integer
+ *
+ * Returns the year:
*
- * Returns the year.
+ * Date.new(2001, 2, 3).year # => 2001
+ * (Date.new(1, 1, 1) - 1).year # => 0
*
- * Date.new(2001,2,3).year #=> 2001
- * (Date.new(1,1,1) - 1).year #=> 0
*/
static VALUE
d_lite_year(VALUE self)
@@ -4965,11 +5324,12 @@ d_lite_year(VALUE self)
/*
* call-seq:
- * d.yday -> fixnum
+ * yday -> integer
+ *
+ * Returns the day of the year, in range (1..366):
*
- * Returns the day of the year (1-366).
+ * Date.new(2001, 2, 3).yday # => 34
*
- * Date.new(2001,2,3).yday #=> 34
*/
static VALUE
d_lite_yday(VALUE self)
@@ -4980,12 +5340,13 @@ d_lite_yday(VALUE self)
/*
* call-seq:
- * d.mon -> fixnum
- * d.month -> fixnum
+ * mon -> integer
*
- * Returns the month (1-12).
+ * Returns the month in range (1..12):
*
- * Date.new(2001,2,3).mon #=> 2
+ * Date.new(2001, 2, 3).mon # => 2
+ *
+ * Date#month is an alias for Date#mon.
*/
static VALUE
d_lite_mon(VALUE self)
@@ -4996,12 +5357,13 @@ d_lite_mon(VALUE self)
/*
* call-seq:
- * d.mday -> fixnum
- * d.day -> fixnum
+ * mday -> integer
+ *
+ * Returns the day of the month in range (1..31):
*
- * Returns the day of the month (1-31).
+ * Date.new(2001, 2, 3).mday # => 3
*
- * Date.new(2001,2,3).mday #=> 3
+ * Date#day is an alias for Date#mday.
*/
static VALUE
d_lite_mday(VALUE self)
@@ -5012,11 +5374,12 @@ d_lite_mday(VALUE self)
/*
* call-seq:
- * d.day_fraction -> rational
+ * day_fraction -> rational
+ *
+ * Returns the fractional part of the day in range (Rational(0, 1)...Rational(1, 1)):
*
- * Returns the fractional part of the day.
+ * DateTime.new(2001,2,3,12).day_fraction # => (1/2)
*
- * DateTime.new(2001,2,3,12).day_fraction #=> (1/2)
*/
static VALUE
d_lite_day_fraction(VALUE self)
@@ -5029,12 +5392,14 @@ d_lite_day_fraction(VALUE self)
/*
* call-seq:
- * d.cwyear -> integer
+ * cwyear -> integer
*
- * Returns the calendar week based year.
+ * Returns commercial-date year for +self+
+ * (see Date.commercial):
+ *
+ * Date.new(2001, 2, 3).cwyear # => 2001
+ * Date.new(2000, 1, 1).cwyear # => 1999
*
- * Date.new(2001,2,3).cwyear #=> 2001
- * Date.new(2000,1,1).cwyear #=> 1999
*/
static VALUE
d_lite_cwyear(VALUE self)
@@ -5045,11 +5410,13 @@ d_lite_cwyear(VALUE self)
/*
* call-seq:
- * d.cweek -> fixnum
+ * cweek -> integer
+ *
+ * Returns commercial-date week index for +self+
+ * (see Date.commercial):
*
- * Returns the calendar week number (1-53).
+ * Date.new(2001, 2, 3).cweek # => 5
*
- * Date.new(2001,2,3).cweek #=> 5
*/
static VALUE
d_lite_cweek(VALUE self)
@@ -5060,11 +5427,14 @@ d_lite_cweek(VALUE self)
/*
* call-seq:
- * d.cwday -> fixnum
+ * cwday -> integer
*
- * Returns the day of calendar week (1-7, Monday is 1).
+ * Returns the commercial-date weekday index for +self+
+ * (see Date.commercial);
+ * 1 is Monday:
+ *
+ * Date.new(2001, 2, 3).cwday # => 6
*
- * Date.new(2001,2,3).cwday #=> 6
*/
static VALUE
d_lite_cwday(VALUE self)
@@ -5074,6 +5444,7 @@ d_lite_cwday(VALUE self)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
d_lite_wnum0(VALUE self)
{
@@ -5081,6 +5452,7 @@ d_lite_wnum0(VALUE self)
return INT2FIX(m_wnum0(dat));
}
+/* :nodoc: */
static VALUE
d_lite_wnum1(VALUE self)
{
@@ -5091,11 +5463,12 @@ d_lite_wnum1(VALUE self)
/*
* call-seq:
- * d.wday -> fixnum
+ * wday -> integer
*
- * Returns the day of week (0-6, Sunday is zero).
+ * Returns the day of week in range (0..6); Sunday is 0:
+ *
+ * Date.new(2001, 2, 3).wday # => 6
*
- * Date.new(2001,2,3).wday #=> 6
*/
static VALUE
d_lite_wday(VALUE self)
@@ -5106,9 +5479,9 @@ d_lite_wday(VALUE self)
/*
* call-seq:
- * d.sunday? -> bool
+ * sunday? -> true or false
*
- * Returns true if the date is Sunday.
+ * Returns +true+ if +self+ is a Sunday, +false+ otherwise.
*/
static VALUE
d_lite_sunday_p(VALUE self)
@@ -5119,9 +5492,9 @@ d_lite_sunday_p(VALUE self)
/*
* call-seq:
- * d.monday? -> bool
+ * monday? -> true or false
*
- * Returns true if the date is Monday.
+ * Returns +true+ if +self+ is a Monday, +false+ otherwise.
*/
static VALUE
d_lite_monday_p(VALUE self)
@@ -5132,9 +5505,9 @@ d_lite_monday_p(VALUE self)
/*
* call-seq:
- * d.tuesday? -> bool
+ * tuesday? -> true or false
*
- * Returns true if the date is Tuesday.
+ * Returns +true+ if +self+ is a Tuesday, +false+ otherwise.
*/
static VALUE
d_lite_tuesday_p(VALUE self)
@@ -5145,9 +5518,9 @@ d_lite_tuesday_p(VALUE self)
/*
* call-seq:
- * d.wednesday? -> bool
+ * wednesday? -> true or false
*
- * Returns true if the date is Wednesday.
+ * Returns +true+ if +self+ is a Wednesday, +false+ otherwise.
*/
static VALUE
d_lite_wednesday_p(VALUE self)
@@ -5158,9 +5531,9 @@ d_lite_wednesday_p(VALUE self)
/*
* call-seq:
- * d.thursday? -> bool
+ * thursday? -> true or false
*
- * Returns true if the date is Thursday.
+ * Returns +true+ if +self+ is a Thursday, +false+ otherwise.
*/
static VALUE
d_lite_thursday_p(VALUE self)
@@ -5171,9 +5544,9 @@ d_lite_thursday_p(VALUE self)
/*
* call-seq:
- * d.friday? -> bool
+ * friday? -> true or false
*
- * Returns true if the date is Friday.
+ * Returns +true+ if +self+ is a Friday, +false+ otherwise.
*/
static VALUE
d_lite_friday_p(VALUE self)
@@ -5184,9 +5557,9 @@ d_lite_friday_p(VALUE self)
/*
* call-seq:
- * d.saturday? -> bool
+ * saturday? -> true or false
*
- * Returns true if the date is Saturday.
+ * Returns +true+ if +self+ is a Saturday, +false+ otherwise.
*/
static VALUE
d_lite_saturday_p(VALUE self)
@@ -5196,6 +5569,7 @@ d_lite_saturday_p(VALUE self)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
{
@@ -5217,11 +5591,12 @@ d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
/*
* call-seq:
- * d.hour -> fixnum
+ * hour -> integer
+ *
+ * Returns the hour in range (0..23):
*
- * Returns the hour (0-23).
+ * DateTime.new(2001, 2, 3, 4, 5, 6).hour # => 4
*
- * DateTime.new(2001,2,3,4,5,6).hour #=> 4
*/
static VALUE
d_lite_hour(VALUE self)
@@ -5232,12 +5607,13 @@ d_lite_hour(VALUE self)
/*
* call-seq:
- * d.min -> fixnum
- * d.minute -> fixnum
+ * min -> integer
*
- * Returns the minute (0-59).
+ * Returns the minute in range (0..59):
*
- * DateTime.new(2001,2,3,4,5,6).min #=> 5
+ * DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5
+ *
+ * Date#minute is an alias for Date#min.
*/
static VALUE
d_lite_min(VALUE self)
@@ -5248,12 +5624,13 @@ d_lite_min(VALUE self)
/*
* call-seq:
- * d.sec -> fixnum
- * d.second -> fixnum
+ * sec -> integer
+ *
+ * Returns the second in range (0..59):
*
- * Returns the second (0-59).
+ * DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6
*
- * DateTime.new(2001,2,3,4,5,6).sec #=> 6
+ * Date#second is an alias for Date#sec.
*/
static VALUE
d_lite_sec(VALUE self)
@@ -5264,12 +5641,14 @@ d_lite_sec(VALUE self)
/*
* call-seq:
- * d.sec_fraction -> rational
- * d.second_fraction -> rational
+ * sec_fraction -> rational
+ *
+ * Returns the fractional part of the second in range
+ * (Rational(0, 1)...Rational(1, 1)):
*
- * Returns the fractional part of the second.
+ * DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2)
*
- * DateTime.new(2001,2,3,4,5,6.5).sec_fraction #=> (1/2)
+ * Date#second_fraction is an alias for Date#sec_fraction.
*/
static VALUE
d_lite_sec_fraction(VALUE self)
@@ -5310,12 +5689,14 @@ d_lite_zone(VALUE self)
/*
* call-seq:
- * d.julian? -> bool
+ * d.julian? -> true or false
*
- * Returns true if the date is before the day of calendar reform.
+ * Returns +true+ if the date is before the date of calendar reform,
+ * +false+ otherwise:
+ *
+ * (Date.new(1582, 10, 15) - 1).julian? # => true
+ * Date.new(1582, 10, 15).julian? # => false
*
- * Date.new(1582,10,15).julian? #=> false
- * (Date.new(1582,10,15) - 1).julian? #=> true
*/
static VALUE
d_lite_julian_p(VALUE self)
@@ -5326,12 +5707,14 @@ d_lite_julian_p(VALUE self)
/*
* call-seq:
- * d.gregorian? -> bool
+ * gregorian? -> true or false
+ *
+ * Returns +true+ if the date is on or after
+ * the date of calendar reform, +false+ otherwise:
*
- * Returns true if the date is on or after the day of calendar reform.
+ * Date.new(1582, 10, 15).gregorian? # => true
+ * (Date.new(1582, 10, 15) - 1).gregorian? # => false
*
- * Date.new(1582,10,15).gregorian? #=> true
- * (Date.new(1582,10,15) - 1).gregorian? #=> false
*/
static VALUE
d_lite_gregorian_p(VALUE self)
@@ -5342,12 +5725,13 @@ d_lite_gregorian_p(VALUE self)
/*
* call-seq:
- * d.leap? -> bool
+ * leap? -> true or false
+ *
+ * Returns +true+ if the year is a leap year, +false+ otherwise:
*
- * Returns true if the year is a leap year.
+ * Date.new(2000).leap? # => true
+ * Date.new(2001).leap? # => false
*
- * Date.new(2000).leap? #=> true
- * Date.new(2001).leap? #=> false
*/
static VALUE
d_lite_leap_p(VALUE self)
@@ -5366,12 +5750,25 @@ d_lite_leap_p(VALUE self)
/*
* call-seq:
- * d.start -> float
+ * start -> float
*
- * Returns the Julian day number denoting the day of calendar reform.
+ * Returns the Julian start date for calendar reform;
+ * if not an infinity, the returned value is suitable
+ * for passing to Date#jd:
+ *
+ * d = Date.new(2001, 2, 3, Date::ITALY)
+ * s = d.start # => 2299161.0
+ * Date.jd(s).to_s # => "1582-10-15"
+ *
+ * d = Date.new(2001, 2, 3, Date::ENGLAND)
+ * s = d.start # => 2361222.0
+ * Date.jd(s).to_s # => "1752-09-14"
+ *
+ * Date.new(2001, 2, 3, Date::GREGORIAN).start # => -Infinity
+ * Date.new(2001, 2, 3, Date::JULIAN).start # => Infinity
+ *
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * Date.new(2001,2,3).start #=> 2299161.0
- * Date.new(2001,2,3,Date::GREGORIAN).start #=> -Infinity
*/
static VALUE
d_lite_start(VALUE self)
@@ -5436,12 +5833,17 @@ dup_obj_with_new_start(VALUE obj, double sg)
/*
* call-seq:
- * d.new_start([start=Date::ITALY]) -> date
+ * new_start(start = Date::ITALY]) -> new_date
+ *
+ * Returns a copy of +self+ with the given +start+ value:
+ *
+ * d0 = Date.new(2000, 2, 3)
+ * d0.julian? # => false
+ * d1 = d0.new_start(Date::JULIAN)
+ * d1.julian? # => true
*
- * Duplicates self and resets its day of calendar reform.
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * d = Date.new(1582,10,15)
- * d.new_start(Date::JULIAN) #=> #<Date: 1582-10-05 ...>
*/
static VALUE
d_lite_new_start(int argc, VALUE *argv, VALUE self)
@@ -5460,9 +5862,10 @@ d_lite_new_start(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.italy -> date
+ * italy -> new_date
+ *
+ * Equivalent to Date#new_start with argument Date::ITALY.
*
- * This method is equivalent to new_start(Date::ITALY).
*/
static VALUE
d_lite_italy(VALUE self)
@@ -5472,9 +5875,9 @@ d_lite_italy(VALUE self)
/*
* call-seq:
- * d.england -> date
+ * england -> new_date
*
- * This method is equivalent to new_start(Date::ENGLAND).
+ * Equivalent to Date#new_start with argument Date::ENGLAND.
*/
static VALUE
d_lite_england(VALUE self)
@@ -5484,9 +5887,9 @@ d_lite_england(VALUE self)
/*
* call-seq:
- * d.julian -> date
+ * julian -> new_date
*
- * This method is equivalent to new_start(Date::JULIAN).
+ * Equivalent to Date#new_start with argument Date::JULIAN.
*/
static VALUE
d_lite_julian(VALUE self)
@@ -5496,9 +5899,9 @@ d_lite_julian(VALUE self)
/*
* call-seq:
- * d.gregorian -> date
+ * gregorian -> new_date
*
- * This method is equivalent to new_start(Date::GREGORIAN).
+ * Equivalent to Date#new_start with argument Date::GREGORIAN.
*/
static VALUE
d_lite_gregorian(VALUE self)
@@ -5979,9 +6382,9 @@ d_lite_minus(VALUE self, VALUE other)
/*
* call-seq:
- * d.next_day([n=1]) -> date
+ * next_day(n = 1) -> new_date
*
- * This method is equivalent to d + n.
+ * Equivalent to Date#+ with argument +n+.
*/
static VALUE
d_lite_next_day(int argc, VALUE *argv, VALUE self)
@@ -5996,9 +6399,9 @@ d_lite_next_day(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.prev_day([n=1]) -> date
+ * prev_day(n = 1) -> new_date
*
- * This method is equivalent to d - n.
+ * Equivalent to Date#- with argument +n+.
*/
static VALUE
d_lite_prev_day(int argc, VALUE *argv, VALUE self)
@@ -6013,10 +6416,15 @@ d_lite_prev_day(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.succ -> date
- * d.next -> date
+ * d.next -> new_date
+ *
+ * Returns a new \Date object representing the following day:
+ *
+ * d = Date.new(2001, 2, 3)
+ * d.to_s # => "2001-02-03"
+ * d.next.to_s # => "2001-02-04"
*
- * Returns a date object denoting the following day.
+ * Date#succ is an alias for Date#next.
*/
static VALUE
d_lite_next(VALUE self)
@@ -6026,26 +6434,30 @@ d_lite_next(VALUE self)
/*
* call-seq:
- * d >> n -> date
+ * d >> n -> new_date
*
- * Returns a date object pointing +n+ months after self.
- * The argument +n+ should be a numeric value.
+ * Returns a new \Date object representing the date
+ * +n+ months later; +n+ should be a numeric:
*
- * Date.new(2001,2,3) >> 1 #=> #<Date: 2001-03-03 ...>
- * Date.new(2001,2,3) >> -2 #=> #<Date: 2000-12-03 ...>
+ * (Date.new(2001, 2, 3) >> 1).to_s # => "2001-03-03"
+ * (Date.new(2001, 2, 3) >> -2).to_s # => "2000-12-03"
*
- * When the same day does not exist for the corresponding month,
- * the last day of the month is used instead:
+ * When the same day does not exist for the new month,
+ * the last day of that month is used instead:
*
- * Date.new(2001,1,28) >> 1 #=> #<Date: 2001-02-28 ...>
- * Date.new(2001,1,31) >> 1 #=> #<Date: 2001-02-28 ...>
+ * (Date.new(2001, 1, 31) >> 1).to_s # => "2001-02-28"
+ * (Date.new(2001, 1, 31) >> -4).to_s # => "2000-09-30"
*
- * This also results in the following, possibly unexpected, behavior:
+ * This results in the following, possibly unexpected, behaviors:
*
- * Date.new(2001,1,31) >> 2 #=> #<Date: 2001-03-31 ...>
- * Date.new(2001,1,31) >> 1 >> 1 #=> #<Date: 2001-03-28 ...>
+ * d0 = Date.new(2001, 1, 31)
+ * d1 = d0 >> 1 # => #<Date: 2001-02-28>
+ * d2 = d1 >> 1 # => #<Date: 2001-03-28>
+ *
+ * d0 = Date.new(2001, 1, 31)
+ * d1 = d0 >> 1 # => #<Date: 2001-02-28>
+ * d2 = d1 >> -1 # => #<Date: 2001-01-28>
*
- * Date.new(2001,1,31) >> 1 >> -1 #=> #<Date: 2001-01-28 ...>
*/
static VALUE
d_lite_rshift(VALUE self, VALUE other)
@@ -6090,24 +6502,28 @@ d_lite_rshift(VALUE self, VALUE other)
* call-seq:
* d << n -> date
*
- * Returns a date object pointing +n+ months before self.
- * The argument +n+ should be a numeric value.
+ * Returns a new \Date object representing the date
+ * +n+ months earlier; +n+ should be a numeric:
+ *
+ * (Date.new(2001, 2, 3) << 1).to_s # => "2001-01-03"
+ * (Date.new(2001, 2, 3) << -2).to_s # => "2001-04-03"
*
- * Date.new(2001,2,3) << 1 #=> #<Date: 2001-01-03 ...>
- * Date.new(2001,2,3) << -2 #=> #<Date: 2001-04-03 ...>
+ * When the same day does not exist for the new month,
+ * the last day of that month is used instead:
*
- * When the same day does not exist for the corresponding month,
- * the last day of the month is used instead:
+ * (Date.new(2001, 3, 31) << 1).to_s # => "2001-02-28"
+ * (Date.new(2001, 3, 31) << -6).to_s # => "2001-09-30"
*
- * Date.new(2001,3,28) << 1 #=> #<Date: 2001-02-28 ...>
- * Date.new(2001,3,31) << 1 #=> #<Date: 2001-02-28 ...>
+ * This results in the following, possibly unexpected, behaviors:
*
- * This also results in the following, possibly unexpected, behavior:
+ * d0 = Date.new(2001, 3, 31)
+ * d0 << 2 # => #<Date: 2001-01-31>
+ * d0 << 1 << 1 # => #<Date: 2001-01-28>
*
- * Date.new(2001,3,31) << 2 #=> #<Date: 2001-01-31 ...>
- * Date.new(2001,3,31) << 1 << 1 #=> #<Date: 2001-01-28 ...>
+ * d0 = Date.new(2001, 3, 31)
+ * d1 = d0 << 1 # => #<Date: 2001-02-28>
+ * d2 = d1 << -1 # => #<Date: 2001-03-28>
*
- * Date.new(2001,3,31) << 1 << -1 #=> #<Date: 2001-03-28 ...>
*/
static VALUE
d_lite_lshift(VALUE self, VALUE other)
@@ -6118,11 +6534,9 @@ d_lite_lshift(VALUE self, VALUE other)
/*
* call-seq:
- * d.next_month([n=1]) -> date
- *
- * This method is equivalent to d >> n.
+ * next_month(n = 1) -> new_date
*
- * See Date#>> for examples.
+ * Equivalent to #>> with argument +n+.
*/
static VALUE
d_lite_next_month(int argc, VALUE *argv, VALUE self)
@@ -6137,11 +6551,9 @@ d_lite_next_month(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.prev_month([n=1]) -> date
+ * prev_month(n = 1) -> new_date
*
- * This method is equivalent to d << n.
- *
- * See Date#<< for examples.
+ * Equivalent to #<< with argument +n+.
*/
static VALUE
d_lite_prev_month(int argc, VALUE *argv, VALUE self)
@@ -6156,15 +6568,9 @@ d_lite_prev_month(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.next_year([n=1]) -> date
- *
- * This method is equivalent to d >> (n * 12).
- *
- * Date.new(2001,2,3).next_year #=> #<Date: 2002-02-03 ...>
- * Date.new(2008,2,29).next_year #=> #<Date: 2009-02-28 ...>
- * Date.new(2008,2,29).next_year(4) #=> #<Date: 2012-02-29 ...>
+ * next_year(n = 1) -> new_date
*
- * See also Date#>>.
+ * Equivalent to #>> with argument <tt>n * 12</tt>.
*/
static VALUE
d_lite_next_year(int argc, VALUE *argv, VALUE self)
@@ -6179,15 +6585,9 @@ d_lite_next_year(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.prev_year([n=1]) -> date
+ * prev_year(n = 1) -> new_date
*
- * This method is equivalent to d << (n * 12).
- *
- * Date.new(2001,2,3).prev_year #=> #<Date: 2000-02-03 ...>
- * Date.new(2008,2,29).prev_year #=> #<Date: 2007-02-28 ...>
- * Date.new(2008,2,29).prev_year(4) #=> #<Date: 2004-02-29 ...>
- *
- * See also Date#<<.
+ * Equivalent to #<< with argument <tt>n * 12</tt>.
*/
static VALUE
d_lite_prev_year(int argc, VALUE *argv, VALUE self)
@@ -6204,14 +6604,33 @@ static VALUE d_lite_cmp(VALUE, VALUE);
/*
* call-seq:
- * d.step(limit[, step=1]) -> enumerator
- * d.step(limit[, step=1]){|date| ...} -> self
+ * step(limit, step = 1){|date| ... } -> self
+ *
+ * Calls the block with specified dates;
+ * returns +self+.
*
- * Iterates evaluation of the given block, which takes a date object.
- * The limit should be a date object.
+ * - The first +date+ is +self+.
+ * - Each successive +date+ is <tt>date + step</tt>,
+ * where +step+ is the numeric step size in days.
+ * - The last date is the last one that is before or equal to +limit+,
+ * which should be a \Date object.
*
- * Date.new(2001).step(Date.new(2001,-1,-1)).select{|d| d.sunday?}.size
- * #=> 52
+ * Example:
+ *
+ * limit = Date.new(2001, 12, 31)
+ * Date.new(2001).step(limit){|date| p date.to_s if date.mday == 31 }
+ *
+ * Output:
+ *
+ * "2001-01-31"
+ * "2001-03-31"
+ * "2001-05-31"
+ * "2001-07-31"
+ * "2001-08-31"
+ * "2001-10-31"
+ * "2001-12-31"
+ *
+ * Returns an Enumerator if no block is given.
*/
static VALUE
d_lite_step(int argc, VALUE *argv, VALUE self)
@@ -6254,10 +6673,9 @@ d_lite_step(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * d.upto(max) -> enumerator
- * d.upto(max){|date| ...} -> self
+ * upto(max){|date| ... } -> self
*
- * This method is equivalent to step(max, 1){|date| ...}.
+ * Equivalent to #step with arguments +max+ and +1+.
*/
static VALUE
d_lite_upto(VALUE self, VALUE max)
@@ -6276,10 +6694,9 @@ d_lite_upto(VALUE self, VALUE max)
/*
* call-seq:
- * d.downto(min) -> enumerator
- * d.downto(min){|date| ...} -> self
+ * downto(min){|date| ... } -> self
*
- * This method is equivalent to step(min, -1){|date| ...}.
+ * Equivalent to #step with arguments +min+ and <tt>-1</tt>.
*/
static VALUE
d_lite_downto(VALUE self, VALUE min)
@@ -6367,19 +6784,43 @@ cmp_dd(VALUE self, VALUE other)
/*
* call-seq:
- * d <=> other -> -1, 0, +1 or nil
+ * self <=> other -> -1, 0, 1 or nil
+ *
+ * Compares +self+ and +other+, returning:
+ *
+ * - <tt>-1</tt> if +other+ is larger.
+ * - <tt>0</tt> if the two are equal.
+ * - <tt>1</tt> if +other+ is smaller.
+ * - +nil+ if the two are incomparable.
*
- * Compares the two dates and returns -1, zero, 1 or nil. The other
- * should be a date object or a numeric value as an astronomical
- * Julian day number.
+ * Argument +other+ may be:
*
- * Date.new(2001,2,3) <=> Date.new(2001,2,4) #=> -1
- * Date.new(2001,2,3) <=> Date.new(2001,2,3) #=> 0
- * Date.new(2001,2,3) <=> Date.new(2001,2,2) #=> 1
- * Date.new(2001,2,3) <=> Object.new #=> nil
- * Date.new(2001,2,3) <=> Rational(4903887,2) #=> 0
+ * - Another \Date object:
+ *
+ * d = Date.new(2022, 7, 27) # => #<Date: 2022-07-27 ((2459788j,0s,0n),+0s,2299161j)>
+ * prev_date = d.prev_day # => #<Date: 2022-07-26 ((2459787j,0s,0n),+0s,2299161j)>
+ * next_date = d.next_day # => #<Date: 2022-07-28 ((2459789j,0s,0n),+0s,2299161j)>
+ * d <=> next_date # => -1
+ * d <=> d # => 0
+ * d <=> prev_date # => 1
+ *
+ * - A DateTime object:
+ *
+ * d <=> DateTime.new(2022, 7, 26) # => 1
+ * d <=> DateTime.new(2022, 7, 27) # => 0
+ * d <=> DateTime.new(2022, 7, 28) # => -1
+ *
+ * - A numeric (compares <tt>self.ajd</tt> to +other+):
+ *
+ * d <=> 2459788 # => -1
+ * d <=> 2459787 # => 1
+ * d <=> 2459786 # => 1
+ * d <=> d.ajd # => 0
+ *
+ * - Any other object:
+ *
+ * d <=> Object.new # => nil
*
- * See also Comparable.
*/
static VALUE
d_lite_cmp(VALUE self, VALUE other)
@@ -6439,20 +6880,39 @@ equal_gen(VALUE self, VALUE other)
/*
* call-seq:
- * d === other -> bool
- *
- * Returns true if they are the same day.
- *
- * Date.new(2001,2,3) === Date.new(2001,2,3)
- * #=> true
- * Date.new(2001,2,3) === Date.new(2001,2,4)
- * #=> false
- * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,12)
- * #=> true
- * DateTime.new(2001,2,3) === DateTime.new(2001,2,3,0,0,0,'+24:00')
- * #=> true
- * DateTime.new(2001,2,3) === DateTime.new(2001,2,4,0,0,0,'+24:00')
- * #=> false
+ * self === other -> true, false, or nil.
+ *
+ * Returns +true+ if +self+ and +other+ represent the same date,
+ * +false+ if not, +nil+ if the two are not comparable.
+ *
+ * Argument +other+ may be:
+ *
+ * - Another \Date object:
+ *
+ * d = Date.new(2022, 7, 27) # => #<Date: 2022-07-27 ((2459788j,0s,0n),+0s,2299161j)>
+ * prev_date = d.prev_day # => #<Date: 2022-07-26 ((2459787j,0s,0n),+0s,2299161j)>
+ * next_date = d.next_day # => #<Date: 2022-07-28 ((2459789j,0s,0n),+0s,2299161j)>
+ * d === prev_date # => false
+ * d === d # => true
+ * d === next_date # => false
+ *
+ * - A DateTime object:
+ *
+ * d === DateTime.new(2022, 7, 26) # => false
+ * d === DateTime.new(2022, 7, 27) # => true
+ * d === DateTime.new(2022, 7, 28) # => false
+ *
+ * - A numeric (compares <tt>self.jd</tt> to +other+):
+ *
+ * d === 2459788 # => true
+ * d === 2459787 # => false
+ * d === 2459786 # => false
+ * d === d.jd # => true
+ *
+ * - An object not comparable:
+ *
+ * d === Object.new # => nil
+ *
*/
static VALUE
d_lite_equal(VALUE self, VALUE other)
@@ -6515,12 +6975,14 @@ static VALUE strftimev(const char *, VALUE,
/*
* call-seq:
- * d.to_s -> string
+ * to_s -> string
*
- * Returns a string in an ISO 8601 format. (This method doesn't use the
- * expanded representations.)
+ * Returns a string representation of the date in +self+
+ * in {ISO 8601 extended date format}[rdoc-ref:strftime_formatting.rdoc@ISO+8601+Format+Specifications]
+ * (<tt>'%Y-%m-%d'</tt>):
+ *
+ * Date.new(2001, 2, 3).to_s # => "2001-02-03"
*
- * Date.new(2001,2,3).to_s #=> "2001-02-03"
*/
static VALUE
d_lite_to_s(VALUE self)
@@ -6529,6 +6991,7 @@ d_lite_to_s(VALUE self)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
mk_inspect_raw(union DateData *x, VALUE klass)
{
@@ -6578,6 +7041,7 @@ mk_inspect_raw(union DateData *x, VALUE klass)
}
}
+/* :nodoc: */
static VALUE
d_lite_inspect_raw(VALUE self)
{
@@ -6599,14 +7063,13 @@ mk_inspect(union DateData *x, VALUE klass, VALUE to_s)
/*
* call-seq:
- * d.inspect -> string
+ * inspect -> string
+ *
+ * Returns a string representation of +self+:
*
- * Returns the value as a string for inspection.
+ * Date.new(2001, 2, 3).inspect
+ * # => "#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>"
*
- * Date.new(2001,2,3).inspect
- * #=> "#<Date: 2001-02-03>"
- * DateTime.new(2001,2,3,4,5,6,'-7').inspect
- * #=> "#<DateTime: 2001-02-03T04:05:06-07:00>"
*/
static VALUE
d_lite_inspect(VALUE self)
@@ -6788,180 +7251,16 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
/*
* call-seq:
- * d.strftime([format='%F']) -> string
- *
- * Formats date according to the directives in the given format
- * string.
- * The directives begin with a percent (%) character.
- * Any text not listed as a directive will be passed through to the
- * output string.
- *
- * A directive consists of a percent (%) character,
- * zero or more flags, an optional minimum field width,
- * an optional modifier, and a conversion specifier
- * as follows.
- *
- * %<flags><width><modifier><conversion>
- *
- * Flags:
- * - don't pad a numerical output.
- * _ use spaces for padding.
- * 0 use zeros for padding.
- * ^ upcase the result string.
- * # change case.
- *
- * The minimum field width specifies the minimum width.
- *
- * The modifiers are "E", "O", ":", "::" and ":::".
- * "E" and "O" are ignored. No effect to result currently.
- *
- * Format directives:
- *
- * Date (Year, Month, Day):
- * %Y - Year with century (can be negative, 4 digits at least)
- * -0001, 0000, 1995, 2009, 14292, etc.
- * %C - year / 100 (round down. 20 in 2009)
- * %y - year % 100 (00..99)
- *
- * %m - Month of the year, zero-padded (01..12)
- * %_m blank-padded ( 1..12)
- * %-m no-padded (1..12)
- * %B - The full month name (``January'')
- * %^B uppercased (``JANUARY'')
- * %b - The abbreviated month name (``Jan'')
- * %^b uppercased (``JAN'')
- * %h - Equivalent to %b
- *
- * %d - Day of the month, zero-padded (01..31)
- * %-d no-padded (1..31)
- * %e - Day of the month, blank-padded ( 1..31)
- *
- * %j - Day of the year (001..366)
- *
- * Time (Hour, Minute, Second, Subsecond):
- * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
- * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
- * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
- * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
- * %P - Meridian indicator, lowercase (``am'' or ``pm'')
- * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
- *
- * %M - Minute of the hour (00..59)
- *
- * %S - Second of the minute (00..60)
- *
- * %L - Millisecond of the second (000..999)
- * %N - Fractional seconds digits, default is 9 digits (nanosecond)
- * %3N millisecond (3 digits) %15N femtosecond (15 digits)
- * %6N microsecond (6 digits) %18N attosecond (18 digits)
- * %9N nanosecond (9 digits) %21N zeptosecond (21 digits)
- * %12N picosecond (12 digits) %24N yoctosecond (24 digits)
- *
- * Time zone:
- * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
- * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
- * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
- * %:::z - hour, minute and second offset from UTC
- * (e.g. +09, +09:30, +09:30:30)
- * %Z - Equivalent to %:z (e.g. +09:00)
- *
- * Weekday:
- * %A - The full weekday name (``Sunday'')
- * %^A uppercased (``SUNDAY'')
- * %a - The abbreviated name (``Sun'')
- * %^a uppercased (``SUN'')
- * %u - Day of the week (Monday is 1, 1..7)
- * %w - Day of the week (Sunday is 0, 0..6)
- *
- * ISO 8601 week-based year and week number:
- * The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
- * The days in the year before the first week are in the last week of
- * the previous year.
- * %G - The week-based year
- * %g - The last 2 digits of the week-based year (00..99)
- * %V - Week number of the week-based year (01..53)
- *
- * Week number:
- * The week 1 of YYYY starts with a Sunday or Monday (according to %U
- * or %W). The days in the year before the first week are in week 0.
- * %U - Week number of the year. The week starts with Sunday. (00..53)
- * %W - Week number of the year. The week starts with Monday. (00..53)
- *
- * Seconds since the Unix Epoch:
- * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
- * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
- *
- * Literal string:
- * %n - Newline character (\n)
- * %t - Tab character (\t)
- * %% - Literal ``%'' character
- *
- * Combination:
- * %c - date and time (%a %b %e %T %Y)
- * %D - Date (%m/%d/%y)
- * %F - The ISO 8601 date format (%Y-%m-%d)
- * %v - VMS date (%e-%b-%Y)
- * %x - Same as %D
- * %X - Same as %T
- * %r - 12-hour time (%I:%M:%S %p)
- * %R - 24-hour time (%H:%M)
- * %T - 24-hour time (%H:%M:%S)
- * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y)
- *
- * This method is similar to the strftime() function defined in ISO C
- * and POSIX.
- * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z)
- * are locale dependent in the function.
- * However, this method is locale independent.
- * So, the result may differ even if the same format string is used in other
- * systems such as C.
- * It is good practice to avoid %x and %X because there are corresponding
- * locale independent representations, %D and %T.
- *
- * Examples:
- *
- * d = DateTime.new(2007,11,19,8,37,48,"-06:00")
- * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...>
- * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
- * d.strftime("at %I:%M%p") #=> "at 08:37AM"
- *
- * Various ISO 8601 formats:
- * %Y%m%d => 20071119 Calendar date (basic)
- * %F => 2007-11-19 Calendar date (extended)
- * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
- * %Y => 2007 Calendar date, reduced accuracy, specific year
- * %C => 20 Calendar date, reduced accuracy, specific century
- * %Y%j => 2007323 Ordinal date (basic)
- * %Y-%j => 2007-323 Ordinal date (extended)
- * %GW%V%u => 2007W471 Week date (basic)
- * %G-W%V-%u => 2007-W47-1 Week date (extended)
- * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
- * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
- * %H%M%S => 083748 Local time (basic)
- * %T => 08:37:48 Local time (extended)
- * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
- * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
- * %H => 08 Local time, reduced accuracy, specific hour
- * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
- * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
- * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
- * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
- * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
- * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
- * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
- * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
- * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
- * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
- * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
- * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
- * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
- * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
- * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
- * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
- * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
- * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
- *
- * See also strftime(3) and ::strptime.
+ * strftime(format = '%F') -> string
+ *
+ * Returns a string representation of the date in +self+,
+ * formatted according the given +format+:
+ *
+ * Date.new(2001, 2, 3).strftime # => "2001-02-03"
+ *
+ * For other formats, see
+ * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc].
+ *
*/
static VALUE
d_lite_strftime(int argc, VALUE *argv, VALUE self)
@@ -6989,13 +7288,17 @@ strftimev(const char *fmt, VALUE self,
/*
* call-seq:
- * d.asctime -> string
- * d.ctime -> string
+ * asctime -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%a %b %e %T %Y'</tt>
+ * (or its {shorthand form}[rdoc-ref:strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
+ * <tt>'%c'</tt>):
+ *
+ * Date.new(2001, 2, 3).asctime # => "Sat Feb 3 00:00:00 2001"
*
- * Returns a string in asctime(3) format (but without "\n\0" at the
- * end). This method is equivalent to strftime('%c').
+ * See {asctime}[https://linux.die.net/man/3/asctime].
*
- * See also asctime(3) or ctime(3).
+ * Date#ctime is an alias for Date#asctime.
*/
static VALUE
d_lite_asctime(VALUE self)
@@ -7005,10 +7308,15 @@ d_lite_asctime(VALUE self)
/*
* call-seq:
- * d.iso8601 -> string
- * d.xmlschema -> string
+ * iso8601 -> string
*
- * This method is equivalent to strftime('%F').
+ * Equivalent to #strftime with argument <tt>'%Y-%m-%d'</tt>
+ * (or its {shorthand form}[rdoc-ref:strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
+ * <tt>'%F'</tt>);
+ *
+ * Date.new(2001, 2, 3).iso8601 # => "2001-02-03"
+ *
+ * Date#xmlschema is an alias for Date#iso8601.
*/
static VALUE
d_lite_iso8601(VALUE self)
@@ -7018,9 +7326,13 @@ d_lite_iso8601(VALUE self)
/*
* call-seq:
- * d.rfc3339 -> string
+ * rfc3339 -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%FT%T%:z'</tt>;
+ * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
+ *
+ * Date.new(2001, 2, 3).rfc3339 # => "2001-02-03T00:00:00+00:00"
*
- * This method is equivalent to strftime('%FT%T%:z').
*/
static VALUE
d_lite_rfc3339(VALUE self)
@@ -7030,10 +7342,14 @@ d_lite_rfc3339(VALUE self)
/*
* call-seq:
- * d.rfc2822 -> string
- * d.rfc822 -> string
+ * rfc2822 -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%a, %-d %b %Y %T %z'</tt>;
+ * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
*
- * This method is equivalent to strftime('%a, %-d %b %Y %T %z').
+ * Date.new(2001, 2, 3).rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ *
+ * Date#rfc822 is an alias for Date#rfc2822.
*/
static VALUE
d_lite_rfc2822(VALUE self)
@@ -7043,10 +7359,13 @@ d_lite_rfc2822(VALUE self)
/*
* call-seq:
- * d.httpdate -> string
+ * httpdate -> string
+ *
+ * Equivalent to #strftime with argument <tt>'%a, %d %b %Y %T GMT'</tt>;
+ * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
+ *
+ * Date.new(2001, 2, 3).httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
*
- * This method is equivalent to strftime('%a, %d %b %Y %T GMT').
- * See also RFC 2616.
*/
static VALUE
d_lite_httpdate(VALUE self)
@@ -7097,11 +7416,13 @@ jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y)
/*
* call-seq:
- * d.jisx0301 -> string
+ * jisx0301 -> string
*
- * Returns a string in a JIS X 0301 format.
+ * Returns a string representation of the date in +self+
+ * in JIS X 0301 format.
+ *
+ * Date.new(2001, 2, 3).jisx0301 # => "H13.02.03"
*
- * Date.new(2001,2,3).jisx0301 #=> "H13.02.03"
*/
static VALUE
d_lite_jisx0301(VALUE self)
@@ -7116,7 +7437,98 @@ d_lite_jisx0301(VALUE self)
return strftimev(fmt, self, set_tmx);
}
+static VALUE
+deconstruct_keys(VALUE self, VALUE keys, int is_datetime)
+{
+ VALUE h = rb_hash_new();
+ long i;
+
+ get_d1(self);
+
+ if (NIL_P(keys)) {
+ rb_hash_aset(h, sym_year, m_real_year(dat));
+ rb_hash_aset(h, sym_month, INT2FIX(m_mon(dat)));
+ rb_hash_aset(h, sym_day, INT2FIX(m_mday(dat)));
+ rb_hash_aset(h, sym_yday, INT2FIX(m_yday(dat)));
+ rb_hash_aset(h, sym_wday, INT2FIX(m_wday(dat)));
+ if (is_datetime) {
+ rb_hash_aset(h, sym_hour, INT2FIX(m_hour(dat)));
+ rb_hash_aset(h, sym_min, INT2FIX(m_min(dat)));
+ rb_hash_aset(h, sym_sec, INT2FIX(m_sec(dat)));
+ rb_hash_aset(h, sym_sec_fraction, m_sf_in_sec(dat));
+ rb_hash_aset(h, sym_zone, m_zone(dat));
+ }
+
+ return h;
+ }
+ if (!RB_TYPE_P(keys, T_ARRAY)) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %"PRIsVALUE" (expected Array or nil)",
+ rb_obj_class(keys));
+
+ }
+
+ for (i=0; i<RARRAY_LEN(keys); i++) {
+ VALUE key = RARRAY_AREF(keys, i);
+
+ if (sym_year == key) rb_hash_aset(h, key, m_real_year(dat));
+ if (sym_month == key) rb_hash_aset(h, key, INT2FIX(m_mon(dat)));
+ if (sym_day == key) rb_hash_aset(h, key, INT2FIX(m_mday(dat)));
+ if (sym_yday == key) rb_hash_aset(h, key, INT2FIX(m_yday(dat)));
+ if (sym_wday == key) rb_hash_aset(h, key, INT2FIX(m_wday(dat)));
+ if (is_datetime) {
+ if (sym_hour == key) rb_hash_aset(h, key, INT2FIX(m_hour(dat)));
+ if (sym_min == key) rb_hash_aset(h, key, INT2FIX(m_min(dat)));
+ if (sym_sec == key) rb_hash_aset(h, key, INT2FIX(m_sec(dat)));
+ if (sym_sec_fraction == key) rb_hash_aset(h, key, m_sf_in_sec(dat));
+ if (sym_zone == key) rb_hash_aset(h, key, m_zone(dat));
+ }
+ }
+ return h;
+}
+
+/*
+ * call-seq:
+ * deconstruct_keys(array_of_names_or_nil) -> hash
+ *
+ * Returns a hash of the name/value pairs, to use in pattern matching.
+ * Possible keys are: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
+ * <tt>:wday</tt>, <tt>:yday</tt>.
+ *
+ * Possible usages:
+ *
+ * d = Date.new(2022, 10, 5)
+ *
+ * if d in wday: 3, day: ..7 # uses deconstruct_keys underneath
+ * puts "first Wednesday of the month"
+ * end
+ * #=> prints "first Wednesday of the month"
+ *
+ * case d
+ * in year: ...2022
+ * puts "too old"
+ * in month: ..9
+ * puts "quarter 1-3"
+ * in wday: 1..5, month:
+ * puts "working day in month #{month}"
+ * end
+ * #=> prints "working day in month 10"
+ *
+ * Note that deconstruction by pattern can also be combined with class check:
+ *
+ * if d in Date(wday: 3, day: ..7)
+ * puts "first Wednesday of the month"
+ * end
+ *
+ */
+static VALUE
+d_lite_deconstruct_keys(VALUE self, VALUE keys)
+{
+ return deconstruct_keys(self, keys, /* is_datetime=false */ 0);
+}
+
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
d_lite_marshal_dump_old(VALUE self)
{
@@ -7404,17 +7816,7 @@ datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
}
/*
- * call-seq:
- * DateTime.civil([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
- * DateTime.new([year=-4712[, month=1[, mday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) -> datetime
- *
- * Creates a DateTime object denoting the given calendar date.
- *
- * DateTime.new(2001,2,3) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
- * DateTime.new(2001,2,3,4,5,6,'+7')
- * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
- * DateTime.new(2001,-11,-26,-20,-55,-54,'+7')
- * #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ * Same as DateTime.new.
*/
static VALUE
datetime_s_civil(int argc, VALUE *argv, VALUE klass)
@@ -7604,6 +8006,7 @@ datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
{
@@ -7673,6 +8076,7 @@ datetime_s_weeknum(int argc, VALUE *argv, VALUE klass)
return ret;
}
+/* :nodoc: */
static VALUE
datetime_s_nth_kday(int argc, VALUE *argv, VALUE klass)
{
@@ -7797,7 +8201,7 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
of = tm.tm_gmtoff;
#elif defined(HAVE_TIMEZONE)
-#ifdef HAVE_ALTZONE
+#if defined(HAVE_ALTZONE) && !defined(_AIX)
of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
#else
of = (long)-timezone;
@@ -8013,14 +8417,14 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]]) -> datetime
+ * DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime
*
* Parses the given representation of date and time, and creates a
* DateTime object.
*
- * This method *does not* function as a validator. If the input
+ * 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
+ * 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
@@ -8032,13 +8436,18 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
* DateTime.parse('3rd Feb 2001 04:05:06 PM')
* #=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_parse(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, comp, sg;
+ VALUE str, comp, sg, opt;
- rb_scan_args(argc, argv, "03", &str, &comp, &sg);
+ rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8050,18 +8459,20 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE argv2[2], hash;
-
- argv2[0] = str;
- argv2[1] = comp;
- hash = date_s__parse(2, argv2, klass);
+ int argc2 = 2;
+ VALUE argv2[3], hash;
+ argv2[0] = str;
+ argv2[1] = comp;
+ argv2[2] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__parse(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
+ * DateTime.iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
*
* Creates a new DateTime object by parsing from a string according to
* some typical ISO 8601 formats.
@@ -8072,13 +8483,18 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
* DateTime.iso8601('2001-W05-6T04:05:06+07:00')
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8088,27 +8504,37 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__iso8601(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2--;
+ hash = date_s__iso8601(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
+ * DateTime.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
*
* Creates a new DateTime object by parsing from a string according to
* some typical RFC 3339 formats.
*
* DateTime.rfc3339('2001-02-03T04:05:06+07:00')
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8118,27 +8544,37 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__rfc3339(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__rfc3339(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
+ * DateTime.xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
*
* Creates a new DateTime object by parsing from a string according to
* some typical XML Schema formats.
*
* DateTime.xmlschema('2001-02-03T04:05:06+07:00')
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8148,28 +8584,38 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__xmlschema(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__xmlschema(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
- * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY]) -> datetime
+ * DateTime.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
+ * DateTime.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> datetime
*
* Creates a new DateTime object by parsing from a string according to
* some typical RFC 2822 formats.
*
* DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8179,7 +8625,12 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__rfc2822(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__rfc2822(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
@@ -8193,13 +8644,18 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
*
* DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
* #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8209,14 +8665,19 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__httpdate(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__httpdate(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
/*
* call-seq:
- * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY]) -> datetime
+ * DateTime.jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> datetime
*
* Creates a new DateTime object by parsing from a string according to
* some typical JIS X 0301 formats.
@@ -8228,13 +8689,18 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
*
* DateTime.jisx0301('13.02.03T04:05:06+07:00')
* #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
+ *
+ * Raise an ArgumentError when the string length is longer than _limit_.
+ * You can stop this check by passing <code>limit: nil</code>, but note
+ * that it may take a long time to parse.
*/
static VALUE
datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
{
- VALUE str, sg;
+ VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02", &str, &sg);
+ rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ if (!NIL_P(opt)) argc--;
switch (argc) {
case 0:
@@ -8244,7 +8710,12 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
}
{
- VALUE hash = date_s__jisx0301(klass, str);
+ int argc2 = 1;
+ VALUE argv2[2], hash;
+ argv2[0] = str;
+ argv2[1] = opt;
+ if (!NIL_P(opt)) argc2++;
+ hash = date_s__jisx0301(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
}
@@ -8267,181 +8738,16 @@ dt_lite_to_s(VALUE self)
/*
* call-seq:
- * dt.strftime([format='%FT%T%:z']) -> string
- *
- * Formats date according to the directives in the given format
- * string.
- * The directives begin with a percent (%) character.
- * Any text not listed as a directive will be passed through to the
- * output string.
- *
- * A directive consists of a percent (%) character,
- * zero or more flags, an optional minimum field width,
- * an optional modifier, and a conversion specifier
- * as follows.
- *
- * %<flags><width><modifier><conversion>
- *
- * Flags:
- * - don't pad a numerical output.
- * _ use spaces for padding.
- * 0 use zeros for padding.
- * ^ upcase the result string.
- * # change case.
- * : use colons for %z.
- *
- * The minimum field width specifies the minimum width.
- *
- * The modifiers are "E" and "O".
- * They are ignored.
- *
- * Format directives:
- *
- * Date (Year, Month, Day):
- * %Y - Year with century (can be negative, 4 digits at least)
- * -0001, 0000, 1995, 2009, 14292, etc.
- * %C - year / 100 (round down. 20 in 2009)
- * %y - year % 100 (00..99)
- *
- * %m - Month of the year, zero-padded (01..12)
- * %_m blank-padded ( 1..12)
- * %-m no-padded (1..12)
- * %B - The full month name (``January'')
- * %^B uppercased (``JANUARY'')
- * %b - The abbreviated month name (``Jan'')
- * %^b uppercased (``JAN'')
- * %h - Equivalent to %b
- *
- * %d - Day of the month, zero-padded (01..31)
- * %-d no-padded (1..31)
- * %e - Day of the month, blank-padded ( 1..31)
- *
- * %j - Day of the year (001..366)
- *
- * Time (Hour, Minute, Second, Subsecond):
- * %H - Hour of the day, 24-hour clock, zero-padded (00..23)
- * %k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
- * %I - Hour of the day, 12-hour clock, zero-padded (01..12)
- * %l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
- * %P - Meridian indicator, lowercase (``am'' or ``pm'')
- * %p - Meridian indicator, uppercase (``AM'' or ``PM'')
- *
- * %M - Minute of the hour (00..59)
- *
- * %S - Second of the minute (00..60)
- *
- * %L - Millisecond of the second (000..999)
- * %N - Fractional seconds digits, default is 9 digits (nanosecond)
- * %3N millisecond (3 digits) %15N femtosecond (15 digits)
- * %6N microsecond (6 digits) %18N attosecond (18 digits)
- * %9N nanosecond (9 digits) %21N zeptosecond (21 digits)
- * %12N picosecond (12 digits) %24N yoctosecond (24 digits)
- *
- * Time zone:
- * %z - Time zone as hour and minute offset from UTC (e.g. +0900)
- * %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
- * %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
- * %:::z - hour, minute and second offset from UTC
- * (e.g. +09, +09:30, +09:30:30)
- * %Z - Equivalent to %:z (e.g. +09:00)
- *
- * Weekday:
- * %A - The full weekday name (``Sunday'')
- * %^A uppercased (``SUNDAY'')
- * %a - The abbreviated name (``Sun'')
- * %^a uppercased (``SUN'')
- * %u - Day of the week (Monday is 1, 1..7)
- * %w - Day of the week (Sunday is 0, 0..6)
- *
- * ISO 8601 week-based year and week number:
- * The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
- * The days in the year before the first week are in the last week of
- * the previous year.
- * %G - The week-based year
- * %g - The last 2 digits of the week-based year (00..99)
- * %V - Week number of the week-based year (01..53)
- *
- * Week number:
- * The week 1 of YYYY starts with a Sunday or Monday (according to %U
- * or %W). The days in the year before the first week are in week 0.
- * %U - Week number of the year. The week starts with Sunday. (00..53)
- * %W - Week number of the year. The week starts with Monday. (00..53)
- *
- * Seconds since the Unix Epoch:
- * %s - Number of seconds since 1970-01-01 00:00:00 UTC.
- * %Q - Number of milliseconds since 1970-01-01 00:00:00 UTC.
- *
- * Literal string:
- * %n - Newline character (\n)
- * %t - Tab character (\t)
- * %% - Literal ``%'' character
- *
- * Combination:
- * %c - date and time (%a %b %e %T %Y)
- * %D - Date (%m/%d/%y)
- * %F - The ISO 8601 date format (%Y-%m-%d)
- * %v - VMS date (%e-%b-%Y)
- * %x - Same as %D
- * %X - Same as %T
- * %r - 12-hour time (%I:%M:%S %p)
- * %R - 24-hour time (%H:%M)
- * %T - 24-hour time (%H:%M:%S)
- * %+ - date(1) (%a %b %e %H:%M:%S %Z %Y)
- *
- * This method is similar to the strftime() function defined in ISO C
- * and POSIX.
- * Several directives (%a, %A, %b, %B, %c, %p, %r, %x, %X, %E*, %O* and %Z)
- * are locale dependent in the function.
- * However, this method is locale independent.
- * So, the result may differ even if the same format string is used in other
- * systems such as C.
- * It is good practice to avoid %x and %X because there are corresponding
- * locale independent representations, %D and %T.
- *
- * Examples:
- *
- * d = DateTime.new(2007,11,19,8,37,48,"-06:00")
- * #=> #<DateTime: 2007-11-19T08:37:48-0600 ...>
- * d.strftime("Printed on %m/%d/%Y") #=> "Printed on 11/19/2007"
- * d.strftime("at %I:%M%p") #=> "at 08:37AM"
- *
- * Various ISO 8601 formats:
- * %Y%m%d => 20071119 Calendar date (basic)
- * %F => 2007-11-19 Calendar date (extended)
- * %Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
- * %Y => 2007 Calendar date, reduced accuracy, specific year
- * %C => 20 Calendar date, reduced accuracy, specific century
- * %Y%j => 2007323 Ordinal date (basic)
- * %Y-%j => 2007-323 Ordinal date (extended)
- * %GW%V%u => 2007W471 Week date (basic)
- * %G-W%V-%u => 2007-W47-1 Week date (extended)
- * %GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
- * %G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
- * %H%M%S => 083748 Local time (basic)
- * %T => 08:37:48 Local time (extended)
- * %H%M => 0837 Local time, reduced accuracy, specific minute (basic)
- * %H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
- * %H => 08 Local time, reduced accuracy, specific hour
- * %H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
- * %T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
- * %H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
- * %T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
- * %H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
- * %T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
- * %Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
- * %FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
- * %Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
- * %Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
- * %GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
- * %G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
- * %Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
- * %FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
- * %Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
- * %Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
- * %GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
- * %G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
- *
- * See also strftime(3) and ::strptime.
+ * strftime(format = '%FT%T%:z') -> string
+ *
+ * Returns a string representation of +self+,
+ * formatted according the given +format:
+ *
+ * DateTime.now.strftime # => "2022-07-01T11:03:19-05:00"
+ *
+ * For other formats, see
+ * {Formats for Dates and Times}[doc/strftime_formatting.rdoc].
+ *
*/
static VALUE
dt_lite_strftime(int argc, VALUE *argv, VALUE self)
@@ -8529,6 +8835,47 @@ dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
iso8601_timediv(self, n));
}
+/*
+ * call-seq:
+ * deconstruct_keys(array_of_names_or_nil) -> hash
+ *
+ * Returns a hash of the name/value pairs, to use in pattern matching.
+ * Possible keys are: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
+ * <tt>:wday</tt>, <tt>:yday</tt>, <tt>:hour</tt>, <tt>:min</tt>,
+ * <tt>:sec</tt>, <tt>:sec_fraction</tt>, <tt>:zone</tt>.
+ *
+ * Possible usages:
+ *
+ * dt = DateTime.new(2022, 10, 5, 13, 30)
+ *
+ * if d in wday: 1..5, hour: 10..18 # uses deconstruct_keys underneath
+ * puts "Working time"
+ * end
+ * #=> prints "Working time"
+ *
+ * case dt
+ * in year: ...2022
+ * puts "too old"
+ * in month: ..9
+ * puts "quarter 1-3"
+ * in wday: 1..5, month:
+ * puts "working day in month #{month}"
+ * end
+ * #=> prints "working day in month 10"
+ *
+ * Note that deconstruction by pattern can also be combined with class check:
+ *
+ * if d in DateTime(wday: 1..5, hour: 10..18, day: ..7)
+ * puts "Working time, first week of the month"
+ * end
+ *
+ */
+static VALUE
+dt_lite_deconstruct_keys(VALUE self, VALUE keys)
+{
+ return deconstruct_keys(self, keys, /* is_datetime=true */ 1);
+}
+
/* conversions */
#define f_subsec(x) rb_funcall(x, rb_intern("subsec"), 0)
@@ -8607,7 +8954,7 @@ time_to_datetime(VALUE self)
ret = d_complex_new_internal(cDateTime,
nth, 0,
0, sf,
- of, DEFAULT_SG,
+ of, GREGORIAN,
ry, m, d,
h, min, s,
HAVE_CIVIL | HAVE_TIME);
@@ -8620,10 +8967,15 @@ time_to_datetime(VALUE self)
/*
* call-seq:
- * d.to_time -> time
+ * to_time -> time
+ *
+ * Returns a new Time object with the same value as +self+;
+ * if +self+ is a Julian date, derives its Gregorian date
+ * for conversion to the \Time object:
+ *
+ * Date.new(2001, 2, 3).to_time # => 2001-02-03 00:00:00 -0600
+ * Date.new(2001, 2, 3, Date::JULIAN).to_time # => 2001-02-16 00:00:00 -0600
*
- * Returns a Time object which denotes self. If self is a julian date,
- * convert it to a gregorian date before converting it to Time.
*/
static VALUE
date_to_time(VALUE self)
@@ -8644,9 +8996,9 @@ date_to_time(VALUE self)
/*
* call-seq:
- * d.to_date -> self
+ * to_date -> self
*
- * Returns self.
+ * Returns +self+.
*/
static VALUE
date_to_date(VALUE self)
@@ -8658,7 +9010,10 @@ date_to_date(VALUE self)
* call-seq:
* d.to_datetime -> datetime
*
- * Returns a DateTime object which denotes self.
+ * Returns a DateTime whose value is the same as +self+:
+ *
+ * Date.new(2001, 2, 3).to_datetime # => #<DateTime: 2001-02-03T00:00:00+00:00>
+ *
*/
static VALUE
date_to_datetime(VALUE self)
@@ -8703,12 +9058,17 @@ date_to_datetime(VALUE self)
static VALUE
datetime_to_time(VALUE self)
{
- volatile VALUE dup = dup_obj(self);
+ get_d1(self);
+
+ if (m_julian_p(dat)) {
+ self = d_lite_gregorian(self);
+ get_d1a(self);
+ dat = adat;
+ }
+
{
VALUE t;
- get_d1(dup);
-
t = rb_funcall(rb_cTime,
rb_intern("new"),
7,
@@ -8776,6 +9136,7 @@ datetime_to_datetime(VALUE self)
#define MIN_JD -327
#define MAX_JD 366963925
+/* :nodoc: */
static int
test_civil(int from, int to, double sg)
{
@@ -8796,6 +9157,7 @@ test_civil(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_civil(VALUE klass)
{
@@ -8816,6 +9178,7 @@ date_s_test_civil(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_ordinal(int from, int to, double sg)
{
@@ -8836,6 +9199,7 @@ test_ordinal(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_ordinal(VALUE klass)
{
@@ -8856,6 +9220,7 @@ date_s_test_ordinal(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_commercial(int from, int to, double sg)
{
@@ -8876,6 +9241,7 @@ test_commercial(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_commercial(VALUE klass)
{
@@ -8896,6 +9262,7 @@ date_s_test_commercial(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_weeknum(int from, int to, int f, double sg)
{
@@ -8916,6 +9283,7 @@ test_weeknum(int from, int to, int f, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_weeknum(VALUE klass)
{
@@ -8940,6 +9308,7 @@ date_s_test_weeknum(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_nth_kday(int from, int to, double sg)
{
@@ -8960,6 +9329,7 @@ test_nth_kday(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_nth_kday(VALUE klass)
{
@@ -8980,6 +9350,7 @@ date_s_test_nth_kday(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_unit_v2v(VALUE i,
VALUE (* conv1)(VALUE),
@@ -8991,6 +9362,7 @@ test_unit_v2v(VALUE i,
return f_eqeq_p(o, i);
}
+/* :nodoc: */
static int
test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
VALUE (* conv2)(VALUE))
@@ -9022,6 +9394,7 @@ test_unit_v2v_iter2(VALUE (* conv1)(VALUE),
return 1;
}
+/* :nodoc: */
static int
test_unit_v2v_iter(VALUE (* conv1)(VALUE),
VALUE (* conv2)(VALUE))
@@ -9033,6 +9406,7 @@ test_unit_v2v_iter(VALUE (* conv1)(VALUE),
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_unit_conv(VALUE klass)
{
@@ -9047,6 +9421,7 @@ date_s_test_unit_conv(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static VALUE
date_s_test_all(VALUE klass)
{
@@ -9113,6 +9488,7 @@ mk_ary_of_str(long len, const char *a[])
return o;
}
+/* :nodoc: */
static VALUE
d_lite_zero(VALUE x)
{
@@ -9130,6 +9506,17 @@ Init_date_core(void)
id_ge_p = rb_intern_const(">=");
id_eqeq_p = rb_intern_const("==");
+ sym_year = ID2SYM(rb_intern_const("year"));
+ sym_month = ID2SYM(rb_intern_const("month"));
+ sym_yday = ID2SYM(rb_intern_const("yday"));
+ sym_wday = ID2SYM(rb_intern_const("wday"));
+ sym_day = ID2SYM(rb_intern_const("day"));
+ sym_hour = ID2SYM(rb_intern_const("hour"));
+ sym_min = ID2SYM(rb_intern_const("min"));
+ sym_sec = ID2SYM(rb_intern_const("sec"));
+ sym_sec_fraction = ID2SYM(rb_intern_const("sec_fraction"));
+ sym_zone = ID2SYM(rb_intern_const("zone"));
+
half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
#if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
@@ -9150,152 +9537,81 @@ Init_date_core(void)
negative_inf = -INFINITY;
/*
- * date and datetime class - Tadayoshi Funaba 1998-2011
- *
- * 'date' provides two classes: Date and DateTime.
+ * \Class \Date provides methods for storing and manipulating
+ * calendar dates.
*
- * == Terms and Definitions
+ * Consider using
+ * {class Time}[rdoc-ref:Time]
+ * instead of class \Date if:
*
- * Some terms and definitions are based on ISO 8601 and JIS X 0301.
+ * - You need both dates and times; \Date handles only dates.
+ * - You need only Gregorian dates (and not Julian dates);
+ * see {Julian and Gregorian Calendars}[rdoc-ref:calendars.rdoc].
*
- * === Calendar Date
+ * A \Date object, once created, is immutable, and cannot be modified.
*
- * The calendar date is a particular day of a calendar year,
- * identified by its ordinal number within a calendar month within
- * that year.
+ * == Creating a \Date
*
- * In those classes, this is so-called "civil".
+ * You can create a date for the current date, using Date.today:
*
- * === Ordinal Date
+ * Date.today # => #<Date: 1999-12-31>
*
- * The ordinal date is a particular day of a calendar year identified
- * by its ordinal number within the year.
+ * You can create a specific date from various combinations of arguments:
*
- * In those classes, this is so-called "ordinal".
+ * - Date.new takes integer year, month, and day-of-month:
*
- * === Week Date
+ * Date.new(1999, 12, 31) # => #<Date: 1999-12-31>
*
- * The week date is a date identified by calendar week and day numbers.
+ * - Date.ordinal takes integer year and day-of-year:
*
- * The calendar week is a seven day period within a calendar year,
- * starting on a Monday and identified by its ordinal number within
- * the year; the first calendar week of the year is the one that
- * includes the first Thursday of that year. In the Gregorian
- * calendar, this is equivalent to the week which includes January 4.
+ * Date.ordinal(1999, 365) # => #<Date: 1999-12-31>
*
- * In those classes, this is so-called "commercial".
+ * - Date.jd takes integer Julian day:
*
- * === Julian Day Number
+ * Date.jd(2451544) # => #<Date: 1999-12-31>
*
- * The Julian day number is in elapsed days since noon (Greenwich Mean
- * Time) on January 1, 4713 BCE (in the Julian calendar).
+ * - Date.commercial takes integer commercial data (year, week, day-of-week):
*
- * In this document, the astronomical Julian day number is the same as
- * the original Julian day number. And the chronological Julian day
- * number is a variation of the Julian day number. Its days begin at
- * midnight on local time.
+ * Date.commercial(1999, 52, 5) # => #<Date: 1999-12-31>
*
- * In this document, when the term "Julian day number" simply appears,
- * it just refers to "chronological Julian day number", not the
- * original.
+ * - Date.parse takes a string, which it parses heuristically:
*
- * In those classes, those are so-called "ajd" and "jd".
+ * Date.parse('1999-12-31') # => #<Date: 1999-12-31>
+ * Date.parse('31-12-1999') # => #<Date: 1999-12-31>
+ * Date.parse('1999-365') # => #<Date: 1999-12-31>
+ * Date.parse('1999-W52-5') # => #<Date: 1999-12-31>
*
- * === Modified Julian Day Number
+ * - Date.strptime takes a date string and a format string,
+ * then parses the date string according to the format string:
*
- * The modified Julian day number is in elapsed days since midnight
- * (Coordinated Universal Time) on November 17, 1858 CE (in the
- * Gregorian calendar).
+ * Date.strptime('1999-12-31', '%Y-%m-%d') # => #<Date: 1999-12-31>
+ * Date.strptime('31-12-1999', '%d-%m-%Y') # => #<Date: 1999-12-31>
+ * Date.strptime('1999-365', '%Y-%j') # => #<Date: 1999-12-31>
+ * Date.strptime('1999-W52-5', '%G-W%V-%u') # => #<Date: 1999-12-31>
+ * Date.strptime('1999 52 5', '%Y %U %w') # => #<Date: 1999-12-31>
+ * Date.strptime('1999 52 5', '%Y %W %u') # => #<Date: 1999-12-31>
+ * Date.strptime('fri31dec99', '%a%d%b%y') # => #<Date: 1999-12-31>
*
- * In this document, the astronomical modified Julian day number is
- * the same as the original modified Julian day number. And the
- * chronological modified Julian day number is a variation of the
- * modified Julian day number. Its days begin at midnight on local
- * time.
+ * See also the specialized methods in
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
*
- * In this document, when the term "modified Julian day number" simply
- * appears, it just refers to "chronological modified Julian day
- * number", not the original.
- *
- * In those classes, those are so-called "amjd" and "mjd".
- *
- * == Date
- *
- * A subclass of Object that includes the Comparable module and
- * easily handles date.
- *
- * A Date object is created with Date::new, Date::jd, Date::ordinal,
- * Date::commercial, Date::parse, Date::strptime, Date::today,
- * Time#to_date, etc.
- *
- * require 'date'
+ * == Argument +limit+
*
- * Date.new(2001,2,3)
- * #=> #<Date: 2001-02-03 ...>
- * Date.jd(2451944)
- * #=> #<Date: 2001-02-03 ...>
- * Date.ordinal(2001,34)
- * #=> #<Date: 2001-02-03 ...>
- * Date.commercial(2001,5,6)
- * #=> #<Date: 2001-02-03 ...>
- * Date.parse('2001-02-03')
- * #=> #<Date: 2001-02-03 ...>
- * Date.strptime('03-02-2001', '%d-%m-%Y')
- * #=> #<Date: 2001-02-03 ...>
- * Time.new(2001,2,3).to_date
- * #=> #<Date: 2001-02-03 ...>
+ * Certain singleton methods in \Date that parse string arguments
+ * also take optional keyword argument +limit+,
+ * which can limit the length of the string argument.
*
- * All date objects are immutable; hence cannot modify themselves.
+ * When +limit+ is:
*
- * The concept of a date object can be represented as a tuple
- * of the day count, the offset and the day of calendar reform.
- *
- * The day count denotes the absolute position of a temporal
- * dimension. The offset is relative adjustment, which determines
- * decoded local time with the day count. The day of calendar
- * reform denotes the start day of the new style. The old style
- * of the West is the Julian calendar which was adopted by
- * Caesar. The new style is the Gregorian calendar, which is the
- * current civil calendar of many countries.
- *
- * The day count is virtually the astronomical Julian day number.
- * The offset in this class is usually zero, and cannot be
- * specified directly.
- *
- * A Date object can be created with an optional argument,
- * the day of calendar reform as a Julian day number, which
- * should be 2298874 to 2426355 or negative/positive infinity.
- * The default value is +Date::ITALY+ (2299161=1582-10-15).
- * See also sample/cal.rb.
- *
- * $ ruby sample/cal.rb -c it 10 1582
- * October 1582
- * S M Tu W Th F S
- * 1 2 3 4 15 16
- * 17 18 19 20 21 22 23
- * 24 25 26 27 28 29 30
- * 31
- *
- * $ ruby sample/cal.rb -c gb 9 1752
- * September 1752
- * S M Tu W Th F S
- * 1 2 14 15 16
- * 17 18 19 20 21 22 23
- * 24 25 26 27 28 29 30
- *
- * A Date object has various methods. See each reference.
- *
- * d = Date.parse('3rd Feb 2001')
- * #=> #<Date: 2001-02-03 ...>
- * d.year #=> 2001
- * d.mon #=> 2
- * d.mday #=> 3
- * d.wday #=> 6
- * d += 1 #=> #<Date: 2001-02-04 ...>
- * d.strftime('%a %d %b %Y') #=> "Sun 04 Feb 2001"
+ * - Non-negative:
+ * raises ArgumentError if the string length is greater than _limit_.
+ * - Other numeric or +nil+: ignores +limit+.
+ * - Other non-numeric: raises TypeError.
*
*/
cDate = rb_define_class("Date", rb_cObject);
+
+ /* Exception for invalid date/time */
eDateError = rb_define_class_under(cDate, "Error", rb_eArgError);
rb_include_module(cDate, rb_mComparable);
@@ -9403,19 +9719,19 @@ Init_date_core(void)
rb_define_singleton_method(cDate, "strptime", date_s_strptime, -1);
rb_define_singleton_method(cDate, "_parse", date_s__parse, -1);
rb_define_singleton_method(cDate, "parse", date_s_parse, -1);
- rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, 1);
+ rb_define_singleton_method(cDate, "_iso8601", date_s__iso8601, -1);
rb_define_singleton_method(cDate, "iso8601", date_s_iso8601, -1);
- rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, 1);
+ rb_define_singleton_method(cDate, "_rfc3339", date_s__rfc3339, -1);
rb_define_singleton_method(cDate, "rfc3339", date_s_rfc3339, -1);
- rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, 1);
+ rb_define_singleton_method(cDate, "_xmlschema", date_s__xmlschema, -1);
rb_define_singleton_method(cDate, "xmlschema", date_s_xmlschema, -1);
- rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, 1);
- rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, 1);
+ rb_define_singleton_method(cDate, "_rfc2822", date_s__rfc2822, -1);
+ rb_define_singleton_method(cDate, "_rfc822", date_s__rfc2822, -1);
rb_define_singleton_method(cDate, "rfc2822", date_s_rfc2822, -1);
rb_define_singleton_method(cDate, "rfc822", date_s_rfc2822, -1);
- rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, 1);
+ rb_define_singleton_method(cDate, "_httpdate", date_s__httpdate, -1);
rb_define_singleton_method(cDate, "httpdate", date_s_httpdate, -1);
- rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, 1);
+ rb_define_singleton_method(cDate, "_jisx0301", date_s__jisx0301, -1);
rb_define_singleton_method(cDate, "jisx0301", date_s_jisx0301, -1);
rb_define_method(cDate, "initialize", date_initialize, -1);
@@ -9522,6 +9838,8 @@ Init_date_core(void)
rb_define_method(cDate, "httpdate", d_lite_httpdate, 0);
rb_define_method(cDate, "jisx0301", d_lite_jisx0301, 0);
+ rb_define_method(cDate, "deconstruct_keys", d_lite_deconstruct_keys, 1);
+
#ifndef NDEBUG
rb_define_method(cDate, "marshal_dump_old", d_lite_marshal_dump_old, 0);
#endif
@@ -9732,6 +10050,8 @@ Init_date_core(void)
rb_define_method(cDateTime, "rfc3339", dt_lite_rfc3339, -1);
rb_define_method(cDateTime, "jisx0301", dt_lite_jisx0301, -1);
+ rb_define_method(cDateTime, "deconstruct_keys", dt_lite_deconstruct_keys, 1);
+
/* conversions */
rb_define_method(rb_cTime, "to_time", time_to_time, 0);
diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c
index 5fa036ed72..c6f26ecb91 100644
--- a/ext/date/date_parse.c
+++ b/ext/date/date_parse.c
@@ -253,6 +253,8 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"
+#define NUMBER "(?<!\\d)\\d"
+
#ifdef TIGHT_PARSER
#define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
#define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
@@ -411,7 +413,6 @@ VALUE
date_zone_to_diff(VALUE str)
{
VALUE offset = Qnil;
- VALUE vbuf = 0;
long l = RSTRING_LEN(str);
const char *s = RSTRING_PTR(str);
@@ -437,16 +438,26 @@ date_zone_to_diff(VALUE str)
l -= w;
dst = 1;
}
+
{
+ const char *zn = s;
long sl = shrunk_size(s, l);
+ char shrunk_buff[MAX_WORD_LENGTH]; /* no terminator to be added */
+ const struct zone *z = 0;
+
+ if (sl <= 0) {
+ sl = l;
+ }
+ else if (sl <= MAX_WORD_LENGTH) {
+ char *d = shrunk_buff;
+ sl = shrink_space(d, s, l);
+ zn = d;
+ }
+
if (sl > 0 && sl <= MAX_WORD_LENGTH) {
- char *d = ALLOCV_N(char, vbuf, sl);
- l = shrink_space(d, s, l);
- s = d;
+ z = zonetab(zn, (unsigned int)sl);
}
- }
- if (l > 0 && l <= MAX_WORD_LENGTH) {
- const struct zone *z = zonetab(s, (unsigned int)l);
+
if (z) {
int d = z->offset;
if (dst)
@@ -455,6 +466,7 @@ date_zone_to_diff(VALUE str)
goto ok;
}
}
+
{
char *p;
int sign = 0;
@@ -471,27 +483,53 @@ date_zone_to_diff(VALUE str)
s++;
l--;
+#define out_of_range(v, min, max) ((v) < (min) || (max) < (v))
hour = STRTOUL(s, &p, 10);
if (*p == ':') {
+ if (out_of_range(hour, 0, 23)) return Qnil;
s = ++p;
min = STRTOUL(s, &p, 10);
+ if (out_of_range(min, 0, 59)) return Qnil;
if (*p == ':') {
s = ++p;
sec = STRTOUL(s, &p, 10);
+ if (out_of_range(sec, 0, 59)) return Qnil;
}
- goto num;
}
- if (*p == ',' || *p == '.') {
- char *e = 0;
- p++;
- min = STRTOUL(p, &e, 10) * 3600;
+ else if (*p == ',' || *p == '.') {
+ /* fractional hour */
+ size_t n;
+ int ov;
+ /* no over precision for offset; 10**-7 hour = 0.36
+ * milliseconds should be enough. */
+ const size_t max_digits = 7; /* 36 * 10**7 < 32-bit FIXNUM_MAX */
+
+ if (out_of_range(hour, 0, 23)) return Qnil;
+
+ n = (s + l) - ++p;
+ if (n > max_digits) n = max_digits;
+ sec = ruby_scan_digits(p, n, 10, &n, &ov);
+ if ((p += n) < s + l && *p >= ('5' + !(sec & 1)) && *p <= '9') {
+ /* round half to even */
+ sec++;
+ }
+ sec *= 36;
if (sign) {
hour = -hour;
- min = -min;
+ sec = -sec;
+ }
+ if (n <= 2) {
+ /* HH.nn or HH.n */
+ if (n == 1) sec *= 10;
+ offset = INT2FIX(sec + hour * 3600);
+ }
+ else {
+ VALUE denom = rb_int_positive_pow(10, (int)(n - 2));
+ offset = f_add(rb_rational_new(INT2FIX(sec), denom), INT2FIX(hour * 3600));
+ if (rb_rational_den(offset) == INT2FIX(1)) {
+ offset = rb_rational_num(offset);
+ }
}
- offset = rb_rational_new(INT2FIX(min),
- rb_int_positive_pow(10, (int)(e - p)));
- offset = f_add(INT2FIX(hour * 3600), offset);
goto ok;
}
else if (l > 2) {
@@ -504,18 +542,16 @@ date_zone_to_diff(VALUE str)
min = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov);
if (l >= 5)
sec = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov);
- goto num;
}
- num:
sec += min * 60 + hour * 3600;
if (sign) sec = -sec;
offset = INT2FIX(sec);
+#undef out_of_range
}
}
}
RB_GC_GUARD(str);
ok:
- ALLOCV_END(vbuf);
return offset;
}
@@ -652,24 +688,27 @@ parse_time(VALUE str, VALUE hash)
{
static const char pat_source[] =
"("
+ "" NUMBER "+\\s*"
"(?:"
- "\\d+\\s*:\\s*\\d+"
"(?:"
+ ":\\s*\\d+"
+ "(?:"
#ifndef TIGHT_PARSER
- "\\s*:\\s*\\d+(?:[,.]\\d*)?"
+ "\\s*:\\s*\\d+(?:[,.]\\d*)?"
#else
- "\\s*:\\s*\\d+(?:[,.]\\d+)?"
+ "\\s*:\\s*\\d+(?:[,.]\\d+)?"
#endif
+ ")?"
+ "|"
+ "h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
+ ")"
+ "(?:"
+ "\\s*"
+ "[ap](?:m\\b|\\.m\\.)"
")?"
"|"
- "\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
- ")"
- "(?:"
- "\\s*"
"[ap](?:m\\b|\\.m\\.)"
- ")?"
- "|"
- "\\d+\\s*[ap](?:m\\b|\\.m\\.)"
+ ")"
")"
"(?:"
"\\s*"
@@ -691,6 +730,9 @@ parse_time(VALUE str, VALUE hash)
#endif
}
+#define BEGIN_ERA "\\b"
+#define END_ERA "(?!(?<!\\.)[a-z])"
+
#ifdef TIGHT_PARSER
static int
parse_era1_cb(VALUE m, VALUE hash)
@@ -702,7 +744,7 @@ static int
parse_era1(VALUE str, VALUE hash)
{
static const char pat_source[] =
- "(a(?:d|\\.d\\.))";
+ BEGIN_ERA "(a(?:d\\b|\\.d\\.))" END_ERA;
static VALUE pat = Qnil;
REGCOMP_I(pat);
@@ -724,8 +766,9 @@ parse_era2_cb(VALUE m, VALUE hash)
static int
parse_era2(VALUE str, VALUE hash)
{
- static const char pat_source[] =
- "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))";
+ static const char pat_source[] = BEGIN_ERA
+ "(c(?:e\\b|\\.e\\.)|b(?:ce\\b|\\.c\\.e\\.)|b(?:c\\b|\\.c\\.))"
+ END_ERA;
static VALUE pat = Qnil;
REGCOMP_I(pat);
@@ -829,7 +872,7 @@ parse_eu(VALUE str, VALUE hash)
FPW_COM FPT_COM
#endif
#ifndef TIGHT_PARSER
- "('?\\d+)[^-\\d\\s]*"
+ "('?" NUMBER "+)[^-\\d\\s]*"
#else
"(\\d+)(?:(?:st|nd|rd|th)\\b)?"
#endif
@@ -842,7 +885,11 @@ parse_eu(VALUE str, VALUE hash)
"(?:"
"\\s*"
#ifndef TIGHT_PARSER
- "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
+ "(?:"
+ BEGIN_ERA
+ "(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))"
+ END_ERA
+ ")?"
"\\s*"
"('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
#else
@@ -919,8 +966,8 @@ parse_us(VALUE str, VALUE hash)
COM_FPT
#endif
"(?:"
- "\\s*,?"
- "\\s*"
+ "\\s*+,?"
+ "\\s*+"
#ifndef TIGHT_PARSER
"(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
"\\s*"
@@ -967,7 +1014,7 @@ parse_iso(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
- "('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"
+ "('?[-+]?" NUMBER "+)-(\\d+)-('?-?\\d+)"
#else
BOS
FPW_COM FPT_COM
@@ -1321,7 +1368,7 @@ parse_vms11(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
- "('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*"
+ "('?-?" NUMBER "+)-(" ABBR_MONTHS ")[^-/.]*"
"-('?-?\\d+)"
#else
BOS
@@ -1416,7 +1463,7 @@ parse_sla(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
- "('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
+ "('?-?" NUMBER "+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
#else
BOS
FPW_COM FPT_COM
@@ -1524,7 +1571,7 @@ parse_dot(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
- "('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
+ "('?-?" NUMBER "+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
#else
BOS
FPW_COM FPT_COM
@@ -1684,7 +1731,7 @@ parse_mday(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
- "(\\d+)(st|nd|rd|th)\\b"
+ "(" NUMBER "+)(st|nd|rd|th)\\b"
#else
BOS
FPW_COM FPT_COM
@@ -1922,7 +1969,7 @@ parse_ddd(VALUE str, VALUE hash)
#ifdef TIGHT_PARSER
BOS
#endif
- "([-+]?)(\\d{2,14})"
+ "([-+]?)(" NUMBER "{2,14})"
"(?:"
"\\s*"
"t?"
diff --git a/ext/date/date_strftime.c b/ext/date/date_strftime.c
index 9d8167b612..d7f28989d6 100644
--- a/ext/date/date_strftime.c
+++ b/ext/date/date_strftime.c
@@ -393,7 +393,7 @@ date_strftime_with_tmx(char *s, const size_t maxsize, const char *format,
continue;
case 'v':
- STRFTIME("%e-%b-%Y");
+ STRFTIME("%e-%^b-%Y");
continue;
case 'w': /* weekday, Sunday == 0, 0 - 6 */
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
index 7b06a31471..f731629df1 100644
--- a/ext/date/date_strptime.c
+++ b/ext/date/date_strptime.c
@@ -10,28 +10,15 @@
static const char *day_names[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
- "Sun", "Mon", "Tue", "Wed",
- "Thu", "Fri", "Sat"
};
+static const int ABBREVIATED_DAY_NAME_LENGTH = 3;
static const char *month_names[] = {
"January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December",
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-static const char *merid_names[] = {
- "am", "pm",
- "a.m.", "p.m."
-};
-
-static const char *extz_pats[] = {
- ":z",
- "::z",
- ":::z"
};
+static const int ABBREVIATED_MONTH_NAME_LENGTH = 3;
#define sizeof_array(o) (sizeof o / sizeof o[0])
@@ -75,7 +62,7 @@ num_pattern_p(const char *s)
#define NUM_PATTERN_P() num_pattern_p(&fmt[fi + 1])
static long
-read_digits(const char *s, VALUE *n, size_t width)
+read_digits(const char *s, size_t slen, VALUE *n, size_t width)
{
size_t l;
@@ -83,7 +70,7 @@ read_digits(const char *s, VALUE *n, size_t width)
return 0;
l = 0;
- while (ISDIGIT(s[l])) {
+ while (l < slen && ISDIGIT(s[l])) {
if (++l == width) break;
}
@@ -131,7 +118,7 @@ do { \
#define READ_DIGITS(n,w) \
do { \
size_t l; \
- l = read_digits(&str[si], &n, w); \
+ l = read_digits(&str[si], slen - si, &n, w); \
if (l == 0) \
fail(); \
si += l; \
@@ -161,6 +148,12 @@ do { \
VALUE date_zone_to_diff(VALUE);
+static inline int
+head_match_p(size_t len, const char *name, const char *str, size_t slen, size_t si)
+{
+ return slen - si >= len && strncasecmp(name, &str[si], len) == 0;
+}
+
static size_t
date__strptime_internal(const char *str, size_t slen,
const char *fmt, size_t flen, VALUE hash)
@@ -168,9 +161,18 @@ date__strptime_internal(const char *str, size_t slen,
size_t si, fi;
int c;
+#define HEAD_MATCH_P(len, name) head_match_p(len, name, str, slen, si)
si = fi = 0;
while (fi < flen) {
+ if (isspace((unsigned char)fmt[fi])) {
+ while (si < slen && isspace((unsigned char)str[si]))
+ si++;
+ while (++fi < flen && isspace((unsigned char)fmt[fi]));
+ continue;
+ }
+
+ if (si >= slen) fail();
switch (fmt[fi]) {
case '%':
@@ -194,12 +196,11 @@ date__strptime_internal(const char *str, size_t slen,
{
int i;
- for (i = 0; i < (int)sizeof_array(extz_pats); i++)
- if (strncmp(extz_pats[i], &fmt[fi],
- strlen(extz_pats[i])) == 0) {
- fi += i;
- goto again;
- }
+ for (i = 1; i < 3 && fi + i < flen && fmt[fi+i] == ':'; ++i);
+ if (fmt[fi+i] == 'z') {
+ fi += i - 1;
+ goto again;
+ }
fail();
}
@@ -209,10 +210,12 @@ date__strptime_internal(const char *str, size_t slen,
int i;
for (i = 0; i < (int)sizeof_array(day_names); i++) {
- size_t l = strlen(day_names[i]);
- if (strncasecmp(day_names[i], &str[si], l) == 0) {
+ const char *day_name = day_names[i];
+ size_t l = strlen(day_name);
+ if (HEAD_MATCH_P(l, day_name) ||
+ HEAD_MATCH_P(l = ABBREVIATED_DAY_NAME_LENGTH, day_name)) {
si += l;
- set_hash("wday", INT2FIX(i % 7));
+ set_hash("wday", INT2FIX(i));
goto matched;
}
}
@@ -225,10 +228,12 @@ date__strptime_internal(const char *str, size_t slen,
int i;
for (i = 0; i < (int)sizeof_array(month_names); i++) {
- size_t l = strlen(month_names[i]);
- if (strncasecmp(month_names[i], &str[si], l) == 0) {
+ const char *month_name = month_names[i];
+ size_t l = strlen(month_name);
+ if (HEAD_MATCH_P(l, month_name) ||
+ HEAD_MATCH_P(l = ABBREVIATED_MONTH_NAME_LENGTH, month_name)) {
si += l;
- set_hash("mon", INT2FIX((i % 12) + 1));
+ set_hash("mon", INT2FIX(i + 1));
goto matched;
}
}
@@ -402,18 +407,19 @@ date__strptime_internal(const char *str, size_t slen,
case 'P':
case 'p':
+ if (slen - si < 2) fail();
{
- int i;
-
- for (i = 0; i < 4; i++) {
- size_t l = strlen(merid_names[i]);
- if (strncasecmp(merid_names[i], &str[si], l) == 0) {
- si += l;
- set_hash("_merid", INT2FIX((i % 2) == 0 ? 0 : 12));
- goto matched;
- }
+ char c = str[si];
+ const int hour = (c == 'P' || c == 'p') ? 12 : 0;
+ if (!hour && !(c == 'A' || c == 'a')) fail();
+ if ((c = str[si+1]) == '.') {
+ if (slen - si < 4 || str[si+3] != '.') fail();
+ c = str[si += 2];
}
- fail();
+ if (!(c == 'M' || c == 'm')) fail();
+ si += 2;
+ set_hash("_merid", INT2FIX(hour));
+ goto matched;
}
case 'Q':
@@ -587,7 +593,7 @@ date__strptime_internal(const char *str, size_t slen,
b = rb_backref_get();
rb_match_busy(b);
- m = f_match(pat, rb_usascii_str_new2(&str[si]));
+ m = f_match(pat, rb_usascii_str_new(&str[si], slen - si));
if (!NIL_P(m)) {
VALUE s, l, o;
@@ -619,22 +625,13 @@ date__strptime_internal(const char *str, size_t slen,
if (str[si] != '%')
fail();
si++;
- if (fi < flen)
- if (str[si] != fmt[fi])
+ if (fi < flen) {
+ if (si >= slen || str[si] != fmt[fi])
fail();
- si++;
+ si++;
+ }
goto matched;
}
- case ' ':
- case '\t':
- case '\n':
- case '\v':
- case '\f':
- case '\r':
- while (isspace((unsigned char)str[si]))
- si++;
- fi++;
- break;
default:
ordinal:
if (str[si] != fmt[fi])
diff --git a/ext/date/depend b/ext/date/depend
index d89965fbef..3f550cd0a7 100644
--- a/ext/date/depend
+++ b/ext/date/depend
@@ -2,6 +2,20 @@
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/assert.h
+date_core.o: $(hdrdir)/ruby/backward.h
+date_core.o: $(hdrdir)/ruby/backward/2/assume.h
+date_core.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_core.o: $(hdrdir)/ruby/backward/2/bool.h
+date_core.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_core.o: $(hdrdir)/ruby/backward/2/limits.h
+date_core.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_core.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_core.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_core.o: $(hdrdir)/ruby/defines.h
+date_core.o: $(hdrdir)/ruby/encoding.h
+date_core.o: $(hdrdir)/ruby/intern.h
+date_core.o: $(hdrdir)/ruby/internal/abi.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
@@ -71,6 +85,15 @@ date_core.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
date_core.o: $(hdrdir)/ruby/internal/ctype.h
date_core.o: $(hdrdir)/ruby/internal/dllexport.h
date_core.o: $(hdrdir)/ruby/internal/dosish.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/re.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/string.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+date_core.o: $(hdrdir)/ruby/internal/encoding/transcode.h
date_core.o: $(hdrdir)/ruby/internal/error.h
date_core.o: $(hdrdir)/ruby/internal/eval.h
date_core.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
date_core.o: $(hdrdir)/ruby/missing.h
date_core.o: $(hdrdir)/ruby/onigmo.h
date_core.o: $(hdrdir)/ruby/oniguruma.h
@@ -167,6 +176,20 @@ 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/assert.h
+date_parse.o: $(hdrdir)/ruby/backward.h
+date_parse.o: $(hdrdir)/ruby/backward/2/assume.h
+date_parse.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_parse.o: $(hdrdir)/ruby/backward/2/bool.h
+date_parse.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_parse.o: $(hdrdir)/ruby/backward/2/limits.h
+date_parse.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_parse.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_parse.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_parse.o: $(hdrdir)/ruby/defines.h
+date_parse.o: $(hdrdir)/ruby/encoding.h
+date_parse.o: $(hdrdir)/ruby/intern.h
+date_parse.o: $(hdrdir)/ruby/internal/abi.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
@@ -237,6 +260,15 @@ date_parse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
date_parse.o: $(hdrdir)/ruby/internal/ctype.h
date_parse.o: $(hdrdir)/ruby/internal/dllexport.h
date_parse.o: $(hdrdir)/ruby/internal/dosish.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/re.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/string.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+date_parse.o: $(hdrdir)/ruby/internal/encoding/transcode.h
date_parse.o: $(hdrdir)/ruby/internal/error.h
date_parse.o: $(hdrdir)/ruby/internal/eval.h
date_parse.o: $(hdrdir)/ruby/internal/event.h
@@ -307,20 +339,6 @@ 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
date_parse.o: $(hdrdir)/ruby/missing.h
date_parse.o: $(hdrdir)/ruby/onigmo.h
date_parse.o: $(hdrdir)/ruby/oniguruma.h
@@ -334,6 +352,19 @@ 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/assert.h
+date_strftime.o: $(hdrdir)/ruby/backward.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/assume.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/bool.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/limits.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_strftime.o: $(hdrdir)/ruby/defines.h
+date_strftime.o: $(hdrdir)/ruby/intern.h
+date_strftime.o: $(hdrdir)/ruby/internal/abi.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
@@ -473,19 +504,6 @@ 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
date_strftime.o: $(hdrdir)/ruby/ruby.h
date_strftime.o: $(hdrdir)/ruby/st.h
@@ -495,6 +513,20 @@ 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/assert.h
+date_strptime.o: $(hdrdir)/ruby/backward.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/assume.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/bool.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/limits.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/stdarg.h
+date_strptime.o: $(hdrdir)/ruby/defines.h
+date_strptime.o: $(hdrdir)/ruby/encoding.h
+date_strptime.o: $(hdrdir)/ruby/intern.h
+date_strptime.o: $(hdrdir)/ruby/internal/abi.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
@@ -565,6 +597,15 @@ date_strptime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
date_strptime.o: $(hdrdir)/ruby/internal/ctype.h
date_strptime.o: $(hdrdir)/ruby/internal/dllexport.h
date_strptime.o: $(hdrdir)/ruby/internal/dosish.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/re.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/string.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+date_strptime.o: $(hdrdir)/ruby/internal/encoding/transcode.h
date_strptime.o: $(hdrdir)/ruby/internal/error.h
date_strptime.o: $(hdrdir)/ruby/internal/eval.h
date_strptime.o: $(hdrdir)/ruby/internal/event.h
@@ -635,20 +676,6 @@ 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
date_strptime.o: $(hdrdir)/ruby/missing.h
date_strptime.o: $(hdrdir)/ruby/onigmo.h
date_strptime.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/date/extconf.rb b/ext/date/extconf.rb
index 8938df13b3..358f64173a 100644
--- a/ext/date/extconf.rb
+++ b/ext/date/extconf.rb
@@ -3,7 +3,10 @@ require 'mkmf'
config_string("strict_warnflags") {|w| $warnflags += " #{w}"}
-have_var("timezone", "time.h")
-have_var("altzone", "time.h")
+have_func("rb_category_warn")
+with_werror("", {:werror => true}) do |opt, |
+ have_var("timezone", "time.h", opt)
+ have_var("altzone", "time.h", opt)
+end
create_makefile('date_core')
diff --git a/ext/date/lib/date.rb b/ext/date/lib/date.rb
index 4901219503..a9fe3ce4b0 100644
--- a/ext/date/lib/date.rb
+++ b/ext/date/lib/date.rb
@@ -4,7 +4,12 @@
require 'date_core'
class Date
+ VERSION = "3.3.3" # :nodoc:
+ # call-seq:
+ # infinite? -> false
+ #
+ # Returns +false+
def infinite?
false
end
diff --git a/ext/date/prereq.mk b/ext/date/prereq.mk
index eb71e55e71..cee7685975 100644
--- a/ext/date/prereq.mk
+++ b/ext/date/prereq.mk
@@ -10,3 +10,10 @@ zonetab.h: zonetab.list
.PHONY: update-zonetab
update-zonetab:
$(RUBY) -C $(srcdir) update-abbr
+
+.PHONY: update-nothing
+update-nothing:
+
+update = nothing
+
+zonetab.list: update-$(update)
diff --git a/ext/date/zonetab.h b/ext/date/zonetab.h
index 379f78e1b8..7ced9e0308 100644
--- a/ext/date/zonetab.h
+++ b/ext/date/zonetab.h
@@ -36,7 +36,7 @@ struct zone {
int name;
int offset;
};
-static const struct zone *zonetab();
+static const struct zone *zonetab(register const char *str, register size_t len);
#line 9 "zonetab.list"
struct zone;
@@ -49,7 +49,7 @@ struct zone;
#ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1
-static unsigned char gperf_downcase[256] =
+static const unsigned char gperf_downcase[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
@@ -846,7 +846,7 @@ zonetab (register const char *str, register size_t len)
{gperf_offsetof(stringpool, 22), 3*3600},
{-1},
#line 101 "zonetab.list"
- {gperf_offsetof(stringpool, 24),10*3600},
+ {gperf_offsetof(stringpool, 24),-6*3600},
#line 217 "zonetab.list"
{gperf_offsetof(stringpool, 25),-18000},
#line 19 "zonetab.list"
@@ -875,7 +875,7 @@ zonetab (register const char *str, register size_t len)
#line 79 "zonetab.list"
{gperf_offsetof(stringpool, 38), 2*3600},
#line 65 "zonetab.list"
- {gperf_offsetof(stringpool, 39),-10*3600},
+ {gperf_offsetof(stringpool, 39),2*3600},
{-1},
#line 202 "zonetab.list"
{gperf_offsetof(stringpool, 41),28800},
@@ -998,7 +998,7 @@ zonetab (register const char *str, register size_t len)
#line 148 "zonetab.list"
{gperf_offsetof(stringpool, 107), -25200},
#line 96 "zonetab.list"
- {gperf_offsetof(stringpool, 108), 8*3600},
+ {gperf_offsetof(stringpool, 108), (6*3600+1800)},
#line 42 "zonetab.list"
{gperf_offsetof(stringpool, 109), -10*3600},
#line 31 "zonetab.list"
@@ -1017,11 +1017,11 @@ zonetab (register const char *str, register size_t len)
{gperf_offsetof(stringpool, 117), 1*3600},
{-1},
#line 95 "zonetab.list"
- {gperf_offsetof(stringpool, 119), 7*3600},
+ {gperf_offsetof(stringpool, 119), 2*3600},
#line 313 "zonetab.list"
{gperf_offsetof(stringpool, 120),43200},
#line 55 "zonetab.list"
- {gperf_offsetof(stringpool, 121), -(3*3600+1800)},
+ {gperf_offsetof(stringpool, 121), -(2*3600+1800)},
#line 184 "zonetab.list"
{gperf_offsetof(stringpool, 122),31500},
#line 204 "zonetab.list"
@@ -1168,7 +1168,7 @@ zonetab (register const char *str, register size_t len)
#line 299 "zonetab.list"
{gperf_offsetof(stringpool, 206),50400},
#line 85 "zonetab.list"
- {gperf_offsetof(stringpool, 207), 2*3600},
+ {gperf_offsetof(stringpool, 207), -11*3600},
{-1},
#line 142 "zonetab.list"
{gperf_offsetof(stringpool, 209), 19800},
@@ -1371,7 +1371,7 @@ zonetab (register const char *str, register size_t len)
{gperf_offsetof(stringpool, 324), 8*3600},
{-1},
#line 50 "zonetab.list"
- {gperf_offsetof(stringpool, 326), -(2*3600+1800)},
+ {gperf_offsetof(stringpool, 326), -(1*3600+1800)},
#line 285 "zonetab.list"
{gperf_offsetof(stringpool, 327),-10800},
{-1}, {-1},
diff --git a/ext/date/zonetab.list b/ext/date/zonetab.list
index d2f902d2d5..748aec1d8a 100644
--- a/ext/date/zonetab.list
+++ b/ext/date/zonetab.list
@@ -3,7 +3,7 @@ struct zone {
int name;
int offset;
};
-static const struct zone *zonetab();
+static const struct zone *zonetab(register const char *str, register size_t len);
%}
struct zone;
diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c
index 6557e43c9d..358ab416b9 100644
--- a/ext/digest/bubblebabble/bubblebabble.c
+++ b/ext/digest/bubblebabble/bubblebabble.c
@@ -37,7 +37,7 @@ bubblebabble_str_new(VALUE str_digest)
digest_len = RSTRING_LEN(str_digest);
if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
- rb_raise(rb_eRuntimeError, "digest string too long");
+ rb_raise(rb_eRuntimeError, "digest string too long");
}
str = rb_str_new(0, (digest_len | 1) * 3 + 2);
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
index b995438236..38f5ddb1e2 100644
--- a/ext/digest/bubblebabble/depend
+++ b/ext/digest/bubblebabble/depend
@@ -2,6 +2,19 @@
bubblebabble.o: $(RUBY_EXTCONF_H)
bubblebabble.o: $(arch_hdrdir)/ruby/config.h
bubblebabble.o: $(hdrdir)/ruby.h
+bubblebabble.o: $(hdrdir)/ruby/assert.h
+bubblebabble.o: $(hdrdir)/ruby/backward.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/assume.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/attributes.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/bool.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/limits.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/long_long.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bubblebabble.o: $(hdrdir)/ruby/defines.h
+bubblebabble.o: $(hdrdir)/ruby/intern.h
+bubblebabble.o: $(hdrdir)/ruby/internal/abi.h
bubblebabble.o: $(hdrdir)/ruby/internal/anyargs.h
bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic.h
bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
bubblebabble.o: $(hdrdir)/ruby/ruby.h
bubblebabble.o: $(hdrdir)/ruby/st.h
diff --git a/ext/digest/depend b/ext/digest/depend
index 856f9caa68..5a84fd53ec 100644
--- a/ext/digest/depend
+++ b/ext/digest/depend
@@ -2,6 +2,19 @@
digest.o: $(RUBY_EXTCONF_H)
digest.o: $(arch_hdrdir)/ruby/config.h
digest.o: $(hdrdir)/ruby.h
+digest.o: $(hdrdir)/ruby/assert.h
+digest.o: $(hdrdir)/ruby/backward.h
+digest.o: $(hdrdir)/ruby/backward/2/assume.h
+digest.o: $(hdrdir)/ruby/backward/2/attributes.h
+digest.o: $(hdrdir)/ruby/backward/2/bool.h
+digest.o: $(hdrdir)/ruby/backward/2/inttypes.h
+digest.o: $(hdrdir)/ruby/backward/2/limits.h
+digest.o: $(hdrdir)/ruby/backward/2/long_long.h
+digest.o: $(hdrdir)/ruby/backward/2/stdalign.h
+digest.o: $(hdrdir)/ruby/backward/2/stdarg.h
+digest.o: $(hdrdir)/ruby/defines.h
+digest.o: $(hdrdir)/ruby/intern.h
+digest.o: $(hdrdir)/ruby/internal/abi.h
digest.o: $(hdrdir)/ruby/internal/anyargs.h
digest.o: $(hdrdir)/ruby/internal/arithmetic.h
digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
digest.o: $(hdrdir)/ruby/ruby.h
digest.o: $(hdrdir)/ruby/st.h
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index 83f4ee42fc..68837a674c 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -154,7 +154,7 @@ static void
rb_digest_instance_method_unimpl(VALUE self, const char *method)
{
rb_raise(rb_eRuntimeError, "%s does not implement %s()",
- rb_obj_classname(self), method);
+ rb_obj_classname(self), method);
}
/*
@@ -383,8 +383,8 @@ rb_digest_instance_equal(VALUE self, VALUE other)
StringValue(str2);
if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
- rb_str_cmp(str1, str2) == 0) {
- return Qtrue;
+ rb_str_cmp(str1, str2) == 0) {
+ return Qtrue;
}
return Qfalse;
}
@@ -602,7 +602,7 @@ static inline void
algo_init(const rb_digest_metadata_t *algo, void *pctx)
{
if (algo->init_func(pctx) != 1) {
- rb_raise(rb_eRuntimeError, "Digest initialization failed.");
+ rb_raise(rb_eRuntimeError, "Digest initialization failed.");
}
}
@@ -614,7 +614,7 @@ rb_digest_base_alloc(VALUE klass)
void *pctx;
if (klass == rb_cDigest_Base) {
- rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
}
algo = get_digest_base_metadata(klass);
@@ -639,7 +639,7 @@ rb_digest_base_copy(VALUE copy, VALUE obj)
algo = get_digest_obj_metadata(copy);
if (algo != get_digest_obj_metadata(obj))
- rb_raise(rb_eTypeError, "different algorithms");
+ rb_raise(rb_eTypeError, "different algorithms");
TypedData_Get_Struct(obj, void, &digest_type, pctx1);
TypedData_Get_Struct(copy, void, &digest_type, pctx2);
diff --git a/ext/digest/digest.gemspec b/ext/digest/digest.gemspec
index 8665e42e0f..4a01c5fde1 100644
--- a/ext/digest/digest.gemspec
+++ b/ext/digest/digest.gemspec
@@ -2,8 +2,13 @@
# frozen_string_literal: true
Gem::Specification.new do |spec|
+ version_module = Module.new do
+ version_rb = File.join(__dir__, "lib/digest/version.rb")
+ module_eval(File.read(version_rb), version_rb)
+ end
+
spec.name = "digest"
- spec.version = "3.0.1.pre"
+ spec.version = version_module::Digest::VERSION
spec.authors = ["Akinori MUSHA"]
spec.email = ["knu@idaemons.org"]
@@ -12,32 +17,28 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/ruby/digest"
spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [
- "LICENSE.txt", "README.md",
- "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.files = [
+ "LICENSE.txt",
+ "README.md",
+ *Dir["lib/digest{.rb,/**/*.rb}"],
]
spec.required_ruby_version = ">= 2.5.0"
spec.bindir = "exe"
spec.executables = []
- 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
- ]
+
+ if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
+ spec.platform = 'java'
+
+ spec.files += Dir["ext/java/**/*.{rb,java}", "lib/digest.jar"]
+ spec.require_paths = %w[lib ext/java/org/jruby/ext/digest/lib]
+ else
+ spec.extensions = Dir["ext/digest/**/extconf.rb"]
+
+ spec.files += Dir["ext/digest/**/{*.{rb,c,h,sh},depend}"]
+ spec.require_paths = %w[lib]
+ end
+
spec.metadata["msys2_mingw_dependencies"] = "openssl"
end
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 0d4f0e7cc2..8a4c5b7e4e 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -38,7 +38,7 @@ rb_digest_##name##_update(void *ctx, unsigned char *ptr, size_t size) \
const unsigned int stride = 16384; \
\
for (; size > stride; size -= stride, ptr += stride) { \
- name##_Update(ctx, ptr, stride); \
+ name##_Update(ctx, ptr, stride); \
} \
if (size > 0) name##_Update(ctx, ptr, size); \
}
diff --git a/ext/digest/digest_conf.rb b/ext/digest/digest_conf.rb
index 1b929d8732..36a7d75289 100644
--- a/ext/digest/digest_conf.rb
+++ b/ext/digest/digest_conf.rb
@@ -3,7 +3,7 @@
def digest_conf(name)
unless with_config("bundled-#{name}")
cc = with_config("common-digest")
- if cc == true or /\b#{name}\b/ =~ cc
+ if cc != false or /\b#{name}\b/ =~ cc
if File.exist?("#$srcdir/#{name}cc.h") and
have_header("CommonCrypto/CommonDigest.h")
$defs << "-D#{name.upcase}_USE_COMMONDIGEST"
diff --git a/ext/digest/extconf.rb b/ext/digest/extconf.rb
index a8c68850a2..0e5f08d794 100644
--- a/ext/digest/extconf.rb
+++ b/ext/digest/extconf.rb
@@ -6,6 +6,6 @@ require "mkmf"
$INSTALLFILES = {
"digest.h" => "$(HDRDIR)"
-}
+} if $extmk
create_makefile("digest")
diff --git a/ext/digest/lib/digest.rb b/ext/digest/lib/digest.rb
index ba0637af32..e995adb450 100644
--- a/ext/digest/lib/digest.rb
+++ b/ext/digest/lib/digest.rb
@@ -1,5 +1,19 @@
# frozen_string_literal: false
-require 'digest.so'
+
+if defined?(Digest) &&
+ /\A(?:2\.|3\.0\.[0-2]\z)/.match?(RUBY_VERSION) &&
+ caller_locations.any? { |l|
+ %r{/(rubygems/gem_runner|bundler/cli)\.rb}.match?(l.path)
+ }
+ # Before Ruby 3.0.3/3.1.0, the gem and bundle commands used to load
+ # the digest library before loading additionally installed gems, so
+ # you will get constant redefinition warnings and unexpected
+ # implementation overwriting if we proceed here. Avoid that.
+ return
+end
+
+require 'digest/version'
+require 'digest/loader'
module Digest
# A mutex for Digest().
@@ -8,7 +22,7 @@ module Digest
def self.const_missing(name) # :nodoc:
case name
when :SHA256, :SHA384, :SHA512
- lib = 'digest/sha2.so'
+ lib = 'digest/sha2'
else
lib = File.join('digest', name.to_s.downcase)
end
diff --git a/ext/digest/lib/digest/loader.rb b/ext/digest/lib/digest/loader.rb
new file mode 100644
index 0000000000..6b989e07be
--- /dev/null
+++ b/ext/digest/lib/digest/loader.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require 'digest.so'
diff --git a/ext/digest/lib/digest/version.rb b/ext/digest/lib/digest/version.rb
new file mode 100644
index 0000000000..42fd7acf6e
--- /dev/null
+++ b/ext/digest/lib/digest/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module Digest
+ VERSION = "3.1.1"
+end
diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend
index 258ec88e54..ea1ceec7fd 100644
--- a/ext/digest/md5/depend
+++ b/ext/digest/md5/depend
@@ -10,7 +10,6 @@ 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
@@ -18,6 +17,7 @@ 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/abi.h
md5.o: $(hdrdir)/ruby/internal/anyargs.h
md5.o: $(hdrdir)/ruby/internal/arithmetic.h
md5.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -172,7 +172,6 @@ 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
@@ -180,6 +179,7 @@ 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/abi.h
md5init.o: $(hdrdir)/ruby/internal/anyargs.h
md5init.o: $(hdrdir)/ruby/internal/arithmetic.h
md5init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -326,5 +326,6 @@ md5init.o: $(hdrdir)/ruby/subst.h
md5init.o: $(srcdir)/../defs.h
md5init.o: $(srcdir)/../digest.h
md5init.o: md5.h
+md5init.o: md5cc.h
md5init.o: md5init.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/md5/md5.c b/ext/digest/md5/md5.c
index 19fe54a693..3a7fe2cdad 100644
--- a/ext/digest/md5/md5.c
+++ b/ext/digest/md5/md5.c
@@ -225,7 +225,7 @@ md5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/)
uint32_t xbuf[16];
const uint32_t *X;
- if (!((data - (const uint8_t *)0) & 3)) {
+ if (!(((uintptr_t)data) & 3)) {
/* data are properly aligned */
X = (const uint32_t *)data;
} else {
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index 8a7f555754..3a0ed72732 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -10,7 +10,6 @@ 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
@@ -18,6 +17,7 @@ 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/abi.h
rmd160.o: $(hdrdir)/ruby/internal/anyargs.h
rmd160.o: $(hdrdir)/ruby/internal/arithmetic.h
rmd160.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -172,7 +172,6 @@ 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
@@ -180,6 +179,7 @@ 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/abi.h
rmd160init.o: $(hdrdir)/ruby/internal/anyargs.h
rmd160init.o: $(hdrdir)/ruby/internal/arithmetic.h
rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index 055e1fbaa0..48aaef158b 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -10,7 +10,6 @@ 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
@@ -18,6 +17,7 @@ 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/abi.h
sha1.o: $(hdrdir)/ruby/internal/anyargs.h
sha1.o: $(hdrdir)/ruby/internal/arithmetic.h
sha1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -172,7 +172,6 @@ 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
@@ -180,6 +179,7 @@ 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/abi.h
sha1init.o: $(hdrdir)/ruby/internal/anyargs.h
sha1init.o: $(hdrdir)/ruby/internal/arithmetic.h
sha1init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -326,5 +326,6 @@ sha1init.o: $(hdrdir)/ruby/subst.h
sha1init.o: $(srcdir)/../defs.h
sha1init.o: $(srcdir)/../digest.h
sha1init.o: sha1.h
+sha1init.o: sha1cc.h
sha1init.o: sha1init.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index c3399e76f5..47a859068c 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -10,7 +10,6 @@ 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
@@ -18,6 +17,7 @@ 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/abi.h
sha2.o: $(hdrdir)/ruby/internal/anyargs.h
sha2.o: $(hdrdir)/ruby/internal/arithmetic.h
sha2.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -172,7 +172,6 @@ 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
@@ -180,6 +179,7 @@ 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/abi.h
sha2init.o: $(hdrdir)/ruby/internal/anyargs.h
sha2init.o: $(hdrdir)/ruby/internal/arithmetic.h
sha2init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -325,5 +325,6 @@ sha2init.o: $(hdrdir)/ruby/st.h
sha2init.o: $(hdrdir)/ruby/subst.h
sha2init.o: $(srcdir)/../digest.h
sha2init.o: sha2.h
+sha2init.o: sha2cc.h
sha2init.o: sha2init.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/sha2/lib/sha2.rb b/ext/digest/sha2/lib/sha2.rb
index 61a0734850..f17593a206 100644
--- a/ext/digest/sha2/lib/sha2.rb
+++ b/ext/digest/sha2/lib/sha2.rb
@@ -11,7 +11,7 @@
# $Id$
require 'digest'
-require 'digest/sha2.so'
+require 'digest/sha2/loader'
module Digest
#
diff --git a/ext/digest/sha2/lib/sha2/loader.rb b/ext/digest/sha2/lib/sha2/loader.rb
new file mode 100644
index 0000000000..7d6d04a59c
--- /dev/null
+++ b/ext/digest/sha2/lib/sha2/loader.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require 'digest/sha2.so'
diff --git a/ext/digest/sha2/sha2.c b/ext/digest/sha2/sha2.c
index e7d7b15c5b..21d5acbe96 100644
--- a/ext/digest/sha2/sha2.c
+++ b/ext/digest/sha2/sha2.c
@@ -128,7 +128,7 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
-#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__) || defined(_HPUX_SOURCE) || defined(__IBMC__)
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__) || defined(__IBMC__)
#define ULL(number) number##ULL
#else
#define ULL(number) (uint64_t)(number)
diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c
index 6ed275eb71..94cccf3feb 100644
--- a/ext/digest/sha2/sha2init.c
+++ b/ext/digest/sha2/sha2init.c
@@ -47,7 +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, \
- rb_digest_make_metadata(&sha##bitlen));
+ rb_digest_make_metadata(&sha##bitlen));
FOREACH_BITLEN(DEFINE_ALGO_CLASS)
}
diff --git a/ext/erb/escape/escape.c b/ext/erb/escape/escape.c
new file mode 100644
index 0000000000..67b2d1ef34
--- /dev/null
+++ b/ext/erb/escape/escape.c
@@ -0,0 +1,95 @@
+#include "ruby.h"
+#include "ruby/encoding.h"
+
+static VALUE rb_cERB, rb_mEscape, rb_cCGI;
+static ID id_escapeHTML;
+
+#define HTML_ESCAPE_MAX_LEN 6
+
+static const struct {
+ uint8_t len;
+ char str[HTML_ESCAPE_MAX_LEN+1];
+} html_escape_table[UCHAR_MAX+1] = {
+#define HTML_ESCAPE(c, str) [c] = {rb_strlen_lit(str), str}
+ HTML_ESCAPE('\'', "&#39;"),
+ HTML_ESCAPE('&', "&amp;"),
+ HTML_ESCAPE('"', "&quot;"),
+ HTML_ESCAPE('<', "&lt;"),
+ HTML_ESCAPE('>', "&gt;"),
+#undef HTML_ESCAPE
+};
+
+static inline void
+preserve_original_state(VALUE orig, VALUE dest)
+{
+ rb_enc_associate(dest, rb_enc_get(orig));
+}
+
+static inline long
+escaped_length(VALUE str)
+{
+ const long len = RSTRING_LEN(str);
+ if (len >= LONG_MAX / HTML_ESCAPE_MAX_LEN) {
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
+ }
+ return len * HTML_ESCAPE_MAX_LEN;
+}
+
+static VALUE
+optimized_escape_html(VALUE str)
+{
+ VALUE vbuf;
+ char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
+ const char *cstr = RSTRING_PTR(str);
+ const char *end = cstr + RSTRING_LEN(str);
+
+ char *dest = buf;
+ while (cstr < end) {
+ const unsigned char c = *cstr++;
+ uint8_t len = html_escape_table[c].len;
+ if (len) {
+ memcpy(dest, html_escape_table[c].str, len);
+ dest += len;
+ }
+ else {
+ *dest++ = c;
+ }
+ }
+
+ VALUE escaped = str;
+ if (RSTRING_LEN(str) < (dest - buf)) {
+ escaped = rb_str_new(buf, dest - buf);
+ preserve_original_state(str, escaped);
+ }
+ ALLOCV_END(vbuf);
+ return escaped;
+}
+
+// ERB::Util.html_escape is different from CGI.escapeHTML in the following two parts:
+// * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING)
+// * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped
+static VALUE
+erb_escape_html(VALUE self, VALUE str)
+{
+ if (!RB_TYPE_P(str, T_STRING)) {
+ str = rb_convert_type(str, T_STRING, "String", "to_s");
+ }
+
+ if (rb_enc_str_asciicompat_p(str)) {
+ return optimized_escape_html(str);
+ }
+ else {
+ return rb_funcall(rb_cCGI, id_escapeHTML, 1, str);
+ }
+}
+
+void
+Init_escape(void)
+{
+ rb_cERB = rb_define_class("ERB", rb_cObject);
+ rb_mEscape = rb_define_module_under(rb_cERB, "Escape");
+ rb_define_module_function(rb_mEscape, "html_escape", erb_escape_html, 1);
+
+ rb_cCGI = rb_define_class("CGI", rb_cObject);
+ id_escapeHTML = rb_intern("escapeHTML");
+}
diff --git a/ext/erb/escape/extconf.rb b/ext/erb/escape/extconf.rb
new file mode 100644
index 0000000000..c1002548ad
--- /dev/null
+++ b/ext/erb/escape/extconf.rb
@@ -0,0 +1,7 @@
+require 'mkmf'
+
+if RUBY_ENGINE == 'truffleruby'
+ File.write('Makefile', dummy_makefile($srcdir).join)
+else
+ create_makefile 'erb/escape'
+end
diff --git a/ext/etc/depend b/ext/etc/depend
index a00f6c0508..a541db6db6 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -12,7 +12,6 @@ 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
@@ -21,6 +20,7 @@ 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/abi.h
etc.o: $(hdrdir)/ruby/internal/anyargs.h
etc.o: $(hdrdir)/ruby/internal/arithmetic.h
etc.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -90,6 +90,15 @@ etc.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
etc.o: $(hdrdir)/ruby/internal/ctype.h
etc.o: $(hdrdir)/ruby/internal/dllexport.h
etc.o: $(hdrdir)/ruby/internal/dosish.h
+etc.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+etc.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+etc.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+etc.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+etc.o: $(hdrdir)/ruby/internal/encoding/re.h
+etc.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+etc.o: $(hdrdir)/ruby/internal/encoding/string.h
+etc.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+etc.o: $(hdrdir)/ruby/internal/encoding/transcode.h
etc.o: $(hdrdir)/ruby/internal/error.h
etc.o: $(hdrdir)/ruby/internal/eval.h
etc.o: $(hdrdir)/ruby/internal/event.h
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 50f566d10f..6c7145b40b 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -47,12 +47,16 @@ static VALUE sGroup;
#define HAVE_UNAME 1
#endif
-#ifndef _WIN32
-char *getenv();
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
#endif
char *getlogin();
-#define RUBY_ETC_VERSION "1.2.0"
+#define RUBY_ETC_VERSION "1.4.2"
#ifdef HAVE_RB_DEPRECATE_CONSTANT
void rb_deprecate_constant(VALUE mod, const char *name);
@@ -190,7 +194,8 @@ setup_passwd(struct passwd *pwd)
/* call-seq:
* getpwuid(uid) -> Passwd
*
- * Returns the /etc/passwd information for the user with the given integer +uid+.
+ * Returns the <tt>/etc/passwd</tt> information for the user with the given
+ * integer +uid+.
*
* The information is returned as a Passwd struct.
*
@@ -229,8 +234,8 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj)
/* call-seq:
* getpwnam(name) -> Passwd
*
- * Returns the /etc/passwd information for the user with specified login
- * +name+.
+ * Returns the <tt>/etc/passwd</tt> information for the user with specified
+ * login +name+.
*
* The information is returned as a Passwd struct.
*
@@ -295,7 +300,7 @@ each_passwd(void)
* Etc.passwd -> Passwd
*
* Provides a convenient Ruby iterator which executes a block for each entry
- * in the /etc/passwd file.
+ * in the <tt>/etc/passwd</tt> file.
*
* The code block is passed an Passwd struct.
*
@@ -330,13 +335,14 @@ etc_passwd(VALUE obj)
* Etc::Passwd.each { |struct| block } -> Passwd
* Etc::Passwd.each -> Enumerator
*
- * Iterates for each entry in the /etc/passwd file if a block is given.
+ * Iterates for each entry in the <tt>/etc/passwd</tt> file if a block is
+ * given.
*
* If no block is given, returns the Enumerator.
*
* The code block is passed an Passwd struct.
*
- * See ::getpwent above for details.
+ * See Etc.getpwent above for details.
*
* Example:
*
@@ -360,8 +366,8 @@ etc_each_passwd(VALUE obj)
return obj;
}
-/* Resets the process of reading the /etc/passwd file, so that the next call
- * to ::getpwent will return the first entry again.
+/* Resets the process of reading the <tt>/etc/passwd</tt> file, so that the
+ * next call to ::getpwent will return the first entry again.
*/
static VALUE
etc_setpwent(VALUE obj)
@@ -372,8 +378,8 @@ etc_setpwent(VALUE obj)
return Qnil;
}
-/* Ends the process of scanning through the /etc/passwd file begun with
- * ::getpwent, and closes the file.
+/* Ends the process of scanning through the <tt>/etc/passwd</tt> file begun
+ * with ::getpwent, and closes the file.
*/
static VALUE
etc_endpwent(VALUE obj)
@@ -384,7 +390,7 @@ etc_endpwent(VALUE obj)
return Qnil;
}
-/* Returns an entry from the /etc/passwd file.
+/* Returns an entry from the <tt>/etc/passwd</tt> file.
*
* The first time it is called it opens the file and returns the first entry;
* each successive call returns the next entry, or +nil+ if the end of the file
@@ -435,7 +441,7 @@ setup_group(struct group *grp)
* getgrgid(group_id) -> Group
*
* Returns information about the group with specified integer +group_id+,
- * as found in /etc/group.
+ * as found in <tt>/etc/group</tt>.
*
* The information is returned as a Group struct.
*
@@ -473,7 +479,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj)
* getgrnam(name) -> Group
*
* Returns information about the group with specified +name+, as found in
- * /etc/group.
+ * <tt>/etc/group</tt>.
*
* The information is returned as a Group struct.
*
@@ -536,7 +542,7 @@ each_group(void)
#endif
/* Provides a convenient Ruby iterator which executes a block for each entry
- * in the /etc/group file.
+ * in the <tt>/etc/group</tt> file.
*
* The code block is passed an Group struct.
*
@@ -572,7 +578,8 @@ etc_group(VALUE obj)
* Etc::Group.each { |group| block } -> obj
* Etc::Group.each -> Enumerator
*
- * Iterates for each entry in the /etc/group file if a block is given.
+ * Iterates for each entry in the <tt>/etc/group</tt> file if a block is
+ * given.
*
* If no block is given, returns the Enumerator.
*
@@ -599,8 +606,8 @@ etc_each_group(VALUE obj)
}
#endif
-/* Resets the process of reading the /etc/group file, so that the next call
- * to ::getgrent will return the first entry again.
+/* Resets the process of reading the <tt>/etc/group</tt> file, so that the
+ * next call to ::getgrent will return the first entry again.
*/
static VALUE
etc_setgrent(VALUE obj)
@@ -611,8 +618,8 @@ etc_setgrent(VALUE obj)
return Qnil;
}
-/* Ends the process of scanning through the /etc/group file begun by
- * ::getgrent, and closes the file.
+/* Ends the process of scanning through the <tt>/etc/group</tt> file begun
+ * by ::getgrent, and closes the file.
*/
static VALUE
etc_endgrent(VALUE obj)
@@ -623,7 +630,7 @@ etc_endgrent(VALUE obj)
return Qnil;
}
-/* Returns an entry from the /etc/group file.
+/* Returns an entry from the <tt>/etc/group</tt> file.
*
* The first time it is called it opens the file and returns the first entry;
* each successive call returns the next entry, or +nil+ if the end of the file
@@ -657,9 +664,11 @@ VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
/*
* Returns system configuration directory.
*
- * This is typically "/etc", but is modified by the prefix used when Ruby was
- * compiled. For example, if Ruby is built and installed in /usr/local,
- * returns "/usr/local/etc" on other platforms than Windows.
+ * This is typically <code>"/etc"</code>, but is modified by the prefix used
+ * when Ruby was compiled. For example, if Ruby is built and installed in
+ * <tt>/usr/local</tt>, returns <code>"/usr/local/etc"</code> on other
+ * platforms than Windows.
+ *
* On Windows, this always returns the directory provided by the system.
*/
static VALUE
@@ -957,11 +966,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
@@ -980,13 +991,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);
@@ -995,10 +1005,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;
}
}
@@ -1066,11 +1076,12 @@ etc_nprocessors(VALUE obj)
/*
* The Etc module provides access to information typically stored in
- * files in the /etc directory on Unix systems.
+ * files in the <tt>/etc</tt> directory on Unix systems.
*
* The information accessible consists of the information found in the
- * /etc/passwd and /etc/group files, plus information about the system's
- * temporary directory (/tmp) and configuration directory (/etc).
+ * <tt>/etc/passwd</tt> and <tt>/etc/group</tt> files, plus information
+ * about the system's temporary directory (<tt>/tmp</tt>) and configuration
+ * directory (<tt>/etc</tt>).
*
* The Etc module provides a more reliable way to access information about
* the logged in user than environment variables such as +$USER+.
@@ -1095,9 +1106,9 @@ Init_etc(void)
{
VALUE mEtc;
- #ifdef HAVE_RB_EXT_RACTOR_SAFE
- RB_EXT_RACTOR_SAFE(true);
- #endif
+#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);
@@ -1157,16 +1168,18 @@ Init_etc(void)
#endif
NULL);
#if 0
- /* Define-const: Passwd
+ /*
+ * Passwd is a placeholder Struct for user database on Unix systems.
*
- * Passwd is a Struct that contains the following members:
+ * === The struct contains the following members
*
* name::
* contains the short login name of the user as a String.
* passwd::
* contains the encrypted password of the user as a String.
- * an 'x' is returned if shadow passwords are in use. An '*' is returned
- * if the user cannot log in using a password.
+ * an <code>'x'</code> is returned if shadow passwords are in
+ * use. An <code>'*'</code> is returned if the user cannot
+ * log in using a password.
* uid::
* contains the integer user ID (uid) of the user.
* gid::
@@ -1176,32 +1189,30 @@ Init_etc(void)
* shell::
* contains the path to the login shell of the user as a String.
*
- * === The following members below are optional, and must be compiled with special flags:
+ * === The following members below are system-dependent
*
* gecos::
* contains a longer String description of the user, such as
* a full name. Some Unix systems provide structured information in the
* gecos field, but this is system-dependent.
- * must be compiled with +HAVE_STRUCT_PASSWD_PW_GECOS+
* change::
- * password change time(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_CHANGE+
+ * password change time(integer).
* quota::
- * quota value(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_QUOTA+
+ * quota value(integer).
* age::
- * password age(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_AGE+
+ * password age(integer).
* class::
- * user access class(string) must be compiled with +HAVE_STRUCT_PASSWD_PW_CLASS+
+ * user access class(string).
* comment::
- * comment(string) must be compiled with +HAVE_STRUCT_PASSWD_PW_COMMENT+
+ * comment(string).
* expire::
- * account expiration time(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_EXPIRE+
+ * account expiration time(integer).
*/
- rb_define_const(mEtc, "Passwd", sPasswd);
+ sPasswd = rb_define_class_under(mEtc, "Passwd", rb_cStruct);
#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
@@ -1210,31 +1221,27 @@ Init_etc(void)
"gid", "mem", NULL);
#if 0
- /* Define-const: Group
- *
- * Group is a Struct that is only available when compiled with +HAVE_GETGRENT+.
+ /*
+ * Group is a placeholder Struct for user group database on Unix systems.
*
- * The struct contains the following members:
+ * === The struct contains the following members
*
* name::
* contains the name of the group as a String.
* passwd::
- * contains the encrypted password as a String. An 'x' is
+ * contains the encrypted password as a String. An <code>'x'</code> is
* returned if password access to the group is not available; an empty
* string is returned if no password is needed to obtain membership of
* the group.
- *
- * Must be compiled with +HAVE_STRUCT_GROUP_GR_PASSWD+.
+ * This is system-dependent.
* gid::
* contains the group's numeric ID as an integer.
* mem::
* is an Array of Strings containing the short login names of the
* members of the group.
*/
- rb_define_const(mEtc, "Group", sGroup);
+ sGroup = rb_define_class_under(mEtc, "Group", rb_cStruct);
#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 7d687e3b99..98c6d66faa 100644
--- a/ext/etc/etc.gemspec
+++ b/ext/etc/etc.gemspec
@@ -22,23 +22,22 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/ruby/etc"
spec.licenses = ["Ruby", "BSD-2-Clause"]
+ changelogs = Dir.glob("logs/ChangeLog-[1-9]*[^~]", base: __dir__)
spec.files = %w[
LICENSE.txt
README.md
+ ChangeLog
ext/etc/constdefs.h
ext/etc/etc.c
ext/etc/extconf.rb
ext/etc/mkconstants.rb
test/etc/test_etc.rb
- ]
+ ] + changelogs
+ spec.rdoc_options = ["--main", "README.md"]
+ spec.extra_rdoc_files = spec.files.grep_v(/\.{rb,[ch]}\z/)
spec.bindir = "exe"
spec.require_paths = ["lib"]
spec.extensions = %w{ext/etc/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.add_development_dependency "test-unit"
+ spec.required_ruby_version = ">= 2.6.0"
end
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index b6ae7700da..159b1614b7 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -47,10 +47,8 @@ if !File.exist?("#{srcdir}/depend")
%x[#{RbConfig.ruby} #{srcdir}/mkconstants.rb -o #{srcdir}/constdefs.h]
end
-decl = [
- "void rb_deprecate_constant(VALUE, const char *);",
-]
-have_func('rb_deprecate_constant(Qnil, "None")', [decl])
+# TODO: remove when dropping 2.7 support, as exported since 3.0
+have_func('rb_deprecate_constant(Qnil, "None")')
$distcleanfiles << "constdefs.h"
diff --git a/ext/extmk.rb b/ext/extmk.rb
index 4a087f294a..4e77a7167b 100755
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -2,6 +2,9 @@
# -*- mode: ruby; coding: us-ascii -*-
# frozen_string_literal: false
+module Gem; end # only needs Gem::Platform
+require 'rubygems/platform'
+
# :stopdoc:
$extension = nil
$extstatic = nil
@@ -34,6 +37,7 @@ require 'rbconfig'
$topdir = "."
$top_srcdir = srcdir
+inplace = File.identical?($top_srcdir, $topdir)
$" << "mkmf.rb"
load File.expand_path("lib/mkmf.rb", srcdir)
@@ -62,12 +66,17 @@ end
def atomic_write_open(filename)
filename_new = filename + ".new.#$$"
- open(filename_new, "wb") do |f|
+ clean = false
+ File.open(filename_new, "wbx") do |f|
+ clean = true
yield f
end
if File.binread(filename_new) != (File.binread(filename) rescue nil)
File.rename(filename_new, filename)
- else
+ clean = false
+ end
+ensure
+ if clean
File.unlink(filename_new)
end
end
@@ -127,6 +136,14 @@ def extract_makefile(makefile, keep = true)
true
end
+def create_makefile(target, srcprefix = nil)
+ if $static and target.include?("/")
+ base = File.basename(target)
+ $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
+ end
+ super
+end
+
def extmake(target, basedir = 'ext', maybestatic = true)
FileUtils.mkpath target unless File.directory?(target)
begin
@@ -135,7 +152,7 @@ def extmake(target, basedir = 'ext', maybestatic = true)
d = target
until (d = File.dirname(d)) == '.'
if File.exist?("#{$top_srcdir}/#{basedir}/#{d}/extconf.rb")
- parent = (/^all:\s*install/ =~ IO.read("#{d}/Makefile") rescue false)
+ parent = (/^all:\s*install/ =~ File.read("#{d}/Makefile") rescue false)
break
end
end
@@ -146,7 +163,7 @@ def extmake(target, basedir = 'ext', maybestatic = true)
top_srcdir = $top_srcdir
topdir = $topdir
hdrdir = $hdrdir
- prefix = "../" * (target.count("/")+1)
+ prefix = "../" * (basedir.count("/")+target.count("/")+1)
$top_srcdir = relative_from(top_srcdir, prefix)
$hdrdir = relative_from(hdrdir, prefix)
$topdir = prefix + $topdir
@@ -154,8 +171,6 @@ def extmake(target, basedir = 'ext', maybestatic = true)
$mdir = target
$srcdir = File.join($top_srcdir, basedir, $mdir)
$preload = nil
- $objs = []
- $srcs = []
$extso = []
makefile = "./Makefile"
static = $static
@@ -189,7 +204,7 @@ def extmake(target, basedir = 'ext', maybestatic = true)
begin
$extconf_h = nil
ok &&= extract_makefile(makefile)
- old_objs = $objs
+ old_objs = $objs || []
old_cleanfiles = $distcleanfiles | $cleanfiles
conf = ["#{$srcdir}/makefile.rb", "#{$srcdir}/extconf.rb"].find {|f| File.exist?(f)}
if (!ok || ($extconf_h && !File.exist?($extconf_h)) ||
@@ -252,6 +267,8 @@ def extmake(target, basedir = 'ext', maybestatic = true)
unless $destdir.to_s.empty? or $mflags.defined?("DESTDIR")
args += ["DESTDIR=" + relative_from($destdir, "../"+prefix)]
end
+ $objs ||= []
+ $srcs ||= []
if $static and ok and !$objs.empty? and !noinstall
args += ["static"]
$extlist.push [(maybestatic ? $static : false), target, $target, $preload]
@@ -408,8 +425,10 @@ if CROSS_COMPILING
$ruby = $mflags.defined?("MINIRUBY") || CONFIG['MINIRUBY']
elsif sep = config_string('BUILD_FILE_SEPARATOR')
$ruby = "$(topdir:/=#{sep})#{sep}miniruby" + EXEEXT
-else
+elsif CONFIG['EXTSTATIC']
$ruby = '$(topdir)/miniruby' + EXEEXT
+else
+ $ruby = '$(topdir)/ruby' + EXEEXT
end
$ruby = [$ruby]
$ruby << "-I'$(topdir)'"
@@ -421,6 +440,7 @@ 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)}
@@ -435,9 +455,8 @@ if $extstatic
end
for dir in ["ext", File::join($top_srcdir, "ext")]
setup = File::join(dir, CONFIG['setup'])
- if File.file? setup
- f = open(setup)
- while line = f.gets()
+ if (f = File.stat(setup) and f.file? rescue next)
+ File.foreach(setup) do |line|
line.chomp!
line.sub!(/#.*$/, '')
next if /^\s*$/ =~ line
@@ -454,16 +473,16 @@ for dir in ["ext", File::join($top_srcdir, "ext")]
end
MTIMES << f.mtime
$setup = setup
- f.close
break
end
end unless $extstatic
@gemname = nil
-if ARGV[0]
- ext_prefix, exts = ARGV.shift.split('/', 2)
+if exts = ARGV.shift
+ ext_prefix = exts[%r[\A(?>\.bundle/)?[^/]+(?:/(?=(.+)?)|\z)]]
+ exts = $1
$extension = [exts] if exts
- if ext_prefix == 'gems'
+ if ext_prefix.start_with?('.')
@gemname = exts
elsif exts
$static_ext.delete_if {|t, *| !File.fnmatch(t, exts)}
@@ -515,14 +534,22 @@ cond = proc {|ext, *|
exts.delete_if {|d| File.fnmatch?("-*", d)}
end
end
-ext_prefix = File.basename(ext_prefix)
+ext_prefix = ext_prefix[$top_srcdir.size+1..-2]
+@ext_prefix = ext_prefix
+@inplace = inplace
extend Module.new {
+
def timestamp_file(name, target_prefix = nil)
if @gemname and name == '$(TARGET_SO_DIR)'
- name = "$(arch)/gems/#{@gemname}#{target_prefix}"
+ gem = true
+ name = "$(gem_platform)/$(ruby_version)/gems/#{@gemname}#{target_prefix}"
end
- super.sub(%r[/\.extout\.(?:-\.)?], '/.')
+ path = super.sub(%r[/\.extout\.(?:-\.)?], '/.')
+ if gem
+ nil while path.sub!(%r[/\.(gem_platform|ruby_version)\.-(?=\.)], '/$(\1)/')
+ end
+ path
end
def configuration(srcdir)
@@ -530,28 +557,81 @@ extend Module.new {
end
def create_makefile(*args, &block)
- return super unless @gemname
+ unless @gemname
+ if $static and (target = args.first).include?("/")
+ base = File.basename(target)
+ $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
+ end
+ return super
+ end
super(*args) do |conf|
conf.find do |s|
+ s.sub!(%r(^(srcdir *= *)\$\(top_srcdir\)/\.bundle/gems/[^/]+(?=/))) {
+ "gem_#{$&}\n" "#{$1}$(gem_srcdir)"
+ }
+ s.sub!(/^(TIMESTAMP_DIR *= *)\$\(extout\)/) {
+ "TARGET_TOPDIR = $(topdir)/.bundle\n" "#{$1}$(TARGET_TOPDIR)"
+ }
s.sub!(/^(TARGET_SO_DIR *= *)\$\(RUBYARCHDIR\)/) {
- "TARGET_GEM_DIR = $(extout)/gems/$(arch)/#{@gemname}\n"\
+ "TARGET_GEM_DIR = $(TARGET_TOPDIR)/extensions/$(gem_platform)"\
+ "/$(ruby_version)#{$enable_shared ? '' : '-static'}/#{@gemname}\n"\
"#{$1}$(TARGET_GEM_DIR)$(target_prefix)"
}
end
- conf.any? {|s| /^TARGET *= *\S/ =~ s} and conf << %{
+
+ gemlib = File.directory?("#{$top_srcdir}/#{@ext_prefix}/#{@gemname}/lib")
+ if conf.any? {|s| /^TARGET *= *\S/ =~ s}
+ conf << %{
+gem_platform = #{Gem::Platform.local}
# default target
all:
+gem = #{@gemname}
+
build_complete = $(TARGET_GEM_DIR)/gem.build_complete
install-so: build_complete
+clean-so:: clean-build_complete
+
build_complete: $(build_complete)
$(build_complete): $(TARGET_SO)
$(Q) $(TOUCH) $@
-clean-so::
+clean-build_complete:
-$(Q)$(RM) $(build_complete)
+
+install: gemspec
+clean: clean-gemspec
+
+gemspec = $(TARGET_TOPDIR)/specifications/$(gem).gemspec
+$(gemspec): $(gem_srcdir)/.bundled.$(gem).gemspec
+ $(Q) $(MAKEDIRS) $(@D)
+ $(Q) $(COPY) $(gem_srcdir)/.bundled.$(gem).gemspec $@
+
+gemspec: $(gemspec)
+
+clean-gemspec:
+ -$(Q)$(RM) $(gemspec)
}
+
+ if gemlib
+ conf << %{
+install-rb: gemlib
+clean-rb:: clean-gemlib
+
+LN_S = #{config_string('LN_S')}
+CP_R = #{config_string('CP')} -r
+
+gemlib = $(TARGET_TOPDIR)/gems/$(gem)/lib
+gemlib:#{%{ $(gemlib)\n$(gemlib): $(gem_srcdir)/lib} if $nmake}
+ $(Q) #{@inplace ? '$(NULLCMD) ' : ''}$(RUBY) $(top_srcdir)/tool/ln_sr.rb -q -f -T $(gem_srcdir)/lib $(gemlib)
+
+clean-gemlib:
+ $(Q) $(#{@inplace ? 'NULLCMD' : 'RM_RF'}) $(gemlib)
+}
+ end
+ end
+
conf
end
end
@@ -634,7 +714,7 @@ rubies = []
end
}
-Dir.chdir ".."
+Dir.chdir dir
unless $destdir.to_s.empty?
$mflags.defined?("DESTDIR") or $mflags << "DESTDIR=#{$destdir}"
end
@@ -653,6 +733,8 @@ begin
mf.puts "ECHO1 = $(V:1=@:)"
mf.puts "ECHO = $(ECHO1:0=@echo)"
mf.puts "MFLAGS = -$(MAKEFLAGS)" if $nmake
+ mf.puts "override MFLAGS := $(filter-out -j%,$(MFLAGS))" if $gnumake
+ mf.puts "ext_build_dir = #{File.dirname($command_output)}"
mf.puts
def mf.macro(name, values, max = 70)
@@ -695,6 +777,7 @@ begin
mf.macro "SUBMAKEOPTS", submakeopts
mf.macro "NOTE_MESG", %w[$(RUBY) $(top_srcdir)/tool/lib/colorize.rb skip]
mf.macro "NOTE_NAME", %w[$(RUBY) $(top_srcdir)/tool/lib/colorize.rb fail]
+ %w[RM RMDIRS RMDIR RMALL].each {|w| mf.macro w, [RbConfig::CONFIG[w]]}
mf.puts
targets = %w[all install static install-so install-rb clean distclean realclean]
targets.each do |tgt|
@@ -729,16 +812,20 @@ begin
exts.each do |d|
d = d[0..-2]
t = "#{d}#{tgt}"
- if /^(dist|real)?clean$/ =~ tgt
+ if clean = /^(dist|real)?clean$/.match(tgt)
deps = exts.select {|e|e.start_with?(d)}.map {|e|"#{e[0..-2]}#{tgt}"} - [t]
- pd = ' ' + deps.join(' ') unless deps.empty?
+ pd = [' clean-local', *deps].join(' ')
else
pext = File.dirname(d)
pd = " #{pext}/#{tgt}" if exts.include?("#{pext}/.")
end
mf.puts "#{t}:#{pd}\n\t$(Q)#{submake} $(MFLAGS) V=$(V) $(@F)"
+ if clean and clean.begin(1)
+ mf.puts "\t$(Q)$(RM) $(ext_build_dir)/exts.mk\n\t$(Q)$(RMDIRS) -p $(@D)"
+ end
end
end
+ mf.puts "\n""clean-local:\n\t$(Q)$(RM) $(ext_build_dir)/*~ $(ext_build_dir)/*.bak $(ext_build_dir)/core"
mf.puts "\n""extso:\n"
mf.puts "\t@echo EXTSO=$(EXTSO)"
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index 720b67d9bf..718de62e26 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -2,6 +2,19 @@
fcntl.o: $(RUBY_EXTCONF_H)
fcntl.o: $(arch_hdrdir)/ruby/config.h
fcntl.o: $(hdrdir)/ruby.h
+fcntl.o: $(hdrdir)/ruby/assert.h
+fcntl.o: $(hdrdir)/ruby/backward.h
+fcntl.o: $(hdrdir)/ruby/backward/2/assume.h
+fcntl.o: $(hdrdir)/ruby/backward/2/attributes.h
+fcntl.o: $(hdrdir)/ruby/backward/2/bool.h
+fcntl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fcntl.o: $(hdrdir)/ruby/backward/2/limits.h
+fcntl.o: $(hdrdir)/ruby/backward/2/long_long.h
+fcntl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fcntl.o: $(hdrdir)/ruby/backward/2/stdarg.h
+fcntl.o: $(hdrdir)/ruby/defines.h
+fcntl.o: $(hdrdir)/ruby/intern.h
+fcntl.o: $(hdrdir)/ruby/internal/abi.h
fcntl.o: $(hdrdir)/ruby/internal/anyargs.h
fcntl.o: $(hdrdir)/ruby/internal/arithmetic.h
fcntl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
fcntl.o: $(hdrdir)/ruby/ruby.h
fcntl.o: $(hdrdir)/ruby/st.h
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index ee42d2abe5..3bccc41e4c 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -256,4 +256,21 @@ Init_fcntl(void)
*/
rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_RDONLY | O_WRONLY | O_RDWR));
#endif
+#ifdef F_DUP2FD
+ /* Document-const: F_DUP2FD
+ *
+ * It is a FreeBSD specific constant and equivalent
+ * to dup2 call.
+ */
+ rb_define_const(mFcntl, "F_DUP2FD", INT2NUM(F_DUP2FD));
+#endif
+#ifdef F_DUP2FD_CLOEXEC
+ /* Document-const: F_DUP2FD_CLOEXEC
+ *
+ * It is a FreeBSD specific constant and acts
+ * similarly as F_DUP2FD but set the FD_CLOEXEC
+ * flag in addition.
+ */
+ rb_define_const(mFcntl, "F_DUP2FD_CLOEXEC", INT2NUM(F_DUP2FD_CLOEXEC));
+#endif
}
diff --git a/ext/fcntl/fcntl.gemspec b/ext/fcntl/fcntl.gemspec
index 645c507a4d..09d3fc2568 100644
--- a/ext/fcntl/fcntl.gemspec
+++ b/ext/fcntl/fcntl.gemspec
@@ -3,7 +3,7 @@
Gem::Specification.new do |spec|
spec.name = "fcntl"
- spec.version = "1.0.0"
+ spec.version = "1.0.2"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
index 3679e5c9ad..892f522a62 100644
--- a/ext/fiddle/closure.c
+++ b/ext/fiddle/closure.c
@@ -56,6 +56,8 @@ closure_memsize(const void * ptr)
const rb_data_type_t closure_data_type = {
"fiddle/closure",
{0, dealloc, closure_memsize,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY,
};
struct callback_args {
@@ -90,7 +92,7 @@ with_gvl_callback(void *ptr)
case TYPE_INT:
rb_ary_push(params, INT2NUM(*(int *)x->args[i]));
break;
- case -TYPE_INT:
+ case TYPE_UINT:
rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i]));
break;
case TYPE_VOIDP:
@@ -101,19 +103,19 @@ with_gvl_callback(void *ptr)
case TYPE_LONG:
rb_ary_push(params, LONG2NUM(*(long *)x->args[i]));
break;
- case -TYPE_LONG:
+ case TYPE_ULONG:
rb_ary_push(params, ULONG2NUM(*(unsigned long *)x->args[i]));
break;
case TYPE_CHAR:
rb_ary_push(params, INT2NUM(*(signed char *)x->args[i]));
break;
- case -TYPE_CHAR:
+ case TYPE_UCHAR:
rb_ary_push(params, UINT2NUM(*(unsigned char *)x->args[i]));
break;
case TYPE_SHORT:
rb_ary_push(params, INT2NUM(*(signed short *)x->args[i]));
break;
- case -TYPE_SHORT:
+ case TYPE_USHORT:
rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i]));
break;
case TYPE_DOUBLE:
@@ -126,7 +128,7 @@ with_gvl_callback(void *ptr)
case TYPE_LONG_LONG:
rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i]));
break;
- case -TYPE_LONG_LONG:
+ case TYPE_ULONG_LONG:
rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i]));
break;
#endif
@@ -149,7 +151,7 @@ with_gvl_callback(void *ptr)
case TYPE_LONG:
*(long *)x->resp = NUM2LONG(ret);
break;
- case -TYPE_LONG:
+ case TYPE_ULONG:
*(unsigned long *)x->resp = NUM2ULONG(ret);
break;
case TYPE_CHAR:
@@ -157,9 +159,9 @@ with_gvl_callback(void *ptr)
case TYPE_INT:
*(ffi_sarg *)x->resp = NUM2INT(ret);
break;
- case -TYPE_CHAR:
- case -TYPE_SHORT:
- case -TYPE_INT:
+ case TYPE_UCHAR:
+ case TYPE_USHORT:
+ case TYPE_UINT:
*(ffi_arg *)x->resp = NUM2UINT(ret);
break;
case TYPE_VOIDP:
@@ -175,7 +177,7 @@ with_gvl_callback(void *ptr)
case TYPE_LONG_LONG:
*(LONG_LONG *)x->resp = NUM2LL(ret);
break;
- case -TYPE_LONG_LONG:
+ case TYPE_ULONG_LONG:
*(unsigned LONG_LONG *)x->resp = NUM2ULL(ret);
break;
#endif
@@ -224,9 +226,27 @@ allocate(VALUE klass)
return i;
}
+static fiddle_closure *
+get_raw(VALUE self)
+{
+ fiddle_closure *closure;
+ TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
+ if (!closure) {
+ rb_raise(rb_eArgError, "already freed: %+"PRIsVALUE, self);
+ }
+ return closure;
+}
+
+typedef struct {
+ VALUE self;
+ int argc;
+ VALUE *argv;
+} initialize_data;
+
static VALUE
-initialize(int rbargc, VALUE argv[], VALUE self)
+initialize_body(VALUE user_data)
{
+ initialize_data *data = (initialize_data *)user_data;
VALUE ret;
VALUE args;
VALUE normalized_args;
@@ -237,14 +257,14 @@ initialize(int rbargc, VALUE argv[], VALUE self)
ffi_status result;
int i, argc;
- if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
- abi = INT2NUM(FFI_DEFAULT_ABI);
+ if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi))
+ abi = INT2NUM(FFI_DEFAULT_ABI);
Check_Type(args, T_ARRAY);
argc = RARRAY_LENINT(args);
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
+ TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl);
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
@@ -257,8 +277,8 @@ initialize(int rbargc, VALUE argv[], VALUE self)
cl->argv[argc] = NULL;
ret = rb_fiddle_type_ensure(ret);
- rb_iv_set(self, "@ctype", ret);
- rb_iv_set(self, "@args", normalized_args);
+ rb_iv_set(data->self, "@ctype", ret);
+ rb_iv_set(data->self, "@args", normalized_args);
cif = &cl->cif;
pcl = cl->pcl;
@@ -269,38 +289,75 @@ initialize(int rbargc, VALUE argv[], VALUE self)
rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
cl->argv);
- if (FFI_OK != result)
- rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
+ if (FFI_OK != result) {
+ rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
+ }
#if USE_FFI_CLOSURE_ALLOC
result = ffi_prep_closure_loc(pcl, cif, callback,
- (void *)self, cl->code);
+ (void *)(data->self), cl->code);
#else
- result = ffi_prep_closure(pcl, cif, callback, (void *)self);
+ result = ffi_prep_closure(pcl, cif, callback, (void *)(data->self));
cl->code = (void *)pcl;
i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
if (i) {
- rb_sys_fail("mprotect");
+ rb_sys_fail("mprotect");
}
#endif
- if (FFI_OK != result)
- rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
+ if (FFI_OK != result) {
+ rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
+ }
- return self;
+ return data->self;
}
static VALUE
-to_i(VALUE self)
+initialize_rescue(VALUE user_data, VALUE exception)
{
- fiddle_closure * cl;
- void *code;
+ initialize_data *data = (initialize_data *)user_data;
+ dealloc(RTYPEDDATA_DATA(data->self));
+ RTYPEDDATA_DATA(data->self) = NULL;
+ rb_exc_raise(exception);
+ return data->self;
+}
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
+static VALUE
+initialize(int argc, VALUE *argv, VALUE self)
+{
+ initialize_data data;
+ data.self = self;
+ data.argc = argc;
+ data.argv = argv;
+ return rb_rescue(initialize_body, (VALUE)&data,
+ initialize_rescue, (VALUE)&data);
+}
- code = cl->code;
+static VALUE
+to_i(VALUE self)
+{
+ fiddle_closure *closure = get_raw(self);
+ return PTR2NUM(closure->code);
+}
- return PTR2NUM(code);
+static VALUE
+closure_free(VALUE self)
+{
+ fiddle_closure *closure;
+ TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
+ if (closure) {
+ dealloc(closure);
+ RTYPEDDATA_DATA(self) = NULL;
+ }
+ return RUBY_Qnil;
+}
+
+static VALUE
+closure_freed_p(VALUE self)
+{
+ fiddle_closure *closure;
+ TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
+ return closure ? RUBY_Qfalse : RUBY_Qtrue;
}
void
@@ -353,8 +410,24 @@ Init_fiddle_closure(void)
/*
* Document-method: to_i
*
- * Returns the memory address for this closure
+ * Returns the memory address for this closure.
*/
rb_define_method(cFiddleClosure, "to_i", to_i, 0);
+
+ /*
+ * Document-method: free
+ *
+ * Free this closure explicitly. You can't use this closure anymore.
+ *
+ * If this closure is already freed, this does nothing.
+ */
+ rb_define_method(cFiddleClosure, "free", closure_free, 0);
+
+ /*
+ * Document-method: freed?
+ *
+ * Whether this closure was freed explicitly.
+ */
+ rb_define_method(cFiddleClosure, "freed?", closure_freed_p, 0);
}
/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c
index 6e0ce36378..3b70f7de4c 100644
--- a/ext/fiddle/conversions.c
+++ b/ext/fiddle/conversions.c
@@ -211,32 +211,32 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
case TYPE_CHAR:
dst->schar = (signed char)NUM2INT(*src);
break;
- case -TYPE_CHAR:
+ case TYPE_UCHAR:
dst->uchar = (unsigned char)NUM2UINT(*src);
break;
case TYPE_SHORT:
dst->sshort = (unsigned short)NUM2INT(*src);
break;
- case -TYPE_SHORT:
+ case TYPE_USHORT:
dst->sshort = (signed short)NUM2UINT(*src);
break;
case TYPE_INT:
dst->sint = NUM2INT(*src);
break;
- case -TYPE_INT:
+ case TYPE_UINT:
dst->uint = NUM2UINT(*src);
break;
case TYPE_LONG:
dst->slong = NUM2LONG(*src);
break;
- case -TYPE_LONG:
+ case TYPE_ULONG:
dst->ulong = NUM2ULONG(*src);
break;
#if HAVE_LONG_LONG
case TYPE_LONG_LONG:
dst->slong_long = NUM2LL(*src);
break;
- case -TYPE_LONG_LONG:
+ case TYPE_ULONG_LONG:
dst->ulong_long = NUM2ULL(*src);
break;
#endif
@@ -283,24 +283,24 @@ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
PTR2NUM((void *)retval.pointer));
case TYPE_CHAR:
return INT2NUM((signed char)retval.fffi_sarg);
- case -TYPE_CHAR:
+ case TYPE_UCHAR:
return INT2NUM((unsigned char)retval.fffi_arg);
case TYPE_SHORT:
return INT2NUM((signed short)retval.fffi_sarg);
- case -TYPE_SHORT:
+ case TYPE_USHORT:
return INT2NUM((unsigned short)retval.fffi_arg);
case TYPE_INT:
return INT2NUM((signed int)retval.fffi_sarg);
- case -TYPE_INT:
+ case TYPE_UINT:
return UINT2NUM((unsigned int)retval.fffi_arg);
case TYPE_LONG:
return LONG2NUM(retval.slong);
- case -TYPE_LONG:
+ case TYPE_ULONG:
return ULONG2NUM(retval.ulong);
#if HAVE_LONG_LONG
case TYPE_LONG_LONG:
return LL2NUM(retval.slong_long);
- case -TYPE_LONG_LONG:
+ case TYPE_ULONG_LONG:
return ULL2NUM(retval.ulong_long);
#endif
case TYPE_FLOAT:
diff --git a/ext/fiddle/depend b/ext/fiddle/depend
index 1d299ba462..d6a053f05b 100644
--- a/ext/fiddle/depend
+++ b/ext/fiddle/depend
@@ -60,7 +60,6 @@ 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
@@ -68,6 +67,7 @@ closure.o: $(hdrdir)/ruby/backward/2/stdalign.h
closure.o: $(hdrdir)/ruby/backward/2/stdarg.h
closure.o: $(hdrdir)/ruby/defines.h
closure.o: $(hdrdir)/ruby/intern.h
+closure.o: $(hdrdir)/ruby/internal/abi.h
closure.o: $(hdrdir)/ruby/internal/anyargs.h
closure.o: $(hdrdir)/ruby/internal/arithmetic.h
closure.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -225,7 +225,6 @@ 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
@@ -233,6 +232,7 @@ conversions.o: $(hdrdir)/ruby/backward/2/stdalign.h
conversions.o: $(hdrdir)/ruby/backward/2/stdarg.h
conversions.o: $(hdrdir)/ruby/defines.h
conversions.o: $(hdrdir)/ruby/intern.h
+conversions.o: $(hdrdir)/ruby/internal/abi.h
conversions.o: $(hdrdir)/ruby/internal/anyargs.h
conversions.o: $(hdrdir)/ruby/internal/arithmetic.h
conversions.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -389,7 +389,6 @@ 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
@@ -397,6 +396,7 @@ fiddle.o: $(hdrdir)/ruby/backward/2/stdalign.h
fiddle.o: $(hdrdir)/ruby/backward/2/stdarg.h
fiddle.o: $(hdrdir)/ruby/defines.h
fiddle.o: $(hdrdir)/ruby/intern.h
+fiddle.o: $(hdrdir)/ruby/internal/abi.h
fiddle.o: $(hdrdir)/ruby/internal/anyargs.h
fiddle.o: $(hdrdir)/ruby/internal/arithmetic.h
fiddle.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -553,7 +553,6 @@ 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
@@ -561,6 +560,7 @@ function.o: $(hdrdir)/ruby/backward/2/stdalign.h
function.o: $(hdrdir)/ruby/backward/2/stdarg.h
function.o: $(hdrdir)/ruby/defines.h
function.o: $(hdrdir)/ruby/intern.h
+function.o: $(hdrdir)/ruby/internal/abi.h
function.o: $(hdrdir)/ruby/internal/anyargs.h
function.o: $(hdrdir)/ruby/internal/arithmetic.h
function.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -718,7 +718,6 @@ 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
@@ -726,6 +725,7 @@ handle.o: $(hdrdir)/ruby/backward/2/stdalign.h
handle.o: $(hdrdir)/ruby/backward/2/stdarg.h
handle.o: $(hdrdir)/ruby/defines.h
handle.o: $(hdrdir)/ruby/intern.h
+handle.o: $(hdrdir)/ruby/internal/abi.h
handle.o: $(hdrdir)/ruby/internal/anyargs.h
handle.o: $(hdrdir)/ruby/internal/arithmetic.h
handle.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -882,7 +882,6 @@ 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
@@ -891,6 +890,7 @@ memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h
memory_view.o: $(hdrdir)/ruby/defines.h
memory_view.o: $(hdrdir)/ruby/encoding.h
memory_view.o: $(hdrdir)/ruby/intern.h
+memory_view.o: $(hdrdir)/ruby/internal/abi.h
memory_view.o: $(hdrdir)/ruby/internal/anyargs.h
memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h
memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -960,6 +960,15 @@ memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
memory_view.o: $(hdrdir)/ruby/internal/ctype.h
memory_view.o: $(hdrdir)/ruby/internal/dllexport.h
memory_view.o: $(hdrdir)/ruby/internal/dosish.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/re.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/string.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+memory_view.o: $(hdrdir)/ruby/internal/encoding/transcode.h
memory_view.o: $(hdrdir)/ruby/internal/error.h
memory_view.o: $(hdrdir)/ruby/internal/eval.h
memory_view.o: $(hdrdir)/ruby/internal/event.h
@@ -1050,7 +1059,6 @@ 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
@@ -1058,6 +1066,7 @@ pinned.o: $(hdrdir)/ruby/backward/2/stdalign.h
pinned.o: $(hdrdir)/ruby/backward/2/stdarg.h
pinned.o: $(hdrdir)/ruby/defines.h
pinned.o: $(hdrdir)/ruby/intern.h
+pinned.o: $(hdrdir)/ruby/internal/abi.h
pinned.o: $(hdrdir)/ruby/internal/anyargs.h
pinned.o: $(hdrdir)/ruby/internal/arithmetic.h
pinned.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1214,7 +1223,6 @@ 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
@@ -1223,6 +1231,7 @@ pointer.o: $(hdrdir)/ruby/backward/2/stdarg.h
pointer.o: $(hdrdir)/ruby/defines.h
pointer.o: $(hdrdir)/ruby/encoding.h
pointer.o: $(hdrdir)/ruby/intern.h
+pointer.o: $(hdrdir)/ruby/internal/abi.h
pointer.o: $(hdrdir)/ruby/internal/anyargs.h
pointer.o: $(hdrdir)/ruby/internal/arithmetic.h
pointer.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1292,6 +1301,15 @@ pointer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
pointer.o: $(hdrdir)/ruby/internal/ctype.h
pointer.o: $(hdrdir)/ruby/internal/dllexport.h
pointer.o: $(hdrdir)/ruby/internal/dosish.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/re.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/string.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+pointer.o: $(hdrdir)/ruby/internal/encoding/transcode.h
pointer.o: $(hdrdir)/ruby/internal/error.h
pointer.o: $(hdrdir)/ruby/internal/eval.h
pointer.o: $(hdrdir)/ruby/internal/event.h
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
index 053456d534..cf8b5223bb 100644
--- a/ext/fiddle/extconf.rb
+++ b/ext/fiddle/extconf.rb
@@ -46,7 +46,7 @@ end
libffi_version = nil
have_libffi = false
-bundle = enable_config('bundled-libffi')
+bundle = with_config("libffi-source-dir")
unless bundle
dir_config 'libffi'
@@ -67,27 +67,11 @@ unless bundle
end
unless have_libffi
- # for https://github.com/ruby/fiddle
- extlibs_rb = File.expand_path("../../bin/extlibs.rb", $srcdir)
- if bundle && File.exist?(extlibs_rb)
- require "fileutils"
- require_relative "../../bin/extlibs"
- extlibs = ExtLibs.new
- cache_dir = File.expand_path("../../tmp/.download_cache", $srcdir)
- ext_dir = File.expand_path("../../ext", $srcdir)
- Dir.glob("#{$srcdir}/libffi-*/").each{|dir| FileUtils.rm_rf(dir)}
- extlibs.run(["--cache=#{cache_dir}", ext_dir])
- end
- 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."
+ if bundle
+ libffi_srcdir = libffi_package_name = bundle
+ else
+ raise "missing libffi. Please install libffi or use --with-libffi-source-dir with libffi source location."
end
-
- 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 = libffi_package_name
@@ -226,7 +210,7 @@ types.each do |type, signed|
end
if libffi
- $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
+ $LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk
$INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
end
create_makefile 'fiddle' do |conf|
diff --git a/ext/fiddle/extlibs b/ext/fiddle/extlibs
deleted file mode 100644
index 68dac46a95..0000000000
--- a/ext/fiddle/extlibs
+++ /dev/null
@@ -1,13 +0,0 @@
-ver = 3.2.1
-pkg = libffi-$(ver)
-
-https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/$(pkg).tar.gz \
- md5:83b89587607e3eb65c70d361f13bab43 \
- sha512:980ca30a8d76f963fca722432b1fe5af77d7a4e4d2eac5144fbc5374d4c596609a293440573f4294207e1bdd9fda80ad1e1cafb2ffb543df5a275bc3bd546483 \
- #
- 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 a8b5123269..c06cd5634a 100644
--- a/ext/fiddle/fiddle.c
+++ b/ext/fiddle/fiddle.c
@@ -164,137 +164,193 @@ Init_fiddle(void)
*/
rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError);
- /* Document-const: TYPE_VOID
+ VALUE mFiddleTypes = rb_define_module_under(mFiddle, "Types");
+
+ /* Document-const: Fiddle::Types::VOID
*
* C type - void
*/
- rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID));
+ rb_define_const(mFiddleTypes, "VOID", INT2NUM(TYPE_VOID));
- /* Document-const: TYPE_VOIDP
+ /* Document-const: Fiddle::Types::VOIDP
*
* C type - void*
*/
- rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP));
+ rb_define_const(mFiddleTypes, "VOIDP", INT2NUM(TYPE_VOIDP));
- /* Document-const: TYPE_CHAR
+ /* Document-const: Fiddle::Types::CHAR
*
* C type - char
*/
- rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR));
+ rb_define_const(mFiddleTypes, "CHAR", INT2NUM(TYPE_CHAR));
- /* Document-const: TYPE_SHORT
+ /* Document-const: Fiddle::Types::UCHAR
+ *
+ * C type - unsigned char
+ */
+ rb_define_const(mFiddleTypes, "UCHAR", INT2NUM(TYPE_UCHAR));
+
+ /* Document-const: Fiddle::Types::SHORT
*
* C type - short
*/
- rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT));
+ rb_define_const(mFiddleTypes, "SHORT", INT2NUM(TYPE_SHORT));
- /* Document-const: TYPE_INT
+ /* Document-const: Fiddle::Types::USHORT
+ *
+ * C type - unsigned short
+ */
+ rb_define_const(mFiddleTypes, "USHORT", INT2NUM(TYPE_USHORT));
+
+ /* Document-const: Fiddle::Types::INT
*
* C type - int
*/
- rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT));
+ rb_define_const(mFiddleTypes, "INT", INT2NUM(TYPE_INT));
+
+ /* Document-const: Fiddle::Types::UINT
+ *
+ * C type - unsigned int
+ */
+ rb_define_const(mFiddleTypes, "UINT", INT2NUM(TYPE_UINT));
+
+ /* Document-const: Fiddle::Types::LONG
+ *
+ * C type - long
+ */
+ rb_define_const(mFiddleTypes, "LONG", INT2NUM(TYPE_LONG));
- /* Document-const: TYPE_LONG
+ /* Document-const: Fiddle::Types::ULONG
*
* C type - long
*/
- rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG));
+ rb_define_const(mFiddleTypes, "ULONG", INT2NUM(TYPE_ULONG));
#if HAVE_LONG_LONG
- /* Document-const: TYPE_LONG_LONG
+ /* Document-const: Fiddle::Types::LONG_LONG
+ *
+ * C type - long long
+ */
+ rb_define_const(mFiddleTypes, "LONG_LONG", INT2NUM(TYPE_LONG_LONG));
+
+ /* Document-const: Fiddle::Types::ULONG_LONG
*
* C type - long long
*/
- rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
+ rb_define_const(mFiddleTypes, "ULONG_LONG", INT2NUM(TYPE_ULONG_LONG));
#endif
#ifdef TYPE_INT8_T
- /* Document-const: TYPE_INT8_T
+ /* Document-const: Fiddle::Types::INT8_T
*
* C type - int8_t
*/
- rb_define_const(mFiddle, "TYPE_INT8_T", INT2NUM(TYPE_INT8_T));
+ rb_define_const(mFiddleTypes, "INT8_T", INT2NUM(TYPE_INT8_T));
+
+ /* Document-const: Fiddle::Types::UINT8_T
+ *
+ * C type - uint8_t
+ */
+ rb_define_const(mFiddleTypes, "UINT8_T", INT2NUM(TYPE_UINT8_T));
#endif
#ifdef TYPE_INT16_T
- /* Document-const: TYPE_INT16_T
+ /* Document-const: Fiddle::Types::INT16_T
*
* C type - int16_t
*/
- rb_define_const(mFiddle, "TYPE_INT16_T", INT2NUM(TYPE_INT16_T));
+ rb_define_const(mFiddleTypes, "INT16_T", INT2NUM(TYPE_INT16_T));
+
+ /* Document-const: Fiddle::Types::UINT16_T
+ *
+ * C type - uint16_t
+ */
+ rb_define_const(mFiddleTypes, "UINT16_T", INT2NUM(TYPE_UINT16_T));
#endif
#ifdef TYPE_INT32_T
- /* Document-const: TYPE_INT32_T
+ /* Document-const: Fiddle::Types::INT32_T
*
* C type - int32_t
*/
- rb_define_const(mFiddle, "TYPE_INT32_T", INT2NUM(TYPE_INT32_T));
+ rb_define_const(mFiddleTypes, "INT32_T", INT2NUM(TYPE_INT32_T));
+
+ /* Document-const: Fiddle::Types::UINT32_T
+ *
+ * C type - uint32_t
+ */
+ rb_define_const(mFiddleTypes, "UINT32_T", INT2NUM(TYPE_UINT32_T));
#endif
#ifdef TYPE_INT64_T
- /* Document-const: TYPE_INT64_T
+ /* Document-const: Fiddle::Types::INT64_T
*
* C type - int64_t
*/
- rb_define_const(mFiddle, "TYPE_INT64_T", INT2NUM(TYPE_INT64_T));
+ rb_define_const(mFiddleTypes, "INT64_T", INT2NUM(TYPE_INT64_T));
+
+ /* Document-const: Fiddle::Types::UINT64_T
+ *
+ * C type - uint64_t
+ */
+ rb_define_const(mFiddleTypes, "UINT64_T", INT2NUM(TYPE_UINT64_T));
#endif
- /* Document-const: TYPE_FLOAT
+ /* Document-const: Fiddle::Types::FLOAT
*
* C type - float
*/
- rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT));
+ rb_define_const(mFiddleTypes, "FLOAT", INT2NUM(TYPE_FLOAT));
- /* Document-const: TYPE_DOUBLE
+ /* Document-const: Fiddle::Types::DOUBLE
*
* C type - double
*/
- rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE));
+ rb_define_const(mFiddleTypes, "DOUBLE", INT2NUM(TYPE_DOUBLE));
#ifdef HAVE_FFI_PREP_CIF_VAR
- /* Document-const: TYPE_VARIADIC
+ /* Document-const: Fiddle::Types::VARIADIC
*
* C type - ...
*/
- rb_define_const(mFiddle, "TYPE_VARIADIC", INT2NUM(TYPE_VARIADIC));
+ rb_define_const(mFiddleTypes, "VARIADIC", INT2NUM(TYPE_VARIADIC));
#endif
- /* Document-const: TYPE_CONST_STRING
+ /* Document-const: Fiddle::Types::CONST_STRING
*
* C type - const char* ('\0' terminated const char*)
*/
- rb_define_const(mFiddle, "TYPE_CONST_STRING", INT2NUM(TYPE_CONST_STRING));
+ rb_define_const(mFiddleTypes, "CONST_STRING", INT2NUM(TYPE_CONST_STRING));
- /* Document-const: TYPE_SIZE_T
+ /* Document-const: Fiddle::Types::SIZE_T
*
* C type - size_t
*/
- rb_define_const(mFiddle, "TYPE_SIZE_T", INT2NUM(TYPE_SIZE_T));
+ rb_define_const(mFiddleTypes, "SIZE_T", INT2NUM(TYPE_SIZE_T));
- /* Document-const: TYPE_SSIZE_T
+ /* Document-const: Fiddle::Types::SSIZE_T
*
* C type - ssize_t
*/
- rb_define_const(mFiddle, "TYPE_SSIZE_T", INT2NUM(TYPE_SSIZE_T));
+ rb_define_const(mFiddleTypes, "SSIZE_T", INT2NUM(TYPE_SSIZE_T));
- /* Document-const: TYPE_PTRDIFF_T
+ /* Document-const: Fiddle::Types::PTRDIFF_T
*
* C type - ptrdiff_t
*/
- rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));
+ rb_define_const(mFiddleTypes, "PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));
- /* Document-const: TYPE_INTPTR_T
+ /* Document-const: Fiddle::Types::INTPTR_T
*
* C type - intptr_t
*/
- rb_define_const(mFiddle, "TYPE_INTPTR_T", INT2NUM(TYPE_INTPTR_T));
+ rb_define_const(mFiddleTypes, "INTPTR_T", INT2NUM(TYPE_INTPTR_T));
- /* Document-const: TYPE_UINTPTR_T
+ /* Document-const: Fiddle::Types::UINTPTR_T
*
* C type - uintptr_t
*/
- rb_define_const(mFiddle, "TYPE_UINTPTR_T", INT2NUM(TYPE_UINTPTR_T));
+ rb_define_const(mFiddleTypes, "UINTPTR_T", INT2NUM(TYPE_UINTPTR_T));
/* Document-const: ALIGN_VOIDP
*
@@ -422,30 +478,60 @@ Init_fiddle(void)
*/
rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char)));
+ /* Document-const: SIZEOF_UCHAR
+ *
+ * size of a unsigned char
+ */
+ rb_define_const(mFiddle, "SIZEOF_UCHAR", INT2NUM(sizeof(unsigned char)));
+
/* Document-const: SIZEOF_SHORT
*
* size of a short
*/
rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
+ /* Document-const: SIZEOF_USHORT
+ *
+ * size of a unsigned short
+ */
+ rb_define_const(mFiddle, "SIZEOF_USHORT", INT2NUM(sizeof(unsigned short)));
+
/* Document-const: SIZEOF_INT
*
* size of an int
*/
rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int)));
+ /* Document-const: SIZEOF_UINT
+ *
+ * size of an unsigned int
+ */
+ rb_define_const(mFiddle, "SIZEOF_UINT", INT2NUM(sizeof(unsigned int)));
+
/* Document-const: SIZEOF_LONG
*
* size of a long
*/
rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long)));
+ /* Document-const: SIZEOF_ULONG
+ *
+ * size of a unsigned long
+ */
+ rb_define_const(mFiddle, "SIZEOF_ULONG", INT2NUM(sizeof(unsigned long)));
+
#if HAVE_LONG_LONG
/* Document-const: SIZEOF_LONG_LONG
*
* size of a long long
*/
rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
+
+ /* Document-const: SIZEOF_ULONG_LONG
+ *
+ * size of a unsigned long long
+ */
+ rb_define_const(mFiddle, "SIZEOF_ULONG_LONG", INT2NUM(sizeof(unsigned LONG_LONG)));
#endif
/* Document-const: SIZEOF_INT8_T
@@ -454,24 +540,48 @@ Init_fiddle(void)
*/
rb_define_const(mFiddle, "SIZEOF_INT8_T", INT2NUM(sizeof(int8_t)));
+ /* Document-const: SIZEOF_UINT8_T
+ *
+ * size of a uint8_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_UINT8_T", INT2NUM(sizeof(uint8_t)));
+
/* Document-const: SIZEOF_INT16_T
*
* size of a int16_t
*/
rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_t)));
+ /* Document-const: SIZEOF_UINT16_T
+ *
+ * size of a uint16_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_UINT16_T", INT2NUM(sizeof(uint16_t)));
+
/* Document-const: SIZEOF_INT32_T
*
* size of a int32_t
*/
rb_define_const(mFiddle, "SIZEOF_INT32_T", INT2NUM(sizeof(int32_t)));
+ /* Document-const: SIZEOF_UINT32_T
+ *
+ * size of a uint32_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_UINT32_T", INT2NUM(sizeof(uint32_t)));
+
/* Document-const: SIZEOF_INT64_T
*
* size of a int64_t
*/
rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t)));
+ /* Document-const: SIZEOF_UINT64_T
+ *
+ * size of a uint64_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_UINT64_T", INT2NUM(sizeof(uint64_t)));
+
/* Document-const: SIZEOF_FLOAT
*
* size of a float
@@ -540,6 +650,30 @@ Init_fiddle(void)
rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);
+ /* Document-const: Qtrue
+ *
+ * The value of Qtrue
+ */
+ rb_define_const(mFiddle, "Qtrue", INT2NUM(Qtrue));
+
+ /* Document-const: Qfalse
+ *
+ * The value of Qfalse
+ */
+ rb_define_const(mFiddle, "Qfalse", INT2NUM(Qfalse));
+
+ /* Document-const: Qnil
+ *
+ * The value of Qnil
+ */
+ rb_define_const(mFiddle, "Qnil", INT2NUM(Qnil));
+
+ /* Document-const: Qundef
+ *
+ * The value of Qundef
+ */
+ rb_define_const(mFiddle, "Qundef", INT2NUM(Qundef));
+
Init_fiddle_function();
Init_fiddle_closure();
Init_fiddle_handle();
diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec
index 509bec5ec9..878109395b 100644
--- a/ext/fiddle/fiddle.gemspec
+++ b/ext/fiddle/fiddle.gemspec
@@ -20,15 +20,12 @@ Gem::Specification.new do |spec|
"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",
@@ -58,9 +55,5 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.5.0"
- spec.add_development_dependency "bundler"
- spec.add_development_dependency "rake"
- spec.add_development_dependency "rake-compiler"
-
spec.metadata["msys2_mingw_dependencies"] = "libffi"
end
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
index 9de62a58cc..10eb9ceedb 100644
--- a/ext/fiddle/fiddle.h
+++ b/ext/fiddle/fiddle.h
@@ -111,11 +111,16 @@
#define TYPE_VOID 0
#define TYPE_VOIDP 1
#define TYPE_CHAR 2
+#define TYPE_UCHAR -TYPE_CHAR
#define TYPE_SHORT 3
+#define TYPE_USHORT -TYPE_SHORT
#define TYPE_INT 4
+#define TYPE_UINT -TYPE_INT
#define TYPE_LONG 5
+#define TYPE_ULONG -TYPE_LONG
#if HAVE_LONG_LONG
#define TYPE_LONG_LONG 6
+#define TYPE_ULONG_LONG -TYPE_LONG_LONG
#endif
#define TYPE_FLOAT 7
#define TYPE_DOUBLE 8
@@ -123,11 +128,18 @@
#define TYPE_CONST_STRING 10
#define TYPE_INT8_T TYPE_CHAR
+#define TYPE_UINT8_T -TYPE_INT8_T
+
#if SIZEOF_SHORT == 2
# define TYPE_INT16_T TYPE_SHORT
#elif SIZEOF_INT == 2
# define TYPE_INT16_T TYPE_INT
#endif
+
+#ifdef TYPE_INT16_T
+# define TYPE_UINT16_T -TYPE_INT16_T
+#endif
+
#if SIZEOF_SHORT == 4
# define TYPE_INT32_T TYPE_SHORT
#elif SIZEOF_INT == 4
@@ -135,6 +147,11 @@
#elif SIZEOF_LONG == 4
# define TYPE_INT32_T TYPE_LONG
#endif
+
+#ifdef TYPE_INT32_T
+#define TYPE_UINT32_T -TYPE_INT32_T
+#endif
+
#if SIZEOF_INT == 8
# define TYPE_INT64_T TYPE_INT
#elif SIZEOF_LONG == 8
@@ -143,6 +160,10 @@
# define TYPE_INT64_T TYPE_LONG_LONG
#endif
+#ifdef TYPE_INT64_T
+#define TYPE_UINT64_T -TYPE_INT64_T
+#endif
+
#ifndef TYPE_SSIZE_T
# if SIZEOF_SIZE_T == SIZEOF_INT
# define TYPE_SSIZE_T TYPE_INT
diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
index 76b90909d3..ae8cc3a581 100644
--- a/ext/fiddle/handle.c
+++ b/ext/fiddle/handle.c
@@ -321,8 +321,10 @@ rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
return fiddle_handle_sym(RTLD_NEXT, sym);
}
-static VALUE
-fiddle_handle_sym(void *handle, VALUE symbol)
+typedef void (*fiddle_void_func)(void);
+
+static fiddle_void_func
+fiddle_handle_find_func(void *handle, VALUE symbol)
{
#if defined(HAVE_DLERROR)
const char *err;
@@ -330,13 +332,13 @@ fiddle_handle_sym(void *handle, VALUE symbol)
#else
# define CHECK_DLERROR
#endif
- void (*func)();
+ fiddle_void_func func;
const char *name = StringValueCStr(symbol);
#ifdef HAVE_DLERROR
dlerror();
#endif
- func = (void (*)())(VALUE)dlsym(handle, name);
+ func = (fiddle_void_func)(VALUE)dlsym(handle, name);
CHECK_DLERROR;
#if defined(FUNC_STDCALL)
if( !func ){
@@ -379,6 +381,53 @@ fiddle_handle_sym(void *handle, VALUE symbol)
xfree(name_n);
}
#endif
+
+ return func;
+}
+
+static VALUE
+rb_fiddle_handle_s_sym_defined(VALUE self, VALUE sym)
+{
+ fiddle_void_func func;
+
+ func = fiddle_handle_find_func(RTLD_NEXT, sym);
+
+ if( func ) {
+ return PTR2NUM(func);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+static VALUE
+rb_fiddle_handle_sym_defined(VALUE self, VALUE sym)
+{
+ struct dl_handle *fiddle_handle;
+ fiddle_void_func func;
+
+ TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
+ if( ! fiddle_handle->open ){
+ rb_raise(rb_eFiddleDLError, "closed handle");
+ }
+
+ func = fiddle_handle_find_func(fiddle_handle->ptr, sym);
+
+ if( func ) {
+ return PTR2NUM(func);
+ }
+ else {
+ return Qnil;
+ }
+}
+
+static VALUE
+fiddle_handle_sym(void *handle, VALUE symbol)
+{
+ fiddle_void_func func;
+
+ func = fiddle_handle_find_func(handle, symbol);
+
if( !func ){
rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
}
@@ -468,6 +517,7 @@ Init_fiddle_handle(void)
rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject);
rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate);
rb_define_singleton_method(rb_cHandle, "sym", rb_fiddle_handle_s_sym, 1);
+ rb_define_singleton_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_s_sym_defined, 1);
rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1);
/* Document-const: NEXT
@@ -526,6 +576,7 @@ Init_fiddle_handle(void)
rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0);
rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1);
rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1);
+ rb_define_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_sym_defined, 1);
rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0);
rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0);
rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0);
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index 4512989310..6137c487c6 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -58,7 +58,36 @@ module Fiddle
#
# See Fiddle::Handle.new for more.
def dlopen library
- Fiddle::Handle.new library
+ begin
+ Fiddle::Handle.new(library)
+ rescue DLError => error
+ case RUBY_PLATFORM
+ when /linux/
+ case error.message
+ when /\A(\/.+?): (?:invalid ELF header|file too short)/
+ # This may be a linker script:
+ # https://sourceware.org/binutils/docs/ld.html#Scripts
+ path = $1
+ else
+ raise
+ end
+ else
+ raise
+ end
+
+ File.open(path) do |input|
+ input.each_line do |line|
+ case line
+ when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
+ # TODO: Should we support multiple files?
+ return dlopen($1)
+ end
+ end
+ end
+
+ # Not found
+ raise
+ end
end
module_function :dlopen
@@ -67,4 +96,8 @@ module Fiddle
RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc:
RTLD_LAZY = Handle::RTLD_LAZY # :nodoc:
RTLD_NOW = Handle::RTLD_NOW # :nodoc:
+
+ Fiddle::Types.constants.each do |type|
+ const_set "TYPE_#{type}", Fiddle::Types.const_get(type)
+ end
end
diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb
index c865a63c20..7e0077ea52 100644
--- a/ext/fiddle/lib/fiddle/closure.rb
+++ b/ext/fiddle/lib/fiddle/closure.rb
@@ -1,6 +1,31 @@
# frozen_string_literal: true
module Fiddle
class Closure
+ class << self
+ # Create a new closure. If a block is given, the created closure
+ # is automatically freed after the given block is executed.
+ #
+ # The all given arguments are passed to Fiddle::Closure.new. So
+ # using this method without block equals to Fiddle::Closure.new.
+ #
+ # == Example
+ #
+ # Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure|
+ # # closure is freed automatically when this block is finished.
+ # end
+ def create(*args)
+ if block_given?
+ closure = new(*args)
+ begin
+ yield(closure)
+ ensure
+ closure.free
+ end
+ else
+ new(*args)
+ end
+ end
+ end
# the C type of the return of the FFI closure
attr_reader :ctype
diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb
index 93a05513c9..9a70402953 100644
--- a/ext/fiddle/lib/fiddle/cparser.rb
+++ b/ext/fiddle/lib/fiddle/cparser.rb
@@ -164,23 +164,23 @@ module Fiddle
unless Fiddle.const_defined?(:TYPE_LONG_LONG)
raise(RuntimeError, "unsupported type: #{ty}")
end
- return -TYPE_LONG_LONG
+ return TYPE_ULONG_LONG
when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/
return TYPE_LONG
when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
- return -TYPE_LONG
+ return TYPE_ULONG
when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
return TYPE_INT
when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
- return -TYPE_INT
+ return TYPE_UINT
when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
return TYPE_SHORT
when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
- return -TYPE_SHORT
+ return TYPE_USHORT
when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
return TYPE_CHAR
when /\Aunsigned\s+char(?:\s+\w+)?\z/
- return -TYPE_CHAR
+ return TYPE_UCHAR
when /\Aint8_t(?:\s+\w+)?\z/
unless Fiddle.const_defined?(:TYPE_INT8_T)
raise(RuntimeError, "unsupported type: #{ty}")
@@ -190,7 +190,7 @@ module Fiddle
unless Fiddle.const_defined?(:TYPE_INT8_T)
raise(RuntimeError, "unsupported type: #{ty}")
end
- return -TYPE_INT8_T
+ return TYPE_UINT8_T
when /\Aint16_t(?:\s+\w+)?\z/
unless Fiddle.const_defined?(:TYPE_INT16_T)
raise(RuntimeError, "unsupported type: #{ty}")
@@ -200,7 +200,7 @@ module Fiddle
unless Fiddle.const_defined?(:TYPE_INT16_T)
raise(RuntimeError, "unsupported type: #{ty}")
end
- return -TYPE_INT16_T
+ return TYPE_UINT16_T
when /\Aint32_t(?:\s+\w+)?\z/
unless Fiddle.const_defined?(:TYPE_INT32_T)
raise(RuntimeError, "unsupported type: #{ty}")
@@ -210,7 +210,7 @@ module Fiddle
unless Fiddle.const_defined?(:TYPE_INT32_T)
raise(RuntimeError, "unsupported type: #{ty}")
end
- return -TYPE_INT32_T
+ return TYPE_UINT32_T
when /\Aint64_t(?:\s+\w+)?\z/
unless Fiddle.const_defined?(:TYPE_INT64_T)
raise(RuntimeError, "unsupported type: #{ty}")
@@ -220,7 +220,7 @@ module Fiddle
unless Fiddle.const_defined?(:TYPE_INT64_T)
raise(RuntimeError, "unsupported type: #{ty}")
end
- return -TYPE_INT64_T
+ return TYPE_UINT64_T
when /\Afloat(?:\s+\w+)?\z/
return TYPE_FLOAT
when /\Adouble(?:\s+\w+)?\z/
diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb
index 22eccedb76..545b985d50 100644
--- a/ext/fiddle/lib/fiddle/pack.rb
+++ b/ext/fiddle/lib/fiddle/pack.rb
@@ -11,24 +11,24 @@ module Fiddle
TYPE_LONG => ALIGN_LONG,
TYPE_FLOAT => ALIGN_FLOAT,
TYPE_DOUBLE => ALIGN_DOUBLE,
- -TYPE_CHAR => ALIGN_CHAR,
- -TYPE_SHORT => ALIGN_SHORT,
- -TYPE_INT => ALIGN_INT,
- -TYPE_LONG => ALIGN_LONG,
+ TYPE_UCHAR => ALIGN_CHAR,
+ TYPE_USHORT => ALIGN_SHORT,
+ TYPE_UINT => ALIGN_INT,
+ TYPE_ULONG => ALIGN_LONG,
}
PACK_MAP = {
- TYPE_VOIDP => "l!",
+ TYPE_VOIDP => "L!",
TYPE_CHAR => "c",
TYPE_SHORT => "s!",
TYPE_INT => "i!",
TYPE_LONG => "l!",
TYPE_FLOAT => "f",
TYPE_DOUBLE => "d",
- -TYPE_CHAR => "c",
- -TYPE_SHORT => "s!",
- -TYPE_INT => "i!",
- -TYPE_LONG => "l!",
+ TYPE_UCHAR => "C",
+ TYPE_USHORT => "S!",
+ TYPE_UINT => "I!",
+ TYPE_ULONG => "L!",
}
SIZE_MAP = {
@@ -39,16 +39,17 @@ module Fiddle
TYPE_LONG => SIZEOF_LONG,
TYPE_FLOAT => SIZEOF_FLOAT,
TYPE_DOUBLE => SIZEOF_DOUBLE,
- -TYPE_CHAR => SIZEOF_CHAR,
- -TYPE_SHORT => SIZEOF_SHORT,
- -TYPE_INT => SIZEOF_INT,
- -TYPE_LONG => SIZEOF_LONG,
+ TYPE_UCHAR => SIZEOF_CHAR,
+ TYPE_USHORT => SIZEOF_SHORT,
+ TYPE_UINT => SIZEOF_INT,
+ TYPE_ULONG => SIZEOF_LONG,
}
if defined?(TYPE_LONG_LONG)
- ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
- PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
- SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
- PACK_MAP[TYPE_VOIDP] = "q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP
+ ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG
+ PACK_MAP[TYPE_LONG_LONG] = "q"
+ PACK_MAP[TYPE_ULONG_LONG] = "Q"
+ SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[TYPE_ULONG_LONG] = SIZEOF_LONG_LONG
+ PACK_MAP[TYPE_VOIDP] = "Q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP
end
def align(addr, align)
diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb
index 2353edcc94..6d05bbd742 100644
--- a/ext/fiddle/lib/fiddle/struct.rb
+++ b/ext/fiddle/lib/fiddle/struct.rb
@@ -15,25 +15,53 @@ module Fiddle
def self.offsetof(name, members, types) # :nodoc:
offset = 0
- index = 0
- member_index = members.index(name)
-
- types.each { |type, count = 1|
- orig_offset = offset
- if type.respond_to?(:entity_class)
- align = type.alignment
- type_size = type.size
- else
- align = PackInfo::ALIGN_MAP[type]
- type_size = PackInfo::SIZE_MAP[type]
+ worklist = name.split('.')
+ this_type = self
+ while search_name = worklist.shift
+ index = 0
+ member_index = members.index(search_name)
+
+ unless member_index
+ # Possibly a sub-structure
+ member_index = members.index { |member_name, _|
+ member_name == search_name
+ }
+ return unless member_index
end
- offset = PackInfo.align(orig_offset, align)
- return offset if index == member_index
+ types.each { |type, count = 1|
+ orig_offset = offset
+ if type.respond_to?(:entity_class)
+ align = type.alignment
+ type_size = type.size
+ else
+ align = PackInfo::ALIGN_MAP[type]
+ type_size = PackInfo::SIZE_MAP[type]
+ end
+
+ # Unions shouldn't advance the offset
+ if this_type.entity_class == CUnionEntity
+ type_size = 0
+ end
- offset += (type_size * count)
- index += 1
- }
+ offset = PackInfo.align(orig_offset, align)
+
+ if worklist.empty?
+ return offset if index == member_index
+ else
+ if index == member_index
+ subtype = types[member_index]
+ members = subtype.members
+ types = subtype.types
+ this_type = subtype
+ break
+ end
+ end
+
+ offset += (type_size * count)
+ index += 1
+ }
+ end
nil
end
diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb
index db6504b650..719dc62e37 100644
--- a/ext/fiddle/lib/fiddle/version.rb
+++ b/ext/fiddle/lib/fiddle/version.rb
@@ -1,3 +1,3 @@
module Fiddle
- VERSION = "1.1.0"
+ VERSION = "1.1.1"
end
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index 5dec1a4c06..21454a73fa 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -75,7 +75,7 @@ getattr(int fd, conmode *t)
#define SET_LAST_ERROR (0)
#endif
-static ID id_getc, id_console, id_close, id_min, id_time, id_intr;
+static ID id_getc, id_console, id_close;
#if ENABLE_IO_GETPASS
static ID id_gets, id_chomp_bang;
#endif
@@ -90,6 +90,10 @@ extern VALUE rb_scheduler_timeout(struct timeval *timeout);
#define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv)
#ifndef HAVE_RB_F_SEND
+#ifndef RB_PASS_CALLED_KEYWORDS
+# define rb_funcallv_kw(recv, mid, arg, argv, kw_splat) rb_funcallv(recv, mid, arg, argv)
+#endif
+
static ID id___send__;
static VALUE
@@ -104,22 +108,38 @@ rb_f_send(int argc, VALUE *argv, VALUE recv)
else {
vid = id___send__;
}
- return rb_funcallv(recv, vid, argc, argv);
+ return rb_funcallv_kw(recv, vid, argc, argv, RB_PASS_CALLED_KEYWORDS);
}
#endif
+enum rawmode_opt_ids {
+ kwd_min,
+ kwd_time,
+ kwd_intr,
+ rawmode_opt_id_count
+};
+static ID rawmode_opt_ids[rawmode_opt_id_count];
+
typedef struct {
int vmin;
int vtime;
int intr;
} rawmode_arg_t;
+#ifndef UNDEF_P
+# define UNDEF_P(obj) ((obj) == Qundef)
+#endif
+#ifndef NIL_OR_UNDEF_P
+# define NIL_OR_UNDEF_P(obj) (NIL_P(obj) || UNDEF_P(obj))
+#endif
+
static rawmode_arg_t *
rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *opts)
{
int argc = *argcp;
rawmode_arg_t *optp = NULL;
VALUE vopts = Qnil;
+ VALUE optvals[rawmode_opt_id_count];
#ifdef RB_SCAN_ARGS_PASS_CALLED_KEYWORDS
argc = rb_scan_args(argc, argv, "*:", NULL, &vopts);
#else
@@ -134,19 +154,20 @@ rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *
}
#endif
rb_check_arity(argc, min_argc, max_argc);
- if (!NIL_P(vopts)) {
- VALUE vmin = rb_hash_aref(vopts, ID2SYM(id_min));
- VALUE vtime = rb_hash_aref(vopts, ID2SYM(id_time));
- VALUE intr = rb_hash_aref(vopts, ID2SYM(id_intr));
+ if (rb_get_kwargs(vopts, rawmode_opt_ids,
+ 0, rawmode_opt_id_count, optvals)) {
+ VALUE vmin = optvals[kwd_min];
+ VALUE vtime = optvals[kwd_time];
+ VALUE intr = optvals[kwd_intr];
/* default values by `stty raw` */
opts->vmin = 1;
opts->vtime = 0;
opts->intr = 0;
- if (!NIL_P(vmin)) {
+ if (!NIL_OR_UNDEF_P(vmin)) {
opts->vmin = NUM2INT(vmin);
optp = opts;
}
- if (!NIL_P(vtime)) {
+ if (!NIL_OR_UNDEF_P(vtime)) {
VALUE v10 = INT2FIX(10);
vtime = rb_funcall3(vtime, '*', 1, &v10);
opts->vtime = NUM2INT(vtime);
@@ -161,6 +182,7 @@ rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *
opts->intr = 0;
optp = opts;
break;
+ case Qundef:
case Qnil:
break;
default:
@@ -555,8 +577,8 @@ console_getch(int argc, VALUE *argv, VALUE io)
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;
+ VALUE result = rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
+ if (!RTEST(result)) return Qnil;
# endif
}
else if (optp->vtime) {
@@ -1629,9 +1651,11 @@ Init_console(void)
#endif
id_console = rb_intern("console");
id_close = rb_intern("close");
- id_min = rb_intern("min");
- id_time = rb_intern("time");
- id_intr = rb_intern("intr");
+#define init_rawmode_opt_id(name) \
+ rawmode_opt_ids[kwd_##name] = rb_intern(#name)
+ init_rawmode_opt_id(min);
+ init_rawmode_opt_id(time);
+ init_rawmode_opt_id(intr);
#ifndef HAVE_RB_F_SEND
id___send__ = rb_intern("__send__");
#endif
diff --git a/ext/io/console/depend b/ext/io/console/depend
index 0721f0e777..36747ef583 100644
--- a/ext/io/console/depend
+++ b/ext/io/console/depend
@@ -7,7 +7,6 @@ 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
@@ -17,6 +16,7 @@ console.o: $(hdrdir)/ruby/defines.h
console.o: $(hdrdir)/ruby/encoding.h
console.o: $(hdrdir)/ruby/fiber/scheduler.h
console.o: $(hdrdir)/ruby/intern.h
+console.o: $(hdrdir)/ruby/internal/abi.h
console.o: $(hdrdir)/ruby/internal/anyargs.h
console.o: $(hdrdir)/ruby/internal/arithmetic.h
console.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -86,6 +86,15 @@ console.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
console.o: $(hdrdir)/ruby/internal/ctype.h
console.o: $(hdrdir)/ruby/internal/dllexport.h
console.o: $(hdrdir)/ruby/internal/dosish.h
+console.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+console.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+console.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+console.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+console.o: $(hdrdir)/ruby/internal/encoding/re.h
+console.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+console.o: $(hdrdir)/ruby/internal/encoding/string.h
+console.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+console.o: $(hdrdir)/ruby/internal/encoding/transcode.h
console.o: $(hdrdir)/ruby/internal/error.h
console.o: $(hdrdir)/ruby/internal/eval.h
console.o: $(hdrdir)/ruby/internal/event.h
@@ -176,7 +185,7 @@ win32_vk.inc: win32_vk.list
-e 'n=$$F[1] and (n.strip!; /\AVK_/=~n) and' \
-e 'puts(%[#ifndef #{n}\n# define #{n} UNDEFINED_VK\n#endif])' \
$< && \
- gperf --ignore-case -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \
+ gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \
| sed -f $(top_srcdir)/tool/gperf.sed \
) > $(@F)
diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec
index dabe9e68f8..d26a757b01 100644
--- a/ext/io/console/io-console.gemspec
+++ b/ext/io/console/io-console.gemspec
@@ -1,5 +1,5 @@
# -*- ruby -*-
-_VERSION = "0.5.9"
+_VERSION = "0.6.0"
Gem::Specification.new do |s|
s.name = "io-console"
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
s.summary = "Console interface"
s.email = "nobu@ruby-lang.org"
s.description = "add console capabilities to IO instances."
- s.required_ruby_version = ">= 2.4.0"
+ s.required_ruby_version = ">= 2.6.0"
s.homepage = "https://github.com/ruby/io-console"
s.metadata["source_code_url"] = s.homepage
s.authors = ["Nobu Nakada"]
diff --git a/ext/io/console/win32_vk.inc b/ext/io/console/win32_vk.inc
index cbec7bef15..d15b1219fb 100644
--- a/ext/io/console/win32_vk.inc
+++ b/ext/io/console/win32_vk.inc
@@ -480,7 +480,7 @@
# define VK_OEM_CLEAR UNDEFINED_VK
#endif
/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf --ignore-case -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */
+/* Command-line: gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -509,18 +509,17 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
#endif
-#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n)
#line 1 "win32_vk.list"
struct vktable {short ofs; unsigned short vk;};
-static const struct vktable *console_win32_vk(/*const char *, unsigned int*/);
+static const struct vktable *console_win32_vk(const char *, size_t);
#line 5 "win32_vk.list"
struct vktable;
/* maximum key range = 245, duplicates = 0 */
#ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1
-static unsigned char gperf_downcase[256] =
+static const unsigned char gperf_downcase[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
@@ -1007,368 +1006,368 @@ console_win32_vk (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
#line 40 "win32_vk.list"
- {gperf_offsetof(stringpool, 12), VK_UP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str12, VK_UP},
#line 52 "win32_vk.list"
- {gperf_offsetof(stringpool, 13), VK_APPS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, VK_APPS},
#line 159 "win32_vk.list"
- {gperf_offsetof(stringpool, 14), VK_CRSEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, VK_CRSEL},
#line 34 "win32_vk.list"
- {gperf_offsetof(stringpool, 15), VK_SPACE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15, VK_SPACE},
#line 95 "win32_vk.list"
- {gperf_offsetof(stringpool, 16), VK_SCROLL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16, VK_SCROLL},
#line 29 "win32_vk.list"
- {gperf_offsetof(stringpool, 17), VK_ESCAPE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17, VK_ESCAPE},
#line 9 "win32_vk.list"
- {gperf_offsetof(stringpool, 18), VK_CANCEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18, VK_CANCEL},
#line 32 "win32_vk.list"
- {gperf_offsetof(stringpool, 19), VK_ACCEPT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, VK_ACCEPT},
#line 66 "win32_vk.list"
- {gperf_offsetof(stringpool, 20), VK_SEPARATOR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20, VK_SEPARATOR},
#line 43 "win32_vk.list"
- {gperf_offsetof(stringpool, 21), VK_SELECT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, VK_SELECT},
#line 18 "win32_vk.list"
- {gperf_offsetof(stringpool, 22), VK_CONTROL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, VK_CONTROL},
#line 166 "win32_vk.list"
- {gperf_offsetof(stringpool, 23), VK_OEM_CLEAR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str23, VK_OEM_CLEAR},
#line 145 "win32_vk.list"
- {gperf_offsetof(stringpool, 24), VK_OEM_RESET},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24, VK_OEM_RESET},
#line 155 "win32_vk.list"
- {gperf_offsetof(stringpool, 25), VK_OEM_AUTO},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25, VK_OEM_AUTO},
#line 151 "win32_vk.list"
- {gperf_offsetof(stringpool, 26), VK_OEM_CUSEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, VK_OEM_CUSEL},
{-1},
#line 22 "win32_vk.list"
- {gperf_offsetof(stringpool, 28), VK_KANA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, VK_KANA},
#line 127 "win32_vk.list"
- {gperf_offsetof(stringpool, 29), VK_OEM_PLUS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, VK_OEM_PLUS},
#line 35 "win32_vk.list"
- {gperf_offsetof(stringpool, 30), VK_PRIOR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, VK_PRIOR},
#line 152 "win32_vk.list"
- {gperf_offsetof(stringpool, 31), VK_OEM_ATTN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, VK_OEM_ATTN},
#line 20 "win32_vk.list"
- {gperf_offsetof(stringpool, 32), VK_PAUSE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32, VK_PAUSE},
#line 13 "win32_vk.list"
- {gperf_offsetof(stringpool, 33), VK_BACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, VK_BACK},
#line 144 "win32_vk.list"
- {gperf_offsetof(stringpool, 34), VK_PACKET},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str34, VK_PACKET},
#line 105 "win32_vk.list"
- {gperf_offsetof(stringpool, 35), VK_RCONTROL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, VK_RCONTROL},
#line 104 "win32_vk.list"
- {gperf_offsetof(stringpool, 36), VK_LCONTROL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, VK_LCONTROL},
#line 37 "win32_vk.list"
- {gperf_offsetof(stringpool, 37), VK_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, VK_END},
#line 38 "win32_vk.list"
- {gperf_offsetof(stringpool, 38), VK_HOME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, VK_HOME},
#line 44 "win32_vk.list"
- {gperf_offsetof(stringpool, 39), VK_PRINT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39, VK_PRINT},
#line 94 "win32_vk.list"
- {gperf_offsetof(stringpool, 40), VK_NUMLOCK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str40, VK_NUMLOCK},
#line 39 "win32_vk.list"
- {gperf_offsetof(stringpool, 41), VK_LEFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41, VK_LEFT},
#line 25 "win32_vk.list"
- {gperf_offsetof(stringpool, 42), VK_JUNJA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42, VK_JUNJA},
#line 19 "win32_vk.list"
- {gperf_offsetof(stringpool, 43), VK_MENU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43, VK_MENU},
#line 150 "win32_vk.list"
- {gperf_offsetof(stringpool, 44), VK_OEM_WSCTRL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, VK_OEM_WSCTRL},
#line 156 "win32_vk.list"
- {gperf_offsetof(stringpool, 45), VK_OEM_ENLW},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, VK_OEM_ENLW},
#line 36 "win32_vk.list"
- {gperf_offsetof(stringpool, 46), VK_NEXT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46, VK_NEXT},
#line 51 "win32_vk.list"
- {gperf_offsetof(stringpool, 47), VK_RWIN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, VK_RWIN},
#line 50 "win32_vk.list"
- {gperf_offsetof(stringpool, 48), VK_LWIN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48, VK_LWIN},
#line 21 "win32_vk.list"
- {gperf_offsetof(stringpool, 49), VK_CAPITAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, VK_CAPITAL},
#line 49 "win32_vk.list"
- {gperf_offsetof(stringpool, 50), VK_HELP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str50, VK_HELP},
#line 164 "win32_vk.list"
- {gperf_offsetof(stringpool, 51), VK_NONAME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str51, VK_NONAME},
#line 8 "win32_vk.list"
- {gperf_offsetof(stringpool, 52), VK_RBUTTON},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, VK_RBUTTON},
#line 7 "win32_vk.list"
- {gperf_offsetof(stringpool, 53), VK_LBUTTON},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53, VK_LBUTTON},
#line 96 "win32_vk.list"
- {gperf_offsetof(stringpool, 54), VK_OEM_NEC_EQUAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54, VK_OEM_NEC_EQUAL},
{-1},
#line 47 "win32_vk.list"
- {gperf_offsetof(stringpool, 56), VK_INSERT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str56, VK_INSERT},
#line 27 "win32_vk.list"
- {gperf_offsetof(stringpool, 57), VK_HANJA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57, VK_HANJA},
{-1}, {-1},
#line 46 "win32_vk.list"
- {gperf_offsetof(stringpool, 60), VK_SNAPSHOT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, VK_SNAPSHOT},
#line 158 "win32_vk.list"
- {gperf_offsetof(stringpool, 61), VK_ATTN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61, VK_ATTN},
#line 14 "win32_vk.list"
- {gperf_offsetof(stringpool, 62), VK_TAB},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, VK_TAB},
#line 157 "win32_vk.list"
- {gperf_offsetof(stringpool, 63), VK_OEM_BACKTAB},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, VK_OEM_BACKTAB},
#line 143 "win32_vk.list"
- {gperf_offsetof(stringpool, 64), VK_ICO_CLEAR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, VK_ICO_CLEAR},
#line 30 "win32_vk.list"
- {gperf_offsetof(stringpool, 65), VK_CONVERT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, VK_CONVERT},
#line 16 "win32_vk.list"
- {gperf_offsetof(stringpool, 66), VK_RETURN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66, VK_RETURN},
#line 146 "win32_vk.list"
- {gperf_offsetof(stringpool, 67), VK_OEM_JUMP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67, VK_OEM_JUMP},
{-1}, {-1}, {-1},
#line 111 "win32_vk.list"
- {gperf_offsetof(stringpool, 71), VK_BROWSER_STOP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, VK_BROWSER_STOP},
#line 26 "win32_vk.list"
- {gperf_offsetof(stringpool, 72), VK_FINAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72, VK_FINAL},
#line 163 "win32_vk.list"
- {gperf_offsetof(stringpool, 73), VK_ZOOM},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str73, VK_ZOOM},
#line 28 "win32_vk.list"
- {gperf_offsetof(stringpool, 74), VK_KANJI},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74, VK_KANJI},
#line 48 "win32_vk.list"
- {gperf_offsetof(stringpool, 75), VK_DELETE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75, VK_DELETE},
#line 128 "win32_vk.list"
- {gperf_offsetof(stringpool, 76), VK_OEM_COMMA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, VK_OEM_COMMA},
#line 67 "win32_vk.list"
- {gperf_offsetof(stringpool, 77), VK_SUBTRACT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77, VK_SUBTRACT},
{-1},
#line 10 "win32_vk.list"
- {gperf_offsetof(stringpool, 79), VK_MBUTTON},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79, VK_MBUTTON},
#line 78 "win32_vk.list"
- {gperf_offsetof(stringpool, 80), VK_F9},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, VK_F9},
#line 17 "win32_vk.list"
- {gperf_offsetof(stringpool, 81), VK_SHIFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81, VK_SHIFT},
#line 103 "win32_vk.list"
- {gperf_offsetof(stringpool, 82), VK_RSHIFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, VK_RSHIFT},
#line 102 "win32_vk.list"
- {gperf_offsetof(stringpool, 83), VK_LSHIFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str83, VK_LSHIFT},
#line 65 "win32_vk.list"
- {gperf_offsetof(stringpool, 84), VK_ADD},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84, VK_ADD},
#line 31 "win32_vk.list"
- {gperf_offsetof(stringpool, 85), VK_NONCONVERT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85, VK_NONCONVERT},
#line 160 "win32_vk.list"
- {gperf_offsetof(stringpool, 86), VK_EXSEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str86, VK_EXSEL},
#line 126 "win32_vk.list"
- {gperf_offsetof(stringpool, 87), VK_OEM_1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str87, VK_OEM_1},
#line 138 "win32_vk.list"
- {gperf_offsetof(stringpool, 88), VK_OEM_AX},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, VK_OEM_AX},
#line 108 "win32_vk.list"
- {gperf_offsetof(stringpool, 89), VK_BROWSER_BACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89, VK_BROWSER_BACK},
#line 137 "win32_vk.list"
- {gperf_offsetof(stringpool, 90), VK_OEM_8},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90, VK_OEM_8},
#line 129 "win32_vk.list"
- {gperf_offsetof(stringpool, 91), VK_OEM_MINUS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91, VK_OEM_MINUS},
#line 162 "win32_vk.list"
- {gperf_offsetof(stringpool, 92), VK_PLAY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92, VK_PLAY},
#line 131 "win32_vk.list"
- {gperf_offsetof(stringpool, 93), VK_OEM_2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93, VK_OEM_2},
#line 15 "win32_vk.list"
- {gperf_offsetof(stringpool, 94), VK_CLEAR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, VK_CLEAR},
#line 99 "win32_vk.list"
- {gperf_offsetof(stringpool, 95), VK_OEM_FJ_TOUROKU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95, VK_OEM_FJ_TOUROKU},
#line 147 "win32_vk.list"
- {gperf_offsetof(stringpool, 96), VK_OEM_PA1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96, VK_OEM_PA1},
#line 140 "win32_vk.list"
- {gperf_offsetof(stringpool, 97), VK_ICO_HELP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, VK_ICO_HELP},
#line 112 "win32_vk.list"
- {gperf_offsetof(stringpool, 98), VK_BROWSER_SEARCH},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str98, VK_BROWSER_SEARCH},
#line 53 "win32_vk.list"
- {gperf_offsetof(stringpool, 99), VK_SLEEP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str99, VK_SLEEP},
{-1},
#line 70 "win32_vk.list"
- {gperf_offsetof(stringpool, 101), VK_F1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101, VK_F1},
#line 148 "win32_vk.list"
- {gperf_offsetof(stringpool, 102), VK_OEM_PA2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102, VK_OEM_PA2},
#line 154 "win32_vk.list"
- {gperf_offsetof(stringpool, 103), VK_OEM_COPY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103, VK_OEM_COPY},
#line 77 "win32_vk.list"
- {gperf_offsetof(stringpool, 104), VK_F8},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, VK_F8},
#line 88 "win32_vk.list"
- {gperf_offsetof(stringpool, 105), VK_F19},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, VK_F19},
#line 41 "win32_vk.list"
- {gperf_offsetof(stringpool, 106), VK_RIGHT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106, VK_RIGHT},
#line 71 "win32_vk.list"
- {gperf_offsetof(stringpool, 107), VK_F2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, VK_F2},
#line 135 "win32_vk.list"
- {gperf_offsetof(stringpool, 108), VK_OEM_6},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, VK_OEM_6},
#line 87 "win32_vk.list"
- {gperf_offsetof(stringpool, 109), VK_F18},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, VK_F18},
{-1},
#line 117 "win32_vk.list"
- {gperf_offsetof(stringpool, 111), VK_VOLUME_UP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, VK_VOLUME_UP},
{-1}, {-1},
#line 120 "win32_vk.list"
- {gperf_offsetof(stringpool, 114), VK_MEDIA_STOP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, VK_MEDIA_STOP},
#line 130 "win32_vk.list"
- {gperf_offsetof(stringpool, 115), VK_OEM_PERIOD},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str115, VK_OEM_PERIOD},
{-1},
#line 161 "win32_vk.list"
- {gperf_offsetof(stringpool, 117), VK_EREOF},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, VK_EREOF},
{-1}, {-1}, {-1},
#line 114 "win32_vk.list"
- {gperf_offsetof(stringpool, 121), VK_BROWSER_HOME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, VK_BROWSER_HOME},
#line 75 "win32_vk.list"
- {gperf_offsetof(stringpool, 122), VK_F6},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122, VK_F6},
{-1},
#line 110 "win32_vk.list"
- {gperf_offsetof(stringpool, 124), VK_BROWSER_REFRESH},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124, VK_BROWSER_REFRESH},
{-1},
#line 165 "win32_vk.list"
- {gperf_offsetof(stringpool, 126), VK_PA1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, VK_PA1},
#line 142 "win32_vk.list"
- {gperf_offsetof(stringpool, 127), VK_PROCESSKEY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127, VK_PROCESSKEY},
#line 68 "win32_vk.list"
- {gperf_offsetof(stringpool, 128), VK_DECIMAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128, VK_DECIMAL},
#line 132 "win32_vk.list"
- {gperf_offsetof(stringpool, 129), VK_OEM_3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129, VK_OEM_3},
#line 107 "win32_vk.list"
- {gperf_offsetof(stringpool, 130), VK_RMENU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, VK_RMENU},
#line 106 "win32_vk.list"
- {gperf_offsetof(stringpool, 131), VK_LMENU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, VK_LMENU},
#line 98 "win32_vk.list"
- {gperf_offsetof(stringpool, 132), VK_OEM_FJ_MASSHOU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, VK_OEM_FJ_MASSHOU},
#line 54 "win32_vk.list"
- {gperf_offsetof(stringpool, 133), VK_NUMPAD0},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133, VK_NUMPAD0},
#line 24 "win32_vk.list"
- {gperf_offsetof(stringpool, 134), VK_HANGUL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, VK_HANGUL},
#line 63 "win32_vk.list"
- {gperf_offsetof(stringpool, 135), VK_NUMPAD9},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, VK_NUMPAD9},
#line 23 "win32_vk.list"
- {gperf_offsetof(stringpool, 136), VK_HANGEUL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str136, VK_HANGEUL},
#line 134 "win32_vk.list"
- {gperf_offsetof(stringpool, 137), VK_OEM_5},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137, VK_OEM_5},
#line 149 "win32_vk.list"
- {gperf_offsetof(stringpool, 138), VK_OEM_PA3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str138, VK_OEM_PA3},
#line 115 "win32_vk.list"
- {gperf_offsetof(stringpool, 139), VK_VOLUME_MUTE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str139, VK_VOLUME_MUTE},
#line 133 "win32_vk.list"
- {gperf_offsetof(stringpool, 140), VK_OEM_4},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str140, VK_OEM_4},
#line 122 "win32_vk.list"
- {gperf_offsetof(stringpool, 141), VK_LAUNCH_MAIL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str141, VK_LAUNCH_MAIL},
#line 97 "win32_vk.list"
- {gperf_offsetof(stringpool, 142), VK_OEM_FJ_JISHO},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str142, VK_OEM_FJ_JISHO},
#line 72 "win32_vk.list"
- {gperf_offsetof(stringpool, 143), VK_F3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143, VK_F3},
#line 101 "win32_vk.list"
- {gperf_offsetof(stringpool, 144), VK_OEM_FJ_ROYA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144, VK_OEM_FJ_ROYA},
#line 100 "win32_vk.list"
- {gperf_offsetof(stringpool, 145), VK_OEM_FJ_LOYA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, VK_OEM_FJ_LOYA},
{-1},
#line 42 "win32_vk.list"
- {gperf_offsetof(stringpool, 147), VK_DOWN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147, VK_DOWN},
{-1},
#line 153 "win32_vk.list"
- {gperf_offsetof(stringpool, 149), VK_OEM_FINISH},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149, VK_OEM_FINISH},
{-1},
#line 74 "win32_vk.list"
- {gperf_offsetof(stringpool, 151), VK_F5},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, VK_F5},
{-1},
#line 136 "win32_vk.list"
- {gperf_offsetof(stringpool, 153), VK_OEM_7},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str153, VK_OEM_7},
#line 73 "win32_vk.list"
- {gperf_offsetof(stringpool, 154), VK_F4},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, VK_F4},
#line 86 "win32_vk.list"
- {gperf_offsetof(stringpool, 155), VK_F17},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str155, VK_F17},
#line 55 "win32_vk.list"
- {gperf_offsetof(stringpool, 156), VK_NUMPAD1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str156, VK_NUMPAD1},
#line 141 "win32_vk.list"
- {gperf_offsetof(stringpool, 157), VK_ICO_00},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str157, VK_ICO_00},
{-1},
#line 62 "win32_vk.list"
- {gperf_offsetof(stringpool, 159), VK_NUMPAD8},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str159, VK_NUMPAD8},
{-1}, {-1},
#line 56 "win32_vk.list"
- {gperf_offsetof(stringpool, 162), VK_NUMPAD2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162, VK_NUMPAD2},
{-1},
#line 124 "win32_vk.list"
- {gperf_offsetof(stringpool, 164), VK_LAUNCH_APP1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, VK_LAUNCH_APP1},
#line 109 "win32_vk.list"
- {gperf_offsetof(stringpool, 165), VK_BROWSER_FORWARD},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str165, VK_BROWSER_FORWARD},
{-1},
#line 76 "win32_vk.list"
- {gperf_offsetof(stringpool, 167), VK_F7},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, VK_F7},
{-1}, {-1},
#line 125 "win32_vk.list"
- {gperf_offsetof(stringpool, 170), VK_LAUNCH_APP2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170, VK_LAUNCH_APP2},
#line 64 "win32_vk.list"
- {gperf_offsetof(stringpool, 171), VK_MULTIPLY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171, VK_MULTIPLY},
{-1}, {-1},
#line 45 "win32_vk.list"
- {gperf_offsetof(stringpool, 174), VK_EXECUTE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174, VK_EXECUTE},
{-1},
#line 113 "win32_vk.list"
- {gperf_offsetof(stringpool, 176), VK_BROWSER_FAVORITES},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176, VK_BROWSER_FAVORITES},
#line 60 "win32_vk.list"
- {gperf_offsetof(stringpool, 177), VK_NUMPAD6},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177, VK_NUMPAD6},
{-1},
#line 85 "win32_vk.list"
- {gperf_offsetof(stringpool, 179), VK_F16},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179, VK_F16},
{-1}, {-1},
#line 79 "win32_vk.list"
- {gperf_offsetof(stringpool, 182), VK_F10},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182, VK_F10},
{-1}, {-1},
#line 116 "win32_vk.list"
- {gperf_offsetof(stringpool, 185), VK_VOLUME_DOWN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, VK_VOLUME_DOWN},
{-1}, {-1},
#line 89 "win32_vk.list"
- {gperf_offsetof(stringpool, 188), VK_F20},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, VK_F20},
#line 119 "win32_vk.list"
- {gperf_offsetof(stringpool, 189), VK_MEDIA_PREV_TRACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, VK_MEDIA_PREV_TRACK},
{-1},
#line 33 "win32_vk.list"
- {gperf_offsetof(stringpool, 191), VK_MODECHANGE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, VK_MODECHANGE},
{-1}, {-1}, {-1}, {-1}, {-1},
#line 83 "win32_vk.list"
- {gperf_offsetof(stringpool, 197), VK_F14},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197, VK_F14},
#line 57 "win32_vk.list"
- {gperf_offsetof(stringpool, 198), VK_NUMPAD3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, VK_NUMPAD3},
#line 11 "win32_vk.list"
- {gperf_offsetof(stringpool, 199), VK_XBUTTON1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199, VK_XBUTTON1},
{-1}, {-1}, {-1},
#line 93 "win32_vk.list"
- {gperf_offsetof(stringpool, 203), VK_F24},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, VK_F24},
{-1},
#line 12 "win32_vk.list"
- {gperf_offsetof(stringpool, 205), VK_XBUTTON2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, VK_XBUTTON2},
#line 59 "win32_vk.list"
- {gperf_offsetof(stringpool, 206), VK_NUMPAD5},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206, VK_NUMPAD5},
{-1}, {-1},
#line 58 "win32_vk.list"
- {gperf_offsetof(stringpool, 209), VK_NUMPAD4},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, VK_NUMPAD4},
{-1}, {-1}, {-1}, {-1}, {-1},
#line 121 "win32_vk.list"
- {gperf_offsetof(stringpool, 215), VK_MEDIA_PLAY_PAUSE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215, VK_MEDIA_PLAY_PAUSE},
{-1},
#line 123 "win32_vk.list"
- {gperf_offsetof(stringpool, 217), VK_LAUNCH_MEDIA_SELECT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, VK_LAUNCH_MEDIA_SELECT},
#line 80 "win32_vk.list"
- {gperf_offsetof(stringpool, 218), VK_F11},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, VK_F11},
{-1},
#line 139 "win32_vk.list"
- {gperf_offsetof(stringpool, 220), VK_OEM_102},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, VK_OEM_102},
#line 118 "win32_vk.list"
- {gperf_offsetof(stringpool, 221), VK_MEDIA_NEXT_TRACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, VK_MEDIA_NEXT_TRACK},
#line 61 "win32_vk.list"
- {gperf_offsetof(stringpool, 222), VK_NUMPAD7},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str222, VK_NUMPAD7},
{-1},
#line 90 "win32_vk.list"
- {gperf_offsetof(stringpool, 224), VK_F21},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, VK_F21},
{-1},
#line 82 "win32_vk.list"
- {gperf_offsetof(stringpool, 226), VK_F13},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str226, VK_F13},
{-1}, {-1},
#line 81 "win32_vk.list"
- {gperf_offsetof(stringpool, 229), VK_F12},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229, VK_F12},
{-1}, {-1},
#line 92 "win32_vk.list"
- {gperf_offsetof(stringpool, 232), VK_F23},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232, VK_F23},
{-1}, {-1},
#line 91 "win32_vk.list"
- {gperf_offsetof(stringpool, 235), VK_F22},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, VK_F22},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#line 84 "win32_vk.list"
- {gperf_offsetof(stringpool, 242), VK_F15},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242, VK_F15},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
#line 69 "win32_vk.list"
- {gperf_offsetof(stringpool, 256), VK_DIVIDE}
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, VK_DIVIDE}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/ext/io/console/win32_vk.list b/ext/io/console/win32_vk.list
index 7909a4d1f0..5df3d6da57 100644
--- a/ext/io/console/win32_vk.list
+++ b/ext/io/console/win32_vk.list
@@ -1,6 +1,6 @@
%{
struct vktable {short ofs; unsigned short vk;};
-static const struct vktable *console_win32_vk(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/);
+static const struct vktable *console_win32_vk(const char *, size_t);
%}
struct vktable
%%
diff --git a/ext/io/nonblock/depend b/ext/io/nonblock/depend
index 1a9fa7c42f..7f2db65732 100644
--- a/ext/io/nonblock/depend
+++ b/ext/io/nonblock/depend
@@ -2,6 +2,20 @@
nonblock.o: $(RUBY_EXTCONF_H)
nonblock.o: $(arch_hdrdir)/ruby/config.h
nonblock.o: $(hdrdir)/ruby.h
+nonblock.o: $(hdrdir)/ruby/assert.h
+nonblock.o: $(hdrdir)/ruby/backward.h
+nonblock.o: $(hdrdir)/ruby/backward/2/assume.h
+nonblock.o: $(hdrdir)/ruby/backward/2/attributes.h
+nonblock.o: $(hdrdir)/ruby/backward/2/bool.h
+nonblock.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nonblock.o: $(hdrdir)/ruby/backward/2/limits.h
+nonblock.o: $(hdrdir)/ruby/backward/2/long_long.h
+nonblock.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nonblock.o: $(hdrdir)/ruby/backward/2/stdarg.h
+nonblock.o: $(hdrdir)/ruby/defines.h
+nonblock.o: $(hdrdir)/ruby/encoding.h
+nonblock.o: $(hdrdir)/ruby/intern.h
+nonblock.o: $(hdrdir)/ruby/internal/abi.h
nonblock.o: $(hdrdir)/ruby/internal/anyargs.h
nonblock.o: $(hdrdir)/ruby/internal/arithmetic.h
nonblock.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ nonblock.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
nonblock.o: $(hdrdir)/ruby/internal/ctype.h
nonblock.o: $(hdrdir)/ruby/internal/dllexport.h
nonblock.o: $(hdrdir)/ruby/internal/dosish.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/re.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/string.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+nonblock.o: $(hdrdir)/ruby/internal/encoding/transcode.h
nonblock.o: $(hdrdir)/ruby/internal/error.h
nonblock.o: $(hdrdir)/ruby/internal/eval.h
nonblock.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
nonblock.o: $(hdrdir)/ruby/io.h
nonblock.o: $(hdrdir)/ruby/missing.h
nonblock.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/io/nonblock/io-nonblock.gemspec b/ext/io/nonblock/io-nonblock.gemspec
index 34d736650b..d6df21a84d 100644
--- a/ext/io/nonblock/io-nonblock.gemspec
+++ b/ext/io/nonblock/io-nonblock.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "io-nonblock"
- spec.version = "0.1.0"
+ spec.version = "0.2.0"
spec.authors = ["Nobu Nakada"]
spec.email = ["nobu@ruby-lang.org"]
@@ -13,13 +13,13 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- %x[git ls-files -z].split("\x0").reject do |f|
- f.match(%r{\A(?:test|spec|features)/|\A\.(?:git|travis)})
- end
- end
+ spec.files = %w[
+ COPYING
+ README.md
+ ext/io/nonblock/depend
+ ext/io/nonblock/extconf.rb
+ ext/io/nonblock/nonblock.c
+ ]
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/nonblock/nonblock.c b/ext/io/nonblock/nonblock.c
index 1c0bdc68e7..b8a40ff38e 100644
--- a/ext/io/nonblock/nonblock.c
+++ b/ext/io/nonblock/nonblock.c
@@ -19,14 +19,14 @@
#ifdef F_GETFL
static int
-io_nonblock_mode(int fd)
+get_fcntl_flags(int fd)
{
int f = fcntl(fd, F_GETFL);
if (f == -1) rb_sys_fail(0);
return f;
}
#else
-#define io_nonblock_mode(fd) ((void)(fd), 0)
+#define get_fcntl_flags(fd) ((void)(fd), 0)
#endif
#ifdef F_GETFL
@@ -41,7 +41,7 @@ rb_io_nonblock_p(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
- if (io_nonblock_mode(fptr->fd) & O_NONBLOCK)
+ if (get_fcntl_flags(fptr->fd) & O_NONBLOCK)
return Qtrue;
return Qfalse;
}
@@ -50,6 +50,13 @@ rb_io_nonblock_p(VALUE io)
#endif
#ifdef F_SETFL
+static void
+set_fcntl_flags(int fd, int f)
+{
+ if (fcntl(fd, F_SETFL, f) == -1)
+ rb_sys_fail(0);
+}
+
static int
io_nonblock_set(int fd, int f, int nb)
{
@@ -63,8 +70,7 @@ io_nonblock_set(int fd, int f, int nb)
return 0;
f &= ~O_NONBLOCK;
}
- if (fcntl(fd, F_SETFL, f) == -1)
- rb_sys_fail(0);
+ set_fcntl_flags(fd, f);
return 1;
}
@@ -74,6 +80,46 @@ io_nonblock_set(int fd, int f, int nb)
*
* Enables non-blocking mode on a stream when set to
* +true+, and blocking mode when set to +false+.
+ *
+ * This method set or clear O_NONBLOCK flag for the file descriptor
+ * in <em>ios</em>.
+ *
+ * The behavior of most IO methods is not affected by this flag
+ * because they retry system calls to complete their task
+ * after EAGAIN and partial read/write.
+ * (An exception is IO#syswrite which doesn't retry.)
+ *
+ * This method can be used to clear non-blocking mode of standard I/O.
+ * Since nonblocking methods (read_nonblock, etc.) set non-blocking mode but
+ * they doesn't clear it, this method is usable as follows.
+ *
+ * END { STDOUT.nonblock = false }
+ * STDOUT.write_nonblock("foo")
+ *
+ * Since the flag is shared across processes and
+ * many non-Ruby commands doesn't expect standard I/O with non-blocking mode,
+ * it would be safe to clear the flag before Ruby program exits.
+ *
+ * For example following Ruby program leaves STDIN/STDOUT/STDER non-blocking mode.
+ * (STDIN, STDOUT and STDERR are connected to a terminal.
+ * So making one of them nonblocking-mode effects other two.)
+ * Thus cat command try to read from standard input and
+ * it causes "Resource temporarily unavailable" error (EAGAIN).
+ *
+ * % ruby -e '
+ * STDOUT.write_nonblock("foo\n")'; cat
+ * foo
+ * cat: -: Resource temporarily unavailable
+ *
+ * Clearing the flag makes the behavior of cat command normal.
+ * (cat command waits input from standard input.)
+ *
+ * % ruby -rio/nonblock -e '
+ * END { STDOUT.nonblock = false }
+ * STDOUT.write_nonblock("foo")
+ * '; cat
+ * foo
+ *
*/
static VALUE
rb_io_nonblock_set(VALUE io, VALUE nb)
@@ -83,7 +129,7 @@ rb_io_nonblock_set(VALUE io, VALUE nb)
if (RTEST(nb))
rb_io_set_nonblock(fptr);
else
- io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
+ io_nonblock_set(fptr->fd, get_fcntl_flags(fptr->fd), RTEST(nb));
return io;
}
@@ -91,15 +137,14 @@ static VALUE
io_nonblock_restore(VALUE arg)
{
int *restore = (int *)arg;
- if (fcntl(restore[0], F_SETFL, restore[1]) == -1)
- rb_sys_fail(0);
+ set_fcntl_flags(restore[0], restore[1]);
return Qnil;
}
/*
* call-seq:
- * io.nonblock {|io| } -> io
- * io.nonblock(boolean) {|io| } -> io
+ * io.nonblock {|io| } -> object
+ * io.nonblock(boolean) {|io| } -> object
*
* Yields +self+ in non-blocking mode.
*
@@ -119,7 +164,7 @@ rb_io_nonblock_block(int argc, VALUE *argv, VALUE io)
rb_scan_args(argc, argv, "01", &v);
nb = RTEST(v);
}
- f = io_nonblock_mode(fptr->fd);
+ f = get_fcntl_flags(fptr->fd);
restore[0] = fptr->fd;
restore[1] = f;
if (!io_nonblock_set(fptr->fd, f, nb))
diff --git a/ext/io/wait/depend b/ext/io/wait/depend
index f3c9b76c19..51e1af8280 100644
--- a/ext/io/wait/depend
+++ b/ext/io/wait/depend
@@ -1,7 +1,22 @@
# AUTOGENERATED DEPENDENCIES START
+# wait.o: $(hdrdir)/ruby/assert.h # not in 2.6
wait.o: $(RUBY_EXTCONF_H)
wait.o: $(arch_hdrdir)/ruby/config.h
wait.o: $(hdrdir)/ruby.h
+wait.o: $(hdrdir)/ruby/assert.h
+wait.o: $(hdrdir)/ruby/backward.h
+wait.o: $(hdrdir)/ruby/backward/2/assume.h
+wait.o: $(hdrdir)/ruby/backward/2/attributes.h
+wait.o: $(hdrdir)/ruby/backward/2/bool.h
+wait.o: $(hdrdir)/ruby/backward/2/inttypes.h
+wait.o: $(hdrdir)/ruby/backward/2/limits.h
+wait.o: $(hdrdir)/ruby/backward/2/long_long.h
+wait.o: $(hdrdir)/ruby/backward/2/stdalign.h
+wait.o: $(hdrdir)/ruby/backward/2/stdarg.h
+wait.o: $(hdrdir)/ruby/defines.h
+wait.o: $(hdrdir)/ruby/encoding.h
+wait.o: $(hdrdir)/ruby/intern.h
+wait.o: $(hdrdir)/ruby/internal/abi.h
wait.o: $(hdrdir)/ruby/internal/anyargs.h
wait.o: $(hdrdir)/ruby/internal/arithmetic.h
wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +86,15 @@ wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
wait.o: $(hdrdir)/ruby/internal/ctype.h
wait.o: $(hdrdir)/ruby/internal/dllexport.h
wait.o: $(hdrdir)/ruby/internal/dosish.h
+wait.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+wait.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+wait.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+wait.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+wait.o: $(hdrdir)/ruby/internal/encoding/re.h
+wait.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/encoding/string.h
+wait.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+wait.o: $(hdrdir)/ruby/internal/encoding/transcode.h
wait.o: $(hdrdir)/ruby/internal/error.h
wait.o: $(hdrdir)/ruby/internal/eval.h
wait.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +165,6 @@ 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
wait.o: $(hdrdir)/ruby/io.h
wait.o: $(hdrdir)/ruby/missing.h
wait.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index b5d36c3fe3..c6230b7783 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -1,19 +1,24 @@
# frozen_string_literal: false
require 'mkmf'
-target = "io/wait"
-unless macro_defined?("DOSISH", "#include <ruby.h>")
- have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
- fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
- have_macro("FIONREAD", [h, ioctl_h].compact)
- end
- if fionread
- $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
- create_makefile(target)
- end
+if RUBY_VERSION < "2.6"
+ File.write("Makefile", dummy_makefile($srcdir).join(""))
else
- if have_func("rb_w32_ioctlsocket", "ruby.h")
- have_func("rb_w32_is_socket", "ruby.h")
- create_makefile(target)
+ target = "io/wait"
+ have_func("rb_io_wait", "ruby/io.h")
+ unless macro_defined?("DOSISH", "#include <ruby.h>")
+ have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
+ fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
+ have_macro("FIONREAD", [h, ioctl_h].compact)
+ end
+ if fionread
+ $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
+ create_makefile(target)
+ end
+ else
+ if have_func("rb_w32_ioctlsocket", "ruby.h")
+ have_func("rb_w32_is_socket", "ruby.h")
+ create_makefile(target)
+ end
end
end
diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec
index 103b75e4ac..ebc1f6f5c7 100644
--- a/ext/io/wait/io-wait.gemspec
+++ b/ext/io/wait/io-wait.gemspec
@@ -1,27 +1,38 @@
-_VERSION = "0.1.1"
+_VERSION = "0.3.0"
Gem::Specification.new do |spec|
spec.name = "io-wait"
spec.version = _VERSION
- spec.authors = ["Nobu Nakada"]
- spec.email = ["nobu@ruby-lang.org"]
+ spec.authors = ["Nobu Nakada", "Charles Oliver Nutter"]
+ spec.email = ["nobu@ruby-lang.org", "headius@headius.com"]
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)})
+ File.identical?(f, __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features|rakelib)/|\.(?:git|travis|circleci)|appveyor|Rakefile)})
end
end
- spec.extensions = %w[ext/io/wait/extconf.rb]
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
+
+ jruby = true if Gem::Platform.new('java') =~ spec.platform or RUBY_ENGINE == 'jruby'
+ spec.files.delete_if do |f|
+ f.end_with?(".java") or
+ f.start_with?("ext/") && (jruby ^ f.start_with?("ext/java/"))
+ end
+ if jruby
+ spec.platform = 'java'
+ spec.files << "lib/io/wait.jar"
+ spec.require_paths += ["ext/java/lib"]
+ else
+ spec.extensions = %w[ext/io/wait/extconf.rb]
+ end
end
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 512e4f6a80..d74afb580b 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -40,23 +40,52 @@
#define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
#endif
+#ifndef HAVE_RB_IO_WAIT
+static struct timeval *
+get_timeout(int argc, VALUE *argv, struct timeval *timerec)
+{
+ VALUE timeout = Qnil;
+ rb_check_arity(argc, 0, 1);
+ if (!argc || NIL_P(timeout = argv[0])) {
+ return NULL;
+ }
+ else {
+ *timerec = rb_time_interval(timeout);
+ return timerec;
+ }
+}
+
+static int
+wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
+{
+ int i = rb_wait_for_single_fd(fptr->fd, events, tv);
+ if (i < 0)
+ rb_sys_fail(0);
+ rb_io_check_closed(fptr);
+ return (i & events);
+}
+#endif
+
/*
* call-seq:
* io.nread -> int
*
* Returns number of bytes that can be read without blocking.
* Returns zero if no information available.
+ *
+ * You must require 'io/wait' to use this method.
*/
static VALUE
io_nread(VALUE io)
{
- rb_io_t *fptr = NULL;
+ rb_io_t *fptr;
+ int len;
ioctl_arg n;
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
- int len = rb_io_read_pending(fptr);
+ 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);
@@ -64,99 +93,151 @@ io_nread(VALUE io)
return INT2FIX(0);
}
+#ifdef HAVE_RB_IO_WAIT
static VALUE
-io_wait_event(VALUE io, int event, VALUE timeout)
+io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
{
VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
if (!RB_TEST(result)) {
- return Qnil;
+ return Qnil;
}
int mask = RB_NUM2INT(result);
if (mask & event) {
- return io;
+ if (return_io)
+ return io;
+ else
+ return result;
}
else {
- return Qfalse;
+ return Qfalse;
}
}
+#endif
/*
* call-seq:
- * io.ready? -> true or false
+ * io.ready? -> truthy or falsy
*
- * Returns +true+ if input available without blocking, or +false+.
+ * Returns a truthy value if input available without blocking, or a
+ * falsy value.
+ *
+ * You must require 'io/wait' to use this method.
*/
static VALUE
io_ready_p(VALUE io)
{
rb_io_t *fptr;
+#ifndef HAVE_RB_IO_WAIT
+ struct timeval tv = {0, 0};
+#endif
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
- return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0));
+#ifndef HAVE_RB_IO_WAIT
+ return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;
+#else
+ return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);
+#endif
}
+/* Ruby 3.2+ can define these methods. This macro indicates that case. */
+#ifndef RUBY_IO_WAIT_METHODS
+
/*
* call-seq:
- * io.wait_readable -> true or false
- * io.wait_readable(timeout) -> true or false
+ * io.wait_readable -> truthy or falsy
+ * io.wait_readable(timeout) -> truthy or falsy
+ *
+ * Waits until IO is readable and returns a truthy value, or a falsy
+ * value when times out. Returns a truthy value immediately when
+ * buffered data is available.
*
- * Waits until IO is readable and returns +true+, or
- * +false+ when times out.
- * Returns +true+ immediately when buffered data is available.
+ * You must require 'io/wait' to use this method.
*/
static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr = NULL;
+ rb_io_t *fptr;
+#ifndef HAVE_RB_IO_WAIT
+ struct timeval timerec;
+ struct timeval *tv;
+#endif
- RB_IO_POINTER(io, fptr);
+ GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
+#ifndef HAVE_RB_IO_WAIT
+ tv = get_timeout(argc, argv, &timerec);
+#endif
if (rb_io_read_pending(fptr)) return Qtrue;
+#ifndef HAVE_RB_IO_WAIT
+ if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
+ return io;
+ }
+ return Qnil;
+#else
rb_check_arity(argc, 0, 1);
VALUE timeout = (argc == 1 ? argv[0] : Qnil);
- return io_wait_event(io, RUBY_IO_READABLE, timeout);
+ return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
+#endif
}
/*
* call-seq:
- * io.wait_writable -> true or false
- * io.wait_writable(timeout) -> true or false
+ * io.wait_writable -> truthy or falsy
+ * io.wait_writable(timeout) -> truthy or falsy
*
- * Waits until IO is writable and returns +true+ or
- * +false+ when times out.
+ * Waits until IO is writable and returns a truthy value or a falsy
+ * value when times out.
+ *
+ * You must require 'io/wait' to use this method.
*/
static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr = NULL;
+ rb_io_t *fptr;
+#ifndef HAVE_RB_IO_WAIT
+ struct timeval timerec;
+ struct timeval *tv;
+#endif
- RB_IO_POINTER(io, fptr);
+ GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
+#ifndef HAVE_RB_IO_WAIT
+ tv = get_timeout(argc, argv, &timerec);
+ if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
+ return io;
+ }
+ return Qnil;
+#else
rb_check_arity(argc, 0, 1);
VALUE timeout = (argc == 1 ? argv[0] : Qnil);
- return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
+ return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
+#endif
}
+#ifdef HAVE_RB_IO_WAIT
/*
* call-seq:
- * io.wait_priority -> true or false
- * io.wait_priority(timeout) -> true or false
+ * io.wait_priority -> truthy or falsy
+ * io.wait_priority(timeout) -> truthy or falsy
+ *
+ * Waits until IO is priority and returns a truthy value or a falsy
+ * value when times out. Priority data is sent and received using
+ * the Socket::MSG_OOB flag and is typically limited to streams.
*
- * Waits until IO is priority and returns +true+ or
- * +false+ when times out.
+ * You must require 'io/wait' to use this method.
*/
static VALUE
io_wait_priority(int argc, VALUE *argv, VALUE io)
@@ -171,101 +252,158 @@ io_wait_priority(int argc, VALUE *argv, VALUE io)
rb_check_arity(argc, 0, 1);
VALUE timeout = argc == 1 ? argv[0] : Qnil;
- return io_wait_event(io, RUBY_IO_PRIORITY, timeout);
+ return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
}
+#endif
static int
wait_mode_sym(VALUE mode)
{
if (mode == ID2SYM(rb_intern("r"))) {
- return RB_WAITFD_IN;
+ return RB_WAITFD_IN;
}
if (mode == ID2SYM(rb_intern("read"))) {
- return RB_WAITFD_IN;
+ return RB_WAITFD_IN;
}
if (mode == ID2SYM(rb_intern("readable"))) {
- return RB_WAITFD_IN;
+ return RB_WAITFD_IN;
}
if (mode == ID2SYM(rb_intern("w"))) {
- return RB_WAITFD_OUT;
+ return RB_WAITFD_OUT;
}
if (mode == ID2SYM(rb_intern("write"))) {
- return RB_WAITFD_OUT;
+ return RB_WAITFD_OUT;
}
if (mode == ID2SYM(rb_intern("writable"))) {
- return RB_WAITFD_OUT;
+ return RB_WAITFD_OUT;
}
if (mode == ID2SYM(rb_intern("rw"))) {
- return RB_WAITFD_IN|RB_WAITFD_OUT;
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
}
if (mode == ID2SYM(rb_intern("read_write"))) {
- return RB_WAITFD_IN|RB_WAITFD_OUT;
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
}
if (mode == ID2SYM(rb_intern("readable_writable"))) {
- return RB_WAITFD_IN|RB_WAITFD_OUT;
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
}
rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
return 0;
}
+#ifdef HAVE_RB_IO_WAIT
+static inline rb_io_event_t
+io_event_from_value(VALUE value)
+{
+ int events = RB_NUM2INT(value);
+
+ if (events <= 0) rb_raise(rb_eArgError, "Events must be positive integer!");
+
+ return events;
+}
+#endif
+
/*
* call-seq:
- * io.wait(events, timeout) -> event mask or false.
- * io.wait(timeout = nil, mode = :read) -> event mask or false.
+ * io.wait(events, timeout) -> event mask, false or nil
+ * io.wait(timeout = nil, mode = :read) -> self, true, or false
*
* Waits until the IO becomes ready for the specified events and returns the
- * subset of events that become ready, or +false+ when times out.
+ * subset of events that become ready, or a falsy value when times out.
*
* The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
* +IO::PRIORITY+.
*
- * Returns +true+ immediately when buffered data is available.
+ * Returns a truthy value immediately when buffered data is available.
*
* Optional parameter +mode+ is one of +:read+, +:write+, or
* +:read_write+.
+ *
+ * You must require 'io/wait' to use this method.
*/
static VALUE
io_wait(int argc, VALUE *argv, VALUE io)
{
+#ifndef HAVE_RB_IO_WAIT
+ rb_io_t *fptr;
+ struct timeval timerec;
+ struct timeval *tv = NULL;
+ int event = 0;
+ int i;
+
+ GetOpenFile(io, fptr);
+ for (i = 0; i < argc; ++i) {
+ if (SYMBOL_P(argv[i])) {
+ event |= wait_mode_sym(argv[i]);
+ }
+ else {
+ *(tv = &timerec) = rb_time_interval(argv[i]);
+ }
+ }
+ /* rb_time_interval() and might_mode() might convert the argument */
+ rb_io_check_closed(fptr);
+ if (!event) event = RB_WAITFD_IN;
+ if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
+ return Qtrue;
+ if (wait_for_single_fd(fptr, event, tv))
+ return io;
+ return Qnil;
+#else
VALUE timeout = Qundef;
rb_io_event_t events = 0;
+ int i, return_io = 0;
+ /* The documented signature for this method is actually incorrect.
+ * A single timeout is allowed in any position, and multiple symbols can be given.
+ * Whether this is intentional or not, I don't know, and as such I consider this to
+ * be a legacy/slow path. */
if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
- for (int i = 0; i < argc; i += 1) {
- if (RB_SYMBOL_P(argv[i])) {
- events |= wait_mode_sym(argv[i]);
- }
- else if (timeout == Qundef) {
- rb_time_interval(timeout = argv[i]);
- }
- else {
- rb_raise(rb_eArgError, "timeout given more than once");
- }
- }
- if (timeout == Qundef) timeout = Qnil;
+ /* We'd prefer to return the actual mask, but this form would return the io itself: */
+ return_io = 1;
+
+ /* Slow/messy path: */
+ for (i = 0; i < argc; i += 1) {
+ if (RB_SYMBOL_P(argv[i])) {
+ events |= wait_mode_sym(argv[i]);
+ }
+ else if (timeout == Qundef) {
+ rb_time_interval(timeout = argv[i]);
+ }
+ else {
+ rb_raise(rb_eArgError, "timeout given more than once");
+ }
+ }
+
+ if (timeout == Qundef) timeout = Qnil;
+
+ if (events == 0) {
+ events = RUBY_IO_READABLE;
+ }
}
- else /* argc == 2 */ {
- events = RB_NUM2UINT(argv[0]);
- timeout = argv[1];
- }
-
- if (events == 0) {
- events = RUBY_IO_READABLE;
+ else /* argc == 2 and neither are symbols */ {
+ /* This is the fast path: */
+ events = io_event_from_value(argv[0]);
+ timeout = argv[1];
}
if (events & RUBY_IO_READABLE) {
- rb_io_t *fptr = NULL;
- RB_IO_POINTER(io, fptr);
-
- if (rb_io_read_pending(fptr)) {
- return Qtrue;
- }
+ rb_io_t *fptr = NULL;
+ RB_IO_POINTER(io, fptr);
+
+ if (rb_io_read_pending(fptr)) {
+ /* This was the original behaviour: */
+ if (return_io) return Qtrue;
+ /* New behaviour always returns an event mask: */
+ else return RB_INT2NUM(RUBY_IO_READABLE);
+ }
}
- return io_wait_event(io, events, timeout);
+ return io_wait_event(io, events, timeout, return_io);
+#endif
}
+#endif /* RUBY_IO_WAIT_METHODS */
+
/*
* IO wait methods
*/
@@ -280,9 +418,13 @@ Init_wait(void)
rb_define_method(rb_cIO, "nread", io_nread, 0);
rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
+#ifndef RUBY_IO_WAIT_METHODS
rb_define_method(rb_cIO, "wait", io_wait, -1);
rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
+#ifdef HAVE_RB_IO_WAIT
rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
+#endif
+#endif
}
diff --git a/ext/json/VERSION b/ext/json/VERSION
index 73462a5a13..ec1cf33c3f 100644
--- a/ext/json/VERSION
+++ b/ext/json/VERSION
@@ -1 +1 @@
-2.5.1
+2.6.3
diff --git a/ext/json/generator/depend b/ext/json/generator/depend
index 6787d492ca..28ef06b36d 100644
--- a/ext/json/generator/depend
+++ b/ext/json/generator/depend
@@ -5,6 +5,20 @@ 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/assert.h
+generator.o: $(hdrdir)/ruby/backward.h
+generator.o: $(hdrdir)/ruby/backward/2/assume.h
+generator.o: $(hdrdir)/ruby/backward/2/attributes.h
+generator.o: $(hdrdir)/ruby/backward/2/bool.h
+generator.o: $(hdrdir)/ruby/backward/2/inttypes.h
+generator.o: $(hdrdir)/ruby/backward/2/limits.h
+generator.o: $(hdrdir)/ruby/backward/2/long_long.h
+generator.o: $(hdrdir)/ruby/backward/2/stdalign.h
+generator.o: $(hdrdir)/ruby/backward/2/stdarg.h
+generator.o: $(hdrdir)/ruby/defines.h
+generator.o: $(hdrdir)/ruby/encoding.h
+generator.o: $(hdrdir)/ruby/intern.h
+generator.o: $(hdrdir)/ruby/internal/abi.h
generator.o: $(hdrdir)/ruby/internal/anyargs.h
generator.o: $(hdrdir)/ruby/internal/arithmetic.h
generator.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -75,6 +89,15 @@ generator.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
generator.o: $(hdrdir)/ruby/internal/ctype.h
generator.o: $(hdrdir)/ruby/internal/dllexport.h
generator.o: $(hdrdir)/ruby/internal/dosish.h
+generator.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+generator.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+generator.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+generator.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+generator.o: $(hdrdir)/ruby/internal/encoding/re.h
+generator.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+generator.o: $(hdrdir)/ruby/internal/encoding/string.h
+generator.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+generator.o: $(hdrdir)/ruby/internal/encoding/transcode.h
generator.o: $(hdrdir)/ruby/internal/error.h
generator.o: $(hdrdir)/ruby/internal/eval.h
generator.o: $(hdrdir)/ruby/internal/event.h
@@ -145,20 +168,6 @@ 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
generator.o: $(hdrdir)/ruby/missing.h
generator.o: $(hdrdir)/ruby/onigmo.h
generator.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index e3a83472e1..98d0ea46c3 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -997,10 +997,10 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
if (!allow_nan) {
if (isinf(value)) {
fbuffer_free(buffer);
- rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
} else if (isnan(value)) {
fbuffer_free(buffer);
- rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
}
}
fbuffer_append_str(buffer, tmp);
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 7a72272bd0..3d4326d836 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.5.1'
+ VERSION = '2.6.3'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/ext/json/parser/depend b/ext/json/parser/depend
index 3675d05875..a8e066ce15 100644
--- a/ext/json/parser/depend
+++ b/ext/json/parser/depend
@@ -5,6 +5,20 @@ 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/assert.h
+parser.o: $(hdrdir)/ruby/backward.h
+parser.o: $(hdrdir)/ruby/backward/2/assume.h
+parser.o: $(hdrdir)/ruby/backward/2/attributes.h
+parser.o: $(hdrdir)/ruby/backward/2/bool.h
+parser.o: $(hdrdir)/ruby/backward/2/inttypes.h
+parser.o: $(hdrdir)/ruby/backward/2/limits.h
+parser.o: $(hdrdir)/ruby/backward/2/long_long.h
+parser.o: $(hdrdir)/ruby/backward/2/stdalign.h
+parser.o: $(hdrdir)/ruby/backward/2/stdarg.h
+parser.o: $(hdrdir)/ruby/defines.h
+parser.o: $(hdrdir)/ruby/encoding.h
+parser.o: $(hdrdir)/ruby/intern.h
+parser.o: $(hdrdir)/ruby/internal/abi.h
parser.o: $(hdrdir)/ruby/internal/anyargs.h
parser.o: $(hdrdir)/ruby/internal/arithmetic.h
parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -74,6 +88,15 @@ parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
parser.o: $(hdrdir)/ruby/internal/ctype.h
parser.o: $(hdrdir)/ruby/internal/dllexport.h
parser.o: $(hdrdir)/ruby/internal/dosish.h
+parser.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+parser.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+parser.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+parser.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+parser.o: $(hdrdir)/ruby/internal/encoding/re.h
+parser.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+parser.o: $(hdrdir)/ruby/internal/encoding/string.h
+parser.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+parser.o: $(hdrdir)/ruby/internal/encoding/transcode.h
parser.o: $(hdrdir)/ruby/internal/error.h
parser.o: $(hdrdir)/ruby/internal/eval.h
parser.o: $(hdrdir)/ruby/internal/event.h
@@ -144,20 +167,6 @@ 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
parser.o: $(hdrdir)/ruby/missing.h
parser.o: $(hdrdir)/ruby/onigmo.h
parser.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb
index feb586e1b4..4723a02aee 100644
--- a/ext/json/parser/extconf.rb
+++ b/ext/json/parser/extconf.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: false
require 'mkmf'
-have_func("rb_enc_raise", "ruby.h")
-have_func("rb_enc_interned_str", "ruby.h")
+have_func("rb_enc_raise", "ruby/encoding.h")
+have_func("rb_enc_interned_str", "ruby/encoding.h")
# checking if String#-@ (str_uminus) dedupes... '
begin
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index b1dc8810c3..9bd7f1971e 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -948,7 +948,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
{p = p - 1; } {p+= 1; cs = 29; goto _out;}
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
}
}
np = JSON_parse_float(json, p, pe, result);
@@ -990,7 +990,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8);
}
}
@@ -1002,7 +1002,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
if (json->allow_nan) {
*result = CNaN;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
}
}
@@ -2348,7 +2348,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
if(cs >= JSON_array_first_final) {
return p + 1;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
return NULL;
}
}
@@ -2363,9 +2363,17 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
char buf[4];
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
+# else
bufferStart = buffer = ALLOC_N(char, bufferSize);
+# endif
} else {
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
+# else
bufferStart = buffer = ALLOCA_N(char, bufferSize);
+# endif
}
while (pe < stringEnd) {
@@ -2405,7 +2413,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
}
rb_enc_raise(
EXC_ENCODING eParserError,
- "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
+ "incomplete unicode character escape sequence at '%s'", p
);
} else {
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
@@ -2418,7 +2426,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
}
rb_enc_raise(
EXC_ENCODING eParserError,
- "%u: incomplete surrogate pair at '%s'", __LINE__, p
+ "incomplete surrogate pair at '%s'", p
);
}
if (pe[0] == '\\' && pe[1] == 'u') {
@@ -2950,6 +2958,7 @@ static const char MAYBE_UNUSED(_JSON_nfa_pop_trans)[] = {
*
* Parses the current JSON text _source_ and returns the complete data
* structure as a result.
+* It raises JSON::ParseError if fail to parse.
*/
static VALUE cParser_parse(VALUE self)
{
@@ -3216,7 +3225,7 @@ static VALUE cParser_parse(VALUE self)
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
return Qnil;
}
}
diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl
index f7be1a5acc..2dbdc7ef24 100644
--- a/ext/json/parser/parser.rl
+++ b/ext/json/parser/parser.rl
@@ -222,14 +222,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) {
*result = CNaN;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
}
}
action parse_infinity {
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8);
}
}
action parse_string {
@@ -245,7 +245,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
fexec p + 10;
fhold; fbreak;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
}
}
np = JSON_parse_float(json, fpc, pe, result);
@@ -447,7 +447,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
if(cs >= JSON_array_first_final) {
return p + 1;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
return NULL;
}
}
@@ -462,9 +462,17 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
char buf[4];
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
+# else
bufferStart = buffer = ALLOC_N(char, bufferSize);
+# endif
} else {
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
+# else
bufferStart = buffer = ALLOCA_N(char, bufferSize);
+# endif
}
while (pe < stringEnd) {
@@ -504,7 +512,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
}
rb_enc_raise(
EXC_ENCODING eParserError,
- "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
+ "incomplete unicode character escape sequence at '%s'", p
);
} else {
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
@@ -517,7 +525,7 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
}
rb_enc_raise(
EXC_ENCODING eParserError,
- "%u: incomplete surrogate pair at '%s'", __LINE__, p
+ "incomplete surrogate pair at '%s'", p
);
}
if (pe[0] == '\\' && pe[1] == 'u') {
@@ -839,6 +847,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
*
* Parses the current JSON text _source_ and returns the complete data
* structure as a result.
+ * It raises JSON::ParseError if fail to parse.
*/
static VALUE cParser_parse(VALUE self)
{
@@ -855,7 +864,7 @@ static VALUE cParser_parse(VALUE self)
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
return Qnil;
}
}
diff --git a/ext/monitor/depend b/ext/monitor/depend
index 2e3ba40928..3030da71d0 100644
--- a/ext/monitor/depend
+++ b/ext/monitor/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
monitor.o: $(RUBY_EXTCONF_H)
monitor.o: $(arch_hdrdir)/ruby/config.h
+monitor.o: $(hdrdir)/ruby/assert.h
+monitor.o: $(hdrdir)/ruby/backward.h
+monitor.o: $(hdrdir)/ruby/backward/2/assume.h
+monitor.o: $(hdrdir)/ruby/backward/2/attributes.h
+monitor.o: $(hdrdir)/ruby/backward/2/bool.h
+monitor.o: $(hdrdir)/ruby/backward/2/inttypes.h
+monitor.o: $(hdrdir)/ruby/backward/2/limits.h
+monitor.o: $(hdrdir)/ruby/backward/2/long_long.h
+monitor.o: $(hdrdir)/ruby/backward/2/stdalign.h
+monitor.o: $(hdrdir)/ruby/backward/2/stdarg.h
+monitor.o: $(hdrdir)/ruby/defines.h
+monitor.o: $(hdrdir)/ruby/intern.h
+monitor.o: $(hdrdir)/ruby/internal/abi.h
monitor.o: $(hdrdir)/ruby/internal/anyargs.h
monitor.o: $(hdrdir)/ruby/internal/arithmetic.h
monitor.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
monitor.o: $(hdrdir)/ruby/ruby.h
monitor.o: $(hdrdir)/ruby/st.h
diff --git a/ext/nkf/depend b/ext/nkf/depend
index f92102fff2..9e2f468ba1 100644
--- a/ext/nkf/depend
+++ b/ext/nkf/depend
@@ -5,6 +5,20 @@ nkf.o: nkf.c
# AUTOGENERATED DEPENDENCIES START
nkf.o: $(RUBY_EXTCONF_H)
nkf.o: $(arch_hdrdir)/ruby/config.h
+nkf.o: $(hdrdir)/ruby/assert.h
+nkf.o: $(hdrdir)/ruby/backward.h
+nkf.o: $(hdrdir)/ruby/backward/2/assume.h
+nkf.o: $(hdrdir)/ruby/backward/2/attributes.h
+nkf.o: $(hdrdir)/ruby/backward/2/bool.h
+nkf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nkf.o: $(hdrdir)/ruby/backward/2/limits.h
+nkf.o: $(hdrdir)/ruby/backward/2/long_long.h
+nkf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nkf.o: $(hdrdir)/ruby/backward/2/stdarg.h
+nkf.o: $(hdrdir)/ruby/defines.h
+nkf.o: $(hdrdir)/ruby/encoding.h
+nkf.o: $(hdrdir)/ruby/intern.h
+nkf.o: $(hdrdir)/ruby/internal/abi.h
nkf.o: $(hdrdir)/ruby/internal/anyargs.h
nkf.o: $(hdrdir)/ruby/internal/arithmetic.h
nkf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -74,6 +88,15 @@ nkf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
nkf.o: $(hdrdir)/ruby/internal/ctype.h
nkf.o: $(hdrdir)/ruby/internal/dllexport.h
nkf.o: $(hdrdir)/ruby/internal/dosish.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/re.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/string.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+nkf.o: $(hdrdir)/ruby/internal/encoding/transcode.h
nkf.o: $(hdrdir)/ruby/internal/error.h
nkf.o: $(hdrdir)/ruby/internal/eval.h
nkf.o: $(hdrdir)/ruby/internal/event.h
@@ -144,20 +167,6 @@ 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
nkf.o: $(hdrdir)/ruby/missing.h
nkf.o: $(hdrdir)/ruby/onigmo.h
nkf.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
index 08b372ffab..6888a43918 100644
--- a/ext/nkf/nkf-utf8/nkf.c
+++ b/ext/nkf/nkf-utf8/nkf.c
@@ -144,7 +144,7 @@ static void w_oconv(nkf_char c2, nkf_char c1);
static void w_oconv16(nkf_char c2, nkf_char c1);
static void w_oconv32(nkf_char c2, nkf_char c1);
-typedef struct {
+typedef const struct {
const char *name;
nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0);
void (*oconv)(nkf_char c2, nkf_char c1);
@@ -158,10 +158,10 @@ nkf_native_encoding NkfEncodingUTF_8 = { "UTF-8", w_iconv, w_oconv };
nkf_native_encoding NkfEncodingUTF_16 = { "UTF-16", w_iconv16, w_oconv16 };
nkf_native_encoding NkfEncodingUTF_32 = { "UTF-32", w_iconv32, w_oconv32 };
-typedef struct {
- const int id;
+typedef const struct {
+ int id;
const char *name;
- const nkf_native_encoding *base_encoding;
+ nkf_native_encoding *base_encoding;
} nkf_encoding;
nkf_encoding nkf_encoding_table[] = {
@@ -204,9 +204,9 @@ nkf_encoding nkf_encoding_table[] = {
{-1, NULL, NULL}
};
-struct {
+static const struct {
const char *name;
- const int id;
+ int id;
} encoding_name_to_id_table[] = {
{"US-ASCII", ASCII},
{"ASCII", ASCII},
@@ -4286,7 +4286,7 @@ static const unsigned char *mime_pattern[] = {
/* $B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u(B */
-nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
+static nkf_char (*const mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
e_iconv, s_iconv, 0, 0, 0, 0, 0,
#if defined(UTF8_INPUT_ENABLE)
w_iconv, w_iconv,
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
index 76f7648d1b..c6ddee1976 100644
--- a/ext/nkf/nkf.c
+++ b/ext/nkf/nkf.c
@@ -65,11 +65,11 @@ rb_encoding* rb_nkf_enc_get(const char *name)
{
int idx = rb_enc_find_index(name);
if (idx < 0) {
- nkf_encoding *nkf_enc = nkf_enc_find(name);
- idx = rb_enc_find_index(nkf_enc_name(nkf_enc_to_base_encoding(nkf_enc)));
- if (idx < 0) {
- idx = rb_define_dummy_encoding(name);
- }
+ nkf_encoding *nkf_enc = nkf_enc_find(name);
+ idx = rb_enc_find_index(nkf_enc_name(nkf_enc_to_base_encoding(nkf_enc)));
+ if (idx < 0) {
+ idx = rb_define_dummy_encoding(name);
+ }
}
return rb_enc_from_index(idx);
}
@@ -83,40 +83,40 @@ int nkf_split_options(const char *arg)
int is_single_quoted = FALSE;
int is_double_quoted = FALSE;
for(i = 0; arg[i]; i++){
- if(j == 255){
- return -1;
- }else if(is_single_quoted){
- if(arg[i] == '\''){
- is_single_quoted = FALSE;
- }else{
- option[j++] = arg[i];
- }
- }else if(is_escaped){
- is_escaped = FALSE;
- option[j++] = arg[i];
- }else if(arg[i] == '\\'){
- is_escaped = TRUE;
- }else if(is_double_quoted){
- if(arg[i] == '"'){
- is_double_quoted = FALSE;
- }else{
- option[j++] = arg[i];
- }
- }else if(arg[i] == '\''){
- is_single_quoted = TRUE;
- }else if(arg[i] == '"'){
- is_double_quoted = TRUE;
- }else if(arg[i] == ' '){
- option[j] = '\0';
- options(option);
- j = 0;
- }else{
- option[j++] = arg[i];
- }
+ if(j == 255){
+ return -1;
+ }else if(is_single_quoted){
+ if(arg[i] == '\''){
+ is_single_quoted = FALSE;
+ }else{
+ option[j++] = arg[i];
+ }
+ }else if(is_escaped){
+ is_escaped = FALSE;
+ option[j++] = arg[i];
+ }else if(arg[i] == '\\'){
+ is_escaped = TRUE;
+ }else if(is_double_quoted){
+ if(arg[i] == '"'){
+ is_double_quoted = FALSE;
+ }else{
+ option[j++] = arg[i];
+ }
+ }else if(arg[i] == '\''){
+ is_single_quoted = TRUE;
+ }else if(arg[i] == '"'){
+ is_double_quoted = TRUE;
+ }else if(arg[i] == ' '){
+ option[j] = '\0';
+ options(option);
+ j = 0;
+ }else{
+ option[j++] = arg[i];
+ }
}
if(j){
- option[j] = '\0';
- options(option);
+ option[j] = '\0';
+ options(option);
}
return count;
}
@@ -170,9 +170,9 @@ rb_nkf_convert(VALUE obj, VALUE opt, VALUE src)
rb_str_set_len(tmp, output_ctr);
if (mimeout_f)
- rb_enc_associate(tmp, rb_usascii_encoding());
+ rb_enc_associate(tmp, rb_usascii_encoding());
else
- rb_enc_associate(tmp, rb_nkf_enc_get(nkf_enc_name(output_encoding)));
+ rb_enc_associate(tmp, rb_nkf_enc_get(nkf_enc_name(output_encoding)));
return tmp;
}
@@ -274,7 +274,7 @@ rb_nkf_guess(VALUE obj, VALUE src)
*
* {de/en}crypt ROT13/47
*
- * === -h[123] --hiragana --katakana --katakana-hiragana
+ * === \-h[123] --hiragana --katakana --katakana-hiragana
*
* [-h1 --hiragana] Katakana to Hiragana conversion.
*
@@ -299,7 +299,7 @@ rb_nkf_guess(VALUE obj, VALUE src)
*
* New line preserving line folding.
*
- * === -Z[0-3]
+ * === \-Z[0-3]
*
* Convert X0208 alphabet (Fullwidth Alphabets) to ASCII.
*
@@ -318,7 +318,7 @@ rb_nkf_guess(VALUE obj, VALUE src)
* With <b>-x</b>, try to preserve X0208 kana and do not convert X0201 kana to X0208.
* In JIS output, ESC-(-I is used. In EUC output, SSO is used.
*
- * === -B[0-2]
+ * === \-B[0-2]
*
* Assume broken JIS-Kanji input, which lost ESC.
* Useful when your site is using old B-News Nihongo patch.
@@ -336,7 +336,7 @@ rb_nkf_guess(VALUE obj, VALUE src)
*
* Delete \r in line feed, Add \r in line feed.
*
- * === -m[BQN0]
+ * === \-m[BQN0]
*
* MIME ISO-2022-JP/ISO8859-1 decode. (DEFAULT)
* To see ISO8859-1 (Latin-1) -l is necessary.
@@ -358,14 +358,14 @@ rb_nkf_guess(VALUE obj, VALUE src)
*
* [-MB] MIME encode Base64 stream.
*
- * [-MQ] Perfome quoted encoding.
+ * [-MQ] Perform quoted encoding.
*
* === -l
*
* Input and output code is ISO8859-1 (Latin-1) and ISO-2022-JP.
* <b>-s</b>, <b>-e</b> and <b>-x</b> are not compatible with this option.
*
- * === -L[uwm]
+ * === \-L[uwm]
*
* new line mode
* Without this option, nkf doesn't convert line breaks.
diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec
index 23f1dcdbaf..7f3bd4a4b1 100644
--- a/ext/nkf/nkf.gemspec
+++ b/ext/nkf/nkf.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "nkf"
- spec.version = "0.1.0"
+ spec.version = "0.1.2"
spec.authors = ["NARUSE Yui"]
spec.email = ["naruse@airemix.jp"]
diff --git a/ext/objspace/depend b/ext/objspace/depend
index 1465bf9292..52797664e0 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -1,23 +1,20 @@
# AUTOGENERATED DEPENDENCIES START
object_tracing.o: $(RUBY_EXTCONF_H)
object_tracing.o: $(arch_hdrdir)/ruby/config.h
-object_tracing.o: $(hdrdir)/ruby.h
object_tracing.o: $(hdrdir)/ruby/assert.h
object_tracing.o: $(hdrdir)/ruby/backward.h
object_tracing.o: $(hdrdir)/ruby/backward/2/assume.h
object_tracing.o: $(hdrdir)/ruby/backward/2/attributes.h
object_tracing.o: $(hdrdir)/ruby/backward/2/bool.h
-object_tracing.o: $(hdrdir)/ruby/backward/2/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/abi.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
@@ -161,13 +158,14 @@ object_tracing.o: $(hdrdir)/ruby/missing.h
object_tracing.o: $(hdrdir)/ruby/ruby.h
object_tracing.o: $(hdrdir)/ruby/st.h
object_tracing.o: $(hdrdir)/ruby/subst.h
+object_tracing.o: $(top_srcdir)/gc.h
object_tracing.o: $(top_srcdir)/internal.h
object_tracing.o: object_tracing.c
object_tracing.o: objspace.h
objspace.o: $(RUBY_EXTCONF_H)
objspace.o: $(arch_hdrdir)/ruby/config.h
-objspace.o: $(hdrdir)/ruby.h
objspace.o: $(hdrdir)/ruby/assert.h
+objspace.o: $(hdrdir)/ruby/atomic.h
objspace.o: $(hdrdir)/ruby/backward.h
objspace.o: $(hdrdir)/ruby/backward/2/assume.h
objspace.o: $(hdrdir)/ruby/backward/2/attributes.h
@@ -176,13 +174,12 @@ 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/abi.h
objspace.o: $(hdrdir)/ruby/internal/anyargs.h
objspace.o: $(hdrdir)/ruby/internal/arithmetic.h
objspace.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -253,6 +250,15 @@ objspace.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
objspace.o: $(hdrdir)/ruby/internal/ctype.h
objspace.o: $(hdrdir)/ruby/internal/dllexport.h
objspace.o: $(hdrdir)/ruby/internal/dosish.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/re.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/string.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+objspace.o: $(hdrdir)/ruby/internal/encoding/transcode.h
objspace.o: $(hdrdir)/ruby/internal/error.h
objspace.o: $(hdrdir)/ruby/internal/eval.h
objspace.o: $(hdrdir)/ruby/internal/event.h
@@ -332,10 +338,16 @@ objspace.o: $(hdrdir)/ruby/regex.h
objspace.o: $(hdrdir)/ruby/ruby.h
objspace.o: $(hdrdir)/ruby/st.h
objspace.o: $(hdrdir)/ruby/subst.h
+objspace.o: $(hdrdir)/ruby/thread_native.h
+objspace.o: $(top_srcdir)/ccan/check_type/check_type.h
+objspace.o: $(top_srcdir)/ccan/container_of/container_of.h
+objspace.o: $(top_srcdir)/ccan/list/list.h
+objspace.o: $(top_srcdir)/ccan/str/str.h
objspace.o: $(top_srcdir)/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/basic_operators.h
objspace.o: $(top_srcdir)/internal/class.h
objspace.o: $(top_srcdir)/internal/compilers.h
objspace.o: $(top_srcdir)/internal/gc.h
@@ -344,14 +356,21 @@ 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/vm.h
objspace.o: $(top_srcdir)/internal/warnings.h
+objspace.o: $(top_srcdir)/method.h
objspace.o: $(top_srcdir)/node.h
+objspace.o: $(top_srcdir)/ruby_assert.h
+objspace.o: $(top_srcdir)/ruby_atomic.h
+objspace.o: $(top_srcdir)/shape.h
objspace.o: $(top_srcdir)/symbol.h
+objspace.o: $(top_srcdir)/thread_pthread.h
+objspace.o: $(top_srcdir)/vm_core.h
+objspace.o: $(top_srcdir)/vm_opts.h
objspace.o: objspace.c
objspace.o: {$(VPATH)}id.h
objspace_dump.o: $(RUBY_EXTCONF_H)
objspace_dump.o: $(arch_hdrdir)/ruby/config.h
-objspace_dump.o: $(hdrdir)/ruby.h
objspace_dump.o: $(hdrdir)/ruby/assert.h
objspace_dump.o: $(hdrdir)/ruby/atomic.h
objspace_dump.o: $(hdrdir)/ruby/backward.h
@@ -362,14 +381,13 @@ 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/abi.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
@@ -439,6 +457,15 @@ objspace_dump.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
objspace_dump.o: $(hdrdir)/ruby/internal/ctype.h
objspace_dump.o: $(hdrdir)/ruby/internal/dllexport.h
objspace_dump.o: $(hdrdir)/ruby/internal/dosish.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/re.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/string.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+objspace_dump.o: $(hdrdir)/ruby/internal/encoding/transcode.h
objspace_dump.o: $(hdrdir)/ruby/internal/error.h
objspace_dump.o: $(hdrdir)/ruby/internal/eval.h
objspace_dump.o: $(hdrdir)/ruby/internal/event.h
@@ -522,9 +549,13 @@ 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)/constant.h
objspace_dump.o: $(top_srcdir)/gc.h
+objspace_dump.o: $(top_srcdir)/id_table.h
objspace_dump.o: $(top_srcdir)/internal.h
objspace_dump.o: $(top_srcdir)/internal/array.h
+objspace_dump.o: $(top_srcdir)/internal/basic_operators.h
+objspace_dump.o: $(top_srcdir)/internal/class.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
@@ -533,12 +564,15 @@ 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/variable.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
objspace_dump.o: $(top_srcdir)/ruby_atomic.h
+objspace_dump.o: $(top_srcdir)/shape.h
+objspace_dump.o: $(top_srcdir)/symbol.h
objspace_dump.o: $(top_srcdir)/thread_pthread.h
objspace_dump.o: $(top_srcdir)/vm_core.h
objspace_dump.o: $(top_srcdir)/vm_opts.h
diff --git a/ext/objspace/lib/objspace.rb b/ext/objspace/lib/objspace.rb
index 0298b0646c..6865fdda4c 100644
--- a/ext/objspace/lib/objspace.rb
+++ b/ext/objspace/lib/objspace.rb
@@ -6,14 +6,15 @@ module ObjectSpace
class << self
private :_dump
private :_dump_all
+ private :_dump_shapes
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
+ # 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.
#
@@ -42,38 +43,88 @@ module ObjectSpace
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..."
+ # 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.
+ #
+ # _full_ must be a boolean. If true all heap slots are dumped including the empty ones (T_NONE).
+ #
+ # _since_ must be a non-negative integer or +nil+.
#
- # Dump the contents of the ruby heap as JSON.
+ # 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.
#
- # _since_ must be a non-negative integer or +nil+.
+ # If _since_ is omitted or is +nil+, all objects are dumped.
#
- # 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.
+ # _shapes_ must be a boolean or a non-negative integer.
#
- # Objects that were allocated without object allocation tracing enabled
- # are ignored. See ::trace_object_allocations for more information and
- # examples.
+ # If _shapes_ is a positive integer, only shapes newer than the provided
+ # shape id are dumped. The current shape_id can be accessed using <tt>RubyVM.stat(:next_shape_id)</tt>.
#
- # If _since_ is omitted or is +nil+, all objects are dumped.
+ # If _shapes_ is +false+, no shapes are dumped.
+ #
+ # To only dump objects allocated past a certain point you can combine _since_ and _shapes_:
+ # ObjectSpace.trace_object_allocations
+ # GC.start
+ # gc_generation = GC.count
+ # shape_generation = RubyVM.stat(:next_shape_id)
+ # call_method_to_instrument
+ # ObjectSpace.dump_all(since: gc_generation, shapes: shape_generation)
+ #
+ # 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, shapes: true)
+ 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
+
+ shapes = 0 if shapes == true
+ ret = _dump_all(out, full, since, shapes)
+ return nil if output == :stdout
+ ret
+ end
+
+ # call-seq:
+ # ObjectSpace.dump_shapes([output: :file]) -> #<File:/tmp/rubyshapes20131125-88469-laoj3v.json>
+ # ObjectSpace.dump_shapes(output: :stdout) -> nil
+ # ObjectSpace.dump_shapes(output: :string) -> "{...}\n{...}\n..."
+ # ObjectSpace.dump_shapes(output: File.open('shapes.json','w')) -> #<File:shapes.json>
+ # ObjectSpace.dump_all(output: :string, since: 42) -> "{...}\n{...}\n..."
+ #
+ # Dump the contents of the ruby shape tree as JSON.
+ #
+ # If _shapes_ is a positive integer, only shapes newer than the provided
+ # shape id are dumped. The current shape_id can be accessed using <tt>RubyVM.stat(:next_shape_id)</tt>.
#
# 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)
+ def dump_shapes(output: :file, since: 0)
out = case output
when :file, nil
require 'tempfile'
- Tempfile.create(%w(rubyheap .json))
+ Tempfile.create(%w(rubyshapes .json))
when :stdout
STDOUT
when :string
@@ -84,7 +135,7 @@ module ObjectSpace
raise ArgumentError, "wrong output option: #{output.inspect}"
end
- ret = _dump_all(out, full, since)
+ ret = _dump_shapes(out, since)
return nil if output == :stdout
ret
end
diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c
index 4973a7535b..8c54d51eab 100644
--- a/ext/objspace/object_tracing.c
+++ b/ext/objspace/object_tracing.c
@@ -13,6 +13,7 @@
**********************************************************************/
+#include "gc.h"
#include "internal.h"
#include "ruby/debug.h"
#include "objspace.h"
@@ -31,24 +32,24 @@ static const char *
make_unique_str(st_table *tbl, const char *str, long len)
{
if (!str) {
- return NULL;
+ return NULL;
}
else {
- st_data_t n;
- char *result;
-
- if (st_lookup(tbl, (st_data_t)str, &n)) {
- st_insert(tbl, (st_data_t)str, n+1);
- st_get_key(tbl, (st_data_t)str, &n);
- result = (char *)n;
- }
- else {
- result = (char *)ruby_xmalloc(len+1);
- strncpy(result, str, len);
- result[len] = 0;
- st_add_direct(tbl, (st_data_t)result, 1);
- }
- return result;
+ st_data_t n;
+ char *result;
+
+ if (st_lookup(tbl, (st_data_t)str, &n)) {
+ st_insert(tbl, (st_data_t)str, n+1);
+ st_get_key(tbl, (st_data_t)str, &n);
+ result = (char *)n;
+ }
+ else {
+ result = (char *)ruby_xmalloc(len+1);
+ strncpy(result, str, len);
+ result[len] = 0;
+ st_add_direct(tbl, (st_data_t)result, 1);
+ }
+ return result;
}
}
@@ -56,17 +57,17 @@ static void
delete_unique_str(st_table *tbl, const char *str)
{
if (str) {
- st_data_t n;
-
- st_lookup(tbl, (st_data_t)str, &n);
- if (n == 1) {
- n = (st_data_t)str;
- st_delete(tbl, &n, 0);
- ruby_xfree((char *)n);
- }
- else {
- st_insert(tbl, (st_data_t)str, n-1);
- }
+ st_data_t n;
+
+ st_lookup(tbl, (st_data_t)str, &n);
+ if (n == 1) {
+ n = (st_data_t)str;
+ st_delete(tbl, &n, 0);
+ ruby_xfree((char *)n);
+ }
+ else {
+ st_insert(tbl, (st_data_t)str, n-1);
+ }
}
}
@@ -87,18 +88,18 @@ newobj_i(VALUE tpval, void *data)
st_data_t v;
if (st_lookup(arg->object_table, (st_data_t)obj, &v)) {
- info = (struct allocation_info *)v;
- if (arg->keep_remains) {
- if (info->living) {
- /* do nothing. there is possibility to keep living if FREEOBJ events while suppressing tracing */
- }
- }
- /* reuse info */
- delete_unique_str(arg->str_table, info->path);
- delete_unique_str(arg->str_table, info->class_path);
+ info = (struct allocation_info *)v;
+ if (arg->keep_remains) {
+ if (info->living) {
+ /* do nothing. there is possibility to keep living if FREEOBJ events while suppressing tracing */
+ }
+ }
+ /* reuse info */
+ delete_unique_str(arg->str_table, info->path);
+ delete_unique_str(arg->str_table, info->class_path);
}
else {
- info = (struct allocation_info *)ruby_xmalloc(sizeof(struct allocation_info));
+ info = (struct allocation_info *)ruby_xmalloc(sizeof(struct allocation_info));
}
info->living = 1;
info->flags = RBASIC(obj)->flags;
@@ -121,20 +122,26 @@ freeobj_i(VALUE tpval, void *data)
st_data_t v;
struct allocation_info *info;
+ /* Modifying the st table can cause allocations, which can trigger GC.
+ * Since freeobj_i is called during GC, it must not trigger another GC. */
+ VALUE gc_disabled = rb_gc_disable_no_rest();
+
if (arg->keep_remains) {
- if (st_lookup(arg->object_table, obj, &v)) {
- info = (struct allocation_info *)v;
- info->living = 0;
- }
+ if (st_lookup(arg->object_table, obj, &v)) {
+ info = (struct allocation_info *)v;
+ info->living = 0;
+ }
}
else {
- if (st_delete(arg->object_table, &obj, &v)) {
- info = (struct allocation_info *)v;
- delete_unique_str(arg->str_table, info->path);
- delete_unique_str(arg->str_table, info->class_path);
- ruby_xfree(info);
- }
+ if (st_delete(arg->object_table, &obj, &v)) {
+ info = (struct allocation_info *)v;
+ delete_unique_str(arg->str_table, info->path);
+ delete_unique_str(arg->str_table, info->class_path);
+ ruby_xfree(info);
+ }
}
+
+ if (gc_disabled == Qfalse) rb_gc_enable();
}
static int
@@ -208,7 +215,8 @@ allocation_info_tracer_compact(void *ptr)
{
struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
- if (st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) {
+ 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");
}
}
@@ -235,12 +243,12 @@ get_traceobj_arg(void)
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;
- tmp_trace_arg->freeobj_trace = 0;
- tmp_trace_arg->object_table = st_init_numtable();
- tmp_trace_arg->str_table = st_init_strtable();
+ tmp_trace_arg->running = 0;
+ tmp_trace_arg->keep_remains = tmp_keep_remains;
+ tmp_trace_arg->newobj_trace = 0;
+ tmp_trace_arg->freeobj_trace = 0;
+ tmp_trace_arg->object_table = st_init_numtable();
+ tmp_trace_arg->str_table = st_init_strtable();
}
return tmp_trace_arg;
}
@@ -257,15 +265,15 @@ trace_object_allocations_start(VALUE self)
struct traceobj_arg *arg = get_traceobj_arg();
if (arg->running++ > 0) {
- /* do nothing */
+ /* do nothing */
}
else {
- if (arg->newobj_trace == 0) {
- arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
- arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
- }
- rb_tracepoint_enable(arg->newobj_trace);
- rb_tracepoint_enable(arg->freeobj_trace);
+ if (arg->newobj_trace == 0) {
+ arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
+ arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
+ }
+ rb_tracepoint_enable(arg->newobj_trace);
+ rb_tracepoint_enable(arg->freeobj_trace);
}
return Qnil;
@@ -286,7 +294,7 @@ trace_object_allocations_stop(VALUE self)
struct traceobj_arg *arg = get_traceobj_arg();
if (arg->running > 0) {
- arg->running--;
+ arg->running--;
}
if (arg->running == 0) {
@@ -373,8 +381,8 @@ object_allocations_reporter_i(st_data_t key, st_data_t val, st_data_t ptr)
else fprintf(out, "C: %p", (void *)info->klass);
fprintf(out, "@%s:%lu", info->path ? info->path : "", info->line);
if (!NIL_P(info->mid)) {
- VALUE m = rb_sym2str(info->mid);
- fprintf(out, " (%s)", RSTRING_PTR(m));
+ VALUE m = rb_sym2str(info->mid);
+ fprintf(out, " (%s)", RSTRING_PTR(m));
}
fprintf(out, ")\n");
@@ -386,7 +394,7 @@ object_allocations_reporter(FILE *out, void *ptr)
{
fprintf(out, "== object_allocations_reporter: START\n");
if (tmp_trace_arg) {
- st_foreach(tmp_trace_arg->object_table, object_allocations_reporter_i, (st_data_t)out);
+ st_foreach(tmp_trace_arg->object_table, object_allocations_reporter_i, (st_data_t)out);
}
fprintf(out, "== object_allocations_reporter: END\n");
}
@@ -396,8 +404,8 @@ trace_object_allocations_debug_start(VALUE self)
{
tmp_keep_remains = 1;
if (object_allocations_reporter_registered == 0) {
- object_allocations_reporter_registered = 1;
- rb_bug_reporter_add(object_allocations_reporter, 0);
+ object_allocations_reporter_registered = 1;
+ rb_bug_reporter_add(object_allocations_reporter, 0);
}
return trace_object_allocations_start(self);
@@ -407,10 +415,10 @@ static struct allocation_info *
lookup_allocation_info(VALUE obj)
{
if (tmp_trace_arg) {
- st_data_t info;
- if (st_lookup(tmp_trace_arg->object_table, obj, &info)) {
- return (struct allocation_info *)info;
- }
+ st_data_t info;
+ if (st_lookup(tmp_trace_arg->object_table, obj, &info)) {
+ return (struct allocation_info *)info;
+ }
}
return NULL;
}
@@ -434,10 +442,10 @@ allocation_sourcefile(VALUE self, VALUE obj)
struct allocation_info *info = lookup_allocation_info(obj);
if (info && info->path) {
- return rb_str_new2(info->path);
+ return rb_str_new2(info->path);
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -454,10 +462,10 @@ allocation_sourceline(VALUE self, VALUE obj)
struct allocation_info *info = lookup_allocation_info(obj);
if (info) {
- return INT2FIX(info->line);
+ return INT2FIX(info->line);
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -485,10 +493,10 @@ allocation_class_path(VALUE self, VALUE obj)
struct allocation_info *info = lookup_allocation_info(obj);
if (info && info->class_path) {
- return rb_str_new2(info->class_path);
+ return rb_str_new2(info->class_path);
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -517,10 +525,10 @@ allocation_method_id(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info) {
- return info->mid;
+ return info->mid;
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -549,10 +557,10 @@ allocation_generation(VALUE self, VALUE obj)
{
struct allocation_info *info = lookup_allocation_info(obj);
if (info) {
- return SIZET2NUM(info->generation);
+ return SIZET2NUM(info->generation);
}
else {
- return Qnil;
+ return Qnil;
}
}
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 2784a88e85..ca08604c95 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -61,18 +61,10 @@ 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_PAYLOAD:
- case T_ZOMBIE:
- return;
- default:
- if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
- data->total += rb_obj_memsize_of(v);
- }
+ if (!rb_objspace_internal_object_p(v)) {
+ if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
+ data->total += rb_obj_memsize_of(v);
+ }
}
}
@@ -148,7 +140,7 @@ memsize_of_all_m(int argc, VALUE *argv, VALUE self)
struct total_data data = {0, 0};
if (argc > 0) {
- rb_scan_args(argc, argv, "01", &data.klass);
+ rb_scan_args(argc, argv, "01", &data.klass);
}
each_object_with_flags(total_i, &data);
@@ -198,34 +190,33 @@ type2sym(enum ruby_value_type i)
VALUE type;
switch (i) {
#define CASE_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
- CASE_TYPE(T_NONE);
- CASE_TYPE(T_OBJECT);
- CASE_TYPE(T_CLASS);
- CASE_TYPE(T_MODULE);
- CASE_TYPE(T_FLOAT);
- CASE_TYPE(T_STRING);
- CASE_TYPE(T_REGEXP);
- CASE_TYPE(T_ARRAY);
- CASE_TYPE(T_HASH);
- CASE_TYPE(T_STRUCT);
- CASE_TYPE(T_BIGNUM);
- CASE_TYPE(T_FILE);
- CASE_TYPE(T_DATA);
- CASE_TYPE(T_MATCH);
- CASE_TYPE(T_COMPLEX);
- CASE_TYPE(T_RATIONAL);
- CASE_TYPE(T_NIL);
- CASE_TYPE(T_TRUE);
- CASE_TYPE(T_FALSE);
- CASE_TYPE(T_SYMBOL);
- CASE_TYPE(T_FIXNUM);
- CASE_TYPE(T_UNDEF);
- CASE_TYPE(T_IMEMO);
- CASE_TYPE(T_NODE);
- CASE_TYPE(T_ICLASS);
+ CASE_TYPE(T_NONE);
+ CASE_TYPE(T_OBJECT);
+ CASE_TYPE(T_CLASS);
+ CASE_TYPE(T_MODULE);
+ CASE_TYPE(T_FLOAT);
+ CASE_TYPE(T_STRING);
+ CASE_TYPE(T_REGEXP);
+ CASE_TYPE(T_ARRAY);
+ CASE_TYPE(T_HASH);
+ CASE_TYPE(T_STRUCT);
+ CASE_TYPE(T_BIGNUM);
+ CASE_TYPE(T_FILE);
+ CASE_TYPE(T_DATA);
+ CASE_TYPE(T_MATCH);
+ CASE_TYPE(T_COMPLEX);
+ CASE_TYPE(T_RATIONAL);
+ CASE_TYPE(T_NIL);
+ CASE_TYPE(T_TRUE);
+ CASE_TYPE(T_FALSE);
+ CASE_TYPE(T_SYMBOL);
+ CASE_TYPE(T_FIXNUM);
+ CASE_TYPE(T_UNDEF);
+ CASE_TYPE(T_IMEMO);
+ CASE_TYPE(T_NODE);
+ CASE_TYPE(T_ICLASS);
CASE_TYPE(T_MOVED);
- CASE_TYPE(T_ZOMBIE);
- CASE_TYPE(T_PAYLOAD);
+ CASE_TYPE(T_ZOMBIE);
#undef CASE_TYPE
default: rb_bug("type2sym: unknown type (%d)", i);
}
@@ -264,17 +255,17 @@ count_objects_size(int argc, VALUE *argv, VALUE os)
VALUE hash = setup_hash(argc, argv);
for (i = 0; i <= T_MASK; i++) {
- counts[i] = 0;
+ counts[i] = 0;
}
each_object_with_flags(cos_i, &counts[0]);
for (i = 0; i <= T_MASK; i++) {
- if (counts[i]) {
- VALUE type = type2sym(i);
- total += counts[i];
- rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
- }
+ if (counts[i]) {
+ VALUE type = type2sym(i);
+ total += counts[i];
+ rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
+ }
}
rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
return hash;
@@ -388,128 +379,128 @@ count_nodes(int argc, VALUE *argv, VALUE os)
VALUE hash = setup_hash(argc, argv);
for (i = 0; i <= NODE_LAST; i++) {
- nodes[i] = 0;
+ nodes[i] = 0;
}
each_object_with_flags(cn_i, &nodes[0]);
for (i=0; i<NODE_LAST; i++) {
- if (nodes[i] != 0) {
- VALUE node;
- switch (i) {
+ if (nodes[i] != 0) {
+ VALUE node;
+ switch (i) {
#define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); goto set
- COUNT_NODE(NODE_SCOPE);
- COUNT_NODE(NODE_BLOCK);
- COUNT_NODE(NODE_IF);
- COUNT_NODE(NODE_UNLESS);
- COUNT_NODE(NODE_CASE);
- COUNT_NODE(NODE_CASE2);
- COUNT_NODE(NODE_CASE3);
- COUNT_NODE(NODE_WHEN);
- COUNT_NODE(NODE_IN);
- COUNT_NODE(NODE_WHILE);
- COUNT_NODE(NODE_UNTIL);
- COUNT_NODE(NODE_ITER);
- COUNT_NODE(NODE_FOR);
- COUNT_NODE(NODE_FOR_MASGN);
- COUNT_NODE(NODE_BREAK);
- COUNT_NODE(NODE_NEXT);
- COUNT_NODE(NODE_REDO);
- COUNT_NODE(NODE_RETRY);
- COUNT_NODE(NODE_BEGIN);
- COUNT_NODE(NODE_RESCUE);
- COUNT_NODE(NODE_RESBODY);
- COUNT_NODE(NODE_ENSURE);
- COUNT_NODE(NODE_AND);
- COUNT_NODE(NODE_OR);
- COUNT_NODE(NODE_MASGN);
- COUNT_NODE(NODE_LASGN);
- COUNT_NODE(NODE_DASGN);
- COUNT_NODE(NODE_DASGN_CURR);
- COUNT_NODE(NODE_GASGN);
- COUNT_NODE(NODE_IASGN);
- COUNT_NODE(NODE_CDECL);
- COUNT_NODE(NODE_CVASGN);
- COUNT_NODE(NODE_OP_ASGN1);
- COUNT_NODE(NODE_OP_ASGN2);
- COUNT_NODE(NODE_OP_ASGN_AND);
- COUNT_NODE(NODE_OP_ASGN_OR);
- COUNT_NODE(NODE_OP_CDECL);
- COUNT_NODE(NODE_CALL);
- COUNT_NODE(NODE_OPCALL);
- COUNT_NODE(NODE_FCALL);
- COUNT_NODE(NODE_VCALL);
- COUNT_NODE(NODE_QCALL);
- COUNT_NODE(NODE_SUPER);
- COUNT_NODE(NODE_ZSUPER);
- COUNT_NODE(NODE_LIST);
- COUNT_NODE(NODE_ZLIST);
- COUNT_NODE(NODE_VALUES);
- COUNT_NODE(NODE_HASH);
- COUNT_NODE(NODE_RETURN);
- COUNT_NODE(NODE_YIELD);
- COUNT_NODE(NODE_LVAR);
- COUNT_NODE(NODE_DVAR);
- COUNT_NODE(NODE_GVAR);
- COUNT_NODE(NODE_IVAR);
- COUNT_NODE(NODE_CONST);
- COUNT_NODE(NODE_CVAR);
- COUNT_NODE(NODE_NTH_REF);
- COUNT_NODE(NODE_BACK_REF);
- COUNT_NODE(NODE_MATCH);
- COUNT_NODE(NODE_MATCH2);
- COUNT_NODE(NODE_MATCH3);
- COUNT_NODE(NODE_LIT);
- COUNT_NODE(NODE_STR);
- COUNT_NODE(NODE_DSTR);
- COUNT_NODE(NODE_XSTR);
- COUNT_NODE(NODE_DXSTR);
- COUNT_NODE(NODE_EVSTR);
- COUNT_NODE(NODE_DREGX);
- COUNT_NODE(NODE_ONCE);
- COUNT_NODE(NODE_ARGS);
- COUNT_NODE(NODE_ARGS_AUX);
- COUNT_NODE(NODE_OPT_ARG);
- COUNT_NODE(NODE_KW_ARG);
- COUNT_NODE(NODE_POSTARG);
- COUNT_NODE(NODE_ARGSCAT);
- COUNT_NODE(NODE_ARGSPUSH);
- COUNT_NODE(NODE_SPLAT);
- COUNT_NODE(NODE_BLOCK_PASS);
- COUNT_NODE(NODE_DEFN);
- COUNT_NODE(NODE_DEFS);
- COUNT_NODE(NODE_ALIAS);
- COUNT_NODE(NODE_VALIAS);
- COUNT_NODE(NODE_UNDEF);
- COUNT_NODE(NODE_CLASS);
- COUNT_NODE(NODE_MODULE);
- COUNT_NODE(NODE_SCLASS);
- COUNT_NODE(NODE_COLON2);
- COUNT_NODE(NODE_COLON3);
- COUNT_NODE(NODE_DOT2);
- COUNT_NODE(NODE_DOT3);
- COUNT_NODE(NODE_FLIP2);
- COUNT_NODE(NODE_FLIP3);
- COUNT_NODE(NODE_SELF);
- COUNT_NODE(NODE_NIL);
- COUNT_NODE(NODE_TRUE);
- COUNT_NODE(NODE_FALSE);
- COUNT_NODE(NODE_ERRINFO);
- COUNT_NODE(NODE_DEFINED);
- COUNT_NODE(NODE_POSTEXE);
- COUNT_NODE(NODE_DSYM);
- COUNT_NODE(NODE_ATTRASGN);
- COUNT_NODE(NODE_LAMBDA);
- COUNT_NODE(NODE_ARYPTN);
- COUNT_NODE(NODE_FNDPTN);
- COUNT_NODE(NODE_HSHPTN);
+ COUNT_NODE(NODE_SCOPE);
+ COUNT_NODE(NODE_BLOCK);
+ COUNT_NODE(NODE_IF);
+ COUNT_NODE(NODE_UNLESS);
+ COUNT_NODE(NODE_CASE);
+ COUNT_NODE(NODE_CASE2);
+ COUNT_NODE(NODE_CASE3);
+ COUNT_NODE(NODE_WHEN);
+ COUNT_NODE(NODE_IN);
+ COUNT_NODE(NODE_WHILE);
+ COUNT_NODE(NODE_UNTIL);
+ COUNT_NODE(NODE_ITER);
+ COUNT_NODE(NODE_FOR);
+ COUNT_NODE(NODE_FOR_MASGN);
+ COUNT_NODE(NODE_BREAK);
+ COUNT_NODE(NODE_NEXT);
+ COUNT_NODE(NODE_REDO);
+ COUNT_NODE(NODE_RETRY);
+ COUNT_NODE(NODE_BEGIN);
+ COUNT_NODE(NODE_RESCUE);
+ COUNT_NODE(NODE_RESBODY);
+ COUNT_NODE(NODE_ENSURE);
+ COUNT_NODE(NODE_AND);
+ COUNT_NODE(NODE_OR);
+ COUNT_NODE(NODE_MASGN);
+ COUNT_NODE(NODE_LASGN);
+ COUNT_NODE(NODE_DASGN);
+ COUNT_NODE(NODE_GASGN);
+ COUNT_NODE(NODE_IASGN);
+ COUNT_NODE(NODE_CDECL);
+ COUNT_NODE(NODE_CVASGN);
+ COUNT_NODE(NODE_OP_ASGN1);
+ COUNT_NODE(NODE_OP_ASGN2);
+ COUNT_NODE(NODE_OP_ASGN_AND);
+ COUNT_NODE(NODE_OP_ASGN_OR);
+ COUNT_NODE(NODE_OP_CDECL);
+ COUNT_NODE(NODE_CALL);
+ COUNT_NODE(NODE_OPCALL);
+ COUNT_NODE(NODE_FCALL);
+ COUNT_NODE(NODE_VCALL);
+ COUNT_NODE(NODE_QCALL);
+ COUNT_NODE(NODE_SUPER);
+ COUNT_NODE(NODE_ZSUPER);
+ COUNT_NODE(NODE_LIST);
+ COUNT_NODE(NODE_ZLIST);
+ COUNT_NODE(NODE_VALUES);
+ COUNT_NODE(NODE_HASH);
+ COUNT_NODE(NODE_RETURN);
+ COUNT_NODE(NODE_YIELD);
+ COUNT_NODE(NODE_LVAR);
+ COUNT_NODE(NODE_DVAR);
+ COUNT_NODE(NODE_GVAR);
+ COUNT_NODE(NODE_IVAR);
+ COUNT_NODE(NODE_CONST);
+ COUNT_NODE(NODE_CVAR);
+ COUNT_NODE(NODE_NTH_REF);
+ COUNT_NODE(NODE_BACK_REF);
+ COUNT_NODE(NODE_MATCH);
+ COUNT_NODE(NODE_MATCH2);
+ COUNT_NODE(NODE_MATCH3);
+ COUNT_NODE(NODE_LIT);
+ COUNT_NODE(NODE_STR);
+ COUNT_NODE(NODE_DSTR);
+ COUNT_NODE(NODE_XSTR);
+ COUNT_NODE(NODE_DXSTR);
+ COUNT_NODE(NODE_EVSTR);
+ COUNT_NODE(NODE_DREGX);
+ COUNT_NODE(NODE_ONCE);
+ COUNT_NODE(NODE_ARGS);
+ COUNT_NODE(NODE_ARGS_AUX);
+ COUNT_NODE(NODE_OPT_ARG);
+ COUNT_NODE(NODE_KW_ARG);
+ COUNT_NODE(NODE_POSTARG);
+ COUNT_NODE(NODE_ARGSCAT);
+ COUNT_NODE(NODE_ARGSPUSH);
+ COUNT_NODE(NODE_SPLAT);
+ COUNT_NODE(NODE_BLOCK_PASS);
+ COUNT_NODE(NODE_DEFN);
+ COUNT_NODE(NODE_DEFS);
+ COUNT_NODE(NODE_ALIAS);
+ COUNT_NODE(NODE_VALIAS);
+ COUNT_NODE(NODE_UNDEF);
+ COUNT_NODE(NODE_CLASS);
+ COUNT_NODE(NODE_MODULE);
+ COUNT_NODE(NODE_SCLASS);
+ COUNT_NODE(NODE_COLON2);
+ COUNT_NODE(NODE_COLON3);
+ COUNT_NODE(NODE_DOT2);
+ COUNT_NODE(NODE_DOT3);
+ COUNT_NODE(NODE_FLIP2);
+ COUNT_NODE(NODE_FLIP3);
+ COUNT_NODE(NODE_SELF);
+ COUNT_NODE(NODE_NIL);
+ COUNT_NODE(NODE_TRUE);
+ COUNT_NODE(NODE_FALSE);
+ COUNT_NODE(NODE_ERRINFO);
+ COUNT_NODE(NODE_DEFINED);
+ COUNT_NODE(NODE_POSTEXE);
+ COUNT_NODE(NODE_DSYM);
+ COUNT_NODE(NODE_ATTRASGN);
+ COUNT_NODE(NODE_LAMBDA);
+ COUNT_NODE(NODE_ARYPTN);
+ COUNT_NODE(NODE_FNDPTN);
+ COUNT_NODE(NODE_HSHPTN);
+ COUNT_NODE(NODE_ERROR);
#undef COUNT_NODE
- case NODE_LAST: break;
- }
- UNREACHABLE;
- set:
- rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
- }
+ case NODE_LAST: break;
+ }
+ UNREACHABLE;
+ set:
+ rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
+ }
}
return hash;
}
@@ -639,20 +630,22 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
VALUE hash = setup_hash(argc, argv);
if (imemo_type_ids[0] == 0) {
- imemo_type_ids[0] = rb_intern("imemo_env");
- imemo_type_ids[1] = rb_intern("imemo_cref");
- imemo_type_ids[2] = rb_intern("imemo_svar");
- imemo_type_ids[3] = rb_intern("imemo_throw_data");
- imemo_type_ids[4] = rb_intern("imemo_ifunc");
- imemo_type_ids[5] = rb_intern("imemo_memo");
- imemo_type_ids[6] = rb_intern("imemo_ment");
- imemo_type_ids[7] = rb_intern("imemo_iseq");
- 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");
+#define INIT_IMEMO_TYPE_ID(n) (imemo_type_ids[n] = rb_intern_const(#n))
+ INIT_IMEMO_TYPE_ID(imemo_env);
+ INIT_IMEMO_TYPE_ID(imemo_cref);
+ INIT_IMEMO_TYPE_ID(imemo_svar);
+ INIT_IMEMO_TYPE_ID(imemo_throw_data);
+ INIT_IMEMO_TYPE_ID(imemo_ifunc);
+ INIT_IMEMO_TYPE_ID(imemo_memo);
+ INIT_IMEMO_TYPE_ID(imemo_ment);
+ INIT_IMEMO_TYPE_ID(imemo_iseq);
+ INIT_IMEMO_TYPE_ID(imemo_tmpbuf);
+ INIT_IMEMO_TYPE_ID(imemo_ast);
+ INIT_IMEMO_TYPE_ID(imemo_parser_strterm);
+ INIT_IMEMO_TYPE_ID(imemo_callinfo);
+ INIT_IMEMO_TYPE_ID(imemo_callcache);
+ INIT_IMEMO_TYPE_ID(imemo_constcache);
+#undef INIT_IMEMO_TYPE_ID
}
each_object_with_flags(count_imemo_objects_i, (void *)hash);
@@ -715,7 +708,7 @@ iow_internal_object_id(VALUE self)
struct rof_data {
VALUE refs;
- VALUE internals;
+ VALUE values;
};
static void
@@ -726,11 +719,15 @@ reachable_object_from_i(VALUE obj, void *data_ptr)
VALUE val = obj;
if (rb_objspace_markable_object_p(obj)) {
- if (rb_objspace_internal_object_p(obj)) {
- val = iow_newobj(obj);
- rb_ary_push(data->internals, val);
- }
- rb_hash_aset(data->refs, key, val);
+ if (NIL_P(rb_hash_lookup(data->refs, key))) {
+ rb_hash_aset(data->refs, key, Qtrue);
+
+ if (rb_objspace_internal_object_p(obj)) {
+ val = iow_newobj(obj);
+ }
+
+ rb_ary_push(data->values, val);
+ }
}
}
@@ -788,21 +785,21 @@ static VALUE
reachable_objects_from(VALUE self, VALUE obj)
{
if (rb_objspace_markable_object_p(obj)) {
- struct rof_data data;
+ struct rof_data data;
- if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
- obj = (VALUE)DATA_PTR(obj);
- }
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
- data.refs = rb_ident_hash_new();
- data.internals = rb_ary_new();
+ data.refs = rb_obj_hide(rb_ident_hash_new());
+ data.values = rb_ary_new();
- rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
+ rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
- return rb_funcall(data.refs, rb_intern("values"), 0);
+ return data.values;
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -821,26 +818,26 @@ reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
VALUE category_objects;
if (category == data->last_category) {
- category_str = data->last_category_str;
- category_objects = data->last_category_objects;
+ category_str = data->last_category_str;
+ category_objects = data->last_category_objects;
}
else {
- data->last_category = category;
- category_str = data->last_category_str = rb_str_new2(category);
- category_objects = data->last_category_objects = rb_ident_hash_new();
- if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
- rb_bug("reachable_object_from_root_i: category should insert at once");
- }
- rb_hash_aset(data->categories, category_str, category_objects);
+ data->last_category = category;
+ category_str = data->last_category_str = rb_str_new2(category);
+ category_objects = data->last_category_objects = rb_ident_hash_new();
+ if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
+ rb_bug("reachable_object_from_root_i: category should insert at once");
+ }
+ rb_hash_aset(data->categories, category_str, category_objects);
}
if (rb_objspace_markable_object_p(obj) &&
- obj != data->categories &&
- obj != data->last_category_objects) {
- if (rb_objspace_internal_object_p(obj)) {
- obj = iow_newobj(obj);
- }
- rb_hash_aset(category_objects, obj, obj);
+ obj != data->categories &&
+ obj != data->last_category_objects) {
+ if (rb_objspace_internal_object_p(obj)) {
+ obj = iow_newobj(obj);
+ }
+ rb_hash_aset(category_objects, obj, obj);
}
}
@@ -876,14 +873,14 @@ static VALUE
wrap_klass_iow(VALUE klass)
{
if (!RTEST(klass)) {
- return Qnil;
+ return Qnil;
}
else if (RB_TYPE_P(klass, T_ICLASS) ||
CLASS_OF(klass) == Qfalse /* hidden object */) {
- return iow_newobj(klass);
+ return iow_newobj(klass);
}
else {
- return klass;
+ return klass;
}
}
@@ -902,7 +899,7 @@ objspace_internal_class_of(VALUE self, VALUE obj)
VALUE klass;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
- obj = (VALUE)DATA_PTR(obj);
+ obj = (VALUE)DATA_PTR(obj);
}
if (RB_TYPE_P(obj, T_IMEMO)) {
@@ -929,17 +926,17 @@ objspace_internal_super_of(VALUE self, VALUE obj)
VALUE super;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
- obj = (VALUE)DATA_PTR(obj);
+ obj = (VALUE)DATA_PTR(obj);
}
switch (OBJ_BUILTIN_TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_ICLASS:
- super = RCLASS_SUPER(obj);
- break;
+ super = RCLASS_SUPER(obj);
+ break;
default:
- rb_raise(rb_eArgError, "class or module is expected");
+ rb_raise(rb_eArgError, "class or module is expected");
}
return wrap_klass_iow(super);
@@ -998,6 +995,7 @@ Init_objspace(void)
* You can use the #type method to check the type of the internal object.
*/
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);
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index cf7acb5c6f..c3cc9a1e7b 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -13,10 +13,15 @@
**********************************************************************/
#include "gc.h"
+#include "id_table.h"
#include "internal.h"
+#include "internal/array.h"
+#include "internal/class.h"
#include "internal/hash.h"
#include "internal/string.h"
#include "internal/sanitizers.h"
+#include "symbol.h"
+#include "shape.h"
#include "node.h"
#include "objspace.h"
#include "ruby/debug.h"
@@ -35,11 +40,13 @@ struct dump_config {
const char *root_category;
VALUE cur_obj;
VALUE cur_obj_klass;
+ size_t cur_page_slot_size;
size_t cur_obj_references;
unsigned int roots: 1;
unsigned int full_heap: 1;
unsigned int partial_dump;
size_t since;
+ size_t shapes_since;
unsigned long buffer_len;
char buffer[BUFFER_CAPACITY];
};
@@ -75,7 +82,8 @@ buffer_ensure_capa(struct dump_config *dc, unsigned long requested)
}
}
-static void buffer_append(struct dump_config *dc, const char *cstr, unsigned long len)
+static void
+buffer_append(struct dump_config *dc, const char *cstr, unsigned long len)
{
if (LIKELY(len > 0)) {
buffer_ensure_capa(dc, len);
@@ -141,10 +149,10 @@ dump_append_sizet(struct dump_config *dc, const size_t number)
}
static void
-dump_append_c(struct dump_config *dc, char c)
+dump_append_c(struct dump_config *dc, unsigned char c)
{
if (c <= 0x1f) {
- const unsigned int width = (sizeof(c) * CHAR_BIT / 4) + 5;
+ const unsigned int width = rb_strlen_lit("\\u0000") + 1;
buffer_ensure_capa(dc, width);
unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "\\u00%02x", c);
RUBY_ASSERT(required <= width);
@@ -162,7 +170,7 @@ dump_append_ref(struct dump_config *dc, VALUE ref)
{
RUBY_ASSERT(ref > 0);
- char buffer[((sizeof(VALUE) * CHAR_BIT + 3) / 4) + 4];
+ char buffer[roomof(sizeof(VALUE) * CHAR_BIT, 4) + rb_strlen_lit("\"0x\"")];
char *buffer_start, *buffer_end;
buffer_start = buffer_end = &buffer[sizeof(buffer)];
@@ -234,32 +242,32 @@ obj_type(VALUE obj)
{
switch (BUILTIN_TYPE(obj)) {
#define CASE_TYPE(type) case T_##type: return #type
- CASE_TYPE(NONE);
- CASE_TYPE(NIL);
- CASE_TYPE(OBJECT);
- CASE_TYPE(CLASS);
- CASE_TYPE(ICLASS);
- CASE_TYPE(MODULE);
- CASE_TYPE(FLOAT);
- CASE_TYPE(STRING);
- CASE_TYPE(REGEXP);
- CASE_TYPE(ARRAY);
- CASE_TYPE(HASH);
- CASE_TYPE(STRUCT);
- CASE_TYPE(BIGNUM);
- CASE_TYPE(FILE);
- CASE_TYPE(FIXNUM);
- CASE_TYPE(TRUE);
- CASE_TYPE(FALSE);
- CASE_TYPE(DATA);
- CASE_TYPE(MATCH);
- CASE_TYPE(SYMBOL);
- CASE_TYPE(RATIONAL);
- CASE_TYPE(COMPLEX);
- CASE_TYPE(IMEMO);
- CASE_TYPE(UNDEF);
- CASE_TYPE(NODE);
- CASE_TYPE(ZOMBIE);
+ CASE_TYPE(NONE);
+ CASE_TYPE(NIL);
+ CASE_TYPE(OBJECT);
+ CASE_TYPE(CLASS);
+ CASE_TYPE(ICLASS);
+ CASE_TYPE(MODULE);
+ CASE_TYPE(FLOAT);
+ CASE_TYPE(STRING);
+ CASE_TYPE(REGEXP);
+ CASE_TYPE(ARRAY);
+ CASE_TYPE(HASH);
+ CASE_TYPE(STRUCT);
+ CASE_TYPE(BIGNUM);
+ CASE_TYPE(FILE);
+ CASE_TYPE(FIXNUM);
+ CASE_TYPE(TRUE);
+ CASE_TYPE(FALSE);
+ CASE_TYPE(DATA);
+ CASE_TYPE(MATCH);
+ CASE_TYPE(SYMBOL);
+ CASE_TYPE(RATIONAL);
+ CASE_TYPE(COMPLEX);
+ CASE_TYPE(IMEMO);
+ CASE_TYPE(UNDEF);
+ CASE_TYPE(NODE);
+ CASE_TYPE(ZOMBIE);
#undef CASE_TYPE
default: break;
}
@@ -312,6 +320,17 @@ reachable_object_i(VALUE ref, void *data)
dc->cur_obj_references++;
}
+static bool
+dump_string_ascii_only(const char *str, long size)
+{
+ for (long i = 0; i < size; i++) {
+ if (str[i] & 0x80) {
+ return false;
+ }
+ }
+ return true;
+}
+
static void
dump_append_string_content(struct dump_config *dc, VALUE obj)
{
@@ -322,12 +341,34 @@ dump_append_string_content(struct dump_config *dc, VALUE obj)
dump_append_sizet(dc, rb_str_capacity(obj));
}
- if (is_ascii_string(obj)) {
- dump_append(dc, ", \"value\":");
- dump_append_string_value(dc, obj);
+ if (RSTRING_LEN(obj) && rb_enc_asciicompat(rb_enc_from_index(ENCODING_GET(obj)))) {
+ int cr = ENC_CODERANGE(obj);
+ if (cr == RUBY_ENC_CODERANGE_UNKNOWN) {
+ if (dump_string_ascii_only(RSTRING_PTR(obj), RSTRING_LEN(obj))) {
+ cr = RUBY_ENC_CODERANGE_7BIT;
+ }
+ }
+ if (cr == RUBY_ENC_CODERANGE_7BIT) {
+ dump_append(dc, ", \"value\":");
+ dump_append_string_value(dc, obj);
+ }
}
}
+static inline void
+dump_append_id(struct dump_config *dc, ID id)
+{
+ if (is_instance_id(id)) {
+ dump_append_string_value(dc, rb_sym2str(ID2SYM(id)));
+ }
+ else {
+ dump_append(dc, "\"ID_INTERNAL(");
+ dump_append_sizet(dc, rb_id_to_serial(id));
+ dump_append(dc, ")\"");
+ }
+}
+
+
static void
dump_object(VALUE obj, struct dump_config *dc)
{
@@ -344,7 +385,11 @@ dump_object(VALUE obj, struct dump_config *dc)
dc->cur_obj = obj;
dc->cur_obj_references = 0;
- dc->cur_obj_klass = BUILTIN_TYPE(obj) == T_NODE ? 0 : RBASIC_CLASS(obj);
+ if (BUILTIN_TYPE(obj) == T_NODE || BUILTIN_TYPE(obj) == T_IMEMO) {
+ dc->cur_obj_klass = 0;
+ } else {
+ dc->cur_obj_klass = RBASIC_CLASS(obj);
+ }
if (dc->partial_dump && (!ainfo || ainfo->generation < dc->since)) {
return;
@@ -360,6 +405,13 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append(dc, obj_type(obj));
dump_append(dc, "\"");
+ size_t shape_id = rb_shape_get_shape_id(obj);
+ dump_append(dc, ", \"shape_id\":");
+ dump_append_sizet(dc, shape_id);
+
+ dump_append(dc, ", \"slot_size\":");
+ dump_append_sizet(dc, dc->cur_page_slot_size);
+
if (dc->cur_obj_klass) {
dump_append(dc, ", \"class\":");
dump_append_ref(dc, dc->cur_obj_klass);
@@ -385,8 +437,6 @@ dump_object(VALUE obj, struct dump_config *dc)
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))
@@ -399,6 +449,27 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append(dc, rb_enc_name(rb_enc_from_index(ENCODING_GET(obj))));
dump_append(dc, "\"");
}
+
+ dump_append(dc, ", \"coderange\":\"");
+ switch (RB_ENC_CODERANGE(obj)) {
+ case RUBY_ENC_CODERANGE_UNKNOWN:
+ dump_append(dc, "unknown");
+ break;
+ case RUBY_ENC_CODERANGE_7BIT:
+ dump_append(dc, "7bit");
+ break;
+ case RUBY_ENC_CODERANGE_VALID:
+ dump_append(dc, "valid");
+ break;
+ case RUBY_ENC_CODERANGE_BROKEN:
+ dump_append(dc, "broken");
+ break;
+ }
+ dump_append(dc, "\"");
+
+ if (RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_BROKEN)
+ dump_append(dc, ", \"broken\":true");
+
break;
case T_HASH:
@@ -413,9 +484,9 @@ dump_object(VALUE obj, struct dump_config *dc)
case T_ARRAY:
dump_append(dc, ", \"length\":");
dump_append_ld(dc, RARRAY_LEN(obj));
- if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED))
+ if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_SHARED_FLAG))
dump_append(dc, ", \"shared\":true");
- if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG))
+ if (FL_TEST(obj, RARRAY_EMBED_FLAG))
dump_append(dc, ", \"embedded\":true");
break;
@@ -427,6 +498,9 @@ dump_object(VALUE obj, struct dump_config *dc)
break;
case T_CLASS:
+ dump_append(dc, ", \"variation_count\":");
+ dump_append_d(dc, RCLASS_EXT(obj)->variation_count);
+
case T_MODULE:
if (rb_class_get_superclass(obj)) {
dump_append(dc, ", \"superclass\":");
@@ -439,7 +513,8 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append(dc, ", \"name\":\"");
dump_append(dc, RSTRING_PTR(mod_name));
dump_append(dc, "\"");
- } else {
+ }
+ else {
VALUE real_mod_name = rb_mod_name(rb_class_real(obj));
if (RTEST(real_mod_name)) {
dump_append(dc, ", \"real_class_name\":\"");
@@ -470,7 +545,10 @@ dump_object(VALUE obj, struct dump_config *dc)
case T_OBJECT:
dump_append(dc, ", \"ivars\":");
- dump_append_lu(dc, ROBJECT_NUMIV(obj));
+ dump_append_lu(dc, ROBJECT_IV_COUNT(obj));
+ if (rb_shape_obj_too_complex(obj)) {
+ dump_append(dc, ", \"too_complex_shape\":true");
+ }
break;
case T_FILE:
@@ -482,8 +560,8 @@ dump_object(VALUE obj, struct dump_config *dc)
break;
case T_ZOMBIE:
- dump_append(dc, "}\n");
- return;
+ dump_append(dc, "}\n");
+ return;
default:
break;
@@ -539,9 +617,10 @@ heap_i(void *vstart, void *vend, size_t stride, void *data)
for (; v != (VALUE)vend; v += stride) {
void *ptr = asan_poisoned_object_p(v);
asan_unpoison_object(v, false);
+ dc->cur_page_slot_size = stride;
- if (dc->full_heap || RBASIC(v)->flags)
- dump_object(v, dc);
+ if (dc->full_heap || RBASIC(v)->flags)
+ dump_object(v, dc);
if (ptr) {
asan_poison_object(v);
@@ -573,7 +652,7 @@ root_obj_i(const char *category, VALUE obj, void *data)
}
static void
-dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since)
+dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since, VALUE shapes)
{
dc->full_heap = 0;
@@ -582,7 +661,8 @@ dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since)
if (TYPE(output) == T_STRING) {
dc->stream = Qfalse;
dc->string = output;
- } else {
+ }
+ else {
dc->stream = output;
dc->string = Qfalse;
}
@@ -594,9 +674,12 @@ dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since)
if (RTEST(since)) {
dc->partial_dump = 1;
dc->since = NUM2SIZET(since);
- } else {
+ }
+ else {
dc->partial_dump = 0;
}
+
+ dc->shapes_since = RTEST(shapes) ? NUM2SIZET(shapes) : 0;
}
static VALUE
@@ -606,28 +689,103 @@ dump_result(struct dump_config *dc)
if (dc->string) {
return dc->string;
- } else {
+ }
+ else {
rb_io_flush(dc->stream);
return dc->stream;
}
}
+/* :nodoc: */
static VALUE
objspace_dump(VALUE os, VALUE obj, VALUE output)
{
struct dump_config dc = {0,};
- dump_output(&dc, output, Qnil, Qnil);
+ if (!RB_SPECIAL_CONST_P(obj)) {
+ dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
+ }
+
+ dump_output(&dc, output, Qnil, Qnil, Qnil);
dump_object(obj, &dc);
return dump_result(&dc);
}
+static void
+shape_i(rb_shape_t *shape, void *data)
+{
+ struct dump_config *dc = (struct dump_config *)data;
+
+ size_t shape_id = rb_shape_id(shape);
+ if (shape_id < dc->shapes_since) {
+ return;
+ }
+
+ dump_append(dc, "{\"address\":");
+ dump_append_ref(dc, (VALUE)shape);
+
+ dump_append(dc, ", \"type\":\"SHAPE\", \"id\":");
+ dump_append_sizet(dc, shape_id);
+
+ if (shape->type != SHAPE_ROOT) {
+ dump_append(dc, ", \"parent_id\":");
+ dump_append_lu(dc, shape->parent_id);
+ }
+
+ dump_append(dc, ", \"depth\":");
+ dump_append_sizet(dc, rb_shape_depth(shape));
+
+ dump_append(dc, ", \"shape_type\":");
+ switch((enum shape_type)shape->type) {
+ case SHAPE_ROOT:
+ dump_append(dc, "\"ROOT\"");
+ break;
+ case SHAPE_IVAR:
+ dump_append(dc, "\"IVAR\"");
+
+ dump_append(dc, ",\"edge_name\":");
+ dump_append_id(dc, shape->edge_name);
+
+ break;
+ case SHAPE_FROZEN:
+ dump_append(dc, "\"FROZEN\"");
+ break;
+ case SHAPE_CAPACITY_CHANGE:
+ dump_append(dc, "\"CAPACITY_CHANGE\"");
+ dump_append(dc, ", \"capacity\":");
+ dump_append_sizet(dc, shape->capacity);
+ break;
+ case SHAPE_INITIAL_CAPACITY:
+ dump_append(dc, "\"INITIAL_CAPACITY\"");
+ dump_append(dc, ", \"capacity\":");
+ dump_append_sizet(dc, shape->capacity);
+ break;
+ case SHAPE_T_OBJECT:
+ dump_append(dc, "\"T_OBJECT\"");
+ break;
+ case SHAPE_OBJ_TOO_COMPLEX:
+ dump_append(dc, "\"OBJ_TOO_COMPLEX\"");
+ break;
+ default:
+ rb_bug("[objspace] unexpected shape type");
+ }
+
+ dump_append(dc, ", \"edges\":");
+ dump_append_sizet(dc, rb_shape_edges_count(shape));
+
+ dump_append(dc, ", \"memsize\":");
+ dump_append_sizet(dc, rb_shape_memsize(shape));
+
+ dump_append(dc, "}\n");
+}
+
+/* :nodoc: */
static VALUE
-objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since)
+objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
{
struct dump_config dc = {0,};
- dump_output(&dc, output, full, since);
+ dump_output(&dc, output, full, since, shapes);
if (!dc.partial_dump || dc.since == 0) {
/* dump roots */
@@ -635,12 +793,29 @@ objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since)
if (dc.roots) dump_append(&dc, "]}\n");
}
+ if (RTEST(shapes)) {
+ rb_shape_each_shape(shape_i, &dc);
+ }
+
/* dump all objects */
rb_objspace_each_objects(heap_i, &dc);
return dump_result(&dc);
}
+/* :nodoc: */
+static VALUE
+objspace_dump_shapes(VALUE os, VALUE output, VALUE shapes)
+{
+ struct dump_config dc = {0,};
+ dump_output(&dc, output, Qfalse, Qnil, shapes);
+
+ if (RTEST(shapes)) {
+ rb_shape_each_shape(shape_i, &dc);
+ }
+ return dump_result(&dc);
+}
+
void
Init_objspace_dump(VALUE rb_mObjSpace)
{
@@ -650,7 +825,8 @@ Init_objspace_dump(VALUE rb_mObjSpace)
#endif
rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2);
- rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 3);
+ rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 4);
+ rb_define_module_function(rb_mObjSpace, "_dump_shapes", objspace_dump_shapes, 2);
/* force create static IDs */
rb_obj_gc_flags(rb_mObjSpace, 0, 0);
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index a4a82a146c..1e0df7dd87 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,217 @@
+Version 3.1.0
+=============
+
+Ruby/OpenSSL 3.1 will be maintained for the lifetime of Ruby 3.2.
+
+Merged bug fixes in 2.2.3 and 3.0.2. Among the new features and changes are:
+
+Notable changes
+---------------
+
+* Add `OpenSSL::SSL::SSLContext#ciphersuites=` to allow setting TLS 1.3 cipher
+ suites.
+ [[GitHub #493]](https://github.com/ruby/openssl/pull/493)
+* Add `OpenSSL::SSL::SSLSocket#export_keying_material` for exporting keying
+ material of the session, as defined in RFC 5705.
+ [[GitHub #530]](https://github.com/ruby/openssl/pull/530)
+* Add `OpenSSL::SSL::SSLContext#keylog_cb=` for setting the TLS key logging
+ callback, which is useful for supporting NSS's SSLKEYLOGFILE debugging output.
+ [[GitHub #536]](https://github.com/ruby/openssl/pull/536)
+* Remove the default digest algorithm from `OpenSSL::OCSP::BasicResponse#sign`
+ and `OpenSSL::OCSP::Request#sign`. Omitting the 5th parameter of these
+ methods used to be equivalent of specifying SHA-1. This default value is now
+ removed and we will let the underlying OpenSSL library decide instead.
+ [[GitHub #507]](https://github.com/ruby/openssl/pull/507)
+* Add `OpenSSL::BN#mod_sqrt`.
+ [[GitHub #553]](https://github.com/ruby/openssl/pull/553)
+* Allow calling `OpenSSL::Cipher#update` with an empty string. This was
+ prohibited to workaround an ancient bug in OpenSSL.
+ [[GitHub #568]](https://github.com/ruby/openssl/pull/568)
+* Fix build on platforms without socket support, such as WASI. `OpenSSL::SSL`
+ will not be defined if OpenSSL is compiled with `OPENSSL_NO_SOCK`.
+ [[GitHub #558]](https://github.com/ruby/openssl/pull/558)
+* Improve support for recent LibreSSL versions. This includes HKDF support in
+ LibreSSL 3.6 and Ed25519 support in LibreSSL 3.7.
+
+
+Version 3.0.2
+=============
+
+Merged changes in 2.2.3. Additionally, the following issues are fixed by this
+release.
+
+Bug fixes
+---------
+
+* Fix OpenSSL::PKey::EC#check_key not working correctly on OpenSSL 3.0.
+ [[GitHub #563]](https://github.com/ruby/openssl/issues/563)
+ [[GitHub #580]](https://github.com/ruby/openssl/pull/580)
+
+
+Version 3.0.1
+=============
+
+Merged changes in 2.1.4 and 2.2.2. Additionally, the following issues are fixed
+by this release.
+
+Bug fixes
+---------
+
+* Add missing type check in OpenSSL::PKey::PKey#sign's optional parameters.
+ [[GitHub #531]](https://github.com/ruby/openssl/pull/531)
+* Work around OpenSSL 3.0's HMAC issues with a zero-length key.
+ [[GitHub #538]](https://github.com/ruby/openssl/pull/538)
+* Fix a regression in OpenSSL::PKey::DSA.generate's default of 'q' size.
+ [[GitHub #483]](https://github.com/ruby/openssl/issues/483)
+ [[GitHub #539]](https://github.com/ruby/openssl/pull/539)
+* Restore OpenSSL::PKey.read's ability to decode "openssl ecparam -genkey"
+ output when linked against OpenSSL 3.0.
+ [[GitHub #535]](https://github.com/ruby/openssl/pull/535)
+ [[GitHub #540]](https://github.com/ruby/openssl/pull/540)
+* Restore error checks in OpenSSL::PKey::EC#{to_der,to_pem}.
+ [[GitHub #541]](https://github.com/ruby/openssl/pull/541)
+
+
+Version 3.0.0
+=============
+
+Compatibility notes
+-------------------
+
+* OpenSSL 1.0.1 and Ruby 2.3-2.5 are no longer supported.
+ [[GitHub #396]](https://github.com/ruby/openssl/pull/396)
+ [[GitHub #466]](https://github.com/ruby/openssl/pull/466)
+
+* OpenSSL 3.0 support is added. It is the first major version bump from OpenSSL
+ 1.1 and contains incompatible changes that affect Ruby/OpenSSL.
+ Note that OpenSSL 3.0 support is preliminary and not all features are
+ currently available:
+ [[GitHub #369]](https://github.com/ruby/openssl/issues/369)
+
+ - Deprecate the ability to modify `OpenSSL::PKey::PKey` instances. OpenSSL 3.0
+ made EVP_PKEY structure immutable, and hence the following methods are not
+ available when Ruby/OpenSSL is linked against OpenSSL 3.0.
+ [[GitHub #480]](https://github.com/ruby/openssl/pull/480)
+
+ - `OpenSSL::PKey::RSA#set_key`, `#set_factors`, `#set_crt_params`
+ - `OpenSSL::PKey::DSA#set_pqg`, `#set_key`
+ - `OpenSSL::PKey::DH#set_pqg`, `#set_key`, `#generate_key!`
+ - `OpenSSL::PKey::EC#private_key=`, `#public_key=`, `#group=`, `#generate_key!`
+
+ - Deprecate `OpenSSL::Engine`. The ENGINE API has been deprecated in OpenSSL 3.0
+ in favor of the new "provider" concept and will be removed in a future
+ version.
+ [[GitHub #481]](https://github.com/ruby/openssl/pull/481)
+
+* `OpenSSL::SSL::SSLContext#tmp_ecdh_callback` has been removed. It has been
+ deprecated since v2.0.0 because it is incompatible with modern OpenSSL
+ versions.
+ [[GitHub #394]](https://github.com/ruby/openssl/pull/394)
+
+* `OpenSSL::SSL::SSLSocket#read` and `#write` now raise `OpenSSL::SSL::SSLError`
+ if called before a TLS connection is established. Historically, they
+ read/wrote unencrypted data to the underlying socket directly in that case.
+ [[GitHub #9]](https://github.com/ruby/openssl/issues/9)
+ [[GitHub #469]](https://github.com/ruby/openssl/pull/469)
+
+
+Notable changes
+---------------
+
+* Enhance OpenSSL::PKey's common interface.
+ [[GitHub #370]](https://github.com/ruby/openssl/issues/370)
+
+ - Key deserialization: Enhance `OpenSSL::PKey.read` to handle PEM encoding of
+ DH parameters, which used to be only deserialized by `OpenSSL::PKey::DH.new`.
+ [[GitHub #328]](https://github.com/ruby/openssl/issues/328)
+ - Key generation: Add `OpenSSL::PKey.generate_parameters` and
+ `OpenSSL::PKey.generate_key`.
+ [[GitHub #329]](https://github.com/ruby/openssl/issues/329)
+ - Public key signing: Enhance `OpenSSL::PKey::PKey#sign` and `#verify` to use
+ the new EVP_DigestSign() family to enable PureEdDSA support on OpenSSL 1.1.1
+ or later. They also now take optional algorithm-specific parameters for more
+ control.
+ [[GitHub #329]](https://github.com/ruby/openssl/issues/329)
+ - Low-level public key signing and verification: Add
+ `OpenSSL::PKey::PKey#sign_raw`, `#verify_raw`, and `#verify_recover`.
+ [[GitHub #382]](https://github.com/ruby/openssl/issues/382)
+ - Public key encryption: Add `OpenSSL::PKey::PKey#encrypt` and `#decrypt`.
+ [[GitHub #382]](https://github.com/ruby/openssl/issues/382)
+ - Key agreement: Add `OpenSSL::PKey::PKey#derive`.
+ [[GitHub #329]](https://github.com/ruby/openssl/issues/329)
+ - Key comparison: Add `OpenSSL::PKey::PKey#compare?` to conveniently check
+ that two keys have common parameters and a public key.
+ [[GitHub #383]](https://github.com/ruby/openssl/issues/383)
+
+* Add `OpenSSL::BN#set_flags` and `#get_flags`. This can be used in combination
+ with `OpenSSL::BN::CONSTTIME` to force constant-time computation.
+ [[GitHub #417]](https://github.com/ruby/openssl/issues/417)
+
+* Add `OpenSSL::BN#abs` to get the absolute value of the BIGNUM.
+ [[GitHub #430]](https://github.com/ruby/openssl/issues/430)
+
+* Add `OpenSSL::SSL::SSLSocket#getbyte`.
+ [[GitHub #438]](https://github.com/ruby/openssl/issues/438)
+
+* Add `OpenSSL::SSL::SSLContext#tmp_dh=`.
+ [[GitHub #459]](https://github.com/ruby/openssl/pull/459)
+
+* Add `OpenSSL::X509::Certificate.load` to load a PEM-encoded and concatenated
+ list of X.509 certificates at once.
+ [[GitHub #441]](https://github.com/ruby/openssl/pull/441)
+
+* Change `OpenSSL::X509::Certificate.new` to attempt to deserialize the given
+ string first as DER encoding first and then as PEM encoding to ensure the
+ round-trip consistency.
+ [[GitHub #442]](https://github.com/ruby/openssl/pull/442)
+
+* Update various part of the code base to use the modern API. No breaking
+ changes are intended with this. This includes:
+
+ - `OpenSSL::HMAC` uses the EVP API.
+ [[GitHub #371]](https://github.com/ruby/openssl/issues/371)
+ - `OpenSSL::Config` uses native OpenSSL API to parse config files.
+ [[GitHub #342]](https://github.com/ruby/openssl/issues/342)
+
+
+Version 2.2.3
+=============
+
+Bug fixes
+---------
+
+* Fix serveral methods in OpenSSL::PKey::EC::Point attempting to raise an error
+ with an incorrect class, which would end up with a TypeError.
+ [[GitHub #570]](https://github.com/ruby/openssl/pull/570)
+* Fix OpenSSL::PKey::EC::Point#eql? and OpenSSL::PKey::EC::Group#eql?
+ incorrectly treated OpenSSL's internal errors as "not equal".
+ [[GitHub #564]](https://github.com/ruby/openssl/pull/564)
+* Fix build with LibreSSL 3.5 or later.
+
+
+Version 2.2.2
+=============
+
+Merged changes in 2.1.4.
+
+
+Version 2.2.1
+=============
+
+Merged changes in 2.1.3. Additionally, the following issues are fixed by this
+release.
+
+Bug fixes
+---------
+
+* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when
+ invalid arguments are given.
+ [[GitHub #407]](https://github.com/ruby/openssl/pull/407)
+* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms
+ where `time_t` has a different size from `long`.
+ [[GitHub #454]](https://github.com/ruby/openssl/pull/454)
+
+
Version 2.2.0
=============
@@ -75,6 +289,52 @@ Notable changes
[[GitHub #297]](https://github.com/ruby/openssl/pull/297)
+Version 2.1.4
+=============
+
+Bug fixes
+---------
+
+* Do not use pkg-config if --with-openssl-dir option is specified.
+ [[GitHub #486]](https://github.com/ruby/openssl/pull/486)
+
+
+Version 2.1.3
+=============
+
+Bug fixes
+---------
+
+* Fix deprecation warnings on Ruby 3.0.
+* Add ".include" directive support in `OpenSSL::Config`.
+ [[GitHub #216]](https://github.com/ruby/openssl/pull/216)
+* Fix handling of IPv6 address SANs.
+ [[GitHub #185]](https://github.com/ruby/openssl/pull/185)
+* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=`
+ sets a proper error code.
+ [[GitHub #350]](https://github.com/ruby/openssl/pull/350)
+* Fix crash with `OpenSSL::BN.new(nil, 2)`.
+ [[Bug #15760]](https://bugs.ruby-lang.org/issues/15760)
+* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from
+ being modified by another thread.
+ [[GitHub #453]](https://github.com/ruby/openssl/pull/453)
+* Fix misuse of input record separator in `OpenSSL::Buffering` where it was
+ for output.
+* Fix wrong integer casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
+ [[GitHub #460]](https://github.com/ruby/openssl/pull/460)
+* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or
+ newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support
+ OpenSSL 3.0 API.
+ [[GitHub #458]](https://github.com/ruby/openssl/pull/458)
+* Activate `digest` gem correctly. `digest` library could go into an
+ inconsistent state if there are multiple versions of `digest` is installed
+ and `openssl` is `require`d before `digest`.
+ [[GitHub #463]](https://github.com/ruby/openssl/pull/463)
+* Fix GC.compact compatibility.
+ [[GitHub #464]](https://github.com/ruby/openssl/issues/464)
+ [[GitHub #465]](https://github.com/ruby/openssl/pull/465)
+
+
Version 2.1.2
=============
diff --git a/ext/openssl/depend b/ext/openssl/depend
index df84de4d71..c38d224c85 100644
--- a/ext/openssl/depend
+++ b/ext/openssl/depend
@@ -11,7 +11,6 @@ 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
@@ -20,6 +19,7 @@ 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/abi.h
ossl.o: $(hdrdir)/ruby/internal/anyargs.h
ossl.o: $(hdrdir)/ruby/internal/arithmetic.h
ossl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -89,6 +89,15 @@ ossl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl.o: $(hdrdir)/ruby/internal/ctype.h
ossl.o: $(hdrdir)/ruby/internal/dllexport.h
ossl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl.o: $(hdrdir)/ruby/internal/error.h
ossl.o: $(hdrdir)/ruby/internal/eval.h
ossl.o: $(hdrdir)/ruby/internal/event.h
@@ -167,7 +176,6 @@ ossl.o: $(hdrdir)/ruby/ruby.h
ossl.o: $(hdrdir)/ruby/st.h
ossl.o: $(hdrdir)/ruby/subst.h
ossl.o: $(hdrdir)/ruby/thread.h
-ossl.o: $(hdrdir)/ruby/thread_native.h
ossl.o: openssl_missing.h
ossl.o: ossl.c
ossl.o: ossl.h
@@ -189,7 +197,6 @@ ossl.o: ossl_rand.h
ossl.o: ossl_ssl.h
ossl.o: ossl_ts.h
ossl.o: ossl_x509.h
-ossl.o: ruby_missing.h
ossl_asn1.o: $(RUBY_EXTCONF_H)
ossl_asn1.o: $(arch_hdrdir)/ruby/config.h
ossl_asn1.o: $(hdrdir)/ruby.h
@@ -198,7 +205,6 @@ 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
@@ -207,6 +213,7 @@ 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/abi.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
@@ -276,6 +283,15 @@ ossl_asn1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_asn1.o: $(hdrdir)/ruby/internal/ctype.h
ossl_asn1.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_asn1.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_asn1.o: $(hdrdir)/ruby/internal/error.h
ossl_asn1.o: $(hdrdir)/ruby/internal/eval.h
ossl_asn1.o: $(hdrdir)/ruby/internal/event.h
@@ -375,7 +391,6 @@ ossl_asn1.o: ossl_rand.h
ossl_asn1.o: ossl_ssl.h
ossl_asn1.o: ossl_ts.h
ossl_asn1.o: ossl_x509.h
-ossl_asn1.o: ruby_missing.h
ossl_bio.o: $(RUBY_EXTCONF_H)
ossl_bio.o: $(arch_hdrdir)/ruby/config.h
ossl_bio.o: $(hdrdir)/ruby.h
@@ -384,7 +399,6 @@ 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
@@ -393,6 +407,7 @@ 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/abi.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
@@ -462,6 +477,15 @@ ossl_bio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_bio.o: $(hdrdir)/ruby/internal/ctype.h
ossl_bio.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_bio.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_bio.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_bio.o: $(hdrdir)/ruby/internal/error.h
ossl_bio.o: $(hdrdir)/ruby/internal/eval.h
ossl_bio.o: $(hdrdir)/ruby/internal/event.h
@@ -561,7 +585,6 @@ ossl_bio.o: ossl_rand.h
ossl_bio.o: ossl_ssl.h
ossl_bio.o: ossl_ts.h
ossl_bio.o: ossl_x509.h
-ossl_bio.o: ruby_missing.h
ossl_bn.o: $(RUBY_EXTCONF_H)
ossl_bn.o: $(arch_hdrdir)/ruby/config.h
ossl_bn.o: $(hdrdir)/ruby.h
@@ -570,7 +593,6 @@ 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
@@ -579,6 +601,7 @@ 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/abi.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
@@ -648,6 +671,15 @@ ossl_bn.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_bn.o: $(hdrdir)/ruby/internal/ctype.h
ossl_bn.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_bn.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_bn.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_bn.o: $(hdrdir)/ruby/internal/error.h
ossl_bn.o: $(hdrdir)/ruby/internal/eval.h
ossl_bn.o: $(hdrdir)/ruby/internal/event.h
@@ -748,7 +780,6 @@ ossl_bn.o: ossl_rand.h
ossl_bn.o: ossl_ssl.h
ossl_bn.o: ossl_ts.h
ossl_bn.o: ossl_x509.h
-ossl_bn.o: ruby_missing.h
ossl_cipher.o: $(RUBY_EXTCONF_H)
ossl_cipher.o: $(arch_hdrdir)/ruby/config.h
ossl_cipher.o: $(hdrdir)/ruby.h
@@ -757,7 +788,6 @@ 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
@@ -766,6 +796,7 @@ 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/abi.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
@@ -835,6 +866,15 @@ ossl_cipher.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_cipher.o: $(hdrdir)/ruby/internal/ctype.h
ossl_cipher.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_cipher.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_cipher.o: $(hdrdir)/ruby/internal/error.h
ossl_cipher.o: $(hdrdir)/ruby/internal/eval.h
ossl_cipher.o: $(hdrdir)/ruby/internal/event.h
@@ -934,7 +974,6 @@ ossl_cipher.o: ossl_rand.h
ossl_cipher.o: ossl_ssl.h
ossl_cipher.o: ossl_ts.h
ossl_cipher.o: ossl_x509.h
-ossl_cipher.o: ruby_missing.h
ossl_config.o: $(RUBY_EXTCONF_H)
ossl_config.o: $(arch_hdrdir)/ruby/config.h
ossl_config.o: $(hdrdir)/ruby.h
@@ -943,7 +982,6 @@ 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
@@ -952,6 +990,7 @@ 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/abi.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
@@ -1021,6 +1060,15 @@ ossl_config.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_config.o: $(hdrdir)/ruby/internal/ctype.h
ossl_config.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_config.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_config.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_config.o: $(hdrdir)/ruby/internal/error.h
ossl_config.o: $(hdrdir)/ruby/internal/eval.h
ossl_config.o: $(hdrdir)/ruby/internal/event.h
@@ -1120,7 +1168,6 @@ ossl_config.o: ossl_rand.h
ossl_config.o: ossl_ssl.h
ossl_config.o: ossl_ts.h
ossl_config.o: ossl_x509.h
-ossl_config.o: ruby_missing.h
ossl_digest.o: $(RUBY_EXTCONF_H)
ossl_digest.o: $(arch_hdrdir)/ruby/config.h
ossl_digest.o: $(hdrdir)/ruby.h
@@ -1129,7 +1176,6 @@ 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
@@ -1138,6 +1184,7 @@ 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/abi.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
@@ -1207,6 +1254,15 @@ ossl_digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_digest.o: $(hdrdir)/ruby/internal/ctype.h
ossl_digest.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_digest.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_digest.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_digest.o: $(hdrdir)/ruby/internal/error.h
ossl_digest.o: $(hdrdir)/ruby/internal/eval.h
ossl_digest.o: $(hdrdir)/ruby/internal/event.h
@@ -1306,7 +1362,6 @@ ossl_digest.o: ossl_rand.h
ossl_digest.o: ossl_ssl.h
ossl_digest.o: ossl_ts.h
ossl_digest.o: ossl_x509.h
-ossl_digest.o: ruby_missing.h
ossl_engine.o: $(RUBY_EXTCONF_H)
ossl_engine.o: $(arch_hdrdir)/ruby/config.h
ossl_engine.o: $(hdrdir)/ruby.h
@@ -1315,7 +1370,6 @@ 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
@@ -1324,6 +1378,7 @@ 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/abi.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
@@ -1393,6 +1448,15 @@ ossl_engine.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_engine.o: $(hdrdir)/ruby/internal/ctype.h
ossl_engine.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_engine.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_engine.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_engine.o: $(hdrdir)/ruby/internal/error.h
ossl_engine.o: $(hdrdir)/ruby/internal/eval.h
ossl_engine.o: $(hdrdir)/ruby/internal/event.h
@@ -1492,7 +1556,6 @@ ossl_engine.o: ossl_rand.h
ossl_engine.o: ossl_ssl.h
ossl_engine.o: ossl_ts.h
ossl_engine.o: ossl_x509.h
-ossl_engine.o: ruby_missing.h
ossl_hmac.o: $(RUBY_EXTCONF_H)
ossl_hmac.o: $(arch_hdrdir)/ruby/config.h
ossl_hmac.o: $(hdrdir)/ruby.h
@@ -1501,7 +1564,6 @@ 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
@@ -1510,6 +1572,7 @@ 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/abi.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
@@ -1579,6 +1642,15 @@ ossl_hmac.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_hmac.o: $(hdrdir)/ruby/internal/ctype.h
ossl_hmac.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_hmac.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_hmac.o: $(hdrdir)/ruby/internal/error.h
ossl_hmac.o: $(hdrdir)/ruby/internal/eval.h
ossl_hmac.o: $(hdrdir)/ruby/internal/event.h
@@ -1678,7 +1750,6 @@ ossl_hmac.o: ossl_rand.h
ossl_hmac.o: ossl_ssl.h
ossl_hmac.o: ossl_ts.h
ossl_hmac.o: ossl_x509.h
-ossl_hmac.o: ruby_missing.h
ossl_kdf.o: $(RUBY_EXTCONF_H)
ossl_kdf.o: $(arch_hdrdir)/ruby/config.h
ossl_kdf.o: $(hdrdir)/ruby.h
@@ -1687,7 +1758,6 @@ 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
@@ -1696,6 +1766,7 @@ 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/abi.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
@@ -1765,6 +1836,15 @@ ossl_kdf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_kdf.o: $(hdrdir)/ruby/internal/ctype.h
ossl_kdf.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_kdf.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_kdf.o: $(hdrdir)/ruby/internal/error.h
ossl_kdf.o: $(hdrdir)/ruby/internal/eval.h
ossl_kdf.o: $(hdrdir)/ruby/internal/event.h
@@ -1864,7 +1944,6 @@ ossl_kdf.o: ossl_rand.h
ossl_kdf.o: ossl_ssl.h
ossl_kdf.o: ossl_ts.h
ossl_kdf.o: ossl_x509.h
-ossl_kdf.o: ruby_missing.h
ossl_ns_spki.o: $(RUBY_EXTCONF_H)
ossl_ns_spki.o: $(arch_hdrdir)/ruby/config.h
ossl_ns_spki.o: $(hdrdir)/ruby.h
@@ -1873,7 +1952,6 @@ 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
@@ -1882,6 +1960,7 @@ 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/abi.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
@@ -1951,6 +2030,15 @@ ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/ctype.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/error.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/eval.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/event.h
@@ -2050,7 +2138,6 @@ ossl_ns_spki.o: ossl_rand.h
ossl_ns_spki.o: ossl_ssl.h
ossl_ns_spki.o: ossl_ts.h
ossl_ns_spki.o: ossl_x509.h
-ossl_ns_spki.o: ruby_missing.h
ossl_ocsp.o: $(RUBY_EXTCONF_H)
ossl_ocsp.o: $(arch_hdrdir)/ruby/config.h
ossl_ocsp.o: $(hdrdir)/ruby.h
@@ -2059,7 +2146,6 @@ 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
@@ -2068,6 +2154,7 @@ 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/abi.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
@@ -2137,6 +2224,15 @@ ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/ctype.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/error.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/eval.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/event.h
@@ -2236,7 +2332,6 @@ ossl_ocsp.o: ossl_rand.h
ossl_ocsp.o: ossl_ssl.h
ossl_ocsp.o: ossl_ts.h
ossl_ocsp.o: ossl_x509.h
-ossl_ocsp.o: ruby_missing.h
ossl_pkcs12.o: $(RUBY_EXTCONF_H)
ossl_pkcs12.o: $(arch_hdrdir)/ruby/config.h
ossl_pkcs12.o: $(hdrdir)/ruby.h
@@ -2245,7 +2340,6 @@ 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
@@ -2254,6 +2348,7 @@ 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/abi.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
@@ -2323,6 +2418,15 @@ ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/error.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/event.h
@@ -2422,7 +2526,6 @@ ossl_pkcs12.o: ossl_rand.h
ossl_pkcs12.o: ossl_ssl.h
ossl_pkcs12.o: ossl_ts.h
ossl_pkcs12.o: ossl_x509.h
-ossl_pkcs12.o: ruby_missing.h
ossl_pkcs7.o: $(RUBY_EXTCONF_H)
ossl_pkcs7.o: $(arch_hdrdir)/ruby/config.h
ossl_pkcs7.o: $(hdrdir)/ruby.h
@@ -2431,7 +2534,6 @@ 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
@@ -2440,6 +2542,7 @@ 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/abi.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
@@ -2509,6 +2612,15 @@ ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/error.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/event.h
@@ -2608,7 +2720,6 @@ ossl_pkcs7.o: ossl_rand.h
ossl_pkcs7.o: ossl_ssl.h
ossl_pkcs7.o: ossl_ts.h
ossl_pkcs7.o: ossl_x509.h
-ossl_pkcs7.o: ruby_missing.h
ossl_pkey.o: $(RUBY_EXTCONF_H)
ossl_pkey.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey.o: $(hdrdir)/ruby.h
@@ -2617,7 +2728,6 @@ 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
@@ -2626,6 +2736,7 @@ 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/abi.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
@@ -2695,6 +2806,15 @@ ossl_pkey.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkey.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkey.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkey.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkey.o: $(hdrdir)/ruby/internal/error.h
ossl_pkey.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkey.o: $(hdrdir)/ruby/internal/event.h
@@ -2794,7 +2914,6 @@ ossl_pkey.o: ossl_rand.h
ossl_pkey.o: ossl_ssl.h
ossl_pkey.o: ossl_ts.h
ossl_pkey.o: ossl_x509.h
-ossl_pkey.o: ruby_missing.h
ossl_pkey_dh.o: $(RUBY_EXTCONF_H)
ossl_pkey_dh.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_dh.o: $(hdrdir)/ruby.h
@@ -2803,7 +2922,6 @@ 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
@@ -2812,6 +2930,7 @@ 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/abi.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
@@ -2881,6 +3000,15 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/error.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/event.h
@@ -2980,7 +3108,6 @@ ossl_pkey_dh.o: ossl_rand.h
ossl_pkey_dh.o: ossl_ssl.h
ossl_pkey_dh.o: ossl_ts.h
ossl_pkey_dh.o: ossl_x509.h
-ossl_pkey_dh.o: ruby_missing.h
ossl_pkey_dsa.o: $(RUBY_EXTCONF_H)
ossl_pkey_dsa.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_dsa.o: $(hdrdir)/ruby.h
@@ -2989,7 +3116,6 @@ 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
@@ -2998,6 +3124,7 @@ 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/abi.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
@@ -3067,6 +3194,15 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/error.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/event.h
@@ -3166,7 +3302,6 @@ ossl_pkey_dsa.o: ossl_rand.h
ossl_pkey_dsa.o: ossl_ssl.h
ossl_pkey_dsa.o: ossl_ts.h
ossl_pkey_dsa.o: ossl_x509.h
-ossl_pkey_dsa.o: ruby_missing.h
ossl_pkey_ec.o: $(RUBY_EXTCONF_H)
ossl_pkey_ec.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_ec.o: $(hdrdir)/ruby.h
@@ -3175,7 +3310,6 @@ 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
@@ -3184,6 +3318,7 @@ 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/abi.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
@@ -3253,6 +3388,15 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/error.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/event.h
@@ -3352,7 +3496,6 @@ ossl_pkey_ec.o: ossl_rand.h
ossl_pkey_ec.o: ossl_ssl.h
ossl_pkey_ec.o: ossl_ts.h
ossl_pkey_ec.o: ossl_x509.h
-ossl_pkey_ec.o: ruby_missing.h
ossl_pkey_rsa.o: $(RUBY_EXTCONF_H)
ossl_pkey_rsa.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_rsa.o: $(hdrdir)/ruby.h
@@ -3361,7 +3504,6 @@ 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
@@ -3370,6 +3512,7 @@ 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/abi.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
@@ -3439,6 +3582,15 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/ctype.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/error.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/eval.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/event.h
@@ -3538,7 +3690,6 @@ ossl_pkey_rsa.o: ossl_rand.h
ossl_pkey_rsa.o: ossl_ssl.h
ossl_pkey_rsa.o: ossl_ts.h
ossl_pkey_rsa.o: ossl_x509.h
-ossl_pkey_rsa.o: ruby_missing.h
ossl_rand.o: $(RUBY_EXTCONF_H)
ossl_rand.o: $(arch_hdrdir)/ruby/config.h
ossl_rand.o: $(hdrdir)/ruby.h
@@ -3547,7 +3698,6 @@ 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
@@ -3556,6 +3706,7 @@ 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/abi.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
@@ -3625,6 +3776,15 @@ ossl_rand.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_rand.o: $(hdrdir)/ruby/internal/ctype.h
ossl_rand.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_rand.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_rand.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_rand.o: $(hdrdir)/ruby/internal/error.h
ossl_rand.o: $(hdrdir)/ruby/internal/eval.h
ossl_rand.o: $(hdrdir)/ruby/internal/event.h
@@ -3724,7 +3884,6 @@ ossl_rand.o: ossl_rand.h
ossl_rand.o: ossl_ssl.h
ossl_rand.o: ossl_ts.h
ossl_rand.o: ossl_x509.h
-ossl_rand.o: ruby_missing.h
ossl_ssl.o: $(RUBY_EXTCONF_H)
ossl_ssl.o: $(arch_hdrdir)/ruby/config.h
ossl_ssl.o: $(hdrdir)/ruby.h
@@ -3733,7 +3892,6 @@ 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
@@ -3742,6 +3900,7 @@ 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/abi.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
@@ -3811,6 +3970,15 @@ ossl_ssl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_ssl.o: $(hdrdir)/ruby/internal/ctype.h
ossl_ssl.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_ssl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_ssl.o: $(hdrdir)/ruby/internal/error.h
ossl_ssl.o: $(hdrdir)/ruby/internal/eval.h
ossl_ssl.o: $(hdrdir)/ruby/internal/event.h
@@ -3910,7 +4078,6 @@ ossl_ssl.o: ossl_ssl.c
ossl_ssl.o: ossl_ssl.h
ossl_ssl.o: ossl_ts.h
ossl_ssl.o: ossl_x509.h
-ossl_ssl.o: ruby_missing.h
ossl_ssl_session.o: $(RUBY_EXTCONF_H)
ossl_ssl_session.o: $(arch_hdrdir)/ruby/config.h
ossl_ssl_session.o: $(hdrdir)/ruby.h
@@ -3919,7 +4086,6 @@ 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
@@ -3928,6 +4094,7 @@ 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/abi.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
@@ -3997,6 +4164,15 @@ ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/ctype.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/error.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/eval.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/event.h
@@ -4096,7 +4272,6 @@ ossl_ssl_session.o: ossl_ssl.h
ossl_ssl_session.o: ossl_ssl_session.c
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
@@ -4105,7 +4280,6 @@ 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
@@ -4114,6 +4288,7 @@ 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/abi.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
@@ -4183,6 +4358,15 @@ ossl_ts.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_ts.o: $(hdrdir)/ruby/internal/ctype.h
ossl_ts.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_ts.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_ts.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_ts.o: $(hdrdir)/ruby/internal/error.h
ossl_ts.o: $(hdrdir)/ruby/internal/eval.h
ossl_ts.o: $(hdrdir)/ruby/internal/event.h
@@ -4282,7 +4466,6 @@ 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
@@ -4291,7 +4474,6 @@ 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
@@ -4300,6 +4482,7 @@ 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/abi.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
@@ -4369,6 +4552,15 @@ ossl_x509.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509.o: $(hdrdir)/ruby/internal/error.h
ossl_x509.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509.o: $(hdrdir)/ruby/internal/event.h
@@ -4468,7 +4660,6 @@ ossl_x509.o: ossl_ssl.h
ossl_x509.o: ossl_ts.h
ossl_x509.o: ossl_x509.c
ossl_x509.o: ossl_x509.h
-ossl_x509.o: ruby_missing.h
ossl_x509attr.o: $(RUBY_EXTCONF_H)
ossl_x509attr.o: $(arch_hdrdir)/ruby/config.h
ossl_x509attr.o: $(hdrdir)/ruby.h
@@ -4477,7 +4668,6 @@ 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
@@ -4486,6 +4676,7 @@ 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/abi.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
@@ -4555,6 +4746,15 @@ ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/error.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/event.h
@@ -4654,7 +4854,6 @@ ossl_x509attr.o: ossl_ssl.h
ossl_x509attr.o: ossl_ts.h
ossl_x509attr.o: ossl_x509.h
ossl_x509attr.o: ossl_x509attr.c
-ossl_x509attr.o: ruby_missing.h
ossl_x509cert.o: $(RUBY_EXTCONF_H)
ossl_x509cert.o: $(arch_hdrdir)/ruby/config.h
ossl_x509cert.o: $(hdrdir)/ruby.h
@@ -4663,7 +4862,6 @@ 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
@@ -4672,6 +4870,7 @@ 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/abi.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
@@ -4741,6 +4940,15 @@ ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/error.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/event.h
@@ -4840,7 +5048,6 @@ ossl_x509cert.o: ossl_ssl.h
ossl_x509cert.o: ossl_ts.h
ossl_x509cert.o: ossl_x509.h
ossl_x509cert.o: ossl_x509cert.c
-ossl_x509cert.o: ruby_missing.h
ossl_x509crl.o: $(RUBY_EXTCONF_H)
ossl_x509crl.o: $(arch_hdrdir)/ruby/config.h
ossl_x509crl.o: $(hdrdir)/ruby.h
@@ -4849,7 +5056,6 @@ 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
@@ -4858,6 +5064,7 @@ 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/abi.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
@@ -4927,6 +5134,15 @@ ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/error.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/event.h
@@ -5026,7 +5242,6 @@ ossl_x509crl.o: ossl_ssl.h
ossl_x509crl.o: ossl_ts.h
ossl_x509crl.o: ossl_x509.h
ossl_x509crl.o: ossl_x509crl.c
-ossl_x509crl.o: ruby_missing.h
ossl_x509ext.o: $(RUBY_EXTCONF_H)
ossl_x509ext.o: $(arch_hdrdir)/ruby/config.h
ossl_x509ext.o: $(hdrdir)/ruby.h
@@ -5035,7 +5250,6 @@ 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
@@ -5044,6 +5258,7 @@ 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/abi.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
@@ -5113,6 +5328,15 @@ ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/error.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/event.h
@@ -5212,7 +5436,6 @@ ossl_x509ext.o: ossl_ssl.h
ossl_x509ext.o: ossl_ts.h
ossl_x509ext.o: ossl_x509.h
ossl_x509ext.o: ossl_x509ext.c
-ossl_x509ext.o: ruby_missing.h
ossl_x509name.o: $(RUBY_EXTCONF_H)
ossl_x509name.o: $(arch_hdrdir)/ruby/config.h
ossl_x509name.o: $(hdrdir)/ruby.h
@@ -5221,7 +5444,6 @@ 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
@@ -5230,6 +5452,7 @@ 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/abi.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
@@ -5299,6 +5522,15 @@ ossl_x509name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509name.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509name.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509name.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509name.o: $(hdrdir)/ruby/internal/error.h
ossl_x509name.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509name.o: $(hdrdir)/ruby/internal/event.h
@@ -5398,7 +5630,6 @@ ossl_x509name.o: ossl_ssl.h
ossl_x509name.o: ossl_ts.h
ossl_x509name.o: ossl_x509.h
ossl_x509name.o: ossl_x509name.c
-ossl_x509name.o: ruby_missing.h
ossl_x509req.o: $(RUBY_EXTCONF_H)
ossl_x509req.o: $(arch_hdrdir)/ruby/config.h
ossl_x509req.o: $(hdrdir)/ruby.h
@@ -5407,7 +5638,6 @@ 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
@@ -5416,6 +5646,7 @@ 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/abi.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
@@ -5485,6 +5716,15 @@ ossl_x509req.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509req.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509req.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509req.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509req.o: $(hdrdir)/ruby/internal/error.h
ossl_x509req.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509req.o: $(hdrdir)/ruby/internal/event.h
@@ -5584,7 +5824,6 @@ ossl_x509req.o: ossl_ssl.h
ossl_x509req.o: ossl_ts.h
ossl_x509req.o: ossl_x509.h
ossl_x509req.o: ossl_x509req.c
-ossl_x509req.o: ruby_missing.h
ossl_x509revoked.o: $(RUBY_EXTCONF_H)
ossl_x509revoked.o: $(arch_hdrdir)/ruby/config.h
ossl_x509revoked.o: $(hdrdir)/ruby.h
@@ -5593,7 +5832,6 @@ 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
@@ -5602,6 +5840,7 @@ 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/abi.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
@@ -5671,6 +5910,15 @@ ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/error.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/event.h
@@ -5770,7 +6018,6 @@ ossl_x509revoked.o: ossl_ssl.h
ossl_x509revoked.o: ossl_ts.h
ossl_x509revoked.o: ossl_x509.h
ossl_x509revoked.o: ossl_x509revoked.c
-ossl_x509revoked.o: ruby_missing.h
ossl_x509store.o: $(RUBY_EXTCONF_H)
ossl_x509store.o: $(arch_hdrdir)/ruby/config.h
ossl_x509store.o: $(hdrdir)/ruby.h
@@ -5779,7 +6026,6 @@ 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
@@ -5788,6 +6034,7 @@ 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/abi.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
@@ -5857,6 +6104,15 @@ ossl_x509store.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ossl_x509store.o: $(hdrdir)/ruby/internal/ctype.h
ossl_x509store.o: $(hdrdir)/ruby/internal/dllexport.h
ossl_x509store.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/re.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/string.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ossl_x509store.o: $(hdrdir)/ruby/internal/error.h
ossl_x509store.o: $(hdrdir)/ruby/internal/eval.h
ossl_x509store.o: $(hdrdir)/ruby/internal/event.h
@@ -5956,5 +6212,4 @@ ossl_x509store.o: ossl_ssl.h
ossl_x509store.o: ossl_ts.h
ossl_x509store.o: ossl_x509.h
ossl_x509store.o: ossl_x509store.c
-ossl_x509store.o: ruby_missing.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index aa4eae824c..bc3e4d3a21 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -13,7 +13,7 @@
require "mkmf"
-dir_config("openssl")
+dir_config_given = dir_config("openssl").any?
dir_config("kerberos")
Logging::message "=== OpenSSL for Ruby configurator ===\n"
@@ -25,8 +25,9 @@ Logging::message "=== OpenSSL for Ruby configurator ===\n"
if with_config("debug") or enable_config("debug")
$defs.push("-DOSSL_DEBUG")
end
+$defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED")
-have_func("rb_io_maybe_wait") # Ruby 3.1
+have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") # Ruby 3.1
Logging::message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
@@ -92,7 +93,7 @@ def find_openssl_library
end
Logging::message "=== Checking for required stuff... ===\n"
-pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
+pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h")
if !pkg_config_found && !find_openssl_library
Logging::message "=== Checking for required stuff failed. ===\n"
@@ -120,8 +121,13 @@ if is_libressl && ($mswin || $mingw)
end
Logging::message "=== Checking for OpenSSL features... ===\n"
+evp_h = "openssl/evp.h".freeze
+x509_h = "openssl/x509.h".freeze
+ts_h = "openssl/ts.h".freeze
+ssl_h = "openssl/ssl.h".freeze
+
# compile options
-have_func("RAND_egd")
+have_func("RAND_egd()", "openssl/rand.h")
engines = %w{dynamic 4758cca aep atalla chil
cswift nuron sureware ubsec padlock capi gmp gost cryptodev}
engines.each { |name|
@@ -132,43 +138,56 @@ engines.each { |name|
if !have_struct_member("SSL", "ctx", "openssl/ssl.h") || is_libressl
$defs.push("-DHAVE_OPAQUE_OPENSSL")
end
-have_func("EVP_MD_CTX_new")
-have_func("EVP_MD_CTX_free")
-have_func("EVP_MD_CTX_pkey_ctx")
-have_func("X509_STORE_get_ex_data")
-have_func("X509_STORE_set_ex_data")
-have_func("X509_STORE_get_ex_new_index")
-have_func("X509_CRL_get0_signature")
-have_func("X509_REQ_get0_signature")
-have_func("X509_REVOKED_get0_serialNumber")
-have_func("X509_REVOKED_get0_revocationDate")
-have_func("X509_get0_tbs_sigalg")
-have_func("X509_STORE_CTX_get0_untrusted")
-have_func("X509_STORE_CTX_get0_cert")
-have_func("X509_STORE_CTX_get0_chain")
-have_func("OCSP_SINGLERESP_get0_id")
-have_func("SSL_CTX_get_ciphers")
-have_func("X509_up_ref")
-have_func("X509_CRL_up_ref")
-have_func("X509_STORE_up_ref")
-have_func("SSL_SESSION_up_ref")
-have_func("EVP_PKEY_up_ref")
-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")
+have_func("EVP_MD_CTX_new()", evp_h)
+have_func("EVP_MD_CTX_free(NULL)", evp_h)
+have_func("EVP_MD_CTX_pkey_ctx(NULL)", evp_h)
+have_func("X509_STORE_get_ex_data(NULL, 0)", x509_h)
+have_func("X509_STORE_set_ex_data(NULL, 0, NULL)", x509_h)
+have_func("X509_STORE_get_ex_new_index(0, NULL, NULL, NULL, NULL)", x509_h)
+have_func("X509_CRL_get0_signature(NULL, NULL, NULL)", x509_h)
+have_func("X509_REQ_get0_signature(NULL, NULL, NULL)", x509_h)
+have_func("X509_REVOKED_get0_serialNumber(NULL)", x509_h)
+have_func("X509_REVOKED_get0_revocationDate(NULL)", x509_h)
+have_func("X509_get0_tbs_sigalg(NULL)", x509_h)
+have_func("X509_STORE_CTX_get0_untrusted(NULL)", x509_h)
+have_func("X509_STORE_CTX_get0_cert(NULL)", x509_h)
+have_func("X509_STORE_CTX_get0_chain(NULL)", x509_h)
+have_func("OCSP_SINGLERESP_get0_id(NULL)", "openssl/ocsp.h")
+have_func("SSL_CTX_get_ciphers(NULL)", ssl_h)
+have_func("X509_up_ref(NULL)", x509_h)
+have_func("X509_CRL_up_ref(NULL)", x509_h)
+have_func("X509_STORE_up_ref(NULL)", x509_h)
+have_func("SSL_SESSION_up_ref(NULL)", ssl_h)
+have_func("EVP_PKEY_up_ref(NULL)", evp_h)
+have_func("SSL_CTX_set_min_proto_version(NULL, 0)", ssl_h)
+have_func("SSL_CTX_get_security_level(NULL)", ssl_h)
+have_func("X509_get0_notBefore(NULL)", x509_h)
+have_func("SSL_SESSION_get_protocol_version(NULL)", ssl_h)
+have_func("TS_STATUS_INFO_get0_status(NULL)", ts_h)
+have_func("TS_STATUS_INFO_get0_text(NULL)", ts_h)
+have_func("TS_STATUS_INFO_get0_failure_info(NULL)", ts_h)
+have_func("TS_VERIFY_CTS_set_certs(NULL, NULL)", ts_h)
+have_func("TS_VERIFY_CTX_set_store(NULL, NULL)", ts_h)
+have_func("TS_VERIFY_CTX_add_flags(NULL, 0)", ts_h)
+have_func("TS_RESP_CTX_set_time_cb(NULL, NULL, NULL)", ts_h)
+have_func("EVP_PBE_scrypt(\"\", 0, (unsigned char *)\"\", 0, 0, 0, 0, 0, NULL, 0)", evp_h)
+have_func("SSL_CTX_set_post_handshake_auth(NULL, 0)", ssl_h)
# added in 1.1.1
-have_func("EVP_PKEY_check")
+have_func("EVP_PKEY_check(NULL)", evp_h)
+have_func("EVP_PKEY_new_raw_private_key(0, NULL, (unsigned char *)\"\", 0)", evp_h)
+have_func("SSL_CTX_set_ciphersuites(NULL, \"\")", ssl_h)
+
+# added in 3.0.0
+have_func("SSL_set0_tmp_dh_pkey(NULL, NULL)", ssl_h)
+have_func("ERR_get_error_all(NULL, NULL, NULL, NULL, NULL)", "openssl/err.h")
+have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", ts_h)
+have_func("SSL_CTX_load_verify_file(NULL, \"\")", ssl_h)
+have_func("BN_check_prime(NULL, NULL, NULL)", "openssl/bn.h")
+have_func("EVP_MD_CTX_get0_md(NULL)", evp_h)
+have_func("EVP_MD_CTX_get_pkey_ctx(NULL)", evp_h)
+have_func("EVP_PKEY_eq(NULL, NULL)", evp_h)
+have_func("EVP_PKEY_dup(NULL)", evp_h)
Logging::message "=== Checking done. ===\n"
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 116179d21f..d47e1082ef 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -99,16 +99,6 @@ module OpenSSL::Buffering
end
end
- if "".respond_to?(:unpack1)
- def unpack_byte(str)
- str.unpack1("C")
- end
- else
- def unpack_byte(str)
- str.unpack("C").first
- end
- end
-
public
# call-seq:
@@ -117,7 +107,7 @@ module OpenSSL::Buffering
# Get the next 8bit byte from `ssl`. Returns `nil` on EOF
def getbyte
byte = read(1)
- byte && unpack_byte(byte)
+ byte && byte.unpack1("C")
end
##
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
index f6bf5892b0..0414658a10 100644
--- a/ext/openssl/lib/openssl/pkey.rb
+++ b/ext/openssl/lib/openssl/pkey.rb
@@ -47,9 +47,19 @@ module OpenSSL::PKey
# * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by
# DH#public_key as that contains the DH parameters only.
def compute_key(pub_bn)
- peer = dup
- peer.set_key(pub_bn, nil)
- derive(peer)
+ # FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very
+ # inefficient
+ obj = OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.ObjectId("dhKeyAgreement"),
+ OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.Integer(p),
+ OpenSSL::ASN1.Integer(g),
+ ]),
+ ]),
+ OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der),
+ ])
+ derive(OpenSSL::PKey.read(obj.to_der))
end
# :call-seq:
@@ -61,14 +71,29 @@ module OpenSSL::PKey
# called first in order to generate the per-session keys before performing
# the actual key exchange.
#
+ # <b>Deprecated in version 3.0</b>. This method is incompatible with
+ # OpenSSL 3.0.0 or later.
+ #
# See also OpenSSL::PKey.generate_key.
#
# Example:
- # dh = OpenSSL::PKey::DH.new(2048)
- # public_key = dh.public_key #contains no private/public key yet
- # public_key.generate_key!
- # puts public_key.private? # => true
+ # # DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later
+ # dh0 = OpenSSL::PKey::DH.new(2048)
+ # dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name)
+ # dh.generate_key!
+ # puts dh.private? # => true
+ # puts dh0.pub_key == dh.pub_key #=> false
+ #
+ # # With OpenSSL::PKey.generate_key
+ # dh0 = OpenSSL::PKey::DH.new(2048)
+ # dh = OpenSSL::PKey.generate_key(dh0)
+ # puts dh0.pub_key == dh.pub_key #=> false
def generate_key!
+ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000
+ raise DHError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \
+ "use OpenSSL::PKey.generate_key instead"
+ end
+
unless priv_key
tmp = OpenSSL::PKey.generate_key(self)
set_key(tmp.pub_key, tmp.priv_key)
@@ -142,8 +167,16 @@ module OpenSSL::PKey
# +size+::
# The desired key size in bits.
def generate(size, &blk)
+ # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224),
+ # (2048,256), and (3072,256).
+ #
+ # q size is derived here with compatibility with
+ # DSA_generator_parameters_ex() which previous versions of ruby/openssl
+ # used to call.
+ qsize = size >= 2048 ? 256 : 160
dsaparams = OpenSSL::PKey.generate_parameters("DSA", {
"dsa_paramgen_bits" => size,
+ "dsa_paramgen_q_bits" => qsize,
}, &blk)
OpenSSL::PKey.generate_key(dsaparams)
end
@@ -249,9 +282,14 @@ module OpenSSL::PKey
# This method is provided for backwards compatibility, and calls #derive
# internally.
def dh_compute_key(pubkey)
- peer = OpenSSL::PKey::EC.new(group)
- peer.public_key = pubkey
- derive(peer)
+ obj = OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.Sequence([
+ OpenSSL::ASN1.ObjectId("id-ecPublicKey"),
+ group.to_der,
+ ]),
+ OpenSSL::ASN1.BitString(pubkey.to_octet_string(:uncompressed)),
+ ])
+ derive(OpenSSL::PKey.read(obj.to_der))
end
end
@@ -325,7 +363,8 @@ module OpenSSL::PKey
# rsa.private_encrypt(string, padding) -> String
#
# Encrypt +string+ with the private key. +padding+ defaults to
- # PKCS1_PADDING. The encrypted string output can be decrypted using
+ # PKCS1_PADDING, which is known to be insecure but is kept for backwards
+ # compatibility. The encrypted string output can be decrypted using
# #public_decrypt.
#
# <b>Deprecated in version 3.0</b>.
@@ -348,7 +387,8 @@ module OpenSSL::PKey
# rsa.public_decrypt(string, padding) -> String
#
# Decrypt +string+, which has been encrypted with the private key, with the
- # public key. +padding+ defaults to PKCS1_PADDING.
+ # public key. +padding+ defaults to PKCS1_PADDING which is known to be
+ # insecure but is kept for backwards compatibility.
#
# <b>Deprecated in version 3.0</b>.
# Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and
@@ -369,7 +409,8 @@ module OpenSSL::PKey
# rsa.public_encrypt(string, padding) -> String
#
# Encrypt +string+ with the public key. +padding+ defaults to
- # PKCS1_PADDING. The encrypted string output can be decrypted using
+ # PKCS1_PADDING, which is known to be insecure but is kept for backwards
+ # compatibility. The encrypted string output can be decrypted using
# #private_decrypt.
#
# <b>Deprecated in version 3.0</b>.
@@ -390,7 +431,8 @@ module OpenSSL::PKey
# rsa.private_decrypt(string, padding) -> String
#
# Decrypt +string+, which has been encrypted with the public key, with the
- # private key. +padding+ defaults to PKCS1_PADDING.
+ # private key. +padding+ defaults to PKCS1_PADDING, which is known to be
+ # insecure but is kept for backwards compatibility.
#
# <b>Deprecated in version 3.0</b>.
# Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead.
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 0930a53017..ea8bb2a18e 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -11,6 +11,9 @@
=end
require "openssl/buffering"
+
+if defined?(OpenSSL::SSL)
+
require "io/nonblock"
require "ipaddr"
require "socket"
@@ -91,15 +94,17 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
DEFAULT_CERT_STORE.set_default_paths
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
- # A callback invoked when DH parameters are required.
+ # A callback invoked when DH parameters are required for ephemeral DH key
+ # exchange.
#
- # The callback is invoked with the Session for the key exchange, an
+ # The callback is invoked with the SSLSocket, a
# flag indicating the use of an export cipher and the keylength
# required.
#
# The callback must return an OpenSSL::PKey::DH instance of the correct
# key length.
-
+ #
+ # <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
attr_accessor :tmp_dh_callback
# A callback invoked at connect time to distinguish between multiple
@@ -432,10 +437,6 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
@context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK
end
- def tmp_ecdh_callback
- @context.tmp_ecdh_callback
- end
-
def session_new_cb
@context.session_new_cb
end
@@ -542,3 +543,5 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
end
end
end
+
+end
diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb
index 9c7515ba0f..4163f55064 100644
--- a/ext/openssl/lib/openssl/version.rb
+++ b/ext/openssl/lib/openssl/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module OpenSSL
- VERSION = "2.2.0"
+ VERSION = "3.1.0"
end
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index 448941f75e..f973f4f4dc 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -279,11 +279,29 @@ module OpenSSL
end
class << self
+ # Parses the UTF-8 string representation of a distinguished name,
+ # according to RFC 2253.
+ #
+ # See also #to_utf8 for the opposite operation.
def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
self.new(ary, template)
end
+ # Parses the string representation of a distinguished name. Two
+ # different forms are supported:
+ #
+ # - \OpenSSL format (<tt>X509_NAME_oneline()</tt>) used by
+ # <tt>#to_s</tt>. For example: <tt>/DC=com/DC=example/CN=nobody</tt>
+ # - \OpenSSL format (<tt>X509_NAME_print()</tt>)
+ # used by <tt>#to_s(OpenSSL::X509::Name::COMPAT)</tt>. For example:
+ # <tt>DC=com, DC=example, CN=nobody</tt>
+ #
+ # Neither of them is standardized and has quirks and inconsistencies
+ # in handling of escaped characters or multi-valued RDNs.
+ #
+ # Use of this method is discouraged in new applications. See
+ # Name.parse_rfc2253 and #to_utf8 for the alternative.
def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
if str.start_with?("/")
# /A=B/C=D format
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index f178e7025d..8d83b69193 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.2.0"
+ spec.version = "3.1.0"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.}
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
spec.extra_rdoc_files = Dir["*.md"]
spec.rdoc_options = ["--main", "README.md"]
- spec.required_ruby_version = ">= 2.3.0"
+ spec.required_ruby_version = ">= 2.6.0"
spec.metadata["msys2_mingw_dependencies"] = "openssl"
end
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
index 8b93cba6d4..4415703db4 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -10,9 +10,6 @@
#include RUBY_EXTCONF_H
#include <string.h> /* memcpy() */
-#if !defined(OPENSSL_NO_ENGINE)
-# include <openssl/engine.h>
-#endif
#include <openssl/x509_vfy.h>
#include "openssl_missing.h"
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 4d9b880138..8629bfe505 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -21,10 +21,6 @@
# define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif
-#if !defined(HAVE_EVP_MD_CTX_PKEY_CTX)
-# define EVP_MD_CTX_pkey_ctx(x) (x)->pctx
-#endif
-
#if !defined(HAVE_X509_STORE_GET_EX_DATA)
# define X509_STORE_get_ex_data(x, idx) \
CRYPTO_get_ex_data(&(x)->ex_data, (idx))
@@ -214,4 +210,29 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
} while (0)
#endif
+/* added in 3.0.0 */
+#if !defined(HAVE_TS_VERIFY_CTX_SET_CERTS)
+# define TS_VERIFY_CTX_set_certs(ctx, crts) TS_VERIFY_CTS_set_certs(ctx, crts)
+#endif
+
+#ifndef HAVE_EVP_MD_CTX_GET0_MD
+# define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx)
+#endif
+
+/*
+ * OpenSSL 1.1.0 added EVP_MD_CTX_pkey_ctx(), and then it was renamed to
+ * EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0.
+ */
+#ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX
+# ifdef HAVE_EVP_MD_CTX_PKEY_CTX
+# define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x)
+# else
+# define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx
+# endif
+#endif
+
+#ifndef HAVE_EVP_PKEY_EQ
+# define EVP_PKEY_eq(a, b) EVP_PKEY_cmp(a, b)
+#endif
+
#endif /* _OSSL_OPENSSL_MISSING_H_ */
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index cf070ef859..6c532aca94 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -21,7 +21,7 @@
* Data Conversion
*/
#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
-STACK_OF(type) * \
+VALUE \
ossl_##name##_ary2sk0(VALUE ary) \
{ \
STACK_OF(type) *sk; \
@@ -43,7 +43,7 @@ ossl_##name##_ary2sk0(VALUE ary) \
x = dup(val); /* NEED TO DUP */ \
sk_##type##_push(sk, x); \
} \
- return sk; \
+ return (VALUE)sk; \
} \
\
STACK_OF(type) * \
@@ -268,15 +268,11 @@ ossl_to_der_if_possible(VALUE obj)
/*
* Errors
*/
-static VALUE
-ossl_make_error(VALUE exc, const char *fmt, va_list args)
+VALUE
+ossl_make_error(VALUE exc, VALUE str)
{
- VALUE str = Qnil;
unsigned long e;
- if (fmt) {
- str = rb_vsprintf(fmt, args);
- }
e = ERR_peek_last_error();
if (e) {
const char *msg = ERR_reason_error_string(e);
@@ -300,37 +296,48 @@ ossl_raise(VALUE exc, const char *fmt, ...)
{
va_list args;
VALUE err;
- va_start(args, fmt);
- err = ossl_make_error(exc, fmt, args);
- va_end(args);
- rb_exc_raise(err);
+
+ if (fmt) {
+ va_start(args, fmt);
+ err = rb_vsprintf(fmt, args);
+ va_end(args);
+ }
+ else {
+ err = Qnil;
+ }
+
+ rb_exc_raise(ossl_make_error(exc, err));
}
void
ossl_clear_error(void)
{
if (dOSSL == Qtrue) {
- unsigned long e;
- const char *file, *data, *errstr;
- int line, flags;
-
- while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
- errstr = ERR_error_string(e, NULL);
- if (!errstr)
- errstr = "(null)";
-
- if (flags & ERR_TXT_STRING) {
- if (!data)
- data = "(null)";
- rb_warn("error on stack: %s (%s)", errstr, data);
- }
- else {
- rb_warn("error on stack: %s", errstr);
- }
- }
+ unsigned long e;
+ const char *file, *data, *func, *lib, *reason;
+ char append[256] = "";
+ int line, flags;
+
+#ifdef HAVE_ERR_GET_ERROR_ALL
+ while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) {
+#else
+ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
+ func = ERR_func_error_string(e);
+#endif
+ lib = ERR_lib_error_string(e);
+ reason = ERR_reason_error_string(e);
+
+ if (flags & ERR_TXT_STRING) {
+ if (!data)
+ data = "(null)";
+ snprintf(append, sizeof(append), " (%s)", data);
+ }
+ rb_warn("error on stack: error:%08lX:%s:%s:%s%s", e, lib ? lib : "",
+ func ? func : "", reason ? reason : "", append);
+ }
}
else {
- ERR_clear_error();
+ ERR_clear_error();
}
}
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 577eb6d6be..facb80aa73 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -18,6 +18,7 @@
#include <ruby/io.h>
#include <ruby/thread.h>
#include <openssl/opensslv.h>
+
#include <openssl/err.h>
#include <openssl/asn1.h>
#include <openssl/x509v3.h>
@@ -30,9 +31,6 @@
#include <openssl/ts.h>
#endif
#include <openssl/crypto.h>
-#if !defined(OPENSSL_NO_ENGINE)
-# include <openssl/engine.h>
-#endif
#if !defined(OPENSSL_NO_OCSP)
# include <openssl/ocsp.h>
#endif
@@ -42,6 +40,28 @@
#include <openssl/evp.h>
#include <openssl/dh.h>
+#ifndef LIBRESSL_VERSION_NUMBER
+# define OSSL_IS_LIBRESSL 0
+# define OSSL_OPENSSL_PREREQ(maj, min, pat) \
+ (OPENSSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12)))
+# define OSSL_LIBRESSL_PREREQ(maj, min, pat) 0
+#else
+# define OSSL_IS_LIBRESSL 1
+# define OSSL_OPENSSL_PREREQ(maj, min, pat) 0
+# define OSSL_LIBRESSL_PREREQ(maj, min, pat) \
+ (LIBRESSL_VERSION_NUMBER >= ((maj << 28) | (min << 20) | (pat << 12)))
+#endif
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_3_const const
+#else
+# define OSSL_3_const /* const */
+#endif
+
+#if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_USE_ENGINE
+#endif
+
/*
* Common Module
*/
@@ -120,7 +140,9 @@ int ossl_pem_passwd_cb(char *, int, int, void *);
/*
* ERRor messages
*/
-NORETURN(void ossl_raise(VALUE, const char *, ...));
+PRINTF_ARGS(NORETURN(void ossl_raise(VALUE, const char *, ...)), 2, 3);
+/* Make exception instance from str and OpenSSL error reason string. */
+VALUE ossl_make_error(VALUE exc, VALUE str);
/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */
void ossl_clear_error(void);
@@ -153,7 +175,6 @@ void ossl_debug(const char *, ...);
* Include all parts
*/
#include "openssl_missing.h"
-#include "ruby_missing.h"
#include "ossl_asn1.h"
#include "ossl_bio.h"
#include "ossl_bn.h"
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index b4b285323b..71c452c88a 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -69,6 +69,12 @@ asn1time_to_time(const ASN1_TIME *time)
return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
}
+static VALUE
+asn1time_to_time_i(VALUE arg)
+{
+ return asn1time_to_time((ASN1_TIME *)arg);
+}
+
void
ossl_time_split(VALUE time, time_t *sec, int *days)
{
@@ -136,6 +142,12 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
return ai;
}
+static VALUE
+asn1integer_to_num_i(VALUE arg)
+{
+ return asn1integer_to_num((ASN1_INTEGER *)arg);
+}
+
/********/
/*
* ASN1 module
@@ -325,7 +337,7 @@ decode_int(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
+ ret = rb_protect(asn1integer_to_num_i,
(VALUE)ai, &status);
ASN1_INTEGER_free(ai);
if(status) rb_jump_tag(status);
@@ -365,7 +377,7 @@ decode_enum(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
+ ret = rb_protect(asn1integer_to_num_i,
(VALUE)ai, &status);
ASN1_ENUMERATED_free(ai);
if(status) rb_jump_tag(status);
@@ -427,7 +439,7 @@ decode_time(unsigned char* der, long length)
p = der;
if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
- ret = rb_protect((VALUE (*)(VALUE))asn1time_to_time,
+ ret = rb_protect(asn1time_to_time_i,
(VALUE)time, &status);
ASN1_TIME_free(time);
if(status) rb_jump_tag(status);
@@ -497,7 +509,8 @@ ossl_asn1_get_asn1type(VALUE obj)
ASN1_TYPE *ret;
VALUE value, rflag;
void *ptr;
- void (*free_func)();
+ typedef void free_func_type(void *);
+ free_func_type *free_func;
int tag;
tag = ossl_asn1_default_tag(obj);
@@ -510,16 +523,16 @@ ossl_asn1_get_asn1type(VALUE obj)
case V_ASN1_INTEGER: /* FALLTHROUGH */
case V_ASN1_ENUMERATED:
ptr = obj_to_asn1int(value);
- free_func = ASN1_INTEGER_free;
+ free_func = (free_func_type *)ASN1_INTEGER_free;
break;
case V_ASN1_BIT_STRING:
rflag = rb_attr_get(obj, sivUNUSED_BITS);
ptr = obj_to_asn1bstr(value, NUM2INT(rflag));
- free_func = ASN1_BIT_STRING_free;
+ free_func = (free_func_type *)ASN1_BIT_STRING_free;
break;
case V_ASN1_NULL:
ptr = obj_to_asn1null(value);
- free_func = ASN1_NULL_free;
+ free_func = (free_func_type *)ASN1_NULL_free;
break;
case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
case V_ASN1_UTF8STRING: /* FALLTHROUGH */
@@ -534,24 +547,24 @@ ossl_asn1_get_asn1type(VALUE obj)
case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
case V_ASN1_BMPSTRING:
ptr = obj_to_asn1str(value);
- free_func = ASN1_STRING_free;
+ free_func = (free_func_type *)ASN1_STRING_free;
break;
case V_ASN1_OBJECT:
ptr = obj_to_asn1obj(value);
- free_func = ASN1_OBJECT_free;
+ free_func = (free_func_type *)ASN1_OBJECT_free;
break;
case V_ASN1_UTCTIME:
ptr = obj_to_asn1utime(value);
- free_func = ASN1_TIME_free;
+ free_func = (free_func_type *)ASN1_TIME_free;
break;
case V_ASN1_GENERALIZEDTIME:
ptr = obj_to_asn1gtime(value);
- free_func = ASN1_TIME_free;
+ free_func = (free_func_type *)ASN1_TIME_free;
break;
case V_ASN1_SET: /* FALLTHROUGH */
case V_ASN1_SEQUENCE:
ptr = obj_to_asn1derstr(obj);
- free_func = ASN1_STRING_free;
+ free_func = (free_func_type *)ASN1_STRING_free;
break;
default:
ossl_raise(eASN1Error, "unsupported ASN.1 type");
@@ -1510,7 +1523,7 @@ Init_ossl_asn1(void)
*
* An Array that stores the name of a given tag number. These names are
* the same as the name of the tag constant that is additionally defined,
- * e.g. +UNIVERSAL_TAG_NAME[2] = "INTEGER"+ and +OpenSSL::ASN1::INTEGER = 2+.
+ * e.g. <tt>UNIVERSAL_TAG_NAME[2] = "INTEGER"</tt> and <tt>OpenSSL::ASN1::INTEGER = 2</tt>.
*
* == Example usage
*
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index 8d0f63a986..bf2bac3679 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -577,22 +577,33 @@ BIGNUM_2c(gcd)
*/
BIGNUM_2c(mod_sqr)
+#define BIGNUM_2cr(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_##func(NULL, bn1, bn2, ossl_bn_ctx))) \
+ ossl_raise(eBNError, NULL); \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
/*
+ * Document-method: OpenSSL::BN#mod_sqrt
+ * call-seq:
+ * bn.mod_sqrt(bn2) => aBN
+ */
+BIGNUM_2cr(mod_sqrt)
+
+/*
+ * Document-method: OpenSSL::BN#mod_inverse
* call-seq:
* bn.mod_inverse(bn2) => aBN
*/
-static VALUE
-ossl_bn_mod_inverse(VALUE self, VALUE other)
-{
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result;
- VALUE obj;
- GetBN(self, bn1);
- obj = NewBN(rb_obj_class(self));
- if (!(result = BN_mod_inverse(NULL, bn1, bn2, ossl_bn_ctx)))
- ossl_raise(eBNError, "BN_mod_inverse");
- SetBN(obj, result);
- return obj;
-}
+BIGNUM_2cr(mod_inverse)
/*
* call-seq:
@@ -792,78 +803,64 @@ BIGNUM_SELF_SHIFT(lshift)
*/
BIGNUM_SELF_SHIFT(rshift)
-#define BIGNUM_RAND(func) \
- static VALUE \
- ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
- { \
- BIGNUM *result; \
- int bottom = 0, top = 0, b; \
- VALUE bits, fill, odd, obj; \
- \
- switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \
- case 3: \
- bottom = (odd == Qtrue) ? 1 : 0; \
- /* FALLTHROUGH */ \
- case 2: \
- top = NUM2INT(fill); \
- } \
- b = NUM2INT(bits); \
- obj = NewBN(klass); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, b, top, bottom) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
- }
-
-/*
- * Document-method: OpenSSL::BN.rand
- * BN.rand(bits [, fill [, odd]]) -> aBN
- */
-BIGNUM_RAND(rand)
-
-/*
- * Document-method: OpenSSL::BN.pseudo_rand
- * BN.pseudo_rand(bits [, fill [, odd]]) -> aBN
- */
-BIGNUM_RAND(pseudo_rand)
-
-#define BIGNUM_RAND_RANGE(func) \
- static VALUE \
- ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
- { \
- BIGNUM *bn = GetBNPtr(range), *result; \
- VALUE obj = NewBN(klass); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func##_range(result, bn) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
- }
-
/*
- * Document-method: OpenSSL::BN.rand_range
* call-seq:
- * BN.rand_range(range) -> aBN
+ * BN.rand(bits [, fill [, odd]]) -> aBN
*
+ * Generates a cryptographically strong pseudo-random number of +bits+.
+ *
+ * See also the man page BN_rand(3).
*/
-BIGNUM_RAND_RANGE(rand)
+static VALUE
+ossl_bn_s_rand(int argc, VALUE *argv, VALUE klass)
+{
+ BIGNUM *result;
+ int bottom = 0, top = 0, b;
+ VALUE bits, fill, odd, obj;
+
+ switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) {
+ case 3:
+ bottom = (odd == Qtrue) ? 1 : 0;
+ /* FALLTHROUGH */
+ case 2:
+ top = NUM2INT(fill);
+ }
+ b = NUM2INT(bits);
+ obj = NewBN(klass);
+ if (!(result = BN_new())) {
+ ossl_raise(eBNError, "BN_new");
+ }
+ if (BN_rand(result, b, top, bottom) <= 0) {
+ BN_free(result);
+ ossl_raise(eBNError, "BN_rand");
+ }
+ SetBN(obj, result);
+ return obj;
+}
/*
- * Document-method: OpenSSL::BN.pseudo_rand_range
* call-seq:
- * BN.pseudo_rand_range(range) -> aBN
+ * BN.rand_range(range) -> aBN
+ *
+ * Generates a cryptographically strong pseudo-random number in the range
+ * 0...+range+.
*
+ * See also the man page BN_rand_range(3).
*/
-BIGNUM_RAND_RANGE(pseudo_rand)
+static VALUE
+ossl_bn_s_rand_range(VALUE klass, VALUE range)
+{
+ BIGNUM *bn = GetBNPtr(range), *result;
+ VALUE obj = NewBN(klass);
+ if (!(result = BN_new()))
+ ossl_raise(eBNError, "BN_new");
+ if (BN_rand_range(result, bn) <= 0) {
+ BN_free(result);
+ ossl_raise(eBNError, "BN_rand_range");
+ }
+ SetBN(obj, result);
+ return obj;
+}
/*
* call-seq:
@@ -1118,34 +1115,29 @@ ossl_bn_hash(VALUE self)
* bn.prime? => true | false
* bn.prime?(checks) => true | false
*
- * Performs a Miller-Rabin probabilistic primality test with _checks_
- * iterations. If _checks_ is not specified, a number of iterations is used
- * that yields a false positive rate of at most 2^-80 for random input.
+ * Performs a Miller-Rabin probabilistic primality test for +bn+.
*
- * === Parameters
- * * _checks_ - integer
+ * <b>+checks+ parameter is deprecated in version 3.0.</b> It has no effect.
*/
static VALUE
ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
{
BIGNUM *bn;
- VALUE vchecks;
- int checks = BN_prime_checks;
+ int ret;
- if (rb_scan_args(argc, argv, "01", &vchecks) == 1) {
- checks = NUM2INT(vchecks);
- }
+ rb_check_arity(argc, 0, 1);
GetBN(self, bn);
- switch (BN_is_prime_ex(bn, checks, ossl_bn_ctx, NULL)) {
- case 1:
- return Qtrue;
- case 0:
- return Qfalse;
- default:
- ossl_raise(eBNError, NULL);
- }
- /* not reachable */
- return Qnil;
+
+#ifdef HAVE_BN_CHECK_PRIME
+ ret = BN_check_prime(bn, ossl_bn_ctx, NULL);
+ if (ret < 0)
+ ossl_raise(eBNError, "BN_check_prime");
+#else
+ ret = BN_is_prime_fasttest_ex(bn, BN_prime_checks, ossl_bn_ctx, 1, NULL);
+ if (ret < 0)
+ ossl_raise(eBNError, "BN_is_prime_fasttest_ex");
+#endif
+ return ret ? Qtrue : Qfalse;
}
/*
@@ -1154,40 +1146,17 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
* bn.prime_fasttest?(checks) => true | false
* bn.prime_fasttest?(checks, trial_div) => true | false
*
- * Performs a Miller-Rabin primality test. This is same as #prime? except this
- * first attempts trial divisions with some small primes.
+ * Performs a Miller-Rabin probabilistic primality test for +bn+.
*
- * === Parameters
- * * _checks_ - integer
- * * _trial_div_ - boolean
+ * <b>Deprecated in version 3.0.</b> Use #prime? instead.
+ *
+ * +checks+ and +trial_div+ parameters no longer have any effect.
*/
static VALUE
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
{
- BIGNUM *bn;
- VALUE vchecks, vtrivdiv;
- int checks = BN_prime_checks, do_trial_division = 1;
-
- rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
-
- if (!NIL_P(vchecks)) {
- checks = NUM2INT(vchecks);
- }
- GetBN(self, bn);
- /* handle true/false */
- if (vtrivdiv == Qfalse) {
- do_trial_division = 0;
- }
- switch (BN_is_prime_fasttest_ex(bn, checks, ossl_bn_ctx, do_trial_division, NULL)) {
- case 1:
- return Qtrue;
- case 0:
- return Qfalse;
- default:
- ossl_raise(eBNError, NULL);
- }
- /* not reachable */
- return Qnil;
+ rb_check_arity(argc, 0, 2);
+ return ossl_bn_is_prime(0, argv, self);
}
/*
@@ -1276,6 +1245,7 @@ Init_ossl_bn(void)
rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2);
rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2);
rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1);
+ rb_define_method(cBN, "mod_sqrt", ossl_bn_mod_sqrt, 1);
rb_define_method(cBN, "**", ossl_bn_exp, 1);
rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2);
rb_define_method(cBN, "gcd", ossl_bn_gcd, 1);
@@ -1306,9 +1276,9 @@ Init_ossl_bn(void)
* get_word */
rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
- rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
- rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1);
+ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand", "rand");
+ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand_range", "rand_range");
rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1);
rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1);
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 28f5c1b5ef..cb8fbc3ca2 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -149,11 +149,11 @@ ossl_cipher_copy(VALUE self, VALUE other)
return self;
}
-static void*
-add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
+static void
+add_cipher_name_to_ary(const OBJ_NAME *name, void *arg)
{
+ VALUE ary = (VALUE)arg;
rb_ary_push(ary, rb_str_new2(name->name));
- return NULL;
}
/*
@@ -169,7 +169,7 @@ ossl_s_ciphers(VALUE self)
ary = rb_ary_new();
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
- (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
+ add_cipher_name_to_ary,
(void*)ary);
return ary;
@@ -384,8 +384,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
StringValue(data);
in = (unsigned char *)RSTRING_PTR(data);
- if ((in_len = RSTRING_LEN(data)) == 0)
- ossl_raise(rb_eArgError, "data must not be empty");
+ in_len = RSTRING_LEN(data);
GetCipher(self, ctx);
out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
if (out_len <= 0) {
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index 21c327b26b..0bac027487 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -60,7 +60,7 @@ config_load_bio(CONF *conf, BIO *bio)
if (eline <= 0)
ossl_raise(eConfigError, "wrong config format");
else
- ossl_raise(eConfigError, "error in line %d", eline);
+ ossl_raise(eConfigError, "error in line %ld", eline);
}
BIO_free(bio);
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index d327f718e2..fc326ec14a 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -63,7 +63,7 @@ ossl_evp_get_digestbyname(VALUE obj)
GetDigest(obj, ctx);
- md = EVP_MD_CTX_md(ctx);
+ md = EVP_MD_CTX_get0_md(ctx);
}
return md;
@@ -176,7 +176,7 @@ ossl_digest_reset(VALUE self)
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) {
+ if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) {
ossl_raise(eDigestError, "Digest initialization failed.");
}
@@ -259,7 +259,7 @@ ossl_digest_name(VALUE self)
GetDigest(self, ctx);
- return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
+ return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx)));
}
/*
@@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self)
void
Init_ossl_digest(void)
{
- rb_require("digest");
-
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
@@ -398,6 +396,12 @@ Init_ossl_digest(void)
* digest2 = sha256.digest(data2)
*
*/
+
+ /*
+ * Digest::Class is defined by the digest library. rb_require() cannot be
+ * used here because it bypasses RubyGems.
+ */
+ rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest"));
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
/* Document-class: OpenSSL::Digest::DigestError
*
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 661a1368e2..1abde7f766 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -9,7 +9,8 @@
*/
#include "ossl.h"
-#if !defined(OPENSSL_NO_ENGINE)
+#ifdef OSSL_USE_ENGINE
+# include <openssl/engine.h>
#define NewEngine(klass) \
TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index a21db6c481..1a5f471a27 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -97,11 +97,19 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
GetHMAC(self, ctx);
StringValue(key);
+#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
+ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
+ (unsigned char *)RSTRING_PTR(key),
+ RSTRING_LENINT(key));
+ if (!pkey)
+ ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key");
+#else
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
(unsigned char *)RSTRING_PTR(key),
RSTRING_LENINT(key));
if (!pkey)
ossl_raise(eHMACError, "EVP_PKEY_new_mac_key");
+#endif
if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest),
NULL, pkey) != 1) {
EVP_PKEY_free(pkey);
@@ -175,7 +183,7 @@ static VALUE
ossl_hmac_digest(VALUE self)
{
EVP_MD_CTX *ctx;
- size_t buf_len;
+ size_t buf_len = EVP_MAX_MD_SIZE;
VALUE ret;
GetHMAC(self, ctx);
@@ -200,7 +208,7 @@ ossl_hmac_hexdigest(VALUE self)
{
EVP_MD_CTX *ctx;
unsigned char buf[EVP_MAX_MD_SIZE];
- size_t buf_len;
+ size_t buf_len = EVP_MAX_MD_SIZE;
VALUE ret;
GetHMAC(self, ctx);
@@ -238,8 +246,8 @@ ossl_hmac_reset(VALUE self)
EVP_PKEY *pkey;
GetHMAC(self, ctx);
- pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
- if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_md(ctx), NULL, pkey) != 1)
+ pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+ if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1)
ossl_raise(eHMACError, "EVP_DigestSignInit");
return self;
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c
index 7fa38b865e..0d25a7304b 100644
--- a/ext/openssl/ossl_kdf.c
+++ b/ext/openssl/ossl_kdf.c
@@ -3,7 +3,7 @@
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
*/
#include "ossl.h"
-#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0)
# include <openssl/kdf.h>
#endif
@@ -141,7 +141,7 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
}
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0)
/*
* call-seq:
* KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
@@ -305,7 +305,7 @@ Init_ossl_kdf(void)
#if defined(HAVE_EVP_PBE_SCRYPT)
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0)
rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1);
#endif
}
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index d4ca958a58..9c8d768d87 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -382,7 +382,7 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
if (!NIL_P(flags))
flg = NUM2INT(flags);
if (NIL_P(digest))
- md = EVP_sha1();
+ md = NULL;
else
md = ossl_evp_get_digestbyname(digest);
if (NIL_P(certs))
@@ -803,7 +803,7 @@ add_status_convert_time(VALUE obj)
* revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants.
* _revocation_time_ is the time when the certificate is revoked.
*
- * _this_update_ and _next_update_ indicate the time at which ths status is
+ * _this_update_ and _next_update_ indicate the time at which the status is
* verified to be correct and the time at or before which newer information
* will be available, respectively. _next_update_ is optional.
*
@@ -1033,7 +1033,7 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
if (!NIL_P(flags))
flg = NUM2INT(flags);
if (NIL_P(digest))
- md = EVP_sha1();
+ md = NULL;
else
md = ossl_evp_get_digestbyname(digest);
if (NIL_P(certs))
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index 4566334481..fb947df1d0 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -149,6 +149,24 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
return obj;
}
+static VALUE
+ossl_pkey_new_i(VALUE arg)
+{
+ return ossl_pkey_new((EVP_PKEY *)arg);
+}
+
+static VALUE
+ossl_x509_new_i(VALUE arg)
+{
+ return ossl_x509_new((X509 *)arg);
+}
+
+static VALUE
+ossl_x509_sk2ary_i(VALUE arg)
+{
+ return ossl_x509_sk2ary((STACK_OF(X509) *)arg);
+}
+
/*
* call-seq:
* PKCS12.new -> pkcs12
@@ -186,15 +204,15 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(ePKCS12Error, "PKCS12_parse");
ERR_pop_to_mark();
if (key) {
- pkey = rb_protect((VALUE (*)(VALUE))ossl_pkey_new, (VALUE)key, &st);
+ pkey = rb_protect(ossl_pkey_new_i, (VALUE)key, &st);
if (st) goto err;
}
if (x509) {
- cert = rb_protect((VALUE (*)(VALUE))ossl_x509_new, (VALUE)x509, &st);
+ cert = rb_protect(ossl_x509_new_i, (VALUE)x509, &st);
if (st) goto err;
}
if (x509s) {
- ca = rb_protect((VALUE (*)(VALUE))ossl_x509_sk2ary, (VALUE)x509s, &st);
+ ca = rb_protect(ossl_x509_sk2ary_i, (VALUE)x509s, &st);
if (st) goto err;
}
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 203ab789ca..476256679b 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -9,6 +9,10 @@
*/
#include "ossl.h"
+#ifdef OSSL_USE_ENGINE
+# include <openssl/engine.h>
+#endif
+
/*
* Classes
*/
@@ -35,15 +39,12 @@ const rb_data_type_t ossl_evp_pkey_type = {
};
static VALUE
-pkey_new0(EVP_PKEY *pkey)
+pkey_new0(VALUE arg)
{
+ EVP_PKEY *pkey = (EVP_PKEY *)arg;
VALUE klass, obj;
- int type;
- if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE)
- ossl_raise(rb_eRuntimeError, "pkey is empty");
-
- switch (type) {
+ switch (EVP_PKEY_base_id(pkey)) {
#if !defined(OPENSSL_NO_RSA)
case EVP_PKEY_RSA: klass = cRSA; break;
#endif
@@ -58,8 +59,8 @@ pkey_new0(EVP_PKEY *pkey)
#endif
default: klass = cPKey; break;
}
- obj = NewPKey(klass);
- SetPKey(obj, pkey);
+ obj = rb_obj_alloc(klass);
+ RTYPEDDATA_DATA(obj) = pkey;
return obj;
}
@@ -69,7 +70,7 @@ ossl_pkey_new(EVP_PKEY *pkey)
VALUE obj;
int status;
- obj = rb_protect((VALUE (*)(VALUE))pkey_new0, (VALUE)pkey, &status);
+ obj = rb_protect(pkey_new0, (VALUE)pkey, &status);
if (status) {
EVP_PKEY_free(pkey);
rb_jump_tag(status);
@@ -78,6 +79,84 @@ ossl_pkey_new(EVP_PKEY *pkey)
return obj;
}
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# include <openssl/decoder.h>
+
+EVP_PKEY *
+ossl_pkey_read_generic(BIO *bio, VALUE pass)
+{
+ void *ppass = (void *)pass;
+ OSSL_DECODER_CTX *dctx;
+ EVP_PKEY *pkey = NULL;
+ int pos = 0, pos2;
+
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, NULL, 0, NULL, NULL);
+ if (!dctx)
+ goto out;
+ if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1)
+ goto out;
+
+ /* First check DER */
+ if (OSSL_DECODER_from_bio(dctx, bio) == 1)
+ goto out;
+ OSSL_BIO_reset(bio);
+
+ /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */
+ if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1)
+ goto out;
+ /*
+ * First check for private key formats. This is to keep compatibility with
+ * ruby/openssl < 3.0 which decoded the following as a private key.
+ *
+ * $ openssl ecparam -name prime256v1 -genkey -outform PEM
+ * -----BEGIN EC PARAMETERS-----
+ * BggqhkjOPQMBBw==
+ * -----END EC PARAMETERS-----
+ * -----BEGIN EC PRIVATE KEY-----
+ * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49
+ * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj
+ * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ==
+ * -----END EC PRIVATE KEY-----
+ *
+ * While the first PEM block is a proper encoding of ECParameters, thus
+ * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return
+ * the latter instead. Existing applications expect this behavior.
+ *
+ * Note that normally, the input is supposed to contain a single decodable
+ * PEM block only, so this special handling should not create a new problem.
+ */
+ OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR);
+ while (1) {
+ if (OSSL_DECODER_from_bio(dctx, bio) == 1)
+ goto out;
+ if (BIO_eof(bio))
+ break;
+ pos2 = BIO_tell(bio);
+ if (pos2 < 0 || pos2 <= pos)
+ break;
+ ossl_clear_error();
+ pos = pos2;
+ }
+
+ OSSL_BIO_reset(bio);
+ OSSL_DECODER_CTX_set_selection(dctx, 0);
+ while (1) {
+ if (OSSL_DECODER_from_bio(dctx, bio) == 1)
+ goto out;
+ if (BIO_eof(bio))
+ break;
+ pos2 = BIO_tell(bio);
+ if (pos2 < 0 || pos2 <= pos)
+ break;
+ ossl_clear_error();
+ pos = pos2;
+ }
+
+ out:
+ OSSL_DECODER_CTX_free(dctx);
+ return pkey;
+}
+#else
EVP_PKEY *
ossl_pkey_read_generic(BIO *bio, VALUE pass)
{
@@ -106,6 +185,7 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
out:
return pkey;
}
+#endif
/*
* call-seq:
@@ -159,6 +239,7 @@ static VALUE
pkey_ctx_apply_options0(VALUE args_v)
{
VALUE *args = (VALUE *)args_v;
+ Check_Type(args[1], T_HASH);
rb_block_call(args[1], rb_intern("each"), 0, NULL,
pkey_ctx_apply_options_i, args[0]);
@@ -275,6 +356,11 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
}
else {
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
+ if (!ctx)
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name");
+#else
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *tmpeng;
int pkey_id;
@@ -293,6 +379,7 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */);
if (!ctx)
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id");
+#endif
}
if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) {
@@ -388,9 +475,19 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
return pkey_generate(argc, argv, self, 0);
}
+/*
+ * TODO: There is no convenient way to check the presence of public key
+ * components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without
+ * these should only be created by OpenSSL::PKey.generate_parameters or by
+ * parsing DER-/PEM-encoded string. We would need another flag for that.
+ */
void
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
{
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ if (EVP_PKEY_missing_parameters(pkey))
+ ossl_raise(ePKeyError, "parameters missing");
+#else
void *ptr;
const BIGNUM *n, *e, *pubkey;
@@ -426,6 +523,7 @@ ossl_pkey_check_public_key(const EVP_PKEY *pkey)
return;
}
ossl_raise(ePKeyError, "public key missing");
+#endif
}
EVP_PKEY *
@@ -475,16 +573,7 @@ DupPKeyPtr(VALUE obj)
static VALUE
ossl_pkey_alloc(VALUE klass)
{
- EVP_PKEY *pkey;
- VALUE obj;
-
- obj = NewPKey(klass);
- if (!(pkey = EVP_PKEY_new())) {
- ossl_raise(ePKeyError, NULL);
- }
- SetPKey(obj, pkey);
-
- return obj;
+ return TypedData_Wrap_Struct(klass, &ossl_evp_pkey_type, NULL);
}
/*
@@ -503,6 +592,26 @@ ossl_pkey_initialize(VALUE self)
return self;
}
+#ifdef HAVE_EVP_PKEY_DUP
+static VALUE
+ossl_pkey_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey, *pkey_other;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+ if (pkey_other) {
+ pkey = EVP_PKEY_dup(pkey_other);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_dup");
+ RTYPEDDATA_DATA(self) = pkey;
+ }
+ return self;
+}
+#endif
+
/*
* call-seq:
* pkey.oid -> string
@@ -601,7 +710,7 @@ ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
}
}
else {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 5, 0)
if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0,
ossl_pem_passwd_cb,
(void *)pass)) {
@@ -768,14 +877,14 @@ ossl_pkey_compare(VALUE self, VALUE other)
if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey))
ossl_raise(rb_eTypeError, "cannot match different PKey types");
- ret = EVP_PKEY_cmp(selfPKey, otherPKey);
+ ret = EVP_PKEY_eq(selfPKey, otherPKey);
if (ret == 0)
return Qfalse;
else if (ret == 1)
return Qtrue;
else
- ossl_raise(ePKeyError, "EVP_PKEY_cmp");
+ ossl_raise(ePKeyError, "EVP_PKEY_eq");
}
/*
@@ -842,7 +951,7 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
rb_jump_tag(state);
}
}
-#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) < 1) {
EVP_MD_CTX_free(ctx);
@@ -947,7 +1056,7 @@ ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
rb_jump_tag(state);
}
}
-#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data));
@@ -1480,6 +1589,11 @@ Init_ossl_pkey(void)
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
+#ifdef HAVE_EVP_PKEY_DUP
+ rb_define_method(cPKey, "initialize_copy", ossl_pkey_initialize_copy, 1);
+#else
+ rb_undef_method(cPKey, "initialize_copy");
+#endif
rb_define_method(cPKey, "oid", ossl_pkey_oid, 0);
rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0);
rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0);
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 4beede22b5..10669b824c 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -15,19 +15,10 @@ extern VALUE cPKey;
extern VALUE ePKeyError;
extern const rb_data_type_t ossl_evp_pkey_type;
-#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
-#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse)
-#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue)
+/* For ENGINE */
+#define OSSL_PKEY_SET_PRIVATE(obj) rb_ivar_set((obj), rb_intern("private"), Qtrue)
+#define OSSL_PKEY_IS_PRIVATE(obj) (rb_attr_get((obj), rb_intern("private")) == Qtrue)
-#define NewPKey(klass) \
- TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, 0)
-#define SetPKey(obj, pkey) do { \
- if (!(pkey)) { \
- rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \
- } \
- RTYPEDDATA_DATA(obj) = (pkey); \
- OSSL_PKEY_SET_PUBLIC(obj); \
-} while (0)
#define GetPKey(obj, pkey) do {\
TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \
if (!(pkey)) { \
@@ -35,6 +26,7 @@ extern const rb_data_type_t ossl_evp_pkey_type;
} \
} while (0)
+/* Takes ownership of the EVP_PKEY */
VALUE ossl_pkey_new(EVP_PKEY *);
void ossl_pkey_check_public_key(const EVP_PKEY *);
EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE);
@@ -100,7 +92,7 @@ void Init_ossl_ec(void);
*/ \
static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
{ \
- _type *obj; \
+ const _type *obj; \
const BIGNUM *bn; \
\
Get##_type(self, obj); \
@@ -124,6 +116,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
_type##_get0_##_group(obj, NULL, &bn))
+#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
/* \
* call-seq: \
@@ -181,6 +174,21 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
} \
return self; \
}
+#else
+#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
+{ \
+ rb_raise(ePKeyError, \
+ #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
+}
+
+#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
+{ \
+ rb_raise(ePKeyError, \
+ #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
+}
+#endif
#define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \
OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index ca782bbe59..83c41378fe 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -58,51 +58,76 @@ VALUE eDHError;
*
* Examples:
* # Creating an instance from scratch
- * dh = DH.new
+ * # Note that this is deprecated and will not work on OpenSSL 3.0 or later.
+ * dh = OpenSSL::PKey::DH.new
* dh.set_pqg(bn_p, nil, bn_g)
*
* # Generating a parameters and a key pair
- * dh = DH.new(2048) # An alias of DH.generate(2048)
+ * dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
*
* # Reading DH parameters
- * dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
- * dh.generate_key! # -> dh with public and private key
+ * dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
+ * dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
*/
static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
+ int type;
DH *dh;
- BIO *in;
+ BIO *in = NULL;
VALUE arg;
- GetPKey(self, pkey);
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
+
/* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
dh = DH_new();
if (!dh)
ossl_raise(eDHError, "DH_new");
+ goto legacy;
}
- else {
- arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(&arg);
- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
- if (!dh){
- OSSL_BIO_reset(in);
- dh = d2i_DHparams_bio(in, NULL);
- }
- BIO_free(in);
- if (!dh) {
- ossl_raise(eDHError, NULL);
- }
+
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+
+ /*
+ * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic
+ * routine does not support DER-encoded parameters
+ */
+ dh = d2i_DHparams_bio(in, NULL);
+ if (dh)
+ goto legacy;
+ OSSL_BIO_reset(in);
+
+ pkey = ossl_pkey_read_generic(in, Qnil);
+ BIO_free(in);
+ if (!pkey)
+ ossl_raise(eDHError, "could not parse pkey");
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_DH) {
+ EVP_PKEY_free(pkey);
+ rb_raise(eDHError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
- if (!EVP_PKEY_assign_DH(pkey, dh)) {
- DH_free(dh);
- ossl_raise(eDHError, NULL);
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
+
+ legacy:
+ BIO_free(in);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
+ EVP_PKEY_free(pkey);
+ DH_free(dh);
+ ossl_raise(eDHError, "EVP_PKEY_assign_DH");
}
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
static VALUE
ossl_dh_initialize_copy(VALUE self, VALUE other)
{
@@ -110,15 +135,14 @@ ossl_dh_initialize_copy(VALUE self, VALUE other)
DH *dh, *dh_other;
const BIGNUM *pub, *priv;
- GetPKey(self, pkey);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
- ossl_raise(eDHError, "DH already initialized");
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
GetDH(other, dh_other);
dh = DHparams_dup(dh_other);
if (!dh)
ossl_raise(eDHError, "DHparams_dup");
- EVP_PKEY_assign_DH(pkey, dh);
DH_get0_key(dh_other, &pub, &priv);
if (pub) {
@@ -133,8 +157,16 @@ ossl_dh_initialize_copy(VALUE self, VALUE other)
DH_set0_key(dh, pub2, priv2);
}
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
+ EVP_PKEY_free(pkey);
+ DH_free(dh);
+ ossl_raise(eDHError, "EVP_PKEY_assign_DH");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#endif
/*
* call-seq:
@@ -146,7 +178,7 @@ ossl_dh_initialize_copy(VALUE self, VALUE other)
static VALUE
ossl_dh_is_public(VALUE self)
{
- DH *dh;
+ OSSL_3_const DH *dh;
const BIGNUM *bn;
GetDH(self, dh);
@@ -165,14 +197,14 @@ ossl_dh_is_public(VALUE self)
static VALUE
ossl_dh_is_private(VALUE self)
{
- DH *dh;
+ OSSL_3_const DH *dh;
const BIGNUM *bn;
GetDH(self, dh);
DH_get0_key(dh, NULL, &bn);
#if !defined(OPENSSL_NO_ENGINE)
- return (bn || DH_get0_engine(dh)) ? Qtrue : Qfalse;
+ return (bn || DH_get0_engine((DH *)dh)) ? Qtrue : Qfalse;
#else
return bn ? Qtrue : Qfalse;
#endif
@@ -191,7 +223,7 @@ ossl_dh_is_private(VALUE self)
static VALUE
ossl_dh_export(VALUE self)
{
- DH *dh;
+ OSSL_3_const DH *dh;
BIO *out;
VALUE str;
@@ -220,7 +252,7 @@ ossl_dh_export(VALUE self)
static VALUE
ossl_dh_to_der(VALUE self)
{
- DH *dh;
+ OSSL_3_const DH *dh;
unsigned char *p;
long len;
VALUE str;
@@ -248,7 +280,7 @@ ossl_dh_to_der(VALUE self)
static VALUE
ossl_dh_get_params(VALUE self)
{
- DH *dh;
+ OSSL_3_const DH *dh;
VALUE hash;
const BIGNUM *p, *q, *g, *pub_key, *priv_key;
@@ -378,7 +410,9 @@ Init_ossl_dh(void)
*/
cDH = rb_define_class_under(mPKey, "DH", cPKey);
rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1);
+#endif
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
rb_define_method(cDH, "export", ossl_dh_export, 0);
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 7af00eebec..b097f8c9d2 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -24,7 +24,7 @@
} while (0)
static inline int
-DSA_HAS_PRIVATE(DSA *dsa)
+DSA_HAS_PRIVATE(OSSL_3_const DSA *dsa)
{
const BIGNUM *bn;
DSA_get0_key(dsa, NULL, &bn);
@@ -32,7 +32,7 @@ DSA_HAS_PRIVATE(DSA *dsa)
}
static inline int
-DSA_PRIVATE(VALUE obj, DSA *dsa)
+DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa)
{
return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj);
}
@@ -83,72 +83,91 @@ VALUE eDSAError;
static VALUE
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
{
- EVP_PKEY *pkey, *tmp;
- DSA *dsa = NULL;
- BIO *in;
+ EVP_PKEY *pkey;
+ DSA *dsa;
+ BIO *in = NULL;
VALUE arg, pass;
+ int type;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
- GetPKey(self, pkey);
/* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
rb_scan_args(argc, argv, "02", &arg, &pass);
if (argc == 0) {
dsa = DSA_new();
if (!dsa)
ossl_raise(eDSAError, "DSA_new");
+ goto legacy;
}
- else {
- pass = ossl_pem_passwd_value(pass);
- arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(&arg);
-
- tmp = ossl_pkey_read_generic(in, pass);
- if (tmp) {
- if (EVP_PKEY_base_id(tmp) != EVP_PKEY_DSA)
- rb_raise(eDSAError, "incorrect pkey type: %s",
- OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
- dsa = EVP_PKEY_get1_DSA(tmp);
- EVP_PKEY_free(tmp);
- }
- if (!dsa) {
- OSSL_BIO_reset(in);
-#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
- (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
- dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
-#undef PEM_read_bio_DSAPublicKey
- }
- BIO_free(in);
- if (!dsa) {
- ossl_clear_error();
- ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
- }
- }
- if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
- DSA_free(dsa);
- ossl_raise(eDSAError, NULL);
+
+ pass = ossl_pem_passwd_value(pass);
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+
+ /* DER-encoded DSAPublicKey format isn't supported by the generic routine */
+ dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey,
+ PEM_STRING_DSA_PUBLIC,
+ in, NULL, NULL, NULL);
+ if (dsa)
+ goto legacy;
+ OSSL_BIO_reset(in);
+
+ pkey = ossl_pkey_read_generic(in, pass);
+ BIO_free(in);
+ if (!pkey)
+ ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_DSA) {
+ EVP_PKEY_free(pkey);
+ rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
+ legacy:
+ BIO_free(in);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) {
+ EVP_PKEY_free(pkey);
+ DSA_free(dsa);
+ ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
static VALUE
ossl_dsa_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
DSA *dsa, *dsa_new;
- GetPKey(self, pkey);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
- ossl_raise(eDSAError, "DSA already initialized");
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
GetDSA(other, dsa);
- dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa);
+ dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey,
+ (d2i_of_void *)d2i_DSAPrivateKey,
+ (char *)dsa);
if (!dsa_new)
ossl_raise(eDSAError, "ASN1_dup");
- EVP_PKEY_assign_DSA(pkey, dsa_new);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) {
+ EVP_PKEY_free(pkey);
+ DSA_free(dsa_new);
+ ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#endif
/*
* call-seq:
@@ -160,7 +179,7 @@ ossl_dsa_initialize_copy(VALUE self, VALUE other)
static VALUE
ossl_dsa_is_public(VALUE self)
{
- DSA *dsa;
+ const DSA *dsa;
const BIGNUM *bn;
GetDSA(self, dsa);
@@ -179,7 +198,7 @@ ossl_dsa_is_public(VALUE self)
static VALUE
ossl_dsa_is_private(VALUE self)
{
- DSA *dsa;
+ OSSL_3_const DSA *dsa;
GetDSA(self, dsa);
@@ -206,7 +225,7 @@ ossl_dsa_is_private(VALUE self)
static VALUE
ossl_dsa_export(int argc, VALUE *argv, VALUE self)
{
- DSA *dsa;
+ OSSL_3_const DSA *dsa;
GetDSA(self, dsa);
if (DSA_HAS_PRIVATE(dsa))
@@ -225,7 +244,7 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
static VALUE
ossl_dsa_to_der(VALUE self)
{
- DSA *dsa;
+ OSSL_3_const DSA *dsa;
GetDSA(self, dsa);
if (DSA_HAS_PRIVATE(dsa))
@@ -246,7 +265,7 @@ ossl_dsa_to_der(VALUE self)
static VALUE
ossl_dsa_get_params(VALUE self)
{
- DSA *dsa;
+ OSSL_3_const DSA *dsa;
VALUE hash;
const BIGNUM *p, *q, *g, *pub_key, *priv_key;
@@ -310,7 +329,9 @@ Init_ossl_dsa(void)
cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1);
+#endif
rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index 9b461cb6a2..92842f95ac 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -109,13 +109,16 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
VALUE obj;
obj = rb_obj_alloc(klass);
- GetPKey(obj, pkey);
ec = ec_key_new_from_group(arg);
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
+ EVP_PKEY_free(pkey);
EC_KEY_free(ec);
ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
}
+ RTYPEDDATA_DATA(obj) = pkey;
+
if (!EC_KEY_generate_key(ec))
ossl_raise(eECError, "EC_KEY_generate_key");
@@ -136,75 +139,83 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- EC_KEY *ec = NULL;
+ EC_KEY *ec;
+ BIO *in;
VALUE arg, pass;
+ int type;
- GetPKey(self, pkey);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
- ossl_raise(eECError, "EC_KEY already initialized");
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
rb_scan_args(argc, argv, "02", &arg, &pass);
-
if (NIL_P(arg)) {
if (!(ec = EC_KEY_new()))
- ossl_raise(eECError, NULL);
- } else if (rb_obj_is_kind_of(arg, cEC)) {
- EC_KEY *other_ec = NULL;
+ ossl_raise(eECError, "EC_KEY_new");
+ goto legacy;
+ }
+ else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ ec = ec_key_new_from_group(arg);
+ goto legacy;
+ }
- GetEC(arg, other_ec);
- if (!(ec = EC_KEY_dup(other_ec)))
- ossl_raise(eECError, NULL);
- } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
- ec = ec_key_new_from_group(arg);
- } else {
- BIO *in = ossl_obj2bio(&arg);
- EVP_PKEY *tmp;
- pass = ossl_pem_passwd_value(pass);
- tmp = ossl_pkey_read_generic(in, pass);
- if (tmp) {
- if (EVP_PKEY_base_id(tmp) != EVP_PKEY_EC)
- rb_raise(eECError, "incorrect pkey type: %s",
- OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
- ec = EVP_PKEY_get1_EC_KEY(tmp);
- EVP_PKEY_free(tmp);
- }
- BIO_free(in);
+ pass = ossl_pem_passwd_value(pass);
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
- if (!ec) {
- ossl_clear_error();
- ec = ec_key_new_from_group(arg);
- }
+ pkey = ossl_pkey_read_generic(in, pass);
+ BIO_free(in);
+ if (!pkey) {
+ ossl_clear_error();
+ ec = ec_key_new_from_group(arg);
+ goto legacy;
}
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
- EC_KEY_free(ec);
- ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_EC) {
+ EVP_PKEY_free(pkey);
+ rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
+ legacy:
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec);
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
static VALUE
ossl_ec_key_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
EC_KEY *ec, *ec_new;
- GetPKey(self, pkey);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
- ossl_raise(eECError, "EC already initialized");
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
GetEC(other, ec);
ec_new = EC_KEY_dup(ec);
if (!ec_new)
ossl_raise(eECError, "EC_KEY_dup");
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
- EC_KEY_free(ec_new);
- ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
+
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) {
+ EC_KEY_free(ec_new);
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
}
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#endif
/*
* call-seq:
@@ -216,7 +227,7 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other)
static VALUE
ossl_ec_key_get_group(VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
const EC_GROUP *group;
GetEC(self, ec);
@@ -237,6 +248,9 @@ ossl_ec_key_get_group(VALUE self)
static VALUE
ossl_ec_key_set_group(VALUE self, VALUE group_v)
{
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
EC_KEY *ec;
EC_GROUP *group;
@@ -247,6 +261,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v)
ossl_raise(eECError, "EC_KEY_set_group");
return group_v;
+#endif
}
/*
@@ -257,7 +272,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v)
*/
static VALUE ossl_ec_key_get_private_key(VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
const BIGNUM *bn;
GetEC(self, ec);
@@ -275,6 +290,9 @@ static VALUE ossl_ec_key_get_private_key(VALUE self)
*/
static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
{
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
EC_KEY *ec;
BIGNUM *bn = NULL;
@@ -288,11 +306,13 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
case 0:
if (bn == NULL)
break;
+ /* fallthrough */
default:
ossl_raise(eECError, "EC_KEY_set_private_key");
}
return private_key;
+#endif
}
/*
@@ -303,7 +323,7 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
*/
static VALUE ossl_ec_key_get_public_key(VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
const EC_POINT *point;
GetEC(self, ec);
@@ -321,6 +341,9 @@ static VALUE ossl_ec_key_get_public_key(VALUE self)
*/
static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
{
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
EC_KEY *ec;
EC_POINT *point = NULL;
@@ -334,11 +357,13 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
case 0:
if (point == NULL)
break;
+ /* fallthrough */
default:
ossl_raise(eECError, "EC_KEY_set_public_key");
}
return public_key;
+#endif
}
/*
@@ -350,7 +375,7 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
*/
static VALUE ossl_ec_key_is_public(VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
GetEC(self, ec);
@@ -366,7 +391,7 @@ static VALUE ossl_ec_key_is_public(VALUE self)
*/
static VALUE ossl_ec_key_is_private(VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
GetEC(self, ec);
@@ -386,9 +411,11 @@ static VALUE ossl_ec_key_is_private(VALUE self)
static VALUE
ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
GetEC(self, ec);
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ ossl_raise(eECError, "can't export - no public key set");
if (EC_KEY_get0_private_key(ec))
return ossl_pkey_export_traditional(argc, argv, self, 0);
else
@@ -404,9 +431,11 @@ ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
static VALUE
ossl_ec_key_to_der(VALUE self)
{
- EC_KEY *ec;
+ OSSL_3_const EC_KEY *ec;
GetEC(self, ec);
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ ossl_raise(eECError, "can't export - no public key set");
if (EC_KEY_get0_private_key(ec))
return ossl_pkey_export_traditional(0, NULL, self, 1);
else
@@ -428,6 +457,9 @@ ossl_ec_key_to_der(VALUE self)
*/
static VALUE ossl_ec_key_generate_key(VALUE self)
{
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
EC_KEY *ec;
GetEC(self, ec);
@@ -435,6 +467,7 @@ static VALUE ossl_ec_key_generate_key(VALUE self)
ossl_raise(eECError, "EC_KEY_generate_key");
return self;
+#endif
}
/*
@@ -450,16 +483,28 @@ static VALUE ossl_ec_key_check_key(VALUE self)
#ifdef HAVE_EVP_PKEY_CHECK
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx;
- int ret;
+ const EC_KEY *ec;
GetPKey(self, pkey);
+ GetEC(self, ec);
pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!pctx)
- ossl_raise(eDHError, "EVP_PKEY_CTX_new");
- ret = EVP_PKEY_public_check(pctx);
+ ossl_raise(eECError, "EVP_PKEY_CTX_new");
+
+ if (EC_KEY_get0_private_key(ec) != NULL) {
+ if (EVP_PKEY_check(pctx) != 1) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eECError, "EVP_PKEY_check");
+ }
+ }
+ else {
+ if (EVP_PKEY_public_check(pctx) != 1) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eECError, "EVP_PKEY_public_check");
+ }
+ }
+
EVP_PKEY_CTX_free(pctx);
- if (ret != 1)
- ossl_raise(eECError, "EVP_PKEY_public_check");
#else
EC_KEY *ec;
@@ -477,7 +522,7 @@ static VALUE ossl_ec_key_check_key(VALUE self)
static void
ossl_ec_group_free(void *ptr)
{
- EC_GROUP_clear_free(ptr);
+ EC_GROUP_free(ptr);
}
static const rb_data_type_t ossl_ec_group_type = {
@@ -596,8 +641,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(rb_eArgError, "wrong number of arguments");
}
- if (group == NULL)
- ossl_raise(eEC_GROUP, "");
+ ASSUME(group);
RTYPEDDATA_DATA(self) = group;
return self;
@@ -636,10 +680,11 @@ static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
GetECGroup(a, group1);
GetECGroup(b, group2);
- if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
- return Qfalse;
-
- return Qtrue;
+ switch (EC_GROUP_cmp(group1, group2, ossl_bn_ctx)) {
+ case 0: return Qtrue;
+ case 1: return Qfalse;
+ default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp");
+ }
}
/*
@@ -1200,10 +1245,13 @@ static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
GetECPoint(b, point2);
GetECGroup(group_v1, group);
- if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
- return Qfalse;
+ switch (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx)) {
+ case 0: return Qtrue;
+ case 1: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_cmp");
+ }
- return Qtrue;
+ UNREACHABLE;
}
/*
@@ -1221,7 +1269,7 @@ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
switch (EC_POINT_is_at_infinity(group, point)) {
case 1: return Qtrue;
case 0: return Qfalse;
- default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_at_infinity");
}
UNREACHABLE;
@@ -1242,7 +1290,7 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
case 1: return Qtrue;
case 0: return Qfalse;
- default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_on_curve");
}
UNREACHABLE;
@@ -1251,6 +1299,8 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
/*
* call-seq:
* point.make_affine! => self
+ *
+ * This method is deprecated and should not be used. This is a no-op.
*/
static VALUE ossl_ec_point_make_affine(VALUE self)
{
@@ -1260,8 +1310,11 @@ static VALUE ossl_ec_point_make_affine(VALUE self)
GetECPoint(self, point);
GetECPointGroup(self, group);
+ rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
+#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
- ossl_raise(cEC_POINT, "EC_POINT_make_affine");
+ ossl_raise(eEC_POINT, "EC_POINT_make_affine");
+#endif
return self;
}
@@ -1279,7 +1332,7 @@ static VALUE ossl_ec_point_invert(VALUE self)
GetECPointGroup(self, group);
if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
- ossl_raise(cEC_POINT, "EC_POINT_invert");
+ ossl_raise(eEC_POINT, "EC_POINT_invert");
return self;
}
@@ -1297,7 +1350,7 @@ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
GetECPointGroup(self, group);
if (EC_POINT_set_to_infinity(group, point) != 1)
- ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
+ ossl_raise(eEC_POINT, "EC_POINT_set_to_infinity");
return self;
}
@@ -1508,8 +1561,9 @@ void Init_ossl_ec(void)
rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1);
-/* copy/dup/cmp */
+#endif
rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 8ebd3ec559..072adabe62 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -24,7 +24,7 @@
} while (0)
static inline int
-RSA_HAS_PRIVATE(RSA *rsa)
+RSA_HAS_PRIVATE(OSSL_3_const RSA *rsa)
{
const BIGNUM *e, *d;
@@ -33,7 +33,7 @@ RSA_HAS_PRIVATE(RSA *rsa)
}
static inline int
-RSA_PRIVATE(VALUE obj, RSA *rsa)
+RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa)
{
return RSA_HAS_PRIVATE(rsa) || OSSL_PKEY_IS_PRIVATE(obj);
}
@@ -76,73 +76,93 @@ VALUE eRSAError;
static VALUE
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
{
- EVP_PKEY *pkey, *tmp;
- RSA *rsa = NULL;
- BIO *in;
+ EVP_PKEY *pkey;
+ RSA *rsa;
+ BIO *in = NULL;
VALUE arg, pass;
+ int type;
+
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
- GetPKey(self, pkey);
/* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
rb_scan_args(argc, argv, "02", &arg, &pass);
if (argc == 0) {
rsa = RSA_new();
if (!rsa)
ossl_raise(eRSAError, "RSA_new");
+ goto legacy;
}
- else {
- pass = ossl_pem_passwd_value(pass);
- arg = ossl_to_der_if_possible(arg);
- in = ossl_obj2bio(&arg);
-
- tmp = ossl_pkey_read_generic(in, pass);
- if (tmp) {
- if (EVP_PKEY_base_id(tmp) != EVP_PKEY_RSA)
- rb_raise(eRSAError, "incorrect pkey type: %s",
- OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
- rsa = EVP_PKEY_get1_RSA(tmp);
- EVP_PKEY_free(tmp);
- }
- if (!rsa) {
- OSSL_BIO_reset(in);
- rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
- }
- if (!rsa) {
- OSSL_BIO_reset(in);
- rsa = d2i_RSAPublicKey_bio(in, NULL);
- }
- BIO_free(in);
- if (!rsa) {
- ossl_clear_error();
- ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
- }
- }
- if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
- RSA_free(rsa);
- ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
+
+ pass = ossl_pem_passwd_value(pass);
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+
+ /* First try RSAPublicKey format */
+ rsa = d2i_RSAPublicKey_bio(in, NULL);
+ if (rsa)
+ goto legacy;
+ OSSL_BIO_reset(in);
+ rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
+ if (rsa)
+ goto legacy;
+ OSSL_BIO_reset(in);
+
+ /* Use the generic routine */
+ pkey = ossl_pkey_read_generic(in, pass);
+ BIO_free(in);
+ if (!pkey)
+ ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
+
+ type = EVP_PKEY_base_id(pkey);
+ if (type != EVP_PKEY_RSA) {
+ EVP_PKEY_free(pkey);
+ rb_raise(eRSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
+ RTYPEDDATA_DATA(self) = pkey;
+ return self;
+ legacy:
+ BIO_free(in);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#ifndef HAVE_EVP_PKEY_DUP
static VALUE
ossl_rsa_initialize_copy(VALUE self, VALUE other)
{
EVP_PKEY *pkey;
RSA *rsa, *rsa_new;
- GetPKey(self, pkey);
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
- ossl_raise(eRSAError, "RSA already initialized");
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
+ if (pkey)
+ rb_raise(rb_eTypeError, "pkey already initialized");
GetRSA(other, rsa);
- rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa);
+ rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey,
+ (d2i_of_void *)d2i_RSAPrivateKey,
+ (char *)rsa);
if (!rsa_new)
ossl_raise(eRSAError, "ASN1_dup");
- EVP_PKEY_assign_RSA(pkey, rsa_new);
+ pkey = EVP_PKEY_new();
+ if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) {
+ RSA_free(rsa_new);
+ ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
+ }
+ RTYPEDDATA_DATA(self) = pkey;
return self;
}
+#endif
/*
* call-seq:
@@ -154,7 +174,7 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other)
static VALUE
ossl_rsa_is_public(VALUE self)
{
- RSA *rsa;
+ OSSL_3_const RSA *rsa;
GetRSA(self, rsa);
/*
@@ -173,7 +193,7 @@ ossl_rsa_is_public(VALUE self)
static VALUE
ossl_rsa_is_private(VALUE self)
{
- RSA *rsa;
+ OSSL_3_const RSA *rsa;
GetRSA(self, rsa);
@@ -183,7 +203,7 @@ ossl_rsa_is_private(VALUE self)
static int
can_export_rsaprivatekey(VALUE self)
{
- RSA *rsa;
+ OSSL_3_const RSA *rsa;
const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
GetRSA(self, rsa);
@@ -433,7 +453,7 @@ ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
static VALUE
ossl_rsa_get_params(VALUE self)
{
- RSA *rsa;
+ OSSL_3_const RSA *rsa;
VALUE hash;
const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
@@ -517,7 +537,9 @@ Init_ossl_rsa(void)
cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
+#ifndef HAVE_EVP_PKEY_DUP
rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1);
+#endif
rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 8f365278f9..f63992664a 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -11,11 +11,15 @@
*/
#include "ossl.h"
+#ifndef OPENSSL_NO_SOCK
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
+#if !defined(OPENSSL_NO_NEXTPROTONEG) && !OSSL_IS_LIBRESSL
+# define OSSL_USE_NEXTPROTONEG
+#endif
+
#if !defined(TLS1_3_VERSION) && \
- defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER >= 0x3020000fL
+ OSSL_LIBRESSL_PREREQ(3, 2, 0) && !OSSL_LIBRESSL_PREREQ(3, 4, 0)
# define TLS1_3_VERSION 0x0304
#endif
@@ -30,7 +34,6 @@
} while (0)
VALUE mSSL;
-static VALUE mSSLExtConfig;
static VALUE eSSLError;
VALUE cSSLContext;
VALUE cSSLSocket;
@@ -49,7 +52,7 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb,
id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
- id_i_verify_hostname;
+ id_i_verify_hostname, id_i_keylog_cb;
static ID id_i_io, id_i_context, id_i_hostname;
static int ossl_ssl_ex_vcb_idx;
@@ -57,6 +60,13 @@ static int ossl_ssl_ex_ptr_idx;
static int ossl_sslctx_ex_ptr_idx;
static void
+ossl_sslctx_mark(void *ptr)
+{
+ SSL_CTX *ctx = ptr;
+ rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
+}
+
+static void
ossl_sslctx_free(void *ptr)
{
SSL_CTX_free(ptr);
@@ -65,7 +75,7 @@ ossl_sslctx_free(void *ptr)
static const rb_data_type_t ossl_sslctx_type = {
"OpenSSL/SSL/CTX",
{
- 0, ossl_sslctx_free,
+ ossl_sslctx_mark, ossl_sslctx_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
@@ -239,22 +249,23 @@ struct tmp_dh_callback_args {
int keylength;
};
-static EVP_PKEY *
-ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args)
+static VALUE
+ossl_call_tmp_dh_callback(VALUE arg)
{
+ struct tmp_dh_callback_args *args = (struct tmp_dh_callback_args *)arg;
VALUE cb, dh;
EVP_PKEY *pkey;
cb = rb_funcall(args->ssl_obj, args->id, 0);
if (NIL_P(cb))
- return NULL;
+ return (VALUE)NULL;
dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
INT2NUM(args->keylength));
pkey = GetPKeyPtr(dh);
if (EVP_PKEY_base_id(pkey) != args->type)
- return NULL;
+ return (VALUE)NULL;
- return pkey;
+ return (VALUE)pkey;
}
#endif
@@ -274,7 +285,7 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
args.keylength = keylength;
args.type = EVP_PKEY_DH;
- pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
+ pkey = (EVP_PKEY *)rb_protect(ossl_call_tmp_dh_callback,
(VALUE)&args, &state);
if (state) {
rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
@@ -283,7 +294,7 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
if (!pkey)
return NULL;
- return EVP_PKEY_get0_DH(pkey);
+ return (DH *)EVP_PKEY_get0_DH(pkey);
}
#endif /* OPENSSL_NO_DH */
@@ -433,6 +444,54 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
return 0;
}
+#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
+/*
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
+ */
+
+struct ossl_call_keylog_cb_args {
+ VALUE ssl_obj;
+ const char * line;
+};
+
+static VALUE
+ossl_call_keylog_cb(VALUE args_v)
+{
+ VALUE sslctx_obj, cb, line_v;
+ struct ossl_call_keylog_cb_args *args = (struct ossl_call_keylog_cb_args *) args_v;
+
+ sslctx_obj = rb_attr_get(args->ssl_obj, id_i_context);
+
+ cb = rb_attr_get(sslctx_obj, id_i_keylog_cb);
+ if (NIL_P(cb)) return Qnil;
+
+ line_v = rb_str_new_cstr(args->line);
+
+ return rb_funcall(cb, id_call, 2, args->ssl_obj, line_v);
+}
+
+static void
+ossl_sslctx_keylog_cb(const SSL *ssl, const char *line)
+{
+ VALUE ssl_obj;
+ struct ossl_call_keylog_cb_args args;
+ int state = 0;
+
+ OSSL_Debug("SSL keylog callback entered");
+
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ args.ssl_obj = ssl_obj;
+ args.line = line;
+
+ rb_protect(ossl_call_keylog_cb, (VALUE)&args, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ }
+}
+#endif
+
static VALUE
ossl_call_session_remove_cb(VALUE ary)
{
@@ -647,12 +706,12 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
return SSL_TLSEXT_ERR_OK;
}
-#ifndef OPENSSL_NO_NEXTPROTONEG
+#ifdef OSSL_USE_NEXTPROTONEG
static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
void *arg)
{
- VALUE protocols = (VALUE)arg;
+ VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
*out = (const unsigned char *) RSTRING_PTR(protocols);
*outlen = RSTRING_LENINT(protocols);
@@ -820,10 +879,17 @@ ossl_sslctx_setup(VALUE self)
ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
val = rb_attr_get(self, id_i_ca_path);
ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
+#ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE
+ if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file))
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_file");
+ if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path))
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_dir");
+#else
if(ca_file || ca_path){
if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
rb_warning("can't set verify locations");
}
+#endif
val = rb_attr_get(self, id_i_verify_mode);
verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
@@ -837,12 +903,12 @@ ossl_sslctx_setup(VALUE self)
val = rb_attr_get(self, id_i_verify_depth);
if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
-#ifndef OPENSSL_NO_NEXTPROTONEG
+#ifdef OSSL_USE_NEXTPROTONEG
val = rb_attr_get(self, id_i_npn_protocols);
if (!NIL_P(val)) {
VALUE encoded = ssl_encode_npn_protocols(val);
rb_ivar_set(self, id_npn_protocols_encoded, encoded);
- SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
OSSL_Debug("SSL NPN advertise callback added");
}
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@@ -896,6 +962,18 @@ ossl_sslctx_setup(VALUE self)
OSSL_Debug("SSL TLSEXT servername callback added");
}
+#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
+ /*
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
+ */
+ if (RTEST(rb_attr_get(self, id_i_keylog_cb))) {
+ SSL_CTX_set_keylog_callback(ctx, ossl_sslctx_keylog_cb);
+ OSSL_Debug("SSL keylog callback added");
+ }
+#endif
+
return Qtrue;
}
@@ -944,27 +1022,13 @@ ossl_sslctx_get_ciphers(VALUE self)
return ary;
}
-/*
- * call-seq:
- * ctx.ciphers = "cipher1:cipher2:..."
- * ctx.ciphers = [name, ...]
- * ctx.ciphers = [[name, version, bits, alg_bits], ...]
- *
- * Sets the list of available cipher suites for this context. Note in a server
- * context some ciphers require the appropriate certificates. For example, an
- * RSA cipher suite can only be chosen when an RSA certificate is available.
- */
static VALUE
-ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+build_cipher_string(VALUE v)
{
- SSL_CTX *ctx;
VALUE str, elem;
int i;
- rb_check_frozen(self);
- if (NIL_P(v))
- return v;
- else if (RB_TYPE_P(v, T_ARRAY)) {
+ if (RB_TYPE_P(v, T_ARRAY)) {
str = rb_str_new(0, 0);
for (i = 0; i < RARRAY_LEN(v); i++) {
elem = rb_ary_entry(v, i);
@@ -978,14 +1042,113 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
StringValue(str);
}
+ return str;
+}
+
+/*
+ * call-seq:
+ * ctx.ciphers = "cipher1:cipher2:..."
+ * ctx.ciphers = [name, ...]
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
+ *
+ * Sets the list of available cipher suites for this context. Note in a server
+ * context some ciphers require the appropriate certificates. For example, an
+ * RSA cipher suite can only be chosen when an RSA certificate is available.
+ */
+static VALUE
+ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ VALUE str;
+
+ rb_check_frozen(self);
+ if (NIL_P(v))
+ return v;
+
+ str = build_cipher_string(v);
+
GetSSLCTX(self, ctx);
- if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) {
+ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str)))
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
- }
return v;
}
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+/*
+ * call-seq:
+ * ctx.ciphersuites = "cipher1:cipher2:..."
+ * ctx.ciphersuites = [name, ...]
+ * ctx.ciphersuites = [[name, version, bits, alg_bits], ...]
+ *
+ * Sets the list of available TLSv1.3 cipher suites for this context.
+ */
+static VALUE
+ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ VALUE str;
+
+ rb_check_frozen(self);
+ if (NIL_P(v))
+ return v;
+
+ str = build_cipher_string(v);
+
+ GetSSLCTX(self, ctx);
+ if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str)))
+ ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites");
+
+ return v;
+}
+#endif
+
+#ifndef OPENSSL_NO_DH
+/*
+ * call-seq:
+ * ctx.tmp_dh = pkey
+ *
+ * Sets DH parameters used for ephemeral DH key exchange. This is relevant for
+ * servers only.
+ *
+ * +pkey+ is an instance of OpenSSL::PKey::DH. Note that key components
+ * contained in the key object, if any, are ignored. The server will always
+ * generate a new key pair for each handshake.
+ *
+ * Added in version 3.0. See also the man page SSL_set0_tmp_dh_pkey(3).
+ *
+ * Example:
+ * ctx = OpenSSL::SSL::SSLContext.new
+ * ctx.tmp_dh = OpenSSL::DH.generate(2048)
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx)
+ * Thread.new { svr.accept }
+ */
+static VALUE
+ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ EVP_PKEY *pkey;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ pkey = GetPKeyPtr(arg);
+
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
+ rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
+ OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
+#ifdef HAVE_SSL_SET0_TMP_DH_PKEY
+ if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
+ ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
+ EVP_PKEY_up_ref(pkey);
+#else
+ if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey)))
+ ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
+#endif
+
+ return arg;
+}
+#endif
+
#if !defined(OPENSSL_NO_EC)
/*
* call-seq:
@@ -1168,7 +1331,7 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
EVP_PKEY_free(pub_pkey);
if (!pub_pkey)
rb_raise(rb_eArgError, "certificate does not contain public key");
- if (EVP_PKEY_cmp(pub_pkey, pkey) != 1)
+ if (EVP_PKEY_eq(pub_pkey, pkey) != 1)
rb_raise(rb_eArgError, "public key mismatch");
if (argc >= 3)
@@ -1378,12 +1541,19 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
/*
* SSLSocket class
*/
-#ifndef OPENSSL_NO_SOCK
static inline int
ssl_started(SSL *ssl)
{
- /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */
- return SSL_get_fd(ssl) >= 0;
+ /* BIO is created through ossl_ssl_setup(), called by #connect or #accept */
+ return SSL_get_rbio(ssl) != NULL;
+}
+
+static void
+ossl_ssl_mark(void *ptr)
+{
+ SSL *ssl = ptr;
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
}
static void
@@ -1395,7 +1565,7 @@ ossl_ssl_free(void *ssl)
const rb_data_type_t ossl_ssl_type = {
"OpenSSL/SSL",
{
- 0, ossl_ssl_free,
+ ossl_ssl_mark, ossl_ssl_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
@@ -1465,6 +1635,7 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
if (rb_respond_to(io, rb_intern("nonblock=")))
rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
+ Check_Type(io, T_FILE);
rb_ivar_set(self, id_i_io, io);
ssl = SSL_new(ctx);
@@ -1532,11 +1703,16 @@ no_exception_p(VALUE opts)
return 0;
}
+// Provided by Ruby 3.2.0 and later in order to support the default IO#timeout.
+#ifndef RUBY_IO_TIMEOUT_DEFAULT
+#define RUBY_IO_TIMEOUT_DEFAULT Qnil
+#endif
+
static void
io_wait_writable(rb_io_t *fptr)
{
#ifdef HAVE_RB_IO_MAYBE_WAIT
- rb_io_maybe_wait_writable(errno, fptr->self, Qnil);
+ rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT);
#else
rb_io_wait_writable(fptr->fd);
#endif
@@ -1546,14 +1722,14 @@ static void
io_wait_readable(rb_io_t *fptr)
{
#ifdef HAVE_RB_IO_MAYBE_WAIT
- rb_io_maybe_wait_readable(errno, fptr->self, Qnil);
+ rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT);
#else
rb_io_wait_readable(fptr->fd);
#endif
}
static VALUE
-ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
+ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
{
SSL *ssl;
rb_io_t *fptr;
@@ -1620,6 +1796,7 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
err_msg, verify_msg);
}
#endif
+ /* fallthrough */
default:
ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s",
funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl));
@@ -1633,8 +1810,7 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
* call-seq:
* ssl.connect => self
*
- * Initiates an SSL/TLS handshake with a server. The handshake may be started
- * after unencrypted data has been sent over the socket.
+ * Initiates an SSL/TLS handshake with a server.
*/
static VALUE
ossl_ssl_connect(VALUE self)
@@ -1681,8 +1857,7 @@ ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
* call-seq:
* ssl.accept => self
*
- * Waits for a SSL/TLS client to initiate a handshake. The handshake may be
- * started after unencrypted data has been sent over the socket.
+ * Waits for a SSL/TLS client to initiate a handshake.
*/
static VALUE
ossl_ssl_accept(VALUE self)
@@ -1729,7 +1904,7 @@ static VALUE
ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
SSL *ssl;
- int ilen, nread = 0;
+ int ilen;
VALUE len, str;
rb_io_t *fptr;
VALUE io, opts = Qnil;
@@ -1739,6 +1914,9 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
} else {
rb_scan_args(argc, argv, "11", &len, &str);
}
+ GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ rb_raise(eSSLError, "SSL session is not started yet");
ilen = NUM2INT(len);
if (NIL_P(str))
@@ -1754,74 +1932,60 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
if (ilen == 0)
return str;
- GetSSL(self, ssl);
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
- if (ssl_started(ssl)) {
- for (;;){
- nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
- switch(ssl_get_error(ssl, nread)){
- case SSL_ERROR_NONE:
- goto end;
- case SSL_ERROR_ZERO_RETURN:
- if (no_exception_p(opts)) { return Qnil; }
- rb_eof_error();
- case SSL_ERROR_WANT_WRITE:
- if (no_exception_p(opts)) { return sym_wait_writable; }
+
+ rb_str_locktmp(str);
+ for (;;) {
+ int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
+ switch (ssl_get_error(ssl, nread)) {
+ case SSL_ERROR_NONE:
+ rb_str_unlocktmp(str);
+ rb_str_set_len(str, nread);
+ return str;
+ case SSL_ERROR_ZERO_RETURN:
+ rb_str_unlocktmp(str);
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ case SSL_ERROR_WANT_WRITE:
+ if (nonblock) {
+ rb_str_unlocktmp(str);
+ if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
- io_wait_writable(fptr);
- continue;
- case SSL_ERROR_WANT_READ:
- if (no_exception_p(opts)) { return sym_wait_readable; }
+ }
+ io_wait_writable(fptr);
+ continue;
+ case SSL_ERROR_WANT_READ:
+ if (nonblock) {
+ rb_str_unlocktmp(str);
+ if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
- io_wait_readable(fptr);
- continue;
- case SSL_ERROR_SYSCALL:
- if (!ERR_peek_error()) {
- if (errno)
- rb_sys_fail(0);
- else {
- /*
- * The underlying BIO returned 0. This is actually a
- * protocol error. But unfortunately, not all
- * implementations cleanly shutdown the TLS connection
- * but just shutdown/close the TCP connection. So report
- * EOF for now...
- */
- if (no_exception_p(opts)) { return Qnil; }
- rb_eof_error();
- }
- }
- /* fall through */
- default:
- ossl_raise(eSSLError, "SSL_read");
- }
+ }
+ io_wait_readable(fptr);
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if (!ERR_peek_error()) {
+ rb_str_unlocktmp(str);
+ if (errno)
+ rb_sys_fail(0);
+ else {
+ /*
+ * The underlying BIO returned 0. This is actually a
+ * protocol error. But unfortunately, not all
+ * implementations cleanly shutdown the TLS connection
+ * but just shutdown/close the TCP connection. So report
+ * EOF for now...
+ */
+ if (no_exception_p(opts)) { return Qnil; }
+ rb_eof_error();
+ }
+ }
+ /* fall through */
+ default:
+ rb_str_unlocktmp(str);
+ ossl_raise(eSSLError, "SSL_read");
}
}
- else {
- ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
-
- rb_warning("SSL session is not started yet.");
-#if defined(RB_PASS_KEYWORDS)
- if (nonblock) {
- VALUE argv[3];
- argv[0] = len;
- argv[1] = str;
- argv[2] = opts;
- return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS);
- }
-#else
- if (nonblock) {
- return rb_funcall(io, meth, 3, len, str, opts);
- }
-#endif
- else
- return rb_funcall(io, meth, 2, len, str);
- }
-
- end:
- rb_str_set_len(str, nread);
- return str;
}
/*
@@ -1861,77 +2025,55 @@ static VALUE
ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
{
SSL *ssl;
- int nwrite = 0;
rb_io_t *fptr;
- int nonblock = opts != Qfalse;
- VALUE io;
+ int num, nonblock = opts != Qfalse;
+ VALUE tmp, io;
- StringValue(str);
GetSSL(self, ssl);
+ if (!ssl_started(ssl))
+ rb_raise(eSSLError, "SSL session is not started yet");
+
+ tmp = rb_str_new_frozen(StringValue(str));
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
- if (ssl_started(ssl)) {
- for (;;){
- int num = RSTRING_LENINT(str);
-
- /* SSL_write(3ssl) manpage states num == 0 is undefined */
- if (num == 0)
- goto end;
-
- nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
- switch(ssl_get_error(ssl, nwrite)){
- case SSL_ERROR_NONE:
- goto end;
- case SSL_ERROR_WANT_WRITE:
- if (no_exception_p(opts)) { return sym_wait_writable; }
- write_would_block(nonblock);
- io_wait_writable(fptr);
- continue;
- case SSL_ERROR_WANT_READ:
- if (no_exception_p(opts)) { return sym_wait_readable; }
- read_would_block(nonblock);
- io_wait_readable(fptr);
- continue;
- case SSL_ERROR_SYSCALL:
+
+ /* SSL_write(3ssl) manpage states num == 0 is undefined */
+ num = RSTRING_LENINT(tmp);
+ if (num == 0)
+ return INT2FIX(0);
+
+ for (;;) {
+ int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num);
+ switch (ssl_get_error(ssl, nwritten)) {
+ case SSL_ERROR_NONE:
+ return INT2NUM(nwritten);
+ case SSL_ERROR_WANT_WRITE:
+ if (no_exception_p(opts)) { return sym_wait_writable; }
+ write_would_block(nonblock);
+ io_wait_writable(fptr);
+ continue;
+ case SSL_ERROR_WANT_READ:
+ if (no_exception_p(opts)) { return sym_wait_readable; }
+ read_would_block(nonblock);
+ io_wait_readable(fptr);
+ continue;
+ case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
- /*
- * It appears that send syscall can return EPROTOTYPE if the
- * socket is being torn down. Retry to get a proper errno to
- * make the error handling in line with the socket library.
- * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
- */
- if (errno == EPROTOTYPE)
- continue;
+ /*
+ * It appears that send syscall can return EPROTOTYPE if the
+ * socket is being torn down. Retry to get a proper errno to
+ * make the error handling in line with the socket library.
+ * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
+ */
+ if (errno == EPROTOTYPE)
+ continue;
#endif
- if (errno) rb_sys_fail(0);
- default:
- ossl_raise(eSSLError, "SSL_write");
- }
+ if (errno) rb_sys_fail(0);
+ /* fallthrough */
+ default:
+ ossl_raise(eSSLError, "SSL_write");
}
}
- else {
- ID meth = nonblock ?
- rb_intern("write_nonblock") : rb_intern("syswrite");
-
- rb_warning("SSL session is not started yet.");
-#if defined(RB_PASS_KEYWORDS)
- if (nonblock) {
- VALUE argv[2];
- argv[0] = str;
- argv[1] = opts;
- return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS);
- }
-#else
- if (nonblock) {
- return rb_funcall(io, meth, 2, str, opts);
- }
-#endif
- else
- return rb_funcall(io, meth, 1, str);
- }
-
- end:
- return INT2NUM(nwrite);
}
/*
@@ -2306,7 +2448,7 @@ ossl_ssl_get_client_ca_list(VALUE self)
return ossl_x509name_sk2ary(ca);
}
-# ifndef OPENSSL_NO_NEXTPROTONEG
+# ifdef OSSL_USE_NEXTPROTONEG
/*
* call-seq:
* ssl.npn_protocol => String | nil
@@ -2356,6 +2498,49 @@ ossl_ssl_alpn_protocol(VALUE self)
/*
* call-seq:
+ * session.export_keying_material(label, length) -> String
+ *
+ * Enables use of shared session key material in accordance with RFC 5705.
+ */
+static VALUE
+ossl_ssl_export_keying_material(int argc, VALUE *argv, VALUE self)
+{
+ SSL *ssl;
+ VALUE str;
+ VALUE label;
+ VALUE length;
+ VALUE context;
+ unsigned char *p;
+ size_t len;
+ int use_ctx = 0;
+ unsigned char *ctx = NULL;
+ size_t ctx_len = 0;
+ int ret;
+
+ rb_scan_args(argc, argv, "21", &label, &length, &context);
+ StringValue(label);
+
+ GetSSL(self, ssl);
+
+ len = (size_t)NUM2LONG(length);
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if (!NIL_P(context)) {
+ use_ctx = 1;
+ StringValue(context);
+ ctx = (unsigned char *)RSTRING_PTR(context);
+ ctx_len = RSTRING_LEN(context);
+ }
+ ret = SSL_export_keying_material(ssl, p, len, (char *)RSTRING_PTR(label),
+ RSTRING_LENINT(label), ctx, ctx_len, use_ctx);
+ if (ret == 0 || ret == -1) {
+ ossl_raise(eSSLError, "SSL_export_keying_material");
+ }
+ return str;
+}
+
+/*
+ * call-seq:
* ssl.tmp_key => PKey or nil
*
* Returns the ephemeral key used in case of forward secrecy cipher.
@@ -2383,6 +2568,7 @@ Init_ossl_ssl(void)
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
#endif
+#ifndef OPENSSL_NO_SOCK
id_call = rb_intern_const("call");
ID_callback_state = rb_intern_const("callback_state");
@@ -2405,16 +2591,6 @@ Init_ossl_ssl(void)
*/
mSSL = rb_define_module_under(mOSSL, "SSL");
- /* Document-module: OpenSSL::ExtConfig
- *
- * This module contains configuration information about the SSL extension,
- * for example if socket support is enabled, or the host name TLS extension
- * is enabled. Constants in this module will always be defined, but contain
- * +true+ or +false+ values depending on the configuration of your OpenSSL
- * installation.
- */
- mSSLExtConfig = rb_define_module_under(mOSSL, "ExtConfig");
-
/* Document-class: OpenSSL::SSL::SSLError
*
* Generic error class raised by SSLSocket and SSLContext.
@@ -2577,8 +2753,6 @@ Init_ossl_ssl(void)
*/
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 on an
* established connection. May be used to disable renegotiation entirely.
@@ -2599,7 +2773,7 @@ Init_ossl_ssl(void)
* end
*/
rb_attr(cSSLContext, rb_intern_const("renegotiation_cb"), 1, 1, Qfalse);
-#ifndef OPENSSL_NO_NEXTPROTONEG
+#ifdef OSSL_USE_NEXTPROTONEG
/*
* An Enumerable of Strings. Each String represents a protocol to be
* advertised as the list of supported protocols for Next Protocol
@@ -2661,12 +2835,41 @@ Init_ossl_ssl(void)
*/
rb_attr(cSSLContext, rb_intern_const("alpn_select_cb"), 1, 1, Qfalse);
+ /*
+ * A callback invoked when TLS key material is generated or received, in
+ * order to allow applications to store this keying material for debugging
+ * purposes.
+ *
+ * The callback is invoked with an SSLSocket and a string containing the
+ * key material in the format used by NSS for its SSLKEYLOGFILE debugging
+ * output.
+ *
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
+ *
+ * === Example
+ *
+ * context.keylog_cb = proc do |_sock, line|
+ * File.open('ssl_keylog_file', "a") do |f|
+ * f.write("#{line}\n")
+ * end
+ * end
+ */
+ rb_attr(cSSLContext, rb_intern_const("keylog_cb"), 1, 1, Qfalse);
+
rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
rb_define_private_method(cSSLContext, "set_minmax_proto_version",
ossl_sslctx_set_minmax_proto_version, 2);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+ rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1);
+#endif
+#ifndef OPENSSL_NO_DH
+ rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1);
+#endif
rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
@@ -2740,11 +2943,6 @@ Init_ossl_ssl(void)
* Document-class: OpenSSL::SSL::SSLSocket
*/
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
-#ifdef OPENSSL_NO_SOCK
- rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue);
- rb_define_method(cSSLSocket, "initialize", rb_f_notimplement, -1);
-#else
- rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
rb_undef_method(cSSLSocket, "initialize_copy");
@@ -2775,10 +2973,10 @@ Init_ossl_ssl(void)
rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0);
rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
-# ifndef OPENSSL_NO_NEXTPROTONEG
+ rb_define_method(cSSLSocket, "export_keying_material", ossl_ssl_export_keying_material, -1);
+# ifdef OSSL_USE_NEXTPROTONEG
rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
# endif
-#endif
rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE));
rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER));
@@ -2786,9 +2984,24 @@ Init_ossl_ssl(void)
rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE));
rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL));
+#ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT));
+#endif
rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT));
+#ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS));
+#endif
rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING));
rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG));
+#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF));
+#endif
+#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION));
+#endif
+#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */
+ rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES));
+#endif
#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */
rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX));
#endif
@@ -2800,13 +3013,15 @@ Init_ossl_ssl(void)
#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */
rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC));
#endif
- rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
- rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
-#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
- rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
+#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */
+ rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT));
+#endif
+#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */
+ rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA));
+#endif
+#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */
+ rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY));
#endif
- rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
-
rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3));
rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1));
rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1));
@@ -2814,6 +3029,12 @@ Init_ossl_ssl(void)
#ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */
rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3));
#endif
+ rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
+ rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
+#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
+ rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
+#endif
+ rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
/* SSL_OP_* flags for DTLS */
#if 0
@@ -2912,8 +3133,10 @@ Init_ossl_ssl(void)
DefIVarID(alpn_select_cb);
DefIVarID(servername_cb);
DefIVarID(verify_hostname);
+ DefIVarID(keylog_cb);
DefIVarID(io);
DefIVarID(context);
DefIVarID(hostname);
+#endif /* !defined(OPENSSL_NO_SOCK) */
}
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
index 92eb1365fe..139a474b04 100644
--- a/ext/openssl/ossl_ssl_session.c
+++ b/ext/openssl/ossl_ssl_session.c
@@ -4,6 +4,7 @@
#include "ossl.h"
+#ifndef OPENSSL_NO_SOCK
VALUE cSSLSession;
static VALUE eSSLSession;
@@ -299,6 +300,7 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
return ossl_membio2str(out);
}
+#endif /* !defined(OPENSSL_NO_SOCK) */
void Init_ossl_ssl_session(void)
{
@@ -307,6 +309,7 @@ void Init_ossl_ssl_session(void)
mSSL = rb_define_module_under(mOSSL, "SSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
+#ifndef OPENSSL_NO_SOCK
cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
@@ -324,4 +327,5 @@ void Init_ossl_ssl_session(void)
rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
+#endif /* !defined(OPENSSL_NO_SOCK) */
}
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
index 4654babfcf..b33ff10c10 100644
--- a/ext/openssl/ossl_ts.c
+++ b/ext/openssl/ossl_ts.c
@@ -146,6 +146,12 @@ obj_to_asn1obj(VALUE obj)
}
static VALUE
+obj_to_asn1obj_i(VALUE obj)
+{
+ return (VALUE)obj_to_asn1obj(obj);
+}
+
+static VALUE
get_asn1obj(ASN1_OBJECT *obj)
{
BIO *out;
@@ -205,8 +211,10 @@ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
in = ossl_obj2bio(&arg);
ts_req = d2i_TS_REQ_bio(in, &ts_req);
BIO_free(in);
- if (!ts_req)
+ if (!ts_req) {
+ DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp request");
+ }
DATA_PTR(self) = ts_req;
return self;
@@ -529,8 +537,10 @@ ossl_ts_resp_initialize(VALUE self, VALUE der)
in = ossl_obj2bio(&der);
ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
BIO_free(in);
- if (!ts_resp)
+ if (!ts_resp) {
+ DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp response");
+ }
DATA_PTR(self) = ts_resp;
return self;
@@ -816,7 +826,7 @@ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
X509_up_ref(cert);
}
- TS_VERIFY_CTS_set_certs(ctx, x509inter);
+ TS_VERIFY_CTX_set_certs(ctx, x509inter);
TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
TS_VERIFY_CTX_set_store(ctx, x509st);
@@ -868,8 +878,10 @@ ossl_ts_token_info_initialize(VALUE self, VALUE der)
in = ossl_obj2bio(&der);
info = d2i_TS_TST_INFO_bio(in, &info);
BIO_free(in);
- if (!info)
+ if (!info) {
+ DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
+ }
DATA_PTR(self) = info;
return self;
@@ -1071,13 +1083,29 @@ ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
}
static int
+#if !defined(LIBRESSL_VERSION_NUMBER)
ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
+#else
+ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
+#endif
{
*sec = *((long *)data);
*usec = 0;
return 1;
}
+static VALUE
+ossl_evp_get_digestbyname_i(VALUE arg)
+{
+ return (VALUE)ossl_evp_get_digestbyname(arg);
+}
+
+static VALUE
+ossl_obj2bio_i(VALUE arg)
+{
+ return (VALUE)ossl_obj2bio((VALUE *)arg);
+}
+
/*
* Creates a Response with the help of an OpenSSL::PKey, an
* OpenSSL::X509::Certificate and a Request.
@@ -1146,7 +1174,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
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);
+ def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status);
if (status)
goto end;
}
@@ -1188,7 +1216,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
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);
+ md = (const EVP_MD *)rb_protect(ossl_evp_get_digestbyname_i, rbmd, &status);
if (status)
goto end;
TS_RESP_CTX_add_md(ctx, md);
@@ -1199,7 +1227,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
if (status)
goto end;
- req_bio = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, (VALUE)&str, &status);
+ req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status);
if (status)
goto end;
@@ -1223,7 +1251,7 @@ end:
ASN1_OBJECT_free(def_policy_id_obj);
TS_RESP_CTX_free(ctx);
if (err_msg)
- ossl_raise(eTimestampError, err_msg);
+ rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg)));
if (status)
rb_jump_tag(status);
return ret;
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index 996f184170..9443541645 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -642,12 +642,12 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509(self, x509);
- while ((ext = X509_delete_ext(x509, 0)))
- X509_EXTENSION_free(ext);
+ for (i = X509_get_ext_count(x509); i > 0; i--)
+ X509_EXTENSION_free(X509_delete_ext(x509, 0));
for (i=0; i<RARRAY_LEN(ary); i++) {
ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, "X509_add_ext");
}
}
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 863f0286c0..6c1d915370 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -474,12 +474,12 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509CRL(self, crl);
- while ((ext = X509_CRL_delete_ext(crl, 0)))
- X509_EXTENSION_free(ext);
+ for (i = X509_CRL_get_ext_count(crl); i > 0; i--)
+ X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0));
for (i=0; i<RARRAY_LEN(ary); i++) {
ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */
if (!X509_CRL_add_ext(crl, ext, -1)) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, "X509_CRL_add_ext");
}
}
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 1522c3d897..13a2b2c030 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -291,7 +291,14 @@ x509name_print(VALUE self, unsigned long iflag)
* * OpenSSL::X509::Name::MULTILINE
*
* If _format_ is omitted, the largely broken and traditional OpenSSL format
- * is used.
+ * (<tt>X509_NAME_oneline()</tt> format) is chosen.
+ *
+ * <b>Use of this method is discouraged.</b> None of the formats other than
+ * OpenSSL::X509::Name::RFC2253 is standardized and may show an inconsistent
+ * behavior through \OpenSSL versions.
+ *
+ * It is recommended to use #to_utf8 instead, which is equivalent to calling
+ * <tt>name.to_s(OpenSSL::X509::Name::RFC2253).force_encoding("UTF-8")</tt>.
*/
static VALUE
ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
@@ -498,7 +505,7 @@ ossl_x509name_to_der(VALUE self)
* You can create a Name by parsing a distinguished name String or by
* supplying the distinguished name as an Array.
*
- * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
+ * name = OpenSSL::X509::Name.parse_rfc2253 'DC=example,CN=nobody'
*
* name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
*/
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index 6eb91e9c2f..77a7d3f2ff 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -380,13 +380,13 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary)
OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr);
}
GetX509Req(self, req);
- while ((attr = X509_REQ_delete_attr(req, 0)))
- X509_ATTRIBUTE_free(attr);
+ for (i = X509_REQ_get_attr_count(req); i > 0; i--)
+ X509_ATTRIBUTE_free(X509_REQ_delete_attr(req, 0));
for (i=0;i<RARRAY_LEN(ary); i++) {
item = RARRAY_AREF(ary, i);
attr = GetX509AttrPtr(item);
if (!X509_REQ_add1_attr(req, attr)) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, "X509_REQ_add1_attr");
}
}
return ary;
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index 5fe6853430..10b8aa4ad6 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -223,13 +223,13 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509Rev(self, rev);
- while ((ext = X509_REVOKED_delete_ext(rev, 0)))
- X509_EXTENSION_free(ext);
+ for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--)
+ X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0));
for (i=0; i<RARRAY_LEN(ary); i++) {
item = RARRAY_AREF(ary, i);
ext = GetX509ExtPtr(item);
if(!X509_REVOKED_add_ext(rev, ext, -1)) {
- ossl_raise(eX509RevError, NULL);
+ ossl_raise(eX509RevError, "X509_REVOKED_add_ext");
}
}
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 5e0ab8d850..7c546187c3 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -52,8 +52,15 @@ struct ossl_verify_cb_args {
};
static VALUE
-call_verify_cb_proc(struct ossl_verify_cb_args *args)
+ossl_x509stctx_new_i(VALUE arg)
{
+ return ossl_x509stctx_new((X509_STORE_CTX *)arg);
+}
+
+static VALUE
+call_verify_cb_proc(VALUE arg)
+{
+ struct ossl_verify_cb_args *args = (struct ossl_verify_cb_args *)arg;
return rb_funcall(args->proc, rb_intern("call"), 2,
args->preverify_ok, args->store_ctx);
}
@@ -69,7 +76,7 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
return ok;
ret = Qfalse;
- rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
+ rctx = rb_protect(ossl_x509stctx_new_i, (VALUE)ctx, &state);
if (state) {
rb_set_errinfo(Qnil);
rb_warn("StoreContext initialization failure");
@@ -78,7 +85,7 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
args.proc = proc;
args.preverify_ok = ok ? Qtrue : Qfalse;
args.store_ctx = rctx;
- ret = rb_protect((VALUE(*)(VALUE))call_verify_cb_proc, (VALUE)&args, &state);
+ ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state);
if (state) {
rb_set_errinfo(Qnil);
rb_warn("exception in verify_callback is ignored");
@@ -106,6 +113,13 @@ VALUE cX509StoreContext;
VALUE eX509StoreError;
static void
+ossl_x509store_mark(void *ptr)
+{
+ X509_STORE *store = ptr;
+ rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx));
+}
+
+static void
ossl_x509store_free(void *ptr)
{
X509_STORE_free(ptr);
@@ -114,7 +128,7 @@ ossl_x509store_free(void *ptr)
static const rb_data_type_t ossl_x509store_type = {
"OpenSSL/X509/STORE",
{
- 0, ossl_x509store_free,
+ ossl_x509store_mark, ossl_x509store_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
@@ -487,23 +501,16 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
}
/*
- * Public Functions
- */
-static void ossl_x509stctx_free(void*);
-
-
-static const rb_data_type_t ossl_x509stctx_type = {
- "OpenSSL/X509/STORE_CTX",
- {
- 0, ossl_x509stctx_free,
- },
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
-};
-
-/*
* Private functions
*/
static void
+ossl_x509stctx_mark(void *ptr)
+{
+ X509_STORE_CTX *ctx = ptr;
+ rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx));
+}
+
+static void
ossl_x509stctx_free(void *ptr)
{
X509_STORE_CTX *ctx = ptr;
@@ -514,6 +521,14 @@ ossl_x509stctx_free(void *ptr)
X509_STORE_CTX_free(ctx);
}
+static const rb_data_type_t ossl_x509stctx_type = {
+ "OpenSSL/X509/STORE_CTX",
+ {
+ ossl_x509stctx_mark, ossl_x509stctx_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
static VALUE
ossl_x509stctx_alloc(VALUE klass)
{
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
deleted file mode 100644
index 069acc8b14..0000000000
--- a/ext/openssl/ruby_missing.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 'OpenSSL for Ruby' project
- * Copyright (C) 2001-2003 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_RUBY_MISSING_H_)
-#define _OSSL_RUBY_MISSING_H_
-
-/* Ruby 2.4 */
-#ifndef RB_INTEGER_TYPE_P
-# define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM))
-#endif
-
-/* Ruby 2.5 */
-#ifndef ST2FIX
-# define RB_ST2FIX(h) LONG2FIX((long)(h))
-# define ST2FIX(h) RB_ST2FIX(h)
-#endif
-
-#endif /* _OSSL_RUBY_MISSING_H_ */
diff --git a/ext/pathname/depend b/ext/pathname/depend
index 3e94d794a9..a6b000e305 100644
--- a/ext/pathname/depend
+++ b/ext/pathname/depend
@@ -2,6 +2,20 @@
pathname.o: $(RUBY_EXTCONF_H)
pathname.o: $(arch_hdrdir)/ruby/config.h
pathname.o: $(hdrdir)/ruby.h
+pathname.o: $(hdrdir)/ruby/assert.h
+pathname.o: $(hdrdir)/ruby/backward.h
+pathname.o: $(hdrdir)/ruby/backward/2/assume.h
+pathname.o: $(hdrdir)/ruby/backward/2/attributes.h
+pathname.o: $(hdrdir)/ruby/backward/2/bool.h
+pathname.o: $(hdrdir)/ruby/backward/2/inttypes.h
+pathname.o: $(hdrdir)/ruby/backward/2/limits.h
+pathname.o: $(hdrdir)/ruby/backward/2/long_long.h
+pathname.o: $(hdrdir)/ruby/backward/2/stdalign.h
+pathname.o: $(hdrdir)/ruby/backward/2/stdarg.h
+pathname.o: $(hdrdir)/ruby/defines.h
+pathname.o: $(hdrdir)/ruby/encoding.h
+pathname.o: $(hdrdir)/ruby/intern.h
+pathname.o: $(hdrdir)/ruby/internal/abi.h
pathname.o: $(hdrdir)/ruby/internal/anyargs.h
pathname.o: $(hdrdir)/ruby/internal/arithmetic.h
pathname.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ pathname.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
pathname.o: $(hdrdir)/ruby/internal/ctype.h
pathname.o: $(hdrdir)/ruby/internal/dllexport.h
pathname.o: $(hdrdir)/ruby/internal/dosish.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/re.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/string.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+pathname.o: $(hdrdir)/ruby/internal/encoding/transcode.h
pathname.o: $(hdrdir)/ruby/internal/error.h
pathname.o: $(hdrdir)/ruby/internal/eval.h
pathname.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
pathname.o: $(hdrdir)/ruby/missing.h
pathname.o: $(hdrdir)/ruby/onigmo.h
pathname.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..7bdfd0eb39 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -338,6 +338,8 @@ class Pathname
#
# Appends a pathname fragment to +self+ to produce a new Pathname object.
+ # Since +other+ is considered as a path relative to +self+, if +other+ is
+ # an absolute path, the new Pathname object is created from just +other+.
#
# p1 = Pathname.new("/usr") # Pathname:/usr
# p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
@@ -399,6 +401,8 @@ class Pathname
#
# Joins the given pathnames onto +self+ to create a new Pathname object.
+ # This is effectively the same as using Pathname#+ to append +self+ and
+ # all arguments sequentially.
#
# path0 = Pathname.new("/usr") # Pathname:/usr
# path0 = path0.join("bin/ruby") # Pathname:/usr/bin/ruby
@@ -574,25 +578,26 @@ class Pathname # * Find *
end
+autoload(:FileUtils, 'fileutils')
+
class Pathname # * FileUtils *
# Creates a full path, including any intermediate directories that don't yet
# exist.
#
# See FileUtils.mkpath and FileUtils.mkdir_p
- def mkpath
- require 'fileutils'
- FileUtils.mkpath(@path)
+ def mkpath(mode: nil)
+ FileUtils.mkpath(@path, mode: mode)
nil
end
# Recursively deletes a directory, including all directories beneath it.
#
- # See FileUtils.rm_r
- def rmtree
+ # See FileUtils.rm_rf
+ def rmtree(noop: nil, verbose: nil, secure: nil)
# The name "rmtree" is borrowed from File::Path of Perl.
# File::Path provides "mkpath" and "rmtree".
require 'fileutils'
- FileUtils.rm_r(@path)
+ FileUtils.rm_rf(@path, noop: noop, verbose: verbose, secure: secure)
nil
end
end
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index 1d4ed2814b..8ee4bcec5b 100644
--- a/ext/pathname/pathname.c
+++ b/ext/pathname/pathname.c
@@ -35,6 +35,7 @@ static ID id_lchmod;
static ID id_lchown;
static ID id_link;
static ID id_lstat;
+static ID id_lutime;
static ID id_mkdir;
static ID id_mtime;
static ID id_open;
@@ -765,6 +766,19 @@ path_utime(VALUE self, VALUE atime, VALUE mtime)
}
/*
+ * Update the access and modification times of the file.
+ *
+ * Same as Pathname#utime, but does not follow symbolic links.
+ *
+ * See File.lutime.
+ */
+static VALUE
+path_lutime(VALUE self, VALUE atime, VALUE mtime)
+{
+ return rb_funcall(rb_cFile, id_lutime, 3, atime, mtime, get_strpath(self));
+}
+
+/*
* Returns the last component of the path.
*
* See File.basename.
@@ -1212,7 +1226,7 @@ path_entries(VALUE self)
ary = rb_funcall(rb_cDir, id_entries, 1, str);
ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE elt = RARRAY_AREF(ary, i);
+ VALUE elt = RARRAY_AREF(ary, i);
elt = rb_class_new_instance(1, &elt, klass);
rb_ary_store(ary, i, elt);
}
@@ -1274,6 +1288,7 @@ static VALUE
path_each_entry(VALUE self)
{
VALUE args[1];
+ RETURN_ENUMERATOR(self, 0, 0);
args[0] = get_strpath(self);
return rb_block_call(rb_cDir, id_foreach, 1, args, each_entry_i, rb_obj_class(self));
@@ -1464,6 +1479,7 @@ path_f_pathname(VALUE self, VALUE str)
* - #make_symlink(old)
* - #truncate(length)
* - #utime(atime, mtime)
+ * - #lutime(atime, mtime)
* - #basename(*args)
* - #dirname
* - #extname
@@ -1562,6 +1578,7 @@ Init_pathname(void)
rb_define_method(rb_cPathname, "make_symlink", path_make_symlink, 1);
rb_define_method(rb_cPathname, "truncate", path_truncate, 1);
rb_define_method(rb_cPathname, "utime", path_utime, 2);
+ rb_define_method(rb_cPathname, "lutime", path_lutime, 2);
rb_define_method(rb_cPathname, "basename", path_basename, -1);
rb_define_method(rb_cPathname, "dirname", path_dirname, 0);
rb_define_method(rb_cPathname, "extname", path_extname, 0);
@@ -1645,6 +1662,7 @@ InitVM_pathname(void)
id_lchown = rb_intern("lchown");
id_link = rb_intern("link");
id_lstat = rb_intern("lstat");
+ id_lutime = rb_intern("lutime");
id_mkdir = rb_intern("mkdir");
id_mtime = rb_intern("mtime");
id_open = rb_intern("open");
diff --git a/ext/pathname/pathname.gemspec b/ext/pathname/pathname.gemspec
index 317029afb1..92bc02b0db 100644
--- a/ext/pathname/pathname.gemspec
+++ b/ext/pathname/pathname.gemspec
@@ -1,13 +1,13 @@
Gem::Specification.new do |spec|
spec.name = "pathname"
- spec.version = "0.1.0"
+ spec.version = "0.2.1"
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.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
diff --git a/ext/psych/.gitignore b/ext/psych/.gitignore
new file mode 100644
index 0000000000..92946455b0
--- /dev/null
+++ b/ext/psych/.gitignore
@@ -0,0 +1 @@
+/yaml-[0-9]*.*.*
diff --git a/ext/psych/depend b/ext/psych/depend
index 07cfc7524a..78bde9a53d 100644
--- a/ext/psych/depend
+++ b/ext/psych/depend
@@ -1,31 +1,18 @@
-$(OBJS): $(YAML_H)
+$(TARGET_SO): $(LIBYAML)
+
+libyaml $(LIBYAML):
+ cd libyaml && $(MAKE)
+ $(AR) $(ARFLAGS) $(LIBYAML) $(LIBYAML_OBJDIR)/*.$(OBJEXT)
+ $(RANLIB) $(LIBYAML)
+
+clean-so::
+ -cd libyaml && $(MAKE) clean
+
+distclean-so::
+ -cd libyaml && $(MAKE) distclean
+ -$(Q)$(RMDIRS) libyaml/* libyaml
# AUTOGENERATED DEPENDENCIES START
-api.o: $(RUBY_EXTCONF_H)
-api.o: yaml/api.c
-api.o: yaml/config.h
-api.o: yaml/yaml.h
-api.o: yaml/yaml_private.h
-dumper.o: $(RUBY_EXTCONF_H)
-dumper.o: yaml/config.h
-dumper.o: yaml/dumper.c
-dumper.o: yaml/yaml.h
-dumper.o: yaml/yaml_private.h
-emitter.o: $(RUBY_EXTCONF_H)
-emitter.o: yaml/config.h
-emitter.o: yaml/emitter.c
-emitter.o: yaml/yaml.h
-emitter.o: yaml/yaml_private.h
-loader.o: $(RUBY_EXTCONF_H)
-loader.o: yaml/config.h
-loader.o: yaml/loader.c
-loader.o: yaml/yaml.h
-loader.o: yaml/yaml_private.h
-parser.o: $(RUBY_EXTCONF_H)
-parser.o: yaml/config.h
-parser.o: yaml/parser.c
-parser.o: yaml/yaml.h
-parser.o: yaml/yaml_private.h
psych.o: $(RUBY_EXTCONF_H)
psych.o: $(arch_hdrdir)/ruby/config.h
psych.o: $(hdrdir)/ruby.h
@@ -34,7 +21,6 @@ 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
@@ -43,6 +29,7 @@ psych.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych.o: $(hdrdir)/ruby/defines.h
psych.o: $(hdrdir)/ruby/encoding.h
psych.o: $(hdrdir)/ruby/intern.h
+psych.o: $(hdrdir)/ruby/internal/abi.h
psych.o: $(hdrdir)/ruby/internal/anyargs.h
psych.o: $(hdrdir)/ruby/internal/arithmetic.h
psych.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -112,6 +99,15 @@ psych.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
psych.o: $(hdrdir)/ruby/internal/ctype.h
psych.o: $(hdrdir)/ruby/internal/dllexport.h
psych.o: $(hdrdir)/ruby/internal/dosish.h
+psych.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych.o: $(hdrdir)/ruby/internal/encoding/transcode.h
psych.o: $(hdrdir)/ruby/internal/error.h
psych.o: $(hdrdir)/ruby/internal/eval.h
psych.o: $(hdrdir)/ruby/internal/event.h
@@ -194,7 +190,6 @@ psych.o: psych_emitter.h
psych.o: psych_parser.h
psych.o: psych_to_ruby.h
psych.o: psych_yaml_tree.h
-psych.o: yaml/yaml.h
psych_emitter.o: $(RUBY_EXTCONF_H)
psych_emitter.o: $(arch_hdrdir)/ruby/config.h
psych_emitter.o: $(hdrdir)/ruby.h
@@ -203,7 +198,6 @@ 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
@@ -212,6 +206,7 @@ psych_emitter.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_emitter.o: $(hdrdir)/ruby/defines.h
psych_emitter.o: $(hdrdir)/ruby/encoding.h
psych_emitter.o: $(hdrdir)/ruby/intern.h
+psych_emitter.o: $(hdrdir)/ruby/internal/abi.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
@@ -281,6 +276,15 @@ psych_emitter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
psych_emitter.o: $(hdrdir)/ruby/internal/ctype.h
psych_emitter.o: $(hdrdir)/ruby/internal/dllexport.h
psych_emitter.o: $(hdrdir)/ruby/internal/dosish.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_emitter.o: $(hdrdir)/ruby/internal/encoding/transcode.h
psych_emitter.o: $(hdrdir)/ruby/internal/error.h
psych_emitter.o: $(hdrdir)/ruby/internal/eval.h
psych_emitter.o: $(hdrdir)/ruby/internal/event.h
@@ -363,7 +367,6 @@ psych_emitter.o: psych_emitter.h
psych_emitter.o: psych_parser.h
psych_emitter.o: psych_to_ruby.h
psych_emitter.o: psych_yaml_tree.h
-psych_emitter.o: yaml/yaml.h
psych_parser.o: $(RUBY_EXTCONF_H)
psych_parser.o: $(arch_hdrdir)/ruby/config.h
psych_parser.o: $(hdrdir)/ruby.h
@@ -372,7 +375,6 @@ 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
@@ -381,6 +383,7 @@ psych_parser.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_parser.o: $(hdrdir)/ruby/defines.h
psych_parser.o: $(hdrdir)/ruby/encoding.h
psych_parser.o: $(hdrdir)/ruby/intern.h
+psych_parser.o: $(hdrdir)/ruby/internal/abi.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
@@ -450,6 +453,15 @@ psych_parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
psych_parser.o: $(hdrdir)/ruby/internal/ctype.h
psych_parser.o: $(hdrdir)/ruby/internal/dllexport.h
psych_parser.o: $(hdrdir)/ruby/internal/dosish.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_parser.o: $(hdrdir)/ruby/internal/encoding/transcode.h
psych_parser.o: $(hdrdir)/ruby/internal/error.h
psych_parser.o: $(hdrdir)/ruby/internal/eval.h
psych_parser.o: $(hdrdir)/ruby/internal/event.h
@@ -532,7 +544,6 @@ psych_parser.o: psych_parser.c
psych_parser.o: psych_parser.h
psych_parser.o: psych_to_ruby.h
psych_parser.o: psych_yaml_tree.h
-psych_parser.o: yaml/yaml.h
psych_to_ruby.o: $(RUBY_EXTCONF_H)
psych_to_ruby.o: $(arch_hdrdir)/ruby/config.h
psych_to_ruby.o: $(hdrdir)/ruby.h
@@ -541,7 +552,6 @@ 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
@@ -550,6 +560,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_to_ruby.o: $(hdrdir)/ruby/defines.h
psych_to_ruby.o: $(hdrdir)/ruby/encoding.h
psych_to_ruby.o: $(hdrdir)/ruby/intern.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/abi.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
@@ -619,6 +630,15 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/ctype.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/dllexport.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/dosish.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/encoding/transcode.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/error.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/eval.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/event.h
@@ -701,7 +721,6 @@ psych_to_ruby.o: psych_parser.h
psych_to_ruby.o: psych_to_ruby.c
psych_to_ruby.o: psych_to_ruby.h
psych_to_ruby.o: psych_yaml_tree.h
-psych_to_ruby.o: yaml/yaml.h
psych_yaml_tree.o: $(RUBY_EXTCONF_H)
psych_yaml_tree.o: $(arch_hdrdir)/ruby/config.h
psych_yaml_tree.o: $(hdrdir)/ruby.h
@@ -710,7 +729,6 @@ 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
@@ -719,6 +737,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_yaml_tree.o: $(hdrdir)/ruby/defines.h
psych_yaml_tree.o: $(hdrdir)/ruby/encoding.h
psych_yaml_tree.o: $(hdrdir)/ruby/intern.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/abi.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
@@ -788,6 +807,15 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/ctype.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/dllexport.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/dosish.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/re.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/string.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/encoding/transcode.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/error.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/eval.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/event.h
@@ -870,20 +898,4 @@ psych_yaml_tree.o: psych_parser.h
psych_yaml_tree.o: psych_to_ruby.h
psych_yaml_tree.o: psych_yaml_tree.c
psych_yaml_tree.o: psych_yaml_tree.h
-psych_yaml_tree.o: yaml/yaml.h
-reader.o: $(RUBY_EXTCONF_H)
-reader.o: yaml/config.h
-reader.o: yaml/reader.c
-reader.o: yaml/yaml.h
-reader.o: yaml/yaml_private.h
-scanner.o: $(RUBY_EXTCONF_H)
-scanner.o: yaml/config.h
-scanner.o: yaml/scanner.c
-scanner.o: yaml/yaml.h
-scanner.o: yaml/yaml_private.h
-writer.o: $(RUBY_EXTCONF_H)
-writer.o: yaml/config.h
-writer.o: yaml/writer.c
-writer.o: yaml/yaml.h
-writer.o: yaml/yaml_private.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/psych/extconf.rb b/ext/psych/extconf.rb
index 857f8e68c4..41daf8c238 100644
--- a/ext/psych/extconf.rb
+++ b/ext/psych/extconf.rb
@@ -1,43 +1,53 @@
# -*- coding: us-ascii -*-
# frozen_string_literal: true
require 'mkmf'
-require 'fileutils'
-# :stopdoc:
-
-dir_config 'libyaml'
-
-if enable_config("bundled-libyaml", false) || !(find_header('yaml.h') && find_library('yaml', 'yaml_get_version'))
- # Embed libyaml since we could not find it.
-
- $VPATH << "$(srcdir)/yaml"
- $INCFLAGS << " -I$(srcdir)/yaml"
-
- $srcs = Dir.glob("#{$srcdir}/{,yaml/}*.c").map {|n| File.basename(n)}.sort
+if $mswin or $mingw or $cygwin
+ $CPPFLAGS << " -DYAML_DECLARE_STATIC"
+end
- header = 'yaml/yaml.h'
- header = "{$(VPATH)}#{header}" if $nmake
- if have_macro("_WIN32")
- $CPPFLAGS << " -DYAML_DECLARE_STATIC -DHAVE_CONFIG_H"
+yaml_source = with_config("libyaml-source-dir")
+if yaml_source
+ yaml_source = yaml_source.gsub(/\$\((\w+)\)|\$\{(\w+)\}/) {ENV[$1||$2]}
+ yaml_source = yaml_source.chomp("/")
+ yaml_configure = "#{File.expand_path(yaml_source)}/configure"
+ unless File.exist?(yaml_configure)
+ raise "Configure script not found in #{yaml_source.quote}"
end
- have_header 'dlfcn.h'
- have_header 'inttypes.h'
- have_header 'memory.h'
- have_header 'stdint.h'
- have_header 'stdlib.h'
- have_header 'strings.h'
- have_header 'string.h'
- have_header 'sys/stat.h'
- have_header 'sys/types.h'
- have_header 'unistd.h'
-
- find_header 'yaml.h'
- have_header 'config.h'
+ puts("Configuring libyaml source in #{yaml_source.quote}")
+ yaml = "libyaml"
+ Dir.mkdir(yaml) unless File.directory?(yaml)
+ shared = $enable_shared || !$static
+ args = [
+ yaml_configure,
+ "--enable-#{shared ? 'shared' : 'static'}",
+ "--host=#{RbConfig::CONFIG['host'].sub(/-unknown-/, '-')}",
+ "CC=#{RbConfig::CONFIG['CC']}",
+ *(["CFLAGS=-w"] if RbConfig::CONFIG["GCC"] == "yes"),
+ ]
+ puts(args.quote.join(' '))
+ unless system(*args, chdir: yaml)
+ raise "failed to configure libyaml"
+ end
+ inc = yaml_source.start_with?("#$srcdir/") ? "$(srcdir)#{yaml_source[$srcdir.size..-1]}" : yaml_source
+ $INCFLAGS << " -I#{yaml}/include -I#{inc}/include"
+ puts("INCFLAGS=#$INCFLAGS")
+ libyaml = "libyaml.#$LIBEXT"
+ $cleanfiles << libyaml
+ $LOCAL_LIBS.prepend("$(LIBYAML) ")
+else # default to pre-installed libyaml
+ pkg_config('yaml-0.1')
+ dir_config('libyaml')
+ find_header('yaml.h') or abort "yaml.h not found"
+ find_library('yaml', 'yaml_get_version') or abort "libyaml not found"
end
create_makefile 'psych' do |mk|
- mk << "YAML_H = #{header}".strip << "\n"
+ mk << "LIBYAML = #{libyaml}".strip << "\n"
+ mk << "LIBYAML_OBJDIR = libyaml/src#{shared ? '/.libs' : ''}\n"
+ mk << "OBJEXT = #$OBJEXT"
+ mk << "RANLIB = #{config_string('RANLIB') || config_string('NULLCMD')}\n"
end
# :startdoc:
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index ecf3b3927e..4a2ab58514 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'psych/versions'
+require_relative 'psych/versions'
case RUBY_ENGINE
when 'jruby'
- require 'psych_jars'
+ require_relative 'psych_jars'
if JRuby::Util.respond_to?(:load_ext)
JRuby::Util.load_ext('org.jruby.ext.psych.PsychLibrary')
else
@@ -12,21 +12,21 @@ when 'jruby'
else
require 'psych.so'
end
-require 'psych/nodes'
-require 'psych/streaming'
-require 'psych/visitors'
-require 'psych/handler'
-require 'psych/tree_builder'
-require 'psych/parser'
-require 'psych/omap'
-require 'psych/set'
-require 'psych/coder'
-require 'psych/core_ext'
-require 'psych/stream'
-require 'psych/json/tree_builder'
-require 'psych/json/stream'
-require 'psych/handlers/document_stream'
-require 'psych/class_loader'
+require_relative 'psych/nodes'
+require_relative 'psych/streaming'
+require_relative 'psych/visitors'
+require_relative 'psych/handler'
+require_relative 'psych/tree_builder'
+require_relative 'psych/parser'
+require_relative 'psych/omap'
+require_relative 'psych/set'
+require_relative 'psych/coder'
+require_relative 'psych/core_ext'
+require_relative 'psych/stream'
+require_relative 'psych/json/tree_builder'
+require_relative 'psych/json/stream'
+require_relative 'psych/handlers/document_stream'
+require_relative 'psych/class_loader'
###
# = Overview
@@ -268,12 +268,11 @@ module Psych
# YAML documents that are supplied via user input. Instead, please use the
# load method or the safe_load method.
#
- def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false
+ def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false
result = parse(yaml, filename: filename)
return fallback unless result
- result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer)
end
- class << self; alias :load :unsafe_load; end
###
# Safely load the yaml string in +yaml+. By default, only the following
@@ -308,7 +307,7 @@ module Psych
# A Psych::DisallowedClass exception will be raised if the yaml contains a
# class that isn't in the +permitted_classes+ list.
#
- # A Psych::BadAlias exception will be raised if the yaml contains aliases
+ # A Psych::AliasesNotEnabled exception will be raised if the yaml contains aliases
# but the +aliases+ keyword argument is set to false.
#
# +filename+ will be used in the exception message if any exception is raised
@@ -320,13 +319,13 @@ module Psych
# Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
# Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
#
- def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
+ def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false
result = parse(yaml, filename: filename)
return fallback unless result
class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
permitted_symbols.map(&:to_s))
- scanner = ScalarScanner.new class_loader
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
visitor = if aliases
Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
else
@@ -366,14 +365,15 @@ module Psych
# Raises a TypeError when `yaml` parameter is NilClass. This method is
# similar to `safe_load` except that `Symbol` objects are allowed by default.
#
- def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
+ def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false
safe_load yaml, permitted_classes: permitted_classes,
permitted_symbols: permitted_symbols,
aliases: aliases,
filename: filename,
fallback: fallback,
symbolize_names: symbolize_names,
- freeze: freeze
+ freeze: freeze,
+ strict_integer: strict_integer
end
###
diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb
index 088373cd66..c2e4ea4c93 100644
--- a/ext/psych/lib/psych/class_loader.rb
+++ b/ext/psych/lib/psych/class_loader.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'psych/omap'
-require 'psych/set'
+require_relative 'omap'
+require_relative 'set'
module Psych
class ClassLoader # :nodoc:
diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb
index 81055cc501..0721a133c3 100644
--- a/ext/psych/lib/psych/core_ext.rb
+++ b/ext/psych/lib/psych/core_ext.rb
@@ -15,5 +15,5 @@ class Object
end
if defined?(::IRB)
- require 'psych/y'
+ require_relative 'y'
end
diff --git a/ext/psych/lib/psych/exception.rb b/ext/psych/lib/psych/exception.rb
index f473b95a3b..d7469a4b30 100644
--- a/ext/psych/lib/psych/exception.rb
+++ b/ext/psych/lib/psych/exception.rb
@@ -6,6 +6,20 @@ module Psych
class BadAlias < Exception
end
+ # Subclasses `BadAlias` for backwards compatibility
+ class AliasesNotEnabled < BadAlias
+ def initialize
+ super "Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`."
+ end
+ end
+
+ # Subclasses `BadAlias` for backwards compatibility
+ class AnchorNotDefined < BadAlias
+ def initialize anchor_name
+ super "An alias referenced an unknown anchor: #{anchor_name}"
+ end
+ end
+
class DisallowedClass < Exception
def initialize action, klass_name
super "Tried to #{action} unspecified class: #{klass_name}"
diff --git a/ext/psych/lib/psych/handlers/document_stream.rb b/ext/psych/lib/psych/handlers/document_stream.rb
index 67da794093..b77115d074 100644
--- a/ext/psych/lib/psych/handlers/document_stream.rb
+++ b/ext/psych/lib/psych/handlers/document_stream.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/tree_builder'
+require_relative '../tree_builder'
module Psych
module Handlers
diff --git a/ext/psych/lib/psych/handlers/recorder.rb b/ext/psych/lib/psych/handlers/recorder.rb
index a8fc7b1144..c98724cb76 100644
--- a/ext/psych/lib/psych/handlers/recorder.rb
+++ b/ext/psych/lib/psych/handlers/recorder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/handler'
+require_relative '../handler'
module Psych
module Handlers
diff --git a/ext/psych/lib/psych/json/stream.rb b/ext/psych/lib/psych/json/stream.rb
index 2ebd3d7a66..24dd4b9baf 100644
--- a/ext/psych/lib/psych/json/stream.rb
+++ b/ext/psych/lib/psych/json/stream.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'psych/json/ruby_events'
-require 'psych/json/yaml_events'
+require_relative 'ruby_events'
+require_relative 'yaml_events'
module Psych
module JSON
diff --git a/ext/psych/lib/psych/json/tree_builder.rb b/ext/psych/lib/psych/json/tree_builder.rb
index 5c2ee8ca25..9a45f6b94c 100644
--- a/ext/psych/lib/psych/json/tree_builder.rb
+++ b/ext/psych/lib/psych/json/tree_builder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/json/yaml_events'
+require_relative 'yaml_events'
module Psych
module JSON
diff --git a/ext/psych/lib/psych/nodes.rb b/ext/psych/lib/psych/nodes.rb
index 5842c2e3e5..2fa52e0055 100644
--- a/ext/psych/lib/psych/nodes.rb
+++ b/ext/psych/lib/psych/nodes.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
-require 'psych/nodes/node'
-require 'psych/nodes/stream'
-require 'psych/nodes/document'
-require 'psych/nodes/sequence'
-require 'psych/nodes/scalar'
-require 'psych/nodes/mapping'
-require 'psych/nodes/alias'
+require_relative 'nodes/node'
+require_relative 'nodes/stream'
+require_relative 'nodes/document'
+require_relative 'nodes/sequence'
+require_relative 'nodes/scalar'
+require_relative 'nodes/mapping'
+require_relative 'nodes/alias'
module Psych
###
diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb
index 05cb08dac0..f44fce5f05 100644
--- a/ext/psych/lib/psych/nodes/node.rb
+++ b/ext/psych/lib/psych/nodes/node.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'stringio'
-require 'psych/class_loader'
-require 'psych/scalar_scanner'
+require_relative '../class_loader'
+require_relative '../scalar_scanner'
module Psych
module Nodes
@@ -46,8 +46,8 @@ module Psych
# Convert this node to Ruby.
#
# See also Psych::Visitors::ToRuby
- def to_ruby(symbolize_names: false, freeze: false)
- Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze).accept(self)
+ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self)
end
alias :transform :to_ruby
diff --git a/ext/psych/lib/psych/parser.rb b/ext/psych/lib/psych/parser.rb
index 39bc8289be..2181c730e5 100644
--- a/ext/psych/lib/psych/parser.rb
+++ b/ext/psych/lib/psych/parser.rb
@@ -48,5 +48,18 @@ module Psych
@handler = handler
@external_encoding = ANY
end
+
+ ###
+ # call-seq:
+ # parser.parse(yaml)
+ #
+ # Parse the YAML document contained in +yaml+. Events will be called on
+ # the handler set on the parser instance.
+ #
+ # See Psych::Parser and Psych::Parser#handler
+
+ def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>"
+ _native_parse @handler, yaml, path
+ end
end
end
diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb
index d565a336e8..3cb4bf3c7e 100644
--- a/ext/psych/lib/psych/scalar_scanner.rb
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'strscan'
module Psych
###
@@ -9,32 +8,39 @@ module Psych
TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/
# Taken from http://yaml.org/type/float.html
- FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
- |[-+]?\.(inf|Inf|INF)(?# infinity)
- |\.(nan|NaN|NAN)(?# not a number))$/x
+ # Base 60, [-+]inf and NaN are handled separately
+ FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
# Taken from http://yaml.org/type/int.html
- INTEGER = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
- |[-+]?0[0-7_,]+ (?# base 8)
- |[-+]?(?:0|[1-9][0-9_,]*) (?# base 10)
- |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
+ INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2)
+ |[-+]?0[0-7_]+ (?# base 8)
+ |[-+]?(0|[1-9][0-9_]*) (?# base 10)
+ |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
+
+ # Same as above, but allows commas.
+ # Not to YML spec, but kept for backwards compatibility
+ INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
+ |[-+]?0[0-7_,]+ (?# base 8)
+ |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
+ |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
attr_reader :class_loader
# Create a new scanner
- def initialize class_loader
+ def initialize class_loader, strict_integer: false
@symbol_cache = {}
@class_loader = class_loader
+ @strict_integer = strict_integer
end
# Tokenize +string+ returning the Ruby object
def tokenize string
return nil if string.empty?
return @symbol_cache[string] if @symbol_cache.key?(string)
-
+ integer_regex = @strict_integer ? INTEGER_STRICT : INTEGER_LEGACY
# Check for a String type, being careful not to get caught by hash keys, hex values, and
# special floats (e.g., -.inf).
- if string.match?(/^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/) || string.match?(/\n/)
+ if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
return string if string.length > 5
if string.match?(/^[^ytonf~]/i)
@@ -57,11 +63,11 @@ module Psych
elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
require 'date'
begin
- class_loader.date.strptime(string, '%Y-%m-%d')
+ class_loader.date.strptime(string, '%F', Date::GREGORIAN)
rescue ArgumentError
string
end
- elsif string.match?(/^\.inf$/i)
+ elsif string.match?(/^\+?\.inf$/i)
Float::INFINITY
elsif string.match?(/^-\.inf$/i)
-Float::INFINITY
@@ -89,9 +95,9 @@ module Psych
if string.match?(/\A[-+]?\.\Z/)
string
else
- Float(string.gsub(/[,_]|\.([Ee]|$)/, '\1'))
+ Float(string.delete(',_').gsub(/\.([Ee]|$)/, '\1'))
end
- elsif string.match?(INTEGER)
+ elsif string.match?(integer_regex)
parse_int string
else
string
@@ -101,7 +107,7 @@ module Psych
###
# Parse and return an int from +string+
def parse_int string
- Integer(string.gsub(/[,_]/, ''))
+ Integer(string.delete(',_'))
end
###
diff --git a/ext/psych/lib/psych/syntax_error.rb b/ext/psych/lib/psych/syntax_error.rb
index 1598e6ff36..a4c9c4a376 100644
--- a/ext/psych/lib/psych/syntax_error.rb
+++ b/ext/psych/lib/psych/syntax_error.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/exception'
+require_relative 'exception'
module Psych
class SyntaxError < Psych::Exception
diff --git a/ext/psych/lib/psych/tree_builder.rb b/ext/psych/lib/psych/tree_builder.rb
index 47a1695643..414ca02bf7 100644
--- a/ext/psych/lib/psych/tree_builder.rb
+++ b/ext/psych/lib/psych/tree_builder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/handler'
+require_relative 'handler'
module Psych
###
diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb
index 513d010903..a592a6916c 100644
--- a/ext/psych/lib/psych/versions.rb
+++ b/ext/psych/lib/psych/versions.rb
@@ -2,9 +2,9 @@
module Psych
# The version of Psych you are using
- VERSION = '4.0.1'
+ VERSION = '5.0.1'
if RUBY_ENGINE == 'jruby'
- DEFAULT_SNAKEYAML_VERSION = '1.28'.freeze
+ DEFAULT_SNAKEYAML_VERSION = '1.33'.freeze
end
end
diff --git a/ext/psych/lib/psych/visitors.rb b/ext/psych/lib/psych/visitors.rb
index e2b084daee..508290d862 100644
--- a/ext/psych/lib/psych/visitors.rb
+++ b/ext/psych/lib/psych/visitors.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'psych/visitors/visitor'
-require 'psych/visitors/to_ruby'
-require 'psych/visitors/emitter'
-require 'psych/visitors/yaml_tree'
-require 'psych/visitors/json_tree'
-require 'psych/visitors/depth_first'
+require_relative 'visitors/visitor'
+require_relative 'visitors/to_ruby'
+require_relative 'visitors/emitter'
+require_relative 'visitors/yaml_tree'
+require_relative 'visitors/json_tree'
+require_relative 'visitors/depth_first'
diff --git a/ext/psych/lib/psych/visitors/json_tree.rb b/ext/psych/lib/psych/visitors/json_tree.rb
index 9912cb1362..979fc100bd 100644
--- a/ext/psych/lib/psych/visitors/json_tree.rb
+++ b/ext/psych/lib/psych/visitors/json_tree.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/json/ruby_events'
+require_relative '../json/ruby_events'
module Psych
module Visitors
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 4de7f80d33..8614251ca9 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'psych/scalar_scanner'
-require 'psych/class_loader'
-require 'psych/exception'
+require_relative '../scalar_scanner'
+require_relative '../class_loader'
+require_relative '../exception'
unless defined?(Regexp::NOENCODING)
Regexp::NOENCODING = 32
@@ -12,9 +12,9 @@ module Psych
###
# This class walks a YAML AST, converting each node to Ruby
class ToRuby < Psych::Visitors::Visitor
- def self.create(symbolize_names: false, freeze: false)
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false)
class_loader = ClassLoader.new
- scanner = ScalarScanner.new class_loader
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
end
@@ -80,7 +80,9 @@ module Psych
when "!ruby/object:DateTime"
class_loader.date_time
require 'date' unless defined? DateTime
- @ss.parse_time(o.value).to_datetime
+ t = @ss.parse_time(o.value)
+ DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
+ (t.subsec/86400)
when '!ruby/encoding'
::Encoding.find o.value
when "!ruby/object:Complex"
@@ -323,7 +325,7 @@ module Psych
end
def visit_Psych_Nodes_Alias o
- @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
+ @st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
end
private
@@ -427,7 +429,7 @@ module Psych
class NoAliasRuby < ToRuby
def visit_Psych_Nodes_Alias o
- raise BadAlias, "Unknown alias: #{o.anchor}"
+ raise AliasesNotEnabled
end
end
end
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
index 05748dd81c..31858798e4 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'psych/tree_builder'
-require 'psych/scalar_scanner'
-require 'psych/class_loader'
+require_relative '../tree_builder'
+require_relative '../scalar_scanner'
+require_relative '../class_loader'
module Psych
module Visitors
@@ -192,12 +192,13 @@ module Psych
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
end
+ def visit_Date o
+ register o, visit_Integer(o.gregorian)
+ end
+
def visit_DateTime o
- formatted = if o.offset.zero?
- o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
- else
- o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
- end
+ t = o.italy
+ formatted = format_time t, t.offset.zero?
tag = '!ruby/object:DateTime'
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
end
@@ -235,7 +236,6 @@ module Psych
end
alias :visit_TrueClass :visit_Integer
alias :visit_FalseClass :visit_Integer
- alias :visit_Date :visit_Integer
def visit_Float o
if o.nan?
@@ -272,6 +272,8 @@ module Psych
tag = 'tag:yaml.org,2002:str'
plain = false
quote = false
+ elsif o == 'y' || o == 'n'
+ style = Nodes::Scalar::DOUBLE_QUOTED
elsif @line_width && o.length > @line_width
style = Nodes::Scalar::FOLDED
elsif o =~ /^[^[:word:]][^"]*$/
@@ -480,8 +482,8 @@ module Psych
@emitter.end_mapping
end
- def format_time time
- if time.utc?
+ def format_time time, utc = time.utc?
+ if utc
time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
else
time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec
index e9e36e6633..5f5168ddb0 100644
--- a/ext/psych/psych.gemspec
+++ b/ext/psych/psych.gemspec
@@ -27,9 +27,6 @@ DESCRIPTION
"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",
- "ext/psych/yaml/LICENSE", "ext/psych/yaml/api.c", "ext/psych/yaml/config.h", "ext/psych/yaml/dumper.c",
- "ext/psych/yaml/emitter.c", "ext/psych/yaml/loader.c", "ext/psych/yaml/parser.c", "ext/psych/yaml/reader.c",
- "ext/psych/yaml/scanner.c", "ext/psych/yaml/writer.c", "ext/psych/yaml/yaml.h", "ext/psych/yaml/yaml_private.h",
"lib/psych.rb", "lib/psych/class_loader.rb", "lib/psych/coder.rb", "lib/psych/core_ext.rb", "lib/psych/exception.rb",
"lib/psych/handler.rb", "lib/psych/handlers/document_stream.rb", "lib/psych/handlers/recorder.rb",
"lib/psych/json/ruby_events.rb", "lib/psych/json/stream.rb", "lib/psych/json/tree_builder.rb",
@@ -63,5 +60,7 @@ DESCRIPTION
s.add_dependency 'jar-dependencies', '>= 0.1.7'
else
s.extensions = ["ext/psych/extconf.rb"]
+ s.add_dependency 'stringio'
end
+
end
diff --git a/ext/psych/psych_parser.c b/ext/psych/psych_parser.c
index fd550b671a..9c5179cc44 100644
--- a/ext/psych/psych_parser.c
+++ b/ext/psych/psych_parser.c
@@ -79,21 +79,25 @@ static VALUE allocate(VALUE klass)
static VALUE make_exception(yaml_parser_t * parser, VALUE path)
{
- size_t line, column;
- VALUE ePsychSyntaxError;
+ if (parser->error == YAML_MEMORY_ERROR) {
+ return rb_eNoMemError;
+ } else {
+ size_t line, column;
+ VALUE ePsychSyntaxError;
- line = parser->context_mark.line + 1;
- column = parser->context_mark.column + 1;
+ line = parser->context_mark.line + 1;
+ column = parser->context_mark.column + 1;
- ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
+ ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
- return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
- path,
- SIZET2NUM(line),
- SIZET2NUM(column),
- SIZET2NUM(parser->problem_offset),
- parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
- parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
+ return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
+ path,
+ SIZET2NUM(line),
+ SIZET2NUM(column),
+ SIZET2NUM(parser->problem_offset),
+ parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
+ parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
+ }
}
static VALUE transcode_string(VALUE src, int * parser_encoding)
@@ -241,18 +245,8 @@ static VALUE protected_event_location(VALUE pointer)
return rb_funcall3(args[0], id_event_location, 4, args + 1);
}
-/*
- * call-seq:
- * parser.parse(yaml)
- *
- * Parse the YAML document contained in +yaml+. Events will be called on
- * the handler set on the parser instance.
- *
- * See Psych::Parser and Psych::Parser#handler
- */
-static VALUE parse(int argc, VALUE *argv, VALUE self)
+static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
{
- VALUE yaml, path;
yaml_parser_t * parser;
yaml_event_t event;
int done = 0;
@@ -260,14 +254,6 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
int parser_encoding = YAML_ANY_ENCODING;
int encoding = rb_utf8_encindex();
rb_encoding * internal_enc = rb_default_internal_encoding();
- VALUE handler = rb_iv_get(self, "@handler");
-
- if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
- if(rb_respond_to(yaml, id_path))
- path = rb_funcall(yaml, id_path, 0);
- else
- path = rb_str_new2("<unknown>");
- }
TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
@@ -293,7 +279,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
VALUE event_args[5];
VALUE start_line, start_column, end_line, end_column;
- if(!yaml_parser_parse(parser, &event)) {
+ if(parser->error || !yaml_parser_parse(parser, &event)) {
VALUE exception;
exception = make_exception(parser, path);
@@ -558,7 +544,7 @@ void Init_psych_parser(void)
rb_require("psych/syntax_error");
- rb_define_method(cPsychParser, "parse", parse, -1);
+ rb_define_private_method(cPsychParser, "_native_parse", parse, 3);
rb_define_method(cPsychParser, "mark", mark, 0);
id_read = rb_intern("read");
diff --git a/ext/psych/yaml/api.c b/ext/psych/yaml/api.c
deleted file mode 100644
index 6add8b2661..0000000000
--- a/ext/psych/yaml/api.c
+++ /dev/null
@@ -1,1393 +0,0 @@
-
-#include "yaml_private.h"
-
-/*
- * Get the library version.
- */
-
-YAML_DECLARE(const char *)
-yaml_get_version_string(void)
-{
- return YAML_VERSION_STRING;
-}
-
-/*
- * Get the library version numbers.
- */
-
-YAML_DECLARE(void)
-yaml_get_version(int *major, int *minor, int *patch)
-{
- *major = YAML_VERSION_MAJOR;
- *minor = YAML_VERSION_MINOR;
- *patch = YAML_VERSION_PATCH;
-}
-
-/*
- * Allocate a dynamic memory block.
- */
-
-YAML_DECLARE(void *)
-yaml_malloc(size_t size)
-{
- return malloc(size ? size : 1);
-}
-
-/*
- * Reallocate a dynamic memory block.
- */
-
-YAML_DECLARE(void *)
-yaml_realloc(void *ptr, size_t size)
-{
- return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
-}
-
-/*
- * Free a dynamic memory block.
- */
-
-YAML_DECLARE(void)
-yaml_free(void *ptr)
-{
- if (ptr) free(ptr);
-}
-
-/*
- * Duplicate a string.
- */
-
-YAML_DECLARE(yaml_char_t *)
-yaml_strdup(const yaml_char_t *str)
-{
- if (!str)
- return NULL;
-
- return (yaml_char_t *)strdup((char *)str);
-}
-
-/*
- * Extend a string.
- */
-
-YAML_DECLARE(int)
-yaml_string_extend(yaml_char_t **start,
- yaml_char_t **pointer, yaml_char_t **end)
-{
- yaml_char_t *new_start = (yaml_char_t *)yaml_realloc((void*)*start, (*end - *start)*2);
-
- if (!new_start) return 0;
-
- memset(new_start + (*end - *start), 0, *end - *start);
-
- *pointer = new_start + (*pointer - *start);
- *end = new_start + (*end - *start)*2;
- *start = new_start;
-
- return 1;
-}
-
-/*
- * Append a string B to a string A.
- */
-
-YAML_DECLARE(int)
-yaml_string_join(
- yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
- yaml_char_t **b_start, yaml_char_t **b_pointer, SHIM(yaml_char_t **b_end))
-{
- UNUSED_PARAM(b_end)
- if (*b_start == *b_pointer)
- return 1;
-
- while (*a_end - *a_pointer <= *b_pointer - *b_start) {
- if (!yaml_string_extend(a_start, a_pointer, a_end))
- return 0;
- }
-
- memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
- *a_pointer += *b_pointer - *b_start;
-
- return 1;
-}
-
-/*
- * Extend a stack.
- */
-
-YAML_DECLARE(int)
-yaml_stack_extend(void **start, void **top, void **end)
-{
- 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;
-
- *top = (char *)new_start + ((char *)*top - (char *)*start);
- *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
- *start = new_start;
-
- return 1;
-}
-
-/*
- * Extend or move a queue.
- */
-
-YAML_DECLARE(int)
-yaml_queue_extend(void **start, void **head, void **tail, void **end)
-{
- /* Check if we need to resize the queue. */
-
- if (*start == *head && *tail == *end) {
- void *new_start = yaml_realloc(*start,
- ((char *)*end - (char *)*start)*2);
-
- if (!new_start) return 0;
-
- *head = (char *)new_start + ((char *)*head - (char *)*start);
- *tail = (char *)new_start + ((char *)*tail - (char *)*start);
- *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
- *start = new_start;
- }
-
- /* Check if we need to move the queue at the beginning of the buffer. */
-
- if (*tail == *end) {
- if (*head != *tail) {
- memmove(*start, *head, (char *)*tail - (char *)*head);
- }
- *tail = (char *)*tail - (char *)*head + (char *)*start;
- *head = *start;
- }
-
- return 1;
-}
-
-
-/*
- * Create a new parser object.
- */
-
-YAML_DECLARE(int)
-yaml_parser_initialize(yaml_parser_t *parser)
-{
- assert(parser); /* Non-NULL parser object expected. */
-
- memset(parser, 0, sizeof(yaml_parser_t));
- if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
- goto error;
- if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
- goto error;
- if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE, yaml_token_t*))
- goto error;
- if (!STACK_INIT(parser, parser->indents, int*))
- goto error;
- if (!STACK_INIT(parser, parser->simple_keys, yaml_simple_key_t*))
- goto error;
- if (!STACK_INIT(parser, parser->states, yaml_parser_state_t*))
- goto error;
- if (!STACK_INIT(parser, parser->marks, yaml_mark_t*))
- goto error;
- if (!STACK_INIT(parser, parser->tag_directives, yaml_tag_directive_t*))
- goto error;
-
- return 1;
-
-error:
-
- BUFFER_DEL(parser, parser->raw_buffer);
- BUFFER_DEL(parser, parser->buffer);
- QUEUE_DEL(parser, parser->tokens);
- STACK_DEL(parser, parser->indents);
- STACK_DEL(parser, parser->simple_keys);
- STACK_DEL(parser, parser->states);
- STACK_DEL(parser, parser->marks);
- STACK_DEL(parser, parser->tag_directives);
-
- return 0;
-}
-
-/*
- * Destroy a parser object.
- */
-
-YAML_DECLARE(void)
-yaml_parser_delete(yaml_parser_t *parser)
-{
- assert(parser); /* Non-NULL parser object expected. */
-
- BUFFER_DEL(parser, parser->raw_buffer);
- BUFFER_DEL(parser, parser->buffer);
- while (!QUEUE_EMPTY(parser, parser->tokens)) {
- yaml_token_delete(&DEQUEUE(parser, parser->tokens));
- }
- QUEUE_DEL(parser, parser->tokens);
- STACK_DEL(parser, parser->indents);
- STACK_DEL(parser, parser->simple_keys);
- STACK_DEL(parser, parser->states);
- STACK_DEL(parser, parser->marks);
- while (!STACK_EMPTY(parser, parser->tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
- STACK_DEL(parser, parser->tag_directives);
-
- memset(parser, 0, sizeof(yaml_parser_t));
-}
-
-/*
- * String read handler.
- */
-
-static int
-yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
- size_t *size_read)
-{
- yaml_parser_t *parser = (yaml_parser_t *)data;
-
- if (parser->input.string.current == parser->input.string.end) {
- *size_read = 0;
- return 1;
- }
-
- if (size > (size_t)(parser->input.string.end
- - parser->input.string.current)) {
- size = parser->input.string.end - parser->input.string.current;
- }
-
- memcpy(buffer, parser->input.string.current, size);
- parser->input.string.current += size;
- *size_read = size;
- return 1;
-}
-
-/*
- * File read handler.
- */
-
-static int
-yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
- size_t *size_read)
-{
- yaml_parser_t *parser = (yaml_parser_t *)data;
-
- *size_read = fread(buffer, 1, size, parser->input.file);
- return !ferror(parser->input.file);
-}
-
-/*
- * Set a string input.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_input_string(yaml_parser_t *parser,
- const unsigned char *input, size_t size)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->read_handler); /* You can set the source only once. */
- assert(input); /* Non-NULL input string expected. */
-
- parser->read_handler = yaml_string_read_handler;
- parser->read_handler_data = parser;
-
- parser->input.string.start = input;
- parser->input.string.current = input;
- parser->input.string.end = input+size;
-}
-
-/*
- * Set a file input.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->read_handler); /* You can set the source only once. */
- assert(file); /* Non-NULL file object expected. */
-
- parser->read_handler = yaml_file_read_handler;
- parser->read_handler_data = parser;
-
- parser->input.file = file;
-}
-
-/*
- * Set a generic input.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_input(yaml_parser_t *parser,
- yaml_read_handler_t *handler, void *data)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->read_handler); /* You can set the source only once. */
- assert(handler); /* Non-NULL read handler expected. */
-
- parser->read_handler = handler;
- parser->read_handler_data = data;
-}
-
-/*
- * Set the source encoding.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
-{
- assert(parser); /* Non-NULL parser object expected. */
- assert(!parser->encoding); /* Encoding is already set or detected. */
-
- parser->encoding = encoding;
-}
-
-/*
- * Create a new emitter object.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_initialize(yaml_emitter_t *emitter)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- memset(emitter, 0, sizeof(yaml_emitter_t));
- if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE))
- goto error;
- if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE))
- goto error;
- if (!STACK_INIT(emitter, emitter->states, yaml_emitter_state_t*))
- goto error;
- if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE, yaml_event_t*))
- goto error;
- if (!STACK_INIT(emitter, emitter->indents, int*))
- goto error;
- if (!STACK_INIT(emitter, emitter->tag_directives, yaml_tag_directive_t*))
- goto error;
-
- return 1;
-
-error:
-
- BUFFER_DEL(emitter, emitter->buffer);
- BUFFER_DEL(emitter, emitter->raw_buffer);
- STACK_DEL(emitter, emitter->states);
- QUEUE_DEL(emitter, emitter->events);
- STACK_DEL(emitter, emitter->indents);
- STACK_DEL(emitter, emitter->tag_directives);
-
- return 0;
-}
-
-/*
- * Destroy an emitter object.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_delete(yaml_emitter_t *emitter)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- BUFFER_DEL(emitter, emitter->buffer);
- BUFFER_DEL(emitter, emitter->raw_buffer);
- STACK_DEL(emitter, emitter->states);
- while (!QUEUE_EMPTY(emitter, emitter->events)) {
- yaml_event_delete(&DEQUEUE(emitter, emitter->events));
- }
- QUEUE_DEL(emitter, emitter->events);
- STACK_DEL(emitter, emitter->indents);
- while (!STACK_EMPTY(empty, emitter->tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
- STACK_DEL(emitter, emitter->tag_directives);
- yaml_free(emitter->anchors);
-
- memset(emitter, 0, sizeof(yaml_emitter_t));
-}
-
-/*
- * String write handler.
- */
-
-static int
-yaml_string_write_handler(void *data, unsigned char *buffer, size_t size)
-{
- yaml_emitter_t *emitter = (yaml_emitter_t *)data;
-
- if (emitter->output.string.size - *emitter->output.string.size_written
- < size) {
- memcpy(emitter->output.string.buffer
- + *emitter->output.string.size_written,
- buffer,
- emitter->output.string.size
- - *emitter->output.string.size_written);
- *emitter->output.string.size_written = emitter->output.string.size;
- return 0;
- }
-
- memcpy(emitter->output.string.buffer
- + *emitter->output.string.size_written, buffer, size);
- *emitter->output.string.size_written += size;
- return 1;
-}
-
-/*
- * File write handler.
- */
-
-static int
-yaml_file_write_handler(void *data, unsigned char *buffer, size_t size)
-{
- yaml_emitter_t *emitter = (yaml_emitter_t *)data;
-
- return (fwrite(buffer, 1, size, emitter->output.file) == size);
-}
-/*
- * Set a string output.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_output_string(yaml_emitter_t *emitter,
- unsigned char *output, size_t size, size_t *size_written)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->write_handler); /* You can set the output only once. */
- assert(output); /* Non-NULL output string expected. */
-
- emitter->write_handler = yaml_string_write_handler;
- emitter->write_handler_data = emitter;
-
- emitter->output.string.buffer = output;
- emitter->output.string.size = size;
- emitter->output.string.size_written = size_written;
- *size_written = 0;
-}
-
-/*
- * Set a file output.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->write_handler); /* You can set the output only once. */
- assert(file); /* Non-NULL file object expected. */
-
- emitter->write_handler = yaml_file_write_handler;
- emitter->write_handler_data = emitter;
-
- emitter->output.file = file;
-}
-
-/*
- * Set a generic output handler.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_output(yaml_emitter_t *emitter,
- yaml_write_handler_t *handler, void *data)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->write_handler); /* You can set the output only once. */
- assert(handler); /* Non-NULL handler object expected. */
-
- emitter->write_handler = handler;
- emitter->write_handler_data = data;
-}
-
-/*
- * Set the output encoding.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
- assert(!emitter->encoding); /* You can set encoding only once. */
-
- emitter->encoding = encoding;
-}
-
-/*
- * Set the canonical output style.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->canonical = (canonical != 0);
-}
-
-/*
- * Set the indentation increment.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
-}
-
-/*
- * Set the preferred line width.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->best_width = (width >= 0) ? width : -1;
-}
-
-/*
- * Set if unescaped non-ASCII characters are allowed.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->unicode = (unicode != 0);
-}
-
-/*
- * Set the preferred line break character.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
-{
- assert(emitter); /* Non-NULL emitter object expected. */
-
- emitter->line_break = line_break;
-}
-
-/*
- * Destroy a token object.
- */
-
-YAML_DECLARE(void)
-yaml_token_delete(yaml_token_t *token)
-{
- assert(token); /* Non-NULL token object expected. */
-
- switch (token->type)
- {
- case YAML_TAG_DIRECTIVE_TOKEN:
- yaml_free(token->data.tag_directive.handle);
- yaml_free(token->data.tag_directive.prefix);
- break;
-
- case YAML_ALIAS_TOKEN:
- yaml_free(token->data.alias.value);
- break;
-
- case YAML_ANCHOR_TOKEN:
- yaml_free(token->data.anchor.value);
- break;
-
- case YAML_TAG_TOKEN:
- yaml_free(token->data.tag.handle);
- yaml_free(token->data.tag.suffix);
- break;
-
- case YAML_SCALAR_TOKEN:
- yaml_free(token->data.scalar.value);
- break;
-
- default:
- break;
- }
-
- memset(token, 0, sizeof(yaml_token_t));
-}
-
-/*
- * Check if a string is a valid UTF-8 sequence.
- *
- * Check 'reader.c' for more details on UTF-8 encoding.
- */
-
-static int
-yaml_check_utf8(const yaml_char_t *start, size_t length)
-{
- const yaml_char_t *end = start+length;
- const yaml_char_t *pointer = start;
-
- while (pointer < end) {
- unsigned char octet;
- unsigned int width;
- unsigned int value;
- size_t k;
-
- octet = pointer[0];
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
- value = (octet & 0x80) == 0x00 ? octet & 0x7F :
- (octet & 0xE0) == 0xC0 ? octet & 0x1F :
- (octet & 0xF0) == 0xE0 ? octet & 0x0F :
- (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
- if (!width) return 0;
- if (pointer+width > end) return 0;
- for (k = 1; k < width; k ++) {
- octet = pointer[k];
- if ((octet & 0xC0) != 0x80) return 0;
- value = (value << 6) + (octet & 0x3F);
- }
- if (!((width == 1) ||
- (width == 2 && value >= 0x80) ||
- (width == 3 && value >= 0x800) ||
- (width == 4 && value >= 0x10000))) return 0;
-
- pointer += width;
- }
-
- return 1;
-}
-
-/*
- * Create STREAM-START.
- */
-
-YAML_DECLARE(int)
-yaml_stream_start_event_initialize(yaml_event_t *event,
- yaml_encoding_t encoding)
-{
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(event); /* Non-NULL event object is expected. */
-
- STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
-
- return 1;
-}
-
-/*
- * Create STREAM-END.
- */
-
-YAML_DECLARE(int)
-yaml_stream_end_event_initialize(yaml_event_t *event)
-{
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(event); /* Non-NULL event object is expected. */
-
- STREAM_END_EVENT_INIT(*event, mark, mark);
-
- return 1;
-}
-
-/*
- * Create DOCUMENT-START.
- */
-
-YAML_DECLARE(int)
-yaml_document_start_event_initialize(yaml_event_t *event,
- yaml_version_directive_t *version_directive,
- yaml_tag_directive_t *tag_directives_start,
- yaml_tag_directive_t *tag_directives_end,
- int implicit)
-{
- struct {
- yaml_error_type_t error;
- } context;
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_version_directive_t *version_directive_copy = NULL;
- struct {
- yaml_tag_directive_t *start;
- yaml_tag_directive_t *end;
- yaml_tag_directive_t *top;
- } tag_directives_copy = { NULL, NULL, NULL };
- yaml_tag_directive_t value = { NULL, NULL };
-
- assert(event); /* Non-NULL event object is expected. */
- assert((tag_directives_start && tag_directives_end) ||
- (tag_directives_start == tag_directives_end));
- /* Valid tag directives are expected. */
-
- if (version_directive) {
- version_directive_copy = YAML_MALLOC_STATIC(yaml_version_directive_t);
- if (!version_directive_copy) goto error;
- version_directive_copy->major = version_directive->major;
- version_directive_copy->minor = version_directive->minor;
- }
-
- if (tag_directives_start != tag_directives_end) {
- yaml_tag_directive_t *tag_directive;
- if (!STACK_INIT(&context, tag_directives_copy, yaml_tag_directive_t*))
- goto error;
- for (tag_directive = tag_directives_start;
- tag_directive != tag_directives_end; tag_directive ++) {
- assert(tag_directive->handle);
- assert(tag_directive->prefix);
- if (!yaml_check_utf8(tag_directive->handle,
- strlen((char *)tag_directive->handle)))
- goto error;
- if (!yaml_check_utf8(tag_directive->prefix,
- strlen((char *)tag_directive->prefix)))
- goto error;
- value.handle = yaml_strdup(tag_directive->handle);
- value.prefix = yaml_strdup(tag_directive->prefix);
- if (!value.handle || !value.prefix) goto error;
- if (!PUSH(&context, tag_directives_copy, value))
- goto error;
- value.handle = NULL;
- value.prefix = NULL;
- }
- }
-
- DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
- tag_directives_copy.start, tag_directives_copy.top,
- implicit, mark, mark);
-
- return 1;
-
-error:
- yaml_free(version_directive_copy);
- while (!STACK_EMPTY(context, tag_directives_copy)) {
- yaml_tag_directive_t value = POP(context, tag_directives_copy);
- yaml_free(value.handle);
- yaml_free(value.prefix);
- }
- STACK_DEL(context, tag_directives_copy);
- yaml_free(value.handle);
- yaml_free(value.prefix);
-
- return 0;
-}
-
-/*
- * Create DOCUMENT-END.
- */
-
-YAML_DECLARE(int)
-yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
-{
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(event); /* Non-NULL emitter object is expected. */
-
- DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark);
-
- return 1;
-}
-
-/*
- * Create ALIAS.
- */
-
-YAML_DECLARE(int)
-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;
-
- assert(event); /* Non-NULL event object is expected. */
- assert(anchor); /* Non-NULL anchor is expected. */
-
- if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0;
-
- anchor_copy = yaml_strdup(anchor);
- if (!anchor_copy)
- return 0;
-
- ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
-
- return 1;
-}
-
-/*
- * Create SCALAR.
- */
-
-YAML_DECLARE(int)
-yaml_scalar_event_initialize(yaml_event_t *event,
- 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)
-{
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_char_t *anchor_copy = NULL;
- yaml_char_t *tag_copy = NULL;
- yaml_char_t *value_copy = NULL;
-
- assert(event); /* Non-NULL event object is expected. */
- assert(value); /* Non-NULL anchor is expected. */
-
- if (anchor) {
- if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
- anchor_copy = yaml_strdup(anchor);
- if (!anchor_copy) goto error;
- }
-
- if (tag) {
- if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
- tag_copy = yaml_strdup(tag);
- if (!tag_copy) goto error;
- }
-
- if (length < 0) {
- length = (int)strlen((char *)value);
- }
-
- if (!yaml_check_utf8(value, length)) goto error;
- value_copy = YAML_MALLOC(length+1);
- if (!value_copy) goto error;
- memcpy(value_copy, value, length);
- value_copy[length] = '\0';
-
- SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
- plain_implicit, quoted_implicit, style, mark, mark);
-
- return 1;
-
-error:
- yaml_free(anchor_copy);
- yaml_free(tag_copy);
- yaml_free(value_copy);
-
- return 0;
-}
-
-/*
- * Create SEQUENCE-START.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_start_event_initialize(yaml_event_t *event,
- const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
- yaml_sequence_style_t style)
-{
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_char_t *anchor_copy = NULL;
- yaml_char_t *tag_copy = NULL;
-
- assert(event); /* Non-NULL event object is expected. */
-
- if (anchor) {
- if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
- anchor_copy = yaml_strdup(anchor);
- if (!anchor_copy) goto error;
- }
-
- if (tag) {
- if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
- tag_copy = yaml_strdup(tag);
- if (!tag_copy) goto error;
- }
-
- SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
- implicit, style, mark, mark);
-
- return 1;
-
-error:
- yaml_free(anchor_copy);
- yaml_free(tag_copy);
-
- return 0;
-}
-
-/*
- * Create SEQUENCE-END.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_end_event_initialize(yaml_event_t *event)
-{
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(event); /* Non-NULL event object is expected. */
-
- SEQUENCE_END_EVENT_INIT(*event, mark, mark);
-
- return 1;
-}
-
-/*
- * Create MAPPING-START.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_start_event_initialize(yaml_event_t *event,
- const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
- yaml_mapping_style_t style)
-{
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_char_t *anchor_copy = NULL;
- yaml_char_t *tag_copy = NULL;
-
- assert(event); /* Non-NULL event object is expected. */
-
- if (anchor) {
- if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
- anchor_copy = yaml_strdup(anchor);
- if (!anchor_copy) goto error;
- }
-
- if (tag) {
- if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
- tag_copy = yaml_strdup(tag);
- if (!tag_copy) goto error;
- }
-
- MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
- implicit, style, mark, mark);
-
- return 1;
-
-error:
- yaml_free(anchor_copy);
- yaml_free(tag_copy);
-
- return 0;
-}
-
-/*
- * Create MAPPING-END.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_end_event_initialize(yaml_event_t *event)
-{
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(event); /* Non-NULL event object is expected. */
-
- MAPPING_END_EVENT_INIT(*event, mark, mark);
-
- return 1;
-}
-
-/*
- * Destroy an event object.
- */
-
-YAML_DECLARE(void)
-yaml_event_delete(yaml_event_t *event)
-{
- yaml_tag_directive_t *tag_directive;
-
- assert(event); /* Non-NULL event object expected. */
-
- switch (event->type)
- {
- case YAML_DOCUMENT_START_EVENT:
- yaml_free(event->data.document_start.version_directive);
- for (tag_directive = event->data.document_start.tag_directives.start;
- tag_directive != event->data.document_start.tag_directives.end;
- tag_directive++) {
- yaml_free(tag_directive->handle);
- yaml_free(tag_directive->prefix);
- }
- yaml_free(event->data.document_start.tag_directives.start);
- break;
-
- case YAML_ALIAS_EVENT:
- yaml_free(event->data.alias.anchor);
- break;
-
- case YAML_SCALAR_EVENT:
- yaml_free(event->data.scalar.anchor);
- yaml_free(event->data.scalar.tag);
- yaml_free(event->data.scalar.value);
- break;
-
- case YAML_SEQUENCE_START_EVENT:
- yaml_free(event->data.sequence_start.anchor);
- yaml_free(event->data.sequence_start.tag);
- break;
-
- case YAML_MAPPING_START_EVENT:
- yaml_free(event->data.mapping_start.anchor);
- yaml_free(event->data.mapping_start.tag);
- break;
-
- default:
- break;
- }
-
- memset(event, 0, sizeof(yaml_event_t));
-}
-
-/*
- * Create a document object.
- */
-
-YAML_DECLARE(int)
-yaml_document_initialize(yaml_document_t *document,
- yaml_version_directive_t *version_directive,
- yaml_tag_directive_t *tag_directives_start,
- yaml_tag_directive_t *tag_directives_end,
- int start_implicit, int end_implicit)
-{
- struct {
- yaml_error_type_t error;
- } context;
- struct {
- yaml_node_t *start;
- yaml_node_t *end;
- yaml_node_t *top;
- } nodes = { NULL, NULL, NULL };
- yaml_version_directive_t *version_directive_copy = NULL;
- struct {
- yaml_tag_directive_t *start;
- yaml_tag_directive_t *end;
- yaml_tag_directive_t *top;
- } tag_directives_copy = { NULL, NULL, NULL };
- yaml_tag_directive_t value = { NULL, NULL };
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(document); /* Non-NULL document object is expected. */
- assert((tag_directives_start && tag_directives_end) ||
- (tag_directives_start == tag_directives_end));
- /* Valid tag directives are expected. */
-
- if (!STACK_INIT(&context, nodes, yaml_node_t*)) goto error;
-
- if (version_directive) {
- version_directive_copy = YAML_MALLOC_STATIC(yaml_version_directive_t);
- if (!version_directive_copy) goto error;
- version_directive_copy->major = version_directive->major;
- version_directive_copy->minor = version_directive->minor;
- }
-
- if (tag_directives_start != tag_directives_end) {
- yaml_tag_directive_t *tag_directive;
- if (!STACK_INIT(&context, tag_directives_copy, yaml_tag_directive_t*))
- goto error;
- for (tag_directive = tag_directives_start;
- tag_directive != tag_directives_end; tag_directive ++) {
- assert(tag_directive->handle);
- assert(tag_directive->prefix);
- if (!yaml_check_utf8(tag_directive->handle,
- strlen((char *)tag_directive->handle)))
- goto error;
- if (!yaml_check_utf8(tag_directive->prefix,
- strlen((char *)tag_directive->prefix)))
- goto error;
- value.handle = yaml_strdup(tag_directive->handle);
- value.prefix = yaml_strdup(tag_directive->prefix);
- if (!value.handle || !value.prefix) goto error;
- if (!PUSH(&context, tag_directives_copy, value))
- goto error;
- value.handle = NULL;
- value.prefix = NULL;
- }
- }
-
- DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
- tag_directives_copy.start, tag_directives_copy.top,
- start_implicit, end_implicit, mark, mark);
-
- return 1;
-
-error:
- STACK_DEL(&context, nodes);
- yaml_free(version_directive_copy);
- while (!STACK_EMPTY(&context, tag_directives_copy)) {
- yaml_tag_directive_t value = POP(&context, tag_directives_copy);
- yaml_free(value.handle);
- yaml_free(value.prefix);
- }
- STACK_DEL(&context, tag_directives_copy);
- yaml_free(value.handle);
- yaml_free(value.prefix);
-
- return 0;
-}
-
-/*
- * Destroy a document object.
- */
-
-YAML_DECLARE(void)
-yaml_document_delete(yaml_document_t *document)
-{
- yaml_tag_directive_t *tag_directive;
-
- assert(document); /* Non-NULL document object is expected. */
-
- while (!STACK_EMPTY(&context, document->nodes)) {
- yaml_node_t node = POP(&context, document->nodes);
- yaml_free(node.tag);
- switch (node.type) {
- case YAML_SCALAR_NODE:
- yaml_free(node.data.scalar.value);
- break;
- case YAML_SEQUENCE_NODE:
- STACK_DEL(&context, node.data.sequence.items);
- break;
- case YAML_MAPPING_NODE:
- STACK_DEL(&context, node.data.mapping.pairs);
- break;
- default:
- assert(0); /* Should not happen. */
- }
- }
- STACK_DEL(&context, document->nodes);
-
- yaml_free(document->version_directive);
- for (tag_directive = document->tag_directives.start;
- tag_directive != document->tag_directives.end;
- tag_directive++) {
- yaml_free(tag_directive->handle);
- yaml_free(tag_directive->prefix);
- }
- yaml_free(document->tag_directives.start);
-
- memset(document, 0, sizeof(yaml_document_t));
-}
-
-/**
- * Get a document node.
- */
-
-YAML_DECLARE(yaml_node_t *)
-yaml_document_get_node(yaml_document_t *document, int index)
-{
- assert(document); /* Non-NULL document object is expected. */
-
- if (index > 0 && document->nodes.start + index <= document->nodes.top) {
- return document->nodes.start + index - 1;
- }
- return NULL;
-}
-
-/**
- * Get the root object.
- */
-
-YAML_DECLARE(yaml_node_t *)
-yaml_document_get_root_node(yaml_document_t *document)
-{
- assert(document); /* Non-NULL document object is expected. */
-
- if (document->nodes.top != document->nodes.start) {
- return document->nodes.start;
- }
- return NULL;
-}
-
-/*
- * Add a scalar node to a document.
- */
-
-YAML_DECLARE(int)
-yaml_document_add_scalar(yaml_document_t *document,
- const yaml_char_t *tag, const yaml_char_t *value, int length,
- yaml_scalar_style_t style)
-{
- struct {
- yaml_error_type_t error;
- } context;
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_char_t *tag_copy = NULL;
- yaml_char_t *value_copy = NULL;
- yaml_node_t node;
-
- assert(document); /* Non-NULL document object is expected. */
- assert(value); /* Non-NULL value is expected. */
-
- if (!tag) {
- tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
- }
-
- if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
- tag_copy = yaml_strdup(tag);
- if (!tag_copy) goto error;
-
- if (length < 0) {
- length = (int)strlen((char *)value);
- }
-
- if (!yaml_check_utf8(value, length)) goto error;
- value_copy = YAML_MALLOC(length+1);
- if (!value_copy) goto error;
- memcpy(value_copy, value, length);
- value_copy[length] = '\0';
-
- SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
- if (!PUSH(&context, document->nodes, node)) goto error;
-
- return (int)(document->nodes.top - document->nodes.start);
-
-error:
- yaml_free(tag_copy);
- yaml_free(value_copy);
-
- return 0;
-}
-
-/*
- * Add a sequence node to a document.
- */
-
-YAML_DECLARE(int)
-yaml_document_add_sequence(yaml_document_t *document,
- const yaml_char_t *tag, yaml_sequence_style_t style)
-{
- struct {
- yaml_error_type_t error;
- } context;
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_char_t *tag_copy = NULL;
- struct {
- yaml_node_item_t *start;
- yaml_node_item_t *end;
- yaml_node_item_t *top;
- } items = { NULL, NULL, NULL };
- yaml_node_t node;
-
- assert(document); /* Non-NULL document object is expected. */
-
- if (!tag) {
- tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
- }
-
- if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
- tag_copy = yaml_strdup(tag);
- if (!tag_copy) goto error;
-
- if (!STACK_INIT(&context, items, yaml_node_item_t*)) goto error;
-
- SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
- style, mark, mark);
- if (!PUSH(&context, document->nodes, node)) goto error;
-
- return (int)(document->nodes.top - document->nodes.start);
-
-error:
- STACK_DEL(&context, items);
- yaml_free(tag_copy);
-
- return 0;
-}
-
-/*
- * Add a mapping node to a document.
- */
-
-YAML_DECLARE(int)
-yaml_document_add_mapping(yaml_document_t *document,
- const yaml_char_t *tag, yaml_mapping_style_t style)
-{
- struct {
- yaml_error_type_t error;
- } context;
- yaml_mark_t mark = { 0, 0, 0 };
- yaml_char_t *tag_copy = NULL;
- struct {
- yaml_node_pair_t *start;
- yaml_node_pair_t *end;
- yaml_node_pair_t *top;
- } pairs = { NULL, NULL, NULL };
- yaml_node_t node;
-
- assert(document); /* Non-NULL document object is expected. */
-
- if (!tag) {
- tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
- }
-
- if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
- tag_copy = yaml_strdup(tag);
- if (!tag_copy) goto error;
-
- if (!STACK_INIT(&context, pairs, yaml_node_pair_t*)) goto error;
-
- MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
- style, mark, mark);
- if (!PUSH(&context, document->nodes, node)) goto error;
-
- return (int)(document->nodes.top - document->nodes.start);
-
-error:
- STACK_DEL(&context, pairs);
- yaml_free(tag_copy);
-
- return 0;
-}
-
-/*
- * Append an item to a sequence node.
- */
-
-YAML_DECLARE(int)
-yaml_document_append_sequence_item(yaml_document_t *document,
- int sequence, int item)
-{
- struct {
- yaml_error_type_t error;
- } context;
-
- assert(document); /* Non-NULL document is required. */
- assert(sequence > 0
- && document->nodes.start + sequence <= document->nodes.top);
- /* Valid sequence id is required. */
- assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
- /* A sequence node is required. */
- assert(item > 0 && document->nodes.start + item <= document->nodes.top);
- /* Valid item id is required. */
-
- if (!PUSH(&context,
- document->nodes.start[sequence-1].data.sequence.items, item))
- return 0;
-
- return 1;
-}
-
-/*
- * Append a pair of a key and a value to a mapping node.
- */
-
-YAML_DECLARE(int)
-yaml_document_append_mapping_pair(yaml_document_t *document,
- int mapping, int key, int value)
-{
- struct {
- yaml_error_type_t error;
- } context;
-
- yaml_node_pair_t pair;
-
- assert(document); /* Non-NULL document is required. */
- assert(mapping > 0
- && document->nodes.start + mapping <= document->nodes.top);
- /* Valid mapping id is required. */
- assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
- /* A mapping node is required. */
- assert(key > 0 && document->nodes.start + key <= document->nodes.top);
- /* Valid key id is required. */
- assert(value > 0 && document->nodes.start + value <= document->nodes.top);
- /* Valid value id is required. */
-
- pair.key = key;
- pair.value = value;
-
- if (!PUSH(&context,
- document->nodes.start[mapping-1].data.mapping.pairs, pair))
- return 0;
-
- return 1;
-}
-
-
diff --git a/ext/psych/yaml/config.h b/ext/psych/yaml/config.h
deleted file mode 100644
index 4b1150f5e4..0000000000
--- a/ext/psych/yaml/config.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* 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 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 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
deleted file mode 100644
index 1fe940b674..0000000000
--- a/ext/psych/yaml/dumper.c
+++ /dev/null
@@ -1,394 +0,0 @@
-
-#include "yaml_private.h"
-
-/*
- * API functions.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_open(yaml_emitter_t *emitter);
-
-YAML_DECLARE(int)
-yaml_emitter_close(yaml_emitter_t *emitter);
-
-YAML_DECLARE(int)
-yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
-
-/*
- * Clean up functions.
- */
-
-static void
-yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
-
-/*
- * Anchor functions.
- */
-
-static void
-yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
-
-static yaml_char_t *
-yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
-
-
-/*
- * Serialize functions.
- */
-
-static int
-yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
-
-static int
-yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
-
-static int
-yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
- yaml_char_t *anchor);
-
-static int
-yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
- yaml_char_t *anchor);
-
-static int
-yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
- yaml_char_t *anchor);
-
-/*
- * Issue a STREAM-START event.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_open(yaml_emitter_t *emitter)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(emitter); /* Non-NULL emitter object is required. */
- assert(!emitter->opened); /* Emitter should not be opened yet. */
-
- STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
-
- if (!yaml_emitter_emit(emitter, &event)) {
- return 0;
- }
-
- emitter->opened = 1;
-
- return 1;
-}
-
-/*
- * Issue a STREAM-END event.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_close(yaml_emitter_t *emitter)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(emitter); /* Non-NULL emitter object is required. */
- assert(emitter->opened); /* Emitter should be opened. */
-
- if (emitter->closed) return 1;
-
- STREAM_END_EVENT_INIT(event, mark, mark);
-
- if (!yaml_emitter_emit(emitter, &event)) {
- return 0;
- }
-
- emitter->closed = 1;
-
- return 1;
-}
-
-/*
- * Dump a YAML document.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- assert(emitter); /* Non-NULL emitter object is required. */
- assert(document); /* Non-NULL emitter object is expected. */
-
- emitter->document = document;
-
- if (!emitter->opened) {
- if (!yaml_emitter_open(emitter)) goto error;
- }
-
- if (STACK_EMPTY(emitter, document->nodes)) {
- if (!yaml_emitter_close(emitter)) goto error;
- yaml_emitter_delete_document_and_anchors(emitter);
- return 1;
- }
-
- assert(emitter->opened); /* Emitter should be opened. */
-
- 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))
- * (document->nodes.top - document->nodes.start));
-
- DOCUMENT_START_EVENT_INIT(event, document->version_directive,
- document->tag_directives.start, document->tag_directives.end,
- document->start_implicit, mark, mark);
- if (!yaml_emitter_emit(emitter, &event)) goto error;
-
- yaml_emitter_anchor_node(emitter, 1);
- if (!yaml_emitter_dump_node(emitter, 1)) goto error;
-
- DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
- if (!yaml_emitter_emit(emitter, &event)) goto error;
-
- yaml_emitter_delete_document_and_anchors(emitter);
-
- return 1;
-
-error:
-
- yaml_emitter_delete_document_and_anchors(emitter);
-
- return 0;
-}
-
-/*
- * Clean up the emitter object after a document is dumped.
- */
-
-static void
-yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
-{
- int index;
-
- if (!emitter->anchors) {
- yaml_document_delete(emitter->document);
- emitter->document = NULL;
- return;
- }
-
- for (index = 0; emitter->document->nodes.start + index
- < emitter->document->nodes.top; index ++) {
- yaml_node_t node = emitter->document->nodes.start[index];
- if (!emitter->anchors[index].serialized) {
- yaml_free(node.tag);
- if (node.type == YAML_SCALAR_NODE) {
- yaml_free(node.data.scalar.value);
- }
- }
- if (node.type == YAML_SEQUENCE_NODE) {
- STACK_DEL(emitter, node.data.sequence.items);
- }
- if (node.type == YAML_MAPPING_NODE) {
- STACK_DEL(emitter, node.data.mapping.pairs);
- }
- }
-
- STACK_DEL(emitter, emitter->document->nodes);
- yaml_free(emitter->anchors);
-
- emitter->anchors = NULL;
- emitter->last_anchor_id = 0;
- emitter->document = NULL;
-}
-
-/*
- * Check the references of a node and assign the anchor id if needed.
- */
-
-static void
-yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
-{
- yaml_node_t *node = emitter->document->nodes.start + index - 1;
- yaml_node_item_t *item;
- yaml_node_pair_t *pair;
-
- emitter->anchors[index-1].references ++;
-
- if (emitter->anchors[index-1].references == 1) {
- switch (node->type) {
- case YAML_SEQUENCE_NODE:
- for (item = node->data.sequence.items.start;
- item < node->data.sequence.items.top; item ++) {
- yaml_emitter_anchor_node(emitter, *item);
- }
- break;
- case YAML_MAPPING_NODE:
- for (pair = node->data.mapping.pairs.start;
- pair < node->data.mapping.pairs.top; pair ++) {
- yaml_emitter_anchor_node(emitter, pair->key);
- yaml_emitter_anchor_node(emitter, pair->value);
- }
- break;
- default:
- break;
- }
- }
-
- else if (emitter->anchors[index-1].references == 2) {
- emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
- }
-}
-
-/*
- * Generate a textual representation for an anchor.
- */
-
-#define ANCHOR_TEMPLATE "id%03d"
-#define ANCHOR_TEMPLATE_LENGTH 16
-
-static yaml_char_t *
-yaml_emitter_generate_anchor(SHIM(yaml_emitter_t *emitter), int anchor_id)
-{
- yaml_char_t *anchor = YAML_MALLOC(ANCHOR_TEMPLATE_LENGTH);
-
- if (!anchor) return NULL;
-
- sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
-
- return anchor;
-}
-
-/*
- * Serialize a node.
- */
-
-static int
-yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
-{
- yaml_node_t *node = emitter->document->nodes.start + index - 1;
- int anchor_id = emitter->anchors[index-1].anchor;
- yaml_char_t *anchor = NULL;
-
- if (anchor_id) {
- anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
- if (!anchor) return 0;
- }
-
- if (emitter->anchors[index-1].serialized) {
- return yaml_emitter_dump_alias(emitter, anchor);
- }
-
- emitter->anchors[index-1].serialized = 1;
-
- switch (node->type) {
- case YAML_SCALAR_NODE:
- return yaml_emitter_dump_scalar(emitter, node, anchor);
- case YAML_SEQUENCE_NODE:
- return yaml_emitter_dump_sequence(emitter, node, anchor);
- case YAML_MAPPING_NODE:
- return yaml_emitter_dump_mapping(emitter, node, anchor);
- default:
- assert(0); /* Could not happen. */
- break;
- }
-
- return 0; /* Could not happen. */
-}
-
-/*
- * Serialize an alias.
- */
-
-static int
-yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- ALIAS_EVENT_INIT(event, anchor, mark, mark);
-
- return yaml_emitter_emit(emitter, &event);
-}
-
-/*
- * Serialize a scalar.
- */
-
-static int
-yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
- yaml_char_t *anchor)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- int plain_implicit = (strcmp((char *)node->tag,
- YAML_DEFAULT_SCALAR_TAG) == 0);
- int quoted_implicit = (strcmp((char *)node->tag,
- YAML_DEFAULT_SCALAR_TAG) == 0);
-
- SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
- node->data.scalar.length, plain_implicit, quoted_implicit,
- node->data.scalar.style, mark, mark);
-
- return yaml_emitter_emit(emitter, &event);
-}
-
-/*
- * Serialize a sequence.
- */
-
-static int
-yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
- yaml_char_t *anchor)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
-
- yaml_node_item_t *item;
-
- SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
- node->data.sequence.style, mark, mark);
- if (!yaml_emitter_emit(emitter, &event)) return 0;
-
- for (item = node->data.sequence.items.start;
- item < node->data.sequence.items.top; item ++) {
- if (!yaml_emitter_dump_node(emitter, *item)) return 0;
- }
-
- SEQUENCE_END_EVENT_INIT(event, mark, mark);
- if (!yaml_emitter_emit(emitter, &event)) return 0;
-
- return 1;
-}
-
-/*
- * Serialize a mapping.
- */
-
-static int
-yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
- yaml_char_t *anchor)
-{
- yaml_event_t event;
- yaml_mark_t mark = { 0, 0, 0 };
-
- int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
-
- yaml_node_pair_t *pair;
-
- MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
- node->data.mapping.style, mark, mark);
- if (!yaml_emitter_emit(emitter, &event)) return 0;
-
- for (pair = node->data.mapping.pairs.start;
- pair < node->data.mapping.pairs.top; pair ++) {
- if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
- if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
- }
-
- MAPPING_END_EVENT_INIT(event, mark, mark);
- if (!yaml_emitter_emit(emitter, &event)) return 0;
-
- return 1;
-}
-
diff --git a/ext/psych/yaml/emitter.c b/ext/psych/yaml/emitter.c
deleted file mode 100644
index 796294ccdf..0000000000
--- a/ext/psych/yaml/emitter.c
+++ /dev/null
@@ -1,2358 +0,0 @@
-
-#include "yaml_private.h"
-
-/*
- * Flush the buffer if needed.
- */
-
-#define FLUSH(emitter) \
- ((emitter->buffer.pointer+5 < emitter->buffer.end) \
- || yaml_emitter_flush(emitter))
-
-/*
- * Put a character to the output buffer.
- */
-
-#define PUT(emitter,value) \
- (FLUSH(emitter) \
- && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \
- emitter->column++, \
- 1))
-
-/*
- * Put a line break to the output buffer.
- */
-
-#define PUT_BREAK(emitter) \
- (FLUSH(emitter) ? \
- ((emitter->line_break == YAML_CR_BREAK ? \
- (*(emitter->buffer.pointer++) = (yaml_char_t) '\r') : \
- emitter->line_break == YAML_LN_BREAK ? \
- (*(emitter->buffer.pointer++) = (yaml_char_t) '\n') : \
- emitter->line_break == YAML_CRLN_BREAK ? \
- (*(emitter->buffer.pointer++) = (yaml_char_t) '\r', \
- *(emitter->buffer.pointer++) = (yaml_char_t) '\n') : 0), \
- emitter->column = 0, \
- emitter->line ++, \
- 1) : 0)
-
-/*
- * Copy a character from a string into buffer.
- */
-
-#define WRITE(emitter,string) \
- (FLUSH(emitter) \
- && (COPY(emitter->buffer,string), \
- emitter->column ++, \
- 1))
-
-/*
- * Copy a line break character from a string into buffer.
- */
-
-#define WRITE_BREAK(emitter,string) \
- (FLUSH(emitter) \
- && (CHECK(string,'\n') ? \
- (PUT_BREAK(emitter), \
- string.pointer ++, \
- 1) : \
- (COPY(emitter->buffer,string), \
- emitter->column = 0, \
- emitter->line ++, \
- 1)))
-
-/*
- * API functions.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
-
-/*
- * Utility functions.
- */
-
-static int
-yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem);
-
-static int
-yaml_emitter_need_more_events(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t value, int allow_duplicates);
-
-static int
-yaml_emitter_increase_indent(yaml_emitter_t *emitter,
- int flow, int indentless);
-
-/*
- * State functions.
- */
-
-static int
-yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event);
-
-static int
-yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
- yaml_event_t *event);
-
-static int
-yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
-
-static int
-yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
- yaml_event_t *event);
-
-static int
-yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
- yaml_event_t *event);
-
-static int
-yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
-
-static int
-yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
-
-static int
-yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple);
-
-static int
-yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
-
-static int
-yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
-
-static int
-yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple);
-
-static int
-yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
- int root, int sequence, int mapping, int simple_key);
-
-static int
-yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event);
-
-static int
-yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event);
-
-static int
-yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event);
-
-static int
-yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event);
-
-/*
- * Checkers.
- */
-
-static int
-yaml_emitter_check_empty_document(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_check_simple_key(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event);
-
-/*
- * Processors.
- */
-
-static int
-yaml_emitter_process_anchor(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_process_tag(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_process_scalar(yaml_emitter_t *emitter);
-
-/*
- * Analyzers.
- */
-
-static int
-yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
- yaml_version_directive_t version_directive);
-
-static int
-yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t tag_directive);
-
-static int
-yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
- yaml_char_t *anchor, int alias);
-
-static int
-yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
- yaml_char_t *tag);
-
-static int
-yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
-
-static int
-yaml_emitter_analyze_event(yaml_emitter_t *emitter,
- yaml_event_t *event);
-
-/*
- * Writers.
- */
-
-static int
-yaml_emitter_write_bom(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_write_indent(yaml_emitter_t *emitter);
-
-static int
-yaml_emitter_write_indicator(yaml_emitter_t *emitter,
- const char *indicator, int need_whitespace,
- int is_whitespace, int is_indention);
-
-static int
-yaml_emitter_write_anchor(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
-
-static int
-yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
-
-static int
-yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int need_whitespace);
-
-static int
-yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks);
-
-static int
-yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks);
-
-static int
-yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks);
-
-static int
-yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
- yaml_string_t string);
-
-static int
-yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
-
-static int
-yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
-
-/*
- * Set an emitter error and return 0.
- */
-
-static int
-yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem)
-{
- emitter->error = YAML_EMITTER_ERROR;
- emitter->problem = problem;
-
- return 0;
-}
-
-/*
- * Emit an event.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
-{
- if (!ENQUEUE(emitter, emitter->events, *event)) {
- yaml_event_delete(event);
- return 0;
- }
-
- while (!yaml_emitter_need_more_events(emitter)) {
- if (!yaml_emitter_analyze_event(emitter, emitter->events.head))
- return 0;
- if (!yaml_emitter_state_machine(emitter, emitter->events.head))
- return 0;
- yaml_event_delete(&DEQUEUE(emitter, emitter->events));
- }
-
- return 1;
-}
-
-/*
- * Check if we need to accumulate more events before emitting.
- *
- * We accumulate extra
- * - 1 event for DOCUMENT-START
- * - 2 events for SEQUENCE-START
- * - 3 events for MAPPING-START
- */
-
-static int
-yaml_emitter_need_more_events(yaml_emitter_t *emitter)
-{
- int level = 0;
- int accumulate = 0;
- yaml_event_t *event;
-
- if (QUEUE_EMPTY(emitter, emitter->events))
- return 1;
-
- switch (emitter->events.head->type) {
- case YAML_DOCUMENT_START_EVENT:
- accumulate = 1;
- break;
- case YAML_SEQUENCE_START_EVENT:
- accumulate = 2;
- break;
- case YAML_MAPPING_START_EVENT:
- accumulate = 3;
- break;
- default:
- return 0;
- }
-
- if (emitter->events.tail - emitter->events.head > accumulate)
- return 0;
-
- for (event = emitter->events.head; event != emitter->events.tail; event ++) {
- switch (event->type) {
- case YAML_STREAM_START_EVENT:
- case YAML_DOCUMENT_START_EVENT:
- case YAML_SEQUENCE_START_EVENT:
- case YAML_MAPPING_START_EVENT:
- level += 1;
- break;
- case YAML_STREAM_END_EVENT:
- case YAML_DOCUMENT_END_EVENT:
- case YAML_SEQUENCE_END_EVENT:
- case YAML_MAPPING_END_EVENT:
- level -= 1;
- break;
- default:
- break;
- }
- if (!level)
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Append a directive to the directives stack.
- */
-
-static int
-yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t value, int allow_duplicates)
-{
- yaml_tag_directive_t *tag_directive;
- yaml_tag_directive_t copy = { NULL, NULL };
-
- for (tag_directive = emitter->tag_directives.start;
- tag_directive != emitter->tag_directives.top; tag_directive ++) {
- if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
- if (allow_duplicates)
- return 1;
- return yaml_emitter_set_emitter_error(emitter,
- "duplicate %TAG directive");
- }
- }
-
- copy.handle = yaml_strdup(value.handle);
- copy.prefix = yaml_strdup(value.prefix);
- if (!copy.handle || !copy.prefix) {
- emitter->error = YAML_MEMORY_ERROR;
- goto error;
- }
-
- if (!PUSH(emitter, emitter->tag_directives, copy))
- goto error;
-
- return 1;
-
-error:
- yaml_free(copy.handle);
- yaml_free(copy.prefix);
- return 0;
-}
-
-/*
- * Increase the indentation level.
- */
-
-static int
-yaml_emitter_increase_indent(yaml_emitter_t *emitter,
- int flow, int indentless)
-{
- if (!PUSH(emitter, emitter->indents, emitter->indent))
- return 0;
-
- if (emitter->indent < 0) {
- emitter->indent = flow ? emitter->best_indent : 0;
- }
- else if (!indentless) {
- emitter->indent += emitter->best_indent;
- }
-
- return 1;
-}
-
-/*
- * State dispatcher.
- */
-
-static int
-yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event)
-{
- switch (emitter->state)
- {
- case YAML_EMIT_STREAM_START_STATE:
- return yaml_emitter_emit_stream_start(emitter, event);
-
- case YAML_EMIT_FIRST_DOCUMENT_START_STATE:
- return yaml_emitter_emit_document_start(emitter, event, 1);
-
- case YAML_EMIT_DOCUMENT_START_STATE:
- return yaml_emitter_emit_document_start(emitter, event, 0);
-
- case YAML_EMIT_DOCUMENT_CONTENT_STATE:
- return yaml_emitter_emit_document_content(emitter, event);
-
- case YAML_EMIT_DOCUMENT_END_STATE:
- return yaml_emitter_emit_document_end(emitter, event);
-
- case YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
- return yaml_emitter_emit_flow_sequence_item(emitter, event, 1);
-
- case YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE:
- return yaml_emitter_emit_flow_sequence_item(emitter, event, 0);
-
- case YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
- return yaml_emitter_emit_flow_mapping_key(emitter, event, 1);
-
- case YAML_EMIT_FLOW_MAPPING_KEY_STATE:
- return yaml_emitter_emit_flow_mapping_key(emitter, event, 0);
-
- case YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
- return yaml_emitter_emit_flow_mapping_value(emitter, event, 1);
-
- case YAML_EMIT_FLOW_MAPPING_VALUE_STATE:
- return yaml_emitter_emit_flow_mapping_value(emitter, event, 0);
-
- case YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
- return yaml_emitter_emit_block_sequence_item(emitter, event, 1);
-
- case YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
- return yaml_emitter_emit_block_sequence_item(emitter, event, 0);
-
- case YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
- return yaml_emitter_emit_block_mapping_key(emitter, event, 1);
-
- case YAML_EMIT_BLOCK_MAPPING_KEY_STATE:
- return yaml_emitter_emit_block_mapping_key(emitter, event, 0);
-
- case YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
- return yaml_emitter_emit_block_mapping_value(emitter, event, 1);
-
- case YAML_EMIT_BLOCK_MAPPING_VALUE_STATE:
- return yaml_emitter_emit_block_mapping_value(emitter, event, 0);
-
- case YAML_EMIT_END_STATE:
- return yaml_emitter_set_emitter_error(emitter,
- "expected nothing after STREAM-END");
-
- default:
- assert(1); /* Invalid state. */
- }
-
- return 0;
-}
-
-/*
- * Expect STREAM-START.
- */
-
-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) {
- emitter->encoding = event->data.stream_start.encoding;
- }
-
- if (!emitter->encoding) {
- emitter->encoding = YAML_UTF8_ENCODING;
- }
-
- if (emitter->best_indent < 2 || emitter->best_indent > 9) {
- emitter->best_indent = 2;
- }
-
- if (emitter->best_width >= 0
- && emitter->best_width <= emitter->best_indent*2) {
- emitter->best_width = 80;
- }
-
- if (emitter->best_width < 0) {
- emitter->best_width = INT_MAX;
- }
-
- if (!emitter->line_break) {
- emitter->line_break = YAML_LN_BREAK;
- }
-
- emitter->indent = -1;
-
- emitter->line = 0;
- emitter->column = 0;
- emitter->whitespace = 1;
- emitter->indention = 1;
-
- if (emitter->encoding != YAML_UTF8_ENCODING) {
- if (!yaml_emitter_write_bom(emitter))
- return 0;
- }
-
- emitter->state = YAML_EMIT_FIRST_DOCUMENT_START_STATE;
-
- return 1;
- }
-
- return yaml_emitter_set_emitter_error(emitter,
- "expected STREAM-START");
-}
-
-/*
- * Expect DOCUMENT-START or STREAM-END.
- */
-
-static int
-yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
-{
- if (event->type == YAML_DOCUMENT_START_EVENT)
- {
- yaml_tag_directive_t default_tag_directives[] = {
- {(yaml_char_t *)"!", (yaml_char_t *)"!"},
- {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
- {NULL, NULL}
- };
- yaml_tag_directive_t *tag_directive;
- int implicit;
-
- if (event->data.document_start.version_directive) {
- if (!yaml_emitter_analyze_version_directive(emitter,
- *event->data.document_start.version_directive))
- return 0;
- }
-
- for (tag_directive = event->data.document_start.tag_directives.start;
- tag_directive != event->data.document_start.tag_directives.end;
- tag_directive ++) {
- if (!yaml_emitter_analyze_tag_directive(emitter, *tag_directive))
- return 0;
- if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 0))
- return 0;
- }
-
- for (tag_directive = default_tag_directives;
- tag_directive->handle; tag_directive ++) {
- if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 1))
- return 0;
- }
-
- implicit = event->data.document_start.implicit;
- if (!first || emitter->canonical) {
- implicit = 0;
- }
-
- if ((event->data.document_start.version_directive ||
- (event->data.document_start.tag_directives.start
- != event->data.document_start.tag_directives.end)) &&
- emitter->open_ended)
- {
- if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
- return 0;
- 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 (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;
- }
-
- if (event->data.document_start.tag_directives.start
- != event->data.document_start.tag_directives.end) {
- implicit = 0;
- for (tag_directive = event->data.document_start.tag_directives.start;
- tag_directive != event->data.document_start.tag_directives.end;
- tag_directive ++) {
- if (!yaml_emitter_write_indicator(emitter, "%TAG", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_tag_handle(emitter, tag_directive->handle,
- strlen((char *)tag_directive->handle)))
- return 0;
- if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix,
- strlen((char *)tag_directive->prefix), 1))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- }
-
- if (yaml_emitter_check_empty_document(emitter)) {
- implicit = 0;
- }
-
- if (!implicit) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, "---", 1, 0, 0))
- return 0;
- if (emitter->canonical) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- }
-
- emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE;
-
- emitter->open_ended = 0;
- return 1;
- }
-
- else if (event->type == YAML_STREAM_END_EVENT)
- {
-
- /**
- * 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;
-
- emitter->state = YAML_EMIT_END_STATE;
-
- return 1;
- }
-
- return yaml_emitter_set_emitter_error(emitter,
- "expected DOCUMENT-START or STREAM-END");
-}
-
-/*
- * Expect the root node.
- */
-
-static int
-yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
- yaml_event_t *event)
-{
- if (!PUSH(emitter, emitter->states, YAML_EMIT_DOCUMENT_END_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 1, 0, 0, 0);
-}
-
-/*
- * Expect DOCUMENT-END.
- */
-
-static int
-yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
- yaml_event_t *event)
-{
- if (event->type == YAML_DOCUMENT_END_EVENT)
- {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- 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;
-
- emitter->state = YAML_EMIT_DOCUMENT_START_STATE;
-
- while (!STACK_EMPTY(emitter, emitter->tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(emitter,
- emitter->tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
-
- return 1;
- }
-
- return yaml_emitter_set_emitter_error(emitter,
- "expected DOCUMENT-END");
-}
-
-/*
- *
- * Expect a flow item node.
- */
-
-static int
-yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
-{
- if (first)
- {
- if (!yaml_emitter_write_indicator(emitter, "[", 1, 1, 0))
- return 0;
- if (!yaml_emitter_increase_indent(emitter, 1, 0))
- return 0;
- emitter->flow_level ++;
- }
-
- if (event->type == YAML_SEQUENCE_END_EVENT)
- {
- emitter->flow_level --;
- emitter->indent = POP(emitter, emitter->indents);
- if (emitter->canonical && !first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_write_indicator(emitter, "]", 0, 0, 0))
- return 0;
- emitter->state = POP(emitter, emitter->states);
-
- return 1;
- }
-
- if (!first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- }
-
- if (emitter->canonical || emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
-}
-
-/*
- * Expect a flow key node.
- */
-
-static int
-yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
-{
- if (first)
- {
- if (!yaml_emitter_write_indicator(emitter, "{", 1, 1, 0))
- return 0;
- if (!yaml_emitter_increase_indent(emitter, 1, 0))
- return 0;
- emitter->flow_level ++;
- }
-
- if (event->type == YAML_MAPPING_END_EVENT)
- {
- emitter->flow_level --;
- emitter->indent = POP(emitter, emitter->indents);
- if (emitter->canonical && !first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_write_indicator(emitter, "}", 0, 0, 0))
- return 0;
- emitter->state = POP(emitter, emitter->states);
-
- return 1;
- }
-
- if (!first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- }
- if (emitter->canonical || emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
-
- if (!emitter->canonical && yaml_emitter_check_simple_key(emitter))
- {
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
- }
- else
- {
- if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 0))
- return 0;
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_FLOW_MAPPING_VALUE_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
- }
-}
-
-/*
- * Expect a flow value node.
- */
-
-static int
-yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple)
-{
- if (simple) {
- if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
- return 0;
- }
- else {
- if (emitter->canonical || emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 0))
- return 0;
- }
- if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_MAPPING_KEY_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
-}
-
-/*
- * Expect a block item node.
- */
-
-static int
-yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
-{
- if (first)
- {
- if (!yaml_emitter_increase_indent(emitter, 0,
- (emitter->mapping_context && !emitter->indention)))
- return 0;
- }
-
- if (event->type == YAML_SEQUENCE_END_EVENT)
- {
- emitter->indent = POP(emitter, emitter->indents);
- emitter->state = POP(emitter, emitter->states);
-
- return 1;
- }
-
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, "-", 1, 0, 1))
- return 0;
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
-}
-
-/*
- * Expect a block key node.
- */
-
-static int
-yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
-{
- if (first)
- {
- if (!yaml_emitter_increase_indent(emitter, 0, 0))
- return 0;
- }
-
- if (event->type == YAML_MAPPING_END_EVENT)
- {
- emitter->indent = POP(emitter, emitter->indents);
- emitter->state = POP(emitter, emitter->states);
-
- return 1;
- }
-
- if (!yaml_emitter_write_indent(emitter))
- return 0;
-
- if (yaml_emitter_check_simple_key(emitter))
- {
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
- }
- else
- {
- if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 1))
- return 0;
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_MAPPING_VALUE_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
- }
-}
-
-/*
- * Expect a block value node.
- */
-
-static int
-yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple)
-{
- if (simple) {
- if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
- return 0;
- }
- else {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 1))
- return 0;
- }
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_MAPPING_KEY_STATE))
- return 0;
-
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
-}
-
-/*
- * Expect a node.
- */
-
-static int
-yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
- int root, int sequence, int mapping, int simple_key)
-{
- emitter->root_context = root;
- emitter->sequence_context = sequence;
- emitter->mapping_context = mapping;
- emitter->simple_key_context = simple_key;
-
- switch (event->type)
- {
- case YAML_ALIAS_EVENT:
- return yaml_emitter_emit_alias(emitter, event);
-
- case YAML_SCALAR_EVENT:
- return yaml_emitter_emit_scalar(emitter, event);
-
- case YAML_SEQUENCE_START_EVENT:
- return yaml_emitter_emit_sequence_start(emitter, event);
-
- case YAML_MAPPING_START_EVENT:
- return yaml_emitter_emit_mapping_start(emitter, event);
-
- default:
- return yaml_emitter_set_emitter_error(emitter,
- "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS");
- }
-
- return 0;
-}
-
-/*
- * Expect ALIAS.
- */
-
-static int
-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;
-}
-
-/*
- * Expect SCALAR.
- */
-
-static int
-yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event)
-{
- if (!yaml_emitter_select_scalar_style(emitter, event))
- return 0;
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (!yaml_emitter_process_tag(emitter))
- return 0;
- if (!yaml_emitter_increase_indent(emitter, 1, 0))
- return 0;
- if (!yaml_emitter_process_scalar(emitter))
- return 0;
- emitter->indent = POP(emitter, emitter->indents);
- emitter->state = POP(emitter, emitter->states);
-
- return 1;
-}
-
-/*
- * Expect SEQUENCE-START.
- */
-
-static int
-yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event)
-{
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (!yaml_emitter_process_tag(emitter))
- return 0;
-
- if (emitter->flow_level || emitter->canonical
- || event->data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE
- || yaml_emitter_check_empty_sequence(emitter)) {
- emitter->state = YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE;
- }
- else {
- emitter->state = YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE;
- }
-
- return 1;
-}
-
-/*
- * Expect MAPPING-START.
- */
-
-static int
-yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event)
-{
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (!yaml_emitter_process_tag(emitter))
- return 0;
-
- if (emitter->flow_level || emitter->canonical
- || event->data.mapping_start.style == YAML_FLOW_MAPPING_STYLE
- || yaml_emitter_check_empty_mapping(emitter)) {
- emitter->state = YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE;
- }
- else {
- emitter->state = YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE;
- }
-
- return 1;
-}
-
-/*
- * Check if the document content is an empty scalar.
- */
-
-static int
-yaml_emitter_check_empty_document(SHIM(yaml_emitter_t *emitter))
-{
- return 0;
-}
-
-/*
- * Check if the next events represent an empty sequence.
- */
-
-static int
-yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter)
-{
- if (emitter->events.tail - emitter->events.head < 2)
- return 0;
-
- return (emitter->events.head[0].type == YAML_SEQUENCE_START_EVENT
- && emitter->events.head[1].type == YAML_SEQUENCE_END_EVENT);
-}
-
-/*
- * Check if the next events represent an empty mapping.
- */
-
-static int
-yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter)
-{
- if (emitter->events.tail - emitter->events.head < 2)
- return 0;
-
- return (emitter->events.head[0].type == YAML_MAPPING_START_EVENT
- && emitter->events.head[1].type == YAML_MAPPING_END_EVENT);
-}
-
-/*
- * Check if the next node can be expressed as a simple key.
- */
-
-static int
-yaml_emitter_check_simple_key(yaml_emitter_t *emitter)
-{
- yaml_event_t *event = emitter->events.head;
- size_t length = 0;
-
- switch (event->type)
- {
- case YAML_ALIAS_EVENT:
- length += emitter->anchor_data.anchor_length;
- break;
-
- case YAML_SCALAR_EVENT:
- if (emitter->scalar_data.multiline)
- return 0;
- length += emitter->anchor_data.anchor_length
- + emitter->tag_data.handle_length
- + emitter->tag_data.suffix_length
- + emitter->scalar_data.length;
- break;
-
- case YAML_SEQUENCE_START_EVENT:
- if (!yaml_emitter_check_empty_sequence(emitter))
- return 0;
- length += emitter->anchor_data.anchor_length
- + emitter->tag_data.handle_length
- + emitter->tag_data.suffix_length;
- break;
-
- case YAML_MAPPING_START_EVENT:
- if (!yaml_emitter_check_empty_mapping(emitter))
- return 0;
- length += emitter->anchor_data.anchor_length
- + emitter->tag_data.handle_length
- + emitter->tag_data.suffix_length;
- break;
-
- default:
- return 0;
- }
-
- if (length > 128)
- return 0;
-
- return 1;
-}
-
-/*
- * Determine an acceptable scalar style.
- */
-
-static int
-yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
-{
- yaml_scalar_style_t style = event->data.scalar.style;
- int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
-
- if (no_tag && !event->data.scalar.plain_implicit
- && !event->data.scalar.quoted_implicit) {
- return yaml_emitter_set_emitter_error(emitter,
- "neither tag nor implicit flags are specified");
- }
-
- if (style == YAML_ANY_SCALAR_STYLE)
- style = YAML_PLAIN_SCALAR_STYLE;
-
- if (emitter->canonical)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
-
- if (emitter->simple_key_context && emitter->scalar_data.multiline)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
-
- if (style == YAML_PLAIN_SCALAR_STYLE)
- {
- if ((emitter->flow_level && !emitter->scalar_data.flow_plain_allowed)
- || (!emitter->flow_level && !emitter->scalar_data.block_plain_allowed))
- style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- if (!emitter->scalar_data.length
- && (emitter->flow_level || emitter->simple_key_context))
- style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- if (no_tag && !event->data.scalar.plain_implicit)
- style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- }
-
- if (style == YAML_SINGLE_QUOTED_SCALAR_STYLE)
- {
- if (!emitter->scalar_data.single_quoted_allowed)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
- }
-
- if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE)
- {
- if (!emitter->scalar_data.block_allowed
- || emitter->flow_level || emitter->simple_key_context)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
- }
-
- if (no_tag && !event->data.scalar.quoted_implicit
- && style != YAML_PLAIN_SCALAR_STYLE)
- {
- emitter->tag_data.handle = (yaml_char_t *)"!";
- emitter->tag_data.handle_length = 1;
- }
-
- emitter->scalar_data.style = style;
-
- return 1;
-}
-
-/*
- * Write an anchor.
- */
-
-static int
-yaml_emitter_process_anchor(yaml_emitter_t *emitter)
-{
- if (!emitter->anchor_data.anchor)
- return 1;
-
- if (!yaml_emitter_write_indicator(emitter,
- (emitter->anchor_data.alias ? "*" : "&"), 1, 0, 0))
- return 0;
-
- return yaml_emitter_write_anchor(emitter,
- emitter->anchor_data.anchor, emitter->anchor_data.anchor_length);
-}
-
-/*
- * Write a tag.
- */
-
-static int
-yaml_emitter_process_tag(yaml_emitter_t *emitter)
-{
- if (!emitter->tag_data.handle && !emitter->tag_data.suffix)
- return 1;
-
- if (emitter->tag_data.handle)
- {
- if (!yaml_emitter_write_tag_handle(emitter, emitter->tag_data.handle,
- emitter->tag_data.handle_length))
- return 0;
- if (emitter->tag_data.suffix) {
- if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
- emitter->tag_data.suffix_length, 0))
- return 0;
- }
- }
- else
- {
- if (!yaml_emitter_write_indicator(emitter, "!<", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
- emitter->tag_data.suffix_length, 0))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0))
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Write a scalar.
- */
-
-static int
-yaml_emitter_process_scalar(yaml_emitter_t *emitter)
-{
- switch (emitter->scalar_data.style)
- {
- case YAML_PLAIN_SCALAR_STYLE:
- return yaml_emitter_write_plain_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length,
- !emitter->simple_key_context);
-
- case YAML_SINGLE_QUOTED_SCALAR_STYLE:
- return yaml_emitter_write_single_quoted_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length,
- !emitter->simple_key_context);
-
- case YAML_DOUBLE_QUOTED_SCALAR_STYLE:
- return yaml_emitter_write_double_quoted_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length,
- !emitter->simple_key_context);
-
- case YAML_LITERAL_SCALAR_STYLE:
- return yaml_emitter_write_literal_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length);
-
- case YAML_FOLDED_SCALAR_STYLE:
- return yaml_emitter_write_folded_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length);
-
- default:
- assert(1); /* Impossible. */
- }
-
- return 0;
-}
-
-/*
- * Check if a %YAML directive is valid.
- */
-
-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
- && version_directive.minor != 2
- )) {
- return yaml_emitter_set_emitter_error(emitter,
- "incompatible %YAML directive");
- }
-
- return 1;
-}
-
-/*
- * Check if a %TAG directive is valid.
- */
-
-static int
-yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t tag_directive)
-{
- yaml_string_t handle;
- yaml_string_t prefix;
- size_t handle_length;
- size_t prefix_length;
-
- handle_length = strlen((char *)tag_directive.handle);
- prefix_length = strlen((char *)tag_directive.prefix);
- STRING_ASSIGN(handle, tag_directive.handle, handle_length);
- STRING_ASSIGN(prefix, tag_directive.prefix, prefix_length);
-
- if (handle.start == handle.end) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must not be empty");
- }
-
- if (handle.start[0] != '!') {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must start with '!'");
- }
-
- if (handle.end[-1] != '!') {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must end with '!'");
- }
-
- handle.pointer ++;
-
- while (handle.pointer < handle.end-1) {
- if (!IS_ALPHA(handle)) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must contain alphanumerical characters only");
- }
- MOVE(handle);
- }
-
- if (prefix.start == prefix.end) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag prefix must not be empty");
- }
-
- return 1;
-}
-
-/*
- * Check if an anchor is valid.
- */
-
-static int
-yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
- yaml_char_t *anchor, int alias)
-{
- size_t anchor_length;
- yaml_string_t string;
-
- anchor_length = strlen((char *)anchor);
- STRING_ASSIGN(string, anchor, anchor_length);
-
- if (string.start == string.end) {
- return yaml_emitter_set_emitter_error(emitter, alias ?
- "alias value must not be empty" :
- "anchor value must not be empty");
- }
-
- while (string.pointer != string.end) {
- if (!IS_ALPHA(string)) {
- return yaml_emitter_set_emitter_error(emitter, alias ?
- "alias value must contain alphanumerical characters only" :
- "anchor value must contain alphanumerical characters only");
- }
- MOVE(string);
- }
-
- emitter->anchor_data.anchor = string.start;
- emitter->anchor_data.anchor_length = string.end - string.start;
- emitter->anchor_data.alias = alias;
-
- return 1;
-}
-
-/*
- * Check if a tag is valid.
- */
-
-static int
-yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
- yaml_char_t *tag)
-{
- size_t tag_length;
- yaml_string_t string;
- yaml_tag_directive_t *tag_directive;
-
- tag_length = strlen((char *)tag);
- STRING_ASSIGN(string, tag, tag_length);
-
- if (string.start == string.end) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag value must not be empty");
- }
-
- for (tag_directive = emitter->tag_directives.start;
- tag_directive != emitter->tag_directives.top; tag_directive ++) {
- size_t prefix_length = strlen((char *)tag_directive->prefix);
- if (prefix_length < (size_t)(string.end - string.start)
- && strncmp((char *)tag_directive->prefix, (char *)string.start,
- prefix_length) == 0)
- {
- emitter->tag_data.handle = tag_directive->handle;
- emitter->tag_data.handle_length =
- strlen((char *)tag_directive->handle);
- emitter->tag_data.suffix = string.start + prefix_length;
- emitter->tag_data.suffix_length =
- (string.end - string.start) - prefix_length;
- return 1;
- }
- }
-
- emitter->tag_data.suffix = string.start;
- emitter->tag_data.suffix_length = string.end - string.start;
-
- return 1;
-}
-
-/*
- * Check if a scalar is valid.
- */
-
-static int
-yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
-{
- yaml_string_t string;
-
- int block_indicators = 0;
- int flow_indicators = 0;
- int line_breaks = 0;
- int special_characters = 0;
-
- int leading_space = 0;
- int leading_break = 0;
- int trailing_space = 0;
- int trailing_break = 0;
- int break_space = 0;
- int space_break = 0;
-
- int preceded_by_whitespace = 0;
- int followed_by_whitespace = 0;
- int previous_space = 0;
- int previous_break = 0;
-
- STRING_ASSIGN(string, value, length);
-
- emitter->scalar_data.value = value;
- emitter->scalar_data.length = length;
-
- if (string.start == string.end)
- {
- emitter->scalar_data.multiline = 0;
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 1;
- emitter->scalar_data.single_quoted_allowed = 1;
- emitter->scalar_data.block_allowed = 0;
-
- return 1;
- }
-
- if ((CHECK_AT(string, '-', 0)
- && CHECK_AT(string, '-', 1)
- && CHECK_AT(string, '-', 2))
- || (CHECK_AT(string, '.', 0)
- && CHECK_AT(string, '.', 1)
- && CHECK_AT(string, '.', 2))) {
- block_indicators = 1;
- flow_indicators = 1;
- }
-
- preceded_by_whitespace = 1;
- followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
-
- while (string.pointer != string.end)
- {
- if (string.start == string.pointer)
- {
- if (CHECK(string, '#') || CHECK(string, ',')
- || CHECK(string, '[') || CHECK(string, ']')
- || CHECK(string, '{') || CHECK(string, '}')
- || CHECK(string, '&') || CHECK(string, '*')
- || CHECK(string, '!') || CHECK(string, '|')
- || CHECK(string, '>') || CHECK(string, '\'')
- || CHECK(string, '"') || CHECK(string, '%')
- || CHECK(string, '@') || CHECK(string, '`')) {
- flow_indicators = 1;
- block_indicators = 1;
- }
-
- if (CHECK(string, '?') || CHECK(string, ':')) {
- flow_indicators = 1;
- if (followed_by_whitespace) {
- block_indicators = 1;
- }
- }
-
- if (CHECK(string, '-') && followed_by_whitespace) {
- flow_indicators = 1;
- block_indicators = 1;
- }
- }
- else
- {
- if (CHECK(string, ',') || CHECK(string, '?')
- || CHECK(string, '[') || CHECK(string, ']')
- || CHECK(string, '{') || CHECK(string, '}')) {
- flow_indicators = 1;
- }
-
- if (CHECK(string, ':')) {
- flow_indicators = 1;
- if (followed_by_whitespace) {
- block_indicators = 1;
- }
- }
-
- if (CHECK(string, '#') && preceded_by_whitespace) {
- flow_indicators = 1;
- block_indicators = 1;
- }
- }
-
- if (!IS_PRINTABLE(string)
- || (!IS_ASCII(string) && !emitter->unicode)) {
- special_characters = 1;
- }
-
- if (IS_BREAK(string)) {
- line_breaks = 1;
- }
-
- if (IS_SPACE(string))
- {
- if (string.start == string.pointer) {
- leading_space = 1;
- }
- if (string.pointer+WIDTH(string) == string.end) {
- trailing_space = 1;
- }
- if (previous_break) {
- break_space = 1;
- }
- previous_space = 1;
- previous_break = 0;
- }
- else if (IS_BREAK(string))
- {
- if (string.start == string.pointer) {
- leading_break = 1;
- }
- if (string.pointer+WIDTH(string) == string.end) {
- trailing_break = 1;
- }
- if (previous_space) {
- space_break = 1;
- }
- previous_space = 0;
- previous_break = 1;
- }
- else
- {
- previous_space = 0;
- previous_break = 0;
- }
-
- preceded_by_whitespace = IS_BLANKZ(string);
- MOVE(string);
- if (string.pointer != string.end) {
- followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
- }
- }
-
- emitter->scalar_data.multiline = line_breaks;
-
- emitter->scalar_data.flow_plain_allowed = 1;
- emitter->scalar_data.block_plain_allowed = 1;
- emitter->scalar_data.single_quoted_allowed = 1;
- emitter->scalar_data.block_allowed = 1;
-
- if (leading_space || leading_break || trailing_space || trailing_break) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- }
-
- if (trailing_space) {
- emitter->scalar_data.block_allowed = 0;
- }
-
- if (break_space) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- emitter->scalar_data.single_quoted_allowed = 0;
- }
-
- if (space_break || special_characters) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- emitter->scalar_data.single_quoted_allowed = 0;
- emitter->scalar_data.block_allowed = 0;
- }
-
- if (line_breaks) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- }
-
- if (flow_indicators) {
- emitter->scalar_data.flow_plain_allowed = 0;
- }
-
- if (block_indicators) {
- emitter->scalar_data.block_plain_allowed = 0;
- }
-
- return 1;
-}
-
-/*
- * Check if the event data is valid.
- */
-
-static int
-yaml_emitter_analyze_event(yaml_emitter_t *emitter,
- yaml_event_t *event)
-{
- emitter->anchor_data.anchor = NULL;
- emitter->anchor_data.anchor_length = 0;
- emitter->tag_data.handle = NULL;
- emitter->tag_data.handle_length = 0;
- emitter->tag_data.suffix = NULL;
- emitter->tag_data.suffix_length = 0;
- emitter->scalar_data.value = NULL;
- emitter->scalar_data.length = 0;
-
- switch (event->type)
- {
- case YAML_ALIAS_EVENT:
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.alias.anchor, 1))
- return 0;
- return 1;
-
- case YAML_SCALAR_EVENT:
- if (event->data.scalar.anchor) {
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.scalar.anchor, 0))
- return 0;
- }
- if (event->data.scalar.tag && (emitter->canonical ||
- (!event->data.scalar.plain_implicit
- && !event->data.scalar.quoted_implicit))) {
- if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag))
- return 0;
- }
- if (!yaml_emitter_analyze_scalar(emitter,
- event->data.scalar.value, event->data.scalar.length))
- return 0;
- return 1;
-
- case YAML_SEQUENCE_START_EVENT:
- if (event->data.sequence_start.anchor) {
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.sequence_start.anchor, 0))
- return 0;
- }
- if (event->data.sequence_start.tag && (emitter->canonical ||
- !event->data.sequence_start.implicit)) {
- if (!yaml_emitter_analyze_tag(emitter,
- event->data.sequence_start.tag))
- return 0;
- }
- return 1;
-
- case YAML_MAPPING_START_EVENT:
- if (event->data.mapping_start.anchor) {
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.mapping_start.anchor, 0))
- return 0;
- }
- if (event->data.mapping_start.tag && (emitter->canonical ||
- !event->data.mapping_start.implicit)) {
- if (!yaml_emitter_analyze_tag(emitter,
- event->data.mapping_start.tag))
- return 0;
- }
- return 1;
-
- default:
- return 1;
- }
-}
-
-/*
- * Write the BOM character.
- */
-
-static int
-yaml_emitter_write_bom(yaml_emitter_t *emitter)
-{
- if (!FLUSH(emitter)) return 0;
-
- *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF';
- *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB';
- *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF';
-
- return 1;
-}
-
-static int
-yaml_emitter_write_indent(yaml_emitter_t *emitter)
-{
- int indent = (emitter->indent >= 0) ? emitter->indent : 0;
-
- if (!emitter->indention || emitter->column > indent
- || (emitter->column == indent && !emitter->whitespace)) {
- if (!PUT_BREAK(emitter)) return 0;
- }
-
- while (emitter->column < indent) {
- if (!PUT(emitter, ' ')) return 0;
- }
-
- emitter->whitespace = 1;
- emitter->indention = 1;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_indicator(yaml_emitter_t *emitter,
- const char *indicator, int need_whitespace,
- int is_whitespace, int is_indention)
-{
- size_t indicator_length;
- yaml_string_t string;
-
- indicator_length = strlen(indicator);
- STRING_ASSIGN(string, (yaml_char_t *)indicator, indicator_length);
-
- if (need_whitespace && !emitter->whitespace) {
- if (!PUT(emitter, ' ')) return 0;
- }
-
- while (string.pointer != string.end) {
- if (!WRITE(emitter, string)) return 0;
- }
-
- emitter->whitespace = is_whitespace;
- emitter->indention = (emitter->indention && is_indention);
-
- return 1;
-}
-
-static int
-yaml_emitter_write_anchor(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
-{
- yaml_string_t string;
- STRING_ASSIGN(string, value, length);
-
- while (string.pointer != string.end) {
- if (!WRITE(emitter, string)) return 0;
- }
-
- emitter->whitespace = 0;
- emitter->indention = 0;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
-{
- yaml_string_t string;
- STRING_ASSIGN(string, value, length);
-
- if (!emitter->whitespace) {
- if (!PUT(emitter, ' ')) return 0;
- }
-
- while (string.pointer != string.end) {
- if (!WRITE(emitter, string)) return 0;
- }
-
- emitter->whitespace = 0;
- emitter->indention = 0;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length,
- int need_whitespace)
-{
- yaml_string_t string;
- STRING_ASSIGN(string, value, length);
-
- if (need_whitespace && !emitter->whitespace) {
- if (!PUT(emitter, ' ')) return 0;
- }
-
- while (string.pointer != string.end) {
- if (IS_ALPHA(string)
- || CHECK(string, ';') || CHECK(string, '/')
- || CHECK(string, '?') || CHECK(string, ':')
- || CHECK(string, '@') || CHECK(string, '&')
- || CHECK(string, '=') || CHECK(string, '+')
- || CHECK(string, '$') || CHECK(string, ',')
- || CHECK(string, '_') || CHECK(string, '.')
- || CHECK(string, '~') || CHECK(string, '*')
- || CHECK(string, '\'') || CHECK(string, '(')
- || CHECK(string, ')') || CHECK(string, '[')
- || CHECK(string, ']')) {
- if (!WRITE(emitter, string)) return 0;
- }
- else {
- int width = WIDTH(string);
- unsigned int value;
- while (width --) {
- value = *(string.pointer++);
- if (!PUT(emitter, '%')) return 0;
- if (!PUT(emitter, (value >> 4)
- + ((value >> 4) < 10 ? '0' : 'A' - 10)))
- return 0;
- if (!PUT(emitter, (value & 0x0F)
- + ((value & 0x0F) < 10 ? '0' : 'A' - 10)))
- return 0;
- }
- }
- }
-
- emitter->whitespace = 0;
- emitter->indention = 0;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks)
-{
- yaml_string_t string;
- int spaces = 0;
- int breaks = 0;
-
- STRING_ASSIGN(string, value, length);
-
- /**
- * 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;
- }
-
- while (string.pointer != string.end)
- {
- if (IS_SPACE(string))
- {
- if (allow_breaks && !spaces
- && emitter->column > emitter->best_width
- && !IS_SPACE_AT(string, 1)) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- spaces = 1;
- }
- else if (IS_BREAK(string))
- {
- if (!breaks && CHECK(string, '\n')) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- }
- if (!WRITE(emitter, string)) return 0;
- emitter->indention = 0;
- spaces = 0;
- breaks = 0;
- }
- }
-
- emitter->whitespace = 0;
- emitter->indention = 0;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks)
-{
- yaml_string_t string;
- int spaces = 0;
- int breaks = 0;
-
- STRING_ASSIGN(string, value, length);
-
- if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0))
- return 0;
-
- while (string.pointer != string.end)
- {
- if (IS_SPACE(string))
- {
- if (allow_breaks && !spaces
- && emitter->column > emitter->best_width
- && string.pointer != string.start
- && string.pointer != string.end - 1
- && !IS_SPACE_AT(string, 1)) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- spaces = 1;
- }
- else if (IS_BREAK(string))
- {
- if (!breaks && CHECK(string, '\n')) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- }
- if (CHECK(string, '\'')) {
- if (!PUT(emitter, '\'')) return 0;
- }
- if (!WRITE(emitter, string)) return 0;
- emitter->indention = 0;
- spaces = 0;
- breaks = 0;
- }
- }
-
- if (breaks)
- if (!yaml_emitter_write_indent(emitter)) return 0;
-
- if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
- return 0;
-
- emitter->whitespace = 0;
- emitter->indention = 0;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks)
-{
- yaml_string_t string;
- int spaces = 0;
-
- STRING_ASSIGN(string, value, length);
-
- if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0))
- return 0;
-
- while (string.pointer != string.end)
- {
- if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string))
- || IS_BOM(string) || IS_BREAK(string)
- || CHECK(string, '"') || CHECK(string, '\\'))
- {
- unsigned char octet;
- unsigned int width;
- unsigned int value;
- int k;
-
- octet = string.pointer[0];
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
- value = (octet & 0x80) == 0x00 ? octet & 0x7F :
- (octet & 0xE0) == 0xC0 ? octet & 0x1F :
- (octet & 0xF0) == 0xE0 ? octet & 0x0F :
- (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
- for (k = 1; k < (int)width; k ++) {
- octet = string.pointer[k];
- value = (value << 6) + (octet & 0x3F);
- }
- string.pointer += width;
-
- if (!PUT(emitter, '\\')) return 0;
-
- switch (value)
- {
- case 0x00:
- if (!PUT(emitter, '0')) return 0;
- break;
-
- case 0x07:
- if (!PUT(emitter, 'a')) return 0;
- break;
-
- case 0x08:
- if (!PUT(emitter, 'b')) return 0;
- break;
-
- case 0x09:
- if (!PUT(emitter, 't')) return 0;
- break;
-
- case 0x0A:
- if (!PUT(emitter, 'n')) return 0;
- break;
-
- case 0x0B:
- if (!PUT(emitter, 'v')) return 0;
- break;
-
- case 0x0C:
- if (!PUT(emitter, 'f')) return 0;
- break;
-
- case 0x0D:
- if (!PUT(emitter, 'r')) return 0;
- break;
-
- case 0x1B:
- if (!PUT(emitter, 'e')) return 0;
- break;
-
- case 0x22:
- if (!PUT(emitter, '\"')) return 0;
- break;
-
- case 0x5C:
- if (!PUT(emitter, '\\')) return 0;
- break;
-
- case 0x85:
- if (!PUT(emitter, 'N')) return 0;
- break;
-
- case 0xA0:
- if (!PUT(emitter, '_')) return 0;
- break;
-
- case 0x2028:
- if (!PUT(emitter, 'L')) return 0;
- break;
-
- case 0x2029:
- if (!PUT(emitter, 'P')) return 0;
- break;
-
- default:
- if (value <= 0xFF) {
- if (!PUT(emitter, 'x')) return 0;
- width = 2;
- }
- else if (value <= 0xFFFF) {
- if (!PUT(emitter, 'u')) return 0;
- width = 4;
- }
- else {
- if (!PUT(emitter, 'U')) return 0;
- width = 8;
- }
- for (k = (width-1)*4; k >= 0; k -= 4) {
- int digit = (value >> k) & 0x0F;
- if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10)))
- return 0;
- }
- }
- spaces = 0;
- }
- else if (IS_SPACE(string))
- {
- if (allow_breaks && !spaces
- && emitter->column > emitter->best_width
- && string.pointer != string.start
- && string.pointer != string.end - 1) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- if (IS_SPACE_AT(string, 1)) {
- if (!PUT(emitter, '\\')) return 0;
- }
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- spaces = 1;
- }
- else
- {
- if (!WRITE(emitter, string)) return 0;
- spaces = 0;
- }
- }
-
- if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0))
- return 0;
-
- emitter->whitespace = 0;
- emitter->indention = 0;
-
- return 1;
-}
-
-static int
-yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
- yaml_string_t string)
-{
- char indent_hint[2];
- const char *chomp_hint = NULL;
-
- if (IS_SPACE(string) || IS_BREAK(string))
- {
- indent_hint[0] = '0' + (char)emitter->best_indent;
- indent_hint[1] = '\0';
- if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0))
- return 0;
- }
-
- emitter->open_ended = 0;
-
- string.pointer = string.end;
- if (string.start == string.pointer)
- {
- chomp_hint = "-";
- }
- else
- {
- do {
- string.pointer --;
- } while ((*string.pointer & 0xC0) == 0x80);
- if (!IS_BREAK(string))
- {
- chomp_hint = "-";
- }
- else if (string.start == string.pointer)
- {
- chomp_hint = "+";
- emitter->open_ended = 2;
- }
- else
- {
- do {
- string.pointer --;
- } while ((*string.pointer & 0xC0) == 0x80);
- if (IS_BREAK(string))
- {
- chomp_hint = "+";
- emitter->open_ended = 2;
- }
- }
- }
-
- if (chomp_hint)
- {
- if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0))
- return 0;
- }
-
- return 1;
-}
-
-static int
-yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
-{
- yaml_string_t string;
- int breaks = 1;
-
- STRING_ASSIGN(string, value, length);
-
- if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_block_scalar_hints(emitter, string))
- return 0;
- if (!PUT_BREAK(emitter)) return 0;
- emitter->indention = 1;
- emitter->whitespace = 1;
-
- while (string.pointer != string.end)
- {
- if (IS_BREAK(string))
- {
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- }
- if (!WRITE(emitter, string)) return 0;
- emitter->indention = 0;
- breaks = 0;
- }
- }
-
- return 1;
-}
-
-static int
-yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
-{
- yaml_string_t string;
- int breaks = 1;
- int leading_spaces = 1;
-
- STRING_ASSIGN(string, value, length);
-
- if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_block_scalar_hints(emitter, string))
- return 0;
- if (!PUT_BREAK(emitter)) return 0;
- emitter->indention = 1;
- emitter->whitespace = 1;
-
- while (string.pointer != string.end)
- {
- if (IS_BREAK(string))
- {
- if (!breaks && !leading_spaces && CHECK(string, '\n')) {
- int k = 0;
- while (IS_BREAK_AT(string, k)) {
- k += WIDTH_AT(string, k);
- }
- if (!IS_BLANKZ_AT(string, k)) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- }
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- leading_spaces = IS_BLANK(string);
- }
- if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1)
- && emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- emitter->indention = 0;
- breaks = 0;
- }
- }
-
- return 1;
-}
diff --git a/ext/psych/yaml/loader.c b/ext/psych/yaml/loader.c
deleted file mode 100644
index bcf3aee8cb..0000000000
--- a/ext/psych/yaml/loader.c
+++ /dev/null
@@ -1,544 +0,0 @@
-
-#include "yaml_private.h"
-
-/*
- * API functions.
- */
-
-YAML_DECLARE(int)
-yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
-
-/*
- * Error handling.
- */
-
-static int
-yaml_parser_set_composer_error(yaml_parser_t *parser,
- const char *problem, yaml_mark_t problem_mark);
-
-static int
-yaml_parser_set_composer_error_context(yaml_parser_t *parser,
- const char *context, yaml_mark_t context_mark,
- const char *problem, yaml_mark_t problem_mark);
-
-
-/*
- * Alias handling.
- */
-
-static int
-yaml_parser_register_anchor(yaml_parser_t *parser,
- int index, yaml_char_t *anchor);
-
-/*
- * Clean up functions.
- */
-
-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_alias(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 *event,
- struct loader_ctx *ctx);
-
-static int
-yaml_parser_load_sequence(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 *event,
- struct loader_ctx *ctx);
-
-static int
-yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
- struct loader_ctx *ctx);
-
-static int
-yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
- struct loader_ctx *ctx);
-
-/*
- * Load the next document of the stream.
- */
-
-YAML_DECLARE(int)
-yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
-{
- yaml_event_t event;
-
- assert(parser); /* Non-NULL parser object is expected. */
- assert(document); /* Non-NULL document object is expected. */
-
- memset(document, 0, sizeof(yaml_document_t));
- if (!STACK_INIT(parser, document->nodes, yaml_node_t*))
- goto error;
-
- if (!parser->stream_start_produced) {
- if (!yaml_parser_parse(parser, &event)) goto error;
- assert(event.type == YAML_STREAM_START_EVENT);
- /* STREAM-START is expected. */
- }
-
- if (parser->stream_end_produced) {
- return 1;
- }
-
- if (!yaml_parser_parse(parser, &event)) goto error;
- if (event.type == YAML_STREAM_END_EVENT) {
- return 1;
- }
-
- if (!STACK_INIT(parser, parser->aliases, yaml_alias_data_t*))
- goto error;
-
- parser->document = document;
-
- if (!yaml_parser_load_document(parser, &event)) goto error;
-
- yaml_parser_delete_aliases(parser);
- parser->document = NULL;
-
- return 1;
-
-error:
-
- yaml_parser_delete_aliases(parser);
- yaml_document_delete(document);
- parser->document = NULL;
-
- return 0;
-}
-
-/*
- * Set composer error.
- */
-
-static int
-yaml_parser_set_composer_error(yaml_parser_t *parser,
- const char *problem, yaml_mark_t problem_mark)
-{
- parser->error = YAML_COMPOSER_ERROR;
- parser->problem = problem;
- parser->problem_mark = problem_mark;
-
- return 0;
-}
-
-/*
- * Set composer error with context.
- */
-
-static int
-yaml_parser_set_composer_error_context(yaml_parser_t *parser,
- const char *context, yaml_mark_t context_mark,
- const char *problem, yaml_mark_t problem_mark)
-{
- parser->error = YAML_COMPOSER_ERROR;
- parser->context = context;
- parser->context_mark = context_mark;
- parser->problem = problem;
- parser->problem_mark = problem_mark;
-
- return 0;
-}
-
-/*
- * Delete the stack of aliases.
- */
-
-static void
-yaml_parser_delete_aliases(yaml_parser_t *parser)
-{
- while (!STACK_EMPTY(parser, parser->aliases)) {
- yaml_free(POP(parser, parser->aliases).anchor);
- }
- STACK_DEL(parser, parser->aliases);
-}
-
-/*
- * Compose a document object.
- */
-
-static int
-yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event)
-{
- struct loader_ctx ctx = { NULL, NULL, NULL };
-
- assert(event->type == YAML_DOCUMENT_START_EVENT);
- /* DOCUMENT-START is expected. */
-
- parser->document->version_directive
- = event->data.document_start.version_directive;
- parser->document->tag_directives.start
- = event->data.document_start.tag_directives.start;
- parser->document->tag_directives.end
- = event->data.document_start.tag_directives.end;
- parser->document->start_implicit
- = event->data.document_start.implicit;
- parser->document->start_mark = event->start_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 tree.
- */
-
-static int
-yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx)
-{
- yaml_event_t event;
-
- 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;
-}
-
-/*
- * Add an anchor.
- */
-
-static int
-yaml_parser_register_anchor(yaml_parser_t *parser,
- int index, yaml_char_t *anchor)
-{
- yaml_alias_data_t data;
- yaml_alias_data_t *alias_data;
-
- if (!anchor) return 1;
-
- data.anchor = anchor;
- data.index = index;
- data.mark = parser->document->nodes.start[index-1].start_mark;
-
- 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 yaml_parser_set_composer_error_context(parser,
- "found duplicate anchor; first occurrence",
- alias_data->mark, "second occurrence", data.mark);
- }
- }
-
- if (!PUSH(parser, parser->aliases, data)) {
- yaml_free(anchor);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Compose node into its parent in the stree.
- */
-
-static int
-yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx,
- int index)
-{
- struct yaml_node_s *parent;
- int parent_index;
-
- if (STACK_EMPTY(parser, *ctx)) {
- /* This is the root node, there's no tree to add it to. */
- return 1;
- }
-
- parent_index = *((*ctx).top - 1);
- parent = &parser->document->nodes.start[parent_index-1];
-
- switch (parent->type) {
- case YAML_SEQUENCE_NODE:
- if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1))
- return 0;
- if (!PUSH(parser, parent->data.sequence.items, index))
- return 0;
- break;
- case YAML_MAPPING_NODE: {
- yaml_node_pair_t pair;
- if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) {
- yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1;
- if (p->key != 0 && p->value == 0) {
- p->value = index;
- break;
- }
- }
-
- pair.key = index;
- pair.value = 0;
- if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1))
- return 0;
- if (!PUSH(parser, parent->data.mapping.pairs, pair))
- return 0;
-
- break;
- }
- default:
- assert(0); /* Could not happen. */
- return 0;
- }
- return 1;
-}
-
-/*
- * Compose a node corresponding to an alias.
- */
-
-static int
-yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
- struct loader_ctx *ctx)
-{
- 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 yaml_parser_load_node_add(parser, ctx, alias_data->index);
- }
- }
-
- yaml_free(anchor);
- return yaml_parser_set_composer_error(parser, "found undefined alias",
- event->start_mark);
-}
-
-/*
- * Compose a scalar node.
- */
-
-static int
-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 = event->data.scalar.tag;
-
- if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
-
- if (!tag || strcmp((char *)tag, "!") == 0) {
- yaml_free(tag);
- tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
- if (!tag) goto error;
- }
-
- 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,
- event->data.scalar.anchor)) return 0;
-
- return yaml_parser_load_node_add(parser, ctx, index);
-
-error:
- yaml_free(tag);
- yaml_free(event->data.scalar.anchor);
- yaml_free(event->data.scalar.value);
- return 0;
-}
-
-/*
- * Compose a sequence node.
- */
-
-static int
-yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
- struct loader_ctx *ctx)
-{
- 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;
- yaml_char_t *tag = event->data.sequence_start.tag;
-
- if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
-
- if (!tag || strcmp((char *)tag, "!") == 0) {
- yaml_free(tag);
- tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
- if (!tag) goto error;
- }
-
- if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error;
-
- SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
- 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,
- event->data.sequence_start.anchor)) return 0;
-
- if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;
-
- 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(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 *event,
- struct loader_ctx *ctx)
-{
- yaml_node_t node;
- struct {
- yaml_node_pair_t *start;
- yaml_node_pair_t *end;
- yaml_node_pair_t *top;
- } pairs = { NULL, NULL, NULL };
- int index;
- yaml_char_t *tag = event->data.mapping_start.tag;
-
- if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
-
- if (!tag || strcmp((char *)tag, "!") == 0) {
- yaml_free(tag);
- tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
- if (!tag) goto error;
- }
-
- if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error;
-
- MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
- 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,
- event->data.mapping_start.anchor)) return 0;
-
- if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;
-
- 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(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
deleted file mode 100644
index ec2f8d3e05..0000000000
--- a/ext/psych/yaml/parser.c
+++ /dev/null
@@ -1,1375 +0,0 @@
-
-/*
- * The parser implements the following grammar:
- *
- * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
- * implicit_document ::= block_node DOCUMENT-END*
- * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
- * block_node_or_indentless_sequence ::=
- * ALIAS
- * | properties (block_content | indentless_block_sequence)?
- * | block_content
- * | indentless_block_sequence
- * block_node ::= ALIAS
- * | properties block_content?
- * | block_content
- * flow_node ::= ALIAS
- * | properties flow_content?
- * | flow_content
- * properties ::= TAG ANCHOR? | ANCHOR TAG?
- * block_content ::= block_collection | flow_collection | SCALAR
- * flow_content ::= flow_collection | SCALAR
- * block_collection ::= block_sequence | block_mapping
- * flow_collection ::= flow_sequence | flow_mapping
- * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
- * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
- * block_mapping ::= BLOCK-MAPPING_START
- * ((KEY block_node_or_indentless_sequence?)?
- * (VALUE block_node_or_indentless_sequence?)?)*
- * BLOCK-END
- * flow_sequence ::= FLOW-SEQUENCE-START
- * (flow_sequence_entry FLOW-ENTRY)*
- * flow_sequence_entry?
- * FLOW-SEQUENCE-END
- * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * flow_mapping ::= FLOW-MAPPING-START
- * (flow_mapping_entry FLOW-ENTRY)*
- * flow_mapping_entry?
- * FLOW-MAPPING-END
- * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- */
-
-#include "yaml_private.h"
-
-/*
- * Peek the next token in the token queue.
- */
-
-#define PEEK_TOKEN(parser) \
- ((parser->token_available || yaml_parser_fetch_more_tokens(parser)) ? \
- parser->tokens.head : NULL)
-
-/*
- * Remove the next token from the queue (must be called after PEEK_TOKEN).
- */
-
-#define SKIP_TOKEN(parser) \
- (parser->token_available = 0, \
- parser->tokens_parsed ++, \
- parser->stream_end_produced = \
- (parser->tokens.head->type == YAML_STREAM_END_TOKEN), \
- parser->tokens.head ++)
-
-/*
- * Public API declarations.
- */
-
-YAML_DECLARE(int)
-yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
-
-/*
- * Error handling.
- */
-
-static int
-yaml_parser_set_parser_error(yaml_parser_t *parser,
- const char *problem, yaml_mark_t problem_mark);
-
-static int
-yaml_parser_set_parser_error_context(yaml_parser_t *parser,
- const char *context, yaml_mark_t context_mark,
- const char *problem, yaml_mark_t problem_mark);
-
-/*
- * State functions.
- */
-
-static int
-yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event);
-
-static int
-yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event);
-
-static int
-yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
- int implicit);
-
-static int
-yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event);
-
-static int
-yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event);
-
-static int
-yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
- int block, int indentless_sequence);
-
-static int
-yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
- yaml_event_t *event, int first);
-
-static int
-yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
- yaml_event_t *event);
-
-static int
-yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
- yaml_event_t *event, int first);
-
-static int
-yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
- yaml_event_t *event);
-
-static int
-yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
- yaml_event_t *event, int first);
-
-static int
-yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
- yaml_event_t *event);
-
-static int
-yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
- yaml_event_t *event);
-
-static int
-yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
- yaml_event_t *event);
-
-static int
-yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
- yaml_event_t *event, int first);
-
-static int
-yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
- yaml_event_t *event, int empty);
-
-/*
- * Utility functions.
- */
-
-static int
-yaml_parser_process_empty_scalar(yaml_parser_t *parser,
- yaml_event_t *event, yaml_mark_t mark);
-
-static int
-yaml_parser_process_directives(yaml_parser_t *parser,
- yaml_version_directive_t **version_directive_ref,
- yaml_tag_directive_t **tag_directives_start_ref,
- yaml_tag_directive_t **tag_directives_end_ref);
-
-static int
-yaml_parser_append_tag_directive(yaml_parser_t *parser,
- yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark);
-
-/*
- * Get the next event.
- */
-
-YAML_DECLARE(int)
-yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event)
-{
- assert(parser); /* Non-NULL parser object is expected. */
- assert(event); /* Non-NULL event object is expected. */
-
- /* Erase the event object. */
-
- memset(event, 0, sizeof(yaml_event_t));
-
- /* No events after the end of the stream or error. */
-
- if (parser->stream_end_produced || parser->error ||
- parser->state == YAML_PARSE_END_STATE) {
- return 1;
- }
-
- /* Generate the next event. */
-
- return yaml_parser_state_machine(parser, event);
-}
-
-/*
- * Set parser error.
- */
-
-static int
-yaml_parser_set_parser_error(yaml_parser_t *parser,
- const char *problem, yaml_mark_t problem_mark)
-{
- parser->error = YAML_PARSER_ERROR;
- parser->problem = problem;
- parser->problem_mark = problem_mark;
-
- return 0;
-}
-
-static int
-yaml_parser_set_parser_error_context(yaml_parser_t *parser,
- const char *context, yaml_mark_t context_mark,
- const char *problem, yaml_mark_t problem_mark)
-{
- parser->error = YAML_PARSER_ERROR;
- parser->context = context;
- parser->context_mark = context_mark;
- parser->problem = problem;
- parser->problem_mark = problem_mark;
-
- return 0;
-}
-
-
-/*
- * State dispatcher.
- */
-
-static int
-yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event)
-{
- switch (parser->state)
- {
- case YAML_PARSE_STREAM_START_STATE:
- return yaml_parser_parse_stream_start(parser, event);
-
- case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
- return yaml_parser_parse_document_start(parser, event, 1);
-
- case YAML_PARSE_DOCUMENT_START_STATE:
- return yaml_parser_parse_document_start(parser, event, 0);
-
- case YAML_PARSE_DOCUMENT_CONTENT_STATE:
- return yaml_parser_parse_document_content(parser, event);
-
- case YAML_PARSE_DOCUMENT_END_STATE:
- return yaml_parser_parse_document_end(parser, event);
-
- case YAML_PARSE_BLOCK_NODE_STATE:
- return yaml_parser_parse_node(parser, event, 1, 0);
-
- case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
- return yaml_parser_parse_node(parser, event, 1, 1);
-
- case YAML_PARSE_FLOW_NODE_STATE:
- return yaml_parser_parse_node(parser, event, 0, 0);
-
- case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
- return yaml_parser_parse_block_sequence_entry(parser, event, 1);
-
- case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
- return yaml_parser_parse_block_sequence_entry(parser, event, 0);
-
- case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
- return yaml_parser_parse_indentless_sequence_entry(parser, event);
-
- case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
- return yaml_parser_parse_block_mapping_key(parser, event, 1);
-
- case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
- return yaml_parser_parse_block_mapping_key(parser, event, 0);
-
- case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
- return yaml_parser_parse_block_mapping_value(parser, event);
-
- case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
- return yaml_parser_parse_flow_sequence_entry(parser, event, 1);
-
- case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
- return yaml_parser_parse_flow_sequence_entry(parser, event, 0);
-
- case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
- return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event);
-
- case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
- return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event);
-
- case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
- return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event);
-
- case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
- return yaml_parser_parse_flow_mapping_key(parser, event, 1);
-
- case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
- return yaml_parser_parse_flow_mapping_key(parser, event, 0);
-
- case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
- return yaml_parser_parse_flow_mapping_value(parser, event, 0);
-
- case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
- return yaml_parser_parse_flow_mapping_value(parser, event, 1);
-
- default:
- assert(1); /* Invalid state. */
- }
-
- return 0;
-}
-
-/*
- * Parse the production:
- * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
- * ************
- */
-
-static int
-yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type != YAML_STREAM_START_TOKEN) {
- return yaml_parser_set_parser_error(parser,
- "did not find expected <stream-start>", token->start_mark);
- }
-
- parser->state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE;
- STREAM_START_EVENT_INIT(*event, token->data.stream_start.encoding,
- token->start_mark, token->start_mark);
- SKIP_TOKEN(parser);
-
- return 1;
-}
-
-/*
- * Parse the productions:
- * implicit_document ::= block_node DOCUMENT-END*
- * *
- * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
- * *************************
- */
-
-static int
-yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
- int implicit)
-{
- yaml_token_t *token;
- yaml_version_directive_t *version_directive = NULL;
- struct {
- yaml_tag_directive_t *start;
- yaml_tag_directive_t *end;
- } tag_directives = { NULL, NULL };
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- /* Parse extra document end indicators. */
-
- if (!implicit)
- {
- while (token->type == YAML_DOCUMENT_END_TOKEN) {
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- }
- }
-
- /* Parse an implicit document. */
-
- if (implicit && token->type != YAML_VERSION_DIRECTIVE_TOKEN &&
- token->type != YAML_TAG_DIRECTIVE_TOKEN &&
- token->type != YAML_DOCUMENT_START_TOKEN &&
- token->type != YAML_STREAM_END_TOKEN)
- {
- if (!yaml_parser_process_directives(parser, NULL, NULL, NULL))
- return 0;
- if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
- return 0;
- parser->state = YAML_PARSE_BLOCK_NODE_STATE;
- DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, NULL, 1,
- token->start_mark, token->start_mark);
- return 1;
- }
-
- /* Parse an explicit document. */
-
- else if (token->type != YAML_STREAM_END_TOKEN)
- {
- yaml_mark_t start_mark, end_mark;
- start_mark = token->start_mark;
- if (!yaml_parser_process_directives(parser, &version_directive,
- &tag_directives.start, &tag_directives.end))
- return 0;
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
- if (token->type != YAML_DOCUMENT_START_TOKEN) {
- yaml_parser_set_parser_error(parser,
- "did not find expected <document start>", token->start_mark);
- goto error;
- }
- if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
- goto error;
- parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE;
- end_mark = token->end_mark;
- DOCUMENT_START_EVENT_INIT(*event, version_directive,
- tag_directives.start, tag_directives.end, 0,
- start_mark, end_mark);
- SKIP_TOKEN(parser);
- version_directive = NULL;
- tag_directives.start = tag_directives.end = NULL;
- return 1;
- }
-
- /* Parse the stream end. */
-
- else
- {
- parser->state = YAML_PARSE_END_STATE;
- STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
- }
-
-error:
- yaml_free(version_directive);
- while (tag_directives.start != tag_directives.end) {
- yaml_free(tag_directives.end[-1].handle);
- yaml_free(tag_directives.end[-1].prefix);
- tag_directives.end --;
- }
- yaml_free(tag_directives.start);
- return 0;
-}
-
-/*
- * Parse the productions:
- * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
- * ***********
- */
-
-static int
-yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
- token->type == YAML_TAG_DIRECTIVE_TOKEN ||
- token->type == YAML_DOCUMENT_START_TOKEN ||
- token->type == YAML_DOCUMENT_END_TOKEN ||
- token->type == YAML_STREAM_END_TOKEN) {
- parser->state = POP(parser, parser->states);
- return yaml_parser_process_empty_scalar(parser, event,
- token->start_mark);
- }
- else {
- return yaml_parser_parse_node(parser, event, 1, 0);
- }
-}
-
-/*
- * Parse the productions:
- * implicit_document ::= block_node DOCUMENT-END*
- * *************
- * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
- * *************
- */
-
-static int
-yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event)
-{
- yaml_token_t *token;
- yaml_mark_t start_mark, end_mark;
- int implicit = 1;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- start_mark = end_mark = token->start_mark;
-
- if (token->type == YAML_DOCUMENT_END_TOKEN) {
- end_mark = token->end_mark;
- SKIP_TOKEN(parser);
- implicit = 0;
- }
-
- while (!STACK_EMPTY(parser, parser->tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
-
- parser->state = YAML_PARSE_DOCUMENT_START_STATE;
- DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark);
-
- return 1;
-}
-
-/*
- * Parse the productions:
- * block_node_or_indentless_sequence ::=
- * ALIAS
- * *****
- * | properties (block_content | indentless_block_sequence)?
- * ********** *
- * | block_content | indentless_block_sequence
- * *
- * block_node ::= ALIAS
- * *****
- * | properties block_content?
- * ********** *
- * | block_content
- * *
- * flow_node ::= ALIAS
- * *****
- * | properties flow_content?
- * ********** *
- * | flow_content
- * *
- * properties ::= TAG ANCHOR? | ANCHOR TAG?
- * *************************
- * block_content ::= block_collection | flow_collection | SCALAR
- * ******
- * flow_content ::= flow_collection | SCALAR
- * ******
- */
-
-static int
-yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
- int block, int indentless_sequence)
-{
- yaml_token_t *token;
- yaml_char_t *anchor = NULL;
- yaml_char_t *tag_handle = NULL;
- yaml_char_t *tag_suffix = NULL;
- yaml_char_t *tag = NULL;
- yaml_mark_t start_mark, end_mark, tag_mark;
- int implicit;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_ALIAS_TOKEN)
- {
- parser->state = POP(parser, parser->states);
- ALIAS_EVENT_INIT(*event, token->data.alias.value,
- token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
- }
-
- else
- {
- start_mark = end_mark = token->start_mark;
-
- if (token->type == YAML_ANCHOR_TOKEN)
- {
- anchor = token->data.anchor.value;
- start_mark = token->start_mark;
- end_mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
- if (token->type == YAML_TAG_TOKEN)
- {
- tag_handle = token->data.tag.handle;
- tag_suffix = token->data.tag.suffix;
- tag_mark = token->start_mark;
- end_mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
- }
- }
- else if (token->type == YAML_TAG_TOKEN)
- {
- tag_handle = token->data.tag.handle;
- tag_suffix = token->data.tag.suffix;
- start_mark = tag_mark = token->start_mark;
- end_mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
- if (token->type == YAML_ANCHOR_TOKEN)
- {
- anchor = token->data.anchor.value;
- end_mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
- }
- }
-
- if (tag_handle) {
- if (!*tag_handle) {
- tag = tag_suffix;
- yaml_free(tag_handle);
- tag_handle = tag_suffix = NULL;
- }
- else {
- yaml_tag_directive_t *tag_directive;
- for (tag_directive = parser->tag_directives.start;
- tag_directive != parser->tag_directives.top;
- tag_directive ++) {
- if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) {
- size_t prefix_len = strlen((char *)tag_directive->prefix);
- size_t suffix_len = strlen((char *)tag_suffix);
- tag = YAML_MALLOC(prefix_len+suffix_len+1);
- if (!tag) {
- parser->error = YAML_MEMORY_ERROR;
- goto error;
- }
- memcpy(tag, tag_directive->prefix, prefix_len);
- memcpy(tag+prefix_len, tag_suffix, suffix_len);
- tag[prefix_len+suffix_len] = '\0';
- yaml_free(tag_handle);
- yaml_free(tag_suffix);
- tag_handle = tag_suffix = NULL;
- break;
- }
- }
- if (!tag) {
- yaml_parser_set_parser_error_context(parser,
- "while parsing a node", start_mark,
- "found undefined tag handle", tag_mark);
- goto error;
- }
- }
- }
-
- implicit = (!tag || !*tag);
- if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) {
- end_mark = token->end_mark;
- parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
- SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
- YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
- return 1;
- }
- else {
- if (token->type == YAML_SCALAR_TOKEN) {
- int plain_implicit = 0;
- int quoted_implicit = 0;
- end_mark = token->end_mark;
- if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag)
- || (tag && strcmp((char *)tag, "!") == 0)) {
- plain_implicit = 1;
- }
- else if (!tag) {
- quoted_implicit = 1;
- }
- parser->state = POP(parser, parser->states);
- SCALAR_EVENT_INIT(*event, anchor, tag,
- token->data.scalar.value, token->data.scalar.length,
- plain_implicit, quoted_implicit,
- token->data.scalar.style, start_mark, end_mark);
- SKIP_TOKEN(parser);
- return 1;
- }
- else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) {
- end_mark = token->end_mark;
- parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
- SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
- YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark);
- return 1;
- }
- else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) {
- end_mark = token->end_mark;
- parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
- MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
- YAML_FLOW_MAPPING_STYLE, start_mark, end_mark);
- return 1;
- }
- else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) {
- end_mark = token->end_mark;
- parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
- SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
- YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
- return 1;
- }
- else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) {
- end_mark = token->end_mark;
- parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
- MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
- YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark);
- return 1;
- }
- else if (anchor || tag) {
- yaml_char_t *value = YAML_MALLOC(1);
- if (!value) {
- parser->error = YAML_MEMORY_ERROR;
- goto error;
- }
- value[0] = '\0';
- parser->state = POP(parser, parser->states);
- SCALAR_EVENT_INIT(*event, anchor, tag, value, 0,
- implicit, 0, YAML_PLAIN_SCALAR_STYLE,
- start_mark, end_mark);
- return 1;
- }
- else {
- yaml_parser_set_parser_error_context(parser,
- (block ? "while parsing a block node"
- : "while parsing a flow node"), start_mark,
- "did not find expected node content", token->start_mark);
- goto error;
- }
- }
- }
-
-error:
- yaml_free(anchor);
- yaml_free(tag_handle);
- yaml_free(tag_suffix);
- yaml_free(tag);
-
- return 0;
-}
-
-/*
- * Parse the productions:
- * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
- * ******************** *********** * *********
- */
-
-static int
-yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
- yaml_event_t *event, int first)
-{
- yaml_token_t *token;
-
- if (first) {
- token = PEEK_TOKEN(parser);
- if (!PUSH(parser, parser->marks, token->start_mark))
- return 0;
- SKIP_TOKEN(parser);
- }
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_BLOCK_ENTRY_TOKEN)
- {
- yaml_mark_t mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
- token->type != YAML_BLOCK_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 1, 0);
- }
- else {
- parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE;
- return yaml_parser_process_empty_scalar(parser, event, mark);
- }
- }
-
- else if (token->type == YAML_BLOCK_END_TOKEN)
- {
- parser->state = POP(parser, parser->states);
- (void)POP(parser, parser->marks);
- SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
- }
-
- else
- {
- return yaml_parser_set_parser_error_context(parser,
- "while parsing a block collection", POP(parser, parser->marks),
- "did not find expected '-' indicator", token->start_mark);
- }
-}
-
-/*
- * Parse the productions:
- * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
- * *********** *
- */
-
-static int
-yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
- yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_BLOCK_ENTRY_TOKEN)
- {
- yaml_mark_t mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
- token->type != YAML_KEY_TOKEN &&
- token->type != YAML_VALUE_TOKEN &&
- token->type != YAML_BLOCK_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 1, 0);
- }
- else {
- parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
- return yaml_parser_process_empty_scalar(parser, event, mark);
- }
- }
-
- else
- {
- parser->state = POP(parser, parser->states);
- SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
- return 1;
- }
-}
-
-/*
- * Parse the productions:
- * block_mapping ::= BLOCK-MAPPING_START
- * *******************
- * ((KEY block_node_or_indentless_sequence?)?
- * *** *
- * (VALUE block_node_or_indentless_sequence?)?)*
- *
- * BLOCK-END
- * *********
- */
-
-static int
-yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
- yaml_event_t *event, int first)
-{
- yaml_token_t *token;
-
- if (first) {
- token = PEEK_TOKEN(parser);
- if (!PUSH(parser, parser->marks, token->start_mark))
- return 0;
- SKIP_TOKEN(parser);
- }
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_KEY_TOKEN)
- {
- yaml_mark_t mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_KEY_TOKEN &&
- token->type != YAML_VALUE_TOKEN &&
- token->type != YAML_BLOCK_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_BLOCK_MAPPING_VALUE_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 1, 1);
- }
- else {
- parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE;
- return yaml_parser_process_empty_scalar(parser, event, mark);
- }
- }
-
- else if (token->type == YAML_BLOCK_END_TOKEN)
- {
- parser->state = POP(parser, parser->states);
- (void)POP(parser, parser->marks);
- MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
- }
-
- else
- {
- return yaml_parser_set_parser_error_context(parser,
- "while parsing a block mapping", POP(parser, parser->marks),
- "did not find expected key", token->start_mark);
- }
-}
-
-/*
- * Parse the productions:
- * block_mapping ::= BLOCK-MAPPING_START
- *
- * ((KEY block_node_or_indentless_sequence?)?
- *
- * (VALUE block_node_or_indentless_sequence?)?)*
- * ***** *
- * BLOCK-END
- *
- */
-
-static int
-yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
- yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_VALUE_TOKEN)
- {
- yaml_mark_t mark = token->end_mark;
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_KEY_TOKEN &&
- token->type != YAML_VALUE_TOKEN &&
- token->type != YAML_BLOCK_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_BLOCK_MAPPING_KEY_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 1, 1);
- }
- else {
- parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
- return yaml_parser_process_empty_scalar(parser, event, mark);
- }
- }
-
- else
- {
- parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
- return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
- }
-}
-
-/*
- * Parse the productions:
- * flow_sequence ::= FLOW-SEQUENCE-START
- * *******************
- * (flow_sequence_entry FLOW-ENTRY)*
- * * **********
- * flow_sequence_entry?
- * *
- * FLOW-SEQUENCE-END
- * *****************
- * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * *
- */
-
-static int
-yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
- yaml_event_t *event, int first)
-{
- yaml_token_t *token;
-
- if (first) {
- token = PEEK_TOKEN(parser);
- if (!PUSH(parser, parser->marks, token->start_mark))
- return 0;
- SKIP_TOKEN(parser);
- }
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN)
- {
- if (!first) {
- if (token->type == YAML_FLOW_ENTRY_TOKEN) {
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- }
- else {
- return yaml_parser_set_parser_error_context(parser,
- "while parsing a flow sequence", POP(parser, parser->marks),
- "did not find expected ',' or ']'", token->start_mark);
- }
- }
-
- if (token->type == YAML_KEY_TOKEN) {
- parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE;
- MAPPING_START_EVENT_INIT(*event, NULL, NULL,
- 1, YAML_FLOW_MAPPING_STYLE,
- token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
- }
-
- else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 0, 0);
- }
- }
-
- parser->state = POP(parser, parser->states);
- (void)POP(parser, parser->marks);
- SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
-}
-
-/*
- * Parse the productions:
- * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * *** *
- */
-
-static int
-yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
- yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN
- && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 0, 0);
- }
- else {
- yaml_mark_t mark = token->end_mark;
- SKIP_TOKEN(parser);
- parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE;
- return yaml_parser_process_empty_scalar(parser, event, mark);
- }
-}
-
-/*
- * Parse the productions:
- * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * ***** *
- */
-
-static int
-yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
- yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type == YAML_VALUE_TOKEN) {
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_FLOW_ENTRY_TOKEN
- && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 0, 0);
- }
- }
- parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE;
- return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
-}
-
-/*
- * Parse the productions:
- * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * *
- */
-
-static int
-yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
- yaml_event_t *event)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE;
-
- MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
- return 1;
-}
-
-/*
- * Parse the productions:
- * flow_mapping ::= FLOW-MAPPING-START
- * ******************
- * (flow_mapping_entry FLOW-ENTRY)*
- * * **********
- * flow_mapping_entry?
- * ******************
- * FLOW-MAPPING-END
- * ****************
- * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * * *** *
- */
-
-static int
-yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
- yaml_event_t *event, int first)
-{
- yaml_token_t *token;
-
- if (first) {
- token = PEEK_TOKEN(parser);
- if (!PUSH(parser, parser->marks, token->start_mark))
- return 0;
- SKIP_TOKEN(parser);
- }
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (token->type != YAML_FLOW_MAPPING_END_TOKEN)
- {
- if (!first) {
- if (token->type == YAML_FLOW_ENTRY_TOKEN) {
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- }
- else {
- return yaml_parser_set_parser_error_context(parser,
- "while parsing a flow mapping", POP(parser, parser->marks),
- "did not find expected ',' or '}'", token->start_mark);
- }
- }
-
- if (token->type == YAML_KEY_TOKEN) {
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_VALUE_TOKEN
- && token->type != YAML_FLOW_ENTRY_TOKEN
- && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_FLOW_MAPPING_VALUE_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 0, 0);
- }
- else {
- parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE;
- return yaml_parser_process_empty_scalar(parser, event,
- token->start_mark);
- }
- }
- else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 0, 0);
- }
- }
-
- parser->state = POP(parser, parser->states);
- (void)POP(parser, parser->marks);
- MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
- SKIP_TOKEN(parser);
- return 1;
-}
-
-/*
- * Parse the productions:
- * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
- * * ***** *
- */
-
-static int
-yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
- yaml_event_t *event, int empty)
-{
- yaml_token_t *token;
-
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
-
- if (empty) {
- parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
- return yaml_parser_process_empty_scalar(parser, event,
- token->start_mark);
- }
-
- if (token->type == YAML_VALUE_TOKEN) {
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) return 0;
- if (token->type != YAML_FLOW_ENTRY_TOKEN
- && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
- if (!PUSH(parser, parser->states,
- YAML_PARSE_FLOW_MAPPING_KEY_STATE))
- return 0;
- return yaml_parser_parse_node(parser, event, 0, 0);
- }
- }
-
- parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
- return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
-}
-
-/*
- * Generate an empty scalar event.
- */
-
-static int
-yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event,
- yaml_mark_t mark)
-{
- yaml_char_t *value;
-
- value = YAML_MALLOC(1);
- if (!value) {
- parser->error = YAML_MEMORY_ERROR;
- return 0;
- }
- value[0] = '\0';
-
- SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0,
- 1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark);
-
- return 1;
-}
-
-/*
- * Parse directives.
- */
-
-static int
-yaml_parser_process_directives(yaml_parser_t *parser,
- yaml_version_directive_t **version_directive_ref,
- yaml_tag_directive_t **tag_directives_start_ref,
- yaml_tag_directive_t **tag_directives_end_ref)
-{
- yaml_tag_directive_t default_tag_directives[] = {
- {(yaml_char_t *)"!", (yaml_char_t *)"!"},
- {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
- {NULL, NULL}
- };
- yaml_tag_directive_t *default_tag_directive;
- yaml_version_directive_t *version_directive = NULL;
- struct {
- yaml_tag_directive_t *start;
- yaml_tag_directive_t *end;
- yaml_tag_directive_t *top;
- } tag_directives = { NULL, NULL, NULL };
- yaml_token_t *token;
-
- if (!STACK_INIT(parser, tag_directives, yaml_tag_directive_t*))
- goto error;
-
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
-
- while (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
- token->type == YAML_TAG_DIRECTIVE_TOKEN)
- {
- if (token->type == YAML_VERSION_DIRECTIVE_TOKEN) {
- if (version_directive) {
- yaml_parser_set_parser_error(parser,
- "found duplicate %YAML directive", token->start_mark);
- goto error;
- }
- if (token->data.version_directive.major != 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;
- }
- version_directive = YAML_MALLOC_STATIC(yaml_version_directive_t);
- if (!version_directive) {
- parser->error = YAML_MEMORY_ERROR;
- goto error;
- }
- version_directive->major = token->data.version_directive.major;
- version_directive->minor = token->data.version_directive.minor;
- }
-
- else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) {
- yaml_tag_directive_t value;
- value.handle = token->data.tag_directive.handle;
- value.prefix = token->data.tag_directive.prefix;
-
- if (!yaml_parser_append_tag_directive(parser, value, 0,
- token->start_mark))
- goto error;
- if (!PUSH(parser, tag_directives, value))
- goto error;
- }
-
- SKIP_TOKEN(parser);
- token = PEEK_TOKEN(parser);
- if (!token) goto error;
- }
-
- for (default_tag_directive = default_tag_directives;
- default_tag_directive->handle; default_tag_directive++) {
- if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1,
- token->start_mark))
- goto error;
- }
-
- if (version_directive_ref) {
- *version_directive_ref = version_directive;
- }
- if (tag_directives_start_ref) {
- if (STACK_EMPTY(parser, tag_directives)) {
- *tag_directives_start_ref = *tag_directives_end_ref = NULL;
- STACK_DEL(parser, tag_directives);
- }
- else {
- *tag_directives_start_ref = tag_directives.start;
- *tag_directives_end_ref = tag_directives.top;
- }
- }
- else {
- STACK_DEL(parser, tag_directives);
- }
-
- if (!version_directive_ref)
- yaml_free(version_directive);
- return 1;
-
-error:
- yaml_free(version_directive);
- while (!STACK_EMPTY(parser, tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(parser, tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
- STACK_DEL(parser, tag_directives);
- return 0;
-}
-
-/*
- * Append a tag directive to the directives stack.
- */
-
-static int
-yaml_parser_append_tag_directive(yaml_parser_t *parser,
- yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark)
-{
- yaml_tag_directive_t *tag_directive;
- yaml_tag_directive_t copy = { NULL, NULL };
-
- for (tag_directive = parser->tag_directives.start;
- tag_directive != parser->tag_directives.top; tag_directive ++) {
- if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
- if (allow_duplicates)
- return 1;
- return yaml_parser_set_parser_error(parser,
- "found duplicate %TAG directive", mark);
- }
- }
-
- copy.handle = yaml_strdup(value.handle);
- copy.prefix = yaml_strdup(value.prefix);
- if (!copy.handle || !copy.prefix) {
- parser->error = YAML_MEMORY_ERROR;
- goto error;
- }
-
- if (!PUSH(parser, parser->tag_directives, copy))
- goto error;
-
- return 1;
-
-error:
- yaml_free(copy.handle);
- yaml_free(copy.prefix);
- return 0;
-}
-
diff --git a/ext/psych/yaml/reader.c b/ext/psych/yaml/reader.c
deleted file mode 100644
index f3ac54c251..0000000000
--- a/ext/psych/yaml/reader.c
+++ /dev/null
@@ -1,469 +0,0 @@
-
-#include "yaml_private.h"
-
-/*
- * Declarations.
- */
-
-static int
-yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
- size_t offset, int value);
-
-static int
-yaml_parser_update_raw_buffer(yaml_parser_t *parser);
-
-static int
-yaml_parser_determine_encoding(yaml_parser_t *parser);
-
-YAML_DECLARE(int)
-yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
-
-/*
- * Set the reader error and return 0.
- */
-
-static int
-yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
- size_t offset, int value)
-{
- parser->error = YAML_READER_ERROR;
- parser->problem = problem;
- parser->problem_offset = offset;
- parser->problem_value = value;
-
- return 0;
-}
-
-/*
- * Byte order marks.
- */
-
-#define BOM_UTF8 "\xef\xbb\xbf"
-#define BOM_UTF16LE "\xff\xfe"
-#define BOM_UTF16BE "\xfe\xff"
-
-/*
- * Determine the input stream encoding by checking the BOM symbol. If no BOM is
- * found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
- */
-
-static int
-yaml_parser_determine_encoding(yaml_parser_t *parser)
-{
- /* Ensure that we had enough bytes in the raw buffer. */
-
- while (!parser->eof
- && parser->raw_buffer.last - parser->raw_buffer.pointer < 3) {
- if (!yaml_parser_update_raw_buffer(parser)) {
- return 0;
- }
- }
-
- /* Determine the encoding. */
-
- if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
- && !memcmp(parser->raw_buffer.pointer, BOM_UTF16LE, 2)) {
- parser->encoding = YAML_UTF16LE_ENCODING;
- parser->raw_buffer.pointer += 2;
- parser->offset += 2;
- }
- else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
- && !memcmp(parser->raw_buffer.pointer, BOM_UTF16BE, 2)) {
- parser->encoding = YAML_UTF16BE_ENCODING;
- parser->raw_buffer.pointer += 2;
- parser->offset += 2;
- }
- else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 3
- && !memcmp(parser->raw_buffer.pointer, BOM_UTF8, 3)) {
- parser->encoding = YAML_UTF8_ENCODING;
- parser->raw_buffer.pointer += 3;
- parser->offset += 3;
- }
- else {
- parser->encoding = YAML_UTF8_ENCODING;
- }
-
- return 1;
-}
-
-/*
- * Update the raw buffer.
- */
-
-static int
-yaml_parser_update_raw_buffer(yaml_parser_t *parser)
-{
- size_t size_read = 0;
-
- /* Return if the raw buffer is full. */
-
- if (parser->raw_buffer.start == parser->raw_buffer.pointer
- && parser->raw_buffer.last == parser->raw_buffer.end)
- return 1;
-
- /* Return on EOF. */
-
- if (parser->eof) return 1;
-
- /* Move the remaining bytes in the raw buffer to the beginning. */
-
- if (parser->raw_buffer.start < parser->raw_buffer.pointer
- && parser->raw_buffer.pointer < parser->raw_buffer.last) {
- memmove(parser->raw_buffer.start, parser->raw_buffer.pointer,
- parser->raw_buffer.last - parser->raw_buffer.pointer);
- }
- parser->raw_buffer.last -=
- parser->raw_buffer.pointer - parser->raw_buffer.start;
- parser->raw_buffer.pointer = parser->raw_buffer.start;
-
- /* Call the read handler to fill the buffer. */
-
- if (!parser->read_handler(parser->read_handler_data, parser->raw_buffer.last,
- parser->raw_buffer.end - parser->raw_buffer.last, &size_read)) {
- return yaml_parser_set_reader_error(parser, "input error",
- parser->offset, -1);
- }
- parser->raw_buffer.last += size_read;
- if (!size_read) {
- parser->eof = 1;
- }
-
- return 1;
-}
-
-/*
- * Ensure that the buffer contains at least `length` characters.
- * Return 1 on success, 0 on failure.
- *
- * The length is supposed to be significantly less that the buffer size.
- */
-
-YAML_DECLARE(int)
-yaml_parser_update_buffer(yaml_parser_t *parser, size_t length)
-{
- int first = 1;
-
- assert(parser->read_handler); /* Read handler must be set. */
-
- /* If the EOF flag is set and the raw buffer is empty, do nothing. */
-
- if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last)
- return 1;
-
- /* Return if the buffer contains enough characters. */
-
- if (parser->unread >= length)
- return 1;
-
- /* Determine the input encoding if it is not known yet. */
-
- if (!parser->encoding) {
- if (!yaml_parser_determine_encoding(parser))
- return 0;
- }
-
- /* Move the unread characters to the beginning of the buffer. */
-
- if (parser->buffer.start < parser->buffer.pointer
- && parser->buffer.pointer < parser->buffer.last) {
- size_t size = parser->buffer.last - parser->buffer.pointer;
- memmove(parser->buffer.start, parser->buffer.pointer, size);
- parser->buffer.pointer = parser->buffer.start;
- parser->buffer.last = parser->buffer.start + size;
- }
- else if (parser->buffer.pointer == parser->buffer.last) {
- parser->buffer.pointer = parser->buffer.start;
- parser->buffer.last = parser->buffer.start;
- }
-
- /* Fill the buffer until it has enough characters. */
-
- while (parser->unread < length)
- {
- /* Fill the raw buffer if necessary. */
-
- if (!first || parser->raw_buffer.pointer == parser->raw_buffer.last) {
- if (!yaml_parser_update_raw_buffer(parser)) return 0;
- }
- first = 0;
-
- /* Decode the raw buffer. */
-
- while (parser->raw_buffer.pointer != parser->raw_buffer.last)
- {
- unsigned int value = 0, value2 = 0;
- int incomplete = 0;
- unsigned char octet;
- unsigned int width = 0;
- int low, high;
- size_t k;
- size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer;
-
- /* Decode the next character. */
-
- switch (parser->encoding)
- {
- case YAML_UTF8_ENCODING:
-
- /*
- * Decode a UTF-8 character. Check RFC 3629
- * (http://www.ietf.org/rfc/rfc3629.txt) for more details.
- *
- * The following table (taken from the RFC) is used for
- * decoding.
- *
- * Char. number range | UTF-8 octet sequence
- * (hexadecimal) | (binary)
- * --------------------+------------------------------------
- * 0000 0000-0000 007F | 0xxxxxxx
- * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
- * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
- * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- *
- * Additionally, the characters in the range 0xD800-0xDFFF
- * are prohibited as they are reserved for use with UTF-16
- * surrogate pairs.
- */
-
- /* Determine the length of the UTF-8 sequence. */
-
- octet = parser->raw_buffer.pointer[0];
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
-
- /* Check if the leading octet is valid. */
-
- if (!width)
- return yaml_parser_set_reader_error(parser,
- "invalid leading UTF-8 octet",
- parser->offset, octet);
-
- /* Check if the raw buffer contains an incomplete character. */
-
- if (width > raw_unread) {
- if (parser->eof) {
- return yaml_parser_set_reader_error(parser,
- "incomplete UTF-8 octet sequence",
- parser->offset, -1);
- }
- incomplete = 1;
- break;
- }
-
- /* Decode the leading octet. */
-
- value = (octet & 0x80) == 0x00 ? octet & 0x7F :
- (octet & 0xE0) == 0xC0 ? octet & 0x1F :
- (octet & 0xF0) == 0xE0 ? octet & 0x0F :
- (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
-
- /* Check and decode the trailing octets. */
-
- for (k = 1; k < width; k ++)
- {
- octet = parser->raw_buffer.pointer[k];
-
- /* Check if the octet is valid. */
-
- if ((octet & 0xC0) != 0x80)
- return yaml_parser_set_reader_error(parser,
- "invalid trailing UTF-8 octet",
- parser->offset+k, octet);
-
- /* Decode the octet. */
-
- value = (value << 6) + (octet & 0x3F);
- }
-
- /* Check the length of the sequence against the value. */
-
- if (!((width == 1) ||
- (width == 2 && value >= 0x80) ||
- (width == 3 && value >= 0x800) ||
- (width == 4 && value >= 0x10000)))
- return yaml_parser_set_reader_error(parser,
- "invalid length of a UTF-8 sequence",
- parser->offset, -1);
-
- /* Check the range of the value. */
-
- if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
- return yaml_parser_set_reader_error(parser,
- "invalid Unicode character",
- parser->offset, value);
-
- break;
-
- case YAML_UTF16LE_ENCODING:
- case YAML_UTF16BE_ENCODING:
-
- low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
- high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
-
- /*
- * The UTF-16 encoding is not as simple as one might
- * naively think. Check RFC 2781
- * (http://www.ietf.org/rfc/rfc2781.txt).
- *
- * Normally, two subsequent bytes describe a Unicode
- * character. However a special technique (called a
- * surrogate pair) is used for specifying character
- * values larger than 0xFFFF.
- *
- * A surrogate pair consists of two pseudo-characters:
- * high surrogate area (0xD800-0xDBFF)
- * low surrogate area (0xDC00-0xDFFF)
- *
- * The following formulas are used for decoding
- * and encoding characters using surrogate pairs:
- *
- * U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
- * U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
- * W1 = 110110yyyyyyyyyy
- * W2 = 110111xxxxxxxxxx
- *
- * where U is the character value, W1 is the high surrogate
- * area, W2 is the low surrogate area.
- */
-
- /* Check for incomplete UTF-16 character. */
-
- if (raw_unread < 2) {
- if (parser->eof) {
- return yaml_parser_set_reader_error(parser,
- "incomplete UTF-16 character",
- parser->offset, -1);
- }
- incomplete = 1;
- break;
- }
-
- /* Get the character. */
-
- value = parser->raw_buffer.pointer[low]
- + (parser->raw_buffer.pointer[high] << 8);
-
- /* Check for unexpected low surrogate area. */
-
- if ((value & 0xFC00) == 0xDC00)
- return yaml_parser_set_reader_error(parser,
- "unexpected low surrogate area",
- parser->offset, value);
-
- /* Check for a high surrogate area. */
-
- if ((value & 0xFC00) == 0xD800) {
-
- width = 4;
-
- /* Check for incomplete surrogate pair. */
-
- if (raw_unread < 4) {
- if (parser->eof) {
- return yaml_parser_set_reader_error(parser,
- "incomplete UTF-16 surrogate pair",
- parser->offset, -1);
- }
- incomplete = 1;
- break;
- }
-
- /* Get the next character. */
-
- value2 = parser->raw_buffer.pointer[low+2]
- + (parser->raw_buffer.pointer[high+2] << 8);
-
- /* Check for a low surrogate area. */
-
- if ((value2 & 0xFC00) != 0xDC00)
- return yaml_parser_set_reader_error(parser,
- "expected low surrogate area",
- parser->offset+2, value2);
-
- /* Generate the value of the surrogate pair. */
-
- value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
- }
-
- else {
- width = 2;
- }
-
- break;
-
- default:
- assert(1); /* Impossible. */
- }
-
- /* Check if the raw buffer contains enough bytes to form a character. */
-
- if (incomplete) break;
-
- /*
- * Check if the character is in the allowed range:
- * #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
- * | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
- * | [#x10000-#x10FFFF] (32 bit)
- */
-
- if (! (value == 0x09 || value == 0x0A || value == 0x0D
- || (value >= 0x20 && value <= 0x7E)
- || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
- || (value >= 0xE000 && value <= 0xFFFD)
- || (value >= 0x10000 && value <= 0x10FFFF)))
- return yaml_parser_set_reader_error(parser,
- "control characters are not allowed",
- parser->offset, value);
-
- /* Move the raw pointers. */
-
- parser->raw_buffer.pointer += width;
- parser->offset += width;
-
- /* Finally put the character into the buffer. */
-
- /* 0000 0000-0000 007F -> 0xxxxxxx */
- if (value <= 0x7F) {
- *(parser->buffer.last++) = value;
- }
- /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
- else if (value <= 0x7FF) {
- *(parser->buffer.last++) = 0xC0 + (value >> 6);
- *(parser->buffer.last++) = 0x80 + (value & 0x3F);
- }
- /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
- else if (value <= 0xFFFF) {
- *(parser->buffer.last++) = 0xE0 + (value >> 12);
- *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
- *(parser->buffer.last++) = 0x80 + (value & 0x3F);
- }
- /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
- else {
- *(parser->buffer.last++) = 0xF0 + (value >> 18);
- *(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F);
- *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
- *(parser->buffer.last++) = 0x80 + (value & 0x3F);
- }
-
- parser->unread ++;
- }
-
- /* On EOF, put NUL into the buffer and return. */
-
- if (parser->eof) {
- *(parser->buffer.last++) = '\0';
- parser->unread ++;
- return 1;
- }
-
- }
-
- if (parser->offset >= MAX_FILE_SIZE) {
- return yaml_parser_set_reader_error(parser, "input is too long",
- parser->offset, -1);
- }
-
- return 1;
-}
diff --git a/ext/psych/yaml/scanner.c b/ext/psych/yaml/scanner.c
deleted file mode 100644
index bb5d201274..0000000000
--- a/ext/psych/yaml/scanner.c
+++ /dev/null
@@ -1,3598 +0,0 @@
-
-/*
- * Introduction
- * ************
- *
- * The following notes assume that you are familiar with the YAML specification
- * (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in
- * some cases we are less restrictive that it requires.
- *
- * The process of transforming a YAML stream into a sequence of events is
- * divided on two steps: Scanning and Parsing.
- *
- * The Scanner transforms the input stream into a sequence of tokens, while the
- * parser transform the sequence of tokens produced by the Scanner into a
- * sequence of parsing events.
- *
- * The Scanner is rather clever and complicated. The Parser, on the contrary,
- * is a straightforward implementation of a recursive-descendant parser (or,
- * LL(1) parser, as it is usually called).
- *
- * Actually there are two issues of Scanning that might be called "clever", the
- * rest is quite straightforward. The issues are "block collection start" and
- * "simple keys". Both issues are explained below in details.
- *
- * Here the Scanning step is explained and implemented. We start with the list
- * of all the tokens produced by the Scanner together with short descriptions.
- *
- * Now, tokens:
- *
- * STREAM-START(encoding) # The stream start.
- * STREAM-END # The stream end.
- * VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
- * TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
- * DOCUMENT-START # '---'
- * DOCUMENT-END # '...'
- * BLOCK-SEQUENCE-START # Indentation increase denoting a block
- * BLOCK-MAPPING-START # sequence or a block mapping.
- * BLOCK-END # Indentation decrease.
- * FLOW-SEQUENCE-START # '['
- * FLOW-SEQUENCE-END # ']'
- * FLOW-MAPPING-START # '{'
- * FLOW-MAPPING-END # '}'
- * BLOCK-ENTRY # '-'
- * FLOW-ENTRY # ','
- * KEY # '?' or nothing (simple keys).
- * VALUE # ':'
- * ALIAS(anchor) # '*anchor'
- * ANCHOR(anchor) # '&anchor'
- * TAG(handle,suffix) # '!handle!suffix'
- * SCALAR(value,style) # A scalar.
- *
- * The following two tokens are "virtual" tokens denoting the beginning and the
- * end of the stream:
- *
- * STREAM-START(encoding)
- * STREAM-END
- *
- * We pass the information about the input stream encoding with the
- * STREAM-START token.
- *
- * The next two tokens are responsible for tags:
- *
- * VERSION-DIRECTIVE(major,minor)
- * TAG-DIRECTIVE(handle,prefix)
- *
- * Example:
- *
- * %YAML 1.1
- * %TAG ! !foo
- * %TAG !yaml! tag:yaml.org,2002:
- * ---
- *
- * The corresponding sequence of tokens:
- *
- * STREAM-START(utf-8)
- * VERSION-DIRECTIVE(1,1)
- * TAG-DIRECTIVE("!","!foo")
- * TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
- * DOCUMENT-START
- * STREAM-END
- *
- * Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
- * line.
- *
- * The document start and end indicators are represented by:
- *
- * DOCUMENT-START
- * DOCUMENT-END
- *
- * Note that if a YAML stream contains an implicit document (without '---'
- * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
- * produced.
- *
- * In the following examples, we present whole documents together with the
- * produced tokens.
- *
- * 1. An implicit document:
- *
- * 'a scalar'
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * SCALAR("a scalar",single-quoted)
- * STREAM-END
- *
- * 2. An explicit document:
- *
- * ---
- * 'a scalar'
- * ...
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * DOCUMENT-START
- * SCALAR("a scalar",single-quoted)
- * DOCUMENT-END
- * STREAM-END
- *
- * 3. Several documents in a stream:
- *
- * 'a scalar'
- * ---
- * 'another scalar'
- * ---
- * 'yet another scalar'
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * SCALAR("a scalar",single-quoted)
- * DOCUMENT-START
- * SCALAR("another scalar",single-quoted)
- * DOCUMENT-START
- * SCALAR("yet another scalar",single-quoted)
- * STREAM-END
- *
- * We have already introduced the SCALAR token above. The following tokens are
- * used to describe aliases, anchors, tag, and scalars:
- *
- * ALIAS(anchor)
- * ANCHOR(anchor)
- * TAG(handle,suffix)
- * SCALAR(value,style)
- *
- * The following series of examples illustrate the usage of these tokens:
- *
- * 1. A recursive sequence:
- *
- * &A [ *A ]
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * ANCHOR("A")
- * FLOW-SEQUENCE-START
- * ALIAS("A")
- * FLOW-SEQUENCE-END
- * STREAM-END
- *
- * 2. A tagged scalar:
- *
- * !!float "3.14" # A good approximation.
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * TAG("!!","float")
- * SCALAR("3.14",double-quoted)
- * STREAM-END
- *
- * 3. Various scalar styles:
- *
- * --- # Implicit empty plain scalars do not produce tokens.
- * --- a plain scalar
- * --- 'a single-quoted scalar'
- * --- "a double-quoted scalar"
- * --- |-
- * a literal scalar
- * --- >-
- * a folded
- * scalar
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * DOCUMENT-START
- * DOCUMENT-START
- * SCALAR("a plain scalar",plain)
- * DOCUMENT-START
- * SCALAR("a single-quoted scalar",single-quoted)
- * DOCUMENT-START
- * SCALAR("a double-quoted scalar",double-quoted)
- * DOCUMENT-START
- * SCALAR("a literal scalar",literal)
- * DOCUMENT-START
- * SCALAR("a folded scalar",folded)
- * STREAM-END
- *
- * Now it's time to review collection-related tokens. We will start with
- * flow collections:
- *
- * FLOW-SEQUENCE-START
- * FLOW-SEQUENCE-END
- * FLOW-MAPPING-START
- * FLOW-MAPPING-END
- * FLOW-ENTRY
- * KEY
- * VALUE
- *
- * The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
- * FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
- * correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
- * indicators '?' and ':', which are used for denoting mapping keys and values,
- * are represented by the KEY and VALUE tokens.
- *
- * The following examples show flow collections:
- *
- * 1. A flow sequence:
- *
- * [item 1, item 2, item 3]
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * FLOW-SEQUENCE-START
- * SCALAR("item 1",plain)
- * FLOW-ENTRY
- * SCALAR("item 2",plain)
- * FLOW-ENTRY
- * SCALAR("item 3",plain)
- * FLOW-SEQUENCE-END
- * STREAM-END
- *
- * 2. A flow mapping:
- *
- * {
- * a simple key: a value, # Note that the KEY token is produced.
- * ? a complex key: another value,
- * }
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * FLOW-MAPPING-START
- * KEY
- * SCALAR("a simple key",plain)
- * VALUE
- * SCALAR("a value",plain)
- * FLOW-ENTRY
- * KEY
- * SCALAR("a complex key",plain)
- * VALUE
- * SCALAR("another value",plain)
- * FLOW-ENTRY
- * FLOW-MAPPING-END
- * STREAM-END
- *
- * A simple key is a key which is not denoted by the '?' indicator. Note that
- * the Scanner still produce the KEY token whenever it encounters a simple key.
- *
- * For scanning block collections, the following tokens are used (note that we
- * repeat KEY and VALUE here):
- *
- * BLOCK-SEQUENCE-START
- * BLOCK-MAPPING-START
- * BLOCK-END
- * BLOCK-ENTRY
- * KEY
- * VALUE
- *
- * 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 peculiarities
- * that makes detections of these tokens more complex.
- *
- * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
- * '-', '?', and ':' correspondingly.
- *
- * The following examples show how the tokens BLOCK-SEQUENCE-START,
- * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
- *
- * 1. Block sequences:
- *
- * - item 1
- * - item 2
- * -
- * - item 3.1
- * - item 3.2
- * -
- * key 1: value 1
- * key 2: value 2
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * BLOCK-SEQUENCE-START
- * BLOCK-ENTRY
- * SCALAR("item 1",plain)
- * BLOCK-ENTRY
- * SCALAR("item 2",plain)
- * BLOCK-ENTRY
- * BLOCK-SEQUENCE-START
- * BLOCK-ENTRY
- * SCALAR("item 3.1",plain)
- * BLOCK-ENTRY
- * SCALAR("item 3.2",plain)
- * BLOCK-END
- * BLOCK-ENTRY
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("key 1",plain)
- * VALUE
- * SCALAR("value 1",plain)
- * KEY
- * SCALAR("key 2",plain)
- * VALUE
- * SCALAR("value 2",plain)
- * BLOCK-END
- * BLOCK-END
- * STREAM-END
- *
- * 2. Block mappings:
- *
- * a simple key: a value # The KEY token is produced here.
- * ? a complex key
- * : another value
- * a mapping:
- * key 1: value 1
- * key 2: value 2
- * a sequence:
- * - item 1
- * - item 2
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("a simple key",plain)
- * VALUE
- * SCALAR("a value",plain)
- * KEY
- * SCALAR("a complex key",plain)
- * VALUE
- * SCALAR("another value",plain)
- * KEY
- * SCALAR("a mapping",plain)
- * VALUE
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("key 1",plain)
- * VALUE
- * SCALAR("value 1",plain)
- * KEY
- * SCALAR("key 2",plain)
- * VALUE
- * SCALAR("value 2",plain)
- * BLOCK-END
- * KEY
- * SCALAR("a sequence",plain)
- * VALUE
- * BLOCK-SEQUENCE-START
- * BLOCK-ENTRY
- * SCALAR("item 1",plain)
- * BLOCK-ENTRY
- * SCALAR("item 2",plain)
- * BLOCK-END
- * BLOCK-END
- * STREAM-END
- *
- * YAML does not always require to start a new block collection from a new
- * line. If the current line contains only '-', '?', and ':' indicators, a new
- * block collection may start at the current line. The following examples
- * illustrate this case:
- *
- * 1. Collections in a sequence:
- *
- * - - item 1
- * - item 2
- * - key 1: value 1
- * key 2: value 2
- * - ? complex key
- * : complex value
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * BLOCK-SEQUENCE-START
- * BLOCK-ENTRY
- * BLOCK-SEQUENCE-START
- * BLOCK-ENTRY
- * SCALAR("item 1",plain)
- * BLOCK-ENTRY
- * SCALAR("item 2",plain)
- * BLOCK-END
- * BLOCK-ENTRY
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("key 1",plain)
- * VALUE
- * SCALAR("value 1",plain)
- * KEY
- * SCALAR("key 2",plain)
- * VALUE
- * SCALAR("value 2",plain)
- * BLOCK-END
- * BLOCK-ENTRY
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("complex key")
- * VALUE
- * SCALAR("complex value")
- * BLOCK-END
- * BLOCK-END
- * STREAM-END
- *
- * 2. Collections in a mapping:
- *
- * ? a sequence
- * : - item 1
- * - item 2
- * ? a mapping
- * : key 1: value 1
- * key 2: value 2
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("a sequence",plain)
- * VALUE
- * BLOCK-SEQUENCE-START
- * BLOCK-ENTRY
- * SCALAR("item 1",plain)
- * BLOCK-ENTRY
- * SCALAR("item 2",plain)
- * BLOCK-END
- * KEY
- * SCALAR("a mapping",plain)
- * VALUE
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("key 1",plain)
- * VALUE
- * SCALAR("value 1",plain)
- * KEY
- * SCALAR("key 2",plain)
- * VALUE
- * SCALAR("value 2",plain)
- * BLOCK-END
- * BLOCK-END
- * STREAM-END
- *
- * YAML also permits non-indented sequences if they are included into a block
- * mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
- *
- * key:
- * - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
- * - item 2
- *
- * Tokens:
- *
- * STREAM-START(utf-8)
- * BLOCK-MAPPING-START
- * KEY
- * SCALAR("key",plain)
- * VALUE
- * BLOCK-ENTRY
- * SCALAR("item 1",plain)
- * BLOCK-ENTRY
- * SCALAR("item 2",plain)
- * BLOCK-END
- */
-
-#include "yaml_private.h"
-
-/*
- * Ensure that the buffer contains the required number of characters.
- * Return 1 on success, 0 on failure (reader error or memory error).
- */
-
-#define CACHE(parser,length) \
- (parser->unread >= (length) \
- ? 1 \
- : yaml_parser_update_buffer(parser, (length)))
-
-/*
- * Advance the buffer pointer.
- */
-
-#define SKIP(parser) \
- (parser->mark.index ++, \
- parser->mark.column ++, \
- parser->unread --, \
- parser->buffer.pointer += WIDTH(parser->buffer))
-
-#define SKIP_LINE(parser) \
- (IS_CRLF(parser->buffer) ? \
- (parser->mark.index += 2, \
- parser->mark.column = 0, \
- parser->mark.line ++, \
- parser->unread -= 2, \
- parser->buffer.pointer += 2) : \
- IS_BREAK(parser->buffer) ? \
- (parser->mark.index ++, \
- parser->mark.column = 0, \
- parser->mark.line ++, \
- parser->unread --, \
- parser->buffer.pointer += WIDTH(parser->buffer)) : 0)
-
-/*
- * Copy a character to a string buffer and advance pointers.
- */
-
-#define READ(parser,string) \
- (STRING_EXTEND(parser,string) ? \
- (COPY(string,parser->buffer), \
- parser->mark.index ++, \
- parser->mark.column ++, \
- parser->unread --, \
- 1) : 0)
-
-/*
- * Copy a line break character to a string buffer and advance pointers.
- */
-
-#define READ_LINE(parser,string) \
- (STRING_EXTEND(parser,string) ? \
- (((CHECK_AT(parser->buffer,'\r',0) \
- && CHECK_AT(parser->buffer,'\n',1)) ? /* CR LF -> LF */ \
- (*((string).pointer++) = (yaml_char_t) '\n', \
- parser->buffer.pointer += 2, \
- parser->mark.index += 2, \
- parser->mark.column = 0, \
- parser->mark.line ++, \
- parser->unread -= 2) : \
- (CHECK_AT(parser->buffer,'\r',0) \
- || CHECK_AT(parser->buffer,'\n',0)) ? /* CR|LF -> LF */ \
- (*((string).pointer++) = (yaml_char_t) '\n', \
- parser->buffer.pointer ++, \
- parser->mark.index ++, \
- parser->mark.column = 0, \
- parser->mark.line ++, \
- parser->unread --) : \
- (CHECK_AT(parser->buffer,'\xC2',0) \
- && CHECK_AT(parser->buffer,'\x85',1)) ? /* NEL -> LF */ \
- (*((string).pointer++) = (yaml_char_t) '\n', \
- parser->buffer.pointer += 2, \
- parser->mark.index ++, \
- parser->mark.column = 0, \
- parser->mark.line ++, \
- parser->unread --) : \
- (CHECK_AT(parser->buffer,'\xE2',0) && \
- CHECK_AT(parser->buffer,'\x80',1) && \
- (CHECK_AT(parser->buffer,'\xA8',2) || \
- CHECK_AT(parser->buffer,'\xA9',2))) ? /* LS|PS -> LS|PS */ \
- (*((string).pointer++) = *(parser->buffer.pointer++), \
- *((string).pointer++) = *(parser->buffer.pointer++), \
- *((string).pointer++) = *(parser->buffer.pointer++), \
- parser->mark.index ++, \
- parser->mark.column = 0, \
- parser->mark.line ++, \
- parser->unread --) : 0), \
- 1) : 0)
-
-/*
- * Public API declarations.
- */
-
-YAML_DECLARE(int)
-yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
-
-/*
- * Error handling.
- */
-
-static int
-yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
- yaml_mark_t context_mark, const char *problem);
-
-/*
- * High-level token API.
- */
-
-YAML_DECLARE(int)
-yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_next_token(yaml_parser_t *parser);
-
-/*
- * Potential simple keys.
- */
-
-static int
-yaml_parser_stale_simple_keys(yaml_parser_t *parser);
-
-static int
-yaml_parser_save_simple_key(yaml_parser_t *parser);
-
-static int
-yaml_parser_remove_simple_key(yaml_parser_t *parser);
-
-static int
-yaml_parser_increase_flow_level(yaml_parser_t *parser);
-
-static int
-yaml_parser_decrease_flow_level(yaml_parser_t *parser);
-
-/*
- * Indentation treatment.
- */
-
-static int
-yaml_parser_roll_indent(yaml_parser_t *parser, ptrdiff_t column,
- ptrdiff_t number, yaml_token_type_t type, yaml_mark_t mark);
-
-static int
-yaml_parser_unroll_indent(yaml_parser_t *parser, ptrdiff_t column);
-
-/*
- * Token fetchers.
- */
-
-static int
-yaml_parser_fetch_stream_start(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_stream_end(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_directive(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
- yaml_token_type_t type);
-
-static int
-yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
- yaml_token_type_t type);
-
-static int
-yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
- yaml_token_type_t type);
-
-static int
-yaml_parser_fetch_flow_entry(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_block_entry(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_key(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_value(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type);
-
-static int
-yaml_parser_fetch_tag(yaml_parser_t *parser);
-
-static int
-yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal);
-
-static int
-yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single);
-
-static int
-yaml_parser_fetch_plain_scalar(yaml_parser_t *parser);
-
-/*
- * Token scanners.
- */
-
-static int
-yaml_parser_scan_to_next_token(yaml_parser_t *parser);
-
-static int
-yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token);
-
-static int
-yaml_parser_scan_directive_name(yaml_parser_t *parser,
- yaml_mark_t start_mark, yaml_char_t **name);
-
-static int
-yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
- yaml_mark_t start_mark, int *major, int *minor);
-
-static int
-yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
- yaml_mark_t start_mark, int *number);
-
-static int
-yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
- yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix);
-
-static int
-yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
- yaml_token_type_t type);
-
-static int
-yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token);
-
-static int
-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 uri_char, int directive,
- yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
-
-static int
-yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
- yaml_mark_t start_mark, yaml_string_t *string);
-
-static int
-yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
- int literal);
-
-static int
-yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
- int *indent, yaml_string_t *breaks,
- yaml_mark_t start_mark, yaml_mark_t *end_mark);
-
-static int
-yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
- int single);
-
-static int
-yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token);
-
-/*
- * Get the next token.
- */
-
-YAML_DECLARE(int)
-yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token)
-{
- assert(parser); /* Non-NULL parser object is expected. */
- assert(token); /* Non-NULL token object is expected. */
-
- /* Erase the token object. */
-
- memset(token, 0, sizeof(yaml_token_t));
-
- /* No tokens after STREAM-END or error. */
-
- if (parser->stream_end_produced || parser->error) {
- return 1;
- }
-
- /* Ensure that the tokens queue contains enough tokens. */
-
- if (!parser->token_available) {
- if (!yaml_parser_fetch_more_tokens(parser))
- return 0;
- }
-
- /* Fetch the next token from the queue. */
-
- *token = DEQUEUE(parser, parser->tokens);
- parser->token_available = 0;
- parser->tokens_parsed ++;
-
- if (token->type == YAML_STREAM_END_TOKEN) {
- parser->stream_end_produced = 1;
- }
-
- return 1;
-}
-
-/*
- * Set the scanner error and return 0.
- */
-
-static int
-yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
- yaml_mark_t context_mark, const char *problem)
-{
- parser->error = YAML_SCANNER_ERROR;
- parser->context = context;
- parser->context_mark = context_mark;
- parser->problem = problem;
- parser->problem_mark = parser->mark;
-
- return 0;
-}
-
-/*
- * Ensure that the tokens queue contains at least one token which can be
- * returned to the Parser.
- */
-
-YAML_DECLARE(int)
-yaml_parser_fetch_more_tokens(yaml_parser_t *parser)
-{
- int need_more_tokens;
-
- /* While we need more tokens to fetch, do it. */
-
- while (1)
- {
- /*
- * Check if we really need to fetch more tokens.
- */
-
- need_more_tokens = 0;
-
- if (parser->tokens.head == parser->tokens.tail)
- {
- /* Queue is empty. */
-
- need_more_tokens = 1;
- }
- else
- {
- yaml_simple_key_t *simple_key;
-
- /* Check if any potential simple key may occupy the head position. */
-
- if (!yaml_parser_stale_simple_keys(parser))
- return 0;
-
- for (simple_key = parser->simple_keys.start;
- simple_key != parser->simple_keys.top; simple_key++) {
- if (simple_key->possible
- && simple_key->token_number == parser->tokens_parsed) {
- need_more_tokens = 1;
- break;
- }
- }
- }
-
- /* We are finished. */
-
- if (!need_more_tokens)
- break;
-
- /* Fetch the next token. */
-
- if (!yaml_parser_fetch_next_token(parser))
- return 0;
- }
-
- parser->token_available = 1;
-
- return 1;
-}
-
-/*
- * The dispatcher for token fetchers.
- */
-
-static int
-yaml_parser_fetch_next_token(yaml_parser_t *parser)
-{
- /* Ensure that the buffer is initialized. */
-
- if (!CACHE(parser, 1))
- return 0;
-
- /* Check if we just started scanning. Fetch STREAM-START then. */
-
- if (!parser->stream_start_produced)
- return yaml_parser_fetch_stream_start(parser);
-
- /* Eat whitespaces and comments until we reach the next token. */
-
- if (!yaml_parser_scan_to_next_token(parser))
- return 0;
-
- /* Remove obsolete potential simple keys. */
-
- if (!yaml_parser_stale_simple_keys(parser))
- return 0;
-
- /* Check the indentation level against the current column. */
-
- if (!yaml_parser_unroll_indent(parser, parser->mark.column))
- return 0;
-
- /*
- * Ensure that the buffer contains at least 4 characters. 4 is the length
- * of the longest indicators ('--- ' and '... ').
- */
-
- if (!CACHE(parser, 4))
- return 0;
-
- /* Is it the end of the stream? */
-
- if (IS_Z(parser->buffer))
- return yaml_parser_fetch_stream_end(parser);
-
- /* Is it a directive? */
-
- if (parser->mark.column == 0 && CHECK(parser->buffer, '%'))
- return yaml_parser_fetch_directive(parser);
-
- /* Is it the document start indicator? */
-
- if (parser->mark.column == 0
- && CHECK_AT(parser->buffer, '-', 0)
- && CHECK_AT(parser->buffer, '-', 1)
- && CHECK_AT(parser->buffer, '-', 2)
- && IS_BLANKZ_AT(parser->buffer, 3))
- return yaml_parser_fetch_document_indicator(parser,
- YAML_DOCUMENT_START_TOKEN);
-
- /* Is it the document end indicator? */
-
- if (parser->mark.column == 0
- && CHECK_AT(parser->buffer, '.', 0)
- && CHECK_AT(parser->buffer, '.', 1)
- && CHECK_AT(parser->buffer, '.', 2)
- && IS_BLANKZ_AT(parser->buffer, 3))
- return yaml_parser_fetch_document_indicator(parser,
- YAML_DOCUMENT_END_TOKEN);
-
- /* Is it the flow sequence start indicator? */
-
- if (CHECK(parser->buffer, '['))
- return yaml_parser_fetch_flow_collection_start(parser,
- YAML_FLOW_SEQUENCE_START_TOKEN);
-
- /* Is it the flow mapping start indicator? */
-
- if (CHECK(parser->buffer, '{'))
- return yaml_parser_fetch_flow_collection_start(parser,
- YAML_FLOW_MAPPING_START_TOKEN);
-
- /* Is it the flow sequence end indicator? */
-
- if (CHECK(parser->buffer, ']'))
- return yaml_parser_fetch_flow_collection_end(parser,
- YAML_FLOW_SEQUENCE_END_TOKEN);
-
- /* Is it the flow mapping end indicator? */
-
- if (CHECK(parser->buffer, '}'))
- return yaml_parser_fetch_flow_collection_end(parser,
- YAML_FLOW_MAPPING_END_TOKEN);
-
- /* Is it the flow entry indicator? */
-
- if (CHECK(parser->buffer, ','))
- return yaml_parser_fetch_flow_entry(parser);
-
- /* Is it the block entry indicator? */
-
- if (CHECK(parser->buffer, '-') && IS_BLANKZ_AT(parser->buffer, 1))
- return yaml_parser_fetch_block_entry(parser);
-
- /* Is it the key indicator? */
-
- if (CHECK(parser->buffer, '?')
- && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1)))
- return yaml_parser_fetch_key(parser);
-
- /* Is it the value indicator? */
-
- if (CHECK(parser->buffer, ':')
- && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1)))
- return yaml_parser_fetch_value(parser);
-
- /* Is it an alias? */
-
- if (CHECK(parser->buffer, '*'))
- return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
-
- /* Is it an anchor? */
-
- if (CHECK(parser->buffer, '&'))
- return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
-
- /* Is it a tag? */
-
- if (CHECK(parser->buffer, '!'))
- return yaml_parser_fetch_tag(parser);
-
- /* Is it a literal scalar? */
-
- if (CHECK(parser->buffer, '|') && !parser->flow_level)
- return yaml_parser_fetch_block_scalar(parser, 1);
-
- /* Is it a folded scalar? */
-
- if (CHECK(parser->buffer, '>') && !parser->flow_level)
- return yaml_parser_fetch_block_scalar(parser, 0);
-
- /* Is it a single-quoted scalar? */
-
- if (CHECK(parser->buffer, '\''))
- return yaml_parser_fetch_flow_scalar(parser, 1);
-
- /* Is it a double-quoted scalar? */
-
- if (CHECK(parser->buffer, '"'))
- return yaml_parser_fetch_flow_scalar(parser, 0);
-
- /*
- * Is it a plain scalar?
- *
- * A plain scalar may start with any non-blank characters except
- *
- * '-', '?', ':', ',', '[', ']', '{', '}',
- * '#', '&', '*', '!', '|', '>', '\'', '\"',
- * '%', '@', '`'.
- *
- * In the block context (and, for the '-' indicator, in the flow context
- * too), it may also start with the characters
- *
- * '-', '?', ':'
- *
- * if it is followed by a non-space character.
- *
- * The last rule is more restrictive than the specification requires.
- */
-
- if (!(IS_BLANKZ(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, '@') || CHECK(parser->buffer, '`')) ||
- (CHECK(parser->buffer, '-') && !IS_BLANK_AT(parser->buffer, 1)) ||
- (!parser->flow_level &&
- (CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':'))
- && !IS_BLANKZ_AT(parser->buffer, 1)))
- return yaml_parser_fetch_plain_scalar(parser);
-
- /*
- * If we don't determine the token type so far, it is an error.
- */
-
- return yaml_parser_set_scanner_error(parser,
- "while scanning for the next token", parser->mark,
- "found character that cannot start any token");
-}
-
-/*
- * Check the list of potential simple keys and remove the positions that
- * cannot contain simple keys anymore.
- */
-
-static int
-yaml_parser_stale_simple_keys(yaml_parser_t *parser)
-{
- yaml_simple_key_t *simple_key;
-
- /* Check for a potential simple key for each flow level. */
-
- for (simple_key = parser->simple_keys.start;
- simple_key != parser->simple_keys.top; simple_key ++)
- {
- /*
- * The specification requires that a simple key
- *
- * - is limited to a single line,
- * - is shorter than 1024 characters.
- */
-
- if (simple_key->possible
- && (simple_key->mark.line < parser->mark.line
- || simple_key->mark.index+1024 < parser->mark.index)) {
-
- /* Check if the potential simple key to be removed is required. */
-
- if (simple_key->required) {
- return yaml_parser_set_scanner_error(parser,
- "while scanning a simple key", simple_key->mark,
- "could not find expected ':'");
- }
-
- simple_key->possible = 0;
- }
- }
-
- return 1;
-}
-
-/*
- * Check if a simple key may start at the current position and add it if
- * needed.
- */
-
-static int
-yaml_parser_save_simple_key(yaml_parser_t *parser)
-{
- /*
- * A simple key is required at the current position if the scanner is in
- * the block context and the current column coincides with the indentation
- * level.
- */
-
- int required = (!parser->flow_level
- && parser->indent == (ptrdiff_t)parser->mark.column);
-
- /*
- * If the current position may start a simple key, save it.
- */
-
- if (parser->simple_key_allowed)
- {
- yaml_simple_key_t simple_key;
- simple_key.possible = 1;
- simple_key.required = required;
- simple_key.token_number =
- parser->tokens_parsed + (parser->tokens.tail - parser->tokens.head);
- simple_key.mark = parser->mark;
-
- if (!yaml_parser_remove_simple_key(parser)) return 0;
-
- *(parser->simple_keys.top-1) = simple_key;
- }
-
- return 1;
-}
-
-/*
- * Remove a potential simple key at the current flow level.
- */
-
-static int
-yaml_parser_remove_simple_key(yaml_parser_t *parser)
-{
- yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
-
- if (simple_key->possible)
- {
- /* If the key is required, it is an error. */
-
- if (simple_key->required) {
- return yaml_parser_set_scanner_error(parser,
- "while scanning a simple key", simple_key->mark,
- "could not find expected ':'");
- }
- }
-
- /* Remove the key from the stack. */
-
- simple_key->possible = 0;
-
- return 1;
-}
-
-/*
- * Increase the flow level and resize the simple key list if needed.
- */
-
-static int
-yaml_parser_increase_flow_level(yaml_parser_t *parser)
-{
- yaml_simple_key_t empty_simple_key = { 0, 0, 0, { 0, 0, 0 } };
-
- /* Reset the simple key on the next level. */
-
- if (!PUSH(parser, parser->simple_keys, empty_simple_key))
- return 0;
-
- /* Increase the flow level. */
-
- if (parser->flow_level == INT_MAX) {
- parser->error = YAML_MEMORY_ERROR;
- return 0;
- }
-
- parser->flow_level++;
-
- return 1;
-}
-
-/*
- * Decrease the flow level.
- */
-
-static int
-yaml_parser_decrease_flow_level(yaml_parser_t *parser)
-{
- if (parser->flow_level) {
- parser->flow_level --;
- (void)POP(parser, parser->simple_keys);
- }
-
- return 1;
-}
-
-/*
- * Push the current indentation level to the stack and set the new level
- * the current column is greater than the indentation level. In this case,
- * append or insert the specified token into the token queue.
- *
- */
-
-static int
-yaml_parser_roll_indent(yaml_parser_t *parser, ptrdiff_t column,
- ptrdiff_t number, yaml_token_type_t type, yaml_mark_t mark)
-{
- yaml_token_t token;
-
- /* In the flow context, do nothing. */
-
- if (parser->flow_level)
- return 1;
-
- if (parser->indent < column)
- {
- /*
- * Push the current indentation level to the stack and set the new
- * indentation level.
- */
-
- if (!PUSH(parser, parser->indents, parser->indent))
- return 0;
-
- if (column > INT_MAX) {
- parser->error = YAML_MEMORY_ERROR;
- return 0;
- }
-
- parser->indent = (int)column;
-
- /* Create a token and insert it into the queue. */
-
- TOKEN_INIT(token, type, mark, mark);
-
- if (number == -1) {
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
- }
- else {
- if (!QUEUE_INSERT(parser,
- parser->tokens, number - parser->tokens_parsed, token))
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- * Pop indentation levels from the indents stack until the current level
- * becomes less or equal to the column. For each indentation level, append
- * the BLOCK-END token.
- */
-
-
-static int
-yaml_parser_unroll_indent(yaml_parser_t *parser, ptrdiff_t column)
-{
- yaml_token_t token;
-
- /* In the flow context, do nothing. */
-
- if (parser->flow_level)
- return 1;
-
- /* Loop through the indentation levels in the stack. */
-
- while (parser->indent > column)
- {
- /* Create a token and append it to the queue. */
-
- TOKEN_INIT(token, YAML_BLOCK_END_TOKEN, parser->mark, parser->mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- /* Pop the indentation level. */
-
- parser->indent = POP(parser, parser->indents);
- }
-
- return 1;
-}
-
-/*
- * Initialize the scanner and produce the STREAM-START token.
- */
-
-static int
-yaml_parser_fetch_stream_start(yaml_parser_t *parser)
-{
- yaml_simple_key_t simple_key = { 0, 0, 0, { 0, 0, 0 } };
- yaml_token_t token;
-
- /* Set the initial indentation. */
-
- parser->indent = -1;
-
- /* Initialize the simple key stack. */
-
- if (!PUSH(parser, parser->simple_keys, simple_key))
- return 0;
-
- /* A simple key is allowed at the beginning of the stream. */
-
- parser->simple_key_allowed = 1;
-
- /* We have started. */
-
- parser->stream_start_produced = 1;
-
- /* Create the STREAM-START token and append it to the queue. */
-
- STREAM_START_TOKEN_INIT(token, parser->encoding,
- parser->mark, parser->mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the STREAM-END token and shut down the scanner.
- */
-
-static int
-yaml_parser_fetch_stream_end(yaml_parser_t *parser)
-{
- yaml_token_t token;
-
- /* Force new line. */
-
- if (parser->mark.column != 0) {
- parser->mark.column = 0;
- parser->mark.line ++;
- }
-
- /* Reset the indentation level. */
-
- if (!yaml_parser_unroll_indent(parser, -1))
- return 0;
-
- /* Reset simple keys. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- parser->simple_key_allowed = 0;
-
- /* Create the STREAM-END token and append it to the queue. */
-
- STREAM_END_TOKEN_INIT(token, parser->mark, parser->mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
- */
-
-static int
-yaml_parser_fetch_directive(yaml_parser_t *parser)
-{
- yaml_token_t token;
-
- /* Reset the indentation level. */
-
- if (!yaml_parser_unroll_indent(parser, -1))
- return 0;
-
- /* Reset simple keys. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- parser->simple_key_allowed = 0;
-
- /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
-
- if (!yaml_parser_scan_directive(parser, &token))
- return 0;
-
- /* Append the token to the queue. */
-
- if (!ENQUEUE(parser, parser->tokens, token)) {
- yaml_token_delete(&token);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Produce the DOCUMENT-START or DOCUMENT-END token.
- */
-
-static int
-yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
- yaml_token_type_t type)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
-
- /* Reset the indentation level. */
-
- if (!yaml_parser_unroll_indent(parser, -1))
- return 0;
-
- /* Reset simple keys. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- parser->simple_key_allowed = 0;
-
- /* Consume the token. */
-
- start_mark = parser->mark;
-
- SKIP(parser);
- SKIP(parser);
- SKIP(parser);
-
- end_mark = parser->mark;
-
- /* Create the DOCUMENT-START or DOCUMENT-END token. */
-
- TOKEN_INIT(token, type, start_mark, end_mark);
-
- /* Append the token to the queue. */
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
- */
-
-static int
-yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
- yaml_token_type_t type)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
-
- /* The indicators '[' and '{' may start a simple key. */
-
- if (!yaml_parser_save_simple_key(parser))
- return 0;
-
- /* Increase the flow level. */
-
- if (!yaml_parser_increase_flow_level(parser))
- return 0;
-
- /* A simple key may follow the indicators '[' and '{'. */
-
- parser->simple_key_allowed = 1;
-
- /* Consume the token. */
-
- start_mark = parser->mark;
- SKIP(parser);
- end_mark = parser->mark;
-
- /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
-
- TOKEN_INIT(token, type, start_mark, end_mark);
-
- /* Append the token to the queue. */
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
- */
-
-static int
-yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
- yaml_token_type_t type)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
-
- /* Reset any potential simple key on the current flow level. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- /* Decrease the flow level. */
-
- if (!yaml_parser_decrease_flow_level(parser))
- return 0;
-
- /* No simple keys after the indicators ']' and '}'. */
-
- parser->simple_key_allowed = 0;
-
- /* Consume the token. */
-
- start_mark = parser->mark;
- SKIP(parser);
- end_mark = parser->mark;
-
- /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
-
- TOKEN_INIT(token, type, start_mark, end_mark);
-
- /* Append the token to the queue. */
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the FLOW-ENTRY token.
- */
-
-static int
-yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
-
- /* Reset any potential simple keys on the current flow level. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- /* Simple keys are allowed after ','. */
-
- parser->simple_key_allowed = 1;
-
- /* Consume the token. */
-
- start_mark = parser->mark;
- SKIP(parser);
- end_mark = parser->mark;
-
- /* Create the FLOW-ENTRY token and append it to the queue. */
-
- TOKEN_INIT(token, YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the BLOCK-ENTRY token.
- */
-
-static int
-yaml_parser_fetch_block_entry(yaml_parser_t *parser)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
-
- /* Check if the scanner is in the block context. */
-
- if (!parser->flow_level)
- {
- /* Check if we are allowed to start a new entry. */
-
- if (!parser->simple_key_allowed) {
- return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
- "block sequence entries are not allowed in this context");
- }
-
- /* Add the BLOCK-SEQUENCE-START token if needed. */
-
- if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
- YAML_BLOCK_SEQUENCE_START_TOKEN, parser->mark))
- return 0;
- }
- else
- {
- /*
- * It is an error for the '-' indicator to occur in the flow context,
- * but we let the Parser detect and report about it because the Parser
- * is able to point to the context.
- */
- }
-
- /* Reset any potential simple keys on the current flow level. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- /* Simple keys are allowed after '-'. */
-
- parser->simple_key_allowed = 1;
-
- /* Consume the token. */
-
- start_mark = parser->mark;
- SKIP(parser);
- end_mark = parser->mark;
-
- /* Create the BLOCK-ENTRY token and append it to the queue. */
-
- TOKEN_INIT(token, YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the KEY token.
- */
-
-static int
-yaml_parser_fetch_key(yaml_parser_t *parser)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
-
- /* In the block context, additional checks are required. */
-
- if (!parser->flow_level)
- {
- /* Check if we are allowed to start a new key (not necessary simple). */
-
- if (!parser->simple_key_allowed) {
- return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
- "mapping keys are not allowed in this context");
- }
-
- /* Add the BLOCK-MAPPING-START token if needed. */
-
- if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
- YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
- return 0;
- }
-
- /* Reset any potential simple keys on the current flow level. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- /* Simple keys are allowed after '?' in the block context. */
-
- parser->simple_key_allowed = (!parser->flow_level);
-
- /* Consume the token. */
-
- start_mark = parser->mark;
- SKIP(parser);
- end_mark = parser->mark;
-
- /* Create the KEY token and append it to the queue. */
-
- TOKEN_INIT(token, YAML_KEY_TOKEN, start_mark, end_mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the VALUE token.
- */
-
-static int
-yaml_parser_fetch_value(yaml_parser_t *parser)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_token_t token;
- yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
-
- /* Have we found a simple key? */
-
- if (simple_key->possible)
- {
-
- /* Create the KEY token and insert it into the queue. */
-
- TOKEN_INIT(token, YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
-
- if (!QUEUE_INSERT(parser, parser->tokens,
- simple_key->token_number - parser->tokens_parsed, token))
- return 0;
-
- /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
-
- if (!yaml_parser_roll_indent(parser, simple_key->mark.column,
- simple_key->token_number,
- YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
- return 0;
-
- /* Remove the simple key. */
-
- simple_key->possible = 0;
-
- /* A simple key cannot follow another simple key. */
-
- parser->simple_key_allowed = 0;
- }
- else
- {
- /* The ':' indicator follows a complex key. */
-
- /* In the block context, extra checks are required. */
-
- if (!parser->flow_level)
- {
- /* Check if we are allowed to start a complex value. */
-
- if (!parser->simple_key_allowed) {
- return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
- "mapping values are not allowed in this context");
- }
-
- /* Add the BLOCK-MAPPING-START token if needed. */
-
- if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
- YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
- return 0;
- }
-
- /* Simple keys after ':' are allowed in the block context. */
-
- parser->simple_key_allowed = (!parser->flow_level);
- }
-
- /* Consume the token. */
-
- start_mark = parser->mark;
- SKIP(parser);
- end_mark = parser->mark;
-
- /* Create the VALUE token and append it to the queue. */
-
- TOKEN_INIT(token, YAML_VALUE_TOKEN, start_mark, end_mark);
-
- if (!ENQUEUE(parser, parser->tokens, token))
- return 0;
-
- return 1;
-}
-
-/*
- * Produce the ALIAS or ANCHOR token.
- */
-
-static int
-yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
-{
- yaml_token_t token;
-
- /* An anchor or an alias could be a simple key. */
-
- if (!yaml_parser_save_simple_key(parser))
- return 0;
-
- /* A simple key cannot follow an anchor or an alias. */
-
- parser->simple_key_allowed = 0;
-
- /* Create the ALIAS or ANCHOR token and append it to the queue. */
-
- if (!yaml_parser_scan_anchor(parser, &token, type))
- return 0;
-
- if (!ENQUEUE(parser, parser->tokens, token)) {
- yaml_token_delete(&token);
- return 0;
- }
- return 1;
-}
-
-/*
- * Produce the TAG token.
- */
-
-static int
-yaml_parser_fetch_tag(yaml_parser_t *parser)
-{
- yaml_token_t token;
-
- /* A tag could be a simple key. */
-
- if (!yaml_parser_save_simple_key(parser))
- return 0;
-
- /* A simple key cannot follow a tag. */
-
- parser->simple_key_allowed = 0;
-
- /* Create the TAG token and append it to the queue. */
-
- if (!yaml_parser_scan_tag(parser, &token))
- return 0;
-
- if (!ENQUEUE(parser, parser->tokens, token)) {
- yaml_token_delete(&token);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
- */
-
-static int
-yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
-{
- yaml_token_t token;
-
- /* Remove any potential simple keys. */
-
- if (!yaml_parser_remove_simple_key(parser))
- return 0;
-
- /* A simple key may follow a block scalar. */
-
- parser->simple_key_allowed = 1;
-
- /* Create the SCALAR token and append it to the queue. */
-
- if (!yaml_parser_scan_block_scalar(parser, &token, literal))
- return 0;
-
- if (!ENQUEUE(parser, parser->tokens, token)) {
- yaml_token_delete(&token);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
- */
-
-static int
-yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
-{
- yaml_token_t token;
-
- /* A plain scalar could be a simple key. */
-
- if (!yaml_parser_save_simple_key(parser))
- return 0;
-
- /* A simple key cannot follow a flow scalar. */
-
- parser->simple_key_allowed = 0;
-
- /* Create the SCALAR token and append it to the queue. */
-
- if (!yaml_parser_scan_flow_scalar(parser, &token, single))
- return 0;
-
- if (!ENQUEUE(parser, parser->tokens, token)) {
- yaml_token_delete(&token);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Produce the SCALAR(...,plain) token.
- */
-
-static int
-yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
-{
- yaml_token_t token;
-
- /* A plain scalar could be a simple key. */
-
- if (!yaml_parser_save_simple_key(parser))
- return 0;
-
- /* A simple key cannot follow a flow scalar. */
-
- parser->simple_key_allowed = 0;
-
- /* Create the SCALAR token and append it to the queue. */
-
- if (!yaml_parser_scan_plain_scalar(parser, &token))
- return 0;
-
- if (!ENQUEUE(parser, parser->tokens, token)) {
- yaml_token_delete(&token);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Eat whitespaces and comments until the next token is found.
- */
-
-static int
-yaml_parser_scan_to_next_token(yaml_parser_t *parser)
-{
- /* Until the next token is not found. */
-
- while (1)
- {
- /* Allow the BOM mark to start a line. */
-
- if (!CACHE(parser, 1)) return 0;
-
- if (parser->mark.column == 0 && IS_BOM(parser->buffer))
- SKIP(parser);
-
- /*
- * Eat whitespaces.
- *
- * Tabs are allowed:
- *
- * - in the flow context;
- * - in the block context, but not at the beginning of the line or
- * after '-', '?', or ':' (complex value).
- */
-
- if (!CACHE(parser, 1)) return 0;
-
- while (CHECK(parser->buffer,' ') ||
- ((parser->flow_level || !parser->simple_key_allowed) &&
- CHECK(parser->buffer, '\t'))) {
- SKIP(parser);
- if (!CACHE(parser, 1)) return 0;
- }
-
- /* Eat a comment until a line break. */
-
- if (CHECK(parser->buffer, '#')) {
- while (!IS_BREAKZ(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) return 0;
- }
- }
-
- /* If it is a line break, eat it. */
-
- if (IS_BREAK(parser->buffer))
- {
- if (!CACHE(parser, 2)) return 0;
- SKIP_LINE(parser);
-
- /* In the block context, a new line may start a simple key. */
-
- if (!parser->flow_level) {
- parser->simple_key_allowed = 1;
- }
- }
- else
- {
- /* We have found a token. */
-
- break;
- }
- }
-
- return 1;
-}
-
-/*
- * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
- *
- * Scope:
- * %YAML 1.1 # a comment \n
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * %TAG !yaml! tag:yaml.org,2002: \n
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- */
-
-int
-yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token)
-{
- yaml_mark_t start_mark, end_mark;
- yaml_char_t *name = NULL;
- int major, minor;
- yaml_char_t *handle = NULL, *prefix = NULL;
-
- /* Eat '%'. */
-
- start_mark = parser->mark;
-
- SKIP(parser);
-
- /* Scan the directive name. */
-
- if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
- goto error;
-
- /* Is it a YAML directive? */
-
- if (strcmp((char *)name, "YAML") == 0)
- {
- /* Scan the VERSION directive value. */
-
- if (!yaml_parser_scan_version_directive_value(parser, start_mark,
- &major, &minor))
- goto error;
-
- end_mark = parser->mark;
-
- /* Create a VERSION-DIRECTIVE token. */
-
- VERSION_DIRECTIVE_TOKEN_INIT(*token, major, minor,
- start_mark, end_mark);
- }
-
- /* Is it a TAG directive? */
-
- else if (strcmp((char *)name, "TAG") == 0)
- {
- /* Scan the TAG directive value. */
-
- if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
- &handle, &prefix))
- goto error;
-
- end_mark = parser->mark;
-
- /* Create a TAG-DIRECTIVE token. */
-
- TAG_DIRECTIVE_TOKEN_INIT(*token, handle, prefix,
- start_mark, end_mark);
- }
-
- /* Unknown directive. */
-
- else
- {
- yaml_parser_set_scanner_error(parser, "while scanning a directive",
- start_mark, "found unknown directive name");
- goto error;
- }
-
- /* Eat the rest of the line including any comments. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_BLANK(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) goto error;
- }
-
- if (CHECK(parser->buffer, '#')) {
- while (!IS_BREAKZ(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) goto error;
- }
- }
-
- /* Check if we are at the end of the line. */
-
- if (!IS_BREAKZ(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a directive",
- start_mark, "did not find expected comment or line break");
- goto error;
- }
-
- /* Eat a line break. */
-
- if (IS_BREAK(parser->buffer)) {
- if (!CACHE(parser, 2)) goto error;
- SKIP_LINE(parser);
- }
-
- yaml_free(name);
-
- return 1;
-
-error:
- yaml_free(prefix);
- yaml_free(handle);
- yaml_free(name);
- return 0;
-}
-
-/*
- * Scan the directive name.
- *
- * Scope:
- * %YAML 1.1 # a comment \n
- * ^^^^
- * %TAG !yaml! tag:yaml.org,2002: \n
- * ^^^
- */
-
-static int
-yaml_parser_scan_directive_name(yaml_parser_t *parser,
- yaml_mark_t start_mark, yaml_char_t **name)
-{
- yaml_string_t string = NULL_STRING;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
-
- /* Consume the directive name. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_ALPHA(parser->buffer))
- {
- if (!READ(parser, string)) goto error;
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Check if the name is empty. */
-
- if (string.start == string.pointer) {
- yaml_parser_set_scanner_error(parser, "while scanning a directive",
- start_mark, "could not find expected directive name");
- goto error;
- }
-
- /* Check for an blank character after the name. */
-
- if (!IS_BLANKZ(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a directive",
- start_mark, "found unexpected non-alphabetical character");
- goto error;
- }
-
- *name = string.start;
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- return 0;
-}
-
-/*
- * Scan the value of VERSION-DIRECTIVE.
- *
- * Scope:
- * %YAML 1.1 # a comment \n
- * ^^^^^^
- */
-
-static int
-yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
- yaml_mark_t start_mark, int *major, int *minor)
-{
- /* Eat whitespaces. */
-
- if (!CACHE(parser, 1)) return 0;
-
- while (IS_BLANK(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) return 0;
- }
-
- /* Consume the major version number. */
-
- if (!yaml_parser_scan_version_directive_number(parser, start_mark, major))
- return 0;
-
- /* Eat '.'. */
-
- if (!CHECK(parser->buffer, '.')) {
- return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
- start_mark, "did not find expected digit or '.' character");
- }
-
- SKIP(parser);
-
- /* Consume the minor version number. */
-
- if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor))
- return 0;
-
- return 1;
-}
-
-#define MAX_NUMBER_LENGTH 9
-
-/*
- * Scan the version number of VERSION-DIRECTIVE.
- *
- * Scope:
- * %YAML 1.1 # a comment \n
- * ^
- * %YAML 1.1 # a comment \n
- * ^
- */
-
-static int
-yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
- yaml_mark_t start_mark, int *number)
-{
- int value = 0;
- size_t length = 0;
-
- /* Repeat while the next character is digit. */
-
- if (!CACHE(parser, 1)) return 0;
-
- while (IS_DIGIT(parser->buffer))
- {
- /* Check if the number is too long. */
-
- if (++length > MAX_NUMBER_LENGTH) {
- return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
- start_mark, "found extremely long version number");
- }
-
- value = value*10 + AS_DIGIT(parser->buffer);
-
- SKIP(parser);
-
- if (!CACHE(parser, 1)) return 0;
- }
-
- /* Check if the number was present. */
-
- if (!length) {
- return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
- start_mark, "did not find expected version number");
- }
-
- *number = value;
-
- return 1;
-}
-
-/*
- * Scan the value of a TAG-DIRECTIVE token.
- *
- * Scope:
- * %TAG !yaml! tag:yaml.org,2002: \n
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- */
-
-static int
-yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
- yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
-{
- yaml_char_t *handle_value = NULL;
- yaml_char_t *prefix_value = NULL;
-
- /* Eat whitespaces. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_BLANK(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Scan a handle. */
-
- if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
- goto error;
-
- /* Expect a whitespace. */
-
- if (!CACHE(parser, 1)) goto error;
-
- if (!IS_BLANK(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
- start_mark, "did not find expected whitespace");
- goto error;
- }
-
- /* Eat whitespaces. */
-
- while (IS_BLANK(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Scan a prefix. */
-
- if (!yaml_parser_scan_tag_uri(parser, 1, 1, NULL, start_mark, &prefix_value))
- goto error;
-
- /* Expect a whitespace or line break. */
-
- if (!CACHE(parser, 1)) goto error;
-
- if (!IS_BLANKZ(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
- start_mark, "did not find expected whitespace or line break");
- goto error;
- }
-
- *handle = handle_value;
- *prefix = prefix_value;
-
- return 1;
-
-error:
- yaml_free(handle_value);
- yaml_free(prefix_value);
- return 0;
-}
-
-static int
-yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
- yaml_token_type_t type)
-{
- int length = 0;
- yaml_mark_t start_mark, end_mark;
- yaml_string_t string = NULL_STRING;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
-
- /* Eat the indicator character. */
-
- start_mark = parser->mark;
-
- SKIP(parser);
-
- /* Consume the value. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_ALPHA(parser->buffer)) {
- if (!READ(parser, string)) goto error;
- if (!CACHE(parser, 1)) goto error;
- length ++;
- }
-
- end_mark = parser->mark;
-
- /*
- * Check if length of the anchor is greater than 0 and it is followed by
- * a whitespace character or one of the indicators:
- *
- * '?', ':', ',', ']', '}', '%', '@', '`'.
- */
-
- if (!length || !(IS_BLANKZ(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, '`'))) {
- yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
- "while scanning an anchor" : "while scanning an alias", start_mark,
- "did not find expected alphabetic or numeric character");
- goto error;
- }
-
- /* Create a token. */
-
- if (type == YAML_ANCHOR_TOKEN) {
- ANCHOR_TOKEN_INIT(*token, string.start, start_mark, end_mark);
- }
- else {
- ALIAS_TOKEN_INIT(*token, string.start, start_mark, end_mark);
- }
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- return 0;
-}
-
-/*
- * Scan a TAG token.
- */
-
-static int
-yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
-{
- yaml_char_t *handle = NULL;
- yaml_char_t *suffix = NULL;
- yaml_mark_t start_mark, end_mark;
-
- start_mark = parser->mark;
-
- /* Check if the tag is in the canonical form. */
-
- if (!CACHE(parser, 2)) goto error;
-
- if (CHECK_AT(parser->buffer, '<', 1))
- {
- /* Set the handle to '' */
-
- handle = YAML_MALLOC(1);
- if (!handle) goto error;
- handle[0] = '\0';
-
- /* Eat '!<' */
-
- SKIP(parser);
- SKIP(parser);
-
- /* Consume the tag value. */
-
- if (!yaml_parser_scan_tag_uri(parser, 1, 0, NULL, start_mark, &suffix))
- goto error;
-
- /* Check for '>' and eat it. */
-
- if (!CHECK(parser->buffer, '>')) {
- yaml_parser_set_scanner_error(parser, "while scanning a tag",
- start_mark, "did not find the expected '>'");
- goto error;
- }
-
- SKIP(parser);
- }
- else
- {
- /* The tag has either the '!suffix' or the '!handle!suffix' form. */
-
- /* First, try to scan a handle. */
-
- if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
- goto error;
-
- /* Check if it is, indeed, handle. */
-
- if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
- {
- /* Scan the suffix now. */
-
- 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, 0, handle, start_mark, &suffix))
- goto error;
-
- /* Set the handle to '!'. */
-
- yaml_free(handle);
- handle = YAML_MALLOC(2);
- if (!handle) goto error;
- handle[0] = '!';
- handle[1] = '\0';
-
- /*
- * A special case: the '!' tag. Set the handle to '' and the
- * suffix to '!'.
- */
-
- if (suffix[0] == '\0') {
- yaml_char_t *tmp = handle;
- handle = suffix;
- suffix = tmp;
- }
- }
- }
-
- /* Check the character which ends the tag. */
-
- if (!CACHE(parser, 1)) goto error;
-
- if (!IS_BLANKZ(parser->buffer)) {
- 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;
-
- /* Create a token. */
-
- TAG_TOKEN_INIT(*token, handle, suffix, start_mark, end_mark);
-
- return 1;
-
-error:
- yaml_free(handle);
- yaml_free(suffix);
- return 0;
-}
-
-/*
- * Scan a tag handle.
- */
-
-static int
-yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
- yaml_mark_t start_mark, yaml_char_t **handle)
-{
- yaml_string_t string = NULL_STRING;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
-
- /* Check the initial '!' character. */
-
- if (!CACHE(parser, 1)) goto error;
-
- if (!CHECK(parser->buffer, '!')) {
- yaml_parser_set_scanner_error(parser, directive ?
- "while scanning a tag directive" : "while scanning a tag",
- start_mark, "did not find expected '!'");
- goto error;
- }
-
- /* Copy the '!' character. */
-
- if (!READ(parser, string)) goto error;
-
- /* Copy all subsequent alphabetical and numerical characters. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_ALPHA(parser->buffer))
- {
- if (!READ(parser, string)) goto error;
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Check if the trailing character is '!' and copy it. */
-
- if (CHECK(parser->buffer, '!'))
- {
- if (!READ(parser, string)) goto error;
- }
- else
- {
- /*
- * It's either the '!' tag or not really a tag handle. If it's a %TAG
- * directive, it's an error. If it's a tag token, it must be a part of
- * URI.
- */
-
- if (directive && !(string.start[0] == '!' && string.start[1] == '\0')) {
- yaml_parser_set_scanner_error(parser, "while parsing a tag directive",
- start_mark, "did not find expected '!'");
- goto error;
- }
- }
-
- *handle = string.start;
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- return 0;
-}
-
-/*
- * Scan a tag.
- */
-
-static int
-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;
- yaml_string_t string = NULL_STRING;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
-
- /* Resize the string to include the head. */
-
- while ((size_t)(string.end - string.start) <= length) {
- if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) {
- parser->error = YAML_MEMORY_ERROR;
- goto error;
- }
- }
-
- /*
- * Copy the head if needed.
- *
- * Note that we don't copy the leading '!' character.
- */
-
- if (length > 1) {
- memcpy(string.start, head+1, length-1);
- string.pointer += length-1;
- }
-
- /* Scan the tag. */
-
- if (!CACHE(parser, 1)) goto error;
-
- /*
- * 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, ';')
- || 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. */
-
- if (CHECK(parser->buffer, '%')) {
- if (!STRING_EXTEND(parser, string))
- goto error;
-
- if (!yaml_parser_scan_uri_escapes(parser,
- directive, start_mark, &string)) goto error;
- }
- else {
- if (!READ(parser, string)) goto error;
- }
-
- length ++;
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Check if the tag is non-empty. */
-
- if (!length) {
- if (!STRING_EXTEND(parser, string))
- goto error;
-
- yaml_parser_set_scanner_error(parser, directive ?
- "while parsing a %TAG directive" : "while parsing a tag",
- start_mark, "did not find expected tag URI");
- goto error;
- }
-
- *uri = string.start;
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- return 0;
-}
-
-/*
- * Decode an URI-escape sequence corresponding to a single UTF-8 character.
- */
-
-static int
-yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
- yaml_mark_t start_mark, yaml_string_t *string)
-{
- int width = 0;
-
- /* Decode the required number of characters. */
-
- do {
-
- unsigned char octet = 0;
-
- /* Check for a URI-escaped octet. */
-
- if (!CACHE(parser, 3)) return 0;
-
- if (!(CHECK(parser->buffer, '%')
- && IS_HEX_AT(parser->buffer, 1)
- && IS_HEX_AT(parser->buffer, 2))) {
- return yaml_parser_set_scanner_error(parser, directive ?
- "while parsing a %TAG directive" : "while parsing a tag",
- start_mark, "did not find URI escaped octet");
- }
-
- /* Get the octet. */
-
- octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2);
-
- /* If it is the leading octet, determine the length of the UTF-8 sequence. */
-
- if (!width)
- {
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
- if (!width) {
- return yaml_parser_set_scanner_error(parser, directive ?
- "while parsing a %TAG directive" : "while parsing a tag",
- start_mark, "found an incorrect leading UTF-8 octet");
- }
- }
- else
- {
- /* Check if the trailing octet is correct. */
-
- if ((octet & 0xC0) != 0x80) {
- return yaml_parser_set_scanner_error(parser, directive ?
- "while parsing a %TAG directive" : "while parsing a tag",
- start_mark, "found an incorrect trailing UTF-8 octet");
- }
- }
-
- /* Copy the octet and move the pointers. */
-
- *(string->pointer++) = octet;
- SKIP(parser);
- SKIP(parser);
- SKIP(parser);
-
- } while (--width);
-
- return 1;
-}
-
-/*
- * Scan a block scalar.
- */
-
-static int
-yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
- int literal)
-{
- yaml_mark_t start_mark;
- yaml_mark_t end_mark;
- yaml_string_t string = NULL_STRING;
- yaml_string_t leading_break = NULL_STRING;
- yaml_string_t trailing_breaks = NULL_STRING;
- int chomping = 0;
- int increment = 0;
- int indent = 0;
- int leading_blank = 0;
- int trailing_blank = 0;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
-
- /* Eat the indicator '|' or '>'. */
-
- start_mark = parser->mark;
-
- SKIP(parser);
-
- /* Scan the additional block scalar indicators. */
-
- if (!CACHE(parser, 1)) goto error;
-
- /* Check for a chomping indicator. */
-
- if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-'))
- {
- /* Set the chomping method and eat the indicator. */
-
- chomping = CHECK(parser->buffer, '+') ? +1 : -1;
-
- SKIP(parser);
-
- /* Check for an indentation indicator. */
-
- if (!CACHE(parser, 1)) goto error;
-
- if (IS_DIGIT(parser->buffer))
- {
- /* Check that the indentation is greater than 0. */
-
- if (CHECK(parser->buffer, '0')) {
- yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
- start_mark, "found an indentation indicator equal to 0");
- goto error;
- }
-
- /* Get the indentation level and eat the indicator. */
-
- increment = AS_DIGIT(parser->buffer);
-
- SKIP(parser);
- }
- }
-
- /* Do the same as above, but in the opposite order. */
-
- else if (IS_DIGIT(parser->buffer))
- {
- if (CHECK(parser->buffer, '0')) {
- yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
- start_mark, "found an indentation indicator equal to 0");
- goto error;
- }
-
- increment = AS_DIGIT(parser->buffer);
-
- SKIP(parser);
-
- if (!CACHE(parser, 1)) goto error;
-
- if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) {
- chomping = CHECK(parser->buffer, '+') ? +1 : -1;
-
- SKIP(parser);
- }
- }
-
- /* Eat whitespaces and comments to the end of the line. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_BLANK(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) goto error;
- }
-
- if (CHECK(parser->buffer, '#')) {
- while (!IS_BREAKZ(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) goto error;
- }
- }
-
- /* Check if we are at the end of the line. */
-
- if (!IS_BREAKZ(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
- start_mark, "did not find expected comment or line break");
- goto error;
- }
-
- /* Eat a line break. */
-
- if (IS_BREAK(parser->buffer)) {
- if (!CACHE(parser, 2)) goto error;
- SKIP_LINE(parser);
- }
-
- end_mark = parser->mark;
-
- /* Set the indentation level if it was specified. */
-
- if (increment) {
- indent = parser->indent >= 0 ? parser->indent+increment : increment;
- }
-
- /* Scan the leading line breaks and determine the indentation level if needed. */
-
- if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks,
- start_mark, &end_mark)) goto error;
-
- /* Scan the block scalar content. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while ((int)parser->mark.column == indent && !(IS_Z(parser->buffer)))
- {
- /*
- * We are at the beginning of a non-empty line.
- */
-
- /* Is it a trailing whitespace? */
-
- trailing_blank = IS_BLANK(parser->buffer);
-
- /* Check if we need to fold the leading line break. */
-
- if (!literal && (*leading_break.start == '\n')
- && !leading_blank && !trailing_blank)
- {
- /* Do we need to join the lines by space? */
-
- if (*trailing_breaks.start == '\0') {
- if (!STRING_EXTEND(parser, string)) goto error;
- *(string.pointer ++) = ' ';
- }
-
- CLEAR(parser, leading_break);
- }
- else {
- if (!JOIN(parser, string, leading_break)) goto error;
- CLEAR(parser, leading_break);
- }
-
- /* Append the remaining line breaks. */
-
- if (!JOIN(parser, string, trailing_breaks)) goto error;
- CLEAR(parser, trailing_breaks);
-
- /* Is it a leading whitespace? */
-
- leading_blank = IS_BLANK(parser->buffer);
-
- /* Consume the current line. */
-
- while (!IS_BREAKZ(parser->buffer)) {
- if (!READ(parser, string)) goto error;
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Consume the line break. */
-
- if (!CACHE(parser, 2)) goto error;
-
- if (!READ_LINE(parser, leading_break)) goto error;
-
- /* Eat the following indentation spaces and line breaks. */
-
- if (!yaml_parser_scan_block_scalar_breaks(parser,
- &indent, &trailing_breaks, start_mark, &end_mark)) goto error;
- }
-
- /* Chomp the tail. */
-
- if (chomping != -1) {
- if (!JOIN(parser, string, leading_break)) goto error;
- }
- if (chomping == 1) {
- if (!JOIN(parser, string, trailing_breaks)) goto error;
- }
-
- /* Create a token. */
-
- SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
- literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE,
- start_mark, end_mark);
-
- STRING_DEL(parser, leading_break);
- STRING_DEL(parser, trailing_breaks);
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- STRING_DEL(parser, leading_break);
- STRING_DEL(parser, trailing_breaks);
-
- return 0;
-}
-
-/*
- * Scan indentation spaces and line breaks for a block scalar. Determine the
- * indentation level if needed.
- */
-
-static int
-yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
- int *indent, yaml_string_t *breaks,
- yaml_mark_t start_mark, yaml_mark_t *end_mark)
-{
- int max_indent = 0;
-
- *end_mark = parser->mark;
-
- /* Eat the indentation spaces and line breaks. */
-
- while (1)
- {
- /* Eat the indentation spaces. */
-
- if (!CACHE(parser, 1)) return 0;
-
- while ((!*indent || (int)parser->mark.column < *indent)
- && IS_SPACE(parser->buffer)) {
- SKIP(parser);
- if (!CACHE(parser, 1)) return 0;
- }
-
- if ((int)parser->mark.column > max_indent)
- max_indent = (int)parser->mark.column;
-
- /* Check for a tab character messing the indentation. */
-
- if ((!*indent || (int)parser->mark.column < *indent)
- && IS_TAB(parser->buffer)) {
- return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
- start_mark, "found a tab character where an indentation space is expected");
- }
-
- /* Have we found a non-empty line? */
-
- if (!IS_BREAK(parser->buffer)) break;
-
- /* Consume the line break. */
-
- if (!CACHE(parser, 2)) return 0;
- if (!READ_LINE(parser, *breaks)) return 0;
- *end_mark = parser->mark;
- }
-
- /* Determine the indentation level if needed. */
-
- if (!*indent) {
- *indent = max_indent;
- if (*indent < parser->indent + 1)
- *indent = parser->indent + 1;
- if (*indent < 1)
- *indent = 1;
- }
-
- return 1;
-}
-
-/*
- * Scan a quoted scalar.
- */
-
-static int
-yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
- int single)
-{
- yaml_mark_t start_mark;
- yaml_mark_t end_mark;
- yaml_string_t string = NULL_STRING;
- yaml_string_t leading_break = NULL_STRING;
- yaml_string_t trailing_breaks = NULL_STRING;
- yaml_string_t whitespaces = NULL_STRING;
- int leading_blanks;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
-
- /* Eat the left quote. */
-
- start_mark = parser->mark;
-
- SKIP(parser);
-
- /* Consume the content of the quoted scalar. */
-
- while (1)
- {
- /* Check that there are no document indicators at the beginning of the line. */
-
- if (!CACHE(parser, 4)) goto error;
-
- if (parser->mark.column == 0 &&
- ((CHECK_AT(parser->buffer, '-', 0) &&
- CHECK_AT(parser->buffer, '-', 1) &&
- CHECK_AT(parser->buffer, '-', 2)) ||
- (CHECK_AT(parser->buffer, '.', 0) &&
- CHECK_AT(parser->buffer, '.', 1) &&
- CHECK_AT(parser->buffer, '.', 2))) &&
- IS_BLANKZ_AT(parser->buffer, 3))
- {
- yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
- start_mark, "found unexpected document indicator");
- goto error;
- }
-
- /* Check for EOF. */
-
- if (IS_Z(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
- start_mark, "found unexpected end of stream");
- goto error;
- }
-
- /* Consume non-blank characters. */
-
- if (!CACHE(parser, 2)) goto error;
-
- leading_blanks = 0;
-
- while (!IS_BLANKZ(parser->buffer))
- {
- /* Check for an escaped single quote. */
-
- if (single && CHECK_AT(parser->buffer, '\'', 0)
- && CHECK_AT(parser->buffer, '\'', 1))
- {
- if (!STRING_EXTEND(parser, string)) goto error;
- *(string.pointer++) = '\'';
- SKIP(parser);
- SKIP(parser);
- }
-
- /* Check for the right quote. */
-
- else if (CHECK(parser->buffer, single ? '\'' : '"'))
- {
- break;
- }
-
- /* Check for an escaped line break. */
-
- else if (!single && CHECK(parser->buffer, '\\')
- && IS_BREAK_AT(parser->buffer, 1))
- {
- if (!CACHE(parser, 3)) goto error;
- SKIP(parser);
- SKIP_LINE(parser);
- leading_blanks = 1;
- break;
- }
-
- /* Check for an escape sequence. */
-
- else if (!single && CHECK(parser->buffer, '\\'))
- {
- size_t code_length = 0;
-
- if (!STRING_EXTEND(parser, string)) goto error;
-
- /* Check the escape character. */
-
- switch (parser->buffer.pointer[1])
- {
- case '0':
- *(string.pointer++) = '\0';
- break;
-
- case 'a':
- *(string.pointer++) = '\x07';
- break;
-
- case 'b':
- *(string.pointer++) = '\x08';
- break;
-
- case 't':
- case '\t':
- *(string.pointer++) = '\x09';
- break;
-
- case 'n':
- *(string.pointer++) = '\x0A';
- break;
-
- case 'v':
- *(string.pointer++) = '\x0B';
- break;
-
- case 'f':
- *(string.pointer++) = '\x0C';
- break;
-
- case 'r':
- *(string.pointer++) = '\x0D';
- break;
-
- case 'e':
- *(string.pointer++) = '\x1B';
- break;
-
- case ' ':
- *(string.pointer++) = '\x20';
- break;
-
- case '"':
- *(string.pointer++) = '"';
- break;
-
- case '/':
- *(string.pointer++) = '/';
- break;
-
- case '\\':
- *(string.pointer++) = '\\';
- break;
-
- case 'N': /* NEL (#x85) */
- *(string.pointer++) = '\xC2';
- *(string.pointer++) = '\x85';
- break;
-
- case '_': /* #xA0 */
- *(string.pointer++) = '\xC2';
- *(string.pointer++) = '\xA0';
- break;
-
- case 'L': /* LS (#x2028) */
- *(string.pointer++) = '\xE2';
- *(string.pointer++) = '\x80';
- *(string.pointer++) = '\xA8';
- break;
-
- case 'P': /* PS (#x2029) */
- *(string.pointer++) = '\xE2';
- *(string.pointer++) = '\x80';
- *(string.pointer++) = '\xA9';
- break;
-
- case 'x':
- code_length = 2;
- break;
-
- case 'u':
- code_length = 4;
- break;
-
- case 'U':
- code_length = 8;
- break;
-
- default:
- yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
- start_mark, "found unknown escape character");
- goto error;
- }
-
- SKIP(parser);
- SKIP(parser);
-
- /* Consume an arbitrary escape code. */
-
- if (code_length)
- {
- unsigned int value = 0;
- size_t k;
-
- /* Scan the character value. */
-
- if (!CACHE(parser, code_length)) goto error;
-
- for (k = 0; k < code_length; k ++) {
- if (!IS_HEX_AT(parser->buffer, k)) {
- yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
- start_mark, "did not find expected hexdecimal number");
- goto error;
- }
- value = (value << 4) + AS_HEX_AT(parser->buffer, k);
- }
-
- /* Check the value and write the character. */
-
- if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
- yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
- start_mark, "found invalid Unicode character escape code");
- goto error;
- }
-
- if (value <= 0x7F) {
- *(string.pointer++) = value;
- }
- else if (value <= 0x7FF) {
- *(string.pointer++) = 0xC0 + (value >> 6);
- *(string.pointer++) = 0x80 + (value & 0x3F);
- }
- else if (value <= 0xFFFF) {
- *(string.pointer++) = 0xE0 + (value >> 12);
- *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
- *(string.pointer++) = 0x80 + (value & 0x3F);
- }
- else {
- *(string.pointer++) = 0xF0 + (value >> 18);
- *(string.pointer++) = 0x80 + ((value >> 12) & 0x3F);
- *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
- *(string.pointer++) = 0x80 + (value & 0x3F);
- }
-
- /* Advance the pointer. */
-
- for (k = 0; k < code_length; k ++) {
- SKIP(parser);
- }
- }
- }
-
- else
- {
- /* It is a non-escaped non-blank character. */
-
- if (!READ(parser, string)) goto error;
- }
-
- if (!CACHE(parser, 2)) goto error;
- }
-
- /* Check if we are at the end of the scalar. */
-
- /* Fix for crash uninitialized value crash
- * Credit for the bug and input is to OSS Fuzz
- * Credit for the fix to Alex Gaynor
- */
- if (!CACHE(parser, 1)) goto error;
- if (CHECK(parser->buffer, single ? '\'' : '"'))
- break;
-
- /* Consume blank characters. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
- {
- if (IS_BLANK(parser->buffer))
- {
- /* Consume a space or a tab character. */
-
- if (!leading_blanks) {
- if (!READ(parser, whitespaces)) goto error;
- }
- else {
- SKIP(parser);
- }
- }
- else
- {
- if (!CACHE(parser, 2)) goto error;
-
- /* Check if it is a first line break. */
-
- if (!leading_blanks)
- {
- CLEAR(parser, whitespaces);
- if (!READ_LINE(parser, leading_break)) goto error;
- leading_blanks = 1;
- }
- else
- {
- if (!READ_LINE(parser, trailing_breaks)) goto error;
- }
- }
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Join the whitespaces or fold line breaks. */
-
- if (leading_blanks)
- {
- /* Do we need to fold line breaks? */
-
- if (leading_break.start[0] == '\n') {
- if (trailing_breaks.start[0] == '\0') {
- if (!STRING_EXTEND(parser, string)) goto error;
- *(string.pointer++) = ' ';
- }
- else {
- if (!JOIN(parser, string, trailing_breaks)) goto error;
- CLEAR(parser, trailing_breaks);
- }
- CLEAR(parser, leading_break);
- }
- else {
- if (!JOIN(parser, string, leading_break)) goto error;
- if (!JOIN(parser, string, trailing_breaks)) goto error;
- CLEAR(parser, leading_break);
- CLEAR(parser, trailing_breaks);
- }
- }
- else
- {
- if (!JOIN(parser, string, whitespaces)) goto error;
- CLEAR(parser, whitespaces);
- }
- }
-
- /* Eat the right quote. */
-
- SKIP(parser);
-
- end_mark = parser->mark;
-
- /* Create a token. */
-
- SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
- single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE,
- start_mark, end_mark);
-
- STRING_DEL(parser, leading_break);
- STRING_DEL(parser, trailing_breaks);
- STRING_DEL(parser, whitespaces);
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- STRING_DEL(parser, leading_break);
- STRING_DEL(parser, trailing_breaks);
- STRING_DEL(parser, whitespaces);
-
- return 0;
-}
-
-/*
- * Scan a plain scalar.
- */
-
-static int
-yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
-{
- yaml_mark_t start_mark;
- yaml_mark_t end_mark;
- yaml_string_t string = NULL_STRING;
- yaml_string_t leading_break = NULL_STRING;
- yaml_string_t trailing_breaks = NULL_STRING;
- yaml_string_t whitespaces = NULL_STRING;
- int leading_blanks = 0;
- int indent = parser->indent+1;
-
- if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
- if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
-
- start_mark = end_mark = parser->mark;
-
- /* Consume the content of the plain scalar. */
-
- while (1)
- {
- /* Check for a document indicator. */
-
- if (!CACHE(parser, 4)) goto error;
-
- if (parser->mark.column == 0 &&
- ((CHECK_AT(parser->buffer, '-', 0) &&
- CHECK_AT(parser->buffer, '-', 1) &&
- CHECK_AT(parser->buffer, '-', 2)) ||
- (CHECK_AT(parser->buffer, '.', 0) &&
- CHECK_AT(parser->buffer, '.', 1) &&
- CHECK_AT(parser->buffer, '.', 2))) &&
- IS_BLANKZ_AT(parser->buffer, 3)) break;
-
- /* Check for a comment. */
-
- if (CHECK(parser->buffer, '#'))
- break;
-
- /* Consume non-blank characters. */
-
- while (!IS_BLANKZ(parser->buffer))
- {
- /* 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, ':')
- && (
- 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;
- }
-
- /* Check for indicators that may end a plain scalar. */
-
- 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, '}'))))
- break;
-
- /* Check if we need to join whitespaces and breaks. */
-
- if (leading_blanks || whitespaces.start != whitespaces.pointer)
- {
- if (leading_blanks)
- {
- /* Do we need to fold line breaks? */
-
- if (leading_break.start[0] == '\n') {
- if (trailing_breaks.start[0] == '\0') {
- if (!STRING_EXTEND(parser, string)) goto error;
- *(string.pointer++) = ' ';
- }
- else {
- if (!JOIN(parser, string, trailing_breaks)) goto error;
- CLEAR(parser, trailing_breaks);
- }
- CLEAR(parser, leading_break);
- }
- else {
- if (!JOIN(parser, string, leading_break)) goto error;
- if (!JOIN(parser, string, trailing_breaks)) goto error;
- CLEAR(parser, leading_break);
- CLEAR(parser, trailing_breaks);
- }
-
- leading_blanks = 0;
- }
- else
- {
- if (!JOIN(parser, string, whitespaces)) goto error;
- CLEAR(parser, whitespaces);
- }
- }
-
- /* Copy the character. */
-
- if (!READ(parser, string)) goto error;
-
- end_mark = parser->mark;
-
- if (!CACHE(parser, 2)) goto error;
- }
-
- /* Is it the end? */
-
- if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)))
- break;
-
- /* Consume blank characters. */
-
- if (!CACHE(parser, 1)) goto error;
-
- while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
- {
- if (IS_BLANK(parser->buffer))
- {
- /* Check for tab characters that abuse indentation. */
-
- 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 violates indentation");
- goto error;
- }
-
- /* Consume a space or a tab character. */
-
- if (!leading_blanks) {
- if (!READ(parser, whitespaces)) goto error;
- }
- else {
- SKIP(parser);
- }
- }
- else
- {
- if (!CACHE(parser, 2)) goto error;
-
- /* Check if it is a first line break. */
-
- if (!leading_blanks)
- {
- CLEAR(parser, whitespaces);
- if (!READ_LINE(parser, leading_break)) goto error;
- leading_blanks = 1;
- }
- else
- {
- if (!READ_LINE(parser, trailing_breaks)) goto error;
- }
- }
- if (!CACHE(parser, 1)) goto error;
- }
-
- /* Check indentation level. */
-
- if (!parser->flow_level && (int)parser->mark.column < indent)
- break;
- }
-
- /* Create a token. */
-
- SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
- YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark);
-
- /* Note that we change the 'simple_key_allowed' flag. */
-
- if (leading_blanks) {
- parser->simple_key_allowed = 1;
- }
-
- STRING_DEL(parser, leading_break);
- STRING_DEL(parser, trailing_breaks);
- STRING_DEL(parser, whitespaces);
-
- return 1;
-
-error:
- STRING_DEL(parser, string);
- STRING_DEL(parser, leading_break);
- STRING_DEL(parser, trailing_breaks);
- STRING_DEL(parser, whitespaces);
-
- return 0;
-}
diff --git a/ext/psych/yaml/writer.c b/ext/psych/yaml/writer.c
deleted file mode 100644
index 5d57f392f1..0000000000
--- a/ext/psych/yaml/writer.c
+++ /dev/null
@@ -1,141 +0,0 @@
-
-#include "yaml_private.h"
-
-/*
- * Declarations.
- */
-
-static int
-yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
-
-YAML_DECLARE(int)
-yaml_emitter_flush(yaml_emitter_t *emitter);
-
-/*
- * Set the writer error and return 0.
- */
-
-static int
-yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
-{
- emitter->error = YAML_WRITER_ERROR;
- emitter->problem = problem;
-
- return 0;
-}
-
-/*
- * Flush the output buffer.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_flush(yaml_emitter_t *emitter)
-{
- int low, high;
-
- assert(emitter); /* Non-NULL emitter object is expected. */
- assert(emitter->write_handler); /* Write handler must be set. */
- assert(emitter->encoding); /* Output encoding must be set. */
-
- emitter->buffer.last = emitter->buffer.pointer;
- emitter->buffer.pointer = emitter->buffer.start;
-
- /* Check if the buffer is empty. */
-
- if (emitter->buffer.start == emitter->buffer.last) {
- return 1;
- }
-
- /* If the output encoding is UTF-8, we don't need to recode the buffer. */
-
- if (emitter->encoding == YAML_UTF8_ENCODING)
- {
- if (emitter->write_handler(emitter->write_handler_data,
- emitter->buffer.start,
- emitter->buffer.last - emitter->buffer.start)) {
- emitter->buffer.last = emitter->buffer.start;
- emitter->buffer.pointer = emitter->buffer.start;
- return 1;
- }
- else {
- return yaml_emitter_set_writer_error(emitter, "write error");
- }
- }
-
- /* Recode the buffer into the raw buffer. */
-
- low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
- high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
-
- while (emitter->buffer.pointer != emitter->buffer.last)
- {
- unsigned char octet;
- unsigned int width;
- unsigned int value;
- size_t k;
-
- /*
- * See the "reader.c" code for more details on UTF-8 encoding. Note
- * that we assume that the buffer contains a valid UTF-8 sequence.
- */
-
- /* Read the next UTF-8 character. */
-
- octet = emitter->buffer.pointer[0];
-
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
-
- value = (octet & 0x80) == 0x00 ? octet & 0x7F :
- (octet & 0xE0) == 0xC0 ? octet & 0x1F :
- (octet & 0xF0) == 0xE0 ? octet & 0x0F :
- (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
-
- for (k = 1; k < width; k ++) {
- octet = emitter->buffer.pointer[k];
- value = (value << 6) + (octet & 0x3F);
- }
-
- emitter->buffer.pointer += width;
-
- /* Write the character. */
-
- if (value < 0x10000)
- {
- emitter->raw_buffer.last[high] = value >> 8;
- emitter->raw_buffer.last[low] = value & 0xFF;
-
- emitter->raw_buffer.last += 2;
- }
- else
- {
- /* Write the character using a surrogate pair (check "reader.c"). */
-
- value -= 0x10000;
- emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
- emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
- emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
- emitter->raw_buffer.last[low+2] = value & 0xFF;
-
- emitter->raw_buffer.last += 4;
- }
- }
-
- /* Write the raw buffer. */
-
- if (emitter->write_handler(emitter->write_handler_data,
- emitter->raw_buffer.start,
- emitter->raw_buffer.last - emitter->raw_buffer.start)) {
- emitter->buffer.last = emitter->buffer.start;
- emitter->buffer.pointer = emitter->buffer.start;
- emitter->raw_buffer.last = emitter->raw_buffer.start;
- emitter->raw_buffer.pointer = emitter->raw_buffer.start;
- return 1;
- }
- else {
- return yaml_emitter_set_writer_error(emitter, "write error");
- }
-}
-
diff --git a/ext/psych/yaml/yaml.h b/ext/psych/yaml/yaml.h
deleted file mode 100644
index f1b7bfde20..0000000000
--- a/ext/psych/yaml/yaml.h
+++ /dev/null
@@ -1,1985 +0,0 @@
-/**
- * @file yaml.h
- * @brief Public interface for libyaml.
- *
- * Include the header file with the code:
- * @code
- * #include <yaml.h>
- * @endcode
- */
-
-#ifndef YAML_H
-#define YAML_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-/**
- * @defgroup export Export Definitions
- * @{
- */
-
-/** The public API declaration. */
-
-#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)
-# define YAML_DECLARE(type) __declspec(dllexport) type
-# else
-# define YAML_DECLARE(type) __declspec(dllimport) type
-# endif
-#else
-# define YAML_DECLARE(type) type
-#endif
-
-/** @} */
-
-/**
- * @defgroup version Version Information
- * @{
- */
-
-/**
- * Get the library version as a string.
- *
- * @returns The function returns the pointer to a static string of the form
- * @c "X.Y.Z", where @c X is the major version number, @c Y is a minor version
- * number, and @c Z is the patch version number.
- */
-
-YAML_DECLARE(const char *)
-yaml_get_version_string(void);
-
-/**
- * Get the library version numbers.
- *
- * @param[out] major Major version number.
- * @param[out] minor Minor version number.
- * @param[out] patch Patch version number.
- */
-
-YAML_DECLARE(void)
-yaml_get_version(int *major, int *minor, int *patch);
-
-/** @} */
-
-/**
- * @defgroup basic Basic Types
- * @{
- */
-
-/** The character type (UTF-8 octet). */
-typedef unsigned char yaml_char_t;
-
-/** The version directive data. */
-typedef struct yaml_version_directive_s {
- /** The major version number. */
- int major;
- /** The minor version number. */
- int minor;
-} yaml_version_directive_t;
-
-/** The tag directive data. */
-typedef struct yaml_tag_directive_s {
- /** The tag handle. */
- yaml_char_t *handle;
- /** The tag prefix. */
- yaml_char_t *prefix;
-} yaml_tag_directive_t;
-
-/** The stream encoding. */
-typedef enum yaml_encoding_e {
- /** Let the parser choose the encoding. */
- YAML_ANY_ENCODING,
- /** The default UTF-8 encoding. */
- YAML_UTF8_ENCODING,
- /** The UTF-16-LE encoding with BOM. */
- YAML_UTF16LE_ENCODING,
- /** The UTF-16-BE encoding with BOM. */
- YAML_UTF16BE_ENCODING
-} yaml_encoding_t;
-
-/** Line break types. */
-
-typedef enum yaml_break_e {
- /** Let the parser choose the break type. */
- YAML_ANY_BREAK,
- /** Use CR for line breaks (Mac style). */
- YAML_CR_BREAK,
- /** Use LN for line breaks (Unix style). */
- YAML_LN_BREAK,
- /** Use CR LN for line breaks (DOS style). */
- YAML_CRLN_BREAK
-} yaml_break_t;
-
-/** Many bad things could happen with the parser and emitter. */
-typedef enum yaml_error_type_e {
- /** No error is produced. */
- YAML_NO_ERROR,
-
- /** Cannot allocate or reallocate a block of memory. */
- YAML_MEMORY_ERROR,
-
- /** Cannot read or decode the input stream. */
- YAML_READER_ERROR,
- /** Cannot scan the input stream. */
- YAML_SCANNER_ERROR,
- /** Cannot parse the input stream. */
- YAML_PARSER_ERROR,
- /** Cannot compose a YAML document. */
- YAML_COMPOSER_ERROR,
-
- /** Cannot write to the output stream. */
- YAML_WRITER_ERROR,
- /** Cannot emit a YAML stream. */
- YAML_EMITTER_ERROR
-} yaml_error_type_t;
-
-/** The pointer position. */
-typedef struct yaml_mark_s {
- /** The position index. */
- size_t index;
-
- /** The position line. */
- size_t line;
-
- /** The position column. */
- size_t column;
-} yaml_mark_t;
-
-/** @} */
-
-/**
- * @defgroup styles Node Styles
- * @{
- */
-
-/** Scalar styles. */
-typedef enum yaml_scalar_style_e {
- /** Let the emitter choose the style. */
- YAML_ANY_SCALAR_STYLE,
-
- /** The plain scalar style. */
- YAML_PLAIN_SCALAR_STYLE,
-
- /** The single-quoted scalar style. */
- YAML_SINGLE_QUOTED_SCALAR_STYLE,
- /** The double-quoted scalar style. */
- YAML_DOUBLE_QUOTED_SCALAR_STYLE,
-
- /** The literal scalar style. */
- YAML_LITERAL_SCALAR_STYLE,
- /** The folded scalar style. */
- YAML_FOLDED_SCALAR_STYLE
-} yaml_scalar_style_t;
-
-/** Sequence styles. */
-typedef enum yaml_sequence_style_e {
- /** Let the emitter choose the style. */
- YAML_ANY_SEQUENCE_STYLE,
-
- /** The block sequence style. */
- YAML_BLOCK_SEQUENCE_STYLE,
- /** The flow sequence style. */
- YAML_FLOW_SEQUENCE_STYLE
-} yaml_sequence_style_t;
-
-/** Mapping styles. */
-typedef enum yaml_mapping_style_e {
- /** Let the emitter choose the style. */
- YAML_ANY_MAPPING_STYLE,
-
- /** The block mapping style. */
- YAML_BLOCK_MAPPING_STYLE,
- /** The flow mapping style. */
- YAML_FLOW_MAPPING_STYLE
-/* YAML_FLOW_SET_MAPPING_STYLE */
-} yaml_mapping_style_t;
-
-/** @} */
-
-/**
- * @defgroup tokens Tokens
- * @{
- */
-
-/** Token types. */
-typedef enum yaml_token_type_e {
- /** An empty token. */
- YAML_NO_TOKEN,
-
- /** A STREAM-START token. */
- YAML_STREAM_START_TOKEN,
- /** A STREAM-END token. */
- YAML_STREAM_END_TOKEN,
-
- /** A VERSION-DIRECTIVE token. */
- YAML_VERSION_DIRECTIVE_TOKEN,
- /** A TAG-DIRECTIVE token. */
- YAML_TAG_DIRECTIVE_TOKEN,
- /** A DOCUMENT-START token. */
- YAML_DOCUMENT_START_TOKEN,
- /** A DOCUMENT-END token. */
- YAML_DOCUMENT_END_TOKEN,
-
- /** A BLOCK-SEQUENCE-START token. */
- YAML_BLOCK_SEQUENCE_START_TOKEN,
- /** A BLOCK-MAPPING-START token. */
- YAML_BLOCK_MAPPING_START_TOKEN,
- /** A BLOCK-END token. */
- YAML_BLOCK_END_TOKEN,
-
- /** A FLOW-SEQUENCE-START token. */
- YAML_FLOW_SEQUENCE_START_TOKEN,
- /** A FLOW-SEQUENCE-END token. */
- YAML_FLOW_SEQUENCE_END_TOKEN,
- /** A FLOW-MAPPING-START token. */
- YAML_FLOW_MAPPING_START_TOKEN,
- /** A FLOW-MAPPING-END token. */
- YAML_FLOW_MAPPING_END_TOKEN,
-
- /** A BLOCK-ENTRY token. */
- YAML_BLOCK_ENTRY_TOKEN,
- /** A FLOW-ENTRY token. */
- YAML_FLOW_ENTRY_TOKEN,
- /** A KEY token. */
- YAML_KEY_TOKEN,
- /** A VALUE token. */
- YAML_VALUE_TOKEN,
-
- /** An ALIAS token. */
- YAML_ALIAS_TOKEN,
- /** An ANCHOR token. */
- YAML_ANCHOR_TOKEN,
- /** A TAG token. */
- YAML_TAG_TOKEN,
- /** A SCALAR token. */
- YAML_SCALAR_TOKEN
-} yaml_token_type_t;
-
-/** The token structure. */
-typedef struct yaml_token_s {
-
- /** The token type. */
- yaml_token_type_t type;
-
- /** The token data. */
- union {
-
- /** The stream start (for @c YAML_STREAM_START_TOKEN). */
- struct {
- /** The stream encoding. */
- yaml_encoding_t encoding;
- } stream_start;
-
- /** The alias (for @c YAML_ALIAS_TOKEN). */
- struct {
- /** The alias value. */
- yaml_char_t *value;
- } alias;
-
- /** The anchor (for @c YAML_ANCHOR_TOKEN). */
- struct {
- /** The anchor value. */
- yaml_char_t *value;
- } anchor;
-
- /** The tag (for @c YAML_TAG_TOKEN). */
- struct {
- /** The tag handle. */
- yaml_char_t *handle;
- /** The tag suffix. */
- yaml_char_t *suffix;
- } tag;
-
- /** The scalar value (for @c YAML_SCALAR_TOKEN). */
- struct {
- /** The scalar value. */
- yaml_char_t *value;
- /** The length of the scalar value. */
- size_t length;
- /** The scalar style. */
- yaml_scalar_style_t style;
- } scalar;
-
- /** The version directive (for @c YAML_VERSION_DIRECTIVE_TOKEN). */
- struct {
- /** The major version number. */
- int major;
- /** The minor version number. */
- int minor;
- } version_directive;
-
- /** The tag directive (for @c YAML_TAG_DIRECTIVE_TOKEN). */
- struct {
- /** The tag handle. */
- yaml_char_t *handle;
- /** The tag prefix. */
- yaml_char_t *prefix;
- } tag_directive;
-
- } data;
-
- /** The beginning of the token. */
- yaml_mark_t start_mark;
- /** The end of the token. */
- yaml_mark_t end_mark;
-
-} yaml_token_t;
-
-/**
- * Free any memory allocated for a token object.
- *
- * @param[in,out] token A token object.
- */
-
-YAML_DECLARE(void)
-yaml_token_delete(yaml_token_t *token);
-
-/** @} */
-
-/**
- * @defgroup events Events
- * @{
- */
-
-/** Event types. */
-typedef enum yaml_event_type_e {
- /** An empty event. */
- YAML_NO_EVENT,
-
- /** A STREAM-START event. */
- YAML_STREAM_START_EVENT,
- /** A STREAM-END event. */
- YAML_STREAM_END_EVENT,
-
- /** A DOCUMENT-START event. */
- YAML_DOCUMENT_START_EVENT,
- /** A DOCUMENT-END event. */
- YAML_DOCUMENT_END_EVENT,
-
- /** An ALIAS event. */
- YAML_ALIAS_EVENT,
- /** A SCALAR event. */
- YAML_SCALAR_EVENT,
-
- /** A SEQUENCE-START event. */
- YAML_SEQUENCE_START_EVENT,
- /** A SEQUENCE-END event. */
- YAML_SEQUENCE_END_EVENT,
-
- /** A MAPPING-START event. */
- YAML_MAPPING_START_EVENT,
- /** A MAPPING-END event. */
- YAML_MAPPING_END_EVENT
-} yaml_event_type_t;
-
-/** The event structure. */
-typedef struct yaml_event_s {
-
- /** The event type. */
- yaml_event_type_t type;
-
- /** The event data. */
- union {
-
- /** The stream parameters (for @c YAML_STREAM_START_EVENT). */
- struct {
- /** The document encoding. */
- yaml_encoding_t encoding;
- } stream_start;
-
- /** The document parameters (for @c YAML_DOCUMENT_START_EVENT). */
- struct {
- /** The version directive. */
- yaml_version_directive_t *version_directive;
-
- /** The list of tag directives. */
- struct {
- /** The beginning of the tag directives list. */
- yaml_tag_directive_t *start;
- /** The end of the tag directives list. */
- yaml_tag_directive_t *end;
- } tag_directives;
-
- /** Is the document indicator implicit? */
- int implicit;
- } document_start;
-
- /** The document end parameters (for @c YAML_DOCUMENT_END_EVENT). */
- struct {
- /** Is the document end indicator implicit? */
- int implicit;
- } document_end;
-
- /** The alias parameters (for @c YAML_ALIAS_EVENT). */
- struct {
- /** The anchor. */
- yaml_char_t *anchor;
- } alias;
-
- /** The scalar parameters (for @c YAML_SCALAR_EVENT). */
- struct {
- /** The anchor. */
- yaml_char_t *anchor;
- /** The tag. */
- yaml_char_t *tag;
- /** The scalar value. */
- yaml_char_t *value;
- /** The length of the scalar value. */
- size_t length;
- /** Is the tag optional for the plain style? */
- int plain_implicit;
- /** Is the tag optional for any non-plain style? */
- int quoted_implicit;
- /** The scalar style. */
- yaml_scalar_style_t style;
- } scalar;
-
- /** The sequence parameters (for @c YAML_SEQUENCE_START_EVENT). */
- struct {
- /** The anchor. */
- yaml_char_t *anchor;
- /** The tag. */
- yaml_char_t *tag;
- /** Is the tag optional? */
- int implicit;
- /** The sequence style. */
- yaml_sequence_style_t style;
- } sequence_start;
-
- /** The mapping parameters (for @c YAML_MAPPING_START_EVENT). */
- struct {
- /** The anchor. */
- yaml_char_t *anchor;
- /** The tag. */
- yaml_char_t *tag;
- /** Is the tag optional? */
- int implicit;
- /** The mapping style. */
- yaml_mapping_style_t style;
- } mapping_start;
-
- } data;
-
- /** The beginning of the event. */
- yaml_mark_t start_mark;
- /** The end of the event. */
- yaml_mark_t end_mark;
-
-} yaml_event_t;
-
-/**
- * Create the STREAM-START event.
- *
- * @param[out] event An empty event object.
- * @param[in] encoding The stream encoding.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_stream_start_event_initialize(yaml_event_t *event,
- yaml_encoding_t encoding);
-
-/**
- * Create the STREAM-END event.
- *
- * @param[out] event An empty event object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_stream_end_event_initialize(yaml_event_t *event);
-
-/**
- * Create the DOCUMENT-START event.
- *
- * The @a implicit argument is considered as a stylistic parameter and may be
- * ignored by the emitter.
- *
- * @param[out] event An empty event object.
- * @param[in] version_directive The %YAML directive value or
- * @c NULL.
- * @param[in] tag_directives_start The beginning of the %TAG
- * directives list.
- * @param[in] tag_directives_end The end of the %TAG directives
- * list.
- * @param[in] implicit If the document start indicator is
- * implicit.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_document_start_event_initialize(yaml_event_t *event,
- yaml_version_directive_t *version_directive,
- yaml_tag_directive_t *tag_directives_start,
- yaml_tag_directive_t *tag_directives_end,
- int implicit);
-
-/**
- * Create the DOCUMENT-END event.
- *
- * The @a implicit argument is considered as a stylistic parameter and may be
- * ignored by the emitter.
- *
- * @param[out] event An empty event object.
- * @param[in] implicit If the document end indicator is implicit.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_document_end_event_initialize(yaml_event_t *event, int implicit);
-
-/**
- * Create an ALIAS event.
- *
- * @param[out] event An empty event object.
- * @param[in] anchor The anchor value.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_alias_event_initialize(yaml_event_t *event, const yaml_char_t *anchor);
-
-/**
- * Create a SCALAR event.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * Either the @a tag attribute or one of the @a plain_implicit and
- * @a quoted_implicit flags must be set.
- *
- * @param[out] event An empty event object.
- * @param[in] anchor The scalar anchor or @c NULL.
- * @param[in] tag The scalar tag or @c NULL.
- * @param[in] value The scalar value.
- * @param[in] length The length of the scalar value.
- * @param[in] plain_implicit If the tag may be omitted for the plain
- * style.
- * @param[in] quoted_implicit If the tag may be omitted for any
- * non-plain style.
- * @param[in] style The scalar style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_scalar_event_initialize(yaml_event_t *event,
- 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);
-
-/**
- * Create a SEQUENCE-START event.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * Either the @a tag attribute or the @a implicit flag must be set.
- *
- * @param[out] event An empty event object.
- * @param[in] anchor The sequence anchor or @c NULL.
- * @param[in] tag The sequence tag or @c NULL.
- * @param[in] implicit If the tag may be omitted.
- * @param[in] style The sequence style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_start_event_initialize(yaml_event_t *event,
- const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
- yaml_sequence_style_t style);
-
-/**
- * Create a SEQUENCE-END event.
- *
- * @param[out] event An empty event object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_sequence_end_event_initialize(yaml_event_t *event);
-
-/**
- * Create a MAPPING-START event.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * Either the @a tag attribute or the @a implicit flag must be set.
- *
- * @param[out] event An empty event object.
- * @param[in] anchor The mapping anchor or @c NULL.
- * @param[in] tag The mapping tag or @c NULL.
- * @param[in] implicit If the tag may be omitted.
- * @param[in] style The mapping style.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_start_event_initialize(yaml_event_t *event,
- const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
- yaml_mapping_style_t style);
-
-/**
- * Create a MAPPING-END event.
- *
- * @param[out] event An empty event object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_mapping_end_event_initialize(yaml_event_t *event);
-
-/**
- * Free any memory allocated for an event object.
- *
- * @param[in,out] event An event object.
- */
-
-YAML_DECLARE(void)
-yaml_event_delete(yaml_event_t *event);
-
-/** @} */
-
-/**
- * @defgroup nodes Nodes
- * @{
- */
-
-/** 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 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"
-/** The tag @c !!int for integer values. */
-#define YAML_INT_TAG "tag:yaml.org,2002:int"
-/** The tag @c !!float for float values. */
-#define YAML_FLOAT_TAG "tag:yaml.org,2002:float"
-/** The tag @c !!timestamp for date and time values. */
-#define YAML_TIMESTAMP_TAG "tag:yaml.org,2002:timestamp"
-
-/** The tag @c !!seq is used to denote sequences. */
-#define YAML_SEQ_TAG "tag:yaml.org,2002:seq"
-/** The tag @c !!map is used to denote mapping. */
-#define YAML_MAP_TAG "tag:yaml.org,2002:map"
-
-/** The default scalar tag is @c !!str. */
-#define YAML_DEFAULT_SCALAR_TAG YAML_STR_TAG
-/** The default sequence tag is @c !!seq. */
-#define YAML_DEFAULT_SEQUENCE_TAG YAML_SEQ_TAG
-/** The default mapping tag is @c !!map. */
-#define YAML_DEFAULT_MAPPING_TAG YAML_MAP_TAG
-
-/** Node types. */
-typedef enum yaml_node_type_e {
- /** An empty node. */
- YAML_NO_NODE,
-
- /** A scalar node. */
- YAML_SCALAR_NODE,
- /** A sequence node. */
- YAML_SEQUENCE_NODE,
- /** A mapping node. */
- YAML_MAPPING_NODE
-} yaml_node_type_t;
-
-/** The forward definition of a document node structure. */
-typedef struct yaml_node_s yaml_node_t;
-
-/** An element of a sequence node. */
-typedef int yaml_node_item_t;
-
-/** An element of a mapping node. */
-typedef struct yaml_node_pair_s {
- /** The key of the element. */
- int key;
- /** The value of the element. */
- int value;
-} yaml_node_pair_t;
-
-/** The node structure. */
-struct yaml_node_s {
-
- /** The node type. */
- yaml_node_type_t type;
-
- /** The node tag. */
- yaml_char_t *tag;
-
- /** The node data. */
- union {
-
- /** The scalar parameters (for @c YAML_SCALAR_NODE). */
- struct {
- /** The scalar value. */
- yaml_char_t *value;
- /** The length of the scalar value. */
- size_t length;
- /** The scalar style. */
- yaml_scalar_style_t style;
- } scalar;
-
- /** The sequence parameters (for @c YAML_SEQUENCE_NODE). */
- struct {
- /** The stack of sequence items. */
- struct {
- /** The beginning of the stack. */
- yaml_node_item_t *start;
- /** The end of the stack. */
- yaml_node_item_t *end;
- /** The top of the stack. */
- yaml_node_item_t *top;
- } items;
- /** The sequence style. */
- yaml_sequence_style_t style;
- } sequence;
-
- /** The mapping parameters (for @c YAML_MAPPING_NODE). */
- struct {
- /** The stack of mapping pairs (key, value). */
- struct {
- /** The beginning of the stack. */
- yaml_node_pair_t *start;
- /** The end of the stack. */
- yaml_node_pair_t *end;
- /** The top of the stack. */
- yaml_node_pair_t *top;
- } pairs;
- /** The mapping style. */
- yaml_mapping_style_t style;
- } mapping;
-
- } data;
-
- /** The beginning of the node. */
- yaml_mark_t start_mark;
- /** The end of the node. */
- yaml_mark_t end_mark;
-
-};
-
-/** The document structure. */
-typedef struct yaml_document_s {
-
- /** The document nodes. */
- struct {
- /** The beginning of the stack. */
- yaml_node_t *start;
- /** The end of the stack. */
- yaml_node_t *end;
- /** The top of the stack. */
- yaml_node_t *top;
- } nodes;
-
- /** The version directive. */
- yaml_version_directive_t *version_directive;
-
- /** The list of tag directives. */
- struct {
- /** The beginning of the tag directives list. */
- yaml_tag_directive_t *start;
- /** The end of the tag directives list. */
- yaml_tag_directive_t *end;
- } tag_directives;
-
- /** Is the document start indicator implicit? */
- int start_implicit;
- /** Is the document end indicator implicit? */
- int end_implicit;
-
- /** The beginning of the document. */
- yaml_mark_t start_mark;
- /** The end of the document. */
- yaml_mark_t end_mark;
-
-} yaml_document_t;
-
-/**
- * Create a YAML document.
- *
- * @param[out] document An empty document object.
- * @param[in] version_directive The %YAML directive value or
- * @c NULL.
- * @param[in] tag_directives_start The beginning of the %TAG
- * directives list.
- * @param[in] tag_directives_end The end of the %TAG directives
- * list.
- * @param[in] start_implicit If the document start indicator is
- * implicit.
- * @param[in] end_implicit If the document end indicator is
- * implicit.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_document_initialize(yaml_document_t *document,
- yaml_version_directive_t *version_directive,
- yaml_tag_directive_t *tag_directives_start,
- yaml_tag_directive_t *tag_directives_end,
- int start_implicit, int end_implicit);
-
-/**
- * Delete a YAML document and all its nodes.
- *
- * @param[in,out] document A document object.
- */
-
-YAML_DECLARE(void)
-yaml_document_delete(yaml_document_t *document);
-
-/**
- * Get a node of a YAML document.
- *
- * The pointer returned by this function is valid until any of the functions
- * modifying the documents are called.
- *
- * @param[in] document A document object.
- * @param[in] index The node id.
- *
- * @returns the node objct or @c NULL if @c node_id is out of range.
- */
-
-YAML_DECLARE(yaml_node_t *)
-yaml_document_get_node(yaml_document_t *document, int index);
-
-/**
- * Get the root of a YAML document node.
- *
- * The root object is the first object added to the document.
- *
- * The pointer returned by this function is valid until any of the functions
- * modifying the documents are called.
- *
- * An empty document produced by the parser signifies the end of a YAML
- * stream.
- *
- * @param[in] document A document object.
- *
- * @returns the node object or @c NULL if the document is empty.
- */
-
-YAML_DECLARE(yaml_node_t *)
-yaml_document_get_root_node(yaml_document_t *document);
-
-/**
- * Create a SCALAR node and attach it to the document.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * @param[in,out] document A document object.
- * @param[in] tag The scalar tag.
- * @param[in] value The scalar value.
- * @param[in] length The length of the scalar value.
- * @param[in] style The scalar style.
- *
- * @returns the node id or @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_document_add_scalar(yaml_document_t *document,
- const yaml_char_t *tag, const yaml_char_t *value, int length,
- yaml_scalar_style_t style);
-
-/**
- * Create a SEQUENCE node and attach it to the document.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * @param[in,out] document A document object.
- * @param[in] tag The sequence tag.
- * @param[in] style The sequence style.
- *
- * @returns the node id or @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_document_add_sequence(yaml_document_t *document,
- const yaml_char_t *tag, yaml_sequence_style_t style);
-
-/**
- * Create a MAPPING node and attach it to the document.
- *
- * The @a style argument may be ignored by the emitter.
- *
- * @param[in,out] document A document object.
- * @param[in] tag The sequence tag.
- * @param[in] style The sequence style.
- *
- * @returns the node id or @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_document_add_mapping(yaml_document_t *document,
- const yaml_char_t *tag, yaml_mapping_style_t style);
-
-/**
- * Add an item to a SEQUENCE node.
- *
- * @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.
- */
-
-YAML_DECLARE(int)
-yaml_document_append_sequence_item(yaml_document_t *document,
- int sequence, int item);
-
-/**
- * Add a pair of a key and a value to a MAPPING node.
- *
- * @param[in,out] document A document object.
- * @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.
- */
-
-YAML_DECLARE(int)
-yaml_document_append_mapping_pair(yaml_document_t *document,
- int mapping, int key, int value);
-
-/** @} */
-
-/**
- * @defgroup parser Parser Definitions
- * @{
- */
-
-/**
- * The prototype of a read handler.
- *
- * The read handler is called when the parser needs to read more bytes from the
- * source. The handler should write not more than @a size bytes to the @a
- * buffer. The number of written bytes should be set to the @a length variable.
- *
- * @param[in,out] data A pointer to an application data specified by
- * yaml_parser_set_input().
- * @param[out] buffer The buffer to write the data from the source.
- * @param[in] size The size of the buffer.
- * @param[out] size_read The actual number of bytes read from the source.
- *
- * @returns On success, the handler should return @c 1. If the handler failed,
- * the returned value should be @c 0. On EOF, the handler should set the
- * @a size_read to @c 0 and return @c 1.
- */
-
-typedef int yaml_read_handler_t(void *data, unsigned char *buffer, size_t size,
- size_t *size_read);
-
-/**
- * This structure holds information about a potential simple key.
- */
-
-typedef struct yaml_simple_key_s {
- /** Is a simple key possible? */
- int possible;
-
- /** Is a simple key required? */
- int required;
-
- /** The number of the token. */
- size_t token_number;
-
- /** The position mark. */
- yaml_mark_t mark;
-} yaml_simple_key_t;
-
-/**
- * The states of the parser.
- */
-typedef enum yaml_parser_state_e {
- /** Expect STREAM-START. */
- YAML_PARSE_STREAM_START_STATE,
- /** Expect the beginning of an implicit document. */
- YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE,
- /** Expect DOCUMENT-START. */
- YAML_PARSE_DOCUMENT_START_STATE,
- /** Expect the content of a document. */
- 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. */
- YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE,
- /** Expect a flow node. */
- YAML_PARSE_FLOW_NODE_STATE,
- /** Expect the first entry of a block sequence. */
- 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. */
- YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE,
- /** Expect a block mapping key. */
- YAML_PARSE_BLOCK_MAPPING_KEY_STATE,
- /** Expect a block mapping value. */
- 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. */
- YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE,
- /** Expect a value of an ordered mapping. */
- YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE,
- /** Expect the and of an ordered mapping entry. */
- YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE,
- /** 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,
- /** Expect an empty value of a flow mapping. */
- YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE,
- /** Expect nothing. */
- YAML_PARSE_END_STATE
-} yaml_parser_state_t;
-
-/**
- * This structure holds aliases data.
- */
-
-typedef struct yaml_alias_data_s {
- /** The anchor. */
- yaml_char_t *anchor;
- /** The node id. */
- int index;
- /** The anchor mark. */
- yaml_mark_t mark;
-} yaml_alias_data_t;
-
-/**
- * The parser structure.
- *
- * All members are internal. Manage the structure using the @c yaml_parser_
- * family of functions.
- */
-
-typedef struct yaml_parser_s {
-
- /**
- * @name Error handling
- * @{
- */
-
- /** Error type. */
- yaml_error_type_t error;
- /** Error description. */
- const char *problem;
- /** The byte about which the problem occurred. */
- size_t problem_offset;
- /** The problematic value (@c -1 is none). */
- int problem_value;
- /** The problem position. */
- yaml_mark_t problem_mark;
- /** The error context. */
- const char *context;
- /** The context position. */
- yaml_mark_t context_mark;
-
- /**
- * @}
- */
-
- /**
- * @name Reader stuff
- * @{
- */
-
- /** Read handler. */
- yaml_read_handler_t *read_handler;
-
- /** A pointer for passing to the read handler. */
- void *read_handler_data;
-
- /** Standard (string or file) input data. */
- union {
- /** String input data. */
- struct {
- /** The string start pointer. */
- const unsigned char *start;
- /** The string end pointer. */
- const unsigned char *end;
- /** The string current position. */
- const unsigned char *current;
- } string;
-
- /** File input data. */
- FILE *file;
- } input;
-
- /** EOF flag */
- int eof;
-
- /** The working buffer. */
- struct {
- /** The beginning of the buffer. */
- yaml_char_t *start;
- /** The end of the buffer. */
- yaml_char_t *end;
- /** The current position of the buffer. */
- yaml_char_t *pointer;
- /** The last filled position of the buffer. */
- yaml_char_t *last;
- } buffer;
-
- /* The number of unread characters in the buffer. */
- size_t unread;
-
- /** The raw buffer. */
- struct {
- /** The beginning of the buffer. */
- unsigned char *start;
- /** The end of the buffer. */
- unsigned char *end;
- /** The current position of the buffer. */
- unsigned char *pointer;
- /** The last filled position of the buffer. */
- unsigned char *last;
- } raw_buffer;
-
- /** The input encoding. */
- yaml_encoding_t encoding;
-
- /** The offset of the current position (in bytes). */
- size_t offset;
-
- /** The mark of the current position. */
- yaml_mark_t mark;
-
- /**
- * @}
- */
-
- /**
- * @name Scanner stuff
- * @{
- */
-
- /** Have we started to scan the input stream? */
- int stream_start_produced;
-
- /** Have we reached the end of the input stream? */
- int stream_end_produced;
-
- /** The number of unclosed '[' and '{' indicators. */
- int flow_level;
-
- /** The tokens queue. */
- struct {
- /** The beginning of the tokens queue. */
- yaml_token_t *start;
- /** The end of the tokens queue. */
- yaml_token_t *end;
- /** The head of the tokens queue. */
- yaml_token_t *head;
- /** The tail of the tokens queue. */
- yaml_token_t *tail;
- } tokens;
-
- /** The number of tokens fetched from the queue. */
- size_t tokens_parsed;
-
- /** Does the tokens queue contain a token ready for dequeueing. */
- int token_available;
-
- /** The indentation levels stack. */
- struct {
- /** The beginning of the stack. */
- int *start;
- /** The end of the stack. */
- int *end;
- /** The top of the stack. */
- int *top;
- } indents;
-
- /** The current indentation level. */
- int indent;
-
- /** May a simple key occur at the current position? */
- int simple_key_allowed;
-
- /** The stack of simple keys. */
- struct {
- /** The beginning of the stack. */
- yaml_simple_key_t *start;
- /** The end of the stack. */
- yaml_simple_key_t *end;
- /** The top of the stack. */
- yaml_simple_key_t *top;
- } simple_keys;
-
- /**
- * @}
- */
-
- /**
- * @name Parser stuff
- * @{
- */
-
- /** The parser states stack. */
- struct {
- /** The beginning of the stack. */
- yaml_parser_state_t *start;
- /** The end of the stack. */
- yaml_parser_state_t *end;
- /** The top of the stack. */
- yaml_parser_state_t *top;
- } states;
-
- /** The current parser state. */
- yaml_parser_state_t state;
-
- /** The stack of marks. */
- struct {
- /** The beginning of the stack. */
- yaml_mark_t *start;
- /** The end of the stack. */
- yaml_mark_t *end;
- /** The top of the stack. */
- yaml_mark_t *top;
- } marks;
-
- /** The list of TAG directives. */
- struct {
- /** The beginning of the list. */
- yaml_tag_directive_t *start;
- /** The end of the list. */
- yaml_tag_directive_t *end;
- /** The top of the list. */
- yaml_tag_directive_t *top;
- } tag_directives;
-
- /**
- * @}
- */
-
- /**
- * @name Dumper stuff
- * @{
- */
-
- /** The alias data. */
- struct {
- /** The beginning of the list. */
- yaml_alias_data_t *start;
- /** The end of the list. */
- yaml_alias_data_t *end;
- /** The top of the list. */
- yaml_alias_data_t *top;
- } aliases;
-
- /** The currently parsed document. */
- yaml_document_t *document;
-
- /**
- * @}
- */
-
-} yaml_parser_t;
-
-/**
- * Initialize a parser.
- *
- * This function creates a new parser object. An application is responsible
- * for destroying the object using the yaml_parser_delete() function.
- *
- * @param[out] parser An empty parser object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_parser_initialize(yaml_parser_t *parser);
-
-/**
- * Destroy a parser.
- *
- * @param[in,out] parser A parser object.
- */
-
-YAML_DECLARE(void)
-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 destroying @a input after
- * destroying the @a parser.
- *
- * @param[in,out] parser A parser object.
- * @param[in] input A source data.
- * @param[in] size The length of the source data in bytes.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_input_string(yaml_parser_t *parser,
- const unsigned char *input, size_t size);
-
-/**
- * Set a file input.
- *
- * @a file should be a file object open for reading. The application is
- * responsible for closing the @a file.
- *
- * @param[in,out] parser A parser object.
- * @param[in] file An open file.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file);
-
-/**
- * Set a generic input handler.
- *
- * @param[in,out] parser A parser object.
- * @param[in] handler A read handler.
- * @param[in] data Any application data for passing to the read
- * handler.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_input(yaml_parser_t *parser,
- yaml_read_handler_t *handler, void *data);
-
-/**
- * Set the source encoding.
- *
- * @param[in,out] parser A parser object.
- * @param[in] encoding The source encoding.
- */
-
-YAML_DECLARE(void)
-yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding);
-
-/**
- * Scan the input stream and produce the next token.
- *
- * Call the function subsequently to produce a sequence of tokens corresponding
- * to the input stream. The initial token has the type
- * @c YAML_STREAM_START_TOKEN while the ending token has the type
- * @c YAML_STREAM_END_TOKEN.
- *
- * An application is responsible for freeing any buffers associated with the
- * produced token object using the @c yaml_token_delete function.
- *
- * An application must not alternate the calls of yaml_parser_scan() with the
- * calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
- * the parser.
- *
- * @param[in,out] parser A parser object.
- * @param[out] token An empty token object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
-
-/**
- * Parse the input stream and produce the next parsing event.
- *
- * Call the function subsequently to produce a sequence of events corresponding
- * to the input stream. The initial event has the type
- * @c YAML_STREAM_START_EVENT while the ending event has the type
- * @c YAML_STREAM_END_EVENT.
- *
- * An application is responsible for freeing any buffers associated with the
- * produced event object using the yaml_event_delete() function.
- *
- * An application must not alternate the calls of yaml_parser_parse() with the
- * calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the
- * parser.
- *
- * @param[in,out] parser A parser object.
- * @param[out] event An empty event object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
-
-/**
- * Parse the input stream and produce the next YAML document.
- *
- * Call this function subsequently to produce a sequence of documents
- * constituting the input stream.
- *
- * If the produced document has no root node, it means that the document
- * end has been reached.
- *
- * An application is responsible for freeing any data associated with the
- * produced document object using the yaml_document_delete() function.
- *
- * An application must not alternate the calls of yaml_parser_load() with the
- * calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
- * the parser.
- *
- * @param[in,out] parser A parser object.
- * @param[out] document An empty document object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
-
-/** @} */
-
-/**
- * @defgroup emitter Emitter Definitions
- * @{
- */
-
-/**
- * The prototype of a write handler.
- *
- * The write handler is called when the emitter needs to flush the accumulated
- * characters to the output. The handler should write @a size bytes of the
- * @a buffer to the output.
- *
- * @param[in,out] data A pointer to an application data specified by
- * yaml_emitter_set_output().
- * @param[in] buffer The buffer with bytes to be written.
- * @param[in] size The size of the buffer.
- *
- * @returns On success, the handler should return @c 1. If the handler failed,
- * the returned value should be @c 0.
- */
-
-typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size);
-
-/** The emitter states. */
-typedef enum yaml_emitter_state_e {
- /** Expect STREAM-START. */
- YAML_EMIT_STREAM_START_STATE,
- /** Expect the first DOCUMENT-START or STREAM-END. */
- YAML_EMIT_FIRST_DOCUMENT_START_STATE,
- /** Expect DOCUMENT-START or STREAM-END. */
- YAML_EMIT_DOCUMENT_START_STATE,
- /** Expect the content of a document. */
- 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. */
- YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE,
- /** Expect the first key of a flow mapping. */
- YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE,
- /** Expect a key of a flow mapping. */
- 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. */
- YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE,
- /** Expect an item of a block sequence. */
- YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE,
- /** Expect the first key of a block mapping. */
- 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. */
- YAML_EMIT_BLOCK_MAPPING_VALUE_STATE,
- /** Expect nothing. */
- 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.
- *
- * All members are internal. Manage the structure using the @c yaml_emitter_
- * family of functions.
- */
-
-typedef struct yaml_emitter_s {
-
- /**
- * @name Error handling
- * @{
- */
-
- /** Error type. */
- yaml_error_type_t error;
- /** Error description. */
- const char *problem;
-
- /**
- * @}
- */
-
- /**
- * @name Writer stuff
- * @{
- */
-
- /** Write handler. */
- yaml_write_handler_t *write_handler;
-
- /** A pointer for passing to the write handler. */
- void *write_handler_data;
-
- /** Standard (string or file) output data. */
- union {
- /** String output data. */
- struct {
- /** The buffer pointer. */
- unsigned char *buffer;
- /** The buffer size. */
- size_t size;
- /** The number of written bytes. */
- size_t *size_written;
- } string;
-
- /** File output data. */
- FILE *file;
- } output;
-
- /** The working buffer. */
- struct {
- /** The beginning of the buffer. */
- yaml_char_t *start;
- /** The end of the buffer. */
- yaml_char_t *end;
- /** The current position of the buffer. */
- yaml_char_t *pointer;
- /** The last filled position of the buffer. */
- yaml_char_t *last;
- } buffer;
-
- /** The raw buffer. */
- struct {
- /** The beginning of the buffer. */
- unsigned char *start;
- /** The end of the buffer. */
- unsigned char *end;
- /** The current position of the buffer. */
- unsigned char *pointer;
- /** The last filled position of the buffer. */
- unsigned char *last;
- } raw_buffer;
-
- /** The stream encoding. */
- yaml_encoding_t encoding;
-
- /**
- * @}
- */
-
- /**
- * @name Emitter stuff
- * @{
- */
-
- /** If the output is in the canonical style? */
- int canonical;
- /** The number of indentation spaces. */
- int best_indent;
- /** The preferred width of the output lines. */
- int best_width;
- /** Allow unescaped non-ASCII characters? */
- int unicode;
- /** The preferred line break. */
- yaml_break_t line_break;
-
- /** The stack of states. */
- struct {
- /** The beginning of the stack. */
- yaml_emitter_state_t *start;
- /** The end of the stack. */
- yaml_emitter_state_t *end;
- /** The top of the stack. */
- yaml_emitter_state_t *top;
- } states;
-
- /** The current emitter state. */
- yaml_emitter_state_t state;
-
- /** The event queue. */
- struct {
- /** The beginning of the event queue. */
- yaml_event_t *start;
- /** The end of the event queue. */
- yaml_event_t *end;
- /** The head of the event queue. */
- yaml_event_t *head;
- /** The tail of the event queue. */
- yaml_event_t *tail;
- } events;
-
- /** The stack of indentation levels. */
- struct {
- /** The beginning of the stack. */
- int *start;
- /** The end of the stack. */
- int *end;
- /** The top of the stack. */
- int *top;
- } indents;
-
- /** The list of tag directives. */
- struct {
- /** The beginning of the list. */
- yaml_tag_directive_t *start;
- /** The end of the list. */
- yaml_tag_directive_t *end;
- /** The top of the list. */
- yaml_tag_directive_t *top;
- } tag_directives;
-
- /** The current indentation level. */
- int indent;
-
- /** The current flow level. */
- int flow_level;
-
- /** Is it the document root context? */
- int root_context;
- /** Is it a sequence context? */
- int sequence_context;
- /** Is it a mapping context? */
- int mapping_context;
- /** Is it a simple mapping key context? */
- int simple_key_context;
-
- /** The current line. */
- int line;
- /** The current column. */
- int column;
- /** If the last character was a whitespace? */
- int whitespace;
- /** If the last character was an indentation character (' ', '-', '?', ':')? */
- int indention;
- /** If an explicit document end is required? */
- int open_ended;
-
- /** Anchor analysis. */
- struct {
- /** The anchor value. */
- yaml_char_t *anchor;
- /** The anchor length. */
- size_t anchor_length;
- /** Is it an alias? */
- int alias;
- } anchor_data;
-
- /** Tag analysis. */
- struct {
- /** The tag handle. */
- yaml_char_t *handle;
- /** The tag handle length. */
- size_t handle_length;
- /** The tag suffix. */
- yaml_char_t *suffix;
- /** The tag suffix length. */
- size_t suffix_length;
- } tag_data;
-
- /** Scalar analysis. */
- struct {
- /** The scalar value. */
- yaml_char_t *value;
- /** The scalar length. */
- size_t length;
- /** Does the scalar contain line breaks? */
- int multiline;
- /** 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;
- /** Can the scalar be expressed in the single quoted style? */
- int single_quoted_allowed;
- /** Can the scalar be expressed in the literal or folded styles? */
- int block_allowed;
- /** The output style. */
- yaml_scalar_style_t style;
- } scalar_data;
-
- /**
- * @}
- */
-
- /**
- * @name Dumper stuff
- * @{
- */
-
- /** If the stream was already opened? */
- int opened;
- /** If the stream was already closed? */
- int closed;
-
- /** The information associated with the document nodes. */
- yaml_anchors_t *anchors;
-
- /** The last assigned anchor id. */
- int last_anchor_id;
-
- /** The currently emitted document. */
- yaml_document_t *document;
-
- /**
- * @}
- */
-
-} yaml_emitter_t;
-
-/**
- * Initialize an emitter.
- *
- * This function creates a new emitter object. An application is responsible
- * for destroying the object using the yaml_emitter_delete() function.
- *
- * @param[out] emitter An empty parser object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_initialize(yaml_emitter_t *emitter);
-
-/**
- * Destroy an emitter.
- *
- * @param[in,out] emitter An emitter object.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_delete(yaml_emitter_t *emitter);
-
-/**
- * Set a string output.
- *
- * The emitter will write the output characters to the @a output buffer of the
- * size @a size. The emitter will set @a size_written to the number of written
- * bytes. If the buffer is smaller than required, the emitter produces the
- * YAML_WRITE_ERROR error.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] output An output buffer.
- * @param[in] size The buffer size.
- * @param[in] size_written The pointer to save the number of written
- * bytes.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_output_string(yaml_emitter_t *emitter,
- unsigned char *output, size_t size, size_t *size_written);
-
-/**
- * Set a file output.
- *
- * @a file should be a file object open for writing. The application is
- * responsible for closing the @a file.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] file An open file.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file);
-
-/**
- * Set a generic output handler.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] handler A write handler.
- * @param[in] data Any application data for passing to the write
- * handler.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_output(yaml_emitter_t *emitter,
- yaml_write_handler_t *handler, void *data);
-
-/**
- * Set the output encoding.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] encoding The output encoding.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding);
-
-/**
- * Set if the output should be in the "canonical" format as in the YAML
- * specification.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] canonical If the output is canonical.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical);
-
-/**
- * Set the indentation increment.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] indent The indentation increment (1 < . < 10).
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent);
-
-/**
- * Set the preferred line width. @c -1 means unlimited.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] width The preferred line width.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_width(yaml_emitter_t *emitter, int width);
-
-/**
- * Set if unescaped non-ASCII characters are allowed.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] unicode If unescaped Unicode characters are allowed.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode);
-
-/**
- * Set the preferred line break.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in] line_break The preferred line break.
- */
-
-YAML_DECLARE(void)
-yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break);
-
-/**
- * Emit an event.
- *
- * The event object may be generated using the yaml_parser_parse() function.
- * The emitter takes the responsibility for the event object and destroys its
- * content after it is emitted. The event object is destroyed even if the
- * function fails.
- *
- * @param[in,out] emitter An emitter object.
- * @param[in,out] event An event object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
-
-/**
- * Start a YAML stream.
- *
- * This function should be used before yaml_emitter_dump() is called.
- *
- * @param[in,out] emitter An emitter object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_open(yaml_emitter_t *emitter);
-
-/**
- * Finish a YAML stream.
- *
- * This function should be used after yaml_emitter_dump() is called.
- *
- * @param[in,out] emitter An emitter object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_close(yaml_emitter_t *emitter);
-
-/**
- * Emit a YAML document.
- *
- * 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 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.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
-
-/**
- * Flush the accumulated characters to the output.
- *
- * @param[in,out] emitter An emitter object.
- *
- * @returns @c 1 if the function succeeded, @c 0 on error.
- */
-
-YAML_DECLARE(int)
-yaml_emitter_flush(yaml_emitter_t *emitter);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* #ifndef YAML_H */
-
diff --git a/ext/psych/yaml/yaml_private.h b/ext/psych/yaml/yaml_private.h
deleted file mode 100644
index 266a6bd3a7..0000000000
--- a/ext/psych/yaml/yaml_private.h
+++ /dev/null
@@ -1,688 +0,0 @@
-#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <yaml.h>
-
-#include <assert.h>
-#include <limits.h>
-#include <stddef.h>
-
-/*
- * Memory management.
- */
-
-YAML_DECLARE(void *)
-yaml_malloc(size_t size);
-
-YAML_DECLARE(void *)
-yaml_realloc(void *ptr, size_t size);
-
-YAML_DECLARE(void)
-yaml_free(void *ptr);
-
-YAML_DECLARE(yaml_char_t *)
-yaml_strdup(const yaml_char_t *);
-
-/*
- * Reader: Ensure that the buffer contains at least `length` characters.
- */
-
-YAML_DECLARE(int)
-yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
-
-/*
- * Scanner: Ensure that the token stack contains at least one token ready.
- */
-
-YAML_DECLARE(int)
-yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
-
-/*
- * The size of the input raw buffer.
- */
-
-#define INPUT_RAW_BUFFER_SIZE 16384
-
-/*
- * The size of the input buffer.
- *
- * It should be possible to decode the whole raw buffer.
- */
-
-#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3)
-
-/*
- * The size of the output buffer.
- */
-
-#define OUTPUT_BUFFER_SIZE 16384
-
-/*
- * The size of the output raw buffer.
- *
- * It should be possible to encode the whole output buffer.
- */
-
-#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
-
-/*
- * The maximum size of a YAML input file.
- * This used to be PTRDIFF_MAX, but that's not entirely portable
- * because stdint.h isn't available on all platforms.
- * It is not entirely clear why this isn't the maximum value
- * that can fit into the parser->offset field.
- */
-
-#define MAX_FILE_SIZE (~(size_t)0 / 2)
-
-
-/*
- * The size of other stacks and queues.
- */
-
-#define INITIAL_STACK_SIZE 16
-#define INITIAL_QUEUE_SIZE 16
-#define INITIAL_STRING_SIZE 16
-
-/*
- * Buffer management.
- */
-
-#define BUFFER_INIT(context,buffer,size) \
- (((buffer).start = (yaml_char_t *)yaml_malloc(size)) ? \
- ((buffer).last = (buffer).pointer = (buffer).start, \
- (buffer).end = (buffer).start+(size), \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define BUFFER_DEL(context,buffer) \
- (yaml_free((buffer).start), \
- (buffer).start = (buffer).pointer = (buffer).end = 0)
-
-/*
- * String management.
- */
-
-typedef struct {
- yaml_char_t *start;
- yaml_char_t *end;
- yaml_char_t *pointer;
-} yaml_string_t;
-
-YAML_DECLARE(int)
-yaml_string_extend(yaml_char_t **start,
- yaml_char_t **pointer, yaml_char_t **end);
-
-YAML_DECLARE(int)
-yaml_string_join(
- yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
- yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end);
-
-#define NULL_STRING { NULL, NULL, NULL }
-
-#define STRING(string,length) { (string), (string)+(length), (string) }
-
-#define STRING_ASSIGN(value,string,length) \
- ((value).start = (string), \
- (value).end = (string)+(length), \
- (value).pointer = (string))
-
-#define STRING_INIT(context,string,size) \
- (((string).start = YAML_MALLOC(size)) ? \
- ((string).pointer = (string).start, \
- (string).end = (string).start+(size), \
- memset((string).start, 0, (size)), \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define STRING_DEL(context,string) \
- (yaml_free((string).start), \
- (string).start = (string).pointer = (string).end = 0)
-
-#define STRING_EXTEND(context,string) \
- ((((string).pointer+5 < (string).end) \
- || yaml_string_extend(&(string).start, \
- &(string).pointer, &(string).end)) ? \
- 1 : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define CLEAR(context,string) \
- ((string).pointer = (string).start, \
- memset((string).start, 0, (string).end-(string).start))
-
-#define JOIN(context,string_a,string_b) \
- ((yaml_string_join(&(string_a).start, &(string_a).pointer, \
- &(string_a).end, &(string_b).start, \
- &(string_b).pointer, &(string_b).end)) ? \
- ((string_b).pointer = (string_b).start, \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-/*
- * String check operations.
- */
-
-/*
- * Check the octet at the specified position.
- */
-
-#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))
-
-/*
- * Check if the character at the specified position is an alphabetical
- * character, a digit, '_', or '-'.
- */
-
-#define IS_ALPHA_AT(string,offset) \
- (((string).pointer[offset] >= (yaml_char_t) '0' && \
- (string).pointer[offset] <= (yaml_char_t) '9') || \
- ((string).pointer[offset] >= (yaml_char_t) 'A' && \
- (string).pointer[offset] <= (yaml_char_t) 'Z') || \
- ((string).pointer[offset] >= (yaml_char_t) 'a' && \
- (string).pointer[offset] <= (yaml_char_t) 'z') || \
- (string).pointer[offset] == '_' || \
- (string).pointer[offset] == '-')
-
-#define IS_ALPHA(string) IS_ALPHA_AT((string),0)
-
-/*
- * Check if the character at the specified position is a digit.
- */
-
-#define IS_DIGIT_AT(string,offset) \
- (((string).pointer[offset] >= (yaml_char_t) '0' && \
- (string).pointer[offset] <= (yaml_char_t) '9'))
-
-#define IS_DIGIT(string) IS_DIGIT_AT((string),0)
-
-/*
- * Get the value of a digit.
- */
-
-#define AS_DIGIT_AT(string,offset) \
- ((string).pointer[offset] - (yaml_char_t) '0')
-
-#define AS_DIGIT(string) AS_DIGIT_AT((string),0)
-
-/*
- * Check if the character at the specified position is a hex-digit.
- */
-
-#define IS_HEX_AT(string,offset) \
- (((string).pointer[offset] >= (yaml_char_t) '0' && \
- (string).pointer[offset] <= (yaml_char_t) '9') || \
- ((string).pointer[offset] >= (yaml_char_t) 'A' && \
- (string).pointer[offset] <= (yaml_char_t) 'F') || \
- ((string).pointer[offset] >= (yaml_char_t) 'a' && \
- (string).pointer[offset] <= (yaml_char_t) 'f'))
-
-#define IS_HEX(string) IS_HEX_AT((string),0)
-
-/*
- * Get the value of a hex-digit.
- */
-
-#define AS_HEX_AT(string,offset) \
- (((string).pointer[offset] >= (yaml_char_t) 'A' && \
- (string).pointer[offset] <= (yaml_char_t) 'F') ? \
- ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
- ((string).pointer[offset] >= (yaml_char_t) 'a' && \
- (string).pointer[offset] <= (yaml_char_t) 'f') ? \
- ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
- ((string).pointer[offset] - (yaml_char_t) '0'))
-
-#define AS_HEX(string) AS_HEX_AT((string),0)
-
-/*
- * Check if the character is ASCII.
- */
-
-#define IS_ASCII_AT(string,offset) \
- ((string).pointer[offset] <= (yaml_char_t) '\x7F')
-
-#define IS_ASCII(string) IS_ASCII_AT((string),0)
-
-/*
- * Check if the character can be printed unescaped.
- */
-
-#define IS_PRINTABLE_AT(string,offset) \
- (((string).pointer[offset] == 0x0A) /* . == #x0A */ \
- || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \
- && (string).pointer[offset] <= 0x7E) \
- || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \
- && (string).pointer[offset+1] >= 0xA0) \
- || ((string).pointer[offset] > 0xC2 \
- && (string).pointer[offset] < 0xED) \
- || ((string).pointer[offset] == 0xED \
- && (string).pointer[offset+1] < 0xA0) \
- || ((string).pointer[offset] == 0xEE) \
- || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \
- && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \
- && (string).pointer[offset+2] == 0xBF) \
- && !((string).pointer[offset+1] == 0xBF \
- && ((string).pointer[offset+2] == 0xBE \
- || (string).pointer[offset+2] == 0xBF))))
-
-#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0)
-
-/*
- * Check if the character at the specified position is NUL.
- */
-
-#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset))
-
-#define IS_Z(string) IS_Z_AT((string),0)
-
-/*
- * Check if the character at the specified position is BOM.
- */
-
-#define IS_BOM_AT(string,offset) \
- (CHECK_AT((string),'\xEF',(offset)) \
- && CHECK_AT((string),'\xBB',(offset)+1) \
- && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */
-
-#define IS_BOM(string) IS_BOM_AT(string,0)
-
-/*
- * Check if the character at the specified position is space.
- */
-
-#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset))
-
-#define IS_SPACE(string) IS_SPACE_AT((string),0)
-
-/*
- * Check if the character at the specified position is tab.
- */
-
-#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset))
-
-#define IS_TAB(string) IS_TAB_AT((string),0)
-
-/*
- * Check if the character at the specified position is blank (space or tab).
- */
-
-#define IS_BLANK_AT(string,offset) \
- (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset)))
-
-#define IS_BLANK(string) IS_BLANK_AT((string),0)
-
-/*
- * Check if the character at the specified position is a line break.
- */
-
-#define IS_BREAK_AT(string,offset) \
- (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \
- || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \
- || (CHECK_AT((string),'\xC2',(offset)) \
- && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \
- || (CHECK_AT((string),'\xE2',(offset)) \
- && CHECK_AT((string),'\x80',(offset)+1) \
- && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \
- || (CHECK_AT((string),'\xE2',(offset)) \
- && CHECK_AT((string),'\x80',(offset)+1) \
- && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */
-
-#define IS_BREAK(string) IS_BREAK_AT((string),0)
-
-#define IS_CRLF_AT(string,offset) \
- (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1))
-
-#define IS_CRLF(string) IS_CRLF_AT((string),0)
-
-/*
- * Check if the character is a line break or NUL.
- */
-
-#define IS_BREAKZ_AT(string,offset) \
- (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset)))
-
-#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0)
-
-/*
- * Check if the character is a line break, space, or NUL.
- */
-
-#define IS_SPACEZ_AT(string,offset) \
- (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
-
-#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0)
-
-/*
- * Check if the character is a line break, space, tab, or NUL.
- */
-
-#define IS_BLANKZ_AT(string,offset) \
- (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
-
-#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0)
-
-/*
- * Determine the width of the character.
- */
-
-#define WIDTH_AT(string,offset) \
- (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \
- ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \
- ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \
- ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0)
-
-#define WIDTH(string) WIDTH_AT((string),0)
-
-/*
- * Move the string pointer to the next character.
- */
-
-#define MOVE(string) ((string).pointer += WIDTH((string)))
-
-/*
- * Copy a character and move the pointers of both strings.
- */
-
-#define COPY(string_a,string_b) \
- ((*(string_b).pointer & 0x80) == 0x00 ? \
- (*((string_a).pointer++) = *((string_b).pointer++)) : \
- (*(string_b).pointer & 0xE0) == 0xC0 ? \
- (*((string_a).pointer++) = *((string_b).pointer++), \
- *((string_a).pointer++) = *((string_b).pointer++)) : \
- (*(string_b).pointer & 0xF0) == 0xE0 ? \
- (*((string_a).pointer++) = *((string_b).pointer++), \
- *((string_a).pointer++) = *((string_b).pointer++), \
- *((string_a).pointer++) = *((string_b).pointer++)) : \
- (*(string_b).pointer & 0xF8) == 0xF0 ? \
- (*((string_a).pointer++) = *((string_b).pointer++), \
- *((string_a).pointer++) = *((string_b).pointer++), \
- *((string_a).pointer++) = *((string_b).pointer++), \
- *((string_a).pointer++) = *((string_b).pointer++)) : 0)
-
-/*
- * Stack and queue management.
- */
-
-YAML_DECLARE(int)
-yaml_stack_extend(void **start, void **top, void **end);
-
-YAML_DECLARE(int)
-yaml_queue_extend(void **start, void **head, void **tail, void **end);
-
-#define STACK_INIT(context,stack,type) \
- (((stack).start = (type)yaml_malloc(INITIAL_STACK_SIZE*sizeof(*(stack).start))) ? \
- ((stack).top = (stack).start, \
- (stack).end = (stack).start+INITIAL_STACK_SIZE, \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define STACK_DEL(context,stack) \
- (yaml_free((stack).start), \
- (stack).start = (stack).top = (stack).end = 0)
-
-#define STACK_EMPTY(context,stack) \
- ((stack).start == (stack).top)
-
-#define STACK_LIMIT(context,stack,size) \
- ((stack).top - (stack).start < (size) ? \
- 1 : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define PUSH(context,stack,value) \
- (((stack).top != (stack).end \
- || yaml_stack_extend((void **)&(stack).start, \
- (void **)&(stack).top, (void **)&(stack).end)) ? \
- (*((stack).top++) = value, \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define POP(context,stack) \
- (*(--(stack).top))
-
-#define QUEUE_INIT(context,queue,size,type) \
- (((queue).start = (type)yaml_malloc((size)*sizeof(*(queue).start))) ? \
- ((queue).head = (queue).tail = (queue).start, \
- (queue).end = (queue).start+(size), \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define QUEUE_DEL(context,queue) \
- (yaml_free((queue).start), \
- (queue).start = (queue).head = (queue).tail = (queue).end = 0)
-
-#define QUEUE_EMPTY(context,queue) \
- ((queue).head == (queue).tail)
-
-#define ENQUEUE(context,queue,value) \
- (((queue).tail != (queue).end \
- || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
- (void **)&(queue).tail, (void **)&(queue).end)) ? \
- (*((queue).tail++) = value, \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-#define DEQUEUE(context,queue) \
- (*((queue).head++))
-
-#define QUEUE_INSERT(context,queue,index,value) \
- (((queue).tail != (queue).end \
- || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
- (void **)&(queue).tail, (void **)&(queue).end)) ? \
- (memmove((queue).head+(index)+1,(queue).head+(index), \
- ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \
- *((queue).head+(index)) = value, \
- (queue).tail++, \
- 1) : \
- ((context)->error = YAML_MEMORY_ERROR, \
- 0))
-
-/*
- * Token initializers.
- */
-
-#define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \
- (memset(&(token), 0, sizeof(yaml_token_t)), \
- (token).type = (token_type), \
- (token).start_mark = (token_start_mark), \
- (token).end_mark = (token_end_mark))
-
-#define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_STREAM_START_TOKEN,(start_mark),(end_mark)), \
- (token).data.stream_start.encoding = (token_encoding))
-
-#define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_STREAM_END_TOKEN,(start_mark),(end_mark)))
-
-#define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_ALIAS_TOKEN,(start_mark),(end_mark)), \
- (token).data.alias.value = (token_value))
-
-#define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_ANCHOR_TOKEN,(start_mark),(end_mark)), \
- (token).data.anchor.value = (token_value))
-
-#define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_TAG_TOKEN,(start_mark),(end_mark)), \
- (token).data.tag.handle = (token_handle), \
- (token).data.tag.suffix = (token_suffix))
-
-#define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_SCALAR_TOKEN,(start_mark),(end_mark)), \
- (token).data.scalar.value = (token_value), \
- (token).data.scalar.length = (token_length), \
- (token).data.scalar.style = (token_style))
-
-#define VERSION_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_VERSION_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
- (token).data.version_directive.major = (token_major), \
- (token).data.version_directive.minor = (token_minor))
-
-#define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \
- (TOKEN_INIT((token),YAML_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
- (token).data.tag_directive.handle = (token_handle), \
- (token).data.tag_directive.prefix = (token_prefix))
-
-/*
- * Event initializers.
- */
-
-#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \
- (memset(&(event), 0, sizeof(yaml_event_t)), \
- (event).type = (event_type), \
- (event).start_mark = (event_start_mark), \
- (event).end_mark = (event_end_mark))
-
-#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)), \
- (event).data.stream_start.encoding = (event_encoding))
-
-#define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark)))
-
-#define DOCUMENT_START_EVENT_INIT(event,event_version_directive, \
- event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \
- (event).data.document_start.version_directive = (event_version_directive), \
- (event).data.document_start.tag_directives.start = (event_tag_directives_start), \
- (event).data.document_start.tag_directives.end = (event_tag_directives_end), \
- (event).data.document_start.implicit = (event_implicit))
-
-#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \
- (event).data.document_end.implicit = (event_implicit))
-
-#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \
- (event).data.alias.anchor = (event_anchor))
-
-#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \
- event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \
- (event).data.scalar.anchor = (event_anchor), \
- (event).data.scalar.tag = (event_tag), \
- (event).data.scalar.value = (event_value), \
- (event).data.scalar.length = (event_length), \
- (event).data.scalar.plain_implicit = (event_plain_implicit), \
- (event).data.scalar.quoted_implicit = (event_quoted_implicit), \
- (event).data.scalar.style = (event_style))
-
-#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \
- event_implicit,event_style,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \
- (event).data.sequence_start.anchor = (event_anchor), \
- (event).data.sequence_start.tag = (event_tag), \
- (event).data.sequence_start.implicit = (event_implicit), \
- (event).data.sequence_start.style = (event_style))
-
-#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
-
-#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \
- event_implicit,event_style,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \
- (event).data.mapping_start.anchor = (event_anchor), \
- (event).data.mapping_start.tag = (event_tag), \
- (event).data.mapping_start.implicit = (event_implicit), \
- (event).data.mapping_start.style = (event_style))
-
-#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \
- (EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark)))
-
-/*
- * Document initializer.
- */
-
-#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
- document_version_directive,document_tag_directives_start, \
- document_tag_directives_end,document_start_implicit, \
- document_end_implicit,document_start_mark,document_end_mark) \
- (memset(&(document), 0, sizeof(yaml_document_t)), \
- (document).nodes.start = (document_nodes_start), \
- (document).nodes.end = (document_nodes_end), \
- (document).nodes.top = (document_nodes_start), \
- (document).version_directive = (document_version_directive), \
- (document).tag_directives.start = (document_tag_directives_start), \
- (document).tag_directives.end = (document_tag_directives_end), \
- (document).start_implicit = (document_start_implicit), \
- (document).end_implicit = (document_end_implicit), \
- (document).start_mark = (document_start_mark), \
- (document).end_mark = (document_end_mark))
-
-/*
- * Node initializers.
- */
-
-#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
- (memset(&(node), 0, sizeof(yaml_node_t)), \
- (node).type = (node_type), \
- (node).tag = (node_tag), \
- (node).start_mark = (node_start_mark), \
- (node).end_mark = (node_end_mark))
-
-#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
- node_style,start_mark,end_mark) \
- (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
- (node).data.scalar.value = (node_value), \
- (node).data.scalar.length = (node_length), \
- (node).data.scalar.style = (node_style))
-
-#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
- node_style,start_mark,end_mark) \
- (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
- (node).data.sequence.items.start = (node_items_start), \
- (node).data.sequence.items.end = (node_items_end), \
- (node).data.sequence.items.top = (node_items_start), \
- (node).data.sequence.style = (node_style))
-
-#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
- node_style,start_mark,end_mark) \
- (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
- (node).data.mapping.pairs.start = (node_pairs_start), \
- (node).data.mapping.pairs.end = (node_pairs_end), \
- (node).data.mapping.pairs.top = (node_pairs_start), \
- (node).data.mapping.style = (node_style))
-
-/* Strict C compiler warning helpers */
-
-#if defined(__clang__) || defined(__GNUC__)
-# define HASATTRIBUTE_UNUSED
-#endif
-#ifdef HASATTRIBUTE_UNUSED
-# define __attribute__unused__ __attribute__((__unused__))
-#else
-# define __attribute__unused__
-#endif
-
-/* Shim arguments are arguments that must be included in your function,
- * but serve no purpose inside. Silence compiler warnings. */
-#define SHIM(a) /*@unused@*/ a __attribute__unused__
-
-/* UNUSED_PARAM() marks a shim argument in the body to silence compiler warnings */
-#ifdef __clang__
-# define UNUSED_PARAM(a) (void)(a);
-#else
-# define UNUSED_PARAM(a) /*@-noeffect*/if (0) (void)(a)/*@=noeffect*/;
-#endif
-
-#define YAML_MALLOC_STATIC(type) (type*)yaml_malloc(sizeof(type))
-#define YAML_MALLOC(size) (yaml_char_t *)yaml_malloc(size)
diff --git a/ext/pty/depend b/ext/pty/depend
index 90ac8df24c..f251caae3f 100644
--- a/ext/pty/depend
+++ b/ext/pty/depend
@@ -1,7 +1,21 @@
# AUTOGENERATED DEPENDENCIES START
pty.o: $(RUBY_EXTCONF_H)
pty.o: $(arch_hdrdir)/ruby/config.h
-pty.o: $(hdrdir)/ruby.h
+pty.o: $(hdrdir)/ruby/assert.h
+pty.o: $(hdrdir)/ruby/backward.h
+pty.o: $(hdrdir)/ruby/backward/2/assume.h
+pty.o: $(hdrdir)/ruby/backward/2/attributes.h
+pty.o: $(hdrdir)/ruby/backward/2/bool.h
+pty.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+pty.o: $(hdrdir)/ruby/backward/2/inttypes.h
+pty.o: $(hdrdir)/ruby/backward/2/limits.h
+pty.o: $(hdrdir)/ruby/backward/2/long_long.h
+pty.o: $(hdrdir)/ruby/backward/2/stdalign.h
+pty.o: $(hdrdir)/ruby/backward/2/stdarg.h
+pty.o: $(hdrdir)/ruby/defines.h
+pty.o: $(hdrdir)/ruby/encoding.h
+pty.o: $(hdrdir)/ruby/intern.h
+pty.o: $(hdrdir)/ruby/internal/abi.h
pty.o: $(hdrdir)/ruby/internal/anyargs.h
pty.o: $(hdrdir)/ruby/internal/arithmetic.h
pty.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ pty.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
pty.o: $(hdrdir)/ruby/internal/ctype.h
pty.o: $(hdrdir)/ruby/internal/dllexport.h
pty.o: $(hdrdir)/ruby/internal/dosish.h
+pty.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+pty.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+pty.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+pty.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+pty.o: $(hdrdir)/ruby/internal/encoding/re.h
+pty.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+pty.o: $(hdrdir)/ruby/internal/encoding/string.h
+pty.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+pty.o: $(hdrdir)/ruby/internal/encoding/transcode.h
pty.o: $(hdrdir)/ruby/internal/error.h
pty.o: $(hdrdir)/ruby/internal/eval.h
pty.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
pty.o: $(hdrdir)/ruby/io.h
pty.o: $(hdrdir)/ruby/missing.h
pty.o: $(hdrdir)/ruby/onigmo.h
@@ -172,5 +181,6 @@ 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: $(top_srcdir)/shape.h
pty.o: pty.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
index 038bdf4d2c..ba0c4286fd 100644
--- a/ext/pty/extconf.rb
+++ b/ext/pty/extconf.rb
@@ -7,10 +7,12 @@ if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM
have_header("sys/stropts.h")
have_func("setresuid")
have_header("libutil.h")
- have_header("util.h") # OpenBSD openpty
have_header("pty.h")
have_header("pwd.h")
- util = have_library("util", "openpty")
+ if /openbsd/ =~ RUBY_PLATFORM
+ have_header("util.h") # OpenBSD openpty
+ util = have_library("util", "openpty")
+ end
if have_func("posix_openpt") or
(util or have_func("openpty")) or
have_func("_getpty") or
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
index 5dbfa09ae9..22cbf54115 100644
--- a/ext/pty/lib/expect.rb
+++ b/ext/pty/lib/expect.rb
@@ -1,19 +1,19 @@
# frozen_string_literal: true
$expect_verbose = false
-# Expect library adds the IO instance method #expect, which does similar act to
-# tcl's expect extension.
-#
-# In order to use this method, you must require expect:
-#
-# require 'expect'
-#
-# Please see #expect for usage.
class IO
# call-seq:
# IO#expect(pattern,timeout=9999999) -> Array
# IO#expect(pattern,timeout=9999999) { |result| ... } -> nil
#
+ # The +expect+ library adds instance method IO#expect,
+ # which is similar to the
+ # {TCL expect extension}[https://www.tcl.tk/man/expect5.31/expect.1.html].
+ #
+ # To use this method, you must require +expect+:
+ #
+ # require 'expect'
+ #
# Reads from the IO until the given +pattern+ matches or the +timeout+ is over.
#
# It returns an array with the read buffer, followed by the matches.
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 72074f7421..acec33f9bf 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -107,8 +107,8 @@ chfunc(void *data, char *errbuf, size_t errbuf_len)
int slave = carg->slave;
#define ERROR_EXIT(str) do { \
- strlcpy(errbuf, (str), errbuf_len); \
- return -1; \
+ strlcpy(errbuf, (str), errbuf_len); \
+ return -1; \
} while (0)
/*
@@ -166,32 +166,32 @@ chfunc(void *data, char *errbuf, size_t errbuf_len)
static void
establishShell(int argc, VALUE *argv, struct pty_info *info,
- char SlaveName[DEVICELEN])
+ char SlaveName[DEVICELEN])
{
int master, slave, status = 0;
rb_pid_t pid;
- char *p, *getenv();
+ char *p;
VALUE v;
struct child_info carg;
char errbuf[32];
if (argc == 0) {
- const char *shellname = "/bin/sh";
+ const char *shellname = "/bin/sh";
- if ((p = getenv("SHELL")) != NULL) {
- shellname = p;
- }
- else {
+ if ((p = getenv("SHELL")) != NULL) {
+ shellname = p;
+ }
+ else {
#if defined HAVE_PWD_H
- const char *username = getenv("USER");
- struct passwd *pwent = getpwnam(username ? username : getlogin());
- if (pwent && pwent->pw_shell)
- shellname = pwent->pw_shell;
+ const char *username = getenv("USER");
+ struct passwd *pwent = getpwnam(username ? username : getlogin());
+ if (pwent && pwent->pw_shell)
+ shellname = pwent->pw_shell;
#endif
- }
- v = rb_str_new2(shellname);
- argc = 1;
- argv = &v;
+ }
+ v = rb_str_new2(shellname);
+ argc = 1;
+ argv = &v;
}
carg.execarg_obj = rb_execarg_new(argc, argv, 1, 0);
@@ -207,13 +207,13 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
pid = rb_fork_async_signal_safe(&status, chfunc, &carg, Qnil, errbuf, sizeof(errbuf));
if (pid < 0) {
- int e = errno;
- close(master);
- close(slave);
+ int e = errno;
+ close(master);
+ close(slave);
rb_execarg_parent_end(carg.execarg_obj);
- errno = e;
- if (status) rb_jump_tag(status);
- rb_sys_fail(errbuf[0] ? errbuf : "fork failed");
+ errno = e;
+ if (status) rb_jump_tag(status);
+ rb_sys_fail(errbuf[0] ? errbuf : "fork failed");
}
close(slave);
@@ -268,14 +268,14 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
rb_fd_fix_cloexec(masterfd);
#else
{
- int flags = O_RDWR|O_NOCTTY;
+ int flags = O_RDWR|O_NOCTTY;
# if defined(O_CLOEXEC)
- /* glibc posix_openpt() in GNU/Linux calls open("/dev/ptmx", flags) internally.
- * So version dependency on GNU/Linux is the same as O_CLOEXEC with open().
- * O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
- flags |= O_CLOEXEC;
+ /* glibc posix_openpt() in GNU/Linux calls open("/dev/ptmx", flags) internally.
+ * So version dependency on GNU/Linux is the same as O_CLOEXEC with open().
+ * O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
+ flags |= O_CLOEXEC;
# endif
- if ((masterfd = posix_openpt(flags)) == -1) goto error;
+ if ((masterfd = posix_openpt(flags)) == -1) goto error;
}
rb_fd_fix_cloexec(masterfd);
if (rb_grantpt(masterfd) == -1) goto error;
@@ -310,15 +310,15 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
* or the same interface function.
*/
if (openpty(master, slave, SlaveName,
- (struct termios *)0, (struct winsize *)0) == -1) {
- if (!fail) return -1;
- rb_raise(rb_eRuntimeError, "openpty() failed");
+ (struct termios *)0, (struct winsize *)0) == -1) {
+ if (!fail) return -1;
+ rb_raise(rb_eRuntimeError, "openpty() failed");
}
rb_fd_fix_cloexec(*master);
rb_fd_fix_cloexec(*slave);
if (no_mesg(SlaveName, nomesg) == -1) {
- if (!fail) return -1;
- rb_raise(rb_eRuntimeError, "can't chmod slave pty");
+ if (!fail) return -1;
+ rb_raise(rb_eRuntimeError, "can't chmod slave pty");
}
return 0;
@@ -329,8 +329,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
mode_t mode = nomesg ? 0600 : 0622;
if (!(name = _getpty(master, O_RDWR, mode, 0))) {
- if (!fail) return -1;
- rb_raise(rb_eRuntimeError, "_getpty() failed");
+ if (!fail) return -1;
+ rb_raise(rb_eRuntimeError, "_getpty() failed");
}
rb_fd_fix_cloexec(*master);
@@ -386,49 +386,42 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg,
char MasterName[DEVICELEN];
#define HEX1(c) \
- c"0",c"1",c"2",c"3",c"4",c"5",c"6",c"7", \
- c"8",c"9",c"a",c"b",c"c",c"d",c"e",c"f"
+ c"0",c"1",c"2",c"3",c"4",c"5",c"6",c"7", \
+ c"8",c"9",c"a",c"b",c"c",c"d",c"e",c"f"
-#if defined(__hpux)
- static const char MasterDevice[] = "/dev/ptym/pty%s";
- static const char SlaveDevice[] = "/dev/pty/tty%s";
- static const char deviceNo[][3] = {
- HEX1("p"), HEX1("q"), HEX1("r"), HEX1("s"),
- HEX1("t"), HEX1("u"), HEX1("v"), HEX1("w"),
- };
-#elif defined(_IBMESA) /* AIX/ESA */
+#if defined(_IBMESA) /* AIX/ESA */
static const char MasterDevice[] = "/dev/ptyp%s";
static const char SlaveDevice[] = "/dev/ttyp%s";
static const char deviceNo[][3] = {
- HEX1("0"), HEX1("1"), HEX1("2"), HEX1("3"),
- HEX1("4"), HEX1("5"), HEX1("6"), HEX1("7"),
- HEX1("8"), HEX1("9"), HEX1("a"), HEX1("b"),
- HEX1("c"), HEX1("d"), HEX1("e"), HEX1("f"),
+ HEX1("0"), HEX1("1"), HEX1("2"), HEX1("3"),
+ HEX1("4"), HEX1("5"), HEX1("6"), HEX1("7"),
+ HEX1("8"), HEX1("9"), HEX1("a"), HEX1("b"),
+ HEX1("c"), HEX1("d"), HEX1("e"), HEX1("f"),
};
#else /* 4.2BSD */
static const char MasterDevice[] = "/dev/pty%s";
static const char SlaveDevice[] = "/dev/tty%s";
static const char deviceNo[][3] = {
- HEX1("p"), HEX1("q"), HEX1("r"), HEX1("s"),
+ HEX1("p"), HEX1("q"), HEX1("r"), HEX1("s"),
};
#endif
#undef HEX1
for (i = 0; i < numberof(deviceNo); i++) {
- const char *const devno = deviceNo[i];
- snprintf(MasterName, sizeof MasterName, MasterDevice, devno);
- if ((masterfd = rb_cloexec_open(MasterName,O_RDWR,0)) >= 0) {
+ const char *const devno = deviceNo[i];
+ snprintf(MasterName, sizeof MasterName, MasterDevice, devno);
+ if ((masterfd = rb_cloexec_open(MasterName,O_RDWR,0)) >= 0) {
rb_update_max_fd(masterfd);
- *master = masterfd;
- snprintf(SlaveName, DEVICELEN, SlaveDevice, devno);
- if ((slavefd = rb_cloexec_open(SlaveName,O_RDWR,0)) >= 0) {
+ *master = masterfd;
+ snprintf(SlaveName, DEVICELEN, SlaveDevice, devno);
+ if ((slavefd = rb_cloexec_open(SlaveName,O_RDWR,0)) >= 0) {
rb_update_max_fd(slavefd);
- *slave = slavefd;
- if (chown(SlaveName, getuid(), getgid()) != 0) goto error;
- if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0) goto error;
- return 0;
- }
- close(masterfd);
- }
+ *slave = slavefd;
+ if (chown(SlaveName, getuid(), getgid()) != 0) goto error;
+ if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0) goto error;
+ return 0;
+ }
+ close(masterfd);
+ }
}
error:
if (slavefd != -1) close(slavefd);
@@ -442,8 +435,8 @@ static void
getDevice(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg)
{
if (get_device_once(master, slave, SlaveName, nomesg, 0)) {
- rb_gc();
- get_device_once(master, slave, SlaveName, nomesg, 1);
+ rb_gc();
+ get_device_once(master, slave, SlaveName, nomesg, 1);
}
}
@@ -526,7 +519,7 @@ pty_open(VALUE klass)
assoc = rb_assoc_new(master_io, slave_file);
if (rb_block_given_p()) {
- return rb_ensure(rb_yield, assoc, pty_close_pty, assoc);
+ return rb_ensure(rb_yield, assoc, pty_close_pty, assoc);
}
return assoc;
}
@@ -538,7 +531,7 @@ pty_detach_process(VALUE v)
#ifdef WNOHANG
int st;
if (rb_waitpid(info->child_pid, &st, WNOHANG) <= 0)
- return Qnil;
+ return Qnil;
#endif
rb_detach_process(info->child_pid);
return Qnil;
@@ -546,10 +539,10 @@ pty_detach_process(VALUE v)
/*
* call-seq:
- * PTY.spawn(command_line) { |r, w, pid| ... }
- * PTY.spawn(command_line) => [r, w, pid]
- * PTY.spawn(command, arguments, ...) { |r, w, pid| ... }
- * PTY.spawn(command, arguments, ...) => [r, w, pid]
+ * PTY.spawn([env,] command_line) { |r, w, pid| ... }
+ * PTY.spawn([env,] command_line) => [r, w, pid]
+ * PTY.spawn([env,] command, arguments, ...) { |r, w, pid| ... }
+ * PTY.spawn([env,] command, arguments, ...) => [r, w, pid]
*
* Spawns the specified command on a newly allocated pty. You can also use the
* alias ::getpty.
@@ -557,6 +550,13 @@ pty_detach_process(VALUE v)
* The command's controlling tty is set to the slave device of the pty
* and its standard input/output/error is redirected to the slave device.
*
+ * +env+ is an optional hash that provides additional environment variables to the spawned pty.
+ *
+ * # sets FOO to "bar"
+ * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "bar\r\n"
+ * # unsets FOO
+ * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") { |r,w,pid| p r.read } #=> ""
+ *
* +command+ and +command_line+ are the full commands to run, given a String.
* Any additional +arguments+ will be passed to the command.
*
@@ -604,8 +604,8 @@ pty_getpty(int argc, VALUE *argv, VALUE self)
rb_ary_store(res,2,PIDT2NUM(info.child_pid));
if (rb_block_given_p()) {
- rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info);
- return Qnil;
+ rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info);
+ return Qnil;
}
return res;
}
@@ -625,13 +625,13 @@ raise_from_check(rb_pid_t pid, int status)
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
#endif /* WIFSTOPPED | IF_STOPPED */
if (WIFSTOPPED(status)) { /* suspend */
- state = "stopped";
+ state = "stopped";
}
else if (kill(pid, 0) == 0) {
- state = "changed";
+ state = "changed";
}
else {
- state = "exited";
+ state = "exited";
}
msg = rb_sprintf("pty - %s: %ld", state, (long)pid);
exc = rb_exc_new_str(eChildExited, msg);
@@ -664,12 +664,12 @@ pty_check(int argc, VALUE *argv, VALUE self)
int status;
const int flag =
#ifdef WNOHANG
- WNOHANG|
+ WNOHANG|
#endif
#ifdef WUNTRACED
- WUNTRACED|
+ WUNTRACED|
#endif
- 0;
+ 0;
rb_scan_args(argc, argv, "11", &pid, &exc);
cpid = rb_waitpid(NUM2PIDT(pid), &status, flag);
diff --git a/ext/racc/cparse/cparse.c b/ext/racc/cparse/cparse.c
index f71ed2bba9..f752eb7749 100644
--- a/ext/racc/cparse/cparse.c
+++ b/ext/racc/cparse/cparse.c
@@ -7,8 +7,6 @@
This library is free software.
You can distribute/modify this program under the same terms of ruby.
- $originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $
-
*/
#include <ruby.h>
@@ -24,7 +22,7 @@
Important Constants
----------------------------------------------------------------------- */
-#define RACC_VERSION "1.4.15"
+#define RACC_VERSION "1.6.2"
#define DEFAULT_TOKEN -1
#define ERROR_TOKEN 1
diff --git a/ext/racc/cparse/depend b/ext/racc/cparse/depend
index 556c47fbd5..9dc509dc7c 100644
--- a/ext/racc/cparse/depend
+++ b/ext/racc/cparse/depend
@@ -2,6 +2,19 @@
cparse.o: $(RUBY_EXTCONF_H)
cparse.o: $(arch_hdrdir)/ruby/config.h
cparse.o: $(hdrdir)/ruby.h
+cparse.o: $(hdrdir)/ruby/assert.h
+cparse.o: $(hdrdir)/ruby/backward.h
+cparse.o: $(hdrdir)/ruby/backward/2/assume.h
+cparse.o: $(hdrdir)/ruby/backward/2/attributes.h
+cparse.o: $(hdrdir)/ruby/backward/2/bool.h
+cparse.o: $(hdrdir)/ruby/backward/2/inttypes.h
+cparse.o: $(hdrdir)/ruby/backward/2/limits.h
+cparse.o: $(hdrdir)/ruby/backward/2/long_long.h
+cparse.o: $(hdrdir)/ruby/backward/2/stdalign.h
+cparse.o: $(hdrdir)/ruby/backward/2/stdarg.h
+cparse.o: $(hdrdir)/ruby/defines.h
+cparse.o: $(hdrdir)/ruby/intern.h
+cparse.o: $(hdrdir)/ruby/internal/abi.h
cparse.o: $(hdrdir)/ruby/internal/anyargs.h
cparse.o: $(hdrdir)/ruby/internal/arithmetic.h
cparse.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -141,19 +154,6 @@ 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
cparse.o: $(hdrdir)/ruby/ruby.h
cparse.o: $(hdrdir)/ruby/st.h
diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend
index b1774d6c62..5b65b83772 100644
--- a/ext/rbconfig/sizeof/depend
+++ b/ext/rbconfig/sizeof/depend
@@ -16,6 +16,19 @@ 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/assert.h
+limits.o: $(hdrdir)/ruby/backward.h
+limits.o: $(hdrdir)/ruby/backward/2/assume.h
+limits.o: $(hdrdir)/ruby/backward/2/attributes.h
+limits.o: $(hdrdir)/ruby/backward/2/bool.h
+limits.o: $(hdrdir)/ruby/backward/2/inttypes.h
+limits.o: $(hdrdir)/ruby/backward/2/limits.h
+limits.o: $(hdrdir)/ruby/backward/2/long_long.h
+limits.o: $(hdrdir)/ruby/backward/2/stdalign.h
+limits.o: $(hdrdir)/ruby/backward/2/stdarg.h
+limits.o: $(hdrdir)/ruby/defines.h
+limits.o: $(hdrdir)/ruby/intern.h
+limits.o: $(hdrdir)/ruby/internal/abi.h
limits.o: $(hdrdir)/ruby/internal/anyargs.h
limits.o: $(hdrdir)/ruby/internal/arithmetic.h
limits.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -155,19 +168,6 @@ 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
limits.o: $(hdrdir)/ruby/ruby.h
limits.o: $(hdrdir)/ruby/st.h
@@ -175,6 +175,19 @@ 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/assert.h
+sizes.o: $(hdrdir)/ruby/backward.h
+sizes.o: $(hdrdir)/ruby/backward/2/assume.h
+sizes.o: $(hdrdir)/ruby/backward/2/attributes.h
+sizes.o: $(hdrdir)/ruby/backward/2/bool.h
+sizes.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sizes.o: $(hdrdir)/ruby/backward/2/limits.h
+sizes.o: $(hdrdir)/ruby/backward/2/long_long.h
+sizes.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sizes.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sizes.o: $(hdrdir)/ruby/defines.h
+sizes.o: $(hdrdir)/ruby/intern.h
+sizes.o: $(hdrdir)/ruby/internal/abi.h
sizes.o: $(hdrdir)/ruby/internal/anyargs.h
sizes.o: $(hdrdir)/ruby/internal/arithmetic.h
sizes.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -314,19 +327,6 @@ 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
sizes.o: $(hdrdir)/ruby/ruby.h
sizes.o: $(hdrdir)/ruby/st.h
diff --git a/ext/readline/depend b/ext/readline/depend
index c95985d62b..c62309622a 100644
--- a/ext/readline/depend
+++ b/ext/readline/depend
@@ -6,7 +6,6 @@ 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
@@ -15,6 +14,7 @@ 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/abi.h
readline.o: $(hdrdir)/ruby/internal/anyargs.h
readline.o: $(hdrdir)/ruby/internal/arithmetic.h
readline.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -84,6 +84,15 @@ readline.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
readline.o: $(hdrdir)/ruby/internal/ctype.h
readline.o: $(hdrdir)/ruby/internal/dllexport.h
readline.o: $(hdrdir)/ruby/internal/dosish.h
+readline.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+readline.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+readline.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+readline.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+readline.o: $(hdrdir)/ruby/internal/encoding/re.h
+readline.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+readline.o: $(hdrdir)/ruby/internal/encoding/string.h
+readline.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+readline.o: $(hdrdir)/ruby/internal/encoding/transcode.h
readline.o: $(hdrdir)/ruby/internal/error.h
readline.o: $(hdrdir)/ruby/internal/eval.h
readline.o: $(hdrdir)/ruby/internal/event.h
diff --git a/ext/readline/readline-ext.gemspec b/ext/readline/readline-ext.gemspec
index 68a34ff9ce..1e16edbfe6 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.2"
+ spec.version = "0.1.5"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
@@ -19,8 +19,4 @@ Gem::Specification.new do |spec|
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 "rake-compiler"
end
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 8d635fce89..fc254ce315 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -376,8 +376,8 @@ prepare_readline(void)
{
static int initialized = 0;
if (!initialized) {
- rl_initialize();
- initialized = 1;
+ rl_initialize();
+ initialized = 1;
}
if (readline_instream) {
@@ -696,7 +696,6 @@ str_subpos(const char *ptr, const char *end, long beg, long *sublen, rb_encoding
VALUE str = rb_enc_str_new_static(ptr, end-ptr, enc);
OBJ_FREEZE(str);
ptr = rb_str_subpos(str, beg, sublen);
- rb_gc_force_recycle(str);
return ptr;
}
diff --git a/ext/ripper/depend b/ext/ripper/depend
index 29fea5b161..856283e177 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -17,12 +17,9 @@ ripper.o: ripper.c
all: check
static: check
-ripper.y: $(srcdir)/tools/preproc.rb $(srcdir)/tools/dsl.rb $(top_srcdir)/parse.y {$(VPATH)}id.h
+ripper.y: $(srcdir)/tools/preproc.rb $(srcdir)/tools/dsl.rb $(top_srcdir)/parse.y $(top_srcdir)/defs/id.def
$(ECHO) extracting $@ from $(top_srcdir)/parse.y
- $(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) $(top_srcdir)/tool/id2token.rb $(top_srcdir)/parse.y > ripper.tmp.y
$(Q) $(RUBY) $(srcdir)/tools/preproc.rb ripper.tmp.y --output=$@
$(Q) $(RM) ripper.tmp.y
@@ -66,6 +63,7 @@ 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/abi.h
ripper.o: $(hdrdir)/ruby/internal/anyargs.h
ripper.o: $(hdrdir)/ruby/internal/arithmetic.h
ripper.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -135,6 +133,15 @@ ripper.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ripper.o: $(hdrdir)/ruby/internal/ctype.h
ripper.o: $(hdrdir)/ruby/internal/dllexport.h
ripper.o: $(hdrdir)/ruby/internal/dosish.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/re.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/string.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ripper.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ripper.o: $(hdrdir)/ruby/internal/error.h
ripper.o: $(hdrdir)/ruby/internal/eval.h
ripper.o: $(hdrdir)/ruby/internal/event.h
@@ -224,6 +231,7 @@ 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/encoding.h
ripper.o: $(top_srcdir)/internal/error.h
ripper.o: $(top_srcdir)/internal/fixnum.h
ripper.o: $(top_srcdir)/internal/gc.h
@@ -239,13 +247,13 @@ 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)/shape.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 ac38663f2d..05687497ac 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -1,22 +1,3 @@
-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,
-# define tHEREDOC_END ((enum yytokentype)tHEREDOC_END)
- k__END__,
-# define k__END__ ((enum yytokentype)k__END__)
-};
-
typedef struct {
ID ripper_id_backref;
ID ripper_id_backtick;
diff --git a/ext/ripper/extconf.rb b/ext/ripper/extconf.rb
index 2dde565bd9..65cb5030d3 100644
--- a/ext/ripper/extconf.rb
+++ b/ext/ripper/extconf.rb
@@ -13,7 +13,8 @@ def main
end
end
$objs = %w(ripper.o)
- $cleanfiles.concat %w(ripper.y ripper.c ripper.E ripper.output y.output eventids1.c eventids2table.c .eventids2-check)
+ $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids2table.c)
+ $cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check)
$defs << '-DRIPPER'
$defs << '-DRIPPER_DEBUG' if $debug
$VPATH << '$(topdir)' << '$(top_srcdir)'
diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
index f6051c6341..a0f1cbeaa8 100644
--- a/ext/ripper/lib/ripper/lexer.rb
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -53,10 +53,27 @@ class Ripper
end
class Lexer < ::Ripper #:nodoc: internal use only
- State = Struct.new(:to_int, :to_s) do
+ class State
+ attr_reader :to_int, :to_s
+
+ def initialize(i)
+ @to_int = i
+ @to_s = Ripper.lex_state_name(i)
+ freeze
+ end
+
+ def [](index)
+ case index
+ when 0, :to_int
+ @to_int
+ when 1, :to_s
+ @event
+ else
+ nil
+ end
+ end
+
alias to_i to_int
- def initialize(i) super(i, Ripper.lex_state_name(i)).freeze end
- # def inspect; "#<#{self.class}: #{self}>" end
alias inspect to_s
def pretty_print(q) q.text(to_s) end
def ==(i) super or to_int == i end
@@ -67,15 +84,40 @@ class Ripper
def nobits?(i) to_int.nobits?(i) end
end
- Elem = Struct.new(:pos, :event, :tok, :state, :message) do
+ class Elem
+ attr_accessor :pos, :event, :tok, :state, :message
+
def initialize(pos, event, tok, state, message = nil)
- super(pos, event, tok, State.new(state), message)
+ @pos = pos
+ @event = event
+ @tok = tok
+ @state = State.new(state)
+ @message = message
+ end
+
+ def [](index)
+ case index
+ when 0, :pos
+ @pos
+ when 1, :event
+ @event
+ when 2, :tok
+ @tok
+ when 3, :state
+ @state
+ when 4, :message
+ @message
+ else
+ nil
+ end
end
def inspect
"#<#{self.class}: #{event}@#{pos[0]}:#{pos[1]}:#{state}: #{tok.inspect}#{": " if message}#{message}>"
end
+ alias to_s inspect
+
def pretty_print(q)
q.group(2, "#<#{self.class}:", ">") {
q.breakable
@@ -94,9 +136,11 @@ class Ripper
end
def to_a
- a = super
- a.pop unless a.last
- a
+ if @message
+ [@pos, @event, @tok, @state, @message]
+ else
+ [@pos, @event, @tok, @state]
+ end
end
end
@@ -152,17 +196,19 @@ class Ripper
def on_heredoc_dedent(v, w)
ignored_sp = []
heredoc = @buf.last
- heredoc.each_with_index do |e, i|
- if Elem === e and e.event == :on_tstring_content and e.pos[1].zero?
- tok = e.tok.dup if w > 0 and /\A\s/ =~ e.tok
- if (n = dedent_string(e.tok, w)) > 0
- if e.tok.empty?
- e.tok = tok[0, n]
- e.event = :on_ignored_sp
- next
+ if Array === heredoc
+ heredoc.each_with_index do |e, i|
+ if Elem === e and e.event == :on_tstring_content and e.pos[1].zero?
+ tok = e.tok.dup if w > 0 and /\A\s/ =~ e.tok
+ if (n = dedent_string(e.tok, w)) > 0
+ if e.tok.empty?
+ e.tok = tok[0, n]
+ e.event = :on_ignored_sp
+ next
+ end
+ ignored_sp << [i, Elem.new(e.pos.dup, :on_ignored_sp, tok[0, n], e.state)]
+ e.pos[1] += n
end
- ignored_sp << [i, Elem.new(e.pos.dup, :on_ignored_sp, tok[0, n], e.state)]
- e.pos[1] += n
end
end
end
@@ -182,7 +228,7 @@ class Ripper
def on_heredoc_end(tok)
@buf.push Elem.new([lineno(), column()], __callee__, tok, state())
- @buf = @stack.pop
+ @buf = @stack.pop unless @stack.empty?
end
def _push_token(tok)
@@ -196,7 +242,12 @@ class Ripper
end
def on_error2(mesg, elem)
- @errors.push Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ if elem
+ elem = Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ else
+ elem = Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
+ end
+ @errors.push elem
end
PARSER_EVENTS.grep(/_error\z/) do |e|
arity = PARSER_EVENT_TABLE.fetch(e)
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb
index b838a78db7..cd85a5da61 100644
--- a/ext/ripper/tools/preproc.rb
+++ b/ext/ripper/tools/preproc.rb
@@ -47,7 +47,7 @@ def prelude(f, out)
when /\A%%/
out << "%%\n"
return
- when /\A%token/
+ when /\A%token/, /\A} <node>/
out << line.sub(/<\w+>/, '<val>')
when /\A%type/
out << line.sub(/<\w+>/, '<val>')
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
index f0b977d79c..eb9eb8ae0e 100644
--- a/ext/socket/addrinfo.h
+++ b/ext/socket/addrinfo.h
@@ -129,14 +129,14 @@
#ifndef HAVE_TYPE_STRUCT_ADDRINFO
struct addrinfo {
- int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
- int ai_family; /* PF_xxx */
- int ai_socktype; /* SOCK_xxx */
- int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- size_t ai_addrlen; /* length of ai_addr */
- char *ai_canonname; /* canonical name for hostname */
- struct sockaddr *ai_addr; /* binary address */
- struct addrinfo *ai_next; /* next structure in linked list */
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
};
#endif
@@ -158,18 +158,18 @@ struct addrinfo {
#endif
extern int getaddrinfo __P((
- const char *hostname, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res));
+ const char *hostname, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res));
extern int getnameinfo __P((
- const struct sockaddr *sa,
- socklen_t salen,
- char *host,
- socklen_t hostlen,
- char *serv,
- socklen_t servlen,
- int flags));
+ const struct sockaddr *sa,
+ socklen_t salen,
+ char *host,
+ socklen_t hostlen,
+ char *serv,
+ socklen_t servlen,
+ int flags));
extern void freehostent __P((struct hostent *));
extern void freeaddrinfo __P((struct addrinfo *));
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 4ec3f3d0a8..7406177de2 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -333,11 +333,11 @@ ancillary_timestamp(VALUE self)
if (level == SOL_SOCKET && type == SCM_BINTIME &&
RSTRING_LEN(data) == sizeof(struct bintime)) {
struct bintime bt;
- VALUE d, timev;
+ VALUE d, timev;
memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt));
- d = ULL2NUM(0x100000000ULL);
- d = mul(d,d);
- timev = add(TIMET2NUM(bt.sec), quo(ULL2NUM(bt.frac), d));
+ d = ULL2NUM(0x100000000ULL);
+ d = mul(d,d);
+ timev = add(TIMET2NUM(bt.sec), quo(ULL2NUM(bt.frac), d));
result = rb_time_num_new(timev, Qnil);
}
# endif
@@ -697,7 +697,7 @@ anc_inspect_passcred_credentials(int level, int type, VALUE data, VALUE ret)
struct ucred cred;
memcpy(&cred, RSTRING_PTR(data), sizeof(struct ucred));
rb_str_catf(ret, " pid=%u uid=%u gid=%u", cred.pid, cred.uid, cred.gid);
- rb_str_cat2(ret, " (ucred)");
+ rb_str_cat2(ret, " (ucred)");
return 1;
}
else {
@@ -712,7 +712,7 @@ static int
anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret)
{
if (level != SOL_SOCKET && type != SCM_CREDS)
- return 0;
+ return 0;
/*
* FreeBSD has struct cmsgcred and struct sockcred.
@@ -727,46 +727,46 @@ anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret)
#if defined(HAVE_TYPE_STRUCT_CMSGCRED) /* FreeBSD */
if (RSTRING_LEN(data) == sizeof(struct cmsgcred)) {
- struct cmsgcred cred;
+ struct cmsgcred cred;
memcpy(&cred, RSTRING_PTR(data), sizeof(struct cmsgcred));
rb_str_catf(ret, " pid=%u", cred.cmcred_pid);
rb_str_catf(ret, " uid=%u", cred.cmcred_uid);
rb_str_catf(ret, " euid=%u", cred.cmcred_euid);
rb_str_catf(ret, " gid=%u", cred.cmcred_gid);
- if (cred.cmcred_ngroups) {
- int i;
- const char *sep = " groups=";
- for (i = 0; i < cred.cmcred_ngroups; i++) {
- rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]);
- sep = ",";
- }
- }
- rb_str_cat2(ret, " (cmsgcred)");
+ if (cred.cmcred_ngroups) {
+ int i;
+ const char *sep = " groups=";
+ for (i = 0; i < cred.cmcred_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]);
+ sep = ",";
+ }
+ }
+ rb_str_cat2(ret, " (cmsgcred)");
return 1;
}
#endif
#if defined(HAVE_TYPE_STRUCT_SOCKCRED) /* FreeBSD, NetBSD */
if ((size_t)RSTRING_LEN(data) >= SOCKCREDSIZE(0)) {
- struct sockcred cred0, *cred;
+ struct sockcred cred0, *cred;
memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0));
- if ((size_t)RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) {
- cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups));
- memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups));
- rb_str_catf(ret, " uid=%u", cred->sc_uid);
- rb_str_catf(ret, " euid=%u", cred->sc_euid);
- rb_str_catf(ret, " gid=%u", cred->sc_gid);
- rb_str_catf(ret, " egid=%u", cred->sc_egid);
- if (cred0.sc_ngroups) {
- int i;
- const char *sep = " groups=";
- for (i = 0; i < cred0.sc_ngroups; i++) {
- rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]);
- sep = ",";
- }
- }
- rb_str_cat2(ret, " (sockcred)");
- return 1;
- }
+ if ((size_t)RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) {
+ cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups));
+ memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups));
+ rb_str_catf(ret, " uid=%u", cred->sc_uid);
+ rb_str_catf(ret, " euid=%u", cred->sc_euid);
+ rb_str_catf(ret, " gid=%u", cred->sc_gid);
+ rb_str_catf(ret, " egid=%u", cred->sc_egid);
+ if (cred0.sc_ngroups) {
+ int i;
+ const char *sep = " groups=";
+ for (i = 0; i < cred0.sc_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]);
+ sep = ",";
+ }
+ }
+ rb_str_cat2(ret, " (sockcred)");
+ return 1;
+ }
}
#endif
return 0;
@@ -851,6 +851,12 @@ anc_inspect_ipv6_pktinfo(int level, int type, VALUE data, VALUE ret)
}
#endif
+#ifdef HAVE_GMTIME_R
+# define LOCALTIME(time, tm) localtime_r(&(time), &(tm))
+#else
+# define LOCALTIME(time, tm) ((tm) = *localtime(&(time)))
+#endif
+
#if defined(SCM_TIMESTAMP) /* GNU/Linux, FreeBSD, NetBSD, OpenBSD, MacOS X, Solaris */
static int
inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret)
@@ -862,7 +868,7 @@ inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret)
char buf[32];
memcpy((char*)&tv, RSTRING_PTR(data), sizeof(tv));
time = tv.tv_sec;
- tm = *localtime(&time);
+ LOCALTIME(time, tm);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
rb_str_catf(ret, " %s.%06ld", buf, (long)tv.tv_usec);
return 1;
@@ -882,7 +888,7 @@ inspect_timespec_as_abstime(int level, int optname, VALUE data, VALUE ret)
struct tm tm;
char buf[32];
memcpy((char*)&ts, RSTRING_PTR(data), sizeof(ts));
- tm = *localtime(&ts.tv_sec);
+ LOCALTIME(ts.tv_sec, tm);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
rb_str_catf(ret, " %s.%09ld", buf, (long)ts.tv_nsec);
return 1;
@@ -900,37 +906,37 @@ inspect_bintime_as_abstime(int level, int optname, VALUE data, VALUE ret)
if (RSTRING_LEN(data) == sizeof(struct bintime)) {
struct bintime bt;
struct tm tm;
- uint64_t frac_h, frac_l;
- uint64_t scale_h, scale_l;
- uint64_t tmp1, tmp2;
- uint64_t res_h, res_l;
+ uint64_t frac_h, frac_l;
+ uint64_t scale_h, scale_l;
+ uint64_t tmp1, tmp2;
+ uint64_t res_h, res_l;
char buf[32];
memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt));
- tm = *localtime(&bt.sec);
+ LOCALTIME(bt.sec, tm);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
- /* res_h = frac * 10**19 / 2**64 */
+ /* res_h = frac * 10**19 / 2**64 */
- frac_h = bt.frac >> 32;
- frac_l = bt.frac & 0xffffffff;
+ frac_h = bt.frac >> 32;
+ frac_l = bt.frac & 0xffffffff;
- scale_h = 0x8ac72304; /* 0x8ac7230489e80000 == 10**19 */
- scale_l = 0x89e80000;
+ scale_h = 0x8ac72304; /* 0x8ac7230489e80000 == 10**19 */
+ scale_l = 0x89e80000;
- res_h = frac_h * scale_h;
- res_l = frac_l * scale_l;
+ res_h = frac_h * scale_h;
+ res_l = frac_l * scale_l;
- tmp1 = frac_h * scale_l;
- res_h += tmp1 >> 32;
- tmp2 = res_l;
- res_l += tmp1 & 0xffffffff;
- if (res_l < tmp2) res_h++;
+ tmp1 = frac_h * scale_l;
+ res_h += tmp1 >> 32;
+ tmp2 = res_l;
+ res_l += tmp1 & 0xffffffff;
+ if (res_l < tmp2) res_h++;
- tmp1 = frac_l * scale_h;
- res_h += tmp1 >> 32;
- tmp2 = res_l;
- res_l += tmp1 & 0xffffffff;
- if (res_l < tmp2) res_h++;
+ tmp1 = frac_l * scale_h;
+ res_h += tmp1 >> 32;
+ tmp2 = res_l;
+ res_l += tmp1 & 0xffffffff;
+ if (res_l < tmp2) res_h++;
rb_str_catf(ret, " %s.%019"PRIu64, buf, res_h);
return 1;
@@ -1130,8 +1136,8 @@ rb_sendmsg(int fd, const struct msghdr *msg, int flags)
static VALUE
bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
- VALUE dest_sockaddr, VALUE controls, VALUE ex,
- int nonblock)
+ VALUE dest_sockaddr, VALUE controls, VALUE ex,
+ int nonblock)
{
rb_io_t *fptr;
struct msghdr mh;
@@ -1154,15 +1160,15 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
tmp = rb_str_tmp_frozen_acquire(data);
if (!RB_TYPE_P(controls, T_ARRAY)) {
- controls = rb_ary_new();
+ controls = rb_ary_new();
}
controls_num = RARRAY_LENINT(controls);
if (controls_num) {
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
- int i;
- size_t last_pad = 0;
- const VALUE *controls_ptr = RARRAY_CONST_PTR(controls);
+ int i;
+ size_t last_pad = 0;
+ const VALUE *controls_ptr = RARRAY_CONST_PTR(controls);
#if defined(__NetBSD__)
int last_level = 0;
int last_type = 0;
@@ -1209,9 +1215,9 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
last_level = cmh.cmsg_level;
last_type = cmh.cmsg_type;
#endif
- last_pad = cspace - cmh.cmsg_len;
+ last_pad = cspace - cmh.cmsg_len;
}
- if (last_pad) {
+ if (last_pad) {
/*
* This code removes the last padding from msg_controllen.
*
@@ -1236,10 +1242,10 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
if (last_level == SOL_SOCKET && last_type == SCM_RIGHTS)
rb_str_set_len(controls_str, RSTRING_LEN(controls_str)-last_pad);
#endif
- }
- RB_GC_GUARD(controls);
+ }
+ RB_GC_GUARD(controls);
#else
- rb_raise(rb_eNotImpError, "control message for sendmsg is unimplemented");
+ rb_raise(rb_eNotImpError, "control message for sendmsg is unimplemented");
#endif
}
@@ -1250,7 +1256,7 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
#endif
if (!NIL_P(dest_sockaddr))
- SockAddrStringValue(dest_sockaddr);
+ SockAddrStringValue(dest_sockaddr);
rb_io_check_closed(fptr);
@@ -1278,20 +1284,20 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
ss = rb_sendmsg(fptr->fd, &mh, flags);
if (ss == -1) {
- int e;
- if (!nonblock && rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
+ int e;
+ if (!nonblock && rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
rb_io_check_closed(fptr);
goto retry;
}
- e = errno;
- if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
- if (ex == Qfalse) {
- return sym_wait_writable;
- }
- rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
- "sendmsg(2) would block");
- }
- rb_syserr_fail(e, "sendmsg(2)");
+ e = errno;
+ if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
+ if (ex == Qfalse) {
+ return sym_wait_writable;
+ }
+ rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
+ "sendmsg(2) would block");
+ }
+ rb_syserr_fail(e, "sendmsg(2)");
}
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
RB_GC_GUARD(controls_str);
@@ -1305,20 +1311,20 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
#if defined(HAVE_SENDMSG)
VALUE
rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags, VALUE dest_sockaddr,
- VALUE controls)
+ VALUE controls)
{
return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr, controls,
- Qtrue, 0);
+ Qtrue, 0);
}
#endif
#if defined(HAVE_SENDMSG)
VALUE
rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
- VALUE dest_sockaddr, VALUE controls, VALUE ex)
+ VALUE dest_sockaddr, VALUE controls, VALUE ex)
{
return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr,
- controls, ex, 1);
+ controls, ex, 1);
}
#endif
@@ -1416,12 +1422,12 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end)
{
if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
int *fdp, *end;
- VALUE ary = rb_ary_new();
- rb_ivar_set(ctl, rb_intern("unix_rights"), ary);
+ VALUE ary = rb_ary_new();
+ rb_ivar_set(ctl, rb_intern("unix_rights"), ary);
fdp = (int *)CMSG_DATA(cmh);
end = (int *)((char *)cmh + cmh->cmsg_len);
while ((char *)fdp + sizeof(int) <= (char *)end &&
- (char *)fdp + sizeof(int) <= msg_end) {
+ (char *)fdp + sizeof(int) <= msg_end) {
int fd = *fdp;
struct stat stbuf;
VALUE io;
@@ -1437,15 +1443,15 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end)
rb_ary_push(ary, io);
fdp++;
}
- OBJ_FREEZE(ary);
+ OBJ_FREEZE(ary);
}
}
#endif
static VALUE
bsock_recvmsg_internal(VALUE sock,
- VALUE vmaxdatlen, VALUE vflags, VALUE vmaxctllen,
- VALUE scm_rights, VALUE ex, int nonblock)
+ VALUE vmaxdatlen, VALUE vflags, VALUE vmaxctllen,
+ VALUE scm_rights, VALUE ex, int nonblock)
{
rb_io_t *fptr;
int grow_buffer;
@@ -1499,28 +1505,28 @@ bsock_recvmsg_internal(VALUE sock,
#if !defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
if (grow_buffer) {
- int socktype;
- socklen_t optlen = (socklen_t)sizeof(socktype);
+ int socktype;
+ socklen_t optlen = (socklen_t)sizeof(socktype);
if (getsockopt(fptr->fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen) == -1) {
- rb_sys_fail("getsockopt(SO_TYPE)");
- }
- if (socktype == SOCK_STREAM)
- grow_buffer = 0;
+ rb_sys_fail("getsockopt(SO_TYPE)");
+ }
+ if (socktype == SOCK_STREAM)
+ grow_buffer = 0;
}
#endif
retry:
if (NIL_P(dat_str))
- dat_str = rb_str_tmp_new(maxdatlen);
+ dat_str = rb_str_tmp_new(maxdatlen);
else
- rb_str_resize(dat_str, maxdatlen);
+ rb_str_resize(dat_str, maxdatlen);
datbuf = RSTRING_PTR(dat_str);
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
if (NIL_P(ctl_str))
- ctl_str = rb_str_tmp_new(maxctllen);
+ ctl_str = rb_str_tmp_new(maxctllen);
else
- rb_str_resize(ctl_str, maxctllen);
+ rb_str_resize(ctl_str, maxctllen);
ctlbuf = RSTRING_PTR(ctl_str);
#endif
@@ -1550,20 +1556,20 @@ bsock_recvmsg_internal(VALUE sock,
ss = rb_recvmsg(fptr->fd, &mh, flags);
if (ss == -1) {
- int e;
- if (!nonblock && rb_io_maybe_wait_readable(errno, fptr->self, Qnil)) {
+ int e;
+ if (!nonblock && rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
rb_io_check_closed(fptr);
goto retry;
}
- e = errno;
- if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
+ e = errno;
+ if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
if (ex == Qfalse) {
return sym_wait_readable;
}
- rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvmsg(2) would block");
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvmsg(2) would block");
}
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
- if (!gc_done && (e == EMFILE || e == EMSGSIZE)) {
+ if (!gc_done && (e == EMFILE || e == EMSGSIZE)) {
/*
* When SCM_RIGHTS hit the file descriptors limit:
* - Linux 2.6.18 causes success with MSG_CTRUNC
@@ -1573,24 +1579,24 @@ bsock_recvmsg_internal(VALUE sock,
gc_and_retry:
rb_gc();
gc_done = 1;
- goto retry;
+ goto retry;
}
#else
- if (NIL_P(vmaxdatlen) && grow_buffer && e == EMSGSIZE)
- ss = (ssize_t)iov.iov_len;
- else
+ if (NIL_P(vmaxdatlen) && grow_buffer && e == EMSGSIZE)
+ ss = (ssize_t)iov.iov_len;
+ else
#endif
- rb_syserr_fail(e, "recvmsg(2)");
+ rb_syserr_fail(e, "recvmsg(2)");
}
if (grow_buffer) {
- int grown = 0;
- if (NIL_P(vmaxdatlen) && ss != -1 && ss == (ssize_t)iov.iov_len) {
+ int grown = 0;
+ if (NIL_P(vmaxdatlen) && ss != -1 && ss == (ssize_t)iov.iov_len) {
if (SIZE_MAX/2 < maxdatlen)
rb_raise(rb_eArgError, "max data length too big");
- maxdatlen *= 2;
- grown = 1;
- }
+ maxdatlen *= 2;
+ grown = 1;
+ }
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
if (NIL_P(vmaxctllen) && (mh.msg_flags & MSG_CTRUNC)) {
#define BIG_ENOUGH_SPACE 65536
@@ -1599,9 +1605,9 @@ bsock_recvmsg_internal(VALUE sock,
/* there are big space bug truncated.
* file descriptors limit? */
if (!gc_done) {
- rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
goto gc_and_retry;
- }
+ }
}
else {
if (SIZE_MAX/2 < maxctllen)
@@ -1610,13 +1616,13 @@ bsock_recvmsg_internal(VALUE sock,
grown = 1;
}
#undef BIG_ENOUGH_SPACE
- }
+ }
#endif
- if (grown) {
+ if (grown) {
rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
- goto retry;
- }
- else {
+ goto retry;
+ }
+ else {
grow_buffer = 0;
if (flags != orig_flags) {
rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
@@ -1630,31 +1636,31 @@ bsock_recvmsg_internal(VALUE sock,
dat_str = rb_str_new(datbuf, ss);
else {
rb_str_resize(dat_str, ss);
- rb_obj_reveal(dat_str, rb_cString);
+ rb_obj_reveal(dat_str, rb_cString);
}
ret = rb_ary_new3(3, dat_str,
rsock_io_socket_addrinfo(sock, mh.msg_name, mh.msg_namelen),
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
- INT2NUM(mh.msg_flags)
+ INT2NUM(mh.msg_flags)
#else
- Qnil
+ Qnil
#endif
- );
+ );
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
family = rsock_getfamily(fptr);
if (mh.msg_controllen) {
- char *msg_end = (char *)mh.msg_control + mh.msg_controllen;
+ char *msg_end = (char *)mh.msg_control + mh.msg_controllen;
for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) {
VALUE ctl;
- char *ctl_end;
+ char *ctl_end;
size_t clen;
if (cmh->cmsg_len == 0) {
rb_raise(rb_eTypeError, "invalid control message (cmsg_len == 0)");
}
ctl_end = (char*)cmh + cmh->cmsg_len;
- clen = (ctl_end <= msg_end ? ctl_end : msg_end) - (char*)CMSG_DATA(cmh);
+ clen = (ctl_end <= msg_end ? ctl_end : msg_end) - (char*)CMSG_DATA(cmh);
ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_str_new((char*)CMSG_DATA(cmh), clen));
if (request_scm_rights)
make_io_for_unix_rights(ctl, cmh, msg_end);
@@ -1673,7 +1679,7 @@ bsock_recvmsg_internal(VALUE sock,
#if defined(HAVE_RECVMSG)
VALUE
rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE flags, VALUE clen,
- VALUE scm_rights)
+ VALUE scm_rights)
{
VALUE ex = Qtrue;
return bsock_recvmsg_internal(sock, dlen, flags, clen, scm_rights, ex, 0);
@@ -1683,7 +1689,7 @@ rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE flags, VALUE clen,
#if defined(HAVE_RECVMSG)
VALUE
rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE flags, VALUE clen,
- VALUE scm_rights, VALUE ex)
+ VALUE scm_rights, VALUE ex)
{
return bsock_recvmsg_internal(sock, dlen, flags, clen, scm_rights, ex, 1);
}
diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c
index 8477a37a6d..54c369f6fc 100644
--- a/ext/socket/basicsocket.c
+++ b/ext/socket/basicsocket.c
@@ -94,16 +94,16 @@ bsock_shutdown(int argc, VALUE *argv, VALUE sock)
rb_scan_args(argc, argv, "01", &howto);
if (howto == Qnil)
- how = SHUT_RDWR;
+ how = SHUT_RDWR;
else {
- how = rsock_shutdown_how_arg(howto);
+ how = rsock_shutdown_how_arg(howto);
if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
- rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
- }
+ rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
+ }
}
GetOpenFile(sock, fptr);
if (shutdown(fptr->fd, how) == -1)
- rb_sys_fail("shutdown(2)");
+ rb_sys_fail("shutdown(2)");
return INT2FIX(0);
}
@@ -126,7 +126,7 @@ bsock_close_read(VALUE sock)
GetOpenFile(sock, fptr);
shutdown(fptr->fd, 0);
if (!(fptr->mode & FMODE_WRITABLE)) {
- return rb_io_close(sock);
+ return rb_io_close(sock);
}
fptr->mode &= ~FMODE_READABLE;
@@ -155,7 +155,7 @@ bsock_close_write(VALUE sock)
GetOpenFile(sock, fptr);
if (!(fptr->mode & FMODE_READABLE)) {
- return rb_io_close(sock);
+ return rb_io_close(sock);
}
shutdown(fptr->fd, 1);
fptr->mode &= ~FMODE_WRITABLE;
@@ -246,21 +246,21 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
switch (TYPE(val)) {
case T_FIXNUM:
- i = FIX2INT(val);
- goto numval;
+ i = FIX2INT(val);
+ goto numval;
case T_FALSE:
- i = 0;
- goto numval;
+ i = 0;
+ goto numval;
case T_TRUE:
- i = 1;
+ i = 1;
numval:
- v = (char*)&i; vlen = (int)sizeof(i);
- break;
+ v = (char*)&i; vlen = (int)sizeof(i);
+ break;
default:
- StringValue(val);
- v = RSTRING_PTR(val);
- vlen = RSTRING_SOCKLEN(val);
- break;
+ StringValue(val);
+ v = RSTRING_PTR(val);
+ vlen = RSTRING_SOCKLEN(val);
+ break;
}
rb_io_check_closed(fptr);
@@ -306,7 +306,7 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
* ipttl = sock.getsockopt(:IP, :TTL).int
*
* optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
- * ipttl = optval.unpack("i")[0]
+ * ipttl = optval.unpack1("i")
*
* Option values may be structs. Decoding them can be complex as it involves
* examining your system headers to determine the correct definition. An
@@ -357,7 +357,7 @@ bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
rb_io_check_closed(fptr);
if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
- rsock_sys_fail_path("getsockopt(2)", fptr->pathv);
+ rsock_sys_fail_path("getsockopt(2)", fptr->pathv);
return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
}
@@ -385,7 +385,7 @@ bsock_getsockname(VALUE sock)
GetOpenFile(sock, fptr);
if (getsockname(fptr->fd, &buf.addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
+ rb_sys_fail("getsockname(2)");
if (len0 < len) len = len0;
return rb_str_new((char*)&buf, len);
}
@@ -416,7 +416,7 @@ bsock_getpeername(VALUE sock)
GetOpenFile(sock, fptr);
if (getpeername(fptr->fd, &buf.addr, &len) < 0)
- rb_sys_fail("getpeername(2)");
+ rb_sys_fail("getpeername(2)");
if (len0 < len) len = len0;
return rb_str_new((char*)&buf, len);
}
@@ -453,7 +453,7 @@ bsock_getpeereid(VALUE self)
gid_t egid;
GetOpenFile(self, fptr);
if (getpeereid(fptr->fd, &euid, &egid) == -1)
- rb_sys_fail("getpeereid(3)");
+ rb_sys_fail("getpeereid(3)");
return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
#elif defined(SO_PEERCRED) /* GNU/Linux */
rb_io_t *fptr;
@@ -461,7 +461,7 @@ bsock_getpeereid(VALUE self)
socklen_t len = sizeof(cred);
GetOpenFile(self, fptr);
if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
- rb_sys_fail("getsockopt(SO_PEERCRED)");
+ rb_sys_fail("getsockopt(SO_PEERCRED)");
return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
#elif defined(HAVE_GETPEERUCRED) /* Solaris */
rb_io_t *fptr;
@@ -469,7 +469,7 @@ bsock_getpeereid(VALUE self)
VALUE ret;
GetOpenFile(self, fptr);
if (getpeerucred(fptr->fd, &uc) == -1)
- rb_sys_fail("getpeerucred(3C)");
+ rb_sys_fail("getpeerucred(3C)");
ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
ucred_free(uc);
return ret;
@@ -506,7 +506,7 @@ bsock_local_address(VALUE sock)
GetOpenFile(sock, fptr);
if (getsockname(fptr->fd, &buf.addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
+ rb_sys_fail("getsockname(2)");
if (len0 < len) len = len0;
return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
}
@@ -540,7 +540,7 @@ bsock_remote_address(VALUE sock)
GetOpenFile(sock, fptr);
if (getpeername(fptr->fd, &buf.addr, &len) < 0)
- rb_sys_fail("getpeername(2)");
+ rb_sys_fail("getpeername(2)");
if (len0 < len) len = len0;
return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len);
}
@@ -601,7 +601,7 @@ rsock_bsock_send(int argc, VALUE *argv, VALUE socket)
if (n >= 0) return SSIZET2NUM(n);
- if (rb_io_maybe_wait_writable(errno, socket, Qnil)) {
+ if (rb_io_maybe_wait_writable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) {
continue;
}
@@ -656,10 +656,10 @@ bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
GetOpenFile(sock, fptr);
if (RTEST(state)) {
- fptr->mode |= FMODE_NOREVLOOKUP;
+ fptr->mode |= FMODE_NOREVLOOKUP;
}
else {
- fptr->mode &= ~FMODE_NOREVLOOKUP;
+ fptr->mode &= ~FMODE_NOREVLOOKUP;
}
return sock;
}
@@ -747,9 +747,9 @@ rsock_init_basicsocket(void)
rb_undef_method(rb_cBasicSocket, "initialize");
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
- bsock_do_not_rev_lookup, 0);
+ bsock_do_not_rev_lookup, 0);
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
- bsock_do_not_rev_lookup_set, 1);
+ bsock_do_not_rev_lookup_set, 1);
rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
@@ -770,23 +770,23 @@ rsock_init_basicsocket(void)
/* for ext/socket/lib/socket.rb use only: */
rb_define_private_method(rb_cBasicSocket,
- "__recv_nonblock", bsock_recv_nonblock, 4);
+ "__recv_nonblock", bsock_recv_nonblock, 4);
#if MSG_DONTWAIT_RELIABLE
rb_define_private_method(rb_cBasicSocket,
- "__read_nonblock", rsock_read_nonblock, 3);
+ "__read_nonblock", rsock_read_nonblock, 3);
rb_define_private_method(rb_cBasicSocket,
- "__write_nonblock", rsock_write_nonblock, 2);
+ "__write_nonblock", rsock_write_nonblock, 2);
#endif
/* in ancdata.c */
rb_define_private_method(rb_cBasicSocket, "__sendmsg",
- rsock_bsock_sendmsg, 4);
+ rsock_bsock_sendmsg, 4);
rb_define_private_method(rb_cBasicSocket, "__sendmsg_nonblock",
- rsock_bsock_sendmsg_nonblock, 5);
+ rsock_bsock_sendmsg_nonblock, 5);
rb_define_private_method(rb_cBasicSocket, "__recvmsg",
- rsock_bsock_recvmsg, 4);
+ rsock_bsock_recvmsg, 4);
rb_define_private_method(rb_cBasicSocket, "__recvmsg_nonblock",
- rsock_bsock_recvmsg_nonblock, 5);
+ rsock_bsock_recvmsg_nonblock, 5);
}
diff --git a/ext/socket/constants.c b/ext/socket/constants.c
index 1bbb53b173..1213f2ae17 100644
--- a/ext/socket/constants.c
+++ b/ext/socket/constants.c
@@ -26,14 +26,14 @@ constant_arg(VALUE arg, int (*str_to_int)(const char*, long, int*), const char *
goto str;
}
else if (!NIL_P(tmp = rb_check_string_type(arg))) {
- arg = tmp;
+ arg = tmp;
str:
ptr = RSTRING_PTR(arg);
if (str_to_int(ptr, RSTRING_LEN(arg), &ret) == -1)
- rb_raise(rb_eSocket, "%s: %s", errmsg, ptr);
+ rb_raise(rb_eSocket, "%s: %s", errmsg, ptr);
}
else {
- ret = NUM2INT(arg);
+ ret = NUM2INT(arg);
}
return ret;
}
diff --git a/ext/socket/depend b/ext/socket/depend
index 7538345d6b..28c5540cd6 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -12,7 +12,6 @@ constdefs.c: constdefs.h
# AUTOGENERATED DEPENDENCIES START
ancdata.o: $(RUBY_EXTCONF_H)
ancdata.o: $(arch_hdrdir)/ruby/config.h
-ancdata.o: $(hdrdir)/ruby.h
ancdata.o: $(hdrdir)/ruby/assert.h
ancdata.o: $(hdrdir)/ruby/backward.h
ancdata.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -28,6 +27,7 @@ ancdata.o: $(hdrdir)/ruby/defines.h
ancdata.o: $(hdrdir)/ruby/encoding.h
ancdata.o: $(hdrdir)/ruby/fiber/scheduler.h
ancdata.o: $(hdrdir)/ruby/intern.h
+ancdata.o: $(hdrdir)/ruby/internal/abi.h
ancdata.o: $(hdrdir)/ruby/internal/anyargs.h
ancdata.o: $(hdrdir)/ruby/internal/arithmetic.h
ancdata.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -97,6 +97,15 @@ ancdata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ancdata.o: $(hdrdir)/ruby/internal/ctype.h
ancdata.o: $(hdrdir)/ruby/internal/dllexport.h
ancdata.o: $(hdrdir)/ruby/internal/dosish.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/re.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/string.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ancdata.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ancdata.o: $(hdrdir)/ruby/internal/error.h
ancdata.o: $(hdrdir)/ruby/internal/eval.h
ancdata.o: $(hdrdir)/ruby/internal/event.h
@@ -188,13 +197,13 @@ 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: $(top_srcdir)/shape.h
ancdata.o: ancdata.c
ancdata.o: constdefs.h
ancdata.o: rubysocket.h
ancdata.o: sockport.h
basicsocket.o: $(RUBY_EXTCONF_H)
basicsocket.o: $(arch_hdrdir)/ruby/config.h
-basicsocket.o: $(hdrdir)/ruby.h
basicsocket.o: $(hdrdir)/ruby/assert.h
basicsocket.o: $(hdrdir)/ruby/backward.h
basicsocket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -210,6 +219,7 @@ basicsocket.o: $(hdrdir)/ruby/defines.h
basicsocket.o: $(hdrdir)/ruby/encoding.h
basicsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
basicsocket.o: $(hdrdir)/ruby/intern.h
+basicsocket.o: $(hdrdir)/ruby/internal/abi.h
basicsocket.o: $(hdrdir)/ruby/internal/anyargs.h
basicsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -279,6 +289,15 @@ basicsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
basicsocket.o: $(hdrdir)/ruby/internal/ctype.h
basicsocket.o: $(hdrdir)/ruby/internal/dllexport.h
basicsocket.o: $(hdrdir)/ruby/internal/dosish.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+basicsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
basicsocket.o: $(hdrdir)/ruby/internal/error.h
basicsocket.o: $(hdrdir)/ruby/internal/eval.h
basicsocket.o: $(hdrdir)/ruby/internal/event.h
@@ -370,13 +389,13 @@ 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: $(top_srcdir)/shape.h
basicsocket.o: basicsocket.c
basicsocket.o: constdefs.h
basicsocket.o: rubysocket.h
basicsocket.o: sockport.h
constants.o: $(RUBY_EXTCONF_H)
constants.o: $(arch_hdrdir)/ruby/config.h
-constants.o: $(hdrdir)/ruby.h
constants.o: $(hdrdir)/ruby/assert.h
constants.o: $(hdrdir)/ruby/backward.h
constants.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -392,6 +411,7 @@ constants.o: $(hdrdir)/ruby/defines.h
constants.o: $(hdrdir)/ruby/encoding.h
constants.o: $(hdrdir)/ruby/fiber/scheduler.h
constants.o: $(hdrdir)/ruby/intern.h
+constants.o: $(hdrdir)/ruby/internal/abi.h
constants.o: $(hdrdir)/ruby/internal/anyargs.h
constants.o: $(hdrdir)/ruby/internal/arithmetic.h
constants.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -461,6 +481,15 @@ constants.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
constants.o: $(hdrdir)/ruby/internal/ctype.h
constants.o: $(hdrdir)/ruby/internal/dllexport.h
constants.o: $(hdrdir)/ruby/internal/dosish.h
+constants.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+constants.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+constants.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+constants.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+constants.o: $(hdrdir)/ruby/internal/encoding/re.h
+constants.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+constants.o: $(hdrdir)/ruby/internal/encoding/string.h
+constants.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+constants.o: $(hdrdir)/ruby/internal/encoding/transcode.h
constants.o: $(hdrdir)/ruby/internal/error.h
constants.o: $(hdrdir)/ruby/internal/eval.h
constants.o: $(hdrdir)/ruby/internal/event.h
@@ -552,6 +581,7 @@ 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: $(top_srcdir)/shape.h
constants.o: constants.c
constants.o: constdefs.c
constants.o: constdefs.h
@@ -559,7 +589,6 @@ constants.o: rubysocket.h
constants.o: sockport.h
ifaddr.o: $(RUBY_EXTCONF_H)
ifaddr.o: $(arch_hdrdir)/ruby/config.h
-ifaddr.o: $(hdrdir)/ruby.h
ifaddr.o: $(hdrdir)/ruby/assert.h
ifaddr.o: $(hdrdir)/ruby/backward.h
ifaddr.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -575,6 +604,7 @@ ifaddr.o: $(hdrdir)/ruby/defines.h
ifaddr.o: $(hdrdir)/ruby/encoding.h
ifaddr.o: $(hdrdir)/ruby/fiber/scheduler.h
ifaddr.o: $(hdrdir)/ruby/intern.h
+ifaddr.o: $(hdrdir)/ruby/internal/abi.h
ifaddr.o: $(hdrdir)/ruby/internal/anyargs.h
ifaddr.o: $(hdrdir)/ruby/internal/arithmetic.h
ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -644,6 +674,15 @@ ifaddr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ifaddr.o: $(hdrdir)/ruby/internal/ctype.h
ifaddr.o: $(hdrdir)/ruby/internal/dllexport.h
ifaddr.o: $(hdrdir)/ruby/internal/dosish.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/re.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/string.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ifaddr.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ifaddr.o: $(hdrdir)/ruby/internal/error.h
ifaddr.o: $(hdrdir)/ruby/internal/eval.h
ifaddr.o: $(hdrdir)/ruby/internal/event.h
@@ -735,13 +774,13 @@ 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: $(top_srcdir)/shape.h
ifaddr.o: constdefs.h
ifaddr.o: ifaddr.c
ifaddr.o: rubysocket.h
ifaddr.o: sockport.h
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
-init.o: $(hdrdir)/ruby.h
init.o: $(hdrdir)/ruby/assert.h
init.o: $(hdrdir)/ruby/backward.h
init.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -757,6 +796,7 @@ init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/encoding.h
init.o: $(hdrdir)/ruby/fiber/scheduler.h
init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/abi.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -826,6 +866,15 @@ init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
init.o: $(hdrdir)/ruby/internal/ctype.h
init.o: $(hdrdir)/ruby/internal/dllexport.h
init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+init.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+init.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+init.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+init.o: $(hdrdir)/ruby/internal/encoding/re.h
+init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+init.o: $(hdrdir)/ruby/internal/encoding/string.h
+init.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+init.o: $(hdrdir)/ruby/internal/encoding/transcode.h
init.o: $(hdrdir)/ruby/internal/error.h
init.o: $(hdrdir)/ruby/internal/eval.h
init.o: $(hdrdir)/ruby/internal/event.h
@@ -917,13 +966,13 @@ 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: $(top_srcdir)/shape.h
init.o: constdefs.h
init.o: init.c
init.o: rubysocket.h
init.o: sockport.h
ipsocket.o: $(RUBY_EXTCONF_H)
ipsocket.o: $(arch_hdrdir)/ruby/config.h
-ipsocket.o: $(hdrdir)/ruby.h
ipsocket.o: $(hdrdir)/ruby/assert.h
ipsocket.o: $(hdrdir)/ruby/backward.h
ipsocket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -939,6 +988,7 @@ ipsocket.o: $(hdrdir)/ruby/defines.h
ipsocket.o: $(hdrdir)/ruby/encoding.h
ipsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
ipsocket.o: $(hdrdir)/ruby/intern.h
+ipsocket.o: $(hdrdir)/ruby/internal/abi.h
ipsocket.o: $(hdrdir)/ruby/internal/anyargs.h
ipsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1008,6 +1058,15 @@ ipsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
ipsocket.o: $(hdrdir)/ruby/internal/ctype.h
ipsocket.o: $(hdrdir)/ruby/internal/dllexport.h
ipsocket.o: $(hdrdir)/ruby/internal/dosish.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ipsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
ipsocket.o: $(hdrdir)/ruby/internal/error.h
ipsocket.o: $(hdrdir)/ruby/internal/eval.h
ipsocket.o: $(hdrdir)/ruby/internal/event.h
@@ -1099,13 +1158,13 @@ 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: $(top_srcdir)/shape.h
ipsocket.o: constdefs.h
ipsocket.o: ipsocket.c
ipsocket.o: rubysocket.h
ipsocket.o: sockport.h
option.o: $(RUBY_EXTCONF_H)
option.o: $(arch_hdrdir)/ruby/config.h
-option.o: $(hdrdir)/ruby.h
option.o: $(hdrdir)/ruby/assert.h
option.o: $(hdrdir)/ruby/backward.h
option.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -1121,6 +1180,7 @@ option.o: $(hdrdir)/ruby/defines.h
option.o: $(hdrdir)/ruby/encoding.h
option.o: $(hdrdir)/ruby/fiber/scheduler.h
option.o: $(hdrdir)/ruby/intern.h
+option.o: $(hdrdir)/ruby/internal/abi.h
option.o: $(hdrdir)/ruby/internal/anyargs.h
option.o: $(hdrdir)/ruby/internal/arithmetic.h
option.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1190,6 +1250,15 @@ option.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
option.o: $(hdrdir)/ruby/internal/ctype.h
option.o: $(hdrdir)/ruby/internal/dllexport.h
option.o: $(hdrdir)/ruby/internal/dosish.h
+option.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+option.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+option.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+option.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+option.o: $(hdrdir)/ruby/internal/encoding/re.h
+option.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+option.o: $(hdrdir)/ruby/internal/encoding/string.h
+option.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+option.o: $(hdrdir)/ruby/internal/encoding/transcode.h
option.o: $(hdrdir)/ruby/internal/error.h
option.o: $(hdrdir)/ruby/internal/eval.h
option.o: $(hdrdir)/ruby/internal/event.h
@@ -1281,13 +1350,13 @@ 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: $(top_srcdir)/shape.h
option.o: constdefs.h
option.o: option.c
option.o: rubysocket.h
option.o: sockport.h
raddrinfo.o: $(RUBY_EXTCONF_H)
raddrinfo.o: $(arch_hdrdir)/ruby/config.h
-raddrinfo.o: $(hdrdir)/ruby.h
raddrinfo.o: $(hdrdir)/ruby/assert.h
raddrinfo.o: $(hdrdir)/ruby/backward.h
raddrinfo.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -1303,6 +1372,7 @@ raddrinfo.o: $(hdrdir)/ruby/defines.h
raddrinfo.o: $(hdrdir)/ruby/encoding.h
raddrinfo.o: $(hdrdir)/ruby/fiber/scheduler.h
raddrinfo.o: $(hdrdir)/ruby/intern.h
+raddrinfo.o: $(hdrdir)/ruby/internal/abi.h
raddrinfo.o: $(hdrdir)/ruby/internal/anyargs.h
raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic.h
raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1372,6 +1442,15 @@ raddrinfo.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
raddrinfo.o: $(hdrdir)/ruby/internal/ctype.h
raddrinfo.o: $(hdrdir)/ruby/internal/dllexport.h
raddrinfo.o: $(hdrdir)/ruby/internal/dosish.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/re.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/string.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+raddrinfo.o: $(hdrdir)/ruby/internal/encoding/transcode.h
raddrinfo.o: $(hdrdir)/ruby/internal/error.h
raddrinfo.o: $(hdrdir)/ruby/internal/eval.h
raddrinfo.o: $(hdrdir)/ruby/internal/event.h
@@ -1463,13 +1542,13 @@ 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: $(top_srcdir)/shape.h
raddrinfo.o: constdefs.h
raddrinfo.o: raddrinfo.c
raddrinfo.o: rubysocket.h
raddrinfo.o: sockport.h
socket.o: $(RUBY_EXTCONF_H)
socket.o: $(arch_hdrdir)/ruby/config.h
-socket.o: $(hdrdir)/ruby.h
socket.o: $(hdrdir)/ruby/assert.h
socket.o: $(hdrdir)/ruby/backward.h
socket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -1485,6 +1564,7 @@ socket.o: $(hdrdir)/ruby/defines.h
socket.o: $(hdrdir)/ruby/encoding.h
socket.o: $(hdrdir)/ruby/fiber/scheduler.h
socket.o: $(hdrdir)/ruby/intern.h
+socket.o: $(hdrdir)/ruby/internal/abi.h
socket.o: $(hdrdir)/ruby/internal/anyargs.h
socket.o: $(hdrdir)/ruby/internal/arithmetic.h
socket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1554,6 +1634,15 @@ socket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
socket.o: $(hdrdir)/ruby/internal/ctype.h
socket.o: $(hdrdir)/ruby/internal/dllexport.h
socket.o: $(hdrdir)/ruby/internal/dosish.h
+socket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+socket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+socket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+socket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+socket.o: $(hdrdir)/ruby/internal/encoding/re.h
+socket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+socket.o: $(hdrdir)/ruby/internal/encoding/string.h
+socket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+socket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
socket.o: $(hdrdir)/ruby/internal/error.h
socket.o: $(hdrdir)/ruby/internal/eval.h
socket.o: $(hdrdir)/ruby/internal/event.h
@@ -1645,13 +1734,13 @@ 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: $(top_srcdir)/shape.h
socket.o: constdefs.h
socket.o: rubysocket.h
socket.o: socket.c
socket.o: sockport.h
sockssocket.o: $(RUBY_EXTCONF_H)
sockssocket.o: $(arch_hdrdir)/ruby/config.h
-sockssocket.o: $(hdrdir)/ruby.h
sockssocket.o: $(hdrdir)/ruby/assert.h
sockssocket.o: $(hdrdir)/ruby/backward.h
sockssocket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -1667,6 +1756,7 @@ sockssocket.o: $(hdrdir)/ruby/defines.h
sockssocket.o: $(hdrdir)/ruby/encoding.h
sockssocket.o: $(hdrdir)/ruby/fiber/scheduler.h
sockssocket.o: $(hdrdir)/ruby/intern.h
+sockssocket.o: $(hdrdir)/ruby/internal/abi.h
sockssocket.o: $(hdrdir)/ruby/internal/anyargs.h
sockssocket.o: $(hdrdir)/ruby/internal/arithmetic.h
sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1736,6 +1826,15 @@ sockssocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
sockssocket.o: $(hdrdir)/ruby/internal/ctype.h
sockssocket.o: $(hdrdir)/ruby/internal/dllexport.h
sockssocket.o: $(hdrdir)/ruby/internal/dosish.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+sockssocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
sockssocket.o: $(hdrdir)/ruby/internal/error.h
sockssocket.o: $(hdrdir)/ruby/internal/eval.h
sockssocket.o: $(hdrdir)/ruby/internal/event.h
@@ -1827,13 +1926,13 @@ 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: $(top_srcdir)/shape.h
sockssocket.o: constdefs.h
sockssocket.o: rubysocket.h
sockssocket.o: sockport.h
sockssocket.o: sockssocket.c
tcpserver.o: $(RUBY_EXTCONF_H)
tcpserver.o: $(arch_hdrdir)/ruby/config.h
-tcpserver.o: $(hdrdir)/ruby.h
tcpserver.o: $(hdrdir)/ruby/assert.h
tcpserver.o: $(hdrdir)/ruby/backward.h
tcpserver.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -1849,6 +1948,7 @@ tcpserver.o: $(hdrdir)/ruby/defines.h
tcpserver.o: $(hdrdir)/ruby/encoding.h
tcpserver.o: $(hdrdir)/ruby/fiber/scheduler.h
tcpserver.o: $(hdrdir)/ruby/intern.h
+tcpserver.o: $(hdrdir)/ruby/internal/abi.h
tcpserver.o: $(hdrdir)/ruby/internal/anyargs.h
tcpserver.o: $(hdrdir)/ruby/internal/arithmetic.h
tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -1918,6 +2018,15 @@ tcpserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
tcpserver.o: $(hdrdir)/ruby/internal/ctype.h
tcpserver.o: $(hdrdir)/ruby/internal/dllexport.h
tcpserver.o: $(hdrdir)/ruby/internal/dosish.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/re.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/string.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+tcpserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h
tcpserver.o: $(hdrdir)/ruby/internal/error.h
tcpserver.o: $(hdrdir)/ruby/internal/eval.h
tcpserver.o: $(hdrdir)/ruby/internal/event.h
@@ -2009,13 +2118,13 @@ 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: $(top_srcdir)/shape.h
tcpserver.o: constdefs.h
tcpserver.o: rubysocket.h
tcpserver.o: sockport.h
tcpserver.o: tcpserver.c
tcpsocket.o: $(RUBY_EXTCONF_H)
tcpsocket.o: $(arch_hdrdir)/ruby/config.h
-tcpsocket.o: $(hdrdir)/ruby.h
tcpsocket.o: $(hdrdir)/ruby/assert.h
tcpsocket.o: $(hdrdir)/ruby/backward.h
tcpsocket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -2031,6 +2140,7 @@ tcpsocket.o: $(hdrdir)/ruby/defines.h
tcpsocket.o: $(hdrdir)/ruby/encoding.h
tcpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
tcpsocket.o: $(hdrdir)/ruby/intern.h
+tcpsocket.o: $(hdrdir)/ruby/internal/abi.h
tcpsocket.o: $(hdrdir)/ruby/internal/anyargs.h
tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -2100,6 +2210,15 @@ tcpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
tcpsocket.o: $(hdrdir)/ruby/internal/ctype.h
tcpsocket.o: $(hdrdir)/ruby/internal/dllexport.h
tcpsocket.o: $(hdrdir)/ruby/internal/dosish.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+tcpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
tcpsocket.o: $(hdrdir)/ruby/internal/error.h
tcpsocket.o: $(hdrdir)/ruby/internal/eval.h
tcpsocket.o: $(hdrdir)/ruby/internal/event.h
@@ -2191,13 +2310,13 @@ 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: $(top_srcdir)/shape.h
tcpsocket.o: constdefs.h
tcpsocket.o: rubysocket.h
tcpsocket.o: sockport.h
tcpsocket.o: tcpsocket.c
udpsocket.o: $(RUBY_EXTCONF_H)
udpsocket.o: $(arch_hdrdir)/ruby/config.h
-udpsocket.o: $(hdrdir)/ruby.h
udpsocket.o: $(hdrdir)/ruby/assert.h
udpsocket.o: $(hdrdir)/ruby/backward.h
udpsocket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -2213,6 +2332,7 @@ udpsocket.o: $(hdrdir)/ruby/defines.h
udpsocket.o: $(hdrdir)/ruby/encoding.h
udpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
udpsocket.o: $(hdrdir)/ruby/intern.h
+udpsocket.o: $(hdrdir)/ruby/internal/abi.h
udpsocket.o: $(hdrdir)/ruby/internal/anyargs.h
udpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -2282,6 +2402,15 @@ udpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
udpsocket.o: $(hdrdir)/ruby/internal/ctype.h
udpsocket.o: $(hdrdir)/ruby/internal/dllexport.h
udpsocket.o: $(hdrdir)/ruby/internal/dosish.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+udpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
udpsocket.o: $(hdrdir)/ruby/internal/error.h
udpsocket.o: $(hdrdir)/ruby/internal/eval.h
udpsocket.o: $(hdrdir)/ruby/internal/event.h
@@ -2373,13 +2502,13 @@ 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: $(top_srcdir)/shape.h
udpsocket.o: constdefs.h
udpsocket.o: rubysocket.h
udpsocket.o: sockport.h
udpsocket.o: udpsocket.c
unixserver.o: $(RUBY_EXTCONF_H)
unixserver.o: $(arch_hdrdir)/ruby/config.h
-unixserver.o: $(hdrdir)/ruby.h
unixserver.o: $(hdrdir)/ruby/assert.h
unixserver.o: $(hdrdir)/ruby/backward.h
unixserver.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -2395,6 +2524,7 @@ unixserver.o: $(hdrdir)/ruby/defines.h
unixserver.o: $(hdrdir)/ruby/encoding.h
unixserver.o: $(hdrdir)/ruby/fiber/scheduler.h
unixserver.o: $(hdrdir)/ruby/intern.h
+unixserver.o: $(hdrdir)/ruby/internal/abi.h
unixserver.o: $(hdrdir)/ruby/internal/anyargs.h
unixserver.o: $(hdrdir)/ruby/internal/arithmetic.h
unixserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -2464,6 +2594,15 @@ unixserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
unixserver.o: $(hdrdir)/ruby/internal/ctype.h
unixserver.o: $(hdrdir)/ruby/internal/dllexport.h
unixserver.o: $(hdrdir)/ruby/internal/dosish.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/re.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/string.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+unixserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h
unixserver.o: $(hdrdir)/ruby/internal/error.h
unixserver.o: $(hdrdir)/ruby/internal/eval.h
unixserver.o: $(hdrdir)/ruby/internal/event.h
@@ -2555,13 +2694,13 @@ 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: $(top_srcdir)/shape.h
unixserver.o: constdefs.h
unixserver.o: rubysocket.h
unixserver.o: sockport.h
unixserver.o: unixserver.c
unixsocket.o: $(RUBY_EXTCONF_H)
unixsocket.o: $(arch_hdrdir)/ruby/config.h
-unixsocket.o: $(hdrdir)/ruby.h
unixsocket.o: $(hdrdir)/ruby/assert.h
unixsocket.o: $(hdrdir)/ruby/backward.h
unixsocket.o: $(hdrdir)/ruby/backward/2/assume.h
@@ -2577,6 +2716,7 @@ unixsocket.o: $(hdrdir)/ruby/defines.h
unixsocket.o: $(hdrdir)/ruby/encoding.h
unixsocket.o: $(hdrdir)/ruby/fiber/scheduler.h
unixsocket.o: $(hdrdir)/ruby/intern.h
+unixsocket.o: $(hdrdir)/ruby/internal/abi.h
unixsocket.o: $(hdrdir)/ruby/internal/anyargs.h
unixsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -2646,6 +2786,15 @@ unixsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
unixsocket.o: $(hdrdir)/ruby/internal/ctype.h
unixsocket.o: $(hdrdir)/ruby/internal/dllexport.h
unixsocket.o: $(hdrdir)/ruby/internal/dosish.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/re.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/string.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+unixsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h
unixsocket.o: $(hdrdir)/ruby/internal/error.h
unixsocket.o: $(hdrdir)/ruby/internal/eval.h
unixsocket.o: $(hdrdir)/ruby/internal/event.h
@@ -2737,6 +2886,7 @@ 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: $(top_srcdir)/shape.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 c86cc8f8c0..37ff216560 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -316,6 +316,7 @@ end
netpacket/packet.h
net/ethernet.h
sys/un.h
+ afunix.h
ifaddrs.h
sys/ioctl.h
sys/sockio.h
@@ -484,6 +485,9 @@ EOF
have_func("getpeerucred(0, (ucred_t **)NULL)", headers) # SunOS
have_func_decl = proc do |name, headers|
+ # check if there is a declaration of <name> by trying to declare
+ # both "int <name>(void)" and "void <name>(void)"
+ # (at least one attempt should fail if there is a declaration)
if !checking_for("declaration of #{name}()") {!%w[int void].all? {|ret| try_compile(<<EOF)}}
#{cpp_include(headers)}
#{ret} #{name}(void);
@@ -492,10 +496,10 @@ EOF
end
end
if have_func('if_indextoname(0, "")', headers)
- have_func_decl["if_indextoname"]
+ have_func_decl["if_indextoname", headers]
end
if have_func('if_nametoindex("")', headers)
- have_func_decl["if_nametoindex"]
+ have_func_decl["if_nametoindex", headers]
end
have_func("hsterror", headers)
@@ -548,7 +552,7 @@ EOS
end
if !have_macro("IPPROTO_IPV6", headers) && have_const("IPPROTO_IPV6", headers)
- IO.read(File.join(File.dirname(__FILE__), "mkconstants.rb")).sub(/\A.*^__END__$/m, '').split(/\r?\n/).grep(/\AIPPROTO_\w*/){$&}.each {|name|
+ File.read(File.join(File.dirname(__FILE__), "mkconstants.rb")).sub(/\A.*^__END__$/m, '').split(/\r?\n/).grep(/\AIPPROTO_\w*/){$&}.each {|name|
have_const(name, headers) unless $defs.include?("-DHAVE_CONST_#{name.upcase}")
}
end
@@ -652,12 +656,20 @@ EOS
end
hdr = "netinet6/in6.h"
- if /darwin/ =~ RUBY_PLATFORM and !try_compile(<<"SRC", nil, :werror=>true)
+ /darwin/ =~ RUBY_PLATFORM and
+ checking_for("if apple's #{hdr} needs s6_addr patch") {!try_compile(<<"SRC", nil, :werror=>true)} and
#include <netinet/in.h>
int t(struct in6_addr *addr) {return IN6_IS_ADDR_UNSPECIFIED(addr);}
SRC
- print "fixing apple's netinet6/in6.h ..."; $stdout.flush
- in6 = File.read("/usr/include/#{hdr}")
+ checking_for("fixing apple's #{hdr}", "%s") do
+ file = xpopen(%w"clang -include netinet/in.h -E -xc -", in: IO::NULL) do |f|
+ re = %r[^# *\d+ *"(.*/netinet/in\.h)"]
+ Logging.message " grep(#{re})\n"
+ f.read[re, 1]
+ end
+ Logging.message "Substitute from #{file}\n"
+
+ in6 = File.read(file)
if in6.gsub!(/\*\(const\s+__uint32_t\s+\*\)\(const\s+void\s+\*\)\(&(\(\w+\))->s6_addr\[(\d+)\]\)/) do
i, r = $2.to_i.divmod(4)
if r.zero?
@@ -667,12 +679,12 @@ SRC
end
end
FileUtils.mkdir_p(File.dirname(hdr))
- open(hdr, "w") {|f| f.write(in6)}
+ File.write(hdr, in6)
$distcleanfiles << hdr
$distcleandirs << File.dirname(hdr)
- puts "done"
+ "done"
else
- puts "not needed"
+ "not needed"
end
end
create_makefile("socket")
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
index ce6dc40478..95a2feb3be 100644
--- a/ext/socket/getaddrinfo.c
+++ b/ext/socket/getaddrinfo.c
@@ -98,42 +98,42 @@ static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
static const char in_addrany[] = { 0, 0, 0, 0 };
static const char in6_addrany[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const char in_loopback[] = { 127, 0, 0, 1 };
static const char in6_loopback[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
struct sockinet {
- u_char si_len;
- u_char si_family;
- u_short si_port;
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
};
static const struct afd {
- int a_af;
- int a_addrlen;
- int a_socklen;
- int a_off;
- const char *a_addrany;
- const char *a_loopback;
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
} afdl [] = {
#ifdef INET6
#define N_INET6 0
- {PF_INET6, sizeof(struct in6_addr),
- sizeof(struct sockaddr_in6),
- offsetof(struct sockaddr_in6, sin6_addr),
- in6_addrany, in6_loopback},
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback},
#define N_INET 1
#else
#define N_INET 0
#endif
- {PF_INET, sizeof(struct in_addr),
- sizeof(struct sockaddr_in),
- offsetof(struct sockaddr_in, sin_addr),
- in_addrany, in_loopback},
- {0, 0, 0, 0, NULL, NULL},
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback},
+ {0, 0, 0, 0, NULL, NULL},
};
#ifdef INET6
@@ -143,58 +143,58 @@ static const struct afd {
#endif
static int get_name __P((const char *, const struct afd *,
- struct addrinfo **, char *, struct addrinfo *,
- int));
+ struct addrinfo **, char *, struct addrinfo *,
+ int));
static int get_addr __P((const char *, int, struct addrinfo **,
- struct addrinfo *, int));
+ struct addrinfo *, int));
static int str_isnumber __P((const char *));
#ifndef HAVE_GAI_STRERROR
static const char *const ai_errlist[] = {
- "success.",
- "address family for hostname not supported.", /* EAI_ADDRFAMILY */
- "temporary failure in name resolution.", /* EAI_AGAIN */
- "invalid value for ai_flags.", /* EAI_BADFLAGS */
- "non-recoverable failure in name resolution.", /* EAI_FAIL */
- "ai_family not supported.", /* EAI_FAMILY */
- "memory allocation failure.", /* EAI_MEMORY */
- "no address associated with hostname.", /* EAI_NODATA */
- "hostname nor servname provided, or not known.",/* EAI_NONAME */
- "servname not supported for ai_socktype.", /* EAI_SERVICE */
- "ai_socktype not supported.", /* EAI_SOCKTYPE */
- "system error returned in errno.", /* EAI_SYSTEM */
- "invalid value for hints.", /* EAI_BADHINTS */
- "resolved protocol is unknown.", /* EAI_PROTOCOL */
- "unknown error.", /* EAI_MAX */
+ "success.",
+ "address family for hostname not supported.", /* EAI_ADDRFAMILY */
+ "temporary failure in name resolution.", /* EAI_AGAIN */
+ "invalid value for ai_flags.", /* EAI_BADFLAGS */
+ "non-recoverable failure in name resolution.", /* EAI_FAIL */
+ "ai_family not supported.", /* EAI_FAMILY */
+ "memory allocation failure.", /* EAI_MEMORY */
+ "no address associated with hostname.", /* EAI_NODATA */
+ "hostname nor servname provided, or not known.",/* EAI_NONAME */
+ "servname not supported for ai_socktype.", /* EAI_SERVICE */
+ "ai_socktype not supported.", /* EAI_SOCKTYPE */
+ "system error returned in errno.", /* EAI_SYSTEM */
+ "invalid value for hints.", /* EAI_BADHINTS */
+ "resolved protocol is unknown.", /* EAI_PROTOCOL */
+ "unknown error.", /* EAI_MAX */
};
#endif
#define GET_CANONNAME(ai, str) \
if (pai->ai_flags & AI_CANONNAME) {\
- if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
- strcpy((ai)->ai_canonname, (str));\
- } else {\
- error = EAI_MEMORY;\
- goto free;\
- }\
+ if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
+ strcpy((ai)->ai_canonname, (str));\
+ } else {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
}
#define GET_AI(ai, afd, addr, port) {\
- char *p;\
- if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
- ((afd)->a_socklen)))\
- == NULL) {\
- error = EAI_MEMORY;\
- goto free;\
- }\
- memcpy((ai), pai, sizeof(struct addrinfo));\
- (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
- (ai)->ai_family = (afd)->a_af;\
- (ai)->ai_addrlen = (afd)->a_socklen;\
- INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\
- ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\
- p = (char *)((ai)->ai_addr);\
- memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
+ char *p;\
+ if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
+ ((afd)->a_socklen)))\
+ == NULL) {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+ memcpy((ai), pai, sizeof(struct addrinfo));\
+ (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
+ (ai)->ai_family = (afd)->a_af;\
+ (ai)->ai_addrlen = (afd)->a_socklen;\
+ INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\
+ ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\
+ p = (char *)((ai)->ai_addr);\
+ memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
}
#define ERR(err) { error = (err); goto bad; }
@@ -206,36 +206,36 @@ const
char *
gai_strerror(int ecode)
{
- if (ecode < 0 || ecode > EAI_MAX)
- ecode = EAI_MAX;
- return (char *)ai_errlist[ecode];
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return (char *)ai_errlist[ecode];
}
#endif
void
freeaddrinfo(struct addrinfo *ai)
{
- struct addrinfo *next;
-
- do {
- next = ai->ai_next;
- if (ai->ai_canonname)
- free(ai->ai_canonname);
- /* no need to free(ai->ai_addr) */
- free(ai);
- } while ((ai = next) != NULL);
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ } while ((ai = next) != NULL);
}
static int
str_isnumber(const char *p)
{
- char *q = (char *)p;
- while (*q) {
- if (! isdigit(*q))
- return NO;
- q++;
- }
- return YES;
+ char *q = (char *)p;
+ while (*q) {
+ if (! isdigit(*q))
+ return NO;
+ q++;
+ }
+ return YES;
}
#ifndef HAVE_INET_PTON
@@ -243,435 +243,435 @@ str_isnumber(const char *p)
static int
inet_pton(int af, const char *hostname, void *pton)
{
- struct in_addr in;
+ struct in_addr in;
#ifdef HAVE_INET_ATON
- if (!inet_aton(hostname, &in))
- return 0;
+ if (!inet_aton(hostname, &in))
+ return 0;
#else
- int d1, d2, d3, d4;
- char ch;
-
- if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
- 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
- 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
- in.s_addr = htonl(
- ((long) d1 << 24) | ((long) d2 << 16) |
- ((long) d3 << 8) | ((long) d4 << 0));
- }
- else {
- return 0;
- }
-#endif
- memcpy(pton, &in, sizeof(in));
- return 1;
+ int d1, d2, d3, d4;
+ char ch;
+
+ if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
+ 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
+ 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
+ in.s_addr = htonl(
+ ((long) d1 << 24) | ((long) d2 << 16) |
+ ((long) d3 << 8) | ((long) d4 << 0));
+ }
+ else {
+ return 0;
+ }
+#endif
+ memcpy(pton, &in, sizeof(in));
+ return 1;
}
#endif
int
getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
{
- struct addrinfo sentinel;
- struct addrinfo *top = NULL;
- struct addrinfo *cur;
- int i, error = 0;
- char pton[PTON_MAX];
- struct addrinfo ai;
- struct addrinfo *pai;
- u_short port;
+ struct addrinfo sentinel;
+ struct addrinfo *top = NULL;
+ struct addrinfo *cur;
+ int i, error = 0;
+ char pton[PTON_MAX];
+ struct addrinfo ai;
+ struct addrinfo *pai;
+ u_short port;
#ifdef FAITH
- static int firsttime = 1;
-
- if (firsttime) {
- /* translator hack */
- {
- char *q = getenv("GAI");
- if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
- translate = YES;
- }
- firsttime = 0;
- }
-#endif
-
- /* initialize file static vars */
- sentinel.ai_next = NULL;
- cur = &sentinel;
- pai = &ai;
- pai->ai_flags = 0;
- pai->ai_family = PF_UNSPEC;
- pai->ai_socktype = ANY;
- pai->ai_protocol = ANY;
- pai->ai_addrlen = 0;
- pai->ai_canonname = NULL;
- pai->ai_addr = NULL;
- pai->ai_next = NULL;
- port = ANY;
-
- if (hostname == NULL && servname == NULL)
- return EAI_NONAME;
- if (hints) {
- /* error check for hints */
- if (hints->ai_addrlen || hints->ai_canonname ||
- hints->ai_addr || hints->ai_next)
- ERR(EAI_BADHINTS); /* xxx */
- if (hints->ai_flags & ~AI_MASK)
- ERR(EAI_BADFLAGS);
- switch (hints->ai_family) {
- case PF_UNSPEC:
- case PF_INET:
+ static int firsttime = 1;
+
+ if (firsttime) {
+ /* translator hack */
+ {
+ char *q = getenv("GAI");
+ if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
+ translate = YES;
+ }
+ firsttime = 0;
+ }
+#endif
+
+ /* initialize file static vars */
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+ port = ANY;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
#ifdef INET6
- case PF_INET6:
-#endif
- break;
- default:
- ERR(EAI_FAMILY);
- }
- memcpy(pai, hints, sizeof(*pai));
- switch (pai->ai_socktype) {
- case ANY:
- switch (pai->ai_protocol) {
- case ANY:
- break;
- case IPPROTO_UDP:
- pai->ai_socktype = SOCK_DGRAM;
- break;
- case IPPROTO_TCP:
- pai->ai_socktype = SOCK_STREAM;
- break;
- default:
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+ switch (pai->ai_socktype) {
+ case ANY:
+ switch (pai->ai_protocol) {
+ case ANY:
+ break;
+ case IPPROTO_UDP:
+ pai->ai_socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ pai->ai_socktype = SOCK_STREAM;
+ break;
+ default:
#if defined(SOCK_RAW)
- pai->ai_socktype = SOCK_RAW;
+ pai->ai_socktype = SOCK_RAW;
#endif
- break;
- }
- break;
+ break;
+ }
+ break;
#if defined(SOCK_RAW)
- case SOCK_RAW:
- break;
-#endif
- case SOCK_DGRAM:
- if (pai->ai_protocol != IPPROTO_UDP &&
- pai->ai_protocol != ANY)
- ERR(EAI_BADHINTS); /*xxx*/
- pai->ai_protocol = IPPROTO_UDP;
- break;
- case SOCK_STREAM:
- if (pai->ai_protocol != IPPROTO_TCP &&
- pai->ai_protocol != ANY)
- ERR(EAI_BADHINTS); /*xxx*/
- pai->ai_protocol = IPPROTO_TCP;
- break;
- default:
- ERR(EAI_SOCKTYPE);
- break;
- }
- }
-
- /*
- * service port
- */
- if (servname) {
- if (str_isnumber(servname)) {
- if (pai->ai_socktype == ANY) {
- /* caller accept *ANY* socktype */
- pai->ai_socktype = SOCK_DGRAM;
- pai->ai_protocol = IPPROTO_UDP;
- }
- port = htons((unsigned short)atoi(servname));
+ case SOCK_RAW:
+ break;
+#endif
+ case SOCK_DGRAM:
+ if (pai->ai_protocol != IPPROTO_UDP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_UDP;
+ break;
+ case SOCK_STREAM:
+ if (pai->ai_protocol != IPPROTO_TCP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_TCP;
+ break;
+ default:
+ ERR(EAI_SOCKTYPE);
+ break;
+ }
+ }
+
+ /*
+ * service port
+ */
+ if (servname) {
+ if (str_isnumber(servname)) {
+ if (pai->ai_socktype == ANY) {
+ /* caller accept *ANY* socktype */
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ }
+ port = htons((unsigned short)atoi(servname));
} else if (pai->ai_flags & AI_NUMERICSERV) {
ERR(EAI_NONAME);
- } else {
- struct servent *sp;
- const char *proto;
-
- proto = NULL;
- switch (pai->ai_socktype) {
- case ANY:
- proto = NULL;
- break;
- case SOCK_DGRAM:
- proto = "udp";
- break;
- case SOCK_STREAM:
- proto = "tcp";
- break;
- default:
- fprintf(stderr, "panic!\n");
- break;
- }
- if ((sp = getservbyname((char*)servname, proto)) == NULL)
- ERR(EAI_SERVICE);
- port = sp->s_port;
- if (pai->ai_socktype == ANY)
- if (strcmp(sp->s_proto, "udp") == 0) {
- pai->ai_socktype = SOCK_DGRAM;
- pai->ai_protocol = IPPROTO_UDP;
- } else if (strcmp(sp->s_proto, "tcp") == 0) {
- pai->ai_socktype = SOCK_STREAM;
- pai->ai_protocol = IPPROTO_TCP;
- } else
- ERR(EAI_PROTOCOL); /*xxx*/
- }
- }
-
- /*
- * hostname == NULL.
- * passive socket -> anyaddr (0.0.0.0 or ::)
- * non-passive socket -> localhost (127.0.0.1 or ::1)
- */
- if (hostname == NULL) {
- const struct afd *afd;
- int s;
-
- for (afd = &afdl[0]; afd->a_af; afd++) {
- if (!(pai->ai_family == PF_UNSPEC
- || pai->ai_family == afd->a_af)) {
- continue;
- }
-
- /*
- * filter out AFs that are not supported by the kernel
- * XXX errno?
- */
- s = socket(afd->a_af, SOCK_DGRAM, 0);
- if (s < 0)
- continue;
-
- close(s);
-
- if (pai->ai_flags & AI_PASSIVE) {
- GET_AI(cur->ai_next, afd, afd->a_addrany, port);
- /* xxx meaningless?
- * GET_CANONNAME(cur->ai_next, "anyaddr");
- */
- } else {
- GET_AI(cur->ai_next, afd, afd->a_loopback,
- port);
- /* xxx meaningless?
- * GET_CANONNAME(cur->ai_next, "localhost");
- */
- }
- cur = cur->ai_next;
- }
- top = sentinel.ai_next;
- if (top)
- goto good;
- else
- ERR(EAI_FAMILY);
- }
-
- /* hostname as numeric name */
- for (i = 0; afdl[i].a_af; i++) {
- if (inet_pton(afdl[i].a_af, hostname, pton)) {
- u_long v4a;
+ } else {
+ struct servent *sp;
+ const char *proto;
+
+ proto = NULL;
+ switch (pai->ai_socktype) {
+ case ANY:
+ proto = NULL;
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ fprintf(stderr, "panic!\n");
+ break;
+ }
+ if ((sp = getservbyname((char*)servname, proto)) == NULL)
+ ERR(EAI_SERVICE);
+ port = sp->s_port;
+ if (pai->ai_socktype == ANY)
+ if (strcmp(sp->s_proto, "udp") == 0) {
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(sp->s_proto, "tcp") == 0) {
+ pai->ai_socktype = SOCK_STREAM;
+ pai->ai_protocol = IPPROTO_TCP;
+ } else
+ ERR(EAI_PROTOCOL); /*xxx*/
+ }
+ }
+
+ /*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+ if (hostname == NULL) {
+ const struct afd *afd;
+ int s;
+
+ for (afd = &afdl[0]; afd->a_af; afd++) {
+ if (!(pai->ai_family == PF_UNSPEC
+ || pai->ai_family == afd->a_af)) {
+ continue;
+ }
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(afd->a_af, SOCK_DGRAM, 0);
+ if (s < 0)
+ continue;
+
+ close(s);
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(cur->ai_next, afd, afd->a_addrany, port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ */
+ } else {
+ GET_AI(cur->ai_next, afd, afd->a_loopback,
+ port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ }
+ cur = cur->ai_next;
+ }
+ top = sentinel.ai_next;
+ if (top)
+ goto good;
+ else
+ ERR(EAI_FAMILY);
+ }
+
+ /* hostname as numeric name */
+ for (i = 0; afdl[i].a_af; i++) {
+ if (inet_pton(afdl[i].a_af, hostname, pton)) {
+ u_long v4a;
#ifdef INET6
- u_char pfx;
-#endif
-
- switch (afdl[i].a_af) {
- case AF_INET:
- v4a = ((struct in_addr *)pton)->s_addr;
- if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
- pai->ai_flags &= ~AI_CANONNAME;
- v4a >>= IN_CLASSA_NSHIFT;
- if (v4a == 0 || v4a == IN_LOOPBACKNET)
- pai->ai_flags &= ~AI_CANONNAME;
- break;
+ u_char pfx;
+#endif
+
+ switch (afdl[i].a_af) {
+ case AF_INET:
+ v4a = ((struct in_addr *)pton)->s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ pai->ai_flags &= ~AI_CANONNAME;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
#ifdef INET6
- case AF_INET6:
- pfx = ((struct in6_addr *)pton)->s6_addr[0];
- if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
- pai->ai_flags &= ~AI_CANONNAME;
- break;
-#endif
- }
-
- if (pai->ai_family == afdl[i].a_af ||
- pai->ai_family == PF_UNSPEC) {
- if (! (pai->ai_flags & AI_CANONNAME)) {
- GET_AI(top, &afdl[i], pton, port);
- goto good;
- }
- /*
- * if AI_CANONNAME and if reverse lookup
- * fail, return ai anyway to pacify
- * calling application.
- *
- * XXX getaddrinfo() is a name->address
- * translation function, and it looks strange
- * that we do addr->name translation here.
- */
- get_name(pton, &afdl[i], &top, pton, pai, port);
- goto good;
- } else
- ERR(EAI_FAMILY); /*xxx*/
- }
- }
-
- if (pai->ai_flags & AI_NUMERICHOST)
- ERR(EAI_NONAME);
-
- /* hostname as alphabetical name */
- error = get_addr(hostname, pai->ai_family, &top, pai, port);
- if (error == 0) {
- if (top) {
+ case AF_INET6:
+ pfx = ((struct in6_addr *)pton)->s6_addr[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#endif
+ }
+
+ if (pai->ai_family == afdl[i].a_af ||
+ pai->ai_family == PF_UNSPEC) {
+ if (! (pai->ai_flags & AI_CANONNAME)) {
+ GET_AI(top, &afdl[i], pton, port);
+ goto good;
+ }
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks strange
+ * that we do addr->name translation here.
+ */
+ get_name(pton, &afdl[i], &top, pton, pai, port);
+ goto good;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+ }
+
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ /* hostname as alphabetical name */
+ error = get_addr(hostname, pai->ai_family, &top, pai, port);
+ if (error == 0) {
+ if (top) {
good:
- *res = top;
- return SUCCESS;
- } else
- error = EAI_FAIL;
- }
+ *res = top;
+ return SUCCESS;
+ } else
+ error = EAI_FAIL;
+ }
free:
- if (top)
- freeaddrinfo(top);
+ if (top)
+ freeaddrinfo(top);
bad:
- *res = NULL;
- return error;
+ *res = NULL;
+ return error;
}
static int
get_name(const char *addr, const struct afd *afd, struct addrinfo **res, char *numaddr, struct addrinfo *pai, int port0)
{
- u_short port = port0 & 0xffff;
- struct hostent *hp;
- struct addrinfo *cur;
- int error = 0;
+ u_short port = port0 & 0xffff;
+ struct hostent *hp;
+ struct addrinfo *cur;
+ int error = 0;
#ifdef INET6
- int h_error;
+ int h_error;
#endif
#ifdef INET6
- hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
#else
- hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET);
+ hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET);
#endif
- if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
- GET_AI(cur, afd, hp->h_addr_list[0], port);
- GET_CANONNAME(cur, hp->h_name);
- } else
- GET_AI(cur, afd, numaddr, port);
+ if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+ GET_AI(cur, afd, hp->h_addr_list[0], port);
+ GET_CANONNAME(cur, hp->h_name);
+ } else
+ GET_AI(cur, afd, numaddr, port);
#ifdef INET6
- if (hp)
- freehostent(hp);
+ if (hp)
+ freehostent(hp);
#endif
- *res = cur;
- return SUCCESS;
+ *res = cur;
+ return SUCCESS;
free:
- if (cur)
- freeaddrinfo(cur);
+ if (cur)
+ freeaddrinfo(cur);
#ifdef INET6
- if (hp)
- freehostent(hp);
+ if (hp)
+ freehostent(hp);
#endif
/* bad: */
- *res = NULL;
- return error;
+ *res = NULL;
+ return error;
}
static int
get_addr(const char *hostname, int af, struct addrinfo **res, struct addrinfo *pai, int port0)
{
- u_short port = port0 & 0xffff;
- struct addrinfo sentinel;
- struct hostent *hp;
- struct addrinfo *top, *cur;
- const struct afd *afd;
- int i, error = 0, h_error;
- char *ap;
-
- top = NULL;
- sentinel.ai_next = NULL;
- cur = &sentinel;
+ u_short port = port0 & 0xffff;
+ struct addrinfo sentinel;
+ struct hostent *hp;
+ struct addrinfo *top, *cur;
+ const struct afd *afd;
+ int i, error = 0, h_error;
+ char *ap;
+
+ top = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
#ifdef INET6
- if (af == AF_UNSPEC) {
- hp = getipnodebyname(hostname, AF_INET6,
- AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
- } else
- hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
+ if (af == AF_UNSPEC) {
+ hp = getipnodebyname(hostname, AF_INET6,
+ AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
+ } else
+ hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
#else
- if (strlen(hostname) >= NI_MAXHOST) ERR(EAI_NODATA);
- hp = gethostbyname((char*)hostname);
- h_error = h_errno;
-#endif
- if (hp == NULL) {
- switch (h_error) {
- case HOST_NOT_FOUND:
- case NO_DATA:
- error = EAI_NODATA;
- break;
- case TRY_AGAIN:
- error = EAI_AGAIN;
- break;
- case NO_RECOVERY:
- default:
- error = EAI_FAIL;
- break;
- }
- goto bad;
- }
-
- if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
- (hp->h_addr_list[0] == NULL))
- ERR(EAI_FAIL);
-
- for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
- switch (af) {
+ if (strlen(hostname) >= NI_MAXHOST) ERR(EAI_NODATA);
+ hp = gethostbyname((char*)hostname);
+ h_error = h_errno;
+#endif
+ if (hp == NULL) {
+ switch (h_error) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NODATA;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ default:
+ error = EAI_FAIL;
+ break;
+ }
+ goto bad;
+ }
+
+ if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
+ (hp->h_addr_list[0] == NULL))
+ ERR(EAI_FAIL);
+
+ for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
+ switch (af) {
#ifdef INET6
- case AF_INET6:
- afd = &afdl[N_INET6];
- break;
+ case AF_INET6:
+ afd = &afdl[N_INET6];
+ break;
#endif
#ifndef INET6
- default: /* AF_UNSPEC */
+ default: /* AF_UNSPEC */
#endif
- case AF_INET:
- afd = &afdl[N_INET];
- break;
+ case AF_INET:
+ afd = &afdl[N_INET];
+ break;
#ifdef INET6
- default: /* AF_UNSPEC */
- if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
- ap += sizeof(struct in6_addr) -
- sizeof(struct in_addr);
- afd = &afdl[N_INET];
- } else
- afd = &afdl[N_INET6];
- break;
-#endif
- }
+ default: /* AF_UNSPEC */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ ap += sizeof(struct in6_addr) -
+ sizeof(struct in_addr);
+ afd = &afdl[N_INET];
+ } else
+ afd = &afdl[N_INET6];
+ break;
+#endif
+ }
#ifdef FAITH
- if (translate && afd->a_af == AF_INET) {
- struct in6_addr *in6;
-
- GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
- in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
- memcpy(&in6->s6_addr, &faith_prefix,
- sizeof(struct in6_addr) - sizeof(struct in_addr));
- memcpy(&in6->s6_addr + sizeof(struct in_addr), ap,
- sizeof(struct in_addr));
- } else
+ if (translate && afd->a_af == AF_INET) {
+ struct in6_addr *in6;
+
+ GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
+ in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
+ memcpy(&in6->s6_addr, &faith_prefix,
+ sizeof(struct in6_addr) - sizeof(struct in_addr));
+ memcpy(&in6->s6_addr + sizeof(struct in_addr), ap,
+ sizeof(struct in_addr));
+ } else
#endif /* FAITH */
- GET_AI(cur->ai_next, afd, ap, port);
- if (cur == &sentinel) {
- top = cur->ai_next;
- GET_CANONNAME(top, hp->h_name);
- }
- cur = cur->ai_next;
- }
+ GET_AI(cur->ai_next, afd, ap, port);
+ if (cur == &sentinel) {
+ top = cur->ai_next;
+ GET_CANONNAME(top, hp->h_name);
+ }
+ cur = cur->ai_next;
+ }
#ifdef INET6
- freehostent(hp);
+ freehostent(hp);
#endif
- *res = top;
- return SUCCESS;
+ *res = top;
+ return SUCCESS;
free:
- if (top)
- freeaddrinfo(top);
+ if (top)
+ freeaddrinfo(top);
#ifdef INET6
- if (hp)
- freehostent(hp);
+ if (hp)
+ freehostent(hp);
#endif
bad:
- *res = NULL;
- return error;
+ *res = NULL;
+ return error;
}
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index 94a5eb9439..ae5284fab6 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -84,30 +84,30 @@ typedef int socklen_t;
#define NO 0
struct sockinet {
- u_char si_len;
- u_char si_family;
- u_short si_port;
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
};
static struct afd {
- int a_af;
- int a_addrlen;
- int a_socklen;
- int a_off;
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
} afdl [] = {
#ifdef INET6
#define N_INET6 0
- {PF_INET6, sizeof(struct in6_addr),
- sizeof(struct sockaddr_in6),
- offsetof(struct sockaddr_in6, sin6_addr)},
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
#define N_INET 1
#else
#define N_INET 0
#endif
- {PF_INET, sizeof(struct in_addr),
- sizeof(struct sockaddr_in),
- offsetof(struct sockaddr_in, sin_addr)},
- {0, 0, 0, 0},
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0, 0},
};
#define ENI_NOSOCKET 0
@@ -121,123 +121,123 @@ static struct afd {
int
getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
{
- struct afd *afd;
- struct hostent *hp;
- u_short port;
- int family, len, i;
- char *addr, *p;
- u_long v4a;
+ struct afd *afd;
+ struct hostent *hp;
+ u_short port;
+ int family, len, i;
+ char *addr, *p;
+ u_long v4a;
#ifdef INET6
- u_char pfx;
+ u_char pfx;
#endif
- int h_error;
- char numserv[512];
- char numaddr[512];
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
- if (sa == NULL)
- return ENI_NOSOCKET;
+ if (sa == NULL)
+ return ENI_NOSOCKET;
- if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN;
+ if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN;
len = salen;
- family = sa->sa_family;
- for (i = 0; afdl[i].a_af; i++)
- if (afdl[i].a_af == family) {
- afd = &afdl[i];
- goto found;
- }
- return ENI_FAMILY;
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return ENI_FAMILY;
found:
- if (len != afd->a_socklen) return ENI_SALEN;
-
- port = ((struct sockinet *)sa)->si_port; /* network byte order */
- addr = (char *)sa + afd->a_off;
-
- if (serv == NULL || servlen == 0) {
- /* what we should do? */
- } else if (flags & NI_NUMERICSERV) {
- snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
- if (strlen(numserv) + 1 > servlen)
- return ENI_MEMORY;
- strcpy(serv, numserv);
- } else {
+ if (len != afd->a_socklen) return ENI_SALEN;
+
+ port = ((struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /* what we should do? */
+ } else if (flags & NI_NUMERICSERV) {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if (strlen(numserv) + 1 > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, numserv);
+ } else {
#if defined(HAVE_GETSERVBYPORT)
- struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
- if (sp) {
- if (strlen(sp->s_name) + 1 > servlen)
- return ENI_MEMORY;
- strcpy(serv, sp->s_name);
- } else
- return ENI_NOSERVNAME;
+ struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
+ if (sp) {
+ if (strlen(sp->s_name) + 1 > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, sp->s_name);
+ } else
+ return ENI_NOSERVNAME;
#else
- return ENI_NOSERVNAME;
-#endif
- }
-
- switch (sa->sa_family) {
- case AF_INET:
- v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
- if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
- flags |= NI_NUMERICHOST;
- v4a >>= IN_CLASSA_NSHIFT;
- if (v4a == 0)
- flags |= NI_NUMERICHOST;
- break;
+ return ENI_NOSERVNAME;
+#endif
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0)
+ flags |= NI_NUMERICHOST;
+ break;
#ifdef INET6
- case AF_INET6:
+ case AF_INET6:
#ifdef HAVE_ADDR8
- pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
#else
- pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
-#endif
- if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
- flags |= NI_NUMERICHOST;
- break;
-#endif
- }
- if (host == NULL || hostlen == 0) {
- /* what should we do? */
- } else if (flags & NI_NUMERICHOST) {
- if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
- == NULL)
- return ENI_SYSTEM;
- if (strlen(numaddr) > hostlen)
- return ENI_MEMORY;
- strcpy(host, numaddr);
- } else {
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
+#endif
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ flags |= NI_NUMERICHOST;
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /* what should we do? */
+ } else if (flags & NI_NUMERICHOST) {
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_SYSTEM;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ } else {
#ifdef INET6
- hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
#else
- hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
- h_error = h_errno;
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ h_error = h_errno;
#endif
- if (hp) {
- if (flags & NI_NOFQDN) {
- p = strchr(hp->h_name, '.');
- if (p) *p = '\0';
- }
- if (strlen(hp->h_name) + 1 > hostlen) {
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlen(hp->h_name) + 1 > hostlen) {
#ifdef INET6
- freehostent(hp);
+ freehostent(hp);
#endif
- return ENI_MEMORY;
- }
- strcpy(host, hp->h_name);
+ return ENI_MEMORY;
+ }
+ strcpy(host, hp->h_name);
#ifdef INET6
- freehostent(hp);
-#endif
- } else {
- if (flags & NI_NAMEREQD)
- return ENI_NOHOSTNAME;
- if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
- == NULL)
- return ENI_NOHOSTNAME;
- if (strlen(numaddr) > hostlen)
- return ENI_MEMORY;
- strcpy(host, numaddr);
- }
- }
- return SUCCESS;
+ freehostent(hp);
+#endif
+ } else {
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_NOHOSTNAME;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ }
+ }
+ return SUCCESS;
}
diff --git a/ext/socket/ifaddr.c b/ext/socket/ifaddr.c
index da013256cb..ab163dcc8f 100644
--- a/ext/socket/ifaddr.c
+++ b/ext/socket/ifaddr.c
@@ -104,7 +104,7 @@ rsock_getifaddrs(void)
rb_sys_fail("getifaddrs");
if (!ifaddrs) {
- return rb_ary_new();
+ return rb_ary_new();
}
numifaddrs = 0;
@@ -128,9 +128,9 @@ rsock_getifaddrs(void)
result = rb_ary_new2(numifaddrs);
rb_ary_push(result, addr);
for (i = 1; i < numifaddrs; i++) {
- addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i]);
- root->refcount++;
- rb_ary_push(result, addr);
+ addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i]);
+ root->refcount++;
+ rb_ary_push(result, addr);
}
return result;
@@ -460,6 +460,7 @@ rsock_init_sockifaddr(void)
* Socket::Ifaddr represents a result of getifaddrs() function.
*/
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 359696e626..557d4374a5 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -41,7 +41,7 @@ rsock_raise_socket_error(const char *reason, int error)
#ifdef EAI_SYSTEM
int e;
if (error == EAI_SYSTEM && (e = errno) != 0)
- rb_syserr_fail(e, reason);
+ rb_syserr_fail(e, reason);
#endif
#ifdef _WIN32
rb_encoding *enc = rb_default_internal_encoding();
@@ -71,7 +71,7 @@ rsock_init_sock(VALUE sock, int fd)
fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
rb_io_ascii8bit_binmode(sock);
if (rsock_do_not_reverse_lookup) {
- fp->mode |= FMODE_NOREVLOOKUP;
+ fp->mode |= FMODE_NOREVLOOKUP;
}
rb_io_synchronized(fp);
@@ -85,7 +85,7 @@ rsock_sendto_blocking(void *data)
VALUE mesg = arg->mesg;
ssize_t ret;
do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
- arg->flags, arg->to, arg->tolen));
+ arg->flags, arg->to, arg->tolen));
return (VALUE)ret;
}
@@ -96,7 +96,7 @@ rsock_send_blocking(void *data)
VALUE mesg = arg->mesg;
ssize_t ret;
do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
- arg->flags));
+ arg->flags));
return (VALUE)ret;
}
@@ -132,9 +132,9 @@ rsock_strbuf(VALUE str, long buflen)
StringValue(str);
len = RSTRING_LEN(str);
if (len >= buflen) {
- rb_str_modify(str);
+ rb_str_modify(str);
} else {
- rb_str_modify_expand(str, buflen - len);
+ rb_str_modify_expand(str, buflen - len);
}
return str;
}
@@ -189,7 +189,7 @@ rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from)
if (slen >= 0) break;
- if (!rb_io_maybe_wait_readable(errno, socket, Qnil))
+ if (!rb_io_maybe_wait_readable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT))
rb_sys_fail("recvfrom(2)");
}
@@ -197,32 +197,32 @@ rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from)
rb_str_set_len(str, slen);
switch (from) {
case RECV_RECV:
- return str;
+ return str;
case RECV_IP:
#if 0
- if (arg.alen != sizeof(struct sockaddr_in)) {
- rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
- }
+ if (arg.alen != sizeof(struct sockaddr_in)) {
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
+ }
#endif
- if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
- return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP));
- else
- return rb_assoc_new(str, Qnil);
+ if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
+ return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP));
+ else
+ return rb_assoc_new(str, Qnil);
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case RECV_UNIX:
return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen));
#endif
case RECV_SOCKET:
- return rb_assoc_new(str, rsock_io_socket_addrinfo(socket, &arg.buf.addr, arg.alen));
+ return rb_assoc_new(str, rsock_io_socket_addrinfo(socket, &arg.buf.addr, arg.alen));
default:
- rb_bug("rsock_s_recvfrom called with bad value");
+ rb_bug("rsock_s_recvfrom called with bad value");
}
}
VALUE
rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
- VALUE ex, enum sock_recv_type from)
+ VALUE ex, enum sock_recv_type from)
{
rb_io_t *fptr;
union_sockaddr buf;
@@ -245,14 +245,14 @@ rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
GetOpenFile(sock, fptr);
if (rb_io_read_pending(fptr)) {
- rb_raise(rb_eIOError, "recvfrom for buffered IO");
+ rb_raise(rb_eIOError, "recvfrom for buffered IO");
}
fd = fptr->fd;
rb_io_check_closed(fptr);
if (!MSG_DONTWAIT_RELIABLE)
- rb_io_set_nonblock(fptr);
+ rb_io_set_nonblock(fptr);
len0 = alen;
slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, &buf.addr, &alen);
@@ -260,20 +260,20 @@ rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
alen = len0;
if (slen < 0) {
- int e = errno;
- switch (e) {
- case EAGAIN:
+ int e = errno;
+ switch (e) {
+ case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
+ case EWOULDBLOCK:
#endif
if (ex == Qfalse)
- return sym_wait_readable;
+ return sym_wait_readable;
rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvfrom(2) would block");
- }
- rb_syserr_fail(e, "recvfrom(2)");
+ }
+ rb_syserr_fail(e, "recvfrom(2)");
}
if (slen != RSTRING_LEN(str)) {
- rb_str_set_len(str, slen);
+ rb_str_set_len(str, slen);
}
switch (from) {
case RECV_RECV:
@@ -324,31 +324,31 @@ rsock_read_nonblock(VALUE sock, VALUE length, VALUE buf, VALUE ex)
GetOpenFile(sock, fptr);
if (len == 0) {
- rb_str_set_len(str, 0);
- return str;
+ rb_str_set_len(str, 0);
+ return str;
}
ptr = RSTRING_PTR(str);
n = read_buffered_data(ptr, len, fptr);
if (n <= 0) {
- n = (long)recv(fptr->fd, ptr, len, MSG_DONTWAIT);
- if (n < 0) {
- int e = errno;
- if ((e == EWOULDBLOCK || e == EAGAIN)) {
- if (ex == Qfalse) return sym_wait_readable;
- rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
- e, "read would block");
- }
- rb_syserr_fail_path(e, fptr->pathv);
- }
+ n = (long)recv(fptr->fd, ptr, len, MSG_DONTWAIT);
+ if (n < 0) {
+ int e = errno;
+ if ((e == EWOULDBLOCK || e == EAGAIN)) {
+ if (ex == Qfalse) return sym_wait_readable;
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
+ e, "read would block");
+ }
+ rb_syserr_fail_path(e, fptr->pathv);
+ }
}
if (n != RSTRING_LEN(str)) {
- rb_str_modify(str);
- rb_str_set_len(str, n);
+ rb_str_modify(str);
+ rb_str_set_len(str, n);
}
if (n == 0) {
- if (ex == Qfalse) return Qnil;
- rb_eof_error();
+ if (ex == Qfalse) return Qnil;
+ rb_eof_error();
}
return str;
@@ -362,7 +362,7 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
long n;
if (!RB_TYPE_P(str, T_STRING))
- str = rb_obj_as_string(str);
+ str = rb_obj_as_string(str);
sock = rb_io_get_write_io(sock);
GetOpenFile(sock, fptr);
@@ -374,7 +374,7 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
* are not userspace-buffered in Ruby by default.
*/
if (fptr->wbuf.len > 0) {
- rb_io_flush(sock);
+ rb_io_flush(sock);
}
#ifdef __APPLE__
@@ -382,19 +382,19 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
#endif
n = (long)send(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str), MSG_DONTWAIT);
if (n < 0) {
- int e = errno;
+ int e = errno;
#ifdef __APPLE__
- if (e == EPROTOTYPE) {
- goto again;
- }
-#endif
- if (e == EWOULDBLOCK || e == EAGAIN) {
- if (ex == Qfalse) return sym_wait_writable;
- rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
- "write would block");
- }
- rb_syserr_fail_path(e, fptr->pathv);
+ if (e == EPROTOTYPE) {
+ goto again;
+ }
+#endif
+ if (e == EWOULDBLOCK || e == EAGAIN) {
+ if (ex == Qfalse) return sym_wait_writable;
+ rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
+ "write would block");
+ }
+ rb_syserr_fail_path(e, fptr->pathv);
}
return LONG2FIX(n);
@@ -497,11 +497,11 @@ wait_connectable(int fd, struct timeval *timeout)
* interrupted connect()
*/
- /* when the connection timed out, no errno is set and revents is 0. */
- if (timeout && revents == 0) {
- errno = ETIMEDOUT;
- return -1;
- }
+ /* 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:
@@ -516,7 +516,7 @@ wait_connectable(int fd, struct timeval *timeout)
#ifdef EISCONN
case EISCONN:
#endif
- return 0; /* success */
+ return 0; /* success */
default:
/* likely (but not limited to): ECONNREFUSED, ETIMEDOUT, EHOSTUNREACH */
errno = sockerr;
@@ -634,27 +634,27 @@ cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
VALUE
rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
- struct sockaddr *sockaddr, socklen_t *len)
+ struct sockaddr *sockaddr, socklen_t *len)
{
int fd2;
rb_io_set_nonblock(fptr);
fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len);
if (fd2 < 0) {
- int e = errno;
- switch (e) {
- case EAGAIN:
+ int e = errno;
+ switch (e) {
+ case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
+ case EWOULDBLOCK:
#endif
- case ECONNABORTED:
+ case ECONNABORTED:
#if defined EPROTO
- case EPROTO:
+ case EPROTO:
#endif
if (ex == Qfalse)
- return sym_wait_readable;
+ return sym_wait_readable;
rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "accept(2) would block");
- }
+ }
rb_syserr_fail(e, "accept(2)");
}
rb_update_max_fd(fd2);
@@ -705,7 +705,7 @@ rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len)
retry = 1;
goto retry;
default:
- if (!rb_io_maybe_wait_readable(error, io, Qnil)) break;
+ if (!rb_io_maybe_wait_readable(error, io, RUBY_IO_TIMEOUT_DEFAULT)) break;
retry = 0;
goto retry;
}
@@ -730,11 +730,11 @@ rsock_getfamily(rb_io_t *fptr)
if (cached) {
switch (cached) {
#ifdef AF_UNIX
- case FMODE_UNIX: return AF_UNIX;
+ case FMODE_UNIX: return AF_UNIX;
#endif
- case FMODE_INET: return AF_INET;
- case FMODE_INET6: return AF_INET6;
- }
+ case FMODE_INET: return AF_INET;
+ case FMODE_INET6: return AF_INET6;
+ }
}
ss.addr.sa_family = AF_UNSPEC;
diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c
index b5cdc60080..0c13620258 100644
--- a/ext/socket/ipsocket.c
+++ b/ext/socket/ipsocket.c
@@ -14,8 +14,8 @@ struct inetsock_arg
{
VALUE sock;
struct {
- VALUE host, serv;
- struct rb_addrinfo *res;
+ VALUE host, serv;
+ struct rb_addrinfo *res;
} remote, local;
int type;
int fd;
@@ -28,15 +28,15 @@ inetsock_cleanup(VALUE v)
{
struct inetsock_arg *arg = (void *)v;
if (arg->remote.res) {
- rb_freeaddrinfo(arg->remote.res);
- arg->remote.res = 0;
+ rb_freeaddrinfo(arg->remote.res);
+ arg->remote.res = 0;
}
if (arg->local.res) {
- rb_freeaddrinfo(arg->local.res);
- arg->local.res = 0;
+ rb_freeaddrinfo(arg->local.res);
+ arg->local.res = 0;
}
if (arg->fd >= 0) {
- close(arg->fd);
+ close(arg->fd);
}
return Qnil;
}
@@ -61,8 +61,8 @@ init_inetsock_internal(VALUE v)
}
arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv,
- family, SOCK_STREAM,
- (type == INET_SERVER) ? AI_PASSIVE : 0);
+ family, SOCK_STREAM,
+ (type == INET_SERVER) ? AI_PASSIVE : 0);
/*
@@ -70,15 +70,15 @@ init_inetsock_internal(VALUE v)
*/
if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
- arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv,
- family, SOCK_STREAM, 0);
+ arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv,
+ family, SOCK_STREAM, 0);
}
arg->fd = fd = -1;
for (res = arg->remote.res->ai; res; res = res->ai_next) {
#if !defined(INET6) && defined(AF_INET6)
- if (res->ai_family == AF_INET6)
- continue;
+ if (res->ai_family == AF_INET6)
+ continue;
#endif
lres = NULL;
if (arg->local.res) {
@@ -94,73 +94,73 @@ init_inetsock_internal(VALUE v)
lres = arg->local.res->ai;
}
}
- status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
- syscall = "socket(2)";
- fd = status;
- if (fd < 0) {
- error = errno;
- continue;
- }
- arg->fd = fd;
- if (type == INET_SERVER) {
+ status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
+ syscall = "socket(2)";
+ fd = status;
+ if (fd < 0) {
+ error = errno;
+ continue;
+ }
+ arg->fd = fd;
+ if (type == INET_SERVER) {
#if !defined(_WIN32) && !defined(__CYGWIN__)
- status = 1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char*)&status, (socklen_t)sizeof(status));
+ status = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char*)&status, (socklen_t)sizeof(status));
#endif
- status = bind(fd, res->ai_addr, res->ai_addrlen);
- syscall = "bind(2)";
- }
- else {
- if (lres) {
+ status = bind(fd, res->ai_addr, res->ai_addrlen);
+ syscall = "bind(2)";
+ }
+ else {
+ if (lres) {
#if !defined(_WIN32) && !defined(__CYGWIN__)
status = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char*)&status, (socklen_t)sizeof(status));
#endif
- status = bind(fd, lres->ai_addr, lres->ai_addrlen);
- local = status;
- syscall = "bind(2)";
- }
-
- if (status >= 0) {
- status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
- (type == INET_SOCKS), tv);
- syscall = "connect(2)";
- }
- }
-
- if (status < 0) {
- error = errno;
- close(fd);
- arg->fd = fd = -1;
- continue;
- } else
- break;
+ status = bind(fd, lres->ai_addr, lres->ai_addrlen);
+ local = status;
+ syscall = "bind(2)";
+ }
+
+ if (status >= 0) {
+ status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
+ (type == INET_SOCKS), tv);
+ syscall = "connect(2)";
+ }
+ }
+
+ if (status < 0) {
+ error = errno;
+ close(fd);
+ arg->fd = fd = -1;
+ continue;
+ } else
+ break;
}
if (status < 0) {
- VALUE host, port;
-
- if (local < 0) {
- host = arg->local.host;
- port = arg->local.serv;
- } else {
- host = arg->remote.host;
- port = arg->remote.serv;
- }
+ VALUE host, port;
+
+ if (local < 0) {
+ host = arg->local.host;
+ port = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ port = arg->remote.serv;
+ }
- rsock_syserr_fail_host_port(error, syscall, host, port);
+ rsock_syserr_fail_host_port(error, syscall, host, port);
}
arg->fd = -1;
if (type == INET_SERVER) {
- status = listen(fd, SOMAXCONN);
- if (status < 0) {
- error = errno;
- close(fd);
- rb_syserr_fail(error, "listen(2)");
- }
+ status = listen(fd, SOMAXCONN);
+ if (status < 0) {
+ error = errno;
+ close(fd);
+ rb_syserr_fail(error, "listen(2)");
+ }
}
/* create new instance */
@@ -169,8 +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 resolv_timeout, VALUE connect_timeout)
+ VALUE local_host, VALUE local_serv, int type,
+ VALUE resolv_timeout, VALUE connect_timeout)
{
struct inetsock_arg arg;
arg.sock = sock;
@@ -185,7 +185,7 @@ rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
arg.resolv_timeout = resolv_timeout;
arg.connect_timeout = connect_timeout;
return rb_ensure(init_inetsock_internal, (VALUE)&arg,
- inetsock_cleanup, (VALUE)&arg);
+ inetsock_cleanup, (VALUE)&arg);
}
static ID id_numeric, id_hostname;
@@ -201,11 +201,11 @@ rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
case Qfalse: return_norevlookup(1);
case Qnil: break;
default:
- Check_Type(revlookup, T_SYMBOL);
- id = SYM2ID(revlookup);
- if (id == id_numeric) return_norevlookup(1);
- if (id == id_hostname) return_norevlookup(0);
- rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id));
+ Check_Type(revlookup, T_SYMBOL);
+ id = SYM2ID(revlookup);
+ if (id == id_numeric) return_norevlookup(1);
+ if (id == id_hostname) return_norevlookup(0);
+ rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id));
}
return 0;
#undef return_norevlookup
@@ -226,24 +226,24 @@ ip_inspect(VALUE sock)
socklen_t len = (socklen_t)sizeof addr;
ID id;
if (fptr && fptr->fd >= 0 &&
- getsockname(fptr->fd, &addr.addr, &len) >= 0 &&
- (id = rsock_intern_family(addr.addr.sa_family)) != 0) {
- VALUE family = rb_id2str(id);
- char hbuf[1024], pbuf[1024];
- long slen = RSTRING_LEN(str);
- const char last = (slen > 1 && RSTRING_PTR(str)[slen - 1] == '>') ?
- (--slen, '>') : 0;
- str = rb_str_subseq(str, 0, slen);
- rb_str_cat_cstr(str, ", ");
- rb_str_append(str, family);
- if (!rb_getnameinfo(&addr.addr, len, hbuf, sizeof(hbuf),
- pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
- rb_str_cat_cstr(str, ", ");
- rb_str_cat_cstr(str, hbuf);
- rb_str_cat_cstr(str, ", ");
- rb_str_cat_cstr(str, pbuf);
- }
- if (last) rb_str_cat(str, &last, 1);
+ getsockname(fptr->fd, &addr.addr, &len) >= 0 &&
+ (id = rsock_intern_family(addr.addr.sa_family)) != 0) {
+ VALUE family = rb_id2str(id);
+ char hbuf[1024], pbuf[1024];
+ long slen = RSTRING_LEN(str);
+ const char last = (slen > 1 && RSTRING_PTR(str)[slen - 1] == '>') ?
+ (--slen, '>') : 0;
+ str = rb_str_subseq(str, 0, slen);
+ rb_str_cat_cstr(str, ", ");
+ rb_str_append(str, family);
+ if (!rb_getnameinfo(&addr.addr, len, hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+ rb_str_cat_cstr(str, ", ");
+ rb_str_cat_cstr(str, hbuf);
+ rb_str_cat_cstr(str, ", ");
+ rb_str_cat_cstr(str, pbuf);
+ }
+ if (last) rb_str_cat(str, &last, 1);
}
return str;
}
@@ -282,9 +282,9 @@ ip_addr(int argc, VALUE *argv, VALUE sock)
GetOpenFile(sock, fptr);
if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
- norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
+ norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
if (getsockname(fptr->fd, &addr.addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
+ rb_sys_fail("getsockname(2)");
return rsock_ipaddr(&addr.addr, len, norevlookup);
}
@@ -323,9 +323,9 @@ ip_peeraddr(int argc, VALUE *argv, VALUE sock)
GetOpenFile(sock, fptr);
if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
- norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
+ norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
if (getpeername(fptr->fd, &addr.addr, &len) < 0)
- rb_sys_fail("getpeername(2)");
+ rb_sys_fail("getpeername(2)");
return rsock_ipaddr(&addr.addr, len, norevlookup);
}
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index d756a32a5a..eecdc7d4b8 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -1,7 +1,11 @@
# frozen_string_literal: true
require 'socket.so'
-require 'io/wait'
+
+unless IO.method_defined?(:wait_writable, false)
+ # It's only required on older Rubies < v3.2:
+ require 'io/wait'
+end
class Addrinfo
# creates an Addrinfo object from the arguments.
@@ -197,7 +201,7 @@ class Addrinfo
sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin
sock.ipv6only! if self.ipv6?
- sock.setsockopt(:SOCKET, :REUSEADDR, 1)
+ sock.setsockopt(:SOCKET, :REUSEADDR, 1) unless self.pfamily == Socket::PF_UNIX
sock.bind(self)
sock.listen(backlog)
rescue Exception
@@ -606,7 +610,6 @@ class Socket < BasicSocket
# _opts_ may have following options:
#
# [:connect_timeout] specify the timeout in seconds.
- # [:resolv_timeout] specify the name resolution timeout in seconds.
#
# If a block is given, the block is called with the socket.
# The value of the block is returned.
diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb
index 620a5f60ff..5e6c0668f6 100644
--- a/ext/socket/mkconstants.rb
+++ b/ext/socket/mkconstants.rb
@@ -358,6 +358,8 @@ SOCK_RAW nil A raw socket provides low-level access for direct access or impleme
SOCK_RDM nil A reliable datagram socket provides reliable delivery of messages
SOCK_SEQPACKET nil A sequential packet socket provides sequenced, reliable two-way connection for datagrams
SOCK_PACKET nil Device-level packet access
+SOCK_NONBLOCK nil Set the O_NONBLOCK file status flag on the open file description (see open(2)) referred to by the new file descriptor.
+SOCK_CLOEXEC nil Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor.
AF_UNSPEC nil Unspecified protocol, any supported address family
PF_UNSPEC nil Unspecified protocol, any supported address family
@@ -397,6 +399,8 @@ AF_SNA nil IBM SNA protocol
PF_SNA nil IBM SNA protocol
AF_DEC nil DECnet protocol
PF_DEC nil DECnet protocol
+AF_DECnet nil DECnet protocol
+PF_DECnet nil DECnet protocol
AF_DLI nil DEC Direct Data Link Interface protocol
PF_DLI nil DEC Direct Data Link Interface protocol
AF_LAT nil Local Area Transport protocol
@@ -438,7 +442,34 @@ AF_E164 nil CCITT (ITU-T) E.164 recommendation
PF_XTP nil eXpress Transfer Protocol
PF_RTIP
PF_PIP
-PF_KEY
+AF_KEY nil Key management protocol, originally developed for usage with IPsec
+PF_KEY nil Key management protocol, originally developed for usage with IPsec
+AF_NETLINK nil Kernel user interface device
+PF_NETLINK nil Kernel user interface device
+AF_RDS nil Reliable Datagram Sockets (RDS) protocol
+PF_RDS nil Reliable Datagram Sockets (RDS) protocol
+AF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
+PF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
+AF_LLC nil Logical link control (IEEE 802.2 LLC) protocol
+PF_LLC nil Logical link control (IEEE 802.2 LLC) protocol
+AF_IB nil InfiniBand native addressing
+PF_IB nil InfiniBand native addressing
+AF_MPLS nil Multiprotocol Label Switching
+PF_MPLS nil Multiprotocol Label Switching
+AF_CAN nil Controller Area Network automotive bus protocol
+PF_CAN nil Controller Area Network automotive bus protocol
+AF_TIPC nil TIPC, "cluster domain sockets" protocol
+PF_TIPC nil TIPC, "cluster domain sockets" protocol
+AF_BLUETOOTH nil Bluetooth low-level socket protocol
+PF_BLUETOOTH nil Bluetooth low-level socket protocol
+AF_ALG nil Interface to kernel crypto API
+PF_ALG nil Interface to kernel crypto API
+AF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication
+PF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication
+AF_KCM nil KCM (kernel connection multiplexor) interface
+PF_KCM nil KCM (kernel connection multiplexor) interface
+AF_XDP nil XDP (express data path) interface
+PF_XDP nil XDP (express data path) interface
MSG_OOB nil Process out-of-band data
MSG_PEEK nil Peek at incoming message
@@ -595,6 +626,7 @@ SO_SNDTIMEO nil Send timeout
SO_ACCEPTCONN nil Socket has had listen() called on it
SO_USELOOPBACK nil Bypass hardware when possible
SO_ACCEPTFILTER nil There is an accept filter
+SO_USER_COOKIE nil Setting an identifier for ipfw purpose mainly
SO_DONTTRUNC nil Retain unread data
SO_WANTMORE nil Give a hint when more data is ready
SO_WANTOOBFLAG nil OOB data is wanted in MSG_FLAG on receive
@@ -630,6 +662,10 @@ SO_SELECT_ERR_QUEUE nil Make select() detect socket error queue with err
SO_BUSY_POLL nil Set the threshold in microseconds for low latency polling (Linux 3.11)
SO_MAX_PACING_RATE nil Cap the rate computed by transport layer. [bytes per second] (Linux 3.13)
SO_BPF_EXTENSIONS nil Query supported BPF extensions (Linux 3.14)
+SO_SETFIB nil Set the associated routing table for the socket (FreeBSD)
+SO_RTABLE nil Set the routing table for this socket (OpenBSD)
+SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19)
+SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12)
SOPRI_INTERACTIVE nil Interactive socket priority
SOPRI_NORMAL nil Normal socket priority
@@ -639,9 +675,11 @@ IPX_TYPE
TCP_NODELAY nil Don't delay sending to coalesce packets
TCP_MAXSEG nil Set maximum segment size
+TCP_CONNECTION_INFO nil Retrieve information about this socket (macOS)
TCP_CORK nil Don't send partial frames (Linux 2.2, glibc 2.2)
TCP_DEFER_ACCEPT nil Don't notify a listening socket until data is ready (Linux 2.4, glibc 2.2)
TCP_INFO nil Retrieve information about this socket (Linux 2.4, glibc 2.2)
+TCP_KEEPALIVE nil Idle time before keepalive probes are sent (macOS)
TCP_KEEPCNT nil Maximum number of keepalive probes allowed before dropping a connection (Linux 2.4, glibc 2.2)
TCP_KEEPIDLE nil Idle time before keepalive probes are sent (Linux 2.4, glibc 2.2)
TCP_KEEPINTVL nil Time between keepalive probes (Linux 2.4, glibc 2.2)
diff --git a/ext/socket/option.c b/ext/socket/option.c
index 4b33b3f1d3..0d818d0c70 100644
--- a/ext/socket/option.c
+++ b/ext/socket/option.c
@@ -31,7 +31,7 @@ VALUE rb_cSockOpt;
((len) == (size) ? \
(void)0 : \
rb_raise(rb_eTypeError, "size differ. expected as "#size"=%d but %ld", \
- (int)size, (long)(len)))
+ (int)size, (long)(len)))
static VALUE
sockopt_pack_byte(VALUE value)
@@ -309,7 +309,7 @@ sockopt_bool(VALUE self)
StringValue(data);
len = RSTRING_LEN(data);
if (len == 1) {
- return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue;
+ return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue;
}
check_size(len, sizeof(int));
memcpy((char*)&i, RSTRING_PTR(data), len);
@@ -420,7 +420,7 @@ sockopt_ipv4_multicast_loop(VALUE self)
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) {
- return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self);
+ return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self);
}
#endif
rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected");
@@ -471,7 +471,7 @@ sockopt_ipv4_multicast_ttl(VALUE self)
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) {
- return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self);
+ return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self);
}
#endif
rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected");
@@ -657,8 +657,8 @@ inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
#else
unsigned long x = ntohl(*(unsigned long*)addr);
snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
- (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
- (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
#endif
return numaddr;
}
@@ -670,10 +670,10 @@ rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int
{
#if defined(HAVE_IF_INDEXTONAME)
char ifbuf[IFNAMSIZ];
- if (if_indextoname(ifindex, ifbuf) == NULL)
- return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
- else
+ if (if_indextoname(ifindex, ifbuf))
return snprintf(buf, len, "%s%s", succ_prefix, ifbuf);
+ else
+ return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
#else
# ifndef IFNAMSIZ
# define IFNAMSIZ (sizeof(unsigned int)*3+1)
@@ -1059,16 +1059,16 @@ inspect_tcp_info(int level, int optname, VALUE data, VALUE ret)
rb_str_catf(ret, " fackets=%u", s.tcpi_fackets);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_SENT
- inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent);
+ inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_SENT
- inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent);
+ inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_RECV
- inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv);
+ inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_RECV
- inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv);
+ inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_PMTU
rb_str_catf(ret, " pmtu=%u", s.tcpi_pmtu);
@@ -1077,10 +1077,10 @@ inspect_tcp_info(int level, int optname, VALUE data, VALUE ret)
rb_str_catf(ret, " rcv_ssthresh=%u", s.tcpi_rcv_ssthresh);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTT
- inspect_tcpi_rtt(ret, s.tcpi_rtt);
+ inspect_tcpi_rtt(ret, s.tcpi_rtt);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTTVAR
- inspect_tcpi_rttvar(ret, s.tcpi_rttvar);
+ inspect_tcpi_rttvar(ret, s.tcpi_rttvar);
#endif
#ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_SSTHRESH
rb_str_catf(ret, " snd_ssthresh=%u", s.tcpi_snd_ssthresh);
@@ -1150,7 +1150,7 @@ inspect_peercred(int level, int optname, VALUE data, VALUE ret)
RUBY_SOCK_PEERCRED cred;
memcpy(&cred, RSTRING_PTR(data), sizeof(RUBY_SOCK_PEERCRED));
rb_str_catf(ret, " pid=%u euid=%u egid=%u",
- (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid);
+ (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid);
rb_str_cat2(ret, " (ucred)");
return 1;
}
@@ -1171,14 +1171,14 @@ inspect_local_peercred(int level, int optname, VALUE data, VALUE ret)
return 0;
rb_str_catf(ret, " version=%u", cred.cr_version);
rb_str_catf(ret, " euid=%u", cred.cr_uid);
- if (cred.cr_ngroups) {
- int i;
- const char *sep = " groups=";
- for (i = 0; i < cred.cr_ngroups; i++) {
- rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]);
- sep = ",";
- }
- }
+ if (cred.cr_ngroups) {
+ int i;
+ const char *sep = " groups=";
+ for (i = 0; i < cred.cr_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]);
+ sep = ",";
+ }
+ }
rb_str_cat2(ret, " (xucred)");
return 1;
}
@@ -1216,42 +1216,42 @@ sockopt_inspect(VALUE self)
family_id = rsock_intern_family_noprefix(family);
if (family_id)
- rb_str_catf(ret, " %s", rb_id2name(family_id));
+ rb_str_catf(ret, " %s", rb_id2name(family_id));
else
rb_str_catf(ret, " family:%d", family);
if (level == SOL_SOCKET) {
rb_str_cat2(ret, " SOCKET");
- optname_id = rsock_intern_so_optname(optname);
- if (optname_id)
- rb_str_catf(ret, " %s", rb_id2name(optname_id));
- else
- rb_str_catf(ret, " optname:%d", optname);
+ optname_id = rsock_intern_so_optname(optname);
+ if (optname_id)
+ rb_str_catf(ret, " %s", rb_id2name(optname_id));
+ else
+ rb_str_catf(ret, " optname:%d", optname);
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
else if (family == AF_UNIX) {
- rb_str_catf(ret, " level:%d", level);
+ rb_str_catf(ret, " level:%d", level);
- optname_id = rsock_intern_local_optname(optname);
- if (optname_id)
- rb_str_catf(ret, " %s", rb_id2name(optname_id));
- else
- rb_str_catf(ret, " optname:%d", optname);
+ optname_id = rsock_intern_local_optname(optname);
+ if (optname_id)
+ rb_str_catf(ret, " %s", rb_id2name(optname_id));
+ else
+ rb_str_catf(ret, " optname:%d", optname);
}
#endif
else if (IS_IP_FAMILY(family)) {
- level_id = rsock_intern_iplevel(level);
- if (level_id)
- rb_str_catf(ret, " %s", rb_id2name(level_id));
- else
- rb_str_catf(ret, " level:%d", level);
-
- v = optname_to_sym(level, optname);
- if (SYMBOL_P(v))
- rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(v));
- else
- rb_str_catf(ret, " optname:%d", optname);
+ level_id = rsock_intern_iplevel(level);
+ if (level_id)
+ rb_str_catf(ret, " %s", rb_id2name(level_id));
+ else
+ rb_str_catf(ret, " level:%d", level);
+
+ v = optname_to_sym(level, optname);
+ if (SYMBOL_P(v))
+ rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(v));
+ else
+ rb_str_catf(ret, " optname:%d", optname);
}
else {
rb_str_catf(ret, " level:%d", level);
@@ -1393,7 +1393,7 @@ sockopt_inspect(VALUE self)
}
break;
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case AF_UNIX:
switch (level) {
case 0:
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index d94e96a2bc..45b4cad38f 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -24,28 +24,28 @@ static const int lookup_order_table[] = {
static int
ruby_getaddrinfo(const char *nodename, const char *servname,
- const struct addrinfo *hints, struct addrinfo **res)
+ const struct addrinfo *hints, struct addrinfo **res)
{
struct addrinfo tmp_hints;
int i, af, error;
if (hints->ai_family != PF_UNSPEC) {
- return getaddrinfo(nodename, servname, hints, res);
+ return getaddrinfo(nodename, servname, hints, res);
}
for (i = 0; i < LOOKUP_ORDERS; i++) {
- af = lookup_order_table[i];
- MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
- tmp_hints.ai_family = af;
- error = getaddrinfo(nodename, servname, &tmp_hints, res);
- if (error) {
- if (tmp_hints.ai_family == PF_UNSPEC) {
- break;
- }
- }
- else {
- break;
- }
+ af = lookup_order_table[i];
+ MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
+ tmp_hints.ai_family = af;
+ error = getaddrinfo(nodename, servname, &tmp_hints, res);
+ if (error) {
+ if (tmp_hints.ai_family == PF_UNSPEC) {
+ break;
+ }
+ }
+ else {
+ break;
+ }
}
return error;
@@ -56,17 +56,17 @@ ruby_getaddrinfo(const char *nodename, const char *servname,
#if defined(_AIX)
static int
ruby_getaddrinfo__aix(const char *nodename, const char *servname,
- const struct addrinfo *hints, struct addrinfo **res)
+ const struct addrinfo *hints, struct addrinfo **res)
{
int error = getaddrinfo(nodename, servname, hints, res);
struct addrinfo *r;
if (error)
- return error;
+ return error;
for (r = *res; r != NULL; r = r->ai_next) {
- if (r->ai_addr->sa_family == 0)
- r->ai_addr->sa_family = r->ai_family;
- if (r->ai_addr->sa_len == 0)
- r->ai_addr->sa_len = r->ai_addrlen;
+ if (r->ai_addr->sa_family == 0)
+ r->ai_addr->sa_family = r->ai_family;
+ if (r->ai_addr->sa_len == 0)
+ r->ai_addr->sa_len = r->ai_addrlen;
}
return 0;
}
@@ -74,21 +74,21 @@ ruby_getaddrinfo__aix(const char *nodename, const char *servname,
#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
static int
ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen,
- char *host, size_t hostlen,
- char *serv, size_t servlen, int flags)
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
{
struct sockaddr_in6 *sa6;
u_int32_t *a6;
if (sa->sa_family == AF_INET6) {
- sa6 = (struct sockaddr_in6 *)sa;
- a6 = sa6->sin6_addr.u6_addr.u6_addr32;
+ sa6 = (struct sockaddr_in6 *)sa;
+ a6 = sa6->sin6_addr.u6_addr.u6_addr32;
- if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
- strncpy(host, "::", hostlen);
- snprintf(serv, servlen, "%d", sa6->sin6_port);
- return 0;
- }
+ if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
+ strncpy(host, "::", hostlen);
+ snprintf(serv, servlen, "%d", sa6->sin6_port);
+ return 0;
+ }
}
return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
}
@@ -102,7 +102,7 @@ static int str_is_number(const char *);
#if defined(__APPLE__)
static int
ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
- const struct addrinfo *hints, struct addrinfo **res)
+ const struct addrinfo *hints, struct addrinfo **res)
{
/* fix [ruby-core:29427] */
const char *tmp_servname;
@@ -112,12 +112,12 @@ ruby_getaddrinfo__darwin(const char *nodename, const char *servname,
tmp_servname = servname;
MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
if (nodename && servname) {
- if (str_is_number(tmp_servname) && atoi(servname) == 0) {
- tmp_servname = NULL;
+ if (str_is_number(tmp_servname) && atoi(servname) == 0) {
+ tmp_servname = NULL;
#ifdef AI_NUMERICSERV
- if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
+ if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV;
#endif
- }
+ }
}
error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res);
@@ -193,7 +193,7 @@ nogvl_getaddrinfo(void *arg)
* it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
*/
if (ret == EAI_SYSTEM && errno == ENOENT)
- ret = EAI_NONAME;
+ ret = EAI_NONAME;
#endif
return (void *)(VALUE)ret;
}
@@ -212,15 +212,15 @@ numeric_getaddrinfo(const char *node, const char *service,
int port;
if (node && parse_numeric_port(service, &port)) {
- static const struct {
- int socktype;
- int protocol;
- } list[] = {
- { SOCK_STREAM, IPPROTO_TCP },
- { SOCK_DGRAM, IPPROTO_UDP },
- { SOCK_RAW, 0 }
- };
- struct addrinfo *ai = NULL;
+ static const struct {
+ int socktype;
+ int protocol;
+ } list[] = {
+ { SOCK_STREAM, IPPROTO_TCP },
+ { SOCK_DGRAM, IPPROTO_UDP },
+ { SOCK_RAW, 0 }
+ };
+ struct addrinfo *ai = NULL;
int hint_family = hints ? hints->ai_family : PF_UNSPEC;
int hint_socktype = hints ? hints->ai_socktype : 0;
int hint_protocol = hints ? hints->ai_protocol : 0;
@@ -287,8 +287,9 @@ numeric_getaddrinfo(const char *node, const char *service,
void
rb_freeaddrinfo(struct rb_addrinfo *ai)
{
- if (!ai->allocated_by_malloc)
- freeaddrinfo(ai->ai);
+ if (!ai->allocated_by_malloc) {
+ if (ai->ai) freeaddrinfo(ai->ai);
+ }
else {
struct addrinfo *ai1, *ai2;
ai1 = ai->ai;
@@ -319,9 +320,9 @@ nogvl_getnameinfo(void *arg)
{
struct getnameinfo_arg *ptr = arg;
return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen,
- ptr->host, (socklen_t)ptr->hostlen,
- ptr->serv, (socklen_t)ptr->servlen,
- ptr->flags);
+ ptr->host, (socklen_t)ptr->hostlen,
+ ptr->serv, (socklen_t)ptr->servlen,
+ ptr->flags);
}
#endif
@@ -587,7 +588,7 @@ rsock_fd_family(int fd)
if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0 ||
(size_t)sa_len < offsetof(struct sockaddr, sa_family) + sizeof(sa.sa_family)) {
- return AF_UNSPEC;
+ return AF_UNSPEC;
}
return sa.sa_family;
}
@@ -618,8 +619,7 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
family = rb_str_dup(rb_id2str(id));
}
else {
- sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
- family = rb_str_new2(pbuf);
+ family = rb_sprintf("unknown:%d", sockaddr->sa_family);
}
addr1 = Qnil;
@@ -645,7 +645,7 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup)
return ary;
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
static long
unixsocket_len(const struct sockaddr_un *su, socklen_t socklen)
{
@@ -677,19 +677,19 @@ rsock_unix_sockaddr_len(VALUE path)
{
#ifdef __linux__
if (RSTRING_LEN(path) == 0) {
- /* autobind; see unix(7) for details. */
- return (socklen_t) sizeof(sa_family_t);
+ /* autobind; see unix(7) for details. */
+ return (socklen_t) sizeof(sa_family_t);
}
else if (RSTRING_PTR(path)[0] == '\0') {
- /* abstract namespace; see unix(7) for details. */
+ /* abstract namespace; see unix(7) for details. */
if (SOCKLEN_MAX - offsetof(struct sockaddr_un, sun_path) < (size_t)RSTRING_LEN(path))
rb_raise(rb_eArgError, "Linux abstract socket too long");
- return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
- RSTRING_SOCKLEN(path);
+ return (socklen_t) offsetof(struct sockaddr_un, sun_path) +
+ RSTRING_SOCKLEN(path);
}
else {
#endif
- return (socklen_t) sizeof(struct sockaddr_un);
+ return (socklen_t) sizeof(struct sockaddr_un);
#ifdef __linux__
}
#endif
@@ -727,7 +727,7 @@ make_hostent_internal(VALUE v)
rb_ary_push(ary, rb_str_new2(hostp));
if (addr->ai_canonname && strlen(addr->ai_canonname) < NI_MAXHOST &&
- (h = gethostbyname(addr->ai_canonname))) {
+ (h = gethostbyname(addr->ai_canonname))) {
names = rb_ary_new();
if (h->h_aliases != NULL) {
for (pch = h->h_aliases; *pch; pch++) {
@@ -875,19 +875,19 @@ call_getaddrinfo(VALUE node, VALUE service,
hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
if (!NIL_P(socktype)) {
- hints.ai_socktype = rsock_socktype_arg(socktype);
+ hints.ai_socktype = rsock_socktype_arg(socktype);
}
if (!NIL_P(protocol)) {
- hints.ai_protocol = NUM2INT(protocol);
+ hints.ai_protocol = NUM2INT(protocol);
}
if (!NIL_P(flags)) {
- hints.ai_flags = NUM2INT(flags);
+ hints.ai_flags = NUM2INT(flags);
}
res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
if (res == NULL)
- rb_raise(rb_eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
return res;
}
@@ -1018,7 +1018,7 @@ addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
static void
init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
{
@@ -1037,7 +1037,7 @@ init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
len = rsock_unix_sockaddr_len(path);
init_addrinfo(rai, (struct sockaddr *)&un, len,
- PF_UNIX, socktype, 0, Qnil, Qnil);
+ PF_UNIX, socktype, 0, Qnil, Qnil);
}
static long
@@ -1065,13 +1065,13 @@ rai_unixsocket_len(const rb_addrinfo_t *rai)
* Socket.sockaddr_in or Socket.unpack_sockaddr_un.
*
* sockaddr examples:
- * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]
- * - ["AF_INET6", 42304, "ip6-localhost", "::1"]
- * - ["AF_UNIX", "/tmp/sock"]
- * - Socket.sockaddr_in("smtp", "2001:DB8::1")
- * - Socket.sockaddr_in(80, "172.18.22.42")
- * - Socket.sockaddr_in(80, "www.ruby-lang.org")
- * - Socket.sockaddr_un("/tmp/sock")
+ * - <code>["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]</code>
+ * - <code>["AF_INET6", 42304, "ip6-localhost", "::1"]</code>
+ * - <code>["AF_UNIX", "/tmp/sock"]</code>
+ * - <code>Socket.sockaddr_in("smtp", "2001:DB8::1")</code>
+ * - <code>Socket.sockaddr_in(80, "172.18.22.42")</code>
+ * - <code>Socket.sockaddr_in(80, "www.ruby-lang.org")</code>
+ * - <code>Socket.sockaddr_un("/tmp/sock")</code>
*
* In an AF_INET/AF_INET6 sockaddr array, the 4th element,
* numeric IP address, is used to construct socket address in the Addrinfo instance.
@@ -1119,7 +1119,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self)
int af;
StringValue(afamily);
if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1)
- rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
+ rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily));
switch (af) {
case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */
#ifdef INET6
@@ -1147,7 +1147,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self)
break;
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */
{
VALUE path = rb_ary_entry(sockaddr_ary, 1);
@@ -1209,45 +1209,45 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r
else {
switch (sockaddr->addr.sa_family) {
case AF_UNSPEC:
- {
- rb_str_cat2(ret, "UNSPEC");
+ {
+ rb_str_cat2(ret, "UNSPEC");
break;
- }
+ }
case AF_INET:
{
struct sockaddr_in *addr;
int port;
- addr = &sockaddr->in;
- if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen)
- rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]);
- else
- rb_str_cat2(ret, "?");
- if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen)
- rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]);
- else
- rb_str_cat2(ret, ".?");
- if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen)
- rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]);
- else
- rb_str_cat2(ret, ".?");
- if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen)
- rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]);
- else
- rb_str_cat2(ret, ".?");
-
- if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) {
- port = ntohs(addr->sin_port);
- if (port)
- rb_str_catf(ret, ":%d", port);
- }
- else {
- rb_str_cat2(ret, ":?");
- }
- if ((socklen_t)sizeof(struct sockaddr_in) != socklen)
- rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)",
- (int)socklen,
- (int)sizeof(struct sockaddr_in));
+ addr = &sockaddr->in;
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen)
+ rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]);
+ else
+ rb_str_cat2(ret, "?");
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen)
+ rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]);
+ else
+ rb_str_cat2(ret, ".?");
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen)
+ rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]);
+ else
+ rb_str_cat2(ret, ".?");
+ if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen)
+ rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]);
+ else
+ rb_str_cat2(ret, ".?");
+
+ if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) {
+ port = ntohs(addr->sin_port);
+ if (port)
+ rb_str_catf(ret, ":%d", port);
+ }
+ else {
+ rb_str_cat2(ret, ":?");
+ }
+ if ((socklen_t)sizeof(struct sockaddr_in) != socklen)
+ rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)",
+ (int)socklen,
+ (int)sizeof(struct sockaddr_in));
break;
}
@@ -1287,7 +1287,7 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r
}
#endif
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case AF_UNIX:
{
struct sockaddr_un *addr = &sockaddr->un;
@@ -1398,20 +1398,20 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r
#endif
#if defined(AF_LINK) && defined(HAVE_TYPE_STRUCT_SOCKADDR_DL)
- /* AF_LINK is defined in 4.4BSD derivations since Net2.
- link_ntoa is also defined at Net2.
+ /* AF_LINK is defined in 4.4BSD derivations since Net2.
+ link_ntoa is also defined at Net2.
However Debian GNU/kFreeBSD defines AF_LINK but
don't have link_ntoa. */
case AF_LINK:
- {
- /*
- * Simple implementation using link_ntoa():
- * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze).
+ {
+ /*
+ * Simple implementation using link_ntoa():
+ * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze).
* Also, the format is bit different.
- *
- * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl));
- * break;
- */
+ *
+ * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl));
+ * break;
+ */
struct sockaddr_dl *addr = &sockaddr->dl;
char *np = NULL, *ap = NULL, *endp;
int nlen = 0, alen = 0;
@@ -1438,14 +1438,14 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r
alen = (int)(endp - ap);
}
- CATSEP;
+ CATSEP;
if (np)
rb_str_catf(ret, "%.*s", nlen, np);
else
rb_str_cat2(ret, "?");
if (ap && 0 < alen) {
- CATSEP;
+ CATSEP;
for (i = 0; i < alen; i++)
rb_str_catf(ret, "%s%02x", i == 0 ? "" : ":", (unsigned char)ap[i]);
}
@@ -1456,10 +1456,10 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r
/* longer length is possible behavior because struct sockaddr_dl has "minimum work area, can be larger" as the last field.
* cf. Net2:/usr/src/sys/net/if_dl.h. */
socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_data) + addr->sdl_nlen + addr->sdl_alen + addr->sdl_slen)) {
- CATSEP;
+ CATSEP;
rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_dl)",
(int)socklen, (int)sizeof(struct sockaddr_dl));
- }
+ }
rb_str_cat2(ret, "]");
#undef CATSEP
@@ -1623,7 +1623,7 @@ addrinfo_mdump(VALUE self)
afamily = rb_id2str(id);
switch(afamily_int) {
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case AF_UNIX:
{
sockaddr = rb_str_new(rai->addr.un.sun_path, rai_unixsocket_len(rai));
@@ -1716,7 +1716,7 @@ addrinfo_mload(VALUE self, VALUE ary)
v = rb_ary_entry(ary, 1);
switch(afamily) {
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case AF_UNIX:
{
struct sockaddr_un uaddr;
@@ -2009,7 +2009,7 @@ addrinfo_ip_unpack(VALUE self)
VALUE ret, portstr;
if (!IS_IP_FAMILY(family))
- rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
+ rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
ret = addrinfo_getnameinfo(1, &vflags, self);
@@ -2036,7 +2036,7 @@ addrinfo_ip_address(VALUE self)
VALUE ret;
if (!IS_IP_FAMILY(family))
- rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
+ rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV);
ret = addrinfo_getnameinfo(1, &vflags, self);
@@ -2062,9 +2062,9 @@ addrinfo_ip_port(VALUE self)
if (!IS_IP_FAMILY(family)) {
bad_family:
#ifdef AF_INET6
- rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
+ rb_raise(rb_eSocket, "need IPv4 or IPv6 address");
#else
- rb_raise(rb_eSocket, "need IPv4 address");
+ rb_raise(rb_eSocket, "need IPv4 address");
#endif
}
@@ -2084,7 +2084,7 @@ addrinfo_ip_port(VALUE self)
#endif
default:
- goto bad_family;
+ goto bad_family;
}
return INT2NUM(port);
@@ -2192,7 +2192,7 @@ addrinfo_ipv6_multicast_p(VALUE self)
}
/*
- * Returns true for IPv6 link local address (ff80::/10).
+ * Returns true for IPv6 link local address (fe80::/10).
* It returns false otherwise.
*/
static VALUE
@@ -2204,7 +2204,7 @@ addrinfo_ipv6_linklocal_p(VALUE self)
}
/*
- * Returns true for IPv6 site local address (ffc0::/10).
+ * Returns true for IPv6 site local address (fec0::/10).
* It returns false otherwise.
*/
static VALUE
@@ -2344,7 +2344,7 @@ addrinfo_ipv6_to_ipv4(VALUE self)
#endif
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
/*
* call-seq:
* addrinfo.unix_path => path
@@ -2362,7 +2362,7 @@ addrinfo_unix_path(VALUE self)
long n;
if (family != AF_UNIX)
- rb_raise(rb_eSocket, "need AF_UNIX address");
+ rb_raise(rb_eSocket, "need AF_UNIX address");
addr = &rai->addr.un;
@@ -2429,10 +2429,10 @@ addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
VALUE node, service, family, socktype, protocol, flags, opts, timeout;
rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype,
- &protocol, &flags, &opts);
+ &protocol, &flags, &opts);
rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout);
if (timeout == Qundef) {
- timeout = Qnil;
+ timeout = Qnil;
}
return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout);
@@ -2492,7 +2492,7 @@ addrinfo_s_udp(VALUE self, VALUE host, VALUE port)
INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0));
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
/*
* call-seq:
@@ -2630,7 +2630,7 @@ rsock_init_addrinfo(void)
rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1);
rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2);
rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2);
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1);
#endif
@@ -2671,7 +2671,7 @@ rsock_init_addrinfo(void)
rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0);
#endif
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0);
#endif
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index c0d40addca..5f803ba0da 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -33,6 +33,9 @@
#endif
#ifdef _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <iphlpapi.h>
# if defined(_MSC_VER)
# undef HAVE_TYPE_STRUCT_SOCKADDR_DL
# endif
@@ -69,6 +72,11 @@
# include <sys/un.h>
#endif
+#ifdef HAVE_AFUNIX_H
+// Windows doesn't have sys/un.h, but it does have afunix.h just to be special:
+# include <afunix.h>
+#endif
+
#if defined(HAVE_FCNTL)
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
@@ -268,7 +276,7 @@ extern VALUE rb_cIPSocket;
extern VALUE rb_cTCPSocket;
extern VALUE rb_cTCPServer;
extern VALUE rb_cUDPSocket;
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
extern VALUE rb_cUNIXSocket;
extern VALUE rb_cUNIXServer;
#endif
@@ -336,7 +344,7 @@ VALUE rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len);
int rsock_revlookup_flag(VALUE revlookup, int *norevlookup);
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
VALUE rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len);
VALUE rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len);
socklen_t rsock_unix_sockaddr_len(VALUE path);
@@ -368,23 +376,23 @@ enum sock_recv_type {
};
VALUE rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
- VALUE ex, enum sock_recv_type from);
+ VALUE ex, enum sock_recv_type from);
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from);
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struct timeval *timeout);
VALUE rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len);
VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
- struct sockaddr *sockaddr, socklen_t *len);
+ struct sockaddr *sockaddr, socklen_t *len);
VALUE rsock_sock_listen(VALUE sock, VALUE log);
VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data);
#if defined(HAVE_SENDMSG)
VALUE rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags,
- VALUE dest_sockaddr, VALUE controls);
+ VALUE dest_sockaddr, VALUE controls);
VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
- VALUE dest_sockaddr, VALUE controls, VALUE ex);
+ VALUE dest_sockaddr, VALUE controls, VALUE ex);
#else
#define rsock_bsock_sendmsg rb_f_notimplement
#define rsock_bsock_sendmsg_nonblock rb_f_notimplement
@@ -392,9 +400,9 @@ VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
#if defined(HAVE_RECVMSG)
VALUE rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE clen, VALUE flags,
- VALUE scm_rights);
+ VALUE scm_rights);
VALUE rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE clen,
- VALUE flags, VALUE scm_rights, VALUE ex);
+ VALUE flags, VALUE scm_rights, VALUE ex);
ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags);
#else
#define rsock_bsock_recvmsg rb_f_notimplement
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index ccf990d11f..eb74f7a936 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -26,7 +26,11 @@ rsock_syserr_fail_host_port(int err, const char *mesg, VALUE host, VALUE port)
VALUE message;
message = rb_sprintf("%s for %+"PRIsVALUE" port % "PRIsVALUE"",
- mesg, host, port);
+ mesg, host, port);
+
+ if (err == ETIMEDOUT) {
+ rb_exc_raise(rb_exc_new3(rb_eIOTimeoutError, message));
+ }
rb_syserr_fail_str(err, message);
}
@@ -43,11 +47,11 @@ rsock_syserr_fail_path(int err, const char *mesg, VALUE path)
VALUE message;
if (RB_TYPE_P(path, T_STRING)) {
- message = rb_sprintf("%s for % "PRIsVALUE"", mesg, path);
- rb_syserr_fail_str(err, message);
+ message = rb_sprintf("%s for % "PRIsVALUE"", mesg, path);
+ rb_syserr_fail_str(err, message);
}
else {
- rb_syserr_fail(err, mesg);
+ rb_syserr_fail(err, mesg);
}
}
@@ -96,12 +100,12 @@ rsock_syserr_fail_raddrinfo_or_sockaddr(int err, const char *mesg, VALUE addr, V
if (NIL_P(rai)) {
StringValue(addr);
- rsock_syserr_fail_sockaddr(err, mesg,
+ rsock_syserr_fail_sockaddr(err, mesg,
(struct sockaddr *)RSTRING_PTR(addr),
(socklen_t)RSTRING_LEN(addr)); /* overflow should be checked already */
}
else
- rsock_syserr_fail_raddrinfo(err, mesg, rai);
+ rsock_syserr_fail_raddrinfo(err, mesg, rai);
}
static void
@@ -256,7 +260,7 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
p = NUM2INT(protocol);
ret = rsock_socketpair(d, t, p, sp);
if (ret < 0) {
- rb_sys_fail("socketpair(2)");
+ rb_sys_fail("socketpair(2)");
}
s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
@@ -395,7 +399,7 @@ sock_connect(VALUE sock, VALUE addr)
fd = fptr->fd;
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);
+ rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
}
return INT2FIX(n);
@@ -415,19 +419,19 @@ sock_connect_nonblock(VALUE sock, VALUE addr, VALUE ex)
rb_io_set_nonblock(fptr);
n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr));
if (n < 0) {
- int e = errno;
- if (e == EINPROGRESS) {
+ int e = errno;
+ if (e == EINPROGRESS) {
if (ex == Qfalse) {
return sym_wait_writable;
}
rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "connect(2) would block");
- }
- if (e == EISCONN) {
+ }
+ if (e == EISCONN) {
if (ex == Qfalse) {
return INT2FIX(0);
}
- }
- rsock_syserr_fail_raddrinfo_or_sockaddr(e, "connect(2)", addr, rai);
+ }
+ rsock_syserr_fail_raddrinfo_or_sockaddr(e, "connect(2)", addr, rai);
}
return INT2FIX(n);
@@ -528,7 +532,7 @@ sock_bind(VALUE sock, VALUE addr)
SockAddrStringValueWithAddrinfo(addr, rai);
GetOpenFile(sock, fptr);
if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0)
- rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai);
+ rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai);
return INT2FIX(0);
}
@@ -612,7 +616,7 @@ rsock_sock_listen(VALUE sock, VALUE log)
backlog = NUM2INT(log);
GetOpenFile(sock, fptr);
if (listen(fptr->fd, backlog) < 0)
- rb_sys_fail("listen(2)");
+ rb_sys_fail("listen(2)");
return INT2FIX(0);
}
@@ -774,7 +778,7 @@ sock_accept_nonblock(VALUE sock, VALUE ex)
sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len);
if (SYMBOL_P(sock2)) /* :wait_readable */
- return sock2;
+ return sock2;
return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
}
@@ -855,19 +859,19 @@ sock_gethostname(VALUE obj)
name = rb_str_new(0, len);
while (gethostname(RSTRING_PTR(name), len) < 0) {
- int e = errno;
- switch (e) {
- case ENAMETOOLONG:
+ int e = errno;
+ switch (e) {
+ case ENAMETOOLONG:
#ifdef __linux__
- case EINVAL:
- /* glibc before version 2.1 uses EINVAL instead of ENAMETOOLONG */
+ case EINVAL:
+ /* glibc before version 2.1 uses EINVAL instead of ENAMETOOLONG */
#endif
- break;
- default:
- rb_syserr_fail(e, "gethostname(3)");
- }
- rb_str_modify_expand(name, len);
- len += len;
+ break;
+ default:
+ rb_syserr_fail(e, "gethostname(3)");
+ }
+ rb_str_modify_expand(name, len);
+ len += len;
}
rb_str_resize(name, strlen(RSTRING_PTR(name)));
return name;
@@ -897,18 +901,18 @@ make_addrinfo(struct rb_addrinfo *res0, int norevlookup)
struct addrinfo *res;
if (res0 == NULL) {
- rb_raise(rb_eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
}
base = rb_ary_new();
for (res = res0->ai; res; res = res->ai_next) {
- ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup);
- if (res->ai_canonname) {
- RARRAY_ASET(ary, 2, rb_str_new2(res->ai_canonname));
- }
- rb_ary_push(ary, INT2FIX(res->ai_family));
- rb_ary_push(ary, INT2FIX(res->ai_socktype));
- rb_ary_push(ary, INT2FIX(res->ai_protocol));
- rb_ary_push(base, ary);
+ ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup);
+ if (res->ai_canonname) {
+ RARRAY_ASET(ary, 2, rb_str_new2(res->ai_canonname));
+ }
+ rb_ary_push(ary, INT2FIX(res->ai_family));
+ rb_ary_push(ary, INT2FIX(res->ai_socktype));
+ rb_ary_push(ary, INT2FIX(res->ai_protocol));
+ rb_ary_push(base, ary);
}
return base;
}
@@ -920,18 +924,18 @@ sock_sockaddr(struct sockaddr *addr, socklen_t len)
switch (addr->sa_family) {
case AF_INET:
- ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
- len = (socklen_t)sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
- break;
+ ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
+ len = (socklen_t)sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
+ break;
#ifdef AF_INET6
case AF_INET6:
- ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
- len = (socklen_t)sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
- break;
+ ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
+ len = (socklen_t)sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
+ break;
#endif
default:
rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
- break;
+ break;
}
return rb_str_new(ptr, len);
}
@@ -961,7 +965,7 @@ sock_s_gethostbyname(VALUE obj, VALUE host)
{
rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
struct rb_addrinfo *res =
- rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
+ rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
return rsock_make_hostent(host, res, sock_sockaddr);
}
@@ -1004,20 +1008,20 @@ sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _)
rb_scan_args(argc, argv, "11", &addr, &family);
StringValue(addr);
if (!NIL_P(family)) {
- t = rsock_family_arg(family);
+ t = rsock_family_arg(family);
}
#ifdef AF_INET6
else if (RSTRING_LEN(addr) == 16) {
- t = AF_INET6;
+ t = AF_INET6;
}
#endif
h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), t);
if (h == NULL) {
#ifdef HAVE_HSTRERROR
- extern int h_errno;
- rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
+ extern int h_errno;
+ rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
#else
- rb_raise(rb_eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
#endif
}
ary = rb_ary_new();
@@ -1025,14 +1029,14 @@ sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _)
names = rb_ary_new();
rb_ary_push(ary, names);
if (h->h_aliases != NULL) {
- for (pch = h->h_aliases; *pch; pch++) {
- rb_ary_push(names, rb_str_new2(*pch));
- }
+ for (pch = h->h_aliases; *pch; pch++) {
+ rb_ary_push(names, rb_str_new2(*pch));
+ }
}
rb_ary_push(ary, INT2NUM(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
- rb_ary_push(ary, rb_str_new(*pch, h->h_length));
+ rb_ary_push(ary, rb_str_new(*pch, h->h_length));
}
#else
rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
@@ -1069,15 +1073,15 @@ sock_s_getservbyname(int argc, VALUE *argv, VALUE _)
if (!NIL_P(proto)) protoname = StringValueCStr(proto);
sp = getservbyname(servicename, protoname);
if (sp) {
- port = ntohs(sp->s_port);
+ port = ntohs(sp->s_port);
}
else {
- char *end;
+ char *end;
- port = STRTOUL(servicename, &end, 0);
- if (*end != '\0') {
- rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
- }
+ port = STRTOUL(servicename, &end, 0);
+ if (*end != '\0') {
+ rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
+ }
}
return INT2FIX(port);
}
@@ -1106,14 +1110,14 @@ sock_s_getservbyport(int argc, VALUE *argv, VALUE _)
rb_scan_args(argc, argv, "11", &port, &proto);
portnum = NUM2LONG(port);
if (portnum != (uint16_t)portnum) {
- const char *s = portnum > 0 ? "big" : "small";
- rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
+ const char *s = portnum > 0 ? "big" : "small";
+ rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
}
if (!NIL_P(proto)) protoname = StringValueCStr(proto);
sp = getservbyport((int)htons((uint16_t)portnum), protoname);
if (!sp) {
- rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
+ rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
}
return rb_str_new2(sp->s_name);
}
@@ -1167,16 +1171,16 @@ sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _)
hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
if (!NIL_P(socktype)) {
- hints.ai_socktype = rsock_socktype_arg(socktype);
+ hints.ai_socktype = rsock_socktype_arg(socktype);
}
if (!NIL_P(protocol)) {
- hints.ai_protocol = NUM2INT(protocol);
+ hints.ai_protocol = NUM2INT(protocol);
}
if (!NIL_P(flags)) {
- hints.ai_flags = NUM2INT(flags);
+ hints.ai_flags = NUM2INT(flags);
}
if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
- norevlookup = rsock_do_not_reverse_lookup;
+ norevlookup = rsock_do_not_reverse_lookup;
}
res = rsock_getaddrinfo(host, port, &hints, 0);
@@ -1226,82 +1230,82 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _)
fl = 0;
if (!NIL_P(flags)) {
- fl = NUM2INT(flags);
+ fl = NUM2INT(flags);
}
tmp = rb_check_sockaddr_string_type(sa);
if (!NIL_P(tmp)) {
- sa = tmp;
- if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
- rb_raise(rb_eTypeError, "sockaddr length too big");
- }
- memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
+ sa = tmp;
+ if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
+ rb_raise(rb_eTypeError, "sockaddr length too big");
+ }
+ memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
if (!VALIDATE_SOCKLEN(&ss.addr, RSTRING_LEN(sa))) {
- rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
- }
- sap = &ss.addr;
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
+ }
+ sap = &ss.addr;
salen = RSTRING_SOCKLEN(sa);
- goto call_nameinfo;
+ goto call_nameinfo;
}
tmp = rb_check_array_type(sa);
if (!NIL_P(tmp)) {
- sa = tmp;
- MEMZERO(&hints, struct addrinfo, 1);
- if (RARRAY_LEN(sa) == 3) {
- af = RARRAY_AREF(sa, 0);
- port = RARRAY_AREF(sa, 1);
- host = RARRAY_AREF(sa, 2);
- }
- else if (RARRAY_LEN(sa) >= 4) {
- af = RARRAY_AREF(sa, 0);
- port = RARRAY_AREF(sa, 1);
- host = RARRAY_AREF(sa, 3);
- if (NIL_P(host)) {
- host = RARRAY_AREF(sa, 2);
- }
- else {
- /*
- * 4th element holds numeric form, don't resolve.
- * see rsock_ipaddr().
- */
+ sa = tmp;
+ MEMZERO(&hints, struct addrinfo, 1);
+ if (RARRAY_LEN(sa) == 3) {
+ af = RARRAY_AREF(sa, 0);
+ port = RARRAY_AREF(sa, 1);
+ host = RARRAY_AREF(sa, 2);
+ }
+ else if (RARRAY_LEN(sa) >= 4) {
+ af = RARRAY_AREF(sa, 0);
+ port = RARRAY_AREF(sa, 1);
+ host = RARRAY_AREF(sa, 3);
+ if (NIL_P(host)) {
+ host = RARRAY_AREF(sa, 2);
+ }
+ else {
+ /*
+ * 4th element holds numeric form, don't resolve.
+ * see rsock_ipaddr().
+ */
#ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
- hints.ai_flags |= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
#endif
- }
- }
- else {
- rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
- RARRAY_LEN(sa));
- }
- hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
- /* af */
+ }
+ }
+ else {
+ rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
+ RARRAY_LEN(sa));
+ }
+ hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
+ /* af */
hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
- res = rsock_getaddrinfo(host, port, &hints, 0);
- sap = res->ai->ai_addr;
+ res = rsock_getaddrinfo(host, port, &hints, 0);
+ sap = res->ai->ai_addr;
salen = res->ai->ai_addrlen;
}
else {
- rb_raise(rb_eTypeError, "expecting String or Array");
+ rb_raise(rb_eTypeError, "expecting String or Array");
}
call_nameinfo:
error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf),
- pbuf, sizeof(pbuf), fl);
+ pbuf, sizeof(pbuf), fl);
if (error) goto error_exit_name;
if (res) {
- for (r = res->ai->ai_next; r; r = r->ai_next) {
- char hbuf2[1024], pbuf2[1024];
+ for (r = res->ai->ai_next; r; r = r->ai_next) {
+ char hbuf2[1024], pbuf2[1024];
- sap = r->ai_addr;
+ sap = r->ai_addr;
salen = r->ai_addrlen;
- error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
- pbuf2, sizeof(pbuf2), fl);
- if (error) goto error_exit_name;
- if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
- rb_freeaddrinfo(res);
- rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
- }
- }
- rb_freeaddrinfo(res);
+ error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
+ pbuf2, sizeof(pbuf2), fl);
+ if (error) goto error_exit_name;
+ if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
+ rb_freeaddrinfo(res);
+ rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
+ }
+ }
+ rb_freeaddrinfo(res);
}
return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
@@ -1379,7 +1383,7 @@ sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
}
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
/*
* call-seq:
@@ -1437,8 +1441,8 @@ sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
}
if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
- rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
- RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
+ rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
+ RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
}
path = rsock_unixpath_str(sockaddr, RSTRING_SOCKLEN(addr));
return path;
@@ -1467,7 +1471,7 @@ sockaddr_len(struct sockaddr *addr)
return (socklen_t)sizeof(struct sockaddr_in6);
#endif
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
case AF_UNIX:
return (socklen_t)sizeof(struct sockaddr_un);
#endif
@@ -1502,19 +1506,19 @@ sockaddr_obj(struct sockaddr *addr, socklen_t len)
#if defined(__KAME__) && defined(AF_INET6)
if (addr->sa_family == AF_INET6) {
- /* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */
+ /* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */
/* http://orange.kame.net/dev/cvsweb.cgi/kame/IMPLEMENTATION */
- /* convert fe80:1::1 to fe80::1%1 */
+ /* convert fe80:1::1 to fe80::1%1 */
len = (socklen_t)sizeof(struct sockaddr_in6);
- memcpy(&addr6, addr, len);
- addr = (struct sockaddr *)&addr6;
- if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
- addr6.sin6_scope_id == 0 &&
- (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
- addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
- addr6.sin6_addr.s6_addr[2] = 0;
- addr6.sin6_addr.s6_addr[3] = 0;
- }
+ memcpy(&addr6, addr, len);
+ addr = (struct sockaddr *)&addr6;
+ if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
+ addr6.sin6_scope_id == 0 &&
+ (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
+ addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
+ addr6.sin6_addr.s6_addr[2] = 0;
+ addr6.sin6_addr.s6_addr[3] = 0;
+ }
}
#endif
@@ -1529,7 +1533,7 @@ rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len)
#endif
-#if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) || defined(_WIN32)
+#if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM)) || defined(SIOCGIFCONF) || defined(_WIN32)
/*
* call-seq:
* Socket.ip_address_list => array
@@ -1590,9 +1594,8 @@ socket_s_ip_address_list(VALUE self)
freeifaddrs(ifp);
return list;
-#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
+#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM)
/* Solaris if_tcp(7P) */
- /* HP-UX has SIOCGLIFCONF too. But it uses different struct */
int fd = -1;
int ret;
struct lifnum ln;
@@ -1613,8 +1616,8 @@ socket_s_ip_address_list(VALUE self)
ret = ioctl(fd, SIOCGLIFNUM, &ln);
if (ret == -1) {
- reason = "SIOCGLIFNUM";
- goto finish;
+ reason = "SIOCGLIFNUM";
+ goto finish;
}
memset(&lc, 0, sizeof(lc));
@@ -1625,13 +1628,13 @@ socket_s_ip_address_list(VALUE self)
ret = ioctl(fd, SIOCGLIFCONF, &lc);
if (ret == -1) {
- reason = "SIOCGLIFCONF";
- goto finish;
+ reason = "SIOCGLIFCONF";
+ goto finish;
}
list = rb_ary_new();
for (i = 0; i < ln.lifn_count; i++) {
- struct lifreq *req = &lc.lifc_req[i];
+ struct lifreq *req = &lc.lifc_req[i];
if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
if (req->lifr_addr.ss_family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
@@ -1652,13 +1655,13 @@ socket_s_ip_address_list(VALUE self)
finish:
save_errno = errno;
if (lc.lifc_buf != NULL)
- xfree(lc.lifc_req);
+ xfree(lc.lifc_req);
if (fd != -1)
- close(fd);
+ close(fd);
errno = save_errno;
if (reason)
- rb_syserr_fail(save_errno, reason);
+ rb_syserr_fail(save_errno, reason);
return list;
#elif defined(SIOCGIFCONF)
@@ -1696,17 +1699,17 @@ socket_s_ip_address_list(VALUE self)
/* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */
if (bufsize - EXTRA_SPACE < conf.ifc_len) {
- if (bufsize < conf.ifc_len) {
- /* NetBSD returns required size for all interfaces. */
- bufsize = conf.ifc_len + EXTRA_SPACE;
- }
- else {
- bufsize = bufsize << 1;
- }
- if (buf == initbuf)
- buf = NULL;
- buf = xrealloc(buf, bufsize);
- goto retry;
+ if (bufsize < conf.ifc_len) {
+ /* NetBSD returns required size for all interfaces. */
+ bufsize = conf.ifc_len + EXTRA_SPACE;
+ }
+ else {
+ bufsize = bufsize << 1;
+ }
+ if (buf == initbuf)
+ buf = NULL;
+ buf = xrealloc(buf, bufsize);
+ goto retry;
}
close(fd);
@@ -1715,10 +1718,10 @@ socket_s_ip_address_list(VALUE self)
list = rb_ary_new();
req = conf.ifc_req;
while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
- struct sockaddr *addr = &req->ifr_addr;
+ struct sockaddr *addr = &req->ifr_addr;
if (IS_IP_FAMILY(addr->sa_family)) {
- rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
- }
+ rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
+ }
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
# ifndef _SIZEOF_ADDR_IFREQ
# define _SIZEOF_ADDR_IFREQ(r) \
@@ -1727,9 +1730,9 @@ socket_s_ip_address_list(VALUE self)
(r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
0))
# endif
- req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
+ req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
#else
- req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
+ req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
#endif
}
@@ -1739,57 +1742,57 @@ socket_s_ip_address_list(VALUE self)
if (buf != initbuf)
xfree(buf);
if (fd != -1)
- close(fd);
+ close(fd);
errno = save_errno;
if (reason)
- rb_syserr_fail(save_errno, reason);
+ rb_syserr_fail(save_errno, reason);
return list;
#undef EXTRA_SPACE
#elif defined(_WIN32)
typedef struct ip_adapter_unicast_address_st {
- unsigned LONG_LONG dummy0;
- struct ip_adapter_unicast_address_st *Next;
- struct {
- struct sockaddr *lpSockaddr;
- int iSockaddrLength;
- } Address;
- int dummy1;
- int dummy2;
- int dummy3;
- long dummy4;
- long dummy5;
- long dummy6;
+ unsigned LONG_LONG dummy0;
+ struct ip_adapter_unicast_address_st *Next;
+ struct {
+ struct sockaddr *lpSockaddr;
+ int iSockaddrLength;
+ } Address;
+ int dummy1;
+ int dummy2;
+ int dummy3;
+ long dummy4;
+ long dummy5;
+ long dummy6;
} ip_adapter_unicast_address_t;
typedef struct ip_adapter_anycast_address_st {
- unsigned LONG_LONG dummy0;
- struct ip_adapter_anycast_address_st *Next;
- struct {
- struct sockaddr *lpSockaddr;
- int iSockaddrLength;
- } Address;
+ unsigned LONG_LONG dummy0;
+ struct ip_adapter_anycast_address_st *Next;
+ struct {
+ struct sockaddr *lpSockaddr;
+ int iSockaddrLength;
+ } Address;
} ip_adapter_anycast_address_t;
typedef struct ip_adapter_addresses_st {
- unsigned LONG_LONG dummy0;
- struct ip_adapter_addresses_st *Next;
- void *dummy1;
- ip_adapter_unicast_address_t *FirstUnicastAddress;
- ip_adapter_anycast_address_t *FirstAnycastAddress;
- void *dummy2;
- void *dummy3;
- void *dummy4;
- void *dummy5;
- void *dummy6;
- BYTE dummy7[8];
- DWORD dummy8;
- DWORD dummy9;
- DWORD dummy10;
- DWORD IfType;
- int OperStatus;
- DWORD dummy12;
- DWORD dummy13[16];
- void *dummy14;
+ unsigned LONG_LONG dummy0;
+ struct ip_adapter_addresses_st *Next;
+ void *dummy1;
+ ip_adapter_unicast_address_t *FirstUnicastAddress;
+ ip_adapter_anycast_address_t *FirstAnycastAddress;
+ void *dummy2;
+ void *dummy3;
+ void *dummy4;
+ void *dummy5;
+ void *dummy6;
+ BYTE dummy7[8];
+ DWORD dummy8;
+ DWORD dummy9;
+ DWORD dummy10;
+ DWORD IfType;
+ int OperStatus;
+ DWORD dummy12;
+ DWORD dummy13[16];
+ void *dummy14;
} ip_adapter_addresses_t;
typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
HMODULE h;
@@ -1801,49 +1804,49 @@ socket_s_ip_address_list(VALUE self)
h = LoadLibrary("iphlpapi.dll");
if (!h)
- rb_notimplement();
+ rb_notimplement();
pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
if (!pGetAdaptersAddresses) {
- FreeLibrary(h);
- rb_notimplement();
+ FreeLibrary(h);
+ rb_notimplement();
}
ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
- errno = rb_w32_map_errno(ret);
- FreeLibrary(h);
- rb_sys_fail("GetAdaptersAddresses");
+ errno = rb_w32_map_errno(ret);
+ FreeLibrary(h);
+ rb_sys_fail("GetAdaptersAddresses");
}
adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
if (ret != ERROR_SUCCESS) {
- errno = rb_w32_map_errno(ret);
- FreeLibrary(h);
- rb_sys_fail("GetAdaptersAddresses");
+ errno = rb_w32_map_errno(ret);
+ FreeLibrary(h);
+ rb_sys_fail("GetAdaptersAddresses");
}
list = rb_ary_new();
for (; adapters; adapters = adapters->Next) {
- ip_adapter_unicast_address_t *uni;
- ip_adapter_anycast_address_t *any;
- if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */
- continue;
- for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
+ ip_adapter_unicast_address_t *uni;
+ ip_adapter_anycast_address_t *any;
+ if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */
+ continue;
+ for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
#ifndef INET6
- if (uni->Address.lpSockaddr->sa_family == AF_INET)
+ if (uni->Address.lpSockaddr->sa_family == AF_INET)
#else
- if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
+ if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
#endif
- rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength));
- }
- for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
+ rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength));
+ }
+ for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
#ifndef INET6
- if (any->Address.lpSockaddr->sa_family == AF_INET)
+ if (any->Address.lpSockaddr->sa_family == AF_INET)
#else
- if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
+ if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
#endif
- rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength));
- }
+ rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength));
+ }
}
FreeLibrary(h);
@@ -1987,7 +1990,7 @@ Init_socket(void)
/* for ext/socket/lib/socket.rb use only: */
rb_define_private_method(rb_cSocket,
- "__connect_nonblock", sock_connect_nonblock, 2);
+ "__connect_nonblock", sock_connect_nonblock, 2);
rb_define_method(rb_cSocket, "bind", sock_bind, 1);
rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
@@ -1995,7 +1998,7 @@ Init_socket(void)
/* for ext/socket/lib/socket.rb use only: */
rb_define_private_method(rb_cSocket,
- "__accept_nonblock", sock_accept_nonblock, 1);
+ "__accept_nonblock", sock_accept_nonblock, 1);
rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
@@ -2003,7 +2006,7 @@ Init_socket(void)
/* for ext/socket/lib/socket.rb use only: */
rb_define_private_method(rb_cSocket,
- "__recvfrom_nonblock", sock_recvfrom_nonblock, 4);
+ "__recvfrom_nonblock", sock_recvfrom_nonblock, 4);
rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
@@ -2017,7 +2020,7 @@ Init_socket(void)
rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
diff --git a/ext/socket/sockssocket.c b/ext/socket/sockssocket.c
index b8b7e12998..f263ac3804 100644
--- a/ext/socket/sockssocket.c
+++ b/ext/socket/sockssocket.c
@@ -30,8 +30,8 @@ socks_init(VALUE sock, VALUE host, VALUE port)
static int init = 0;
if (init == 0) {
- SOCKSinit("ruby");
- init = 1;
+ SOCKSinit("ruby");
+ init = 1;
}
return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil);
diff --git a/ext/socket/tcpserver.c b/ext/socket/tcpserver.c
index 675733c6f9..04e5a0bb51 100644
--- a/ext/socket/tcpserver.c
+++ b/ext/socket/tcpserver.c
@@ -133,7 +133,7 @@ rsock_init_tcpserver(void)
rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
rb_define_private_method(rb_cTCPServer,
- "__accept_nonblock", tcp_accept_nonblock, 1);
+ "__accept_nonblock", tcp_accept_nonblock, 1);
rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */
diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c
index 51e77a0de9..03787272f3 100644
--- a/ext/socket/tcpsocket.c
+++ b/ext/socket/tcpsocket.c
@@ -32,22 +32,22 @@ tcp_init(int argc, VALUE *argv, VALUE sock)
VALUE connect_timeout = Qnil;
if (!keyword_ids[0]) {
- CONST_ID(keyword_ids[0], "resolv_timeout");
- CONST_ID(keyword_ids[1], "connect_timeout");
+ 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);
+ &local_host, &local_serv, &opt);
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]; }
+ 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,
- resolv_timeout, connect_timeout);
+ local_host, local_serv, INET_CLIENT,
+ resolv_timeout, connect_timeout);
}
static VALUE
@@ -80,7 +80,7 @@ tcp_s_gethostbyname(VALUE obj, VALUE host)
{
rb_warn("TCPSocket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
struct rb_addrinfo *res =
- rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
+ rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
return rsock_make_hostent(host, res, tcp_sockaddr);
}
diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c
index 2bfd7c8560..5224e48a96 100644
--- a/ext/socket/udpsocket.c
+++ b/ext/socket/udpsocket.c
@@ -33,11 +33,11 @@ udp_init(int argc, VALUE *argv, VALUE sock)
int fd;
if (rb_scan_args(argc, argv, "01", &arg) == 1) {
- family = rsock_family_arg(arg);
+ family = rsock_family_arg(arg);
}
fd = rsock_socket(family, SOCK_DGRAM, 0);
if (fd < 0) {
- rb_sys_fail("socket(2) - udp");
+ rb_sys_fail("socket(2) - udp");
}
return rsock_init_sock(sock, fd);
@@ -60,9 +60,9 @@ 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, NULL) >= 0) {
- return Qtrue;
- }
+ if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0, NULL) >= 0) {
+ return Qtrue;
+ }
}
return Qfalse;
}
@@ -92,7 +92,7 @@ udp_connect(VALUE sock, VALUE host, VALUE port)
GetOpenFile(sock, arg.fptr);
arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
- rsock_freeaddrinfo, (VALUE)arg.res);
+ rsock_freeaddrinfo, (VALUE)arg.res);
if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
return INT2FIX(0);
}
@@ -108,10 +108,10 @@ udp_bind_internal(VALUE v)
rb_io_check_closed(fptr = arg->fptr);
fd = fptr->fd;
for (res = arg->res->ai; res; res = res->ai_next) {
- if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
- continue;
- }
- return Qtrue;
+ if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
+ continue;
+ }
+ return Qtrue;
}
return Qfalse;
}
@@ -137,7 +137,7 @@ udp_bind(VALUE sock, VALUE host, VALUE port)
GetOpenFile(sock, arg.fptr);
arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
ret = rb_ensure(udp_bind_internal, (VALUE)&arg,
- rsock_freeaddrinfo, (VALUE)arg.res);
+ rsock_freeaddrinfo, (VALUE)arg.res);
if (!ret) rsock_sys_fail_host_port("bind(2)", host, port);
return INT2FIX(0);
}
@@ -170,7 +170,7 @@ udp_send_internal(VALUE v)
if (n >= 0) return RB_SSIZE2NUM(n);
- if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
+ if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
goto retry;
}
}
@@ -207,7 +207,7 @@ udp_send(int argc, VALUE *argv, VALUE sock)
VALUE ret;
if (argc == 2 || argc == 3) {
- return rsock_bsock_send(argc, argv, sock);
+ return rsock_bsock_send(argc, argv, sock);
}
rb_scan_args(argc, argv, "4", &arg.sarg.mesg, &flags, &host, &port);
@@ -217,7 +217,7 @@ udp_send(int argc, VALUE *argv, VALUE sock)
arg.sarg.flags = NUM2INT(flags);
arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
ret = rb_ensure(udp_send_internal, (VALUE)&arg,
- rsock_freeaddrinfo, (VALUE)arg.res);
+ rsock_freeaddrinfo, (VALUE)arg.res);
if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port);
return ret;
}
@@ -246,5 +246,5 @@ rsock_init_udpsocket(void)
/* for ext/socket/lib/socket.rb use only: */
rb_define_private_method(rb_cUDPSocket,
- "__recvfrom_nonblock", udp_recvfrom_nonblock, 4);
+ "__recvfrom_nonblock", udp_recvfrom_nonblock, 4);
}
diff --git a/ext/socket/unixserver.c b/ext/socket/unixserver.c
index 890f9d3fae..0ea5ac083c 100644
--- a/ext/socket/unixserver.c
+++ b/ext/socket/unixserver.c
@@ -10,7 +10,7 @@
#include "rubysocket.h"
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
/*
* call-seq:
* UNIXServer.new(path) => unixserver
@@ -66,7 +66,7 @@ unix_accept_nonblock(VALUE sock, VALUE ex)
GetOpenFile(sock, fptr);
fromlen = (socklen_t)sizeof(from);
return rsock_s_accept_nonblock(rb_cUNIXSocket, ex, fptr,
- (struct sockaddr *)&from, &fromlen);
+ (struct sockaddr *)&from, &fromlen);
}
/*
@@ -101,7 +101,7 @@ unix_sysaccept(VALUE server)
void
rsock_init_unixserver(void)
{
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
/*
* Document-class: UNIXServer < UNIXSocket
*
@@ -113,7 +113,7 @@ rsock_init_unixserver(void)
rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
rb_define_private_method(rb_cUNIXServer,
- "__accept_nonblock", unix_accept_nonblock, 1);
+ "__accept_nonblock", unix_accept_nonblock, 1);
rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */
diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c
index 857cfa6002..26ab76fc9f 100644
--- a/ext/socket/unixsocket.c
+++ b/ext/socket/unixsocket.c
@@ -10,7 +10,7 @@
#include "rubysocket.h"
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
struct unixsock_arg {
struct sockaddr_un *sockaddr;
socklen_t sockaddrlen;
@@ -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, NULL);
+ arg->sockaddrlen, 0, NULL);
}
static VALUE
@@ -43,6 +43,10 @@ unixsock_path_value(VALUE path)
}
}
#endif
+#ifdef _WIN32
+ /* UNIXSocket requires UTF-8 per spec. */
+ path = rb_str_export_to_enc(path, rb_utf8_encoding());
+#endif
return rb_get_path(path);
}
@@ -66,42 +70,42 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server)
fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
- rsock_sys_fail_path("socket(2)", path);
+ rsock_sys_fail_path("socket(2)", path);
}
if (server) {
status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
}
else {
- int prot;
- struct unixsock_arg arg;
- arg.sockaddr = &sockaddr;
- arg.sockaddrlen = sockaddrlen;
- arg.fd = fd;
+ int prot;
+ struct unixsock_arg arg;
+ arg.sockaddr = &sockaddr;
+ arg.sockaddrlen = sockaddrlen;
+ arg.fd = fd;
status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
- if (prot) {
- close(fd);
- rb_jump_tag(prot);
- }
+ if (prot) {
+ close(fd);
+ rb_jump_tag(prot);
+ }
}
if (status < 0) {
- int e = errno;
- close(fd);
- rsock_syserr_fail_path(e, "connect(2)", path);
+ int e = errno;
+ close(fd);
+ rsock_syserr_fail_path(e, "connect(2)", path);
}
if (server) {
- if (listen(fd, SOMAXCONN) < 0) {
- int e = errno;
- close(fd);
- rsock_syserr_fail_path(e, "listen(2)", path);
- }
+ if (listen(fd, SOMAXCONN) < 0) {
+ int e = errno;
+ close(fd);
+ rsock_syserr_fail_path(e, "listen(2)", path);
+ }
}
rsock_init_sock(sock, fd);
if (server) {
- GetOpenFile(sock, fptr);
+ GetOpenFile(sock, fptr);
fptr->pathv = rb_str_new_frozen(path);
}
@@ -143,13 +147,13 @@ unix_path(VALUE sock)
GetOpenFile(sock, fptr);
if (NIL_P(fptr->pathv)) {
- struct sockaddr_un addr;
- socklen_t len = (socklen_t)sizeof(addr);
- socklen_t len0 = len;
- if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
+ struct sockaddr_un addr;
+ socklen_t len = (socklen_t)sizeof(addr);
+ socklen_t len0 = len;
+ if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
rsock_sys_fail_path("getsockname(2)", fptr->pathv);
if (len0 < len) len = len0;
- fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len));
+ fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len));
}
return rb_str_dup(fptr->pathv);
}
@@ -240,21 +244,21 @@ unix_send_io(VALUE sock, VALUE val)
#if FD_PASSING_BY_MSG_CONTROL
union {
- struct cmsghdr hdr;
- char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
+ struct cmsghdr hdr;
+ char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
} cmsg;
#endif
if (rb_obj_is_kind_of(val, rb_cIO)) {
rb_io_t *valfptr;
- GetOpenFile(val, valfptr);
- fd = valfptr->fd;
+ GetOpenFile(val, valfptr);
+ fd = valfptr->fd;
}
else if (FIXNUM_P(val)) {
fd = FIX2INT(val);
}
else {
- rb_raise(rb_eTypeError, "neither IO nor file descriptor");
+ rb_raise(rb_eTypeError, "neither IO nor file descriptor");
}
GetOpenFile(sock, fptr);
@@ -285,8 +289,8 @@ unix_send_io(VALUE sock, VALUE val)
arg.fd = fptr->fd;
while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) {
- if (!rb_io_wait_writable(arg.fd))
- rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
+ if (!rb_io_wait_writable(arg.fd))
+ rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
}
return Qnil;
@@ -348,16 +352,16 @@ unix_recv_io(int argc, VALUE *argv, VALUE sock)
int fd;
#if FD_PASSING_BY_MSG_CONTROL
union {
- struct cmsghdr hdr;
- char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
+ struct cmsghdr hdr;
+ char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
} cmsg;
#endif
rb_scan_args(argc, argv, "02", &klass, &mode);
if (argc == 0)
- klass = rb_cIO;
+ klass = rb_cIO;
if (argc <= 1)
- mode = Qnil;
+ mode = Qnil;
retry:
GetOpenFile(sock, fptr);
@@ -400,8 +404,8 @@ retry:
rb_gc_for_fd(e);
goto retry;
}
- if (!rb_io_wait_readable(arg.fd))
- rsock_syserr_fail_path(e, "recvmsg(2)", fptr->pathv);
+ if (!rb_io_wait_readable(arg.fd))
+ rsock_syserr_fail_path(e, "recvmsg(2)", fptr->pathv);
}
#if FD_PASSING_BY_MSG_CONTROL
@@ -412,41 +416,41 @@ retry:
rb_gc_for_fd(EMFILE);
goto retry;
}
- rb_raise(rb_eSocket,
- "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
- (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
+ (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
}
if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_level=%d, %d expected)",
- cmsg.hdr.cmsg_level, SOL_SOCKET);
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_level=%d, %d expected)",
+ cmsg.hdr.cmsg_level, SOL_SOCKET);
}
if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_type=%d, %d expected)",
- cmsg.hdr.cmsg_type, SCM_RIGHTS);
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_type=%d, %d expected)",
+ cmsg.hdr.cmsg_type, SCM_RIGHTS);
}
if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
- (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
+ (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
}
if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
- (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
+ (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
}
if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
- rsock_discard_cmsg_resource(&arg.msg, 0);
- rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_len=%d, %d expected)",
- (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
+ rsock_discard_cmsg_resource(&arg.msg, 0);
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (cmsg_len=%d, %d expected)",
+ (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
}
#else
if (arg.msg.msg_accrightslen != sizeof(fd)) {
- rb_raise(rb_eSocket,
- "file descriptor was not passed (accrightslen=%d, %d expected)",
- arg.msg.msg_accrightslen, (int)sizeof(fd));
+ rb_raise(rb_eSocket,
+ "file descriptor was not passed (accrightslen=%d, %d expected)",
+ arg.msg.msg_accrightslen, (int)sizeof(fd));
}
#endif
@@ -458,15 +462,15 @@ retry:
rb_maygvl_fd_fix_cloexec(fd);
if (klass == Qnil)
- return INT2FIX(fd);
+ return INT2FIX(fd);
else {
- ID for_fd;
- int ff_argc;
- VALUE ff_argv[2];
- CONST_ID(for_fd, "for_fd");
- ff_argc = mode == Qnil ? 1 : 2;
- ff_argv[0] = INT2FIX(fd);
- ff_argv[1] = mode;
+ ID for_fd;
+ int ff_argc;
+ VALUE ff_argv[2];
+ CONST_ID(for_fd, "for_fd");
+ ff_argc = mode == Qnil ? 1 : 2;
+ ff_argv[0] = INT2FIX(fd);
+ ff_argv[1] = mode;
return rb_funcallv(klass, for_fd, ff_argc, ff_argv);
}
}
@@ -556,9 +560,9 @@ unix_s_socketpair(int argc, VALUE *argv, VALUE klass)
domain = INT2FIX(PF_UNIX);
rb_scan_args(argc, argv, "02", &type, &protocol);
if (argc == 0)
- type = INT2FIX(SOCK_STREAM);
+ type = INT2FIX(SOCK_STREAM);
if (argc <= 1)
- protocol = INT2FIX(0);
+ protocol = INT2FIX(0);
args[0] = domain;
args[1] = type;
@@ -571,7 +575,7 @@ unix_s_socketpair(int argc, VALUE *argv, VALUE klass)
void
rsock_init_unixsocket(void)
{
-#ifdef HAVE_SYS_UN_H
+#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
/*
* Document-class: UNIXSocket < BasicSocket
*
diff --git a/ext/stringio/depend b/ext/stringio/depend
index c72378a3c9..828fc6e842 100644
--- a/ext/stringio/depend
+++ b/ext/stringio/depend
@@ -2,6 +2,20 @@
stringio.o: $(RUBY_EXTCONF_H)
stringio.o: $(arch_hdrdir)/ruby/config.h
stringio.o: $(hdrdir)/ruby.h
+stringio.o: $(hdrdir)/ruby/assert.h
+stringio.o: $(hdrdir)/ruby/backward.h
+stringio.o: $(hdrdir)/ruby/backward/2/assume.h
+stringio.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringio.o: $(hdrdir)/ruby/backward/2/bool.h
+stringio.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringio.o: $(hdrdir)/ruby/backward/2/limits.h
+stringio.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringio.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringio.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stringio.o: $(hdrdir)/ruby/defines.h
+stringio.o: $(hdrdir)/ruby/encoding.h
+stringio.o: $(hdrdir)/ruby/intern.h
+stringio.o: $(hdrdir)/ruby/internal/abi.h
stringio.o: $(hdrdir)/ruby/internal/anyargs.h
stringio.o: $(hdrdir)/ruby/internal/arithmetic.h
stringio.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ stringio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
stringio.o: $(hdrdir)/ruby/internal/ctype.h
stringio.o: $(hdrdir)/ruby/internal/dllexport.h
stringio.o: $(hdrdir)/ruby/internal/dosish.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/re.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/string.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+stringio.o: $(hdrdir)/ruby/internal/encoding/transcode.h
stringio.o: $(hdrdir)/ruby/internal/error.h
stringio.o: $(hdrdir)/ruby/internal/eval.h
stringio.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
stringio.o: $(hdrdir)/ruby/io.h
stringio.o: $(hdrdir)/ruby/missing.h
stringio.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 295650e89e..0054766dac 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -12,7 +12,7 @@
**********************************************************************/
-#define STRINGIO_VERSION "3.0.0"
+#define STRINGIO_VERSION "3.0.4"
#include "ruby.h"
#include "ruby/io.h"
@@ -67,15 +67,20 @@ strio_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
e = strchr(++n, ':');
len = e ? e - n : (long)strlen(n);
if (len > 0 && len <= ENCODING_MAXNAMELEN) {
+ rb_encoding *enc;
if (e) {
memcpy(encname, n, len);
encname[len] = '\0';
n = encname;
}
- convconfig_p->enc = rb_enc_find(n);
+ enc = rb_enc_find(n);
+ if (e)
+ convconfig_p->enc2 = enc;
+ else
+ convconfig_p->enc = enc;
}
if (e && (len = strlen(++e)) > 0 && len <= ENCODING_MAXNAMELEN) {
- convconfig_p->enc2 = rb_enc_find(e);
+ convconfig_p->enc = rb_enc_find(e);
}
}
}
@@ -252,9 +257,20 @@ strio_s_allocate(VALUE klass)
}
/*
- * call-seq: StringIO.new(string=""[, mode])
+ * call-seq:
+ * StringIO.new(string = '', mode = 'r+') -> new_stringio
+ *
+ * Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
+ *
+ * Returns a new \StringIO instance formed from +string+ and +mode+;
+ * see {Access Modes}[rdoc-ref:File@Access+Modes]:
*
- * Creates new StringIO instance from with _string_ and _mode_.
+ * strio = StringIO.new # => #<StringIO>
+ * strio.close
+ *
+ * The instance should be closed when no longer needed.
+ *
+ * Related: StringIO.open (accepts block; closes automatically).
*/
static VALUE
strio_initialize(int argc, VALUE *argv, VALUE self)
@@ -387,11 +403,26 @@ strio_finalize(VALUE self)
}
/*
- * call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
+ * call-seq:
+ * StringIO.open(string = '', mode = 'r+') {|strio| ... }
+ *
+ * Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
+ *
+ * Creates a new \StringIO instance formed from +string+ and +mode+;
+ * see {Access Modes}[rdoc-ref:File@Access+Modes].
+ *
+ * With no block, returns the new instance:
+ *
+ * strio = StringIO.open # => #<StringIO>
+ *
+ * With a block, calls the block with the new instance
+ * and returns the block's value;
+ * closes the instance on block exit.
*
- * Equivalent to StringIO.new except that when it is called with a block, it
- * yields with the new instance and closes it, and returns the result which
- * returned from the block.
+ * StringIO.open {|strio| p strio }
+ * # => #<StringIO>
+ *
+ * Related: StringIO.new.
*/
static VALUE
strio_s_open(int argc, VALUE *argv, VALUE klass)
@@ -477,9 +508,23 @@ strio_unimpl(int argc, VALUE *argv, VALUE self)
}
/*
- * call-seq: strio.string -> string
+ * call-seq:
+ * string -> string
+ *
+ * Returns underlying string:
+ *
+ * StringIO.open('foo') do |strio|
+ * p strio.string
+ * strio.string = 'bar'
+ * p strio.string
+ * end
+ *
+ * Output:
+ *
+ * "foo"
+ * "bar"
*
- * Returns underlying String object, the subject of IO.
+ * Related: StringIO#string= (assigns the underlying string).
*/
static VALUE
strio_get_string(VALUE self)
@@ -489,9 +534,23 @@ strio_get_string(VALUE self)
/*
* call-seq:
- * strio.string = string -> string
+ * string = other_string -> other_string
*
- * Changes underlying String object, the subject of IO.
+ * Assigns the underlying string as +other_string+, and sets position to zero;
+ * returns +other_string+:
+ *
+ * StringIO.open('foo') do |strio|
+ * p strio.string
+ * strio.string = 'bar'
+ * p strio.string
+ * end
+ *
+ * Output:
+ *
+ * "foo"
+ * "bar"
+ *
+ * Related: StringIO#string (returns the underlying string).
*/
static VALUE
strio_set_string(VALUE self, VALUE string)
@@ -509,10 +568,13 @@ strio_set_string(VALUE self, VALUE string)
/*
* call-seq:
- * strio.close -> nil
+ * close -> nil
+ *
+ * Closes +self+ for both reading and writing.
*
- * Closes a StringIO. The stream is unavailable for any further data
- * operations; an +IOError+ is raised if such an attempt is made.
+ * Raises IOError if reading or writing is attempted.
+ *
+ * Related: StringIO#close_read, StringIO#close_write.
*/
static VALUE
strio_close(VALUE self)
@@ -524,10 +586,13 @@ strio_close(VALUE self)
/*
* call-seq:
- * strio.close_read -> nil
+ * close_read -> nil
+ *
+ * Closes +self+ for reading; closed-write setting remains unchanged.
+ *
+ * Raises IOError if reading is attempted.
*
- * Closes the read end of a StringIO. Will raise an +IOError+ if the
- * receiver is not readable.
+ * Related: StringIO#close, StringIO#close_write.
*/
static VALUE
strio_close_read(VALUE self)
@@ -542,10 +607,13 @@ strio_close_read(VALUE self)
/*
* call-seq:
- * strio.close_write -> nil
+ * close_write -> nil
*
- * Closes the write end of a StringIO. Will raise an +IOError+ if the
- * receiver is not writeable.
+ * Closes +self+ for writing; closed-read setting remains unchanged.
+ *
+ * Raises IOError if writing is attempted.
+ *
+ * Related: StringIO#close, StringIO#close_read.
*/
static VALUE
strio_close_write(VALUE self)
@@ -560,9 +628,10 @@ strio_close_write(VALUE self)
/*
* call-seq:
- * strio.closed? -> true or false
+ * closed? -> true or false
*
- * Returns +true+ if the stream is completely closed, +false+ otherwise.
+ * Returns +true+ if +self+ is closed for both reading and writing,
+ * +false+ otherwise.
*/
static VALUE
strio_closed(VALUE self)
@@ -574,9 +643,9 @@ strio_closed(VALUE self)
/*
* call-seq:
- * strio.closed_read? -> true or false
+ * closed_read? -> true or false
*
- * Returns +true+ if the stream is not readable, +false+ otherwise.
+ * Returns +true+ if +self+ is closed for reading, +false+ otherwise.
*/
static VALUE
strio_closed_read(VALUE self)
@@ -588,9 +657,9 @@ strio_closed_read(VALUE self)
/*
* call-seq:
- * strio.closed_write? -> true or false
+ * closed_write? -> true or false
*
- * Returns +true+ if the stream is not writable, +false+ otherwise.
+ * Returns +true+ if +self+ is closed for writing, +false+ otherwise.
*/
static VALUE
strio_closed_write(VALUE self)
@@ -610,11 +679,14 @@ strio_to_read(VALUE self)
/*
* call-seq:
- * strio.eof -> true or false
- * strio.eof? -> true or false
+ * eof? -> true or false
+ *
+ * Returns +true+ if positioned at end-of-stream, +false+ otherwise;
+ * see {Position}[rdoc-ref:File@Position].
*
- * Returns true if the stream is at the end of the data (underlying string).
- * The stream must be opened for reading or an +IOError+ will be raised.
+ * Raises IOError if the stream is not opened for reading.
+ *
+ * StreamIO#eof is an alias for StreamIO#eof?.
*/
static VALUE
strio_eof(VALUE self)
@@ -644,13 +716,10 @@ strio_copy(VALUE copy, VALUE orig)
/*
* call-seq:
- * strio.lineno -> integer
+ * lineno -> current_line_number
*
- * Returns the current line number. The stream must be
- * opened for reading. +lineno+ counts the number of times +gets+ is
- * called, rather than the number of newlines encountered. The two
- * values will differ if +gets+ is called with a separator other than
- * newline. See also the <code>$.</code> variable.
+ * Returns the current line number in +self+;
+ * see {Line Number}[rdoc-ref:IO@Line+Number].
*/
static VALUE
strio_get_lineno(VALUE self)
@@ -660,10 +729,10 @@ strio_get_lineno(VALUE self)
/*
* call-seq:
- * strio.lineno = integer -> integer
+ * lineno = new_line_number -> new_line_number
*
- * Manually sets the current line number to the given value.
- * <code>$.</code> is updated only on the next read.
+ * Sets the current line number in +self+ to the given +new_line_number+;
+ * see {Line Number}[rdoc-ref:IO@Line+Number].
*/
static VALUE
strio_set_lineno(VALUE self, VALUE lineno)
@@ -674,9 +743,10 @@ strio_set_lineno(VALUE self, VALUE lineno)
/*
* call-seq:
- * strio.binmode -> stringio
+ * binmode -> self
*
- * Puts stream into binary mode. See IO#binmode.
+ * Sets the data mode in +self+ to binary mode;
+ * see {Data Mode}[rdoc-ref:File@Data+Mode].
*
*/
static VALUE
@@ -700,11 +770,27 @@ strio_binmode(VALUE self)
/*
* call-seq:
- * strio.reopen(other_StrIO) -> strio
- * strio.reopen(string, mode) -> strio
+ * reopen(other, mode = 'r+') -> self
+ *
+ * Reinitializes the stream with the given +other+ (string or StringIO) and +mode+;
+ * see IO.new:
+ *
+ * StringIO.open('foo') do |strio|
+ * p strio.string
+ * strio.reopen('bar')
+ * p strio.string
+ * other_strio = StringIO.new('baz')
+ * strio.reopen(other_strio)
+ * p strio.string
+ * other_strio.close
+ * end
+ *
+ * Output:
+ *
+ * "foo"
+ * "bar"
+ * "baz"
*
- * Reinitializes the stream with the given <i>other_StrIO</i> or _string_
- * and _mode_ (see StringIO#new).
*/
static VALUE
strio_reopen(int argc, VALUE *argv, VALUE self)
@@ -718,10 +804,12 @@ strio_reopen(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * strio.pos -> integer
- * strio.tell -> integer
+ * pos -> stream_position
*
- * Returns the current offset (in bytes).
+ * Returns the current position (in bytes);
+ * see {Position}[rdoc-ref:IO@Position].
+ *
+ * StringIO#tell is an alias for StringIO#pos.
*/
static VALUE
strio_get_pos(VALUE self)
@@ -731,9 +819,10 @@ strio_get_pos(VALUE self)
/*
* call-seq:
- * strio.pos = integer -> integer
+ * pos = new_position -> new_position
*
- * Seeks to the given position (in bytes).
+ * Sets the current position (in bytes);
+ * see {Position}[rdoc-ref:IO@Position].
*/
static VALUE
strio_set_pos(VALUE self, VALUE pos)
@@ -749,10 +838,11 @@ strio_set_pos(VALUE self, VALUE pos)
/*
* call-seq:
- * strio.rewind -> 0
+ * rewind -> 0
*
- * Positions the stream to the beginning of input, resetting
- * +lineno+ to zero.
+ * Sets the current position and line number to zero;
+ * see {Position}[rdoc-ref:IO@Position]
+ * and {Line Number}[rdoc-ref:IO@Line+Number].
*/
static VALUE
strio_rewind(VALUE self)
@@ -765,10 +855,11 @@ strio_rewind(VALUE self)
/*
* call-seq:
- * strio.seek(amount, whence=SEEK_SET) -> 0
+ * seek(offset, whence = SEEK_SET) -> 0
*
- * Seeks to a given offset _amount_ in the stream according to
- * the value of _whence_ (see IO#seek).
+ * Sets the current position to the given integer +offset+ (in bytes),
+ * with respect to a given constant +whence+;
+ * see {Position}[rdoc-ref:IO@Position].
*/
static VALUE
strio_seek(int argc, VALUE *argv, VALUE self)
@@ -804,9 +895,9 @@ strio_seek(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * strio.sync -> true
+ * sync -> true
*
- * Returns +true+ always.
+ * Returns +true+; implemented only for compatibility with other stream classes.
*/
static VALUE
strio_get_sync(VALUE self)
@@ -821,10 +912,12 @@ strio_get_sync(VALUE self)
/*
* call-seq:
- * strio.each_byte {|byte| block } -> strio
- * strio.each_byte -> anEnumerator
+ * each_byte {|byte| ... } -> self
+ *
+ * With a block given, calls the block with each remaining byte in the stream;
+ * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*
- * See IO#each_byte.
+ * With no block given, returns an enumerator.
*/
static VALUE
strio_each_byte(VALUE self)
@@ -842,9 +935,10 @@ strio_each_byte(VALUE self)
/*
* call-seq:
- * strio.getc -> string or nil
+ * getc -> character or nil
*
- * See IO#getc.
+ * Reads and returns the next character from the stream;
+ * see {Character IO}[rdoc-ref:IO@Character+IO].
*/
static VALUE
strio_getc(VALUE self)
@@ -867,9 +961,10 @@ strio_getc(VALUE self)
/*
* call-seq:
- * strio.getbyte -> fixnum or nil
+ * getbyte -> byte or nil
*
- * See IO#getbyte.
+ * Reads and returns the next 8-bit byte from the stream;
+ * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*/
static VALUE
strio_getbyte(VALUE self)
@@ -905,12 +1000,10 @@ strio_extend(struct StringIO *ptr, long pos, long len)
/*
* call-seq:
- * strio.ungetc(string) -> nil
+ * ungetc(character) -> nil
*
- * Pushes back one character (passed as a parameter)
- * such that a subsequent buffered read will return it. There is no
- * limitation for multiple pushbacks including pushing back behind the
- * beginning of the buffer string.
+ * Pushes back ("unshifts") a character or integer onto the stream;
+ * see {Character IO}[rdoc-ref:IO@Character+IO].
*/
static VALUE
strio_ungetc(VALUE self, VALUE c)
@@ -945,9 +1038,10 @@ strio_ungetc(VALUE self, VALUE c)
/*
* call-seq:
- * strio.ungetbyte(fixnum) -> nil
+ * ungetbyte(byte) -> nil
*
- * See IO#ungetbyte
+ * Pushes back ("unshifts") an 8-bit byte onto the stream;
+ * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*/
static VALUE
strio_ungetbyte(VALUE self, VALUE c)
@@ -984,7 +1078,7 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
len = RSTRING_LEN(str);
rest = pos - len;
if (cl > pos) {
- long ex = (rest < 0 ? cl-pos : cl+rest);
+ long ex = cl - (rest < 0 ? pos : len);
rb_str_modify_expand(str, ex);
rb_str_set_len(str, len + ex);
s = RSTRING_PTR(str);
@@ -1007,9 +1101,10 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
/*
* call-seq:
- * strio.readchar -> string
+ * readchar -> string
*
- * See IO#readchar.
+ * Like +getc+, but raises an exception if already at end-of-stream;
+ * see {Character IO}[rdoc-ref:IO@Character+IO].
*/
static VALUE
strio_readchar(VALUE self)
@@ -1021,9 +1116,10 @@ strio_readchar(VALUE self)
/*
* call-seq:
- * strio.readbyte -> fixnum
+ * readbyte -> byte
*
- * See IO#readbyte.
+ * Like +getbyte+, but raises an exception if already at end-of-stream;
+ * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*/
static VALUE
strio_readbyte(VALUE self)
@@ -1035,10 +1131,12 @@ strio_readbyte(VALUE self)
/*
* call-seq:
- * strio.each_char {|char| block } -> strio
- * strio.each_char -> anEnumerator
+ * each_char {|c| ... } -> self
+ *
+ * With a block given, calls the block with each remaining character in the stream;
+ * see {Character IO}[rdoc-ref:IO@Character+IO].
*
- * See IO#each_char.
+ * With no block given, returns an enumerator.
*/
static VALUE
strio_each_char(VALUE self)
@@ -1055,10 +1153,12 @@ strio_each_char(VALUE self)
/*
* call-seq:
- * strio.each_codepoint {|c| block } -> strio
- * strio.each_codepoint -> anEnumerator
+ * each_codepoint {|codepoint| ... } -> self
*
- * See IO#each_codepoint.
+ * With a block given, calls the block with each remaining codepoint in the stream;
+ * see {Codepoint IO}[rdoc-ref:IO@Codepoint+IO].
+ *
+ * With no block given, returns an enumerator.
*/
static VALUE
strio_each_codepoint(VALUE self)
@@ -1125,8 +1225,10 @@ prepare_getline_args(struct getline_arg *arg, int argc, VALUE *argv)
{
VALUE str, lim, opts;
long limit = -1;
+ int respect_chomp;
argc = rb_scan_args(argc, argv, "02:", &str, &lim, &opts);
+ respect_chomp = argc == 0 || !NIL_P(str);
switch (argc) {
case 0:
str = rb_rs;
@@ -1160,7 +1262,9 @@ prepare_getline_args(struct getline_arg *arg, int argc, VALUE *argv)
keywords[0] = rb_intern_const("chomp");
}
rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
- arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
+ if (respect_chomp) {
+ arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
+ }
}
return arg;
}
@@ -1181,7 +1285,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
const char *s, *e, *p;
long n, limit = arg->limit;
VALUE str = arg->rs;
- int w = 0;
+ long w = 0;
rb_encoding *enc = get_enc(ptr);
if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
@@ -1200,6 +1304,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
str = strio_substr(ptr, ptr->pos, e - s - w, enc);
}
else if ((n = RSTRING_LEN(str)) == 0) {
+ const char *paragraph_end = NULL;
p = s;
while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
p += *p == '\r';
@@ -1209,19 +1314,21 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
}
s = p;
while ((p = memchr(p, '\n', e - p)) && (p != e)) {
- if (*++p == '\n') {
- e = p + 1;
- w = (arg->chomp ? 1 : 0);
- break;
- }
- else if (*p == '\r' && p < e && p[1] == '\n') {
- e = p + 2;
- w = (arg->chomp ? 2 : 0);
- break;
- }
+ p++;
+ if (!((p < e && *p == '\n') ||
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n'))) {
+ continue;
+ }
+ paragraph_end = p - ((*(p-2) == '\r') ? 2 : 1);
+ while ((p < e && *p == '\n') ||
+ (p + 1 < e && *p == '\r' && *(p+1) == '\n')) {
+ p += (*p == '\r') ? 2 : 1;
+ }
+ e = p;
+ break;
}
- if (!w && arg->chomp) {
- w = chomp_newline_width(s, e);
+ if (arg->chomp && paragraph_end) {
+ w = e - paragraph_end;
}
str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s - w, enc);
}
@@ -1233,11 +1340,13 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
str = strio_substr(ptr, ptr->pos, e - s - w, enc);
}
else {
- if (n < e - s) {
- if (e - s < 1024) {
+ if (n < e - s + arg->chomp) {
+ /* unless chomping, RS at the end does not matter */
+ if (e - s < 1024 || n == e - s) {
for (p = s; p + n <= e; ++p) {
if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
- e = p + (arg->chomp ? 0 : n);
+ e = p + n;
+ w = (arg->chomp ? n : 0);
break;
}
}
@@ -1260,11 +1369,13 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
/*
* call-seq:
- * strio.gets(sep=$/, chomp: false) -> string or nil
- * strio.gets(limit, chomp: false) -> string or nil
- * strio.gets(sep, limit, chomp: false) -> string or nil
+ * gets(sep = $/, chomp: false) -> string or nil
+ * gets(limit, chomp: false) -> string or nil
+ * gets(sep, limit, chomp: false) -> string or nil
*
- * See IO#gets.
+ * Reads and returns a line from the stream;
+ * assigns the return value to <tt>$_</tt>;
+ * see {Line IO}[rdoc-ref:IO@Line+IO].
*/
static VALUE
strio_gets(int argc, VALUE *argv, VALUE self)
@@ -1284,11 +1395,12 @@ strio_gets(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * strio.readline(sep=$/, chomp: false) -> string
- * strio.readline(limit, chomp: false) -> string or nil
- * strio.readline(sep, limit, chomp: false) -> string or nil
+ * readline(sep = $/, chomp: false) -> string
+ * readline(limit, chomp: false) -> string
+ * readline(sep, limit, chomp: false) -> string
*
- * See IO#readline.
+ * Reads a line as with IO#gets, but raises EOFError if already at end-of-file;
+ * see {Line IO}[rdoc-ref:IO@Line+IO].
*/
static VALUE
strio_readline(int argc, VALUE *argv, VALUE self)
@@ -1300,17 +1412,16 @@ strio_readline(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * strio.each(sep=$/, chomp: false) {|line| block } -> strio
- * strio.each(limit, chomp: false) {|line| block } -> strio
- * strio.each(sep, limit, chomp: false) {|line| block } -> strio
- * strio.each(...) -> anEnumerator
+ * each_line(sep = $/, chomp: false) {|line| ... } -> self
+ * each_line(limit, chomp: false) {|line| ... } -> self
+ * each_line(sep, limit, chomp: false) {|line| ... } -> self
*
- * strio.each_line(sep=$/, chomp: false) {|line| block } -> strio
- * strio.each_line(limit, chomp: false) {|line| block } -> strio
- * strio.each_line(sep, limit, chomp: false) {|line| block } -> strio
- * strio.each_line(...) -> anEnumerator
+ * Calls the block with each remaining line read from the stream;
+ * does nothing if already at end-of-file;
+ * returns +self+.
+ * See {Line IO}[rdoc-ref:IO@Line+IO].
*
- * See IO#each.
+ * StringIO#each is an alias for StringIO#each_line.
*/
static VALUE
strio_each(int argc, VALUE *argv, VALUE self)
@@ -1655,7 +1766,7 @@ strio_truncate(VALUE self, VALUE len)
if (plen < l) {
MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
}
- return len;
+ return INT2FIX(0);
}
/*
@@ -1711,7 +1822,14 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
enc = rb_default_external_encoding();
}
else {
- enc = rb_to_encoding(ext_enc);
+ enc = rb_find_encoding(ext_enc);
+ if (!enc) {
+ struct rb_io_enc_t convconfig;
+ int oflags, fmode;
+ VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);
+ rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);
+ enc = convconfig.enc2;
+ }
}
ptr->enc = enc;
if (WRITABLE(self)) {
@@ -1731,24 +1849,16 @@ strio_set_encoding_by_bom(VALUE self)
}
/*
- * Pseudo I/O on String object, with interface corresponding to IO.
+ * \IO streams for strings, with access similar to
+ * {IO}[rdoc-ref:IO];
+ * see {IO}[rdoc-ref:IO].
*
- * Commonly used to simulate <code>$stdio</code> or <code>$stderr</code>
+ * === About the Examples
*
- * === Examples
+ * Examples on this page assume that \StringIO has been required:
*
* require 'stringio'
*
- * # Writing stream emulation
- * io = StringIO.new
- * io.puts "Hello World"
- * io.string #=> "Hello World\n"
- *
- * # Reading stream emulation
- * io = StringIO.new "first\nsecond\nlast\n"
- * io.getc #=> "f"
- * io.gets #=> "irst\n"
- * io.read #=> "second\nlast\n"
*/
void
Init_stringio(void)
diff --git a/ext/stringio/stringio.gemspec b/ext/stringio/stringio.gemspec
index 524d976cfb..1015d261f5 100644
--- a/ext/stringio/stringio.gemspec
+++ b/ext/stringio/stringio.gemspec
@@ -1,4 +1,4 @@
-# -*- encoding: utf-8 -*-
+# -*- coding: utf-8 -*-
# frozen_string_literal: true
source_version = ["", "ext/stringio/"].find do |dir|
@@ -16,11 +16,18 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 2.6")
s.require_paths = ["lib"]
- s.authors = ["Nobu Nakada"]
+ s.authors = ["Nobu Nakada", "Charles Oliver Nutter"]
s.description = "Pseudo `IO` class from/to `String`."
- s.email = "nobu@ruby-lang.org"
- s.extensions = ["ext/stringio/extconf.rb"]
- s.files = ["README.md", "ext/stringio/extconf.rb", "ext/stringio/stringio.c"]
+ s.email = ["nobu@ruby-lang.org", "headius@headius.com"]
+ s.files = ["README.md"]
+ jruby = true if Gem::Platform.new('java') =~ s.platform or RUBY_ENGINE == 'jruby'
+ if jruby
+ s.files += ["lib/stringio.rb", "lib/stringio.jar"]
+ s.platform = "java"
+ else
+ s.extensions = ["ext/stringio/extconf.rb"]
+ s.files += ["ext/stringio/extconf.rb", "ext/stringio/stringio.c"]
+ end
s.homepage = "https://github.com/ruby/stringio"
s.licenses = ["Ruby", "BSD-2-Clause"]
s.required_ruby_version = ">= 2.5"
diff --git a/ext/strscan/depend b/ext/strscan/depend
index ef0f007474..8fe3cb23d9 100644
--- a/ext/strscan/depend
+++ b/ext/strscan/depend
@@ -1,6 +1,20 @@
# AUTOGENERATED DEPENDENCIES START
strscan.o: $(RUBY_EXTCONF_H)
strscan.o: $(arch_hdrdir)/ruby/config.h
+strscan.o: $(hdrdir)/ruby/assert.h
+strscan.o: $(hdrdir)/ruby/backward.h
+strscan.o: $(hdrdir)/ruby/backward/2/assume.h
+strscan.o: $(hdrdir)/ruby/backward/2/attributes.h
+strscan.o: $(hdrdir)/ruby/backward/2/bool.h
+strscan.o: $(hdrdir)/ruby/backward/2/inttypes.h
+strscan.o: $(hdrdir)/ruby/backward/2/limits.h
+strscan.o: $(hdrdir)/ruby/backward/2/long_long.h
+strscan.o: $(hdrdir)/ruby/backward/2/stdalign.h
+strscan.o: $(hdrdir)/ruby/backward/2/stdarg.h
+strscan.o: $(hdrdir)/ruby/defines.h
+strscan.o: $(hdrdir)/ruby/encoding.h
+strscan.o: $(hdrdir)/ruby/intern.h
+strscan.o: $(hdrdir)/ruby/internal/abi.h
strscan.o: $(hdrdir)/ruby/internal/anyargs.h
strscan.o: $(hdrdir)/ruby/internal/arithmetic.h
strscan.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ strscan.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
strscan.o: $(hdrdir)/ruby/internal/ctype.h
strscan.o: $(hdrdir)/ruby/internal/dllexport.h
strscan.o: $(hdrdir)/ruby/internal/dosish.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/re.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/string.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+strscan.o: $(hdrdir)/ruby/internal/encoding/transcode.h
strscan.o: $(hdrdir)/ruby/internal/error.h
strscan.o: $(hdrdir)/ruby/internal/eval.h
strscan.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
strscan.o: $(hdrdir)/ruby/missing.h
strscan.o: $(hdrdir)/ruby/onigmo.h
strscan.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/strscan/extconf.rb b/ext/strscan/extconf.rb
index f0ecbf85d8..3c311d2364 100644
--- a/ext/strscan/extconf.rb
+++ b/ext/strscan/extconf.rb
@@ -1,5 +1,10 @@
# frozen_string_literal: true
require 'mkmf'
-$INCFLAGS << " -I$(top_srcdir)" if $extmk
-have_func("onig_region_memsize", "ruby.h")
-create_makefile 'strscan'
+if RUBY_ENGINE == 'ruby'
+ $INCFLAGS << " -I$(top_srcdir)" if $extmk
+ have_func("onig_region_memsize(NULL)")
+ have_func("rb_reg_onig_match", "ruby/re.h")
+ create_makefile 'strscan'
+else
+ File.write('Makefile', dummy_makefile("").join)
+end
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index 42027cd8d2..16d669d8a5 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
#include <stdbool.h>
-#define STRSCAN_VERSION "3.0.0"
+#define STRSCAN_VERSION "3.0.7"
/* =======================================================================
Data Type Definitions
@@ -435,11 +435,11 @@ strscan_get_pos(VALUE self)
*
* In short, it's a 0-based index into the string.
*
- * s = StringScanner.new("abcädeföghi")
- * s.charpos # -> 0
- * s.scan_until(/ä/) # -> "abcä"
- * s.pos # -> 5
- * s.charpos # -> 4
+ * s = StringScanner.new("abc\u00e4def\u00f6ghi")
+ * s.charpos # -> 0
+ * s.scan_until(/\u00e4/) # -> "abc\u00E4"
+ * s.pos # -> 5
+ * s.charpos # -> 4
*/
static VALUE
strscan_get_charpos(VALUE self)
@@ -539,6 +539,68 @@ adjust_register_position(struct strscanner *p, long position)
}
}
+/* rb_reg_onig_match is available in Ruby 3.3 and later. */
+#ifndef HAVE_RB_REG_ONIG_MATCH
+static OnigPosition
+rb_reg_onig_match(VALUE re, VALUE str,
+ OnigPosition (*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args),
+ void *args, struct re_registers *regs)
+{
+ regex_t *reg = rb_reg_prepare_re(re, str);
+
+ bool tmpreg = reg != RREGEXP_PTR(re);
+ if (!tmpreg) RREGEXP(re)->usecnt++;
+
+ OnigPosition result = match(reg, str, regs, args);
+
+ if (!tmpreg) RREGEXP(re)->usecnt--;
+ if (tmpreg) {
+ if (RREGEXP(re)->usecnt) {
+ onig_free(reg);
+ }
+ else {
+ onig_free(RREGEXP_PTR(re));
+ RREGEXP_PTR(re) = reg;
+ }
+ }
+
+ if (result < 0) {
+ if (result != ONIG_MISMATCH) {
+ rb_raise(ScanError, "regexp buffer overflow");
+ }
+ }
+
+ return result;
+}
+#endif
+
+static OnigPosition
+strscan_match(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
+{
+ struct strscanner *p = (struct strscanner *)args_ptr;
+
+ return onig_match(reg,
+ match_target(p),
+ (UChar* )(CURPTR(p) + S_RESTLEN(p)),
+ (UChar* )CURPTR(p),
+ regs,
+ ONIG_OPTION_NONE);
+}
+
+static OnigPosition
+strscan_search(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
+{
+ struct strscanner *p = (struct strscanner *)args_ptr;
+
+ return onig_search(reg,
+ match_target(p),
+ (UChar *)(CURPTR(p) + S_RESTLEN(p)),
+ (UChar *)CURPTR(p),
+ (UChar *)(CURPTR(p) + S_RESTLEN(p)),
+ regs,
+ ONIG_OPTION_NONE);
+}
+
static VALUE
strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly)
{
@@ -560,47 +622,14 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
}
if (RB_TYPE_P(pattern, T_REGEXP)) {
- regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
- regex_t *re;
- long ret;
- int tmpreg;
-
p->regex = pattern;
- re = rb_reg_prepare_re(pattern, p->str);
- tmpreg = re != RREGEXP_PTR(pattern);
- if (!tmpreg) RREGEXP(pattern)->usecnt++;
-
- if (headonly) {
- ret = onig_match(re,
- match_target(p),
- (UChar* )(CURPTR(p) + S_RESTLEN(p)),
- (UChar* )CURPTR(p),
- &(p->regs),
- ONIG_OPTION_NONE);
- }
- else {
- ret = onig_search(re,
- match_target(p),
- (UChar* )(CURPTR(p) + S_RESTLEN(p)),
- (UChar* )CURPTR(p),
- (UChar* )(CURPTR(p) + S_RESTLEN(p)),
- &(p->regs),
- ONIG_OPTION_NONE);
- }
- if (!tmpreg) RREGEXP(pattern)->usecnt--;
- if (tmpreg) {
- if (RREGEXP(pattern)->usecnt) {
- onig_free(re);
- }
- else {
- onig_free(RREGEXP_PTR(pattern));
- RREGEXP_PTR(pattern) = re;
- }
- }
+ OnigPosition ret = rb_reg_onig_match(pattern,
+ p->str,
+ headonly ? strscan_match : strscan_search,
+ (void *)p,
+ &(p->regs));
- if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
- if (ret < 0) {
- /* not matched */
+ if (ret == ONIG_MISMATCH) {
return Qnil;
}
}
@@ -1038,8 +1067,9 @@ strscan_empty_p(VALUE self)
* This method is obsolete; use #eos? instead.
*
* s = StringScanner.new('test string')
- * s.eos? # These two
- * s.rest? # are opposites.
+ * # These two are opposites
+ * s.eos? # => false
+ * s.rest? # => true
*/
static VALUE
strscan_rest_p(VALUE self)
@@ -1458,6 +1488,56 @@ strscan_fixed_anchor_p(VALUE self)
return p->fixed_anchor_p ? Qtrue : Qfalse;
}
+typedef struct {
+ VALUE self;
+ VALUE captures;
+} named_captures_data;
+
+static int
+named_captures_iter(const OnigUChar *name,
+ const OnigUChar *name_end,
+ int back_num,
+ int *back_refs,
+ OnigRegex regex,
+ void *arg)
+{
+ named_captures_data *data = arg;
+
+ VALUE key = rb_str_new((const char *)name, name_end - name);
+ VALUE value = RUBY_Qnil;
+ int i;
+ for (i = 0; i < back_num; i++) {
+ value = strscan_aref(data->self, INT2NUM(back_refs[i]));
+ }
+ rb_hash_aset(data->captures, key, value);
+ return 0;
+}
+
+/*
+ * call-seq:
+ * scanner.named_captures -> hash
+ *
+ * Returns a hash of string variables matching the regular expression.
+ *
+ * scan = StringScanner.new('foobarbaz')
+ * scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)
+ * scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"}
+ */
+static VALUE
+strscan_named_captures(VALUE self)
+{
+ struct strscanner *p;
+ GET_SCANNER(self, p);
+ named_captures_data data;
+ data.self = self;
+ data.captures = rb_hash_new();
+ if (!RB_NIL_P(p->regex)) {
+ onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data);
+ }
+
+ return data.captures;
+}
+
/* =======================================================================
Ruby Interface
======================================================================= */
@@ -1468,6 +1548,8 @@ strscan_fixed_anchor_p(VALUE self)
* StringScanner provides for lexical scanning operations on a String. Here is
* an example of its usage:
*
+ * require 'strscan'
+ *
* s = StringScanner.new('This is an example string')
* s.eos? # -> false
*
@@ -1650,4 +1732,6 @@ Init_strscan(void)
rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0);
+
+ rb_define_method(StringScanner, "named_captures", strscan_named_captures, 0);
}
diff --git a/ext/strscan/strscan.gemspec b/ext/strscan/strscan.gemspec
index 5d8119ea4c..8a61c7abe6 100644
--- a/ext/strscan/strscan.gemspec
+++ b/ext/strscan/strscan.gemspec
@@ -16,13 +16,26 @@ Gem::Specification.new do |s|
s.summary = "Provides lexical scanning operations on a String."
s.description = "Provides lexical scanning operations on a String."
- s.require_path = %w{lib}
- s.files = %w{ext/strscan/extconf.rb ext/strscan/strscan.c}
- s.extensions = %w{ext/strscan/extconf.rb}
+ files = [
+ "COPYING",
+ "LICENSE.txt",
+ ]
+ if RUBY_ENGINE == "jruby"
+ s.require_paths = %w{ext/jruby/lib lib}
+ files << "ext/jruby/lib/strscan.rb"
+ files << "lib/strscan.jar"
+ s.platform = "java"
+ else
+ s.require_paths = %w{lib}
+ files << "ext/strscan/extconf.rb"
+ files << "ext/strscan/strscan.c"
+ s.extensions = %w{ext/strscan/extconf.rb}
+ end
+ s.files = files
s.required_ruby_version = ">= 2.4.0"
- s.authors = ["Minero Aoki", "Sutou Kouhei"]
- s.email = [nil, "kou@cozmixng.org"]
+ s.authors = ["Minero Aoki", "Sutou Kouhei", "Charles Oliver Nutter"]
+ s.email = [nil, "kou@cozmixng.org", "headius@headius.com"]
s.homepage = "https://github.com/ruby/strscan"
s.licenses = ["Ruby", "BSD-2-Clause"]
end
diff --git a/ext/syslog/depend b/ext/syslog/depend
index fb98401e52..4eea8c3bf9 100644
--- a/ext/syslog/depend
+++ b/ext/syslog/depend
@@ -1,6 +1,19 @@
# AUTOGENERATED DEPENDENCIES START
syslog.o: $(RUBY_EXTCONF_H)
syslog.o: $(arch_hdrdir)/ruby/config.h
+syslog.o: $(hdrdir)/ruby/assert.h
+syslog.o: $(hdrdir)/ruby/backward.h
+syslog.o: $(hdrdir)/ruby/backward/2/assume.h
+syslog.o: $(hdrdir)/ruby/backward/2/attributes.h
+syslog.o: $(hdrdir)/ruby/backward/2/bool.h
+syslog.o: $(hdrdir)/ruby/backward/2/inttypes.h
+syslog.o: $(hdrdir)/ruby/backward/2/limits.h
+syslog.o: $(hdrdir)/ruby/backward/2/long_long.h
+syslog.o: $(hdrdir)/ruby/backward/2/stdalign.h
+syslog.o: $(hdrdir)/ruby/backward/2/stdarg.h
+syslog.o: $(hdrdir)/ruby/defines.h
+syslog.o: $(hdrdir)/ruby/intern.h
+syslog.o: $(hdrdir)/ruby/internal/abi.h
syslog.o: $(hdrdir)/ruby/internal/anyargs.h
syslog.o: $(hdrdir)/ruby/internal/arithmetic.h
syslog.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -140,19 +153,6 @@ 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
syslog.o: $(hdrdir)/ruby/ruby.h
syslog.o: $(hdrdir)/ruby/st.h
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
index 4c540fc9c7..8f3674aa8d 100644
--- a/ext/syslog/syslog.c
+++ b/ext/syslog/syslog.c
@@ -165,15 +165,15 @@ static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self)
syslog_ident = strdup(ident_ptr);
if (NIL_P(opt)) {
- syslog_options = LOG_PID | LOG_CONS;
+ syslog_options = LOG_PID | LOG_CONS;
} else {
- syslog_options = NUM2INT(opt);
+ syslog_options = NUM2INT(opt);
}
if (NIL_P(fac)) {
- syslog_facility = LOG_USER;
+ syslog_facility = LOG_USER;
} else {
- syslog_facility = NUM2INT(fac);
+ syslog_facility = NUM2INT(fac);
}
openlog(syslog_ident, syslog_options, syslog_facility);
@@ -307,7 +307,7 @@ static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
pri = *argv++;
if (!FIXNUM_P(pri)) {
- rb_raise(rb_eTypeError, "type mismatch: %"PRIsVALUE" given", rb_obj_class(pri));
+ rb_raise(rb_eTypeError, "type mismatch: %"PRIsVALUE" given", rb_obj_class(pri));
}
syslog_write(FIX2INT(pri), argc, argv);
@@ -322,14 +322,14 @@ static VALUE mSyslog_inspect(VALUE self)
Check_Type(self, T_MODULE);
if (!syslog_opened)
- return rb_sprintf("<#%"PRIsVALUE": opened=false>", self);
+ return rb_sprintf("<#%"PRIsVALUE": opened=false>", self);
return rb_sprintf("<#%"PRIsVALUE": opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
- self,
- syslog_ident,
- syslog_options,
- syslog_facility,
- syslog_mask);
+ self,
+ syslog_ident,
+ syslog_options,
+ syslog_facility,
+ syslog_mask);
}
/* Returns self, for backward compatibility.
diff --git a/ext/syslog/syslog.gemspec b/ext/syslog/syslog.gemspec
index 8f73f5ad0d..6aa2e9570d 100644
--- a/ext/syslog/syslog.gemspec
+++ b/ext/syslog/syslog.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "syslog"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Akinori MUSHA"]
spec.email = ["knu@idaemons.org"]
diff --git a/ext/win32/lib/win32/registry.rb b/ext/win32/lib/win32/registry.rb
index b5b99ff684..bda8bb012f 100644
--- a/ext/win32/lib/win32/registry.rb
+++ b/ext/win32/lib/win32/registry.rb
@@ -69,7 +69,11 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
WCHAR_NUL = "\0".encode(WCHAR).freeze
WCHAR_CR = "\r".encode(WCHAR).freeze
WCHAR_SIZE = WCHAR_NUL.bytesize
- LOCALE = Encoding.find(Encoding.locale_charmap)
+ begin
+ LOCALE = Encoding.find(Encoding.locale_charmap)
+ rescue ArgumentError
+ LOCALE = Encoding::UTF_8
+ end
class Registry
@@ -740,14 +744,11 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# method returns.
#
def write(name, type, data)
- termsize = 0
case type
when REG_SZ, REG_EXPAND_SZ
- data = data.encode(WCHAR)
- termsize = WCHAR_SIZE
+ data = data.encode(WCHAR) << WCHAR_NUL
when REG_MULTI_SZ
data = data.to_a.map {|s| s.encode(WCHAR)}.join(WCHAR_NUL) << WCHAR_NUL
- termsize = WCHAR_SIZE
when REG_BINARY, REG_NONE
data = data.to_s
when REG_DWORD
@@ -759,7 +760,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
else
raise TypeError, "Unsupported type #{Registry.type2name(type)}"
end
- API.SetValue(@hkey, name, type, data, data.bytesize + termsize)
+ API.SetValue(@hkey, name, type, data, data.bytesize)
end
#
diff --git a/ext/win32/resolv/resolv.c b/ext/win32/resolv/resolv.c
index f19243ccc1..8a50ef7824 100644
--- a/ext/win32/resolv/resolv.c
+++ b/ext/win32/resolv/resolv.c
@@ -29,19 +29,19 @@ get_dns_server_list(VALUE self)
ret = GetNetworkParams(NULL, &buflen);
if (ret != NO_ERROR && ret != ERROR_BUFFER_OVERFLOW) {
- w32error_raise(ret);
+ w32error_raise(ret);
}
fixedinfo = ALLOCV(buf, buflen);
ret = GetNetworkParams(fixedinfo, &buflen);
if (ret == NO_ERROR) {
- const IP_ADDR_STRING *ipaddr = &fixedinfo->DnsServerList;
- nameservers = rb_ary_new();
- do {
- const char *s = ipaddr->IpAddress.String;
- if (!*s) continue;
- if (strcmp(s, "0.0.0.0") == 0) continue;
- rb_ary_push(nameservers, rb_str_new_cstr(s));
- } while ((ipaddr = ipaddr->Next) != NULL);
+ const IP_ADDR_STRING *ipaddr = &fixedinfo->DnsServerList;
+ nameservers = rb_ary_new();
+ do {
+ const char *s = ipaddr->IpAddress.String;
+ if (!*s) continue;
+ if (strcmp(s, "0.0.0.0") == 0) continue;
+ rb_ary_push(nameservers, rb_str_new_cstr(s));
+ } while ((ipaddr = ipaddr->Next) != NULL);
}
ALLOCV_END(buf);
if (ret != NO_ERROR) w32error_raise(ret);
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index 5ad6a80eb9..3f083bb12d 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -454,12 +454,12 @@ vtdate2rbtime(double date)
double sec;
VariantTimeToSystemTime(date, &st);
v = rb_funcall(rb_cTime, rb_intern("new"), 6,
- RB_INT2FIX(st.wYear),
- RB_INT2FIX(st.wMonth),
- RB_INT2FIX(st.wDay),
- RB_INT2FIX(st.wHour),
- RB_INT2FIX(st.wMinute),
- RB_INT2FIX(st.wSecond));
+ RB_INT2FIX(st.wYear),
+ RB_INT2FIX(st.wMonth),
+ RB_INT2FIX(st.wDay),
+ RB_INT2FIX(st.wHour),
+ RB_INT2FIX(st.wMinute),
+ RB_INT2FIX(st.wSecond));
st.wYear = RB_FIX2INT(rb_funcall(v, rb_intern("year"), 0));
st.wMonth = RB_FIX2INT(rb_funcall(v, rb_intern("month"), 0));
st.wDay = RB_FIX2INT(rb_funcall(v, rb_intern("mday"), 0));
@@ -568,16 +568,16 @@ load_conv_function51932(void)
void *p;
if (!pIMultiLanguage) {
#if defined(HAVE_TYPE_IMULTILANGUAGE2)
- hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
- &IID_IMultiLanguage2, &p);
+ hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMultiLanguage2, &p);
#elif defined(HAVE_TYPE_IMULTILANGUAGE)
- hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
- &IID_IMultiLanguage, &p);
+ hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMultiLanguage, &p);
#endif
- if (FAILED(hr)) {
- failed_load_conv51932();
- }
- pIMultiLanguage = p;
+ if (FAILED(hr)) {
+ failed_load_conv51932();
+ }
+ pIMultiLanguage = p;
}
}
#define need_conv_function51932() (load_conv_function51932(), 1)
@@ -624,7 +624,7 @@ ole_init_cp(void)
rb_encoding *encdef;
encdef = rb_default_internal_encoding();
if (!encdef) {
- encdef = rb_default_external_encoding();
+ encdef = rb_default_external_encoding();
}
cp = ole_encoding2cp(encdef);
set_ole_codepage(cp);
@@ -650,38 +650,38 @@ ole_cp2encoding(UINT cp)
int idx;
if (!code_page_installed(cp)) {
- switch(cp) {
- case CP_ACP:
- cp = GetACP();
- break;
- case CP_OEMCP:
- cp = GetOEMCP();
- break;
- case CP_MACCP:
- case CP_THREAD_ACP:
- if (!pGetCPInfoEx) {
- pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
- GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
- if (!pGetCPInfoEx) {
- pGetCPInfoEx = (void*)-1;
- }
- }
- buf = ALLOCA_N(struct myCPINFOEX, 1);
- ZeroMemory(buf, sizeof(struct myCPINFOEX));
- if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
- rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
- break; /* never reach here */
- }
- cp = buf->CodePage;
- break;
- case CP_SYMBOL:
- case CP_UTF7:
- case CP_UTF8:
- break;
- case 51932:
- load_conv_function51932();
- break;
- default:
+ switch(cp) {
+ case CP_ACP:
+ cp = GetACP();
+ break;
+ case CP_OEMCP:
+ cp = GetOEMCP();
+ break;
+ case CP_MACCP:
+ case CP_THREAD_ACP:
+ if (!pGetCPInfoEx) {
+ pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
+ GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
+ if (!pGetCPInfoEx) {
+ pGetCPInfoEx = (void*)-1;
+ }
+ }
+ buf = ALLOCA_N(struct myCPINFOEX, 1);
+ ZeroMemory(buf, sizeof(struct myCPINFOEX));
+ if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
+ rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
+ break; /* never reach here */
+ }
+ cp = buf->CodePage;
+ break;
+ case CP_SYMBOL:
+ case CP_UTF7:
+ case CP_UTF8:
+ break;
+ case 51932:
+ load_conv_function51932();
+ break;
+ default:
rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
break;
}
@@ -690,7 +690,7 @@ ole_cp2encoding(UINT cp)
enc_name = rb_sprintf("CP%d", cp);
idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name));
if (idx < 0)
- idx = rb_define_dummy_encoding(enc_cstr);
+ idx = rb_define_dummy_encoding(enc_cstr);
return rb_enc_from_index(idx);
}
@@ -700,14 +700,14 @@ ole_ml_wc2mb_conv0(LPWSTR pw, LPSTR pm, UINT *size)
{
DWORD dw = 0;
return pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
- &dw, cWIN32OLE_cp, pw, NULL, pm, size);
+ &dw, cWIN32OLE_cp, pw, NULL, pm, size);
}
#define ole_ml_wc2mb_conv(pw, pm, size, onfailure) do { \
- HRESULT hr = ole_ml_wc2mb_conv0(pw, pm, &size); \
- if (FAILED(hr)) { \
- onfailure; \
- ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); \
- } \
+ HRESULT hr = ole_ml_wc2mb_conv0(pw, pm, &size); \
+ if (FAILED(hr)) { \
+ onfailure; \
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); \
+ } \
} while (0)
#endif
@@ -720,11 +720,11 @@ ole_wc2mb_alloc(LPWSTR pw, char *(alloc)(UINT size, void *arg), void *arg)
UINT size = 0;
if (conv_51932(cWIN32OLE_cp)) {
#ifndef pIMultiLanguage
- ole_ml_wc2mb_conv(pw, NULL, size, {});
- pm = alloc(size, arg);
- if (size) ole_ml_wc2mb_conv(pw, pm, size, xfree(pm));
- pm[size] = '\0';
- return pm;
+ ole_ml_wc2mb_conv(pw, NULL, size, {});
+ pm = alloc(size, arg);
+ if (size) ole_ml_wc2mb_conv(pw, pm, size, xfree(pm));
+ pm[size] = '\0';
+ return pm;
#endif
}
size = ole_wc2mb_conv(pw, NULL, 0);
@@ -816,8 +816,8 @@ ole_initialize(void)
HRESULT hr;
if(!g_uninitialize_hooked) {
- rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil);
- g_uninitialize_hooked = TRUE;
+ rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil);
+ g_uninitialize_hooked = TRUE;
}
if(g_ole_initialized == FALSE) {
@@ -911,21 +911,21 @@ ole_mb2wc(char *pm, int len, UINT cp)
if (conv_51932(cp)) {
#ifndef pIMultiLanguage
- DWORD dw = 0;
- UINT n = len;
- HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
- &dw, cp, pm, &n, NULL, &size);
- if (FAILED(hr)) {
+ DWORD dw = 0;
+ UINT n = len;
+ HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cp, pm, &n, NULL, &size);
+ if (FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
- }
- pw = SysAllocStringLen(NULL, size);
- n = len;
- hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
- &dw, cp, pm, &n, pw, &size);
- if (FAILED(hr)) {
+ }
+ pw = SysAllocStringLen(NULL, size);
+ n = len;
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cp, pm, &n, pw, &size);
+ if (FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
- }
- return pw;
+ }
+ return pw;
#endif
}
size = MultiByteToWideChar(cp, 0, pm, len, NULL, 0);
@@ -1737,11 +1737,11 @@ reg_get_val(HKEY hkey, const char *subkey)
if (err == ERROR_SUCCESS) {
pbuf[size] = '\0';
if (dwtype == REG_EXPAND_SZ) {
- char* pbuf2 = (char *)pbuf;
- DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0);
- pbuf = ALLOC_N(char, len + 1);
- ExpandEnvironmentStrings(pbuf2, pbuf, len + 1);
- free(pbuf2);
+ char* pbuf2 = (char *)pbuf;
+ DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0);
+ pbuf = ALLOC_N(char, len + 1);
+ ExpandEnvironmentStrings(pbuf2, pbuf, len + 1);
+ free(pbuf2);
}
val = rb_str_new2((char *)pbuf);
}
@@ -2522,12 +2522,12 @@ fole_initialize(int argc, VALUE *argv, VALUE self)
OLE_RELEASE(pIClassFactory2);
}
}
- pDispatch = p;
if(FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError,
"failed to create WIN32OLE object from `%s'",
StringValuePtr(svr_name));
}
+ pDispatch = p;
ole_set_member(self, pDispatch);
return self;
@@ -2555,7 +2555,7 @@ hash2named_arg(VALUE key, VALUE val, VALUE pop)
rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
}
if (RB_TYPE_P(key, T_SYMBOL)) {
- key = rb_sym2str(key);
+ key = rb_sym2str(key);
}
/* pNamedArgs[0] is <method name>, so "index + 1" */
@@ -2619,10 +2619,10 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
rb_scan_args(argc, argv, "1*", &cmd, &paramS);
if(!RB_TYPE_P(cmd, T_STRING) && !RB_TYPE_P(cmd, T_SYMBOL) && !is_bracket) {
- rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
+ rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
}
if (RB_TYPE_P(cmd, T_SYMBOL)) {
- cmd = rb_sym2str(cmd);
+ cmd = rb_sym2str(cmd);
}
pole = oledata_get_struct(self);
if(!pole->pDispatch) {
@@ -2631,7 +2631,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
if (is_bracket) {
DispID = DISPID_VALUE;
argc += 1;
- rb_ary_unshift(paramS, cmd);
+ rb_ary_unshift(paramS, cmd);
} else {
wcmdname = ole_vstr2wc(cmd);
hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
@@ -3639,7 +3639,7 @@ fole_respond_to(VALUE self, VALUE method)
pole = oledata_get_struct(self);
wcmdname = ole_vstr2wc(method);
hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
- &wcmdname, 1, cWIN32OLE_lcid, &DispID);
+ &wcmdname, 1, cWIN32OLE_lcid, &DispID);
SysFreeString(wcmdname);
return SUCCEEDED(hr) ? Qtrue : Qfalse;
}
diff --git a/ext/win32ole/win32ole.gemspec b/ext/win32ole/win32ole.gemspec
index 021625e44e..b6ea8e8a55 100644
--- a/ext/win32ole/win32ole.gemspec
+++ b/ext/win32ole/win32ole.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "win32ole"
- spec.version = "1.8.8"
+ spec.version = "1.8.9"
spec.authors = ["Masaki Suketa"]
spec.email = ["suke@ruby-lang.org"]
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/win32ole"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/ext/win32ole/win32ole_event.c b/ext/win32ole/win32ole_event.c
index 041639af6c..45ebf13433 100644
--- a/ext/win32ole/win32ole_event.c
+++ b/ext/win32ole/win32ole_event.c
@@ -200,7 +200,7 @@ STDMETHODIMP EVENTSINK_Invoke(
}
outargv = Qnil;
if (is_outarg == Qtrue) {
- outargv = rb_ary_new();
+ outargv = rb_ary_new();
rb_ary_push(args, outargv);
}
@@ -413,15 +413,15 @@ hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS
bstrs, pdispparams->cArgs + 1,
&len);
if (FAILED(hr))
- return;
+ return;
for (i = 0; i < len - 1; i++) {
- key = WC2VSTR(bstrs[i + 1]);
+ key = WC2VSTR(bstrs[i + 1]);
val = rb_hash_aref(hash, RB_UINT2NUM(i));
- if (val == Qnil)
- val = rb_hash_aref(hash, key);
- if (val == Qnil)
- val = rb_hash_aref(hash, rb_str_intern(key));
+ if (val == Qnil)
+ val = rb_hash_aref(hash, key);
+ if (val == Qnil)
+ val = rb_hash_aref(hash, rb_str_intern(key));
pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
ole_val2ptr_variant(val, pvar);
}
@@ -433,7 +433,7 @@ hash2result(VALUE hash)
VALUE ret = Qnil;
ret = rb_hash_aref(hash, rb_str_new2("return"));
if (ret == Qnil)
- ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
+ ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
return ret;
}
@@ -610,7 +610,7 @@ find_coclass(
hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
if (FAILED(hr)) {
- return hr;
+ return hr;
}
count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
for (i = 0; i < count && !found; i++) {
@@ -1264,7 +1264,8 @@ Init_win32ole_event(void)
ary_ole_event = rb_ary_new();
rb_gc_register_mark_object(ary_ole_event);
id_events = rb_intern("events");
- cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
+ cWIN32OLE_EVENT = rb_define_class_under(cWIN32OLE, "Event", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_EVENT", cWIN32OLE_EVENT);
rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
diff --git a/ext/win32ole/win32ole_method.c b/ext/win32ole/win32ole_method.c
index bf668300c2..646fdaf60c 100644
--- a/ext/win32ole/win32ole_method.c
+++ b/ext/win32ole/win32ole_method.c
@@ -437,7 +437,7 @@ ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
/*
* call-seq:
- * WIN32OLE_MTHOD#invkind
+ * WIN32OLE_METHOD#invkind
*
* Returns the method invoke kind.
* tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
@@ -927,7 +927,8 @@ VALUE cWIN32OLE_METHOD;
void Init_win32ole_method(void)
{
- cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject);
+ cWIN32OLE_METHOD = rb_define_class_under(cWIN32OLE, "Method", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_METHOD", cWIN32OLE_METHOD);
rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate);
rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2);
rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0);
diff --git a/ext/win32ole/win32ole_param.c b/ext/win32ole/win32ole_param.c
index 52905b3e8e..b654aaa845 100644
--- a/ext/win32ole/win32ole_param.c
+++ b/ext/win32ole/win32ole_param.c
@@ -422,7 +422,8 @@ foleparam_inspect(VALUE self)
void
Init_win32ole_param(void)
{
- cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject);
+ cWIN32OLE_PARAM = rb_define_class_under(cWIN32OLE, "Param", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_PARAM", cWIN32OLE_PARAM);
rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate);
rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2);
rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0);
diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c
index 03523bc47d..9e18653db9 100644
--- a/ext/win32ole/win32ole_record.c
+++ b/ext/win32ole/win32ole_record.c
@@ -594,7 +594,8 @@ VALUE cWIN32OLE_RECORD;
void
Init_win32ole_record(void)
{
- cWIN32OLE_RECORD = rb_define_class("WIN32OLE_RECORD", rb_cObject);
+ cWIN32OLE_RECORD = rb_define_class_under(cWIN32OLE, "Record", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_RECORD", cWIN32OLE_RECORD);
rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate);
rb_define_method(cWIN32OLE_RECORD, "initialize", folerecord_initialize, 2);
rb_define_method(cWIN32OLE_RECORD, "to_h", folerecord_to_h, 0);
diff --git a/ext/win32ole/win32ole_type.c b/ext/win32ole/win32ole_type.c
index 48dbc9dbde..1b96aea858 100644
--- a/ext/win32ole/win32ole_type.c
+++ b/ext/win32ole/win32ole_type.c
@@ -887,7 +887,8 @@ VALUE cWIN32OLE_TYPE;
void Init_win32ole_type(void)
{
- cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject);
+ cWIN32OLE_TYPE = rb_define_class_under(cWIN32OLE, "Type", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_TYPE", cWIN32OLE_TYPE);
rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1);
rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0);
rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0);
diff --git a/ext/win32ole/win32ole_typelib.c b/ext/win32ole/win32ole_typelib.c
index d89f181e07..fb68bebda8 100644
--- a/ext/win32ole/win32ole_typelib.c
+++ b/ext/win32ole/win32ole_typelib.c
@@ -285,7 +285,7 @@ oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr)
hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr);
if (FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError,
- "failed to get library attribute(TLIBATTR) from ITypeLib");
+ "failed to get library attribute(TLIBATTR) from ITypeLib");
}
}
@@ -588,13 +588,13 @@ foletypelib_path(VALUE self)
pTypeLib = itypelib(self);
oletypelib_get_libattr(pTypeLib, &pTLibAttr);
hr = QueryPathOfRegTypeLib(&pTLibAttr->guid,
- pTLibAttr->wMajorVerNum,
- pTLibAttr->wMinorVerNum,
- lcid,
- &bstr);
+ pTLibAttr->wMajorVerNum,
+ pTLibAttr->wMinorVerNum,
+ lcid,
+ &bstr);
if (FAILED(hr)) {
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib");
+ pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib");
}
pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
@@ -722,7 +722,7 @@ typelib_file_from_typelib(VALUE ole)
if (ver == Qnil)
break;
err = reg_open_vkey(hclsid, ver, &hversion);
- if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
+ if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
continue;
fver = atof(StringValuePtr(ver));
typelib = reg_get_val(hversion, NULL);
@@ -827,7 +827,8 @@ VALUE cWIN32OLE_TYPELIB;
void
Init_win32ole_typelib(void)
{
- cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject);
+ cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "Typelib", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_TYPELIB", cWIN32OLE_TYPELIB);
rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0);
rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate);
rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2);
diff --git a/ext/win32ole/win32ole_variable.c b/ext/win32ole/win32ole_variable.c
index 803083156c..e7f58c891e 100644
--- a/ext/win32ole/win32ole_variable.c
+++ b/ext/win32ole/win32ole_variable.c
@@ -369,7 +369,9 @@ VALUE cWIN32OLE_VARIABLE;
void Init_win32ole_variable(void)
{
- cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject);
+ cWIN32OLE_VARIABLE = rb_define_class_under(cWIN32OLE, "Variable", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_VARIABLE", cWIN32OLE_VARIABLE);
+ rb_undef_alloc_func(cWIN32OLE_VARIABLE);
rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0);
rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0);
rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0);
diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c
index 0953fc324c..f1d83ed2e1 100644
--- a/ext/win32ole/win32ole_variant.c
+++ b/ext/win32ole/win32ole_variant.c
@@ -695,7 +695,8 @@ void
Init_win32ole_variant(void)
{
#undef rb_intern
- cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
+ cWIN32OLE_VARIANT = rb_define_class_under(cWIN32OLE, "Variant", rb_cObject);
+ rb_define_const(rb_cObject, "WIN32OLE_VARIANT", cWIN32OLE_VARIANT);
rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
diff --git a/ext/zlib/depend b/ext/zlib/depend
index 9e3443f5d7..15186f8266 100644
--- a/ext/zlib/depend
+++ b/ext/zlib/depend
@@ -2,6 +2,20 @@
zlib.o: $(RUBY_EXTCONF_H)
zlib.o: $(arch_hdrdir)/ruby/config.h
zlib.o: $(hdrdir)/ruby.h
+zlib.o: $(hdrdir)/ruby/assert.h
+zlib.o: $(hdrdir)/ruby/backward.h
+zlib.o: $(hdrdir)/ruby/backward/2/assume.h
+zlib.o: $(hdrdir)/ruby/backward/2/attributes.h
+zlib.o: $(hdrdir)/ruby/backward/2/bool.h
+zlib.o: $(hdrdir)/ruby/backward/2/inttypes.h
+zlib.o: $(hdrdir)/ruby/backward/2/limits.h
+zlib.o: $(hdrdir)/ruby/backward/2/long_long.h
+zlib.o: $(hdrdir)/ruby/backward/2/stdalign.h
+zlib.o: $(hdrdir)/ruby/backward/2/stdarg.h
+zlib.o: $(hdrdir)/ruby/defines.h
+zlib.o: $(hdrdir)/ruby/encoding.h
+zlib.o: $(hdrdir)/ruby/intern.h
+zlib.o: $(hdrdir)/ruby/internal/abi.h
zlib.o: $(hdrdir)/ruby/internal/anyargs.h
zlib.o: $(hdrdir)/ruby/internal/arithmetic.h
zlib.o: $(hdrdir)/ruby/internal/arithmetic/char.h
@@ -71,6 +85,15 @@ zlib.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
zlib.o: $(hdrdir)/ruby/internal/ctype.h
zlib.o: $(hdrdir)/ruby/internal/dllexport.h
zlib.o: $(hdrdir)/ruby/internal/dosish.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/re.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/string.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+zlib.o: $(hdrdir)/ruby/internal/encoding/transcode.h
zlib.o: $(hdrdir)/ruby/internal/error.h
zlib.o: $(hdrdir)/ruby/internal/eval.h
zlib.o: $(hdrdir)/ruby/internal/event.h
@@ -141,20 +164,6 @@ 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
zlib.o: $(hdrdir)/ruby/io.h
zlib.o: $(hdrdir)/ruby/missing.h
zlib.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/zlib/extconf.rb b/ext/zlib/extconf.rb
index d674544f22..5477f49178 100644
--- a/ext/zlib/extconf.rb
+++ b/ext/zlib/extconf.rb
@@ -121,10 +121,12 @@ if have_zlib
$defs << "-DHAVE_CRC32_COMBINE"
$defs << "-DHAVE_ADLER32_COMBINE"
$defs << "-DHAVE_TYPE_Z_CRC_T"
+ $defs << "-DHAVE_TYPE_Z_SIZE_T"
else
have_func('crc32_combine', 'zlib.h')
have_func('adler32_combine', 'zlib.h')
have_type('z_crc_t', 'zlib.h')
+ have_type('z_size_t', 'zlib.h')
end
create_makefile('zlib') {|conf|
diff --git a/ext/zlib/extlibs b/ext/zlib/extlibs
deleted file mode 100644
index a64b37ba5f..0000000000
--- a/ext/zlib/extlibs
+++ /dev/null
@@ -1,8 +0,0 @@
-ver = 1.2.11
-pkg = zlib-$(ver)
-
-https://zlib.net/$(pkg).tar.gz \
- md5:1c9f62f0778697a09d36121ead88e08e \
- sha512:73fd3fff4adeccd4894084c15ddac89890cd10ef105dd5e1835e1e9bbb6a49ff229713bd197d203edfa17c2727700fce65a2a235f07568212d820dca88b528ae \
- #
- win32/$(pkg)-mswin.patch -p0
diff --git a/ext/zlib/win32/zlib-1.2.11-mswin.patch b/ext/zlib/win32/zlib-1.2.11-mswin.patch
deleted file mode 100644
index 8810b4403c..0000000000
--- a/ext/zlib/win32/zlib-1.2.11-mswin.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-diff -ru zlib-1.2.11/gzread.c zlib-1.2.11/gzread.c
---- zlib-1.2.11/gzread.c 2016-12-31 23:37:10.000000000 +0900
-+++ zlib-1.2.11/gzread.c 2020-11-23 19:35:00.550987184 +0900
-@@ -316,7 +316,7 @@
- /* set n to the maximum amount of len that fits in an unsigned int */
- n = -1;
- if (n > len)
-- n = len;
-+ n = (unsigned)len;
-
- /* first just try copying data from the output buffer */
- if (state->x.have) {
-@@ -397,7 +397,7 @@
- }
-
- /* read len or fewer bytes to buf */
-- len = gz_read(state, buf, len);
-+ len = (unsigned)gz_read(state, buf, len);
-
- /* check for an error */
- if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
-@@ -469,7 +469,7 @@
- }
-
- /* nothing there -- try gz_read() */
-- ret = gz_read(state, buf, 1);
-+ ret = (int)gz_read(state, buf, 1);
- return ret < 1 ? -1 : buf[0];
- }
-
-diff -ru zlib-1.2.11/gzwrite.c zlib-1.2.11/gzwrite.c
---- zlib-1.2.11/gzwrite.c 2017-01-15 09:29:40.000000000 +0900
-+++ zlib-1.2.11/gzwrite.c 2020-11-23 19:35:41.530494030 +0900
-@@ -209,7 +209,7 @@
- state->in);
- copy = state->size - have;
- if (copy > len)
-- copy = len;
-+ copy = (unsigned)len;
- memcpy(state->in + have, buf, copy);
- state->strm.avail_in += copy;
- state->x.pos += copy;
-@@ -229,7 +229,7 @@
- do {
- unsigned n = (unsigned)-1;
- if (n > len)
-- n = len;
-+ n = (unsigned)len;
- state->strm.avail_in = n;
- state->x.pos += n;
- if (gz_comp(state, Z_NO_FLUSH) == -1)
-@@ -368,7 +368,7 @@
-
- /* write string */
- len = strlen(str);
-- ret = gz_write(state, str, len);
-+ ret = (int)gz_write(state, str, len);
- return ret == 0 && len != 0 ? -1 : ret;
- }
-
-diff -ru zlib-1.2.11/win32/Makefile.msc zlib-1.2.11/win32/Makefile.msc
---- zlib-1.2.11/win32/Makefile.msc 2017-01-15 09:07:08.000000000 +0900
-+++ zlib-1.2.11/win32/Makefile.msc 2020-11-23 22:37:19.746500208 +0900
-@@ -37,6 +37,22 @@
- gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj
- OBJA =
-
-+!ifdef USE_ASM
-+LOC = -DASMV -DASMINF
-+!if "$(ARCH)" == "i386"
-+OBJA = inffas32.obj match686.obj
-+!else if "$(ARCH)" == "x64"
-+AS = ml64
-+LOC = $(LOC) -I.
-+OBJA = inffasx64.obj gvmat64.obj inffas8664.obj
-+!endif
-+!endif
-+
-+!if "$(ARCH)" == "x64"
-+ZBASE = 0x5A4C000000
-+!else
-+ZBASE = 0x5A4C0000
-+!endif
-
- # targets
- all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
-@@ -49,7 +65,7 @@
-
- $(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res
- $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \
-- -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res
-+ -out:$@ -base:$(ZBASE) $(OBJS) $(OBJA) zlib1.res
- if exist $@.manifest \
- mt -nologo -manifest $@.manifest -outputresource:$@;2
-
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 794cf3b103..aefdba0ebd 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 "3.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)
@@ -44,6 +44,14 @@
#endif
#endif
+#if defined(HAVE_TYPE_Z_SIZE_T)
+typedef uLong (*checksum_func)(uLong, const Bytef*, z_size_t);
+# define crc32 crc32_z
+# define adler32 adler32_z
+#else
+typedef uLong (*checksum_func)(uLong, const Bytef*, uInt);
+#endif
+
#if SIZEOF_LONG > SIZEOF_INT
static inline uInt
max_uint(long n)
@@ -65,7 +73,7 @@ static ID id_dictionaries, id_read, id_buffer;
static NORETURN(void raise_zlib_error(int, const char*));
static VALUE rb_zlib_version(VALUE);
-static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
+static VALUE do_checksum(int, VALUE*, checksum_func);
static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
static VALUE rb_zlib_crc_table(VALUE);
@@ -288,6 +296,7 @@ static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
* - Zlib::MemError
* - Zlib::BufError
* - Zlib::VersionError
+ * - Zlib::InProgressError
*
* (if you have GZIP_SUPPORT)
* - Zlib::GzipReader
@@ -304,7 +313,7 @@ void Init_zlib(void);
/*--------- Exceptions --------*/
static VALUE cZError, cStreamEnd, cNeedDict;
-static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError;
+static VALUE cStreamError, cDataError, cMemError, cBufError, cVersionError, cInProgressError;
static void
raise_zlib_error(int err, const char *msg)
@@ -354,7 +363,9 @@ raise_zlib_error(int err, const char *msg)
static void
finalizer_warn(const char *msg)
{
+#if 0
fprintf(stderr, "zlib(finalizer): %s\n", msg);
+#endif
}
@@ -371,26 +382,32 @@ rb_zlib_version(VALUE klass)
return rb_str_new2(zlibVersion());
}
-#if SIZEOF_LONG > SIZEOF_INT
+#if SIZEOF_LONG * CHAR_BIT > 32
+# define mask32(x) ((x) & 0xffffffff)
+#else
+# define mask32(x) (x)
+#endif
+
+#if SIZEOF_LONG > SIZEOF_INT && !defined(HAVE_TYPE_Z_SIZE_T)
static uLong
checksum_long(uLong (*func)(uLong, const Bytef*, uInt), uLong sum, const Bytef *ptr, long len)
{
if (len > UINT_MAX) {
do {
- sum = func(sum, ptr, UINT_MAX);
+ sum = func(mask32(sum), ptr, UINT_MAX);
ptr += UINT_MAX;
len -= UINT_MAX;
} while (len >= UINT_MAX);
}
- if (len > 0) sum = func(sum, ptr, (uInt)len);
+ if (len > 0) sum = func(mask32(sum), ptr, (uInt)len);
return sum;
}
#else
-#define checksum_long(func, sum, ptr, len) (func)((sum), (ptr), (len))
+#define checksum_long(func, sum, ptr, len) (func)(mask32(sum), (ptr), (len))
#endif
static VALUE
-do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
+do_checksum(int argc, VALUE *argv, checksum_func func)
{
VALUE str, vsum;
unsigned long sum;
@@ -408,7 +425,7 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
}
if (NIL_P(str)) {
- sum = func(sum, Z_NULL, 0);
+ sum = func(mask32(sum), Z_NULL, 0);
}
else if (rb_obj_is_kind_of(str, rb_cIO)) {
VALUE buf;
@@ -458,7 +475,7 @@ rb_zlib_adler32(int argc, VALUE *argv, VALUE klass)
*
* call-seq: Zlib.adler32_combine(adler1, adler2, len2)
*
- * Combine two Adler-32 check values in to one. +alder1+ is the first Adler-32
+ * Combine two Adler-32 check values in to one. +adler1+ is the first Adler-32
* value, +adler2+ is the second Adler-32 value. +len2+ is the length of the
* string used to generate +adler2+.
*
@@ -555,14 +572,15 @@ struct zstream {
} *func;
};
-#define ZSTREAM_FLAG_READY 0x1
-#define ZSTREAM_FLAG_IN_STREAM 0x2
-#define ZSTREAM_FLAG_FINISHED 0x4
-#define ZSTREAM_FLAG_CLOSING 0x8
-#define ZSTREAM_FLAG_GZFILE 0x10 /* disallows yield from expand_buffer for
+#define ZSTREAM_FLAG_READY (1 << 0)
+#define ZSTREAM_FLAG_IN_STREAM (1 << 1)
+#define ZSTREAM_FLAG_FINISHED (1 << 2)
+#define ZSTREAM_FLAG_CLOSING (1 << 3)
+#define ZSTREAM_FLAG_GZFILE (1 << 4) /* disallows yield from expand_buffer for
gzip*/
-#define ZSTREAM_REUSE_BUFFER 0x20
-#define ZSTREAM_FLAG_UNUSED 0x40
+#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)
@@ -591,7 +609,9 @@ static const struct zstream_funcs inflate_funcs = {
};
struct zstream_run_args {
- struct zstream * z;
+ struct zstream *const z;
+ Bytef *src;
+ long len;
int flush; /* stream flush value for inflate() or deflate() */
int interrupt; /* stop processing the stream and return to ruby */
int jump_state; /* for buffer expansion block break or exception */
@@ -892,7 +912,6 @@ zstream_discard_input(struct zstream *z, long len)
}
rb_str_resize(z->input, newlen);
if (newlen == 0) {
- rb_gc_force_recycle(z->input);
z->input = Qnil;
}
else {
@@ -1057,19 +1076,18 @@ zstream_unblock_func(void *ptr)
args->interrupt = 1;
}
-static void
-zstream_run0(struct zstream *z, Bytef *src, long len, int flush)
+static VALUE
+zstream_run_try(VALUE value_arg)
{
- struct zstream_run_args args;
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+ struct zstream *z = args->z;
+ Bytef *src = args->src;
+ long len = args->len;
+ int flush = args->flush;
+
int err;
VALUE old_input = Qnil;
- args.z = z;
- args.flush = flush;
- args.interrupt = 0;
- args.jump_state = 0;
- args.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p();
-
if (NIL_P(z->input) && len == 0) {
z->stream.next_in = (Bytef*)"";
z->stream.avail_in = 0;
@@ -1091,17 +1109,17 @@ zstream_run0(struct zstream *z, Bytef *src, long len, int flush)
loop:
#ifndef RB_NOGVL_UBF_ASYNC_SAFE
- err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)&args,
- zstream_unblock_func, (void *)&args);
+ err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)args,
+ zstream_unblock_func, (void *)args);
#else
- err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
- zstream_unblock_func, (void *)&args,
+ err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args,
+ zstream_unblock_func, (void *)args,
RB_NOGVL_UBF_ASYNC_SAFE);
#endif
/* retry if no exception is thrown */
- if (err == Z_OK && args.interrupt) {
- args.interrupt = 0;
+ if (err == Z_OK && args->interrupt) {
+ args->interrupt = 0;
goto loop;
}
@@ -1135,37 +1153,54 @@ loop:
}
if (!NIL_P(old_input)) {
rb_str_resize(old_input, 0);
- rb_gc_force_recycle(old_input);
}
- if (args.jump_state)
- rb_jump_tag(args.jump_state);
+ if (args->jump_state)
+ rb_jump_tag(args->jump_state);
+
+ return Qnil;
}
-struct zstream_run_synchronized_args {
- struct zstream *z;
- Bytef *src;
- long len;
- int flush;
-};
+static VALUE
+zstream_run_ensure(VALUE value_arg)
+{
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+
+ /* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */
+ args->z->flags &= ~ZSTREAM_IN_PROGRESS;
+
+ return Qnil;
+}
static VALUE
zstream_run_synchronized(VALUE value_arg)
{
- struct zstream_run_synchronized_args *run_args = (struct zstream_run_synchronized_args *)value_arg;
- zstream_run0(run_args->z, run_args->src, run_args->len, run_args->flush);
+ struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+
+ /* Cannot start zstream while it is in progress. */
+ if (args->z->flags & ZSTREAM_IN_PROGRESS) {
+ rb_raise(cInProgressError, "zlib stream is in progress");
+ }
+ args->z->flags |= ZSTREAM_IN_PROGRESS;
+
+ rb_ensure(zstream_run_try, value_arg, zstream_run_ensure, value_arg);
+
return Qnil;
}
static void
zstream_run(struct zstream *z, Bytef *src, long len, int flush)
{
- struct zstream_run_synchronized_args run_args;
- run_args.z = z;
- run_args.src = src;
- run_args.len = len;
- run_args.flush = flush;
- rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&run_args);
+ struct zstream_run_args args = {
+ .z = z,
+ .src = src,
+ .len = len,
+ .flush = flush,
+ .interrupt = 0,
+ .jump_state = 0,
+ .stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(),
+ };
+ rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args);
}
static VALUE
@@ -2904,8 +2939,6 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf)
if (!NIL_P(outbuf)) {
rb_str_resize(outbuf, RSTRING_LEN(dst));
memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
- rb_str_resize(dst, 0);
- rb_gc_force_recycle(dst);
dst = outbuf;
}
return dst;
@@ -4197,17 +4230,17 @@ gzreader_charboundary(struct gzfile *gz, long n)
{
char *s = RSTRING_PTR(gz->z.buf);
char *e = s + ZSTREAM_BUF_FILLED(&gz->z);
- char *p = rb_enc_left_char_head(s, s + n, e, gz->enc);
+ char *p = rb_enc_left_char_head(s, s + n - 1, e, gz->enc);
long l = p - s;
if (l < n) {
- n = rb_enc_precise_mbclen(p, e, gz->enc);
- if (MBCLEN_NEEDMORE_P(n)) {
- if ((l = gzfile_fill(gz, l + MBCLEN_NEEDMORE_LEN(n))) > 0) {
+ int n_bytes = rb_enc_precise_mbclen(p, e, gz->enc);
+ if (MBCLEN_NEEDMORE_P(n_bytes)) {
+ if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes))) > 0) {
return l;
}
}
- else if (MBCLEN_CHARFOUND_P(n)) {
- return l + MBCLEN_CHARFOUND_LEN(n);
+ else if (MBCLEN_CHARFOUND_P(n_bytes)) {
+ return l + MBCLEN_CHARFOUND_LEN(n_bytes);
}
}
return n;
@@ -4617,6 +4650,7 @@ Init_zlib(void)
cMemError = rb_define_class_under(mZlib, "MemError", cZError);
cBufError = rb_define_class_under(mZlib, "BufError", cZError);
cVersionError = rb_define_class_under(mZlib, "VersionError", cZError);
+ cInProgressError = rb_define_class_under(mZlib, "InProgressError", cZError);
rb_define_module_function(mZlib, "zlib_version", rb_zlib_version, 0);
rb_define_module_function(mZlib, "adler32", rb_zlib_adler32, -1);
@@ -4924,6 +4958,7 @@ Init_zlib(void)
* - Zlib::MemError
* - Zlib::BufError
* - Zlib::VersionError
+ * - Zlib::InProgressError
*
*/
@@ -4999,6 +5034,20 @@ Init_zlib(void)
*/
/*
+ * Document-class: Zlib::InProgressError
+ *
+ * Subclass of Zlib::Error. This error is raised when the zlib
+ * stream is currently in progress.
+ *
+ * For example:
+ *
+ * inflater = Zlib::Inflate.new
+ * inflater.inflate(compressed) do
+ * inflater.inflate(compressed) # Raises Zlib::InProgressError
+ * end
+ */
+
+/*
* Document-class: Zlib::GzipFile::Error
*
* Base class of errors that occur when processing GZIP files.
diff --git a/file.c b/file.c
index 4ea8de6d20..3a8439ef07 100644
--- a/file.c
+++ b/file.c
@@ -115,6 +115,8 @@ int flock(int, int);
# define link(f, t) rb_w32_ulink((f), (t))
# undef unlink
# define unlink(p) rb_w32_uunlink(p)
+# undef readlink
+# define readlink(f, t, l) rb_w32_ureadlink((f), (t), (l))
# undef rename
# define rename(f, t) rb_w32_urename((f), (t))
# undef symlink
@@ -182,15 +184,15 @@ file_path_convert(VALUE name)
int fname_encidx = ENCODING_GET(name);
int fs_encidx;
if (ENCINDEX_US_ASCII != fname_encidx &&
- ENCINDEX_ASCII != fname_encidx &&
- (fs_encidx = rb_filesystem_encindex()) != fname_encidx &&
- rb_default_internal_encoding() &&
- !rb_enc_str_asciionly_p(name)) {
- /* Don't call rb_filesystem_encoding() before US-ASCII and ASCII-8BIT */
- /* fs_encoding should be ascii compatible */
- rb_encoding *fname_encoding = rb_enc_from_index(fname_encidx);
- rb_encoding *fs_encoding = rb_enc_from_index(fs_encidx);
- name = rb_str_conv_enc(name, fname_encoding, fs_encoding);
+ ENCINDEX_ASCII_8BIT != fname_encidx &&
+ (fs_encidx = rb_filesystem_encindex()) != fname_encidx &&
+ rb_default_internal_encoding() &&
+ !rb_enc_str_asciionly_p(name)) {
+ /* Don't call rb_filesystem_encoding() before US-ASCII and ASCII-8BIT */
+ /* fs_encoding should be ascii compatible */
+ rb_encoding *fname_encoding = rb_enc_from_index(fname_encidx);
+ rb_encoding *fs_encoding = rb_enc_from_index(fs_encidx);
+ name = rb_str_conv_enc(name, fname_encoding, fs_encoding);
}
#endif
return name;
@@ -201,8 +203,8 @@ check_path_encoding(VALUE str)
{
rb_encoding *enc = rb_enc_get(str);
if (!rb_enc_asciicompat(enc)) {
- rb_raise(rb_eEncCompatError, "path name must be ASCII-compatible (%s): %"PRIsVALUE,
- rb_enc_name(enc), rb_str_inspect(str));
+ rb_raise(rb_eEncCompatError, "path name must be ASCII-compatible (%s): %"PRIsVALUE,
+ rb_enc_name(enc), rb_str_inspect(str));
}
return enc;
}
@@ -214,7 +216,7 @@ rb_get_path_check_to_string(VALUE obj)
ID to_path;
if (RB_TYPE_P(obj, T_STRING)) {
- return obj;
+ return obj;
}
CONST_ID(to_path, "to_path");
tmp = rb_check_funcall_default(obj, to_path, 0, 0, obj);
@@ -229,7 +231,7 @@ rb_get_path_check_convert(VALUE obj)
check_path_encoding(obj);
if (!rb_str_to_cstr(obj)) {
- rb_raise(rb_eArgError, "path name contains null byte");
+ rb_raise(rb_eArgError, "path name contains null byte");
}
return rb_str_new4(obj);
@@ -253,14 +255,14 @@ rb_str_encode_ospath(VALUE path)
#if USE_OSPATH
int encidx = ENCODING_GET(path);
#if 0 && defined _WIN32
- if (encidx == ENCINDEX_ASCII) {
- encidx = rb_filesystem_encindex();
+ if (encidx == ENCINDEX_ASCII_8BIT) {
+ encidx = rb_filesystem_encindex();
}
#endif
- if (encidx != ENCINDEX_ASCII && encidx != ENCINDEX_UTF_8) {
- rb_encoding *enc = rb_enc_from_index(encidx);
- rb_encoding *utf8 = rb_utf8_encoding();
- path = rb_str_conv_enc(path, enc, utf8);
+ if (encidx != ENCINDEX_ASCII_8BIT && encidx != ENCINDEX_UTF_8) {
+ rb_encoding *enc = rb_enc_from_index(encidx);
+ rb_encoding *utf8 = rb_utf8_encoding();
+ path = rb_str_conv_enc(path, enc, utf8);
}
#endif
return path;
@@ -268,15 +270,55 @@ 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)
{
CFIndex buflen = 0;
CFRange all;
CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
- (const UInt8 *)ptr, len,
- kCFStringEncodingUTF8, FALSE,
- kCFAllocatorNull);
+ (const UInt8 *)ptr, len,
+ kCFStringEncodingUTF8, FALSE,
+ kCFAllocatorNull);
CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault, len, s);
long oldlen = RSTRING_LEN(str);
@@ -285,7 +327,7 @@ rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
CFStringGetBytes(m, all, kCFStringEncodingUTF8, '?', FALSE, NULL, 0, &buflen);
rb_str_modify_expand(str, buflen);
CFStringGetBytes(m, all, kCFStringEncodingUTF8, '?', FALSE,
- (UInt8 *)(RSTRING_PTR(str) + oldlen), buflen, &buflen);
+ (UInt8 *)(RSTRING_PTR(str) + oldlen), buflen, &buflen);
rb_str_set_len(str, oldlen + buflen);
CFRelease(m);
CFRelease(s);
@@ -303,34 +345,34 @@ rb_str_normalize_ospath(const char *ptr, long len)
rb_enc_associate(str, enc);
while (p < e) {
- int l, c;
- int r = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(r)) {
- /* invalid byte shall not happen but */
- static const char invalid[3] = "\xEF\xBF\xBD";
- rb_str_append_normalized_ospath(str, p1, p-p1);
- rb_str_cat(str, invalid, sizeof(invalid));
- p += 1;
- p1 = p;
- continue;
- }
- l = MBCLEN_CHARFOUND_LEN(r);
- c = rb_enc_mbc_to_codepoint(p, e, enc);
- if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
- (0x2F800 <= c && c <= 0x2FAFF)) {
- if (p - p1 > 0) {
- rb_str_append_normalized_ospath(str, p1, p-p1);
- }
- rb_str_cat(str, p, l);
- p += l;
- p1 = p;
- }
- else {
- p += l;
- }
+ int l, c;
+ int r = rb_enc_precise_mbclen(p, e, enc);
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ /* invalid byte shall not happen but */
+ static const char invalid[3] = "\xEF\xBF\xBD";
+ rb_str_append_normalized_ospath(str, p1, p-p1);
+ rb_str_cat(str, invalid, sizeof(invalid));
+ p += 1;
+ p1 = p;
+ continue;
+ }
+ l = MBCLEN_CHARFOUND_LEN(r);
+ c = rb_enc_mbc_to_codepoint(p, e, enc);
+ if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
+ (0x2F800 <= c && c <= 0x2FAFF)) {
+ if (p - p1 > 0) {
+ rb_str_append_normalized_ospath(str, p1, p-p1);
+ }
+ rb_str_cat(str, p, l);
+ p += l;
+ p1 = p;
+ }
+ else {
+ p += l;
+ }
}
if (p - p1 > 0) {
- rb_str_append_normalized_ospath(str, p1, p-p1);
+ rb_str_append_normalized_ospath(str, p1, p-p1);
}
return str;
@@ -343,27 +385,27 @@ ignored_char_p(const char *p, const char *e, rb_encoding *enc)
if (p+3 > e) return 0;
switch ((unsigned char)*p) {
case 0xe2:
- switch ((unsigned char)p[1]) {
- case 0x80:
- c = (unsigned char)p[2];
- /* c >= 0x200c && c <= 0x200f */
- if (c >= 0x8c && c <= 0x8f) return 3;
- /* c >= 0x202a && c <= 0x202e */
- if (c >= 0xaa && c <= 0xae) return 3;
- return 0;
- case 0x81:
- c = (unsigned char)p[2];
- /* c >= 0x206a && c <= 0x206f */
- if (c >= 0xaa && c <= 0xaf) return 3;
- return 0;
- }
- break;
+ switch ((unsigned char)p[1]) {
+ case 0x80:
+ c = (unsigned char)p[2];
+ /* c >= 0x200c && c <= 0x200f */
+ if (c >= 0x8c && c <= 0x8f) return 3;
+ /* c >= 0x202a && c <= 0x202e */
+ if (c >= 0xaa && c <= 0xae) return 3;
+ return 0;
+ case 0x81:
+ c = (unsigned char)p[2];
+ /* c >= 0x206a && c <= 0x206f */
+ if (c >= 0xaa && c <= 0xaf) return 3;
+ return 0;
+ }
+ break;
case 0xef:
- /* c == 0xfeff */
- if ((unsigned char)p[1] == 0xbb &&
- (unsigned char)p[2] == 0xbf)
- return 3;
- break;
+ /* c == 0xfeff */
+ if ((unsigned char)p[1] == 0xbb &&
+ (unsigned char)p[2] == 0xbf)
+ return 3;
+ break;
}
return 0;
}
@@ -393,10 +435,10 @@ no_gvl_apply2files(void *ptr)
struct apply_arg *aa = ptr;
for (aa->i = 0; aa->i < aa->argc; aa->i++) {
- if (aa->func(aa->fn[aa->i].ptr, aa->arg) < 0) {
- aa->errnum = errno;
- break;
- }
+ if (aa->func(aa->fn[aa->i].ptr, aa->arg) < 0) {
+ aa->errnum = errno;
+ break;
+ }
}
return 0;
}
@@ -420,63 +462,28 @@ apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg)
aa->func = func;
for (aa->i = 0; aa->i < argc; aa->i++) {
- VALUE path = rb_get_path(argv[aa->i]);
+ VALUE path = rb_get_path(argv[aa->i]);
- path = rb_str_encode_ospath(path);
- aa->fn[aa->i].ptr = RSTRING_PTR(path);
- aa->fn[aa->i].path = path;
+ path = rb_str_encode_ospath(path);
+ aa->fn[aa->i].ptr = RSTRING_PTR(path);
+ aa->fn[aa->i].path = path;
}
rb_thread_call_without_gvl(no_gvl_apply2files, aa, RUBY_UBF_IO, 0);
if (aa->errnum) {
#ifdef UTIME_EINVAL
- if (func == utime_internal) {
- utime_failed(aa);
- }
+ if (func == utime_internal) {
+ utime_failed(aa);
+ }
#endif
- rb_syserr_fail_path(aa->errnum, aa->fn[aa->i].path);
+ rb_syserr_fail_path(aa->errnum, aa->fn[aa->i].path);
}
if (v) {
- ALLOCV_END(v);
+ ALLOCV_END(v);
}
return LONG2FIX(argc);
}
-/*
- * call-seq:
- * file.path -> filename
- * file.to_path -> filename
- *
- * Returns the pathname used to create <i>file</i> as a string. Does
- * not normalize the name.
- *
- * The pathname may not point to the file corresponding to <i>file</i>.
- * For instance, the pathname becomes void when the file has been
- * moved or deleted.
- *
- * This method raises IOError for a <i>file</i> created using
- * File::Constants::TMPFILE because they don't have a pathname.
- *
- * File.new("testfile").path #=> "testfile"
- * File.new("/tmp/../tmp/xxx", "w").path #=> "/tmp/../tmp/xxx"
- *
- */
-
-static VALUE
-rb_file_path(VALUE obj)
-{
- rb_io_t *fptr;
-
- fptr = RFILE(rb_io_taint_check(obj))->fptr;
- rb_io_check_initialized(fptr);
-
- if (NIL_P(fptr->pathv)) {
- rb_raise(rb_eIOError, "File is unnamed (TMPFILE?)");
- }
-
- return rb_str_dup(fptr->pathv);
-}
-
static size_t
stat_memsize(const void *p)
{
@@ -496,9 +503,9 @@ stat_new_0(VALUE klass, const struct stat *st)
VALUE obj = TypedData_Wrap_Struct(klass, &stat_data_type, 0);
if (st) {
- nst = ALLOC(struct stat);
- *nst = *st;
- RTYPEDDATA_DATA(obj) = nst;
+ nst = ALLOC(struct stat);
+ *nst = *st;
+ RTYPEDDATA_DATA(obj) = nst;
}
return obj;
}
@@ -886,12 +893,17 @@ stat_atimespec(const struct stat *st)
}
static VALUE
-stat_atime(const struct stat *st)
+stat_time(const struct timespec ts)
{
- struct timespec ts = stat_atimespec(st);
return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
}
+static VALUE
+stat_atime(const struct stat *st)
+{
+ return stat_time(stat_atimespec(st));
+}
+
static struct timespec
stat_mtimespec(const struct stat *st)
{
@@ -912,8 +924,7 @@ stat_mtimespec(const struct stat *st)
static VALUE
stat_mtime(const struct stat *st)
{
- struct timespec ts = stat_mtimespec(st);
- return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
+ return stat_time(stat_mtimespec(st));
}
static struct timespec
@@ -936,8 +947,7 @@ stat_ctimespec(const struct stat *st)
static VALUE
stat_ctime(const struct stat *st)
{
- struct timespec ts = stat_ctimespec(st);
- return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
+ return stat_time(stat_ctimespec(st));
}
#define HAVE_STAT_BIRTHTIME
@@ -975,7 +985,7 @@ rb_stat_atime(VALUE self)
/*
* call-seq:
- * stat.mtime -> aTime
+ * stat.mtime -> time
*
* Returns the modification time of <i>stat</i>.
*
@@ -991,7 +1001,7 @@ rb_stat_mtime(VALUE self)
/*
* call-seq:
- * stat.ctime -> aTime
+ * stat.ctime -> time
*
* Returns the change time for <i>stat</i> (that is, the time
* directory information about the file was changed, not the file
@@ -1012,7 +1022,7 @@ rb_stat_ctime(VALUE self)
#if defined(HAVE_STAT_BIRTHTIME)
/*
* call-seq:
- * stat.birthtime -> aTime
+ * stat.birthtime -> time
*
* Returns the birth time for <i>stat</i>.
*
@@ -1062,24 +1072,24 @@ rb_stat_inspect(VALUE self)
VALUE str;
size_t i;
static const struct {
- const char *name;
- VALUE (*func)(VALUE);
+ const char *name;
+ VALUE (*func)(VALUE);
} member[] = {
- {"dev", rb_stat_dev},
- {"ino", rb_stat_ino},
- {"mode", rb_stat_mode},
- {"nlink", rb_stat_nlink},
- {"uid", rb_stat_uid},
- {"gid", rb_stat_gid},
- {"rdev", rb_stat_rdev},
- {"size", rb_stat_size},
- {"blksize", rb_stat_blksize},
- {"blocks", rb_stat_blocks},
- {"atime", rb_stat_atime},
- {"mtime", rb_stat_mtime},
- {"ctime", rb_stat_ctime},
+ {"dev", rb_stat_dev},
+ {"ino", rb_stat_ino},
+ {"mode", rb_stat_mode},
+ {"nlink", rb_stat_nlink},
+ {"uid", rb_stat_uid},
+ {"gid", rb_stat_gid},
+ {"rdev", rb_stat_rdev},
+ {"size", rb_stat_size},
+ {"blksize", rb_stat_blksize},
+ {"blocks", rb_stat_blocks},
+ {"atime", rb_stat_atime},
+ {"mtime", rb_stat_mtime},
+ {"ctime", rb_stat_ctime},
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
- {"birthtime", rb_stat_birthtime},
+ {"birthtime", rb_stat_birthtime},
#endif
};
@@ -1094,23 +1104,23 @@ rb_stat_inspect(VALUE self)
rb_str_buf_cat2(str, " ");
for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
- VALUE v;
-
- if (i > 0) {
- rb_str_buf_cat2(str, ", ");
- }
- rb_str_buf_cat2(str, member[i].name);
- rb_str_buf_cat2(str, "=");
- v = (*member[i].func)(self);
- if (i == 2) { /* mode */
- rb_str_catf(str, "0%lo", (unsigned long)NUM2ULONG(v));
- }
- else if (i == 0 || i == 6) { /* dev/rdev */
- rb_str_catf(str, "0x%"PRI_DEVT_PREFIX"x", NUM2DEVT(v));
- }
- else {
- rb_str_append(str, rb_inspect(v));
- }
+ VALUE v;
+
+ if (i > 0) {
+ rb_str_buf_cat2(str, ", ");
+ }
+ rb_str_buf_cat2(str, member[i].name);
+ rb_str_buf_cat2(str, "=");
+ v = (*member[i].func)(self);
+ if (i == 2) { /* mode */
+ rb_str_catf(str, "0%lo", (unsigned long)NUM2ULONG(v));
+ }
+ else if (i == 0 || i == 6) { /* dev/rdev */
+ rb_str_catf(str, "0x%"PRI_DEVT_PREFIX"x", NUM2DEVT(v));
+ }
+ else {
+ rb_str_append(str, rb_inspect(v));
+ }
}
rb_str_buf_cat2(str, ">");
@@ -1120,8 +1130,8 @@ rb_stat_inspect(VALUE self)
typedef struct no_gvl_stat_data {
struct stat *st;
union {
- const char *path;
- int fd;
+ const char *path;
+ int fd;
} file;
} no_gvl_stat_data;
@@ -1159,7 +1169,7 @@ stat_without_gvl(const char *path, struct stat *st)
data.st = st;
return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data,
- RUBY_UBF_IO, NULL);
+ RUBY_UBF_IO, NULL);
}
#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
@@ -1289,16 +1299,16 @@ rb_stat(VALUE file, struct stat *st)
tmp = rb_check_convert_type_with_id(file, T_FILE, "IO", idTo_io);
if (!NIL_P(tmp)) {
- rb_io_t *fptr;
+ rb_io_t *fptr;
- GetOpenFile(tmp, fptr);
- result = fstat_without_gvl(fptr->fd, st);
- file = tmp;
+ GetOpenFile(tmp, fptr);
+ result = fstat_without_gvl(fptr->fd, st);
+ file = tmp;
}
else {
- FilePathValue(file);
- file = rb_str_encode_ospath(file);
- result = stat_without_gvl(RSTRING_PTR(file), st);
+ FilePathValue(file);
+ file = rb_str_encode_ospath(file);
+ result = stat_without_gvl(RSTRING_PTR(file), st);
}
RB_GC_GUARD(file);
return result;
@@ -1306,11 +1316,11 @@ rb_stat(VALUE file, struct stat *st)
/*
* call-seq:
- * File.stat(file_name) -> stat
+ * File.stat(filepath) -> stat
*
- * Returns a File::Stat object for the named file (see File::Stat).
+ * Returns a File::Stat object for the file at +filepath+ (see File::Stat):
*
- * File.stat("testfile").mtime #=> Tue Apr 08 12:58:04 CDT 2003
+ * File.stat('t.txt').class # => File::Stat
*
*/
@@ -1322,7 +1332,7 @@ rb_file_s_stat(VALUE klass, VALUE fname)
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (stat_without_gvl(RSTRING_PTR(fname), &st) < 0) {
- rb_sys_fail_path(fname);
+ rb_sys_fail_path(fname);
}
return rb_stat_new(&st);
}
@@ -1350,7 +1360,7 @@ rb_io_stat(VALUE obj)
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return rb_stat_new(&st);
}
@@ -1372,21 +1382,20 @@ lstat_without_gvl(const char *path, struct stat *st)
data.st = st;
return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_lstat, &data,
- RUBY_UBF_IO, NULL);
+ RUBY_UBF_IO, NULL);
}
#endif /* HAVE_LSTAT */
/*
* call-seq:
- * File.lstat(file_name) -> stat
+ * File.lstat(filepath) -> stat
*
- * Same as File::stat, but does not follow the last symbolic link.
- * Instead, reports on the link itself.
+ * Like File::stat, but does not follow the last symbolic link;
+ * instead, returns a File::Stat object for the link itself.
*
- * File.symlink("testfile", "link2test") #=> 0
- * File.stat("testfile").size #=> 66
- * File.lstat("link2test").size #=> 8
- * File.stat("link2test").size #=> 66
+ * File.symlink('t.txt', 'symlink')
+ * File.stat('symlink').size # => 47
+ * File.lstat('symlink').size # => 5
*
*/
@@ -1399,7 +1408,7 @@ rb_file_s_lstat(VALUE klass, VALUE fname)
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) {
- rb_sys_fail_path(fname);
+ rb_sys_fail_path(fname);
}
return rb_stat_new(&st);
#else
@@ -1409,16 +1418,16 @@ rb_file_s_lstat(VALUE klass, VALUE fname)
/*
* call-seq:
- * file.lstat -> stat
+ * lstat -> stat
*
- * Same as IO#stat, but does not follow the last symbolic link.
- * Instead, reports on the link itself.
+ * Like File#stat, but does not follow the last symbolic link;
+ * instead, returns a File::Stat object for the link itself:
+ *
+ * File.symlink('t.txt', 'symlink')
+ * f = File.new('symlink')
+ * f.stat.size # => 47
+ * f.lstat.size # => 11
*
- * File.symlink("testfile", "link2test") #=> 0
- * File.stat("testfile").size #=> 66
- * f = File.new("link2test")
- * f.lstat.size #=> 8
- * f.stat.size #=> 66
*/
static VALUE
@@ -1433,7 +1442,7 @@ rb_file_lstat(VALUE obj)
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (lstat_without_gvl(RSTRING_PTR(path), &st) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return rb_stat_new(&st);
#else
@@ -1448,41 +1457,25 @@ rb_group_member(GETGROUPS_T gid)
return FALSE;
#else
int rv = FALSE;
- int groups = 16;
+ int groups;
VALUE v = 0;
GETGROUPS_T *gary;
int anum = -1;
if (getgid() == gid || getegid() == gid)
- return TRUE;
-
- /*
- * On Mac OS X (Mountain Lion), NGROUPS is 16. But libc and kernel
- * accept more larger value.
- * So we don't trunk NGROUPS anymore.
- */
- while (groups <= RB_MAX_GROUPS) {
- gary = ALLOCV_N(GETGROUPS_T, v, groups);
- anum = getgroups(groups, gary);
- if (anum != -1 && anum != groups)
- break;
- groups *= 2;
- if (v) {
- ALLOCV_END(v);
- v = 0;
- }
- }
- if (anum == -1)
- return FALSE;
+ return TRUE;
+ groups = getgroups(0, NULL);
+ gary = ALLOCV_N(GETGROUPS_T, v, groups);
+ anum = getgroups(groups, gary);
while (--anum >= 0) {
- if (gary[anum] == gid) {
- rv = TRUE;
- break;
- }
+ if (gary[anum] == gid) {
+ rv = TRUE;
+ break;
+ }
}
if (v)
- ALLOCV_END(v);
+ ALLOCV_END(v);
return rv;
#endif
@@ -1508,28 +1501,28 @@ eaccess(const char *path, int mode)
/* no setuid nor setgid. run shortcut. */
if (getuid() == euid && getgid() == getegid())
- return access(path, mode);
+ return access(path, mode);
if (STAT(path, &st) < 0)
- return -1;
+ return -1;
if (euid == 0) {
- /* Root can read or write any file. */
- if (!(mode & X_OK))
- return 0;
+ /* Root can read or write any file. */
+ if (!(mode & X_OK))
+ return 0;
- /* Root can execute any file that has any one of the execute
- bits set. */
- if (st.st_mode & S_IXUGO)
- return 0;
+ /* Root can execute any file that has any one of the execute
+ bits set. */
+ if (st.st_mode & S_IXUGO)
+ return 0;
- return -1;
+ return -1;
}
if (st.st_uid == euid) /* owner */
- mode <<= 6;
+ mode <<= 6;
else if (rb_group_member(st.st_gid))
- mode <<= 3;
+ mode <<= 3;
if ((int)(st.st_mode & mode) == mode) return 0;
@@ -1564,7 +1557,7 @@ rb_eaccess(VALUE fname, int mode)
aa.mode = mode;
return (int)(VALUE)rb_thread_call_without_gvl(nogvl_eaccess, &aa,
- RUBY_UBF_IO, 0);
+ RUBY_UBF_IO, 0);
}
static void *
@@ -1586,7 +1579,7 @@ rb_access(VALUE fname, int mode)
aa.mode = mode;
return (int)(VALUE)rb_thread_call_without_gvl(nogvl_access, &aa,
- RUBY_UBF_IO, 0);
+ RUBY_UBF_IO, 0);
}
/*
@@ -1603,15 +1596,20 @@ rb_access(VALUE fname, int mode)
* Document-method: directory?
*
* call-seq:
- * File.directory?(file_name) -> true or false
+ * File.directory?(path) -> true or false
*
- * Returns <code>true</code> if the named file is a directory,
- * or a symlink that points at a directory, and <code>false</code>
- * otherwise.
+ * With string +object+ given, returns +true+ if +path+ is a string path
+ * leading to a directory, or to a symbolic link to a directory; +false+ otherwise:
*
- * _file_name_ can be an IO object.
+ * File.directory?('.') # => true
+ * File.directory?('foo') # => false
+ * File.symlink('.', 'dirlink') # => 0
+ * File.directory?('dirlink') # => true
+ * File.symlink('t,txt', 'filelink') # => 0
+ * File.directory?('filelink') # => false
+ *
+ * Argument +path+ can be an IO object.
*
- * File.directory?(".")
*/
VALUE
@@ -1630,11 +1628,14 @@ rb_file_directory_p(VALUE obj, VALUE fname)
/*
* call-seq:
- * File.pipe?(file_name) -> true or false
+ * File.pipe?(filepath) -> true or false
*
- * Returns <code>true</code> if the named file is a pipe.
+ * Returns +true+ if +filepath+ points to a pipe, +false+ otherwise:
+ *
+ * File.mkfifo('tmp/fifo')
+ * File.pipe?('tmp/fifo') # => true
+ * File.pipe?('t.txt') # => false
*
- * _file_name_ can be an IO object.
*/
static VALUE
@@ -1656,9 +1657,14 @@ rb_file_pipe_p(VALUE obj, VALUE fname)
/*
* call-seq:
- * File.symlink?(file_name) -> true or false
+ * File.symlink?(filepath) -> true or false
+ *
+ * Returns +true+ if +filepath+ points to a symbolic link, +false+ otherwise:
+ *
+ * symlink = File.symlink('t.txt', 'symlink')
+ * File.symlink?('symlink') # => true
+ * File.symlink?('t.txt') # => false
*
- * Returns <code>true</code> if the named file is a symbolic link.
*/
static VALUE
@@ -1692,11 +1698,14 @@ rb_file_symlink_p(VALUE obj, VALUE fname)
/*
* call-seq:
- * File.socket?(file_name) -> true or false
+ * File.socket?(filepath) -> true or false
*
- * Returns <code>true</code> if the named file is a socket.
+ * Returns +true+ if +filepath+ points to a socket, +false+ otherwise:
+ *
+ * require 'socket'
+ * File.socket?(Socket.new(:INET, :STREAM)) # => true
+ * File.socket?(File.new('t.txt')) # => false
*
- * _file_name_ can be an IO object.
*/
static VALUE
@@ -1721,18 +1730,20 @@ rb_file_socket_p(VALUE obj, VALUE fname)
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISSOCK(st.st_mode)) return Qtrue;
-
#endif
+
return Qfalse;
}
/*
* call-seq:
- * File.blockdev?(file_name) -> true or false
+ * File.blockdev?(filepath) -> true or false
*
- * Returns <code>true</code> if the named file is a block device.
+ * Returns +true+ if +filepath+ points to a block device, +false+ otherwise:
+ *
+ * File.blockdev?('/dev/sda1') # => true
+ * File.blockdev?(File.new('t.tmp')) # => false
*
- * _file_name_ can be an IO object.
*/
static VALUE
@@ -1758,11 +1769,13 @@ rb_file_blockdev_p(VALUE obj, VALUE fname)
/*
* call-seq:
- * File.chardev?(file_name) -> true or false
+ * File.chardev?(filepath) -> true or false
*
- * Returns <code>true</code> if the named file is a character device.
+ * Returns +true+ if +filepath+ points to a character device, +false+ otherwise.
+ *
+ * File.chardev?($stdin) # => true
+ * File.chardev?('t.txt') # => false
*
- * _file_name_ can be an IO object.
*/
static VALUE
rb_file_chardev_p(VALUE obj, VALUE fname)
@@ -1799,23 +1812,6 @@ rb_file_exist_p(VALUE obj, VALUE fname)
return Qtrue;
}
-/* :nodoc: */
-static VALUE
-rb_file_exists_p(VALUE obj, VALUE fname)
-{
- const char *s = "FileTest#exist?";
- if (obj == rb_mFileTest) {
- s = "FileTest.exist?";
- }
- else if (obj == rb_cFile ||
- (RB_TYPE_P(obj, T_CLASS) &&
- RTEST(rb_class_inherited_p(obj, rb_cFile)))) {
- s = "File.exist?";
- }
- rb_warn_deprecated("%.*ss?", s, (int)(strlen(s)-1), s);
- return rb_file_exist_p(obj, fname);
-}
-
/*
* call-seq:
* File.readable?(file_name) -> true or false
@@ -1882,7 +1878,7 @@ rb_file_world_readable_p(VALUE obj, VALUE fname)
if (rb_stat(fname, &st) < 0) return Qnil;
if ((st.st_mode & (S_IROTH)) == S_IROTH) {
- return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
@@ -1946,7 +1942,7 @@ rb_file_world_writable_p(VALUE obj, VALUE fname)
if (rb_stat(fname, &st) < 0) return Qnil;
if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
- return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
@@ -2016,8 +2012,7 @@ rb_file_file_p(VALUE obj, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISREG(st.st_mode)) return Qtrue;
- return Qfalse;
+ return RBOOL(S_ISREG(st.st_mode));
}
/*
@@ -2036,8 +2031,7 @@ rb_file_zero_p(VALUE obj, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_size == 0) return Qtrue;
- return Qfalse;
+ return RBOOL(st.st_size == 0);
}
/*
@@ -2077,8 +2071,7 @@ rb_file_owned_p(VALUE obj, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_uid == geteuid()) return Qtrue;
- return Qfalse;
+ return RBOOL(st.st_uid == geteuid());
}
static VALUE
@@ -2087,8 +2080,7 @@ rb_file_rowned_p(VALUE obj, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_uid == getuid()) return Qtrue;
- return Qfalse;
+ return RBOOL(st.st_uid == getuid());
}
/*
@@ -2121,8 +2113,7 @@ check3rdbyte(VALUE fname, int mode)
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_mode & mode) return Qtrue;
- return Qfalse;
+ return RBOOL(st.st_mode & mode);
}
#endif
@@ -2179,7 +2170,7 @@ rb_file_sticky_p(VALUE obj, VALUE fname)
#ifdef S_ISVTX
return check3rdbyte(fname, S_ISVTX);
#else
- return Qnil;
+ return Qfalse;
#endif
}
@@ -2234,9 +2225,9 @@ rb_file_s_size(VALUE klass, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) {
- int e = errno;
- FilePathValue(fname);
- rb_syserr_fail_path(e, fname);
+ int e = errno;
+ FilePathValue(fname);
+ rb_syserr_fail_path(e, fname);
}
return OFFT2NUM(st.st_size);
}
@@ -2247,36 +2238,36 @@ rb_file_ftype(const struct stat *st)
const char *t;
if (S_ISREG(st->st_mode)) {
- t = "file";
+ t = "file";
}
else if (S_ISDIR(st->st_mode)) {
- t = "directory";
+ t = "directory";
}
else if (S_ISCHR(st->st_mode)) {
- t = "characterSpecial";
+ t = "characterSpecial";
}
#ifdef S_ISBLK
else if (S_ISBLK(st->st_mode)) {
- t = "blockSpecial";
+ t = "blockSpecial";
}
#endif
#ifdef S_ISFIFO
else if (S_ISFIFO(st->st_mode)) {
- t = "fifo";
+ t = "fifo";
}
#endif
#ifdef S_ISLNK
else if (S_ISLNK(st->st_mode)) {
- t = "link";
+ t = "link";
}
#endif
#ifdef S_ISSOCK
else if (S_ISSOCK(st->st_mode)) {
- t = "socket";
+ t = "socket";
}
#endif
else {
- t = "unknown";
+ t = "unknown";
}
return rb_usascii_str_new2(t);
@@ -2305,7 +2296,7 @@ rb_file_s_ftype(VALUE klass, VALUE fname)
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) {
- rb_sys_fail_path(fname);
+ rb_sys_fail_path(fname);
}
return rb_file_ftype(&st);
@@ -2329,9 +2320,9 @@ rb_file_s_atime(VALUE klass, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) {
- int e = errno;
- FilePathValue(fname);
- rb_syserr_fail_path(e, fname);
+ int e = errno;
+ FilePathValue(fname);
+ rb_syserr_fail_path(e, fname);
}
return stat_atime(&st);
}
@@ -2355,7 +2346,7 @@ rb_file_atime(VALUE obj)
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return stat_atime(&st);
}
@@ -2378,9 +2369,9 @@ rb_file_s_mtime(VALUE klass, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) {
- int e = errno;
- FilePathValue(fname);
- rb_syserr_fail_path(e, fname);
+ int e = errno;
+ FilePathValue(fname);
+ rb_syserr_fail_path(e, fname);
}
return stat_mtime(&st);
}
@@ -2403,7 +2394,7 @@ rb_file_mtime(VALUE obj)
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return stat_mtime(&st);
}
@@ -2430,9 +2421,9 @@ rb_file_s_ctime(VALUE klass, VALUE fname)
struct stat st;
if (rb_stat(fname, &st) < 0) {
- int e = errno;
- FilePathValue(fname);
- rb_syserr_fail_path(e, fname);
+ int e = errno;
+ FilePathValue(fname);
+ rb_syserr_fail_path(e, fname);
}
return stat_ctime(&st);
}
@@ -2458,7 +2449,7 @@ rb_file_ctime(VALUE obj)
GetOpenFile(obj, fptr);
if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return stat_ctime(&st);
}
@@ -2484,9 +2475,9 @@ rb_file_s_birthtime(VALUE klass, VALUE fname)
statx_data st;
if (rb_statx(fname, &st, STATX_BTIME) < 0) {
- int e = errno;
- FilePathValue(fname);
- rb_syserr_fail_path(e, fname);
+ int e = errno;
+ FilePathValue(fname);
+ rb_syserr_fail_path(e, fname);
}
return statx_birthtime(&st, fname);
}
@@ -2515,7 +2506,7 @@ rb_file_birthtime(VALUE obj)
GetOpenFile(obj, fptr);
if (fstatx_without_gvl(fptr->fd, &st, STATX_BTIME) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return statx_birthtime(&st, fptr->pathv);
}
@@ -2533,20 +2524,33 @@ rb_file_birthtime(VALUE obj)
*
*/
-static VALUE
-rb_file_size(VALUE obj)
+rb_off_t
+rb_file_size(VALUE file)
{
- rb_io_t *fptr;
- struct stat st;
+ if (RB_TYPE_P(file, T_FILE)) {
+ rb_io_t *fptr;
+ struct stat st;
- GetOpenFile(obj, fptr);
- if (fptr->mode & FMODE_WRITABLE) {
- rb_io_flush_raw(obj, 0);
+ RB_IO_POINTER(file, fptr);
+ if (fptr->mode & FMODE_WRITABLE) {
+ rb_io_flush_raw(file, 0);
+ }
+
+ if (fstat(fptr->fd, &st) == -1) {
+ rb_sys_fail_path(fptr->pathv);
+ }
+
+ return st.st_size;
}
- if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail_path(fptr->pathv);
+ else {
+ return NUM2OFFT(rb_funcall(file, idSize, 0));
}
- return OFFT2NUM(st.st_size);
+}
+
+static VALUE
+file_size(VALUE self)
+{
+ return OFFT2NUM(rb_file_size(self));
}
static int
@@ -2606,18 +2610,18 @@ rb_file_chmod(VALUE obj, VALUE vmode)
GetOpenFile(obj, fptr);
#ifdef HAVE_FCHMOD
if (fchmod(fptr->fd, mode) == -1) {
- if (HAVE_FCHMOD || errno != ENOSYS)
- rb_sys_fail_path(fptr->pathv);
+ if (HAVE_FCHMOD || errno != ENOSYS)
+ rb_sys_fail_path(fptr->pathv);
}
else {
- if (!HAVE_FCHMOD) return INT2FIX(0);
+ if (!HAVE_FCHMOD) return INT2FIX(0);
}
#endif
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (chmod(RSTRING_PTR(path), mode) == -1)
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
#endif
return INT2FIX(0);
@@ -2658,7 +2662,7 @@ static inline rb_uid_t
to_uid(VALUE u)
{
if (NIL_P(u)) {
- return (rb_uid_t)-1;
+ return (rb_uid_t)-1;
}
return NUM2UIDT(u);
}
@@ -2667,7 +2671,7 @@ static inline rb_gid_t
to_gid(VALUE g)
{
if (NIL_P(g)) {
- return (rb_gid_t)-1;
+ return (rb_gid_t)-1;
}
return NUM2GIDT(g);
}
@@ -2743,10 +2747,10 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (chown(RSTRING_PTR(path), o, g) == -1)
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
#else
if (fchown(fptr->fd, o, g) == -1)
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
#endif
return INT2FIX(0);
@@ -2803,32 +2807,32 @@ utime_failed(struct apply_arg *aa)
struct utime_args *ua = aa->arg;
if (ua->tsp && e == EINVAL) {
- VALUE e[2], a = Qnil, m = Qnil;
- int d = 0;
- VALUE atime = ua->atime;
- VALUE mtime = ua->mtime;
-
- if (!NIL_P(atime)) {
- a = rb_inspect(atime);
- }
- if (!NIL_P(mtime) && mtime != atime && !rb_equal(atime, mtime)) {
- m = rb_inspect(mtime);
- }
- if (NIL_P(a)) e[0] = m;
- else if (NIL_P(m) || rb_str_cmp(a, m) == 0) e[0] = a;
- else {
- e[0] = rb_str_plus(a, rb_str_new_cstr(" or "));
- rb_str_append(e[0], m);
- d = 1;
- }
- if (!NIL_P(e[0])) {
- if (path) {
- if (!d) e[0] = rb_str_dup(e[0]);
- rb_str_append(rb_str_cat2(e[0], " for "), path);
- }
- e[1] = INT2FIX(EINVAL);
- rb_exc_raise(rb_class_new_instance(2, e, rb_eSystemCallError));
- }
+ VALUE e[2], a = Qnil, m = Qnil;
+ int d = 0;
+ VALUE atime = ua->atime;
+ VALUE mtime = ua->mtime;
+
+ if (!NIL_P(atime)) {
+ a = rb_inspect(atime);
+ }
+ if (!NIL_P(mtime) && mtime != atime && !rb_equal(atime, mtime)) {
+ m = rb_inspect(mtime);
+ }
+ if (NIL_P(a)) e[0] = m;
+ else if (NIL_P(m) || rb_str_cmp(a, m) == 0) e[0] = a;
+ else {
+ e[0] = rb_str_plus(a, rb_str_new_cstr(" or "));
+ rb_str_append(e[0], m);
+ d = 1;
+ }
+ if (!NIL_P(e[0])) {
+ if (path) {
+ if (!d) e[0] = rb_str_dup(e[0]);
+ rb_str_append(rb_str_cat2(e[0], " for "), path);
+ }
+ e[1] = INT2FIX(EINVAL);
+ rb_exc_raise(rb_class_new_instance(2, e, rb_eSystemCallError));
+ }
}
rb_syserr_fail_path(e, path);
}
@@ -2836,6 +2840,29 @@ utime_failed(struct apply_arg *aa)
#if defined(HAVE_UTIMES)
+# if !defined(HAVE_UTIMENSAT)
+/* utimensat() is not found, runtime check is not needed */
+# elif defined(__APPLE__) && \
+ (!defined(MAC_OS_X_VERSION_13_0) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_13_0))
+
+# if defined(__has_attribute) && __has_attribute(availability)
+typedef int utimensat_func(int, const char *, const struct timespec [2], int);
+
+RBIMPL_WARNING_PUSH()
+RBIMPL_WARNING_IGNORED(-Wunguarded-availability-new)
+static inline utimensat_func *
+rb_utimensat(void)
+{
+ return &utimensat;
+}
+RBIMPL_WARNING_POP()
+
+# define utimensat rb_utimensat()
+# else /* __API_AVAILABLE macro does nothing on gcc */
+__attribute__((weak)) int utimensat(int, const char *, const struct timespec [2], int);
+# endif
+# endif
+
static int
utime_internal(const char *path, void *arg)
{
@@ -2844,35 +2871,40 @@ utime_internal(const char *path, void *arg)
struct timeval tvbuf[2], *tvp = NULL;
#if defined(HAVE_UTIMENSAT)
+# if defined(__APPLE__)
+ const int try_utimensat = utimensat != NULL;
+ const int try_utimensat_follow = utimensat != NULL;
+# else
+# define TRY_UTIMENSAT 1
static int try_utimensat = 1;
# ifdef AT_SYMLINK_NOFOLLOW
static int try_utimensat_follow = 1;
# else
const int try_utimensat_follow = 0;
# endif
+# endif
int flags = 0;
if (v->follow ? try_utimensat_follow : try_utimensat) {
# ifdef AT_SYMLINK_NOFOLLOW
- if (v->follow) {
- flags = AT_SYMLINK_NOFOLLOW;
- }
+ if (v->follow) {
+ flags = AT_SYMLINK_NOFOLLOW;
+ }
# endif
- if (utimensat(AT_FDCWD, path, tsp, flags) < 0) {
- if (errno == ENOSYS) {
+ int result = utimensat(AT_FDCWD, path, tsp, flags);
+# ifdef TRY_UTIMENSAT
+ if (result < 0 && errno == ENOSYS) {
# ifdef AT_SYMLINK_NOFOLLOW
- try_utimensat_follow = 0;
+ try_utimensat_follow = 0;
# endif
- if (!v->follow)
- try_utimensat = 0;
- goto no_utimensat;
- }
- return -1; /* calls utime_failed */
+ if (!v->follow)
+ try_utimensat = 0;
}
- return 0;
+ else
+# endif
+ return result;
}
-no_utimensat:
#endif
if (tsp) {
@@ -2926,12 +2958,12 @@ utime_internal_i(int argc, VALUE *argv, int follow)
args.follow = follow;
if (!NIL_P(args.atime) || !NIL_P(args.mtime)) {
- tsp = tss;
- tsp[0] = rb_time_timespec(args.atime);
- if (args.atime == args.mtime)
- tsp[1] = tsp[0];
- else
- tsp[1] = rb_time_timespec(args.mtime);
+ tsp = tss;
+ tsp[0] = rb_time_timespec(args.atime);
+ if (args.atime == args.mtime)
+ tsp[1] = tsp[0];
+ else
+ tsp[1] = rb_time_timespec(args.mtime);
}
args.tsp = tsp;
@@ -2995,7 +3027,7 @@ syserr_fail2_in(const char *func, int e, VALUE s1, VALUE s2)
#endif
if (e == EEXIST) {
- rb_syserr_fail_path(e, rb_str_ellipsize(s2, max_pathlen));
+ rb_syserr_fail_path(e, rb_str_ellipsize(s2, max_pathlen));
}
str = rb_str_new_cstr("(");
rb_str_append(str, rb_str_ellipsize(s1, max_pathlen));
@@ -3031,7 +3063,7 @@ rb_file_s_link(VALUE klass, VALUE from, VALUE to)
to = rb_str_encode_ospath(to);
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
- sys_fail2(from, to);
+ sys_fail2(from, to);
}
return INT2FIX(0);
}
@@ -3061,7 +3093,7 @@ rb_file_s_symlink(VALUE klass, VALUE from, VALUE to)
to = rb_str_encode_ospath(to);
if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
- sys_fail2(from, to);
+ sys_fail2(from, to);
}
return INT2FIX(0);
}
@@ -3087,7 +3119,6 @@ rb_file_s_readlink(VALUE klass, VALUE path)
return rb_readlink(path, rb_filesystem_encoding());
}
-#ifndef _WIN32
struct readlink_arg {
const char *path;
char *buf;
@@ -3112,7 +3143,7 @@ readlink_without_gvl(VALUE path, VALUE buf, size_t size)
ra.size = size;
return (ssize_t)rb_thread_call_without_gvl(nogvl_readlink, &ra,
- RUBY_UBF_IO, 0);
+ RUBY_UBF_IO, 0);
}
VALUE
@@ -3127,23 +3158,22 @@ rb_readlink(VALUE path, rb_encoding *enc)
v = rb_enc_str_new(0, size, enc);
while ((rv = readlink_without_gvl(path, v, size)) == size
#ifdef _AIX
- || (rv < 0 && errno == ERANGE) /* quirky behavior of GPFS */
+ || (rv < 0 && errno == ERANGE) /* quirky behavior of GPFS */
#endif
- ) {
- rb_str_modify_expand(v, size);
- size *= 2;
- rb_str_set_len(v, size);
+ ) {
+ rb_str_modify_expand(v, size);
+ size *= 2;
+ rb_str_set_len(v, size);
}
if (rv < 0) {
- int e = errno;
- rb_str_resize(v, 0);
- rb_syserr_fail_path(e, path);
+ int e = errno;
+ rb_str_resize(v, 0);
+ rb_syserr_fail_path(e, path);
}
rb_str_resize(v, rv);
return v;
}
-#endif
#else
#define rb_file_s_readlink rb_f_notimplement
#endif
@@ -3215,18 +3245,18 @@ rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
errno = 0;
#endif
if ((int)(VALUE)rb_thread_call_without_gvl(no_gvl_rename, &ra,
- RUBY_UBF_IO, 0) < 0) {
- int e = errno;
+ RUBY_UBF_IO, 0) < 0) {
+ int e = errno;
#if defined DOSISH
- switch (e) {
- case EEXIST:
- if (chmod(ra.dst, 0666) == 0 &&
- unlink(ra.dst) == 0 &&
- rename(ra.src, ra.dst) == 0)
- return INT2FIX(0);
- }
+ switch (e) {
+ case EEXIST:
+ if (chmod(ra.dst, 0666) == 0 &&
+ unlink(ra.dst) == 0 &&
+ rename(ra.src, ra.dst) == 0)
+ return INT2FIX(0);
+ }
#endif
- syserr_fail2(e, from, to);
+ syserr_fail2(e, from, to);
}
return INT2FIX(0);
@@ -3254,11 +3284,11 @@ rb_file_s_umask(int argc, VALUE *argv, VALUE _)
switch (argc) {
case 0:
- omask = umask(0);
- umask(omask);
+ omask = umask(0);
+ umask(omask);
break;
case 1:
- omask = umask(NUM2MODET(argv[0]));
+ omask = umask(NUM2MODET(argv[0]));
break;
default:
rb_error_arity(argc, 0, 1);
@@ -3323,10 +3353,10 @@ static inline int
has_drive_letter(const char *buf)
{
if (ISALPHA(buf[0]) && buf[1] == ':') {
- return 1;
+ return 1;
}
else {
- return 0;
+ return 0;
}
}
@@ -3347,17 +3377,16 @@ getcwdofdrv(int drv)
*/
oldcwd = ruby_getcwd();
if (chdir(drive) == 0) {
- drvcwd = ruby_getcwd();
- chdir(oldcwd);
- xfree(oldcwd);
+ drvcwd = ruby_getcwd();
+ chdir(oldcwd);
+ xfree(oldcwd);
}
else {
- /* perhaps the drive is not exist. we return only drive letter */
- drvcwd = strdup(drive);
+ /* perhaps the drive is not exist. we return only drive letter */
+ drvcwd = strdup(drive);
}
return drvcwd;
}
-#endif
static inline int
not_same_drive(VALUE path, int drive)
@@ -3365,13 +3394,14 @@ not_same_drive(VALUE path, int drive)
const char *p = RSTRING_PTR(path);
if (RSTRING_LEN(path) < 2) return 0;
if (has_drive_letter(p)) {
- return TOLOWER(p[0]) != TOLOWER(drive);
+ return TOLOWER(p[0]) != TOLOWER(drive);
}
else {
- return has_unc(p);
+ return has_unc(p);
}
}
#endif
+#endif
static inline char *
skiproot(const char *path, const char *end, rb_encoding *enc)
@@ -3388,7 +3418,7 @@ char *
rb_enc_path_next(const char *s, const char *e, rb_encoding *enc)
{
while (s < e && !isdirsep(*s)) {
- Inc(s, e, enc);
+ Inc(s, e, enc);
}
return (char *)s;
}
@@ -3404,16 +3434,16 @@ rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
#ifdef DOSISH_UNC
if (path + 2 <= end && isdirsep(path[0]) && isdirsep(path[1])) {
- path += 2;
- while (path < end && isdirsep(*path)) path++;
- if ((path = rb_enc_path_next(path, end, enc)) < end && path[0] && path[1] && !isdirsep(path[1]))
- path = rb_enc_path_next(path + 1, end, enc);
- return (char *)path;
+ path += 2;
+ while (path < end && isdirsep(*path)) path++;
+ if ((path = rb_enc_path_next(path, end, enc)) < end && path[0] && path[1] && !isdirsep(path[1]))
+ path = rb_enc_path_next(path + 1, end, enc);
+ return (char *)path;
}
#endif
#ifdef DOSISH_DRIVE_LETTER
if (has_drive_letter(path))
- return (char *)(path + 2);
+ return (char *)(path + 2);
#endif
#endif
return (char *)path;
@@ -3437,15 +3467,15 @@ rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc)
{
char *last = NULL;
while (path < end) {
- if (isdirsep(*path)) {
- const char *tmp = path++;
- while (path < end && isdirsep(*path)) path++;
- if (path >= end) break;
- last = (char *)tmp;
- }
- else {
- Inc(path, end, enc);
- }
+ if (isdirsep(*path)) {
+ const char *tmp = path++;
+ while (path < end && isdirsep(*path)) path++;
+ if (path >= end) break;
+ last = (char *)tmp;
+ }
+ else {
+ Inc(path, end, enc);
+ }
}
return last;
}
@@ -3454,14 +3484,14 @@ static char *
chompdirsep(const char *path, const char *end, rb_encoding *enc)
{
while (path < end) {
- if (isdirsep(*path)) {
- const char *last = path++;
- while (path < end && isdirsep(*path)) path++;
- if (path >= end) return (char *)last;
- }
- else {
- Inc(path, end, enc);
- }
+ if (isdirsep(*path)) {
+ const char *last = path++;
+ while (path < end && isdirsep(*path)) path++;
+ if (path >= end) return (char *)last;
+ }
+ else {
+ Inc(path, end, enc);
+ }
}
return (char *)path;
}
@@ -3493,20 +3523,20 @@ ntfs_tail(const char *path, const char *end, rb_encoding *enc)
{
while (path < end && *path == '.') path++;
while (path < end && !isADS(*path)) {
- if (istrailinggarbage(*path)) {
- const char *last = path++;
- while (path < end && istrailinggarbage(*path)) path++;
- if (path >= end || isADS(*path)) return (char *)last;
- }
- else if (isdirsep(*path)) {
- const char *last = path++;
- while (path < end && isdirsep(*path)) path++;
- if (path >= end) return (char *)last;
- if (isADS(*path)) path++;
- }
- else {
- Inc(path, end, enc);
- }
+ if (istrailinggarbage(*path)) {
+ const char *last = path++;
+ while (path < end && istrailinggarbage(*path)) path++;
+ if (path >= end || isADS(*path)) return (char *)last;
+ }
+ else if (isdirsep(*path)) {
+ const char *last = path++;
+ while (path < end && isdirsep(*path)) path++;
+ if (path >= end) return (char *)last;
+ if (isADS(*path)) path++;
+ }
+ else {
+ Inc(path, end, enc);
+ }
}
return (char *)path;
}
@@ -3515,11 +3545,11 @@ ntfs_tail(const char *path, const char *end, rb_encoding *enc)
#define BUFCHECK(cond) do {\
bdiff = p - buf;\
if (cond) {\
- do {buflen *= 2;} while (cond);\
- rb_str_resize(result, buflen);\
- buf = RSTRING_PTR(result);\
- p = buf + bdiff;\
- pend = buf + buflen;\
+ do {buflen *= 2;} while (cond);\
+ rb_str_resize(result, buflen);\
+ buf = RSTRING_PTR(result);\
+ p = buf + bdiff;\
+ pend = buf + buflen;\
}\
} while (0)
@@ -3568,9 +3598,9 @@ copy_home_path(VALUE result, const char *dir)
#if defined DOSISH || defined __CYGWIN__
enc = rb_enc_from_index(encidx);
for (bend = (p = buf) + dirlen; p < bend; Inc(p, bend, enc)) {
- if (*p == '\\') {
- *p = '/';
- }
+ if (*p == '\\') {
+ *p = '/';
+ }
}
#endif
return result;
@@ -3601,11 +3631,11 @@ rb_home_dir_of(VALUE user, VALUE result)
pwPtr = getpwnam(username);
#else
if (strcasecmp(username, getlogin()) == 0)
- dir = pwPtr = getenv("HOME");
+ dir = pwPtr = getenv("HOME");
#endif
if (!pwPtr) {
- endpwent();
- rb_raise(rb_eArgError, "user %"PRIsVALUE" doesn't exist", user);
+ endpwent();
+ rb_raise(rb_eArgError, "user %"PRIsVALUE" doesn't exist", user);
}
#ifdef HAVE_PWD_H
dir = pwPtr->pw_dir;
@@ -3662,7 +3692,7 @@ rb_default_home_dir(VALUE result)
}
#endif
if (!dir) {
- rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
+ rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
}
return copy_home_path(result, dir);
}
@@ -3687,15 +3717,15 @@ append_fspath(VALUE result, VALUE fname, char *dir, rb_encoding **enc, rb_encodi
size_t dirlen = strlen(dir), buflen = rb_str_capacity(result);
if (NORMALIZE_UTF8PATH || *enc != fsenc) {
- rb_encoding *direnc = fs_enc_check(fname, dirname = ospath_new(dir, dirlen, fsenc));
- if (direnc != fsenc) {
- dirname = rb_str_conv_enc(dirname, fsenc, direnc);
- RSTRING_GETMEM(dirname, cwdp, dirlen);
- }
- else if (NORMALIZE_UTF8PATH) {
- RSTRING_GETMEM(dirname, cwdp, dirlen);
- }
- *enc = direnc;
+ rb_encoding *direnc = fs_enc_check(fname, dirname = ospath_new(dir, dirlen, fsenc));
+ if (direnc != fsenc) {
+ dirname = rb_str_conv_enc(dirname, fsenc, direnc);
+ RSTRING_GETMEM(dirname, cwdp, dirlen);
+ }
+ else if (NORMALIZE_UTF8PATH) {
+ RSTRING_GETMEM(dirname, cwdp, dirlen);
+ }
+ *enc = direnc;
}
do {buflen *= 2;} while (dirlen > buflen);
rb_str_resize(result, buflen);
@@ -3721,115 +3751,115 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na
BUFINIT();
if (s[0] == '~' && abs_mode == 0) { /* execute only if NOT absolute_path() */
- long userlen = 0;
- if (isdirsep(s[1]) || s[1] == '\0') {
- buf = 0;
- b = 0;
- rb_str_set_len(result, 0);
- if (*++s) ++s;
- rb_default_home_dir(result);
- }
- else {
- s = nextdirsep(b = s, fend, enc);
- b++; /* b[0] is '~' */
- userlen = s - b;
- BUFCHECK(bdiff + userlen >= buflen);
- memcpy(p, b, userlen);
- ENC_CODERANGE_CLEAR(result);
- rb_str_set_len(result, userlen);
- rb_enc_associate(result, enc);
- rb_home_dir_of(result, result);
- buf = p + 1;
- p += userlen;
- }
- if (!rb_is_absolute_path(RSTRING_PTR(result))) {
- if (userlen) {
- rb_enc_raise(enc, rb_eArgError, "non-absolute home of %.*s%.0"PRIsVALUE,
- (int)userlen, b, fname);
- }
- else {
- rb_raise(rb_eArgError, "non-absolute home");
- }
- }
- BUFINIT();
- p = pend;
+ long userlen = 0;
+ if (isdirsep(s[1]) || s[1] == '\0') {
+ buf = 0;
+ b = 0;
+ rb_str_set_len(result, 0);
+ if (*++s) ++s;
+ rb_default_home_dir(result);
+ }
+ else {
+ s = nextdirsep(b = s, fend, enc);
+ b++; /* b[0] is '~' */
+ userlen = s - b;
+ BUFCHECK(bdiff + userlen >= buflen);
+ memcpy(p, b, userlen);
+ ENC_CODERANGE_CLEAR(result);
+ rb_str_set_len(result, userlen);
+ rb_enc_associate(result, enc);
+ rb_home_dir_of(result, result);
+ buf = p + 1;
+ p += userlen;
+ }
+ if (!rb_is_absolute_path(RSTRING_PTR(result))) {
+ if (userlen) {
+ rb_enc_raise(enc, rb_eArgError, "non-absolute home of %.*s%.0"PRIsVALUE,
+ (int)userlen, b, fname);
+ }
+ else {
+ rb_raise(rb_eArgError, "non-absolute home");
+ }
+ }
+ BUFINIT();
+ p = pend;
}
#ifdef DOSISH_DRIVE_LETTER
/* skip drive letter */
else if (has_drive_letter(s)) {
- if (isdirsep(s[2])) {
- /* specified drive letter, and full path */
- /* skip drive letter */
- BUFCHECK(bdiff + 2 >= buflen);
- memcpy(p, s, 2);
- p += 2;
- s += 2;
- rb_enc_copy(result, fname);
- }
- else {
- /* specified drive, but not full path */
- int same = 0;
- if (!NIL_P(dname) && !not_same_drive(dname, s[0])) {
- rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result);
- BUFINIT();
- if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) {
- /* ok, same drive */
- same = 1;
- }
- }
- if (!same) {
- char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
- BUFINIT();
- p = e;
- }
- else {
- rb_enc_associate(result, enc = fs_enc_check(result, fname));
- p = pend;
- }
- p = chompdirsep(skiproot(buf, p, enc), p, enc);
- s += 2;
- }
+ if (isdirsep(s[2])) {
+ /* specified drive letter, and full path */
+ /* skip drive letter */
+ BUFCHECK(bdiff + 2 >= buflen);
+ memcpy(p, s, 2);
+ p += 2;
+ s += 2;
+ rb_enc_copy(result, fname);
+ }
+ else {
+ /* specified drive, but not full path */
+ int same = 0;
+ if (!NIL_P(dname) && !not_same_drive(dname, s[0])) {
+ rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result);
+ BUFINIT();
+ if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) {
+ /* ok, same drive */
+ same = 1;
+ }
+ }
+ if (!same) {
+ char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
+ BUFINIT();
+ p = e;
+ }
+ else {
+ rb_enc_associate(result, enc = fs_enc_check(result, fname));
+ p = pend;
+ }
+ p = chompdirsep(skiproot(buf, p, enc), p, enc);
+ s += 2;
+ }
}
#endif
else if (!rb_is_absolute_path(s)) {
- if (!NIL_P(dname)) {
- rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result);
- rb_enc_associate(result, fs_enc_check(result, fname));
- BUFINIT();
- p = pend;
- }
- else {
- char *e = append_fspath(result, fname, ruby_getcwd(), &enc, fsenc);
- BUFINIT();
- p = e;
- }
+ if (!NIL_P(dname)) {
+ rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result);
+ rb_enc_associate(result, fs_enc_check(result, fname));
+ BUFINIT();
+ p = pend;
+ }
+ else {
+ char *e = append_fspath(result, fname, ruby_getcwd(), &enc, fsenc);
+ BUFINIT();
+ p = e;
+ }
#if defined DOSISH || defined __CYGWIN__
- if (isdirsep(*s)) {
- /* specified full path, but not drive letter nor UNC */
- /* we need to get the drive letter or UNC share name */
- p = skipprefix(buf, p, enc);
- }
- else
+ if (isdirsep(*s)) {
+ /* specified full path, but not drive letter nor UNC */
+ /* we need to get the drive letter or UNC share name */
+ p = skipprefix(buf, p, enc);
+ }
+ else
#endif
- p = chompdirsep(skiproot(buf, p, enc), p, enc);
+ p = chompdirsep(skiproot(buf, p, enc), p, enc);
}
else {
- size_t len;
- b = s;
- do s++; while (isdirsep(*s));
- len = s - b;
- p = buf + len;
- BUFCHECK(bdiff >= buflen);
- memset(buf, '/', len);
- rb_str_set_len(result, len);
- rb_enc_associate(result, fs_enc_check(result, fname));
+ size_t len;
+ b = s;
+ do s++; while (isdirsep(*s));
+ len = s - b;
+ p = buf + len;
+ BUFCHECK(bdiff >= buflen);
+ memset(buf, '/', len);
+ rb_str_set_len(result, len);
+ rb_enc_associate(result, fs_enc_check(result, fname));
}
if (p > buf && p[-1] == '/')
- --p;
+ --p;
else {
- rb_str_set_len(result, p-buf);
- BUFCHECK(bdiff + 1 >= buflen);
- *p = '/';
+ rb_str_set_len(result, p-buf);
+ BUFCHECK(bdiff + 1 >= buflen);
+ *p = '/';
}
rb_str_set_len(result, p-buf+1);
@@ -3839,213 +3869,213 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na
b = s;
while (*s) {
- switch (*s) {
- case '.':
- if (b == s++) { /* beginning of path element */
- switch (*s) {
- case '\0':
- b = s;
- break;
- case '.':
- if (*(s+1) == '\0' || isdirsep(*(s+1))) {
- /* We must go back to the parent */
- char *n;
- *p = '\0';
- if (!(n = strrdirsep(root, p, enc))) {
- *p = '/';
- }
- else {
- p = n;
- }
- b = ++s;
- }
+ switch (*s) {
+ case '.':
+ if (b == s++) { /* beginning of path element */
+ switch (*s) {
+ case '\0':
+ b = s;
+ break;
+ case '.':
+ if (*(s+1) == '\0' || isdirsep(*(s+1))) {
+ /* We must go back to the parent */
+ char *n;
+ *p = '\0';
+ if (!(n = strrdirsep(root, p, enc))) {
+ *p = '/';
+ }
+ else {
+ p = n;
+ }
+ b = ++s;
+ }
#if USE_NTFS
- else {
- do ++s; while (istrailinggarbage(*s));
- }
+ else {
+ do ++s; while (istrailinggarbage(*s));
+ }
#endif
- break;
- case '/':
+ break;
+ case '/':
#if defined DOSISH || defined __CYGWIN__
- case '\\':
-#endif
- b = ++s;
- break;
- default:
- /* ordinary path element, beginning don't move */
- break;
- }
- }
+ case '\\':
+#endif
+ b = ++s;
+ break;
+ default:
+ /* ordinary path element, beginning don't move */
+ break;
+ }
+ }
#if USE_NTFS
- else {
- --s;
- case ' ': {
- const char *e = s;
- while (s < fend && istrailinggarbage(*s)) s++;
- if (s >= fend) {
- s = e;
- goto endpath;
- }
- }
- }
-#endif
- break;
- case '/':
+ else {
+ --s;
+ case ' ': {
+ const char *e = s;
+ while (s < fend && istrailinggarbage(*s)) s++;
+ if (s >= fend) {
+ s = e;
+ goto endpath;
+ }
+ }
+ }
+#endif
+ break;
+ case '/':
#if defined DOSISH || defined __CYGWIN__
- case '\\':
-#endif
- if (s > b) {
- WITH_ROOTDIFF(BUFCOPY(b, s-b));
- *p = '/';
- }
- b = ++s;
- break;
- default:
+ case '\\':
+#endif
+ if (s > b) {
+ WITH_ROOTDIFF(BUFCOPY(b, s-b));
+ *p = '/';
+ }
+ b = ++s;
+ break;
+ default:
#ifdef __APPLE__
- {
- int n = ignored_char_p(s, fend, enc);
- if (n) {
- if (s > b) {
- WITH_ROOTDIFF(BUFCOPY(b, s-b));
- *p = '\0';
- }
- b = s += n;
- break;
- }
- }
-#endif
- Inc(s, fend, enc);
- break;
- }
+ {
+ int n = ignored_char_p(s, fend, enc);
+ if (n) {
+ if (s > b) {
+ WITH_ROOTDIFF(BUFCOPY(b, s-b));
+ *p = '\0';
+ }
+ b = s += n;
+ break;
+ }
+ }
+#endif
+ Inc(s, fend, enc);
+ break;
+ }
}
if (s > b) {
#if USE_NTFS
# if USE_NTFS_ADS
- static const char prime[] = ":$DATA";
- enum {prime_len = sizeof(prime) -1};
+ static const char prime[] = ":$DATA";
+ enum {prime_len = sizeof(prime) -1};
# endif
endpath:
# if USE_NTFS_ADS
- if (s > b + prime_len && strncasecmp(s - prime_len, prime, prime_len) == 0) {
- /* alias of stream */
- /* get rid of a bug of x64 VC++ */
- if (isADS(*(s - (prime_len+1)))) {
- s -= prime_len + 1; /* prime */
- }
- else if (memchr(b, ':', s - prime_len - b)) {
- s -= prime_len; /* alternative */
- }
- }
+ if (s > b + prime_len && strncasecmp(s - prime_len, prime, prime_len) == 0) {
+ /* alias of stream */
+ /* get rid of a bug of x64 VC++ */
+ if (isADS(*(s - (prime_len+1)))) {
+ s -= prime_len + 1; /* prime */
+ }
+ else if (memchr(b, ':', s - prime_len - b)) {
+ s -= prime_len; /* alternative */
+ }
+ }
# endif
#endif
- BUFCOPY(b, s-b);
- rb_str_set_len(result, p-buf);
+ BUFCOPY(b, s-b);
+ rb_str_set_len(result, p-buf);
}
if (p == skiproot(buf, p + !!*p, enc) - 1) p++;
#if USE_NTFS
*p = '\0';
if ((s = strrdirsep(b = buf, p, enc)) != 0 && !strpbrk(s, "*?")) {
- VALUE tmp, v;
- size_t len;
- int encidx;
- WCHAR *wstr;
- WIN32_FIND_DATAW wfd;
- HANDLE h;
+ VALUE tmp, v;
+ size_t len;
+ int encidx;
+ WCHAR *wstr;
+ WIN32_FIND_DATAW wfd;
+ HANDLE h;
#ifdef __CYGWIN__
#ifdef HAVE_CYGWIN_CONV_PATH
- char *w32buf = NULL;
- const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
+ char *w32buf = NULL;
+ const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
#else
- char w32buf[MAXPATHLEN];
-#endif
- const char *path;
- ssize_t bufsize;
- int lnk_added = 0, is_symlink = 0;
- struct stat st;
- p = (char *)s;
- len = strlen(p);
- if (lstat_without_gvl(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
- is_symlink = 1;
- if (len > 4 && STRCASECMP(p + len - 4, ".lnk") != 0) {
- lnk_added = 1;
- }
- }
- path = *buf ? buf : "/";
+ char w32buf[MAXPATHLEN];
+#endif
+ const char *path;
+ ssize_t bufsize;
+ int lnk_added = 0, is_symlink = 0;
+ struct stat st;
+ p = (char *)s;
+ len = strlen(p);
+ if (lstat_without_gvl(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
+ is_symlink = 1;
+ if (len > 4 && STRCASECMP(p + len - 4, ".lnk") != 0) {
+ lnk_added = 1;
+ }
+ }
+ path = *buf ? buf : "/";
#ifdef HAVE_CYGWIN_CONV_PATH
- bufsize = cygwin_conv_path(flags, path, NULL, 0);
- if (bufsize > 0) {
- bufsize += len;
- if (lnk_added) bufsize += 4;
- w32buf = ALLOCA_N(char, bufsize);
- if (cygwin_conv_path(flags, path, w32buf, bufsize) == 0) {
- b = w32buf;
- }
- }
+ bufsize = cygwin_conv_path(flags, path, NULL, 0);
+ if (bufsize > 0) {
+ bufsize += len;
+ if (lnk_added) bufsize += 4;
+ w32buf = ALLOCA_N(char, bufsize);
+ if (cygwin_conv_path(flags, path, w32buf, bufsize) == 0) {
+ b = w32buf;
+ }
+ }
#else
- bufsize = MAXPATHLEN;
- if (cygwin_conv_to_win32_path(path, w32buf) == 0) {
- b = w32buf;
- }
-#endif
- if (is_symlink && b == w32buf) {
- *p = '\\';
- strlcat(w32buf, p, bufsize);
- if (lnk_added) {
- strlcat(w32buf, ".lnk", bufsize);
- }
- }
- else {
- lnk_added = 0;
- }
- *p = '/';
-#endif
- rb_str_set_len(result, p - buf + strlen(p));
- encidx = ENCODING_GET(result);
- tmp = result;
- if (encidx != ENCINDEX_UTF_8 && rb_enc_str_coderange(result) != ENC_CODERANGE_7BIT) {
- tmp = rb_str_encode_ospath(result);
- }
- len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, NULL, 0);
- wstr = ALLOCV_N(WCHAR, v, len);
- MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, wstr, len);
- if (tmp != result) rb_str_set_len(tmp, 0);
- h = FindFirstFileW(wstr, &wfd);
- ALLOCV_END(v);
- if (h != INVALID_HANDLE_VALUE) {
- size_t wlen;
- FindClose(h);
- len = lstrlenW(wfd.cFileName);
+ bufsize = MAXPATHLEN;
+ if (cygwin_conv_to_win32_path(path, w32buf) == 0) {
+ b = w32buf;
+ }
+#endif
+ if (is_symlink && b == w32buf) {
+ *p = '\\';
+ strlcat(w32buf, p, bufsize);
+ if (lnk_added) {
+ strlcat(w32buf, ".lnk", bufsize);
+ }
+ }
+ else {
+ lnk_added = 0;
+ }
+ *p = '/';
+#endif
+ rb_str_set_len(result, p - buf + strlen(p));
+ encidx = ENCODING_GET(result);
+ tmp = result;
+ if (encidx != ENCINDEX_UTF_8 && !is_ascii_string(result)) {
+ tmp = rb_str_encode_ospath(result);
+ }
+ len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, NULL, 0);
+ wstr = ALLOCV_N(WCHAR, v, len);
+ MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, wstr, len);
+ if (tmp != result) rb_str_set_len(tmp, 0);
+ h = FindFirstFileW(wstr, &wfd);
+ ALLOCV_END(v);
+ if (h != INVALID_HANDLE_VALUE) {
+ size_t wlen;
+ FindClose(h);
+ len = lstrlenW(wfd.cFileName);
#ifdef __CYGWIN__
- if (lnk_added && len > 4 &&
- wcscasecmp(wfd.cFileName + len - 4, L".lnk") == 0) {
- wfd.cFileName[len -= 4] = L'\0';
- }
+ if (lnk_added && len > 4 &&
+ wcscasecmp(wfd.cFileName + len - 4, L".lnk") == 0) {
+ wfd.cFileName[len -= 4] = L'\0';
+ }
#else
- p = (char *)s;
-#endif
- ++p;
- wlen = (int)len;
- len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, NULL, 0, NULL, NULL);
- if (tmp == result) {
- BUFCHECK(bdiff + len >= buflen);
- WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1, NULL, NULL);
- }
- else {
- rb_str_modify_expand(tmp, len);
- WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, RSTRING_PTR(tmp), len + 1, NULL, NULL);
- rb_str_cat_conv_enc_opts(result, bdiff, RSTRING_PTR(tmp), len,
- rb_utf8_encoding(), 0, Qnil);
- BUFINIT();
- rb_str_resize(tmp, 0);
- }
- p += len;
- }
+ p = (char *)s;
+#endif
+ ++p;
+ wlen = (int)len;
+ len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, NULL, 0, NULL, NULL);
+ if (tmp == result) {
+ BUFCHECK(bdiff + len >= buflen);
+ WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1, NULL, NULL);
+ }
+ else {
+ rb_str_modify_expand(tmp, len);
+ WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, RSTRING_PTR(tmp), len + 1, NULL, NULL);
+ rb_str_cat_conv_enc_opts(result, bdiff, RSTRING_PTR(tmp), len,
+ rb_utf8_encoding(), 0, Qnil);
+ BUFINIT();
+ rb_str_resize(tmp, 0);
+ }
+ p += len;
+ }
#ifdef __CYGWIN__
- else {
- p += strlen(p);
- }
+ else {
+ p += strlen(p);
+ }
#endif
}
#endif
@@ -4057,7 +4087,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na
}
#endif /* _WIN32 */
-#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2)
+#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, 1)
static VALUE
str_shrink(VALUE str)
@@ -4194,27 +4224,27 @@ enum rb_realpath_mode {
static int
realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE fallback,
- VALUE loopcheck, enum rb_realpath_mode mode, int last)
+ VALUE loopcheck, enum rb_realpath_mode mode, int last)
{
const char *pend = unresolved + strlen(unresolved);
rb_encoding *enc = rb_enc_get(*resolvedp);
ID resolving;
CONST_ID(resolving, "resolving");
while (unresolved < pend) {
- const char *testname = unresolved;
- const char *unresolved_firstsep = rb_enc_path_next(unresolved, pend, enc);
- long testnamelen = unresolved_firstsep - unresolved;
- const char *unresolved_nextname = unresolved_firstsep;
+ const char *testname = unresolved;
+ const char *unresolved_firstsep = rb_enc_path_next(unresolved, pend, enc);
+ long testnamelen = unresolved_firstsep - unresolved;
+ const char *unresolved_nextname = unresolved_firstsep;
while (unresolved_nextname < pend && isdirsep(*unresolved_nextname))
- unresolved_nextname++;
+ unresolved_nextname++;
unresolved = unresolved_nextname;
if (testnamelen == 1 && testname[0] == '.') {
}
else if (testnamelen == 2 && testname[0] == '.' && testname[1] == '.') {
if (*prefixlenp < RSTRING_LEN(*resolvedp)) {
- const char *resolved_str = RSTRING_PTR(*resolvedp);
- const char *resolved_names = resolved_str + *prefixlenp;
- const char *lastsep = strrdirsep(resolved_names, resolved_str + RSTRING_LEN(*resolvedp), enc);
+ const char *resolved_str = RSTRING_PTR(*resolvedp);
+ const char *resolved_names = resolved_str + *prefixlenp;
+ const char *lastsep = strrdirsep(resolved_names, resolved_str + RSTRING_LEN(*resolvedp), enc);
long len = lastsep ? lastsep - resolved_names : 0;
rb_str_resize(*resolvedp, *prefixlenp + len);
}
@@ -4225,20 +4255,20 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE f
if (*prefixlenp < RSTRING_LEN(testpath))
rb_str_cat2(testpath, "/");
#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
- if (*prefixlenp > 1 && *prefixlenp == RSTRING_LEN(testpath)) {
- const char *prefix = RSTRING_PTR(testpath);
- const char *last = rb_enc_left_char_head(prefix, prefix + *prefixlenp - 1, prefix + *prefixlenp, enc);
- if (!isdirsep(*last)) rb_str_cat2(testpath, "/");
- }
+ if (*prefixlenp > 1 && *prefixlenp == RSTRING_LEN(testpath)) {
+ const char *prefix = RSTRING_PTR(testpath);
+ const char *last = rb_enc_left_char_head(prefix, prefix + *prefixlenp - 1, prefix + *prefixlenp, enc);
+ if (!isdirsep(*last)) rb_str_cat2(testpath, "/");
+ }
#endif
rb_str_cat(testpath, testname, testnamelen);
checkval = rb_hash_aref(loopcheck, testpath);
if (!NIL_P(checkval)) {
if (checkval == ID2SYM(resolving)) {
- if (mode == RB_REALPATH_CHECK) {
- errno = ELOOP;
- return -1;
- }
+ if (mode == RB_REALPATH_CHECK) {
+ errno = ELOOP;
+ return -1;
+ }
rb_syserr_fail_path(ELOOP, testpath);
}
else {
@@ -4250,49 +4280,49 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE f
int ret;
ret = lstat_without_gvl(RSTRING_PTR(testpath), &sbuf);
if (ret == -1) {
- int e = errno;
- if (e == ENOENT && !NIL_P(fallback)) {
- if (stat_without_gvl(RSTRING_PTR(fallback), &sbuf) == 0) {
- rb_str_replace(*resolvedp, fallback);
- return 0;
- }
- }
- if (mode == RB_REALPATH_CHECK) return -1;
- if (e == ENOENT) {
- if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
- rb_syserr_fail_path(e, testpath);
+ int e = errno;
+ if (e == ENOENT && !NIL_P(fallback)) {
+ if (stat_without_gvl(RSTRING_PTR(fallback), &sbuf) == 0) {
+ rb_str_replace(*resolvedp, fallback);
+ return 0;
+ }
+ }
+ if (mode == RB_REALPATH_CHECK) return -1;
+ if (e == ENOENT) {
+ if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
+ rb_syserr_fail_path(e, testpath);
*resolvedp = testpath;
break;
}
else {
- rb_syserr_fail_path(e, testpath);
+ rb_syserr_fail_path(e, testpath);
}
}
#ifdef HAVE_READLINK
if (S_ISLNK(sbuf.st_mode)) {
- VALUE link;
- VALUE link_orig = Qnil;
- const char *link_prefix, *link_names;
+ VALUE link;
+ VALUE link_orig = Qnil;
+ const char *link_prefix, *link_names;
long link_prefixlen;
rb_hash_aset(loopcheck, testpath, ID2SYM(resolving));
- link = rb_readlink(testpath, enc);
+ link = rb_readlink(testpath, enc);
link_prefix = RSTRING_PTR(link);
- link_names = skipprefixroot(link_prefix, link_prefix + RSTRING_LEN(link), rb_enc_get(link));
- link_prefixlen = link_names - link_prefix;
- if (link_prefixlen > 0) {
- rb_encoding *tmpenc, *linkenc = rb_enc_get(link);
- link_orig = link;
- link = rb_str_subseq(link, 0, link_prefixlen);
- tmpenc = fs_enc_check(*resolvedp, link);
- if (tmpenc != linkenc) link = rb_str_conv_enc(link, linkenc, tmpenc);
- *resolvedp = link;
- *prefixlenp = link_prefixlen;
- }
- if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
- loopcheck, mode, !*unresolved_firstsep))
- return -1;
- RB_GC_GUARD(link_orig);
- rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp));
+ link_names = skipprefixroot(link_prefix, link_prefix + RSTRING_LEN(link), rb_enc_get(link));
+ link_prefixlen = link_names - link_prefix;
+ if (link_prefixlen > 0) {
+ rb_encoding *tmpenc, *linkenc = rb_enc_get(link);
+ link_orig = link;
+ link = rb_str_subseq(link, 0, link_prefixlen);
+ tmpenc = fs_enc_check(*resolvedp, link);
+ if (tmpenc != linkenc) link = rb_str_conv_enc(link, linkenc, tmpenc);
+ *resolvedp = link;
+ *prefixlenp = link_prefixlen;
+ }
+ if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
+ loopcheck, mode, !*unresolved_firstsep))
+ return -1;
+ RB_GC_GUARD(link_orig);
+ rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp));
}
else
#endif
@@ -4338,11 +4368,11 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum
}
if (!NIL_P(basedir)) {
- RSTRING_GETMEM(basedir, ptr, len);
- basedir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(basedir));
+ RSTRING_GETMEM(basedir, ptr, len);
+ basedir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(basedir));
if (ptr != basedir_names) {
- resolved = rb_str_subseq(basedir, 0, basedir_names - ptr);
- goto root_found;
+ resolved = rb_str_subseq(basedir, 0, basedir_names - ptr);
+ goto root_found;
}
}
@@ -4361,38 +4391,38 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum
}
#ifdef FILE_ALT_SEPARATOR
while (prefixptr < ptr) {
- if (*prefixptr == FILE_ALT_SEPARATOR) {
- *prefixptr = '/';
- }
- Inc(prefixptr, pend, enc);
+ if (*prefixptr == FILE_ALT_SEPARATOR) {
+ *prefixptr = '/';
+ }
+ Inc(prefixptr, pend, enc);
}
#endif
switch (rb_enc_to_index(enc)) {
- case ENCINDEX_ASCII:
+ case ENCINDEX_ASCII_8BIT:
case ENCINDEX_US_ASCII:
- rb_enc_associate_index(resolved, rb_filesystem_encindex());
+ rb_enc_associate_index(resolved, rb_filesystem_encindex());
}
loopcheck = rb_hash_new();
if (curdir_names) {
- if (realpath_rec(&prefixlen, &resolved, curdir_names, Qnil, loopcheck, mode, 0))
- return Qnil;
+ if (realpath_rec(&prefixlen, &resolved, curdir_names, Qnil, loopcheck, mode, 0))
+ return Qnil;
}
if (basedir_names) {
- if (realpath_rec(&prefixlen, &resolved, basedir_names, Qnil, loopcheck, mode, 0))
- return Qnil;
+ if (realpath_rec(&prefixlen, &resolved, basedir_names, Qnil, loopcheck, mode, 0))
+ return Qnil;
}
if (realpath_rec(&prefixlen, &resolved, path_names, Qnil, loopcheck, mode, 1))
- return Qnil;
+ return Qnil;
if (origenc && origenc != rb_enc_get(resolved)) {
- if (rb_enc_str_asciionly_p(resolved)) {
- rb_enc_associate(resolved, origenc);
- }
- else {
- resolved = rb_str_conv_enc(resolved, NULL, origenc);
- }
+ if (rb_enc_str_asciionly_p(resolved)) {
+ rb_enc_associate(resolved, origenc);
+ }
+ else {
+ resolved = rb_str_conv_enc(resolved, NULL, origenc);
+ }
}
RB_GC_GUARD(unresolved_path);
@@ -4402,6 +4432,21 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum
static VALUE rb_file_join(VALUE ary);
+#ifndef HAVE_REALPATH
+static VALUE
+rb_check_realpath_emulate_try(VALUE arg)
+{
+ VALUE *args = (VALUE *)arg;
+ return rb_check_realpath_emulate(args[0], args[1], (rb_encoding *)args[2], RB_REALPATH_CHECK);
+}
+
+static VALUE
+rb_check_realpath_emulate_rescue(VALUE arg, VALUE exc)
+{
+ return Qnil;
+}
+#endif /* HAVE_REALPATH */
+
static VALUE
rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode)
{
@@ -4458,9 +4503,9 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
rb_enc_associate(resolved, origenc);
}
- if (rb_enc_str_coderange(resolved) == ENC_CODERANGE_BROKEN) {
+ if (is_broken_string(resolved)) {
rb_enc_associate(resolved, rb_filesystem_encoding());
- if (rb_enc_str_coderange(resolved) == ENC_CODERANGE_BROKEN) {
+ if (is_broken_string(resolved)) {
rb_enc_associate(resolved, rb_ascii8bit_encoding());
}
}
@@ -4468,7 +4513,18 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
RB_GC_GUARD(unresolved_path);
return resolved;
#else
- return rb_check_realpath_emulate(basedir, path, origenc, mode);
+ if (mode == RB_REALPATH_CHECK) {
+ VALUE arg[3];
+ arg[0] = basedir;
+ arg[1] = path;
+ arg[2] = (VALUE)origenc;
+
+ return rb_rescue(rb_check_realpath_emulate_try, (VALUE)arg,
+ rb_check_realpath_emulate_rescue, Qnil);
+ }
+ else {
+ return rb_check_realpath_emulate(basedir, path, origenc, mode);
+ }
#endif /* HAVE_REALPATH */
}
@@ -4476,7 +4532,7 @@ VALUE
rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{
const enum rb_realpath_mode mode =
- strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR;
+ strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR;
return rb_check_realpath_internal(basedir, path, rb_enc_get(path), mode);
}
@@ -4540,15 +4596,15 @@ rmext(const char *p, long l0, long l1, const char *e, long l2, rb_encoding *enc)
c = rb_enc_codepoint_len(e, e + l2, &len1, enc);
if (rb_enc_ascget(e + len1, e + l2, &len2, enc) == '*' && len1 + len2 == l2) {
- if (c == '.') return l0;
- s = p;
- e = p + l1;
- last = e;
- while (s < e) {
- if (rb_enc_codepoint_len(s, e, &len1, enc) == c) last = s;
- s += len1;
- }
- return last - p;
+ if (c == '.') return l0;
+ s = p;
+ e = p + l1;
+ last = e;
+ while (s < e) {
+ if (rb_enc_codepoint_len(s, e, &len1, enc) == c) last = s;
+ s += len1;
+ }
+ return last - p;
}
if (l1 < l2) return l1;
@@ -4560,7 +4616,7 @@ rmext(const char *p, long l0, long l1, const char *e, long l2, rb_encoding *enc)
#define fncomp strncmp
#endif
if (fncomp(s, e, l2) == 0) {
- return l1-l2;
+ return l1-l2;
}
return 0;
}
@@ -4580,51 +4636,51 @@ ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encodin
root = name;
#endif
while (isdirsep(*name))
- name++;
+ name++;
if (!*name) {
- p = name - 1;
- f = 1;
+ p = name - 1;
+ f = 1;
#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
- if (name != root) {
- /* has slashes */
- }
+ if (name != root) {
+ /* has slashes */
+ }
#ifdef DOSISH_DRIVE_LETTER
- else if (*p == ':') {
- p++;
- f = 0;
- }
+ else if (*p == ':') {
+ p++;
+ f = 0;
+ }
#endif
#ifdef DOSISH_UNC
- else {
- p = "/";
- }
+ else {
+ p = "/";
+ }
#endif
#endif
}
else {
- if (!(p = strrdirsep(name, end, enc))) {
- p = name;
- }
- else {
- while (isdirsep(*p)) p++; /* skip last / */
- }
+ if (!(p = strrdirsep(name, end, enc))) {
+ p = name;
+ }
+ else {
+ while (isdirsep(*p)) p++; /* skip last / */
+ }
#if USE_NTFS
- n = ntfs_tail(p, end, enc) - p;
+ n = ntfs_tail(p, end, enc) - p;
#else
- n = chompdirsep(p, end, enc) - p;
+ n = chompdirsep(p, end, enc) - p;
#endif
- for (q = p; q - p < n && *q == '.'; q++);
- for (e = 0; q - p < n; Inc(q, end, enc)) {
- if (*q == '.') e = q;
- }
- if (e) f = e - p;
- else f = n;
+ for (q = p; q - p < n && *q == '.'; q++);
+ for (e = 0; q - p < n; Inc(q, end, enc)) {
+ if (*q == '.') e = q;
+ }
+ if (e) f = e - p;
+ else f = n;
}
if (baselen)
- *baselen = f;
+ *baselen = f;
if (alllen)
- *alllen = n;
+ *alllen = n;
return p;
}
@@ -4655,33 +4711,33 @@ rb_file_s_basename(int argc, VALUE *argv, VALUE _)
fext = Qnil;
if (rb_check_arity(argc, 1, 2) == 2) {
- fext = argv[1];
- StringValue(fext);
- enc = check_path_encoding(fext);
+ fext = argv[1];
+ StringValue(fext);
+ enc = check_path_encoding(fext);
}
fname = argv[0];
FilePathStringValue(fname);
if (NIL_P(fext) || !(enc = rb_enc_compatible(fname, fext))) {
- enc = rb_enc_get(fname);
- fext = Qnil;
+ enc = rb_enc_get(fname);
+ fext = Qnil;
}
if ((n = RSTRING_LEN(fname)) == 0 || !*(name = RSTRING_PTR(fname)))
- return rb_str_new_shared(fname);
+ return rb_str_new_shared(fname);
p = ruby_enc_find_basename(name, &f, &n, enc);
if (n >= 0) {
- if (NIL_P(fext)) {
- f = n;
- }
- else {
- const char *fp;
- fp = StringValueCStr(fext);
- if (!(f = rmext(p, f, n, fp, RSTRING_LEN(fext), enc))) {
- f = n;
- }
- RB_GC_GUARD(fext);
- }
- if (f == RSTRING_LEN(fname)) return rb_str_new_shared(fname);
+ if (NIL_P(fext)) {
+ f = n;
+ }
+ else {
+ const char *fp;
+ fp = StringValueCStr(fext);
+ if (!(f = rmext(p, f, n, fp, RSTRING_LEN(fext), enc))) {
+ f = n;
+ }
+ RB_GC_GUARD(fext);
+ }
+ if (f == RSTRING_LEN(fname)) return rb_str_new_shared(fname);
}
basename = rb_str_new(p, f);
@@ -4715,7 +4771,7 @@ rb_file_s_dirname(int argc, VALUE *argv, VALUE klass)
{
int n = 1;
if ((argc = rb_check_arity(argc, 1, 2)) > 1) {
- n = NUM2INT(argv[1]);
+ n = NUM2INT(argv[1]);
}
return rb_file_dirname_n(argv[0], n);
}
@@ -4743,58 +4799,58 @@ rb_file_dirname_n(VALUE fname, int n)
root = skiproot(name, end, enc);
#ifdef DOSISH_UNC
if (root > name + 1 && isdirsep(*name))
- root = skipprefix(name = root - 2, end, enc);
+ root = skipprefix(name = root - 2, end, enc);
#else
if (root > name + 1)
- name = root - 1;
+ name = root - 1;
#endif
if (n > (end - root + 1) / 2) {
- p = root;
+ p = root;
}
else {
- int i;
- switch (n) {
- case 0:
- p = end;
- break;
- case 1:
- if (!(p = strrdirsep(root, end, enc))) p = root;
- break;
- default:
- seps = ALLOCV_N(const char *, sepsv, n);
- for (i = 0; i < n; ++i) seps[i] = root;
- i = 0;
- for (p = root; p < end; ) {
- if (isdirsep(*p)) {
- const char *tmp = p++;
- while (p < end && isdirsep(*p)) p++;
- if (p >= end) break;
- seps[i++] = tmp;
- if (i == n) i = 0;
- }
- else {
- Inc(p, end, enc);
- }
- }
- p = seps[i];
- ALLOCV_END(sepsv);
- break;
- }
+ int i;
+ switch (n) {
+ case 0:
+ p = end;
+ break;
+ case 1:
+ if (!(p = strrdirsep(root, end, enc))) p = root;
+ break;
+ default:
+ seps = ALLOCV_N(const char *, sepsv, n);
+ for (i = 0; i < n; ++i) seps[i] = root;
+ i = 0;
+ for (p = root; p < end; ) {
+ if (isdirsep(*p)) {
+ const char *tmp = p++;
+ while (p < end && isdirsep(*p)) p++;
+ if (p >= end) break;
+ seps[i++] = tmp;
+ if (i == n) i = 0;
+ }
+ else {
+ Inc(p, end, enc);
+ }
+ }
+ p = seps[i];
+ ALLOCV_END(sepsv);
+ break;
+ }
}
if (p == name)
- return rb_usascii_str_new2(".");
+ return rb_usascii_str_new2(".");
#ifdef DOSISH_DRIVE_LETTER
if (has_drive_letter(name) && isdirsep(*(name + 2))) {
- const char *top = skiproot(name + 2, end, enc);
- dirname = rb_str_new(name, 3);
- rb_str_cat(dirname, top, p - top);
+ const char *top = skiproot(name + 2, end, enc);
+ dirname = rb_str_new(name, 3);
+ rb_str_cat(dirname, top, p - top);
}
else
#endif
dirname = rb_str_new(name, p - name);
#ifdef DOSISH_DRIVE_LETTER
if (has_drive_letter(name) && root == name + 2 && p - name == 2)
- rb_str_cat(dirname, ".", 1);
+ rb_str_cat(dirname, ".", 1);
#endif
rb_enc_copy(dirname, fname);
return dirname;
@@ -4809,7 +4865,7 @@ rb_file_dirname_n(VALUE fname, int n)
* dotfile top 0
* end with dot dot 1
* .ext dot len of .ext
- * .ext:stream dot len of .ext without :stream (NT only)
+ * .ext:stream dot len of .ext without :stream (NTFS only)
*
*/
const char *
@@ -4819,48 +4875,48 @@ ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc)
p = strrdirsep(name, end, enc); /* get the last path component */
if (!p)
- p = name;
+ p = name;
else
- do name = ++p; while (isdirsep(*p));
+ do name = ++p; while (isdirsep(*p));
e = 0;
while (*p && *p == '.') p++;
while (*p) {
- if (*p == '.' || istrailinggarbage(*p)) {
+ if (*p == '.' || istrailinggarbage(*p)) {
#if USE_NTFS
- const char *last = p++, *dot = last;
- while (istrailinggarbage(*p)) {
- if (*p == '.') dot = p;
- p++;
- }
- if (!*p || isADS(*p)) {
- p = last;
- break;
- }
- if (*last == '.' || dot > last) e = dot;
- continue;
+ const char *last = p++, *dot = last;
+ while (istrailinggarbage(*p)) {
+ if (*p == '.') dot = p;
+ p++;
+ }
+ if (!*p || isADS(*p)) {
+ p = last;
+ break;
+ }
+ if (*last == '.' || dot > last) e = dot;
+ continue;
#else
- e = p; /* get the last dot of the last component */
+ e = p; /* get the last dot of the last component */
#endif
- }
+ }
#if USE_NTFS
- else if (isADS(*p)) {
- break;
- }
+ else if (isADS(*p)) {
+ break;
+ }
#endif
- else if (isdirsep(*p))
- break;
- Inc(p, end, enc);
+ else if (isdirsep(*p))
+ break;
+ Inc(p, end, enc);
}
if (len) {
- /* no dot, or the only dot is first or end? */
- if (!e || e == name)
- *len = 0;
- else if (e+1 == p)
- *len = 1;
- else
- *len = p - e;
+ /* no dot, or the only dot is first or end? */
+ if (!e || e == name)
+ *len = 0;
+ else if (e+1 == p)
+ *len = 1;
+ else
+ *len = p - e;
}
return e;
}
@@ -4903,7 +4959,7 @@ rb_file_s_extname(VALUE klass, VALUE fname)
len = RSTRING_LEN(fname);
e = ruby_enc_find_extname(name, &len, rb_enc_get(fname));
if (len < 1)
- return rb_str_new(0, 0);
+ return rb_str_new(0, 0);
extname = rb_str_subseq(fname, e - name, len); /* keep the dot, too! */
return extname;
}
@@ -4963,53 +5019,53 @@ rb_file_join(VALUE ary)
len = 1;
for (i=0; i<RARRAY_LEN(ary); i++) {
- tmp = RARRAY_AREF(ary, i);
- if (RB_TYPE_P(tmp, T_STRING)) {
- check_path_encoding(tmp);
- len += RSTRING_LEN(tmp);
- }
- else {
- len += 10;
- }
+ tmp = RARRAY_AREF(ary, i);
+ if (RB_TYPE_P(tmp, T_STRING)) {
+ check_path_encoding(tmp);
+ len += RSTRING_LEN(tmp);
+ }
+ else {
+ len += 10;
+ }
}
len += RARRAY_LEN(ary) - 1;
result = rb_str_buf_new(len);
RBASIC_CLEAR_CLASS(result);
for (i=0; i<RARRAY_LEN(ary); i++) {
- tmp = RARRAY_AREF(ary, i);
- switch (OBJ_BUILTIN_TYPE(tmp)) {
- case T_STRING:
- if (!checked) check_path_encoding(tmp);
- StringValueCStr(tmp);
- break;
- case T_ARRAY:
- if (ary == tmp) {
- rb_raise(rb_eArgError, "recursive array");
- }
- else {
- tmp = rb_exec_recursive(file_inspect_join, ary, tmp);
- }
- break;
- default:
- FilePathStringValue(tmp);
- checked = FALSE;
- }
- RSTRING_GETMEM(result, name, len);
- if (i == 0) {
- rb_enc_copy(result, tmp);
- }
- else {
- tail = chompdirsep(name, name + len, rb_enc_get(result));
- if (RSTRING_PTR(tmp) && isdirsep(RSTRING_PTR(tmp)[0])) {
- rb_str_set_len(result, tail - name);
- }
- else if (!*tail) {
- rb_str_cat(result, "/", 1);
- }
- }
- enc = fs_enc_check(result, tmp);
- rb_str_buf_append(result, tmp);
- rb_enc_associate(result, enc);
+ tmp = RARRAY_AREF(ary, i);
+ switch (OBJ_BUILTIN_TYPE(tmp)) {
+ case T_STRING:
+ if (!checked) check_path_encoding(tmp);
+ StringValueCStr(tmp);
+ break;
+ case T_ARRAY:
+ if (ary == tmp) {
+ rb_raise(rb_eArgError, "recursive array");
+ }
+ else {
+ tmp = rb_exec_recursive(file_inspect_join, ary, tmp);
+ }
+ break;
+ default:
+ FilePathStringValue(tmp);
+ checked = FALSE;
+ }
+ RSTRING_GETMEM(result, name, len);
+ if (i == 0) {
+ rb_enc_copy(result, tmp);
+ }
+ else {
+ tail = chompdirsep(name, name + len, rb_enc_get(result));
+ if (RSTRING_PTR(tmp) && isdirsep(RSTRING_PTR(tmp)[0])) {
+ rb_str_set_len(result, tail - name);
+ }
+ else if (!*tail) {
+ rb_str_cat(result, "/", 1);
+ }
+ }
+ enc = fs_enc_check(result, tmp);
+ rb_str_buf_append(result, tmp);
+ rb_enc_associate(result, enc);
}
RBASIC_SET_CLASS_RAW(result, rb_cString);
@@ -5033,41 +5089,17 @@ rb_file_s_join(VALUE klass, VALUE args)
return rb_file_join(args);
}
-#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE)
+#if defined(HAVE_TRUNCATE)
struct truncate_arg {
const char *path;
-#if defined(HAVE_TRUNCATE)
-#define NUM2POS(n) NUM2OFFT(n)
- off_t pos;
-#else
-#define NUM2POS(n) NUM2LONG(n)
- long pos;
-#endif
+ rb_off_t pos;
};
static void *
nogvl_truncate(void *ptr)
{
struct truncate_arg *ta = ptr;
-#ifdef HAVE_TRUNCATE
return (void *)(VALUE)truncate(ta->path, ta->pos);
-#else /* defined(HAVE_CHSIZE) */
- {
- int tmpfd = rb_cloexec_open(ta->path, 0, 0);
-
- if (tmpfd < 0)
- return (void *)-1;
- rb_update_max_fd(tmpfd);
- if (chsize(tmpfd, ta->pos) < 0) {
- int e = errno;
- close(tmpfd);
- errno = e;
- return (void *)-1;
- }
- close(tmpfd);
- return 0;
- }
-#endif
}
/*
@@ -5091,32 +5123,25 @@ rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
struct truncate_arg ta;
int r;
- ta.pos = NUM2POS(len);
+ ta.pos = NUM2OFFT(len);
FilePathValue(path);
path = rb_str_encode_ospath(path);
ta.path = StringValueCStr(path);
r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_truncate, &ta,
- RUBY_UBF_IO, NULL);
+ RUBY_UBF_IO, NULL);
if (r < 0)
- rb_sys_fail_path(path);
+ rb_sys_fail_path(path);
return INT2FIX(0);
-#undef NUM2POS
}
#else
#define rb_file_s_truncate rb_f_notimplement
#endif
-#if defined(HAVE_FTRUNCATE) || defined(HAVE_CHSIZE)
+#if defined(HAVE_FTRUNCATE)
struct ftruncate_arg {
int fd;
-#if defined(HAVE_FTRUNCATE)
-#define NUM2POS(n) NUM2OFFT(n)
- off_t pos;
-#else
-#define NUM2POS(n) NUM2LONG(n)
- long pos;
-#endif
+ rb_off_t pos;
};
static VALUE
@@ -5124,11 +5149,7 @@ nogvl_ftruncate(void *ptr)
{
struct ftruncate_arg *fa = ptr;
-#ifdef HAVE_FTRUNCATE
return (VALUE)ftruncate(fa->fd, fa->pos);
-#else /* defined(HAVE_CHSIZE) */
- return (VALUE)chsize(fa->fd, fa->pos);
-#endif
}
/*
@@ -5151,18 +5172,17 @@ rb_file_truncate(VALUE obj, VALUE len)
rb_io_t *fptr;
struct ftruncate_arg fa;
- fa.pos = NUM2POS(len);
+ fa.pos = NUM2OFFT(len);
GetOpenFile(obj, fptr);
if (!(fptr->mode & FMODE_WRITABLE)) {
- rb_raise(rb_eIOError, "not opened for writing");
+ rb_raise(rb_eIOError, "not opened for writing");
}
rb_io_flush_raw(obj, 0);
fa.fd = fptr->fd;
if ((int)rb_thread_io_blocking_region(nogvl_ftruncate, &fa, fa.fd) < 0) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
return INT2FIX(0);
-#undef NUM2POS
}
#else
#define rb_file_truncate rb_f_notimplement
@@ -5195,8 +5215,8 @@ rb_thread_flock(void *data)
#ifdef __CYGWIN__
if (GetLastError() == ERROR_NOT_LOCKED) {
- ret = 0;
- errno = old_errno;
+ ret = 0;
+ errno = old_errno;
}
#endif
return (VALUE)ret;
@@ -5258,33 +5278,33 @@ rb_file_flock(VALUE obj, VALUE operation)
op[0] = fptr->fd;
if (fptr->mode & FMODE_WRITABLE) {
- rb_io_flush_raw(obj, 0);
+ rb_io_flush_raw(obj, 0);
}
while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
- int e = errno;
- switch (e) {
- case EAGAIN:
- case EACCES:
+ int e = errno;
+ switch (e) {
+ case EAGAIN:
+ case EACCES:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
+ case EWOULDBLOCK:
#endif
- if (op1 & LOCK_NB) return Qfalse;
+ if (op1 & LOCK_NB) return Qfalse;
- time.tv_sec = 0;
- time.tv_usec = 100 * 1000; /* 0.1 sec */
- rb_thread_wait_for(time);
- rb_io_check_closed(fptr);
- continue;
+ time.tv_sec = 0;
+ time.tv_usec = 100 * 1000; /* 0.1 sec */
+ rb_thread_wait_for(time);
+ rb_io_check_closed(fptr);
+ continue;
- case EINTR:
+ case EINTR:
#if defined(ERESTART)
- case ERESTART:
+ case ERESTART:
#endif
- break;
+ break;
- default:
- rb_syserr_fail_path(e, fptr->pathv);
- }
+ default:
+ rb_syserr_fail_path(e, fptr->pathv);
+ }
}
return INT2FIX(0);
}
@@ -5297,9 +5317,9 @@ test_check(int n, int argc, VALUE *argv)
n+=1;
rb_check_arity(argc, n, n);
for (i=1; i<n; i++) {
- if (!RB_TYPE_P(argv[i], T_FILE)) {
- FilePathValue(argv[i]);
- }
+ if (!RB_TYPE_P(argv[i], T_FILE)) {
+ FilePathValue(argv[i]);
+ }
}
}
@@ -5322,8 +5342,7 @@ test_check(int n, int argc, VALUE *argv)
* "d" | boolean | True if file1 exists and is a directory
* "e" | boolean | True if file1 exists
* "f" | boolean | True if file1 exists and is a regular file
- * "g" | boolean | True if file1 has the \CF{setgid} bit
- * | | set (false under NT)
+ * "g" | boolean | True if file1 has the setgid bit set
* "G" | boolean | True if file1 exists and has a group
* | | ownership equal to the caller's group
* "k" | boolean | True if file1 exists and has the sticky bit set
@@ -5374,128 +5393,128 @@ rb_f_test(int argc, VALUE *argv, VALUE _)
goto unknown;
}
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
- CHECK(1);
- switch (cmd) {
- case 'b':
- return rb_file_blockdev_p(0, argv[1]);
+ CHECK(1);
+ switch (cmd) {
+ case 'b':
+ return rb_file_blockdev_p(0, argv[1]);
- case 'c':
- return rb_file_chardev_p(0, argv[1]);
+ case 'c':
+ return rb_file_chardev_p(0, argv[1]);
- case 'd':
- return rb_file_directory_p(0, argv[1]);
+ case 'd':
+ return rb_file_directory_p(0, argv[1]);
- case 'e':
- return rb_file_exist_p(0, argv[1]);
+ case 'e':
+ return rb_file_exist_p(0, argv[1]);
- case 'f':
- return rb_file_file_p(0, argv[1]);
+ case 'f':
+ return rb_file_file_p(0, argv[1]);
- case 'g':
- return rb_file_sgid_p(0, argv[1]);
+ case 'g':
+ return rb_file_sgid_p(0, argv[1]);
- case 'G':
- return rb_file_grpowned_p(0, argv[1]);
+ case 'G':
+ return rb_file_grpowned_p(0, argv[1]);
- case 'k':
- return rb_file_sticky_p(0, argv[1]);
+ case 'k':
+ return rb_file_sticky_p(0, argv[1]);
- case 'l':
- return rb_file_symlink_p(0, argv[1]);
+ case 'l':
+ return rb_file_symlink_p(0, argv[1]);
- case 'o':
- return rb_file_owned_p(0, argv[1]);
+ case 'o':
+ return rb_file_owned_p(0, argv[1]);
- case 'O':
- return rb_file_rowned_p(0, argv[1]);
+ case 'O':
+ return rb_file_rowned_p(0, argv[1]);
- case 'p':
- return rb_file_pipe_p(0, argv[1]);
+ case 'p':
+ return rb_file_pipe_p(0, argv[1]);
- case 'r':
- return rb_file_readable_p(0, argv[1]);
+ case 'r':
+ return rb_file_readable_p(0, argv[1]);
- case 'R':
- return rb_file_readable_real_p(0, argv[1]);
+ case 'R':
+ return rb_file_readable_real_p(0, argv[1]);
- case 's':
- return rb_file_size_p(0, argv[1]);
+ case 's':
+ return rb_file_size_p(0, argv[1]);
- case 'S':
- return rb_file_socket_p(0, argv[1]);
+ case 'S':
+ return rb_file_socket_p(0, argv[1]);
- case 'u':
- return rb_file_suid_p(0, argv[1]);
+ case 'u':
+ return rb_file_suid_p(0, argv[1]);
- case 'w':
- return rb_file_writable_p(0, argv[1]);
+ case 'w':
+ return rb_file_writable_p(0, argv[1]);
- case 'W':
- return rb_file_writable_real_p(0, argv[1]);
+ case 'W':
+ return rb_file_writable_real_p(0, argv[1]);
- case 'x':
- return rb_file_executable_p(0, argv[1]);
+ case 'x':
+ return rb_file_executable_p(0, argv[1]);
- case 'X':
- return rb_file_executable_real_p(0, argv[1]);
+ case 'X':
+ return rb_file_executable_real_p(0, argv[1]);
- case 'z':
- return rb_file_zero_p(0, argv[1]);
- }
+ case 'z':
+ return rb_file_zero_p(0, argv[1]);
+ }
}
if (strchr("MAC", cmd)) {
- struct stat st;
- VALUE fname = argv[1];
-
- CHECK(1);
- if (rb_stat(fname, &st) == -1) {
- int e = errno;
- FilePathValue(fname);
- rb_syserr_fail_path(e, fname);
- }
-
- switch (cmd) {
- case 'A':
- return stat_atime(&st);
- case 'M':
- return stat_mtime(&st);
- case 'C':
- return stat_ctime(&st);
- }
+ struct stat st;
+ VALUE fname = argv[1];
+
+ CHECK(1);
+ if (rb_stat(fname, &st) == -1) {
+ int e = errno;
+ FilePathValue(fname);
+ rb_syserr_fail_path(e, fname);
+ }
+
+ switch (cmd) {
+ case 'A':
+ return stat_atime(&st);
+ case 'M':
+ return stat_mtime(&st);
+ case 'C':
+ return stat_ctime(&st);
+ }
}
if (cmd == '-') {
- CHECK(2);
- return rb_file_identical_p(0, argv[1], argv[2]);
+ CHECK(2);
+ return rb_file_identical_p(0, argv[1], argv[2]);
}
if (strchr("=<>", cmd)) {
- struct stat st1, st2;
+ struct stat st1, st2;
struct timespec t1, t2;
- CHECK(2);
- if (rb_stat(argv[1], &st1) < 0) return Qfalse;
- if (rb_stat(argv[2], &st2) < 0) return Qfalse;
+ CHECK(2);
+ if (rb_stat(argv[1], &st1) < 0) return Qfalse;
+ if (rb_stat(argv[2], &st2) < 0) return Qfalse;
t1 = stat_mtimespec(&st1);
t2 = stat_mtimespec(&st2);
- switch (cmd) {
- case '=':
- if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
- return Qfalse;
+ switch (cmd) {
+ case '=':
+ if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
+ return Qfalse;
- case '>':
- if (t1.tv_sec > t2.tv_sec) return Qtrue;
- if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
- return Qfalse;
+ case '>':
+ if (t1.tv_sec > t2.tv_sec) return Qtrue;
+ if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
+ return Qfalse;
- case '<':
- if (t1.tv_sec < t2.tv_sec) return Qtrue;
- if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
- return Qfalse;
- }
+ case '<':
+ if (t1.tv_sec < t2.tv_sec) return Qtrue;
+ if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
+ return Qfalse;
+ }
}
unknown:
/* unknown command */
@@ -5544,11 +5563,12 @@ rb_stat_init(VALUE obj, VALUE fname)
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
if (STAT(StringValueCStr(fname), &st) == -1) {
- rb_sys_fail_path(fname);
+ rb_sys_fail_path(fname);
}
+
if (DATA_PTR(obj)) {
- xfree(DATA_PTR(obj));
- DATA_PTR(obj) = NULL;
+ xfree(DATA_PTR(obj));
+ DATA_PTR(obj) = NULL;
}
nst = ALLOC(struct stat);
*nst = st;
@@ -5565,13 +5585,13 @@ rb_stat_init_copy(VALUE copy, VALUE orig)
if (!OBJ_INIT_COPY(copy, orig)) return copy;
if (DATA_PTR(copy)) {
- xfree(DATA_PTR(copy));
- DATA_PTR(copy) = 0;
+ xfree(DATA_PTR(copy));
+ DATA_PTR(copy) = 0;
}
if (DATA_PTR(orig)) {
- nst = ALLOC(struct stat);
- *nst = *(struct stat*)DATA_PTR(orig);
- DATA_PTR(copy) = nst;
+ nst = ALLOC(struct stat);
+ *nst = *(struct stat*)DATA_PTR(orig);
+ DATA_PTR(copy) = nst;
}
return copy;
@@ -5754,7 +5774,7 @@ rb_stat_rowned(VALUE obj)
* stat.grpowned? -> true or false
*
* Returns true if the effective group id of the process is the same as
- * the group id of <i>stat</i>. On Windows NT, returns <code>false</code>.
+ * the group id of <i>stat</i>. On Windows, returns <code>false</code>.
*
* File.stat("testfile").grpowned? #=> true
* File.stat("/etc/passwd").grpowned? #=> false
@@ -5791,11 +5811,11 @@ rb_stat_r(VALUE obj)
#endif
#ifdef S_IRUSR
if (rb_stat_owned(obj))
- return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_stat_grpowned(obj))
- return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IRGRP);
#endif
#ifdef S_IROTH
if (!(st->st_mode & S_IROTH)) return Qfalse;
@@ -5824,11 +5844,11 @@ rb_stat_R(VALUE obj)
#endif
#ifdef S_IRUSR
if (rb_stat_rowned(obj))
- return st->st_mode & S_IRUSR ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_group_member(get_stat(obj)->st_gid))
- return st->st_mode & S_IRGRP ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IRGRP);
#endif
#ifdef S_IROTH
if (!(st->st_mode & S_IROTH)) return Qfalse;
@@ -5855,10 +5875,10 @@ rb_stat_wr(VALUE obj)
#ifdef S_IROTH
struct stat *st = get_stat(obj);
if ((st->st_mode & (S_IROTH)) == S_IROTH) {
- return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
else {
- return Qnil;
+ return Qnil;
}
#endif
}
@@ -5884,11 +5904,11 @@ rb_stat_w(VALUE obj)
#endif
#ifdef S_IWUSR
if (rb_stat_owned(obj))
- return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_stat_grpowned(obj))
- return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IWGRP);
#endif
#ifdef S_IWOTH
if (!(st->st_mode & S_IWOTH)) return Qfalse;
@@ -5917,11 +5937,11 @@ rb_stat_W(VALUE obj)
#endif
#ifdef S_IWUSR
if (rb_stat_rowned(obj))
- return st->st_mode & S_IWUSR ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_group_member(get_stat(obj)->st_gid))
- return st->st_mode & S_IWGRP ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IWGRP);
#endif
#ifdef S_IWOTH
if (!(st->st_mode & S_IWOTH)) return Qfalse;
@@ -5948,10 +5968,10 @@ rb_stat_ww(VALUE obj)
#ifdef S_IROTH
struct stat *st = get_stat(obj);
if ((st->st_mode & (S_IWOTH)) == S_IWOTH) {
- return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
}
else {
- return Qnil;
+ return Qnil;
}
#endif
}
@@ -5976,16 +5996,16 @@ rb_stat_x(VALUE obj)
#ifdef USE_GETEUID
if (geteuid() == 0) {
- return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_owned(obj))
- return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_stat_grpowned(obj))
- return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IXGRP);
#endif
#ifdef S_IXOTH
if (!(st->st_mode & S_IXOTH)) return Qfalse;
@@ -6008,16 +6028,16 @@ rb_stat_X(VALUE obj)
#ifdef USE_GETEUID
if (getuid() == 0) {
- return st->st_mode & S_IXUGO ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_rowned(obj))
- return st->st_mode & S_IXUSR ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_group_member(get_stat(obj)->st_gid))
- return st->st_mode & S_IXGRP ? Qtrue : Qfalse;
+ return RBOOL(st->st_mode & S_IXGRP);
#endif
#ifdef S_IXOTH
if (!(st->st_mode & S_IXOTH)) return Qfalse;
@@ -6063,18 +6083,20 @@ rb_stat_z(VALUE obj)
/*
* call-seq:
- * state.size -> integer
+ * stat.size? -> Integer or nil
*
- * Returns the size of <i>stat</i> in bytes.
+ * Returns +nil+ if <i>stat</i> is a zero-length file, the size of
+ * the file otherwise.
*
- * File.stat("testfile").size #=> 66
+ * File.stat("testfile").size? #=> 66
+ * File.stat("/dev/null").size? #=> nil
*
*/
static VALUE
rb_stat_s(VALUE obj)
{
- off_t size = get_stat(obj)->st_size;
+ rb_off_t size = get_stat(obj)->st_size;
if (size == 0) return Qnil;
return OFFT2NUM(size);
@@ -6180,14 +6202,14 @@ rb_file_s_mkfifo(int argc, VALUE *argv, VALUE _)
ma.mode = 0666;
rb_check_arity(argc, 1, 2);
if (argc > 1) {
- ma.mode = NUM2MODET(argv[1]);
+ ma.mode = NUM2MODET(argv[1]);
}
path = argv[0];
FilePathValue(path);
path = rb_str_encode_ospath(path);
ma.path = RSTRING_PTR(path);
if (rb_thread_call_without_gvl(nogvl_mkfifo, &ma, RUBY_UBF_IO, 0)) {
- rb_sys_fail_path(path);
+ rb_sys_fail_path(path);
}
return INT2FIX(0);
}
@@ -6237,16 +6259,16 @@ path_check_0(VALUE path)
char *p = 0, *s;
if (!rb_is_absolute_path(p0)) {
- char *buf = ruby_getcwd();
- VALUE newpath;
+ char *buf = ruby_getcwd();
+ VALUE newpath;
- newpath = rb_str_new2(buf);
- xfree(buf);
+ newpath = rb_str_new2(buf);
+ xfree(buf);
- rb_str_cat2(newpath, "/");
- rb_str_cat2(newpath, p0);
- path = newpath;
- p0 = RSTRING_PTR(path);
+ rb_str_cat2(newpath, "/");
+ rb_str_cat2(newpath, p0);
+ path = newpath;
+ p0 = RSTRING_PTR(path);
}
e0 = p0 + RSTRING_LEN(path);
enc = rb_enc_get(path);
@@ -6254,28 +6276,28 @@ path_check_0(VALUE path)
#ifndef S_IWOTH
# define S_IWOTH 002
#endif
- if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
+ if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
#ifdef S_ISVTX
- && !(p && (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 PATH, mode 0%"
+ && !access(p0, W_OK)) {
+ rb_enc_warn(enc, "Insecure world writable dir %s in PATH, mode 0%"
#if SIZEOF_DEV_T > SIZEOF_INT
- PRI_MODET_PREFIX"o",
+ PRI_MODET_PREFIX"o",
#else
- "o",
+ "o",
#endif
- p0, st.st_mode);
- if (p) *p = '/';
- RB_GC_GUARD(path);
- return 0;
- }
- s = strrdirsep(p0, e0, enc);
- if (p) *p = '/';
- if (!s || s == p0) return 1;
- p = s;
- e0 = p;
- *p = '\0';
+ p0, st.st_mode);
+ if (p) *p = '/';
+ RB_GC_GUARD(path);
+ return 0;
+ }
+ s = strrdirsep(p0, e0, enc);
+ if (p) *p = '/';
+ if (!s || s == p0) return 1;
+ p = s;
+ e0 = p;
+ *p = '\0';
}
}
#endif
@@ -6295,13 +6317,13 @@ rb_path_check(const char *path)
if (!p) p = pend;
for (;;) {
- if (!path_check_0(rb_str_new(p0, p - p0))) {
- return 0; /* not safe */
- }
- p0 = p + 1;
- if (p0 > pend) break;
- p = strchr(p0, sep);
- if (!p) p = pend;
+ if (!path_check_0(rb_str_new(p0, p - p0))) {
+ return 0; /* not safe */
+ }
+ p0 = p + 1;
+ if (p0 > pend) break;
+ p = strchr(p0, sep);
+ if (!p) p = pend;
}
#endif
return 1;
@@ -6316,18 +6338,18 @@ ruby_is_fd_loadable(int fd)
struct stat st;
if (fstat(fd, &st) < 0)
- return 0;
+ return 0;
if (S_ISREG(st.st_mode))
- return 1;
+ return 1;
if (S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode))
- return -1;
+ return -1;
if (S_ISDIR(st.st_mode))
- errno = EISDIR;
+ errno = EISDIR;
else
- errno = ENXIO;
+ errno = ENXIO;
return 0;
#endif
@@ -6344,11 +6366,11 @@ rb_file_load_ok(const char *path)
*/
int mode = (O_RDONLY |
#if defined O_NONBLOCK
- O_NONBLOCK |
+ O_NONBLOCK |
#elif defined O_NDELAY
- O_NDELAY |
+ O_NDELAY |
#endif
- 0);
+ 0);
int fd = rb_cloexec_open(path, mode, 0);
if (fd == -1) return 0;
rb_update_max_fd(fd);
@@ -6369,6 +6391,10 @@ is_explicit_relative(const char *path)
static VALUE
copy_path_class(VALUE path, VALUE orig)
{
+ int encidx = rb_enc_get_index(orig);
+ if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII)
+ encidx = rb_filesystem_encindex();
+ rb_enc_associate_index(path, encidx);
str_shrink(path);
RBASIC_SET_CLASS(path, rb_obj_class(orig));
OBJ_FREEZE(path);
@@ -6386,24 +6412,24 @@ rb_find_file_ext(VALUE *filep, const char *const *ext)
if (!ext[0]) return 0;
if (f[0] == '~') {
- fname = file_expand_path_1(fname);
- f = RSTRING_PTR(fname);
- *filep = fname;
- expanded = 1;
+ fname = file_expand_path_1(fname);
+ f = RSTRING_PTR(fname);
+ *filep = fname;
+ expanded = 1;
}
if (expanded || rb_is_absolute_path(f) || is_explicit_relative(f)) {
- if (!expanded) fname = file_expand_path_1(fname);
- fnlen = RSTRING_LEN(fname);
- for (i=0; ext[i]; i++) {
- rb_str_cat2(fname, ext[i]);
- if (rb_file_load_ok(RSTRING_PTR(fname))) {
- *filep = copy_path_class(fname, *filep);
- return (int)(i+1);
- }
- rb_str_set_len(fname, fnlen);
- }
- return 0;
+ if (!expanded) fname = file_expand_path_1(fname);
+ fnlen = RSTRING_LEN(fname);
+ for (i=0; ext[i]; i++) {
+ rb_str_cat2(fname, ext[i]);
+ if (rb_file_load_ok(RSTRING_PTR(fname))) {
+ *filep = copy_path_class(fname, *filep);
+ return (int)(i+1);
+ }
+ rb_str_set_len(fname, fnlen);
+ }
+ return 0;
}
RB_GC_GUARD(load_path) = rb_get_expanded_load_path();
@@ -6415,19 +6441,19 @@ rb_find_file_ext(VALUE *filep, const char *const *ext)
tmp = rb_str_tmp_new(MAXPATHLEN + 2);
rb_enc_associate_index(tmp, rb_usascii_encindex());
for (j=0; ext[j]; j++) {
- rb_str_cat2(fname, ext[j]);
- for (i = 0; i < RARRAY_LEN(load_path); i++) {
- VALUE str = RARRAY_AREF(load_path, i);
+ rb_str_cat2(fname, ext[j]);
+ for (i = 0; i < RARRAY_LEN(load_path); i++) {
+ VALUE str = RARRAY_AREF(load_path, i);
RB_GC_GUARD(str) = rb_get_path(str);
- if (RSTRING_LEN(str) == 0) continue;
- rb_file_expand_path_internal(fname, str, 0, 0, tmp);
- if (rb_file_load_ok(RSTRING_PTR(tmp))) {
- *filep = copy_path_class(tmp, *filep);
- return (int)(j+1);
- }
- }
- rb_str_set_len(fname, fnlen);
+ if (RSTRING_LEN(str) == 0) continue;
+ rb_file_expand_path_internal(fname, str, 0, 0, tmp);
+ if (rb_file_load_ok(RSTRING_PTR(tmp))) {
+ *filep = copy_path_class(tmp, *filep);
+ return (int)(j+1);
+ }
+ }
+ rb_str_set_len(fname, fnlen);
}
rb_str_resize(tmp, 0);
RB_GC_GUARD(load_path);
@@ -6442,51 +6468,49 @@ rb_find_file(VALUE path)
int expanded = 0;
if (f[0] == '~') {
- tmp = file_expand_path_1(path);
- path = copy_path_class(tmp, path);
- f = RSTRING_PTR(path);
- expanded = 1;
+ tmp = file_expand_path_1(path);
+ path = copy_path_class(tmp, path);
+ f = RSTRING_PTR(path);
+ expanded = 1;
}
if (expanded || rb_is_absolute_path(f) || is_explicit_relative(f)) {
- if (!rb_file_load_ok(f)) return 0;
- if (!expanded)
- path = copy_path_class(file_expand_path_1(path), path);
- return path;
+ if (!rb_file_load_ok(f)) return 0;
+ if (!expanded)
+ path = copy_path_class(file_expand_path_1(path), path);
+ return path;
}
RB_GC_GUARD(load_path) = rb_get_expanded_load_path();
if (load_path) {
- long i;
+ long i;
- tmp = rb_str_tmp_new(MAXPATHLEN + 2);
- rb_enc_associate_index(tmp, rb_usascii_encindex());
- for (i = 0; i < RARRAY_LEN(load_path); i++) {
- VALUE str = RARRAY_AREF(load_path, i);
+ tmp = rb_str_tmp_new(MAXPATHLEN + 2);
+ rb_enc_associate_index(tmp, rb_usascii_encindex());
+ for (i = 0; i < RARRAY_LEN(load_path); i++) {
+ VALUE str = RARRAY_AREF(load_path, i);
RB_GC_GUARD(str) = rb_get_path(str);
- if (RSTRING_LEN(str) > 0) {
- rb_file_expand_path_internal(path, str, 0, 0, tmp);
- f = RSTRING_PTR(tmp);
- if (rb_file_load_ok(f)) goto found;
- }
- }
- rb_str_resize(tmp, 0);
- return 0;
+ if (RSTRING_LEN(str) > 0) {
+ rb_file_expand_path_internal(path, str, 0, 0, tmp);
+ f = RSTRING_PTR(tmp);
+ if (rb_file_load_ok(f)) goto found;
+ }
+ }
+ rb_str_resize(tmp, 0);
+ return 0;
}
else {
- return 0; /* no path, no load */
+ return 0; /* no path, no load */
}
found:
return copy_path_class(tmp, path);
}
-static void
-define_filetest_function(const char *name, VALUE (*func)(ANYARGS), int argc)
-{
- rb_define_module_function(rb_mFileTest, name, func, argc);
- rb_define_singleton_method(rb_cFile, name, func, argc);
-}
+#define define_filetest_function(name, func, argc) do { \
+ rb_define_module_function(rb_mFileTest, name, func, argc); \
+ rb_define_singleton_method(rb_cFile, name, func, argc); \
+} while(false)
const char ruby_null_device[] =
#if defined DOSISH
@@ -6501,174 +6525,805 @@ const char ruby_null_device[] =
;
/*
- * A File is an abstraction of any file object accessible by the
- * program and is closely associated with class IO. File includes
- * the methods of module FileTest as class methods, allowing you to
- * write (for example) <code>File.exist?("foo")</code>.
- *
- * In the description of File methods,
- * <em>permission bits</em> are a platform-specific
- * set of bits that indicate permissions of a file. On Unix-based
- * systems, permissions are viewed as a set of three octets, for the
- * owner, the group, and the rest of the world. For each of these
- * entities, permissions may be set to read, write, or execute the
- * file:
- *
- * The permission bits <code>0644</code> (in octal) would thus be
- * interpreted as read/write for owner, and read-only for group and
- * other. Higher-order bits may also be used to indicate the type of
- * file (plain, directory, pipe, socket, and so on) and various other
- * special features. If the permissions are for a directory, the
- * meaning of the execute bit changes; when set the directory can be
- * searched.
- *
- * On non-Posix operating systems, there may be only the ability to
- * make a file read-only or read-write. In this case, the remaining
- * permission bits will be synthesized to resemble typical values. For
- * instance, on Windows NT the default permission bits are
- * <code>0644</code>, which means read/write for owner, read-only for
- * all others. The only change that can be made is to make the file
+ * A \File object is a representation of a file in the underlying platform.
+ *
+ * \Class \File extends module FileTest, supporting such singleton methods
+ * as <tt>File.exist?</tt>.
+ *
+ * === About the Examples
+ *
+ * Many examples here use these variables:
+ *
+ * :include: doc/examples/files.rdoc
+ *
+ * == Access Modes
+ *
+ * \Methods File.new and File.open each create a \File object for a given file path.
+ *
+ * === \String Access Modes
+ *
+ * \Methods File.new and File.open each may take string argument +mode+, which:
+ *
+ * - Begins with a 1- or 2-character
+ * {read/write mode}[rdoc-ref:File@Read-2FWrite+Mode].
+ * - May also contain a 1-character {data mode}[rdoc-ref:File@Data+Mode].
+ * - May also contain a 1-character
+ * {file-create mode}[rdoc-ref:File@File-Create+Mode].
+ *
+ * ==== Read/Write Mode
+ *
+ * The read/write +mode+ determines:
+ *
+ * - Whether the file is to be initially truncated.
+ *
+ * - Whether reading is allowed, and if so:
+ *
+ * - The initial read position in the file.
+ * - Where in the file reading can occur.
+ *
+ * - Whether writing is allowed, and if so:
+ *
+ * - The initial write position in the file.
+ * - Where in the file writing can occur.
+ *
+ * These tables summarize:
+ *
+ * Read/Write Modes for Existing File
+ *
+ * |------|-----------|----------|----------|----------|-----------|
+ * | R/W | Initial | | Initial | | Initial |
+ * | Mode | Truncate? | Read | Read Pos | Write | Write Pos |
+ * |------|-----------|----------|----------|----------|-----------|
+ * | 'r' | No | Anywhere | 0 | Error | - |
+ * | 'w' | Yes | Error | - | Anywhere | 0 |
+ * | 'a' | No | Error | - | End only | End |
+ * | 'r+' | No | Anywhere | 0 | Anywhere | 0 |
+ * | 'w+' | Yes | Anywhere | 0 | Anywhere | 0 |
+ * | 'a+' | No | Anywhere | End | End only | End |
+ * |------|-----------|----------|----------|----------|-----------|
+ *
+ * Read/Write Modes for \File To Be Created
+ *
+ * |------|----------|----------|----------|-----------|
+ * | R/W | | Initial | | Initial |
+ * | Mode | Read | Read Pos | Write | Write Pos |
+ * |------|----------|----------|----------|-----------|
+ * | 'w' | Error | - | Anywhere | 0 |
+ * | 'a' | Error | - | End only | 0 |
+ * | 'w+' | Anywhere | 0 | Anywhere | 0 |
+ * | 'a+' | Anywhere | 0 | End only | End |
+ * |------|----------|----------|----------|-----------|
+ *
+ * Note that modes <tt>'r'</tt> and <tt>'r+'</tt> are not allowed
+ * for a non-existent file (exception raised).
+ *
+ * In the tables:
+ *
+ * - +Anywhere+ means that methods IO#rewind, IO#pos=, and IO#seek
+ * may be used to change the file's position,
+ * so that allowed reading or writing may occur anywhere in the file.
+ * - <tt>End only</tt> means that writing can occur only at end-of-file,
+ * and that methods IO#rewind, IO#pos=, and IO#seek do not affect writing.
+ * - +Error+ means that an exception is raised if disallowed reading or writing
+ * is attempted.
+ *
+ * ===== Read/Write Modes for Existing \File
+ *
+ * - <tt>'r'</tt>:
+ *
+ * - File is not initially truncated:
+ *
+ * f = File.new('t.txt') # => #<File:t.txt>
+ * f.size == 0 # => false
+ *
+ * - File's initial read position is 0:
+ *
+ * f.pos # => 0
+ *
+ * - File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.readline # => "First line\n"
+ * f.readline # => "Second line\n"
+ *
+ * f.rewind
+ * f.readline # => "First line\n"
+ *
+ * f.pos = 1
+ * f.readline # => "irst line\n"
+ *
+ * f.seek(1, :CUR)
+ * f.readline # => "econd line\n"
+ *
+ * - Writing is not allowed:
+ *
+ * f.write('foo') # Raises IOError.
+ *
+ * - <tt>'w'</tt>:
+ *
+ * - File is initially truncated:
+ *
+ * path = 't.tmp'
+ * File.write(path, text)
+ * f = File.new(path, 'w')
+ * f.size == 0 # => true
+ *
+ * - File's initial write position is 0:
+ *
+ * f.pos # => 0
+ *
+ * - File may be written anywhere (even past end-of-file);
+ * see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.write('foo')
+ * f.flush
+ * File.read(path) # => "foo"
+ * f.pos # => 3
+ *
+ * f.write('bar')
+ * f.flush
+ * File.read(path) # => "foobar"
+ * f.pos # => 6
+ *
+ * f.rewind
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "bazbar"
+ * f.pos # => 3
+ *
+ * f.pos = 3
+ * f.write('foo')
+ * f.flush
+ * File.read(path) # => "bazfoo"
+ * f.pos # => 6
+ *
+ * f.seek(-3, :END)
+ * f.write('bam')
+ * f.flush
+ * File.read(path) # => "bazbam"
+ * f.pos # => 6
+ *
+ * f.pos = 8
+ * f.write('bah') # Zero padding as needed.
+ * f.flush
+ * File.read(path) # => "bazbam\u0000\u0000bah"
+ * f.pos # => 11
+ *
+ * - Reading is not allowed:
+ *
+ * f.read # Raises IOError.
+ *
+ * - <tt>'a'</tt>:
+ *
+ * - File is not initially truncated:
+ *
+ * path = 't.tmp'
+ * File.write(path, 'foo')
+ * f = File.new(path, 'a')
+ * f.size == 0 # => false
+ *
+ * - File's initial position is 0 (but is ignored):
+ *
+ * f.pos # => 0
+ *
+ * - File may be written only at end-of-file;
+ * IO#rewind, IO#pos=, IO#seek do not affect writing:
+ *
+ * f.write('bar')
+ * f.flush
+ * File.read(path) # => "foobar"
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "foobarbaz"
+ *
+ * f.rewind
+ * f.write('bat')
+ * f.flush
+ * File.read(path) # => "foobarbazbat"
+ *
+ * - Reading is not allowed:
+ *
+ * f.read # Raises IOError.
+ *
+ * - <tt>'r+'</tt>:
+ *
+ * - File is not initially truncated:
+ *
+ * path = 't.tmp'
+ * File.write(path, text)
+ * f = File.new(path, 'r+')
+ * f.size == 0 # => false
+ *
+ * - File's initial read position is 0:
+ *
+ * f.pos # => 0
+ *
+ * - File may be read or written anywhere (even past end-of-file);
+ * see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.readline # => "First line\n"
+ * f.readline # => "Second line\n"
+ *
+ * f.rewind
+ * f.readline # => "First line\n"
+ *
+ * f.pos = 1
+ * f.readline # => "irst line\n"
+ *
+ * f.seek(1, :CUR)
+ * f.readline # => "econd line\n"
+ *
+ * f.rewind
+ * f.write('WWW')
+ * f.flush
+ * File.read(path)
+ * # => "WWWst line\nSecond line\nFourth line\nFifth line\n"
+ *
+ * f.pos = 10
+ * f.write('XXX')
+ * f.flush
+ * File.read(path)
+ * # => "WWWst lineXXXecond line\nFourth line\nFifth line\n"
+ *
+ * f.seek(-6, :END)
+ * # => 0
+ * f.write('YYY')
+ * # => 3
+ * f.flush
+ * # => #<File:t.tmp>
+ * File.read(path)
+ * # => "WWWst lineXXXecond line\nFourth line\nFifth YYYe\n"
+ *
+ * f.seek(2, :END)
+ * f.write('ZZZ') # Zero padding as needed.
+ * f.flush
+ * File.read(path)
+ * # => "WWWst lineXXXecond line\nFourth line\nFifth YYYe\n\u0000\u0000ZZZ"
+ *
+ *
+ * - <tt>'a+'</tt>:
+ *
+ * - File is not initially truncated:
+ *
+ * path = 't.tmp'
+ * File.write(path, 'foo')
+ * f = File.new(path, 'a+')
+ * f.size == 0 # => false
+ *
+ * - File's initial read position is 0:
+ *
+ * f.pos # => 0
+ *
+ * - File may be written only at end-of-file;
+ * IO#rewind, IO#pos=, IO#seek do not affect writing:
+ *
+ * f.write('bar')
+ * f.flush
+ * File.read(path) # => "foobar"
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "foobarbaz"
+ *
+ * f.rewind
+ * f.write('bat')
+ * f.flush
+ * File.read(path) # => "foobarbazbat"
+ *
+ * - File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.rewind
+ * f.read # => "foobarbazbat"
+ *
+ * f.pos = 3
+ * f.read # => "barbazbat"
+ *
+ * f.seek(-3, :END)
+ * f.read # => "bat"
+ *
+ * ===== Read/Write Modes for \File To Be Created
+ *
+ * Note that modes <tt>'r'</tt> and <tt>'r+'</tt> are not allowed
+ * for a non-existent file (exception raised).
+ *
+ * - <tt>'w'</tt>:
+ *
+ * - File's initial write position is 0:
+ *
+ * path = 't.tmp'
+ * FileUtils.rm_f(path)
+ * f = File.new(path, 'w')
+ * f.pos # => 0
+ *
+ * - File may be written anywhere (even past end-of-file);
+ * see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.write('foo')
+ * f.flush
+ * File.read(path) # => "foo"
+ * f.pos # => 3
+ *
+ * f.write('bar')
+ * f.flush
+ * File.read(path) # => "foobar"
+ * f.pos # => 6
+ *
+ * f.rewind
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "bazbar"
+ * f.pos # => 3
+ *
+ * f.pos = 3
+ * f.write('foo')
+ * f.flush
+ * File.read(path) # => "bazfoo"
+ * f.pos # => 6
+ *
+ * f.seek(-3, :END)
+ * f.write('bam')
+ * f.flush
+ * File.read(path) # => "bazbam"
+ * f.pos # => 6
+ *
+ * f.pos = 8
+ * f.write('bah') # Zero padding as needed.
+ * f.flush
+ * File.read(path) # => "bazbam\u0000\u0000bah"
+ * f.pos # => 11
+ *
+ * - Reading is not allowed:
+ *
+ * f.read # Raises IOError.
+ *
+ * - <tt>'a'</tt>:
+ *
+ * - File's initial write position is 0:
+ *
+ * path = 't.tmp'
+ * FileUtils.rm_f(path)
+ * f = File.new(path, 'a')
+ * f.pos # => 0
+ *
+ * - Writing occurs only at end-of-file:
+ *
+ * f.write('foo')
+ * f.pos # => 3
+ * f.write('bar')
+ * f.pos # => 6
+ * f.flush
+ * File.read(path) # => "foobar"
+ *
+ * f.rewind
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "foobarbaz"
+ *
+ * - Reading is not allowed:
+ *
+ * f.read # Raises IOError.
+ *
+ * - <tt>'w+'</tt>:
+ *
+ * - File's initial position is 0:
+ *
+ * path = 't.tmp'
+ * FileUtils.rm_f(path)
+ * f = File.new(path, 'w+')
+ * f.pos # => 0
+ *
+ * - File may be written anywhere (even past end-of-file);
+ * see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.write('foo')
+ * f.flush
+ * File.read(path) # => "foo"
+ * f.pos # => 3
+ *
+ * f.write('bar')
+ * f.flush
+ * File.read(path) # => "foobar"
+ * f.pos # => 6
+ *
+ * f.rewind
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "bazbar"
+ * f.pos # => 3
+ *
+ * f.pos = 3
+ * f.write('foo')
+ * f.flush
+ * File.read(path) # => "bazfoo"
+ * f.pos # => 6
+ *
+ * f.seek(-3, :END)
+ * f.write('bam')
+ * f.flush
+ * File.read(path) # => "bazbam"
+ * f.pos # => 6
+ *
+ * f.pos = 8
+ * f.write('bah') # Zero padding as needed.
+ * f.flush
+ * File.read(path) # => "bazbam\u0000\u0000bah"
+ * f.pos # => 11
+ *
+ * - File may be read anywhere (even past end-of-file);
+ * see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.rewind
+ * # => 0
+ * f.read
+ * # => "bazbam\u0000\u0000bah"
+ *
+ * f.pos = 3
+ * # => 3
+ * f.read
+ * # => "bam\u0000\u0000bah"
+ *
+ * f.seek(-3, :END)
+ * # => 0
+ * f.read
+ * # => "bah"
+ *
+ * - <tt>'a+'</tt>:
+ *
+ * - File's initial write position is 0:
+ *
+ * path = 't.tmp'
+ * FileUtils.rm_f(path)
+ * f = File.new(path, 'a+')
+ * f.pos # => 0
+ *
+ * - Writing occurs only at end-of-file:
+ *
+ * f.write('foo')
+ * f.pos # => 3
+ * f.write('bar')
+ * f.pos # => 6
+ * f.flush
+ * File.read(path) # => "foobar"
+ *
+ * f.rewind
+ * f.write('baz')
+ * f.flush
+ * File.read(path) # => "foobarbaz"
+ *
+ * - File may be read anywhere (even past end-of-file);
+ * see IO#rewind, IO#pos=, IO#seek:
+ *
+ * f.rewind
+ * f.read # => "foobarbaz"
+ *
+ * f.pos = 3
+ * f.read # => "barbaz"
+ *
+ * f.seek(-3, :END)
+ * f.read # => "baz"
+ *
+ * f.pos = 800
+ * f.read # => ""
+ *
+ * ==== \Data Mode
+ *
+ * To specify whether data is to be treated as text or as binary data,
+ * either of the following may be suffixed to any of the string read/write modes
+ * above:
+ *
+ * - <tt>'t'</tt>: Text data; sets the default external encoding
+ * to <tt>Encoding::UTF_8</tt>;
+ * on Windows, enables conversion between EOL and CRLF
+ * and enables interpreting <tt>0x1A</tt> as an end-of-file marker.
+ * - <tt>'b'</tt>: Binary data; sets the default external encoding
+ * to <tt>Encoding::ASCII_8BIT</tt>;
+ * on Windows, suppresses conversion between EOL and CRLF
+ * and disables interpreting <tt>0x1A</tt> as an end-of-file marker.
+ *
+ * If neither is given, the stream defaults to text data.
+ *
+ * Examples:
+ *
+ * File.new('t.txt', 'rt')
+ * File.new('t.dat', 'rb')
+ *
+ * When the data mode is specified, the read/write mode may not be omitted,
+ * and the data mode must precede the file-create mode, if given:
+ *
+ * File.new('t.dat', 'b') # Raises an exception.
+ * File.new('t.dat', 'rxb') # Raises an exception.
+ *
+ * ==== \File-Create Mode
+ *
+ * The following may be suffixed to any writable string mode above:
+ *
+ * - <tt>'x'</tt>: Creates the file if it does not exist;
+ * raises an exception if the file exists.
+ *
+ * Example:
+ *
+ * File.new('t.tmp', 'wx')
+ *
+ * When the file-create mode is specified, the read/write mode may not be omitted,
+ * and the file-create mode must follow the data mode:
+ *
+ * File.new('t.dat', 'x') # Raises an exception.
+ * File.new('t.dat', 'rxb') # Raises an exception.
+ *
+ * === \Integer Access Modes
+ *
+ * When mode is an integer it must be one or more of the following constants,
+ * which may be combined by the bitwise OR operator <tt>|</tt>:
+ *
+ * - +File::RDONLY+: Open for reading only.
+ * - +File::WRONLY+: Open for writing only.
+ * - +File::RDWR+: Open for reading and writing.
+ * - +File::APPEND+: Open for appending only.
+ *
+ * Examples:
+ *
+ * File.new('t.txt', File::RDONLY)
+ * File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
+ *
+ * Note: Method IO#set_encoding does not allow the mode to be specified as an integer.
+ *
+ * === File-Create Mode Specified as an \Integer
+ *
+ * These constants may also be ORed into the integer mode:
+ *
+ * - +File::CREAT+: Create file if it does not exist.
+ * - +File::EXCL+: Raise an exception if +File::CREAT+ is given and the file exists.
+ *
+ * === \Data Mode Specified as an \Integer
+ *
+ * \Data mode cannot be specified as an integer.
+ * When the stream access mode is given as an integer,
+ * the data mode is always text, never binary.
+ *
+ * Note that although there is a constant +File::BINARY+,
+ * setting its value in an integer stream mode has no effect;
+ * this is because, as documented in File::Constants,
+ * the +File::BINARY+ value disables line code conversion,
+ * but does not change the external encoding.
+ *
+ * === Encodings
+ *
+ * Any of the string modes above may specify encodings -
+ * either external encoding only or both external and internal encodings -
+ * by appending one or both encoding names, separated by colons:
+ *
+ * f = File.new('t.dat', 'rb')
+ * f.external_encoding # => #<Encoding:ASCII-8BIT>
+ * f.internal_encoding # => nil
+ * f = File.new('t.dat', 'rb:UTF-16')
+ * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
+ * f.internal_encoding # => nil
+ * f = File.new('t.dat', 'rb:UTF-16:UTF-16')
+ * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
+ * f.internal_encoding # => #<Encoding:UTF-16>
+ * f.close
+ *
+ * The numerous encoding names are available in array Encoding.name_list:
+ *
+ * Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
+ *
+ * When the external encoding is set, strings read are tagged by that encoding
+ * when reading, and strings written are converted to that encoding when
+ * writing.
+ *
+ * When both external and internal encodings are set,
+ * strings read are converted from external to internal encoding,
+ * and strings written are converted from internal to external encoding.
+ * For further details about transcoding input and output,
+ * see {Encodings}[rdoc-ref:encodings.rdoc@Encodings].
+ *
+ * If the external encoding is <tt>'BOM|UTF-8'</tt>, <tt>'BOM|UTF-16LE'</tt>
+ * or <tt>'BOM|UTF16-BE'</tt>,
+ * Ruby checks for a Unicode BOM in the input document
+ * to help determine the encoding.
+ * For UTF-16 encodings the file open mode must be binary.
+ * If the BOM is found,
+ * it is stripped and the external encoding from the BOM is used.
+ *
+ * Note that the BOM-style encoding option is case insensitive,
+ * so <tt>'bom|utf-8'</tt> is also valid.
+ *
+ * == \File Permissions
+ *
+ * A \File object has _permissions_, an octal integer representing
+ * the permissions of an actual file in the underlying platform.
+ *
+ * Note that file permissions are quite different from the _mode_
+ * of a file stream (\File object).
+ * See IO@Modes.
+ *
+ * In a \File object, the permissions are available thus,
+ * where method +mode+, despite its name, returns permissions:
+ *
+ * f = File.new('t.txt')
+ * f.lstat.mode.to_s(8) # => "100644"
+ *
+ * On a Unix-based operating system,
+ * the three low-order octal digits represent the permissions
+ * for owner (6), group (4), and world (4).
+ * The triplet of bits in each octal digit represent, respectively,
+ * read, write, and execute permissions.
+ *
+ * Permissions <tt>0644</tt> thus represent read-write access for owner
+ * and read-only access for group and world.
+ * See man pages {open(2)}[https://www.unix.com/man-page/bsd/2/open]
+ * and {chmod(2)}[https://www.unix.com/man-page/bsd/2/chmod].
+ *
+ * For a directory, the meaning of the execute bit changes:
+ * when set, the directory can be searched.
+ *
+ * Higher-order bits in permissions may indicate the type of file
+ * (plain, directory, pipe, socket, etc.) and various other special features.
+ *
+ * On non-Posix operating systems, permissions may include only read-only or read-write,
+ * in which case, the remaining permission will resemble typical values.
+ * On Windows, for instance, the default permissions are <code>0644</code>;
+ * The only change that can be made is to make the file
* read-only, which is reported as <code>0444</code>.
*
- * Various constants for the methods in File can be found in File::Constants.
+ * For a method that actually creates a file in the underlying platform
+ * (as opposed to merely creating a \File object),
+ * permissions may be specified:
+ *
+ * File.new('t.tmp', File::CREAT, 0644)
+ * File.new('t.tmp', File::CREAT, 0444)
+ *
+ * Permissions may also be changed:
+ *
+ * f = File.new('t.tmp', File::CREAT, 0444)
+ * f.chmod(0644)
+ * f.chmod(0444)
+ *
+ * == \File \Constants
+ *
+ * Various constants for use in \File and \IO methods
+ * may be found in module File::Constants;
+ * an array of their names is returned by <tt>File::Constants.constants</tt>.
*
* == What's Here
*
* First, what's elsewhere. \Class \File:
*
- * - Inherits from {class IO}[IO.html#class-IO-label-What-27s+Here],
+ * - Inherits from {class IO}[rdoc-ref:IO@What-27s+Here],
* in particular, methods for creating, reading, and writing files
- * - Includes {module FileTest}[FileTest.html#module-FileTest-label-What-27s+Here].
+ * - Includes {module FileTest}[rdoc-ref:FileTest@What-27s+Here].
* which provides dozens of additional methods.
*
* Here, class \File provides methods that are useful for:
*
- * - {Creating}[#class-File-label-Creating]
- * - {Querying}[#class-File-label-Querying]
- * - {Settings}[#class-File-label-Settings]
- * - {Other}[#class-File-label-Other]
+ * - {Creating}[rdoc-ref:File@Creating]
+ * - {Querying}[rdoc-ref:File@Querying]
+ * - {Settings}[rdoc-ref:File@Settings]
+ * - {Other}[rdoc-ref:File@Other]
*
* === Creating
*
- * - ::new:: Opens the file at the given path; returns the file.
- * - ::open:: Same as ::new, but when given a block will yield the file to the block,
- * and close the file upon exiting the block.
- * - ::link:: Creates a new name for an existing file using a hard link.
- * - ::mkfifo:: Returns the FIFO file created at the given path.
- * - ::symlink:: Creates a symbolic link for the given file path.
+ * - ::new: Opens the file at the given path; returns the file.
+ * - ::open: Same as ::new, but when given a block will yield the file to the block,
+ * and close the file upon exiting the block.
+ * - ::link: Creates a new name for an existing file using a hard link.
+ * - ::mkfifo: Returns the FIFO file created at the given path.
+ * - ::symlink: Creates a symbolic link for the given file path.
*
* === Querying
*
* _Paths_
*
- * - ::absolute_path:: Returns the absolute file path for the given path.
- * - ::absolute_path?:: Returns whether the given path is the absolute file path.
- * - ::basename:: Returns the last component of the given file path.
- * - ::dirname:: Returns all but the last component of the given file path.
- * - ::expand_path:: Returns the absolute file path for the given path,
- * expanding <tt>~</tt> for a home directory.
- * - ::extname:: Returns the file extension for the given file path.
- * - ::fnmatch? (aliased as ::fnmatch):: Returns whether the given file path
- * matches the given pattern.
- * - ::join:: Joins path components into a single path string.
- * - ::path:: Returns the string representation of the given path.
- * - ::readlink:: Returns the path to the file at the given symbolic link.
- * - ::realdirpath:: Returns the real path for the given file path,
- * where the last component need not exist.
- * - ::realpath:: Returns the real path for the given file path,
- * where all components must exist.
- * - ::split:: Returns an array of two strings: the directory name and basename
- * of the file at the given path.
- * - #path (aliased as #to_path):: Returns the string representation of the given path.
+ * - ::absolute_path: Returns the absolute file path for the given path.
+ * - ::absolute_path?: Returns whether the given path is the absolute file path.
+ * - ::basename: Returns the last component of the given file path.
+ * - ::dirname: Returns all but the last component of the given file path.
+ * - ::expand_path: Returns the absolute file path for the given path,
+ * expanding <tt>~</tt> for a home directory.
+ * - ::extname: Returns the file extension for the given file path.
+ * - ::fnmatch? (aliased as ::fnmatch): Returns whether the given file path
+ * matches the given pattern.
+ * - ::join: Joins path components into a single path string.
+ * - ::path: Returns the string representation of the given path.
+ * - ::readlink: Returns the path to the file at the given symbolic link.
+ * - ::realdirpath: Returns the real path for the given file path,
+ * where the last component need not exist.
+ * - ::realpath: Returns the real path for the given file path,
+ * where all components must exist.
+ * - ::split: Returns an array of two strings: the directory name and basename
+ * of the file at the given path.
+ * - #path (aliased as #to_path): Returns the string representation of the given path.
*
* _Times_
*
- * - ::atime:: Returns a \Time for the most recent access to the given file.
- * - ::birthtime:: Returns a \Time for the creation of the given file.
- * - ::ctime:: Returns a \Time for the metadata change of the given file.
- * - ::mtime:: Returns a \Time for the most recent data modification to
- * the content of the given file.
- * - #atime:: Returns a \Time for the most recent access to +self+.
- * - #birthtime:: Returns a \Time the creation for +self+.
- * - #ctime:: Returns a \Time for the metadata change of +self+.
- * - #mtime:: Returns a \Time for the most recent data modification
- * to the content of +self+.
+ * - ::atime: Returns a \Time for the most recent access to the given file.
+ * - ::birthtime: Returns a \Time for the creation of the given file.
+ * - ::ctime: Returns a \Time for the metadata change of the given file.
+ * - ::mtime: Returns a \Time for the most recent data modification to
+ * the content of the given file.
+ * - #atime: Returns a \Time for the most recent access to +self+.
+ * - #birthtime: Returns a \Time the creation for +self+.
+ * - #ctime: Returns a \Time for the metadata change of +self+.
+ * - #mtime: Returns a \Time for the most recent data modification
+ * to the content of +self+.
*
* _Types_
*
- * - ::blockdev?:: Returns whether the file at the given path is a block device.
- * - ::chardev?:: Returns whether the file at the given path is a character device.
- * - ::directory?:: Returns whether the file at the given path is a diretory.
- * - ::executable?:: Returns whether the file at the given path is executable
- * by the effective user and group of the current process.
- * - ::executable_real?:: Returns whether the file at the given path is executable
- * by the real user and group of the current process.
- * - ::exist?:: Returns whether the file at the given path exists.
- * - ::file?:: Returns whether the file at the given path is a regular file.
- * - ::ftype:: Returns a string giving the type of the file at the given path.
- * - ::grpowned?:: Returns whether the effective group of the current process
- * owns the file at the given path.
- * - ::identical?:: Returns whether the files at two given paths are identical.
- * - ::lstat:: Returns the File::Stat object for the last symbolic link
- * in the given path.
- * - ::owned?:: Returns whether the effective user of the current process
- * owns the file at the given path.
- * - ::pipe?:: Returns whether the file at the given path is a pipe.
- * - ::readable?:: Returns whether the file at the given path is readable
- * by the effective user and group of the current process.
- * - ::readable_real?:: Returns whether the file at the given path is readable
- * by the real user and group of the current process.
- * - ::setgid?:: Returns whether the setgid bit is set for the file at the given path.
- * - ::setuid?:: Returns whether the setuid bit is set for the file at the given path.
- * - ::socket?:: Returns whether the file at the given path is a socket.
- * - ::stat:: Returns the File::Stat object for the file at the given path.
- * - ::sticky?:: Returns whether the file at the given path has its sticky bit set.
- * - ::symlink?:: Returns whether the file at the given path is a symbolic link.
- * - ::umask:: Returns the umask value for the current process.
- * - ::world_readable?:: Returns whether the file at the given path is readable
- * by others.
- * - ::world_writable?:: Returns whether the file at the given path is writable
- * by others.
- * - ::writable?:: Returns whether the file at the given path is writable
- * by the effective user and group of the current process.
- * - ::writable_real?:: Returns whether the file at the given path is writable
- * by the real user and group of the current process.
- * - #lstat:: Returns the File::Stat object for the last symbolic link
- * in the path for +self+.
+ * - ::blockdev?: Returns whether the file at the given path is a block device.
+ * - ::chardev?: Returns whether the file at the given path is a character device.
+ * - ::directory?: Returns whether the file at the given path is a directory.
+ * - ::executable?: Returns whether the file at the given path is executable
+ * by the effective user and group of the current process.
+ * - ::executable_real?: Returns whether the file at the given path is executable
+ * by the real user and group of the current process.
+ * - ::exist?: Returns whether the file at the given path exists.
+ * - ::file?: Returns whether the file at the given path is a regular file.
+ * - ::ftype: Returns a string giving the type of the file at the given path.
+ * - ::grpowned?: Returns whether the effective group of the current process
+ * owns the file at the given path.
+ * - ::identical?: Returns whether the files at two given paths are identical.
+ * - ::lstat: Returns the File::Stat object for the last symbolic link
+ * in the given path.
+ * - ::owned?: Returns whether the effective user of the current process
+ * owns the file at the given path.
+ * - ::pipe?: Returns whether the file at the given path is a pipe.
+ * - ::readable?: Returns whether the file at the given path is readable
+ * by the effective user and group of the current process.
+ * - ::readable_real?: Returns whether the file at the given path is readable
+ * by the real user and group of the current process.
+ * - ::setgid?: Returns whether the setgid bit is set for the file at the given path.
+ * - ::setuid?: Returns whether the setuid bit is set for the file at the given path.
+ * - ::socket?: Returns whether the file at the given path is a socket.
+ * - ::stat: Returns the File::Stat object for the file at the given path.
+ * - ::sticky?: Returns whether the file at the given path has its sticky bit set.
+ * - ::symlink?: Returns whether the file at the given path is a symbolic link.
+ * - ::umask: Returns the umask value for the current process.
+ * - ::world_readable?: Returns whether the file at the given path is readable
+ * by others.
+ * - ::world_writable?: Returns whether the file at the given path is writable
+ * by others.
+ * - ::writable?: Returns whether the file at the given path is writable
+ * by the effective user and group of the current process.
+ * - ::writable_real?: Returns whether the file at the given path is writable
+ * by the real user and group of the current process.
+ * - #lstat: Returns the File::Stat object for the last symbolic link
+ * in the path for +self+.
*
* _Contents_
*
- * - ::empty? (aliased as ::zero?):: Returns whether the file at the given path
- * exists and is empty.
- * - ::size:: Returns the size (bytes) of the file at the given path.
- * - ::size?:: Returns +nil+ if there is no file at the given path,
- * or if that file is empty; otherwise returns the file size (bytes).
- * - #size:: Returns the size (bytes) of +self+.
+ * - ::empty? (aliased as ::zero?): Returns whether the file at the given path
+ * exists and is empty.
+ * - ::size: Returns the size (bytes) of the file at the given path.
+ * - ::size?: Returns +nil+ if there is no file at the given path,
+ * or if that file is empty; otherwise returns the file size (bytes).
+ * - #size: Returns the size (bytes) of +self+.
*
* === Settings
*
- * - ::chmod:: Changes permissions of the file at the given path.
- * - ::chown:: Change ownership of the file at the given path.
- * - ::lchmod:: Changes permissions of the last symbolic link in the given path.
- * - ::lchown:: Change ownership of the last symbolic in the given path.
- * - ::lutime:: For each given file path, sets the access time and modification time
- * of the last symbolic link in the path.
- * - ::rename:: Moves the file at one given path to another given path.
- * - ::utime:: Sets the access time and modification time of each file
- * at the given paths.
- * - #flock:: Locks or unlocks +self+.
+ * - ::chmod: Changes permissions of the file at the given path.
+ * - ::chown: Change ownership of the file at the given path.
+ * - ::lchmod: Changes permissions of the last symbolic link in the given path.
+ * - ::lchown: Change ownership of the last symbolic in the given path.
+ * - ::lutime: For each given file path, sets the access time and modification time
+ * of the last symbolic link in the path.
+ * - ::rename: Moves the file at one given path to another given path.
+ * - ::utime: Sets the access time and modification time of each file
+ * at the given paths.
+ * - #flock: Locks or unlocks +self+.
*
* === Other
*
- * - ::truncate:: Truncates the file at the given file path to the given size.
- * - ::unlink (aliased as ::delete):: Deletes the file for each given file path.
- * - #truncate:: Truncates +self+ to the given size.
+ * - ::truncate: Truncates the file at the given file path to the given size.
+ * - ::unlink (aliased as ::delete): Deletes the file for each given file path.
+ * - #truncate: Truncates +self+ to the given size.
*
*/
void
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");
@@ -6676,7 +7331,6 @@ Init_File(void)
define_filetest_function("directory?", rb_file_directory_p, 1);
define_filetest_function("exist?", rb_file_exist_p, 1);
- define_filetest_function("exists?", rb_file_exists_p, 1);
define_filetest_function("readable?", rb_file_readable_p, 1);
define_filetest_function("readable_real?", rb_file_readable_real_p, 1);
define_filetest_function("world_readable?", rb_file_world_readable_p, 1);
@@ -6766,7 +7420,7 @@ Init_File(void)
rb_define_method(rb_cFile, "mtime", rb_file_mtime, 0);
rb_define_method(rb_cFile, "ctime", rb_file_ctime, 0);
rb_define_method(rb_cFile, "birthtime", rb_file_birthtime, 0);
- rb_define_method(rb_cFile, "size", rb_file_size, 0);
+ rb_define_method(rb_cFile, "size", file_size, 0);
rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1);
rb_define_method(rb_cFile, "chown", rb_file_chown, 2);
@@ -6866,8 +7520,6 @@ Init_File(void)
/* Name of the null device */
rb_define_const(rb_mFConst, "NULL", rb_fstring_cstr(ruby_null_device));
- rb_define_method(rb_cFile, "path", rb_file_path, 0);
- rb_define_method(rb_cFile, "to_path", rb_file_path, 0);
rb_define_global_function("test", rb_f_test, -1);
rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject);
diff --git a/gc.c b/gc.c
index d37f7360fc..919d57989a 100644
--- a/gc.c
+++ b/gc.c
@@ -28,7 +28,12 @@
#include <sys/mman.h>
#endif
-#include <setjmp.h>
+#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
+# include "wasm/setjmp.h"
+# include "wasm/machine.h"
+#else
+# include <setjmp.h>
+#endif
#include <stdarg.h>
#include <stdio.h>
@@ -82,6 +87,11 @@
#include <emscripten.h>
#endif
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+# include <mach/task.h>
+# include <mach/mach_init.h>
+# include <mach/mach_port.h>
+#endif
#undef LIST_HEAD /* ccan/list conflicts with BSD-origin sys/queue.h. */
#include "constant.h"
@@ -128,11 +138,16 @@
#include "ractor_core.h"
#include "builtin.h"
+#include "shape.h"
#define rb_setjmp(env) RUBY_SETJMP(env)
#define rb_jmp_buf rb_jmpbuf_t
#undef rb_data_object_wrap
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
static inline struct rbimpl_size_mul_overflow_tag
size_add_overflow(size_t x, size_t y)
{
@@ -193,7 +208,7 @@ size_mul_or_raise(size_t x, size_t y, VALUE exc)
"integer overflow: %"PRIuSIZE
" * %"PRIuSIZE
" > %"PRIuSIZE,
- x, y, SIZE_MAX);
+ x, y, (size_t)SIZE_MAX);
}
}
@@ -220,7 +235,7 @@ size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc)
" * %"PRIuSIZE
" + %"PRIuSIZE
" > %"PRIuSIZE,
- x, y, z, SIZE_MAX);
+ x, y, z, (size_t)SIZE_MAX);
}
}
@@ -248,7 +263,7 @@ size_mul_add_mul_or_raise(size_t x, size_t y, size_t z, size_t w, VALUE exc)
" + %"PRIdSIZE
" * %"PRIdSIZE
" > %"PRIdSIZE,
- x, y, z, w, SIZE_MAX);
+ x, y, z, w, (size_t)SIZE_MAX);
}
}
@@ -555,93 +570,83 @@ typedef struct gc_profile_record {
#endif
} gc_profile_record;
-#define FL_FROM_FREELIST FL_USER0
-#define FL_FROM_PAYLOAD FL_USER0
-
struct RMoved {
VALUE flags;
VALUE dummy;
VALUE destination;
+ shape_id_t original_shape_id;
};
#define RMOVED(obj) ((struct RMoved *)(obj))
-#if (SIZEOF_DOUBLE > SIZEOF_VALUE) && (defined(_MSC_VER) || defined(__CYGWIN__))
-#pragma pack(push, 4) /* == SIZEOF_VALUE: magic for reducing sizeof(RVALUE): 24 -> 20 */
-#endif
-
-struct RPayload {
- VALUE flags;
-};
-#define RPAYLOAD(obj) ((struct RPayload *)obj)
-static unsigned short
-RPAYLOAD_LEN(VALUE obj)
-{
- unsigned short len = (unsigned short)(RPAYLOAD(obj)->flags >> FL_USHIFT);
- return len;
-}
-
-static void
-RPAYLOAD_FLAGS_SET(VALUE obj, unsigned short len)
-{
- // as len is the only thing in the user bits, we can overwrite it every time
- RPAYLOAD(obj)->flags = T_PAYLOAD | (len << FL_USHIFT);
-}
-
typedef struct RVALUE {
union {
- struct {
- VALUE flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
- struct RPayload payload;
+ struct {
+ VALUE flags; /* always 0 for freed obj */
+ struct RVALUE *next;
+ } free;
struct RMoved moved;
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- struct RFloat flonum;
- struct RString string;
- struct RArray array;
- struct RRegexp regexp;
- struct RHash hash;
- struct RData data;
- struct RTypedData typeddata;
- struct RStruct rstruct;
- struct RBignum bignum;
- struct RFile file;
- struct RMatch match;
- struct RRational rational;
- struct RComplex complex;
+ struct RBasic basic;
+ struct RObject object;
+ struct RClass klass;
+ struct RFloat flonum;
+ struct RString string;
+ struct RArray array;
+ struct RRegexp regexp;
+ struct RHash hash;
+ struct RData data;
+ struct RTypedData typeddata;
+ struct RStruct rstruct;
+ struct RBignum bignum;
+ struct RFile file;
+ struct RMatch match;
+ struct RRational rational;
+ struct RComplex complex;
struct RSymbol symbol;
- union {
- rb_cref_t cref;
- struct vm_svar svar;
- struct vm_throw_data throw_data;
- struct vm_ifunc ifunc;
- struct MEMO memo;
- struct rb_method_entry_struct ment;
- const rb_iseq_t iseq;
- rb_env_t env;
- struct rb_imemo_tmpbuf_struct alloc;
- rb_ast_t ast;
- } imemo;
- struct {
- struct RBasic basic;
- VALUE v1;
- VALUE v2;
- VALUE v3;
- } values;
+ union {
+ rb_cref_t cref;
+ struct vm_svar svar;
+ struct vm_throw_data throw_data;
+ struct vm_ifunc ifunc;
+ struct MEMO memo;
+ struct rb_method_entry_struct ment;
+ const rb_iseq_t iseq;
+ rb_env_t env;
+ struct rb_imemo_tmpbuf_struct alloc;
+ rb_ast_t ast;
+ } imemo;
+ struct {
+ struct RBasic basic;
+ VALUE v1;
+ VALUE v2;
+ VALUE v3;
+ } values;
} as;
+
+ /* Start of RVALUE_OVERHEAD.
+ * Do not directly read these members from the RVALUE as they're located
+ * at the end of the slot (which may differ in size depending on the size
+ * pool). */
+#if RACTOR_CHECK_MODE
+ uint32_t _ractor_belonging_id;
+#endif
#if GC_DEBUG
const char *file;
int line;
#endif
} RVALUE;
-#if (SIZEOF_DOUBLE > SIZEOF_VALUE) && (defined(_MSC_VER) || defined(__CYGWIN__))
-#pragma pack(pop)
+#if RACTOR_CHECK_MODE
+# define RVALUE_OVERHEAD (sizeof(RVALUE) - offsetof(RVALUE, _ractor_belonging_id))
+#elif GC_DEBUG
+# define RVALUE_OVERHEAD (sizeof(RVALUE) - offsetof(RVALUE, file))
+#else
+# define RVALUE_OVERHEAD 0
#endif
+STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == (SIZEOF_VALUE * 5) + RVALUE_OVERHEAD);
+STATIC_ASSERT(alignof_rvalue, RUBY_ALIGNOF(RVALUE) == SIZEOF_VALUE);
+
typedef uintptr_t bits_t;
enum {
BITS_SIZE = sizeof(bits_t),
@@ -680,12 +685,15 @@ typedef struct mark_stack {
size_t unused_cache_size;
} mark_stack_t;
+#define SIZE_POOL_EDEN_HEAP(size_pool) (&(size_pool)->eden_heap)
+#define SIZE_POOL_TOMB_HEAP(size_pool) (&(size_pool)->tomb_heap)
+
typedef struct rb_heap_struct {
struct heap_page *free_pages;
- struct list_head pages;
+ struct ccan_list_head pages;
struct heap_page *sweeping_page; /* iterator for .pages */
struct heap_page *compact_cursor;
- RVALUE * compact_cursor_index;
+ uintptr_t compact_cursor_index;
#if GC_ENABLE_INCREMENTAL_MARK
struct heap_page *pooled_pages;
#endif
@@ -693,146 +701,170 @@ typedef struct rb_heap_struct {
size_t total_slots; /* total slot count (about total_pages * HEAP_PAGE_OBJ_LIMIT) */
} rb_heap_t;
+typedef struct rb_size_pool_struct {
+ short slot_size;
+
+ size_t allocatable_pages;
+
+ /* Basic statistics */
+ size_t total_allocated_pages;
+ size_t total_freed_pages;
+ size_t force_major_gc_count;
+
+#if USE_RVARGC
+ /* Sweeping statistics */
+ size_t freed_slots;
+ size_t empty_slots;
+#endif
+
+ rb_heap_t eden_heap;
+ rb_heap_t tomb_heap;
+} rb_size_pool_t;
+
enum gc_mode {
gc_mode_none,
gc_mode_marking,
- gc_mode_sweeping
+ gc_mode_sweeping,
+ gc_mode_compacting,
};
typedef struct rb_objspace {
struct {
- size_t limit;
- size_t increase;
+ size_t limit;
+ size_t increase;
#if MALLOC_ALLOCATED_SIZE
- size_t allocated_size;
- size_t allocations;
+ size_t allocated_size;
+ size_t allocations;
#endif
+
} malloc_params;
struct {
- unsigned int mode : 2;
- unsigned int immediate_sweep : 1;
- unsigned int dont_gc : 1;
- unsigned int dont_incremental : 1;
- unsigned int during_gc : 1;
+ unsigned int mode : 2;
+ unsigned int immediate_sweep : 1;
+ unsigned int dont_gc : 1;
+ unsigned int dont_incremental : 1;
+ unsigned int during_gc : 1;
unsigned int during_compacting : 1;
- unsigned int gc_stressful: 1;
- unsigned int has_hook: 1;
- unsigned int during_minor_gc : 1;
+ unsigned int gc_stressful: 1;
+ unsigned int has_hook: 1;
+ unsigned int during_minor_gc : 1;
#if GC_ENABLE_INCREMENTAL_MARK
- unsigned int during_incremental_marking : 1;
+ unsigned int during_incremental_marking : 1;
#endif
+ unsigned int measure_gc : 1;
} flags;
rb_event_flag_t hook_events;
size_t total_allocated_objects;
VALUE next_object_id;
- rb_heap_t eden_heap;
- rb_heap_t tomb_heap; /* heap for zombies and ghosts */
+ rb_size_pool_t size_pools[SIZE_POOL_COUNT];
struct {
- rb_atomic_t finalizing;
+ rb_atomic_t finalizing;
} atomic_flags;
mark_stack_t mark_stack;
size_t marked_slots;
struct {
- struct heap_page **sorted;
- size_t allocated_pages;
- size_t allocatable_pages;
- size_t sorted_length;
- RVALUE *range[2];
- size_t freeable_pages;
-
- /* final */
- size_t final_slots;
- VALUE deferred_final;
+ struct heap_page **sorted;
+ size_t allocated_pages;
+ size_t allocatable_pages;
+ size_t sorted_length;
+ uintptr_t range[2];
+ size_t freeable_pages;
+
+ /* final */
+ size_t final_slots;
+ VALUE deferred_final;
} heap_pages;
st_table *finalizer_table;
struct {
- int run;
- unsigned int latest_gc_info;
- gc_profile_record *records;
- gc_profile_record *current_record;
- size_t next_index;
- size_t size;
+ int run;
+ unsigned int latest_gc_info;
+ gc_profile_record *records;
+ gc_profile_record *current_record;
+ size_t next_index;
+ size_t size;
#if GC_PROFILE_MORE_DETAIL
- double prepare_time;
+ double prepare_time;
#endif
- double invoke_time;
+ double invoke_time;
- size_t minor_gc_count;
- size_t major_gc_count;
- size_t compact_count;
- size_t read_barrier_faults;
+ size_t minor_gc_count;
+ size_t major_gc_count;
+ size_t compact_count;
+ size_t read_barrier_faults;
#if RGENGC_PROFILE > 0
- size_t total_generated_normal_object_count;
- size_t total_generated_shady_object_count;
- size_t total_shade_operation_count;
- size_t total_promoted_count;
- size_t total_remembered_normal_object_count;
- size_t total_remembered_shady_object_count;
+ size_t total_generated_normal_object_count;
+ size_t total_generated_shady_object_count;
+ size_t total_shade_operation_count;
+ size_t total_promoted_count;
+ size_t total_remembered_normal_object_count;
+ size_t total_remembered_shady_object_count;
#if RGENGC_PROFILE >= 2
- size_t generated_normal_object_count_types[RUBY_T_MASK];
- size_t generated_shady_object_count_types[RUBY_T_MASK];
- size_t shade_operation_count_types[RUBY_T_MASK];
- size_t promoted_types[RUBY_T_MASK];
- size_t remembered_normal_object_count_types[RUBY_T_MASK];
- size_t remembered_shady_object_count_types[RUBY_T_MASK];
+ size_t generated_normal_object_count_types[RUBY_T_MASK];
+ size_t generated_shady_object_count_types[RUBY_T_MASK];
+ size_t shade_operation_count_types[RUBY_T_MASK];
+ size_t promoted_types[RUBY_T_MASK];
+ size_t remembered_normal_object_count_types[RUBY_T_MASK];
+ size_t remembered_shady_object_count_types[RUBY_T_MASK];
#endif
#endif /* RGENGC_PROFILE */
- /* temporary profiling space */
- double gc_sweep_start_time;
- size_t total_allocated_objects_at_gc_start;
- size_t heap_used_at_gc_start;
+ /* temporary profiling space */
+ double gc_sweep_start_time;
+ size_t total_allocated_objects_at_gc_start;
+ size_t heap_used_at_gc_start;
- /* basic statistics */
- size_t count;
- size_t total_freed_objects;
- size_t total_allocated_pages;
- size_t total_freed_pages;
+ /* basic statistics */
+ size_t count;
+ size_t total_freed_objects;
+ uint64_t total_time_ns;
+ struct timespec start_time;
} profile;
struct gc_list *global_list;
VALUE gc_stress_mode;
struct {
- VALUE parent_object;
- int need_major_gc;
- size_t last_major_gc;
- size_t uncollectible_wb_unprotected_objects;
- size_t uncollectible_wb_unprotected_objects_limit;
- size_t old_objects;
- size_t old_objects_limit;
+ VALUE parent_object;
+ int need_major_gc;
+ size_t last_major_gc;
+ size_t uncollectible_wb_unprotected_objects;
+ size_t uncollectible_wb_unprotected_objects_limit;
+ size_t old_objects;
+ size_t old_objects_limit;
#if RGENGC_ESTIMATE_OLDMALLOC
- size_t oldmalloc_increase;
- size_t oldmalloc_increase_limit;
+ size_t oldmalloc_increase;
+ size_t oldmalloc_increase_limit;
#endif
#if RGENGC_CHECK_MODE >= 2
- struct st_table *allrefs_table;
- size_t error_count;
+ struct st_table *allrefs_table;
+ size_t error_count;
#endif
} rgengc;
struct {
size_t considered_count_table[T_MASK];
size_t moved_count_table[T_MASK];
+ size_t moved_up_count_table[T_MASK];
+ size_t moved_down_count_table[T_MASK];
size_t total_moved;
} rcompactor;
#if GC_ENABLE_INCREMENTAL_MARK
struct {
- size_t pooled_slots;
- size_t step_slots;
+ size_t pooled_slots;
+ size_t step_slots;
} rincgc;
#endif
@@ -845,54 +877,89 @@ typedef struct rb_objspace {
} rb_objspace_t;
-/* default tiny heap size: 16KB */
-#define HEAP_PAGE_ALIGN_LOG 14
-#define CEILDIV(i, mod) (((i) + (mod) - 1)/(mod))
+#ifndef HEAP_PAGE_ALIGN_LOG
+/* default tiny heap size: 64KiB */
+#define HEAP_PAGE_ALIGN_LOG 16
+#endif
+
+#define BASE_SLOT_SIZE sizeof(RVALUE)
+
+#define CEILDIV(i, mod) roomof(i, mod)
enum {
HEAP_PAGE_ALIGN = (1UL << HEAP_PAGE_ALIGN_LOG),
HEAP_PAGE_ALIGN_MASK = (~(~0UL << HEAP_PAGE_ALIGN_LOG)),
HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN,
- HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header))/sizeof(struct RVALUE)),
- HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, sizeof(struct RVALUE)), BITS_BITLENGTH),
+ HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)) / BASE_SLOT_SIZE),
+ HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, BASE_SLOT_SIZE), BITS_BITLENGTH),
HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT),
- HEAP_PAGE_BITMAP_PLANES = 4 /* RGENGC: mark, unprotected, uncollectible, marking */
};
#define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG)
#define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN
-#ifdef HAVE_MMAP
-# if HAVE_CONST_PAGE_SIZE
-/* If we have the HEAP_PAGE and it is a constant, then we can directly use it. */
-static const bool USE_MMAP_ALIGNED_ALLOC = (PAGE_SIZE <= HEAP_PAGE_SIZE);
-# elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE)
-/* PAGE_SIZE <= HEAP_PAGE_SIZE */
-static const bool USE_MMAP_ALIGNED_ALLOC = true;
-# else
-/* Otherwise, fall back to determining if we can use mmap during runtime. */
-# define USE_MMAP_ALIGNED_ALLOC (use_mmap_aligned_alloc != false)
-
-static bool use_mmap_aligned_alloc;
-# endif
-#elif !defined(__MINGW32__) && !defined(_WIN32)
-static const bool USE_MMAP_ALIGNED_ALLOC = false;
+#if GC_ENABLE_INCREMENTAL_MARK && !defined(INCREMENTAL_MARK_STEP_ALLOCATIONS)
+# define INCREMENTAL_MARK_STEP_ALLOCATIONS 500
+#endif
+
+#undef INIT_HEAP_PAGE_ALLOC_USE_MMAP
+/* Must define either HEAP_PAGE_ALLOC_USE_MMAP or
+ * INIT_HEAP_PAGE_ALLOC_USE_MMAP. */
+
+#ifndef HAVE_MMAP
+/* We can't use mmap of course, if it is not available. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
+
+#elif defined(__wasm__)
+/* wasmtime does not have proper support for mmap.
+ * See https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-rationale.md#why-no-mmap-and-friends
+ */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
+
+#elif HAVE_CONST_PAGE_SIZE
+/* If we have the PAGE_SIZE and it is a constant, then we can directly use it. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = (PAGE_SIZE <= HEAP_PAGE_SIZE);
+
+#elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE)
+/* If we can use the maximum page size. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = true;
+
+#elif defined(PAGE_SIZE)
+/* If the PAGE_SIZE macro can be used dynamically. */
+# define INIT_HEAP_PAGE_ALLOC_USE_MMAP (PAGE_SIZE <= HEAP_PAGE_SIZE)
+
+#elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
+/* If we can use sysconf to determine the page size. */
+# define INIT_HEAP_PAGE_ALLOC_USE_MMAP (sysconf(_SC_PAGE_SIZE) <= HEAP_PAGE_SIZE)
+
+#else
+/* Otherwise we can't determine the system page size, so don't use mmap. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
+#endif
+
+#ifdef INIT_HEAP_PAGE_ALLOC_USE_MMAP
+/* We can determine the system page size at runtime. */
+# define HEAP_PAGE_ALLOC_USE_MMAP (heap_page_alloc_use_mmap != false)
+
+static bool heap_page_alloc_use_mmap;
#endif
struct heap_page {
+ short slot_size;
short total_slots;
short free_slots;
- short pinned_slots;
short final_slots;
struct {
- unsigned int before_sweep : 1;
- unsigned int has_remembered_objects : 1;
- unsigned int has_uncollectible_shady_objects : 1;
- unsigned int in_tomb : 1;
+ unsigned int before_sweep : 1;
+ unsigned int has_remembered_objects : 1;
+ unsigned int has_uncollectible_shady_objects : 1;
+ unsigned int in_tomb : 1;
} flags;
+ rb_size_pool_t *size_pool;
+
struct heap_page *free_next;
- RVALUE *start;
+ uintptr_t start;
RVALUE *freelist;
- struct list_node page_node;
+ struct ccan_list_node page_node;
bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT];
/* the following three bitmaps are cleared at the beginning of full GC */
@@ -904,11 +971,29 @@ struct heap_page {
bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT];
};
+/*
+ * When asan is enabled, this will prohibit writing to the freelist until it is unlocked
+ */
+static void
+asan_lock_freelist(struct heap_page *page)
+{
+ asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+}
+
+/*
+ * When asan is enabled, this will enable the ability to write to the freelist
+ */
+static void
+asan_unlock_freelist(struct heap_page *page)
+{
+ asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+}
+
#define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_PAGE_ALIGN_MASK)))
#define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header)
#define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page)
-#define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_PAGE_ALIGN_MASK)/sizeof(RVALUE))
+#define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_PAGE_ALIGN_MASK) / BASE_SLOT_SIZE)
#define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH )
#define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1))
#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p))
@@ -925,6 +1010,8 @@ struct heap_page {
#define GET_HEAP_WB_UNPROTECTED_BITS(x) (&GET_HEAP_PAGE(x)->wb_unprotected_bits[0])
#define GET_HEAP_MARKING_BITS(x) (&GET_HEAP_PAGE(x)->marking_bits[0])
+#define GC_SWEEP_PAGES_FREEABLE_PER_STEP 3
+
/* Aliases */
#define rb_objspace (*rb_objspace_of(GET_VM()))
#define rb_objspace_of(vm) ((vm)->objspace)
@@ -941,12 +1028,10 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
#define heap_pages_sorted_length objspace->heap_pages.sorted_length
#define heap_pages_lomem objspace->heap_pages.range[0]
#define heap_pages_himem objspace->heap_pages.range[1]
-#define heap_allocatable_pages objspace->heap_pages.allocatable_pages
#define heap_pages_freeable_pages objspace->heap_pages.freeable_pages
#define heap_pages_final_slots objspace->heap_pages.final_slots
#define heap_pages_deferred_final objspace->heap_pages.deferred_final
-#define heap_eden (&objspace->eden_heap)
-#define heap_tomb (&objspace->tomb_heap)
+#define size_pools objspace->size_pools
#define during_gc objspace->flags.during_gc
#define finalizing objspace->atomic_flags.finalizing
#define finalizer_table objspace->finalizer_table
@@ -979,14 +1064,100 @@ gc_mode_verify(enum gc_mode mode)
case gc_mode_none:
case gc_mode_marking:
case gc_mode_sweeping:
- break;
+ case gc_mode_compacting:
+ break;
default:
- rb_bug("gc_mode_verify: unreachable (%d)", (int)mode);
+ rb_bug("gc_mode_verify: unreachable (%d)", (int)mode);
}
#endif
return mode;
}
+static inline bool
+has_sweeping_pages(rb_objspace_t *objspace)
+{
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ if (SIZE_POOL_EDEN_HEAP(&size_pools[i])->sweeping_page) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static inline size_t
+heap_eden_total_pages(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ count += SIZE_POOL_EDEN_HEAP(&size_pools[i])->total_pages;
+ }
+ return count;
+}
+
+static inline size_t
+heap_eden_total_slots(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ count += SIZE_POOL_EDEN_HEAP(&size_pools[i])->total_slots;
+ }
+ return count;
+}
+
+static inline size_t
+heap_tomb_total_pages(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ count += SIZE_POOL_TOMB_HEAP(&size_pools[i])->total_pages;
+ }
+ return count;
+}
+
+static inline size_t
+heap_allocatable_pages(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ count += size_pools[i].allocatable_pages;
+ }
+ return count;
+}
+
+static inline size_t
+heap_allocatable_slots(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ int slot_size_multiple = size_pool->slot_size / BASE_SLOT_SIZE;
+ count += size_pool->allocatable_pages * HEAP_PAGE_OBJ_LIMIT / slot_size_multiple;
+ }
+ return count;
+}
+
+static inline size_t
+total_allocated_pages(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ count += size_pool->total_allocated_pages;
+ }
+ return count;
+}
+
+static inline size_t
+total_freed_pages(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ count += size_pool->total_freed_pages;
+ }
+ return count;
+}
+
#define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode)
#define gc_mode_set(objspace, mode) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(mode))
@@ -1003,8 +1174,10 @@ gc_mode_verify(enum gc_mode mode)
#else
#define will_be_incremental_marking(objspace) FALSE
#endif
-#define has_sweeping_pages(heap) ((heap)->sweeping_page != 0)
-#define is_lazy_sweeping(heap) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(heap))
+#if GC_ENABLE_INCREMENTAL_MARK
+#define GC_INCREMENTAL_SWEEP_SLOT_COUNT 2048
+#endif
+#define is_lazy_sweeping(objspace) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(objspace))
#if SIZEOF_LONG == SIZEOF_VOIDP
# define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)
@@ -1074,16 +1247,19 @@ static inline void gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, u
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_finish(rb_objspace_t *objspace);
static void gc_marks_rest(rb_objspace_t *objspace);
-static void gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap);
+static void gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap);
static void gc_sweep(rb_objspace_t *objspace);
static void gc_sweep_start(rb_objspace_t *objspace);
+#if USE_RVARGC
+static void gc_sweep_finish_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool);
+#endif
static void gc_sweep_finish(rb_objspace_t *objspace);
-static int gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap);
+static int gc_sweep_step(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap);
static void gc_sweep_rest(rb_objspace_t *objspace);
-static void gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap);
+static void gc_sweep_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap);
static inline void gc_mark(rb_objspace_t *objspace, VALUE ptr);
static inline void gc_pin(rb_objspace_t *objspace, VALUE ptr);
@@ -1124,8 +1300,8 @@ static inline void gc_prof_set_malloc_info(rb_objspace_t *);
static inline void gc_prof_set_heap_info(rb_objspace_t *);
#define TYPED_UPDATE_IF_MOVED(_objspace, _type, _thing) do { \
- if (gc_object_moved_p(_objspace, (VALUE)_thing)) { \
- *((_type *)(&_thing)) = (_type)RMOVED((_thing))->destination; \
+ if (gc_object_moved_p((_objspace), (VALUE)(_thing))) { \
+ *(_type *)&(_thing) = (_type)RMOVED(_thing)->destination; \
} \
} while (0)
@@ -1158,7 +1334,7 @@ static const char *obj_type_name(VALUE obj);
/* the following code is only for internal tuning. */
/* Source code to use RDTSC is quoted and modified from
- * http://www.mcs.anl.gov/~kazutomo/rdtsc.html
+ * https://www.mcs.anl.gov/~kazutomo/rdtsc.html
* written by Kazutomo Yoshii <kazutomo@mcs.anl.gov>
*/
@@ -1196,6 +1372,27 @@ tick(void)
return val;
}
+/* Implementation for macOS PPC by @nobu
+ * See: https://github.com/ruby/ruby/pull/5975#discussion_r890045558
+ */
+#elif defined(__POWERPC__) && defined(__APPLE__)
+typedef unsigned long long tick_t;
+#define PRItick "llu"
+
+static __inline__ tick_t
+tick(void)
+{
+ unsigned long int upper, lower, tmp;
+ # define mftbu(r) __asm__ volatile("mftbu %0" : "=r"(r))
+ # define mftb(r) __asm__ volatile("mftb %0" : "=r"(r))
+ do {
+ mftbu(upper);
+ mftb(lower);
+ mftbu(tmp);
+ } while (tmp != upper);
+ return ((tick_t)upper << 32) | lower;
+}
+
#elif defined(__aarch64__) && defined(__GNUC__)
typedef unsigned long tick_t;
#define PRItick "lu"
@@ -1256,6 +1453,29 @@ 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;
+}
+
+static inline void *
+asan_poison_object_restore(VALUE obj, void *ptr)
+{
+ if (ptr) {
+ asan_poison_object(obj);
+ }
+ return NULL;
+}
+
+#define asan_unpoisoning_object(obj) \
+ for (void *poisoned = asan_unpoison_object_temporary(obj), \
+ *unpoisoning = &poisoned; /* flag to loop just once */ \
+ unpoisoning; \
+ unpoisoning = asan_poison_object_restore(obj, poisoned))
+
#define FL_CHECK2(name, x, pred) \
((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? \
(rb_bug(name": SPECIAL_CONST (%p)", (void *)(x)), 0) : (pred))
@@ -1290,36 +1510,6 @@ RVALUE_FLAGS_AGE(VALUE flags)
return (int)((flags & (FL_PROMOTED0 | FL_PROMOTED1)) >> RVALUE_AGE_SHIFT);
}
-#if USE_RVARGC
-static VALUE
-payload_or_self(VALUE obj)
-{
- struct heap_page *p = GET_HEAP_PAGE(obj);
- VALUE cur = (VALUE)p->start;
-
- while (cur != obj && GET_HEAP_PAGE(cur) == p) {
- VALUE p = cur;
- void *poisoned = asan_poisoned_object_p((VALUE)p);
- asan_unpoison_object((VALUE)p, false);
-
- if (BUILTIN_TYPE(cur) == T_PAYLOAD) {
- if (cur < obj && obj < cur + RPAYLOAD_LEN(cur) * sizeof(RVALUE)) {
- return cur;
- }
- cur += RPAYLOAD_LEN(cur) * sizeof(RVALUE);
- }
- else {
- cur += sizeof(RVALUE);
- }
- if (poisoned) {
- asan_poison_object((VALUE)p);
- }
- }
-
- return obj;
-}
-#endif
-
static int
check_rvalue_consistency_force(const VALUE obj, int terminate)
{
@@ -1335,13 +1525,16 @@ check_rvalue_consistency_force(const VALUE obj, int terminate)
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;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ ccan_list_for_each(&size_pool->tomb_heap.pages, page, page_node) {
+ if (page->start <= (uintptr_t)obj &&
+ (uintptr_t)obj < (page->start + (page->total_slots * size_pool->slot_size))) {
+ fprintf(stderr, "check_rvalue_consistency: %p is in a tomb_heap (%p).\n",
+ (void *)obj, (void *)page);
+ err++;
+ goto skip;
+ }
}
}
bp();
@@ -1444,8 +1637,7 @@ gc_object_moved_p(rb_objspace_t * objspace, VALUE obj)
return FALSE;
}
else {
- void *poisoned = asan_poisoned_object_p(obj);
- asan_unpoison_object(obj, false);
+ void *poisoned = asan_unpoison_object_temporary(obj);
int ret = BUILTIN_TYPE(obj) == T_MOVED;
/* Re-poison slot if it's not the one we want */
@@ -1527,18 +1719,6 @@ RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(rb_objspace_t *objspace, struct heap_page *pag
{
MARK_IN_BITMAP(&page->uncollectible_bits[0], obj);
objspace->rgengc.old_objects++;
-
-#if USE_RVARGC
- if (BUILTIN_TYPE(obj) == T_PAYLOAD) {
- int plen = RPAYLOAD_LEN(obj);
-
- for (int i = 1; i < plen; i++) {
- VALUE pbody = obj + i * sizeof(RVALUE);
- MARK_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(pbody), pbody);
- }
- objspace->rgengc.old_objects += plen - 1;
- }
-#endif
rb_transient_heap_promote(obj);
#if RGENGC_PROFILE >= 2
@@ -1570,14 +1750,14 @@ RVALUE_AGE_INC(rb_objspace_t *objspace, VALUE obj)
int age = RVALUE_FLAGS_AGE(flags);
if (RGENGC_CHECK_MODE && age == RVALUE_OLD_AGE) {
- rb_bug("RVALUE_AGE_INC: can not increment age of OLD object %s.", obj_info(obj));
+ rb_bug("RVALUE_AGE_INC: can not increment age of OLD object %s.", obj_info(obj));
}
age++;
RBASIC(obj)->flags = RVALUE_FLAGS_AGE_SET(flags, age);
if (age == RVALUE_OLD_AGE) {
- RVALUE_OLD_UNCOLLECTIBLE_SET(objspace, obj);
+ RVALUE_OLD_UNCOLLECTIBLE_SET(objspace, obj);
}
check_rvalue_consistency(obj);
}
@@ -1621,18 +1801,13 @@ RVALUE_DEMOTE(rb_objspace_t *objspace, VALUE obj)
GC_ASSERT(RVALUE_OLD_P(obj));
if (!is_incremental_marking(objspace) && RVALUE_REMEMBERED(obj)) {
- CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
}
RVALUE_DEMOTE_RAW(objspace, obj);
if (RVALUE_MARKED(obj)) {
- objspace->rgengc.old_objects--;
-#if USE_RVARGC
- if (BUILTIN_TYPE(obj) == T_PAYLOAD) {
- objspace->rgengc.old_objects -= RPAYLOAD_LEN(obj) - 1;
- }
-#endif
+ objspace->rgengc.old_objects--;
}
check_rvalue_consistency(obj);
@@ -1688,52 +1863,68 @@ rb_objspace_t *
rb_objspace_alloc(void)
{
rb_objspace_t *objspace = calloc1(sizeof(rb_objspace_t));
+ objspace->flags.measure_gc = 1;
malloc_limit = gc_params.malloc_limit_min;
- list_head_init(&objspace->eden_heap.pages);
- list_head_init(&objspace->tomb_heap.pages);
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+
+ size_pool->slot_size = (1 << i) * BASE_SLOT_SIZE;
+
+ ccan_list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages);
+ ccan_list_head_init(&SIZE_POOL_TOMB_HEAP(size_pool)->pages);
+ }
+
dont_gc_on();
return objspace;
}
static void free_stack_chunks(mark_stack_t *);
+static void mark_stack_free_cache(mark_stack_t *);
static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page);
void
rb_objspace_free(rb_objspace_t *objspace)
{
- if (is_lazy_sweeping(heap_eden))
- rb_bug("lazy sweeping underway when freeing object space");
+ if (is_lazy_sweeping(objspace))
+ rb_bug("lazy sweeping underway when freeing object space");
if (objspace->profile.records) {
- free(objspace->profile.records);
- objspace->profile.records = 0;
+ free(objspace->profile.records);
+ objspace->profile.records = 0;
}
if (global_list) {
- struct gc_list *list, *next;
- for (list = global_list; list; list = next) {
- next = list->next;
- xfree(list);
- }
+ struct gc_list *list, *next;
+ for (list = global_list; list; list = next) {
+ next = list->next;
+ xfree(list);
+ }
}
if (heap_pages_sorted) {
- size_t i;
- for (i = 0; i < heap_allocated_pages; ++i) {
- heap_page_free(objspace, heap_pages_sorted[i]);
- }
- free(heap_pages_sorted);
- heap_allocated_pages = 0;
- heap_pages_sorted_length = 0;
- heap_pages_lomem = 0;
- heap_pages_himem = 0;
-
- objspace->eden_heap.total_pages = 0;
- objspace->eden_heap.total_slots = 0;
+ size_t i;
+ for (i = 0; i < heap_allocated_pages; ++i) {
+ heap_page_free(objspace, heap_pages_sorted[i]);
+ }
+ free(heap_pages_sorted);
+ heap_allocated_pages = 0;
+ heap_pages_sorted_length = 0;
+ heap_pages_lomem = 0;
+ heap_pages_himem = 0;
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ SIZE_POOL_EDEN_HEAP(size_pool)->total_pages = 0;
+ SIZE_POOL_EDEN_HEAP(size_pool)->total_slots = 0;
+ }
}
st_free_table(objspace->id_to_obj_tbl);
st_free_table(objspace->obj_to_id_tbl);
+
free_stack_chunks(&objspace->mark_stack);
+ mark_stack_free_cache(&objspace->mark_stack);
+
free(objspace);
}
@@ -1747,15 +1938,15 @@ heap_pages_expand_sorted_to(rb_objspace_t *objspace, size_t next_length)
next_length, size);
if (heap_pages_sorted_length > 0) {
- sorted = (struct heap_page **)realloc(heap_pages_sorted, size);
- if (sorted) heap_pages_sorted = sorted;
+ sorted = (struct heap_page **)realloc(heap_pages_sorted, size);
+ if (sorted) heap_pages_sorted = sorted;
}
else {
- sorted = heap_pages_sorted = (struct heap_page **)malloc(size);
+ sorted = heap_pages_sorted = (struct heap_page **)malloc(size);
}
if (sorted == 0) {
- rb_memerror();
+ rb_memerror();
}
heap_pages_sorted_length = next_length;
@@ -1769,22 +1960,25 @@ heap_pages_expand_sorted(rb_objspace_t *objspace)
* however, if there are pages which do not have empty slots, then try to create new pages
* so that the additional allocatable_pages counts (heap_tomb->total_pages) are added.
*/
- size_t next_length = heap_allocatable_pages;
- next_length += heap_eden->total_pages;
- next_length += heap_tomb->total_pages;
+ size_t next_length = heap_allocatable_pages(objspace);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ next_length += SIZE_POOL_EDEN_HEAP(size_pool)->total_pages;
+ next_length += SIZE_POOL_TOMB_HEAP(size_pool)->total_pages;
+ }
if (next_length > heap_pages_sorted_length) {
- heap_pages_expand_sorted_to(objspace, next_length);
+ heap_pages_expand_sorted_to(objspace, next_length);
}
- GC_ASSERT(heap_allocatable_pages + heap_eden->total_pages <= heap_pages_sorted_length);
+ GC_ASSERT(heap_allocatable_pages(objspace) + heap_eden_total_pages(objspace) <= heap_pages_sorted_length);
GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
}
static void
-heap_allocatable_pages_set(rb_objspace_t *objspace, size_t s)
+size_pool_allocatable_pages_set(rb_objspace_t *objspace, rb_size_pool_t *size_pool, size_t s)
{
- heap_allocatable_pages = s;
+ size_pool->allocatable_pages = s;
heap_pages_expand_sorted(objspace);
}
@@ -1797,18 +1991,18 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj
asan_unpoison_object(obj, false);
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+ asan_unlock_freelist(page);
p->as.free.flags = 0;
p->as.free.next = page->freelist;
page->freelist = p;
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ asan_lock_freelist(page);
if (RGENGC_CHECK_MODE &&
/* obj should belong to page */
- !(&page->start[0] <= (RVALUE *)obj &&
- (RVALUE *)obj < &page->start[page->total_slots] &&
- obj % sizeof(RVALUE) == 0)) {
+ !(page->start <= (uintptr_t)obj &&
+ (uintptr_t)obj < ((uintptr_t)page->start + (page->total_slots * page->slot_size)) &&
+ obj % BASE_SLOT_SIZE == 0)) {
rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)p);
}
@@ -1819,23 +2013,23 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj
static inline void
heap_add_freepage(rb_heap_t *heap, struct heap_page *page)
{
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+ asan_unlock_freelist(page);
GC_ASSERT(page->free_slots != 0);
GC_ASSERT(page->freelist != NULL);
page->free_next = heap->free_pages;
heap->free_pages = page;
- RUBY_DEBUG_LOG("page:%p freelist:%p", page, page->freelist);
+ RUBY_DEBUG_LOG("page:%p freelist:%p", (void *)page, (void *)page->freelist);
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ asan_lock_freelist(page);
}
#if GC_ENABLE_INCREMENTAL_MARK
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);
+ asan_unlock_freelist(page);
GC_ASSERT(page->free_slots != 0);
GC_ASSERT(page->freelist != NULL);
@@ -1843,14 +2037,14 @@ heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *pa
heap->pooled_pages = page;
objspace->rincgc.pooled_slots += page->free_slots;
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ asan_lock_freelist(page);
}
#endif
static void
heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
{
- list_del(&page->page_node);
+ ccan_list_del(&page->page_node);
heap->total_pages--;
heap->total_slots -= page->total_slots;
}
@@ -1858,11 +2052,29 @@ heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *pag
static void rb_aligned_free(void *ptr, size_t size);
static void
+heap_page_body_free(struct heap_page_body *page_body)
+{
+ GC_ASSERT((uintptr_t)page_body % HEAP_PAGE_ALIGN == 0);
+
+ if (HEAP_PAGE_ALLOC_USE_MMAP) {
+#ifdef HAVE_MMAP
+ GC_ASSERT(HEAP_PAGE_SIZE % sysconf(_SC_PAGE_SIZE) == 0);
+ if (munmap(page_body, HEAP_PAGE_SIZE)) {
+ rb_bug("heap_page_body_free: munmap failed");
+ }
+#endif
+ }
+ else {
+ rb_aligned_free(page_body, HEAP_PAGE_SIZE);
+ }
+}
+
+static void
heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
{
heap_allocated_pages--;
- objspace->profile.total_freed_pages++;
- rb_aligned_free(GET_PAGE_BODY(page->start), HEAP_PAGE_SIZE);
+ page->size_pool->total_freed_pages++;
+ heap_page_body_free(GET_PAGE_BODY(page->start));
free(page);
}
@@ -1871,98 +2083,167 @@ heap_pages_free_unused_pages(rb_objspace_t *objspace)
{
size_t i, j;
- if (!list_empty(&heap_tomb->pages)) {
- for (i = j = 1; j < heap_allocated_pages; i++) {
- struct heap_page *page = heap_pages_sorted[i];
-
- if (page->flags.in_tomb && page->free_slots == page->total_slots) {
- heap_unlink_page(objspace, heap_tomb, page);
- heap_page_free(objspace, page);
- }
- else {
- if (i != j) {
- heap_pages_sorted[j] = page;
- }
- j++;
- }
- }
+ bool has_pages_in_tomb_heap = FALSE;
+ for (i = 0; i < SIZE_POOL_COUNT; i++) {
+ if (!ccan_list_empty(&SIZE_POOL_TOMB_HEAP(&size_pools[i])->pages)) {
+ has_pages_in_tomb_heap = TRUE;
+ break;
+ }
+ }
+
+ if (has_pages_in_tomb_heap) {
+ for (i = j = 1; j < heap_allocated_pages; i++) {
+ struct heap_page *page = heap_pages_sorted[i];
+
+ if (page->flags.in_tomb && page->free_slots == page->total_slots) {
+ heap_unlink_page(objspace, SIZE_POOL_TOMB_HEAP(page->size_pool), page);
+ heap_page_free(objspace, page);
+ }
+ else {
+ if (i != j) {
+ heap_pages_sorted[j] = page;
+ }
+ j++;
+ }
+ }
struct heap_page *hipage = heap_pages_sorted[heap_allocated_pages - 1];
- RVALUE *himem = hipage->start + hipage->total_slots;
+ uintptr_t himem = (uintptr_t)hipage->start + (hipage->total_slots * hipage->slot_size);
GC_ASSERT(himem <= heap_pages_himem);
heap_pages_himem = himem;
- GC_ASSERT(j == heap_allocated_pages);
+ GC_ASSERT(j == heap_allocated_pages);
+ }
+}
+
+static struct heap_page_body *
+heap_page_body_allocate(void)
+{
+ struct heap_page_body *page_body;
+
+ if (HEAP_PAGE_ALLOC_USE_MMAP) {
+#ifdef HAVE_MMAP
+ GC_ASSERT(HEAP_PAGE_ALIGN % sysconf(_SC_PAGE_SIZE) == 0);
+
+ char *ptr = mmap(NULL, HEAP_PAGE_ALIGN + HEAP_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ptr == MAP_FAILED) {
+ return NULL;
+ }
+
+ char *aligned = ptr + HEAP_PAGE_ALIGN;
+ aligned -= ((VALUE)aligned & (HEAP_PAGE_ALIGN - 1));
+ GC_ASSERT(aligned > ptr);
+ GC_ASSERT(aligned <= ptr + HEAP_PAGE_ALIGN);
+
+ size_t start_out_of_range_size = aligned - ptr;
+ GC_ASSERT(start_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0);
+ if (start_out_of_range_size > 0) {
+ if (munmap(ptr, start_out_of_range_size)) {
+ rb_bug("heap_page_body_allocate: munmap failed for start");
+ }
+ }
+
+ size_t end_out_of_range_size = HEAP_PAGE_ALIGN - start_out_of_range_size;
+ GC_ASSERT(end_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0);
+ if (end_out_of_range_size > 0) {
+ if (munmap(aligned + HEAP_PAGE_SIZE, end_out_of_range_size)) {
+ rb_bug("heap_page_body_allocate: munmap failed for end");
+ }
+ }
+
+ page_body = (struct heap_page_body *)aligned;
+#endif
}
+ else {
+ page_body = rb_aligned_malloc(HEAP_PAGE_ALIGN, HEAP_PAGE_SIZE);
+ }
+
+ GC_ASSERT((uintptr_t)page_body % HEAP_PAGE_ALIGN == 0);
+
+ return page_body;
}
static struct heap_page *
-heap_page_allocate(rb_objspace_t *objspace)
+heap_page_allocate(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
{
- RVALUE *start, *end, *p;
+ uintptr_t start, end, p;
struct heap_page *page;
- struct heap_page_body *page_body = 0;
- size_t hi, lo, mid;
- int limit = HEAP_PAGE_OBJ_LIMIT;
+ uintptr_t hi, lo, mid;
+ size_t stride = size_pool->slot_size;
+ unsigned int limit = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)))/(int)stride;
/* assign heap_page body (contains heap_page_header and RVALUEs) */
- page_body = (struct heap_page_body *)rb_aligned_malloc(HEAP_PAGE_ALIGN, HEAP_PAGE_SIZE);
+ struct heap_page_body *page_body = heap_page_body_allocate();
if (page_body == 0) {
- rb_memerror();
+ rb_memerror();
}
/* assign heap_page entry */
page = calloc1(sizeof(struct heap_page));
if (page == 0) {
- rb_aligned_free(page_body, HEAP_PAGE_SIZE);
- rb_memerror();
+ heap_page_body_free(page_body);
+ rb_memerror();
}
/* adjust obj_limit (object number available in this page) */
- start = (RVALUE*)((VALUE)page_body + sizeof(struct heap_page_header));
- if ((VALUE)start % sizeof(RVALUE) != 0) {
- int delta = (int)(sizeof(RVALUE) - ((VALUE)start % sizeof(RVALUE)));
- start = (RVALUE*)((VALUE)start + delta);
- limit = (HEAP_PAGE_SIZE - (int)((VALUE)start - (VALUE)page_body))/(int)sizeof(RVALUE);
+ start = (uintptr_t)((VALUE)page_body + sizeof(struct heap_page_header));
+
+ if (start % BASE_SLOT_SIZE != 0) {
+ int delta = BASE_SLOT_SIZE - (start % BASE_SLOT_SIZE);
+ start = start + delta;
+ GC_ASSERT(NUM_IN_PAGE(start) == 0 || NUM_IN_PAGE(start) == 1);
+
+ /* Find a num in page that is evenly divisible by `stride`.
+ * This is to ensure that objects are aligned with bit planes.
+ * In other words, ensure there are an even number of objects
+ * per bit plane. */
+ if (NUM_IN_PAGE(start) == 1) {
+ start += stride - BASE_SLOT_SIZE;
+ }
+
+ GC_ASSERT(NUM_IN_PAGE(start) * BASE_SLOT_SIZE % stride == 0);
+
+ limit = (HEAP_PAGE_SIZE - (int)(start - (uintptr_t)page_body))/(int)stride;
}
- end = start + limit;
+ end = start + (limit * (int)stride);
/* setup heap_pages_sorted */
lo = 0;
- hi = heap_allocated_pages;
+ hi = (uintptr_t)heap_allocated_pages;
while (lo < hi) {
- struct heap_page *mid_page;
+ struct heap_page *mid_page;
- mid = (lo + hi) / 2;
- mid_page = heap_pages_sorted[mid];
- if (mid_page->start < start) {
- lo = mid + 1;
- }
- else if (mid_page->start > start) {
- hi = mid;
- }
- else {
- rb_bug("same heap page is allocated: %p at %"PRIuVALUE, (void *)page_body, (VALUE)mid);
- }
+ mid = (lo + hi) / 2;
+ mid_page = heap_pages_sorted[mid];
+ if ((uintptr_t)mid_page->start < start) {
+ lo = mid + 1;
+ }
+ else if ((uintptr_t)mid_page->start > start) {
+ hi = mid;
+ }
+ else {
+ rb_bug("same heap page is allocated: %p at %"PRIuVALUE, (void *)page_body, (VALUE)mid);
+ }
}
- if (hi < heap_allocated_pages) {
- MEMMOVE(&heap_pages_sorted[hi+1], &heap_pages_sorted[hi], struct heap_page_header*, heap_allocated_pages - hi);
+ if (hi < (uintptr_t)heap_allocated_pages) {
+ MEMMOVE(&heap_pages_sorted[hi+1], &heap_pages_sorted[hi], struct heap_page_header*, heap_allocated_pages - hi);
}
heap_pages_sorted[hi] = page;
heap_allocated_pages++;
- GC_ASSERT(heap_eden->total_pages + heap_allocatable_pages <= heap_pages_sorted_length);
- GC_ASSERT(heap_eden->total_pages + heap_tomb->total_pages == heap_allocated_pages - 1);
+ GC_ASSERT(heap_eden_total_pages(objspace) + heap_allocatable_pages(objspace) <= heap_pages_sorted_length);
+ GC_ASSERT(heap_eden_total_pages(objspace) + heap_tomb_total_pages(objspace) == heap_allocated_pages - 1);
GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
- objspace->profile.total_allocated_pages++;
+ size_pool->total_allocated_pages++;
if (heap_allocated_pages > heap_pages_sorted_length) {
- rb_bug("heap_page_allocate: allocated(%"PRIdSIZE") > sorted(%"PRIdSIZE")",
- heap_allocated_pages, heap_pages_sorted_length);
+ rb_bug("heap_page_allocate: allocated(%"PRIdSIZE") > sorted(%"PRIdSIZE")",
+ heap_allocated_pages, heap_pages_sorted_length);
}
if (heap_pages_lomem == 0 || heap_pages_lomem > start) heap_pages_lomem = start;
@@ -1970,124 +2251,129 @@ heap_page_allocate(rb_objspace_t *objspace)
page->start = start;
page->total_slots = limit;
+ page->slot_size = size_pool->slot_size;
+ page->size_pool = size_pool;
page_body->header.page = page;
- for (p = start; p != end; p++) {
- gc_report(3, objspace, "assign_heap_page: %p is added to freelist\n", (void *)p);
- heap_page_add_freeobj(objspace, page, (VALUE)p);
+ for (p = start; p != end; p += stride) {
+ gc_report(3, objspace, "assign_heap_page: %p is added to freelist\n", (void *)p);
+ heap_page_add_freeobj(objspace, page, (VALUE)p);
}
page->free_slots = limit;
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ asan_lock_freelist(page);
return page;
}
static struct heap_page *
-heap_page_resurrect(rb_objspace_t *objspace)
+heap_page_resurrect(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
{
struct heap_page *page = 0, *next;
- list_for_each_safe(&heap_tomb->pages, page, next, page_node) {
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
- if (page->freelist != NULL) {
- heap_unlink_page(objspace, heap_tomb, page);
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
- return page;
- }
+ ccan_list_for_each_safe(&SIZE_POOL_TOMB_HEAP(size_pool)->pages, page, next, page_node) {
+ asan_unlock_freelist(page);
+ if (page->freelist != NULL) {
+ heap_unlink_page(objspace, &size_pool->tomb_heap, page);
+ asan_lock_freelist(page);
+ return page;
+ }
}
return NULL;
}
static struct heap_page *
-heap_page_create(rb_objspace_t *objspace)
+heap_page_create(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
{
struct heap_page *page;
const char *method = "recycle";
- heap_allocatable_pages--;
+ size_pool->allocatable_pages--;
- page = heap_page_resurrect(objspace);
+ page = heap_page_resurrect(objspace, size_pool);
if (page == NULL) {
- page = heap_page_allocate(objspace);
- method = "allocate";
+ page = heap_page_allocate(objspace, size_pool);
+ method = "allocate";
}
if (0) fprintf(stderr, "heap_page_create: %s - %p, "
"heap_allocated_pages: %"PRIdSIZE", "
"heap_allocated_pages: %"PRIdSIZE", "
"tomb->total_pages: %"PRIdSIZE"\n",
- method, (void *)page, heap_pages_sorted_length, heap_allocated_pages, heap_tomb->total_pages);
+ method, (void *)page, heap_pages_sorted_length, heap_allocated_pages, SIZE_POOL_TOMB_HEAP(size_pool)->total_pages);
return page;
}
static void
-heap_add_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
+heap_add_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, struct heap_page *page)
{
/* 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_tail(&heap->pages, &page->page_node);
+ GC_ASSERT(!(heap == SIZE_POOL_EDEN_HEAP(size_pool) && heap->sweeping_page));
+ page->flags.in_tomb = (heap == SIZE_POOL_TOMB_HEAP(size_pool));
+ ccan_list_add_tail(&heap->pages, &page->page_node);
heap->total_pages++;
heap->total_slots += page->total_slots;
}
static void
-heap_assign_page(rb_objspace_t *objspace, rb_heap_t *heap)
+heap_assign_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
- struct heap_page *page = heap_page_create(objspace);
- heap_add_page(objspace, heap, page);
+ struct heap_page *page = heap_page_create(objspace, size_pool);
+ heap_add_page(objspace, size_pool, heap, page);
heap_add_freepage(heap, page);
}
static void
-heap_add_pages(rb_objspace_t *objspace, rb_heap_t *heap, size_t add)
+heap_add_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, size_t add)
{
size_t i;
- heap_allocatable_pages_set(objspace, add);
+ size_pool_allocatable_pages_set(objspace, size_pool, add);
for (i = 0; i < add; i++) {
- heap_assign_page(objspace, heap);
+ heap_assign_page(objspace, size_pool, heap);
}
- GC_ASSERT(heap_allocatable_pages == 0);
+ GC_ASSERT(size_pool->allocatable_pages == 0);
}
static size_t
-heap_extend_pages(rb_objspace_t *objspace, size_t free_slots, size_t total_slots)
+heap_extend_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, size_t free_slots, size_t total_slots, size_t used)
{
double goal_ratio = gc_params.heap_free_slots_goal_ratio;
- size_t used = heap_allocated_pages + heap_allocatable_pages;
size_t next_used;
if (goal_ratio == 0.0) {
- next_used = (size_t)(used * gc_params.growth_factor);
+ next_used = (size_t)(used * gc_params.growth_factor);
+ }
+ else if (total_slots == 0) {
+ int multiple = size_pool->slot_size / BASE_SLOT_SIZE;
+ next_used = (gc_params.heap_init_slots * multiple) / HEAP_PAGE_OBJ_LIMIT;
}
else {
- /* Find `f' where free_slots = f * total_slots * goal_ratio
- * => f = (total_slots - free_slots) / ((1 - goal_ratio) * total_slots)
- */
- double f = (double)(total_slots - free_slots) / ((1 - goal_ratio) * total_slots);
+ /* Find `f' where free_slots = f * total_slots * goal_ratio
+ * => f = (total_slots - free_slots) / ((1 - goal_ratio) * total_slots)
+ */
+ double f = (double)(total_slots - free_slots) / ((1 - goal_ratio) * total_slots);
- if (f > gc_params.growth_factor) f = gc_params.growth_factor;
- if (f < 1.0) f = 1.1;
+ if (f > gc_params.growth_factor) f = gc_params.growth_factor;
+ if (f < 1.0) f = 1.1;
- next_used = (size_t)(f * used);
+ next_used = (size_t)(f * used);
- if (0) {
- fprintf(stderr,
- "free_slots(%8"PRIuSIZE")/total_slots(%8"PRIuSIZE")=%1.2f,"
- " G(%1.2f), f(%1.2f),"
- " used(%8"PRIuSIZE") => next_used(%8"PRIuSIZE")\n",
- free_slots, total_slots, free_slots/(double)total_slots,
- goal_ratio, f, used, next_used);
- }
+ if (0) {
+ fprintf(stderr,
+ "free_slots(%8"PRIuSIZE")/total_slots(%8"PRIuSIZE")=%1.2f,"
+ " G(%1.2f), f(%1.2f),"
+ " used(%8"PRIuSIZE") => next_used(%8"PRIuSIZE")\n",
+ free_slots, total_slots, free_slots/(double)total_slots,
+ goal_ratio, f, used, next_used);
+ }
}
if (gc_params.growth_max_slots > 0) {
- size_t max_used = (size_t)(used + gc_params.growth_max_slots/HEAP_PAGE_OBJ_LIMIT);
- if (next_used > max_used) next_used = max_used;
+ size_t max_used = (size_t)(used + gc_params.growth_max_slots/HEAP_PAGE_OBJ_LIMIT);
+ if (next_used > max_used) next_used = max_used;
}
size_t extend_page_count = next_used - used;
@@ -2098,39 +2384,83 @@ heap_extend_pages(rb_objspace_t *objspace, size_t free_slots, size_t total_slots
}
static int
-heap_increment(rb_objspace_t *objspace, rb_heap_t *heap)
+heap_increment(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
- if (heap_allocatable_pages > 0) {
- gc_report(1, objspace, "heap_increment: heap_pages_sorted_length: %"PRIdSIZE", "
+ if (size_pool->allocatable_pages > 0) {
+ gc_report(1, objspace, "heap_increment: heap_pages_sorted_length: %"PRIdSIZE", "
"heap_pages_inc: %"PRIdSIZE", heap->total_pages: %"PRIdSIZE"\n",
- heap_pages_sorted_length, heap_allocatable_pages, heap->total_pages);
+ heap_pages_sorted_length, size_pool->allocatable_pages, heap->total_pages);
- GC_ASSERT(heap_allocatable_pages + heap_eden->total_pages <= heap_pages_sorted_length);
- GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
+ GC_ASSERT(heap_allocatable_pages(objspace) + heap_eden_total_pages(objspace) <= heap_pages_sorted_length);
+ GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
- heap_assign_page(objspace, heap);
- return TRUE;
+ heap_assign_page(objspace, size_pool, heap);
+ return TRUE;
}
return FALSE;
}
static void
-heap_prepare(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
- GC_ASSERT(heap->free_pages == NULL);
-
- if (is_lazy_sweeping(heap)) {
- gc_sweep_continue(objspace, heap);
+ /* Continue marking if in incremental marking. */
+ if (heap->free_pages == NULL && is_incremental_marking(objspace)) {
+ gc_marks_continue(objspace, size_pool, heap);
}
- else if (is_incremental_marking(objspace)) {
- gc_marks_continue(objspace, heap);
+
+ /* Continue sweeping if in lazy sweeping or the previous incremental
+ * marking finished and did not yield a free page. */
+ if (heap->free_pages == NULL && is_lazy_sweeping(objspace)) {
+ gc_sweep_continue(objspace, size_pool, heap);
}
+}
+
+static void
+heap_prepare(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
+{
+ GC_ASSERT(heap->free_pages == NULL);
+ /* Continue incremental marking or lazy sweeping, if in any of those steps. */
+ gc_continue(objspace, size_pool, heap);
+
+ /* If we still don't have a free page and not allowed to create a new page,
+ * we should start a new GC cycle. */
if (heap->free_pages == NULL &&
- (will_be_incremental_marking(objspace) || heap_increment(objspace, heap) == FALSE) &&
- gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
- rb_memerror();
+ (will_be_incremental_marking(objspace) ||
+ (heap_increment(objspace, size_pool, heap) == FALSE))) {
+ if (gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
+ rb_memerror();
+ }
+ else {
+ /* Do steps of incremental marking or lazy sweeping if the GC run permits. */
+ gc_continue(objspace, size_pool, heap);
+
+ /* If we're not incremental marking (e.g. a minor GC) or finished
+ * sweeping and still don't have a free page, then
+ * gc_sweep_finish_size_pool should allow us to create a new page. */
+ if (heap->free_pages == NULL && !heap_increment(objspace, size_pool, heap)) {
+ if (objspace->rgengc.need_major_gc == GPR_FLAG_NONE) {
+ rb_bug("cannot create a new page after GC");
+ }
+ else { // Major GC is required, which will allow us to create new page
+ if (gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
+ rb_memerror();
+ }
+ else {
+ /* Do steps of incremental marking or lazy sweeping. */
+ gc_continue(objspace, size_pool, heap);
+
+ if (heap->free_pages == NULL &&
+ !heap_increment(objspace, size_pool, heap)) {
+ rb_bug("cannot create a new page after major GC");
+ }
+ }
+ }
+ }
+ }
}
+
+ GC_ASSERT(heap->free_pages != NULL);
}
void
@@ -2144,6 +2474,7 @@ rb_objspace_set_event_hook(const rb_event_flag_t event)
static void
gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data)
{
+ if (UNLIKELY(!ec->cfp)) return;
const VALUE *pc = ec->cfp->pc;
if (pc && VM_FRAME_RUBYFRAME_P(ec->cfp)) {
/* increment PC because source line is calculated with PC-1 */
@@ -2159,7 +2490,7 @@ gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb
#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)); \
+ gc_event_hook_body(GET_EC(), (objspace), (event), (data)); \
} \
} while (0)
@@ -2255,155 +2586,75 @@ newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace,
return obj;
}
-static unsigned long
-rvargc_slot_count(size_t size)
+size_t
+rb_gc_obj_slot_size(VALUE obj)
{
- // roomof == ceiling division, so we don't have to do div then mod
- return roomof(size + sizeof(struct RPayload), sizeof(RVALUE));
+ return GET_HEAP_PAGE(obj)->slot_size - RVALUE_OVERHEAD;
}
-#if USE_RVARGC
-static RVALUE *
-rvargc_find_contiguous_slots(int slots, RVALUE *freelist)
-{
- RVALUE *cursor = freelist;
- RVALUE *previous_region = NULL;
-
- while (cursor) {
- int i;
- RVALUE *search = cursor;
- for (i = 0; i < (slots - 1); i++) {
-
- // Peek ahead to see if the region is contiguous
- if (search->as.free.next == (search - 1)) {
- search = search->as.free.next;
- }
- else {
- // Next slot is not contiguous
- if (search->as.free.next) {
- cursor = search->as.free.next;
- previous_region = search;
-
- break;
- }
- else {
- // Hit the end of the free list
- return NULL;
- }
- }
- }
-
- if (i == slots - 1) {
- if (previous_region) {
- previous_region->as.free.next = search->as.free.next;
- search->as.free.next = freelist;
- }
- return search;
- }
- }
- rb_bug("rvargc_find_contiguous_slots: unreachable");
-}
-#endif
-
-static inline void heap_add_freepage(rb_heap_t *heap, struct heap_page *page);
-static struct heap_page * heap_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap);
-static inline void ractor_set_cache(rb_ractor_t *cr, struct heap_page *page);
-
-#if USE_RVARGC
-static inline void *
-rvargc_find_region(size_t size, rb_ractor_t *cr, RVALUE *freelist)
+static inline size_t
+size_pool_slot_size(unsigned char pool_id)
{
- // maintain master behaviour when we only need one slot
- if (size == sizeof(RVALUE))
- return freelist;
+ GC_ASSERT(pool_id < SIZE_POOL_COUNT);
- if (!freelist) return freelist;
+ size_t slot_size = (1 << pool_id) * BASE_SLOT_SIZE;
+#if RGENGC_CHECK_MODE
rb_objspace_t *objspace = &rb_objspace;
- int slots = (int)rvargc_slot_count(size);
- RVALUE * p = rvargc_find_contiguous_slots(slots, freelist);
-
- // We found a contiguous space on the freelist stored in the ractor cache
- if (p) {
- struct heap_page *page = GET_HEAP_PAGE(p);
-
- page->free_slots -= slots;
- asan_unpoison_memory_region(p, sizeof(RVALUE) * slots, false);
- return p;
- }
- else {
- struct heap_page *search_page;
- heap_allocatable_pages_set(objspace, heap_allocatable_pages + 1);
-
- while (!p) {
- // search_page is the page we're going to search for contiguous slots
- search_page = heap_next_freepage(objspace, heap_eden);
- p = rvargc_find_contiguous_slots(slots, search_page->freelist);
-
- if (p) {
- // Remove the region from the freelist
- search_page->freelist = p->as.free.next;
- search_page->free_slots -= slots;
-
- // If we started sweeping, the object cache can be removed
- // from the ractor. Set it to the page we found
- if (!cr->newobj_cache.using_page) {
- ractor_set_cache(cr, search_page);
- }
- // Otherwise we need to add this page back to the list of free
- // pages.
- else {
- // make this pointer point at the Ractor's freelist
- p->as.free.next = freelist;
- }
-
- asan_unpoison_memory_region(p, sizeof(RVALUE) * slots, false);
- return p;
- }
- }
- }
- return NULL;
-}
+ GC_ASSERT(size_pools[pool_id].slot_size == (short)slot_size);
#endif
-int
-rb_slot_size(void)
-{
- return sizeof(RVALUE);
+ slot_size -= RVALUE_OVERHEAD;
+
+ return slot_size;
}
-VALUE
-rb_rvargc_payload_init(VALUE obj, size_t size)
+size_t
+rb_size_pool_slot_size(unsigned char pool_id)
{
- rb_objspace_t * objspace = &rb_objspace;
- struct RPayload *ph = (struct RPayload *)obj;
- memset(ph, 0, rvargc_slot_count(size) * sizeof(RVALUE));
-
- RPAYLOAD_FLAGS_SET((VALUE)ph, rvargc_slot_count(size));
- objspace->total_allocated_objects += rvargc_slot_count(size);
-
- return (VALUE)ph;
+ return size_pool_slot_size(pool_id);
}
-void *
-rb_rvargc_payload_data_ptr(VALUE phead)
+bool
+rb_gc_size_allocatable_p(size_t size)
{
- return (void *)(phead + sizeof(struct RPayload));
+ return size <= size_pool_slot_size(SIZE_POOL_COUNT - 1);
}
static inline VALUE
-ractor_cached_free_region(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size)
+ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache,
+ size_t size_pool_idx)
{
-#if USE_RVARGC
- RVALUE *p = rvargc_find_region(size, cr, cr->newobj_cache.freelist);
-#else
- RVALUE *p = cr->newobj_cache.freelist;
+ rb_ractor_newobj_size_pool_cache_t *size_pool_cache = &cache->size_pool_caches[size_pool_idx];
+ RVALUE *p = size_pool_cache->freelist;
+
+#if GC_ENABLE_INCREMENTAL_MARK
+ if (is_incremental_marking(objspace)) {
+ // Not allowed to allocate without running an incremental marking step
+ if (cache->incremental_mark_step_allocated_slots >= INCREMENTAL_MARK_STEP_ALLOCATIONS) {
+ return Qfalse;
+ }
+
+ if (p) {
+ cache->incremental_mark_step_allocated_slots++;
+ }
+ }
#endif
if (p) {
VALUE obj = (VALUE)p;
- cr->newobj_cache.freelist = p->as.free.next;
+ MAYBE_UNUSED(const size_t) stride = size_pool_slot_size(size_pool_idx);
+ size_pool_cache->freelist = p->as.free.next;
+#if USE_RVARGC
+ asan_unpoison_memory_region(p, stride, true);
+#else
asan_unpoison_object(obj, true);
+#endif
+#if RGENGC_CHECK_MODE
+ GC_ASSERT(rb_gc_obj_slot_size(obj) == stride);
+ // zero clear
+ MEMZERO((char *)obj, char, stride);
+#endif
return obj;
}
else {
@@ -2412,48 +2663,47 @@ ractor_cached_free_region(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size)
}
static struct heap_page *
-heap_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
+heap_next_free_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
ASSERT_vm_locking();
struct heap_page *page;
- while (heap->free_pages == NULL) {
- heap_prepare(objspace, heap);
+ if (heap->free_pages == NULL) {
+ heap_prepare(objspace, size_pool, heap);
}
+
page = heap->free_pages;
heap->free_pages = page->free_next;
GC_ASSERT(page->free_slots != 0);
- RUBY_DEBUG_LOG("page:%p freelist:%p cnt:%d", page, page->freelist, page->free_slots);
+ RUBY_DEBUG_LOG("page:%p freelist:%p cnt:%d", (void *)page, (void *)page->freelist, page->free_slots);
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+ asan_unlock_freelist(page);
return page;
}
static inline void
-ractor_set_cache(rb_ractor_t *cr, struct heap_page *page)
+ractor_cache_set_page(rb_ractor_newobj_cache_t *cache, size_t size_pool_idx,
+ struct heap_page *page)
{
gc_report(3, &rb_objspace, "ractor_set_cache: Using page %p\n", (void *)GET_PAGE_BODY(page->start));
- cr->newobj_cache.using_page = page;
- cr->newobj_cache.freelist = page->freelist;
- page->free_slots = 0;
- page->freelist = NULL;
- asan_unpoison_object((VALUE)cr->newobj_cache.freelist, false);
- GC_ASSERT(RB_TYPE_P((VALUE)cr->newobj_cache.freelist, T_NONE));
- asan_poison_object((VALUE)cr->newobj_cache.freelist);
-}
+ rb_ractor_newobj_size_pool_cache_t *size_pool_cache = &cache->size_pool_caches[size_pool_idx];
-static inline void
-ractor_cache_slots(rb_objspace_t *objspace, rb_ractor_t *cr)
-{
- ASSERT_vm_locking();
+ GC_ASSERT(size_pool_cache->freelist == NULL);
+ GC_ASSERT(page->free_slots != 0);
+ GC_ASSERT(page->freelist != NULL);
- struct heap_page *page = heap_next_freepage(objspace, heap_eden);
+ size_pool_cache->using_page = page;
+ size_pool_cache->freelist = page->freelist;
+ page->free_slots = 0;
+ page->freelist = NULL;
- ractor_set_cache(cr, page);
+ asan_unpoison_object((VALUE)size_pool_cache->freelist, false);
+ GC_ASSERT(RB_TYPE_P((VALUE)size_pool_cache->freelist, T_NONE));
+ asan_poison_object((VALUE)size_pool_cache->freelist);
}
static inline VALUE
@@ -2466,10 +2716,96 @@ newobj_fill(VALUE obj, VALUE v1, VALUE v2, VALUE v3)
return obj;
}
-ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t alloc_size));
+static inline size_t
+size_pool_idx_for_size(size_t size)
+{
+#if USE_RVARGC
+ size += RVALUE_OVERHEAD;
+
+ size_t slot_count = CEILDIV(size, BASE_SLOT_SIZE);
+
+ /* size_pool_idx is ceil(log2(slot_count)) */
+ size_t size_pool_idx = 64 - nlz_int64(slot_count - 1);
+
+ if (size_pool_idx >= SIZE_POOL_COUNT) {
+ rb_bug("size_pool_idx_for_size: allocation size too large");
+ }
+
+#if RGENGC_CHECK_MODE
+ rb_objspace_t *objspace = &rb_objspace;
+ GC_ASSERT(size <= (size_t)size_pools[size_pool_idx].slot_size);
+ if (size_pool_idx > 0) GC_ASSERT(size > (size_t)size_pools[size_pool_idx - 1].slot_size);
+#endif
+
+ return size_pool_idx;
+#else
+ GC_ASSERT(size <= sizeof(RVALUE));
+ return 0;
+#endif
+}
+
+static VALUE
+newobj_alloc(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx, bool vm_locked)
+{
+ rb_size_pool_t *size_pool = &size_pools[size_pool_idx];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ rb_ractor_newobj_cache_t *cache = &cr->newobj_cache;
+
+ VALUE obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
+
+ if (UNLIKELY(obj == Qfalse)) {
+ unsigned int lev;
+ bool unlock_vm = false;
+
+ if (!vm_locked) {
+ RB_VM_LOCK_ENTER_CR_LEV(cr, &lev);
+ vm_locked = true;
+ unlock_vm = true;
+ }
+
+ {
+ ASSERT_vm_locking();
+
+#if GC_ENABLE_INCREMENTAL_MARK
+ if (is_incremental_marking(objspace)) {
+ gc_marks_continue(objspace, size_pool, heap);
+ cache->incremental_mark_step_allocated_slots = 0;
+
+ // Retry allocation after resetting incremental_mark_step_allocated_slots
+ obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
+ }
+#endif
+
+ if (obj == Qfalse) {
+ // Get next free page (possibly running GC)
+ struct heap_page *page = heap_next_free_page(objspace, size_pool, heap);
+ ractor_cache_set_page(cache, size_pool_idx, page);
+
+ // Retry allocation after moving to new page
+ obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
+
+ GC_ASSERT(obj != Qfalse);
+ }
+ }
+
+ if (unlock_vm) {
+ RB_VM_LOCK_LEAVE_CR_LEV(cr, &lev);
+ }
+ }
+
+ return obj;
+}
+
+static void
+newobj_zero_slot(VALUE obj)
+{
+ memset((char *)obj + sizeof(struct RBasic), 0, rb_gc_obj_slot_size(obj) - sizeof(struct RBasic));
+}
+
+ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t size_pool_idx));
static inline VALUE
-newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t alloc_size)
+newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected, size_t size_pool_idx)
{
VALUE obj;
unsigned int lev;
@@ -2490,18 +2826,13 @@ newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *
}
}
- // allocate new slot
- while ((obj = ractor_cached_free_region(objspace, cr, alloc_size)) == Qfalse) {
- ractor_cache_slots(objspace, cr);
- }
- GC_ASSERT(obj != 0);
- newobj_init(klass, flags, wb_protected, objspace, obj);
-#if USE_RVARGC
- if (alloc_size > sizeof(RVALUE))
- rb_rvargc_payload_init(obj + sizeof(RVALUE), alloc_size - sizeof(RVALUE));
+ obj = newobj_alloc(objspace, cr, size_pool_idx, true);
+#if SHAPE_IN_BASIC_FLAGS
+ flags |= (VALUE)(size_pool_idx) << SHAPE_FLAG_SHIFT;
#endif
+ newobj_init(klass, flags, wb_protected, objspace, obj);
- gc_event_hook_prep(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj, newobj_fill(obj, 0, 0, 0));
+ gc_event_hook_prep(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj, newobj_zero_slot(obj));
}
RB_VM_LOCK_LEAVE_CR_LEV(cr, &lev);
@@ -2509,20 +2840,20 @@ newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *
}
NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags,
- rb_objspace_t *objspace, rb_ractor_t *cr, size_t alloc_size));
+ rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx));
NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags,
- rb_objspace_t *objspace, rb_ractor_t *cr, size_t alloc_size));
+ rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx));
static VALUE
-newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t alloc_size)
+newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx)
{
- return newobj_slowpath(klass, flags, objspace, cr, TRUE, alloc_size);
+ return newobj_slowpath(klass, flags, objspace, cr, TRUE, size_pool_idx);
}
static VALUE
-newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t alloc_size)
+newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx)
{
- return newobj_slowpath(klass, flags, objspace, cr, FALSE, alloc_size);
+ return newobj_slowpath(klass, flags, objspace, cr, FALSE, size_pool_idx);
}
static inline VALUE
@@ -2543,24 +2874,24 @@ newobj_of0(VALUE klass, VALUE flags, int wb_protected, rb_ractor_t *cr, size_t a
}
#endif
- if ((!UNLIKELY(during_gc ||
- ruby_gc_stressful ||
- gc_event_hook_available_p(objspace)) &&
- wb_protected &&
- (obj = ractor_cached_free_region(objspace, cr, alloc_size)) != Qfalse)) {
+ size_t size_pool_idx = size_pool_idx_for_size(alloc_size);
- newobj_init(klass, flags, wb_protected, objspace, obj);
-#if USE_RVARGC
- if (alloc_size > sizeof(RVALUE))
- rb_rvargc_payload_init(obj + sizeof(RVALUE), alloc_size - sizeof(RVALUE));
+ if (!UNLIKELY(during_gc ||
+ ruby_gc_stressful ||
+ gc_event_hook_available_p(objspace)) &&
+ wb_protected) {
+ obj = newobj_alloc(objspace, cr, size_pool_idx, false);
+#if SHAPE_IN_BASIC_FLAGS
+ flags |= (VALUE)size_pool_idx << SHAPE_FLAG_SHIFT;
#endif
+ newobj_init(klass, flags, wb_protected, objspace, obj);
}
else {
RB_DEBUG_COUNTER_INC(obj_newobj_slowpath);
obj = wb_protected ?
- newobj_slowpath_wb_protected(klass, flags, objspace, cr, alloc_size) :
- newobj_slowpath_wb_unprotected(klass, flags, objspace, cr, alloc_size);
+ newobj_slowpath_wb_protected(klass, flags, objspace, cr, size_pool_idx) :
+ newobj_slowpath_wb_unprotected(klass, flags, objspace, cr, size_pool_idx);
}
return obj;
@@ -2584,7 +2915,6 @@ VALUE
rb_wb_unprotected_newobj_of(VALUE klass, VALUE flags, size_t size)
{
GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
- size = size + sizeof(RVALUE);
return newobj_of(klass, flags, 0, 0, 0, FALSE, size);
}
@@ -2592,7 +2922,6 @@ VALUE
rb_wb_protected_newobj_of(VALUE klass, VALUE flags, size_t size)
{
GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
- size = size + sizeof(RVALUE);
return newobj_of(klass, flags, 0, 0, 0, TRUE, size);
}
@@ -2600,7 +2929,6 @@ VALUE
rb_ec_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags, size_t size)
{
GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
- size = size + sizeof(RVALUE);
return newobj_of_cr(rb_ec_ractor_ptr(ec), klass, flags, 0, 0, 0, TRUE, size);
}
@@ -2609,30 +2937,66 @@ rb_ec_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flag
VALUE
rb_newobj(void)
{
- return newobj_of(0, T_NONE, 0, 0, 0, FALSE, sizeof(RVALUE));
+ return newobj_of(0, T_NONE, 0, 0, 0, FALSE, RVALUE_SIZE);
+}
+
+static size_t
+rb_obj_embedded_size(uint32_t numiv)
+{
+ return offsetof(struct RObject, as.ary) + (sizeof(VALUE) * numiv);
+}
+
+static VALUE
+rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected)
+{
+ GC_ASSERT((flags & RUBY_T_MASK) == T_OBJECT);
+ GC_ASSERT(flags & ROBJECT_EMBED);
+
+ size_t size;
+#if USE_RVARGC
+ uint32_t index_tbl_num_entries = RCLASS_EXT(klass)->max_iv_count;
+
+ size = rb_obj_embedded_size(index_tbl_num_entries);
+ if (!rb_gc_size_allocatable_p(size)) {
+ size = sizeof(struct RObject);
+ }
+#else
+ size = sizeof(struct RObject);
+#endif
+
+ VALUE obj = newobj_of(klass, flags, 0, 0, 0, wb_protected, size);
+ RUBY_ASSERT(rb_shape_get_shape(obj)->type == SHAPE_ROOT ||
+ rb_shape_get_shape(obj)->type == SHAPE_INITIAL_CAPACITY);
+
+ // Set the shape to the specific T_OBJECT shape which is always
+ // SIZE_POOL_COUNT away from the root shape.
+ ROBJECT_SET_SHAPE_ID(obj, ROBJECT_SHAPE_ID(obj) + SIZE_POOL_COUNT);
+
+#if RUBY_DEBUG
+ RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ for (size_t i = 0; i < ROBJECT_IV_CAPACITY(obj); i++) {
+ ptr[i] = Qundef;
+ }
+#endif
+
+ return obj;
}
VALUE
rb_newobj_of(VALUE klass, VALUE flags)
{
if ((flags & RUBY_T_MASK) == T_OBJECT) {
- st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass);
-
- VALUE obj = newobj_of(klass, (flags | ROBJECT_EMBED) & ~FL_WB_PROTECTED , Qundef, Qundef, Qundef, flags & FL_WB_PROTECTED, sizeof(RVALUE));
-
- if (index_tbl && index_tbl->num_entries > ROBJECT_EMBED_LEN_MAX) {
- rb_init_iv_list(obj);
- }
- return obj;
+ return rb_class_instance_allocate_internal(klass, (flags | ROBJECT_EMBED) & ~FL_WB_PROTECTED, flags & FL_WB_PROTECTED);
}
else {
- return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED, sizeof(RVALUE));
+ return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED, RVALUE_SIZE);
}
}
#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)
+ BUILTIN_TYPE(obj), (void*)(obj), RBASIC(obj)->flags)
const char *
rb_imemo_name(enum imemo_type type)
@@ -2664,7 +3028,7 @@ rb_imemo_name(enum imemo_type type)
VALUE
rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
{
- size_t size = sizeof(RVALUE);
+ size_t size = RVALUE_SIZE;
VALUE flags = T_IMEMO | (type << FL_USHIFT);
return newobj_of(v0, flags, v1, v2, v3, TRUE, size);
}
@@ -2672,7 +3036,7 @@ rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
static VALUE
rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0)
{
- size_t size = sizeof(RVALUE);
+ size_t size = sizeof(struct rb_imemo_tmpbuf_struct);
VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT);
return newobj_of(v0, flags, v1, v2, v3, FALSE, size);
}
@@ -2733,28 +3097,27 @@ rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0,
}
#endif
-VALUE
+MJIT_FUNC_EXPORTED VALUE
rb_class_allocate_instance(VALUE klass)
{
- st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass);
-
- VALUE flags = T_OBJECT | ROBJECT_EMBED;
-
- VALUE obj = newobj_of(klass, flags, Qundef, Qundef, Qundef, RGENGC_WB_PROTECTED_OBJECT, sizeof(RVALUE));
+ return rb_class_instance_allocate_internal(klass, T_OBJECT | ROBJECT_EMBED, RGENGC_WB_PROTECTED_OBJECT);
+}
- if (index_tbl && index_tbl->num_entries > ROBJECT_EMBED_LEN_MAX) {
- rb_init_iv_list(obj);
+static inline void
+rb_data_object_check(VALUE klass)
+{
+ if (klass != rb_cObject && (rb_get_alloc_func(klass) == rb_class_allocate_instance)) {
+ rb_undef_alloc_func(klass);
+ rb_warn("undefining the allocator of T_DATA class %"PRIsVALUE, klass);
}
-
- return obj;
}
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, sizeof(RVALUE));
+ if (klass) rb_data_object_check(klass);
+ return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE, sizeof(struct RTypedData));
}
VALUE
@@ -2768,9 +3131,9 @@ 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, sizeof(RVALUE));
+ RBIMPL_NONNULL_ARG(type);
+ if (klass) rb_data_object_check(klass);
+ return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED, sizeof(struct RTypedData));
}
VALUE
@@ -2785,11 +3148,11 @@ size_t
rb_objspace_data_type_memsize(VALUE obj)
{
if (RTYPEDDATA_P(obj)) {
- const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
- const void *ptr = RTYPEDDATA_DATA(obj);
- if (ptr && type->function.dsize) {
- return type->function.dsize(ptr);
- }
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
+ const void *ptr = RTYPEDDATA_DATA(obj);
+ if (ptr && type->function.dsize) {
+ return type->function.dsize(ptr);
+ }
}
return 0;
}
@@ -2798,10 +3161,47 @@ const char *
rb_objspace_data_type_name(VALUE obj)
{
if (RTYPEDDATA_P(obj)) {
- return RTYPEDDATA_TYPE(obj)->wrap_struct_name;
+ return RTYPEDDATA_TYPE(obj)->wrap_struct_name;
}
else {
- return 0;
+ return 0;
+ }
+}
+
+static int
+ptr_in_page_body_p(const void *ptr, const void *memb)
+{
+ struct heap_page *page = *(struct heap_page **)memb;
+ uintptr_t p_body = (uintptr_t)GET_PAGE_BODY(page->start);
+
+ if ((uintptr_t)ptr >= p_body) {
+ return (uintptr_t)ptr < (p_body + HEAP_PAGE_SIZE) ? 0 : 1;
+ }
+ else {
+ return -1;
+ }
+}
+
+PUREFUNC(static inline struct heap_page * heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr);)
+static inline struct heap_page *
+heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr)
+{
+ struct heap_page **res;
+
+ if (ptr < (uintptr_t)heap_pages_lomem ||
+ ptr > (uintptr_t)heap_pages_himem) {
+ return NULL;
+ }
+
+ res = bsearch((void *)ptr, heap_pages_sorted,
+ (size_t)heap_allocated_pages, sizeof(struct heap_page *),
+ ptr_in_page_body_p);
+
+ if (res) {
+ return *res;
+ }
+ else {
+ return NULL;
}
}
@@ -2809,40 +3209,30 @@ PUREFUNC(static inline int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr
static inline int
is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
{
- register RVALUE *p = RANY(ptr);
+ register uintptr_t p = (uintptr_t)ptr;
register struct heap_page *page;
- register size_t hi, lo, mid;
RB_DEBUG_COUNTER_INC(gc_isptr_trial);
if (p < heap_pages_lomem || p > heap_pages_himem) return FALSE;
RB_DEBUG_COUNTER_INC(gc_isptr_range);
- if ((VALUE)p % sizeof(RVALUE) != 0) return FALSE;
+ if (p % BASE_SLOT_SIZE != 0) return FALSE;
RB_DEBUG_COUNTER_INC(gc_isptr_align);
- /* check if p looks like a pointer using bsearch*/
- lo = 0;
- hi = heap_allocated_pages;
- while (lo < hi) {
- mid = (lo + hi) / 2;
- page = heap_pages_sorted[mid];
- if (page->start <= p) {
- if (p < page->start + page->total_slots) {
- RB_DEBUG_COUNTER_INC(gc_isptr_maybe);
+ page = heap_page_for_ptr(objspace, (uintptr_t)ptr);
+ if (page) {
+ RB_DEBUG_COUNTER_INC(gc_isptr_maybe);
+ if (page->flags.in_tomb) {
+ return FALSE;
+ }
+ else {
+ if (p < page->start) return FALSE;
+ if (p >= page->start + (page->total_slots * page->slot_size)) return FALSE;
+ if ((NUM_IN_PAGE(p) * BASE_SLOT_SIZE) % page->slot_size != 0) return FALSE;
- if (page->flags.in_tomb) {
- return FALSE;
- }
- else {
- return TRUE;
- }
- }
- lo = mid + 1;
- }
- else {
- hi = mid;
- }
+ return TRUE;
+ }
}
return FALSE;
}
@@ -2862,20 +3252,6 @@ rb_free_const_table(struct rb_id_table *tbl)
rb_id_table_free(tbl);
}
-static int
-free_iv_index_tbl_free_i(st_data_t key, st_data_t value, st_data_t data)
-{
- xfree((void *)value);
- return ST_CONTINUE;
-}
-
-static void
-iv_index_tbl_free(struct st_table *tbl)
-{
- st_foreach(tbl, free_iv_index_tbl_free_i, 0);
- st_free_table(tbl);
-}
-
// alive: if false, target pointers can be freed already.
// To check it, we need objspace parameter.
static void
@@ -2885,8 +3261,7 @@ vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, rb_objspace_t *objspace,
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);
+ void *ptr = asan_unpoison_object_temporary((VALUE)cc);
// ccs can be free'ed.
if (is_pointer_to_heap(objspace, (void *)cc) &&
IMEMO_TYPE_P(cc, imemo_callcache) &&
@@ -2940,7 +3315,7 @@ cc_table_mark_i(ID id, VALUE ccs_ptr, void *data_ptr)
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));
+ VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
gc_mark(data->objspace, (VALUE)ccs->entries[i].ci);
gc_mark(data->objspace, (VALUE)ccs->entries[i].cc);
@@ -3008,8 +3383,11 @@ make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *dat
zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & FL_SEEN_OBJ_ID);
zombie->dfree = dfree;
zombie->data = data;
- zombie->next = heap_pages_deferred_final;
- heap_pages_deferred_final = (VALUE)zombie;
+ VALUE prev, next = heap_pages_deferred_final;
+ do {
+ zombie->next = prev = next;
+ next = RUBY_ATOMIC_VALUE_CAS(heap_pages_deferred_final, prev, obj);
+ } while (next != prev);
struct heap_page *page = GET_HEAP_PAGE(obj);
page->final_slots++;
@@ -3054,15 +3432,15 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_FIXNUM:
case T_TRUE:
case T_FALSE:
- rb_bug("obj_free() called for broken object");
- break;
+ rb_bug("obj_free() called for broken object");
+ break;
default:
break;
}
if (FL_TEST(obj, FL_EXIVAR)) {
- rb_free_generic_ivar((VALUE)obj);
- FL_UNSET(obj, FL_EXIVAR);
+ rb_free_generic_ivar((VALUE)obj);
+ FL_UNSET(obj, FL_EXIVAR);
}
if (FL_TEST(obj, FL_SEEN_OBJ_ID) && !FL_TEST(obj, FL_FINALIZE)) {
@@ -3073,16 +3451,20 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
#if RGENGC_CHECK_MODE
#define CHECK(x) if (x(obj) != FALSE) rb_bug("obj_free: " #x "(%s) != FALSE", obj_info(obj))
- CHECK(RVALUE_WB_UNPROTECTED);
- CHECK(RVALUE_MARKED);
- CHECK(RVALUE_MARKING);
- CHECK(RVALUE_UNCOLLECTIBLE);
+ CHECK(RVALUE_WB_UNPROTECTED);
+ CHECK(RVALUE_MARKED);
+ CHECK(RVALUE_MARKING);
+ CHECK(RVALUE_UNCOLLECTIBLE);
#undef CHECK
#endif
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
+ if (rb_shape_obj_too_complex(obj)) {
+ RB_DEBUG_COUNTER_INC(obj_obj_too_complex);
+ st_free_table(ROBJECT_IV_HASH(obj));
+ }
+ else if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
RB_DEBUG_COUNTER_INC(obj_obj_embed);
}
else if (ROBJ_TRANSIENT_P(obj)) {
@@ -3095,44 +3477,39 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_MODULE:
case T_CLASS:
- rb_id_table_free(RCLASS_M_TBL(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));
- }
- if (RCLASS_CONST_TBL(obj)) {
- rb_free_const_table(RCLASS_CONST_TBL(obj));
- }
- if (RCLASS_IV_INDEX_TBL(obj)) {
- iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj));
- }
- if (RCLASS_CVC_TBL(obj)) {
+ if (RCLASS_IVPTR(obj)) {
+ xfree(RCLASS_IVPTR(obj));
+ }
+ if (RCLASS_CONST_TBL(obj)) {
+ rb_free_const_table(RCLASS_CONST_TBL(obj));
+ }
+ if (RCLASS_CVC_TBL(obj)) {
rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL);
rb_id_table_free(RCLASS_CVC_TBL(obj));
- }
- if (RCLASS_SUBCLASSES(obj)) {
- if (BUILTIN_TYPE(obj) == T_MODULE) {
- rb_class_detach_module_subclasses(obj);
- }
- else {
- rb_class_detach_subclasses(obj);
- }
- RCLASS_SUBCLASSES(obj) = NULL;
- }
- rb_class_remove_from_module_subclasses(obj);
- rb_class_remove_from_super_subclasses(obj);
- if (RCLASS_EXT(obj))
- RCLASS_EXT(obj) = NULL;
+ }
+ rb_class_remove_subclass_head(obj);
+ rb_class_remove_from_module_subclasses(obj);
+ rb_class_remove_from_super_subclasses(obj);
+ if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
+ xfree(RCLASS_SUPERCLASSES(obj));
+ }
+
+#if SIZE_POOL_COUNT == 1
+ if (RCLASS_EXT(obj))
+ xfree(RCLASS_EXT(obj));
+#endif
(void)RB_DEBUG_COUNTER_INC_IF(obj_module_ptr, BUILTIN_TYPE(obj) == T_MODULE);
(void)RB_DEBUG_COUNTER_INC_IF(obj_class_ptr, BUILTIN_TYPE(obj) == T_CLASS);
- break;
+ break;
case T_STRING:
- rb_str_free(obj);
- break;
+ rb_str_free(obj);
+ break;
case T_ARRAY:
rb_ary_free(obj);
- break;
+ break;
case T_HASH:
#if USE_DEBUG_COUNTER
switch (RHASH_SIZE(obj)) {
@@ -3190,53 +3567,53 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
GC_ASSERT(RHASH_ST_TABLE_P(obj));
st_free_table(RHASH(obj)->as.st);
}
- break;
+ break;
case T_REGEXP:
- if (RANY(obj)->as.regexp.ptr) {
- onig_free(RANY(obj)->as.regexp.ptr);
+ if (RANY(obj)->as.regexp.ptr) {
+ onig_free(RANY(obj)->as.regexp.ptr);
RB_DEBUG_COUNTER_INC(obj_regexp_ptr);
- }
- break;
+ }
+ break;
case T_DATA:
- if (DATA_PTR(obj)) {
- int free_immediately = FALSE;
- void (*dfree)(void *);
- void *data = DATA_PTR(obj);
-
- if (RTYPEDDATA_P(obj)) {
- free_immediately = (RANY(obj)->as.typeddata.type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
- dfree = RANY(obj)->as.typeddata.type->function.dfree;
- if (0 && free_immediately == 0) {
- /* to expose non-free-immediate T_DATA */
- fprintf(stderr, "not immediate -> %s\n", RANY(obj)->as.typeddata.type->wrap_struct_name);
- }
- }
- else {
- dfree = RANY(obj)->as.data.dfree;
- }
-
- if (dfree) {
- if (dfree == RUBY_DEFAULT_FREE) {
- xfree(data);
+ if (DATA_PTR(obj)) {
+ int free_immediately = FALSE;
+ void (*dfree)(void *);
+ void *data = DATA_PTR(obj);
+
+ if (RTYPEDDATA_P(obj)) {
+ free_immediately = (RANY(obj)->as.typeddata.type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
+ dfree = RANY(obj)->as.typeddata.type->function.dfree;
+ if (0 && free_immediately == 0) {
+ /* to expose non-free-immediate T_DATA */
+ fprintf(stderr, "not immediate -> %s\n", RANY(obj)->as.typeddata.type->wrap_struct_name);
+ }
+ }
+ else {
+ dfree = RANY(obj)->as.data.dfree;
+ }
+
+ if (dfree) {
+ if (dfree == RUBY_DEFAULT_FREE) {
+ xfree(data);
RB_DEBUG_COUNTER_INC(obj_data_xfree);
- }
- else if (free_immediately) {
- (*dfree)(data);
+ }
+ else if (free_immediately) {
+ (*dfree)(data);
RB_DEBUG_COUNTER_INC(obj_data_imm_free);
- }
- else {
- make_zombie(objspace, obj, dfree, data);
+ }
+ else {
+ make_zombie(objspace, obj, dfree, data);
RB_DEBUG_COUNTER_INC(obj_data_zombie);
- return 1;
- }
- }
+ return FALSE;
+ }
+ }
else {
RB_DEBUG_COUNTER_INC(obj_data_empty);
}
- }
- break;
+ }
+ break;
case T_MATCH:
- if (RANY(obj)->as.match.rmatch) {
+ if (RANY(obj)->as.match.rmatch) {
struct rmatch *rm = RANY(obj)->as.match.rmatch;
#if USE_DEBUG_COUNTER
if (rm->regs.num_regs >= 8) {
@@ -3249,21 +3626,21 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
RB_DEBUG_COUNTER_INC(obj_match_under4);
}
#endif
- onig_region_free(&rm->regs, 0);
+ onig_region_free(&rm->regs, 0);
if (rm->char_offset)
- xfree(rm->char_offset);
- xfree(rm);
+ xfree(rm->char_offset);
+ xfree(rm);
RB_DEBUG_COUNTER_INC(obj_match_ptr);
- }
- break;
+ }
+ break;
case T_FILE:
- if (RANY(obj)->as.file.fptr) {
- make_io_zombie(objspace, obj);
+ if (RANY(obj)->as.file.fptr) {
+ make_io_zombie(objspace, obj);
RB_DEBUG_COUNTER_INC(obj_file_ptr);
- return 1;
- }
- break;
+ return FALSE;
+ }
+ break;
case T_RATIONAL:
RB_DEBUG_COUNTER_INC(obj_rational);
break;
@@ -3271,45 +3648,44 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
RB_DEBUG_COUNTER_INC(obj_complex);
break;
case T_MOVED:
- break;
+ break;
case T_ICLASS:
- /* Basically , T_ICLASS shares table with the module */
+ /* Basically , T_ICLASS shares table with the module */
if (RICLASS_OWNS_M_TBL_P(obj)) {
/* Method table is not shared for origin iclasses of classes */
rb_id_table_free(RCLASS_M_TBL(obj));
}
- if (RCLASS_CALLABLE_M_TBL(obj) != NULL) {
- rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
- }
- if (RCLASS_SUBCLASSES(obj)) {
- rb_class_detach_subclasses(obj);
- RCLASS_SUBCLASSES(obj) = NULL;
- }
+ if (RCLASS_CALLABLE_M_TBL(obj) != NULL) {
+ rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
+ }
+ rb_class_remove_subclass_head(obj);
cc_table_free(objspace, obj, FALSE);
- rb_class_remove_from_module_subclasses(obj);
- rb_class_remove_from_super_subclasses(obj);
- RCLASS_EXT(obj) = NULL;
+ rb_class_remove_from_module_subclasses(obj);
+ rb_class_remove_from_super_subclasses(obj);
+#if !RCLASS_EXT_EMBEDDED
+ xfree(RCLASS_EXT(obj));
+#endif
RB_DEBUG_COUNTER_INC(obj_iclass_ptr);
- break;
+ break;
case T_FLOAT:
RB_DEBUG_COUNTER_INC(obj_float);
- break;
+ break;
case T_BIGNUM:
- if (!BIGNUM_EMBED_P(obj) && BIGNUM_DIGITS(obj)) {
- xfree(BIGNUM_DIGITS(obj));
+ if (!BIGNUM_EMBED_P(obj) && BIGNUM_DIGITS(obj)) {
+ xfree(BIGNUM_DIGITS(obj));
RB_DEBUG_COUNTER_INC(obj_bignum_ptr);
- }
+ }
else {
RB_DEBUG_COUNTER_INC(obj_bignum_embed);
}
- break;
+ break;
case T_NODE:
- UNEXPECTED_NODE(obj_free);
- break;
+ UNEXPECTED_NODE(obj_free);
+ break;
case T_STRUCT:
if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) ||
@@ -3322,39 +3698,39 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
else {
xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr);
RB_DEBUG_COUNTER_INC(obj_struct_ptr);
- }
- break;
+ }
+ break;
case T_SYMBOL:
- {
+ {
rb_gc_free_dsymbol(obj);
RB_DEBUG_COUNTER_INC(obj_symbol);
- }
- break;
+ }
+ break;
case T_IMEMO:
- switch (imemo_type(obj)) {
- case imemo_ment:
- rb_free_method_entry(&RANY(obj)->as.imemo.ment);
+ switch (imemo_type(obj)) {
+ case imemo_ment:
+ rb_free_method_entry(&RANY(obj)->as.imemo.ment);
RB_DEBUG_COUNTER_INC(obj_imemo_ment);
- break;
- case imemo_iseq:
- rb_iseq_free(&RANY(obj)->as.imemo.iseq);
+ break;
+ case imemo_iseq:
+ rb_iseq_free(&RANY(obj)->as.imemo.iseq);
RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
- break;
- case imemo_env:
- GC_ASSERT(VM_ENV_ESCAPED_P(RANY(obj)->as.imemo.env.ep));
- xfree((VALUE *)RANY(obj)->as.imemo.env.env);
+ break;
+ case imemo_env:
+ GC_ASSERT(VM_ENV_ESCAPED_P(RANY(obj)->as.imemo.env.ep));
+ xfree((VALUE *)RANY(obj)->as.imemo.env.env);
RB_DEBUG_COUNTER_INC(obj_imemo_env);
- break;
- case imemo_tmpbuf:
- xfree(RANY(obj)->as.imemo.alloc.ptr);
+ break;
+ case imemo_tmpbuf:
+ xfree(RANY(obj)->as.imemo.alloc.ptr);
RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
- break;
- case imemo_ast:
- rb_ast_free(&RANY(obj)->as.imemo.ast);
+ break;
+ case imemo_ast:
+ rb_ast_free(&RANY(obj)->as.imemo.ast);
RB_DEBUG_COUNTER_INC(obj_imemo_ast);
- break;
+ break;
case imemo_cref:
RB_DEBUG_COUNTER_INC(obj_imemo_cref);
break;
@@ -3382,20 +3758,20 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case imemo_constcache:
RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
break;
- }
- return 0;
+ }
+ return TRUE;
default:
- rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE,
- BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags);
+ rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE,
+ BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags);
}
if (FL_TEST(obj, FL_FINALIZE)) {
make_zombie(objspace, obj, 0, 0);
- return 1;
+ return FALSE;
}
else {
- return 0;
+ return TRUE;
}
}
@@ -3406,7 +3782,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
static int
object_id_cmp(st_data_t x, st_data_t y)
{
- if (RB_TYPE_P(x, T_BIGNUM)) {
+ if (RB_BIGNUM_TYPE_P(x)) {
return !rb_big_eql(x, y);
}
else {
@@ -3417,7 +3793,7 @@ object_id_cmp(st_data_t x, st_data_t y)
static st_index_t
object_id_hash(st_data_t n)
{
- if (RB_TYPE_P(n, T_BIGNUM)) {
+ if (RB_BIGNUM_TYPE_P(n)) {
return FIX2LONG(rb_big_hash(n));
}
else {
@@ -3434,29 +3810,9 @@ 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
-
-#if defined(HAVE_MMAP) && !HAVE_CONST_PAGE_SIZE && !defined(PAGE_MAX_SIZE)
+#if defined(INIT_HEAP_PAGE_ALLOC_USE_MMAP)
/* Need to determine if we can use mmap at runtime. */
-# ifdef PAGE_SIZE
- /* If the PAGE_SIZE macro can be used. */
- use_mmap_aligned_alloc = PAGE_SIZE <= HEAP_PAGE_SIZE;
-# elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
- /* If we can use sysconf to determine the page size. */
- use_mmap_aligned_alloc = pagesize <= HEAP_PAGE_SIZE;
-# else
- /* Otherwise we can't determine the system page size, so don't use mmap. */
- use_mmap_aligned_alloc = FALSE;
-# endif
+ heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP;
#endif
objspace->next_object_id = INT2FIX(OBJ_ID_INITIAL);
@@ -3467,7 +3823,16 @@ Init_heap(void)
objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
#endif
- heap_add_pages(objspace, heap_eden, gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT);
+ heap_add_pages(objspace, &size_pools[0], SIZE_POOL_EDEN_HEAP(&size_pools[0]), gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT);
+
+ /* Give other size pools allocatable pages. */
+ for (int i = 1; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ int multiple = size_pool->slot_size / BASE_SLOT_SIZE;
+ size_pool->allocatable_pages = gc_params.heap_init_slots * multiple / HEAP_PAGE_OBJ_LIMIT;
+ }
+ heap_pages_expand_sorted(objspace);
+
init_mark_stack(&objspace->mark_stack);
objspace->profile.invoke_time = getrusage_time();
@@ -3494,8 +3859,8 @@ struct each_obj_data {
each_obj_callback *callback;
void *data;
- struct heap_page **pages;
- size_t pages_count;
+ struct heap_page **pages[SIZE_POOL_COUNT];
+ size_t pages_counts[SIZE_POOL_COUNT];
};
static VALUE
@@ -3509,10 +3874,14 @@ objspace_each_objects_ensure(VALUE arg)
objspace->flags.dont_incremental = FALSE;
}
- /* Free pages buffer */
- struct heap_page **pages = data->pages;
- GC_ASSERT(pages);
- free(pages);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ struct heap_page **pages = data->pages[i];
+ /* pages could be NULL if an error was raised during setup (e.g.
+ * malloc failed due to out of memory). */
+ if (pages) {
+ free(pages);
+ }
+ }
return Qnil;
}
@@ -3522,52 +3891,56 @@ objspace_each_objects_try(VALUE arg)
{
struct each_obj_data *data = (struct each_obj_data *)arg;
rb_objspace_t *objspace = data->objspace;
- struct heap_page **pages = data->pages;
- size_t pages_count = data->pages_count;
-
- struct heap_page *page = list_top(&heap_eden->pages, struct heap_page, page_node);
- for (size_t i = 0; i < pages_count; i++) {
- /* If we have reached the end of the linked list then there are no
- * more pages, so break. */
- if (page == NULL) break;
-
- /* If this page does not match the one in the buffer, then move to
- * the next page in the buffer. */
- if (pages[i] != page) continue;
-
- RVALUE *pstart = page->start;
- RVALUE *pend = pstart + page->total_slots;
- RVALUE *cursor_end = pstart;
-
- while (cursor_end < pend) {
- int payload_len = 0;
-
-#if USE_RVARGC
- while (cursor_end < pend && BUILTIN_TYPE((VALUE)cursor_end) != T_PAYLOAD) {
- cursor_end++;
- }
-
- //Make sure the Payload header slot is yielded
- if (cursor_end < pend && BUILTIN_TYPE((VALUE)cursor_end) == T_PAYLOAD) {
- payload_len = RPAYLOAD_LEN((VALUE)cursor_end);
- cursor_end++;
- }
-#else
- cursor_end = pend;
-#endif
- if ((*data->callback)(pstart, cursor_end, sizeof(RVALUE), data->data)) {
+ /* Copy pages from all size_pools to their respective buffers. */
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ size_t size = size_mul_or_raise(SIZE_POOL_EDEN_HEAP(size_pool)->total_pages, sizeof(struct heap_page *), rb_eRuntimeError);
+
+ struct heap_page **pages = malloc(size);
+ if (!pages) rb_memerror();
+
+ /* Set up pages buffer by iterating over all pages in the current eden
+ * heap. This will be a snapshot of the state of the heap before we
+ * call the callback over each page that exists in this buffer. Thus it
+ * is safe for the callback to allocate objects without possibly entering
+ * an infinite loop. */
+ struct heap_page *page = 0;
+ size_t pages_count = 0;
+ ccan_list_for_each(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node) {
+ pages[pages_count] = page;
+ pages_count++;
+ }
+ data->pages[i] = pages;
+ data->pages_counts[i] = pages_count;
+ GC_ASSERT(pages_count == SIZE_POOL_EDEN_HEAP(size_pool)->total_pages);
+ }
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ size_t pages_count = data->pages_counts[i];
+ struct heap_page **pages = data->pages[i];
+
+ struct heap_page *page = ccan_list_top(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, struct heap_page, page_node);
+ for (size_t i = 0; i < pages_count; i++) {
+ /* If we have reached the end of the linked list then there are no
+ * more pages, so break. */
+ if (page == NULL) break;
+
+ /* If this page does not match the one in the buffer, then move to
+ * the next page in the buffer. */
+ if (pages[i] != page) continue;
+
+ uintptr_t pstart = (uintptr_t)page->start;
+ uintptr_t pend = pstart + (page->total_slots * size_pool->slot_size);
+
+ if (!__asan_region_is_poisoned((void *)pstart, pend - pstart) &&
+ (*data->callback)((void *)pstart, (void *)pend, size_pool->slot_size, data->data)) {
break;
}
- // Move the cursor over the rest of the payload body
- if (payload_len) {
- cursor_end += (payload_len - 1);
- pstart = cursor_end;
- }
+ page = ccan_list_next(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node);
}
-
- page = list_next(&heap_eden->pages, page, page_node);
}
return Qnil;
@@ -3627,25 +4000,6 @@ objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void
objspace->flags.dont_incremental = TRUE;
}
- /* Create pages buffer */
- size_t size = size_mul_or_raise(heap_eden->total_pages, sizeof(struct heap_page *), rb_eRuntimeError);
- struct heap_page **pages = malloc(size);
- if (!pages) rb_memerror();
-
- /* Set up pages buffer by iterating over all pages in the current eden
- * heap. This will be a snapshot of the state of the heap before we
- * call the callback over each page that exists in this buffer. Thus it
- * is safe for the callback to allocate objects without possibly entering
- * an infinite loop. */
- struct heap_page *page = 0;
- size_t pages_count = 0;
- list_for_each(&heap_eden->pages, page, page_node) {
- pages[pages_count] = page;
- pages_count++;
- }
- GC_ASSERT(pages_count == heap_eden->total_pages);
-
- /* Run the callback */
struct each_obj_data each_obj_data = {
.objspace = objspace,
.reenable_incremental = reenable_incremental,
@@ -3653,8 +4007,8 @@ objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void
.callback = callback,
.data = data,
- .pages = pages,
- .pages_count = pages_count
+ .pages = {NULL},
+ .pages_counts = {0},
};
rb_ensure(objspace_each_objects_try, (VALUE)&each_obj_data,
objspace_each_objects_ensure, (VALUE)&each_obj_data);
@@ -3675,32 +4029,30 @@ static int
internal_object_p(VALUE obj)
{
RVALUE *p = (RVALUE *)obj;
- void *ptr = __asan_region_is_poisoned(p, SIZEOF_VALUE);
- asan_unpoison_object(obj, false);
+ void *ptr = asan_unpoison_object_temporary(obj);
bool used_p = p->as.basic.flags;
if (used_p) {
switch (BUILTIN_TYPE(obj)) {
- case T_NODE:
- UNEXPECTED_NODE(internal_object_p);
- break;
- case T_NONE:
+ case T_NODE:
+ UNEXPECTED_NODE(internal_object_p);
+ break;
+ case T_NONE:
case T_MOVED:
- case T_IMEMO:
- case T_ICLASS:
- case T_ZOMBIE:
- case T_PAYLOAD:
- break;
- case T_CLASS:
- if (!p->as.basic.klass) break;
- if (FL_TEST(obj, FL_SINGLETON)) {
- return rb_singleton_class_internal_p(obj);
- }
- return 0;
- default:
- if (!p->as.basic.klass) break;
- return 0;
- }
+ case T_IMEMO:
+ case T_ICLASS:
+ case T_ZOMBIE:
+ break;
+ case T_CLASS:
+ if (!p->as.basic.klass) break;
+ if (FL_TEST(obj, FL_SINGLETON)) {
+ return rb_singleton_class_internal_p(obj);
+ }
+ return 0;
+ default:
+ if (!p->as.basic.klass) break;
+ return 0;
+ }
}
if (ptr || ! used_p) {
asan_poison_object(obj);
@@ -3721,14 +4073,14 @@ os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
- if (!internal_object_p(v)) {
- if (!oes->of || rb_obj_is_kind_of(v, oes->of)) {
+ if (!internal_object_p(v)) {
+ if (!oes->of || rb_obj_is_kind_of(v, oes->of)) {
if (!rb_multi_ractor_p() || rb_ractor_shareable_p(v)) {
rb_yield(v);
oes->num++;
}
- }
- }
+ }
+ }
}
return 0;
@@ -3820,8 +4172,8 @@ static void
should_be_callable(VALUE block)
{
if (!rb_obj_respond_to(block, idCall, TRUE)) {
- rb_raise(rb_eArgError, "wrong type argument %"PRIsVALUE" (should be callable)",
- rb_obj_class(block));
+ rb_raise(rb_eArgError, "wrong type argument %"PRIsVALUE" (should be callable)",
+ rb_obj_class(block));
}
}
@@ -3829,8 +4181,8 @@ static void
should_be_finalizable(VALUE obj)
{
if (!FL_ABLE(obj)) {
- rb_raise(rb_eArgError, "cannot define finalizer for %s",
- rb_obj_classname(obj));
+ rb_raise(rb_eArgError, "cannot define finalizer for %s",
+ rb_obj_classname(obj));
}
rb_check_frozen(obj);
}
@@ -3905,10 +4257,10 @@ define_final(int argc, VALUE *argv, VALUE os)
rb_scan_args(argc, argv, "11", &obj, &block);
should_be_finalizable(obj);
if (argc == 1) {
- block = rb_block_proc();
+ block = rb_block_proc();
}
else {
- should_be_callable(block);
+ should_be_callable(block);
}
if (rb_callable_receiver(block) == obj) {
@@ -3928,28 +4280,28 @@ define_final0(VALUE obj, VALUE block)
RBASIC(obj)->flags |= FL_FINALIZE;
if (st_lookup(finalizer_table, obj, &data)) {
- table = (VALUE)data;
+ table = (VALUE)data;
- /* avoid duplicate block, table is usually small */
- {
- long len = RARRAY_LEN(table);
- long i;
+ /* avoid duplicate block, table is usually small */
+ {
+ long len = RARRAY_LEN(table);
+ long i;
for (i = 0; i < len; i++) {
VALUE recv = RARRAY_AREF(table, i);
if (rb_equal(recv, block)) {
block = recv;
goto end;
- }
- }
- }
+ }
+ }
+ }
- rb_ary_push(table, block);
+ rb_ary_push(table, block);
}
else {
- table = rb_ary_new3(1, block);
- RBASIC_CLEAR_CLASS(table);
- st_add_direct(finalizer_table, obj, table);
+ table = rb_ary_new3(1, block);
+ RBASIC_CLEAR_CLASS(table);
+ st_add_direct(finalizer_table, obj, table);
}
end:
block = rb_ary_new3(2, INT2FIX(0), block);
@@ -3974,8 +4326,8 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj)
if (!FL_TEST(obj, FL_FINALIZE)) return;
if (st_lookup(finalizer_table, obj, &data)) {
- table = (VALUE)data;
- st_insert(finalizer_table, dest, table);
+ table = (VALUE)data;
+ st_insert(finalizer_table, dest, table);
}
FL_SET(dest, FL_FINALIZE);
}
@@ -3989,10 +4341,10 @@ run_single_final(VALUE cmd, VALUE objid)
static void
warn_exception_in_finalizer(rb_execution_context_t *ec, VALUE final)
{
- if (final != Qundef && !NIL_P(ruby_verbose)) {
- VALUE errinfo = ec->errinfo;
- rb_warn("Exception in finalizer %+"PRIsVALUE, final);
- rb_ec_error_print(ec, errinfo);
+ if (!UNDEF_P(final) && !NIL_P(ruby_verbose)) {
+ VALUE errinfo = ec->errinfo;
+ rb_warn("Exception in finalizer %+"PRIsVALUE, final);
+ rb_ec_error_print(ec, errinfo);
}
}
@@ -4002,33 +4354,37 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
long i;
enum ruby_tag_type state;
volatile struct {
- VALUE errinfo;
- VALUE objid;
- VALUE final;
- rb_control_frame_t *cfp;
- long finished;
+ VALUE errinfo;
+ VALUE objid;
+ VALUE final;
+ rb_control_frame_t *cfp;
+ VALUE *sp;
+ long finished;
} saved;
+
rb_execution_context_t * volatile ec = GET_EC();
#define RESTORE_FINALIZER() (\
- ec->cfp = saved.cfp, \
- ec->errinfo = saved.errinfo)
+ ec->cfp = saved.cfp, \
+ ec->cfp->sp = saved.sp, \
+ ec->errinfo = saved.errinfo)
saved.errinfo = ec->errinfo;
saved.objid = rb_obj_id(obj);
saved.cfp = ec->cfp;
+ saved.sp = ec->cfp->sp;
saved.finished = 0;
saved.final = Qundef;
EC_PUSH_TAG(ec);
state = EC_EXEC_TAG();
if (state != TAG_NONE) {
- ++saved.finished; /* skip failed finalizer */
- warn_exception_in_finalizer(ec, ATOMIC_VALUE_EXCHANGE(saved.final, Qundef));
+ ++saved.finished; /* skip failed finalizer */
+ warn_exception_in_finalizer(ec, ATOMIC_VALUE_EXCHANGE(saved.final, Qundef));
}
for (i = saved.finished;
- RESTORE_FINALIZER(), i<RARRAY_LEN(table);
- saved.finished = ++i) {
- run_single_final(saved.final = RARRAY_AREF(table, i), saved.objid);
+ RESTORE_FINALIZER(), i<RARRAY_LEN(table);
+ saved.finished = ++i) {
+ run_single_final(saved.final = RARRAY_AREF(table, i), saved.objid);
}
EC_POP_TAG();
#undef RESTORE_FINALIZER
@@ -4040,12 +4396,12 @@ run_final(rb_objspace_t *objspace, VALUE zombie)
st_data_t key, table;
if (RZOMBIE(zombie)->dfree) {
- RZOMBIE(zombie)->dfree(RZOMBIE(zombie)->data);
+ RZOMBIE(zombie)->dfree(RZOMBIE(zombie)->data);
}
key = (st_data_t)zombie;
if (st_delete(finalizer_table, &key, &table)) {
- run_finalizer(objspace, zombie, (VALUE)table);
+ run_finalizer(objspace, zombie, (VALUE)table);
}
}
@@ -4059,7 +4415,7 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie)
next_zombie = RZOMBIE(zombie)->next;
page = GET_HEAP_PAGE(zombie);
- run_final(objspace, zombie);
+ run_final(objspace, zombie);
RB_VM_LOCK_ENTER();
{
@@ -4084,16 +4440,20 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie)
}
static void
-finalize_deferred(rb_objspace_t *objspace)
+finalize_deferred_heap_pages(rb_objspace_t *objspace)
{
VALUE zombie;
- rb_execution_context_t *ec = GET_EC();
- ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
-
while ((zombie = ATOMIC_VALUE_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
- finalize_list(objspace, zombie);
+ finalize_list(objspace, zombie);
}
+}
+static void
+finalize_deferred(rb_objspace_t *objspace)
+{
+ rb_execution_context_t *ec = GET_EC();
+ ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
+ finalize_deferred_heap_pages(objspace);
ec->interrupt_mask &= ~PENDING_INTERRUPT_MASK;
}
@@ -4103,19 +4463,15 @@ gc_finalize_deferred(void *dmy)
rb_objspace_t *objspace = dmy;
if (ATOMIC_EXCHANGE(finalizing, 1)) return;
- RB_VM_LOCK_ENTER();
- {
- finalize_deferred(objspace);
- ATOMIC_SET(finalizing, 0);
- }
- RB_VM_LOCK_LEAVE();
+ finalize_deferred(objspace);
+ ATOMIC_SET(finalizing, 0);
}
static void
gc_finalize_deferred_register(rb_objspace_t *objspace)
{
if (rb_postponed_job_register_one(0, gc_finalize_deferred, objspace) == 0) {
- rb_bug("gc_finalize_deferred_register: can't register finalizer.");
+ rb_bug("gc_finalize_deferred_register: can't register finalizer.");
}
}
@@ -4142,7 +4498,6 @@ bool rb_obj_is_main_ractor(VALUE gv);
void
rb_objspace_call_finalizer(rb_objspace_t *objspace)
{
- RVALUE *p, *pend;
size_t i;
#if RGENGC_CHECK_MODE >= 2
@@ -4162,16 +4517,16 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
/* force to run finalizer */
while (finalizer_table->num_entries) {
- struct force_finalize_list *list = 0;
- st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
- while (list) {
- struct force_finalize_list *curr = list;
- st_data_t obj = (st_data_t)curr->obj;
- run_finalizer(objspace, curr->obj, curr->table);
- st_delete(finalizer_table, &obj, 0);
- list = curr->next;
- xfree(curr);
- }
+ struct force_finalize_list *list = 0;
+ st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
+ while (list) {
+ struct force_finalize_list *curr = list;
+ st_data_t obj = (st_data_t)curr->obj;
+ run_finalizer(objspace, curr->obj, curr->table);
+ st_delete(finalizer_table, &obj, 0);
+ list = curr->next;
+ xfree(curr);
+ }
}
/* prohibit GC because force T_DATA finalizers can break an object graph consistency */
@@ -4183,96 +4538,75 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
/* 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) {
+ struct heap_page *page = heap_pages_sorted[i];
+ short stride = page->slot_size;
+
+ uintptr_t p = (uintptr_t)page->start;
+ uintptr_t pend = p + page->total_slots * stride;
+ for (; p < pend; p += stride) {
VALUE vp = (VALUE)p;
- void *poisoned = asan_poisoned_object_p(vp);
- asan_unpoison_object(vp, false);
+ void *poisoned = asan_unpoison_object_temporary(vp);
switch (BUILTIN_TYPE(vp)) {
- case T_DATA:
- if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
+ case T_DATA:
+ if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
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) {
+ RDATA(p)->dfree = RANY(p)->as.typeddata.type->function.dfree;
+ }
+ RANY(p)->as.free.flags = 0;
+ if (RANY(p)->as.data.dfree == RUBY_DEFAULT_FREE) {
+ xfree(DATA_PTR(p));
+ }
+ else if (RANY(p)->as.data.dfree) {
make_zombie(objspace, vp, RANY(p)->as.data.dfree, RANY(p)->as.data.data);
- }
- break;
- case T_FILE:
- if (RANY(p)->as.file.fptr) {
+ }
+ break;
+ case T_FILE:
+ if (RANY(p)->as.file.fptr) {
make_io_zombie(objspace, vp);
- }
- break;
+ }
+ break;
default:
break;
- }
+ }
if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE);
asan_poison_object(vp);
}
- p++;
- }
+ }
}
gc_exit(objspace, gc_enter_event_finalizer, &lock_lev);
- if (heap_pages_deferred_final) {
- finalize_list(objspace, heap_pages_deferred_final);
- }
+ finalize_deferred_heap_pages(objspace);
st_free_table(finalizer_table);
finalizer_table = 0;
ATOMIC_SET(finalizing, 0);
}
-PUREFUNC(static inline int is_id_value(rb_objspace_t *objspace, VALUE ptr));
static inline int
-is_id_value(rb_objspace_t *objspace, VALUE ptr)
-{
- if (!is_pointer_to_heap(objspace, (void *)ptr)) return FALSE;
- if (BUILTIN_TYPE(ptr) > T_FIXNUM) return FALSE;
- if (BUILTIN_TYPE(ptr) == T_ICLASS) return FALSE;
- return TRUE;
-}
-
-static inline int
-heap_is_swept_object(rb_objspace_t *objspace, rb_heap_t *heap, VALUE ptr)
+is_swept_object(rb_objspace_t *objspace, VALUE ptr)
{
struct heap_page *page = GET_HEAP_PAGE(ptr);
return page->flags.before_sweep ? FALSE : TRUE;
}
-static inline int
-is_swept_object(rb_objspace_t *objspace, VALUE ptr)
-{
- if (heap_is_swept_object(objspace, heap_eden, ptr)) {
- return TRUE;
- }
- else {
- return FALSE;
- }
-}
-
/* garbage objects will be collected soon. */
static inline int
is_garbage_object(rb_objspace_t *objspace, VALUE ptr)
{
- if (!is_lazy_sweeping(heap_eden) ||
- is_swept_object(objspace, ptr) ||
- MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr)) {
+ if (!is_lazy_sweeping(objspace) ||
+ is_swept_object(objspace, ptr) ||
+ MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr)) {
- return FALSE;
+ return FALSE;
}
else {
- return TRUE;
+ return TRUE;
}
}
@@ -4283,16 +4617,16 @@ is_live_object(rb_objspace_t *objspace, VALUE ptr)
case T_NONE:
case T_MOVED:
case T_ZOMBIE:
- return FALSE;
+ return FALSE;
default:
break;
}
if (!is_garbage_object(objspace, ptr)) {
- return TRUE;
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -4363,7 +4697,7 @@ id2ref(VALUE objid)
ptr = NUM2PTR(objid);
if (ptr == Qtrue) return Qtrue;
if (ptr == Qfalse) return Qfalse;
- if (ptr == Qnil) return Qnil;
+ if (NIL_P(ptr)) return Qnil;
if (FIXNUM_P(ptr)) return (VALUE)ptr;
if (FLONUM_P(ptr)) return (VALUE)ptr;
@@ -4371,13 +4705,13 @@ id2ref(VALUE objid)
if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
ID symid = ptr / sizeof(RVALUE);
p0 = (void *)ptr;
- if (rb_id2str(symid) == 0)
+ if (!rb_static_id_valid_p(symid))
rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
return ID2SYM(symid);
}
}
- if ((orig = id2ref_obj_tbl(objspace, objid)) != Qundef &&
+ if (!UNDEF_P(orig = id2ref_obj_tbl(objspace, objid)) &&
is_live_object(objspace, orig)) {
if (!rb_multi_ractor_p() || rb_ractor_shareable_p(orig)) {
@@ -4396,6 +4730,7 @@ id2ref(VALUE objid)
}
}
+/* :nodoc: */
static VALUE
os_id2ref(VALUE os, VALUE objid)
{
@@ -4548,135 +4883,134 @@ obj_memsize_of(VALUE obj, int use_all_types)
size_t size = 0;
if (SPECIAL_CONST_P(obj)) {
- return 0;
+ return 0;
}
if (FL_TEST(obj, FL_EXIVAR)) {
- size += rb_generic_ivar_memsize(obj);
+ size += rb_generic_ivar_memsize(obj);
}
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) {
- size += ROBJECT_NUMIV(obj) * sizeof(VALUE);
- }
- break;
+ if (rb_shape_obj_too_complex(obj)) {
+ size += rb_st_memsize(ROBJECT_IV_HASH(obj));
+ }
+ else if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) {
+ size += ROBJECT_IV_CAPACITY(obj) * sizeof(VALUE);
+ }
+ break;
case T_MODULE:
case T_CLASS:
- if (RCLASS_EXT(obj)) {
+ if (RCLASS_EXT(obj)) {
if (RCLASS_M_TBL(obj)) {
size += rb_id_table_memsize(RCLASS_M_TBL(obj));
}
- if (RCLASS_IV_TBL(obj)) {
- size += st_memsize(RCLASS_IV_TBL(obj));
- }
- if (RCLASS_CVC_TBL(obj)) {
- size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
- }
- if (RCLASS_IV_INDEX_TBL(obj)) {
- // TODO: more correct value
- size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
- }
- if (RCLASS(obj)->ptr->iv_tbl) {
- size += st_memsize(RCLASS(obj)->ptr->iv_tbl);
- }
- if (RCLASS(obj)->ptr->const_tbl) {
- size += rb_id_table_memsize(RCLASS(obj)->ptr->const_tbl);
- }
+ // class IV sizes are allocated as powers of two
+ size += SIZEOF_VALUE << bit_length(RCLASS_IV_COUNT(obj));
+ if (RCLASS_CVC_TBL(obj)) {
+ size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
+ }
+ if (RCLASS_EXT(obj)->const_tbl) {
+ size += rb_id_table_memsize(RCLASS_EXT(obj)->const_tbl);
+ }
if (RCLASS_CC_TBL(obj)) {
size += cc_table_memsize(RCLASS_CC_TBL(obj));
}
- size += sizeof(rb_classext_t);
- }
- break;
+ if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
+ size += (RCLASS_SUPERCLASS_DEPTH(obj) + 1) * sizeof(VALUE);
+ }
+#if SIZE_POOL_COUNT == 1
+ size += sizeof(rb_classext_t);
+#endif
+ }
+ break;
case T_ICLASS:
if (RICLASS_OWNS_M_TBL_P(obj)) {
- if (RCLASS_M_TBL(obj)) {
- size += rb_id_table_memsize(RCLASS_M_TBL(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;
+ break;
case T_STRING:
- size += rb_str_memsize(obj);
- break;
+ size += rb_str_memsize(obj);
+ break;
case T_ARRAY:
- size += rb_ary_memsize(obj);
- break;
+ size += rb_ary_memsize(obj);
+ break;
case T_HASH:
if (RHASH_AR_TABLE_P(obj)) {
if (RHASH_AR_TABLE(obj) != NULL) {
size_t rb_hash_ar_table_size(void);
size += rb_hash_ar_table_size();
}
- }
+ }
else {
VM_ASSERT(RHASH_ST_TABLE(obj) != NULL);
size += st_memsize(RHASH_ST_TABLE(obj));
}
- break;
+ break;
case T_REGEXP:
- if (RREGEXP_PTR(obj)) {
- size += onig_memsize(RREGEXP_PTR(obj));
- }
- break;
+ if (RREGEXP_PTR(obj)) {
+ size += onig_memsize(RREGEXP_PTR(obj));
+ }
+ break;
case T_DATA:
- if (use_all_types) size += rb_objspace_data_type_memsize(obj);
- break;
+ if (use_all_types) size += rb_objspace_data_type_memsize(obj);
+ break;
case T_MATCH:
- if (RMATCH(obj)->rmatch) {
+ if (RMATCH(obj)->rmatch) {
struct rmatch *rm = RMATCH(obj)->rmatch;
- size += onig_region_memsize(&rm->regs);
- size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated;
- size += sizeof(struct rmatch);
- }
- break;
+ size += onig_region_memsize(&rm->regs);
+ size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated;
+ size += sizeof(struct rmatch);
+ }
+ break;
case T_FILE:
- if (RFILE(obj)->fptr) {
- size += rb_io_memsize(RFILE(obj)->fptr);
- }
- break;
+ if (RFILE(obj)->fptr) {
+ size += rb_io_memsize(RFILE(obj)->fptr);
+ }
+ break;
case T_RATIONAL:
case T_COMPLEX:
break;
case T_IMEMO:
size += imemo_memsize(obj);
- break;
+ break;
case T_FLOAT:
case T_SYMBOL:
- break;
+ break;
case T_BIGNUM:
- if (!(RBASIC(obj)->flags & BIGNUM_EMBED_FLAG) && BIGNUM_DIGITS(obj)) {
- size += BIGNUM_LEN(obj) * sizeof(BDIGIT);
- }
- break;
+ if (!(RBASIC(obj)->flags & BIGNUM_EMBED_FLAG) && BIGNUM_DIGITS(obj)) {
+ size += BIGNUM_LEN(obj) * sizeof(BDIGIT);
+ }
+ break;
case T_NODE:
- UNEXPECTED_NODE(obj_memsize_of);
- break;
+ UNEXPECTED_NODE(obj_memsize_of);
+ break;
case T_STRUCT:
- if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
- RSTRUCT(obj)->as.heap.ptr) {
- size += sizeof(VALUE) * RSTRUCT_LEN(obj);
- }
- break;
+ if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
+ RSTRUCT(obj)->as.heap.ptr) {
+ size += sizeof(VALUE) * RSTRUCT_LEN(obj);
+ }
+ break;
case T_ZOMBIE:
case T_MOVED:
- case T_PAYLOAD:
- break;
+ break;
default:
- rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)",
- BUILTIN_TYPE(obj), (void*)obj);
+ rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)",
+ BUILTIN_TYPE(obj), (void*)obj);
}
- return size + sizeof(RVALUE);
+ return size + rb_gc_obj_slot_size(obj);
}
size_t
@@ -4726,7 +5060,6 @@ type_sym(size_t type)
COUNT_TYPE(T_ICLASS);
COUNT_TYPE(T_ZOMBIE);
COUNT_TYPE(T_MOVED);
- COUNT_TYPE(T_PAYLOAD);
#undef COUNT_TYPE
default: return SIZET2NUM(type); break;
}
@@ -4788,39 +5121,31 @@ count_objects(int argc, VALUE *argv, VALUE os)
}
for (i = 0; i < heap_allocated_pages; i++) {
- struct heap_page *page = heap_pages_sorted[i];
- RVALUE *p, *pend;
- int stride = 1;
+ struct heap_page *page = heap_pages_sorted[i];
+ short stride = page->slot_size;
- p = page->start; pend = p + page->total_slots;
+ uintptr_t p = (uintptr_t)page->start;
+ uintptr_t pend = p + page->total_slots * stride;
for (;p < pend; p += stride) {
- stride = 1;
VALUE vp = (VALUE)p;
+ GC_ASSERT((NUM_IN_PAGE(vp) * BASE_SLOT_SIZE) % page->slot_size == 0);
- void *poisoned = asan_poisoned_object_p(vp);
- asan_unpoison_object(vp, false);
-#if USE_RVARGC
- if (RB_TYPE_P(vp, T_PAYLOAD)) {
- stride = RPAYLOAD_LEN(vp);
- counts[BUILTIN_TYPE(vp)] += RPAYLOAD_LEN(vp);
- }
- else
-#endif
- if (p->as.basic.flags) {
+ void *poisoned = asan_unpoison_object_temporary(vp);
+ if (RANY(p)->as.basic.flags) {
counts[BUILTIN_TYPE(vp)]++;
- }
- else {
- freed++;
- }
+ }
+ else {
+ freed++;
+ }
if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE);
asan_poison_object(vp);
}
- }
- total += page->total_slots;
+ }
+ total += page->total_slots;
}
- if (hash == Qnil) {
+ if (NIL_P(hash)) {
hash = rb_hash_new();
}
else if (!RHASH_EMPTY_P(hash)) {
@@ -4847,7 +5172,13 @@ count_objects(int argc, VALUE *argv, VALUE os)
static size_t
objspace_available_slots(rb_objspace_t *objspace)
{
- return heap_eden->total_slots + heap_tomb->total_slots;
+ size_t total_slots = 0;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ total_slots += SIZE_POOL_EDEN_HEAP(size_pool)->total_slots;
+ total_slots += SIZE_POOL_TOMB_HEAP(size_pool)->total_slots;
+ }
+ return total_slots;
}
static size_t
@@ -4870,19 +5201,27 @@ gc_setup_mark_bits(struct heap_page *page)
}
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 VALUE gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, size_t slot_size);
-static void
-lock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
-{
#if defined(_WIN32)
- DWORD old_protect;
+enum {HEAP_PAGE_LOCK = PAGE_NOACCESS, HEAP_PAGE_UNLOCK = PAGE_READWRITE};
- if (!VirtualProtect(body, HEAP_PAGE_SIZE, PAGE_NOACCESS, &old_protect)) {
+static BOOL
+protect_page_body(struct heap_page_body *body, DWORD protect)
+{
+ DWORD old_protect;
+ return VirtualProtect(body, HEAP_PAGE_SIZE, protect, &old_protect) != 0;
+}
#else
- if (mprotect(body, HEAP_PAGE_SIZE, PROT_NONE)) {
+enum {HEAP_PAGE_LOCK = PROT_NONE, HEAP_PAGE_UNLOCK = PROT_READ | PROT_WRITE};
+#define protect_page_body(body, protect) !mprotect((body), HEAP_PAGE_SIZE, (protect))
#endif
- rb_bug("Couldn't protect page %p", (void *)body);
+
+static void
+lock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
+{
+ if (!protect_page_body(body, HEAP_PAGE_LOCK)) {
+ rb_bug("Couldn't protect page %p, errno: %s", (void *)body, strerror(errno));
}
else {
gc_report(5, objspace, "Protecting page in move %p\n", (void *)body);
@@ -4892,130 +5231,56 @@ lock_page_body(rb_objspace_t *objspace, struct heap_page_body *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);
+ if (!protect_page_body(body, HEAP_PAGE_UNLOCK)) {
+ rb_bug("Couldn't unprotect page %p, errno: %s", (void *)body, strerror(errno));
}
else {
gc_report(5, objspace, "Unprotecting page in move %p\n", (void *)body);
}
}
-static inline bool
-try_move_in_plane(rb_objspace_t *objspace, rb_heap_t *heap, intptr_t p, bits_t bits, VALUE dest)
+static bool
+try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *free_page, VALUE src)
{
- if (bits) {
- do {
- if (bits & 1) {
- /* We're trying to move "p" */
- objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)p)]++;
-
- if (gc_is_moveable_obj(objspace, (VALUE)p)) {
- /* We were able to move "p" */
- objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)p)]++;
- objspace->rcompactor.total_moved++;
-
- bool from_freelist = false;
-
- if (BUILTIN_TYPE(dest) == T_NONE) {
- from_freelist = true;
- }
+ GC_ASSERT(gc_is_moveable_obj(objspace, src));
- gc_move(objspace, (VALUE)p, dest);
- gc_pin(objspace, (VALUE)p);
- heap->compact_cursor_index = (RVALUE *)p;
- if (from_freelist) {
- FL_SET((VALUE)p, FL_FROM_FREELIST);
- }
-
- return true;
- }
- }
- p += sizeof(RVALUE);
- bits >>= 1;
- } while (bits);
+ struct heap_page *src_page = GET_HEAP_PAGE(src);
+ if (!free_page) {
+ return false;
}
- return false;
-}
+ /* We should return true if either src is successfully moved, or src is
+ * unmoveable. A false return will cause the sweeping cursor to be
+ * incremented to the next page, and src will attempt to move again */
+ GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(src), src));
-static short
-try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, VALUE dest)
-{
- struct heap_page * cursor = heap->compact_cursor;
-
- GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest));
-
- /* T_NONE objects came from the free list. If the object is *not* a
- * T_NONE, it is an object that just got freed but hasn't been
- * added to the freelist yet */
-
- while (1) {
- size_t index;
-
- bits_t *mark_bits = cursor->mark_bits;
- bits_t *pin_bits = cursor->pinned_bits;
- RVALUE * p;
-
- if (heap->compact_cursor_index) {
- index = BITMAP_INDEX(heap->compact_cursor_index);
- p = heap->compact_cursor_index;
- GC_ASSERT(cursor == GET_HEAP_PAGE(p));
- }
- else {
- index = 0;
- p = cursor->start;
- }
-
- bits_t bits = mark_bits[index] & ~pin_bits[index];
-
- bits >>= NUM_IN_PAGE(p);
- if (try_move_in_plane(objspace, heap, (intptr_t)p, bits, dest)) return 1;
-
- if (index == 0) {
- p = cursor->start + (BITS_BITLENGTH - NUM_IN_PAGE(cursor->start));
- }
- else {
- p = cursor->start + (BITS_BITLENGTH - NUM_IN_PAGE(cursor->start)) + (BITS_BITLENGTH * index);
- }
-
- /* Find an object to move and move it. Movable objects must be
- * marked, so we iterate using the marking bitmap */
- for (size_t i = index + 1; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
- bits_t bits = mark_bits[i] & ~pin_bits[i];
- if (try_move_in_plane(objspace, heap, (intptr_t)p, bits, dest)) return 1;
- p += BITS_BITLENGTH;
- }
-
- /* We couldn't find a movable object on the compact cursor, so lets
- * move to the next page (previous page since we are traveling in the
- * opposite direction of the sweep cursor) and look there. */
-
- struct heap_page * next;
-
- next = list_prev(&heap->pages, cursor, page_node);
-
- /* Protect the current cursor since it probably has T_MOVED slots. */
- lock_page_body(objspace, GET_PAGE_BODY(cursor->start));
+ asan_unlock_freelist(free_page);
+ VALUE dest = (VALUE)free_page->freelist;
+ asan_lock_freelist(free_page);
+ asan_unpoison_object(dest, false);
+ if (!dest) {
+ /* if we can't get something from the freelist then the page must be
+ * full */
+ return false;
+ }
+ free_page->freelist = RANY(dest)->as.free.next;
- heap->compact_cursor = next;
- heap->compact_cursor_index = 0;
- cursor = next;
+ GC_ASSERT(RB_BUILTIN_TYPE(dest) == T_NONE);
- // 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;
- }
+ if (src_page->slot_size > free_page->slot_size) {
+ objspace->rcompactor.moved_down_count_table[BUILTIN_TYPE(src)]++;
+ }
+ else if (free_page->slot_size > src_page->slot_size) {
+ objspace->rcompactor.moved_up_count_table[BUILTIN_TYPE(src)]++;
}
+ objspace->rcompactor.moved_count_table[BUILTIN_TYPE(src)]++;
+ objspace->rcompactor.total_moved++;
- return 0;
+ gc_move(objspace, src, dest, src_page->slot_size, free_page->slot_size);
+ gc_pin(objspace, src);
+ free_page->free_slots--;
+
+ return true;
}
static void
@@ -5025,26 +5290,52 @@ gc_unprotect_pages(rb_objspace_t *objspace, rb_heap_t *heap)
while (cursor) {
unlock_page_body(objspace, GET_PAGE_BODY(cursor->start));
- cursor = list_next(&heap->pages, cursor, page_node);
+ cursor = ccan_list_next(&heap->pages, cursor, page_node);
}
}
-static void gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap);
+static void gc_update_references(rb_objspace_t * objspace);
static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);
+#ifndef GC_CAN_COMPILE_COMPACTION
+#if defined(__wasi__) /* WebAssembly doesn't support signals */
+# define GC_CAN_COMPILE_COMPACTION 0
+#else
+# define GC_CAN_COMPILE_COMPACTION 1
+#endif
+#endif
+
+#if defined(__MINGW32__) || defined(_WIN32)
+# define GC_COMPACTION_SUPPORTED 1
+#else
+/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
+ * the read barrier, so we must disable compaction. */
+# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && HEAP_PAGE_ALLOC_USE_MMAP)
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
static void
-read_barrier_handler(intptr_t address)
+read_barrier_handler(uintptr_t original_address)
{
VALUE obj;
rb_objspace_t * objspace = &rb_objspace;
- address -= address % sizeof(RVALUE);
+ /* Calculate address aligned to slots. */
+ uintptr_t address = original_address - (original_address % BASE_SLOT_SIZE);
obj = (VALUE)address;
+ struct heap_page_body *page_body = GET_PAGE_BODY(obj);
+
+ /* If the page_body is NULL, then mprotect cannot handle it and will crash
+ * with "Cannot allocate memory". */
+ if (page_body == NULL) {
+ rb_bug("read_barrier_handler: segmentation fault at %p", (void *)original_address);
+ }
+
RB_VM_LOCK_ENTER();
{
- unlock_page_body(objspace, GET_PAGE_BODY(obj));
+ unlock_page_body(objspace, page_body);
objspace->profile.read_barrier_faults++;
@@ -5052,8 +5343,21 @@ read_barrier_handler(intptr_t address)
}
RB_VM_LOCK_LEAVE();
}
+#endif
-#if defined(_WIN32)
+#if !GC_CAN_COMPILE_COMPACTION
+static void
+uninstall_handlers(void)
+{
+ /* no-op */
+}
+
+static void
+install_handlers(void)
+{
+ /* no-op */
+}
+#elif defined(_WIN32)
static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;
typedef void (*signal_handler)(int);
static signal_handler old_sigsegv_handler;
@@ -5067,7 +5371,7 @@ read_barrier_signal(EXCEPTION_POINTERS * info)
* 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]);
+ read_barrier_handler((uintptr_t)info->ExceptionRecord->ExceptionInformation[1]);
return EXCEPTION_CONTINUE_EXECUTION;
}
else {
@@ -5095,6 +5399,38 @@ install_handlers(void)
static struct sigaction old_sigbus_handler;
static struct sigaction old_sigsegv_handler;
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+static exception_mask_t old_exception_masks[32];
+static mach_port_t old_exception_ports[32];
+static exception_behavior_t old_exception_behaviors[32];
+static thread_state_flavor_t old_exception_flavors[32];
+static mach_msg_type_number_t old_exception_count;
+
+static void
+disable_mach_bad_access_exc(void)
+{
+ old_exception_count = sizeof(old_exception_masks) / sizeof(old_exception_masks[0]);
+ task_swap_exception_ports(
+ mach_task_self(), EXC_MASK_BAD_ACCESS,
+ MACH_PORT_NULL, EXCEPTION_DEFAULT, 0,
+ old_exception_masks, &old_exception_count,
+ old_exception_ports, old_exception_behaviors, old_exception_flavors
+ );
+}
+
+static void
+restore_mach_bad_access_exc(void)
+{
+ for (mach_msg_type_number_t i = 0; i < old_exception_count; i++) {
+ task_set_exception_ports(
+ mach_task_self(),
+ old_exception_masks[i], old_exception_ports[i],
+ old_exception_behaviors[i], old_exception_flavors[i]
+ );
+ }
+}
+#endif
+
static void
read_barrier_signal(int sig, siginfo_t * info, void * data)
{
@@ -5109,11 +5445,16 @@ read_barrier_signal(int sig, siginfo_t * info, void * data)
sigaddset(&set, SIGBUS);
sigaddset(&set, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &set, &prev_set);
-
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ disable_mach_bad_access_exc();
+#endif
// run handler
- read_barrier_handler((intptr_t)info->si_addr);
+ read_barrier_handler((uintptr_t)info->si_addr);
// reset SEGV/BUS handlers
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ restore_mach_bad_access_exc();
+#endif
sigaction(SIGBUS, &prev_sigbus, NULL);
sigaction(SIGSEGV, &prev_sigsegv, NULL);
sigprocmask(SIG_SETMASK, &prev_set, NULL);
@@ -5122,6 +5463,9 @@ read_barrier_signal(int sig, siginfo_t * info, void * data)
static void
uninstall_handlers(void)
{
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ restore_mach_bad_access_exc();
+#endif
sigaction(SIGBUS, &old_sigbus_handler, NULL);
sigaction(SIGSEGV, &old_sigsegv_handler, NULL);
}
@@ -5137,6 +5481,9 @@ install_handlers(void)
sigaction(SIGBUS, &action, &old_sigbus_handler);
sigaction(SIGSEGV, &action, &old_sigsegv_handler);
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ disable_mach_bad_access_exc();
+#endif
}
#endif
@@ -5177,12 +5524,17 @@ check_stack_for_moved(rb_objspace_t *objspace)
each_machine_stack_value(ec, revert_machine_stack_references);
}
+static void gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode);
+
static void
-gc_compact_finish(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_compact_finish(rb_objspace_t *objspace)
{
- GC_ASSERT(heap->sweeping_page == heap->compact_cursor);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ gc_unprotect_pages(objspace, heap);
+ }
- gc_unprotect_pages(objspace, heap);
uninstall_handlers();
/* The mutator is allowed to run during incremental sweeping. T_MOVED
@@ -5192,15 +5544,21 @@ gc_compact_finish(rb_objspace_t *objspace, rb_heap_t *heap)
* 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;
+ gc_update_references(objspace);
objspace->profile.compact_count++;
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ heap->compact_cursor = NULL;
+ heap->free_pages = NULL;
+ heap->compact_cursor_index = 0;
+ }
+
if (gc_prof_enabled(objspace)) {
gc_profile_record *record = gc_prof_record(objspace);
record->moved_objects = objspace->rcompactor.total_moved - record->moved_objects;
}
- rb_clear_constant_cache();
objspace->flags.during_compacting = FALSE;
}
@@ -5212,102 +5570,17 @@ struct gc_sweep_context {
};
static inline void
-gc_fill_swept_page_plane(rb_objspace_t *objspace, rb_heap_t *heap, intptr_t p, bits_t bitset, bool * finished_compacting, struct gc_sweep_context *ctx)
-{
- struct heap_page * sweep_page = ctx->page;
-
- if (bitset) {
- do {
- if (bitset & 1) {
- VALUE dest = (VALUE)p;
-
- GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(dest), dest));
- GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest));
-
- CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(dest), dest);
-
- if (*finished_compacting) {
- if (BUILTIN_TYPE(dest) == T_NONE) {
- ctx->empty_slots++;
- }
- else {
- ctx->freed_slots++;
- }
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)dest, sizeof(RVALUE));
- heap_page_add_freeobj(objspace, sweep_page, dest);
- }
- else {
- /* Zombie slots don't get marked, but we can't reuse
- * their memory until they have their finalizers run.*/
- if (BUILTIN_TYPE(dest) != T_ZOMBIE) {
- if (!try_move(objspace, heap, sweep_page, dest)) {
- *finished_compacting = true;
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- gc_report(5, objspace, "Quit compacting, couldn't find an object to move\n");
- if (BUILTIN_TYPE(dest) == T_NONE) {
- ctx->empty_slots++;
- }
- else {
- ctx->freed_slots++;
- }
- heap_page_add_freeobj(objspace, sweep_page, dest);
- gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(dest));
- }
- else {
- //moved_slots++;
- }
- }
- }
- }
- p += sizeof(RVALUE);
- bitset >>= 1;
- } while (bitset);
- }
-}
-
-static bool
-gc_fill_swept_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, struct gc_sweep_context *ctx)
-{
- /* Find any pinned but not marked objects and try to fill those slots */
- bool finished_compacting = false;
- bits_t *mark_bits, *pin_bits;
- bits_t bitset;
- RVALUE *p;
-
- mark_bits = sweep_page->mark_bits;
- pin_bits = sweep_page->pinned_bits;
-
- p = sweep_page->start;
-
- struct heap_page * cursor = heap->compact_cursor;
-
- unlock_page_body(objspace, GET_PAGE_BODY(cursor->start));
-
- /* *Want to move* objects are pinned but not marked. */
- bitset = pin_bits[0] & ~mark_bits[0];
- bitset >>= NUM_IN_PAGE(p); // Skip header / dead space bits
- gc_fill_swept_page_plane(objspace ,heap, (intptr_t)p, bitset, &finished_compacting, ctx);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p));
-
- for (int i = 1; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
- /* *Want to move* objects are pinned but not marked. */
- bitset = pin_bits[i] & ~mark_bits[i];
- gc_fill_swept_page_plane(objspace ,heap, (intptr_t)p, bitset, &finished_compacting, ctx);
- p += BITS_BITLENGTH;
- }
-
- lock_page_body(objspace, GET_PAGE_BODY(heap->compact_cursor->start));
-
- return finished_compacting;
-}
-
-static inline void
-gc_plane_sweep(rb_objspace_t *objspace, rb_heap_t *heap, intptr_t p, bits_t bitset, struct gc_sweep_context *ctx)
+gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct gc_sweep_context *ctx)
{
struct heap_page * sweep_page = ctx->page;
+ short slot_size = sweep_page->slot_size;
+ short slot_bits = slot_size / BASE_SLOT_SIZE;
+ GC_ASSERT(slot_bits > 0);
do {
VALUE vp = (VALUE)p;
+ GC_ASSERT(vp % BASE_SLOT_SIZE == 0);
+
asan_unpoison_object(vp, false);
if (bitset & 1) {
switch (BUILTIN_TYPE(vp)) {
@@ -5320,52 +5593,18 @@ gc_plane_sweep(rb_objspace_t *objspace, rb_heap_t *heap, intptr_t p, bits_t bits
}
#endif
if (obj_free(objspace, vp)) {
- ctx->final_slots++;
+ // always add free slots back to the swept pages freelist,
+ // so that if we're comapacting, we can re-use the slots
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
+ ctx->freed_slots++;
}
else {
- if (heap->compact_cursor) {
- /* We *want* to fill this slot */
- MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(vp), vp);
- }
- else {
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- heap_page_add_freeobj(objspace, sweep_page, vp);
- gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
- ctx->freed_slots++;
- }
-
+ ctx->final_slots++;
}
break;
- /* minor cases */
- case T_PAYLOAD:
- {
- int plen = RPAYLOAD_LEN(vp);
- ctx->freed_slots += plen;
-
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)vp, sizeof(RVALUE));
- heap_page_add_freeobj(objspace, sweep_page, vp);
-
- // This loop causes slots *following this slot* to be marked as
- // T_NONE. On the next iteration of this sweep loop, the T_NONE slots
- // can be double counted. Mutating the bit plane is difficult because it's
- // copied to a local variable. So we would need special logic to mutate
- // local bitmap plane (stored in `bitset`) plane, versus T_PAYLOAD objects that span
- // bitplanes. (Imagine a T_PAYLOAD at positions 0-3 versus positions 62-65,
- // their mark bits would be on different planes. We would have to mutate only `bitset`
- // for the first case, but `bitset` and `bits[i+1]` for the second
- for (int i = 1; i < plen; i++) {
- VALUE pbody = vp + i * sizeof(RVALUE);
-
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)pbody, sizeof(RVALUE));
- heap_page_add_freeobj(objspace, sweep_page, pbody);
-
- // Lets set a bit on the object so that the T_NONE branch
- // will know to avoid double counting this slot.
- FL_SET(pbody, FL_FROM_PAYLOAD);
- }
- }
- break;
case T_MOVED:
if (objspace->flags.during_compacting) {
/* The sweep cursor shouldn't have made it to any
@@ -5376,100 +5615,71 @@ gc_plane_sweep(rb_objspace_t *objspace, rb_heap_t *heap, intptr_t p, bits_t bits
rb_bug("T_MOVED shouldn't be seen until compaction is finished\n");
}
gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
- if (FL_TEST(vp, FL_FROM_FREELIST)) {
- ctx->empty_slots++;
- }
- else {
- ctx->freed_slots++;
- }
+ ctx->empty_slots++;
heap_page_add_freeobj(objspace, sweep_page, vp);
break;
case T_ZOMBIE:
/* already counted */
break;
case T_NONE:
- if (heap->compact_cursor) {
- /* We *want* to fill this slot */
- MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(vp), vp);
- }
- else {
- // This slot came from a T_PAYLOAD object and
- // has already been counted
- if (FL_TEST(vp, FL_FROM_PAYLOAD)) {
- FL_UNSET(vp, FL_FROM_PAYLOAD);
- }
- else {
- ctx->empty_slots++; /* already freed */
- }
- }
+ ctx->empty_slots++; /* already freed */
break;
}
}
- p += sizeof(RVALUE);
- bitset >>= 1;
+ p += slot_size;
+ bitset >>= slot_bits;
} while (bitset);
}
-static inline int
-gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page)
+static inline void
+gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context *ctx)
{
- int i;
- struct gc_sweep_context ctx;
-
- ctx.page = sweep_page;
- ctx.final_slots = 0;
- ctx.freed_slots = 0;
- ctx.empty_slots = 0;
+ struct heap_page *sweep_page = ctx->page;
+ GC_ASSERT(SIZE_POOL_EDEN_HEAP(sweep_page->size_pool) == heap);
- RVALUE *p;
+ uintptr_t p;
bits_t *bits, bitset;
gc_report(2, objspace, "page_sweep: start.\n");
- if (heap->compact_cursor) {
- if (sweep_page == heap->compact_cursor) {
- /* The compaction cursor and sweep page met, so we need to quit compacting */
- gc_report(5, objspace, "Quit compacting, mark and compact cursor met\n");
- gc_compact_finish(objspace, 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*));
- }
+#if RGENGC_CHECK_MODE
+ if (!objspace->flags.immediate_sweep) {
+ GC_ASSERT(sweep_page->flags.before_sweep == TRUE);
}
-
+#endif
sweep_page->flags.before_sweep = FALSE;
+ sweep_page->free_slots = 0;
- p = sweep_page->start;
+ p = (uintptr_t)sweep_page->start;
bits = sweep_page->mark_bits;
- int out_of_range_bits = (NUM_IN_PAGE(p) + sweep_page->total_slots) % BITS_BITLENGTH;
+ int page_rvalue_count = sweep_page->total_slots * (sweep_page->slot_size / BASE_SLOT_SIZE);
+ int out_of_range_bits = (NUM_IN_PAGE(p) + page_rvalue_count) % BITS_BITLENGTH;
if (out_of_range_bits != 0) { // sizeof(RVALUE) == 64
- bits[BITMAP_INDEX(p) + sweep_page->total_slots / BITS_BITLENGTH] |= ~(((bits_t)1 << out_of_range_bits) - 1);
+ bits[BITMAP_INDEX(p) + page_rvalue_count / BITS_BITLENGTH] |= ~(((bits_t)1 << out_of_range_bits) - 1);
}
+ /* The last bitmap plane may not be used if the last plane does not
+ * have enough space for the slot_size. In that case, the last plane must
+ * be skipped since none of the bits will be set. */
+ int bitmap_plane_count = CEILDIV(NUM_IN_PAGE(p) + page_rvalue_count, BITS_BITLENGTH);
+ GC_ASSERT(bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT - 1 ||
+ bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT);
+
// Skip out of range slots at the head of the page
bitset = ~bits[0];
bitset >>= NUM_IN_PAGE(p);
if (bitset) {
- gc_plane_sweep(objspace, heap, (intptr_t)p, bitset, &ctx);
+ gc_sweep_plane(objspace, heap, p, bitset, ctx);
}
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p));
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
- for (i=1; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
+ for (int i = 1; i < bitmap_plane_count; i++) {
bitset = ~bits[i];
if (bitset) {
- gc_plane_sweep(objspace, heap, (intptr_t)p, bitset, &ctx);
- }
- p += BITS_BITLENGTH;
- }
-
- if (heap->compact_cursor) {
- if (gc_fill_swept_page(objspace, heap, sweep_page, &ctx)) {
- gc_compact_finish(objspace, heap);
+ gc_sweep_plane(objspace, heap, p, bitset, ctx);
}
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
}
if (!heap->compact_cursor) {
@@ -5478,55 +5688,59 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
#if GC_PROFILE_MORE_DETAIL
if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- record->removing_objects += ctx.final_slots + ctx.freed_slots;
- record->empty_objects += ctx.empty_slots;
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->removing_objects += ctx->final_slots + ctx->freed_slots;
+ record->empty_objects += ctx->empty_slots;
}
#endif
- if (0) fprintf(stderr, "gc_page_sweep(%"PRIdSIZE"): total_slots: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n",
- rb_gc_count(),
- sweep_page->total_slots,
- ctx.freed_slots, ctx.empty_slots, ctx.final_slots);
+ if (0) fprintf(stderr, "gc_sweep_page(%"PRIdSIZE"): total_slots: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n",
+ rb_gc_count(),
+ sweep_page->total_slots,
+ ctx->freed_slots, ctx->empty_slots, ctx->final_slots);
- sweep_page->free_slots = ctx.freed_slots + ctx.empty_slots;
- objspace->profile.total_freed_objects += ctx.freed_slots;
+ sweep_page->free_slots += ctx->freed_slots + ctx->empty_slots;
+ objspace->profile.total_freed_objects += ctx->freed_slots;
if (heap_pages_deferred_final && !finalizing) {
rb_thread_t *th = GET_THREAD();
if (th) {
- gc_finalize_deferred_register(objspace);
+ gc_finalize_deferred_register(objspace);
}
}
#if RGENGC_CHECK_MODE
short freelist_len = 0;
+ asan_unlock_freelist(sweep_page);
RVALUE *ptr = sweep_page->freelist;
while (ptr) {
freelist_len++;
ptr = ptr->as.free.next;
}
+ asan_lock_freelist(sweep_page);
if (freelist_len != sweep_page->free_slots) {
rb_bug("inconsistent freelist length: expected %d but was %d", sweep_page->free_slots, freelist_len);
}
#endif
gc_report(2, objspace, "page_sweep: end.\n");
-
- return ctx.freed_slots + ctx.empty_slots;
}
+#if !USE_RVARGC
/* allocate additional minimum page to work */
static void
-gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
- if (!heap->free_pages && heap_increment(objspace, heap) == FALSE) {
- /* there is no free after page_sweep() */
- heap_allocatable_pages_set(objspace, 1);
- if (!heap_increment(objspace, heap)) { /* can't allocate additional free objects */
- rb_memerror();
- }
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ if (!heap->free_pages && heap_increment(objspace, size_pool, heap) == FALSE) {
+ /* there is no free after page_sweep() */
+ size_pool_allocatable_pages_set(objspace, size_pool, 1);
+ if (!heap_increment(objspace, size_pool, heap)) { /* can't allocate additional free objects */
+ rb_memerror();
+ }
+ }
}
}
+#endif
static const char *
gc_mode_name(enum gc_mode mode)
@@ -5535,6 +5749,7 @@ gc_mode_name(enum gc_mode mode)
case gc_mode_none: return "none";
case gc_mode_marking: return "marking";
case gc_mode_sweeping: return "sweeping";
+ case gc_mode_compacting: return "compacting";
default: rb_bug("gc_mode_name: unknown mode: %d", (int)mode);
}
}
@@ -5547,7 +5762,8 @@ gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode)
switch (prev_mode) {
case gc_mode_none: GC_ASSERT(mode == gc_mode_marking); break;
case gc_mode_marking: GC_ASSERT(mode == gc_mode_sweeping); break;
- case gc_mode_sweeping: GC_ASSERT(mode == gc_mode_none); break;
+ case gc_mode_sweeping: GC_ASSERT(mode == gc_mode_none || mode == gc_mode_compacting); break;
+ case gc_mode_compacting: GC_ASSERT(mode == gc_mode_none); break;
}
#endif
if (0) fprintf(stderr, "gc_mode_transition: %s->%s\n", gc_mode_name(gc_mode(objspace)), gc_mode_name(mode));
@@ -5555,13 +5771,44 @@ gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode)
}
static void
+heap_page_freelist_append(struct heap_page *page, RVALUE *freelist)
+{
+ if (freelist) {
+ asan_unlock_freelist(page);
+ if (page->freelist) {
+ RVALUE *p = page->freelist;
+ asan_unpoison_object((VALUE)p, false);
+ while (p->as.free.next) {
+ RVALUE *prev = p;
+ p = p->as.free.next;
+ asan_poison_object((VALUE)prev);
+ asan_unpoison_object((VALUE)p, false);
+ }
+ p->as.free.next = freelist;
+ asan_poison_object((VALUE)p);
+ }
+ else {
+ page->freelist = freelist;
+ }
+ asan_lock_freelist(page);
+ }
+}
+
+static void
gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
{
- heap->sweeping_page = list_top(&heap->pages, struct heap_page, page_node);
+ heap->sweeping_page = ccan_list_top(&heap->pages, struct heap_page, page_node);
heap->free_pages = NULL;
#if GC_ENABLE_INCREMENTAL_MARK
heap->pooled_pages = NULL;
#endif
+ if (!objspace->flags.immediate_sweep) {
+ struct heap_page *page = NULL;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->flags.before_sweep = TRUE;
+ }
+ }
}
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
@@ -5571,18 +5818,98 @@ static void
gc_sweep_start(rb_objspace_t *objspace)
{
gc_mode_transition(objspace, gc_mode_sweeping);
- gc_sweep_start_heap(objspace, heap_eden);
#if GC_ENABLE_INCREMENTAL_MARK
objspace->rincgc.pooled_slots = 0;
#endif
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+
+ gc_sweep_start_heap(objspace, heap);
+
+#if USE_RVARGC
+ /* We should call gc_sweep_finish_size_pool for size pools with no pages. */
+ if (heap->sweeping_page == NULL) {
+ GC_ASSERT(heap->total_pages == 0);
+ GC_ASSERT(heap->total_slots == 0);
+ gc_sweep_finish_size_pool(objspace, size_pool);
+ }
+#endif
+ }
+
rb_ractor_t *r = NULL;
- list_for_each(&GET_VM()->ractor.set, r, vmlr_node) {
+ ccan_list_for_each(&GET_VM()->ractor.set, r, vmlr_node) {
rb_gc_ractor_newobj_cache_clear(&r->newobj_cache);
}
}
+#if USE_RVARGC
+static void
+gc_sweep_finish_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
+{
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ size_t total_slots = heap->total_slots + SIZE_POOL_TOMB_HEAP(size_pool)->total_slots;
+ size_t total_pages = heap->total_pages + SIZE_POOL_TOMB_HEAP(size_pool)->total_pages;
+ size_t swept_slots = size_pool->freed_slots + size_pool->empty_slots;
+
+ size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio);
+
+ /* If we don't have enough slots and we have pages on the tomb heap, move
+ * pages from the tomb heap to the eden heap. This may prevent page
+ * creation thrashing (frequently allocating and deallocting pages) and
+ * GC thrashing (running GC more frequently than required). */
+ struct heap_page *resurrected_page;
+ while ((swept_slots < min_free_slots || swept_slots < gc_params.heap_init_slots) &&
+ (resurrected_page = heap_page_resurrect(objspace, size_pool))) {
+ swept_slots += resurrected_page->free_slots;
+
+ heap_add_page(objspace, size_pool, heap, resurrected_page);
+ heap_add_freepage(heap, resurrected_page);
+ }
+
+ /* Some size pools may have very few pages (or even no pages). These size pools
+ * should still have allocatable pages. */
+ if (min_free_slots < gc_params.heap_init_slots && swept_slots < gc_params.heap_init_slots) {
+ int multiple = size_pool->slot_size / BASE_SLOT_SIZE;
+ size_t extra_slots = gc_params.heap_init_slots - swept_slots;
+ size_t extend_page_count = CEILDIV(extra_slots * multiple, HEAP_PAGE_OBJ_LIMIT);
+ if (extend_page_count > size_pool->allocatable_pages) {
+ size_pool_allocatable_pages_set(objspace, size_pool, extend_page_count);
+ }
+ }
+
+ if (swept_slots < min_free_slots) {
+ bool grow_heap = is_full_marking(objspace);
+
+ if (!is_full_marking(objspace)) {
+ /* The heap is a growth heap if it freed more slots than had empty
+ * slots and used up all of its allocatable pages. */
+ bool is_growth_heap = (size_pool->empty_slots == 0 ||
+ size_pool->freed_slots > size_pool->empty_slots) &&
+ size_pool->allocatable_pages == 0;
+
+ if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
+ grow_heap = TRUE;
+ }
+ else if (is_growth_heap) { /* Only growth heaps are allowed to start a major GC. */
+ objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE;
+ size_pool->force_major_gc_count++;
+ }
+ }
+
+ if (grow_heap) {
+ size_t extend_page_count = heap_extend_pages(objspace, size_pool, swept_slots, total_slots, total_pages);
+
+ if (extend_page_count > size_pool->allocatable_pages) {
+ size_pool_allocatable_pages_set(objspace, size_pool, extend_page_count);
+ }
+ }
+ }
+}
+#endif
+
static void
gc_sweep_finish(rb_objspace_t *objspace)
{
@@ -5591,28 +5918,55 @@ gc_sweep_finish(rb_objspace_t *objspace)
gc_prof_set_heap_info(objspace);
heap_pages_free_unused_pages(objspace);
- /* if heap_pages has unused pages, then assign them to increment */
- if (heap_allocatable_pages < heap_tomb->total_pages) {
- heap_allocatable_pages_set(objspace, heap_tomb->total_pages);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+
+ /* if heap_pages has unused pages, then assign them to increment */
+ size_t tomb_pages = SIZE_POOL_TOMB_HEAP(size_pool)->total_pages;
+ if (size_pool->allocatable_pages < tomb_pages) {
+ size_pool->allocatable_pages = tomb_pages;
+ }
+
+#if USE_RVARGC
+ size_pool->freed_slots = 0;
+ size_pool->empty_slots = 0;
+
+#if GC_ENABLE_INCREMENTAL_MARK
+ if (!will_be_incremental_marking(objspace)) {
+ rb_heap_t *eden_heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ struct heap_page *end_page = eden_heap->free_pages;
+ if (end_page) {
+ while (end_page->free_next) end_page = end_page->free_next;
+ end_page->free_next = eden_heap->pooled_pages;
+ }
+ else {
+ eden_heap->free_pages = eden_heap->pooled_pages;
+ }
+ eden_heap->pooled_pages = NULL;
+ objspace->rincgc.pooled_slots = 0;
+ }
+#endif
+#endif
}
+ heap_pages_expand_sorted(objspace);
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_SWEEP, 0);
gc_mode_transition(objspace, gc_mode_none);
-
-#if RGENGC_CHECK_MODE >= 2
- gc_verify_internal_consistency(objspace);
-#endif
}
static int
-gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_sweep_step(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
struct heap_page *sweep_page = heap->sweeping_page;
- int unlink_limit = 3;
+ int unlink_limit = GC_SWEEP_PAGES_FREEABLE_PER_STEP;
#if GC_ENABLE_INCREMENTAL_MARK
int swept_slots = 0;
+#if USE_RVARGC
+ bool need_pool = TRUE;
+#else
int need_pool = will_be_incremental_marking(objspace) ? TRUE : FALSE;
+#endif
gc_report(2, objspace, "gc_sweep_step (need_pool: %d)\n", need_pool);
#else
@@ -5626,79 +5980,118 @@ 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);
-
- if (sweep_page->final_slots + free_slots == sweep_page->total_slots &&
- heap_pages_freeable_pages > 0 &&
- unlink_limit > 0) {
- heap_pages_freeable_pages--;
- unlink_limit--;
- /* there are no living objects -> move this page to tomb heap */
- heap_unlink_page(objspace, heap, sweep_page);
- heap_add_page(objspace, heap_tomb, sweep_page);
- }
- else if (free_slots > 0) {
+ RUBY_DEBUG_LOG("sweep_page:%p", (void *)sweep_page);
+
+ struct gc_sweep_context ctx = {
+ .page = sweep_page,
+ .final_slots = 0,
+ .freed_slots = 0,
+ .empty_slots = 0,
+ };
+ gc_sweep_page(objspace, heap, &ctx);
+ int free_slots = ctx.freed_slots + ctx.empty_slots;
+
+ heap->sweeping_page = ccan_list_next(&heap->pages, sweep_page, page_node);
+
+ if (sweep_page->final_slots + free_slots == sweep_page->total_slots &&
+ heap_pages_freeable_pages > 0 &&
+ unlink_limit > 0) {
+ heap_pages_freeable_pages--;
+ unlink_limit--;
+ /* there are no living objects -> move this page to tomb heap */
+ heap_unlink_page(objspace, heap, sweep_page);
+ heap_add_page(objspace, size_pool, SIZE_POOL_TOMB_HEAP(size_pool), sweep_page);
+ }
+ else if (free_slots > 0) {
+#if USE_RVARGC
+ size_pool->freed_slots += ctx.freed_slots;
+ size_pool->empty_slots += ctx.empty_slots;
+#endif
+
#if GC_ENABLE_INCREMENTAL_MARK
- if (need_pool) {
+ if (need_pool) {
heap_add_poolpage(objspace, heap, sweep_page);
need_pool = FALSE;
- }
- else {
+ }
+ else {
heap_add_freepage(heap, sweep_page);
swept_slots += free_slots;
- if (swept_slots > 2048) {
+ if (swept_slots > GC_INCREMENTAL_SWEEP_SLOT_COUNT) {
break;
}
- }
+ }
#else
heap_add_freepage(heap, sweep_page);
break;
#endif
- }
- else {
- sweep_page->free_next = NULL;
- }
+ }
+ else {
+ sweep_page->free_next = NULL;
+ }
} while ((sweep_page = heap->sweeping_page));
if (!heap->sweeping_page) {
- gc_sweep_finish(objspace);
+#if USE_RVARGC
+ gc_sweep_finish_size_pool(objspace, size_pool);
+#endif
+
+ if (!has_sweeping_pages(objspace)) {
+ gc_sweep_finish(objspace);
+ }
}
#if GC_ENABLE_LAZY_SWEEP
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;
}
static void
gc_sweep_rest(rb_objspace_t *objspace)
{
- rb_heap_t *heap = heap_eden; /* lazy sweep only for eden */
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
- while (has_sweeping_pages(heap)) {
- gc_sweep_step(objspace, heap);
+ while (SIZE_POOL_EDEN_HEAP(size_pool)->sweeping_page) {
+ gc_sweep_step(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool));
+ }
}
}
static void
-gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_sweep_continue(rb_objspace_t *objspace, rb_size_pool_t *sweep_size_pool, rb_heap_t *heap)
{
GC_ASSERT(dont_gc_val() == FALSE);
if (!GC_ENABLE_LAZY_SWEEP) return;
unsigned int lock_lev;
gc_enter(objspace, gc_enter_event_sweep_continue, &lock_lev);
- gc_sweep_step(objspace, heap);
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ if (!gc_sweep_step(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool))) {
+#if USE_RVARGC
+ /* sweep_size_pool requires a free slot but sweeping did not yield any. */
+ if (size_pool == sweep_size_pool) {
+ if (size_pool->allocatable_pages > 0) {
+ heap_increment(objspace, size_pool, heap);
+ }
+ else {
+ /* Not allowed to create a new page so finish sweeping. */
+ gc_sweep_rest(objspace);
+ break;
+ }
+ }
+#endif
+ }
+ }
+
gc_exit(objspace, gc_enter_event_sweep_continue, &lock_lev);
}
static void
-invalidate_moved_plane(rb_objspace_t *objspace, intptr_t p, bits_t bitset, struct gc_sweep_context *ctx)
+invalidate_moved_plane(rb_objspace_t *objspace, struct heap_page *page, uintptr_t p, bits_t bitset)
{
if (bitset) {
do {
@@ -5714,24 +6107,29 @@ invalidate_moved_plane(rb_objspace_t *objspace, intptr_t p, bits_t bitset, struc
object = rb_gc_location(forwarding_object);
- if (FL_TEST(forwarding_object, FL_FROM_FREELIST)) {
- ctx->empty_slots++; /* already freed */
- }
- else {
- ctx->freed_slots++;
+ shape_id_t original_shape_id = 0;
+ if (RB_TYPE_P(object, T_OBJECT)) {
+ original_shape_id = RMOVED(forwarding_object)->original_shape_id;
}
- gc_move(objspace, object, forwarding_object);
+ gc_move(objspace, object, forwarding_object, GET_HEAP_PAGE(object)->slot_size, page->slot_size);
/* forwarding_object is now our actual object, and "object"
* is the free slot for the original page */
- heap_page_add_freeobj(objspace, GET_HEAP_PAGE(object), object);
+
+ if (original_shape_id) {
+ ROBJECT_SET_SHAPE_ID(forwarding_object, original_shape_id);
+ }
+
+ struct heap_page *orig_page = GET_HEAP_PAGE(object);
+ orig_page->free_slots++;
+ heap_page_add_freeobj(objspace, orig_page, object);
GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(forwarding_object), forwarding_object));
GC_ASSERT(BUILTIN_TYPE(forwarding_object) != T_MOVED);
GC_ASSERT(BUILTIN_TYPE(forwarding_object) != T_NONE);
}
}
- p += sizeof(RVALUE);
+ p += BASE_SLOT_SIZE;
bitset >>= 1;
} while (bitset);
}
@@ -5743,43 +6141,43 @@ invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page)
int i;
bits_t *mark_bits, *pin_bits;
bits_t bitset;
- RVALUE *p;
mark_bits = page->mark_bits;
pin_bits = page->pinned_bits;
- p = page->start;
-
- struct gc_sweep_context ctx;
- ctx.page = page;
- ctx.final_slots = 0;
- ctx.freed_slots = 0;
- ctx.empty_slots = 0;
+ uintptr_t p = page->start;
// Skip out of range slots at the head of the page
bitset = pin_bits[0] & ~mark_bits[0];
bitset >>= NUM_IN_PAGE(p);
- invalidate_moved_plane(objspace, (intptr_t)p, bitset, &ctx);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p));
+ invalidate_moved_plane(objspace, page, p, bitset);
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
for (i=1; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
/* Moved objects are pinned but never marked. We reuse the pin bits
* to indicate there is a moved object in this slot. */
bitset = pin_bits[i] & ~mark_bits[i];
- invalidate_moved_plane(objspace, (intptr_t)p, bitset, &ctx);
- p += BITS_BITLENGTH;
+ invalidate_moved_plane(objspace, page, p, bitset);
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
}
-
- page->free_slots += (ctx.empty_slots + ctx.freed_slots);
- objspace->profile.total_freed_objects += ctx.freed_slots;
}
static void
-gc_compact_start(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_compact_start(rb_objspace_t *objspace)
{
- heap->compact_cursor = list_tail(&heap->pages, struct heap_page, page_node);
- heap->compact_cursor_index = 0;
+ struct heap_page *page = NULL;
+ gc_mode_transition(objspace, gc_mode_compacting);
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(&size_pools[i]);
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->flags.before_sweep = TRUE;
+ }
+
+ heap->compact_cursor = ccan_list_tail(&heap->pages, struct heap_page, page_node);
+ heap->compact_cursor_index = 0;
+ }
if (gc_prof_enabled(objspace)) {
gc_profile_record *record = gc_prof_record(objspace);
@@ -5788,11 +6186,15 @@ gc_compact_start(rb_objspace_t *objspace, rb_heap_t *heap)
memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t));
memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t));
+ memset(objspace->rcompactor.moved_up_count_table, 0, T_MASK * sizeof(size_t));
+ memset(objspace->rcompactor.moved_down_count_table, 0, T_MASK * sizeof(size_t));
/* Set up read barrier for pages containing MOVED objects */
install_handlers();
}
+static void gc_sweep_compact(rb_objspace_t *objspace);
+
static void
gc_sweep(rb_objspace_t *objspace)
{
@@ -5800,41 +6202,33 @@ gc_sweep(rb_objspace_t *objspace)
gc_report(1, objspace, "gc_sweep: immediate: %d\n", immediate_sweep);
+ gc_sweep_start(objspace);
+ if (objspace->flags.during_compacting) {
+ gc_sweep_compact(objspace);
+ }
+
if (immediate_sweep) {
#if !GC_ENABLE_LAZY_SWEEP
- gc_prof_sweep_timer_start(objspace);
+ 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);
+ gc_sweep_rest(objspace);
#if !GC_ENABLE_LAZY_SWEEP
- gc_prof_sweep_timer_stop(objspace);
+ gc_prof_sweep_timer_stop(objspace);
#endif
}
else {
- struct heap_page *page = NULL;
- gc_sweep_start(objspace);
- if (ruby_enable_autocompact && is_full_marking(objspace)) {
- gc_compact_start(objspace, heap_eden);
+ /* Sweep every size pool. */
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ gc_sweep_step(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool));
}
-
- list_for_each(&heap_eden->pages, page, page_node) {
- page->flags.before_sweep = TRUE;
- }
- gc_sweep_step(objspace, heap_eden);
}
- gc_heap_prepare_minimum_pages(objspace, heap_eden);
+#if !USE_RVARGC
+ rb_size_pool_t *size_pool = &size_pools[0];
+ gc_heap_prepare_minimum_pages(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool));
+#endif
}
/* Marking - Marking stack */
@@ -5864,8 +6258,8 @@ mark_stack_size(mark_stack_t *stack)
stack_chunk_t *chunk = stack->chunk ? stack->chunk->next : NULL;
while (chunk) {
- size += stack->limit;
- chunk = chunk->next;
+ size += stack->limit;
+ chunk = chunk->next;
}
return size;
}
@@ -5927,9 +6321,8 @@ pop_mark_stack_chunk(mark_stack_t *stack)
}
static void
-free_stack_chunks(mark_stack_t *stack)
+mark_stack_chunk_list_free(stack_chunk_t *chunk)
{
- stack_chunk_t *chunk = stack->chunk;
stack_chunk_t *next = NULL;
while (chunk != NULL) {
@@ -5940,6 +6333,20 @@ free_stack_chunks(mark_stack_t *stack)
}
static void
+free_stack_chunks(mark_stack_t *stack)
+{
+ mark_stack_chunk_list_free(stack->chunk);
+}
+
+static void
+mark_stack_free_cache(mark_stack_t *stack)
+{
+ mark_stack_chunk_list_free(stack->cache);
+ stack->cache_size = 0;
+ stack->unused_cache_size = 0;
+}
+
+static void
push_mark_stack(mark_stack_t *stack, VALUE data)
{
VALUE obj = data;
@@ -5962,7 +6369,6 @@ push_mark_stack(mark_stack_t *stack, VALUE data)
case T_TRUE:
case T_FALSE:
case T_SYMBOL:
- case T_PAYLOAD:
case T_IMEMO:
case T_ICLASS:
if (stack->index == stack->limit) {
@@ -5978,11 +6384,11 @@ push_mark_stack(mark_stack_t *stack, VALUE data)
case T_ZOMBIE:
case T_UNDEF:
case T_MASK:
- rb_bug("push_mark_stack() called for broken object");
- break;
+ rb_bug("push_mark_stack() called for broken object");
+ break;
case T_NODE:
- UNEXPECTED_NODE(push_mark_stack);
+ UNEXPECTED_NODE(push_mark_stack);
break;
}
@@ -6002,40 +6408,11 @@ pop_mark_stack(mark_stack_t *stack, VALUE *data)
pop_mark_stack_chunk(stack);
}
else {
- *data = stack->chunk->data[--stack->index];
+ *data = stack->chunk->data[--stack->index];
}
return TRUE;
}
-#if GC_ENABLE_INCREMENTAL_MARK
-static int
-invalidate_mark_stack_chunk(stack_chunk_t *chunk, int limit, VALUE obj)
-{
- int i;
- for (i=0; i<limit; i++) {
- if (chunk->data[i] == obj) {
- chunk->data[i] = Qundef;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static void
-invalidate_mark_stack(mark_stack_t *stack, VALUE obj)
-{
- stack_chunk_t *chunk = stack->chunk;
- int limit = stack->index;
-
- while (chunk) {
- if (invalidate_mark_stack_chunk(chunk, limit, obj)) return;
- chunk = chunk->next;
- limit = stack->limit;
- }
- rb_bug("invalid_mark_stack: unreachable");
-}
-#endif
-
static void
init_mark_stack(mark_stack_t *stack)
{
@@ -6064,7 +6441,7 @@ init_mark_stack(mark_stack_t *stack)
# define STACK_LENGTH (size_t)(STACK_END - STACK_START + 1)
#else
# define STACK_LENGTH ((STACK_END < STACK_START) ? (size_t)(STACK_START - STACK_END) \
- : (size_t)(STACK_END - STACK_START + 1))
+ : (size_t)(STACK_END - STACK_START + 1))
#endif
#if !STACK_GROW_DIRECTION
int ruby_stack_grow_direction;
@@ -6133,7 +6510,7 @@ each_location(rb_objspace_t *objspace, register const VALUE *x, register long n,
while (n--) {
v = *x;
cb(objspace, v);
- x++;
+ x++;
}
}
@@ -6332,34 +6709,40 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
gc_mark(objspace, me->defined_class);
if (def) {
- switch (def->type) {
- case VM_METHOD_TYPE_ISEQ:
- if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr);
- gc_mark(objspace, (VALUE)def->body.iseq.cref);
- break;
- case VM_METHOD_TYPE_ATTRSET:
- case VM_METHOD_TYPE_IVAR:
- gc_mark(objspace, def->body.attr.location);
- break;
- case VM_METHOD_TYPE_BMETHOD:
+ switch (def->type) {
+ case VM_METHOD_TYPE_ISEQ:
+ if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr);
+ gc_mark(objspace, (VALUE)def->body.iseq.cref);
+
+ if (def->iseq_overload && me->defined_class) {
+ // it can be a key of "overloaded_cme" table
+ // so it should be pinned.
+ gc_mark_and_pin(objspace, (VALUE)me);
+ }
+ break;
+ case VM_METHOD_TYPE_ATTRSET:
+ case VM_METHOD_TYPE_IVAR:
+ gc_mark(objspace, def->body.attr.location);
+ break;
+ case VM_METHOD_TYPE_BMETHOD:
gc_mark(objspace, def->body.bmethod.proc);
if (def->body.bmethod.hooks) rb_hook_list_mark(def->body.bmethod.hooks);
- break;
- case VM_METHOD_TYPE_ALIAS:
- gc_mark(objspace, (VALUE)def->body.alias.original_me);
- return;
- case VM_METHOD_TYPE_REFINED:
- gc_mark(objspace, (VALUE)def->body.refined.orig_me);
- gc_mark(objspace, (VALUE)def->body.refined.owner);
- break;
- case VM_METHOD_TYPE_CFUNC:
- case VM_METHOD_TYPE_ZSUPER:
- case VM_METHOD_TYPE_MISSING:
- case VM_METHOD_TYPE_OPTIMIZED:
- case VM_METHOD_TYPE_UNDEF:
- case VM_METHOD_TYPE_NOTIMPLEMENTED:
- break;
- }
+ break;
+ case VM_METHOD_TYPE_ALIAS:
+ gc_mark(objspace, (VALUE)def->body.alias.original_me);
+ return;
+ case VM_METHOD_TYPE_REFINED:
+ gc_mark(objspace, (VALUE)def->body.refined.orig_me);
+ gc_mark(objspace, (VALUE)def->body.refined.owner);
+ break;
+ case VM_METHOD_TYPE_CFUNC:
+ case VM_METHOD_TYPE_ZSUPER:
+ case VM_METHOD_TYPE_MISSING:
+ case VM_METHOD_TYPE_OPTIMIZED:
+ case VM_METHOD_TYPE_UNDEF:
+ case VM_METHOD_TYPE_NOTIMPLEMENTED:
+ break;
+ }
}
}
@@ -6376,7 +6759,7 @@ static void
mark_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
{
if (tbl) {
- rb_id_table_foreach_values(tbl, mark_method_entry_i, objspace);
+ rb_id_table_foreach_values(tbl, mark_method_entry_i, objspace);
}
}
@@ -6411,13 +6794,53 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec,
const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE));
-#ifndef __EMSCRIPTEN__
+#if defined(__wasm__)
+
+
+static VALUE *rb_stack_range_tmp[2];
+
+static void
+rb_mark_locations(void *begin, void *end)
+{
+ rb_stack_range_tmp[0] = begin;
+ rb_stack_range_tmp[1] = end;
+}
+
+# if defined(__EMSCRIPTEN__)
+
+static void
+mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
+{
+ emscripten_scan_stack(rb_mark_locations);
+ each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
+
+ emscripten_scan_registers(rb_mark_locations);
+ each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
+}
+# else // use Asyncify version
+
+static void
+mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
+{
+ VALUE *stack_start, *stack_end;
+ SET_STACK_END;
+ GET_STACK_BOUNDS(stack_start, stack_end, 1);
+ each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe);
+
+ rb_wasm_scan_locals(rb_mark_locations);
+ each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
+}
+
+# endif
+
+#else // !defined(__wasm__)
+
static void
mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
{
union {
- rb_jmp_buf j;
- VALUE v[sizeof(rb_jmp_buf) / (sizeof(VALUE))];
+ rb_jmp_buf j;
+ VALUE v[sizeof(rb_jmp_buf) / (sizeof(VALUE))];
} save_regs_gc_mark;
VALUE *stack_start, *stack_end;
@@ -6436,26 +6859,6 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec
each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe);
}
-#else
-
-static VALUE *rb_emscripten_stack_range_tmp[2];
-
-static void
-rb_emscripten_mark_locations(void *begin, void *end)
-{
- rb_emscripten_stack_range_tmp[0] = begin;
- rb_emscripten_stack_range_tmp[1] = end;
-}
-
-static void
-mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
-{
- emscripten_scan_stack(rb_emscripten_mark_locations);
- each_stack_location(objspace, ec, rb_emscripten_stack_range_tmp[0], rb_emscripten_stack_range_tmp[1], gc_mark_maybe);
-
- emscripten_scan_registers(rb_emscripten_mark_locations);
- each_stack_location(objspace, ec, rb_emscripten_stack_range_tmp[0], rb_emscripten_stack_range_tmp[1], gc_mark_maybe);
-}
#endif
static void
@@ -6476,15 +6879,15 @@ rb_gc_mark_machine_stack(const rb_execution_context_t *ec)
static void
each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec,
- const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE))
+ const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE))
{
gc_mark_locations(objspace, stack_start, stack_end, cb);
#if defined(__mc68000__)
gc_mark_locations(objspace,
- (VALUE*)((char*)stack_start + 2),
- (VALUE*)((char*)stack_end - 2), cb);
+ (VALUE*)((char*)stack_start + 2),
+ (VALUE*)((char*)stack_end - 2), cb);
#endif
}
@@ -6500,20 +6903,13 @@ rb_mark_tbl_no_pin(st_table *tbl)
mark_tbl_no_pin(&rb_objspace, tbl);
}
-static void gc_mark_payload(rb_objspace_t *objspace, VALUE obj);
-
static void
gc_mark_maybe(rb_objspace_t *objspace, VALUE obj)
{
(void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj));
if (is_pointer_to_heap(objspace, (void *)obj)) {
-#if USE_RVARGC
- obj = payload_or_self(obj);
-#endif
-
- void *ptr = __asan_region_is_poisoned((void *)obj, SIZEOF_VALUE);
- asan_unpoison_object(obj, false);
+ void *ptr = asan_unpoison_object_temporary(obj);
/* Garbage can live on the stack, so do not mark or pin */
switch (BUILTIN_TYPE(obj)) {
@@ -6554,20 +6950,20 @@ gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj)
bits_t *uncollectible_bits = &page->uncollectible_bits[0];
if (!MARKED_IN_BITMAP(uncollectible_bits, obj)) {
- page->flags.has_uncollectible_shady_objects = TRUE;
- MARK_IN_BITMAP(uncollectible_bits, obj);
- objspace->rgengc.uncollectible_wb_unprotected_objects++;
+ page->flags.has_uncollectible_shady_objects = TRUE;
+ MARK_IN_BITMAP(uncollectible_bits, obj);
+ objspace->rgengc.uncollectible_wb_unprotected_objects++;
#if RGENGC_PROFILE > 0
- objspace->profile.total_remembered_shady_object_count++;
+ objspace->profile.total_remembered_shady_object_count++;
#if RGENGC_PROFILE >= 2
- objspace->profile.remembered_shady_object_count_types[BUILTIN_TYPE(obj)]++;
+ objspace->profile.remembered_shady_object_count_types[BUILTIN_TYPE(obj)]++;
#endif
#endif
- return TRUE;
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -6577,32 +6973,32 @@ rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
const VALUE old_parent = objspace->rgengc.parent_object;
if (old_parent) { /* parent object is old */
- if (RVALUE_WB_UNPROTECTED(obj)) {
- if (gc_remember_unprotected(objspace, obj)) {
- gc_report(2, objspace, "relation: (O->S) %s -> %s\n", obj_info(old_parent), obj_info(obj));
- }
- }
- else {
- if (!RVALUE_OLD_P(obj)) {
- if (RVALUE_MARKED(obj)) {
- /* An object pointed from an OLD object should be OLD. */
- gc_report(2, objspace, "relation: (O->unmarked Y) %s -> %s\n", obj_info(old_parent), obj_info(obj));
- RVALUE_AGE_SET_OLD(objspace, obj);
- if (is_incremental_marking(objspace)) {
- if (!RVALUE_MARKING(obj)) {
- gc_grey(objspace, obj);
- }
- }
- else {
- rgengc_remember(objspace, obj);
- }
- }
- else {
- gc_report(2, objspace, "relation: (O->Y) %s -> %s\n", obj_info(old_parent), obj_info(obj));
- RVALUE_AGE_SET_CANDIDATE(objspace, obj);
- }
- }
- }
+ if (RVALUE_WB_UNPROTECTED(obj)) {
+ if (gc_remember_unprotected(objspace, obj)) {
+ gc_report(2, objspace, "relation: (O->S) %s -> %s\n", obj_info(old_parent), obj_info(obj));
+ }
+ }
+ else {
+ if (!RVALUE_OLD_P(obj)) {
+ if (RVALUE_MARKED(obj)) {
+ /* An object pointed from an OLD object should be OLD. */
+ gc_report(2, objspace, "relation: (O->unmarked Y) %s -> %s\n", obj_info(old_parent), obj_info(obj));
+ RVALUE_AGE_SET_OLD(objspace, obj);
+ if (is_incremental_marking(objspace)) {
+ if (!RVALUE_MARKING(obj)) {
+ gc_grey(objspace, obj);
+ }
+ }
+ else {
+ rgengc_remember(objspace, obj);
+ }
+ }
+ else {
+ gc_report(2, objspace, "relation: (O->Y) %s -> %s\n", obj_info(old_parent), obj_info(obj));
+ RVALUE_AGE_SET_CANDIDATE(objspace, obj);
+ }
+ }
+ }
}
GC_ASSERT(old_parent == objspace->rgengc.parent_object);
@@ -6618,7 +7014,7 @@ gc_grey(rb_objspace_t *objspace, VALUE obj)
#if GC_ENABLE_INCREMENTAL_MARK
if (is_incremental_marking(objspace)) {
- MARK_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ MARK_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
}
#endif
@@ -6634,25 +7030,14 @@ gc_aging(rb_objspace_t *objspace, VALUE obj)
check_rvalue_consistency(obj);
if (!RVALUE_PAGE_WB_UNPROTECTED(page, obj)) {
- if (!RVALUE_OLD_P(obj)) {
- gc_report(3, objspace, "gc_aging: YOUNG: %s\n", obj_info(obj));
- RVALUE_AGE_INC(objspace, obj);
- }
- else if (is_full_marking(objspace)) {
- GC_ASSERT(RVALUE_PAGE_UNCOLLECTIBLE(page, obj) == FALSE);
- RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(objspace, page, obj);
- }
-
-#if USE_RVARGC
- if (RVALUE_UNCOLLECTIBLE(obj) && BUILTIN_TYPE(obj) == T_PAYLOAD) {
- int plen = RPAYLOAD_LEN(obj);
-
- for (int i = 1; i < plen; i++) {
- VALUE pbody = obj + i * sizeof(RVALUE);
- MARK_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(pbody), pbody);
- }
+ if (!RVALUE_OLD_P(obj)) {
+ gc_report(3, objspace, "gc_aging: YOUNG: %s\n", obj_info(obj));
+ RVALUE_AGE_INC(objspace, obj);
+ }
+ else if (is_full_marking(objspace)) {
+ GC_ASSERT(RVALUE_PAGE_UNCOLLECTIBLE(page, obj) == FALSE);
+ RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(objspace, page, obj);
}
-#endif
}
check_rvalue_consistency(obj);
@@ -6666,8 +7051,8 @@ static void
gc_mark_ptr(rb_objspace_t *objspace, VALUE obj)
{
if (LIKELY(during_gc)) {
- rgengc_check_relation(objspace, obj);
- if (!gc_mark_set(objspace, obj)) return; /* already marked */
+ rgengc_check_relation(objspace, obj);
+ if (!gc_mark_set(objspace, obj)) return; /* already marked */
if (0) { // for debug GC marking miss
if (objspace->rgengc.parent_object) {
@@ -6684,8 +7069,8 @@ gc_mark_ptr(rb_objspace_t *objspace, VALUE obj)
rp(obj);
rb_bug("try to mark T_NONE object"); /* check here will help debugging */
}
- gc_aging(objspace, obj);
- gc_grey(objspace, obj);
+ gc_aging(objspace, obj);
+ gc_grey(objspace, obj);
}
else {
reachable_objects_from_callback(obj);
@@ -6744,10 +7129,10 @@ static inline void
gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj)
{
if (RVALUE_OLD_P(obj)) {
- objspace->rgengc.parent_object = obj;
+ objspace->rgengc.parent_object = obj;
}
else {
- objspace->rgengc.parent_object = Qfalse;
+ objspace->rgengc.parent_object = Qfalse;
}
}
@@ -6756,8 +7141,8 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
{
switch (imemo_type(obj)) {
case imemo_env:
- {
- const rb_env_t *env = (const rb_env_t *)obj;
+ {
+ const rb_env_t *env = (const rb_env_t *)obj;
if (LIKELY(env->ep)) {
// just after newobj() can be NULL here.
@@ -6768,50 +7153,50 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env));
gc_mark(objspace, (VALUE)env->iseq);
}
- }
- return;
+ }
+ return;
case imemo_cref:
- gc_mark(objspace, RANY(obj)->as.imemo.cref.klass);
- gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next);
- gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements);
- return;
+ gc_mark(objspace, RANY(obj)->as.imemo.cref.klass_or_self);
+ gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next);
+ gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements);
+ return;
case imemo_svar:
- gc_mark(objspace, RANY(obj)->as.imemo.svar.cref_or_me);
- gc_mark(objspace, RANY(obj)->as.imemo.svar.lastline);
- gc_mark(objspace, RANY(obj)->as.imemo.svar.backref);
- gc_mark(objspace, RANY(obj)->as.imemo.svar.others);
- return;
+ gc_mark(objspace, RANY(obj)->as.imemo.svar.cref_or_me);
+ gc_mark(objspace, RANY(obj)->as.imemo.svar.lastline);
+ gc_mark(objspace, RANY(obj)->as.imemo.svar.backref);
+ gc_mark(objspace, RANY(obj)->as.imemo.svar.others);
+ return;
case imemo_throw_data:
- gc_mark(objspace, RANY(obj)->as.imemo.throw_data.throw_obj);
- return;
+ gc_mark(objspace, RANY(obj)->as.imemo.throw_data.throw_obj);
+ return;
case imemo_ifunc:
- gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data);
- return;
+ gc_mark_maybe(objspace, (VALUE)RANY(obj)->as.imemo.ifunc.data);
+ return;
case imemo_memo:
- gc_mark(objspace, RANY(obj)->as.imemo.memo.v1);
- gc_mark(objspace, RANY(obj)->as.imemo.memo.v2);
- gc_mark_maybe(objspace, RANY(obj)->as.imemo.memo.u3.value);
- return;
+ gc_mark(objspace, RANY(obj)->as.imemo.memo.v1);
+ gc_mark(objspace, RANY(obj)->as.imemo.memo.v2);
+ gc_mark_maybe(objspace, RANY(obj)->as.imemo.memo.u3.value);
+ return;
case imemo_ment:
- mark_method_entry(objspace, &RANY(obj)->as.imemo.ment);
- return;
+ mark_method_entry(objspace, &RANY(obj)->as.imemo.ment);
+ return;
case imemo_iseq:
- rb_iseq_mark((rb_iseq_t *)obj);
- return;
+ rb_iseq_mark((rb_iseq_t *)obj);
+ return;
case imemo_tmpbuf:
- {
- const rb_imemo_tmpbuf_t *m = &RANY(obj)->as.imemo.alloc;
- do {
- rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
- } while ((m = m->next) != NULL);
- }
- return;
+ {
+ const rb_imemo_tmpbuf_t *m = &RANY(obj)->as.imemo.alloc;
+ do {
+ rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
+ } while ((m = m->next) != NULL);
+ }
+ return;
case imemo_ast:
- rb_ast_mark(&RANY(obj)->as.imemo.ast);
- return;
+ rb_ast_mark(&RANY(obj)->as.imemo.ast);
+ return;
case imemo_parser_strterm:
- rb_strterm_mark(obj);
- return;
+ rb_strterm_mark(obj);
+ return;
case imemo_callinfo:
return;
case imemo_callcache:
@@ -6829,26 +7214,12 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
return;
#if VM_CHECK_MODE > 0
default:
- VM_UNREACHABLE(gc_mark_imemo);
+ VM_UNREACHABLE(gc_mark_imemo);
#endif
}
}
-static inline void
-gc_mark_payload(rb_objspace_t *objspace, VALUE obj)
-{
-#if USE_RVARGC
- GC_ASSERT(BUILTIN_TYPE(obj) == T_PAYLOAD);
- // Mark payload head here
- gc_mark_and_pin(objspace, obj);
-
- for (int i = 1 ; i < RPAYLOAD_LEN(obj); i++) {
- VALUE p = obj + i * sizeof(RVALUE);
- MARK_IN_BITMAP(GET_HEAP_MARK_BITS(p), p);
- MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(p), p);
- }
-#endif
-}
+static void mark_cvc_tbl(rb_objspace_t *objspace, VALUE klass);
static void
gc_mark_children(rb_objspace_t *objspace, VALUE obj)
@@ -6857,7 +7228,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark_set_parent(objspace, obj);
if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_generic_ivar(obj);
+ rb_mark_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) {
@@ -6870,114 +7241,128 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
case T_NIL:
case T_FIXNUM:
- rb_bug("rb_gc_mark() called for broken object");
- break;
+ rb_bug("rb_gc_mark() called for broken object");
+ break;
case T_NODE:
- UNEXPECTED_NODE(rb_gc_mark);
- break;
+ UNEXPECTED_NODE(rb_gc_mark);
+ break;
case T_IMEMO:
- gc_mark_imemo(objspace, obj);
- return;
+ gc_mark_imemo(objspace, obj);
+ return;
default:
break;
}
- if (BUILTIN_TYPE(obj) != T_PAYLOAD) {
- gc_mark(objspace, any->as.basic.klass);
- }
+ gc_mark(objspace, any->as.basic.klass);
switch (BUILTIN_TYPE(obj)) {
- case T_PAYLOAD:
- gc_mark_payload(objspace, obj);
- break;
case T_CLASS:
case T_MODULE:
if (RCLASS_SUPER(obj)) {
gc_mark(objspace, RCLASS_SUPER(obj));
}
- if (!RCLASS_EXT(obj)) break;
+ if (!RCLASS_EXT(obj)) break;
mark_m_tbl(objspace, RCLASS_M_TBL(obj));
+ mark_cvc_tbl(objspace, obj);
cc_table_mark(objspace, obj);
- mark_tbl_no_pin(objspace, RCLASS_IV_TBL(obj));
- mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
- gc_mark_payload(objspace, (VALUE)((uintptr_t)RCLASS(obj)->ptr - sizeof(struct RPayload)));
- break;
+ for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
+ gc_mark(objspace, RCLASS_IVPTR(obj)[i]);
+ }
+ mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
+ break;
case T_ICLASS:
if (RICLASS_OWNS_M_TBL_P(obj)) {
- mark_m_tbl(objspace, RCLASS_M_TBL(obj));
- }
+ mark_m_tbl(objspace, RCLASS_M_TBL(obj));
+ }
if (RCLASS_SUPER(obj)) {
gc_mark(objspace, RCLASS_SUPER(obj));
}
- if (!RCLASS_EXT(obj)) break;
- mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
+ if (!RCLASS_EXT(obj)) break;
+
+ if (RCLASS_INCLUDER(obj)) {
+ gc_mark(objspace, RCLASS_INCLUDER(obj));
+ }
+ mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
cc_table_mark(objspace, obj);
- gc_mark_payload(objspace, (VALUE)((uintptr_t)RCLASS(obj)->ptr - sizeof(struct RPayload)));
- break;
+ break;
case T_ARRAY:
- if (FL_TEST(obj, ELTS_SHARED)) {
- VALUE root = any->as.array.as.heap.aux.shared_root;
+ if (ARY_SHARED_P(obj)) {
+ VALUE root = ARY_SHARED_ROOT(obj);
gc_mark(objspace, root);
- }
- else {
- long i, len = RARRAY_LEN(obj);
+ }
+ else {
+ long i, len = RARRAY_LEN(obj);
const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(obj);
- for (i=0; i < len; i++) {
+ for (i=0; i < len; i++) {
gc_mark(objspace, ptr[i]);
- }
+ }
if (LIKELY(during_gc)) {
- if (!FL_TEST_RAW(obj, RARRAY_EMBED_FLAG) &&
- RARRAY_TRANSIENT_P(obj)) {
+ if (!ARY_EMBED_P(obj) && RARRAY_TRANSIENT_P(obj)) {
rb_transient_heap_mark(obj, ptr);
}
}
}
- break;
+ break;
case T_HASH:
mark_hash(objspace, obj);
- break;
+ break;
case T_STRING:
- if (STR_SHARED_P(obj)) {
- gc_mark(objspace, any->as.string.as.heap.aux.shared);
- }
- break;
+ if (STR_SHARED_P(obj)) {
+ gc_mark(objspace, any->as.string.as.heap.aux.shared);
+ }
+ break;
case T_DATA:
- {
- void *const ptr = DATA_PTR(obj);
- if (ptr) {
- RUBY_DATA_FUNC mark_func = RTYPEDDATA_P(obj) ?
- any->as.typeddata.type->function.dmark :
- any->as.data.dmark;
- if (mark_func) (*mark_func)(ptr);
- }
- }
- break;
+ {
+ void *const ptr = DATA_PTR(obj);
+ if (ptr) {
+ RUBY_DATA_FUNC mark_func = RTYPEDDATA_P(obj) ?
+ any->as.typeddata.type->function.dmark :
+ any->as.data.dmark;
+ if (mark_func) (*mark_func)(ptr);
+ }
+ }
+ break;
case T_OBJECT:
{
- const VALUE * const ptr = ROBJECT_IVPTR(obj);
+ rb_shape_t *shape = rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj));
+ if (rb_shape_obj_too_complex(obj)) {
+ mark_tbl_no_pin(objspace, ROBJECT_IV_HASH(obj));
+ }
+ else {
+ const VALUE * const ptr = ROBJECT_IVPTR(obj);
- uint32_t i, len = ROBJECT_NUMIV(obj);
- for (i = 0; i < len; i++) {
- gc_mark(objspace, ptr[i]);
+ uint32_t i, len = ROBJECT_IV_COUNT(obj);
+ for (i = 0; i < len; i++) {
+ gc_mark(objspace, ptr[i]);
+ }
+
+ if (LIKELY(during_gc) &&
+ ROBJ_TRANSIENT_P(obj)) {
+ rb_transient_heap_mark(obj, ptr);
+ }
}
+ if (shape) {
+ VALUE klass = RBASIC_CLASS(obj);
- if (LIKELY(during_gc) &&
- ROBJ_TRANSIENT_P(obj)) {
- rb_transient_heap_mark(obj, ptr);
+ // Increment max_iv_count if applicable, used to determine size pool allocation
+ uint32_t num_of_ivs = shape->next_iv_index;
+ if (RCLASS_EXT(klass)->max_iv_count < num_of_ivs) {
+ RCLASS_EXT(klass)->max_iv_count = num_of_ivs;
+ }
}
}
- break;
+ break;
case T_FILE:
if (any->as.file.fptr) {
@@ -6988,32 +7373,33 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, any->as.file.fptr->writeconv_pre_ecopts);
gc_mark(objspace, any->as.file.fptr->encs.ecopts);
gc_mark(objspace, any->as.file.fptr->write_lock);
+ gc_mark(objspace, any->as.file.fptr->timeout);
}
break;
case T_REGEXP:
gc_mark(objspace, any->as.regexp.src);
- break;
+ break;
case T_MATCH:
- gc_mark(objspace, any->as.match.regexp);
- if (any->as.match.str) {
- gc_mark(objspace, any->as.match.str);
- }
- break;
+ gc_mark(objspace, any->as.match.regexp);
+ if (any->as.match.str) {
+ gc_mark(objspace, any->as.match.str);
+ }
+ break;
case T_RATIONAL:
- gc_mark(objspace, any->as.rational.num);
- gc_mark(objspace, any->as.rational.den);
- break;
+ gc_mark(objspace, any->as.rational.num);
+ gc_mark(objspace, any->as.rational.den);
+ break;
case T_COMPLEX:
- gc_mark(objspace, any->as.complex.real);
- gc_mark(objspace, any->as.complex.imag);
- break;
+ gc_mark(objspace, any->as.complex.real);
+ gc_mark(objspace, any->as.complex.imag);
+ break;
case T_STRUCT:
- {
+ {
long i;
const long len = RSTRUCT_LEN(obj);
const VALUE * const ptr = RSTRUCT_CONST_PTR(obj);
@@ -7026,19 +7412,19 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
RSTRUCT_TRANSIENT_P(obj)) {
rb_transient_heap_mark(obj, ptr);
}
- }
- break;
+ }
+ break;
default:
#if GC_DEBUG
- rb_gcdebug_print_obj_condition((VALUE)obj);
+ rb_gcdebug_print_obj_condition((VALUE)obj);
#endif
if (BUILTIN_TYPE(obj) == T_MOVED) rb_bug("rb_gc_mark(): %p is T_MOVED", (void *)obj);
- if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("rb_gc_mark(): %p is T_NONE", (void *)obj);
- if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("rb_gc_mark(): %p is T_ZOMBIE", (void *)obj);
- rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
- BUILTIN_TYPE(obj), (void *)any,
- is_pointer_to_heap(objspace, any) ? "corrupted object" : "non object");
+ if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("rb_gc_mark(): %p is T_NONE", (void *)obj);
+ if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("rb_gc_mark(): %p is T_ZOMBIE", (void *)obj);
+ rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
+ BUILTIN_TYPE(obj), (void *)any,
+ is_pointer_to_heap(objspace, any) ? "corrupted object" : "non object");
}
}
@@ -7057,39 +7443,39 @@ gc_mark_stacked_objects(rb_objspace_t *objspace, int incremental, size_t count)
#endif
while (pop_mark_stack(mstack, &obj)) {
- if (obj == Qundef) continue; /* skip */
+ if (UNDEF_P(obj)) continue; /* skip */
- if (RGENGC_CHECK_MODE && !RVALUE_MARKED(obj)) {
- rb_bug("gc_mark_stacked_objects: %s is not marked.", obj_info(obj));
- }
+ if (RGENGC_CHECK_MODE && !RVALUE_MARKED(obj)) {
+ rb_bug("gc_mark_stacked_objects: %s is not marked.", obj_info(obj));
+ }
gc_mark_children(objspace, obj);
#if GC_ENABLE_INCREMENTAL_MARK
- if (incremental) {
- if (RGENGC_CHECK_MODE && !RVALUE_MARKING(obj)) {
- rb_bug("gc_mark_stacked_objects: incremental, but marking bit is 0");
- }
- CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
- popped_count++;
+ if (incremental) {
+ if (RGENGC_CHECK_MODE && !RVALUE_MARKING(obj)) {
+ rb_bug("gc_mark_stacked_objects: incremental, but marking bit is 0");
+ }
+ CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ popped_count++;
- if (popped_count + (objspace->marked_slots - marked_slots_at_the_beginning) > count) {
- break;
- }
- }
- else {
- /* just ignore marking bits */
- }
+ if (popped_count + (objspace->marked_slots - marked_slots_at_the_beginning) > count) {
+ break;
+ }
+ }
+ else {
+ /* just ignore marking bits */
+ }
#endif
}
if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
if (is_mark_stack_empty(mstack)) {
- shrink_stack_chunk_cache(mstack);
- return TRUE;
+ shrink_stack_chunk_cache(mstack);
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -7116,13 +7502,13 @@ show_mark_ticks(void)
int i;
fprintf(stderr, "mark ticks result:\n");
for (i=0; i<MAX_TICKS; i++) {
- const char *category = mark_ticks_categories[i];
- if (category) {
- fprintf(stderr, "%s\t%8lu\n", category, (unsigned long)mark_ticks[i]);
- }
- else {
- break;
- }
+ const char *category = mark_ticks_categories[i];
+ if (category) {
+ fprintf(stderr, "%s\t%8lu\n", category, (unsigned long)mark_ticks[i]);
+ }
+ else {
+ break;
+ }
}
}
@@ -7141,7 +7527,7 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
const char *prev_category = 0;
if (mark_ticks_categories[0] == 0) {
- atexit(show_mark_ticks);
+ atexit(show_mark_ticks);
}
#endif
@@ -7152,10 +7538,10 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
#if PRINT_ROOT_TICKS
#define MARK_CHECKPOINT_PRINT_TICK(category) do { \
if (prev_category) { \
- tick_t t = tick(); \
- mark_ticks[tick_count] = t - start_tick; \
- mark_ticks_categories[tick_count] = prev_category; \
- tick_count++; \
+ tick_t t = tick(); \
+ mark_ticks[tick_count] = t - start_tick; \
+ mark_ticks_categories[tick_count] = prev_category; \
+ tick_count++; \
} \
prev_category = category; \
start_tick = tick(); \
@@ -7236,8 +7622,8 @@ static void
reflist_add(struct reflist *refs, VALUE obj)
{
if (refs->pos == refs->size) {
- refs->size *= 2;
- SIZED_REALLOC_N(refs->list, VALUE, refs->size, refs->size/2);
+ refs->size *= 2;
+ SIZED_REALLOC_N(refs->list, VALUE, refs->size, refs->size/2);
}
refs->list[refs->pos++] = obj;
@@ -7248,14 +7634,14 @@ reflist_dump(struct reflist *refs)
{
int i;
for (i=0; i<refs->pos; i++) {
- VALUE obj = refs->list[i];
- if (IS_ROOTSIG(obj)) { /* root */
- fprintf(stderr, "<root@%s>", GET_ROOTSIG(obj));
- }
- else {
- fprintf(stderr, "<%s>", obj_info(obj));
- }
- if (i+1 < refs->pos) fprintf(stderr, ", ");
+ VALUE obj = refs->list[i];
+ if (IS_ROOTSIG(obj)) { /* root */
+ fprintf(stderr, "<root@%s>", GET_ROOTSIG(obj));
+ }
+ else {
+ fprintf(stderr, "<%s>", obj_info(obj));
+ }
+ if (i+1 < refs->pos) fprintf(stderr, ", ");
}
}
@@ -7264,8 +7650,8 @@ reflist_referred_from_machine_context(struct reflist *refs)
{
int i;
for (i=0; i<refs->pos; i++) {
- VALUE obj = refs->list[i];
- if (IS_ROOTSIG(obj) && strcmp(GET_ROOTSIG(obj), "machine_context") == 0) return 1;
+ VALUE obj = refs->list[i];
+ if (IS_ROOTSIG(obj) && strcmp(GET_ROOTSIG(obj), "machine_context") == 0) return 1;
}
return 0;
}
@@ -7293,13 +7679,13 @@ allrefs_add(struct allrefs *data, VALUE obj)
if (st_lookup(data->references, obj, &r)) {
refs = (struct reflist *)r;
- reflist_add(refs, data->root_obj);
- return 0;
+ reflist_add(refs, data->root_obj);
+ return 0;
}
else {
- refs = reflist_create(data->root_obj);
- st_insert(data->references, obj, (st_data_t)refs);
- return 1;
+ refs = reflist_create(data->root_obj);
+ st_insert(data->references, obj, (st_data_t)refs);
+ return 1;
}
}
@@ -7309,7 +7695,7 @@ allrefs_i(VALUE obj, void *ptr)
struct allrefs *data = (struct allrefs *)ptr;
if (allrefs_add(data, obj)) {
- push_mark_stack(&data->mark_stack, obj);
+ push_mark_stack(&data->mark_stack, obj);
}
}
@@ -7321,7 +7707,7 @@ allrefs_roots_i(VALUE obj, void *ptr)
data->root_obj = MAKE_ROOTSIG(data->category);
if (allrefs_add(data, obj)) {
- push_mark_stack(&data->mark_stack, obj);
+ push_mark_stack(&data->mark_stack, obj);
}
}
#define PUSH_MARK_FUNC_DATA(v) do { \
@@ -7354,7 +7740,7 @@ objspace_allrefs(rb_objspace_t *objspace)
/* traverse rest objects reachable from root objects */
while (pop_mark_stack(&data.mark_stack, &obj)) {
- rb_objspace_reachable_objects_from(data.root_obj = obj, allrefs_i, &data);
+ rb_objspace_reachable_objects_from(data.root_obj = obj, allrefs_i, &data);
}
free_stack_chunks(&data.mark_stack);
@@ -7407,18 +7793,18 @@ gc_check_after_marks_i(st_data_t k, st_data_t v, st_data_t ptr)
/* object should be marked or oldgen */
if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj)) {
- fprintf(stderr, "gc_check_after_marks_i: %s is not marked and not oldgen.\n", obj_info(obj));
- fprintf(stderr, "gc_check_after_marks_i: %p is referred from ", (void *)obj);
- reflist_dump(refs);
-
- if (reflist_referred_from_machine_context(refs)) {
- fprintf(stderr, " (marked from machine stack).\n");
- /* marked from machine context can be false positive */
- }
- else {
- objspace->rgengc.error_count++;
- fprintf(stderr, "\n");
- }
+ fprintf(stderr, "gc_check_after_marks_i: %s is not marked and not oldgen.\n", obj_info(obj));
+ fprintf(stderr, "gc_check_after_marks_i: %p is referred from ", (void *)obj);
+ reflist_dump(refs);
+
+ if (reflist_referred_from_machine_context(refs)) {
+ fprintf(stderr, " (marked from machine stack).\n");
+ /* marked from machine context can be false positive */
+ }
+ else {
+ objspace->rgengc.error_count++;
+ fprintf(stderr, "\n");
+ }
}
return ST_CONTINUE;
}
@@ -7435,14 +7821,14 @@ gc_marks_check(rb_objspace_t *objspace, st_foreach_callback_func *checker_func,
objspace->rgengc.allrefs_table = objspace_allrefs(objspace);
if (checker_func) {
- st_foreach(objspace->rgengc.allrefs_table, checker_func, (st_data_t)objspace);
+ st_foreach(objspace->rgengc.allrefs_table, checker_func, (st_data_t)objspace);
}
if (objspace->rgengc.error_count > 0) {
#if RGENGC_CHECK_MODE >= 5
- allrefs_dump(objspace);
+ allrefs_dump(objspace);
#endif
- if (checker_name) rb_bug("%s: GC has problem.", checker_name);
+ if (checker_name) rb_bug("%s: GC has problem.", checker_name);
}
objspace_allrefs_destruct(objspace->rgengc.allrefs_table);
@@ -7476,12 +7862,12 @@ check_generation_i(const VALUE child, void *ptr)
if (RGENGC_CHECK_MODE) GC_ASSERT(RVALUE_OLD_P(parent));
if (!RVALUE_OLD_P(child)) {
- if (!RVALUE_REMEMBERED(parent) &&
- !RVALUE_REMEMBERED(child) &&
- !RVALUE_UNCOLLECTIBLE(child)) {
- fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (O->Y) %s -> %s\n", obj_info(parent), obj_info(child));
- data->err_count++;
- }
+ if (!RVALUE_REMEMBERED(parent) &&
+ !RVALUE_REMEMBERED(child) &&
+ !RVALUE_UNCOLLECTIBLE(child)) {
+ fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (O->Y) %s -> %s\n", obj_info(parent), obj_info(child));
+ data->err_count++;
+ }
}
}
@@ -7492,9 +7878,9 @@ check_color_i(const VALUE child, void *ptr)
const VALUE parent = data->parent;
if (!RVALUE_WB_UNPROTECTED(parent) && RVALUE_WHITE_P(child)) {
- fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (B->W) - %s -> %s\n",
- obj_info(parent), obj_info(child));
- data->err_count++;
+ fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (B->W) - %s -> %s\n",
+ obj_info(parent), obj_info(child));
+ data->err_count++;
}
}
@@ -7519,12 +7905,11 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
rb_objspace_t *objspace = data->objspace;
for (obj = (VALUE)page_start; obj != (VALUE)page_end; obj += stride) {
- void *poisoned = asan_poisoned_object_p(obj);
- asan_unpoison_object(obj, false);
+ void *poisoned = asan_unpoison_object_temporary(obj);
- if (is_live_object(objspace, obj)) {
- /* count objects */
- data->live_object_count++;
+ if (is_live_object(objspace, obj)) {
+ /* count objects */
+ data->live_object_count++;
data->parent = obj;
/* Normally, we don't expect T_MOVED objects to be in the heap.
@@ -7534,38 +7919,30 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data);
}
- /* check health of children */
- if (RVALUE_OLD_P(obj)) data->old_object_count++;
- if (RVALUE_WB_UNPROTECTED(obj) && RVALUE_UNCOLLECTIBLE(obj)) data->remembered_shady_count++;
-
- if (!is_marking(objspace) && RVALUE_OLD_P(obj)) {
- /* reachable objects from an oldgen object should be old or (young with remember) */
- data->parent = obj;
- rb_objspace_reachable_objects_from(obj, check_generation_i, (void *)data);
- }
-
- if (is_incremental_marking(objspace)) {
- if (RVALUE_BLACK_P(obj)) {
- /* reachable objects from black objects should be black or grey objects */
- data->parent = obj;
- rb_objspace_reachable_objects_from(obj, check_color_i, (void *)data);
- }
- }
-
- /* make sure we have counted the payload body slots */
- if (BUILTIN_TYPE(obj) == T_PAYLOAD) {
- if (RVALUE_OLD_P(obj)) {
- data->old_object_count += RPAYLOAD_LEN(obj) - 1;
+ /* check health of children */
+ if (RVALUE_OLD_P(obj)) data->old_object_count++;
+ if (RVALUE_WB_UNPROTECTED(obj) && RVALUE_UNCOLLECTIBLE(obj)) data->remembered_shady_count++;
+
+ if (!is_marking(objspace) && RVALUE_OLD_P(obj)) {
+ /* reachable objects from an oldgen object should be old or (young with remember) */
+ data->parent = obj;
+ rb_objspace_reachable_objects_from(obj, check_generation_i, (void *)data);
+ }
+
+ if (is_incremental_marking(objspace)) {
+ if (RVALUE_BLACK_P(obj)) {
+ /* reachable objects from black objects should be black or grey objects */
+ data->parent = obj;
+ rb_objspace_reachable_objects_from(obj, check_color_i, (void *)data);
}
- data->live_object_count += RPAYLOAD_LEN(obj) - 1;
- }
- }
- else {
- if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
- GC_ASSERT((RBASIC(obj)->flags & ~FL_SEEN_OBJ_ID) == T_ZOMBIE);
- data->zombie_object_count++;
- }
- }
+ }
+ }
+ else {
+ if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
+ GC_ASSERT((RBASIC(obj)->flags & ~FL_SEEN_OBJ_ID) == T_ZOMBIE);
+ data->zombie_object_count++;
+ }
+ }
if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
asan_poison_object(obj);
@@ -7578,43 +7955,30 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
static int
gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
{
- int i;
unsigned int has_remembered_shady = FALSE;
unsigned int has_remembered_old = FALSE;
int remembered_old_objects = 0;
int free_objects = 0;
int zombie_objects = 0;
- int stride = 1;
-#if USE_RVARGC
- int default_stride = 1;
-#endif
- for (i=0; i<page->total_slots; i+=stride) {
- VALUE val = (VALUE)&page->start[i];
- void *poisoned = asan_poisoned_object_p(val);
- asan_unpoison_object(val, false);
+ short slot_size = page->slot_size;
+ uintptr_t start = (uintptr_t)page->start;
+ uintptr_t end = start + page->total_slots * slot_size;
-#if USE_RVARGC
- if (BUILTIN_TYPE(val) == T_PAYLOAD) {
- stride = RPAYLOAD_LEN(val);
+ for (uintptr_t ptr = start; ptr < end; ptr += slot_size) {
+ VALUE val = (VALUE)ptr;
+ void *poisoned = asan_unpoison_object_temporary(val);
+ enum ruby_value_type type = BUILTIN_TYPE(val);
+
+ if (type == T_NONE) free_objects++;
+ if (type == T_ZOMBIE) zombie_objects++;
+ if (RVALUE_PAGE_UNCOLLECTIBLE(page, val) && RVALUE_PAGE_WB_UNPROTECTED(page, val)) {
+ has_remembered_shady = TRUE;
}
- else {
- stride = default_stride;
+ if (RVALUE_PAGE_MARKING(page, val)) {
+ has_remembered_old = TRUE;
+ remembered_old_objects++;
}
-#endif
-
- if (RBASIC(val) == 0) free_objects++;
-#if USE_RVARGC
- if (BUILTIN_TYPE(val) == T_PAYLOAD) stride = RPAYLOAD_LEN(val);
-#endif
- if (BUILTIN_TYPE(val) == T_ZOMBIE) zombie_objects++;
- if (RVALUE_PAGE_UNCOLLECTIBLE(page, val) && RVALUE_PAGE_WB_UNPROTECTED(page, val)) {
- has_remembered_shady = TRUE;
- }
- if (RVALUE_PAGE_MARKING(page, val)) {
- has_remembered_old = TRUE;
- remembered_old_objects++;
- }
if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(val) == T_NONE);
@@ -7623,44 +7987,44 @@ gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
}
if (!is_incremental_marking(objspace) &&
- page->flags.has_remembered_objects == FALSE && has_remembered_old == TRUE) {
+ page->flags.has_remembered_objects == FALSE && has_remembered_old == TRUE) {
- for (i=0; i<page->total_slots; i++) {
- VALUE val = (VALUE)&page->start[i];
- if (RVALUE_PAGE_MARKING(page, val)) {
- fprintf(stderr, "marking -> %s\n", obj_info(val));
- }
- }
- rb_bug("page %p's has_remembered_objects should be false, but there are remembered old objects (%d). %s",
- (void *)page, remembered_old_objects, obj ? obj_info(obj) : "");
+ for (uintptr_t ptr = start; ptr < end; ptr += slot_size) {
+ VALUE val = (VALUE)ptr;
+ if (RVALUE_PAGE_MARKING(page, val)) {
+ fprintf(stderr, "marking -> %s\n", obj_info(val));
+ }
+ }
+ rb_bug("page %p's has_remembered_objects should be false, but there are remembered old objects (%d). %s",
+ (void *)page, remembered_old_objects, obj ? obj_info(obj) : "");
}
if (page->flags.has_uncollectible_shady_objects == FALSE && has_remembered_shady == TRUE) {
- rb_bug("page %p's has_remembered_shady should be false, but there are remembered shady objects. %s",
- (void *)page, obj ? obj_info(obj) : "");
+ rb_bug("page %p's has_remembered_shady should be false, but there are remembered shady objects. %s",
+ (void *)page, obj ? obj_info(obj) : "");
}
if (0) {
- /* free_slots may not equal to free_objects */
- if (page->free_slots != free_objects) {
- rb_bug("page %p's free_slots should be %d, but %d\n", (void *)page, page->free_slots, free_objects);
- }
+ /* 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, 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, 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;
}
static int
-gc_verify_heap_pages_(rb_objspace_t *objspace, struct list_head *head)
+gc_verify_heap_pages_(rb_objspace_t *objspace, struct ccan_list_head *head)
{
int remembered_old_objects = 0;
struct heap_page *page = 0;
- list_for_each(head, page, page_node) {
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+ ccan_list_for_each(head, page, page_node) {
+ asan_unlock_freelist(page);
RVALUE *p = page->freelist;
while (p) {
VALUE vp = (VALUE)p;
@@ -7672,11 +8036,11 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct list_head *head)
p = p->as.free.next;
asan_poison_object(prev);
}
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ asan_lock_freelist(page);
- if (page->flags.has_remembered_objects == FALSE) {
- remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse);
- }
+ if (page->flags.has_remembered_objects == FALSE) {
+ remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse);
+ }
}
return remembered_old_objects;
@@ -7686,8 +8050,10 @@ static int
gc_verify_heap_pages(rb_objspace_t *objspace)
{
int remembered_old_objects = 0;
- remembered_old_objects += gc_verify_heap_pages_(objspace, &heap_eden->pages);
- remembered_old_objects += gc_verify_heap_pages_(objspace, &heap_tomb->pages);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ remembered_old_objects += gc_verify_heap_pages_(objspace, &(SIZE_POOL_EDEN_HEAP(&size_pools[i])->pages));
+ remembered_old_objects += gc_verify_heap_pages_(objspace, &(SIZE_POOL_TOMB_HEAP(&size_pools[i])->pages));
+ }
return remembered_old_objects;
}
@@ -7719,16 +8085,21 @@ gc_verify_internal_consistency_(rb_objspace_t *objspace)
/* check relations */
for (size_t i = 0; i < heap_allocated_pages; i++) {
struct heap_page *page = heap_pages_sorted[i];
- verify_internal_consistency_i(page->start, page->start + page->total_slots, sizeof(RVALUE), &data);
+ short slot_size = page->slot_size;
+
+ uintptr_t start = (uintptr_t)page->start;
+ uintptr_t end = start + page->total_slots * slot_size;
+
+ verify_internal_consistency_i((void *)start, (void *)end, slot_size, &data);
}
if (data.err_count != 0) {
#if RGENGC_CHECK_MODE >= 5
- objspace->rgengc.error_count = data.err_count;
- gc_marks_check(objspace, NULL, NULL);
- allrefs_dump(objspace);
+ objspace->rgengc.error_count = data.err_count;
+ gc_marks_check(objspace, NULL, NULL);
+ allrefs_dump(objspace);
#endif
- rb_bug("gc_verify_internal_consistency: found internal inconsistency.");
+ rb_bug("gc_verify_internal_consistency: found internal inconsistency.");
}
/* check heap_page status */
@@ -7736,42 +8107,42 @@ gc_verify_internal_consistency_(rb_objspace_t *objspace)
/* check counters */
- if (!is_lazy_sweeping(heap_eden) &&
+ if (!is_lazy_sweeping(objspace) &&
!finalizing &&
ruby_single_main_ractor != NULL) {
- if (objspace_live_slots(objspace) != data.live_object_count) {
- fprintf(stderr, "heap_pages_final_slots: %"PRIdSIZE", "
+ if (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".",
+ 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 (!is_marking(objspace)) {
- if (objspace->rgengc.old_objects != data.old_object_count) {
- rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".",
+ if (objspace->rgengc.old_objects != data.old_object_count) {
+ rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".",
objspace->rgengc.old_objects, data.old_object_count);
- }
- if (objspace->rgengc.uncollectible_wb_unprotected_objects != data.remembered_shady_count) {
+ }
+ if (objspace->rgengc.uncollectible_wb_unprotected_objects != data.remembered_shady_count) {
rb_bug("inconsistent number of wb unprotected objects: expect %"PRIuSIZE", but %"PRIuSIZE".",
objspace->rgengc.uncollectible_wb_unprotected_objects, data.remembered_shady_count);
- }
+ }
}
if (!finalizing) {
- size_t list_count = 0;
+ size_t list_count = 0;
- {
- VALUE z = heap_pages_deferred_final;
- while (z) {
- list_count++;
- z = RZOMBIE(z)->next;
- }
- }
+ {
+ VALUE z = heap_pages_deferred_final;
+ while (z) {
+ list_count++;
+ z = RZOMBIE(z)->next;
+ }
+ }
- if (heap_pages_final_slots != data.zombie_object_count ||
- heap_pages_final_slots != list_count) {
+ if (heap_pages_final_slots != data.zombie_object_count ||
+ heap_pages_final_slots != list_count) {
rb_bug("inconsistent finalizing object count:\n"
" expect %"PRIuSIZE"\n"
@@ -7780,7 +8151,7 @@ gc_verify_internal_consistency_(rb_objspace_t *objspace)
heap_pages_final_slots,
data.zombie_object_count,
list_count);
- }
+ }
}
gc_report(5, objspace, "gc_verify_internal_consistency: OK\n");
@@ -7816,6 +8187,27 @@ gc_verify_transient_heap_internal_consistency(VALUE dmy)
return Qnil;
}
+#if GC_ENABLE_INCREMENTAL_MARK
+static void
+heap_move_pooled_pages_to_free_pages(rb_heap_t *heap)
+{
+ if (heap->pooled_pages) {
+ if (heap->free_pages) {
+ struct heap_page *free_pages_tail = heap->free_pages;
+ while (free_pages_tail->free_next) {
+ free_pages_tail = free_pages_tail->free_next;
+ }
+ free_pages_tail->free_next = heap->pooled_pages;
+ }
+ else {
+ heap->free_pages = heap->pooled_pages;
+ }
+
+ heap->pooled_pages = NULL;
+ }
+}
+#endif
+
/* marks */
static void
@@ -7827,30 +8219,40 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark)
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);
+ size_t incremental_marking_steps = (objspace->rincgc.pooled_slots / INCREMENTAL_MARK_STEP_ALLOCATIONS) + 1;
+ objspace->rincgc.step_slots = (objspace->marked_slots * 2) / incremental_marking_steps;
- if (0) fprintf(stderr, "objspace->marked_slots: %"PRIdSIZE", "
+ 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;
+ objspace->flags.during_minor_gc = FALSE;
if (ruby_enable_autocompact) {
objspace->flags.during_compacting |= TRUE;
}
- objspace->profile.major_gc_count++;
- objspace->rgengc.uncollectible_wb_unprotected_objects = 0;
- objspace->rgengc.old_objects = 0;
- objspace->rgengc.last_major_gc = objspace->profile.count;
- objspace->marked_slots = 0;
- rgengc_mark_and_rememberset_clear(objspace, heap_eden);
+ objspace->profile.major_gc_count++;
+ objspace->rgengc.uncollectible_wb_unprotected_objects = 0;
+ objspace->rgengc.old_objects = 0;
+ objspace->rgengc.last_major_gc = objspace->profile.count;
+ objspace->marked_slots = 0;
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+ rgengc_mark_and_rememberset_clear(objspace, heap);
+ heap_move_pooled_pages_to_free_pages(heap);
+ }
}
else {
- objspace->flags.during_minor_gc = TRUE;
- objspace->marked_slots =
- objspace->rgengc.old_objects + objspace->rgengc.uncollectible_wb_unprotected_objects; /* uncollectible objects are marked already */
- objspace->profile.minor_gc_count++;
- rgengc_rememberset_mark(objspace, heap_eden);
+ objspace->flags.during_minor_gc = TRUE;
+ objspace->marked_slots =
+ objspace->rgengc.old_objects + objspace->rgengc.uncollectible_wb_unprotected_objects; /* uncollectible objects are marked already */
+ objspace->profile.minor_gc_count++;
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rgengc_rememberset_mark(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i]));
+ }
}
gc_mark_roots(objspace, NULL);
@@ -7861,7 +8263,7 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark)
#if GC_ENABLE_INCREMENTAL_MARK
static inline void
-gc_marks_wb_unprotected_objects_in_plane(rb_objspace_t *objspace, intptr_t p, bits_t bits)
+gc_marks_wb_unprotected_objects_plane(rb_objspace_t *objspace, uintptr_t p, bits_t bits)
{
if (bits) {
do {
@@ -7871,7 +8273,7 @@ gc_marks_wb_unprotected_objects_in_plane(rb_objspace_t *objspace, intptr_t p, bi
GC_ASSERT(RVALUE_MARKED((VALUE)p));
gc_mark_children(objspace, (VALUE)p);
}
- p += sizeof(RVALUE);
+ p += BASE_SLOT_SIZE;
bits >>= 1;
} while (bits);
}
@@ -7882,76 +8284,54 @@ gc_marks_wb_unprotected_objects(rb_objspace_t *objspace, rb_heap_t *heap)
{
struct heap_page *page = 0;
- list_for_each(&heap->pages, page, page_node) {
- bits_t *mark_bits = page->mark_bits;
- bits_t *wbun_bits = page->wb_unprotected_bits;
- RVALUE *p = page->start;
- size_t j;
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ bits_t *mark_bits = page->mark_bits;
+ bits_t *wbun_bits = page->wb_unprotected_bits;
+ uintptr_t p = page->start;
+ size_t j;
bits_t bits = mark_bits[0] & wbun_bits[0];
bits >>= NUM_IN_PAGE(p);
- gc_marks_wb_unprotected_objects_in_plane(objspace, (intptr_t)p, bits);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p));
+ gc_marks_wb_unprotected_objects_plane(objspace, p, bits);
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
- for (j=1; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
- bits_t bits = mark_bits[j] & wbun_bits[j];
+ for (j=1; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bits_t bits = mark_bits[j] & wbun_bits[j];
- gc_marks_wb_unprotected_objects_in_plane(objspace, (intptr_t)p, bits);
- p += BITS_BITLENGTH;
- }
+ gc_marks_wb_unprotected_objects_plane(objspace, p, bits);
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
}
gc_mark_stacked_objects_all(objspace);
}
-
-static struct heap_page *
-heap_move_pooled_pages_to_free_pages(rb_heap_t *heap)
-{
- struct heap_page *page = heap->pooled_pages;
-
- if (page) {
- heap->pooled_pages = page->free_next;
- heap_add_freepage(heap, page);
- }
-
- return page;
-}
#endif
-static int
+static void
gc_marks_finish(rb_objspace_t *objspace)
{
#if GC_ENABLE_INCREMENTAL_MARK
/* finish incremental GC */
if (is_incremental_marking(objspace)) {
- if (heap_eden->pooled_pages) {
- heap_move_pooled_pages_to_free_pages(heap_eden);
- gc_report(1, objspace, "gc_marks_finish: pooled pages are exists. retry.\n");
- return FALSE; /* continue marking phase */
- }
-
- if (RGENGC_CHECK_MODE && is_mark_stack_empty(&objspace->mark_stack) == 0) {
- rb_bug("gc_marks_finish: mark stack is not empty (%"PRIdSIZE").",
+ if (RGENGC_CHECK_MODE && is_mark_stack_empty(&objspace->mark_stack) == 0) {
+ rb_bug("gc_marks_finish: mark stack is not empty (%"PRIdSIZE").",
mark_stack_size(&objspace->mark_stack));
- }
-
- gc_mark_roots(objspace, 0);
+ }
- if (is_mark_stack_empty(&objspace->mark_stack) == FALSE) {
- gc_report(1, objspace, "gc_marks_finish: not empty (%"PRIdSIZE"). retry.\n",
- mark_stack_size(&objspace->mark_stack));
- return FALSE;
- }
+ gc_mark_roots(objspace, 0);
+ while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == false);
#if RGENGC_CHECK_MODE >= 2
- if (gc_verify_heap_pages(objspace) != 0) {
- rb_bug("gc_marks_finish (incremental): there are remembered old objects.");
- }
+ if (gc_verify_heap_pages(objspace) != 0) {
+ rb_bug("gc_marks_finish (incremental): there are remembered old objects.");
+ }
#endif
- objspace->flags.during_incremental_marking = FALSE;
- /* check children of all marked wb-unprotected objects */
- gc_marks_wb_unprotected_objects(objspace, heap_eden);
+ objspace->flags.during_incremental_marking = FALSE;
+ /* check children of all marked wb-unprotected objects */
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ gc_marks_wb_unprotected_objects(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i]));
+ }
}
#endif /* GC_ENABLE_INCREMENTAL_MARK */
@@ -7960,10 +8340,10 @@ gc_marks_finish(rb_objspace_t *objspace)
#endif
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);
+ /* 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);
}
#if RGENGC_CHECK_MODE >= 4
@@ -7973,85 +8353,87 @@ gc_marks_finish(rb_objspace_t *objspace)
#endif
{
- /* decide full GC is needed or not */
- rb_heap_t *heap = heap_eden;
- size_t total_slots = heap_allocatable_pages * HEAP_PAGE_OBJ_LIMIT + heap->total_slots;
- size_t sweep_slots = total_slots - objspace->marked_slots; /* will be swept slots */
- size_t max_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_max_ratio);
- size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio);
- int full_marking = is_full_marking(objspace);
+ /* decide full GC is needed or not */
+ size_t total_slots = heap_allocatable_slots(objspace) + heap_eden_total_slots(objspace);
+ size_t sweep_slots = total_slots - objspace->marked_slots; /* will be swept slots */
+ size_t max_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_max_ratio);
+ size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio);
+ int full_marking = is_full_marking(objspace);
const int r_cnt = GET_VM()->ractor.cnt;
const int r_mul = r_cnt > 8 ? 8 : r_cnt; // upto 8
- GC_ASSERT(heap->total_slots >= objspace->marked_slots);
+ GC_ASSERT(heap_eden_total_slots(objspace) >= objspace->marked_slots);
- /* setup free-able page counts */
+ /* setup free-able page counts */
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;
- }
- else {
- heap_pages_freeable_pages = 0;
- }
+ if (sweep_slots > max_free_slots) {
+ heap_pages_freeable_pages = (sweep_slots - max_free_slots) / HEAP_PAGE_OBJ_LIMIT;
+ }
+ else {
+ heap_pages_freeable_pages = 0;
+ }
/* check free_min */
if (min_free_slots < gc_params.heap_free_slots * r_mul) {
min_free_slots = gc_params.heap_free_slots * r_mul;
}
- if (sweep_slots < min_free_slots) {
- if (!full_marking) {
- if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
- full_marking = TRUE;
- /* do not update last_major_gc, because full marking is not done. */
+ if (sweep_slots < min_free_slots) {
+ if (!full_marking) {
+ if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
+ full_marking = TRUE;
+ /* do not update last_major_gc, because full marking is not done. */
/* goto increment; */
- }
- else {
- gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE;
- }
- }
+ }
+ else {
+ gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
+ objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE;
+ }
+ }
+
+#if !USE_RVARGC
if (full_marking) {
/* increment: */
- gc_report(1, objspace, "gc_marks_finish: heap_set_increment!!\n");
- heap_allocatable_pages_set(objspace, heap_extend_pages(objspace, sweep_slots, total_slots));
- heap_increment(objspace, heap);
- }
- }
-
- if (full_marking) {
- /* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
- const double r = gc_params.oldobject_limit_factor;
- objspace->rgengc.uncollectible_wb_unprotected_objects_limit = (size_t)(objspace->rgengc.uncollectible_wb_unprotected_objects * r);
- objspace->rgengc.old_objects_limit = (size_t)(objspace->rgengc.old_objects * r);
- }
-
- if (objspace->rgengc.uncollectible_wb_unprotected_objects > objspace->rgengc.uncollectible_wb_unprotected_objects_limit) {
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_SHADY;
- }
- if (objspace->rgengc.old_objects > objspace->rgengc.old_objects_limit) {
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDGEN;
- }
- if (RGENGC_FORCE_MAJOR_GC) {
- objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_FORCE;
- }
-
- gc_report(1, objspace, "gc_marks_finish (marks %"PRIdSIZE" objects, "
+ gc_report(1, objspace, "gc_marks_finish: heap_set_increment!!\n");
+ rb_size_pool_t *size_pool = &size_pools[0];
+ size_pool_allocatable_pages_set(objspace, size_pool, heap_extend_pages(objspace, size_pool, sweep_slots, total_slots, heap_allocated_pages + heap_allocatable_pages(objspace)));
+
+ heap_increment(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool));
+ }
+#endif
+ }
+
+ if (full_marking) {
+ /* 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);
+ }
+
+ if (objspace->rgengc.uncollectible_wb_unprotected_objects > objspace->rgengc.uncollectible_wb_unprotected_objects_limit) {
+ objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_SHADY;
+ }
+ if (objspace->rgengc.old_objects > objspace->rgengc.old_objects_limit) {
+ objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDGEN;
+ }
+ if (RGENGC_FORCE_MAJOR_GC) {
+ objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_FORCE;
+ }
+
+ gc_report(1, objspace, "gc_marks_finish (marks %"PRIdSIZE" objects, "
"old %"PRIdSIZE" objects, total %"PRIdSIZE" slots, "
"sweep %"PRIdSIZE" slots, increment: %"PRIdSIZE", next GC: %s)\n",
- objspace->marked_slots, objspace->rgengc.old_objects, heap->total_slots, sweep_slots, heap_allocatable_pages,
- objspace->rgengc.need_major_gc ? "major" : "minor");
+ objspace->marked_slots, objspace->rgengc.old_objects, heap_eden_total_slots(objspace), sweep_slots, heap_allocatable_pages(objspace),
+ objspace->rgengc.need_major_gc ? "major" : "minor");
}
rb_transient_heap_finish_marking();
rb_ractor_finish_marking();
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_MARK, 0);
-
- return TRUE;
}
#if GC_ENABLE_INCREMENTAL_MARK
@@ -8061,40 +8443,260 @@ gc_marks_step(rb_objspace_t *objspace, size_t slots)
GC_ASSERT(is_marking(objspace));
if (gc_mark_stacked_objects_incremental(objspace, slots)) {
- if (gc_marks_finish(objspace)) {
- /* finish */
- gc_sweep(objspace);
- }
+ gc_marks_finish(objspace);
+ gc_sweep(objspace);
}
if (0) fprintf(stderr, "objspace->marked_slots: %"PRIdSIZE"\n", objspace->marked_slots);
}
#endif
+static bool
+gc_compact_heap_cursors_met_p(rb_heap_t *heap)
+{
+ return heap->sweeping_page == heap->compact_cursor;
+}
+
+static rb_size_pool_t *
+gc_compact_destination_pool(rb_objspace_t *objspace, rb_size_pool_t *src_pool, VALUE src)
+{
+ size_t obj_size;
+ size_t idx = 0;
+
+ switch (BUILTIN_TYPE(src)) {
+ case T_ARRAY:
+ obj_size = rb_ary_size_as_embedded(src);
+ break;
+
+ case T_OBJECT:
+ if (rb_shape_obj_too_complex(src)) {
+ return &size_pools[0];
+ }
+ else {
+ obj_size = rb_obj_embedded_size(ROBJECT_IV_CAPACITY(src));
+ }
+ break;
+
+ case T_STRING:
+ obj_size = rb_str_size_as_embedded(src);
+ break;
+
+ default:
+ return src_pool;
+ }
+
+ if (rb_gc_size_allocatable_p(obj_size)){
+ idx = size_pool_idx_for_size(obj_size);
+ }
+ return &size_pools[idx];
+}
+
+static bool
+gc_compact_move(rb_objspace_t *objspace, rb_heap_t *heap, rb_size_pool_t *size_pool, VALUE src)
+{
+ GC_ASSERT(BUILTIN_TYPE(src) != T_MOVED);
+ GC_ASSERT(gc_is_moveable_obj(objspace, src));
+
+ rb_size_pool_t *dest_pool = gc_compact_destination_pool(objspace, size_pool, src);
+ rb_heap_t *dheap = SIZE_POOL_EDEN_HEAP(dest_pool);
+ rb_shape_t *new_shape = NULL;
+ rb_shape_t *orig_shape = NULL;
+
+ if (gc_compact_heap_cursors_met_p(dheap)) {
+ return dheap != heap;
+ }
+
+ if (RB_TYPE_P(src, T_OBJECT)) {
+ orig_shape = rb_shape_get_shape(src);
+ if (dheap != heap && !rb_shape_obj_too_complex(src)) {
+ rb_shape_t *initial_shape = rb_shape_get_shape_by_id((shape_id_t)((dest_pool - size_pools) + SIZE_POOL_COUNT));
+ new_shape = rb_shape_traverse_from_new_root(initial_shape, orig_shape);
+
+ if (!new_shape) {
+ dest_pool = size_pool;
+ dheap = heap;
+ }
+ }
+ }
+
+ while (!try_move(objspace, dheap, dheap->free_pages, src)) {
+ struct gc_sweep_context ctx = {
+ .page = dheap->sweeping_page,
+ .final_slots = 0,
+ .freed_slots = 0,
+ .empty_slots = 0,
+ };
+
+ /* The page of src could be partially compacted, so it may contain
+ * T_MOVED. Sweeping a page may read objects on this page, so we
+ * need to lock the page. */
+ lock_page_body(objspace, GET_PAGE_BODY(src));
+ gc_sweep_page(objspace, dheap, &ctx);
+ unlock_page_body(objspace, GET_PAGE_BODY(src));
+
+ if (dheap->sweeping_page->free_slots > 0) {
+ heap_add_freepage(dheap, dheap->sweeping_page);
+ };
+
+ dheap->sweeping_page = ccan_list_next(&dheap->pages, dheap->sweeping_page, page_node);
+ if (gc_compact_heap_cursors_met_p(dheap)) {
+ return dheap != heap;
+ }
+ }
+
+ if (orig_shape) {
+ if (new_shape) {
+ VALUE dest = rb_gc_location(src);
+ rb_shape_set_shape(dest, new_shape);
+ }
+ RMOVED(src)->original_shape_id = rb_shape_id(orig_shape);
+ }
+
+ return true;
+}
+
+static bool
+gc_compact_plane(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct heap_page *page)
+{
+ short slot_size = page->slot_size;
+ short slot_bits = slot_size / BASE_SLOT_SIZE;
+ GC_ASSERT(slot_bits > 0);
+
+ do {
+ VALUE vp = (VALUE)p;
+ GC_ASSERT(vp % sizeof(RVALUE) == 0);
+
+ if (bitset & 1) {
+ objspace->rcompactor.considered_count_table[BUILTIN_TYPE(vp)]++;
+
+ if (gc_is_moveable_obj(objspace, vp)) {
+ if (!gc_compact_move(objspace, heap, size_pool, vp)) {
+ //the cursors met. bubble up
+ return false;
+ }
+ }
+ }
+ p += slot_size;
+ bitset >>= slot_bits;
+ } while (bitset);
+
+ return true;
+}
+
+// Iterate up all the objects in page, moving them to where they want to go
+static bool
+gc_compact_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, struct heap_page *page)
+{
+ GC_ASSERT(page == heap->compact_cursor);
+
+ bits_t *mark_bits, *pin_bits;
+ bits_t bitset;
+ uintptr_t p = page->start;
+
+ mark_bits = page->mark_bits;
+ pin_bits = page->pinned_bits;
+
+ // objects that can be moved are marked and not pinned
+ bitset = (mark_bits[0] & ~pin_bits[0]);
+ bitset >>= NUM_IN_PAGE(p);
+ if (bitset) {
+ if (!gc_compact_plane(objspace, size_pool, heap, (uintptr_t)p, bitset, page))
+ return false;
+ }
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ for (int j = 1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bitset = (mark_bits[j] & ~pin_bits[j]);
+ if (bitset) {
+ if (!gc_compact_plane(objspace, size_pool, heap, (uintptr_t)p, bitset, page))
+ return false;
+ }
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+
+ return true;
+}
+
+static bool
+gc_compact_all_compacted_p(rb_objspace_t *objspace)
+{
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+
+ if (heap->total_pages > 0 &&
+ !gc_compact_heap_cursors_met_p(heap)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void
+gc_sweep_compact(rb_objspace_t *objspace)
+{
+ gc_compact_start(objspace);
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+
+ while (!gc_compact_all_compacted_p(objspace)) {
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+
+ if (gc_compact_heap_cursors_met_p(heap)) {
+ continue;
+ }
+
+ struct heap_page *start_page = heap->compact_cursor;
+
+ if (!gc_compact_page(objspace, size_pool, heap, start_page)) {
+ lock_page_body(objspace, GET_PAGE_BODY(start_page->start));
+
+ continue;
+ }
+
+ // If we get here, we've finished moving all objects on the compact_cursor page
+ // So we can lock it and move the cursor on to the next one.
+ lock_page_body(objspace, GET_PAGE_BODY(start_page->start));
+ heap->compact_cursor = ccan_list_prev(&heap->pages, heap->compact_cursor, page_node);
+ }
+ }
+
+ gc_compact_finish(objspace);
+
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+}
+
static void
gc_marks_rest(rb_objspace_t *objspace)
{
gc_report(1, objspace, "gc_marks_rest\n");
#if GC_ENABLE_INCREMENTAL_MARK
- heap_eden->pooled_pages = NULL;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ SIZE_POOL_EDEN_HEAP(&size_pools[i])->pooled_pages = NULL;
+ }
#endif
if (is_incremental_marking(objspace)) {
- do {
- while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == FALSE);
- } while (gc_marks_finish(objspace) == FALSE);
+ while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == FALSE);
}
else {
- gc_mark_stacked_objects_all(objspace);
- gc_marks_finish(objspace);
+ gc_mark_stacked_objects_all(objspace);
}
+ gc_marks_finish(objspace);
+
/* move to sweep */
gc_sweep(objspace);
}
static void
-gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap)
+gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
GC_ASSERT(dont_gc_val() == FALSE);
#if GC_ENABLE_INCREMENTAL_MARK
@@ -8102,24 +8704,8 @@ gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap)
unsigned int lock_lev;
gc_enter(objspace, gc_enter_event_mark_continue, &lock_lev);
- 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 (slots > 0) {
- gc_report(2, objspace, "gc_marks_continue: provide %d slots from %s.\n",
- slots, from);
+ if (heap->free_pages) {
+ gc_report(2, objspace, "gc_marks_continue: has pooled pages");
gc_marks_step(objspace, objspace->rincgc.step_slots);
}
else {
@@ -8159,29 +8745,29 @@ static void
gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
{
if (level <= RGENGC_DEBUG) {
- char buf[1024];
- FILE *out = stderr;
- va_list args;
- const char *status = " ";
+ char buf[1024];
+ FILE *out = stderr;
+ va_list args;
+ const char *status = " ";
- if (during_gc) {
- status = is_full_marking(objspace) ? "+" : "-";
- }
- else {
- if (is_lazy_sweeping(heap_eden)) {
- status = "S";
- }
- if (is_incremental_marking(objspace)) {
- status = "M";
- }
- }
+ if (during_gc) {
+ status = is_full_marking(objspace) ? "+" : "-";
+ }
+ else {
+ if (is_lazy_sweeping(objspace)) {
+ status = "S";
+ }
+ if (is_incremental_marking(objspace)) {
+ status = "M";
+ }
+ }
- va_start(args, fmt);
- vsnprintf(buf, 1024, fmt, args);
- va_end(args);
+ va_start(args, fmt);
+ vsnprintf(buf, 1024, fmt, args);
+ va_end(args);
- fprintf(out, "%s|", status);
- fputs(buf, out);
+ fprintf(out, "%s|", status);
+ fputs(buf, out);
}
}
@@ -8202,12 +8788,12 @@ rgengc_remembersetbits_set(rb_objspace_t *objspace, VALUE obj)
GC_ASSERT(!is_incremental_marking(objspace));
if (MARKED_IN_BITMAP(bits, obj)) {
- return FALSE;
+ return FALSE;
}
else {
- page->flags.has_remembered_objects = TRUE;
- MARK_IN_BITMAP(bits, obj);
- return TRUE;
+ page->flags.has_remembered_objects = TRUE;
+ MARK_IN_BITMAP(bits, obj);
+ return TRUE;
}
}
@@ -8218,22 +8804,22 @@ static int
rgengc_remember(rb_objspace_t *objspace, VALUE obj)
{
gc_report(6, objspace, "rgengc_remember: %s %s\n", obj_info(obj),
- rgengc_remembersetbits_get(objspace, obj) ? "was already remembered" : "is remembered now");
+ rgengc_remembersetbits_get(objspace, obj) ? "was already remembered" : "is remembered now");
check_rvalue_consistency(obj);
if (RGENGC_CHECK_MODE) {
- if (RVALUE_WB_UNPROTECTED(obj)) rb_bug("rgengc_remember: %s is not wb protected.", obj_info(obj));
+ if (RVALUE_WB_UNPROTECTED(obj)) rb_bug("rgengc_remember: %s is not wb protected.", obj_info(obj));
}
#if RGENGC_PROFILE > 0
if (!rgengc_remembered(objspace, obj)) {
- if (RVALUE_WB_UNPROTECTED(obj) == 0) {
- objspace->profile.total_remembered_normal_object_count++;
+ if (RVALUE_WB_UNPROTECTED(obj) == 0) {
+ objspace->profile.total_remembered_normal_object_count++;
#if RGENGC_PROFILE >= 2
- objspace->profile.remembered_normal_object_count_types[BUILTIN_TYPE(obj)]++;
+ objspace->profile.remembered_normal_object_count_types[BUILTIN_TYPE(obj)]++;
#endif
- }
+ }
}
#endif /* RGENGC_PROFILE > 0 */
@@ -8260,7 +8846,7 @@ rgengc_remembered(rb_objspace_t *objspace, VALUE obj)
#endif
static inline void
-rgengc_rememberset_mark_in_plane(rb_objspace_t *objspace, intptr_t p, bits_t bitset)
+rgengc_rememberset_mark_plane(rb_objspace_t *objspace, uintptr_t p, bits_t bitset)
{
if (bitset) {
do {
@@ -8272,7 +8858,7 @@ rgengc_rememberset_mark_in_plane(rb_objspace_t *objspace, intptr_t p, bits_t bit
gc_mark_children(objspace, obj);
}
- p += sizeof(RVALUE);
+ p += BASE_SLOT_SIZE;
bitset >>= 1;
} while (bitset);
}
@@ -8288,39 +8874,39 @@ rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap)
#endif
gc_report(1, objspace, "rgengc_rememberset_mark: start\n");
- list_for_each(&heap->pages, page, page_node) {
- if (page->flags.has_remembered_objects | page->flags.has_uncollectible_shady_objects) {
- RVALUE *p = page->start;
- bits_t bitset, bits[HEAP_PAGE_BITMAP_LIMIT];
- bits_t *marking_bits = page->marking_bits;
- bits_t *uncollectible_bits = page->uncollectible_bits;
- bits_t *wb_unprotected_bits = page->wb_unprotected_bits;
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ if (page->flags.has_remembered_objects | page->flags.has_uncollectible_shady_objects) {
+ uintptr_t p = page->start;
+ bits_t bitset, bits[HEAP_PAGE_BITMAP_LIMIT];
+ bits_t *marking_bits = page->marking_bits;
+ bits_t *uncollectible_bits = page->uncollectible_bits;
+ bits_t *wb_unprotected_bits = page->wb_unprotected_bits;
#if PROFILE_REMEMBERSET_MARK
- if (page->flags.has_remembered_objects && page->flags.has_uncollectible_shady_objects) has_both++;
- else if (page->flags.has_remembered_objects) has_old++;
- else if (page->flags.has_uncollectible_shady_objects) has_shady++;
+ if (page->flags.has_remembered_objects && page->flags.has_uncollectible_shady_objects) has_both++;
+ else if (page->flags.has_remembered_objects) has_old++;
+ else if (page->flags.has_uncollectible_shady_objects) has_shady++;
#endif
- for (j=0; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
- bits[j] = marking_bits[j] | (uncollectible_bits[j] & wb_unprotected_bits[j]);
- marking_bits[j] = 0;
- }
- page->flags.has_remembered_objects = FALSE;
+ for (j=0; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bits[j] = marking_bits[j] | (uncollectible_bits[j] & wb_unprotected_bits[j]);
+ marking_bits[j] = 0;
+ }
+ page->flags.has_remembered_objects = FALSE;
bitset = bits[0];
bitset >>= NUM_IN_PAGE(p);
- rgengc_rememberset_mark_in_plane(objspace, (intptr_t)p, bitset);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p));
-
- for (j=1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
- bitset = bits[j];
- rgengc_rememberset_mark_in_plane(objspace, (intptr_t)p, bitset);
- p += BITS_BITLENGTH;
- }
- }
+ rgengc_rememberset_mark_plane(objspace, p, bitset);
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ for (j=1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bitset = bits[j];
+ rgengc_rememberset_mark_plane(objspace, p, bitset);
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+ }
#if PROFILE_REMEMBERSET_MARK
- else {
- skip++;
- }
+ else {
+ skip++;
+ }
#endif
}
@@ -8335,13 +8921,13 @@ rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap)
{
struct heap_page *page = 0;
- list_for_each(&heap->pages, page, page_node) {
- memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- memset(&page->uncollectible_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ memset(&page->uncollectible_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
memset(&page->marking_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
memset(&page->pinned_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- page->flags.has_uncollectible_shady_objects = FALSE;
- page->flags.has_remembered_objects = FALSE;
+ page->flags.has_uncollectible_shady_objects = FALSE;
+ page->flags.has_remembered_objects = FALSE;
}
}
@@ -8353,9 +8939,9 @@ static void
gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace)
{
if (RGENGC_CHECK_MODE) {
- if (!RVALUE_OLD_P(a)) rb_bug("gc_writebarrier_generational: %s is not an old object.", obj_info(a));
- if ( RVALUE_OLD_P(b)) rb_bug("gc_writebarrier_generational: %s is an old object.", obj_info(b));
- if (is_incremental_marking(objspace)) rb_bug("gc_writebarrier_generational: called while incremental marking: %s -> %s", obj_info(a), obj_info(b));
+ if (!RVALUE_OLD_P(a)) rb_bug("gc_writebarrier_generational: %s is not an old object.", obj_info(a));
+ if ( RVALUE_OLD_P(b)) rb_bug("gc_writebarrier_generational: %s is an old object.", obj_info(b));
+ if (is_incremental_marking(objspace)) rb_bug("gc_writebarrier_generational: called while incremental marking: %s -> %s", obj_info(a), obj_info(b));
}
#if 1
@@ -8366,17 +8952,17 @@ gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace)
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));
+ gc_report(1, objspace, "gc_writebarrier_generational: %s (remembered) -> %s\n", obj_info(a), obj_info(b));
}
#else
/* mark `b' and remember */
MARK_IN_BITMAP(GET_HEAP_MARK_BITS(b), b);
if (RVALUE_WB_UNPROTECTED(b)) {
- gc_remember_unprotected(objspace, b);
+ gc_remember_unprotected(objspace, b);
}
else {
- RVALUE_AGE_SET_OLD(objspace, b);
- rgengc_remember(objspace, b);
+ RVALUE_AGE_SET_OLD(objspace, b);
+ rgengc_remember(objspace, b);
}
gc_report(1, objspace, "gc_writebarrier_generational: %s -> %s (remembered)\n", obj_info(a), obj_info(b));
@@ -8405,26 +8991,26 @@ gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace)
gc_report(2, objspace, "gc_writebarrier_incremental: [LG] %p -> %s\n", (void *)a, obj_info(b));
if (RVALUE_BLACK_P(a)) {
- if (RVALUE_WHITE_P(b)) {
- if (!RVALUE_WB_UNPROTECTED(a)) {
- gc_report(2, objspace, "gc_writebarrier_incremental: [IN] %p -> %s\n", (void *)a, obj_info(b));
- gc_mark_from(objspace, b, a);
- }
- }
- else if (RVALUE_OLD_P(a) && !RVALUE_OLD_P(b)) {
- if (!RVALUE_WB_UNPROTECTED(b)) {
- gc_report(1, objspace, "gc_writebarrier_incremental: [GN] %p -> %s\n", (void *)a, obj_info(b));
- RVALUE_AGE_SET_OLD(objspace, b);
-
- if (RVALUE_BLACK_P(b)) {
- gc_grey(objspace, b);
- }
- }
- else {
- gc_report(1, objspace, "gc_writebarrier_incremental: [LL] %p -> %s\n", (void *)a, obj_info(b));
- gc_remember_unprotected(objspace, b);
- }
- }
+ if (RVALUE_WHITE_P(b)) {
+ if (!RVALUE_WB_UNPROTECTED(a)) {
+ gc_report(2, objspace, "gc_writebarrier_incremental: [IN] %p -> %s\n", (void *)a, obj_info(b));
+ gc_mark_from(objspace, b, a);
+ }
+ }
+ else if (RVALUE_OLD_P(a) && !RVALUE_OLD_P(b)) {
+ if (!RVALUE_WB_UNPROTECTED(b)) {
+ gc_report(1, objspace, "gc_writebarrier_incremental: [GN] %p -> %s\n", (void *)a, obj_info(b));
+ RVALUE_AGE_SET_OLD(objspace, b);
+
+ if (RVALUE_BLACK_P(b)) {
+ gc_grey(objspace, b);
+ }
+ }
+ else {
+ gc_report(1, objspace, "gc_writebarrier_incremental: [LL] %p -> %s\n", (void *)a, obj_info(b));
+ gc_remember_unprotected(objspace, b);
+ }
+ }
if (UNLIKELY(objspace->flags.during_compacting)) {
MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(b), b);
@@ -8440,8 +9026,10 @@ rb_gc_writebarrier(VALUE a, VALUE b)
{
rb_objspace_t *objspace = &rb_objspace;
- if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(a)) rb_bug("rb_gc_writebarrier: a is special const");
- if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const");
+ if (RGENGC_CHECK_MODE) {
+ if (SPECIAL_CONST_P(a)) rb_bug("rb_gc_writebarrier: a is special const: %"PRIxVALUE, a);
+ if (SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const: %"PRIxVALUE, b);
+ }
retry:
if (!is_incremental_marking(objspace)) {
@@ -8475,33 +9063,37 @@ void
rb_gc_writebarrier_unprotect(VALUE obj)
{
if (RVALUE_WB_UNPROTECTED(obj)) {
- return;
+ return;
}
else {
- rb_objspace_t *objspace = &rb_objspace;
+ rb_objspace_t *objspace = &rb_objspace;
- gc_report(2, objspace, "rb_gc_writebarrier_unprotect: %s %s\n", obj_info(obj),
- rgengc_remembered(objspace, obj) ? " (already remembered)" : "");
+ gc_report(2, objspace, "rb_gc_writebarrier_unprotect: %s %s\n", obj_info(obj),
+ rgengc_remembered(objspace, obj) ? " (already remembered)" : "");
- if (RVALUE_OLD_P(obj)) {
- gc_report(1, objspace, "rb_gc_writebarrier_unprotect: %s\n", obj_info(obj));
- RVALUE_DEMOTE(objspace, obj);
- gc_mark_set(objspace, obj);
- gc_remember_unprotected(objspace, obj);
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ if (RVALUE_OLD_P(obj)) {
+ gc_report(1, objspace, "rb_gc_writebarrier_unprotect: %s\n", obj_info(obj));
+ RVALUE_DEMOTE(objspace, obj);
+ gc_mark_set(objspace, obj);
+ gc_remember_unprotected(objspace, obj);
#if RGENGC_PROFILE
- objspace->profile.total_shade_operation_count++;
+ objspace->profile.total_shade_operation_count++;
#if RGENGC_PROFILE >= 2
- objspace->profile.shade_operation_count_types[BUILTIN_TYPE(obj)]++;
+ objspace->profile.shade_operation_count_types[BUILTIN_TYPE(obj)]++;
#endif /* RGENGC_PROFILE >= 2 */
#endif /* RGENGC_PROFILE */
- }
- else {
- RVALUE_AGE_RESET(obj);
- }
+ }
+ else {
+ RVALUE_AGE_RESET(obj);
+ }
- RB_DEBUG_COUNTER_INC(obj_wb_unprotect);
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ RB_DEBUG_COUNTER_INC(obj_wb_unprotect);
+ MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ }
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
}
}
@@ -8516,14 +9108,14 @@ rb_gc_writebarrier_remember(VALUE obj)
gc_report(1, objspace, "rb_gc_writebarrier_remember: %s\n", obj_info(obj));
if (is_incremental_marking(objspace)) {
- if (RVALUE_BLACK_P(obj)) {
- gc_grey(objspace, obj);
- }
+ if (RVALUE_BLACK_P(obj)) {
+ gc_grey(objspace, obj);
+ }
}
else {
- if (RVALUE_OLD_P(obj)) {
- rgengc_remember(objspace, obj);
- }
+ if (RVALUE_OLD_P(obj)) {
+ rgengc_remember(objspace, obj);
+ }
}
}
@@ -8548,25 +9140,25 @@ rb_gc_unprotect_logging(void *objptr, const char *filename, int line)
VALUE obj = (VALUE)objptr;
if (rgengc_unprotect_logging_table == 0) {
- rgengc_unprotect_logging_table = st_init_strtable();
- atexit(rgengc_unprotect_logging_exit_func);
+ rgengc_unprotect_logging_table = st_init_strtable();
+ atexit(rgengc_unprotect_logging_exit_func);
}
if (RVALUE_WB_UNPROTECTED(obj) == 0) {
- char buff[0x100];
- st_data_t cnt = 1;
- char *ptr = buff;
+ char buff[0x100];
+ st_data_t cnt = 1;
+ char *ptr = buff;
- snprintf(ptr, 0x100 - 1, "%s|%s:%d", obj_info(obj), filename, line);
+ snprintf(ptr, 0x100 - 1, "%s|%s:%d", obj_info(obj), filename, line);
- if (st_lookup(rgengc_unprotect_logging_table, (st_data_t)ptr, &cnt)) {
- cnt++;
- }
- else {
- ptr = (strdup)(buff);
- if (!ptr) rb_memerror();
- }
- st_insert(rgengc_unprotect_logging_table, (st_data_t)ptr, cnt);
+ if (st_lookup(rgengc_unprotect_logging_table, (st_data_t)ptr, &cnt)) {
+ cnt++;
+ }
+ else {
+ ptr = (strdup)(buff);
+ if (!ptr) rb_memerror();
+ }
+ st_insert(rgengc_unprotect_logging_table, (st_data_t)ptr, cnt);
}
}
@@ -8576,13 +9168,13 @@ rb_copy_wb_protected_attribute(VALUE dest, VALUE obj)
rb_objspace_t *objspace = &rb_objspace;
if (RVALUE_WB_UNPROTECTED(obj) && !RVALUE_WB_UNPROTECTED(dest)) {
- if (!RVALUE_OLD_P(dest)) {
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(dest), dest);
- RVALUE_AGE_RESET_RAW(dest);
- }
- else {
- RVALUE_DEMOTE(objspace, dest);
- }
+ if (!RVALUE_OLD_P(dest)) {
+ MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(dest), dest);
+ RVALUE_AGE_RESET_RAW(dest);
+ }
+ else {
+ RVALUE_DEMOTE(objspace, dest);
+ }
}
check_rvalue_consistency(dest);
@@ -8593,7 +9185,7 @@ rb_copy_wb_protected_attribute(VALUE dest, VALUE obj)
VALUE
rb_obj_rgengc_writebarrier_protected_p(VALUE obj)
{
- return RVALUE_WB_UNPROTECTED(obj) ? Qfalse : Qtrue;
+ return RBOOL(!RVALUE_WB_UNPROTECTED(obj));
}
VALUE
@@ -8611,11 +9203,11 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
if (!ID_marked) {
#define I(s) ID_##s = rb_intern(#s);
- I(marked);
- I(wb_protected);
- I(old);
- I(marking);
- I(uncollectible);
+ I(marked);
+ I(wb_protected);
+ I(old);
+ I(marking);
+ I(uncollectible);
I(pinned);
#undef I
}
@@ -8634,80 +9226,28 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
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 GC_ENABLE_INCREMENTAL_MARK
+ newobj_cache->incremental_mark_step_allocated_slots = 0;
+#endif
- 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*));
- }
+ for (size_t size_pool_idx = 0; size_pool_idx < SIZE_POOL_COUNT; size_pool_idx++) {
+ rb_ractor_newobj_size_pool_cache_t *cache = &newobj_cache->size_pool_caches[size_pool_idx];
+
+ struct heap_page *page = cache->using_page;
+ RVALUE *freelist = cache->freelist;
+ RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", (void *)page, (void *)freelist);
- newobj_cache->using_page = NULL;
- newobj_cache->freelist = NULL;
+ heap_page_freelist_append(page, freelist);
+
+ cache->using_page = NULL;
+ 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);
-
- 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);
- CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
-
- if (is_incremental_marking(objspace)) {
-#if GC_ENABLE_INCREMENTAL_MARK
- 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);
-#endif
- }
- else {
- 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);
- }
-
- objspace->profile.total_freed_objects++;
-
- heap_page_add_freeobj(objspace, GET_HEAP_PAGE(obj), obj);
-
- /* Disable counting swept_slots because there are no meaning.
- * if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) {
- * objspace->heap.swept_slots++;
- * }
- */
- }
- RB_VM_LOCK_LEAVE();
+ /* no-op */
}
#ifndef MARK_OBJECT_ARY_BUCKET_SIZE
@@ -8725,8 +9265,8 @@ rb_gc_register_mark_object(VALUE obj)
VALUE ary_ary = GET_VM()->mark_object_ary;
VALUE ary = rb_ary_last(0, 0, ary_ary);
- if (ary == Qnil || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
- ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE);
+ if (NIL_P(ary) || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
+ ary = rb_ary_hidden_new(MARK_OBJECT_ARY_BUCKET_SIZE);
rb_ary_push(ary_ary, ary);
}
@@ -8741,10 +9281,23 @@ rb_gc_register_address(VALUE *addr)
rb_objspace_t *objspace = &rb_objspace;
struct gc_list *tmp;
+ VALUE obj = *addr;
+
tmp = ALLOC(struct gc_list);
tmp->next = global_list;
tmp->varptr = addr;
global_list = tmp;
+
+ /*
+ * Because some C extensions have assignment-then-register bugs,
+ * we guard `obj` here so that it would not get swept defensively.
+ */
+ RB_GC_GUARD(obj);
+ if (0 && !SPECIAL_CONST_P(obj)) {
+ rb_warn("Object is assigned to registering address already: %"PRIsVALUE,
+ rb_obj_class(obj));
+ rb_print_backtrace();
+ }
}
void
@@ -8754,19 +9307,19 @@ rb_gc_unregister_address(VALUE *addr)
struct gc_list *tmp = global_list;
if (tmp->varptr == addr) {
- global_list = tmp->next;
- xfree(tmp);
- return;
+ global_list = tmp->next;
+ xfree(tmp);
+ return;
}
while (tmp->next) {
- if (tmp->next->varptr == addr) {
- struct gc_list *t = tmp->next;
+ if (tmp->next->varptr == addr) {
+ struct gc_list *t = tmp->next;
- tmp->next = tmp->next->next;
- xfree(t);
- break;
- }
- tmp = tmp->next;
+ tmp->next = tmp->next->next;
+ xfree(t);
+ break;
+ }
+ tmp = tmp->next;
}
}
@@ -8789,13 +9342,13 @@ enum {
(FIXNUM_P(ruby_gc_stress_mode) && (FIX2LONG(ruby_gc_stress_mode) & (1<<gc_stress_full_mark_after_malloc)))
static void
-heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap)
+heap_ready_to_gc(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
{
if (!heap->free_pages) {
- if (!heap_increment(objspace, heap)) {
- heap_allocatable_pages_set(objspace, 1);
- heap_increment(objspace, heap);
- }
+ if (!heap_increment(objspace, size_pool, heap)) {
+ size_pool_allocatable_pages_set(objspace, size_pool, 1);
+ heap_increment(objspace, size_pool, heap);
+ }
}
}
@@ -8803,78 +9356,81 @@ static int
ready_to_gc(rb_objspace_t *objspace)
{
if (dont_gc_val() || during_gc || ruby_disable_gc) {
- heap_ready_to_gc(objspace, heap_eden);
- return FALSE;
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ heap_ready_to_gc(objspace, size_pool, SIZE_POOL_EDEN_HEAP(size_pool));
+ }
+ return FALSE;
}
else {
- return TRUE;
+ return TRUE;
}
}
static void
-gc_reset_malloc_info(rb_objspace_t *objspace)
+gc_reset_malloc_info(rb_objspace_t *objspace, bool full_mark)
{
gc_prof_set_malloc_info(objspace);
{
- size_t inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
- size_t old_limit = malloc_limit;
-
- if (inc > malloc_limit) {
- malloc_limit = (size_t)(inc * gc_params.malloc_limit_growth_factor);
- if (malloc_limit > gc_params.malloc_limit_max) {
- malloc_limit = gc_params.malloc_limit_max;
- }
- }
- else {
- malloc_limit = (size_t)(malloc_limit * 0.98); /* magic number */
- if (malloc_limit < gc_params.malloc_limit_min) {
- malloc_limit = gc_params.malloc_limit_min;
- }
- }
-
- if (0) {
- if (old_limit != malloc_limit) {
- fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: %"PRIuSIZE" -> %"PRIuSIZE"\n",
- rb_gc_count(), old_limit, malloc_limit);
- }
- else {
- fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: not changed (%"PRIuSIZE")\n",
- rb_gc_count(), malloc_limit);
- }
- }
+ size_t inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
+ size_t old_limit = malloc_limit;
+
+ if (inc > malloc_limit) {
+ malloc_limit = (size_t)(inc * gc_params.malloc_limit_growth_factor);
+ if (malloc_limit > gc_params.malloc_limit_max) {
+ malloc_limit = gc_params.malloc_limit_max;
+ }
+ }
+ else {
+ malloc_limit = (size_t)(malloc_limit * 0.98); /* magic number */
+ if (malloc_limit < gc_params.malloc_limit_min) {
+ malloc_limit = gc_params.malloc_limit_min;
+ }
+ }
+
+ if (0) {
+ if (old_limit != malloc_limit) {
+ fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: %"PRIuSIZE" -> %"PRIuSIZE"\n",
+ rb_gc_count(), old_limit, malloc_limit);
+ }
+ else {
+ fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: not changed (%"PRIuSIZE")\n",
+ rb_gc_count(), malloc_limit);
+ }
+ }
}
/* reset oldmalloc info */
#if RGENGC_ESTIMATE_OLDMALLOC
- if (!is_full_marking(objspace)) {
- if (objspace->rgengc.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) {
- objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDMALLOC;
- objspace->rgengc.oldmalloc_increase_limit =
- (size_t)(objspace->rgengc.oldmalloc_increase_limit * gc_params.oldmalloc_limit_growth_factor);
-
- if (objspace->rgengc.oldmalloc_increase_limit > gc_params.oldmalloc_limit_max) {
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_max;
- }
- }
-
- if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n",
- rb_gc_count(),
- objspace->rgengc.need_major_gc,
- objspace->rgengc.oldmalloc_increase,
- objspace->rgengc.oldmalloc_increase_limit,
- gc_params.oldmalloc_limit_max);
+ if (!full_mark) {
+ if (objspace->rgengc.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) {
+ objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_OLDMALLOC;
+ objspace->rgengc.oldmalloc_increase_limit =
+ (size_t)(objspace->rgengc.oldmalloc_increase_limit * gc_params.oldmalloc_limit_growth_factor);
+
+ if (objspace->rgengc.oldmalloc_increase_limit > gc_params.oldmalloc_limit_max) {
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_max;
+ }
+ }
+
+ if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n",
+ rb_gc_count(),
+ objspace->rgengc.need_major_gc,
+ objspace->rgengc.oldmalloc_increase,
+ objspace->rgengc.oldmalloc_increase_limit,
+ gc_params.oldmalloc_limit_max);
}
else {
- /* major GC */
- objspace->rgengc.oldmalloc_increase = 0;
-
- if ((objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_BY_OLDMALLOC) == 0) {
- objspace->rgengc.oldmalloc_increase_limit =
- (size_t)(objspace->rgengc.oldmalloc_increase_limit / ((gc_params.oldmalloc_limit_growth_factor - 1)/10 + 1));
- if (objspace->rgengc.oldmalloc_increase_limit < gc_params.oldmalloc_limit_min) {
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
- }
- }
+ /* major GC */
+ objspace->rgengc.oldmalloc_increase = 0;
+
+ if ((objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_BY_OLDMALLOC) == 0) {
+ objspace->rgengc.oldmalloc_increase_limit =
+ (size_t)(objspace->rgengc.oldmalloc_increase_limit / ((gc_params.oldmalloc_limit_growth_factor - 1)/10 + 1));
+ if (objspace->rgengc.oldmalloc_increase_limit < gc_params.oldmalloc_limit_min) {
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
+ }
+ }
}
#endif
}
@@ -8915,13 +9471,18 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
objspace->flags.immediate_sweep = !!(reason & GPR_FLAG_IMMEDIATE_SWEEP);
/* Explicitly enable compaction (GC.compact) */
- objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
+ if (do_full_mark && ruby_enable_autocompact) {
+ objspace->flags.during_compacting = TRUE;
+ }
+ else {
+ objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
+ }
if (!heap_allocated_pages) return FALSE; /* heap is not ready */
if (!(reason & GPR_FLAG_METHOD) && !ready_to_gc(objspace)) return TRUE; /* GC is not allowed */
GC_ASSERT(gc_mode(objspace) == gc_mode_none);
- GC_ASSERT(!is_lazy_sweeping(heap_eden));
+ GC_ASSERT(!is_lazy_sweeping(objspace));
GC_ASSERT(!is_incremental_marking(objspace));
unsigned int lock_lev;
@@ -8932,49 +9493,49 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
#endif
if (ruby_gc_stressful) {
- int flag = FIXNUM_P(ruby_gc_stress_mode) ? FIX2INT(ruby_gc_stress_mode) : 0;
+ int flag = FIXNUM_P(ruby_gc_stress_mode) ? FIX2INT(ruby_gc_stress_mode) : 0;
- if ((flag & (1<<gc_stress_no_major)) == 0) {
- do_full_mark = TRUE;
- }
+ if ((flag & (1<<gc_stress_no_major)) == 0) {
+ do_full_mark = TRUE;
+ }
- objspace->flags.immediate_sweep = !(flag & (1<<gc_stress_no_immediate_sweep));
+ objspace->flags.immediate_sweep = !(flag & (1<<gc_stress_no_immediate_sweep));
}
else {
- if (objspace->rgengc.need_major_gc) {
- reason |= objspace->rgengc.need_major_gc;
- do_full_mark = TRUE;
- }
- else if (RGENGC_FORCE_MAJOR_GC) {
- reason = GPR_FLAG_MAJOR_BY_FORCE;
- do_full_mark = TRUE;
- }
+ if (objspace->rgengc.need_major_gc) {
+ reason |= objspace->rgengc.need_major_gc;
+ do_full_mark = TRUE;
+ }
+ else if (RGENGC_FORCE_MAJOR_GC) {
+ reason = GPR_FLAG_MAJOR_BY_FORCE;
+ do_full_mark = TRUE;
+ }
- objspace->rgengc.need_major_gc = GPR_FLAG_NONE;
+ objspace->rgengc.need_major_gc = GPR_FLAG_NONE;
}
if (do_full_mark && (reason & GPR_FLAG_MAJOR_MASK) == 0) {
- reason |= GPR_FLAG_MAJOR_BY_FORCE; /* GC by CAPI, METHOD, and so on. */
+ reason |= GPR_FLAG_MAJOR_BY_FORCE; /* GC by CAPI, METHOD, and so on. */
}
#if GC_ENABLE_INCREMENTAL_MARK
if (!GC_ENABLE_INCREMENTAL_MARK || objspace->flags.dont_incremental || immediate_mark) {
- objspace->flags.during_incremental_marking = FALSE;
+ objspace->flags.during_incremental_marking = FALSE;
}
else {
- objspace->flags.during_incremental_marking = do_full_mark;
+ objspace->flags.during_incremental_marking = do_full_mark;
}
#endif
if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_incremental) {
- objspace->flags.immediate_sweep = TRUE;
+ objspace->flags.immediate_sweep = TRUE;
}
if (objspace->flags.immediate_sweep) reason |= GPR_FLAG_IMMEDIATE_SWEEP;
gc_report(1, objspace, "gc_start(reason: %x) => %u, %d, %d\n",
- reason,
- do_full_mark, !is_incremental_marking(objspace), objspace->flags.immediate_sweep);
+ reason,
+ do_full_mark, !is_incremental_marking(objspace), objspace->flags.immediate_sweep);
#if USE_DEBUG_COUNTER
RB_DEBUG_COUNTER_INC(gc_count);
@@ -9002,7 +9563,7 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
objspace->profile.total_allocated_objects_at_gc_start = objspace->total_allocated_objects;
objspace->profile.heap_used_at_gc_start = heap_allocated_pages;
gc_prof_setup_new_record(objspace, reason);
- gc_reset_malloc_info(objspace);
+ gc_reset_malloc_info(objspace, do_full_mark);
rb_transient_heap_start_marking(do_full_mark);
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_START, 0 /* TODO: pass minor/immediate flag? */);
@@ -9010,7 +9571,7 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
gc_prof_timer_start(objspace);
{
- gc_marks(objspace, do_full_mark);
+ gc_marks(objspace, do_full_mark);
}
gc_prof_timer_stop(objspace);
@@ -9022,21 +9583,21 @@ static void
gc_rest(rb_objspace_t *objspace)
{
int marking = is_incremental_marking(objspace);
- int sweeping = is_lazy_sweeping(heap_eden);
+ int sweeping = is_lazy_sweeping(objspace);
if (marking || sweeping) {
unsigned int lock_lev;
- gc_enter(objspace, gc_enter_event_rest, &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)) {
+ if (is_incremental_marking(objspace)) {
gc_marks_rest(objspace);
}
- if (is_lazy_sweeping(heap_eden)) {
- gc_sweep_rest(objspace);
- }
- gc_exit(objspace, gc_enter_event_rest, &lock_lev);
+ if (is_lazy_sweeping(objspace)) {
+ gc_sweep_rest(objspace);
+ }
+ gc_exit(objspace, gc_enter_event_rest, &lock_lev);
}
}
@@ -9050,18 +9611,18 @@ gc_current_status_fill(rb_objspace_t *objspace, char *buff)
{
int i = 0;
if (is_marking(objspace)) {
- buff[i++] = 'M';
- if (is_full_marking(objspace)) buff[i++] = 'F';
+ buff[i++] = 'M';
+ if (is_full_marking(objspace)) buff[i++] = 'F';
#if GC_ENABLE_INCREMENTAL_MARK
- if (is_incremental_marking(objspace)) buff[i++] = 'I';
+ if (is_incremental_marking(objspace)) buff[i++] = 'I';
#endif
}
else if (is_sweeping(objspace)) {
- buff[i++] = 'S';
- if (is_lazy_sweeping(heap_eden)) buff[i++] = 'L';
+ buff[i++] = 'S';
+ if (is_lazy_sweeping(objspace)) buff[i++] = 'L';
}
else {
- buff[i++] = 'N';
+ buff[i++] = 'N';
}
buff[i] = '\0';
}
@@ -9085,31 +9646,31 @@ static inline void
gc_record(rb_objspace_t *objspace, int direction, const char *event)
{
if (direction == 0) { /* enter */
- enter_count++;
- enter_tick = tick();
- gc_current_status_fill(objspace, last_gc_status);
+ enter_count++;
+ enter_tick = tick();
+ gc_current_status_fill(objspace, last_gc_status);
}
else { /* exit */
- tick_t exit_tick = tick();
- char current_gc_status[0x10];
- gc_current_status_fill(objspace, current_gc_status);
+ tick_t exit_tick = tick();
+ char current_gc_status[0x10];
+ gc_current_status_fill(objspace, current_gc_status);
#if 1
- /* [last mutator time] [gc time] [event] */
- fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
- enter_tick - last_exit_tick,
- exit_tick - enter_tick,
- event,
- last_gc_status, current_gc_status,
- (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
- last_exit_tick = exit_tick;
+ /* [last mutator time] [gc time] [event] */
+ fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
+ enter_tick - last_exit_tick,
+ exit_tick - enter_tick,
+ event,
+ last_gc_status, current_gc_status,
+ (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
+ last_exit_tick = exit_tick;
#else
- /* [enter_tick] [gc time] [event] */
- fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
- enter_tick,
- exit_tick - enter_tick,
- event,
- last_gc_status, current_gc_status,
- (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
+ /* [enter_tick] [gc time] [event] */
+ fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
+ enter_tick,
+ exit_tick - enter_tick,
+ event,
+ last_gc_status, current_gc_status,
+ (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
#endif
}
}
@@ -9148,11 +9709,72 @@ gc_enter_count(enum gc_enter_event event)
}
}
+#ifndef MEASURE_GC
+#define MEASURE_GC (objspace->flags.measure_gc)
+#endif
+
+static bool
+gc_enter_event_measure_p(rb_objspace_t *objspace, enum gc_enter_event event)
+{
+ if (!MEASURE_GC) return false;
+
+ switch (event) {
+ case gc_enter_event_start:
+ case gc_enter_event_mark_continue:
+ case gc_enter_event_sweep_continue:
+ case gc_enter_event_rest:
+ return true;
+
+ default:
+ // case gc_enter_event_finalizer:
+ // case gc_enter_event_rb_memerror:
+ return false;
+ }
+}
+
+static bool current_process_time(struct timespec *ts);
+
+static void
+gc_enter_clock(rb_objspace_t *objspace, enum gc_enter_event event)
+{
+ if (gc_enter_event_measure_p(objspace, event)) {
+ if (!current_process_time(&objspace->profile.start_time)) {
+ objspace->profile.start_time.tv_sec = 0;
+ objspace->profile.start_time.tv_nsec = 0;
+ }
+ }
+}
+
+static void
+gc_exit_clock(rb_objspace_t *objspace, enum gc_enter_event event)
+{
+ if (gc_enter_event_measure_p(objspace, event)) {
+ struct timespec end_time;
+
+ if ((objspace->profile.start_time.tv_sec > 0 ||
+ objspace->profile.start_time.tv_nsec > 0) &&
+ current_process_time(&end_time)) {
+
+ if (end_time.tv_sec < objspace->profile.start_time.tv_sec) {
+ return; // ignore
+ }
+ else {
+ uint64_t ns =
+ (uint64_t)(end_time.tv_sec - objspace->profile.start_time.tv_sec) * (1000 * 1000 * 1000) +
+ (end_time.tv_nsec - objspace->profile.start_time.tv_nsec);
+ objspace->profile.total_time_ns += ns;
+ }
+ }
+ }
+}
+
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);
+ gc_enter_clock(objspace, event);
+
switch (event) {
case gc_enter_event_rest:
if (!is_marking(objspace)) break;
@@ -9170,8 +9792,6 @@ gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_
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;
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));
@@ -9190,8 +9810,16 @@ gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_l
gc_report(1, objspace, "gc_exit: %s [%s]\n", gc_enter_event_cstr(event), gc_current_status(objspace));
during_gc = FALSE;
- mjit_gc_exit_hook();
+ gc_exit_clock(objspace, event);
RB_VM_LOCK_LEAVE_LEV(lock_lev);
+
+#if RGENGC_CHECK_MODE >= 2
+ if (event == gc_enter_event_sweep_continue && gc_mode(objspace) == gc_mode_none) {
+ GC_ASSERT(!during_gc);
+ // sweep finished
+ gc_verify_internal_consistency(objspace);
+ }
+#endif
}
static void *
@@ -9206,20 +9834,20 @@ garbage_collect_with_gvl(rb_objspace_t *objspace, unsigned int reason)
{
if (dont_gc_val()) return TRUE;
if (ruby_thread_has_gvl_p()) {
- return garbage_collect(objspace, reason);
+ return garbage_collect(objspace, reason);
}
else {
- if (ruby_native_thread_p()) {
- struct objspace_and_reason oar;
- oar.objspace = objspace;
- oar.reason = reason;
- return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)&oar);
- }
- else {
- /* no ruby thread */
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- exit(EXIT_FAILURE);
- }
+ if (ruby_native_thread_p()) {
+ struct objspace_and_reason oar;
+ oar.objspace = objspace;
+ oar.reason = reason;
+ return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)&oar);
+ }
+ else {
+ /* no ruby thread */
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ exit(EXIT_FAILURE);
+ }
}
}
@@ -9234,6 +9862,8 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE
/* For now, compact implies full mark / sweep, so ignore other flags */
if (RTEST(compact)) {
+ GC_ASSERT(GC_COMPACTION_SUPPORTED);
+
reason |= GPR_FLAG_COMPACT;
}
else {
@@ -9305,8 +9935,19 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
return FALSE;
}
+/* Used in places that could malloc, which can cause the GC to run. We need to
+ * temporarily disable the GC to allow the malloc to happen. */
+#define COULD_MALLOC_REGION_START() \
+ GC_ASSERT(during_gc); \
+ VALUE _already_disabled = rb_gc_disable_no_rest(); \
+ during_gc = false;
+
+#define COULD_MALLOC_REGION_END() \
+ during_gc = true; \
+ if (_already_disabled == Qfalse) rb_objspace_gc_enable(objspace);
+
static VALUE
-gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
+gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, size_t slot_size)
{
int marked;
int wb_unprotected;
@@ -9333,11 +9974,12 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS((VALUE)src), (VALUE)src);
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);
+ /* Resizing the st table could cause a malloc */
+ COULD_MALLOC_REGION_START();
+ {
+ rb_mv_generic_ivar((VALUE)src, (VALUE)dest);
+ }
+ COULD_MALLOC_REGION_END();
}
st_data_t srcid = (st_data_t)src, id;
@@ -9346,18 +9988,26 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
* the object to object id mapping. */
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);
- /* 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);
+ /* Resizing the st table could cause a malloc */
+ COULD_MALLOC_REGION_START();
+ {
+ st_delete(objspace->obj_to_id_tbl, &srcid, 0);
+ st_insert(objspace->obj_to_id_tbl, (st_data_t)dest, id);
+ }
+ COULD_MALLOC_REGION_END();
}
/* Move the object */
- memcpy(dest, src, sizeof(RVALUE));
- memset(src, 0, sizeof(RVALUE));
+ memcpy(dest, src, MIN(src_slot_size, slot_size));
+
+ if (RVALUE_OVERHEAD > 0) {
+ void *dest_overhead = (void *)(((uintptr_t)dest) + slot_size - RVALUE_OVERHEAD);
+ void *src_overhead = (void *)(((uintptr_t)src) + src_slot_size - RVALUE_OVERHEAD);
+
+ memcpy(dest_overhead, src_overhead, RVALUE_OVERHEAD);
+ }
+
+ memset(src, 0, src_slot_size);
/* Set bits for object in new location */
if (marking) {
@@ -9397,6 +10047,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
return (VALUE)src;
}
+#if GC_CAN_COMPILE_COMPACTION
static int
compare_free_slots(const void *left, const void *right, void *dummy)
{
@@ -9412,59 +10063,109 @@ compare_free_slots(const void *left, const void *right, void *dummy)
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);
- size_t i = 0;
+ for (int j = 0; j < SIZE_POOL_COUNT; j++) {
+ rb_size_pool_t *size_pool = &size_pools[j];
- list_for_each(&heap_eden->pages, page, page_node) {
- page_list[i++] = page;
- assert(page != NULL);
- }
- assert(total_pages > 0);
- assert((size_t)i == total_pages);
+ size_t total_pages = SIZE_POOL_EDEN_HEAP(size_pool)->total_pages;
+ size_t size = size_mul_or_raise(total_pages, sizeof(struct heap_page *), rb_eRuntimeError);
+ struct heap_page *page = 0, **page_list = malloc(size);
+ size_t i = 0;
- /* 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);
+ SIZE_POOL_EDEN_HEAP(size_pool)->free_pages = NULL;
+ ccan_list_for_each(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node) {
+ page_list[i++] = page;
+ GC_ASSERT(page);
+ }
+
+ GC_ASSERT((size_t)i == total_pages);
- /* Reset the eden heap */
- list_head_init(&objspace->eden_heap.pages);
+ /* Sort the heap so "filled pages" are first. `heap_add_page` adds to the
+ * head of the list, so empty pages will end up at the start of the heap */
+ ruby_qsort(page_list, total_pages, sizeof(struct heap_page *), compare_free_slots, NULL);
- 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]);
+ /* Reset the eden heap */
+ ccan_list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages);
+
+ for (i = 0; i < total_pages; i++) {
+ ccan_list_add(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, &page_list[i]->page_node);
+ if (page_list[i]->free_slots != 0) {
+ heap_add_freepage(SIZE_POOL_EDEN_HEAP(size_pool), page_list[i]);
+ }
}
- }
- free(page_list);
+ free(page_list);
+ }
}
+#endif
static void
gc_ref_update_array(rb_objspace_t * objspace, VALUE v)
{
- long i, len;
+ if (ARY_SHARED_P(v)) {
+#if USE_RVARGC
+ VALUE old_root = RARRAY(v)->as.heap.aux.shared_root;
+#endif
- if (FL_TEST(v, ELTS_SHARED))
- return;
+ UPDATE_IF_MOVED(objspace, RARRAY(v)->as.heap.aux.shared_root);
- len = RARRAY_LEN(v);
- if (len > 0) {
- VALUE *ptr = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(v);
- for (i = 0; i < len; i++) {
- UPDATE_IF_MOVED(objspace, ptr[i]);
+#if USE_RVARGC
+ VALUE new_root = RARRAY(v)->as.heap.aux.shared_root;
+ // If the root is embedded and its location has changed
+ if (ARY_EMBED_P(new_root) && new_root != old_root) {
+ size_t offset = (size_t)(RARRAY(v)->as.heap.ptr - RARRAY(old_root)->as.ary);
+ GC_ASSERT(RARRAY(v)->as.heap.ptr >= RARRAY(old_root)->as.ary);
+ RARRAY(v)->as.heap.ptr = RARRAY(new_root)->as.ary + offset;
}
+#endif
+ }
+ else {
+ long len = RARRAY_LEN(v);
+
+ if (len > 0) {
+ VALUE *ptr = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(v);
+ for (long i = 0; i < len; i++) {
+ UPDATE_IF_MOVED(objspace, ptr[i]);
+ }
+ }
+
+#if USE_RVARGC
+ if (rb_gc_obj_slot_size(v) >= rb_ary_size_as_embedded(v)) {
+ if (rb_ary_embeddable_p(v)) {
+ rb_ary_make_embedded(v);
+ }
+ }
+#endif
}
}
static void
-gc_ref_update_object(rb_objspace_t * objspace, VALUE v)
+gc_ref_update_object(rb_objspace_t *objspace, VALUE v)
{
VALUE *ptr = ROBJECT_IVPTR(v);
- uint32_t i, len = ROBJECT_NUMIV(v);
- for (i = 0; i < len; i++) {
+ if (rb_shape_obj_too_complex(v)) {
+ rb_gc_update_tbl_refs(ROBJECT_IV_HASH(v));
+ return;
+ }
+
+#if USE_RVARGC
+ size_t slot_size = rb_gc_obj_slot_size(v);
+ size_t embed_size = rb_obj_embedded_size(ROBJECT_IV_CAPACITY(v));
+ if (slot_size >= embed_size && !RB_FL_TEST_RAW(v, ROBJECT_EMBED)) {
+ // Object can be re-embedded
+ memcpy(ROBJECT(v)->as.ary, ptr, sizeof(VALUE) * ROBJECT_IV_COUNT(v));
+ RB_FL_SET_RAW(v, ROBJECT_EMBED);
+ if (ROBJ_TRANSIENT_P(v)) {
+ ROBJ_TRANSIENT_UNSET(v);
+ }
+ else {
+ xfree(ptr);
+ }
+ ptr = ROBJECT(v)->as.ary;
+ }
+#endif
+
+ for (uint32_t i = 0; i < ROBJECT_IV_COUNT(v); i++) {
UPDATE_IF_MOVED(objspace, ptr[i]);
}
}
@@ -9628,7 +10329,7 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
}
break;
case imemo_cref:
- UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.klass);
+ UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.klass_or_self);
TYPED_UPDATE_IF_MOVED(objspace, struct rb_cref_struct *, RANY(obj)->as.imemo.cref.next);
UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.refinements);
break;
@@ -9691,7 +10392,7 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
}
static enum rb_id_table_iterator_result
-check_id_table_move(ID id, VALUE value, void *data)
+check_id_table_move(VALUE value, void *data)
{
rb_objspace_t *objspace = (rb_objspace_t *)data;
@@ -9711,8 +10412,7 @@ rb_gc_location(VALUE value)
VALUE destination;
if (!SPECIAL_CONST_P(value)) {
- void *poisoned = asan_poisoned_object_p(value);
- asan_unpoison_object(value, false);
+ void *poisoned = asan_unpoison_object_temporary(value);
if (BUILTIN_TYPE(value) == T_MOVED) {
destination = (VALUE)RMOVED(value)->destination;
@@ -9736,7 +10436,7 @@ rb_gc_location(VALUE value)
}
static enum rb_id_table_iterator_result
-update_id_table(ID *key, VALUE * value, void *data, int existing)
+update_id_table(VALUE *value, void *data, int existing)
{
rb_objspace_t *objspace = (rb_objspace_t *)data;
@@ -9751,12 +10451,12 @@ static void
update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
{
if (tbl) {
- rb_id_table_foreach_with_replace(tbl, check_id_table_move, update_id_table, objspace);
+ rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace);
}
}
static enum rb_id_table_iterator_result
-update_cc_tbl_i(ID id, VALUE ccs_ptr, void *data)
+update_cc_tbl_i(VALUE ccs_ptr, void *data)
{
rb_objspace_t *objspace = (rb_objspace_t *)data;
struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
@@ -9784,17 +10484,22 @@ 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);
+ rb_id_table_foreach_values(tbl, update_cc_tbl_i, objspace);
}
}
static enum rb_id_table_iterator_result
-update_cvc_tbl_i(ID id, VALUE cvc_entry, void *data)
+update_cvc_tbl_i(VALUE cvc_entry, void *data)
{
struct rb_cvar_class_tbl_entry *entry;
+ rb_objspace_t * objspace = (rb_objspace_t *)data;
entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
+ if (entry->cref) {
+ TYPED_UPDATE_IF_MOVED(objspace, rb_cref_t *, entry->cref);
+ }
+
entry->class_value = rb_gc_location(entry->class_value);
return ID_TABLE_CONTINUE;
@@ -9805,7 +10510,29 @@ update_cvc_tbl(rb_objspace_t *objspace, VALUE klass)
{
struct rb_id_table *tbl = RCLASS_CVC_TBL(klass);
if (tbl) {
- rb_id_table_foreach_with_replace(tbl, update_cvc_tbl_i, 0, objspace);
+ rb_id_table_foreach_values(tbl, update_cvc_tbl_i, objspace);
+ }
+}
+
+static enum rb_id_table_iterator_result
+mark_cvc_tbl_i(VALUE cvc_entry, void *data)
+{
+ struct rb_cvar_class_tbl_entry *entry;
+
+ entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
+
+ RUBY_ASSERT(entry->cref == 0 || (BUILTIN_TYPE((VALUE)entry->cref) == T_IMEMO && IMEMO_TYPE_P(entry->cref, imemo_cref)));
+ rb_gc_mark((VALUE) entry->cref);
+
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+mark_cvc_tbl(rb_objspace_t *objspace, VALUE klass)
+{
+ struct rb_id_table *tbl = RCLASS_CVC_TBL(klass);
+ if (tbl) {
+ rb_id_table_foreach_values(tbl, mark_cvc_tbl_i, objspace);
}
}
@@ -9842,25 +10569,22 @@ 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->includer);
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
+update_superclasses(rb_objspace_t *objspace, VALUE obj)
+{
+ if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
+ for (size_t i = 0; i < RCLASS_SUPERCLASS_DEPTH(obj) + 1; i++) {
+ UPDATE_IF_MOVED(objspace, RCLASS_SUPERCLASSES(obj)[i]);
+ }
}
}
@@ -9881,8 +10605,11 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
update_m_tbl(objspace, RCLASS_M_TBL(obj));
update_cc_tbl(objspace, obj);
update_cvc_tbl(objspace, obj);
+ update_superclasses(objspace, obj);
- gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj));
+ for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
+ UPDATE_IF_MOVED(objspace, RCLASS_IVPTR(obj)[i]);
+ }
update_class_ext(objspace, RCLASS_EXT(obj));
update_const_tbl(objspace, RCLASS_CONST_TBL(obj));
@@ -9897,9 +10624,6 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
}
if (!RCLASS_EXT(obj)) break;
- if (RCLASS_IV_TBL(obj)) {
- gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj));
- }
update_class_ext(objspace, RCLASS_EXT(obj));
update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
update_cc_tbl(objspace, obj);
@@ -9918,12 +10642,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
return;
case T_ARRAY:
- if (FL_TEST(obj, ELTS_SHARED)) {
- UPDATE_IF_MOVED(objspace, any->as.array.as.heap.aux.shared_root);
- }
- else {
- gc_ref_update_array(objspace, obj);
- }
+ gc_ref_update_array(objspace, obj);
break;
case T_HASH:
@@ -9932,11 +10651,33 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
break;
case T_STRING:
- if (STR_SHARED_P(obj)) {
- UPDATE_IF_MOVED(objspace, any->as.string.as.heap.aux.shared);
- }
- break;
+ {
+#if USE_RVARGC
+#endif
+ if (STR_SHARED_P(obj)) {
+#if USE_RVARGC
+ VALUE old_root = any->as.string.as.heap.aux.shared;
+#endif
+ UPDATE_IF_MOVED(objspace, any->as.string.as.heap.aux.shared);
+#if USE_RVARGC
+ VALUE new_root = any->as.string.as.heap.aux.shared;
+ rb_str_update_shared_ary(obj, old_root, new_root);
+#endif
+ }
+
+#if USE_RVARGC
+ /* If, after move the string is not embedded, and can fit in the
+ * slot it's been placed in, then re-embed it. */
+ if (rb_gc_obj_slot_size(obj) >= rb_str_size_as_embedded(obj)) {
+ if (!STR_EMBED_P(obj) && rb_str_reembeddable_p(obj)) {
+ rb_str_make_embedded(obj);
+ }
+ }
+#endif
+
+ break;
+ }
case T_DATA:
/* Call the compaction callback, if it exists */
{
@@ -10027,24 +10768,20 @@ static int
gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace, struct heap_page *page)
{
VALUE v = (VALUE)vstart;
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ asan_unlock_freelist(page);
+ asan_lock_freelist(page);
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) {
- void *poisoned = asan_poisoned_object_p(v);
- asan_unpoison_object(v, false);
+ void *poisoned = asan_unpoison_object_temporary(v);
switch (BUILTIN_TYPE(v)) {
case T_NONE:
case T_MOVED:
case T_ZOMBIE:
break;
- case T_PAYLOAD:
- v += (stride * (RPAYLOAD_LEN(v) - 1));
- break;
default:
if (RVALUE_WB_UNPROTECTED(v)) {
page->flags.has_uncollectible_shady_objects = TRUE;
@@ -10074,21 +10811,29 @@ extern rb_symbols_t ruby_global_symbols;
#define global_symbols ruby_global_symbols
static void
-gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap)
+gc_update_references(rb_objspace_t *objspace)
{
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;
- 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);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ bool should_set_mark_bits = TRUE;
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ uintptr_t start = (uintptr_t)page->start;
+ uintptr_t end = start + (page->total_slots * size_pool->slot_size);
+
+ gc_ref_update((void *)start, (void *)end, size_pool->slot_size, objspace, page);
+ if (page == heap->sweeping_page) {
+ should_set_mark_bits = FALSE;
+ }
+ if (should_set_mark_bits) {
+ gc_setup_mark_bits(page);
+ }
}
}
rb_vm_update_references(vm);
@@ -10102,14 +10847,29 @@ gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap)
gc_update_table_refs(objspace, finalizer_table);
}
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * call-seq:
+ * GC.latest_compact_info -> hash
+ *
+ * Returns information about object moved in the most recent \GC compaction.
+ *
+ * The returned hash 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.
+ */
static VALUE
-gc_compact_stats(rb_execution_context_t *ec, VALUE self)
+gc_compact_stats(VALUE self)
{
size_t i;
rb_objspace_t *objspace = &rb_objspace;
VALUE h = rb_hash_new();
VALUE considered = rb_hash_new();
VALUE moved = rb_hash_new();
+ VALUE moved_up = rb_hash_new();
+ VALUE moved_down = rb_hash_new();
for (i=0; i<T_MASK; i++) {
if (objspace->rcompactor.considered_count_table[i]) {
@@ -10119,14 +10879,28 @@ gc_compact_stats(rb_execution_context_t *ec, VALUE self)
if (objspace->rcompactor.moved_count_table[i]) {
rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i]));
}
+
+ if (objspace->rcompactor.moved_up_count_table[i]) {
+ rb_hash_aset(moved_up, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_up_count_table[i]));
+ }
+
+ if (objspace->rcompactor.moved_down_count_table[i]) {
+ rb_hash_aset(moved_down, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_down_count_table[i]));
+ }
}
rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered);
rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved);
+ rb_hash_aset(h, ID2SYM(rb_intern("moved_up")), moved_up);
+ rb_hash_aset(h, ID2SYM(rb_intern("moved_down")), moved_down);
return h;
}
+#else
+# define gc_compact_stats rb_f_notimplement
+#endif
+#if GC_CAN_COMPILE_COMPACTION
static void
root_obj_check_moved_i(const char *category, VALUE obj, void *data)
{
@@ -10153,8 +10927,7 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
/* Moved object still on the heap, something may have a reference. */
}
else {
- void *poisoned = asan_poisoned_object_p(v);
- asan_unpoison_object(v, false);
+ void *poisoned = asan_unpoison_object_temporary(v);
switch (BUILTIN_TYPE(v)) {
case T_NONE:
@@ -10176,47 +10949,67 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
return 0;
}
+/*
+ * 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 <tt>GC.latest_gc_info</tt> for details about
+ * compaction statistics.
+ *
+ * This method is implementation specific and not expected to be implemented
+ * in any implementation besides MRI.
+ *
+ * To test whether \GC compaction is supported, use the idiom:
+ *
+ * GC.respond_to?(:compact)
+ */
static VALUE
-gc_compact(rb_execution_context_t *ec, VALUE self)
+gc_compact(VALUE self)
{
-#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 compaction. */
- int pagesize;
- pagesize = (int)sysconf(_SC_PAGE_SIZE);
- if ((HEAP_PAGE_SIZE % pagesize) != 0) {
- rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
- }
-#endif
-
- /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
- * the read barrier, so we must disable compaction. */
-#if !defined(__MINGW32__) && !defined(_WIN32)
- if (!USE_MMAP_ALIGNED_ALLOC) {
- rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
- }
-#endif
-
/* Run GC with compaction enabled */
- gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
+ gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
- return gc_compact_stats(ec, self);
+ return gc_compact_stats(self);
}
+#else
+# define gc_compact rb_f_notimplement
+#endif
+#if GC_CAN_COMPILE_COMPACTION
static VALUE
-gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE toward_empty)
+gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE expand_heap, VALUE toward_empty)
{
rb_objspace_t *objspace = &rb_objspace;
/* Clear the heap. */
- gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qfalse);
+ gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qfalse);
+ size_t growth_slots = gc_params.heap_init_slots;
+
+ if (RTEST(double_heap)) {
+ rb_warn("double_heap is deprecated, please use expand_heap instead");
+ }
RB_VM_LOCK_ENTER();
{
gc_rest(objspace);
- if (RTEST(double_heap)) {
- heap_add_pages(objspace, heap_eden, heap_allocated_pages);
+ /* if both double_heap and expand_heap are set, expand_heap takes precedence */
+ if (RTEST(double_heap) || RTEST(expand_heap)) {
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+ rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
+
+ if (RTEST(expand_heap)) {
+ size_t required_pages = growth_slots / size_pool->slot_size;
+ heap_add_pages(objspace, size_pool, heap, MAX(required_pages, heap->total_pages));
+ }
+ else {
+ heap_add_pages(objspace, size_pool, heap, heap->total_pages);
+ }
+ }
}
if (RTEST(toward_empty)) {
@@ -10225,13 +11018,16 @@ gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE do
}
RB_VM_LOCK_LEAVE();
- gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
+ gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL);
objspace_each_objects(objspace, heap_check_moved_i, NULL, TRUE);
- return gc_compact_stats(ec, self);
+ return gc_compact_stats(self);
}
+#else
+# define gc_verify_compaction_references (rb_builtin_arity3_function_type)rb_f_notimplement
+#endif
VALUE
rb_gc_start(void)
@@ -10287,7 +11083,7 @@ gc_count(rb_execution_context_t *ec, VALUE self)
static VALUE
gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned int orig_flags)
{
- static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state;
+ static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state, sym_need_major_by;
static VALUE sym_nofree, sym_oldgen, sym_shady, sym_force, sym_stress;
#if RGENGC_ESTIMATE_OLDMALLOC
static VALUE sym_oldmalloc;
@@ -10295,7 +11091,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned
static VALUE sym_newobj, sym_malloc, sym_method, sym_capi;
static VALUE sym_none, sym_marking, sym_sweeping;
VALUE hash = Qnil, key = Qnil;
- VALUE major_by;
+ VALUE major_by, need_major_by;
unsigned int flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info;
if (SYMBOL_P(hash_or_key)) {
@@ -10308,13 +11104,14 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned
rb_raise(rb_eTypeError, "non-hash or symbol given");
}
- if (sym_major_by == Qnil) {
+ if (NIL_P(sym_major_by)) {
#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
S(major_by);
S(gc_by);
S(immediate_sweep);
S(have_finalizer);
S(state);
+ S(need_major_by);
S(stress);
S(nofree);
@@ -10352,6 +11149,20 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned
Qnil;
SET(major_by, major_by);
+ if (orig_flags == 0) { /* set need_major_by only if flags not set explicitly */
+ unsigned int need_major_flags = objspace->rgengc.need_major_gc;
+ need_major_by =
+ (need_major_flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
+ (need_major_flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
+ (need_major_flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady :
+ (need_major_flags & GPR_FLAG_MAJOR_BY_FORCE) ? sym_force :
+#if RGENGC_ESTIMATE_OLDMALLOC
+ (need_major_flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc :
+#endif
+ Qnil;
+ SET(need_major_by, need_major_by);
+ }
+
SET(gc_by,
(flags & GPR_FLAG_NEWOBJ) ? sym_newobj :
(flags & GPR_FLAG_MALLOC) ? sym_malloc :
@@ -10361,8 +11172,8 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned
Qnil
);
- SET(have_finalizer, (flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse);
- SET(immediate_sweep, (flags & GPR_FLAG_IMMEDIATE_SWEEP) ? Qtrue : Qfalse);
+ SET(have_finalizer, RBOOL(flags & GPR_FLAG_HAVE_FINALIZE));
+ SET(immediate_sweep, RBOOL(flags & GPR_FLAG_IMMEDIATE_SWEEP));
if (orig_flags == 0) {
SET(state, gc_mode(objspace) == gc_mode_none ? sym_none :
@@ -10401,6 +11212,7 @@ gc_latest_gc_info(rb_execution_context_t *ec, VALUE self, VALUE arg)
enum gc_stat_sym {
gc_stat_sym_count,
+ gc_stat_sym_time,
gc_stat_sym_heap_allocated_pages,
gc_stat_sym_heap_sorted_length,
gc_stat_sym_heap_allocatable_pages,
@@ -10448,43 +11260,44 @@ setup_gc_stat_symbols(void)
{
if (gc_stat_symbols[0] == 0) {
#define S(s) gc_stat_symbols[gc_stat_sym_##s] = ID2SYM(rb_intern_const(#s))
- S(count);
- S(heap_allocated_pages);
- S(heap_sorted_length);
- S(heap_allocatable_pages);
- S(heap_available_slots);
- S(heap_live_slots);
- S(heap_free_slots);
- S(heap_final_slots);
- S(heap_marked_slots);
- S(heap_eden_pages);
- S(heap_tomb_pages);
- S(total_allocated_pages);
- S(total_freed_pages);
- S(total_allocated_objects);
- S(total_freed_objects);
- S(malloc_increase_bytes);
- S(malloc_increase_bytes_limit);
- S(minor_gc_count);
- S(major_gc_count);
- S(compact_count);
- S(read_barrier_faults);
- S(total_moved_objects);
- S(remembered_wb_unprotected_objects);
- S(remembered_wb_unprotected_objects_limit);
- S(old_objects);
- S(old_objects_limit);
+ S(count);
+ S(time);
+ S(heap_allocated_pages);
+ S(heap_sorted_length);
+ S(heap_allocatable_pages);
+ S(heap_available_slots);
+ S(heap_live_slots);
+ S(heap_free_slots);
+ S(heap_final_slots);
+ S(heap_marked_slots);
+ S(heap_eden_pages);
+ S(heap_tomb_pages);
+ S(total_allocated_pages);
+ S(total_freed_pages);
+ S(total_allocated_objects);
+ S(total_freed_objects);
+ S(malloc_increase_bytes);
+ S(malloc_increase_bytes_limit);
+ S(minor_gc_count);
+ S(major_gc_count);
+ S(compact_count);
+ S(read_barrier_faults);
+ S(total_moved_objects);
+ S(remembered_wb_unprotected_objects);
+ S(remembered_wb_unprotected_objects_limit);
+ S(old_objects);
+ S(old_objects_limit);
#if RGENGC_ESTIMATE_OLDMALLOC
- S(oldmalloc_increase_bytes);
- S(oldmalloc_increase_bytes_limit);
+ S(oldmalloc_increase_bytes);
+ S(oldmalloc_increase_bytes_limit);
#endif
#if RGENGC_PROFILE
- S(total_generated_normal_object_count);
- S(total_generated_shady_object_count);
- S(total_shade_operation_count);
- S(total_promoted_count);
- S(total_remembered_normal_object_count);
- S(total_remembered_shady_object_count);
+ S(total_generated_normal_object_count);
+ S(total_generated_shady_object_count);
+ S(total_shade_operation_count);
+ S(total_promoted_count);
+ S(total_remembered_normal_object_count);
+ S(total_remembered_shady_object_count);
#endif /* RGENGC_PROFILE */
#undef S
}
@@ -10499,36 +11312,37 @@ gc_stat_internal(VALUE hash_or_sym)
setup_gc_stat_symbols();
if (RB_TYPE_P(hash_or_sym, T_HASH)) {
- hash = hash_or_sym;
+ hash = hash_or_sym;
}
else if (SYMBOL_P(hash_or_sym)) {
- key = hash_or_sym;
+ key = hash_or_sym;
}
else {
- rb_raise(rb_eTypeError, "non-hash or symbol argument");
+ rb_raise(rb_eTypeError, "non-hash or symbol argument");
}
#define SET(name, attr) \
if (key == gc_stat_symbols[gc_stat_sym_##name]) \
- return attr; \
+ return attr; \
else if (hash != Qnil) \
- rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr));
+ rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr));
SET(count, objspace->profile.count);
+ SET(time, (size_t) (objspace->profile.total_time_ns / (1000 * 1000) /* ns -> ms */)); // TODO: UINT64T2NUM
/* implementation dependent counters */
SET(heap_allocated_pages, heap_allocated_pages);
SET(heap_sorted_length, heap_pages_sorted_length);
- SET(heap_allocatable_pages, heap_allocatable_pages);
+ SET(heap_allocatable_pages, heap_allocatable_pages(objspace));
SET(heap_available_slots, objspace_available_slots(objspace));
SET(heap_live_slots, objspace_live_slots(objspace));
SET(heap_free_slots, objspace_free_slots(objspace));
SET(heap_final_slots, heap_pages_final_slots);
SET(heap_marked_slots, objspace->marked_slots);
- SET(heap_eden_pages, heap_eden->total_pages);
- SET(heap_tomb_pages, heap_tomb->total_pages);
- SET(total_allocated_pages, objspace->profile.total_allocated_pages);
- SET(total_freed_pages, objspace->profile.total_freed_pages);
+ SET(heap_eden_pages, heap_eden_total_pages(objspace));
+ SET(heap_tomb_pages, heap_tomb_total_pages(objspace));
+ SET(total_allocated_pages, total_allocated_pages(objspace));
+ SET(total_freed_pages, total_freed_pages(objspace));
SET(total_allocated_objects, objspace->total_allocated_objects);
SET(total_freed_objects, objspace->profile.total_freed_objects);
SET(malloc_increase_bytes, malloc_increase);
@@ -10558,17 +11372,17 @@ gc_stat_internal(VALUE hash_or_sym)
#undef SET
if (!NIL_P(key)) { /* matched key should return above */
- rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
+ rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
}
#if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2
if (hash != Qnil) {
- gc_count_add_each_types(hash, "generated_normal_object_count_types", objspace->profile.generated_normal_object_count_types);
- gc_count_add_each_types(hash, "generated_shady_object_count_types", objspace->profile.generated_shady_object_count_types);
- gc_count_add_each_types(hash, "shade_operation_count_types", objspace->profile.shade_operation_count_types);
- gc_count_add_each_types(hash, "promoted_types", objspace->profile.promoted_types);
- gc_count_add_each_types(hash, "remembered_normal_object_count_types", objspace->profile.remembered_normal_object_count_types);
- gc_count_add_each_types(hash, "remembered_shady_object_count_types", objspace->profile.remembered_shady_object_count_types);
+ gc_count_add_each_types(hash, "generated_normal_object_count_types", objspace->profile.generated_normal_object_count_types);
+ gc_count_add_each_types(hash, "generated_shady_object_count_types", objspace->profile.generated_shady_object_count_types);
+ gc_count_add_each_types(hash, "shade_operation_count_types", objspace->profile.shade_operation_count_types);
+ gc_count_add_each_types(hash, "promoted_types", objspace->profile.promoted_types);
+ gc_count_add_each_types(hash, "remembered_normal_object_count_types", objspace->profile.remembered_normal_object_count_types);
+ gc_count_add_each_types(hash, "remembered_shady_object_count_types", objspace->profile.remembered_shady_object_count_types);
}
#endif
@@ -10600,13 +11414,144 @@ size_t
rb_gc_stat(VALUE key)
{
if (SYMBOL_P(key)) {
- size_t value = gc_stat_internal(key);
- return value;
+ size_t value = gc_stat_internal(key);
+ return value;
+ }
+ else {
+ gc_stat_internal(key);
+ return 0;
+ }
+}
+
+
+enum gc_stat_heap_sym {
+ gc_stat_heap_sym_slot_size,
+ gc_stat_heap_sym_heap_allocatable_pages,
+ gc_stat_heap_sym_heap_eden_pages,
+ gc_stat_heap_sym_heap_eden_slots,
+ gc_stat_heap_sym_heap_tomb_pages,
+ gc_stat_heap_sym_heap_tomb_slots,
+ gc_stat_heap_sym_total_allocated_pages,
+ gc_stat_heap_sym_total_freed_pages,
+ gc_stat_heap_sym_force_major_gc_count,
+ gc_stat_heap_sym_last
+};
+
+static VALUE gc_stat_heap_symbols[gc_stat_heap_sym_last];
+
+static void
+setup_gc_stat_heap_symbols(void)
+{
+ if (gc_stat_heap_symbols[0] == 0) {
+#define S(s) gc_stat_heap_symbols[gc_stat_heap_sym_##s] = ID2SYM(rb_intern_const(#s))
+ S(slot_size);
+ S(heap_allocatable_pages);
+ S(heap_eden_pages);
+ S(heap_eden_slots);
+ S(heap_tomb_pages);
+ S(heap_tomb_slots);
+ S(total_allocated_pages);
+ S(total_freed_pages);
+ S(force_major_gc_count);
+#undef S
+ }
+}
+
+static size_t
+gc_stat_heap_internal(int size_pool_idx, VALUE hash_or_sym)
+{
+ rb_objspace_t *objspace = &rb_objspace;
+ VALUE hash = Qnil, key = Qnil;
+
+ setup_gc_stat_heap_symbols();
+
+ if (RB_TYPE_P(hash_or_sym, T_HASH)) {
+ hash = hash_or_sym;
+ }
+ else if (SYMBOL_P(hash_or_sym)) {
+ key = hash_or_sym;
+ }
+ else {
+ rb_raise(rb_eTypeError, "non-hash or symbol argument");
+ }
+
+ if (size_pool_idx < 0 || size_pool_idx >= SIZE_POOL_COUNT) {
+ rb_raise(rb_eArgError, "size pool index out of range");
+ }
+
+ rb_size_pool_t *size_pool = &size_pools[size_pool_idx];
+
+#define SET(name, attr) \
+ if (key == gc_stat_heap_symbols[gc_stat_heap_sym_##name]) \
+ return attr; \
+ else if (hash != Qnil) \
+ rb_hash_aset(hash, gc_stat_heap_symbols[gc_stat_heap_sym_##name], SIZET2NUM(attr));
+
+ SET(slot_size, size_pool->slot_size);
+ SET(heap_allocatable_pages, size_pool->allocatable_pages);
+ SET(heap_eden_pages, SIZE_POOL_EDEN_HEAP(size_pool)->total_pages);
+ SET(heap_eden_slots, SIZE_POOL_EDEN_HEAP(size_pool)->total_slots);
+ SET(heap_tomb_pages, SIZE_POOL_TOMB_HEAP(size_pool)->total_pages);
+ SET(heap_tomb_slots, SIZE_POOL_TOMB_HEAP(size_pool)->total_slots);
+ SET(total_allocated_pages, size_pool->total_allocated_pages);
+ SET(total_freed_pages, size_pool->total_freed_pages);
+ SET(force_major_gc_count, size_pool->force_major_gc_count);
+#undef SET
+
+ if (!NIL_P(key)) { /* matched key should return above */
+ rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
+ }
+
+ return 0;
+}
+
+static VALUE
+gc_stat_heap(rb_execution_context_t *ec, VALUE self, VALUE heap_name, VALUE arg)
+{
+ if (NIL_P(heap_name)) {
+ if (NIL_P(arg)) {
+ arg = rb_hash_new();
+ }
+ else if (RB_TYPE_P(arg, T_HASH)) {
+ // ok
+ }
+ else {
+ rb_raise(rb_eTypeError, "non-hash given");
+ }
+
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ VALUE hash = rb_hash_aref(arg, INT2FIX(i));
+ if (NIL_P(hash)) {
+ hash = rb_hash_new();
+ rb_hash_aset(arg, INT2FIX(i), hash);
+ }
+ gc_stat_heap_internal(i, hash);
+ }
+ }
+ else if (FIXNUM_P(heap_name)) {
+ int size_pool_idx = FIX2INT(heap_name);
+
+ if (NIL_P(arg)) {
+ arg = rb_hash_new();
+ }
+ else if (SYMBOL_P(arg)) {
+ size_t value = gc_stat_heap_internal(size_pool_idx, arg);
+ return SIZET2NUM(value);
+ }
+ else if (RB_TYPE_P(arg, T_HASH)) {
+ // ok
+ }
+ else {
+ rb_raise(rb_eTypeError, "non-hash or symbol given");
+ }
+
+ gc_stat_heap_internal(size_pool_idx, arg);
}
else {
- gc_stat_internal(key);
- return 0;
+ rb_raise(rb_eTypeError, "heap_name must be nil or an Integer");
}
+
+ return arg;
}
static VALUE
@@ -10688,37 +11633,44 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
return rb_gc_disable();
}
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * call-seq:
+ * GC.auto_compact = flag
+ *
+ * Updates automatic compaction mode.
+ *
+ * When enabled, the compactor will execute on every major collection.
+ *
+ * Enabling compaction will degrade performance on major collections.
+ */
static VALUE
-gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v)
+gc_set_auto_compact(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
-
- /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
- * the read barrier, so we must disable automatic compaction. */
-#if !defined(__MINGW32__) && !defined(_WIN32)
- if (!USE_MMAP_ALIGNED_ALLOC) {
- rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform");
- }
-#endif
+ GC_ASSERT(GC_COMPACTION_SUPPORTED);
ruby_enable_autocompact = RTEST(v);
return v;
}
+#else
+# define gc_set_auto_compact rb_f_notimplement
+#endif
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * call-seq:
+ * GC.auto_compact -> true or false
+ *
+ * Returns whether or not automatic compaction has been enabled.
+ */
static VALUE
-gc_get_auto_compact(rb_execution_context_t *ec, VALUE _)
+gc_get_auto_compact(VALUE _)
{
return RBOOL(ruby_enable_autocompact);
}
+#else
+# define gc_get_auto_compact rb_f_notimplement
+#endif
static int
get_envparam_size(const char *name, size_t *default_value, size_t lower_bound)
@@ -10727,53 +11679,53 @@ get_envparam_size(const char *name, size_t *default_value, size_t lower_bound)
ssize_t val;
if (ptr != NULL && *ptr) {
- size_t unit = 0;
- char *end;
+ size_t unit = 0;
+ char *end;
#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
- val = strtoll(ptr, &end, 0);
+ val = strtoll(ptr, &end, 0);
#else
- val = strtol(ptr, &end, 0);
-#endif
- switch (*end) {
- case 'k': case 'K':
- unit = 1024;
- ++end;
- break;
- case 'm': case 'M':
- unit = 1024*1024;
- ++end;
- break;
- case 'g': case 'G':
- unit = 1024*1024*1024;
- ++end;
- break;
- }
- while (*end && isspace((unsigned char)*end)) end++;
- if (*end) {
- if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
- return 0;
- }
- if (unit > 0) {
- if (val < -(ssize_t)(SIZE_MAX / 2 / unit) || (ssize_t)(SIZE_MAX / 2 / unit) < val) {
- if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%s is ignored because it overflows\n", name, ptr);
- return 0;
- }
- val *= unit;
- }
- if (val > 0 && (size_t)val > lower_bound) {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE")\n", name, val, *default_value);
- }
- *default_value = (size_t)val;
- return 1;
- }
- else {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE") is ignored because it must be greater than %"PRIuSIZE".\n",
- name, val, *default_value, lower_bound);
- }
- return 0;
- }
+ val = strtol(ptr, &end, 0);
+#endif
+ switch (*end) {
+ case 'k': case 'K':
+ unit = 1024;
+ ++end;
+ break;
+ case 'm': case 'M':
+ unit = 1024*1024;
+ ++end;
+ break;
+ case 'g': case 'G':
+ unit = 1024*1024*1024;
+ ++end;
+ break;
+ }
+ while (*end && isspace((unsigned char)*end)) end++;
+ if (*end) {
+ if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
+ return 0;
+ }
+ if (unit > 0) {
+ if (val < -(ssize_t)(SIZE_MAX / 2 / unit) || (ssize_t)(SIZE_MAX / 2 / unit) < val) {
+ if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%s is ignored because it overflows\n", name, ptr);
+ return 0;
+ }
+ val *= unit;
+ }
+ if (val > 0 && (size_t)val > lower_bound) {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE")\n", name, val, *default_value);
+ }
+ *default_value = (size_t)val;
+ return 1;
+ }
+ else {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE") is ignored because it must be greater than %"PRIuSIZE".\n",
+ name, val, *default_value, lower_bound);
+ }
+ return 0;
+ }
}
return 0;
}
@@ -10785,32 +11737,32 @@ get_envparam_double(const char *name, double *default_value, double lower_bound,
double val;
if (ptr != NULL && *ptr) {
- char *end;
- val = strtod(ptr, &end);
- if (!*ptr || *end) {
- if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
- return 0;
- }
-
- if (accept_zero && val == 0.0) {
- goto accept;
- }
- else if (val <= lower_bound) {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be greater than %f.\n",
- name, val, *default_value, lower_bound);
- }
- }
- else if (upper_bound != 0.0 && /* ignore upper_bound if it is 0.0 */
- val > upper_bound) {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be lower than %f.\n",
- name, val, *default_value, upper_bound);
- }
- }
- else {
+ char *end;
+ val = strtod(ptr, &end);
+ if (!*ptr || *end) {
+ if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
+ return 0;
+ }
+
+ if (accept_zero && val == 0.0) {
goto accept;
- }
+ }
+ else if (val <= lower_bound) {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be greater than %f.\n",
+ name, val, *default_value, lower_bound);
+ }
+ }
+ else if (upper_bound != 0.0 && /* ignore upper_bound if it is 0.0 */
+ val > upper_bound) {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be lower than %f.\n",
+ name, val, *default_value, upper_bound);
+ }
+ }
+ else {
+ goto accept;
+ }
}
return 0;
@@ -10821,17 +11773,25 @@ get_envparam_double(const char *name, double *default_value, double lower_bound,
}
static void
-gc_set_initial_pages(void)
+gc_set_initial_pages(rb_objspace_t *objspace)
{
- size_t min_pages;
- rb_objspace_t *objspace = &rb_objspace;
-
gc_rest(objspace);
- min_pages = gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT;
- if (min_pages > heap_eden->total_pages) {
- heap_add_pages(objspace, heap_eden, min_pages - heap_eden->total_pages);
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_size_pool_t *size_pool = &size_pools[i];
+
+ if (gc_params.heap_init_slots > size_pool->eden_heap.total_slots) {
+ size_t slots = gc_params.heap_init_slots - size_pool->eden_heap.total_slots;
+ int multiple = size_pool->slot_size / BASE_SLOT_SIZE;
+ size_pool->allocatable_pages = slots * multiple / HEAP_PAGE_OBJ_LIMIT;
+ }
+ else {
+ /* We already have more slots than heap_init_slots allows, so
+ * prevent creating more pages. */
+ size_pool->allocatable_pages = 0;
+ }
}
+ heap_pages_expand_sorted(objspace);
}
/*
@@ -10879,27 +11839,30 @@ gc_set_initial_pages(void)
void
ruby_gc_set_params(void)
{
+ rb_objspace_t *objspace = &rb_objspace;
/* RUBY_GC_HEAP_FREE_SLOTS */
if (get_envparam_size("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) {
- /* ok */
+ /* ok */
}
/* RUBY_GC_HEAP_INIT_SLOTS */
if (get_envparam_size("RUBY_GC_HEAP_INIT_SLOTS", &gc_params.heap_init_slots, 0)) {
- gc_set_initial_pages();
+ gc_set_initial_pages(objspace);
}
get_envparam_double("RUBY_GC_HEAP_GROWTH_FACTOR", &gc_params.growth_factor, 1.0, 0.0, FALSE);
get_envparam_size ("RUBY_GC_HEAP_GROWTH_MAX_SLOTS", &gc_params.growth_max_slots, 0);
get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO", &gc_params.heap_free_slots_min_ratio,
- 0.0, 1.0, FALSE);
+ 0.0, 1.0, FALSE);
get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO", &gc_params.heap_free_slots_max_ratio,
- gc_params.heap_free_slots_min_ratio, 1.0, FALSE);
+ gc_params.heap_free_slots_min_ratio, 1.0, FALSE);
get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO", &gc_params.heap_free_slots_goal_ratio,
- gc_params.heap_free_slots_min_ratio, gc_params.heap_free_slots_max_ratio, TRUE);
+ gc_params.heap_free_slots_min_ratio, gc_params.heap_free_slots_max_ratio, TRUE);
get_envparam_double("RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR", &gc_params.oldobject_limit_factor, 0.0, 0.0, TRUE);
- get_envparam_size ("RUBY_GC_MALLOC_LIMIT", &gc_params.malloc_limit_min, 0);
+ if (get_envparam_size("RUBY_GC_MALLOC_LIMIT", &gc_params.malloc_limit_min, 0)) {
+ malloc_limit = gc_params.malloc_limit_min;
+ }
get_envparam_size ("RUBY_GC_MALLOC_LIMIT_MAX", &gc_params.malloc_limit_max, 0);
if (!gc_params.malloc_limit_max) { /* ignore max-check if 0 */
gc_params.malloc_limit_max = SIZE_MAX;
@@ -10908,8 +11871,7 @@ ruby_gc_set_params(void)
#if RGENGC_ESTIMATE_OLDMALLOC
if (get_envparam_size("RUBY_GC_OLDMALLOC_LIMIT", &gc_params.oldmalloc_limit_min, 0)) {
- rb_objspace_t *objspace = &rb_objspace;
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
}
get_envparam_size ("RUBY_GC_OLDMALLOC_LIMIT_MAX", &gc_params.oldmalloc_limit_max, 0);
get_envparam_double("RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR", &gc_params.oldmalloc_limit_growth_factor, 1.0, 0.0, FALSE);
@@ -10928,19 +11890,23 @@ rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *
{
rb_objspace_t *objspace = &rb_objspace;
- if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true");
+ RB_VM_LOCK_ENTER();
+ {
+ if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true");
- if (is_markable_object(objspace, obj)) {
- rb_ractor_t *cr = GET_RACTOR();
- struct gc_mark_func_data_struct mfd = {
- .mark_func = func,
- .data = data,
- }, *prev_mfd = cr->mfd;
+ if (is_markable_object(objspace, obj)) {
+ 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);
- cr->mfd = prev_mfd;
+ cr->mfd = &mfd;
+ gc_mark_children(objspace, obj);
+ cr->mfd = prev_mfd;
+ }
}
+ RB_VM_LOCK_LEAVE();
}
struct root_objects_data {
@@ -11049,16 +12015,16 @@ static void
ruby_memerror(void)
{
if (ruby_thread_has_gvl_p()) {
- rb_memerror();
+ rb_memerror();
}
else {
- if (ruby_native_thread_p()) {
- rb_thread_call_with_gvl(ruby_memerror_body, 0);
- }
- else {
- /* no ruby thread */
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- }
+ if (ruby_native_thread_p()) {
+ rb_thread_call_with_gvl(ruby_memerror_body, 0);
+ }
+ else {
+ /* no ruby thread */
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ }
}
exit(EXIT_FAILURE);
}
@@ -11083,16 +12049,16 @@ rb_memerror(void)
exc = nomem_error;
if (!exc ||
- rb_ec_raised_p(ec, RAISED_NOMEMORY)) {
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- exit(EXIT_FAILURE);
+ rb_ec_raised_p(ec, RAISED_NOMEMORY)) {
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ exit(EXIT_FAILURE);
}
if (rb_ec_raised_p(ec, RAISED_NOMEMORY)) {
- rb_ec_raised_clear(ec);
+ rb_ec_raised_clear(ec);
}
else {
- rb_ec_raised_set(ec, RAISED_NOMEMORY);
- exc = ruby_vm_special_exception_copy(exc);
+ rb_ec_raised_set(ec, RAISED_NOMEMORY);
+ exc = ruby_vm_special_exception_copy(exc);
}
ec->errinfo = exc;
EC_JUMP_TAG(ec, TAG_RAISE);
@@ -11101,6 +12067,10 @@ rb_memerror(void)
void *
rb_aligned_malloc(size_t alignment, size_t size)
{
+ /* alignment must be a power of 2 */
+ GC_ASSERT(((alignment - 1) & alignment) == 0);
+ GC_ASSERT(alignment % sizeof(void*) == 0);
+
void *res;
#if defined __MINGW32__
@@ -11108,59 +12078,23 @@ rb_aligned_malloc(size_t alignment, size_t size)
#elif defined _WIN32
void *_aligned_malloc(size_t, size_t);
res = _aligned_malloc(size, alignment);
-#else
- if (USE_MMAP_ALIGNED_ALLOC) {
- GC_ASSERT(alignment % sysconf(_SC_PAGE_SIZE) == 0);
-
- char *ptr = mmap(NULL, alignment + size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (ptr == MAP_FAILED) {
- return NULL;
- }
-
- char *aligned = ptr + alignment;
- aligned -= ((VALUE)aligned & (alignment - 1));
- GC_ASSERT(aligned > ptr);
- GC_ASSERT(aligned <= ptr + alignment);
-
- size_t start_out_of_range_size = aligned - ptr;
- GC_ASSERT(start_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0);
- if (start_out_of_range_size > 0) {
- if (munmap(ptr, start_out_of_range_size)) {
- rb_bug("rb_aligned_malloc: munmap failed for start");
- }
- }
-
- size_t end_out_of_range_size = alignment - start_out_of_range_size;
- GC_ASSERT(end_out_of_range_size % sysconf(_SC_PAGE_SIZE) == 0);
- if (end_out_of_range_size > 0) {
- if (munmap(aligned + size, end_out_of_range_size)) {
- rb_bug("rb_aligned_malloc: munmap failed for end");
- }
- }
-
- res = (void *)aligned;
- }
- else {
-# if defined(HAVE_POSIX_MEMALIGN)
- if (posix_memalign(&res, alignment, size) != 0) {
- return NULL;
- }
-# elif defined(HAVE_MEMALIGN)
- res = memalign(alignment, size);
-# else
- char* aligned;
- res = malloc(alignment + size + sizeof(void*));
- aligned = (char*)res + alignment + sizeof(void*);
- aligned -= ((VALUE)aligned & (alignment - 1));
- ((void**)aligned)[-1] = res;
- res = (void*)aligned;
-# endif
+#elif defined(HAVE_POSIX_MEMALIGN)
+ if (posix_memalign(&res, alignment, size) != 0) {
+ return NULL;
}
+#elif defined(HAVE_MEMALIGN)
+ res = memalign(alignment, size);
+#else
+ char* aligned;
+ res = malloc(alignment + size + sizeof(void*));
+ aligned = (char*)res + alignment + sizeof(void*);
+ aligned -= ((VALUE)aligned & (alignment - 1));
+ ((void**)aligned)[-1] = res;
+ res = (void*)aligned;
#endif
- /* alignment must be a power of 2 */
- GC_ASSERT(((alignment - 1) & alignment) == 0);
- GC_ASSERT(alignment % sizeof(void*) == 0);
+ GC_ASSERT((uintptr_t)res % alignment == 0);
+
return res;
}
@@ -11171,20 +12105,10 @@ rb_aligned_free(void *ptr, size_t size)
__mingw_aligned_free(ptr);
#elif defined _WIN32
_aligned_free(ptr);
+#elif defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)
+ free(ptr);
#else
- if (USE_MMAP_ALIGNED_ALLOC) {
- GC_ASSERT(size % sysconf(_SC_PAGE_SIZE) == 0);
- if (munmap(ptr, size)) {
- rb_bug("rb_aligned_free: munmap failed");
- }
- }
- else {
-# if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)
- free(ptr);
-# else
- free(((void**)ptr)[-1]);
-# endif
- }
+ free(((void**)ptr)[-1]);
#endif
}
@@ -11210,9 +12134,9 @@ atomic_sub_nounderflow(size_t *var, size_t sub)
if (sub == 0) return;
while (1) {
- size_t val = *var;
- if (val < sub) sub = val;
- if (ATOMIC_SIZE_CAS(*var, val, val-sub) == val) break;
+ size_t val = *var;
+ if (val < sub) sub = val;
+ if (ATOMIC_SIZE_CAS(*var, val, val-sub) == val) break;
}
}
@@ -11230,78 +12154,89 @@ objspace_malloc_gc_stress(rb_objspace_t *objspace)
}
}
-static void
-objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type)
+static inline bool
+objspace_malloc_increase_report(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type)
+{
+ if (0) fprintf(stderr, "increase - ptr: %p, type: %s, new_size: %"PRIdSIZE", old_size: %"PRIdSIZE"\n",
+ mem,
+ type == MEMOP_TYPE_MALLOC ? "malloc" :
+ type == MEMOP_TYPE_FREE ? "free " :
+ type == MEMOP_TYPE_REALLOC ? "realloc": "error",
+ new_size, old_size);
+ return false;
+}
+
+static bool
+objspace_malloc_increase_body(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type)
{
if (new_size > old_size) {
- ATOMIC_SIZE_ADD(malloc_increase, new_size - old_size);
+ ATOMIC_SIZE_ADD(malloc_increase, new_size - old_size);
#if RGENGC_ESTIMATE_OLDMALLOC
- ATOMIC_SIZE_ADD(objspace->rgengc.oldmalloc_increase, new_size - old_size);
+ ATOMIC_SIZE_ADD(objspace->rgengc.oldmalloc_increase, new_size - old_size);
#endif
}
else {
- atomic_sub_nounderflow(&malloc_increase, old_size - new_size);
+ atomic_sub_nounderflow(&malloc_increase, old_size - new_size);
#if RGENGC_ESTIMATE_OLDMALLOC
- atomic_sub_nounderflow(&objspace->rgengc.oldmalloc_increase, old_size - new_size);
+ atomic_sub_nounderflow(&objspace->rgengc.oldmalloc_increase, old_size - new_size);
#endif
}
if (type == MEMOP_TYPE_MALLOC) {
retry:
- if (malloc_increase > malloc_limit && ruby_native_thread_p() && !dont_gc_val()) {
- if (ruby_thread_has_gvl_p() && is_lazy_sweeping(heap_eden)) {
- gc_rest(objspace); /* gc_rest can reduce malloc_increase */
- goto retry;
- }
- garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC);
- }
+ if (malloc_increase > malloc_limit && ruby_native_thread_p() && !dont_gc_val()) {
+ if (ruby_thread_has_gvl_p() && is_lazy_sweeping(objspace)) {
+ gc_rest(objspace); /* gc_rest can reduce malloc_increase */
+ goto retry;
+ }
+ garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC);
+ }
}
#if MALLOC_ALLOCATED_SIZE
if (new_size >= old_size) {
- ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - old_size);
+ ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - old_size);
}
else {
- size_t dec_size = old_size - new_size;
- size_t allocated_size = objspace->malloc_params.allocated_size;
+ size_t dec_size = old_size - new_size;
+ size_t allocated_size = objspace->malloc_params.allocated_size;
#if MALLOC_ALLOCATED_SIZE_CHECK
- if (allocated_size < dec_size) {
- rb_bug("objspace_malloc_increase: underflow malloc_params.allocated_size.");
- }
+ if (allocated_size < dec_size) {
+ rb_bug("objspace_malloc_increase: underflow malloc_params.allocated_size.");
+ }
#endif
- atomic_sub_nounderflow(&objspace->malloc_params.allocated_size, dec_size);
+ atomic_sub_nounderflow(&objspace->malloc_params.allocated_size, dec_size);
}
- if (0) fprintf(stderr, "increase - ptr: %p, type: %s, new_size: %"PRIdSIZE", old_size: %"PRIdSIZE"\n",
- mem,
- type == MEMOP_TYPE_MALLOC ? "malloc" :
- type == MEMOP_TYPE_FREE ? "free " :
- type == MEMOP_TYPE_REALLOC ? "realloc": "error",
- new_size, old_size);
-
switch (type) {
case MEMOP_TYPE_MALLOC:
- ATOMIC_SIZE_INC(objspace->malloc_params.allocations);
- break;
+ ATOMIC_SIZE_INC(objspace->malloc_params.allocations);
+ break;
case MEMOP_TYPE_FREE:
- {
- size_t allocations = objspace->malloc_params.allocations;
- if (allocations > 0) {
- atomic_sub_nounderflow(&objspace->malloc_params.allocations, 1);
- }
+ {
+ size_t allocations = objspace->malloc_params.allocations;
+ if (allocations > 0) {
+ atomic_sub_nounderflow(&objspace->malloc_params.allocations, 1);
+ }
#if MALLOC_ALLOCATED_SIZE_CHECK
- else {
- GC_ASSERT(objspace->malloc_params.allocations > 0);
- }
+ else {
+ GC_ASSERT(objspace->malloc_params.allocations > 0);
+ }
#endif
- }
- break;
+ }
+ break;
case MEMOP_TYPE_REALLOC: /* ignore */ break;
}
#endif
+ return true;
}
+#define objspace_malloc_increase(...) \
+ for (bool malloc_increase_done = objspace_malloc_increase_report(__VA_ARGS__); \
+ !malloc_increase_done; \
+ malloc_increase_done = objspace_malloc_increase_body(__VA_ARGS__))
+
struct malloc_obj_info { /* 4 words */
size_t size;
#if USE_GC_MALLOC_OBJ_INFO_DETAILS
@@ -11328,6 +12263,16 @@ objspace_malloc_prepare(rb_objspace_t *objspace, size_t size)
return size;
}
+static bool
+malloc_during_gc_p(rb_objspace_t *objspace)
+{
+ /* malloc is not allowed during GC when we're not using multiple ractors
+ * (since ractors can run while another thread is sweeping) and when we
+ * have the GVL (since if we don't have the GVL, we'll try to acquire the
+ * GVL which will block and ensure the other thread finishes GC). */
+ return during_gc && !rb_multi_ractor_p() && ruby_thread_has_gvl_p();
+}
+
static inline void *
objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
{
@@ -11351,10 +12296,16 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
}
#if defined(__GNUC__) && RUBY_DEBUG
-#define RB_BUG_INSTEAD_OF_RB_MEMERROR
+#define RB_BUG_INSTEAD_OF_RB_MEMERROR 1
#endif
-#ifdef RB_BUG_INSTEAD_OF_RB_MEMERROR
+#ifndef RB_BUG_INSTEAD_OF_RB_MEMERROR
+# define RB_BUG_INSTEAD_OF_RB_MEMERROR 0
+#endif
+
+#define GC_MEMERROR(...) \
+ ((RB_BUG_INSTEAD_OF_RB_MEMERROR+0) ? rb_bug("" __VA_ARGS__) : rb_memerror())
+
#define TRY_WITH_GC(siz, expr) do { \
const gc_profile_record_flag gpr = \
GPR_FLAG_FULL_MARK | \
@@ -11368,29 +12319,27 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
} \
else if (!garbage_collect_with_gvl(objspace, gpr)) { \
/* @shyouhei thinks this doesn't happen */ \
- rb_bug("TRY_WITH_GC: could not GC"); \
+ GC_MEMERROR("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); \
+ GC_MEMERROR("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 | \
- GPR_FLAG_IMMEDIATE_MARK | GPR_FLAG_IMMEDIATE_SWEEP | \
- GPR_FLAG_MALLOC) || \
- !(alloc))) { \
- ruby_memerror(); \
- } \
- } while (0)
-#endif
+
+static void
+check_malloc_not_in_gc(rb_objspace_t *objspace, const char *msg)
+{
+ if (UNLIKELY(malloc_during_gc_p(objspace))) {
+ dont_gc_on();
+ during_gc = false;
+ rb_bug("Cannot %s during GC", msg);
+ }
+}
/* these shouldn't be called directly.
* objspace_* functions do not check allocation size.
@@ -11398,6 +12347,8 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
static void *
objspace_xmalloc0(rb_objspace_t *objspace, size_t size)
{
+ check_malloc_not_in_gc(objspace, "malloc");
+
void *mem;
size = objspace_malloc_prepare(objspace, size);
@@ -11415,6 +12366,8 @@ xmalloc2_size(const size_t count, const size_t elsize)
static void *
objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t old_size)
{
+ check_malloc_not_in_gc(objspace, "realloc");
+
void *mem;
if (!ptr) return objspace_xmalloc0(objspace, new_size);
@@ -11438,7 +12391,7 @@ objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t ol
* a non-NULL pointer when its argument is 0. That return value
* is safe (and is expected) to be passed to free().
*
- * http://man7.org/linux/man-pages/man3/malloc.3.html
+ * https://man7.org/linux/man-pages/man3/malloc.3.html
*
* - As I read the implementation jemalloc's malloc() returns fully
* normal 16 bytes memory region when its argument is 0.
@@ -11472,7 +12425,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(new_size, mem = realloc(ptr, new_size));
+ TRY_WITH_GC(new_size, mem = RB_GNUC_EXTENSION_BLOCK(realloc(ptr, new_size)));
new_size = objspace_malloc_size(objspace, mem, new_size);
#if CALC_EXACT_MALLOC_SIZE
@@ -11613,10 +12566,11 @@ objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size)
#endif
old_size = objspace_malloc_size(objspace, ptr, old_size);
- free(ptr);
- RB_DEBUG_COUNTER_INC(heap_xfree);
-
- objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE);
+ objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE) {
+ free(ptr);
+ ptr = NULL;
+ RB_DEBUG_COUNTER_INC(heap_xfree);
+ }
}
static void *
@@ -11629,7 +12583,7 @@ void *
ruby_xmalloc_body(size_t size)
{
if ((ssize_t)size < 0) {
- negative_size_allocation_error("too large allocation size");
+ negative_size_allocation_error("too large allocation size");
}
return ruby_xmalloc0(size);
}
@@ -11638,8 +12592,8 @@ void
ruby_malloc_size_overflow(size_t count, size_t elsize)
{
rb_raise(rb_eArgError,
- "malloc: possible integer overflow (%"PRIuSIZE"*%"PRIuSIZE")",
- count, elsize);
+ "malloc: possible integer overflow (%"PRIuSIZE"*%"PRIuSIZE")",
+ count, elsize);
}
void *
@@ -11651,6 +12605,13 @@ ruby_xmalloc2_body(size_t n, size_t size)
static void *
objspace_xcalloc(rb_objspace_t *objspace, size_t size)
{
+ if (UNLIKELY(malloc_during_gc_p(objspace))) {
+ rb_warn("calloc during GC detected, this could cause crashes if it triggers another GC");
+#if RGENGC_CHECK_MODE || RUBY_DEBUG
+ rb_bug("Cannot calloc during GC");
+#endif
+ }
+
void *mem;
size = objspace_malloc_prepare(objspace, size);
@@ -11671,7 +12632,7 @@ void *
ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size)
{
if ((ssize_t)new_size < 0) {
- negative_size_allocation_error("too large allocation size");
+ negative_size_allocation_error("too large allocation size");
}
return objspace_xrealloc(&rb_objspace, ptr, new_size, old_size);
@@ -11705,8 +12666,16 @@ ruby_xrealloc2_body(void *ptr, size_t n, size_t size)
void
ruby_sized_xfree(void *x, size_t size)
{
- if (x) {
- objspace_xfree(&rb_objspace, x, size);
+ if (LIKELY(x)) {
+ /* It's possible for a C extension's pthread destructor function set by pthread_key_create
+ * to be called after ruby_vm_destruct and attempt to free memory. Fall back to mimfree in
+ * that case. */
+ if (LIKELY(GET_VM())) {
+ objspace_xfree(&rb_objspace, x, size);
+ }
+ else {
+ ruby_mimfree(x);
+ }
}
}
@@ -11724,6 +12693,13 @@ rb_xmalloc_mul_add(size_t x, size_t y, size_t z) /* x * y + z */
}
void *
+rb_xcalloc_mul_add(size_t x, size_t y, size_t z) /* x * y + z */
+{
+ size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
+ return ruby_xcalloc(w, 1);
+}
+
+void *
rb_xrealloc_mul_add(const void *p, size_t x, size_t y, size_t z) /* x * y + z */
{
size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
@@ -11809,7 +12785,7 @@ rb_alloc_tmp_buffer(volatile VALUE *store, long len)
long cnt;
if (len < 0 || (cnt = (long)roomof(len, sizeof(VALUE))) < 0) {
- rb_raise(rb_eArgError, "negative buffer size (or size too big)");
+ rb_raise(rb_eArgError, "negative buffer size (or size too big)");
}
return rb_alloc_tmp_buffer_with_count(store, len, cnt);
@@ -11820,9 +12796,9 @@ rb_free_tmp_buffer(volatile VALUE *store)
{
rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
if (s) {
- void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
- s->cnt = 0;
- ruby_xfree(ptr);
+ void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
+ s->cnt = 0;
+ ruby_xfree(ptr);
}
}
@@ -11863,10 +12839,10 @@ rb_gc_adjust_memory_usage(ssize_t diff)
{
rb_objspace_t *objspace = &rb_objspace;
if (diff > 0) {
- objspace_malloc_increase(objspace, 0, diff, 0, MEMOP_TYPE_REALLOC);
+ objspace_malloc_increase(objspace, 0, diff, 0, MEMOP_TYPE_REALLOC);
}
else if (diff < 0) {
- objspace_malloc_increase(objspace, 0, 0, -diff, MEMOP_TYPE_REALLOC);
+ objspace_malloc_increase(objspace, 0, 0, -diff, MEMOP_TYPE_REALLOC);
}
}
@@ -11893,12 +12869,47 @@ wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg)
}
#endif
+static int
+wmap_replace_ref(st_data_t *key, st_data_t *value, st_data_t _argp, int existing)
+{
+ *key = rb_gc_location((VALUE)*key);
+
+ VALUE *values = (VALUE *)*value;
+ VALUE size = values[0];
+
+ for (VALUE index = 1; index <= size; index++) {
+ values[index] = rb_gc_location(values[index]);
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+wmap_foreach_replace(st_data_t key, st_data_t value, st_data_t _argp, int error)
+{
+ if (rb_gc_location((VALUE)key) != (VALUE)key) {
+ return ST_REPLACE;
+ }
+
+ VALUE *values = (VALUE *)value;
+ VALUE size = values[0];
+
+ for (VALUE index = 1; index <= size; index++) {
+ VALUE val = values[index];
+ if (rb_gc_location(val) != val) {
+ return ST_REPLACE;
+ }
+ }
+
+ return ST_CONTINUE;
+}
+
static void
wmap_compact(void *ptr)
{
struct weakmap *w = ptr;
if (w->wmap2obj) rb_gc_update_tbl_refs(w->wmap2obj);
- if (w->obj2wmap) rb_gc_update_tbl_refs(w->obj2wmap);
+ if (w->obj2wmap) st_foreach_with_replace(w->obj2wmap, wmap_foreach_replace, wmap_replace_ref, (st_data_t)NULL);
w->final = rb_gc_location(w->final);
}
@@ -11927,6 +12938,7 @@ wmap_free(void *ptr)
st_foreach(w->obj2wmap, wmap_free_map, 0);
st_free_table(w->obj2wmap);
st_free_table(w->wmap2obj);
+ xfree(w);
}
static int
@@ -11952,9 +12964,9 @@ wmap_memsize(const void *ptr)
static const rb_data_type_t weakmap_type = {
"weakmap",
{
- wmap_mark,
- wmap_free,
- wmap_memsize,
+ wmap_mark,
+ wmap_free,
+ wmap_memsize,
wmap_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
@@ -11976,32 +12988,59 @@ 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;
- return TRUE;
+ if (SPECIAL_CONST_P(obj)) return TRUE;
+ /* If is_pointer_to_heap returns false, the page could be in the tomb heap
+ * or have already been freed. */
+ if (!is_pointer_to_heap(objspace, (void *)obj)) return FALSE;
+
+ 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;
}
static int
-wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+wmap_remove_inverse_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
{
- VALUE wmap, *ptr, size, i, j;
if (!existing) return ST_STOP;
- wmap = (VALUE)arg, ptr = (VALUE *)*value;
- for (i = j = 1, size = ptr[0]; i <= size; ++i) {
- if (ptr[i] != wmap) {
- ptr[j++] = ptr[i];
- }
+
+ VALUE old_ref = (VALUE)arg;
+
+ VALUE *values = (VALUE *)*val;
+ VALUE size = values[0];
+
+ if (size == 1) {
+ // fast path, we only had one backref
+ RUBY_ASSERT(values[1] == old_ref);
+ ruby_sized_xfree(values, 2 * sizeof(VALUE));
+ return ST_DELETE;
}
- if (j == 1) {
- ruby_sized_xfree(ptr, i * sizeof(VALUE));
- return ST_DELETE;
+
+ bool found = false;
+ VALUE index = 1;
+ for (; index <= size; index++) {
+ if (values[index] == old_ref) {
+ found = true;
+ break;
+ }
}
- if (j < i) {
- SIZED_REALLOC_N(ptr, VALUE, j + 1, i);
- ptr[0] = j;
- *value = (st_data_t)ptr;
+ if (!found) return ST_STOP;
+
+ if (size > index) {
+ MEMMOVE(&values[index], &values[index + 1], VALUE, size - index);
}
+
+ size -= 1;
+ values[0] = size;
+ SIZED_REALLOC_N(values, VALUE, size + 1, size + 2);
+ *val = (st_data_t)values;
return ST_CONTINUE;
}
@@ -12015,26 +13054,26 @@ wmap_finalize(RB_BLOCK_CALL_FUNC_ARGLIST(objid, self))
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
/* Get reference from object id. */
- if ((obj = id2ref_obj_tbl(&rb_objspace, objid)) == Qundef) {
+ if (UNDEF_P(obj = id2ref_obj_tbl(&rb_objspace, objid))) {
rb_bug("wmap_finalize: objid is not found.");
}
/* obj is original referenced object and/or weak reference. */
orig = (st_data_t)obj;
if (st_delete(w->obj2wmap, &orig, &data)) {
- rids = (VALUE *)data;
- size = *rids++;
- for (i = 0; i < size; ++i) {
- wmap = (st_data_t)rids[i];
- st_delete(w->wmap2obj, &wmap, NULL);
- }
- ruby_sized_xfree((VALUE *)data, (size + 1) * sizeof(VALUE));
+ rids = (VALUE *)data;
+ size = *rids++;
+ for (i = 0; i < size; ++i) {
+ wmap = (st_data_t)rids[i];
+ st_delete(w->wmap2obj, &wmap, NULL);
+ }
+ ruby_sized_xfree((VALUE *)data, (size + 1) * sizeof(VALUE));
}
wmap = (st_data_t)obj;
if (st_delete(w->wmap2obj, &wmap, &orig)) {
- wmap = (st_data_t)obj;
- st_update(w->obj2wmap, orig, wmap_final_func, wmap);
+ wmap = (st_data_t)obj;
+ st_update(w->obj2wmap, orig, wmap_remove_inverse_ref, wmap);
}
return self;
}
@@ -12044,24 +13083,38 @@ struct wmap_iter_arg {
VALUE value;
};
+static VALUE
+wmap_inspect_append(rb_objspace_t *objspace, VALUE str, VALUE obj)
+{
+ if (SPECIAL_CONST_P(obj)) {
+ return rb_str_append(str, rb_inspect(obj));
+ }
+ else if (wmap_live_p(objspace, obj)) {
+ return rb_str_append(str, rb_any_to_s(obj));
+ }
+ else {
+ return rb_str_catf(str, "#<collected:%p>", (void*)obj);
+ }
+}
+
static int
wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
{
- VALUE str = (VALUE)arg;
+ struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
+ rb_objspace_t *objspace = argp->objspace;
+ VALUE str = argp->value;
VALUE k = (VALUE)key, v = (VALUE)val;
if (RSTRING_PTR(str)[0] == '#') {
- rb_str_cat2(str, ", ");
+ rb_str_cat2(str, ", ");
}
else {
- rb_str_cat2(str, ": ");
- RSTRING_PTR(str)[0] = '#';
+ rb_str_cat2(str, ": ");
+ RSTRING_PTR(str)[0] = '#';
}
- k = SPECIAL_CONST_P(k) ? rb_inspect(k) : rb_any_to_s(k);
- rb_str_append(str, k);
+ wmap_inspect_append(objspace, str, k);
rb_str_cat2(str, " => ");
- v = SPECIAL_CONST_P(v) ? rb_inspect(v) : rb_any_to_s(v);
- rb_str_append(str, v);
+ wmap_inspect_append(objspace, str, v);
return ST_CONTINUE;
}
@@ -12072,26 +13125,38 @@ wmap_inspect(VALUE self)
VALUE str;
VALUE c = rb_class_name(CLASS_OF(self));
struct weakmap *w;
+ struct wmap_iter_arg args;
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self);
if (w->wmap2obj) {
- st_foreach(w->wmap2obj, wmap_inspect_i, str);
+ args.objspace = &rb_objspace;
+ args.value = str;
+ st_foreach(w->wmap2obj, wmap_inspect_i, (st_data_t)&args);
}
RSTRING_PTR(str)[0] = '#';
rb_str_cat2(str, ">");
return str;
}
+static inline bool
+wmap_live_entry_p(rb_objspace_t *objspace, st_data_t key, st_data_t val)
+{
+ return wmap_live_p(objspace, (VALUE)key) && wmap_live_p(objspace, (VALUE)val);
+}
+
static int
wmap_each_i(st_data_t key, st_data_t val, st_data_t arg)
{
rb_objspace_t *objspace = (rb_objspace_t *)arg;
- VALUE obj = (VALUE)val;
- if (wmap_live_p(objspace, obj)) {
- rb_yield_values(2, (VALUE)key, obj);
+
+ if (wmap_live_entry_p(objspace, key, val)) {
+ rb_yield_values(2, (VALUE)key, (VALUE)val);
+ return ST_CONTINUE;
+ }
+ else {
+ return ST_DELETE;
}
- return ST_CONTINUE;
}
/* Iterates over keys and objects in a weakly referenced object */
@@ -12110,11 +13175,14 @@ static int
wmap_each_key_i(st_data_t key, st_data_t val, st_data_t arg)
{
rb_objspace_t *objspace = (rb_objspace_t *)arg;
- VALUE obj = (VALUE)val;
- if (wmap_live_p(objspace, obj)) {
- rb_yield((VALUE)key);
+
+ if (wmap_live_entry_p(objspace, key, val)) {
+ rb_yield((VALUE)key);
+ return ST_CONTINUE;
+ }
+ else {
+ return ST_DELETE;
}
- return ST_CONTINUE;
}
/* Iterates over keys and objects in a weakly referenced object */
@@ -12133,11 +13201,14 @@ static int
wmap_each_value_i(st_data_t key, st_data_t val, st_data_t arg)
{
rb_objspace_t *objspace = (rb_objspace_t *)arg;
- VALUE obj = (VALUE)val;
- if (wmap_live_p(objspace, obj)) {
- rb_yield(obj);
+
+ if (wmap_live_entry_p(objspace, key, val)) {
+ rb_yield((VALUE)val);
+ return ST_CONTINUE;
+ }
+ else {
+ return ST_DELETE;
}
- return ST_CONTINUE;
}
/* Iterates over keys and objects in a weakly referenced object */
@@ -12158,11 +13229,14 @@ wmap_keys_i(st_data_t key, st_data_t val, st_data_t arg)
struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
rb_objspace_t *objspace = argp->objspace;
VALUE ary = argp->value;
- VALUE obj = (VALUE)val;
- if (wmap_live_p(objspace, obj)) {
- rb_ary_push(ary, (VALUE)key);
+
+ if (wmap_live_entry_p(objspace, key, val)) {
+ rb_ary_push(ary, (VALUE)key);
+ return ST_CONTINUE;
+ }
+ else {
+ return ST_DELETE;
}
- return ST_CONTINUE;
}
/* Iterates over keys and objects in a weakly referenced object */
@@ -12185,11 +13259,14 @@ wmap_values_i(st_data_t key, st_data_t val, st_data_t arg)
struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
rb_objspace_t *objspace = argp->objspace;
VALUE ary = argp->value;
- VALUE obj = (VALUE)val;
- if (wmap_live_p(objspace, obj)) {
- rb_ary_push(ary, obj);
+
+ if (wmap_live_entry_p(objspace, key, val)) {
+ rb_ary_push(ary, (VALUE)val);
+ return ST_CONTINUE;
+ }
+ else {
+ return ST_DELETE;
}
- return ST_CONTINUE;
}
/* Iterates over values and objects in a weakly referenced object */
@@ -12211,14 +13288,22 @@ wmap_aset_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
{
VALUE size, *ptr, *optr;
if (existing) {
- size = (ptr = optr = (VALUE *)*val)[0];
- ++size;
+ size = (ptr = optr = (VALUE *)*val)[0];
+
+ for (VALUE index = 1; index <= size; index++) {
+ if (ptr[index] == (VALUE)arg) {
+ // The reference was already registered.
+ return ST_STOP;
+ }
+ }
+
+ ++size;
SIZED_REALLOC_N(ptr, VALUE, size + 1, size);
}
else {
- optr = 0;
- size = 1;
- ptr = ruby_xmalloc0(2 * sizeof(VALUE));
+ optr = 0;
+ size = 1;
+ ptr = ruby_xmalloc0(2 * sizeof(VALUE));
}
ptr[0] = size;
ptr[size] = (VALUE)arg;
@@ -12227,6 +13312,23 @@ wmap_aset_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
return ST_CONTINUE;
}
+struct wmap_aset_replace_args {
+ VALUE new_value;
+ VALUE old_value;
+};
+
+static int
+wmap_aset_replace_value(st_data_t *key, st_data_t *val, st_data_t _args, int existing)
+{
+ struct wmap_aset_replace_args *args = (struct wmap_aset_replace_args *)_args;
+
+ if (existing) {
+ args->old_value = *val;
+ }
+ *val = (st_data_t)args->new_value;
+ return ST_CONTINUE;
+}
+
/* Creates a weak reference from the given key to the given value */
static VALUE
wmap_aset(VALUE self, VALUE key, VALUE value)
@@ -12241,8 +13343,25 @@ wmap_aset(VALUE self, VALUE key, VALUE value)
define_final0(key, w->final);
}
- st_update(w->obj2wmap, (st_data_t)value, wmap_aset_update, key);
- st_insert(w->wmap2obj, (st_data_t)key, (st_data_t)value);
+ struct wmap_aset_replace_args aset_args = {
+ .new_value = value,
+ .old_value = Qundef,
+ };
+ st_update(w->wmap2obj, (st_data_t)key, wmap_aset_replace_value, (st_data_t)&aset_args);
+
+ // If the value is unchanged, we have nothing to do.
+ if (value != aset_args.old_value) {
+ if (!UNDEF_P(aset_args.old_value) && FL_ABLE(aset_args.old_value)) {
+ // That key existed and had an inverse reference, we need to clear the outdated inverse reference.
+ st_update(w->obj2wmap, (st_data_t)aset_args.old_value, wmap_remove_inverse_ref, key);
+ }
+
+ if (FL_ABLE(value)) {
+ // If the value has no finalizer, we don't need to keep the inverse reference
+ st_update(w->obj2wmap, (st_data_t)value, wmap_aset_update, key);
+ }
+ }
+
return nonspecial_obj_id(value);
}
@@ -12254,6 +13373,7 @@ wmap_lookup(VALUE self, VALUE key)
VALUE obj;
struct weakmap *w;
rb_objspace_t *objspace = &rb_objspace;
+ GC_ASSERT(wmap_live_p(objspace, key));
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
if (!st_lookup(w->wmap2obj, (st_data_t)key, &data)) return Qundef;
@@ -12267,14 +13387,14 @@ static VALUE
wmap_aref(VALUE self, VALUE key)
{
VALUE obj = wmap_lookup(self, key);
- return obj != Qundef ? obj : Qnil;
+ return !UNDEF_P(obj) ? obj : Qnil;
}
/* Returns +true+ if +key+ is registered */
static VALUE
wmap_has_key(VALUE self, VALUE key)
{
- return wmap_lookup(self, key) == Qundef ? Qfalse : Qtrue;
+ return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
}
/* Returns the number of referenced objects */
@@ -12299,16 +13419,14 @@ wmap_size(VALUE self)
#define GC_PROFILE_RECORD_DEFAULT_SIZE 100
-/* return sec in user time */
-static double
-getrusage_time(void)
+static bool
+current_process_time(struct timespec *ts)
{
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
{
static int try_clock_gettime = 1;
- struct timespec ts;
- if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
- return ts.tv_sec + ts.tv_nsec * 1e-9;
+ if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ts) == 0) {
+ return true;
}
else {
try_clock_gettime = 0;
@@ -12322,80 +13440,87 @@ getrusage_time(void)
struct timeval time;
if (getrusage(RUSAGE_SELF, &usage) == 0) {
time = usage.ru_utime;
- return time.tv_sec + time.tv_usec * 1e-6;
+ ts->tv_sec = time.tv_sec;
+ ts->tv_nsec = (int32_t)time.tv_usec * 1000;
+ return true;
}
}
#endif
#ifdef _WIN32
{
- FILETIME creation_time, exit_time, kernel_time, user_time;
- ULARGE_INTEGER ui;
- LONG_LONG q;
- double t;
-
- if (GetProcessTimes(GetCurrentProcess(),
- &creation_time, &exit_time, &kernel_time, &user_time) != 0) {
- memcpy(&ui, &user_time, sizeof(FILETIME));
- q = ui.QuadPart / 10L;
- t = (DWORD)(q % 1000000L) * 1e-6;
- q /= 1000000L;
-#ifdef __GNUC__
- t += q;
-#else
- t += (double)(DWORD)(q >> 16) * (1 << 16);
- t += (DWORD)q & ~(~0 << 16);
-#endif
- return t;
- }
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+ ULARGE_INTEGER ui;
+
+ if (GetProcessTimes(GetCurrentProcess(),
+ &creation_time, &exit_time, &kernel_time, &user_time) != 0) {
+ memcpy(&ui, &user_time, sizeof(FILETIME));
+#define PER100NSEC (uint64_t)(1000 * 1000 * 10)
+ ts->tv_nsec = (long)(ui.QuadPart % PER100NSEC);
+ ts->tv_sec = (time_t)(ui.QuadPart / PER100NSEC);
+ return true;
+ }
}
#endif
- return 0.0;
+ return false;
+}
+
+static double
+getrusage_time(void)
+{
+ struct timespec ts;
+ if (current_process_time(&ts)) {
+ return ts.tv_sec + ts.tv_nsec * 1e-9;
+ }
+ else {
+ return 0.0;
+ }
}
+
static inline void
gc_prof_setup_new_record(rb_objspace_t *objspace, unsigned int reason)
{
if (objspace->profile.run) {
- size_t index = objspace->profile.next_index;
- gc_profile_record *record;
-
- /* create new record */
- objspace->profile.next_index++;
-
- if (!objspace->profile.records) {
- objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE;
- objspace->profile.records = malloc(xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
- }
- if (index >= objspace->profile.size) {
- void *ptr;
- objspace->profile.size += 1000;
- ptr = realloc(objspace->profile.records, xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
- if (!ptr) rb_memerror();
- objspace->profile.records = ptr;
- }
- if (!objspace->profile.records) {
- rb_bug("gc_profile malloc or realloc miss");
- }
- record = objspace->profile.current_record = &objspace->profile.records[objspace->profile.next_index - 1];
- MEMZERO(record, gc_profile_record, 1);
-
- /* setup before-GC parameter */
- record->flags = reason | (ruby_gc_stressful ? GPR_FLAG_STRESS : 0);
+ size_t index = objspace->profile.next_index;
+ gc_profile_record *record;
+
+ /* create new record */
+ objspace->profile.next_index++;
+
+ if (!objspace->profile.records) {
+ objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE;
+ objspace->profile.records = malloc(xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
+ }
+ if (index >= objspace->profile.size) {
+ void *ptr;
+ objspace->profile.size += 1000;
+ ptr = realloc(objspace->profile.records, xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
+ if (!ptr) rb_memerror();
+ objspace->profile.records = ptr;
+ }
+ if (!objspace->profile.records) {
+ rb_bug("gc_profile malloc or realloc miss");
+ }
+ record = objspace->profile.current_record = &objspace->profile.records[objspace->profile.next_index - 1];
+ MEMZERO(record, gc_profile_record, 1);
+
+ /* setup before-GC parameter */
+ record->flags = reason | (ruby_gc_stressful ? GPR_FLAG_STRESS : 0);
#if MALLOC_ALLOCATED_SIZE
- record->allocated_size = malloc_allocated_size;
+ record->allocated_size = malloc_allocated_size;
#endif
#if GC_PROFILE_MORE_DETAIL && GC_PROFILE_DETAIL_MEMORY
#ifdef RUSAGE_SELF
- {
- struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage) == 0) {
- record->maxrss = usage.ru_maxrss;
- record->minflt = usage.ru_minflt;
- record->majflt = usage.ru_majflt;
- }
- }
+ {
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage) == 0) {
+ record->maxrss = usage.ru_maxrss;
+ record->minflt = usage.ru_minflt;
+ record->majflt = usage.ru_majflt;
+ }
+ }
#endif
#endif
}
@@ -12405,12 +13530,12 @@ static inline void
gc_prof_timer_start(rb_objspace_t *objspace)
{
if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
+ gc_profile_record *record = gc_prof_record(objspace);
#if GC_PROFILE_MORE_DETAIL
- record->prepare_time = objspace->profile.prepare_time;
+ record->prepare_time = objspace->profile.prepare_time;
#endif
- record->gc_time = 0;
- record->gc_invoke_time = getrusage_time();
+ record->gc_time = 0;
+ record->gc_invoke_time = getrusage_time();
}
}
@@ -12419,10 +13544,10 @@ elapsed_time_from(double time)
{
double now = getrusage_time();
if (now > time) {
- return now - time;
+ return now - time;
}
else {
- return 0;
+ return 0;
}
}
@@ -12430,9 +13555,9 @@ static inline void
gc_prof_timer_stop(rb_objspace_t *objspace)
{
if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- record->gc_time = elapsed_time_from(record->gc_invoke_time);
- record->gc_invoke_time -= objspace->profile.invoke_time;
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->gc_time = elapsed_time_from(record->gc_invoke_time);
+ record->gc_invoke_time -= objspace->profile.invoke_time;
}
}
@@ -12444,7 +13569,7 @@ gc_prof_mark_timer_start(rb_objspace_t *objspace)
RUBY_DTRACE_GC_HOOK(MARK_BEGIN);
#if GC_PROFILE_MORE_DETAIL
if (gc_prof_enabled(objspace)) {
- gc_prof_record(objspace)->gc_mark_time = getrusage_time();
+ gc_prof_record(objspace)->gc_mark_time = getrusage_time();
}
#endif
}
@@ -12456,7 +13581,7 @@ gc_prof_mark_timer_stop(rb_objspace_t *objspace)
#if GC_PROFILE_MORE_DETAIL
if (gc_prof_enabled(objspace)) {
gc_profile_record *record = gc_prof_record(objspace);
- record->gc_mark_time = elapsed_time_from(record->gc_mark_time);
+ record->gc_mark_time = elapsed_time_from(record->gc_mark_time);
}
#endif
}
@@ -12466,11 +13591,11 @@ gc_prof_sweep_timer_start(rb_objspace_t *objspace)
{
RUBY_DTRACE_GC_HOOK(SWEEP_BEGIN);
if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
+ gc_profile_record *record = gc_prof_record(objspace);
- if (record->gc_time > 0 || GC_PROFILE_MORE_DETAIL) {
- objspace->profile.gc_sweep_start_time = getrusage_time();
- }
+ if (record->gc_time > 0 || GC_PROFILE_MORE_DETAIL) {
+ objspace->profile.gc_sweep_start_time = getrusage_time();
+ }
}
}
@@ -12480,23 +13605,23 @@ gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
RUBY_DTRACE_GC_HOOK(SWEEP_END);
if (gc_prof_enabled(objspace)) {
- double sweep_time;
- gc_profile_record *record = gc_prof_record(objspace);
-
- if (record->gc_time > 0) {
- sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
- /* need to accumulate GC time for lazy sweep after gc() */
- record->gc_time += sweep_time;
- }
- else if (GC_PROFILE_MORE_DETAIL) {
- sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
- }
+ double sweep_time;
+ gc_profile_record *record = gc_prof_record(objspace);
+
+ if (record->gc_time > 0) {
+ sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
+ /* need to accumulate GC time for lazy sweep after gc() */
+ record->gc_time += sweep_time;
+ }
+ else if (GC_PROFILE_MORE_DETAIL) {
+ sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
+ }
#if GC_PROFILE_MORE_DETAIL
- record->gc_sweep_time += sweep_time;
- if (heap_pages_deferred_final) record->flags |= GPR_FLAG_HAVE_FINALIZE;
+ record->gc_sweep_time += sweep_time;
+ if (heap_pages_deferred_final) record->flags |= GPR_FLAG_HAVE_FINALIZE;
#endif
- if (heap_pages_deferred_final) objspace->profile.latest_gc_info |= GPR_FLAG_HAVE_FINALIZE;
+ if (heap_pages_deferred_final) objspace->profile.latest_gc_info |= GPR_FLAG_HAVE_FINALIZE;
}
}
@@ -12506,8 +13631,8 @@ gc_prof_set_malloc_info(rb_objspace_t *objspace)
#if GC_PROFILE_MORE_DETAIL
if (gc_prof_enabled(objspace)) {
gc_profile_record *record = gc_prof_record(objspace);
- record->allocate_increase = malloc_increase;
- record->allocate_limit = malloc_limit;
+ record->allocate_increase = malloc_increase;
+ record->allocate_limit = malloc_limit;
}
#endif
}
@@ -12516,19 +13641,19 @@ static inline void
gc_prof_set_heap_info(rb_objspace_t *objspace)
{
if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- size_t live = objspace->profile.total_allocated_objects_at_gc_start - objspace->profile.total_freed_objects;
- size_t total = objspace->profile.heap_used_at_gc_start * HEAP_PAGE_OBJ_LIMIT;
+ gc_profile_record *record = gc_prof_record(objspace);
+ size_t live = objspace->profile.total_allocated_objects_at_gc_start - objspace->profile.total_freed_objects;
+ size_t total = objspace->profile.heap_used_at_gc_start * HEAP_PAGE_OBJ_LIMIT;
#if GC_PROFILE_MORE_DETAIL
- record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
- record->heap_live_objects = live;
- record->heap_free_objects = total - live;
+ record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
+ record->heap_live_objects = live;
+ record->heap_free_objects = total - live;
#endif
- record->heap_total_objects = total;
- record->heap_use_size = live * sizeof(RVALUE);
- record->heap_total_size = total * sizeof(RVALUE);
+ record->heap_total_objects = total;
+ record->heap_use_size = live * sizeof(RVALUE);
+ record->heap_total_size = total * sizeof(RVALUE);
}
}
@@ -12536,7 +13661,7 @@ gc_prof_set_heap_info(rb_objspace_t *objspace)
* call-seq:
* GC::Profiler.clear -> nil
*
- * Clears the GC profiler data.
+ * Clears the \GC profiler data.
*
*/
@@ -12614,14 +13739,14 @@ gc_profile_record_get(VALUE _)
rb_objspace_t *objspace = (&rb_objspace);
if (!objspace->profile.run) {
- return Qnil;
+ return Qnil;
}
for (i =0; i < objspace->profile.next_index; i++) {
- gc_profile_record *record = &objspace->profile.records[i];
+ gc_profile_record *record = &objspace->profile.records[i];
- prof = rb_hash_new();
- rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(0, rb_hash_new(), record->flags));
+ prof = rb_hash_new();
+ rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(0, rb_hash_new(), record->flags));
rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(record->gc_time));
rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(record->gc_invoke_time));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(record->heap_use_size));
@@ -12638,18 +13763,18 @@ gc_profile_record_get(VALUE _)
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(record->heap_live_objects));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(record->heap_free_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("REMOVING_OBJECTS")), SIZET2NUM(record->removing_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("EMPTY_OBJECTS")), SIZET2NUM(record->empty_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("REMOVING_OBJECTS")), SIZET2NUM(record->removing_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("EMPTY_OBJECTS")), SIZET2NUM(record->empty_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), (record->flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse);
+ rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), RBOOL(record->flags & GPR_FLAG_HAVE_FINALIZE));
#endif
#if RGENGC_PROFILE > 0
- rb_hash_aset(prof, ID2SYM(rb_intern("OLD_OBJECTS")), SIZET2NUM(record->old_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_NORMAL_OBJECTS")), SIZET2NUM(record->remembered_normal_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_SHADY_OBJECTS")), SIZET2NUM(record->remembered_shady_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("OLD_OBJECTS")), SIZET2NUM(record->old_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_NORMAL_OBJECTS")), SIZET2NUM(record->remembered_normal_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_SHADY_OBJECTS")), SIZET2NUM(record->remembered_shady_objects));
#endif
- rb_ary_push(gc_profile, prof);
+ rb_ary_push(gc_profile, prof);
}
return gc_profile;
@@ -12665,8 +13790,8 @@ gc_profile_dump_major_reason(unsigned int flags, char *buff)
int i = 0;
if (reason == GPR_FLAG_NONE) {
- buff[0] = '-';
- buff[1] = 0;
+ buff[0] = '-';
+ buff[1] = 0;
}
else {
#define C(x, s) \
@@ -12675,11 +13800,11 @@ gc_profile_dump_major_reason(unsigned int flags, char *buff)
if (i >= MAJOR_REASON_MAX) rb_bug("gc_profile_dump_major_reason: overflow"); \
buff[i] = 0; \
}
- C(NOFREE, N);
- C(OLDGEN, O);
- C(SHADY, S);
+ C(NOFREE, N);
+ C(OLDGEN, O);
+ C(SHADY, S);
#if RGENGC_ESTIMATE_OLDMALLOC
- C(OLDMALLOC, M);
+ C(OLDMALLOC, M);
#endif
#undef C
}
@@ -12697,88 +13822,88 @@ gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
#endif
if (objspace->profile.run && count /* > 1 */) {
- size_t i;
- const gc_profile_record *record;
+ size_t i;
+ const gc_profile_record *record;
- append(out, rb_sprintf("GC %"PRIuSIZE" invokes.\n", objspace->profile.count));
- append(out, rb_str_new_cstr("Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
+ append(out, rb_sprintf("GC %"PRIuSIZE" invokes.\n", objspace->profile.count));
+ append(out, rb_str_new_cstr("Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
- for (i = 0; i < count; i++) {
- record = &objspace->profile.records[i];
- append(out, rb_sprintf("%5"PRIuSIZE" %19.3f %20"PRIuSIZE" %20"PRIuSIZE" %20"PRIuSIZE" %30.20f\n",
- i+1, record->gc_invoke_time, record->heap_use_size,
- record->heap_total_size, record->heap_total_objects, record->gc_time*1000));
- }
+ for (i = 0; i < count; i++) {
+ record = &objspace->profile.records[i];
+ append(out, rb_sprintf("%5"PRIuSIZE" %19.3f %20"PRIuSIZE" %20"PRIuSIZE" %20"PRIuSIZE" %30.20f\n",
+ i+1, record->gc_invoke_time, record->heap_use_size,
+ record->heap_total_size, record->heap_total_objects, record->gc_time*1000));
+ }
#if GC_PROFILE_MORE_DETAIL
const char *str = "\n\n" \
- "More detail.\n" \
- "Prepare Time = Previously GC's rest sweep time\n"
- "Index Flags Allocate Inc. Allocate Limit"
+ "More detail.\n" \
+ "Prepare Time = Previously GC's rest sweep time\n"
+ "Index Flags Allocate Inc. Allocate Limit"
#if CALC_EXACT_MALLOC_SIZE
- " Allocated Size"
+ " Allocated Size"
#endif
- " Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj"
+ " Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj"
#if RGENGC_PROFILE
- " OldgenObj RemNormObj RemShadObj"
+ " OldgenObj RemNormObj RemShadObj"
#endif
#if GC_PROFILE_DETAIL_MEMORY
- " MaxRSS(KB) MinorFLT MajorFLT"
+ " MaxRSS(KB) MinorFLT MajorFLT"
#endif
"\n";
append(out, rb_str_new_cstr(str));
- for (i = 0; i < count; i++) {
- record = &objspace->profile.records[i];
- append(out, rb_sprintf("%5"PRIuSIZE" %4s/%c/%6s%c %13"PRIuSIZE" %15"PRIuSIZE
+ for (i = 0; i < count; i++) {
+ record = &objspace->profile.records[i];
+ append(out, rb_sprintf("%5"PRIuSIZE" %4s/%c/%6s%c %13"PRIuSIZE" %15"PRIuSIZE
#if CALC_EXACT_MALLOC_SIZE
- " %15"PRIuSIZE
+ " %15"PRIuSIZE
#endif
- " %9"PRIuSIZE" %17.12f %17.12f %17.12f %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
+ " %9"PRIuSIZE" %17.12f %17.12f %17.12f %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
#if RGENGC_PROFILE
- "%10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
+ "%10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
#endif
#if GC_PROFILE_DETAIL_MEMORY
- "%11ld %8ld %8ld"
-#endif
-
- "\n",
- i+1,
- gc_profile_dump_major_reason(record->flags, reason_str),
- (record->flags & GPR_FLAG_HAVE_FINALIZE) ? 'F' : '.',
- (record->flags & GPR_FLAG_NEWOBJ) ? "NEWOBJ" :
- (record->flags & GPR_FLAG_MALLOC) ? "MALLOC" :
- (record->flags & GPR_FLAG_METHOD) ? "METHOD" :
- (record->flags & GPR_FLAG_CAPI) ? "CAPI__" : "??????",
- (record->flags & GPR_FLAG_STRESS) ? '!' : ' ',
- record->allocate_increase, record->allocate_limit,
+ "%11ld %8ld %8ld"
+#endif
+
+ "\n",
+ i+1,
+ gc_profile_dump_major_reason(record->flags, reason_str),
+ (record->flags & GPR_FLAG_HAVE_FINALIZE) ? 'F' : '.',
+ (record->flags & GPR_FLAG_NEWOBJ) ? "NEWOBJ" :
+ (record->flags & GPR_FLAG_MALLOC) ? "MALLOC" :
+ (record->flags & GPR_FLAG_METHOD) ? "METHOD" :
+ (record->flags & GPR_FLAG_CAPI) ? "CAPI__" : "??????",
+ (record->flags & GPR_FLAG_STRESS) ? '!' : ' ',
+ record->allocate_increase, record->allocate_limit,
#if CALC_EXACT_MALLOC_SIZE
- record->allocated_size,
+ record->allocated_size,
#endif
- record->heap_use_pages,
- record->gc_mark_time*1000,
- record->gc_sweep_time*1000,
- record->prepare_time*1000,
+ record->heap_use_pages,
+ record->gc_mark_time*1000,
+ record->gc_sweep_time*1000,
+ record->prepare_time*1000,
- record->heap_live_objects,
- record->heap_free_objects,
- record->removing_objects,
- record->empty_objects
+ record->heap_live_objects,
+ record->heap_free_objects,
+ record->removing_objects,
+ record->empty_objects
#if RGENGC_PROFILE
- ,
- record->old_objects,
- record->remembered_normal_objects,
- record->remembered_shady_objects
+ ,
+ record->old_objects,
+ record->remembered_normal_objects,
+ record->remembered_shady_objects
#endif
#if GC_PROFILE_DETAIL_MEMORY
- ,
- record->maxrss / 1024,
- record->minflt,
- record->majflt
+ ,
+ record->maxrss / 1024,
+ record->minflt,
+ record->majflt
#endif
- ));
- }
+ ));
+ }
#endif
}
}
@@ -12836,12 +13961,12 @@ gc_profile_total_time(VALUE self)
rb_objspace_t *objspace = &rb_objspace;
if (objspace->profile.run && objspace->profile.next_index > 0) {
- size_t i;
- size_t count = objspace->profile.next_index;
+ size_t i;
+ size_t count = objspace->profile.next_index;
- for (i = 0; i < count; i++) {
- time += objspace->profile.records[i].gc_time;
- }
+ for (i = 0; i < count; i++) {
+ time += objspace->profile.records[i].gc_time;
+ }
}
return DBL2NUM(time);
}
@@ -12850,7 +13975,7 @@ gc_profile_total_time(VALUE self)
* call-seq:
* GC::Profiler.enabled? -> true or false
*
- * The current status of GC profile mode.
+ * The current status of \GC profile mode.
*/
static VALUE
@@ -12864,7 +13989,7 @@ gc_profile_enable_get(VALUE self)
* call-seq:
* GC::Profiler.enable -> nil
*
- * Starts the GC profiler.
+ * Starts the \GC profiler.
*
*/
@@ -12881,7 +14006,7 @@ gc_profile_enable(VALUE _)
* call-seq:
* GC::Profiler.disable -> nil
*
- * Stops the GC profiler.
+ * Stops the \GC profiler.
*
*/
@@ -12904,37 +14029,36 @@ type_name(int type, VALUE obj)
{
switch (type) {
#define TYPE_NAME(t) case (t): return #t;
- TYPE_NAME(T_NONE);
- TYPE_NAME(T_OBJECT);
- TYPE_NAME(T_CLASS);
- TYPE_NAME(T_MODULE);
- TYPE_NAME(T_FLOAT);
- TYPE_NAME(T_STRING);
- TYPE_NAME(T_REGEXP);
- TYPE_NAME(T_ARRAY);
- TYPE_NAME(T_HASH);
- TYPE_NAME(T_STRUCT);
- TYPE_NAME(T_BIGNUM);
- TYPE_NAME(T_FILE);
- TYPE_NAME(T_MATCH);
- TYPE_NAME(T_COMPLEX);
- TYPE_NAME(T_RATIONAL);
- TYPE_NAME(T_NIL);
- TYPE_NAME(T_TRUE);
- TYPE_NAME(T_FALSE);
- TYPE_NAME(T_SYMBOL);
- TYPE_NAME(T_FIXNUM);
- TYPE_NAME(T_UNDEF);
- TYPE_NAME(T_IMEMO);
- TYPE_NAME(T_ICLASS);
+ TYPE_NAME(T_NONE);
+ TYPE_NAME(T_OBJECT);
+ TYPE_NAME(T_CLASS);
+ TYPE_NAME(T_MODULE);
+ TYPE_NAME(T_FLOAT);
+ TYPE_NAME(T_STRING);
+ TYPE_NAME(T_REGEXP);
+ TYPE_NAME(T_ARRAY);
+ TYPE_NAME(T_HASH);
+ TYPE_NAME(T_STRUCT);
+ TYPE_NAME(T_BIGNUM);
+ TYPE_NAME(T_FILE);
+ TYPE_NAME(T_MATCH);
+ TYPE_NAME(T_COMPLEX);
+ TYPE_NAME(T_RATIONAL);
+ TYPE_NAME(T_NIL);
+ TYPE_NAME(T_TRUE);
+ TYPE_NAME(T_FALSE);
+ TYPE_NAME(T_SYMBOL);
+ TYPE_NAME(T_FIXNUM);
+ TYPE_NAME(T_UNDEF);
+ TYPE_NAME(T_IMEMO);
+ TYPE_NAME(T_ICLASS);
TYPE_NAME(T_MOVED);
- TYPE_NAME(T_ZOMBIE);
- TYPE_NAME(T_PAYLOAD);
+ TYPE_NAME(T_ZOMBIE);
case T_DATA:
- if (obj && rb_objspace_data_type_name(obj)) {
- return rb_objspace_data_type_name(obj);
- }
- return "T_DATA";
+ if (obj && rb_objspace_data_type_name(obj)) {
+ return rb_objspace_data_type_name(obj);
+ }
+ return "T_DATA";
#undef TYPE_NAME
}
return "unknown";
@@ -12966,29 +14090,18 @@ rb_method_type_name(rb_method_type_t type)
rb_bug("rb_method_type_name: unreachable (type: %d)", type);
}
-/* from array.c */
-# define ARY_SHARED_P(ary) \
- (GC_ASSERT(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
- FL_TEST((ary),ELTS_SHARED)!=0)
-# define ARY_EMBED_P(ary) \
- (GC_ASSERT(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
- FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
-
static void
-rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq)
+rb_raw_iseq_info(char *const buff, const size_t buff_size, const rb_iseq_t *iseq)
{
- if (buff_size > 0 && iseq->body && iseq->body->location.label && !RB_TYPE_P(iseq->body->location.pathobj, T_MOVED)) {
- VALUE path = rb_iseq_path(iseq);
- VALUE n = iseq->body->location.first_lineno;
+ if (buff_size > 0 && ISEQ_BODY(iseq) && ISEQ_BODY(iseq)->location.label && !RB_TYPE_P(ISEQ_BODY(iseq)->location.pathobj, T_MOVED)) {
+ VALUE path = rb_iseq_path(iseq);
+ int n = ISEQ_BODY(iseq)->location.first_lineno;
snprintf(buff, buff_size, " %s@%s:%d",
- RSTRING_PTR(iseq->body->location.label),
- RSTRING_PTR(path),
- n ? FIX2INT(n) : 0 );
+ RSTRING_PTR(ISEQ_BODY(iseq)->location.label),
+ RSTRING_PTR(path), n);
}
}
-bool rb_ractor_p(VALUE rv);
-
static int
str_len_no_raise(VALUE str)
{
@@ -12998,134 +14111,151 @@ str_len_no_raise(VALUE str)
return (int)len;
}
-const char *
-rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
+#define BUFF_ARGS buff + pos, buff_size - pos
+#define APPEND_F(...) if ((pos += snprintf(BUFF_ARGS, "" __VA_ARGS__)) >= buff_size) goto end
+#define APPEND_S(s) do { \
+ if ((pos + (int)rb_strlen_lit(s)) >= buff_size) { \
+ goto end; \
+ } \
+ else { \
+ memcpy(buff + pos, (s), rb_strlen_lit(s) + 1); \
+ } \
+ } while (0)
+#define TF(c) ((c) != 0 ? "true" : "false")
+#define C(c, s) ((c) != 0 ? (s) : " ")
+
+static size_t
+rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj)
{
- int pos = 0;
- void *poisoned = asan_poisoned_object_p(obj);
- asan_unpoison_object(obj, false);
+ size_t pos = 0;
-#define BUFF_ARGS buff + pos, buff_size - pos
-#define APPENDF(f) if ((pos += snprintf f) >= buff_size) goto end
if (SPECIAL_CONST_P(obj)) {
- APPENDF((BUFF_ARGS, "%s", obj_type_name(obj)));
+ APPEND_F("%s", obj_type_name(obj));
if (FIXNUM_P(obj)) {
- APPENDF((BUFF_ARGS, " %ld", FIX2LONG(obj)));
+ APPEND_F(" %ld", FIX2LONG(obj));
}
else if (SYMBOL_P(obj)) {
- APPENDF((BUFF_ARGS, " %s", rb_id2name(SYM2ID(obj))));
+ APPEND_F(" %s", rb_id2name(SYM2ID(obj)));
}
}
else {
-#define TF(c) ((c) != 0 ? "true" : "false")
-#define C(c, s) ((c) != 0 ? (s) : " ")
- const int type = BUILTIN_TYPE(obj);
- const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags);
+ const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags);
if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
- APPENDF((BUFF_ARGS, "%p [%d%s%s%s%s%s] %s ",
+ APPEND_F("%p [%d%s%s%s%s%s%s] %s ",
(void *)obj, age,
C(RVALUE_UNCOLLECTIBLE_BITMAP(obj), "L"),
C(RVALUE_MARK_BITMAP(obj), "M"),
C(RVALUE_PIN_BITMAP(obj), "P"),
C(RVALUE_MARKING_BITMAP(obj), "R"),
C(RVALUE_WB_UNPROTECTED_BITMAP(obj), "U"),
- obj_type_name(obj)));
+ C(rb_objspace_garbage_object_p(obj), "G"),
+ obj_type_name(obj));
}
else {
/* fake */
- APPENDF((BUFF_ARGS, "%p [%dXXXX] %s",
+ APPEND_F("%p [%dXXXX] %s",
(void *)obj, age,
- obj_type_name(obj)));
+ obj_type_name(obj));
}
- if (internal_object_p(obj)) {
- /* ignore */
- }
- else if (type == T_PAYLOAD) {
+ if (internal_object_p(obj)) {
/* ignore */
}
- else if (RBASIC(obj)->klass == 0) {
- APPENDF((BUFF_ARGS, "(temporary internal)"));
- }
- else {
- if (RTEST(RBASIC(obj)->klass)) {
+ else if (RBASIC(obj)->klass == 0) {
+ APPEND_S("(temporary internal)");
+ }
+ else if (RTEST(RBASIC(obj)->klass)) {
VALUE class_path = rb_class_path_cached(RBASIC(obj)->klass);
- if (!NIL_P(class_path)) {
- APPENDF((BUFF_ARGS, "(%s)", RSTRING_PTR(class_path)));
- }
+ if (!NIL_P(class_path)) {
+ APPEND_F("(%s)", RSTRING_PTR(class_path));
}
- }
+ }
#if GC_DEBUG
- APPENDF((BUFF_ARGS, "@%s:%d", RANY(obj)->file, RANY(obj)->line));
-#endif
-
- switch (type) {
- case T_PAYLOAD:
- APPENDF((BUFF_ARGS, "len: %i", RPAYLOAD_LEN(obj)));
- break;
- case T_NODE:
- UNEXPECTED_NODE(rb_raw_obj_info);
- break;
- case T_ARRAY:
- if (FL_TEST(obj, ELTS_SHARED)) {
- APPENDF((BUFF_ARGS, "shared -> %s",
- rb_obj_info(RARRAY(obj)->as.heap.aux.shared_root)));
- }
- else if (FL_TEST(obj, RARRAY_EMBED_FLAG)) {
- APPENDF((BUFF_ARGS, "[%s%s] len: %ld (embed)",
+ APPEND_F("@%s:%d", RANY(obj)->file, RANY(obj)->line);
+#endif
+ }
+ end:
+
+ return pos;
+}
+
+static size_t
+rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALUE obj, size_t pos)
+{
+ if (LIKELY(pos < buff_size) && !SPECIAL_CONST_P(obj)) {
+ const enum ruby_value_type type = BUILTIN_TYPE(obj);
+
+ switch (type) {
+ case T_NODE:
+ UNEXPECTED_NODE(rb_raw_obj_info);
+ break;
+ case T_ARRAY:
+ if (ARY_SHARED_P(obj)) {
+ APPEND_S("shared -> ");
+ rb_raw_obj_info(BUFF_ARGS, ARY_SHARED_ROOT(obj));
+ }
+ else if (ARY_EMBED_P(obj)) {
+ APPEND_F("[%s%s] len: %ld (embed)",
C(ARY_EMBED_P(obj), "E"),
C(ARY_SHARED_P(obj), "S"),
- RARRAY_LEN(obj)));
+ RARRAY_LEN(obj));
}
else {
- APPENDF((BUFF_ARGS, "[%s%s%s] len: %ld, capa:%ld ptr:%p",
+ APPEND_F("[%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"),
RARRAY_LEN(obj),
ARY_EMBED_P(obj) ? -1L : RARRAY(obj)->as.heap.aux.capa,
- (void *)RARRAY_CONST_PTR_TRANSIENT(obj)));
- }
- break;
- case T_STRING: {
- if (STR_SHARED_P(obj)) APPENDF((BUFF_ARGS, " [shared] "));
- APPENDF((BUFF_ARGS, "%.*s", str_len_no_raise(obj), RSTRING_PTR(obj)));
- break;
- }
+ (void *)RARRAY_CONST_PTR_TRANSIENT(obj));
+ }
+ break;
+ case T_STRING: {
+ if (STR_SHARED_P(obj)) {
+ APPEND_F(" [shared] len: %ld", RSTRING_LEN(obj));
+ }
+ else {
+ if (STR_EMBED_P(obj)) APPEND_S(" [embed]");
+
+ APPEND_F(" len: %ld, capa: %" PRIdSIZE, RSTRING_LEN(obj), rb_str_capacity(obj));
+ }
+ APPEND_F(" \"%.*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;
+ VALUE fstr = RSYMBOL(obj)->fstr;
+ ID id = RSYMBOL(obj)->id;
+ if (RB_TYPE_P(fstr, T_STRING)) {
+ APPEND_F(":%s id:%d", RSTRING_PTR(fstr), (unsigned int)id);
+ }
+ else {
+ APPEND_F("(%p) id:%d", (void *)fstr, (unsigned int)id);
+ }
+ break;
}
case T_MOVED: {
- APPENDF((BUFF_ARGS, "-> %p", (void*)rb_gc_location(obj)));
+ APPEND_F("-> %p", (void*)rb_gc_location(obj));
break;
}
case T_HASH: {
- APPENDF((BUFF_ARGS, "[%c%c] %"PRIdSIZE,
- RHASH_AR_TABLE_P(obj) ? 'A' : 'S',
- RHASH_TRANSIENT_P(obj) ? 'T' : ' ',
- RHASH_SIZE(obj)));
- break;
+ APPEND_F("[%c%c] %"PRIdSIZE,
+ RHASH_AR_TABLE_P(obj) ? 'A' : 'S',
+ RHASH_TRANSIENT_P(obj) ? 'T' : ' ',
+ RHASH_SIZE(obj));
+ break;
}
case T_CLASS:
case T_MODULE:
{
VALUE class_path = rb_class_path_cached(obj);
if (!NIL_P(class_path)) {
- APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(class_path)));
+ APPEND_F("%s", RSTRING_PTR(class_path));
}
else {
- APPENDF((BUFF_ARGS, "(annon)"));
+ APPEND_S("(annon)");
}
break;
}
@@ -13133,55 +14263,55 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
{
VALUE class_path = rb_class_path_cached(RBASIC_CLASS(obj));
if (!NIL_P(class_path)) {
- APPENDF((BUFF_ARGS, "src:%s", RSTRING_PTR(class_path)));
+ APPEND_F("src:%s", RSTRING_PTR(class_path));
}
break;
}
case T_OBJECT:
{
- uint32_t len = ROBJECT_NUMIV(obj);
+ uint32_t len = ROBJECT_IV_CAPACITY(obj);
if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
- APPENDF((BUFF_ARGS, "(embed) len:%d", len));
+ APPEND_F("(embed) len:%d", len);
}
else {
VALUE *ptr = ROBJECT_IVPTR(obj);
- APPENDF((BUFF_ARGS, "len:%d ptr:%p", len, (void *)ptr));
+ APPEND_F("len:%d ptr:%p", len, (void *)ptr);
}
}
break;
- case T_DATA: {
- const struct rb_block *block;
- const rb_iseq_t *iseq;
- if (rb_obj_is_proc(obj) &&
- (block = vm_proc_block(obj)) != NULL &&
- (vm_block_type(block) == block_type_iseq) &&
- (iseq = vm_block_iseq(block)) != NULL) {
+ case T_DATA: {
+ const struct rb_block *block;
+ const rb_iseq_t *iseq;
+ if (rb_obj_is_proc(obj) &&
+ (block = vm_proc_block(obj)) != NULL &&
+ (vm_block_type(block) == block_type_iseq) &&
+ (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));
+ APPEND_F("r:%d", r->pub.id);
+ }
+ }
+ else {
+ const char * const type_name = rb_objspace_data_type_name(obj);
+ if (type_name) {
+ APPEND_F("%s", type_name);
}
}
- else {
- const char * const type_name = rb_objspace_data_type_name(obj);
- if (type_name) {
- APPENDF((BUFF_ARGS, "%s", type_name));
- }
- }
- break;
- }
- case T_IMEMO: {
- APPENDF((BUFF_ARGS, "<%s> ", rb_imemo_name(imemo_type(obj))));
-
- switch (imemo_type(obj)) {
- case imemo_ment:
+ break;
+ }
+ case T_IMEMO: {
+ APPEND_F("<%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;
- APPENDF((BUFF_ARGS, ":%s (%s%s%s%s) type:%s alias:%d owner:%p defined_class:%p",
+ APPEND_F(":%s (%s%s%s%s) type:%s aliased:%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",
@@ -13189,14 +14319,16 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
METHOD_ENTRY_CACHED(me) ? ",cc" : "",
METHOD_ENTRY_INVALIDATED(me) ? ",inv" : "",
me->def ? rb_method_type_name(me->def->type) : "NULL",
- me->def ? me->def->alias_count : -1,
+ me->def ? me->def->aliased : -1,
(void *)me->owner, // obj_info(me->owner),
- (void *)me->defined_class)); //obj_info(me->defined_class)));
+ (void *)me->defined_class); //obj_info(me->defined_class)));
if (me->def) {
switch (me->def->type) {
case VM_METHOD_TYPE_ISEQ:
- APPENDF((BUFF_ARGS, " (iseq:%s)", obj_info((VALUE)me->def->body.iseq.iseqptr)));
+ APPEND_S(" (iseq:");
+ rb_raw_obj_info(BUFF_ARGS, (VALUE)me->def->body.iseq.iseqptr);
+ APPEND_S(")");
break;
default:
break;
@@ -13205,19 +14337,19 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
break;
}
- case imemo_iseq: {
- const rb_iseq_t *iseq = (const rb_iseq_t *)obj;
+ case imemo_iseq: {
+ const rb_iseq_t *iseq = (const rb_iseq_t *)obj;
rb_raw_iseq_info(BUFF_ARGS, iseq);
- break;
- }
+ 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)",
+ APPEND_F("(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"));
+ vm_ci_kwarg(ci) ? "available" : "NULL");
break;
}
case imemo_callcache:
@@ -13226,50 +14358,71 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
VALUE class_path = cc->klass ? rb_class_path_cached(cc->klass) : Qnil;
const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
- APPENDF((BUFF_ARGS, "(klass:%s cme:%s%s (%p) call:%p",
+ APPEND_F("(klass:%s cme:%s%s (%p) call:%p",
NIL_P(class_path) ? (cc->klass ? "??" : "<NULL>") : RSTRING_PTR(class_path),
cme ? rb_id2name(cme->called_id) : "<NULL>",
cme ? (METHOD_ENTRY_INVALIDATED(cme) ? " [inv]" : "") : "",
(void *)cme,
- (void *)vm_cc_call(cc)));
+ (void *)vm_cc_call(cc));
break;
}
- default:
- break;
- }
- }
- default:
- break;
- }
-#undef TF
-#undef C
+ default:
+ break;
+ }
+ }
+ default:
+ break;
+ }
}
end:
- if (poisoned) {
- asan_poison_object(obj);
+
+ return pos;
+}
+
+#undef TF
+#undef C
+
+const char *
+rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj)
+{
+ asan_unpoisoning_object(obj) {
+ size_t pos = rb_raw_obj_info_common(buff, buff_size, obj);
+ pos = rb_raw_obj_info_buitin_type(buff, buff_size, obj, pos);
+ if (pos >= buff_size) {} // truncated
}
return buff;
-#undef APPENDF
-#undef BUFF_ARGS
}
+#undef APPEND_S
+#undef APPEND_F
+#undef BUFF_ARGS
+
#if RGENGC_OBJ_INFO
#define OBJ_INFO_BUFFERS_NUM 10
#define OBJ_INFO_BUFFERS_SIZE 0x100
-static int obj_info_buffers_index = 0;
+static rb_atomic_t obj_info_buffers_index = 0;
static char obj_info_buffers[OBJ_INFO_BUFFERS_NUM][OBJ_INFO_BUFFERS_SIZE];
-static const char *
-obj_info(VALUE obj)
+/* Increments *var atomically and resets *var to 0 when maxval is
+ * reached. Returns the wraparound old *var value (0...maxval). */
+static rb_atomic_t
+atomic_inc_wraparound(rb_atomic_t *var, const rb_atomic_t maxval)
{
- const int index = obj_info_buffers_index++;
- char *const buff = &obj_info_buffers[index][0];
-
- if (obj_info_buffers_index >= OBJ_INFO_BUFFERS_NUM) {
- obj_info_buffers_index = 0;
+ rb_atomic_t oldval = RUBY_ATOMIC_FETCH_ADD(*var, 1);
+ if (UNLIKELY(oldval >= maxval - 1)) { // wraparound *var
+ const rb_atomic_t newval = oldval + 1;
+ RUBY_ATOMIC_CAS(*var, newval, newval % maxval);
+ oldval %= maxval;
}
+ return oldval;
+}
+static const char *
+obj_info(VALUE obj)
+{
+ rb_atomic_t index = atomic_inc_wraparound(&obj_info_buffers_index, OBJ_INFO_BUFFERS_NUM);
+ char *const buff = obj_info_buffers[index];
return rb_raw_obj_info(buff, OBJ_INFO_BUFFERS_SIZE, obj);
}
#else
@@ -13330,7 +14483,7 @@ rb_gcdebug_print_obj_condition(VALUE obj)
fprintf(stderr, "WB-protected?: %s\n", RVALUE_WB_UNPROTECTED(obj) ? "false" : "true");
fprintf(stderr, "remembered? : %s\n", RVALUE_REMEMBERED(obj) ? "true" : "false");
- if (is_lazy_sweeping(heap_eden)) {
+ if (is_lazy_sweeping(objspace)) {
fprintf(stderr, "lazy sweeping?: true\n");
fprintf(stderr, "swept?: %s\n", is_swept_object(objspace, obj) ? "done" : "not yet");
}
@@ -13368,7 +14521,7 @@ rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
rb_objspace_t *objspace = &rb_objspace;
if (!stress_to_class) {
- stress_to_class = rb_ary_tmp_new(argc);
+ stress_to_class = rb_ary_hidden_new(argc);
}
rb_ary_cat(stress_to_class, argv, argc);
return self;
@@ -13389,12 +14542,12 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
int i;
if (stress_to_class) {
- for (i = 0; i < argc; ++i) {
- rb_ary_delete_same(stress_to_class, argv[i]);
- }
- if (RARRAY_LEN(stress_to_class) == 0) {
- stress_to_class = 0;
- }
+ for (i = 0; i < argc; ++i) {
+ rb_ary_delete_same(stress_to_class, argv[i]);
+ }
+ if (RARRAY_LEN(stress_to_class) == 0) {
+ stress_to_class = 0;
+ }
}
return Qnil;
}
@@ -13457,6 +14610,22 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
*/
#include "gc.rbinc"
+/*
+ * call-seq:
+ * GC.using_rvargc? -> true or false
+ *
+ * Returns true if using experimental feature Variable Width Allocation, false
+ * otherwise.
+ */
+static VALUE
+gc_using_rvargc_p(VALUE mod)
+{
+#if USE_RVARGC
+ return Qtrue;
+#else
+ return Qfalse;
+#endif
+}
void
Init_GC(void)
@@ -13469,12 +14638,15 @@ Init_GC(void)
rb_mGC = rb_define_module("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("DEBUG")), RBOOL(GC_DEBUG));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE - RVALUE_OVERHEAD));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), SIZET2NUM(RVALUE_OVERHEAD));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(RVALUE)));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_OBJ_LIMIT")), SIZET2NUM(HEAP_PAGE_OBJ_LIMIT));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE));
- rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_PLANES")), SIZET2NUM(HEAP_PAGE_BITMAP_PLANES));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("SIZE_POOL_COUNT")), LONG2FIX(SIZE_POOL_COUNT));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(size_pool_slot_size(SIZE_POOL_COUNT - 1)));
OBJ_FREEZE(gc_constants);
/* internal constants */
rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants);
@@ -13506,23 +14678,23 @@ Init_GC(void)
rb_define_module_function(rb_mObjSpace, "count_objects", count_objects, -1);
{
- VALUE rb_cWeakMap = rb_define_class_under(rb_mObjSpace, "WeakMap", rb_cObject);
- rb_define_alloc_func(rb_cWeakMap, wmap_allocate);
- rb_define_method(rb_cWeakMap, "[]=", wmap_aset, 2);
- rb_define_method(rb_cWeakMap, "[]", wmap_aref, 1);
- rb_define_method(rb_cWeakMap, "include?", wmap_has_key, 1);
- rb_define_method(rb_cWeakMap, "member?", wmap_has_key, 1);
- rb_define_method(rb_cWeakMap, "key?", wmap_has_key, 1);
- rb_define_method(rb_cWeakMap, "inspect", wmap_inspect, 0);
- rb_define_method(rb_cWeakMap, "each", wmap_each, 0);
- rb_define_method(rb_cWeakMap, "each_pair", wmap_each, 0);
- rb_define_method(rb_cWeakMap, "each_key", wmap_each_key, 0);
- rb_define_method(rb_cWeakMap, "each_value", wmap_each_value, 0);
- rb_define_method(rb_cWeakMap, "keys", wmap_keys, 0);
- rb_define_method(rb_cWeakMap, "values", wmap_values, 0);
- rb_define_method(rb_cWeakMap, "size", wmap_size, 0);
- rb_define_method(rb_cWeakMap, "length", wmap_size, 0);
- rb_include_module(rb_cWeakMap, rb_mEnumerable);
+ VALUE rb_cWeakMap = rb_define_class_under(rb_mObjSpace, "WeakMap", rb_cObject);
+ rb_define_alloc_func(rb_cWeakMap, wmap_allocate);
+ rb_define_method(rb_cWeakMap, "[]=", wmap_aset, 2);
+ rb_define_method(rb_cWeakMap, "[]", wmap_aref, 1);
+ rb_define_method(rb_cWeakMap, "include?", wmap_has_key, 1);
+ rb_define_method(rb_cWeakMap, "member?", wmap_has_key, 1);
+ rb_define_method(rb_cWeakMap, "key?", wmap_has_key, 1);
+ rb_define_method(rb_cWeakMap, "inspect", wmap_inspect, 0);
+ rb_define_method(rb_cWeakMap, "each", wmap_each, 0);
+ rb_define_method(rb_cWeakMap, "each_pair", wmap_each, 0);
+ rb_define_method(rb_cWeakMap, "each_key", wmap_each_key, 0);
+ rb_define_method(rb_cWeakMap, "each_value", wmap_each_value, 0);
+ rb_define_method(rb_cWeakMap, "keys", wmap_keys, 0);
+ rb_define_method(rb_cWeakMap, "values", wmap_values, 0);
+ rb_define_method(rb_cWeakMap, "size", wmap_size, 0);
+ rb_define_method(rb_cWeakMap, "length", wmap_size, 0);
+ rb_include_module(rb_cWeakMap, rb_mEnumerable);
}
/* internal methods */
@@ -13533,30 +14705,48 @@ Init_GC(void)
rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
#endif
+ rb_define_singleton_method(rb_mGC, "using_rvargc?", gc_using_rvargc_p, 0);
+
+ if (GC_COMPACTION_SUPPORTED) {
+ rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
+ }
+ else {
+ rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
+ /* When !GC_COMPACTION_SUPPORTED, this method is not defined in gc.rb */
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
+ }
+
#if GC_DEBUG_STRESS_TO_CLASS
rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
rb_define_singleton_method(rb_mGC, "remove_stress_to_class", rb_gcdebug_remove_stress_to_class, -1);
#endif
{
- VALUE opts;
- /* GC build options */
- rb_define_const(rb_mGC, "OPTS", opts = rb_ary_new());
+ VALUE opts;
+ /* \GC build options */
+ rb_define_const(rb_mGC, "OPTS", opts = rb_ary_new());
#define OPT(o) if (o) rb_ary_push(opts, rb_fstring_lit(#o))
- OPT(GC_DEBUG);
- OPT(USE_RGENGC);
- OPT(RGENGC_DEBUG);
- OPT(RGENGC_CHECK_MODE);
- OPT(RGENGC_PROFILE);
- OPT(RGENGC_ESTIMATE_OLDMALLOC);
- OPT(GC_PROFILE_MORE_DETAIL);
- OPT(GC_ENABLE_LAZY_SWEEP);
- OPT(CALC_EXACT_MALLOC_SIZE);
- OPT(MALLOC_ALLOCATED_SIZE);
- OPT(MALLOC_ALLOCATED_SIZE_CHECK);
- OPT(GC_PROFILE_DETAIL_MEMORY);
+ OPT(GC_DEBUG);
+ OPT(USE_RGENGC);
+ OPT(RGENGC_DEBUG);
+ OPT(RGENGC_CHECK_MODE);
+ OPT(RGENGC_PROFILE);
+ OPT(RGENGC_ESTIMATE_OLDMALLOC);
+ OPT(GC_PROFILE_MORE_DETAIL);
+ OPT(GC_ENABLE_LAZY_SWEEP);
+ OPT(CALC_EXACT_MALLOC_SIZE);
+ OPT(MALLOC_ALLOCATED_SIZE);
+ OPT(MALLOC_ALLOCATED_SIZE_CHECK);
+ OPT(GC_PROFILE_DETAIL_MEMORY);
+ OPT(GC_COMPACTION_SUPPORTED);
#undef OPT
- OBJ_FREEZE(opts);
+ OBJ_FREEZE(opts);
}
}
diff --git a/gc.h b/gc.h
index 5d113cafce..23218c1a9e 100644
--- a/gc.h
+++ b/gc.h
@@ -6,8 +6,12 @@
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p)))
#elif defined(__i386) && defined(__GNUC__)
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movl\t%%esp, %0" : "=r" (*(p)))
-#elif defined(__powerpc64__) && defined(__GNUC__)
+#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && !defined(_AIX) && !defined(__APPLE__) // Not Apple is NEEDED to unbreak ppc64 build on Darwin. Don't ask.
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr\t%0, %%r1" : "=r" (*(p)))
+#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && defined(_AIX)
+#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr %0,1" : "=r" (*(p)))
+#elif defined(__POWERPC__) && defined(__APPLE__) // Darwin ppc and ppc64
+#define SET_MACHINE_STACK_END(p) __asm__ volatile("mr %0, r1" : "=r" (*(p)))
#elif defined(__aarch64__) && defined(__GNUC__)
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mov\t%0, sp" : "=r" (*(p)))
#else
@@ -18,9 +22,9 @@ NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p));
#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); \
+ FLUSH_REGISTER_WINDOWS; \
+ setjmp((th)->ec->machine.regs); \
+ SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \
} while (0)
/* for GC debug */
@@ -35,20 +39,20 @@ extern int ruby_gc_debug_indent;
static inline void
rb_gc_debug_indent(void)
{
- printf("%*s", ruby_gc_debug_indent, "");
+ ruby_debug_printf("%*s", ruby_gc_debug_indent, "");
}
static inline void
rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
{
if (st == 0) {
- ruby_gc_debug_indent--;
+ ruby_gc_debug_indent--;
}
rb_gc_debug_indent();
- printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr);
+ ruby_debug_printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr);
if (st) {
- ruby_gc_debug_indent++;
+ ruby_gc_debug_indent++;
}
fflush(stdout);
@@ -58,7 +62,7 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
#define RUBY_MARK_LEAVE(msg) rb_gc_debug_body("mark", (msg), 0, ptr)
#define RUBY_FREE_ENTER(msg) rb_gc_debug_body("free", (msg), 1, ptr)
#define RUBY_FREE_LEAVE(msg) rb_gc_debug_body("free", (msg), 0, ptr)
-#define RUBY_GC_INFO rb_gc_debug_indent(); printf
+#define RUBY_GC_INFO rb_gc_debug_indent(), ruby_debug_printf
#else
#define RUBY_MARK_ENTER(msg)
@@ -86,9 +90,9 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
RUBY_EXTERN int ruby_stack_grow_direction;
int ruby_get_stack_grow_direction(volatile VALUE *addr);
# define stack_growup_p(x) ( \
- (ruby_stack_grow_direction ? \
- ruby_stack_grow_direction : \
- ruby_get_stack_grow_direction(x)) > 0)
+ (ruby_stack_grow_direction ? \
+ ruby_stack_grow_direction : \
+ ruby_get_stack_grow_direction(x)) > 0)
# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? (a) : (b))
#endif
@@ -110,12 +114,12 @@ int ruby_get_stack_grow_direction(volatile VALUE *addr);
#define IS_STACK_DIR_UPPER() STACK_DIR_UPPER(1,0)
const char *rb_obj_info(VALUE obj);
-const char *rb_raw_obj_info(char *buff, const int buff_size, VALUE obj);
-
-VALUE rb_gc_disable_no_rest(void);
+const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
struct rb_thread_struct;
+size_t rb_size_pool_slot_size(unsigned char pool_id);
+
RUBY_SYMBOL_EXPORT_BEGIN
/* exports for objspace module */
@@ -125,7 +129,6 @@ void rb_objspace_reachable_objects_from_root(void (func)(const char *category, V
int rb_objspace_markable_object_p(VALUE obj);
int rb_objspace_internal_object_p(VALUE obj);
int rb_objspace_marked_object_p(VALUE obj);
-int rb_objspace_garbage_object_p(VALUE obj);
void rb_objspace_each_objects(
int (*callback)(void *start, void *end, size_t stride, void *data),
@@ -135,6 +138,10 @@ void rb_objspace_each_objects_without_setup(
int (*callback)(void *, void *, size_t, void *),
void *data);
+size_t rb_gc_obj_slot_size(VALUE obj);
+
+VALUE rb_gc_disable_no_rest(void);
+
RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_GC_H */
diff --git a/gc.rb b/gc.rb
index 8a00b406ce..57aeeb9131 100644
--- a/gc.rb
+++ b/gc.rb
@@ -6,7 +6,7 @@
# Some of the underlying methods are also available via the ObjectSpace
# module.
#
-# You may obtain information about the operation of the GC through
+# You may obtain information about the operation of the \GC through
# GC::Profiler.
module GC
@@ -24,7 +24,7 @@ module GC
#
# def GC.start(full_mark: true, immediate_sweep: true); end
#
- # Use full_mark: false to perform a minor GC.
+ # Use full_mark: false to perform a minor \GC.
# Use immediate_sweep: false to defer sweeping (use lazy sweep).
#
# Note: These keyword arguments are implementation and version dependent. They
@@ -39,27 +39,6 @@ module GC
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:
# GC.enable -> true or false
#
# Enables garbage collection, returning +true+ if garbage
@@ -88,7 +67,7 @@ module GC
# call-seq:
# GC.stress -> integer, true or false
#
- # Returns current status of GC stress mode.
+ # Returns current status of \GC stress mode.
def self.stress
Primitive.gc_stress_get
end
@@ -96,9 +75,9 @@ module GC
# call-seq:
# GC.stress = flag -> flag
#
- # Updates the GC stress mode.
+ # Updates the \GC stress mode.
#
- # When stress mode is enabled, the GC is invoked at every GC opportunity:
+ # When stress mode is enabled, the \GC is invoked at every \GC opportunity:
# all memory and object allocations.
#
# Enabling stress mode will degrade performance, it is only for debugging.
@@ -114,68 +93,137 @@ module GC
# call-seq:
# GC.count -> Integer
#
- # The number of times GC occurred.
+ # The number of times \GC occurred.
#
- # It returns the number of times GC occurred since the process started.
+ # It returns the number of times \GC occurred since the process started.
def self.count
Primitive.gc_count
end
# call-seq:
# GC.stat -> Hash
- # GC.stat(hash) -> hash
+ # GC.stat(hash) -> Hash
# GC.stat(:key) -> Numeric
#
- # Returns a Hash containing information about the GC.
- #
- # The hash includes information about internal statistics about GC such as:
- #
- # {
- # :count=>0,
- # :heap_allocated_pages=>24,
- # :heap_sorted_length=>24,
- # :heap_allocatable_pages=>0,
- # :heap_available_slots=>9783,
- # :heap_live_slots=>7713,
- # :heap_free_slots=>2070,
- # :heap_final_slots=>0,
- # :heap_marked_slots=>0,
- # :heap_eden_pages=>24,
- # :heap_tomb_pages=>0,
- # :total_allocated_pages=>24,
- # :total_freed_pages=>0,
- # :total_allocated_objects=>7796,
- # :total_freed_objects=>83,
- # :malloc_increase_bytes=>2389312,
- # :malloc_increase_bytes_limit=>16777216,
- # :minor_gc_count=>0,
- # :major_gc_count=>0,
- # :remembered_wb_unprotected_objects=>0,
- # :remembered_wb_unprotected_objects_limit=>0,
- # :old_objects=>0,
- # :old_objects_limit=>0,
- # :oldmalloc_increase_bytes=>2389760,
- # :oldmalloc_increase_bytes_limit=>16777216
- # }
- #
- # The contents of the hash are implementation specific and may be changed in
- # the future.
+ # Returns a Hash containing information about the \GC.
+ #
+ # The contents of the hash are implementation specific and may change in
+ # the future without notice.
+ #
+ # The hash includes information about internal statistics about \GC such as:
+ #
+ # [count]
+ # The total number of garbage collections ran since application start
+ # (count includes both minor and major garbage collections)
+ # [time]
+ # The total time spent in garbage collections (in milliseconds)
+ # [heap_allocated_pages]
+ # The total number of `:heap_eden_pages` + `:heap_tomb_pages`
+ # [heap_sorted_length]
+ # The number of pages that can fit into the buffer that holds references to
+ # all pages
+ # [heap_allocatable_pages]
+ # The total number of pages the application could allocate without additional \GC
+ # [heap_available_slots]
+ # The total number of slots in all `:heap_allocated_pages`
+ # [heap_live_slots]
+ # The total number of slots which contain live objects
+ # [heap_free_slots]
+ # The total number of slots which do not contain live objects
+ # [heap_final_slots]
+ # The total number of slots with pending finalizers to be run
+ # [heap_marked_slots]
+ # The total number of objects marked in the last \GC
+ # [heap_eden_pages]
+ # The total number of pages which contain at least one live slot
+ # [heap_tomb_pages]
+ # The total number of pages which do not contain any live slots
+ # [total_allocated_pages]
+ # The cumulative number of pages allocated since application start
+ # [total_freed_pages]
+ # The cumulative number of pages freed since application start
+ # [total_allocated_objects]
+ # The cumulative number of objects allocated since application start
+ # [total_freed_objects]
+ # The cumulative number of objects freed since application start
+ # [malloc_increase_bytes]
+ # Amount of memory allocated on the heap for objects. Decreased by any \GC
+ # [malloc_increase_bytes_limit]
+ # When `:malloc_increase_bytes` crosses this limit, \GC is triggered
+ # [minor_gc_count]
+ # The total number of minor garbage collections run since process start
+ # [major_gc_count]
+ # The total number of major garbage collections run since process start
+ # [compact_count]
+ # The total number of compactions run since process start
+ # [read_barrier_faults]
+ # The total number of times the read barrier was triggered during
+ # compaction
+ # [total_moved_objects]
+ # The total number of objects compaction has moved
+ # [remembered_wb_unprotected_objects]
+ # The total number of objects without write barriers
+ # [remembered_wb_unprotected_objects_limit]
+ # When `:remembered_wb_unprotected_objects` crosses this limit,
+ # major \GC is triggered
+ # [old_objects]
+ # Number of live, old objects which have survived at least 3 garbage collections
+ # [old_objects_limit]
+ # When `:old_objects` crosses this limit, major \GC is triggered
+ # [oldmalloc_increase_bytes]
+ # Amount of memory allocated on the heap for objects. Decreased by major \GC
+ # [oldmalloc_increase_bytes_limit]
+ # When `:old_malloc_increase_bytes` crosses this limit, major \GC is triggered
#
# If the optional argument, hash, is given,
# it is overwritten and returned.
# This is intended to avoid probe effect.
#
- # This method is only expected to work on C Ruby.
+ # This method is only expected to work on CRuby.
def self.stat hash_or_key = nil
Primitive.gc_stat hash_or_key
end
- # call-seq:
- # GC.latest_gc_info -> {:gc_by=>:newobj}
+ # call-seq:
+ # GC.stat_heap -> Hash
+ # GC.stat_heap(nil, hash) -> Hash
+ # GC.stat_heap(heap_name) -> Hash
+ # GC.stat_heap(heap_name, hash) -> Hash
+ # GC.stat_heap(heap_name, :key) -> Numeric
+ #
+ # Returns information for memory pools in the \GC.
+ #
+ # If the first optional argument, +heap_name+, is passed in and not +nil+, it
+ # returns a +Hash+ containing information about the particular memory pool.
+ # Otherwise, it will return a +Hash+ with memory pool names as keys and
+ # a +Hash+ containing information about the memory pool as values.
+ #
+ # If the second optional argument, +hash_or_key+, is given as +Hash+, it will
+ # be overwritten and returned. This is intended to avoid the probe effect.
+ #
+ # If both optional arguments are passed in and the second optional argument is
+ # a symbol, it will return a +Numeric+ of the value for the particular memory
+ # pool.
+ #
+ # On CRuby, +heap_name+ is of the type +Integer+ but may be of type +String+
+ # on other implementations.
+ #
+ # The contents of the hash are implementation specific and may change in
+ # the future without notice.
+ #
+ # If the optional argument, hash, is given, it is overwritten and returned.
+ #
+ # This method is only expected to work on CRuby.
+ def self.stat_heap heap_name = nil, hash_or_key = nil
+ Primitive.gc_stat_heap heap_name, hash_or_key
+ end
+
+ # call-seq:
+ # GC.latest_gc_info -> hash
# GC.latest_gc_info(hash) -> hash
# GC.latest_gc_info(:major_by) -> :malloc
#
- # Returns information about the most recent garbage collection.
+ # Returns information about the most recent garbage collection.
#
# If the optional argument, hash, is given,
# it is overwritten and returned.
@@ -184,51 +232,58 @@ module GC
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
+ if respond_to?(:compact)
+ # call-seq:
+ # GC.verify_compaction_references(toward: nil, double_heap: false) -> hash
+ #
+ # Verify compaction reference consistency.
+ #
+ # This method is implementation specific. During compaction, objects that
+ # were moved are replaced with T_MOVED objects. No object should have a
+ # reference to a T_MOVED object after compaction.
+ #
+ # This function expands the heap to ensure room to move all objects,
+ # compacts the heap to make sure everything moves, updates all references,
+ # then performs a full \GC. If any object contains a reference to a T_MOVED
+ # object, that object should be pushed on the mark stack, and will
+ # make a SEGV.
+ def self.verify_compaction_references(toward: nil, double_heap: false, expand_heap: false)
+ Primitive.gc_verify_compaction_references(double_heap, expand_heap, toward == :empty)
+ end
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
- Primitive.gc_compact
+ # call-seq:
+ # GC.measure_total_time = true/false
+ #
+ # Enable to measure \GC time.
+ # You can get the result with <tt>GC.stat(:time)</tt>.
+ # Note that \GC time measurement can cause some performance overhead.
+ def self.measure_total_time=(flag)
+ Primitive.cstmt! %{
+ rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE;
+ return flag;
+ }
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.
+ # GC.measure_total_time -> true/false
+ #
+ # Return measure_total_time flag (default: +true+).
+ # Note that measurement can affect the application performance.
+ def self.measure_total_time
+ Primitive.cexpr! %{
+ RBOOL(rb_objspace.flags.measure_gc)
+ }
+ end
+
+ # call-seq:
+ # GC.total_time -> int
#
- # 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)
+ # Return measured \GC total time in nano seconds.
+ def self.total_time
+ Primitive.cexpr! %{
+ ULL2NUM(rb_objspace.profile.total_time_ns)
+ }
end
end
diff --git a/gem_prelude.rb b/gem_prelude.rb
index f60ea46eea..f382021ca3 100644
--- a/gem_prelude.rb
+++ b/gem_prelude.rb
@@ -1,6 +1,8 @@
begin
require 'rubygems'
-rescue LoadError
+rescue LoadError => e
+ raise unless e.path == 'rubygems'
+
warn "`RubyGems' were not loaded."
end if defined?(Gem)
@@ -15,3 +17,10 @@ begin
rescue LoadError
warn "`did_you_mean' was not loaded."
end if defined?(DidYouMean)
+
+begin
+ require 'syntax_suggest/core_ext'
+rescue LoadError
+ warn "`syntax_suggest' was not loaded."
+end if defined?(SyntaxSuggest)
+
diff --git a/gems/bundled_gems b/gems/bundled_gems
index 0def51fbad..d37d869d41 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -1,15 +1,16 @@
# gem-name version-to-bundle repository-url [optional-commit-hash-to-test-or-defaults-to-v-version]
-minitest 5.14.4 https://github.com/seattlerb/minitest
-power_assert 2.0.0 https://github.com/ruby/power_assert
-rake 13.0.6 https://github.com/ruby/rake
-test-unit 3.4.4 https://github.com/test-unit/test-unit 3.4.4
-rexml 3.2.5 https://github.com/ruby/rexml
-rss 0.2.9 https://github.com/ruby/rss 0.2.9
-net-ftp 0.1.3 https://github.com/ruby/net-ftp
-net-imap 0.2.2 https://github.com/ruby/net-imap
-net-pop 0.1.1 https://github.com/ruby/net-pop
-net-smtp 0.2.1 https://github.com/ruby/net-smtp
-matrix 0.4.2 https://github.com/ruby/matrix
-prime 0.1.2 https://github.com/ruby/prime
-typeprof 0.15.0 https://github.com/ruby/typeprof
-rbs 1.3.3 https://github.com/ruby/rbs
+minitest 5.25.1 https://github.com/seattlerb/minitest
+power_assert 2.0.3 https://github.com/ruby/power_assert
+rake 13.0.6 https://github.com/ruby/rake
+test-unit 3.5.7 https://github.com/test-unit/test-unit
+rexml 3.3.9 https://github.com/ruby/rexml
+rss 0.3.1 https://github.com/ruby/rss
+net-ftp 0.2.1 https://github.com/ruby/net-ftp
+net-imap 0.3.9 https://github.com/ruby/net-imap
+net-pop 0.1.2 https://github.com/ruby/net-pop
+net-smtp 0.3.4 https://github.com/ruby/net-smtp
+matrix 0.4.2 https://github.com/ruby/matrix
+prime 0.1.2 https://github.com/ruby/prime
+rbs 2.8.2 https://github.com/ruby/rbs
+typeprof 0.21.3 https://github.com/ruby/typeprof
+debug 1.7.1 https://github.com/ruby/debug
diff --git a/gems/lib/core_assertions.rb b/gems/lib/core_assertions.rb
new file mode 100644
index 0000000000..7334063885
--- /dev/null
+++ b/gems/lib/core_assertions.rb
@@ -0,0 +1 @@
+require_relative "../../tool/lib/core_assertions.rb"
diff --git a/gems/lib/envutil.rb b/gems/lib/envutil.rb
new file mode 100644
index 0000000000..d684c22cf2
--- /dev/null
+++ b/gems/lib/envutil.rb
@@ -0,0 +1 @@
+require_relative "../../tool/lib/envutil.rb"
diff --git a/gems/lib/rake/extensiontask.rb b/gems/lib/rake/extensiontask.rb
new file mode 100644
index 0000000000..fdbe8d8874
--- /dev/null
+++ b/gems/lib/rake/extensiontask.rb
@@ -0,0 +1,12 @@
+require "rake/tasklib" unless defined?(Rake::TaskLib)
+
+module Rake
+ class ExtensionTask < TaskLib
+ def initialize(...)
+ task :compile do |args|
+ puts "Dummy `compile` task defined in #{__FILE__}"
+ puts "#{args.name} => #{args.prereqs.join(' ')}"
+ end
+ end
+ end
+end
diff --git a/goruby.c b/goruby.c
index c90fc97b0a..5d45277207 100644
--- a/goruby.c
+++ b/goruby.c
@@ -37,21 +37,21 @@ goruby_options(int argc, char **argv)
void *ret;
if ((isatty(0) && isatty(1) && isatty(2)) && (pipe(rw) == 0)) {
- ssize_t n;
- infd = dup(0);
- if (infd < 0) {
- close(rw[0]);
- close(rw[1]);
- goto no_irb;
- }
- dup2(rw[0], 0);
- close(rw[0]);
- n = write(rw[1], cmd, sizeof(cmd) - 1);
- close(rw[1]);
- ret = n > 0 ? ruby_options(argc, argv) : NULL;
- dup2(infd, 0);
- close(infd);
- return ret;
+ ssize_t n;
+ infd = dup(0);
+ if (infd < 0) {
+ close(rw[0]);
+ close(rw[1]);
+ goto no_irb;
+ }
+ dup2(rw[0], 0);
+ close(rw[0]);
+ n = write(rw[1], cmd, sizeof(cmd) - 1);
+ close(rw[1]);
+ ret = n > 0 ? ruby_options(argc, argv) : NULL;
+ dup2(infd, 0);
+ close(infd);
+ return ret;
}
no_irb:
return ruby_options(argc, argv);
@@ -62,7 +62,7 @@ goruby_run_node(void *arg)
{
int state;
if (NIL_P(rb_protect(init_golf, Qtrue, &state))) {
- return state == EXIT_SUCCESS ? EXIT_FAILURE : state;
+ return state == EXIT_SUCCESS ? EXIT_FAILURE : state;
}
return ruby_run_node(arg);
}
diff --git a/hash.c b/hash.c
index 6208ab9e2c..d2dce30624 100644
--- a/hash.c
+++ b/hash.c
@@ -28,6 +28,7 @@
#include "internal.h"
#include "internal/array.h"
#include "internal/bignum.h"
+#include "internal/basic_operators.h"
#include "internal/class.h"
#include "internal/cont.h"
#include "internal/error.h"
@@ -35,6 +36,7 @@
#include "internal/object.h"
#include "internal/proc.h"
#include "internal/symbol.h"
+#include "internal/thread.h"
#include "internal/time.h"
#include "internal/vm.h"
#include "probes.h"
@@ -43,6 +45,9 @@
#include "ruby_assert.h"
#include "symbol.h"
#include "transient_heap.h"
+#include "ruby/thread_native.h"
+#include "ruby/ractor.h"
+#include "vm_sync.h"
#ifndef HASH_DEBUG
#define HASH_DEBUG 0
@@ -52,11 +57,6 @@
#include "gc.h"
#endif
-#define HAS_EXTRA_STATES(hash, klass) ( \
- ((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \
- FL_TEST((hash), FL_EXIVAR|RHASH_PROC_DEFAULT) || \
- !NIL_P(RHASH_IFNONE(hash)))
-
#define SET_DEFAULT(hash, ifnone) ( \
FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
RHASH_SET_IFNONE(hash, ifnone))
@@ -73,18 +73,6 @@ copy_default(struct RHash *hash, const struct RHash *hash2)
RHASH_SET_IFNONE(hash, RHASH_IFNONE((VALUE)hash2));
}
-static VALUE
-has_extra_methods(VALUE klass)
-{
- const VALUE base = rb_cHash;
- VALUE c = klass;
- while (c != base) {
- if (rb_class_has_methods(c)) return klass;
- c = RCLASS_SUPER(c);
- }
- return 0;
-}
-
static VALUE rb_hash_s_try_convert(VALUE, VALUE);
/*
@@ -106,9 +94,11 @@ rb_hash_freeze(VALUE hash)
VALUE rb_cHash;
static VALUE envtbl;
-static ID id_hash, id_default, id_flatten_bang;
+static ID id_hash, id_flatten_bang;
static ID id_hash_iter_lev;
+#define id_default idDefault
+
VALUE
rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
{
@@ -121,12 +111,12 @@ rb_any_cmp(VALUE a, VALUE b)
{
if (a == b) return 0;
if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString &&
- RB_TYPE_P(b, T_STRING) && RBASIC(b)->klass == rb_cString) {
- return rb_str_hash_cmp(a, b);
+ RB_TYPE_P(b, T_STRING) && RBASIC(b)->klass == rb_cString) {
+ return rb_str_hash_cmp(a, b);
}
- if (a == Qundef || b == Qundef) return -1;
+ if (UNDEF_P(a) || UNDEF_P(b)) return -1;
if (SYMBOL_P(a) && SYMBOL_P(b)) {
- return a != b;
+ return a != b;
}
return !rb_eql(a, b);
@@ -139,33 +129,6 @@ hash_recursive(VALUE obj, VALUE arg, int recurse)
return rb_funcallv(obj, id_hash, 0, 0);
}
-VALUE
-rb_hash(VALUE obj)
-{
- VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
-
- if (hval == Qundef) {
- hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
- }
-
- while (!FIXNUM_P(hval)) {
- if (RB_TYPE_P(hval, T_BIGNUM)) {
- int sign;
- unsigned long ul;
- sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0,
- INTEGER_PACK_NATIVE_BYTE_ORDER);
- if (sign < 0) {
- hval = LONG2FIX(ul | FIXNUM_MIN);
- }
- else {
- hval = LONG2FIX(ul & FIXNUM_MAX);
- }
- }
- hval = rb_to_int(hval);
- }
- return hval;
-}
-
static long rb_objid_hash(st_index_t index);
static st_index_t
@@ -196,7 +159,7 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
switch (TYPE(a)) {
case T_SYMBOL:
- if (STATIC_SYM_P(a)) {
+ if (STATIC_SYM_P(a)) {
hnum = a >> (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
hnum = rb_hash_start(hnum);
}
@@ -208,41 +171,69 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
case T_TRUE:
case T_FALSE:
case T_NIL:
- hnum = rb_objid_hash((st_index_t)a);
+ hnum = rb_objid_hash((st_index_t)a);
break;
case T_STRING:
- hnum = rb_str_hash(a);
+ hnum = rb_str_hash(a);
break;
case T_BIGNUM:
- hval = rb_big_hash(a);
- hnum = FIX2LONG(hval);
+ hval = rb_big_hash(a);
+ hnum = FIX2LONG(hval);
break;
case T_FLOAT: /* prevent pathological behavior: [Bug #10761] */
- hnum = rb_dbl_long_hash(rb_float_value(a));
+ hnum = rb_dbl_long_hash(rb_float_value(a));
break;
default:
- hnum = other_func(a);
+ hnum = other_func(a);
}
if ((SIGNED_VALUE)hnum > 0)
- hnum &= FIXNUM_MAX;
+ hnum &= FIXNUM_MAX;
else
- hnum |= FIXNUM_MIN;
+ hnum |= FIXNUM_MIN;
return (long)hnum;
}
static st_index_t
obj_any_hash(VALUE obj)
{
- obj = rb_hash(obj);
- return FIX2LONG(obj);
+ VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
+
+ if (UNDEF_P(hval)) {
+ hval = rb_exec_recursive_outer_mid(hash_recursive, obj, 0, id_hash);
+ }
+
+ while (!FIXNUM_P(hval)) {
+ if (RB_TYPE_P(hval, T_BIGNUM)) {
+ int sign;
+ unsigned long ul;
+ sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0,
+ INTEGER_PACK_NATIVE_BYTE_ORDER);
+ if (sign < 0) {
+ hval = LONG2FIX(ul | FIXNUM_MIN);
+ }
+ else {
+ hval = LONG2FIX(ul & FIXNUM_MAX);
+ }
+ }
+ hval = rb_to_int(hval);
+ }
+
+ return FIX2LONG(hval);
}
-static st_index_t
+st_index_t
rb_any_hash(VALUE a)
{
return any_hash(a, obj_any_hash);
}
+VALUE
+rb_hash(VALUE obj)
+{
+ return LONG2FIX(any_hash(obj, obj_any_hash));
+}
+
+
/* Here is a hash function for 64-bit key. It is about 5 times faster
(2 times faster when uint128 type is absent) on Haswell than
tailored Spooky or City hash function can be. */
@@ -316,6 +307,19 @@ objid_hash(VALUE obj)
*
* Certain core classes such as Integer use built-in hash calculations and
* do not call the #hash method when used as a hash key.
+ *
+ * When implementing your own #hash based on multiple values, the best
+ * practice is to combine the class and any values using the hash code of an
+ * array:
+ *
+ * For example:
+ *
+ * def hash
+ * [self.class, a, b, c].hash
+ * end
+ *
+ * The reason for this is that the Array#hash method already has logic for
+ * safely and efficiently combining multiple hash values.
*--
* \private
*++
@@ -357,6 +361,9 @@ const struct st_hash_type rb_hashtype_ident = {
rb_ident_hash,
};
+#define RHASH_IDENTHASH_P(hash) (RHASH_TYPE(hash) == &identhash)
+#define RHASH_STRING_KEY_P(hash, key) (!RHASH_IDENTHASH_P(hash) && (rb_obj_class(key) == rb_cString))
+
typedef st_index_t st_hash_t;
/*
@@ -436,7 +443,7 @@ ar_cleared_entry(VALUE hash, unsigned int index)
* so you need to check key == Qundef
*/
ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
- return pair->key == Qundef;
+ return UNDEF_P(pair->key);
}
else {
return FALSE;
@@ -516,8 +523,8 @@ hash_verify_(VALUE hash, const char *file, int line)
ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
k = pair->key;
v = pair->val;
- HASH_ASSERT(k != Qundef);
- HASH_ASSERT(v != Qundef);
+ HASH_ASSERT(!UNDEF_P(k));
+ HASH_ASSERT(!UNDEF_P(v));
n++;
}
}
@@ -763,31 +770,39 @@ ar_free_and_clear_table(VALUE hash)
HASH_ASSERT(RHASH_TRANSIENT_P(hash) == 0);
}
-static void
-ar_try_convert_table(VALUE hash)
-{
- if (!RHASH_AR_TABLE_P(hash)) return;
-
- const unsigned size = RHASH_AR_TABLE_SIZE(hash);
+void rb_st_add_direct_with_hash(st_table *tab, st_data_t key, st_data_t value, st_hash_t hash); // st.c
- st_table *new_tab;
- st_index_t i;
+enum ar_each_key_type {
+ ar_each_key_copy,
+ ar_each_key_cmp,
+ ar_each_key_insert,
+};
- if (size < RHASH_AR_TABLE_MAX_SIZE) {
- return;
+static inline int
+ar_each_key(ar_table *ar, int max, enum ar_each_key_type type, st_data_t *dst_keys, st_table *new_tab, st_hash_t *hashes)
+{
+ for (int i = 0; i < max; i++) {
+ ar_table_pair *pair = &ar->pairs[i];
+
+ switch (type) {
+ case ar_each_key_copy:
+ dst_keys[i] = pair->key;
+ break;
+ case ar_each_key_cmp:
+ if (dst_keys[i] != pair->key) return 1;
+ break;
+ case ar_each_key_insert:
+ if (UNDEF_P(pair->key)) continue; // deleted entry
+ rb_st_add_direct_with_hash(new_tab, pair->key, pair->val, hashes[i]);
+ break;
+ }
}
- new_tab = st_init_table_with_size(&objhash, size * 2);
-
- for (i = 0; i < RHASH_AR_TABLE_MAX_BOUND; i++) {
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- st_add_direct(new_tab, pair->key, pair->val);
- }
- ar_free_and_clear_table(hash);
- RHASH_ST_TABLE_SET(hash, new_tab);
- return;
+ return 0;
}
+
+
static st_table *
ar_force_convert_table(VALUE hash, const char *file, int line)
{
@@ -798,22 +813,32 @@ ar_force_convert_table(VALUE hash, const char *file, int line)
}
if (RHASH_AR_TABLE(hash)) {
- unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
-
-#if defined(RHASH_CONVERT_TABLE_DEBUG) && RHASH_CONVERT_TABLE_DEBUG
- rb_obj_info_dump(hash);
- fprintf(stderr, "force_convert: %s:%d\n", file, line);
- RB_DEBUG_COUNTER_INC(obj_hash_force_convert);
-#endif
+ ar_table *ar = RHASH_AR_TABLE(hash);
+ st_hash_t hashes[RHASH_AR_TABLE_MAX_SIZE];
+ unsigned int bound, size;
+
+ // prepare hash values
+ do {
+ st_data_t keys[RHASH_AR_TABLE_MAX_SIZE];
+ bound = RHASH_AR_TABLE_BOUND(hash);
+ size = RHASH_AR_TABLE_SIZE(hash);
+ ar_each_key(ar, bound, ar_each_key_copy, keys, NULL, NULL);
+
+ for (unsigned int i = 0; i < bound; i++) {
+ // do_hash calls #hash method and it can modify hash object
+ hashes[i] = UNDEF_P(keys[i]) ? 0 : ar_do_hash(keys[i]);
+ }
- new_tab = st_init_table_with_size(&objhash, RHASH_AR_TABLE_SIZE(hash));
+ // check if modified
+ if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) return RHASH_ST_TABLE(hash);
+ if (UNLIKELY(RHASH_AR_TABLE_BOUND(hash) != bound)) continue;
+ if (UNLIKELY(ar_each_key(ar, bound, ar_each_key_cmp, keys, NULL, NULL))) continue;
+ } while (0);
- for (i = 0; i < bound; i++) {
- if (ar_cleared_entry(hash, i)) continue;
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- st_add_direct(new_tab, pair->key, pair->val);
- }
+ // make st
+ new_tab = st_init_table_with_size(&objhash, size);
+ ar_each_key(ar, bound, ar_each_key_insert, NULL, new_tab, hashes);
ar_free_and_clear_table(hash);
}
else {
@@ -962,7 +987,7 @@ ar_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
static int
ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg,
- st_data_t never)
+ st_data_t never)
{
if (RHASH_AR_TABLE_SIZE(hash) > 0) {
unsigned i, ret = 0, bound = RHASH_AR_TABLE_BOUND(hash);
@@ -983,13 +1008,13 @@ ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg
switch (retval) {
case ST_CHECK: {
- pair = RHASH_AR_TABLE_REF(hash, i);
- if (pair->key == never) break;
- ret = ar_find_entry_hint(hash, hint, key);
- if (ret == RHASH_AR_TABLE_MAX_BOUND) {
- retval = (*func)(0, 0, arg, 1);
- return 2;
- }
+ pair = RHASH_AR_TABLE_REF(hash, i);
+ if (pair->key == never) break;
+ ret = ar_find_entry_hint(hash, hint, key);
+ if (ret == RHASH_AR_TABLE_MAX_BOUND) {
+ retval = (*func)(0, 0, arg, 1);
+ return 2;
+ }
}
case ST_CONTINUE:
break;
@@ -997,11 +1022,11 @@ ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg
case ST_REPLACE:
return 0;
case ST_DELETE: {
- if (!ar_cleared_entry(hash, i)) {
- ar_clear_entry(hash, i);
- RHASH_AR_TABLE_SIZE_DEC(hash);
- }
- break;
+ if (!ar_cleared_entry(hash, i)) {
+ ar_clear_entry(hash, i);
+ RHASH_AR_TABLE_SIZE_DEC(hash);
+ }
+ break;
}
}
}
@@ -1283,7 +1308,6 @@ rb_hash_transient_heap_evacuate(VALUE hash, int promote)
ar_table *old_tab = RHASH_AR_TABLE(hash);
if (UNLIKELY(old_tab == NULL)) {
- rb_gc_force_recycle(hash);
return;
}
HASH_ASSERT(old_tab != NULL);
@@ -1319,7 +1343,7 @@ foreach_safe_i(st_data_t key, st_data_t value, st_data_t args, int error)
if (error) return ST_STOP;
status = (*arg->func)(key, value, arg->arg);
if (status == ST_CONTINUE) {
- return ST_CHECK;
+ return ST_CHECK;
}
return status;
}
@@ -1333,7 +1357,7 @@ st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
arg.func = (st_foreach_func *)func;
arg.arg = a;
if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ rb_raise(rb_eRuntimeError, "hash modified during iteration");
}
}
@@ -1346,15 +1370,8 @@ struct hash_foreach_arg {
};
static int
-hash_ar_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
+hash_iter_status_check(int status)
{
- struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
- int status;
-
- if (error) return ST_STOP;
- status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
- /* TODO: rehash check? rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); */
-
switch (status) {
case ST_DELETE:
return ST_DELETE;
@@ -1363,31 +1380,38 @@ hash_ar_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
case ST_STOP:
return ST_STOP;
}
+
return ST_CHECK;
}
static int
+hash_ar_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
+
+ if (error) return ST_STOP;
+
+ int status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
+ /* TODO: rehash check? rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); */
+
+ return hash_iter_status_check(status);
+}
+
+static int
hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
{
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
- int status;
- st_table *tbl;
if (error) return ST_STOP;
- tbl = RHASH_ST_TABLE(arg->hash);
- status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
+
+ st_table *tbl = RHASH_ST_TABLE(arg->hash);
+ int status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
+
if (RHASH_ST_TABLE(arg->hash) != tbl) {
- rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
+ rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
}
- switch (status) {
- case ST_DELETE:
- return ST_DELETE;
- case ST_CONTINUE:
- break;
- case ST_STOP:
- return ST_STOP;
- }
- return ST_CHECK;
+
+ return hash_iter_status_check(status);
}
static int
@@ -1406,13 +1430,19 @@ iter_lev_in_ivar_set(VALUE hash, int lev)
rb_ivar_set_internal(hash, id_hash_iter_lev, INT2FIX(lev));
}
-static int
+static inline int
iter_lev_in_flags(VALUE hash)
{
unsigned int u = (unsigned int)((RBASIC(hash)->flags >> RHASH_LEV_SHIFT) & RHASH_LEV_MAX);
return (int)u;
}
+static inline void
+iter_lev_in_flags_set(VALUE hash, int lev)
+{
+ RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT));
+}
+
static int
RHASH_ITER_LEV(VALUE hash)
{
@@ -1436,7 +1466,7 @@ hash_iter_lev_inc(VALUE hash)
}
else {
lev += 1;
- RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT));
+ iter_lev_in_flags_set(hash, lev);
if (lev == RHASH_LEV_MAX) {
iter_lev_in_ivar_set(hash, lev);
}
@@ -1454,7 +1484,7 @@ hash_iter_lev_dec(VALUE hash)
}
else {
HASH_ASSERT(lev > 0);
- RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((lev-1) << RHASH_LEV_SHIFT));
+ iter_lev_in_flags_set(hash, lev - 1);
}
}
@@ -1520,14 +1550,29 @@ rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
if (RHASH_TABLE_EMPTY_P(hash))
return;
- hash_iter_lev_inc(hash);
arg.hash = hash;
arg.func = (rb_foreach_func *)func;
arg.arg = farg;
- rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
+ if (RB_OBJ_FROZEN(hash)) {
+ hash_foreach_call((VALUE)&arg);
+ }
+ else {
+ hash_iter_lev_inc(hash);
+ rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
+ }
hash_verify(hash);
}
+void rb_st_compact_table(st_table *tab);
+
+static void
+compact_after_delete(VALUE hash)
+{
+ if (RHASH_ITER_LEV(hash) == 0 && RHASH_ST_TABLE_P(hash)) {
+ rb_st_compact_table(RHASH_ST_TABLE(hash));
+ }
+}
+
static VALUE
hash_alloc_flags(VALUE klass, VALUE flags, VALUE ifnone)
{
@@ -1559,8 +1604,6 @@ rb_hash_new(void)
return hash_alloc(rb_cHash);
}
-static VALUE rb_hash_compare_by_id(VALUE hash);
-
static VALUE
copy_compare_by_id(VALUE hash, VALUE basis)
{
@@ -1586,6 +1629,12 @@ rb_hash_new_with_size(st_index_t size)
return ret;
}
+VALUE
+rb_hash_new_capa(long capa)
+{
+ return rb_hash_new_with_size((st_index_t)capa);
+}
+
static VALUE
hash_copy(VALUE ret, VALUE hash)
{
@@ -1684,6 +1733,8 @@ struct update_arg {
st_data_t arg;
st_update_callback_func *func;
VALUE hash;
+ VALUE key;
+ VALUE value;
};
typedef int (*tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int);
@@ -1694,7 +1745,7 @@ rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func,
if (RHASH_AR_TABLE_P(hash)) {
int result = ar_update(hash, key, func, arg);
if (result == -1) {
- ar_try_convert_table(hash);
+ ar_force_convert_table(hash, __FILE__, __LINE__);
}
else {
return result;
@@ -1716,11 +1767,11 @@ tbl_update_modify(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
default:
break;
case ST_CONTINUE:
- if (!existing || *key != old_key || *val != old_value)
+ if (!existing || *key != old_key || *val != old_value) {
rb_hash_modify(hash);
- /* write barrier */
- RB_OBJ_WRITTEN(hash, Qundef, *key);
- RB_OBJ_WRITTEN(hash, Qundef, *val);
+ p->key = *key;
+ p->value = *val;
+ }
break;
case ST_DELETE:
if (existing)
@@ -1738,9 +1789,17 @@ tbl_update(VALUE hash, VALUE key, tbl_update_func func, st_data_t optional_arg)
.arg = optional_arg,
.func = func,
.hash = hash,
+ .key = key,
+ .value = (VALUE)optional_arg,
};
- return rb_hash_stlike_update(hash, key, tbl_update_modify, (st_data_t)&arg);
+ int ret = rb_hash_stlike_update(hash, key, tbl_update_modify, (st_data_t)&arg);
+
+ /* write barrier */
+ RB_OBJ_WRITTEN(hash, Qundef, arg.key);
+ RB_OBJ_WRITTEN(hash, Qundef, arg.value);
+
+ return ret;
}
#define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert)
@@ -1756,12 +1815,12 @@ static void
set_proc_default(VALUE hash, VALUE proc)
{
if (rb_proc_lambda_p(proc)) {
- int n = rb_proc_arity(proc);
+ int n = rb_proc_arity(proc);
- if (n != 2 && (n >= 0 || n < -3)) {
- if (n < 0) n = -n-1;
- rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
- }
+ if (n != 2 && (n >= 0 || n < -3)) {
+ if (n < 0) n = -n-1;
+ rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
+ }
}
FL_SET_RAW(hash, RHASH_PROC_DEFAULT);
@@ -1776,7 +1835,7 @@ set_proc_default(VALUE hash, VALUE proc)
* 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].
+ * depend on which form above was used. See {Default Values}[rdoc-ref:Hash@Default+Values].
*
* If neither an argument nor a block given,
* initializes both the default value and the default proc to <tt>nil</tt>:
@@ -1806,14 +1865,14 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
rb_hash_modify(hash);
if (rb_block_given_p()) {
- rb_check_arity(argc, 0, 0);
- ifnone = rb_block_proc();
- SET_PROC_DEFAULT(hash, ifnone);
+ rb_check_arity(argc, 0, 0);
+ ifnone = rb_block_proc();
+ SET_PROC_DEFAULT(hash, ifnone);
}
else {
- rb_check_arity(argc, 0, 1);
- ifnone = argc == 0 ? Qnil : argv[0];
- RHASH_SET_IFNONE(hash, ifnone);
+ rb_check_arity(argc, 0, 1);
+ ifnone = argc == 0 ? Qnil : argv[0];
+ RHASH_SET_IFNONE(hash, ifnone);
}
return hash;
@@ -1861,42 +1920,42 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
if (argc == 1) {
tmp = rb_hash_s_try_convert(Qnil, argv[0]);
- if (!NIL_P(tmp)) {
- hash = hash_alloc(klass);
+ if (!NIL_P(tmp)) {
+ hash = hash_alloc(klass);
hash_copy(hash, tmp);
- return hash;
- }
-
- tmp = rb_check_array_type(argv[0]);
- if (!NIL_P(tmp)) {
- long i;
-
- hash = hash_alloc(klass);
- for (i = 0; i < RARRAY_LEN(tmp); ++i) {
- VALUE e = RARRAY_AREF(tmp, i);
- VALUE v = rb_check_array_type(e);
- VALUE key, val = Qnil;
-
- if (NIL_P(v)) {
- rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
- rb_builtin_class_name(e), i);
- }
- switch (RARRAY_LEN(v)) {
- default:
- rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
- RARRAY_LEN(v));
- case 2:
- val = RARRAY_AREF(v, 1);
- case 1:
- key = RARRAY_AREF(v, 0);
- rb_hash_aset(hash, key, val);
- }
- }
- return hash;
- }
+ return hash;
+ }
+
+ tmp = rb_check_array_type(argv[0]);
+ if (!NIL_P(tmp)) {
+ long i;
+
+ hash = hash_alloc(klass);
+ for (i = 0; i < RARRAY_LEN(tmp); ++i) {
+ VALUE e = RARRAY_AREF(tmp, i);
+ VALUE v = rb_check_array_type(e);
+ VALUE key, val = Qnil;
+
+ if (NIL_P(v)) {
+ rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
+ rb_builtin_class_name(e), i);
+ }
+ switch (RARRAY_LEN(v)) {
+ default:
+ rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
+ RARRAY_LEN(v));
+ case 2:
+ val = RARRAY_AREF(v, 1);
+ case 1:
+ key = RARRAY_AREF(v, 0);
+ rb_hash_aset(hash, key, val);
+ }
+ }
+ return hash;
+ }
}
if (argc % 2 != 0) {
- rb_raise(rb_eArgError, "odd number of arguments for Hash");
+ rb_raise(rb_eArgError, "odd number of arguments for Hash");
}
hash = hash_alloc(klass);
@@ -2009,7 +2068,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
*
* 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].
+ * See {Modifying an Active Hash Key}[rdoc-ref:Hash@Modifying+an+Active+Hash+Key].
*/
VALUE
@@ -2019,7 +2078,7 @@ rb_hash_rehash(VALUE hash)
st_table *tbl;
if (RHASH_ITER_LEV(hash) > 0) {
- rb_raise(rb_eRuntimeError, "rehash during iteration");
+ rb_raise(rb_eRuntimeError, "rehash during iteration");
}
rb_hash_modify_check(hash);
if (RHASH_AR_TABLE_P(hash)) {
@@ -2051,17 +2110,31 @@ call_default_proc(VALUE proc, VALUE hash, VALUE key)
return rb_proc_call_with_block(proc, 2, args, Qnil);
}
+static bool
+rb_hash_default_unredefined(VALUE hash)
+{
+ VALUE klass = RBASIC_CLASS(hash);
+ if (LIKELY(klass == rb_cHash)) {
+ return !!BASIC_OP_UNREDEFINED_P(BOP_DEFAULT, HASH_REDEFINED_OP_FLAG);
+ }
+ else {
+ return LIKELY(rb_method_basic_definition_p(klass, id_default));
+ }
+}
+
VALUE
rb_hash_default_value(VALUE hash, VALUE key)
{
- 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;
+ RUBY_ASSERT(RB_TYPE_P(hash, T_HASH));
+
+ if (LIKELY(rb_hash_default_unredefined(hash))) {
+ VALUE ifnone = RHASH_IFNONE(hash);
+ if (LIKELY(!FL_TEST_RAW(hash, RHASH_PROC_DEFAULT))) return ifnone;
+ if (UNDEF_P(key)) return Qnil;
return call_default_proc(ifnone, hash, key);
}
else {
- return rb_funcall(hash, id_default, 1, key);
+ return rb_funcall(hash, id_default, 1, key);
}
}
@@ -2093,7 +2166,7 @@ rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
* h[:foo] # => 0
*
* If +key+ is not found, returns a default value
- * (see {Default Values}[#class-Hash-label-Default+Values]):
+ * (see {Default Values}[rdoc-ref:Hash@Default+Values]):
* h = {foo: 0, bar: 1, baz: 2}
* h[:nosuch] # => nil
*/
@@ -2165,7 +2238,7 @@ rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
block_given = rb_block_given_p();
if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
+ rb_warn("block supersedes default value argument");
}
if (hash_stlike_lookup(hash, key, &val)) {
@@ -2202,7 +2275,7 @@ rb_hash_fetch(VALUE hash, VALUE key)
*
* 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].
+ * See {Default Values}[rdoc-ref:Hash@Default+Values].
*
* With no argument, returns the current default value:
* h = {}
@@ -2223,8 +2296,8 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash)
rb_check_arity(argc, 0, 1);
ifnone = RHASH_IFNONE(hash);
if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
- if (argc == 0) return Qnil;
- return call_default_proc(ifnone, hash, argv[0]);
+ if (argc == 0) return Qnil;
+ return call_default_proc(ifnone, hash, argv[0]);
}
return ifnone;
}
@@ -2239,7 +2312,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash)
* h.default = false # => false
* h.default # => false
*
- * See {Default Values}[#class-Hash-label-Default+Values].
+ * See {Default Values}[rdoc-ref:Hash@Default+Values].
*/
static VALUE
@@ -2255,7 +2328,7 @@ rb_hash_set_default(VALUE hash, VALUE ifnone)
* hash.default_proc -> proc or nil
*
* Returns the default proc for +self+
- * (see {Default Values}[#class-Hash-label-Default+Values]):
+ * (see {Default Values}[rdoc-ref:Hash@Default+Values]):
* h = {}
* h.default_proc # => nil
* h.default_proc = proc {|hash, key| "Default value for #{key}" }
@@ -2266,7 +2339,7 @@ static VALUE
rb_hash_default_proc(VALUE hash)
{
if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
- return RHASH_IFNONE(hash);
+ return RHASH_IFNONE(hash);
}
return Qnil;
}
@@ -2276,7 +2349,7 @@ rb_hash_default_proc(VALUE hash)
* hash.default_proc = proc -> proc
*
* Sets the default proc for +self+ to +proc+:
- * (see {Default Values}[#class-Hash-label-Default+Values]):
+ * (see {Default Values}[rdoc-ref:Hash@Default+Values]):
* h = {}
* h.default_proc # => nil
* h.default_proc = proc { |hash, key| "Default value for #{key}" }
@@ -2292,14 +2365,14 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc)
rb_hash_modify_check(hash);
if (NIL_P(proc)) {
- SET_DEFAULT(hash, proc);
- return proc;
+ SET_DEFAULT(hash, proc);
+ return proc;
}
b = rb_check_convert_type_with_id(proc, T_DATA, "Proc", idTo_proc);
if (NIL_P(b) || !rb_obj_is_proc(b)) {
- rb_raise(rb_eTypeError,
- "wrong default_proc type %s (expected Proc)",
- rb_obj_classname(proc));
+ rb_raise(rb_eTypeError,
+ "wrong default_proc type %s (expected Proc)",
+ rb_obj_classname(proc));
}
proc = b;
SET_PROC_DEFAULT(hash, proc);
@@ -2312,8 +2385,8 @@ key_i(VALUE key, VALUE value, VALUE arg)
VALUE *args = (VALUE *)arg;
if (rb_equal(value, args[0])) {
- args[1] = key;
- return ST_STOP;
+ args[1] = key;
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -2323,7 +2396,7 @@ key_i(VALUE key, VALUE value, VALUE arg)
* hash.key(value) -> key or nil
*
* Returns the key for the first-found entry with the given +value+
- * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
* h = {foo: 0, bar: 2, baz: 2}
* h.key(0) # => :foo
* h.key(2) # => :bar
@@ -2383,11 +2456,11 @@ rb_hash_delete(VALUE hash, VALUE key)
{
VALUE deleted_value = rb_hash_delete_entry(hash, key);
- if (deleted_value != Qundef) { /* likely pass */
- return deleted_value;
+ if (!UNDEF_P(deleted_value)) { /* likely pass */
+ return deleted_value;
}
else {
- return Qnil;
+ return Qnil;
}
}
@@ -2426,16 +2499,17 @@ rb_hash_delete_m(VALUE hash, VALUE key)
rb_hash_modify_check(hash);
val = rb_hash_delete_entry(hash, key);
- if (val != Qundef) {
- return val;
+ if (!UNDEF_P(val)) {
+ compact_after_delete(hash);
+ return val;
}
else {
- if (rb_block_given_p()) {
- return rb_yield(key);
- }
- else {
- return Qnil;
- }
+ if (rb_block_given_p()) {
+ return rb_yield(key);
+ }
+ else {
+ return Qnil;
+ }
}
}
@@ -2456,17 +2530,16 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hash.shift -> [key, value] or default_value
+ * hash.shift -> [key, value] or nil
*
* Removes the first hash entry
- * (see {Entry Order}[#class-Hash-label-Entry+Order]);
+ * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]);
* returns a 2-element \Array containing the removed key and value:
* h = {foo: 0, bar: 1, baz: 2}
* h.shift # => [:foo, 0]
* h # => {:bar=>1, :baz=>2}
*
- * Returns the default value if the hash is empty
- * (see {Default Values}[#class-Hash-label-Default+Values]).
+ * Returns nil if the hash is empty.
*/
static VALUE
@@ -2476,15 +2549,15 @@ rb_hash_shift(VALUE hash)
rb_hash_modify_check(hash);
if (RHASH_AR_TABLE_P(hash)) {
- var.key = Qundef;
- if (RHASH_ITER_LEV(hash) == 0) {
+ var.key = Qundef;
+ if (RHASH_ITER_LEV(hash) == 0) {
if (ar_shift(hash, &var.key, &var.val)) {
- return rb_assoc_new(var.key, var.val);
- }
- }
- else {
+ return rb_assoc_new(var.key, var.val);
+ }
+ }
+ else {
rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
- if (var.key != Qundef) {
+ if (!UNDEF_P(var.key)) {
rb_hash_delete_entry(hash, var.key);
return rb_assoc_new(var.key, var.val);
}
@@ -2498,22 +2571,22 @@ rb_hash_shift(VALUE hash)
}
}
else {
- rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
- if (var.key != Qundef) {
- rb_hash_delete_entry(hash, var.key);
- return rb_assoc_new(var.key, var.val);
- }
- }
+ rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
+ if (!UNDEF_P(var.key)) {
+ rb_hash_delete_entry(hash, var.key);
+ return rb_assoc_new(var.key, var.val);
+ }
+ }
}
- return rb_hash_default_value(hash, Qnil);
+ return Qnil;
}
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;
+ rb_hash_modify(hash);
+ return ST_DELETE;
}
return ST_CONTINUE;
}
@@ -2548,6 +2621,7 @@ rb_hash_delete_if(VALUE hash)
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
rb_hash_foreach(hash, delete_if_i, hash);
+ compact_after_delete(hash);
}
return hash;
}
@@ -2608,15 +2682,10 @@ rb_hash_reject(VALUE hash)
VALUE result;
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
- if (RTEST(ruby_verbose)) {
- VALUE klass;
- if (HAS_EXTRA_STATES(hash, klass)) {
- rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash);
- }
- }
result = hash_dup_with_compare_by_id(hash);
if (!RHASH_EMPTY_P(hash)) {
- rb_hash_foreach(result, delete_if_i, result);
+ rb_hash_foreach(result, delete_if_i, result);
+ compact_after_delete(result);
}
return result;
}
@@ -2644,10 +2713,10 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash)
result = copy_compare_by_id(rb_hash_new_with_size(argc), hash);
for (i = 0; i < argc; i++) {
- key = argv[i];
- value = rb_hash_lookup2(hash, key, Qundef);
- if (value != Qundef)
- rb_hash_aset(result, key, value);
+ key = argv[i];
+ value = rb_hash_lookup2(hash, key, Qundef);
+ if (!UNDEF_P(value))
+ rb_hash_aset(result, key, value);
}
return result;
@@ -2676,6 +2745,7 @@ rb_hash_except(int argc, VALUE *argv, VALUE hash)
key = argv[i];
rb_hash_delete(result, key);
}
+ compact_after_delete(result);
return result;
}
@@ -2688,7 +2758,7 @@ rb_hash_except(int argc, VALUE *argv, VALUE hash)
* h = {foo: 0, bar: 1, baz: 2}
* h.values_at(:baz, :foo) # => [2, 0]
*
- * The {default values}[#class-Hash-label-Default+Values] are returned
+ * The {default values}[rdoc-ref:Hash@Default+Values] are returned
* for any keys that are not found:
* h.values_at(:hello, :foo) # => [nil, 0]
*/
@@ -2700,7 +2770,7 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
long i;
for (i=0; i<argc; i++) {
- rb_ary_push(result, rb_hash_aref(hash, argv[i]));
+ rb_ary_push(result, rb_hash_aref(hash, argv[i]));
}
return result;
}
@@ -2732,7 +2802,7 @@ rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
long i;
for (i=0; i<argc; i++) {
- rb_ary_push(result, rb_hash_fetch(hash, argv[i]));
+ rb_ary_push(result, rb_hash_fetch(hash, argv[i]));
}
return result;
}
@@ -2741,8 +2811,8 @@ 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;
+ rb_hash_modify(hash);
+ return ST_DELETE;
}
return ST_CONTINUE;
}
@@ -2772,7 +2842,8 @@ rb_hash_select(VALUE hash)
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
result = hash_dup_with_compare_by_id(hash);
if (!RHASH_EMPTY_P(hash)) {
- rb_hash_foreach(result, keep_if_i, result);
+ rb_hash_foreach(result, keep_if_i, result);
+ compact_after_delete(result);
}
return result;
}
@@ -2864,6 +2935,7 @@ rb_hash_clear(VALUE hash)
}
else {
st_clear(RHASH_ST_TABLE(hash));
+ compact_after_delete(hash);
}
return hash;
@@ -2883,7 +2955,7 @@ rb_hash_key_str(VALUE key)
return rb_fstring(key);
}
else {
- return rb_str_new_frozen(key);
+ return rb_str_new_frozen(key);
}
}
@@ -2891,7 +2963,7 @@ static int
hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
{
if (!existing && !RB_OBJ_FROZEN(*key)) {
- *key = rb_hash_key_str(*key);
+ *key = rb_hash_key_str(*key);
}
return hash_aset(key, val, arg, existing);
}
@@ -2910,7 +2982,7 @@ NOINSERT_UPDATE_CALLBACK(hash_aset_str)
*
* 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]):
+ * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
* h = {foo: 0, bar: 1}
* h[:foo] = 2 # => 2
* h.store(:bar, 3) # => 3
@@ -2918,7 +2990,7 @@ NOINSERT_UPDATE_CALLBACK(hash_aset_str)
*
* 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]):
+ * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
* h = {foo: 0, bar: 1}
* h[:baz] = 2 # => 2
* h.store(:bat, 3) # => 3
@@ -2933,15 +3005,15 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
rb_hash_modify(hash);
if (RHASH_TABLE_NULL_P(hash)) {
- if (iter_lev > 0) no_new_key();
+ if (iter_lev > 0) no_new_key();
ar_alloc_table(hash);
}
- if (RHASH_TYPE(hash) == &identhash || rb_obj_class(key) != rb_cString) {
- RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
+ if (!RHASH_STRING_KEY_P(hash, key)) {
+ RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
}
else {
- RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
+ RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
}
return val;
}
@@ -2969,25 +3041,17 @@ rb_hash_replace(VALUE hash, VALUE hash2)
COPY_DEFAULT(hash, hash2);
if (RHASH_AR_TABLE_P(hash)) {
- if (RHASH_AR_TABLE_P(hash2)) {
- ar_clear(hash);
- }
- else {
- ar_free_and_clear_table(hash);
- RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), RHASH_SIZE(hash2)));
- }
+ ar_free_and_clear_table(hash);
}
else {
- if (RHASH_AR_TABLE_P(hash2)) {
- st_free_table(RHASH_ST_TABLE(hash));
- RHASH_ST_CLEAR(hash);
- }
- else {
- st_clear(RHASH_ST_TABLE(hash));
- RHASH_TBL_RAW(hash)->type = RHASH_ST_TABLE(hash2)->type;
- }
+ st_free_table(RHASH_ST_TABLE(hash));
+ RHASH_ST_CLEAR(hash);
}
hash_copy(hash, hash2);
+ if (RHASH_EMPTY_P(hash2) && RHASH_ST_TABLE_P(hash2)) {
+ /* ident hash */
+ RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), 0));
+ }
rb_gc_writebarrier_remember(hash);
@@ -3159,9 +3223,9 @@ rb_hash_each_pair(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
if (rb_block_pair_yield_optimizable())
- rb_hash_foreach(hash, each_pair_i_fast, 0);
+ rb_hash_foreach(hash, each_pair_i_fast, 0);
else
- rb_hash_foreach(hash, each_pair_i, 0);
+ rb_hash_foreach(hash, each_pair_i, 0);
return hash;
}
@@ -3177,7 +3241,7 @@ 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 (UNDEF_P(new_key)) {
if (p->block_given)
new_key = rb_yield(key);
else
@@ -3290,7 +3354,7 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
if (!RHASH_TABLE_EMPTY_P(hash)) {
long i;
VALUE new_keys = hash_alloc(0);
- VALUE pairs = rb_ary_tmp_new(RHASH_SIZE(hash) * 2);
+ VALUE pairs = rb_ary_hidden_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, val;
@@ -3298,7 +3362,7 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
if (!trans) {
new_key = rb_yield(key);
}
- else if ((new_key = rb_hash_lookup2(trans, key, Qundef)) != Qundef) {
+ else if (!UNDEF_P(new_key = rb_hash_lookup2(trans, key, Qundef))) {
/* use the transformed key */
}
else if (block_given) {
@@ -3316,8 +3380,8 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
}
rb_ary_clear(pairs);
rb_hash_clear(new_keys);
- rb_gc_force_recycle(new_keys);
}
+ compact_after_delete(hash);
return hash;
}
@@ -3368,6 +3432,7 @@ rb_hash_transform_values(VALUE hash)
if (!RHASH_EMPTY_P(hash)) {
rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, result);
+ compact_after_delete(result);
}
return result;
@@ -3436,10 +3501,10 @@ inspect_i(VALUE key, VALUE value, VALUE str)
str2 = rb_inspect(key);
if (RSTRING_LEN(str) > 1) {
- rb_str_buf_cat_ascii(str, ", ");
+ rb_str_buf_cat_ascii(str, ", ");
}
else {
- rb_enc_copy(str, str2);
+ rb_enc_copy(str, str2);
}
rb_str_buf_append(str, str2);
rb_str_buf_cat_ascii(str, "=>");
@@ -3477,7 +3542,7 @@ static VALUE
rb_hash_inspect(VALUE hash)
{
if (RHASH_EMPTY_P(hash))
- return rb_usascii_str_new2("{}");
+ return rb_usascii_str_new2("{}");
return rb_exec_recursive(inspect_hash, hash, 0);
}
@@ -3552,7 +3617,7 @@ rb_hash_to_h(VALUE hash)
return rb_hash_to_h_block(hash);
}
if (rb_obj_class(hash) != rb_cHash) {
- const VALUE flags = RBASIC(hash)->flags;
+ const VALUE flags = RBASIC(hash)->flags;
hash = hash_dup(hash, rb_cHash, flags & RHASH_PROC_DEFAULT);
}
return hash;
@@ -3593,10 +3658,10 @@ rb_hash_keys(VALUE hash)
}
});
rb_gc_writebarrier_remember(keys);
- rb_ary_set_len(keys, size);
+ rb_ary_set_len(keys, size);
}
else {
- rb_hash_foreach(hash, keys_i, keys);
+ rb_hash_foreach(hash, keys_i, keys);
}
return keys;
@@ -3641,11 +3706,11 @@ rb_hash_values(VALUE hash)
size = st_values(table, ptr, size);
});
}
- rb_ary_set_len(values, size);
+ rb_ary_set_len(values, size);
}
else {
- rb_hash_foreach(hash, values_i, values);
+ rb_hash_foreach(hash, values_i, values);
}
return values;
@@ -3675,8 +3740,8 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
VALUE *data = (VALUE *)arg;
if (rb_equal(value, data[1])) {
- data[0] = Qtrue;
- return ST_STOP;
+ data[0] = Qtrue;
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -3747,23 +3812,23 @@ hash_equal(VALUE hash1, VALUE hash2, int eql)
if (hash1 == hash2) return Qtrue;
if (!RB_TYPE_P(hash2, T_HASH)) {
- if (!rb_respond_to(hash2, idTo_hash)) {
- return Qfalse;
- }
- if (eql) {
- if (rb_eql(hash2, hash1)) {
- return Qtrue;
- }
- else {
- return Qfalse;
- }
- }
- else {
- return rb_equal(hash2, hash1);
- }
+ if (!rb_respond_to(hash2, idTo_hash)) {
+ return Qfalse;
+ }
+ if (eql) {
+ if (rb_eql(hash2, hash1)) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ else {
+ return rb_equal(hash2, hash1);
+ }
}
if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
- return Qfalse;
+ return Qfalse;
if (!RHASH_TABLE_EMPTY_P(hash1) && !RHASH_TABLE_EMPTY_P(hash2)) {
if (RHASH_TYPE(hash1) != RHASH_TYPE(hash2)) {
return Qfalse;
@@ -3778,7 +3843,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql)
#if 0
if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) &&
FL_TEST(hash1, RHASH_PROC_DEFAULT) == FL_TEST(hash2, RHASH_PROC_DEFAULT)))
- return Qfalse;
+ return Qfalse;
#endif
return Qtrue;
}
@@ -3866,7 +3931,7 @@ rb_hash_hash(VALUE hash)
st_index_t hval = rb_hash_start(size);
hval = rb_hash_uint(hval, (st_index_t)rb_hash_hash);
if (size) {
- rb_hash_foreach(hash, hash_i, (VALUE)&hval);
+ rb_hash_foreach(hash, hash_i, (VALUE)&hval);
}
hval = rb_hash_end(hval);
return ST2FIX(hval);
@@ -3889,7 +3954,7 @@ rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
* h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
*
* Overwrites any repeated new keys:
- * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
* h = {foo: 0, bar: 0, baz: 0}
* h.invert # => {0=>:baz}
*/
@@ -3904,18 +3969,9 @@ rb_hash_invert(VALUE hash)
}
static int
-rb_hash_update_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
-{
- *value = arg->arg;
- return ST_CONTINUE;
-}
-
-NOINSERT_UPDATE_CALLBACK(rb_hash_update_callback)
-
-static int
rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
{
- RHASH_UPDATE(hash, key, rb_hash_update_callback, value);
+ rb_hash_aset(hash, key, value);
return ST_CONTINUE;
}
@@ -3927,6 +3983,9 @@ rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_ar
if (existing) {
newvalue = (st_data_t)rb_yield_values(3, (VALUE)*key, (VALUE)*value, (VALUE)newvalue);
}
+ else if (RHASH_STRING_KEY_P(arg->hash, *key) && !RB_OBJ_FROZEN(*key)) {
+ *key = rb_hash_key_str(*key);
+ }
*value = newvalue;
return ST_CONTINUE;
}
@@ -4022,7 +4081,7 @@ rb_hash_update_func_callback(st_data_t *key, st_data_t *value, struct update_arg
VALUE newvalue = uf_arg->value;
if (existing) {
- newvalue = (*uf_arg->func)((VALUE)*key, (VALUE)*value, newvalue);
+ newvalue = (*uf_arg->func)((VALUE)*key, (VALUE)*value, newvalue);
}
*value = newvalue;
return ST_CONTINUE;
@@ -4047,13 +4106,13 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
rb_hash_modify(hash1);
hash2 = to_hash(hash2);
if (func) {
- struct update_func_arg arg;
- arg.hash = hash1;
- arg.func = func;
- rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg);
+ struct update_func_arg arg;
+ arg.hash = hash1;
+ arg.func = func;
+ rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg);
}
else {
- rb_hash_foreach(hash2, rb_hash_update_i, hash1);
+ rb_hash_foreach(hash2, rb_hash_update_i, hash1);
}
return hash1;
}
@@ -4148,8 +4207,8 @@ assoc_i(VALUE key, VALUE val, VALUE arg)
VALUE *args = (VALUE *)arg;
if (RTEST(rb_equal(args[0], key))) {
- args[1] = rb_assoc_new(key, val);
- return ST_STOP;
+ args[1] = rb_assoc_new(key, val);
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -4179,20 +4238,20 @@ rb_hash_assoc(VALUE hash, VALUE key)
table = RHASH_ST_TABLE(hash);
orighash = table->type;
- if (orighash != &identhash) {
- VALUE value;
- struct reset_hash_type_arg ensure_arg;
- struct st_hash_type assochash;
+ if (!RHASH_IDENTHASH_P(hash)) {
+ VALUE value;
+ struct reset_hash_type_arg ensure_arg;
+ struct st_hash_type assochash;
- assochash.compare = assoc_cmp;
- assochash.hash = orighash->hash;
+ assochash.compare = assoc_cmp;
+ assochash.hash = orighash->hash;
table->type = &assochash;
- args[0] = hash;
- args[1] = key;
- ensure_arg.hash = hash;
- ensure_arg.orighash = orighash;
- value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
- if (value != Qundef) return rb_assoc_new(key, value);
+ args[0] = hash;
+ args[1] = key;
+ ensure_arg.hash = hash;
+ ensure_arg.orighash = orighash;
+ value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
+ if (!UNDEF_P(value)) return rb_assoc_new(key, value);
}
args[0] = key;
@@ -4207,8 +4266,8 @@ rassoc_i(VALUE key, VALUE val, VALUE arg)
VALUE *args = (VALUE *)arg;
if (RTEST(rb_equal(args[0], val))) {
- args[1] = rb_assoc_new(key, val);
- return ST_STOP;
+ args[1] = rb_assoc_new(key, val);
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -4219,7 +4278,7 @@ rassoc_i(VALUE key, VALUE val, VALUE arg)
*
* 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]):
+ * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
* h = {foo: 0, bar: 1, baz: 1}
* h.rassoc(1) # => [:bar, 1]
*
@@ -4288,26 +4347,26 @@ rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
rb_check_arity(argc, 0, 1);
if (argc) {
- int level = NUM2INT(argv[0]);
+ int level = NUM2INT(argv[0]);
- if (level == 0) return rb_hash_to_a(hash);
+ if (level == 0) return rb_hash_to_a(hash);
- ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
- rb_hash_foreach(hash, flatten_i, ary);
- level--;
+ ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
+ rb_hash_foreach(hash, flatten_i, ary);
+ level--;
- if (level > 0) {
- VALUE ary_flatten_level = INT2FIX(level);
- rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
- }
- else if (level < 0) {
- /* flatten recursively */
- rb_funcallv(ary, id_flatten_bang, 0, 0);
- }
+ if (level > 0) {
+ VALUE ary_flatten_level = INT2FIX(level);
+ rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
+ }
+ else if (level < 0) {
+ /* flatten recursively */
+ rb_funcallv(ary, id_flatten_bang, 0, 0);
+ }
}
else {
- ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
- rb_hash_foreach(hash, flatten_i, ary);
+ ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
+ rb_hash_foreach(hash, flatten_i, ary);
}
return ary;
@@ -4317,7 +4376,7 @@ static int
delete_if_nil(VALUE key, VALUE value, VALUE hash)
{
if (NIL_P(value)) {
- return ST_DELETE;
+ return ST_DELETE;
}
return ST_CONTINUE;
}
@@ -4326,7 +4385,7 @@ static int
set_if_not_nil(VALUE key, VALUE value, VALUE hash)
{
if (!NIL_P(value)) {
- rb_hash_aset(hash, key, value);
+ rb_hash_aset(hash, key, value);
}
return ST_CONTINUE;
}
@@ -4346,7 +4405,7 @@ rb_hash_compact(VALUE hash)
{
VALUE result = rb_hash_new();
if (!RHASH_EMPTY_P(hash)) {
- rb_hash_foreach(hash, set_if_not_nil, result);
+ rb_hash_foreach(hash, set_if_not_nil, result);
}
return result;
}
@@ -4369,9 +4428,9 @@ rb_hash_compact_bang(VALUE hash)
rb_hash_modify_check(hash);
n = RHASH_SIZE(hash);
if (n) {
- rb_hash_foreach(hash, delete_if_nil, hash);
+ rb_hash_foreach(hash, delete_if_nil, hash);
if (n != RHASH_SIZE(hash))
- return hash;
+ return hash;
}
return Qnil;
}
@@ -4406,7 +4465,7 @@ static st_table *rb_init_identtable_with_size(st_index_t size);
* h # => {"x"=>0, "x"=>1}
*/
-static VALUE
+VALUE
rb_hash_compare_by_id(VALUE hash)
{
VALUE tmp;
@@ -4425,7 +4484,6 @@ rb_hash_compare_by_id(VALUE hash)
st_free_table(RHASH_ST_TABLE(hash));
RHASH_ST_TABLE_SET(hash, identtable);
RHASH_ST_CLEAR(tmp);
- rb_gc_force_recycle(tmp);
return hash;
}
@@ -4440,7 +4498,7 @@ rb_hash_compare_by_id(VALUE hash)
MJIT_FUNC_EXPORTED VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
- return RBOOL(RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash);
+ return RBOOL(RHASH_IDENTHASH_P(hash));
}
VALUE
@@ -4451,6 +4509,14 @@ rb_ident_hash_new(void)
return hash;
}
+VALUE
+rb_ident_hash_new_with_size(st_index_t size)
+{
+ VALUE hash = rb_hash_new();
+ RHASH_ST_TABLE_SET(hash, st_init_table_with_size(&identhash, size));
+ return hash;
+}
+
st_table *
rb_init_identtable(void)
{
@@ -4468,8 +4534,8 @@ any_p_i(VALUE key, VALUE value, VALUE arg)
{
VALUE ret = rb_yield(rb_assoc_new(key, value));
if (RTEST(ret)) {
- *(VALUE *)arg = Qtrue;
- return ST_STOP;
+ *(VALUE *)arg = Qtrue;
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -4479,8 +4545,8 @@ any_p_i_fast(VALUE key, VALUE value, VALUE arg)
{
VALUE ret = rb_yield_values(2, key, value);
if (RTEST(ret)) {
- *(VALUE *)arg = Qtrue;
- return ST_STOP;
+ *(VALUE *)arg = Qtrue;
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -4490,8 +4556,8 @@ any_p_i_pattern(VALUE key, VALUE value, VALUE arg)
{
VALUE ret = rb_funcall(((VALUE *)arg)[1], idEqq, 1, rb_assoc_new(key, value));
if (RTEST(ret)) {
- *(VALUE *)arg = Qtrue;
- return ST_STOP;
+ *(VALUE *)arg = Qtrue;
+ return ST_STOP;
}
return ST_CONTINUE;
}
@@ -4537,19 +4603,19 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
if (rb_block_given_p()) {
rb_warn("given block not used");
}
- args[1] = argv[0];
+ args[1] = argv[0];
- rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
+ rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
}
else {
- if (!rb_block_given_p()) {
- /* yields pairs, never false */
- return Qtrue;
- }
+ if (!rb_block_given_p()) {
+ /* yields pairs, never false */
+ return Qtrue;
+ }
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);
+ rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
+ else
+ rb_hash_foreach(hash, any_p_i, (VALUE)args);
}
return args[0];
}
@@ -4561,7 +4627,7 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
* 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].
+ * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
*
* Nested Hashes:
* h = {foo: {bar: {baz: 2}}}
@@ -4574,7 +4640,7 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
* h = {foo: {bar: [:a, :b, :c]}}
* h.dig(:foo, :bar, 2) # => :c
*
- * This method will use the {default values}[#class-Hash-label-Default+Values]
+ * This method will use the {default values}[rdoc-ref:Hash@Default+Values]
* for keys that are not present:
* h = {foo: {bar: [:a, :b, :c]}}
* h.dig(:hello) # => nil
@@ -4598,7 +4664,7 @@ hash_le_i(VALUE key, VALUE value, VALUE arg)
{
VALUE *args = (VALUE *)arg;
VALUE v = rb_hash_lookup2(args[0], key, Qundef);
- if (v != Qundef && rb_equal(value, v)) return ST_CONTINUE;
+ if (!UNDEF_P(v) && rb_equal(value, v)) return ST_CONTINUE;
args[1] = Qfalse;
return ST_STOP;
}
@@ -4750,7 +4816,7 @@ rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
if (ret != -1) {
return ret;
}
- ar_try_convert_table(hash);
+ ar_force_convert_table(hash, __FILE__, __LINE__);
}
tbl = RHASH_TBL_RAW(hash);
return st_update(tbl, (st_data_t)key, add_new_i, (st_data_t)args);
@@ -4830,6 +4896,9 @@ extern char **environ;
#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
#endif
+#define ENV_LOCK() RB_VM_LOCK_ENTER()
+#define ENV_UNLOCK() RB_VM_LOCK_LEAVE()
+
static inline rb_encoding *
env_encoding(void)
{
@@ -4850,12 +4919,6 @@ env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
}
static VALUE
-env_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
-{
- return env_enc_str_new(ptr, strlen(ptr), enc);
-}
-
-static VALUE
env_str_new(const char *ptr, long len)
{
return env_enc_str_new(ptr, len, env_encoding());
@@ -4868,14 +4931,35 @@ env_str_new2(const char *ptr)
return env_str_new(ptr, strlen(ptr));
}
-static const char TZ_ENV[] = "TZ";
-
static VALUE
-env_name_new(const char *name, const char *ptr)
+getenv_with_lock(const char *name)
{
- return env_enc_str_new_cstr(ptr, env_encoding());
+ VALUE ret;
+ ENV_LOCK();
+ {
+ const char *val = getenv(name);
+ ret = env_str_new2(val);
+ }
+ ENV_UNLOCK();
+ return ret;
+}
+
+static bool
+has_env_with_lock(const char *name)
+{
+ const char *val;
+
+ ENV_LOCK();
+ {
+ val = getenv(name);
+ }
+ ENV_UNLOCK();
+
+ return val ? true : false;
}
+static const char TZ_ENV[] = "TZ";
+
static void *
get_env_cstr(
VALUE str,
@@ -4884,12 +4968,12 @@ get_env_cstr(
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));
+ rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s",
+ name, rb_enc_name(enc));
}
var = RSTRING_PTR(str);
if (memchr(var, '\0', RSTRING_LEN(str))) {
- rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name);
+ rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name);
}
return rb_str_fill_terminator(str, 1); /* ASCII compatible */
}
@@ -4911,7 +4995,7 @@ env_name(volatile VALUE *s)
static VALUE env_aset(VALUE nm, VALUE val);
static void
-reset_by_modified_env(const char *nam)
+reset_by_modified_env(const char *nam, const char *val)
{
/*
* ENV['TZ'] = nil has a special meaning.
@@ -4920,7 +5004,7 @@ reset_by_modified_env(const char *nam)
* This hack might works only on Linux glibc.
*/
if (ENVMATCH(nam, TZ_ENV)) {
- ruby_reset_timezone();
+ ruby_reset_timezone(val);
}
}
@@ -4928,17 +5012,13 @@ 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);
+ reset_by_modified_env(nam, NULL);
+ VALUE val = getenv_with_lock(nam);
- ruby_setenv(nam, 0);
- return value;
+ if (!NIL_P(val)) {
+ ruby_setenv(nam, 0);
}
- return Qnil;
+ return val;
}
/*
@@ -4964,7 +5044,7 @@ env_delete(VALUE name)
* 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}[rdoc-ref:ENV@Invalid+Names+and+Values].
*/
static VALUE
env_delete_m(VALUE obj, VALUE name)
@@ -4986,19 +5066,14 @@ env_delete_m(VALUE obj, VALUE name)
* 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}[rdoc-ref:ENV@Invalid+Names+and+Values].
*/
static VALUE
rb_f_getenv(VALUE obj, VALUE name)
{
- const char *nam, *env;
-
- nam = env_name(name);
- env = getenv(nam);
- if (env) {
- return env_name_new(nam, env);
- }
- return Qnil;
+ const char *nam = env_name(name);
+ VALUE env = getenv_with_lock(nam);
+ return env;
}
/*
@@ -5024,38 +5099,33 @@ 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}[rdoc-ref:ENV@Invalid+Names+and+Values].
*/
static VALUE
env_fetch(int argc, VALUE *argv, VALUE _)
{
VALUE key;
long block_given;
- const char *nam, *env;
+ const char *nam;
+ VALUE env;
rb_check_arity(argc, 1, 2);
key = argv[0];
block_given = rb_block_given_p();
if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
+ rb_warn("block supersedes default value argument");
}
nam = env_name(key);
- env = getenv(nam);
- if (!env) {
- if (block_given) return rb_yield(key);
- if (argc == 1) {
- rb_key_err_raise(rb_sprintf("key not found: \"%"PRIsVALUE"\"", key), envtbl, key);
- }
- return argv[1];
- }
- return env_name_new(nam, env);
-}
+ env = getenv_with_lock(nam);
-int
-rb_env_path_tainted(void)
-{
- rb_warn_deprecated_to_remove_at(3.2, "rb_env_path_tainted", NULL);
- return 0;
+ if (NIL_P(env)) {
+ if (block_given) return rb_yield(key);
+ if (argc == 1) {
+ rb_key_err_raise(rb_sprintf("key not found: \"%"PRIsVALUE"\"", key), envtbl, key);
+ }
+ return argv[1];
+ }
+ return env;
}
#if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
@@ -5065,7 +5135,7 @@ in_origenv(const char *str)
{
char **env;
for (env = origenviron; *env; ++env) {
- if (*env == str) return 1;
+ if (*env == str) return 1;
}
return 0;
}
@@ -5073,13 +5143,15 @@ in_origenv(const char *str)
static int
envix(const char *nam)
{
+ // should be locked
+
register int i, len = strlen(nam);
char **env;
env = GET_ENVIRON(environ);
for (i = 0; env[i]; i++) {
- if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
- break; /* memcmp must come first to avoid */
+ if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
+ break; /* memcmp must come first to avoid */
} /* potential SEGV's */
FREE_ENVIRON(environ);
return i;
@@ -5109,16 +5181,16 @@ static int
check_envsize(size_t n)
{
if (_WIN32_WINNT < 0x0600 && rb_w32_osver() < 6) {
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx */
- /* Windows Server 2003 and Windows XP: The maximum size of the
- * environment block for the process is 32,767 characters. */
- WCHAR* p = GetEnvironmentStringsW();
- if (!p) return -1; /* never happen */
- n += getenvsize(p);
- FreeEnvironmentStringsW(p);
- if (n >= getenvblocksize()) {
- return -1;
- }
+ /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx */
+ /* Windows Server 2003 and Windows XP: The maximum size of the
+ * environment block for the process is 32,767 characters. */
+ WCHAR* p = GetEnvironmentStringsW();
+ if (!p) return -1; /* never happen */
+ n += getenvsize(p);
+ FreeEnvironmentStringsW(p);
+ if (n >= getenvblocksize()) {
+ return -1;
+ }
}
return 0;
}
@@ -5139,7 +5211,7 @@ static const char *
check_envname(const char *name)
{
if (strchr(name, '=')) {
- invalid_envname(name);
+ invalid_envname(name);
}
return name;
}
@@ -5160,56 +5232,78 @@ ruby_setenv(const char *name, const char *value)
check_envname(name);
len = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
if (value) {
- int len2;
- len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
- if (check_envsize((size_t)len + len2)) { /* len and len2 include '\0' */
- goto fail; /* 2 for '=' & '\0' */
- }
- wname = ALLOCV_N(WCHAR, buf, len + len2);
- wvalue = wname + len;
- MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
- MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
+ int len2;
+ len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
+ if (check_envsize((size_t)len + len2)) { /* len and len2 include '\0' */
+ goto fail; /* 2 for '=' & '\0' */
+ }
+ wname = ALLOCV_N(WCHAR, buf, len + len2);
+ wvalue = wname + len;
+ MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
+ MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
#ifndef HAVE__WPUTENV_S
- wname[len-1] = L'=';
+ wname[len-1] = L'=';
#endif
}
else {
- wname = ALLOCV_N(WCHAR, buf, len + 1);
- MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
- wvalue = wname + len;
- *wvalue = L'\0';
+ wname = ALLOCV_N(WCHAR, buf, len + 1);
+ MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
+ wvalue = wname + len;
+ *wvalue = L'\0';
#ifndef HAVE__WPUTENV_S
- wname[len-1] = L'=';
+ wname[len-1] = L'=';
#endif
}
+
+ ENV_LOCK();
+ {
#ifndef HAVE__WPUTENV_S
- failed = _wputenv(wname);
+ failed = _wputenv(wname);
#else
- failed = _wputenv_s(wname, wvalue);
+ failed = _wputenv_s(wname, wvalue);
#endif
+ }
+ ENV_UNLOCK();
+
ALLOCV_END(buf);
/* even if putenv() failed, clean up and try to delete the
* variable from the system area. */
if (!value || !*value) {
- /* putenv() doesn't handle empty value */
- if (!SetEnvironmentVariable(name, value) &&
- GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
+ /* putenv() doesn't handle empty value */
+ if (!SetEnvironmentVariable(name, value) &&
+ GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
}
if (failed) {
fail:
- invalid_envname(name);
+ invalid_envname(name);
}
#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
if (value) {
- if (setenv(name, value, 1))
- rb_sys_fail_str(rb_sprintf("setenv(%s)", name));
+ int ret;
+ ENV_LOCK();
+ {
+ ret = setenv(name, value, 1);
+ }
+ ENV_UNLOCK();
+
+ if (ret) rb_sys_fail_str(rb_sprintf("setenv(%s)", name));
}
else {
#ifdef VOID_UNSETENV
- unsetenv(name);
+ ENV_LOCK();
+ {
+ unsetenv(name);
+ }
+ ENV_UNLOCK();
#else
- if (unsetenv(name))
- rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name));
+ int ret;
+ ENV_LOCK();
+ {
+ ret = unsetenv(name);
+ }
+ ENV_UNLOCK();
+
+ if (ret) rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name));
#endif
}
#elif defined __sun
@@ -5223,64 +5317,85 @@ ruby_setenv(const char *name, const char *value)
check_envname(name);
len = strlen(name);
if (value) {
- mem_size = len + strlen(value) + 2;
- mem_ptr = malloc(mem_size);
- if (mem_ptr == NULL)
- rb_sys_fail_str(rb_sprintf("malloc("PRIuSIZE")", mem_size));
- snprintf(mem_ptr, mem_size, "%s=%s", name, value);
- }
- for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) {
- if (!strncmp(str, name, len) && str[len] == '=') {
- if (!in_origenv(str)) free(str);
- while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
- break;
- }
+ mem_size = len + strlen(value) + 2;
+ mem_ptr = malloc(mem_size);
+ if (mem_ptr == NULL)
+ rb_sys_fail_str(rb_sprintf("malloc(%"PRIuSIZE")", mem_size));
+ snprintf(mem_ptr, mem_size, "%s=%s", name, value);
+ }
+
+ ENV_LOCK();
+ {
+ for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) {
+ if (!strncmp(str, name, len) && str[len] == '=') {
+ if (!in_origenv(str)) free(str);
+ while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
+ break;
+ }
+ }
}
+ ENV_UNLOCK();
+
if (value) {
- if (putenv(mem_ptr)) {
- free(mem_ptr);
- rb_sys_fail_str(rb_sprintf("putenv(%s)", name));
- }
+ int ret;
+ ENV_LOCK();
+ {
+ ret = putenv(mem_ptr);
+ }
+ ENV_UNLOCK();
+
+ if (ret) {
+ free(mem_ptr);
+ rb_sys_fail_str(rb_sprintf("putenv(%s)", name));
+ }
}
#else /* WIN32 */
size_t len;
int i;
- i=envix(name); /* where does it go? */
-
- if (environ == origenviron) { /* need we copy environment? */
- int j;
- int max;
- char **tmpenv;
-
- for (max = i; environ[max]; max++) ;
- tmpenv = ALLOC_N(char*, max+2);
- for (j=0; j<max; j++) /* copy environment */
- tmpenv[j] = ruby_strdup(environ[j]);
- tmpenv[max] = 0;
- environ = tmpenv; /* tell exec where it is now */
- }
- if (environ[i]) {
- char **envp = origenviron;
- while (*envp && *envp != environ[i]) envp++;
- if (!*envp)
- xfree(environ[i]);
- if (!value) {
- while (environ[i]) {
- environ[i] = environ[i+1];
- i++;
- }
- return;
- }
- }
- else { /* does not exist yet */
- if (!value) return;
- REALLOC_N(environ, char*, i+2); /* just expand it a bit */
- environ[i+1] = 0; /* make sure it's null terminated */
- }
- len = strlen(name) + strlen(value) + 2;
- environ[i] = ALLOC_N(char, len);
- snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
+ ENV_LOCK();
+ {
+ i = envix(name); /* where does it go? */
+
+ if (environ == origenviron) { /* need we copy environment? */
+ int j;
+ int max;
+ char **tmpenv;
+
+ for (max = i; environ[max]; max++) ;
+ tmpenv = ALLOC_N(char*, max+2);
+ for (j=0; j<max; j++) /* copy environment */
+ tmpenv[j] = ruby_strdup(environ[j]);
+ tmpenv[max] = 0;
+ environ = tmpenv; /* tell exec where it is now */
+ }
+
+ if (environ[i]) {
+ char **envp = origenviron;
+ while (*envp && *envp != environ[i]) envp++;
+ if (!*envp)
+ xfree(environ[i]);
+ if (!value) {
+ while (environ[i]) {
+ environ[i] = environ[i+1];
+ i++;
+ }
+ goto finish;
+ }
+ }
+ else { /* does not exist yet */
+ if (!value) goto finish;
+ REALLOC_N(environ, char*, i+2); /* just expand it a bit */
+ environ[i+1] = 0; /* make sure it's null terminated */
+ }
+
+ len = strlen(name) + strlen(value) + 2;
+ environ[i] = ALLOC_N(char, len);
+ snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
+
+ finish:;
+ }
+ ENV_UNLOCK();
#endif /* WIN32 */
}
@@ -5299,7 +5414,7 @@ ruby_unsetenv(const char *name)
*
* Creates, updates, or deletes the named environment variable, returning the value.
* Both +name+ and +value+ may be instances of String.
- * See {Valid Names and Values}[#class-ENV-label-Valid+Names+and+Values].
+ * See {Valid Names and Values}[rdoc-ref:ENV@Valid+Names+and+Values].
*
* - If the named environment variable does not exist:
* - If +value+ is +nil+, does nothing.
@@ -5332,7 +5447,7 @@ ruby_unsetenv(const char *name)
* ENV.include?('bar') # => false
*
* Raises an exception if +name+ or +value+ is invalid.
- * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
+ * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
*/
static VALUE
env_aset_m(VALUE obj, VALUE nm, VALUE val)
@@ -5347,7 +5462,7 @@ env_aset(VALUE nm, VALUE val)
if (NIL_P(val)) {
env_delete(nm);
- return Qnil;
+ return Qnil;
}
SafeStringValue(nm);
SafeStringValue(val);
@@ -5357,30 +5472,33 @@ env_aset(VALUE nm, VALUE val)
get_env_ptr(value, val);
ruby_setenv(name, value);
- reset_by_modified_env(name);
+ reset_by_modified_env(name, value);
return val;
}
static VALUE
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) {
- 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++;
+ VALUE ary = rb_ary_new();
+
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ const char *p = *env;
+ size_t l = s - p;
+ VALUE e = raw ? rb_utf8_str_new(p, l) : env_enc_str_new(p, l, enc);
+ rb_ary_push(ary, e);
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
return ary;
}
@@ -5392,7 +5510,7 @@ env_keys(int raw)
* ENV.replace('foo' => '0', 'bar' => '1')
* ENV.keys # => ['bar', 'foo']
* The order of the names is OS-dependent.
- * See {About Ordering}[#class-ENV-label-About+Ordering].
+ * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
*
* Returns the empty Array if ENV is empty.
*/
@@ -5409,13 +5527,18 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
char **env;
long cnt = 0;
- env = GET_ENVIRON(environ);
- for (; *env ; ++env) {
- if (strchr(*env, '=')) {
- cnt++;
- }
+ ENV_LOCK();
+ {
+ env = GET_ENVIRON(environ);
+ for (; *env ; ++env) {
+ if (strchr(*env, '=')) {
+ cnt++;
+ }
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
return LONG2FIX(cnt);
}
@@ -5445,7 +5568,7 @@ env_each_key(VALUE ehash)
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
keys = env_keys(FALSE);
for (i=0; i<RARRAY_LEN(keys); i++) {
- rb_yield(RARRAY_AREF(keys, i));
+ rb_yield(RARRAY_AREF(keys, i));
}
return ehash;
}
@@ -5453,19 +5576,23 @@ env_each_key(VALUE ehash)
static VALUE
env_values(void)
{
- VALUE ary;
- char **env;
+ VALUE ary = rb_ary_new();
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, env_str_new2(s+1));
- }
- env++;
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_ary_push(ary, env_str_new2(s+1));
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
return ary;
}
@@ -5477,7 +5604,7 @@ env_values(void)
* ENV.replace('foo' => '0', 'bar' => '1')
* ENV.values # => ['1', '0']
* The order of the values is OS-dependent.
- * See {About Ordering}[#class-ENV-label-About+Ordering].
+ * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
*
* Returns the empty Array if ENV is empty.
*/
@@ -5513,7 +5640,7 @@ env_each_value(VALUE ehash)
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
values = env_values();
for (i=0; i<RARRAY_LEN(values); i++) {
- rb_yield(RARRAY_AREF(values, i));
+ rb_yield(RARRAY_AREF(values, i));
}
return ehash;
}
@@ -5539,34 +5666,39 @@ env_each_value(VALUE ehash)
static VALUE
env_each_pair(VALUE ehash)
{
- char **env;
- VALUE ary;
long i;
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, env_str_new(*env, s-*env));
- rb_ary_push(ary, env_str_new2(s+1));
- }
- env++;
+ VALUE ary = rb_ary_new();
+
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_ary_push(ary, env_str_new(*env, s-*env));
+ rb_ary_push(ary, env_str_new2(s+1));
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
if (rb_block_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));
- }
+ for (i=0; i<RARRAY_LEN(ary); i+=2) {
+ rb_yield_values(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1));
+ }
}
else {
- for (i=0; i<RARRAY_LEN(ary); i+=2) {
- rb_yield(rb_assoc_new(RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1)));
- }
+ for (i=0; i<RARRAY_LEN(ary); i+=2) {
+ rb_yield(rb_assoc_new(RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1)));
+ }
}
+
return ehash;
}
@@ -5603,13 +5735,13 @@ env_reject_bang(VALUE ehash)
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));
- if (!NIL_P(val)) {
- if (RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
+ VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
+ if (!NIL_P(val)) {
+ if (RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
env_delete(RARRAY_AREF(keys, i));
- del++;
- }
- }
+ del++;
+ }
+ }
}
RB_GC_GUARD(keys);
if (del == 0) return Qnil;
@@ -5659,7 +5791,7 @@ env_delete_if(VALUE ehash)
* 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].
+ * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
*/
static VALUE
env_values_at(int argc, VALUE *argv, VALUE _)
@@ -5669,7 +5801,7 @@ env_values_at(int argc, VALUE *argv, VALUE _)
result = rb_ary_new();
for (i=0; i<argc; i++) {
- rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
+ rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
}
return result;
}
@@ -5706,13 +5838,13 @@ env_select(VALUE ehash)
result = rb_hash_new();
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);
- if (!NIL_P(val)) {
- if (RTEST(rb_yield_values(2, key, val))) {
- rb_hash_aset(result, key, val);
- }
- }
+ VALUE key = RARRAY_AREF(keys, i);
+ VALUE val = rb_f_getenv(Qnil, key);
+ if (!NIL_P(val)) {
+ if (RTEST(rb_yield_values(2, key, val))) {
+ rb_hash_aset(result, key, val);
+ }
+ }
}
RB_GC_GUARD(keys);
@@ -5767,13 +5899,13 @@ env_select_bang(VALUE ehash)
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));
- if (!NIL_P(val)) {
- if (!RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
+ VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
+ if (!NIL_P(val)) {
+ if (!RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
env_delete(RARRAY_AREF(keys, i));
- del++;
- }
- }
+ del++;
+ }
+ }
}
RB_GC_GUARD(keys);
if (del == 0) return Qnil;
@@ -5815,7 +5947,7 @@ env_keep_if(VALUE ehash)
* 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]):
+ * (see {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values]):
* ENV.slice('foo', 'bar', :bat) # Raises TypeError (no implicit conversion of Symbol into String)
*/
static VALUE
@@ -5895,27 +6027,30 @@ env_to_s(VALUE _)
static VALUE
env_inspect(VALUE _)
{
- char **env;
- VALUE str, i;
+ VALUE str = rb_str_buf_new2("{");
+ rb_encoding *enc = env_encoding();
- str = rb_str_buf_new2("{");
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
-
- if (env != environ) {
- rb_str_buf_cat2(str, ", ");
- }
- if (s) {
- rb_str_buf_cat2(str, "\"");
- rb_str_buf_cat(str, *env, s-*env);
- rb_str_buf_cat2(str, "\"=>");
- i = rb_inspect(rb_str_new2(s+1));
- rb_str_buf_append(str, i);
- }
- env++;
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (*env) {
+ const char *s = strchr(*env, '=');
+
+ if (env != environ) {
+ rb_str_buf_cat2(str, ", ");
+ }
+ if (s) {
+ rb_str_buf_append(str, rb_str_inspect(env_enc_str_new(*env, s-*env, enc)));
+ rb_str_buf_cat2(str, "=>");
+ s++;
+ rb_str_buf_append(str, rb_str_inspect(env_enc_str_new(s, strlen(s), enc)));
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
rb_str_buf_cat2(str, "}");
return str;
@@ -5933,20 +6068,23 @@ env_inspect(VALUE _)
static VALUE
env_to_a(VALUE _)
{
- char **env;
- VALUE ary;
+ VALUE ary = rb_ary_new();
- ary = rb_ary_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
- env_str_new2(s+1)));
- }
- env++;
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
+ env_str_new2(s+1)));
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
return ary;
}
@@ -5964,6 +6102,22 @@ env_none(VALUE _)
return Qnil;
}
+static int
+env_size_with_lock(void)
+{
+ int i = 0;
+
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (env[i]) i++;
+ FREE_ENVIRON(environ);
+ }
+ ENV_UNLOCK();
+
+ return i;
+}
+
/*
* call-seq:
* ENV.length -> an_integer
@@ -5977,14 +6131,7 @@ env_none(VALUE _)
static VALUE
env_size(VALUE _)
{
- int i;
- char **env;
-
- env = GET_ENVIRON(environ);
- for (i=0; env[i]; i++)
- ;
- FREE_ENVIRON(environ);
- return INT2FIX(i);
+ return INT2FIX(env_size_with_lock());
}
/*
@@ -6000,15 +6147,19 @@ env_size(VALUE _)
static VALUE
env_empty_p(VALUE _)
{
- char **env;
+ bool empty = true;
- env = GET_ENVIRON(environ);
- if (env[0] == 0) {
- FREE_ENVIRON(environ);
- return Qtrue;
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ if (env[0] != 0) {
+ empty = false;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
- return Qfalse;
+ ENV_UNLOCK();
+
+ return RBOOL(empty);
}
/*
@@ -6039,10 +6190,8 @@ env_empty_p(VALUE _)
static VALUE
env_has_key(VALUE env, VALUE key)
{
- const char *s;
-
- s = env_name(key);
- return RBOOL(getenv(s));
+ const char *s = env_name(key);
+ return RBOOL(has_env_with_lock(s));
}
/*
@@ -6068,12 +6217,15 @@ env_has_key(VALUE env, VALUE key)
static VALUE
env_assoc(VALUE env, VALUE key)
{
- const char *s, *e;
+ const char *s = env_name(key);
+ VALUE e = getenv_with_lock(s);
- s = env_name(key);
- e = getenv(s);
- if (e) return rb_assoc_new(key, env_str_new2(e));
- return Qnil;
+ if (!NIL_P(e)) {
+ return rb_assoc_new(key, e);
+ }
+ else {
+ return Qnil;
+ }
}
/*
@@ -6091,24 +6243,30 @@ env_assoc(VALUE env, VALUE key)
static VALUE
env_has_value(VALUE dmy, VALUE obj)
{
- char **env;
-
obj = rb_check_string_type(obj);
if (NIL_P(obj)) return Qnil;
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s++) {
- long len = strlen(s);
- if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
- FREE_ENVIRON(environ);
- return Qtrue;
- }
- }
- env++;
+
+ VALUE ret = Qfalse;
+
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s++) {
+ long len = strlen(s);
+ if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
+ ret = Qtrue;
+ break;
+ }
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
- return Qfalse;
+ ENV_UNLOCK();
+
+ return ret;
}
/*
@@ -6121,32 +6279,39 @@ env_has_value(VALUE dmy, VALUE obj)
* 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].
+ * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
*
* Returns +nil+ if there is no such environment variable.
*/
static VALUE
env_rassoc(VALUE dmy, VALUE obj)
{
- char **env;
-
obj = rb_check_string_type(obj);
if (NIL_P(obj)) return Qnil;
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s++) {
- long len = strlen(s);
- if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
- VALUE result = rb_assoc_new(rb_str_new(*env, s-*env-1), obj);
- FREE_ENVIRON(environ);
- return result;
- }
- }
- env++;
+
+ VALUE result = Qnil;
+
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+
+ while (*env) {
+ const char *p = *env;
+ char *s = strchr(p, '=');
+ if (s++) {
+ long len = strlen(s);
+ if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
+ result = rb_assoc_new(rb_str_new(p, s-p-1), obj);
+ break;
+ }
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
- return Qnil;
+ ENV_UNLOCK();
+
+ return result;
}
/*
@@ -6157,58 +6322,76 @@ env_rassoc(VALUE dmy, VALUE obj)
* 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].
+ * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
*
* 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].
+ * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
*/
static VALUE
env_key(VALUE dmy, VALUE value)
{
- char **env;
- VALUE str;
-
SafeStringValue(value);
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s++) {
- long len = strlen(s);
- if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
- str = env_str_new(*env, s-*env-1);
- FREE_ENVIRON(environ);
- return str;
- }
- }
- env++;
+ VALUE str = Qnil;
+
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s++) {
+ long len = strlen(s);
+ if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
+ str = env_str_new(*env, s-*env-1);
+ break;
+ }
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
- return Qnil;
+ ENV_UNLOCK();
+
+ return str;
}
static VALUE
env_to_hash(void)
{
- char **env;
- VALUE hash;
+ VALUE hash = rb_hash_new();
- hash = rb_hash_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- rb_hash_aset(hash, env_str_new(*env, s-*env),
- env_str_new2(s+1));
- }
- env++;
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ while (*env) {
+ char *s = strchr(*env, '=');
+ if (s) {
+ rb_hash_aset(hash, env_str_new(*env, s-*env),
+ env_str_new2(s+1));
+ }
+ env++;
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
return hash;
}
+VALUE
+rb_envtbl(void)
+{
+ return envtbl;
+}
+
+VALUE
+rb_env_to_hash(void)
+{
+ return env_to_hash();
+}
+
/*
* call-seq:
* ENV.to_hash -> hash of name/value pairs
@@ -6322,27 +6505,36 @@ env_freeze(VALUE self)
* ENV.shift # => ['bar', '1']
* ENV.to_hash # => {'foo' => '0'}
* Exactly which environment variable is "first" is OS-dependent.
- * See {About Ordering}[#class-ENV-label-About+Ordering].
+ * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
*
* Returns +nil+ if the environment is empty.
*/
static VALUE
env_shift(VALUE _)
{
- char **env;
VALUE result = Qnil;
+ VALUE key = Qnil;
- env = GET_ENVIRON(environ);
- if (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- VALUE key = env_str_new(*env, s-*env);
- VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
- env_delete(key);
- result = rb_assoc_new(key, val);
- }
+ ENV_LOCK();
+ {
+ char **env = GET_ENVIRON(environ);
+ if (*env) {
+ const char *p = *env;
+ char *s = strchr(p, '=');
+ if (s) {
+ key = env_str_new(p, s-p);
+ VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
+ result = rb_assoc_new(key, val);
+ }
+ }
+ FREE_ENVIRON(environ);
}
- FREE_ENVIRON(environ);
+ ENV_UNLOCK();
+
+ if (!NIL_P(key)) {
+ env_delete(key);
+ }
+
return result;
}
@@ -6359,7 +6551,7 @@ env_shift(VALUE _)
* 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].
+ * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
*/
static VALUE
env_invert(VALUE _)
@@ -6409,7 +6601,7 @@ env_replace_i(VALUE key, VALUE val, VALUE keys)
* 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]):
+ * (see {Invalid Names and Values}[rdoc-ref:ENV@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"}
@@ -6444,7 +6636,7 @@ env_update_block_i(VALUE key, VALUE val, VALUE _)
{
VALUE oldval = rb_f_getenv(Qnil, key);
if (!NIL_P(oldval)) {
- val = rb_yield_values(3, key, oldval, val);
+ val = rb_yield_values(3, key, oldval, val);
}
env_aset(key, val);
return ST_CONTINUE;
@@ -6452,10 +6644,12 @@ env_update_block_i(VALUE key, VALUE val, VALUE _)
/*
* call-seq:
- * 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 -> ENV
+ * ENV.update(*hashes) -> ENV
+ * ENV.update(*hashes) { |name, env_val, hash_val| block } -> ENV
+ * ENV.merge! -> ENV
+ * ENV.merge!(*hashes) -> ENV
+ * ENV.merge!(*hashes) { |name, env_val, hash_val| block } -> ENV
*
* ENV.update is an alias for ENV.merge!.
*
@@ -6471,14 +6665,14 @@ env_update_block_i(VALUE key, VALUE val, 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]);
+ * (see {Invalid Names and Values}[rdoc-ref:ENV@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]):
+ * (see {Invalid Names and Values}[rdoc-ref:ENV@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"}
*
@@ -6487,41 +6681,39 @@ env_update_block_i(VALUE key, VALUE val, VALUE _)
* those following are ignored.
*/
static VALUE
-env_update(VALUE env, VALUE hash)
+env_update(int argc, VALUE *argv, VALUE env)
{
- if (env == hash) return env;
- hash = to_hash(hash);
rb_foreach_func *func = rb_block_given_p() ?
env_update_block_i : env_update_i;
- rb_hash_foreach(hash, func, 0);
+ for (int i = 0; i < argc; ++i) {
+ VALUE hash = argv[i];
+ if (env == hash) continue;
+ hash = to_hash(hash);
+ rb_hash_foreach(hash, func, 0);
+ }
return env;
}
+NORETURN(static VALUE env_clone(int, VALUE *, VALUE));
/*
* call-seq:
- * ENV.clone(freeze: nil) -> ENV
+ * ENV.clone(freeze: nil) # raises TypeError
*
- * Returns ENV itself, and warns because ENV is a wrapper for the
- * process-wide environment variables and a clone is useless.
- * If +freeze+ keyword is given and not +nil+ or +false+, raises ArgumentError.
- * If +freeze+ keyword is given and +true+, raises TypeError, as ENV storage
- * cannot be frozen.
+ * Raises TypeError, because ENV is a wrapper for the process-wide
+ * environment variables and a clone is useless.
+ * Use #to_h to get a copy of ENV data as a hash.
*/
static VALUE
env_clone(int argc, VALUE *argv, VALUE obj)
{
if (argc) {
- VALUE opt, kwfreeze;
+ VALUE opt;
if (rb_scan_args(argc, argv, "0:", &opt) < argc) {
- kwfreeze = rb_get_freeze_opt(1, &opt);
- if (RTEST(kwfreeze)) {
- rb_raise(rb_eTypeError, "cannot freeze ENV");
- }
+ rb_get_freeze_opt(1, &opt);
}
}
- rb_warn_deprecated("ENV.clone", "ENV.to_h");
- return envtbl;
+ rb_raise(rb_eTypeError, "Cannot clone ENV, use ENV.to_h to get a copy of ENV as a hash");
}
NORETURN(static VALUE env_dup(VALUE));
@@ -6538,6 +6730,17 @@ env_dup(VALUE obj)
rb_raise(rb_eTypeError, "Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash");
}
+static const rb_data_type_t env_data_type = {
+ "ENV",
+ {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
/*
* A \Hash maps each of its unique keys to a specific value.
*
@@ -6575,6 +6778,14 @@ env_dup(VALUE obj)
* # Raises SyntaxError (syntax error, unexpected ':', expecting =>):
* h = {0: 'zero'}
*
+ * Hash value can be omitted, meaning that value will be fetched from the context
+ * by the name of the key:
+ *
+ * x = 0
+ * y = 100
+ * h = {x:, y:}
+ * h # => {:x=>0, :y=>100}
+ *
* === Common Uses
*
* You can use a \Hash to give names to objects:
@@ -6608,13 +6819,13 @@ env_dup(VALUE obj)
*
* === Creating a \Hash
*
- * Here are three ways to create a \Hash:
+ * You can create a \Hash object explicitly with:
*
- * - \Method <tt>Hash.new</tt>
- * - \Method <tt>Hash[]</tt>
- * - Literal form: <tt>{}</tt>.
+ * - A {hash literal}[rdoc-ref:syntax/literals.rdoc@Hash+Literals].
*
- * ---
+ * You can convert certain objects to Hashes with:
+ *
+ * - \Method #Hash.
*
* You can create a \Hash by calling method Hash.new.
*
@@ -6624,8 +6835,6 @@ env_dup(VALUE obj)
* h # => {}
* h.class # => Hash
*
- * ---
- *
* You can create a \Hash by calling method Hash.[].
*
* Create an empty Hash:
@@ -6638,8 +6847,6 @@ env_dup(VALUE obj)
* 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:
@@ -6882,129 +7089,129 @@ env_dup(VALUE obj)
*
* First, what's elsewhere. \Class \Hash:
*
- * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
- * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
* Here, class \Hash provides methods that are useful for:
*
- * - {Creating a Hash}[#class-Hash-label-Methods+for+Creating+a+Hash]
- * - {Setting Hash State}[#class-Hash-label-Methods+for+Setting+Hash+State]
- * - {Querying}[#class-Hash-label-Methods+for+Querying]
- * - {Comparing}[#class-Hash-label-Methods+for+Comparing]
- * - {Fetching}[#class-Hash-label-Methods+for+Fetching]
- * - {Assigning}[#class-Hash-label-Methods+for+Assigning]
- * - {Deleting}[#class-Hash-label-Methods+for+Deleting]
- * - {Iterating}[#class-Hash-label-Methods+for+Iterating]
- * - {Converting}[#class-Hash-label-Methods+for+Converting]
- * - {Transforming Keys and Values}[#class-Hash-label-Methods+for+Transforming+Keys+and+Values]
- * - {And more....}[#class-Hash-label-Other+Methods]
+ * - {Creating a Hash}[rdoc-ref:Hash@Methods+for+Creating+a+Hash]
+ * - {Setting Hash State}[rdoc-ref:Hash@Methods+for+Setting+Hash+State]
+ * - {Querying}[rdoc-ref:Hash@Methods+for+Querying]
+ * - {Comparing}[rdoc-ref:Hash@Methods+for+Comparing]
+ * - {Fetching}[rdoc-ref:Hash@Methods+for+Fetching]
+ * - {Assigning}[rdoc-ref:Hash@Methods+for+Assigning]
+ * - {Deleting}[rdoc-ref:Hash@Methods+for+Deleting]
+ * - {Iterating}[rdoc-ref:Hash@Methods+for+Iterating]
+ * - {Converting}[rdoc-ref:Hash@Methods+for+Converting]
+ * - {Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values]
+ * - {And more....}[rdoc-ref:Hash@Other+Methods]
*
* \Class \Hash also includes methods from module Enumerable.
*
* ==== Methods for Creating a \Hash
*
- * ::[]:: Returns a new hash populated with given objects.
- * ::new:: Returns a new empty hash.
- * ::try_convert:: Returns a new hash created from a given object.
+ * - ::[]: Returns a new hash populated with given objects.
+ * - ::new: Returns a new empty hash.
+ * - ::try_convert: Returns a new hash created from a given object.
*
* ==== Methods for Setting \Hash State
*
- * #compare_by_identity:: Sets +self+ to consider only identity in comparing keys.
- * #default=:: Sets the default to a given value.
- * #default_proc=:: Sets the default proc to a given proc.
- * #rehash:: Rebuilds the hash table by recomputing the hash index for each key.
+ * - #compare_by_identity: Sets +self+ to consider only identity in comparing keys.
+ * - #default=: Sets the default to a given value.
+ * - #default_proc=: Sets the default proc to a given proc.
+ * - #rehash: Rebuilds the hash table by recomputing the hash index for each key.
*
* ==== Methods for Querying
*
- * #any?:: Returns whether any element satisfies a given criterion.
- * #compare_by_identity?:: Returns whether the hash considers only identity when comparing keys.
- * #default:: Returns the default value, or the default value for a given key.
- * #default_proc:: Returns the default proc.
- * #empty?:: Returns whether there are no entries.
- * #eql?:: Returns whether a given object is equal to +self+.
- * #hash:: Returns the integer hash code.
- * #has_value?:: Returns whether a given object is a value in +self+.
- * #include?, #has_key?, #member?, #key?:: Returns whether a given object is a key in +self+.
- * #length, #size:: Returns the count of entries.
- * #value?:: Returns whether a given object is a value in +self+.
+ * - #any?: Returns whether any element satisfies a given criterion.
+ * - #compare_by_identity?: Returns whether the hash considers only identity when comparing keys.
+ * - #default: Returns the default value, or the default value for a given key.
+ * - #default_proc: Returns the default proc.
+ * - #empty?: Returns whether there are no entries.
+ * - #eql?: Returns whether a given object is equal to +self+.
+ * - #hash: Returns the integer hash code.
+ * - #has_value?: Returns whether a given object is a value in +self+.
+ * - #include?, #has_key?, #member?, #key?: Returns whether a given object is a key in +self+.
+ * - #length, #size: Returns the count of entries.
+ * - #value?: Returns whether a given object is a value in +self+.
*
* ==== Methods for Comparing
*
- * {#<}[#method-i-3C]:: Returns whether +self+ is a proper subset of a given object.
- * {#<=}[#method-i-3C-3D]:: Returns whether +self+ is a subset of a given object.
- * {#==}[#method-i-3D-3D]:: Returns whether a given object is equal to +self+.
- * {#>}[#method-i-3E]:: Returns whether +self+ is a proper superset of a given object
- * {#>=}[#method-i-3E-3D]:: Returns whether +self+ is a proper superset of a given object.
+ * - #<: Returns whether +self+ is a proper subset of a given object.
+ * - #<=: Returns whether +self+ is a subset of a given object.
+ * - #==: Returns whether a given object is equal to +self+.
+ * - #>: Returns whether +self+ is a proper superset of a given object
+ * - #>=: Returns whether +self+ is a proper superset of a given object.
*
* ==== Methods for Fetching
*
- * #[]:: Returns the value associated with a given key.
- * #assoc:: Returns a 2-element array containing a given key and its value.
- * #dig:: Returns the object in nested objects that is specified
- * by a given key and additional arguments.
- * #fetch:: Returns the value for a given key.
- * #fetch_values:: Returns array containing the values associated with given keys.
- * #key:: Returns the key for the first-found entry with a given value.
- * #keys:: Returns an array containing all keys in +self+.
- * #rassoc:: Returns a 2-element array consisting of the key and value
- of the first-found entry having a given value.
- * #values:: Returns an array containing all values in +self+/
- * #values_at:: Returns an array containing values for given keys.
+ * - #[]: Returns the value associated with a given key.
+ * - #assoc: Returns a 2-element array containing a given key and its value.
+ * - #dig: Returns the object in nested objects that is specified
+ * by a given key and additional arguments.
+ * - #fetch: Returns the value for a given key.
+ * - #fetch_values: Returns array containing the values associated with given keys.
+ * - #key: Returns the key for the first-found entry with a given value.
+ * - #keys: Returns an array containing all keys in +self+.
+ * - #rassoc: Returns a 2-element array consisting of the key and value
+ of the first-found entry having a given value.
+ * - #values: Returns an array containing all values in +self+/
+ * - #values_at: Returns an array containing values for given keys.
*
* ==== Methods for Assigning
*
- * #[]=, #store:: Associates a given key with a given value.
- * #merge:: Returns the hash formed by merging each given hash into a copy of +self+.
- * #merge!, #update:: Merges each given hash into +self+.
- * #replace:: Replaces the entire contents of +self+ with the contents of a givan hash.
+ * - #[]=, #store: Associates a given key with a given value.
+ * - #merge: Returns the hash formed by merging each given hash into a copy of +self+.
+ * - #merge!, #update: Merges each given hash into +self+.
+ * - #replace: Replaces the entire contents of +self+ with the contents of a given hash.
*
* ==== Methods for Deleting
*
* These methods remove entries from +self+:
*
- * #clear:: Removes all entries from +self+.
- * #compact!:: Removes all +nil+-valued entries from +self+.
- * #delete:: Removes the entry for a given key.
- * #delete_if:: Removes entries selected by a given block.
- * #filter!, #select!:: Keep only those entries selected by a given block.
- * #keep_if:: Keep only those entries selected by a given block.
- * #reject!:: Removes entries selected by a given block.
- * #shift:: Removes and returns the first entry.
+ * - #clear: Removes all entries from +self+.
+ * - #compact!: Removes all +nil+-valued entries from +self+.
+ * - #delete: Removes the entry for a given key.
+ * - #delete_if: Removes entries selected by a given block.
+ * - #filter!, #select!: Keep only those entries selected by a given block.
+ * - #keep_if: Keep only those entries selected by a given block.
+ * - #reject!: Removes entries selected by a given block.
+ * - #shift: Removes and returns the first entry.
*
* These methods return a copy of +self+ with some entries removed:
*
- * #compact:: Returns a copy of +self+ with all +nil+-valued entries removed.
- * #except:: Returns a copy of +self+ with entries removed for specified keys.
- * #filter, #select:: Returns a copy of +self+ with only those entries selected by a given block.
- * #reject:: Returns a copy of +self+ with entries removed as specified by a given block.
- * #slice:: Returns a hash containing the entries for given keys.
+ * - #compact: Returns a copy of +self+ with all +nil+-valued entries removed.
+ * - #except: Returns a copy of +self+ with entries removed for specified keys.
+ * - #filter, #select: Returns a copy of +self+ with only those entries selected by a given block.
+ * - #reject: Returns a copy of +self+ with entries removed as specified by a given block.
+ * - #slice: Returns a hash containing the entries for given keys.
*
* ==== Methods for Iterating
- * #each, #each_pair:: Calls a given block with each key-value pair.
- * #each_key:: Calls a given block with each key.
- * #each_value:: Calls a given block with each value.
+ * - #each, #each_pair: Calls a given block with each key-value pair.
+ * - #each_key: Calls a given block with each key.
+ * - #each_value: Calls a given block with each value.
*
* ==== Methods for Converting
*
- * #inspect, #to_s:: Returns a new String containing the hash entries.
- * #to_a:: Returns a new array of 2-element arrays;
- * each nested array contains a key-value pair from +self+.
- * #to_h:: Returns +self+ if a \Hash;
- * if a subclass of \Hash, returns a \Hash containing the entries from +self+.
- * #to_hash:: Returns +self+.
- * #to_proc:: Returns a proc that maps a given key to its value.
+ * - #inspect, #to_s: Returns a new String containing the hash entries.
+ * - #to_a: Returns a new array of 2-element arrays;
+ * each nested array contains a key-value pair from +self+.
+ * - #to_h: Returns +self+ if a \Hash;
+ * if a subclass of \Hash, returns a \Hash containing the entries from +self+.
+ * - #to_hash: Returns +self+.
+ * - #to_proc: Returns a proc that maps a given key to its value.
*
* ==== Methods for Transforming Keys and Values
*
- * #transform_keys:: Returns a copy of +self+ with modified keys.
- * #transform_keys!:: Modifies keys in +self+
- * #transform_values:: Returns a copy of +self+ with modified values.
- * #transform_values!:: Modifies values in +self+.
+ * - #transform_keys: Returns a copy of +self+ with modified keys.
+ * - #transform_keys!: Modifies keys in +self+
+ * - #transform_values: Returns a copy of +self+ with modified values.
+ * - #transform_values!: Modifies values in +self+.
*
* ==== Other Methods
- * #flatten:: Returns an array that is a 1-dimensional flattening of +self+.
- * #invert:: Returns a hash with the each key-value pair inverted.
+ * - #flatten: Returns an array that is a 1-dimensional flattening of +self+.
+ * - #invert: Returns a hash with the each key-value pair inverted.
*
*/
@@ -7012,7 +7219,6 @@ void
Init_Hash(void)
{
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();
@@ -7190,6 +7396,86 @@ Init_Hash(void)
* so most example snippets begin by resetting the contents of ENV:
* - ENV.replace replaces ENV with a new collection of entries.
* - ENV.clear empties ENV.
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere. \Class \ENV:
+ *
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Extends {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
+ *
+ * Here, class \ENV provides methods that are useful for:
+ *
+ * - {Querying}[rdoc-ref:ENV@Methods+for+Querying]
+ * - {Assigning}[rdoc-ref:ENV@Methods+for+Assigning]
+ * - {Deleting}[rdoc-ref:ENV@Methods+for+Deleting]
+ * - {Iterating}[rdoc-ref:ENV@Methods+for+Iterating]
+ * - {Converting}[rdoc-ref:ENV@Methods+for+Converting]
+ * - {And more ....}[rdoc-ref:ENV@More+Methods]
+ *
+ * === Methods for Querying
+ *
+ * - ::[]: Returns the value for the given environment variable name if it exists:
+ * - ::empty?: Returns whether \ENV is empty.
+ * - ::has_value?, ::value?: Returns whether the given value is in \ENV.
+ * - ::include?, ::has_key?, ::key?, ::member?: Returns whether the given name
+ is in \ENV.
+ * - ::key: Returns the name of the first entry with the given value.
+ * - ::size, ::length: Returns the number of entries.
+ * - ::value?: Returns whether any entry has the given value.
+ *
+ * === Methods for Assigning
+ *
+ * - ::[]=, ::store: Creates, updates, or deletes the named environment variable.
+ * - ::clear: Removes every environment variable; returns \ENV:
+ * - ::update, ::merge!: Adds to \ENV each key/value pair in the given hash.
+ * - ::replace: Replaces the entire content of the \ENV
+ * with the name/value pairs in the given hash.
+ *
+ * === Methods for Deleting
+ *
+ * - ::delete: Deletes the named environment variable name if it exists.
+ * - ::delete_if: Deletes entries selected by the block.
+ * - ::keep_if: Deletes entries not selected by the block.
+ * - ::reject!: Similar to #delete_if, but returns +nil+ if no change was made.
+ * - ::select!, ::filter!: Deletes entries selected by the block.
+ * - ::shift: Removes and returns the first entry.
+ *
+ * === Methods for Iterating
+ *
+ * - ::each, ::each_pair: Calls the block with each name/value pair.
+ * - ::each_key: Calls the block with each name.
+ * - ::each_value: Calls the block with each value.
+ *
+ * === Methods for Converting
+ *
+ * - ::assoc: Returns a 2-element array containing the name and value
+ * of the named environment variable if it exists:
+ * - ::clone: Returns \ENV (and issues a warning).
+ * - ::except: Returns a hash of all name/value pairs except those given.
+ * - ::fetch: Returns the value for the given name.
+ * - ::inspect: Returns the contents of \ENV as a string.
+ * - ::invert: Returns a hash whose keys are the ENV values,
+ and whose values are the corresponding ENV names.
+ * - ::keys: Returns an array of all names.
+ * - ::rassoc: Returns the name and value of the first found entry
+ * that has the given value.
+ * - ::reject: Returns a hash of those entries not rejected by the block.
+ * - ::select, ::filter: Returns a hash of name/value pairs selected by the block.
+ * - ::slice: Returns a hash of the given names and their corresponding values.
+ * - ::to_a: Returns the entries as an array of 2-element Arrays.
+ * - ::to_h: Returns a hash of entries selected by the block.
+ * - ::to_hash: Returns a hash of all entries.
+ * - ::to_s: Returns the string <tt>'ENV'</tt>.
+ * - ::values: Returns all values as an array.
+ * - ::values_at: Returns an array of the values for the given name.
+ *
+ * === More Methods
+ *
+ * - ::dup: Raises an exception.
+ * - ::freeze: Raises an exception.
+ * - ::rehash: Returns +nil+, without modifying \ENV.
+ *
*/
/*
@@ -7197,8 +7483,10 @@ Init_Hash(void)
* envtbl = rb_define_class("ENV", rb_cObject);
*/
origenviron = environ;
- envtbl = rb_obj_alloc(rb_cObject);
+ envtbl = TypedData_Wrap_Struct(rb_cObject, &env_data_type, NULL);
rb_extend_object(envtbl, rb_mEnumerable);
+ FL_SET_RAW(envtbl, RUBY_FL_SHAREABLE);
+
rb_define_singleton_method(envtbl, "[]", rb_f_getenv, 1);
rb_define_singleton_method(envtbl, "fetch", env_fetch, -1);
@@ -7224,8 +7512,8 @@ Init_Hash(void)
rb_define_singleton_method(envtbl, "freeze", env_freeze, 0);
rb_define_singleton_method(envtbl, "invert", env_invert, 0);
rb_define_singleton_method(envtbl, "replace", env_replace, 1);
- rb_define_singleton_method(envtbl, "update", env_update, 1);
- rb_define_singleton_method(envtbl, "merge!", env_update, 1);
+ rb_define_singleton_method(envtbl, "update", env_update, -1);
+ rb_define_singleton_method(envtbl, "merge!", env_update, -1);
rb_define_singleton_method(envtbl, "inspect", env_inspect, 0);
rb_define_singleton_method(envtbl, "rehash", env_none, 0);
rb_define_singleton_method(envtbl, "to_a", env_to_a, 0);
diff --git a/hrtime.h b/hrtime.h
index f133bdb1ac..7ed4e6b04c 100644
--- a/hrtime.h
+++ b/hrtime.h
@@ -36,6 +36,7 @@
#define RB_HRTIME_PER_MSEC (RB_HRTIME_PER_USEC * (rb_hrtime_t)1000)
#define RB_HRTIME_PER_SEC (RB_HRTIME_PER_MSEC * (rb_hrtime_t)1000)
#define RB_HRTIME_MAX UINT64_MAX
+#define RB_HRTIME_MIN ((rb_hrtime_t)0)
/*
* Lets try to support time travelers. Lets assume anybody with a time machine
@@ -91,6 +92,15 @@ rb_hrtime_add(rb_hrtime_t a, rb_hrtime_t b)
return c;
}
+static inline rb_hrtime_t
+rb_hrtime_sub(rb_hrtime_t a, rb_hrtime_t b)
+{
+ if (a < b) {
+ return RB_HRTIME_MIN;
+ }
+ return a - b;
+}
+
/*
* convert a timeval struct to rb_hrtime_t, clamping at RB_HRTIME_MAX
*/
@@ -165,4 +175,53 @@ rb_hrtime2timeval(struct timeval *tv, const rb_hrtime_t *hrt)
}
return 0;
}
+
+#include "internal/warnings.h"
+#include "internal/time.h"
+
+/*
+ * Back when we used "struct timeval", not all platforms implemented
+ * tv_sec as time_t. Nowadays we use "struct timespec" and tv_sec
+ * seems to be implemented more consistently across platforms.
+ * At least other parts of our code hasn't had to deal with non-time_t
+ * tv_sec in timespec...
+ */
+#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 inline 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 = 2.0 * (TIMESPEC_SEC_MAX_as_double / 2.0 + 1.0);
+
+ if (TIMESPEC_SEC_MAX_PLUS_ONE <= d) {
+ *hrt = RB_HRTIME_MAX;
+ return NULL;
+ }
+ else if (d <= 0) {
+ *hrt = 0;
+ }
+ else {
+ *hrt = (rb_hrtime_t)(d * (double)RB_HRTIME_PER_SEC);
+ }
+ return hrt;
+}
+
+static inline double
+hrtime2double(rb_hrtime_t hrt)
+{
+ return (double)hrt / (double)RB_HRTIME_PER_SEC;
+}
+
#endif /* RB_HRTIME_H */
diff --git a/id_table.c b/id_table.c
index 149f52cd88..a9a041b955 100644
--- a/id_table.c
+++ b/id_table.c
@@ -85,9 +85,9 @@ rb_id_table_init(struct rb_id_table *tbl, int capa)
{
MEMZERO(tbl, struct rb_id_table, 1);
if (capa > 0) {
- capa = round_capa(capa);
- tbl->capa = (int)capa;
- tbl->items = ZALLOC_N(item_t, capa);
+ capa = round_capa(capa);
+ tbl->capa = (int)capa;
+ tbl->items = ZALLOC_N(item_t, capa);
}
return tbl;
}
@@ -130,16 +130,16 @@ static int
hash_table_index(struct rb_id_table* tbl, id_key_t key)
{
if (tbl->capa > 0) {
- int mask = tbl->capa - 1;
- int ix = key & mask;
- int d = 1;
- while (key != ITEM_GET_KEY(tbl, ix)) {
- if (!ITEM_COLLIDED(tbl, ix))
- return -1;
- ix = (ix + d) & mask;
- d++;
- }
- return ix;
+ int mask = tbl->capa - 1;
+ int ix = key & mask;
+ int d = 1;
+ while (key != ITEM_GET_KEY(tbl, ix)) {
+ if (!ITEM_COLLIDED(tbl, ix))
+ return -1;
+ ix = (ix + d) & mask;
+ d++;
+ }
+ return ix;
}
return -1;
}
@@ -152,13 +152,13 @@ hash_table_raw_insert(struct rb_id_table *tbl, id_key_t key, VALUE val)
int d = 1;
assert(key != 0);
while (ITEM_KEY_ISSET(tbl, ix)) {
- ITEM_SET_COLLIDED(tbl, ix);
- ix = (ix + d) & mask;
- d++;
+ ITEM_SET_COLLIDED(tbl, ix);
+ ix = (ix + d) & mask;
+ d++;
}
tbl->num++;
if (!ITEM_COLLIDED(tbl, ix)) {
- tbl->used++;
+ tbl->used++;
}
ITEM_SET_KEY(tbl, ix, key);
tbl->items[ix].val = val;
@@ -168,16 +168,16 @@ static int
hash_delete_index(struct rb_id_table *tbl, int ix)
{
if (ix >= 0) {
- if (!ITEM_COLLIDED(tbl, ix)) {
- tbl->used--;
- }
- tbl->num--;
- ITEM_SET_KEY(tbl, ix, 0);
- tbl->items[ix].val = 0;
- return TRUE;
+ if (!ITEM_COLLIDED(tbl, ix)) {
+ tbl->used--;
+ }
+ tbl->num--;
+ ITEM_SET_KEY(tbl, ix, 0);
+ tbl->items[ix].val = 0;
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -185,24 +185,24 @@ static void
hash_table_extend(struct rb_id_table* tbl)
{
if (tbl->used + (tbl->used >> 1) >= tbl->capa) {
- int new_cap = round_capa(tbl->num + (tbl->num >> 1));
- int i;
- item_t* old;
- struct rb_id_table tmp_tbl = {0, 0, 0};
- if (new_cap < tbl->capa) {
- new_cap = round_capa(tbl->used + (tbl->used >> 1));
- }
- tmp_tbl.capa = new_cap;
- tmp_tbl.items = ZALLOC_N(item_t, new_cap);
- for (i = 0; i < tbl->capa; i++) {
- id_key_t key = ITEM_GET_KEY(tbl, i);
- if (key != 0) {
- hash_table_raw_insert(&tmp_tbl, key, tbl->items[i].val);
- }
- }
- old = tbl->items;
- *tbl = tmp_tbl;
- xfree(old);
+ int new_cap = round_capa(tbl->num + (tbl->num >> 1));
+ int i;
+ item_t* old;
+ struct rb_id_table tmp_tbl = {0, 0, 0};
+ if (new_cap < tbl->capa) {
+ new_cap = round_capa(tbl->used + (tbl->used >> 1));
+ }
+ tmp_tbl.capa = new_cap;
+ tmp_tbl.items = ZALLOC_N(item_t, new_cap);
+ for (i = 0; i < tbl->capa; i++) {
+ id_key_t key = ITEM_GET_KEY(tbl, i);
+ if (key != 0) {
+ hash_table_raw_insert(&tmp_tbl, key, tbl->items[i].val);
+ }
+ }
+ old = tbl->items;
+ *tbl = tmp_tbl;
+ xfree(old);
}
}
@@ -216,9 +216,9 @@ hash_table_show(struct rb_id_table *tbl)
fprintf(stderr, "tbl: %p (capa: %d, num: %d, used: %d)\n", tbl, tbl->capa, tbl->num, tbl->used);
for (i=0; i<capa; i++) {
- if (ITEM_KEY_ISSET(tbl, i)) {
- fprintf(stderr, " -> [%d] %s %d\n", i, rb_id2name(key2id(keys[i])), (int)keys[i]);
- }
+ if (ITEM_KEY_ISSET(tbl, i)) {
+ fprintf(stderr, " -> [%d] %s %d\n", i, rb_id2name(key2id(keys[i])), (int)keys[i]);
+ }
}
}
#endif
@@ -231,10 +231,10 @@ rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
if (index >= 0) {
*valp = tbl->items[index].val;
- return TRUE;
+ return TRUE;
}
else {
- return FALSE;
+ return FALSE;
}
}
@@ -244,11 +244,11 @@ rb_id_table_insert_key(struct rb_id_table *tbl, const id_key_t key, const VALUE
const int index = hash_table_index(tbl, key);
if (index >= 0) {
- tbl->items[index].val = val;
+ tbl->items[index].val = val;
}
else {
- hash_table_extend(tbl);
- hash_table_raw_insert(tbl, key, val);
+ hash_table_extend(tbl);
+ hash_table_raw_insert(tbl, key, val);
}
return TRUE;
}
@@ -268,20 +268,18 @@ rb_id_table_delete(struct rb_id_table *tbl, ID id)
}
void
-rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, rb_id_table_update_callback_func_t *replace, void *data)
+rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
{
int i, capa = tbl->capa;
for (i=0; i<capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
- enum rb_id_table_iterator_result ret = (*func)(Qundef, tbl->items[i].val, data);
- assert(ITEM_GET_KEY(tbl, i));
+ const id_key_t key = ITEM_GET_KEY(tbl, i);
+ enum rb_id_table_iterator_result ret = (*func)(key2id(key), tbl->items[i].val, data);
+ assert(key != 0);
- if (ret == ID_TABLE_REPLACE) {
- VALUE val = tbl->items[i].val;
- ret = (*replace)(NULL, &val, data, TRUE);
- tbl->items[i].val = val;
- }
+ if (ret == ID_TABLE_DELETE)
+ hash_delete_index(tbl, i);
else if (ret == ID_TABLE_STOP)
return;
}
@@ -289,37 +287,40 @@ rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_fu
}
void
-rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
+rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data)
{
int i, capa = tbl->capa;
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)(key2id(key), tbl->items[i].val, data);
- assert(key != 0);
-
- if (ret == ID_TABLE_DELETE)
- hash_delete_index(tbl, i);
- else if (ret == ID_TABLE_STOP)
- return;
- }
+ if (ITEM_KEY_ISSET(tbl, i)) {
+ enum rb_id_table_iterator_result ret = (*func)(tbl->items[i].val, data);
+
+ if (ret == ID_TABLE_DELETE)
+ hash_delete_index(tbl, i);
+ else if (ret == ID_TABLE_STOP)
+ return;
+ }
}
}
void
-rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data)
+rb_id_table_foreach_values_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, rb_id_table_update_value_callback_func_t *replace, void *data)
{
int i, capa = tbl->capa;
- for (i=0; i<capa; i++) {
- if (ITEM_KEY_ISSET(tbl, i)) {
- enum rb_id_table_iterator_result ret = (*func)(tbl->items[i].val, data);
-
- if (ret == ID_TABLE_DELETE)
- hash_delete_index(tbl, i);
- else if (ret == ID_TABLE_STOP)
- return;
- }
+ for (i = 0; i < capa; i++) {
+ if (ITEM_KEY_ISSET(tbl, i)) {
+ enum rb_id_table_iterator_result ret = (*func)(tbl->items[i].val, data);
+
+ if (ret == ID_TABLE_REPLACE) {
+ VALUE val = tbl->items[i].val;
+ ret = (*replace)(&val, data, TRUE);
+ tbl->items[i].val = val;
+ }
+
+ if (ret == ID_TABLE_STOP)
+ return;
+ }
}
}
+
diff --git a/id_table.h b/id_table.h
index f3dc681d17..f72e2d1d92 100644
--- a/id_table.h
+++ b/id_table.h
@@ -19,18 +19,21 @@ struct rb_id_table *rb_id_table_create(size_t size);
void rb_id_table_free(struct rb_id_table *tbl);
void rb_id_table_clear(struct rb_id_table *tbl);
-size_t rb_id_table_size(const struct rb_id_table *tbl);
size_t rb_id_table_memsize(const struct rb_id_table *tbl);
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val);
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp);
int rb_id_table_delete(struct rb_id_table *tbl, ID id);
-typedef enum rb_id_table_iterator_result rb_id_table_update_callback_func_t(ID *id, VALUE *val, void *data, int existing);
+typedef enum rb_id_table_iterator_result rb_id_table_update_value_callback_func_t(VALUE *val, void *data, int existing);
typedef enum rb_id_table_iterator_result rb_id_table_foreach_func_t(ID id, VALUE val, void *data);
typedef enum rb_id_table_iterator_result rb_id_table_foreach_values_func_t(VALUE val, void *data);
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data);
-void rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, rb_id_table_update_callback_func_t *replace, void *data);
void rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data);
+void rb_id_table_foreach_values_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, rb_id_table_update_value_callback_func_t *replace, void *data);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+size_t rb_id_table_size(const struct rb_id_table *tbl);
+RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_ID_TABLE_H */
diff --git a/include/ruby.h b/include/ruby.h
index 2775c11a40..789804b7b4 100644
--- a/include/ruby.h
+++ b/include/ruby.h
@@ -1,7 +1,6 @@
#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
diff --git a/include/ruby/assert.h b/include/ruby/assert.h
index b0bbdd2c14..0c052363bc 100644
--- a/include/ruby/assert.h
+++ b/include/ruby/assert.h
@@ -18,7 +18,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
*/
#include "ruby/internal/assume.h"
#include "ruby/internal/attr/cold.h"
@@ -103,7 +103,7 @@
# /* keep NDEBUG undefined */
#elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0)
-# /* The (*1) situation in avobe diagram. */
+# /* The (*1) situation in above diagram. */
# define RUBY_DEBUG 0
# define RUBY_NDEBUG 1
# define NDEBUG
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h
index 083f1f6aa0..3eb80fbf7d 100644
--- a/include/ruby/atomic.h
+++ b/include/ruby/atomic.h
@@ -1,236 +1,890 @@
-#ifndef RUBY_ATOMIC_H
+#ifndef RUBY_ATOMIC_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_ATOMIC_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 Atomic operations
+ *
+ * Basically, if we could assume either C11 or C++11, these macros are just
+ * redundant. Sadly we cannot. We have to do them ourselves.
+ */
+
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h> /* size_t */
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* ssize_t */
+#endif
+
+#if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
+# pragma intrinsic(_InterlockedOr)
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+# include <atomic.h>
+#endif
+
+#include "ruby/assert.h"
+#include "ruby/backward/2/limits.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/static_assert.h"
+#include "ruby/internal/stdbool.h"
/*
- * - 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.
+ * Asserts that your environment supports more than one atomic types. These
+ * days systems tend to have such property (C11 was a standard of decades ago,
+ * right?) but we still support older ones.
*/
-#if 0
-#elif defined HAVE_GCC_ATOMIC_BUILTINS
+#if defined(__DOXYGEN__) || defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
+# define RUBY_ATOMIC_GENERIC_MACRO 1
+#endif
+
+/**
+ * Type that is eligible for atomic operations. Depending on your host
+ * platform you might have more than one such type, but we choose one of them
+ * anyways.
+ */
+#if defined(__DOXYGEN__)
+using rb_atomic_t = std::atomic<unsigned>;
+#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 )
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+typedef unsigned int rb_atomic_t;
+#elif defined(_WIN32)
+typedef LONG rb_atomic_t;
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+typedef unsigned int rb_atomic_t;
+#else
+# error No atomic operation found
+#endif
-# define RUBY_ATOMIC_GENERIC_MACRO 1
+/**
+ * Atomically replaces the value pointed by `var` with the result of addition
+ * of `val` to the old value of `var`.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to add.
+ * @return What was stored in `var` before the addition.
+ * @post `var` holds `var + val`.
+ */
+#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val))
+
+/**
+ * Atomically replaces the value pointed by `var` with the result of
+ * subtraction of `val` to the old value of `var`.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to subtract.
+ * @return What was stored in `var` before the subtraction.
+ * @post `var` holds `var - val`.
+ */
+#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val))
+
+/**
+ * Atomically replaces the value pointed by `var` with the result of
+ * bitwise OR between `val` and the old value of `var`.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to mix.
+ * @return void
+ * @post `var` holds `var | val`.
+ * @note For portability, this macro can return void.
+ */
+#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val))
+
+/**
+ * Atomically replaces the value pointed by `var` with `val`. This is just an
+ * assignment, but you can additionally know the previous value.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to set.
+ * @return What was stored in `var` before the assignment.
+ * @post `var` holds `val`.
+ */
+#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val))
+
+/**
+ * Atomic compare-and-swap. This stores `val` to `var` if and only if the
+ * assignment changes the value of `var` from `oldval` to `newval`. You can
+ * detect whether the assignment happened or not using the return value.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param oldval Expected value of `var` before the assignment.
+ * @param newval What you want to store at `var`.
+ * @retval oldval Successful assignment (`var` is now `newval`).
+ * @retval otherwise Something else is at `var`; not updated.
+ */
+#define RUBY_ATOMIC_CAS(var, oldval, newval) \
+ rbimpl_atomic_cas(&(var), (oldval), (newval))
+
+/**
+ * Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to set.
+ * @return void
+ * @post `var` holds `val`.
+ */
+#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_set(&(var), (val))
+
+/**
+ * Identical to #RUBY_ATOMIC_FETCH_ADD, except for the return type.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to add.
+ * @return void
+ * @post `var` holds `var + val`.
+ */
+#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val))
+
+/**
+ * Identical to #RUBY_ATOMIC_FETCH_SUB, except for the return type.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @param val Value to subtract.
+ * @return void
+ * @post `var` holds `var - val`.
+ */
+#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val))
+
+/**
+ * Atomically increments the value pointed by `var`.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @return void
+ * @post `var` holds `var + 1`.
+ */
+#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var))
+
+/**
+ * Atomically decrements the value pointed by `var`.
+ *
+ * @param var A variable of ::rb_atomic_t.
+ * @return void
+ * @post `var` holds `var - 1`.
+ */
+#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var))
+
+/**
+ * Identical to #RUBY_ATOMIC_INC, except it expects its argument is `size_t`.
+ * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `size_t`.
+ * @return void
+ * @post `var` holds `var + 1`.
+ */
+#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var))
+
+/**
+ * Identical to #RUBY_ATOMIC_DEC, except it expects its argument is `size_t`.
+ * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `size_t`.
+ * @return void
+ * @post `var` holds `var - 1`.
+ */
+#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var))
+
+/**
+ * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
+ * `size_t`. There are cases where ::rb_atomic_t is 32bit while `size_t` is
+ * 64bit. This should be used for size related operations to support such
+ * platforms.
+ *
+ * @param var A variable of `size_t`.
+ * @param val Value to set.
+ * @return What was stored in `var` before the assignment.
+ * @post `var` holds `val`.
+ */
+#define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) \
+ rbimpl_atomic_size_exchange(&(var), (val))
+
+/**
+ * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `size_t`.
+ * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `size_t`.
+ * @param oldval Expected value of `var` before the assignment.
+ * @param newval What you want to store at `var`.
+ * @retval oldval Successful assignment (`var` is now `newval`).
+ * @retval otherwise Something else is at `var`; not updated.
+ */
+#define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) \
+ rbimpl_atomic_size_cas(&(var), (oldval), (newval))
+
+/**
+ * Identical to #RUBY_ATOMIC_ADD, except it expects its arguments are `size_t`.
+ * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `size_t`.
+ * @param val Value to add.
+ * @return void
+ * @post `var` holds `var + val`.
+ */
+#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val))
+
+/**
+ * Identical to #RUBY_ATOMIC_SUB, except it expects its arguments are `size_t`.
+ * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `size_t`.
+ * @param val Value to subtract.
+ * @return void
+ * @post `var` holds `var - val`.
+ */
+#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val))
+
+/**
+ * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
+ * `void*`. There are cases where ::rb_atomic_t is 32bit while `void*` is
+ * 64bit. This should be used for pointer related operations to support such
+ * platforms.
+ *
+ * @param var A variable of `void *`.
+ * @param val Value to set.
+ * @return What was stored in `var` before the assignment.
+ * @post `var` holds `val`.
+ *
+ * @internal
+ *
+ * :FIXME: this `(void*)` cast is evil! However `void*` is incompatible with
+ * some pointers, most notably function pointers.
+ */
+#define RUBY_ATOMIC_PTR_EXCHANGE(var, val) \
+ RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val))
+
+/**
+ * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`.
+ * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `void*`.
+ * @param oldval Expected value of `var` before the assignment.
+ * @param newval What you want to store at `var`.
+ * @retval oldval Successful assignment (`var` is now `newval`).
+ * @retval otherwise Something else is at `var`; not updated.
+ */
+#define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) \
+ RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (oldval), (newval)))
+
+/**
+ * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
+ * ::VALUE. There are cases where ::rb_atomic_t is 32bit while ::VALUE is
+ * 64bit. This should be used for pointer related operations to support such
+ * platforms.
+ *
+ * @param var A variable of ::VALUE.
+ * @param val Value to set.
+ * @return What was stored in `var` before the assignment.
+ * @post `var` holds `val`.
+ */
+#define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) \
+ rbimpl_atomic_value_exchange(&(var), (val))
+
+/**
+ * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are ::VALUE.
+ * There are cases where ::rb_atomic_t is 32bit while ::VALUE is 64bit. This
+ * should be used for size related operations to support such platforms.
+ *
+ * @param var A variable of `void*`.
+ * @param oldval Expected value of `var` before the assignment.
+ * @param newval What you want to store at `var`.
+ * @retval oldval Successful assignment (`var` is now `newval`).
+ * @retval otherwise Something else is at `var`; not updated.
+ */
+#define RUBY_ATOMIC_VALUE_CAS(var, oldval, newval) \
+ rbimpl_atomic_value_cas(&(var), (oldval), (newval))
-#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 */
+/** @cond INTERNAL_MACRO */
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline rb_atomic_t
+rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
+{
+#if 0
-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))
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST);
-# define RUBY_ATOMIC_GENERIC_MACRO 1
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_fetch_and_add(ptr, val);
-#elif defined _WIN32
-#if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
-#pragma intrinsic(_InterlockedOr)
+#elif defined(_WIN32)
+ return InterlockedExchangeAdd(ptr, val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ /*
+ * `atomic_add_int_nv` takes its second argument as `int`! Meanwhile our
+ * `rb_atomic_t` is unsigned. We cannot pass `val` as-is. We have to
+ * manually check integer overflow.
+ */
+ RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
+ return atomic_add_int_nv(ptr, val) - val;
+
+#else
+# error Unsupported platform.
#endif
-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))
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
static inline void
-rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
+rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
{
-#ifdef _M_IX86
- __asm mov eax, var;
- __asm mov ecx, val;
- __asm lock or [eax], ecx;
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ /*
+ * GCC on amd64 is smart enough to detect this `__atomic_add_fetch`'s
+ * return value is not used, then compiles it into single `LOCK ADD`
+ * instruction.
+ */
+ __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ __sync_add_and_fetch(ptr, val);
+
+#elif defined(_WIN32)
+ /*
+ * `InterlockedExchangeAdd` is `LOCK XADD`. It seems there also is
+ * `_InterlockedAdd` intrinsic in ARM Windows but not for x86? Sticking to
+ * `InterlockedExchangeAdd` for better portability.
+ */
+ InterlockedExchangeAdd(ptr, val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ /* Ditto for `atomic_add_int_nv`. */
+ RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
+ atomic_add_int(ptr, val);
+
#else
-#error unsupported architecture
+# error Unsupported platform.
#endif
}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_size_add(volatile size_t *ptr, size_t val)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ __sync_add_and_fetch(ptr, val);
+
+#elif defined(_WIN32) && defined(_M_AMD64)
+ /* Ditto for `InterlockeExchangedAdd`. */
+ InterlockedExchangeAdd64(ptr, val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ /* Ditto for `atomic_add_int_nv`. */
+ RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX);
+ atomic_add_long(ptr, val);
+
#else
-# define RUBY_ATOMIC_OR(var, val) _InterlockedOr(&(var), (val))
+ RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t));
+
+ volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
+ rbimpl_atomic_add(tmp, val);
+
#endif
-# 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)
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_inc(volatile rb_atomic_t *ptr)
{
- 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 */
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
+ rbimpl_atomic_add(ptr, 1);
+
+#elif defined(_WIN32)
+ InterlockedIncrement(ptr);
#elif defined(__sun) && defined(HAVE_ATOMIC_H)
-#include <atomic.h>
-typedef unsigned int rb_atomic_t;
+ atomic_inc_uint(ptr);
-# 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))
+#else
+ rbimpl_atomic_add(ptr, 1);
-static inline rb_atomic_t
-rb_atomic_fetch_add(volatile rb_atomic_t *var, rb_atomic_t val)
+#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_size_inc(volatile size_t *ptr)
{
- return atomic_add_int_nv(var, val) - val;
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
+ rbimpl_atomic_size_add(ptr, 1);
+
+#elif defined(_WIN32) && defined(_M_AMD64)
+ InterlockedIncrement64(ptr);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ atomic_inc_ulong(ptr);
+
+#else
+ rbimpl_atomic_size_add(ptr, 1);
+
+#endif
}
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rb_atomic_fetch_sub(volatile rb_atomic_t *var, rb_atomic_t val)
+rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
{
- return atomic_add_int_nv(var, (rb_atomic_t)(-(int)val)) + val;
-}
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_fetch_and_sub(ptr, val);
+
+#elif defined(_WIN32)
+ /* rb_atomic_t is signed here! Safe to do `-val`. */
+ return InterlockedExchangeAdd(ptr, -val);
-# 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
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ /* Ditto for `rbimpl_atomic_fetch_add`. */
+ const signed neg = -1;
+ RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
+ return atomic_add_int_nv(ptr, neg * val) + val;
#else
-# error No atomic operation found
+# error Unsupported platform.
#endif
+}
-#ifndef RUBY_ATOMIC_SET
-# define RUBY_ATOMIC_SET(var, val) (void)RUBY_ATOMIC_EXCHANGE(var, val)
-#endif
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
+{
+#if 0
-#ifndef RUBY_ATOMIC_ADD
-# define RUBY_ATOMIC_ADD(var, val) (void)RUBY_ATOMIC_FETCH_ADD(var, val)
-#endif
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST);
-#ifndef RUBY_ATOMIC_SUB
-# define RUBY_ATOMIC_SUB(var, val) (void)RUBY_ATOMIC_FETCH_SUB(var, val)
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ __sync_sub_and_fetch(ptr, val);
+
+#elif defined(_WIN32)
+ InterlockedExchangeAdd(ptr, -val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ const signed neg = -1;
+ RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
+ atomic_add_int(ptr, neg * val);
+
+#else
+# error Unsupported platform.
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ __sync_sub_and_fetch(ptr, val);
+
+#elif defined(_WIN32) && defined(_M_AMD64)
+ const ssize_t neg = -1;
+ InterlockedExchangeAdd64(ptr, neg * val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ const signed neg = -1;
+ RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX);
+ atomic_add_long(ptr, neg * val);
+
+#else
+ RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t));
+
+ volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
+ rbimpl_atomic_sub(tmp, val);
-#ifndef RUBY_ATOMIC_INC
-# define RUBY_ATOMIC_INC(var) RUBY_ATOMIC_ADD(var, 1)
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_dec(volatile rb_atomic_t *ptr)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
+ rbimpl_atomic_sub(ptr, 1);
+
+#elif defined(_WIN32)
+ InterlockedDecrement(ptr);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ atomic_dec_uint(ptr);
+
+#else
+ rbimpl_atomic_sub(ptr, 1);
-#ifndef RUBY_ATOMIC_DEC
-# define RUBY_ATOMIC_DEC(var) RUBY_ATOMIC_SUB(var, 1)
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_size_dec(volatile size_t *ptr)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
+ rbimpl_atomic_size_sub(ptr, 1);
+
+#elif defined(_WIN32) && defined(_M_AMD64)
+ InterlockedDecrement64(ptr);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ atomic_dec_ulong(ptr);
+
+#else
+ rbimpl_atomic_size_sub(ptr, 1);
-#ifndef RUBY_ATOMIC_SIZE_INC
-# define RUBY_ATOMIC_SIZE_INC(var) RUBY_ATOMIC_INC(var)
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_or_fetch(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ __sync_or_and_fetch(ptr, val);
+
+#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
+ _InterlockedOr(ptr, val);
+
+#elif defined(_WIN32) && defined(__GNUC__)
+ /* This was for old MinGW. Maybe not needed any longer? */
+ __asm__(
+ "lock\n\t"
+ "orl\t%1, %0"
+ : "=m"(ptr)
+ : "Ir"(val));
-#ifndef RUBY_ATOMIC_SIZE_DEC
-# define RUBY_ATOMIC_SIZE_DEC(var) RUBY_ATOMIC_DEC(var)
+#elif defined(_WIN32) && defined(_M_IX86)
+ __asm mov eax, ptr;
+ __asm mov ecx, val;
+ __asm lock or [eax], ecx;
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ atomic_or_uint(ptr, val);
+
+#else
+# error Unsupported platform.
#endif
+}
-#ifndef RUBY_ATOMIC_SIZE_EXCHANGE
-# define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
+/* Nobody uses this but for theoretical backwards compatibility... */
+#if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0)
+static inline rb_atomic_t
+rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
+{
+ return rbimpl_atomic_or(var, val);
+}
#endif
-#ifndef RUBY_ATOMIC_SIZE_CAS
-# define RUBY_ATOMIC_SIZE_CAS(var, oldval, val) RUBY_ATOMIC_CAS(var, oldval, val)
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline rb_atomic_t
+rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_lock_test_and_set(ptr, val);
+
+#elif defined(_WIN32)
+ return InterlockedExchange(ptr, val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ return atomic_swap_uint(ptr, val);
+
+#else
+# error Unsupported platform.
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline size_t
+rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_lock_test_and_set(ptr, val);
+
+#elif defined(_WIN32) && defined(_M_AMD64)
+ return InterlockedExchange64(ptr, val);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ return atomic_swap_ulong(ptr, val);
+
+#else
+ RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
+
+ volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
+ const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val);
+ return RBIMPL_CAST((size_t)ret);
-#ifndef RUBY_ATOMIC_SIZE_ADD
-# define RUBY_ATOMIC_SIZE_ADD(var, val) RUBY_ATOMIC_ADD(var, val)
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void *
+rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val)
+{
+#if 0
+
+#elif defined(InterlockedExchangePointer)
+ /* const_cast */
+ PVOID *pptr = RBIMPL_CAST((PVOID *)ptr);
+ PVOID pval = RBIMPL_CAST((PVOID)val);
+ return InterlockedExchangePointer(pptr, pval);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ return atomic_swap_ptr(ptr, RBIMPL_CAST((void *)val));
+
+#else
+ RBIMPL_STATIC_ASSERT(sizeof_voidp, sizeof *ptr == sizeof(size_t));
+
+ const size_t sval = RBIMPL_CAST((size_t)val);
+ volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
+ const size_t sret = rbimpl_atomic_size_exchange(sptr, sval);
+ return RBIMPL_CAST((void *)sret);
-#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
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline VALUE
+rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val)
+{
+ RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t));
-# ifndef RUBY_ATOMIC_PTR_CAS
-# define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) RUBY_ATOMIC_CAS(var, oldval, newval)
-# endif
+ const size_t sval = RBIMPL_CAST((size_t)val);
+ volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
+ const size_t sret = rbimpl_atomic_size_exchange(sptr, sval);
+ return RBIMPL_CAST((VALUE)sret);
+}
-# ifndef RUBY_ATOMIC_VALUE_EXCHANGE
-# define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
-# endif
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_set(volatile rb_atomic_t *ptr, rb_atomic_t val)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST);
+
+#else
+ /* Maybe std::atomic<rb_atomic_t>::store can be faster? */
+ rbimpl_atomic_exchange(ptr, val);
-# ifndef RUBY_ATOMIC_VALUE_CAS
-# define RUBY_ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_CAS(var, oldval, val)
-# endif
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline rb_atomic_t
+rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_compare_exchange_n(
+ ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ return oldval;
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_val_compare_and_swap(ptr, oldval, newval);
+
+#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
+ return InterlockedCompareExchange(ptr, newval, oldval);
+
+#elif defined(_WIN32)
+ PVOID *pptr = RBIMPL_CAST((PVOID *)ptr);
+ PVOID pold = RBIMPL_CAST((PVOID)oldval);
+ PVOID pnew = RBIMPL_CAST((PVOID)newval);
+ PVOID pret = InterlockedCompareExchange(pptr, pnew, pold);
+ return RBIMPL_CAST((rb_atomic_t)pret);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ return atomic_cas_uint(ptr, oldval, newval);
-#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
+#else
+# error Unsupported platform.
#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
+/* Nobody uses this but for theoretical backwards compatibility... */
+#if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0)
+static inline rb_atomic_t
+rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval)
+{
+ return rbimpl_atomic_cas(var, oldval, newval);
+}
#endif
-#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
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline size_t
+rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval)
+{
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_compare_exchange_n(
+ ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ return oldval;
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_val_compare_and_swap(ptr, oldval, newval);
+
+#elif defined(_WIN32) && defined(_M_AMD64)
+ return InterlockedCompareExchange64(ptr, newval, oldval);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ return atomic_cas_ulong(ptr, oldval, newval);
+
+#else
+ RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
+
+ volatile rb_atomic_t *tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
+ return rbimpl_atomic_cas(tmp, oldval, newval);
+
#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void *
+rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval)
+{
+#if 0
+
+#elif defined(InterlockedExchangePointer)
+ /* ... Can we say that InterlockedCompareExchangePtr surly exists when
+ * InterlockedExchangePointer is defined? Seems so but...?*/
+ PVOID *pptr = RBIMPL_CAST((PVOID *)ptr);
+ PVOID pold = RBIMPL_CAST((PVOID)oldval);
+ PVOID pnew = RBIMPL_CAST((PVOID)newval);
+ return InterlockedCompareExchangePointer(pptr, pnew, pold);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ void *pold = RBIMPL_CAST((void *)oldval);
+ void *pnew = RBIMPL_CAST((void *)newval);
+ return atomic_cas_ptr(ptr, pold, pnew);
+
+
+#else
+ RBIMPL_STATIC_ASSERT(sizeof_voidp, sizeof *ptr == sizeof(size_t));
+
+ const size_t snew = RBIMPL_CAST((size_t)newval);
+ const size_t sold = RBIMPL_CAST((size_t)oldval);
+ volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
+ const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew);
+ return RBIMPL_CAST((void *)sret);
-#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
+}
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline VALUE
+rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval)
+{
+ RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t));
+
+ const size_t snew = RBIMPL_CAST((size_t)newval);
+ const size_t sold = RBIMPL_CAST((size_t)oldval);
+ volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
+ const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew);
+ return RBIMPL_CAST((VALUE)sret);
+}
+/** @endcond */
#endif /* RUBY_ATOMIC_H */
diff --git a/include/ruby/backward.h b/include/ruby/backward.h
index 445f4cc69c..f804c2c36e 100644
--- a/include/ruby/backward.h
+++ b/include/ruby/backward.h
@@ -1,7 +1,6 @@
#ifndef RUBY_RUBY_BACKWARD_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_RUBY_BACKWARD_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
@@ -14,59 +13,13 @@
#define RBIMPL_ATTR_DEPRECATED_SINCE(ver) RBIMPL_ATTR_DEPRECATED(("since " #ver))
#define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal"))
+#define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() RBIMPL_ATTR_DEPRECATED(("only for internal use"))
-/* eval.c */
-RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_disable_super();
-RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_enable_super();
-
-/* hash.c */
-RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_hash_iter_lev();
-RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_hash_ifnone();
-
-/* string.c */
-RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_str_associate();
-RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_str_associated();
-
-/* variable.c */
-RBIMPL_ATTR_DEPRECATED_SINCE(2.5) void rb_autoload();
-
-/* eval.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.6) void rb_frozen_class_p();
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_exec_end_proc();
-
-/* error.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error();
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error_with_enc();
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error_append();
-
-/* gc.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_gc_call_finalizer_at_exit();
-
-/* signal.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_trap_exit();
-
-/* struct.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.4) void rb_struct_ptr();
-
-/* thread.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_clear_trace_func();
-
-/* variable.c */
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_generic_ivar_table();
-RBIMPL_ATTR_DEPRECATED_INTERNAL(2.6) NORETURN(VALUE rb_mod_const_missing(VALUE, VALUE));
+RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() void rb_clear_constant_cache(void);
/* from version.c */
#if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0)
-/* for source code backward compatibility */
-RBIMPL_ATTR_DEPRECATED_SINCE(2.4)
-static inline int
-ruby_show_copyright_to_die(int exitcode)
-{
- ruby_show_copyright();
- return exitcode;
-}
-#define ruby_show_copyright() /* defer EXIT_SUCCESS */ \
- (exit(ruby_show_copyright_to_die(EXIT_SUCCESS)))
+# error RUBY_SHOW_COPYRIGHT_TO_DIE is deprecated
#endif
#endif /* RUBY_RUBY_BACKWARD_H */
diff --git a/include/ruby/backward/2/assume.h b/include/ruby/backward/2/assume.h
index 3fbb81439a..d148710127 100644
--- a/include/ruby/backward/2/assume.h
+++ b/include/ruby/backward/2/assume.h
@@ -17,24 +17,37 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
+#define ASSUME RBIMPL_ASSUME /**< @old{RBIMPL_ASSUME} */
+#define UNREACHABLE RBIMPL_UNREACHABLE() /**< @old{RBIMPL_UNREACHABLE} */
+#define UNREACHABLE_RETURN RBIMPL_UNREACHABLE_RETURN /**< @old{RBIMPL_UNREACHABLE_RETURN} */
/* likely */
#if RBIMPL_HAS_BUILTIN(__builtin_expect)
+/**
+ * Asserts that the given Boolean expression likely holds.
+ *
+ * @param x An expression that likely holds.
+ *
+ * @note Consider this macro carefully. It has been here since when CPUs were
+ * like babies, but contemporary processors are beasts. They are
+ * smarter than mare mortals like us today. Their branch predictions
+ * highly expectedly outperform your use of this macro.
+ */
# define RB_LIKELY(x) (__builtin_expect(!!(x), 1))
-# define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+/**
+ * Asserts that the given Boolean expression likely doesn't hold.
+ *
+ * @param x An expression that likely doesn't hold.
+ */
+# define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0))
#else
# define RB_LIKELY(x) (x)
# define RB_UNLIKELY(x) (x)
diff --git a/include/ruby/backward/2/attributes.h b/include/ruby/backward/2/attributes.h
index 0389f82190..73acfc9dc0 100644
--- a/include/ruby/backward/2/attributes.h
+++ b/include/ruby/backward/2/attributes.h
@@ -1,7 +1,6 @@
#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
@@ -17,7 +16,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Various attribute-related macros.
*
* ### Q&A ###
diff --git a/include/ruby/backward/2/bool.h b/include/ruby/backward/2/bool.h
index 53164eb3b8..f2fa390c80 100644
--- a/include/ruby/backward/2/bool.h
+++ b/include/ruby/backward/2/bool.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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
+ * extension libraries. They could be written in C++98.
+ * @brief Defines old TRUE / FALSE
*/
#include "ruby/internal/stdbool.h"
diff --git a/include/ruby/backward/2/gcc_version_since.h b/include/ruby/backward/2/gcc_version_since.h
index 2a5b76c102..00cc40ca56 100644
--- a/include/ruby/backward/2/gcc_version_since.h
+++ b/include/ruby/backward/2/gcc_version_since.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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
+ * extension libraries. They could be written in C++98.
+ * @brief Defines old GCC_VERSION_SINCE
*/
#include "ruby/internal/compiler_since.h"
diff --git a/include/ruby/backward/2/inttypes.h b/include/ruby/backward/2/inttypes.h
index c1e376a107..45460878bc 100644
--- a/include/ruby/backward/2/inttypes.h
+++ b/include/ruby/backward/2/inttypes.h
@@ -1,7 +1,6 @@
#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
@@ -17,7 +16,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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 */
diff --git a/include/ruby/backward/2/limits.h b/include/ruby/backward/2/limits.h
index e38009b01a..6f7021e5f4 100644
--- a/include/ruby/backward/2/limits.h
+++ b/include/ruby/backward/2/limits.h
@@ -1,7 +1,6 @@
#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
@@ -17,11 +16,11 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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?
+ * own definition of `CHAR_BIT` today?
*/
#include "ruby/internal/config.h"
diff --git a/include/ruby/backward/2/long_long.h b/include/ruby/backward/2/long_long.h
index 83eabb459c..8e6b2743fc 100644
--- a/include/ruby/backward/2/long_long.h
+++ b/include/ruby/backward/2/long_long.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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.
@@ -29,7 +29,15 @@
#include "ruby/internal/has/warning.h"
#include "ruby/internal/warning_push.h"
-#if RBIMPL_HAS_WARNING("-Wc++11-long-long")
+#if defined(__DOXYGEN__)
+# /** @cond INTERNAL_MACRO */
+# define HAVE_LONG_LONG 1
+# define HAVE_TRUE_LONG_LONG 1
+# /** @endcond */
+# /** @deprecated Just use `long long` directly. */
+# define LONG_LONG long long.
+
+#elif RBIMPL_HAS_WARNING("-Wc++11-long-long")
# define HAVE_TRUE_LONG_LONG 1
# define LONG_LONG \
RBIMPL_WARNING_PUSH() \
diff --git a/include/ruby/backward/2/r_cast.h b/include/ruby/backward/2/r_cast.h
index 4600699a9e..3d0f40fd1e 100644
--- a/include/ruby/backward/2/r_cast.h
+++ b/include/ruby/backward/2/r_cast.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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
+ * extension libraries. They could be written in C++98.
+ * @brief Defines old R_CAST
*
* Nobody is actively using this macro.
*/
diff --git a/include/ruby/backward/2/rmodule.h b/include/ruby/backward/2/rmodule.h
index a3e2d39f35..53b37831c0 100644
--- a/include/ruby/backward/2/rmodule.h
+++ b/include/ruby/backward/2/rmodule.h
@@ -1,7 +1,6 @@
#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
@@ -17,7 +16,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Orphan macros.
*
* These macros seems broken since at least 2011. Nobody (except ruby itself
diff --git a/include/ruby/backward/2/stdalign.h b/include/ruby/backward/2/stdalign.h
index 2d3c333bde..8b491bf564 100644
--- a/include/ruby/backward/2/stdalign.h
+++ b/include/ruby/backward/2/stdalign.h
@@ -17,14 +17,14 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
+#define RUBY_ALIGNAS RBIMPL_ALIGNAS /**< @copydoc RBIMPL_ALIGNAS */
+#define RUBY_ALIGNOF RBIMPL_ALIGNOF /**< @copydoc RBIMPL_ALIGNOF */
#endif /* RUBY_BACKWARD2_STDALIGN_H */
diff --git a/include/ruby/backward/2/stdarg.h b/include/ruby/backward/2/stdarg.h
index 5c5e1b31ce..08659fee47 100644
--- a/include/ruby/backward/2/stdarg.h
+++ b/include/ruby/backward/2/stdarg.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines old #_
*
* Nobody should ever use these macros any longer. No known compilers lack
@@ -25,6 +25,10 @@
*/
#undef _
+/**
+ * @deprecated Nobody practically needs this macro any longer.
+ * @brief This was a transition path from K&R to ANSI.
+ */
#ifdef HAVE_PROTOTYPES
# define _(args) args
#else
@@ -32,12 +36,30 @@
#endif
#undef __
+/**
+ * @deprecated Nobody practically needs this macro any longer.
+ * @brief This was a transition path from K&R to ANSI.
+ */
#ifdef HAVE_STDARG_PROTOTYPES
# define __(args) args
#else
# define __(args) ()
#endif
+/**
+ * Functions declared using this macro take arbitrary arguments, including
+ * void.
+ *
+ * ```CXX
+ * void func(ANYARGS);
+ * ```
+ *
+ * This was a necessary evil when there was no such thing like function
+ * overloading. But it is the 21st century today. People generally need not
+ * use this. Just use a granular typed function.
+ *
+ * @see ruby::backward::cxxanyargs
+ */
#ifdef __cplusplus
#define ANYARGS ...
#else
diff --git a/include/ruby/backward/cxxanyargs.hpp b/include/ruby/backward/cxxanyargs.hpp
index 05f1f275ef..2414b7ae6d 100644
--- a/include/ruby/backward/cxxanyargs.hpp
+++ b/include/ruby/backward/cxxanyargs.hpp
@@ -1,12 +1,12 @@
#ifndef RUBY_BACKWARD_CXXANYARGS_HPP //-*-C++-*-vi:ft=cpp
#define RUBY_BACKWARD_CXXANYARGS_HPP
/// @file
-/// @author \@shyouhei
+/// @author @shyouhei
/// @copyright This file is a part of the programming language Ruby.
/// Permission is hereby granted, to either redistribute and/or
/// modify this file, provided that the conditions mentioned in the
/// file COPYING are met. Consult the file for details.
-/// @note DO NOT MODERNIZE THIS FILE! As the file name implies it is
+/// @note DO NOT MODERNISE THIS FILE! As the file name implies it is
/// meant to be a backwards compatibility shim. Please stick to
/// C++ 98 and never use newer features, like `constexpr`.
/// @brief Provides old prototypes for C++ programs.
@@ -39,7 +39,7 @@ namespace ruby {
/// Backwards compatibility layer.
namespace backward {
-/// Provides ANYARGS deprecation warnings. In C, ANYARGS means there is no
+/// 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
@@ -68,7 +68,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] e Setter function.
/// @note Both functions can be nullptr.
/// @see rb_define_hooked_variable()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline void
rb_define_virtual_variable(const char *q, type *w, void_type *e)
{
@@ -131,7 +131,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] r Setter function.
/// @note Both functions can be nullptr.
/// @see rb_define_virtual_variable()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline void
rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
{
@@ -199,7 +199,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] r Passed to `e`.
/// @return The return value of `q`.
/// @note `e` can be nullptr.
-/// @deprecated This function is obsolated since long before 2.x era. Do not
+/// @deprecated This function is obsoleted since long before 2.x era. Do not
/// use it any longer. rb_block_call() is provided instead.
inline VALUE
rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r)
@@ -227,7 +227,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] y Passed to `t`
/// @return Return value of `q#w(*r,&t)`
/// @note 't' can be nullptr.
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
{
@@ -255,7 +255,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @see rb_ensure()
/// @see rb_rescue2()
/// @see rb_protect()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_rescue(type *q, VALUE w, type *e, VALUE r)
{
@@ -279,7 +279,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @see rb_ensure()
/// @see rb_rescue()
/// @see rb_protect()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_rescue2(type *q, VALUE w, type *e, VALUE r, ...)
{
@@ -305,7 +305,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @see rb_rescue()
/// @see rb_rescue2()
/// @see rb_protect()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_ensure(type *q, VALUE w, type *e, VALUE r)
{
@@ -326,7 +326,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @see rb_protect()
/// @see rb_rb_catch_obj()
/// @see rb_rescue()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_catch(const char *q, type *w, VALUE e)
{
@@ -353,7 +353,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @see rb_protect()
/// @see rb_rb_catch_obj()
/// @see rb_rescue()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_catch_obj(VALUE q, type *w, VALUE e)
{
@@ -366,14 +366,14 @@ rb_catch_obj(VALUE q, type *w, VALUE e)
/// @{
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
-/// @brief Creates a @ref rb_cFiber instance.
+/// @brief Creates a rb_cFiber instance.
/// @param[in] q The fiber body.
/// @param[in] w Passed to `q`.
/// @return What was allocated.
/// @note It makes no sense to pass nullptr to`q`.
/// @see rb_proc_new()
-/// @see rb_thread_creatr()
-/// @deprecated Use glanular typed overload instead.
+/// @see rb_thread_create()
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_fiber_new(type *q, VALUE w)
{
@@ -388,8 +388,8 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @return What was allocated.
/// @note It makes no sense to pass nullptr to`q`.
/// @see rb_fiber_new()
-/// @see rb_thread_creatr()
-/// @deprecated Use glanular typed overload instead.
+/// @see rb_thread_create()
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_proc_new(type *q, VALUE w)
{
@@ -405,7 +405,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @note It makes no sense to pass nullptr to`q`.
/// @see rb_proc_new()
/// @see rb_fiber_new()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline VALUE
rb_thread_create(type *q, void *w)
{
@@ -427,7 +427,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @note It makes no sense to pass nullptr to`w`.
/// @see st_foreach_check()
/// @see rb_hash_foreach()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline int
st_foreach(st_table *q, int_type *w, st_data_t e)
{
@@ -445,7 +445,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @retval 1 Element removed during traversing.
/// @note It makes no sense to pass nullptr to`w`.
/// @see st_foreach()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline int
st_foreach_check(st_table *q, int_type *w, st_data_t e, st_data_t)
{
@@ -461,7 +461,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] e Passed to `w`.
/// @note It makes no sense to pass nullptr to`w`.
/// @see st_foreach_check()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline void
st_foreach_safe(st_table *q, int_type *w, st_data_t e)
{
@@ -477,7 +477,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] e Passed to `w`.
/// @note It makes no sense to pass nullptr to`w`.
/// @see st_foreach()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline void
rb_hash_foreach(VALUE q, int_type *w, VALUE e)
{
@@ -493,7 +493,7 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @param[in] e Passed to `w`.
/// @note It makes no sense to pass nullptr to`w`.
/// @see st_foreach()
-/// @deprecated Use glanular typed overload instead.
+/// @deprecated Use granular typed overload instead.
inline void
rb_ivar_foreach(VALUE q, int_type *w, VALUE e)
{
@@ -541,7 +541,7 @@ struct driver {
RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated")
#endif
/// @copydoc define(VALUE klass, T mid, U func)
- /// @deprecated Pass corrctly typed function instead.
+ /// @deprecated Pass correctly typed function instead.
static inline void
define(VALUE klass, T mid, type func)
{
@@ -594,27 +594,42 @@ struct driver {
/* We could perhaps merge this struct into the one above using variadic
* template parameters if we could assume C++11, but sadly we cannot. */
+/// @copydoc ruby::backward::cxxanyargs::define_method::driver
template<typename T, void (*F)(T mid, type func, int arity)>
struct driver0 {
+
+ /// @brief Defines a method
+ /// @tparam N Arity of the function.
+ /// @tparam U The function in question
template<int N, typename U>
struct engine {
RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated")
+ /// @copydoc define(T mid, U func)
+ /// @deprecated Pass correctly typed function instead.
static inline void
define(T mid, type func)
{
F(mid, func, N);
}
+
+ /// @brief Defines Kernel#mid as func, whose arity is N.
+ /// @param[in] mid Name of the method to define.
+ /// @param[in] func Function that implements klass#mid.
static inline void
define(T mid, U func)
{
F(mid, reinterpret_cast<type *>(func), N);
}
+
+ /// @copydoc define(T mid, U func)
+ /// @deprecated Pass correctly typed function instead.
static inline void
define(T mid, notimpl_type func)
{
F(mid, reinterpret_cast<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)> {};
diff --git a/include/ruby/debug.h b/include/ruby/debug.h
index 16891e8458..f95acdb17e 100644
--- a/include/ruby/debug.h
+++ b/include/ruby/debug.h
@@ -10,6 +10,8 @@
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
*/
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/returns_nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/event.h"
#include "ruby/internal/value.h"
@@ -19,74 +21,634 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
/* Note: This file contains experimental APIs. */
/* APIs can be replaced at Ruby 2.0.1 or later */
+/**
+ * @name Frame-profiling APIs
+ *
+ * @{
+ */
-/* profile frames APIs */
+RBIMPL_ATTR_NONNULL((3))
+/**
+ * Queries mysterious "frame"s of the given range.
+ *
+ * The returned values are opaque backtrace pointers, which you are allowed to
+ * issue a very limited set of operations listed below. Don't call arbitrary
+ * ruby methods.
+ *
+ * @param[in] start Start position (0 means the topmost).
+ * @param[in] limit Number objects of `buff`.
+ * @param[out] buff Return buffer.
+ * @param[out] lines Return buffer.
+ * @return Number of objects filled into `buff`.
+ * @post `buff` is filled with backtrace pointers.
+ * @post `lines` is filled with `__LINE__` of each backtraces.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't like this abuse of ::VALUE. It should have been
+ * `const struct rb_callable_method_entry_struct *`.
+ */
int rb_profile_frames(int start, int limit, VALUE *buff, int *lines);
+
+/**
+ * Queries the path of the passed backtrace.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil The frame is implemented in C etc.
+ * @retval otherwise Where `frame` is running.
+ */
VALUE rb_profile_frame_path(VALUE frame);
+
+/**
+ * Identical to rb_profile_frame_path(), except it tries to expand the
+ * returning path. In case the path is `require`-d from something else
+ * rb_profile_frame_path() can return relative paths. This one tries to avoid
+ * that.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval "<cfunc>" The frame is in C.
+ * @retval RUBY_Qnil Can't infer real path (inside of `eval` etc.).
+ * @retval otherwise Where `frame` is running.
+ */
VALUE rb_profile_frame_absolute_path(VALUE frame);
+
+/**
+ * Queries human-readable "label" string. This is `"<main>"` for the toplevel,
+ * `"<compiled>"` for evaluated ones, method name for methods, class name for
+ * classes.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil Can't infer the label (C etc.).
+ * @retval "<main>" The frame is global toplevel.
+ * @retval "<compiled>" The frame is dynamic.
+ * @retval otherwise Label of the frame.
+ */
VALUE rb_profile_frame_label(VALUE frame);
+
+/**
+ * Identical to rb_profile_frame_label(), except it does not "qualify" the
+ * result. Consider the following backtrace:
+ *
+ * ```ruby
+ * def bar
+ * caller_locations
+ * end
+ *
+ * def foo
+ * [1].map { bar }.first
+ * end
+ *
+ * obj = foo.first
+ * obj.label # => "block in foo"
+ * obj.base_label # => "foo"
+ * ```
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil Can't infer the label (C etc.).
+ * @retval "<main>" The frame is global toplevel.
+ * @retval "<compiled>" The frame is dynamic.
+ * @retval otherwise Base label of the frame.
+ */
VALUE rb_profile_frame_base_label(VALUE frame);
+
+/**
+ * Identical to rb_profile_frame_label(), except it returns a qualified result.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil Can't infer the label (C etc.).
+ * @retval "<main>" The frame is global toplevel.
+ * @retval "<compiled>" The frame is dynamic.
+ * @retval otherwise Qualified label of the frame.
+ *
+ * @internal
+ *
+ * As of writing there is no way to obtain this return value from a Ruby
+ * script. This may change in future (it took 8 years and still no progress,
+ * though).
+ */
VALUE rb_profile_frame_full_label(VALUE frame);
+
+/**
+ * Queries the first line of the method of the passed frame pointer. Can be
+ * handy when for instance a debugger want to display the frame in question.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil Can't infer the line (C etc.).
+ * @retval otherwise Line number of the method in question.
+ */
VALUE rb_profile_frame_first_lineno(VALUE frame);
+
+/**
+ * Queries the class path of the method that the passed frame represents.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil Can't infer the class (global toplevel etc.).
+ * @retval otherwise Class path as in rb_class_path().
+ */
VALUE rb_profile_frame_classpath(VALUE frame);
+
+/**
+ * Queries if the method of the passed frame is a singleton class.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qtrue It is a singleton method.
+ * @retval RUBY_Qfalse Otherwise (normal method/non-method).
+ */
VALUE rb_profile_frame_singleton_method_p(VALUE frame);
+
+/**
+ * Queries the name of the method of the passed frame.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil The frame in question is not a method.
+ * @retval otherwise Name of the method of the frame.
+ */
VALUE rb_profile_frame_method_name(VALUE frame);
+
+/**
+ * Identical to rb_profile_frame_method_name(), except it "qualifies" the
+ * return value with its defining class.
+ *
+ * @param[in] frame What rb_profile_frames() returned.
+ * @retval RUBY_Qnil The frame in question is not a method.
+ * @retval otherwise Qualified name of the method of the frame.
+ */
VALUE rb_profile_frame_qualified_method_name(VALUE frame);
-/* debug inspector APIs */
+/** @} */
+
+/**
+ * @name Debug inspector APIs
+ *
+ * @{
+ */
+
+/** Opaque struct representing a debug inspector. */
typedef struct rb_debug_inspector_struct rb_debug_inspector_t;
-typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *);
+/**
+ * Type of the callback function passed to rb_debug_inspector_open().
+ * Inspection shall happen only inside of them. The passed pointers gets
+ * invalidated once after the callback returns.
+ *
+ * @param[in] dc A debug context.
+ * @param[in,out] data What was passed to rb_debug_inspector_open().
+ * @return What would be the return value of rb_debug_inspector_open().
+ */
+typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void *data);
+
+/**
+ * Prepares, executes, then cleans up a debug session.
+ *
+ * @param[in] func A callback to run inside of a debug session.
+ * @param[in,out] data Passed as-is to `func`.
+ * @return What was returned from `func`.
+ */
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data);
+
+/**
+ * Queries the backtrace object of the context. This is as if you call
+ * `caller_locations` at the point of debugger.
+ *
+ * @param[in] dc A debug context.
+ * @return An array of `Thread::Backtrace::Location` which represents the
+ * current point of execution at `dc`.
+
+ */
+VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
+
+/**
+ * Queries the current receiver of the passed context's upper frame.
+ *
+ * @param[in] dc A debug context.
+ * @param[in] index Index of the frame from top to bottom.
+ * @exception rb_eArgError `index` out of range.
+ * @return The current receiver at `index`-th frame.
+ */
VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index);
+
+/**
+ * Queries the current class of the passed context's upper frame.
+ *
+ * @param[in] dc A debug context.
+ * @param[in] index Index of the frame from top to bottom.
+ * @exception rb_eArgError `index` out of range.
+ * @return The current class at `index`-th frame.
+ */
VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index);
+
+/**
+ * Queries the binding of the passed context's upper frame.
+ *
+ * @param[in] dc A debug context.
+ * @param[in] index Index of the frame from top to bottom.
+ * @exception rb_eArgError `index` out of range.
+ * @return The binding at `index`-th frame.
+ */
VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index);
+
+/**
+ * Queries the instruction sequence of the passed context's upper frame.
+ *
+ * @param[in] dc A debug context.
+ * @param[in] index Index of the frame from top to bottom.
+ * @exception rb_eArgError `index` out of range.
+ * @retval RUBY_Qnil `index`-th frame is not in Ruby (C etc.).
+ * @retval otherwise An instance of `RubyVM::InstructionSequence` which
+ * represents the instruction sequence at `index`-th
+ * frame.
+ */
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index);
-VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
-/* Old style set_trace_func APIs */
+/**
+ * Queries the depth of the passed context's upper frame.
+ *
+ * Note that the depth is not same as the frame index because debug_inspector
+ * skips some special frames but the depth counts all frames.
+ *
+ * @param[in] dc A debug context.
+ * @param[in] index Index of the frame from top to bottom.
+ * @exception rb_eArgError `index` out of range.
+ * @retval The depth at `index`-th frame in Integer.
+ */
+VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index);
+
+// A macro to recognize `rb_debug_inspector_frame_depth()` is available or not
+#define RB_DEBUG_INSPECTOR_FRAME_DEPTH(dc, index) rb_debug_inspector_frame_depth(dc, index)
+
+/**
+ * Return current frmae depth.
+ *
+ * @retval The depth of the current frame in Integer.
+ */
+VALUE rb_debug_inspector_current_depth(void);
+
+/** @} */
+
+/**
+ * @name Old style set_trace_func APIs
+ *
+ * @{
+ */
/* duplicated def of include/ruby/ruby.h */
-void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
-int rb_remove_event_hook(rb_event_hook_func_t func);
+#include "ruby/internal/event.h"
+/**
+ * Identical to rb_remove_event_hook(), except it additionally takes the data
+ * argument. This extra argument is the same as that of rb_add_event_hook(),
+ * and this function removes the hook which matches both arguments at once.
+ *
+ * @param[in] func A callback.
+ * @param[in] data What to be passed to `func`.
+ * @return Number of deleted event hooks.
+ * @note As multiple events can share the same `func` it is quite
+ * possible for the return value to become more than one.
+ */
int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data);
+
+/**
+ * Identical to rb_add_event_hook(), except its effect is limited to the passed
+ * thread. Other threads are not affected by this.
+ *
+ * @param[in] thval An instance of ::rb_cThread.
+ * @param[in] func A callback.
+ * @param[in] events A set of events that `func` should run.
+ * @param[in] data Passed as-is to `func`.
+ * @exception rb_eTypeError `thval` is not a thread.
+ */
void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
+
+/**
+ * Identical to rb_remove_event_hook(), except it additionally takes a thread
+ * argument. This extra argument is the same as that of
+ * rb_thread_add_event_hook(), and this function removes the hook which matches
+ * both arguments at once.
+ *
+ * @param[in] thval An instance of ::rb_cThread.
+ * @param[in] func A callback.
+ * @exception rb_eTypeError `thval` is not a thread.
+ * @return Number of deleted event hooks.
+ * @note As multiple events can share the same `func` it is quite
+ * possible for the return value to become more than one.
+ */
int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func);
+
+/**
+ * Identical to rb_thread_remove_event_hook(), except it additionally takes the
+ * data argument. It can also be seen as a routine identical to
+ * rb_remove_event_hook_with_data(), except it additionally takes the thread.
+ * This function deletes hooks that satisfy all three criteria.
+ *
+ * @param[in] thval An instance of ::rb_cThread.
+ * @param[in] func A callback.
+ * @param[in] data What to be passed to `func`.
+ * @exception rb_eTypeError `thval` is not a thread.
+ * @return Number of deleted event hooks.
+ * @note As multiple events can share the same `func` it is quite
+ * possible for the return value to become more than one.
+ */
int rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data);
-/* TracePoint APIs */
+/** @} */
+/**
+ * @name TracePoint APIs
+ *
+ * @{
+ */
+
+/**
+ * Creates a tracepoint by registering a callback function for one or more
+ * tracepoint events. Once the tracepoint is created, you can use
+ * rb_tracepoint_enable to enable the tracepoint.
+ *
+ * @param[in] target_thread_not_supported_yet Meant for picking the
+ * thread in which the tracepoint is to be created.
+ * However, current implementation ignore this
+ * parameter, tracepoint is created for all threads.
+ * Simply specify Qnil.
+ * @param[in] events Event(s) to listen to.
+ * @param[in] func A callback function.
+ * @param[in,out] data Void pointer that will be passed to the callback
+ * function.
+ *
+ * When the callback function is called, it will be passed 2 parameters:
+ * 1. `VALUE tpval` - the TracePoint object from which trace args can be
+ * extracted.
+ * 1. `void *data` - A void pointer which helps to share scope with the
+ * callback function.
+ *
+ * It is important to note that you cannot register callbacks for normal events
+ * and internal events simultaneously because they are different purpose. You
+ * can use any Ruby APIs (calling methods and so on) on normal event hooks.
+ * However, in internal events, you can not use any Ruby APIs (even object
+ * creations). This is why we can't specify internal events by TracePoint
+ * directly. Limitations are MRI version specific.
+ *
+ * Example:
+ *
+ * ```CXX
+ * rb_tracepoint_new(
+ * Qnil,
+ * RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREEOBJ,
+ * obj_event_i,
+ * data);
+ * ```
+ *
+ * In this example, a callback function `obj_event_i` will be registered for
+ * internal events #RUBY_INTERNAL_EVENT_NEWOBJ and
+ * #RUBY_INTERNAL_EVENT_FREEOBJ.
+ */
VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void (*func)(VALUE, void *), void *data);
+
+/**
+ * Starts (enables) trace(s) defined by the passed object. A TracePoint object
+ * does not immediately take effect on creation. You have to explicitly call
+ * this API.
+ *
+ * @param[in] tpval An instance of TracePoint.
+ * @exception rb_eArgError A trace is already running.
+ * @return Undefined value. Forget this. It should have returned `void`.
+ * @post Trace(s) defined by `tpval` start.
+ */
VALUE rb_tracepoint_enable(VALUE tpval);
+
+/**
+ * Stops (disables) an already running instance of TracePoint.
+ *
+ * @param[in] tpval An instance of TracePoint.
+ * @return Undefined value. Forget this. It should have returned `void`.
+ * @post Trace(s) defined by `tpval` stop.
+ */
VALUE rb_tracepoint_disable(VALUE tpval);
+
+/**
+ * Queries if the passed TracePoint is up and running.
+ *
+ * @param[in] tpval An instance of TracePoint.
+ * @retval RUBY_Qtrue It is.
+ * @retval RUBY_Qfalse It isn't.
+ */
VALUE rb_tracepoint_enabled_p(VALUE tpval);
+/**
+ * Type that represents a specific trace event. Roughly resembles the
+ * tracepoint object that is passed to the block of `TracePoint.new`:
+ *
+ * ```ruby
+ * TracePoint.new(*events) do |obj|
+ * ... # ^^^^^ Resembles this object.
+ * end
+ * ```
+ */
typedef struct rb_trace_arg_struct rb_trace_arg_t;
+
+RBIMPL_ATTR_RETURNS_NONNULL()
+/**
+ * Queries the current event of the passed tracepoint.
+ *
+ * @param[in] tpval An instance of TracePoint.
+ * @exception rb_eRuntimeError `tpval` is disabled.
+ * @return The current event.
+ *
+ * @internal
+ *
+ * `tpval` is a fake. There is only one instance of ::rb_trace_arg_t at one
+ * time. This function just returns that global variable.
+ */
rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the event of the passed trace.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @return Its event.
+ */
rb_event_flag_t rb_tracearg_event_flag(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_tracearg_event_flag(), except it returns the name of the
+ * event in Ruby's symbol.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @return Its event, in Ruby level Symbol object.
+ */
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the line of the point where the trace is at.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @retval 0 The trace is not at Ruby frame.
+ * @return otherwise Its line number.
+ */
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the file name of the point where the trace is at.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @retval RUBY_Qnil The trace is not at Ruby frame.
+ * @retval otherwise Its path.
+ */
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the method name of the point where the trace is at.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @retval RUBY_Qnil There is no method.
+ * @retval otherwise Its method name, in Ruby level Symbol.
+ */
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_tracearg_method_id(), except it returns callee id like
+ * rb_frame_callee().
+ *
+ * @param[in] trace_arg A trace instance.
+ * @retval RUBY_Qnil There is no method.
+ * @retval otherwise Its method name, in Ruby level Symbol.
+ */
VALUE rb_tracearg_callee_id(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the class that defines the method that the passed trace is at. This
+ * can be different from the class of rb_tracearg_self()'s return value because
+ * of inheritance(s).
+ *
+ * @param[in] trace_arg A trace instance.
+ * @retval RUBY_Qnil There is no method.
+ * @retval otherwise Its method's class.
+ */
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Creates a binding object of the point where the trace is at.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @retval RUBY_Qnil The point has no binding.
+ * @retval otherwise Its binding.
+ *
+ * @internal
+ *
+ * @shyouhei has no idea on which situation shall this function return
+ * ::RUBY_Qnil.
+ */
VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the receiver of the point trace is at.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @return Its receiver.
+ */
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the return value that the trace represents.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @exception rb_eRuntimeError The tracing event is not return-related.
+ * @return The return value.
+ */
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the raised exception that the trace represents.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @exception rb_eRuntimeError The tracing event is not exception-related.
+ * @return The raised exception.
+ */
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries the allocated/deallocated object that the trace represents.
+ *
+ * @param[in] trace_arg A trace instance.
+ * @exception rb_eRuntimeError The tracing event is not GC-related.
+ * @return The allocated/deallocated object.
+ */
VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg);
+
+/** @} */
+
+/**
+ * @name Postponed Job API
+ *
+ * @{
+ */
+
/*
* Postponed Job API
* rb_postponed_job_register and rb_postponed_job_register_one are
* async-signal-safe and used via SIGPROF by the "stackprof" RubyGem
*/
+
+/**
+ * Type of postponed jobs.
+ *
+ * @param[in,out] arg What was passed to rb_postponed_job_register().
+ */
typedef void (*rb_postponed_job_func_t)(void *arg);
+
+/**
+ * Registers a postponed job.
+ *
+ * There are situations when running a ruby program is not possible. For
+ * instance when a program is in a signal handler; for another instance when
+ * the GC is busy. On such situations however, there might be needs to do
+ * something. We cannot but defer such operations until we are 100% sure it is
+ * safe to execute them. This mechanism is called postponed jobs. This
+ * function registers a new one. The registered job would eventually gets
+ * executed.
+ *
+ * @param[in] flags (Unused) reserved for future extensions.
+ * @param[in] func Job body.
+ * @param[in,out] data Passed as-is to `func`.
+ * @retval 0 Postponed job buffer is full. Failed.
+ * @retval otherwise Opaque return value.
+ * @post The passed job is postponed.
+ */
int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data);
+
+/**
+ * Identical to rb_postponed_job_register_one(), except it additionally checks
+ * for duplicated registration. In case the passed job is already in the
+ * postponed job buffer this function does nothing.
+ *
+ * @param[in] flags (Unused) reserved for future extensions.
+ * @param[in] func Job body.
+ * @param[in,out] data Passed as-is to `func`.
+ * @retval 0 Postponed job buffer is full. Failed.
+ * @retval otherwise Opaque return value.
+ */
int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data);
+/** @} */
+
+/**
+ * @cond INTERNAL_MACRO
+ *
+ * Anything after this are intentionally left undocumented, to honour the
+ * comment below.
+ */
+
/* undocumented advanced tracing APIs */
typedef enum {
@@ -98,6 +660,8 @@ typedef enum {
void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag);
void rb_thread_add_event_hook2(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag);
+/** @endcond */
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_DEBUG_H */
diff --git a/include/ruby/defines.h b/include/ruby/defines.h
index d632a69fc1..48184f8a18 100644
--- a/include/ruby/defines.h
+++ b/include/ruby/defines.h
@@ -72,23 +72,30 @@
#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"
+/**
+ * Asserts that the compilation unit includes Ruby's CAPI. This has been here
+ * since the very beginning (at least since version 0.49).
+ */
#define RUBY
#ifdef __GNUC__
+# /** This is expanded to nothing for non-GCC compilers. */
# define RB_GNUC_EXTENSION __extension__
+# /** This is expanded to the passed token for non-GCC compilers. */
# define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; })
#else
# define RB_GNUC_EXTENSION
# define RB_GNUC_EXTENSION_BLOCK(x) (x)
#endif
+/** @cond INTERNAL_MACRO */
+
/* :FIXME: Can someone tell us why is this macro defined here? @shyouhei
* thinks this is a truly internal macro but cannot move around because he
* doesn't understand the reason of this arrangement. */
@@ -105,5 +112,5 @@ RBIMPL_SYMBOL_EXPORT_END()
#else
# define FLUSH_REGISTER_WINDOWS ((void)0)
#endif
-
+/** @endcond */
#endif /* RUBY_DEFINES_H */
diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h
index 4e46d0d996..1256393701 100644
--- a/include/ruby/encoding.h
+++ b/include/ruby/encoding.h
@@ -9,403 +9,23 @@
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
+ * @brief Encoding relates APIs.
+ *
+ * These APIs are mainly for implementing encodings themselves. Encodings are
+ * built on top of Ruby's core CAPIs. Though not prohibited, there can be
+ * relatively less rooms for things in this header file be useful when writing
+ * an extension library.
*/
-#include "ruby/internal/config.h"
-#include <stdarg.h>
#include "ruby/ruby.h"
-#include "ruby/oniguruma.h"
-#include "ruby/internal/dllexport.h"
-RBIMPL_SYMBOL_EXPORT_BEGIN()
-
-enum ruby_encoding_consts {
- RUBY_ENCODING_INLINE_MAX = 127,
- RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10),
- RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<<RUBY_ENCODING_SHIFT
- /* RUBY_FL_USER10..RUBY_FL_USER16 */),
- RUBY_ENCODING_MAXNAMELEN = 42
-};
-
-#define ENCODING_INLINE_MAX RUBY_ENCODING_INLINE_MAX
-#define ENCODING_SHIFT RUBY_ENCODING_SHIFT
-#define ENCODING_MASK RUBY_ENCODING_MASK
-
-#define RB_ENCODING_SET_INLINED(obj,i) do {\
- RBASIC(obj)->flags &= ~RUBY_ENCODING_MASK;\
- RBASIC(obj)->flags |= (VALUE)(i) << RUBY_ENCODING_SHIFT;\
-} while (0)
-#define RB_ENCODING_SET(obj,i) rb_enc_set_index((obj), (i))
-
-#define RB_ENCODING_GET_INLINED(obj) \
- (int)((RBASIC(obj)->flags & RUBY_ENCODING_MASK)>>RUBY_ENCODING_SHIFT)
-#define RB_ENCODING_GET(obj) \
- (RB_ENCODING_GET_INLINED(obj) != RUBY_ENCODING_INLINE_MAX ? \
- RB_ENCODING_GET_INLINED(obj) : \
- rb_enc_get_index(obj))
-
-#define RB_ENCODING_IS_ASCII8BIT(obj) (RB_ENCODING_GET_INLINED(obj) == 0)
-
-#define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i)
-#define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i)
-#define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj)
-#define ENCODING_GET(obj) RB_ENCODING_GET(obj)
-#define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj)
-#define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN
-
-enum ruby_coderange_type {
- RUBY_ENC_CODERANGE_UNKNOWN = 0,
- RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8),
- RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9),
- RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)),
- RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT|
- RUBY_ENC_CODERANGE_VALID|
- RUBY_ENC_CODERANGE_BROKEN)
-};
-
-static inline int
-rb_enc_coderange_clean_p(int cr)
-{
- return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT;
-}
-#define RB_ENC_CODERANGE_CLEAN_P(cr) rb_enc_coderange_clean_p(cr)
-#define RB_ENC_CODERANGE(obj) ((int)RBASIC(obj)->flags & RUBY_ENC_CODERANGE_MASK)
-#define RB_ENC_CODERANGE_ASCIIONLY(obj) (RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT)
-#define RB_ENC_CODERANGE_SET(obj,cr) (\
- RBASIC(obj)->flags = \
- (RBASIC(obj)->flags & ~RUBY_ENC_CODERANGE_MASK) | (cr))
-#define RB_ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_SET((obj),0)
-
-/* assumed ASCII compatibility */
-#define RB_ENC_CODERANGE_AND(a, b) \
- ((a) == RUBY_ENC_CODERANGE_7BIT ? (b) : \
- (a) != RUBY_ENC_CODERANGE_VALID ? RUBY_ENC_CODERANGE_UNKNOWN : \
- (b) == RUBY_ENC_CODERANGE_7BIT ? RUBY_ENC_CODERANGE_VALID : (b))
-
-#define RB_ENCODING_CODERANGE_SET(obj, encindex, cr) \
- do { \
- VALUE rb_encoding_coderange_obj = (obj); \
- RB_ENCODING_SET(rb_encoding_coderange_obj, (encindex)); \
- RB_ENC_CODERANGE_SET(rb_encoding_coderange_obj, (cr)); \
- } while (0)
-
-#define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK
-#define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN
-#define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT
-#define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID
-#define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN
-#define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr)
-#define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj)
-#define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj)
-#define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr)
-#define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj)
-#define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b)
-#define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr)
-
-typedef const OnigEncodingType rb_encoding;
-
-int rb_char_to_option_kcode(int c, int *option, int *kcode);
-
-int rb_enc_replicate(const char *, rb_encoding *);
-int rb_define_dummy_encoding(const char *);
-PUREFUNC(int rb_enc_dummy_p(rb_encoding *enc));
-PUREFUNC(int rb_enc_to_index(rb_encoding *enc));
-int rb_enc_get_index(VALUE obj);
-void rb_enc_set_index(VALUE obj, int encindex);
-int rb_enc_capable(VALUE obj);
-int rb_enc_find_index(const char *name);
-int rb_enc_alias(const char *alias, const char *orig);
-int rb_to_encoding_index(VALUE);
-rb_encoding *rb_to_encoding(VALUE);
-rb_encoding *rb_find_encoding(VALUE);
-rb_encoding *rb_enc_get(VALUE);
-rb_encoding *rb_enc_compatible(VALUE,VALUE);
-rb_encoding *rb_enc_check(VALUE,VALUE);
-VALUE rb_enc_associate_index(VALUE, int);
-VALUE rb_enc_associate(VALUE, rb_encoding*);
-void rb_enc_copy(VALUE dst, VALUE src);
-
-VALUE rb_enc_str_new(const char*, long, rb_encoding*);
-VALUE rb_enc_str_new_cstr(const char*, rb_encoding*);
-VALUE rb_enc_str_new_static(const char*, long, rb_encoding*);
-VALUE rb_enc_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);
-long rb_enc_strlen(const char*, const char*, rb_encoding*);
-char* rb_enc_nth(const char*, const char*, long, rb_encoding*);
-VALUE rb_obj_encoding(VALUE);
-VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc);
-VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc);
-
-VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *);
-VALUE rb_str_export_to_enc(VALUE, rb_encoding *);
-VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to);
-VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts);
-
-#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
-#define rb_enc_str_new(str, len, enc) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
- rb_enc_str_new_static((str), (len), (enc)) : \
- rb_enc_str_new((str), (len), (enc)) \
-)
-#define rb_enc_str_new_cstr(str, enc) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_enc_str_new_static((str), (long)strlen(str), (enc)) : \
- rb_enc_str_new_cstr((str), (enc)) \
-)
-#endif
-
-PRINTF_ARGS(NORETURN(void rb_enc_raise(rb_encoding *, VALUE, const char*, ...)), 3, 4);
-
-/* index -> rb_encoding */
-rb_encoding *rb_enc_from_index(int idx);
-
-/* name -> rb_encoding */
-rb_encoding *rb_enc_find(const char *name);
-
-/* rb_encoding * -> name */
-#define rb_enc_name(enc) (enc)->name
-
-/* rb_encoding * -> minlen/maxlen */
-#define rb_enc_mbminlen(enc) (enc)->min_enc_len
-#define rb_enc_mbmaxlen(enc) (enc)->max_enc_len
-
-/* -> mbclen (no error notification: 0 < ret <= e-p, no exception) */
-int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc);
-
-/* -> mbclen (only for valid encoding) */
-int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc);
-
-/* -> chlen, invalid or needmore */
-int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc);
-#define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret)
-#define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret)
-#define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret)
-#define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret)
-#define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret)
-
-/* -> 0x00..0x7f, -1 */
-int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc);
-
-
-/* -> code (and len) or raise exception */
-unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc);
-
-/* prototype for obsolete function */
-unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc);
-/* overriding macro */
-#define rb_enc_codepoint(p,e,enc) rb_enc_codepoint_len((p),(e),0,(enc))
-#define rb_enc_mbc_to_codepoint(p, e, enc) ONIGENC_MBC_TO_CODE((enc),(UChar*)(p),(UChar*)(e))
-
-/* -> codelen>0 or raise exception */
-int rb_enc_codelen(int code, rb_encoding *enc);
-/* -> 0 for invalid codepoint */
-int rb_enc_code_to_mbclen(int code, rb_encoding *enc);
-#define rb_enc_code_to_mbclen(c, enc) ONIGENC_CODE_TO_MBCLEN((enc), (c));
-
-/* code,ptr,encoding -> write buf */
-#define rb_enc_mbcput(c,buf,enc) ONIGENC_CODE_TO_MBC((enc),(c),(UChar*)(buf))
-
-/* start, ptr, end, encoding -> prev_char */
-#define rb_enc_prev_char(s,p,e,enc) ((char *)onigenc_get_prev_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e)))
-/* start, ptr, end, encoding -> next_char */
-#define rb_enc_left_char_head(s,p,e,enc) ((char *)onigenc_get_left_adjust_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e)))
-#define rb_enc_right_char_head(s,p,e,enc) ((char *)onigenc_get_right_adjust_char_head((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e)))
-#define rb_enc_step_back(s,p,e,n,enc) ((char *)onigenc_step_back((enc),(UChar*)(s),(UChar*)(p),(UChar*)(e),(int)(n)))
-
-/* ptr, ptr, encoding -> newline_or_not */
-#define rb_enc_is_newline(p,end,enc) ONIGENC_IS_MBC_NEWLINE((enc),(UChar*)(p),(UChar*)(end))
-
-#define rb_enc_isctype(c,t,enc) ONIGENC_IS_CODE_CTYPE((enc),(c),(t))
-#define rb_enc_isascii(c,enc) ONIGENC_IS_CODE_ASCII(c)
-#define rb_enc_isalpha(c,enc) ONIGENC_IS_CODE_ALPHA((enc),(c))
-#define rb_enc_islower(c,enc) ONIGENC_IS_CODE_LOWER((enc),(c))
-#define rb_enc_isupper(c,enc) ONIGENC_IS_CODE_UPPER((enc),(c))
-#define rb_enc_ispunct(c,enc) ONIGENC_IS_CODE_PUNCT((enc),(c))
-#define rb_enc_isalnum(c,enc) ONIGENC_IS_CODE_ALNUM((enc),(c))
-#define rb_enc_isprint(c,enc) ONIGENC_IS_CODE_PRINT((enc),(c))
-#define rb_enc_isspace(c,enc) ONIGENC_IS_CODE_SPACE((enc),(c))
-#define rb_enc_isdigit(c,enc) ONIGENC_IS_CODE_DIGIT((enc),(c))
-
-static inline int
-rb_enc_asciicompat_inline(rb_encoding *enc)
-{
- return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc);
-}
-#define rb_enc_asciicompat(enc) rb_enc_asciicompat_inline(enc)
-
-CONSTFUNC(int rb_enc_toupper(int c, rb_encoding *enc));
-CONSTFUNC(int rb_enc_tolower(int c, rb_encoding *enc));
-ID rb_intern3(const char*, long, rb_encoding*);
-int rb_enc_symname_p(const char*, rb_encoding*);
-int rb_enc_symname2_p(const char*, long, rb_encoding*);
-int rb_enc_str_coderange(VALUE);
-long rb_str_coderange_scan_restartable(const char*, const char*, rb_encoding*, int*);
-int rb_enc_str_asciionly_p(VALUE);
-#define rb_enc_str_asciicompat_p(str) rb_enc_asciicompat(rb_enc_get(str))
-VALUE rb_enc_from_encoding(rb_encoding *enc);
-PUREFUNC(int rb_enc_unicode_p(rb_encoding *enc));
-rb_encoding *rb_ascii8bit_encoding(void);
-rb_encoding *rb_utf8_encoding(void);
-rb_encoding *rb_usascii_encoding(void);
-rb_encoding *rb_locale_encoding(void);
-rb_encoding *rb_filesystem_encoding(void);
-rb_encoding *rb_default_external_encoding(void);
-rb_encoding *rb_default_internal_encoding(void);
-#ifndef rb_ascii8bit_encindex
-CONSTFUNC(int rb_ascii8bit_encindex(void));
-#endif
-#ifndef rb_utf8_encindex
-CONSTFUNC(int rb_utf8_encindex(void));
-#endif
-#ifndef rb_usascii_encindex
-CONSTFUNC(int rb_usascii_encindex(void));
-#endif
-int rb_locale_encindex(void);
-int rb_filesystem_encindex(void);
-VALUE rb_enc_default_external(void);
-VALUE rb_enc_default_internal(void);
-void rb_enc_set_default_external(VALUE encoding);
-void rb_enc_set_default_internal(VALUE encoding);
-VALUE rb_locale_charmap(VALUE klass);
-long rb_memsearch(const void*,long,const void*,long,rb_encoding*);
-char *rb_enc_path_next(const char *,const char *,rb_encoding*);
-char *rb_enc_path_skip_prefix(const char *,const char *,rb_encoding*);
-char *rb_enc_path_last_separator(const char *,const char *,rb_encoding*);
-char *rb_enc_path_end(const char *,const char *,rb_encoding*);
-const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc);
-const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc);
-ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc);
-VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc);
-
-RUBY_EXTERN VALUE rb_cEncoding;
-
-/* econv stuff */
-
-typedef enum {
- econv_invalid_byte_sequence,
- econv_undefined_conversion,
- econv_destination_buffer_full,
- econv_source_buffer_empty,
- econv_finished,
- econv_after_output,
- econv_incomplete_input
-} rb_econv_result_t;
-
-typedef struct rb_econv_t rb_econv_t;
-
-VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts);
-int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding);
-
-int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags);
-int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts);
-
-rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags);
-rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts);
-
-rb_econv_result_t rb_econv_convert(rb_econv_t *ec,
- const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end,
- unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end,
- int flags);
-void rb_econv_close(rb_econv_t *ec);
-
-/* result: 0:success -1:failure */
-int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname);
-
-/* result: 0:success -1:failure */
-int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name);
-int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name);
-
-VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags);
-
-/* result: 0:success -1:failure */
-int rb_econv_insert_output(rb_econv_t *ec,
- const unsigned char *str, size_t len, const char *str_encoding);
-
-/* encoding that rb_econv_insert_output doesn't need conversion */
-const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec);
-
-/* raise an error if the last rb_econv_convert is error */
-void rb_econv_check_error(rb_econv_t *ec);
-
-/* returns an exception object or nil */
-VALUE rb_econv_make_exception(rb_econv_t *ec);
-
-int rb_econv_putbackable(rb_econv_t *ec);
-void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n);
-
-/* returns the corresponding ASCII compatible encoding for encname,
- * or NULL if encname is not ASCII incompatible encoding. */
-const char *rb_econv_asciicompat_encoding(const char *encname);
-
-VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags);
-VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags);
-VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags);
-VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags);
-VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags);
-
-void rb_econv_binmode(rb_econv_t *ec);
-
-enum ruby_econv_flag_type {
-/* flags for rb_econv_open */
- RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff,
-
- RUBY_ECONV_INVALID_MASK = 0x0000000f,
- RUBY_ECONV_INVALID_REPLACE = 0x00000002,
-
- RUBY_ECONV_UNDEF_MASK = 0x000000f0,
- RUBY_ECONV_UNDEF_REPLACE = 0x00000020,
- RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030,
-
- RUBY_ECONV_DECORATOR_MASK = 0x0000ff00,
- RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00003f00,
- RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00,
- RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00003000,
-
- RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100,
- RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000,
- RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000,
- RUBY_ECONV_XML_TEXT_DECORATOR = 0x00004000,
- RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00008000,
-
- RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000,
- RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000,
-
- RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR =
-#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
- RUBY_ECONV_CRLF_NEWLINE_DECORATOR,
-#else
- 0,
-#endif
-#define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK
-#define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK
-#define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE
-#define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK
-#define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE
-#define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF
-#define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK
-#define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK
-#define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK
-#define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK
-#define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR
-#define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR
-#define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR
-#define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR
-#define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR
-#define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK
-#define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR
-#define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR
-/* end of flags for rb_econv_open */
-
-/* flags for rb_econv_convert */
- RUBY_ECONV_PARTIAL_INPUT = 0x00010000,
- RUBY_ECONV_AFTER_OUTPUT = 0x00020000,
-#define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT
-#define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT
-/* end of flags for rb_econv_convert */
-RUBY_ECONV_FLAGS_PLACEHOLDER};
-
-RBIMPL_SYMBOL_EXPORT_END()
+#include "ruby/internal/encoding/coderange.h"
+#include "ruby/internal/encoding/ctype.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/encoding/pathname.h"
+#include "ruby/internal/encoding/re.h"
+#include "ruby/internal/encoding/sprintf.h"
+#include "ruby/internal/encoding/string.h"
+#include "ruby/internal/encoding/symbol.h"
+#include "ruby/internal/encoding/transcode.h"
#endif /* RUBY_ENCODING_H */
diff --git a/include/ruby/fiber/scheduler.h b/include/ruby/fiber/scheduler.h
index 246e690587..250b39b6df 100644
--- a/include/ruby/fiber/scheduler.h
+++ b/include/ruby/fiber/scheduler.h
@@ -1,4 +1,4 @@
-#ifndef RUBY_FIBER_SCHEDULER_H /*-*-C-*-vi:se ft=c:*/
+#ifndef RUBY_FIBER_SCHEDULER_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_FIBER_SCHEDULER_H
/**
* @file
@@ -7,45 +7,368 @@
* Permission is hereby granted, 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.
+ * @brief Scheduler APIs.
*/
+#include "ruby/internal/config.h"
+
+#include <errno.h>
+
+#ifdef STDC_HEADERS
+#include <stddef.h> /* size_t */
+#endif
+
#include "ruby/ruby.h"
-#include "ruby/intern.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/arithmetic.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
+#define RUBY_FIBER_SCHEDULER_VERSION 2
+
+struct timeval;
+
+/**
+ * Wrap a `ssize_t` and `int errno` into a single `VALUE`. This interface should
+ * be used to safely capture results from system calls like `read` and `write`.
+ *
+ * You should use `rb_fiber_scheduler_io_result_apply` to unpack the result of
+ * this value and update `int errno`.
+ *
+ * You should not directly try to interpret the result value as it is considered
+ * an opaque representation. However, the general representation is an integer
+ * in the range of `[-int errno, size_t size]`. Linux generally restricts the
+ * result of system calls like `read` and `write` to `<= 2^31` which means this
+ * will typically fit within a single FIXNUM.
+ *
+ * @param[in] result The result of the system call.
+ * @param[in] error The value of `errno`.
+ * @return A `VALUE` which contains the result and/or errno.
+ */
+static inline VALUE
+rb_fiber_scheduler_io_result(ssize_t result, int error)
+{
+ if (result == -1) {
+ return RB_INT2NUM(-error);
+ }
+ else {
+ return RB_SIZE2NUM(result);
+ }
+}
+
+/**
+ * Apply an io result to the local thread, returning the value of the original
+ * system call that created it and updating `int errno`.
+ *
+ * You should not directly try to interpret the result value as it is considered
+ * an opaque representation.
+ *
+ * @param[in] result The `VALUE` which contains an errno and/or result size.
+ * @post Updates `int errno` with the value if negative.
+ * @return The original result of the system call.
+ */
+static inline ssize_t
+rb_fiber_scheduler_io_result_apply(VALUE result)
+{
+ if (RB_FIXNUM_P(result) && RB_NUM2INT(result) < 0) {
+ errno = -RB_NUM2INT(result);
+ return -1;
+ }
+ else {
+ return RB_NUM2SIZE(result);
+ }
+}
+
+/**
+ * Queries the current scheduler of the current thread that is calling this
+ * function.
+ *
+ * @retval RUBY_Qnil No scheduler has been set so far to this thread (which
+ * is the default).
+ * @retval otherwise The scheduler that was last set for the current thread
+ * with rb_fiber_scheduler_set().
+ */
VALUE rb_fiber_scheduler_get(void);
+
+/**
+ * Destructively assigns the passed scheduler to that of the current thread
+ * that is calling this function. If the scheduler is set, non-blocking fibers
+ * (created by `Fiber.new` with `blocking: false`, or by `Fiber.schedule`) call
+ * that scheduler's hook methods on potentially blocking operations, and the
+ * current thread will call scheduler's `#close` method on finalisation
+ * (allowing the scheduler to properly manage all non-finished fibers).
+ * `scheduler` can be an object of any class corresponding to
+ * `Fiber::SchedulerInterface`. Its implementation is up to the user.
+ *
+ * @param[in] scheduler The scheduler to set.
+ * @exception rb_eArgError `scheduler` does not conform the interface.
+ * @post Current thread's scheduler is `scheduler`.
+ */
VALUE rb_fiber_scheduler_set(VALUE scheduler);
+/**
+ * Identical to rb_fiber_scheduler_get(), except it also returns ::RUBY_Qnil in
+ * case of a blocking fiber. As blocking fibers do not participate schedulers'
+ * scheduling this function can be handy.
+ *
+ * @retval RUBY_Qnil No scheduler is in effect.
+ * @retval otherwise The scheduler that is in effect, if any.
+ */
VALUE rb_fiber_scheduler_current(void);
+
+/**
+ * Identical to rb_fiber_scheduler_current(), except it queries for that of the
+ * passed thread instead of the implicit current one.
+ *
+ * @param[in] thread Target thread.
+ * @exception rb_eTypeError `thread` is not a thread.
+ * @retval RUBY_Qnil No scheduler is in effect in `thread`.
+ * @retval otherwise The scheduler that is in effect in `thread`.
+ */
VALUE rb_fiber_scheduler_current_for_thread(VALUE thread);
+/**
+ * Converts the passed timeout to an expression that rb_fiber_scheduler_block()
+ * etc. expects.
+ *
+ * @param[in] timeout A duration (can be `NULL`).
+ * @retval RUBY_Qnil No timeout (blocks indefinitely).
+ * @retval otherwise A timeout object.
+ */
VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout);
+/**
+ * Closes the passed scheduler object. This expects the scheduler to wait for
+ * all fibers. Thus the scheduler's main loop tends to start here.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @return What `scheduler.close` returns.
+ */
VALUE rb_fiber_scheduler_close(VALUE scheduler);
+/**
+ * Non-blocking `sleep`. Depending on scheduler implementation, this for
+ * instance switches to another fiber etc.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] duration Passed as-is to `scheduler.kernel_sleep`.
+ * @return What `scheduler.kernel_sleep` returns.
+ */
VALUE rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE duration);
+
+/**
+ * Identical to rb_fiber_scheduler_kernel_sleep(), except it can pass multiple
+ * arguments.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed as-is to `scheduler.kernel_sleep`
+ * @return What `scheduler.kernel_sleep` returns.
+ */
VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv);
+/* Description TBW */
#if 0
VALUE rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message);
VALUE rb_fiber_scheduler_timeout_afterv(VALUE scheduler, int argc, VALUE * argv);
+int rb_fiber_scheduler_supports_process_wait(VALUE scheduler);
#endif
-int rb_fiber_scheduler_supports_process_wait(VALUE scheduler);
+/**
+ * Non-blocking `waitpid`. Depending on scheduler implementation, this for
+ * instance switches to another fiber etc.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] pid Process ID to wait.
+ * @param[in] flags Wait flags, e.g. `WUNTRACED`.
+ * @return What `scheduler.process_wait` returns.
+ */
VALUE rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags);
+/**
+ * Non-blocking wait for the passed "blocker", which is for instance
+ * `Thread.join` or `Mutex.lock`. Depending on scheduler implementation, this
+ * for instance switches to another fiber etc.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] blocker What blocks the current fiber.
+ * @param[in] timeout Numeric timeout.
+ * @return What `scheduler.block` returns.
+ */
VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout);
+
+/**
+ * Wakes up a fiber previously blocked using rb_fiber_scheduler_block().
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] blocker What was awaited for.
+ * @param[in] fiber What to unblock.
+ * @return What `scheduler.unblock` returns.
+ */
VALUE rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber);
+/**
+ * Non-blocking version of rb_io_wait(). Depending on scheduler
+ * implementation, this for instance switches to another fiber etc.
+ *
+ * The "events" here is a Ruby level integer, which is an OR-ed value of
+ * `IO::READABLE`, `IO::WRITABLE`, and `IO::PRIORITY`.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] io An io object to wait.
+ * @param[in] events An integer set of interests.
+ * @param[in] timeout Numeric timeout.
+ * @return What `scheduler.io_wait` returns.
+ */
VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout);
+
+/**
+ * Non-blocking wait until the passed IO is ready for reading. This is a
+ * special case of rb_fiber_scheduler_io_wait(), where the interest is
+ * `IO::READABLE` and timeout is never.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] io An io object to wait.
+ * @return What `scheduler.io_wait` returns.
+ */
VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io);
+
+/**
+ * Non-blocking wait until the passed IO is ready for writing. This is a
+ * special case of rb_fiber_scheduler_io_wait(), where the interest is
+ * `IO::WRITABLE` and timeout is never.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] io An io object to wait.
+ * @return What `scheduler.io_wait` returns.
+ */
VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io);
-VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length);
-VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length);
+/**
+ * Non-blocking version of `IO.select`.
+ *
+ * It's possible that this will be emulated using a thread, so you should not
+ * rely on it for high performance.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] readables An array of readable objects.
+ * @param[in] writables An array of writable objects.
+ * @param[in] exceptables An array of objects that might encounter exceptional conditions.
+ * @param[in] timeout Numeric timeout or nil.
+ * @return What `scheduler.io_select` returns, normally a 3-tuple of arrays of ready objects.
+ */
+VALUE rb_fiber_scheduler_io_select(VALUE scheduler, VALUE readables, VALUE writables, VALUE exceptables, VALUE timeout);
+
+/**
+ * Non-blocking version of `IO.select`, `argv` variant.
+ */
+VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv);
+
+/**
+ * Non-blocking read from the passed IO.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[out] io An io object to read from.
+ * @param[out] buffer Return buffer.
+ * @param[in] length Requested number of bytes to read.
+ * @param[in] offset The offset in the buffer to read to.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`.
+ * @return otherwise What `scheduler.io_read` returns `[-errno, size]`.
+ */
+VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset);
+
+/**
+ * Non-blocking write to the passed IO.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[out] io An io object to write to.
+ * @param[in] buffer What to write.
+ * @param[in] length Number of bytes to write.
+ * @param[in] offset The offset in the buffer to write from.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`.
+ * @return otherwise What `scheduler.io_write` returns `[-errno, size]`.
+ */
+VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset);
+
+/**
+ * Non-blocking read from the passed IO at the specified offset.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[out] io An io object to read from.
+ * @param[in] from The offset in the given IO to read the data from.
+ * @param[out] buffer The buffer to read the data to.
+ * @param[in] length Requested number of bytes to read.
+ * @param[in] offset The offset in the buffer to read to.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`.
+ * @return otherwise What `scheduler.io_read` returns.
+ */
+VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset);
+
+/**
+ * Non-blocking write to the passed IO at the specified offset.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[out] io An io object to write to.
+ * @param[in] from The offset in the given IO to write the data to.
+ * @param[in] buffer The buffer to write the data from.
+ * @param[in] length Number of bytes to write.
+ * @param[in] offset The offset in the buffer to write from.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`.
+ * @return otherwise What `scheduler.io_write` returns.
+ */
+VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset);
+
+/**
+ * Non-blocking read from the passed IO using a native buffer.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[out] io An io object to read from.
+ * @param[out] buffer Return buffer.
+ * @param[in] size Size of the return buffer.
+ * @param[in] length Requested number of bytes to read.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`.
+ * @return otherwise What `scheduler.io_read` returns.
+ */
+VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *buffer, size_t size, size_t length);
+
+/**
+ * Non-blocking write to the passed IO using a native buffer.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[out] io An io object to write to.
+ * @param[in] buffer What to write.
+ * @param[in] size Size of the buffer.
+ * @param[in] length Number of bytes to write.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`.
+ * @return otherwise What `scheduler.io_write` returns.
+ */
+VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *buffer, size_t size, size_t length);
+
+/**
+ * Non-blocking close the given IO.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] io An io object to close.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#io_close`.
+ * @return otherwise What `scheduler.io_close` returns.
+ */
+VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io);
+
+/**
+ * Non-blocking DNS lookup.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] hostname A host name to query.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#address_resolve`.
+ * @return otherwise What `scheduler.address_resolve` returns.
+ */
VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname);
+/**
+ * Create and schedule a non-blocking fiber.
+ *
+ */
+VALUE rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat);
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_FIBER_SCHEDULER_H */
diff --git a/include/ruby/internal/abi.h b/include/ruby/internal/abi.h
new file mode 100644
index 0000000000..44111a0055
--- /dev/null
+++ b/include/ruby/internal/abi.h
@@ -0,0 +1,58 @@
+#ifndef RUBY_ABI_H
+#define RUBY_ABI_H
+
+#ifdef RUBY_ABI_VERSION /* should match the definition in config.h */
+
+/* This number represents Ruby's ABI version.
+ *
+ * In development Ruby, it should be bumped every time an ABI incompatible
+ * change is introduced. This will force other developers to rebuild extension
+ * gems.
+ *
+ * The following cases are considered as ABI incompatible changes:
+ * - Changing any data structures.
+ * - Changing macros or inline functions causing a change in behavior.
+ * - Deprecating or removing function declarations.
+ *
+ * The following cases are NOT considered as ABI incompatible changes:
+ * - Any changes that does not involve the header files in the `include`
+ * directory.
+ * - Adding macros, inline functions, or function declarations.
+ * - Backwards compatible refactors.
+ * - Editing comments.
+ *
+ * In released versions of Ruby, this number is not defined since teeny
+ * versions of Ruby should guarantee ABI compatibility.
+ */
+#define RUBY_ABI_VERSION 3
+
+/* Windows does not support weak symbols so ruby_abi_version will not exist
+ * in the shared library. */
+#if defined(HAVE_FUNC_WEAK) && !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+# define RUBY_DLN_CHECK_ABI
+#endif
+#endif /* RUBY_ABI_VERSION */
+
+#ifdef RUBY_DLN_CHECK_ABI
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+RUBY_FUNC_EXPORTED unsigned long long __attribute__((weak))
+ruby_abi_version(void)
+{
+# ifdef RUBY_ABI_VERSION
+ return RUBY_ABI_VERSION;
+# else
+ return 0;
+# endif
+}
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+#endif
diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h
index f09a4e72e9..e4c6d155cc 100644
--- a/include/ruby/internal/anyargs.h
+++ b/include/ruby/internal/anyargs.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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,
@@ -84,12 +84,15 @@
#elif defined(_WIN32) || defined(__CYGWIN__)
# /* Skip due to [Bug #16134] */
+# define RBIMPL_CAST_FN_PTR 1
#elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union)
# /* :TODO: improve here, please find a way to support. */
+# define RBIMPL_CAST_FN_PTR 1
#elif ! defined(HAVE_VA_ARGS_MACRO)
# /* :TODO: improve here, please find a way to support. */
+# define RBIMPL_CAST_FN_PTR 1
#else
# /** @cond INTERNAL_MACRO */
@@ -239,15 +242,16 @@
# 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_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_notimpl, 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_notimpl, 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_notimpl, 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_notimpl, 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_notimpl, 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_notimpl, 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_notimpl, 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 ## _notimpl(__VA_ARGS__, VALUE(*)(int, const VALUE *, VALUE, VALUE), int); \
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); \
@@ -338,7 +342,7 @@ RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *)
/**
* @brief Defines ::rb_mKerbel \#mid.
- * @see ::rb_define_gobal_function
+ * @see ::rb_define_global_function
* @param mid Name of the defining method.
* @param func Implementation of ::rb_mKernel \#mid.
* @param arity Arity of ::rb_mKernel \#mid.
@@ -347,9 +351,28 @@ RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *)
#endif /* __cplusplus */
+#if defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus)
+/* In C23, K&R style prototypes are gone and so `void foo(ANYARGS)` became
+ * equivalent to `void foo(void)` unlike in earlier versions. This is a problem
+ * for rb_define_* functions since that makes all valid functions one can pass
+ * trip -Wincompatible-pointer-types, which we treat as errors. This is mostly
+ * not a problem for the __builtin_choose_expr path, but outside of that we
+ * need to add a cast for compatibility.
+ */
+#define rb_define_method(klass, mid, func, arity) rb_define_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_method_id(klass, mid, func, arity) rb_define_method_id((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_singleton_method(obj, mid, func, arity) rb_define_singleton_method((obj), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_protected_method(klass, mid, func, arity) rb_define_protected_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_private_method(klass, mid, func, arity) rb_define_private_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_module_function(mod, mid, func, arity) rb_define_module_function((mod), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_global_function(mid, func, arity) rb_define_global_function((mid), (VALUE (*)(ANYARGS))(func), (arity))
+
+#undef RBIMPL_CAST_FN_PTR
+#endif /* defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus) */
+
/**
* This macro is to properly cast a function parameter of *_define_method
- * family. It has been around since 1.x era so you can maximize backwards
+ * family. It has been around since 1.x era so you can maximise backwards
* compatibility by using it.
*
* ```CXX
diff --git a/include/ruby/internal/arithmetic.h b/include/ruby/internal/arithmetic.h
index c3806db444..7ebb4a86f1 100644
--- a/include/ruby/internal/arithmetic.h
+++ b/include/ruby/internal/arithmetic.h
@@ -17,8 +17,9 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Conversion between C's arithmetic types and Ruby's numeric
+ * types.
*/
#include "ruby/internal/arithmetic/char.h"
#include "ruby/internal/arithmetic/double.h"
diff --git a/include/ruby/internal/arithmetic/char.h b/include/ruby/internal/arithmetic/char.h
index 3033639a43..920fdc0c9d 100644
--- a/include/ruby/internal/arithmetic/char.h
+++ b/include/ruby/internal/arithmetic/char.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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 */
@@ -29,9 +29,9 @@
#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
+#define RB_NUM2CHR rb_num2char_inline /**< @alias{rb_num2char_inline} */
+#define NUM2CHR RB_NUM2CHR /**< @old{RB_NUM2CHR} */
+#define CHR2FIX RB_CHR2FIX /**< @old{RB_CHR2FIX} */
/** @cond INTERNAL_MACRO */
#define RB_CHR2FIX RB_CHR2FIX
@@ -40,12 +40,35 @@
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Converts a C's `unsigned char` into an instance of ::rb_cInteger.
+ *
+ * @param[in] c Arbitrary `unsigned char` value.
+ * @return An instance of ::rb_cInteger.
+ *
+ * @internal
+ *
+ * Nobody explicitly states this but in Ruby, a char means an unsigned integer
+ * value of range 0..255. This is a general principle. AFAIK there is no
+ * single line of code where char is signed.
+ */
static inline VALUE
RB_CHR2FIX(unsigned char c)
{
return RB_INT2FIX(c);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `char`. At the same time it
+ * accepts a String of more than one character, and returns its first byte. In
+ * the early days there was a Ruby level "character" literal `?c`, which
+ * roughly worked this way.
+ *
+ * @param[in] x Either a string or a numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `unsigned int`.
+ * @return The passed value converted into C's `char`.
+ */
static inline char
rb_num2char_inline(VALUE x)
{
diff --git a/include/ruby/internal/arithmetic/double.h b/include/ruby/internal/arithmetic/double.h
index 69d8630dbb..229de47aef 100644
--- a/include/ruby/internal/arithmetic/double.h
+++ b/include/ruby/internal/arithmetic/double.h
@@ -17,23 +17,56 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
+#define NUM2DBL rb_num2dbl /**< @old{rb_num2dbl} */
+#define RFLOAT_VALUE rb_float_value /**< @old{rb_float_value} */
+#define DBL2NUM rb_float_new /**< @old{rb_float_new} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-double rb_num2dbl(VALUE);
+/**
+ * Converts an instance of ::rb_cNumeric into C's `double`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @return The passed value converted into C's `double`.
+ */
+double rb_num2dbl(VALUE num);
+
RBIMPL_ATTR_PURE()
-double rb_float_value(VALUE);
-VALUE rb_float_new(double);
-VALUE rb_float_new_in_heap(double);
+/**
+ * Extracts its double value from an instance of ::rb_cFloat.
+ *
+ * @param[in] num An instance of ::rb_cFloat.
+ * @pre Must not pass anything other than a Fixnum.
+ * @return The passed value converted into C's `double`.
+ */
+double rb_float_value(VALUE num);
+
+/**
+ * Converts a C's `double` into an instance of ::rb_cFloat.
+ *
+ * @param[in] d Arbitrary `double` value.
+ * @return An instance of ::rb_cFloat.
+ */
+VALUE rb_float_new(double d);
+
+/**
+ * Identical to rb_float_new(), except it does not generate Flonums.
+ *
+ * @param[in] d Arbitrary `double` value.
+ * @return An instance of ::rb_cFloat.
+ *
+ * @internal
+ *
+ * @shyouhei has no idea why it is here.
+ */
+VALUE rb_float_new_in_heap(double d);
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_ARITHMETIC_DOUBLE_H */
diff --git a/include/ruby/internal/arithmetic/fixnum.h b/include/ruby/internal/arithmetic/fixnum.h
index 68544b760b..c8927ac824 100644
--- a/include/ruby/internal/arithmetic/fixnum.h
+++ b/include/ruby/internal/arithmetic/fixnum.h
@@ -17,28 +17,44 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
+#define FIXABLE RB_FIXABLE /**< @old{RB_FIXABLE} */
+#define FIXNUM_MAX RUBY_FIXNUM_MAX /**< @old{RUBY_FIXNUM_MAX} */
+#define FIXNUM_MIN RUBY_FIXNUM_MIN /**< @old{RUBY_FIXNUM_MIN} */
+#define NEGFIXABLE RB_NEGFIXABLE /**< @old{RB_NEGFIXABLE} */
+#define POSFIXABLE RB_POSFIXABLE /**< @old{RB_POSFIXABLE} */
-/*
+/**
+ * Checks if the passed value is in range of fixnum, assuming it is a positive
+ * number. Can sometimes be useful for C's unsigned integer types.
+ *
+ * @internal
+ *
* FIXABLE can be applied to anything, from double to intmax_t. The problem is
* double. On a 64bit system RUBY_FIXNUM_MAX is 4,611,686,018,427,387,903,
* which is not representable by a double. The nearest value that a double can
* represent is 4,611,686,018,427,387,904, which is not fixable. The
- * seemingly-stragne "< FIXNUM_MAX + 1" expression below is due to this.
+ * seemingly-strange "< FIXNUM_MAX + 1" expression below is due to this.
*/
#define RB_POSFIXABLE(_) ((_) < RUBY_FIXNUM_MAX + 1)
+
+/**
+ * Checks if the passed value is in range of fixnum, assuming it is a negative
+ * number. This is an implementation of #RB_FIXABLE. Rarely used stand alone.
+ */
#define RB_NEGFIXABLE(_) ((_) >= RUBY_FIXNUM_MIN)
+
+/** Checks if the passed value is in range of fixnum */
#define RB_FIXABLE(_) (RB_POSFIXABLE(_) && RB_NEGFIXABLE(_))
+
+/** Maximum possible value that a fixnum can represent. */
#define RUBY_FIXNUM_MAX (LONG_MAX / 2)
+
+/** Minimum possible value that a fixnum can represent. */
#define RUBY_FIXNUM_MIN (LONG_MIN / 2)
#endif /* RBIMPL_ARITHMETIC_FIXNUM_H */
diff --git a/include/ruby/internal/arithmetic/gid_t.h b/include/ruby/internal/arithmetic/gid_t.h
index 094fc63092..361220bfab 100644
--- a/include/ruby/internal/arithmetic/gid_t.h
+++ b/include/ruby/internal/arithmetic/gid_t.h
@@ -17,20 +17,23 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `gid_t` and Ruby's.
*/
#include "ruby/internal/config.h"
#include "ruby/internal/arithmetic/long.h"
+/** Converts a C's `gid_t` into an instance of ::rb_cInteger. */
#ifndef GIDT2NUM
# define GIDT2NUM RB_LONG2NUM
#endif
+/** Converts an instance of ::rb_cNumeric into C's `gid_t`. */
#ifndef NUM2GIDT
# define NUM2GIDT RB_NUM2LONG
#endif
+/** A rb_sprintf() format prefix to be used for a `gid_t` parameter. */
#ifndef PRI_GIDT_PREFIX
# define PRI_GIDT_PREFIX PRI_LONG_PREFIX
#endif
diff --git a/include/ruby/internal/arithmetic/int.h b/include/ruby/internal/arithmetic/int.h
index 346fa9258b..6bd8ec2184 100644
--- a/include/ruby/internal/arithmetic/int.h
+++ b/include/ruby/internal/arithmetic/int.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `int` and Ruby's.
*/
#include "ruby/internal/config.h"
@@ -34,16 +34,16 @@
#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 RB_INT2NUM rb_int2num_inline /**< @alias{rb_int2num_inline} */
+#define RB_NUM2INT rb_num2int_inline /**< @alias{rb_num2int_inline} */
+#define RB_UINT2NUM rb_uint2num_inline /**< @alias{rb_uint2num_inline} */
-#define FIX2INT RB_FIX2INT
-#define FIX2UINT RB_FIX2UINT
-#define INT2NUM RB_INT2NUM
-#define NUM2INT RB_NUM2INT
-#define NUM2UINT RB_NUM2UINT
-#define UINT2NUM RB_UINT2NUM
+#define FIX2INT RB_FIX2INT /**< @old{RB_FIX2INT} */
+#define FIX2UINT RB_FIX2UINT /**< @old{RB_FIX2UINT} */
+#define INT2NUM RB_INT2NUM /**< @old{RB_INT2NUM} */
+#define NUM2INT RB_NUM2INT /**< @old{RB_NUM2INT} */
+#define NUM2UINT RB_NUM2UINT /**< @old{RB_NUM2UINT} */
+#define UINT2NUM RB_UINT2NUM /**< @old{RB_UINT2NUM} */
/** @cond INTERNAL_MACRO */
#define RB_FIX2INT RB_FIX2INT
@@ -52,13 +52,79 @@
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-long rb_num2int(VALUE);
-long rb_fix2int(VALUE);
-unsigned long rb_num2uint(VALUE);
-unsigned long rb_fix2uint(VALUE);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `long`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `int`.
+ * @return The passed value converted into C's `long`.
+ *
+ * @internal
+ *
+ * Yes, the API is really strange. It returns `long`, but raises when the
+ * value is out of `int`. This seems to be due to the fact that Matz favoured
+ * K&R before, and his machine at that moment was an ILP32 architecture.
+ */
+long rb_num2int(VALUE num);
+
+/**
+ * Identical to rb_num2int().
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `int`.
+ * @return The passed value converted into C's `long`.
+ *
+ * @internal
+ *
+ * This function seems to be a complete waste of disk space. @shyouhei has no
+ * idea why this is a different thing from rb_num2short().
+ */
+long rb_fix2int(VALUE num);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned long`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `unsigned int`.
+ * @return The passed value converted into C's `unsigned long`.
+ *
+ * @internal
+ *
+ * Yes, the API is really strange. It returns `unsigned long`, but raises when
+ * the value is out of `unsigned int`. This seems to be due to the fact that
+ * Matz favoured K&R before, and his machine at that moment was an ILP32
+ * architecture.
+ */
+unsigned long rb_num2uint(VALUE num);
+
+/**
+ * Identical to rb_num2uint().
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `unsigned int`.
+ * @return The passed value converted into C's `unsigned long`.
+ *
+ * @internal
+ *
+ * This function seems to be a complete waste of disk space. @shyouhei has no
+ * idea why this is a different thing from rb_num2short().
+ */
+unsigned long rb_fix2uint(VALUE num);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Converts a Fixnum into C's `int`.
+ *
+ * @param[in] x Some Fixnum.
+ * @pre Must not pass anything other than a Fixnum.
+ * @return The passed value converted into C's `int`.
+ */
static inline int
RB_FIX2INT(VALUE x)
{
@@ -80,6 +146,14 @@ RB_FIX2INT(VALUE x)
return RBIMPL_CAST((int)ret);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `int`.
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `int`.
+ * @return The passed value converted into C's `int`.
+ */
static inline int
rb_num2int_inline(VALUE x)
{
@@ -98,6 +172,14 @@ rb_num2int_inline(VALUE x)
return RBIMPL_CAST((int)ret);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned int`.
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `unsigned int`.
+ * @return The passed value converted into C's `unsigned int`.
+ */
RBIMPL_ATTR_ARTIFICIAL()
static inline unsigned int
RB_NUM2UINT(VALUE x)
@@ -115,6 +197,13 @@ RB_NUM2UINT(VALUE x)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Converts a Fixnum into C's `int`.
+ *
+ * @param[in] x Some Fixnum.
+ * @pre Must not pass anything other than a Fixnum.
+ * @return The passed value converted into C's `int`.
+ */
static inline unsigned int
RB_FIX2UINT(VALUE x)
{
@@ -140,6 +229,12 @@ RBIMPL_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */
RBIMPL_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare)
#endif
+/**
+ * Converts a C's `int` into an instance of ::rb_cInteger.
+ *
+ * @param[in] v Arbitrary `int` value.
+ * @return An instance of ::rb_cInteger.
+ */
static inline VALUE
rb_int2num_inline(int v)
{
@@ -149,6 +244,12 @@ rb_int2num_inline(int v)
return rb_int2big(v);
}
+/**
+ * Converts a C's `unsigned int` into an instance of ::rb_cInteger.
+ *
+ * @param[in] v Arbitrary `unsigned int` value.
+ * @return An instance of ::rb_cInteger.
+ */
static inline VALUE
rb_uint2num_inline(unsigned int v)
{
diff --git a/include/ruby/internal/arithmetic/intptr_t.h b/include/ruby/internal/arithmetic/intptr_t.h
index 442c87144c..a354f4469c 100644
--- a/include/ruby/internal/arithmetic/intptr_t.h
+++ b/include/ruby/internal/arithmetic/intptr_t.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
@@ -29,13 +29,45 @@
#include "ruby/internal/value.h"
#include "ruby/internal/dllexport.h"
-#define rb_int_new rb_int2inum
-#define rb_uint_new rb_uint2inum
+#define rb_int_new rb_int2inum /**< @alias{rb_int2inum} */
+#define rb_uint_new rb_uint2inum /**< @alias{rb_uint2inum} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Converts a C's `intptr_t` into an instance of ::rb_cInteger.
+ *
+ * @param[in] i Arbitrary `intptr_t` value.
+ * @return An instance of ::rb_cInteger.
+ * @note This function always allocates Bignums, even if the given number
+ * is small enough to fit into a Fixnum.
+ */
VALUE rb_int2big(intptr_t i);
+
+/**
+ * Converts a C's `intptr_t` into an instance of ::rb_cInteger.
+ *
+ * @param[in] i Arbitrary `intptr_t` value.
+ * @return An instance of ::rb_cInteger.
+ */
VALUE rb_int2inum(intptr_t i);
+
+/**
+ * Converts a C's `intptr_t` into an instance of ::rb_cInteger.
+ *
+ * @param[in] i Arbitrary `intptr_t` value.
+ * @return An instance of ::rb_cInteger.
+ * @note This function always allocates Bignums, even if the given number
+ * is small enough to fit into a Fixnum.
+ */
VALUE rb_uint2big(uintptr_t i);
+
+/**
+ * Converts a C's `uintptr_t` into an instance of ::rb_cInteger.
+ *
+ * @param[in] i Arbitrary `uintptr_t` value.
+ * @return An instance of ::rb_cInteger.
+ */
VALUE rb_uint2inum(uintptr_t i);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/arithmetic/long.h b/include/ruby/internal/arithmetic/long.h
index aff7d68478..6b8fd8ffc3 100644
--- a/include/ruby/internal/arithmetic/long.h
+++ b/include/ruby/internal/arithmetic/long.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `long` and Ruby's.
*
* ### Q&A ###
@@ -43,23 +43,23 @@
#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
+#define FIX2LONG RB_FIX2LONG /**< @old{RB_FIX2LONG} */
+#define FIX2ULONG RB_FIX2ULONG /**< @old{RB_FIX2ULONG} */
+#define INT2FIX RB_INT2FIX /**< @old{RB_INT2FIX} */
+#define LONG2FIX RB_INT2FIX /**< @old{RB_INT2FIX} */
+#define LONG2NUM RB_LONG2NUM /**< @old{RB_LONG2NUM} */
+#define NUM2LONG RB_NUM2LONG /**< @old{RB_NUM2LONG} */
+#define NUM2ULONG RB_NUM2ULONG /**< @old{RB_NUM2ULONG} */
+#define RB_FIX2LONG rb_fix2long /**< @alias{rb_fix2long} */
+#define RB_FIX2ULONG rb_fix2ulong /**< @alias{rb_fix2ulong} */
+#define RB_LONG2FIX RB_INT2FIX /**< @alias{RB_INT2FIX} */
+#define RB_LONG2NUM rb_long2num_inline /**< @alias{rb_long2num_inline} */
+#define RB_NUM2LONG rb_num2long_inline /**< @alias{rb_num2long_inline} */
+#define RB_NUM2ULONG rb_num2ulong_inline /**< @alias{rb_num2ulong_inline} */
+#define RB_ULONG2NUM rb_ulong2num_inline /**< @alias{rb_ulong2num_inline} */
+#define ULONG2NUM RB_ULONG2NUM /**< @old{RB_ULONG2NUM} */
+#define rb_fix_new RB_INT2FIX /**< @alias{RB_INT2FIX} */
+#define rb_long2int rb_long2int_inline /**< @alias{rb_long2int_inline} */
/** @cond INTERNAL_MACRO */
#define RB_INT2FIX RB_INT2FIX
@@ -69,15 +69,44 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_NORETURN()
RBIMPL_ATTR_COLD()
+/**
+ * This is an utility function to raise an ::rb_eRangeError.
+ *
+ * @param[in] num A signed value about to overflow.
+ * @exception rb_eRangeError `num` is out of range of `int`.
+ */
void rb_out_of_int(SIGNED_VALUE num);
+/**
+ * Converts an instance of ::rb_cNumeric into C's `long`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `long`.
+ * @return The passed value converted into C's `long`.
+ */
long rb_num2long(VALUE num);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned long`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `unsigned long`.
+ * @return The passed value converted into C's `unsigned long`.
+ */
unsigned long rb_num2ulong(VALUE num);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Converts a C's `long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] i Arbitrary `long` value.
+ * @return An instance of ::rb_cInteger.
+ */
static inline VALUE
RB_INT2FIX(long i)
{
@@ -86,7 +115,7 @@ RB_INT2FIX(long 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 unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG;
const long l = k;
const SIGNED_VALUE m = l; /* Sign extend */
const VALUE n = m;
@@ -95,6 +124,13 @@ RB_INT2FIX(long i)
return n;
}
+/**
+ * Checks if `int` can hold the given integer.
+ *
+ * @param[in] n Arbitrary `long` value.
+ * @exception rb_eRangeError `n` is out of range of `int`.
+ * @return Identical value of type `int`
+ */
static inline int
rb_long2int_inline(long n)
{
@@ -112,6 +148,16 @@ rb_long2int_inline(long n)
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_fix2long(). People don't use it
+ * directly.
+ *
+ * @param[in] x A Fixnum.
+ * @return Identical value of type `long`
+ * @pre Must not pass anything other than a Fixnum.
+ */
static inline long
rbimpl_fix2long_by_idiv(VALUE x)
{
@@ -130,6 +176,16 @@ rbimpl_fix2long_by_idiv(VALUE x)
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_fix2long(). People don't use it
+ * directly.
+ *
+ * @param[in] x A Fixnum.
+ * @return Identical value of type `long`
+ * @pre Must not pass anything other than a Fixnum.
+ */
static inline long
rbimpl_fix2long_by_shift(VALUE x)
{
@@ -147,6 +203,15 @@ rbimpl_fix2long_by_shift(VALUE x)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_fix2long(). People don't use it
+ * directly.
+ *
+ * @retval true This C compiler's right shift operator is arithmetic.
+ * @retval false This C compiler's right shift operator is logical.
+ */
static inline bool
rbimpl_right_shift_is_arithmetic_p(void)
{
@@ -155,6 +220,13 @@ rbimpl_right_shift_is_arithmetic_p(void)
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+/**
+ * Converts a Fixnum into C's `long`.
+ *
+ * @param[in] x Some Fixnum.
+ * @pre Must not pass anything other than a Fixnum.
+ * @return The passed value converted into C's `long`.
+ */
static inline long
rb_fix2long(VALUE x)
{
@@ -168,6 +240,14 @@ rb_fix2long(VALUE x)
RBIMPL_ATTR_CONST_UNLESS_DEBUG()
RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+/**
+ * Converts a Fixnum into C's `unsigned long`.
+ *
+ * @param[in] x Some Fixnum.
+ * @pre Must not pass anything other than a Fixnum.
+ * @return The passed value converted into C's `unsigned long`.
+ * @note Negative fixnums will be converted into large unsigned longs.
+ */
static inline unsigned long
rb_fix2ulong(VALUE x)
{
@@ -175,6 +255,14 @@ rb_fix2ulong(VALUE x)
return rb_fix2long(x);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `long`.
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `long`.
+ * @return The passed value converted into C's `long`.
+ */
static inline long
rb_num2long_inline(VALUE x)
{
@@ -184,20 +272,38 @@ rb_num2long_inline(VALUE x)
return rb_num2long(x);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned long`.
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `unsigned long`.
+ * @return The passed value converted into C's `unsigned long`.
+ *
+ * @internal
+ *
+ * This (negative fixnum would become a large unsigned long while negative
+ * bignum is an exception) has been THE behaviour of NUM2ULONG since the
+ * beginning. It is strange, but we can no longer change how it works at this
+ * moment. We have to get by with it.
+ *
+ * @see https://bugs.ruby-lang.org/issues/9089
+ */
static inline unsigned long
rb_num2ulong_inline(VALUE x)
{
- /* 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);
}
+/**
+ * Converts a C's `long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] v Arbitrary `long` value.
+ * @return An instance of ::rb_cInteger.
+ */
static inline VALUE
rb_long2num_inline(long v)
{
@@ -207,6 +313,12 @@ rb_long2num_inline(long v)
return rb_int2big(v);
}
+/**
+ * Converts a C's `unsigned long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] v Arbitrary `unsigned long` value.
+ * @return An instance of ::rb_cInteger.
+ */
static inline VALUE
rb_ulong2num_inline(unsigned long v)
{
diff --git a/include/ruby/internal/arithmetic/long_long.h b/include/ruby/internal/arithmetic/long_long.h
index a4a5d0aa09..65dec8729d 100644
--- a/include/ruby/internal/arithmetic/long_long.h
+++ b/include/ruby/internal/arithmetic/long_long.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
@@ -25,22 +25,59 @@
#include "ruby/internal/special_consts.h"
#include "ruby/backward/2/long_long.h"
-#define RB_LL2NUM rb_ll2num_inline
-#define RB_ULL2NUM rb_ull2num_inline
-#define LL2NUM RB_LL2NUM
-#define ULL2NUM RB_ULL2NUM
-#define RB_NUM2LL rb_num2ll_inline
-#define RB_NUM2ULL rb_num2ull_inline
-#define NUM2LL RB_NUM2LL
-#define NUM2ULL RB_NUM2ULL
+#define RB_LL2NUM rb_ll2num_inline /**< @alias{rb_ll2num_inline} */
+#define RB_ULL2NUM rb_ull2num_inline /**< @alias{rb_ull2num_inline} */
+#define LL2NUM RB_LL2NUM /**< @old{RB_LL2NUM} */
+#define ULL2NUM RB_ULL2NUM /**< @old{RB_ULL2NUM} */
+#define RB_NUM2LL rb_num2ll_inline /**< @alias{rb_num2ll_inline} */
+#define RB_NUM2ULL rb_num2ull_inline /**< @alias{rb_num2ull_inline} */
+#define NUM2LL RB_NUM2LL /**< @old{RB_NUM2LL} */
+#define NUM2ULL RB_NUM2ULL /**< @old{RB_NUM2ULL} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-VALUE rb_ll2inum(LONG_LONG);
-VALUE rb_ull2inum(unsigned LONG_LONG);
-LONG_LONG rb_num2ll(VALUE);
-unsigned LONG_LONG rb_num2ull(VALUE);
+/**
+ * Converts a C's `long long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] num Arbitrary `long long` value.
+ * @return An instance of ::rb_cInteger.
+ */
+VALUE rb_ll2inum(LONG_LONG num);
+
+/**
+ * Converts a C's `unsigned long long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] num Arbitrary `unsigned long long` value.
+ * @return An instance of ::rb_cInteger.
+ */
+VALUE rb_ull2inum(unsigned LONG_LONG num);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `long long`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `long long`.
+ * @return The passed value converted into C's `long long`.
+ */
+LONG_LONG rb_num2ll(VALUE num);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned long long`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `unsigned long long`.
+ * @return The passed value converted into C's `unsigned long long`.
+ */
+unsigned LONG_LONG rb_num2ull(VALUE num);
RBIMPL_SYMBOL_EXPORT_END()
+/**
+ * Converts a C's `long long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] n Arbitrary `long long` value.
+ * @return An instance of ::rb_cInteger
+ */
static inline VALUE
rb_ll2num_inline(LONG_LONG n)
{
@@ -48,6 +85,12 @@ rb_ll2num_inline(LONG_LONG n)
return rb_ll2inum(n);
}
+/**
+ * Converts a C's `unsigned long long` into an instance of ::rb_cInteger.
+ *
+ * @param[in] n Arbitrary `unsigned long long` value.
+ * @return An instance of ::rb_cInteger
+ */
static inline VALUE
rb_ull2num_inline(unsigned LONG_LONG n)
{
@@ -55,6 +98,14 @@ rb_ull2num_inline(unsigned LONG_LONG n)
return rb_ull2inum(n);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `long long`.
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `long long`.
+ * @return The passed value converted into C's `long long`.
+ */
static inline LONG_LONG
rb_num2ll_inline(VALUE x)
{
@@ -64,6 +115,14 @@ rb_num2ll_inline(VALUE x)
return rb_num2ll(x);
}
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned long long`.
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `unsigned long long`.
+ * @return The passed value converted into C's `unsigned long long`.
+ */
static inline unsigned LONG_LONG
rb_num2ull_inline(VALUE x)
{
diff --git a/include/ruby/internal/arithmetic/mode_t.h b/include/ruby/internal/arithmetic/mode_t.h
index 46e41f7ef9..5b7ad35fbc 100644
--- a/include/ruby/internal/arithmetic/mode_t.h
+++ b/include/ruby/internal/arithmetic/mode_t.h
@@ -17,20 +17,23 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `mode_t` and Ruby's.
*/
#include "ruby/internal/config.h"
#include "ruby/internal/arithmetic/int.h"
+/** Converts a C's `mode_t` into an instance of ::rb_cInteger. */
#ifndef NUM2MODET
# define NUM2MODET RB_NUM2INT
#endif
+/** Converts an instance of ::rb_cNumeric into C's `mode_t`. */
#ifndef MODET2NUM
# define MODET2NUM RB_INT2NUM
#endif
+/** A rb_sprintf() format prefix to be used for a `mode_t` parameter. */
#ifndef PRI_MODET_PREFIX
# define PRI_MODET_PREFIX PRI_INT_PREFIX
#endif
diff --git a/include/ruby/internal/arithmetic/off_t.h b/include/ruby/internal/arithmetic/off_t.h
index c1959c61a1..0ec9362cc9 100644
--- a/include/ruby/internal/arithmetic/off_t.h
+++ b/include/ruby/internal/arithmetic/off_t.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
@@ -26,6 +26,7 @@
#include "ruby/internal/arithmetic/long_long.h"
#include "ruby/backward/2/long_long.h"
+/** Converts a C's `off_t` into an instance of ::rb_cInteger. */
#ifdef OFFT2NUM
# /* take that. */
#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
@@ -36,6 +37,7 @@
# define OFFT2NUM RB_INT2NUM
#endif
+/** Converts an instance of ::rb_cNumeric into C's `off_t`. */
#ifdef NUM2OFFT
# /* take that. */
#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
@@ -46,6 +48,7 @@
# define NUM2OFFT RB_NUM2INT
#endif
+/** A rb_sprintf() format prefix to be used for an `off_t` parameter. */
#ifdef PRI_OFFT_PREFIX
# /* take that. */
#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
diff --git a/include/ruby/internal/arithmetic/pid_t.h b/include/ruby/internal/arithmetic/pid_t.h
index 86373ebfde..df9704e8f5 100644
--- a/include/ruby/internal/arithmetic/pid_t.h
+++ b/include/ruby/internal/arithmetic/pid_t.h
@@ -17,20 +17,23 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `pid_t` and Ruby's.
*/
#include "ruby/internal/config.h"
#include "ruby/internal/arithmetic/long.h"
+/** Converts a C's `pid_t` into an instance of ::rb_cInteger. */
#ifndef PIDT2NUM
# define PIDT2NUM RB_LONG2NUM
#endif
+/** Converts an instance of ::rb_cNumeric into C's `pid_t`. */
#ifndef NUM2PIDT
# define NUM2PIDT RB_NUM2LONG
#endif
+/** A rb_sprintf() format prefix to be used for a `pid_t` parameter. */
#ifndef PRI_PIDT_PREFIX
# define PRI_PIDT_PREFIX PRI_LONG_PREFIX
#endif
diff --git a/include/ruby/internal/arithmetic/short.h b/include/ruby/internal/arithmetic/short.h
index ef213a8d3e..7a324d945b 100644
--- a/include/ruby/internal/arithmetic/short.h
+++ b/include/ruby/internal/arithmetic/short.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
@@ -27,21 +27,80 @@
#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
+#define RB_NUM2SHORT rb_num2short_inline /**< @alias{rb_num2short_inline} */
+#define RB_NUM2USHORT rb_num2ushort /**< @alias{rb_num2ushort} */
+#define NUM2SHORT RB_NUM2SHORT /**< @old{RB_NUM2SHORT} */
+#define NUM2USHORT RB_NUM2USHORT /**< @old{RB_NUM2USHORT} */
+#define USHORT2NUM RB_INT2FIX /**< @old{RB_INT2FIX} */
+#define RB_FIX2SHORT rb_fix2short /**< @alias{rb_fix2ushort} */
+#define FIX2SHORT RB_FIX2SHORT /**< @old{RB_FIX2SHORT} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-short rb_num2short(VALUE);
-unsigned short rb_num2ushort(VALUE);
-short rb_fix2short(VALUE);
-unsigned short rb_fix2ushort(VALUE);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `short`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `short`.
+ * @return The passed value converted into C's `short`.
+ */
+short rb_num2short(VALUE num);
+
+/**
+ * Converts an instance of ::rb_cNumeric into C's `unsigned short`.
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `unsigned short`.
+ * @return The passed value converted into C's `unsigned short`.
+ */
+unsigned short rb_num2ushort(VALUE num);
+
+/**
+ * Identical to rb_num2short().
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `short`.
+ * @return The passed value converted into C's `short`.
+ *
+ * @internal
+ *
+ * This function seems to be a complete waste of disk space. @shyouhei has no
+ * idea why this is a different thing from rb_num2short().
+ */
+short rb_fix2short(VALUE num);
+
+/**
+ * Identical to rb_num2ushort().
+ *
+ * @param[in] num Something numeric.
+ * @exception rb_eTypeError `num` is not a numeric.
+ * @exception rb_eRangeError `num` is out of range of `unsigned short`.
+ * @return The passed value converted into C's `unsigned short`.
+ *
+ * @internal
+ *
+ * This function seems to be a complete waste of disk space. @shyouhei has no
+ * idea why this is a different thing from rb_num2ushort().
+ */
+unsigned short rb_fix2ushort(VALUE num);
RBIMPL_SYMBOL_EXPORT_END()
+/**
+ * Identical to rb_num2short().
+ *
+ * @param[in] x Something numeric.
+ * @exception rb_eTypeError `x` is not a numeric.
+ * @exception rb_eRangeError `x` is out of range of `short`.
+ * @return The passed value converted into C's `short`.
+ *
+ * @internal
+ *
+ * This function seems to be a complete waste of time. @shyouhei has no idea
+ * why this is a different thing from rb_num2short().
+ */
static inline short
rb_num2short_inline(VALUE x)
{
@@ -51,4 +110,4 @@ rb_num2short_inline(VALUE x)
return rb_num2short(x);
}
-#endif /* RBIMPL_ARITHMETIC_SOHRT_H */
+#endif /* RBIMPL_ARITHMETIC_SHORT_H */
diff --git a/include/ruby/internal/arithmetic/size_t.h b/include/ruby/internal/arithmetic/size_t.h
index 0458f1f5f3..1082160b8e 100644
--- a/include/ruby/internal/arithmetic/size_t.h
+++ b/include/ruby/internal/arithmetic/size_t.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
@@ -26,7 +26,12 @@
#include "ruby/internal/arithmetic/long_long.h"
#include "ruby/backward/2/long_long.h"
-#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+#if defined(__DOXYGEN__)
+# /** Converts a C's `size_t` into an instance of ::rb_cInteger. */
+# define RB_SIZE2NUM RB_ULONG2NUM
+# /** Converts a C's `ssize_t` into an instance of ::rb_cInteger. */
+# define RB_SSIZE2NUM RB_LONG2NUM
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
# define RB_SIZE2NUM RB_ULL2NUM
# define RB_SSIZE2NUM RB_LL2NUM
#elif SIZEOF_SIZE_T == SIZEOF_LONG
@@ -37,7 +42,12 @@
# define RB_SSIZE2NUM RB_INT2NUM
#endif
-#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+#if defined(__DOXYGEN__)
+# /** Converts an instance of ::rb_cInteger into C's `size_t`. */
+# define RB_NUM2SIZE RB_NUM2ULONG
+# /** Converts an instance of ::rb_cInteger into C's `ssize_t`. */
+# define RB_NUM2SSIZE RB_NUM2LONG
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
# define RB_NUM2SIZE RB_NUM2ULL
# define RB_NUM2SSIZE RB_NUM2LL
#elif SIZEOF_SIZE_T == SIZEOF_LONG
@@ -48,9 +58,9 @@
# define RB_NUM2SSIZE RB_NUM2INT
#endif
-#define NUM2SIZET RB_NUM2SIZE
-#define SIZET2NUM RB_SIZE2NUM
-#define NUM2SSIZET RB_NUM2SSIZE
-#define SSIZET2NUM RB_SSIZE2NUM
+#define NUM2SIZET RB_NUM2SIZE /**< @old{RB_NUM2SIZE} */
+#define SIZET2NUM RB_SIZE2NUM /**< @old{RB_SIZE2NUM} */
+#define NUM2SSIZET RB_NUM2SSIZE /**< @old{RB_NUM2SSIZE} */
+#define SSIZET2NUM RB_SSIZE2NUM /**< @old{RB_SSIZE2NUM} */
#endif /* RBIMPL_ARITHMETIC_SIZE_T_H */
diff --git a/include/ruby/internal/arithmetic/st_data_t.h b/include/ruby/internal/arithmetic/st_data_t.h
index 93a5ccb7a1..3bff4ffc0b 100644
--- a/include/ruby/internal/arithmetic/st_data_t.h
+++ b/include/ruby/internal/arithmetic/st_data_t.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
@@ -30,7 +30,7 @@
#include "ruby/assert.h"
#include "ruby/st.h"
-#define ST2FIX RB_ST2FIX
+#define ST2FIX RB_ST2FIX /**< @old{RB_ST2FIX} */
/** @cond INTERNAL_MACRO */
#define RB_ST2FIX RB_ST2FIX
/** @endcond */
@@ -38,7 +38,23 @@
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] */
+/**
+ * Converts a C's `st_data_t` into an instance of ::rb_cInteger.
+ *
+ * @param[in] i The data in question.
+ * @return A converted result
+ * @warning THIS CONVERSION LOSES DATA! Be warned.
+ * @see https://bugs.ruby-lang.org/issues/13877
+ * @see https://bugs.ruby-lang.org/issues/14218
+ *
+ * @internal
+ *
+ * This is needed because of hash functions. Hash functions return
+ * `st_data_t`, which could theoretically be bigger than Fixnums. However
+ * allocating Bignums for them every time we calculate hash values is just too
+ * heavy. To avoid penalty we need to ignore some upper bit(s) and stick to
+ * Fixnums. This function is used for that purpose.
+ */
static inline VALUE
RB_ST2FIX(st_data_t i)
{
@@ -56,4 +72,4 @@ RB_ST2FIX(st_data_t i)
return RB_LONG2FIX(y);
}
-#endif /* RBIMPL_ARITHMERIC_ST_DATA_T_H */
+#endif /* RBIMPL_ARITHMETIC_ST_DATA_T_H */
diff --git a/include/ruby/internal/arithmetic/uid_t.h b/include/ruby/internal/arithmetic/uid_t.h
index a990b2f480..12cde2a9c8 100644
--- a/include/ruby/internal/arithmetic/uid_t.h
+++ b/include/ruby/internal/arithmetic/uid_t.h
@@ -17,20 +17,23 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Arithmetic conversion between C's `uid_t` and Ruby's.
*/
#include "ruby/internal/config.h"
#include "ruby/internal/arithmetic/long.h"
+/** Converts a C's `uid_t` into an instance of ::rb_cInteger. */
#ifndef UIDT2NUM
# define UIDT2NUM RB_LONG2NUM
#endif
+/** Converts an instance of ::rb_cNumeric into C's `uid_t`. */
#ifndef NUM2UIDT
# define NUM2UIDT RB_NUM2LONG
#endif
+/** A rb_sprintf() format prefix to be used for a `uid_t` parameter. */
#ifndef PRI_UIDT_PREFIX
# define PRI_UIDT_PREFIX PRI_LONG_PREFIX
#endif
diff --git a/include/ruby/internal/assume.h b/include/ruby/internal/assume.h
index e95b2fb12a..4c183e8af9 100644
--- a/include/ruby/internal/assume.h
+++ b/include/ruby/internal/assume.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ASSUME / #RBIMPL_UNREACHABLE.
*
* These macros must be defined at once because:
@@ -32,10 +32,7 @@
#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)
+#if defined(HAVE___ASSUME)
# define RBIMPL_HAVE___ASSUME
#endif
/** @endcond */
diff --git a/include/ruby/internal/attr/alloc_size.h b/include/ruby/internal/attr/alloc_size.h
index ea96feec99..954a2010f6 100644
--- a/include/ruby/internal/attr/alloc_size.h
+++ b/include/ruby/internal/attr/alloc_size.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_ALLOC_SIZE.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/artificial.h b/include/ruby/internal/attr/artificial.h
index fa9a3814cc..ef5f36abff 100644
--- a/include/ruby/internal/attr/artificial.h
+++ b/include/ruby/internal/attr/artificial.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_ARTIFICIAL.
*
* ### Q&A ###
diff --git a/include/ruby/internal/attr/cold.h b/include/ruby/internal/attr/cold.h
index 6db57fc9c2..c68b3ae784 100644
--- a/include/ruby/internal/attr/cold.h
+++ b/include/ruby/internal/attr/cold.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_COLD.
*/
#include "ruby/internal/compiler_is.h"
diff --git a/include/ruby/internal/attr/const.h b/include/ruby/internal/attr/const.h
index c9e8577693..e66aa17c70 100644
--- a/include/ruby/internal/attr/const.h
+++ b/include/ruby/internal/attr/const.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_CONST.
*/
#include "ruby/internal/compiler_since.h"
diff --git a/include/ruby/internal/attr/constexpr.h b/include/ruby/internal/attr/constexpr.h
index d887fa41c1..abc4f238b5 100644
--- a/include/ruby/internal/attr/constexpr.h
+++ b/include/ruby/internal/attr/constexpr.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief #RBIMPL_ATTR_CONSTEXPR.
*/
#include "ruby/internal/has/feature.h"
diff --git a/include/ruby/internal/attr/deprecated.h b/include/ruby/internal/attr/deprecated.h
index 874e416f83..e1bbdbd15a 100644
--- a/include/ruby/internal/attr/deprecated.h
+++ b/include/ruby/internal/attr/deprecated.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_DEPRECATED.
*/
#include "ruby/internal/compiler_since.h"
@@ -64,4 +64,12 @@
# define RBIMPL_ATTR_DEPRECATED(msg) /* void */
#endif
+/** This is when a function is used internally (for backwards compatibility
+ * etc.), but extension libraries must consider it deprecated. */
+#if defined(RUBY_EXPORT)
+# define RBIMPL_ATTR_DEPRECATED_EXT(msg) /* void */
+#else
+# define RBIMPL_ATTR_DEPRECATED_EXT(msg) RBIMPL_ATTR_DEPRECATED(msg)
+#endif
+
#endif /* RBIMPL_ATTR_DEPRECATED_H */
diff --git a/include/ruby/internal/attr/diagnose_if.h b/include/ruby/internal/attr/diagnose_if.h
index 6a79e904b7..cadc6ce258 100644
--- a/include/ruby/internal/attr/diagnose_if.h
+++ b/include/ruby/internal/attr/diagnose_if.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_DIAGNOSE_IF.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/enum_extensibility.h b/include/ruby/internal/attr/enum_extensibility.h
index 6faa58185a..eb0d5b6e9b 100644
--- a/include/ruby/internal/attr/enum_extensibility.h
+++ b/include/ruby/internal/attr/enum_extensibility.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief #RBIMPL_ATTR_ENUM_EXTENSIBILITY.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/error.h b/include/ruby/internal/attr/error.h
index da19b73c2b..2ed388a770 100644
--- a/include/ruby/internal/attr/error.h
+++ b/include/ruby/internal/attr/error.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_ERROR.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/flag_enum.h b/include/ruby/internal/attr/flag_enum.h
index 148384d842..3053d75074 100644
--- a/include/ruby/internal/attr/flag_enum.h
+++ b/include/ruby/internal/attr/flag_enum.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
*/
diff --git a/include/ruby/internal/attr/forceinline.h b/include/ruby/internal/attr/forceinline.h
index 6b31f1016f..b7daafede7 100644
--- a/include/ruby/internal/attr/forceinline.h
+++ b/include/ruby/internal/attr/forceinline.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_FORCEINLINE.
*/
#include "ruby/internal/compiler_since.h"
diff --git a/include/ruby/internal/attr/format.h b/include/ruby/internal/attr/format.h
index fcbf7b6cfe..b3488ee00a 100644
--- a/include/ruby/internal/attr/format.h
+++ b/include/ruby/internal/attr/format.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_FORMAT.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/maybe_unused.h b/include/ruby/internal/attr/maybe_unused.h
index f46d1bc670..3ee8be4540 100644
--- a/include/ruby/internal/attr/maybe_unused.h
+++ b/include/ruby/internal/attr/maybe_unused.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_MAYBE_UNUSED.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/noalias.h b/include/ruby/internal/attr/noalias.h
index 63324b7184..0790ef60e5 100644
--- a/include/ruby/internal/attr/noalias.h
+++ b/include/ruby/internal/attr/noalias.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_NOALIAS.
*
* ### Q&A ###
@@ -46,10 +46,21 @@
* that has to be passed to the function as a pointer. ::VALUE -taking
* functions thus cannot be attributed as such.
*/
+#include "ruby/internal/compiler_since.h"
#include "ruby/internal/has/declspec_attribute.h"
/** Wraps (or simulates) `__declspec((noalias))` */
-#if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias)
+#if RBIMPL_COMPILER_BEFORE(Clang, 12, 0, 0)
+# /*
+# * `::llvm::Attribute::ArgMemOnly` was buggy before. Maybe because nobody
+# * actually seriously used it. It seems they somehow mitigated the situation
+# * in LLVM 12. Still not found the exact changeset which fiexed the
+# * attribute, though.
+# *
+# * :FIXME: others (armclang, xlclang, ...) can also be affected?
+# */
+# define RBIMPL_ATTR_NOALIAS() /* void */
+#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias)
# define RBIMPL_ATTR_NOALIAS() __declspec(noalias)
#else
# define RBIMPL_ATTR_NOALIAS() /* void */
diff --git a/include/ruby/internal/attr/nodiscard.h b/include/ruby/internal/attr/nodiscard.h
index 5fd71b1c23..c3ae118942 100644
--- a/include/ruby/internal/attr/nodiscard.h
+++ b/include/ruby/internal/attr/nodiscard.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_NODISCARD.
*/
#include "ruby/internal/has/attribute.h"
@@ -26,7 +26,7 @@
/**
* 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.
+ * nodiscard attribute can have a message why the result shall not be ignored.
* However GCC attribute and SAL annotation cannot take them.
*/
#if RBIMPL_HAS_CPP_ATTRIBUTE(nodiscard)
diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h
index 968a7742b9..ea3001df2a 100644
--- a/include/ruby/internal/attr/noexcept.h
+++ b/include/ruby/internal/attr/noexcept.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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...
diff --git a/include/ruby/internal/attr/noinline.h b/include/ruby/internal/attr/noinline.h
index 619f99a171..b7605a0c91 100644
--- a/include/ruby/internal/attr/noinline.h
+++ b/include/ruby/internal/attr/noinline.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_NOINLINE.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/nonnull.h b/include/ruby/internal/attr/nonnull.h
index cfced0bf74..778d5be208 100644
--- a/include/ruby/internal/attr/nonnull.h
+++ b/include/ruby/internal/attr/nonnull.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_NONNULL.
*/
#include "ruby/internal/has/attribute.h"
@@ -25,8 +25,10 @@
/** Wraps (or simulates) `__attribute__((nonnull))` */
#if RBIMPL_HAS_ATTRIBUTE(nonnull)
# define RBIMPL_ATTR_NONNULL(list) __attribute__((__nonnull__ list))
+# define RBIMPL_NONNULL_ARG(arg) RBIMPL_ASSERT_NOTHING
#else
# define RBIMPL_ATTR_NONNULL(list) /* void */
+# define RBIMPL_NONNULL_ARG(arg) RUBY_ASSERT(arg)
#endif
#endif /* RBIMPL_ATTR_NONNULL_H */
diff --git a/include/ruby/internal/attr/nonstring.h b/include/ruby/internal/attr/nonstring.h
new file mode 100644
index 0000000000..de26e926d4
--- /dev/null
+++ b/include/ruby/internal/attr/nonstring.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_NONSTRING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NONSTRING_H
+/**
+ * @file
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
+ * implementation details. Don't take them as canon. They could
+ * rapidly appear then vanish. The name (path) of this header file
+ * is also an implementation detail. Do not expect it to persist
+ * at the place it is now. Developers are free to move it anywhere
+ * anytime at will.
+ * @note To ruby-core: remember that this header can be possibly
+ * recursively included from extension libraries written in C++.
+ * Do not expect for instance `__VA_ARGS__` is always available.
+ * We assume C99 for ruby itself but we don't assume languages of
+ * extension libraries. They could be written in C++98.
+ * @brief Defines #RBIMPL_ATTR_NONSTRING.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((nonstring))` */
+#if RBIMPL_HAS_ATTRIBUTE(nonstring)
+# define RBIMPL_ATTR_NONSTRING() __attribute__((nonstring))
+#else
+# define RBIMPL_ATTR_NONSTRING() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NONSTRING_H */
diff --git a/include/ruby/internal/attr/noreturn.h b/include/ruby/internal/attr/noreturn.h
index f741167c12..5839212037 100644
--- a/include/ruby/internal/attr/noreturn.h
+++ b/include/ruby/internal/attr/noreturn.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_NORETURN.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/pure.h b/include/ruby/internal/attr/pure.h
index 4416c25aa0..015711bdab 100644
--- a/include/ruby/internal/attr/pure.h
+++ b/include/ruby/internal/attr/pure.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_PURE.
*/
#include "ruby/internal/compiler_since.h"
diff --git a/include/ruby/internal/attr/restrict.h b/include/ruby/internal/attr/restrict.h
index aca122af45..e39104138c 100644
--- a/include/ruby/internal/attr/restrict.h
+++ b/include/ruby/internal/attr/restrict.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_RESTRICT.
*/
#include "ruby/internal/compiler_since.h"
diff --git a/include/ruby/internal/attr/returns_nonnull.h b/include/ruby/internal/attr/returns_nonnull.h
index 91c7be15cd..5d6f1d1459 100644
--- a/include/ruby/internal/attr/returns_nonnull.h
+++ b/include/ruby/internal/attr/returns_nonnull.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_RETURNS_NONNULL.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/warning.h b/include/ruby/internal/attr/warning.h
index fb6b214828..e5ced269b8 100644
--- a/include/ruby/internal/attr/warning.h
+++ b/include/ruby/internal/attr/warning.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_WARNING.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/attr/weakref.h b/include/ruby/internal/attr/weakref.h
index 59dba678fa..f118bb62b8 100644
--- a/include/ruby/internal/attr/weakref.h
+++ b/include/ruby/internal/attr/weakref.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ATTR_WEAKREF.
*/
#include "ruby/internal/has/attribute.h"
diff --git a/include/ruby/internal/cast.h b/include/ruby/internal/cast.h
index 065a5d01c2..a31fddbe4c 100644
--- a/include/ruby/internal/cast.h
+++ b/include/ruby/internal/cast.h
@@ -1,7 +1,6 @@
#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
@@ -17,9 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
@@ -48,6 +46,5 @@
#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
index 776d7add4f..7070b033a0 100644
--- a/include/ruby/internal/compiler_is.h
+++ b/include/ruby/internal/compiler_is.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_COMPILER_IS.
*/
diff --git a/include/ruby/internal/compiler_is/apple.h b/include/ruby/internal/compiler_is/apple.h
index 5a5f558254..a81f1f2c8f 100644
--- a/include/ruby/internal/compiler_is/apple.h
+++ b/include/ruby/internal/compiler_is/apple.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * 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
diff --git a/include/ruby/internal/compiler_is/clang.h b/include/ruby/internal/compiler_is/clang.h
index 30655f2f25..169ff789f6 100644
--- a/include/ruby/internal/compiler_is/clang.h
+++ b/include/ruby/internal/compiler_is/clang.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Defines RBIMPL_COMPILER_IS_Clang.
*/
#include "ruby/internal/compiler_is/apple.h"
diff --git a/include/ruby/internal/compiler_is/gcc.h b/include/ruby/internal/compiler_is/gcc.h
index 6eabfb61a2..accc80e9aa 100644
--- a/include/ruby/internal/compiler_is/gcc.h
+++ b/include/ruby/internal/compiler_is/gcc.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * 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"
diff --git a/include/ruby/internal/compiler_is/intel.h b/include/ruby/internal/compiler_is/intel.h
index ada120485e..377946ace0 100644
--- a/include/ruby/internal/compiler_is/intel.h
+++ b/include/ruby/internal/compiler_is/intel.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * 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
diff --git a/include/ruby/internal/compiler_is/msvc.h b/include/ruby/internal/compiler_is/msvc.h
index 60189da1a3..8a864ea558 100644
--- a/include/ruby/internal/compiler_is/msvc.h
+++ b/include/ruby/internal/compiler_is/msvc.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * 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"
diff --git a/include/ruby/internal/compiler_is/sunpro.h b/include/ruby/internal/compiler_is/sunpro.h
index 2eb7b892f2..c11c8452e7 100644
--- a/include/ruby/internal/compiler_is/sunpro.h
+++ b/include/ruby/internal/compiler_is/sunpro.h
@@ -1,7 +1,6 @@
#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
@@ -17,8 +16,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * 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
diff --git a/include/ruby/internal/compiler_since.h b/include/ruby/internal/compiler_since.h
index b213cfd8b9..1929032884 100644
--- a/include/ruby/internal/compiler_since.h
+++ b/include/ruby/internal/compiler_since.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_COMPILER_SINCE.
*/
#include "ruby/internal/compiler_is.h"
diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h
index b26e7eea25..aa63376d7c 100644
--- a/include/ruby/internal/config.h
+++ b/include/ruby/internal/config.h
@@ -1,7 +1,6 @@
#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
@@ -17,7 +16,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Thin wrapper to ruby/config.h
*/
#include "ruby/config.h"
@@ -114,6 +113,8 @@
# define UNALIGNED_WORD_ACCESS 1
#elif defined(__powerpc64__)
# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__POWERPC__) // __POWERPC__ is defined for ppc and ppc64 on Darwin
+# define UNALIGNED_WORD_ACCESS 1
#elif defined(__aarch64__)
# define UNALIGNED_WORD_ACCESS 1
#elif defined(__mc68020__)
@@ -147,4 +148,8 @@
# undef RBIMPL_TEST3
#endif /* HAVE_VA_ARGS_MACRO */
+#ifndef USE_RVARGC
+# define USE_RVARGC 1
+#endif
+
#endif /* RBIMPL_CONFIG_H */
diff --git a/include/ruby/internal/constant_p.h b/include/ruby/internal/constant_p.h
index e54a8d85b9..92d69cb972 100644
--- a/include/ruby/internal/constant_p.h
+++ b/include/ruby/internal/constant_p.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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,
@@ -28,6 +28,7 @@
*/
#include "ruby/internal/has/builtin.h"
+/** Wraps (or simulates) `__builtin_constant_p` */
#if RBIMPL_HAS_BUILTIN(__builtin_constant_p)
# define RBIMPL_CONSTANT_P(expr) __builtin_constant_p(expr)
#else
diff --git a/include/ruby/internal/core.h b/include/ruby/internal/core.h
index 279a697ea1..3f4561c6a6 100644
--- a/include/ruby/internal/core.h
+++ b/include/ruby/internal/core.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Core data structures, definitions and manipulations.
*/
#include "ruby/internal/core/rarray.h"
diff --git a/include/ruby/internal/core/rarray.h b/include/ruby/internal/core/rarray.h
index 938e2dc897..c3bb40be25 100644
--- a/include/ruby/internal/core/rarray.h
+++ b/include/ruby/internal/core/rarray.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RArray.
*/
#include "ruby/internal/arithmetic/long.h"
@@ -35,11 +35,26 @@
#include "ruby/internal/value_type.h"
#include "ruby/assert.h"
+/**
+ * @private
+ * @warning Do not touch this macro.
+ * @warning It is an implementation detail.
+ * @warning The value of this macro must match for ruby itself and all
+ * extension libraries, otherwise serious memory corruption shall
+ * occur.
+ */
#ifndef USE_TRANSIENT_HEAP
# define USE_TRANSIENT_HEAP 1
#endif
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RArray.
+ * @return The passed object casted to ::RArray.
+ */
#define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj))
+/** @cond INTERNAL_MACRO */
#define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG
#define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK
#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX
@@ -49,9 +64,10 @@
#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
+/** @endcond */
+#define RARRAY_LEN rb_array_len /**< @alias{rb_array_len} */
+#define RARRAY_CONST_PTR rb_array_const_ptr /**< @alias{rb_array_const_ptr} */
+#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient /**< @alias{rb_array_const_ptr_transient} */
/** @cond INTERNAL_MACRO */
#if defined(__fcc__) || defined(__fcc_version) || \
@@ -69,28 +85,127 @@
#define RARRAY_PTR RARRAY_PTR
/** @endcond */
+/**
+ * @private
+ *
+ * Bits that you can set to ::RBasic::flags.
+ *
+ * @warning These enums are not the only bits we use for arrays.
+ *
+ * @internal
+ *
+ * Unlike strings, flag usages for arrays are scattered across the entire
+ * source codes. @shyouhei doesn't know the complete list. But what is listed
+ * here is at least incomplete.
+ */
enum ruby_rarray_flags {
+ /**
+ * This flag has something to do with memory footprint. If the array is
+ * "small" enough, ruby tries to be creative to abuse padding bits of
+ * struct ::RArray for storing its contents. This flag denotes that
+ * situation.
+ *
+ * @warning This bit has to be considered read-only. Setting/clearing
+ * this bit without corresponding fix up must cause immediate
+ * SEGV. Also, internal structures of an array change
+ * dynamically and transparently throughout of its lifetime.
+ * Don't assume it being persistent.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store array elements. It was a bad idea to expose this to them.
+ */
RARRAY_EMBED_FLAG = RUBY_FL_USER1,
+
/* RUBY_FL_USER2 is for ELTS_SHARED */
+
+ /**
+ * When an array employs embedded strategy (see ::RARRAY_EMBED_FLAG), these
+ * bits are used to store the number of elements actually filled into
+ * ::RArray::ary.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store array elements. It was a bad idea to expose this to them.
+ */
+#if USE_RVARGC
+ RARRAY_EMBED_LEN_MASK = RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | RUBY_FL_USER6 |
+ RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3
+#else
RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3
+#endif
+
#if USE_TRANSIENT_HEAP
,
+
+ /**
+ * This flag has something to do with an array's "transiency". A transient
+ * array is an array of young generation (of generational GC), who stores
+ * its elements inside of dedicated memory pages called a transient heap.
+ * Not every young generation share that storage scheme, but elder
+ * generations must no join.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store array elements. It was a bad idea to expose this to them.
+ */
RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13
#endif
};
+/**
+ * This is an enum because GDB wants it (rather than a macro). People need not
+ * bother.
+ */
enum ruby_rarray_consts {
- RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3,
+ /** Where ::RARRAY_EMBED_LEN_MASK resides. */
+ RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3
+
+#if !USE_RVARGC
+ ,
+
+ /** Max possible number elements that can be embedded. */
RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
+#endif
};
+/** Ruby's array. */
struct RArray {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /** Array's specific fields. */
union {
+
+ /**
+ * Arrays that use separated memory region for elements use this
+ * pattern.
+ */
struct {
+
+ /** Number of elements of the array. */
long len;
+
+ /** Auxiliary info. */
union {
+
+ /**
+ * Capacity of `*ptr`. A continuous memory region of at least
+ * `capa` elements is expected to exist at `*ptr`. This can be
+ * bigger than `len`.
+ */
long capa;
+
+ /**
+ * Parent of the array. Nowadays arrays can share their
+ * backend memory regions each other, constructing gigantic
+ * nest of objects. This situation is called "shared", and
+ * this is the field to control such properties.
+ */
#if defined(__clang__) /* <- clang++ is sane */ || \
!defined(__cplusplus) /* <- C99 is sane */ || \
(__cplusplus > 199711L) /* <- C++11 is sane */
@@ -98,22 +213,86 @@ struct RArray {
#endif
VALUE shared_root;
} aux;
+
+ /**
+ * Pointer to the C array that holds the elements of the array. In
+ * the old days each array had dedicated memory regions. That is
+ * no longer true today, but there still are arrays of such
+ * properties. This field could be used to point such things.
+ */
const VALUE *ptr;
} heap;
+
+ /**
+ * Embedded elements. When an array is short enough, it uses this area
+ * to store its elements. In this case the length is encoded into the
+ * flags.
+ */
+#if USE_RVARGC
+ /* This is a length 1 array because:
+ * 1. GCC has a bug that does not optimize C flexible array members
+ * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
+ * 2. Zero length arrays are not supported by all compilers
+ */
+ const VALUE ary[1];
+#else
const VALUE ary[RARRAY_EMBED_LEN_MAX];
+#endif
} as;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * @private
+ *
+ * Declares a section of code where raw pointers are used. This is an
+ * implementation detail of #RARRAY_PTR_USE. People don't use it directly.
+ *
+ * @param[in] ary An object of ::RArray.
+ * @return `ary`'s backend C array.
+ */
VALUE *rb_ary_ptr_use_start(VALUE ary);
+
+/**
+ * @private
+ *
+ * Declares an end of a section formerly started by rb_ary_ptr_use_start().
+ * This is an implementation detail of #RARRAY_PTR_USE. People don't use it
+ * directly.
+ *
+ * @param[in] a An object of ::RArray.
+ */
void rb_ary_ptr_use_end(VALUE a);
+
#if USE_TRANSIENT_HEAP
+/**
+ * Destructively converts an array of transient backend into ordinal one.
+ *
+ * @param[out] a An object of ::RArray.
+ * @pre `a` must be a transient array.
+ * @post `a` gets out of transient heap, destructively.
+ */
void rb_ary_detransient(VALUE a);
#endif
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the length of the array.
+ *
+ * @param[in] ary Array in question.
+ * @return Its number of elements.
+ * @pre `ary` must be an instance of ::RArray, and must has its
+ * ::RARRAY_EMBED_FLAG flag set.
+ *
+ * @internal
+ *
+ * This was a macro before. It was inevitable to be public, since macros are
+ * global constructs. But should it be forever? Now that it is a function,
+ * @shyouhei thinks it could just be eliminated, hidden into implementation
+ * details.
+ */
static inline long
RARRAY_EMBED_LEN(VALUE ary)
{
@@ -127,6 +306,13 @@ RARRAY_EMBED_LEN(VALUE ary)
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/**
+ * Queries the length of the array.
+ *
+ * @param[in] a Array in question.
+ * @return Its number of elements.
+ * @pre `a` must be an instance of ::RArray.
+ */
static inline long
rb_array_len(VALUE a)
{
@@ -141,6 +327,18 @@ rb_array_len(VALUE a)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Identical to rb_array_len(), except it differs for the return type.
+ *
+ * @param[in] ary Array in question.
+ * @exception rb_eRangeError Too long.
+ * @return Its number of elements.
+ * @pre `ary` must be an instance of ::RArray.
+ *
+ * @internal
+ *
+ * This API seems redundant but has actual usages.
+ */
static inline int
RARRAY_LENINT(VALUE ary)
{
@@ -149,6 +347,19 @@ RARRAY_LENINT(VALUE ary)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries if the array is a transient array.
+ *
+ * @param[in] ary Array in question.
+ * @retval true Yes it is.
+ * @retval false No it isn't.
+ * @pre `ary` must be an instance of ::RArray.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't understand the benefit of this function called from
+ * extension libraries.
+ */
static inline bool
RARRAY_TRANSIENT_P(VALUE ary)
{
@@ -162,7 +373,15 @@ RARRAY_TRANSIENT_P(VALUE ary)
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
-/* internal function. do not use this function */
+/**
+ * @private
+ *
+ * This is an implementation detail of RARRAY_PTR(). People do not use it
+ * directly.
+ *
+ * @param[in] a An object of ::RArray.
+ * @return Its backend storage.
+ */
static inline const VALUE *
rb_array_const_ptr_transient(VALUE a)
{
@@ -179,7 +398,16 @@ rb_array_const_ptr_transient(VALUE a)
#if ! USE_TRANSIENT_HEAP
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
#endif
-/* internal function. do not use this function */
+/**
+ * @private
+ *
+ * This is an implementation detail of RARRAY_PTR(). People do not use it
+ * directly.
+ *
+ * @param[in] a An object of ::RArray.
+ * @return Its backend storage.
+ * @post `a` is not a transient array.
+ */
static inline const VALUE *
rb_array_const_ptr(VALUE a)
{
@@ -193,7 +421,17 @@ rb_array_const_ptr(VALUE a)
return rb_array_const_ptr_transient(a);
}
-/* internal function. do not use this function */
+/**
+ * @private
+ *
+ * This is an implementation detail of #RARRAY_PTR_USE. People do not use it
+ * directly.
+ *
+ * @param[in] a An object of ::RArray.
+ * @param[in] allow_transient Whether `a` can be transient or not.
+ * @return Its backend storage.
+ * @post `a` is not a transient array unless `allow_transient`.
+ */
static inline VALUE *
rb_array_ptr_use_start(VALUE a,
RBIMPL_ATTR_MAYBE_UNUSED()
@@ -212,7 +450,15 @@ rb_array_ptr_use_start(VALUE a,
return rb_ary_ptr_use_start(a);
}
-/* internal function. do not use this function */
+/**
+ * @private
+ *
+ * This is an implementation detail of #RARRAY_PTR_USE. People do not use it
+ * directly.
+ *
+ * @param[in] a An object of ::RArray.
+ * @param[in] allow_transient Whether `a` can be transient or not.
+ */
static inline void
rb_array_ptr_use_end(VALUE a,
RBIMPL_ATTR_MAYBE_UNUSED()
@@ -222,6 +468,12 @@ rb_array_ptr_use_end(VALUE a,
rb_ary_ptr_use_end(a);
}
+/**
+ * @private
+ *
+ * This is an implementation detail of #RARRAY_PTR_USE. People do not use it
+ * directly.
+ */
#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \
RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \
const VALUE rbimpl_ary = (ary); \
@@ -230,16 +482,66 @@ rb_array_ptr_use_end(VALUE a,
rb_array_ptr_use_end(rbimpl_ary, (flag)); \
} while (0)
-#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0)
+/**
+ * @private
+ *
+ * This is an implementation detail of #RARRAY_PTR_USE. People do not use it
+ * directly.
+ */
#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
-#define RARRAY_PTR_USE(ary, ptr_name, expr) \
+
+/**
+ * Declares a section of code where raw pointers are used. In case you need to
+ * touch the raw C array instead of polite CAPIs, then that operation shall be
+ * wrapped using this macro.
+ *
+ * ```CXX
+ * const auto ary = rb_eval_string("[...]");
+ * const auto len = RARRAY_LENINT(ary);
+ * const auto symwrite = rb_intern("write");
+ *
+ * RARRAY_PTR_USE(ary, ptr, {
+ * rb_funcallv(rb_stdout, symwrite, len, ptr);
+ * });
+ * ```
+ *
+ * @param ary An object of ::RArray.
+ * @param ptr_name A variable name which points the C array in `expr`.
+ * @param expr The expression that touches `ptr_name`.
+ *
+ * @internal
+ *
+ * For historical reasons use of this macro is not enforced. There are
+ * extension libraries in the wild which call RARRAY_PTR() without it. We want
+ * them use it... Maybe some transition path can be implemented later.
+ */
+#define RARRAY_PTR_USE(ary, ptr_name, expr) \
RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr)
-#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) \
+/**
+ * Identical to #RARRAY_PTR_USE, except the pointer can be a transient one.
+ *
+ * @param ary An object of ::RArray.
+ * @param ptr_name A variable name which points the C array in `expr`.
+ * @param expr The expression that touches `ptr_name`.
+ */
+#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \
RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr)
+/**
+ * Wild use of a C pointer. This function accesses the backend storage
+ * directly. This is slower than #RARRAY_PTR_USE_TRANSIENT. It exercises
+ * extra manoeuvres to protect our generational GC. Use of this function is
+ * considered archaic. Use a modern way instead.
+ *
+ * @param[in] ary An object of ::RArray.
+ * @return The backend C array.
+ *
+ * @internal
+ *
+ * That said... there are extension libraries in the wild who uses it. We
+ * cannot but continue supporting.
+ */
static inline VALUE *
RARRAY_PTR(VALUE ary)
{
@@ -249,6 +551,17 @@ RARRAY_PTR(VALUE ary)
return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp));
}
+/**
+ * Assigns an object in an array.
+ *
+ * @param[out] ary Destination array object.
+ * @param[in] i Index of `ary`.
+ * @param[in] v Arbitrary ruby object.
+ * @pre `ary` must be an instance of ::RArray.
+ * @pre `ary`'s length must be longer than or equal to `i`.
+ * @pre `i` must be greater than or equal to zero.
+ * @post `ary`'s `i`th element is set to `v`.
+ */
static inline void
RARRAY_ASET(VALUE ary, long i, VALUE v)
{
@@ -256,7 +569,9 @@ RARRAY_ASET(VALUE ary, long i, VALUE v)
RB_OBJ_WRITE(ary, &ptr[i], v));
}
-/*
+/**
+ * @deprecated
+ *
* :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms
* for more sanity checks). However there were situations where the address of
* this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this
diff --git a/include/ruby/internal/core/rbasic.h b/include/ruby/internal/core/rbasic.h
index aafec2422f..4617f743a7 100644
--- a/include/ruby/internal/core/rbasic.h
+++ b/include/ruby/internal/core/rbasic.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RBasic.
*/
#include "ruby/internal/attr/artificial.h"
@@ -31,22 +31,60 @@
#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
-
+/**
+ * Convenient casting macro.
+ *
+ * @param obj Arbitrary Ruby object.
+ * @return The passed object casted to ::RBasic.
+ */
+#define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj))
/** @cond INTERNAL_MACRO */
+#define RBASIC_CLASS RBASIC_CLASS
+#define RBIMPL_RVALUE_EMBED_LEN_MAX 3
+#define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX
#define RBIMPL_EMBED_LEN_MAX_OF(T) \
RBIMPL_CAST((int)(sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]) / (sizeof(T))))
/** @endcond */
-#define RBIMPL_RVALUE_EMBED_LEN_MAX 3
-enum ruby_rvalue_flags { RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX };
+/**
+ * This is an enum because GDB wants it (rather than a macro). People need not
+ * bother.
+ */
+enum ruby_rvalue_flags {
+ /** Max possible number of objects that can be embedded. */
+ RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX
+};
+/**
+ * Ruby's object's, base components. Every single ruby objects have them in
+ * common.
+ */
struct
RUBY_ALIGNAS(SIZEOF_VALUE)
RBasic {
- VALUE flags; /**< @see enum ::ruby_fl_type. */
+
+ /**
+ * Per-object flags. Each ruby objects have their own characteristics
+ * apart from their classes. For instance whether an object is frozen or
+ * not is not controlled by its class. This is where such properties are
+ * stored.
+ *
+ * @see enum ::ruby_fl_type
+ *
+ * @note This is ::VALUE rather than an enum for alignment purpose. Back
+ * in the 1990s there were no such thing like `_Alignas` in C.
+ */
+ VALUE flags;
+
+ /**
+ * Class of an object. Every object has its class. Also, everything is an
+ * object in Ruby. This means classes are also objects. Classes have
+ * their own classes, classes of classes have their classes, too ... and
+ * it recursively continues forever.
+ *
+ * Also note the `const` qualifier. In ruby an object cannot "change" its
+ * class.
+ */
const VALUE klass;
#ifdef __cplusplus
@@ -70,12 +108,46 @@ RBasic {
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * Make the object invisible from Ruby code.
+ *
+ * It is useful to let Ruby's GC manage your internal data structure -- The
+ * object keeps being managed by GC, but `ObjectSpace.each_object` never yields
+ * the object.
+ *
+ * Note that the object also lose a way to call a method on it.
+ *
+ * @param[out] obj A Ruby object.
+ * @return The passed object.
+ * @post The object is destructively modified to be invisible.
+ * @see rb_obj_reveal
+ */
VALUE rb_obj_hide(VALUE obj);
+
+/**
+ * Make a hidden object visible again.
+ *
+ * It is the caller's responsibility to pass the right `klass` which `obj`
+ * originally used to belong to.
+ *
+ * @param[out] obj A Ruby object.
+ * @param[in] klass Class of `obj`.
+ * @return Passed `obj`.
+ * @pre `obj` was previously hidden.
+ * @post `obj`'s class is `klass`.
+ * @see rb_obj_hide
+ */
VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the class of an object.
+ *
+ * @param[in] obj An object.
+ * @return Its class.
+ */
static inline VALUE
RBASIC_CLASS(VALUE obj)
{
diff --git a/include/ruby/internal/core/rbignum.h b/include/ruby/internal/core/rbignum.h
index 3cd7d19850..1d31743235 100644
--- a/include/ruby/internal/core/rbignum.h
+++ b/include/ruby/internal/core/rbignum.h
@@ -17,15 +17,16 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Routines to manipulate struct RBignum.
+ * @note The struct RBignum itself is opaque.
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/internal/stdbool.h"
-#define RBIGNUM_SIGN rb_big_sign
+#define RBIGNUM_SIGN rb_big_sign /**< @alias{rb_big_sign} */
/** @cond INTERNAL_MACRO */
#define RBIGNUM_POSITIVE_P RBIGNUM_POSITIVE_P
@@ -33,9 +34,29 @@
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * The "sign" of a bignum.
+ *
+ * @param[in] num An object of RBignum.
+ * @retval 1 It is greater than or equal to zero.
+ * @retval 0 It is less than zero.
+ *
+ * @internal
+ *
+ * Implementation wise, unlike fixnums (which are 2's complement), bignums are
+ * signed magnitude system. Theoretically it could be possible to have
+ * negative zero instances. But in reality there is no way to create such
+ * thing. Nobody ever needed that kind of insanity.
+ */
int rb_big_sign(VALUE num);
RBIMPL_SYMBOL_EXPORT_END()
+/**
+ * Checks if the bignum is positive.
+ * @param[in] b An object of RBignum.
+ * @retval false `b` is less than zero.
+ * @retval true Otherwise.
+ */
static inline bool
RBIGNUM_POSITIVE_P(VALUE b)
{
@@ -43,6 +64,12 @@ RBIGNUM_POSITIVE_P(VALUE b)
return RBIGNUM_SIGN(b);
}
+/**
+ * Checks if the bignum is negative.
+ * @param[in] b An object of RBignum.
+ * @retval true `b` is less than zero.
+ * @retval false Otherwise.
+ */
static inline bool
RBIGNUM_NEGATIVE_P(VALUE b)
{
diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h
index 0aa6b1290e..b0b6bfc80c 100644
--- a/include/ruby/internal/core/rclass.h
+++ b/include/ruby/internal/core/rclass.h
@@ -17,31 +17,77 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Routines to manipulate struct RClass.
+ * @note The struct RClass itself is opaque.
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/cast.h"
-#define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID
+/** @cond INTERNAL_MACRO */
#define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT
-#define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT
+/** @endcond */
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an RClass.
+ * @return The passed object casted to RClass.
+ */
#define RCLASS(obj) RBIMPL_CAST((struct RClass *)(obj))
+
+/** @alias{RCLASS} */
#define RMODULE RCLASS
+
+/** @alias{rb_class_get_superclass} */
#define RCLASS_SUPER rb_class_get_superclass
+/**
+ * @private
+ *
+ * Bits that you can set to ::RBasic::flags.
+ *
+ * @internal
+ *
+ * Why is it here, given RClass itself is not?
+ */
enum ruby_rmodule_flags {
- RMODULE_IS_OVERLAID = RUBY_FL_USER2,
- RMODULE_IS_REFINEMENT = RUBY_FL_USER3,
- RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4
+ /**
+ * This flag has something to do with refinements. A module created using
+ * rb_mod_refine() has this flag set. This is the bit which controls
+ * difference between normal inclusion versus refinements.
+ */
+ RMODULE_IS_REFINEMENT = RUBY_FL_USER3
};
struct RClass; /* Opaque, declared here for RCLASS() macro. */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-VALUE rb_class_get_superclass(VALUE);
+/**
+ * Returns the superclass of a class.
+ * @param[in] klass An object of RClass.
+ * @retval RUBY_Qfalse `klass` has no super class.
+ * @retval otherwise Raw superclass of `klass`
+ * @see rb_class_superclass
+ *
+ * ### Q&A ###
+ *
+ * - Q: How can a class have no super class?
+ *
+ * - A: `klass` could be a module. Or it could be ::rb_cBasicObject.
+ *
+ * - Q: What do you mean by "raw" superclass?
+ *
+ * - A: This is a really good question. The answer is that this function
+ * returns something different from what you would normally expect. On
+ * occasions ruby inserts hidden classes in a hierarchy of class
+ * inheritance behind-the-scene. Such classes are called "iclass"es and
+ * distinguished using ::RUBY_T_ICLASS in C level. They are truly
+ * transparent from Ruby level but can be accessed from C, by using this
+ * API.
+ */
+VALUE rb_class_get_superclass(VALUE klass);
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_RCLASS_H */
diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h
index 9432b2ed7a..43ab3c01e7 100644
--- a/include/ruby/internal/core/rdata.h
+++ b/include/ruby/internal/core/rdata.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RData.
*/
#include "ruby/internal/config.h"
@@ -36,6 +36,7 @@
#include "ruby/internal/value_type.h"
#include "ruby/defines.h"
+/** @cond INTERNAL_MACRO */
#ifdef RUBY_UNTYPED_DATA_WARNING
# /* Take that. */
#elif defined(RUBY_EXPORT)
@@ -44,39 +45,160 @@
# 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"))
+
+#define RBIMPL_MACRO_SELECT(x, y) x ## y
+#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y)
/** @endcond */
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RData.
+ * @return The passed object casted to ::RData.
+ */
#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj))
+
+/**
+ * Convenient getter macro.
+ *
+ * @param obj An object, which is in fact an ::RData.
+ * @return The passed object's ::RData::data field.
+ */
#define DATA_PTR(obj) RDATA(obj)->data
-#define RBIMPL_MACRO_SELECT(x, y) x ## y
-#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y)
+
+/**
+ * This is a value you can set to ::RData::dfree. Setting this means the data
+ * was allocated using ::ruby_xmalloc() (or variants), and shall be freed using
+ * ::ruby_xfree().
+ *
+ * @warning Do not use this if you want to use system malloc, because the
+ * system and Ruby might or might not share the same malloc
+ * implementation.
+ */
#define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1)
+
+/**
+ * This is a value you can set to ::RData::dfree. Setting this means the data
+ * is managed by someone else, like, statically allocated. Of course you are
+ * on your own then.
+ */
#define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0)
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/*
#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func))
*/
+
+/**
+ * This is the type of callbacks registered to ::RData. The argument is the
+ * `data` field.
+ */
typedef void (*RUBY_DATA_FUNC)(void*);
+/**
+ * @deprecated
+ *
+ * Old "untyped" user data. It has roughly the same usage as struct
+ * ::RTypedData, but lacked several features such as support for compaction GC.
+ * Use of this struct is not recommended any longer. If it is dead necessary,
+ * please inform the core devs about your usage.
+ *
+ * @internal
+ *
+ * @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded
+ * too many warnings in the core. Maybe we want to retry later... Just add
+ * deprecated document for now.
+ */
struct RData {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /**
+ * This function is called when the object is experiencing GC marks. If it
+ * contains references to other Ruby objects, you need to mark them also.
+ * Otherwise GC will smash your data.
+ *
+ * @see rb_gc_mark()
+ * @warning This is called during GC runs. Object allocations are
+ * impossible at that moment (that is why GC runs).
+ */
RUBY_DATA_FUNC dmark;
+
+ /**
+ * This function is called when the object is no longer used. You need to
+ * do whatever necessary to avoid memory leaks.
+ *
+ * @warning This is called during GC runs. Object allocations are
+ * impossible at that moment (that is why GC runs).
+ */
RUBY_DATA_FUNC dfree;
+
+ /** Pointer to the actual C level struct that you want to wrap. */
void *data;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * This is the primitive way to wrap an existing C struct into ::RData.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] datap Pointer to the target C struct.
+ * @param[in] dmark Mark function.
+ * @param[in] dfree Free function.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return An allocated object that wraps `datap`.
+ */
VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
+
+/**
+ * Identical to rb_data_object_wrap(), except it allocates a new data region
+ * internally instead of taking an existing one. The allocation is done using
+ * ruby_calloc(). Hence it makes no sense to pass anything other than
+ * ::RUBY_DEFAULT_FREE to the last argument.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] size Requested size of memory to allocate.
+ * @param[in] dmark Mark function.
+ * @param[in] dfree Free function.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return An allocated object that wraps a new `size` byte region.
+ */
VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
+
+/**
+ * @private
+ * Documented in include/ruby/internal/globals.h
+ */
RUBY_EXTERN VALUE rb_cObject;
RBIMPL_SYMBOL_EXPORT_END()
+/**
+ * Converts sval, a pointer to your struct, into a Ruby object.
+ *
+ * @param klass A ruby level class.
+ * @param mark Mark function.
+ * @param free Free function.
+ * @param sval A pointer to your struct.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return A created Ruby object.
+ */
#define Data_Wrap_Struct(klass, mark, free, sval) \
rb_data_object_wrap( \
(klass), \
@@ -84,6 +206,20 @@ RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free))
+/**
+ * @private
+ *
+ * This is an implementation detail of #Data_Make_Struct. People don't use it
+ * directly.
+ *
+ * @param result Variable name of created Ruby object.
+ * @param klass Ruby level class of the object.
+ * @param type Type name of the C struct.
+ * @param size Size of the C struct.
+ * @param mark Mark function.
+ * @param free Free function.
+ * @param sval Variable name of created C struct.
+ */
#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \
VALUE result = rb_data_object_zalloc( \
(klass), \
@@ -93,6 +229,21 @@ RBIMPL_SYMBOL_EXPORT_END()
(sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
+/**
+ * Identical to #Data_Wrap_Struct, except it allocates a new data region
+ * internally instead of taking an existing one. The allocation is done using
+ * ruby_calloc(). Hence it makes no sense to pass anything other than
+ * ::RUBY_DEFAULT_FREE to the `free` argument.
+ *
+ * @param klass Ruby level class of the returning object.
+ * @param type Type name of the C struct.
+ * @param mark Mark function.
+ * @param free Free function.
+ * @param sval Variable name of created C struct.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return A created Ruby object.
+ */
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
#define Data_Make_Struct(klass, type, mark, free, sval) \
RB_GNUC_EXTENSION({ \
@@ -116,16 +267,47 @@ RBIMPL_SYMBOL_EXPORT_END()
sizeof(type))
#endif
+/**
+ * Obtains a C struct from inside of a wrapper Ruby object.
+ *
+ * @param obj An instance of ::RData.
+ * @param type Type name of the C struct.
+ * @param sval Variable name of obtained C struct.
+ * @return Unwrapped C struct that `obj` holds.
+ */
#define Data_Get_Struct(obj, type, sval) \
((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj)))
RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_data_object_wrap(). People don't use
+ * it directly.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] ptr Pointer to the target C struct.
+ * @param[in] mark Mark function.
+ * @param[in] free Free function.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return An allocated object that wraps `datap`.
+ */
static inline VALUE
rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free)
{
return rb_data_object_wrap(klass, ptr, mark, free);
}
+/**
+ * @private
+ *
+ * This is an implementation detail of #Data_Get_Struct. People don't use it
+ * directly.
+ *
+ * @param[in] obj An instance of ::RData.
+ * @return Unwrapped C struct that `obj` holds.
+ */
static inline void *
rb_data_object_get(VALUE obj)
{
@@ -134,6 +316,15 @@ rb_data_object_get(VALUE obj)
}
RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
+/**
+ * @private
+ *
+ * This is an implementation detail of #Data_Get_Struct. People don't use it
+ * directly.
+ *
+ * @param[in] obj An instance of ::RData.
+ * @return Unwrapped C struct that `obj` holds.
+ */
static inline void *
rb_data_object_get_warning(VALUE obj)
{
@@ -149,6 +340,20 @@ rb_data_object_get_warning(VALUE obj)
(rb_data_object_wrap_warning)(klass, ptr, mark, free)))
#endif
+/**
+ * This is an implementation detail of #Data_Make_Struct. People don't use it
+ * directly.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] mark_func Mark function.
+ * @param[in] free_func Free function.
+ * @param[in] datap Variable of created C struct.
+ * @param[in] size Requested size of allocation.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return A created Ruby object.
+ * @post `*datap` holds the created C struct.
+ */
static inline VALUE
rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size)
{
@@ -157,21 +362,14 @@ rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_f
}
RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap"))
+/** @deprecated This function was renamed to rb_data_object_wrap(). */
static inline VALUE
rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
return rb_data_object_wrap(klass, data, dmark, dfree);
}
-RBIMPL_ATTR_DEPRECATED(("by: rb_cObject. Will be removed in 3.1."))
-RBIMPL_ATTR_PURE()
-static inline VALUE
-rb_cData(void)
-{
- return rb_cObject;
-}
-#define rb_cData rb_cData()
-
+/** @cond INTERNAL_MACRO */
#define rb_data_object_wrap_0 rb_data_object_wrap
#define rb_data_object_wrap_1 rb_data_object_wrap_warning
#define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */
@@ -184,4 +382,5 @@ rb_cData(void)
#define rb_data_object_make_1 rb_data_object_make_warning
#define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */
#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING)
+/** @endcond */
#endif /* RBIMPL_RDATA_H */
diff --git a/include/ruby/internal/core/rfile.h b/include/ruby/internal/core/rfile.h
index 464625b2bd..f8dddde9e5 100644
--- a/include/ruby/internal/core/rfile.h
+++ b/include/ruby/internal/core/rfile.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RFile.
*/
#include "ruby/internal/core/rbasic.h"
@@ -27,10 +27,25 @@
* into ruby/ruby.h. We follow that tradition. */
struct rb_io_t;
+/**
+ * Ruby's File and IO. Ruby's IO are not just file descriptors. They have
+ * buffers. They also have encodings. Various information are controlled
+ * using this struct.
+ */
struct RFile {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /** IO's specific fields. */
struct rb_io_t *fptr;
};
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RFile.
+ * @return The passed object casted to ::RFile.
+ */
#define RFILE(obj) RBIMPL_CAST((struct RFile *)(obj))
#endif /* RBIMPL_RFILE_H */
diff --git a/include/ruby/internal/core/rhash.h b/include/ruby/internal/core/rhash.h
index cffd0b28ce..61d2c15d87 100644
--- a/include/ruby/internal/core/rhash.h
+++ b/include/ruby/internal/core/rhash.h
@@ -17,20 +17,9 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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-broken. The situation (as of writing) 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Routines to manipulate struct RHash.
+ * @note The struct RHash itself is opaque.
*/
#include "ruby/internal/config.h"
@@ -44,18 +33,111 @@
# include "ruby/backward.h"
#endif
+/**
+ * Retrieves the internal table.
+ *
+ * @param[in] h An instance of RHash.
+ * @pre `h` must be of ::RUBY_T_HASH.
+ * @return A struct st_table which has the contents of this hash.
+ * @note Nowadays as Ruby evolved over ages, RHash has multiple backend
+ * storage engines. `h`'s backend is not guaranteed to be a
+ * st_table. This function creates one when necessary.
+ */
#define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__)
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * Declaration of rb_hash_iter_lev() is at include/ruby/backward.h.
+ */
#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h)
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * Declaration of rb_hash_ifnone() is at include/ruby/backward.h.
+ */
#define RHASH_IFNONE(h) rb_hash_ifnone(h)
+
+/**
+ * Queries the size of the hash. Size here means the number of keys that the
+ * hash stores.
+ *
+ * @param[in] h An instance of RHash.
+ * @pre `h` must be of ::RUBY_T_HASH.
+ * @return The size of the hash.
+ */
#define RHASH_SIZE(h) rb_hash_size_num(h)
+
+/**
+ * Checks if the hash is empty.
+ *
+ * @param[in] h An instance of RHash.
+ * @pre `h` must be of ::RUBY_T_HASH.
+ * @retval true It is.
+ * @retval false It isn't.
+ */
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
+
+/**
+ * Destructively updates the default value of the hash.
+ *
+ * @param[out] h An instance of RHash.
+ * @param[in] ifnone Arbitrary default value.
+ * @pre `h` must be of ::RUBY_T_HASH.
+ *
+ * @internal
+ *
+ * But why you can set this, given rb_hash_ifnone() doesn't exist?
+ */
#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone)
struct st_table; /* in ruby/st.h */
RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * This is the implementation detail of #RHASH_SIZE. People don't call this
+ * directly.
+ *
+ * @param[in] hash An instance of RHash.
+ * @pre `hash` must be of ::RUBY_T_HASH.
+ * @return The size of the hash.
+ */
size_t rb_hash_size_num(VALUE hash);
-struct st_table *rb_hash_tbl(VALUE, const char *file, int line);
+
+/**
+ * This is the implementation detail of #RHASH_TBL. People don't call this
+ * directly.
+ *
+ * @param[in] hash An instance of RHash.
+ * @param[in] file The `__FILE__`.
+ * @param[in] line The `__LINE__`.
+ * @pre `hash` must be of ::RUBY_T_HASH.
+ * @return Table that has the contents of the hash.
+ */
+struct st_table *rb_hash_tbl(VALUE hash, const char *file, int line);
+
+/**
+ * This is the implementation detail of #RHASH_SET_IFNONE. People don't call
+ * this directly.
+ *
+ * @param[out] hash An instance of RHash.
+ * @param[in] ifnone Arbitrary default value.
+ * @pre `hash` must be of ::RUBY_T_HASH.
+ */
VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/core/rmatch.h b/include/ruby/internal/core/rmatch.h
index 03ab5e5d82..2d2fd897f5 100644
--- a/include/ruby/internal/core/rmatch.h
+++ b/include/ruby/internal/core/rmatch.h
@@ -17,18 +17,23 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RMatch.
+ * @return The passed object casted to ::RMatch.
+ */
#define RMATCH(obj) RBIMPL_CAST((struct RMatch *)(obj))
/** @cond INTERNAL_MACRO */
#define RMATCH_REGS RMATCH_REGS
@@ -37,31 +42,99 @@
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 ...? */
+/**
+ * @old{re_pattern_buffer}
+ *
+ * @internal
+ *
+ * @shyouhei wonders: is anyone actively using this typedef ...?
+ */
typedef struct re_pattern_buffer Regexp;
+/**
+ * Represents the region of a capture group. This is basically for caching
+ * purpose. re_registers have similar concepts (`beg` and `end`) but they are
+ * in `ptrdiff_t*`. In order for us to implement `MatchData#offset` that info
+ * has to be converted to offset integers. This is the struct to hold such
+ * things.
+ *
+ * @internal
+ *
+ * But why on earth it has to be visible from extension libraries?
+ */
struct rmatch_offset {
- long beg;
- long end;
+ long beg; /**< Beginning of a group. */
+ long end; /**< End of a group. */
};
+/** Represents a match. */
struct rmatch {
+ /**
+ * "Registers" of a match. This is a quasi-opaque struct that holds
+ * execution result of a match. Roughly resembles `&~`.
+ */
struct re_registers regs;
+ /** Capture group offsets, in C array. */
struct rmatch_offset *char_offset;
+
+ /** Number of ::rmatch_offset that ::rmatch::char_offset holds. */
int char_offset_num_allocated;
};
+/**
+ * Regular expression execution context. When a regular expression "matches"
+ * to a string, it generates capture groups etc. This struct holds that info.
+ * Visible from Ruby as an instance of `MatchData`.
+ *
+ * @note There is no way for extension libraries to manually generate this
+ * struct except by actually exercising the match operation of a regular
+ * expression.
+ */
struct RMatch {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /**
+ * The target string that the match was made against.
+ */
VALUE str;
+
+ /**
+ * The result of this match.
+ */
struct rmatch *rmatch;
+
+ /**
+ * The expression of this match.
+ */
VALUE regexp; /* RRegexp */
};
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
-RBIMPL_ATTR_RETURNS_NONNULL()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the raw ::re_registers.
+ *
+ * @param[in] match A match object
+ * @pre `match` must be of ::RMatch.
+ * @return Its execution result.
+ * @note Good. So you are aware of the fact that it could return NULL.
+ * Yes. It actually does. This is a really bizarre thing. The
+ * situation is about `String#gsub` and its family. They take
+ * strings as arguments, like `"foo".sub("bar", "baz")`. On such
+ * situations, in order to optimise memory allocations, these
+ * methods do not involve regular expressions at all. They just
+ * sequentially scan the receiver. Okay. The story begins here.
+ * Even when they do not kick our regexp engine, there must be
+ * backref objects e.g. `$&`. But how? You know what? Ruby fakes
+ * them. It allocates an empty ::RMatch and behaves as if there
+ * were execution contexts. In reality there weren't. No
+ * ::re_registers are allocated then. There is no way for this
+ * function but to return NULL for those fake ::RMatch. This is
+ * the reason for the nullability of this function.
+ */
static inline struct re_registers *
RMATCH_REGS(VALUE match)
{
diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h
index c352c87a40..b1c2e1b0a9 100644
--- a/include/ruby/internal/core/robject.h
+++ b/include/ruby/internal/core/robject.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RObject.
*/
#include "ruby/internal/config.h"
@@ -34,50 +34,130 @@
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RObject.
+ * @return The passed object casted to ::RObject.
+ */
#define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj))
+/** @cond INTERNAL_MACRO */
#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
#define ROBJECT_EMBED ROBJECT_EMBED
-/** @cond INTERNAL_MACRO */
-#define ROBJECT_NUMIV ROBJECT_NUMIV
+#define ROBJECT_IV_CAPACITY ROBJECT_IV_CAPACITY
#define ROBJECT_IVPTR ROBJECT_IVPTR
-#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL
/** @endcond */
-enum ruby_robject_flags { ROBJECT_EMBED = RUBY_FL_USER1 };
+/**
+ * @private
+ *
+ * Bits that you can set to ::RBasic::flags.
+ */
+enum ruby_robject_flags {
+ /**
+ * This flag has something to do with memory footprint. If the object is
+ * "small" enough, ruby tries to be creative to abuse padding bits of
+ * struct ::RObject for storing instance variables. This flag denotes that
+ * situation.
+ *
+ * @warning This bit has to be considered read-only. Setting/clearing
+ * this bit without corresponding fix up must cause immediate
+ * SEGV. Also, internal structures of an object change
+ * dynamically and transparently throughout of its lifetime.
+ * Don't assume it being persistent.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store instance variables. Might better be hidden.
+ */
+ ROBJECT_EMBED = RUBY_FL_USER1
+};
-enum ruby_robject_consts { ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) };
+#if !USE_RVARGC
+/**
+ * This is an enum because GDB wants it (rather than a macro). People need not
+ * bother.
+ */
+enum ruby_robject_consts {
+ /** Max possible number of instance variables that can be embedded. */
+ ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
+};
+#endif
struct st_table;
+/**
+ * Ruby's ordinal objects. Unless otherwise special cased, all predefined and
+ * user-defined classes share this struct to hold their instances.
+ */
struct RObject {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /** Object's specific fields. */
union {
+
+ /**
+ * Object that use separated memory region for instance variables use
+ * this pattern.
+ */
struct {
- uint32_t numiv;
+ /** Pointer to a C array that holds instance variables. */
VALUE *ivptr;
- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
+
+ /**
+ * This is a table that holds instance variable name to index
+ * mapping. Used when accessing instance variables using names.
+ *
+ * @internal
+ *
+ * This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`.
+ */
+ struct rb_id_table *iv_index_tbl;
} heap;
+
+#if USE_RVARGC
+ /* Embedded instance variables. When an object is small enough, it
+ * uses this area to store the instance variables.
+ *
+ * This is a length 1 array because:
+ * 1. GCC has a bug that does not optimize C flexible array members
+ * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
+ * 2. Zero length arrays are not supported by all compilers
+ */
+ VALUE ary[1];
+#else
+ /**
+ * Embedded instance variables. When an object is small enough, it
+ * uses this area to store the instance variables.
+ */
VALUE ary[ROBJECT_EMBED_LEN_MAX];
+#endif
} 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;
- }
-}
+/* Offsets for YJIT */
+#ifndef __cplusplus
+static const int32_t ROBJECT_OFFSET_AS_HEAP_IVPTR = offsetof(struct RObject, as.heap.ivptr);
+static const int32_t ROBJECT_OFFSET_AS_HEAP_IV_INDEX_TBL = offsetof(struct RObject, as.heap.iv_index_tbl);
+static const int32_t ROBJECT_OFFSET_AS_ARY = offsetof(struct RObject, as.ary);
+#endif
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the instance variables.
+ *
+ * @param[in] obj Object in question.
+ * @return Its instance variables, in C array.
+ * @pre `obj` must be an instance of ::RObject.
+ *
+ * @internal
+ *
+ * @shyouhei finds no reason for this to be visible from extension libraries.
+ */
static inline VALUE *
ROBJECT_IVPTR(VALUE obj)
{
diff --git a/include/ruby/internal/core/rregexp.h b/include/ruby/internal/core/rregexp.h
index f289ee1dda..cf54a399f1 100644
--- a/include/ruby/internal/core/rregexp.h
+++ b/include/ruby/internal/core/rregexp.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RRegexp.
*/
#include "ruby/internal/attr/artificial.h"
@@ -28,7 +28,20 @@
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RRegexp.
+ * @return The passed object casted to ::RRegexp.
+ */
#define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj))
+
+/**
+ * Convenient accessor macro.
+ *
+ * @param obj An object, which is in fact an ::RRegexp.
+ * @return The passed object's pattern buffer.
+ */
#define RREGEXP_PTR(obj) (RREGEXP(obj)->ptr)
/** @cond INTERNAL_MACRO */
#define RREGEXP_SRC RREGEXP_SRC
@@ -37,17 +50,55 @@
#define RREGEXP_SRC_END RREGEXP_SRC_END
/** @endcond */
-struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */
+struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */
+/**
+ * Ruby's regular expression. A regexp is compiled into its own intermediate
+ * representation. This one holds that info. Regexp "match" operation then
+ * executes that IR.
+ */
struct RRegexp {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /**
+ * The pattern buffer. This is a quasi-opaque struct that holds compiled
+ * intermediate representation of the regular expression.
+ *
+ * @note Compilation of a regexp could be delayed until actual match.
+ */
struct re_pattern_buffer *ptr;
+
+ /** Source code of this expression. */
const VALUE src;
+
+ /**
+ * Reference count. A regexp match can take extraordinarily long time to
+ * run. Ruby's regular expression is heavily extended and not a regular
+ * language any longer; runs in NP-time in practice. Now, Ruby also has
+ * threads and GVL. In order to prevent long GVL lockup, our regexp engine
+ * can release it on occasions. This means that multiple threads can touch
+ * a regular expressions at once. That itself is okay. But their cleanup
+ * phase shall wait for all the concurrent runs, to prevent use-after-free
+ * situation. This field is used to count such threads that are executing
+ * this particular pattern buffer.
+ *
+ * @warning Of course, touching this field from extension libraries causes
+ * catastrophic effects. Just leave it.
+ */
unsigned long usecnt;
};
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Convenient getter function.
+ *
+ * @param[in] rexp The regular expression in question.
+ * @return The source code of the regular expression.
+ * @pre `rexp` must be of ::RRegexp.
+ */
static inline VALUE
RREGEXP_SRC(VALUE rexp)
{
@@ -59,6 +110,17 @@ RREGEXP_SRC(VALUE rexp)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Convenient getter function.
+ *
+ * @param[in] rexp The regular expression in question.
+ * @return The source code of the regular expression, in C's string.
+ * @pre `rexp` must be of ::RRegexp.
+ *
+ * @internal
+ *
+ * It seems nobody uses this function in the wild. Subject to hide?
+ */
static inline char *
RREGEXP_SRC_PTR(VALUE rexp)
{
@@ -67,6 +129,17 @@ RREGEXP_SRC_PTR(VALUE rexp)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Convenient getter function.
+ *
+ * @param[in] rexp The regular expression in question.
+ * @return The length of the source code of the regular expression.
+ * @pre `rexp` must be of ::RRegexp.
+ *
+ * @internal
+ *
+ * It seems nobody uses this function in the wild. Subject to hide?
+ */
static inline long
RREGEXP_SRC_LEN(VALUE rexp)
{
@@ -75,6 +148,17 @@ RREGEXP_SRC_LEN(VALUE rexp)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Convenient getter function.
+ *
+ * @param[in] rexp The regular expression in question.
+ * @return The end of the source code of the regular expression.
+ * @pre `rexp` must be of ::RRegexp.
+ *
+ * @internal
+ *
+ * It seems nobody uses this function in the wild. Subject to hide?
+ */
static inline char *
RREGEXP_SRC_END(VALUE rexp)
{
diff --git a/include/ruby/internal/core/rstring.h b/include/ruby/internal/core/rstring.h
index d073da1d2c..e394ab7dca 100644
--- a/include/ruby/internal/core/rstring.h
+++ b/include/ruby/internal/core/rstring.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RString.
*/
#include "ruby/internal/config.h"
@@ -32,14 +32,22 @@
#include "ruby/internal/warning_push.h"
#include "ruby/assert.h"
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RString.
+ * @return The passed object casted to ::RString.
+ */
#define RSTRING(obj) RBIMPL_CAST((struct RString *)(obj))
+
+/** @cond INTERNAL_MACRO */
#define RSTRING_NOEMBED RSTRING_NOEMBED
+#if !USE_RVARGC
#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK
#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT
#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX
+#endif
#define RSTRING_FSTR RSTRING_FSTR
-
-/** @cond INTERNAL_MACRO */
#define RSTRING_EMBED_LEN RSTRING_EMBED_LEN
#define RSTRING_LEN RSTRING_LEN
#define RSTRING_LENINT RSTRING_LENINT
@@ -47,69 +55,385 @@
#define RSTRING_END RSTRING_END
/** @endcond */
+/**
+ * @name Conversion of Ruby strings into C's
+ *
+ * @{
+ */
+
+/**
+ * Ensures that the parameter object is a String. This is done by calling its
+ * `to_str` method.
+ *
+ * @param[in,out] v Arbitrary Ruby object.
+ * @exception rb_eTypeError No implicit conversion defined.
+ * @post `v` is a String.
+ */
#define StringValue(v) rb_string_value(&(v))
+
+/**
+ * Identical to #StringValue, except it returns a `char*`.
+ *
+ * @param[in,out] v Arbitrary Ruby object.
+ * @exception rb_eTypeError No implicit conversion defined.
+ * @return Converted Ruby string's backend C string.
+ * @post `v` is a String.
+ */
#define StringValuePtr(v) rb_string_value_ptr(&(v))
+
+/**
+ * Identical to #StringValuePtr, except it additionally checks for the contents
+ * for viability as a C string. Ruby can accept wider range of contents as
+ * strings, compared to C. This function is to check that.
+ *
+ * @param[in,out] v Arbitrary Ruby object.
+ * @exception rb_eTypeError No implicit conversion defined.
+ * @exception rb_eArgError String is not C-compatible.
+ * @return Converted Ruby string's backend C string.
+ * @post `v` is a String.
+ */
#define StringValueCStr(v) rb_string_value_cstr(&(v))
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define SafeStringValue(v) StringValue(v)
+
+/**
+ * Identical to #StringValue, except it additionally converts the string's
+ * encoding to default external encoding. Ruby has a concept called encodings.
+ * A string can have different encoding than the environment expects. Someone
+ * has to make sure its contents be converted to something suitable. This is
+ * that routine. Call it when necessary.
+ *
+ * @param[in,out] v Arbitrary Ruby object.
+ * @exception rb_eTypeError No implicit conversion defined.
+ * @return Converted Ruby string's backend C string.
+ * @post `v` is a String.
+ *
+ * @internal
+ *
+ * Not sure but it seems this macro does not raise on encoding
+ * incompatibilities? Doesn't sound right to @shyouhei.
+ */
#define ExportStringValue(v) do { \
StringValue(v); \
(v) = rb_str_export(v); \
} while (0)
+/** @} */
+
+/**
+ * @private
+ *
+ * Bits that you can set to ::RBasic::flags.
+ *
+ * @warning These enums are not the only bits we use for strings.
+ *
+ * @internal
+ *
+ * Actually all bits through FL_USER1 to FL_USER19 are used for strings. Why
+ * only this tiny part of them are made public here? @shyouhei can find no
+ * reason.
+ */
enum ruby_rstring_flags {
+
+ /**
+ * This flag has something to do with memory footprint. If the string is
+ * short enough, ruby tries to be creative to abuse padding bits of struct
+ * ::RString for storing contents. If this flag is set that string does
+ * _not_ do that, to resort to good old fashioned external allocation
+ * strategy instead.
+ *
+ * @warning This bit has to be considered read-only. Setting/clearing
+ * this bit without corresponding fix up must cause immediate
+ * SEGV. Also, internal structures of a string change
+ * dynamically and transparently throughout of its lifetime.
+ * Don't assume it being persistent.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store a string. Might better be hidden.
+ */
RSTRING_NOEMBED = RUBY_FL_USER1,
+
+#if !USE_RVARGC
+ /**
+ * When a string employs embedded strategy (see ::RSTRING_NOEMBED), these
+ * bits are used to store the number of bytes actually filled into
+ * ::RString::ary.
+ *
+ * @internal
+ *
+ * 3rd parties must not be aware that there even is more than one way to
+ * store a string. Might better be hidden.
+ */
RSTRING_EMBED_LEN_MASK = RUBY_FL_USER2 | RUBY_FL_USER3 | RUBY_FL_USER4 |
RUBY_FL_USER5 | RUBY_FL_USER6,
+#endif
+
/* Actually, string encodings are also encoded into the flags, using
* remaining bits.*/
+
+ /**
+ * This flag has something to do with infamous "f"string. What is a
+ * fstring? Well it is a special subkind of strings that is immutable,
+ * deduped globally, and managed by our GC. It is much like a Symbol (in
+ * fact Symbols are dynamic these days and are backended using fstrings).
+ * This concept has been silently introduced at some point in 2.x era.
+ * Since then it gained wider acceptance in the core. But extension
+ * libraries could not know that until very recently. Strings of this flag
+ * live in a special Limbo deep inside of the interpreter. Never try to
+ * manipulate it by hand.
+ *
+ * @internal
+ *
+ * Fstrings are not the only variant strings that we implement today.
+ * Other things are behind-the-scene. This is the only one that is visible
+ * from extension library. There is no clear reason why it has to be.
+ * Given there are more "polite" ways to create fstrings, it seems this bit
+ * need not be exposed to extension libraries. Might better be hidden.
+ */
RSTRING_FSTR = RUBY_FL_USER17
};
+#if !USE_RVARGC
+/**
+ * This is an enum because GDB wants it (rather than a macro). People need not
+ * bother.
+ */
enum ruby_rstring_consts {
+ /** Where ::RSTRING_EMBED_LEN_MASK resides. */
RSTRING_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 2,
+
+ /** Max possible number of characters that can be embedded. */
RSTRING_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(char) - 1
};
+#endif
+/**
+ * Ruby's String. A string in ruby conceptually has these information:
+ *
+ * - Encoding of the string.
+ * - Length of the string.
+ * - Contents of the string.
+ *
+ * It is worth noting that a string is _not_ an array of characters in ruby.
+ * It has never been. In 1.x a string was an array of integers. Since 2.x a
+ * string is no longer an array of anything. A string is a string -- just like
+ * a Time is not an integer.
+ */
struct RString {
+
+ /** Basic part, including flags and class. */
struct RBasic basic;
+
+ /** String's specific fields. */
union {
+
+ /**
+ * Strings that use separated memory region for contents use this
+ * pattern.
+ */
struct {
+
+ /**
+ * Length of the string, not including terminating NUL character.
+ *
+ * @note This is in bytes.
+ */
long len;
+
+ /**
+ * Pointer to the contents of the string. In the old days each
+ * string had dedicated memory regions. That is no longer true
+ * today, but there still are strings of such properties. This
+ * field could be used to point such things.
+ */
char *ptr;
+
+ /** Auxiliary info. */
union {
+
+ /**
+ * Capacity of `*ptr`. A continuous memory region of at least
+ * `capa` bytes is expected to exist at `*ptr`. This can be
+ * bigger than `len`.
+ */
long capa;
+
+ /**
+ * Parent of the string. Nowadays strings can share their
+ * contents each other, constructing gigantic nest of objects.
+ * This situation is called "shared", and this is the field to
+ * control such properties.
+ */
VALUE shared;
} aux;
} heap;
- char ary[RSTRING_EMBED_LEN_MAX + 1];
+
+ /** Embedded contents. */
+ struct {
+#if USE_RVARGC
+ long len;
+ /* This is a length 1 array because:
+ * 1. GCC has a bug that does not optimize C flexible array members
+ * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
+ * 2. Zero length arrays are not supported by all compilers
+ */
+ char ary[1];
+#else
+ /**
+ * When a string is short enough, it uses this area to store the
+ * contents themselves. This was impractical in the 20th century,
+ * but these days 64 bit machines can typically hold 24 bytes here.
+ * Could be sufficiently large. In this case the length is encoded
+ * into the flags.
+ */
+ char ary[RSTRING_EMBED_LEN_MAX + 1];
+#endif
+ } embed;
} as;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
-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);
+/**
+ * Identical to rb_check_string_type(), except it raises exceptions in case of
+ * conversion failures.
+ *
+ * @param[in] obj Target object.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @return Return value of `obj.to_str`.
+ * @see rb_io_get_io
+ * @see rb_ary_to_ary
+ */
+VALUE rb_str_to_str(VALUE obj);
+
+/**
+ * Identical to rb_str_to_str(), except it fills the passed pointer with the
+ * converted object.
+ *
+ * @param[in,out] ptr Pointer to a variable of target object.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @return Return value of `obj.to_str`.
+ * @post `*ptr` is the return value.
+ */
+VALUE rb_string_value(volatile VALUE *ptr);
+
+/**
+ * Identical to rb_str_to_str(), except it returns the converted string's
+ * backend memory region.
+ *
+ * @param[in,out] ptr Pointer to a variable of target object.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @post `*ptr` is the return value of `obj.to_str`.
+ * @return Pointer to the contents of the return value.
+ */
+char *rb_string_value_ptr(volatile VALUE *ptr);
+
+/**
+ * Identical to rb_string_value_ptr(), except it additionally checks for the
+ * contents for viability as a C string. Ruby can accept wider range of
+ * contents as strings, compared to C. This function is to check that.
+ *
+ * @param[in,out] ptr Pointer to a variable of target object.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @exception rb_eArgError String is not C-compatible.
+ * @post `*ptr` is the return value of `obj.to_str`.
+ * @return Pointer to the contents of the return value.
+ */
+char *rb_string_value_cstr(volatile VALUE *ptr);
+
+/**
+ * Identical to rb_str_to_str(), except it additionally converts the string
+ * into default external encoding. Ruby has a concept called encodings. A
+ * string can have different encoding than the environment expects. Someone
+ * has to make sure its contents be converted to something suitable. This is
+ * that routine. Call it when necessary.
+ *
+ * @param[in] obj Target object.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @return Converted ruby string of default external encoding.
+ */
+VALUE rb_str_export(VALUE obj);
+
+/**
+ * Identical to rb_str_export(), except it converts into the locale encoding
+ * instead.
+ *
+ * @param[in] obj Target object.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @return Converted ruby string of locale encoding.
+ */
+VALUE rb_str_export_locale(VALUE obj);
RBIMPL_ATTR_ERROR(("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead"))
+/**
+ * @private
+ *
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ */
void rb_check_safe_str(VALUE);
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define Check_SafeStr(v) rb_check_safe_str(RBIMPL_CAST((VALUE)(v)))
+
+/**
+ * @private
+ *
+ * Prints diagnostic message to stderr when RSTRING_PTR or RSTRING_END
+ * is NULL.
+ *
+ * @param[in] func The function name where encountered NULL pointer.
+ */
+void rb_debug_rstring_null_ptr(const char *func);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the length of the string.
+ *
+ * @param[in] str String in question.
+ * @return Its length, in bytes.
+ * @pre `str` must be an instance of ::RString, and must has its
+ * ::RSTRING_NOEMBED flag off.
+ *
+ * @internal
+ *
+ * This was a macro before. It was inevitable to be public, since macros are
+ * global constructs. But should it be forever? Now that it is a function,
+ * @shyouhei thinks it could just be eliminated, hidden into implementation
+ * details.
+ */
static inline long
RSTRING_EMBED_LEN(VALUE str)
{
RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING);
RBIMPL_ASSERT_OR_ASSUME(! RB_FL_ANY_RAW(str, RSTRING_NOEMBED));
+#if USE_RVARGC
+ long f = RSTRING(str)->as.embed.len;
+ return f;
+#else
VALUE f = RBASIC(str)->flags;
f &= RSTRING_EMBED_LEN_MASK;
f >>= RSTRING_EMBED_LEN_SHIFT;
return RBIMPL_CAST((long)f);
+#endif
}
RBIMPL_WARNING_PUSH()
@@ -119,6 +443,15 @@ RBIMPL_WARNING_IGNORED(413)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * @private
+ *
+ * "Expands" an embedded string into an ordinal one. This is a function that
+ * returns aggregated type. The returned struct always has its `as.heap.len`
+ * an `as.heap.ptr` fields set appropriately.
+ *
+ * This is an implementation detail that 3rd parties should never bother.
+ */
static inline struct RString
rbimpl_rstring_getmem(VALUE str)
{
@@ -131,7 +464,7 @@ rbimpl_rstring_getmem(VALUE str)
/* 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;
+ retval.as.heap.ptr = RSTRING(str)->as.embed.ary;
return retval;
}
}
@@ -140,6 +473,13 @@ RBIMPL_WARNING_POP()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the length of the string.
+ *
+ * @param[in] str String in question.
+ * @return Its length, in bytes.
+ * @pre `str` must be an instance of ::RString.
+ */
static inline long
RSTRING_LEN(VALUE str)
{
@@ -147,6 +487,13 @@ RSTRING_LEN(VALUE str)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the contents pointer of the string.
+ *
+ * @param[in] str String in question.
+ * @return Pointer to its contents.
+ * @pre `str` must be an instance of ::RString.
+ */
static inline char *
RSTRING_PTR(VALUE str)
{
@@ -163,18 +510,20 @@ RSTRING_PTR(VALUE str)
* 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."
- );
+ rb_debug_rstring_null_ptr("RSTRING_PTR");
}
return ptr;
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the end of the contents pointer of the string.
+ *
+ * @param[in] str String in question.
+ * @return Pointer to its end of contents.
+ * @pre `str` must be an instance of ::RString.
+ */
static inline char *
RSTRING_END(VALUE str)
{
@@ -182,24 +531,38 @@ RSTRING_END(VALUE 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."
- );
+ rb_debug_rstring_null_ptr("RSTRING_END");
}
return &buf.as.heap.ptr[buf.as.heap.len];
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Identical to RSTRING_LEN(), except it differs for the return type.
+ *
+ * @param[in] str String in question.
+ * @exception rb_eRangeError Too long.
+ * @return Its length, in bytes.
+ * @pre `str` must be an instance of ::RString.
+ *
+ * @internal
+ *
+ * This API seems redundant but has actual usages.
+ */
static inline int
RSTRING_LENINT(VALUE str)
{
return rb_long2int(RSTRING_LEN(str));
}
+/**
+ * Convenient macro to obtain the contents and length at once.
+ *
+ * @param str String in question.
+ * @param ptrvar Variable where its contents is stored.
+ * @param lenvar Variable where its length is stored.
+ */
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
# define RSTRING_GETMEM(str, ptrvar, lenvar) \
__extension__ ({ \
diff --git a/include/ruby/internal/core/rstruct.h b/include/ruby/internal/core/rstruct.h
index 17454f7cbe..69be487b59 100644
--- a/include/ruby/internal/core/rstruct.h
+++ b/include/ruby/internal/core/rstruct.h
@@ -17,8 +17,9 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Routines to manipulate struct RStruct.
+ * @note The struct RStruct itself is opaque.
*/
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/dllexport.h"
@@ -30,6 +31,17 @@
# include "ruby/backward.h"
#endif
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * Declaration of rb_struct_ptr() is at include/ruby/backward.h.
+ */
#define RSTRUCT_PTR(st) rb_struct_ptr(st)
/** @cond INTERNAL_MACRO */
#define RSTRUCT_LEN RSTRUCT_LEN
@@ -38,12 +50,46 @@
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-VALUE rb_struct_size(VALUE s);
-VALUE rb_struct_aref(VALUE, VALUE);
-VALUE rb_struct_aset(VALUE, VALUE, VALUE);
+/**
+ * Returns the number of struct members.
+ *
+ * @param[in] st An instance of RStruct.
+ * @return The number of members of `st`.
+ * @pre `st` must be of ::RUBY_T_STRUCT.
+ */
+VALUE rb_struct_size(VALUE st);
+
+/**
+ * Resembles `Struct#[]`.
+ *
+ * @param[in] st An instance of RStruct.
+ * @param[in] k Index a.k.a. key of the struct.
+ * @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String.
+ * @exception rb_eIndexError Numerical index out of range.
+ * @exception rb_eNameError No such key.
+ * @return The member stored at `k` in `st`.
+ * @pre `st` must be of ::RUBY_T_STRUCT.
+ */
+VALUE rb_struct_aref(VALUE st, VALUE k);
+
+/**
+ * Resembles `Struct#[]=`.
+ *
+ * @param[out] st An instance of RStruct.
+ * @param[in] k Index a.k.a. key of the struct.
+ * @param[in] v Value to store.
+ * @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String.
+ * @exception rb_eIndexError Numerical index out of range.
+ * @exception rb_eNameError No such key.
+ * @return Passed `v`.
+ * @pre `st` must be of ::RUBY_T_STRUCT.
+ * @post `v` is stored at `k` in `st`.
+ */
+VALUE rb_struct_aset(VALUE st, VALUE k, VALUE v);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_ARTIFICIAL()
+/** @copydoc rb_struct_size() */
static inline long
RSTRUCT_LEN(VALUE st)
{
@@ -53,6 +99,7 @@ RSTRUCT_LEN(VALUE st)
}
RBIMPL_ATTR_ARTIFICIAL()
+/** @copydoc rb_struct_aset() */
static inline VALUE
RSTRUCT_SET(VALUE st, int k, VALUE v)
{
@@ -62,6 +109,7 @@ RSTRUCT_SET(VALUE st, int k, VALUE v)
}
RBIMPL_ATTR_ARTIFICIAL()
+/** @copydoc rb_struct_aref() */
static inline VALUE
RSTRUCT_GET(VALUE st, int k)
{
diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h
index c038e6f2b8..bbf208867d 100644
--- a/include/ruby/internal/core/rtypeddata.h
+++ b/include/ruby/internal/core/rtypeddata.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines struct ::RTypedData.
*/
#include "ruby/internal/config.h"
@@ -28,6 +28,8 @@
#include "ruby/internal/assume.h"
#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/flag_enum.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
@@ -38,13 +40,68 @@
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value_type.h"
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_TYPE_RB_DATA_TYPE_T 1
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_RB_DATA_TYPE_T_PARENT 1
+
+/**
+ * This is a value you can set to ::rb_data_type_struct::dfree. Setting this
+ * means the data was allocated using ::ruby_xmalloc() (or variants), and shall
+ * be freed using ::ruby_xfree().
+ *
+ * @warning Do not use this if you want to use system malloc, because the
+ * system and Ruby might or might not share the same malloc
+ * implementation.
+ */
#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
+
+/**
+ * This is a value you can set to ::rb_data_type_struct::dfree. Setting this
+ * means the data is managed by someone else, like, statically allocated. Of
+ * course you are on your own then.
+ */
#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
+
+/**
+ * Convenient casting macro.
+ *
+ * @param obj An object, which is in fact an ::RTypedData.
+ * @return The passed object casted to ::RTypedData.
+ */
#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
+
+/**
+ * Convenient getter macro.
+ *
+ * @param v An object, which is in fact an ::RTypedData.
+ * @return The passed object's ::RTypedData::data field.
+ */
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
+
+/** @old{rb_check_typeddata} */
#define Check_TypedStruct(v, t) \
rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
@@ -57,55 +114,365 @@
#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
/** @endcond */
-/* bits for rb_data_type_struct::flags */
-enum rbimpl_typeddata_flags {
+/**
+ * @private
+ *
+ * Bits for rb_data_type_struct::flags.
+ */
+enum
+RBIMPL_ATTR_FLAG_ENUM()
+rbimpl_typeddata_flags {
+ /**
+ * This flag has something to do with Ruby's global interpreter lock. For
+ * maximum safety, Ruby locks the entire VM during GC. However your
+ * callback functions could unintentionally unlock it, for instance when
+ * they try to flush an IO buffer. Such operations are dangerous (threads
+ * then run alongside of GC). By default, to prevent those scenario,
+ * callbacks are deferred until the GC engine is 100% sure threads can run.
+ * This flag skips that; structs with it are deallocated during the sweep
+ * phase.
+ *
+ * Using this flag needs deep understanding of both GC and threads. You
+ * would better leave it unspecified.
+ */
RUBY_TYPED_FREE_IMMEDIATELY = 1,
+
+ /**
+ * This flag has something to do with Ractor. Multiple Ractors run without
+ * protecting each other. Sharing an object among Ractors is basically
+ * dangerous, disabled by default. This flag is used to bypass that
+ * restriction. but setting it is not enough. In addition to do so, an
+ * object also has to be frozen, and be passed to
+ * rb_ractor_make_shareable() before being actually shareable. Of course,
+ * you have to manually prevent race conditions then.
+ *
+ * Using this flag needs deep understanding of multithreaded programming.
+ * You would better leave it unspecified.
+ */
RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
+
+ /**
+ * This flag has something to do with our garbage collector. These days
+ * ruby objects are "generational". There are those who are young and
+ * those who are old. Young objects are prone to die; monitored relatively
+ * extensively by the garbage collector. OTOH old objects tend to live
+ * longer. They are relatively rarely considered. This basically works.
+ * But there is one tweak that has to be exercised. When an elder object
+ * has reference(s) to younger one(s), that referenced objects must not
+ * die. In order to detect additions of such references, old generations
+ * are protected by write barriers. It is a very difficult hack to
+ * appropriately insert write barriers everywhere. This mechanism is
+ * disabled by default for 3rd party extensions (they never get aged). By
+ * specifying this flag you can enable the generational feature to your
+ * data structure. Of course, you have to manually insert write barriers
+ * then.
+ *
+ * Using this flag needs deep understanding of GC internals, often at the
+ * level of source code. You would better leave it unspecified.
+ */
RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
+
+ /**
+ * This flag is mysterious. It seems nobody is currently using it. The
+ * intention of this flag is also unclear. We need further investigations.
+ */
RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */
};
+/**
+ * This is the struct that holds necessary info for a struct. It roughly
+ * resembles a Ruby level class; multiple objects can share a ::rb_data_type_t
+ * instance.
+ */
typedef struct rb_data_type_struct rb_data_type_t;
+/** @copydoc rb_data_type_t */
struct rb_data_type_struct {
+
+ /**
+ * Name of structs of this kind. This is used for diagnostic purposes.
+ * This has to be unique in the process, but doesn't has to be a valid
+ * C/Ruby identifier.
+ */
const char *wrap_struct_name;
+
+ /** Function pointers. Resembles C++ `vtbl`.*/
struct {
+
+ /**
+ * This function is called when the object is experiencing GC marks.
+ * If it contains references to other Ruby objects, you need to mark
+ * them also. Otherwise GC will smash your data.
+ *
+ * @see rb_gc_mark()
+ * @warning This is called during GC runs. Object allocations are
+ * impossible at that moment (that is why GC runs).
+ */
RUBY_DATA_FUNC dmark;
+
+ /**
+ * This function is called when the object is no longer used. You need
+ * to do whatever necessary to avoid memory leaks.
+ *
+ * @warning This is called during GC runs. Object allocations are
+ * impossible at that moment (that is why GC runs).
+ */
RUBY_DATA_FUNC dfree;
+
+ /**
+ * This function is to query the size of the underlying memory regions.
+ *
+ * @internal
+ *
+ * This function has only one usage, which is form inside of
+ * `ext/objspace`.
+ */
size_t (*dsize)(const void *);
+
+ /**
+ * This function is called when the object is relocated. Like
+ * ::rb_data_type_struct::dmark, you need to update references to Ruby
+ * objects inside of your structs.
+ *
+ * @see rb_gc_location()
+ * @warning This is called during GC runs. Object allocations are
+ * impossible at that moment (that is why GC runs).
+ */
RUBY_DATA_FUNC dcompact;
+
+ /**
+ * This field is reserved for future extension. For now, it must be
+ * filled with zeros.
+ */
void *reserved[1]; /* For future extension.
This array *must* be filled with ZERO. */
} function;
+
+ /**
+ * Parent of this class. Sometimes C structs have inheritance-like
+ * relationships. An example is `struct sockaddr` and its family. If you
+ * design such things, make ::rb_data_type_t for each of them and connect
+ * using this field. Ruby can then transparently cast your data back and
+ * forth when you call #TypedData_Get_Struct().
+ *
+ * ```CXX
+ * struct parent { };
+ * static inline const rb_data_type_t parent_type = {
+ * .wrap_struct_name = "parent",
+ * };
+ *
+ * struct child: public parent { };
+ * static inline const rb_data_type_t child_type = {
+ * .wrap_struct_name = "child",
+ * .parent = &parent_type,
+ * };
+ *
+ * // This function can take both parent_class and child_class.
+ * static inline struct parent *
+ * get_parent(VALUE v)
+ * {
+ * struct parent *p;
+ * TypedData_Get_Struct(v, parent_type, struct parent, p);
+ * return p;
+ * }
+ * ```
+ */
const rb_data_type_t *parent;
+
+ /**
+ * Type-specific static data. This area can be used for any purpose by a
+ * programmer who define the type. Ruby does not manage this at all.
+ */
void *data; /* This area can be used for any purpose
by a programmer who define the type. */
+
+ /**
+ * Type-specific behavioural characteristics. This is a bitfield. It is
+ * an EXTREMELY WISE IDEA to leave this field blank. It is designed so
+ * that setting zero is the safest thing to do. If you risk to set any
+ * bits on, you have to know exactly what you are doing.
+ *
+ * @internal
+ *
+ * Why it has to be a ::VALUE? @shyouhei doesn't understand the design.
+ */
VALUE flags; /* RUBY_FL_WB_PROTECTED */
};
+/**
+ * "Typed" user data. By using this, extension libraries can wrap a C struct
+ * to make it visible from Ruby. For instance if you have a `struct timeval`,
+ * and you want users to use it,
+ *
+ * ```CXX
+ * static inline const rb_data_type_t timeval_type = {
+ * // Note that unspecified fields are 0-filled by default.
+ * .wrap_struct_name = "timeval",
+ * .function = {
+ * .dmark = nullptr, // no need to mark
+ * .dfree = RUBY_TYPED_DEFAULT_FREE, // use ruby_xfree()
+ * .dsize = [](auto) {
+ * return sizeof(struct timeval);
+ * },
+ * },
+ * };
+ *
+ * extern "C" void
+ * Init_timeval(void)
+ * {
+ * auto klass = rb_define_class("YourName", rb_cObject);
+ *
+ * rb_define_alloc_func(klass, [](auto klass) {
+ * struct timeval *t;
+ * auto ret = TypedData_Make_Struct(
+ * klass, struct timeval, &timeval_type, t);
+ *
+ * if (auto i = gettimeofday(t, nullptr); i == -1) {
+ * rb_sys_fail("gettimeofday(3)");
+ * }
+ * else {
+ * return ret;
+ * }
+ * });
+ * }
+ * ```
+ */
struct RTypedData {
+
+ /** The part that all ruby objects have in common. */
struct RBasic basic;
+
+ /**
+ * This field stores various information about how Ruby should handle a
+ * data. This roughly resembles a Ruby level class (apart from method
+ * definition etc.)
+ */
const rb_data_type_t *type;
- VALUE typed_flag; /* 1 or not */
+
+ /**
+ * This has to be always 1.
+ *
+ * @internal
+ *
+ * Why, then, this is not a const ::VALUE?
+ */
+ VALUE typed_flag;
+
+ /** Pointer to the actual C level struct that you want to wrap. */
void *data;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
-VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *);
+RBIMPL_ATTR_NONNULL((3))
+/**
+ * This is the primitive way to wrap an existing C struct into ::RTypedData.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] datap Pointer to the target C struct.
+ * @param[in] type The characteristics of the passed data.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return An allocated object that wraps `datap`.
+ */
+VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type);
+
+/**
+ * Identical to rb_data_typed_object_wrap(), except it allocates a new data
+ * region internally instead of taking an existing one. The allocation is done
+ * using ruby_calloc(). Hence it makes no sense for `type->function.dfree` to
+ * be anything other than ::RUBY_TYPED_DEFAULT_FREE.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] size Requested size of memory to allocate.
+ * @param[in] type The characteristics of the passed data.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return An allocated object that wraps a new `size` byte region.
+ */
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type);
+
+/**
+ * Checks for the domestic relationship between the two.
+ *
+ * @param[in] child A data type supposed to be a child of `parent`.
+ * @param[in] parent A data type supposed to be a parent of `child`.
+ * @retval true `child` is a descendent of `parent`.
+ * @retval false Otherwise.
+ *
+ * @internal
+ *
+ * You can path NULL to both arguments, don't know what that means though.
+ */
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
+
+/**
+ * Checks if the given object is of given kind.
+ *
+ * @param[in] obj An instance of ::RTypedData.
+ * @param[in] data_type Expected data type of `obj`.
+ * @retval true `obj` is of `data_type`.
+ * @retval false Otherwise.
+ */
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
+
+/**
+ * Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead
+ * of returning false.
+ *
+ * @param[in] obj An instance of ::RTypedData.
+ * @param[in] data_type Expected data type of `obj`.
+ * @exception rb_eTypeError obj is not of `data_type`.
+ * @return Unwrapped C struct that `obj` holds.
+ * @post Upon successful return `obj`'s type is guaranteed `data_type`.
+ */
void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type);
RBIMPL_SYMBOL_EXPORT_END()
+/**
+ * Converts sval, a pointer to your struct, into a Ruby object.
+ *
+ * @param klass A ruby level class.
+ * @param data_type The type of `sval`.
+ * @param sval A pointer to your struct.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return A created Ruby object.
+ */
#define TypedData_Wrap_Struct(klass,data_type,sval)\
rb_data_typed_object_wrap((klass),(sval),(data_type))
+/**
+ * @private
+ *
+ * This is an implementation detail of #TypedData_Make_Struct. People don't
+ * use it directly.
+ *
+ * @param result Variable name of created Ruby object.
+ * @param klass Ruby level class of the object.
+ * @param type Type name of the C struct.
+ * @param size Size of the C struct.
+ * @param data_type The data type describing `type`.
+ * @param sval Variable name of created C struct.
+ */
#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
(sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
+/**
+ * Identical to #TypedData_Wrap_Struct, except it allocates a new data region
+ * internally instead of taking an existing one. The allocation is done using
+ * ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to
+ * be anything other than ::RUBY_TYPED_DEFAULT_FREE.
+ *
+ * @param klass Ruby level class of the object.
+ * @param type Type name of the C struct.
+ * @param data_type The data type describing `type`.
+ * @param sval Variable name of created C struct.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return A created Ruby object.
+ */
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
#define TypedData_Make_Struct(klass, type, data_type, sval) \
RB_GNUC_EXTENSION({ \
@@ -127,11 +494,32 @@ RBIMPL_SYMBOL_EXPORT_END()
sizeof(type))
#endif
+/**
+ * Obtains a C struct from inside of a wrapper Ruby object.
+ *
+ * @param obj An instance of ::RTypedData.
+ * @param type Type name of the C struct.
+ * @param data_type The data type describing `type`.
+ * @param sval Variable name of obtained C struct.
+ * @exception rb_eTypeError `obj` is not a kind of `data_type`.
+ * @return Unwrapped C struct that `obj` holds.
+ */
#define TypedData_Get_Struct(obj,type,data_type,sval) \
((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type))))
RBIMPL_ATTR_PURE()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * @private
+ *
+ * This is an implementation detail of Check_Type(). People don't use it
+ * directly.
+ *
+ * @param[in] obj Object in question
+ * @retval true `obj` is an instance of ::RTypedData.
+ * @retval false `obj` is an instance of ::RData.
+ * @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
+ */
static inline bool
rbimpl_rtypeddata_p(VALUE obj)
{
@@ -140,6 +528,14 @@ rbimpl_rtypeddata_p(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks whether the passed object is ::RTypedData or ::RData.
+ *
+ * @param[in] obj Object in question
+ * @retval true `obj` is an instance of ::RTypedData.
+ * @retval false `obj` is an instance of ::RData.
+ * @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
+ */
static inline bool
RTYPEDDATA_P(VALUE obj)
{
@@ -156,6 +552,13 @@ RTYPEDDATA_P(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+/**
+ * Queries for the type of given object.
+ *
+ * @param[in] obj Object in question
+ * @return Data type struct that corresponds to `obj`.
+ * @pre `obj` must be an instance of ::RTypedData.
+ */
static inline const struct rb_data_type_struct *
RTYPEDDATA_TYPE(VALUE obj)
{
@@ -169,6 +572,20 @@ RTYPEDDATA_TYPE(VALUE obj)
return RTYPEDDATA(obj)->type;
}
+/**
+ * While we don't stop you from using this function, it seems to be an
+ * implementation detail of #TypedData_Make_Struct, which is preferred over
+ * this one.
+ *
+ * @param[in] klass Ruby level class of the returning object.
+ * @param[in] type The data type
+ * @param[out] datap Return pointer.
+ * @param[in] size Size of the C struct.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eNoMemError Out of memory.
+ * @return A created Ruby object.
+ * @post `*datap` points to the C struct wrapped by the returned object.
+ */
static inline VALUE
rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
{
@@ -177,6 +594,7 @@ rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap,
}
RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap"))
+/** @deprecated This function was renamed to rb_data_typed_object_wrap(). */
static inline VALUE
rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
{
diff --git a/include/ruby/internal/ctype.h b/include/ruby/internal/ctype.h
index aea3e0ca3d..0f7ca6c516 100644
--- a/include/ruby/internal/ctype.h
+++ b/include/ruby/internal/ctype.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Our own, locale independent, character handling routines.
*/
#include "ruby/internal/config.h"
@@ -29,34 +29,161 @@
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/const.h"
#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
+/**
+ * @name Old character classification macros
+ *
+ * What is this #ISPRINT business? Well, according to our VCS and some
+ * internet surfing, it appears that the initial intent of these macros were to
+ * mimic codes appear in common in several GNU projects. As far as @shyouhei
+ * detects they seem to originate GNU regex (that standalone one rather than
+ * Gnulib or Glibc), and at least date back to 1995.
+ *
+ * Let me lawfully quote from a GNU coreutils commit
+ * https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=49803907f5dbd7646184a8912c9db9b09dcd0f22
+ *
+ * > Jim Meyering writes:
+ * >
+ * > "... Some ctype macros are valid only for character codes that
+ * > isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+ * > using /bin/cc or gcc but without giving an ansi option). So, all
+ * > ctype uses should be through macros like ISPRINT... If
+ * > STDC_HEADERS is defined, then autoconf has verified that the ctype
+ * > macros don't need to be guarded with references to isascii. ...
+ * > Defining isascii to 1 should let any compiler worth its salt
+ * > eliminate the && through constant folding."
+ * >
+ * > Bruno Haible adds:
+ * >
+ * > "... Furthermore, isupper(c) etc. have an undefined result if c is
+ * > outside the range -1 <= c <= 255. One is tempted to write isupper(c)
+ * > with c being of type `char', but this is wrong if c is an 8-bit
+ * > character >= 128 which gets sign-extended to a negative value.
+ * > The macro ISUPPER protects against this as well."
+ *
+ * So the intent was to reroute old problematic systems that no longer exist.
+ * At the same time the problems described above no longer hurt us, because we
+ * decided to completely avoid using system-provided isupper etc. to reinvent
+ * the wheel. These macros are entirely legacy; please ignore them.
+ *
+ * But let me also put stress that GNU people are wise; they use those macros
+ * only inside of their own implementations and never let them be public. On
+ * the other hand ruby has thoughtlessly publicised them to 3rd party libraries
+ * since its beginning, which is a very bad idea. These macros are too easy to
+ * get conflicted with definitions elsewhere.
+ *
+ * New programs should stick to the `rb_` prefixed names.
+ *
+ * @note It seems we just mimic the API. We do not share their implementation
+ * with GPL-ed programs.
+ *
+ * @{
+ */
#ifndef ISPRINT
-# define ISASCII rb_isascii
-# 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
+# define ISASCII rb_isascii /**< @old{rb_isascii}*/
+# define ISPRINT rb_isprint /**< @old{rb_isprint}*/
+# define ISGRAPH rb_isgraph /**< @old{rb_isgraph}*/
+# define ISSPACE rb_isspace /**< @old{rb_isspace}*/
+# define ISUPPER rb_isupper /**< @old{rb_isupper}*/
+# define ISLOWER rb_islower /**< @old{rb_islower}*/
+# define ISALNUM rb_isalnum /**< @old{rb_isalnum}*/
+# define ISALPHA rb_isalpha /**< @old{rb_isalpha}*/
+# define ISDIGIT rb_isdigit /**< @old{rb_isdigit}*/
+# define ISXDIGIT rb_isxdigit /**< @old{rb_isxdigit}*/
+# define ISBLANK rb_isblank /**< @old{rb_isblank}*/
+# define ISCNTRL rb_iscntrl /**< @old{rb_iscntrl}*/
+# define ISPUNCT rb_ispunct /**< @old{rb_ispunct}*/
#endif
-#define TOUPPER rb_toupper
-#define TOLOWER rb_tolower
-#define STRCASECMP st_locale_insensitive_strcasecmp
-#define STRNCASECMP st_locale_insensitive_strncasecmp
-#define STRTOUL ruby_strtoul
+#define TOUPPER rb_toupper /**< @old{rb_toupper}*/
+#define TOLOWER rb_tolower /**< @old{rb_tolower}*/
+#define STRCASECMP st_locale_insensitive_strcasecmp /**< @old{st_locale_insensitive_strcasecmp}*/
+#define STRNCASECMP st_locale_insensitive_strncasecmp /**< @old{st_locale_insensitive_strncasecmp}*/
+#define STRTOUL ruby_strtoul /**< @old{ruby_strtoul}*/
+
+/** @} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-/* locale insensitive functions */
+/** @name locale insensitive functions
+ * @{
+ */
+
+/* In descriptions below, `the POSIX Locale` and `the "C" locale` are tactfully
+ * used as to whether the described function mimics POSIX or C99. */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Our own locale-insensitive version of `strcasecmp(3)`. The "case" here
+ * always means that of the POSIX Locale. It doesn't depend on runtime locale
+ * settings.
+ *
+ * @param[in] s1 Comparison LHS.
+ * @param[in] s2 Comparison RHS.
+ * @retval -1 `s1` is "less" than `s2`.
+ * @retval 0 Both strings converted into lowercase would be identical.
+ * @retval 1 `s1` is "greater" than `s2`.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ */
int st_locale_insensitive_strcasecmp(const char *s1, const char *s2);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Our own locale-insensitive version of `strcnasecmp(3)`. The "case" here
+ * always means that of the POSIX Locale. It doesn't depend on runtime locale
+ * settings.
+ *
+ * @param[in] s1 Comparison LHS.
+ * @param[in] s2 Comparison RHS.
+ * @param[in] n Comparison shall stop after first `n` bytes are scanned.
+ * @retval -1 `s1` is "less" than `s2`.
+ * @retval 0 Both strings converted into lowercase would be identical.
+ * @retval 1 `s1` is "greater" than `s2`.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning This function is _not_ timing safe.
+ */
int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Our own locale-insensitive version of `strtoul(3)`. The conversion is done
+ * as if the current locale is set to the "C" locale, no matter actual runtime
+ * locale settings.
+ *
+ * @note This is needed because `strtoul("i", 0, 36)` would return zero
+ * if it is locale sensitive and the current locale is `tr_TR`.
+ * @param[in] str String of digits, optionally preceded with whitespaces
+ * (ignored) and optionally `+` or `-` sign.
+ * @param[out] endptr NULL, or an arbitrary pointer (overwritten on return).
+ * @param[in] base `2` to `36` inclusive for each base, or special case
+ * `0` to detect the base from the contents of the string.
+ * @return Converted integer, casted to unsigned long.
+ * @post If `endptr` is not NULL, it is updated to point the first such
+ * byte where conversion failed.
+ * @note This function sets `errno` on failure.
+ * - `EINVAL`: Passed `base` is out of range.
+ * - `ERANGE`: Converted integer is out of range of `long`.
+ * @warning As far as @shyouhei reads ISO/IEC 9899:2018 section 7.22.1.4, a
+ * conforming `strtoul` implementation shall render `ERANGE`
+ * whenever it finds the input string represents a negative
+ * integer. Such thing can never be representable using `unsigned
+ * long`. However this implementation does not honour that
+ * language. It just casts such negative value to the return
+ * type, resulting a very big return value. This behaviour is at
+ * least questionable. But we can no longer change that at this
+ * point.
+ * @note Not only does this function works under the "C" locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ */
unsigned long ruby_strtoul(const char *str, char **endptr, int base);
RBIMPL_SYMBOL_EXPORT_END()
@@ -68,6 +195,16 @@ RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isascii(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval false `c` is out of range of ASCII character set.
+ * @retval true Yes it is.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isascii(int c)
{
@@ -77,6 +214,20 @@ rb_isascii(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isupper(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "upper".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isupper(int c)
{
@@ -86,6 +237,20 @@ rb_isupper(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `islower(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "lower".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_islower(int c)
{
@@ -95,6 +260,21 @@ rb_islower(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isalpha(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1
+ * "upper" or "lower".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isalpha(int c)
{
@@ -104,6 +284,20 @@ rb_isalpha(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isdigit(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "digit".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isdigit(int c)
{
@@ -113,6 +307,21 @@ rb_isdigit(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isalnum(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1
+ * "upper", "lower", or "digit".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isalnum(int c)
{
@@ -122,6 +331,20 @@ rb_isalnum(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isxdigit(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "xdigit".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isxdigit(int c)
{
@@ -131,6 +354,20 @@ rb_isxdigit(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isblank(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "blank".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isblank(int c)
{
@@ -140,6 +377,20 @@ rb_isblank(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isspace(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "space".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isspace(int c)
{
@@ -149,6 +400,20 @@ rb_isspace(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `iscntrl(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "cntrl".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_iscntrl(int c)
{
@@ -158,6 +423,21 @@ rb_iscntrl(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Identical to rb_isgraph(), except it also returns true for `' '`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1
+ * "upper", "lower", "digit", "punct", or a `' '`.
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isprint(int c)
{
@@ -167,6 +447,20 @@ rb_isprint(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `ispunct(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "punct".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_ispunct(int c)
{
@@ -176,6 +470,21 @@ rb_ispunct(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `isgraph(3)`.
+ *
+ * @param[in] c Byte in question to query.
+ * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1
+ * "upper", "lower", "digit", or "punct".
+ * @retval false Anything else.
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_isgraph(int c)
{
@@ -185,6 +494,22 @@ rb_isgraph(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `tolower(3)`.
+ *
+ * @param[in] c Byte in question to convert.
+ * @retval c The byte is not listed in in IEEE 1003.1 section
+ * 7.3.1.1 "upper".
+ * @retval otherwise Byte converted using the map defined in IEEE 1003.1
+ * section 7.3.1 "tolower".
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_tolower(int c)
{
@@ -194,10 +519,27 @@ rb_tolower(int c)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Our own locale-insensitive version of `toupper(3)`.
+ *
+ * @param[in] c Byte in question to convert.
+ * @retval c The byte is not listed in in IEEE 1003.1 section
+ * 7.3.1.1 "lower".
+ * @retval otherwise Byte converted using the map defined in IEEE 1003.1
+ * section 7.3.1 "toupper".
+ * @note Not only does this function works under the POSIX Locale, but
+ * also assumes its execution character set be what ruby calls an
+ * ASCII-compatible character set; which does not include for
+ * instance EBCDIC or UTF-16LE.
+ * @warning `c` is an int. This means that when you pass a `char` value
+ * here, it experiences "integer promotion" as defined in ISO/IEC
+ * 9899:2018 section 6.3.1.1 paragraph 1.
+ */
static inline int
rb_toupper(int c)
{
return rb_islower(c) ? (c&0x5f) : c;
}
+/** @} */
#endif /* RBIMPL_CTYPE_H */
diff --git a/include/ruby/internal/dllexport.h b/include/ruby/internal/dllexport.h
index 1488140854..08a262209d 100644
--- a/include/ruby/internal/dllexport.h
+++ b/include/ruby/internal/dllexport.h
@@ -17,14 +17,25 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Tweaking visibility of C variables/functions.
*/
#include "ruby/internal/config.h"
#include "ruby/internal/compiler_is.h"
-/* For MinGW, we need __declspec(dllimport) for RUBY_EXTERN on MJIT.
- mswin's RUBY_EXTERN already has that. See also: win32/Makefile.sub */
+/**
+ * Declaration of externally visible global variables. Here "externally" means
+ * they should be visible from extension libraries. Depending on operating
+ * systems (dynamic linkers, to be precise), global variables inside of a DLL
+ * may or may not be visible form outside of that DLL by default. This
+ * declaration manually tweaks that default and ensures the declared variable
+ * be truly globally visible.
+ *
+ * ```CXX
+ * extern VALUE foo; // hidden on some OS
+ * RUBY_EXTERN VALUE foo; // ensure visible
+ * ```
+ */
#undef RUBY_EXTERN
#if defined(MJIT_HEADER) && defined(_WIN32)
# define RUBY_EXTERN extern __declspec(dllimport)
@@ -48,6 +59,13 @@
# define RUBY_FUNC_EXPORTED /* void */
#endif
+/**
+ * @cond INTERNAL_MACRO
+ *
+ * These MJIT related macros are placed here because translate_mjit_header can
+ * need them. Extension libraries should not touch.
+ */
+
/* These macros are used for functions which are exported only for MJIT
and NOT ensured to be exported in future versions. */
@@ -71,6 +89,8 @@
# define MJIT_STATIC
#endif
+/** @endcond */
+
/** Shortcut macro equivalent to `RUBY_SYMBOL_EXPORT_BEGIN extern "C" {`.
* \@shyouhei finds it handy. */
#if defined(__DOXYGEN__)
diff --git a/include/ruby/internal/dosish.h b/include/ruby/internal/dosish.h
index eb71e36505..7d354ddd1a 100644
--- a/include/ruby/internal/dosish.h
+++ b/include/ruby/internal/dosish.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Support for so-called dosish systems.
*/
#ifdef __CYGWIN__
@@ -38,20 +38,46 @@
#include "ruby/win32.h"
#endif
+/** The delimiter of `PATH` environment variable. */
#if defined(DOSISH)
#define PATH_SEP ";"
#else
#define PATH_SEP ":"
#endif
+/** Identical to #PATH_SEP, except it is of type `char`. */
#define PATH_SEP_CHAR PATH_SEP[0]
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * For historical interests: there was an operating system called Human68k
+ * which used an environment variable called `"path"` for this purpose.
+ */
#define PATH_ENV "PATH"
#if defined(DOSISH)
#define ENV_IGNORECASE
#endif
+/**
+ * Stone age assumption was that an operating system supports only one file
+ * system at a moment. This macro was to detect if such (one and only) file
+ * system has case sensitivity. This assumption is largely not true any
+ * longer; most operating systems can mount many kinds of file systems side by
+ * side. Also there are file systems that do or do not ignore cases depending
+ * on configuration (e.g. EXT4's `casefold` feature).
+ *
+ * This macro is still used internally (for instance Ruby level constant
+ * `File::FNM_SYSCASE` depends on it), but it is basically a wrong idea for you
+ * to use it today. Please just find another way.
+ */
#ifndef CASEFOLD_FILESYSTEM
# if defined DOSISH
# define CASEFOLD_FILESYSTEM 1
diff --git a/include/ruby/internal/encoding/coderange.h b/include/ruby/internal/encoding/coderange.h
new file mode 100644
index 0000000000..7a81208c9e
--- /dev/null
+++ b/include/ruby/internal/encoding/coderange.h
@@ -0,0 +1,202 @@
+#ifndef RUBY_INTERNAL_ENCODING_CODERANGE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_CODERANGE_H
+/**
+ * @file
+ * @author Ruby developers <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 for code ranges.
+ */
+
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/** What rb_enc_str_coderange() returns. */
+enum ruby_coderange_type {
+
+ /** The object's coderange is unclear yet. */
+ RUBY_ENC_CODERANGE_UNKNOWN = 0,
+
+ /** The object holds 0 to 127 inclusive and nothing else. */
+ RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8),
+
+ /** The object's encoding and contents are consistent each other */
+ RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9),
+
+ /** The object holds invalid/malformed/broken character(s). */
+ RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)),
+
+ /** Where the coderange resides. */
+ RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT|
+ RUBY_ENC_CODERANGE_VALID|
+ RUBY_ENC_CODERANGE_BROKEN)
+};
+
+RBIMPL_ATTR_CONST()
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ENC_CODERANGE_CLEAN_P. People don't
+ * use it directly.
+ *
+ * @param[in] cr An enum ::ruby_coderange_type.
+ * @retval 1 It is.
+ * @retval 0 It isn't.
+ */
+static inline int
+rb_enc_coderange_clean_p(int cr)
+{
+ return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT;
+}
+
+RBIMPL_ATTR_CONST()
+/**
+ * Queries if a code range is "clean". "Clean" in this context means it is
+ * known and valid.
+ *
+ * @param[in] cr An enum ::ruby_coderange_type.
+ * @retval 1 It is.
+ * @retval 0 It isn't.
+ */
+static inline bool
+RB_ENC_CODERANGE_CLEAN_P(enum ruby_coderange_type cr)
+{
+ return rb_enc_coderange_clean_p(cr);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/**
+ * Queries the (inline) code range of the passed object. The object must be
+ * capable of having inline encoding. Using this macro needs deep
+ * understanding of bit level object binary layout.
+ *
+ * @param[in] obj Target object.
+ * @return An enum ::ruby_coderange_type.
+ */
+static inline enum ruby_coderange_type
+RB_ENC_CODERANGE(VALUE obj)
+{
+ VALUE ret = RB_FL_TEST_RAW(obj, RUBY_ENC_CODERANGE_MASK);
+
+ return RBIMPL_CAST((enum ruby_coderange_type)ret);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/**
+ * Queries the (inline) code range of the passed object is
+ * ::RUBY_ENC_CODERANGE_7BIT. The object must be capable of having inline
+ * encoding. Using this macro needs deep understanding of bit level object
+ * binary layout.
+ *
+ * @param[in] obj Target object.
+ * @retval 1 It is ascii only.
+ * @retval 0 Otherwise (including cases when the range is not known).
+ */
+static inline bool
+RB_ENC_CODERANGE_ASCIIONLY(VALUE obj)
+{
+ return RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT;
+}
+
+/**
+ * Destructively modifies the passed object so that its (inline) code range is
+ * the passed one. The object must be capable of having inline encoding.
+ * Using this macro needs deep understanding of bit level object binary layout.
+ *
+ * @param[out] obj Target object.
+ * @param[out] cr An enum ::ruby_coderange_type.
+ * @post `obj`'s code range is `cr`.
+ */
+static inline void
+RB_ENC_CODERANGE_SET(VALUE obj, enum ruby_coderange_type cr)
+{
+ RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK);
+ RB_FL_SET_RAW(obj, cr);
+}
+
+/**
+ * Destructively clears the passed object's (inline) code range. The object
+ * must be capable of having inline encoding. Using this macro needs deep
+ * understanding of bit level object binary layout.
+ *
+ * @param[out] obj Target object.
+ * @post `obj`'s code range is ::RUBY_ENC_CODERANGE_UNKNOWN.
+ */
+static inline void
+RB_ENC_CODERANGE_CLEAR(VALUE obj)
+{
+ RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK);
+}
+
+RBIMPL_ATTR_CONST()
+/* assumed ASCII compatibility */
+/**
+ * "Mix" two code ranges into one. This is handy for instance when you
+ * concatenate two strings into one. Consider one of then is valid but the
+ * other isn't. The result must be invalid. This macro computes that kind of
+ * mixture.
+ *
+ * @param[in] a An enum ::ruby_coderange_type.
+ * @param[in] b Another enum ::ruby_coderange_type.
+ * @return The `a` "and" `b`.
+ */
+static inline enum ruby_coderange_type
+RB_ENC_CODERANGE_AND(enum ruby_coderange_type a, enum ruby_coderange_type b)
+{
+ if (a == RUBY_ENC_CODERANGE_7BIT) {
+ return b;
+ }
+ else if (a != RUBY_ENC_CODERANGE_VALID) {
+ return RUBY_ENC_CODERANGE_UNKNOWN;
+ }
+ else if (b == RUBY_ENC_CODERANGE_7BIT) {
+ return RUBY_ENC_CODERANGE_VALID;
+ }
+ else {
+ return b;
+ }
+}
+
+#define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK /**< @old{RUBY_ENC_CODERANGE_MASK} */
+#define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN /**< @old{RUBY_ENC_CODERANGE_UNKNOWN} */
+#define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT /**< @old{RUBY_ENC_CODERANGE_7BIT} */
+#define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID /**< @old{RUBY_ENC_CODERANGE_VALID} */
+#define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN /**< @old{RUBY_ENC_CODERANGE_BROKEN} */
+#define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr) /**< @old{RB_ENC_CODERANGE_CLEAN_P} */
+#define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj) /**< @old{RB_ENC_CODERANGE} */
+#define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj) /**< @old{RB_ENC_CODERANGE_ASCIIONLY} */
+#define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr) /**< @old{RB_ENC_CODERANGE_SET} */
+#define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj) /**< @old{RB_ENC_CODERANGE_CLEAR} */
+#define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b) /**< @old{RB_ENC_CODERANGE_AND} */
+#define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr) /**< @old{RB_ENCODING_CODERANGE_SET} */
+
+/** @cond INTERNAL_MACRO */
+#define RB_ENC_CODERANGE RB_ENC_CODERANGE
+#define RB_ENC_CODERANGE_AND RB_ENC_CODERANGE_AND
+#define RB_ENC_CODERANGE_ASCIIONLY RB_ENC_CODERANGE_ASCIIONLY
+#define RB_ENC_CODERANGE_CLEAN_P RB_ENC_CODERANGE_CLEAN_P
+#define RB_ENC_CODERANGE_CLEAR RB_ENC_CODERANGE_CLEAR
+#define RB_ENC_CODERANGE_SET RB_ENC_CODERANGE_SET
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_CODERANGE_H */
diff --git a/include/ruby/internal/encoding/ctype.h b/include/ruby/internal/encoding/ctype.h
new file mode 100644
index 0000000000..05c314aeb3
--- /dev/null
+++ b/include/ruby/internal/encoding/ctype.h
@@ -0,0 +1,258 @@
+#ifndef RUBY_INTERNAL_ENCODING_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_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 Routines to query chacater types.
+ */
+
+#include "ruby/onigmo.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Queries if the passed pointer points to a newline character. What is a
+ * newline and what is not depends on the passed encoding.
+ *
+ * @param[in] p Pointer to a possibly-middle of a character.
+ * @param[in] end End of the string.
+ * @param[in] enc Encoding.
+ * @retval false It isn't.
+ * @retval true It is.
+ */
+static inline bool
+rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc)
+{
+ OnigUChar *up = RBIMPL_CAST((OnigUChar *)p);
+ OnigUChar *ue = RBIMPL_CAST((OnigUChar *)e);
+
+ return ONIGENC_IS_MBC_NEWLINE(enc, up, ue);
+}
+
+/**
+ * Queries if the passed code point is of passed character type in the passed
+ * encoding. The "character type" here is a set of macros defined in onigmo.h,
+ * like `ONIGENC_CTYPE_PUNCT`.
+ *
+ * @param[in] c An `OnigCodePoint` value.
+ * @param[in] t An `OnigCtype` value.
+ * @param[in] enc A `rb_encoding*` value.
+ * @retval true `c` is of `t` in `enc`.
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_CTYPE(enc, c, t);
+}
+
+/**
+ * Identical to rb_isascii(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval false `c` is out of range of ASCII character set in `enc`.
+ * @retval true Otherwise.
+ *
+ * @internal
+ *
+ * `enc` is ignored. This is at least an intentional implementation detail
+ * (not a bug). But there could be rooms for future extensions.
+ */
+static inline bool
+rb_enc_isascii(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_ASCII(c);
+}
+
+/**
+ * Identical to rb_isalpha(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "ALPHA".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isalpha(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_ALPHA(enc, c);
+}
+
+/**
+ * Identical to rb_islower(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "LOWER".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_islower(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_LOWER(enc, c);
+}
+
+/**
+ * Identical to rb_isupper(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "UPPER".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isupper(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_UPPER(enc, c);
+}
+
+/**
+ * Identical to rb_iscntrl(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "CNTRL".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_iscntrl(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_CNTRL(enc, c);
+}
+
+/**
+ * Identical to rb_ispunct(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "PUNCT".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_ispunct(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_PUNCT(enc, c);
+}
+
+/**
+ * Identical to rb_isalnum(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "ANUM".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isalnum(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_ALNUM(enc, c);
+}
+
+/**
+ * Identical to rb_isprint(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "PRINT".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isprint(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_PRINT(enc, c);
+}
+
+/**
+ * Identical to rb_isspace(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "PRINT".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isspace(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_SPACE(enc, c);
+}
+
+/**
+ * Identical to rb_isdigit(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @retval true `enc` classifies `c` as "DIGIT".
+ * @retval false Otherwise.
+ */
+static inline bool
+rb_enc_isdigit(OnigCodePoint c, rb_encoding *enc)
+{
+ return ONIGENC_IS_CODE_DIGIT(enc, c);
+}
+
+RBIMPL_ATTR_CONST()
+/**
+ * Identical to rb_toupper(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @return `c`'s (Ruby's definition of) upper case counterpart.
+ *
+ * @internal
+ *
+ * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`.
+ */
+int rb_enc_toupper(int c, rb_encoding *enc);
+
+RBIMPL_ATTR_CONST()
+/**
+ * Identical to rb_tolower(), except it additionally takes an encoding.
+ *
+ * @param[in] c A code point.
+ * @param[in] enc An encoding.
+ * @return `c`'s (Ruby's definition of) lower case counterpart.
+ *
+ * @internal
+ *
+ * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`.
+ */
+int rb_enc_tolower(int c, rb_encoding *enc);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+/** @cond INTERNAL_MACRO */
+#define rb_enc_is_newline rb_enc_is_newline
+#define rb_enc_isalnum rb_enc_isalnum
+#define rb_enc_isalpha rb_enc_isalpha
+#define rb_enc_isascii rb_enc_isascii
+#define rb_enc_isctype rb_enc_isctype
+#define rb_enc_isdigit rb_enc_isdigit
+#define rb_enc_islower rb_enc_islower
+#define rb_enc_isprint rb_enc_isprint
+#define rb_enc_iscntrl rb_enc_iscntrl
+#define rb_enc_ispunct rb_enc_ispunct
+#define rb_enc_isspace rb_enc_isspace
+#define rb_enc_isupper rb_enc_isupper
+/** @endcond */
+
+#endif /* RUBY_INTERNAL_ENCODING_CTYPE_H */
diff --git a/include/ruby/internal/encoding/encoding.h b/include/ruby/internal/encoding/encoding.h
new file mode 100644
index 0000000000..4748ca806b
--- /dev/null
+++ b/include/ruby/internal/encoding/encoding.h
@@ -0,0 +1,1060 @@
+#ifndef RUBY_INTERNAL_ENCODING_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_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.
+ * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
+ * implementation details. Don't take them as canon. They could
+ * rapidly appear then vanish. The name (path) of this header file
+ * is also an implementation detail. Do not expect it to persist
+ * at the place it is now. Developers are free to move it anywhere
+ * anytime at will.
+ * @note To ruby-core: remember that this header can be possibly
+ * recursively included from extension libraries written in C++.
+ * Do not expect for instance `__VA_ARGS__` is always available.
+ * We assume C99 for ruby itself but we don't assume languages of
+ * extension libraries. They could be written in C++98.
+ * @brief Defines ::rb_encoding
+ */
+
+#include "ruby/oniguruma.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/returns_nonnull.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/fl_type.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * `Encoding` class.
+ *
+ * @ingroup object
+ */
+RUBY_EXTERN VALUE rb_cEncoding;
+
+/**
+ * @private
+ *
+ * Bit constants used when embedding encodings into ::RBasic::flags. Extension
+ * libraries must not bother such things.
+ */
+enum ruby_encoding_consts {
+
+ /** Max possible number of embeddable encodings. */
+ RUBY_ENCODING_INLINE_MAX = 127,
+
+ /** Where inline encodings reside. */
+ RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10),
+
+ /** Bits we use to store inline encodings. */
+ RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<<RUBY_ENCODING_SHIFT
+ /* RUBY_FL_USER10..RUBY_FL_USER16 */),
+
+ /** Max possible length of an encoding name. */
+ RUBY_ENCODING_MAXNAMELEN = 42
+};
+
+#define ENCODING_INLINE_MAX RUBY_ENCODING_INLINE_MAX /**< @old{RUBY_ENCODING_INLINE_MAX} */
+#define ENCODING_SHIFT RUBY_ENCODING_SHIFT /**< @old{RUBY_ENCODING_SHIFT} */
+#define ENCODING_MASK RUBY_ENCODING_MASK /**< @old{RUBY_ENCODING_MASK} */
+
+/**
+ * Destructively assigns the passed encoding to the passed object. The object
+ * must be capable of having inline encoding. Using this macro needs deep
+ * understanding of bit level object binary layout.
+ *
+ * @param[out] obj Target object to modify.
+ * @param[in] ecindex Encoding in encindex format.
+ * @post `obj`'s encoding is `encindex`.
+ */
+static inline void
+RB_ENCODING_SET_INLINED(VALUE obj, int encindex)
+{
+ VALUE f = /* upcast */ encindex;
+
+ f <<= RUBY_ENCODING_SHIFT;
+ RB_FL_UNSET_RAW(obj, RUBY_ENCODING_MASK);
+ RB_FL_SET_RAW(obj, f);
+}
+
+/**
+ * Queries the encoding of the passed object. The encoding must be smaller
+ * than ::RUBY_ENCODING_INLINE_MAX, which means you have some assumption on the
+ * return value. This means the API is for internal use only.
+ *
+ * @param[in] obj Target object.
+ * @return `obj`'s encoding index.
+ */
+static inline int
+RB_ENCODING_GET_INLINED(VALUE obj)
+{
+ VALUE ret = RB_FL_TEST_RAW(obj, RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT;
+
+ return RBIMPL_CAST((int)ret);
+}
+
+#define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i) /**< @old{RB_ENCODING_SET_INLINED} */
+#define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i) /**< @old{RB_ENCODING_SET} */
+#define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj) /**< @old{RB_ENCODING_GET_INLINED} */
+#define ENCODING_GET(obj) RB_ENCODING_GET(obj) /**< @old{RB_ENCODING_GET} */
+#define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj) /**< @old{RB_ENCODING_IS_ASCII8BIT} */
+#define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN /**< @old{RUBY_ENCODING_MAXNAMELEN} */
+
+/**
+ * The type of encoding. Our design here is we take Oniguruma/Onigmo's
+ * multilingualisation schema as our base data structure.
+ */
+typedef const OnigEncodingType rb_encoding;
+
+RBIMPL_ATTR_NOALIAS()
+/**
+ * Converts a character option to its encoding. It only supports a very
+ * limited set of Japanese encodings due to its Japanese origin. Ruby still
+ * has this in-core for backwards compatibility. But new codes must not bother
+ * such concept like one-character encoding option. Consider deprecated in
+ * practice.
+ *
+ * @param[in] c One of `['n', 'e', 's', 'u', 'i', 'x', 'm']`.
+ * @param[out] option Return buffer.
+ * @param[out] kcode Return buffer.
+ * @retval 1 `c` understood properly.
+ * @retval 0 `c` is not understood.
+ * @post `option` is a ::OnigOptionType.
+ * @post `kcode` is an enum `ruby_preserved_encindex`.
+ *
+ * @internal
+ *
+ * `kcode` is opaque because `ruby_preserved_encindex` is not visible from
+ * extension libraries. But who cares?
+ */
+int rb_char_to_option_kcode(int c, int *option, int *kcode);
+
+/**
+ * Creates a new encoding, using the passed one as a template.
+ *
+ * @param[in] name Name of the creating encoding.
+ * @param[in] src Template.
+ * @exception rb_eArgError Duplicated or malformed `name`.
+ * @return Replicated new encoding's index.
+ * @post Encoding named `name` is created as a copy of `src`, whose index
+ * is the return value.
+ *
+ * @internal
+ *
+ * `name` can be `NULL`, but that just raises an exception. OTOH it seems no
+ * sanity check is done against `src`...?
+ */
+int rb_enc_replicate(const char *name, rb_encoding *src);
+
+/**
+ * Creates a new "dummy" encoding. Roughly speaking, an encoding is dummy when
+ * it is stateful. Notable example of dummy encoding are those defined in
+ * ISO/IEC 2022
+ *
+ * @param[in] name Name of the creating encoding.
+ * @exception rb_eArgError Duplicated or malformed `name`.
+ * @return New dummy encoding's index.
+ * @post Encoding named `name` is created, whose index is the return
+ * value.
+ */
+int rb_define_dummy_encoding(const char *name);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the passed encoding is dummy.
+ *
+ * @param[in] enc Encoding in question.
+ * @retval 1 It is.
+ * @retval 0 It isn't.
+ */
+int rb_enc_dummy_p(rb_encoding *enc);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries the index of the encoding. An encoding's index is a Ruby-local
+ * concept. It is a (sequential) number assigned to each encoding.
+ *
+ * @param[in] enc Encoding in question.
+ * @return Its index.
+ * @note You can pass null pointers to this function. It is equivalent
+ * to rb_usascii_encindex() then.
+ */
+int rb_enc_to_index(rb_encoding *enc);
+
+/**
+ * Queries the index of the encoding of the passed object, if any.
+ *
+ * @param[in] obj Object in question.
+ * @retval -1 `obj` is incapable of having an encoding.
+ * @retval otherwise `obj`'s encoding's index.
+ */
+int rb_enc_get_index(VALUE obj);
+
+/**
+ * @alias{rb_enc_get_index}
+ *
+ * @internal
+ *
+ * Implementation wise this is not a verbatim alias of rb_enc_get_index(). But
+ * the API is consistent. Don't bother.
+ */
+static inline int
+RB_ENCODING_GET(VALUE obj)
+{
+ int encindex = RB_ENCODING_GET_INLINED(obj);
+
+ if (encindex == RUBY_ENCODING_INLINE_MAX) {
+ return rb_enc_get_index(obj);
+ }
+ else {
+ return encindex;
+ }
+}
+
+/**
+ * Destructively assigns an encoding (via its index) to an object.
+ *
+ * @param[out] obj Object in question.
+ * @param[in] encindex An encoding index.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @exception rb_eArgError `obj` is incapable of having an encoding.
+ * @exception rb_eEncodingError `encindex` is out of bounds.
+ * @exception rb_eLoadError Failed to load the encoding.
+ */
+void rb_enc_set_index(VALUE obj, int encindex);
+
+/** @alias{rb_enc_set_index} */
+static inline void
+RB_ENCODING_SET(VALUE obj, int encindex)
+{
+ rb_enc_set_index(obj, encindex);
+}
+
+/**
+ * This is #RB_ENCODING_SET + RB_ENC_CODERANGE_SET combo. The object must be
+ * capable of having inline encoding. Using this macro needs deep
+ * understanding of bit level object binary layout.
+ *
+ * @param[out] obj Target object.
+ * @param[in] encindex Encoding in encindex format.
+ * @param[in] cr An enum ::ruby_coderange_type.
+ * @post `obj`'s encoding is `encindex`.
+ * @post `obj`'s code range is `cr`.
+ */
+static inline void
+RB_ENCODING_CODERANGE_SET(VALUE obj, int encindex, enum ruby_coderange_type cr)
+{
+ RB_ENCODING_SET(obj, encindex);
+ RB_ENC_CODERANGE_SET(obj, cr);
+}
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the passed object can have its encoding.
+ *
+ * @param[in] obj Object in question.
+ * @retval 1 It can.
+ * @retval 0 It cannot.
+ */
+int rb_enc_capable(VALUE obj);
+
+/**
+ * Queries the index of the encoding.
+ *
+ * @param[in] name Name of the encoding to find.
+ * @exception rb_eArgError No such encoding named `name`.
+ * @retval -1 `name` exists, but unable to load.
+ * @retval otherwise Index of encoding named `name`.
+ */
+int rb_enc_find_index(const char *name);
+
+/**
+ * Registers an "alias" name. In the wild, an encoding can be called using
+ * multiple names. For instance an encoding known as `"CP932"` is also called
+ * `"SJIS"` on occasions. This API registers such relationships.
+ *
+ * @param[in] alias New name.
+ * @param[in] orig Old name.
+ * @exception rb_eArgError `alias` is duplicated or malformed.
+ * @retval -1 Failed to load `orig`.
+ * @retval otherwise The index of `orig` and `alias`.
+ * @post `alias` is a synonym of `orig`. They refer to the identical
+ * encoding.
+ */
+int rb_enc_alias(const char *alias, const char *orig);
+
+/**
+ * Obtains a encoding index from a wider range of objects (than
+ * rb_enc_find_index()).
+ *
+ * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString.
+ * @retval -1 `obj` is unexpected type/contents.
+ * @retval otherwise Index corresponding to `obj`.
+ */
+int rb_to_encoding_index(VALUE obj);
+
+/**
+ * Identical to rb_find_encoding(), except it raises an exception instead of
+ * returning NULL.
+ *
+ * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString.
+ * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString.
+ * @exception rb_eArgError `obj` is an unknown encoding name.
+ * @return Encoding of `obj`.
+ */
+rb_encoding *rb_to_encoding(VALUE obj);
+
+/**
+ * Identical to rb_to_encoding_index(), except the return type.
+ *
+ * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString.
+ * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString.
+ * @retval NULL No such encoding.
+ * @return otherwise Encoding of `obj`.
+ */
+rb_encoding *rb_find_encoding(VALUE obj);
+
+/**
+ * Identical to rb_enc_get_index(), except the return type.
+ *
+ * @param[in] obj Object in question.
+ * @retval NULL Obj is incapable of having an encoding.
+ * @retval otherwise `obj`'s encoding.
+ */
+rb_encoding *rb_enc_get(VALUE obj);
+
+/**
+ * Look for the "common" encoding between the two. One character can or cannot
+ * be expressed depending on an encoding. This function finds the super-set of
+ * encodings that satisfy contents of both arguments. If that is impossible
+ * returns NULL.
+ *
+ * @param[in] str1 An object.
+ * @param[in] str2 Another object.
+ * @retval NULL No encoding can satisfy both at once.
+ * @retval otherwise Common encoding between the two.
+ * @note Arguments can be non-string, e.g. Regexp.
+ */
+rb_encoding *rb_enc_compatible(VALUE str1, VALUE str2);
+
+/**
+ * Identical to rb_enc_compatible(), except it raises an exception instead of
+ * returning NULL.
+ *
+ * @param[in] str1 An object.
+ * @param[in] str2 Another object.
+ * @exception rb_eEncCompatError No encoding can satisfy both.
+ * @return Common encoding between the two.
+ * @note Arguments can be non-string, e.g. Regexp.
+ */
+rb_encoding *rb_enc_check(VALUE str1,VALUE str2);
+
+/**
+ * Identical to rb_enc_set_index(), except it additionally does contents fix-up
+ * depending on the passed object. It for instance changes the byte length of
+ * terminating `U+0000` according to the passed encoding.
+ *
+ * @param[out] obj Object in question.
+ * @param[in] encindex An encoding index.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @exception rb_eArgError `obj` is incapable of having an encoding.
+ * @exception rb_eEncodingError `encindex` is out of bounds.
+ * @exception rb_eLoadError Failed to load the encoding.
+ * @return The passed `obj`.
+ * @post `obj`'s contents might be fixed according to `encindex`.
+ */
+VALUE rb_enc_associate_index(VALUE obj, int encindex);
+
+/**
+ * Identical to rb_enc_associate_index(), except it takes an encoding itself
+ * instead of its index.
+ *
+ * @param[out] obj Object in question.
+ * @param[in] enc An encoding.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @exception rb_eArgError `obj` is incapable of having an encoding.
+ * @return The passed `obj`.
+ * @post `obj`'s contents might be fixed according to `enc`.
+ */
+VALUE rb_enc_associate(VALUE obj, rb_encoding *enc);
+
+/**
+ * Destructively copies the encoding of the latter object to that of former
+ * one. It can also be seen as a routine identical to
+ * rb_enc_associate_index(), except it takes an object's encoding instead of an
+ * encoding's index.
+ *
+ * @param[out] dst Object to modify.
+ * @param[in] src Object to reference.
+ * @exception rb_eFrozenError `dst` is frozen.
+ * @exception rb_eArgError `dst` is incapable of having an encoding.
+ * @exception rb_eEncodingError `src` is incapable of having an encoding.
+ * @post `dst`'s encoding is that of `src`'s.
+ */
+void rb_enc_copy(VALUE dst, VALUE src);
+
+
+/**
+ * Identical to rb_find_encoding(), except it takes an encoding index instead
+ * of a Ruby object.
+ *
+ * @param[in] idx An encoding index.
+ * @retval NULL No such encoding.
+ * @retval otherwise An encoding whose index is `idx`.
+ */
+rb_encoding *rb_enc_from_index(int idx);
+
+/**
+ * Identical to rb_find_encoding(), except it takes a C's string instead of
+ * Ruby's.
+ *
+ * @param[in] name Name of the encoding to query.
+ * @retval NULL No such encoding.
+ * @retval otherwise An encoding whose index is `idx`.
+ */
+rb_encoding *rb_enc_find(const char *name);
+
+/**
+ * Queries the (canonical) name of the passed encoding.
+ *
+ * @param[in] enc An encoding.
+ * @return Its name.
+ */
+static inline const char *
+rb_enc_name(rb_encoding *enc)
+{
+ return enc->name;
+}
+
+/**
+ * Queries the minimum number of bytes that the passed encoding needs to
+ * represent a character. For ASCII and compatible encodings this is typically
+ * 1. There are however encodings whose minimum is not 1; they are
+ * historically called wide characters.
+ *
+ * @param[in] enc An encoding.
+ * @return Its least possible number of bytes except 0.
+ */
+static inline int
+rb_enc_mbminlen(rb_encoding *enc)
+{
+ return enc->min_enc_len;
+}
+
+/**
+ * Queries the maximum number of bytes that the passed encoding needs to
+ * represent a character. Fixed-width encodings have the same value for this
+ * one and #rb_enc_mbminlen. However there are variable-width encodings.
+ * UTF-8, for instance, takes from 1 up to 6 bytes.
+ *
+ * @param[in] enc An encoding.
+ * @return Its maximum possible number of bytes of a character.
+ */
+static inline int
+rb_enc_mbmaxlen(rb_encoding *enc)
+{
+ return enc->max_enc_len;
+}
+
+/**
+ * Queries the number of bytes of the character at the passed pointer.
+ *
+ * @param[in] p Pointer to a character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] enc Encoding of the string.
+ * @return If the character at `p` does not end until `e`, number of bytes
+ * between `p` and `e`. Otherwise the number of bytes that the
+ * character at `p` is encoded.
+ *
+ * @internal
+ *
+ * Strictly speaking there are chances when `p` points to a middle byte of a
+ * wide character. This function returns "the number of bytes from `p` to
+ * nearest of either `e` or the next character boundary", if you go strict.
+ */
+int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc);
+
+/**
+ * Identical to rb_enc_mbclen() unless the character at `p` overruns `e`. That
+ * can happen for instance when you read from a socket and its partial read
+ * cuts a wide character in-between. In those situations this function
+ * "estimates" theoretical length of the character in question. Typically it
+ * tends to be possible to know how many bytes a character needs before
+ * actually reaching its end; for instance UTF-8 encodes a character's length
+ * in the first byte of it. This function returns that info.
+ *
+ * @note This implies that the string is not broken.
+ *
+ * @param[in] p Pointer to the character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] enc Encoding of the string.
+ * @return Number of bytes of character at `p`, measured or estimated.
+ */
+int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc);
+
+/**
+ * Queries the number of bytes of the character at the passed pointer. This
+ * function returns 3 different types of information:
+ *
+ * ```CXX
+ * auto n = rb_enc_precise_mbclen(p, q, r);
+ *
+ * if (ONIGENC_MBCLEN_CHARFOUND_P(n)) {
+ * // Character found. Normal return.
+ * auto found_length = ONIGENC_MBCLEN_CHARFOUND_LEN(n);
+ * }
+ * else if (ONIGENC_MBCLEN_NEEDMORE_P(n)) {
+ * // Character overruns past `q`; needs more.
+ * auto requested_length = ONIGENC_MBCLEN_NEEDMORE_LEN(n);
+ * }
+ * else {
+ * // `p` is broken.
+ * assert(ONIGENC_MBCLEN_INVALID_P(n));
+ * }
+ * ```
+ *
+ * @param[in] p Pointer to the character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] enc Encoding of the string.
+ * @return Encoded read/needed number of bytes (see above).
+ */
+int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc);
+
+#define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_P} */
+#define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_LEN} */
+#define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret) /**< @old{ONIGENC_MBCLEN_INVALID_P} */
+#define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_P} */
+#define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_LEN} */
+
+/**
+ * Queries the code point of character pointed by the passed pointer. If that
+ * code point is included in ASCII that code point is returned. Otherwise -1.
+ * This can be different from just looking at the first byte. For instance it
+ * reads 2 bytes in case of UTF-16BE.
+ *
+ * @param[in] p Pointer to the character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] len Return buffer.
+ * @param[in] enc Encoding of the string.
+ * @retval -1 The character at `p` is not i ASCII.
+ * @retval otherwise A code point of the character at `p`.
+ * @post `len` (if set) is the number of bytes of `p`.
+ */
+int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc);
+
+/**
+ * Queries the code point of character pointed by the passed pointer.
+ * Exceptions happen in case of broken input.
+ *
+ * @param[in] p Pointer to the character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] len Return buffer.
+ * @param[in] enc Encoding of the string.
+ * @exception rb_eArgError `p` is broken.
+ * @return Code point of the character pointed by `p`.
+ * @post `len` (if set) is the number of bytes of `p`.
+ */
+unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc);
+
+/**
+ * Queries the code point of character pointed by the passed pointer.
+ * Exceptions happen in case of broken input.
+ *
+ * @deprecated Use rb_enc_codepoint_len() instead.
+ * @param[in] p Pointer to the character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] enc Encoding of the string.
+ * @exception rb_eArgError `p` is broken.
+ * @return Code point of the character pointed by `p`.
+ *
+ * @internal
+ *
+ * @matz says in commit 91e5ba1cb865a2385d3e1cbfacd824496898e098 that the line
+ * below is a "prototype for obsolete function". However even today there
+ * still are some use cases of it throughout our repository. It seems it has
+ * its own niche.
+ */
+static inline unsigned int
+rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
+{
+ return rb_enc_codepoint_len(p, e, 0, enc);
+ /* ^^^
+ * This can be `NULL` in C, `nullptr` in C++, and `0` for both.
+ * We choose the most portable one here.
+ */
+}
+
+
+/**
+ * Identical to rb_enc_codepoint(), except it assumes the passed character is
+ * not broken.
+ *
+ * @param[in] p Pointer to the character's first byte.
+ * @param[in] e End of the string that has `p`.
+ * @param[in] enc Encoding of the string.
+ * @return Code point of the character pointed by `p`.
+ */
+static inline OnigCodePoint
+rb_enc_mbc_to_codepoint(const char *p, const char *e, rb_encoding *enc)
+{
+ const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p);
+ const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e);
+
+ return ONIGENC_MBC_TO_CODE(enc, up, ue);
+}
+
+/**
+ * Queries the number of bytes requested to represent the passed code point
+ * using the passed encoding.
+ *
+ * @param[in] code Code point in question.
+ * @param[in] enc Encoding to convert the code into a byte sequence.
+ * @exception rb_eArgError `enc` does not glean `code`.
+ * @return Number of bytes requested to represent `code` using `enc`.
+ */
+int rb_enc_codelen(int code, rb_encoding *enc);
+
+/**
+ * Identical to rb_enc_codelen(), except it returns 0 for invalid code points.
+ *
+ * @param[in] c Code point in question.
+ * @param[in] enc Encoding to convert `c` into a byte sequence.
+ * @retval 0 `c` is invalid.
+ * @return otherwise Number of bytes needed for `enc` to encode `c`.
+ */
+static inline int
+rb_enc_code_to_mbclen(int c, rb_encoding *enc)
+{
+ OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c);
+
+ return ONIGENC_CODE_TO_MBCLEN(enc, uc);
+}
+
+/**
+ * Identical to rb_enc_uint_chr(), except it writes back to the passed buffer
+ * instead of allocating one.
+ *
+ * @param[in] c Code point.
+ * @param[out] buf Return buffer.
+ * @param[in] enc Target encoding scheme.
+ * @retval <= 0 `c` is invalid in `enc`.
+ * @return otherwise Number of bytes written to `buf`.
+ * @post `c` is encoded according to `enc`, then written to `buf`.
+ *
+ * @internal
+ *
+ * The second argument must be typed. But its current usages prevent us from
+ * being any stricter than this. :FIXME:
+ */
+static inline int
+rb_enc_mbcput(unsigned int c, void *buf, rb_encoding *enc)
+{
+ OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c);
+ OnigUChar *ubuf = RBIMPL_CAST((OnigUChar *)buf);
+
+ return ONIGENC_CODE_TO_MBC(enc, uc, ubuf);
+}
+
+/**
+ * Queries the previous (left) character.
+ *
+ * @param[in] s Start of the string.
+ * @param[in] p Pointer to a character.
+ * @param[in] e End of the string.
+ * @param[in] enc Encoding.
+ * @retval NULL No previous character.
+ * @retval otherwise Pointer to the head of the previous character.
+ */
+static inline char *
+rb_enc_prev_char(const char *s, const char *p, const char *e, rb_encoding *enc)
+{
+ const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s);
+ const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p);
+ const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e);
+ OnigUChar *ur = onigenc_get_prev_char_head(enc, us, up, ue);
+
+ return RBIMPL_CAST((char *)ur);
+}
+
+/**
+ * Queries the left boundary of a character. This function takes a pointer
+ * that is not necessarily a head of a character, and searches for its head.
+ *
+ * @param[in] s Start of the string.
+ * @param[in] p Pointer to a possibly-middle of a character.
+ * @param[in] e End of the string.
+ * @param[in] enc Encoding.
+ * @return Pointer to the head of the character that contains `p`.
+ */
+static inline char *
+rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
+{
+ const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s);
+ const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p);
+ const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e);
+ OnigUChar *ur = onigenc_get_left_adjust_char_head(enc, us, up, ue);
+
+ return RBIMPL_CAST((char *)ur);
+}
+
+/**
+ * Queries the right boundary of a character. This function takes a pointer
+ * that is not necessarily a head of a character, and searches for its tail.
+ *
+ * @param[in] s Start of the string.
+ * @param[in] p Pointer to a possibly-middle of a character.
+ * @param[in] e End of the string.
+ * @param[in] enc Encoding.
+ * @return Pointer to the end of the character that contains `p`.
+ */
+static inline char *
+rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
+{
+ const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s);
+ const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p);
+ const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e);
+ OnigUChar *ur = onigenc_get_right_adjust_char_head(enc, us, up, ue);
+
+ return RBIMPL_CAST((char *)ur);
+}
+
+/**
+ * Scans the string backwards for n characters.
+ *
+ * @param[in] s Start of the string.
+ * @param[in] p Pointer to a character.
+ * @param[in] e End of the string.
+ * @param[in] n Steps.
+ * @param[in] enc Encoding.
+ * @retval NULL There are no `n` characters left.
+ * @retval otherwise Pointer to `n` character before `p`.
+ */
+static inline char *
+rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc)
+{
+ const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s);
+ const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p);
+ const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e);
+ const OnigUChar *ur = onigenc_step_back(enc, us, up, ue, n);
+
+ return RBIMPL_CAST((char *)ur);
+}
+
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_enc_asciicompat(). People don't use
+ * it directly. Just always use rb_enc_asciicompat().
+ *
+ * @param[in] enc Encoding in question.
+ * @retval 1 It is ASCII compatible.
+ * @retval 0 It isn't.
+ */
+static inline int
+rb_enc_asciicompat_inline(rb_encoding *enc)
+{
+ return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc);
+}
+
+/**
+ * Queries if the passed encoding is _in some sense_ compatible with ASCII.
+ * The concept of ASCII compatibility is nuanced, and private to our
+ * implementation. For instance SJIS is ASCII compatible to us, despite their
+ * having different characters at code point `0x5C`. This is based on some
+ * practical consideration that Japanese people confuses SJIS to be "upper
+ * compatible" with ASCII (which is in fact a wrong idea, but we just don't go
+ * strict here). An example of ASCII incompatible encoding is UTF-16. UTF-16
+ * shares code points with ASCII, but employs a completely different encoding
+ * scheme.
+ *
+ * @param[in] enc Encoding in question.
+ * @retval 0 It is incompatible.
+ * @retval 1 It is compatible.
+ */
+static inline bool
+rb_enc_asciicompat(rb_encoding *enc)
+{
+ if (rb_enc_mbminlen(enc) != 1) {
+ return false;
+ }
+ else if (rb_enc_dummy_p(enc)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/**
+ * Queries if the passed string is in an ASCII-compatible encoding.
+ *
+ * @param[in] str A Ruby's string to query.
+ * @retval 0 `str` is not a String, or an ASCII-incompatible string.
+ * @retval 1 Otherwise.
+ */
+static inline bool
+rb_enc_str_asciicompat_p(VALUE str)
+{
+ rb_encoding *enc = rb_enc_get(str);
+
+ return rb_enc_asciicompat(enc);
+}
+
+/**
+ * Queries the Ruby-level counterpart instance of ::rb_cEncoding that
+ * corresponds to the passed encoding.
+ *
+ * @param[in] enc An encoding
+ * @retval RUBY_Qnil `enc` is a null pointer.
+ * @retval otherwise An instance of ::rb_cEncoding.
+ */
+VALUE rb_enc_from_encoding(rb_encoding *enc);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the passed encoding is either one of UTF-8/16/32.
+ *
+ * @note It does not take UTF-7, which we actually support, into account.
+ *
+ * @param[in] enc Encoding in question.
+ * @retval 0 It is not a Unicode variant.
+ * @retval otherwise It is.
+ *
+ * @internal
+ *
+ * In reality it returns 1/0, but the value is abstracted as
+ * `ONIGENC_FLAG_UNICODE`.
+ */
+int rb_enc_unicode_p(rb_encoding *enc);
+
+RBIMPL_ATTR_RETURNS_NONNULL()
+/**
+ * Queries the encoding that represents ASCII-8BIT a.k.a. binary.
+ *
+ * @return The encoding that represents ASCII-8BIT.
+ *
+ * @internal
+ *
+ * This can not return NULL once the process properly boots up.
+ */
+rb_encoding *rb_ascii8bit_encoding(void);
+
+RBIMPL_ATTR_RETURNS_NONNULL()
+/**
+ * Queries the encoding that represents UTF-8.
+ *
+ * @return The encoding that represents UTF-8.
+ *
+ * @internal
+ *
+ * This can not return NULL once the process properly boots up.
+ */
+rb_encoding *rb_utf8_encoding(void);
+
+RBIMPL_ATTR_RETURNS_NONNULL()
+/**
+ * Queries the encoding that represents US-ASCII.
+ *
+ * @return The encoding that represents US-ASCII.
+ *
+ * @internal
+ *
+ * This can not return NULL once the process properly boots up.
+ */
+rb_encoding *rb_usascii_encoding(void);
+
+/**
+ * Queries the encoding that represents the current locale.
+ *
+ * @return The encoding that represents the process' locale.
+ *
+ * @internal
+ *
+ * This is dynamic. If you change the process' locale by e.g. calling
+ * `setlocale(3)`, that should also change the return value of this function.
+ *
+ * There is no official way for Ruby scripts to manipulate locales, though.
+ */
+rb_encoding *rb_locale_encoding(void);
+
+/**
+ * Queries the "filesystem" encoding. This is the encoding that ruby expects
+ * info from the OS' file system are in. This affects for instance return
+ * value of rb_dir_getwd(). Most notably on Windows it can be an alias of OS
+ * codepage. Most notably on Linux users can set this via default external
+ * encoding.
+ *
+ * @return The "filesystem" encoding.
+ */
+rb_encoding *rb_filesystem_encoding(void);
+
+/**
+ * Queries the "default external" encoding. This is used to interact with
+ * outer-process things such as File. Though not recommended, you can set this
+ * using rb_enc_set_default_external().
+ *
+ * @return The "default external" encoding.
+ */
+rb_encoding *rb_default_external_encoding(void);
+
+/**
+ * Queries the "default internal" encoding. This could be a null pointer.
+ * Otherwise, outer-process info are transcoded from default external encoding
+ * to this one during reading from an IO.
+ *
+ * @return The "default internal" encoding (if any).
+ */
+rb_encoding *rb_default_internal_encoding(void);
+
+#ifndef rb_ascii8bit_encindex
+RBIMPL_ATTR_CONST()
+/**
+ * Identical to rb_ascii8bit_encoding(), except it returns the encoding's index
+ * instead of the encoding itself.
+ *
+ * @return The index of encoding of ASCII-8BIT.
+ *
+ * @internal
+ *
+ * This happens to be 0.
+ */
+int rb_ascii8bit_encindex(void);
+#endif
+
+/**
+ * Queries if the passed object is in ascii 8bit (== binary) encoding. The
+ * object must be capable of having inline encoding. Using this macro needs
+ * deep understanding of bit level object binary layout.
+ *
+ * @param[in] obj An object to check.
+ * @retval 1 It is.
+ * @retval 0 It isn't.
+ */
+static inline bool
+RB_ENCODING_IS_ASCII8BIT(VALUE obj)
+{
+ return RB_ENCODING_GET_INLINED(obj) == rb_ascii8bit_encindex();
+}
+
+#ifndef rb_utf8_encindex
+RBIMPL_ATTR_CONST()
+/**
+ * Identical to rb_utf8_encoding(), except it returns the encoding's index
+ * instead of the encoding itself.
+ *
+ * @return The index of encoding of UTF-8.
+ */
+int rb_utf8_encindex(void);
+#endif
+
+#ifndef rb_usascii_encindex
+RBIMPL_ATTR_CONST()
+/**
+ * Identical to rb_usascii_encoding(), except it returns the encoding's index
+ * instead of the encoding itself.
+ *
+ * @return The index of encoding of UTF-8.
+ */
+int rb_usascii_encindex(void);
+#endif
+
+/**
+ * Identical to rb_locale_encoding(), except it returns the encoding's index
+ * instead of the encoding itself.
+ *
+ * @return The index of the locale encoding.
+ */
+int rb_locale_encindex(void);
+
+/**
+ * Identical to rb_filesystem_encoding(), except it returns the encoding's
+ * index instead of the encoding itself.
+ *
+ * @return The index of the filesystem encoding.
+ */
+int rb_filesystem_encindex(void);
+
+/**
+ * Identical to rb_default_external_encoding(), except it returns the
+ * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the
+ * default external encoding.
+ *
+ * @return An instance of ::rb_cEncoding of default external.
+ */
+VALUE rb_enc_default_external(void);
+
+/**
+ * Identical to rb_default_internal_encoding(), except it returns the
+ * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the
+ * default internal encoding.
+ *
+ * @return An instance of ::rb_cEncoding of default internal.
+ */
+VALUE rb_enc_default_internal(void);
+
+/**
+ * Destructively assigns the passed encoding as the default external encoding.
+ * You should not use this API. It has process-global side effects. Also it
+ * doesn't change encodings of strings that have already been read.
+ *
+ * @param[in] encoding Ruby level encoding.
+ * @exception rb_eArgError `encoding` is ::RUBY_Qnil.
+ * @post The default external encoding is `encoding`.
+ */
+void rb_enc_set_default_external(VALUE encoding);
+
+/**
+ * Destructively assigns the passed encoding as the default internal encoding.
+ * You should not use this API. It has process-global side effects. Also it
+ * doesn't change encodings of strings that have already been read.
+ *
+ * @param[in] encoding Ruby level encoding.
+ * @post The default internal encoding is `encoding`.
+ * @note Unlike rb_enc_set_default_external() you can pass ::RUBY_Qnil.
+ */
+void rb_enc_set_default_internal(VALUE encoding);
+
+/**
+ * Returns a platform-depended "charmap" of the current locale. This
+ * information is called a "Codeset name" in IEEE 1003.1 section 13
+ * (`<langinfo.h>`). This is a very low-level API. The return value can have
+ * no corresponding encoding when passed to rb_find_encoding().
+ *
+ * @param[in] klass Ignored for no reason (why...)
+ * @return The low-level locale charmap, in Ruby's String.
+ */
+VALUE rb_locale_charmap(VALUE klass);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+/** @cond INTERNAL_MACRO */
+#define RB_ENCODING_GET RB_ENCODING_GET
+#define RB_ENCODING_GET_INLINED RB_ENCODING_GET_INLINED
+#define RB_ENCODING_IS_ASCII8BIT RB_ENCODING_IS_ASCII8BIT
+#define RB_ENCODING_SET RB_ENCODING_SET
+#define RB_ENCODING_SET_INLINED RB_ENCODING_SET_INLINED
+#define rb_enc_asciicompat rb_enc_asciicompat
+#define rb_enc_code_to_mbclen rb_enc_code_to_mbclen
+#define rb_enc_codepoint rb_enc_codepoint
+#define rb_enc_left_char_head rb_enc_left_char_head
+#define rb_enc_mbc_to_codepoint rb_enc_mbc_to_codepoint
+#define rb_enc_mbcput rb_enc_mbcput
+#define rb_enc_mbmaxlen rb_enc_mbmaxlen
+#define rb_enc_mbminlen rb_enc_mbminlen
+#define rb_enc_name rb_enc_name
+#define rb_enc_prev_char rb_enc_prev_char
+#define rb_enc_right_char_head rb_enc_right_char_head
+#define rb_enc_step_back rb_enc_step_back
+#define rb_enc_str_asciicompat_p rb_enc_str_asciicompat_p
+/** @endcond */
+
+#endif /* RUBY_INTERNAL_ENCODING_ENCODING_H */
diff --git a/include/ruby/internal/encoding/pathname.h b/include/ruby/internal/encoding/pathname.h
new file mode 100644
index 0000000000..0b5e85a524
--- /dev/null
+++ b/include/ruby/internal/encoding/pathname.h
@@ -0,0 +1,184 @@
+#ifndef RUBY_INTERNAL_ENCODING_PATHNAME_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_PATHNAME_H
+/**
+ * @file
+ * @author Ruby developers <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 encodings of pathnames.
+ */
+
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Returns a path component directly adjacent to the passed pointer.
+ *
+ * ```
+ * "/multi/byte/encoded/pathname.txt"
+ * ^ ^ ^
+ * | | +--- end
+ * | +--- @return
+ * +--- path
+ * ```
+ *
+ * @param[in] path Where to start scanning.
+ * @param[in] end End of the path string.
+ * @param[in] enc Encoding of the string.
+ * @return A pointer in the passed string where the next path component
+ * resides, or `end` if there is no next path component.
+ */
+char *rb_enc_path_next(const char *path, const char *end, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Seeks for non-prefix part of a pathname. This can be a no-op when the OS
+ * has no such concept like a path prefix. But there are OSes where path
+ * prefixes do exist.
+ *
+ * ```
+ * "C:\multi\byte\encoded\pathname.txt"
+ * ^ ^ ^
+ * | | +--- end
+ * | +--- @return
+ * +--- path
+ * ```
+ *
+ * @param[in] path Where to start scanning.
+ * @param[in] end End of the path string.
+ * @param[in] enc Encoding of the string.
+ * @return A pointer in the passed string where non-prefix part starts, or
+ * `path` if the OS does not have path prefix.
+ */
+char *rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Returns the last path component.
+ *
+ * ```
+ * "/multi/byte/encoded/pathname.txt"
+ * ^ ^ ^
+ * | | +--- end
+ * | +--- @return
+ * +--- path
+ * ```
+ *
+ * @param[in] path Where to start scanning.
+ * @param[in] end End of the path string.
+ * @param[in] enc Encoding of the string.
+ * @return A pointer in the passed string where the last path component
+ * resides, or `end` if there is no more path component.
+ */
+char *rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This just returns the passed end basically. It makes difference in case the
+ * passed string ends with tons of path separators like the following:
+ *
+ * ```
+ * "/path/that/ends/with/lots/of/slashes//////////////"
+ * ^ ^ ^
+ * | | +--- end
+ * | +--- @return
+ * +--- path
+ * ```
+ *
+ * @param[in] path Where to start scanning.
+ * @param[in] end End of the path string.
+ * @param[in] enc Encoding of the string.
+ * @return A pointer in the passed string where the trailing path
+ * separators start, or `end` if there is no trailing path
+ * separators.
+ *
+ * @internal
+ *
+ * It seems this function was introduced to mimic what POSIX says about
+ * `basename(3)`.
+ */
+char *rb_enc_path_end(const char *path, const char *end, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL((1, 4))
+/**
+ * Our own encoding-aware version of `basename(3)`. Normally, this function
+ * returns the last path component of the given name. However in case the
+ * passed name ends with a path separator, it returns the name of the
+ * directory, not the last (empty) component. Also if the passed name is a
+ * root directory, it returns that root directory. Note however that Windows
+ * filesystem have drive letters, which this function does not return.
+ *
+ * @param[in] name Target path.
+ * @param[out] baselen Return buffer.
+ * @param[in,out] alllen Number of bytes of `name`.
+ * @param[enc] enc Encoding of `name`.
+ * @return The rightmost component of `name`.
+ * @post `baselen`, if passed, is updated to be the number of bytes
+ * of the returned basename.
+ * @post `alllen`, if passed, is updated to be the number of bytes of
+ * strings not considered as the basename.
+ */
+const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL((1, 3))
+/**
+ * Our own encoding-aware version of `extname`. This function first applies
+ * rb_enc_path_last_separator() to the passed name and only concerns its return
+ * value (ignores any parent directories). This function returns complicated
+ * results:
+ *
+ * ```CXX
+ * auto path = "...";
+ * auto len = strlen(path);
+ * auto ret = ruby_enc_find_extname(path, &len, rb_ascii8bit_encoding());
+ *
+ * switch(len) {
+ * case 0:
+ * if (ret == 0) {
+ * // `path` is a file without extensions.
+ * }
+ * else {
+ * // `path` is a dotfile.
+ * // `ret` is the file's name.
+ * }
+ * break;
+ *
+ * case 1:
+ * // `path` _ends_ with a dot.
+ * // `ret` is that dot.
+ * break;
+ *
+ * default:
+ * // `path` has an extension.
+ * // `ret` is that extension.
+ * }
+ * ```
+ *
+ * @param[in] name Target path.
+ * @param[in,out] len Number of bytes of `name`.
+ * @param[in] enc Encoding of `name`.
+ * @return See above.
+ * @post `len`, if passed, is updated (see above).
+ */
+const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_PATHNAME_H */
diff --git a/include/ruby/internal/encoding/re.h b/include/ruby/internal/encoding/re.h
new file mode 100644
index 0000000000..d0de23bc83
--- /dev/null
+++ b/include/ruby/internal/encoding/re.h
@@ -0,0 +1,46 @@
+#ifndef RUBY_INTERNAL_ENCODING_RE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_RE_H
+/**
+ * @file
+ * @author Ruby developers <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 encodings of symbols.
+ */
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Identical to rb_reg_new(), except it additionally takes an encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @param[in] enc Encoding of `ptr`.
+ * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE.
+ * @exception rb_eRegexpError Failed to compile `ptr`.
+ * @return An allocated new instance of ::rb_cRegexp, of `enc` encoding,
+ * whose expression is compiled according to `ptr`.
+ */
+VALUE rb_enc_reg_new(const char *ptr, long len, rb_encoding *enc, int opts);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_RE_H */
diff --git a/include/ruby/internal/encoding/sprintf.h b/include/ruby/internal/encoding/sprintf.h
new file mode 100644
index 0000000000..cb8737b414
--- /dev/null
+++ b/include/ruby/internal/encoding/sprintf.h
@@ -0,0 +1,78 @@
+#ifndef RUBY_INTERNAL_ENCODING_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_SPRINTF_H
+/**
+ * @file
+ * @author Ruby developers <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 encodings of symbols.
+ */
+#include "ruby/internal/config.h"
+#include <stdarg.h>
+#include "ruby/internal/attr/format.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Identical to rb_sprintf(), except it additionally takes an encoding. The
+ * passed encoding rules both the incoming format specifier and the resulting
+ * string.
+ *
+ * @param[in] enc Encoding of `fmt`.
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ... Variadic number of contents to format.
+ * @return A rendered new instance of ::rb_cString, of `enc` encoding.
+ */
+VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
+/**
+ * Identical to rb_enc_sprintf(), except it takes a `va_list` instead of
+ * variadic arguments. It can also be seen as a routine identical to
+ * rb_vsprintf(), except it additionally takes an encoding.
+ *
+ * @param[in] enc Encoding of `fmt`.
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ap Contents to format.
+ * @return A rendered new instance of ::rb_cString, of `enc` encoding.
+ */
+VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((3))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4)
+/**
+ * Identical to rb_raise(), except it additionally takes an encoding.
+ *
+ * @param[in] enc Encoding of the generating exception.
+ * @param[in] exc A subclass of ::rb_eException.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @param[in] ... Contents of the message.
+ * @exception exc The specified exception.
+ * @note It never returns.
+ */
+void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_SPRINTF_H */
diff --git a/include/ruby/internal/encoding/string.h b/include/ruby/internal/encoding/string.h
new file mode 100644
index 0000000000..6ed7ca1c90
--- /dev/null
+++ b/include/ruby/internal/encoding/string.h
@@ -0,0 +1,346 @@
+#ifndef RUBY_INTERNAL_ENCODING_STRING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_STRING_H
+/**
+ * @file
+ * @author Ruby developers <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 encodings of strings.
+ */
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/intern/string.h" /* rbimpl_strlen */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Identical to rb_enc_str_new(), except it additionally takes an encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of `enc`
+ * encoding, whose contents are verbatim copy of `ptr`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ * @note `enc` can be a null pointer. It can also be seen as a routine
+ * identical to rb_usascii_str_new() then.
+ */
+VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_enc_str_new(), except it assumes the passed pointer is a
+ * pointer to a C string. It can also be seen as a routine identical to
+ * rb_str_new_cstr(), except it additionally takes an encoding.
+ *
+ * @param[in] ptr A C string.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of `enc` encoding, whose contents
+ * are verbatim copy of `ptr`.
+ * @pre `ptr` must not be a null pointer.
+ * @pre Because `ptr` is a C string it makes no sense for `enc` to be
+ * something like UTF-32.
+ * @note `enc` can be a null pointer. It can also be seen as a routine
+ * identical to rb_usascii_str_new_cstr() then.
+ */
+VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc);
+
+/**
+ * Identical to rb_enc_str_new(), except it takes a C string literal. It can
+ * also be seen as a routine identical to rb_str_new_static(), except it
+ * additionally takes an encoding.
+ *
+ * @param[in] ptr A C string literal.
+ * @param[in] len `strlen(ptr)`.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eArgError `len` out of range of `size_t`.
+ * @pre `ptr` must be a C string constant.
+ * @return An instance of ::rb_cString, of `enc` encoding, whose backend
+ * storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ * @note `enc` can be a null pointer. It can also be seen as a routine
+ * identical to rb_usascii_str_new_static() then.
+ */
+VALUE rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc);
+
+/**
+ * Identical to rb_enc_str_new(), except it returns a "f"string. It can also
+ * be seen as a routine identical to rb_interned_str(), except it additionally
+ * takes an encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eArgError `len` is negative.
+ * @return A found or created instance of ::rb_cString, of `len` bytes
+ * length, of `enc` encoding, whose contents are identical to that
+ * of `ptr`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ * @note `enc` can be a null pointer.
+ */
+VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_enc_str_new_cstr(), except it returns a "f"string. It can
+ * also be seen as a routine identical to rb_interned_str_cstr(), except it
+ * additionally takes an encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] enc Encoding of `ptr`.
+ * @return A found or created instance of ::rb_cString of `enc` encoding,
+ * whose contents are identical to that of `ptr`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ * @note `enc` can be a null pointer.
+ */
+VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc);
+
+/**
+ * Counts the number of characters of the passed string, according to the
+ * passed encoding. This has to be complicated. The passed string could be
+ * invalid and/or broken. This routine would scan from the beginning til the
+ * end, byte by byte, to seek out character boundaries. Could be super slow.
+ *
+ * @param[in] head Leftmost pointer to the string.
+ * @param[in] tail Rightmost pointer to the string.
+ * @param[in] enc Encoding of the string.
+ * @return Number of characters exist in `head` .. `tail`. The definition
+ * of "character" depends on the passed `enc`.
+ */
+long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc);
+
+/**
+ * Queries the n-th character. Like rb_enc_strlen() this function can be fast
+ * or slow depending on the contents. Don't expect characters to be uniformly
+ * distributed across the entire string.
+ *
+ * @param[in] head Leftmost pointer to the string.
+ * @param[in] tail Rightmost pointer to the string.
+ * @param[in] nth Requested index of characters.
+ * @param[in] enc Encoding of the string.
+ * @return Pointer to the first byte of the character that is `nth`
+ * character ahead of `head`, or `tail` if there is no such
+ * character (OOB etc). The definition of "character" depends on
+ * the passed `enc`.
+ */
+char *rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc);
+
+/**
+ * Identical to rb_enc_get_index(), except the return type.
+ *
+ * @param[in] obj Object in question.
+ * @exception rb_eTypeError `obj` is incapable of having an encoding.
+ * @return `obj`'s encoding.
+ */
+VALUE rb_obj_encoding(VALUE obj);
+
+/**
+ * Identical to rb_str_cat(), except it additionally takes an encoding.
+ *
+ * @param[out] str Destination object.
+ * @param[in] ptr Contents to append.
+ * @param[in] len Length of `src`, in bytes.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eArgError `len` is negative.
+ * @exception rb_eEncCompatError `enc` is not compatible with `str`.
+ * @return The passed `dst`.
+ * @post The contents of `ptr` is copied, transcoded into `dst`'s
+ * encoding, then pasted into `dst`'s end.
+ */
+VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc);
+
+/**
+ * Encodes the passed code point into a series of bytes.
+ *
+ * @param[in] code Code point.
+ * @param[in] enc Target encoding scheme.
+ * @exception rb_eRangeError `enc` does not glean `code`.
+ * @return An instance of ::rb_cString, of `enc` encoding, whose sole
+ * contents is `code` represented in `enc`.
+ * @note No way to encode code points bigger than UINT_MAX.
+ *
+ * @internal
+ *
+ * In other languages, APIs like this one could be seen as the primitive
+ * routines where encodings' "encode" feature are implemented. However in case
+ * of Ruby this is not the primitive one. We directly manipulate encoded
+ * strings. Encoding conversion routines transcode an encoded string directly
+ * to another one; not via a code point array.
+ */
+VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc);
+
+/**
+ * Identical to rb_external_str_new(), except it additionally takes an
+ * encoding. However the whole point of rb_external_str_new() is to encode a
+ * string into default external encoding. Being able to specify arbitrary
+ * encoding just ruins the designed purpose the function meseems.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @param[in] enc Target encoding scheme.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to `enc` is fully defined over the given
+ * contents, then the return value is a string of `enc` encoding,
+ * whose contents are the converted ones. Otherwise the string is
+ * a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ *
+ * @internal
+ *
+ * @shyouhei has no idea why this one does not follow the naming convention
+ * that others obey. It seems to him that this should have been called
+ * `rb_enc_external_str_new`.
+ */
+VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc);
+
+/**
+ * Identical to rb_str_export(), except it additionally takes an encoding.
+ *
+ * @param[in] obj Target object.
+ * @param[in] enc Target encoding.
+ * @exception rb_eTypeError No implicit conversion to String.
+ * @return Converted ruby string of `enc` encoding.
+ */
+VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc);
+
+/**
+ * Encoding conversion main routine.
+ *
+ * @param[in] str String to convert.
+ * @param[in] from Source encoding.
+ * @param[in] to Destination encoding.
+ * @return A copy of `str`, with conversion from `from` to `to` applied.
+ * @note `from` can be a null pointer. `str`'s encoding is taken then.
+ * @note `to` can be a null pointer. No-op then.
+ */
+VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to);
+
+/**
+ * Identical to rb_str_conv_enc(), except it additionally takes IO encoder
+ * options. The extra arguments can be constructed using io_extract_modeenc()
+ * etc.
+ *
+ * @param[in] str String to convert.
+ * @param[in] from Source encoding.
+ * @param[in] to Destination encoding.
+ * @param[in] ecflags A set of enum ::ruby_econv_flag_type.
+ * @param[in] ecopts Optional hash.
+ * @return A copy of `str`, with conversion from `from` to `to` applied.
+ * @note `from` can be a null pointer. `str`'s encoding is taken then.
+ * @note `to` can be a null pointer. No-op then.
+ * @note `ecopts` can be ::RUBY_Qnil, which is equivalent to passing an
+ * empty hash.
+ */
+VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts);
+
+/**
+ * Scans the passed string to collect its code range. Because a Ruby's string
+ * is mutable, its contents change from time to time; so does its code range.
+ * A long-lived string tends to fall back to ::RUBY_ENC_CODERANGE_UNKNOWN.
+ * This API scans it and re-assigns a fine-grained code range constant.
+ *
+ * @param[out] str A string.
+ * @return An enum ::ruby_coderange_type.
+ */
+int rb_enc_str_coderange(VALUE str);
+
+/**
+ * Scans the passed string until it finds something odd. Returns the number of
+ * bytes scanned. As the name implies this is suitable for repeated call. One
+ * of its application is `IO#readlines`. The method reads from its receiver's
+ * read buffer, maybe more than once, looking for newlines. But "newline" can
+ * be different among encodings. This API is used to detect broken contents to
+ * properly mark them as such.
+ *
+ * @param[in] str String to scan.
+ * @param[in] end End of `str`.
+ * @param[in] enc `str`'s encoding.
+ * @param[out] cr Return buffer.
+ * @return Distance between `str` and first such byte where broken.
+ * @post `cr` has the code range type.
+ */
+long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr);
+
+/**
+ * Queries if the passed string is "ASCII only". An ASCII only string is a
+ * string who doesn't have any non-ASCII characters at all. This doesn't
+ * necessarily mean the string is in ASCII encoding. For instance a String of
+ * CP932 encoding can quite much be ASCII only, depending on its contents.
+ *
+ * @param[in] str String in question.
+ * @retval 1 It doesn't have non-ASCII characters.
+ * @retval 0 It has characters that are out of ASCII.
+ */
+int rb_enc_str_asciionly_p(VALUE str);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Looks for the passed string in the passed buffer.
+ *
+ * @param[in] x Buffer that potentially includes `y`.
+ * @param[in] m Number of bytes of `x`.
+ * @param[in] y Query string.
+ * @param[in] n Number of bytes of `y`.
+ * @param[in] enc Encoding of both `x` and `y`.
+ * @retval -1 Not found.
+ * @retval otherwise Found index in `x`.
+ * @note This API can match at a non-character-boundary.
+ */
+long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc);
+
+/** @cond INTERNAL_MACRO */
+RBIMPL_ATTR_NONNULL(())
+static inline VALUE
+rbimpl_enc_str_new_cstr(const char *str, rb_encoding *enc)
+{
+ long len = rbimpl_strlen(str);
+
+ return rb_enc_str_new_static(str, len, enc);
+}
+
+#define rb_enc_str_new(str, len, enc) \
+ ((RBIMPL_CONSTANT_P(str) && \
+ RBIMPL_CONSTANT_P(len) ? \
+ rb_enc_str_new_static: \
+ rb_enc_str_new) ((str), (len), (enc)))
+
+#define rb_enc_str_new_cstr(str, enc) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_enc_str_new_cstr : \
+ rb_enc_str_new_cstr) ((str), (enc)))
+
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_STRING_H */
diff --git a/include/ruby/internal/encoding/symbol.h b/include/ruby/internal/encoding/symbol.h
new file mode 100644
index 0000000000..9cd1b0dbf4
--- /dev/null
+++ b/include/ruby/internal/encoding/symbol.h
@@ -0,0 +1,100 @@
+#ifndef RUBY_INTERNAL_ENCODING_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_SYMBOL_H
+/**
+ * @file
+ * @author Ruby developers <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 encodings of symbols.
+ */
+
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/encoding/encoding.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Identical to rb_intern2(), except it additionally takes an encoding.
+ *
+ * @param[in] name The name of the id.
+ * @param[in] len Length of `name`.
+ * @param[in] enc `name`'s encoding.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given name.
+ * @note These days Ruby internally has two kinds of symbols
+ * (static/dynamic). Symbols created using this function would
+ * become static ones; i.e. would never be garbage collected. It
+ * is up to you to avoid memory leaks. Think twice before using
+ * it.
+ */
+ID rb_intern3(const char *name, long len, rb_encoding *enc);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_symname_p(), except it additionally takes an encoding.
+ *
+ * @param[in] str A C string to check.
+ * @param[in] enc `str`'s encoding.
+ * @retval 1 It is a valid symbol name.
+ * @retval 0 It is invalid as a symbol name.
+ */
+int rb_enc_symname_p(const char *str, rb_encoding *enc);
+
+/**
+ * Identical to rb_enc_symname_p(), except it additionally takes the passed
+ * string's length. This is needed for strings containing NUL bytes, like in
+ * case of UTF-32.
+ *
+ * @param[in] name A C string to check.
+ * @param[in] len Number of bytes of `str`.
+ * @param[in] enc `str`'s encoding.
+ * @retval 1 It is a valid symbol name.
+ * @retval 0 It is invalid as a symbol name.
+ */
+int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc);
+
+/**
+ * Identical to rb_check_id(), except it takes a pointer to a memory region
+ * instead of Ruby's string.
+ *
+ * @param[in] ptr A pointer to a memory region.
+ * @param[in] len Number of bytes of `ptr`.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`.
+ * @retval 0 No such id ever existed in the history.
+ * @retval otherwise The id that represents the given name.
+ */
+ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc);
+
+/**
+ * Identical to rb_check_id_cstr(), except for the return type. It can also be
+ * seen as a routine identical to rb_check_symbol(), except it takes a pointer
+ * to a memory region instead of Ruby's string.
+ *
+ * @param[in] ptr A pointer to a memory region.
+ * @param[in] len Number of bytes of `ptr`.
+ * @param[in] enc Encoding of `ptr`.
+ * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`.
+ * @retval RUBY_Qnil No such id ever existed in the history.
+ * @retval otherwise The id that represents the given name.
+ */
+VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_SYMBOL_H */
diff --git a/include/ruby/internal/encoding/transcode.h b/include/ruby/internal/encoding/transcode.h
new file mode 100644
index 0000000000..7f26d2eae9
--- /dev/null
+++ b/include/ruby/internal/encoding/transcode.h
@@ -0,0 +1,562 @@
+#ifndef RUBY_INTERNAL_ENCODING_TRANSCODE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_INTERNAL_ENCODING_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.
+ * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
+ * implementation details. Don't take them as canon. They could
+ * rapidly appear then vanish. The name (path) of this header file
+ * is also an implementation detail. Do not expect it to persist
+ * at the place it is now. Developers are free to move it anywhere
+ * anytime at will.
+ * @note To ruby-core: remember that this header can be possibly
+ * recursively included from extension libraries written in C++.
+ * Do not expect for instance `__VA_ARGS__` is always available.
+ * We assume C99 for ruby itself but we don't assume languages of
+ * extension libraries. They could be written in C++98.
+ * @brief econv stuff
+ */
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/** return value of rb_econv_convert() */
+typedef enum {
+
+ /**
+ * The conversion stopped when it found an invalid sequence.
+ */
+ econv_invalid_byte_sequence,
+
+ /**
+ * The conversion stopped when it found a character in the input which
+ * cannot be representable in the output.
+ */
+ econv_undefined_conversion,
+
+ /**
+ * The conversion stopped because there is no destination.
+ */
+ econv_destination_buffer_full,
+
+ /**
+ * The conversion stopped because there is no input.
+ */
+ econv_source_buffer_empty,
+
+ /**
+ * The conversion stopped after converting everything. This is arguably
+ * the expected normal end of conversion.
+ */
+ econv_finished,
+
+ /**
+ * The conversion stopped after writing something to somewhere, before
+ * reading everything.
+ */
+ econv_after_output,
+
+ /**
+ * The conversion stopped in middle of reading a character, possibly due to
+ * a partial read of a socket etc.
+ */
+ econv_incomplete_input
+} rb_econv_result_t;
+
+/** An opaque struct that represents a lowest level of encoding conversion. */
+typedef struct rb_econv_t rb_econv_t;
+
+/**
+ * Converts the contents of the passed string from its encoding to the passed
+ * one.
+ *
+ * @param[in] str Target string.
+ * @param[in] to Destination encoding.
+ * @param[in] ecflags A set of enum
+ * ::ruby_econv_flag_type.
+ * @param[in] ecopts A keyword hash, like
+ * ::rb_io_t::rb_io_enc_t::ecopts.
+ * @exception rb_eArgError Not fully converted.
+ * @exception rb_eInvalidByteSequenceError `str` is malformed.
+ * @exception rb_eUndefinedConversionError `str` has a character not
+ * representable using `to`.
+ * @exception rb_eConversionNotFoundError There is no known conversion from
+ * `str`'s encoding to `to`.
+ * @return A string whose encoding is `to`, and whose contents is converted
+ * contents of `str`.
+ * @note Use rb_econv_prepare_options() to generate `ecopts`.
+ */
+VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts);
+
+/**
+ * Queries if there is more than one way to convert between the passed two
+ * encodings. Encoding conversion are has_and_belongs_to_many relationships.
+ * There could be no direct conversion defined for the passed pair. Ruby tries
+ * to find an indirect way to do so then. For instance ISO-8859-1 has no
+ * direct conversion to ISO-2022-JP. But there is ISO-8859-1 to UTF-8
+ * conversion; then there is UTF-8 to EUC-JP conversion; finally there also is
+ * EUC-JP to ISO-2022-JP conversion. So in short ISO-8859-1 can be converted
+ * to ISO-2022-JP using that path. This function returns true. Obviously not
+ * everything that can be represented using UTF-8 can also be represented using
+ * EUC-JP. Conversions in practice can fail depending on the actual input, and
+ * that renders exceptions in case of rb_str_encode().
+ *
+ * @param[in] from_encoding One encoding.
+ * @param[in] to_encoding Another encoding.
+ * @retval 0 No way to convert the two.
+ * @retval 1 At least one way to convert the two.
+ *
+ * @internal
+ *
+ * Practically @shyouhei knows no way for this function to return 0. It seems
+ * everything can eventually be converted to/from UTF-8, which connects
+ * everything.
+ */
+int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding);
+
+/**
+ * Identical to rb_econv_prepare_opts(), except it additionally takes the
+ * initial value of flags. The extra bits are bitwise-ORed to the return
+ * value.
+ *
+ * @param[in] opthash Keyword arguments.
+ * @param[out] ecopts Return buffer.
+ * @param[in] ecflags Default set of enum ::ruby_econv_flag_type.
+ * @exception rb_eArgError Unknown/Broken values passed.
+ * @return Calculated set of enum ::ruby_econv_flag_type.
+ * @post `ecopts` holds a hash object suitable for
+ * ::rb_io_t::rb_io_enc_t::ecopts.
+ */
+int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags);
+
+/**
+ * Splits a keyword arguments hash (that for instance `String#encode` took)
+ * into a set of enum ::ruby_econv_flag_type and a hash storing replacement
+ * characters etc.
+ *
+ * @param[in] opthash Keyword arguments.
+ * @param[out] ecopts Return buffer.
+ * @exception rb_eArgError Unknown/Broken values passed.
+ * @return Calculated set of enum ::ruby_econv_flag_type.
+ * @post `ecopts` holds a hash object suitable for
+ * ::rb_io_t::rb_io_enc_t::ecopts.
+ */
+int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts);
+
+/**
+ * Creates a new instance of struct ::rb_econv_t.
+ *
+ * @param[in] source_encoding Name of an encoding.
+ * @param[in] destination_encoding Name of another encoding.
+ * @param[in] ecflags A set of enum ::ruby_econv_flag_type.
+ * @exception rb_eArgError No such encoding.
+ * @retval NULL Failed to create a struct ::rb_econv_t.
+ * @retval otherwise Allocated struct ::rb_econv_t.
+ * @warning Return value must be passed to rb_econv_close() exactly once.
+ */
+rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags);
+
+/**
+ * Identical to rb_econv_open(), except it additionally takes a hash of
+ * optional strings.
+ *
+ *
+ * @param[in] source_encoding Name of an encoding.
+ * @param[in] destination_encoding Name of another encoding.
+ * @param[in] ecflags A set of enum ::ruby_econv_flag_type.
+ * @param[in] ecopts Optional set of strings.
+ * @exception rb_eArgError No such encoding.
+ * @retval NULL Failed to create a struct ::rb_econv_t.
+ * @retval otherwise Allocated struct ::rb_econv_t.
+ * @warning Return value must be passed to rb_econv_close() exactly once.
+ */
+rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts);
+
+/**
+ * Converts a string from an encoding to another.
+ *
+ * Possible flags are either ::RUBY_ECONV_PARTIAL_INPUT (means the source
+ * buffer is a part of much larger one), ::RUBY_ECONV_AFTER_OUTPUT (instructs
+ * the converter to stop after output before input), or both of them.
+ *
+ * @param[in,out] ec Conversion specification/state etc.
+ * @param[in] source_buffer_ptr Target string.
+ * @param[in] source_buffer_end End of target string.
+ * @param[out] destination_buffer_ptr Return buffer.
+ * @param[out] destination_buffer_end End of return buffer.
+ * @param[in] flags Flags (see above).
+ * @return The status of the conversion.
+ * @post `destination_buffer_ptr` holds conversion results.
+ */
+rb_econv_result_t rb_econv_convert(rb_econv_t *ec,
+ const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end,
+ unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end,
+ int flags);
+
+/**
+ * Destructs a converter. Note that a converter can have a buffer, and can be
+ * non-empty. Calling this would lose your data then.
+ *
+ * @param[out] ec The converter to destroy.
+ * @post `ec` is no longer a valid pointer.
+ */
+void rb_econv_close(rb_econv_t *ec);
+
+/**
+ * Assigns the replacement string. The string passed here would appear in
+ * converted string when it cannot represent its source counterpart. This can
+ * happen for instance you convert an emoji to ISO-8859-1.
+ *
+ * @param[out] ec Target converter.
+ * @param[in] str Replacement string.
+ * @param[in] len Number of bytes of `str`.
+ * @param[in] encname Name of encoding of `str`.
+ * @retval 0 Success.
+ * @retval -1 Failure (ENOMEM etc.).
+ * @post `ec`'s replacement string is set to `str`.
+ */
+int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname);
+
+/**
+ * "Decorate"s a converter. There are special kind of converters that
+ * transforms the contents, like replacing CR into CRLF. You can add such
+ * decorators to a converter using this API. By using this function a
+ * decorator is prepended at the beginning of a conversion sequence: in case of
+ * CRLF conversion, newlines are converted before encodings are converted.
+ *
+ * @param[out] ec Target converter to decorate.
+ * @param[in] decorator_name Name of decorator to prepend.
+ * @retval 0 Success.
+ * @retval -1 Failure (no such decorator etc.).
+ * @post Decorator works before encoding conversion happens.
+ *
+ * @internal
+ *
+ * What is the possible value of the `decorator_name` is not public. You have
+ * to read through `transcode.c` carefully.
+ */
+int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name);
+
+/**
+ * Identical to rb_econv_decorate_at_first(), except it adds to the opposite
+ * direction. For instance CRLF conversion would run _after_ encodings are
+ * converted.
+ *
+ * @param[out] ec Target converter to decorate.
+ * @param[in] decorator_name Name of decorator to prepend.
+ * @retval 0 Success.
+ * @retval -1 Failure (no such decorator etc.).
+ * @post Decorator works after encoding conversion happens.
+ */
+int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name);
+
+/**
+ * Creates a `rb_eConverterNotFoundError` exception object (but does not
+ * raise).
+ *
+ * @param[in] senc Name of source encoding.
+ * @param[in] denc Name of destination encoding.
+ * @param[in] ecflags A set of enum ::ruby_econv_flag_type.
+ * @return An instance of `rb_eConverterNotFoundError`.
+ */
+VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags);
+
+/**
+ * Appends the passed string to the passed converter's output buffer. This can
+ * be handy when an encoding needs bytes out of thin air; for instance
+ * ISO-2022-JP has "shift function" which does not correspond to any
+ * characters.
+ *
+ * @param[out] ec Target converter.
+ * @param[in] str String to insert.
+ * @param[in] len Number of bytes of `str`.
+ * @param[in] str_encoding Encoding of `str`.
+ * @retval 0 Success.
+ * @retval -1 Failure (conversion error etc.).
+ * @note `str_encoding` can be anything, and `str` itself is converted
+ * when necessary.
+ */
+int rb_econv_insert_output(rb_econv_t *ec,
+ const unsigned char *str, size_t len, const char *str_encoding);
+
+/**
+ * Queries an encoding name which best suits for rb_econv_insert_output()'s
+ * last parameter. Strings in this encoding need no conversion when inserted;
+ * can be both time/space efficient.
+ *
+ * @param[in] ec Target converter.
+ * @return Its encoding for insertion.
+ */
+const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec);
+
+/**
+ * This is a rb_econv_make_exception() + rb_exc_raise() combo.
+ *
+ * @param[in] ec (Possibly failed) conversion.
+ * @exception rb_eInvalidByteSequenceError Invalid byte sequence.
+ * @exception rb_eUndefinedConversionError Conversion undefined.
+ * @note This function can return when no error.
+ */
+void rb_econv_check_error(rb_econv_t *ec);
+
+/**
+ * This function makes sense right after rb_econv_convert() returns. As listed
+ * in ::rb_econv_result_t, rb_econv_convert() can bail out for various reasons.
+ * This function checks the passed converter's internal state and convert it to
+ * an appropriate exception object.
+ *
+ * @param[in] ec Target converter.
+ * @retval RUBY_Qnil The converter has no error.
+ * @retval otherwise Conversion error turned into an exception.
+ */
+VALUE rb_econv_make_exception(rb_econv_t *ec);
+
+/**
+ * Queries if rb_econv_putback() makes sense, i.e. there are invalid byte
+ * sequences remain in the buffer.
+ *
+ * @param[in] ec Target converter.
+ * @return Number of bytes that can be pushed back.
+ */
+int rb_econv_putbackable(rb_econv_t *ec);
+
+/**
+ * Puts back the bytes. In case of ::econv_invalid_byte_sequence, some of
+ * those invalid bytes are discarded and the others are buffered to be
+ * converted later. The latter bytes can be put back using this API.
+ *
+ * @param[out] ec Target converter (invalid byte sequence).
+ * @param[out] p Return buffer.
+ * @param[in] n Max number of bytes to put back.
+ * @post At most `n` bytes of what was put back is written to `p`.
+ */
+void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n);
+
+/**
+ * Queries the passed encoding's corresponding ASCII compatible encoding. "The
+ * corresponding ASCII compatible encoding" in this context is an ASCII
+ * compatible encoding which can represent exactly the same character sets as
+ * the given ASCII incompatible encoding. For instance that of UTF-16LE is
+ * UTF-8.
+ *
+ * @param[in] encname Name of an ASCII incompatible encoding.
+ * @retval NULL `encname` is already ASCII compatible.
+ * @retval otherwise The corresponding ASCII compatible encoding.
+ */
+const char *rb_econv_asciicompat_encoding(const char *encname);
+
+/**
+ * Identical to rb_econv_convert(), except it takes Ruby's string instead of
+ * C's pointer.
+ *
+ * @param[in,out] ec Target converter.
+ * @param[in] src Source string.
+ * @param[in] flags Flags (see rb_econv_convert).
+ * @exception rb_eArgError Converted string is too long.
+ * @exception rb_eInvalidByteSequenceError Invalid byte sequence.
+ * @exception rb_eUndefinedConversionError Conversion undefined.
+ * @return The conversion result.
+ */
+VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags);
+
+/**
+ * Identical to rb_econv_str_convert(), except it converts only a part of the
+ * passed string. Can be handy when you for instance want to do line-buffered
+ * conversion.
+ *
+ * @param[in,out] ec Target converter.
+ * @param[in] src Source string.
+ * @param[in] byteoff Number of bytes to seek.
+ * @param[in] bytesize Number of bytes to read.
+ * @param[in] flags Flags (see rb_econv_convert).
+ * @exception rb_eArgError Converted string is too long.
+ * @exception rb_eInvalidByteSequenceError Invalid byte sequence.
+ * @exception rb_eUndefinedConversionError Conversion undefined.
+ * @return The conversion result.
+ */
+VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags);
+
+/**
+ * Identical to rb_econv_str_convert(), except it appends the conversion result
+ * to the additionally passed string instead of creating a new string. It can
+ * also be seen as a routine identical to rb_econv_append(), except it takes a
+ * Ruby's string instead of C's pointer.
+ *
+ * @param[in,out] ec Target converter.
+ * @param[in] src Source string.
+ * @param[in] dst Return buffer.
+ * @param[in] flags Flags (see rb_econv_convert).
+ * @exception rb_eArgError Converted string is too long.
+ * @exception rb_eInvalidByteSequenceError Invalid byte sequence.
+ * @exception rb_eUndefinedConversionError Conversion undefined.
+ * @return The conversion result.
+ */
+VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags);
+
+/**
+ * Identical to rb_econv_str_append(), except it appends only a part of the
+ * passed string with conversion. It can also be seen as a routine identical
+ * to rb_econv_substr_convert(), except it appends the conversion result to the
+ * additionally passed string instead of creating a new string.
+ *
+ * @param[in,out] ec Target converter.
+ * @param[in] src Source string.
+ * @param[in] byteoff Number of bytes to seek.
+ * @param[in] bytesize Number of bytes to read.
+ * @param[in] dst Return buffer.
+ * @param[in] flags Flags (see rb_econv_convert).
+ * @exception rb_eArgError Converted string is too long.
+ * @exception rb_eInvalidByteSequenceError Invalid byte sequence.
+ * @exception rb_eUndefinedConversionError Conversion undefined.
+ * @return The conversion result.
+ */
+VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags);
+
+/**
+ * Converts the passed C's pointer according to the passed converter, then
+ * append the conversion result to the passed Ruby's string. This way buffer
+ * overflow is properly avoided to resize the destination properly.
+ *
+ * @param[in,out] ec Target converter.
+ * @param[in] bytesrc Target string.
+ * @param[in] bytesize Number of bytes of `bytesrc`.
+ * @param[in] dst Return buffer.
+ * @param[in] flags Flags (see rb_econv_convert).
+ * @exception rb_eArgError Converted string is too long.
+ * @exception rb_eInvalidByteSequenceError Invalid byte sequence.
+ * @exception rb_eUndefinedConversionError Conversion undefined.
+ * @return The conversion result.
+ */
+VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags);
+
+/**
+ * This badly named function does not set the destination encoding to binary,
+ * but instead just nullifies newline conversion decorators if any. Other
+ * ordinal character conversions still happen after this; something non-binary
+ * would still be generated.
+ *
+ * @param[out] ec Target converter to modify.
+ * @post Any newline conversions, if any, would be killed.
+ */
+void rb_econv_binmode(rb_econv_t *ec);
+
+/**
+ * This enum is kind of omnibus. Gathers various constants.
+ */
+enum ruby_econv_flag_type {
+
+ /**
+ * @name Flags for rb_econv_open()
+ *
+ * @{
+ */
+
+ /** Mask for error handling related bits. */
+ RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff,
+
+ /** Special handling of invalid sequences are there. */
+ RUBY_ECONV_INVALID_MASK = 0x0000000f,
+
+ /** Invalid sequences shall be replaced. */
+ RUBY_ECONV_INVALID_REPLACE = 0x00000002,
+
+ /** Special handling of undefined conversion are there. */
+ RUBY_ECONV_UNDEF_MASK = 0x000000f0,
+
+ /** Undefined characters shall be replaced. */
+ RUBY_ECONV_UNDEF_REPLACE = 0x00000020,
+
+ /** Undefined characters shall be escaped. */
+ RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030,
+
+ /** Decorators are there. */
+ RUBY_ECONV_DECORATOR_MASK = 0x0001ff00,
+
+ /** Newline converters are there. */
+ RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00007f00,
+
+ /** (Unclear; seems unused). */
+ RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00,
+
+ /** (Unclear; seems unused). */
+ RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00007000,
+
+ /** Universal newline mode. */
+ RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100,
+
+ /** CR to CRLF conversion shall happen. */
+ RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000,
+
+ /** CRLF to CR conversion shall happen. */
+ RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000,
+
+ /** CRLF to LF conversion shall happen. */
+ RUBY_ECONV_LF_NEWLINE_DECORATOR = 0x00004000,
+
+ /** Texts shall be XML-escaped. */
+ RUBY_ECONV_XML_TEXT_DECORATOR = 0x00008000,
+
+ /** Texts shall be AttrValue escaped */
+ RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00010000,
+
+ /** (Unclear; seems unused). */
+ RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000,
+
+ /** Texts shall be AttrValue escaped. */
+ RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000,
+
+ /** Newline decorator's default. */
+ RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR =
+#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
+ RUBY_ECONV_CRLF_NEWLINE_DECORATOR,
+#else
+ 0,
+#endif
+
+#define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK /**< @old{RUBY_ECONV_ERROR_HANDLER_MASK} */
+#define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK /**< @old{RUBY_ECONV_INVALID_MASK} */
+#define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE /**< @old{RUBY_ECONV_INVALID_REPLACE} */
+#define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK /**< @old{RUBY_ECONV_UNDEF_MASK} */
+#define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE /**< @old{RUBY_ECONV_UNDEF_REPLACE} */
+#define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF /**< @old{RUBY_ECONV_UNDEF_HEX_CHARREF} */
+#define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK /**< @old{RUBY_ECONV_DECORATOR_MASK} */
+#define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_MASK} */
+#define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK} */
+#define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK} */
+#define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR} */
+#define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CRLF_NEWLINE_DECORATOR} */
+#define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CR_NEWLINE_DECORATOR} */
+#define ECONV_LF_NEWLINE_DECORATOR RUBY_ECONV_LF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_LF_NEWLINE_DECORATOR} */
+#define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR /**< @old{RUBY_ECONV_XML_TEXT_DECORATOR} */
+#define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR} */
+#define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK /**< @old{RUBY_ECONV_STATEFUL_DECORATOR_MASK} */
+#define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR} */
+#define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR} */
+ /** @} */
+
+ /**
+ * @name Flags for rb_econv_convert()
+ *
+ * @{
+ */
+
+ /** Indicates the input is a part of much larger one. */
+ RUBY_ECONV_PARTIAL_INPUT = 0x00020000,
+
+ /** Instructs the converter to stop after output. */
+ RUBY_ECONV_AFTER_OUTPUT = 0x00040000,
+#define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT /**< @old{RUBY_ECONV_PARTIAL_INPUT} */
+#define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT /**< @old{RUBY_ECONV_AFTER_OUTPUT} */
+
+ RUBY_ECONV_FLAGS_PLACEHOLDER /**< Placeholder (not used) */
+};
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_INTERNAL_ENCODING_TRANSCODE_H */
diff --git a/include/ruby/internal/error.h b/include/ruby/internal/error.h
index bd5c4d2ea1..49e2276cb9 100644
--- a/include/ruby/internal/error.h
+++ b/include/ruby/internal/error.h
@@ -17,67 +17,565 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Declares ::rb_raise().
*/
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/format.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
-#include "ruby/backward/2/attributes.h"
-RBIMPL_SYMBOL_EXPORT_BEGIN()
-
-VALUE rb_errinfo(void);
-void rb_set_errinfo(VALUE);
+/**
+ * @defgroup exception Exception handlings
+ * @{
+ */
+/**
+ * Warning categories. A warning issued using this API can be selectively
+ * requested / suppressed by the end-users. For instance passing
+ * `-W:no-deprecated` to the ruby process would suppress those warnings in
+ * deprecated category.
+ *
+ * @warning There is no way to declare a new category (for now).
+ */
typedef enum {
+ /** Category unspecified. */
RB_WARN_CATEGORY_NONE,
+
+ /** Warning is for deprecated features. */
RB_WARN_CATEGORY_DEPRECATED,
+
+ /** Warning is for experimental features. */
RB_WARN_CATEGORY_EXPERIMENTAL,
+
RB_WARN_CATEGORY_ALL_BITS = 0x6 /* no RB_WARN_CATEGORY_NONE bit */
} rb_warning_category_t;
-/* for rb_readwrite_sys_fail first argument */
+/** for rb_readwrite_sys_fail first argument */
enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE};
+/** @cond INTERNAL_MACRO */
#define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE
#define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * This is the same as `$!` in Ruby.
+ *
+ * @retval RUBY_Qnil Not handling exceptions at the moment.
+ * @retval otherwise The current exception in the current thread.
+ * @ingroup exception
+ */
+VALUE rb_errinfo(void);
+
+/**
+ * Sets the current exception (`$!`) to the given value.
+ *
+ * @param[in] err An instance of ::rb_eException, or ::RUBY_Qnil.
+ * @exception rb_eTypeError What is given was neither ::rb_eException nor
+ * ::RUBY_Qnil.
+ * @note Use rb_raise() instead to raise `err`. This function just
+ * assigns the given object to the global variable.
+ * @ingroup exception
+ */
+void rb_set_errinfo(VALUE err);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Exception entry point. By calling this function the execution of your
+ * program gets interrupted to "raise" an exception up to the callee entities.
+ * Programs could "rescue" that exception, or could "ensure" some part of them.
+ * If nobody cares about such things, the raised exception reaches at the top
+ * of execution. This yields abnormal end of the process.
+ *
+ * @param[in] exc A subclass of ::rb_eException.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception exc The specified exception.
+ * @note It never returns.
+ */
+void rb_raise(VALUE exc, const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+/**
+ * Raises the unsung "fatal" exception. This is considered severe. Nobody can
+ * rescue the exception. Once raised, process termination is inevitable.
+ * However ensure clauses still run, so that resources are properly cleaned up.
+ *
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception rb_eFatal An exception that you cannot rescue.
+ * @note It never returns.
+ */
+void rb_fatal(const char *fmt, ...);
+
+RBIMPL_ATTR_COLD()
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+/**
+ * Interpreter panic switch. Immediate process termination without any
+ * synchronisations shall occur. LOTS of internal states, stack traces, and
+ * even machine registers are displayed if possible for debugging purposes
+ * then.
+ *
+ * @warning Do not use this API.
+ * @warning You are not expected to use this API.
+ * @warning Why not just fix your code instead of calling this API?
+ * @warning It was a bad idea to expose this API to extension libraries at
+ * the first place. We just cannot delete it at this point for
+ * backwards compatibility. That doesn't mean everyone are
+ * welcomed to call this function at will.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @note It never returns.
+ */
+void rb_bug(const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is a wrapper of rb_bug() which automatically constructs appropriate
+ * message from the passed errno.
+ *
+ * @param[in] msg Additional message to display.
+ * @exception err C level errno.
+ * @note It never returns.
+ */
+void rb_bug_errno(const char *msg, int err);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Converts a C errno into a Ruby exception, then raises it. For instance:
+ *
+ * ```CXX
+ * static VALUE
+ * foo(VALUE argv)
+ * {
+ * const auto cmd = StringValueCStr(argv);
+ * const auto waitr = system(cmd);
+ * if (waitr == -1) {
+ * rb_sys_fail("system(3posix)"); // <-------------- this
+ * }
+ * else {
+ * return INT2FIX(fd);
+ * }
+ * }
+ * ```
+ *
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing errno.
+ * @note It never returns.
+ */
+void rb_sys_fail(const char *msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_sys_fail(), except it takes the message in Ruby's String
+ * instead of C's.
+ *
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing errno.
+ * @note It never returns.
+ */
+void rb_sys_fail_str(VALUE msg);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * Identical to rb_sys_fail(), except it takes additional module to extend the
+ * exception object before raising.
+ *
+ * @param[in] mod A ::rb_cModule instance.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing errno.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * Does anybody use it?
+ */
+void rb_mod_sys_fail(VALUE mod, const char *msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_mod_sys_fail(), except it takes the message in Ruby's String
+ * instead of C's.
+ *
+ * @param[in] mod A ::rb_cModule instance.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing errno.
+ * @note It never returns.
+ */
+void rb_mod_sys_fail_str(VALUE mod, VALUE msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Raises appropriate exception using the parameters.
+ *
+ * In Ruby level there are rb_eEAGAINWaitReadable etc. This function maps the
+ * given parameter to an appropriate exception class, then raises it.
+ *
+ * @param[in] waiting Reason for the IO to wait.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eEAGAINWaitWritable
+ * @exception rb_eEWOULDBLOCKWaitWritable
+ * @exception rb_eEINPROGRESSWaitWritable
+ * @exception rb_eEAGAINWaitReadable
+ * @exception rb_eEWOULDBLOCKWaitReadable
+ * @exception rb_eEINPROGRESSWaitReadable
+ * @exception rb_eSystemCallError
+ * @note It never returns.
+ */
+void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Breaks from a block. Because you are using a CAPI this is not as intuitive
+ * as it sounds. In order for this function to properly work, make a
+ * ::rb_block_call_func_t function that calls it internally, and pass that
+ * function to rb_block_call().
+ *
+ * @exception rb_eLocalJumpError Called from outside of a block.
+ * @note It never returns.
+ */
+void rb_iter_break(void);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_iter_break(), except it additionally takes the "value" of
+ * this breakage. It will be the evaluation result of the iterator. This is
+ * kind of complicated; you cannot see this as a "return from a block"
+ * behaviour. Take a look at this example:
+ *
+ * ```ruby
+ * def foo(q)
+ * puts(w = yield(q))
+ * puts(e = yield(w))
+ * puts(r = yield(e))
+ * puts(t = yield(r))
+ * puts(y = yield(t))
+ * return "howdy!"
+ * end
+ *
+ * x = foo(0) {|i|
+ * if i > 2
+ * break "hello!"
+ * else
+ * next i + 1
+ * end
+ * }
+ *
+ * puts x
+ * ```
+ *
+ * This script outputs 1, 2, 3, and hello. Note that the value passed to break
+ * becomes the return value of foo method, not the value of yield. This is
+ * confusing, but can be handy on occasions e.g. when you want to bring a
+ * local variable out of a block.
+ *
+ * @param[in] val The value of the iterator.
+ * @exception rb_eLocalJumpError Called from outside of a block.
+ * @note It never returns.
+ */
+void rb_iter_break_value(VALUE val);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Terminates the current execution context. This API is the entry point of a
+ * "well-mannered" termination sequence. When called from an extension
+ * library, it raises ::rb_eSystemExit exception. Programs could rescue that
+ * exception. Can cancel process exit then. Otherwise, that exception results
+ * in a process termination with the status passed to this function.
+ *
+ * @param[in] status Exit status, see also exit(3).
+ * @exception rb_eSystemExit Exception representing the exit status.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * "When called from an extension library"? You might wonder. In fact there
+ * are chances for this function to be called from outside of it, for instance
+ * when dlopen(3) failed. In case it is not possible for this function to
+ * raise an exception, it does not (silently enters to process cleanup). But
+ * that is a kind of implementation detail which extension library authors
+ * should not bother.
+ */
+void rb_exit(int status);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * @exception rb_eNotImpError
+ * @note It never returns.
+ */
+void rb_notimplement(void);
-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 *);
+/**
+ * Creates an exception object that represents the given C errno.
+ *
+ * @param[in] err C level errno.
+ * @param[in] msg Additional message.
+ * @retval rb_eSystemCallError An exception for the errno.
+ */
+VALUE rb_syserr_new(int err, const char * msg);
+
+/**
+ * Identical to rb_syserr_new(), except it takes the message in Ruby's String
+ * instead of C's.
+ *
+ * @param[in] n C level errno.
+ * @param[in] arg Additional message.
+ * @retval rb_eSystemCallError An exception for the errno.
+ */
VALUE rb_syserr_new_str(int n, VALUE arg);
-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*));
-COLDFUNC NORETURN(void rb_unexpected_type(VALUE,int));
+RBIMPL_ATTR_NORETURN()
+/**
+ * Raises appropriate exception that represents a C errno.
+ *
+ * @param[in] err C level errno.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing `err`.
+ * @note It never returns.
+ */
+void rb_syserr_fail(int err, const char *msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_syserr_fail(), except it takes the message in Ruby's String
+ * instead of C's.
+ *
+ * @param[in] err C level errno.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing `err`.
+ * @note It never returns.
+ */
+void rb_syserr_fail_str(int err, VALUE msg);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_mod_sys_fail(), except it does not depend on C global
+ * variable errno. Pass it explicitly.
+ *
+ * @param[in] mod A ::rb_cModule instance.
+ * @param[in] err C level errno.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing `err`.
+ * @note It never returns.
+ */
+void rb_mod_syserr_fail(VALUE mod, int err, const char *msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's
+ * String instead of C's.
+ *
+ * @param[in] mod A ::rb_cModule instance.
+ * @param[in] err C level errno.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eSystemCallError An exception representing `err`.
+ * @note It never returns.
+ */
+void rb_mod_syserr_fail_str(VALUE mod, int err, VALUE msg);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_readwrite_sys_fail(), except it does not depend on C global
+ * variable errno. Pass it explicitly.
+ *
+ * @param[in] waiting Reason for the IO to wait.
+ * @param[in] err C level errno.
+ * @param[in] msg Additional message to raise.
+ * @exception rb_eEAGAINWaitWritable
+ * @exception rb_eEWOULDBLOCKWaitWritable
+ * @exception rb_eEINPROGRESSWaitWritable
+ * @exception rb_eEAGAINWaitReadable
+ * @exception rb_eEWOULDBLOCKWaitReadable
+ * @exception rb_eEINPROGRESSWaitReadable
+ * @exception rb_eSystemCallError
+ * @note It never returns.
+ */
+void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int err, const char *msg);
+
+RBIMPL_ATTR_COLD()
+RBIMPL_ATTR_NORETURN()
+/**
+ * Fails with the given object's type incompatibility to the type.
+ *
+ * It seems this function is visible from extension libraries only because
+ * RTYPEDDATA_TYPE() uses it on RUBY_DEBUG. So you can basically ignore it;
+ * use some other fine-grained method instead.
+ *
+ * @param[in] self The object in question.
+ * @param[in] t Expected type of the object.
+ * @exception rb_eTypeError `self` not in type `t`.
+ * @note It never returns.
+ * @note The second argument must have been an enum ::ruby_value_type,
+ * but for historical reasons it remains to be an int (in other
+ * words we see no benefits fixing this bug).
+ */
+void rb_unexpected_type(VALUE self, int t);
+
+/**
+ * @private
+ *
+ * This is an implementation detail of #ruby_verbose. Please don't use it
+ * directly.
+ *
+ * @retval Qnil Interpreter is quiet.
+ * @retval Qfalse Interpreter is kind of chatty.
+ * @retval otherwise Interpreter is very verbose.
+ */
VALUE *rb_ruby_verbose_ptr(void);
+
+/**
+ * @private
+ *
+ * This is an implementation detail of #ruby_debug. Please don't use it
+ * directly.
+ *
+ * @retval Qnil Interpreter not in debug mode.
+ * @retval Qfalse Interpreter not in debug mode.
+ * @retval otherwise Interpreter is in debug mode.
+ */
VALUE *rb_ruby_debug_ptr(void);
+
+/**
+ * This variable controls whether the interpreter is in debug mode. Setting
+ * this to some truthy value is equivalent to passing `-W` flag to the
+ * interpreter. Setting this to ::Qfalse is equivalent to passing `-W1` flag
+ * to the interpreter. Setting this to ::Qnil is equivalent to passing `-W0`
+ * flag to the interpreter.
+ *
+ * @retval Qnil Interpreter is quiet.
+ * @retval Qfalse Interpreter is kind of chatty.
+ * @retval otherwise Interpreter is very verbose.
+ */
#define ruby_verbose (*rb_ruby_verbose_ptr())
+
+/**
+ * This variable controls whether the interpreter is in debug mode. Setting
+ * this to some truthy value is equivalent to passing `-d` flag to the
+ * interpreter.
+ *
+ * @retval Qnil Interpreter not in debug mode.
+ * @retval Qfalse Interpreter not in debug mode.
+ * @retval otherwise Interpreter is in debug mode.
+ */
#define ruby_debug (*rb_ruby_debug_ptr())
/* reports if `-W' specified */
-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);
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+/**
+ * Issues a warning.
+ *
+ * In ruby, warnings these days are tightly coupled with the rb_mWarning
+ * constant and its `warn` singleton method. This CAPI is just a thin wrapper
+ * of it; everything passed are formatted like what rb_sprintf() does, then
+ * passed through to the method. Programs can have their own `def
+ * Warning.warn` at will to do whatever they want, from ignoring the warnings
+ * at all to sinking them to some BigQuery data set via a Fluentd cluster. By
+ * default, the method just emits its passed contents to ::rb_stderr using
+ * rb_io_write().
+ *
+ * @note This function is affected by the `-W` flag.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+void rb_warning(const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Identical to rb_warning(), except it takes additional "category" parameter.
+ *
+ * @param[in] cat Name of a known category.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_category_warning(rb_warning_category_t cat, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((1, 3))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4)
+/**
+ * Issues a compile-time warning that happens at `__file__:__line__`. Purpose
+ * of this function being exposed to CAPI is unclear.
+ *
+ * @note This function is affected by the `-W` flag.
+ * @param[in] file The path corresponding to Ruby level `__FILE__`.
+ * @param[in] line The number corresponding to Ruby level `__LINE__`.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_compile_warning(const char *file, int line, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+/**
+ * Identical to rb_sys_fail(), except it does not raise an exception to render
+ * a warning instead.
+ *
+ * @note This function is affected by the `-W` flag.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_sys_warning(const char *fmt, ...);
+
/* reports always */
-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_ATTR_COLD()
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+/**
+ * Identical to rb_warning(), except it reports always regardless of runtime
+ * `-W` flag.
+ *
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_warn(const char *fmt, ...);
+
+RBIMPL_ATTR_COLD()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Identical to rb_category_warning(), except it reports always regardless of
+ * runtime `-W` flag.
+ *
+ * @param[in] cat Category e.g. deprecated.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_category_warn(rb_warning_category_t cat, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((1, 3))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4)
+/**
+ * Identical to rb_compile_warning(), except it reports always regardless of
+ * runtime `-W` flag.
+ *
+ * @param[in] file The path corresponding to Ruby level `__FILE__`.
+ * @param[in] line The number corresponding to Ruby level `__LINE__`.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_compile_warn(const char *file, int line, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((2, 4))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5)
+/**
+ * Identical to rb_compile_warn(), except it also accepts category.
+ *
+ * @param[in] cat Category e.g. deprecated.
+ * @param[in] file The path corresponding to Ruby level `__FILE__`.
+ * @param[in] line The number corresponding to Ruby level `__LINE__`.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ */
+void rb_category_compile_warn(rb_warning_category_t cat, const char *file, int line, const char *fmt, ...);
+
+/** @} */
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/eval.h b/include/ruby/internal/eval.h
index 934611fbb9..5bcbb97746 100644
--- a/include/ruby/internal/eval.h
+++ b/include/ruby/internal/eval.h
@@ -17,32 +17,382 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Declares ::rb_eval_string().
*/
#include "ruby/internal/dllexport.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
-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);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Evaluates the given string.
+ *
+ * In case it is called from within a C-backended method, the evaluation is
+ * done under the current binding. However there can be no method. On such
+ * situation this function evaluates in an isolated binding, like `require`
+ * runs in a separate one.
+ *
+ * `__FILE__` will be `"(eval)"`, and `__LINE__` starts from 1 in the
+ * evaluation.
+ *
+ * @param[in] str Ruby code to evaluate.
+ * @exception rb_eException Raises an exception on error.
+ * @return The evaluated result.
+ *
+ * @internal
+ *
+ * @shyouhei's old tale about the birth and growth of this function:
+ *
+ * At the beginning, there was no rb_eval_string(). @shyouhei heard that
+ * @shugo, author of Apache httpd's mod_ruby module, requested @matz for this
+ * API. He wanted a way so that mod_ruby can evaluate ruby scripts one by one,
+ * separately, in each different contexts. So this function was made. It was
+ * designed to be a global interpreter entry point like ruby_run_node().
+ *
+ * The way it is implemented however allows extension libraries (not just
+ * programs like Apache httpd) to call this function. Because its name says
+ * nothing about the initial design, people started to think of it as an
+ * orthodox way to call ruby level `eval` method from their extension
+ * libraries. Even our `extension.rdoc` has had a description of this function
+ * basically according to this understanding.
+ *
+ * The old (mod_ruby like) usage still works. But over time, usages of this
+ * function from extension libraries got popular, while mod_ruby faded out; is
+ * no longer maintained now. Devs decided to actively support both. This
+ * function now auto-detects how it is called, and switches how it works
+ * depending on it.
+ *
+ * @see https://bugs.ruby-lang.org/issues/18780
+ */
+VALUE rb_eval_string(const char *str);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_eval_string(), except it avoids potential global escapes.
+ * Such global escapes include exceptions, `throw`, `break`, for example.
+ *
+ * It first evaluates the given string as rb_eval_string() does. If no global
+ * escape occurred during the evaluation, it returns the result and `*state` is
+ * zero. Otherwise, it returns some undefined value and sets `*state` to
+ * nonzero. If state is `NULL`, it is not set in both cases.
+ *
+ * @param[in] str Ruby code to evaluate.
+ * @param[out] state State of execution.
+ * @return The evaluated result if succeeded, an undefined value if
+ * otherwise.
+ * @post `*state` is set to zero if succeeded. Nonzero otherwise.
+ * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if
+ * you decide to ignore the caught exception.
+ * @see rb_eval_string
+ * @see rb_protect
+ *
+ * @internal
+ *
+ * The "undefined value" described above is in fact ::RUBY_Qnil for now. But
+ * @shyouhei doesn't think that we would never change that.
+ *
+ * Though not a part of our public API, `state` is in fact an
+ * enum ruby_tag_type. You can see the potential "nonzero" values by looking
+ * at vm_core.h.
+ */
+VALUE rb_eval_string_protect(const char *str, int *state);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_eval_string_protect(), except it evaluates the given string
+ * under a module binding in an isolated binding. This is the same as a
+ * binding for loaded libraries on `rb_load(something, true)`.
+ *
+ * @param[in] str Ruby code to evaluate.
+ * @param[out] state State of execution.
+ * @return The evaluated result if succeeded, an undefined value if
+ * otherwise.
+ * @post `*state` is set to zero if succeeded. Nonzero otherwise.
+ * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if
+ * you decide to ignore the caught exception.
+ * @see rb_eval_string
+ */
+VALUE rb_eval_string_wrap(const char *str, int *state);
+
+/**
+ * Calls a method. Can call both public and private methods.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] n Number of arguments that follow.
+ * @param[in] ... Arbitrary number of method arguments.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcall(VALUE recv, ID mid, int n, ...);
+
+/**
+ * Identical to rb_funcall(), except it takes the method arguments as a C
+ * array.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_funcallv(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat);
+
+/**
+ * Identical to rb_funcallv(), except it only takes public methods into
+ * account. This is roughly Ruby's `Object#public_send`.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eNoMethodError The method is private or protected.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_funcallv_public(), except you can specify how to handle the
+ * last element of the given array. It can also be seen as a routine identical
+ * to rb_funcallv_kw(), except it only takes public methods into account.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eNoMethodError The method is private or protected.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat);
+
+/**
+ * @deprecated This is an old name of rb_funcallv(). Provided here for
+ * backwards compatibility to 2.x programs (introduced in 2.1).
+ * It is not a good name. Please don't use it any longer.
+ */
#define rb_funcall2 rb_funcallv
+
+/**
+ * @deprecated This is an old name of rb_funcallv_public(). Provided here
+ * for backwards compatibility to 2.x programs (introduced in
+ * 2.1). It is not a good name. Please don't use it any longer.
+ */
#define rb_funcall3 rb_funcallv_public
-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);
+
+/**
+ * Identical to rb_funcallv_public(), except you can pass the passed block.
+ *
+ * Sometimes you want to "pass" a block parameter form one method to another.
+ * Suppose you have this Ruby method `foo`:
+ *
+ * ```ruby
+ * def foo(x, y, &z)
+ * x.open(y, &z)
+ * end
+ * ```
+ *
+ * And suppose you want to translate this into C. Then
+ * rb_funcall_passing_block() function is usable in this situation.
+ *
+ * ```CXX
+ * VALUE
+ * foo_translated_into_C(VALUE self, VALUE x, VALUE y)
+ * {
+ * const auto open = rb_intern("open");
+ *
+ * return rb_funcall_passing_block(x, open, 1, &y);
+ * }
+ * ```
+ *
+ * @see rb_yield_block
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eNoMethodError The method is private or protected.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_funcallv_passing_block(), except you can specify how to
+ * handle the last element of the given array. It can also be seen as a
+ * routine identical to rb_funcallv_public_kw(), except you can pass the passed
+ * block.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eNoMethodError The method is private or protected.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat);
+
+/**
+ * Identical to rb_funcallv_public(), except you can pass a block. A block
+ * here basically is an instance of ::rb_cProc. If you want to exercise
+ * `to_proc` conversion, do so before passing it here. However nil and symbols
+ * are special-case allowed.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] procval An instance of Proc, Symbol, or NilClass.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eNoMethodError The method is private or protected.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ *
+ * @internal
+ *
+ * Implementation-wise, `procval` is in fact a "block handler" object. You
+ * could also pass an IFUNC (block_handler_ifunc) here to say precise. --- But
+ * AFAIK there is no 3rd party way to even know that there are objects called
+ * IFUNC behind-the-scene.
+ */
+VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval);
+
+/**
+ * Identical to rb_funcallv_with_block(), except you can specify how to handle
+ * the last element of the given array. It can also be seen as a routine
+ * identical to rb_funcallv_public_kw(), except you can pass a block.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] procval An instance of Proc, Symbol, or NilClass.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eNoMethodError The method is private or protected.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ */
+VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval, int kw_splat);
+
+/**
+ * This resembles ruby's `super`.
+ *
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @exception rb_eNoMethodError No super method are there.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the super method evaluates to.
+ */
+VALUE rb_call_super(int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_call_super(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eNoMethodError No super method are there.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the super method evaluates to.
+ */
+VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat);
+
+/**
+ * This resembles ruby's `self`.
+ *
+ * @exception rb_eRuntimeError Called from outside of method context.
+ * @return Current receiver.
+ */
VALUE rb_current_receiver(void);
-int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *);
+
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * Keyword argument deconstructor.
+ *
+ * Retrieves argument values bound to keywords, which directed by `table` into
+ * `values`, deleting retrieved entries from `keyword_hash` along the way.
+ * First `required` number of IDs referred by `table` are mandatory, and
+ * succeeding `optional` (`-optional-1` if `optional` is negative) number of
+ * IDs are optional. If a mandatory key is not contained in `keyword_hash`,
+ * raises ::rb_eArgError. If an optional key is not present in `keyword_hash`,
+ * the corresponding element in `values` is set to ::RUBY_Qundef. If
+ * `optional` is negative, rest of `keyword_hash` are ignored, otherwise raises
+ * ::rb_eArgError.
+ *
+ * @warning Handling keyword arguments in the C API is less efficient than
+ * handling them in Ruby. Consider using a Ruby wrapper method
+ * around a non-keyword C function.
+ * @see https://bugs.ruby-lang.org/issues/11339
+ * @param[out] keyword_hash Target hash to deconstruct.
+ * @param[in] table List of keywords that you are interested in.
+ * @param[in] required Number of mandatory keywords.
+ * @param[in] optional Number of optional keywords (can be negative).
+ * @param[out] values Buffer to be filled.
+ * @exception rb_eArgError Absence of a mandatory keyword.
+ * @exception rb_eArgError Found an unknown keyword.
+ * @return Number of found values that are stored into `values`.
+ */
+int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Splits a hash into two.
+ *
+ * Takes a hash of various keys, and split it into symbol-keyed parts and
+ * others. Symbol-keyed part becomes the return value. What remains are
+ * returned as a new hash object stored at the argument pointer.
+ *
+ * @param[in,out] orighash Pointer to a target hash to split.
+ * @return An extracted keyword hash.
+ * @post Upon successful return `orighash` points to another hash
+ * object, whose contents are the remainder of the operation.
+ * @note The argument hash object is not modified.
+ */
VALUE rb_extract_keywords(VALUE *orighash);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/event.h b/include/ruby/internal/event.h
index f20e01dc01..04b137a193 100644
--- a/include/ruby/internal/event.h
+++ b/include/ruby/internal/event.h
@@ -17,59 +17,138 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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()
+/* These macros are not enums because they are wider than int.*/
+
+/**
+ * @name Traditional set_trace_func events
+ *
+ * @{
+ */
+#define RUBY_EVENT_NONE 0x0000 /**< No events. */
+#define RUBY_EVENT_LINE 0x0001 /**< Encountered a new line. */
+#define RUBY_EVENT_CLASS 0x0002 /**< Encountered a new class. */
+#define RUBY_EVENT_END 0x0004 /**< Encountered an end of a class clause. */
+#define RUBY_EVENT_CALL 0x0008 /**< A method, written in Ruby, is called. */
+#define RUBY_EVENT_RETURN 0x0010 /**< Encountered a `return` statement. */
+#define RUBY_EVENT_C_CALL 0x0020 /**< A method, written in C, is called. */
+#define RUBY_EVENT_C_RETURN 0x0040 /**< Return from a method, written in C. */
+#define RUBY_EVENT_RAISE 0x0080 /**< Encountered a `raise` statement. */
+#define RUBY_EVENT_ALL 0x00ff /**< Bitmask of traditional events. */
+
+/** @} */
+
+/**
+ * @name TracePoint extended events
+ *
+ * @{
+ */
+#define RUBY_EVENT_B_CALL 0x0100 /**< Encountered an `yield` statement. */
+#define RUBY_EVENT_B_RETURN 0x0200 /**< Encountered a `next` statement. */
+#define RUBY_EVENT_THREAD_BEGIN 0x0400 /**< Encountered a new thread. */
+#define RUBY_EVENT_THREAD_END 0x0800 /**< Encountered an end of a thread. */
+#define RUBY_EVENT_FIBER_SWITCH 0x1000 /**< Encountered a `Fiber#yield`. */
+#define RUBY_EVENT_SCRIPT_COMPILED 0x2000 /**< Encountered an `eval`. */
+#define RUBY_EVENT_TRACEPOINT_ALL 0xffff /**< Bitmask of extended events. */
-/* 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 */
+/** @} */
+
+/**
+ * @name Special events
+ *
+ * @internal
+ *
+ * These bits are actually used internally. See vm_core.h if you are curious.
+ *
+ * @endinternal
+ *
+ * @{
+ */
+#define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 /**< Opaque bits. */
+
+/** @} */
+
+/**
+ * @name Internal events
+ *
+ * @shyouhei's understanding is that some of them are visible from extension
+ * libraries because of `ext/objspace`. But it seems that doesn't describe
+ * everything? The ultimate reason why they are here remains unclear.
+ *
+ * @{
+ */
+#define RUBY_INTERNAL_EVENT_SWITCH 0x040000 /**< Thread switched. */
+#define RUBY_EVENT_SWITCH 0x040000 /**< @old{RUBY_INTERNAL_EVENT_SWITCH} */
/* 0x080000 */
-#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000
-#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
+#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000 /**< Object allocated. */
+#define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000 /**< Object swept. */
+#define RUBY_INTERNAL_EVENT_GC_START 0x400000 /**< GC started. */
+#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000 /**< GC ended mark phase. */
+#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000 /**< GC ended sweep phase. */
+#define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000 /**< `gc_enter()` is called. */
+#define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000 /**< `gc_exit()` is called. */
+#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000 /**< Bitmask of GC events. */
+#define RUBY_INTERNAL_EVENT_MASK 0xffff0000 /**< Bitmask of internal events. */
+
+/** @} */
+/**
+ * Represents event(s). As the name implies events are bit flags.
+ */
typedef uint32_t rb_event_flag_t;
+
+/**
+ * Type of event hooks. When an event happens registered functions are kicked
+ * with appropriate parameters.
+ *
+ * @param[in] evflag The kind of event that happened.
+ * @param[in] data The `data` passed to rb_add_event_hook().
+ * @param[in] self Current receiver.
+ * @param[in] mid Name of the current method.
+ * @param[in] klass Current class.
+ */
typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass);
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Registers an event hook function.
+ *
+ * @param[in] func A callback.
+ * @param[in] events A set of events that `func` should run.
+ * @param[in] data Passed as-is to `func`.
+ */
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
-int rb_remove_event_hook(rb_event_hook_func_t func);
+/**
+ * Removes the passed function from the list of event hooks.
+ *
+ * @param[in] func A callback.
+ * @return Number of deleted event hooks.
+ * @note As multiple events can share the same `func` it is quite
+ * possible for the return value to become more than one.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't know if this is an Easter egg or an official feature, but
+ * you can pass 0 to the argument. That effectively swipes everything out from
+ * the hook list.
+ */
+int rb_remove_event_hook(rb_event_hook_func_t func);
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_EVENT_H */
diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h
index 1906133f9d..7383426b23 100644
--- a/include/ruby/internal/fl_type.h
+++ b/include/ruby/internal/fl_type.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines enum ::ruby_fl_type.
*/
#include "ruby/internal/config.h" /* for ENUM_OVER_INT */
@@ -55,46 +55,46 @@
#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
+#define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) /**< @old{RUBY_FL_SINGLETON} */
+#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */
+#define FL_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0) /**< @old{RUBY_FL_PROMOTED0} */
+#define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1) /**< @old{RUBY_FL_PROMOTED1} */
+#define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */
+#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */
+#define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */
+#define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */
+#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) /**< @old{RUBY_FL_SEEN_OBJ_ID} */
+#define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) /**< @old{RUBY_FL_EXIVAR} */
+#define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) /**< @old{RUBY_FL_FREEZE} */
+
+#define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT) /**< @old{RUBY_FL_USHIFT} */
+
+#define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0) /**< @old{RUBY_FL_USER0} */
+#define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1) /**< @old{RUBY_FL_USER1} */
+#define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2) /**< @old{RUBY_FL_USER2} */
+#define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3) /**< @old{RUBY_FL_USER3} */
+#define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4) /**< @old{RUBY_FL_USER4} */
+#define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5) /**< @old{RUBY_FL_USER5} */
+#define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6) /**< @old{RUBY_FL_USER6} */
+#define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7) /**< @old{RUBY_FL_USER7} */
+#define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8) /**< @old{RUBY_FL_USER8} */
+#define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9) /**< @old{RUBY_FL_USER9} */
+#define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10) /**< @old{RUBY_FL_USER10} */
+#define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11) /**< @old{RUBY_FL_USER11} */
+#define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12) /**< @old{RUBY_FL_USER12} */
+#define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13) /**< @old{RUBY_FL_USER13} */
+#define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14) /**< @old{RUBY_FL_USER14} */
+#define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15) /**< @old{RUBY_FL_USER15} */
+#define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16) /**< @old{RUBY_FL_USER16} */
+#define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17) /**< @old{RUBY_FL_USER17} */
+#define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18) /**< @old{RUBY_FL_USER18} */
+#define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19) /**< @old{RUBY_FL_USER19} */
+
+#define ELTS_SHARED RUBY_ELTS_SHARED /**< @old{RUBY_ELTS_SHARED} */
+#define RB_OBJ_FREEZE rb_obj_freeze_inline /**< @alias{rb_obj_freeze_inline} */
/** @cond INTERNAL_MACRO */
+#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED
#define RB_FL_ABLE RB_FL_ABLE
#define RB_FL_ALL RB_FL_ALL
#define RB_FL_ALL_RAW RB_FL_ALL_RAW
@@ -123,57 +123,158 @@
/** @endcond */
/**
- * @defgroup deprecated_macros deprecated macro APIs
+ * @defgroup deprecated_macros Deprecated macro APIs
* @{
- * These macros are deprecated. Prefer their `RB_`-prefixed versions.
+ * 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
+#define FL_ABLE RB_FL_ABLE /**< @old{RB_FL_ABLE} */
+#define FL_ALL RB_FL_ALL /**< @old{RB_FL_ALL} */
+#define FL_ALL_RAW RB_FL_ALL_RAW /**< @old{RB_FL_ALL_RAW} */
+#define FL_ANY RB_FL_ANY /**< @old{RB_FL_ANY} */
+#define FL_ANY_RAW RB_FL_ANY_RAW /**< @old{RB_FL_ANY_RAW} */
+#define FL_REVERSE RB_FL_REVERSE /**< @old{RB_FL_REVERSE} */
+#define FL_REVERSE_RAW RB_FL_REVERSE_RAW /**< @old{RB_FL_REVERSE_RAW} */
+#define FL_SET RB_FL_SET /**< @old{RB_FL_SET} */
+#define FL_SET_RAW RB_FL_SET_RAW /**< @old{RB_FL_SET_RAW} */
+#define FL_TEST RB_FL_TEST /**< @old{RB_FL_TEST} */
+#define FL_TEST_RAW RB_FL_TEST_RAW /**< @old{RB_FL_TEST_RAW} */
+#define FL_UNSET RB_FL_UNSET /**< @old{RB_FL_UNSET} */
+#define FL_UNSET_RAW RB_FL_UNSET_RAW /**< @old{RB_FL_UNSET_RAW} */
+#define OBJ_FREEZE RB_OBJ_FREEZE /**< @old{RB_OBJ_FREEZE} */
+#define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW /**< @old{RB_OBJ_FREEZE_RAW} */
+#define OBJ_FROZEN RB_OBJ_FROZEN /**< @old{RB_OBJ_FROZEN} */
+#define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW /**< @old{RB_OBJ_FROZEN_RAW} */
+#define OBJ_INFECT RB_OBJ_INFECT /**< @old{RB_OBJ_INFECT} */
+#define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW /**< @old{RB_OBJ_INFECT_RAW} */
+#define OBJ_TAINT RB_OBJ_TAINT /**< @old{RB_OBJ_TAINT} */
+#define OBJ_TAINTABLE RB_OBJ_TAINTABLE /**< @old{RB_OBJ_TAINT_RAW} */
+#define OBJ_TAINTED RB_OBJ_TAINTED /**< @old{RB_OBJ_TAINTED} */
+#define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW /**< @old{RB_OBJ_TAINTED_RAW} */
+#define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW /**< @old{RB_OBJ_TAINT_RAW} */
+#define OBJ_UNTRUST RB_OBJ_UNTRUST /**< @old{RB_OBJ_TAINT} */
+#define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED /**< @old{RB_OBJ_TAINTED} */
/** @} */
-/* This is an enum because GDB wants it (rather than a macro) */
-enum ruby_fl_ushift { RUBY_FL_USHIFT = 12 };
+/**
+ * This is an enum because GDB wants it (rather than a macro). People need not
+ * bother.
+ */
+enum ruby_fl_ushift {
+ /**
+ * Number of bits in ::ruby_fl_type that are _not_ open to users. This is
+ * an implementation detail. Please ignore.
+ */
+ RUBY_FL_USHIFT = 12
+};
/* > The expression that defines the value of an enumeration constant shall be
* > an integer constant expression that has a value representable as an `int`.
*
* -- ISO/IEC 9899:2018 section 6.7.2.2
*
- * So ENUM_OVER_INT situation is an extension to the standard. Note however
+ * So ENUM_OVER_INT situation is an extension to the standard. Note however
* that we do not support 16 bit `int` environment. */
RB_GNUC_EXTENSION
+/**
+ * The flags. Each ruby objects have their own characteristics apart from
+ * their classes. For instance whether an object is frozen or not is not
+ * controlled by its class. This is the type that represents such properties.
+ *
+ * @note About the `FL_USER` terminology: the "user" here does not necessarily
+ * mean only you. For instance struct ::RString instances use these
+ * bits to cache their encodings etc. Devs discussed about this topic,
+ * reached their consensus that ::RUBY_T_DATA is the only valid data
+ * structure that can use these bits; other data structures including
+ * ::RUBY_T_OBJECT use these bits for their own purpose. See also
+ * https://bugs.ruby-lang.org/issues/18059
+ */
enum
RBIMPL_ATTR_FLAG_ENUM()
ruby_fl_type {
+
+ /**
+ * @deprecated This flag once was a thing back in the old days, but makes
+ * no sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * The reality is our GC no longer remembers write barriers inside of each
+ * objects, to use dedicated bitmap instead. But this flag is still used
+ * internally. The current usages of this flag should be something
+ * different, which is unclear to @shyouhei.
+ */
RUBY_FL_WB_PROTECTED = (1<<5),
+
+ /**
+ * This flag has something to do with our garbage collector. These days
+ * ruby objects are "generational". There are those who are young and
+ * those who are old. Young objects are prone to die; monitored relatively
+ * extensively by the garbage collector. OTOH old objects tend to live
+ * longer. They are relatively rarely considered. This flag is set when a
+ * object experienced promotion i.e. survived a garbage collection.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_FL_PROMOTED0 = (1<<5),
+
+ /**
+ * This flag has something to do with our garbage collector. These days
+ * ruby objects are "generational". There are those who are young and
+ * those who are old. Young objects are prone to die; monitored relatively
+ * extensively by the garbage collector. OTOH old objects tend to live
+ * longer. They are relatively rarely considered. This flag is set when a
+ * object experienced two promotions i.e. survived garbage collections
+ * twice.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_FL_PROMOTED1 = (1<<6),
+
+ /**
+ * This flag has something to do with our garbage collector. These days
+ * ruby objects are "generational". There are those who are young and
+ * those who are old. Young objects are prone to die; monitored relatively
+ * extensively by the garbage collector. OTOH old objects tend to live
+ * longer. They are relatively rarely considered. This flag is set when a
+ * object experienced promotions i.e. survived more than one garbage
+ * collections.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1,
+
+ /**
+ * This flag has something to do with finalisers. A ruby object can have
+ * its finaliser, which is another object that evaluates when the target
+ * object is about to die. This flag is used to denote that there is an
+ * attached finaliser.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_FL_FINALIZE = (1<<7),
+
+ /**
+ * @deprecated This flag once was a thing back in the old days, but makes
+ * no sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ */
RUBY_FL_TAINT
#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE)
@@ -183,7 +284,24 @@ ruby_fl_type {
#endif
= (1<<8),
+
+ /**
+ * This flag has something to do with Ractor. Multiple Ractors run without
+ * protecting each other. Sharing an object among Ractors are basically
+ * dangerous, disabled by default. This flag is used to bypass that
+ * restriction. Of course, you have to manually prevent race conditions
+ * then.
+ *
+ * This flag needs deep understanding of multithreaded programming. You
+ * would better not use it.
+ */
RUBY_FL_SHAREABLE = (1<<8),
+
+ /**
+ * @deprecated This flag once was a thing back in the old days, but makes
+ * no sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ */
RUBY_FL_UNTRUSTED
#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE)
@@ -193,43 +311,131 @@ ruby_fl_type {
#endif
= (1<<8),
+
+ /**
+ * This flag has something to do with object IDs. Unlike in the old days,
+ * an object's object ID (that a user can query using `Object#object_id`)
+ * is no longer its physical address represented using Ruby level integers.
+ * It is now a monotonic-increasing integer unrelated to the underlying
+ * memory arrangement. Object IDs are assigned when necessary; objects are
+ * born without one, and will eventually have such property when queried.
+ * The interpreter has to manage which one is which. This is the flag that
+ * helps the management. Objects with this flag set are the ones with
+ * object IDs assigned.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_FL_SEEN_OBJ_ID = (1<<9),
+
+ /**
+ * This flag has something to do with instance variables. 3rd parties need
+ * not know, but there are several ways to store an object's instance
+ * variables. Objects with this flag use so-called "generic" backend
+ * storage. This distinction is purely an implementation detail. People
+ * need not be aware of this working behind-the-scene.
+ *
+ * @internal
+ *
+ * As of writing everything except ::RObject and RModule use this scheme.
+ */
RUBY_FL_EXIVAR = (1<<10),
+
+ /**
+ * This flag has something to do with data immutability. When this flag is
+ * set an object is considered "frozen". No modification are expected to
+ * happen beyond that point for the particular object. Immutability is
+ * basically considered to be a good property these days. Library authors
+ * are expected to obey. Test this bit before you touch a data structure.
+ *
+ * @see rb_check_frozen()
+ */
RUBY_FL_FREEZE = (1<<11),
+/** (@shyouhei doesn't know how to excude this macro from doxygen). */
#define RBIMPL_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n))
- RBIMPL_FL_USER_N(0),
- 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),
+ RBIMPL_FL_USER_N(0), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(1), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(2), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(3), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(4), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(5), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(6), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(7), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(8), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(9), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(10), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(11), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(12), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(13), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(14), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(15), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(16), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(17), /**< User-defined flag. */
+ RBIMPL_FL_USER_N(18), /**< User-defined flag. */
#ifdef ENUM_OVER_INT
- RBIMPL_FL_USER_N(19),
+ RBIMPL_FL_USER_N(19), /**< User-defined flag. */
#else
# define RUBY_FL_USER19 (RBIMPL_VALUE_ONE<<(RUBY_FL_USHIFT+19))
#endif
#undef RBIMPL_FL_USER_N
#undef RBIMPL_WIDER_ENUM
+ /**
+ * This flag has something to do with data structures. Over time, ruby
+ * evolved to reduce memory footprints. One of such attempt is so-called
+ * copy-on-write, which delays duplication of resources until ultimately
+ * necessary. Some data structures share this scheme. For example
+ * multiple instances of struct ::RArray could point identical memory
+ * region in common, as long as they don't differ. As people favour
+ * immutable style of programming than before, this situation is getting
+ * more and more common. Because such "shared" memory regions have nuanced
+ * ownership by nature, each structures need special care for them. This
+ * flag is used to distinguish such shared constructs.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_ELTS_SHARED = RUBY_FL_USER2,
+
+ /**
+ * This flag has something to do with an object's class. There are kind of
+ * classes called "singleton class", each of which have exactly one
+ * instance. What is interesting about singleton classes is that they are
+ * created _after_ their instance were instantiated, like this:
+ *
+ * ```ruby
+ * foo = Object.new # foo is an instance of Object...
+ * bar = foo.singleton_class # foo is now an instance of bar.
+ * ```
+ *
+ * Here as you see `bar` is a singleton class of `foo`, which is injected
+ * into `foo`'s inheritance tree in a different statement (== distinct
+ * sequence point). In order to achieve this property singleton classes
+ * are special-cased in the interpreter. There is one bit flag that
+ * distinguishes if a class is a singleton class or not, and this is it.
+ *
+ * @internal
+ *
+ * But honestly, @shyouhei doesn't think this flag should be visible from
+ * 3rd parties. It must be an implementation detail that they should never
+ * know. Might better be hidden.
+ */
RUBY_FL_SINGLETON = RUBY_FL_USER0,
};
enum {
+ /**
+ * @deprecated This flag once was a thing back in the old days, but makes
+ * no sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ */
RUBY_FL_DUPPED
#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE)
@@ -244,13 +450,28 @@ enum {
#undef RBIMPL_HAVE_ENUM_ATTRIBUTE
RBIMPL_SYMBOL_EXPORT_BEGIN()
-void rb_obj_infect(VALUE victim, VALUE carrier);
+/**
+ * This is an implementation detail of #RB_OBJ_FREEZE(). People don't use it
+ * directly.
+ *
+ * @param[out] klass A singleton class.
+ * @post `klass` gets frozen.
+ */
void rb_freeze_singleton_class(VALUE klass);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_FORCEINLINE()
+/**
+ * Checks if the object is flaggable. There are some special cases (most
+ * notably ::RUBY_Qfalse) where appending a flag to an object is not possible.
+ * This function can detect that.
+ *
+ * @param[in] obj Object in question
+ * @retval true It is flaggable.
+ * @retval false No it isn't.
+ */
static bool
RB_FL_ABLE(VALUE obj)
{
@@ -267,6 +488,15 @@ RB_FL_ABLE(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_FL_TEST(). 3rd parties need not use
+ * this. Just always use RB_FL_TEST().
+ *
+ * @param[in] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @pre The object must not be an enum ::ruby_special_consts.
+ * @return `obj`'s flags, masked by `flags`.
+ */
static inline VALUE
RB_FL_TEST_RAW(VALUE obj, VALUE flags)
{
@@ -276,6 +506,23 @@ RB_FL_TEST_RAW(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Tests if the given flag(s) are set or not. You can pass multiple flags at
+ * once:
+ *
+ * ```CXX
+ * auto obj = rb_eval_string("...");
+ * if (RB_FL_TEST(obj, RUBY_FL_FREEZE | RUBY_FL_SHAREABLE)) {
+ * printf("Ractor ready!\n");
+ * }
+ * ```
+ *
+ * @param[in] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @return `obj`'s flags, masked by `flags`.
+ * @note It is intentional for this function to return ::VALUE. The
+ * return value could be passed to RB_FL_STE() etc.
+ */
static inline VALUE
RB_FL_TEST(VALUE obj, VALUE flags)
{
@@ -289,6 +536,16 @@ RB_FL_TEST(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_FL_ANY(). 3rd parties need not use
+ * this. Just always use RB_FL_ANY().
+ *
+ * @param[in] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @retval true The object has any of the flags set.
+ * @retval false No it doesn't at all.
+ * @pre The object must not be an enum ::ruby_special_consts.
+ */
static inline bool
RB_FL_ANY_RAW(VALUE obj, VALUE flags)
{
@@ -297,6 +554,14 @@ RB_FL_ANY_RAW(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Identical to RB_FL_TEST(), except it returns bool.
+ *
+ * @param[in] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @retval true The object has any of the flags set.
+ * @retval false No it doesn't at all.
+ */
static inline bool
RB_FL_ANY(VALUE obj, VALUE flags)
{
@@ -305,6 +570,16 @@ RB_FL_ANY(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_FL_ALL(). 3rd parties need not use
+ * this. Just always use RB_FL_ALL().
+ *
+ * @param[in] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @retval true The object has all of the flags set.
+ * @retval false The object lacks any of the flags.
+ * @pre The object must not be an enum ::ruby_special_consts.
+ */
static inline bool
RB_FL_ALL_RAW(VALUE obj, VALUE flags)
{
@@ -313,6 +588,14 @@ RB_FL_ALL_RAW(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Identical to RB_FL_ANY(), except it mandates all passed flags be set.
+ *
+ * @param[in] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @retval true The object has all of the flags set.
+ * @retval false The object lacks any of the flags.
+ */
static inline bool
RB_FL_ALL(VALUE obj, VALUE flags)
{
@@ -321,6 +604,21 @@ RB_FL_ALL(VALUE obj, VALUE flags)
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * @private
+ *
+ * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use
+ * this. Just always use RB_FL_SET().
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` set.
+ *
+ * @internal
+ *
+ * This is function is here to annotate a part of RB_FL_SET_RAW() as
+ * `__declspec(noalias)`.
+ */
static inline void
rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags)
{
@@ -328,6 +626,14 @@ rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use
+ * this. Just always use RB_FL_SET().
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` set.
+ */
static inline void
RB_FL_SET_RAW(VALUE obj, VALUE flags)
{
@@ -336,6 +642,18 @@ RB_FL_SET_RAW(VALUE obj, VALUE flags)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Sets the given flag(s).
+ *
+ * ```CXX
+ * auto v = rb_eval_string("...");
+ * RB_FL_SET(v, RUBY_FL_FREEZE);
+ * ```
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` set.
+ */
static inline void
RB_FL_SET(VALUE obj, VALUE flags)
{
@@ -346,6 +664,21 @@ RB_FL_SET(VALUE obj, VALUE flags)
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * @private
+ *
+ * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use
+ * this. Just always use RB_FL_UNSET().
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` cleared.
+ *
+ * @internal
+ *
+ * This is function is here to annotate a part of RB_FL_UNSET_RAW() as
+ * `__declspec(noalias)`.
+ */
static inline void
rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags)
{
@@ -353,6 +686,14 @@ rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use
+ * this. Just always use RB_FL_UNSET().
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` cleared.
+ */
static inline void
RB_FL_UNSET_RAW(VALUE obj, VALUE flags)
{
@@ -361,6 +702,13 @@ RB_FL_UNSET_RAW(VALUE obj, VALUE flags)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Clears the given flag(s).
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` cleard.
+ */
static inline void
RB_FL_UNSET(VALUE obj, VALUE flags)
{
@@ -371,6 +719,21 @@ RB_FL_UNSET(VALUE obj, VALUE flags)
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * @private
+ *
+ * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not
+ * use this. Just always use RB_FL_REVERSE().
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` reversed.
+ *
+ * @internal
+ *
+ * This is function is here to annotate a part of RB_FL_REVERSE_RAW() as
+ * `__declspec(noalias)`.
+ */
static inline void
rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags)
{
@@ -378,6 +741,14 @@ rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not
+ * use this. Just always use RB_FL_REVERSE().
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` cleared.
+ */
static inline void
RB_FL_REVERSE_RAW(VALUE obj, VALUE flags)
{
@@ -386,6 +757,14 @@ RB_FL_REVERSE_RAW(VALUE obj, VALUE flags)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Reverses the flags. This function is here mainly for symmetry on set/unset.
+ * Rarely used in practice.
+ *
+ * @param[out] obj Object in question.
+ * @param[in] flags A set of enum ::ruby_fl_type.
+ * @post `obj` has `flags` reversed.
+ */
static inline void
RB_FL_REVERSE(VALUE obj, VALUE flags)
{
@@ -397,6 +776,14 @@ RB_FL_REVERSE(VALUE obj, VALUE flags)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] obj Object in question.
+ * @return false always.
+ */
static inline bool
RB_OBJ_TAINTABLE(VALUE obj)
{
@@ -406,6 +793,14 @@ RB_OBJ_TAINTABLE(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] obj Object in question.
+ * @return false always.
+ */
static inline VALUE
RB_OBJ_TAINTED_RAW(VALUE obj)
{
@@ -415,6 +810,14 @@ RB_OBJ_TAINTED_RAW(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] obj Object in question.
+ * @return false always.
+ */
static inline bool
RB_OBJ_TAINTED(VALUE obj)
{
@@ -423,6 +826,13 @@ RB_OBJ_TAINTED(VALUE obj)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] obj Object in question.
+ */
static inline void
RB_OBJ_TAINT_RAW(VALUE obj)
{
@@ -431,6 +841,13 @@ RB_OBJ_TAINT_RAW(VALUE obj)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] obj Object in question.
+ */
static inline void
RB_OBJ_TAINT(VALUE obj)
{
@@ -439,6 +856,14 @@ RB_OBJ_TAINT(VALUE obj)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] dst Victim object.
+ * @param[in] src Infectant object.
+ */
static inline void
RB_OBJ_INFECT_RAW(VALUE dst, VALUE src)
{
@@ -447,6 +872,14 @@ RB_OBJ_INFECT_RAW(VALUE dst, VALUE src)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] dst Victim object.
+ * @param[in] src Infectant object.
+ */
static inline void
RB_OBJ_INFECT(VALUE dst, VALUE src)
{
@@ -455,9 +888,20 @@ RB_OBJ_INFECT(VALUE dst, VALUE 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. */
+/**
+ * This is an implenentation detail of RB_OBJ_FROZEN(). 3rd parties need not
+ * use this. Just always use RB_OBJ_FROZEN().
+ *
+ * @param[in] obj Object in question.
+ * @retval RUBY_FL_FREEZE Yes it is.
+ * @retval 0 No it isn't.
+ *
+ * @internal
+ *
+ * It is intentional not to return bool here. There is a place in ruby core
+ * (namely `class.c:singleton_class_of()`) where return value of this function
+ * is passed to RB_FL_SET_RAW().
+ */
static inline VALUE
RB_OBJ_FROZEN_RAW(VALUE obj)
{
@@ -466,6 +910,13 @@ RB_OBJ_FROZEN_RAW(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if an object is frozen.
+ *
+ * @param[in] obj Object in question.
+ * @retval true Yes it is.
+ * @retval false No it isn't.
+ */
static inline bool
RB_OBJ_FROZEN(VALUE obj)
{
@@ -478,21 +929,20 @@ RB_OBJ_FROZEN(VALUE obj)
}
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is an implenentation detail of RB_OBJ_FREEZE(). 3rd parties need not
+ * use this. Just always use RB_OBJ_FREEZE().
+ *
+ * @param[out] obj Object in question.
+ */
static inline void
RB_OBJ_FREEZE_RAW(VALUE obj)
{
RB_FL_SET_RAW(obj, RUBY_FL_FREEZE);
}
-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);
- }
- }
-}
+RUBY_SYMBOL_EXPORT_BEGIN
+void rb_obj_freeze_inline(VALUE obj);
+RUBY_SYMBOL_EXPORT_END
#endif /* RBIMPL_FL_TYPE_H */
diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h
index d94f8a3736..054e4b0f9c 100644
--- a/include/ruby/internal/gc.h
+++ b/include/ruby/internal/gc.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Registering values to the GC.
*/
#include "ruby/internal/dllexport.h"
@@ -26,10 +26,15 @@
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.
+ * Inform the garbage collector that the global or static variable pointed by
+ * `valptr` stores 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.
+ *
+ * Because this registration itself has a possibility to trigger a GC, this
+ * function must be called before any GC-able objects is assigned to the
+ * address pointed by `valptr`.
*/
void rb_gc_register_address(VALUE *valptr);
diff --git a/include/ruby/internal/glob.h b/include/ruby/internal/glob.h
index b78bb75b88..adbccbdc5e 100644
--- a/include/ruby/internal/glob.h
+++ b/include/ruby/internal/glob.h
@@ -17,18 +17,96 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Declares ::rb_glob().
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
-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);
+/**
+ * Type of a glob callback function. Called every time glob scans a path.
+ *
+ * @param[in] path The path in question.
+ * @param[in] arg The argument passed to rb_glob().
+ * @param[in] enc Encoding of the path.
+ * @retval -1 Not enough memory to do the operation.
+ * @retval 0 Operation successful.
+ * @retval otherwise Opaque exception state.
+ * @note You can use rb_protect() to generate the return value.
+ *
+ * @internal
+ *
+ * This is a wrong design. Type of `enc` should have been `rb_encoding*`
+ * instead of just `void*`. But we cannot change the API any longer.
+ *
+ * Though not a part of our public API, the "opaque exception state" is in fact
+ * an enum ruby_tag_type. You can see the potential "otherwise" values by
+ * looking at vm_core.h.
+ */
+typedef int ruby_glob_func(const char *path, VALUE arg, void *enc);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * The "glob" operator. Expands the given pattern against the actual local
+ * filesystem, then iterates over the expanded filenames by calling the
+ * callback function.
+ *
+ * @param[in] pattern A glob pattern.
+ * @param[in] func Identical to ruby_glob_func, except it can raise
+ * exceptions instead of returning opaque state.
+ * @param[in] arg Extra argument passed to func.
+ * @exception rb_eException Can propagate what `func` raises.
+ * @note The language accepted as the pattern is not a regular
+ * expression. It resembles shell's glob.
+ */
+void rb_glob(const char *pattern, void (*func)(const char *path, VALUE arg, void *enc), VALUE arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_glob(), except it returns opaque exception states instead of
+ * raising exceptions.
+ *
+ * @param[in] pattern A glob pattern.
+ * @param[in] flags No, you are not allowed to use this. Just pass 0.
+ * @param[in] func A callback function.
+ * @param[in] arg Extra argument passed to func.
+ * @return Return value of `func`.
+ *
+ * @internal
+ *
+ * This function is completely broken by design... Not only is there no sane
+ * way to pass flags, but there also is no sane way to know what a return value
+ * is meant to be.
+ *
+ * Though not a part of our public API, and @shyouhei thinks it's a failure not
+ * to be a public API, the flags can be `FNM_EXTGLOB`, `FNM_DOTMATCH` etc.
+ * Look at dir.c for the list.
+ *
+ * Though not a part of our public API, the return value is in fact an
+ * enum ruby_tag_type. You can see the potential values by looking at
+ * vm_core.h.
+ */
+int ruby_glob(const char *pattern, int flags, ruby_glob_func *func, VALUE arg);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to ruby_glob(), @shyouhei currently suspects. Historically you
+ * had to call this function instead of ruby_glob() if the pattern included
+ * "{x,y,...}" syntax. However since commit 0f63d961169989a7f6dcf7c0487fe29da,
+ * ruby_glob() also supports that syntax. It seems as of writing these two
+ * functions provide basically the same functionality in a different
+ * implementation. Is this analysis right? Correct me! :FIXME:
+ *
+ * @param[in] pattern A glob pattern.
+ * @param[in] flags No, you are not allowed to use this. Just pass 0.
+ * @param[in] func A callback function.
+ * @param[in] arg Extra argument passed to func.
+ * @return Return value of `func`.
+ */
+int ruby_brace_glob(const char *pattern, int flags, ruby_glob_func *func, VALUE arg);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h
index ddd731349e..5a414fc472 100644
--- a/include/ruby/internal/globals.h
+++ b/include/ruby/internal/globals.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Ruby-level global variables / constants, visible from C.
*/
#include "ruby/internal/attr/pure.h"
@@ -27,97 +27,147 @@
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
+/**
+ * @defgroup object Core objects and their operations
+ *
+ * @internal
+ *
+ * There are several questionable constants listed in this header file. They
+ * are intentionally left untouched for purely academic backwards compatibility
+ * concerns. But for instance do any one of 3rd party extension libraries even
+ * need to know that there is NameError::Message?
+ *
+ * @endinternal
+ *
+ * @{
+ */
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RUBY_INTEGER_UNIFICATION 1
-RUBY_EXTERN VALUE rb_mKernel;
-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;
+RUBY_EXTERN VALUE rb_mKernel; /**< `Kernel` module. */
+RUBY_EXTERN VALUE rb_mComparable; /**< `Comparable` module. */
+RUBY_EXTERN VALUE rb_mEnumerable; /**< `Enumerable` module. */
+RUBY_EXTERN VALUE rb_mErrno; /**< `Errno` module. */
+RUBY_EXTERN VALUE rb_mFileTest; /**< `FileTest` module. */
+RUBY_EXTERN VALUE rb_mGC; /**< `GC` module. */
+RUBY_EXTERN VALUE rb_mMath; /**< `Math` module. */
+RUBY_EXTERN VALUE rb_mProcess; /**< `Process` module. */
+RUBY_EXTERN VALUE rb_mWaitReadable; /**< `IO::WaitReadable` module. */
+RUBY_EXTERN VALUE rb_mWaitWritable; /**< `IO::WaitReadable` module. */
+
+RUBY_EXTERN VALUE rb_cBasicObject; /**< `BasicObject` class. */
+RUBY_EXTERN VALUE rb_cObject; /**< `Object` class. */
+RUBY_EXTERN VALUE rb_cArray; /**< `Array` class. */
+RUBY_EXTERN VALUE rb_cBinding; /**< `Binding` class. */
+RUBY_EXTERN VALUE rb_cClass; /**< `Class` class. */
+RUBY_EXTERN VALUE rb_cDir; /**< `Dir` class. */
+RUBY_EXTERN VALUE rb_cEncoding; /**< `Encoding` class. */
+RUBY_EXTERN VALUE rb_cEnumerator; /**< `Enumerator` class. */
+RUBY_EXTERN VALUE rb_cFalseClass; /**< `FalseClass` class. */
+RUBY_EXTERN VALUE rb_cFile; /**< `File` class. */
+RUBY_EXTERN VALUE rb_cComplex; /**< `Complex` class. */
+RUBY_EXTERN VALUE rb_cFloat; /**< `Float` class. */
+RUBY_EXTERN VALUE rb_cHash; /**< `Hash` class. */
+RUBY_EXTERN VALUE rb_cIO; /**< `IO` class. */
+RUBY_EXTERN VALUE rb_cInteger; /**< `Module` class. */
+RUBY_EXTERN VALUE rb_cMatch; /**< `MatchData` class. */
+RUBY_EXTERN VALUE rb_cMethod; /**< `Method` class. */
+RUBY_EXTERN VALUE rb_cModule; /**< `Module` class. */
+RUBY_EXTERN VALUE rb_cRefinement; /**< `Refinement` class. */
+RUBY_EXTERN VALUE rb_cNameErrorMesg; /**< `NameError::Message` class. */
+RUBY_EXTERN VALUE rb_cNilClass; /**< `NilClass` class. */
+RUBY_EXTERN VALUE rb_cNumeric; /**< `Numeric` class. */
+RUBY_EXTERN VALUE rb_cProc; /**< `Proc` class. */
+RUBY_EXTERN VALUE rb_cRandom; /**< `Random` class. */
+RUBY_EXTERN VALUE rb_cRange; /**< `Range` class. */
+RUBY_EXTERN VALUE rb_cRational; /**< `Rational` class. */
+RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */
+RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */
+RUBY_EXTERN VALUE rb_cString; /**< `String` class. */
+RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */
+RUBY_EXTERN VALUE rb_cSymbol; /**< `Sumbol` class. */
+RUBY_EXTERN VALUE rb_cThread; /**< `Thread` class. */
+RUBY_EXTERN VALUE rb_cTime; /**< `Time` class. */
+RUBY_EXTERN VALUE rb_cTrueClass; /**< `TrueClass` class. */
+RUBY_EXTERN VALUE rb_cUnboundMethod; /**< `UnboundMethod` class. */
+
+/**
+ * @}
+ * @addtogroup exception
+ * @{
+ */
+
+RUBY_EXTERN VALUE rb_eException; /**< Mother of all exceptions. */
+RUBY_EXTERN VALUE rb_eStandardError; /**< `StandardError` exception. */
+RUBY_EXTERN VALUE rb_eSystemExit; /**< `SystemExit` exception. */
+RUBY_EXTERN VALUE rb_eInterrupt; /**< `Interrupt` exception. */
+RUBY_EXTERN VALUE rb_eSignal; /**< `SignalException` exception. */
+RUBY_EXTERN VALUE rb_eFatal; /**< `fatal` exception. */
+RUBY_EXTERN VALUE rb_eArgError; /**< `ArgumentError` exception. */
+RUBY_EXTERN VALUE rb_eEOFError; /**< `EOFError` exception. */
+RUBY_EXTERN VALUE rb_eIndexError; /**< `IndexError` exception. */
+RUBY_EXTERN VALUE rb_eStopIteration; /**< `StopIteration` exception. */
+RUBY_EXTERN VALUE rb_eKeyError; /**< `KeyError` exception. */
+RUBY_EXTERN VALUE rb_eRangeError; /**< `RangeError` exception. */
+RUBY_EXTERN VALUE rb_eIOError; /**< `IOError` exception. */
+RUBY_EXTERN VALUE rb_eRuntimeError; /**< `RuntimeError` exception. */
+RUBY_EXTERN VALUE rb_eFrozenError; /**< `FrozenError` exception. */
+RUBY_EXTERN VALUE rb_eSecurityError; /**< `SecurityError` exception. */
+RUBY_EXTERN VALUE rb_eSystemCallError; /**< `SystemCallError` exception. */
+RUBY_EXTERN VALUE rb_eThreadError; /**< `ThreadError` exception. */
+RUBY_EXTERN VALUE rb_eTypeError; /**< `TypeError` exception. */
+RUBY_EXTERN VALUE rb_eZeroDivError; /**< `ZeroDivisionError` exception. */
+RUBY_EXTERN VALUE rb_eNotImpError; /**< `NotImplementedError` exception. */
+RUBY_EXTERN VALUE rb_eNoMemError; /**< `NoMemoryError` exception. */
+RUBY_EXTERN VALUE rb_eNoMethodError; /**< `NoMethodError` exception. */
+RUBY_EXTERN VALUE rb_eFloatDomainError; /**< `FloatDomainError` exception. */
+RUBY_EXTERN VALUE rb_eLocalJumpError; /**< `LocalJumpError` exception. */
+RUBY_EXTERN VALUE rb_eSysStackError; /**< `SystemStackError` exception. */
+RUBY_EXTERN VALUE rb_eRegexpError; /**< `RegexpError` exception. */
+RUBY_EXTERN VALUE rb_eEncodingError; /**< `EncodingError` exception. */
+RUBY_EXTERN VALUE rb_eEncCompatError; /**< `Encoding::CompatibilityError` exception. */
+RUBY_EXTERN VALUE rb_eNoMatchingPatternError; /**< `NoMatchingPatternError` exception. */
+RUBY_EXTERN VALUE rb_eNoMatchingPatternKeyError; /**< `NoMatchingPatternKeyError` exception. */
+
+RUBY_EXTERN VALUE rb_eScriptError; /**< `ScriptError` exception. */
+RUBY_EXTERN VALUE rb_eNameError; /**< `NameError` exception. */
+RUBY_EXTERN VALUE rb_eSyntaxError; /**< `SyntaxError` exception. */
+RUBY_EXTERN VALUE rb_eLoadError; /**< `LoadError` exception. */
+
+RUBY_EXTERN VALUE rb_eMathDomainError; /**< `Math::DomainError` exception. */
+
+/**
+ * @}
+ * @addtogroup object
+ * @{
+ */
+
+RUBY_EXTERN VALUE rb_stdin; /**< `STDIN` constant. */
+RUBY_EXTERN VALUE rb_stdout; /**< `STDOUT` constant. */
+RUBY_EXTERN VALUE rb_stderr; /**< `STDERR` constant. */
RBIMPL_ATTR_PURE()
+/**
+ * Object to class mapping function. Every object have its class. This
+ * function obtains that.
+ *
+ * @param[in] obj Target object to query.
+ * @return The class of the given object.
+ *
+ * @internal
+ *
+ * This function is a super-duper hot path. Optimised targeting modern C
+ * compilers and x86_64 architecture.
+ */
static inline VALUE
rb_class_of(VALUE obj)
{
@@ -150,8 +200,10 @@ rb_class_of(VALUE obj)
#endif
}
-#define CLASS_OF rb_class_of
+#define CLASS_OF rb_class_of /**< @old{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
index 5231d053d5..f068a65caf 100644
--- a/include/ruby/internal/has/attribute.h
+++ b/include/ruby/internal/has/attribute.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_ATTRIBUTE.
*/
#include "ruby/internal/config.h"
diff --git a/include/ruby/internal/has/builtin.h b/include/ruby/internal/has/builtin.h
index 01b1861eef..243ba2a34c 100644
--- a/include/ruby/internal/has/builtin.h
+++ b/include/ruby/internal/has/builtin.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_BUILTIN.
*/
#include "ruby/internal/config.h"
@@ -53,8 +53,10 @@
# define RBIMPL_HAS_BUILTIN___builtin_assume 0
# /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 for bswap16. */
# define RBIMPL_HAS_BUILTIN___builtin_bswap16 RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0)
+#ifndef __OpenBSD__
# 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)
+#endif
# 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)
@@ -76,10 +78,6 @@
# define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0)
# /* Note that "0, 0, 0" might be inaccurate. */
-#elif RBIMPL_COMPILER_IS(MSVC)
-# /* MSVC has UNREACHABLE, but that is not __builtin_unreachable. */
-# define RBIMPL_HAS_BUILTIN(_) 0
-
#else
# /* Take config.h definition when available */
# define RBIMPL_HAS_BUILTIN(_) ((RBIMPL_HAS_BUILTIN_ ## _)+0)
@@ -109,7 +107,7 @@
# define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0
# define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL
# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW
-# if defined(UNREACHABLE)
+# if defined(HAVE___BUILTIN_UNREACHABLE)
# define RBIMPL_HAS_BUILTIN___builtin_unreachable 1
# else
# define RBIMPL_HAS_BUILTIN___builtin_unreachable 0
diff --git a/include/ruby/internal/has/c_attribute.h b/include/ruby/internal/has/c_attribute.h
index b7eb94d22a..c5c48867bf 100644
--- a/include/ruby/internal/has/c_attribute.h
+++ b/include/ruby/internal/has/c_attribute.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_C_ATTRIBUTE.
*/
diff --git a/include/ruby/internal/has/cpp_attribute.h b/include/ruby/internal/has/cpp_attribute.h
index f42a4f5296..6a393b1a24 100644
--- a/include/ruby/internal/has/cpp_attribute.h
+++ b/include/ruby/internal/has/cpp_attribute.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_CPP_ATTRIBUTE.
*/
#include "ruby/internal/compiler_is.h"
diff --git a/include/ruby/internal/has/declspec_attribute.h b/include/ruby/internal/has/declspec_attribute.h
index f813da4f5e..1c526daf78 100644
--- a/include/ruby/internal/has/declspec_attribute.h
+++ b/include/ruby/internal/has/declspec_attribute.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_DECLSPEC_ATTRIBUTE.
*/
#include "ruby/internal/compiler_since.h"
diff --git a/include/ruby/internal/has/extension.h b/include/ruby/internal/has/extension.h
index 9ceb365ab9..da8c0d3cc2 100644
--- a/include/ruby/internal/has/extension.h
+++ b/include/ruby/internal/has/extension.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_EXTENSION.
*/
#include "ruby/internal/has/feature.h"
diff --git a/include/ruby/internal/has/feature.h b/include/ruby/internal/has/feature.h
index b827590c00..7be8d27314 100644
--- a/include/ruby/internal/has/feature.h
+++ b/include/ruby/internal/has/feature.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_FEATURE.
*/
diff --git a/include/ruby/internal/has/warning.h b/include/ruby/internal/has/warning.h
index 03975ecc2f..12d7db183b 100644
--- a/include/ruby/internal/has/warning.h
+++ b/include/ruby/internal/has/warning.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_HAS_WARNING.
*/
diff --git a/include/ruby/internal/intern/array.h b/include/ruby/internal/intern/array.h
index aafe0d1350..2262c6f0c6 100644
--- a/include/ruby/internal/intern/array.h
+++ b/include/ruby/internal/intern/array.h
@@ -17,61 +17,640 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cArray.
*/
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/noexcept.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* array.c */
-void rb_mem_clear(VALUE*, long);
-VALUE rb_assoc_new(VALUE, VALUE);
-VALUE rb_check_array_type(VALUE);
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NOALIAS()
+/**
+ * Fills the memory region with a series of ::RUBY_Qnil.
+ *
+ * @param[out] buf Buffer to squash.
+ * @param[in] len Number of objects of `buf`.
+ * @post `buf` is filled with ::RUBY_Qnil.
+ */
+void rb_mem_clear(VALUE *buf, long len)
+ RBIMPL_ATTR_NOEXCEPT(true)
+ ;
+
+/**
+ * Identical to rb_ary_new_from_values(), except it expects exactly two
+ * parameters.
+ *
+ * @param[in] car Arbitrary ruby object.
+ * @param[in] cdr Arbitrary ruby object.
+ * @return An allocated new array, of length 2, whose contents are the
+ * passed objects.
+ */
+VALUE rb_assoc_new(VALUE car, VALUE cdr);
+
+/**
+ * Try converting an object to its array representation using its `to_ary`
+ * method, if any. If there is no such thing, returns ::RUBY_Qnil.
+ *
+ * @param[in] obj Arbitrary ruby object to convert.
+ * @exception rb_eTypeError `obj.to_ary` returned something non-Array.
+ * @retval RUBY_Qnil No conversion from `obj` to array defined.
+ * @retval otherwise Converted array representation of `obj`.
+ * @see rb_io_check_io
+ * @see rb_check_string_type
+ * @see rb_check_hash_type
+ */
+VALUE rb_check_array_type(VALUE obj);
+
+/**
+ * Allocates a new, empty array.
+ *
+ * @return An allocated new array, whose length is 0.
+ */
VALUE rb_ary_new(void);
+
+/**
+ * Identical to rb_ary_new(), except it additionally specifies how many rooms
+ * of objects it should allocate. This way you can create an array whose
+ * capacity is bigger than the length of it. If you can say that an array
+ * grows to a specific amount, this could be effective than resizing an array
+ * over and over again and again.
+ *
+ * @param[in] capa Designed capacity of the generating array.
+ * @return An empty array, whose capacity is `capa`.
+ */
VALUE rb_ary_new_capa(long capa);
+
+/**
+ * Constructs an array from the passed objects.
+ *
+ * @param[in] n Number of passed objects.
+ * @param[in] ... Arbitrary ruby objects, filled into the returning array.
+ * @return An array of size `n`, whose contents are the passed objects.
+ */
VALUE rb_ary_new_from_args(long n, ...);
+
+/**
+ * Identical to rb_ary_new_from_args(), except how objects are passed.
+ *
+ * @param[in] n Number of objects of `elts`.
+ * @param[in] elts Arbitrary ruby objects, filled into the returning array.
+ * @return An array of size `n`, whose contents are the passed objects.
+ */
VALUE rb_ary_new_from_values(long n, const VALUE *elts);
-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);
+
+/**
+ * Allocates a hidden (no class) empty array.
+ *
+ * @param[in] capa Designed capacity of the array.
+ * @return A hidden, empty array.
+ * @see rb_obj_hide()
+ */
+VALUE rb_ary_hidden_new(long capa);
+#define rb_ary_tmp_new rb_ary_hidden_new
+
+/**
+ * Destroys the given array for no reason.
+ *
+ * @warning DO NOT USE IT.
+ * @warning Leave this task to our GC.
+ * @warning It was a wrong indea at the first place to let you know about it.
+ *
+ * @param[out] ary The array to be executed.
+ * @post The given array no longer exists.
+ * @note Maybe `Array#clear` could be what you want.
+ *
+ * @internal
+ *
+ * Should have moved this to `internal/array.h`.
+ */
+void rb_ary_free(VALUE ary);
+
+/**
+ * Declares that the array is about to be modified. This for instance let the
+ * array have a dedicated backend storage.
+ *
+ * @param[out] ary Array about to be modified.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @post Upon successful return the passed array is eligible to be
+ * modified.
+ */
+void rb_ary_modify(VALUE ary);
+
+/** @alias{rb_obj_freeze} */
+VALUE rb_ary_freeze(VALUE obj);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the passed two arrays share the same backend storage. A use-case
+ * for knowing such property is to take a snapshot of an array (using
+ * e.g. rb_ary_replace()), then check later if that snapshot still shares the
+ * storage with the original. Taking a snapshot is ultra-cheap. If nothing
+ * happens the impact shall be minimal. But if someone modifies the original,
+ * that entity shall pay the cost of copy-on-write. You can detect that using
+ * this API.
+ *
+ * @param[in] lhs Comparison LHS.
+ * @param[in] rhs Comparison RHS.
+ * @retval RUBY_Qtrue They share the same backend storage.
+ * @retval RUBY_Qfalse They are distinct.
+ * @pre Both arguments must be of ::RUBY_T_ARRAY.
+ */
+VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs);
+
+/**
+ * Queries element(s) of an array. This is complicated! Refer `Array#slice`
+ * document for the complete description of how it behaves.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Up to 2 objects.
+ * @param[in] ary Target array.
+ * @exception rb_eTypeError `argv` (or its part) includes non-Integer.
+ * @exception rb_eRangeError rb_cArithSeq is passed, and is OOB.
+ * @return An element (if requested), or an array of elements (if
+ * requested), or ::RUBY_Qnil (if index OOB).
+ *
+ * @internal
+ *
+ * ```rbs
+ * # "int" is ::Integer or `#to_int`, defined in builtin.rbs
+ *
+ * class ::Array[unchecked out T]
+ * def slice
+ * : (int i) -> T?
+ * | (int beg, int len) -> ::Array[T]?
+ * | (Range[int] r) -> ::Array[T]?
+ * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RagneError.
+ * end
+ * ```
+ */
+VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary);
+
+/**
+ * Obtains a part of the passed array.
+ *
+ * @param[in] ary Target array.
+ * @param[in] beg Subpart index.
+ * @param[in] len Requested length of returning array.
+ * @retval RUBY_Qnil Requested range out of bounds of `ary`.
+ * @retval otherwise An allocated new array whose contents are `ary`'s
+ * `beg` to `len`.
+ * @note Return array can be shorter than `len` when for instance
+ * `[0, 1, 2, 3]`'s 4th to 1,000,000,000th is requested.
+ */
+VALUE rb_ary_subseq(VALUE ary, long beg, long len);
+
+/**
+ * Destructively stores the passed value to the passed array's passed index.
+ * It also resizes the array's backend storage so that the requested index is
+ * not out of bounds.
+ *
+ * @param[out] ary Target array to modify.
+ * @param[in] key Where to store `val`.
+ * @param[in] val What to store at `key`.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @exception rb_eIndexError `key` is negative.
+ * @post `ary`'s `key`th position is occupied with `val`.
+ * @post Depending on `key` and previous length of `ary` this operation
+ * can also create a series of "hole" positions inside of the
+ * backend storage. They are filled with ::RUBY_Qnil.
+ */
+void rb_ary_store(VALUE ary, long key, VALUE val);
+
+/**
+ * Duplicates an array.
+ *
+ * @param[in] ary Target to duplicate.
+ * @return An allocated new array whose contents are identical to `ary`.
+ *
+ * @internal
+ *
+ * Not sure why this has to be something different from `ary_make_shared_copy`,
+ * which seems much efficient.
+ */
+VALUE rb_ary_dup(VALUE ary);
+
+/**
+ * I guess there is no use case of this function in extension libraries, but
+ * this is a routine identical to rb_ary_dup(). This makes the most sense when
+ * the passed array is formerly hidden by rb_obj_hide().
+ *
+ * @param[in] ary An array, possibly hidden.
+ * @return A duplicated new instance of ::rb_cArray.
+ */
VALUE rb_ary_resurrect(VALUE ary);
-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);
+
+/**
+ * Force converts an object to an array. It first tries its `#to_ary` method.
+ * Takes the result if any. Otherwise creates an array of size 1 whose sole
+ * element is the passed object.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @return An array representation of `obj`.
+ * @note Unlike rb_str_to_str() which is a variant of
+ * rb_check_string_type(), rb_ary_to_ary() is not a variant of
+ * rb_check_array_type().
+ */
+VALUE rb_ary_to_ary(VALUE obj);
+
+/**
+ * Converts an array into a human-readable string. Historically its behaviour
+ * changed over time. Currently it is identical to calling `inspect` method.
+ * This behaviour is from that of python (!!) circa 2006.
+ *
+ * @param[in] ary Array to inspect.
+ * @return Recursively inspected representation of `ary`.
+ * @see `[ruby-dev:29520]`
+ */
+VALUE rb_ary_to_s(VALUE ary);
+
+/**
+ * Destructively appends multiple elements at the end of the array.
+ *
+ * @param[out] ary Where to push `train`.
+ * @param[in] train Arbitrary ruby objects to push to `ary`.
+ * @param[in] len Number of objects of `train`.
+ * @exception rb_eIndexError `len` too large.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return The passed `ary`.
+ * @post `ary` has contents from `train` appended at its end.
+ */
+VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len);
+
+/**
+ * Special case of rb_ary_cat() that it adds only one element.
+ *
+ * @param[out] ary Where to push `elem`.
+ * @param[in] elem Arbitrary ruby object to push.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return The passed `ary`.
+ * @post `ary` has `elem` appended at its end.
+ */
+VALUE rb_ary_push(VALUE ary, VALUE elem);
+
+/**
+ * Destructively deletes an element from the end of the passed array and
+ * returns what was deleted.
+ *
+ * @param[out] ary Target array to modify.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return What was at the end of `ary`, or ::RUBY_Qnil if there is
+ * nothing to remove.
+ * @post `ary`'s last element, if any, is removed.
+ * @note There is no way to distinguish whether `ary` was an 1-element
+ * array whose content was ::RUBY_Qnil, or was empty.
+ */
+VALUE rb_ary_pop(VALUE ary);
+
+/**
+ * Destructively deletes an element from the beginning of the passed array and
+ * returns what was deleted. It can also be seen as a routine identical to
+ * rb_ary_pop(), except which side of the array to scrub.
+ *
+ * @param[out] ary Target array to modify.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return What was at the beginning of `ary`, or ::RUBY_Qnil if there is
+ * nothing to remove.
+ * @post `ary`'s first element, if any, is removed. As the name implies
+ * everything else remaining in `ary` gets moved towards `ary`'s
+ * beginning.
+ * @note There is no way to distinguish whether `ary` was an 1-element
+ * array whose content was ::RUBY_Qnil, or was empty.
+ */
+VALUE rb_ary_shift(VALUE ary);
+
+/**
+ * Destructively prepends the passed item at the beginning of the passed array.
+ * It can also be seen as a routine identical to rb_ary_push(), except which
+ * side of the array to modify.
+ *
+ * @param[out] ary Target array to modify.
+ * @param[in] elem Arbitrary ruby object to unshift.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return The passed `ary`.
+ * @post `ary` has `elem` prepended at this beginning.
+ */
+VALUE rb_ary_unshift(VALUE ary, VALUE elem);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries an element of an array. When passed offset is negative it counts
+ * backwards.
+ *
+ * @param[in] ary An array to look into.
+ * @param[in] off Offset (can be negative).
+ * @return ::RUBY_Qnil when `off` is out of bounds of `ary`. Otherwise
+ * what is stored at `off`-th position of `ary`.
+ * @note `ary`'s `off`-th element can happen to be ::RUBY_Qnil.
+ */
+VALUE rb_ary_entry(VALUE ary, long off);
+
+/**
+ * Iteratively yields each element of the passed array to the implicitly passed
+ * block if any. In case there is no block given, an enumerator that does the
+ * thing is generated instead.
+ *
+ * @param[in] ary Array to iterate over.
+ * @retval ary Passed block was evaluated.
+ * @retval otherwise An instance of ::rb_cEnumerator for `Array#each`.
+ */
+VALUE rb_ary_each(VALUE ary);
+
+/**
+ * Recursively stringises the elements of the passed array, flattens that
+ * result, then joins the sequence using the passed separator.
+ *
+ * @param[in] ary Target array to convert.
+ * @param[in] sep Separator. Either a string, or ::RUBY_Qnil
+ * if you want no separator.
+ * @exception rb_eArgError Infinite recursion in `ary`.
+ * @exception rb_eTypeError `sep` is not a string.
+ * @exception rb_eEncCompatError Strings do not agree with their encodings.
+ * @return An instance of ::rb_cString which concatenates stringised
+ * contents of `ary`, using `sep` as separator.
+ */
+VALUE rb_ary_join(VALUE ary, VALUE sep);
+
+/**
+ * _Destructively_ reverses the passed array in-place.
+ *
+ * @warning This is `Array#reverse!`, not `Array#reverse`.
+ * @param[out] ary Target array to modify.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return Passed `ary`.
+ * @post `ary` is reversed.
+ */
+VALUE rb_ary_reverse(VALUE ary);
+
+/**
+ * _Destructively_ rotates the passed array in-place to towards its end. The
+ * amount can be negative. Would rotate to the opposite direction then.
+ *
+ * @warning This is `Array#rotate!`, not `Array#rotate`.
+ * @param[out] ary Target array to modify.
+ * @param[in] rot Amount of rotation.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @retval RUBY_Qnil Not rotated.
+ * @retval ary Rotated.
+ * @post `ary` is rotated.
+ */
+VALUE rb_ary_rotate(VALUE ary, long rot);
+
+/**
+ * Creates a copy of the passed array, whose elements are sorted according to
+ * their `<=>` result.
+ *
+ * @param[in] ary Array to sort.
+ * @exception rb_eArgError Comparison not defined among elements.
+ * @exception rb_eRuntimeError Infinite recursion in `<=>`.
+ * @return A copy of `ary`, sorted.
+ * @note As of writing this function uses `qsort` as backend algorithm,
+ * which means the result is unstable (in terms of sort stability).
+ */
+VALUE rb_ary_sort(VALUE ary);
+
+/**
+ * Destructively sorts the passed array in-place, according to each elements'
+ * `<=>` result.
+ *
+ * @param[in] ary Target array to modify.
+ * @exception rb_eArgError Comparison not defined among elements.
+ * @exception rb_eRuntimeError Infinite recursion in `<=>`.
+ * @return Passed `ary`.
+ * @post `ary` is sorted.
+ * @note As of writing this function uses `qsort` as backend algorithm,
+ * which means the result is unstable (in terms of sort stability).
+ */
+VALUE rb_ary_sort_bang(VALUE ary);
+
+/**
+ * Destructively removes elements from the passed array, so that there would be
+ * no elements inside that satisfy `==` relationship with the passed object.
+ * Returns the last deleted element if any. But in case there was nothing to
+ * delete it gets complicated. It checks for the implicitly passed block. If
+ * there is a block the return value would be what the block evaluates to.
+ * Otherwise it resorts to ::RUBY_Qnil.
+ *
+ * @param[out] ary Target array to modify.
+ * @param[in] elem Template object to match against each element.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return What was deleted, or what was the block returned, or
+ * ::RUBY_Qnil (see above).
+ * @post All elements that have `==` relationship with `elem` are purged
+ * from `ary`. Elements shift their positions so that `ary` gets
+ * compact.
+ *
+ * @internal
+ *
+ * Internally there also is `rb_ary_delete_same`, which compares by identity.
+ */
+VALUE rb_ary_delete(VALUE ary, VALUE elem);
+
+/**
+ * Destructively removes an element which resides at the specific index of the
+ * passed array. Unlike rb_ary_stre() the index can be negative, which means
+ * the index counts backwards from the array's tail.
+ *
+ * @param[out] ary Target array to modify.
+ * @param[in] pos Position (can be negative).
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return What was deleted, or ::RUBY_Qnil in case of OOB.
+ * @post `ary`'s `pos`-th element is deleted if any.
+ * @note There is no way to distinguish whether `pos` is out of bound,
+ * or `pos` did exist but stored ::RUBY_Qnil as an ordinal value.
+ */
+VALUE rb_ary_delete_at(VALUE ary, long pos);
+
+/**
+ * Destructively removes everything form an array.
+ *
+ * @param[out] ary Target array to modify.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @return The passed `ary`.
+ * @post `ary` is an empty array.
+ */
+VALUE rb_ary_clear(VALUE ary);
+
+/**
+ * Creates a new array, concatenating the former to the latter.
+ *
+ * @param[in] lhs Source array #1.
+ * @param[in] rhs Source array #2.
+ * @exception rb_eIndexError Result array too big.
+ * @return A new array containing `rhs` concatenated to `lhs`.
+ * @note This operation doesn't commute. Don't get confused by the
+ * "plus" terminology. For historical reasons there are some
+ * noncommutative `+`s in Ruby. This is one of such things. There
+ * has been a long discussion around `+`s in programming languages.
+ *
+ * @internal
+ *
+ * rb_ary_concat() is not a destructive version of rb_ary_plus(). They raise
+ * different exceptions. Don't know why though.
+ */
+VALUE rb_ary_plus(VALUE lhs, VALUE rhs);
+
+/**
+ * Destructively appends the contents of latter into the end of former.
+ *
+ * @param[out] lhs Destination array.
+ * @param[in] rhs Source array.
+ * @exception rb_eFrozenError `lhs` is frozen.
+ * @exception rb_eIndexError Result array too big.
+ * @exception rb_eTypeError `rhs` doesn't respond to `#to_ary`.
+ * @return The passed `lhs`.
+ * @post `lhs` has contents of `rhs` appended to its end.
+ */
+VALUE rb_ary_concat(VALUE lhs, VALUE rhs);
+
+/**
+ * Looks up the passed key, assuming the passed array is an alist. An "alist"
+ * here is a list of "association"s, much like that of Emacs. Emacs has
+ * `assoc` function that behaves exactly the same as this one.
+ *
+ * ```ruby
+ * # This is an example of aliist.
+ * auto_mode_alist = [
+ * [ /\.[ch]\z/, :"c-mode" ],
+ * [ /\.[ch]pp\z/, :"c++-mode" ],
+ * [ /\.awk\z/, :"awk-mode" ],
+ * [ /\.cs\z/, :"csharp-mode" ],
+ * [ /\.go\z/, :"go-mode" ],
+ * [ /\.java\z/, :"java-mode" ],
+ * [ /\.pas\z/, :"pascal-mode" ],
+ * [ /\.rs\z/, :"rust-mode" ],
+ * [ /\.txt\z/, :"text-mode" ],
+ * ]
+ * ```
+ *
+ * This function scans the passed array looking for an element, which itself is
+ * an array, whose first element is the passed key. If no such element is
+ * found, returns ::RUBY_Qnil.
+ *
+ * Although this function expects the passed array be an array of arrays, it
+ * can happily accept non-array elements; it just ignores such things.
+ *
+ * @param[in] alist An array of arrays.
+ * @param[in] key Needle.
+ * @retval RUBY_Qnil Nothing was found.
+ * @retval otherwise An element in `alist` whose first element is in `==`
+ * relationship with `key`.
+ */
+VALUE rb_ary_assoc(VALUE alist, VALUE key);
+
+/**
+ * Identical to rb_ary_assoc(), except it scans the passed array from the
+ * opposite direction.
+ *
+ * @param[in] alist An array of arrays.
+ * @param[in] key Needle.
+ * @retval RUBY_Qnil Nothing was found.
+ * @retval otherwise An element in `alist` whose first element is in `==`
+ * relationship with `key`.
+ */
+VALUE rb_ary_rassoc(VALUE alist, VALUE key);
+
+/**
+ * Queries if the passed array has the passed entry.
+ *
+ * @param[in] ary Target array to scan.
+ * @param[in] elem Target array to find.
+ * @retval RUBY_Qfalse No element in `ary` is in `==` relationship with
+ * `elem`.
+ * @retval RUBY_Qtrue There is at least one element in `ary` which is in
+ * `==` relationship with `elem`.
+ *
+ * @internal
+ *
+ * This is the only function in the entire C API that is named using third
+ * person singular form of a verb (except #ISASCII etc., which are not our
+ * naming). The counterpart Ruby API of this function is `Array#include?`.
+ */
+VALUE rb_ary_includes(VALUE ary, VALUE elem);
+
+/**
+ * Recursively compares each elements of the two arrays one-by-one using `<=>`.
+ *
+ * @param[in] lhs Comparison LHS.
+ * @param[in] rhs Comparison RHS.
+ * @retval RUBY_Qnil `lhs` and `rhs` are not comparable.
+ * @retval -1 `lhs` is less than `rhs`.
+ * @retval 0 They are equal.
+ * @retval 1 `rhs` is less then `lhs`.
+ */
+VALUE rb_ary_cmp(VALUE lhs, VALUE rhs);
+
+/**
+ * Replaces the contents of the former object with the contents of the latter.
+ *
+ * @param[out] copy Destination object.
+ * @param[in] orig Source object.
+ * @exception rb_eTypeError `orig` has no implicit conversion to Array.
+ * @exception rb_eFrozenError `copy` is frozen.
+ * @return The passed `copy`.
+ * @post `copy`'s former components are abandoned. It now has the
+ * identical length and contents to `orig`.
+ */
VALUE rb_ary_replace(VALUE copy, VALUE orig);
-VALUE rb_get_values_at(VALUE, long, int, const VALUE*, VALUE(*)(VALUE,long));
+
+/**
+ * This _was_ a generalisation of `Array#values_at`, `Struct#values_at`, and
+ * `MatchData#values_at`. It begun its life as a refactoring effort. However
+ * as Ruby evolves over time, as of writing none of aforementioned methods
+ * share their implementations at all. This function is not deprecated; still
+ * works as it has been. But it is now kind of like a rudimentum.
+ *
+ * This function takes an object, which is a receiver, and a series of
+ * "indices", which are either integers, or ranges of integers. Calls the
+ * passed callback for each of those indices, along with the receiver. This
+ * callback is expected to do something like rb_ary_aref(), rb_struct_aref(),
+ * etc. In case of a range index rb_range_beg_len() expands the range.
+ * Finally return values of the callback are gathered as an array, then
+ * returned.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @param[in] olen "Length" of `obj`.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv List of "indices", described above.
+ * @param[in] func Callback function.
+ * @return A new instance of ::rb_cArray gathering `func`outputs.
+ *
+ * @internal
+ *
+ * `Array#values_at` no longer uses this function. There is no reason apart
+ * from historical ones to list this function here.
+ */
+VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func)(VALUE obj, long oidx));
+
+/**
+ * Expands or shrinks the passed array to the passed length.
+ *
+ * @param[out] ary An array to modify.
+ * @param[in] len Desired length of `ary`.
+ * @exception rb_eFrozenError `ary` is frozen.
+ * @exception rb_eIndexError `len` too long.
+ * @return The passed `ary`.
+ * @post `ary`'s length is `len`.
+ * @post Depending on `len` and previous length of `ary` this operation
+ * can also create a series of "hole" positions inside of the
+ * backend storage. They are filled with ::RUBY_Qnil.
+ *
+ * @internal
+ *
+ * `len` is signed. Intentional or...?
+ */
VALUE rb_ary_resize(VALUE ary, long len);
-#define rb_ary_new2 rb_ary_new_capa
-#define rb_ary_new3 rb_ary_new_from_args
-#define rb_ary_new4 rb_ary_new_from_values
+
+#define rb_ary_new2 rb_ary_new_capa /**< @old{rb_ary_new_capa} */
+#define rb_ary_new3 rb_ary_new_from_args /**< @old{rb_ary_new_from_args} */
+#define rb_ary_new4 rb_ary_new_from_values /**< @old{rb_ary_new_from_values} */
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/bignum.h b/include/ruby/internal/intern/bignum.h
index 1ac92e9c90..43d68018de 100644
--- a/include/ruby/internal/intern/bignum.h
+++ b/include/ruby/internal/intern/bignum.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to so-called rb_cBignum.
*/
#include "ruby/internal/config.h"
@@ -26,6 +26,7 @@
# include <stddef.h>
#endif
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/backward/2/long_long.h"
@@ -33,71 +34,811 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* bignum.c */
-VALUE rb_big_new(size_t, int);
+
+/**
+ * Allocates a bignum object.
+ *
+ * @param[in] len Length of the bignum's backend storage, in words.
+ * @param[in] sign Sign of the bignum.
+ * @return An allocated new bignum instance.
+ * @note This only allocates an object, doesn't fill its value in.
+ *
+ * @internal
+ *
+ * @shyouhei finds it hard to use from extension libraries. `len` is per
+ * `BDIGIT` but its definition is hidden.
+ */
+VALUE rb_big_new(size_t len, int sign);
+
+/**
+ * Queries if the passed bignum instance is a "bigzro". What is a bigzero?
+ * Well, bignums are for very big integers, but can also represent tiny ones
+ * like -1, 0, 1. Bigzero are instances of bignums whose values are zero.
+ * Knowing if a bignum is bigzero can be handy on occasions, like for instance
+ * detecting division by zero situation.
+ *
+ * @param[in] x A bignum.
+ * @retval 1 It is a bigzero.
+ * @retval 0 Otherwise.
+ */
int rb_bigzero_p(VALUE x);
-VALUE rb_big_clone(VALUE);
-void rb_big_2comp(VALUE);
-VALUE rb_big_norm(VALUE);
+
+/**
+ * Duplicates the given bignum.
+ *
+ * @param[in] num A bignum.
+ * @return An allocated bignum, who is equivalent to `num`.
+ */
+VALUE rb_big_clone(VALUE num);
+
+/**
+ * Destructively modify the passed bignum into 2's complement representation.
+ *
+ * @note By default bignums are in signed magnitude system.
+ *
+ * @param[out] num A bignum to modify.
+ */
+void rb_big_2comp(VALUE num);
+
+/**
+ * Normalises the passed bignum. It for instance returns a fixnum of the same
+ * value if fixnum can represent that number.
+ *
+ * @param[out] x Target bignum (can be destructively modified).
+ * @return An integer of the identical value (can be `x` itself).
+ */
+VALUE rb_big_norm(VALUE x);
+
+/**
+ * Destructively resizes the backend storage of the passed bignum.
+ *
+ * @param[out] big A bignum.
+ * @param[in] len New length of `big`'s backend, in words.
+ */
void rb_big_resize(VALUE big, size_t len);
-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);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Parses C's string to convert into a Ruby's integer. It understands prefixes
+ * (e.g. `0x`) and underscores.
+ *
+ * @param[in] str Stringised representation of the return value.
+ * @param[in] base Base of conversion. Must be `-36..36` inclusive,
+ * except `1`. `2..36` means the conversion is done
+ * according to it, with unmatched prefix understood
+ * as a part of the result. `-36..-2` means the
+ * conversion honours prefix when present, or use
+ * `-base` when absent. `0` is equivalent to `-10`.
+ * `-1` mandates a prefix. `1` is an error.
+ * @param[in] badcheck Whether to raise ::rb_eArgError on failure. If
+ * `0` is passed here this function can return
+ * `INT2FIX(0)` for parse errors.
+ * @exception rb_eArgError Failed to parse (and `badcheck` is truthy).
+ * @return An instance of ::rb_cInteger, which is a numeric interpretation
+ * of what is written in `str`.
+ *
+ * @internal
+ *
+ * Not sure if it intentionally accepts `base == -1` or is just buggy. Nobody
+ * practically uses negative bases these days.
+ */
+VALUE rb_cstr_to_inum(const char *str, int base, int badcheck);
+
+/**
+ * Identical to rb_cstr2inum(), except it takes Ruby's strings instead of C's.
+ *
+ * @param[in] str Stringised representation of the return
+ * value.
+ * @param[in] base Base of conversion. Must be `-36..36`
+ * inclusive, except `1`. `2..36` means the
+ * conversion is done according to it, with
+ * unmatched prefix understood as a part of the
+ * result. `-36..-2` means the conversion
+ * honours prefix when present, or use `-base`
+ * when absent. `0` is equivalent to `-10`.
+ * `-1` mandates a prefix. `1` is an error.
+ * @param[in] badcheck Whether to raise ::rb_eArgError on failure.
+ * If `0` is passed here this function can
+ * return `INT2FIX(0)` for parse errors.
+ * @exception rb_eArgError Failed to parse (and `badcheck` is truthy).
+ * @exception rb_eTypeError `str` is not a string.
+ * @exception rb_eEncCompatError `str` is not ASCII compatible.
+ * @return An instance of ::rb_cInteger, which is a numeric interpretation
+ * of what is written in `str`.
+ */
+VALUE rb_str_to_inum(VALUE str, int base, int badcheck);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_cstr_to_inum(), except the second argument controls the base
+ * and badcheck at once. It basically doesn't raise for parse errors, unless
+ * the base is zero.
+ *
+ * This is an older API. New codes might prefer rb_cstr_to_inum().
+ *
+ * @param[in] str Stringised representation of the return value.
+ * @param[in] base Base of conversion. Must be `-36..36` inclusive,
+ * except `1`. `2..36` means the conversion is done
+ * according to it, with unmatched prefix understood
+ * as a part of the result. `-36..-2` means the
+ * conversion honours prefix when present, or use
+ * `-base` when absent. `0` is equivalent to `-10`.
+ * `-1` mandates a prefix. `1` is an error.
+ * @exception rb_eArgError Failed to parse (and `base` is zero).
+ * @return An instance of ::rb_cInteger, which is a numeric interpretation
+ * of what is written in `str`.
+ */
+VALUE rb_cstr2inum(const char *str, int base);
+
+/**
+ * Identical to rb_str_to_inum(), except the second argument controls the base
+ * and badcheck at once. It can also be seen as a routine identical to
+ * rb_cstr2inum(), except it takes Ruby's strings instead of C's.
+ *
+ * This is an older API. New codes might prefer rb_cstr_to_inum().
+ *
+ * @param[in] str Stringised representation of the return
+ * value.
+ * @param[in] base Base of conversion. Must be `-36..36`
+ * inclusive, except `1`. `2..36` means the
+ * conversion is done according to it, with
+ * unmatched prefix understood as a part of the
+ * result. `-36..-2` means the conversion
+ * honours prefix when present, or use `-base`
+ * when absent. `0` is equivalent to `-10`.
+ * `-1` mandates a prefix. `1` is an error.
+ * @exception rb_eArgError Failed to parse (and `base` is zero).
+ * @exception rb_eTypeError `str` is not a string.
+ * @exception rb_eEncCompatError `str` is not ASCII compatible.
+ * @return An instance of ::rb_cInteger, which is a numeric interpretation
+ * of what is written in `str`.
+ */
+VALUE rb_str2inum(VALUE str, int base);
+
+/**
+ * Generates a place-value representation of the passed integer.
+ *
+ * @param[in] x An integer to stringify.
+ * @param[in] base `2` to `36` inclusive for each radix.
+ * @exception rb_eArgError `base` is out of range.
+ * @exception rb_eRangeError `x` is too big, cannot represent in string.
+ * @return An instance of ::rb_cString which represents `x`.
+ */
+VALUE rb_big2str(VALUE x, int base);
+
+/**
+ * Converts a bignum into C's `long`.
+ *
+ * @param[in] x A bignum.
+ * @exception rb_eRangeError `x` is out of range of `long`.
+ * @return The passed value converted into C's `long`.
+ */
+long rb_big2long(VALUE x);
+
+/** @alias{rb_big2long} */
#define rb_big2int(x) rb_big2long(x)
-unsigned long rb_big2ulong(VALUE);
+
+/**
+ * Converts a bignum into C's `unsigned long`.
+ *
+ * @param[in] x A bignum.
+ * @exception rb_eRangeError `x` is out of range of `unsigned long`.
+ * @return The passed value converted into C's `unsigned long`.
+ *
+ * @internal
+ *
+ * This function can generate a very large positive integer for a negative
+ * input. For instance applying Ruby's -4,611,686,018,427,387,905 to this
+ * function yields C's 13,835,058,055,282,163,711 on my machine. This is how
+ * it has been. Cannot change any longer.
+ */
+unsigned long rb_big2ulong(VALUE x);
+
+/** @alias{rb_big2long} */
#define rb_big2uint(x) rb_big2ulong(x)
+
#if HAVE_LONG_LONG
+/**
+ * Converts a bignum into C's `long long`.
+ *
+ * @param[in] x A bignum.
+ * @exception rb_eRangeError `x` is out of range of `long long`.
+ * @return The passed value converted into C's `long long`.
+ */
LONG_LONG rb_big2ll(VALUE);
+
+/**
+ * Converts a bignum into C's `unsigned long long`.
+ *
+ * @param[in] x A bignum.
+ * @exception rb_eRangeError `x` is out of range of `unsigned long long`.
+ * @return The passed value converted into C's `unsigned long long`.
+ *
+ * @internal
+ *
+ * This function can generate a very large positive integer for a negative
+ * input. For instance applying Ruby's -4,611,686,018,427,387,905 to this
+ * function yields C's 13,835,058,055,282,163,711 on my machine. This is how
+ * it has been. Cannot change any longer.
+ */
unsigned LONG_LONG rb_big2ull(VALUE);
+
#endif /* HAVE_LONG_LONG */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Converts a bignum into a series of its parts.
+ *
+ * @param[in] val An integer.
+ * @param[out] buf Return buffer.
+ * @param[in] num_longs Number of words of `buf`.
+ * @exception rb_eTypeError `val` doesn't respond to `#to_int`.
+ * @post `buf` is filled with `val`'s 2's complement representation, in
+ * the host CPU's native byte order, from least significant word
+ * towards the most significant one, for `num_longs` words.
+ * @note The "pack" terminology comes from `Array#pack`.
+ */
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Constructs a (possibly very big) bignum from a series of integers. `buf[0]`
+ * would be the return value's least significant word; `buf[num_longs-1]` would
+ * be that of most significant.
+ *
+ * @param[in] buf A series of integers.
+ * @param[in] num_longs Number of words of `buf`.
+ * @exception rb_eArgError Result would be too big.
+ * @return An instance of ::rb_cInteger which is an "unpack"-ed value of
+ * the parameters.
+ * @note The "unpack" terminology comes from `String#pack`.
+ */
VALUE rb_big_unpack(unsigned long *buf, long num_longs);
-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" */
+
+/* pack.c */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Encodes a Unicode codepoint into its UTF-8 representation.
+ *
+ * @param[out] buf Return buffer, must at least be 6 bytes width.
+ * @param[in] uv An Unicode codepoint.
+ * @exception rb_eRangeError `uv` is out of Unicode.
+ * @return Number of bytes written to `buf`
+ * @post `buf` holds a UTF-8 representation of `uv`.
+ */
+int rb_uv_to_utf8(char buf[6], unsigned long uv);
+
+/* bignum.c */
+
+/**
+ * Converts a C's `double` into a bignum.
+ *
+ * @param[in] d A value to convert.
+ * @exception rb_eFloatDomainError `d` is Inf/NaN.
+ * @return An instance of ::rb_cInteger whose value is approximately `d`.
+ *
+ * @internal
+ *
+ * @shyouhei is not sure if the result is guaranteed to be the nearest integer
+ * of `d`.
+ */
+VALUE rb_dbl2big(double d);
+
+/**
+ * Converts a bignum into C's `double`.
+ *
+ * @param[in] x A bignum.
+ * @return The passed value converted into C's `double`.
+ *
+ * @internal
+ *
+ * @shyouhei is not sure if the result is guaranteed to be `x`'s nearest value
+ * that a `double` can represent.
+ */
+double rb_big2dbl(VALUE x);
+
+/**
+ * Compares the passed two bignums.
+ *
+ * @param[in] lhs Comparison LHS.
+ * @param[in] rhs Comparison RHS.
+ * @retval -1 `rhs` is bigger than `lhs`.
+ * @retval 0 They are identical.
+ * @retval 1 `lhs` is bigger than `rhs`.
+ * @see rb_num_coerce_cmp()
+ */
+VALUE rb_big_cmp(VALUE lhs, VALUE rhs);
+
+/**
+ * Equality, in terms of `==`. This checks if the _value_ is the same, not the
+ * identity. For instance `1 == 1.0` must hold.
+ *
+ * @param[in] lhs Comparison LHS.
+ * @param[in] rhs Comparison RHS.
+ * @retval RUBY_Qtrue They are the same.
+ * @retval RUBY_Qfalse They are different.
+ */
+VALUE rb_big_eq(VALUE lhs, VALUE rhs);
+
+/**
+ * Equality, in terms of `eql?`. Unlike rb_big_eq() it does not convert
+ * ::rb_cFloat etc. This function returns ::RUBY_Qtrue if and only if both
+ * parameters are bignums, which represent the identical numerical value.
+ *
+ * @param[in] lhs Comparison LHS.
+ * @param[in] rhs Comparison RHS.
+ * @retval RUBY_Qtrue They are identical.
+ * @retval RUBY_Qfalse They are distinct.
+ */
+VALUE rb_big_eql(VALUE lhs, VALUE rhs);
+
+/**
+ * Performs addition of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x + y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
+VALUE rb_big_plus(VALUE x, VALUE y);
+
+/**
+ * Performs subtraction of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x - y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
+VALUE rb_big_minus(VALUE x, VALUE y);
+
+/**
+ * Performs multiplication of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x * y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
+VALUE rb_big_mul(VALUE x, VALUE y);
+
+/**
+ * Performs division of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x / y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
+VALUE rb_big_div(VALUE x, VALUE y);
+
+/**
+ * Performs "integer division". This is different from rb_big_div().
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x.div y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
+VALUE rb_big_idiv(VALUE x, VALUE y);
+
+/**
+ * Performs modulo of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x % y` evaluates to.
+ * @see rb_num_coerce_bin()
+ *
+ * @internal
+ *
+ * There also is `rb_big_remainder()` internally, which is different from this
+ * one.
+ */
+VALUE rb_big_modulo(VALUE x, VALUE y);
+
+/**
+ * Performs "divmod" operation. The operation in bignum's context is that it
+ * calculates rb_big_idiv() and rb_big_modulo() at once.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x.divmod y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
+VALUE rb_big_divmod(VALUE x, VALUE y);
+
+/**
+ * Raises `x` to the powerof `y`.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x ** y` evaluates to.
+ * @see rb_num_coerce_bin()
+ * @note This can return an instance of ::rb_cFloat, even when both `x`
+ * and `y` are bignums. Or an instance of ::rb_cRational, when for
+ * instance `y` is negative.
+ */
+VALUE rb_big_pow(VALUE x, VALUE y);
+
+/**
+ * Performs bitwise and of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x & y` evaluates to.
+ * @see rb_num_coerce_bit()
+ */
+VALUE rb_big_and(VALUE x, VALUE y);
+
+/**
+ * Performs bitwise or of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x | y` evaluates to.
+ * @see rb_num_coerce_bit()
+ */
+VALUE rb_big_or(VALUE x, VALUE y);
+
+/**
+ * Performs exclusive or of the passed two objects.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x ^ y` evaluates to.
+ * @see rb_num_coerce_bit()
+ */
+VALUE rb_big_xor(VALUE x, VALUE y);
+
+/**
+ * Performs shift left.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Shift amount.
+ * @exception rb_eTypeError `y` is not an integer.
+ * @exception rb_eArgError `y` is too big.
+ * @return `x` shifted left to `y` bits.
+ * @note `y` can be negative. Shifts right then.
+ */
+VALUE rb_big_lshift(VALUE x, VALUE y);
+
+/**
+ * Performs shift right.
+ *
+ * @param[in] x A bignum.
+ * @param[in] y Shift amount.
+ * @exception rb_eTypeError `y` is not an integer.
+ * @return `x` shifted right to `y` bits.
+ * @note This is arithmetic. Because bignums are not bitfields there is
+ * no shift right logical operator.
+ */
+VALUE rb_big_rshift(VALUE x, VALUE y);
+
+/**
+ * @name Flags for rb_integer_pack()/rb_integer_unpack()
+ * @{
+ */
+
+/** Stores/interprets the most significant word as the first word. */
#define INTEGER_PACK_MSWORD_FIRST 0x01
+
+/** Stores/interprets the least significant word as the first word. */
#define INTEGER_PACK_LSWORD_FIRST 0x02
+
+/**
+ * Stores/interprets the most significant byte in a word as the first byte in
+ * the word.
+ */
#define INTEGER_PACK_MSBYTE_FIRST 0x10
+
+/**
+ * Stores/interprets the least significant byte in a word as the first byte in
+ * the word.
+ */
#define INTEGER_PACK_LSBYTE_FIRST 0x20
+
+/**
+ * Means either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST,
+ * depending on the host processor's endian.
+ */
#define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40
+
+/** Uses 2's complement representation. */
#define INTEGER_PACK_2COMP 0x80
+
+/** Uses "generic" implementation (handy on test). */
#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400
-/* For rb_integer_unpack: */
+
+/**
+ * Always generates a bignum object even if the integer can be representable
+ * using fixnum scheme (unpack only)
+ */
#define INTEGER_PACK_FORCE_BIGNUM 0x100
+
+/**
+ * Interprets the input as a signed negative number (unpack only). If not
+ * specified returns a positive number.
+ */
#define INTEGER_PACK_NEGATIVE 0x200
-/* Combinations: */
+
+/** Little endian combination. */
#define INTEGER_PACK_LITTLE_ENDIAN \
(INTEGER_PACK_LSWORD_FIRST | \
INTEGER_PACK_LSBYTE_FIRST)
+
+/** Big endian combination */
#define INTEGER_PACK_BIG_ENDIAN \
(INTEGER_PACK_MSWORD_FIRST | \
INTEGER_PACK_MSBYTE_FIRST)
+
+/** @} */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Exports an integer into a buffer. This function fills the buffer specified
+ * by `words` and `numwords` as `val` in the format specified by `wordsize`,
+ * `nails` and `flags`.
+ *
+ * @param[in] val Integer or integer-like object which has
+ * `#to_int` method.
+ * @param[out] words Return buffer.
+ * @param[in] numwords Number of words of `words`.
+ * @param[in] wordsize Number of bytes per word.
+ * @param[in] nails Number of padding bits in a word. Most
+ * significant nails bits of each word are filled
+ * by zero.
+ * @param[in] flags Bitwise or of constants whose name starts
+ * "INTEGER_PACK_".
+ * @exception rb_eTypeError `val` doesn't respond to `#to_int`.
+ *
+ * Possible flags are:
+ *
+ * - #INTEGER_PACK_MSWORD_FIRST:
+ * Stores the most significant word as the first word.
+ *
+ * - #INTEGER_PACK_LSWORD_FIRST:
+ * Stores the least significant word as the first word.
+ *
+ * - #INTEGER_PACK_MSBYTE_FIRST:
+ * Stores the most significant byte in a word as the first byte in the
+ * word.
+ *
+ * - #INTEGER_PACK_LSBYTE_FIRST:
+ * Stores the least significant byte in a word as the first byte in the
+ * word.
+ *
+ * - #INTEGER_PACK_NATIVE_BYTE_ORDER:
+ * Either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST
+ * corresponding to the host's endian.
+ *
+ * - #INTEGER_PACK_2COMP:
+ * Uses 2's complement representation.
+ *
+ * - #INTEGER_PACK_LITTLE_ENDIAN: Shorthand of
+ * `INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST`.
+ *
+ * - #INTEGER_PACK_BIG_ENDIAN: Shorthand of
+ * `INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST`.
+ *
+ * - #INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION:
+ * Uses generic implementation (for test and debug).
+ *
+ * This function fills the buffer specified by `words` as `val`'s 2's
+ * complement representation if #INTEGER_PACK_2COMP is specified in `flags`.
+ * Otherwise it fills `words` as `abs(val)` and signedness is returned via the
+ * return value.
+ *
+ * @return The signedness and overflow condition. The overflow condition
+ * depends on #INTEGER_PACK_2COMP.
+ *
+ * When #INTEGER_PACK_2COMP is not specified:
+ *
+ * - `-2` :
+ * Negative overflow. `val <= -2**(numwords*(wordsize*CHAR_BIT-nails))`
+ *
+ * - `-1` :
+ * Negative without overflow.
+ * `-2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0`
+ *
+ * - `0` : zero. `val == 0`
+ *
+ * - `1` :
+ * Positive without overflow.
+ * `0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))`
+ *
+ * - `2` :
+ * Positive overflow. `2**(numwords*(wordsize*CHAR_BIT-nails)) <= val`
+ *
+ * When #INTEGER_PACK_2COMP is specified:
+ *
+ * - `-2` :
+ * Negative overflow. `val < -2**(numwords*(wordsize*CHAR_BIT-nails))`
+ *
+ * - `-1` :
+ * Negative without overflow.
+ * `-2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0`
+ *
+ * - `0` : zero. `val == 0`
+ *
+ * - `1` :
+ * Positive without overflow.
+ * `0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))`
+ *
+ * - `2` :
+ * Positive overflow. `2**(numwords*(wordsize*CHAR_BIT-nails)) <= val`
+ *
+ * The value, `-2**(numwords*(wordsize*CHAR_BIT-nails))`, is representable in
+ * 2's complement representation but not representable in absolute value. So
+ * `-1` is returned for the value if #INTEGER_PACK_2COMP is specified but
+ * returns `-2` if #INTEGER_PACK_2COMP is not specified.
+ *
+ * The least significant words are filled in the buffer when overflow occur.
+ */
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Import an integer from a buffer.
+ *
+ * @param[in] words Buffer to import.
+ * @param[in] numwords Number of words of `words`.
+ * @param[in] wordsize Number of bytes per word.
+ * @param[in] nails Number of padding bits in a word. Most
+ * significant nails bits of each word are ignored.
+ * @param[in] flags Bitwise or of constants whose name starts
+ * "INTEGER_PACK_".
+ * @exception rb_eArgError `numwords * wordsize` too big.
+ *
+ * Possible flags are:
+ *
+ * - #INTEGER_PACK_MSWORD_FIRST:
+ * Interpret the first word as the most significant word.
+ *
+ * - #INTEGER_PACK_LSWORD_FIRST:
+ * Interpret the first word as the least significant word.
+ *
+ * - #INTEGER_PACK_MSBYTE_FIRST:
+ * Interpret the first byte in a word as the most significant byte in the
+ * word.
+ *
+ * - #INTEGER_PACK_LSBYTE_FIRST:
+ * Interpret the first byte in a word as the least significant byte in
+ * the word.
+ *
+ * - #INTEGER_PACK_NATIVE_BYTE_ORDER:
+ * Either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST
+ * corresponding to the host's endian.
+ *
+ * - #INTEGER_PACK_2COMP:
+ * Uses 2's complement representation.
+ *
+ * - #INTEGER_PACK_LITTLE_ENDIAN: Shorthand of
+ * `INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST`
+ *
+ * - #INTEGER_PACK_BIG_ENDIAN: Shorthand of
+ * `INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST`
+ *
+ * - #INTEGER_PACK_FORCE_BIGNUM:
+ * Returns a bignum even if its value is representable as a fixnum.
+ *
+ * - #INTEGER_PACK_NEGATIVE:
+ * Returns a non-positive value. (Returns a non-negative value if not
+ * specified.)
+ *
+ * - #INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION:
+ * Uses generic implementation (for test and debug).
+ *
+ * @return An instance of ::rb_cInteger whose value is the interpreted
+ * `words`. The range of the result value depends on
+ * #INTEGER_PACK_2COMP and #INTEGER_PACK_NEGATIVE.
+ *
+ * When #INTEGER_PACK_2COMP is not set:
+ *
+ * - `0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails))` if
+ * `!INTEGER_PACK_NEGATIVE`
+ *
+ * - `-2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0` if
+ * `INTEGER_PACK_NEGATIVE`
+ *
+ * When #INTEGER_PACK_2COMP is set:
+ *
+ * - `-2**(numwords*(wordsize*CHAR_BIT-nails)-1)` `<= val <=`
+ * `2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1` if
+ * `!INTEGER_PACK_NEGATIVE`
+ *
+ * - `-2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1` if
+ * `INTEGER_PACK_NEGATIVE`
+ *
+ * Passing #INTEGER_PACK_2COMP without #INTEGER_PACK_NEGATIVE means sign
+ * extension. #INTEGER_PACK_2COMP with #INTEGER_PACK_NEGATIVE means assuming
+ * the higher bits are `1`.
+ *
+ * Note that this function returns 0 when `numwords` is zero and
+ * #INTEGER_PACK_2COMP is set but #INTEGER_PACK_NEGATIVE is not set.
+ */
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
+
+/**
+ * Calculates the number of bytes needed to represent the absolute value of the
+ * passed integer.
+ *
+ * @param[in] val Integer or integer-like object which has
+ * `#to_int` method.
+ * @param[out] nlz_bits_ret Number of leading zero bits in the most
+ * significant byte is returned if not `NULL`.
+ * @exception rb_eTypeError `val` doesn't respond to `#to_int`.
+ * @return `((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)`, where
+ * val_numbits is the number of bits of `abs(val)`.
+ * @post If `nlz_bits_ret` is not `NULL`,
+ * `(return_value * CHAR_BIT - val_numbits)` is stored in
+ * `*nlz_bits_ret`. In this case,
+ * `0 <= *nlz_bits_ret < CHAR_BIT`.
+ *
+ * This function should not overflow.
+ */
size_t rb_absint_size(VALUE val, int *nlz_bits_ret);
+
+/**
+ * Calculates the number of words needed represent the absolute value of the
+ * passed integer. Unlike rb_absint_size() this function can overflow. It
+ * returns `(size_t)-1` then.
+ *
+ * @param[in] val Integer or integer-like object which has
+ * `#to_int` method.
+ * @param[in] word_numbits Number of bits per word.
+ * @param[out] nlz_bits_ret Number of leading zero bits in the most
+ * significant word is returned if not `NULL`.
+ * @exception rb_eTypeError `val` doesn't respond to `#to_int`.
+ * @retval (size_t)-1 Overflowed.
+ * @retval otherwise
+ `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`,
+ * where val_numbits is the number of bits of `abs(val)`.
+ * @post If `nlz_bits_ret` is not `NULL` and there is no overflow,
+ * `(return_value * word_numbits - val_numbits)` is stored in
+ * `*nlz_bits_ret`. In this case,
+ * `0 <= *nlz_bits_ret < word_numbits.`
+ *
+ */
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret);
+
+/**
+ * Tests `abs(val)` consists only of a bit or not.
+ *
+ * @param[in] val Integer or integer-like object which has
+ * `#to_int` method.
+ * @exception rb_eTypeError `val` doesn't respond to `#to_int`.
+ * @retval 1 `abs(val) == 1 << n` for some `n >= 0`.
+ * @retval 0 Otherwise.
+ *
+ * rb_absint_singlebit_p() can be used to determine required buffer size for
+ * rb_integer_pack() used with #INTEGER_PACK_2COMP (two's complement).
+ *
+ * Following example calculates number of bits required to represent val in
+ * two's complement number, without sign bit.
+ *
+ * ```CXX
+ * size_t size;
+ * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
+ * size = rb_absint_numwords(val, 1, NULL)
+ * if (size == (size_t)-1) ...overflow...
+ * if (neg && rb_absint_singlebit_p(val))
+ * size--;
+ * ```
+ *
+ * Following example calculates number of bytes required to represent val in
+ * two's complement number, with sign bit.
+ *
+ * ```CXX
+ * size_t size;
+ * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
+ * int nlz_bits;
+ * size = rb_absint_size(val, &nlz_bits);
+ * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val)))
+ * size++;
+ * ```
+ */
int rb_absint_singlebit_p(VALUE val);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/class.h b/include/ruby/internal/intern/class.h
index d3be80d283..0fb2d001bc 100644
--- a/include/ruby/internal/intern/class.h
+++ b/include/ruby/internal/intern/class.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cClass/::rb_cModule.
*/
#include "ruby/internal/dllexport.h"
@@ -27,30 +27,367 @@
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);
+
+/**
+ * Creates a new, anonymous class.
+ *
+ * @param[in] super What would become a parent class.
+ * @exception rb_eTypeError `super` is not something inheritable.
+ * @return An anonymous class that inherits `super`.
+ */
+VALUE rb_class_new(VALUE super);
+
+/**
+ * The comment that comes with this function says `:nodoc:`. Not sure what
+ * that means though.
+ *
+ * @param[out] clone Destination object.
+ * @param[in] orig Source object.
+ * @exception rb_eTypeError Cannot copy `orig`.
+ * @return The passed `clone`.
+ */
+VALUE rb_mod_init_copy(VALUE clone, VALUE orig);
+
+/**
+ * Asserts that the given class can derive a child class. A class might or
+ * might not be able to do so; for instance a singleton class cannot.
+ *
+ * @param[in] super Possible super class.
+ * @exception rb_eTypeError No it cannot.
+ * @post Upon successful return `super` can derive.
+ */
+void rb_check_inheritable(VALUE super);
+
+/**
+ * This is a very badly designed API that creates an anonymous class.
+ *
+ * @param[in] id Discarded for no reason (why...).
+ * @param[in] super What would become a parent class. 0 means
+ * ::rb_cObject.
+ * @exception rb_eTypeError `super` is not something inheritable.
+ * @return An anonymous class that inherits `super`.
+ * @warning You must explicitly name the return value.
+ */
+VALUE rb_define_class_id(ID id, VALUE super);
+
+/**
+ * Identical to rb_define_class_under(), except it takes the name in ::ID
+ * instead of C's string.
+ *
+ * @param[out] outer A class which contains the new class.
+ * @param[in] id Name of the new class
+ * @param[in] super A class from which the new class will derive.
+ * 0 means ::rb_cObject.
+ * @exception rb_eTypeError The constant name `id` is already taken but the
+ * constant is not a class.
+ * @exception rb_eTypeError The class is already defined but the class can
+ * not be reopened because its superclass is not
+ * `super`.
+ * @exception rb_eArgError `super` is NULL.
+ * @return The created class.
+ * @post `outer::id` refers the returned class.
+ * @note If a class named `id` is already defined and its superclass is
+ * `super`, the function just returns the defined class.
+ * @note The compaction GC does not move classes returned by this
+ * function.
+ */
+VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super);
+
+/**
+ * Creates a new, anonymous module.
+ *
+ * @return An anonymous module.
+ */
VALUE rb_module_new(void);
-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);
+
+
+/**
+ * Creates a new, anonymous refinement.
+ *
+ * @return An anonymous refinement.
+ */
+VALUE rb_refinement_new(void);
+
+/**
+ * This is a very badly designed API that creates an anonymous module.
+ *
+ * @param[in] id Discarded for no reason (why...).
+ * @return An anonymous module.
+ * @warning You must explicitly name the return value.
+ */
+VALUE rb_define_module_id(ID id);
+
+/**
+ * Identical to rb_define_module_under(), except it takes the name in ::ID
+ * instead of C's string.
+ *
+ * @param[out] outer A class which contains the new module.
+ * @param[in] id Name of the new module
+ * @exception rb_eTypeError The constant name `id` is already taken but the
+ * constant is not a module.
+ * @return The created module.
+ * @post `outer::id` refers the returned module.
+ * @note The compaction GC does not move classes returned by this
+ * function.
+ */
+VALUE rb_define_module_id_under(VALUE outer, ID id);
+
+/**
+ * Queries the list of included modules. It can also be seen as a routine to
+ * first call rb_mod_ancestors(), then rejects non-modules from the return
+ * value.
+ *
+ * @param[in] mod Class or Module.
+ * @return An array of modules that are either included or prepended in any
+ * of `mod`'s ancestry tree (including itself).
+ */
+VALUE rb_mod_included_modules(VALUE mod);
+
+/**
+ * Queries if the passed module is included by the module. It can also be seen
+ * as a routine to first call rb_mod_included_modules(), then see if the return
+ * value contains the passed module.
+ *
+ * @param[in] child A Module.
+ * @param[in] parent Another Module.
+ * @exception rb_eTypeError `child` is not an instance of ::rb_cModule.
+ * @retval RUBY_Qtrue `parent` is either included or prepended in any
+ * of `child`'s ancestry tree (including itself).
+ * @return RUBY_Qfalse Otherwise.
+ */
+VALUE rb_mod_include_p(VALUE child, VALUE parent);
+
+/**
+ * Queries the module's ancestors. This routine gathers classes and modules
+ * that the passed module either inherits, includes, or prepends, then
+ * recursively applies that routine again and again to the collected entries
+ * until the list doesn't grow up.
+ *
+ * @param[in] mod A module or a class.
+ * @return An array of classes or modules that `mod` possibly recursively
+ * inherits, includes, or prepends.
+ *
+ * @internal
+ *
+ * Above description is written in a recursive language but in practice it
+ * computes the return value iteratively.
+ */
+VALUE rb_mod_ancestors(VALUE mod);
+
+/**
+ * Queries the class's descendants. This routine gathers classes that are
+ * subclasses of the given class (or subclasses of those subclasses, etc.),
+ * returning an array of classes that have the given class as an ancestor.
+ * The returned array does not include the given class or singleton classes.
+ *
+ * @param[in] klass A class.
+ * @return An array of classes where `klass` is an ancestor.
+ *
+ * @internal
+ */
+VALUE rb_class_descendants(VALUE klass);
+
+/**
+ * Queries the class's direct descendants. This routine gathers classes that are
+ * direct subclasses of the given class,
+ * returning an array of classes that have the given class as a superclass.
+ * The returned array does not include singleton classes.
+ *
+ * @param[in] klass A class.
+ * @return An array of classes where `klass` is the `superclass`.
+ *
+ * @internal
+ */
+VALUE rb_class_subclasses(VALUE klass);
+
+
+/**
+ * Returns the attached object for a singleton class.
+ * If the given class is not a singleton class, raises a TypeError.
+ *
+ * @param[in] klass A class.
+ * @return The object which has the singleton class `klass`.
+ *
+ * @internal
+ */
+VALUE rb_class_attached_object(VALUE klass);
+
+/**
+ * Generates an array of symbols, which are the list of method names defined in
+ * the passed class.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Array of at most one object, which controls (if
+ * any) whether the return array includes the names
+ * of methods defined in ancestors or not.
+ * @param[in] mod A module or a class.
+ * @exception rb_eArgError `argc` out of range.
+ * @return An array of symbols collecting names of instance methods that
+ * are not private, defined at `mod`.
+ */
+VALUE rb_class_instance_methods(int argc, const VALUE *argv, VALUE mod);
+
+/**
+ * Identical to rb_class_instance_methods(), except it returns names of methods
+ * that are public only.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Array of at most one object, which controls (if
+ * any) whether the return array includes the names
+ * of methods defined in ancestors or not.
+ * @param[in] mod A module or a class.
+ * @exception rb_eArgError `argc` out of range.
+ * @return An array of symbols collecting names of instance methods that
+ * are public, defined at `mod`.
+ */
+VALUE rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod);
+
+/**
+ * Identical to rb_class_instance_methods(), except it returns names of methods
+ * that are protected only.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Array of at most one object, which controls (if
+ * any) whether the return array includes the names
+ * of methods defined in ancestors or not.
+ * @param[in] mod A module or a class.
+ * @exception rb_eArgError `argc` out of range.
+ * @return An array of symbols collecting names of instance methods that
+ * are protected, defined at `mod`.
+ */
+VALUE rb_class_protected_instance_methods(int argc, const VALUE *argv, VALUE mod);
+
+/**
+ * Identical to rb_class_instance_methods(), except it returns names of methods
+ * that are private only.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Array of at most one object, which controls (if
+ * any) whether the return array includes the names
+ * of methods defined in ancestors or not.
+ * @param[in] mod A module or a class.
+ * @exception rb_eArgError `argc` out of range.
+ * @return An array of symbols collecting names of instance methods that
+ * are protected, defined at `mod`.
+ */
+VALUE rb_class_private_instance_methods(int argc, const VALUE *argv, VALUE mod);
+
+/**
+ * Identical to rb_class_instance_methods(), except it returns names of
+ * singleton methods instead of instance methods.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Array of at most one object, which controls (if
+ * any) whether the return array includes the names
+ * of methods defined in ancestors or not.
+ * @param[in] obj Arbitrary ruby object.
+ * @exception rb_eArgError `argc` out of range.
+ * @return An array of symbols collecting names of instance methods that
+ * are not private, defined at the singleton class of `obj`.
+ */
+VALUE rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj);
+
+/**
+ * Identical to rb_define_method(), except it takes the name of the method in
+ * ::ID instead of C's string.
+ *
+ * @param[out] klass A module or a class.
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_method_id
+ */
+void rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int arity);
+
+/* vm_method.c */
+
+/**
+ * Inserts a method entry that hides previous method definition of the given
+ * name. This is not a deletion of a method. Method of the same name defined
+ * in a parent class is kept invisible in this way.
+ *
+ * @param[out] mod The module to insert an undef.
+ * @param[in] mid Name of the undef.
+ * @exception rb_eTypeError `klass` is a non-module.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @exception rb_eNameError No such method named `klass#name`.
+ * @post `klass#name` is undefined.
+ * @see rb_undef_method
+ *
+ * @internal
+ *
+ * @shyouhei doesn't understand why this is not the ::ID -taking variant of
+ * rb_undef_method(), given rb_remove_method() has its ::ID -taking counterpart
+ * named rb_remove_method_id().
+ */
+void rb_undef(VALUE mod, ID mid);
+
+/* class.c */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_define_method(), except it defines a protected method.
+ *
+ * @param[out] klass A module or a class.
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method
+ */
+void rb_define_protected_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_define_method(), except it defines a private method.
+ *
+ * @param[out] klass A module or a class.
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method
+ */
+void rb_define_private_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_define_method(), except it defines a singleton method.
+ *
+ * @param[out] obj Arbitrary ruby object.
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_singleton_method
+ */
+void rb_define_singleton_method(VALUE obj, const char *mid, VALUE(*func)(ANYARGS), int arity);
+
+/**
+ * Finds or creates the singleton class of the passed object.
+ *
+ * @param[out] obj Arbitrary ruby object.
+ * @exception rb_eTypeError `obj` cannot have its singleton class.
+ * @return A (possibly newly allocated) instance of ::rb_cClass.
+ * @post `obj` has its singleton class, which is the return value.
+ * @post In case `obj` is a class, the returned singleton class also has
+ * its own singleton class in order to keep consistency of the
+ * inheritance structure of metaclasses.
+ * @note A new singleton class will be created if `obj` did not have
+ * one.
+ * @note The singleton classes for ::RUBY_Qnil, ::RUBY_Qtrue, and
+ * ::RUBY_Qfalse are ::rb_cNilClass, ::rb_cTrueClass, and
+ * ::rb_cFalseClass respectively.
+ *
+ * @internal
+ *
+ * You can _create_ a singleton class of a frozen object. Intentional or ...?
+ *
+ * Nowadays there are wider range of objects who cannot have singleton classes
+ * than before. For instance some string instances cannot for some reason.
+ */
+VALUE rb_singleton_class(VALUE obj);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/compar.h b/include/ruby/internal/intern/compar.h
index d226ca37b1..dc3b377b01 100644
--- a/include/ruby/internal/intern/compar.h
+++ b/include/ruby/internal/intern/compar.h
@@ -17,17 +17,45 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_mComparable.
*/
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/* bignum.c */
+
+/**
+ * Canonicalises the passed `val`, which is the return value of `a <=> b`, into
+ * C's `{-1, 0, 1}`. This can be handy when you implement a callback function
+ * to pass to `qsort(3)` etc.
+ *
+ * @param[in] val Return value of a space ship operator.
+ * @param[in] a Comparison LHS.
+ * @param[in] b Comparison RHS.
+ * @exception rb_eArgError `a` and `b` are not comparable each other.
+ * @retval -1 `val` is less than zero.
+ * @retval 0 `val` is equal to zero.
+ * @retval 1 `val` is greater than zero.
+ */
+int rb_cmpint(VALUE val, VALUE a, VALUE b);
+
/* compar.c */
-int rb_cmpint(VALUE, VALUE, VALUE);
-NORETURN(void rb_cmperr(VALUE, VALUE));
+
+RBIMPL_ATTR_COLD()
+RBIMPL_ATTR_NORETURN()
+/**
+ * Raises "comparison failed" error.
+ *
+ * @param[in] a Comparison LHS.
+ * @param[in] b Comparison RHS.
+ * @exception rb_eArgError `a` and `b` are not comparable each other.
+ */
+void rb_cmperr(VALUE a, VALUE b);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/complex.h b/include/ruby/internal/intern/complex.h
index 70343221f6..e111bd8ced 100644
--- a/include/ruby/internal/intern/complex.h
+++ b/include/ruby/internal/intern/complex.h
@@ -17,9 +17,11 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cComplex.
*/
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */
@@ -27,32 +29,223 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* complex.c */
-VALUE rb_complex_raw(VALUE, VALUE);
+
+/**
+ * Identical to rb_complex_new(), except it assumes both arguments are not
+ * instances of ::rb_cComplex. It is thus dangerous for extension libraries.
+ *
+ * @param[in] real Real part, in any numeric except Complex.
+ * @param[in] imag Imaginary part, in any numeric except Complex.
+ * @return An instance of ::rb_cComplex whose value is `real + (imag)i`.
+ */
+VALUE rb_complex_raw(VALUE real, VALUE imag);
+
+/**
+ * Shorthand of `x+0i`. It practically converts `x` into a Complex of the
+ * identical value.
+ *
+ * @param[in] x Any numeric except Complex.
+ * @return An instance of ::rb_cComplex, whose value is `x + 0i`.
+ */
#define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0))
+
+/** @alias{rb_complex_raw} */
#define rb_complex_raw2(x,y) rb_complex_raw((x), (y))
-VALUE rb_complex_new(VALUE, VALUE);
+
+/**
+ * Constructs a Complex, by first multiplying the imaginary part with `1i` then
+ * adds it to the real part. This definition doesn't need both arguments be
+ * real numbers. It can happily combine two instances of ::rb_cComplex (with
+ * rotating the latter one).
+ *
+ * @param[in] real An instance of ::rb_cNumeric.
+ * @param[in] imag Another instance of ::rb_cNumeric.
+ * @return An instance of ::rb_cComplex whose value is `imag * 1i + real`.
+ */
+VALUE rb_complex_new(VALUE real, VALUE imag);
+
+/**
+ * Shorthand of `x+0i`. It practically converts `x` into a Complex of the
+ * identical value.
+ *
+ * @param[in] x Any numeric value.
+ * @return An instance of ::rb_cComplex, whose value is `x + 0i`.
+ */
#define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0))
+
+/** @alias{rb_complex_new} */
#define rb_complex_new2(x,y) rb_complex_new((x), (y))
+
+/**
+ * Constructs a Complex using polar representations. Unlike rb_complex_new()
+ * it makes no sense to pass non-real instances to this function.
+ *
+ * @param[in] abs Magnitude, in any numeric except Complex.
+ * @param[in] arg Angle, in radians, in any numeric except Complex.
+ * @return An instance of ::rb_cComplex which denotes the given polar
+ * coordinates.
+ */
VALUE rb_complex_new_polar(VALUE abs, VALUE arg);
-DEPRECATED_BY(rb_complex_new_polar, VALUE rb_complex_polar(VALUE abs, VALUE arg));
+
+RBIMPL_ATTR_DEPRECATED(("by: rb_complex_new_polar"))
+/** @old{rb_complex_new_polar} */
+VALUE rb_complex_polar(VALUE abs, VALUE arg);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries the real part of the passed Complex.
+ *
+ * @param[in] z An instance of ::rb_cComplex.
+ * @return Its real part, which is an instance of ::rb_cNumeric.
+ */
VALUE rb_complex_real(VALUE z);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries the imaginary part of the passed Complex.
+ *
+ * @param[in] z An instance of ::rb_cComplex.
+ * @return Its imaginary part, which is an instance of ::rb_cNumeric.
+ */
VALUE rb_complex_imag(VALUE z);
+
+/**
+ * Performs addition of the passed two objects.
+ *
+ * @param[in] x An instance of ::rb_cComplex.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x + y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
VALUE rb_complex_plus(VALUE x, VALUE y);
+
+/**
+ * Performs subtraction of the passed two objects.
+ *
+ * @param[in] x An instance of ::rb_cComplex.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x - y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
VALUE rb_complex_minus(VALUE x, VALUE y);
+
+/**
+ * Performs multiplication of the passed two objects.
+ *
+ * @param[in] x An instance of ::rb_cComplex.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x * y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
VALUE rb_complex_mul(VALUE x, VALUE y);
+
+/**
+ * Performs division of the passed two objects.
+ *
+ * @param[in] x An instance of ::rb_cComplex.
+ * @param[in] y Arbitrary ruby object.
+ * @return What `x / y` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
VALUE rb_complex_div(VALUE x, VALUE y);
+
+/**
+ * Performs negation of the passed object.
+ *
+ * @param[in] z An instance of ::rb_cComplex.
+ * @return What `-z` evaluates to.
+ */
VALUE rb_complex_uminus(VALUE z);
+
+/**
+ * Performs complex conjugation of the passed object.
+ *
+ * @param[in] z An instance of ::rb_cComplex.
+ * @return Its complex conjugate, in ::rb_cComplex.
+ */
VALUE rb_complex_conjugate(VALUE z);
+
+/**
+ * Queries the absolute (or the magnitude) of the passed object.
+ *
+ * @param[in] z An instance of ::rb_cComplex.
+ * @return Its magnitude, in ::rb_cFloat.
+ */
VALUE rb_complex_abs(VALUE z);
+
+/**
+ * Queries the argument (or the angle) of the passed object.
+ *
+ * @param[in] z An instance of ::rb_cComplex.
+ * @return Its magnitude, in ::rb_cFloat.
+ */
VALUE rb_complex_arg(VALUE z);
+
+/**
+ * Performs exponentiation of the passed two objects.
+ *
+ * @param[in] base An instance of ::rb_cComplex.
+ * @param[in] exp Arbitrary ruby object.
+ * @return What `base ** exp` evaluates to.
+ * @see rb_num_coerce_bin()
+ */
VALUE rb_complex_pow(VALUE base, VALUE exp);
+
+/**
+ * Identical to rb_complex_new(), except it takes the arguments as C's double
+ * instead of Ruby's object.
+ *
+ * @param[in] real Real part.
+ * @param[in] imag Imaginary part.
+ * @return An instance of ::rb_cComplex whose value is `real + (imag)i`.
+ */
VALUE rb_dbl_complex_new(double real, double imag);
+
+/** @alias{rb_complex_plus} */
#define rb_complex_add rb_complex_plus
+
+/** @alias{rb_complex_minus} */
#define rb_complex_sub rb_complex_minus
+
+/** @alias{rb_complex_uminus} */
#define rb_complex_nagate rb_complex_uminus
-VALUE rb_Complex(VALUE, VALUE);
+/**
+ * Converts various values into a Complex. This function accepts:
+ *
+ * - Instances of ::rb_cComplex (taken as-is),
+ * - Instances of ::rb_cNumeric (adds `0i`),
+ * - Instances of ::rb_cString (parses),
+ * - Other objects that respond to `#to_c`.
+ *
+ * It (possibly recursively) applies `#to_c` until both sides become a Complex
+ * value, then computes `imag * 1i + real`.
+ *
+ * As a special case, passing ::RUBY_Qundef to `imag` is the same as passing
+ * `RB_INT2NUM(0)`.
+ *
+ * @param[in] real Real part (see above).
+ * @param[in] imag Imaginary part (see above).
+ * @exception rb_eTypeError Passed something not described above.
+ * @return An instance of ::rb_cComplex whose value is `1i * imag + real`.
+ *
+ * @internal
+ *
+ * This was the implementation of `Kernel#Complex` before, but they diverged.
+ */
+VALUE rb_Complex(VALUE real, VALUE imag);
+
+/**
+ * Shorthand of `x+0i`. It practically converts `x` into a Complex of the
+ * identical value.
+ *
+ * @param[in] x ::rb_cNumeric, ::rb_cString, or something that responds to
+ * `#to_c`.
+ * @return An instance of ::rb_cComplex, whose value is `x + 0i`.
+ */
#define rb_Complex1(x) rb_Complex((x), INT2FIX(0))
+
+/** @alias{rb_Complex} */
#define rb_Complex2(x,y) rb_Complex((x), (y))
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/cont.h b/include/ruby/internal/intern/cont.h
index cb651e682e..32647f48aa 100644
--- a/include/ruby/internal/intern/cont.h
+++ b/include/ruby/internal/intern/cont.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to rb_cFiber.
*/
#include "ruby/internal/dllexport.h"
@@ -27,20 +27,256 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* cont.c */
-VALUE rb_fiber_new(rb_block_call_func_t, VALUE);
+
+/**
+ * Creates a Fiber instance from a C-backended block.
+ *
+ * @param[in] func A function, to become the fiber's body.
+ * @param[in] callback_obj Passed as-is to `func`.
+ * @return An allocated new instance of rb_cFiber, which is ready to be
+ * "resume"d.
+ */
+VALUE rb_fiber_new(rb_block_call_func_t func, VALUE callback_obj);
+
+/**
+ * Creates a Fiber instance from a C-backended block with the specified
+ * storage.
+ *
+ * If the given storage is Qundef or Qtrue, this function is equivalent to
+ * rb_fiber_new() which inherits storage from the current fiber.
+ *
+ * Specifying Qtrue is experimental and may be changed in the future.
+ *
+ * If the given storage is Qnil, this function will lazy initialize the
+ * internal storage which starts of empty (without any inheritance).
+ *
+ * Otherwise, the given storage is used as the internal storage.
+ *
+ * @param[in] func A function, to become the fiber's body.
+ * @param[in] callback_obj Passed as-is to `func`.
+ * @param[in] storage The way to set up the storage for the fiber.
+ * @return An allocated new instance of rb_cFiber, which is ready to be
+ * "resume"d.
+ */
+VALUE rb_fiber_new_storage(rb_block_call_func_t func, VALUE callback_obj, VALUE storage);
+
+/**
+ * Queries the fiber which is calling this function. Any ruby execution
+ * context has its fiber, either explicitly or implicitly.
+ *
+ * @return The current fiber.
+ */
VALUE rb_fiber_current(void);
-VALUE rb_fiber_alive_p(VALUE);
-VALUE rb_obj_is_fiber(VALUE);
+/**
+ * Queries the liveness of the passed fiber. "Alive" in this context means
+ * that the fiber can still be resumed. Once it reaches is its end of
+ * execution, this function returns ::RUBY_Qfalse.
+ *
+ * @param[in] fiber A target fiber.
+ * @retval RUBY_Qtrue It is.
+ * @retval RUBY_Qfalse It isn't.
+ */
+VALUE rb_fiber_alive_p(VALUE fiber);
+
+/**
+ * Queries if an object is a fiber.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @retval RUBY_Qtrue It is.
+ * @retval RUBY_Qfalse It isn't.
+ */
+VALUE rb_obj_is_fiber(VALUE obj);
+
+/**
+ * Resumes the execution of the passed fiber, either from the point at which
+ * the last rb_fiber_yield() was called if any, or at the beginning of the
+ * fiber body if it is the first call to this function.
+ *
+ * Other arguments are passed into the fiber's body, either as return values of
+ * rb_fiber_yield() in case it switches to there, or as the block parameter of
+ * the fiber body if it switches to the beginning of the fiber.
+ *
+ * The return value of this function is either the value passed to previous
+ * rb_fiber_yield() call, or the ultimate evaluated value of the entire fiber
+ * body if the execution reaches the end of it.
+ *
+ * When an exception happens inside of a fiber it propagates to this function.
+ *
+ * ```ruby
+ * f = Fiber.new do |i|
+ * puts "<x> =>> #{i}"
+ * puts "<y> <-- #{i + 1}"
+ * j = Fiber.yield(i + 1)
+ * puts "<z> =>> #{j}"
+ * puts "<w> <-- #{j + 1}"
+ * next j + 1
+ * end
+ *
+ * puts "[a] <-- 1"
+ * p = f.resume(1)
+ * puts "[b] =>> #{p}"
+ * puts "[c] <-- #{p + 1}"
+ * q = f.resume(p + 1)
+ * puts "[d] =>> #{q}"
+ * ```
+ *
+ * Above program executes in `[a] <x> <y> [b] [c] <z> <w> [d]`.
+ *
+ * @param[out] fiber The fiber to resume.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed (somehow) to `fiber`.
+ * @exception rb_eFiberError `fib` is terminated etc.
+ * @exception rb_eException Any exceptions happen in `fiber`.
+ * @return (See above)
+ * @note This function _does_ return.
+ *
+ * @internal
+ *
+ * @shyouhei expected this function to raise ::rb_eFrozenError for frozen
+ * fibers but it doesn't in practice. Intentional or ...?
+ */
VALUE rb_fiber_resume(VALUE fiber, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_fiber_resume(), except you can specify how to handle the
+ * last element of the given array.
+ *
+ * @param[out] fiber The fiber to resume.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed (somehow) to `fiber`.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eFiberError `fiber` is terminated etc.
+ * @exception rb_eException Any exceptions happen in `fiber`.
+ * @return Either what was yielded or the last value of the fiber body.
+ */
VALUE rb_fiber_resume_kw(VALUE fiber, int argc, const VALUE *argv, int kw_splat);
+/**
+ * Yields the control back to the point where the current fiber was resumed.
+ * The passed objects would be the return value of rb_fiber_resume(). This
+ * fiber then suspends its execution until next time it is resumed.
+ *
+ * This function can also raise arbitrary exceptions injected from outside of
+ * the fiber using rb_fiber_raise().
+ *
+ * ```ruby
+ * exc = Class.new Exception
+ *
+ * f = Fiber.new do
+ * Fiber.yield
+ * rescue exc => e
+ * puts e.message
+ * end
+ *
+ * f.resume
+ * f.raise exc, "Hi!"
+ * ```
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed to rb_fiber_resume().
+ * @exception rb_eException (See above)
+ * @return (See rb_fiber_resume() for details)
+ */
VALUE rb_fiber_yield(int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_fiber_yield(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed to rb_fiber_resume().
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eException What was raised using `Fiber#raise`.
+ * @return (See rb_fiber_resume() for details)
+ */
VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat);
+/**
+ * Transfers control to another fiber, resuming it from where it last stopped
+ * or starting it if it was not resumed before. The calling fiber will be
+ * suspended much like in a call to rb_fiber_yield().
+ *
+ * The fiber which receives the transfer call treats it much like a resume
+ * call. Arguments passed to transfer are treated like those passed to resume.
+ *
+ * The two style of control passing to and from fiber (one is rb_fiber_resume()
+ * and rb_fiber_yield(), another is rb_fiber_transfer() to and from fiber)
+ * can't be freely mixed.
+ *
+ * - If the Fiber's lifecycle had started with transfer, it will never be
+ * able to yield or be resumed control passing, only finish or transfer
+ * back. (It still can resume other fibers that are allowed to be
+ * resumed.)
+ *
+ * - If the Fiber's lifecycle had started with resume, it can yield or
+ * transfer to another Fiber, but can receive control back only the way
+ * compatible with the way it was given away: if it had transferred, it
+ * only can be transferred back, and if it had yielded, it only can be
+ * resumed back. After that, it again can transfer or yield.
+ *
+ * If those rules are broken, rb_eFiberError is raised.
+ *
+ * For an individual Fiber design, yield/resume is easier to use (the Fiber
+ * just gives away control, it doesn't need to think about who the control is
+ * given to), while transfer is more flexible for complex cases, allowing to
+ * build arbitrary graphs of Fibers dependent on each other.
+ *
+ * @param[out] fiber Explicit control destination.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed to rb_fiber_resume().
+ * @exception rb_eFiberError (See above)
+ * @exception rb_eException What was raised using `Fiber#raise`.
+ * @return (See rb_fiber_resume() for details)
+ */
VALUE rb_fiber_transfer(VALUE fiber, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_fiber_transfer(), except you can specify how to handle the
+ * last element of the given array.
+ *
+ * @param[out] fiber Explicit control destination.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed to rb_fiber_resume().
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eFiberError (See above)
+ * @exception rb_eException What was raised using `Fiber#raise`.
+ * @return (See rb_fiber_resume() for details)
+ */
VALUE rb_fiber_transfer_kw(VALUE fiber, int argc, const VALUE *argv, int kw_splat);
+/**
+ * Identical to rb_fiber_resume() but instead of resuming normal execution of
+ * the passed fiber, it raises the given exception in it. From inside of the
+ * fiber this would be seen as if rb_fiber_yield() raised.
+ *
+ * This function does return in case the passed fiber gracefully handled the
+ * passed exception. But if it does not, the raised exception propagates out
+ * of the passed fiber; this function then does not return.
+ *
+ * Parameters are passed to rb_make_exception() to create an exception object.
+ * See its document for what are allowed here.
+ *
+ * It is a failure to call this function against a fiber which is resuming,
+ * have never run yet, or has already finished running.
+ *
+ * @param[out] fiber Where exception is raised.
+ * @param[in] argc Passed as-is to rb_make_exception().
+ * @param[in] argv Passed as-is to rb_make_exception().
+ * @exception rb_eFiberError `fiber` is terminated etc.
+ * @return (See rb_fiber_resume() for details)
+ */
+VALUE rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv);
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_INTERN_CONT_H */
diff --git a/include/ruby/internal/intern/dir.h b/include/ruby/internal/intern/dir.h
index 936f4e1f36..da1873e068 100644
--- a/include/ruby/internal/intern/dir.h
+++ b/include/ruby/internal/intern/dir.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cDir.
*/
#include "ruby/internal/dllexport.h"
@@ -26,6 +26,15 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* dir.c */
+
+/**
+ * Queries the path of the current working directory of the current process.
+ *
+ * @return An instance of ::rb_cString that holds the working directory.
+ * @note The returned string is in "filesystem" encoding. Most notably on
+ * Linux this is an alias of default external encoding. Most notably
+ * on Windows it can be an alias of OS codepage.
+ */
VALUE rb_dir_getwd(void);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/enum.h b/include/ruby/internal/intern/enum.h
index 17c20c1c0a..215ad82672 100644
--- a/include/ruby/internal/intern/enum.h
+++ b/include/ruby/internal/intern/enum.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_mEnumerable.
*/
#include "ruby/internal/dllexport.h"
@@ -26,7 +26,47 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* enum.c */
-VALUE rb_enum_values_pack(int, const VALUE*);
+
+/**
+ * Basically identical to rb_ary_new_form_values(), except it returns something
+ * different when `argc` < 2.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary objects.
+ * @retval RUBY_Qnil `argc` is zero.
+ * @retval argv[0] `argc` is one.
+ * @retval otherwise Otherwise.
+ *
+ * @internal
+ *
+ * What is this business? Well, this function is about `yield`'s taking
+ * multiple values. Consider following user-defined class:
+ *
+ * ```ruby
+ * class Foo
+ * include Enumerable
+ *
+ * def each
+ * yield :q, :w, :e, :r
+ * end
+ * end
+ *
+ * Foo.new.each_with_object([]) do |i, j|
+ * j << i # ^^^ <- What to expect for `i`?
+ * end
+ * ```
+ *
+ * Here, `Foo#each_with_object` is in fact `Enumerable#each_with_object`, which
+ * doesn't know what would be yielded. Yet, it has to take a block of arity 2.
+ * This function is used here, to "pack" arbitrary number of yielded objects
+ * into one.
+ *
+ * If people want to implement their own `Enumerable#each_with_object` this API
+ * can be handy. Though @shyouhei suspects it is relatively rare for 3rd party
+ * extension libraries to have such things. Also `Enumerable#each_entry` is
+ * basically this function exposed as a Ruby method.
+ */
+VALUE rb_enum_values_pack(int argc, const VALUE *argv);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/enumerator.h b/include/ruby/internal/intern/enumerator.h
index c81485155c..20e5d7c6fc 100644
--- a/include/ruby/internal/intern/enumerator.h
+++ b/include/ruby/internal/intern/enumerator.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cEnumerator.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/intern/eval.h" /* rb_frame_this_func */
#include "ruby/internal/iterator.h" /* rb_block_given_p */
@@ -28,52 +29,230 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
-typedef VALUE rb_enumerator_size_func(VALUE, VALUE, VALUE);
+/**
+ * This is the type of functions that rb_enumeratorize_with_size() expects. In
+ * theory an enumerator can have indefinite number of elements, but in practice
+ * it often is the case we can compute the size of an enumerator beforehand.
+ * If your enumerator has such property, supply a function that calculates such
+ * values.
+ *
+ * @param[in] recv The original receiver of the enumerator.
+ * @param[in] argv Arguments passed to `Object#enum_for` etc.
+ * @param[in] eobj The enumerator object.
+ * @return The size of `eobj`, in ::rb_cNumeric, or ::RUBY_Qnil if the size
+ * is not known until we actually iterate.
+ */
+typedef VALUE rb_enumerator_size_func(VALUE recv, VALUE argv, VALUE eobj);
+/**
+ * Decomposed `Enumerator::ArithmeicSequence`. This is a subclass of
+ * ::rb_cEnumerator, which represents a sequence of numbers with common
+ * difference. Internal data structure of the class is opaque to users, but
+ * you can obtain a decomposed one using rb_arithmetic_sequence_extract().
+ */
typedef struct {
- VALUE begin;
- VALUE end;
- VALUE step;
- int exclude_end;
+ VALUE begin; /**< "Left" or "lowest" endpoint of the sequence. */
+ VALUE end; /**< "Right" or "highest" endpoint of the sequence.*/
+ VALUE step; /**< Step between a sequence. */
+ int exclude_end; /**< Whether the endpoint is open or closed. */
} rb_arithmetic_sequence_components_t;
/* enumerator.c */
-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);
+
+/**
+ * Constructs an enumerator. This roughly resembles `Object#enum_for`.
+ *
+ * @param[in] recv A receiver of `meth`.
+ * @param[in] meth Method ID in a symbol object.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to `meth`.
+ * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol.
+ * @return A new instance of ::rb_cEnumerator which, when yielded,
+ * enumerates by calling `meth` on `recv` with `argv`.
+ */
+VALUE rb_enumeratorize(VALUE recv, VALUE meth, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_enumeratorize(), except you can additionally specify the
+ * size function of return value.
+ *
+ * @param[in] recv A receiver of `meth`.
+ * @param[in] meth Method ID in a symbol object.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to `meth`.
+ * @param[in] func Size calculator.
+ * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol.
+ * @return A new instance of ::rb_cEnumerator which, when yielded,
+ * enumerates by calling `meth` on `recv` with `argv`.
+ * @note `func` can be zero, which means the size is unknown.
+ */
+VALUE rb_enumeratorize_with_size(VALUE recv, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *func);
+
+/**
+ * Identical to rb_enumeratorize_with_func(), except you can specify how to
+ * handle the last element of the given array.
+ *
+ * @param[in] recv A receiver of `meth`.
+ * @param[in] meth Method ID in a symbol object.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to `meth`.
+ * @param[in] func Size calculator.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol.
+ * @return A new instance of ::rb_cEnumerator which, when yielded,
+ * enumerates by calling `meth` on `recv` with `argv`.
+ * @note `func` can be zero, which means the size is unknown.
+ */
+VALUE rb_enumeratorize_with_size_kw(VALUE recv, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *func, int kw_splat);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Extracts components of the passed arithmetic sequence. This can be seen as
+ * an extended version of rb_range_values().
+ *
+ * @param[in] as Target instance of `Enumerator::ArithmericSequence`.
+ * @param[out] buf Decomposed results buffer.
+ * @return 0 `as` is not `Enumerator::ArithmericSequence`.
+ * @return 1 Success.
+ * @post `buf` is filled.
+ */
+int rb_arithmetic_sequence_extract(VALUE as, rb_arithmetic_sequence_components_t *buf);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_range_beg_len(), except it takes an instance of
+ * `Enumerator::ArithmericSequence`.
+ *
+ * @param[in] as An `Enumerator::ArithmericSequence` instance.
+ * @param[out] begp Return value buffer.
+ * @param[out] lenp Return value buffer.
+ * @param[out] stepp Return value buffer.
+ * @param[in] len Updated length.
+ * @param[in] err In case `len` is out of range...
+ * - `0`: returns ::RUBY_Qnil.
+ * - `1`: raises ::rb_eRangeError.
+ * - `2`: `beg` and `len` expanded accordingly.
+ * @exception rb_eRangeError `as` cannot fit into `long`.
+ * @retval RUBY_Qfalse `as` is not `Enumerator::ArithmericSequence`.
+ * @retval RUBY_Qnil `len` is out of `as` but `err` is zero.
+ * @retval RUBY_Qtrue Otherwise.
+ * @post `beg` is the (possibly updated) left endpoint.
+ * @post `len` is the (possibly updated) length of the range.
+ *
+ * @internal
+ *
+ * Currently no 3rd party applications of this function is found. But that can
+ * be because this function is relatively new.
+ */
+VALUE rb_arithmetic_sequence_beg_len_step(VALUE as, long *begp, long *lenp, long *stepp, long len, int err);
RBIMPL_SYMBOL_EXPORT_END()
+/** @cond INTERNAL_MACRO */
#ifndef RUBY_EXPORT
# define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \
rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn))
# define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \
rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat)
#endif
+/** @endcond */
+/**
+ * This is an implementation detail of #RETURN_SIZED_ENUMERATOR(). You could
+ * use it directly, but can hardly be handy.
+ *
+ * @param[in] obj A receiver.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to the current method.
+ * @param[in] size_fn Size calculator.
+ * @return A new instance of ::rb_cEnumerator which, when yielded,
+ * enumerates by calling the current method on `recv` with `argv`.
+ */
#define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \
(argc), (argv), (size_fn))
+/**
+ * This is an implementation detail of #RETURN_SIZED_ENUMERATOR_KW(). You
+ * could use it directly, but can hardly be handy.
+ *
+ * @param[in] obj A receiver.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to the current method.
+ * @param[in] size_fn Size calculator.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @return A new instance of ::rb_cEnumerator which, when yielded,
+ * enumerates by calling the current method on `recv` with `argv`.
+ */
#define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \
rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \
(argc), (argv), (size_fn), (kw_splat))
+/**
+ * This roughly resembles `return enum_for(__callee__) unless block_given?`.
+ *
+ * @param[in] obj A receiver.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to the current method.
+ * @param[in] size_fn Size calculator.
+ * @note This macro may return inside.
+ */
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \
if (!rb_block_given_p()) \
return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \
} while (0)
+
+/**
+ * Identical to #RETURN_SIZED_ENUMERATOR(), except you can specify how to
+ * handle the last element of the given array.
+ *
+ * @param[in] obj A receiver.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to the current method.
+ * @param[in] size_fn Size calculator.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @note This macro may return inside.
+ */
#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \
if (!rb_block_given_p()) \
return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \
} while (0)
+/**
+ * Identical to #RETURN_SIZED_ENUMERATOR(), except its size is unknown.
+ *
+ * @param[in] obj A receiver.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to the current method.
+ * @note This macro may return inside.
+ */
#define RETURN_ENUMERATOR(obj, argc, argv) \
RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0)
+/**
+ * Identical to #RETURN_SIZED_ENUMERATOR_KW(), except its size is unknown. It
+ * can also be seen as a routine identical to #RETURN_ENUMERATOR(), except you
+ * can specify how to handle the last element of the given array.
+ *
+ * @param[in] obj A receiver.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to the current method.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @note This macro may return inside.
+ */
#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \
RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat)
diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h
index aa9fe2daba..9c153cbac5 100644
--- a/include/ruby/internal/intern/error.h
+++ b/include/ruby/internal/intern/error.h
@@ -17,44 +17,233 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_eException.
*/
+#include "ruby/internal/attr/format.h"
+#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/fl_type.h"
#include "ruby/backward/2/assume.h"
-#include "ruby/backward/2/attributes.h"
+/**
+ * This macro is used in conjunction with rb_check_arity(). If you pass it to
+ * the function's last (max) argument, that means the function does not check
+ * upper limit.
+ */
#define UNLIMITED_ARGUMENTS (-1)
-#define rb_exc_new2 rb_exc_new_cstr
-#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_exc_new2 rb_exc_new_cstr /**< @old{rb_exc_new_cstr} */
+#define rb_exc_new3 rb_exc_new_str /**< @old{rb_exc_new_str} */
+
+/** @cond INTERNAL_MACRO */
#define rb_check_arity rb_check_arity
+/** @endcond */
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);
+
+/**
+ * Creates an instance of the passed exception class.
+ *
+ * @param[in] etype A subclass of ::rb_eException.
+ * @param[in] ptr Buffer contains error message.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eTypeError `etype` is not a class.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of `etype`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ *
+ * @internal
+ *
+ * This function works for non-exception classes as well, as long as they take
+ * one string argument.
+ */
+VALUE rb_exc_new(VALUE etype, const char *ptr, long len);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer
+ * to a C string.
+ *
+ * @param[in] etype A subclass of ::rb_eException.
+ * @param[in] str A C string (becomes an error message).
+ * @exception rb_eTypeError `etype` is not a class.
+ * @return An instance of `etype`.
+ */
+VALUE rb_exc_new_cstr(VALUE etype, const char *str);
+
+/**
+ * Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of
+ * C's.
+ *
+ * @param[in] etype A subclass of ::rb_eException.
+ * @param[in] str An instance of ::rb_cString.
+ * @exception rb_eTypeError `etype` is not a class.
+ * @return An instance of `etype`.
+ */
+VALUE rb_exc_new_str(VALUE etype, VALUE str);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+/**
+ * Raises an instance of ::rb_eLoadError.
+ *
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception rb_eLoadError Always raises this.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * Who needs this? Except ruby itself?
+ */
+void rb_loaderror(const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Identical to rb_loaderror(), except it additionally takes which file is
+ * unable to load. The path can be obtained later using `LoadError#path` of
+ * the raising exception.
+ *
+ * @param[in] path What failed.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception rb_eLoadError Always raises this.
+ * @note It never returns.
+ */
+void rb_loaderror_with_path(VALUE path, const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Raises an instance of ::rb_eNameError. The name can be obtained later using
+ * `NameError#name` of the raising exception.
+ *
+ * @param[in] name What failed.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception rb_eNameError Always raises this.
+ * @note It never returns.
+ */
+void rb_name_error(ID name, const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Identical to rb_name_error(), except it takes a ::VALUE instead of ::ID.
+ *
+ * @param[in] name What failed.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception rb_eNameError Always raises this.
+ * @note It never returns.
+ */
+void rb_name_error_str(VALUE name, const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+/**
+ * Raises an instance of ::rb_eFrozenError. The object can be obtained later
+ * using `FrozenError#receiver` of the raising exception.
+ *
+ * @param[in] recv What is frozen.
+ * @param[in] fmt Format specifier string compatible with rb_sprintf().
+ * @exception rb_eFrozenError Always raises this.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * Note however, that it is often not possible to inspect a frozen object,
+ * because the inspection itself could be forbidden by the frozen-ness.
+ */
+void rb_frozen_error_raise(VALUE recv, const char *fmt, ...);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Honestly I don't understand the name, but it raises an instance of
+ * ::rb_eArgError.
+ *
+ * @param[in] str A message.
+ * @param[in] type Another message.
+ * @exception rb_eArgError Always raises this.
+ * @note It never returns.
+ */
+void rb_invalid_str(const char *str, const char *type);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_frozen_error_raise(), except its raising exception has a
+ * message like "can't modify frozen /what/".
+ *
+ * @param[in] what What was frozen.
+ * @exception rb_eFrozenError Always raises this.
+ * @note It never returns.
+ */
+void rb_error_frozen(const char *what);
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * Identical to rb_error_frozen(), except it takes arbitrary Ruby object
+ * instead of C's string.
+ *
+ * @param[in] what What was frozen.
+ * @exception rb_eFrozenError Always raises this.
+ * @note It never returns.
+ */
+void rb_error_frozen_object(VALUE what);
+
+/**
+ * Queries if the passed object is frozen.
+ *
+ * @param[in] obj Target object to test frozen-ness.
+ * @exception rb_eFrozenError It is frozen.
+ * @post Upon successful return it is guaranteed _not_ frozen.
+ */
+void rb_check_frozen(VALUE obj);
+
+/**
+ * Ensures that the passed object can be `initialize_copy` relationship. When
+ * you implement your own one you would better call this at the right beginning
+ * of your implementation.
+ *
+ * @param[in] obj Destination object.
+ * @param[in] orig Source object.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @post Upon successful return obj is guaranteed safe to copy orig.
+ */
void rb_check_copyable(VALUE obj, VALUE orig);
-NORETURN(MJIT_STATIC void rb_error_arity(int, int, int));
+
+RBIMPL_ATTR_NORETURN()
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_scan_args(). You don't have to
+ * bother.
+ *
+ * @pre `argc` is out of range of `min`..`max`, both inclusive.
+ * @param[in] argc Arbitrary integer.
+ * @param[in] min Minimum allowed `argc`.
+ * @param[in] max Maximum allowed `argc`.
+ * @exception rb_eArgError Always.
+ */
+MJIT_STATIC void rb_error_arity(int argc, int min, int max);
+
RBIMPL_SYMBOL_EXPORT_END()
-/* Does anyone use this? Remain not deleted for compatibility. */
+/**
+ * @deprecated
+ *
+ * Does anyone use this? Remain not deleted for compatibility.
+ */
#define rb_check_frozen_internal(obj) do { \
VALUE frozen_obj = (obj); \
if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \
@@ -62,6 +251,7 @@ RBIMPL_SYMBOL_EXPORT_END()
} \
} while (0)
+/** @alias{rb_check_frozen} */
static inline void
rb_check_frozen_inline(VALUE obj)
{
@@ -69,8 +259,23 @@ rb_check_frozen_inline(VALUE obj)
rb_error_frozen_object(obj);
}
}
+
+/** @alias{rb_check_frozen} */
#define rb_check_frozen rb_check_frozen_inline
+/**
+ * Ensures that the passed integer is in the passed range. When you can use
+ * rb_scan_args() that is preferred over this one (powerful, descriptive). But
+ * it can have its own application area.
+ *
+ * @param[in] argc Arbitrary integer.
+ * @param[in] min Minimum allowed `argv`.
+ * @param[in] max Maximum allowed `argv`, or `UNLIMITED_ARGUMENTS`.
+ * @exception rb_eArgError `argc` out of range.
+ * @return The passed `argc`.
+ * @post Upon successful return `argc` is in range of `min`..`max`, both
+ * inclusive.
+ */
static inline int
rb_check_arity(int argc, int min, int max)
{
diff --git a/include/ruby/internal/intern/eval.h b/include/ruby/internal/intern/eval.h
index 11957053d7..2230f7ab0c 100644
--- a/include/ruby/internal/intern/eval.h
+++ b/include/ruby/internal/intern/eval.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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"
@@ -28,31 +28,194 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
/* eval.c */
RBIMPL_ATTR_NORETURN()
-void rb_exc_raise(VALUE);
+/**
+ * Identical to rb_raise(), except it raises the passed exception instance as-
+ * is instead of creating new one.
+ *
+ * @param[in] exc An instance of a subclass of ::rb_eException.
+ * @exception exc What is passed.
+ * @exception rb_eTypeError `exc` is not an exception.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * Wellll actually, it can take more than what is described above. This
+ * function tries to call `exception` method of the passed object. If that
+ * function returns an exception object that is used instead.
+ */
+void rb_exc_raise(VALUE exc);
RBIMPL_ATTR_NORETURN()
-void rb_exc_fatal(VALUE);
+/**
+ * Identical to rb_fatal(), except it raises the passed exception instance as-
+ * is instead of creating new one.
+ *
+ * @param[in] exc An instance of a subclass of ::rb_eException.
+ * @exception exc What is passed.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * You know what...? Using this API you can make arbitrary exceptions, like
+ * `RuntimeError`, that doesn't interface with `rescue` clause. This is very
+ * confusing.
+ */
+void rb_exc_fatal(VALUE exc);
+
+/* process.c */
RBIMPL_ATTR_NORETURN()
-VALUE rb_f_exit(int, const VALUE*);
+/**
+ * Identical to rb_exit(), except how arguments are passed.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Contains at most one of the following:
+ * - ::RUBY_Qtrue - means `EXIT_SUCCESS`.
+ * - ::RUBY_Qfalse - means `EXIT_FAILURE`.
+ * - Numerical value - takes that value.
+ * @exception rb_eArgError Wrong `argc`.
+ * @exception rb_eSystemExit Exception representing the exit status.
+ * @note It never returns.
+ */
+VALUE rb_f_exit(int argc, const VALUE *argv);
RBIMPL_ATTR_NORETURN()
-VALUE rb_f_abort(int, const VALUE*);
+/**
+ * This is similar to rb_f_exit(). In fact on some situation it internally
+ * calls rb_exit(). But can be very esoteric on occasions.
+ *
+ * It takes up to one argument. If an argument is passed, it tries to display
+ * that. Otherwise if there is `$!`, displays that exception instead. It
+ * finally raise ::rb_eSystemExit in both cases.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Contains at most one string-ish object.
+ * @exception rb_eArgError Wrong `argc`.
+ * @exception rb_eTypeError No conversion from `argv[0]` to String.
+ * @exception rb_eSystemExit Exception representing `EXIT_FAILURE`.
+ * @note It never returns.
+ */
+VALUE rb_f_abort(int argc, const VALUE *argv);
+
+/* eval.c*/
RBIMPL_ATTR_NORETURN()
+/**
+ * Raises an instance of ::rb_eInterrupt.
+ *
+ * @exception rb_eInterrupt Always raises this exception.
+ * @note It never returns.
+ */
void rb_interrupt(void);
+
+/**
+ * Queries the name of the Ruby level method that is calling this function.
+ * The "name" in this context is the one assigned to the function for the first
+ * time (note that methods can have multiple names via aliases).
+ *
+ * @retval 0 There is no method (e.g. toplevel context).
+ * @retval otherwise The name of the current method.
+ */
ID rb_frame_this_func(void);
RBIMPL_ATTR_NORETURN()
-void rb_jump_tag(int);
-void rb_obj_call_init(VALUE, int, const VALUE*);
+/**
+ * This function is to re-throw global escapes. Such global escapes include
+ * exceptions, `throw`, `break`, for example.
+ *
+ * It makes sense only when used in conjunction with "protect" series APIs
+ * e.g. rb_protect(), rb_load_protect(), rb_eval_string_protect(), etc. In
+ * case these functions experience global escapes, they fill their opaque
+ * `state` return buffer. You can ignore such escapes. But if you decide
+ * otherwise, you have to somehow escape globally again. This function is used
+ * for that purpose.
+ *
+ * @param[in] state Opaque state of execution.
+ * @note It never returns.
+ *
+ * @internal
+ *
+ * Though not a part of our public API, `state` is in fact an enum
+ * ruby_tag_type. You can see the potential values by looking at vm_core.h.
+ */
+void rb_jump_tag(int state);
+
+/**
+ * Calls `initialize` method of the passed object with the passed arguments.
+ * It also forwards the implicitly passed block to the method.
+ *
+ * @param[in] obj Receiver object.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed as-is to `obj.initialize`.
+ * @exception rb_eException Any exceptions happen inside.
+ */
+void rb_obj_call_init(VALUE obj, int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_obj_call_init(), except you can specify how to handle the
+ * last element of the given array.
+ *
+ * @param[in] obj Receiver object.
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Passed as-is to `obj.initialize`.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eException Any exceptions happen inside.
+ */
void rb_obj_call_init_kw(VALUE, int, const VALUE*, int);
-VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
+
+/**
+ * Identical to rb_frame_this_func(), except it returns the named used to call
+ * the method.
+ *
+ * @retval 0 There is no method (e.g. toplevel context).
+ * @retval otherwise The name of the current method.
+ */
ID rb_frame_callee(void);
-VALUE rb_make_exception(int, const VALUE*);
+
+/**
+ * Constructs an exception object from the list of arguments, in a manner
+ * similar to Ruby's `raise`. This function can take:
+ *
+ * - No arguments at all, i.e. `argc == 0`. This is not a failure. It
+ * returns ::RUBY_Qnil then.
+ *
+ * - An object, which is an instance of ::rb_cString. In this case an
+ * instance of ::rb_eRuntimeError whose message is the passed string is
+ * created then returned.
+ *
+ * - An object, which responds to `exception` method, and optionally its
+ * argument, and optionally its backtrace. For example instances of
+ * subclasses of ::rb_eException have this method. What is returned from
+ * the method is returned.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv 0 up to 3 objects.
+ * @exception rb_eArgError Wrong `argc`.
+ * @exception rb_eTypeError `argv[0].exception` returned non-exception.
+ * @return An instance of a subclass of ::rb_eException.
+ *
+ * @internal
+ *
+ * Historically this was _the_ way `raise` converted its arguments to an
+ * exception. However they diverged.
+ */
+VALUE rb_make_exception(int argc, const VALUE *argv);
/* eval_jump.c */
-void rb_set_end_proc(void (*)(VALUE), VALUE);
+
+/**
+ * Registers a function that shall run on process exit. Registered functions
+ * run in reverse-chronological order, mixed with syntactic `END` block and
+ * `Kernel#at_exit`.
+ *
+ * @param[in] func Function to run at process exit.
+ * @param[in] arg Passed as-is to `func`.
+ */
+void rb_set_end_proc(void (*func)(VALUE arg), VALUE arg);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/file.h b/include/ruby/internal/intern/file.h
index 9ebefece66..79820fdc61 100644
--- a/include/ruby/internal/intern/file.h
+++ b/include/ruby/internal/intern/file.h
@@ -17,25 +17,196 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cFile.
*/
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* file.c */
-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);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_file_expand_path(), except how arguments are passed.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Filename, and base directory, in that order.
+ * @exception rb_eArgError Wrong `argc`.
+ * @exception rb_eTypeError Non-string passed.
+ * @exception rb_eEncCompatError No conversion from arguments to a path.
+ * @return Expanded path.
+ *
+ * @internal
+ *
+ * It seems nobody actually uses this function right now. Maybe delete it?
+ */
+VALUE rb_file_s_expand_path(int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_file_absolute_path(), except it additionally understands
+ * `~`. If a given pathname starts with `~someone/`, that part expands to the
+ * user's home directory (or that of current process' owner's in case of `~/`).
+ *
+ * @param[in] fname Relative file name.
+ * @param[in] dname Lookup base directory name, or in case
+ * ::RUBY_Qnil is passed the process' current
+ * working directory is assumed.
+ * @exception rb_eArgError Home directory is not absolute.
+ * @exception rb_eTypeError Non-string passed.
+ * @exception rb_eEncCompatError No conversion from arguments to a path.
+ * @return Expanded path.
+ */
+VALUE rb_file_expand_path(VALUE fname, VALUE dname);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_file_absolute_path(), except how arguments are passed.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Filename, and base directory, in that order.
+ * @exception rb_eArgError Wrong `argc`.
+ * @exception rb_eTypeError Non-string passed.
+ * @exception rb_eEncCompatError No conversion from arguments to a path.
+ * @return Expanded path.
+ *
+ * @internal
+ *
+ * It seems nobody actually uses this function right now. Maybe delete it?
+ */
+VALUE rb_file_s_absolute_path(int argc, const VALUE *argv);
+
+/**
+ * Maps a relative path to its absolute representation. Relative paths are
+ * referenced from the passed directory name, or from the process' current
+ * working directory in case ::RUBY_Qnil is passed.
+ *
+ * @param[in] fname Relative file name.
+ * @param[in] dname Lookup base directory name, or in case
+ * ::RUBY_Qnil is passed the process' current
+ * working directory is assumed.
+ * @exception rb_eArgError Strings contain NUL bytes.
+ * @exception rb_eTypeError Non-string passed.
+ * @exception rb_eEncCompatError No conversion from arguments to a path.
+ * @return Expanded path.
+ */
+VALUE rb_file_absolute_path(VALUE fname, VALUE dname);
+
+/**
+ * Strips a file path's last component (and trailing separators if any). This
+ * function is relatively simple on POSIX environments; just splits the input
+ * with `/`, strips the last one, if something remains joins them again,
+ * otherwise the return value is `"."`. However when it comes to Windows this
+ * function is quite very much complicated. We have to take UNC etc. into
+ * account. So for instance `"C:foo"`'s dirname is `"C:."`.
+ *
+ * @param[in] fname File name to strip.
+ * @exception rb_eTypeError `fname` is not a String.
+ * @exception rb_eArgError `fname` contains NUL bytes.
+ * @exception rb_eEncCompatError `fname`'s encoding is not path-compat.
+ * @return A dirname of `fname`.
+ * @note This is a "pure" operation; it computes the return value solely
+ * from the passed object and never does any file IO.
+ */
VALUE rb_file_dirname(VALUE fname);
-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_ATTR_NONNULL(())
+/**
+ * Resolves a feature's path. This function takes for instance `"json"` and
+ * `[".so", ".rb"]`, and iterates over the `$LOAD_PATH` to see if there is
+ * either `json.so` or `json.rb` in the directory.
+ *
+ * This is not what everything `require` does, but at least `require` is built
+ * on top of it.
+ *
+ * @param[in,out] feature File to search, and return buffer.
+ * @param[in] exts List of file extensions.
+ * @exception rb_eTypeError `feature` is not a String.
+ * @exception rb_eArgError `feature` contains NUL bytes.
+ * @exception rb_eEncCompatError `feature`'s encoding is not path-compat.
+ * @retval 0 Not found
+ * @retval otherwise Found index in `ext`, plus one.
+ * @post `*feature` is a resolved path.
+ */
+int rb_find_file_ext(VALUE *feature, const char *const *exts);
+
+/**
+ * Identical to rb_find_file_ext(), except it takes a feature name and is
+ * extension at once, e.g. `"json.rb"`. This difference is much like how
+ * `require` and `load` are different.
+ *
+ * @param[in] path A path relative to `$LOAD_PATH`.
+ * @exception rb_eTypeError `path` is not a String.
+ * @exception rb_eArgError `path` contains NUL bytes.
+ * @exception rb_eEncCompatError `path`'s encoding is not path-compat.
+ * @return Expanded path.
+ */
+VALUE rb_find_file(VALUE path);
+
+/**
+ * Queries if the given path is either a directory, or a symlink that
+ * (potentially recursively) points to such thing.
+ *
+ * @param[in] _ Ignored (why...?)
+ * @param[in] path String, or IO. In case of IO it issues
+ * `fstat(2)` instead of `stat(2)`.
+ * @exception rb_eFrozenError `path` is a frozen IO (why...?)
+ * @exception rb_eTypeError `path` is neither String nor IO.
+ * @exception rb_eArgError `path` contains NUL bytes.
+ * @exception rb_eEncCompatError `path`'s encoding is not path-compat.
+ * @retval RUBY_Qtrue `path` is a directory.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_file_directory_p(VALUE _, VALUE path);
+
+/**
+ * Converts a string into an "OS Path" encoding, if any. In most operating
+ * systems there are no such things like per-OS default encoding of filename.
+ * For them this function is no-op. However most notably on MacOS, pathnames
+ * are UTF-8 encoded. It converts the given string into such encoding.
+ *
+ * @param[in] path An instance of ::rb_cString.
+ * @exception rb_eEncCompatError `path`'s encoding is not path-compat.
+ * @return `path`'s contents converted to the OS' path encoding.
+ */
+VALUE rb_str_encode_ospath(VALUE path);
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the given path is an absolute path. On POSIX environments it is
+ * as easy as `path[0] == '/'`. However on Windows, drive letters and UNC
+ * paths are also taken into account.
+ *
+ * @param[in] path A possibly relative path string.
+ * @retval 1 `path` is absolute.
+ * @retval 0 `path` is relative.
+ */
+int rb_is_absolute_path(const char *path);
+
+/**
+ * Queries the file size of the given file. Because this function calls
+ * `fstat(2)` internally, it is a failure to pass a closed file to this
+ * function.
+ *
+ * This function flushes the passed file's buffer if any. Can take time.
+ *
+ * @param[in] file A file object.
+ * @exception rb_eFrozenError `file` is frozen.
+ * @exception rb_eIOError `file` is closed.
+ * @exception rb_eSystemCallError Permission denied etc.
+ * @exception rb_eNoMethodError The given non-file object doesn't respond
+ * to `#size`.
+ * @return The size of the passed file.
+ * @note Passing a non-regular file such as a UNIX domain socket to this
+ * function is not a failure. But the return value is
+ * unpredictable. POSIX's `<sys/stat.h>` states that "the use of
+ * this field is unspecified" then.
+ */
+rb_off_t rb_file_size(VALUE file);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/gc.h b/include/ruby/internal/intern/gc.h
index 30759e0ded..2ee1d257db 100644
--- a/include/ruby/internal/intern/gc.h
+++ b/include/ruby/internal/intern/gc.h
@@ -17,40 +17,375 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_mGC.
*/
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h> /* size_t */
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* ssize_t */
+#endif
+
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
-#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*);
+
+RBIMPL_ATTR_COLD()
+RBIMPL_ATTR_NORETURN()
+/**
+ * Triggers out-of-memory error. If possible it raises ::rb_eNoMemError. But
+ * because we are running out of memory that is not always doable. This
+ * function tries hard to show something, but ultimately can die silently.
+ *
+ * @exception rb_eNoMemError Raises it if possible.
+ */
+void rb_memerror(void);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the GC is busy.
+ *
+ * @retval 0 It isn't.
+ * @retval 1 It is.
+ */
+int rb_during_gc(void);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Marks objects between the two pointers. This is one of the GC utility
+ * functions that you can call when you design your own
+ * ::rb_data_type_struct::dmark.
+ *
+ * @pre Continuous memory region from `start` to `end` shall be fully
+ * addressable.
+ * @param[out] start Pointer to an array of objects.
+ * @param[out] end Pointer that terminates the array of objects.
+ * @post Objects from `start` (included) to `end` (excluded) are marked.
+ *
+ * @internal
+ *
+ * `end` can be NULL... But that just results in no-op.
+ */
+void rb_gc_mark_locations(const VALUE *start, const VALUE *end);
+
+/**
+ * Identical to rb_mark_hash(), except it marks only values of the table and
+ * leave their associated keys unmarked. This is one of the GC utility
+ * functions that you can call when you design your own
+ * ::rb_data_type_struct::dmark.
+ *
+ * @warning Of course it can break GC. Leave it unused if unsure.
+ * @param[in] tbl A table to mark.
+ * @post Values stored in `tbl` are marked.
+ */
+void rb_mark_tbl(struct st_table *tbl);
+
+/**
+ * Identical to rb_mark_tbl(), except it marks objects using
+ * rb_gc_mark_movable(). This is one of the GC utility functions that you can
+ * call when you design your own ::rb_data_type_struct::dmark.
+ *
+ * @warning Of course it can break GC. Leave it unused if unsure.
+ * @param[in] tbl A table to mark.
+ * @post Values stored in `tbl` are marked.
+ */
+void rb_mark_tbl_no_pin(struct st_table *tbl);
+
+/**
+ * Identical to rb_mark_hash(), except it marks only keys of the table and
+ * leave their associated values unmarked. This is one of the GC utility
+ * functions that you can call when you design your own
+ * ::rb_data_type_struct::dmark.
+ *
+ * @warning Of course it can break GC. Leave it unused if unsure.
+ * @param[in] tbl A table to mark.
+ * @post Keys stored in `tbl` are marked.
+ */
+void rb_mark_set(struct st_table *tbl);
+
+/**
+ * Marks keys and values associated inside of the given table. This is one of
+ * the GC utility functions that you can call when you design your own
+ * ::rb_data_type_struct::dmark.
+ *
+ * @param[in] tbl A table to mark.
+ * @post Objects stored in `tbl` are marked.
+ */
+void rb_mark_hash(struct st_table *tbl);
+
+/**
+ * Updates references inside of tables. After you marked values using
+ * rb_mark_tbl_no_pin(), the objects inside of the table could of course be
+ * moved. This function is to fixup those references. You can call this from
+ * your ::rb_data_type_struct::dcompact.
+ *
+ * @param[out] ptr A table that potentially includes moved references.
+ * @post Moved references, if any, are corrected.
+ */
void rb_gc_update_tbl_refs(st_table *ptr);
-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);
+
+/**
+ * Identical to rb_gc_mark(), except it allows the passed value be a
+ * non-object. For instance pointers to different type of memory regions are
+ * allowed here. Such values are silently ignored. This is one of the GC
+ * utility functions that you can call when you design your own
+ * ::rb_data_type_struct::dmark.
+ *
+ * @param[out] obj A possible object.
+ * @post `obj` is marked, if possible.
+ */
+void rb_gc_mark_maybe(VALUE obj);
+
+/**
+ * Marks an object. This is one of the GC utility functions that you can call
+ * when you design your own ::rb_data_type_struct::dmark.
+ *
+ * @param[out] obj Arbitrary Ruby object.
+ * @post `obj` is marked.
+ */
+void rb_gc_mark(VALUE obj);
+
+/**
+ * Maybe this is the only function provided for C extensions to control the
+ * pinning of objects, so let us describe it in detail. These days Ruby's GC
+ * is copying. As far as an object's physical address is guaranteed unused, it
+ * can move around the object space. Our GC engine rearranges these objects
+ * after it reclaims unreachable objects from our object space, so that the
+ * space is compact (improves memory locality). This is called the
+ * "compaction" phase, and works well most of the time... as far as there are
+ * no C extensions. C extensions complicate the scenario because Ruby core
+ * cannot detect any use of the physical address of an object inside of C
+ * functions. In order to prevent memory corruptions, objects observable from
+ * C extensions are "pinned"; they stick to where they are born until they die,
+ * just in case any C extensions touch their raw pointers. This variant of
+ * scheme is called "Mostly-Copying" garbage collector. Authors of C
+ * extensions, however, can extremely carefully write them to become
+ * compaction-aware. To do so avoid referring to a Ruby object from inside of
+ * your struct in the first place. But if that is not possible, use this
+ * function from your ::rb_data_type_struct::dmark then. This way objects
+ * marked using it are considered movable. If you chose this way you have to
+ * manually fix up locations of such moved pointers using rb_gc_location().
+ *
+ * @see Bartlett, Joel F., "Compacting Garbage Collection with Ambiguous
+ * Roots", ACM SIGPLAN Lisp Pointers Volume 1 Issue 6 pp. 3-12,
+ * April-May-June, 1988. https://doi.org/10.1145/1317224.1317225
+ *
+ * @param[in] obj Object that is movable.
+ * @post Values stored in `tbl` are marked.
+ */
+void rb_gc_mark_movable(VALUE obj);
+
+/**
+ * Finds a new "location" of an object. An object can be moved on compaction.
+ * This function projects its new abode, or just returns the passed object if
+ * not moved. This is one of the GC utility functions that you can call when
+ * you design your own ::rb_data_type_struct::dcompact.
+ *
+ * @param[in] obj An object, possibly already moved to somewhere else.
+ * @return An object, which holds the current contents of former `obj`.
+ */
+VALUE rb_gc_location(VALUE obj);
+
+/**
+ * Asserts that the passed object is no longer needed. Such objects are
+ * reclaimed sooner or later so this function is not mandatory. But sometimes
+ * you can know from your application knowledge that an object is surely dead
+ * at some point. Calling this as a hint can be a polite way.
+ *
+ * @param[out] obj Object, dead.
+ * @pre `obj` have never been passed to this function before.
+ * @post `obj` could be invalidated.
+ * @warning It is a failure to pass an object multiple times to this
+ * function.
+ * @deprecated This is now a no-op function.
+ */
+RBIMPL_ATTR_DEPRECATED(("this is now a no-op function"))
+void rb_gc_force_recycle(VALUE obj);
+
+/**
+ * Triggers a GC process. This was the only GC entry point that we had at the
+ * beginning. Over time our GC evolved. Now what this function does is just a
+ * very simplified variation of the entire GC algorithms. A series of
+ * procedures kicked by this API is called a "full" GC.
+ *
+ * - It immediately scans the entire object space to sort the dead.
+ * - It immediately reclaims any single dead bodies to reuse later.
+ *
+ * It is worth noting that the procedures above do not include evaluations of
+ * finalisers. They run later.
+ *
+ * @internal
+ *
+ * Finalisers are deferred until we can handle interrupts. See
+ * `rb_postponed_job_flush` in vm_trace.c.
+ *
+ * Of course there are GC that are not "full". For instance this one and the
+ * GC which runs when we are running out of memory are different. See
+ * `gc_profile_record_flag` defined in gc.c for the kinds of GC.
+ *
+ * In spite of the name this is not what everything that a GC can trigger. As
+ * of writing it seems this function does not trigger compaction. But this
+ * might change in future.
+ */
void rb_gc(void);
-void rb_gc_copy_finalizer(VALUE,VALUE);
+
+/**
+ * Copy&paste an object's finaliser to another. This is one of the GC utility
+ * functions that you can call when you design your own `initialize_copy`,
+ * `initialize_dup`, `initialize_clone`.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source object.
+ * @post `dst` and `src` share the same finaliser.
+ *
+ * @internal
+ *
+ * But isn't it easier for you to call super, and let `Object#initialize_copy`
+ * call this function instead?
+ */
+void rb_gc_copy_finalizer(VALUE dst, VALUE src);
+
+/**
+ * (Re-) enables GC. This makes sense only after you called rb_gc_disable().
+ *
+ * @retval RUBY_Qtrue GC was disabled before.
+ * @retval RUBY_Qfalse GC was enabled before.
+ * @post GC is enabled.
+ *
+ * @internal
+ *
+ * This is one of such exceptional functions that does not raise both Ruby
+ * exceptions and C++ exceptions.
+ */
VALUE rb_gc_enable(void);
+
+/**
+ * Disables GC. This prevents automatic GC runs when the process is running
+ * out of memory. Such situations shall result in rb_memerror(). However this
+ * does not prevent users from manually invoking rb_gc(). That should work.
+ * People abused this by disabling GC at the beginning of an event loop,
+ * process events without GC overheads, then manually force reclaiming garbage
+ * at the bottom of the loop. However because our GC is now much smarter than
+ * just calling rb_gc(), this technique is proven to be sub-optimal these days.
+ * It is believed that there is currently practically no needs of this
+ * function.
+ *
+ * @retval RUBY_Qtrue GC was disabled before.
+ * @retval RUBY_Qfalse GC was enabled before.
+ * @post GC is disabled.
+ */
VALUE rb_gc_disable(void);
+
+/**
+ * Identical to rb_gc(), except the return value.
+ *
+ * @return Always returns ::RUBY_Qnil.
+ */
VALUE rb_gc_start(void);
-VALUE rb_define_finalizer(VALUE, VALUE);
-VALUE rb_undefine_finalizer(VALUE);
+
+/**
+ * Assigns a finaliser for an object. Each objects can have objects (typically
+ * blocks) that run immediately after that object dies. They are called
+ * finalisers of an object. This function associates a finaliser object with a
+ * target object.
+ *
+ * @note Note that finalisers run _after_ the object they finalise dies. You
+ * cannot for instance call its methods.
+ * @note If your finaliser references the object it finalises that object
+ * loses any chance to become a garbage; effectively leaks memory until
+ * the end of the process.
+ *
+ * @param[in] obj Target to finalise.
+ * @param[in] block Something `call`able.
+ * @exception rb_eRuntimeError Somehow `obj` cannot have finalisers.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @exception rb_eArgError `block` doesn't respond to `call`.
+ * @return The passed `block`.
+ * @post `block` runs after `obj` dies.
+ */
+VALUE rb_define_finalizer(VALUE obj, VALUE block);
+
+/**
+ * Modifies the object so that it has no finalisers at all. This function is
+ * mainly provided for symmetry. No practical usages can be thought of.
+ *
+ * @param[out] obj Object to clear its finalisers.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @return The passed `obj`.
+ * @post `obj` has no finalisers.
+ * @note There is no way to undefine a specific part of many finalisers
+ * that `obj` could have. All you can do is to clear them all.
+ */
+VALUE rb_undefine_finalizer(VALUE obj);
+
+/**
+ * Identical to rb_gc_stat(), with "count" parameter.
+ *
+ * @return Lifetime total number of runs of GC.
+ */
size_t rb_gc_count(void);
-size_t rb_gc_stat(VALUE);
-VALUE rb_gc_latest_gc_info(VALUE);
-void rb_gc_adjust_memory_usage(ssize_t);
+
+/**
+ * Obtains various GC related profiles. The parameter can be either a Symbol
+ * or a Hash. If a Hash is passed, it is filled with everything currently
+ * available. If a Symbol is passed just that portion is returned.
+ *
+ * Possible variations of keys you can pass here change from version to
+ * version. You can get the list of known keys by passing an empty hash and
+ * let it be filled.
+ *
+ * @param[in,out] key_or_buf A Symbol, or a Hash.
+ * @exception rb_eTypeError Neither Symbol nor Hash.
+ * @exception rb_eFrozenError Frozen hash is passed.
+ * @return In case a Hash is passed it returns 0. Otherwise the
+ * profile value associated with the given key is returned.
+ * @post In case a Hash is passed it is filled with values.
+ */
+size_t rb_gc_stat(VALUE key_or_buf);
+
+/**
+ * Obtains various info regarding the most recent GC run. This includes for
+ * instance the reason of the GC. The parameter can be either a Symbol or a
+ * Hash. If a Hash is passed, it is filled with everything currently
+ * available. If a Symbol is passed just that portion is returned.
+ *
+ * Possible variations of keys you can pass here change from version to
+ * version. You can get the list of known keys by passing an empty hash and
+ * let it be filled.
+ *
+ * @param[in,out] key_or_buf A Symbol, or a Hash.
+ * @exception rb_eTypeError Neither Symbol nor Hash.
+ * @exception rb_eFrozenError Frozen hash is passed.
+ * @return In case a Hash is passed it returns that hash. Otherwise
+ * the profile value associated with the given key is returned.
+ * @post In case a Hash is passed it is filled with values.
+ */
+VALUE rb_gc_latest_gc_info(VALUE key_or_buf);
+
+/**
+ * Informs that there are external memory usages. Our GC runs when we are
+ * running out of memory. The amount of memory, however, can increase/decrease
+ * behind-the-scene. For instance DLLs can allocate memories using `mmap(2)`
+ * etc, which are opaque to us. Registering such external allocations using
+ * this function enables proper detection of how much memories an object used
+ * as a whole. That will trigger GCs more often than it would otherwise. You
+ * can also pass negative numbers here, to indicate that such external
+ * allocations are gone.
+ *
+ * @param[in] diff Amount of memory increased(+)/decreased(-).
+ */
+void rb_gc_adjust_memory_usage(ssize_t diff);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/hash.h b/include/ruby/internal/intern/hash.h
index 70c37917f1..af8dfd5d8f 100644
--- a/include/ruby/internal/intern/hash.h
+++ b/include/ruby/internal/intern/hash.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cHash.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/st.h"
@@ -27,31 +28,292 @@
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);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_st_foreach(), except it raises exceptions when the callback
+ * function tampers the table during iterating over it.
+ *
+ * @param[in] st Table to iterate over.
+ * @param[in] func Callback function to apply.
+ * @param[in] arg Passed as-is to `func`.
+ * @exception rb_eRuntimeError `st` was tampered during iterating.
+ *
+ * @internal
+ *
+ * This is declared here because exceptions are Ruby level concept.
+ *
+ * This is in fact a very thin wrapper of rb_st_foreach_check().
+ */
+void rb_st_foreach_safe(struct st_table *st, st_foreach_callback_func *func, st_data_t arg);
+
+/** @alias{rb_st_foreach_safe} */
#define st_foreach_safe rb_st_foreach_safe
-VALUE rb_check_hash_type(VALUE);
-void rb_hash_foreach(VALUE, int (*)(VALUE, VALUE, VALUE), VALUE);
-VALUE rb_hash(VALUE);
+
+/**
+ * Try converting an object to its hash representation using its `to_hash`
+ * method, if any. If there is no such thing, returns ::RUBY_Qnil.
+ *
+ * @param[in] obj Arbitrary ruby object to convert.
+ * @exception rb_eTypeError `obj.to_hash` returned something non-Hash.
+ * @retval RUBY_Qnil No conversion from `obj` to hash defined.
+ * @retval otherwise Converted hash representation of `obj`.
+ * @see rb_io_check_io
+ * @see rb_check_array_type
+ * @see rb_check_string_type
+ *
+ * @internal
+ *
+ * There is no rb_hash_to_hash() that analogous to rb_str_to_str().
+ * Intentional or ...?
+ */
+VALUE rb_check_hash_type(VALUE obj);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Iterates over a hash. This basically does the same thing as
+ * rb_st_foreach(). But because the passed hash is a Ruby object, its keys and
+ * values are both Ruby objects.
+ *
+ * @param[in] hash An instance of ::rb_cHash to iterate over.
+ * @param[in] func Callback function to yield.
+ * @param[in] arg Passed as-is to `func`.
+ * @exception rb_eRuntimeError `hash` was tampered during iterating.
+ */
+void rb_hash_foreach(VALUE hash, int (*func)(VALUE key, VALUE val, VALUE arg), VALUE arg);
+
+/**
+ * Calculates a message authentication code of the passed object. The return
+ * value is a very small integer used as an index of a key of a table. In
+ * order to calculate the value this function calls `#hash` method of the
+ * passed object. Ruby provides you a default implementation. But if you
+ * implement your class in C, that default implementation cannot know the
+ * underlying data structure. You must implement your own `#hash` method then,
+ * which must return an integer of uniform distribution in a sufficiently
+ * instant manner.
+ *
+ * @param[in] obj Arbitrary Ruby object.
+ * @exception rb_eTypeError `obj.hash` returned something non-Integer.
+ * @return A small integer.
+ * @note `#hash` can return very big integers, but they get truncated.
+ */
+VALUE rb_hash(VALUE obj);
+
+/**
+ * Creates a new, empty hash object.
+ *
+ * @return An allocated new instance of ::rb_cHash.
+ */
VALUE rb_hash_new(void);
-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);
+
+/**
+ * Identical to rb_hash_new(), except it additionally specifies how many keys
+ * it is expected to contain. This way you can create a hash that is large enough
+ * for your need. For large hashes it means it won't need to be reallocated and
+ * rehashed as much, improving performance.
+ *
+ * @param[in] capa Designed capacity of the hash.
+ * @return An empty Hash, whose capacity is `capa`.
+ */
+VALUE rb_hash_new_capa(long capa);
+
+/**
+ * Duplicates a hash.
+ *
+ * @param[in] hash An instance of ::rb_cHash.
+ * @return An allocated new instance of ::rb_cHash, whose contents are
+ * a verbatim copy of from `hash`.
+ */
+VALUE rb_hash_dup(VALUE hash);
+
+/** @alias{rb_obj_freeze} */
+VALUE rb_hash_freeze(VALUE obj);
+
+/**
+ * Queries the given key in the given hash table. If there is the key in the
+ * hash, returns the value associated with the key. Otherwise it returns the
+ * "default" value (defined per hash table).
+ *
+ * @param[in] hash Hash table to look into.
+ * @param[in] key Hash key to look for.
+ * @return Either the value associated with the key, or the default one if
+ * absent.
+ */
+VALUE rb_hash_aref(VALUE hash, VALUE key);
+
+/**
+ * Identical to rb_hash_aref(), except it always returns ::RUBY_Qnil for
+ * misshits.
+ *
+ * @param[in] hash Hash table to look into.
+ * @param[in] key Hash key to look for.
+ * @return Either the value associated with the key, or ::RUBY_Qnil if
+ * absent.
+ * @note A hash can store ::RUBY_Qnil as an ordinary value. You cannot
+ * distinguish whether the key is missing, or just its associated
+ * value happens to be ::RUBY_Qnil, as far as you use this API.
+ */
+VALUE rb_hash_lookup(VALUE hash, VALUE key);
+
+/**
+ * Identical to rb_hash_lookup(), except you can specify what to return on
+ * misshits. This is much like 2-arguments version of `Hash#fetch`.
+ *
+ * ```CXX
+ * VALUE hash;
+ * VALUE key;
+ * VALUE tmp = rb_obj_alloc(rb_cObject);
+ * VALUE val = rb_hash_lookup2(hash, key, tmp);
+ * if (val == tmp) {
+ * printf("misshit");
+ * }
+ * else {
+ * printf("hit");
+ * }
+ * ```
+ *
+ * @param[in] hash Hash table to look into.
+ * @param[in] key Hash key to look for.
+ * @param[in] def Default value.
+ * @retval def `hash` does not have `key`.
+ * @retval otherwise The value associated with `key`.
+ */
+VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def);
+
+/**
+ * Identical to rb_hash_lookup(), except it yields the (implicitly) passed
+ * block instead of returning ::RUBY_Qnil.
+ *
+ * @param[in] hash Hash table to look into.
+ * @param[in] key Hash key to look for.
+ * @exception rb_eKeyError No block given.
+ * @return Either the value associated with the key, or what the block
+ * evaluates to if absent.
+ */
+VALUE rb_hash_fetch(VALUE hash, VALUE key);
+
+/**
+ * Inserts or replaces ("upsert"s) the objects into the given hash table. This
+ * basically associates the given value with the given key. On duplicate key
+ * this function updates its associated value with the given one. Otherwise it
+ * inserts the association at the end of the table.
+ *
+ * @param[out] hash Target hash table to modify.
+ * @param[in] key Arbitrary Ruby object.
+ * @param[in] val A value to be associated with `key`.
+ * @exception rb_eFrozenError `hash` is frozen.
+ * @return The passed `val`
+ * @post `val` is associated with `key` in `hash`.
+ */
+VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val);
+
+/**
+ * Swipes everything out of the passed hash table.
+ *
+ * @param[out] hash Target to clear.
+ * @exception rb_eFrozenError `hash`is frozen.
+ * @return The passed `hash`
+ * @post `hash` has no contents.
+ */
+VALUE rb_hash_clear(VALUE hash);
+
+/**
+ * Deletes each entry for which the block returns a truthy value. If there is
+ * no block given, it returns an enumerator that does the thing.
+ *
+ * @param[out] hash Target hash to modify.
+ * @exception rb_eFrozenError `hash` is frozen.
+ * @retval hash The hash is modified.
+ * @retval otherwise An instance of ::rb_cEnumerator that does it.
+ */
+VALUE rb_hash_delete_if(VALUE hash);
+
+/**
+ * Deletes the passed key from the passed hash table, if any.
+ *
+ * @param[out] hash Target hash to modify.
+ * @param[in] key Key to delete.
+ * @retval RUBY_Qnil `hash` has no such key as `key`.
+ * @retval otherwise What was associated with `key`.
+ * @post `hash` has no such key as `key`.
+ */
+VALUE rb_hash_delete(VALUE hash, VALUE key);
+
+/**
+ * Inserts a list of key-value pairs into a hash table at once. It is
+ * semantically identical to repeatedly calling rb_hash_aset(), but can be
+ * faster than that.
+ *
+ * @param[in] argc Length of `argv`, must be even.
+ * @param[in] argv A list of key, value, key, value, ...
+ * @param[out] hash Target hash table to modify.
+ * @post `hash` has contents from `argv`.
+ * @note `argv` is allowed to be NULL as long as `argc` is zero.
+ *
+ * @internal
+ *
+ * What happens for duplicated keys? Well it silently discards older ones to
+ * accept the newest (rightmost) one. This behaviour also mimics repeated call
+ * of rb_hash_aset().
+ */
+void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash);
+
+/**
+ * Type of callback functions to pass to rb_hash_update_by().
+ *
+ * @param[in] newkey A key of the table.
+ * @param[in] oldkey Value associated with `key` in hash1.
+ * @param[in] value Value associated with `key` in hash2.
+ * @return Either one of the passed values to take.
+ */
typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value);
+
+/**
+ * Destructively merges two hash tables into one. It resolves key conflicts by
+ * calling the passed function and take its return value.
+ *
+ * @param[out] hash1 Target hash to be modified.
+ * @param[in] hash2 A hash to merge into `hash1`.
+ * @param[in] func Conflict reconciler.
+ * @exception rb_eFrozenError `hash1` is frozen.
+ * @exception rb_eRuntimeError `hash2` is updated instead.
+ * @return The passed `hash1`.
+ * @post Contents of `hash2` is merged into `hash1`.
+ * @note You can pass zero to `func`. This means values from `hash2`
+ * are always taken.
+ */
VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func);
-struct st_table *rb_hash_tbl(VALUE, const char *file, int line);
-int rb_path_check(const char*);
-int rb_env_path_tainted(void);
+
+/* file.c */
+
+/**
+ * This function is mysterious. What it does is not immediately obvious. Also
+ * what it does seems platform dependent.
+ *
+ * @param[in] path A local path.
+ * @retval 0 The "check" succeeded.
+ * @retval otherwise The "check" failed.
+ */
+int rb_path_check(const char *path);
+
+/* hash.c */
+
+/**
+ * Destructively removes every environment variables of the running process.
+ *
+ * @return The `ENV` object.
+ * @post The process has no environment variables.
+ */
VALUE rb_env_clear(void);
-VALUE rb_hash_size(VALUE);
+
+/**
+ * Identical to #RHASH_SIZE(), except it returns the size in Ruby's integer
+ * instead of C's.
+ *
+ * @param[in] hash A hash object.
+ * @return The size of the hash.
+ */
+VALUE rb_hash_size(VALUE hash);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/io.h b/include/ruby/internal/intern/io.h
index d2f2e53486..02c249723e 100644
--- a/include/ruby/internal/intern/io.h
+++ b/include/ruby/internal/intern/io.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cIO.
*/
#include "ruby/internal/dllexport.h"
@@ -26,43 +26,634 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* io.c */
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define rb_defout rb_stdout
+
+/* string.c */ /* ...why? moved in commit de7161526014b781468cea5d84411e23be */
+
+/**
+ * The field separator character for inputs, or the `$;`. This affects how
+ * `String#split` works. You can set this via the `-F` command line option.
+ * You can also assign arbitrary ruby objects programmatically, but it makes
+ * best sense for you to assign a regular expression here.
+ *
+ * @internal
+ *
+ * Tidbit: "fs" comes from AWK's `FS` variable.
+ */
RUBY_EXTERN VALUE rb_fs;
+
+/* io.c */ /* ...why? given rb_fs is in string.c? */
+
+/**
+ * The field separator character for outputs, or the `$,`. This affects how
+ * `Array#join` works.
+ *
+ * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is
+ * deprecated.
+ */
RUBY_EXTERN VALUE rb_output_fs;
+
+/**
+ * The record separator character for inputs, or the `$/`. This affects how
+ * `IO#gets` works. You can set this via the `-0` command line option.
+ *
+ * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is
+ * deprecated.
+ *
+ * @internal
+ *
+ * Tidbit: "rs" comes from AWK's `RS` variable.
+ */
RUBY_EXTERN VALUE rb_rs;
+
+/**
+ * This is the default value of ::rb_rs, i.e. `"\n"`. It seems it has always
+ * been just a newline string since the beginning. Not sure why C codes has to
+ * use this, given there is no way for ruby programs to interface.
+ *
+ * Also it has not been deprecated for unknown reasons.
+ */
RUBY_EXTERN VALUE rb_default_rs;
+
+/**
+ * The record separator character for outputs, or the `$\`. This affects how
+ * `IO#print` works.
+ *
+ * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is
+ * deprecated.
+ */
RUBY_EXTERN VALUE rb_output_rs;
-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*);
+
+/**
+ * Writes the given string to the given IO.
+ *
+ * @param[out] io An IO, opened for writing.
+ * @param[in] str A String-like object to write to `io`.
+ * @exception rb_eIOError `io` isn't opened for writing.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `str` to String.
+ * @exception rb_eSystemCallError `write(2)` failed for some reason.
+ * @return The number of bytes written to the `io`.
+ * @post `str` (up to the length of return value) is written to `io`.
+ * @note This function blocks.
+ * @note Partial write is a thing. It must be at least questionable not
+ * to check the return value.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This function can take arbitrary
+ * objects, and calls their `write` method. What is written above in fact
+ * describes how `IO#write` works. You can pass StringIO etc. here, and would
+ * work completely differently.
+ */
+VALUE rb_io_write(VALUE io, VALUE str);
+
+/**
+ * Reads a "line" from the given IO. A line here means a chunk of characters
+ * which is terminated by either `"\n"` or an EOF.
+ *
+ * @param[in,out] io An IO, opened for reading.
+ * @exception rb_eIOError `io` isn't opened for reading.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @retval RUBY_Qnil `io` is at EOF.
+ * @retval otherwise An instance of ::rb_cString.
+ * @post `io` is read.
+ * @note Unlike `IO#gets` it doesn't set `$_`.
+ * @note Unlike `IO#gets` it doesn't consider `$/`.
+ */
+VALUE rb_io_gets(VALUE io);
+
+/**
+ * Reads a byte from the given IO.
+ *
+ * @note In Ruby a "byte" always means an 8 bit integer ranging from
+ * 0 to 255 inclusive.
+ * @param[in,out] io An IO, opened for reading.
+ * @exception rb_eIOError `io` is not opened for reading.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @retval RUBY_Qnil `io` is at EOF.
+ * @retval otherwise An instance of ::rb_cInteger.
+ * @post `io` is read.
+ *
+ * @internal
+ *
+ * Of course there was a function called `rb_io_getc()`. It was removed in
+ * commit a25fbe3b3e531bbe479f344af24eaf9d2eeae6ea.
+ */
+VALUE rb_io_getbyte(VALUE io);
+
+/**
+ * "Unget"s a string. This function pushes back the passed string onto the
+ * passed IO, such that a subsequent buffered read will return it. If the
+ * passed content is in fact an integer, a single character string of that
+ * codepoint of the encoding of the IO will be pushed back instead.
+ *
+ * It might be counter-intuitive but this function can push back multiple
+ * characters at once. Also this function can be called multiple times on a
+ * same IO. Also a "character" can be wider than a byte, depending on the
+ * encoding of the IO.
+ *
+ * @param[out] io An IO, opened for reading.
+ * @param[in] c Either a String, or an Integer.
+ * @exception rb_eIOError `io` is not opened for reading.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `c` to ::rb_cString.
+ * @return Always returns ::RUBY_Qnil.
+ *
+ * @internal
+ *
+ * Why there is ungetc, given there is no getc?
+ */
+VALUE rb_io_ungetc(VALUE io, VALUE c);
+
+/**
+ * Identical to rb_io_ungetc(), except it doesn't take the encoding of the
+ * passed IO into account. When an integer is passed, it just casts that value
+ * to C's `unsigned char`, and pushes that back.
+ *
+ * @param[out] io An IO, opened for reading.
+ * @param[in] b Either a String, or an Integer.
+ * @exception rb_eIOError `io` is not opened for reading.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `b` to ::rb_cString.
+ * @return Always returns ::RUBY_Qnil.
+ */
+VALUE rb_io_ungetbyte(VALUE io, VALUE b);
+
+/**
+ * Closes the IO. Any buffered contents are flushed to the operating system.
+ * Any future operations against the IO would raise ::rb_eIOError. In case the
+ * io was created using `IO.popen`, it also sets the `$?`.
+ *
+ * @param[out] io Target IO to close.
+ * @return Always returns ::RUBY_Qnil.
+ * @post `$?` is set in case IO is a pipe.
+ * @post No operations are possible against `io` any further.
+ * @note This can block to flush the contents.
+ * @note This can wake other threads up, especially those who are
+ * `select()`-ing the passed IO.
+ * @note Multiple invocations of this function over the same IO again
+ * and again is not an error, since Ruby 2.3.
+ *
+ * @internal
+ *
+ * You can close a frozen IO... Is this intentional?
+ */
+VALUE rb_io_close(VALUE io);
+
+/**
+ * Flushes any buffered data within the passed IO to the underlying operating
+ * system.
+ *
+ * @param[out] io Target IO to flush.
+ * @exception rb_eIOError `io` is closed.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eSystemCallError `write(2)` failed for some reason.
+ * @return The passed `io`.
+ * @post `io`'s buffers are empty.
+ * @note This operation also discards the read buffer. Should basically
+ * be harmless, but in an esoteric situation like when user pushed
+ * something different from what was read using `ungetc`, this
+ * operation in fact changes the behaviour of the `io`.
+ * @note Buffering is difficult. This operation flushes the data from
+ * our userspace to the kernel, but that doesn't always mean you
+ * can expect them stored persistently onto your hard drive.
+ */
+VALUE rb_io_flush(VALUE io);
+
+/**
+ * Queries if the passed IO is at the end of file. "The end of file" here mans
+ * that there are no more data to read. This function blocks until the read
+ * buffer is filled in, and if that operation reached the end of file, it still
+ * returns ::RUBY_Qfalse (because there are data yet in that buffer). It
+ * returns ::RUBY_Qtrue once after the buffer is cleared.
+ *
+ * @param[in,out] io Target io to query.
+ * @exception rb_eIOError `io` is not opened for reading.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @retval RUBY_Qfalse There are things yet to be read.
+ * @retval RUBY_Qtrue "The end of file" situation.
+ */
+VALUE rb_io_eof(VALUE io);
+
+/**
+ * Sets the binmode. This operation nullifies the effect of textmode (newline
+ * conversion from `"\r\n"` to `"\n"` or vice versa). Note that it doesn't
+ * stop character encodings conversions. For instance an IO created using:
+ *
+ * ```ruby
+ * File.open(
+ * "/dev/urandom",
+ * textmode: true,
+ * external_encoding: Encoding::GB18030,
+ * internal_encoding: Encoding::Windows_31J)
+ * ```
+ *
+ * has both newline and character conversions. If you pass such IO to this
+ * function, only the `textmode:true` part is cancelled. Texts read through
+ * the IO would still be encoded in Windows-31J; texts written to the IO will
+ * be encoded in GB18030.
+ *
+ * @param[out] io Target IO to modify.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @return The passed `io`.
+ * @post `io` is in binmode.
+ * @note There is no equivalent operation in Ruby. You can do this only
+ * in C.
+ */
+VALUE rb_io_binmode(VALUE io);
+
+/**
+ * Forces no conversions be applied to the passed IO. Unlike rb_io_binmode(),
+ * this cancels any newline conversions as well as encoding conversions. Any
+ * texts read/written through the IO will be the verbatim binary contents.
+ *
+ * @param[out] io Target IO to modify.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @return The passed `io`.
+ * @post `io` is in binmode. Both external/internal encoding are set to
+ * rb_ascii8bit_encoding().
+ * @note This is the implementation of `IO#binmode`.
+ */
+VALUE rb_io_ascii8bit_binmode(VALUE io);
+
+/**
+ * Identical to rb_io_write(), except it always returns the passed IO.
+ *
+ * @param[out] io An IO, opened for writing.
+ * @param[in] str A String-like object to write to `io`.
+ * @exception rb_eIOError `io` isn't opened for writing.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `str` to String.
+ * @exception rb_eSystemCallError `write(2)` failed.
+ * @return The passed `io`.
+ * @post `str` is written to `io`.
+ * @note This function blocks.
+ *
+ * @internal
+ *
+ * As rb_io_write(), above description is a fake.
+ */
+VALUE rb_io_addstr(VALUE io, VALUE str);
+
+/**
+ * This is a rb_f_sprintf() + rb_io_write() combo.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv A format string followed by its arguments.
+ * @param[out] io An IO, opened for writing.
+ * @exception rb_eIOError `io` isn't opened for writing.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `str` to String.
+ * @exception rb_eSystemCallError `write(2)` failed.
+ * @return Always returns ::RUBY_Qnil.
+ * @post `argv` is formatted, then written to `io`.
+ * @note This function blocks.
+ *
+ * @internal
+ *
+ * As rb_io_write(), above descriptions include fakes.
+ */
+VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io);
+
+/**
+ * Iterates over the passed array to apply rb_io_write() individually. If
+ * there is `$,`, this function inserts the string in middle of each
+ * iterations. If there is `$\`, this function appends the string at the end.
+ * If the array is empty, this function outputs `$_`.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv An array of strings to display.
+ * @param[out] io An IO, opened for writing.
+ * @exception rb_eIOError `io` isn't opened for writing.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `str` to String.
+ * @exception rb_eSystemCallError `write(2)` failed.
+ * @return Always returns ::RUBY_Qnil.
+ * @post `argv` is written to `io`.
+ * @note This function blocks.
+ * @note This function calls rb_io_write() multiple times. Which means,
+ * it is not an atomic operation. Outputs from multiple threads
+ * can interleave.
+ *
+ * @internal
+ *
+ * As rb_io_write(), above descriptions include fakes.
+ */
+VALUE rb_io_print(int argc, const VALUE *argv, VALUE io);
+
+/**
+ * Iterates over the passed array to apply rb_io_write() individually. Unlike
+ * rb_io_print(), this function prints a newline per each element. It also
+ * flattens the passed array (OTOH rb_io_print() just resorts to
+ * rb_ary_to_s()).
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv An array of strings to display.
+ * @param[out] io An IO, opened for writing.
+ * @exception rb_eIOError `io` isn't opened for writing.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eTypeError No conversion from `str` to String.
+ * @exception rb_eSystemCallError `write(2)` failed.
+ * @return Always returns ::RUBY_Qnil.
+ * @post `argv` is written to `io`.
+ * @note This function blocks.
+ * @note This function calls rb_io_write() multiple times. Which means,
+ * it is not an atomic operation. Outputs from multiple threads
+ * can interleave.
+ *
+ * @internal
+ *
+ * As rb_io_write(), above descriptions include fakes.
+ */
+VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io);
+
+/**
+ * Creates an IO instance whose backend is the given file descriptor. C
+ * extension libraries sometimes have file descriptors created elsewhere (maybe
+ * deep inside of another shared library), which they want ruby programs to
+ * handle. This function is handy for such situations.
+ *
+ * @param[in] fd Target file descriptor.
+ * @param[in] flags Flags, e.g. `O_CREAT|O_EXCL`
+ * @param[in] path The path of the file that backs `fd`, for diagnostics.
+ * @return An allocated instance of ::rb_cIO.
+ * @note Leave `path` NULL if you don't know.
+ */
+VALUE rb_io_fdopen(int fd, int flags, const char *path);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Opens a file located at the given path.
+ *
+ * `fmode` is a C string that represents the open mode. It can be one of:
+ *
+ * - `r` (means `O_RDONLY`),
+ * - `w` (means `O_WRONLY | O_TRUNC | O_CREAT`),
+ * - `a` (means `O_WRONLY | O_APPEND | O_CREAT`),
+ *
+ * Followed by zero or more combinations of:
+ *
+ * - `b` (means `_O_BINARY`),
+ * - `t` (means `_O_TEXT`),
+ * - `+` (means `O_RDWR`),
+ * - `x` (means `O_TRUNC`), or
+ * - `:[BOM|]enc[:enc]` (see below).
+ *
+ * This last one specifies external (and internal if any) encodings,
+ * respectively. If optional `BOM|` is specified and the specified external
+ * encoding is capable of expressing BOMs, opening file's contents' byte order
+ * is auto-detected using the mechanism.
+ *
+ * So for instance, fmode of `"rt|BOM:utf-16le:utf-8"` specifies that...
+ *
+ * - the physical representation of the contents of the file is in UTF-16;
+ * - honours its BOM but assumes little endian if absent;
+ * - opens the file for reading;
+ * - what is read is converted into UTF-8;
+ * - with newlines cannibalised to `\n`.
+ *
+ * @param[in] fname Path to open.
+ * @param[in] fmode Mode specifier much like `fopen(3)`.
+ * @exception rb_eArgError `fmode` contradicted (e.g. `"bt"`).
+ * @exception rb_eSystemCallError `open(2)` failed for some reason.
+ * @return An instance of ::rb_cIO.
+ */
+VALUE rb_file_open(const char *fname, const char *fmode);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_file_open(), except it takes the pathname as a Ruby's string
+ * instead of C's. In case the passed Ruby object is a non-String it tries to
+ * call `#to_path`.
+ *
+ * @param[in] fname Path to open.
+ * @param[in] fmode Mode specifier much like `fopen(3)`.
+ * @exception rb_eTypeError `fname` is not a String.
+ * @exception rb_eEncCompatError `fname` is not ASCII-compatible.
+ * @exception rb_eArgError `fmode` contradicted (e.g. `"bt"`).
+ * @exception rb_eSystemCallError `open(2)` failed for some reason.
+ * @return An instance of ::rb_cIO.
+ */
+VALUE rb_file_open_str(VALUE fname, const char *fmode);
+
+/**
+ * Much like rb_io_gets(), but it reads from the mysterious ARGF object. ARGF
+ * in this context can be seen as a virtual IO which concatenates contents of
+ * the files passed to the process via the ARGV, or just STDIN if there are no
+ * such files.
+ *
+ * Unlike rb_io_gets() this function sets `$_`.
+ *
+ * @exception rb_eFrozenError ARGF resorts to STDIN but it is frozen.
+ * @retval RUBY_Qnil ARGF is at EOF.
+ * @retval otherwise An instance of ::rb_cString.
+ * @post ARGF is read.
+ * @post `$_` is set.
+ *
+ * @internal
+ *
+ * In reality, this function can call `ARGF.gets`. Its redefinition can affect
+ * the behaviour.
+ *
+ * Also, you can tamper ARGV on-the-fly in middle of ARGF usages:
+ *
+ * ```
+ * gets # Reads the first file.
+ * ARGV << '/proc/self/limits' # Adds a file.
+ * gets # Can read from /proc/self/limits.
+ * ```
+ */
VALUE rb_gets(void);
-void rb_write_error(const char*);
-void rb_write_error2(const char*, long);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Writes the given error message to somewhere applicable. On Windows it goes
+ * to the console. On POSIX environments it goes to the standard error.
+ *
+ * @warning IT IS A BAD IDEA to use this function form your C extensions.
+ * It is often annoying when GUI applications write to consoles;
+ * users don't want to look at there. Programmers also want to
+ * control the cause of the message itself, like by rescuing an
+ * exception. Just let ruby handle errors. That must be better than
+ * going your own way.
+ *
+ * @param[in] str Error message to display.
+ * @post `str` is written to somewhere.
+ *
+ * @internal
+ *
+ * AFAIK this function is listed here without marked deprecated because there
+ * are usages of this function in the wild.
+ */
+void rb_write_error(const char *str);
+
+/**
+ * Identical to rb_write_error(), except it additionally takes the message's
+ * length. Necessary when you want to handle wide characters.
+ *
+ * @param[in] str Error message to display.
+ * @param[in] len Length of `str`, in bytes.
+ * @post `str` is written to somewhere.
+ */
+void rb_write_error2(const char *str, long len);
+
+/**
+ * Closes everything. In case of POSIX environments, a child process inherits
+ * its parent's opened file descriptors. Which is nowadays considered as one
+ * of the UNIX mistakes. This function closes such inherited file descriptors.
+ * When your C extension needs to have a child process, don't forget to call
+ * this from your child process right before exec.
+ *
+ * @param[in] lowfd Lower bound of FDs (you want STDIN to remain, no?).
+ * @param[in] maxhint Hint of max FDs.
+ * @param[in] noclose_fds A hash, whose keys are an allowlist.
+ *
+ * @internal
+ *
+ * As of writing, in spite of the name, this function does not actually close
+ * anything. It just sets `FD_CLOEXEC` for everything and let `execve(2)` to
+ * atomically close them at once. This is because as far as we know there are
+ * no such platform that has `fork(2)` but lacks `FD_CLOEXEC`.
+ *
+ * Because this function is expected to run on a forked process it is entirely
+ * async-signal-safe.
+ */
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is an rb_cloexec_pipe() + rb_update_max_fd() combo.
+ *
+ * @param[out] pipes Return buffer. Must at least hold 2 elements.
+ * @retval 0 Successful creation of a pipe.
+ * @retval -1 Failure in underlying system call(s).
+ * @post `pipes` is filled with file descriptors.
+ * @post `errno` is set on failure.
+ */
int rb_pipe(int *pipes);
+
+/**
+ * Queries if the given FD is reserved or not. Occasionally Ruby interpreter
+ * opens files for its own purposes. Use this function to prevent touching
+ * such behind-the-scene descriptors.
+ *
+ * @param[in] fd Target file descriptor.
+ * @retval 1 `fd` is reserved.
+ * @retval 0 Otherwise.
+ */
int rb_reserved_fd_p(int fd);
+
+/** @alias{rb_reserved_fd_p} */
+#define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd)
+
+/**
+ * Opens a file that closes on exec. In case of POSIX environments, a child
+ * process inherits its parent's opened file descriptors. Which is nowadays
+ * considered as one of the UNIX mistakes. This function opens a file
+ * descriptor as `open(2)` does, but additionally instructs the operating
+ * system that we don't want it be seen from child processes.
+ *
+ * @param[in] pathname File path to open.
+ * @param[in] flags Open mode, as in `open(2)`.
+ * @param[in] mode File mode, in case of `O_CREAT`.
+ * @retval -1 `open(2)` failed for some reason.
+ * @retval otherwise An allocated new file descriptor.
+ * @note This function does not raise.
+ *
+ * @internal
+ *
+ * Whether this function can take NULL or not depends on the underlying open(2)
+ * system call implementation but @shyouhei doesn't think it's worth trying.
+ */
int rb_cloexec_open(const char *pathname, int flags, mode_t mode);
+
+/**
+ * Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3.
+ *
+ * @param[in] oldfd File descriptor to duplicate.
+ * @retval -1 `dup2(2)` failed for some reason.
+ * @retval otherwise An allocated new file descriptor.
+ * @note This function does not raise.
+ */
int rb_cloexec_dup(int oldfd);
+
+/**
+ * Identical to rb_cloexec_dup(), except you can specify the destination file
+ * descriptor. If the destination is already squatted by another file
+ * descriptor that gets silently closed without any warnings. (This is a spec
+ * requested by POSIX.)
+ *
+ * @param[in] oldfd File descriptor to duplicate.
+ * @param[in] newfd Return value destination.
+ * @retval -1 `dup2(2)` failed for some reason.
+ * @retval newfd An allocated new file descriptor.
+ * @post Whatever sat at `newfd` gets closed with no notifications.
+ * @post In case return value is -1 `newfd` is untouched.
+ * @note This function does not raise.
+ */
int rb_cloexec_dup2(int oldfd, int newfd);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Opens a pipe with closing on exec. In case of POSIX environments, a child
+ * process inherits its parent's opened file descriptors. Which is nowadays
+ * considered as one of the UNIX mistakes. This function opens a pipe as
+ * `pipe(2)` does, but additionally instructs the operating system that we
+ * don't want the duplicated FDs be seen from child processes.
+ *
+ * @param[out] fildes Return buffer. Must at least hold 2 elements.
+ * @retval 0 Successful creation of a pipe.
+ * @retval -1 Failure in underlying system call(s).
+ * @post `pipes` is filled with file descriptors.
+ * @post `errno` is set on failure.
+ */
int rb_cloexec_pipe(int fildes[2]);
+
+/**
+ * Duplicates a file descriptor with closing on exec. In case of POSIX
+ * environments, a child process inherits its parent's opened file descriptors.
+ * Which is nowadays considered as one of the UNIX mistakes. This function
+ * duplicates a file descriptor as `dup(2)` does, but additionally instructs
+ * the operating system that we don't want the duplicated FD be seen from child
+ * processes.
+ *
+ * @param[in] fd File descriptor to duplicate.
+ * @param[in] minfd Minimum allowed FD to return.
+ * @retval -1 `dup(2)` failed for some reason.
+ * @retval otherwise An allocated new file descriptor.
+ * @note This function does not raise.
+ *
+ * `minfd` is handy when for instance STDERR is closed but you don't want to
+ * use fd 2.
+ */
int rb_cloexec_fcntl_dupfd(int fd, int minfd);
-#define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd)
+
+/**
+ * Informs the interpreter that the passed fd can be the max. This information
+ * is used from rb_close_before_exec().
+ *
+ * @param[in] fd An open FD, which can be large.
+ */
void rb_update_max_fd(int fd);
+
+/**
+ * Sets or clears the close-on-exec flag of the passed file descriptor to the
+ * desired state. STDIN, STDOUT, STDERR are the exceptional file descriptors
+ * that shall remain open. All others are to be closed on exec. When a C
+ * extension library opens a file descriptor using anything other than
+ * rb_cloexec_open() etc., that file descriptor shall experience this function.
+ *
+ * @param[in] fd An open file descriptor.
+ */
void rb_fd_fix_cloexec(int fd);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/load.h b/include/ruby/internal/intern/load.h
index 2cc5be0ebe..288a16c2ec 100644
--- a/include/ruby/internal/intern/load.h
+++ b/include/ruby/internal/intern/load.h
@@ -17,28 +17,202 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_f_require().
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* load.c */
-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
+
+/**
+ * Loads and executes the Ruby program in the given file.
+ *
+ * If the path is an absolute path (e.g. starts with `'/'`), the file will be
+ * loaded directly using the absolute path. If the path is an explicit
+ * relative path (e.g. starts with `'./'` or `'../'`), the file will be loaded
+ * using the relative path from the current directory. Otherwise, the file
+ * will be searched for in the library directories listed in the `$LOAD_PATH`.
+ * If the file is found in a directory, this function will attempt to load the
+ * file relative to that directory. If the file is not found in any of the
+ * directories in the `$LOAD_PATH`, the file will be loaded using the relative
+ * path from the current directory.
+ *
+ * If the file doesn't exist when there is an attempt to load it, a LoadError
+ * will be raised.
+ *
+ * If the `wrap` parameter is true, the loaded script will be executed under an
+ * anonymous module, protecting the calling program's global namespace. In no
+ * circumstance will any local variables in the loaded file be propagated to
+ * the loading environment.
+ *
+ * @param[in] path Pathname of a file to load.
+ * @param[in] wrap Either to load under an anonymous module.
+ * @exception rb_eTypeError `path` is not a string.
+ * @exception rb_eArgError `path` is broken as a pathname.
+ * @exception rb_eEncCompatError `path` is incompatible with pathnames.
+ * @exception rb_eLoadError `path` not found.
+ * @exception rb_eException Any exceptions while loading the contents.
+ *
+ * @internal
+ *
+ * It seems this function is under the rule of bootsnap's regime?
+ */
+void rb_load(VALUE path, int wrap);
+
+/**
+ * Identical to rb_load(), except it avoids potential global escapes. Such
+ * global escapes include exceptions, `throw`, `break`, for example.
+ *
+ * It first evaluates the given file as rb_load() does. If no global escape
+ * occurred during the evaluation, it `*state` is set to zero on return.
+ * Otherwise, it sets `*state` to nonzero. If state is `NULL`, it is not set
+ * in both cases.
+ *
+ * @param[in] path Pathname of a file to load.
+ * @param[in] wrap Either to load under an anonymous module.
+ * @param[out] state State of execution.
+ * @post `*state` is set to zero if succeeded. Nonzero otherwise.
+ * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if
+ * you decide to ignore the caught exception.
+ * @see rb_load
+ * @see rb_protect
+ *
+ * @internal
+ *
+ * Though not a part of our public API, `state` is in fact an
+ * enum ruby_tag_type. You can see the potential "nonzero" values by looking
+ * at vm_core.h.
+ */
+void rb_load_protect(VALUE path, int wrap, int *state);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries if the given feature has already been loaded into the execution
+ * context. The "feature" head are things like `"json"` or `"socket"`.
+ *
+ * @param[in] feature Name of a library you want to know about.
+ * @retval 1 Yes there is.
+ * @retval 0 Not yet.
+ */
+int rb_provided(const char *feature);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_provided(), except it additionally returns the "canonical"
+ * name of the loaded feature. This can be handy when for instance you want to
+ * know the actually loaded library is either `foo.rb` or `foo.so`.
+ *
+ * @param[in] feature Name of a library you want to know about.
+ * @param[out] loading Return buffer.
+ * @retval 1 Yes there is.
+ * @retval 0 Not yet.
+ */
+int rb_feature_provided(const char *feature, const char **loading);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Declares that the given feature is already provided by someone else. This
+ * API can be handy when you have an extension called `foo.so` which, when
+ * required, also provides functionality of `bar.so`.
+ *
+ * @param[in] feature Name of a library which had already been provided.
+ * @post No further `require` would search `feature`.
+ */
+void rb_provide(const char *feature);
+
+/**
+ * Identical to rb_require_string(), except it ignores the first argument for
+ * no reason. There seems to be no reason for 3rd party extension libraries to
+ * use it.
+ *
+ * @param[in] self Ignored. Can be anything.
+ * @param[in] feature Name of a feature, e.g. `"json"`.
+ * @exception rb_eLoadError No such feature.
+ * @exception rb_eRuntimeError `$"` is frozen; unable to push.
+ * @retval RUBY_Qtrue The feature is loaded for the first time.
+ * @retval RUBY_Qfalse The feature has already been loaded.
+ * @post `$"` is updated.
+ */
+VALUE rb_f_require(VALUE self, VALUE feature);
+
+/**
+ * Finds and loads the given feature, if absent.
+ *
+ * If the feature is an absolute path (e.g. starts with `'/'`), the feature
+ * will be loaded directly using the absolute path. If the feature is an
+ * explicit relative path (e.g. starts with `'./'` or `'../'`), the feature
+ * will be loaded using the relative path from the current directory.
+ * Otherwise, the feature will be searched for in the library directories
+ * listed in the `$LOAD_PATH`.
+ *
+ * If the feature has the extension `".rb"`, it is loaded as a source file; if
+ * the extension is `".so"`, `".o"`, or `".dll"`, or the default shared library
+ * extension on the current platform, Ruby loads the shared library as a Ruby
+ * extension. Otherwise, Ruby tries adding `".rb"`, `".so"`, and so on to the
+ * name until found. If the file named cannot be found, a LoadError will be
+ * raised.
+ *
+ * For extension libraries the given feature may use any shared library
+ * extension. For example, on Linux you can require `"socket.dll"` to actually
+ * load `socket.so`.
+ *
+ * The absolute path of the loaded file is added to `$LOADED_FEATURES`. A file
+ * will not be loaded again if its path already appears in there.
+ *
+ * Any constants or globals within the loaded source file will be available in
+ * the calling program's global namespace. However, local variables will not
+ * be propagated to the loading environment.
+ *
+ * @param[in] feature Name of a feature, e.g. `"json"`.
+ * @exception rb_eLoadError No such feature.
+ * @exception rb_eRuntimeError `$"` is frozen; unable to push.
+ * @retval RUBY_Qtrue The feature is loaded for the first time.
+ * @retval RUBY_Qfalse The feature has already been loaded.
+ * @post `$"` is updated.
+ */
+VALUE rb_require_string(VALUE feature);
+
+/**
+ * @name extension configuration
+ * @{
+ */
+
+/**
+ * Asserts that the extension library that calls this function is aware of
+ * Ractor. Multiple Ractors run without protecting each other. This doesn't
+ * interface well with C programs, unless designed with an in-depth
+ * understanding of how Ractors work. Extension libraries are shut out from
+ * Ractors by default. This API is to bypass that restriction. Once after it
+ * was called, successive calls to rb_define_method() etc. become definitions
+ * of methods that are aware of Ractors. The amendment would be in effect
+ * until the end of rb_require_string() etc.
+ *
+ * @param[in] flag Either the library is aware of Ractors or not.
+ * @post Methods would be callable form Ractors, if `flag` is true.
+ */
void rb_ext_ractor_safe(bool flag);
+
+/** @alias{rb_ext_ractor_safe} */
#define RB_EXT_RACTOR_SAFE(f) rb_ext_ractor_safe(f)
+
+/**
+ * This macro is to provide backwards compatibility. It must be safe to do
+ * something like:
+ *
+ * ```CXX
+ * #ifdef HAVE_RB_EXT_RACTOR_SAFE
+ * rb_ext_ractor_safe(true);
+ * #endif
+ * ```
+ */
#define HAVE_RB_EXT_RACTOR_SAFE 1
+/** @} */
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_INTERN_LOAD_H */
diff --git a/include/ruby/internal/intern/marshal.h b/include/ruby/internal/intern/marshal.h
index 6b0243244e..118d78a4a0 100644
--- a/include/ruby/internal/intern/marshal.h
+++ b/include/ruby/internal/intern/marshal.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to rb_mMarshal.
*/
#include "ruby/internal/dllexport.h"
@@ -26,8 +26,85 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* marshal.c */
-VALUE rb_marshal_dump(VALUE, VALUE);
-VALUE rb_marshal_load(VALUE);
+
+/**
+ * Serialises the given object and all its referring objects, to write them
+ * down to the passed port.
+ *
+ * @param[in] obj Target object to dump.
+ * @param[out] port IO-like destination buffer.
+ * @exception rb_eTypeError `obj` cannot be dumped for some reason.
+ * @exception rb_eRuntimeError `obj` was tampered during dumping.
+ * @exception rb_eArgError Traversal too deep.
+ * @return The passed `port` as-is.
+ * @post Serialised representation of `obj` is written to `port`.
+ * @note `port` is basically an IO but StringIO is also possible.
+ */
+VALUE rb_marshal_dump(VALUE obj, VALUE port);
+
+/**
+ * Deserialises a previous output of rb_marshal_dump() into a network of
+ * objects.
+ *
+ * @param[in,out] port Either IO or String.
+ * @exception rb_eTypeError `port` is in unexpected type.
+ * @exception rb_eArgError Contents of `port` is broken.
+ * @return Object(s) rebuilt using the info from `port`.
+ *
+ * SECURITY CONSIDERATIONS
+ * ========================
+ *
+ * @warning By design, rb_marshal_load() can deserialise almost any
+ * class loaded into the Ruby process. In many cases this can
+ * lead to remote code execution if the Marshal data is loaded
+ * from an untrusted source.
+ * @warning As a result, rb_marshal_load() is not suitable as a general
+ * purpose serialisation format and you should never unmarshal
+ * user supplied input or other untrusted data.
+ * @warning If you need to deserialise untrusted data, use JSON or
+ * another serialisation format that is only able to load
+ * simple, 'primitive' types such as String, Array, Hash, etc.
+ * Never allow user input to specify arbitrary types to
+ * deserialise into.
+ */
+VALUE rb_marshal_load(VALUE port);
+
+/**
+ * Marshal format compatibility layer. Over time, classes evolve, so that
+ * their internal data structure change drastically. For instance an instance
+ * of ::rb_cRange was made of ::RUBY_T_OBJECT in 1.x., but in 3.x it is a
+ * ::RUBY_T_STRUCT now. In order to keep binary compatibility, we "fake" the
+ * marshalled representation to stick to old types. This is the API to enable
+ * that manoeuvre. Here is how:
+ *
+ * First, because you are going to keep backwards compatibility, you need to
+ * retain the old implementation of your class. Rename it, and keep the class
+ * somewhere (for instance rb_register_global_address() could help). Next
+ * create your new class. Do whatever you want.
+ *
+ * Then, this is the key point. Create two new "bridge" functions that convert
+ * the structs back and forth:
+ *
+ * - the "dumper" function that takes an instance of the new class, and
+ * returns an instance of the old one. This is called from
+ * rb_marshal_dump(), to keep it possible for old programs to read your new
+ * data.
+ *
+ * - the "loader" function that takes two arguments, new one and old one, in
+ * that order. rb_marshal_load() calls this function when it finds a
+ * representation of the retained old class. The old one passed to this
+ * function is the reconstructed instance of the old class.
+ * Reverse-engineer that to modify the new one, to have the identical
+ * contents.
+ *
+ * Finally, connect all of them using this function.
+ *
+ * @param[in] newclass The class that needs conversion.
+ * @param[in] oldclass Old implementation of `newclass`.
+ * @param[in] dumper Function that converts `newclass` to `oldclass`.
+ * @param[in] loader Function that converts `oldclass` to `newclass`.
+ * @exception rb_eTypeError `newclass` has no allocator.
+ */
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE));
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/numeric.h b/include/ruby/internal/intern/numeric.h
index effc583756..30863fb0c8 100644
--- a/include/ruby/internal/intern/numeric.h
+++ b/include/ruby/internal/intern/numeric.h
@@ -17,25 +17,191 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cNumeric.
*/
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
-#include "ruby/backward/2/attributes.h"
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
+#define RB_NUM_COERCE_FUNCS_NEED_OPID 1
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* numeric.c */
-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_ATTR_NORETURN()
+RBIMPL_ATTR_COLD()
+/**
+ * Just always raises an exception.
+ *
+ * @exception rb_eZeroDivError Division by zero error.
+ */
+void rb_num_zerodiv(void);
+
+/**
+ * @name Coercion operators.
+ *
+ * What is a coercion? Well Ruby is basically an OOPL but it also has
+ * arithmetic operators. They are implemented in OO manners. For instance
+ * `a+b` is a binary operation `+`, whose receiver is `a`, and whose (sole)
+ * argument is `b`.
+ *
+ * The problem is, you often want `a+b == b+a` to hold. That is easy if both
+ * `a` and `b` belongs to the same class... Ensuring `1 + 2 == 2 + 1` is kind
+ * of intuitive. But if you want `1.0 + 2 == 2 + 1.0`, things start getting
+ * complicated. `1.0+2` is `Float#+`, while `2+1.0` is `Integer#+`. In order
+ * to achieve the equality Float's and Integer's methods must agree with their
+ * behaviours.
+ *
+ * Now. Floats versus Integers situation is still controllable because they
+ * are both built-in. But in Ruby you can define your own numeric classes.
+ * BigDecimal, which is a rubygems gem distributed along with the interpreter,
+ * is one of such examples. Rational was another such example before. In
+ * short you cannot create list of all possible combination of the classes that
+ * could be the operand of `+` operator. Then how do we achieve the
+ * commutativity?
+ *
+ * Here comes the concept of coercion. If a definition of an operator
+ * encounters an object which is unknown to the author, just assumes that the
+ * unknown object knows how to handle the situation. So for instance when
+ * `1+x` has unknown `x`, it lets the `x` handle this.
+ *
+ * ```ruby
+ * class Foo
+ * def +(x)
+ * if we_know_what_is_x? then
+ * ... # handle here
+ * else
+ * y, z = x.coerce self
+ * return y + z
+ * end
+ * end
+ * end
+ * ```
+ *
+ * The `x.coerce` method returns a 2-element array which are "casted" versions
+ * of `x` and `self`.
+ *
+ * @{
+ */
+
+/**
+ * Coerced binary operation. This function first coerces the two objects, then
+ * applies the operation.
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @exception rb_eTypeError Coercion failed for some reason.
+ * @return `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op);
+
+/**
+ * Identical to rb_num_coerce_bin(), except for return values. This function
+ * best suits for comparison operators e.g. `<=>`.
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @retval RUBY_Qnil Coercion failed for some reason.
+ * @retval otherwise `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op);
+
+/**
+ * Identical to rb_num_coerce_cmp(), except for return values. This function
+ * best suits for relationship operators e.g. `<=`.
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @exception rb_eArgError Coercion failed for some reason.
+ * @return `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op);
+
+/**
+ * This one is optimised for bitwise operations, but the API is identical to
+ * rb_num_coerce_bin().
+ *
+ * @param[in] lhs LHS operand.
+ * @param[in] rhs RHS operand.
+ * @param[in] op Operator method name.
+ * @exception rb_eArgError Coercion failed for some reason.
+ * @return `lhs op rhs`, in a coerced way.
+ */
+VALUE rb_num_coerce_bit(VALUE lhs, VALUE rhs, ID op);
+
+/** @} */
+
+/**
+ * Converts a numeric value into a Fixnum. This is not a preserving
+ * conversion; for instance 1.5 would be converted into 1.
+ *
+ * @param[in] val A numeric object.
+ * @exception rb_eTypeError No conversion from `val` to Integer.
+ * @exception rb_eRangeError `val` out of range.
+ * @return A fixnum converted from `val`.
+ *
+ * @internal
+ *
+ * This seems used from nowhere?
+ */
+VALUE rb_num2fix(VALUE val);
+
+/**
+ * Generates a place-value representation of the given Fixnum, with given
+ * radix.
+ *
+ * @param[in] val A fixnum to stringify.
+ * @param[in] base `2` to `36` inclusive for each radix.
+ * @exception rb_eArgError `base` is out of range.
+ * @return An instance of ::rb_cString representing `val`.
+ * @pre `val` must be a Fixnum (no checks performed).
+ */
+VALUE rb_fix2str(VALUE val, int base);
+
+RBIMPL_ATTR_CONST()
+/**
+ * Compares two `double`s. Handy when implementing a spaceship operator.
+ *
+ * @param[in] lhs A value.
+ * @param[in] rhs Another value.
+ * @retval RB_INT2FIX(-1) `lhs` is "bigger than" `rhs`.
+ * @retval RB_INT2FIX(1) `rhs` is "bigger than" `lhs`.
+ * @retval RB_INT2FIX(0) They are equal.
+ * @retval RUBY_Qnil Not comparable, e.g. NaN.
+ */
+VALUE rb_dbl_cmp(double lhs, double rhs);
+
+/**
+ * Raises the passed `x` to the power of `y`.
+ *
+ * @note The return value can be really big.
+ * @note Also the return value can be really small, in case `x` is a
+ * negative number.
+ * @param[in] x A number.
+ * @param[in] y Another number.
+ * @retval Inf Cannot express the result.
+ * @retval 1 Either `y` is 0 or `x` is 1.
+ * @retval otherwise An instance of ::rb_cInteger whose value is `x ** y`.
+ *
+ * @internal
+ *
+ * This function returns Infinity when `y` is big enough not to fit into a
+ * Fixnum. Warning is issued then.
+ */
+RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h
index d55178584b..b9ffa57c06 100644
--- a/include/ruby/internal/intern/object.h
+++ b/include/ruby/internal/intern/object.h
@@ -17,73 +17,484 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cObject.
*/
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * This macro is (used but) mysterious. Why on earth do we need this?
+ *
+ * - `obj != orig` check is done anyways inside of rb_obj_init_copy().
+ * - rb_obj_init_copy() returns something. No need are there to add `, 1`.
+ */
#define RB_OBJ_INIT_COPY(obj, orig) \
((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
+/** @old{RB_OBJ_INIT_COPY} */
#define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig)
-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 */
+
+/**
+ * Identical to rb_class_new_instance(), except it passes the passed keywords
+ * if any to the `#initialize` method.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] klass An instance of ::rb_cClass.
+ * @exception rb_eTypeError `klass`'s allocator is undefined.
+ * @exception rb_eException Any exceptions can happen inside.
+ * @return An allocated new instance of `klass`.
+ * @note This is _the_ implementation of `Object.new`.
+ */
+VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass);
+
+/**
+ * Allocates, then initialises an instance of the given class. It first calls
+ * the passed class' allocator to obtain an uninitialised object, then calls
+ * its initialiser with the remaining arguments.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arguments passed to `#initialize`.
+ * @param[in] klass An instance of ::rb_cClass.
+ * @exception rb_eTypeError `klass`'s allocator is undefined.
+ * @exception rb_eException Any exceptions can happen inside.
+ * @return An allocated new instance of `klass`.
+ */
+VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass);
+
+/**
+ * Identical to rb_class_new_instance(), except you can specify how to handle
+ * the last element of the given array.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] klass An instance of ::rb_cClass.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eTypeError `klass`'s allocator is undefined.
+ * @exception rb_eException Any exceptions can happen inside.
+ * @return An allocated new instance of `klass`.
+ */
+VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat);
+
+/**
+ * Checks for equality of the passed objects, in terms of `Object#eql?`.
+ *
+ * @param[in] lhs Comparison left hand side.
+ * @param[in] rhs Comparison right hand side.
+ * @retval non-zero They are equal.
+ * @retval 0 Otherwise.
+ * @note This function actually calls `lhs.eql?(rhs)` so you cannot
+ * implement your class' `#eql?` method using it.
+ */
+int rb_eql(VALUE lhs, VALUE rhs);
+
+/**
+ * Generates a textual representation of the given object.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @return An instance of ::rb_cString that represents `obj`.
+ * @note This is the default implementation of `Object#to_s` that each
+ * subclasses want to override.
+ */
+VALUE rb_any_to_s(VALUE obj);
+
+/**
+ * Generates a human-readable textual representation of the given object. This
+ * is largely similar to Ruby level `Object#inspect` but not the same; it
+ * additionally escapes the inspection result so that the string be compatible
+ * with that of default internal (or default external, if absent).
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @return An instance of ::rb_cString that represents `obj`.
+ */
+VALUE rb_inspect(VALUE obj);
+
+/**
+ * Queries if the given object is a direct instance of the given class.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @param[in] klass An instance of ::rb_cModule.
+ * @exception rb_eTypeError `klass` is neither module nor class.
+ * @retval RUBY_Qtrue `obj` is an instance of `klass`.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_obj_is_instance_of(VALUE obj, VALUE klass);
+
+/**
+ * Queries if the given object is an instance (of possibly descendants) of the
+ * given class.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @param[in] klass An instance of ::rb_cModule.
+ * @exception rb_eTypeError `klass` is neither module nor class.
+ * @retval RUBY_Qtrue `obj` is a `klass`.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass);
+
+/**
+ * Allocates an instance of the given class.
+ *
+ * @param[in] klass A class to instantiate.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @return An allocated, not yet initialised instance of `klass`.
+ * @note It calls the allocator defined by rb_define_alloc_func(). You
+ * cannot use this function to define an allocator. Use
+ * rb_newobj_of(), #TypedData_Make_Struct or others, instead.
+ * @note Usually prefer rb_class_new_instance() to rb_obj_alloc() and
+ * rb_obj_call_init().
+ * @see rb_class_new_instance()
+ * @see rb_obj_call_init()
+ * @see rb_define_alloc_func()
+ * @see rb_newobj_of()
+ * @see #TypedData_Make_Struct
+ */
+VALUE rb_obj_alloc(VALUE klass);
+
+/**
+ * Produces a shallow copy of the given object. Its list of instance variables
+ * are copied, but not the objects they reference. It also copies the frozen
+ * value state.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @exception rb_eException `#initialize_copy` can raise anything.
+ * @return A "clone" of `obj`.
+ *
+ * @internal
+ *
+ * Unlike ruby-level `Object#clone`, there is no way to control the frozen-ness
+ * of the return value.
+ */
+VALUE rb_obj_clone(VALUE obj);
+
+/**
+ * Duplicates the given object. This does almost the same thing as
+ * rb_obj_clone() do. However it does not copy the singleton class (if any).
+ * It also doesn't copy frozen-ness.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @exception rb_eException `#initialize_copy` can raise anything.
+ * @return A shallow copy of `obj`.
+ */
+VALUE rb_obj_dup(VALUE obj);
+
+/**
+ * Default implementation of `#initialize_copy`, `#initialize_dup` and
+ * `#initialize_clone`. It does almost nothing. Just raises exceptions for
+ * checks.
+ *
+ * @param[in] dst The destination object.
+ * @param[in] src The source object.
+ * @exception rb_eFrozenError `dst` is frozen.
+ * @exception rb_eTypeError `dst` and `src` have different classes.
+ * @return Always returns `dst`.
+ */
+VALUE rb_obj_init_copy(VALUE src, VALUE dst);
+
+/**
+ * Just calls rb_obj_freeze_inline() inside. Does this make any sens to
+ * extension libraries?
+ *
+ * @param[out] obj Object to freeze.
+ * @return Verbatim `obj`.
+ */
+VALUE rb_obj_freeze(VALUE obj);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Just calls RB_OBJ_FROZEN() inside. Does this make any sens to extension
+ * libraries?
+ *
+ * @param[in] obj Object in question.
+ * @retval RUBY_Qtrue Yes it is.
+ * @retval RUBY_Qfalse No it isn't.
+ */
+VALUE rb_obj_frozen_p(VALUE obj);
+
+/* gc.c */
+
+/**
+ * Finds or creates an integer primary key of the given object. In the old
+ * days this function was a purely arithmetic operation that maps the
+ * underlying memory address where the object resides into a Ruby's integer.
+ * Some time around 2.x this changed. It no longer relates its return values
+ * to C level pointers. This function assigns some random number to the given
+ * object if absent. The same number will be returned on all subsequent
+ * requests. No two active objects share a number.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @return An instance of ::rb_cInteger which is an "identifier" of `obj`.
+ *
+ * @internal
+ *
+ * The "some random number" is in fact a monotonic-increasing process-global
+ * unique integer, much like an `INTEGER AUTO_INCREMENT PRIMARY KEY` column in
+ * a MySQL table.
+ */
+VALUE rb_obj_id(VALUE obj);
+
+RBIMPL_ATTR_CONST()
+/**
+ * Identical to rb_obj_id(), except it hesitates from allocating a new instance
+ * of ::rb_cInteger. rb_obj_id() could allocate ::RUBY_T_BIGNUM objects. That
+ * allocation might perhaps impact negatively. On such situations, this
+ * function instead returns one-shot temporary small integers that need no
+ * allocations at all. The values are guaranteed unique at the moment, but no
+ * future promise is made; could be reused. Use of this API should be very
+ * instant. It is a failure to store the returned integer to somewhere else.
+ *
+ * In short it is difficult to use.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @return An instance of ::rb_cInteger unique at the moment.
+ *
+ * @internal
+ *
+ * This is roughly the old behaviour of rb_obj_id().
+ */
+VALUE rb_memory_id(VALUE obj);
/* object.c */
-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);
+/**
+ * Finds a "real" class. As the name implies there are class objects that are
+ * surreal. This function takes a class, traverses its ancestry tree, and
+ * returns its nearest ancestor which is neither a module nor a singleton
+ * class.
+ *
+ * @param[in] klass An instance of ::rb_cClass.
+ * @retval RUBY_Qfalse No real class in `klass`' ancestry tree.
+ * @retval klass `klass` itself is a real class.
+ * @retval otherwise Nearest ancestor of `klass` who is real.
+ */
+VALUE rb_class_real(VALUE klass);
RBIMPL_ATTR_PURE()
-VALUE rb_obj_untrusted(VALUE);
-VALUE rb_obj_trust(VALUE);
-VALUE rb_obj_freeze(VALUE);
+/**
+ * Determines if the given two modules are relatives.
+ *
+ * @param[in] scion Possible subclass.
+ * @param[in] ascendant Possible superclass.
+ * @exception rb_eTypeError `ascendant` is not a module.
+ * @retval RUBY_Qtrue `scion` inherits, or is equal to `ascendant`.
+ * @retval RUBY_Qfalse `ascendant` inherits `scion`.
+ * @retval RUBY_Qnil They are not relatives.
+ */
+VALUE rb_class_inherited_p(VALUE scion, VALUE ascendant);
RBIMPL_ATTR_PURE()
-VALUE rb_obj_frozen_p(VALUE);
+/**
+ * Queries the parent of the given class.
+ *
+ * @param[in] klass A child class.
+ * @exception rb_eTypeError `klass` is a `Class.allocate`.
+ * @retval RUBY_Qfalse `klass` has no superclass.
+ * @retval otherwise `klass`' superclass.
+ *
+ * @internal
+ *
+ * Is there any class except ::rb_cBasicObject, that has no superclass?
+ */
+VALUE rb_class_superclass(VALUE klass);
-VALUE rb_obj_id(VALUE);
-VALUE rb_memory_id(VALUE);
-VALUE rb_obj_class(VALUE);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Converts an object into another type. Calls the specified conversion method
+ * if necessary.
+ *
+ * @param[in] val An object to convert.
+ * @param[in] type A value of enum ::ruby_value_type.
+ * @param[in] name Name to display on error (e.g. "Array").
+ * @param[in] mid Conversion method (e.g. "to_ary").
+ * @exception rb_eTypeError Failed to convert.
+ * @return An object of the specified type.
+ */
+VALUE rb_convert_type(VALUE val, int type, const char *name, const char *mid);
-RBIMPL_ATTR_PURE()
-VALUE rb_class_real(VALUE);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_convert_type(), except it returns ::RUBY_Qnil instead of
+ * raising exceptions, in case of conversion failure. It still raises
+ * exceptions for various reasons, like when the conversion method itself
+ * raises, though.
+ *
+ * @param[in] val An object to convert.
+ * @param[in] type A value of enum ::ruby_value_type.
+ * @param[in] name Name to display on error (e.g. "Array").
+ * @param[in] mid Conversion method (e.g. "to_ary").
+ * @exception rb_eTypeError The `mid` does not generate `type`.
+ * @retval RUBY_Qnil No conversion defined.
+ * @retval otherwise An object of the specified type.
+ */
+VALUE rb_check_convert_type(VALUE val, int type, const char *name, const char *mid);
-RBIMPL_ATTR_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_ATTR_NONNULL(())
+/**
+ * Identical to rb_check_convert_type(), except the return value type is fixed
+ * to ::rb_cInteger.
+ *
+ * @param[in] val An object to convert.
+ * @param[in] mid Conversion method (e.g. "to_ary").
+ * @exception rb_eTypeError The `mid` does not generate an integer.
+ * @retval RUBY_Qnil No conversion defined.
+ * @retval otherwise An instance of ::rb_cInteger.
+ */
+VALUE rb_check_to_integer(VALUE val, const char *mid);
+
+/**
+ * This is complicated.
+ *
+ * - When the passed object is already an instance of ::rb_cFloat, just
+ * returns it as-is.
+ *
+ * - When the passed object is something numeric, the function tries to
+ * convert it using `#to_f` method.
+ *
+ * - If that conversion fails (this happens for instance when the numeric
+ * is a complex) it returns ::RUBY_Qnil.
+ *
+ * - Otherwise returns the conversion result.
+ *
+ * - Otherwise it also returns ::RUBY_Qnil.
+ *
+ * @param[in] val An object to convert.
+ * @retval RUBY_Qnil Conversion from `val` to float is undefined.
+ * @retval otherwise Converted result.
+ */
+VALUE rb_check_to_float(VALUE val);
+
+/**
+ * Identical to rb_check_to_int(), except it raises in case of conversion
+ * mismatch.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eTypeError `#to_int` does not generate an integer.
+ * @return An instance of ::rb_cInteger.
+ */
+VALUE rb_to_int(VALUE val);
+
+/**
+ * Identical to rb_check_to_integer(), except it uses `#to_int` for conversion.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eTypeError `#to_int` does not return an integer.
+ * @retval RUBY_Qnil No conversion defined.
+ * @retval otherwise An instance of ::rb_cInteger.
+ */
+VALUE rb_check_to_int(VALUE val);
+
+/**
+ * This is the logic behind `Kernel#Integer`. Numeric types are converted
+ * directly, with floating point numbers being truncated. Strings are
+ * interpreted strictly; only leading/trailing whitespaces, plus/minus sign,
+ * radix indicators such as `0x`, digits, and underscores are allowed.
+ * Anything else are converted by first trying `#to_int`, then `#to_i`.
+ *
+ * This is slightly stricter than `String#to_i`.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eArgError Malformed `val` passed.
+ * @exception rb_eTypeError No conversion defined.
+ * @return An instance of ::rb_cInteger.
+ */
+VALUE rb_Integer(VALUE val);
+
+/**
+ * Identical to rb_check_to_float(), except it raises on error.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eTypeError No conversion defined.
+ * @return An instance of ::rb_cFloat.
+ */
+VALUE rb_to_float(VALUE val);
+
+/**
+ * This is the logic behind `Kernel#Float`. Numeric types are converted
+ * directly to the nearest value that a Float can represent. Strings are
+ * interpreted strictly; only leading/trailing whitespaces are allowed except
+ * what `strtod` understands. Anything else are converted using `#to_f`.
+ *
+ * This is slightly stricter than `String#to_f`.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eArgError Malformed `val` passed.
+ * @exception rb_eTypeError No conversion defined.
+ * @return An instance of ::rb_cFloat.
+ */
+VALUE rb_Float(VALUE val);
+
+/**
+ * This is the logic behind `Kernel#String`. Arguments are converted by first
+ * trying `#to_str`, then `#to_s`.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eTypeError No conversion defined.
+ * @return An instance of ::rb_cString.
+ */
+VALUE rb_String(VALUE val);
+
+/**
+ * This is the logic behind `Kernel#Array`. Arguments are converted by first
+ * trying `#to_ary`, then `#to_a`, and if both failed, returns an array of
+ * length 1 that contains the passed argument as the sole contents.
+ *
+ * @param[in] val An object to convert.
+ * @return An instance of ::rb_cArray.
+ */
+VALUE rb_Array(VALUE val);
+
+/**
+ * This is the logic behind `Kernel#Hash`. Arguments are converted by first
+ * trying `#to_hash`. if it failed, and the argument is either ::RUBY_Qnil or
+ * an empty array, returns an empty hash. Otherwise an exception is raised.
+ *
+ * @param[in] val An object to convert.
+ * @exception rb_eTypeError No conversion defined.
+ * @return An instance of ::rb_cHash.
+ */
+VALUE rb_Hash(VALUE val);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Converts a textual representation of a real number into a numeric, which is
+ * the nearest value that the return type can represent, of the value that the
+ * argument represents. This is in fact a 2-in-1 function whose behaviour can
+ * be controlled using the second (mode) argument. If the mode is zero, this
+ * function is in "historical" mode which only understands "floating-constant"
+ * defined at ISO/IEC 9899:1990 section 6.1.3.1. If the mode is nonzero, it is
+ * in "extended" mode, which also accepts "hexadecimal-floating-constant"
+ * defined at ISO/IEC 9899:2018 section 6.4.4.2.
+ *
+ * @param[in] str A textual representation of a real number.
+ * @param[in] mode Conversion mode, as described above.
+ * @exception rb_eArgError Malformed `str` passed.
+ * @see https://bugs.ruby-lang.org/issues/2969
+ * @note Null pointers are allowed, and it returns 0.0 then.
+ */
+double rb_cstr_to_dbl(const char *str, int mode);
+
+/**
+ * Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of
+ * C's.
+ *
+ * @param[in] str A textual representation of a real number.
+ * @param[in] mode Conversion mode, as described in rb_cstr_to_dbl().
+ * @exception rb_eArgError Malformed `str` passed.
+ * @see https://bugs.ruby-lang.org/issues/2969
+ */
+double rb_str_to_dbl(VALUE str, int mode);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/parse.h b/include/ruby/internal/intern/parse.h
index 9424657bbc..7c4e9925b9 100644
--- a/include/ruby/internal/intern/parse.h
+++ b/include/ruby/internal/intern/parse.h
@@ -17,45 +17,176 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cSymbol.
*/
#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
-/* parse.y */
-ID rb_id_attrset(ID);
+/* symbol.c */
+
+/**
+ * Calculates an ID of attribute writer. For instance it returns `:foo=` when
+ * passed `:foo`.
+ *
+ * @param[in] id An id.
+ * @exception rb_eNameError `id` is not for attributes (e.g. operator).
+ * @return Calculated name of attribute writer.
+ */
+ID rb_id_attrset(ID id);
RBIMPL_ATTR_CONST()
-int rb_is_const_id(ID);
+/**
+ * Classifies the given ID, then sees if it is a constant. In case an ID is in
+ * Unicode (likely), its "constant"-ness is determined if its first character
+ * is either upper case or title case. Otherwise it is detected if case-
+ * folding the first character changes its case or not.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is a constant.
+ * @retval 0 It isn't.
+ */
+int rb_is_const_id(ID id);
RBIMPL_ATTR_CONST()
-int rb_is_global_id(ID);
+/**
+ * Classifies the given ID, then sees if it is a global variable. A global
+ * variable must start with `$`.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is a global variable.
+ * @retval 0 It isn't.
+ */
+int rb_is_global_id(ID id);
RBIMPL_ATTR_CONST()
-int rb_is_instance_id(ID);
+/**
+ * Classifies the given ID, then sees if it is an instance variable. An
+ * instance variable must start with `@`, but not `@@`.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is an instance variable.
+ * @retval 0 It isn't.
+ */
+int rb_is_instance_id(ID id);
RBIMPL_ATTR_CONST()
-int rb_is_attrset_id(ID);
+/**
+ * Classifies the given ID, then sees if it is an attribute writer. An
+ * attribute writer is otherwise a local variable, except it ends with `=`.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is an attribute writer.
+ * @retval 0 It isn't.
+ */
+int rb_is_attrset_id(ID id);
RBIMPL_ATTR_CONST()
-int rb_is_class_id(ID);
+/**
+ * Classifies the given ID, then sees if it is a class variable. A class
+ * variable is must start with `@@`.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is a class variable.
+ * @retval 0 It isn't.
+ */
+int rb_is_class_id(ID id);
RBIMPL_ATTR_CONST()
-int rb_is_local_id(ID);
+/**
+ * Classifies the given ID, then sees if it is a local variable. A local
+ * variable starts with a lowercase character, followed by some alphanumeric
+ * characters or `_`, then ends with anything other than `!`, `?`, or `=`.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is a local variable.
+ * @retval 0 It isn't.
+ */
+int rb_is_local_id(ID id);
RBIMPL_ATTR_CONST()
+/**
+ * Classifies the given ID, then sees if it is a junk ID. An ID with no
+ * special syntactic structure is considered junk. This category includes for
+ * instance punctuation.
+ *
+ * @param[in] id An id to classify.
+ * @retval 1 It is a junk.
+ * @retval 0 It isn't.
+ */
int rb_is_junk_id(ID);
-int rb_symname_p(const char*);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Sees if the passed C string constructs a valid syntactic symbol. Invalid
+ * ones for instance includes whitespaces.
+ *
+ * @param[in] str A C string to check.
+ * @retval 1 It is a valid symbol name.
+ * @retval 0 It is invalid as a symbol name.
+ */
+int rb_symname_p(const char *str);
+
+/* vm.c */
+
+/**
+ * Queries the last match, or `Regexp.last_match`, or the `$~`. You don't have
+ * to use it, because in reality you can get `$~` using rb_gv_get() as usual.
+ *
+ * @retval RUBY_Qnil The method has not ran a regular expression.
+ * @retval otherwise An instance of ::rb_cMatch.
+ */
VALUE rb_backref_get(void);
-void rb_backref_set(VALUE);
+
+/**
+ * Updates `$~`. You don't have to use it, because in reality you can set `$~`
+ * using rb_gv_set() as usual.
+ *
+ * @param[in] md Arbitrary Ruby object.
+ * @post The passed object is assigned to `$~`.
+ *
+ * @internal
+ *
+ * Yes, this function bypasses the Check_Type() that would normally prevent
+ * evil souls from assigning evil objects to `$~`. Use of this function is a
+ * really bad smell.
+ */
+void rb_backref_set(VALUE md);
+
+/**
+ * Queries the last line, or the `$_`. You don't have to use it, because in
+ * reality you can get `$_` using rb_gv_get() as usual.
+ *
+ * @retval RUBY_Qnil There has never been a "line" yet.
+ * @retval otherwise The last set `$_` value.
+ */
VALUE rb_lastline_get(void);
-void rb_lastline_set(VALUE);
+
+/**
+ * Updates `$_`. You don't have to use it, because in reality you can set `$_`
+ * using rb_gv_set() as usual.
+ *
+ * @param[in] str Arbitrary Ruby object.
+ * @post The passed object is assigned to `$_`.
+ *
+ * @internal
+ *
+ * Unlike `$~`, you can assign non-strings to `$_`, even from ruby scripts.
+ */
+void rb_lastline_set(VALUE str);
/* symbol.c */
+
+/**
+ * Collects every single bits of symbols that have ever interned in the entire
+ * history of the current process.
+ *
+ * @return An array that contains all symbols that have ever existed.
+ */
VALUE rb_sym_all_symbols(void);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/proc.h b/include/ruby/internal/intern/proc.h
index d6f77cbd4d..b8c3c5e146 100644
--- a/include/ruby/internal/intern/proc.h
+++ b/include/ruby/internal/intern/proc.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cProc.
*/
#include "ruby/internal/dllexport.h"
@@ -27,26 +27,326 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* proc.c */
+
+/**
+ * Constructs a Proc object from implicitly passed components. When a ruby
+ * method is called with a block, that block is not explicitly passed around
+ * using C level function parameters. This function gathers all the necessary
+ * info to turn them into a Ruby level instance of ::rb_cProc.
+ *
+ * @exception rb_eArgError There is no passed block.
+ * @return An instance of ::rb_cProc.
+ */
VALUE rb_block_proc(void);
+
+/**
+ * Identical to rb_proc_new(), except it returns a lambda.
+ *
+ * @exception rb_eArgError There is no passed block.
+ * @return An instance of ::rb_cProc.
+ */
VALUE rb_block_lambda(void);
-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);
+
+/**
+ * This is an rb_iterate() + rb_block_proc() combo.
+ *
+ * ```CXX
+ * VALUE
+ * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c))
+ * {
+ * const auto plus = rb_intern("+");
+ * return rb_funcall(c, plus, 1, y);
+ * }
+ *
+ * VALUE
+ * my_own_method(VALUE self)
+ * {
+ * return rb_proc_new(my_own_iterator, self);
+ * }
+ * ```
+ *
+ * @param[in] func A backend function of a proc.
+ * @param[in] callback_arg Passed to `func`'s callback_arg.
+ * @return A C-backended proc object.
+ *
+ */
+VALUE rb_proc_new(rb_block_call_func_t func, VALUE callback_arg);
+
+/**
+ * Queries if the given object is a proc.
+ *
+ * @note This is about the object's data structure, not its class etc.
+ * @param[in] recv Object in question.
+ * @retval RUBY_Qtrue It is a proc.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_obj_is_proc(VALUE recv);
+
+/**
+ * Evaluates the passed proc with the passed arguments.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] args An instance of ::RArray which is the arguments.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call(VALUE recv, VALUE args);
+
+/**
+ * Identical to rb_proc_call(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] args An instance of ::RArray which is the arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call_kw(VALUE recv, VALUE args, int kw_splat);
+
+/**
+ * Identical to rb_proc_call(), except you can additionally pass another proc
+ * object, as a block. Nowadays procs can take blocks:
+ *
+ * ```ruby
+ * l = -> (positional, optional=nil, *rest, kwarg:, **kwrest, &block) {
+ * # ... how can we pass this `&block`? ^^^^^^
+ * }
+ * ```
+ *
+ * And this function is to pass one to such procs.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of proc arguments.
+ * @param[in] proc Proc as a passed block.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc);
+
+/**
+ * Identical to rb_proc_call_with_block(), except you can specify how to handle
+ * the last element of the given array. It can also be seen as a routine
+ * identical to rb_proc_call_kw(), except you can additionally pass another
+ * proc object as a block.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of proc arguments.
+ * @param[in] proc Proc as a passed block.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call_with_block_kw(VALUE recv, int argc, const VALUE *argv, VALUE proc, int kw_splat);
+
+/**
+ * Queries the number of mandatory arguments of the given Proc. If its block
+ * is declared to take no arguments, returns `0`. If the block is known to
+ * take exactly `n` arguments, returns `n`. If the block has optional
+ * arguments, returns `-n-1`, where `n` is the number of mandatory arguments,
+ * with the exception for blocks that are not lambdas and have only a finite
+ * number of optional arguments; in this latter case, returns `n`. Keyword
+ * arguments will be considered as a single additional argument, that argument
+ * being mandatory if any keyword argument is mandatory.
+ *
+ * @param[in] recv Target Proc object.
+ * @retval 0 It takes no arguments.
+ * @retval >0 It takes exactly this number of arguments.
+ * @retval <0 It takes optional arguments.
+ */
+int rb_proc_arity(VALUE recv);
+
+/**
+ * Queries if the given object is a lambda. Instances of ::rb_cProc are either
+ * lambda or proc. They differ in several points. This function can
+ * distinguish them without actually evaluating their contents.
+ *
+ * @param[in] recv Target proc object.
+ * @retval RUBY_Qtrue It is a lambda.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_proc_lambda_p(VALUE recv);
+
+/**
+ * Snapshots the current execution context and turn it into an instance of
+ * ::rb_cBinding.
+ *
+ * @return An instance of ::rb_cBinding.
+ */
VALUE rb_binding_new(void);
-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*);
+
+/**
+ * Creates a method object. A method object is a proc-like object that you can
+ * "call". Note that a method object snapshots the method at the time the
+ * object is created:
+ *
+ * ```ruby
+ * class Foo
+ * def foo
+ * return 1
+ * end
+ * end
+ *
+ * obj = Foo.new.method(:foo)
+ *
+ * class Foo
+ * def foo
+ * return 2
+ * end
+ * end
+ *
+ * obj.call # => 1, not 2.
+ * ```
+ *
+ * @param[in] recv Receiver of the method.
+ * @param[in] mid Method name, in either String or Symbol.
+ * @exception rb_eNoMethodError No such method.
+ * @return An instance of ::rb_cMethod.
+ */
+VALUE rb_obj_method(VALUE recv, VALUE mid);
+
+/**
+ * Queries if the given object is a method.
+ *
+ * @note This is about the object's data structure, not its class etc.
+ * @param[in] recv Object in question.
+ * @retval RUBY_Qtrue It is a method.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_obj_is_method(VALUE recv);
+
+/**
+ * Evaluates the passed method with the passed arguments.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv);
+
+/**
+ * Identical to rb_method_call(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call_kw(int argc, const VALUE *argv, VALUE recv, int kw_splat);
+
+/**
+ * Identical to rb_proc_call(), except you can additionally pass a proc as a
+ * block.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @param[in] proc Proc as a passed block.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE proc);
+
+/**
+ * Identical to rb_method_call_with_block(), except you can specify how to
+ * handle the last element of the given array. It can also be seen as a
+ * routine identical to rb_method_call_kw(), except you can additionally pass
+ * another proc object as a block.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @param[in] proc Proc as a passed block.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call_with_block_kw(int argc, const VALUE *argv, VALUE recv, VALUE proc, int kw_splat);
+
+/**
+ * Queries the number of mandatory arguments of the method defined in the given
+ * module. If it is declared to take no arguments, returns `0`. If it takes
+ * exactly `n` arguments, returns `n`. If it has optional arguments, returns
+ * `-n-1`, where `n` is the number of mandatory arguments. Keyword arguments
+ * will be considered as a single additional argument, that argument being
+ * mandatory if any keyword argument is mandatory.
+ *
+ * @param[in] mod Namespace to search a method for.
+ * @param[in] mid Method id.
+ * @retval 0 It takes no arguments.
+ * @retval >0 It takes exactly this number of arguments.
+ * @retval <0 It takes optional arguments.
+ */
+int rb_mod_method_arity(VALUE mod, ID mid);
+
+/**
+ * Identical to rb_mod_method_arity(), except it searches for singleton methods
+ * rather than instance methods.
+ *
+ * @param[in] obj Object to search for a singleton method.
+ * @param[in] mid Method id.
+ * @retval 0 It takes no arguments.
+ * @retval >0 It takes exactly this number of arguments.
+ * @retval <0 It takes optional arguments.
+ */
+int rb_obj_method_arity(VALUE obj, ID mid);
+
+/* eval.c */
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Protects a function call from potential global escapes from the function.
+ * Such global escapes include exceptions, `throw`, `break`, for example.
+ *
+ * It first calls the function func with `args` as the argument. If no global
+ * escape occurred during the function, it returns the result and `*state` is
+ * zero. Otherwise, it returns ::RUBY_Qnil and sets `*state` to nonzero. If
+ * `state` is `NULL`, it is not set in both cases.
+ *
+ * @param[in] func A function that potentially escapes globally.
+ * @param[in] args Passed as-is to `func`.
+ * @param[out] state State of execution.
+ * @return What `func` returns, or an undefined value when it did not
+ * return.
+ * @post `*state` is set to zero if succeeded. Nonzero otherwise.
+ * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if
+ * you decide to ignore the caught exception.
+ * @see rb_eval_string_protect()
+ * @see rb_load_protect()
+ *
+ * @internal
+ *
+ * The "undefined value" described above is in fact ::RUBY_Qnil for now. But
+ * @shyouhei doesn't think that we would never change that.
+ *
+ * Though not a part of our public API, `state` is in fact an
+ * enum ruby_tag_type. You can see the potential "nonzero" values by looking
+ * at vm_core.h.
+ */
+VALUE rb_protect(VALUE (*func)(VALUE args), VALUE args, int *state);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/process.h b/include/ruby/internal/intern/process.h
index 2b1005a205..7a7b24ed4b 100644
--- a/include/ruby/internal/intern/process.h
+++ b/include/ruby/internal/intern/process.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_mProcess.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/config.h" /* rb_pid_t is defined here. */
#include "ruby/internal/dllexport.h"
@@ -28,17 +29,243 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* process.c */
+
+/**
+ * Sets the "last status", or the `$?`.
+ *
+ * @param[in] status The termination status, as defined in `waitpid(3posix)`.
+ * @param[in] pid The last child of the current process.
+ * @post `$?` is updated.
+ */
void rb_last_status_set(int status, rb_pid_t pid);
+
+/**
+ * Queries the "last status", or the `$?`.
+ *
+ * @retval RUBY_Qnil The current thread has no dead children.
+ * @retval otherwise An instance of Process::Status describing the status of
+ * the child that was most recently `wait`-ed.
+ */
VALUE rb_last_status_get(void);
-int rb_proc_exec(const char*);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Executes a shell command.
+ *
+ * @warning THIS FUNCTION RETURNS on error!
+ * @param[in] cmd Passed to the shell.
+ * @retval -1 Something prevented the command execution.
+ * @post Upon successful execution this function doesn't return.
+ * @post In case it returns the `errno` is set properly.
+ */
+int rb_proc_exec(const char *cmd);
RBIMPL_ATTR_NORETURN()
-VALUE rb_f_exec(int, const VALUE*);
+/**
+ * Replaces the current process by running the given external command. This is
+ * the implementation of `Kernel#exec`.
+ *
+ * @param[in] argc Number of objects in `argv`.
+ * @param[in] argv Command and its options to execute.
+ * @exception rb_eTypeError Invalid options e.g. non-String argv.
+ * @exception rb_eArgError Invalid options e.g. redirection cycle.
+ * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`.
+ * @exception rb_eRuntimeError `Process::UID.switch` in operation.
+ * @exception rb_eSystemCallError `execve(2)` failed.
+ * @warning This function doesn't return.
+ * @warning On failure it raises. On success the process is replaced.
+ *
+ * @internal
+ *
+ * @shyouhei have to say that the rdoc for `Kernel#exec` is fairly incomplete.
+ * AFAIK this function ultimately takes the following signature:
+ *
+ * ```rbs
+ * type boolx = bool | nil # != `boolish`
+ *
+ * type rlim_t = Integer # rlim_cur
+ * | [ Integer, Integer ] # rlim_cur, rlim_max
+ *
+ * type uid_t = String # e.g. "root"
+ * | Integer # e.g. 0
+ *
+ * type gid_t = String # e.g. "wheel"
+ * | Integer # e.g. 0
+ *
+ * type fmode = String # e.g. "rb"
+ * | Integer # e.g. O_RDONLY | O_BINARY
+ *
+ * type mode_t = Integer # e.g. 0644
+ *
+ * type pgrp = true # Creates a dedicated pgroup
+ * | 0 # ditto
+ * | nil # Uses the current one
+ * | Integer # Uses this specific pgroup
+ *
+ * type fd = :in # STDIN
+ * | :out # STDOUT
+ * | :err # STDERR
+ * | IO # This specific IO
+ * | Integer # A file descriptor of this #
+ *
+ * type src = fd | [ fd ]
+ * type dst = :close # Intuitive
+ * | fd # Intuitive
+ * | String # Open a file at this path
+ * | [ String ] # ... using O_RDONLY
+ * | [ String, fmode ] # ... using this mode
+ * | [ String, fmode, mode_t ] # ... with a permission
+ * | [ :child, fd ] # fd of child side
+ *
+ * type redir = Hash[ src, dst ]
+ *
+ * # ----
+ *
+ * # Key-value pair of environment variables
+ * type envp = Hash[ String, String ]
+ *
+ * # Actual name (and the name passed to the subprocess if any)
+ * type arg0 = String | [ String, String ]
+ *
+ * # Arbitrary string parameters
+ * type argv = String
+ *
+ * # Exec options:
+ * type argh = redir | {
+ * chdir: String, # Working directory
+ * close_others: boolx, # O_CLOEXEC like behaviour
+ * gid: gid_t, # setegid(2)
+ * pgrooup: pgrp, # setpgrp(2)
+ * rlimit_as: rlim_t, # setrlimit(2)
+ * rlimit_core: rlim_t, # ditto
+ * rlimit_cpu: rlim_t, # ditto
+ * rlimit_data: rlim_t, # ditto
+ * rlimit_fsize: rlim_t, # ditto
+ * rlimit_memlock: rlim_t, # ditto
+ * rlimit_msgqueue: rlim_t, # ditto
+ * rlimit_nice: rlim_t, # ditto
+ * rlimit_nofile: rlim_t, # ditto
+ * rlimit_nproc: rlim_t, # ditto
+ * rlimit_rss: rlim_t, # ditto
+ * rlimit_rtprio: rlim_t, # ditto
+ * rlimit_rttime: rlim_t, # ditto
+ * rlimit_sbsize: rlim_t, # ditto
+ * rlimit_sigpending: rlim_t, # ditto
+ * rlimit_stack: rlim_t, # ditto
+ * uid: uid_t, # seteuid(2)
+ * umask: mode_t, # umask(2)
+ * unsetenv_others: boolx # Unset everything except the passed envp
+ * }
+ *
+ * # ====
+ *
+ * class Kernel
+ * def self?.exec
+ * : ( arg0 cmd, *argv args ) -> void
+ * | ( arg0 cmd, *argv args, argh opts) -> void
+ * | (envp env, arg0 cmd, *argv args ) -> void
+ * | (envp env, arg0 cmd, *argv args, argh opts) -> void
+ * end
+ * ```
+ */
+VALUE rb_f_exec(int argc, const VALUE *argv);
+
+/**
+ * Waits for a process, with releasing GVL.
+ *
+ * @param[in] pid Process ID.
+ * @param[out] status The wait status is filled back.
+ * @param[in] flags Wait options.
+ * @retval -1 System call failed, errno set.
+ * @retval 0 WNOHANG but no waitable children.
+ * @retval otherwise A process ID that was `wait()`-ed.
+ * @post Upon successful return `status` is updated to have the process'
+ * status.
+ * @note `status` can be NULL.
+ * @note The arguments are passed through to underlying system call(s).
+ * Can have special meanings. For instance passing `(rb_pid_t)-1`
+ * to `pid` means it waits for any processes, under
+ * POSIX-compliant situations.
+ */
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags);
+
+/**
+ * This is a shorthand of rb_waitpid without status and flags. It has been
+ * like this since the very beginning. The initial revision already did the
+ * same thing. Not sure why, then, it has been named `syswait`. AFAIK this is
+ * different from how `wait(3posix)` works.
+ *
+ * @param[in] pid Passed to rb_waitpid().
+ */
void rb_syswait(rb_pid_t pid);
-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);
+
+/**
+ * Identical to rb_f_exec(), except it spawns a child process instead of
+ * replacing the current one.
+ *
+ * @param[in] argc Number of objects in `argv`.
+ * @param[in] argv Command and its options to execute.
+ * @exception rb_eTypeError Invalid options e.g. non-String argv.
+ * @exception rb_eArgError Invalid options e.g. redirection cycle.
+ * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`.
+ * @exception rb_eRuntimeError `Process::UID.switch` in operation.
+ * @retval -1 Child process died for some reason.
+ * @retval otherwise The ID of the born child.
+ *
+ * @internal
+ *
+ * This is _really_ identical to rb_f_exec() until ultimately calling the
+ * system call. Almost everything are shared among these two (and
+ * rb_f_system()).
+ */
+rb_pid_t rb_spawn(int argc, const VALUE *argv);
+
+/**
+ * Identical to rb_spawn(), except you can additionally know the detailed
+ * situation in case of abnormal parturitions.
+ *
+ * @param[in] argc Number of objects in `argv`.
+ * @param[in] argv Command and its options to execute.
+ * @param[out] errbuf Error description write-back buffer.
+ * @param[in] buflen Number of bytes of `errbuf`, including NUL.
+ * @exception rb_eTypeError Invalid options e.g. non-String argv.
+ * @exception rb_eArgError Invalid options e.g. redirection cycle.
+ * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`.
+ * @exception rb_eRuntimeError `Process::UID.switch` in operation.
+ * @retval -1 Child process died for some reason.
+ * @retval otherwise The ID of the born child.
+ * @post In case of `-1`, at most `buflen` bytes of the reason why is
+ * written back to `errbuf`.
+ */
+rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen);
+
+/**
+ * Gathers info about resources consumed by the current process.
+ *
+ * @param[in] _ Not used. Pass anything.
+ * @return An instance of `Process::Tms`.
+ *
+ * @internal
+ *
+ * This function might or might not exist depending on `./confiugre` result.
+ * It must be a portability hell. Better not use.
+ */
+VALUE rb_proc_times(VALUE _);
+
+/**
+ * "Detaches" a subprocess. In POSIX systems every child processes that a
+ * process creates must be `wait(2)`-ed. A child process that died yet has not
+ * been waited so far is called a "zombie", which more or less consumes
+ * resources. This function automates reclamation of such processes. Once
+ * after this function successfully returns you can basically forget about the
+ * child process.
+ *
+ * @param[in] pid Process to wait.
+ * @return An instance of ::rb_cThread which is `waitpid(2)`-ing `pid`.
+ * @post You can just forget about the return value. GC reclaims it.
+ * @post You can know the exit status by querying `#value` of the
+ * return value (which is a blocking operation).
+ */
VALUE rb_detach_process(rb_pid_t pid);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/random.h b/include/ruby/internal/intern/random.h
index 6482a8f6e8..5577f53cb4 100644
--- a/include/ruby/internal/intern/random.h
+++ b/include/ruby/internal/intern/random.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
@@ -30,13 +30,85 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* random.c */
+
+/**
+ * Generates a 32 bit random number.
+ *
+ * @return A random number.
+ * @note Now that we have ractors, the RNG behind this function is
+ * per-ractor.
+ */
unsigned int rb_genrand_int32(void);
+
+/**
+ * Generates a `double` random number.
+ *
+ * @return A random number.
+ * @note This function shares the RNG with rb_genrand_int32().
+ */
double rb_genrand_real(void);
+
+/**
+ * Resets the RNG behind rb_genrand_int32()/rb_genrand_real().
+ *
+ * @post The (now per-ractor) default RNG's internal state is cleared.
+ */
void rb_reset_random_seed(void);
+
+/**
+ * Generates a String of random bytes.
+ *
+ * @param[in,out] rnd An instance of ::rb_cRandom.
+ * @param[in] n Requested number of bytes.
+ * @return An instance of ::rb_cString, of binary, of `n` bytes length,
+ * whose contents are random bits.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't know if this is an Easter egg or an official feature, but
+ * this function can take a wider range of objects, such as `Socket::Ifaddr`.
+ * The arguments are just silently ignored and the default RNG is used instead,
+ * if they are non-RNG.
+ */
VALUE rb_random_bytes(VALUE rnd, long n);
+
+/**
+ * Identical to rb_genrand_int32(), except it generates using the passed RNG.
+ *
+ * @param[in,out] rnd An instance of ::rb_cRandom.
+ * @return A random number.
+ */
unsigned int rb_random_int32(VALUE rnd);
+
+/**
+ * Identical to rb_genrand_real(), except it generates using the passed RNG.
+ *
+ * @param[in,out] rnd An instance of ::rb_cRandom.
+ * @return A random number.
+ */
double rb_random_real(VALUE rnd);
+
+/**
+ * Identical to rb_genrand_ulong_limited(), except it generates using the
+ * passed RNG.
+ *
+ * @param[in,out] rnd An instance of ::rb_cRandom.
+ * @param[in] limit Max possible return value.
+ * @return A random number, distributed in `[0, limit]` interval.
+ * @note Note it can return `limit`.
+ * @note Whether the return value distributes uniformly in the
+ * interval or not depends on how the argument RNG behaves; at
+ * least in case of MT19937 it does.
+ */
unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit);
+
+/**
+ * Generates a random number whose upper limit is `i`.
+ *
+ * @param[in] i Max possible return value.
+ * @return A random number, uniformly distributed in `[0, limit]` interval.
+ * @note Note it can return `i`.
+ */
unsigned long rb_genrand_ulong_limited(unsigned long i);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/range.h b/include/ruby/internal/intern/range.h
index 7ca47915e2..1f7d7c313f 100644
--- a/include/ruby/internal/intern/range.h
+++ b/include/ruby/internal/intern/range.h
@@ -17,17 +17,71 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cRange.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* range.c */
-VALUE rb_range_new(VALUE, VALUE, int);
-VALUE rb_range_beg_len(VALUE, long*, long*, long, int);
+
+/**
+ * Creates a new Range.
+ *
+ * @param[in] beg "Left" or "lowest" endpoint of the range.
+ * @param[in] end "Right" or "highest" endpoint of the range.
+ * @param[in] excl Whether the range is open-ended.
+ * @exception rb_eArgError `beg` and `end` are not comparable.
+ * @note These days both endpoints can be ::RUBY_Qnil, which means that
+ * endpoint is unbound.
+ */
+VALUE rb_range_new(VALUE beg, VALUE end, int excl);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Deconstructs a numerical range. As the arguments are `long` based, it
+ * expects everything are in the `long` domain.
+ *
+ * @param[in] range A range of numerical endpoints.
+ * @param[out] begp Return value buffer.
+ * @param[out] lenp Return value buffer.
+ * @param[in] len Updated length.
+ * @param[in] err In case `len` is out of range...
+ * - `0`: returns ::RUBY_Qnil.
+ * - `1`: raises ::rb_eRangeError.
+ * - `2`: `beg` and `len` expanded accordingly.
+ * @exception rb_eTypeError `range` is not a numerical range.
+ * @exception rb_eRangeError `range` cannot fit into `long`.
+ * @retval RUBY_Qfalse `range` is not an ::rb_cRange.
+ * @retval RUBY_Qnil `len` is out of `range` but `err` is zero.
+ * @retval RUBY_Qtrue Otherwise.
+ * @post `beg` is the (possibly updated) left endpoint.
+ * @post `len` is the (possibly updated) length of the range.
+ *
+ * @internal
+ *
+ * The complex error handling switch reflects the fact that `Array#[]=` and
+ * `String#[]=` behave differently when they take ranges.
+ */
+VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Deconstructs a range into its components.
+ *
+ * @param[in] range Range or range-ish object.
+ * @param[out] begp Return value buffer.
+ * @param[out] endp Return value buffer.
+ * @param[out] exclp Return value buffer.
+ * @retval RUBY_Qfalse `range` is not an instance of ::rb_cRange.
+ * @retval RUBY_Qtrue Argument pointers are updated.
+ * @post `*begp` is the left endpoint of the range.
+ * @post `*endp` is the right endpoint of the range.
+ * @post `*exclp` is whether the range is open-ended or not.
+ */
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/rational.h b/include/ruby/internal/intern/rational.h
index 30a87ff31f..ff4beca297 100644
--- a/include/ruby/internal/intern/rational.h
+++ b/include/ruby/internal/intern/rational.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cRational.
*/
+#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */
@@ -27,19 +28,144 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* rational.c */
-VALUE rb_rational_raw(VALUE, VALUE);
+
+/**
+ * Identical to rb_rational_new(), except it skips argument validations. It is
+ * thus dangerous for extension libraries. For instance `1/0r` could be
+ * constructed using this.
+ *
+ * @param[in] num Numerator, an instance of ::rb_cInteger.
+ * @param[in] den Denominator, an instance of ::rb_cInteger.
+ * @exception rb_eTypeError Either argument is not an Integer.
+ * @return An instance of ::rb_cRational whose value is `(num/den)r`.
+ */
+VALUE rb_rational_raw(VALUE num, VALUE den);
+
+/**
+ * Shorthand of `(x/1)r`. As `x` is already an Integer, it practically
+ * converts it into a Rational of the identical value.
+ *
+ * @param[in] x An instance of ::rb_cInteger.
+ * @return An instance of ::rb_cRational, whose value is `(x/1)r`.
+ */
#define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1))
+
+/** @alias{rb_rational_raw} */
#define rb_rational_raw2(x,y) rb_rational_raw((x), (y))
-VALUE rb_rational_new(VALUE, VALUE);
+
+/**
+ * Constructs a Rational, with reduction. This returns for instance `(2/3)r`
+ * for `rb_rational_new(INT2NUM(-384), INT2NUM(-576))`.
+ *
+ * @param[in] num Numerator, an instance of ::rb_cInteger.
+ * @param[in] den Denominator, an instance of ::rb_cInteger.
+ * @exception rb_eZeroDivError `den` is zero.
+ * @return An instance of ::rb_cRational whose value is `(num/den)r`.
+ */
+VALUE rb_rational_new(VALUE num, VALUE den);
+
+/**
+ * Shorthand of `(x/1)r`. As `x` is already an Integer, it practically
+ * converts it into a Rational of the identical value.
+ *
+ * @param[in] x An instance of ::rb_cInteger.
+ * @return An instance of ::rb_cRational, whose value is `(x/1)r`.
+ */
#define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1))
+
+/** @alias{rb_rational_new} */
#define rb_rational_new2(x,y) rb_rational_new((x), (y))
-VALUE rb_Rational(VALUE, VALUE);
+
+/**
+ * Converts various values into a Rational. This function accepts:
+ *
+ * - Instances of ::rb_cInteger (taken as-is),
+ * - Instances of ::rb_cRational (taken as-is),
+ * - Instances of ::rb_cFloat (applies `#to_r`),
+ * - Instances of ::rb_cComplex (applies `#to_r`),
+ * - Instances of ::rb_cString (applies `#to_r`),
+ * - Other objects that respond to `#to_r`.
+ *
+ * It (possibly recursively) applies `#to_r` until both sides become either
+ * Integer or Rational, then divides them.
+ *
+ * As a special case, passing ::RUBY_Qundef to `den` is the same as passing
+ * `RB_INT2NUM(1)`.
+ *
+ * @param[in] num Numerator (see above).
+ * @param[in] den Denominator (see above).
+ * @exception rb_eTypeError Passed something not described above.
+ * @exception rb_eFloatDomainError `#to_r` produced Nan/Inf.
+ * @exception rb_eZeroDivError `#to_r` produced zero for `den`.
+ * @return An instance of ::rb_cRational whose value is `(num/den)r`.
+ *
+ * @internal
+ *
+ * This was the implementation of `Kernel#Rational` before, but they diverged.
+ */
+VALUE rb_Rational(VALUE num, VALUE den);
+
+/**
+ * Shorthand of `(x/1)r`. It practically converts it into a Rational of the
+ * identical value.
+ *
+ * @param[in] x ::rb_cInteger, ::rb_cRational, or something that responds to
+ * `#to_r`.
+ * @return An instance of ::rb_cRational, whose value is `(x/1)r`.
+ */
#define rb_Rational1(x) rb_Rational((x), INT2FIX(1))
+
+/** @alias{rb_Rational} */
#define rb_Rational2(x,y) rb_Rational((x), (y))
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries the numerator of the passed Rational.
+ *
+ * @param[in] rat An instance of ::rb_cRational.
+ * @return Its numerator part, which is an instance of ::rb_cInteger.
+ */
VALUE rb_rational_num(VALUE rat);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries the denominator of the passed Rational.
+ *
+ * @param[in] rat An instance of ::rb_cRational.
+ * @return Its denominator part, which is an instance of ::rb_cInteger
+ * greater than or equal to one..
+ */
VALUE rb_rational_den(VALUE rat);
-VALUE rb_flt_rationalize_with_prec(VALUE, VALUE);
-VALUE rb_flt_rationalize(VALUE);
+
+/**
+ * Simplified approximation of a float. It returns a rational `rat` which
+ * satisfies:
+ *
+ * ```
+ * flt - |prec| <= rat <= flt + |prec|
+ * ```
+ *
+ * ```ruby
+ * 3.141592.rationalize(0.001) # => (201/64)r
+ * 3.141592.rationalize(0.01)' # => (22/7)r
+ * 3.141592.rationalize(0.1)' # => (16/5)r
+ * 3.141592.rationalize(1)' # => (3/1)r
+ * ```
+ *
+ * @param[in] flt An instance of ::rb_cFloat to rationalise.
+ * @param[in] prec Another ::rb_cFloat, which is the "precision".
+ * @return Approximation of `flt`, in ::rb_cRational.
+ */
+VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec);
+
+/**
+ * Identical to rb_flt_rationalize_with_prec(), except it auto-detects
+ * appropriate precision depending on the passed value.
+ *
+ * @param[in] flt An instance of ::rb_cFloat to rationalise.
+ * @return Approximation of `flt`, in ::rb_cRational.
+ */
+VALUE rb_flt_rationalize(VALUE flt);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/re.h b/include/ruby/internal/intern/re.h
index dd7baef954..31f5593275 100644
--- a/include/ruby/internal/intern/re.h
+++ b/include/ruby/internal/intern/re.h
@@ -17,33 +17,232 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cRegexp.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* re.c */
+
+/**
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * This was a function that switched between memcmp and rb_memcicmp depending
+ * on then-called `ruby_ignorecase`, or the `$=` global variable. That feature
+ * was abandoned in sometime around version 1.9.0.
+ */
#define rb_memcmp memcmp
-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);
+
+/**
+ * Identical to st_locale_insensitive_strcasecmp(), except it is timing safe
+ * and returns something different.
+ *
+ * @param[in] s1 Comparison LHS.
+ * @param[in] s2 Comparison RHS.
+ * @param[in] n Comparison shall stop after first `n` bytes are scanned.
+ * @retval <0 `s1` is "less" than `s2`.
+ * @retval 0 Both sides converted into lowercase would be identical.
+ * @retval >0 `s1` is "greater" than `s2`.
+ * @note The "case" here means that of the POSIX Locale.
+ *
+ * @internal
+ *
+ * Can accept NULLs as long as n is also 0, and returns 0.
+ */
+int rb_memcicmp(const void *s1,const void *s2, long n);
+
+/**
+ * Asserts that the given MatchData is "occupied". MatchData shares its
+ * backend storages with its Regexp object. But programs can destructively
+ * tamper its contents. Calling this function beforehand shall prevent such
+ * modifications to spill over into other objects.
+ *
+ * @param[out] md Target instance of ::rb_cMatch.
+ * @post The object is "busy".
+ *
+ * @internal
+ *
+ * There is rb_match_unbusy internally, but extension libraries are left unable
+ * to do so.
+ */
+void rb_match_busy(VALUE md);
+
+/**
+ * Identical to rb_reg_nth_match(), except it just returns Boolean. This could
+ * skip allocating a returning string, resulting in reduced memory footprints
+ * if applicable.
+ *
+ * @param[in] n Match index.
+ * @param[in] md An instance of ::rb_cMatch.
+ * @exception rb_eTypeError `md` is not initialised.
+ * @retval RUBY_Qnil There is no `n`-th capture.
+ * @retval RUBY_Qfalse There is a `n`-th capture and is empty.
+ * @retval RUBY_Qtrue There is a `n`-th capture that has something.
+ *
+ * @internal
+ *
+ * @shyouhei wonders: why there are both rb_reg_match_defined() and
+ * rb_match_nth_defined, which are largely the same things, but do not share
+ * their implementations at all?
+ */
+VALUE rb_reg_nth_defined(int n, VALUE md);
+
+/**
+ * Queries the nth captured substring.
+ *
+ * @param[in] n Match index.
+ * @param[in] md An instance of ::rb_cMatch.
+ * @exception rb_eTypeError `md` is not initialised.
+ * @retval RUBY_Qnil There is no `n`-th capture.
+ * @retval otherwise An allocated instance of ::rb_cString containing
+ * the contents captured.
+ */
+VALUE rb_reg_nth_match(int n, VALUE md);
+
+/**
+ * Queries the index of the given named capture. Captures could be named. But
+ * that doesn't mean named ones are not indexed. A regular expression can mix
+ * named and non-named captures, and they are all indexed. This function
+ * converts from a name to its index.
+ *
+ * @param[in] match An instance of ::rb_cMatch.
+ * @param[in] backref Capture name, in String, Symbol, or Numeric.
+ * @exception rb_eIndexError No such named capture.
+ * @return The index of the given name.
+ */
int rb_reg_backref_number(VALUE match, VALUE backref);
-VALUE rb_reg_last_match(VALUE);
-VALUE rb_reg_match_pre(VALUE);
-VALUE rb_reg_match_post(VALUE);
-VALUE rb_reg_match_last(VALUE);
+
+/**
+ * This just returns the argument, stringified. What a poor name.
+ *
+ * @param[in] md An instance of ::rb_cMatch.
+ * @return Its 0th capture (i.e. entire matched string).
+ */
+VALUE rb_reg_last_match(VALUE md);
+
+/**
+ * The portion of the original string before the given match.
+ *
+ * @param[in] md An instance of ::rb_cMatch.
+ * @return Its "prematch". This is perl's ``$```.
+ */
+VALUE rb_reg_match_pre(VALUE md);
+
+/**
+ * The portion of the original string after the given match.
+ *
+ * @param[in] md An instance of ::rb_cMatch.
+ * @return Its "postmatch". This is perl's `$'`.
+ */
+VALUE rb_reg_match_post(VALUE md);
+
+/**
+ * The portion of the original string that captured at the very last.
+ *
+ * @param[in] md An instance of ::rb_cMatch.
+ * @return Its "lastmatch". This is perl's `$+`.
+ */
+VALUE rb_reg_match_last(VALUE md);
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_RB_REG_NEW_STR 1
-VALUE rb_reg_new_str(VALUE, int);
-VALUE rb_reg_new(const char *, long, int);
+
+/**
+ * Identical to rb_reg_new(), except it takes the expression in Ruby's string
+ * instead of C's.
+ *
+ * @param[in] src Source code in String.
+ * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE.
+ * @exception rb_eRegexpError `src` and `opts` do not interface.
+ * @return Allocated new instance of ::rb_cRegexp.
+ */
+VALUE rb_reg_new_str(VALUE src, int opts);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Creates a new Regular expression.
+ *
+ * @param[in] src Source code.
+ * @param[in] len `strlen(src)`.
+ * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE.
+ * @return Allocated new instance of ::rb_cRegexp.
+ */
+VALUE rb_reg_new(const char *src, long len, int opts);
+
+/**
+ * Allocates an instance of ::rb_cRegexp.
+ *
+ * @private
+ *
+ * Nobody should call this function. Regular expressions that are not
+ * initialised must not exist in the wild.
+ */
VALUE rb_reg_alloc(void);
+
+/**
+ * Initialises an instance of ::rb_cRegexp.
+ *
+ * @private
+ *
+ * This just raises for ordinal regexp objects. Extension libraries must not
+ * use.
+ */
VALUE rb_reg_init_str(VALUE re, VALUE s, int options);
-VALUE rb_reg_match(VALUE, VALUE);
-VALUE rb_reg_match2(VALUE);
-int rb_reg_options(VALUE);
+
+/**
+ * This is the match operator.
+ *
+ * @param[in] re An instance of ::rb_cRegexp.
+ * @param[in] str An instance of ::rb_cString.
+ * @exception rb_eTypeError `str` is not a string.
+ * @exception rb_eRegexpError Error inside of Onigmo (unlikely).
+ * @retval RUBY_Qnil Match failed.
+ * @retval otherwise Matched position (character index inside of
+ * `str`).
+ * @post `Regexp.last_match` is updated.
+ * @post `$&`, `$~`, etc., are updated.
+ * @note If you do this in ruby, named captures are assigned to local
+ * variable of the local scope. But that doesn't happen here. The
+ * assignment is done by the interpreter.
+ */
+VALUE rb_reg_match(VALUE re, VALUE str);
+
+/**
+ * Identical to rb_reg_match(), except it matches against rb_lastline_get()
+ * (or, the `$_`).
+ *
+ * @param[in] re An instance of ::rb_cRegexp.
+ * @exception rb_eRegexpError Error inside of Onigmo (unlikely).
+ * @retval RUBY_Qnil Match failed or `$_` is absent.
+ * @retval otherwise Matched position (character index inside of
+ * `$_`).
+ * @post `Regexp.last_match` is updated.
+ * @post `$&`, `$~`, etc., are updated.
+ */
+VALUE rb_reg_match2(VALUE re);
+
+/**
+ * Queries the options of the passed regular expression.
+ *
+ * @param[in] re An instance of ::rb_cRegexp.
+ * @return Its options.
+ * @note Possible return values are defined in Onigmo.h.
+ */
+int rb_reg_options(VALUE re);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/ruby.h b/include/ruby/internal/intern/ruby.h
index 9d9a71cf7a..efe61424ca 100644
--- a/include/ruby/internal/intern/ruby.h
+++ b/include/ruby/internal/intern/ruby.h
@@ -17,20 +17,60 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Process-global APIs.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* ruby.c */
+/** @alias{rb_get_argv} */
#define rb_argv rb_get_argv()
+
+/**
+ * The value of `$0` at process bootup.
+ *
+ * @note This is just a snapshot of `$0`, not the backend storage of it. `$0`
+ * could become something different because it is a writable global
+ * variable. Modifying it for instance affects `ps(1)` output. Don't
+ * assume they are synced.
+ */
RUBY_EXTERN VALUE rb_argv0;
+
+/* io.c */
+
+/**
+ * Queries the arguments passed to the current process that you can access from
+ * Ruby as `ARGV`.
+ *
+ * @return An array of strings containing arguments passed to the process.
+ */
VALUE rb_get_argv(void);
-void *rb_load_file(const char*);
-void *rb_load_file_str(VALUE);
+
+/* ruby.c */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Loads the given file. This function opens the given pathname for reading,
+ * parses the contents as a Ruby script, and returns an opaque "node" pointer.
+ * You can then pass it to ruby_run_node() for evaluation.
+ *
+ * @param[in] file File name, or "-" to read from stdin.
+ * @return Opaque "node" pointer.
+ */
+void *rb_load_file(const char *file);
+
+/**
+ * Identical to rb_load_file(), except it takes the argument as a Ruby's string
+ * instead of C's.
+ *
+ * @param[in] file File name, or "-" to read from stdin.
+ * @return Opaque "node" pointer.
+ */
+void *rb_load_file_str(VALUE file);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h
index 43d4cf354c..fabc287cd1 100644
--- a/include/ruby/internal/intern/select.h
+++ b/include/ruby/internal/intern/select.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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.
@@ -35,9 +35,11 @@
# include "ruby/internal/intern/select/largesize.h"
#elif defined(_WIN32)
# include "ruby/internal/intern/select/win32.h"
+# /** Does nothing (defined for compatibility). */
# define rb_fd_resize(n, f) ((void)(f))
#else
# include "ruby/internal/intern/select/posix.h"
+# /** Does nothing (defined for compatibility). */
# define rb_fd_resize(n, f) ((void)(f))
#endif
@@ -45,7 +47,39 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
struct timeval;
-int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
+/**
+ * Waits for multiple file descriptors at once. This is basically a wrapper of
+ * system-provided select() with releasing GVL, to allow other Ruby threads run
+ * in parallel.
+ *
+ * @param[in] nfds Max FD in everything passed, plus one.
+ * @param[in,out] rfds Set of FDs to wait for reads.
+ * @param[in,out] wfds Set of FDs to wait for writes.
+ * @param[in,out] efds Set of FDs to wait for OOBs.
+ * @param[in,out] timeout Max blocking duration.
+ * @retval -1 Failed, errno set.
+ * @retval 0 Timeout exceeded.
+ * @retval otherwise Total number of file descriptors returned.
+ * @post `rfds` contains readable FDs.
+ * @post `wfds` contains writable FDs.
+ * @post `efds` contains exceptional FDs.
+ * @post `timeout` is the time left.
+ * @note All pointers are allowed to be null pointers.
+ *
+ * Although backend threads can run in parallel of this function, touching a
+ * file descriptor from multiple threads could be problematic. For instance
+ * what happens when a thread closes a file descriptor that is selected by
+ * someone else, vastly varies among operating systems. You would better avoid
+ * touching an fd from more than one threads.
+ *
+ * @internal
+ *
+ * Although any file descriptors are possible here, it makes completely no
+ * sense to pass a descriptor that is not `O_NONBLOCK`. If you want to know
+ * the reason for this limitatuon in detail, you might find this thread super
+ * interesting: https://lkml.org/lkml/2004/10/6/117
+ */
+int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/select/largesize.h b/include/ruby/internal/intern/select/largesize.h
index ba56a159b1..d65f088c06 100644
--- a/include/ruby/internal/intern/select/largesize.h
+++ b/include/ruby/internal/intern/select/largesize.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
@@ -35,9 +35,6 @@
* `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)
@@ -66,26 +63,134 @@
struct timeval;
+/**
+ * The data structure which wraps the fd_set bitmap used by select(2). This
+ * allows Ruby to use FD sets larger than that allowed by historic limitations
+ * on modern platforms.
+ */
typedef struct {
- int maxfd;
- fd_set *fdset;
+ int maxfd; /**< Maximum allowed number of FDs. */
+ fd_set *fdset; /**< File descriptors buffer */
} 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);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * (Re-)initialises a fdset. One must be initialised before other `rb_fd_*`
+ * operations. Analogous to calling `malloc(3)` to allocate an `fd_set`.
+ *
+ * @param[out] f An fdset to squash.
+ * @post `f` holds no file descriptors.
+ */
+void rb_fd_init(rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Destroys the ::rb_fdset_t, releasing any memory and resources it used. It
+ * must be reinitialised using rb_fd_init() before future use. Analogous to
+ * calling `free(3)` to release memory for an `fd_set`.
+ *
+ * @param[out] f An fdset to squash.
+ * @post `f` holds no file descriptors.
+ */
+void rb_fd_term(rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Wipes out the current set of FDs.
+ *
+ * @param[out] f The fdset to clear.
+ * @post `f` has no FDs.
+ */
+void rb_fd_zero(rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Sets an fd to a fdset.
+ *
+ * @param[in] fd A file descriptor.
+ * @param[out] f Target fdset.
+ * @post `f` holds `fd`.
+ */
+void rb_fd_set(int fd, rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Releases a specific FD from the given fdset.
+ *
+ * @param[in] fd Target FD.
+ * @param[out] f The fdset that holds `fd`.
+ * @post `f` doesn't hold n.
+ */
+void rb_fd_clr(int fd, rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the given FD is in the given set.
+ *
+ * @param[in] fd Target FD.
+ * @param[in] f The fdset to scan.
+ * @retval 1 Yes there is.
+ * @retval 0 No there isn't.
+ * @see http://www.freebsd.org/cgi/query-pr.cgi?pr=91421
+ */
+int rb_fd_isset(int fd, const rb_fdset_t *f);
+
+/**
+ * Destructively overwrites an fdset with another.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @param[in] max Maximum number of file descriptors to copy.
+ * @post `dst` is a copy of `src`.
+ */
+void rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max);
+
+/**
+ * Identical to rb_fd_copy(), except it copies unlimited number of file
+ * descriptors.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @post `dst` is a copy of `src`.
+ */
void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
-int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
+
+/**
+ * Waits for multiple file descriptors at once.
+ *
+ * @param[in] nfds Max FD in everything passed, plus one.
+ * @param[in,out] rfds Set of FDs to wait for reads.
+ * @param[in,out] wfds Set of FDs to wait for writes.
+ * @param[in,out] efds Set of FDs to wait for OOBs.
+ * @param[in,out] timeout Max blocking duration.
+ * @retval -1 Failed, errno set.
+ * @retval 0 Timeout exceeded.
+ * @retval otherwise Total number of file descriptors returned.
+ * @post `rfds` contains readable FDs.
+ * @post `wfds` contains writable FDs.
+ * @post `efds` contains exceptional FDs.
+ * @post `timeout` is the time left.
+ * @note All pointers are allowed to be null pointers.
+ */
+int rb_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_NONNULL(())
RBIMPL_ATTR_PURE()
-/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+/**
+ * Raw pointer to `fd_set`.
+ *
+ * @param[in] f Target fdset.
+ * @retval NULL `f` is already terminated by rb_fd_term().
+ * @retval otherwise Underlying fd_set.
+ *
+ * @internal
+ *
+ * Extension library must not touch raw pointers. It was a bad idea to let
+ * them use it.
+ */
static inline fd_set *
rb_fd_ptr(const rb_fdset_t *f)
{
@@ -94,6 +199,12 @@ rb_fd_ptr(const rb_fdset_t *f)
RBIMPL_ATTR_NONNULL(())
RBIMPL_ATTR_PURE()
+/**
+ * It seems this function has no use. Maybe just remove?
+ *
+ * @param[in] f A set.
+ * @return Number of file descriptors stored.
+ */
static inline int
rb_fd_max(const rb_fdset_t *f)
{
diff --git a/include/ruby/internal/intern/select/posix.h b/include/ruby/internal/intern/select/posix.h
index 6c1092b39d..0a9b0b2e51 100644
--- a/include/ruby/internal/intern/select/posix.h
+++ b/include/ruby/internal/intern/select/posix.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs to provide ::rb_fd_select().
*/
#include "ruby/internal/config.h"
@@ -30,17 +30,41 @@
# include <unistd.h> /* for select(2) (archaic UNIX) */
#endif
-#include "ruby/internal/attr/pure.h"
#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
+/**
+ * The data structure which wraps the fd_set bitmap used by `select(2)`. This
+ * allows Ruby to use FD sets larger than what has been historically allowed on
+ * modern platforms.
+ *
+ * @internal
+ *
+ * ... but because this header file is included only when the system is with
+ * that "historic restrictions", this is nothing more than an alias of fd_set.
+ */
typedef fd_set rb_fdset_t;
+/** Clears the given ::rb_fdset_t. */
#define rb_fd_zero FD_ZERO
+
+/** Sets the given fd to the ::rb_fdset_t. */
#define rb_fd_set FD_SET
+
+/** Unsets the given fd from the ::rb_fdset_t. */
#define rb_fd_clr FD_CLR
+
+/** Queries if the given fd is in the ::rb_fdset_t. */
#define rb_fd_isset FD_ISSET
+
+/** Initialises the :given :rb_fdset_t. */
#define rb_fd_init FD_ZERO
+
+/** Waits for multiple file descriptors at once. */
#define rb_fd_select select
+
/**@cond INTERNAL_MACRO */
#define rb_fd_copy rb_fd_copy
#define rb_fd_dup rb_fd_dup
@@ -48,20 +72,50 @@ typedef fd_set rb_fdset_t;
#define rb_fd_max rb_fd_max
/** @endcond */
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NOALIAS()
+/**
+ * Destructively overwrites an fdset with another.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @param[in] n Unused parameter.
+ * @post `dst` is a copy of `src`.
+ */
static inline void
rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n)
{
*dst = *src;
}
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NOALIAS()
+/**
+ * Destructively overwrites an fdset with another.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @post `dst` is a copy of `src`.
+ */
static inline void
-rb_fd_dup(rb_fdset_t *dst, const fd_set *src, int n)
+rb_fd_dup(rb_fdset_t *dst, const fd_set *src)
{
*dst = *src;
}
RBIMPL_ATTR_PURE()
/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+/**
+ * Raw pointer to `fd_set`.
+ *
+ * @param[in] f Target fdset.
+ * @return Underlying fd_set.
+ *
+ * @internal
+ *
+ * Extension library must not touch raw pointers. It was a bad idea to let
+ * them use it.
+ */
static inline fd_set *
rb_fd_ptr(rb_fdset_t *f)
{
@@ -69,14 +123,22 @@ rb_fd_ptr(rb_fdset_t *f)
}
RBIMPL_ATTR_CONST()
+/**
+ * It seems this function has no use. Maybe just remove?
+ *
+ * @param[in] f A set.
+ * @return Number of file descriptors stored.
+ */
static inline int
rb_fd_max(const rb_fdset_t *f)
{
return FD_SETSIZE;
}
-/* :FIXME: What are these? They don't exist for shibling implementations. */
+/** @cond INTERNAL_MACRO */
+/* :FIXME: What are these? They don't exist for sibling implementations. */
#define rb_fd_init_copy(d, s) (*(d) = *(s))
#define rb_fd_term(f) ((void)(f))
+/** @endcond */
#endif /* RBIMPL_INTERN_SELECT_POSIX_H */
diff --git a/include/ruby/internal/intern/select/win32.h b/include/ruby/internal/intern/select/win32.h
index ef75a0f760..edaf7a8523 100644
--- a/include/ruby/internal/intern/select/win32.h
+++ b/include/ruby/internal/intern/select/win32.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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 */
@@ -41,21 +41,83 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
struct timeval;
+/**
+ * The data structure which wraps the fd_set bitmap used by select(2). This
+ * allows Ruby to use FD sets larger than that allowed by historic limitations
+ * on modern platforms.
+ */
typedef struct {
- int capa;
- fd_set *fdset;
+ int capa; /**< Maximum allowed number of FDs. */
+ fd_set *fdset; /**< File descriptors buffer. */
} 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);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * (Re-)initialises a fdset. One must be initialised before other `rb_fd_*`
+ * operations. Analogous to calling `malloc(3)` to allocate an `fd_set`.
+ *
+ * @param[out] f An fdset to squash.
+ * @post `f` holds no file descriptors.
+ *
+ * @internal
+ *
+ * Can't this leak memory if the same `f` is passed twice...?
+ */
+void rb_fd_init(rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Destroys the ::rb_fdset_t, releasing any memory and resources it used. It
+ * must be reinitialised using rb_fd_init() before future use. Analogous to
+ * calling `free(3)` to release memory for an `fd_set`.
+ *
+ * @param[out] f An fdset to squash.
+ * @post `f` holds no file descriptors.
+ */
+void rb_fd_term(rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Sets an fd to a fdset.
+ *
+ * @param[in] fd A file descriptor.
+ * @param[out] f Target fdset.
+ * @post `f` holds `fd`.
+ */
+void rb_fd_set(int fd, rb_fdset_t *f);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Destructively overwrites an fdset with another.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @param[in] max Maximum number of file descriptors to copy.
+ * @post `dst` is a copy of `src`.
+ */
+void rb_w32_fd_copy(rb_fdset_t *dst, const fd_set *src, int max);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_w32_fd_copy(), except it copies unlimited number of file
+ * descriptors.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @post `dst` is a copy of `src`.
+ */
void rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_NONNULL(())
RBIMPL_ATTR_NOALIAS()
+/**
+ * Wipes out the current set of FDs.
+ *
+ * @param[out] f The fdset to clear.
+ * @post `f` has no FDs.
+ */
static inline void
rb_fd_zero(rb_fdset_t *f)
{
@@ -63,6 +125,13 @@ rb_fd_zero(rb_fdset_t *f)
}
RBIMPL_ATTR_NONNULL(())
+/**
+ * Releases a specific FD from the given fdset.
+ *
+ * @param[in] n Target FD.
+ * @param[out] f The fdset that holds `n`.
+ * @post `f` doesn't hold n.
+ */
static inline void
rb_fd_clr(int n, rb_fdset_t *f)
{
@@ -70,6 +139,14 @@ rb_fd_clr(int n, rb_fdset_t *f)
}
RBIMPL_ATTR_NONNULL(())
+/**
+ * Queries if the given FD is in the given set.
+ *
+ * @param[in] n Target FD.
+ * @param[in] f The fdset to scan.
+ * @retval 1 Yes there is.
+ * @retval 0 No there isn't.
+ */
static inline int
rb_fd_isset(int n, rb_fdset_t *f)
{
@@ -77,6 +154,14 @@ rb_fd_isset(int n, rb_fdset_t *f)
}
RBIMPL_ATTR_NONNULL(())
+/**
+ * Destructively overwrites an fdset with another.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @param[in] n Maximum number of file descriptors to copy.
+ * @post `dst` is a copy of `src`.
+ */
static inline void
rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n)
{
@@ -84,12 +169,45 @@ rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n)
}
RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_fd_copy(), except it copies unlimited number of file
+ * descriptors.
+ *
+ * @param[out] dst Target fdset.
+ * @param[in] src Source fdset.
+ * @post `dst` is a copy of `src`.
+ */
static inline void
rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
{
rb_w32_fd_dup(dst, src);
}
+/**
+ * Waits for multiple file descriptors at once.
+ *
+ * @param[in] n Max FD in everything passed, plus one.
+ * @param[in,out] rfds Set of FDs to wait for reads.
+ * @param[in,out] wfds Set of FDs to wait for writes.
+ * @param[in,out] efds Set of FDs to wait for OOBs.
+ * @param[in,out] timeout Max blocking duration.
+ * @retval -1 Failed, errno set.
+ * @retval 0 Timeout exceeded.
+ * @retval otherwise Total number of file descriptors returned.
+ * @post `rfds` contains readable FDs.
+ * @post `wfds` contains writable FDs.
+ * @post `efds` contains exceptional FDs.
+ * @post `timeout` is the time left.
+ * @note All pointers are allowed to be null pointers.
+ *
+ * @internal
+ *
+ * This can wait for `SOCKET` and `HANDLE` at once. In order to achieve that
+ * property we heavily touch the internals of MSVCRT. We `CreateFile` a
+ * `"NUL"` alongside of a socket and directly manipulate its `struct ioinfo`.
+ * This is of course a very dirty hack. If we could design the API today we
+ * could use `CancellIoEx`. But we are older than that Win32 API.
+ */
static inline int
rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
{
@@ -103,7 +221,18 @@ rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct
RBIMPL_ATTR_NONNULL(())
RBIMPL_ATTR_PURE()
-/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+/**
+ * Raw pointer to `fd_set`.
+ *
+ * @param[in] f Target fdset.
+ * @retval NULL `f` is already terminated by rb_fd_term().
+ * @retval otherwise Underlying fd_set.
+ *
+ * @internal
+ *
+ * Extension library must not touch raw pointers. It was a bad idea to let
+ * them use it.
+ */
static inline fd_set *
rb_fd_ptr(const rb_fdset_t *f)
{
@@ -111,7 +240,13 @@ rb_fd_ptr(const rb_fdset_t *f)
}
RBIMPL_ATTR_NONNULL(())
-RBIMPL_ATTR_PURE()
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/**
+ * It seems this function has no use. Maybe just remove?
+ *
+ * @param[in] f A set.
+ * @return Number of file descriptors stored.
+ */
static inline int
rb_fd_max(const rb_fdset_t *f)
{
diff --git a/include/ruby/internal/intern/signal.h b/include/ruby/internal/intern/signal.h
index 8739c51f53..84f7558404 100644
--- a/include/ruby/internal/intern/signal.h
+++ b/include/ruby/internal/intern/signal.h
@@ -17,22 +17,135 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Signal handling APIs.
*/
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* signal.c */
-VALUE rb_f_kill(int, const VALUE*);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Sends a signal ("kills") to processes.
+ *
+ * The first argument is the signal, either in:
+ *
+ * - Numerical representation (e.g. `9`), or
+ * - Textual representation of canonical (e.g. `:SIGKILL`) name or
+ * abbreviated (e.g. `:KILL`) name, either in ::rb_cSymbol or ::rb_cString.
+ *
+ * All the remaining arguments are numerical representations of process IDs.
+ * This function iterates over them to send the specified signal.
+ *
+ * You can specify both negative PIDs and negative signo to this function:
+ *
+ * ```
+ * sig \ pid | >= 1 | == 0 | == -1 | <= -2
+ * ===========+======+======+=======+=======
+ * > 0 | #1 | #2 | #3 | #4
+ * == 0 | #5 | #6 | #7 | #8
+ * < 0 | #9 | #10 | #11
+ * ```
+ *
+ * - Case #1: When signo and PID are both positive, this function sends the
+ * specified signal to the specified process (intuitive).
+ *
+ * - Case #2: When signo is positive and PID is zero, this function sends
+ * that signal to the current process group.
+ *
+ * - Case #3: When signo is positive and PID is -1, this function sends that
+ * signal to everything that the current process is allowed to kill.
+ *
+ * - Case #4: When signo is positive and PID is negative (but not -1), this
+ * function sends that signal to every processes in a process group, whose
+ * process group ID is the absolute value of the passed PID.
+ *
+ * - Case #5: When signo is zero and PID is positive, this function just
+ * checks for the existence of the specified process and doesn't send
+ * anything to anyone. In case the process is absent `Errno::ESRCH` is
+ * raised.
+ *
+ * - Case #6: When signo and PID are both zero, this function checks for the
+ * existence of the current process group. And it must do. This function
+ * is effectively a no-op then.
+ *
+ * - Case #7: When signo is zero and PID is -1, this function checks if there
+ * is any other process that the current process can kill. At least init
+ * (PID 1) must exist, so this must not fail.
+ *
+ * - Case #8: When signo is zero and PID is negative (but not -1), this
+ * function checks if there is a process group whose process group ID is
+ * the absolute value of the passed PID. In case the process group is
+ * absent `Errno::ESRCH` is raised.
+ *
+ * - Case #9: When signo is negative and PID is positive, this function sends
+ * the absolute value of the passed signo to the process group specified as
+ * the PID.
+ *
+ * - Case #10: When signo is negative and PID is zero, it is highly expected
+ * that this function sends the absolute value of the passed signo to the
+ * current process group. Strictly speaking, IEEE Std 1003.1-2017
+ * specifies that this (`killpg(3posix)` with an argument of zero) is an
+ * undefined behaviour. But no operating system is known so far that does
+ * things differently.
+ *
+ * - Case #11: When signo and PID are both negative, the behaviour of this
+ * function depends on how `killpg(3)` works. On Linux, it seems such
+ * attempt is strictly prohibited and `Errno::EINVAL` is raised. But on
+ * macOS, it seems it tries to to send the signal actually to the process
+ * group.
+ *
+ * @note Above description is in fact different from how `kill(2)` works.
+ * We interpret the passed arguments before passing them through to
+ * system calls.
+ * @param[in] argc Number of objects in `argv`.
+ * @param[in] argv Signal, followed by target PIDs.
+ * @exception rb_eArgError Unknown signal name.
+ * @exception rb_eSystemCallError Various errors sending signal to processes.
+ * @return Something numeric. The meaning of this return value is unclear.
+ * It seems in case of #1 above, this could be the body count. But
+ * other cases remain mysterious.
+ */
+VALUE rb_f_kill(int argc, const VALUE *argv);
+
+/* This must be private, @shyouhei guesses. */
#ifdef POSIX_SIGNAL
#define posix_signal ruby_posix_signal
void (*posix_signal(int, void (*)(int)))(int);
#endif
-const char *ruby_signal_name(int);
-void ruby_default_signal(int);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries the name of the signal. It returns for instance `"KILL"` for
+ * SIGKILL.
+ *
+ * @param[in] signo Signal number to query.
+ * @retval 0 No such signal.
+ * @retval otherwise A pointer to a static C string that is the name of
+ * the signal.
+ * @warning Don't free the return value.
+ */
+const char *ruby_signal_name(int signo);
+
+/**
+ * Pretends as if there was no custom signal handler. This function sets the
+ * signal action to SIG_DFL, then kills itself.
+ *
+ * @param[in] sig The signal.
+ * @post Previous signal handler is lost.
+ * @post Passed signal is sent to the current process.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't understand the needs of this function being visible from
+ * extension libraries.
+ */
+void ruby_default_signal(int sig);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/sprintf.h b/include/ruby/internal/intern/sprintf.h
index 2c90548353..aedc0f9ab1 100644
--- a/include/ruby/internal/intern/sprintf.h
+++ b/include/ruby/internal/intern/sprintf.h
@@ -17,26 +17,142 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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).
+ * extension libraries. They could be written in C++98.
+ * @brief Our own private `printf(3)`.
*/
#include "ruby/internal/attr/format.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* sprintf.c */
-VALUE rb_f_sprintf(int, const VALUE*);
+/**
+ * Identical to rb_str_format(), except how the arguments are arranged.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv A format string, followed by its arguments.
+ * @return A rendered new instance of ::rb_cString.
+ *
+ * @internal
+ *
+ * You can safely pass NULL to `argv`. Doesn't make any sense though.
+ */
+VALUE rb_f_sprintf(int argc, const VALUE *argv);
+
+RBIMPL_ATTR_NONNULL((1))
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
-VALUE rb_sprintf(const char*, ...);
-VALUE rb_vsprintf(const char*, va_list);
+/**
+ * Ruby's extended `sprintf(3)`. We ended up reinventing the entire `printf`
+ * business because we don't want to depend on locales. OS-provided `printf`
+ * routines might or might not, which caused instabilities of the result
+ * strings.
+ *
+ * The format sequence is a mixture of format specifiers and other verbatim
+ * contents. Each format specifier starts with a `%`, and has the following
+ * structure:
+ *
+ * ```
+ * %[flags][width][.precision][length]conversion
+ * ```
+ *
+ * This function supports flags of ` `, `#`, `+`, `-`, `0`, width of
+ * non-negative decimal integer and `*`, precision of non-negative decimal
+ * integers and `*`, length of `L`, `h`, `t`, `z`, `l`, `ll`, `q`, conversions
+ * of `A`, `D`, `E`, `G`, `O`, `U`, `X`, `a`, `c`, `d`, `e`, `f`, `g`, `i`,
+ * `n`, `o`, `p`, `s`, `u`, `x`, and `%`. In case of `_WIN32` it also supports
+ * `I`. And additionally, it supports magical `PRIsVALUE` macro that can
+ * stringise arbitrary Ruby objects:
+ *
+ * ```CXX
+ * rb_sprintf("|%"PRIsVALUE"|", RUBY_Qtrue); // => "|true|"
+ * rb_sprintf("%+"PRIsVALUE, rb_stdin); // => "#<IO:<STDIN>>"
+ * ```
+ *
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ... Variadic number of contents to format.
+ * @return A rendered new instance of ::rb_cString.
+ *
+ * @internal
+ *
+ * :FIXME: We can improve this document.
+ */
+VALUE rb_sprintf(const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
+/**
+ * Identical to rb_sprintf(), except it takes a `va_list`.
+ *
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ap Contents to format.
+ * @return A rendered new instance of ::rb_cString.
+ */
+VALUE rb_vsprintf(const char *fmt, va_list ap);
+RBIMPL_ATTR_NONNULL((2))
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
-VALUE rb_str_catf(VALUE, const char*, ...);
-VALUE rb_str_vcatf(VALUE, const char*, va_list);
-VALUE rb_str_format(int, const VALUE *, VALUE);
+/**
+ * Identical to rb_sprintf(), except it renders the output to the specified
+ * object rather than creating a new one.
+ *
+ * @param[out] dst String to modify.
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ... Variadic number of contents to format.
+ * @exception rb_eTypeError `dst` is not a String.
+ * @return Passed `dst`.
+ * @post `dst` has the rendered output appended to its end.
+ */
+VALUE rb_str_catf(VALUE dst, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((2))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
+/**
+ * Identical to rb_str_catf(), except it takes a `va_list`. It can also be
+ * seen as a routine identical to rb_vsprintf(), except it renders the output
+ * to the specified object rather than creating a new one.
+ *
+ * @param[out] dst String to modify.
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ap Contents to format.
+ * @exception rb_eTypeError `dst` is not a String.
+ * @return Passed `dst`.
+ * @post `dst` has the rendered output appended to its end.
+ */
+VALUE rb_str_vcatf(VALUE dst, const char *fmt, va_list ap);
+
+/**
+ * Formats a string.
+ *
+ * Returns the string resulting from applying `fmt` to `argv`. The format
+ * sequence is a mixture of format specifiers and other verbatim contents.
+ * Each format specifier starts with a `%`, and has the following structure:
+ *
+ * ```
+ * %[flags][width][.precision]type
+ * ```
+ *
+ * ... which is different from that of rb_sprintf(). Because ruby has no
+ * `short` or `long`, there is no way to specify a "length" of an argument.
+ *
+ * This function supports flags of ` `, `#`, `+`, `-`, `<>`, `{}`, with of
+ * non-negative decimal integer and `$`, `*`, precision of non-negative decimal
+ * integer and `$`, `*`, type of `A`, `B`, `E`, `G`, `X`, `a`, `b`, `c`, `d`,
+ * `e`, `f`, `g`, `i`, `o`, `p`, `s`, `u`, `x`, `%`. This list is also
+ * (largely the same but) not identical to that of rb_sprintf().
+ *
+ * @param[in] argc Number of objects in `argv`.
+ * @param[in] argv Format arguments.
+ * @param[in] fmt A printf-like format specifier.
+ * @exception rb_eTypeError `fmt` is not a string.
+ * @exception rb_eArgError Failed to parse `fmt`.
+ * @return A rendered new instance of ::rb_cString.
+ * @note Everything it takes must be Ruby objects.
+ *
+ */
+VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h
index a590b2043e..3083125e56 100644
--- a/include/ruby/internal/intern/string.h
+++ b/include/ruby/internal/intern/string.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cString.
*/
#include "ruby/internal/config.h"
@@ -34,6 +34,7 @@
# include <stdint.h>
#endif
+#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/constant_p.h"
@@ -45,107 +46,1320 @@
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*);
+
+/**
+ * Allocates an instance of ::rb_cString.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of
+ * "binary" encoding, whose contents are verbatim copy of `ptr`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ */
+VALUE rb_str_new(const char *ptr, long len);
+
+/**
+ * Identical to rb_str_new(), except it assumes the passed pointer is a pointer
+ * to a C string.
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @exception rb_eArgError `ptr` is a null pointer.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose
+ * contents are verbatim copy of `ptr`.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_str_new_cstr(const char *ptr);
+
+/**
+ * Identical to rb_str_new_cstr(), except it takes a Ruby's string instead of
+ * C's. Implementation wise it creates a string that shares the backend memory
+ * region with the receiver. So the name. But there is no way for extension
+ * libraries to know if a string is of such variant.
+ *
+ * @param[in] str An object of ::RString.
+ * @return An allocated instance of ::rb_cString, which shares the
+ * encoding, length, and contents with the passed string.
+ * @pre `str` must not be any arbitrary object except ::RString.
+ * @note Use #StringValue to enforce the precondition.
+ */
+VALUE rb_str_new_shared(VALUE str);
+
+/**
+ * Creates a frozen copy of the string, if necessary. This function does
+ * nothing when the passed string is already frozen. Otherwise, it allocates a
+ * copy of it, which is frozen. The passed string is untouched either ways.
+ *
+ * @param[in] str An object of ::RString.
+ * @return Something frozen.
+ * @pre `str` must not be any arbitrary object except ::RString.
+ * @note Use #StringValue to enforce the precondition.
+ */
+VALUE rb_str_new_frozen(VALUE str);
+
+/**
+ * Identical to rb_str_new(), except it takes the class of the allocating
+ * object.
+ *
+ * @param[in] obj A string-ish object.
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of the class of `obj`, of `len` bytes length, of
+ * "binary" encoding, whose contents are verbatim copy of `ptr`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ *
+ * @internal
+ *
+ * Why it doesn't take an instance of ::rb_cClass?
+ */
+VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len);
+
+/**
+ * Identical to rb_str_new(), except it generates a string of "default
+ * external" encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "default external" is fully defined over
+ * the given contents, then the return value is a string of
+ * "default external" encoding, whose contents are the converted
+ * ones. Otherwise the string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ */
+VALUE rb_external_str_new(const char *ptr, long len);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_external_str_new(), except it assumes the passed pointer is
+ * a pointer to a C string. It can also be seen as a routine identical to
+ * rb_str_new_cstr(), except it generates a string of "default external"
+ * encoding.
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "default external" is fully defined over
+ * the given contents, then the return value is a string of
+ * "default external" encoding, whose contents are the converted
+ * ones. Otherwise the string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_external_str_new_cstr(const char *ptr);
+
+/**
+ * Identical to rb_str_new(), except it generates a string of "locale"
+ * encoding. It can also be seen as a routine identical to
+ * rb_external_str_new(), except it generates a string of "locale" encoding
+ * instead of "default external" encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "locale" is fully defined over the given
+ * contents, then the return value is a string of "locale"
+ * encoding, whose contents are the converted ones. Otherwise the
+ * string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ */
+VALUE rb_locale_str_new(const char *ptr, long len);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_locale_str_new(), except it assumes the passed pointer is a
+ * pointer to a C string. It can also be seen as a routine identical to
+ * rb_external_str_new_cstr(), except it generates a string of "locale"
+ * encoding instead of "default external".
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "locale" is fully defined over the given
+ * contents, then the return value is a string of "locale"
+ * encoding, whose contents are the converted ones. Otherwise the
+ * string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_locale_str_new_cstr(const char *ptr);
+
+/**
+ * Identical to rb_str_new(), except it generates a string of "filesystem"
+ * encoding. It can also be seen as a routine identical to
+ * rb_external_str_new(), except it generates a string of "filesystem" encoding
+ * instead of "default external" encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "filesystem" is fully defined over the
+ * given contents, then the return value is a string of
+ * "filesystem" encoding, whose contents are the converted ones.
+ * Otherwise the string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ */
+VALUE rb_filesystem_str_new(const char *ptr, long len);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_filesystem_str_new(), except it assumes the passed pointer
+ * is a pointer to a C string. It can also be seen as a routine identical to
+ * rb_external_str_new_cstr(), except it generates a string of "filesystem"
+ * encoding instead of "default external".
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "filesystem" is fully defined over the
+ * given contents, then the return value is a string of
+ * "filesystem" encoding, whose contents are the converted ones.
+ * Otherwise the string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_filesystem_str_new_cstr(const char *ptr);
+
+/**
+ * Allocates a "string buffer". A string buffer here is an instance of
+ * ::rb_cString, whose capacity is bigger than the length of it. If you can
+ * say that a string grows to a specific amount of bytes, this could be
+ * effective than resizing a string over and over again and again.
+ *
+ * @param[in] capa Designed capacity of the generating string.
+ * @return An empty string, of "binary" encoding, whose capacity is `capa`.
+ */
+VALUE rb_str_buf_new(long capa);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is a rb_str_buf_new() + rb_str_buf_cat() combo.
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose
+ * contents are verbatim copy of `ptr`.
+ * @pre `ptr` must not be a null pointer.
+ *
+ * @internal
+ *
+ * This must be identical to rb_str_new_cstr(), except done in inefficient way?
+ * @shyouhei doesn't understand why this is not a simple alias.
+ */
+VALUE rb_str_buf_new_cstr(const char *ptr);
+
+/**
+ * Allocates a "temporary" string. This is a hidden empty string. Handy on
+ * occasions.
+ *
+ * @param[in] len Designed length of the string.
+ * @return A hidden, empty string.
+ * @see rb_obj_hide()
+ */
+VALUE rb_str_tmp_new(long len);
+
+/**
+ * Identical to rb_str_new(), except it generates a string of "US ASCII"
+ * encoding. This is different from rb_external_str_new(), not only for the
+ * output encoding, but also it doesn't convert the contents.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of
+ * "US ASCII" encoding, whose contents are verbatim copy of `ptr`.
+ */
+VALUE rb_usascii_str_new(const char *ptr, long len);
+
+/**
+ * Identical to rb_str_new_cstr(), except it generates a string of "US ASCII"
+ * encoding. It can also be seen as a routine Identical to
+ * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a
+ * C string.
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @exception rb_eArgError `ptr` is a null pointer.
+ * @return An instance of ::rb_cString, of "US ASCII" encoding, whose
+ * contents are verbatim copy of `ptr`.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_usascii_str_new_cstr(const char *ptr);
+
+/**
+ * Identical to rb_str_new(), except it generates a string of "UTF-8" encoding.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of
+ * "UTF-8" encoding, whose contents are verbatim copy of `ptr`.
+ */
+VALUE rb_utf8_str_new(const char *ptr, long len);
+
+/**
+ * Identical to rb_str_new_cstr(), except it generates a string of "UTF-8"
+ * encoding. It can also be seen as a routine Identical to
+ * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a
+ * C string.
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @exception rb_eArgError `ptr` is a null pointer.
+ * @return An instance of ::rb_cString, of "UTF-8" encoding, whose contents
+ * are verbatim copy of `ptr`.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_utf8_str_new_cstr(const char *ptr);
+
/**
+ * @name Special strings that are backended by C string literals.
+ *
* *_str_new_static functions are intended for C string literals.
* They require memory in the range [ptr, ptr+len] to always be readable.
* Note that this range covers a total of len + 1 bytes.
+ *
+ * @{
+ */
+
+/**
+ * Identical to rb_str_new(), except it takes a C string literal.
+ *
+ * @param[in] ptr A C string literal.
+ * @param[in] len `strlen(ptr)`.
+ * @exception rb_eArgError `len` out of range of `size_t`.
+ * @pre `ptr` must be a C string constant.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose backend
+ * storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ *
+ * @internal
+ *
+ * Surprisingly it can take NULL, and generates an empty string.
*/
VALUE rb_str_new_static(const char *ptr, long len);
+
+/**
+ * Identical to rb_str_new_static(), except it generates a string of "US ASCII"
+ * encoding instead of "binary". It can also be seen as a routine identical to
+ * rb_usascii_str_new(), except it takes a C string literal.
+ *
+ * @param[in] ptr A C string literal.
+ * @param[in] len `strlen(ptr)`.
+ * @exception rb_eArgError `len` out of range of `size_t`.
+ * @pre `ptr` must be a C string constant.
+ * @return An instance of ::rb_cString, of "US ASCII" encoding, whose
+ * backend storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ */
VALUE rb_usascii_str_new_static(const char *ptr, long len);
+
+/**
+ * Identical to rb_str_new_static(), except it generates a string of "UTF-8"
+ * encoding instead of "binary". It can also be seen as a routine identical to
+ * rb_utf8_str_new(), except it takes a C string literal.
+ *
+ * @param[in] ptr A C string literal.
+ * @param[in] len `strlen(ptr)`.
+ * @exception rb_eArgError `len` out of range of `size_t`.
+ * @pre `ptr` must be a C string constant.
+ * @return An instance of ::rb_cString, of "UTF-8" encoding, whose backend
+ * storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ */
VALUE rb_utf8_str_new_static(const char *ptr, long len);
-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);
+
+/** @} */
+
+/**
+ * Identical to rb_interned_str(), except it takes a Ruby's string instead of
+ * C's. It can also be seen as a routine identical to to rb_str_new_shared(),
+ * except it returns an infamous "f"string.
+ *
+ * @param[in] str An object of ::RString.
+ * @return An instance of ::rb_cString, either cached or allocated, which
+ * has the identical encoding, length, and contents with the passed
+ * string.
+ * @pre `str` must not be any arbitrary object except ::RString.
+ * @note Use #StringValue to enforce the precondition.
+ *
+ * @internal
+ *
+ * It actually finds or creates a fstring of the needed property, and
+ * destructively modifies the receiver behind-the-scene so that it becomes a
+ * shared string whose parent is the returning fstring.
+ */
+VALUE rb_str_to_interned_str(VALUE str);
+
+/**
+ * Identical to rb_str_new(), except it returns an infamous "f"string. What is
+ * a fstring? Well it is a special subkind of strings that is immutable,
+ * deduped globally, and managed by our GC. It is much like a Symbol (in fact
+ * Symbols are dynamic these days and are backended using fstrings). This
+ * concept has been silently introduced at some point in 2.x era. Since then
+ * it gained wider acceptance in the core. Starting from 3.x extension
+ * libraries can also generate ones.
+ *
+ * @param[in] ptr A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eArgError `len` is negative.
+ * @return A found or created instance of ::rb_cString, of `len` bytes
+ * length, of "binary" encoding, whose contents are identical to
+ * that of `ptr`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `ptr`.
+ */
+VALUE rb_interned_str(const char *ptr, long len);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_interned_str(), except it assumes the passed pointer is a
+ * pointer to a C's string. It can also be seen as a routine identical to to
+ * rb_str_to_interned_str(), except it takes a C's string instead of Ruby's.
+ * Or it can also be seen as a routine identical to rb_str_new_cstr(), except
+ * it returns an infamous "f"string.
+ *
+ * @param[in] ptr A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose
+ * contents are verbatim copy of `ptr`.
+ * @pre `ptr` must not be a null pointer.
+ */
+VALUE rb_interned_str_cstr(const char *ptr);
+
+/**
+ * Destroys the given string for no reason.
+ *
+ * @warning DO NOT USE IT.
+ * @warning Leave this task to our GC.
+ * @warning It was a bad idea at the first place to let you know about it.
+ *
+ * @param[out] str The string to be executed.
+ * @post The given string no longer exists.
+ * @note Maybe `String#clear` could be what you want.
+ *
+ * @internal
+ *
+ * Should have moved this to `internal/string.h`.
+ */
+void rb_str_free(VALUE str);
+
+/**
+ * Replaces the contents of the former with the latter.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source object.
+ * @pre Both objects must not be any arbitrary objects except
+ * ::RString.
+ * @post `dst`'s former components are abandoned. It now has the
+ * identical encoding, length, and contents to `src`.
+ * @see rb_str_replace()
+ *
+ * @internal
+ *
+ * @shyouhei doesn't understand why this is useful to extension libraries.
+ * Just use rb_str_replace(). What's wrong with that?
+ */
+void rb_str_shared_replace(VALUE dst, VALUE src);
+
+/**
+ * Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of
+ * C's. It can also be seen as a routine identical to rb_str_shared_replace(),
+ * except it appends instead of replaces.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source object.
+ * @exception rb_eEncCompatError Can't mix the encodings.
+ * @exception rb_eArgError Result string too big.
+ * @return The passed `dst`.
+ * @pre Both objects must not be any arbitrary objects except
+ * ::RString.
+ * @post `dst` has the contents of `src` appended, with encoding
+ * converted into `dst`'s one, into the end of `dst`.
+ */
+VALUE rb_str_buf_append(VALUE dst, VALUE src);
+
+/** @alias{rb_str_cat} */
VALUE rb_str_buf_cat(VALUE, const char*, long);
+
+/** @alias{rb_str_cat_cstr} */
VALUE rb_str_buf_cat2(VALUE, const char*);
-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);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_str_cat_cstr(), except it additionally assumes the source
+ * string be a NUL terminated ASCII string.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source string.
+ * @exception rb_eArgError Result string too big.
+ * @return The passed `dst`.
+ * @pre `dst` must not be any arbitrary object except ::RString.
+ * @pre `src` must be a NUL terminated ASCII string.
+ * @post `dst` has the contents of `src` appended, with encoding
+ * converted into `dst`'s one, into the end of `dst`.
+ */
+VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src);
+
+/**
+ * Try converting an object to its stringised representation using its `to_s`
+ * method, if any. If there is no such thing, it resorts to rb_any_to_s()
+ * output.
+ *
+ * @param[in] obj Arbitrary ruby object to stringise.
+ * @return An instance of ::rb_cString.
+ */
+VALUE rb_obj_as_string(VALUE obj);
+
+/**
+ * Try converting an object to its stringised representation using its `to_str`
+ * method, if any. If there is no such thing, returns ::RUBY_Qnil.
+ *
+ * @param[in] obj Arbitrary ruby object to stringise.
+ * @exception rb_eTypeError `obj.to_str` returned something non-String.
+ * @retval RUBY_Qnil No conversion from obj to String defined.
+ * @return otherwise Stringised representation of `obj`.
+ * @see rb_io_check_io
+ * @see rb_check_array_type
+ * @see rb_check_hash_type
+ */
+VALUE rb_check_string_type(VALUE obj);
+
+/**
+ * Asserts that the given string's encoding is (Ruby's definition of) ASCII
+ * compatible.
+ *
+ * @param[in] obj An instance of ::rb_cString.
+ * @exception rb_eEncCompatError `obj` is ASCII incompatible.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't know if this is an Easter egg or an official feature, but
+ * this function can in fact take non-strings such as Symbols, Regexps, IOs,
+ * etc. However if something unsupported is passed, it causes SEGV. It seems
+ * the feature is kind of untested.
+ */
+void rb_must_asciicompat(VALUE obj);
+
+/**
+ * Duplicates a string.
+ *
+ * @param[in] str String in question to duplicate.
+ * @return A duplicated new instance.
+ * @pre `str` must be of ::RString.
+ */
+VALUE rb_str_dup(VALUE str);
+
+/**
+ * I guess there is no use case of this function in extension libraries, but
+ * this is a routine identical to rb_str_dup(), except it always creates an
+ * instance of ::rb_cString regardless of the given object's class. This makes
+ * the most sense when the passed string is formerly hidden by rb_obj_hide().
+ *
+ * @param[in] str A string, possibly hidden.
+ * @return A duplicated new instance of ::rb_cString.
+ */
VALUE rb_str_resurrect(VALUE str);
-VALUE rb_str_locktmp(VALUE);
-VALUE rb_str_unlocktmp(VALUE);
+
+/**
+ * Obtains a "temporary lock" of the string. This advisory locking mechanism
+ * prevents other cooperating threads from tampering the receiver. The same
+ * thing could be done via freeze mechanism, but this one can also be unlocked
+ * using rb_str_unlocktmp().
+ *
+ * @param[out] str String to lock.
+ * @exception rb_eRuntimeError `str` already locked.
+ * @return The given string.
+ * @post The string is locked.
+ */
+VALUE rb_str_locktmp(VALUE str);
+
+/**
+ * Releases a lock formerly obtained by rb_str_locktmp().
+ *
+ * @param[out] str String to unlock.
+ * @exception rb_eRuntimeError `str` already unlocked.
+ * @return The given string.
+ * @post The string is locked.
+ */
+VALUE rb_str_unlocktmp(VALUE str);
+
+/** @alias{rb_str_new_frozen} */
VALUE rb_str_dup_frozen(VALUE);
+
+/** @alias{rb_str_new_frozen} */
#define rb_str_dup_frozen rb_str_new_frozen
-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*);
+
+/**
+ * Generates a new string, concatenating the former to the latter. It can also
+ * be seen as a routine identical to rb_str_append(), except it doesn't tamper
+ * the passed strings to create a new one instead.
+ *
+ * @param[in] lhs Source string #1.
+ * @param[in] rhs Source string #2.
+ * @exception rb_eEncCompatError Can't mix the encodings.
+ * @exception rb_eArgError Result string too big.
+ * @return A new string containing `rhs` concatenated to `lhs`.
+ * @pre Both objects must not be any arbitrary objects except ::RString.
+ * @note This operation doesn't commute. Don't get confused by the
+ * "plus" terminology. For historical reasons there are some
+ * noncommutative `+`s in Ruby. This is one of such things. There
+ * has been a long discussion around `+`s in programming languages.
+ */
+VALUE rb_str_plus(VALUE lhs, VALUE rhs);
+
+/**
+ * Repetition of a string.
+ *
+ * @param[in] str String to repeat.
+ * @param[in] num Count, something numeric.
+ * @exception rb_eArgError `num` is negative.
+ * @return A new string repeating `num` times of `str`.
+ */
+VALUE rb_str_times(VALUE str, VALUE num);
+
+/**
+ * Byte offset to character offset conversion. This makes sense when the
+ * receiver is in a multibyte encoding. The string's i-th character does not
+ * always sit at its i-th byte. This function scans the contents to find the
+ * character index that matches the byte index. Generally speaking this is an
+ * `O(n)` operation. Could be slow.
+ *
+ * @param[in] str The string to scan.
+ * @param[in] pos Offset, in bytes.
+ * @return Offset, in characters.
+ */
+long rb_str_sublen(VALUE str, long pos);
+
+/**
+ * This is the implementation of two-argumented `String#slice`.
+ *
+ * - Returns the substring of the given `len` found in `str` at offset `beg`:
+ *
+ * ```ruby
+ * 'foo'[0, 2] # => "fo"
+ * 'foo'[0, 0] # => ""
+ * ```
+ *
+ * - Counts backward from the end of `str` if `beg` is negative:
+ *
+ * ```ruby
+ * 'foo'[-2, 2] # => "oo"
+ * ```
+ *
+ * - Special case: returns a new empty string if `beg` is equal to the length
+ * of `str`:
+ *
+ * ```ruby
+ * 'foo'[3, 2] # => ""
+ * ```
+ *
+ * - Returns a null pointer if `beg` is out of range:
+ *
+ * ```ruby
+ * 'foo'[4, 2] # => nil
+ * 'foo'[-4, 2] # => nil
+ * ```
+ *
+ * - Returns the trailing substring of `str` if `len` is large:
+ *
+ * ```ruby
+ * 'foo'[1, 50] # => "oo"
+ * ```
+ *
+ * - Returns a null pointer if `len` is negative:
+ *
+ * ```ruby
+ * 'foo'[0, -1] # => nil
+ * ```
+ *
+ * @param[in] str The string to slice.
+ * @param[in] beg Requested offset of the substring.
+ * @param[in] len Requested length of the substring.
+ * @retval RUBY_Qnil Parameters out of range.
+ * @retval otherwise A new string whose contents is the specified
+ * substring of `str`.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ */
+VALUE rb_str_substr(VALUE str, long beg, long len);
+
+/**
+ * Identical to rb_str_substr(), except the numbers are interpreted as byte
+ * offsets instead of character offsets.
+ *
+ * @param[in] str The string to slice.
+ * @param[in] beg Requested offset of the substring.
+ * @param[in] len Requested length of the substring.
+ * @return A new string whose contents is the specified substring of `str`.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @pre `beg` and `len` must not point to OOB contents.
+ */
+VALUE rb_str_subseq(VALUE str, long beg, long len);
+
+/**
+ * Identical to rb_str_substr(), except it returns a C's string instead of
+ * Ruby's.
+ *
+ * @param[in] str The string to slice.
+ * @param[in] beg Requested offset of the substring.
+ * @param[in,out] len Requested length of the substring.
+ * @retval NULL Parameters out of range.
+ * @retval otherwise A pointer inside of `str`'s backend storage where
+ * the specified substring exist.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @post `len` is updated to have the length of the return value.
+ */
+char *rb_str_subpos(VALUE str, long beg, long *len);
+
+/**
+ * Declares that the string is about to be modified. This for instance let the
+ * string have a dedicated backend storage.
+ *
+ * @param[out] str String about to be modified.
+ * @exception rb_eRuntimeError `str` is `locktmp`-ed.
+ * @exception rb_eFrozenError `str` is frozen.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @post Upon successful return the passed string is eligible to be
+ * modified.
+ */
+void rb_str_modify(VALUE str);
+
+/**
+ * Identical to rb_str_modify(), except it additionally expands the capacity of
+ * the receiver.
+ *
+ * @param[out] str Target string to modify.
+ * @param[in] capa Additional capacity to add.
+ * @exception rb_eArgError `capa` is negative.
+ * @exception rb_eRuntimeError `str` is `locktmp`-ed.
+ * @exception rb_eFrozenError `str` is frozen.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @post Upon successful return the passed string is modified so that
+ * its capacity is increased for `capa` bytes.
+ */
+void rb_str_modify_expand(VALUE str, long capa);
+
+/**
+ * This is the implementation of `String#freeze`.
+ *
+ * @param[out] str Target string to freeze.
+ * @return The passed string.
+ * @post Upon successful return the passed string is frozen.
+ */
+VALUE rb_str_freeze(VALUE str);
+
+/**
+ * Overwrites the length of the string. Typically this is used to shrink a
+ * string that was formerly expanded.
+ *
+ * ```CXX
+ * extern int fd;
+ * auto str = rb_eval_string("'...'");
+ * rb_str_modify_expand(str, BUFSIZ);
+ * if (auto len = recv(fd, RSTRING_PTR(str), BUFSIZ, 0); len >= 0) {
+ * rb_str_set_len(str, len);
+ * }
+ * else {
+ * rb_sys_fail("recv(2)");
+ * }
+ * ```
+ *
+ * @param[out] str String to shrink.
+ * @param[in] len New length of the string.
+ * @exception rb_eRuntimeError `str` is `locktmp`-ed.
+ * @exception rb_eFrozenError `str` is frozen.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @post Upon successful return `str`'s length is set to `len`.
+ */
+void rb_str_set_len(VALUE str, long len);
+
+/**
+ * Overwrites the length of the string. In contrast to rb_str_set_len(), this
+ * function can also expand a string.
+ *
+ * @param[out] str String to shrink.
+ * @param[in] len New length of the string.
+ * @exception rb_eArgError `len` is negative.
+ * @exception rb_eRuntimeError `str` is `locktmp`-ed.
+ * @exception rb_eFrozenError `str` is frozen.
+ * @return The passed `str`.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @post Upon successful return `str` is either expanded or shrunken to
+ * have its length be `len`.
+ */
+VALUE rb_str_resize(VALUE str, long len);
+
+/**
+ * Destructively appends the passed contents to the string.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Contents to append.
+ * @param[in] srclen Length of `src`.
+ * @exception rb_eArgError `srclen` is negative.
+ * @return The passed `dst`.
+ * @pre `dst` must not be any arbitrary objects except ::RString.
+ * @post `dst` has the contents of `ptr` appended.
+ */
+VALUE rb_str_cat(VALUE dst, const char *src, long srclen);
+
+/**
+ * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer
+ * to a C string.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Contents to append.
+ * @exception rb_eArgError Result string too big.
+ * @exception rb_eArgError `src` is a null pointer.
+ * @return The passed `dst`.
+ * @pre `dst` must not be any arbitrary objects except ::RString.
+ * @pre `src` must not be a null pointer.
+ * @post `dst` has the contents of `src` appended.
+ */
+VALUE rb_str_cat_cstr(VALUE dst, const char *src);
+
+/** @alias{rb_str_cat_cstr} */
VALUE rb_str_cat2(VALUE, const char*);
-VALUE rb_str_append(VALUE, VALUE);
-VALUE rb_str_concat(VALUE, VALUE);
+
+/**
+ * Identical to rb_str_buf_append(), except it converts the right hand side
+ * before concatenating.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source object.
+ * @exception rb_eEncCompatError Can't mix the encodings.
+ * @exception rb_eArgError Result string too big.
+ * @return The passed `dst`.
+ * @pre `dst` must not be any arbitrary objects except ::RString.
+ * @post `dst` has the contents of `src` appended, with encoding
+ * converted into `dst`'s one, into the end of `dst`.
+ */
+VALUE rb_str_append(VALUE dst, VALUE src);
+
+/**
+ * Identical to rb_str_append(), except it also accepts an integer as a
+ * codepoint. This resembles `String#<<`.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source object, String or Numeric.
+ * @exception rb_eRangeError Source numeric is out of range.
+ * @exception rb_eEncCompatError Source string too long.
+ * @exception rb_eArgError Result string too big.
+ * @return The passed `dst`.
+ * @pre `dst` must not be any arbitrary objects except ::RString.
+ * @post `dst` has the contents of `src` appended, with encoding
+ * converted into `dst`'s one, into the end of `dst`.
+ */
+VALUE rb_str_concat(VALUE dst, VALUE src);
+
+/* random.c */
+
+/**
+ * This is a universal hash function.
+ *
+ * @warning This function changes its value per process.
+ * @param[in] ptr Target message.
+ * @param[in] len Length of `ptr` in bytes.
+ * @return A pseudorandom number suitable for Hash's hash value.
+ * @see Aumasson, JP., Bernstein, D.J., "SipHash: A Fast Short-Input
+ * PRF", In proceedings of 13th International Conference on
+ * Cryptology in India (INDOCRYPT 2012), LNCS 7668, pp. 489-508,
+ * 2012. http://doi.org/10.1007/978-3-642-34931-7_28
+*/
st_index_t rb_memhash(const void *ptr, long len);
-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);
+
+/**
+ * Starts a series of hashing. Suppose you have a struct:
+ *
+ * ```CXX
+ * struct foo_tag {
+ * unsigned char bar;
+ * uint32_t baz;
+ * };
+ * ```
+ *
+ * It is not a wise idea to call rb_memhash() over it, because there could be
+ * padding bits. Instead you should explicitly iterate over each fields:
+ *
+ * ```CXX
+ * foo_tag foo = { 0, 0, };
+ * st_index_t hash = 0;
+ *
+ * hash = rb_hash_start(0);
+ * hash = rb_hash_uint(hash, foo.bar);
+ * hash = rb_hash_uint32(hash, foo.baz);
+ * hash = rb_hash_end(hash);
+ * ```
+ *
+ * @param[in] i Initial value.
+ * @return A hash value.
+ */
+st_index_t rb_hash_start(st_index_t i);
+
+/** @alias{st_hash_uint32} */
#define rb_hash_uint32(h, i) st_hash_uint32((h), (i))
+
+/** @alias{st_hash_uint} */
#define rb_hash_uint(h, i) st_hash_uint((h), (i))
+
+/** @alias{st_hash_end} */
#define rb_hash_end(h) st_hash_end(h)
-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);
+
+/* string.c */
+
+/**
+ * Calculates a hash value of a string. This is one of the two functions that
+ * constructs struct ::st_hash_type.
+ *
+ * @param[in] str An object of ::RString.
+ * @return A hash value.
+ * @pre `str` must not be any arbitrary object except ::RString.
+ *
+ * @internal
+ *
+ * Although safe to call, there must be no particular use case of this function
+ * for extension libraries. Only ruby internals must know about it.
+ *
+ * This is not a simple alias of rb_memhash(), because it considers the passed
+ * string's encoding as well as its contents.
+ */
+st_index_t rb_str_hash(VALUE str);
+
+/**
+ * Compares two strings. This is one of the two functions that constructs
+ * struct ::st_hash_type.
+ *
+ * @param[in] str1 A string.
+ * @param[in] str2 Another string.
+ * @retval 1 They have identical contents, length, and encodings.
+ * @retval 0 Otherwise.
+ * @pre Both objects must not be any arbitrary objects except
+ * ::RString.
+ *
+ * @internal
+ *
+ * In contrast to rb_str_hash(), this could be handy for comparison that only
+ * concerns equality. rb_str_cmp() returns 1, 0, -1.
+ */
+int rb_str_hash_cmp(VALUE str1, VALUE str2);
+
+/**
+ * Checks if two strings are comparable each other or not. Because
+ * rb_str_cmp() must return "lesser than" or "greater than" information,
+ * comparing two strings needs a stricter restriction. Both sides must be in a
+ * same set of strings which have total order. This is to check that property.
+ * Intuitive it sounds? But they can have different encodings. A character
+ * and another might or might not appear in the same order in their codepoints.
+ * It is complicated than you think.
+ *
+ * @param[in] str1 A string.
+ * @param[in] str2 Another string.
+ * @retval 1 They agree on a total order.
+ * @retval 0 Otherwise.
+ * @pre Both objects must not be any arbitrary objects except
+ * ::RString.
+ */
+int rb_str_comparable(VALUE str1, VALUE str2);
+
+/**
+ * Compares two strings, as in `strcmp(3)`. This does not consider the current
+ * locale, but considers the encodings of both sides instead.
+ *
+ * @param[in] lhs A string.
+ * @param[in] rhs Another string.
+ * @retval -1 `lhs` is "bigger than" `rhs`.
+ * @retval 1 `rhs` is "bigger than" `lhs`.
+ * @retval 0 Otherwise, e.g. not comparable.
+ * @pre Both objects must not be any arbitrary objects except
+ * ::RString.
+ */
+int rb_str_cmp(VALUE lhs, VALUE rhs);
+
+/**
+ * Equality of two strings.
+ *
+ * If `str2` is not a String, it resorts to `str2 == str1`. Otherwise if they
+ * are not comparable, returns ::RUBY_Qfalse. Otherwise if they have the same
+ * contents and the length, returns ::RUBY_Qtrue. Otherwise, returns
+ * ::RUBY_Qfalse.
+ *
+ * @param[in] str1 A string.
+ * @param[in] str2 Another string.
+ * @retval RUBY_Qtrue They are equal.
+ * @retval RUBY_Qfalse They are either different, or not comparable.
+ */
VALUE rb_str_equal(VALUE str1, VALUE str2);
-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*);
+
+/**
+ * Shrinks the given string for the given number of bytes.
+ *
+ * @param[out] str String to squash.
+ * @param[in] len Number of bytes to reduce.
+ * @exception rb_eRuntimeError `str` is `locktmp`-ed.
+ * @exception rb_eFrozenError `str` is frozen.
+ * @return The passed `str`.
+ * @pre `str` must not be any arbitrary objects except ::RString.
+ * @post `str` is shrunken.
+ * @warning Can break a multibyte character in middle.
+ *
+ * @internal
+ *
+ * What if `len` is negative?
+ */
+VALUE rb_str_drop_bytes(VALUE str, long len);
+
+/**
+ * Replaces some (or all) of the contents of the given string. This is the
+ * implementation of three-argumented `String#[]=`.
+ *
+ * @param[out] dst Target string to update.
+ * @param[in] beg Offset of the affected portion.
+ * @param[in] len Length of the affected portion.
+ * @param[in] src Object to be assigned.
+ * @exception rb_eTypeError `src` has no implicit conversion to String.
+ * @exception rb_eIndexError `len` is negative, or `beg` is OOB.
+ * @exception rb_eRuntimeError `dst` is `locktmp`-ed.
+ * @exception rb_eFrozenError `dst` is frozen.
+ * @note Unlike rb_str_substr(), this function raises.
+ * @post A portion of `dst` from `beg` to `len` is the stringised
+ * representation of `src`. If that replacement string is not the
+ * same length as the portion it is replacing, `dst` will be
+ * resized accordingly.
+ */
+void rb_str_update(VALUE dst, long beg, long len, VALUE src);
+
+/**
+ * Replaces the contents of the former object with the stringised contents of
+ * the latter.
+ *
+ * @param[out] dst Destination object.
+ * @param[in] src Source object.
+ * @exception rb_eTypeError `src` has no implicit conversion to String.
+ * @exception rb_eRuntimeError `dst` is `locktmp`-ed.
+ * @exception rb_eFrozenError `dst` is frozen.
+ * @return The passed `dst`.
+ * @pre `dst` must not be any arbitrary object except ::RString.
+ * @post `dst`'s former components are abandoned. It now has the
+ * identical encoding, length, and contents to `src`.
+ */
+VALUE rb_str_replace(VALUE dst, VALUE src);
+
+/**
+ * Generates a "readable" version of the receiver.
+ *
+ * @warning The output is _insecure_. Never feed one to `eval`.
+ * @warning The output is not always in the same encoding as the given one.
+ * @warning A character might or might not be escaped, depending on the
+ * result encoding.
+ * @param[in] str String to inspect.
+ * @return Its inspection, either in default internal encoding if any, or
+ * in default external encoding otherwise.
+ * @see rb_str_dump()
+ *
+ * @internal
+ *
+ * This is a (silent) fix of an actual vulnerability feeding `inspect` output
+ * strings to `eval`:
+ * https://github.com/hiki/hiki/commit/8771a6e25198e264a2bf9dc1c102fea2cc8ff975
+ *
+ * ... and its advisory:
+ * http://hikiwiki.org/en/advisory20040712.html
+ */
+VALUE rb_str_inspect(VALUE str);
+
+/**
+ * "Inverse" of rb_eval_string(). Returns a quoted version of the string. All
+ * non-printing characters are replaced by `\uNNNN` or `\xHH` notation and all
+ * special characters are escaped. The result string is guaranteed to render a
+ * string of the same contents when passed to `eval` and friends.
+ *
+ * @param[in] str String to dump.
+ * @exception rb_eRuntimeError Too many escape sequences causes integer
+ * overflow on the length of the string.
+ * @return An US-ASCII string that includes all the necessary info to
+ * reconstruct the original string.
+ */
+VALUE rb_str_dump(VALUE str);
+
+/**
+ * Divides the given string based on the given delimiter. This is the
+ * 1-argument 0-block version of `String#split`.
+ *
+ * @param[in] str Object in question to split.
+ * @param[in] delim Delimiter, in C string.
+ * @exception rb_eTypeError `str` has no implicit conversion to String.
+ * @exception rb_eArgError `delim` is a null pointer.
+ * @return An array of strings, which are substrings of the passed `str`.
+ * If `delim` is an empty C string (i.e. `""`), `str` is split into
+ * each characters. If `delim` is a C string whose sole content is
+ * a whitespace (i.e. `" "`), `str` is split on whitespaces, with
+ * leading and trailing whitespace and runs of contiguous
+ * whitespace characters ignored. Otherwise, `str` is split
+ * according to `delim`.
+ */
+VALUE rb_str_split(VALUE str, const char *delim);
+
+/**
+ * This is a ::rb_gvar_setter_t that refutes non-string assignments.
+ *
+ * @exception rb_eTypeError Passed something non-string.
+ */
rb_gvar_setter_t rb_str_setter;
-VALUE rb_str_intern(VALUE);
-VALUE rb_sym_to_s(VALUE);
-long rb_str_strlen(VALUE);
+
+/* symbol.c */
+
+/**
+ * Identical to rb_to_symbol(), except it assumes the receiver being an
+ * instance of ::RString.
+ *
+ * @param[in] str The name of the id.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given `str`.
+ * @pre `str` must not be any arbitrary object except ::RString.
+ * @note These days Ruby internally has two kinds of symbols
+ * (static/dynamic). Symbols created using this function would
+ * become dynamic ones; i.e. would be garbage collected. It could
+ * be safer for you to use it than alternatives, when applicable.
+ */
+VALUE rb_str_intern(VALUE str);
+
+/* string.c */
+
+/**
+ * This is an rb_sym2str() + rb_str_dup() combo.
+ *
+ * @param[in] sym A symbol to query.
+ * @return A string duplicating the symbol's backend storage.
+ *
+ * @internal
+ *
+ * This function causes SEGV when the passed value is a static symbol that
+ * doesn't exist.
+ */
+VALUE rb_sym_to_s(VALUE sym);
+
+/**
+ * Counts the number of characters (not bytes) that are stored inside of the
+ * given string. This of course depends on its encoding. Also this function
+ * generally runs in O(n), because for instance you have to scan the entire
+ * string to know how many characters are there in a UTF-8 string.
+ *
+ * @param[in] str Target string to query.
+ * @return Its number of characters.
+ */
+long rb_str_strlen(VALUE str);
+
+/**
+ * Identical to rb_str_strlen(), except it returns the value in ::rb_cInteger.
+ *
+ * @param[in] str Target string to query.
+ * @return Its number of characters.
+ */
VALUE rb_str_length(VALUE);
-long rb_str_offset(VALUE, long);
+
+/**
+ * "Inverse" of rb_str_sublen(). This function scans the contents to find the
+ * byte index that matches the character index. Generally speaking this is an
+ * `O(n)` operation. Could be slow.
+ *
+ * @param[in] str The string to scan.
+ * @param[in] pos Offset, in characters.
+ * @return Offset, in bytes.
+ */
+long rb_str_offset(VALUE str, long pos);
+
RBIMPL_ATTR_PURE()
-size_t rb_str_capacity(VALUE);
-VALUE rb_str_ellipsize(VALUE, long);
-VALUE rb_str_scrub(VALUE, VALUE);
-VALUE rb_str_succ(VALUE);
+/**
+ * Queries the capacity of the given string.
+ *
+ * @see ::RString::capa
+ * @param[in] str String in question.
+ * @return Its capacity.
+ */
+size_t rb_str_capacity(VALUE str);
+
+/**
+ * Shortens `str` and adds three dots, an ellipsis, if it is longer than `len`
+ * characters. The length of the returned string in characters is less than or
+ * equal to `len`. If the length of `str` is less than or equal `len`, returns
+ * `str` itself. The encoding of returned string is equal to that of passed
+ * one. The class of returned string is equal to that of passed one.
+ *
+ * @param[in] str The string to shorten.
+ * @param[in] len The maximum string length.
+ * @exception rb_eIndexError `len` is negative.
+ * @retval str No need to add ellipsis.
+ * @retval otherwise A new, shortened string.
+ * @note The length is counted in characters.
+ */
+VALUE rb_str_ellipsize(VALUE str, long len);
+
+/**
+ * "Cleanses" the string. A string has its encoding and its contents. They,
+ * in practice, do not always fit. There are strings in the wild that are
+ * "broken"; include bit patterns that are not allowed by its encoding. That
+ * can happen when a user copy&pasted something bad, network input got
+ * clobbered by a middleman, cosmic rays hit the physical memory, and many more
+ * occasions. This function takes such strings, and fills the "broken" portion
+ * with the passed replacement bit pattern.
+ *
+ * This function also takes a ruby block. That is a neat way to do things, but
+ * can be annoying when the caller function want to use a block for another
+ * purpose.
+ *
+ * @param[in] str Target string to scrub.
+ * @param[in] repl Replacement string. When it is a string,
+ * this function takes that as a replacement.
+ * When it is ::RUBY_Qnil, this function tries
+ * to yield a block (if any) and takes its
+ * evaluated value as a replacement. In case
+ * of ::RUBY_Qnil without a block, this
+ * function takes an encoding-specific default
+ * character (`U+FFFD`, for instance) as a last
+ * resort.
+ * @exception rb_eTypeError `repl` is neither string nor nil.
+ * @exception rb_eArgError `repl` itself is broken.
+ * @exception rb_eEncCompatError `repl` and `str` are incompatible.
+ * @retval RUBY_Qnil `str` is already clean.
+ * @retval otherwise A new, clean string.
+ */
+VALUE rb_str_scrub(VALUE str, VALUE repl);
+
+/**
+ * Searches for the "successor" of a string. This function is complicated!
+ * This is the only function in the entire ruby API (either C or Ruby) that
+ * generates a string out of thin air. First, the successor to an empty string
+ * is a new empty string:
+ *
+ * ```ruby
+ * ''.succ # => ""
+ * ```
+ *
+ * Otherwise the successor is calculated by "incrementing" characters. The
+ * first character to be incremented is the rightmost alphanumeric: or, if no
+ * alphanumerics, the rightmost character:
+ *
+ * ```ruby
+ * 'THX1138'.succ # => "THX1139"
+ * '<<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:
+ *
+ * ```ruby
+ * '00'.succ # => "01"
+ * '09'.succ # => "10"
+ * '99'.succ # => "100"
+ * '-9'.succ # => "-10"
+ * ```
+ *
+ * The successor to a letter is another letter of the same case, carrying to
+ * the next-left character for a rollover, and prepending another same-case
+ * letter if necessary:
+ *
+ * ```ruby
+ * 'aa'.succ # => "ab"
+ * 'az'.succ # => "ba"
+ * 'zz'.succ # => "aaa"
+ * 'AA'.succ # => "AB"
+ * 'AZ'.succ # => "BA"
+ * 'ZZ'.succ # => "AAA"
+ * ```
+ *
+ * The successor to a non-alphanumeric character is the next character in the
+ * underlying character set's collating sequence, carrying to the next-left
+ * character for a rollover, and prepending another character if necessary:
+ *
+ * ```ruby
+ * s = "\u03A1"
+ * s.succ # => "\u03A3" # There is no such thing like \u03A2.
+ * s = 255.chr * 3
+ * s # => "\xFF\xFF\xFF"
+ * s.succ # => "\x01\x00\x00\x00"
+ * ```
+ *
+ * Carrying can occur between and among mixtures of alphanumeric characters:
+ *
+ * ```ruby
+ * s = 'zz99zz99'
+ * s.succ # => "aaa00aa00"
+ * s = '99zz99zz'
+ * s.succ # => "100aa00aa"
+ * s = '1.9.9'
+ * s.succ # => "2.0.0"
+ * ```
+ *
+ * @param[in] orig Predecessor string.
+ * @return Successor string.
+ */
+VALUE rb_str_succ(VALUE orig);
RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string.
+ * @return `strlen`, casted to `long`.
+ */
static inline long
rbimpl_strlen(const char *str)
{
return RBIMPL_CAST((long)strlen(str));
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string literal.
+ * @return Corresponding Ruby string.
+ */
static inline VALUE
rbimpl_str_new_cstr(const char *str)
{
@@ -153,13 +1367,15 @@ rbimpl_str_new_cstr(const char *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);
-}
-
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string literal.
+ * @return Corresponding Ruby string.
+ */
static inline VALUE
rbimpl_usascii_str_new_cstr(const char *str)
{
@@ -167,6 +1383,15 @@ rbimpl_usascii_str_new_cstr(const char *str)
return rb_usascii_str_new_static(str, len);
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string literal.
+ * @return Corresponding Ruby string.
+ */
static inline VALUE
rbimpl_utf8_str_new_cstr(const char *str)
{
@@ -174,6 +1399,15 @@ rbimpl_utf8_str_new_cstr(const char *str)
return rb_utf8_str_new_static(str, len);
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string literal.
+ * @return Corresponding Ruby string.
+ */
static inline VALUE
rbimpl_external_str_new_cstr(const char *str)
{
@@ -181,6 +1415,15 @@ rbimpl_external_str_new_cstr(const char *str)
return rb_external_str_new(str, len);
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string literal.
+ * @return Corresponding Ruby string.
+ */
static inline VALUE
rbimpl_locale_str_new_cstr(const char *str)
{
@@ -188,6 +1431,15 @@ rbimpl_locale_str_new_cstr(const char *str)
return rb_locale_str_new(str, len);
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] str A C string literal.
+ * @return Corresponding Ruby string.
+ */
static inline VALUE
rbimpl_str_buf_new_cstr(const char *str)
{
@@ -196,6 +1448,16 @@ rbimpl_str_buf_new_cstr(const char *str)
return rb_str_buf_cat(buf, str, len);
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[out] buf A string buffer.
+ * @param[in] str A C string literal.
+ * @return `buf` itself.
+ */
static inline VALUE
rbimpl_str_cat_cstr(VALUE buf, const char *str)
{
@@ -203,6 +1465,16 @@ rbimpl_str_cat_cstr(VALUE buf, const char *str)
return rb_str_cat(buf, str, len);
}
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail. Don't bother.
+ *
+ * @param[in] exc An exception class.
+ * @param[in] str A C string literal.
+ * @return An instance of `exc`.
+ */
static inline VALUE
rbimpl_exc_new_cstr(VALUE exc, const char *str)
{
@@ -210,88 +1482,275 @@ rbimpl_exc_new_cstr(VALUE exc, const char *str)
return rb_exc_new(exc, str, len);
}
+/**
+ * Allocates an instance of ::rb_cString.
+ *
+ * @param[in] str A memory region of `len` bytes length.
+ * @param[in] len Length of `ptr`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of
+ * "binary" encoding, whose contents are verbatim copy of `str`.
+ * @pre At least `len` bytes of continuous memory region shall be
+ * accessible via `str`.
+ */
#define rb_str_new(str, len) \
((RBIMPL_CONSTANT_P(str) && \
RBIMPL_CONSTANT_P(len) ? \
rb_str_new_static : \
rb_str_new) ((str), (len)))
+/**
+ * Identical to #rb_str_new, except it assumes the passed pointer is a pointer
+ * to a C string.
+ *
+ * @param[in] str A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose
+ * contents are verbatim copy of `str`.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_str_new_cstr(str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_str_new_cstr : \
rb_str_new_cstr) (str))
+/**
+ * Identical to #rb_str_new, except it generates a string of "US ASCII"
+ * encoding. This is different from rb_external_str_new(), not only for the
+ * output encoding, but also it doesn't convert the contents.
+ *
+ * @param[in] str A memory region of `len` bytes length.
+ * @param[in] len Length of `str`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of
+ * "US ASCII" encoding, whose contents are verbatim copy of `str`.
+ */
#define rb_usascii_str_new(str, len) \
((RBIMPL_CONSTANT_P(str) && \
RBIMPL_CONSTANT_P(len) ? \
rb_usascii_str_new_static : \
rb_usascii_str_new) ((str), (len)))
+/**
+ * Identical to #rb_str_new, except it generates a string of "UTF-8" encoding.
+ *
+ * @param[in] str A memory region of `len` bytes length.
+ * @param[in] len Length of `str`, in bytes, not including the
+ * terminating NUL character.
+ * @exception rb_eNoMemError Failed to allocate `len+1` bytes.
+ * @exception rb_eArgError `len` is negative.
+ * @return An instance of ::rb_cString, of `len` bytes length, of
+ * "UTF-8" encoding, whose contents are verbatim copy of `str`.
+ */
#define rb_utf8_str_new(str, len) \
((RBIMPL_CONSTANT_P(str) && \
RBIMPL_CONSTANT_P(len) ? \
rb_utf8_str_new_static : \
rb_utf8_str_new) ((str), (len)))
-#define rb_tainted_str_new_cstr(str) \
- ((RBIMPL_CONSTANT_P(str) ? \
- rbimpl_tainted_str_new_cstr : \
- rb_tainted_str_new_cstr) (str))
-
+/**
+ * Identical to #rb_str_new_cstr, except it generates a string of "US ASCII"
+ * encoding. It can also be seen as a routine Identical to
+ * #rb_usascii_str_new, except it assumes the passed pointer is a pointer to a
+ * C string.
+ *
+ * @param[in] str A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of "US ASCII" encoding, whose
+ * contents are verbatim copy of `str`.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_usascii_str_new_cstr(str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_usascii_str_new_cstr : \
rb_usascii_str_new_cstr) (str))
+/**
+ * Identical to #rb_str_new_cstr, except it generates a string of "UTF-8"
+ * encoding. It can also be seen as a routine Identical to #rb_utf8_str_new,
+ * except it assumes the passed pointer is a pointer to a C string.
+ *
+ * @param[in] str A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of "UTF-8" encoding, whose contents
+ * are verbatim copy of `str`.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_utf8_str_new_cstr(str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_utf8_str_new_cstr : \
rb_utf8_str_new_cstr) (str))
+/**
+ * Identical to #rb_str_new_cstr, except it generates a string of "default
+ * external" encoding.
+ *
+ * @param[in] str A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "default external" is fully defined over
+ * the given contents, then the return value is a string of
+ * "default external" encoding, whose contents are the converted
+ * ones. Otherwise the string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_external_str_new_cstr(str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_external_str_new_cstr : \
rb_external_str_new_cstr) (str))
+/**
+ * Identical to #rb_external_str_new_cstr, except it generates a string of
+ * "locale" encoding instead of "default external".
+ *
+ * @param[in] str A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString. In case encoding conversion from
+ * "default internal" to "locale" is fully defined over the given
+ * contents, then the return value is a string of "locale"
+ * encoding, whose contents are the converted ones. Otherwise the
+ * string is a junk.
+ * @warning It doesn't raise on a conversion failure and silently ends up in
+ * a corrupted output. You can know the failure by querying
+ * `valid_encoding?` of the result object.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_locale_str_new_cstr(str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_locale_str_new_cstr : \
rb_locale_str_new_cstr) (str))
+/**
+ * Identical to #rb_str_new_cstr, except done differently.
+ *
+ * @param[in] str A C string.
+ * @exception rb_eNoMemError Failed to allocate memory.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose
+ * contents are verbatim copy of `str`.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_str_buf_new_cstr(str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_str_buf_new_cstr : \
rb_str_buf_new_cstr) (str))
+/**
+ * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer
+ * to a C string.
+ *
+ * @param[out] buf Destination object.
+ * @param[in] str Contents to append.
+ * @exception rb_eArgError Result string too big.
+ * @return The passed `buf`.
+ * @pre `buf` must not be any arbitrary objects except ::RString.
+ * @pre `str` must not be a null pointer.
+ * @post `buf` has the contents of `str` appended.
+ */
#define rb_str_cat_cstr(buf, str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_str_cat_cstr : \
rb_str_cat_cstr) ((buf), (str)))
+/**
+ * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer
+ * to a C string.
+ *
+ * @param[out] exc A subclass of ::rb_eException.
+ * @param[in] str Message to raise.
+ * @return An instance of `exc` whose message is `str`.
+ * @pre `str` must not be a null pointer.
+ */
#define rb_exc_new_cstr(exc, str) \
((RBIMPL_CONSTANT_P(str) ? \
rbimpl_exc_new_cstr : \
rb_exc_new_cstr) ((exc), (str)))
-#define rb_str_new2 rb_str_new_cstr
-#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_str_new2 rb_str_new_cstr /**< @old{rb_str_new_cstr} */
+#define rb_str_new3 rb_str_new_shared /**< @old{rb_str_new_shared} */
+#define rb_str_new4 rb_str_new_frozen /**< @old{rb_str_new_frozen} */
+#define rb_str_new5 rb_str_new_with_class /**< @old{rb_str_new_with_class} */
+#define rb_str_buf_new2 rb_str_buf_new_cstr /**< @old{rb_str_buf_new_cstr} */
+#define rb_usascii_str_new2 rb_usascii_str_new_cstr /**< @old{rb_usascii_str_new_cstr} */
+#define rb_str_buf_cat rb_str_cat /**< @alias{rb_str_cat} */
+#define rb_str_buf_cat2 rb_str_cat_cstr /**< @old{rb_usascii_str_new_cstr} */
+#define rb_str_cat2 rb_str_cat_cstr /**< @old{rb_str_cat_cstr} */
+
+/**
+ * Length of a string literal.
+ *
+ * @param[in] str A C String literal.
+ * @return An integer constant expression that represents `str`'s length,
+ * in bytes, not including the terminating NUL character.
+ */
#define rb_strlen_lit(str) (sizeof(str "") - 1)
+
+/**
+ * Identical to rb_str_new_static(), except it cannot take string variables.
+ *
+ * @param[in] str A C string literal.
+ * @pre `str` must not be a variable.
+ * @return An instance of ::rb_cString, of "binary" encoding, whose backend
+ * storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ */
#define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str))
+
+/**
+ * Identical to rb_usascii_str_new_static(), except it cannot take string
+ * variables.
+ *
+ * @param[in] str A C string literal.
+ * @pre `str` must not be a variable.
+ * @return An instance of ::rb_cString, of "US ASCII" encoding, whose
+ * backend storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ */
#define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str))
+
+/**
+ * Identical to rb_utf8_str_new_static(), except it cannot take string
+ * variables.
+ *
+ * @param[in] str A C string literal.
+ * @pre `str` must not be a variable.
+ * @return An instance of ::rb_cString, of "UTF-8" encoding, whose backend
+ * storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ */
#define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str))
+
+/**
+ * Identical to rb_enc_str_new_static(), except it cannot take string
+ * variables.
+ *
+ * @param[in] str A C string literal.
+ * @param[in] enc A pointer to an encoding.
+ * @pre `str` must not be a variable.
+ * @return An instance of ::rb_cString, of the passed encoding, whose
+ * backend storage is the passed C string literal.
+ * @warning It is a very bad idea to write to a C string literal (often
+ * immediate SEGV shall occur). Consider return values of this
+ * function be read-only.
+ */
#define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc))
-#define rb_str_new_literal(str) rb_str_new_lit(str)
-#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)
+
+#define rb_str_new_literal(str) rb_str_new_lit(str) /**< @alias{rb_str_new_lit} */
+#define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str) /**< @alias{rb_usascii_str_new_lit} */
+#define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str) /**< @alias{rb_utf8_str_new_lit} */
+#define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc) /**< @alias{rb_enc_str_new_lit} */
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/struct.h b/include/ruby/internal/intern/struct.h
index 8818da96c7..312cf444e2 100644
--- a/include/ruby/internal/intern/struct.h
+++ b/include/ruby/internal/intern/struct.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cStruct.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/intern/vm.h" /* rb_alloc_func_t */
#include "ruby/internal/value.h"
@@ -27,19 +28,174 @@
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, ...);
+
+/**
+ * Creates an instance of the given struct.
+ *
+ * @param[in] klass The class of the instance to allocate.
+ * @param[in] ... The fields.
+ * @return Allocated instance of `klass`.
+ * @pre `klass` must be a subclass of ::rb_cStruct.
+ * @note Number of variadic arguments must much that of the passed klass'
+ * fields.
+ */
+VALUE rb_struct_new(VALUE klass, ...);
+
+/**
+ * Defines a struct class.
+ *
+ * @param[in] name Name of the class.
+ * @param[in] ... Arbitrary number of `const char*`, terminated by
+ * zero. Each of which are the name of fields.
+ * @exception rb_eNameError `name` is not a constant name.
+ * @exception rb_eTypeError `name` is already taken.
+ * @exception rb_eArgError Duplicated field name.
+ * @return The defined class.
+ * @post Global toplevel constant `name` is defined.
+ * @note `name` is allowed to be a null pointer. This function creates
+ * an anonymous struct class then.
+ *
+ * @internal
+ *
+ * Not seriously checked but it seems this function does not share its
+ * implementation with how `Struct.new` is implemented...?
+ */
+VALUE rb_struct_define(const char *name, ...);
+
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * Identical to rb_struct_define(), except it defines the class under the
+ * specified namespace instead of global toplevel.
+ *
+ * @param[out] space Namespace that the defining class shall reside.
+ * @param[in] name Name of the class.
+ * @param[in] ... Arbitrary number of `const char*`, terminated by
+ * zero. Each of which are the name of fields.
+ * @exception rb_eNameError `name` is not a constant name.
+ * @exception rb_eTypeError `name` is already taken.
+ * @exception rb_eArgError Duplicated field name.
+ * @return The defined class.
+ * @post `name` is a constant under `space`.
+ * @note In contrast to rb_struct_define(), it doesn't make any sense to
+ * pass a null pointer to this function.
+ */
+VALUE rb_struct_define_under(VALUE space, const char *name, ...);
+
+/**
+ * Identical to rb_struct_new(), except it takes the field values as a Ruby
+ * array.
+ *
+ * @param[in] klass The class of the instance to allocate.
+ * @param[in] values Field values.
+ * @return Allocated instance of `klass`.
+ * @pre `klass` must be a subclass of ::rb_cStruct.
+ * @pre `values` must be an instance of struct ::RArray.
+ */
+VALUE rb_struct_alloc(VALUE klass, VALUE values);
+
+/**
+ * Mass-assigns a struct's fields.
+ *
+ * @param[out] self An instance of a struct class to squash.
+ * @param[in] values New values.
+ * @return ::RUBY_Qnil.
+ */
+VALUE rb_struct_initialize(VALUE self, VALUE values);
+
+/**
+ * Identical to rb_struct_aref(), except it takes ::ID instead of ::VALUE.
+ *
+ * @param[in] self An instance of a struct class.
+ * @param[in] key Key to query.
+ * @exception rb_eTypeError `self` is not a struct.
+ * @exception rb_eNameError No such field.
+ * @return The value stored at `key` in `self`.
+ */
+VALUE rb_struct_getmember(VALUE self, ID key);
+
+/**
+ * Queries the list of the names of the fields of the given struct class.
+ *
+ * @param[in] klass A subclass of ::rb_cStruct.
+ * @return The list of the names of the fields of `klass`.
+ */
+VALUE rb_struct_s_members(VALUE klass);
+
+/**
+ * Queries the list of the names of the fields of the class of the given struct
+ * object. This is almost the same as calling rb_struct_s_members() over the
+ * class of the receiver.
+ *
+ * @internal
+ *
+ * "Almost"? What exactly is the difference?
+ *
+ * @endinternal
+ *
+ * @param[in] self An instance of a subclass of ::rb_cStruct.
+ * @return The list of the names of the fields.
+ */
+VALUE rb_struct_members(VALUE self);
+
+/**
+ * Allocates an instance of the given class. This consequential name is of
+ * course because rb_struct_alloc() not only allocates but also initialises an
+ * instance. The API design is broken.
+ *
+ * @param[in] klass A subclass of ::rb_cStruct.
+ * @return An allocated instance of `klass`, not initialised.
+ */
+VALUE rb_struct_alloc_noinit(VALUE klass);
+
+/**
+ * Identical to rb_struct_define(), except it does not define accessor methods.
+ * You have to define them yourself. Forget about the allocator function
+ * parameter; it is for internal use only. Extension libraries are unable to
+ * properly allocate a ruby struct, because `RStruct` is opaque.
+ *
+ * @internal
+ *
+ * Several flags must be set up properly for ::RUBY_T_STRUCT objects, which are
+ * also missing for extension libraries.
+ *
+ * @endinternal
+ *
+ * @param[in] name Name of the class.
+ * @param[in] super Superclass of the defining class.
+ * @param[in] func Must be 0 for extension libraries.
+ * @param[in] ... Arbitrary number of `const char*`, terminated by
+ * zero. Each of which are the name of fields.
+ * @exception rb_eNameError `name` is not a constant name.
+ * @exception rb_eTypeError `name` is already taken.
+ * @exception rb_eArgError Duplicated field name.
+ * @return The defined class.
+ * @post Global toplevel constant `name` is defined.
+ * @note `name` is allowed to be a null pointer. This function creates
+ * an anonymous struct class then.
+ */
+VALUE rb_struct_define_without_accessor(const char *name, VALUE super, rb_alloc_func_t func, ...);
+
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * Identical to rb_struct_define_without_accessor(), except it defines the
+ * class under the specified namespace instead of global toplevel. It can also
+ * be seen as a routine identical to rb_struct_define_under(), except it does
+ * not define accessor methods.
+ *
+ * @param[out] outer Namespace that the defining class shall reside.
+ * @param[in] class_name Name of the class.
+ * @param[in] super Superclass of the defining class.
+ * @param[in] alloc Must be 0 for extension libraries.
+ * @param[in] ... Arbitrary number of `const char*`, terminated by
+ * zero. Each of which are the name of fields.
+ * @exception rb_eNameError `class_name` is not a constant name.
+ * @exception rb_eTypeError `class_name` is already taken.
+ * @exception rb_eArgError Duplicated field name.
+ * @return The defined class.
+ * @post `class_name` is a constant under `outer`.
+ * @note In contrast to rb_struct_define_without_accessor(), it doesn't
+ * make any sense to pass a null name.
+ */
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h
index 7c656a628c..716375acd7 100644
--- a/include/ruby/internal/intern/thread.h
+++ b/include/ruby/internal/intern/thread.h
@@ -17,11 +17,12 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cThread.
*/
-#include "ruby/internal/config.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/cast.h"
+#include "ruby/internal/config.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
@@ -30,45 +31,460 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
struct timeval;
/* thread.c */
+
+/**
+ * Tries to switch to another thread. This function blocks until the current
+ * thread re-acquires the GVL.
+ *
+ * @exception rb_eInterrupt Operation interrupted.
+ */
void rb_thread_schedule(void);
-int rb_thread_wait_fd(int);
-int rb_thread_fd_writable(int);
-void rb_thread_fd_close(int);
+
+/**
+ * Blocks the current thread until the given file descriptor is ready to be
+ * read.
+ *
+ * @param[in] fd A file descriptor.
+ * @exception rb_eIOError Closed stream.
+ * @exception rb_eSystemCallError Situations like EBADF.
+ */
+int rb_thread_wait_fd(int fd);
+
+/**
+ * Identical to rb_thread_wait_fd(), except it blocks the current thread until
+ * the given file descriptor is ready to be written.
+ *
+ * @param[in] fd A file descriptor.
+ * @exception rb_eIOError Closed stream.
+ * @exception rb_eSystemCallError Situations like EBADF.
+ */
+int rb_thread_fd_writable(int fd);
+
+/**
+ * Notifies a closing of a file descriptor to other threads. Multiple threads
+ * can wait for the given file descriptor at once. If such file descriptor is
+ * closed, threads need to start propagating their exceptions. This is the API
+ * to kick that process.
+ *
+ * @param[in] fd A file descriptor.
+ * @note This function blocks until all the threads waiting for such fd
+ * have woken up.
+ */
+void rb_thread_fd_close(int fd);
+
+/**
+ * Checks if the thread this function is running is the only thread that is
+ * currently alive.
+ *
+ * @retval 1 Yes it is.
+ * @retval 0 No it isn't.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. There are Ractors these days.
+ */
int rb_thread_alone(void);
-void rb_thread_sleep(int);
+
+/**
+ * Blocks for the given period of time.
+ *
+ * @warning This function can be interrupted by signals.
+ * @param[in] sec Duration in seconds.
+ * @exception rb_eInterrupt Interrupted.
+ */
+void rb_thread_sleep(int sec);
+
+/**
+ * Blocks indefinitely.
+ *
+ * @exception rb_eInterrupt Interrupted.
+ */
void rb_thread_sleep_forever(void);
+
+/**
+ * Identical to rb_thread_sleep_forever(), except the thread calling this
+ * function is considered "dead" when our deadlock checker is triggered.
+ *
+ * @exception rb_eInterrupt Interrupted.
+ */
void rb_thread_sleep_deadly(void);
+
+/**
+ * Stops the current thread. This is not the end of the thread's lifecycle. A
+ * stopped thread can later be woken up.
+ *
+ * @exception rb_eThreadError Stopping this thread would deadlock.
+ * @retval ::RUBY_Qnil Always.
+ *
+ * @internal
+ *
+ * The return value makes no sense at all.
+ */
VALUE rb_thread_stop(void);
-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);
+
+/**
+ * Marks a given thread as eligible for scheduling.
+ *
+ * @note It may still remain blocked on I/O.
+ * @note This does not invoke the scheduler itself.
+ *
+ * @param[out] thread Thread in question to wake up.
+ * @exception rb_eThreadError Stop flogging a dead horse.
+ * @return The passed thread.
+ * @post The passed thread is made runnable.
+ */
+VALUE rb_thread_wakeup(VALUE thread);
+
+/**
+ * Identical to rb_thread_wakeup(), except it doesn't raise on an already
+ * killed thread.
+ *
+ * @param[out] thread A thread to wake up.
+ * @retval RUBY_Qnil `thread` is already killed.
+ * @retval otherwise `thread` is alive.
+ * @post The passed thread is made runnable, unless killed.
+ */
+VALUE rb_thread_wakeup_alive(VALUE thread);
+
+/**
+ * This is a rb_thread_wakeup() + rb_thread_schedule() combo.
+ *
+ * @note There is no guarantee that this function yields to the passed
+ * thread. It may still remain blocked on I/O.
+ * @param[out] thread Thread in question to wake up.
+ * @exception rb_eThreadError Stop flogging a dead horse.
+ * @return The passed thread.
+ */
+VALUE rb_thread_run(VALUE thread);
+
+/**
+ * Terminates the given thread. Unlike a stopped thread, a killed thread could
+ * never be revived. This function does return, when passed e.g. an already
+ * killed thread. But if the passed thread is the only one, or a special
+ * thread called "main", then it also terminates the entire process.
+ *
+ * @param[out] thread The thread to terminate.
+ * @exception rb_eFatal The passed thread is the running thread.
+ * @exception rb_eSystemExit The passed thread is the last thread.
+ * @return The passed thread.
+ * @post Either the passed thread, or the process entirely, is killed.
+ *
+ * @internal
+ *
+ * It seems killing the main thread also kills the entire process even if there
+ * are multiple running ractors. No idea why.
+ */
+VALUE rb_thread_kill(VALUE thread);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Creates a Ruby thread that is backended by a C function.
+ *
+ * @param[in] f The function to run on a thread.
+ * @param[in,out] g Passed through to `f`.
+ * @exception rb_eThreadError Could not create a ruby thread.
+ * @exception rb_eSystemCallError Situations like `EPERM`.
+ * @return Allocated instance of ::rb_cThread.
+ * @note This doesn't wait for anything.
+ */
+VALUE rb_thread_create(VALUE (*f)(void *g), void *g);
+
+/**
+ * Identical to rb_thread_sleep(), except it takes struct `timeval` instead.
+ *
+ * @warning This function can be interrupted by signals.
+ * @param[in] time Duration.
+ * @exception rb_eInterrupt Interrupted.
+ */
+void rb_thread_wait_for(struct timeval time);
+
+/**
+ * Obtains the "current" thread.
+ *
+ * @return The current thread of the current ractor of the current execution
+ * context.
+ * @pre This function must be called from a thread controlled by ruby.
+ */
VALUE rb_thread_current(void);
+
+/**
+ * Obtains the "main" thread. There are threads called main. Historically the
+ * (only) main thread was the one which runs when the process boots. Now that
+ * we have Ractor, there are more than one main threads.
+ *
+ * @return The main thread of the current ractor of the current execution
+ * context.
+ * @pre This function must be called from a thread controlled by ruby.
+ */
VALUE rb_thread_main(void);
-VALUE rb_thread_local_aref(VALUE, ID);
-VALUE rb_thread_local_aset(VALUE, ID, VALUE);
+
+/**
+ * This badly named function reads from a Fiber local storage. When this
+ * function was born there was no such thing like a Fiber. The world was
+ * innocent. But now... This is a Fiber local storage. Sorry.
+ *
+ * @param[in] thread Thread that the target Fiber is running.
+ * @param[in] key The name of the Fiber local storage to read.
+ * @retval RUBY_Qnil No such storage.
+ * @retval otherwise The value stored at `key`.
+ * @note There in fact are "true" thread local storage, but Ruby doesn't
+ * provide any interface of them to you, C programmers.
+ */
+VALUE rb_thread_local_aref(VALUE thread, ID key);
+
+/**
+ * This badly named function writes to a Fiber local storage. When this
+ * function was born there was no such thing like a Fiber. The world was
+ * innocent. But now... This is a Fiber local storage. Sorry.
+ *
+ * @param[in] thread Thread that the target Fiber is running.
+ * @param[in] key The name of the Fiber local storage to write.
+ * @param[in] val The new value of the storage.
+ * @exception rb_eFrozenError `thread` is frozen.
+ * @return The passed `val` as-is.
+ * @post Fiber local storage `key` has value of `val`.
+ * @note There in fact are "true" thread local storage, but Ruby doesn't
+ * provide any interface of them to you, C programmers.
+ */
+VALUE rb_thread_local_aset(VALUE thread, ID key, VALUE val);
+
+/**
+ * A `pthread_atfork(3posix)`-like API. Ruby expects its child processes to
+ * call this function at the very beginning of their processes. If you plan to
+ * fork a process don't forget to call it.
+ */
void rb_thread_atfork(void);
+
+/**
+ * :FIXME: situation of this function is unclear. It seems nobody uses it.
+ * Maybe a good idea to KonMari.
+ */
void rb_thread_atfork_before_exec(void);
-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);
+/**
+ * "Recursion" API entry point. This basically calls the given function with
+ * the given arguments, but additionally with recursion flag. The flag is set
+ * to 1 if the execution have already experienced the passed `g` parameter
+ * before.
+ *
+ * @param[in] f The function that possibly recurs.
+ * @param[in,out] g Passed as-is to `f`.
+ * @param[in,out] h Passed as-is to `f`.
+ * @return The return value of f.
+ */
+VALUE rb_exec_recursive(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h);
+
+/**
+ * Identical to rb_exec_recursive(), except it checks for the recursion on the
+ * ordered pair of `{ g, p }` instead of just `g`.
+ *
+ * @param[in] f The function that possibly recurs.
+ * @param[in,out] g Passed as-is to `f`.
+ * @param[in] p Paired object for recursion detection.
+ * @param[in,out] h Passed as-is to `f`.
+ */
+VALUE rb_exec_recursive_paired(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h);
+
+/**
+ * Identical to rb_exec_recursive(), except it calls `f` for outermost
+ * recursion only. Inner recursions yield calls to rb_throw_obj().
+ *
+ * @param[in] f The function that possibly recurs.
+ * @param[in,out] g Passed as-is to `f`.
+ * @param[in,out] h Passed as-is to `f`.
+ * @return The return value of f.
+ *
+ * @internal
+ *
+ * It seems nobody uses the "it calls rb_throw_obj()" part of this function.
+ * @shyouhei doesn't understand the needs.
+ */
+VALUE rb_exec_recursive_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h);
+
+/**
+ * Identical to rb_exec_recursive_outer(), except it checks for the recursion
+ * on the ordered pair of `{ g, p }` instead of just `g`. It can also be seen
+ * as a routine identical to rb_exec_recursive_paired(), except it calls `f`
+ * for outermost recursion only. Inner recursions yield calls to
+ * rb_throw_obj().
+ *
+ * @param[in] f The function that possibly recurs.
+ * @param[in,out] g Passed as-is to `f`.
+ * @param[in] p Paired object for recursion detection.
+ * @param[in,out] h Passed as-is to `f`.
+ *
+ * @internal
+ *
+ * It seems nobody uses the "it calls rb_throw_obj()" part of this function.
+ * @shyouhei doesn't understand the needs.
+ */
+VALUE rb_exec_recursive_paired_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h);
+
+/**
+ * This is the type of UBFs. An UBF is a function that unblocks a blocking
+ * region. For instance when a thread is blocking due to `pselect(3posix)`, it
+ * is highly expected that `pthread_kill(3posix)` can interrupt the system call
+ * and the thread could revive. Or when a thread is blocking due to
+ * `waitpid(3posix)`, it is highly expected that killing the waited process
+ * should suffice. An UBF is a function that does such things. Designing your
+ * own UBF needs deep understanding of why your blocking region blocks, how
+ * threads work in ruby, and a matter of luck. It often is the case you simply
+ * cannot cancel something that had already begun.
+ *
+ * @see rb_thread_call_without_gvl()
+ */
typedef void rb_unblock_function_t(void *);
+
+/**
+ * @private
+ *
+ * This is an implementation detail. Must be a mistake to be here.
+ *
+ * @internal
+ *
+ * Why is this function type different from what rb_thread_call_without_gvl()
+ * takes?
+ */
typedef VALUE rb_blocking_function_t(void *);
+
+/**
+ * Checks for interrupts. In ruby, signals are masked by default. You can
+ * call this function at will to check if there are pending signals. In case
+ * there are, they would be handled in this function.
+ *
+ * If your extension library has a function that takes a long time, consider
+ * calling it periodically.
+ *
+ * @note It might switch to another thread.
+ */
void rb_thread_check_ints(void);
+
+/**
+ * Checks if the thread's execution was recently interrupted. If called from
+ * that thread, this function can be used to detect spurious wake-ups.
+ *
+ * @param[in] thval Thread in question.
+ * @retval 0 The thread was not interrupted.
+ * @retval otherwise The thread was interrupted recently.
+ *
+ * @internal
+ *
+ * Above description is not a lie. But actually the return value is an opaque
+ * trap vector. If you know which bit means which, you can know what happened.
+ */
int rb_thread_interrupted(VALUE thval);
+/**
+ * A special UBF for blocking IO operations. You need deep understanding of
+ * what this actually do before using. Basically you should not use it from
+ * extension libraries. It is too easy to mess up.
+ */
#define RUBY_UBF_IO RBIMPL_CAST((rb_unblock_function_t *)-1)
+
+/**
+ * A special UBF for blocking process operations. You need deep understanding
+ * of what this actually do before using. Basically you should not use it from
+ * extension libraries. It is too easy to mess up.
+ */
#define RUBY_UBF_PROCESS RBIMPL_CAST((rb_unblock_function_t *)-1)
+
+/* thread_sync.c */
+
+/**
+ * Creates a mutex.
+ *
+ * @return An allocated instance of rb_cMutex.
+ */
VALUE rb_mutex_new(void);
+
+/**
+ * Queries if there are any threads that holds the lock.
+ *
+ * @param[in] mutex The mutex in question.
+ * @retval RUBY_Qtrue The mutex is locked by someone.
+ * @retval RUBY_Qfalse The mutex is not locked by anyone.
+ */
VALUE rb_mutex_locked_p(VALUE mutex);
+
+/**
+ * Attempts to lock the mutex, without waiting for other threads to unlock it.
+ * Failure in locking the mutex can be detected by the return value.
+ *
+ * @param[out] mutex The mutex to lock.
+ * @retval RUBY_Qtrue Successfully locked by the current thread.
+ * @retval RUBY_Qfalse Otherwise.
+ * @note This function also returns ::RUBY_Qfalse when the mutex is
+ * already owned by the calling thread itself.
+ */
VALUE rb_mutex_trylock(VALUE mutex);
+
+/**
+ * Attempts to lock the mutex. It waits until the mutex gets available.
+ *
+ * @param[out] mutex The mutex to lock.
+ * @exception rb_eThreadError Recursive deadlock situation.
+ * @return The passed mutex.
+ * @post The mutex is owned by the current thread.
+ */
VALUE rb_mutex_lock(VALUE mutex);
+
+/**
+ * Releases the mutex.
+ *
+ * @param[out] mutex The mutex to unlock.
+ * @exception rb_eThreadError The mutex is not owned by the current thread.
+ * @return The passed mutex.
+ * @post Upon successful return the passed mutex is no longer owned by
+ * the current thread.
+ */
VALUE rb_mutex_unlock(VALUE mutex);
+
+/**
+ * Releases the lock held in the mutex and waits for the period of time;
+ * reacquires the lock on wakeup.
+ *
+ * @pre The lock has to be owned by the current thread beforehand.
+ * @param[out] self The target mutex.
+ * @param[in] timeout Duration, in seconds, in ::rb_cNumeric.
+ * @exception rb_eArgError `timeout` is negative.
+ * @exception rb_eRangeError `timeout` is out of range of `time_t`.
+ * @exception rb_eThreadError The mutex is not owned by the current thread.
+ * @return Number of seconds it actually slept.
+ * @warning It is a failure not to check the return value. This function
+ * can return spuriously for various reasons. Maybe other threads
+ * can rb_thread_wakeup(). Maybe an end user can press the
+ * Control and C key from the interactive console. On the other
+ * hand it can also take longer than the specified. The mutex
+ * could be locked by someone else. It waits then.
+ * @post Upon successful return the passed mutex is owned by the current
+ * thread.
+ *
+ * @internal
+ *
+ * This function is called from `ConditionVariable#wait`. So it is not a
+ * deprecated feature. However @shyouhei have never seen any similar mutex
+ * primitive available in any other languages than Ruby.
+ *
+ * EDIT: In 2021, @shyouhei asked @ko1 in person about this API. He answered
+ * that it is his invention. The motivation behind its design is to eliminate
+ * needs of condition variables as primitives. Unlike other languages, Ruby's
+ * `ConditionVariable` class was written in pure-Ruby initially. We don't have
+ * to implement machine-native condition variables in assembly each time we
+ * port Ruby to a new architecture. This function made it possible. "I felt I
+ * was a genius when this idea came to me", said @ko1.
+ *
+ * `rb_cConditionVariable` is now written in C for speed, though.
+ */
VALUE rb_mutex_sleep(VALUE self, VALUE timeout);
+
+/**
+ * Obtains the lock, runs the passed function, and releases the lock when it
+ * completes.
+ *
+ * @param[out] mutex The mutex to lock.
+ * @param[in] func What to do during the mutex is locked.
+ * @param[in,out] arg Passed as-is to `func`.
+ */
VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/time.h b/include/ruby/internal/intern/time.h
index c7ae6ec2f5..df482862eb 100644
--- a/include/ruby/internal/intern/time.h
+++ b/include/ruby/internal/intern/time.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cTime.
*/
#include "ruby/internal/config.h"
@@ -26,6 +26,7 @@
# include <time.h> /* for time_t */
#endif
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
@@ -35,15 +36,124 @@ 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);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Fills the current time into the given struct.
+ *
+ * @param[out] ts Return buffer.
+ * @exception rb_eSystemCallError Access denied for hardware clock.
+ * @post Current time is stored in `*ts`.
+ */
+void rb_timespec_now(struct timespec *ts);
+
+/**
+ * Creates an instance of ::rb_cTime with the given time and the local
+ * timezone.
+ *
+ * @param[in] sec Seconds since the UNIX epoch.
+ * @param[in] usec Subsecond part, in microseconds resolution.
+ * @exception rb_eRangeError Cannot express the time.
+ * @return An allocated instance of ::rb_cTime.
+ */
+VALUE rb_time_new(time_t sec, long usec);
+
+/**
+ * Identical to rb_time_new(), except it accepts the time in nanoseconds
+ * resolution.
+ *
+ * @param[in] sec Seconds since the UNIX epoch.
+ * @param[in] nsec Subsecond part, in nanoseconds resolution.
+ * @exception rb_eRangeError Cannot express the time.
+ * @return An allocated instance of ::rb_cTime.
+ */
+VALUE rb_time_nano_new(time_t sec, long nsec);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Creates an instance of ::rb_cTime, with given time and offset.
+ *
+ * @param[in] ts Time specifier.
+ * @param[in] offset Offset specifier, can take following values:
+ * - `INT_MAX`: `ts` is in local time.
+ * - `INT_MAX - 1`: `ts` is in UTC.
+ * - `-86400` to `86400`: fixed timezone.
+ * @exception rb_eArgError Malformed `offset`.
+ * @return An allocated instance of ::rb_cTime.
+ */
+VALUE rb_time_timespec_new(const struct timespec *ts, int offset);
+
+/**
+ * Identical to rb_time_timespec_new(), except it takes Ruby values instead of
+ * C structs.
+ *
+ * @param[in] timev Something numeric. Currently Integers, Rationals,
+ * and Floats are accepted.
+ * @param[in] off Offset specifier. As of 2.7 this argument is
+ * heavily extended to take following kinds of
+ * objects:
+ * - ::RUBY_Qundef ... means UTC.
+ * - ::rb_cString ... "+12:34" etc.
+ * - A mysterious "zone" object. This is largely
+ * undocumented. However the initial intent was
+ * that we want to accept
+ * `ActiveSupport::TimeZone` here. Other gems
+ * could also be possible... But how to make an
+ * acceptable class is beyond this document.
+ * @exception rb_eArgError Malformed `off`.
+ * @return An allocated instance of ::rb_cTime.
+ */
+VALUE rb_time_num_new(VALUE timev, VALUE off);
+
+/**
+ * Creates a "time interval". This basically converts an instance of
+ * ::rb_cNumeric into a struct `timeval`, but for instance negative time
+ * interval must not exist.
+ *
+ * @param[in] num An instance of ::rb_cNumeric.
+ * @exception rb_eArgError `num` is negative.
+ * @exception rb_eRangeError `num` is out of range of `timeval::tv_sec`.
+ * @return A struct that represents the identical time to `num`.
+ */
struct timeval rb_time_interval(VALUE num);
+
+/**
+ * Converts an instance of rb_cTime to a struct timeval that represents the
+ * identical point of time. It can also take something numeric; would consider
+ * it as a UNIX time then.
+ *
+ * @param[in] time Instance of either ::rb_cTime or ::rb_cNumeric.
+ * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`.
+ * @return A struct that represents the identical time to `num`.
+ */
struct timeval rb_time_timeval(VALUE time);
+
+/**
+ * Identical to rb_time_timeval(), except for return type.
+ *
+ * @param[in] time Instance of either ::rb_cTime or ::rb_cNumeric.
+ * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`.
+ * @return A struct that represents the identical time to `num`.
+ */
struct timespec rb_time_timespec(VALUE time);
+
+/**
+ * Identical to rb_time_interval(), except for return type.
+ *
+ * @param[in] num An instance of ::rb_cNumeric.
+ * @exception rb_eArgError `num` is negative.
+ * @exception rb_eRangeError `num` is out of range of `timespec::tv_sec`.
+ * @return A struct that represents the identical time to `num`.
+ */
struct timespec rb_time_timespec_interval(VALUE num);
+
+/**
+ * Queries the offset, in seconds between the time zone of the time and the
+ * UTC.
+ *
+ * @param[in] time An instance of ::rb_cTime.
+ * @return Numeric offset.
+ */
VALUE rb_time_utc_offset(VALUE time);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/variable.h b/include/ruby/internal/intern/variable.h
index faa0cc004f..479c3950c1 100644
--- a/include/ruby/internal/intern/variable.h
+++ b/include/ruby/internal/intern/variable.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to names inside of a Ruby program.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
@@ -28,56 +29,599 @@
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*);
+
+/**
+ * Queries the name of a module.
+ *
+ * @param[in] mod An instance of ::rb_cModule.
+ * @retval RUBY_Qnil `mod` is anonymous.
+ * @retval otherwise `mod` is onymous.
+ */
+VALUE rb_mod_name(VALUE mod);
+
+/**
+ * Identical to rb_mod_name(), except it returns `#<Class: ...>` style
+ * inspection for anonymous modules.
+ *
+ * @param[in] mod An instance of ::rb_cModule.
+ * @return An instance of ::rb_cString representing `mod`'s path.
+ */
+VALUE rb_class_path(VALUE mod);
+
+/**
+ * @alias{rb_mod_name}
+ *
+ * @internal
+ *
+ * Am I missing something? Why we have the same thing in different names?
+ */
+VALUE rb_class_path_cached(VALUE mod);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Names a class.
+ *
+ * @param[out] klass Target module to name.
+ * @param[out] space Namespace that `klass` shall reside.
+ * @param[in] name Name of `klass`.
+ * @post `klass` has `space::klass` name.
+ */
+void rb_set_class_path(VALUE klass, VALUE space, const char *name);
+
+/**
+ * Identical to rb_set_class_path(), except it accepts the name as Ruby's
+ * string instead of C's.
+ *
+ * @param[out] klass Target module to name.
+ * @param[out] space Namespace that `klass` shall reside.
+ * @param[in] name Name of `klass`.
+ * @post `klass` has `space::klass` name.
+ */
+void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name);
+
+/**
+ * Identical to rb_path2class(), except it accepts the path as Ruby's string
+ * instead of C's.
+ *
+ * @param[in] path Path to query.
+ * @exception rb_eArgError No such constant.
+ * @exception rb_eTypeError The path resolved to a non-module.
+ * @return Resolved class.
+ */
+VALUE rb_path_to_class(VALUE path);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Resolves a `Q::W::E::R`-style path string to the actual class it points.
+ *
+ * @param[in] path Path to query.
+ * @exception rb_eArgError No such constant.
+ * @exception rb_eTypeError The path resolved to a non-module.
+ * @return Resolved class.
+ */
+VALUE rb_path2class(const char *path);
+
+/**
+ * Queries the name of the given object's class.
+ *
+ * @param[in] obj Arbitrary object.
+ * @return An instance of ::rb_cString representing `obj`'s class' path.
+ */
+VALUE rb_class_name(VALUE obj);
+
+/**
+ * Kicks the autoload procedure as if it was "touched".
+ *
+ * @param[out] space Namespace where autoload is defined.
+ * @param[in] name Name of the autoloaded constant.
+ * @retval RUBY_Qfalse No such autoload.
+ * @retval RUBY_Qtrue Autoload successfully initiated.
+ * @note As an autoloaded library is expected to define `space::name`,
+ * it is a nature of this function to have process-global side
+ * effects.
+ * @note Multiple threads can simultaneously call this API. It blocks
+ * then. That must not last indefinitely but can take longer than
+ * you expect.
+ *
+ * @internal
+ *
+ * @shyouhei has no idea why extension libraries should use this API.
+ */
+VALUE rb_autoload_load(VALUE space, ID name);
+
+/**
+ * Queries if an autoload is defined at a point.
+ *
+ * @param[in] space Namespace where autoload is defined.
+ * @param[in] name Name of the autoloaded constant.
+ * @retval RUBY_Qnil No such autoload.
+ * @retval otherwise The feature (path) registered at `space::name`.
+ */
+VALUE rb_autoload_p(VALUE space, ID name);
+
+/**
+ * Traces a global variable.
+ *
+ * @param[in] argc Either 1 or 2.
+ * @param[in] argv Variable name, optionally a Proc.
+ * @retval RUBY_Qnil No previous tracers.
+ * @retval otherwise Previous tracers.
+ *
+ * @internal
+ *
+ * @shyouhei has no idea why extension libraries should use this API.
+ */
+VALUE rb_f_trace_var(int argc, const VALUE *argv);
+
+/**
+ * Deletes the passed tracer from the passed global variable, or if omitted,
+ * deletes everything.
+ *
+ * @param[in] argc Either 1 or 2.
+ * @param[in] argv Variable name, optionally a Proc.
+ * @retval RUBY_Qnil No previous tracers.
+ * @retval otherwise Deleted tracers.
+ *
+ * @internal
+ *
+ * @shyouhei has no idea why extension libraries should use this API.
+ */
+VALUE rb_f_untrace_var(int argc, const VALUE *argv);
+
+/**
+ * Queries the list of global variables.
+ *
+ * @return The list of the name of the global variables.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
VALUE rb_f_global_variables(void);
-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);
+
+/**
+ * Aliases a global variable. Did you know that you can alias a global
+ * variable? It is like aliasing methods:
+ *
+ * ```ruby
+ * alias $dst $src
+ * ```
+ *
+ * This C function does the same thing.
+ *
+ * @param[in] dst Destination name.
+ * @param[in] src Source name.
+ * @post A global variable named `dst` is defined to be an alias of a
+ * global variable named `src`.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+void rb_alias_variable(ID dst, ID src);
+
+/**
+ * Frees the list of instance variables. 3rd parties need not know, but there
+ * are several ways to store an object's instance variables, depending on its
+ * internal structure. This function makes sense when the passed objects is
+ * using so-called "generic" backend storage. People need not be aware of this
+ * working behind-the-scenes.
+ *
+ * @param[out] obj The object in question.
+ *
+ * @internal
+ *
+ * This just destroys the given object. @shyouhei has no idea why extension
+ * libraries should use this API.
+ */
+void rb_free_generic_ivar(VALUE obj);
+
+/**
+ * Identical to rb_iv_get(), except it accepts the name as an ::ID instead of a
+ * C string.
+ *
+ * @param[in] obj Target object.
+ * @param[in] name Target instance variable to query.
+ * @retval RUBY_nil No such instance variable.
+ * @retval otherwise The value assigned to the instance variable.
+ */
+VALUE rb_ivar_get(VALUE obj, ID name);
+
+/**
+ * Identical to rb_iv_set(), except it accepts the name as an ::ID instead of a
+ * C string.
+ *
+ * @param[out] obj Target object.
+ * @param[in] name Target instance variable.
+ * @param[in] val Value to assign.
+ * @exception rb_eFrozenError Can't modify `obj`.
+ * @exception rb_eArgError `obj` has too many instance variables.
+ * @return Passed value.
+ * @post An instance variable named `name` is defined if absent on
+ * `obj`, whose value is set to `val`.
+ */
+VALUE rb_ivar_set(VALUE obj, ID name, VALUE val);
+
+/**
+ * Queries if the instance variable is defined at the object. This roughly
+ * resembles `defined?(@name)` in `obj`'s context.
+ *
+ * @param[in] obj Target object.
+ * @param[in] name Target instance variable to query.
+ * @retval RUBY_Qtrue There is an instance variable.
+ * @retval RUBY_Qfalse No such instance variable.
+ */
+VALUE rb_ivar_defined(VALUE obj, ID name);
+
+/**
+ * Iterates over an object's instance variables.
+ *
+ * @param[in] obj Target object.
+ * @param[in] func Callback function.
+ * @param[in] arg Passed as-is to the last argument of `func`.
+ */
+void rb_ivar_foreach(VALUE obj, int (*func)(ID name, VALUE val, st_data_t arg), st_data_t arg);
+
+/**
+ * Number of instance variables defined on an object.
+ *
+ * @param[in] obj Target object.
+ * @return Number of instance variables defined on `obj`.
+ */
+st_index_t rb_ivar_count(VALUE obj);
+
+/**
+ * Identical to rb_ivar_get()
+ *
+ * @param[in] obj Target object.
+ * @param[in] name Target instance variable to query.
+ * @retval RUBY_nil No such instance variable.
+ * @retval otherwise The value assigned to the instance variable.
+ *
+ * @internal
+ *
+ * Am I missing something? Why we have the same thing in different names?
+ */
+VALUE rb_attr_get(VALUE obj, ID name);
+
+/**
+ * Resembles `Object#instance_variables`.
+ *
+ * @param[in] obj Target object to query.
+ * @return An array of instance variable names for the receiver.
+ * @note Simply defining an accessor does not create the corresponding
+ * instance variable.
+ */
+VALUE rb_obj_instance_variables(VALUE obj);
+
+/**
+ * Resembles `Object#remove_instance_variable`.
+ *
+ * @param[out] obj Target object.
+ * @param[in] name Variable name to remove, either in Symbol or String.
+ * @return What was removed.
+ * @pre Instance variable named `name` is deleted from `obj`.
+ */
+VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name);
+
+/**
+ * This API is mysterious. It has been there since the initial revision. No
+ * single bits of documents has ever been written. The function name doesn't
+ * describe anything. What should be passed to the argument, or what should be
+ * the return value, are not obvious. Yet it has evolved over time. The
+ * source code is written in counter-intuitive way (as of 3.0).
+ *
+ * Simply put, don't try to understand this API.
+ */
void *rb_mod_const_at(VALUE, void*);
+
+/**
+ * This is a variant of rb_mod_const_at(). As a result, it is also mysterious.
+ * It _seems_ it iterates over the ancestry tree of the module. But what that
+ * means is beyond a human brain.
+ */
void *rb_mod_const_of(VALUE, void*);
+
+/**
+ * This is another mysterious API that comes with no documents at all. It
+ * seems it expects some specific data structure for the passed pointer. But
+ * the details has never been made explicit. It seems nobody should use this
+ * API.
+ */
VALUE rb_const_list(void*);
-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);
+
+/**
+ * Resembles `Module#constants`. List up the constants defined at the
+ * receiver. This includes the names of constants in any included modules,
+ * unless `argv[0]` is ::RUBY_Qfalse.
+ *
+ * The implementation makes no guarantees about the order in which the
+ * constants are yielded.
+ *
+ * @param[in] argc Either 0 or 1.
+ * @param[in] argv Pointer to ::RUBY_Qfalse, if `argc == 1`.
+ * @param[in] recv Target namespace.
+ * @return An array of symbols, which are constant names under `recv`.
+ */
+VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv);
+
+/**
+ * Resembles `Module#remove_const`.
+ *
+ * @param[out] space Target namespace.
+ * @param[in] name Variable name to remove, either in Symbol or String.
+ * @return What was removed.
+ * @pre Constant named `space::name` is deleted.
+ * @note In case what was removed was in fact a module or a class, this
+ * operation does not affect its name. Which means when people
+ * for instance look at it using `p` etc., it still introduces
+ * itself using the deleted name. Can confuse people.
+ */
+VALUE rb_mod_remove_const(VALUE space, VALUE name);
+
+/**
+ * Queries if the constant is defined at the namespace.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name to query.
+ * @retval RUBY_Qtrue There is a constant.
+ * @retval RUBY_Qfalse No such constant.
+ *
+ * @internal
+ *
+ * The return values are not typo! This function returns ruby values casted to
+ * `int`. Completely brain-damaged design.
+ */
+int rb_const_defined(VALUE space, ID name);
+
+/**
+ * Identical to rb_const_defined(), except it doesn't look for parent classes.
+ * For instance `Array` is a toplevel constant, which is visible from
+ * everywhere. But this function does not take such things into account. It
+ * concerns only what is directly defined inside of the given namespace.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name to query.
+ * @retval RUBY_Qtrue There is a constant.
+ * @retval RUBY_Qfalse No such constant.
+ *
+ * @internal
+ *
+ * The return values are not typo! This function returns ruby values casted to
+ * `int`. Completely brain-damaged design.
+ */
+int rb_const_defined_at(VALUE space, ID name);
+
+/**
+ * Identical to rb_const_defined(), except it returns false for private
+ * constants.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name to query.
+ * @retval RUBY_Qtrue There is a constant.
+ * @retval RUBY_Qfalse No such constant.
+ *
+ * @internal
+ *
+ * What does "from" mean? The name sounds quite cryptic.
+ *
+ * The return values are not typo! This function returns ruby values casted to
+ * `int`. Completely brain-damaged design.
+ */
+int rb_const_defined_from(VALUE space, ID name);
+
+/**
+ * Identical to rb_const_defined(), except it returns the actual defined value.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name to query.
+ * @exception rb_eNameError No such constant.
+ * @return The defined constant.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+VALUE rb_const_get(VALUE space, ID name);
+
+/**
+ * Identical to rb_const_defined_at(), except it returns the actual defined
+ * value. It can also be seen as a routine identical to rb_const_get(), except
+ * it doesn't look for parent classes.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name to query.
+ * @exception rb_eNameError No such constant.
+ * @return The defined constant.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+VALUE rb_const_get_at(VALUE space, ID name);
+
+/**
+ * Identical to rb_const_defined_at(), except it returns the actual defined
+ * value. It can also be seen as a routine identical to rb_const_get(), except
+ * it doesn't return a private constant.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name to query.
+ * @exception rb_eNameError No such constant.
+ * @return The defined constant.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+VALUE rb_const_get_from(VALUE space, ID name);
+
+/**
+ * Names a constant.
+ *
+ * @param[out] space Target namespace.
+ * @param[in] name Target name to query.
+ * @param[in] val Value to define.
+ * @exception rb_eTypeError `space` is not a module.
+ * @post `name` is a constant under `space`, whose value is `val`.
+ * @note You can reassign.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+void rb_const_set(VALUE space, ID name, VALUE val);
+
+/**
+ * Identical to rb_mod_remove_const(), except it takes the name as ::ID instead
+ * of ::VALUE.
+ *
+ * @param[out] space Target namespace.
+ * @param[in] name Variable name to remove, either in Symbol or String.
+ * @return What was removed.
+ * @pre Constant named `space::name` is deleted.
+ * @note In case what was removed was in fact a module or a class, this
+ * operation does not affect its name. Which means when people
+ * for instance look at it using `p` etc., it still introduces
+ * itself using the deleted name. Can confuse people.
+ */
+VALUE rb_const_remove(VALUE space, ID name);
+
#if 0 /* EXPERIMENTAL: remove if no problem */
RBIMPL_ATTR_NORETURN()
-VALUE rb_mod_const_missing(VALUE,VALUE);
+/**
+ * This is the default implementation of `Module#const_missing`.
+ *
+ * @param[in] space Target namespace.
+ * @param[in] name Target name that is nonexistent.
+ * @exception rb_eNameError Always.
+ */
+VALUE rb_mod_const_missing(VALUE space, VALUE name);
#endif
-VALUE rb_cvar_defined(VALUE, ID);
-void rb_cvar_set(VALUE, ID, VALUE);
-VALUE rb_cvar_get(VALUE, ID);
-VALUE rb_cvar_find(VALUE, ID, VALUE*);
-void rb_cv_set(VALUE, const char*, VALUE);
-VALUE rb_cv_get(VALUE, const char*);
+
+/**
+ * Queries if the given class has the given class variable.
+ *
+ * @param[in] klass Target class.
+ * @param[in] name Name to query.
+ * @return RUBY_Qtrue Yes there is.
+ * @return RUBY_Qfalse No there isn't.
+ * @pre `klass` must be an instance of rb_cModule.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+VALUE rb_cvar_defined(VALUE klass, ID name);
+
+/**
+ * Assigns a value to a class variable.
+ *
+ * @param[out] klass Target class.
+ * @param[in] name Variable name.
+ * @param[in] val Value to be assigned.
+ * @post `klass` has a class variable named `name` whose value is `val`.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+void rb_cvar_set(VALUE klass, ID name, VALUE val);
+
+/**
+ * Obtains a value from a class variable.
+ *
+ * @param[in] klass Target class.
+ * @param[in] name Variable name.
+ * @exception rb_eNameError Uninitialised class variable.
+ * @exception rb_eRuntimeError `[Bug#14541]` situation.
+ * @return Class variable named `name` under `klass`.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+VALUE rb_cvar_get(VALUE klass, ID name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_cvar_get(), except it takes additional "front" pointer.
+ * This extra parameter is a buffer, which will have the class where the
+ * queried class variable actually resides.
+ *
+ * @param[in] klass Target class.
+ * @param[in] name Variable name.
+ * @param[out] front Return buffer.
+ * @exception rb_eNameError Uninitialised class variable.
+ * @exception rb_eRuntimeError `[Bug#14541]` situation.
+ * @return Class variable named `name` under `klass`.
+ * @post `front` has the class object, which is an ancestor of `klass`,
+ * where the queried class variable actually resides.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_cvar_set(), except it accepts C's string instead of ::ID.
+ *
+ * @param[out] klass Target class.
+ * @param[in] name Variable name.
+ * @param[in] val Value to be assigned.
+ * @post `klass` has a class variable named `name` whose value is `val`.
+ */
+void rb_cv_set(VALUE klass, const char *name, VALUE val);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_cvar_get(), except it accepts C's string instead of ::ID.
+ *
+ * @param[in] klass Target class.
+ * @param[in] name Variable name.
+ * @exception rb_eNameError Uninitialised class variable.
+ * @exception rb_eRuntimeError `[Bug#14541]` situation.
+ * @return Class variable named `name` under `klass`.
+ */
+VALUE rb_cv_get(VALUE klass, const char *name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @alias{rb_cv_set}
+ *
+ * @internal
+ *
+ * Am I missing something? Why we have the same thing in different names?
+ */
void rb_define_class_variable(VALUE, const char*, VALUE);
-VALUE rb_mod_class_variables(int, const VALUE*, VALUE);
-VALUE rb_mod_remove_cvar(VALUE, VALUE);
+
+/**
+ * Resembles `Module#class_variables`. List up the variables defined at the
+ * receiver. This includes the names of constants in any included modules,
+ * unless `argv[0]` is ::RUBY_Qfalse.
+ *
+ * The implementation makes no guarantees about the order in which the
+ * constants are yielded.
+ *
+ * @param[in] argc Either 0 or 1.
+ * @param[in] argv Pointer to ::RUBY_Qfalse, if `argc == 1`.
+ * @param[in] recv Target class.
+ * @return An array of symbols, which are class variable names under
+ * `recv`.
+ */
+VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv);
+
+/**
+ * Resembles `Module#remove_class_variable`.
+ *
+ * @param[out] mod Target class.
+ * @param[in] name Variable name to remove, either in Symbol or String.
+ * @return What was removed.
+ * @pre Instance variable named `name` is deleted from `obj`.
+ */
+VALUE rb_mod_remove_cvar(VALUE mod, VALUE name);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h
index 298a6ad2bb..76af796b54 100644
--- a/include/ruby/internal/intern/vm.h
+++ b/include/ruby/internal/intern/vm.h
@@ -17,9 +17,10 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Public APIs related to rb_cRubyVM.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
@@ -27,40 +28,374 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* vm.c */
+
+/**
+ * Resembles `__LINE__`.
+ *
+ * @retval 0 Current execution context not in a ruby method.
+ * @retval otherwise The current line number of the current thread of the
+ * current ractor of the current execution context.
+ */
int rb_sourceline(void);
+
+/**
+ * Resembles `__FILE__`.
+ *
+ * @retval 0 Current execution context not in a ruby method.
+ * @retval otherwise The current source path of the current thread of the
+ * current ractor of the current execution context.
+ * @note This may or may not be an absolute path.
+ */
const char *rb_sourcefile(void);
+
+/**
+ * Resembles `__method__`.
+ *
+ * @param[out] idp Return buffer for method id.
+ * @param[out] klassp Return buffer for class.
+ * @retval 0 Current execution context not in a method.
+ * @retval 1 Successful return.
+ * @post Upon successful return `*idp` and `*klassp` are updated to have
+ * the current method name and its defined class respectively.
+ * @note Both parameters can be `NULL`.
+ */
int rb_frame_method_id_and_class(ID *idp, VALUE *klassp);
/* vm_eval.c */
-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);
+/**
+ * Identical to rb_funcallv(), except it returns ::RUBY_Qundef instead of
+ * raising ::rb_eNoMethodError.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @retval RUBY_Qundef `recv` doesn't respond to `mid`.
+ * @retval otherwise What the method evaluates to.
+ */
+VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv);
-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);
+/**
+ * Identical to rb_check_funcall(), except you can specify how to handle the
+ * last element of the given array. It can also be seen as a routine identical
+ * to rb_funcallv_kw(), except it returns ::RUBY_Qundef instead of raising
+ * ::rb_eNoMethodError.
+ *
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @retval RUBY_Qundef `recv` doesn't respond to `mid`.
+ * @retval otherwise What the method evaluates to.
+ */
+VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat);
+
+/**
+ * This API is practically a variant of rb_proc_call_kw() now. Historically
+ * when there still was a concept called `$SAFE`, this was an API for that.
+ * But we no longer have that. This function basically ended its role. It
+ * just remains here because of no harm.
+ *
+ * @param[in] cmd A string, or something callable.
+ * @param[in] arg Argument passed to the call.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `arg`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `arg`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @return What the command evaluates to.
+ */
+VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat);
+
+/**
+ * Identical to rb_funcallv(), except it takes Ruby's array instead of C's.
+ * @param[in,out] recv Receiver of the method.
+ * @param[in] mid Name of the method to call.
+ * @param[in] args An instance of ::RArray.
+ * @exception rb_eNoMethodError No such method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method evaluates to.
+ * @pre `args` must be an ::RArray. Call `to_ary` beforehand when
+ * necessary.
+ */
+VALUE rb_apply(VALUE recv, ID mid, VALUE args);
+
+/**
+ * Evaluates a string containing Ruby source code, or the given block, within
+ * the context of the receiver. In order to set the context, the variable
+ * `self` is set to `recv` while the code is executing, giving the code access
+ * to `recv`'s instance variables and private methods.
+ *
+ * When given a block, `recv` is also passed in as the block's only argument.
+ *
+ * When given a string, the optional second and third parameters supply a
+ * filename and starting line number that are used when reporting compilation
+ * errors.
+ *
+ * @param[in] argc Number of objects in `argv`
+ * @param[in] argv C array of 0 up to 3 elements.
+ * @param[in] recv The object in question.
+ * @return What was evaluated.
+ */
+VALUE rb_obj_instance_eval(int argc, const VALUE *argv, VALUE recv);
+
+/**
+ * Executes the given block within the context of the receiver. In order to
+ * set the context, the variable `self` is set to `recv` while the code is
+ * executing, giving the code access to `recv`'s instance variables. Arguments
+ * are passed as block parameters.
+ *
+ * @param[in] argc Number of objects in `argv`
+ * @param[in] argv Arbitrary parameters to be passed to the block.
+ * @param[in] recv The object in question.
+ * @return What was evaluated.
+ * @note Don't confuse this with rb_obj_instance_eval(). The key
+ * difference is whether you can pass arbitrary parameters to the
+ * block, like this:
+ *
+ * ```ruby
+ * class Foo
+ * def initialize
+ * @foo = 5
+ * end
+ * end
+ * Foo.new.instance_exec(7) {|i| @foo + i } # => 12
+ * ```
+ */
+VALUE rb_obj_instance_exec(int argc, const VALUE *argv, VALUE recv);
+
+/**
+ * Identical to rb_obj_instance_eval(), except it evaluates within the context
+ * of module.
+ *
+ * @param[in] argc Number of objects in `argv`
+ * @param[in] argv C array of 0 up to 3 elements.
+ * @param[in] mod The module in question.
+ * @pre `mod` must be a Module.
+ * @return What was evaluated.
+ */
+VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod);
+
+/**
+ * Identical to rb_obj_instance_exec(), except it evaluates within the context
+ * of module.
+ *
+ * @param[in] argc Number of objects in `argv`
+ * @param[in] argv Arbitrary parameters to be passed to the block.
+ * @param[in] mod The module in question.
+ * @pre `mod` must be a Module.
+ * @return What was evaluated.
+ */
+VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod);
/* vm_method.c */
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_RB_DEFINE_ALLOC_FUNC 1
-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_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);
+
+/**
+ * This is the type of functions that ruby calls when trying to allocate an
+ * object. It is sometimes necessary to allocate extra memory regions for an
+ * object. When you define a class that uses ::RTypedData, it is typically the
+ * case. On such situations define a function of this type and pass it to
+ * rb_define_alloc_func().
+ *
+ * @param[in] klass The class that this function is registered.
+ * @return A newly allocated instance of `klass`.
+ */
+typedef VALUE (*rb_alloc_func_t)(VALUE klass);
+
+/**
+ * Sets the allocator function of a class.
+ *
+ * @param[out] klass The class to modify.
+ * @param[in] func An allocator function for the class.
+ * @pre `klass` must be an instance of Class.
+ */
+void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func);
+
+/**
+ * Deletes the allocator function of a class. It is sometimes desirable to
+ * restrict creation of an instance of a class. For example it rarely makes
+ * sense for a DB adaptor class to allow programmers creating DB row objects
+ * without querying the DB itself. You can kill sporadic creation of such
+ * objects then, by nullifying the allocator function using this API. Your
+ * object shall be allocated using #RB_NEWOBJ_OF() directly.
+ *
+ * @param[out] klass The class to modify.
+ * @pre `klass` must be an instance of Class.
+ */
+void rb_undef_alloc_func(VALUE klass);
+
+/**
+ * Queries the allocator function of a class.
+ *
+ * @param[in] klass The class in question.
+ * @pre `klass` must be an instance of Class.
+ * @retval 0 No allocator function is registered.
+ * @retval otherwise The allocator function.
+ *
+ * @internal
+ *
+ * Who cares? @shyouhei finds no practical usage of the return value. Maybe we
+ * need KonMari.
+ */
+rb_alloc_func_t rb_get_alloc_func(VALUE klass);
+
+/**
+ * Clears the inline constant caches associated with a particular ID. Extension
+ * libraries should not bother with such things. Just forget about this API (or
+ * even, the presence of constant caches).
+ */
+void rb_clear_constant_cache_for_id(ID id);
+
+/**
+ * Resembles `alias`.
+ *
+ * @param[out] klass Where to define an alias.
+ * @param[in] dst New name.
+ * @param[in] src Existing name.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @exception rb_eNameError No such method named `src`.
+ * @post `klass` has a method named `dst`, which is the identical to its
+ * method named `src`.
+ */
+void rb_alias(VALUE klass, ID dst, ID src);
+
+/**
+ * This function resembles now-deprecated `Module#attr`.
+ *
+ * @param[out] klass Where to define an attribute.
+ * @param[in] name Name of an instance variable.
+ * @param[in] need_reader Whether attr_reader is needed.
+ * @param[in] need_writer Whether attr_writer is needed.
+ * @param[in] honour_visibility Whether to use the current visibility.
+ * @exception rb_eTypeError `klass` is not a class.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @post If `need_reader` is set `klass` has a method named `name`.
+ * @post If `need_writer` is set `klass` has a method named `name=`.
+ *
+ * @internal
+ *
+ * The three `int` arguments should have been bool, but there was no such thing
+ * like a bool when K&R was used in this project.
+ */
+void rb_attr(VALUE klass, ID name, int need_reader, int need_writer, int honour_visibility);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Removes a method. Don't confuse this to rb_undef_method(), which doesn't
+ * remove a method. This one resembles `Module#remove_method`.
+ *
+ * @param[out] klass The class to remove a method.
+ * @param[in] name Name of a method to be removed.
+ * @exception rb_eTypeError `klass` is a non-module.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @exception rb_eNameError No such method.
+ * @see rb_undef_method
+ */
+void rb_remove_method(VALUE klass, const char *name);
+
+/**
+ * Identical to rb_remove_method(), except it accepts the method name as ::ID.
+ *
+ * @param[out] klass The class to remove a method.
+ * @param[in] mid Name of a method to be removed.
+ * @exception rb_eTypeError `klass` is a non-module.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @exception rb_eNameError No such method.
+ * @see rb_undef
+ */
+void rb_remove_method_id(VALUE klass, ID mid);
+
+/**
+ * Queries if the klass has this method. This function has only one line of
+ * document in the implementation that states "// deprecated". Don't know what
+ * that means though.
+ *
+ * @param[in] klass The class in question.
+ * @param[in] id The method name to query.
+ * @param[in] ex Undocumented magic value.
+ * @retval false Method not found.
+ * @retval true There is a method.
+ * @pre `klass` must be a module.
+ *
+ * @internal
+ *
+ * @shyouhei has no motivation to describe what should be passed to `ex`. It
+ * seems this function should just be trashed.
+ */
+int rb_method_boundp(VALUE klass, ID id, int ex);
+
+/**
+ * Well... Let us hesitate from describing what a "basic definition" is. This
+ * nuanced concept should have been kept private. Just please. Don't touch
+ * it. This function is a badly distributed random number generator. Right?
+ *
+ * @param[in] klass The class in question.
+ * @param[in] mid The method name in question.
+ * @retval 1 It is.
+ * @retval 0 It isn't.
+ */
+int rb_method_basic_definition_p(VALUE klass, ID mid);
+
+/**
+ * Identical to rb_respond_to(), except it additionally takes the visibility
+ * parameter. This does not make difference unless the object has
+ * `respond_to?` undefined, but has `respond_to_missing?` defined. That case
+ * the passed argument becomes the second argument of `respond_to_missing?`.
+ *
+ * @param[in] obj The object in question.
+ * @param[in] mid The method name in question.
+ * @param[in] private_p This is the second argument of `obj`'s
+ * `respond_to_missing?`.
+ * @retval 1 Yes it does.
+ * @retval 0 No it doesn't.
+ */
+int rb_obj_respond_to(VALUE obj, ID mid, int private_p);
+
+/**
+ * Queries if the object responds to the method. This involves calling the
+ * object's `respond_to?` method.
+ *
+ * @param[in] obj The object in question.
+ * @param[in] mid The method name in question.
+ * @retval 1 Yes it does.
+ * @retval 0 No it doesn't.
+ */
+int rb_respond_to(VALUE obj, ID mid);
RBIMPL_ATTR_NORETURN()
+/**
+ * Raises ::rb_eNotImpError. This function is used as an argument to
+ * rb_define_method() etc.
+ *
+ * ```CXX
+ * rb_define_method(rb_cFoo, "foo", rb_f_notimplement, -1);
+ * ```
+ *
+ * @param argc Unused parameter.
+ * @param argv Unused parameter.
+ * @param obj Unused parameter.
+ * @param marker Unused parameter.
+ * @exception rb_eNotImpError Always.
+ * @return Never returns.
+ *
+ * @internal
+ *
+ * See also the Q&A section of include/ruby/internal/anyargs.h.
+ */
VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker);
#if !defined(RUBY_EXPORT) && defined(_WIN32)
RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker);
@@ -68,7 +403,27 @@ RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE m
#endif
/* vm_backtrace.c */
+
+/**
+ * Prints the backtrace out to the standard error. This just confuses people
+ * for no reason. Evil souls must only use it.
+ *
+ * @internal
+ *
+ * Actually it is very useful when called from an interactive GDB session.
+ */
void rb_backtrace(void);
+
+/**
+ * Creates the good old fashioned array-of-strings style backtrace info.
+ *
+ * @return An array which contains strings, which are the textual
+ * representations of the backtrace locations of the current thread of
+ * the current ractor of the current execution context.
+ * @note Ruby scripts can access more sophisticated
+ * `Thread::Backtrace::Location`. But it seems there is no way for C
+ * extensions to use that API.
+ */
VALUE rb_make_backtrace(void);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h
index 12e7486e15..662d39c0ec 100644
--- a/include/ruby/internal/interpreter.h
+++ b/include/ruby/internal/interpreter.h
@@ -17,10 +17,11 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Interpreter embedding APIs.
*/
#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
@@ -28,65 +29,275 @@ 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
+/**
+ * @defgroup ruby1 ruby(1) implementation
+ *
* A part of the implementation of ruby(1) command.
* Other programs that embed Ruby interpreter do not always need to use these
* functions.
+ *
* @{
*/
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Initializes the process for libruby.
+ *
+ * This function assumes this process is `ruby(1)` and it has just started.
+ * Usually programs that embed CRuby interpreter may not call this function,
+ * and may do their own initialization.
+ *
+ * @param[in] argc Pointer to process main's `argc`.
+ * @param[in] argv Pointer to process main's `argv`.
+ * @warning `argc` and `argv` cannot be `NULL`.
+ *
+ * @internal
+ *
+ * AFAIK Ruby does write to argv, especially `argv[0][0]`, via setproctitle(3).
+ * It is intentional that the argument is not const-qualified.
+ */
void ruby_sysinit(int *argc, char ***argv);
+
+/**
+ * Calls ruby_setup() and check error.
+ *
+ * Prints errors and calls exit(3) if an error occurred.
+ */
void ruby_init(void);
+
+/**
+ * Processes command line arguments and compiles the Ruby source to execute.
+ *
+ * This function does:
+ * - Processes the given command line flags and arguments for `ruby(1)`
+ * - Compiles the source code from the given argument, `-e` or `stdin`, and
+ * - Returns the compiled source as an opaque pointer to an internal data
+ * structure
+ *
+ * @param[in] argc Process main's `argc`.
+ * @param[in] argv Process main's `argv`.
+ * @return An opaque pointer to the compiled source or an internal special
+ * value. Pass it to ruby_executable_node() to detect which.
+ * @see ruby_executable_node
+ */
void* ruby_options(int argc, char** argv);
+
+/**
+ * Checks the return value of ruby_options().
+ *
+ * ruby_options() sometimes returns a special value to indicate this process
+ * should immediately exit. This function checks if the case. Also stores the
+ * exit status that the caller have to pass to exit(3) into `*status`.
+ *
+ * @param[in] n A return value of ruby_options().
+ * @param[out] status Pointer to the exit status of this process.
+ * @retval 0 The given value is such a special value.
+ * @retval otherwise The given opaque pointer is actually a compiled
+ * source.
+ */
int ruby_executable_node(void *n, int *status);
+
+/**
+ * Runs the given compiled source and exits this process.
+ *
+ * @param[in] n Opaque "node" pointer.
+ * @retval EXIT_SUCCESS Successfully run the source.
+ * @retval EXIT_FAILURE An error occurred.
+ */
int ruby_run_node(void *n);
/* version.c */
+/** Prints the version information of the CRuby interpreter to stdout. */
void ruby_show_version(void);
+
#ifndef ruby_show_copyright
+/** Prints the copyright notice of the CRuby interpreter to stdout. */
void ruby_show_copyright(void);
#endif
-/*! A convenience macro to call ruby_init_stack(). Must be placed just after
- * variable declarations */
+/**
+ * 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*);
+/**
+ * Set stack bottom of Ruby implementation.
+ *
+ * You must call this function before any heap allocation by Ruby
+ * implementation. Or GC will break living objects.
+ *
+ * @param[in] addr A pointer somewhere on the stack, near its bottom.
+ */
+void ruby_init_stack(volatile VALUE *addr);
+/**
+ * Initializes the VM and builtin libraries.
+ *
+ * @retval 0 Initialization succeeded.
+ * @retval otherwise An error occurred.
+ *
+ * @internal
+ *
+ * Though not a part of our public API, the return value is in fact an enum
+ * ruby_tag_type. You can see the potential "otherwise" values by looking at
+ * vm_core.h.
+ */
int ruby_setup(void);
-int ruby_cleanup(int);
+/**
+ * Destructs the VM.
+ *
+ * Runs the VM finalization processes as well as ruby_finalize(), and frees
+ * resources used by the VM.
+ *
+ * @param[in] ex Default value to the return value.
+ * @retval EXIT_FAILURE An error occurred.
+ * @retval ex Successful cleanup.
+ * @note This function does not raise any exception.
+ */
+int ruby_cleanup(int ex);
+
+/**
+ * Runs the VM finalization processes.
+ *
+ * `END{}` and procs registered by `Kernel.#at_exit` are executed here. See the
+ * Ruby language spec for more details.
+ *
+ * @note This function is allowed to raise an exception if an error occurred.
+ */
void ruby_finalize(void);
RBIMPL_ATTR_NORETURN()
+/** Calls ruby_cleanup() and exits the process. */
void ruby_stop(int);
+/**
+ * Checks for stack overflow.
+ *
+ * @retval true NG machine stack is about to overflow.
+ * @retval false OK there still is a room in the stack.
+ *
+ * @internal
+ *
+ * Does anybody use it? So far @shyouhei have never seen any actual use-case.
+ */
int ruby_stack_check(void);
-size_t ruby_stack_length(VALUE**);
+/**
+ * Queries what Ruby thinks is the machine stack. Ruby manages a region of
+ * memory. It calls that area the "machine stack". By calling this function,
+ * in spite of its name, you can obtain both one end of the stack and its
+ * length at once. Which means you can know the entire region.
+ *
+ * @param[out] topnotch On return the pointer points to the upmost address of
+ * the macihne stack that Ruby knows.
+ * @return Length of the machine stack that Ruby knows.
+ *
+ * @internal
+ *
+ * Does anybody use it? @shyouhei is quite skeptical if this is useful outside
+ * of the VM. Maybe it was a wrong idea to expose this API to 3rd parties.
+ */
+size_t ruby_stack_length(VALUE **topnotch);
+
+/**
+ * Identical to ruby_run_node(), except it returns an opaque execution status.
+ * You can pass it to rb_cleanup().
+ *
+ * @param[in] n Opaque "node" pointer.
+ * @retval 0 Successful end-of-execution.
+ * @retval otherwise An error occurred.
+ *
+ * @internal
+ *
+ * Though not a part of our public API, the return value is in fact an enum
+ * ruby_tag_type. You can see the potential "otherwise" values by looking at
+ * vm_core.h.
+ */
int ruby_exec_node(void *n);
+/**
+ * Sets the current script name to this value.
+ *
+ * This is similar to `$0 = name` in Ruby level but also affects
+ * `Method#location` and others.
+ *
+ * @param[in] name File name to set.
+ */
void ruby_script(const char* name);
+
+/**
+ * Identical to ruby_script(), except it takes the name as a Ruby String
+ * instance.
+ *
+ * @param[in] name File name to set.
+ */
void ruby_set_script_name(VALUE name);
+/** Defines built-in variables */
void ruby_prog_init(void);
-void ruby_set_argv(int, char**);
-void *ruby_process_options(int, char**);
+
+/**
+ * Sets argv that ruby understands. Your program might have its own command
+ * line parameters etc. Handle them as you wish, and pass remaining parts of
+ * argv here.
+ *
+ * @param[in] argc Number of elements of `argv`.
+ * @param[in] argv Command line arguments.
+ */
+void ruby_set_argv(int argc, char **argv);
+
+/**
+ * Identical to ruby_options(), except it raises ruby-level exceptions on
+ * failure.
+ *
+ * @param[in] argc Process main's `argc`.
+ * @param[in] argv Process main's `argv`.
+ * @return An opaque "node" pointer.
+ */
+void *ruby_process_options(int argc, char **argv);
+
+/**
+ * Sets up `$LOAD_PATH`.
+ *
+ * @internal
+ *
+ * @shyouhei guesses this has to be called at very later stage, at least after
+ * the birth of object system. But is not exactly sure when.
+ */
void ruby_init_loadpath(void);
-void ruby_incpush(const char*);
+
+/**
+ * Appends the given path to the end of the load path.
+ *
+ * @pre ruby_init_loadpath() must be done beforehand.
+ * @param[in] path The path you want to push to the load path.
+ */
+void ruby_incpush(const char *path);
+
+/**
+ * Clear signal handlers.
+ *
+ * Ruby installs its own signal handler (apart from those which user scripts
+ * set). This is to clear that. Must be called when the ruby part terminates,
+ * before switching to your program's own logic.
+ */
void ruby_sig_finalize(void);
-/*! @} */
+/** @} */
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/iterator.h b/include/ruby/internal/iterator.h
index 720262f146..5f706460f8 100644
--- a/include/ruby/internal/iterator.h
+++ b/include/ruby/internal/iterator.h
@@ -17,57 +17,496 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Block related APIs.
*/
+#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RB_BLOCK_CALL_FUNC_STRICT 1
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1
+
+/**
+ * Shim for block function parameters. Historically ::rb_block_call_func_t had
+ * only two parameters. Over time it evolved to have much more than that. By
+ * using this macro you can absorb such API differences.
+ *
+ * ```CXX
+ * // This works since 2.1.0
+ * VALUE my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c));
+ * ```
+ */
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \
VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg
+
+/**
+ * This is the type of a function that the interpreter expect for C-backended
+ * blocks. Blocks are often written in Ruby. But C extensions might want to
+ * have their own blocks. In order to do so authors have to create a separate
+ * C function of this type, and pass its pointer to rb_block_call().
+ *
+ * ```CXX
+ * VALUE
+ * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c))
+ * {
+ * const auto plus = rb_intern("+");
+ * return rb_funcall(c, plus, 1, y);
+ * }
+ *
+ * VALUE
+ * my_own_method(VALUE self)
+ * {
+ * const auto each = rb_intern("each");
+ * return rb_block_call(self, each, 0, 0, my_own_iterator, self);
+ * }
+ * ```
+ */
typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg));
+
+/**
+ * Shorthand type that represents an iterator-written-in-C function pointer.
+ */
typedef rb_block_call_func *rb_block_call_func_t;
-VALUE rb_each(VALUE);
-VALUE rb_yield(VALUE);
+/**
+ * This is a shorthand of calling `obj.each`.
+ *
+ * @param[in] obj The receiver.
+ * @return What `obj.each` returns.
+ *
+ * @internal
+ *
+ * Does anyone still need it? This API was to use with rb_iterate(), which is
+ * marked deprecated (see below). Old idiom to call an iterator was:
+ *
+ * ```CXX
+ * VALUE recv;
+ * VALUE iter_func(ANYARGS);
+ * VALUE iter_data;
+ * rb_iterate(rb_each, recv, iter_func, iter_data);
+ * ```
+ */
+VALUE rb_each(VALUE obj);
+
+/**
+ * Yields the block. In Ruby there is a concept called a block. You can pass
+ * one to a method. In a method, when called with a block, you can yield it
+ * using this function.
+ *
+ * ```CXX
+ * VALUE
+ * iterate(VALUE self)
+ * {
+ * extern int get_n(VALUE);
+ * extern VALUE get_v(VALUE, VALUE);
+ * const auto n = get_n(self);
+ *
+ * for (int i=0; i<n; i++) {
+ * auto v = get_v(self, i);
+ *
+ * rb_yield(v);
+ * }
+ * return self;
+ * }
+ * ```
+ *
+ * @param[in] val Passed to the block.
+ * @exception rb_eLocalJumpError There is no block given.
+ * @return Evaluated value of the given block.
+ */
+VALUE rb_yield(VALUE val);
+
+/**
+ * Identical to rb_yield(), except it takes variadic number of parameters and
+ * pass them to the block.
+ *
+ * @param[in] n Number of parameters.
+ * @param[in] ... List of arguments passed to the block.
+ * @exception rb_eLocalJumpError There is no block given.
+ * @return Evaluated value of the given block.
+ */
VALUE rb_yield_values(int n, ...);
+
+/**
+ * Identical to rb_yield_values(), except it takes the parameters as a C array
+ * instead of variadic arguments.
+ *
+ * @param[in] n Number of parameters.
+ * @param[in] argv List of arguments passed to the block.
+ * @exception rb_eLocalJumpError There is no block given.
+ * @return Evaluated value of the given block.
+ */
VALUE rb_yield_values2(int n, const VALUE *argv);
+
+/**
+ * Identical to rb_yield_values2(), except you can specify how to handle the
+ * last element of the given array.
+ *
+ * @param[in] n Number of parameters.
+ * @param[in] argv List of arguments passed to the block.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `ary`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `ary`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS makes no sense here.
+ * @exception rb_eLocalJumpError There is no block given.
+ * @return Evaluated value of the given block.
+ */
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);
+
+/**
+ * Identical to rb_yield_values(), except it splats an array to generate the
+ * list of parameters.
+ *
+ * @param[in] ary Array to splat.
+ * @exception rb_eLocalJumpError There is no block given.
+ * @return Evaluated value of the given block.
+ */
+VALUE rb_yield_splat(VALUE ary);
+
+/**
+ * Identical to rb_yield_splat(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] ary Array to splat.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `ary`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `ary`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS makes no sense here.
+ * @exception rb_eLocalJumpError There is no block given.
+ * @return Evaluated value of the given block.
+ */
+VALUE rb_yield_splat_kw(VALUE ary, int kw_splat);
+
+/**
+ * Pass a passed block.
+ *
+ * Sometimes you want to "pass" a block form one method to another. Suppose
+ * you have this Ruby method `foo`:
+ *
+ * ```ruby
+ * def foo(x, y)
+ * x.open(y) do |*z|
+ * yield(*z)
+ * end
+ * end
+ * ```
+ *
+ * And suppose you want to translate this into C. Then rb_yield_block()
+ * function is usable in this situation.
+ *
+ * ```CXX
+ * VALUE
+ * foo_translated_into_C(VALUE self, VALUE x, VALUE y)
+ * {
+ * const auto open = rb_intern("open");
+ *
+ * return rb_block_call(x, open, 1, &y, rb_yield_block, Qfalse);
+ * // ^^^^^^^^^^^^^^ Here.
+ * }
+ * ```
+ *
+ * @see rb_funcall_passing_block
+ *
+ * @internal
+ *
+ * @shyouhei honestly doesn't understand why this is needed, given there
+ * already was rb_funcall_passing_block() at the time it was implemented. If
+ * somebody knows its raison d'etre, please improve the document :FIXME:
+ */
VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */
+
+/**
+ * Determines if the current method is given a keyword argument.
+ *
+ * @retval false No keyword argument is given.
+ * @retval true Keyword argument(s) are given.
+ * @ingroup defmethod
+ */
int rb_keyword_given_p(void);
+
+/**
+ * Determines if the current method is given a block.
+ *
+ * @retval false No block is given.
+ * @retval true A block is given.
+ * @ingroup defmethod
+ *
+ * @internal
+ *
+ * This function should have returned a bool. But at the time it was designed
+ * the project was entirely written in K&R C.
+ */
int rb_block_given_p(void);
+
+/**
+ * Declares that the current method needs a block.
+ *
+ * @exception rb_eLocalJumpError No block given.
+ * @ingroup defmethod
+ */
void rb_need_block(void);
-VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE);
+
+#ifndef __cplusplus
+RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
+#endif
+/**
+ * Old way to iterate a block.
+ *
+ * @deprecated This is an old API. Use rb_block_call() instead.
+ * @warning The passed function must at least once call a ruby method
+ * (to handle interrupts etc.)
+ * @param[in] func1 A function that could yield a value.
+ * @param[in,out] data1 Passed to `func1`
+ * @param[in] proc A function acts as a block.
+ * @param[in,out] data2 Passed to `proc` as the data2 parameter.
+ * @return What `func1` returns.
+ */
+VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
+
#ifdef __cplusplus
-namespace ruby {namespace backward {
+namespace ruby {
+namespace backward {
+/**
+ * Old way to iterate a block.
+ *
+ * @deprecated This is an old API. Use rb_block_call() instead.
+ * @warning The passed function must at least once call a ruby method
+ * (to handle interrupts etc.)
+ * @param[in] iter A function that could yield a value.
+ * @param[in,out] data1 Passed to `func1`
+ * @param[in] bl A function acts as a block.
+ * @param[in,out] data2 Passed to `proc` as the data2 parameter.
+ * @return What `func1` returns.
+ */
static inline VALUE
rb_iterate_deprecated(VALUE (*iter)(VALUE), VALUE data1, rb_block_call_func_t bl, VALUE data2)
{
return ::rb_iterate(iter, data1, bl, data2);
}}}
+
+RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
+VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
#endif
-DEPRECATED_BY(rb_block_call since 1.9, 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);
+
+/**
+ * Identical to rb_funcallv(), except it additionally passes a function as a
+ * block. When the method yields, `proc` is called with the yielded value as
+ * its first argument, and `data2` as the second. Yielded values would be
+ * packed into an array if multiple values are yielded at once.
+ *
+ * @param[in,out] obj Receiver.
+ * @param[in] mid Method signature.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arguments passed to `obj.mid`.
+ * @param[in] proc A function acts as a block.
+ * @param[in,out] data2 Passed to `proc` as the data2 parameter.
+ * @return What `obj.mid` returns.
+ */
+VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2);
+
+/**
+ * Identical to rb_funcallv_kw(), except it additionally passes a function as a
+ * block. It can also be seen as a routine identical to rb_block_call(),
+ * except it handles keyword-ness of `argv[argc-1]`.
+ *
+ * @param[in,out] obj Receiver.
+ * @param[in] mid Method signature.
+ * @param[in] argc Number of arguments including the keywords.
+ * @param[in] argv Arguments passed to `obj.mid`.
+ * @param[in] proc A function acts as a block.
+ * @param[in,out] data2 Passed to `proc` as the data2 parameter.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @return What `obj.mid` returns.
+ */
+VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat);
+
+/**
+ * Identical to rb_rescue2(), except it does not take a list of exception
+ * classes. This is a shorthand of:
+ *
+ * ```CXX
+ * rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0);
+ * ```
+ *
+ * @param[in] b_proc A function which potentially raises an exception.
+ * @param[in,out] data1 Passed to `b_proc`.
+ * @param[in] r_proc A function which rescues an exception in `b_proc`.
+ * @param[in,out] data2 The first argument of `r_proc`.
+ * @return The return value of `b_proc` if no exception occurs, or the
+ * return value of `r_proc` otherwise.
+ * @see rb_rescue
+ * @see rb_ensure
+ * @see rb_protect
+ * @ingroup exception
+ */
+VALUE rb_rescue(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*r_proc)(VALUE, VALUE), VALUE data2);
+
+/**
+ * An equivalent of `rescue` clause.
+ *
+ * First it calls the function `b_proc` with `data1` as the argument. If
+ * nothing is thrown the function happily returns the return value of `b_proc`.
+ * When `b_proc` raises an exception, and the exception is a kind of one of the
+ * given exception classes, it then calls `r_proc` with `data2` and that
+ * exception. If the exception does not match any of them, it propagates.
+ *
+ * @param[in] b_proc A function which potentially raises an exception.
+ * @param[in,out] data1 Passed to `b_proc`.
+ * @param[in] r_proc A function which rescues an exception in `b_proc`.
+ * @param[in,out] data2 The first argument of `r_proc`.
+ * @param[in] ... 1 or more exception classes. Must be terminated by
+ * `(VALUE)0`
+ * @return The return value of `b_proc` if no exception occurs, or the
+ * return value of `r_proc` otherwise.
+ * @see rb_rescue
+ * @see rb_ensure
+ * @see rb_protect
+ * @ingroup exception
+ */
+VALUE rb_rescue2(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*r_proc)(VALUE, VALUE), VALUE data2, ...);
+
+/**
+ * Identical to rb_rescue2(), except it takes `va_list` instead of variadic
+ * number of arguments. This is exposed to 3rd parties because inline
+ * functions use it. Basically you don't have to bother.
+ *
+ * @param[in] b_proc A function which potentially raises an exception.
+ * @param[in,out] data1 Passed to `b_proc`.
+ * @param[in] r_proc A function which rescues an exception in `b_proc`.
+ * @param[in,out] data2 The first argument of `r_proc`.
+ * @param[in] ap 1 or more exception classes. Must be terminated by
+ * `(VALUE)0`
+ * @return The return value of `b_proc` if no exception occurs, or the
+ * return value of `r_proc` otherwise.
+ * @see rb_rescue
+ * @see rb_ensure
+ * @see rb_protect
+ * @ingroup exception
+ */
+VALUE rb_vrescue2(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*r_proc)(VALUE, VALUE), VALUE data2, va_list ap);
+
+/**
+ * An equivalent to `ensure` clause. Calls the function `b_proc` with `data1`
+ * as the argument, then calls `e_proc` with `data2` when execution terminated.
+ *
+ * @param[in] b_proc A function representing begin clause.
+ * @param[in,out] data1 Passed to `b_proc`.
+ * @param[in] e_proc A function representing ensure clause.
+ * @param[in,out] data2 Passed to `e_proc`.
+ * @retval RUBY_Qnil exception occurred inside of `b_proc`.
+ * @retval otherwise The return value of `b_proc`.
+ * @see rb_rescue
+ * @see rb_rescue2
+ * @see rb_protect
+ * @ingroup exception
+ */
+VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
+
+/**
+ * Executes the passed block and catches values thrown from inside of it.
+ *
+ * In case the block does not contain any throw`, this function returns the
+ * value of the last expression evaluated.
+ *
+ * ```CXX
+ * VALUE
+ * iter(RB_BLOCK_CALL_FUNC_ARGLIST(yielded, callback))
+ * {
+ * return INT2FIX(123);
+ * }
+ *
+ * VALUE
+ * method(VALUE self)
+ * {
+ * return rb_catch("tag", iter, Qnil); // returns 123
+ * }
+ * ```
+ *
+ * In case there do exist `throw`, Ruby searches up its execution context for a
+ * `catch` block. When a matching catch is found, the block stops executing
+ * and returns that thrown value instead.
+ *
+ * ```CXX
+ * VALUE
+ * iter(RB_BLOCK_CALL_FUNC_ARGLIST(yielded, callback))
+ * {
+ * rb_throw("tag", 456);
+ * return INT2FIX(123);
+ * }
+ *
+ * VALUE
+ * method(VALUE self)
+ * {
+ * return rb_catch("tag", iter, Qnil); // returns 456
+ * }
+ * ```
+ *
+ * @param[in] tag Arbitrary tag string.
+ * @param[in] func Function pointer that acts as a block.
+ * @param[in,out] data Extra parameter passed to `func`.
+ * @return Either caught value for `tag`, or the return value of `func`
+ * if nothing is thrown.
+ */
+VALUE rb_catch(const char *tag, rb_block_call_func_t func, VALUE data);
+
+/**
+ * Identical to rb_catch(), except it catches arbitrary Ruby objects.
+ *
+ * @param[in] tag Arbitrary tag object.
+ * @param[in] func Function pointer that acts as a block.
+ * @param[in,out] data Extra parameter passed to `func`.
+ * @return Either caught value for `tag`, or the return value of `func`
+ * if nothing is thrown.
+ */
+VALUE rb_catch_obj(VALUE tag, rb_block_call_func_t func, VALUE data);
RBIMPL_ATTR_NORETURN()
-void rb_throw(const char*,VALUE);
+/**
+ * Transfers control to the end of the active `catch` block waiting for `tag`.
+ * Raises rb_eUncughtThrow if there is no `catch` block for the tag. The
+ * second parameter supplies a return value for the `catch` block, which
+ * otherwise defaults to ::RUBY_Qnil. For examples, see rb_catch().
+ *
+ * @param[in] tag Tag string.
+ * @param[in] val Value to throw.
+ * @exception rb_eUncughtThrow There is no corresponding `catch` clause.
+ * @note It never returns.
+ */
+void rb_throw(const char *tag, VALUE val);
RBIMPL_ATTR_NORETURN()
-void rb_throw_obj(VALUE,VALUE);
+/**
+ * Identical to rb_throw(), except it allows arbitrary Ruby object to become a
+ * tag.
+ *
+ * @param[in] tag Arbitrary object.
+ * @param[in] val Value to throw.
+ * @exception rb_eUncughtThrow There is no corresponding `catch` clause.
+ * @note It never returns.
+ */
+void rb_throw_obj(VALUE tag, VALUE val);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h
index 1f95387416..6884db195d 100644
--- a/include/ruby/internal/memory.h
+++ b/include/ruby/internal/memory.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Memory management stuff.
*/
#include "ruby/internal/config.h"
@@ -62,6 +62,8 @@
#include "ruby/backward/2/assume.h"
#include "ruby/defines.h"
+/** @cond INTENAL_MACRO */
+
/* Make alloca work the best possible way. */
#if defined(alloca)
# /* Take that. */
@@ -75,18 +77,86 @@ extern "C" void *alloca(size_t);
extern void *alloca();
#endif
-#if defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8
+/** @endcond */
+
+#if defined(__DOXYGEN__)
+/**
+ * @private
+ *
+ * Type that is as twice wider as size_t. This is an implementation detail of
+ * rb_mul_size_overflow(). People should not use it. This is not a good name
+ * either.
+ */
+typedef uint128_t DSIZE_T;
+#elif defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8
# define DSIZE_T uint128_t
#elif SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG
# define DSIZE_T unsigned LONG_LONG
#endif
+/**
+ * @private
+ *
+ * Maximum possible number of bytes that #RB_ALLOCV can allocate using
+ * `alloca`. Anything beyond this is allocated using rb_alloc_tmp_buffer().
+ * This selection is transparent to users. People don't have to bother.
+ */
#ifdef C_ALLOCA
# define RUBY_ALLOCV_LIMIT 0
#else
# define RUBY_ALLOCV_LIMIT 1024
#endif
+/**
+ * Prevents premature destruction of local objects. Ruby's garbage collector
+ * is conservative; it scans the C level machine stack as well. Possible in-
+ * use Ruby objects must remain visible on stack, to be properly marked as
+ * such. However contemporary C compilers do not interface well with this.
+ * Consider the following example:
+ *
+ * ```CXX
+ * auto s = rb_str_new_cstr(" world");
+ * auto sptr = RSTRING_PTR(s);
+ * auto t = rb_str_new_cstr("hello,"); // Possible GC invocation
+ * auto u = rb_str_cat_cstr(t, sptr);
+ *
+ * RB_GC_GUARD(s); // ensure `s` (and thus `sptr`) do not get GC-ed
+ * ```
+ *
+ * Here, without the #RB_GC_GUARD, the last use of `s` is _before_ the last use
+ * of `sptr`. Compilers could thus think `s` and `t` are allowed to overlap.
+ * That would eliminate `s` from the stack, while `sptr` is still in use. If
+ * our GC ran at that very moment, `s` gets swept out, which also destroys
+ * `sptr`. Boom! You got a SEGV.
+ *
+ * In order to prevent this scenario #RB_GC_GUARD must be placed _after_ the
+ * last use of `sptr`. Placing #RB_GC_GUARD before dereferencing `sptr` would
+ * be of no use.
+ *
+ * #RB_GC_GUARD would not be necessary at all in the above example if non-
+ * inlined function calls are made on the `s` variable after `sptr` is
+ * dereferenced. Thus, in the above example, calling any un-inlined function
+ * on `s` such as `rb_str_modify(s);` will ensure `s` stays on the stack or
+ * register to prevent a GC invocation from prematurely freeing it.
+ *
+ * Using the #RB_GC_GUARD macro is preferable to using the `volatile` keyword
+ * in C. #RB_GC_GUARD has the following advantages:
+ *
+ * - the intent of the macro use is clear.
+ *
+ * - #RB_GC_GUARD only affects its call site. OTOH `volatile` generates some
+ * extra code every time the variable is used, hurting optimisation.
+ *
+ * - `volatile` implementations may be buggy/inconsistent in some compilers
+ * and architectures. #RB_GC_GUARD is customisable for broken
+ * systems/compilers without negatively affecting other systems.
+ *
+ * - C++ since C++20 deprecates `volatile`. If you write your extension
+ * library in that language there is no escape but to use this macro.
+ *
+ * @param v A variable of ::VALUE type.
+ * @post `v` is still alive.
+ */
#ifdef __GNUC__
#define RB_GC_GUARD(v) \
(*__extension__ ({ \
@@ -101,65 +171,316 @@ extern void *alloca();
#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v)))
#endif
-/* Casts needed because void* is NOT compaible with others in C++. */
+/* Casts needed because void* is NOT compatible with others in C++. */
+
+/**
+ * Convenient macro that allocates an array of n elements.
+ *
+ * @param type Type of array elements.
+ * @param n Length of the array.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @exception rb_eArgError Integer overflow trying to calculate the length
+ * of continuous memory region of `n` elements of
+ * `type`.
+ * @return Storage instance that is capable of storing at least `n`
+ * elements of type `type`.
+ * @note It doesn't return NULL, even when `n` is zero.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
#define RB_ALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xmalloc2((n), sizeof(type)))
+
+/**
+ * Shorthand of #RB_ALLOC_N with `n=1`.
+ *
+ * @param type Type of allocation.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @return Storage instance that can hold an `type` object.
+ * @note It doesn't return NULL.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
#define RB_ALLOC(type) RBIMPL_CAST((type *)ruby_xmalloc(sizeof(type)))
+
+/**
+ * Identical to #RB_ALLOC_N() but also nullifies the allocated region before
+ * returning.
+ *
+ * @param type Type of array elements.
+ * @param n Length of the array.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @exception rb_eArgError Integer overflow trying to calculate the length
+ * of continuous memory region of `n` elements of
+ * `type`.
+ * @return Storage instance that is capable of storing at least `n`
+ * elements of type `type`.
+ * @post Returned array is filled with zeros.
+ * @note It doesn't return NULL, even when `n` is zero.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
#define RB_ZALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xcalloc((n), sizeof(type)))
+
+/**
+ * Shorthand of #RB_ZALLOC_N with `n=1`.
+ *
+ * @param type Type of allocation.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @return Storage instance that can hold an `type` object.
+ * @post Returned object is filled with zeros.
+ * @note It doesn't return NULL.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
#define RB_ZALLOC(type) (RB_ZALLOC_N(type, 1))
+
+/**
+ * Convenient macro that reallocates an array with a new size.
+ *
+ * @param var A variable of `type`, which points to a storage
+ * instance that was previously returned from
+ * either
+ * - ruby_xmalloc(),
+ * - ruby_xmalloc2(),
+ * - ruby_xcalloc(),
+ * - ruby_xrealloc(), or
+ * - ruby_xrealloc2().
+ * @param type Type of allocation.
+ * @param n Requested new size of each element.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @exception rb_eArgError Integer overflow trying to calculate the length
+ * of continuous memory region of `n` elements of
+ * `type`.
+ * @return Storage instance that is capable of storing at least `n`
+ * elements of type `type`.
+ * @pre The passed variable must point to a valid live storage instance.
+ * It is a failure to pass a variable that holds an already-freed
+ * pointer.
+ * @note It doesn't return NULL, even when `n` is zero.
+ * @warning Do not assume anything on the alignment of the return value.
+ * There is no guarantee that it inherits the passed argument's
+ * one.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
#define RB_REALLOC_N(var,type,n) \
((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type))))
+/**
+ * @deprecated This macro is dangerous (does not bother stack overflow at
+ * all). #RB_ALLOCV is the modern way to do the same thing.
+ * @param type Type of array elements.
+ * @param n Length of the array.
+ * @return A pointer on stack.
+ */
#define ALLOCA_N(type,n) \
RBIMPL_CAST((type *)alloca(rbimpl_size_mul_or_raise(sizeof(type), (n))))
-/* allocates _n_ bytes temporary buffer and stores VALUE including it
- * in _v_. _n_ may be evaluated twice. */
+/**
+ * Identical to #RB_ALLOCV_N(), except that it allocates a number of bytes and
+ * returns a void* .
+ *
+ * @param v A variable to hold the just-in-case opaque Ruby object.
+ * @param n Size of allocation, in bytes.
+ * @return A void pointer to `n` bytes storage.
+ * @note `n` may be evaluated twice.
+ */
#define RB_ALLOCV(v, n) \
((n) < RUBY_ALLOCV_LIMIT ? \
((v) = 0, alloca(n)) : \
rb_alloc_tmp_buffer(&(v), (n)))
+
+/**
+ * Allocates a memory region, possibly on stack. If the given size exceeds
+ * #RUBY_ALLOCV_LIMIT, it allocates a dedicated opaque ruby object instead and
+ * let our GC sweep that region after use. Either way you can fire-and-forget.
+ *
+ * ```CXX
+ * #include <sys/types.h>
+ *
+ * VALUE
+ * foo(int n)
+ * {
+ * VALUE v;
+ * auto ptr = RB_ALLOCV(struct tms, v, n);
+ * ...
+ * // no need to free `ptr`.
+ * }
+ * ```
+ *
+ * If you want to be super-duper polite you can also explicitly state the end
+ * of use of such memory region by calling #RB_ALLOCV_END().
+ *
+ * @param type The type of array elements.
+ * @param v A variable to hold the just-in-case opaque Ruby object.
+ * @param n Number of elements requested to allocate.
+ * @return An array of `n` elements of `type`.
+ * @note `n` may be evaluated twice.
+ */
#define RB_ALLOCV_N(type, v, n) \
RBIMPL_CAST((type *) \
(((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \
((v) = 0, alloca((n) * sizeof(type))) : \
rb_alloc_tmp_buffer2(&(v), (n), sizeof(type))))
+
+/**
+ * Polite way to declare that the given array is not used any longer. Calling
+ * this not mandatory. Our GC can baby-sit you. However it is not a very bad
+ * idea to use it when possible. Doing so could reduce memory footprint.
+ *
+ * @param v A variable previously passed to either #RB_ALLOCV/#RB_ALLOCV_N.
+ */
#define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v))
+/**
+ * Handy macro to erase a region of memory.
+ *
+ * @param p Target pointer.
+ * @param type Type of `p[0]`
+ * @param n Length of `p`.
+ * @return `p`.
+ * @post First `n` elements of `p` are squashed.
+ */
#define MEMZERO(p,type,n) memset((p), 0, rbimpl_size_mul_or_raise(sizeof(type), (n)))
-#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
+
+/**
+ * Handy macro to call memcpy.
+ *
+ * @param p1 Destination pointer.
+ * @param p2 Source pointer.
+ * @param type Type of `p2[0]`
+ * @param n Length of `p2`.
+ * @return `p1`.
+ * @post First `n` elements of `p2` are copied into `p1`.
+ */
+#define MEMCPY(p1,p2,type,n) ruby_nonempty_memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
+
+/**
+ * Handy macro to call memmove.
+ *
+ * @param p1 Destination pointer.
+ * @param p2 Source pointer.
+ * @param type Type of `p2[0]`
+ * @param n Length of `p2`.
+ * @return `p1`.
+ * @post First `n` elements of `p2` are copied into `p1`.
+ */
#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
+
+/**
+ * Handy macro to call memcmp
+ *
+ * @param p1 Target LHS.
+ * @param p2 Target RHS.
+ * @param type Type of `p1[0]`
+ * @param n Length of `p1`.
+ * @retval <0 `p1` is "less" than `p2`.
+ * @retval 0 `p1` is equal to `p2`.
+ * @retval >0 `p1` is "greater" than `p2`.
+ */
#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
-#define ALLOC_N RB_ALLOC_N
-#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
+#define ALLOC_N RB_ALLOC_N /**< @old{RB_ALLOC_N} */
+#define ALLOC RB_ALLOC /**< @old{RB_ALLOC} */
+#define ZALLOC_N RB_ZALLOC_N /**< @old{RB_ZALLOC_N} */
+#define ZALLOC RB_ZALLOC /**< @old{RB_ZALLOC} */
+#define REALLOC_N RB_REALLOC_N /**< @old{RB_REALLOC_N} */
+#define ALLOCV RB_ALLOCV /**< @old{RB_ALLOCV} */
+#define ALLOCV_N RB_ALLOCV_N /**< @old{RB_ALLOCV_N} */
+#define ALLOCV_END RB_ALLOCV_END /**< @old{RB_ALLOCV_END} */
-/* Expecting this struct to be eliminated by function inlinings */
+/**
+ * @private
+ *
+ * This is an implementation detail of rbimpl_size_mul_overflow().
+ *
+ * @internal
+ *
+ * Expecting this struct to be eliminated by function inlinings. This is
+ * nothing more than std::variant<std::size_t> if we could use recent C++, but
+ * reality is we cannot.
+ */
struct rbimpl_size_mul_overflow_tag {
- bool left;
- size_t right;
+ bool left; /**< Whether overflow happened or not. */
+ size_t right; /**< Multiplication result. */
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_RESTRICT()
RBIMPL_ATTR_RETURNS_NONNULL()
RBIMPL_ATTR_ALLOC_SIZE((2))
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ALLOCV(). People don't use this
+ * directly.
+ *
+ * @param[out] store Pointer to a variable.
+ * @param[in] len Requested number of bytes to allocate.
+ * @return Allocated `len` bytes array.
+ * @post `store` holds the corresponding tmp buffer object.
+ */
void *rb_alloc_tmp_buffer(volatile VALUE *store, long len);
RBIMPL_ATTR_RESTRICT()
RBIMPL_ATTR_RETURNS_NONNULL()
RBIMPL_ATTR_ALLOC_SIZE((2,3))
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ALLOCV_N(). People don't use this
+ * directly.
+ *
+ * @param[out] store Pointer to a variable.
+ * @param[in] len Requested number of bytes to allocate.
+ * @param[in] count Number of elements in an array.
+ * @return Allocated `len` bytes array.
+ * @post `store` holds the corresponding tmp buffer object.
+ *
+ * @internal
+ *
+ * Although the meaning of `count` variable is clear, @shyouhei doesn't
+ * understand its needs.
+ */
void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count);
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ALLOCV_END(). People don't use this
+ * directly.
+ *
+ * @param[out] store Pointer to a variable.
+ * @pre `store` is a NULL, or a pointer to a tmp buffer object.
+ * @post `*store` is ::RUBY_Qfalse.
+ * @post The object formerly stored in `store` is destroyed.
+ */
void rb_free_tmp_buffer(volatile VALUE *store);
RBIMPL_ATTR_NORETURN()
-void ruby_malloc_size_overflow(size_t, size_t);
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ALLOCV_N(). People don't use this
+ * directly.
+ *
+ * @param[in] x Arbitrary value.
+ * @param[in] y Arbitrary value.
+ * @exception rb_eArgError `x` * `y` would integer overflow.
+ */
+void ruby_malloc_size_overflow(size_t x, size_t y);
#ifdef HAVE_RB_GC_GUARDED_PTR_VAL
volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val);
@@ -169,6 +490,15 @@ RBIMPL_SYMBOL_EXPORT_END()
#ifdef _MSC_VER
# pragma optimize("", off)
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_GC_GUARD(). People don't use this
+ * directly.
+ *
+ * @param[in] ptr A pointer to an on-stack C variable.
+ * @return `ptr` as-is.
+ */
static inline volatile VALUE *
rb_gc_guarded_ptr(volatile VALUE *ptr)
{
@@ -178,7 +508,19 @@ rb_gc_guarded_ptr(volatile VALUE *ptr)
# pragma optimize("", on)
#endif
-/* Does anyone use it? Just here for backwards compatibility. */
+/**
+ * @deprecated This function was an implementation detail of old
+ * #RB_ALLOCV_N(). We no longer use it. @shyouhei suspects that
+ * there are no actual usage now. However it was not marked as
+ * private before. We cannot delete it any longer.
+ * @param[in] a Arbitrary value.
+ * @param[in] b Arbitrary value.
+ * @param[in] max Possible maximum value.
+ * @param[out] c A pointer to return the computation result.
+ * @retval 1 `c` is insane.
+ * @retval 0 `c` is sane.
+ * @post `c` holds `a` * `b`, but could be overflowed.
+ */
static inline int
rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c)
{
@@ -196,12 +538,30 @@ rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c)
return 0;
}
-#if RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
+#if defined(__DOXYGEN__)
+RBIMPL_ATTR_CONSTEXPR(CXX14)
+#elif RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */
#elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0)
RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */
#endif
RBIMPL_ATTR_CONST()
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ALLOCV_N(). People don't use this
+ * directly.
+ *
+ * @param[in] x Arbitrary value.
+ * @param[in] y Arbitrary value.
+ * @return `{ left, right }`, where `left` is whether there is an integer
+ * overflow or not, and `right` is a (possibly overflowed) result
+ * of `x` * `y`.
+ *
+ * @internal
+ *
+ * This is in fact also an implementation detail of ruby_xmalloc2() etc.
+ */
static inline struct rbimpl_size_mul_overflow_tag
rbimpl_size_mul_overflow(size_t x, size_t y)
{
@@ -232,6 +592,21 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
return ret;
}
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_ALLOCV_N(). People don't use this
+ * directly.
+ *
+ * @param[in] x Arbitrary value.
+ * @param[in] y Arbitrary value.
+ * @exception rb_eArgError Multiplication could integer overflow.
+ * @return `x` * `y`.
+ *
+ * @internal
+ *
+ * This is in fact also an implementation detail of ruby_xmalloc2() etc.
+ */
static inline size_t
rbimpl_size_mul_or_raise(size_t x, size_t y)
{
@@ -247,6 +622,20 @@ rbimpl_size_mul_or_raise(size_t x, size_t y)
}
}
+/**
+ * This is an implementation detail of #RB_ALLOCV_N(). People don't use this
+ * directly.
+ *
+ * @param[out] store Pointer to a variable.
+ * @param[in] count Number of elements in an array.
+ * @param[in] elsize Size of each elements.
+ * @return Region of `count` * `elsize` bytes.
+ * @post `store` holds the corresponding tmp buffer object.
+ *
+ * @internal
+ *
+ * We might want to deprecate this function and make a `rbimpl_` counterpart.
+ */
static inline void *
rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
{
@@ -255,7 +644,6 @@ rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
return rb_alloc_tmp_buffer_with_count(store, total_size, cnt);
}
-#ifndef __MINGW32__
RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
@@ -274,8 +662,5 @@ ruby_nonempty_memcpy(void *dest, const void *src, size_t n)
}
}
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
index 67600e8732..19feb0c10b 100644
--- a/include/ruby/internal/method.h
+++ b/include/ruby/internal/method.h
@@ -17,22 +17,188 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Creation and modification of Ruby methods.
*/
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/backward/2/stdarg.h"
+/**
+ * @defgroup defmethod Defining methods
+ *
+ * There are some APIs to define a method from C.
+ * These API takes a C function as a method body.
+ *
+ * ### Method body functions
+ *
+ * Method body functions must return a VALUE and
+ * can be one of the following form:
+ *
+ * #### Fixed number of parameters
+ *
+ * This form is a normal C function, excepting it takes
+ * a receiver object as the first argument.
+ *
+ * ```CXX
+ * static VALUE my_method(VALUE self, VALUE x, VALUE y);
+ * ```
+ *
+ * #### argc and argv style
+ *
+ * This form takes three parameters: argc, argv and self.
+ * self is the receiver. argc is the number of arguments.
+ * argv is a pointer to an array of the arguments.
+ *
+ * ```CXX
+ * static VALUE my_method(int argc, VALUE *argv, VALUE self);
+ * ```
+ *
+ * #### Ruby array style
+ *
+ * This form takes two parameters: self and args.
+ * self is the receiver. args is an Array object which
+ * contains the arguments.
+ *
+ * ```CXX
+ * static VALUE my_method(VALUE self, VALUE args);
+ * ```
+ *
+ * ### Number of parameters
+ *
+ * Method defining APIs takes the number of parameters which the
+ * method will takes. This number is called argc.
+ * argc can be:
+ *
+ * - Zero or positive number.
+ * This means the method body function takes a fixed number of parameters.
+ *
+ * - `-1`.
+ * This means the method body function is "argc and argv" style.
+ *
+ * - `-2`.
+ * This means the method body function is "self and args" style.
+ *
+ * @{
+ */
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
-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);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a method.
+ *
+ * @param[out] klass A module or a class.
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_method
+ */
+void rb_define_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a module function for a module.
+ *
+ * @param[out] klass A module or a class.
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_module_function
+ */
+void rb_define_module_function(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a global function.
+ *
+ * @param[in] mid Name of the function.
+ * @param[in] func The method body.
+ * @param[in] arity The number of parameters. See @ref defmethod.
+ * @note There are in fact 18 different prototypes for func.
+ * @see ::ruby::backward::cxxanyargs::define_method::rb_define_global_function
+ */
+void rb_define_global_function(const char *mid, VALUE (*func)(ANYARGS), int arity);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines an undef of a method. -- What?
+ *
+ * In ruby, there are two separate concepts called "undef" and "remove_method".
+ * The thing you imagine when you "un-define" a method is remove_method. This
+ * one on the other hand is masking of a previous method definition. Suppose
+ * for instance:
+ *
+ * ```ruby
+ * class Foo
+ * def foo
+ * end
+ * end
+ *
+ * class Bar < Foo
+ * def bar
+ * foo
+ * end
+ * end
+ *
+ * class Baz < Foo
+ * undef foo # <--- (*1)
+ * end
+ * ```
+ *
+ * This `undef foo` at `(*1)` must not eliminate `Foo#foo`, because that method
+ * is also used from `Bar#bar`. So instead of physically executing the target
+ * method, `undef` inserts a special filtering entry to the class (`Baz` this
+ * case). That entry, when called, acts as if there were no methods at all.
+ * But the original can still be accessible, via ways like `Bar#bar` above.
+ *
+ * @param[out] klass The class to insert an undef.
+ * @param[in] name Name of the undef.
+ * @exception rb_eTypeError `klass` is a non-module.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @see rb_remove_method
+ */
+void rb_undef_method(VALUE klass, const char *name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines an alias of a method.
+ *
+ * @param[in,out] klass The class which the original method belongs
+ * to; this is also where the new method will
+ * belong to.
+ * @param[in] dst A new name for the method.
+ * @param[in] src The original name of the method.
+ * @exception rb_eTypeError `klass` is a non-module.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @exception rb_eNameError There is no such method named as `src` in
+ * `klass`.
+ *
+ * @internal
+ *
+ * Above description is in fact a bit inaccurate because it ignores
+ * Refinements.
+ */
+void rb_define_alias(VALUE klass, const char *dst, const char *src);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines public accessor method(s) for an attribute.
+ *
+ * @param[out] klass The class which the attribute will belong to.
+ * @param[in] name Name of the attribute.
+ * @param[in] read Whether to define a getter method.
+ * @param[in] write Whether to define a setter method.
+ * @exception rb_eTypeError `klass` is a non-module.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @exception rb_eNameError `name` invalid as an attr e.g. an operator.
+ */
+void rb_define_attr(VALUE klass, const char *name, int read, int write);
-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()
diff --git a/include/ruby/internal/module.h b/include/ruby/internal/module.h
index 1dc6b820cc..d678dd2102 100644
--- a/include/ruby/internal/module.h
+++ b/include/ruby/internal/module.h
@@ -17,26 +17,160 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Creation and modification of Ruby modules.
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
+/**
+ * @defgroup class Classes and their hierarchy.
+ *
+ * @par Terminology
+ * - class: same as in Ruby.
+ * - singleton class: class for a particular object.
+ * - eigenclass: = singleton class
+ * - metaclass: class of a class. Metaclass is a kind of singleton class.
+ * - metametaclass: class of a metaclass.
+ * - meta^(n)-class: class of a meta^(n-1)-class.
+ * - attached object: A singleton class knows its unique instance.
+ * The instance is called the attached object for the singleton class.
+ * @{
+ */
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a top-level class.
+ *
+ * @param[in] name Name of the class.
+ * @param[in] super A class from which the new class will derive.
+ * @exception rb_eTypeError The constant name `name` is already taken but the
+ * constant is not a class.
+ * @exception rb_eTypeError The class is already defined but the class can
+ * not be reopened because its superclass is not
+ * `super`.
+ * @exception rb_eArgError `super` is NULL.
+ * @return The created class.
+ * @post Top-level constant named `name` refers the returned class.
+ * @note If a class named `name` is already defined and its superclass is
+ * `super`, the function just returns the defined class.
+ * @note The compaction GC does not move classes returned by this
+ * function.
+ *
+ * @internal
+ *
+ * There are classes without names, but you can't pass NULL here. You have to
+ * use other ways to create one.
+ */
+VALUE rb_define_class(const char *name, VALUE super);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a top-level module.
+ *
+ * @param[in] name Name of the module.
+ * @exception rb_eTypeError The constant name `name` is already taken but the
+ * constant is not a module.
+ * @return The created module.
+ * @post Top-level constant named `name` refers the returned module.
+ * @note The compaction GC does not move classes returned by this
+ * function.
+ *
+ * @internal
+ *
+ * There are modules without names, but you can't pass NULL here. You have to
+ * use other ways to create one.
+ */
+VALUE rb_define_module(const char *name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a class under the namespace of `outer`.
+ *
+ * @param[out] outer A class which contains the new class.
+ * @param[in] name Name of the new class
+ * @param[in] super A class from which the new class will derive.
+ * 0 means ::rb_cObject.
+ * @exception rb_eTypeError The constant name `name` is already taken but
+ * the constant is not a class.
+ * @exception rb_eTypeError The class is already defined but the class can
+ * not be reopened because its superclass is not
+ * `super`.
+ * @exception rb_eArgError `super` is NULL.
+ * @return The created class.
+ * @post `outer::name` refers the returned class.
+ * @note If a class named `name` is already defined and its superclass
+ * is `super`, the function just returns the defined class.
+ * @note The compaction GC does not move classes returned by this
+ * function.
+ */
+VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a module under the namespace of `outer`.
+ *
+ * @param[out] outer A class which contains the new module.
+ * @param[in] name Name of the new module
+ * @exception rb_eTypeError The constant name `name` is already taken but
+ * the constant is not a class.
+ * @return The created module.
+ * @post `outer::name` refers the returned module.
+ * @note The compaction GC does not move classes returned by this
+ * function.
+ */
+VALUE rb_define_module_under(VALUE outer, const char *name);
+
+/**
+ * Includes a module to a class.
+ *
+ * @param[out] klass Inclusion destination.
+ * @param[in] module Inclusion source.
+ * @exception rb_eArgError Cyclic inclusion.
+ *
+ * @internal
+ *
+ * :FIXME: @shyouhei suspects this function lacks assertion that the arguments
+ * being modules... Could silently SEGV if non-module was passed?
+ */
+void rb_include_module(VALUE klass, VALUE module);
+
+/**
+ * Extend the object with the module.
+ *
+ * @warning This is the same as `Module#extend_object`, not
+ * `Object#extend`! These two methods are very similar, but not
+ * identical. The difference is the hook. `Module#extend_object`
+ * does not invoke `Module#extended`, while `Object#extend` does.
+ * @param[out] obj Object to extend.
+ * @param[in] mod Module of extension.
+ */
+void rb_extend_object(VALUE obj, VALUE mod);
+
/**
- * GC compaction note: class and modules returned by these four functions
- * do not move.
+ * Identical to rb_include_module(), except it "prepends" the passed module to
+ * the klass, instead of includes. This affects how `super` resolves. For
+ * instance:
+ *
+ * ```ruby
+ * class Q; def foo; "<q/>" end end
+ * module W; def foo; "<w>#{super}</w>" end end
+ * class E < Q; include W; def foo; "<e>#{super}</e>" end end
+ * class R < Q; prepend W; def foo; "<r>#{super}</r>" end end
+ *
+ * E.new.foo # => "<e><w><q/></w></e>"
+ * r.new.foo # => "<W><r><q/></r></w>"
+ * ```
+ *
+ * @param[out] klass Target class to modify.
+ * @param[in] module Module to prepend.
+ * @exception rb_eArgError Cyclic inclusion.
*/
-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_prepend_module(VALUE klass, VALUE module);
-void rb_include_module(VALUE,VALUE);
-void rb_extend_object(VALUE,VALUE);
-void rb_prepend_module(VALUE,VALUE);
+/** @} */
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h
index 1bb4f0efa3..a8a5557a25 100644
--- a/include/ruby/internal/newobj.h
+++ b/include/ruby/internal/newobj.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #NEWOBJ.
*/
#include "ruby/internal/attr/deprecated.h"
@@ -29,26 +29,146 @@
#include "ruby/internal/value.h"
#include "ruby/assert.h"
+/**
+ * Declares, allocates, then assigns a new object to the given variable.
+ *
+ * @param obj Variable name.
+ * @param type Variable type.
+ * @exception rb_eNoMemError No space left.
+ * @return An allocated object, not initialised.
+ * @note Modern programs tend to use #NEWOBJ_OF instead.
+ *
+ * @internal
+ *
+ * :FIXME: Should we deprecate it?
+ */
#define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj())
+
+/**
+ * Identical to #RB_NEWOBJ, except it also accepts the allocating object's
+ * class and flags.
+ *
+ * @param obj Variable name.
+ * @param type Variable type.
+ * @param klass Object's class.
+ * @param flags Object's flags.
+ * @exception rb_eNoMemError No space left.
+ * @return An allocated object, filled with the arguments.
+ */
#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags))
-#define NEWOBJ RB_NEWOBJ
-#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
+#define NEWOBJ RB_NEWOBJ /**< @old{RB_NEWOBJ} */
+#define NEWOBJ_OF RB_NEWOBJ_OF /**< @old{RB_NEWOBJ_OF} */
+#define OBJSETUP rb_obj_setup /**< @old{rb_obj_setup} */
+#define CLONESETUP rb_clone_setup /**< @old{rb_clone_setup} */
+#define DUPSETUP rb_dup_setup /**< @old{rb_dup_setup} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * This is the implementation detail of #RB_NEWOBJ.
+ *
+ * @exception rb_eNoMemError No space left.
+ * @return An allocated object, not initialised.
+ */
VALUE rb_newobj(void);
-VALUE rb_newobj_of(VALUE, VALUE);
+
+/**
+ * This is the implementation detail of #RB_NEWOBJ_OF.
+ *
+ * @param klass Object's class.
+ * @param flags Object's flags.
+ * @exception rb_eNoMemError No space left.
+ * @return An allocated object, filled with the arguments.
+ */
+VALUE rb_newobj_of(VALUE klass, VALUE flags);
+
+/**
+ * Fills common fields in the object.
+ *
+ * @note Prefer rb_newobj_of() to this function.
+ * @param[in,out] obj A Ruby object to be set up.
+ * @param[in] klass `obj` will belong to this class.
+ * @param[in] type One of ::ruby_value_type.
+ * @return The passed object.
+ *
+ * @internal
+ *
+ * Historically, authors of Ruby has described the `type` argument as "one of
+ * ::ruby_value_type". In reality it accepts either ::ruby_value_type,
+ * ::ruby_fl_type, or any combinations of the two. For instance
+ * `RUBY_T_STRING | RUBY_FL_FREEZE` is a valid value that this function takes,
+ * and means this is a frozen string.
+ *
+ * 3rd party extension libraries rarely need to allocate Strings this way.
+ * They normally only concern ::RUBY_T_DATA. This argument is mainly used for
+ * specifying flags, @shyouhei suspects.
+ */
VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
-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);
+
+/**
+ * Queries the class of an object. This is not always identical to
+ * `RBASIC_CLASS(obj)`. It searches for the nearest ancestor skipping
+ * singleton classes or included modules.
+ *
+ * @param[in] obj Object in question.
+ * @return The object's class, in a normal sense.
+ */
+VALUE rb_obj_class(VALUE obj);
+
+/**
+ * Clones a singleton class. An object can have its own singleton class. OK.
+ * Then what happens when a program clones such object? The singleton class
+ * that is attached to the source object must also be cloned. Otherwise a
+ * singleton object gets shared with two objects, which breaks "singleton"-ness
+ * of such class.
+ *
+ * This is basically an implementation detail of rb_clone_setup(). People
+ * need not be aware of this working behind-the-scene.
+ *
+ * @param[in] obj The object that has its own singleton class.
+ * @return Cloned singleton class.
+ */
+VALUE rb_singleton_class_clone(VALUE obj);
+
+/**
+ * Attaches a singleton class to its corresponding object.
+ *
+ * This is basically an implementation detail of rb_clone_setup(). People
+ * need not be aware of this working behind-the-scene.
+ *
+ * @param[in] klass The singleton class.
+ * @param[out] obj The object to attach a class.
+ * @pre The passed two objects must agree with each other that `klass`
+ * becomes a singleton class of `obj`.
+ * @post `klass` becomes the singleton class of `obj`.
+ */
+void rb_singleton_class_attached(VALUE klass, VALUE obj);
+
+/**
+ * Copies the list of instance variables. 3rd parties need not know, but there
+ * are several ways to store an object's instance variables, depending on its
+ * internal structure. This function makes sense when either of the passed
+ * objects are using so-called "generic" backend storage. This distinction is
+ * purely an implementation detail of rb_clone_setup(). People need not be
+ * aware of this working behind-the-scenes.
+ *
+ * @param[out] clone The destination object.
+ * @param[in] obj The source object.
+ */
+void rb_copy_generic_ivar(VALUE clone, VALUE obj);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#clone works."))
+/**
+ * @deprecated Not sure exactly when but at some time, the implementation of
+ * `Object#clone` stopped using this function. It remained
+ * untouched for a while, and then @shyouhei realised that they
+ * are no longer doing the same thing. It seems nobody seriously
+ * uses this function any longer. Let's just abandon it.
+ *
+ * @param[out] clone The destination object.
+ * @param[in] obj The source object.
+ */
static inline void
rb_clone_setup(VALUE clone, VALUE obj)
{
@@ -56,6 +176,16 @@ rb_clone_setup(VALUE clone, VALUE obj)
}
RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#dup works."))
+/**
+ * @deprecated Not sure exactly when but at some time, the implementation of
+ * `Object#dup` stopped using this function. It remained
+ * untouched for a while, and then @shyouhei realised that they
+ * are no longer the same thing. It seems nobody seriously uses
+ * this function any longer. Let's just abandon it.
+ *
+ * @param[out] dup The destination object.
+ * @param[in] obj The source object.
+ */
static inline void
rb_dup_setup(VALUE dup, VALUE obj)
{
diff --git a/include/ruby/internal/rgengc.h b/include/ruby/internal/rgengc.h
index 2681d41844..7ea04442f6 100644
--- a/include/ruby/internal/rgengc.h
+++ b/include/ruby/internal/rgengc.h
@@ -17,111 +17,255 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
+ * 115-121, 2019. https://doi.org/10.1145/3315573.3329986
*/
#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/maybe_unused.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/special_consts.h"
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value.h"
#include "ruby/assert.h"
-#include "ruby/backward/2/attributes.h"
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#undef USE_RGENGC
#define USE_RGENGC 1
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable incremental GC feature. It
+ * has to be set at the time ruby itself compiles. Makes no sense for 3rd
+ * parties. It is safe for them to set this though; that just doesn't change
+ * anything.
+ */
#ifndef USE_RINCGC
# define USE_RINCGC 1
#endif
+/**
+ * @deprecated This macro seems broken. Setting this to anything other than
+ * zero just doesn't compile. We need to KonMari.
+ */
#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT
# define USE_RGENGC_LOGGING_WB_UNPROTECT 0
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RArray. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_ARRAY
# define RGENGC_WB_PROTECTED_ARRAY 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RHash. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_HASH
# define RGENGC_WB_PROTECTED_HASH 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RStruct. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_STRUCT
# define RGENGC_WB_PROTECTED_STRUCT 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RString. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_STRING
# define RGENGC_WB_PROTECTED_STRING 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RObject. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_OBJECT
# define RGENGC_WB_PROTECTED_OBJECT 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RRegexp. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_REGEXP
# define RGENGC_WB_PROTECTED_REGEXP 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RClass. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_CLASS
# define RGENGC_WB_PROTECTED_CLASS 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RFloat. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_FLOAT
# define RGENGC_WB_PROTECTED_FLOAT 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RComplex. It has to be set at the time ruby itself compiles.
+ * Makes no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_COMPLEX
# define RGENGC_WB_PROTECTED_COMPLEX 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RRational. It has to be set at the time ruby itself compiles.
+ * Makes no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_RATIONAL
# define RGENGC_WB_PROTECTED_RATIONAL 1
#endif
+/**
+ * @private
+ *
+ * This is a compile-time flag to enable/disable write barrier for
+ * struct ::RBignum. It has to be set at the time ruby itself compiles. Makes
+ * no sense for 3rd parties.
+ */
#ifndef RGENGC_WB_PROTECTED_BIGNUM
# define RGENGC_WB_PROTECTED_BIGNUM 1
#endif
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't think anybody uses this right now.
+ */
#ifndef RGENGC_WB_PROTECTED_NODE_CREF
# define RGENGC_WB_PROTECTED_NODE_CREF 1
#endif
/**
- * @name Write barrier (WB) interfaces:
- * @{
+ * @defgroup rgengc Write barrier (WB) interfaces:
*
* @note The following core interfaces can be changed in the future. Please
* catch up if you want to insert WB into C-extensions correctly.
+ *
+ * @{
*/
/**
- * WB for new reference from `a' to `b'. Write `b' into `*slot'. `slot' is a
- * pointer in `a'.
+ * Declaration of a "back" pointer. This is a write barrier for new reference
+ * from "old" generation to "young" generation. It writes `young` into
+ * `*slot`, which is a pointer inside of `old`.
+ *
+ * @param[in] old An old object.
+ * @param[in] slot A pointer inside of `old`.
+ * @param[out] young A young object.
*/
-#define RB_OBJ_WRITE(a, slot, b) \
- RBIMPL_CAST(rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__))
+#define RB_OBJ_WRITE(old, slot, young) \
+ RBIMPL_CAST(rb_obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young), __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).
+ * Identical to #RB_OBJ_WRITE(), except it doesn't write any values, but only a
+ * WB declaration. `oldv` is replaced value with `b` (not used in current
+ * Ruby).
+ *
+ * @param[in] old An old object.
+ * @param[in] oldv An object previously stored inside of `old`.
+ * @param[out] young A young object.
*/
-#define RB_OBJ_WRITTEN(a, oldv, b) \
- RBIMPL_CAST(rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__))
+#define RB_OBJ_WRITTEN(old, oldv, young) \
+ RBIMPL_CAST(rb_obj_written((VALUE)(old), (VALUE)(oldv), (VALUE)(young), __FILE__, __LINE__))
/** @} */
-#define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW
-#define OBJ_PROMOTED RB_OBJ_PROMOTED
-#define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT
+#define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW /**< @old{RB_OBJ_PROMOTED_RAW} */
+#define OBJ_PROMOTED RB_OBJ_PROMOTED /**< @old{RB_OBJ_PROMOTED} */
+#define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT /**< @old{RB_OBJ_WB_UNPROTECT} */
+/**
+ * Asserts that the passed object is not fenced by write barriers. Objects of
+ * such property do not contribute to generational GCs. They are scanned
+ * always.
+ *
+ * @param[out] x An object that would not be protected by the barrier.
+ */
#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__)
+
+/**
+ * Identical to #RB_OBJ_WB_UNPROTECT(), except it can also assert that the
+ * given object is of given type.
+ *
+ * @param[in] type One of `ARRAY`, `STRING`, etc.
+ * @param[out] obj An object of `type` that would not be protected.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't understand why this has to be visible from extensions.
+ */
#define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \
(RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj)
+
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_obj_wb_unprotect(). People don't use
+ * it directly.
+ */
#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging
/** @cond INTERNAL_MACRO */
@@ -130,15 +274,51 @@
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-void rb_gc_writebarrier(VALUE a, VALUE b);
+/**
+ * This is the implementation of #RB_OBJ_WRITE(). People don't use it
+ * directly.
+ *
+ * @param[in] old An object that points to `young`.
+ * @param[out] young An object that is referenced from `old`.
+ */
+void rb_gc_writebarrier(VALUE old, VALUE young);
+
+/**
+ * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it
+ * directly.
+ *
+ * @param[out] obj An object that does not participate in WB.
+ */
void rb_gc_writebarrier_unprotect(VALUE obj);
+
#if USE_RGENGC_LOGGING_WB_UNPROTECT
+/**
+ * @private
+ *
+ * This is the implementation of #RGENGC_LOGGING_WB_UNPROTECT(). People
+ * don't use it directly.
+ *
+ * @param[in] objptr Don't know why this is a pointer to void but in
+ * reality this is a pointer to an object that is about
+ * to be un-protected.
+ * @param[in] filename Pass C's `__FILE__` here.
+ * @param[in] line Pass C's `__LINE__` here.
+ */
void rb_gc_unprotect_logging(void *objptr, const char *filename, int line);
#endif
+
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * This is the implementation of #RB_OBJ_PROMOTED(). People don't use it
+ * directly.
+ *
+ * @param[in] obj An object to query.
+ * @retval true The object is "promoted".
+ * @retval false The object is young. Have not experienced GC at all.
+ */
static inline bool
RB_OBJ_PROMOTED_RAW(VALUE obj)
{
@@ -148,6 +328,17 @@ RB_OBJ_PROMOTED_RAW(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Tests if the object is "promoted" -- that is, whether the object experienced
+ * one or more GC marks.
+ *
+ * @param[in] obj An object to query.
+ * @retval true The object is "promoted".
+ * @retval false The object is young. Have not experienced GC at all.
+ * @note Hello, is anyone actively calling this function? @shyouhei have
+ * never seen any actual usages outside of the GC implementation
+ * itself.
+ */
static inline bool
RB_OBJ_PROMOTED(VALUE obj)
{
@@ -159,8 +350,22 @@ RB_OBJ_PROMOTED(VALUE obj)
}
}
+/**
+ * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it
+ * directly.
+ *
+ * @param[out] x An object that does not participate in WB.
+ * @param[in] filename C's `__FILE__` of the caller function.
+ * @param[in] line C's `__LINE__` of the caller function.
+ * @return x
+ */
static inline VALUE
-rb_obj_wb_unprotect(VALUE x, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
+rb_obj_wb_unprotect(
+ VALUE x,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ const char *filename,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ int line)
{
#if USE_RGENGC_LOGGING_WB_UNPROTECT
RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line);
@@ -169,8 +374,29 @@ rb_obj_wb_unprotect(VALUE x, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(
return x;
}
+/**
+ * @private
+ *
+ * This is the implementation of #RB_OBJ_WRITTEN(). People don't use it
+ * directly.
+ *
+ * @param[in] a An old object.
+ * @param[in] oldv An object previously stored inside of `old`.
+ * @param[out] b A young object.
+ * @param[in] filename C's `__FILE__` of the caller function.
+ * @param[in] line C's `__LINE__` of the caller function.
+ * @return a
+ */
static inline VALUE
-rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
+rb_obj_written(
+ VALUE a,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ VALUE oldv,
+ VALUE b,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ const char *filename,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ int line)
{
#if USE_RGENGC_LOGGING_WB_UNPROTECT
RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line);
@@ -183,8 +409,26 @@ rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const
return a;
}
+/**
+ * @private
+ *
+ * This is the implementation of #RB_OBJ_WRITE(). People don't use it
+ * directly.
+ *
+ * @param[in] a An old object.
+ * @param[in] slot A pointer inside of `old`.
+ * @param[out] b A young object.
+ * @param[in] filename C's `__FILE__` of the caller function.
+ * @param[in] line C's `__LINE__` of the caller function.
+ * @return a
+ */
static inline VALUE
-rb_obj_write(VALUE a, VALUE *slot, VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
+rb_obj_write(
+ VALUE a, VALUE *slot, VALUE b,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ const char *filename,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ int line)
{
#ifdef RGENGC_LOGGING_WRITE
RGENGC_LOGGING_WRITE(a, slot, b, filename, line);
diff --git a/include/ruby/internal/scan_args.h b/include/ruby/internal/scan_args.h
index d9329e7e98..1ed2bf6368 100644
--- a/include/ruby/internal/scan_args.h
+++ b/include/ruby/internal/scan_args.h
@@ -17,15 +17,17 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Compile-time static implementation of ::rb_scan_args().
*
* This is a beast. It statically analyses the argument spec string, and
* expands the assignment of variables into dedicated codes.
*/
+#include "ruby/assert.h"
#include "ruby/internal/attr/diagnose_if.h"
#include "ruby/internal/attr/error.h"
#include "ruby/internal/attr/forceinline.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/config.h"
#include "ruby/internal/dllexport.h"
@@ -38,29 +40,155 @@
#include "ruby/internal/static_assert.h"
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value.h"
-#include "ruby/assert.h"
+/**
+ * @name Possible values that you should pass to rb_scan_args_kw().
+ * @{
+ */
+
+/** Same behaviour as rb_scan_args(). */
#define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0
+
+/** The final argument should be a hash treated as keywords.*/
#define RB_SCAN_ARGS_KEYWORDS 1
+
+/**
+ * Treat a final argument as keywords if it is a hash, and not as keywords
+ * otherwise.
+ */
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3
+
+/** @} */
+
+/**
+ * @name Possible values that you should pass to rb_funcallv_kw().
+ * @{
+ */
+
+/** Do not pass keywords. */
#define RB_NO_KEYWORDS 0
+
+/** Pass keywords, final argument should be a hash of keywords. */
#define RB_PASS_KEYWORDS 1
+
+/**
+ * Pass keywords if current method is called with keywords, useful for argument
+ * delegation
+ */
#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p()
-/* rb_scan_args() format allows ':' for optional hash */
+
+/** @} */
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1
RBIMPL_SYMBOL_EXPORT_BEGIN()
-int rb_scan_args(int, const VALUE*, const char*, ...);
-int rb_scan_args_kw(int, int, const VALUE*, const char*, ...);
+RBIMPL_ATTR_NONNULL((2, 3))
+/**
+ * Retrieves argument from argc and argv to given ::VALUE references according
+ * to the format string. The format can be described in ABNF as follows:
+ *
+ * ```
+ * scan-arg-spec := param-arg-spec [keyword-arg-spec] [block-arg-spec]
+ *
+ * param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec /
+ * pre-opt-post-arg-spec
+ * pre-arg-spec := num-of-leading-mandatory-args
+ * [num-of-optional-args]
+ * post-arg-spec := sym-for-variable-length-args
+ * [num-of-trailing-mandatory-args]
+ * pre-opt-post-arg-spec := num-of-leading-mandatory-args num-of-optional-args
+ * num-of-trailing-mandatory-args
+ * keyword-arg-spec := sym-for-keyword-arg
+ * block-arg-spec := sym-for-block-arg
+ *
+ * num-of-leading-mandatory-args := DIGIT ; The number of leading mandatory
+ * ; arguments
+ * num-of-optional-args := DIGIT ; The number of optional arguments
+ * sym-for-variable-length-args := "*" ; Indicates that variable length
+ * ; arguments are captured as a ruby
+ * ; array
+ * num-of-trailing-mandatory-args := DIGIT ; The number of trailing mandatory
+ * ; arguments
+ * sym-for-keyword-arg := ":" ; Indicates that keyword argument
+ * ; captured as a hash.
+ * ; If keyword arguments are not
+ * ; provided, returns nil.
+ * sym-for-block-arg := "&" ; Indicates that an iterator block
+ * ; should be captured if given
+ * ```
+ *
+ * For example, "12" means that the method requires at least one argument, and
+ * at most receives three (1+2) arguments. So, the format string must be
+ * followed by three variable references, which are to be assigned to captured
+ * arguments. For omitted arguments, variables are set to ::RUBY_Qnil. `NULL`
+ * can be put in place of a variable reference, which means the corresponding
+ * captured argument(s) should be just dropped.
+ *
+ * The number of given arguments, excluding an option hash or iterator block,
+ * is returned.
+ *
+ * @param[in] argc Length of `argv`.
+ * @param[in] argv Pointer to the arguments to parse.
+ * @param[in] fmt Format, in the language described above.
+ * @param[out] ... Variables to fill in.
+ * @exception rb_eFatal Malformed `fmt`.
+ * @exception rb_eArgError Arity mismatch.
+ * @return Actually parsed number of given arguments.
+ * @post Each values passed to `argv` is filled into the variadic
+ * arguments, according to the format.
+ */
+int rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((3, 4))
+/**
+ * Identical to rb_scan_args(), except it also accepts `kw_splat`.
+ *
+ * @param[in] kw_splat How to understand the keyword arguments.
+ * - RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: Same behaviour as rb_scan_args().
+ * - RB_SCAN_ARGS_KEYWORDS: The final argument is a kwarg.
+ * - RB_SCAN_ARGS_LAST_HASH_KEYWORDS: The final argument is a kwarg, iff it
+ * is a hash.
+ * @param[in] argc Length of `argv`.
+ * @param[in] argv Pointer to the arguments to parse.
+ * @param[in] fmt Format, in the language described above.
+ * @param[out] ... Variables to fill in.
+ * @exception rb_eFatal Malformed `fmt`.
+ * @exception rb_eArgError Arity mismatch.
+ * @return Actually parsed number of given arguments.
+ * @post Each values passed to `argv` is filled into the variadic
+ * arguments, according to the format.
+ */
+int rb_scan_args_kw(int kw_splat, int argc, const VALUE *argv, const char *fmt, ...);
RBIMPL_ATTR_ERROR(("bad scan arg format"))
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_scan_args(). People don't use it
+ * directly.
+ */
void rb_scan_args_bad_format(const char*);
RBIMPL_ATTR_ERROR(("variable argument length doesn't match"))
+/**
+ * @private
+ *
+ * This is an implementation detail of rb_scan_args(). People don't use it
+ * directly.
+ */
void rb_scan_args_length_mismatch(const char*,int);
RBIMPL_SYMBOL_EXPORT_END()
+/** @cond INTERNAL_MACRO */
+
/* If we could use constexpr the following macros could be inline functions
* ... but sadly we cannot. */
@@ -106,13 +234,13 @@ RBIMPL_SYMBOL_EXPORT_END()
# 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.
+# * static assertions. The reality is no, they don't. Because fmt is a
+# * string literal, any operations against fmt cannot produce the "integer
+# * constant expression"s, as defined in ISO/IEC 9899:2018 section 6.6
+# * paragraph #6. Static assertions need such integer constant expressions as
+# * defined in ISO/IEC 9899:2018 section 6.7.10 paragraph #3.
# *
-# * GCC nonetheless constant-folds this into no-op, though. */
+# * GCC nonetheless constant-folds this into a no-op, though. */
# define rb_scan_args_verify(fmt, varc) \
(sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \
rb_scan_args_bad_format(fmt) : \
@@ -349,7 +477,12 @@ rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
#undef rb_scan_args_next_param
}
-#if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
+/** @endcond */
+
+#if defined(__DOXYGEN__)
+# /* don't bother */
+
+#elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
# /* skip */
#elif ! defined(HAVE_VA_ARGS_MACRO)
diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h
index f36a230af2..dc0a6b41d6 100644
--- a/include/ruby/internal/special_consts.h
+++ b/include/ruby/internal/special_consts.h
@@ -17,9 +17,9 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines enum ::ruby_special_consts.
- * @see Sasada, K., "A Lighweight Representation of Floting-Point
+ * @see Sasada, K., "A Lightweight Representation of Floating-Point
* Numbers on Ruby Interpreter", in proceedings of 10th JSSST
* SIGPPL Workshop on Programming and Programming Languages
* (PPL2008), pp. 9-16, 2008.
@@ -31,6 +31,14 @@
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value.h"
+/**
+ * @private
+ * @warning Do not touch this macro.
+ * @warning It is an implementation detail.
+ * @warning The value of this macro must match for ruby itself and all
+ * extension libraries, otherwise serious memory corruption shall
+ * occur.
+ */
#if defined(USE_FLONUM)
# /* Take that. */
#elif SIZEOF_VALUE >= SIZEOF_DOUBLE
@@ -39,27 +47,28 @@
# define USE_FLONUM 0
#endif
+/** This is an old name of #RB_TEST. Not sure which name is preferred. */
#define RTEST RB_TEST
-#define FIXNUM_P RB_FIXNUM_P
-#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 FIXNUM_P RB_FIXNUM_P /**< @old{RB_FIXNUM_P} */
+#define IMMEDIATE_P RB_IMMEDIATE_P /**< @old{RB_IMMEDIATE_P} */
+#define NIL_P RB_NIL_P /**< @old{RB_NIL_P} */
+#define SPECIAL_CONST_P RB_SPECIAL_CONST_P /**< @old{RB_SPECIAL_CONST_P} */
+#define STATIC_SYM_P RB_STATIC_SYM_P /**< @old{RB_STATIC_SYM_P} */
-#define Qfalse RUBY_Qfalse
-#define Qnil RUBY_Qnil
-#define Qtrue RUBY_Qtrue
-#define Qundef RUBY_Qundef
+#define Qfalse RUBY_Qfalse /**< @old{RUBY_Qfalse} */
+#define Qnil RUBY_Qnil /**< @old{RUBY_Qnil} */
+#define Qtrue RUBY_Qtrue /**< @old{RUBY_Qtrue} */
+#define Qundef RUBY_Qundef /**< @old{RUBY_Qundef} */
-/** @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 FIXNUM_FLAG RUBY_FIXNUM_FLAG /**< @old{RUBY_FIXNUM_FLAG} */
+#define FLONUM_FLAG RUBY_FLONUM_FLAG /**< @old{RUBY_FLONUM_FLAG} */
+#define FLONUM_MASK RUBY_FLONUM_MASK /**< @old{RUBY_FLONUM_MASK} */
+#define FLONUM_P RB_FLONUM_P /**< @old{RB_FLONUM_P} */
+#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK /**< @old{RUBY_IMMEDIATE_MASK} */
+#define SYMBOL_FLAG RUBY_SYMBOL_FLAG /**< @old{RUBY_SYMBOL_FLAG} */
+/** @cond INTERNAL_MACRO */
#define RB_FIXNUM_P RB_FIXNUM_P
#define RB_FLONUM_P RB_FLONUM_P
#define RB_IMMEDIATE_P RB_IMMEDIATE_P
@@ -67,17 +76,29 @@
#define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P
#define RB_STATIC_SYM_P RB_STATIC_SYM_P
#define RB_TEST RB_TEST
+#define RB_UNDEF_P RB_UNDEF_P
+#define RB_NIL_OR_UNDEF_P RB_NIL_OR_UNDEF_P
/** @endcond */
/** special constants - i.e. non-zero and non-fixnum constants */
enum
RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed)
ruby_special_consts {
-#if USE_FLONUM
+#if defined(__DOXYGEN__)
+ RUBY_Qfalse, /**< @see ::rb_cFalseClass */
+ RUBY_Qtrue, /**< @see ::rb_cTrueClass */
+ RUBY_Qnil, /**< @see ::rb_cNilClass */
+ RUBY_Qundef, /**< Represents so-called undef. */
+ RUBY_IMMEDIATE_MASK, /**< Bit mask detecting special consts. */
+ RUBY_FIXNUM_FLAG, /**< Flag to denote a fixnum. */
+ RUBY_FLONUM_MASK, /**< Bit mask detecting a flonum. */
+ RUBY_FLONUM_FLAG, /**< Flag to denote a flonum. */
+ RUBY_SYMBOL_FLAG, /**< Flag to denote a static symbol. */
+#elif USE_FLONUM
RUBY_Qfalse = 0x00, /* ...0000 0000 */
+ RUBY_Qnil = 0x04, /* ...0000 0100 */
RUBY_Qtrue = 0x14, /* ...0001 0100 */
- RUBY_Qnil = 0x08, /* ...0000 1000 */
- RUBY_Qundef = 0x34, /* ...0011 0100 */
+ RUBY_Qundef = 0x24, /* ...0010 0100 */
RUBY_IMMEDIATE_MASK = 0x07, /* ...0000 0111 */
RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */
RUBY_FLONUM_MASK = 0x03, /* ...0000 0011 */
@@ -85,36 +106,53 @@ ruby_special_consts {
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_Qnil = 0x02, /* ...0000 0010 */
+ RUBY_Qtrue = 0x06, /* ...0000 0110 */
+ RUBY_Qundef = 0x0a, /* ...0000 1010 */
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 */
+ RUBY_SYMBOL_FLAG = 0x0e, /* ...xxxx 1110 */
#endif
- RUBY_SPECIAL_SHIFT = 8 /** Least significant 8 bits are reserved. */
+ 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()`.
+/**
+ * Emulates Ruby's "if" statement.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval false `obj` is either ::RUBY_Qfalse or ::RUBY_Qnil.
+ * @retval true Anything else.
+ *
+ * @internal
+ *
+ * It HAS to be `__attribute__((const))` in order for clang to properly deduce
+ * `__builtin_assume()`.
*/
static inline bool
RB_TEST(VALUE obj)
{
/*
+ * if USE_FLONUM
+ * Qfalse: ....0000 0000
+ * Qnil: ....0000 0100
+ * ~Qnil: ....1111 1011
+ * v ....xxxx xxxx
+ * ----------------------------
+ * RTEST(v) ....xxxx x0xx
+ *
+ * if ! USE_FLONUM
* Qfalse: ....0000 0000
- * Qnil: ....0000 1000
- * ~Qnil: ....1111 0111
+ * Qnil: ....0000 0010
+ * ~Qnil: ....1111 1101
* v ....xxxx xxxx
* ----------------------------
- * RTEST(v) ....xxxx 0xxx
+ * RTEST(v) ....xxxx xx0x
*
* RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil).
*/
@@ -124,6 +162,13 @@ RB_TEST(VALUE obj)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is nil.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is ::RUBY_Qnil.
+ * @retval false Anything else.
+ */
static inline bool
RB_NIL_P(VALUE obj)
{
@@ -133,6 +178,71 @@ RB_NIL_P(VALUE obj)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is undef.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is ::RUBY_Qundef.
+ * @retval false Anything else.
+ */
+static inline bool
+RB_UNDEF_P(VALUE obj)
+{
+ return obj == RUBY_Qundef;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX14)
+RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is nil or undef. Can be used to see if
+ * a keyword argument is not given or given `nil`.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is ::RUBY_Qnil or ::RUBY_Qundef.
+ * @retval false Anything else.
+ */
+static inline bool
+RB_NIL_OR_UNDEF_P(VALUE obj)
+{
+ /*
+ * if USE_FLONUM
+ * Qundef: ....0010 0100
+ * Qnil: ....0000 0100
+ * mask: ....1101 1111
+ * common_bits: ....0000 0100
+ * ---------------------------------
+ * Qnil & mask ....0000 0100
+ * Qundef & mask ....0000 0100
+ *
+ * if ! USE_FLONUM
+ * Qundef: ....0000 1010
+ * Qnil: ....0000 0010
+ * mask: ....1111 0111
+ * common_bits: ....0000 0010
+ * ----------------------------
+ * Qnil & mask ....0000 0010
+ * Qundef & mask ....0000 0010
+ *
+ * NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil.
+ */
+ const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil);
+ const VALUE common_bits = RUBY_Qundef & RUBY_Qnil;
+ return (obj & mask) == common_bits;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is a so-called Fixnum.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is a Fixnum.
+ * @retval false Anything else.
+ * @note Fixnum was a thing in the 20th century, but it is rather an
+ * implementation detail today.
+ */
static inline bool
RB_FIXNUM_P(VALUE obj)
{
@@ -142,6 +252,17 @@ RB_FIXNUM_P(VALUE obj)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX14)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is a static symbol.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is a static symbol
+ * @retval false Anything else.
+ * @see RB_DYNAMIC_SYM_P()
+ * @see RB_SYMBOL_P()
+ * @note These days there are static and dynamic symbols, just like we
+ * once had Fixnum/Bignum back in the old days.
+ */
static inline bool
RB_STATIC_SYM_P(VALUE obj)
{
@@ -153,6 +274,16 @@ RB_STATIC_SYM_P(VALUE obj)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is a so-called Flonum.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is a Flonum.
+ * @retval false Anything else.
+ * @see RB_FLOAT_TYPE_P()
+ * @note These days there are Flonums and non-Flonum floats, just like we
+ * once had Fixnum/Bignum back in the old days.
+ */
static inline bool
RB_FLONUM_P(VALUE obj)
{
@@ -166,6 +297,16 @@ RB_FLONUM_P(VALUE obj)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is an immediate i.e. an object which has no
+ * corresponding storage inside of the object space.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is a Flonum.
+ * @retval false Anything else.
+ * @see RB_FLOAT_TYPE_P()
+ * @note The concept of "immediate" is purely C specific.
+ */
static inline bool
RB_IMMEDIATE_P(VALUE obj)
{
@@ -175,16 +316,33 @@ RB_IMMEDIATE_P(VALUE obj)
RBIMPL_ATTR_CONST()
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Checks if the given object is of enum ::ruby_special_consts.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval true `obj` is a special constant.
+ * @retval false Anything else.
+ */
static inline bool
RB_SPECIAL_CONST_P(VALUE obj)
{
- return RB_IMMEDIATE_P(obj) || ! RB_TEST(obj);
+ return RB_IMMEDIATE_P(obj) || obj == RUBY_Qfalse;
}
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? */
+/**
+ * Identical to RB_SPECIAL_CONST_P, except it returns a ::VALUE.
+ *
+ * @param[in] obj An arbitrary ruby object.
+ * @retval RUBY_Qtrue `obj` is a special constant.
+ * @retval RUBY_Qfalse Anything else.
+ *
+ * @internal
+ *
+ * This function is to mimic old rb_special_const_p macro but have anyone
+ * actually used its return value? Wasn't it just something no one needed?
+ */
static inline VALUE
rb_special_const_p(VALUE obj)
{
diff --git a/include/ruby/internal/static_assert.h b/include/ruby/internal/static_assert.h
index d4bdadf196..594c2b2917 100644
--- a/include/ruby/internal/static_assert.h
+++ b/include/ruby/internal/static_assert.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_STATIC_ASSERT.
*/
#include <assert.h>
diff --git a/include/ruby/internal/stdalign.h b/include/ruby/internal/stdalign.h
index 02eb7ab959..ec68f6a882 100644
--- a/include/ruby/internal/stdalign.h
+++ b/include/ruby/internal/stdalign.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #RBIMPL_ALIGNAS / #RBIMPL_ALIGNOF
*/
#include "ruby/internal/config.h"
@@ -83,7 +83,9 @@
* @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560
* @see https://bugs.llvm.org/show_bug.cgi?id=26547
*/
-#if defined(__cplusplus)
+#if defined(__DOXYGEN__)
+# define RBIMPL_ALIGNOF alignof
+#elif defined(__cplusplus)
# /* C++11 `alignof()` can be buggy. */
# /* see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 */
# /* But don't worry, we can use templates. */
@@ -117,7 +119,7 @@ struct rbimpl_alignof {
# * 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
+# * 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
diff --git a/include/ruby/internal/stdbool.h b/include/ruby/internal/stdbool.h
index 0cd5103a05..1ca61136ba 100644
--- a/include/ruby/internal/stdbool.h
+++ b/include/ruby/internal/stdbool.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief C99 shim for <stdbool.h>
*/
#include "ruby/internal/config.h"
@@ -39,7 +39,7 @@
# /* Take stdbool.h definition. */
# include <stdbool.h>
-#else
+#elif !defined(HAVE__BOOL)
typedef unsigned char _Bool;
# /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */
# define bool _Bool
diff --git a/include/ruby/internal/symbol.h b/include/ruby/internal/symbol.h
index 762f1e8f9b..869a31115c 100644
--- a/include/ruby/internal/symbol.h
+++ b/include/ruby/internal/symbol.h
@@ -17,12 +17,12 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines #rb_intern
*/
#include "ruby/internal/config.h"
-#ifdef HAVE_STDDEF_H
+#ifdef STDC_HEADERS
# include <stddef.h>
#endif
@@ -30,43 +30,248 @@
# include <string.h>
#endif
+#include "ruby/internal/attr/noalias.h"
#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
+#define RB_ID2SYM rb_id2sym /**< @alias{rb_id2sym} */
+#define RB_SYM2ID rb_sym2id /**< @alias{rb_sym2id} */
+#define ID2SYM RB_ID2SYM /**< @old{RB_ID2SYM} */
+#define SYM2ID RB_SYM2ID /**< @old{RB_SYM2ID} */
+#define CONST_ID_CACHE RUBY_CONST_ID_CACHE /**< @old{RUBY_CONST_ID_CACHE} */
+#define CONST_ID RUBY_CONST_ID /**< @old{RUBY_CONST_ID} */
/** @cond INTERNAL_MACRO */
#define rb_intern_const rb_intern_const
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-ID rb_sym2id(VALUE);
-VALUE rb_id2sym(ID);
-ID rb_intern(const char*);
-ID rb_intern2(const char*, long);
+
+/**
+ * Converts an instance of ::rb_cSymbol into an ::ID.
+ *
+ * @param[in] obj An instance of ::rb_cSymbol.
+ * @exception rb_eTypeError `obj` is not an instance of ::rb_cSymbol.
+ * @return An ::ID of the identical symbol.
+ */
+ID rb_sym2id(VALUE obj);
+
+/**
+ * Allocates an instance of ::rb_cSymbol that has the given id.
+ *
+ * @param[in] id An id.
+ * @retval RUBY_Qfalse No such id ever existed in the history.
+ * @retval Otherwise An allocated ::rb_cSymbol instance.
+ */
+VALUE rb_id2sym(ID id);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Finds or creates a symbol of the given name.
+ *
+ * @param[in] name The name of the id.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given name.
+ * @note These days Ruby internally has two kinds of symbols (static /
+ * dynamic). Symbols created using this function would become a
+ * static one; i.e. would never be garbage collected. It is up to
+ * you to avoid memory leaks. Think twice before using it.
+ */
+ID rb_intern(const char *name);
+
+/**
+ * Identical to rb_intern(), except it additionally takes the length of the
+ * string. This way you can have a symbol that contains NUL characters.
+ *
+ * @param[in] name The name of the id.
+ * @param[in] len Length of `name`.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given name.
+ * @note These days Ruby internally has two kinds of symbols
+ * (static/dynamic). Symbols created using this function would
+ * become static ones; i.e. would never be garbage collected. It
+ * is up to you to avoid memory leaks. Think twice before using
+ * it.
+ */
+ID rb_intern2(const char *name, long len);
+
+/**
+ * Identical to rb_intern(), except it takes an instance of ::rb_cString.
+ *
+ * @param[in] str The name of the id.
+ * @pre `str` must either be an instance of ::rb_cSymbol, or an instance
+ * of ::rb_cString, or responds to `#to_str` method.
+ * @exception rb_eTypeError Can't convert `str` into ::rb_cString.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given str.
+ * @note These days Ruby internally has two kinds of symbols
+ * (static/dynamic). Symbols created using this function would
+ * become static ones; i.e. would never be garbage collected. It
+ * is up to you to avoid memory leaks. Think twice before using
+ * it.
+ */
ID rb_intern_str(VALUE str);
-const char *rb_id2name(ID);
-ID rb_check_id(volatile VALUE *);
-ID rb_to_id(VALUE);
-VALUE rb_id2str(ID);
-VALUE rb_sym2str(VALUE);
+
+/**
+ * Retrieves the name mapped to the given id.
+ *
+ * @param[in] id An id to query.
+ * @retval NULL No such id ever existed in the history.
+ * @retval otherwise A name that the id represents.
+ * @note The return value is managed by the interpreter. Don't pass it
+ * to free().
+ */
+const char *rb_id2name(ID id);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Detects if the given name is already interned or not. It first tries to
+ * convert the argument to an instance of ::rb_cString if it is neither an
+ * instance of ::rb_cString nor ::rb_cSymbol. The conversion result is written
+ * back to the variable. Then queries if that name was already interned
+ * before. If found it returns such id, otherwise zero.
+ *
+ * We eventually introduced this API to avoid inadvertent symbol pin-down.
+ * Before, there was no way to know if an ID was already interned or not
+ * without actually creating one (== leaking memory). By using this API you
+ * can avoid such situations:
+ *
+ * ```CXX
+ * bool does_interning_this_leak_memory(VALUE obj)
+ * {
+ * auto tmp = obj;
+ * if (auto id = rb_check_id(&tmp); id) {
+ * return false;
+ * }
+ * else {
+ * return true; // Let GC sweep tmp if necessary.
+ * }
+ * }
+ * ```
+ *
+ * @param[in,out] namep A pointer to a name to query.
+ * @pre The object referred by `*namep` must either be an instance
+ * of ::rb_cSymbol, or an instance of ::rb_cString, or responds
+ * to `#to_str` method.
+ * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString.
+ * @exception rb_eEncodingError Given string is non-ASCII.
+ * @retval 0 No such id ever existed in the history.
+ * @retval otherwise The id that represents the given name.
+ * @post The object that `*namep` points to is a converted result
+ * object, which is always an instance of either ::rb_cSymbol
+ * or ::rb_cString.
+ * @see https://bugs.ruby-lang.org/issues/5072
+ *
+ * @internal
+ *
+ * @shyouhei doesn't know why this has to raise rb_eEncodingError.
+ */
+ID rb_check_id(volatile VALUE *namep);
+
+/**
+ * @copydoc rb_intern_str()
+ *
+ * @internal
+ *
+ * :FIXME: Can anyone tell us what is the difference between this one and
+ * rb_intern_str()? As far as @shyouhei reads the implementation it seems what
+ * rb_to_id() does is is just waste some CPU time, then call rb_intern_str().
+ * He hopes he is wrong.
+ */
+ID rb_to_id(VALUE str);
+
+/**
+ * Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
+ *
+ * @param[in] id An id to query.
+ * @retval RUBY_Qfalse No such id ever existed in the history.
+ * @retval otherwise An instance of ::rb_cString with the name of id.
+ *
+ * @internal
+ *
+ * In reality "rb_id2str() is identical to rb_id2name() except it returns Ruby
+ * string" is just describing things upside down; truth is `rb_id2name(foo)` is
+ * a shorthand of `RSTRING_PTR(rb_id2str(foo))`.
+ */
+VALUE rb_id2str(ID id);
+
+/**
+ * Identical to rb_id2str(), except it takes an instance of ::rb_cSymbol rather
+ * than an ::ID.
+ *
+ * @param[in] id An id to query.
+ * @retval RUBY_Qfalse No such id ever existed in the history.
+ * @retval otherwise An instance of ::rb_cString with the name of id.
+ */
+VALUE rb_sym2str(VALUE id);
+
+/**
+ * Identical to rb_intern_str(), except it generates a dynamic symbol if
+ * necessary.
+ *
+ * @param[in] name The name of the id.
+ * @pre `name` must either be an instance of ::rb_cSymbol, or an
+ * instance of ::rb_cString, or responds to `#to_str` method.
+ * @exception rb_eTypeError Can't convert `name` into ::rb_cString.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given name.
+ * @note These days Ruby internally has two kinds of symbols
+ * (static/dynamic). Symbols created using this function would
+ * become dynamic ones; i.e. would be garbage collected. It could
+ * be safer for you to use it than alternatives, when applicable.
+ */
VALUE rb_to_symbol(VALUE name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_check_id(), except it returns an instance of ::rb_cSymbol
+ * instead.
+ *
+ * @param[in,out] namep A pointer to a name to query.
+ * @pre The object referred by `*namep` must either be an instance
+ * of ::rb_cSymbol, or an instance of ::rb_cString, or responds
+ * to `#to_str` method.
+ * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString.
+ * @exception rb_eEncodingError Given string is non-ASCII.
+ * @retval RUBY_Qnil No such id ever existed in the history.
+ * @retval otherwise The id that represents the given name.
+ * @post The object that `*namep` points to is a converted result
+ * object, which is always an instance of either ::rb_cSymbol
+ * or ::rb_cString.
+ * @see https://bugs.ruby-lang.org/issues/5072
+ *
+ * @internal
+ *
+ * @shyouhei doesn't know why this has to raise rb_eEncodingError.
+ */
VALUE rb_check_symbol(volatile VALUE *namep);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE()
RBIMPL_ATTR_NONNULL(())
+/**
+ * This is a "tiny optimisation" over rb_intern(). If you pass a string
+ * _literal_, and if your C compiler can special-case strlen of such literal to
+ * strength-reduce into an integer constant expression, then this inline
+ * function can precalc a part of conversion.
+ *
+ * @note This function also works happily for non-constant strings. Why
+ * bother then? Just apply liberally to everything.
+ * @note But #rb_intern() could be faster on compilers with statement
+ * expressions, because they can cache the created ::ID.
+ * @param[in] str The name of the id.
+ * @exception rb_eRuntimeError Too many symbols.
+ * @return A (possibly new) id whose value is the given str.
+ * @note These days Ruby internally has two kinds of symbols (static /
+ * dynamic). Symbols created using this function would become a
+ * static one; i.e. would never be garbage collected. It is up to
+ * you to avoid memory leaks. Think twice before using it.
+ */
static inline ID
rb_intern_const(const char *str)
{
@@ -76,6 +281,11 @@ rb_intern_const(const char *str)
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * This is an implementation detail of #rb_intern(). Just don't use it.
+ */
static inline ID
rbimpl_intern_const(ID *ptr, const char *str)
{
@@ -86,13 +296,21 @@ rbimpl_intern_const(ID *ptr, const char *str)
return *ptr;
}
-/* Does anyone use it? Preserved for backward compat. */
+/**
+ * Old implementation detail of rb_intern().
+ * @deprecated Does anyone use it? Preserved for backward compat.
+ */
#define RUBY_CONST_ID_CACHE(result, str) \
{ \
static ID rb_intern_id_cache; \
rbimpl_intern_const(&rb_intern_id_cache, (str)); \
result rb_intern_id_cache; \
}
+
+/**
+ * Old implementation detail of rb_intern().
+ * @deprecated Does anyone use it? Preserved for backward compat.
+ */
#define RUBY_CONST_ID(var, str) \
do { \
static ID rbimpl_id; \
diff --git a/include/ruby/internal/value.h b/include/ruby/internal/value.h
index b87fe140af..805cd83513 100644
--- a/include/ruby/internal/value.h
+++ b/include/ruby/internal/value.h
@@ -17,14 +17,79 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * 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
+#if defined(__DOXYGEN__)
+
+/**
+ * Type that represents a Ruby object. It is an unsigned integer of some kind,
+ * depending on platforms.
+ *
+ * ```CXX
+ * VALUE value = rb_eval_string("ARGF.readlines.map.with_index");
+ * ```
+ *
+ * @warning ::VALUE is not a pointer.
+ * @warning ::VALUE can be wider than `long`.
+ */
+typedef uintptr_t VALUE;
+
+/**
+ * Type that represents a Ruby identifier such as a variable name.
+ *
+ * ```CXX
+ * ID method = rb_intern("method");
+ * VALUE result = rb_funcall(obj, method, 0);
+ * ```
+ *
+ * @note ::rb_cSymbol is a Ruby-level data type for the same thing.
+ */
+typedef uintptr_t ID;
+
+/**
+ * A signed integer type that has the same width with ::VALUE.
+ *
+ * @internal
+ *
+ * @shyouhei wonders: is it guaranteed that `uintptr_t` and `intptr_t` are the
+ * same width? As far as I read ISO/IEC 9899:2018 section 7.20.1.4 paragraph 1
+ * no such description is given... or defined elsewhere?
+ */
+typedef intptr_t SIGNED_VALUE;
+
+/**
+ * Identical to `sizeof(VALUE)`, except it is a macro that can also be used
+ * inside of preprocessor directives such as `#if`. Handy on occasions.
+ */
+#define SIZEOF_VALUE SIZEOF_UINTPTR_T
+
+/**
+ * @private
+ *
+ * A compile-time constant of type ::VALUE whose value is 0.
+ */
+#define RBIMPL_VALUE_NULL UINTPTR_C(0)
+
+/**
+ * @private
+ *
+ * A compile-time constant of type ::VALUE whose value is 1.
+ */
+#define RBIMPL_VALUE_ONE UINTPTR_C(1)
+
+/**
+ * @private
+ *
+ * Maximum possible value that a ::VALUE can take.
+ */
+#define RBIMPL_VALUE_FULL UINTPTR_MAX
+
+#elif defined HAVE_UINTPTR_T && 0
typedef uintptr_t VALUE;
typedef uintptr_t ID;
# define SIGNED_VALUE intptr_t
@@ -59,8 +124,10 @@ typedef unsigned LONG_LONG ID;
# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
#endif
+/** @cond INTERNAL_MACRO */
RBIMPL_STATIC_ASSERT(sizeof_int, SIZEOF_INT == sizeof(int));
RBIMPL_STATIC_ASSERT(sizeof_long, SIZEOF_LONG == sizeof(long));
RBIMPL_STATIC_ASSERT(sizeof_long_long, SIZEOF_LONG_LONG == sizeof(LONG_LONG));
RBIMPL_STATIC_ASSERT(sizeof_voidp, SIZEOF_VOIDP == sizeof(void *));
+/** @endcond */
#endif /* RBIMPL_VALUE_H */
diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h
index 5642686c7b..977f60a009 100644
--- a/include/ruby/internal/value_type.h
+++ b/include/ruby/internal/value_type.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Defines enum ::ruby_value_type.
*/
#include "ruby/internal/assume.h"
@@ -53,41 +53,40 @@
# 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 T_PAYLOAD RUBY_T_PAYLOAD
+#define T_ARRAY RUBY_T_ARRAY /**< @old{RUBY_T_ARRAY} */
+#define T_BIGNUM RUBY_T_BIGNUM /**< @old{RUBY_T_BIGNUM} */
+#define T_CLASS RUBY_T_CLASS /**< @old{RUBY_T_CLASS} */
+#define T_COMPLEX RUBY_T_COMPLEX /**< @old{RUBY_T_COMPLEX} */
+#define T_DATA RUBY_T_DATA /**< @old{RUBY_T_DATA} */
+#define T_FALSE RUBY_T_FALSE /**< @old{RUBY_T_FALSE} */
+#define T_FILE RUBY_T_FILE /**< @old{RUBY_T_FILE} */
+#define T_FIXNUM RUBY_T_FIXNUM /**< @old{RUBY_T_FIXNUM} */
+#define T_FLOAT RUBY_T_FLOAT /**< @old{RUBY_T_FLOAT} */
+#define T_HASH RUBY_T_HASH /**< @old{RUBY_T_HASH} */
+#define T_ICLASS RUBY_T_ICLASS /**< @old{RUBY_T_ICLASS} */
+#define T_IMEMO RUBY_T_IMEMO /**< @old{RUBY_T_IMEMO} */
+#define T_MASK RUBY_T_MASK /**< @old{RUBY_T_MASK} */
+#define T_MATCH RUBY_T_MATCH /**< @old{RUBY_T_MATCH} */
+#define T_MODULE RUBY_T_MODULE /**< @old{RUBY_T_MODULE} */
+#define T_MOVED RUBY_T_MOVED /**< @old{RUBY_T_MOVED} */
+#define T_NIL RUBY_T_NIL /**< @old{RUBY_T_NIL} */
+#define T_NODE RUBY_T_NODE /**< @old{RUBY_T_NODE} */
+#define T_NONE RUBY_T_NONE /**< @old{RUBY_T_NONE} */
+#define T_OBJECT RUBY_T_OBJECT /**< @old{RUBY_T_OBJECT} */
+#define T_RATIONAL RUBY_T_RATIONAL /**< @old{RUBY_T_RATIONAL} */
+#define T_REGEXP RUBY_T_REGEXP /**< @old{RUBY_T_REGEXP} */
+#define T_STRING RUBY_T_STRING /**< @old{RUBY_T_STRING} */
+#define T_STRUCT RUBY_T_STRUCT /**< @old{RUBY_T_STRUCT} */
+#define T_SYMBOL RUBY_T_SYMBOL /**< @old{RUBY_T_SYMBOL} */
+#define T_TRUE RUBY_T_TRUE /**< @old{RUBY_T_TRUE} */
+#define T_UNDEF RUBY_T_UNDEF /**< @old{RUBY_T_UNDEF} */
+#define T_ZOMBIE RUBY_T_ZOMBIE /**< @old{RUBY_T_ZOMBIE} */
-#define BUILTIN_TYPE RB_BUILTIN_TYPE
-#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
+#define BUILTIN_TYPE RB_BUILTIN_TYPE /**< @old{RB_BUILTIN_TYPE} */
+#define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P /**< @old{RB_DYNAMIC_SYM_P} */
+#define RB_INTEGER_TYPE_P rb_integer_type_p /**< @old{rb_integer_type_p} */
+#define SYMBOL_P RB_SYMBOL_P /**< @old{RB_SYMBOL_P} */
+#define rb_type_p RB_TYPE_P /**< @alias{RB_TYPE_P} */
/** @cond INTERNAL_MACRO */
#define RB_BUILTIN_TYPE RB_BUILTIN_TYPE
@@ -104,6 +103,7 @@
#endif
/** @endcond */
+/** @old{rb_type} */
#define TYPE(_) RBIMPL_CAST((int)rb_type(_))
/** C-level type of an object. */
@@ -134,7 +134,6 @@ ruby_value_type {
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_PAYLOAD = 0x17, /**< @see ::RPayload */
RUBY_T_IMEMO = 0x1a, /**< @see struct ::RIMemo */
RUBY_T_NODE = 0x1b, /**< @see struct ::RNode */
@@ -142,16 +141,42 @@ ruby_value_type {
RUBY_T_ZOMBIE = 0x1d, /**< @see struct ::RZombie */
RUBY_T_MOVED = 0x1e, /**< @see struct ::RMoved */
- RUBY_T_MASK = 0x1f
+ RUBY_T_MASK = 0x1f /**< Bitmask of ::ruby_value_type. */
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_COLD()
+/**
+ * @private
+ *
+ * This was the old implementation of Check_Type(), but they diverged. This
+ * one remains for theoretical backwards compatibility. People normally need
+ * not use it.
+ *
+ * @param[in] obj An object.
+ * @param[in] t A type.
+ * @exception rb_eTypeError `obj` is not of type `t`.
+ * @exception rb_eFatal `obj` is corrupt.
+ * @post Upon successful return `obj` is guaranteed to have type `t`.
+ *
+ * @internal
+ *
+ * The second argument shall have been enum ::ruby_value_type. But at the time
+ * matz designed this function he still used K&R C. There was no such thing
+ * like a function prototype. We can no longer change this API.
+ */
void rb_check_type(VALUE obj, int t);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries the type of the object.
+ *
+ * @param[in] obj Object in question.
+ * @pre `obj` must not be a special constant.
+ * @return The type of `obj`.
+ */
static inline enum ruby_value_type
RB_BUILTIN_TYPE(VALUE obj)
{
@@ -167,6 +192,13 @@ RB_BUILTIN_TYPE(VALUE obj)
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/**
+ * Queries if the object is an instance of ::rb_cInteger.
+ *
+ * @param[in] obj Object in question.
+ * @retval true It is.
+ * @retval false It isn't.
+ */
static inline bool
rb_integer_type_p(VALUE obj)
{
@@ -182,6 +214,12 @@ rb_integer_type_p(VALUE obj)
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/**
+ * Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
+ *
+ * @param[in] obj Object in question.
+ * @return The type of `obj`.
+ */
static inline enum ruby_value_type
rb_type(VALUE obj)
{
@@ -214,6 +252,13 @@ rb_type(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries if the object is an instance of ::rb_cFloat.
+ *
+ * @param[in] obj Object in question.
+ * @retval true It is.
+ * @retval false It isn't.
+ */
static inline bool
RB_FLOAT_TYPE_P(VALUE obj)
{
@@ -230,6 +275,13 @@ RB_FLOAT_TYPE_P(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries if the object is a dynamic symbol.
+ *
+ * @param[in] obj Object in question.
+ * @retval true It is.
+ * @retval false It isn't.
+ */
static inline bool
RB_DYNAMIC_SYM_P(VALUE obj)
{
@@ -243,6 +295,13 @@ RB_DYNAMIC_SYM_P(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries if the object is an instance of ::rb_cSymbol.
+ *
+ * @param[in] obj Object in question.
+ * @retval true It is.
+ * @retval false It isn't.
+ */
static inline bool
RB_SYMBOL_P(VALUE obj)
{
@@ -252,6 +311,16 @@ RB_SYMBOL_P(VALUE obj)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_FORCEINLINE()
+/**
+ * @private
+ *
+ * This is an implementation detail of RB_TYPE_P(). Just don't use it.
+ *
+ * @param[in] obj An object.
+ * @param[in] t A type.
+ * @retval true `obj` is of type `t`.
+ * @retval false Otherwise.
+ */
static bool
rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
{
@@ -289,6 +358,19 @@ rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Queries if the given object is of given type.
+ *
+ * @param[in] obj An object.
+ * @param[in] t A type.
+ * @retval true `obj` is of type `t`.
+ * @retval false Otherwise.
+ *
+ * @internal
+ *
+ * This function is a super-duper hot path. Optimised targeting modern C
+ * compilers and x86_64 architecture.
+ */
static inline bool
RB_TYPE_P(VALUE obj, enum ruby_value_type t)
{
@@ -329,10 +411,23 @@ RB_TYPE_P(VALUE obj, enum ruby_value_type t)
RBIMPL_ATTR_PURE()
RBIMPL_ATTR_ARTIFICIAL()
-/* Defined in ruby/internal/core/rtypeddata.h */
+/**
+ * @private
+ * Defined in ruby/internal/core/rtypeddata.h
+ */
static inline bool rbimpl_rtypeddata_p(VALUE obj);
RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * Identical to RB_TYPE_P(), except it raises exceptions on predication
+ * failure.
+ *
+ * @param[in] v An object.
+ * @param[in] t A type.
+ * @exception rb_eTypeError `obj` is not of type `t`.
+ * @exception rb_eFatal `obj` is corrupt.
+ * @post Upon successful return `obj` is guaranteed to have type `t`.
+ */
static inline void
Check_Type(VALUE v, enum ruby_value_type t)
{
diff --git a/include/ruby/internal/variable.h b/include/ruby/internal/variable.h
index b0cfa61a62..c017ffe3f7 100644
--- a/include/ruby/internal/variable.h
+++ b/include/ruby/internal/variable.h
@@ -17,45 +17,320 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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.
+ * extension libraries. They could be written in C++98.
+ * @brief Declares rb_define_variable().
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
+#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/noreturn.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * Type that represents a global variable getter function.
+ *
+ * @param[in] id The variable name.
+ * @param[in,out] data Where the value is stored.
+ * @return The value that shall be visible from Ruby.
+ */
typedef VALUE rb_gvar_getter_t(ID id, VALUE *data);
+
+/**
+ * Type that represents a global variable setter function.
+ *
+ * @param[in] val The value to set.
+ * @param[in] id The variable name.
+ * @param[in,out] data Where the value is to be stored.
+ */
typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data);
+
+/**
+ * Type that represents a global variable marker function.
+ *
+ * @param[in] var Where the value is to be stored.
+ */
typedef void rb_gvar_marker_t(VALUE *var);
+/**
+ * @deprecated
+ *
+ * This function has no actual usage (than in ruby itself). Please ignore. It
+ * was a bad idea to expose this function to 3rd parties, but we can no longer
+ * delete it.
+ */
rb_gvar_getter_t rb_gvar_undef_getter;
+
+/**
+ * @deprecated
+ *
+ * This function has no actual usage (than in ruby itself). Please ignore. It
+ * was a bad idea to expose this function to 3rd parties, but we can no longer
+ * delete it.
+ */
rb_gvar_setter_t rb_gvar_undef_setter;
+
+/**
+ * @deprecated
+ *
+ * This function has no actual usage (than in ruby itself). Please ignore. It
+ * was a bad idea to expose this function to 3rd parties, but we can no longer
+ * delete it.
+ */
rb_gvar_marker_t rb_gvar_undef_marker;
+/**
+ * This is the getter function that backs global variables defined from a ruby
+ * script. Extension libraries can use this if its global variable needs no
+ * custom logic.
+ */
rb_gvar_getter_t rb_gvar_val_getter;
+
+/**
+ * This is the setter function that backs global variables defined from a ruby
+ * script. Extension libraries can use this if its global variable needs no
+ * custom logic.
+ */
rb_gvar_setter_t rb_gvar_val_setter;
+
+/**
+ * This is the setter function that backs global variables defined from a ruby
+ * script. Extension libraries can use this if its global variable needs no
+ * custom logic.
+ */
rb_gvar_marker_t rb_gvar_val_marker;
+/**
+ * @deprecated
+ *
+ * This function has no actual usage (than in ruby itself). Please ignore. It
+ * was a bad idea to expose this function to 3rd parties, but we can no longer
+ * delete it.
+ */
rb_gvar_getter_t rb_gvar_var_getter;
+
+/**
+ * @deprecated
+ *
+ * This function has no actual usage (than in ruby itself). Please ignore. It
+ * was a bad idea to expose this function to 3rd parties, but we can no longer
+ * delete it.
+ */
rb_gvar_setter_t rb_gvar_var_setter;
+
+/**
+ * @deprecated
+ *
+ * This function has no actual usage (than in ruby itself). Please ignore. It
+ * was a bad idea to expose this function to 3rd parties, but we can no longer
+ * delete it.
+ */
rb_gvar_marker_t rb_gvar_var_marker;
RBIMPL_ATTR_NORETURN()
+/**
+ * This function just raises ::rb_eNameError. Handy when you want to prohibit
+ * a global variable from being squashed by someone.
+ */
rb_gvar_setter_t rb_gvar_readonly_setter;
-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_ATTR_NONNULL(())
+/**
+ * "Shares" a global variable between Ruby and C. Normally a Ruby-level global
+ * variable is stored somewhere deep inside of the interpreter's execution
+ * context, but this way you can explicitly specify its storage.
+ *
+ * ```CXX
+ * static VALUE foo;
+ *
+ * extern "C" void
+ * init_Foo(void)
+ * {
+ * foo = rb_eval_string("...");
+ * rb_define_variable("$foo", &foo);
+ * }
+ * ```
+ *
+ * In the above example a Ruby global variable named `$foo` is stored in a C
+ * global variable named `foo`.
+ *
+ * @param[in] name Variable (Ruby side).
+ * @param[in] var Variable (C side).
+ * @post Ruby level global variable named `name` is defined if absent,
+ * and its storage is set to `var`.
+ */
+void rb_define_variable(const char *name, VALUE *var);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Defines a global variable that is purely function-backended. By using this
+ * API a programmer can define a global variable that dynamically changes from
+ * time to time.
+ *
+ * @param[in] name Variable name, in C's string.
+ * @param[in] getter A getter function.
+ * @param[in] setter A setter function.
+ * @post Ruby level global variable named `name` is defined if absent.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't know if this is an Easter egg or an official feature, but
+ * you can pass 0 to the third argument (setter). That effectively nullifies
+ * any efforts to write to the defining global variable.
+ */
+void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_define_virtual_variable(), but can also specify a storage.
+ * A programmer can use the storage for e.g. memoisation, storing intermediate
+ * computation result, etc.
+ *
+ * Also you can pass 0 to this function, unlike other variants:
+ *
+ * - When getter is 0 ::rb_gvar_var_getter is used instead.
+ * - When setter is 0 ::rb_gvar_var_setter is used instead.
+ * - When data is 0, you must specify a non-zero setter function. Otherwise
+ * ::rb_gvar_var_setter tries to write to `*NULL`, and just causes SEGV.
+ *
+ * @param[in] name Variable name, in C's string.
+ * @param[in] var Variable storage.
+ * @param[in] getter A getter function.
+ * @param[in] setter A setter function.
+ * @post Ruby level global variable named `name` is defined if absent.
+ */
+void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_define_variable(), except it does not allow Ruby programs to
+ * assign values to such global variable. C codes can still set values at
+ * will. This could be handy for you when implementing an `errno`-like
+ * experience, where a method updates a read-only global variable as a side-
+ * effect.
+ *
+ * @param[in] name Variable (Ruby side).
+ * @param[in] var Variable (C side).
+ * @post Ruby level global variable named `name` is defined if absent,
+ * and its storage is set to `var`.
+ */
+void rb_define_readonly_variable(const char *name, const VALUE *var);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Defines a Ruby level constant under a namespace.
+ *
+ * @param[out] klass Namespace for the constant to reside.
+ * @param[in] name Name of the constant.
+ * @param[in] val Value of the constant.
+ * @exception rb_eTypeError `klass` is not a kind of ::rb_cModule.
+ * @exception rb_eFrozenError `klass` is frozen.
+ * @post Ruby level constant `klass::name` is defined to be `val`.
+ * @note This API does not stop you from defining a constant that is
+ * unable to reach from ruby (like for instance passing
+ * non-capital letter to `name`).
+ * @note This API does not stop you from overwriting a constant that
+ * already exist.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+void rb_define_const(VALUE klass, const char *name, VALUE val);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Identical to rb_define_const(), except it defines that of "global",
+ * i.e. toplevel constant.
+ *
+ * @param[in] name Name of the constant.
+ * @param[in] val Value of the constant.
+ * @exception rb_eFrozenError ::rb_cObject is frozen.
+ * @post Ruby level constant \::name is defined to be `val`.
+ * @note This API does not stop you from defining a constant that is
+ * unable to reach from ruby (like for instance passing
+ * non-capital letter to `name`).
+ * @note This API does not stop you from overwriting a constant that
+ * already exist.
+ */
+void rb_define_global_const(const char *name, VALUE val);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Asserts that the given constant is deprecated. Attempt to refer such
+ * constant will produce a warning.
+ *
+ * @param[in] mod Namespace of the target constant.
+ * @param[in] name Name of the constant.
+ * @exception rb_eNameError No such constant.
+ * @exception rb_eFrozenError `mod` is frozen.
+ * @post `name` under `mod` is deprecated.
+ */
+void rb_deprecate_constant(VALUE mod, const char *name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Assigns to a global variable.
+ *
+ * @param[in] name Target global variable.
+ * @param[in] val Value to assign.
+ * @return Passed value.
+ * @post Ruby level global variable named `name` is defined if absent,
+ * whose value is set to `val`.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with
+ * `set_trace_func`.
+ */
+VALUE rb_gv_set(const char *name, VALUE val);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Obtains a global variable.
+ *
+ * @param[in] name Global variable to query.
+ * @retval RUBY_Qnil The global variable does not exist.
+ * @retval otherwise The value assigned to the global variable.
+ *
+ * @internal
+ *
+ * Unlike rb_gv_set(), there is no way to trace this function.
+ */
+VALUE rb_gv_get(const char *name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Obtains an instance variable.
+ *
+ * @param[in] obj Target object.
+ * @param[in] name Target instance variable to query.
+ * @exception rb_eEncodingError `name` is corrupt (contains Hanzi etc.).
+ * @retval RUBY_nil No such instance variable.
+ * @retval otherwise The value assigned to the instance variable.
+ */
+VALUE rb_iv_get(VALUE obj, const char *name);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Assigns to an instance variable.
+ *
+ * @param[out] obj Target object.
+ * @param[in] name Target instance variable.
+ * @param[in] val Value to assign.
+ * @exception rb_eFrozenError Can't modify `obj`.
+ * @exception rb_eArgError `obj` has too many instance variables.
+ * @return Passed value.
+ * @post An instance variable named `name` is defined if absent on
+ * `obj`, whose value is set to `val`.
+ *
+ * @internal
+ *
+ * This function does not stop you form creating an ASCII-incompatible instance
+ * variable, but there is no way to get one because rb_iv_get raises exceptions
+ * for such things. This design seems broken... But no idea why.
+ */
+VALUE rb_iv_set(VALUE obj, const char *name, VALUE val);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/warning_push.h b/include/ruby/internal/warning_push.h
index ca521290c9..f5981633f8 100644
--- a/include/ruby/internal/warning_push.h
+++ b/include/ruby/internal/warning_push.h
@@ -17,9 +17,8 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always 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
+ * extension libraries. They could be written in C++98.
+ * @brief Defines #RBIMPL_WARNING_PUSH.
*
* ### Q&A ###
*
@@ -46,7 +45,41 @@
#include "ruby/internal/compiler_is.h"
#include "ruby/internal/compiler_since.h"
-#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
+#if defined(__DOXYGEN__)
+
+/**
+ * @private
+ *
+ * Pushes compiler warning state.
+ */
+#define RBIMPL_WARNING_PUSH() __pragma(warning(push))
+
+/**
+ * @private
+ *
+ * Pops compiler warning state.
+ */
+#define RBIMPL_WARNING_POP() __pragma(warning(pop))
+
+/**
+ * @private
+ *
+ * Turns a warning into a fatal error.
+ *
+ * @param flag A flag that represents the kind of warnings.
+ */
+#define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag))
+
+/**
+ * @private
+ *
+ * Suppresses a warning.
+ *
+ * @param flag A flag that represents the kind of warnings.
+ */
+#define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag))
+
+#elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
# /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/
# define RBIMPL_WARNING_PUSH() __pragma(warning(push))
# define RBIMPL_WARNING_POP() __pragma(warning(pop))
diff --git a/include/ruby/internal/xmalloc.h b/include/ruby/internal/xmalloc.h
index 76da1eb099..57552e4e7d 100644
--- a/include/ruby/internal/xmalloc.h
+++ b/include/ruby/internal/xmalloc.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Declares ::ruby_xmalloc().
*/
#include "ruby/internal/config.h"
@@ -37,16 +37,25 @@
#include "ruby/internal/attr/returns_nonnull.h"
#include "ruby/internal/dllexport.h"
+/**
+ * @private
+ * @warning Do not touch this macro.
+ * @warning It is an implementation detail.
+ * @warning It was a failure at the first place to let you know about it.
+ * @warning The value of this macro must match for ruby itself and all
+ * extension libraries, otherwise serious memory corruption shall
+ * occur.
+ */
#ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS
# define USE_GC_MALLOC_OBJ_INFO_DETAILS 0
#endif
-#define xmalloc ruby_xmalloc
-#define xmalloc2 ruby_xmalloc2
-#define xcalloc ruby_xcalloc
-#define xrealloc ruby_xrealloc
-#define xrealloc2 ruby_xrealloc2
-#define xfree ruby_xfree
+#define xmalloc ruby_xmalloc /**< @old{ruby_xmalloc} */
+#define xmalloc2 ruby_xmalloc2 /**< @old{ruby_xmalloc2} */
+#define xcalloc ruby_xcalloc /**< @old{ruby_xcalloc} */
+#define xrealloc ruby_xrealloc /**< @old{ruby_xrealloc} */
+#define xrealloc2 ruby_xrealloc2 /**< @old{ruby_xrealloc2} */
+#define xfree ruby_xfree /**< @old{ruby_xfree} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
@@ -114,9 +123,9 @@ 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.
+ * Identical to ruby_xmalloc2(), except it returns a zero-filled storage
+ * instance. It can also be seen as a routine identical to ruby_xmalloc(),
+ * except it calls calloc() instead of malloc().
*
* @param[in] nelems Number of elements.
* @param[in] elemsiz Size of an element.
@@ -125,6 +134,7 @@ RBIMPL_ATTR_ALLOC_SIZE((1,2))
* @return A valid pointer to an allocated storage instance; which has at
* least `nelems` * `elemsiz` bytes width, with appropriate
* alignment detected by the underlying calloc() routine.
+ * @post The returned storage instance is filled with zeros.
* @note It doesn't return NULL.
* @note Unlike some calloc() implementations, it allocates something and
* returns a meaningful value even when `nelems` or `elemsiz` or
@@ -145,22 +155,28 @@ 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().
+ * 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().
+ * @return A valid pointer to a (possibly newly allocated) storage
+ * instance; which has at least `newsiz` bytes width, with
+ * appropriate alignment detected by the underlying realloc()
+ * routine.
+ * @pre The passed pointer must point to a valid live storage instance.
+ * It is a failure to pass an already freed pointer.
+ * @post In case the function returns the passed pointer as-is, the
+ * storage instance that the pointer holds is either grown or
+ * shrunken to have at least `newsiz` bytes. Otherwise a valid
+ * pointer to a newly allocated storage instance is returned. In
+ * this case `ptr` is invalidated as if it was passed to
+ * ruby_xfree().
* @note It doesn't return NULL.
- * @warning Unlike some realloc() implementations, passing zero to `elemsiz`
+ * @warning Unlike some realloc() implementations, passing zero to `newsiz`
* is not the same as calling ruby_xfree(), because this function
* never returns NULL. Something meaningful still returns then.
* @warning It is a failure not to check the return value. Do not assume
@@ -193,23 +209,28 @@ RBIMPL_ATTR_ALLOC_SIZE((2,3))
* 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().
-
+ * 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().
+ * @return A valid pointer to a (possibly newly allocated) storage
+ * instance; which has at least `newelems` * `newsiz` bytes width,
+ * with appropriate alignment detected by the underlying realloc()
+ * routine.
+ * @pre The passed pointer must point to a valid live storage instance.
+ * It is a failure to pass an already freed pointer.
+ * @post In case the function returns the passed pointer as-is, the
+ * storage instance that the pointer holds is either grown or
+ * shrunken to have at least `newelems` * `newsiz` bytes.
+ * Otherwise a valid pointer to a newly allocated storage instance
+ * is returned. In this case `ptr` is invalidated as if it was
+ * passed to ruby_xfree().
* @note It doesn't return NULL.
* @warning Unlike some realloc() implementations, passing zero to either
* `newelems` or `elemsiz` are not the same as calling
@@ -233,9 +254,18 @@ 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().
+ * @param[out] ptr Either
+ * - NULL, or
+ * - a valid pointer previously returned from one of:
+ * - ruby_xmalloc(),
+ * - ruby_xmalloc2(),
+ * - ruby_xcalloc(),
+ * - ruby_xrealloc(), or
+ * - ruby_xrealloc2().
+ * @pre The passed pointer must point to a valid live storage instance.
+ * It is a failure to pass an already freed pointer.
+ * @post The storage instance pointed by the passed pointer gets
+ * invalidated; it is no longer addressable.
* @warning Every single storage instance that was previously allocated by
* either ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(),
* ruby_xrealloc(), or ruby_xrealloc2() shall be invalidated
@@ -253,7 +283,7 @@ void ruby_xfree(void *ptr)
RBIMPL_ATTR_NOEXCEPT(free(ptr))
;
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS || defined(__DOXYGEN)
+#if USE_GC_MALLOC_OBJ_INFO_DETAILS
# define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__)
# define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__)
# define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__)
diff --git a/include/ruby/io.h b/include/ruby/io.h
index dfef85bbe3..88029b1bb9 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -20,6 +20,8 @@
#endif
#include <errno.h>
+
+/** @cond INTERNAL_MACRO */
#if defined(HAVE_POLL)
# ifdef _AIX
# define reqevents events
@@ -33,153 +35,985 @@
# undef revents
# endif
# define RB_WAITFD_IN POLLIN
-# define RB_WAITFD_PRI POLLPRI
+# if defined(POLLPRI)
+# define RB_WAITFD_PRI POLLPRI
+# else
+# define RB_WAITFD_PRI 0
+# endif
# define RB_WAITFD_OUT POLLOUT
#else
# define RB_WAITFD_IN 0x001
# define RB_WAITFD_PRI 0x002
# define RB_WAITFD_OUT 0x004
#endif
+/** @endcond */
-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/attr/const.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/attributes.h" /* PACKED_STRUCT_UNALIGNED */
+
+// IO#wait, IO#wait_readable, IO#wait_writable, IO#wait_priority are defined by this implementation.
+#define RUBY_IO_WAIT_METHODS
+
+// Used as the default timeout argument to `rb_io_wait` to use the `IO#timeout` value.
+#define RUBY_IO_TIMEOUT_DEFAULT Qnil
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
+struct stat;
+struct timeval;
+
+/**
+ * Indicates that a timeout has occurred while performing an IO operation.
+ */
+RUBY_EXTERN VALUE rb_eIOTimeoutError;
+
+/**
+ * Type of events that an IO can wait.
+ *
+ * @internal
+ *
+ * This is visible from extension libraries because `io/wait` wants it.
+ */
+typedef enum {
+ RUBY_IO_READABLE = RB_WAITFD_IN, /**< `IO::READABLE` */
+ RUBY_IO_WRITABLE = RB_WAITFD_OUT, /**< `IO::WRITABLE` */
+ RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */
+} rb_io_event_t;
+
+/**
+ * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and
+ * ::rb_io_t::rbuf. People don't manipulate it directly.
+ */
PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t {
+
+ /** Pointer to the underlying memory region, of at least `capa` bytes. */
char *ptr; /* off + len <= capa */
+
+ /** Offset inside of `ptr`. */
int off;
+
+ /** Length of the buffer. */
int len;
+
+ /** Designed capacity of the buffer. */
int capa;
});
+
+/** @alias{rb_io_buffer_t} */
typedef struct rb_io_buffer_t rb_io_buffer_t;
+/** Decomposed encoding flags (e.g. `"enc:enc2""`). */
+/*
+ * enc enc2 read action write action
+ * NULL NULL force_encoding(default_external) write the byte sequence of str
+ * e1 NULL force_encoding(e1) convert str.encoding to e1
+ * e1 e2 convert from e2 to e1 convert str.encoding to e2
+ */
+struct rb_io_enc_t {
+ /** Internal encoding. */
+ rb_encoding *enc;
+ /** External encoding. */
+ rb_encoding *enc2;
+ /**
+ * Flags.
+ *
+ * @see enum ::ruby_econv_flag_type
+ */
+ int ecflags;
+ /**
+ * Flags as Ruby hash.
+ *
+ * @internal
+ *
+ * This is set. But used from nowhere maybe?
+ */
+ VALUE ecopts;
+};
+
+/** Ruby's IO, metadata and buffers. */
typedef struct rb_io_t {
+
+ /** The IO's Ruby level counterpart. */
VALUE self;
- FILE *stdio_file; /* stdio ptr for read/write if available */
- int fd; /* file descriptor */
- int mode; /* mode flags: FMODE_XXXs */
- rb_pid_t pid; /* child's pid (for pipes) */
- int lineno; /* number of lines read */
- VALUE pathv; /* pathname for file */
- void (*finalize)(struct rb_io_t*,int); /* finalize proc */
+ /** stdio ptr for read/write, if available. */
+ FILE *stdio_file;
- rb_io_buffer_t wbuf, rbuf;
+ /** file descriptor. */
+ int fd;
- VALUE tied_io_for_writing;
+ /** mode flags: FMODE_XXXs */
+ int mode;
+
+ /** child's pid (for pipes) */
+ rb_pid_t pid;
- /*
- * enc enc2 read action write action
- * NULL NULL force_encoding(default_external) write the byte sequence of str
- * e1 NULL force_encoding(e1) convert str.encoding to e1
- * e1 e2 convert from e2 to e1 convert str.encoding to e2
+ /** number of lines read */
+ int lineno;
+
+ /** pathname for file */
+ VALUE pathv;
+
+ /** finalize proc */
+ void (*finalize)(struct rb_io_t*,int);
+
+ /** Write buffer. */
+ rb_io_buffer_t wbuf;
+
+ /**
+ * (Byte) read buffer. Note also that there is a field called
+ * ::rb_io_t::cbuf, which also concerns read IO.
*/
- struct rb_io_enc_t {
- rb_encoding *enc;
- rb_encoding *enc2;
- int ecflags;
- VALUE ecopts;
- } encs;
+ rb_io_buffer_t rbuf;
+ /**
+ * Duplex IO object, if set.
+ *
+ * @see rb_io_set_write_io()
+ */
+ VALUE tied_io_for_writing;
+
+ struct rb_io_enc_t encs; /**< Decomposed encoding flags. */
+
+ /** Encoding converter used when reading from this IO. */
rb_econv_t *readconv;
+
+ /**
+ * rb_io_ungetc() destination. This buffer is read before checking
+ * ::rb_io_t::rbuf
+ */
rb_io_buffer_t cbuf;
+ /** Encoding converter used when writing to this IO. */
rb_econv_t *writeconv;
+
+ /**
+ * This is, when set, an instance of ::rb_cString which holds the "common"
+ * encoding. Write conversion can convert strings twice... In case
+ * conversion from encoding X to encoding Y does not exist, Ruby finds an
+ * encoding Z that bridges the two, so that X to Z to Y conversion happens.
+ */
VALUE writeconv_asciicompat;
+
+ /** Whether ::rb_io_t::writeconv is already set up. */
int writeconv_initialized;
+
+ /**
+ * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before
+ * initialising ::rb_io_t::writeconv.
+ */
int writeconv_pre_ecflags;
+
+ /**
+ * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising
+ * ::rb_io_t::writeconv.
+ */
VALUE writeconv_pre_ecopts;
+ /**
+ * This is a Ruby level mutex. It avoids multiple threads to write to an
+ * IO at once; helps for instance rb_io_puts() to ensure newlines right
+ * next to its arguments.
+ *
+ * This of course doesn't help inter-process IO interleaves, though.
+ */
VALUE write_lock;
+
+ /**
+ * The timeout associated with this IO when performing blocking operations.
+ */
+ VALUE timeout;
} rb_io_t;
+/** @alias{rb_io_enc_t} */
typedef struct rb_io_enc_t rb_io_enc_t;
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_RB_IO_T 1
+/**
+ * @name Possible flags for ::rb_io_t::mode
+ *
+ * @{
+ */
+
+/** The IO is opened for reading. */
#define FMODE_READABLE 0x00000001
+
+/** The IO is opened for writing. */
#define FMODE_WRITABLE 0x00000002
+
+/** The IO is opened for both read/write. */
#define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE)
+
+/**
+ * The IO is in "binary mode". This is not what everything rb_io_binmode()
+ * concerns. This low-level flag is to stop CR <-> CRLF conversions that would
+ * happen in the underlying operating system.
+ *
+ * Setting this one and #FMODE_TEXTMODE at the same time is a contradiction.
+ * Setting this one and #ECONV_NEWLINE_DECORATOR_MASK at the same time is also
+ * a contradiction.
+ */
#define FMODE_BINMODE 0x00000004
+
+/**
+ * The IO is in "sync mode". All output is immediately flushed to the
+ * underlying operating system then. Can be set via rb_io_synchronized(), but
+ * there is no way except calling `IO#sync=` to reset.
+ */
#define FMODE_SYNC 0x00000008
+
+/**
+ * The IO is a TTY. What is a TTY and what isn't depends on the underlying
+ * operating system's `isatty(3)` output. You cannot change this.
+ */
#define FMODE_TTY 0x00000010
+
+/**
+ * Ruby eventually detects that the IO is bidirectional. For instance a TTY
+ * has such property. There are several other things known to be duplexed.
+ * Additionally you (extension library authors) can also implement your own
+ * bidirectional IO subclasses. One of such example is `Socket`.
+ */
#define FMODE_DUPLEX 0x00000020
+
+/**
+ * The IO is opened for appending. This mode always writes at the end of the
+ * IO. Ruby manages this flag for record but basically the logic behind this
+ * mode is at the underlying operating system. We almost do nothing.
+ */
#define FMODE_APPEND 0x00000040
+
+/**
+ * The IO is opened for creating. This makes sense only when the destination
+ * file does not exist at the time the IO object was created. This is the
+ * default mode for writing, but you can pass `"r+"` to `IO.open` etc., to
+ * reroute this creation.
+ */
#define FMODE_CREATE 0x00000080
/* #define FMODE_NOREVLOOKUP 0x00000100 */
+
+/**
+ * This flag amends the effect of #FMODE_CREATE, so that if there already is a
+ * file at the given path the operation fails. Using this you can be sure that
+ * the file you get is a fresh new one.
+ */
#define FMODE_EXCL 0x00000400
+
+/**
+ * This flag amends the effect of #FMODE_CREATE, so that if there already is a
+ * file at the given path it gets truncated.
+ */
#define FMODE_TRUNC 0x00000800
+
+/**
+ * The IO is in "text mode". On systems where such mode make sense, this flag
+ * changes the way the IO handles the contents. On POSIX systems it is
+ * basically a no-op, but with this flag set you can optionally let Ruby
+ * manually convert newlines, unlike when in binary mode:
+ *
+ * ```ruby
+ * IO.open("/p/a/t/h", "wt", crlf_newline: true) # "wb" is NG.
+ * ```
+ *
+ * Setting this one and #FMODE_BINMODE at the same time is a contradiction.
+ */
#define FMODE_TEXTMODE 0x00001000
/* #define FMODE_PREP 0x00010000 */
+/* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */
+
+/**
+ * This flag amends the encoding of the IO so that the BOM of the contents of
+ * the IO takes effect.
+ */
#define FMODE_SETENC_BY_BOM 0x00100000
/* #define FMODE_UNIX 0x00200000 */
/* #define FMODE_INET 0x00400000 */
/* #define FMODE_INET6 0x00800000 */
+/** @} */
+
+/**
+ * Queries the underlying IO pointer.
+ *
+ * @param[in] obj An IO object.
+ * @param[out] fp A variable of type ::rb_io_t.
+ * @exception rb_eFrozenError `obj` is frozen.
+ * @exception rb_eIOError `obj` is closed.
+ * @post `fp` holds `obj`'s underlying IO.
+ */
#define RB_IO_POINTER(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr)
+
+/**
+ * This is an old name of #RB_IO_POINTER. Not sure if we want to deprecate
+ * this macro. There still are tons of usages out there in the wild.
+ */
#define GetOpenFile RB_IO_POINTER
+/**
+ * Fills an IO object. This makes the best sense when called from inside of an
+ * `#initialize` method of a 3rd party extension library that inherits
+ * ::rb_cIO.
+ *
+ * If the passed IO is already opened for something it first closes that and
+ * opens a new one instead.
+ *
+ * @param[out] obj An IO object to fill in.
+ * @param[out] fp A variable of type ::rb_io_t.
+ * @exception rb_eTypeError `obj` is not ::RUBY_T_FILE.
+ * @post `fp` holds `obj`'s underlying IO.
+ */
#define RB_IO_OPEN(obj, fp) do {\
(fp) = rb_io_make_open_file(obj);\
} while (0)
+
+/**
+ * This is an old name of #RB_IO_OPEN. Not sure if we want to deprecate this
+ * macro. There still are usages out there in the wild.
+ */
#define MakeOpenFile RB_IO_OPEN
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_IO_OPEN. People don't use it
+ * directly.
+ *
+ * @param[out] obj An IO object to fill in.
+ * @exception rb_eTypeError `obj` is not ::RUBY_T_FILE.
+ * @return `obj`'s backend IO.
+ * @post `obj` is initialised.
+ */
rb_io_t *rb_io_make_open_file(VALUE obj);
+/**
+ * Finds or creates a stdio's file structure from a Ruby's one. This can be
+ * handy if you want to call an external API that accepts `FILE *`.
+ *
+ * @note Note however, that `FILE`s can have their own buffer. Mixing Ruby's
+ * and stdio's file are basically dangerous. Use with care.
+ *
+ * @param[in,out] fptr Target IO.
+ * @return A stdio's file, created if absent.
+ * @post `fptr` has its corresponding stdio's file.
+ *
+ * @internal
+ *
+ * We had rich support for `FILE` before! In the days of 1.8.x ::rb_io_t was
+ * like this:
+ *
+ * ```CXX
+ * typedef struct rb_io_t {
+ * FILE *f; // stdio ptr for read/write
+ * FILE *f2; // additional ptr for rw pipes
+ * int mode; // mode flags
+ * int pid; // child's pid (for pipes)
+ * int lineno; // number of lines read
+ * char *path; // pathname for file
+ * void (*finalize) _((struct rb_io_t*,int)); // finalize proc
+ * } rb_io_t;
+ *```
+ *
+ * But we eventually abandoned this layout. It was too difficult. We could
+ * not have fine-grained control over the `f` field.
+ *
+ * - `FILE` tends to be an opaque struct. It does not interface well with
+ * `select(2)` etc. This makes IO multiplexing quite hard. Using stdio,
+ * there is arguably no portable way to know if `fwrite(3)` blocks.
+ *
+ * - Nonblocking mode, which is another core concept that enables IO
+ * multiplexing, does not interface with stdio routines at all.
+ *
+ * - Detection of duplexed IO is also hard for the same reason.
+ *
+ * - `feof(3)` is not portable.
+ * https://mail.python.org/pipermail/python-dev/2001-January/011390.html
+ *
+ * - Solaris was a thing back then. They could not have more than 256 `FILE`
+ * structures at a time. Their file descriptors ware stored in an
+ * `unsigned char`.
+ *
+ * - It is next to impossible to avoid SEGV, especially when a thread tries to
+ * `ungetc(3)`-ing from a `FILE` which is `fread(3)`-ed by another one.
+ *
+ * In short, it is a bad idea to let someone else manage IO buffers, especially
+ * someone you cannot control. This still applies to extension libraries
+ * methinks. Ruby doesn't prevent you from shooting yourself in the foot, but
+ * consider yourself warned here.
+ */
FILE *rb_io_stdio_file(rb_io_t *fptr);
-FILE *rb_fdopen(int, const char*);
+/**
+ * Identical to rb_io_stdio_file(), except it takes file descriptors instead of
+ * Ruby's IO. It can also be seen as a compatibility layer to wrap
+ * `fdopen(3)`. Nowadays all supporting systems, including Windows, have
+ * `fdopen`. Why not use them.
+ *
+ * @param[in] fd A file descriptor.
+ * @param[in] modestr C string, something like `"r+"`.
+ * @exception rb_eSystemCallError `fdopen` failed for some reason.
+ * @return A stdio's file associated with `fd`.
+ * @note Interpretation of `modestr` depends on the underlying operating
+ * system. On glibc you might be able to pass e.g. `"rm"`, but
+ * that's an extension to POSIX.
+ */
+FILE *rb_fdopen(int fd, const char *modestr);
+
+/**
+ * Maps a file mode string (that rb_file_open() takes) into a mixture of
+ * `FMODE_` flags. This for instance returns
+ * `FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE | FMODE_EXCL` for `"wx"`.
+ *
+ * @note You cannot pass this return value to OS provided `open(2)` etc.
+ *
+ * @param[in] modestr File mode, in C's string.
+ * @exception rb_eArgError `modestr` is broken.
+ * @return A set of flags.
+ *
+ * @internal
+ *
+ * rb_io_modestr_fmode() is not a pure function because it raises.
+ */
int rb_io_modestr_fmode(const char *modestr);
+
+/**
+ * Identical to rb_io_modestr_fmode(), except it returns a mixture of `O_`
+ * flags. This for instance returns `O_WRONLY | O_TRUNC | O_CREAT | O_EXCL` for
+ * `"wx"`.
+ *
+ * @param[in] modestr File mode, in C's string.
+ * @exception rb_eArgError `modestr` is broken.
+ * @return A set of flags.
+ *
+ * @internal
+ *
+ * rb_io_modestr_oflags() is not a pure function because it raises.
+ */
int rb_io_modestr_oflags(const char *modestr);
-CONSTFUNC(int rb_io_oflags_fmode(int oflags));
-void rb_io_check_writable(rb_io_t*);
-void rb_io_check_readable(rb_io_t*);
+
+RBIMPL_ATTR_CONST()
+/**
+ * Converts an oflags (that rb_io_modestr_oflags() returns) to a fmode (that
+ * rb_io_mode_flags() returns). This is a purely functional operation.
+ *
+ * @param[in] oflags A set of `O_` flags.
+ * @return Corresponding set of `FMODE_` flags.
+ */
+int rb_io_oflags_fmode(int oflags);
+
+/**
+ * Asserts that an IO is opened for writing.
+ *
+ * @param[in] fptr An IO you want to write to.
+ * @exception rb_eIOError `fptr` is not for writing.
+ * @post Upon successful return `fptr` is ready for writing.
+ *
+ * @internal
+ *
+ * The parameter must have been `const rb_io_t *`.
+ */
+void rb_io_check_writable(rb_io_t *fptr);
+
+/** @alias{rb_io_check_byte_readable} */
+void rb_io_check_readable(rb_io_t *fptr);
+
+/**
+ * Asserts that an IO is opened for character-based reading. A character can
+ * be wider than a byte. Because of this we have to buffer reads from
+ * descriptors. This fiction checks if that is possible.
+ *
+ * @param[in] fptr An IO you want to read characters from.
+ * @exception rb_eIOError `fptr` is not for reading.
+ * @post Upon successful return `fptr` is ready for reading characters.
+ *
+ * @internal
+ *
+ * Unlike rb_io_check_writable() the parameter cannot be `const rb_io_t *`.
+ * Behind the scene this operation flushes its write buffers. This is because
+ * of OpenSSL. They mandate this way.
+ *
+ * @see "Can I use OpenSSL's SSL library with non-blocking I/O?"
+ * https://www.openssl.org/docs/faq.html
+ */
void rb_io_check_char_readable(rb_io_t *fptr);
+
+/**
+ * Asserts that an IO is opened for byte-based reading. Byte-based and
+ * character-based reading operations cannot be mixed at a time.
+ *
+ * @param[in] fptr An IO you want to read characters from.
+ * @exception rb_eIOError `fptr` is not for reading.
+ * @post Upon successful return `fptr` is ready for reading bytes.
+ */
void rb_io_check_byte_readable(rb_io_t *fptr);
-int rb_io_fptr_finalize(rb_io_t*);
-void rb_io_synchronized(rb_io_t*);
-void rb_io_check_initialized(rb_io_t*);
-void rb_io_check_closed(rb_io_t*);
+
+/**
+ * Destroys the given IO. Any pending operations are flushed.
+ *
+ * @note It makes no sense to call this function from anywhere outside of your
+ * class' ::rb_data_type_struct::dfree.
+ *
+ * @param[out] fptr IO to close.
+ * @post `fptr` is no longer a valid pointer.
+ */
+int rb_io_fptr_finalize(rb_io_t *fptr);
+
+/**
+ * Sets #FMODE_SYNC.
+ *
+ * @note There is no way for C extensions to undo this operation.
+ *
+ * @param[out] fptr IO to set the flag.
+ * @exception rb_eIOError `fptr` is not opened.
+ * @post `fptr` is in sync mode.
+ */
+void rb_io_synchronized(rb_io_t *fptr);
+
+/**
+ * Asserts that the passed IO is initialised.
+ *
+ * @param[in] fptr IO that you expect be initialised.
+ * @exception rb_eIOError `fptr` is not initialised.
+ * @post `fptr` is initialised.
+ */
+void rb_io_check_initialized(rb_io_t *fptr);
+
+/**
+ * This badly named function asserts that the passed IO is _open_.
+ *
+ * @param[in] fptr An IO
+ * @exception rb_eIOError `fptr` is closed.
+ * @post `fptr` is open.
+ */
+void rb_io_check_closed(rb_io_t *fptr);
+
+/**
+ * Identical to rb_io_check_io(), except it raises exceptions on conversion
+ * failures.
+ *
+ * @param[in] io Target object.
+ * @exception rb_eTypeError No implicit conversion to IO.
+ * @return Return value of `obj.to_io`.
+ * @see rb_str_to_str
+ * @see rb_ary_to_ary
+ */
VALUE rb_io_get_io(VALUE io);
+
+/**
+ * Try converting an object to its IO representation using its `to_io` method,
+ * if any. If there is no such thing, returns ::RUBY_Qnil.
+ *
+ * @param[in] io Arbitrary ruby object to convert.
+ * @exception rb_eTypeError `obj.to_io` returned something non-IO.
+ * @retval RUBY_Qnil No conversion from `obj` to IO defined.
+ * @retval otherwise Converted IO representation of `obj`.
+ * @see rb_check_array_type
+ * @see rb_check_string_type
+ * @see rb_check_hash_type
+ */
VALUE rb_io_check_io(VALUE io);
+
+/**
+ * Queries the tied IO for writing. An IO can be duplexed. Fine. The thing
+ * is, that characteristics could sometimes be achieved by the underlying
+ * operating system (for instance a socket's duplexity is by nature) but
+ * sometimes by us. Notable example is a bidirectional pipe. Suppose you
+ * have:
+ *
+ * ```ruby
+ * fp = IO.popen("-", "r+")
+ * ```
+ *
+ * This pipe is duplexed (the `"r+"`). You can both read from/write to it.
+ * However your operating system may or may not implement bidirectional pipes.
+ * FreeBSD is one of such operating systems known to have one; OTOH Linux is
+ * known to lack such things. So to achieve maximum portability, Ruby's
+ * bidirectional pipes are done purely in user land. A pipe in ruby can have
+ * multiple file descriptors; one for reading and the other for writing. This
+ * API is to obtain the IO port which corresponds to the passed one, for
+ * writing.
+ *
+ * @param[in] io An IO.
+ * @return Its tied IO for writing, if any, or `io` itself otherwise.
+ */
VALUE rb_io_get_write_io(VALUE io);
+
+/**
+ * Assigns the tied IO for writing. See rb_io_get_write_io() for what a "tied
+ * IO for writing" is.
+ *
+ * @param[out] io An IO.
+ * @param[in] w Another IO.
+ * @retval RUBY_Qnil There was no tied IO for writing for `io`.
+ * @retval otherwise The IO formerly tied to `io`.
+ * @post `io` ties `w` for writing.
+ *
+ * @internal
+ *
+ * @shyouhei doesn't think there is any needs of this function for 3rd party
+ * extension libraries.
+ */
VALUE rb_io_set_write_io(VALUE io, VALUE w);
+
+/**
+ * Instructs the OS to put its internal file structure into "nonblocking mode".
+ * This is an in-Kernel concept. Reading from/writing to that file using C
+ * function calls would return -1 with errno set. However when it comes to a
+ * ruby program, we hide that error behind our `IO#read` method. Ruby level
+ * `IO#read` blocks regardless of this flag. If you want to avoid blocking,
+ * you should consider using methods like `IO#readpartial`.
+ *
+ * ```ruby
+ * require 'io/nonblock'
+ * STDIN.nonblock = true
+ * STDIN.gets # blocks.
+ * ```
+ *
+ * As of writing there is a room of this API in Fiber schedulers. A Fiber
+ * scheduler could be written in a way its behaviour depends on this property.
+ * You need an in-depth understanding of how schedulers work to properly
+ * leverage this, though.
+ *
+ * @note Note however that nonblocking-ness propagates across process
+ * boundaries. You must really carefully watch your step when turning
+ * for instance `stderr` into nonblock mode (it tends to be shared
+ * across many processes). Also it is a complete disaster to mix a
+ * nonblocking file and stdio, and `stderr` tends to be under control of
+ * stdio in other processes.
+ *
+ * @param[out] fptr An IO that is to ne nonblocking.
+ * @post Descriptor that `fptr` describes is under nonblocking mode.
+ *
+ * @internal
+ *
+ * There is `O_NONBLOCK` but not `FMODE_NONBLOCK`. You cannot atomically
+ * create a nonblocking file descriptor using our API.
+ */
void rb_io_set_nonblock(rb_io_t *fptr);
+
+/**
+ * Returns an integer representing the numeric file descriptor for
+ * <em>io</em>.
+ *
+ * @param[in] io An IO.
+ * @retval int A file descriptor.
+ */
+int rb_io_descriptor(VALUE io);
+
+/**
+ * This function breaks down the option hash that `IO#initialize` takes into
+ * components. This is an implementation detail of rb_io_extract_modeenc()
+ * today. People prefer that API instead.
+ *
+ * @param[in] opt The hash to decompose.
+ * @param[out] enc_p Return value buffer.
+ * @param[out] enc2_p Return value buffer.
+ * @param[out] fmode_p Return value buffer.
+ * @exception rb_eTypeError `opt` is broken.
+ * @exception rb_eArgError Specified encoding does not exist.
+ * @retval 1 Components got extracted.
+ * @retval 0 Otherwise.
+ * @post `enc_p` is the specified internal encoding.
+ * @post `enc2_p` is the specified external encoding.
+ * @post `fmode_p` is the specified set of `FMODE_` modes.
+ */
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p);
+
+/**
+ * This function can be seen as an extended version of
+ * rb_io_extract_encoding_option() that not only concerns the option hash but
+ * also mode string and so on. This should be mixed with rb_scan_args() like:
+ *
+ * ```CXX
+ * // This method mimics File.new
+ * static VALUE
+ * your_method(int argc, const VALUE *argv, VALUE self)
+ * {
+ * VALUE f; // file name
+ * VALUE m; // open mode
+ * VALUE p; // permission (O_CREAT)
+ * VALUE k; // keywords
+ * rb_io_enc_t c; // converter
+ * int oflags;
+ * int fmode;
+ *
+ * int n = rb_scan_args(argc, argv, "12:", &f, &m, &p, &k);
+ * rb_io_extract_modeenc(&m, &p, k, &oflags, &fmode, &c);
+ *
+ * // Every local variables declared so far has been properly filled here.
+ * ...
+ * }
+ * ```
+ *
+ * @param[in,out] vmode_p Pointer to a mode object.
+ * @param[in,out] vperm_p Pointer to a permission object.
+ * @param[in] opthash Keyword arguments
+ * @param[out] oflags_p `O_` flags return buffer.
+ * @param[out] fmode_p `FMODE_` flags return buffer.
+ * @param[out] convconfig_p Encoding config return buffer.
+ * @exception rb_eTypeError Unexpected object (e.g. Time) passed.
+ * @exception rb_eArgError Contradiction inside of params.
+ * @post `*vmode_p` is a mode object (filled if any).
+ * @post `*vperm_p` is a permission object (filled if any).
+ * @post `*oflags_p` is filled with `O_` flags.
+ * @post `*fmode_p` is filled with `FMODE_` flags.
+ * @post `*convconfig_p` is filled with conversion instructions.
+ *
+ * @internal
+ *
+ * ```rbs
+ * class File
+ * def initialize: (
+ * (String | int) path,
+ * ?(String | int) fmode,
+ * ?(String | int) perm,
+ * ?mode: (String | int),
+ * ?flags: int,
+ * ?external_encoding: (Encoding | String),
+ * ?internal_encoding: (Encoding | String),
+ * ?encoding: String,
+ * ?textmode: bool,
+ * ?binmode: bool,
+ * ?autoclose: bool,
+ * ?invalid: :replace,
+ * ?undef: :replace,
+ * ?replace: String,
+ * ?fallback: (Hash | Proc | Method),
+ * ?xml: (:text | :attr),
+ * ?crlf_newline: bool,
+ * ?cr_newline: bool,
+ * ?universal_newline: bool
+ * ) -> void
+ * ```
+ */
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p);
+
+/* :TODO: can this function be __attribute__((warn_unused_result)) or not? */
+/**
+ * Buffered write to the passed IO.
+ *
+ * @param[out] io Destination IO.
+ * @param[in] buf Contents to go to `io`.
+ * @param[in] size Number of bytes of `buf`.
+ * @exception rb_eFrozenError `io` is frozen.
+ * @exception rb_eIOError `io` is not open for writing.
+ * @exception rb_eSystemCallError `writev(2)` failed for some reason.
+ * @retval -1 Write failed.
+ * @retval otherwise Number of bytes actually written.
+ * @post `buf` is written to `io`.
+ * @note Partial write is a thing. It is a failure not to check the
+ * return value.
+ */
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size);
//RBIMPL_ATTR_DEPRECATED(("use rb_io_maybe_wait_readable"))
+/**
+ * Blocks until the passed file descriptor gets readable.
+ *
+ * @deprecated We now prefer rb_io_maybe_wait_readable() over this one.
+ * @param[in] fd The file descriptor to wait.
+ * @exception rb_eIOError Bad file descriptor.
+ * @return 0 or 1 (meaning unclear).
+ * @post `fd` is ready for reading.
+ */
int rb_io_wait_readable(int fd);
//RBIMPL_ATTR_DEPRECATED(("use rb_io_maybe_wait_writable"))
+/**
+ * Blocks until the passed file descriptor gets writable.
+ *
+ * @deprecated We now prefer rb_io_maybe_wait_writable() over this one.
+ * @param[in] fd The file descriptor to wait.
+ * @exception rb_eIOError Bad file descriptor.
+ * @return 0 or 1 (meaning unclear).
+ */
int rb_io_wait_writable(int fd);
//RBIMPL_ATTR_DEPRECATED(("use rb_io_wait"))
+/**
+ * Blocks until the passed file descriptor is ready for the passed events.
+ *
+ * @deprecated We now prefer rb_io_maybe_wait() over this one.
+ * @param[in] fd The file descriptor to wait.
+ * @param[in] events A set of enum ::rb_io_event_t.
+ * @param[in,out] tv Timeout.
+ * @retval 0 Operation timed out.
+ * @retval -1 `select(2)` failed for some reason.
+ * @retval otherwise A set of enum ::rb_io_event_t.
+ * @note Depending on your operating system `tv` might or might not
+ * be updated (POSIX permits both). Portable programs must
+ * have no assumptions.
+ */
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv);
+/**
+ * Get the timeout associated with the specified io object.
+ *
+ * @param[in] io An IO object.
+ * @retval RUBY_Qnil There is no associated timeout.
+ * @retval Otherwise The timeout value.
+ */
+VALUE rb_io_timeout(VALUE io);
+
+/**
+ * Set the timeout associated with the specified io object. This timeout is
+ * used as a best effort timeout to prevent operations from blocking forever.
+ *
+ * @param[in] io An IO object.
+ * @param[in] timeout A timeout value. Must respond to #to_f.
+ * @
+ */
+VALUE rb_io_set_timeout(VALUE io, VALUE timeout);
+
+/**
+ * Blocks until the passed IO is ready for the passed events. The "events"
+ * here is a Ruby level integer, which is an OR-ed value of `IO::READABLE`,
+ * `IO::WRITable`, and `IO::PRIORITY`.
+ *
+ * If timeout is `Qnil`, it will use the default timeout as given by
+ * `rb_io_timeout(io)`.
+ *
+ * @param[in] io An IO object to wait.
+ * @param[in] events See above.
+ * @param[in] timeout Time, or numeric seconds since UNIX epoch.
+ * If Qnil, use the default timeout. If Qfalse
+ * or Qundef, wait forever.
+ * @exception rb_eIOError `io` is not open.
+ * @exception rb_eRangeError `timeout` is out of range.
+ * @exception rb_eSystemCallError `select(2)` failed for some reason.
+ * @retval RUBY_Qfalse Operation timed out.
+ * @retval Otherwise Actual events reached.
+ */
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout);
+
+/**
+ * Identical to rb_io_wait() except it additionally takes previous errno. If
+ * the passed errno indicates for instance `EINTR`, this function returns
+ * immediately. This is expected to be called in a loop.
+ *
+ * ```CXX
+ * while (true) {
+ *
+ * ... // Your interesting operation here
+ * // `errno` could be updated
+ *
+ * rb_io_maybe_wait(errno, io, ev, Qnil);
+ * }
+ * ```
+ *
+ * @param[in] error System errno.
+ * @param[in] io An IO object to wait.
+ * @param[in] events An integer set of interests.
+ * @param[in] timeout Time, or numeric seconds since UNIX epoch.
+ * @exception rb_eIOError `io` is not open.
+ * @exception rb_eRangeError `timeout` is out of range.
+ * @exception rb_eSystemCallError `select(2)` failed for some reason.
+ * @retval RUBY_Qfalse Operation timed out.
+ * @retval Otherwise Actual events reached.
+ *
+ * @internal
+ *
+ * This function to return ::RUBY_Qfalse on timeout could be unintended. It
+ * seems timeout feature has some rough edge.
+ */
VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout);
+
+/**
+ * Blocks until the passed IO is ready for reading, if that makes sense for the
+ * passed errno. This is a special case of rb_io_maybe_wait() that only
+ * concerns for reading.
+ *
+ * @param[in] error System errno.
+ * @param[in] io An IO object to wait.
+ * @param[in] timeout Time, or numeric seconds since UNIX epoch.
+ * @exception rb_eIOError `io` is not open.
+ * @exception rb_eRangeError `timeout` is out of range.
+ * @exception rb_eSystemCallError `select(2)` failed for some reason.
+ * @retval 0 Operation timed out.
+ * @retval Otherwise Always returns ::RUBY_IO_READABLE.
+ */
int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout);
+
+/**
+ * Blocks until the passed IO is ready for writing, if that makes sense for the
+ * passed errno. This is a special case of rb_io_maybe_wait() that only
+ * concernsfor writing.
+ *
+ * @param[in] error System errno.
+ * @param[in] io An IO object to wait.
+ * @param[in] timeout Time, or numeric seconds since UNIX epoch.
+ * @exception rb_eIOError `io` is not open.
+ * @exception rb_eRangeError `timeout` is out of range.
+ * @exception rb_eSystemCallError `select(2)` failed for some reason.
+ * @retval 0 Operation timed out.
+ * @retval Otherwise Always returns ::RUBY_IO_WRITABLE.
+ */
int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout);
+/** @cond INTERNAL_MACRO */
/* compatibility for ruby 1.8 and older */
#define rb_io_mode_flags(modestr) [<"rb_io_mode_flags() is obsolete; use rb_io_modestr_fmode()">]
#define rb_io_modenum_flags(oflags) [<"rb_io_modenum_flags() is obsolete; use rb_io_oflags_fmode()">]
+/** @endcond */
-VALUE rb_io_taint_check(VALUE);
-NORETURN(void rb_eof_error(void));
+/**
+ * @deprecated This function once was a thing in the old days, but makes no
+ * sense any longer today. Exists here for backwards
+ * compatibility only. You can safely forget about it.
+ *
+ * @param[in] obj Object in question.
+ * @exception rb_eFrozenError obj is frozen.
+ * @return The passed `obj`
+ */
+VALUE rb_io_taint_check(VALUE obj);
-void rb_io_read_check(rb_io_t*);
-int rb_io_read_pending(rb_io_t*);
+RBIMPL_ATTR_NORETURN()
+/**
+ * Utility function to raise ::rb_eEOFError.
+ *
+ * @exception rb_eEOFError End of file situation.
+ * @note It never returns.
+ */
+void rb_eof_error(void);
-struct stat;
-VALUE rb_stat_new(const struct stat *);
+/**
+ * Blocks until there is a pending read in the passed IO. If there already is
+ * it just returns.
+ *
+ * @param[out] fptr An IO to wait for reading.
+ * @post The are bytes to be read.
+ */
+void rb_io_read_check(rb_io_t *fptr);
+
+RBIMPL_ATTR_PURE()
+/**
+ * Queries if the passed IO has any pending reads. Unlike rb_io_read_check()
+ * this doesn't block; has no side effects.
+ *
+ * @param[in] fptr An IO which can have pending reads.
+ * @retval 0 The IO is empty.
+ * @retval 1 There is something buffered.
+ */
+int rb_io_read_pending(rb_io_t *fptr);
+
+/**
+ * Constructs an instance of ::rb_cStat from the passed information.
+ *
+ * @param[in] st A stat.
+ * @return Allocated new instance of ::rb_cStat.
+ */
+VALUE rb_stat_new(const struct stat *st);
/* gc.c */
diff --git a/include/ruby/io/buffer.h b/include/ruby/io/buffer.h
new file mode 100644
index 0000000000..e4b855d8e7
--- /dev/null
+++ b/include/ruby/io/buffer.h
@@ -0,0 +1,92 @@
+#ifndef RUBY_IO_BUFFER_H
+#define RUBY_IO_BUFFER_H
+/**
+ * @file
+ * @author Samuel Williams
+ * @date Fri 2 Jul 2021 16:29:01 NZST
+ * @copyright Copyright (C) 2021 Samuel Williams
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+
+#pragma once
+
+#include "ruby/ruby.h"
+#include "ruby/internal/config.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+// WARNING: This entire interface is experimental and may change in the future!
+#define RB_IO_BUFFER_EXPERIMENTAL 1
+
+#define RUBY_IO_BUFFER_VERSION 2
+
+RUBY_EXTERN VALUE rb_cIOBuffer;
+RUBY_EXTERN size_t RUBY_IO_BUFFER_PAGE_SIZE;
+RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE;
+
+enum rb_io_buffer_flags {
+ // The memory in the buffer is owned by someone else.
+ // More specifically, it means that someone else owns the buffer and we shouldn't try to resize it.
+ RB_IO_BUFFER_EXTERNAL = 1,
+ // The memory in the buffer is allocated internally.
+ RB_IO_BUFFER_INTERNAL = 2,
+ // The memory in the buffer is mapped.
+ // A non-private mapping is marked as external.
+ RB_IO_BUFFER_MAPPED = 4,
+
+ // A mapped buffer that is also shared.
+ RB_IO_BUFFER_SHARED = 8,
+
+ // The buffer is locked and cannot be resized.
+ // More specifically, it means we can't change the base address or size.
+ // A buffer is typically locked before a system call that uses the data.
+ RB_IO_BUFFER_LOCKED = 32,
+
+ // The buffer mapping is private and will not impact other processes or the underlying file.
+ RB_IO_BUFFER_PRIVATE = 64,
+
+ // The buffer is read-only and cannot be modified.
+ RB_IO_BUFFER_READONLY = 128
+};
+
+enum rb_io_buffer_endian {
+ RB_IO_BUFFER_LITTLE_ENDIAN = 4,
+ RB_IO_BUFFER_BIG_ENDIAN = 8,
+
+#if defined(WORDS_BIGENDIAN)
+ RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN,
+#else
+ RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN,
+#endif
+
+ RB_IO_BUFFER_NETWORK_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN
+};
+
+VALUE rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags);
+VALUE rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags flags);
+
+VALUE rb_io_buffer_lock(VALUE self);
+VALUE rb_io_buffer_unlock(VALUE self);
+int rb_io_buffer_try_unlock(VALUE self);
+VALUE rb_io_buffer_free(VALUE self);
+
+int rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size);
+void rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size);
+void rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size);
+
+VALUE rb_io_buffer_transfer(VALUE self);
+void rb_io_buffer_resize(VALUE self, size_t size);
+void rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length);
+
+// The length is the minimum required length.
+VALUE rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset);
+VALUE rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset);
+VALUE rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset);
+VALUE rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RUBY_IO_BUFFER_H */
diff --git a/include/ruby/memory_view.h b/include/ruby/memory_view.h
index 4492c06b38..1ddca2d46f 100644
--- a/include/ruby/memory_view.h
+++ b/include/ruby/memory_view.h
@@ -1,4 +1,4 @@
-#ifndef RUBY_MEMORY_VIEW_H
+#ifndef RUBY_MEMORY_VIEW_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_MEMORY_VIEW_H 1
/**
* @file
@@ -10,11 +10,25 @@
* @brief Memory View.
*/
-#include "ruby/internal/dllexport.h"
-#include "ruby/internal/stdbool.h"
-#include "ruby/internal/value.h"
-#include "ruby/intern.h"
+#include "ruby/internal/config.h"
+#ifdef STDC_HEADERS
+# include <stddef.h> /* size_t */
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* ssize_t */
+#endif
+
+#include "ruby/internal/attr/pure.h" /* RBIMPL_ATTR_PURE */
+#include "ruby/internal/core/rtypeddata.h" /* rb_data_type_t */
+#include "ruby/internal/dllexport.h" /* RUBY_EXTERN */
+#include "ruby/internal/stdbool.h" /* bool */
+#include "ruby/internal/value.h" /* VALUE */
+
+/**
+ * Flags passed to rb_memory_view_get(), then to ::rb_memory_view_get_func_t.
+ */
enum ruby_memory_view_flags {
RUBY_MEMORY_VIEW_SIMPLE = 0,
RUBY_MEMORY_VIEW_WRITABLE = (1<<0),
@@ -27,29 +41,56 @@ enum ruby_memory_view_flags {
RUBY_MEMORY_VIEW_INDIRECT = (1<<6) | RUBY_MEMORY_VIEW_STRIDES,
};
+/** Memory view component metadata. */
typedef struct {
+ /** @see ::rb_memory_view_t::format */
char format;
+
+ /** :FIXME: what is a "native" size is unclear. */
unsigned native_size_p: 1;
+
+ /** Endian of the component */
unsigned little_endian_p: 1;
+
+ /** The component's offset. */
size_t offset;
+
+ /** The component's size. */
size_t size;
+
+ /**
+ * How many numbers of components are there. For instance "CCC"'s repeat is
+ * 3.
+ */
size_t repeat;
} rb_memory_view_item_component_t;
+/**
+ * A MemoryView structure, `rb_memory_view_t`, is used for exporting objects'
+ * MemoryView.
+ *
+ * This structure contains the reference of the object, which is the owner of
+ * the MemoryView, the pointer to the head of exported memory, and the metadata
+ * that describes the structure of the memory. The metadata can describe
+ * multidimensional arrays with strides.
+ */
typedef struct {
- /* The original object that has the memory exported via this memory view. */
+ /**
+ * The original object that has the memory exported via this memory view.
+ */
VALUE obj;
- /* The pointer to the exported memory. */
+ /** The pointer to the exported memory. */
void *data;
- /* The number of bytes in data. */
+ /** The number of bytes in data. */
ssize_t byte_size;
- /* true for readonly memory, false for writable memory. */
+ /** true for readonly memory, false for writable memory. */
bool readonly;
- /* A string to describe the format of an element, or NULL for unsigned bytes.
+ /**
+ * 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!,
@@ -69,83 +110,204 @@ typedef struct {
*/
const char *format;
- /* The number of bytes in each element.
+ /**
+ * The number of bytes in each element.
* item_size should equal to rb_memory_view_item_size_from_format(format). */
ssize_t item_size;
+ /** Description of each components. */
struct {
- /* The array of rb_memory_view_item_component_t that describes the
+ /**
+ * 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. */
+ /** The number of components in an item. */
size_t length;
} item_desc;
- /* The number of dimension. */
+ /** The number of dimension. */
ssize_t ndim;
- /* ndim size array indicating the number of elements in each dimension.
+ /**
+ * 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
+ /**
+ * 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.
+ /**
+ * 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;
+ /** The private data for managing this exported memory */
+ void *private_data;
+
+ /** DO NOT TOUCH THIS: The memory view entry for the internal use */
+ const struct rb_memory_view_entry *_memory_view_entry;
} rb_memory_view_t;
+/** Type of function of ::rb_memory_view_entry_t::get_func. */
typedef bool (* rb_memory_view_get_func_t)(VALUE obj, rb_memory_view_t *view, int flags);
+
+/** Type of function of ::rb_memory_view_entry_t::release_func. */
typedef bool (* rb_memory_view_release_func_t)(VALUE obj, rb_memory_view_t *view);
+
+/** Type of function of ::rb_memory_view_entry_t::available_p_func. */
typedef bool (* rb_memory_view_available_p_func_t)(VALUE obj);
-typedef struct {
+/** Operations applied to a specific kind of a memory view. */
+typedef struct rb_memory_view_entry {
+ /**
+ * Exports a memory view from a Ruby object.
+ */
rb_memory_view_get_func_t get_func;
+
+ /**
+ * Releases a memory view that was previously generated using
+ * ::rb_memory_view_entry_t::get_func.
+ */
rb_memory_view_release_func_t release_func;
+
+ /**
+ * Queries if an object understands memory view protocol.
+ */
rb_memory_view_available_p_func_t available_p_func;
} rb_memory_view_entry_t;
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* memory_view.c */
+
+/**
+ * Associates the passed class with the passed memory view entry. This has to
+ * be called before actually creating a memory view from an instance.
+ */
bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry);
RBIMPL_ATTR_PURE()
+/**
+ * Return `true` if the data in the MemoryView `view` is row-major contiguous.
+ *
+ * Return `false` otherwise.
+ */
bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view);
+
RBIMPL_ATTR_PURE()
+/**
+ * Return `true` if the data in the MemoryView `view` is column-major
+ * contiguous.
+ *
+ * Return `false` otherwise.
+ */
bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view);
+
RBIMPL_ATTR_NOALIAS()
+/**
+ * Fill the `strides` array with byte-Strides of a contiguous array of the
+ * given shape with the given element size.
+ */
void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides);
+
RBIMPL_ATTR_NOALIAS()
+/**
+ * Fill the members of `view` as an 1-dimensional byte array.
+ */
bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly);
+
+/**
+ * Deconstructs the passed format string, as describe in
+ * ::rb_memory_view_t::format.
+ */
ssize_t rb_memory_view_parse_item_format(const char *format,
rb_memory_view_item_component_t **members,
size_t *n_members, const char **err);
+
+/**
+ * Calculate the number of bytes occupied by an element.
+ *
+ * When the calculation fails, the failed location in `format` is stored into
+ * `err`, and returns `-1`.
+ */
ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err);
+
+/**
+ * Calculate the location of the item indicated by the given `indices`.
+ *
+ * The length of `indices` must equal to `view->ndim`.
+ *
+ * This function initializes `view->item_desc` if needed.
+ */
void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices);
+
+/**
+ * Return a value that consists of item members.
+ *
+ * When an item is a single member, the return value is a single value.
+ *
+ * When an item consists of multiple members, an array will be returned.
+ */
VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members);
+
+/** Fill the `item_desc` member of `view`. */
void rb_memory_view_prepare_item_desc(rb_memory_view_t *view);
+
+/** * Return a value that consists of item members in the given memory view. */
VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices);
+/**
+ * Return `true` if `obj` supports to export a MemoryView. Return `false`
+ * otherwise.
+ *
+ * If this function returns `true`, it doesn't mean the function
+ * `rb_memory_view_get` will succeed.
+ */
bool rb_memory_view_available_p(VALUE obj);
+
+/**
+ * If the given `obj` supports to export a MemoryView that conforms the given
+ * `flags`, this function fills `view` by the information of the MemoryView and
+ * returns `true`. In this case, the reference count of `obj` is increased.
+ *
+ * If the given combination of `obj` and `flags` cannot export a MemoryView,
+ * this function returns `false`. The content of `view` is not touched in this
+ * case.
+ *
+ * The exported MemoryView must be released by `rb_memory_view_release` when
+ * the MemoryView is no longer needed.
+ */
bool rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags);
+
+/**
+ * Release the given MemoryView `view` and decrement the reference count of
+ * `memory_view->obj`.
+ *
+ * Consumers must call this function when the MemoryView is no longer needed.
+ * Missing to call this function leads memory leak.
+ */
bool rb_memory_view_release(rb_memory_view_t* memory_view);
/* for testing */
+/** @cond INTERNAL_MACRO */
RUBY_EXTERN VALUE rb_memory_view_exported_object_registry;
RUBY_EXTERN const rb_data_type_t rb_memory_view_exported_object_registry_data_type;
+/** @endcond */
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE()
+/**
+ * Return `true` if the data in the MemoryView `view` is row-major or
+ * column-major contiguous.
+ *
+ * Return `false` otherwise.
+ */
static inline bool
rb_memory_view_is_contiguous(const rb_memory_view_t *view)
{
diff --git a/include/ruby/missing.h b/include/ruby/missing.h
index 7d551248ae..aea6c9088d 100644
--- a/include/ruby/missing.h
+++ b/include/ruby/missing.h
@@ -1,7 +1,6 @@
#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.
@@ -34,11 +33,24 @@
# include <sys/time.h>
#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif
+
#ifdef HAVE_IEEEFP_H
# include <ieeefp.h>
#endif
#include "ruby/internal/dllexport.h"
+#include "ruby/internal/attr/format.h"
#ifndef M_PI
# define M_PI 3.14159265358979323846
@@ -92,10 +104,6 @@ RUBY_EXTERN int eaccess(const char*, int);
RUBY_EXTERN double round(double); /* numeric.c */
#endif
-#ifndef HAVE_FINITE
-RUBY_EXTERN int finite(double);
-#endif
-
#ifndef HAVE_FLOCK
RUBY_EXTERN int flock(int, int);
#endif
@@ -152,35 +160,9 @@ RUBY_EXTERN const union bytesequence4_or_float rb_nan;
# define HUGE_VAL ((double)INFINITY)
#endif
-#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
-
-#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
-
-#if defined(isfinite)
-# /* Take that. */
-#elif defined(HAVE_ISFINITE)
-# /* Take that. */
-#else
-# define HAVE_ISFINITE 1
-# define isfinite(x) finite(x)
+#ifndef HAVE_FINITE
+# define HAVE_FINITE 1
+# define finite(x) isfinite(x)
#endif
#ifndef HAVE_NAN
@@ -228,10 +210,6 @@ RUBY_EXTERN size_t strlcpy(char *, const char*, size_t);
RUBY_EXTERN size_t strlcat(char *, const char*, size_t);
#endif
-#ifndef HAVE_SIGNBIT
-RUBY_EXTERN int signbit(double x);
-#endif
-
#ifndef HAVE_FFS
RUBY_EXTERN int ffs(int);
#endif
@@ -246,6 +224,7 @@ RUBY_EXTERN int ruby_close(int);
#endif
#ifndef HAVE_SETPROCTITLE
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
RUBY_EXTERN void setproctitle(const char *fmt, ...);
#endif
@@ -257,6 +236,107 @@ RUBY_EXTERN void setproctitle(const char *fmt, ...);
RUBY_EXTERN void explicit_bzero(void *b, size_t len);
#endif
+#ifndef HAVE_TZSET
+RUBY_EXTERN void tzset(void);
+#endif
+
+#ifndef HAVE_POSIX_MADVISE
+RUBY_EXTERN int posix_madvise(void *, size_t, int);
+#endif
+
+#ifndef HAVE_GETEUID
+RUBY_EXTERN rb_uid_t geteuid(void);
+#endif
+
+#ifndef HAVE_GETUID
+RUBY_EXTERN rb_uid_t getuid(void);
+#endif
+
+#ifndef HAVE_GETEGID
+RUBY_EXTERN rb_gid_t getegid(void);
+#endif
+
+#ifndef HAVE_GETGID
+RUBY_EXTERN rb_gid_t getgid(void);
+#endif
+
+#ifndef HAVE_GETLOGIN
+RUBY_EXTERN char *getlogin(void);
+#endif
+
+#ifndef HAVE_GETPPID
+RUBY_EXTERN rb_pid_t getppid(void);
+#endif
+
+#ifndef HAVE_UMASK
+RUBY_EXTERN rb_mode_t umask(rb_mode_t);
+#endif
+
+#ifndef HAVE_CHMOD
+RUBY_EXTERN int chmod(const char *, rb_mode_t);
+#endif
+
+#ifndef HAVE_CHOWN
+RUBY_EXTERN int chown(const char *, rb_uid_t, rb_gid_t);
+#endif
+
+#ifndef HAVE_PCLOSE
+RUBY_EXTERN int pclose(FILE *);
+#endif
+
+#ifndef HAVE_POPEN
+RUBY_EXTERN FILE *popen(const char *, const char *);
+#endif
+
+#ifndef HAVE_PIPE
+RUBY_EXTERN int pipe(int [2]);
+#endif
+
+#ifndef HAVE_DUP
+RUBY_EXTERN int dup(int);
+#endif
+
+#ifndef HAVE_DUP2
+RUBY_EXTERN int dup2(int, int);
+#endif
+
+#ifndef HAVE_KILL
+RUBY_EXTERN int kill(rb_pid_t, int);
+#endif
+
+#ifndef HAVE_EXECL
+RUBY_EXTERN int execl(const char *, const char *, ...);
+#endif
+
+#ifndef HAVE_EXECLE
+RUBY_EXTERN int execle(const char *, const char *, ...);
+#endif
+
+#ifndef HAVE_EXECV
+RUBY_EXTERN int execv(const char *, char *const []);
+#endif
+
+#ifndef HAVE_EXECVE
+RUBY_EXTERN int execve(const char *, char *const [], char *const []);
+#endif
+
+#ifndef HAVE_SHUTDOWN
+RUBY_EXTERN int shutdown(int, int);
+#endif
+
+#ifndef HAVE_SYSTEM
+RUBY_EXTERN int system(const char *);
+#endif
+
+#ifndef WNOHANG
+# define WNOHANG 0
+#endif
+
+#ifndef HAVE_WAITPID
+# define HAVE_WAITPID 1
+RUBY_EXTERN rb_pid_t waitpid(rb_pid_t, int *, int);
+#endif
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_MISSING_H */
diff --git a/include/ruby/onigmo.h b/include/ruby/onigmo.h
index 6187b37dc3..8d7c601703 100644
--- a/include/ruby/onigmo.h
+++ b/include/ruby/onigmo.h
@@ -356,9 +356,9 @@ int onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, c
#define ONIGENC_PRECISE_MBC_ENC_LEN(enc,p,e) (enc)->precise_mbc_enc_len(p,e,enc)
ONIG_EXTERN
-int onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc);
+int onigenc_mbclen(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc);
-#define ONIGENC_MBC_ENC_LEN(enc,p,e) onigenc_mbclen_approximate(p,e,enc)
+#define ONIGENC_MBC_ENC_LEN(enc,p,e) onigenc_mbclen(p,e,enc)
#define ONIGENC_MBC_MAXLEN(enc) ((enc)->max_enc_len)
#define ONIGENC_MBC_MAXLEN_DIST(enc) ONIGENC_MBC_MAXLEN(enc)
#define ONIGENC_MBC_MINLEN(enc) ((enc)->min_enc_len)
@@ -744,6 +744,8 @@ typedef struct {
typedef struct {
int lower;
int upper;
+ long base_num;
+ long inner_num;
} OnigRepeatRange;
typedef void (*OnigWarnFunc)(const char* s);
@@ -793,6 +795,13 @@ typedef struct re_pattern_buffer {
OnigDistance dmin; /* min-distance of exact or map */
OnigDistance dmax; /* max-distance of exact or map */
+ /* rb_hrtime_t from hrtime.h */
+#ifdef MY_RUBY_BUILD_MAY_TIME_TRAVEL
+ int128_t timelimit;
+#else
+ uint64_t timelimit;
+#endif
+
/* regex_t link chain */
struct re_pattern_buffer* chain; /* escape compile-conflict */
} OnigRegexType;
@@ -845,6 +854,8 @@ OnigPosition onig_search_gpos(OnigRegex, const OnigUChar* str, const OnigUChar*
ONIG_EXTERN
OnigPosition onig_match(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* at, OnigRegion* region, OnigOptionType option);
ONIG_EXTERN
+int onig_check_linear_time(OnigRegex reg);
+ONIG_EXTERN
OnigRegion* onig_region_new(void);
ONIG_EXTERN
void onig_region_init(OnigRegion* region);
diff --git a/include/ruby/ractor.h b/include/ruby/ractor.h
index 1d6687456c..7811616f6d 100644
--- a/include/ruby/ractor.h
+++ b/include/ruby/ractor.h
@@ -1,4 +1,4 @@
-#ifndef RUBY_RACTOR_H
+#ifndef RUBY_RACTOR_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_RACTOR_H 1
/**
@@ -11,50 +11,246 @@
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
*/
+#include "internal/dllexport.h" /* RUBY_EXTERN is here */
+#include "internal/fl_type.h" /* FL_TEST_RAW is here */
+#include "internal/special_consts.h" /* RB_SPECIAL_CONSTS_P is here */
+#include "internal/stdbool.h" /* bool is here */
+#include "internal/value.h" /* VALUE is here */
+/** Type that defines a ractor-local storage. */
struct rb_ractor_local_storage_type {
+
+ /**
+ * A function to mark a ractor-local storage.
+ *
+ * @param[out] ptr A ractor-local storage.
+ * @post Ruby objects inside of `ptr` are marked.
+ */
void (*mark)(void *ptr);
+
+ /**
+ * A function to destruct a ractor-local storage.
+ *
+ * @param[out] ptr A ractor-local storage.
+ * @post `ptr` is not a valid pointer.
+ */
void (*free)(void *ptr);
// TODO: update
};
+/** (Opaque) struct that holds a ractor-local storage key. */
typedef struct rb_ractor_local_key_struct *rb_ractor_local_key_t;
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * `Ractor` class.
+ *
+ * @ingroup object
+ */
RUBY_EXTERN VALUE rb_cRactor;
+/**
+ * Queries the standard input of the current Ractor that is calling this
+ * function.
+ *
+ * @return An IO.
+ * @note This can be different from the process-global one.
+ */
VALUE rb_ractor_stdin(void);
+
+/**
+ * Queries the standard output of the current Ractor that is calling this
+ * function.
+ *
+ * @return An IO.
+ * @note This can be different from the process-global one.
+ */
VALUE rb_ractor_stdout(void);
+
+/**
+ * Queries the standard error of the current Ractor that is calling this
+ * function.
+ *
+ * @return An IO.
+ * @note This can be different from the process-global one.
+ */
VALUE rb_ractor_stderr(void);
-void rb_ractor_stdin_set(VALUE);
-void rb_ractor_stdout_set(VALUE);
-void rb_ractor_stderr_set(VALUE);
+/**
+ * Assigns an IO to the standard input of the Ractor that is calling this
+ * function.
+ *
+ * @param[in] io An IO.
+ * @post `io` is the standard input of the current ractor.
+ * @post In case the calling Ractor is the main Ractor, it also updates
+ * the process global ::rb_stdin.
+ */
+void rb_ractor_stdin_set(VALUE io);
+
+/**
+ * Assigns an IO to the standard output of the Ractor that is calling this
+ * function.
+ *
+ * @param[in] io An IO.
+ * @post `io` is the standard input of the current ractor.
+ * @post In case the calling Ractor is the main Ractor, it also updates
+ * the process global ::rb_stdout.
+ */
+void rb_ractor_stdout_set(VALUE io);
+
+/**
+ * Assigns an IO to the standard error of the Ractor that is calling this
+ * function.
+ *
+ * @param[in] io An IO.
+ * @post `io` is the standard input of the current ractor.
+ * @post In case the calling Ractor is the main Ractor, it also updates
+ * the process global ::rb_stderr.
+ */
+void rb_ractor_stderr_set(VALUE io);
+
+/**
+ * Issues a new key.
+ *
+ * @return A newly issued ractor-local storage key. Keys issued using this
+ * key can be associated to a Ruby object per Ractor.
+ */
rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void);
+
+/**
+ * Queries the key.
+ *
+ * @param[in] key A ractor-local storage key to lookup.
+ * @retval RUBY_Qnil No such key.
+ * @retval otherwise A value corresponds to `key` in the current Ractor.
+ * @note This cannot distinguish between a nonexistent key and a key
+ * exists and corresponds to ::RUBY_Qnil.
+ */
VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key);
+
+/**
+ * Queries the key.
+ *
+ * @param[in] key A ractor-local storage key to lookup.
+ * @param[out] val Return value buffer.
+ * @retval false `key` not found.
+ * @retval true `key` found.
+ * @post `val` is updated so that it has the value corresponds to `key`
+ * in the current Ractor.
+ */
bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val);
+
+/**
+ * Associates the passed value to the passed key.
+ *
+ * @param[in] key A ractor-local storage key.
+ * @param[in] val Arbitrary ruby object.
+ * @post `val` corresponds to `key` in the current Ractor.
+ */
void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val);
+/**
+ * A type of ractor-local storage that destructs itself using ::ruby_xfree.
+ *
+ * @internal
+ *
+ * Why it is visible from 3rd party extension libraries is not obvious to
+ * @shyouhei.
+ */
RUBY_EXTERN const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free;
+
+/** @alias{rb_ractor_local_storage_type_free} */
#define RB_RACTOR_LOCAL_STORAGE_TYPE_FREE (&rb_ractor_local_storage_type_free)
+/**
+ * Extended version of rb_ractor_local_storage_value_newkey(). It additionally
+ * takes the type of the issuing key.
+ *
+ * @param[in] type How the value associated with the issuing key should
+ * behave.
+ * @return A newly issued ractor-local storage key, of type `type`.
+ */
rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type);
+
+/**
+ * Identical to rb_ractor_local_storage_value() except the return type.
+ *
+ * @param[in] key A ractor-local storage key to lookup.
+ * @retval NULL No such key.
+ * @retval otherwise A value corresponds to `key` in the current Ractor.
+ */
void *rb_ractor_local_storage_ptr(rb_ractor_local_key_t key);
+
+/**
+ * Identical to rb_ractor_local_storage_value_set() except the parameter type.
+ *
+ * @param[in] key A ractor-local storage key.
+ * @param[in] ptr A pointer that conforms `key`'s type.
+ * @post `ptr` corresponds to `key` in the current Ractor.
+ */
void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr);
+/**
+ * Destructively transforms the passed object so that multiple Ractors can
+ * share it. What is a shareable object and what is not is a nuanced concept,
+ * and @ko1 says the definition can still change. However extension library
+ * authors might interest to learn how to use #RUBY_TYPED_FROZEN_SHAREABLE.
+ *
+ * @param[out] obj Arbitrary ruby object to modify.
+ * @exception rb_eRactorError Ractors cannot share `obj` by nature.
+ * @return Passed `obj`.
+ * @post Multiple Ractors can share `obj`.
+ *
+ * @internal
+ *
+ * In case an exception is raised, `obj` remains in an intermediate state where
+ * some of its part is frozen and others are not. @shyouhei is not sure if it
+ * is either an intended behaviour, current implementation limitation, or
+ * simply a bug. Note also that there is no way to "melt" a frozen object.
+ */
VALUE rb_ractor_make_shareable(VALUE obj);
+
+/**
+ * Identical to rb_ractor_make_shareable(), except it returns a (deep) copy of
+ * the passed one instead of modifying it in-place.
+ *
+ * @param[in] obj Arbitrary ruby object to duplicate.
+ * @exception rb_eRactorError Ractors cannot share `obj` by nature.
+ * @return A deep copy of `obj` which is sharable among Ractors.
+ */
VALUE rb_ractor_make_shareable_copy(VALUE obj);
-RUBY_SYMBOL_EXPORT_END
+RBIMPL_SYMBOL_EXPORT_END()
+/**
+ * Queries if the passed object has previously classified as shareable or not.
+ * This doesn't mean anything in practice... Objects can be shared later.
+ * Always use rb_ractor_shareable_p() instead.
+ *
+ * @param[in] obj Object in question.
+ * @retval RUBY_FL_SHAREABLE It once was shareable before.
+ * @retval 0 Otherwise.
+ */
#define RB_OBJ_SHAREABLE_P(obj) FL_TEST_RAW((obj), RUBY_FL_SHAREABLE)
+/**
+ * Queries if multiple Ractors can share the passed object or not. Ractors run
+ * without protecting each other. Sharing an object among them is basically
+ * dangerous, disabled by default. However there are objects that are
+ * extremely carefully implemented to be Ractor-safe; for instance integers
+ * have such property. This function can classify that.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @retval true `obj` is capable of shared across ractors.
+ * @retval false `obj` cannot travel across ractor boundaries.
+ */
static inline bool
rb_ractor_shareable_p(VALUE obj)
{
bool rb_ractor_shareable_p_continue(VALUE obj);
- if (SPECIAL_CONST_P(obj)) {
+ if (RB_SPECIAL_CONST_P(obj)) {
return true;
}
else if (RB_OBJ_SHAREABLE_P(obj)) {
diff --git a/include/ruby/random.h b/include/ruby/random.h
index 56b2dd413f..39bdb6f3e3 100644
--- a/include/ruby/random.h
+++ b/include/ruby/random.h
@@ -1,4 +1,4 @@
-#ifndef RUBY_RANDOM_H
+#ifndef RUBY_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_RANDOM_H 1
/**
* @file
@@ -8,69 +8,327 @@
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
+ *
+ * This is a set of APIs to roll your own subclass of ::rb_cRandom. An
+ * illustrative example of such PRNG can be found at
+ * `ext/-test-/ramdom/loop.c`.
*/
#include "ruby/ruby.h"
+/*
+ * version
+ * 0: before versioning; deprecated
+ * 1: added version, flags and init_32bit function
+ */
+#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR 1
+#define RUBY_RANDOM_INTERFACE_VERSION_MINOR 0
+
+#define RUBY_RANDOM_PASTE_VERSION_SUFFIX(x, y, z) x##_##y##_##z
+#define RUBY_RANDOM_WITH_VERSION_SUFFIX(name, major, minor) \
+ RUBY_RANDOM_PASTE_VERSION_SUFFIX(name, major, minor)
+#define rb_random_data_type \
+ RUBY_RANDOM_WITH_VERSION_SUFFIX(rb_random_data_type, \
+ RUBY_RANDOM_INTERFACE_VERSION_MAJOR, \
+ RUBY_RANDOM_INTERFACE_VERSION_MINOR)
+#define RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER \
+ {RUBY_RANDOM_INTERFACE_VERSION_MAJOR, RUBY_RANDOM_INTERFACE_VERSION_MINOR}
+#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX 0xff
+#define RUBY_RANDOM_INTERFACE_VERSION_MINOR_MAX 0xff
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * Base components of the random interface.
+ *
+ * @internal
+ *
+ * Ideally this could be an empty class if we could assume C++, but in C a
+ * struct must have at least one field.
+ */
struct rb_random_struct {
+ /** Seed, passed through e.g. `Random.new` */
VALUE seed;
};
-typedef struct rb_random_struct rb_random_t;
+typedef struct rb_random_struct rb_random_t; /**< @see ::rb_random_struct */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is the type of functions called when your random object is initialised.
+ * Passed buffer is the seed object basically. But in Ruby a number can be
+ * really big. This type of functions accept such big integers as a series of
+ * machine words.
+ *
+ * @param[out] rng Your random struct to fill in.
+ * @param[in] buf Seed, maybe converted from a bignum.
+ * @param[in] len Number of words of `buf`.
+ * @post `rng` is initialised using the passed seeds.
+ */
+typedef void rb_random_init_func(rb_random_t *rng, const uint32_t *buf, size_t len);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is the type of functions called when your random object is initialised.
+ * Passed data is the seed integer.
+ *
+ * @param[out] rng Your random struct to fill in.
+ * @param[in] data Seed, single word.
+ * @post `rng` is initialised using the passed seeds.
+ */
+typedef void rb_random_init_int32_func(rb_random_t *rng, uint32_t data);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is the type of functions called from your object's `#rand` method.
+ *
+ * @param[out] rng Your random struct to extract an integer from.
+ * @return A random number.
+ * @post `rng` is consumed somehow.
+ */
+typedef unsigned int rb_random_get_int32_func(rb_random_t *rng);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is the type of functions called from your object's `#bytes` method.
+ *
+ * @param[out] rng Your random struct to extract an integer from.
+ * @param[out] buf Return buffer of at least `len` bytes length.
+ * @param[in] len Number of bytes of `buf`.
+ * @post `rng` is consumed somehow.
+ * @post `buf` is filled with random bytes.
+ */
+typedef void rb_random_get_bytes_func(rb_random_t *rng, void *buf, size_t len);
-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);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is the type of functions called from your object's `#rand` method.
+ *
+ * @param[out] rng Your random struct to extract an integer from.
+ * @param[in] excl Pass nonzero value here to indicate you don't want 1.0.
+ * @return A random number of range 0.0 to 1.0.
+ * @post `rng` is consumed somehow.
+ */
+typedef double rb_random_get_real_func(rb_random_t *rng, int excl);
+/** PRNG algorithmic interface, analogous to Ruby level classes. */
typedef struct {
+ /** Number of bits of seed numbers. */
size_t default_seed_bits;
+
+ /**
+ * Major/minor versions of this interface
+ */
+ struct {
+ uint8_t major, minor;
+ } version;
+
+ /**
+ * Reserved flags
+ */
+ uint16_t flags;
+
+ /** Function to initialize from uint32_t array. */
rb_random_init_func *init;
+
+ /** Function to initialize from single uint32_t. */
+ rb_random_init_int32_func *init_int32;
+
+ /** Function to obtain a random integer. */
rb_random_get_int32_func *get_int32;
+
+ /**
+ * Function to obtain a series of random bytes. If your PRNG have a native
+ * method to yield arbitrary number of bytes use that to implement this.
+ * But in case you lack such things, you can do so by using
+ * rb_rand_bytes_int32()
+ *
+ * ```CXX
+ * extern rb_random_get_int32_func your_get_int32_func;
+ *
+ * void
+ * your_get_byes_func(rb_random_t *rng, void *buf, size_t len)
+ * {
+ * rb_rand_bytes_int32(your_get_int32_func, rng, buf, len);
+ * }
+ * ```
+ */
rb_random_get_bytes_func *get_bytes;
+
+ /**
+ * Function to obtain a random double. If your PRNG have a native method
+ * to yield a floating point random number use that to implement this. But
+ * in case you lack such things, you can do so by using
+ * rb_int_pair_to_real().
+ *
+ * ```CXX
+ * extern rb_random_get_int32_func your_get_int32_func;
+ *
+ * void
+ * your_get_real_func(rb_random_t *rng, int excl)
+ * {
+ * auto a = your_get_int32_func(rng);
+ * auto b = your_get_int32_func(rng);
+ * return rb_int_pair_to_real(a, b, excl);
+ * }
+ * ```
+ */
rb_random_get_real_func *get_real;
} rb_random_interface_t;
+/**
+ * This utility macro defines 4 functions named prefix_init, prefix_init_int32,
+ * prefix_get_int32, prefix_get_bytes.
+ */
#define RB_RANDOM_INTERFACE_DECLARE(prefix) \
static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \
+ static void prefix##_init_int32(rb_random_t *, uint32_t); \
static unsigned int prefix##_get_int32(rb_random_t *); \
static void prefix##_get_bytes(rb_random_t *, void *, size_t)
+/**
+ * Identical to #RB_RANDOM_INTERFACE_DECLARE except it also declares
+ * prefix_get_real.
+ */
#define RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(prefix) \
RB_RANDOM_INTERFACE_DECLARE(prefix); \
static double prefix##_get_real(rb_random_t *, int)
+/**
+ * This utility macro expands to the names declared using
+ * #RB_RANDOM_INTERFACE_DECLARE. Expected to be used inside of a
+ * ::rb_random_interface_t initialiser:
+ *
+ * ```CXX
+ * RB_RANDOM_INTERFACE_DECLARE(foo);
+ *
+ * static inline constexpr rb_random_interface_t foo_interface = {
+ * 32768, // bits
+ * RB_RANDOM_INTERFACE_DEFINE(foo),
+ * };
+ * ```
+ */
#define RB_RANDOM_INTERFACE_DEFINE(prefix) \
+ RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER, 0, \
prefix##_init, \
+ prefix##_init_int32, \
prefix##_get_int32, \
prefix##_get_bytes
+/**
+ * Identical to #RB_RANDOM_INTERFACE_DEFINE except it also defines
+ * prefix_get_real.
+ */
#define RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(prefix) \
RB_RANDOM_INTERFACE_DEFINE(prefix), \
prefix##_get_real
+#define RB_RANDOM_DEFINE_INIT_INT32_FUNC(prefix) \
+ static void prefix##_init_int32(rb_random_t *rnd, uint32_t data) \
+ { \
+ prefix##_init(rnd, &data, 1); \
+ }
+
#if defined _WIN32 && !defined __CYGWIN__
typedef rb_data_type_t rb_random_data_type_t;
# define RB_RANDOM_PARENT 0
#else
+
+/** This is the type of ::rb_random_data_type. */
typedef const rb_data_type_t rb_random_data_type_t;
+
+/**
+ * This utility macro can be used when you define your own PRNG type:
+ *
+ * ```CXX
+ * static inline constexpr rb_random_interface_t your_if = {
+ * 0, RB_RANDOM_INTERFACE_DEFINE(your),
+ * };
+ *
+ * static inline constexpr rb_random_data_type_t your_prng_type = {
+ * "your PRNG",
+ * { rb_random_mark, },
+ * RB_RANDOM_PARENT, // <<-- HERE
+ * &your_if,
+ * 0,
+ * }
+ * ```
+ */
# define RB_RANDOM_PARENT &rb_random_data_type
#endif
+/**
+ * This macro is expected to be called exactly once at the beginning of a
+ * program, possibly from inside of your `Init_Foo()` function. Depending on
+ * platforms #RB_RANDOM_PARENT can require a fixup. This routine does that
+ * when necessary.
+ */
#define RB_RANDOM_DATA_INIT_PARENT(random_data) \
rbimpl_random_data_init_parent(&random_data)
+/**
+ * This is the implementation of ::rb_data_type_struct::dmark for
+ * ::rb_random_data_type. In case your PRNG does not involve Ruby objects at
+ * all (which is quite likely), you can simply reuse it.
+ *
+ * @param[out] ptr Target to mark, which is a ::rb_random_t this case.
+ */
void rb_random_mark(void *ptr);
+
+/**
+ * Initialises an allocated ::rb_random_t instance. Call it from your own
+ * initialiser appropriately.
+ *
+ * @param[out] rnd Your PRNG's base part.
+ * @post `rnd` is filled with an initial state.
+ */
void rb_random_base_init(rb_random_t *rnd);
+
+/**
+ * Generates a 64 bit floating point number by concatenating two 32bit unsigned
+ * integers.
+ *
+ * @param[in] a Most significant 32 bits of the result.
+ * @param[in] b Least significant 32 bits of the result.
+ * @param[in] excl Whether the result should exclude 1.0 or not.
+ * @return A double, whose range is either `[0, 1)` or `[0, 1]`.
+ * @see ::rb_random_interface_t::get_real()
+ *
+ * @internal
+ *
+ * This in fact has nothing to do with PRNGs.
+ */
double rb_int_pair_to_real(uint32_t a, uint32_t b, int excl);
-void rb_rand_bytes_int32(rb_random_get_int32_func *, rb_random_t *, void *, size_t);
+
+/**
+ * Repeatedly calls the passed function over and over again until the passed
+ * buffer is filled with random bytes.
+ *
+ * @param[in] func Generator function.
+ * @param[out] prng Passed as-is to `func`.
+ * @param[out] buff Return buffer.
+ * @param[in] size Number of words of `buff`.
+ * @post `buff` is filled with random bytes.
+ * @post `prng` is updated by `func`.
+ * @see ::rb_random_interface_t::get_bytes()
+ */
+void rb_rand_bytes_int32(rb_random_get_int32_func *func, rb_random_t *prng, void *buff, size_t size);
+
+/**
+ * The data that holds the backend type of ::rb_cRandom. Used as your PRNG's
+ * ::rb_data_type_struct::parent.
+ */
RUBY_EXTERN const rb_data_type_t rb_random_data_type;
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+/**
+ * Queries the interface of the passed random object.
+ *
+ * @param[in] obj An instance (of a subclass) of ::rb_cRandom.
+ * @return Its corresponding ::rb_random_interface_t interface.
+ */
static inline const rb_random_interface_t *
rb_rand_if(VALUE obj)
{
@@ -81,6 +339,15 @@ rb_rand_if(VALUE obj)
}
RBIMPL_ATTR_NOALIAS()
+/**
+ * @private
+ *
+ * This is an implementation detail of #RB_RANDOM_DATA_INIT_PARENT. People
+ * don't use it directly.
+ *
+ * @param[out] random_data Region to fill.
+ * @post ::rb_random_data_type is filled appropriately.
+ */
static inline void
rbimpl_random_data_init_parent(rb_random_data_type_t *random_data)
{
diff --git a/include/ruby/re.h b/include/ruby/re.h
index ec0f425db0..3892d6e7f2 100644
--- a/include/ruby/re.h
+++ b/include/ruby/re.h
@@ -11,23 +11,136 @@
* file COPYING are met. Consult the file for details.
*/
#include "ruby/internal/config.h"
-#include <sys/types.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
#include <stdio.h>
#include "ruby/regex.h"
#include "ruby/internal/core/rmatch.h"
#include "ruby/internal/dllexport.h"
+struct re_registers; /* Defined in onigmo.h */
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
-VALUE rb_reg_regcomp(VALUE);
-long rb_reg_search(VALUE, VALUE, long, int);
-VALUE rb_reg_regsub(VALUE, VALUE, struct re_registers *, VALUE);
-long rb_reg_adjust_startpos(VALUE, VALUE, long, int);
-void rb_match_busy(VALUE);
-VALUE rb_reg_quote(VALUE);
+/**
+ * Creates a new instance of ::rb_cRegexp. It can be seen as a specialised
+ * version of rb_reg_new_str() where it does not take options.
+ *
+ * @param[in] str Source code in String.
+ * @return Allocated new instance of ::rb_cRegexp.
+ */
+VALUE rb_reg_regcomp(VALUE str);
+
+/**
+ * Runs the passed regular expression over the passed string. Unlike
+ * rb_reg_search() this function also takes position and direction of the
+ * search, which make it possible for this function to run from in middle of
+ * the string.
+ *
+ * @param[in] re Regular expression to execute.
+ * @param[in] str Target string to search.
+ * @param[in] pos Offset in `str` to start searching, in bytes.
+ * @param[in] dir `pos`' direction; 0 means left-to-right, 1 for
+ * the opposite.
+ * @exception rb_eArgError `re` is broken.
+ * @exception rb_eRegexpError `re` is malformed.
+ * @retval -1 Match failed.
+ * @retval otherwise Offset of first such byte where match happened.
+ * @post `Regexp.last_match` is updated.
+ * @post `$&`, `$~`, etc., are updated.
+ *
+ * @internal
+ *
+ * Distinction between raising ::rb_eArgError and ::rb_eRegexpError is not
+ * obvious, at least to @shyouhei.
+ */
+long rb_reg_search(VALUE re, VALUE str, long pos, int dir);
+
+/**
+ * Substitution. This is basically the implementation of `String#sub`. Also
+ * `String#gsub` repeatedly calls this function.
+ *
+ * @param[in] repl Replacement string, e.g. `"\\1\\2"`
+ * @param[in] src Source string, to be replaced.
+ * @param[in] regs Matched data generated by applying `rexp` to `src`.
+ * @param[in] rexp Regular expression.
+ * @return A substituted string.
+ *
+ * @internal
+ *
+ * This function does not check for encoding compatibility. `String#sub!`
+ * etc. employ their own checker.
+ *
+ * `regs` should have been `const struct re_registers *` because it is read
+ * only. Kept as-is for compatibility.
+ */
+VALUE rb_reg_regsub(VALUE repl, VALUE src, struct re_registers *regs, VALUE rexp);
+
+/**
+ * Tell us if this is a wrong idea, but it seems this function has no usage at
+ * all. Just remains here for theoretical backwards compatibility.
+ *
+ * @param[in] re Regular expression to execute.
+ * @param[in] str Target string to search.
+ * @param[in] pos Offset in `str` to start searching, in bytes.
+ * @param[in] dir `pos`' direction; 0 means left-to-right, 1 for
+ * the opposite.
+ * @return Adjusted nearest offset to `pos` inside of `str`, where is a
+ * character boundary.
+ *
+ */
+long rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int dir);
+
+/**
+ * Escapes any characters that would have special meaning in a regular
+ * expression.
+ *
+ * @param[in] str Target string to escape.
+ * @return A copy of `str` whose contents are escaped.
+ */
+VALUE rb_reg_quote(VALUE str);
+
+/**
+ * Exercises various checks and preprocesses so that the given regular
+ * expression can be applied to the given string. The preprocess here includes
+ * (but not limited to) for instance encoding conversion.
+ *
+ * @param[in] re Target regular expression.
+ * @param[in] str What `re` is about to run on.
+ * @exception rb_eArgError `re` does not fit for `str`.
+ * @exception rb_eEncCompatError `re` and `str` are incompatible.
+ * @exception rb_eRegexpError `re` is malformed.
+ * @return A preprocessesed pattern buffer ready to be applied to `str`.
+ * @note The return value is manages by our GC. Don't free.
+ *
+ * @internal
+ *
+ * The return type, `regex_t *`, is defined in `<ruby/onigmo.h>`, _and_
+ * _conflicts_ with POSIX's `<regex.h>`. We can no longer save the situation
+ * at this point. Just don't mix the two.
+ */
regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
-int rb_reg_region_copy(struct re_registers *, const struct re_registers *);
+
+/**
+ * Duplicates a match data. This is roughly the same as `onig_region_copy()`,
+ * except it tries to GC when there is not enough memory.
+ *
+ * @param[out] dst Target registers to fill.
+ * @param[in] src Source registers to duplicate.
+ * @exception rb_eNoMemError Not enough memory.
+ * @retval 0 Successful
+ * @retval ONIGERR_MEMORY Not enough memory, even after GC (unlikely).
+ * @post `dst` has identical contents to `src`.
+ *
+ * @internal
+ *
+ * It seems this function is here for `ext/strscan` and nothing else.
+ */
+int rb_reg_region_copy(struct re_registers *dst, const struct re_registers *src);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/regex.h b/include/ruby/regex.h
index 22dae3231d..53278173f8 100644
--- a/include/ruby/regex.h
+++ b/include/ruby/regex.h
@@ -1,7 +1,6 @@
#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.
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 341a716953..444940ca3a 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -14,6 +14,8 @@
*/
#include "ruby/internal/config.h"
+/* @shyouhei doesn't understand why we need <intrinsics.h> at this very
+ * beginning of the entire <ruby.h> circus. */
#ifdef HAVE_INTRINSICS_H
# include <intrinsics.h>
#endif
@@ -21,6 +23,7 @@
#include <stdarg.h>
#include "defines.h"
+#include "ruby/internal/abi.h"
#include "ruby/internal/anyargs.h"
#include "ruby/internal/arithmetic.h"
#include "ruby/internal/core.h"
@@ -55,19 +58,57 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* Module#methods, #singleton_methods and so on return Symbols */
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define USE_SYMBOL_AS_METHOD_NAME 1
-VALUE rb_get_path(VALUE);
+/**
+ * Converts an object to a path. It first tries `#to_path` method if any, then
+ * falls back to `#to_str` method.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @exception rb_eArgError `obj` contains a NUL byte.
+ * @exception rb_eTypeError `obj` is not path-ish.
+ * @exception rb_eEncCompatError No encoding conversion from `obj` to path.
+ * @return Converted path object.
+ */
+VALUE rb_get_path(VALUE obj);
+
+/**
+ * Ensures that the parameter object is a path.
+ *
+ * @param[in,out] v Arbitrary ruby object.
+ * @exception rb_eArgError `v` contains a NUL byte.
+ * @exception rb_eTypeError `v` is not path-ish.
+ * @exception rb_eEncCompatError `v` is not path-compatible.
+ * @post `v` is a path.
+ */
#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v))
+/**
+ * @deprecated This function is an alias of rb_get_path() now. The part that
+ * did "no_checksafe" was deleted. It remains here because of no
+ * harm.
+ */
VALUE rb_get_path_no_checksafe(VALUE);
+
+/**
+ * @deprecated This macro is an alias of #FilePathValue now. The part that did
+ * "String" was deleted. It remains here because of no harm.
+ */
#define FilePathStringValue(v) ((v) = rb_get_path(v))
+/** @cond INTERNAL_MACRO */
#if defined(HAVE_BUILTIN___BUILTIN_CONSTANT_P) && defined(HAVE_STMT_AND_DECL_IN_EXPR)
# define rb_varargs_argc_check_runtime(argc, vargc) \
(((argc) <= (vargc)) ? (argc) : \
(rb_fatal("argc(%d) exceeds actual arguments(%d)", \
- argc, vargc), 0))
+ argc, vargc), 0))
# define rb_varargs_argc_valid_p(argc, vargc) \
((argc) == 0 ? (vargc) <= 1 : /* [ruby-core:85266] [Bug #14425] */ \
(argc) == (vargc))
@@ -76,64 +117,187 @@ VALUE rb_get_path_no_checksafe(VALUE);
ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int));
# else
# define rb_varargs_bad_length(argc, vargc) \
- ((argc)/rb_varargs_argc_valid_p(argc, vargc))
+ ((argc)/rb_varargs_argc_valid_p(argc, vargc))
# endif
# define rb_varargs_argc_check(argc, vargc) \
__builtin_choose_expr(__builtin_constant_p(argc), \
- (rb_varargs_argc_valid_p(argc, vargc) ? (argc) : \
- rb_varargs_bad_length(argc, vargc)), \
- rb_varargs_argc_check_runtime(argc, vargc))
+ (rb_varargs_argc_valid_p(argc, vargc) ? (argc) : \
+ rb_varargs_bad_length(argc, vargc)), \
+ rb_varargs_argc_check_runtime(argc, vargc))
# else
# define rb_varargs_argc_check(argc, vargc) \
- rb_varargs_argc_check_runtime(argc, vargc)
+ rb_varargs_argc_check_runtime(argc, vargc)
# endif
#endif
+/** @endcond */
-const char *rb_class2name(VALUE);
-const char *rb_obj_classname(VALUE);
+/**
+ * Queries the name of the passed class.
+ *
+ * @param[in] klass An instance of a class.
+ * @return The name of `klass`.
+ * @note Return value is managed by our GC. Don't free.
+ */
+const char *rb_class2name(VALUE klass);
-void rb_p(VALUE);
+/**
+ * Queries the name of the class of the passed object.
+ *
+ * @param[in] obj Arbitrary ruby object.
+ * @return The name of the class of `obj`.
+ * @note Return value is managed by our GC. Don't free.
+ */
+const char *rb_obj_classname(VALUE obj);
+
+/**
+ * Inspects an object. It first calls the argument's `#inspect` method, then
+ * feeds its result string into ::rb_stdout.
+ *
+ * This is identical to Ruby level `Kernel#p`, except it takes only one object.
+ *
+ * @internal
+ *
+ * Above description is in fact inaccurate. This API interfaces with Ractors.
+ */
+void rb_p(VALUE obj);
-VALUE rb_equal(VALUE,VALUE);
+/**
+ * This function is an optimised version of calling `#==`. It checks equality
+ * between two objects by first doing a fast identity check using using C's
+ * `==` (same as `BasicObject#equal?`). If that check fails, it calls `#==`
+ * dynamically. This optimisation actually affects semantics, because when
+ * `#==` returns false for the same object obj, `rb_equal(obj, obj)` would
+ * still return true. This happens for `Float::NAN`, where `Float::NAN ==
+ * Float::NAN` is `false`, but `rb_equal(Float::NAN, Float::NAN)` is `true`.
+ *
+ * @param[in] lhs Comparison LHS.
+ * @param[in] rhs Comparison RHS.
+ * @retval RUBY_Qtrue They are the same.
+ * @retval RUBY_Qfalse They are different.
+ */
+VALUE rb_equal(VALUE lhs, VALUE rhs);
-VALUE rb_require(const char*);
+/**
+ * Identical to rb_require_string(), except it takes C's string instead of
+ * Ruby's.
+ *
+ * @param[in] feature Name of a feature, e.g. `"json"`.
+ * @exception rb_eLoadError No such feature.
+ * @exception rb_eRuntimeError `$"` is frozen; unable to push.
+ * @retval RUBY_Qtrue The feature is loaded for the first time.
+ * @retval RUBY_Qfalse The feature has already been loaded.
+ * @post `$"` is updated.
+ */
+VALUE rb_require(const char *feature);
#include "ruby/intern.h"
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RUBY_VM 1 /* YARV */
+
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define HAVE_NATIVETHREAD
+
+/**
+ * Queries if the thread which calls this function is a ruby's thread.
+ * "Ruby's" in this context is a thread created using one of our APIs like
+ * rb_thread_create(). There are distinctions between ruby's and other
+ * threads. For instance calling ruby methods are allowed only from inside of
+ * a ruby's thread.
+ *
+ * @retval 1 The current thread is a Ruby's thread.
+ * @retval 0 The current thread is a random thread from outside of Ruby.
+ */
int ruby_native_thread_p(void);
+/**
+ * @private
+ *
+ * This macro is for internal use. Must be a mistake to place here.
+ */
#define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();}
-PRINTF_ARGS(int ruby_snprintf(char *str, size_t n, char const *fmt, ...), 3, 4);
+RBIMPL_ATTR_NONNULL((3))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4)
+/**
+ * Our own locale-insensitive version of `snprintf(3)`. It can also be seen as
+ * a routine identical to rb_sprintf(), except it writes back to the passed
+ * buffer instead of allocating a new Ruby object.
+ *
+ * @param[out] str Return buffer
+ * @param[in] n Number of bytes of `str`.
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ... Variadic number of contents to format.
+ * @return Number of bytes that would have been written to `str`, if `n`
+ * was large enough. Comparing this to `n` can give you insights
+ * that the buffer is too small or too big. Especially passing 0
+ * to `n` gives you the exact number of bytes necessary to hold
+ * the result string without writing anything to anywhere.
+ * @post `str` holds up to `n-1` bytes of formatted contents (and the
+ * terminating NUL character.)
+ */
+int ruby_snprintf(char *str, size_t n, char const *fmt, ...);
+
+RBIMPL_ATTR_NONNULL((3))
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0)
+/**
+ * Identical to ruby_snprintf(), except it takes a `va_list`. It can also be
+ * seen as a routine identical to rb_vsprintf(), except it writes back to the
+ * passed buffer instead of allocating a new Ruby object.
+ *
+ * @param[out] str Return buffer
+ * @param[in] n Number of bytes of `str`.
+ * @param[in] fmt A `printf`-like format specifier.
+ * @param[in] ap Contents to format.
+ * @return Number of bytes that would have been written to `str`, if `n`
+ * was large enough. Comparing this to `n` can give you insights
+ * that the buffer is too small or too big. Especially passing 0
+ * to `n` gives you the exact number of bytes necessary to hold
+ * the result string without writing anything to anywhere.
+ * @post `str` holds up to `n-1` bytes of formatted contents (and the
+ * terminating NUL character.)
+ */
int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
+/** @cond INTERNAL_MACRO */
#if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments")
# /* Skip it; clang -pedantic doesn't like the following */
#elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__)
# define rb_yield_values(argc, ...) \
__extension__({ \
- const int rb_yield_values_argc = (argc); \
- const VALUE rb_yield_values_args[] = {__VA_ARGS__}; \
- const int rb_yield_values_nargs = \
- (int)(sizeof(rb_yield_values_args) / sizeof(VALUE)); \
- rb_yield_values2( \
- rb_varargs_argc_check(rb_yield_values_argc, rb_yield_values_nargs), \
- rb_yield_values_nargs ? rb_yield_values_args : NULL); \
+ const int rb_yield_values_argc = (argc); \
+ const VALUE rb_yield_values_args[] = {__VA_ARGS__}; \
+ const int rb_yield_values_nargs = \
+ (int)(sizeof(rb_yield_values_args) / sizeof(VALUE)); \
+ rb_yield_values2( \
+ rb_varargs_argc_check(rb_yield_values_argc, rb_yield_values_nargs), \
+ rb_yield_values_nargs ? rb_yield_values_args : NULL); \
})
# define rb_funcall(recv, mid, argc, ...) \
__extension__({ \
- const int rb_funcall_argc = (argc); \
- const VALUE rb_funcall_args[] = {__VA_ARGS__}; \
- const int rb_funcall_nargs = \
- (int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \
+ const int rb_funcall_argc = (argc); \
+ const VALUE rb_funcall_args[] = {__VA_ARGS__}; \
+ const int rb_funcall_nargs = \
+ (int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \
rb_funcallv(recv, mid, \
- rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \
- rb_funcall_nargs ? rb_funcall_args : NULL); \
+ rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \
+ rb_funcall_nargs ? rb_funcall_args : NULL); \
})
#endif
+/** @endcond */
#ifndef RUBY_DONT_SUBST
#include "ruby/subst.h"
diff --git a/include/ruby/st.h b/include/ruby/st.h
index 1e4bb80686..f35ab43603 100644
--- a/include/ruby/st.h
+++ b/include/ruby/st.h
@@ -98,6 +98,8 @@ struct st_table {
enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK, ST_REPLACE};
+size_t rb_st_table_size(const struct st_table *tbl);
+#define st_table_size rb_st_table_size
st_table *rb_st_init_table(const struct st_hash_type *);
#define st_init_table rb_st_init_table
st_table *rb_st_init_table_with_size(const struct st_hash_type *, st_index_t);
diff --git a/include/ruby/subst.h b/include/ruby/subst.h
index cf48a3909c..d7b9a63050 100644
--- a/include/ruby/subst.h
+++ b/include/ruby/subst.h
@@ -1,7 +1,6 @@
#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
diff --git a/include/ruby/thread.h b/include/ruby/thread.h
index b05537badb..0b5b1ca0f3 100644
--- a/include/ruby/thread.h
+++ b/include/ruby/thread.h
@@ -10,33 +10,226 @@
* 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/attr/nonnull.h"
+#include "ruby/internal/intern/thread.h" /* rb_unblock_function_t */
#include "ruby/internal/dllexport.h"
-/* flags for rb_nogvl */
+/**
+ * @name Flags for rb_nogvl()
+ *
+ * @{
+ */
+
+/**
+ * Passing this flag to rb_nogvl() prevents it from checking interrupts.
+ * Interrupts can impact your program negatively. For instance consider
+ * following callback function:
+ *
+ * ```CXX
+ * static inline int fd; // set elsewhere.
+ * static inline auto callback(auto buf) {
+ * auto tmp = ruby_xmalloc(BUFSIZ);
+ * auto ret = ruby_xmalloc(sizeof(ssize_t)); // (a)
+ * auto n = read(fd, tmp, BUFSIZ); // (b)
+ * memcpy(buf, tmp, n); // (c)
+ * memcpy(ret, n, sizeof(n));
+ * ruby_xfree(tmp);
+ * return ret;
+ * }
+ * ```
+ *
+ * Here, if it gets interrupted at (a) or (b), `read(2)` is cancelled and this
+ * function leaks memory (which is not a good thing of course, but...). But if
+ * it gets interrupted at (c), where `read(2)` is already done, interruption is
+ * way more catastrophic because what was read gets lost. To reroute this kind
+ * of problem you should set this flag. And check interrupts elsewhere at your
+ * own risk.
+ */
#define RB_NOGVL_INTR_FAIL (0x1)
+
+/**
+ * Passing this flag to rb_nogvl() indicates that the passed UBF is
+ * async-signal-safe. An UBF could be async safe, and that makes things
+ * simpler. However async unsafe UBFs are just okay. If unsure, you can
+ * safely leave it unspecified.
+ *
+ * @internal
+ *
+ * This makes sense only in case of POSIX threads.
+ */
#define RB_NOGVL_UBF_ASYNC_SAFE (0x2)
+/** @} */
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * (Re-)acquires the GVL. This manoeuvre makes it possible for an out-of-GVL
+ * routine to one-shot call a ruby method.
+ *
+ * What this function does:
+ *
+ * 1. Blocks until it acquires the GVL.
+ * 2. Calls the passed function.
+ * 3. Releases the GVL.
+ * 4. Returns what was returned form the passed function.
+ *
+ * @param[in] func What to call with GVL.
+ * @param[in,out] data1 Passed as-is to `func`.
+ * @return What was returned from `func`.
+ * @warning `func` must not return a Ruby object. If it did such return
+ * value would escape from GC's scope; would not be marked.
+ * @warning Global escapes from this function just yield whatever fatal
+ * undefined behaviours. You must make sure that `func` does
+ * not raise, by properly rescuing everything using
+ * e.g. rb_protect().
+ * @warning You cannot convert a non-Ruby thread into a Ruby thread
+ * using this API. This function makes sense only from inside
+ * of a rb_thread_call_without_gvl()'s callback.
+ */
void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Allows the passed function to run in parallel with other Ruby threads.
+ *
+ * What this function does:
+ *
+ * 1. Checks (and handles) pending interrupts.
+ * 2. Releases the GVL. (Others can run here in parallel...)
+ * 3. Calls the passed function.
+ * 4. Blocks until it re-acquires the GVL.
+ * 5. Checks interrupts that happened between 2 to 4.
+ *
+ * In case other threads interfaced with this thread using rb_thread_kill()
+ * etc., the passed UBF is additionally called. See ::rb_unblock_function_t
+ * for details.
+ *
+ * Unlike rb_thread_call_without_gvl2() this function also reacts to signals
+ * etc.
+ *
+ * @param[in] func A function to call without GVL.
+ * @param[in,out] data1 Passed as-is to `func`.
+ * @param[in] ubf An UBF to cancel `func`.
+ * @param[in,out] data2 Passed as-is to `ubf`.
+ * @return What `func` returned, or 0 in case `ubf` cancelled `func`.
+ * @warning You cannot use most of Ruby C APIs like calling methods or
+ * raising exceptions from any of the functions passed to it.
+ * If that is dead necessary use rb_thread_call_with_gvl() to
+ * re-acquire the GVL.
+ * @warning In short, this API is difficult. @ko1 recommends you to use
+ * other ways if any. We lack experiences to use this API. If
+ * you find any corner cases etc., please report it to the
+ * devs.
+ * @warning Releasing and re-acquiring the GVL are expensive operations.
+ * For a short-running `func`, it might be faster to just call
+ * `func` with blocking everything else. Be sure to benchmark
+ * your code to see if it is actually worth releasing the GVL.
+ */
void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
- rb_unblock_function_t *ubf, void *data2);
+ rb_unblock_function_t *ubf, void *data2);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_thread_call_without_gvl(), except it does not interface with
+ * signals etc. As described in #RB_NOGVL_INTR_FAIL, interrupts can hurt you.
+ * In case this function detects an interrupt, it returns immediately. You can
+ * record progress of your callback and check it after returning from this
+ * function.
+ *
+ * What this function does:
+ *
+ * 1. Checks for pending interrupts and if any, just returns.
+ * 2. Releases the GVL. (Others can run here in parallel...)
+ * 3. Calls the passed function.
+ * 4. Blocks until it re-acquires the GVL.
+ *
+ * @param[in] func A function to call without GVL.
+ * @param[in,out] data1 Passed as-is to `func`.
+ * @param[in] ubf An UBF to cancel `func`.
+ * @param[in,out] data2 Passed as-is to `ubf`.
+ * @return What `func` returned, or 0 in case `func` did not return.
+ */
void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1,
- rb_unblock_function_t *ubf, void *data2);
+ rb_unblock_function_t *ubf, void *data2);
/*
* XXX: unstable/unapproved - out-of-tree code should NOT not depend
* on this until it hits Ruby 2.6.1
*/
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Identical to rb_thread_call_without_gvl(), except it additionally takes
+ * "flags" that change the behaviour.
+ *
+ * @param[in] func A function to call without GVL.
+ * @param[in,out] data1 Passed as-is to `func`.
+ * @param[in] ubf An UBF to cancel `func`.
+ * @param[in,out] data2 Passed as-is to `ubf`.
+ * @param[in] flags Flags.
+ * @return What `func` returned, or 0 in case `func` did not return.
+ */
void *rb_nogvl(void *(*func)(void *), void *data1,
rb_unblock_function_t *ubf, void *data2,
int flags);
+/**
+ * @private
+ *
+ * @deprecated This macro once was a thing in the old days, but makes no sense
+ * any longer today. Exists here for backwards compatibility
+ * only. You can safely forget about it.
+ */
#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_AFTER 0x01
+
+/**
+ * @private
+ * @deprecated It seems even in the old days it made no sense...?
+ */
#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_
+#define RUBY_INTERNAL_THREAD_EVENT_STARTED 1 << 0 /** thread started */
+#define RUBY_INTERNAL_THREAD_EVENT_READY 1 << 1 /** acquiring GVL */
+#define RUBY_INTERNAL_THREAD_EVENT_RESUMED 1 << 2 /** acquired GVL */
+#define RUBY_INTERNAL_THREAD_EVENT_SUSPENDED 1 << 3 /** released GVL */
+#define RUBY_INTERNAL_THREAD_EVENT_EXITED 1 << 4 /** thread terminated */
+#define RUBY_INTERNAL_THREAD_EVENT_MASK 0xff /** All Thread events */
+
+typedef void rb_internal_thread_event_data_t; // for future extension.
+
+typedef void (*rb_internal_thread_event_callback)(rb_event_flag_t event,
+ const rb_internal_thread_event_data_t *event_data,
+ void *user_data);
+typedef struct rb_internal_thread_event_hook rb_internal_thread_event_hook_t;
+
+/**
+ * Registers a thread event hook function.
+ *
+ * @param[in] func A callback.
+ * @param[in] events A set of events that `func` should run.
+ * @param[in] data Passed as-is to `func`.
+ * @return An opaque pointer to the hook, to unregister it later.
+ * @note This functionality is a noop on Windows.
+ * @warning This function MUST not be called from a thread event callback.
+ */
+rb_internal_thread_event_hook_t *rb_internal_thread_add_event_hook(
+ rb_internal_thread_event_callback func, rb_event_flag_t events,
+ void *data);
+
+
+/**
+ * Unregister the passed hook.
+ *
+ * @param[in] hook. The hook to unregister.
+ * @return Wether the hook was found and unregistered.
+ * @note This functionality is a noop on Windows.
+ * @warning This function MUST not be called from a thread event callback.
+*/
+bool rb_internal_thread_remove_event_hook(
+ rb_internal_thread_event_hook_t * hook);
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_THREAD_H */
diff --git a/include/ruby/thread_native.h b/include/ruby/thread_native.h
index 343c02c30d..c23b15e133 100644
--- a/include/ruby/thread_native.h
+++ b/include/ruby/thread_native.h
@@ -9,9 +9,7 @@
* Permission is hereby granted, 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.
*
@@ -21,7 +19,6 @@
* please use Mutex directly.
*/
-
#if defined(_WIN32)
#include <windows.h>
typedef HANDLE rb_nativethread_id_t;
@@ -40,33 +37,169 @@ typedef pthread_t rb_nativethread_id_t;
typedef pthread_mutex_t rb_nativethread_lock_t;
typedef pthread_cond_t rb_nativethread_cond_t;
+#elif defined(__wasi__) // no-thread platforms
+
+typedef struct rb_nativethread_id_t *rb_nativethread_id_t;
+typedef struct rb_nativethread_lock_t *rb_nativethread_lock_t;
+typedef struct rb_nativethread_cond_t *rb_nativethread_cond_t;
+
+#elif defined(__DOXYGEN__)
+
+/** Opaque type that holds an ID of a native thread. */
+struct rb_nativethread_id_t;
+
+/** Opaque type that holds a lock. */
+struct rb_nativethread_lock_t;
+
+/** Opaque type that holds a condition variable. */
+struct rb_nativethread_cond_t;
+
#else
#error "unsupported thread type"
#endif
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+/**
+ * Queries the ID of the native thread that is calling this function.
+ *
+ * @return The caller thread's native ID.
+ */
rb_nativethread_id_t rb_nativethread_self(void);
+/**
+ * Fills the passed lock with an initial value.
+ *
+ * @param[out] lock A mutex to initialise.
+ * @post `lock` is updated to its initial state.
+ *
+ * @internal
+ *
+ * There is no data structure that analogous to pthread_once_t in ruby. It is
+ * pretty much tricky (if not impossible) to properly initialise a mutex
+ * exactly once.
+ */
void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock);
+
+/**
+ * Destroys the passed mutex.
+ *
+ * @param[out] lock A mutex to kill.
+ * @post `lock` is no longer eligible for other functions.
+ *
+ * @internal
+ *
+ * It is an undefined behaviour (see `pthread_mutex_destroy(3posix)`) to
+ * destroy a locked mutex. So it has to be unlocked. But an unlocked mutex
+ * can of course be locked by another thread. That's the ultimate reason why
+ * we do mutex. There is an inevitable race condition here. 2017 edition of
+ * IEEE 1003.1 issue 7 says in its rationale that "care must be taken". Care?
+ * How?
+ *
+ * @shyouhei thinks that POSIX is broken by design.
+ */
void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock);
+
+/**
+ * Blocks until the current thread obtains a lock.
+ *
+ * @param[out] lock A mutex to lock.
+ * @post `lock` is owned by the current native thread.
+ */
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock);
+
+/**
+ * Releases a lock.
+ *
+ * @param[out] lock A mutex to unlock.
+ * @pre `lock` is owned by the current native thread.
+ * @post `lock` is not owned by the current native thread.
+ */
void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock);
+/** @alias{rb_nativethread_lock_lock} */
void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
+
+/**
+ * Identical to rb_native_mutex_lock(), except it doesn't block in case
+ * rb_native_mutex_lock() would.
+ *
+ * @param[out] lock A mutex to lock.
+ * @retval 0 `lock` is successfully owned by the current thread.
+ * @retval EBUSY `lock` is owned by someone else.
+ */
int rb_native_mutex_trylock(rb_nativethread_lock_t *lock);
+
+/** @alias{rb_nativethread_lock_unlock} */
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
+
+/** @alias{rb_nativethread_lock_initialize} */
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock);
+
+/** @alias{rb_nativethread_lock_destroy} */
void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
+/**
+ * Signals a condition variable.
+ *
+ * @param[out] cond A condition variable to ping.
+ * @post More than one threads waiting for `cond` gets signalled.
+ * @note This function can spuriously wake multiple threads up.
+ * `pthread_cond_signal(3posix)` says it can even be "impossible
+ * to avoid the unblocking of more than one thread blocked on a
+ * condition variable". Just brace spurious wakeups.
+ */
void rb_native_cond_signal(rb_nativethread_cond_t *cond);
+
+/**
+ * Signals a condition variable.
+ *
+ * @param[out] cond A condition variable to ping.
+ * @post All threads waiting for `cond` gets signalled.
+ */
void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
+
+/**
+ * Waits for the passed condition variable to be signalled.
+ *
+ * @param[out] cond A condition variable to wait.
+ * @param[out] mutex A mutex.
+ * @pre `mutex` is owned by the current thread.
+ * @post `mutex` is owned by the current thread.
+ * @note This can wake up spuriously.
+ */
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
+
+/**
+ * Identical to rb_native_cond_wait(), except it additionally takes timeout in
+ * msec resolution. Timeouts can be detected by catching exceptions.
+ *
+ * @param[out] cond A condition variable to wait.
+ * @param[out] mutex A mutex.
+ * @param[in] msec Timeout.
+ * @exception rb_eSystemCallError `Errno::ETIMEDOUT` for timeout.
+ * @pre `mutex` is owned by the current thread.
+ * @post `mutex` is owned by the current thread.
+ * @note This can wake up spuriously.
+ */
void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec);
+
+/**
+ * Fills the passed condition variable with an initial value.
+ *
+ * @param[out] cond A condition variable to initialise.
+ * @post `cond` is updated to its initial state.
+ */
void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
-void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
-RUBY_SYMBOL_EXPORT_END
+/**
+ * Destroys the passed condition variable.
+ *
+ * @param[out] cond A condition variable to kill.
+ * @post `cond` is no longer eligible for other functions.
+ */
+void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
+RBIMPL_SYMBOL_EXPORT_END()
#endif
diff --git a/include/ruby/util.h b/include/ruby/util.h
index af022dacbd..e8727a3200 100644
--- a/include/ruby/util.h
+++ b/include/ruby/util.h
@@ -9,42 +9,219 @@
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
+ * @warning DO NOT ADD RANDOM GARBAGES IN THIS FILE! Contents of this file
+ * reside here for historical reasons. Find a right place for your
+ * API!
*/
#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h> /* size_t */
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* ssize_t */
+#endif
+
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/nodiscard.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/restrict.h"
+#include "ruby/internal/attr/returns_nonnull.h"
#include "ruby/internal/dllexport.h"
#include "ruby/defines.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
+/** an approximation of ceil(n * log10(2)), up to 65536 at least */
#define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999)
-/* an approximation of ceil(n * log10(2)), up to 65536 at least */
+/**
+ * Character to number mapping like `'a'` -> `10`, `'b'` -> `11` etc. For
+ * punctuation etc., the value is -1. "36" terminology comes from the fact
+ * that this is the table behind `str.to_i(36)`.
+ */
+RUBY_EXTERN const signed char ruby_digit36_to_number_table[];
+
+/**
+ * Characters that Ruby accepts as hexadecimal digits. This is `/\h/` expanded
+ * into an array.
+ */
+RUBY_EXTERN const char ruby_hexdigits[];
+
+/**
+ * Scans the passed string, assuming the string is a textual representation of
+ * an integer. Stops when encountering something non-digit for the passed
+ * base.
+ *
+ * @note This does not understand minus sign.
+ * @note This does not understand e.g. `0x` prefix.
+ * @note It is a failure to pass `0` to `base`, unlike ruby_strtoul().
+ * @param[in] str Target string of digits to interpret.
+ * @param[in] len Number of bytes of `str`, or -1 to detect `NUL`.
+ * @param[in] base Base, `2` to `36` inclusive.
+ * @param[out] retlen Return value buffer.
+ * @param[out] overflow Return value buffer.
+ * @return Interpreted numeric representation of `str`.
+ * @post `retlen` is the number of bytes scanned so far.
+ * @post `overflow` is set to true if the string represents something
+ * bigger than `ULONG_MAX`. Something meaningful still returns;
+ * which is the designed belabour of C's unsigned arithmetic.
+ */
+unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
+
+/** @old{ruby_scan_oct} */
#define scan_oct(s,l,e) ((int)ruby_scan_oct((s),(l),(e)))
-unsigned long ruby_scan_oct(const char *, size_t, size_t *);
+
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Interprets the passed string as an octal unsigned integer. Stops when
+ * encounters something not understood.
+ *
+ * @param[in] str C string to scan.
+ * @param[in] len Length of `str`.
+ * @param[out] consumed Return value buffer.
+ * @return Parsed integer.
+ * @post `ret` is the number of characters read.
+ *
+ * @internal
+ *
+ * No consideration is made for integer overflows. As the return value is
+ * unsigned this function has fully defined behaviour, but you cannot know if
+ * there was an integer wrap-around or not.
+ */
+unsigned long ruby_scan_oct(const char *str, size_t len, size_t *consumed);
+
+/** @old{ruby_scan_hex} */
#define scan_hex(s,l,e) ((int)ruby_scan_hex((s),(l),(e)))
-unsigned long ruby_scan_hex(const char *, size_t, size_t *);
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Interprets the passed string a hexadecimal unsigned integer. Stops when
+ * encounters something not understood.
+ *
+ * @param[in] str C string to scan.
+ * @param[in] len Length of `str`.
+ * @param[out] ret Return value buffer.
+ * @return Parsed integer.
+ * @post `ret` is the number of characters read.
+ *
+ * @internal
+ *
+ * No consideration is made for integer overflows. As the return value is
+ * unsigned this function has fully defined behaviour, but you cannot know if
+ * there was an integer wrap-around or not.
+ */
+unsigned long ruby_scan_hex(const char *str, size_t len, size_t *ret);
+
+/**
+ * Reentrant implementation of quick sort. If your system provides something
+ * (like C11 qsort_s), this is a thin wrapper of that routine. Otherwise
+ * resorts to our own version.
+ */
#ifdef HAVE_GNU_QSORT_R
# define ruby_qsort qsort_r
#else
void ruby_qsort(void *, const size_t, const size_t,
- int (*)(const void *, const void *, void *), void *);
+ int (*)(const void *, const void *, void *), void *);
#endif
-void ruby_setenv(const char *, const char *);
-void ruby_unsetenv(const char *);
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Sets an environment variable. In case of POSIX this is a wrapper of
+ * `setenv(3)`. But there are systems which lack one. We try hard emulating.
+ *
+ * @param[in] key An environment variable.
+ * @param[in] val A value to be associated with `key`, or 0.
+ * @exception rb_eSystemCallError `setenv(3)` failed for some reason.
+ * @post Environment variable `key` is created if necessary. Its value
+ * is updated to be `val`.
+ */
+void ruby_setenv(const char *key, const char *val);
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Deletes the passed environment variable, if any.
+ *
+ * @param[in] key An environment variable.
+ * @exception rb_eSystemCallError `unsetenv(3)` failed for some reason.
+ * @post Environment variable `key` does not exist.
+ */
+void ruby_unsetenv(const char *key);
+
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * This is our own version of `strdup(3)` that uses ruby_xmalloc() instead of
+ * system malloc (benefits our GC).
+ *
+ * @param[in] str Target C string to duplicate.
+ * @return An allocated C string holding the identical contents.
+ * @note Return value must be discarded using ruby_xfree().
+ */
+char *ruby_strdup(const char *str);
-char *ruby_strdup(const char *);
#undef strdup
+/**
+ * @alias{ruby_strdup}
+ *
+ * @internal
+ *
+ * @shyouhei doesn't think it is a wise idea. ruby_strdup()'s return value
+ * must be passed to ruby_xfree(), but this macro makes it almost impossible.
+ */
#define strdup(s) ruby_strdup(s)
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+/**
+ * This is our own version of `getcwd(3)` that uses ruby_xmalloc() instead of
+ * system malloc (benefits our GC).
+ *
+ * @return An allocated C string holding the process working directory.
+ * @note Return value must be discarded using ruby_xfree().
+ */
char *ruby_getcwd(void);
-double ruby_strtod(const char *, char **);
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Our own locale-insensitive version of `strtod(3)`. The conversion is done
+ * as if the current locale is set to the "C" locale, no matter actual runtime
+ * locale settings.
+ *
+ * @param[in] str Decimal or hexadecimal representation of a floating
+ * point number.
+ * @param[out] endptr NULL, or an arbitrary pointer (overwritten on return).
+ * @return Converted number.
+ * @post If `endptr` is not NULL, it is updated to point the first such
+ * byte where conversion failed.
+ * @note This function sets `errno` on failure.
+ * - `ERANGE`: Converted integer is out of range of `double`.
+ * @see William D. Clinger, "How to Read Floating Point Numbers
+ * Accurately" in Proc. ACM SIGPLAN '90, pp. 92-101.
+ * https://doi.org/10.1145/93542.93557
+ */
+double ruby_strtod(const char *str, char **endptr);
+
#undef strtod
+/** @alias{ruby_strtod} */
#define strtod(s,e) ruby_strtod((s),(e))
-void ruby_each_words(const char *, void (*)(const char*, int, void*), void *);
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * Scans the passed string, with calling the callback function every time it
+ * encounters a "word". A word here is a series of characters separated by
+ * either a space (of IEEE 1003.1 section 7.3.1.1), or a `','`.
+ *
+ * @param[in] str Target string to split into each words.
+ * @param[in] func Callback function.
+ * @param[in,out] argv Passed as-is to `func`.
+ */
+void ruby_each_words(const char *str, void (*func)(const char *word, int len, void *argv), void *argv);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/version.h b/include/ruby/version.h
index d25008fad9..18b3abc8d7 100644
--- a/include/ruby/version.h
+++ b/include/ruby/version.h
@@ -20,40 +20,139 @@
* check the features with mkmf.rb instead.
*/
-/* The origin. */
+/**
+ * @name The origin.
+ *
+ * These information never change. Just written here to remember.
+ *
+ * @{
+ */
+
+/** Author of this project. */
#define RUBY_AUTHOR "Yukihiro Matsumoto"
+
+/** Ruby's birth year. */
#define RUBY_BIRTH_YEAR 1993
+
+/** Ruby's birth month. */
#define RUBY_BIRTH_MONTH 2
+
+/** Ruby's birth day. */
#define RUBY_BIRTH_DAY 24
-/* API version */
+/** @} */
+
+/**
+ * @name The API version.
+ *
+ * API version is different from binary version. These numbers are for API
+ * stability. When you have distinct API versions x and y, you cannot expect
+ * codes targeted to x also works for y.
+ *
+ * However let us repeat here that it's a BAD idea to check
+ * #RUBY_API_VERSION_CODE form extension libraries. Different API versions are
+ * just different. There is no such thing like upper compatibility.
+ *
+ * @{
+ */
+
+/**
+ * Major version. This digit changes sometimes for various reasons, but that
+ * doesn't mean a total rewrite. Practically when it comes to API versioning,
+ * major and minor version changes are equally catastrophic.
+ */
#define RUBY_API_VERSION_MAJOR 3
-#define RUBY_API_VERSION_MINOR 1
+
+/**
+ * Minor version. As of writing this version changes annually. Greater
+ * version doesn't mean "better"; they just mean years passed.
+ */
+#define RUBY_API_VERSION_MINOR 2
+
+/**
+ * Teeny version. This digit is kind of reserved these days. Kept 0 for the
+ * entire 2.x era. Waiting for future uses.
+ */
#define RUBY_API_VERSION_TEENY 0
+
+/**
+ * This macro is API versions encoded into a C integer.
+ *
+ * @note Use mkmf.
+ * @note Don't rely on it.
+ */
#define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY)
+/** @} */
+
#ifdef RUBY_EXTERN
/* Internal note: this file could be included from verconf.mk _before_
* generating config.h, on Windows. The #ifdef above is to trick such
* situation. */
RBIMPL_SYMBOL_EXPORT_BEGIN()
-/*
- * Interfaces from extension libraries.
+/**
+ * @name Interfaces from extension libraries.
*
* Before using these infos, think thrice whether they are really
* necessary or not, and if the answer was yes, think twice a week
* later again.
+ *
+ * @{
*/
+
+/** API versions, in { major, minor, teeny } order. */
RUBY_EXTERN const int ruby_api_version[3];
+
+/**
+ * Stringised version.
+ *
+ * @note This is the runtime version, not the API version. For instance it
+ * was `"2.5.9"` when ::ruby_api_version was `{ 2, 5, 0 }`.
+ */
RUBY_EXTERN const char ruby_version[];
+
+/** Date of release, in a C string. */
RUBY_EXTERN const char ruby_release_date[];
+
+/**
+ * Target platform identifier, in a C string.
+ *
+ * @note Seasoned UNIX programmers should beware that this "platform
+ * identifier" is our invention; not always identical to so-called
+ * target triplets that GNU systems use. For instance on @shyouhei's
+ * machine, ::ruby_platform is `"x64_64-linux"` while its target triplet
+ * is `x86_64-pc-linux-gnu`.
+ * @note Note also that we support Windows.
+ */
RUBY_EXTERN const char ruby_platform[];
+
+/**
+ * This is a monotonic increasing integer that describes specific "patch"
+ * level. You can know the exact changeset your binary is running by this info
+ * (and ::ruby_version), unless this is -1. -1 means there is no release yet
+ * for the version; ruby is actively developed. 0 means the initial GA version.
+ */
RUBY_EXTERN const int ruby_patchlevel;
+
+/**
+ * This is what `ruby -v` prints to the standard error. Something like:
+ * `"ruby 2.5.9p229 (2021-04-05 revision 67829) [x86_64-linux]"`. This doesn't
+ * include runtime options like a JIT being enabled.
+ */
RUBY_EXTERN const char ruby_description[];
+
+/** Copyright notice. */
RUBY_EXTERN const char ruby_copyright[];
+
+/**
+ * This is just `"ruby"` for us. But different implementations can have
+ * different strings here.
+ */
RUBY_EXTERN const char ruby_engine[];
+/** @} */
+
RBIMPL_SYMBOL_EXPORT_END()
#endif
diff --git a/include/ruby/vm.h b/include/ruby/vm.h
index 7bdd567453..3458c28be7 100644
--- a/include/ruby/vm.h
+++ b/include/ruby/vm.h
@@ -9,21 +9,26 @@
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
+ *
+ * We planned to have multiple VMs run side-by-side. The API here was a
+ * preparation of that feature. The topic branch was eventually abandoned, and
+ * we now have Ractor. This file is kind of obsolescent.
*/
#include "ruby/internal/dllexport.h"
RBIMPL_SYMBOL_EXPORT_BEGIN()
-/* Place holder.
- *
- * We will prepare VM creation/control APIs on 1.9.2 or later.
- *
+/**
+ * The opaque struct to hold VM internals. Its fields are intentionally hidden
+ * from extension libraries because it changes drastically time to time.
*/
-
-/* VM type declaration */
typedef struct rb_vm_struct ruby_vm_t;
-/* core API */
+/**
+ * Destructs the passed VM. You don't have to call this API directly now,
+ * because there is no way to create one. There is only one VM at one time.
+ * ruby_stop() should just suffice.
+ */
int ruby_vm_destruct(ruby_vm_t *vm);
/**
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 4978655e3c..18de3a17d8 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -19,11 +19,6 @@ RUBY_SYMBOL_EXPORT_BEGIN
*/
/*
- * Definitions for NT port of Perl
- */
-
-
-/*
* Ok now we can include the normal include files.
*/
@@ -130,8 +125,15 @@ typedef unsigned int uintptr_t;
#define O_SHARE_DELETE 0x20000000 /* for rb_w32_open(), rb_w32_wopen() */
typedef int clockid_t;
+#if defined(__MINGW32__)
+#undef CLOCK_PROCESS_CPUTIME_ID
+#undef CLOCK_THREAD_CPUTIME_ID
+#undef CLOCK_REALTIME_COARSE
+#endif
+#if defined(HAVE_CLOCK_GETTIME) && !defined(CLOCK_REALTIME)
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
+#endif
#undef utime
#undef lseek
@@ -155,10 +157,14 @@ typedef int clockid_t;
#define read(f, b, s) rb_w32_read(f, b, s)
#define write(f, b, s) rb_w32_write(f, b, s)
#define getpid() rb_w32_getpid()
+#undef HAVE_GETPPID
+#define HAVE_GETPPID 1
#define getppid() rb_w32_getppid()
#define sleep(x) rb_w32_Sleep((x)*1000)
#define Sleep(msec) (void)rb_w32_Sleep(msec)
+#undef HAVE_EXECV
+#define HAVE_EXECV 1
#undef execv
#define execv(path,argv) rb_w32_uaspawn(P_OVERLAY,path,argv)
#undef isatty
@@ -191,7 +197,6 @@ struct stati128 {
long st_ctimensec;
};
-#define off_t __int64
#define stat stati128
#undef SIZEOF_STRUCT_STAT_ST_INO
#define SIZEOF_STRUCT_STAT_ST_INO sizeof(unsigned __int64)
@@ -299,7 +304,6 @@ extern DWORD rb_w32_osver(void);
extern int rb_w32_uchown(const char *, int, int);
extern int rb_w32_ulink(const char *, const char *);
extern ssize_t rb_w32_ureadlink(const char *, char *, size_t);
-extern ssize_t rb_w32_wreadlink(const WCHAR *, WCHAR *, size_t);
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 *);
@@ -309,7 +313,9 @@ extern rb_pid_t wait(int *);
extern rb_pid_t rb_w32_uspawn(int, const char *, const char*);
extern rb_pid_t rb_w32_uaspawn(int, const char *, char *const *);
extern rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD);
-extern int kill(int, int);
+#undef HAVE_KILL
+#define HAVE_KILL 1
+extern int kill(rb_pid_t, int);
extern int fcntl(int, int, ...);
extern int rb_w32_set_nonblock(int);
extern rb_pid_t rb_w32_getpid(void);
@@ -343,14 +349,6 @@ rb_infinity_float(void)
#endif
#if !defined __MINGW32__ || defined __NO_ISOCEXT
-#ifndef isnan
-#define isnan(x) _isnan(x)
-#endif
-static inline int
-finite(double x)
-{
- return _finite(x);
-}
#ifndef copysign
#define copysign(a, b) _copysign(a, b)
#endif
@@ -359,8 +357,6 @@ scalb(double a, long b)
{
return _scalb(a, b);
}
-#else
-__declspec(dllimport) extern int finite(double);
#endif
#if !defined S_IFIFO && defined _S_IFIFO
@@ -398,6 +394,7 @@ __declspec(dllimport) extern int finite(double);
#endif
#define S_IFLNK 0xa000
+#define S_IFSOCK 0xc000
/*
* define this so we can do inplace editing
@@ -405,9 +402,9 @@ __declspec(dllimport) extern int finite(double);
#define SUFFIX
-extern int rb_w32_ftruncate(int fd, off_t length);
-extern int rb_w32_truncate(const char *path, off_t length);
-extern int rb_w32_utruncate(const char *path, off_t length);
+extern int rb_w32_ftruncate(int fd, rb_off_t length);
+extern int rb_w32_truncate(const char *path, rb_off_t length);
+extern int rb_w32_utruncate(const char *path, rb_off_t length);
#undef HAVE_FTRUNCATE
#define HAVE_FTRUNCATE 1
@@ -657,6 +654,8 @@ extern char *rb_w32_strerror(int);
#undef setsockopt
#define setsockopt(s, v, n, o, l) rb_w32_setsockopt(s, v, n, o, l)
+#undef HAVE_SHUTDOWN
+#define HAVE_SHUTDOWN 1
#undef shutdown
#define shutdown(s, h) rb_w32_shutdown(s, h)
@@ -704,10 +703,10 @@ extern char *rb_w32_strerror(int);
#endif
struct tms {
- long tms_utime;
- long tms_stime;
- long tms_cutime;
- long tms_cstime;
+ long tms_utime;
+ long tms_stime;
+ long tms_cutime;
+ long tms_cstime;
};
int rb_w32_times(struct tms *);
@@ -724,7 +723,7 @@ int rb_w32_fclose(FILE*);
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);
+rb_off_t rb_w32_lseek(int, rb_off_t, int);
int rb_w32_uutime(const char *, const struct utimbuf *);
int rb_w32_uutimes(const char *, const struct timeval *);
int rb_w32_uutimensat(int /* must be AT_FDCWD */, const char *, const struct timespec *, int /* must be 0 */);
@@ -806,6 +805,25 @@ double rb_w32_pow(double x, double y);
#define pow rb_w32_pow
#endif
+// mmap tiny emulation
+#define MAP_FAILED ((void *)-1)
+
+#define PROT_READ 0x01
+#define PROT_WRITE 0x02
+#define PROT_EXEC 0x04
+
+#define MAP_PRIVATE 0x0002
+#define MAP_ANON 0x1000
+#define MAP_ANONYMOUS MAP_ANON
+
+extern void *rb_w32_mmap(void *, size_t, int, int, int, rb_off_t);
+extern int rb_w32_munmap(void *, size_t);
+extern int rb_w32_mprotect(void *, size_t, int);
+
+#define mmap(a, l, p, f, d, o) rb_w32_mmap(a, l, p, f, d, o)
+#define munmap(a, l) rb_w32_munmap(a, l)
+#define mprotect(a, l, prot) rb_w32_mprotect(a, l, prot)
+
#if defined(__cplusplus)
#if 0
{ /* satisfy cc-mode */
diff --git a/inits.c b/inits.c
index 3e04c26111..e809b56cc9 100644
--- a/inits.c
+++ b/inits.c
@@ -20,6 +20,7 @@ static void Init_builtin_prelude(void);
void
rb_call_inits(void)
{
+ CALL(default_shapes);
CALL(Thread_Mutex);
#if USE_TRANSIENT_HEAP
CALL(TransientHeap);
@@ -51,6 +52,7 @@ rb_call_inits(void)
CALL(marshal);
CALL(Range);
CALL(IO);
+ CALL(IO_Buffer)
CALL(Dir);
CALL(Time);
CALL(Random);
@@ -76,6 +78,7 @@ rb_call_inits(void)
CALL(vm_stack_canary);
CALL(ast);
CALL(gc_stress);
+ CALL(shape);
// enable builtin loading
CALL(builtin);
@@ -96,8 +99,16 @@ rb_call_builtin_inits(void)
BUILTIN(warning);
BUILTIN(array);
BUILTIN(kernel);
+ BUILTIN(symbol);
BUILTIN(timev);
+ BUILTIN(thread_sync);
+ BUILTIN(yjit);
BUILTIN(nilclass);
+ BUILTIN(marshal);
+#if USE_MJIT
+ BUILTIN(mjit);
+ BUILTIN(mjit_c);
+#endif
Init_builtin_prelude();
}
#undef CALL
diff --git a/insns.def b/insns.def
index 0b741af504..9f5ee7095a 100644
--- a/insns.def
+++ b/insns.def
@@ -109,14 +109,14 @@ getblockparam
VM_ASSERT(VM_ENV_LOCAL_P(ep));
if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) {
- val = rb_vm_bh_to_procval(ec, VM_ENV_BLOCK_HANDLER(ep));
- vm_env_write(ep, -(int)idx, val);
- VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
+ val = rb_vm_bh_to_procval(ec, VM_ENV_BLOCK_HANDLER(ep));
+ vm_env_write(ep, -(int)idx, val);
+ VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
}
else {
- val = *(ep - idx);
- RB_DEBUG_COUNTER_INC(lvar_get);
- (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
+ val = *(ep - idx);
+ RB_DEBUG_COUNTER_INC(lvar_get);
+ (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
}
}
@@ -150,35 +150,35 @@ getblockparamproxy
VM_ASSERT(VM_ENV_LOCAL_P(ep));
if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) {
- VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
-
- if (block_handler) {
- switch (vm_block_handler_type(block_handler)) {
- case block_handler_type_iseq:
- case block_handler_type_ifunc:
- val = rb_block_param_proxy;
- break;
- case block_handler_type_symbol:
- val = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
- goto INSN_LABEL(set);
- case block_handler_type_proc:
- val = VM_BH_TO_PROC(block_handler);
- goto INSN_LABEL(set);
- default:
- VM_UNREACHABLE(getblockparamproxy);
- }
- }
- else {
- val = Qnil;
- INSN_LABEL(set):
- vm_env_write(ep, -(int)idx, val);
- VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
- }
+ VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
+
+ if (block_handler) {
+ switch (vm_block_handler_type(block_handler)) {
+ case block_handler_type_iseq:
+ case block_handler_type_ifunc:
+ val = rb_block_param_proxy;
+ break;
+ case block_handler_type_symbol:
+ val = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
+ goto INSN_LABEL(set);
+ case block_handler_type_proc:
+ val = VM_BH_TO_PROC(block_handler);
+ goto INSN_LABEL(set);
+ default:
+ VM_UNREACHABLE(getblockparamproxy);
+ }
+ }
+ else {
+ val = Qnil;
+ INSN_LABEL(set):
+ vm_env_write(ep, -(int)idx, val);
+ VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
+ }
}
else {
- val = *(ep - idx);
- RB_DEBUG_COUNTER_INC(lvar_get);
- (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
+ val = *(ep - idx);
+ RB_DEBUG_COUNTER_INC(lvar_get);
+ (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
}
}
@@ -230,28 +230,50 @@ setinstancevariable
/* Get value of class variable id of klass as val. */
DEFINE_INSN
getclassvariable
-(ID id, IVC ic)
+(ID id, ICVARC ic)
()
(VALUE val)
/* "class variable access from toplevel" warning can be hooked. */
// attr bool leaf = false; /* has rb_warning() */
{
- rb_cref_t * cref = vm_get_cref(GET_EP());
rb_control_frame_t *cfp = GET_CFP();
- val = vm_getclassvariable(GET_ISEQ(), cref, cfp, id, (ICVARC)ic);
+ val = vm_getclassvariable(GET_ISEQ(), cfp, id, ic);
}
/* Set value of class variable id of klass as val. */
DEFINE_INSN
setclassvariable
-(ID id, IVC ic)
+(ID id, ICVARC ic)
(VALUE val)
()
/* "class variable access from toplevel" warning can be hooked. */
// attr bool leaf = false; /* has rb_warning() */
{
vm_ensure_not_refinement_module(GET_SELF());
- vm_setclassvariable(GET_ISEQ(), vm_get_cref(GET_EP()), GET_CFP(), id, val, (ICVARC)ic);
+ vm_setclassvariable(GET_ISEQ(), GET_CFP(), id, val, ic);
+}
+
+DEFINE_INSN
+opt_getconstant_path
+(IC ic)
+()
+(VALUE val)
+// attr bool leaf = false; /* may autoload or raise */
+{
+ const ID *segments = ic->segments;
+ struct iseq_inline_constant_cache_entry *ice = ic->entry;
+ if (ice && vm_ic_hit_p(ice, GET_EP())) {
+ val = ice->value;
+
+ VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
+ } else {
+ ruby_vm_constant_cache_misses++;
+ val = vm_get_ev_const_chain(ec, segments);
+ vm_ic_track_const_chain(GET_CFP(), ic, segments);
+ // Because leaf=false, we need to undo the PC increment to get the address to this instruction
+ // INSN_ATTR(width) == 2
+ vm_ic_update(GET_ISEQ(), ic, val, GET_EP(), GET_PC() - 2);
+ }
}
/* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants
@@ -351,6 +373,7 @@ putspecialobject
(rb_num_t value_type)
()
(VALUE val)
+// attr bool leaf = (value_type == VM_SPECIAL_OBJECT_VMCORE); /* others may raise when allocating singleton */
{
enum vm_special_object_type type;
@@ -382,9 +405,10 @@ concatstrings
val = rb_str_concat_literals(num, STACK_ADDR_FROM_TOP(num));
}
-/* push the result of to_s. */
+/* Convert the result to string if not already a string.
+ This is used as a backup if to_s does not return a string. */
DEFINE_INSN
-tostring
+anytostring
()
(VALUE val, VALUE str)
(VALUE val)
@@ -526,11 +550,13 @@ newhash
{
RUBY_DTRACE_CREATE_HOOK(HASH, num);
- val = rb_hash_new_with_size(num / 2);
-
if (num) {
+ val = rb_hash_new_with_size(num / 2);
rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
}
+ else {
+ val = rb_hash_new();
+ }
}
/* put new Range object.(Range.new(low, high, flag)) */
@@ -594,6 +620,25 @@ swap
/* none */
}
+/* reverse stack top N order. */
+DEFINE_INSN
+opt_reverse
+(rb_num_t n)
+(...)
+(...)
+// attr rb_snum_t sp_inc = 0;
+{
+ rb_num_t i;
+ VALUE *sp = STACK_ADDR_FROM_TOP(n);
+
+ for (i=0; i<n/2; i++) {
+ VALUE v0 = sp[i];
+ VALUE v1 = TOPN(i);
+ sp[i] = v1;
+ TOPN(i) = v0;
+ }
+}
+
/* for stack caching. */
DEFINE_INSN_IF(STACK_CACHING)
reput
@@ -652,7 +697,7 @@ defined
{
val = Qnil;
if (vm_defined(ec, GET_CFP(), op_type, obj, v)) {
- val = pushval;
+ val = pushval;
}
}
@@ -660,7 +705,7 @@ defined
`flag & VM_CHECKMATCH_TYPE_MASK' describe how to check pattern.
VM_CHECKMATCH_TYPE_WHEN: ignore target and check pattern is truthy.
VM_CHECKMATCH_TYPE_CASE: check `patten === target'.
- VM_CHECKMATCH_TYPE_RESCUE: check `pattern.kind_op?(Module) && pattern === target'.
+ VM_CHECKMATCH_TYPE_RESCUE: check `pattern.kind_of?(Module) && pattern === target'.
if `flag & VM_CHECKMATCH_ARRAY' is not 0, then `patten' is array of patterns.
*/
DEFINE_INSN
@@ -690,7 +735,7 @@ checktype
(VALUE val)
(VALUE ret)
{
- ret = (TYPE(val) == (int)type) ? Qtrue : Qfalse;
+ ret = RBOOL(TYPE(val) == (int)type);
}
/**********************************************************/
@@ -712,11 +757,11 @@ defineclass
/* enter scope */
vm_push_frame(ec, class_iseq, VM_FRAME_MAGIC_CLASS | VM_ENV_FLAG_LOCAL, klass,
- GET_BLOCK_HANDLER(),
- (VALUE)vm_cref_push(ec, klass, NULL, FALSE),
- class_iseq->body->iseq_encoded, GET_SP(),
- class_iseq->body->local_table_size,
- class_iseq->body->stack_max);
+ GET_BLOCK_HANDLER(),
+ (VALUE)vm_cref_push(ec, klass, NULL, FALSE, FALSE),
+ ISEQ_BODY(class_iseq)->iseq_encoded, GET_SP(),
+ ISEQ_BODY(class_iseq)->local_table_size,
+ ISEQ_BODY(class_iseq)->stack_max);
RESTORE_REGS();
NEXT_INSN();
}
@@ -780,6 +825,21 @@ opt_send_without_block
}
}
+/* Convert object to string using to_s or equivalent. */
+DEFINE_INSN
+objtostring
+(CALL_DATA cd)
+(VALUE recv)
+(VALUE val)
+// attr bool leaf = false;
+{
+ val = vm_objtostring(GET_ISEQ(), recv, cd);
+
+ if (val == Qundef) {
+ CALL_SIMPLE_METHOD();
+ }
+}
+
DEFINE_INSN
opt_str_freeze
(VALUE str, CALL_DATA cd)
@@ -834,7 +894,7 @@ opt_newarray_max
// attr bool leaf = false; /* has rb_funcall() */
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
{
- val = vm_opt_newarray_max(num, STACK_ADDR_FROM_TOP(num));
+ val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num));
}
DEFINE_INSN
@@ -846,7 +906,7 @@ opt_newarray_min
// attr bool leaf = false; /* has rb_funcall() */
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
{
- val = vm_opt_newarray_min(num, STACK_ADDR_FROM_TOP(num));
+ val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num));
}
/* super(args) # args.size => num */
@@ -902,19 +962,19 @@ leave
const VALUE *const bp = vm_base_ptr(GET_CFP());
if (GET_SP() != bp) {
vm_stack_consistency_error(ec, GET_CFP(), bp);
- }
+ }
}
if (vm_pop_frame(ec, GET_CFP(), GET_EP())) {
#if OPT_CALL_THREADED_CODE
- rb_ec_thread_ptr(ec)->retval = val;
- return 0;
+ rb_ec_thread_ptr(ec)->retval = val;
+ return 0;
#else
- return val;
+ return val;
#endif
}
else {
- RESTORE_REGS();
+ RESTORE_REGS();
}
}
@@ -963,8 +1023,8 @@ branchif
// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
if (RTEST(val)) {
- RUBY_VM_CHECK_INTS(ec);
- JUMP(dst);
+ RUBY_VM_CHECK_INTS(ec);
+ JUMP(dst);
}
}
@@ -978,8 +1038,8 @@ branchunless
// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
if (!RTEST(val)) {
- RUBY_VM_CHECK_INTS(ec);
- JUMP(dst);
+ RUBY_VM_CHECK_INTS(ec);
+ JUMP(dst);
}
}
@@ -993,8 +1053,8 @@ branchnil
// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
if (NIL_P(val)) {
- RUBY_VM_CHECK_INTS(ec);
- JUMP(dst);
+ RUBY_VM_CHECK_INTS(ec);
+ JUMP(dst);
}
}
@@ -1002,34 +1062,6 @@ branchnil
/* for optimize */
/**********************************************************/
-/* push inline-cached value and go to dst if it is valid */
-DEFINE_INSN
-opt_getinlinecache
-(OFFSET dst, IC ic)
-()
-(VALUE val)
-{
- 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;
- }
-}
-
-/* set inline cache */
-DEFINE_INSN
-opt_setinlinecache
-(IC ic)
-(VALUE val)
-(VALUE val)
-// attr bool leaf = false;
-{
- vm_ic_update(GET_ISEQ(), ic, val, GET_EP());
-}
-
/* run iseq only once */
DEFINE_INSN
once
@@ -1051,7 +1083,7 @@ opt_case_dispatch
OFFSET dst = vm_case_dispatch(hash, else_offset, key);
if (dst) {
- JUMP(dst);
+ JUMP(dst);
}
}
@@ -1310,12 +1342,12 @@ opt_aset_with
VALUE tmp = vm_opt_aset_with(recv, key, val);
if (tmp != Qundef) {
- val = tmp;
+ val = tmp;
}
else {
#ifndef MJIT_HEADER
- TOPN(0) = rb_str_resurrect(key);
- PUSH(val);
+ TOPN(0) = rb_str_resurrect(key);
+ PUSH(val);
#endif
CALL_SIMPLE_METHOD();
}
@@ -1334,7 +1366,7 @@ opt_aref_with
if (val == Qundef) {
#ifndef MJIT_HEADER
- PUSH(rb_str_resurrect(key));
+ PUSH(rb_str_resurrect(key));
#endif
CALL_SIMPLE_METHOD();
}
@@ -1437,9 +1469,9 @@ opt_call_c_function
reg_cfp = (funcptr)(ec, reg_cfp);
if (reg_cfp == 0) {
- VALUE err = ec->errinfo;
- ec->errinfo = Qnil;
- THROW_EXCEPTION(err);
+ VALUE err = ec->errinfo;
+ ec->errinfo = Qnil;
+ THROW_EXCEPTION(err);
}
RESTORE_REGS();
diff --git a/internal.h b/internal.h
index 883459bfa6..b63af50616 100644
--- a/internal.h
+++ b/internal.h
@@ -1,7 +1,6 @@
#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
@@ -26,6 +25,9 @@
/* Prevent compiler from reordering access */
#define ACCESS_ONCE(type,x) (*((volatile type *)&(x)))
+#define UNDEF_P RB_UNDEF_P
+#define NIL_OR_UNDEF_P RB_NIL_OR_UNDEF_P
+
#include "ruby/ruby.h"
/* Following macros were formerly defined in this header but moved to somewhere
@@ -49,9 +51,6 @@
#undef RHASH_TBL
#undef RHASH_EMPTY_P
-/* internal/object.h */
-#undef ROBJECT_IV_INDEX_TBL
-
/* internal/struct.h */
#undef RSTRUCT_LEN
#undef RSTRUCT_PTR
@@ -96,8 +95,8 @@ RUBY_SYMBOL_EXPORT_END
// same as rp, but add message header
#define rp_m(msg, obj) do { \
- fprintf(stderr, "%s", (msg)); \
- rb_obj_info_dump((VALUE)obj); \
+ fputs((msg), stderr); \
+ rb_obj_info_dump((VALUE)(obj)); \
} while (0)
// `ruby_debug_breakpoint()` does nothing,
@@ -105,5 +104,10 @@ RUBY_SYMBOL_EXPORT_END
#define bp() ruby_debug_breakpoint()
#define RBOOL(v) ((v) ? Qtrue : Qfalse)
+#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM)
+#ifndef __MINGW32__
+#undef memcpy
+#define memcpy ruby_nonempty_memcpy
+#endif
#endif /* RUBY_INTERNAL_H */
diff --git a/internal/array.h b/internal/array.h
index 97b707f271..a0d16dec3f 100644
--- a/internal/array.h
+++ b/internal/array.h
@@ -1,7 +1,6 @@
#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
@@ -19,28 +18,30 @@
# define ARRAY_DEBUG (0+RUBY_DEBUG)
#endif
-#define RARRAY_PTR_IN_USE_FLAG FL_USER14
+#define RARRAY_SHARED_FLAG ELTS_SHARED
+#define RARRAY_SHARED_ROOT_FLAG FL_USER12
+#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_hidden_new_fill(long capa);
VALUE rb_ary_at(VALUE, VALUE);
size_t rb_ary_memsize(VALUE);
VALUE rb_to_array_type(VALUE obj);
VALUE rb_to_array(VALUE obj);
void rb_ary_cancel_sharing(VALUE ary);
+size_t rb_ary_size_as_embedded(VALUE ary);
+void rb_ary_make_embedded(VALUE ary);
+bool rb_ary_embeddable_p(VALUE ary);
+VALUE rb_ary_diff(VALUE ary1, VALUE ary2);
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) */
-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);
@@ -51,6 +52,7 @@ struct rb_execution_context_struct;
VALUE rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts);
MJIT_SYMBOL_EXPORT_END
+// YJIT needs this function to never allocate and never raise
static inline VALUE
rb_ary_entry_internal(VALUE ary, long offset)
{
@@ -73,6 +75,50 @@ ARY_PTR_USING_P(VALUE ary)
return FL_TEST_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
}
+RBIMPL_ATTR_MAYBE_UNUSED()
+static inline int
+ary_should_not_be_shared_and_embedded(VALUE ary)
+{
+ return !FL_ALL_RAW(ary, RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG);
+}
+
+static inline bool
+ARY_SHARED_P(VALUE ary)
+{
+ assert(RB_TYPE_P(ary, T_ARRAY));
+ assert(ary_should_not_be_shared_and_embedded(ary));
+ return FL_TEST_RAW(ary, RARRAY_SHARED_FLAG);
+}
+
+static inline bool
+ARY_EMBED_P(VALUE ary)
+{
+ assert(RB_TYPE_P(ary, T_ARRAY));
+ assert(ary_should_not_be_shared_and_embedded(ary));
+ return FL_TEST_RAW(ary, RARRAY_EMBED_FLAG);
+}
+
+static inline VALUE
+ARY_SHARED_ROOT(VALUE ary)
+{
+ assert(ARY_SHARED_P(ary));
+ return RARRAY(ary)->as.heap.aux.shared_root;
+}
+
+static inline bool
+ARY_SHARED_ROOT_P(VALUE ary)
+{
+ assert(RB_TYPE_P(ary, T_ARRAY));
+ return FL_TEST_RAW(ary, RARRAY_SHARED_ROOT_FLAG);
+}
+
+static inline long
+ARY_SHARED_ROOT_REFCNT(VALUE ary)
+{
+ assert(ARY_SHARED_ROOT_P(ary));
+ return RARRAY(ary)->as.heap.aux.capa;
+}
+
static inline void
RARY_TRANSIENT_SET(VALUE ary)
{
diff --git a/internal/basic_operators.h b/internal/basic_operators.h
new file mode 100644
index 0000000000..2cd9f50073
--- /dev/null
+++ b/internal/basic_operators.h
@@ -0,0 +1,64 @@
+#ifndef INTERNAL_BOP_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_BOP_H
+
+#include "internal.h"
+#include "ruby/internal/dllexport.h"
+
+enum ruby_basic_operators {
+ BOP_PLUS,
+ BOP_MINUS,
+ BOP_MULT,
+ BOP_DIV,
+ BOP_MOD,
+ BOP_EQ,
+ BOP_EQQ,
+ BOP_LT,
+ BOP_LE,
+ BOP_LTLT,
+ BOP_AREF,
+ BOP_ASET,
+ BOP_LENGTH,
+ BOP_SIZE,
+ BOP_EMPTY_P,
+ BOP_NIL_P,
+ BOP_SUCC,
+ BOP_GT,
+ BOP_GE,
+ BOP_NOT,
+ BOP_NEQ,
+ BOP_MATCH,
+ BOP_FREEZE,
+ BOP_UMINUS,
+ BOP_MAX,
+ BOP_MIN,
+ BOP_CALL,
+ BOP_AND,
+ BOP_OR,
+ BOP_CMP,
+ BOP_DEFAULT,
+
+ BOP_LAST_
+};
+
+MJIT_SYMBOL_EXPORT_BEGIN
+RUBY_EXTERN short ruby_vm_redefined_flag[BOP_LAST_];
+MJIT_SYMBOL_EXPORT_END
+
+/* optimize insn */
+#define INTEGER_REDEFINED_OP_FLAG (1 << 0)
+#define FLOAT_REDEFINED_OP_FLAG (1 << 1)
+#define STRING_REDEFINED_OP_FLAG (1 << 2)
+#define ARRAY_REDEFINED_OP_FLAG (1 << 3)
+#define HASH_REDEFINED_OP_FLAG (1 << 4)
+/* #define BIGNUM_REDEFINED_OP_FLAG (1 << 5) */
+#define SYMBOL_REDEFINED_OP_FLAG (1 << 6)
+#define TIME_REDEFINED_OP_FLAG (1 << 7)
+#define REGEXP_REDEFINED_OP_FLAG (1 << 8)
+#define NIL_REDEFINED_OP_FLAG (1 << 9)
+#define TRUE_REDEFINED_OP_FLAG (1 << 10)
+#define FALSE_REDEFINED_OP_FLAG (1 << 11)
+#define PROC_REDEFINED_OP_FLAG (1 << 12)
+
+#define BASIC_OP_UNREDEFINED_P(op, klass) (LIKELY((ruby_vm_redefined_flag[(op)]&(klass)) == 0))
+
+#endif
diff --git a/internal/bignum.h b/internal/bignum.h
index 9b89e61f28..5cd35ede8a 100644
--- a/internal/bignum.h
+++ b/internal/bignum.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/bits.h b/internal/bits.h
index 746947bfc2..2602ff7a31 100644
--- a/internal/bits.h
+++ b/internal/bits.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/class.h b/internal/class.h
index 1d25d9e7eb..63917e867f 100644
--- a/internal/class.h
+++ b/internal/class.h
@@ -1,7 +1,6 @@
#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
@@ -15,6 +14,10 @@
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/intern.h" /* for rb_alloc_func_t */
#include "ruby/ruby.h" /* for struct RBasic */
+#include "shape.h"
+#include "ruby_assert.h"
+#include "vm_core.h"
+#include "method.h" /* for rb_cref_t */
#ifdef RCLASS_SUPER
# undef RCLASS_SUPER
@@ -23,111 +26,108 @@
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_subclass_entry *prev;
};
struct rb_cvar_class_tbl_entry {
uint32_t index;
rb_serial_t global_cvar_state;
+ const rb_cref_t * cref;
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
+ VALUE *iv_ptr;
struct rb_id_table *const_tbl;
struct rb_id_table *callable_m_tbl;
struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */
struct rb_id_table *cvc_tbl;
+ size_t superclass_depth;
+ VALUE *superclasses;
struct rb_subclass_entry *subclasses;
- struct rb_subclass_entry **parent_subclasses;
+ struct rb_subclass_entry *subclass_entry;
/**
* In the case that this is an `ICLASS`, `module_subclasses` points to the link
* in the module's `subclasses` list that indicates that the klass has been
* included. Hopefully that makes sense.
*/
- struct rb_subclass_entry **module_subclasses;
-#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */
- rb_serial_t class_serial;
-#endif
+ struct rb_subclass_entry *module_subclass_entry;
const VALUE origin_;
const VALUE refined_class;
rb_alloc_func_t allocator;
const VALUE includer;
+ uint32_t max_iv_count;
+ uint32_t variation_count;
+#if !SHAPE_IN_BASIC_FLAGS
+ shape_id_t shape_id;
+#endif
};
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;
+#if SIZE_POOL_COUNT == 1
+ struct rb_classext_struct *ptr;
#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)
+#if RCLASS_EXT_EMBEDDED
+# define RCLASS_EXT(c) ((rb_classext_t *)((char *)(c) + sizeof(struct RClass)))
#else
-# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
+# define RCLASS_EXT(c) (RCLASS(c)->ptr)
#endif
+#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
+#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
+#define RCLASS_IVPTR(c) (RCLASS_EXT(c)->iv_ptr)
#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
#define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl)
#define RCLASS_CVC_TBL(c) (RCLASS_EXT(c)->cvc_tbl)
-#define RCLASS_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_PARENT_SUBCLASSES(c) (RCLASS_EXT(c)->parent_subclasses)
-#define RCLASS_MODULE_SUBCLASSES(c) (RCLASS_EXT(c)->module_subclasses)
+#define RCLASS_SUBCLASS_ENTRY(c) (RCLASS_EXT(c)->subclass_entry)
+#define RCLASS_MODULE_SUBCLASS_ENTRY(c) (RCLASS_EXT(c)->module_subclass_entry)
#define RCLASS_ALLOCATOR(c) (RCLASS_EXT(c)->allocator)
#define RCLASS_SUBCLASSES(c) (RCLASS_EXT(c)->subclasses)
+#define RCLASS_SUPERCLASS_DEPTH(c) (RCLASS_EXT(c)->superclass_depth)
+#define RCLASS_SUPERCLASSES(c) (RCLASS_EXT(c)->superclasses)
-#define RICLASS_IS_ORIGIN FL_USER5
-#define RCLASS_CLONED FL_USER6
-#define RICLASS_ORIGIN_SHARED_MTBL FL_USER8
+#define RICLASS_IS_ORIGIN FL_USER0
+#define RCLASS_CLONED FL_USER1
+#define RCLASS_SUPERCLASSES_INCLUDE_SELF FL_USER2
+#define RICLASS_ORIGIN_SHARED_MTBL FL_USER3
/* class.c */
void rb_class_subclass_add(VALUE super, VALUE klass);
void rb_class_remove_from_super_subclasses(VALUE);
+void rb_class_update_superclasses(VALUE);
+size_t rb_class_superclasses_memsize(VALUE);
+void rb_class_remove_subclass_head(VALUE);
int rb_singleton_class_internal_p(VALUE sklass);
VALUE rb_class_boot(VALUE);
+VALUE rb_class_s_alloc(VALUE klass);
+VALUE rb_module_s_alloc(VALUE klass);
+void rb_module_set_initialized(VALUE module);
+void rb_module_check_initializable(VALUE module);
VALUE rb_make_metaclass(VALUE, VALUE);
VALUE rb_include_class_new(VALUE, VALUE);
void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE);
void rb_class_detach_subclasses(VALUE);
void rb_class_detach_module_subclasses(VALUE);
void rb_class_remove_from_module_subclasses(VALUE);
+VALUE rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super);
VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj);
VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj);
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_class_undefined_instance_methods(VALUE mod);
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);
@@ -180,6 +180,7 @@ RCLASS_SET_SUPER(VALUE klass, VALUE super)
rb_class_subclass_add(super, klass);
}
RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super);
+ rb_class_update_superclasses(klass);
return super;
}
diff --git a/internal/cmdlineopt.h b/internal/cmdlineopt.h
new file mode 100644
index 0000000000..bf52f1214b
--- /dev/null
+++ b/internal/cmdlineopt.h
@@ -0,0 +1,61 @@
+#ifndef INTERNAL_CMDLINEOPT_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_CMDLINEOPT_H
+
+#include "mjit.h"
+#include "yjit.h"
+
+typedef struct {
+ unsigned int mask;
+ unsigned int set;
+} ruby_features_t;
+
+typedef struct ruby_cmdline_options {
+ const char *script;
+ VALUE script_name;
+ VALUE e_script;
+ struct {
+ struct {
+ VALUE name;
+ int index;
+ } enc;
+ } src, ext, intern;
+ VALUE req_list;
+ ruby_features_t features;
+ ruby_features_t warn;
+ unsigned int dump;
+#if USE_MJIT
+ struct mjit_options mjit;
+#endif
+
+ int sflag, xflag;
+ unsigned int warning: 1;
+ unsigned int verbose: 1;
+ unsigned int do_loop: 1;
+ unsigned int do_print: 1;
+ unsigned int do_line: 1;
+ unsigned int do_split: 1;
+ unsigned int do_search: 1;
+ unsigned int setids: 2;
+#if USE_YJIT
+ unsigned int yjit: 1;
+#endif
+} ruby_cmdline_options_t;
+
+struct ruby_opt_message {
+ const char *str;
+ unsigned short namelen, secondlen;
+};
+
+#define RUBY_OPT_MESSAGE(shortopt, longopt, desc) { \
+ shortopt " " longopt " " desc, \
+ (unsigned short)sizeof(shortopt), \
+ (unsigned short)sizeof(longopt), \
+}
+
+#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))
+
+#endif
diff --git a/internal/compar.h b/internal/compar.h
index 888a3b5e1e..9115e4bd63 100644
--- a/internal/compar.h
+++ b/internal/compar.h
@@ -1,7 +1,6 @@
#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
@@ -9,38 +8,18 @@
* file COPYING are met. Consult the file for details.
* @brief Internal header for Comparable.
*/
-#include "internal/vm.h" /* for rb_method_basic_definition_p */
+#include "internal/basic_operators.h"
#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
-};
+#define CMP_OPTIMIZABLE(type) BASIC_OP_UNREDEFINED_P(BOP_CMP, type##_REDEFINED_OP_FLAG)
-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)) ? \
+#define OPTIMIZED_CMP(a, b) \
+ ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) ? \
(((long)a > (long)b) ? 1 : ((long)a < (long)b) ? -1 : 0) : \
- (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data, String)) ? \
+ (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) ? \
rb_str_cmp(a, b) : \
- (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(data, Float)) ? \
+ (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(FLOAT)) ? \
rb_float_cmp(a, b) : \
rb_cmpint(rb_funcallv(a, id_cmp, 1, &b), a, b))
diff --git a/internal/compile.h b/internal/compile.h
index 99c15d6a44..d32c2233c9 100644
--- a/internal/compile.h
+++ b/internal/compile.h
@@ -1,7 +1,6 @@
#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
@@ -26,6 +25,7 @@ st_index_t rb_iseq_cdhash_hash(VALUE a);
/* iseq.c */
int rb_vm_insn_addr2insn(const void *);
int rb_vm_insn_decode(const VALUE encoded);
+extern bool ruby_vm_keep_script_lines;
MJIT_SYMBOL_EXPORT_BEGIN
/* iseq.c (export) */
diff --git a/internal/compilers.h b/internal/compilers.h
index 975bf4575d..26c2f05cc0 100644
--- a/internal/compilers.h
+++ b/internal/compilers.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/complex.h b/internal/complex.h
index 9eae804ddb..42151652b7 100644
--- a/internal/complex.h
+++ b/internal/complex.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/cont.h b/internal/cont.h
index 8be1950e98..c3b091668a 100644
--- a/internal/cont.h
+++ b/internal/cont.h
@@ -1,7 +1,6 @@
#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
@@ -10,16 +9,24 @@
* @brief Internal header for Fiber.
*/
#include "ruby/ruby.h" /* for VALUE */
+#include "iseq.h"
struct rb_thread_struct; /* in vm_core.h */
struct rb_fiber_struct; /* in cont.c */
+struct rb_execution_context_struct; /* in vm_core.c */
/* cont.c */
void rb_fiber_reset_root_local_storage(struct rb_thread_struct *);
void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE));
-void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber);
+void rb_jit_cont_init(void);
+void rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data);
+void rb_jit_cont_finish(void);
+
+// Copy locals from the current execution to the specified fiber.
+VALUE rb_fiber_inherit_storage(struct rb_execution_context_struct *ec, struct rb_fiber_struct *fiber);
VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber);
unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber);
+struct rb_execution_context_struct * rb_fiberptr_get_ec(struct rb_fiber_struct *fiber);
#endif /* INTERNAL_CONT_H */
diff --git a/internal/dir.h b/internal/dir.h
index ffbdb25208..0a4dc90ece 100644
--- a/internal/dir.h
+++ b/internal/dir.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/enc.h b/internal/enc.h
index 0afc74db5d..a005dc810d 100644
--- a/internal/enc.h
+++ b/internal/enc.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/encoding.h b/internal/encoding.h
index c0cf061bd4..a3b81bd388 100644
--- a/internal/encoding.h
+++ b/internal/encoding.h
@@ -1,7 +1,6 @@
#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
@@ -13,6 +12,9 @@
#include "ruby/encoding.h" /* for rb_encoding */
#define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
+#define rb_is_usascii_enc(enc) ((enc) == rb_usascii_encoding())
+#define rb_is_ascii8bit_enc(enc) ((enc) == rb_ascii8bit_encoding())
+#define rb_is_locale_enc(enc) ((enc) == rb_locale_encoding())
/* encoding.c */
ID rb_id_encoding(void);
@@ -25,7 +27,6 @@ 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
index 50890f0c9f..282464436f 100644
--- a/internal/enum.h
+++ b/internal/enum.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/enumerator.h b/internal/enumerator.h
index 2e20c37d9e..e11a684c5b 100644
--- a/internal/enumerator.h
+++ b/internal/enumerator.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/error.h b/internal/error.h
index 360203aefc..11601858f4 100644
--- a/internal/error.h
+++ b/internal/error.h
@@ -1,7 +1,6 @@
#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
@@ -44,14 +43,24 @@ extern long rb_backtrace_length_limit;
extern VALUE rb_eEAGAIN;
extern VALUE rb_eEWOULDBLOCK;
extern VALUE rb_eEINPROGRESS;
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0)
void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args);
NORETURN(void rb_async_bug_errno(const char *,int));
const char *rb_builtin_type_name(int t);
const char *rb_builtin_class_name(VALUE x);
PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3);
PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...), 2, 4);
-#if RUBY_DEBUG && (RBIMPL_HAS_ATTRIBUTE(diagnose_if) || defined(__OPTIMIZE__))
+#if RUBY_DEBUG
# include "ruby/version.h"
+# define RUBY_VERSION_SINCE(major, minor) (RUBY_API_VERSION_CODE >= (major * 10000) + (minor) * 100)
+# define RUBY_VERSION_BEFORE(major, minor) (RUBY_API_VERSION_CODE < (major * 10000) + (minor) * 100)
+# if defined(RBIMPL_WARNING_PRAGMA0)
+# define RBIMPL_TODO0(x) RBIMPL_WARNING_PRAGMA0(message(x))
+# elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
+# define RBIMPL_TODO0(x) __pragma(message(x))
+# endif
+
+# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) || defined(__OPTIMIZE__)
#define RUBY_VERSION_isdigit(c) ('0'<=(c)&&(c)<='9')
// upto 99
@@ -68,32 +77,45 @@ PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *removal, const char *f
(RUBY_VERSION__to_number(v, 0) * 10000 + \
((v)[RUBY_VERSION__number_len(v, 0)] == '.' ? \
RUBY_VERSION__to_number(v, RUBY_VERSION__number_len(v, 0)+1) * 100 : 0))
-#define RUBY_VERSION_SINCE(v) (RUBY_API_VERSION_CODE >= RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
-#define RUBY_VERSION_BEFORE(v) (RUBY_API_VERSION_CODE < RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
+#define RUBY_VERSION_STRING_SINCE(v) (RUBY_API_VERSION_CODE >= RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
+#define RUBY_VERSION_STRING_BEFORE(v) (RUBY_API_VERSION_CODE < RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v))
# if RBIMPL_HAS_ATTRIBUTE(diagnose_if)
RBIMPL_ATTR_FORCEINLINE()
static void
rb_deprecated_method_to_be_removed(const char *removal)
RBIMPL_ATTR_DIAGNOSE_IF(!RUBY_VERSION_isdigit(removal[0]), "malformed version number", "error")
- RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_SINCE(removal), "deprecated method to be removed", "error")
+ RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(removal), "deprecated method to be removed", "error")
{
}
# else
RBIMPL_ATTR_ERROR(("deprecated"))
void rb_deprecated_method_to_be_removed(const char *);
# define rb_deprecated_method_to_be_removed(removal) \
- (sizeof(char[1-2*(!RUBY_VERSION_isdigit(removal[0]) || RUBY_VERSION_SINCE(removal))])!=1 ? \
+ (sizeof(char[1-2*(!RUBY_VERSION_isdigit(removal[0]) || RUBY_VERSION_STRING_SINCE(removal))])!=1 ? \
rb_deprecated_method_to_be_removed(removal) : \
RBIMPL_ASSERT_NOTHING)
# endif
# define rb_warn_deprecated_to_remove_at(removal, ...) \
(rb_deprecated_method_to_be_removed(#removal), \
rb_warn_deprecated_to_remove(#removal, __VA_ARGS__))
-#else
+# endif
+#endif
+#ifndef rb_warn_deprecated_to_remove_at
# define rb_warn_deprecated_to_remove_at(removal, ...) \
rb_warn_deprecated_to_remove(#removal, __VA_ARGS__)
#endif
+#ifndef RUBY_VERSION_SINCE
+# define RUBY_VERSION_SINCE(major, minor) 0
+#endif
+#ifndef RUBY_VERSION_BEFORE
+# define RUBY_VERSION_BEFORE(major, minor) 0
+#endif
+#ifndef RBIMPL_TODO0
+# define RBIMPL_TODO0(x)
+#endif
+#define RBIMPL_TODO(message) RBIMPL_TODO0("TODO: " message)
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0)
VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list);
PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3);
PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3);
@@ -104,6 +126,7 @@ VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv);
VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name);
PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2);
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
NORETURN(void rb_vraise(VALUE, const char *, va_list));
NORETURN(static inline void rb_raise_cstr(VALUE etype, const char *mesg));
NORETURN(static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg));
diff --git a/internal/eval.h b/internal/eval.h
index 8dae76b6f8..e594d8516d 100644
--- a/internal/eval.h
+++ b/internal/eval.h
@@ -1,7 +1,6 @@
#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
@@ -22,6 +21,7 @@ extern ID ruby_static_id_status;
VALUE rb_refinement_module_get_refined_class(VALUE module);
void rb_class_modify_check(VALUE);
NORETURN(VALUE rb_f_raise(int argc, VALUE *argv));
+VALUE rb_top_main_class(const char *method);
/* eval_error.c */
VALUE rb_get_backtrace(VALUE info);
diff --git a/internal/file.h b/internal/file.h
index a93c1392f0..9c192ff4d1 100644
--- a/internal/file.h
+++ b/internal/file.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/fixnum.h b/internal/fixnum.h
index 7e0e4be84c..8c251adef1 100644
--- a/internal/fixnum.h
+++ b/internal/fixnum.h
@@ -1,7 +1,6 @@
#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
@@ -19,7 +18,7 @@
#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
# define DLONG LONG_LONG
# define DL2NUM(x) LL2NUM(x)
-#elif defined(HAVE_INT128_T)
+#elif defined(HAVE_INT128_T) && !(defined(__OpenBSD__) && defined(__mips64__))
# define DLONG int128_t
# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x))
VALUE rb_int128t2big(int128_t n); /* in bignum.c */
diff --git a/internal/gc.h b/internal/gc.h
index 42d82aac76..e54a5dce9d 100644
--- a/internal/gc.h
+++ b/internal/gc.h
@@ -1,7 +1,6 @@
#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
@@ -19,32 +18,29 @@
struct rb_execution_context_struct; /* in vm_core.h */
struct rb_objspace; /* in vm_core.h */
-#ifndef USE_RVARGC
-#define USE_RVARGC 0
-#endif
-
#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, 0) : \
- rb_wb_unprotected_newobj_of((c), (f), 0))
-
-#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, 0) : \
- rb_wb_unprotected_newobj_of((c), (f), 0))
+#define RVALUE_SIZE (sizeof(struct RBasic) + sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]))
#define RB_RVARGC_NEWOBJ_OF(var, T, c, f, s) \
T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
rb_wb_protected_newobj_of((c), (f) & ~FL_WB_PROTECTED, s) : \
rb_wb_unprotected_newobj_of((c), (f), s))
+#define RB_RVARGC_EC_NEWOBJ_OF(ec, var, T, c, f, s) \
+ T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
+ rb_ec_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED, s) : \
+ rb_wb_unprotected_newobj_of((c), (f), s))
+
+/* optimized version of NEWOBJ() */
+#define RB_NEWOBJ_OF(var, T, c, f) RB_RVARGC_NEWOBJ_OF(var, T, c, f, RVALUE_SIZE)
+
+#define RB_EC_NEWOBJ_OF(ec, var, T, c, f) RB_RVARGC_EC_NEWOBJ_OF(ec, var, T, c, f, RVALUE_SIZE)
+
#define NEWOBJ_OF(var, T, c, f) RB_NEWOBJ_OF((var), T, (c), (f))
#define RVARGC_NEWOBJ_OF(var, T, c, f, s) RB_RVARGC_NEWOBJ_OF((var), T, (c), (f), (s))
#define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */
@@ -71,11 +67,24 @@ struct rb_objspace; /* in vm_core.h */
rb_obj_write((VALUE)(a), UNALIGNED_MEMBER_ACCESS((VALUE *)(slot)), \
(VALUE)(b), __FILE__, __LINE__)
-#define RVARGC_PAYLOAD_INIT(obj, size) (void *)rb_rvargc_payload_init((VALUE)obj, (size_t)size)
+// We use SIZE_POOL_COUNT number of shape IDs for transitions out of different size pools
+// The next available shapd ID will be the SPECIAL_CONST_SHAPE_ID
+#if USE_RVARGC && (SIZEOF_UINT64_T == SIZEOF_VALUE)
+# define SIZE_POOL_COUNT 5
+#else
+# define SIZE_POOL_COUNT 1
+#endif
-typedef struct ractor_newobj_cache {
+#define RCLASS_EXT_EMBEDDED (SIZE_POOL_COUNT > 1)
+
+typedef struct ractor_newobj_size_pool_cache {
struct RVALUE *freelist;
struct heap_page *using_page;
+} rb_ractor_newobj_size_pool_cache_t;
+
+typedef struct ractor_newobj_cache {
+ size_t incremental_mark_step_allocated_slots;
+ rb_ractor_newobj_size_pool_cache_t size_pool_caches[SIZE_POOL_COUNT];
} rb_ractor_newobj_cache_t;
/* gc.c */
@@ -95,6 +104,7 @@ 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);
+RUBY_ATTR_MALLOC void *rb_xcalloc_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);
@@ -103,6 +113,9 @@ static inline void *ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, si
static inline void ruby_sized_xfree_inlined(void *ptr, size_t size);
VALUE rb_class_allocate_instance(VALUE klass);
void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache);
+size_t rb_gc_obj_slot_size(VALUE obj);
+bool rb_gc_size_allocatable_p(size_t size);
+int rb_objspace_garbage_object_p(VALUE obj);
RUBY_SYMBOL_EXPORT_BEGIN
/* gc.c (export) */
@@ -110,8 +123,6 @@ const char *rb_objspace_data_type_name(VALUE obj);
VALUE rb_wb_protected_newobj_of(VALUE, VALUE, size_t);
VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE, size_t);
VALUE rb_ec_wb_protected_newobj_of(struct rb_execution_context_struct *ec, VALUE klass, VALUE flags, size_t);
-VALUE rb_rvargc_payload_init(VALUE obj, size_t size);
-void * rb_rvargc_payload_data_ptr(VALUE obj);
size_t rb_obj_memsize_of(VALUE);
void rb_gc_verify_internal_consistency(void);
size_t rb_obj_gc_flags(VALUE, ID[], size_t);
@@ -120,7 +131,6 @@ 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);
-int rb_slot_size(void);
RUBY_SYMBOL_EXPORT_END
MJIT_SYMBOL_EXPORT_BEGIN
diff --git a/internal/hash.h b/internal/hash.h
index a4677c581b..64832c9610 100644
--- a/internal/hash.h
+++ b/internal/hash.h
@@ -1,7 +1,6 @@
#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
@@ -74,6 +73,7 @@ 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);
+st_index_t rb_any_hash(VALUE a);
VALUE rb_to_hash_type(VALUE obj);
VALUE rb_hash_key_str(VALUE);
VALUE rb_hash_values(VALUE hash);
@@ -84,6 +84,7 @@ int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval);
int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg);
int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg);
extern st_table *rb_hash_st_table(VALUE hash);
+VALUE rb_ident_hash_new_with_size(st_index_t size);
static inline unsigned RHASH_AR_TABLE_SIZE_RAW(VALUE h);
static inline VALUE RHASH_IFNONE(VALUE h);
@@ -118,6 +119,8 @@ st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line);
#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__)
MJIT_SYMBOL_EXPORT_END
+VALUE rb_hash_compare_by_id(VALUE hash);
+
#if 0 /* for debug */
static inline bool
diff --git a/internal/imemo.h b/internal/imemo.h
index a9e2136ac4..91b524e0a6 100644
--- a/internal/imemo.h
+++ b/internal/imemo.h
@@ -1,7 +1,6 @@
#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
@@ -11,7 +10,7 @@
*/
#include "ruby/internal/config.h"
#include <stddef.h> /* for size_t */
-#include "internal/array.h" /* for rb_ary_tmp_new_fill */
+#include "internal/array.h" /* for rb_ary_hidden_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 */
@@ -122,14 +121,13 @@ struct MEMO {
#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))
+ ((value) = rb_ary_hidden_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)), \
+ ((value) = rb_ary_hidden_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);
diff --git a/internal/inits.h b/internal/inits.h
index 680c9cc1a5..03e180f77b 100644
--- a/internal/inits.h
+++ b/internal/inits.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/io.h b/internal/io.h
index b184cec439..b5f15499d7 100644
--- a/internal/io.h
+++ b/internal/io.h
@@ -1,7 +1,6 @@
#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
@@ -25,6 +24,10 @@ void rb_io_fptr_finalize_internal(void *ptr);
#define rb_io_fptr_finalize rb_io_fptr_finalize_internal
VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt);
+VALUE rb_io_prep_stdin(void);
+VALUE rb_io_prep_stdout(void);
+VALUE rb_io_prep_stderr(void);
+
RUBY_SYMBOL_EXPORT_BEGIN
/* io.c (export) */
void rb_maygvl_fd_fix_cloexec(int fd);
diff --git a/internal/load.h b/internal/load.h
index 37c1dee351..d4c0bb91ba 100644
--- a/internal/load.h
+++ b/internal/load.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/loadpath.h b/internal/loadpath.h
index f89f6694cd..b3a85e7b41 100644
--- a/internal/loadpath.h
+++ b/internal/loadpath.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/math.h b/internal/math.h
index cd8d553790..08f852ffc1 100644
--- a/internal/math.h
+++ b/internal/math.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/missing.h b/internal/missing.h
index 0224075b3d..c0992a151a 100644
--- a/internal/missing.h
+++ b/internal/missing.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/numeric.h b/internal/numeric.h
index 82ba4c1cfb..89bc54b307 100644
--- a/internal/numeric.h
+++ b/internal/numeric.h
@@ -1,7 +1,6 @@
#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
@@ -36,9 +35,22 @@ enum ruby_num_rounding_mode {
RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT,
};
+/* same as internal.h */
+#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
+#define roomof(x, y) (((x) + (y) - 1) / (y))
+#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
+
+#if SIZEOF_DOUBLE <= SIZEOF_VALUE
+typedef double rb_float_value_type;
+#else
+typedef struct {
+ VALUE values[roomof(SIZEOF_DOUBLE, SIZEOF_VALUE)];
+} rb_float_value_type;
+#endif
+
struct RFloat {
struct RBasic basic;
- double float_value;
+ rb_float_value_type float_value;
};
#define RFLOAT(obj) ((struct RFloat *)(obj))
@@ -97,7 +109,6 @@ static inline bool FLOAT_ZERO_P(VALUE num);
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
@@ -211,7 +222,15 @@ rb_float_flonum_value(VALUE v)
static inline double
rb_float_noflonum_value(VALUE v)
{
+#if SIZEOF_DOUBLE <= SIZEOF_VALUE
return RFLOAT(v)->float_value;
+#else
+ union {
+ rb_float_value_type v;
+ double d;
+ } u = {RFLOAT(v)->float_value};
+ return u.d;
+#endif
}
static inline double
diff --git a/internal/object.h b/internal/object.h
index 512c367b77..7b54e13dd2 100644
--- a/internal/object.h
+++ b/internal/object.h
@@ -1,7 +1,6 @@
#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
@@ -10,11 +9,6 @@
* @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);
@@ -23,11 +17,10 @@ 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 *);
+int rb_bool_expected(VALUE, const char *, int raise);
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) */
@@ -65,20 +58,4 @@ RBASIC_SET_CLASS(VALUE obj, VALUE klass)
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
index 588b2b34da..f242c384ad 100644
--- a/internal/parse.h
+++ b/internal/parse.h
@@ -1,7 +1,6 @@
#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
@@ -15,7 +14,9 @@ struct rb_iseq_struct; /* in vm_core.h */
/* parse.y */
VALUE rb_parser_set_yydebug(VALUE, VALUE);
void *rb_parser_load_file(VALUE parser, VALUE name);
-void rb_parser_save_script_lines(VALUE vparser);
+void rb_parser_keep_script_lines(VALUE vparser);
+void rb_parser_error_tolerant(VALUE vparser);
+void rb_parser_keep_tokens(VALUE vparser);
RUBY_SYMBOL_EXPORT_BEGIN
VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
diff --git a/internal/proc.h b/internal/proc.h
index 5628a1f1c7..2416c31e14 100644
--- a/internal/proc.h
+++ b/internal/proc.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/process.h b/internal/process.h
index 904c9a5cea..ceadfdcbbb 100644
--- a/internal/process.h
+++ b/internal/process.h
@@ -1,7 +1,6 @@
#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
@@ -27,6 +26,7 @@
#define RB_MAX_GROUPS (65536)
struct waitpid_state;
+struct rb_process_status;
struct rb_execarg {
union {
struct {
@@ -57,6 +57,7 @@ struct rb_execarg {
unsigned gid_given : 1;
unsigned exception : 1;
unsigned exception_given : 1;
+ struct rb_process_status *status;
struct waitpid_state *waitpid_state; /* for async process management */
rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0<V). */
VALUE rlimit_limits; /* Qfalse or [[rtype, softlim, hardlim], ...] */
@@ -74,7 +75,7 @@ struct rb_execarg {
};
/* process.c */
-rb_pid_t rb_fork_ruby(int *status);
+rb_pid_t rb_call_proc__fork(void);
void rb_last_status_clear(void);
static inline char **ARGVSTR2ARGV(VALUE argv_str);
static inline size_t ARGVSTR2ARGC(VALUE argv_str);
diff --git a/internal/ractor.h b/internal/ractor.h
new file mode 100644
index 0000000000..eef5ffdb89
--- /dev/null
+++ b/internal/ractor.h
@@ -0,0 +1,6 @@
+#ifndef INTERNAL_RACTOR_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_RACTOR_H
+
+void rb_ractor_ensure_main_ractor(const char *msg);
+
+#endif /* INTERNAL_RACTOR_H */
diff --git a/internal/random.h b/internal/random.h
index a92e65b8ba..231e2d5d7e 100644
--- a/internal/random.h
+++ b/internal/random.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/range.h b/internal/range.h
index 4fe6037c89..8daba0ecab 100644
--- a/internal/range.h
+++ b/internal/range.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/rational.h b/internal/rational.h
index a9e96742c9..61ddbf089a 100644
--- a/internal/rational.h
+++ b/internal/rational.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/re.h b/internal/re.h
index a19ad934f7..8b31b3d8a5 100644
--- a/internal/re.h
+++ b/internal/re.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/sanitizers.h b/internal/sanitizers.h
index b4f5bdeda1..6e2d81137f 100644
--- a/internal/sanitizers.h
+++ b/internal/sanitizers.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/serial.h b/internal/serial.h
index 977cb35477..df9e9a44f0 100644
--- a/internal/serial.h
+++ b/internal/serial.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/signal.h b/internal/signal.h
index 6b4672f15b..86fb54e949 100644
--- a/internal/signal.h
+++ b/internal/signal.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/static_assert.h b/internal/static_assert.h
index 284e410313..70dd0b7a1e 100644
--- a/internal/static_assert.h
+++ b/internal/static_assert.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/string.h b/internal/string.h
index 5062de4636..12edbff2b1 100644
--- a/internal/string.h
+++ b/internal/string.h
@@ -1,7 +1,6 @@
#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
@@ -43,6 +42,9 @@ 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);
+int rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code);
+VALUE rb_str_include(VALUE str, VALUE arg);
static inline bool STR_EMBED_P(VALUE str);
static inline bool STR_SHARED_P(VALUE str);
@@ -59,6 +61,10 @@ void rb_str_tmp_frozen_release(VALUE str, VALUE tmp);
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc);
VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE);
VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE);
+void rb_str_make_embedded(VALUE);
+size_t rb_str_size_as_embedded(VALUE);
+bool rb_str_reembeddable_p(VALUE);
+void rb_str_update_shared_ary(VALUE str, VALUE old_root, VALUE new_root);
RUBY_SYMBOL_EXPORT_END
MJIT_SYMBOL_EXPORT_BEGIN
@@ -100,7 +106,7 @@ STR_EMBED_P(VALUE str)
static inline bool
STR_SHARED_P(VALUE str)
{
- return FL_ALL_RAW(str, STR_NOEMBED | ELTS_SHARED);
+ return FL_ALL_RAW(str, STR_NOEMBED | STR_SHARED);
}
static inline bool
@@ -116,6 +122,7 @@ is_broken_string(VALUE str)
}
/* expect tail call optimization */
+// YJIT needs this function to never allocate and never raise
static inline VALUE
rb_str_eql_internal(const VALUE str1, const VALUE str2)
{
diff --git a/internal/struct.h b/internal/struct.h
index 82b2738b69..8acc00ec3c 100644
--- a/internal/struct.h
+++ b/internal/struct.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/symbol.h b/internal/symbol.h
index 691df66228..30c81ea004 100644
--- a/internal/symbol.h
+++ b/internal/symbol.h
@@ -1,7 +1,6 @@
#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
@@ -29,7 +28,9 @@ int rb_is_local_name(VALUE name);
PUREFUNC(int rb_is_const_sym(VALUE sym));
PUREFUNC(int rb_is_attrset_sym(VALUE sym));
ID rb_make_internal_id(void);
+ID rb_make_temporary_id(size_t n);
void rb_gc_free_dsymbol(VALUE);
+int rb_static_id_valid_p(ID id);
#if __has_builtin(__builtin_constant_p)
#define rb_sym_intern_ascii_cstr(ptr) \
diff --git a/internal/thread.h b/internal/thread.h
index 09b8551b5c..c3e54de683 100644
--- a/internal/thread.h
+++ b/internal/thread.h
@@ -1,7 +1,6 @@
#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
@@ -21,6 +20,7 @@ struct rb_thread_struct; /* in vm_core.h */
#define COVERAGE_TARGET_BRANCHES 2
#define COVERAGE_TARGET_METHODS 4
#define COVERAGE_TARGET_ONESHOT_LINES 8
+#define COVERAGE_TARGET_EVAL 16
VALUE rb_obj_is_mutex(VALUE obj);
VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
@@ -29,6 +29,7 @@ VALUE rb_get_coverages(void);
int rb_get_coverage_mode(void);
VALUE rb_default_coverage(int);
VALUE rb_thread_shield_new(void);
+bool rb_thread_shield_owned(VALUE self);
VALUE rb_thread_shield_wait(VALUE self);
VALUE rb_thread_shield_release(VALUE self);
VALUE rb_thread_shield_destroy(VALUE self);
@@ -36,6 +37,7 @@ 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);
+VALUE rb_exec_recursive_outer_mid(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h, ID mid);
int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout);
diff --git a/internal/time.h b/internal/time.h
index f9ac084603..e21b3574f6 100644
--- a/internal/time.h
+++ b/internal/time.h
@@ -1,7 +1,6 @@
#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
@@ -29,7 +28,10 @@ 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);
+#ifdef RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY
+RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY()
+#endif
+void ruby_reset_timezone(const char *);
RUBY_SYMBOL_EXPORT_END
#endif /* INTERNAL_TIME_H */
diff --git a/internal/transcode.h b/internal/transcode.h
index a60ac06d10..9922332ea9 100644
--- a/internal/transcode.h
+++ b/internal/transcode.h
@@ -1,7 +1,6 @@
#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
diff --git a/internal/util.h b/internal/util.h
index c28b884d32..6eadbb9f94 100644
--- a/internal/util.h
+++ b/internal/util.h
@@ -1,7 +1,6 @@
#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
@@ -23,9 +22,6 @@ char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign
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
index 057beccfcc..6dec6a6759 100644
--- a/internal/variable.h
+++ b/internal/variable.h
@@ -1,7 +1,6 @@
#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
@@ -14,10 +13,11 @@
#include "constant.h" /* for rb_const_entry_t */
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/ruby.h" /* for VALUE */
+#include "shape.h" /* for rb_shape_t */
/* global variable */
-#define ROBJECT_TRANSIENT_FLAG FL_USER13
+#define ROBJECT_TRANSIENT_FLAG FL_USER2
/* variable.c */
void rb_gc_mark_global_tbl(void);
@@ -25,7 +25,6 @@ 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));
@@ -37,6 +36,10 @@ static inline bool ROBJ_TRANSIENT_P(VALUE obj);
static inline void ROBJ_TRANSIENT_SET(VALUE obj);
static inline void ROBJ_TRANSIENT_UNSET(VALUE obj);
+struct gen_ivtbl;
+int rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl);
+int rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg);
+
RUBY_SYMBOL_EXPORT_BEGIN
/* variable.c (export) */
void rb_mark_generic_ivar(VALUE);
@@ -44,15 +47,18 @@ 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_ivar_lookup(VALUE obj, ID id, VALUE undef);
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);
+rb_shape_t * rb_grow_iv_list(VALUE obj);
+void rb_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize);
+struct gen_ivtbl *rb_ensure_generic_iv_list_size(VALUE obj, rb_shape_t *shape, uint32_t newsize);
+attr_index_t rb_obj_ivar_set(VALUE obj, ID id, VALUE val);
MJIT_SYMBOL_EXPORT_END
static inline bool
diff --git a/internal/vm.h b/internal/vm.h
index 8251b09e98..cf245c6579 100644
--- a/internal/vm.h
+++ b/internal/vm.h
@@ -1,7 +1,6 @@
#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
@@ -41,14 +40,13 @@ enum method_missing_reason {
};
/* vm_insnhelper.h */
-rb_serial_t rb_next_class_serial(void);
+VALUE rb_vm_push_frame_fname(struct rb_execution_context_struct *ec, VALUE fname);
/* 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);
@@ -97,6 +95,8 @@ 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
+void rb_clear_constant_cache(void);
+
/* vm_dump.c */
void rb_print_backtrace(void);
@@ -112,7 +112,8 @@ VALUE rb_backtrace_to_str_ary(VALUE obj);
VALUE rb_backtrace_to_location_ary(VALUE obj);
void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output);
int rb_frame_info_p(VALUE obj);
-void rb_frame_info_get(VALUE obj, VALUE *path, int *node_id);
+int rb_get_node_id_from_frame_info(VALUE obj);
+const struct rb_iseq_struct *rb_get_iseq_from_frame_info(VALUE obj);
MJIT_SYMBOL_EXPORT_BEGIN
VALUE rb_ec_backtrace_object(const struct rb_execution_context_struct *ec);
diff --git a/internal/warnings.h b/internal/warnings.h
index e9de46eb38..020212ebd8 100644
--- a/internal/warnings.h
+++ b/internal/warnings.h
@@ -1,7 +1,6 @@
#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
diff --git a/io.c b/io.c
index 4d5c3acd3a..99ec59da29 100644
--- a/io.c
+++ b/io.c
@@ -14,6 +14,7 @@
#include "ruby/internal/config.h"
#include "ruby/fiber/scheduler.h"
+#include "ruby/io/buffer.h"
#ifdef _WIN32
# include "ruby/ruby.h"
@@ -74,10 +75,6 @@
#include <sys/fcntl.h>
#endif
-#if !HAVE_OFF_T && !defined(off_t)
-# define off_t long
-#endif
-
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@@ -131,6 +128,8 @@
#include "internal/transcode.h"
#include "internal/variable.h"
#include "ruby/io.h"
+#include "ruby/io/buffer.h"
+#include "ruby/missing.h"
#include "ruby/thread.h"
#include "ruby/util.h"
#include "ruby_atomic.h"
@@ -146,10 +145,6 @@
#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#endif
-#if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
-# error off_t is bigger than long, but you have no long long...
-#endif
-
#ifndef PIPE_BUF
# ifdef _POSIX_PIPE_BUF
# define PIPE_BUF _POSIX_PIPE_BUF
@@ -172,6 +167,8 @@ off_t __syscall(quad_t number, ...);
#define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
#define IO_WBUF_CAPA_MIN 8192
+#define IO_MAX_BUFFER_GROWTH 8 * 1024 * 1024 // 8MB
+
/* define system APIs */
#ifdef _WIN32
#undef open
@@ -183,6 +180,7 @@ off_t __syscall(quad_t number, ...);
VALUE rb_cIO;
VALUE rb_eEOFError;
VALUE rb_eIOError;
+VALUE rb_eIOTimeoutError;
VALUE rb_mWaitReadable;
VALUE rb_mWaitWritable;
@@ -203,7 +201,7 @@ VALUE rb_default_rs;
static VALUE argf;
-static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
+static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
static VALUE sym_textmode, sym_binmode, sym_autoclose;
static VALUE sym_SET, sym_CUR, sym_END;
@@ -251,7 +249,7 @@ rb_update_max_fd(int fd)
}
while (max_fd < afd) {
- max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
+ max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
}
}
@@ -296,12 +294,18 @@ rb_fix_detect_o_cloexec(int fd)
rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
if (flags & FD_CLOEXEC)
- return 1;
+ return 1;
#endif /* fall through if O_CLOEXEC does not work: */
rb_maygvl_fd_fix_cloexec(fd);
return 0;
}
+static inline bool
+io_again_p(int e)
+{
+ return (e == EWOULDBLOCK) || (e == EAGAIN);
+}
+
int
rb_cloexec_open(const char *pathname, int flags, mode_t mode)
{
@@ -322,7 +326,7 @@ rb_cloexec_open(const char *pathname, int flags, mode_t mode)
while ((ret = open(pathname, flags, mode)) == -1) {
int e = errno;
- if (e != EAGAIN && e != EWOULDBLOCK) break;
+ if (!io_again_p(e)) break;
if (retry_count++ >= retry_max_count) break;
sleep(retry_interval);
@@ -330,13 +334,13 @@ rb_cloexec_open(const char *pathname, int flags, mode_t mode)
if (ret < 0) return ret;
if (ret <= 2 || o_cloexec_state == 0) {
- rb_maygvl_fd_fix_cloexec(ret);
+ rb_maygvl_fd_fix_cloexec(ret);
}
else if (o_cloexec_state > 0) {
- return ret;
+ return ret;
}
else {
- o_cloexec_state = rb_fix_detect_o_cloexec(ret);
+ o_cloexec_state = rb_fix_detect_o_cloexec(ret);
}
return ret;
}
@@ -492,15 +496,15 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd)
#if defined(_WIN32)
#define WAIT_FD_IN_WIN32(fptr) \
- (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : RB_NUM2INT(rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil)))
+ (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT))
#else
#define WAIT_FD_IN_WIN32(fptr)
#endif
#define READ_CHECK(fptr) do {\
if (!READ_DATA_PENDING(fptr)) {\
- WAIT_FD_IN_WIN32(fptr);\
- rb_io_check_closed(fptr);\
+ WAIT_FD_IN_WIN32(fptr);\
+ rb_io_check_closed(fptr);\
}\
} while(0)
@@ -589,19 +593,19 @@ raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
- if (((fptr)->mode & FMODE_READABLE) &&\
- !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
- setmode((fptr)->fd, O_BINARY);\
- }\
- else {\
- setmode((fptr)->fd, O_TEXT);\
- }\
+ if (((fptr)->mode & FMODE_READABLE) &&\
+ !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
+ setmode((fptr)->fd, O_BINARY);\
+ }\
+ else {\
+ setmode((fptr)->fd, O_TEXT);\
+ }\
}\
} while(0)
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
- (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
+ (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
}\
} while(0)
@@ -611,7 +615,7 @@ raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
static void
io_unread(rb_io_t *fptr)
{
- off_t r, pos;
+ rb_off_t r, pos;
ssize_t read_size;
long i;
long newlines = 0;
@@ -621,28 +625,28 @@ io_unread(rb_io_t *fptr)
rb_io_check_closed(fptr);
if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
- return;
+ return;
}
errno = 0;
if (!rb_w32_fd_is_text(fptr->fd)) {
- r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
- if (r < 0 && errno) {
- if (errno == ESPIPE)
- fptr->mode |= FMODE_DUPLEX;
- return;
- }
+ r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
+ if (r < 0 && errno) {
+ if (errno == ESPIPE)
+ fptr->mode |= FMODE_DUPLEX;
+ return;
+ }
- fptr->rbuf.off = 0;
- fptr->rbuf.len = 0;
- return;
+ fptr->rbuf.off = 0;
+ fptr->rbuf.len = 0;
+ return;
}
pos = lseek(fptr->fd, 0, SEEK_CUR);
if (pos < 0 && errno) {
- if (errno == ESPIPE)
- fptr->mode |= FMODE_DUPLEX;
- return;
+ if (errno == ESPIPE)
+ fptr->mode |= FMODE_DUPLEX;
+ return;
}
/* add extra offset for removed '\r' in rbuf */
@@ -651,36 +655,36 @@ io_unread(rb_io_t *fptr)
/* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
- newlines++;
+ newlines++;
}
for (i = 0; i < fptr->rbuf.len; i++) {
- if (*p == '\n') newlines++;
- if (extra_max == newlines) break;
- p++;
+ if (*p == '\n') newlines++;
+ if (extra_max == newlines) break;
+ p++;
}
buf = ALLOC_N(char, fptr->rbuf.len + newlines);
while (newlines >= 0) {
- r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
- if (newlines == 0) break;
- if (r < 0) {
- newlines--;
- continue;
- }
- read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
- if (read_size < 0) {
- int e = errno;
- free(buf);
- rb_syserr_fail_path(e, fptr->pathv);
- }
- if (read_size == fptr->rbuf.len) {
- lseek(fptr->fd, r, SEEK_SET);
- break;
- }
- else {
- newlines--;
- }
+ r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
+ if (newlines == 0) break;
+ if (r < 0) {
+ newlines--;
+ continue;
+ }
+ read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
+ if (read_size < 0) {
+ int e = errno;
+ free(buf);
+ rb_syserr_fail_path(e, fptr->pathv);
+ }
+ if (read_size == fptr->rbuf.len) {
+ lseek(fptr->fd, r, SEEK_SET);
+ break;
+ }
+ else {
+ newlines--;
+ }
}
free(buf);
fptr->rbuf.off = 0;
@@ -701,7 +705,7 @@ set_binary_mode_with_seek_cur(rb_io_t *fptr)
if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
- return setmode(fptr->fd, O_BINARY);
+ return setmode(fptr->fd, O_BINARY);
}
flush_before_seek(fptr);
return setmode(fptr->fd, O_BINARY);
@@ -770,7 +774,7 @@ void
rb_io_check_initialized(rb_io_t *fptr)
{
if (!fptr) {
- rb_raise(rb_eIOError, "uninitialized stream");
+ rb_raise(rb_eIOError, "uninitialized stream");
}
}
@@ -818,10 +822,10 @@ rb_io_set_write_io(VALUE io, VALUE w)
VALUE write_io;
rb_io_t *fptr = rb_io_get_fptr(io);
if (!RTEST(w)) {
- w = 0;
+ w = 0;
}
else {
- GetWriteIO(w);
+ GetWriteIO(w);
}
write_io = fptr->tied_io_for_writing;
fptr->tied_io_for_writing = w;
@@ -830,19 +834,62 @@ rb_io_set_write_io(VALUE io, VALUE w)
/*
* call-seq:
- * IO.try_convert(obj) -> io or nil
+ * timeout -> duration or nil
+ *
+ * Get the internal timeout duration or nil if it was not set.
+ *
+ */
+VALUE
+rb_io_timeout(VALUE self)
+{
+ rb_io_t *fptr = rb_io_get_fptr(self);
+
+ return fptr->timeout;
+}
+
+/*
+ * call-seq:
+ * timeout = duration -> duration
+ * timeout = nil -> nil
+ *
+ * Set the internal timeout to the specified duration or nil. The timeout
+ * applies to all blocking operations where possible.
+ *
+ * This affects the following methods (but is not limited to): #gets, #puts,
+ * #read, #write, #wait_readable and #wait_writable. This also affects
+ * blocking socket operations like Socket#accept and Socket#connect.
*
- * Try to convert <i>obj</i> into an IO, using to_io method.
- * Returns converted IO or +nil+ if <i>obj</i> cannot be converted
- * for any reason.
+ * Some operations like File#open and IO#close are not affected by the
+ * timeout. A timeout during a write operation may leave the IO in an
+ * inconsistent state, e.g. data was partially written. Generally speaking, a
+ * timeout is a last ditch effort to prevent an application from hanging on
+ * slow I/O operations, such as those that occur during a slowloris attack.
+ */
+VALUE
+rb_io_set_timeout(VALUE self, VALUE timeout)
+{
+ // Validate it:
+ if (RTEST(timeout)) {
+ rb_time_interval(timeout);
+ }
+
+ rb_io_t *fptr = rb_io_get_fptr(self);
+
+ fptr->timeout = timeout;
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * IO.try_convert(object) -> new_io or nil
*
- * IO.try_convert(STDOUT) #=> STDOUT
- * IO.try_convert("STDOUT") #=> nil
+ * Attempts to convert +object+ into an \IO object via method +to_io+;
+ * returns the new \IO object if successful, or +nil+ otherwise:
*
- * require 'zlib'
- * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
- * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
- * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
+ * IO.try_convert(STDOUT) # => #<IO:<STDOUT>>
+ * IO.try_convert(ARGF) # => #<IO:<STDIN>>
+ * IO.try_convert('STDOUT') # => nil
*
*/
static VALUE
@@ -855,7 +902,7 @@ rb_io_s_try_convert(VALUE dummy, VALUE io)
static void
io_unread(rb_io_t *fptr)
{
- off_t r;
+ rb_off_t r;
rb_io_check_closed(fptr);
if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
return;
@@ -885,17 +932,17 @@ io_ungetbyte(VALUE str, rb_io_t *fptr)
fptr->rbuf.off = 0;
fptr->rbuf.len = 0;
#if SIZEOF_LONG > SIZEOF_INT
- if (len > INT_MAX)
- rb_raise(rb_eIOError, "ungetbyte failed");
+ if (len > INT_MAX)
+ rb_raise(rb_eIOError, "ungetbyte failed");
#endif
- if (len > min_capa)
- fptr->rbuf.capa = (int)len;
- else
- fptr->rbuf.capa = min_capa;
+ if (len > min_capa)
+ fptr->rbuf.capa = (int)len;
+ else
+ fptr->rbuf.capa = min_capa;
fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
}
if (fptr->rbuf.capa < len + fptr->rbuf.len) {
- rb_raise(rb_eIOError, "ungetbyte failed");
+ rb_raise(rb_eIOError, "ungetbyte failed");
}
if (fptr->rbuf.off < len) {
MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
@@ -932,15 +979,15 @@ rb_io_check_char_readable(rb_io_t *fptr)
{
rb_io_check_closed(fptr);
if (!(fptr->mode & FMODE_READABLE)) {
- rb_raise(rb_eIOError, "not opened for reading");
+ rb_raise(rb_eIOError, "not opened for reading");
}
if (fptr->wbuf.len) {
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
}
if (fptr->tied_io_for_writing) {
- rb_io_t *wfptr;
- GetOpenFile(fptr->tied_io_for_writing, wfptr);
+ rb_io_t *wfptr;
+ GetOpenFile(fptr->tied_io_for_writing, wfptr);
if (io_fflush(wfptr) < 0)
rb_sys_fail_on_write(wfptr);
}
@@ -951,7 +998,7 @@ rb_io_check_byte_readable(rb_io_t *fptr)
{
rb_io_check_char_readable(fptr);
if (READ_CHAR_PENDING(fptr)) {
- rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
+ rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
}
}
@@ -965,7 +1012,7 @@ static rb_encoding*
io_read_encoding(rb_io_t *fptr)
{
if (fptr->encs.enc) {
- return fptr->encs.enc;
+ return fptr->encs.enc;
}
return rb_default_external_encoding();
}
@@ -974,7 +1021,7 @@ static rb_encoding*
io_input_encoding(rb_io_t *fptr)
{
if (fptr->encs.enc2) {
- return fptr->encs.enc2;
+ return fptr->encs.enc2;
}
return io_read_encoding(fptr);
}
@@ -984,7 +1031,7 @@ rb_io_check_writable(rb_io_t *fptr)
{
rb_io_check_closed(fptr);
if (!(fptr->mode & FMODE_WRITABLE)) {
- rb_raise(rb_eIOError, "not opened for writing");
+ rb_raise(rb_eIOError, "not opened for writing");
}
if (fptr->rbuf.len) {
io_unread(fptr);
@@ -1004,7 +1051,7 @@ void
rb_io_read_check(rb_io_t *fptr)
{
if (!READ_DATA_PENDING(fptr)) {
- rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
+ rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT);
}
return;
}
@@ -1013,8 +1060,8 @@ int
rb_gc_for_fd(int err)
{
if (err == EMFILE || err == ENFILE || err == ENOMEM) {
- rb_gc();
- return 1;
+ rb_gc();
+ return 1;
}
return 0;
}
@@ -1026,13 +1073,13 @@ ruby_dup(int orig)
fd = rb_cloexec_dup(orig);
if (fd < 0) {
- int e = errno;
- if (rb_gc_for_fd(e)) {
- fd = rb_cloexec_dup(orig);
- }
- if (fd < 0) {
- rb_syserr_fail(e, 0);
- }
+ int e = errno;
+ if (rb_gc_for_fd(e)) {
+ fd = rb_cloexec_dup(orig);
+ }
+ if (fd < 0) {
+ rb_syserr_fail(e, 0);
+ }
}
rb_update_max_fd(fd);
return fd;
@@ -1054,64 +1101,126 @@ io_alloc(VALUE klass)
struct io_internal_read_struct {
VALUE th;
- int fd;
+ rb_io_t *fptr;
int nonblock;
+ int fd;
+
void *buf;
size_t capa;
+ struct timeval *timeout;
};
struct io_internal_write_struct {
+ VALUE th;
+ rb_io_t *fptr;
+ int nonblock;
int fd;
+
const void *buf;
size_t capa;
+ struct timeval *timeout;
};
#ifdef HAVE_WRITEV
struct io_internal_writev_struct {
+ VALUE th;
+ rb_io_t *fptr;
+ int nonblock;
int fd;
+
int iovcnt;
const struct iovec *iov;
+ struct timeval *timeout;
};
#endif
-static int nogvl_wait_for_single_fd(VALUE th, int fd, short events);
+static int nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval *timeout);
+
+/**
+ * Wait for the given events on the given file descriptor.
+ * Returns -1 if an error or timeout occurred. +errno+ will be set.
+ * Returns the event mask if an event occurred.
+ */
+static inline int
+io_internal_wait(VALUE thread, rb_io_t *fptr, int error, int events, struct timeval *timeout)
+{
+ int ready = nogvl_wait_for(thread, fptr, events, timeout);
+
+ if (ready > 0) {
+ return ready;
+ }
+ else if (ready == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ errno = error;
+ return -1;
+}
+
static VALUE
internal_read_func(void *ptr)
{
struct io_internal_read_struct *iis = ptr;
- ssize_t r;
-retry:
- r = read(iis->fd, iis->buf, iis->capa);
- if (r < 0 && !iis->nonblock) {
- int e = errno;
- if (e == EAGAIN || e == EWOULDBLOCK) {
- if (nogvl_wait_for_single_fd(iis->th, iis->fd, RB_WAITFD_IN) != -1) {
+ ssize_t result;
+
+ if (iis->timeout && !iis->nonblock) {
+ if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
+ return -1;
+ }
+ }
+
+ retry:
+ result = read(iis->fd, iis->buf, iis->capa);
+
+ if (result < 0 && !iis->nonblock) {
+ if (io_again_p(errno)) {
+ if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_IN, iis->timeout) == -1) {
+ return -1;
+ }
+ else {
goto retry;
}
- errno = e;
}
}
- return r;
+
+ return result;
}
#if defined __APPLE__
-# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
+# define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
#else
-# define do_write_retry(code) ret = code
+# define do_write_retry(code) result = code
#endif
+
static VALUE
internal_write_func(void *ptr)
{
struct io_internal_write_struct *iis = ptr;
- ssize_t ret;
+ ssize_t result;
+
+ if (iis->timeout && !iis->nonblock) {
+ if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
+ return -1;
+ }
+ }
+
+ retry:
do_write_retry(write(iis->fd, iis->buf, iis->capa));
- return (VALUE)ret;
-}
-static void*
-internal_write_func2(void *ptr)
-{
- return (void*)internal_write_func(ptr);
+ if (result < 0 && !iis->nonblock) {
+ int e = errno;
+ if (io_again_p(e)) {
+ if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
+ return -1;
+ }
+ else {
+ goto retry;
+ }
+ }
+ }
+
+ return result;
}
#ifdef HAVE_WRITEV
@@ -1119,62 +1228,133 @@ static VALUE
internal_writev_func(void *ptr)
{
struct io_internal_writev_struct *iis = ptr;
- ssize_t ret;
+ ssize_t result;
+
+ if (iis->timeout && !iis->nonblock) {
+ if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
+ return -1;
+ }
+ }
+
+ retry:
do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
- return (VALUE)ret;
+
+ if (result < 0 && !iis->nonblock) {
+ if (io_again_p(errno)) {
+ if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
+ return -1;
+ }
+ else {
+ goto retry;
+ }
+ }
+ }
+
+ return result;
}
#endif
static ssize_t
-rb_read_internal(int fd, void *buf, size_t count)
+rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, fptr->self, buf, count, 0);
+
+ if (!UNDEF_P(result)) {
+ return rb_fiber_scheduler_io_result_apply(result);
+ }
+ }
+
struct io_internal_read_struct iis = {
.th = rb_thread_current(),
- .fd = fd,
+ .fptr = fptr,
.nonblock = 0,
+ .fd = fptr->fd,
+
.buf = buf,
- .capa = count
+ .capa = count,
+ .timeout = NULL,
};
- return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
-}
+ struct timeval timeout_storage;
-static ssize_t
-rb_write_internal(int fd, const void *buf, size_t count)
-{
- struct io_internal_write_struct iis = {
- .fd = fd,
- .buf = buf,
- .capa = count
- };
+ if (fptr->timeout != Qnil) {
+ timeout_storage = rb_time_interval(fptr->timeout);
+ iis.timeout = &timeout_storage;
+ }
- return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
+ return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->fd);
}
static ssize_t
-rb_write_internal2(int fd, const void *buf, size_t count)
+rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, buf, count, 0);
+
+ if (!UNDEF_P(result)) {
+ return rb_fiber_scheduler_io_result_apply(result);
+ }
+ }
+
struct io_internal_write_struct iis = {
- .fd = fd,
+ .th = rb_thread_current(),
+ .fptr = fptr,
+ .nonblock = 0,
+ .fd = fptr->fd,
+
.buf = buf,
- .capa = count
+ .capa = count,
+ .timeout = NULL
};
- return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
- RUBY_UBF_IO, NULL);
+ struct timeval timeout_storage;
+
+ if (fptr->timeout != Qnil) {
+ timeout_storage = rb_time_interval(fptr->timeout);
+ iis.timeout = &timeout_storage;
+ }
+
+ return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->fd);
}
#ifdef HAVE_WRITEV
static ssize_t
-rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
+rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
{
+ if (!iovcnt) return 0;
+
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ // This path assumes at least one `iov`:
+ VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[0].iov_base, iov[0].iov_len, 0);
+
+ if (!UNDEF_P(result)) {
+ return rb_fiber_scheduler_io_result_apply(result);
+ }
+ }
+
struct io_internal_writev_struct iis = {
- .fd = fd,
+ .th = rb_thread_current(),
+ .fptr = fptr,
+ .nonblock = 0,
+ .fd = fptr->fd,
+
.iov = iov,
.iovcnt = iovcnt,
+ .timeout = NULL
};
- return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
+ struct timeval timeout_storage;
+
+ if (fptr->timeout != Qnil) {
+ timeout_storage = rb_time_interval(fptr->timeout);
+ iis.timeout = &timeout_storage;
+ }
+
+ return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->fd);
}
#endif
@@ -1186,28 +1366,18 @@ io_flush_buffer_sync(void *arg)
ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
if (fptr->wbuf.len <= r) {
- fptr->wbuf.off = 0;
- fptr->wbuf.len = 0;
- return 0;
+ fptr->wbuf.off = 0;
+ fptr->wbuf.len = 0;
+ return 0;
}
+
if (0 <= r) {
- fptr->wbuf.off += (int)r;
- fptr->wbuf.len -= (int)r;
- errno = EAGAIN;
+ fptr->wbuf.off += (int)r;
+ fptr->wbuf.len -= (int)r;
+ errno = EAGAIN;
}
- return (VALUE)-1;
-}
-static void*
-io_flush_buffer_sync2(void *arg)
-{
- VALUE result = io_flush_buffer_sync(arg);
-
- /*
- * rb_thread_call_without_gvl2 uses 0 as interrupted.
- * So, we need to avoid to use 0.
- */
- return !result ? (void*)1 : (void*)result;
+ return (VALUE)-1;
}
static VALUE
@@ -1217,36 +1387,14 @@ io_flush_buffer_async(VALUE arg)
return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
}
-static VALUE
-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);
-
- if (!ret) {
- /* pending async interrupt is there. */
- errno = EAGAIN;
- return -1;
- }
- else if (ret == 1) {
- return 0;
- }
- return ret;
-}
-
static inline int
io_flush_buffer(rb_io_t *fptr)
{
- if (fptr->write_lock) {
- if (rb_mutex_owned_p(fptr->write_lock))
- return (int)io_flush_buffer_async2((VALUE)fptr);
- else
- return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
+ if (!NIL_P(fptr->write_lock) && rb_mutex_owned_p(fptr->write_lock)) {
+ return (int)io_flush_buffer_async((VALUE)fptr);
}
else {
- return (int)io_flush_buffer_async((VALUE)fptr);
+ return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async, (VALUE)fptr);
}
}
@@ -1259,7 +1407,7 @@ io_fflush(rb_io_t *fptr)
return 0;
while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
- if (!rb_io_maybe_wait_writable(errno, fptr->self, Qnil))
+ if (!rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT))
return -1;
rb_io_check_closed(fptr);
@@ -1283,6 +1431,10 @@ rb_io_wait(VALUE io, VALUE events, VALUE timeout)
struct timeval tv_storage;
struct timeval *tv = NULL;
+ if (NIL_OR_UNDEF_P(timeout)) {
+ timeout = fptr->timeout;
+ }
+
if (timeout != Qnil) {
tv_storage = rb_time_interval(timeout);
tv = &tv_storage;
@@ -1297,7 +1449,7 @@ rb_io_wait(VALUE io, VALUE events, VALUE timeout)
// Not sure if this is necessary:
rb_io_check_closed(fptr);
- if (ready > 0) {
+ if (ready) {
return RB_INT2NUM(ready);
}
else {
@@ -1311,8 +1463,8 @@ io_from_fd(int fd)
return prep_io(fd, FMODE_PREP, rb_cIO, NULL);
}
-static
-int io_wait_for_single_fd(int fd, int events, struct timeval *timeout)
+static int
+io_wait_for_single_fd(int fd, int events, struct timeval *timeout)
{
VALUE scheduler = rb_fiber_scheduler_current();
@@ -1341,7 +1493,7 @@ rb_io_wait_readable(int f)
return TRUE;
case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
if (scheduler != Qnil) {
@@ -1375,8 +1527,8 @@ rb_io_wait_writable(int f)
* 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
+ * e.g. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
+ * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
* In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
* Then rb_thread_check_ints() is enough.
*/
@@ -1384,7 +1536,7 @@ rb_io_wait_writable(int f)
return TRUE;
case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
if (scheduler != Qnil) {
@@ -1420,7 +1572,8 @@ rb_thread_fd_writable(int fd)
return rb_wait_for_single_fd(fd, RUBY_IO_WRITABLE, NULL);
}
-VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
+VALUE
+rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
{
// fptr->fd can be set to -1 at any time by another thread when the GVL is
// released. Many code, e.g. `io_bufread` didn't check this correctly and
@@ -1433,8 +1586,8 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
// 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
+ // e.g. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
+ // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
// In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
// Then rb_thread_check_ints() is enough.
case EINTR:
@@ -1448,7 +1601,7 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
return events;
case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
// The operation would block, so wait for the specified events:
@@ -1456,18 +1609,34 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
default:
// Non-specific error, no event is ready:
- return RB_INT2NUM(0);
+ return Qfalse;
}
}
-int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
+int
+rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
{
- return RB_NUM2INT(rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_READABLE), timeout));
+ VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
+
+ if (RTEST(result)) {
+ return RB_NUM2INT(result);
+ }
+ else {
+ return 0;
+ }
}
-int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
+int
+rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
{
- return RB_NUM2INT(rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_WRITABLE), timeout));
+ VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_WRITABLE), timeout);
+
+ if (RTEST(result)) {
+ return RB_NUM2INT(result);
+ }
+ else {
+ return 0;
+ }
}
static void
@@ -1484,7 +1653,7 @@ make_writeconv(rb_io_t *fptr)
ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
ecopts = fptr->encs.ecopts;
- if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
+ if (!fptr->encs.enc || (rb_is_ascii8bit_enc(fptr->encs.enc) && !fptr->encs.enc2)) {
/* no encoding conversion */
fptr->writeconv_pre_ecflags = 0;
fptr->writeconv_pre_ecopts = Qnil;
@@ -1540,144 +1709,180 @@ struct write_arg {
};
#ifdef HAVE_WRITEV
-static VALUE
-io_binwrite_string(VALUE arg)
+static ssize_t
+io_binwrite_string_internal(rb_io_t *fptr, const char *ptr, long length)
{
- struct binwrite_arg *p = (struct binwrite_arg *)arg;
- rb_io_t *fptr = p->fptr;
- long r;
-
if (fptr->wbuf.len) {
- struct iovec iov[2];
+ struct iovec iov[2];
- iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
- iov[0].iov_len = fptr->wbuf.len;
- iov[1].iov_base = (char *)p->ptr;
- iov[1].iov_len = p->length;
+ iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
+ iov[0].iov_len = fptr->wbuf.len;
+ iov[1].iov_base = (void*)ptr;
+ iov[1].iov_len = length;
- r = rb_writev_internal(fptr->fd, iov, 2);
+ ssize_t result = rb_writev_internal(fptr, iov, 2);
- if (r < 0)
- return r;
+ if (result < 0)
+ return result;
- if (fptr->wbuf.len <= r) {
- r -= fptr->wbuf.len;
- fptr->wbuf.off = 0;
- fptr->wbuf.len = 0;
- }
- else {
- fptr->wbuf.off += (int)r;
- fptr->wbuf.len -= (int)r;
- r = 0L;
- }
+ if (result >= fptr->wbuf.len) {
+ // We wrote more than the internal buffer:
+ result -= fptr->wbuf.len;
+ fptr->wbuf.off = 0;
+ fptr->wbuf.len = 0;
+ }
+ else {
+ // We only wrote less data than the internal buffer:
+ fptr->wbuf.off += (int)result;
+ fptr->wbuf.len -= (int)result;
+
+ result = 0;
+ }
+
+ return result;
}
else {
- r = rb_write_internal(fptr->fd, p->ptr, p->length);
+ return rb_io_write_memory(fptr, ptr, length);
}
-
- return r;
}
#else
-static VALUE
-io_binwrite_string(VALUE arg)
+static ssize_t
+io_binwrite_string_internal(rb_io_t *fptr, const char *ptr, long length)
{
- struct binwrite_arg *p = (struct binwrite_arg *)arg;
- rb_io_t *fptr = p->fptr;
- long l, len;
-
- l = len = p->length;
+ long remaining = length;
if (fptr->wbuf.len) {
- if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
- if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
- MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
- fptr->wbuf.off = 0;
- }
- MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
- fptr->wbuf.len += (int)len;
- l = 0;
- }
- if (io_fflush(fptr) < 0)
- return -2L; /* fail in fflush */
- if (l == 0)
- return len;
+ if (fptr->wbuf.len+length <= fptr->wbuf.capa) {
+ if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+length) {
+ MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
+ fptr->wbuf.off = 0;
+ }
+
+ MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr, char, length);
+ fptr->wbuf.len += (int)length;
+
+ // We copied the entire incoming data to the internal buffer:
+ remaining = 0;
+ }
+
+ // Flush the internal buffer:
+ if (io_fflush(fptr) < 0) {
+ return -1;
+ }
+
+ // If all the data was buffered, we are done:
+ if (remaining == 0) {
+ return length;
+ }
}
- return rb_write_internal(p->fptr->fd, p->ptr, p->length);
+ // Otherwise, we should write the data directly:
+ return rb_io_write_memory(fptr, ptr, length);
}
#endif
-static long
-io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
+static VALUE
+io_binwrite_string(VALUE arg)
{
- long n, r, offset = 0;
-
- /* don't write anything if current thread has a pending interrupt. */
- rb_thread_check_ints();
-
- if ((n = len) <= 0) return n;
-
- VALUE scheduler = rb_fiber_scheduler_current();
- if (scheduler != Qnil) {
- VALUE result = rb_fiber_scheduler_io_write(scheduler, fptr->self, str, offset, len);
+ struct binwrite_arg *p = (struct binwrite_arg *)arg;
- if (result != Qundef) {
- ssize_t length = RB_NUM2SSIZE(result);
+ const char *ptr = p->ptr;
+ size_t remaining = p->length;
- if (length < 0) rb_sys_fail_path(fptr->pathv);
+ while (remaining) {
+ // Write as much as possible:
+ ssize_t result = io_binwrite_string_internal(p->fptr, ptr, remaining);
- return length;
+ if (result == 0) {
+ // If only the internal buffer is written, result will be zero [bytes of given data written]. This means we
+ // should try again immediately.
+ }
+ else if (result > 0) {
+ if ((size_t)result == remaining) break;
+ ptr += result;
+ remaining -= result;
+ }
+ // Wait for it to become writable:
+ else if (rb_io_maybe_wait_writable(errno, p->fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_io_check_closed(p->fptr);
+ }
+ else {
+ // The error was unrelated to waiting for it to become writable, so we fail:
+ return -1;
}
}
- if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
+ return p->length;
+}
+
+inline static void
+io_allocate_write_buffer(rb_io_t *fptr, int sync)
+{
+ if (fptr->wbuf.ptr == NULL && !(sync && (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);
+ }
+
+ if (NIL_P(fptr->write_lock)) {
fptr->write_lock = rb_mutex_new();
- rb_mutex_allow_trap(fptr->write_lock, 1);
+ rb_mutex_allow_trap(fptr->write_lock, 1);
}
- if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
- (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
- struct binwrite_arg arg;
+}
- arg.fptr = fptr;
- arg.str = str;
- retry:
- arg.ptr = ptr + offset;
- arg.length = n;
- if (fptr->write_lock) {
- r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
- }
- else {
- r = io_binwrite_string((VALUE)&arg);
- }
- /* xxx: other threads may modify given string. */
- if (r == n) return len;
- if (0 <= r) {
- offset += r;
- n -= r;
- errno = EAGAIN;
- }
- if (r == -2L)
- return -1L;
- if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
- rb_io_check_closed(fptr);
- if (offset < len)
- goto retry;
+static inline int
+io_binwrite_requires_flush_write(rb_io_t *fptr, long len, int nosync)
+{
+ // If the requested operation was synchronous and the output mode is synchronus or a TTY:
+ if (!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY)))
+ return 1;
+
+ // If the amount of data we want to write exceeds the internal buffer:
+ if (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)
+ return 1;
+
+ // Otherwise, we can append to the internal buffer:
+ return 0;
+}
+
+static long
+io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
+{
+ if (len <= 0) return len;
+
+ // Don't write anything if current thread has a pending interrupt:
+ rb_thread_check_ints();
+
+ io_allocate_write_buffer(fptr, !nosync);
+
+ if (io_binwrite_requires_flush_write(fptr, len, nosync)) {
+ struct binwrite_arg arg;
+
+ arg.fptr = fptr;
+ arg.str = str;
+ arg.ptr = ptr;
+ arg.length = len;
+
+ if (!NIL_P(fptr->write_lock)) {
+ return rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
+ }
+ else {
+ return io_binwrite_string((VALUE)&arg);
}
- return -1L;
}
+ else {
+ if (fptr->wbuf.off) {
+ if (fptr->wbuf.len)
+ MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
+ fptr->wbuf.off = 0;
+ }
- if (fptr->wbuf.off) {
- if (fptr->wbuf.len)
- MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
- fptr->wbuf.off = 0;
+ MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr, char, len);
+ fptr->wbuf.len += (int)len;
+
+ return len;
}
- MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
- fptr->wbuf.len += (int)len;
- return len;
}
# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
@@ -1692,7 +1897,7 @@ do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
{
if (NEED_WRITECONV(fptr)) {
VALUE common_encoding = Qnil;
- SET_BINARY_MODE(fptr);
+ SET_BINARY_MODE(fptr);
make_writeconv(fptr);
@@ -1716,27 +1921,27 @@ do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
if (!NIL_P(common_encoding)) {
str = rb_str_encode(str, common_encoding,
fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
- *converted = 1;
+ *converted = 1;
}
if (fptr->writeconv) {
str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
- *converted = 1;
+ *converted = 1;
}
}
#if RUBY_CRLF_ENVIRONMENT
#define fmode (fptr->mode)
else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
- if ((fptr->mode & FMODE_READABLE) &&
- !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
- setmode(fptr->fd, O_BINARY);
- }
- else {
- setmode(fptr->fd, O_TEXT);
- }
- if (!rb_enc_asciicompat(rb_enc_get(str))) {
- rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
- rb_enc_name(rb_enc_get(str)));
+ if ((fptr->mode & FMODE_READABLE) &&
+ !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
+ setmode(fptr->fd, O_BINARY);
+ }
+ else {
+ setmode(fptr->fd, O_TEXT);
+ }
+ if (!rb_enc_asciicompat(rb_enc_get(str))) {
+ rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
+ rb_enc_name(rb_enc_get(str)));
}
}
#undef fmode
@@ -1751,15 +1956,17 @@ io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
VALUE tmp;
long n, len;
const char *ptr;
+
#ifdef _WIN32
if (fptr->mode & FMODE_TTY) {
- long len = rb_w32_write_console(str, fptr->fd);
- if (len > 0) return len;
+ long len = rb_w32_write_console(str, fptr->fd);
+ if (len > 0) return len;
}
#endif
+
str = do_writeconv(str, fptr, &converted);
if (converted)
- OBJ_FREEZE(str);
+ OBJ_FREEZE(str);
tmp = rb_str_tmp_frozen_acquire(str);
RSTRING_GETMEM(tmp, ptr, len);
@@ -1789,10 +1996,12 @@ io_write(VALUE io, VALUE str, int nosync)
io = GetWriteIO(io);
str = rb_obj_as_string(str);
tmp = rb_io_check_io(io);
+
if (NIL_P(tmp)) {
- /* port is not IO, call write method for it. */
- return rb_funcall(io, id_write, 1, str);
+ /* port is not IO, call write method for it. */
+ return rb_funcall(io, id_write, 1, str);
}
+
io = tmp;
if (RSTRING_LEN(str) == 0) return INT2FIX(0);
@@ -1808,104 +2017,124 @@ io_write(VALUE io, VALUE str, int nosync)
#ifdef HAVE_WRITEV
struct binwritev_arg {
rb_io_t *fptr;
- const struct iovec *iov;
+ struct iovec *iov;
int iovcnt;
+ size_t total;
};
static VALUE
-call_writev_internal(VALUE arg)
+io_binwritev_internal(VALUE arg)
{
struct binwritev_arg *p = (struct binwritev_arg *)arg;
- return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
+
+ size_t remaining = p->total;
+ size_t offset = 0;
+
+ rb_io_t *fptr = p->fptr;
+ struct iovec *iov = p->iov;
+ int iovcnt = p->iovcnt;
+
+ while (remaining) {
+ long result = rb_writev_internal(fptr, iov, iovcnt);
+
+ if (result >= 0) {
+ offset += result;
+ if (fptr->wbuf.ptr && fptr->wbuf.len) {
+ if (offset < (size_t)fptr->wbuf.len) {
+ fptr->wbuf.off += result;
+ fptr->wbuf.len -= result;
+ }
+ else {
+ offset -= (size_t)fptr->wbuf.len;
+ fptr->wbuf.off = 0;
+ fptr->wbuf.len = 0;
+ }
+ }
+
+ if (offset == p->total) {
+ return p->total;
+ }
+
+ while (result >= (ssize_t)iov->iov_len) {
+ /* iovcnt > 0 */
+ result -= iov->iov_len;
+ iov->iov_len = 0;
+ iov++;
+
+ if (!--iovcnt) {
+ // I don't believe this code path can ever occur.
+ return offset;
+ }
+ }
+
+ iov->iov_base = (char *)iov->iov_base + result;
+ iov->iov_len -= result;
+ }
+ else if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
+ rb_io_check_closed(fptr);
+ }
+ else {
+ return -1;
+ }
+ }
+
+ return offset;
}
static long
io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
{
- int i;
- long r, total = 0, written_len = 0;
-
- /* don't write anything if current thread has a pending interrupt. */
+ // Don't write anything if current thread has a pending interrupt:
rb_thread_check_ints();
if (iovcnt == 0) return 0;
- for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
- if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
- fptr->wbuf.off = 0;
- fptr->wbuf.len = 0;
- fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
- fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
- fptr->write_lock = rb_mutex_new();
- rb_mutex_allow_trap(fptr->write_lock, 1);
- }
+ size_t total = 0;
+ for (int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
+
+ io_allocate_write_buffer(fptr, 1);
if (fptr->wbuf.ptr && fptr->wbuf.len) {
- long offset = fptr->wbuf.off + fptr->wbuf.len;
- if (offset + total <= fptr->wbuf.capa) {
- for (i = 1; i < iovcnt; i++) {
- memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
- offset += iov[i].iov_len;
- }
- fptr->wbuf.len += total;
- return total;
- }
- else {
- iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
- iov[0].iov_len = fptr->wbuf.len;
- }
- }
- else {
- iov++;
- if (!--iovcnt) return 0;
- }
+ // The end of the buffered data:
+ size_t offset = fptr->wbuf.off + fptr->wbuf.len;
- retry:
- if (fptr->write_lock) {
- struct binwritev_arg arg;
- arg.fptr = fptr;
- arg.iov = iov;
- arg.iovcnt = iovcnt;
- r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
+ if (offset + total <= (size_t)fptr->wbuf.capa) {
+ for (int i = 1; i < iovcnt; i++) {
+ memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
+ offset += iov[i].iov_len;
+ }
+
+ fptr->wbuf.len += total;
+
+ return total;
+ }
+ else {
+ iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
+ iov[0].iov_len = fptr->wbuf.len;
+ }
}
else {
- r = rb_writev_internal(fptr->fd, iov, iovcnt);
- }
+ // The first iov is reserved for the internal buffer, and it's empty.
+ iov++;
- if (r >= 0) {
- written_len += r;
- if (fptr->wbuf.ptr && fptr->wbuf.len) {
- if (written_len < fptr->wbuf.len) {
- fptr->wbuf.off += r;
- fptr->wbuf.len -= r;
- }
- else {
- written_len -= fptr->wbuf.len;
- fptr->wbuf.off = 0;
- fptr->wbuf.len = 0;
- }
- }
- if (written_len == total) return total;
+ if (!--iovcnt) {
+ // If there are no other io vectors we are done.
+ return 0;
+ }
+ }
- while (r >= (ssize_t)iov->iov_len) {
- /* iovcnt > 0 */
- r -= iov->iov_len;
- iov->iov_len = 0;
- iov++;
- if (!--iovcnt) return total;
- /* defensive check: written_len should == total */
- }
- iov->iov_base = (char *)iov->iov_base + r;
- iov->iov_len -= r;
+ struct binwritev_arg arg;
+ arg.fptr = fptr;
+ arg.iov = iov;
+ arg.iovcnt = iovcnt;
+ arg.total = total;
- errno = EAGAIN;
+ if (!NIL_P(fptr->write_lock)) {
+ return rb_mutex_synchronize(fptr->write_lock, io_binwritev_internal, (VALUE)&arg);
}
- if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
- rb_io_check_closed(fptr);
- goto retry;
+ else {
+ return io_binwritev_internal((VALUE)&arg);
}
-
- return -1L;
}
static long
@@ -1920,24 +2149,26 @@ io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr)
tmp_array = ALLOCV_N(VALUE, v2, argc);
for (i = 0; i < argc; i++) {
- str = rb_obj_as_string(argv[i]);
- converted = 0;
- str = do_writeconv(str, fptr, &converted);
- if (converted)
- OBJ_FREEZE(str);
+ str = rb_obj_as_string(argv[i]);
+ converted = 0;
+ str = do_writeconv(str, fptr, &converted);
+
+ if (converted)
+ OBJ_FREEZE(str);
+
+ tmp = rb_str_tmp_frozen_acquire(str);
+ tmp_array[i] = tmp;
- tmp = rb_str_tmp_frozen_acquire(str);
- tmp_array[i] = tmp;
- /* iov[0] is reserved for buffer of fptr */
- iov[i+1].iov_base = RSTRING_PTR(tmp);
- iov[i+1].iov_len = RSTRING_LEN(tmp);
+ /* iov[0] is reserved for buffer of fptr */
+ iov[i+1].iov_base = RSTRING_PTR(tmp);
+ iov[i+1].iov_len = RSTRING_LEN(tmp);
}
n = io_binwritev(iov, iovcnt, fptr);
if (v1) ALLOCV_END(v1);
for (i = 0; i < argc; i++) {
- rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
+ rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
}
if (v2) ALLOCV_END(v2);
@@ -1966,10 +2197,12 @@ io_writev(int argc, const VALUE *argv, VALUE io)
io = GetWriteIO(io);
tmp = rb_io_check_io(io);
+
if (NIL_P(tmp)) {
- /* port is not IO, call write method for it. */
- return rb_funcallv(io, id_write, argc, argv);
+ /* port is not IO, call write method for it. */
+ return rb_funcallv(io, id_write, argc, argv);
}
+
io = tmp;
GetOpenFile(io, fptr);
@@ -1977,18 +2210,21 @@ io_writev(int argc, const VALUE *argv, VALUE io)
for (i = 0; i < argc; i += cnt) {
#ifdef HAVE_WRITEV
- if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
- n = io_fwritev(cnt, &argv[i], fptr);
- }
- else
+ if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
+ n = io_fwritev(cnt, &argv[i], fptr);
+ }
+ else
#endif
- {
- cnt = 1;
- /* sync at last item */
- n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
- }
- if (n < 0L) rb_sys_fail_on_write(fptr);
- total = rb_fix_plus(LONG2FIX(n), total);
+ {
+ cnt = 1;
+ /* sync at last item */
+ n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
+ }
+
+ if (n < 0L)
+ rb_sys_fail_on_write(fptr);
+
+ total = rb_fix_plus(LONG2FIX(n), total);
}
return total;
@@ -1996,31 +2232,34 @@ io_writev(int argc, const VALUE *argv, VALUE io)
/*
* call-seq:
- * ios.write(string, ...) -> integer
+ * write(*objects) -> integer
*
- * Writes the given strings to <em>ios</em>. The stream must be opened
- * for writing. Arguments that are not a string will be converted
- * to a string using <code>to_s</code>. Returns the number of bytes
- * written in total.
+ * Writes each of the given +objects+ to +self+,
+ * which must be opened for writing
+ * (see {Access Modes}[rdoc-ref:File@Access+Modes]);
+ * returns the total number bytes written;
+ * each of +objects+ that is not a string is converted via method +to_s+:
*
- * count = $stdout.write("This is", " a test\n")
- * puts "That was #{count} bytes of data"
+ * $stdout.write('Hello', ', ', 'World!', "\n") # => 14
+ * $stdout.write('foo', :bar, 2, "\n") # => 8
*
- * <em>produces:</em>
+ * Output:
+ *
+ * Hello, World!
+ * foobar2
*
- * This is a test
- * That was 15 bytes of data
+ * Related: IO#read.
*/
static VALUE
io_write_m(int argc, VALUE *argv, VALUE io)
{
if (argc != 1) {
- return io_writev(argc, argv, io);
+ return io_writev(argc, argv, io);
}
else {
- VALUE str = argv[0];
- return io_write(io, str, 0);
+ VALUE str = argv[0];
+ return io_write(io, str, 0);
}
}
@@ -2034,32 +2273,41 @@ static VALUE
rb_io_writev(VALUE io, int argc, const VALUE *argv)
{
if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
- if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
- VALUE klass = CLASS_OF(io);
- char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
- rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
- " which accepts just one argument",
- klass, sep);
- }
- do rb_io_write(io, *argv++); while (--argc);
- return argv[0]; /* unused right now */
+ if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
+ VALUE klass = CLASS_OF(io);
+ char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
+ rb_category_warning(
+ RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
+ " which accepts just one argument",
+ klass, sep
+ );
+ }
+
+ do rb_io_write(io, *argv++); while (--argc);
+
+ return Qnil;
}
+
return rb_funcallv(io, id_write, argc, argv);
}
/*
* call-seq:
- * ios << obj -> ios
+ * self << object -> self
*
- * String Output---Writes <i>obj</i> to <em>ios</em>.
- * <i>obj</i> will be converted to a string using
- * <code>to_s</code>.
+ * Writes the given +object+ to +self+,
+ * which must be opened for writing (see {Access Modes}[rdoc-ref:File@Access+Modes]);
+ * returns +self+;
+ * if +object+ is not a string, it is converted via method +to_s+:
*
- * $stdout << "Hello " << "world!\n"
+ * $stdout << 'Hello' << ', ' << 'World!' << "\n"
+ * $stdout << 'foo' << :bar << 2 << "\n"
*
- * <em>produces:</em>
+ * Output:
+ *
+ * Hello, World!
+ * foobar2
*
- * Hello world!
*/
@@ -2078,7 +2326,7 @@ nogvl_fsync(void *ptr)
#ifdef _WIN32
if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
- return 0;
+ return 0;
#endif
return (VALUE)fsync(fptr->fd);
}
@@ -2109,18 +2357,14 @@ rb_io_flush_raw(VALUE io, int sync)
/*
* call-seq:
- * ios.flush -> ios
- *
- * Flushes any buffered data within <em>ios</em> to the underlying
- * operating system (note that this is Ruby internal buffering only;
- * the OS may buffer the data as well).
+ * flush -> self
*
- * $stdout.print "no newline"
- * $stdout.flush
+ * Flushes data buffered in +self+ to the operating system
+ * (but does not necessarily flush data buffered in the operating system):
*
- * <em>produces:</em>
+ * $stdout.print 'no newline' # Not necessarily flushed.
+ * $stdout.flush # Flushed.
*
- * no newline
*/
VALUE
@@ -2131,22 +2375,28 @@ rb_io_flush(VALUE io)
/*
* call-seq:
- * ios.pos -> integer
- * ios.tell -> integer
+ * tell -> integer
*
- * Returns the current offset (in bytes) of <em>ios</em>.
+ * Returns the current position (in bytes) in +self+
+ * (see {Position}[rdoc-ref:IO@Position]):
+ *
+ * f = File.open('t.txt')
+ * f.tell # => 0
+ * f.gets # => "First line\n"
+ * f.tell # => 12
+ * f.close
+ *
+ * Related: IO#pos=, IO#seek.
+ *
+ * IO#pos is an alias for IO#tell.
*
- * f = File.new("testfile")
- * f.pos #=> 0
- * f.gets #=> "This is line one\n"
- * f.pos #=> 17
*/
static VALUE
rb_io_tell(VALUE io)
{
rb_io_t *fptr;
- off_t pos;
+ rb_off_t pos;
GetOpenFile(io, fptr);
pos = io_tell(fptr);
@@ -2159,7 +2409,7 @@ static VALUE
rb_io_seek(VALUE io, VALUE offset, int whence)
{
rb_io_t *fptr;
- off_t pos;
+ rb_off_t pos;
pos = NUM2OFFT(offset);
GetOpenFile(io, fptr);
@@ -2191,23 +2441,49 @@ interpret_seek_whence(VALUE vwhence)
/*
* call-seq:
- * ios.seek(amount, whence=IO::SEEK_SET) -> 0
+ * seek(offset, whence = IO::SEEK_SET) -> 0
*
- * Seeks to a given offset <i>anInteger</i> in the stream according to
- * the value of <i>whence</i>:
+ * Seeks to the position given by integer +offset+
+ * (see {Position}[rdoc-ref:IO@Position])
+ * and constant +whence+, which is one of:
*
- * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
- * ----------------------+--------------------------------------------------
- * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
- * | probably want a negative value for _amount_)
- * ----------------------+--------------------------------------------------
- * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
+ * - +:CUR+ or <tt>IO::SEEK_CUR</tt>:
+ * Repositions the stream to its current position plus the given +offset+:
*
- * Example:
+ * f = File.open('t.txt')
+ * f.tell # => 0
+ * f.seek(20, :CUR) # => 0
+ * f.tell # => 20
+ * f.seek(-10, :CUR) # => 0
+ * f.tell # => 10
+ * f.close
+ *
+ * - +:END+ or <tt>IO::SEEK_END</tt>:
+ * Repositions the stream to its end plus the given +offset+:
+ *
+ * f = File.open('t.txt')
+ * f.tell # => 0
+ * f.seek(0, :END) # => 0 # Repositions to stream end.
+ * f.tell # => 52
+ * f.seek(-20, :END) # => 0
+ * f.tell # => 32
+ * f.seek(-40, :END) # => 0
+ * f.tell # => 12
+ * f.close
+ *
+ * - +:SET+ or <tt>IO:SEEK_SET</tt>:
+ * Repositions the stream to the given +offset+:
+ *
+ * f = File.open('t.txt')
+ * f.tell # => 0
+ * f.seek(20, :SET) # => 0
+ * f.tell # => 20
+ * f.seek(40, :SET) # => 0
+ * f.tell # => 40
+ * f.close
+ *
+ * Related: IO#pos=, IO#tell.
*
- * f = File.new("testfile")
- * f.seek(-13, IO::SEEK_END) #=> 0
- * f.readline #=> "And so on...\n"
*/
static VALUE
@@ -2217,7 +2493,7 @@ rb_io_seek_m(int argc, VALUE *argv, VALUE io)
int whence = SEEK_SET;
if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
- whence = interpret_seek_whence(ptrname);
+ whence = interpret_seek_whence(ptrname);
}
return rb_io_seek(io, offset, whence);
@@ -2225,22 +2501,26 @@ rb_io_seek_m(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * ios.pos = integer -> integer
+ * pos = new_position -> new_position
+ *
+ * Seeks to the given +new_position+ (in bytes);
+ * see {Position}[rdoc-ref:IO@Position]:
*
- * Seeks to the given position (in bytes) in <em>ios</em>.
- * It is not guaranteed that seeking to the right position when <em>ios</em>
- * is textmode.
+ * f = File.open('t.txt')
+ * f.tell # => 0
+ * f.pos = 20 # => 20
+ * f.tell # => 20
+ * f.close
+ *
+ * Related: IO#seek, IO#tell.
*
- * f = File.new("testfile")
- * f.pos = 17
- * f.gets #=> "This is line two\n"
*/
static VALUE
rb_io_set_pos(VALUE io, VALUE offset)
{
rb_io_t *fptr;
- off_t pos;
+ rb_off_t pos;
pos = NUM2OFFT(offset);
GetOpenFile(io, fptr);
@@ -2254,18 +2534,26 @@ static void clear_readconv(rb_io_t *fptr);
/*
* call-seq:
- * ios.rewind -> 0
+ * rewind -> 0
+ *
+ * Repositions the stream to its beginning,
+ * setting both the position and the line number to zero;
+ * see {Position}[rdoc-ref:IO@Position]
+ * and {Line Number}[rdoc-ref:IO@Line+Number]:
*
- * Positions <em>ios</em> to the beginning of input, resetting
- * #lineno to zero.
+ * f = File.open('t.txt')
+ * f.tell # => 0
+ * f.lineno # => 0
+ * f.gets # => "First line\n"
+ * f.tell # => 12
+ * f.lineno # => 1
+ * f.rewind # => 0
+ * f.tell # => 0
+ * f.lineno # => 0
+ * f.close
*
- * f = File.new("testfile")
- * f.readline #=> "This is line one\n"
- * f.rewind #=> 0
- * f.lineno #=> 0
- * f.readline #=> "This is line one\n"
+ * Note that this method cannot be used with streams such as pipes, ttys, and sockets.
*
- * Note that it cannot be used with streams such as pipes, ttys, and sockets.
*/
static VALUE
@@ -2276,11 +2564,11 @@ rb_io_rewind(VALUE io)
GetOpenFile(io, fptr);
if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
if (io == ARGF.current_file) {
- ARGF.lineno -= fptr->lineno;
+ ARGF.lineno -= fptr->lineno;
}
fptr->lineno = 0;
if (fptr->readconv) {
- clear_readconv(fptr);
+ clear_readconv(fptr);
}
return INT2FIX(0);
@@ -2289,11 +2577,12 @@ rb_io_rewind(VALUE io)
static int
fptr_wait_readable(rb_io_t *fptr)
{
- int ret = rb_io_maybe_wait_readable(errno, fptr->self, Qnil);
+ int result = rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT);
- if (ret)
+ if (result)
rb_io_check_closed(fptr);
- return ret;
+
+ return result;
}
static int
@@ -2307,27 +2596,26 @@ io_fillbuf(rb_io_t *fptr)
fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
#ifdef _WIN32
- fptr->rbuf.capa--;
+ fptr->rbuf.capa--;
#endif
}
if (fptr->rbuf.len == 0) {
retry:
- {
- r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
- }
+ r = rb_io_read_memory(fptr, fptr->rbuf.ptr, fptr->rbuf.capa);
+
if (r < 0) {
if (fptr_wait_readable(fptr))
goto retry;
- {
- int e = errno;
- VALUE path = rb_sprintf("fd:%d ", fptr->fd);
- if (!NIL_P(fptr->pathv)) {
- rb_str_append(path, fptr->pathv);
- }
- rb_syserr_fail_path(e, path);
- }
- }
- if (r > 0) rb_io_check_closed(fptr);
+
+ int e = errno;
+ VALUE path = rb_sprintf("fd:%d ", fptr->fd);
+ if (!NIL_P(fptr->pathv)) {
+ rb_str_append(path, fptr->pathv);
+ }
+
+ rb_syserr_fail_path(e, path);
+ }
+ if (r > 0) rb_io_check_closed(fptr);
fptr->rbuf.off = 0;
fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
if (r == 0)
@@ -2338,35 +2626,40 @@ io_fillbuf(rb_io_t *fptr)
/*
* call-seq:
- * ios.eof -> true or false
- * ios.eof? -> true or false
+ * eof -> true or false
*
- * Returns true if <em>ios</em> is at end of file that means
- * there are no more data to read.
- * The stream must be opened for reading or an IOError will be
- * raised.
+ * Returns +true+ if the stream is positioned at its end, +false+ otherwise;
+ * see {Position}[rdoc-ref:IO@Position]:
*
- * f = File.new("testfile")
- * dummy = f.readlines
- * f.eof #=> true
+ * f = File.open('t.txt')
+ * f.eof # => false
+ * f.seek(0, :END) # => 0
+ * f.eof # => true
+ * f.close
*
- * If <em>ios</em> is a stream such as pipe or socket, IO#eof?
- * blocks until the other end sends some data or closes it.
+ * Raises an exception unless the stream is opened for reading;
+ * see {Mode}[rdoc-ref:File@Access+Modes].
*
- * r, w = IO.pipe
- * Thread.new { sleep 1; w.close }
- * r.eof? #=> true after 1 second blocking
+ * If +self+ is a stream such as pipe or socket, this method
+ * blocks until the other end sends some data or closes it:
*
- * r, w = IO.pipe
- * Thread.new { sleep 1; w.puts "a" }
- * r.eof? #=> false after 1 second blocking
+ * r, w = IO.pipe
+ * Thread.new { sleep 1; w.close }
+ * r.eof? # => true # After 1-second wait.
*
- * r, w = IO.pipe
- * r.eof? # blocks forever
+ * r, w = IO.pipe
+ * Thread.new { sleep 1; w.puts "a" }
+ * r.eof? # => false # After 1-second wait.
*
- * Note that IO#eof? reads data to the input byte buffer. So
+ * r, w = IO.pipe
+ * r.eof? # blocks forever
+ *
+ * Note that this method reads data to the input byte buffer. So
* IO#sysread may not behave as you intend with IO#eof?, unless you
* call IO#rewind first (which is not available for some streams).
+ *
+ * IO#eof? is an alias for IO#eof.
+ *
*/
VALUE
@@ -2382,7 +2675,7 @@ rb_io_eof(VALUE io)
READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
- return RBOOL(eof(fptr->fd));;
+ return RBOOL(eof(fptr->fd));;
}
#endif
return RBOOL(io_fillbuf(fptr) < 0);
@@ -2390,15 +2683,18 @@ rb_io_eof(VALUE io)
/*
* call-seq:
- * ios.sync -> true or false
+ * sync -> true or false
+ *
+ * Returns the current sync mode of the stream.
+ * When sync mode is true, all output is immediately flushed to the underlying
+ * operating system and is not buffered by Ruby internally. See also #fsync.
*
- * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
- * true, all output is immediately flushed to the underlying operating
- * system and is not buffered by Ruby internally. See also
- * IO#fsync.
+ * f = File.open('t.tmp', 'w')
+ * f.sync # => false
+ * f.sync = true
+ * f.sync # => true
+ * f.close
*
- * f = File.new("testfile")
- * f.sync #=> false
*/
static VALUE
@@ -2415,15 +2711,27 @@ rb_io_sync(VALUE io)
/*
* call-seq:
- * ios.sync = boolean -> boolean
+ * sync = boolean -> boolean
+ *
+ * Sets the _sync_ _mode_ for the stream to the given value;
+ * returns the given value.
*
- * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
- * When sync mode is true, all output is immediately flushed to the
- * underlying operating system and is not buffered internally. Returns
- * the new state. See also IO#fsync.
+ * Values for the sync mode:
+ *
+ * - +true+: All output is immediately flushed to the
+ * underlying operating system and is not buffered internally.
+ * - +false+: Output may be buffered internally.
+ *
+ * Example;
+ *
+ * f = File.open('t.tmp', 'w')
+ * f.sync # => false
+ * f.sync = true
+ * f.sync # => true
+ * f.close
+ *
+ * Related: IO#fsync.
*
- * f = File.new("testfile")
- * f.sync = true
*/
static VALUE
@@ -2434,25 +2742,30 @@ rb_io_set_sync(VALUE io, VALUE sync)
io = GetWriteIO(io);
GetOpenFile(io, fptr);
if (RTEST(sync)) {
- fptr->mode |= FMODE_SYNC;
+ fptr->mode |= FMODE_SYNC;
}
else {
- fptr->mode &= ~FMODE_SYNC;
+ fptr->mode &= ~FMODE_SYNC;
}
return sync;
}
/*
* call-seq:
- * ios.fsync -> 0 or nil
+ * fsync -> 0
+ *
+ * Immediately writes to disk all data buffered in the stream,
+ * via the operating system's <tt>fsync(2)</tt>.
+
+ * Note this difference:
*
- * Immediately writes all buffered data in <em>ios</em> to disk.
- * Note that #fsync differs from using IO#sync=. The latter ensures
- * that data is flushed from Ruby's buffers, but does not guarantee
- * that the underlying operating system actually writes it to disk.
+ * - IO#sync=: Ensures that data is flushed from the stream's internal buffers,
+ * but does not guarantee that the operating system actually writes the data to disk.
+ * - IO#fsync: Ensures both that data is flushed from internal buffers,
+ * and that data is written to disk.
+ *
+ * Raises an exception if the operating system does not support <tt>fsync(2)</tt>.
*
- * NotImplementedError is raised
- * if the underlying operating system does not support <em>fsync(2)</em>.
*/
static VALUE
@@ -2466,7 +2779,7 @@ rb_io_fsync(VALUE io)
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
return INT2FIX(0);
}
#else
@@ -2488,20 +2801,20 @@ nogvl_fdatasync(void *ptr)
#ifdef _WIN32
if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
- return 0;
+ return 0;
#endif
return (VALUE)fdatasync(fptr->fd);
}
/*
* call-seq:
- * ios.fdatasync -> 0 or nil
+ * fdatasync -> 0
*
- * Immediately writes all buffered data in <em>ios</em> to disk.
+ * Immediately writes to disk all data buffered in the stream,
+ * via the operating system's: <tt>fdatasync(2)</tt>, if supported,
+ * otherwise via <tt>fsync(2)</tt>, if supported;
+ * otherwise raises an exception.
*
- * If the underlying operating system does not support <em>fdatasync(2)</em>,
- * IO#fsync is called instead (which might raise a
- * NotImplementedError).
*/
static VALUE
@@ -2516,7 +2829,7 @@ rb_io_fdatasync(VALUE io)
rb_sys_fail_on_write(fptr);
if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
- return INT2FIX(0);
+ return INT2FIX(0);
/* fall back */
return rb_io_fsync(io);
@@ -2527,14 +2840,18 @@ rb_io_fdatasync(VALUE io)
/*
* call-seq:
- * ios.fileno -> integer
- * ios.to_i -> integer
+ * fileno -> integer
*
- * Returns an integer representing the numeric file descriptor for
- * <em>ios</em>.
+ * Returns the integer file descriptor for the stream:
+ *
+ * $stdin.fileno # => 0
+ * $stdout.fileno # => 1
+ * $stderr.fileno # => 2
+ * File.open('t.txt').fileno # => 10
+ * f.close
+ *
+ * IO#to_i is an alias for IO#fileno.
*
- * $stdin.fileno #=> 0
- * $stdout.fileno #=> 1
*/
static VALUE
@@ -2548,25 +2865,39 @@ rb_io_fileno(VALUE io)
return INT2FIX(fd);
}
+int
+rb_io_descriptor(VALUE io)
+{
+ if (RB_TYPE_P(io, T_FILE)) {
+ rb_io_t *fptr = RFILE(io)->fptr;
+ rb_io_check_closed(fptr);
+ return fptr->fd;
+ }
+ else {
+ return RB_NUM2INT(rb_funcall(io, id_fileno, 0));
+ }
+}
/*
* call-seq:
- * ios.pid -> integer
+ * pid -> integer or nil
*
- * Returns the process ID of a child process associated with
- * <em>ios</em>. This will be set by IO.popen.
+ * Returns the process ID of a child process associated with the stream,
+ * which will have been set by IO#popen, or +nil+ if the stream was not
+ * created by IO#popen:
*
- * pipe = IO.popen("-")
- * if pipe
- * $stderr.puts "In parent, child pid is #{pipe.pid}"
- * else
- * $stderr.puts "In child, pid is #{$$}"
- * end
+ * pipe = IO.popen("-")
+ * if pipe
+ * $stderr.puts "In parent, child pid is #{pipe.pid}"
+ * else
+ * $stderr.puts "In child, pid is #{$$}"
+ * end
*
- * <em>produces:</em>
+ * Output:
+ *
+ * In child, pid is 26209
+ * In parent, child pid is 26209
*
- * In child, pid is 26209
- * In parent, child pid is 26209
*/
static VALUE
@@ -2576,16 +2907,44 @@ rb_io_pid(VALUE io)
GetOpenFile(io, fptr);
if (!fptr->pid)
- return Qnil;
+ return Qnil;
return PIDT2NUM(fptr->pid);
}
+/*
+ * call-seq:
+ * path -> string or nil
+ *
+ * Returns the path associated with the IO, or +nil+ if there is no path
+ * associated with the IO. It is not guaranteed that the path exists on
+ * the filesystem.
+ *
+ * $stdin.path # => "<STDIN>"
+ *
+ * File.open("testfile") {|f| f.path} # => "testfile"
+ */
+
+static VALUE
+rb_io_path(VALUE io)
+{
+ rb_io_t *fptr = RFILE(io)->fptr;
+
+ if (!fptr)
+ return Qnil;
+
+ return rb_obj_dup(fptr->pathv);
+}
/*
- * call-seq:
- * ios.inspect -> string
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a string representation of +self+:
+ *
+ * f = File.open('t.txt')
+ * f.inspect # => "#<File:t.txt>"
+ * f.close
*
- * Return a string describing this IO object.
*/
static VALUE
@@ -2602,16 +2961,16 @@ rb_io_inspect(VALUE obj)
rb_str_cat2(result, ":");
if (NIL_P(fptr->pathv)) {
if (fptr->fd < 0) {
- rb_str_cat(result, closed+1, strlen(closed)-1);
+ rb_str_cat(result, closed+1, strlen(closed)-1);
}
else {
- rb_str_catf(result, "fd %d", fptr->fd);
+ rb_str_catf(result, "fd %d", fptr->fd);
}
}
else {
- rb_str_append(result, fptr->pathv);
+ rb_str_append(result, fptr->pathv);
if (fptr->fd < 0) {
- rb_str_cat(result, closed, strlen(closed));
+ rb_str_cat(result, closed, strlen(closed));
}
}
return rb_str_cat2(result, ">");
@@ -2619,9 +2978,10 @@ rb_io_inspect(VALUE obj)
/*
* call-seq:
- * ios.to_io -> ios
+ * to_io -> self
+ *
+ * Returns +self+.
*
- * Returns <em>ios</em>.
*/
static VALUE
@@ -2656,7 +3016,7 @@ io_bufread(char *ptr, long len, rb_io_t *fptr)
while (n > 0) {
again:
rb_io_check_closed(fptr);
- c = rb_read_internal(fptr->fd, ptr+offset, n);
+ c = rb_io_read_memory(fptr, ptr+offset, n);
if (c == 0) break;
if (c < 0) {
if (fptr_wait_readable(fptr))
@@ -2702,19 +3062,6 @@ bufread_call(VALUE arg)
static long
io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
{
- VALUE scheduler = rb_fiber_scheduler_current();
- if (scheduler != Qnil) {
- VALUE result = rb_fiber_scheduler_io_read(scheduler, fptr->self, str, offset, size);
-
- if (result != Qundef) {
- ssize_t length = RB_NUM2SSIZE(result);
-
- if (length < 0) rb_sys_fail_path(fptr->pathv);
-
- return length;
- }
- }
-
long len;
struct bufread_arg arg;
@@ -2732,27 +3079,27 @@ static long
remain_size(rb_io_t *fptr)
{
struct stat st;
- off_t siz = READ_DATA_PENDING_COUNT(fptr);
- off_t pos;
+ rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
+ rb_off_t pos;
if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
#if defined(__HAIKU__)
- && (st.st_dev > 3)
+ && (st.st_dev > 3)
#endif
- )
+ )
{
if (io_fflush(fptr) < 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;
- if (siz > LONG_MAX) {
- rb_raise(rb_eIOError, "file too big for single read");
- }
- }
+ pos = lseek(fptr->fd, 0, SEEK_CUR);
+ if (st.st_size >= pos && pos >= 0) {
+ siz += st.st_size - pos;
+ if (siz > LONG_MAX) {
+ rb_raise(rb_eIOError, "file too big for single read");
+ }
+ }
}
else {
- siz += BUFSIZ;
+ siz += BUFSIZ;
}
return (long)siz;
}
@@ -2764,6 +3111,8 @@ io_enc_str(VALUE str, rb_io_t *fptr)
return str;
}
+static rb_encoding *io_read_encoding(rb_io_t *fptr);
+
static void
make_readconv(rb_io_t *fptr, int size)
{
@@ -2775,7 +3124,7 @@ make_readconv(rb_io_t *fptr, int size)
ecopts = fptr->encs.ecopts;
if (fptr->encs.enc2) {
sname = rb_enc_name(fptr->encs.enc2);
- dname = rb_enc_name(fptr->encs.enc);
+ dname = rb_enc_name(io_read_encoding(fptr));
}
else {
sname = dname = "";
@@ -2785,7 +3134,7 @@ make_readconv(rb_io_t *fptr, int size)
rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
fptr->cbuf.off = 0;
fptr->cbuf.len = 0;
- if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
+ if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
fptr->cbuf.capa = size;
fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
}
@@ -2842,27 +3191,27 @@ fill_cbuf(rb_io_t *fptr, int ec_flags)
if (res == econv_finished) {
return MORE_CHAR_FINISHED;
- }
+ }
if (res == econv_source_buffer_empty) {
if (fptr->rbuf.len == 0) {
- READ_CHECK(fptr);
+ READ_CHECK(fptr);
if (io_fillbuf(fptr) < 0) {
- if (!fptr->readconv) {
- return MORE_CHAR_FINISHED;
- }
+ if (!fptr->readconv) {
+ return MORE_CHAR_FINISHED;
+ }
ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
fptr->cbuf.len += (int)(dp - ds);
rb_econv_check_error(fptr->readconv);
- break;
+ break;
}
}
}
}
if (cbuf_len0 != fptr->cbuf.len)
- return MORE_CHAR_SUSPENDED;
+ return MORE_CHAR_SUSPENDED;
return MORE_CHAR_FINISHED;
}
@@ -2882,14 +3231,14 @@ io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
{
VALUE str = Qnil;
if (strp) {
- str = *strp;
- if (NIL_P(str)) {
- *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
- }
- else {
- rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
- }
- rb_enc_associate(str, fptr->encs.enc);
+ str = *strp;
+ if (NIL_P(str)) {
+ *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
+ }
+ else {
+ rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
+ }
+ rb_enc_associate(str, fptr->encs.enc);
}
fptr->cbuf.off += len;
fptr->cbuf.len -= len;
@@ -2907,22 +3256,25 @@ static int
io_setstrbuf(VALUE *str, long len)
{
#ifdef _WIN32
- len = (len + 1) & ~1L; /* round up for wide char */
+ if (len > 0)
+ len = (len + 1) & ~1L; /* round up for wide char */
#endif
if (NIL_P(*str)) {
- *str = rb_str_new(0, len);
- return TRUE;
+ *str = rb_str_new(0, len);
+ return TRUE;
}
else {
- VALUE s = StringValue(*str);
- long clen = RSTRING_LEN(s);
- if (clen >= len) {
- rb_str_modify(s);
- return FALSE;
- }
- len -= clen;
- }
- rb_str_modify_expand(*str, len);
+ VALUE s = StringValue(*str);
+ long clen = RSTRING_LEN(s);
+ if (clen >= len) {
+ rb_str_modify(s);
+ return FALSE;
+ }
+ len -= clen;
+ }
+ if ((rb_str_capacity(*str) - (size_t)RSTRING_LEN(*str)) < (size_t)len) {
+ rb_str_modify_expand(*str, len);
+ }
return FALSE;
}
@@ -2931,7 +3283,7 @@ static void
io_shrink_read_string(VALUE str, long n)
{
if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
- rb_str_resize(str, n);
+ rb_str_resize(str, n);
}
}
@@ -2939,9 +3291,9 @@ static void
io_set_read_length(VALUE str, long n, int shrinkable)
{
if (RSTRING_LEN(str) != n) {
- rb_str_modify(str);
- rb_str_set_len(str, n);
- if (shrinkable) io_shrink_read_string(str, n);
+ rb_str_modify(str);
+ rb_str_set_len(str, n);
+ if (shrinkable) io_shrink_read_string(str, n);
}
}
@@ -2956,28 +3308,28 @@ read_all(rb_io_t *fptr, long siz, VALUE str)
int shrinkable;
if (NEED_READCONV(fptr)) {
- int first = !NIL_P(str);
- SET_BINARY_MODE(fptr);
- shrinkable = io_setstrbuf(&str,0);
+ int first = !NIL_P(str);
+ SET_BINARY_MODE(fptr);
+ shrinkable = io_setstrbuf(&str,0);
make_readconv(fptr, 0);
while (1) {
VALUE v;
if (fptr->cbuf.len) {
- if (first) rb_str_set_len(str, first = 0);
+ if (first) rb_str_set_len(str, first = 0);
io_shift_cbuf(fptr, fptr->cbuf.len, &str);
}
v = fill_cbuf(fptr, 0);
if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
if (fptr->cbuf.len) {
- if (first) rb_str_set_len(str, first = 0);
+ if (first) rb_str_set_len(str, first = 0);
io_shift_cbuf(fptr, fptr->cbuf.len, &str);
}
rb_exc_raise(v);
}
if (v == MORE_CHAR_FINISHED) {
clear_readconv(fptr);
- if (first) rb_str_set_len(str, first = 0);
- if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
+ if (first) rb_str_set_len(str, first = 0);
+ if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
return io_enc_str(str, fptr);
}
}
@@ -2993,19 +3345,29 @@ read_all(rb_io_t *fptr, long siz, VALUE str)
if (siz == 0) siz = BUFSIZ;
shrinkable = io_setstrbuf(&str, siz);
for (;;) {
- READ_CHECK(fptr);
- n = io_fread(str, bytes, siz - bytes, fptr);
- if (n == 0 && bytes == 0) {
- rb_str_set_len(str, 0);
- break;
- }
- bytes += n;
- rb_str_set_len(str, bytes);
- if (cr != ENC_CODERANGE_BROKEN)
- pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
- if (bytes < siz) break;
- siz += BUFSIZ;
- rb_str_modify_expand(str, BUFSIZ);
+ READ_CHECK(fptr);
+ n = io_fread(str, bytes, siz - bytes, fptr);
+ if (n == 0 && bytes == 0) {
+ rb_str_set_len(str, 0);
+ break;
+ }
+ bytes += n;
+ rb_str_set_len(str, bytes);
+ if (cr != ENC_CODERANGE_BROKEN)
+ pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
+ if (bytes < siz) break;
+ siz += BUFSIZ;
+
+ size_t capa = rb_str_capacity(str);
+ if (capa < (size_t)RSTRING_LEN(str) + BUFSIZ) {
+ if (capa < BUFSIZ) {
+ capa = BUFSIZ;
+ }
+ else if (capa > IO_MAX_BUFFER_GROWTH) {
+ capa = IO_MAX_BUFFER_GROWTH;
+ }
+ rb_str_modify_expand(str, capa);
+ }
}
if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
str = io_enc_str(str, fptr);
@@ -3017,22 +3379,32 @@ void
rb_io_set_nonblock(rb_io_t *fptr)
{
if (rb_fd_set_nonblock(fptr->fd) != 0) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
}
static VALUE
-read_internal_call(VALUE arg)
+io_read_memory_call(VALUE arg)
{
struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
- return rb_thread_io_blocking_region(internal_read_func, iis, iis->fd);
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, iis->fptr->self, iis->buf, iis->capa, 0);
+
+ if (!UNDEF_P(result)) {
+ // This is actually returned as a pseudo-VALUE and later cast to a long:
+ return (VALUE)rb_fiber_scheduler_io_result_apply(result);
+ }
+ }
+
+ return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->fd);
}
static long
-read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
+io_read_memory_locktmp(VALUE str, struct io_internal_read_struct *iis)
{
- return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
+ return (long)rb_str_locktmp_ensure(str, io_read_memory_call, (VALUE)iis);
}
#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
@@ -3049,7 +3421,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
rb_scan_args(argc, argv, "11", &length, &str);
if ((len = NUM2LONG(length)) < 0) {
- rb_raise(rb_eArgError, "negative length %ld given", len);
+ rb_raise(rb_eArgError, "negative length %ld given", len);
}
shrinkable = io_setstrbuf(&str, len);
@@ -3057,8 +3429,10 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
- if (len == 0)
- return str;
+ if (len == 0) {
+ io_set_read_length(str, 0, shrinkable);
+ return str;
+ }
if (!nonblock)
READ_CHECK(fptr);
@@ -3068,23 +3442,25 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
if (nonblock) {
rb_io_set_nonblock(fptr);
}
- io_setstrbuf(&str, len);
+ io_setstrbuf(&str, len);
iis.th = rb_thread_current();
- iis.fd = fptr->fd;
+ iis.fptr = fptr;
iis.nonblock = nonblock;
+ iis.fd = fptr->fd;
iis.buf = RSTRING_PTR(str);
iis.capa = len;
- n = read_internal_locktmp(str, &iis);
+ iis.timeout = NULL;
+ n = io_read_memory_locktmp(str, &iis);
if (n < 0) {
- int e = errno;
+ int e = errno;
if (!nonblock && fptr_wait_readable(fptr))
goto again;
- if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
+ if (nonblock && (io_again_p(e))) {
if (no_exception)
return sym_wait_readable;
else
- rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
- e, "read would block");
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
+ e, "read would block");
}
rb_syserr_fail_path(e, fptr->pathv);
}
@@ -3099,67 +3475,94 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
/*
* call-seq:
- * ios.readpartial(maxlen) -> string
- * ios.readpartial(maxlen, outbuf) -> outbuf
+ * readpartial(maxlen) -> string
+ * readpartial(maxlen, out_string) -> out_string
*
- * Reads at most <i>maxlen</i> bytes from the I/O stream.
- * It blocks only if <em>ios</em> has no data immediately available.
- * It doesn't block if some data available.
+ * Reads up to +maxlen+ bytes from the stream;
+ * returns a string (either a new string or the given +out_string+).
+ * Its encoding is:
*
- * If the optional _outbuf_ argument is present,
- * it must reference a String, which will receive the data.
- * The _outbuf_ will contain only the received data after the method call
- * even if it is not empty at the beginning.
+ * - The unchanged encoding of +out_string+, if +out_string+ is given.
+ * - ASCII-8BIT, otherwise.
*
- * It raises EOFError on end of file.
- *
- * readpartial is designed for streams such as pipe, socket, tty, etc.
- * It blocks only when no data immediately available.
- * This means that it blocks only when following all conditions hold.
- * * the byte buffer in the IO object is empty.
- * * the content of the stream is empty.
- * * the stream is not reached to EOF.
- *
- * When readpartial blocks, it waits data or EOF on the stream.
- * If some data is reached, readpartial returns with the data.
- * If EOF is reached, readpartial raises EOFError.
- *
- * When readpartial doesn't blocks, it returns or raises immediately.
- * If the byte buffer is not empty, it returns the data in the buffer.
- * Otherwise if the stream has some content,
- * it returns the data in the stream.
- * Otherwise if the stream is reached to EOF, it raises EOFError.
- *
- * r, w = IO.pipe # buffer pipe content
- * w << "abc" # "" "abc".
- * r.readpartial(4096) #=> "abc" "" ""
- * r.readpartial(4096) # blocks because buffer and pipe is empty.
- *
- * r, w = IO.pipe # buffer pipe content
- * w << "abc" # "" "abc"
- * w.close # "" "abc" EOF
- * r.readpartial(4096) #=> "abc" "" EOF
- * r.readpartial(4096) # raises EOFError
+ * - Contains +maxlen+ bytes from the stream, if available.
+ * - Otherwise contains all available bytes, if any available.
+ * - Otherwise is an empty string.
+ *
+ * With the single non-negative integer argument +maxlen+ given,
+ * returns a new string:
+ *
+ * f = File.new('t.txt')
+ * f.readpartial(20) # => "First line\nSecond l"
+ * f.readpartial(20) # => "ine\n\nFourth line\n"
+ * f.readpartial(20) # => "Fifth line\n"
+ * f.readpartial(20) # Raises EOFError.
+ * f.close
+ *
+ * With both argument +maxlen+ and string argument +out_string+ given,
+ * returns modified +out_string+:
+ *
+ * f = File.new('t.txt')
+ * s = 'foo'
+ * f.readpartial(20, s) # => "First line\nSecond l"
+ * s = 'bar'
+ * f.readpartial(0, s) # => ""
+ * f.close
+ *
+ * This method is useful for a stream such as a pipe, a socket, or a tty.
+ * It blocks only when no data is immediately available.
+ * This means that it blocks only when _all_ of the following are true:
*
- * r, w = IO.pipe # buffer pipe content
- * w << "abc\ndef\n" # "" "abc\ndef\n"
- * r.gets #=> "abc\n" "def\n" ""
- * w << "ghi\n" # "def\n" "ghi\n"
- * r.readpartial(4096) #=> "def\n" "" "ghi\n"
- * r.readpartial(4096) #=> "ghi\n" "" ""
+ * - The byte buffer in the stream is empty.
+ * - The content of the stream is empty.
+ * - The stream is not at EOF.
*
- * Note that readpartial behaves similar to sysread.
- * The differences are:
- * * If the byte buffer is not empty, read from the byte buffer
+ * When blocked, the method waits for either more data or EOF on the stream:
+ *
+ * - If more data is read, the method returns the data.
+ * - If EOF is reached, the method raises EOFError.
+ *
+ * When not blocked, the method responds immediately:
+ *
+ * - Returns data from the buffer if there is any.
+ * - Otherwise returns data from the stream if there is any.
+ * - Otherwise raises EOFError if the stream has reached EOF.
+ *
+ * Note that this method is similar to sysread. The differences are:
+ *
+ * - If the byte buffer is not empty, read from the byte buffer
* instead of "sysread for buffered IO (IOError)".
- * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
+ * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
* readpartial meets EWOULDBLOCK and EINTR by read system call,
- * readpartial retry the system call.
+ * readpartial retries the system call.
*
- * The latter means that readpartial is nonblocking-flag insensitive.
+ * The latter means that readpartial is non-blocking-flag insensitive.
* It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
* if the fd is blocking mode.
*
+ * Examples:
+ *
+ * # # Returned Buffer Content Pipe Content
+ * r, w = IO.pipe #
+ * w << 'abc' # "" "abc".
+ * r.readpartial(4096) # => "abc" "" ""
+ * r.readpartial(4096) # (Blocks because buffer and pipe are empty.)
+ *
+ * # # Returned Buffer Content Pipe Content
+ * r, w = IO.pipe #
+ * w << 'abc' # "" "abc"
+ * w.close # "" "abc" EOF
+ * r.readpartial(4096) # => "abc" "" EOF
+ * r.readpartial(4096) # raises EOFError
+ *
+ * # # Returned Buffer Content Pipe Content
+ * r, w = IO.pipe #
+ * w << "abc\ndef\n" # "" "abc\ndef\n"
+ * r.gets # => "abc\n" "def\n" ""
+ * w << "ghi\n" # "def\n" "ghi\n"
+ * r.readpartial(4096) # => "def\n" "" "ghi\n"
+ * r.readpartial(4096) # => "ghi\n" "" ""
+ *
*/
static VALUE
@@ -3192,33 +3595,37 @@ io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str,
int shrinkable;
if ((len = NUM2LONG(length)) < 0) {
- rb_raise(rb_eArgError, "negative length %ld given", len);
+ rb_raise(rb_eArgError, "negative length %ld given", len);
}
shrinkable = io_setstrbuf(&str, len);
- rb_bool_expected(ex, "exception");
+ rb_bool_expected(ex, "exception", TRUE);
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
- if (len == 0)
- return str;
+ if (len == 0) {
+ io_set_read_length(str, 0, shrinkable);
+ return str;
+ }
n = read_buffered_data(RSTRING_PTR(str), len, fptr);
if (n <= 0) {
- rb_io_set_nonblock(fptr);
- shrinkable |= io_setstrbuf(&str, len);
- iis.fd = fptr->fd;
+ rb_fd_set_nonblock(fptr->fd);
+ shrinkable |= io_setstrbuf(&str, len);
+ iis.fptr = fptr;
iis.nonblock = 1;
+ iis.fd = fptr->fd;
iis.buf = RSTRING_PTR(str);
iis.capa = len;
- n = read_internal_locktmp(str, &iis);
+ iis.timeout = NULL;
+ n = io_read_memory_locktmp(str, &iis);
if (n < 0) {
- int e = errno;
- if ((e == EWOULDBLOCK || e == EAGAIN)) {
+ int e = errno;
+ if (io_again_p(e)) {
if (!ex) return sym_wait_readable;
- rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
- e, "read would block");
+ rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
+ e, "read would block");
}
rb_syserr_fail_path(e, fptr->pathv);
}
@@ -3227,7 +3634,7 @@ io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str,
if (n == 0) {
if (!ex) return Qnil;
- rb_eof_error();
+ rb_eof_error();
}
return str;
@@ -3241,8 +3648,8 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
long n;
if (!RB_TYPE_P(str, T_STRING))
- str = rb_obj_as_string(str);
- rb_bool_expected(ex, "exception");
+ str = rb_obj_as_string(str);
+ rb_bool_expected(ex, "exception", TRUE);
io = GetWriteIO(io);
GetOpenFile(io, fptr);
@@ -3251,21 +3658,21 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
- rb_io_set_nonblock(fptr);
+ rb_fd_set_nonblock(fptr->fd);
n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
RB_GC_GUARD(str);
if (n < 0) {
- int e = errno;
- if (e == EWOULDBLOCK || e == EAGAIN) {
+ int e = errno;
+ if (io_again_p(e)) {
if (!ex) {
- return sym_wait_writable;
- }
- else {
- rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
- }
- }
- rb_syserr_fail_path(e, fptr->pathv);
+ return sym_wait_writable;
+ }
+ else {
+ rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
+ }
+ }
+ rb_syserr_fail_path(e, fptr->pathv);
}
return LONG2FIX(n);
@@ -3273,69 +3680,73 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
/*
* call-seq:
- * ios.read([length [, outbuf]]) -> string, outbuf, or nil
+ * read(maxlen = nil, out_string = nil) -> new_string, out_string, or nil
*
- * Reads _length_ bytes from the I/O stream.
+ * Reads bytes from the stream; the stream must be opened for reading
+ * (see {Access Modes}[rdoc-ref:File@Access+Modes]):
*
- * _length_ must be a non-negative integer or +nil+.
+ * - If +maxlen+ is +nil+, reads all bytes using the stream's data mode.
+ * - Otherwise reads up to +maxlen+ bytes in binary mode.
*
- * If _length_ is a positive integer, +read+ tries to read
- * _length_ bytes without any conversion (binary mode).
- * It returns +nil+ if an EOF is encountered before anything can be read.
- * Fewer than _length_ bytes are returned if an EOF is encountered during
- * the read.
- * In the case of an integer _length_, the resulting string is always
- * in ASCII-8BIT encoding.
+ * Returns a string (either a new string or the given +out_string+)
+ * containing the bytes read.
+ * The encoding of the string depends on both +maxLen+ and +out_string+:
*
- * If _length_ is omitted or is +nil+, it reads until EOF
- * and the encoding conversion is applied, if applicable.
- * A string is returned even if EOF is encountered before any data is read.
+ * - +maxlen+ is +nil+: uses internal encoding of +self+
+ * (regardless of whether +out_string+ was given).
+ * - +maxlen+ not +nil+:
*
- * If _length_ is zero, it returns an empty string (<code>""</code>).
+ * - +out_string+ given: encoding of +out_string+ not modified.
+ * - +out_string+ not given: ASCII-8BIT is used.
*
- * If the optional _outbuf_ argument is present,
- * it must reference a String, which will receive the data.
- * The _outbuf_ will contain only the received data after the method call
- * even if it is not empty at the beginning.
+ * <b>Without Argument +out_string+</b>
*
- * When this method is called at end of file, it returns +nil+
- * or <code>""</code>, depending on _length_:
- * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
- * <code>""</code>,
- * <code>read(<i>positive_integer</i>)</code> returns +nil+.
+ * When argument +out_string+ is omitted,
+ * the returned value is a new string:
*
- * f = File.new("testfile")
- * f.read(16) #=> "This is line one"
+ * f = File.new('t.txt')
+ * f.read
+ * # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * f.rewind
+ * f.read(30) # => "First line\r\nSecond line\r\n\r\nFou"
+ * f.read(30) # => "rth line\r\nFifth line\r\n"
+ * f.read(30) # => nil
+ * f.close
*
- * # read whole file
- * open("file") do |f|
- * data = f.read # This returns a string even if the file is empty.
- * # ...
- * end
+ * If +maxlen+ is zero, returns an empty string.
*
- * # iterate over fixed length records
- * open("fixed-record-file") do |f|
- * while record = f.read(256)
- * # ...
- * end
- * end
+ * <b> With Argument +out_string+</b>
*
- * # iterate over variable length records,
- * # each record is prefixed by its 32-bit length
- * open("variable-record-file") do |f|
- * while len = f.read(4)
- * len = len.unpack("N")[0] # 32-bit length
- * record = f.read(len) # This returns a string even if len is 0.
- * end
- * end
+ * When argument +out_string+ is given,
+ * the returned value is +out_string+, whose content is replaced:
+ *
+ * f = File.new('t.txt')
+ * s = 'foo' # => "foo"
+ * f.read(nil, s) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * s # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * f.rewind
+ * s = 'bar'
+ * f.read(30, s) # => "First line\r\nSecond line\r\n\r\nFou"
+ * s # => "First line\r\nSecond line\r\n\r\nFou"
+ * s = 'baz'
+ * f.read(30, s) # => "rth line\r\nFifth line\r\n"
+ * s # => "rth line\r\nFifth line\r\n"
+ * s = 'bat'
+ * f.read(30, s) # => nil
+ * s # => ""
+ * f.close
*
* Note that this method behaves like the fread() function in C.
* This means it retries to invoke read(2) system calls to read data
- * with the specified length (or until EOF).
- * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
- * (This method is non-blocking flag insensitive as other methods.)
+ * with the specified maxlen (or until EOF).
+ *
+ * This behavior is preserved even if the stream is in non-blocking mode.
+ * (This method is non-blocking-flag insensitive as other methods.)
+ *
* If you need the behavior like a single read(2) system call,
* consider #readpartial, #read_nonblock, and #sysread.
+ *
+ * Related: IO#write.
*/
static VALUE
@@ -3352,13 +3763,13 @@ io_read(int argc, VALUE *argv, VALUE io)
rb_scan_args(argc, argv, "02", &length, &str);
if (NIL_P(length)) {
- GetOpenFile(io, fptr);
- rb_io_check_char_readable(fptr);
- return read_all(fptr, remain_size(fptr), str);
+ GetOpenFile(io, fptr);
+ rb_io_check_char_readable(fptr);
+ return read_all(fptr, remain_size(fptr), str);
}
len = NUM2LONG(length);
if (len < 0) {
- rb_raise(rb_eArgError, "negative length %ld given", len);
+ rb_raise(rb_eArgError, "negative length %ld given", len);
}
shrinkable = io_setstrbuf(&str,len);
@@ -3366,8 +3777,8 @@ io_read(int argc, VALUE *argv, VALUE io)
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
if (len == 0) {
- io_set_read_length(str, 0, shrinkable);
- return str;
+ io_set_read_length(str, 0, shrinkable);
+ return str;
}
READ_CHECK(fptr);
@@ -3378,7 +3789,7 @@ io_read(int argc, VALUE *argv, VALUE io)
io_set_read_length(str, n, shrinkable);
#if RUBY_CRLF_ENVIRONMENT
if (previous_mode == O_TEXT) {
- setmode(fptr->fd, O_TEXT);
+ setmode(fptr->fd, O_TEXT);
}
#endif
if (n == 0) return Qnil;
@@ -3391,17 +3802,42 @@ rscheck(const char *rsptr, long rslen, VALUE rs)
{
if (!rs) return;
if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
- rb_raise(rb_eRuntimeError, "rs modified");
+ rb_raise(rb_eRuntimeError, "rs modified");
+}
+
+static const char *
+search_delim(const char *p, long len, int delim, rb_encoding *enc)
+{
+ if (rb_enc_mbminlen(enc) == 1) {
+ p = memchr(p, delim, len);
+ if (p) return p + 1;
+ }
+ else {
+ const char *end = p + len;
+ while (p < end) {
+ int r = rb_enc_precise_mbclen(p, end, enc);
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ p += rb_enc_mbminlen(enc);
+ continue;
+ }
+ int n = MBCLEN_CHARFOUND_LEN(r);
+ if (rb_enc_mbc_to_codepoint(p, end, enc) == (unsigned int)delim) {
+ return p + n;
+ }
+ p += n;
+ }
+ }
+ return NULL;
}
static int
-appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
+appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp, rb_encoding *enc)
{
VALUE str = *strp;
long limit = *lp;
if (NEED_READCONV(fptr)) {
- SET_BINARY_MODE(fptr);
+ SET_BINARY_MODE(fptr);
make_readconv(fptr, 0);
do {
const char *p, *e;
@@ -3410,9 +3846,9 @@ appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
p = READ_CHAR_PENDING_PTR(fptr);
if (0 < limit && limit < searchlen)
searchlen = (int)limit;
- e = memchr(p, delim, searchlen);
+ e = search_delim(p, searchlen, delim, enc);
if (e) {
- int len = (int)(e-p+1);
+ int len = (int)(e-p);
if (NIL_P(str))
*strp = str = rb_str_new(p, len);
else
@@ -3445,32 +3881,32 @@ appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
do {
- long pending = READ_DATA_PENDING_COUNT(fptr);
- if (pending > 0) {
- const char *p = READ_DATA_PENDING_PTR(fptr);
- const char *e;
- long last;
-
- if (limit > 0 && pending > limit) pending = limit;
- e = memchr(p, delim, pending);
- if (e) pending = e - p + 1;
- if (!NIL_P(str)) {
- last = RSTRING_LEN(str);
- rb_str_resize(str, last + pending);
- }
- else {
+ long pending = READ_DATA_PENDING_COUNT(fptr);
+ if (pending > 0) {
+ const char *p = READ_DATA_PENDING_PTR(fptr);
+ const char *e;
+ long last;
+
+ if (limit > 0 && pending > limit) pending = limit;
+ e = search_delim(p, pending, delim, enc);
+ if (e) pending = e - p;
+ if (!NIL_P(str)) {
+ last = RSTRING_LEN(str);
+ rb_str_resize(str, last + pending);
+ }
+ else {
last = 0;
- *strp = str = rb_str_buf_new(pending);
- rb_str_set_len(str, pending);
- }
- read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
- limit -= pending;
- *lp = limit;
- if (e) return delim;
- if (limit == 0)
- return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
- }
- READ_CHECK(fptr);
+ *strp = str = rb_str_buf_new(pending);
+ rb_str_set_len(str, pending);
+ }
+ read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
+ limit -= pending;
+ *lp = limit;
+ if (e) return delim;
+ if (limit == 0)
+ return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
+ }
+ READ_CHECK(fptr);
} while (io_fillbuf(fptr) >= 0);
*lp = limit;
return EOF;
@@ -3480,47 +3916,47 @@ static inline int
swallow(rb_io_t *fptr, int term)
{
if (NEED_READCONV(fptr)) {
- rb_encoding *enc = io_read_encoding(fptr);
- int needconv = rb_enc_mbminlen(enc) != 1;
- SET_BINARY_MODE(fptr);
- make_readconv(fptr, 0);
- do {
- size_t cnt;
- while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
- const char *p = READ_CHAR_PENDING_PTR(fptr);
- int i;
- if (!needconv) {
- if (*p != term) return TRUE;
- i = (int)cnt;
- while (--i && *++p == term);
- }
- else {
- const char *e = p + cnt;
- if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
- while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
- i = (int)(e - p);
- }
- io_shift_cbuf(fptr, (int)cnt - i, NULL);
- }
- } while (more_char(fptr) != MORE_CHAR_FINISHED);
- return FALSE;
+ rb_encoding *enc = io_read_encoding(fptr);
+ int needconv = rb_enc_mbminlen(enc) != 1;
+ SET_BINARY_MODE(fptr);
+ make_readconv(fptr, 0);
+ do {
+ size_t cnt;
+ while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
+ const char *p = READ_CHAR_PENDING_PTR(fptr);
+ int i;
+ if (!needconv) {
+ if (*p != term) return TRUE;
+ i = (int)cnt;
+ while (--i && *++p == term);
+ }
+ else {
+ const char *e = p + cnt;
+ if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
+ while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
+ i = (int)(e - p);
+ }
+ io_shift_cbuf(fptr, (int)cnt - i, NULL);
+ }
+ } while (more_char(fptr) != MORE_CHAR_FINISHED);
+ return FALSE;
}
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
do {
- size_t cnt;
- while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
- char buf[1024];
- const char *p = READ_DATA_PENDING_PTR(fptr);
- int i;
- if (cnt > sizeof buf) cnt = sizeof buf;
- if (*p != term) return TRUE;
- i = (int)cnt;
- while (--i && *++p == term);
- if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
- rb_sys_fail_path(fptr->pathv);
- }
- READ_CHECK(fptr);
+ size_t cnt;
+ while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
+ char buf[1024];
+ const char *p = READ_DATA_PENDING_PTR(fptr);
+ int i;
+ if (cnt > sizeof buf) cnt = sizeof buf;
+ if (*p != term) return TRUE;
+ i = (int)cnt;
+ while (--i && *++p == term);
+ if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
+ rb_sys_fail_path(fptr->pathv);
+ }
+ READ_CHECK(fptr);
} while (io_fillbuf(fptr) == 0);
return FALSE;
}
@@ -3534,43 +3970,43 @@ rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
int cr = 0;
do {
- int pending = READ_DATA_PENDING_COUNT(fptr);
+ int pending = READ_DATA_PENDING_COUNT(fptr);
- if (pending > 0) {
- const char *p = READ_DATA_PENDING_PTR(fptr);
- const char *e;
- int chomplen = 0;
+ if (pending > 0) {
+ const char *p = READ_DATA_PENDING_PTR(fptr);
+ const char *e;
+ int chomplen = 0;
- e = memchr(p, '\n', pending);
- if (e) {
+ e = memchr(p, '\n', pending);
+ if (e) {
pending = (int)(e - p + 1);
- if (chomp) {
- chomplen = (pending > 1 && *(e-1) == '\r') + 1;
- }
- }
- if (NIL_P(str)) {
- str = rb_str_new(p, pending - chomplen);
- fptr->rbuf.off += pending;
- fptr->rbuf.len -= pending;
- }
- else {
- rb_str_resize(str, len + pending - chomplen);
- read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
- fptr->rbuf.off += chomplen;
- fptr->rbuf.len -= chomplen;
+ if (chomp) {
+ chomplen = (pending > 1 && *(e-1) == '\r') + 1;
+ }
+ }
+ if (NIL_P(str)) {
+ str = rb_str_new(p, pending - chomplen);
+ fptr->rbuf.off += pending;
+ fptr->rbuf.len -= pending;
+ }
+ else {
+ rb_str_resize(str, len + pending - chomplen);
+ read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
+ fptr->rbuf.off += chomplen;
+ fptr->rbuf.len -= chomplen;
if (pending == 1 && chomplen == 1 && len > 0) {
if (RSTRING_PTR(str)[len-1] == '\r') {
rb_str_resize(str, --len);
break;
}
}
- }
- len += pending - chomplen;
- if (cr != ENC_CODERANGE_BROKEN)
- pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
- if (e) break;
- }
- READ_CHECK(fptr);
+ }
+ len += pending - chomplen;
+ if (cr != ENC_CODERANGE_BROKEN)
+ pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
+ if (e) break;
+ }
+ READ_CHECK(fptr);
} while (io_fillbuf(fptr) >= 0);
if (NIL_P(str)) return Qnil;
@@ -3593,13 +4029,13 @@ extract_getline_opts(VALUE opts, struct getline_arg *args)
{
int chomp = FALSE;
if (!NIL_P(opts)) {
- static ID kwds[1];
- VALUE vchomp;
- if (!kwds[0]) {
- kwds[0] = rb_intern_const("chomp");
- }
- rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
- chomp = (vchomp != Qundef) && RTEST(vchomp);
+ static ID kwds[1];
+ VALUE vchomp;
+ if (!kwds[0]) {
+ kwds[0] = rb_intern_const("chomp");
+ }
+ rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
+ chomp = (!UNDEF_P(vchomp)) && RTEST(vchomp);
}
args->chomp = chomp;
}
@@ -3620,7 +4056,7 @@ extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
}
}
else if (2 <= argc) {
- rs = argv[0], lim = argv[1];
+ rs = argv[0], lim = argv[1];
if (!NIL_P(rs))
StringValue(rs);
}
@@ -3635,25 +4071,25 @@ check_getline_args(VALUE *rsp, long *limit, VALUE io)
VALUE rs = *rsp;
if (!NIL_P(rs)) {
- rb_encoding *enc_rs, *enc_io;
-
- GetOpenFile(io, fptr);
- enc_rs = rb_enc_get(rs);
- enc_io = io_read_encoding(fptr);
- if (enc_io != enc_rs &&
- (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
- (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
+ rb_encoding *enc_rs, *enc_io;
+
+ GetOpenFile(io, fptr);
+ enc_rs = rb_enc_get(rs);
+ enc_io = io_read_encoding(fptr);
+ if (enc_io != enc_rs &&
+ (!is_ascii_string(rs) ||
+ (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
if (rs == rb_default_rs) {
rs = rb_enc_str_new(0, 0, enc_io);
rb_str_buf_cat_ascii(rs, "\n");
- *rsp = rs;
+ *rsp = rs;
}
else {
rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
rb_enc_name(enc_io),
rb_enc_name(enc_rs));
}
- }
+ }
}
}
@@ -3676,77 +4112,86 @@ rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
rb_io_check_char_readable(fptr);
if (NIL_P(rs) && limit < 0) {
- str = read_all(fptr, 0, Qnil);
- if (RSTRING_LEN(str) == 0) return Qnil;
- if (chomp) rb_str_chomp_string(str, rb_default_rs);
+ str = read_all(fptr, 0, Qnil);
+ if (RSTRING_LEN(str) == 0) return Qnil;
}
else if (limit == 0) {
- return rb_enc_str_new(0, 0, io_read_encoding(fptr));
+ return rb_enc_str_new(0, 0, io_read_encoding(fptr));
}
else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
- NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
- return rb_io_getline_fast(fptr, enc, chomp);
+ NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
+ return rb_io_getline_fast(fptr, enc, chomp);
}
else {
- int c, newline = -1;
- const char *rsptr = 0;
- long rslen = 0;
- int rspara = 0;
+ int c, newline = -1;
+ const char *rsptr = 0;
+ long rslen = 0;
+ int rspara = 0;
int extra_limit = 16;
- int chomp_cr = chomp;
+ int chomp_cr = chomp;
- SET_BINARY_MODE(fptr);
+ SET_BINARY_MODE(fptr);
enc = io_read_encoding(fptr);
- if (!NIL_P(rs)) {
- rslen = RSTRING_LEN(rs);
- if (rslen == 0) {
- rsptr = "\n\n";
- rslen = 2;
- rspara = 1;
- swallow(fptr, '\n');
- rs = 0;
- if (!rb_enc_asciicompat(enc)) {
- rs = rb_usascii_str_new(rsptr, rslen);
- rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
- OBJ_FREEZE(rs);
- rsptr = RSTRING_PTR(rs);
- rslen = RSTRING_LEN(rs);
- }
- }
- else {
- rsptr = RSTRING_PTR(rs);
- }
- newline = (unsigned char)rsptr[rslen - 1];
- chomp_cr = chomp && rslen == 1 && newline == '\n';
- }
-
- /* MS - Optimization */
- while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
+ if (!NIL_P(rs)) {
+ rslen = RSTRING_LEN(rs);
+ if (rslen == 0) {
+ rsptr = "\n\n";
+ rslen = 2;
+ rspara = 1;
+ swallow(fptr, '\n');
+ rs = 0;
+ if (!rb_enc_asciicompat(enc)) {
+ rs = rb_usascii_str_new(rsptr, rslen);
+ rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
+ OBJ_FREEZE(rs);
+ rsptr = RSTRING_PTR(rs);
+ rslen = RSTRING_LEN(rs);
+ }
+ newline = '\n';
+ }
+ else if (rb_enc_mbminlen(enc) == 1) {
+ rsptr = RSTRING_PTR(rs);
+ newline = (unsigned char)rsptr[rslen - 1];
+ }
+ else {
+ rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
+ rsptr = RSTRING_PTR(rs);
+ const char *e = rsptr + rslen;
+ const char *last = rb_enc_prev_char(rsptr, e, e, enc);
+ int n;
+ newline = rb_enc_codepoint_len(last, e, &n, enc);
+ if (last + n != e) rb_raise(rb_eArgError, "broken separator");
+ }
+ chomp_cr = chomp && newline == '\n' && rslen == rb_enc_mbminlen(enc);
+ }
+
+ /* MS - Optimization */
+ while ((c = appendline(fptr, newline, &str, &limit, enc)) != EOF) {
const char *s, *p, *pp, *e;
- if (c == newline) {
- if (RSTRING_LEN(str) < rslen) continue;
- s = RSTRING_PTR(str);
+ if (c == newline) {
+ if (RSTRING_LEN(str) < rslen) continue;
+ s = RSTRING_PTR(str);
e = RSTRING_END(str);
- p = e - rslen;
- pp = rb_enc_left_char_head(s, p, e, enc);
- if (pp != p) continue;
- if (!rspara) rscheck(rsptr, rslen, rs);
- if (memcmp(p, rsptr, rslen) == 0) {
- if (chomp) {
- if (chomp_cr && p > s && *(p-1) == '\r') --p;
- rb_str_set_len(str, p - s);
- }
- break;
- }
- }
- if (limit == 0) {
- s = RSTRING_PTR(str);
- p = RSTRING_END(str);
- pp = rb_enc_left_char_head(s, p-1, p, enc);
- if (extra_limit &&
+ p = e - rslen;
+ pp = rb_enc_left_char_head(s, p, e, enc);
+ if (pp != p) continue;
+ if (!rspara) rscheck(rsptr, rslen, rs);
+ if (memcmp(p, rsptr, rslen) == 0) {
+ if (chomp) {
+ if (chomp_cr && p > s && *(p-1) == '\r') --p;
+ rb_str_set_len(str, p - s);
+ }
+ break;
+ }
+ }
+ if (limit == 0) {
+ s = RSTRING_PTR(str);
+ p = RSTRING_END(str);
+ pp = rb_enc_prev_char(s, p, p, enc);
+ if (extra_limit && pp &&
MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
/* relax the limit while incomplete character.
* extra_limit limits the relax length */
@@ -3757,17 +4202,17 @@ rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
nolimit = 1;
break;
}
- }
- }
+ }
+ }
- if (rspara && c != EOF)
- swallow(fptr, '\n');
- if (!NIL_P(str))
+ if (rspara && c != EOF)
+ swallow(fptr, '\n');
+ if (!NIL_P(str))
str = io_enc_str(str, fptr);
}
if (!NIL_P(str) && !nolimit) {
- fptr->lineno++;
+ fptr->lineno++;
}
return str;
@@ -3784,13 +4229,13 @@ rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
old_lineno = fptr->lineno;
str = rb_io_getline_0(rs, limit, chomp, fptr);
if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
- if (io == ARGF.current_file) {
- ARGF.lineno += new_lineno - old_lineno;
- ARGF.last_lineno = ARGF.lineno;
- }
- else {
- ARGF.last_lineno = new_lineno;
- }
+ if (io == ARGF.current_file) {
+ ARGF.lineno += new_lineno - old_lineno;
+ ARGF.last_lineno = ARGF.lineno;
+ }
+ else {
+ ARGF.last_lineno = new_lineno;
+ }
}
return str;
@@ -3821,35 +4266,77 @@ rb_io_gets_internal(VALUE io)
/*
* call-seq:
- * ios.gets(sep=$/ [, getline_args]) -> string or nil
- * ios.gets(limit [, getline_args]) -> string or nil
- * ios.gets(sep, limit [, getline_args]) -> string or nil
+ * gets(sep = $/, chomp: false) -> string or nil
+ * gets(limit, chomp: false) -> string or nil
+ * gets(sep, limit, chomp: false) -> string or nil
+ *
+ * Reads and returns a line from the stream;
+ * assigns the return value to <tt>$_</tt>.
+ * See {Line IO}[rdoc-ref:IO@Line+IO].
+ *
+ * With no arguments given, returns the next line
+ * as determined by line separator <tt>$/</tt>, or +nil+ if none:
+ *
+ * f = File.open('t.txt')
+ * f.gets # => "First line\n"
+ * $_ # => "First line\n"
+ * f.gets # => "\n"
+ * f.gets # => "Fourth line\n"
+ * f.gets # => "Fifth line\n"
+ * f.gets # => nil
+ * f.close
*
- * Reads the next ``line'' from the I/O stream; lines are separated by
- * <i>sep</i>. A separator of +nil+ reads the entire
- * contents, and a zero-length separator reads the input a paragraph at
- * a time (two successive newlines in the input separate paragraphs).
- * The stream must be opened for reading or an IOError will be raised.
- * The line read in will be returned and also assigned to
- * <code>$_</code>. Returns +nil+ if called at end of file. If the
- * first argument is an integer, or optional second argument is given,
- * the returning string would not be longer than the given value in
- * bytes.
+ * With only string argument +sep+ given,
+ * returns the next line as determined by line separator +sep+,
+ * or +nil+ if none;
+ * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
*
- * File.new("testfile").gets #=> "This is line one\n"
- * $_ #=> "This is line one\n"
+ * f = File.new('t.txt')
+ * f.gets('l') # => "First l"
+ * f.gets('li') # => "ine\nSecond li"
+ * f.gets('lin') # => "ne\n\nFourth lin"
+ * f.gets # => "e\n"
+ * f.close
*
- * File.new("testfile").gets(4)#=> "This"
+ * The two special values for +sep+ are honored:
*
- * If IO contains multibyte characters byte then <code>gets(1)</code>
- * returns character entirely:
+ * f = File.new('t.txt')
+ * # Get all.
+ * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * f.rewind
+ * # Get paragraph (up to two line separators).
+ * f.gets('') # => "First line\nSecond line\n\n"
+ * f.close
+ *
+ * With only integer argument +limit+ given,
+ * limits the number of bytes in the line;
+ * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
+ *
+ * # No more than one line.
+ * File.open('t.txt') {|f| f.gets(10) } # => "First line"
+ * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
+ * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
+ *
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors:
+ *
+ * - Returns the next line as determined by line separator +sep+,
+ * or +nil+ if none.
+ * - But returns no more bytes than are allowed by the limit.
+ *
+ * Optional keyword argument +chomp+ specifies whether line separators
+ * are to be omitted:
+ *
+ * f = File.open('t.txt')
+ * # Chomp the lines.
+ * f.gets(chomp: true) # => "First line"
+ * f.gets(chomp: true) # => "Second line"
+ * f.gets(chomp: true) # => ""
+ * f.gets(chomp: true) # => "Fourth line"
+ * f.gets(chomp: true) # => "Fifth line"
+ * f.gets(chomp: true) # => nil
+ * f.close
*
- * # Russian characters take 2 bytes
- * File.write("testfile", "\u{442 435 441 442}")
- * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
- * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
- * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
- * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
*/
static VALUE
@@ -3865,24 +4352,11 @@ rb_io_gets_m(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * ios.lineno -> integer
- *
- * Returns the current line number in <em>ios</em>. The stream must be
- * opened for reading. #lineno counts the number of times #gets is called
- * rather than the number of newlines encountered. The two values will
- * differ if #gets is called with a separator other than newline.
+ * lineno -> integer
*
- * Methods that use <code>$/</code> like #each, #lines and #readline will
- * also increment #lineno.
+ * Returns the current line number for the stream;
+ * see {Line Number}[rdoc-ref:IO@Line+Number].
*
- * See also the <code>$.</code> variable.
- *
- * f = File.new("testfile")
- * f.lineno #=> 0
- * f.gets #=> "This is line one\n"
- * f.lineno #=> 1
- * f.gets #=> "This is line two\n"
- * f.lineno #=> 2
*/
static VALUE
@@ -3897,19 +4371,11 @@ rb_io_lineno(VALUE io)
/*
* call-seq:
- * ios.lineno = integer -> integer
+ * lineno = integer -> integer
*
- * Manually sets the current line number to the given value.
- * <code>$.</code> is updated only on the next read.
+ * Sets and returns the line number for the stream;
+ * see {Line Number}[rdoc-ref:IO@Line+Number].
*
- * f = File.new("testfile")
- * f.gets #=> "This is line one\n"
- * $. #=> 1
- * f.lineno = 1000
- * f.lineno #=> 1000
- * $. #=> 1 # lineno of last read
- * f.gets #=> "This is line two\n"
- * $. #=> 1001 # lineno of last read
*/
static VALUE
@@ -3925,11 +4391,14 @@ rb_io_set_lineno(VALUE io, VALUE lineno)
/*
* call-seq:
- * ios.readline(sep=$/ [, getline_args]) -> string
- * ios.readline(limit [, getline_args]) -> string
- * ios.readline(sep, limit [, getline_args]) -> string
+ * readline(sep = $/, chomp: false) -> string
+ * readline(limit, chomp: false) -> string
+ * readline(sep, limit, chomp: false) -> string
+ *
+ * Reads a line as with IO#gets, but raises EOFError if already at end-of-stream.
*
- * Reads a line as with IO#gets, but raises an EOFError on end of file.
+ * Optional keyword argument +chomp+ specifies whether line separators
+ * are to be omitted.
*/
static VALUE
@@ -3938,7 +4407,7 @@ rb_io_readline(int argc, VALUE *argv, VALUE io)
VALUE line = rb_io_gets_m(argc, argv, io);
if (NIL_P(line)) {
- rb_eof_error();
+ rb_eof_error();
}
return line;
}
@@ -3947,26 +4416,68 @@ static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
/*
* call-seq:
- * ios.readlines(sep=$/ [, getline_args]) -> array
- * ios.readlines(limit [, getline_args]) -> array
- * ios.readlines(sep, limit [, getline_args]) -> array
+ * readlines(sep = $/, chomp: false) -> array
+ * readlines(limit, chomp: false) -> array
+ * readlines(sep, limit, chomp: false) -> array
*
- * Reads all of the lines in <em>ios</em>, and returns them in
- * an array. Lines are separated by the optional <i>sep</i>. If
- * <i>sep</i> is +nil+, the rest of the stream is returned
- * as a single record.
- * If the first argument is an integer, or an
- * optional second argument is given, the returning string would not be
- * longer than the given value in bytes. The stream must be opened for
- * reading or an IOError will be raised.
+ * Reads and returns all remaining line from the stream;
+ * does not modify <tt>$_</tt>.
+ * See {Line IO}[rdoc-ref:IO@Line+IO].
*
- * f = File.new("testfile")
- * f.readlines[0] #=> "This is line one\n"
+ * With no arguments given, returns lines
+ * as determined by line separator <tt>$/</tt>, or +nil+ if none:
*
- * f = File.new("testfile", chomp: true)
- * f.readlines[0] #=> "This is line one"
+ * f = File.new('t.txt')
+ * f.readlines
+ * # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
+ * f.readlines # => []
+ * f.close
+ *
+ * With only string argument +sep+ given,
+ * returns lines as determined by line separator +sep+,
+ * or +nil+ if none;
+ * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
+ *
+ * f = File.new('t.txt')
+ * f.readlines('li')
+ * # => ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
+ * f.close
+ *
+ * The two special values for +sep+ are honored:
+ *
+ * f = File.new('t.txt')
+ * # Get all into one string.
+ * f.readlines(nil)
+ * # => ["First line\nSecond line\n\nFourth line\nFifth line\n"]
+ * # Get paragraphs (up to two line separators).
+ * f.rewind
+ * f.readlines('')
+ * # => ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
+ * f.close
+ *
+ * With only integer argument +limit+ given,
+ * limits the number of bytes in each line;
+ * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
+ *
+ * f = File.new('t.txt')
+ * f.readlines(8)
+ * # => ["First li", "ne\n", "Second l", "ine\n", "\n", "Fourth l", "ine\n", "Fifth li", "ne\n"]
+ * f.close
+ *
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors:
+ *
+ * - Returns lines as determined by line separator +sep+.
+ * - But returns no more bytes in a line than are allowed by the limit.
+ *
+ * Optional keyword argument +chomp+ specifies whether line separators
+ * are to be omitted:
+ *
+ * f = File.new('t.txt')
+ * f.readlines(chomp: true)
+ * # => ["First line", "Second line", "", "Fourth line", "Fifth line"]
+ * f.close
*
- * See IO.readlines for details about getline_args.
*/
static VALUE
@@ -3984,43 +4495,123 @@ io_readlines(const struct getline_arg *arg, VALUE io)
VALUE line, ary;
if (arg->limit == 0)
- rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
+ rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
ary = rb_ary_new();
while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
- rb_ary_push(ary, line);
+ rb_ary_push(ary, line);
}
return ary;
}
/*
* call-seq:
- * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
- * ios.each(limit [, getline_args]) {|line| block } -> ios
- * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
- * ios.each(...) -> an_enumerator
+ * each_line(sep = $/, chomp: false) {|line| ... } -> self
+ * each_line(limit, chomp: false) {|line| ... } -> self
+ * each_line(sep, limit, chomp: false) {|line| ... } -> self
+ * each_line -> enumerator
*
- * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
- * ios.each_line(limit [, getline_args]) {|line| block } -> ios
- * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
- * ios.each_line(...) -> an_enumerator
+ * Calls the block with each remaining line read from the stream;
+ * returns +self+.
+ * Does nothing if already at end-of-stream;
+ * See {Line IO}[rdoc-ref:IO@Line+IO].
*
- * Executes the block for every line in <em>ios</em>, where lines are
- * separated by <i>sep</i>. <em>ios</em> must be opened for
- * reading or an IOError will be raised.
+ * With no arguments given, reads lines
+ * as determined by line separator <tt>$/</tt>:
*
- * If no block is given, an enumerator is returned instead.
+ * f = File.new('t.txt')
+ * f.each_line {|line| p line }
+ * f.each_line {|line| fail 'Cannot happen' }
+ * f.close
*
- * f = File.new("testfile")
- * f.each {|line| puts "#{f.lineno}: #{line}" }
+ * Output:
*
- * <em>produces:</em>
+ * "First line\n"
+ * "Second line\n"
+ * "\n"
+ * "Fourth line\n"
+ * "Fifth line\n"
*
- * 1: This is line one
- * 2: This is line two
- * 3: This is line three
- * 4: And so on...
+ * With only string argument +sep+ given,
+ * reads lines as determined by line separator +sep+;
+ * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
+ *
+ * f = File.new('t.txt')
+ * f.each_line('li') {|line| p line }
+ * f.close
+ *
+ * Output:
+ *
+ * "First li"
+ * "ne\nSecond li"
+ * "ne\n\nFourth li"
+ * "ne\nFifth li"
+ * "ne\n"
+ *
+ * The two special values for +sep+ are honored:
+ *
+ * f = File.new('t.txt')
+ * # Get all into one string.
+ * f.each_line(nil) {|line| p line }
+ * f.close
+ *
+ * Output:
+ *
+ * "First line\nSecond line\n\nFourth line\nFifth line\n"
+ *
+ * f.rewind
+ * # Get paragraphs (up to two line separators).
+ * f.each_line('') {|line| p line }
+ *
+ * Output:
+ *
+ * "First line\nSecond line\n\n"
+ * "Fourth line\nFifth line\n"
+ *
+ * With only integer argument +limit+ given,
+ * limits the number of bytes in each line;
+ * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
+ *
+ * f = File.new('t.txt')
+ * f.each_line(8) {|line| p line }
+ * f.close
+ *
+ * Output:
+ *
+ * "First li"
+ * "ne\n"
+ * "Second l"
+ * "ine\n"
+ * "\n"
+ * "Fourth l"
+ * "ine\n"
+ * "Fifth li"
+ * "ne\n"
+ *
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors:
+ *
+ * - Calls with the next line as determined by line separator +sep+.
+ * - But returns no more bytes than are allowed by the limit.
+ *
+ * Optional keyword argument +chomp+ specifies whether line separators
+ * are to be omitted:
+ *
+ * f = File.new('t.txt')
+ * f.each_line(chomp: true) {|line| p line }
+ * f.close
+ *
+ * Output:
+ *
+ * "First line"
+ * "Second line"
+ * ""
+ * "Fourth line"
+ * "Fifth line"
+ *
+ * Returns an Enumerator if no block is given.
+ *
+ * IO#each is an alias for IO#each_line.
*
- * See IO.readlines for details about getline_args.
*/
static VALUE
@@ -4032,28 +4623,31 @@ rb_io_each_line(int argc, VALUE *argv, VALUE io)
RETURN_ENUMERATOR(io, argc, argv);
prepare_getline_args(argc, argv, &args, io);
if (args.limit == 0)
- rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
+ rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
- rb_yield(str);
+ rb_yield(str);
}
return io;
}
/*
* call-seq:
- * ios.each_byte {|byte| block } -> ios
- * ios.each_byte -> an_enumerator
+ * each_byte {|byte| ... } -> self
+ * each_byte -> enumerator
*
- * Calls the given block once for each byte (0..255) in <em>ios</em>,
- * passing the byte as an argument. The stream must be opened for
- * reading or an IOError will be raised.
+ * Calls the given block with each byte (0..255) in the stream; returns +self+.
+ * See {Byte IO}[rdoc-ref:IO@Byte+IO].
*
- * If no block is given, an enumerator is returned instead.
+ * f = File.new('t.rus')
+ * a = []
+ * f.each_byte {|b| a << b }
+ * a # => [209, 130, 208, 181, 209, 129, 209, 130]
+ * f.close
+ *
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: IO#each_char, IO#each_codepoint.
*
- * f = File.new("testfile")
- * checksum = 0
- * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
- * checksum #=> 12
*/
static VALUE
@@ -4065,14 +4659,14 @@ rb_io_each_byte(VALUE io)
GetOpenFile(io, fptr);
do {
- while (fptr->rbuf.len > 0) {
- char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
- fptr->rbuf.len--;
- rb_yield(INT2FIX(*p & 0xff));
- rb_io_check_byte_readable(fptr);
- errno = 0;
- }
- READ_CHECK(fptr);
+ while (fptr->rbuf.len > 0) {
+ char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
+ fptr->rbuf.len--;
+ rb_yield(INT2FIX(*p & 0xff));
+ rb_io_check_byte_readable(fptr);
+ errno = 0;
+ }
+ READ_CHECK(fptr);
} while (io_fillbuf(fptr) >= 0);
return io;
}
@@ -4084,17 +4678,17 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
VALUE str;
if (NEED_READCONV(fptr)) {
- rb_encoding *read_enc = io_read_encoding(fptr);
+ rb_encoding *read_enc = io_read_encoding(fptr);
- str = Qnil;
- SET_BINARY_MODE(fptr);
+ str = Qnil;
+ SET_BINARY_MODE(fptr);
make_readconv(fptr, 0);
while (1) {
if (fptr->cbuf.len) {
- r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
- fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
- read_enc);
+ r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
+ fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
+ read_enc);
if (!MBCLEN_NEEDMORE_P(r))
break;
if (fptr->cbuf.len == fptr->cbuf.capa) {
@@ -4104,16 +4698,16 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
if (more_char(fptr) == MORE_CHAR_FINISHED) {
if (fptr->cbuf.len == 0) {
- clear_readconv(fptr);
- return Qnil;
- }
+ clear_readconv(fptr);
+ return Qnil;
+ }
/* return an unit of an incomplete character just before EOF */
- str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
- fptr->cbuf.off += 1;
- fptr->cbuf.len -= 1;
+ str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
+ fptr->cbuf.off += 1;
+ fptr->cbuf.len -= 1;
if (fptr->cbuf.len == 0) clear_readconv(fptr);
- ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
- return str;
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
+ return str;
}
}
if (MBCLEN_INVALID_P(r)) {
@@ -4121,62 +4715,62 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
read_enc);
io_shift_cbuf(fptr, r, &str);
- cr = ENC_CODERANGE_BROKEN;
- }
- else {
- io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
- cr = ENC_CODERANGE_VALID;
- if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
- ISASCII(RSTRING_PTR(str)[0])) {
- cr = ENC_CODERANGE_7BIT;
- }
- }
- str = io_enc_str(str, fptr);
- ENC_CODERANGE_SET(str, cr);
- return str;
+ cr = ENC_CODERANGE_BROKEN;
+ }
+ else {
+ io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
+ cr = ENC_CODERANGE_VALID;
+ if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
+ ISASCII(RSTRING_PTR(str)[0])) {
+ cr = ENC_CODERANGE_7BIT;
+ }
+ }
+ str = io_enc_str(str, fptr);
+ ENC_CODERANGE_SET(str, cr);
+ return str;
}
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
if (io_fillbuf(fptr) < 0) {
- return Qnil;
+ return Qnil;
}
if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
- str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
- fptr->rbuf.off += 1;
- fptr->rbuf.len -= 1;
- cr = ENC_CODERANGE_7BIT;
+ str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
+ fptr->rbuf.off += 1;
+ fptr->rbuf.len -= 1;
+ cr = ENC_CODERANGE_7BIT;
}
else {
- r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
- if (MBCLEN_CHARFOUND_P(r) &&
- (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
- str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
- fptr->rbuf.off += n;
- fptr->rbuf.len -= n;
- cr = ENC_CODERANGE_VALID;
- }
- else if (MBCLEN_NEEDMORE_P(r)) {
- str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
- fptr->rbuf.len = 0;
- getc_needmore:
- if (io_fillbuf(fptr) != -1) {
- rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
- fptr->rbuf.off++;
- fptr->rbuf.len--;
- r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
- if (MBCLEN_NEEDMORE_P(r)) {
- goto getc_needmore;
- }
- else if (MBCLEN_CHARFOUND_P(r)) {
- cr = ENC_CODERANGE_VALID;
- }
- }
- }
- else {
- str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
- fptr->rbuf.off++;
- fptr->rbuf.len--;
- }
+ r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
+ if (MBCLEN_CHARFOUND_P(r) &&
+ (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
+ str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
+ fptr->rbuf.off += n;
+ fptr->rbuf.len -= n;
+ cr = ENC_CODERANGE_VALID;
+ }
+ else if (MBCLEN_NEEDMORE_P(r)) {
+ str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
+ fptr->rbuf.len = 0;
+ getc_needmore:
+ if (io_fillbuf(fptr) != -1) {
+ rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
+ fptr->rbuf.off++;
+ fptr->rbuf.len--;
+ r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
+ if (MBCLEN_NEEDMORE_P(r)) {
+ goto getc_needmore;
+ }
+ else if (MBCLEN_CHARFOUND_P(r)) {
+ cr = ENC_CODERANGE_VALID;
+ }
+ }
+ }
+ else {
+ str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
+ fptr->rbuf.off++;
+ fptr->rbuf.len--;
+ }
}
if (!cr) cr = ENC_CODERANGE_BROKEN;
str = io_enc_str(str, fptr);
@@ -4186,17 +4780,22 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
/*
* call-seq:
- * ios.each_char {|c| block } -> ios
- * ios.each_char -> an_enumerator
+ * each_char {|c| ... } -> self
+ * each_char -> enumerator
*
- * Calls the given block once for each character in <em>ios</em>,
- * passing the character as an argument. The stream must be opened for
- * reading or an IOError will be raised.
+ * Calls the given block with each character in the stream; returns +self+.
+ * See {Character IO}[rdoc-ref:IO@Character+IO].
*
- * If no block is given, an enumerator is returned instead.
+ * f = File.new('t.rus')
+ * a = []
+ * f.each_char {|c| a << c.ord }
+ * a # => [1090, 1077, 1089, 1090]
+ * f.close
+ *
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: IO#each_byte, IO#each_codepoint.
*
- * f = File.new("testfile")
- * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
*/
static VALUE
@@ -4220,14 +4819,20 @@ rb_io_each_char(VALUE io)
/*
* call-seq:
- * ios.each_codepoint {|c| block } -> ios
- * ios.each_codepoint -> an_enumerator
+ * each_codepoint {|c| ... } -> self
+ * each_codepoint -> enumerator
*
- * Passes the Integer ordinal of each character in <i>ios</i>,
- * passing the codepoint as an argument. The stream must be opened for
- * reading or an IOError will be raised.
+ * Calls the given block with each codepoint in the stream; returns +self+:
*
- * If no block is given, an enumerator is returned instead.
+ * f = File.new('t.rus')
+ * a = []
+ * f.each_codepoint {|c| a << c }
+ * a # => [1090, 1077, 1089, 1090]
+ * f.close
+ *
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: IO#each_byte, IO#each_char.
*
*/
@@ -4245,87 +4850,87 @@ rb_io_each_codepoint(VALUE io)
READ_CHECK(fptr);
if (NEED_READCONV(fptr)) {
- SET_BINARY_MODE(fptr);
- r = 1; /* no invalid char yet */
- for (;;) {
- make_readconv(fptr, 0);
- for (;;) {
- if (fptr->cbuf.len) {
- if (fptr->encs.enc)
- r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
- fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
- fptr->encs.enc);
- else
- r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
- if (!MBCLEN_NEEDMORE_P(r))
- break;
- if (fptr->cbuf.len == fptr->cbuf.capa) {
- rb_raise(rb_eIOError, "too long character");
- }
- }
- if (more_char(fptr) == MORE_CHAR_FINISHED) {
+ SET_BINARY_MODE(fptr);
+ r = 1; /* no invalid char yet */
+ for (;;) {
+ make_readconv(fptr, 0);
+ for (;;) {
+ if (fptr->cbuf.len) {
+ if (fptr->encs.enc)
+ r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
+ fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
+ fptr->encs.enc);
+ else
+ r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
+ if (!MBCLEN_NEEDMORE_P(r))
+ break;
+ if (fptr->cbuf.len == fptr->cbuf.capa) {
+ rb_raise(rb_eIOError, "too long character");
+ }
+ }
+ if (more_char(fptr) == MORE_CHAR_FINISHED) {
clear_readconv(fptr);
- if (!MBCLEN_CHARFOUND_P(r)) {
- enc = fptr->encs.enc;
- goto invalid;
- }
- return io;
- }
- }
- if (MBCLEN_INVALID_P(r)) {
- enc = fptr->encs.enc;
- goto invalid;
- }
- n = MBCLEN_CHARFOUND_LEN(r);
- if (fptr->encs.enc) {
- c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
- fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
- fptr->encs.enc);
- }
- else {
- c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
- }
- fptr->cbuf.off += n;
- fptr->cbuf.len -= n;
- rb_yield(UINT2NUM(c));
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ enc = fptr->encs.enc;
+ goto invalid;
+ }
+ return io;
+ }
+ }
+ if (MBCLEN_INVALID_P(r)) {
+ enc = fptr->encs.enc;
+ goto invalid;
+ }
+ n = MBCLEN_CHARFOUND_LEN(r);
+ if (fptr->encs.enc) {
+ c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
+ fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
+ fptr->encs.enc);
+ }
+ else {
+ c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
+ }
+ 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);
enc = io_input_encoding(fptr);
while (io_fillbuf(fptr) >= 0) {
- r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
- fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
- if (MBCLEN_CHARFOUND_P(r) &&
- (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
- c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
- fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
- fptr->rbuf.off += n;
- fptr->rbuf.len -= n;
- rb_yield(UINT2NUM(c));
- }
- else if (MBCLEN_INVALID_P(r)) {
+ r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
+ fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
+ if (MBCLEN_CHARFOUND_P(r) &&
+ (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
+ c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
+ fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
+ fptr->rbuf.off += n;
+ fptr->rbuf.len -= n;
+ rb_yield(UINT2NUM(c));
+ }
+ else if (MBCLEN_INVALID_P(r)) {
goto invalid;
- }
- else if (MBCLEN_NEEDMORE_P(r)) {
- char cbuf[8], *p = cbuf;
- int more = MBCLEN_NEEDMORE_LEN(r);
- if (more > numberof(cbuf)) goto invalid;
- more += n = fptr->rbuf.len;
- if (more > numberof(cbuf)) goto invalid;
- while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
- (p += n, (more -= n) > 0)) {
- if (io_fillbuf(fptr) < 0) goto invalid;
- if ((n = fptr->rbuf.len) > more) n = more;
- }
- r = rb_enc_precise_mbclen(cbuf, p, enc);
- if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
- c = rb_enc_codepoint(cbuf, p, enc);
- rb_yield(UINT2NUM(c));
- }
- else {
- continue;
- }
+ }
+ else if (MBCLEN_NEEDMORE_P(r)) {
+ char cbuf[8], *p = cbuf;
+ int more = MBCLEN_NEEDMORE_LEN(r);
+ if (more > numberof(cbuf)) goto invalid;
+ more += n = fptr->rbuf.len;
+ if (more > numberof(cbuf)) goto invalid;
+ while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
+ (p += n, (more -= n) > 0)) {
+ if (io_fillbuf(fptr) < 0) goto invalid;
+ if ((n = fptr->rbuf.len) > more) n = more;
+ }
+ r = rb_enc_precise_mbclen(cbuf, p, enc);
+ if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
+ c = rb_enc_codepoint(cbuf, p, enc);
+ rb_yield(UINT2NUM(c));
+ }
+ else {
+ continue;
+ }
rb_io_check_byte_readable(fptr);
}
return io;
@@ -4337,14 +4942,21 @@ rb_io_each_codepoint(VALUE io)
/*
* call-seq:
- * ios.getc -> string or nil
+ * getc -> character or nil
+ *
+ * Reads and returns the next 1-character string from the stream;
+ * returns +nil+ if already at end-of-stream.
+ * See {Character IO}[rdoc-ref:IO@Character+IO].
+ *
+ * f = File.open('t.txt')
+ * f.getc # => "F"
+ * f.close
+ * f = File.open('t.rus')
+ * f.getc.ord # => 1090
+ * f.close
*
- * Reads a one-character string from <em>ios</em>. Returns
- * +nil+ if called at end of file.
+ * Related: IO#readchar (may raise EOFError).
*
- * f = File.new("testfile")
- * f.getc #=> "h"
- * f.getc #=> "e"
*/
static VALUE
@@ -4363,14 +4975,21 @@ rb_io_getc(VALUE io)
/*
* call-seq:
- * ios.readchar -> string
+ * readchar -> string
*
- * Reads a one-character string from <em>ios</em>. Raises an
- * EOFError on end of file.
+ * Reads and returns the next 1-character string from the stream;
+ * raises EOFError if already at end-of-stream.
+ * See {Character IO}[rdoc-ref:IO@Character+IO].
+ *
+ * f = File.open('t.txt')
+ * f.readchar # => "F"
+ * f.close
+ * f = File.open('t.rus')
+ * f.readchar.ord # => 1090
+ * f.close
+ *
+ * Related: IO#getc (will not raise EOFError).
*
- * f = File.new("testfile")
- * f.readchar #=> "h"
- * f.readchar #=> "e"
*/
static VALUE
@@ -4379,21 +4998,27 @@ rb_io_readchar(VALUE io)
VALUE c = rb_io_getc(io);
if (NIL_P(c)) {
- rb_eof_error();
+ rb_eof_error();
}
return c;
}
/*
* call-seq:
- * ios.getbyte -> integer or nil
+ * getbyte -> integer or nil
*
- * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
- * +nil+ if called at end of file.
+ * Reads and returns the next byte (in range 0..255) from the stream;
+ * returns +nil+ if already at end-of-stream.
+ * See {Byte IO}[rdoc-ref:IO@Byte+IO].
*
- * f = File.new("testfile")
- * f.getbyte #=> 84
- * f.getbyte #=> 104
+ * f = File.open('t.txt')
+ * f.getbyte # => 70
+ * f.close
+ * f = File.open('t.rus')
+ * f.getbyte # => 209
+ * f.close
+ *
+ * Related: IO#readbyte (may raise EOFError).
*/
VALUE
@@ -4414,7 +5039,7 @@ rb_io_getbyte(VALUE io)
}
}
if (io_fillbuf(fptr) < 0) {
- return Qnil;
+ return Qnil;
}
fptr->rbuf.off++;
fptr->rbuf.len--;
@@ -4424,10 +5049,21 @@ rb_io_getbyte(VALUE io)
/*
* call-seq:
- * ios.readbyte -> integer
+ * readbyte -> integer
+ *
+ * Reads and returns the next byte (in range 0..255) from the stream;
+ * raises EOFError if already at end-of-stream.
+ * See {Byte IO}[rdoc-ref:IO@Byte+IO].
+ *
+ * f = File.open('t.txt')
+ * f.readbyte # => 70
+ * f.close
+ * f = File.open('t.rus')
+ * f.readbyte # => 209
+ * f.close
+ *
+ * Related: IO#getbyte (will not raise EOFError).
*
- * Reads a byte as with IO#getbyte, but raises an EOFError on end of
- * file.
*/
static VALUE
@@ -4436,45 +5072,47 @@ rb_io_readbyte(VALUE io)
VALUE c = rb_io_getbyte(io);
if (NIL_P(c)) {
- rb_eof_error();
+ rb_eof_error();
}
return c;
}
/*
* call-seq:
- * ios.ungetbyte(string) -> nil
- * ios.ungetbyte(integer) -> nil
+ * ungetbyte(integer) -> nil
+ * ungetbyte(string) -> nil
*
- * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
- * such that a subsequent buffered read will return it.
- * It is only guaranteed to support a single byte, and only if ungetbyte
- * or ungetc has not already been called on <em>ios</em> since the previous
- * read of at least a single byte from <em>ios</em>.
- * However, it can support additional bytes if there is space in the
- * internal buffer to allow for it.
+ * Pushes back ("unshifts") the given data onto the stream's buffer,
+ * placing the data so that it is next to be read; returns +nil+.
+ * See {Byte IO}[rdoc-ref:IO@Byte+IO].
*
- * f = File.new("testfile") #=> #<File:testfile>
- * b = f.getbyte #=> 0x38
- * f.ungetbyte(b) #=> nil
- * f.getbyte #=> 0x38
+ * Note that:
*
- * If given an integer, only uses the lower 8 bits of the integer as the byte
- * to push.
+ * - Calling the method has no effect with unbuffered reads (such as IO#sysread).
+ * - Calling #rewind on the stream discards the pushed-back data.
*
- * f = File.new("testfile") #=> #<File:testfile>
- * f.ungetbyte(0x102) #=> nil
- * f.getbyte #=> 0x2
+ * When argument +integer+ is given, uses only its low-order byte:
*
- * Calling this method prepends to the existing buffer, even if the method
- * has already been called previously:
+ * File.write('t.tmp', '012')
+ * f = File.open('t.tmp')
+ * f.ungetbyte(0x41) # => nil
+ * f.read # => "A012"
+ * f.rewind
+ * f.ungetbyte(0x4243) # => nil
+ * f.read # => "C012"
+ * f.close
*
- * f = File.new("testfile") #=> #<File:testfile>
- * f.ungetbyte("ab") #=> nil
- * f.ungetbyte("cd") #=> nil
- * f.read(5) #=> "cdab8"
+ * When argument +string+ is given, uses all bytes:
+ *
+ * File.write('t.tmp', '012')
+ * f = File.open('t.tmp')
+ * f.ungetbyte('A') # => nil
+ * f.read # => "A012"
+ * f.rewind
+ * f.ungetbyte('BCDE') # => nil
+ * f.read # => "BCDE012"
+ * f.close
*
- * Has no effect with unbuffered reads (such as IO#sysread).
*/
VALUE
@@ -4502,34 +5140,43 @@ rb_io_ungetbyte(VALUE io, VALUE b)
/*
* call-seq:
- * ios.ungetc(integer) -> nil
- * ios.ungetc(string) -> nil
+ * ungetc(integer) -> nil
+ * ungetc(string) -> nil
+ *
+ * Pushes back ("unshifts") the given data onto the stream's buffer,
+ * placing the data so that it is next to be read; returns +nil+.
+ * See {Character IO}[rdoc-ref:IO@Character+IO].
*
- * Pushes back characters (passed as a parameter) onto <em>ios</em>,
- * such that a subsequent buffered read will return it.
- * It is only guaranteed to support a single byte, and only if ungetbyte
- * or ungetc has not already been called on <em>ios</em> since the previous
- * read of at least a single byte from <em>ios</em>.
- * However, it can support additional bytes if there is space in the
- * internal buffer to allow for it.
+ * Note that:
*
- * f = File.new("testfile") #=> #<File:testfile>
- * c = f.getc #=> "8"
- * f.ungetc(c) #=> nil
- * f.getc #=> "8"
+ * - Calling the method has no effect with unbuffered reads (such as IO#sysread).
+ * - Calling #rewind on the stream discards the pushed-back data.
*
- * If given an integer, the integer must represent a valid codepoint in the
- * external encoding of <em>ios</em>.
+ * When argument +integer+ is given, interprets the integer as a character:
*
- * Calling this method prepends to the existing buffer, even if the method
- * has already been called previously:
+ * File.write('t.tmp', '012')
+ * f = File.open('t.tmp')
+ * f.ungetc(0x41) # => nil
+ * f.read # => "A012"
+ * f.rewind
+ * f.ungetc(0x0442) # => nil
+ * f.getc.ord # => 1090
+ * f.close
*
- * f = File.new("testfile") #=> #<File:testfile>
- * f.ungetc("ab") #=> nil
- * f.ungetc("cd") #=> nil
- * f.read(5) #=> "cdab8"
+ * When argument +string+ is given, uses all characters:
+ *
+ * File.write('t.tmp', '012')
+ * f = File.open('t.tmp')
+ * f.ungetc('A') # => nil
+ * f.read # => "A012"
+ * f.rewind
+ * f.ungetc("\u0442\u0435\u0441\u0442") # => nil
+ * f.getc.ord # => 1090
+ * f.getc.ord # => 1077
+ * f.getc.ord # => 1089
+ * f.getc.ord # => 1090
+ * f.close
*
- * Has no effect with unbuffered reads (such as IO#sysread).
*/
VALUE
@@ -4541,20 +5188,20 @@ rb_io_ungetc(VALUE io, VALUE c)
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
if (FIXNUM_P(c)) {
- c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
+ c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
}
- else if (RB_TYPE_P(c, T_BIGNUM)) {
- c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
+ else if (RB_BIGNUM_TYPE_P(c)) {
+ c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
}
else {
- SafeStringValue(c);
+ SafeStringValue(c);
}
if (NEED_READCONV(fptr)) {
- SET_BINARY_MODE(fptr);
+ SET_BINARY_MODE(fptr);
len = RSTRING_LEN(c);
#if SIZEOF_LONG > SIZEOF_INT
- if (len > INT_MAX)
- rb_raise(rb_eIOError, "ungetc failed");
+ if (len > INT_MAX)
+ rb_raise(rb_eIOError, "ungetc failed");
#endif
make_readconv(fptr, (int)len);
if (fptr->cbuf.capa - fptr->cbuf.len < len)
@@ -4570,7 +5217,7 @@ rb_io_ungetc(VALUE io, VALUE c)
MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
}
else {
- NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
+ NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
io_ungetbyte(c, fptr);
}
return Qnil;
@@ -4578,14 +5225,18 @@ rb_io_ungetc(VALUE io, VALUE c)
/*
* call-seq:
- * ios.isatty -> true or false
- * ios.tty? -> true or false
+ * isatty -> true or false
*
- * Returns <code>true</code> if <em>ios</em> is associated with a
- * terminal device (tty), <code>false</code> otherwise.
+ * Returns +true+ if the stream is associated with a terminal device (tty),
+ * +false+ otherwise:
+ *
+ * f = File.new('t.txt').isatty #=> false
+ * f.close
+ * f = File.new('/dev/tty').isatty #=> true
+ * f.close
+ *
+ * IO#tty? is an alias for IO#isatty.
*
- * File.new("testfile").isatty #=> false
- * File.new("/dev/tty").isatty #=> true
*/
static VALUE
@@ -4600,16 +5251,16 @@ rb_io_isatty(VALUE io)
#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
/*
* call-seq:
- * ios.close_on_exec? -> true or false
+ * close_on_exec? -> true or false
*
- * Returns <code>true</code> if <em>ios</em> will be closed on exec.
+ * Returns +true+ if the stream will be closed on exec, +false+ otherwise:
+ *
+ * f = File.open('t.txt')
+ * f.close_on_exec? # => true
+ * f.close_on_exec = false
+ * f.close_on_exec? # => false
+ * f.close
*
- * f = open("/dev/null")
- * f.close_on_exec? #=> false
- * f.close_on_exec = true
- * f.close_on_exec? #=> true
- * f.close_on_exec = false
- * f.close_on_exec? #=> false
*/
static VALUE
@@ -4642,7 +5293,7 @@ rb_io_close_on_exec_p(VALUE io)
#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
/*
* call-seq:
- * ios.close_on_exec = bool -> true or false
+ * self.close_on_exec = bool -> true or false
*
* Sets a close-on-exec flag.
*
@@ -4708,7 +5359,6 @@ finish_writeconv(rb_io_t *fptr, int noalloc)
if (!fptr->wbuf.ptr) {
unsigned char buf[1024];
- long r;
res = econv_destination_buffer_full;
while (res == econv_destination_buffer_full) {
@@ -4716,22 +5366,20 @@ finish_writeconv(rb_io_t *fptr, int noalloc)
de = buf + sizeof(buf);
res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
while (dp-ds) {
- retry:
- if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
- r = rb_write_internal2(fptr->fd, ds, dp-ds);
- else
- r = rb_write_internal(fptr->fd, ds, dp-ds);
- if (r == dp-ds)
- break;
- if (0 <= r) {
- ds += r;
+ size_t remaining = dp-ds;
+ long result = rb_io_write_memory(fptr, ds, remaining);
+
+ if (result > 0) {
+ ds += result;
+ if ((size_t)result == remaining) break;
}
- if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
+ else if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
if (fptr->fd < 0)
return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
- goto retry;
}
- return noalloc ? Qtrue : INT2NUM(errno);
+ else {
+ return noalloc ? Qtrue : INT2NUM(errno);
+ }
}
if (res == econv_invalid_byte_sequence ||
res == econv_incomplete_input ||
@@ -4746,8 +5394,9 @@ finish_writeconv(rb_io_t *fptr, int noalloc)
res = econv_destination_buffer_full;
while (res == econv_destination_buffer_full) {
if (fptr->wbuf.len == fptr->wbuf.capa) {
- if (io_fflush(fptr) < 0)
+ if (io_fflush(fptr) < 0) {
return noalloc ? Qtrue : INT2NUM(errno);
+ }
}
ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
@@ -4787,7 +5436,7 @@ static int
maygvl_close(int fd, int keepgvl)
{
if (keepgvl)
- return close(fd);
+ return close(fd);
/*
* close() may block for certain file types (NFS, SO_LINGER sockets,
@@ -4808,7 +5457,7 @@ static int
maygvl_fclose(FILE *file, int keepgvl)
{
if (keepgvl)
- return fclose(file);
+ return fclose(file);
return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
}
@@ -4818,72 +5467,92 @@ static void clear_codeconv(rb_io_t *fptr);
static void
fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
- struct list_head *busy)
+ struct ccan_list_head *busy)
{
- VALUE err = Qnil;
+ VALUE error = Qnil;
int fd = fptr->fd;
FILE *stdio_file = fptr->stdio_file;
int mode = fptr->mode;
if (fptr->writeconv) {
- if (fptr->write_lock && !noraise) {
+ if (!NIL_P(fptr->write_lock) && !noraise) {
struct finish_writeconv_arg arg;
arg.fptr = fptr;
arg.noalloc = noraise;
- err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
- }
- else {
- err = finish_writeconv(fptr, noraise);
- }
+ error = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
+ }
+ else {
+ error = finish_writeconv(fptr, noraise);
+ }
}
if (fptr->wbuf.len) {
- if (noraise) {
- io_flush_buffer_sync(fptr);
- }
- else {
- if (io_fflush(fptr) < 0 && NIL_P(err))
- err = INT2NUM(errno);
- }
+ if (noraise) {
+ io_flush_buffer_sync(fptr);
+ }
+ else {
+ if (io_fflush(fptr) < 0 && NIL_P(error)) {
+ error = INT2NUM(errno);
+ }
+ }
+ }
+
+ int done = 0;
+
+ if (IS_PREP_STDIO(fptr) || fd <= 2) {
+ // Need to keep FILE objects of stdin, stdout and stderr, so we are done:
+ done = 1;
}
fptr->fd = -1;
fptr->stdio_file = 0;
fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
- /*
- * ensure waiting_fd users do not hit EBADF, wait for them
- * to exit before we call close().
- */
+ // Ensure waiting_fd users do not hit EBADF.
if (busy) {
- do rb_thread_schedule(); while (!list_empty(busy));
- }
+ // Wait for them to exit before we call close().
+ do rb_thread_schedule(); while (!ccan_list_empty(busy));
+ }
+
+ // Disable for now.
+ // if (!done && fd >= 0) {
+ // VALUE scheduler = rb_fiber_scheduler_current();
+ // if (scheduler != Qnil) {
+ // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
+ // if (!UNDEF_P(result)) done = 1;
+ // }
+ // }
+
+ if (!done && stdio_file) {
+ // stdio_file is deallocated anyway even if fclose failed.
+ if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(error)) {
+ if (!noraise) {
+ error = INT2NUM(errno);
+ }
+ }
- if (IS_PREP_STDIO(fptr) || fd <= 2) {
- /* need to keep FILE objects of stdin, stdout and stderr */
+ done = 1;
}
- else if (stdio_file) {
- /* stdio_file is deallocated anyway
- * even if fclose failed. */
- if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
- if (!noraise) err = INT2NUM(errno);
- }
- else if (0 <= fd) {
- /* fptr->fd may be closed even if close fails.
- * POSIX doesn't specify it.
- * We assumes it is closed. */
- /**/
- keepgvl |= !(mode & FMODE_WRITABLE);
- keepgvl |= noraise;
- if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
- if (!noraise) err = INT2NUM(errno);
+ if (!done && fd >= 0) {
+ // fptr->fd may be closed even if close fails. POSIX doesn't specify it.
+ // We assumes it is closed.
+
+ keepgvl |= !(mode & FMODE_WRITABLE);
+ keepgvl |= noraise;
+ if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(error)) {
+ if (!noraise) {
+ error = INT2NUM(errno);
+ }
+ }
+
+ done = 1;
}
- if (!NIL_P(err) && !noraise) {
- if (RB_INTEGER_TYPE_P(err))
- rb_syserr_fail_path(NUM2INT(err), fptr->pathv);
- else
- rb_exc_raise(err);
+ if (!NIL_P(error) && !noraise) {
+ if (RB_INTEGER_TYPE_P(error))
+ rb_syserr_fail_path(NUM2INT(error), fptr->pathv);
+ else
+ rb_exc_raise(error);
}
}
@@ -4900,10 +5569,10 @@ static void
rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
{
if (fptr->finalize) {
- (*fptr->finalize)(fptr, noraise);
+ (*fptr->finalize)(fptr, noraise);
}
else {
- fptr_finalize(fptr, noraise);
+ fptr_finalize(fptr, noraise);
}
}
@@ -4952,7 +5621,7 @@ rb_io_fptr_finalize_internal(void *ptr)
fptr->pathv = Qnil;
if (0 <= fptr->fd)
rb_io_fptr_cleanup(fptr, TRUE);
- fptr->write_lock = 0;
+ fptr->write_lock = Qnil;
free_io_buffer(&fptr->rbuf);
free_io_buffer(&fptr->wbuf);
clear_codeconv(fptr);
@@ -4992,16 +5661,16 @@ rb_io_memsize(const rb_io_t *fptr)
# define KEEPGVL FALSE
#endif
-int rb_notify_fd_close(int fd, struct list_head *);
+int rb_notify_fd_close(int fd, struct ccan_list_head *);
static rb_io_t *
io_close_fptr(VALUE io)
{
rb_io_t *fptr;
VALUE write_io;
rb_io_t *write_fptr;
- struct list_head busy;
+ struct ccan_list_head busy;
- list_head_init(&busy);
+ ccan_list_head_init(&busy);
write_io = GetWriteIO(io);
if (io != write_io) {
write_fptr = RFILE(write_io)->fptr;
@@ -5043,17 +5712,34 @@ rb_io_close(VALUE io)
/*
* call-seq:
- * ios.close -> nil
+ * close -> nil
+ *
+ * Closes the stream for both reading and writing
+ * if open for either or both; returns +nil+.
+ * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
*
- * Closes <em>ios</em> and flushes any pending writes to the operating
- * system. The stream is unavailable for any further data operations;
- * an IOError is raised if such an attempt is made. I/O streams are
- * automatically closed when they are claimed by the garbage collector.
+ * If the stream is open for writing, flushes any buffered writes
+ * to the operating system before closing.
*
- * If <em>ios</em> is opened by IO.popen, #close sets
- * <code>$?</code>.
+ * If the stream was opened by IO.popen, sets global variable <tt>$?</tt>
+ * (child exit status).
*
- * Calling this method on closed IO object is just ignored since Ruby 2.3.
+ * Example:
+ *
+ * IO.popen('ruby', 'r+') do |pipe|
+ * puts pipe.closed?
+ * pipe.close
+ * puts $?
+ * puts pipe.closed?
+ * end
+ *
+ * Output:
+ *
+ * false
+ * pid 13760 exit 0
+ * true
+ *
+ * Related: IO#close_read, IO#close_write, IO#closed?.
*/
static VALUE
@@ -5080,9 +5766,9 @@ ignore_closed_stream(VALUE io, VALUE exc)
enum {mesg_len = sizeof(closed_stream)-1};
VALUE mesg = rb_attr_get(exc, idMesg);
if (!RB_TYPE_P(mesg, T_STRING) ||
- RSTRING_LEN(mesg) != mesg_len ||
- memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
- rb_exc_raise(exc);
+ RSTRING_LEN(mesg) != mesg_len ||
+ memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
+ rb_exc_raise(exc);
}
return io;
}
@@ -5091,28 +5777,35 @@ static VALUE
io_close(VALUE io)
{
VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
- if (closed != Qundef && RTEST(closed)) return io;
+ if (!UNDEF_P(closed) && RTEST(closed)) return io;
rb_rescue2(io_call_close, io, ignore_closed_stream, io,
- rb_eIOError, (VALUE)0);
+ rb_eIOError, (VALUE)0);
return io;
}
/*
* call-seq:
- * ios.closed? -> true or false
+ * closed? -> true or false
*
- * Returns <code>true</code> if <em>ios</em> is completely closed (for
- * duplex streams, both reader and writer), <code>false</code>
- * otherwise.
+ * Returns +true+ if the stream is closed for both reading and writing,
+ * +false+ otherwise.
+ * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
*
- * f = File.new("testfile")
- * f.close #=> nil
- * f.closed? #=> true
- * f = IO.popen("/bin/sh","r+")
- * f.close_write #=> nil
- * f.closed? #=> false
- * f.close_read #=> nil
- * f.closed? #=> true
+ * IO.popen('ruby', 'r+') do |pipe|
+ * puts pipe.closed?
+ * pipe.close_read
+ * puts pipe.closed?
+ * pipe.close_write
+ * puts pipe.closed?
+ * end
+ *
+ * Output:
+ *
+ * false
+ * false
+ * true
+ *
+ * Related: IO#close_read, IO#close_write, IO#close.
*/
@@ -5137,22 +5830,34 @@ rb_io_closed(VALUE io)
/*
* call-seq:
- * ios.close_read -> nil
+ * close_read -> nil
*
- * Closes the read end of a duplex I/O stream (i.e., one that contains
- * both a read and a write stream, such as a pipe). Will raise an
- * IOError if the stream is not duplexed.
+ * Closes the stream for reading if open for reading;
+ * returns +nil+.
+ * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
*
- * f = IO.popen("/bin/sh","r+")
- * f.close_read
- * f.readlines
+ * If the stream was opened by IO.popen and is also closed for writing,
+ * sets global variable <tt>$?</tt> (child exit status).
*
- * <em>produces:</em>
+ * Example:
+ *
+ * IO.popen('ruby', 'r+') do |pipe|
+ * puts pipe.closed?
+ * pipe.close_write
+ * puts pipe.closed?
+ * pipe.close_read
+ * puts $?
+ * puts pipe.closed?
+ * end
+ *
+ * Output:
*
- * prog.rb:3:in `readlines': not opened for reading (IOError)
- * from prog.rb:3
+ * false
+ * false
+ * pid 14748 exit 0
+ * true
*
- * Calling this method on closed IO object is just ignored since Ruby 2.3.
+ * Related: IO#close, IO#close_write, IO#closed?.
*/
static VALUE
@@ -5177,44 +5882,55 @@ rb_io_close_read(VALUE io)
write_io = GetWriteIO(io);
if (io != write_io) {
- rb_io_t *wfptr;
- wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
- wfptr->pid = fptr->pid;
- fptr->pid = 0;
+ rb_io_t *wfptr;
+ wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
+ wfptr->pid = fptr->pid;
+ fptr->pid = 0;
RFILE(io)->fptr = wfptr;
- /* bind to write_io temporarily to get rid of memory/fd leak */
- fptr->tied_io_for_writing = 0;
- RFILE(write_io)->fptr = fptr;
- rb_io_fptr_cleanup(fptr, FALSE);
- /* should not finalize fptr because another thread may be reading it */
+ /* bind to write_io temporarily to get rid of memory/fd leak */
+ fptr->tied_io_for_writing = 0;
+ RFILE(write_io)->fptr = fptr;
+ rb_io_fptr_cleanup(fptr, FALSE);
+ /* should not finalize fptr because another thread may be reading it */
return Qnil;
}
if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
- rb_raise(rb_eIOError, "closing non-duplex IO for reading");
+ rb_raise(rb_eIOError, "closing non-duplex IO for reading");
}
return rb_io_close(io);
}
/*
* call-seq:
- * ios.close_write -> nil
+ * close_write -> nil
*
- * Closes the write end of a duplex I/O stream (i.e., one that contains
- * both a read and a write stream, such as a pipe). Will raise an
- * IOError if the stream is not duplexed.
+ * Closes the stream for writing if open for writing;
+ * returns +nil+.
+ * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
*
- * f = IO.popen("/bin/sh","r+")
- * f.close_write
- * f.print "nowhere"
+ * Flushes any buffered writes to the operating system before closing.
*
- * <em>produces:</em>
+ * If the stream was opened by IO.popen and is also closed for reading,
+ * sets global variable <tt>$?</tt> (child exit status).
+ *
+ * IO.popen('ruby', 'r+') do |pipe|
+ * puts pipe.closed?
+ * pipe.close_read
+ * puts pipe.closed?
+ * pipe.close_write
+ * puts $?
+ * puts pipe.closed?
+ * end
+ *
+ * Output:
*
- * prog.rb:3:in `write': not opened for writing (IOError)
- * from prog.rb:3:in `print'
- * from prog.rb:3
+ * false
+ * false
+ * pid 15044 exit 0
+ * true
*
- * Calling this method on closed IO object is just ignored since Ruby 2.3.
+ * Related: IO#close, IO#close_read, IO#closed?.
*/
static VALUE
@@ -5234,17 +5950,17 @@ rb_io_close_write(VALUE io)
rb_sys_fail_path(fptr->pathv);
fptr->mode &= ~FMODE_WRITABLE;
if (!(fptr->mode & FMODE_READABLE))
- return rb_io_close(write_io);
+ return rb_io_close(write_io);
return Qnil;
}
if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
- rb_raise(rb_eIOError, "closing non-duplex IO for writing");
+ rb_raise(rb_eIOError, "closing non-duplex IO for writing");
}
if (io != write_io) {
- fptr = rb_io_get_fptr(rb_io_taint_check(io));
- fptr->tied_io_for_writing = 0;
+ fptr = rb_io_get_fptr(rb_io_taint_check(io));
+ fptr->tied_io_for_writing = 0;
}
rb_io_close(write_io);
return Qnil;
@@ -5252,15 +5968,13 @@ rb_io_close_write(VALUE io)
/*
* call-seq:
- * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
+ * sysseek(offset, whence = IO::SEEK_SET) -> integer
*
- * Seeks to a given <i>offset</i> in the stream according to the value
- * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
- * the new offset into the file.
+ * Behaves like IO#seek, except that it:
+ *
+ * - Uses low-level system functions.
+ * - Returns the new position.
*
- * f = File.new("testfile")
- * f.sysseek(-13, IO::SEEK_END) #=> 53
- * f.sysread(10) #=> "And so on."
*/
static VALUE
@@ -5269,19 +5983,19 @@ rb_io_sysseek(int argc, VALUE *argv, VALUE io)
VALUE offset, ptrname;
int whence = SEEK_SET;
rb_io_t *fptr;
- off_t pos;
+ rb_off_t pos;
if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
- whence = interpret_seek_whence(ptrname);
+ whence = interpret_seek_whence(ptrname);
}
pos = NUM2OFFT(offset);
GetOpenFile(io, fptr);
if ((fptr->mode & FMODE_READABLE) &&
(READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
- rb_raise(rb_eIOError, "sysseek for buffered IO");
+ rb_raise(rb_eIOError, "sysseek for buffered IO");
}
if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
- rb_warn("sysseek for buffered IO");
+ rb_warn("sysseek for buffered IO");
}
errno = 0;
pos = lseek(fptr->fd, pos, whence);
@@ -5292,15 +6006,20 @@ rb_io_sysseek(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * ios.syswrite(string) -> integer
+ * syswrite(object) -> integer
+ *
+ * Writes the given +object+ to self, which must be opened for writing (see Modes);
+ * returns the number bytes written.
+ * If +object+ is not a string is converted via method to_s:
*
- * Writes the given string to <em>ios</em> using a low-level write.
- * Returns the number of bytes written. Do not mix with other methods
- * that write to <em>ios</em> or you may get unpredictable results.
- * Raises SystemCallError on error.
+ * f = File.new('t.tmp', 'w')
+ * f.syswrite('foo') # => 3
+ * f.syswrite(30) # => 2
+ * f.syswrite(:foo) # => 3
+ * f.close
+ *
+ * This methods should not be used with other stream-writer methods.
*
- * f = File.new("out", "w")
- * f.syswrite("ABCDEF") #=> 6
*/
static VALUE
@@ -5312,19 +6031,19 @@ rb_io_syswrite(VALUE io, VALUE str)
const char *ptr;
if (!RB_TYPE_P(str, T_STRING))
- str = rb_obj_as_string(str);
+ str = rb_obj_as_string(str);
io = GetWriteIO(io);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
if (fptr->wbuf.len) {
- rb_warn("syswrite for buffered IO");
+ rb_warn("syswrite for buffered IO");
}
tmp = rb_str_tmp_frozen_acquire(str);
RSTRING_GETMEM(tmp, ptr, len);
- n = rb_write_internal(fptr->fd, ptr, len);
+ n = rb_io_write_memory(fptr, ptr, len);
if (n < 0) rb_sys_fail_path(fptr->pathv);
rb_str_tmp_frozen_release(str, tmp);
@@ -5333,21 +6052,13 @@ rb_io_syswrite(VALUE io, VALUE str)
/*
* call-seq:
- * ios.sysread(maxlen[, outbuf]) -> string
+ * sysread(maxlen) -> string
+ * sysread(maxlen, out_string) -> string
*
- * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
- * read and returns them as a string. Do not mix with other methods
- * that read from <em>ios</em> or you may get unpredictable results.
+ * Behaves like IO#readpartial, except that it uses low-level system functions.
*
- * If the optional _outbuf_ argument is present,
- * it must reference a String, which will receive the data.
- * The _outbuf_ will contain only the received data after the method call
- * even if it is not empty at the beginning.
+ * This method should not be used with other stream-reader methods.
*
- * Raises SystemCallError on error and EOFError at end of file.
- *
- * f = File.new("testfile")
- * f.sysread(16) #=> "This is line one"
*/
static VALUE
@@ -5376,11 +6087,13 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
io_setstrbuf(&str, ilen);
iis.th = rb_thread_current();
- iis.fd = fptr->fd;
+ iis.fptr = fptr;
iis.nonblock = 0;
+ iis.fd = fptr->fd;
iis.buf = RSTRING_PTR(str);
iis.capa = ilen;
- n = read_internal_locktmp(str, &iis);
+ iis.timeout = NULL;
+ n = io_read_memory_locktmp(str, &iis);
if (n < 0) {
rb_sys_fail_path(fptr->pathv);
@@ -5400,7 +6113,7 @@ struct prdwr_internal_arg {
int fd;
void *buf;
size_t count;
- off_t offset;
+ rb_off_t offset;
};
#endif /* HAVE_PREAD || HAVE_PWRITE */
@@ -5421,25 +6134,31 @@ pread_internal_call(VALUE arg)
/*
* call-seq:
- * ios.pread(maxlen, offset[, outbuf]) -> string
+ * pread(maxlen, offset) -> string
+ * pread(maxlen, offset, out_string) -> string
*
- * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
- * and returns them as a string without modifying the underlying
- * descriptor offset. This is advantageous compared to combining IO#seek
- * and IO#read in that it is atomic, allowing multiple threads/process to
- * share the same IO object for reading the file at various locations.
- * This bypasses any userspace buffering of the IO layer.
- * If the optional <i>outbuf</i> argument is present, it must
- * reference a String, which will receive the data.
- * Raises SystemCallError on error, EOFError at end of file and
- * NotImplementedError if platform does not implement the system call.
+ * Behaves like IO#readpartial, except that it:
+ *
+ * - Reads at the given +offset+ (in bytes).
+ * - Disregards, and does not modify, the stream's position
+ * (see {Position}[rdoc-ref:IO@Position]).
+ * - Bypasses any user space buffering in the stream.
+ *
+ * Because this method does not disturb the stream's state
+ * (its position, in particular), +pread+ allows multiple threads and processes
+ * to use the same \IO object for reading at various offsets.
+ *
+ * f = File.open('t.txt')
+ * f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * f.pos # => 52
+ * # Read 12 bytes at offset 0.
+ * f.pread(12, 0) # => "First line\n"
+ * # Read 9 bytes at offset 8.
+ * f.pread(9, 8) # => "ne\nSecon"
+ * f.close
+ *
+ * Not available on some platforms.
*
- * File.write("testfile", "This is line one\nThis is line two\n")
- * File.open("testfile") do |f|
- * p f.read # => "This is line one\nThis is line two\n"
- * p f.pread(12, 0) # => "This is line"
- * p f.pread(9, 8) # => "line one\n"
- * end
*/
static VALUE
rb_io_pread(int argc, VALUE *argv, VALUE io)
@@ -5468,11 +6187,11 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
if (n < 0) {
- rb_sys_fail_path(fptr->pathv);
+ rb_sys_fail_path(fptr->pathv);
}
io_set_read_length(str, n, shrinkable);
if (n == 0 && arg.count > 0) {
- rb_eof_error();
+ rb_eof_error();
}
return str;
@@ -5492,22 +6211,28 @@ internal_pwrite_func(void *ptr)
/*
* call-seq:
- * ios.pwrite(string, offset) -> integer
+ * pwrite(object, offset) -> integer
*
- * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
- * system call. This is advantageous to combining IO#seek and IO#write
- * in that it is atomic, allowing multiple threads/process to share the
- * same IO object for reading the file at various locations.
- * This bypasses any userspace buffering of the IO layer.
- * Returns the number of bytes written.
- * Raises SystemCallError on error and NotImplementedError
- * if platform does not implement the system call.
+ * Behaves like IO#write, except that it:
*
- * File.open("out", "w") do |f|
- * f.pwrite("ABCDEF", 3) #=> 6
- * end
+ * - Writes at the given +offset+ (in bytes).
+ * - Disregards, and does not modify, the stream's position
+ * (see {Position}[rdoc-ref:IO@Position]).
+ * - Bypasses any user space buffering in the stream.
+ *
+ * Because this method does not disturb the stream's state
+ * (its position, in particular), +pwrite+ allows multiple threads and processes
+ * to use the same \IO object for writing at various offsets.
+ *
+ * f = File.open('t.tmp', 'w+')
+ * # Write 6 bytes at offset 3.
+ * f.pwrite('ABCDEF', 3) # => 6
+ * f.rewind
+ * f.read # => "\u0000\u0000\u0000ABCDEF"
+ * f.close
+ *
+ * Not available on some platforms.
*
- * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
*/
static VALUE
rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
@@ -5518,7 +6243,7 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
VALUE tmp;
if (!RB_TYPE_P(str, T_STRING))
- str = rb_obj_as_string(str);
+ str = rb_obj_as_string(str);
arg.offset = NUM2OFFT(offset);
@@ -5556,10 +6281,10 @@ rb_io_binmode(VALUE io)
fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
#ifdef O_BINARY
if (!fptr->readconv) {
- SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
+ SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
}
else {
- setmode(fptr->fd, O_BINARY);
+ setmode(fptr->fd, O_BINARY);
}
#endif
return io;
@@ -5600,14 +6325,13 @@ rb_io_ascii8bit_binmode(VALUE io)
/*
* call-seq:
- * ios.binmode -> ios
+ * binmode -> self
+ *
+ * Sets the stream's data mode as binary
+ * (see {Data Mode}[rdoc-ref:File@Data+Mode]).
*
- * Puts <em>ios</em> into binary mode.
- * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
+ * A stream's data mode may not be changed from binary to text.
*
- * - newline conversion disabled
- * - encoding conversion disabled
- * - content is treated as ASCII-8BIT
*/
static VALUE
@@ -5625,9 +6349,11 @@ rb_io_binmode_m(VALUE io)
/*
* call-seq:
- * ios.binmode? -> true or false
+ * binmode? -> true or false
+ *
+ * Returns +true+ if the stream is on binary mode, +false+ otherwise.
+ * See {Data Mode}[rdoc-ref:File@Data+Mode].
*
- * Returns <code>true</code> if <em>ios</em> is binmode.
*/
static VALUE
rb_io_binmode_p(VALUE io)
@@ -5641,23 +6367,23 @@ static const char*
rb_io_fmode_modestr(int fmode)
{
if (fmode & FMODE_APPEND) {
- if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
- return MODE_BTMODE("a+", "ab+", "at+");
- }
- return MODE_BTMODE("a", "ab", "at");
+ if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
+ return MODE_BTMODE("a+", "ab+", "at+");
+ }
+ return MODE_BTMODE("a", "ab", "at");
}
switch (fmode & FMODE_READWRITE) {
default:
- rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
+ rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
case FMODE_READABLE:
- return MODE_BTMODE("r", "rb", "rt");
+ return MODE_BTMODE("r", "rb", "rt");
case FMODE_WRITABLE:
- return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
+ return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
case FMODE_READWRITE:
- if (fmode & FMODE_CREATE) {
+ if (fmode & FMODE_CREATE) {
return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
- }
- return MODE_BTMODE("r+", "rb+", "rt+");
+ }
+ return MODE_BTMODE("r+", "rb+", "rt+");
}
}
@@ -5680,27 +6406,27 @@ rb_io_modestr_fmode(const char *modestr)
switch (*m++) {
case 'r':
- fmode |= FMODE_READABLE;
- break;
+ fmode |= FMODE_READABLE;
+ break;
case 'w':
- fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
- break;
+ fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
+ break;
case 'a':
- fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
- break;
+ fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
+ break;
default:
goto error;
}
while (*m) {
switch (*m++) {
- case 'b':
+ case 'b':
fmode |= FMODE_BINMODE;
break;
- case 't':
+ case 't':
fmode |= FMODE_TEXTMODE;
break;
- case '+':
+ case '+':
fmode |= FMODE_READWRITE;
break;
case 'x':
@@ -5708,12 +6434,12 @@ rb_io_modestr_fmode(const char *modestr)
goto error;
fmode |= FMODE_EXCL;
break;
- default:
+ default:
goto error;
- case ':':
- p = strchr(m, ':');
- if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
- fmode |= FMODE_SETENC_BY_BOM;
+ case ':':
+ p = strchr(m, ':');
+ if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
+ fmode |= FMODE_SETENC_BY_BOM;
goto finished;
}
}
@@ -5736,31 +6462,31 @@ rb_io_oflags_fmode(int oflags)
switch (oflags & O_ACCMODE) {
case O_RDONLY:
- fmode = FMODE_READABLE;
- break;
+ fmode = FMODE_READABLE;
+ break;
case O_WRONLY:
- fmode = FMODE_WRITABLE;
- break;
+ fmode = FMODE_WRITABLE;
+ break;
case O_RDWR:
- fmode = FMODE_READWRITE;
- break;
+ fmode = FMODE_READWRITE;
+ break;
}
if (oflags & O_APPEND) {
- fmode |= FMODE_APPEND;
+ fmode |= FMODE_APPEND;
}
if (oflags & O_TRUNC) {
- fmode |= FMODE_TRUNC;
+ fmode |= FMODE_TRUNC;
}
if (oflags & O_CREAT) {
- fmode |= FMODE_CREATE;
+ fmode |= FMODE_CREATE;
}
if (oflags & O_EXCL) {
fmode |= FMODE_EXCL;
}
#ifdef O_BINARY
if (oflags & O_BINARY) {
- fmode |= FMODE_BINMODE;
+ fmode |= FMODE_BINMODE;
}
#endif
@@ -5825,25 +6551,25 @@ rb_io_oflags_modestr(int oflags)
}
accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
if (oflags & O_APPEND) {
- if (accmode == O_WRONLY) {
- return MODE_BINARY("a", "ab");
- }
- if (accmode == O_RDWR) {
- return MODE_BINARY("a+", "ab+");
- }
+ if (accmode == O_WRONLY) {
+ return MODE_BINARY("a", "ab");
+ }
+ if (accmode == O_RDWR) {
+ return MODE_BINARY("a+", "ab+");
+ }
}
switch (accmode) {
default:
- rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
+ rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
case O_RDONLY:
- return MODE_BINARY("r", "rb");
+ return MODE_BINARY("r", "rb");
case O_WRONLY:
- return MODE_BINARY("w", "wb");
+ return MODE_BINARY("w", "wb");
case O_RDWR:
- if (oflags & O_TRUNC) {
- return MODE_BINARY("w+", "wb+");
- }
- return MODE_BINARY("r+", "rb+");
+ if (oflags & O_TRUNC) {
+ return MODE_BINARY("w+", "wb+");
+ }
+ return MODE_BINARY("r+", "rb+");
}
}
@@ -5858,25 +6584,25 @@ rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc,
int default_ext = 0;
if (ext == NULL) {
- ext = rb_default_external_encoding();
- default_ext = 1;
+ ext = rb_default_external_encoding();
+ default_ext = 1;
}
- if (ext == rb_ascii8bit_encoding()) {
- /* If external is ASCII-8BIT, no transcoding */
- intern = NULL;
+ if (rb_is_ascii8bit_enc(ext)) {
+ /* If external is ASCII-8BIT, no transcoding */
+ intern = NULL;
}
else if (intern == NULL) {
- intern = rb_default_internal_encoding();
+ intern = rb_default_internal_encoding();
}
if (intern == NULL || intern == (rb_encoding *)Qnil ||
- (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
- /* No internal encoding => use external + no transcoding */
- *enc = (default_ext && intern != ext) ? NULL : ext;
- *enc2 = NULL;
+ (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
+ /* No internal encoding => use external + no transcoding */
+ *enc = (default_ext && intern != ext) ? NULL : ext;
+ *enc2 = NULL;
}
else {
- *enc = intern;
- *enc2 = ext;
+ *enc = intern;
+ *enc2 = ext;
}
}
@@ -5888,7 +6614,7 @@ unsupported_encoding(const char *name, rb_encoding *enc)
static void
parse_mode_enc(const char *estr, rb_encoding *estr_enc,
- rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
+ rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
{
const char *p;
char encname[ENCODING_MAXNAMELEN+1];
@@ -5902,53 +6628,53 @@ parse_mode_enc(const char *estr, rb_encoding *estr_enc,
p = strrchr(estr, ':');
len = p ? (p++ - estr) : (long)strlen(estr);
if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
- estr += bom_prefix_len;
- len -= bom_prefix_len;
- if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
- fmode |= FMODE_SETENC_BY_BOM;
- }
- else {
- rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
- fmode &= ~FMODE_SETENC_BY_BOM;
- }
+ estr += bom_prefix_len;
+ len -= bom_prefix_len;
+ if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
+ fmode |= FMODE_SETENC_BY_BOM;
+ }
+ else {
+ rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
+ fmode &= ~FMODE_SETENC_BY_BOM;
+ }
}
if (len == 0 || len > ENCODING_MAXNAMELEN) {
- idx = -1;
+ idx = -1;
}
else {
- if (p) {
- memcpy(encname, estr, len);
- encname[len] = '\0';
- estr = encname;
- }
- idx = rb_enc_find_index(estr);
+ if (p) {
+ memcpy(encname, estr, len);
+ encname[len] = '\0';
+ estr = encname;
+ }
+ idx = rb_enc_find_index(estr);
}
if (fmode_p) *fmode_p = fmode;
if (idx >= 0)
- ext_enc = rb_enc_from_index(idx);
+ ext_enc = rb_enc_from_index(idx);
else {
- if (idx != -2)
- unsupported_encoding(estr, estr_enc);
- ext_enc = NULL;
+ if (idx != -2)
+ unsupported_encoding(estr, estr_enc);
+ ext_enc = NULL;
}
int_enc = NULL;
if (p) {
- if (*p == '-' && *(p+1) == '\0') {
- /* Special case - "-" => no transcoding */
- int_enc = (rb_encoding *)Qnil;
- }
- else {
- idx2 = rb_enc_find_index(p);
- if (idx2 < 0)
- unsupported_encoding(p, estr_enc);
- else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
- int_enc = (rb_encoding *)Qnil;
- }
- else
- int_enc = rb_enc_from_index(idx2);
- }
+ if (*p == '-' && *(p+1) == '\0') {
+ /* Special case - "-" => no transcoding */
+ int_enc = (rb_encoding *)Qnil;
+ }
+ else {
+ idx2 = rb_enc_find_index(p);
+ if (idx2 < 0)
+ unsupported_encoding(p, estr_enc);
+ else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
+ int_enc = (rb_encoding *)Qnil;
+ }
+ else
+ int_enc = rb_enc_from_index(idx2);
+ }
}
rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
@@ -5963,62 +6689,62 @@ rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2
rb_encoding *intencoding = NULL;
if (!NIL_P(opt)) {
- VALUE v;
- v = rb_hash_lookup2(opt, sym_encoding, Qnil);
- if (v != Qnil) encoding = v;
- v = rb_hash_lookup2(opt, sym_extenc, Qundef);
- if (v != Qnil) extenc = v;
- v = rb_hash_lookup2(opt, sym_intenc, Qundef);
- if (v != Qundef) intenc = v;
- }
- if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
- if (!NIL_P(ruby_verbose)) {
- int idx = rb_to_encoding_index(encoding);
- if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
- rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
- encoding, extenc == Qundef ? "internal" : "external");
- }
- encoding = Qnil;
- }
- if (extenc != Qundef && !NIL_P(extenc)) {
- extencoding = rb_to_encoding(extenc);
- }
- if (intenc != Qundef) {
- if (NIL_P(intenc)) {
- /* internal_encoding: nil => no transcoding */
- intencoding = (rb_encoding *)Qnil;
- }
- else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
- char *p = StringValueCStr(tmp);
-
- if (*p == '-' && *(p+1) == '\0') {
- /* Special case - "-" => no transcoding */
- intencoding = (rb_encoding *)Qnil;
- }
- else {
- intencoding = rb_to_encoding(intenc);
- }
- }
- else {
- intencoding = rb_to_encoding(intenc);
- }
- if (extencoding == intencoding) {
- intencoding = (rb_encoding *)Qnil;
- }
+ VALUE v;
+ v = rb_hash_lookup2(opt, sym_encoding, Qnil);
+ if (v != Qnil) encoding = v;
+ v = rb_hash_lookup2(opt, sym_extenc, Qundef);
+ if (v != Qnil) extenc = v;
+ v = rb_hash_lookup2(opt, sym_intenc, Qundef);
+ if (!UNDEF_P(v)) intenc = v;
+ }
+ if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !NIL_P(encoding)) {
+ if (!NIL_P(ruby_verbose)) {
+ int idx = rb_to_encoding_index(encoding);
+ if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
+ rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
+ encoding, UNDEF_P(extenc) ? "internal" : "external");
+ }
+ encoding = Qnil;
+ }
+ if (!UNDEF_P(extenc) && !NIL_P(extenc)) {
+ extencoding = rb_to_encoding(extenc);
+ }
+ if (!UNDEF_P(intenc)) {
+ if (NIL_P(intenc)) {
+ /* internal_encoding: nil => no transcoding */
+ intencoding = (rb_encoding *)Qnil;
+ }
+ else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
+ char *p = StringValueCStr(tmp);
+
+ if (*p == '-' && *(p+1) == '\0') {
+ /* Special case - "-" => no transcoding */
+ intencoding = (rb_encoding *)Qnil;
+ }
+ else {
+ intencoding = rb_to_encoding(intenc);
+ }
+ }
+ else {
+ intencoding = rb_to_encoding(intenc);
+ }
+ if (extencoding == intencoding) {
+ intencoding = (rb_encoding *)Qnil;
+ }
}
if (!NIL_P(encoding)) {
- extracted = 1;
- if (!NIL_P(tmp = rb_check_string_type(encoding))) {
- parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
- enc_p, enc2_p, fmode_p);
- }
- else {
- rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
- }
- }
- else if (extenc != Qundef || intenc != Qundef) {
extracted = 1;
- rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
+ if (!NIL_P(tmp = rb_check_string_type(encoding))) {
+ parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
+ enc_p, enc2_p, fmode_p);
+ }
+ else {
+ rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
+ }
+ }
+ else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
+ extracted = 1;
+ rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
}
return extracted;
}
@@ -6037,17 +6763,17 @@ validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *e
rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
- rb_raise(rb_eArgError, "newline decorator with binary mode");
+ rb_raise(rb_eArgError, "newline decorator with binary mode");
}
if (!(fmode & FMODE_BINMODE) &&
- (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
- fmode |= FMODE_TEXTMODE;
- *fmode_p = fmode;
+ (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
+ fmode |= FMODE_TEXTMODE;
+ *fmode_p = fmode;
}
#if !DEFAULT_TEXTMODE
else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
- fmode &= ~FMODE_TEXTMODE;
- *fmode_p = fmode;
+ fmode &= ~FMODE_TEXTMODE;
+ *fmode_p = fmode;
}
#endif
}
@@ -6056,28 +6782,28 @@ static void
extract_binmode(VALUE opthash, int *fmode)
{
if (!NIL_P(opthash)) {
- VALUE v;
- v = rb_hash_aref(opthash, sym_textmode);
- if (!NIL_P(v)) {
- if (*fmode & FMODE_TEXTMODE)
- rb_raise(rb_eArgError, "textmode specified twice");
- if (*fmode & FMODE_BINMODE)
- rb_raise(rb_eArgError, "both textmode and binmode specified");
- if (RTEST(v))
- *fmode |= FMODE_TEXTMODE;
- }
- v = rb_hash_aref(opthash, sym_binmode);
- if (!NIL_P(v)) {
- if (*fmode & FMODE_BINMODE)
- rb_raise(rb_eArgError, "binmode specified twice");
- if (*fmode & FMODE_TEXTMODE)
- rb_raise(rb_eArgError, "both textmode and binmode specified");
- if (RTEST(v))
- *fmode |= FMODE_BINMODE;
- }
-
- if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
- rb_raise(rb_eArgError, "both textmode and binmode specified");
+ VALUE v;
+ v = rb_hash_aref(opthash, sym_textmode);
+ if (!NIL_P(v)) {
+ if (*fmode & FMODE_TEXTMODE)
+ rb_raise(rb_eArgError, "textmode specified twice");
+ if (*fmode & FMODE_BINMODE)
+ rb_raise(rb_eArgError, "both textmode and binmode specified");
+ if (RTEST(v))
+ *fmode |= FMODE_TEXTMODE;
+ }
+ v = rb_hash_aref(opthash, sym_binmode);
+ if (!NIL_P(v)) {
+ if (*fmode & FMODE_BINMODE)
+ rb_raise(rb_eArgError, "binmode specified twice");
+ if (*fmode & FMODE_TEXTMODE)
+ rb_raise(rb_eArgError, "both textmode and binmode specified");
+ if (RTEST(v))
+ *fmode |= FMODE_BINMODE;
+ }
+
+ if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
+ rb_raise(rb_eArgError, "both textmode and binmode specified");
}
}
@@ -6120,24 +6846,24 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
has_enc = 1;
parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
}
- else {
- rb_encoding *e;
+ else {
+ rb_encoding *e;
- e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
- rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
- }
+ e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
+ rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
+ }
}
if (NIL_P(opthash)) {
- ecflags = (fmode & FMODE_READABLE) ?
- MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
- 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
+ ecflags = (fmode & FMODE_READABLE) ?
+ MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
+ 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
- ecflags |= (fmode & FMODE_WRITABLE) ?
- MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
- 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
+ ecflags |= (fmode & FMODE_WRITABLE) ?
+ MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
+ 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
#endif
- SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
ecopts = Qnil;
if (fmode & FMODE_BINMODE) {
#ifdef O_BINARY
@@ -6153,57 +6879,57 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
#endif
}
else {
- VALUE v;
- if (!has_vmode) {
- v = rb_hash_aref(opthash, sym_mode);
- if (!NIL_P(v)) {
- if (!NIL_P(vmode)) {
- rb_raise(rb_eArgError, "mode specified twice");
- }
- has_vmode = 1;
- vmode = v;
- goto vmode_handle;
- }
- }
- v = rb_hash_aref(opthash, sym_flags);
- if (!NIL_P(v)) {
- v = rb_to_int(v);
- oflags |= NUM2INT(v);
- vmode = INT2NUM(oflags);
- fmode = rb_io_oflags_fmode(oflags);
- }
- extract_binmode(opthash, &fmode);
- if (fmode & FMODE_BINMODE) {
+ VALUE v;
+ if (!has_vmode) {
+ v = rb_hash_aref(opthash, sym_mode);
+ if (!NIL_P(v)) {
+ if (!NIL_P(vmode)) {
+ rb_raise(rb_eArgError, "mode specified twice");
+ }
+ has_vmode = 1;
+ vmode = v;
+ goto vmode_handle;
+ }
+ }
+ v = rb_hash_aref(opthash, sym_flags);
+ if (!NIL_P(v)) {
+ v = rb_to_int(v);
+ oflags |= NUM2INT(v);
+ vmode = INT2NUM(oflags);
+ fmode = rb_io_oflags_fmode(oflags);
+ }
+ extract_binmode(opthash, &fmode);
+ 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 (!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
- v = rb_hash_aref(opthash, sym_perm);
- if (!NIL_P(v)) {
- if (vperm_p) {
- if (!NIL_P(*vperm_p)) {
- rb_raise(rb_eArgError, "perm specified twice");
- }
- *vperm_p = v;
- }
- else {
- /* perm no use, just ignore */
- }
- }
- ecflags = (fmode & FMODE_READABLE) ?
- MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
- 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
+ else if (NIL_P(vmode)) {
+ fmode |= DEFAULT_TEXTMODE;
+ }
+#endif
+ v = rb_hash_aref(opthash, sym_perm);
+ if (!NIL_P(v)) {
+ if (vperm_p) {
+ if (!NIL_P(*vperm_p)) {
+ rb_raise(rb_eArgError, "perm specified twice");
+ }
+ *vperm_p = v;
+ }
+ else {
+ /* perm no use, just ignore */
+ }
+ }
+ ecflags = (fmode & FMODE_READABLE) ?
+ MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
+ 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
- ecflags |= (fmode & FMODE_WRITABLE) ?
- MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
- 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
+ ecflags |= (fmode & FMODE_WRITABLE) ?
+ MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
+ 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
#endif
if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
@@ -6211,8 +6937,8 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
rb_raise(rb_eArgError, "encoding specified twice");
}
}
- SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
- ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
+ ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
}
validate_enc_binmode(&fmode, ecflags, enc, enc2);
@@ -6264,13 +6990,13 @@ rb_sysopen(VALUE fname, int oflags, mode_t perm)
fd = rb_sysopen_internal(&data);
if (fd < 0) {
- int e = errno;
- if (rb_gc_for_fd(e)) {
- fd = rb_sysopen_internal(&data);
- }
- if (fd < 0) {
- rb_syserr_fail_path(e, fname);
- }
+ int e = errno;
+ if (rb_gc_for_fd(e)) {
+ fd = rb_sysopen_internal(&data);
+ }
+ if (fd < 0) {
+ rb_syserr_fail_path(e, fname);
+ }
}
return fd;
}
@@ -6285,32 +7011,32 @@ rb_fdopen(int fd, const char *modestr)
#endif
file = fdopen(fd, modestr);
if (!file) {
- int e = errno;
+ int e = errno;
#if defined(__sun)
- if (e == 0) {
- rb_gc();
- errno = 0;
- file = fdopen(fd, modestr);
- }
- else
-#endif
- if (rb_gc_for_fd(e)) {
- file = fdopen(fd, modestr);
- }
- if (!file) {
+ if (e == 0) {
+ rb_gc();
+ errno = 0;
+ file = fdopen(fd, modestr);
+ }
+ else
+#endif
+ if (rb_gc_for_fd(e)) {
+ file = fdopen(fd, modestr);
+ }
+ if (!file) {
#ifdef _WIN32
- if (e == 0) e = EINVAL;
+ if (e == 0) e = EINVAL;
#elif defined(__sun)
- if (e == 0) e = EMFILE;
+ if (e == 0) e = EMFILE;
#endif
- rb_syserr_fail(e, 0);
- }
+ rb_syserr_fail(e, 0);
+ }
}
/* xxx: should be _IONBF? A buffer in FILE may have trouble. */
#ifdef USE_SETVBUF
if (setvbuf(file, NULL, _IOFBF, 0) != 0)
- rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
+ rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
#endif
return file;
}
@@ -6338,53 +7064,53 @@ io_strip_bom(VALUE io)
if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
switch (b1) {
case INT2FIX(0xEF):
- if (NIL_P(b2 = rb_io_getbyte(io))) break;
- if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
- if (b3 == INT2FIX(0xBF)) {
- return rb_utf8_encindex();
- }
- rb_io_ungetbyte(io, b3);
- }
- rb_io_ungetbyte(io, b2);
- break;
+ if (NIL_P(b2 = rb_io_getbyte(io))) break;
+ if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
+ if (b3 == INT2FIX(0xBF)) {
+ return rb_utf8_encindex();
+ }
+ rb_io_ungetbyte(io, b3);
+ }
+ rb_io_ungetbyte(io, b2);
+ break;
case INT2FIX(0xFE):
- if (NIL_P(b2 = rb_io_getbyte(io))) break;
- if (b2 == INT2FIX(0xFF)) {
- return ENCINDEX_UTF_16BE;
- }
- rb_io_ungetbyte(io, b2);
- break;
+ if (NIL_P(b2 = rb_io_getbyte(io))) break;
+ if (b2 == INT2FIX(0xFF)) {
+ return ENCINDEX_UTF_16BE;
+ }
+ rb_io_ungetbyte(io, b2);
+ break;
case INT2FIX(0xFF):
- if (NIL_P(b2 = rb_io_getbyte(io))) break;
- if (b2 == INT2FIX(0xFE)) {
- b3 = rb_io_getbyte(io);
- if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
- if (b4 == INT2FIX(0)) {
- return ENCINDEX_UTF_32LE;
- }
- rb_io_ungetbyte(io, b4);
- }
+ if (NIL_P(b2 = rb_io_getbyte(io))) break;
+ if (b2 == INT2FIX(0xFE)) {
+ b3 = rb_io_getbyte(io);
+ if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
+ if (b4 == INT2FIX(0)) {
+ return ENCINDEX_UTF_32LE;
+ }
+ rb_io_ungetbyte(io, b4);
+ }
rb_io_ungetbyte(io, b3);
return ENCINDEX_UTF_16LE;
- }
- rb_io_ungetbyte(io, b2);
- break;
+ }
+ rb_io_ungetbyte(io, b2);
+ break;
case INT2FIX(0):
- if (NIL_P(b2 = rb_io_getbyte(io))) break;
- if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
- if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
- if (b4 == INT2FIX(0xFF)) {
- return ENCINDEX_UTF_32BE;
- }
- rb_io_ungetbyte(io, b4);
- }
- rb_io_ungetbyte(io, b3);
- }
- rb_io_ungetbyte(io, b2);
- break;
+ if (NIL_P(b2 = rb_io_getbyte(io))) break;
+ if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
+ if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
+ if (b4 == INT2FIX(0xFF)) {
+ return ENCINDEX_UTF_32BE;
+ }
+ rb_io_ungetbyte(io, b4);
+ }
+ rb_io_ungetbyte(io, b3);
+ }
+ rb_io_ungetbyte(io, b2);
+ break;
}
rb_io_ungetbyte(io, b1);
return 0;
@@ -6404,27 +7130,27 @@ io_set_encoding_by_bom(VALUE io)
rb_io_internal_encoding(io), Qnil);
}
else {
- fptr->encs.enc2 = NULL;
+ fptr->encs.enc2 = NULL;
}
return extenc;
}
static VALUE
rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
- const convconfig_t *convconfig, mode_t perm)
+ const convconfig_t *convconfig, mode_t perm)
{
VALUE pathv;
rb_io_t *fptr;
convconfig_t cc;
if (!convconfig) {
- /* Set to default encodings */
- rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
+ /* Set to default encodings */
+ rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
cc.ecflags = 0;
cc.ecopts = Qnil;
convconfig = &cc;
}
validate_enc_binmode(&fmode, convconfig->ecflags,
- convconfig->enc, convconfig->enc2);
+ convconfig->enc, convconfig->enc2);
MakeOpenFile(io, fptr);
fptr->mode = fmode;
@@ -6453,16 +7179,16 @@ rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
if (p) {
parse_mode_enc(p+1, rb_usascii_encoding(),
- &convconfig.enc, &convconfig.enc2, &fmode);
+ &convconfig.enc, &convconfig.enc2, &fmode);
convconfig.ecflags = 0;
convconfig.ecopts = Qnil;
}
else {
- rb_encoding *e;
- /* Set to default encodings */
+ rb_encoding *e;
+ /* Set to default encodings */
- e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
- rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
+ e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
+ rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
convconfig.ecflags = 0;
convconfig.ecopts = Qnil;
}
@@ -6511,12 +7237,12 @@ pipe_del_fptr(rb_io_t *fptr)
struct pipe_list *tmp;
while ((tmp = *prev) != 0) {
- if (tmp->fptr == fptr) {
- *prev = tmp->next;
- free(tmp);
- return;
- }
- prev = &tmp->next;
+ if (tmp->fptr == fptr) {
+ *prev = tmp->next;
+ free(tmp);
+ return;
+ }
+ prev = &tmp->next;
}
}
@@ -6528,9 +7254,9 @@ pipe_atexit(void)
struct pipe_list *tmp;
while (list) {
- tmp = list->next;
- rb_io_fptr_finalize(list->fptr);
- list = tmp;
+ tmp = list->next;
+ rb_io_fptr_finalize(list->fptr);
+ list = tmp;
}
}
#endif
@@ -6566,14 +7292,14 @@ fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
if (old_finalize != pipe_finalize) {
- struct pipe_list *list;
- for (list = pipe_list; list; list = list->next) {
- if (list->fptr == fptr) break;
- }
- if (!list) pipe_add_fptr(fptr);
+ struct pipe_list *list;
+ for (list = pipe_list; list; list = list->next) {
+ if (list->fptr == fptr) break;
+ }
+ if (!list) pipe_add_fptr(fptr);
}
else {
- pipe_del_fptr(fptr);
+ pipe_del_fptr(fptr);
}
#endif
}
@@ -6625,6 +7351,7 @@ struct popen_arg {
#endif
#ifdef HAVE_WORKING_FORK
+# ifndef __EMSCRIPTEN__
static void
popen_redirect(struct popen_arg *p)
{
@@ -6655,6 +7382,7 @@ popen_redirect(struct popen_arg *p)
}
}
}
+# endif
#if defined(__linux__)
/* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
@@ -6722,19 +7450,20 @@ rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
if (!NIL_P(noclose_fds) &&
RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
continue;
- ret = fcntl(fd, F_GETFD); /* async-signal-safe */
- if (ret != -1 && !(ret & FD_CLOEXEC)) {
+ ret = fcntl(fd, F_GETFD); /* async-signal-safe */
+ if (ret != -1 && !(ret & FD_CLOEXEC)) {
fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
}
# define CONTIGUOUS_CLOSED_FDS 20
if (ret != -1) {
- if (max < fd + CONTIGUOUS_CLOSED_FDS)
- max = fd + CONTIGUOUS_CLOSED_FDS;
- }
+ if (max < fd + CONTIGUOUS_CLOSED_FDS)
+ max = fd + CONTIGUOUS_CLOSED_FDS;
+ }
}
#endif
}
+# ifndef __EMSCRIPTEN__
static int
popen_exec(void *pp, char *errmsg, size_t errmsg_len)
{
@@ -6742,9 +7471,10 @@ popen_exec(void *pp, char *errmsg, size_t errmsg_len)
return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
}
+# endif
#endif
-#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
+#if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
static VALUE
rb_execarg_fixup_v(VALUE execarg_obj)
{
@@ -6758,7 +7488,7 @@ char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
#ifndef __EMSCRIPTEN__
static VALUE
pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
- const convconfig_t *convconfig)
+ const convconfig_t *convconfig)
{
struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
@@ -6779,12 +7509,12 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
#if defined(HAVE_SPAWNV)
# if defined(HAVE_SPAWNVE)
# define DO_SPAWN(cmd, args, envp) ((args) ? \
- spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
- spawne(P_NOWAIT, (cmd), (envp)))
+ spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
+ spawne(P_NOWAIT, (cmd), (envp)))
# else
# define DO_SPAWN(cmd, args, envp) ((args) ? \
- spawnv(P_NOWAIT, (cmd), (args)) : \
- spawn(P_NOWAIT, (cmd)))
+ spawnv(P_NOWAIT, (cmd), (args)) : \
+ spawn(P_NOWAIT, (cmd)))
# endif
# if !defined(HAVE_WORKING_FORK)
char **args = NULL;
@@ -6831,19 +7561,19 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
}
- break;
+ break;
case FMODE_READABLE:
if (rb_pipe(arg.pair) < 0)
rb_sys_fail_str(prog);
if (eargp)
rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
- break;
+ break;
case FMODE_WRITABLE:
if (rb_pipe(arg.pair) < 0)
rb_sys_fail_str(prog);
if (eargp)
rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
- break;
+ break;
default:
rb_sys_fail_str(prog);
}
@@ -6859,59 +7589,59 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
}
# if defined(HAVE_WORKING_FORK)
- pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
+ pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
# else
- rb_execarg_run_options(eargp, sargp, NULL, 0);
+ rb_execarg_run_options(eargp, sargp, NULL, 0);
# if defined(HAVE_SPAWNVE)
- if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
+ if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
# endif
while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
- /* exec failed */
- switch (e = errno) {
- case EAGAIN:
-# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
+ /* exec failed */
+ switch (e = errno) {
+ case EAGAIN:
+# if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
# endif
- rb_thread_sleep(1);
- continue;
- }
- break;
- }
- if (eargp)
- rb_execarg_run_options(sargp, NULL, NULL, 0);
+ rb_thread_sleep(1);
+ continue;
+ }
+ break;
+ }
+ if (eargp)
+ rb_execarg_run_options(sargp, NULL, NULL, 0);
# endif
rb_execarg_parent_end(execarg_obj);
}
else {
# if defined(HAVE_WORKING_FORK)
- pid = rb_fork_ruby(&status);
- if (pid == 0) { /* child */
- popen_redirect(&arg);
- rb_io_synchronized(RFILE(orig_stdout)->fptr);
- rb_io_synchronized(RFILE(orig_stderr)->fptr);
- return Qnil;
- }
+ pid = rb_call_proc__fork();
+ if (pid == 0) { /* child */
+ popen_redirect(&arg);
+ rb_io_synchronized(RFILE(orig_stdout)->fptr);
+ rb_io_synchronized(RFILE(orig_stderr)->fptr);
+ return Qnil;
+ }
# else
- rb_notimplement();
+ rb_notimplement();
# endif
}
/* parent */
if (pid < 0) {
# if defined(HAVE_WORKING_FORK)
- e = errno;
+ e = errno;
# endif
- close(arg.pair[0]);
- close(arg.pair[1]);
+ close(arg.pair[0]);
+ close(arg.pair[1]);
if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
close(arg.write_pair[0]);
close(arg.write_pair[1]);
}
# if defined(HAVE_WORKING_FORK)
if (errmsg[0])
- rb_syserr_fail(e, errmsg);
+ rb_syserr_fail(e, errmsg);
# endif
- rb_syserr_fail_str(e, prog);
+ rb_syserr_fail_str(e, prog);
}
if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
close(arg.pair[1]);
@@ -6930,14 +7660,14 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
#else
cmd = rb_execarg_commandline(eargp, &prog);
if (!NIL_P(execarg_obj)) {
- rb_execarg_parent_start(execarg_obj);
- rb_execarg_run_options(eargp, sargp, NULL, 0);
+ rb_execarg_parent_start(execarg_obj);
+ rb_execarg_run_options(eargp, sargp, NULL, 0);
}
fp = popen(cmd, modestr);
e = errno;
if (eargp) {
rb_execarg_parent_end(execarg_obj);
- rb_execarg_run_options(sargp, NULL, NULL, 0);
+ rb_execarg_run_options(sargp, NULL, NULL, 0);
}
if (!fp) rb_syserr_fail_path(e, prog);
fd = fileno(fp);
@@ -6951,19 +7681,19 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
if (convconfig) {
fptr->encs = *convconfig;
#if RUBY_CRLF_ENVIRONMENT
- if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
- fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
- }
+ if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
+ fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
+ }
#endif
}
else {
- if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
- fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
- }
+ if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
+ fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
+ }
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
- if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
- fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
- }
+ if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
+ fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
+ }
#endif
}
fptr->pid = pid;
@@ -6987,7 +7717,7 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
#else
static VALUE
pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
- const convconfig_t *convconfig)
+ const convconfig_t *convconfig)
{
rb_raise(rb_eNotImpError, "popen() is not available");
}
@@ -6998,10 +7728,10 @@ is_popen_fork(VALUE prog)
{
if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
#if !defined(HAVE_WORKING_FORK)
- rb_raise(rb_eNotImpError,
- "fork() function is unimplemented on this machine");
+ rb_raise(rb_eNotImpError,
+ "fork() function is unimplemented on this machine");
#else
- return TRUE;
+ return TRUE;
#endif
}
return FALSE;
@@ -7009,7 +7739,7 @@ is_popen_fork(VALUE prog)
static VALUE
pipe_open_s(VALUE prog, const char *modestr, int fmode,
- const convconfig_t *convconfig)
+ const convconfig_t *convconfig)
{
int argc = 1;
VALUE *argv = &prog;
@@ -7025,7 +7755,7 @@ pipe_close(VALUE io)
{
rb_io_t *fptr = io_close_fptr(io);
if (fptr) {
- fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
+ fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
}
return Qnil;
}
@@ -7034,67 +7764,136 @@ static VALUE popen_finish(VALUE port, VALUE klass);
/*
* call-seq:
- * IO.popen([env,] cmd, mode="r" [, opt]) -> io
- * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
+ * IO.popen(env = {}, cmd, mode = 'r', **opts) -> io
+ * IO.popen(env = {}, cmd, mode = 'r', **opts) {|io| ... } -> object
*
- * Runs the specified command as a subprocess; the subprocess's
- * standard input and output will be connected to the returned
- * IO object.
+ * Executes the given command +cmd+ as a subprocess
+ * whose $stdin and $stdout are connected to a new stream +io+.
*
- * The PID of the started process can be obtained by IO#pid method.
+ * This method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * _cmd_ is a string or an array as follows.
+ * If no block is given, returns the new stream,
+ * which depending on given +mode+ may be open for reading, writing, or both.
+ * The stream should be explicitly closed (eventually) to avoid resource leaks.
*
- * cmd:
- * "-" : fork
- * commandline : command line string which is passed to a shell
- * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
- * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
- * (env and opts are optional.)
+ * If a block is given, the stream is passed to the block
+ * (again, open for reading, writing, or both);
+ * when the block exits, the stream is closed,
+ * and the block's value is assigned to global variable <tt>$?</tt> and returned.
*
- * If _cmd_ is a +String+ ``<code>-</code>'',
- * then a new instance of Ruby is started as the subprocess.
+ * Optional argument +mode+ may be any valid \IO mode.
+ * See {Access Modes}[rdoc-ref:File@Access+Modes].
*
- * If <i>cmd</i> is an +Array+ of +String+,
- * then it will be used as the subprocess's +argv+ bypassing a shell.
- * The array can contain a hash at first for environments and
- * a hash at last for options similar to #spawn.
+ * Required argument +cmd+ determines which of the following occurs:
*
- * The default mode for the new file object is ``r'',
- * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
- * The last argument <i>opt</i> qualifies <i>mode</i>.
+ * - The process forks.
+ * - A specified program runs in a shell.
+ * - A specified program runs with specified arguments.
+ * - A specified program runs with specified arguments and a specified +argv0+.
*
- * # set IO encoding
- * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
- * euc_jp_string = nkf_io.read
- * }
+ * Each of these is detailed below.
*
- * # merge standard output and standard error using
- * # spawn option. See the document of Kernel.spawn.
- * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
- * ls_result_with_error = ls_io.read
- * }
+ * The optional hash argument +env+ specifies name/value pairs that are to be added
+ * to the environment variables for the subprocess:
*
- * # spawn options can be mixed with IO options
- * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
- * ls_result_with_error = ls_io.read
- * }
+ * IO.popen({'FOO' => 'bar'}, 'ruby', 'r+') do |pipe|
+ * pipe.puts 'puts ENV["FOO"]'
+ * pipe.close_write
+ * pipe.gets
+ * end => "bar\n"
+ *
+ * Optional keyword arguments +opts+ specify:
+ *
+ * - {Open options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
+ * - Options for Kernel#spawn.
+ *
+ * <b>Forked \Process</b>
+ *
+ * When argument +cmd+ is the 1-character string <tt>'-'</tt>, causes the process to fork:
+ * IO.popen('-') do |pipe|
+ * if pipe
+ * $stderr.puts "In parent, child pid is #{pipe.pid}\n"
+ * else
+ * $stderr.puts "In child, pid is #{$$}\n"
+ * end
+ * end
+ *
+ * Output:
+ *
+ * In parent, child pid is 26253
+ * In child, pid is 26253
+ *
+ * Note that this is not supported on all platforms.
+ *
+ * <b>Shell Subprocess</b>
+ *
+ * When argument +cmd+ is a single string (but not <tt>'-'</tt>),
+ * the program named +cmd+ is run as a shell command:
+ *
+ * IO.popen('uname') do |pipe|
+ * pipe.readlines
+ * end
+ *
+ * Output:
+ *
+ * ["Linux\n"]
*
- * Raises exceptions which IO.pipe and Kernel.spawn raise.
+ * Another example:
*
- * If a block is given, Ruby will run the command as a child connected
- * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
- * parameter to the block.
- * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
- * In this case IO.popen returns the value of the block.
+ * IO.popen('/bin/sh', 'r+') do |pipe|
+ * pipe.puts('ls')
+ * pipe.close_write
+ * $stderr.puts pipe.readlines.size
+ * end
+ *
+ * Output:
+ *
+ * 213
+ *
+ * <b>Program Subprocess</b>
+ *
+ * When argument +cmd+ is an array of strings,
+ * the program named <tt>cmd[0]</tt> is run with all elements of +cmd+ as its arguments:
+ *
+ * IO.popen(['du', '..', '.']) do |pipe|
+ * $stderr.puts pipe.readlines.size
+ * end
+ *
+ * Output:
+ *
+ * 1111
+ *
+ * <b>Program Subprocess with <tt>argv0</tt></b>
+ *
+ * When argument +cmd+ is an array whose first element is a 2-element string array
+ * and whose remaining elements (if any) are strings:
+ *
+ * - <tt>cmd[0][0]</tt> (the first string in the nested array) is the name of a program that is run.
+ * - <tt>cmd[0][1]</tt> (the second string in the nested array) is set as the program's <tt>argv[0]</tt>.
+ * - <tt>cmd[1..-1]</tt> (the strings in the outer array) are the program's arguments.
+ *
+ * Example (sets <tt>$0</tt> to 'foo'):
+ *
+ * IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"
*
- * If a block is given with a _cmd_ of ``<code>-</code>'',
- * the block will be run in two separate processes: once in the parent,
- * and once in a child. The parent process will be passed the pipe
- * object as a parameter to the block, the child version of the block
- * will be passed +nil+, and the child's standard in and
- * standard out will be connected to the parent through the pipe. Not
- * available on all platforms.
+ * <b>Some Special Examples</b>
+ *
+ * # Set IO encoding.
+ * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
+ * euc_jp_string = nkf_io.read
+ * }
+ *
+ * # Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn.
+ * IO.popen(["ls", "/", :err=>[:child, :out]]) do |io|
+ * ls_result_with_error = io.read
+ * end
+ *
+ * # Use mixture of spawn options and IO options.
+ * IO.popen(["ls", "/"], :err=>[:child, :out]) do |io|
+ * ls_result_with_error = io.read
+ * end
*
* f = IO.popen("uname")
* p f.readlines
@@ -7107,7 +7906,7 @@ static VALUE popen_finish(VALUE port, VALUE klass);
* f.puts "bar"; f.close_write; puts f.gets
* }
*
- * <em>produces:</em>
+ * Output (from last section):
*
* ["Linux\n"]
* Parent is 21346
@@ -7116,6 +7915,9 @@ static VALUE popen_finish(VALUE port, VALUE klass);
* 21352 is here, f is nil
* #<Process::Status: pid 21352 exit 0>
* <foo>bar;zot;
+ *
+ * Raises exceptions that IO.pipe and Kernel.spawn raise.
+ *
*/
static VALUE
@@ -7127,15 +7929,15 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
switch (argc) {
case 2:
- pmode = argv[1];
+ pmode = argv[1];
case 1:
- pname = argv[0];
- break;
+ pname = argv[0];
+ break;
default:
- {
- int ex = !NIL_P(opt);
- rb_error_arity(argc + ex, 1 + ex, 2 + ex);
- }
+ {
+ int ex = !NIL_P(opt);
+ rb_error_arity(argc + ex, 1 + ex, 2 + ex);
+ }
}
return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
}
@@ -7150,26 +7952,26 @@ rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
tmp = rb_check_array_type(pname);
if (!NIL_P(tmp)) {
- long len = RARRAY_LEN(tmp);
+ long len = RARRAY_LEN(tmp);
#if SIZEOF_LONG > SIZEOF_INT
- if (len > INT_MAX) {
- rb_raise(rb_eArgError, "too many arguments");
- }
+ if (len > INT_MAX) {
+ rb_raise(rb_eArgError, "too many arguments");
+ }
#endif
execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
- RB_GC_GUARD(tmp);
+ RB_GC_GUARD(tmp);
}
else {
- SafeStringValue(pname);
- execarg_obj = Qnil;
- if (!is_popen_fork(pname))
+ SafeStringValue(pname);
+ execarg_obj = Qnil;
+ if (!is_popen_fork(pname))
execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
}
if (!NIL_P(execarg_obj)) {
- if (!NIL_P(opt))
- opt = rb_execarg_extract_options(execarg_obj, opt);
- if (!NIL_P(env))
- rb_execarg_setenv(execarg_obj, env);
+ if (!NIL_P(opt))
+ opt = rb_execarg_extract_options(execarg_obj, opt);
+ if (!NIL_P(env))
+ rb_execarg_setenv(execarg_obj, env);
}
rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
modestr = rb_io_oflags_modestr(oflags);
@@ -7181,18 +7983,18 @@ static VALUE
popen_finish(VALUE port, VALUE klass)
{
if (NIL_P(port)) {
- /* child */
- if (rb_block_given_p()) {
- rb_yield(Qnil);
+ /* child */
+ if (rb_block_given_p()) {
+ rb_protect(rb_yield, Qnil, NULL);
rb_io_flush(rb_ractor_stdout());
rb_io_flush(rb_ractor_stderr());
- _exit(0);
- }
- return Qnil;
+ _exit(0);
+ }
+ return Qnil;
}
RBASIC_SET_CLASS(port, klass);
if (rb_block_given_p()) {
- return rb_ensure(rb_yield, port, pipe_close, port);
+ return rb_ensure(rb_yield, port, pipe_close, port);
}
return port;
}
@@ -7233,41 +8035,36 @@ rb_open_file(int argc, const VALUE *argv, VALUE io)
return io;
}
-
/*
* Document-method: File::open
*
* call-seq:
- * File.open(filename, mode="r" [, opt]) -> file
- * File.open(filename [, mode [, perm]] [, opt]) -> file
- * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
- * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
+ * File.open(path, mode = 'r', perm = 0666, **opts) -> file
+ * File.open(path, mode = 'r', perm = 0666, **opts) {|f| ... } -> object
*
- * With no associated block, File.open is a synonym for
- * File.new. If the optional code block is given, it will
- * be passed the opened +file+ as an argument and the File object will
- * automatically be closed when the block terminates. The value of the block
- * will be returned from File.open.
+ * Creates a new \File object, via File.new with the given arguments.
*
- * If a file is being created, its initial permissions may be set using the
- * +perm+ parameter. See File.new for further discussion.
+ * With no block given, returns the \File object.
+ *
+ * With a block given, calls the block with the \File object
+ * and returns the block's value.
*
- * See IO.new for a description of the +mode+ and +opt+ parameters.
*/
/*
* Document-method: IO::open
*
* call-seq:
- * IO.open(fd, mode="r" [, opt]) -> io
- * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
+ * IO.open(fd, mode = 'r', **opts) -> io
+ * IO.open(fd, mode = 'r', **opts) {|io| ... } -> object
+ *
+ * Creates a new \IO object, via IO.new with the given arguments.
+ *
+ * With no block given, returns the \IO object.
*
- * With no associated block, IO.open is a synonym for IO.new. If
- * the optional code block is given, it will be passed +io+ as an argument,
- * and the IO object will automatically be closed when the block terminates.
- * In this instance, IO.open returns the value of the block.
+ * With a block given, calls the block with the \IO object
+ * and returns the block's value.
*
- * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
*/
static VALUE
@@ -7276,7 +8073,7 @@ rb_io_s_open(int argc, VALUE *argv, VALUE klass)
VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
if (rb_block_given_p()) {
- return rb_ensure(rb_yield, io, io_close, io);
+ return rb_ensure(rb_yield, io, io_close, io);
}
return io;
@@ -7284,12 +8081,20 @@ rb_io_s_open(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * IO.sysopen(path, [mode, [perm]]) -> integer
+ * IO.sysopen(path, mode = 'r', perm = 0666) -> integer
+ *
+ * Opens the file at the given path with the given mode and permissions;
+ * returns the integer file descriptor.
+ *
+ * If the file is to be readable, it must exist;
+ * if the file is to be writable and does not exist,
+ * it is created with the given permissions:
+ *
+ * File.write('t.tmp', '') # => 0
+ * IO.sysopen('t.tmp') # => 8
+ * IO.sysopen('t.tmp', 'w') # => 9
*
- * Opens the given path, returning the underlying file descriptor as a
- * Integer.
*
- * IO.sysopen("testfile") #=> 3
*/
static VALUE
@@ -7308,8 +8113,8 @@ rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
oflags = NUM2INT(intmode);
else {
- SafeStringValue(vmode);
- oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
+ SafeStringValue(vmode);
+ oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
}
if (NIL_P(vperm)) perm = 0666;
else perm = NUM2MODET(vperm);
@@ -7336,101 +8141,100 @@ check_pipe_command(VALUE filename_or_command)
/*
* call-seq:
- * open(path [, mode [, perm]] [, opt]) -> io or nil
- * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
+ * open(path, mode = 'r', perm = 0666, **opts) -> io or nil
+ * open(path, mode = 'r', perm = 0666, **opts) {|io| ... } -> obj
*
* Creates an IO object connected to the given stream, file, or subprocess.
*
- * If +path+ does not start with a pipe character (<code>|</code>), treat it
- * as the name of a file to open using the specified mode (defaulting to
- * "r").
+ * Required string argument +path+ determines which of the following occurs:
*
- * The +mode+ is either a string or an integer. If it is an integer, it
- * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
- * it is a string, it is either "fmode", "fmode:ext_enc", or
- * "fmode:ext_enc:int_enc".
+ * - The file at the specified +path+ is opened.
+ * - The process forks.
+ * - A subprocess is created.
*
- * See the documentation of IO.new for full documentation of the +mode+ string
- * directives.
+ * Each of these is detailed below.
*
- * If a file is being created, its initial permissions may be set using the
- * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
- * a description of permissions.
+ * <b>File Opened</b>
+
+ * If +path+ does _not_ start with a pipe character (<tt>'|'</tt>),
+ * a file stream is opened with <tt>File.open(path, mode, perm, **opts)</tt>.
*
- * If a block is specified, it will be invoked with the IO object as a
- * parameter, and the IO will be automatically closed when the block
- * terminates. The call returns the value of the block.
+ * With no block given, file stream is returned:
*
- * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
- * created, connected to the caller by a pair of pipes. The returned IO
- * object may be used to write to the standard input and read from the
- * standard output of this subprocess.
+ * open('t.txt') # => #<File:t.txt>
*
- * If the command following the pipe is a single minus sign
- * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
- * parent. If the command is not <code>"-"</code>, the subprocess runs the
- * command. Note that the command may be processed by shell if it contains
- * shell metacharacters.
+ * With a block given, calls the block with the open file stream,
+ * then closes the stream:
*
- * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
- * call returns +nil+. If a block is associated with the open call, that
- * block will run twice --- once in the parent and once in the child.
+ * open('t.txt') {|f| p f } # => #<File:t.txt (closed)>
*
- * The block parameter will be an IO object in the parent and +nil+ in the
- * child. The parent's +IO+ object will be connected to the child's $stdin
- * and $stdout. The subprocess will be terminated at the end of the block.
+ * Output:
*
- * === Examples
+ * #<File:t.txt>
*
- * Reading from "testfile":
+ * See File.open for details.
*
- * open("testfile") do |f|
- * print f.gets
- * end
+ * <b>Process Forked</b>
*
- * Produces:
+ * If +path+ is the 2-character string <tt>'|-'</tt>, the process forks
+ * and the child process is connected to the parent.
*
- * This is line one
+ * With no block given:
*
- * Open a subprocess and read its output:
+ * io = open('|-')
+ * if io
+ * $stderr.puts "In parent, child pid is #{io.pid}."
+ * else
+ * $stderr.puts "In child, pid is #{$$}."
+ * end
*
- * cmd = open("|date")
- * print cmd.gets
- * cmd.close
+ * Output:
*
- * Produces:
+ * In parent, child pid is 27903.
+ * In child, pid is 27903.
*
- * Wed Apr 9 08:56:31 CDT 2003
+ * With a block given:
*
- * Open a subprocess running the same Ruby program:
+ * open('|-') do |io|
+ * if io
+ * $stderr.puts "In parent, child pid is #{io.pid}."
+ * else
+ * $stderr.puts "In child, pid is #{$$}."
+ * end
+ * end
*
- * f = open("|-", "w+")
- * if f.nil?
- * puts "in Child"
- * exit
- * else
- * puts "Got: #{f.gets}"
- * end
+ * Output:
*
- * Produces:
+ * In parent, child pid is 28427.
+ * In child, pid is 28427.
*
- * Got: in Child
+ * <b>Subprocess Created</b>
*
- * Open a subprocess using a block to receive the IO object:
+ * If +path+ is <tt>'|command'</tt> (<tt>'command' != '-'</tt>),
+ * a new subprocess runs the command; its open stream is returned.
+ * Note that the command may be processed by shell if it contains
+ * shell metacharacters.
*
- * open "|-" do |f|
- * if f then
- * # parent process
- * puts "Got: #{f.gets}"
- * else
- * # child process
- * puts "in Child"
- * end
- * end
+ * With no block given:
+ *
+ * io = open('|echo "Hi!"') # => #<IO:fd 12>
+ * print io.gets
+ * io.close
+ *
+ * Output:
*
- * Produces:
+ * "Hi!"
+ *
+ * With a block given, calls the block with the stream, then closes the stream:
+ *
+ * open('|echo "Hi!"') do |io|
+ * print io.gets
+ * end
+ *
+ * Output:
+ *
+ * "Hi!"
*
- * Got: in Child
*/
static VALUE
@@ -7440,32 +8244,32 @@ rb_f_open(int argc, VALUE *argv, VALUE _)
int redirect = FALSE;
if (argc >= 1) {
- CONST_ID(to_open, "to_open");
- if (rb_respond_to(argv[0], to_open)) {
- redirect = TRUE;
- }
- else {
- VALUE tmp = argv[0];
- FilePathValue(tmp);
- if (NIL_P(tmp)) {
- redirect = TRUE;
- }
- else {
+ CONST_ID(to_open, "to_open");
+ if (rb_respond_to(argv[0], to_open)) {
+ redirect = TRUE;
+ }
+ else {
+ VALUE tmp = argv[0];
+ FilePathValue(tmp);
+ if (NIL_P(tmp)) {
+ redirect = TRUE;
+ }
+ else {
VALUE cmd = check_pipe_command(tmp);
if (!NIL_P(cmd)) {
- argv[0] = cmd;
- return rb_io_s_popen(argc, argv, rb_cIO);
- }
- }
- }
+ argv[0] = cmd;
+ return rb_io_s_popen(argc, argv, rb_cIO);
+ }
+ }
+ }
}
if (redirect) {
VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, io, io_close, io);
- }
- return io;
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, io, io_close, io);
+ }
+ return io;
}
return rb_io_s_open(argc, argv, rb_cFile);
}
@@ -7486,15 +8290,15 @@ rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
static VALUE
rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
- const convconfig_t *convconfig, mode_t perm)
+ const convconfig_t *convconfig, mode_t perm)
{
VALUE cmd;
if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
- return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
+ return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
}
else {
- return rb_file_open_generic(io_alloc(klass), filename,
- oflags, fmode, convconfig, perm);
+ return rb_file_open_generic(io_alloc(klass), filename,
+ oflags, fmode, convconfig, perm);
}
}
@@ -7503,7 +8307,7 @@ io_reopen(VALUE io, VALUE nfile)
{
rb_io_t *fptr, *orig;
int fd, fd2;
- off_t pos = 0;
+ rb_off_t pos = 0;
nfile = rb_io_get_io(nfile);
GetOpenFile(io, fptr);
@@ -7514,11 +8318,11 @@ io_reopen(VALUE io, VALUE nfile)
if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
(fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
(fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
- rb_raise(rb_eArgError,
- "%s can't change access mode from \"%s\" to \"%s\"",
- PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
- rb_io_fmode_modestr(orig->mode));
- }
+ rb_raise(rb_eArgError,
+ "%s can't change access mode from \"%s\" to \"%s\"",
+ PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
+ rb_io_fmode_modestr(orig->mode));
+ }
}
if (fptr->mode & FMODE_WRITABLE) {
if (io_fflush(fptr) < 0)
@@ -7528,7 +8332,7 @@ io_reopen(VALUE io, VALUE nfile)
flush_before_seek(fptr);
}
if (orig->mode & FMODE_READABLE) {
- pos = io_tell(orig);
+ pos = io_tell(orig);
}
if (orig->mode & FMODE_WRITABLE) {
if (io_fflush(orig) < 0)
@@ -7546,13 +8350,13 @@ io_reopen(VALUE io, VALUE nfile)
fd = fptr->fd;
fd2 = orig->fd;
if (fd != fd2) {
- if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
- /* need to keep FILE objects of stdin, stdout and stderr */
- if (rb_cloexec_dup2(fd2, fd) < 0)
- rb_sys_fail_path(orig->pathv);
+ if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
+ /* need to keep FILE objects of stdin, stdout and stderr */
+ if (rb_cloexec_dup2(fd2, fd) < 0)
+ rb_sys_fail_path(orig->pathv);
rb_update_max_fd(fd);
- }
- else {
+ }
+ else {
fclose(fptr->stdio_file);
fptr->stdio_file = 0;
fptr->fd = -1;
@@ -7560,20 +8364,20 @@ io_reopen(VALUE io, VALUE nfile)
rb_sys_fail_path(orig->pathv);
rb_update_max_fd(fd);
fptr->fd = fd;
- }
- rb_thread_fd_close(fd);
- if ((orig->mode & FMODE_READABLE) && pos >= 0) {
- if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
- rb_sys_fail_path(fptr->pathv);
- }
- if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
- rb_sys_fail_path(orig->pathv);
- }
- }
+ }
+ rb_thread_fd_close(fd);
+ if ((orig->mode & FMODE_READABLE) && pos >= 0) {
+ if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
+ rb_sys_fail_path(fptr->pathv);
+ }
+ if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
+ rb_sys_fail_path(orig->pathv);
+ }
+ }
}
if (fptr->mode & FMODE_BINMODE) {
- rb_io_binmode(io);
+ rb_io_binmode(io);
}
RBASIC_SET_CLASS(io, rb_obj_class(nfile));
@@ -7587,8 +8391,8 @@ static int
rb_freopen(VALUE fname, const char *mode, FILE *fp)
{
if (!freopen(RSTRING_PTR(fname), mode, fp)) {
- RB_GC_GUARD(fname);
- return errno;
+ RB_GC_GUARD(fname);
+ return errno;
}
return 0;
}
@@ -7596,19 +8400,36 @@ rb_freopen(VALUE fname, const char *mode, FILE *fp)
/*
* call-seq:
- * ios.reopen(other_IO) -> ios
- * ios.reopen(path, mode [, opt]) -> ios
+ * reopen(other_io) -> self
+ * reopen(path, mode = 'r', **opts) -> self
+ *
+ * Reassociates the stream with another stream,
+ * which may be of a different class.
+ * This method may be used to redirect an existing stream
+ * to a new destination.
+ *
+ * With argument +other_io+ given, reassociates with that stream:
+ *
+ * # Redirect $stdin from a file.
+ * f = File.open('t.txt')
+ * $stdin.reopen(f)
+ * f.close
+ *
+ * # Redirect $stdout to a file.
+ * f = File.open('t.tmp', 'w')
+ * $stdout.reopen(f)
+ * f.close
+ *
+ * With argument +path+ given, reassociates with a new stream to that file path:
+ *
+ * $stdin.reopen('t.txt')
+ * $stdout.reopen('t.tmp', 'w')
+ *
+ * Optional keyword arguments +opts+ specify:
*
- * Reassociates <em>ios</em> with the I/O stream given in
- * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
- * dynamically change the actual class of this stream.
- * The +mode+ and +opt+ parameters accept the same values as IO.open.
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
*
- * f1 = File.new("testfile")
- * f2 = File.new("testfile")
- * f2.readlines[0] #=> "This is line one\n"
- * f2.reopen(f1) #=> #<File:testfile>
- * f2.readlines[0] #=> "This is line one\n"
*/
static VALUE
@@ -7619,44 +8440,44 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
rb_io_t *fptr;
if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
- VALUE tmp = rb_io_check_io(fname);
- if (!NIL_P(tmp)) {
- return io_reopen(file, tmp);
- }
+ VALUE tmp = rb_io_check_io(fname);
+ if (!NIL_P(tmp)) {
+ return io_reopen(file, tmp);
+ }
}
FilePathValue(fname);
rb_io_taint_check(file);
fptr = RFILE(file)->fptr;
if (!fptr) {
- fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
+ fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
}
if (!NIL_P(nmode) || !NIL_P(opt)) {
- int fmode;
- convconfig_t convconfig;
+ int fmode;
+ convconfig_t convconfig;
- rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
- if (IS_PREP_STDIO(fptr) &&
+ rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
+ if (IS_PREP_STDIO(fptr) &&
((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
(fptr->mode & FMODE_READWRITE)) {
- rb_raise(rb_eArgError,
- "%s can't change access mode from \"%s\" to \"%s\"",
- PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
- rb_io_fmode_modestr(fmode));
- }
- fptr->mode = fmode;
- fptr->encs = convconfig;
+ rb_raise(rb_eArgError,
+ "%s can't change access mode from \"%s\" to \"%s\"",
+ PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
+ rb_io_fmode_modestr(fmode));
+ }
+ fptr->mode = fmode;
+ fptr->encs = convconfig;
}
else {
- oflags = rb_io_fmode_oflags(fptr->mode);
+ oflags = rb_io_fmode_oflags(fptr->mode);
}
fptr->pathv = fname;
if (fptr->fd < 0) {
fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
- fptr->stdio_file = 0;
- return file;
+ fptr->stdio_file = 0;
+ return file;
}
if (fptr->mode & FMODE_WRITABLE) {
@@ -7666,9 +8487,9 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
fptr->rbuf.off = fptr->rbuf.len = 0;
if (fptr->stdio_file) {
- int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
- rb_io_oflags_modestr(oflags),
- fptr->stdio_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);
fptr->fd = fileno(fptr->stdio_file);
rb_fd_fix_cloexec(fptr->fd);
@@ -7686,14 +8507,14 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
}
}
else {
- int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
- int err = 0;
- if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
- err = errno;
- (void)close(tmpfd);
- if (err) {
- rb_syserr_fail_path(err, fptr->pathv);
- }
+ int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
+ int err = 0;
+ if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
+ err = errno;
+ (void)close(tmpfd);
+ if (err) {
+ rb_syserr_fail_path(err, fptr->pathv);
+ }
}
return file;
@@ -7706,7 +8527,7 @@ rb_io_init_copy(VALUE dest, VALUE io)
rb_io_t *fptr, *orig;
int fd;
VALUE write_io;
- off_t pos;
+ rb_off_t pos;
io = rb_io_get_io(io);
if (!OBJ_INIT_COPY(dest, io)) return dest;
@@ -7720,6 +8541,7 @@ rb_io_init_copy(VALUE dest, VALUE io)
fptr->encs = orig->encs;
fptr->pid = orig->pid;
fptr->lineno = orig->lineno;
+ fptr->timeout = orig->timeout;
if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
fptr_copy_finalizer(fptr, orig);
@@ -7729,7 +8551,7 @@ rb_io_init_copy(VALUE dest, VALUE io)
if (0 <= pos)
io_seek(fptr, pos, SEEK_SET);
if (fptr->mode & FMODE_BINMODE) {
- rb_io_binmode(dest);
+ rb_io_binmode(dest);
}
write_io = GetWriteIO(io);
@@ -7744,10 +8566,13 @@ rb_io_init_copy(VALUE dest, VALUE io)
/*
* call-seq:
- * ios.printf(format_string [, obj, ...]) -> nil
+ * printf(format_string, *objects) -> nil
+ *
+ * Formats and writes +objects+ to the stream.
+ *
+ * For details on +format_string+, see
+ * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
*
- * Formats and writes to <em>ios</em>, converting parameters under
- * control of the format string. See Kernel#sprintf for details.
*/
VALUE
@@ -7759,13 +8584,36 @@ rb_io_printf(int argc, const VALUE *argv, VALUE out)
/*
* call-seq:
- * printf(io, string [, obj ... ]) -> nil
- * printf(string [, obj ... ]) -> nil
+ * printf(format_string, *objects) -> nil
+ * printf(io, format_string, *objects) -> nil
*
* Equivalent to:
- * io.write(sprintf(string, obj, ...))
- * or
- * $stdout.write(sprintf(string, obj, ...))
+ *
+ * io.write(sprintf(format_string, *objects))
+ *
+ * For details on +format_string+, see
+ * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
+ *
+ * With the single argument +format_string+, formats +objects+ into the string,
+ * then writes the formatted string to $stdout:
+ *
+ * printf('%4.4d %10s %2.2f', 24, 24, 24.0)
+ *
+ * Output (on $stdout):
+ *
+ * 0024 24 24.00#
+ *
+ * With arguments +io+ and +format_string+, formats +objects+ into the string,
+ * then writes the formatted string to +io+:
+ *
+ * printf($stderr, '%4.4d %10s %2.2f', 24, 24, 24.0)
+ *
+ * Output (on $stderr):
+ *
+ * 0024 24 24.00# => nil
+ *
+ * With no arguments, does nothing.
+ *
*/
static VALUE
@@ -7775,12 +8623,12 @@ rb_f_printf(int argc, VALUE *argv, VALUE _)
if (argc == 0) return Qnil;
if (RB_TYPE_P(argv[0], T_STRING)) {
- out = rb_ractor_stdout();
+ out = rb_ractor_stdout();
}
else {
- out = argv[0];
- argv++;
- argc--;
+ out = argv[0];
+ argv++;
+ argc--;
}
rb_io_write(out, rb_f_sprintf(argc, argv));
@@ -7799,26 +8647,58 @@ deprecated_str_setter(VALUE val, ID id, VALUE *var)
/*
* call-seq:
- * ios.print -> nil
- * ios.print(obj, ...) -> nil
+ * print(*objects) -> nil
*
- * Writes the given object(s) to <em>ios</em>. Returns +nil+.
+ * Writes the given objects to the stream; returns +nil+.
+ * Appends the output record separator <tt>$OUTPUT_RECORD_SEPARATOR</tt>
+ * (<tt>$\\</tt>), if it is not +nil+.
+ * See {Line IO}[rdoc-ref:IO@Line+IO].
*
- * The stream must be opened for writing.
- * Each given object that isn't a string will be converted by calling
- * its <code>to_s</code> method.
- * When called without arguments, prints the contents of <code>$_</code>.
+ * With argument +objects+ given, for each object:
*
- * If the output field separator (<code>$,</code>) is not +nil+,
- * it is inserted between objects.
- * If the output record separator (<code>$\\</code>) is not +nil+,
- * it is appended to the output.
+ * - Converts via its method +to_s+ if not a string.
+ * - Writes to the stream.
+ * - If not the last object, writes the output field separator
+ * <tt>$OUTPUT_FIELD_SEPARATOR</tt> (<tt>$,</tt>) if it is not +nil+.
*
- * $stdout.print("This is ", 100, " percent.\n")
+ * With default separators:
*
- * <em>produces:</em>
+ * f = File.open('t.tmp', 'w+')
+ * objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
+ * p $OUTPUT_RECORD_SEPARATOR
+ * p $OUTPUT_FIELD_SEPARATOR
+ * f.print(*objects)
+ * f.rewind
+ * p f.read
+ * f.close
+ *
+ * Output:
+ *
+ * nil
+ * nil
+ * "00.00/10+0izerozero"
+ *
+ * With specified separators:
+ *
+ * $\ = "\n"
+ * $, = ','
+ * f.rewind
+ * f.print(*objects)
+ * f.rewind
+ * p f.read
+ *
+ * Output:
+ *
+ * "0,0.0,0/1,0+0i,zero,zero\n"
+ *
+ * With no argument given, writes the content of <tt>$_</tt>
+ * (which is usually the most recent user input):
+ *
+ * f = File.open('t.tmp', 'w+')
+ * gets # Sets $_ to the most recent user input.
+ * f.print
+ * f.close
*
- * This is 100 percent.
*/
VALUE
@@ -7829,21 +8709,21 @@ rb_io_print(int argc, const VALUE *argv, VALUE out)
/* if no argument given, print `$_' */
if (argc == 0) {
- argc = 1;
- line = rb_lastline_get();
- argv = &line;
+ argc = 1;
+ 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);
- }
- rb_io_write(out, argv[i]);
+ if (!NIL_P(rb_output_fs) && i>0) {
+ rb_io_write(out, rb_output_fs);
+ }
+ rb_io_write(out, argv[i]);
}
if (argc > 0 && !NIL_P(rb_output_rs)) {
- rb_io_write(out, rb_output_rs);
+ rb_io_write(out, rb_output_rs);
}
return Qnil;
@@ -7851,25 +8731,51 @@ rb_io_print(int argc, const VALUE *argv, VALUE out)
/*
* call-seq:
- * print(obj, ...) -> nil
+ * print(*objects) -> nil
*
- * Prints each object in turn to <code>$stdout</code>. If the output
- * field separator (<code>$,</code>) is not +nil+, its
- * contents will appear between each field. If the output record
- * separator (<code>$\\</code>) is not +nil+, it will be
- * appended to the output. If no arguments are given, prints
- * <code>$_</code>. Objects that aren't strings will be converted by
- * calling their <code>to_s</code> method.
+ * Equivalent to <tt>$stdout.print(*objects)</tt>,
+ * this method is the straightforward way to write to <tt>$stdout</tt>.
*
- * print "cat", [1,2,3], 99, "\n"
- * $, = ", "
- * $\ = "\n"
- * print "cat", [1,2,3], 99
+ * Writes the given objects to <tt>$stdout</tt>; returns +nil+.
+ * Appends the output record separator <tt>$OUTPUT_RECORD_SEPARATOR</tt>
+ * <tt>$\\</tt>), if it is not +nil+.
*
- * <em>produces:</em>
+ * With argument +objects+ given, for each object:
+ *
+ * - Converts via its method +to_s+ if not a string.
+ * - Writes to <tt>stdout</tt>.
+ * - If not the last object, writes the output field separator
+ * <tt>$OUTPUT_FIELD_SEPARATOR</tt> (<tt>$,</tt> if it is not +nil+.
+ *
+ * With default separators:
+ *
+ * objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
+ * $OUTPUT_RECORD_SEPARATOR
+ * $OUTPUT_FIELD_SEPARATOR
+ * print(*objects)
+ *
+ * Output:
+ *
+ * nil
+ * nil
+ * 00.00/10+0izerozero
+ *
+ * With specified separators:
+ *
+ * $OUTPUT_RECORD_SEPARATOR = "\n"
+ * $OUTPUT_FIELD_SEPARATOR = ','
+ * print(*objects)
+ *
+ * Output:
+ *
+ * 0,0.0,0/1,0+0i,zero,zero
+ *
+ * With no argument given, writes the content of <tt>$_</tt>
+ * (which is usually the most recent user input):
+ *
+ * gets # Sets $_ to the most recent user input.
+ * print # Prints $_.
*
- * cat12399
- * cat, 1, 2, 3, 99
*/
static VALUE
@@ -7881,19 +8787,23 @@ rb_f_print(int argc, const VALUE *argv, VALUE _)
/*
* call-seq:
- * ios.putc(obj) -> obj
+ * putc(object) -> object
*
- * If <i>obj</i> is Numeric, write the character whose code is the
- * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
- * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
- * raise TypeError.
+ * Writes a character to the stream.
+ * See {Character IO}[rdoc-ref:IO@Character+IO].
*
- * $stdout.putc "A"
- * $stdout.putc 65
+ * If +object+ is numeric, converts to integer if necessary,
+ * then writes the character whose code is the
+ * least significant byte;
+ * if +object+ is a string, writes the first character:
*
- * <em>produces:</em>
+ * $stdout.putc "A"
+ * $stdout.putc 65
+ *
+ * Output:
*
* AA
+ *
*/
static VALUE
@@ -7901,11 +8811,11 @@ rb_io_putc(VALUE io, VALUE ch)
{
VALUE str;
if (RB_TYPE_P(ch, T_STRING)) {
- str = rb_str_substr(ch, 0, 1);
+ str = rb_str_substr(ch, 0, 1);
}
else {
- char c = NUM2CHR(ch);
- str = rb_str_new(&c, 1);
+ char c = NUM2CHR(ch);
+ str = rb_str_new(&c, 1);
}
rb_io_write(io, str);
return ch;
@@ -7920,14 +8830,14 @@ rb_io_putc(VALUE io, VALUE ch)
/*
* call-seq:
- * putc(int) -> int
+ * putc(int) -> int
*
* Equivalent to:
*
* $stdout.putc(int)
*
- * Refer to the documentation for IO#putc for important information regarding
- * multi-byte characters.
+ * See IO#putc for important information regarding multi-byte characters.
+ *
*/
static VALUE
@@ -7935,7 +8845,7 @@ rb_f_putc(VALUE recv, VALUE ch)
{
VALUE r_stdout = rb_ractor_stdout();
if (recv == r_stdout) {
- return rb_io_putc(recv, ch);
+ return rb_io_putc(recv, ch);
}
return forward(r_stdout, rb_intern("putc"), 1, &ch);
}
@@ -7951,7 +8861,7 @@ rb_str_end_with_asciichar(VALUE str, int c)
if (len == 0) return 0;
if ((n = rb_enc_mbminlen(enc)) == 1) {
- return ptr[len - 1] == c;
+ return ptr[len - 1] == c;
}
return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
}
@@ -7963,74 +8873,101 @@ io_puts_ary(VALUE ary, VALUE out, int recur)
long i;
if (recur) {
- tmp = rb_str_new2("[...]");
- rb_io_puts(1, &tmp, out);
- return Qtrue;
+ tmp = rb_str_new2("[...]");
+ rb_io_puts(1, &tmp, out);
+ return Qtrue;
}
ary = rb_check_array_type(ary);
if (NIL_P(ary)) return Qfalse;
for (i=0; i<RARRAY_LEN(ary); i++) {
- tmp = RARRAY_AREF(ary, i);
- rb_io_puts(1, &tmp, out);
+ tmp = RARRAY_AREF(ary, i);
+ rb_io_puts(1, &tmp, out);
}
return Qtrue;
}
/*
* call-seq:
- * ios.puts(obj, ...) -> nil
+ * puts(*objects) -> nil
*
- * Writes the given object(s) to <em>ios</em>.
- * Writes a newline after any that do not already end
- * with a newline sequence. Returns +nil+.
+ * Writes the given +objects+ to the stream, which must be open for writing;
+ * returns +nil+.\
+ * Writes a newline after each that does not already end with a newline sequence.
+ * If called without arguments, writes a newline.
+ * See {Line IO}[rdoc-ref:IO@Line+IO].
*
- * The stream must be opened for writing.
- * If called with an array argument, writes each element on a new line.
- * Each given object that isn't a string or array will be converted
- * by calling its +to_s+ method.
- * If called without arguments, outputs a single newline.
+ * Note that each added newline is the character <tt>"\n"<//tt>,
+ * not the output record separator (<tt>$\\</tt>).
*
- * $stdout.puts("this", "is", ["a", "test"])
+ * Treatment for each object:
*
- * <em>produces:</em>
+ * - \String: writes the string.
+ * - Neither string nor array: writes <tt>object.to_s</tt>.
+ * - \Array: writes each element of the array; arrays may be nested.
*
- * this
- * is
- * a
- * test
+ * To keep these examples brief, we define this helper method:
+ *
+ * def show(*objects)
+ * # Puts objects to file.
+ * f = File.new('t.tmp', 'w+')
+ * f.puts(objects)
+ * # Return file content.
+ * f.rewind
+ * p f.read
+ * f.close
+ * end
+ *
+ * # Strings without newlines.
+ * show('foo', 'bar', 'baz') # => "foo\nbar\nbaz\n"
+ * # Strings, some with newlines.
+ * show("foo\n", 'bar', "baz\n") # => "foo\nbar\nbaz\n"
+ *
+ * # Neither strings nor arrays:
+ * show(0, 0.0, Rational(0, 1), Complex(9, 0), :zero)
+ * # => "0\n0.0\n0/1\n9+0i\nzero\n"
+ *
+ * # Array of strings.
+ * show(['foo', "bar\n", 'baz']) # => "foo\nbar\nbaz\n"
+ * # Nested arrays.
+ * show([[[0, 1], 2, 3], 4, 5]) # => "0\n1\n2\n3\n4\n5\n"
*
- * Note that +puts+ always uses newlines and is not affected
- * by the output record separator (<code>$\\</code>).
*/
VALUE
rb_io_puts(int argc, const VALUE *argv, VALUE out)
{
- int i, n;
VALUE line, args[2];
/* if no argument given, print newline. */
if (argc == 0) {
- rb_io_write(out, rb_default_rs);
- return Qnil;
+ rb_io_write(out, rb_default_rs);
+ return Qnil;
}
- for (i=0; i<argc; i++) {
- if (RB_TYPE_P(argv[i], T_STRING)) {
- line = argv[i];
- goto string;
- }
- if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
- continue;
- }
- line = rb_obj_as_string(argv[i]);
- string:
- n = 0;
- args[n++] = line;
- if (RSTRING_LEN(line) == 0 ||
- !rb_str_end_with_asciichar(line, '\n')) {
- args[n++] = rb_default_rs;
- }
- rb_io_writev(out, n, args);
+ for (int i = 0; i < argc; i++) {
+ // Convert the argument to a string:
+ if (RB_TYPE_P(argv[i], T_STRING)) {
+ line = argv[i];
+ }
+ else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
+ continue;
+ }
+ else {
+ line = rb_obj_as_string(argv[i]);
+ }
+
+ // Write the line:
+ int n = 0;
+ if (RSTRING_LEN(line) == 0) {
+ args[n++] = rb_default_rs;
+ }
+ else {
+ args[n++] = line;
+ if (!rb_str_end_with_asciichar(line, '\n')) {
+ args[n++] = rb_default_rs;
+ }
+ }
+
+ rb_io_writev(out, n, args);
}
return Qnil;
@@ -8038,11 +8975,11 @@ rb_io_puts(int argc, const VALUE *argv, VALUE out)
/*
* call-seq:
- * puts(obj, ...) -> nil
+ * puts(*objects) -> nil
*
* Equivalent to
*
- * $stdout.puts(obj, ...)
+ * $stdout.puts(objects)
*/
static VALUE
@@ -8050,7 +8987,7 @@ rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
VALUE r_stdout = rb_ractor_stdout();
if (recv == r_stdout) {
- return rb_io_puts(argc, argv, recv);
+ return rb_io_puts(argc, argv, recv);
}
return forward(r_stdout, rb_intern("puts"), argc, argv);
}
@@ -8064,10 +9001,10 @@ rb_p_write(VALUE str)
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);
+ io_writev(2, args, r_stdout);
}
else {
- rb_io_writev(r_stdout, 2, args);
+ rb_io_writev(r_stdout, 2, args);
}
return Qnil;
}
@@ -8084,34 +9021,44 @@ rb_p_result(int argc, const VALUE *argv)
VALUE ret = Qnil;
if (argc == 1) {
- ret = argv[0];
+ ret = argv[0];
}
else if (argc > 1) {
- ret = rb_ary_new4(argc, argv);
+ ret = rb_ary_new4(argc, argv);
}
VALUE r_stdout = rb_ractor_stdout();
if (RB_TYPE_P(r_stdout, T_FILE)) {
- rb_io_flush(r_stdout);
+ rb_uninterruptible(rb_io_flush, r_stdout);
}
return ret;
}
/*
* call-seq:
- * p(obj) -> obj
- * p(obj1, obj2, ...) -> [obj, ...]
- * p() -> nil
+ * p(object) -> obj
+ * p(*objects) -> array of objects
+ * p -> nil
*
- * For each object, directly writes _obj_.+inspect+ followed by a
- * newline to the program's standard output.
+ * For each object +obj+, executes:
*
- * S = Struct.new(:name, :state)
- * s = S['dave', 'TX']
- * p s
+ * $stdout.write(obj.inspect, "\n")
*
- * <em>produces:</em>
+ * With one object given, returns the object;
+ * with multiple objects given, returns an array containing the objects;
+ * with no object given, returns +nil+.
+ *
+ * Examples:
+ *
+ * r = Range.new(0, 4)
+ * p r # => 0..4
+ * p [r, r, r] # => [0..4, 0..4, 0..4]
+ * p # => nil
+ *
+ * Output:
+ *
+ * 0..4
+ * [0..4, 0..4, 0..4]
*
- * #<S name="dave", state="TX">
*/
static VALUE
@@ -8127,26 +9074,19 @@ rb_f_p(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * obj.display(port=$>) -> nil
+ * display(port = $>) -> nil
*
- * Prints <i>obj</i> on the given port (default <code>$></code>).
- * Equivalent to:
- *
- * def display(port=$>)
- * port.write self
- * nil
- * end
- *
- * For example:
+ * Writes +self+ on the given port:
*
* 1.display
* "cat".display
* [ 4, 5, 6 ].display
* puts
*
- * <em>produces:</em>
+ * Output:
*
* 1cat[4, 5, 6]
+ *
*/
static VALUE
@@ -8161,27 +9101,28 @@ rb_obj_display(int argc, VALUE *argv, VALUE self)
}
static int
-rb_stderr_to_original_p(void)
+rb_stderr_to_original_p(VALUE err)
{
- return (rb_ractor_stderr() == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
+ return (err == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
}
void
rb_write_error2(const char *mesg, long len)
{
- if (rb_stderr_to_original_p()) {
+ VALUE out = rb_ractor_stderr();
+ if (rb_stderr_to_original_p(out)) {
#ifdef _WIN32
- if (isatty(fileno(stderr))) {
- if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
- }
+ if (isatty(fileno(stderr))) {
+ if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
+ }
#endif
- if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
- /* failed to write to stderr, what can we do? */
- return;
- }
+ if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
+ /* failed to write to stderr, what can we do? */
+ return;
+ }
}
else {
- rb_io_write(rb_ractor_stderr(), rb_str_new(mesg, len));
+ rb_io_write(out, rb_str_new(mesg, len));
}
}
@@ -8194,30 +9135,31 @@ rb_write_error(const char *mesg)
void
rb_write_error_str(VALUE mesg)
{
+ VALUE out = rb_ractor_stderr();
/* a stopgap measure for the time being */
- if (rb_stderr_to_original_p()) {
- size_t len = (size_t)RSTRING_LEN(mesg);
+ if (rb_stderr_to_original_p(out)) {
+ size_t len = (size_t)RSTRING_LEN(mesg);
#ifdef _WIN32
- if (isatty(fileno(stderr))) {
- if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
- }
+ if (isatty(fileno(stderr))) {
+ if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
+ }
#endif
- if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
- RB_GC_GUARD(mesg);
- return;
- }
+ if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
+ RB_GC_GUARD(mesg);
+ return;
+ }
}
else {
- /* may unlock GVL, and */
- rb_io_write(rb_ractor_stderr(), mesg);
+ /* may unlock GVL, and */
+ rb_io_write(out, mesg);
}
}
int
rb_stderr_tty_p(void)
{
- if (rb_stderr_to_original_p())
- return isatty(fileno(stderr));
+ if (rb_stderr_to_original_p(rb_ractor_stderr()))
+ return isatty(fileno(stderr));
return 0;
}
@@ -8225,9 +9167,9 @@ static void
must_respond_to(ID mid, VALUE val, ID id)
{
if (!rb_respond_to(val, mid)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
- rb_id2str(id), rb_id2str(mid),
- rb_obj_class(val));
+ rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
+ rb_id2str(id), rb_id2str(mid),
+ rb_obj_class(val));
}
}
@@ -8279,10 +9221,11 @@ prep_io(int fd, int fmode, VALUE klass, const char *path)
fp->self = io;
fp->fd = fd;
fp->mode = fmode;
+ fp->timeout = Qnil;
if (!io_check_tty(fp)) {
#ifdef __CYGWIN__
- fp->mode |= FMODE_BINMODE;
- setmode(fd, O_BINARY);
+ fp->mode |= FMODE_BINMODE;
+ setmode(fd, O_BINARY);
#endif
}
if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
@@ -8311,7 +9254,7 @@ prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
if (fmode & FMODE_READABLE) {
- fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
+ fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
}
#endif
fptr->stdio_file = f;
@@ -8382,7 +9325,8 @@ rb_io_fptr_new(void)
fp->encs.enc2 = NULL;
fp->encs.ecflags = 0;
fp->encs.ecopts = Qnil;
- fp->write_lock = 0;
+ fp->write_lock = Qnil;
+ fp->timeout = Qnil;
return fp;
}
@@ -8405,155 +9349,43 @@ rb_io_make_open_file(VALUE obj)
/*
* call-seq:
- * IO.new(fd [, mode] [, opt]) -> io
- *
- * Returns a new IO object (a stream) for the given integer file descriptor
- * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
- * more readable fashion. See also IO.sysopen and IO.for_fd.
- *
- * IO.new is called by various File and IO opening methods such as IO::open,
- * Kernel#open, and File::open.
- *
- * === Open Mode
- *
- * When +mode+ is an integer it must be combination of the modes defined in
- * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
- * See the open(2) man page for more information.
- *
- * When +mode+ is a string it must be in one of the following forms:
- *
- * fmode
- * fmode ":" ext_enc
- * fmode ":" ext_enc ":" int_enc
- * fmode ":" "BOM|UTF-*"
- *
- * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
- * the IO and +int_enc+ is the internal encoding.
- *
- * ==== IO Open Mode
- *
- * Ruby allows the following open modes:
- *
- * "r" Read-only, starts at beginning of file (default mode).
+ * IO.new(fd, mode = 'r', **opts) -> io
*
- * "r+" Read-write, starts at beginning of file.
+ * Creates and returns a new \IO object (file stream) from a file descriptor.
*
- * "w" Write-only, truncates existing file
- * to zero length or creates a new file for writing.
+ * \IO.new may be useful for interaction with low-level libraries.
+ * For higher-level interactions, it may be simpler to create
+ * the file stream using File.open.
*
- * "w+" Read-write, truncates existing file to zero length
- * or creates a new file for reading and writing.
+ * Argument +fd+ must be a valid file descriptor (integer):
*
- * "a" Write-only, each write call appends data at end of file.
- * Creates a new file for writing if file does not exist.
+ * path = 't.tmp'
+ * fd = IO.sysopen(path) # => 3
+ * IO.new(fd) # => #<IO:fd 3>
*
- * "a+" Read-write, each write call appends data at end of file.
- * Creates a new file for reading and writing if file does
- * not exist.
+ * The new \IO object does not inherit encoding
+ * (because the integer file descriptor does not have an encoding):
*
- * The following modes must be used separately, and along with one or more of
- * the modes seen above.
+ * fd = IO.sysopen('t.rus', 'rb')
+ * io = IO.new(fd)
+ * io.external_encoding # => #<Encoding:UTF-8> # Not ASCII-8BIT.
*
- * "b" Binary file mode
- * Suppresses EOL <-> CRLF conversion on Windows. And
- * sets external encoding to ASCII-8BIT unless explicitly
- * specified.
+ * Optional argument +mode+ (defaults to 'r') must specify a valid mode;
+ * see {Access Modes}[rdoc-ref:File@Access+Modes]:
*
- * "t" Text file mode
+ * IO.new(fd, 'w') # => #<IO:fd 3>
+ * IO.new(fd, File::WRONLY) # => #<IO:fd 3>
*
- * The exclusive access mode ("x") can be used together with "w" to ensure
- * the file is created. Errno::EEXIST is raised when it already exists.
- * It may not be supported with all kinds of streams (e.g. pipes).
+ * Optional keyword arguments +opts+ specify:
*
- * When the open mode of original IO is read only, the mode cannot be
- * changed to be writable. Similarly, the open mode cannot be changed from
- * write only to readable.
- *
- * When such a change is attempted the error is raised in different locations
- * according to the platform.
- *
- * === IO Encoding
- *
- * When +ext_enc+ is specified, strings read will be tagged by the encoding
- * when reading, and strings output will be converted to the specified
- * encoding when writing.
- *
- * When +ext_enc+ and +int_enc+ are specified read strings will be converted
- * from +ext_enc+ to +int_enc+ upon input, and written strings will be
- * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
- * further details of transcoding on input and output.
- *
- * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
- * a Unicode BOM in the input document to help determine the encoding. For
- * UTF-16 encodings the file open mode must be binary. When present, the BOM
- * is stripped and the external encoding from the BOM is used. When the BOM
- * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
- * encoding option is case insensitive, so "bom|utf-8" is also valid.)
- *
- * === Options
- *
- * +opt+ can be used instead of +mode+ for improved readability. The
- * following keys are supported:
- *
- * :mode ::
- * Same as +mode+ parameter
- *
- * :flags ::
- * Specifies file open flags as integer.
- * If +mode+ parameter is given, this parameter will be bitwise-ORed.
- *
- * :\external_encoding ::
- * External encoding for the IO.
- *
- * :\internal_encoding ::
- * Internal encoding for the IO. "-" is a synonym for the default internal
- * encoding.
- *
- * If the value is +nil+ no conversion occurs.
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
*
- * :encoding ::
- * Specifies external and internal encodings as "extern:intern".
- *
- * :textmode ::
- * If the value is truth value, same as "t" in argument +mode+.
- *
- * :binmode ::
- * If the value is truth value, same as "b" in argument +mode+.
- *
- * :autoclose ::
- * If the value is +false+, the +fd+ will be kept open after this IO
- * instance gets finalized.
- *
- * Also, +opt+ can have same keys in String#encode for controlling conversion
- * between the external encoding and the internal encoding.
- *
- * === Example 1
- *
- * fd = IO.sysopen("/dev/tty", "w")
- * a = IO.new(fd,"w")
- * $stderr.puts "Hello"
- * a.puts "World"
- *
- * Produces:
- *
- * Hello
- * World
- *
- * === Example 2
- *
- * require 'fcntl'
- *
- * fd = STDERR.fcntl(Fcntl::F_DUPFD)
- * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
- * io.puts "Hello, World!"
+ * Examples:
*
- * fd = STDERR.fcntl(Fcntl::F_DUPFD)
- * io = IO.new(fd, mode: 'w', cr_newline: true,
- * external_encoding: Encoding::UTF_16LE)
- * io.puts "Hello, World!"
+ * IO.new(fd, internal_encoding: nil) # => #<IO:fd 3>
+ * IO.new(fd, autoclose: true) # => #<IO:fd 3>
*
- * Both of above print "Hello, World!" in UTF-16LE to standard error output
- * with converting EOL generated by #puts to CR.
*/
static VALUE
@@ -8576,7 +9408,7 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
fd = NUM2INT(fnum);
if (rb_reserved_fd_p(fd)) {
- rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
+ rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
}
#if defined(HAVE_FCNTL) && defined(F_GETFL)
oflags = fcntl(fd, F_GETFL);
@@ -8588,29 +9420,42 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
#if defined(HAVE_FCNTL) && defined(F_GETFL)
ofmode = rb_io_oflags_fmode(oflags);
if (NIL_P(vmode)) {
- fmode = ofmode;
+ fmode = ofmode;
}
else if ((~ofmode & fmode) & FMODE_READWRITE) {
- VALUE error = INT2FIX(EINVAL);
- rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
+ VALUE error = INT2FIX(EINVAL);
+ rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
}
#endif
- if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
- fmode |= FMODE_PREP;
+ VALUE path = Qnil;
+
+ if (!NIL_P(opt)) {
+ if (rb_hash_aref(opt, sym_autoclose) == Qfalse) {
+ fmode |= FMODE_PREP;
+ }
+
+ path = rb_hash_aref(opt, RB_ID2SYM(idPath));
+ if (!NIL_P(path)) {
+ StringValue(path);
+ path = rb_str_new_frozen(path);
+ }
}
+
MakeOpenFile(io, fp);
fp->self = io;
fp->fd = fd;
fp->mode = fmode;
fp->encs = convconfig;
+ fp->pathv = path;
+ fp->timeout = Qnil;
clear_codeconv(fp);
io_check_tty(fp);
if (fileno(stdin) == fd)
- fp->stdio_file = stdin;
+ fp->stdio_file = stdin;
else if (fileno(stdout) == fd)
- fp->stdio_file = stdout;
+ fp->stdio_file = stdout;
else if (fileno(stderr) == fd)
- fp->stdio_file = stderr;
+ fp->stdio_file = stderr;
if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
return io;
@@ -8618,20 +9463,26 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * ios.set_encoding_by_bom -> encoding or nil
+ * set_encoding_by_bom -> encoding or nil
+ *
+ * If the stream begins with a BOM
+ * ({byte order marker}[https://en.wikipedia.org/wiki/Byte_order_mark]),
+ * consumes the BOM and sets the external encoding accordingly;
+ * returns the result encoding if found, or +nil+ otherwise:
+ *
+ * File.write('t.tmp', "\u{FEFF}abc")
+ * io = File.open('t.tmp', 'rb')
+ * io.set_encoding_by_bom # => #<Encoding:UTF-8>
+ * io.close
*
- * Checks if +ios+ starts with a BOM, and then consumes it and sets
- * the external encoding. Returns the result encoding if found, or
- * nil. If +ios+ is not binmode or its encoding has been set
- * already, an exception will be raised.
+ * File.write('t.tmp', 'abc')
+ * io = File.open('t.tmp', 'rb')
+ * io.set_encoding_by_bom # => nil
+ * io.close
*
- * File.write("bom.txt", "\u{FEFF}abc")
- * ios = File.open("bom.txt", "rb")
- * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
+ * Raises an exception if the stream is not binmode
+ * or its encoding has already been set.
*
- * File.write("nobom.txt", "abc")
- * ios = File.open("nobom.txt", "rb")
- * ios.set_encoding_by_bom #=> nil
*/
static VALUE
@@ -8656,42 +9507,58 @@ rb_io_set_encoding_by_bom(VALUE io)
/*
* call-seq:
- * File.new(filename, mode="r" [, opt]) -> file
- * File.new(filename [, mode [, perm]] [, opt]) -> file
+ * File.new(path, mode = 'r', perm = 0666, **opts) -> file
*
- * Opens the file named by +filename+ according to the given +mode+ and
- * returns a new File object.
+ * Opens the file at the given +path+ according to the given +mode+;
+ * creates and returns a new \File object for that file.
*
- * See IO.new for a description of +mode+ and +opt+.
+ * The new \File object is buffered mode (or non-sync mode), unless
+ * +filename+ is a tty.
+ * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync=.
*
- * If a file is being created, permission bits may be given in +perm+. These
- * mode and permission bits are platform dependent; on Unix systems, see
- * open(2) and chmod(2) man pages for details.
+ * Argument +path+ must be a valid file path:
*
- * The new File object is buffered mode (or non-sync mode), unless
- * +filename+ is a tty.
- * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
+ * f = File.new('/etc/fstab')
+ * f.close
+ * f = File.new('t.txt')
+ * f.close
+ *
+ * Optional argument +mode+ (defaults to 'r') must specify a valid mode;
+ * see {Access Modes}[rdoc-ref:File@Access+Modes]:
+ *
+ * f = File.new('t.tmp', 'w')
+ * f.close
+ * f = File.new('t.tmp', File::RDONLY)
+ * f.close
+ *
+ * Optional argument +perm+ (defaults to 0666) must specify valid permissions
+ * see {File Permissions}[rdoc-ref:File@File+Permissions]:
+ *
+ * f = File.new('t.tmp', File::CREAT, 0644)
+ * f.close
+ * f = File.new('t.tmp', File::CREAT, 0444)
+ * f.close
*
- * === Examples
+ * Optional keyword arguments +opts+ specify:
+ *
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
*
- * f = File.new("testfile", "r")
- * f = File.new("newfile", "w+")
- * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
*/
static VALUE
rb_file_initialize(int argc, VALUE *argv, VALUE io)
{
if (RFILE(io)->fptr) {
- rb_raise(rb_eRuntimeError, "reinitializing File");
+ rb_raise(rb_eRuntimeError, "reinitializing File");
}
if (0 < argc && argc < 3) {
- VALUE fd = rb_check_to_int(argv[0]);
+ VALUE fd = rb_check_to_int(argv[0]);
- if (!NIL_P(fd)) {
- argv[0] = fd;
- return rb_io_initialize(argc, argv, io);
- }
+ if (!NIL_P(fd)) {
+ argv[0] = fd;
+ return rb_io_initialize(argc, argv, io);
+ }
}
rb_open_file(argc, argv, io);
@@ -8703,10 +9570,10 @@ static VALUE
rb_io_s_new(int argc, VALUE *argv, VALUE klass)
{
if (rb_block_given_p()) {
- VALUE cname = rb_obj_as_string(klass);
+ VALUE cname = rb_obj_as_string(klass);
- rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
- cname, cname);
+ rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
+ cname, cname);
}
return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
}
@@ -8714,7 +9581,7 @@ rb_io_s_new(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * IO.for_fd(fd, mode [, opt]) -> io
+ * IO.for_fd(fd, mode = 'r', **opts) -> io
*
* Synonym for IO.new.
*
@@ -8741,7 +9608,7 @@ rb_io_autoclose_p(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;
rb_io_check_closed(fptr);
- return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
+ return RBOOL(!(fptr->mode & FMODE_PREP));
}
/*
@@ -8767,12 +9634,223 @@ rb_io_set_autoclose(VALUE io, VALUE autoclose)
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (!RTEST(autoclose))
- fptr->mode |= FMODE_PREP;
+ fptr->mode |= FMODE_PREP;
else
- fptr->mode &= ~FMODE_PREP;
+ fptr->mode &= ~FMODE_PREP;
return autoclose;
}
+static VALUE
+io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
+{
+ VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
+
+ if (!RB_TEST(result)) {
+ return Qnil;
+ }
+
+ int mask = RB_NUM2INT(result);
+
+ if (mask & event) {
+ if (return_io)
+ return io;
+ else
+ return result;
+ }
+ else {
+ return Qfalse;
+ }
+}
+
+/*
+ * call-seq:
+ * io.wait_readable -> truthy or falsy
+ * io.wait_readable(timeout) -> truthy or falsy
+ *
+ * Waits until IO is readable and returns a truthy value, or a falsy
+ * value when times out. Returns a truthy value immediately when
+ * buffered data is available.
+ */
+
+static VALUE
+io_wait_readable(int argc, VALUE *argv, VALUE io)
+{
+ rb_io_t *fptr;
+
+ 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_READABLE, timeout, 1);
+}
+
+/*
+ * call-seq:
+ * io.wait_writable -> truthy or falsy
+ * io.wait_writable(timeout) -> truthy or falsy
+ *
+ * Waits until IO is writable and returns a truthy value or a falsy
+ * value when times out.
+ */
+static VALUE
+io_wait_writable(int argc, VALUE *argv, VALUE io)
+{
+ rb_io_t *fptr;
+
+ RB_IO_POINTER(io, fptr);
+ rb_io_check_writable(fptr);
+
+ rb_check_arity(argc, 0, 1);
+ VALUE timeout = (argc == 1 ? argv[0] : Qnil);
+
+ return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
+}
+
+/*
+ * call-seq:
+ * io.wait_priority -> truthy or falsy
+ * io.wait_priority(timeout) -> truthy or falsy
+ *
+ * Waits until IO is priority and returns a truthy value or a falsy
+ * value when times out. Priority data is sent and received using
+ * the Socket::MSG_OOB flag and is typically limited to streams.
+ */
+static VALUE
+io_wait_priority(int argc, VALUE *argv, VALUE io)
+{
+ rb_io_t *fptr = NULL;
+
+ RB_IO_POINTER(io, fptr);
+ rb_io_check_readable(fptr);
+
+ if (rb_io_read_pending(fptr)) return Qtrue;
+
+ rb_check_arity(argc, 0, 1);
+ VALUE timeout = argc == 1 ? argv[0] : Qnil;
+
+ return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
+}
+
+static int
+wait_mode_sym(VALUE mode)
+{
+ if (mode == ID2SYM(rb_intern("r"))) {
+ return RB_WAITFD_IN;
+ }
+ if (mode == ID2SYM(rb_intern("read"))) {
+ return RB_WAITFD_IN;
+ }
+ if (mode == ID2SYM(rb_intern("readable"))) {
+ return RB_WAITFD_IN;
+ }
+ if (mode == ID2SYM(rb_intern("w"))) {
+ return RB_WAITFD_OUT;
+ }
+ if (mode == ID2SYM(rb_intern("write"))) {
+ return RB_WAITFD_OUT;
+ }
+ if (mode == ID2SYM(rb_intern("writable"))) {
+ return RB_WAITFD_OUT;
+ }
+ if (mode == ID2SYM(rb_intern("rw"))) {
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
+ }
+ if (mode == ID2SYM(rb_intern("read_write"))) {
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
+ }
+ if (mode == ID2SYM(rb_intern("readable_writable"))) {
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
+ }
+
+ rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
+}
+
+static inline rb_io_event_t
+io_event_from_value(VALUE value)
+{
+ int events = RB_NUM2INT(value);
+
+ if (events <= 0) rb_raise(rb_eArgError, "Events must be positive integer!");
+
+ return events;
+}
+
+/*
+ * call-seq:
+ * io.wait(events, timeout) -> event mask, false or nil
+ * io.wait(timeout = nil, mode = :read) -> self, true, or false
+ *
+ * Waits until the IO becomes ready for the specified events and returns the
+ * subset of events that become ready, or a falsy value when times out.
+ *
+ * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
+ * +IO::PRIORITY+.
+ *
+ * Returns an event mask (truthy value) immediately when buffered data is available.
+ *
+ * Optional parameter +mode+ is one of +:read+, +:write+, or
+ * +:read_write+.
+ */
+
+static VALUE
+io_wait(int argc, VALUE *argv, VALUE io)
+{
+ VALUE timeout = Qundef;
+ rb_io_event_t events = 0;
+ int return_io = 0;
+
+ // The documented signature for this method is actually incorrect.
+ // A single timeout is allowed in any position, and multiple symbols can be given.
+ // Whether this is intentional or not, I don't know, and as such I consider this to
+ // be a legacy/slow path.
+ if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
+ // We'd prefer to return the actual mask, but this form would return the io itself:
+ return_io = 1;
+
+ // Slow/messy path:
+ for (int i = 0; i < argc; i += 1) {
+ if (RB_SYMBOL_P(argv[i])) {
+ events |= wait_mode_sym(argv[i]);
+ }
+ else if (UNDEF_P(timeout)) {
+ rb_time_interval(timeout = argv[i]);
+ }
+ else {
+ rb_raise(rb_eArgError, "timeout given more than once");
+ }
+ }
+
+ if (UNDEF_P(timeout)) timeout = Qnil;
+
+ if (events == 0) {
+ events = RUBY_IO_READABLE;
+ }
+ }
+ else /* argc == 2 and neither are symbols */ {
+ // This is the fast path:
+ events = io_event_from_value(argv[0]);
+ timeout = argv[1];
+ }
+
+ if (events & RUBY_IO_READABLE) {
+ rb_io_t *fptr = NULL;
+ RB_IO_POINTER(io, fptr);
+
+ if (rb_io_read_pending(fptr)) {
+ // This was the original behaviour:
+ if (return_io) return Qtrue;
+ // New behaviour always returns an event mask:
+ else return RB_INT2NUM(RUBY_IO_READABLE);
+ }
+ }
+
+ return io_wait_event(io, events, timeout, return_io);
+}
+
static void
argf_mark(void *ptr)
{
@@ -8843,11 +9921,11 @@ argf_initialize_copy(VALUE argf, VALUE orig)
* call-seq:
* ARGF.lineno = integer -> integer
*
- * Sets the line number of +ARGF+ as a whole to the given +Integer+.
+ * Sets the line number of ARGF as a whole to the given Integer.
*
- * +ARGF+ sets the line number automatically as you read data, so normally
+ * ARGF sets the line number automatically as you read data, so normally
* you will not need to set it explicitly. To access the current line number
- * use +ARGF.lineno+.
+ * use ARGF.lineno.
*
* For example:
*
@@ -8862,7 +9940,7 @@ argf_set_lineno(VALUE argf, VALUE val)
{
ARGF.lineno = NUM2INT(val);
ARGF.last_lineno = ARGF.lineno;
- return Qnil;
+ return val;
}
/*
@@ -8870,7 +9948,7 @@ argf_set_lineno(VALUE argf, VALUE val)
* ARGF.lineno -> integer
*
* Returns the current line number of ARGF as a whole. This value
- * can be set manually with +ARGF.lineno=+.
+ * can be set manually with ARGF.lineno=.
*
* For example:
*
@@ -8895,7 +9973,7 @@ argf_forward(int argc, VALUE *argv, VALUE argf)
(ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
#define ARGF_FORWARD(argc, argv) do {\
if (ARGF_GENERIC_INPUT_P())\
- return argf_forward((argc), (argv), argf);\
+ return argf_forward((argc), (argv), argf);\
} while (0)
#define NEXT_ARGF_FORWARD(argc, argv) do {\
if (!next_argv()) return Qnil;\
@@ -8908,7 +9986,7 @@ argf_close(VALUE argf)
VALUE file = ARGF.current_file;
if (file == rb_stdin) return;
if (RB_TYPE_P(file, T_FILE)) {
- rb_io_set_write_io(file, Qnil);
+ rb_io_set_write_io(file, Qnil);
}
io_close(file);
ARGF.init_p = -1;
@@ -8931,163 +10009,163 @@ argf_next_argv(VALUE argf)
}
if (ARGF.init_p == 0) {
- if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
- ARGF.next_p = 1;
- }
- else {
- ARGF.next_p = -1;
- }
- ARGF.init_p = 1;
+ if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
+ ARGF.next_p = 1;
+ }
+ else {
+ ARGF.next_p = -1;
+ }
+ ARGF.init_p = 1;
}
else {
- if (NIL_P(ARGF.argv)) {
- ARGF.next_p = -1;
- }
- else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
- ARGF.next_p = 1;
- }
+ if (NIL_P(ARGF.argv)) {
+ ARGF.next_p = -1;
+ }
+ else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
+ ARGF.next_p = 1;
+ }
}
if (ARGF.next_p == 1) {
- if (ARGF.init_p == 1) argf_close(argf);
+ if (ARGF.init_p == 1) argf_close(argf);
retry:
- if (RARRAY_LEN(ARGF.argv) > 0) {
- VALUE filename = rb_ary_shift(ARGF.argv);
- FilePathValue(filename);
- ARGF.filename = filename;
- filename = rb_str_encode_ospath(filename);
- fn = StringValueCStr(filename);
- if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
- ARGF.current_file = rb_stdin;
- if (ARGF.inplace) {
- rb_warn("Can't do inplace edit for stdio; skipping");
- goto retry;
- }
- }
- else {
- VALUE write_io = Qnil;
- int fr = rb_sysopen(filename, O_RDONLY, 0);
-
- if (ARGF.inplace) {
- struct stat st;
+ if (RARRAY_LEN(ARGF.argv) > 0) {
+ VALUE filename = rb_ary_shift(ARGF.argv);
+ FilePathValue(filename);
+ ARGF.filename = filename;
+ filename = rb_str_encode_ospath(filename);
+ fn = StringValueCStr(filename);
+ if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
+ ARGF.current_file = rb_stdin;
+ if (ARGF.inplace) {
+ rb_warn("Can't do inplace edit for stdio; skipping");
+ goto retry;
+ }
+ }
+ else {
+ VALUE write_io = Qnil;
+ int fr = rb_sysopen(filename, O_RDONLY, 0);
+
+ if (ARGF.inplace) {
+ struct stat st;
#ifndef NO_SAFE_RENAME
- struct stat st2;
-#endif
- VALUE str;
- int fw;
-
- if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) {
- rb_io_close(r_stdout);
- }
- fstat(fr, &st);
- str = filename;
- if (!NIL_P(ARGF.inplace)) {
- VALUE suffix = ARGF.inplace;
- str = rb_str_dup(str);
- if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
- RSTRING_PTR(suffix), RSTRING_LEN(suffix),
- rb_enc_get(suffix), 0, Qnil))) {
- rb_str_append(str, suffix);
- }
+ struct stat st2;
+#endif
+ VALUE str;
+ int fw;
+
+ if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) {
+ rb_io_close(r_stdout);
+ }
+ fstat(fr, &st);
+ str = filename;
+ if (!NIL_P(ARGF.inplace)) {
+ VALUE suffix = ARGF.inplace;
+ str = rb_str_dup(str);
+ if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
+ RSTRING_PTR(suffix), RSTRING_LEN(suffix),
+ rb_enc_get(suffix), 0, Qnil))) {
+ rb_str_append(str, suffix);
+ }
#ifdef NO_SAFE_RENAME
- (void)close(fr);
- (void)unlink(RSTRING_PTR(str));
- if (rename(fn, RSTRING_PTR(str)) < 0) {
- rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
- filename, str, strerror(errno));
- goto retry;
- }
- fr = rb_sysopen(str, O_RDONLY, 0);
+ (void)close(fr);
+ (void)unlink(RSTRING_PTR(str));
+ if (rename(fn, RSTRING_PTR(str)) < 0) {
+ rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
+ filename, str, strerror(errno));
+ goto retry;
+ }
+ fr = rb_sysopen(str, O_RDONLY, 0);
#else
- if (rename(fn, RSTRING_PTR(str)) < 0) {
- rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
- filename, str, strerror(errno));
- close(fr);
- goto retry;
- }
-#endif
- }
- else {
+ if (rename(fn, RSTRING_PTR(str)) < 0) {
+ rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
+ filename, str, strerror(errno));
+ close(fr);
+ goto retry;
+ }
+#endif
+ }
+ else {
#ifdef NO_SAFE_RENAME
- rb_fatal("Can't do inplace edit without backup");
+ rb_fatal("Can't do inplace edit without backup");
#else
- if (unlink(fn) < 0) {
- rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
- filename, strerror(errno));
- close(fr);
- goto retry;
- }
-#endif
- }
- fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (unlink(fn) < 0) {
+ rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
+ filename, strerror(errno));
+ close(fr);
+ goto retry;
+ }
+#endif
+ }
+ fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
#ifndef NO_SAFE_RENAME
- fstat(fw, &st2);
+ fstat(fw, &st2);
#ifdef HAVE_FCHMOD
- fchmod(fw, st.st_mode);
+ fchmod(fw, st.st_mode);
#else
- chmod(fn, st.st_mode);
+ chmod(fn, st.st_mode);
#endif
- if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
- int err;
+ if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
+ int err;
#ifdef HAVE_FCHOWN
- err = fchown(fw, st.st_uid, st.st_gid);
+ err = fchown(fw, st.st_uid, st.st_gid);
#else
- err = chown(fn, st.st_uid, st.st_gid);
-#endif
- if (err && getuid() == 0 && st2.st_uid == 0) {
- const char *wkfn = RSTRING_PTR(filename);
- rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
- filename, str, strerror(errno));
- (void)close(fr);
- (void)close(fw);
- (void)unlink(wkfn);
- goto retry;
- }
- }
-#endif
- write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
- rb_ractor_stdout_set(write_io);
- if (stdout_binmode) rb_io_binmode(rb_stdout);
- }
- fmode = FMODE_READABLE;
- if (!ARGF.binmode) {
- fmode |= DEFAULT_TEXTMODE;
- }
- ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
- if (!NIL_P(write_io)) {
- rb_io_set_write_io(ARGF.current_file, write_io);
- }
- RB_GC_GUARD(filename);
- }
- if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
- GetOpenFile(ARGF.current_file, fptr);
- if (ARGF.encs.enc) {
- fptr->encs = ARGF.encs;
+ err = chown(fn, st.st_uid, st.st_gid);
+#endif
+ if (err && getuid() == 0 && st2.st_uid == 0) {
+ const char *wkfn = RSTRING_PTR(filename);
+ rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
+ filename, str, strerror(errno));
+ (void)close(fr);
+ (void)close(fw);
+ (void)unlink(wkfn);
+ goto retry;
+ }
+ }
+#endif
+ write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
+ rb_ractor_stdout_set(write_io);
+ if (stdout_binmode) rb_io_binmode(rb_stdout);
+ }
+ fmode = FMODE_READABLE;
+ if (!ARGF.binmode) {
+ fmode |= DEFAULT_TEXTMODE;
+ }
+ ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
+ if (!NIL_P(write_io)) {
+ rb_io_set_write_io(ARGF.current_file, write_io);
+ }
+ RB_GC_GUARD(filename);
+ }
+ if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
+ GetOpenFile(ARGF.current_file, fptr);
+ if (ARGF.encs.enc) {
+ fptr->encs = ARGF.encs;
clear_codeconv(fptr);
- }
- else {
- fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
- if (!ARGF.binmode) {
- fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
+ }
+ else {
+ fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
+ if (!ARGF.binmode) {
+ fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
- fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
+ fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
#endif
- }
- }
- ARGF.next_p = 0;
- }
- else {
- ARGF.next_p = 1;
- return FALSE;
- }
+ }
+ }
+ ARGF.next_p = 0;
+ }
+ else {
+ ARGF.next_p = 1;
+ return FALSE;
+ }
}
else if (ARGF.next_p == -1) {
- ARGF.current_file = rb_stdin;
- ARGF.filename = rb_str_new2("-");
- if (ARGF.inplace) {
- rb_warn("Can't do inplace edit for stdio");
- rb_ractor_stdout_set(orig_stdout);
- }
+ ARGF.current_file = rb_stdin;
+ ARGF.filename = rb_str_new2("-");
+ if (ARGF.inplace) {
+ rb_warn("Can't do inplace edit for stdio");
+ rb_ractor_stdout_set(orig_stdout);
+ }
}
if (ARGF.init_p == -1) ARGF.init_p = 1;
return TRUE;
@@ -9102,24 +10180,24 @@ argf_getline(int argc, VALUE *argv, VALUE argf)
retry:
if (!next_argv()) return Qnil;
if (ARGF_GENERIC_INPUT_P()) {
- line = forward_current(idGets, argc, argv);
+ line = forward_current(idGets, argc, argv);
}
else {
- if (argc == 0 && rb_rs == rb_default_rs) {
- line = rb_io_gets(ARGF.current_file);
- }
- else {
- line = rb_io_getline(argc, argv, ARGF.current_file);
- }
- if (NIL_P(line) && ARGF.next_p != -1) {
- argf_close(argf);
- ARGF.next_p = 1;
- goto retry;
- }
+ if (argc == 0 && rb_rs == rb_default_rs) {
+ line = rb_io_gets(ARGF.current_file);
+ }
+ else {
+ line = rb_io_getline(argc, argv, ARGF.current_file);
+ }
+ if (NIL_P(line) && ARGF.next_p != -1) {
+ argf_close(argf);
+ ARGF.next_p = 1;
+ goto retry;
+ }
}
if (!NIL_P(line)) {
- ARGF.lineno = ++lineno;
- ARGF.last_lineno = ARGF.lineno;
+ ARGF.lineno = ++lineno;
+ ARGF.last_lineno = ARGF.lineno;
}
return line;
}
@@ -9139,6 +10217,12 @@ argf_lineno_setter(VALUE val, ID id, VALUE *var)
ARGF.last_lineno = ARGF.lineno = n;
}
+void
+rb_reset_argf_lineno(long n)
+{
+ ARGF.last_lineno = ARGF.lineno = n;
+}
+
static VALUE argf_gets(int, VALUE *, VALUE);
/*
@@ -9178,7 +10262,7 @@ static VALUE
rb_f_gets(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
- return argf_gets(argc, argv, argf);
+ return argf_gets(argc, argv, argf);
}
return forward(argf, idGets, argc, argv);
}
@@ -9189,10 +10273,10 @@ rb_f_gets(int argc, VALUE *argv, VALUE recv)
* ARGF.gets(limit [, getline_args]) -> string or nil
* ARGF.gets(sep, limit [, getline_args]) -> string or nil
*
- * Returns the next line from the current file in +ARGF+.
+ * Returns the next line from the current file in ARGF.
*
* By default lines are assumed to be separated by <code>$/</code>;
- * to use a different character as a separator, supply it as a +String+
+ * to use a different character as a separator, supply it as a String
* for the _sep_ argument.
*
* The optional _limit_ argument specifies how many characters of each line
@@ -9218,21 +10302,21 @@ rb_gets(void)
VALUE line;
if (rb_rs != rb_default_rs) {
- return rb_f_gets(0, 0, argf);
+ return rb_f_gets(0, 0, argf);
}
retry:
if (!next_argv()) return Qnil;
line = rb_io_gets(ARGF.current_file);
if (NIL_P(line) && ARGF.next_p != -1) {
- rb_io_close(ARGF.current_file);
- ARGF.next_p = 1;
- goto retry;
+ rb_io_close(ARGF.current_file);
+ ARGF.next_p = 1;
+ goto retry;
}
rb_lastline_set(line);
if (!NIL_P(line)) {
- ARGF.lineno++;
- ARGF.last_lineno = ARGF.lineno;
+ ARGF.lineno++;
+ ARGF.last_lineno = ARGF.lineno;
}
return line;
@@ -9242,19 +10326,26 @@ static VALUE argf_readline(int, VALUE *, VALUE);
/*
* call-seq:
- * readline(sep=$/) -> string
- * readline(limit) -> string
- * readline(sep, limit) -> string
+ * readline(sep = $/, chomp: false) -> string
+ * readline(limit, chomp: false) -> string
+ * readline(sep, limit, chomp: false) -> string
+ *
+ * Equivalent to method Kernel#gets, except that it raises an exception
+ * if called at end-of-stream:
*
- * Equivalent to Kernel::gets, except
- * +readline+ raises +EOFError+ at end of file.
+ * $ cat t.txt | ruby -e "p readlines; readline"
+ * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
+ * in `readline': end of file reached (EOFError)
+ *
+ * Optional keyword argument +chomp+ specifies whether line separators
+ * are to be omitted.
*/
static VALUE
rb_f_readline(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
- return argf_readline(argc, argv, argf);
+ return argf_readline(argc, argv, argf);
}
return forward(argf, rb_intern("readline"), argc, argv);
}
@@ -9266,16 +10357,16 @@ rb_f_readline(int argc, VALUE *argv, VALUE recv)
* ARGF.readline(limit) -> string
* ARGF.readline(sep, limit) -> string
*
- * Returns the next line from the current file in +ARGF+.
+ * Returns the next line from the current file in ARGF.
*
* By default lines are assumed to be separated by <code>$/</code>;
- * to use a different character as a separator, supply it as a +String+
+ * to use a different character as a separator, supply it as a String
* for the _sep_ argument.
*
* The optional _limit_ argument specifies how many characters of each line
* to return. By default all characters are returned.
*
- * An +EOFError+ is raised at the end of the file.
+ * An EOFError is raised at the end of the file.
*/
static VALUE
argf_readline(int argc, VALUE *argv, VALUE argf)
@@ -9286,7 +10377,7 @@ argf_readline(int argc, VALUE *argv, VALUE argf)
ARGF_FORWARD(argc, argv);
line = argf_gets(argc, argv, argf);
if (NIL_P(line)) {
- rb_eof_error();
+ rb_eof_error();
}
return line;
@@ -9296,35 +10387,83 @@ static VALUE argf_readlines(int, VALUE *, VALUE);
/*
* call-seq:
- * readlines(sep=$/) -> array
- * readlines(limit) -> array
- * readlines(sep, limit) -> array
+ * readlines(sep = $/, chomp: false, **enc_opts) -> array
+ * readlines(limit, chomp: false, **enc_opts) -> array
+ * readlines(sep, limit, chomp: false, **enc_opts) -> array
*
* Returns an array containing the lines returned by calling
- * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
+ * Kernel#gets until the end-of-stream is reached;
+ * (see {Line IO}[rdoc-ref:IO@Line+IO]).
+ *
+ * With only string argument +sep+ given,
+ * returns the remaining lines as determined by line separator +sep+,
+ * or +nil+ if none;
+ * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
+ *
+ * # Default separator.
+ * $ cat t.txt | ruby -e "p readlines"
+ * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
+ *
+ * # Specified separator.
+ * $ cat t.txt | ruby -e "p readlines 'li'"
+ * ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
+ *
+ * # Get-all separator.
+ * $ cat t.txt | ruby -e "p readlines nil"
+ * ["First line\nSecond line\n\nFourth line\nFifth line\n"]
+ *
+ * # Get-paragraph separator.
+ * $ cat t.txt | ruby -e "p readlines ''"
+ * ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
+ *
+ * With only integer argument +limit+ given,
+ * limits the number of bytes in the line;
+ * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
+ *
+ * $cat t.txt | ruby -e "p readlines 10"
+ * ["First line", "\n", "Second lin", "e\n", "\n", "Fourth lin", "e\n", "Fifth line", "\n"]
+ *
+ * $cat t.txt | ruby -e "p readlines 11"
+ * ["First line\n", "Second line", "\n", "\n", "Fourth line", "\n", "Fifth line\n"]
+ *
+ * $cat t.txt | ruby -e "p readlines 12"
+ * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
+ *
+ * With arguments +sep+ and +limit+ given, combines the two behaviors;
+ * see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit].
+ *
+ * Optional keyword argument +chomp+ specifies whether line separators
+ * are to be omitted:
+ *
+ * $ cat t.txt | ruby -e "p readlines(chomp: true)"
+ * ["First line", "Second line", "", "Fourth line", "Fifth line"]
+ *
+ * Optional keyword arguments +enc_opts+ specify encoding options;
+ * see {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
+ *
*/
static VALUE
rb_f_readlines(int argc, VALUE *argv, VALUE recv)
{
if (recv == argf) {
- return argf_readlines(argc, argv, argf);
+ return argf_readlines(argc, argv, argf);
}
return forward(argf, rb_intern("readlines"), argc, argv);
}
/*
* call-seq:
- * ARGF.readlines(sep=$/) -> array
+ * ARGF.readlines(sep = $/) -> array
* ARGF.readlines(limit) -> array
* ARGF.readlines(sep, limit) -> array
*
- * ARGF.to_a(sep=$/) -> array
+ * ARGF.to_a(sep = $/) -> array
* ARGF.to_a(limit) -> array
* ARGF.to_a(sep, limit) -> array
*
- * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
- * lines, one line per element. Lines are assumed to be separated by _sep_.
+ * Reads each file in ARGF in its entirety, returning an Array containing
+ * lines from the files. Lines are assumed to be separated by _sep_.
*
* lines = ARGF.readlines
* lines[0] #=> "This is line one\n"
@@ -9337,17 +10476,17 @@ argf_readlines(int argc, VALUE *argv, VALUE argf)
ary = rb_ary_new();
while (next_argv()) {
- if (ARGF_GENERIC_INPUT_P()) {
- lines = forward_current(rb_intern("readlines"), argc, argv);
- }
- else {
- lines = rb_io_readlines(argc, argv, ARGF.current_file);
- argf_close(argf);
- }
- ARGF.next_p = 1;
- rb_ary_concat(ary, lines);
- ARGF.lineno = lineno + RARRAY_LEN(ary);
- ARGF.last_lineno = ARGF.lineno;
+ if (ARGF_GENERIC_INPUT_P()) {
+ lines = forward_current(rb_intern("readlines"), argc, argv);
+ }
+ else {
+ lines = rb_io_readlines(argc, argv, ARGF.current_file);
+ argf_close(argf);
+ }
+ ARGF.next_p = 1;
+ rb_ary_concat(ary, lines);
+ ARGF.lineno = lineno + RARRAY_LEN(ary);
+ ARGF.last_lineno = ARGF.lineno;
}
ARGF.init_p = 0;
return ary;
@@ -9355,16 +10494,23 @@ argf_readlines(int argc, VALUE *argv, VALUE argf)
/*
* call-seq:
- * `cmd` -> string
+ * `command` -> string
*
- * Returns the standard output of running _cmd_ in a subshell.
- * The built-in syntax <code>%x{...}</code> uses
- * this method. Sets <code>$?</code> to the process status.
+ * Returns the <tt>$stdout</tt> output from running +command+ in a subshell;
+ * sets global variable <tt>$?</tt> to the process status.
+ *
+ * This method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ *
+ * Examples:
+ *
+ * $ `date` # => "Wed Apr 9 08:56:30 CDT 2003\n"
+ * $ `echo oops && exit 99` # => "oops\n"
+ * $ $? # => #<Process::Status: pid 17088 exit 99>
+ * $ $?.status # => 99>
+ *
+ * The built-in syntax <tt>%x{...}</tt> uses this method.
*
- * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
- * `ls testdir`.split[1] #=> "main.rb"
- * `echo oops && exit 99` #=> "oops\n"
- * $?.exitstatus #=> 99
*/
static VALUE
@@ -9384,7 +10530,7 @@ rb_f_backquote(VALUE obj, VALUE str)
rb_io_close(port);
RFILE(port)->fptr = NULL;
rb_io_fptr_finalize(fptr);
- rb_gc_force_recycle(port); /* also guards from premature GC */
+ RB_GC_GUARD(port);
return result;
}
@@ -9405,63 +10551,63 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
struct timeval timerec;
if (!NIL_P(read)) {
- Check_Type(read, T_ARRAY);
- for (i=0; i<RARRAY_LEN(read); i++) {
- GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
- rb_fd_set(fptr->fd, &fds[0]);
- if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
- pending++;
- rb_fd_set(fptr->fd, &fds[3]);
- }
- if (max < fptr->fd) max = fptr->fd;
- }
- if (pending) { /* no blocking if there's buffered data */
- timerec.tv_sec = timerec.tv_usec = 0;
- tp = &timerec;
- }
- rp = &fds[0];
+ Check_Type(read, T_ARRAY);
+ for (i=0; i<RARRAY_LEN(read); i++) {
+ GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
+ rb_fd_set(fptr->fd, &fds[0]);
+ if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
+ pending++;
+ rb_fd_set(fptr->fd, &fds[3]);
+ }
+ if (max < fptr->fd) max = fptr->fd;
+ }
+ if (pending) { /* no blocking if there's buffered data */
+ timerec.tv_sec = timerec.tv_usec = 0;
+ tp = &timerec;
+ }
+ rp = &fds[0];
}
else
- rp = 0;
+ rp = 0;
if (!NIL_P(write)) {
- Check_Type(write, T_ARRAY);
- for (i=0; i<RARRAY_LEN(write); i++) {
+ Check_Type(write, T_ARRAY);
+ for (i=0; i<RARRAY_LEN(write); i++) {
VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
- GetOpenFile(write_io, fptr);
- rb_fd_set(fptr->fd, &fds[1]);
- if (max < fptr->fd) max = fptr->fd;
- }
- wp = &fds[1];
+ GetOpenFile(write_io, fptr);
+ rb_fd_set(fptr->fd, &fds[1]);
+ if (max < fptr->fd) max = fptr->fd;
+ }
+ wp = &fds[1];
}
else
- wp = 0;
+ wp = 0;
if (!NIL_P(except)) {
- Check_Type(except, T_ARRAY);
- for (i=0; i<RARRAY_LEN(except); i++) {
+ Check_Type(except, T_ARRAY);
+ for (i=0; i<RARRAY_LEN(except); i++) {
VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
VALUE write_io = GetWriteIO(io);
- GetOpenFile(io, fptr);
- rb_fd_set(fptr->fd, &fds[2]);
- if (max < fptr->fd) max = fptr->fd;
+ GetOpenFile(io, fptr);
+ rb_fd_set(fptr->fd, &fds[2]);
+ if (max < fptr->fd) max = fptr->fd;
if (io != write_io) {
GetOpenFile(write_io, fptr);
rb_fd_set(fptr->fd, &fds[2]);
if (max < fptr->fd) max = fptr->fd;
}
- }
- ep = &fds[2];
+ }
+ ep = &fds[2];
}
else {
- ep = 0;
+ ep = 0;
}
max++;
n = rb_thread_fd_select(max, rp, wp, ep, tp);
if (n < 0) {
- rb_sys_fail(0);
+ rb_sys_fail(0);
}
if (!pending && n == 0) return Qnil; /* returns nil on timeout */
@@ -9471,48 +10617,48 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
if (rp) {
- list = RARRAY_AREF(res, 0);
- for (i=0; i< RARRAY_LEN(read); i++) {
- VALUE obj = rb_ary_entry(read, i);
- VALUE io = rb_io_get_io(obj);
- GetOpenFile(io, fptr);
- if (rb_fd_isset(fptr->fd, &fds[0]) ||
- rb_fd_isset(fptr->fd, &fds[3])) {
- rb_ary_push(list, obj);
- }
- }
+ list = RARRAY_AREF(res, 0);
+ for (i=0; i< RARRAY_LEN(read); i++) {
+ VALUE obj = rb_ary_entry(read, i);
+ VALUE io = rb_io_get_io(obj);
+ GetOpenFile(io, fptr);
+ if (rb_fd_isset(fptr->fd, &fds[0]) ||
+ rb_fd_isset(fptr->fd, &fds[3])) {
+ rb_ary_push(list, obj);
+ }
+ }
}
if (wp) {
- list = RARRAY_AREF(res, 1);
- for (i=0; i< RARRAY_LEN(write); i++) {
- VALUE obj = rb_ary_entry(write, i);
- VALUE io = rb_io_get_io(obj);
- VALUE write_io = GetWriteIO(io);
- GetOpenFile(write_io, fptr);
- if (rb_fd_isset(fptr->fd, &fds[1])) {
- rb_ary_push(list, obj);
- }
- }
+ list = RARRAY_AREF(res, 1);
+ for (i=0; i< RARRAY_LEN(write); i++) {
+ VALUE obj = rb_ary_entry(write, i);
+ VALUE io = rb_io_get_io(obj);
+ VALUE write_io = GetWriteIO(io);
+ GetOpenFile(write_io, fptr);
+ if (rb_fd_isset(fptr->fd, &fds[1])) {
+ rb_ary_push(list, obj);
+ }
+ }
}
if (ep) {
- list = RARRAY_AREF(res, 2);
- for (i=0; i< RARRAY_LEN(except); i++) {
- VALUE obj = rb_ary_entry(except, i);
- VALUE io = rb_io_get_io(obj);
- VALUE write_io = GetWriteIO(io);
- GetOpenFile(io, fptr);
- if (rb_fd_isset(fptr->fd, &fds[2])) {
- rb_ary_push(list, obj);
- }
- else if (io != write_io) {
- GetOpenFile(write_io, fptr);
- if (rb_fd_isset(fptr->fd, &fds[2])) {
- rb_ary_push(list, obj);
- }
- }
- }
+ list = RARRAY_AREF(res, 2);
+ for (i=0; i< RARRAY_LEN(except); i++) {
+ VALUE obj = rb_ary_entry(except, i);
+ VALUE io = rb_io_get_io(obj);
+ VALUE write_io = GetWriteIO(io);
+ GetOpenFile(io, fptr);
+ if (rb_fd_isset(fptr->fd, &fds[2])) {
+ rb_ary_push(list, obj);
+ }
+ else if (io != write_io) {
+ GetOpenFile(write_io, fptr);
+ if (rb_fd_isset(fptr->fd, &fds[2])) {
+ rb_ary_push(list, obj);
+ }
+ }
+ }
}
return res; /* returns an empty array on interrupt */
@@ -9539,7 +10685,7 @@ select_end(VALUE arg)
int i;
for (i = 0; i < numberof(p->fdsets); ++i)
- rb_fd_term(&p->fdsets[i]);
+ rb_fd_term(&p->fdsets[i]);
return Qnil;
}
@@ -9550,8 +10696,8 @@ static VALUE sym_normal, sym_sequential, sym_random,
struct io_advise_struct {
int fd;
int advice;
- off_t offset;
- off_t len;
+ rb_off_t offset;
+ rb_off_t len;
};
static VALUE
@@ -9566,39 +10712,39 @@ io_advise_sym_to_const(VALUE sym)
{
#ifdef POSIX_FADV_NORMAL
if (sym == sym_normal)
- return INT2NUM(POSIX_FADV_NORMAL);
+ return INT2NUM(POSIX_FADV_NORMAL);
#endif
#ifdef POSIX_FADV_RANDOM
if (sym == sym_random)
- return INT2NUM(POSIX_FADV_RANDOM);
+ return INT2NUM(POSIX_FADV_RANDOM);
#endif
#ifdef POSIX_FADV_SEQUENTIAL
if (sym == sym_sequential)
- return INT2NUM(POSIX_FADV_SEQUENTIAL);
+ return INT2NUM(POSIX_FADV_SEQUENTIAL);
#endif
#ifdef POSIX_FADV_WILLNEED
if (sym == sym_willneed)
- return INT2NUM(POSIX_FADV_WILLNEED);
+ return INT2NUM(POSIX_FADV_WILLNEED);
#endif
#ifdef POSIX_FADV_DONTNEED
if (sym == sym_dontneed)
- return INT2NUM(POSIX_FADV_DONTNEED);
+ return INT2NUM(POSIX_FADV_DONTNEED);
#endif
#ifdef POSIX_FADV_NOREUSE
if (sym == sym_noreuse)
- return INT2NUM(POSIX_FADV_NOREUSE);
+ return INT2NUM(POSIX_FADV_NOREUSE);
#endif
return Qnil;
}
static VALUE
-do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
+do_io_advise(rb_io_t *fptr, VALUE advice, rb_off_t offset, rb_off_t len)
{
int rv;
struct io_advise_struct ias;
@@ -9611,7 +10757,7 @@ do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
* silently ignore it. Because IO::advise is only hint.
*/
if (NIL_P(num_adv))
- return Qnil;
+ return Qnil;
ias.fd = fptr->fd;
ias.advice = NUM2INT(num_adv);
@@ -9620,14 +10766,14 @@ do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
if (rv && rv != ENOSYS) {
- /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
- it returns the error code. */
- VALUE message = rb_sprintf("%"PRIsVALUE" "
- "(%"PRI_OFFT_PREFIX"d, "
- "%"PRI_OFFT_PREFIX"d, "
- "%"PRIsVALUE")",
- fptr->pathv, offset, len, advice);
- rb_syserr_fail_str(rv, message);
+ /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
+ it returns the error code. */
+ VALUE message = rb_sprintf("%"PRIsVALUE" "
+ "(%"PRI_OFFT_PREFIX"d, "
+ "%"PRI_OFFT_PREFIX"d, "
+ "%"PRIsVALUE")",
+ fptr->pathv, offset, len, advice);
+ rb_syserr_fail_str(rv, message);
}
return Qnil;
@@ -9639,65 +10785,56 @@ static void
advice_arg_check(VALUE advice)
{
if (!SYMBOL_P(advice))
- rb_raise(rb_eTypeError, "advice must be a Symbol");
+ rb_raise(rb_eTypeError, "advice must be a Symbol");
if (advice != sym_normal &&
- advice != sym_sequential &&
- advice != sym_random &&
- advice != sym_willneed &&
- advice != sym_dontneed &&
- advice != sym_noreuse) {
- rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
+ advice != sym_sequential &&
+ advice != sym_random &&
+ advice != sym_willneed &&
+ advice != sym_dontneed &&
+ advice != sym_noreuse) {
+ rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
}
}
/*
* call-seq:
- * ios.advise(advice, offset=0, len=0) -> nil
+ * advise(advice, offset = 0, len = 0) -> nil
*
- * Announce an intention to access data from the current file in a
- * specific pattern. On platforms that do not support the
- * <em>posix_fadvise(2)</em> system call, this method is a no-op.
+ * Invokes Posix system call
+ * {posix_fadvise(2)}[https://linux.die.net/man/2/posix_fadvise],
+ * which announces an intention to access data from the current file
+ * in a particular manner.
*
- * _advice_ is one of the following symbols:
+ * The arguments and results are platform-dependent.
*
- * :normal:: No advice to give; the default assumption for an open file.
- * :sequential:: The data will be accessed sequentially
- * with lower offsets read before higher ones.
- * :random:: The data will be accessed in random order.
- * :willneed:: The data will be accessed in the near future.
- * :dontneed:: The data will not be accessed in the near future.
- * :noreuse:: The data will only be accessed once.
+ * The relevant data is specified by:
*
- * The semantics of a piece of advice are platform-dependent. See
- * <em>man 2 posix_fadvise</em> for details.
+ * - +offset+: The offset of the first byte of data.
+ * - +len+: The number of bytes to be accessed;
+ * if +len+ is zero, or is larger than the number of bytes remaining,
+ * all remaining bytes will be accessed.
*
- * "data" means the region of the current file that begins at
- * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
- * ends at the last byte of the file. By default, both _offset_ and
- * _len_ are 0, meaning that the advice applies to the entire file.
+ * Argument +advice+ is one of the following symbols:
*
- * If an error occurs, one of the following exceptions will be raised:
+ * - +:normal+: The application has no advice to give
+ * about its access pattern for the specified data.
+ * If no advice is given for an open file, this is the default assumption.
+ * - +:sequential+: The application expects to access the specified data sequentially
+ * (with lower offsets read before higher ones).
+ * - +:random+: The specified data will be accessed in random order.
+ * - +:noreuse+: The specified data will be accessed only once.
+ * - +:willneed+: The specified data will be accessed in the near future.
+ * - +:dontneed+: The specified data will not be accessed in the near future.
*
- * IOError:: The IO stream is closed.
- * Errno::EBADF::
- * The file descriptor of the current file is invalid.
- * Errno::EINVAL:: An invalid value for _advice_ was given.
- * Errno::ESPIPE::
- * The file descriptor of the current file refers to a FIFO or
- * pipe. (Linux raises Errno::EINVAL in this case).
- * TypeError::
- * Either _advice_ was not a Symbol, or one of the
- * other arguments was not an Integer.
- * RangeError:: One of the arguments given was too big/small.
+ * Not implemented on all platforms.
*
- * This list is not exhaustive; other Errno:: exceptions are also possible.
*/
static VALUE
rb_io_advise(int argc, VALUE *argv, VALUE io)
{
VALUE advice, offset, len;
- off_t off, l;
+ rb_off_t off, l;
rb_io_t *fptr;
rb_scan_args(argc, argv, "12", &advice, &offset, &len);
@@ -9719,31 +10856,45 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
+ * IO.select(read_ios, write_ios = [], error_ios = [], timeout = nil) -> array or nil
+ *
+ * Invokes system call {select(2)}[https://linux.die.net/man/2/select],
+ * which monitors multiple file descriptors,
+ * waiting until one or more of the file descriptors
+ * becomes ready for some class of I/O operation.
+ *
+ * Not implemented on all platforms.
+ *
+ * Each of the arguments +read_ios+, +write_ios+, and +error_ios+
+ * is an array of IO objects.
+ *
+ * Argument +timeout+ is an integer timeout interval in seconds.
+ *
+ * The method monitors the \IO objects given in all three arrays,
+ * waiting for some to be ready;
+ * returns a 3-element array whose elements are:
+ *
+ * - An array of the objects in +read_ios+ that are ready for reading.
+ * - An array of the objects in +write_ios+ that are ready for writing.
+ * - An array of the objects in +error_ios+ have pending exceptions.
*
- * Calls select(2) system call.
- * It monitors given arrays of IO objects, waits until one or more of
- * IO objects are ready for reading, are ready for writing, and have
- * pending exceptions respectively, and returns an array that contains
- * arrays of those IO objects. It will return +nil+ if optional
- * <i>timeout</i> value is given and no IO object is ready in
- * <i>timeout</i> seconds.
+ * If no object becomes ready within the given +timeout+, +nil+ is returned.
*
- * IO.select peeks the buffer of IO objects for testing readability.
- * If the IO buffer is not empty, IO.select immediately notifies
- * readability. This "peek" only happens for IO objects. It does not
+ * \IO.select peeks the buffer of \IO objects for testing readability.
+ * If the \IO buffer is not empty, \IO.select immediately notifies
+ * readability. This "peek" only happens for \IO objects. It does not
* happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
*
- * The best way to use IO.select is invoking it after nonblocking
+ * The best way to use \IO.select is invoking it after non-blocking
* methods such as #read_nonblock, #write_nonblock, etc. The methods
* raise an exception which is extended by IO::WaitReadable or
* IO::WaitWritable. The modules notify how the caller should wait
- * with IO.select. If IO::WaitReadable is raised, the caller should
+ * with \IO.select. If IO::WaitReadable is raised, the caller should
* wait for reading. If IO::WaitWritable is raised, the caller should
* wait for writing.
*
* So, blocking read (#readpartial) can be emulated using
- * #read_nonblock and IO.select as follows:
+ * #read_nonblock and \IO.select as follows:
*
* begin
* result = io_like.read_nonblock(maxlen)
@@ -9755,16 +10906,16 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
* retry
* end
*
- * Especially, the combination of nonblocking methods and IO.select is
+ * Especially, the combination of non-blocking methods and \IO.select is
* preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
* has #to_io method to return underlying IO object. IO.select calls
* #to_io to obtain the file descriptor to wait.
*
- * This means that readability notified by IO.select doesn't mean
+ * This means that readability notified by \IO.select doesn't mean
* readability from OpenSSL::SSL::SSLSocket object.
*
* The most likely situation is that OpenSSL::SSL::SSLSocket buffers
- * some data. IO.select doesn't see the buffer. So IO.select can
+ * some data. \IO.select doesn't see the buffer. So \IO.select can
* block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
*
* However, several more complicated situations exist.
@@ -9784,23 +10935,23 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
* So, the caller should wait for ready for writability as above
* example.
*
- * The combination of nonblocking methods and IO.select is also useful
+ * The combination of non-blocking methods and \IO.select is also useful
* for streams such as tty, pipe socket socket when multiple processes
* read from a stream.
*
* Finally, Linux kernel developers don't guarantee that
* readability of select(2) means readability of following read(2) even
- * for a single process.
- * See select(2) manual on GNU/Linux system.
+ * for a single process;
+ * see {select(2)}[https://linux.die.net/man/2/select]
*
- * Invoking IO.select before IO#readpartial works well as usual.
- * However it is not the best way to use IO.select.
+ * Invoking \IO.select before IO#readpartial works well as usual.
+ * However it is not the best way to use \IO.select.
*
* The writability notified by select(2) doesn't show
* how many bytes are writable.
* IO#write method blocks until given whole string is written.
- * So, <code>IO#write(two or more bytes)</code> can block after
- * writability is notified by IO.select. IO#write_nonblock is required
+ * So, <tt>IO#write(two or more bytes)</tt> can block after
+ * writability is notified by \IO.select. IO#write_nonblock is required
* to avoid the blocking.
*
* Blocking write (#write) can be emulated using #write_nonblock and
@@ -9820,13 +10971,7 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
* string = string.byteslice(written..-1)
* end
*
- * === Parameters
- * read_array:: an array of IO objects that wait until ready for read
- * write_array:: an array of IO objects that wait until ready for write
- * error_array:: an array of IO objects that wait for exceptions
- * timeout:: a numeric value in second
- *
- * === Example
+ * Example:
*
* rp, wp = IO.pipe
* mesg = "ping "
@@ -9848,18 +10993,26 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
* end
* }
*
- * <em>produces:</em>
+ * Output:
*
* ping pong
* ping pong
* ping pong
* (snipped)
* ping
+ *
*/
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ // It's optionally supported.
+ VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);
+ if (!UNDEF_P(result)) return result;
+ }
+
VALUE timeout;
struct select_args args;
struct timeval timerec;
@@ -9867,15 +11020,15 @@ rb_f_select(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
if (NIL_P(timeout)) {
- args.timeout = 0;
+ args.timeout = 0;
}
else {
- timerec = rb_time_interval(timeout);
- args.timeout = &timerec;
+ timerec = rb_time_interval(timeout);
+ args.timeout = &timerec;
}
for (i = 0; i < numberof(args.fdsets); ++i)
- rb_fd_init(&args.fdsets[i]);
+ rb_fd_init(&args.fdsets[i]);
return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}
@@ -9918,7 +11071,7 @@ do_ioctl(int fd, ioctl_req_t cmd, long narg)
}
#endif
-#define DEFULT_IOCTL_NARG_LEN (256)
+#define DEFAULT_IOCTL_NARG_LEN (256)
#if defined(__linux__) && defined(_IOC_SIZE)
static long
@@ -9927,20 +11080,21 @@ linux_iocparm_len(ioctl_req_t cmd)
long len;
if ((cmd & 0xFFFF0000) == 0) {
- /* legacy and unstructured ioctl number. */
- return DEFULT_IOCTL_NARG_LEN;
+ /* legacy and unstructured ioctl number. */
+ return DEFAULT_IOCTL_NARG_LEN;
}
len = _IOC_SIZE(cmd);
/* paranoia check for silly drivers which don't keep ioctl convention */
- if (len < DEFULT_IOCTL_NARG_LEN)
- len = DEFULT_IOCTL_NARG_LEN;
+ if (len < DEFAULT_IOCTL_NARG_LEN)
+ len = DEFAULT_IOCTL_NARG_LEN;
return len;
}
#endif
+#ifdef HAVE_IOCTL
static long
ioctl_narg_len(ioctl_req_t cmd)
{
@@ -9957,11 +11111,12 @@ ioctl_narg_len(ioctl_req_t cmd)
len = linux_iocparm_len(cmd);
#else
/* otherwise guess at what's safe */
- len = DEFULT_IOCTL_NARG_LEN;
+ len = DEFAULT_IOCTL_NARG_LEN;
#endif
return len;
}
+#endif
#ifdef HAVE_FCNTL
#ifdef __linux__
@@ -9972,181 +11127,196 @@ typedef int fcntl_arg_t;
#endif
static long
-fcntl_narg_len(int cmd)
+fcntl_narg_len(ioctl_req_t cmd)
{
long len;
switch (cmd) {
#ifdef F_DUPFD
case F_DUPFD:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_DUP2FD /* bsd specific */
case F_DUP2FD:
- len = sizeof(int);
- break;
+ len = sizeof(int);
+ break;
#endif
#ifdef F_DUPFD_CLOEXEC /* linux specific */
case F_DUPFD_CLOEXEC:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_GETFD
case F_GETFD:
- len = 1;
- break;
+ len = 1;
+ break;
#endif
#ifdef F_SETFD
case F_SETFD:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_GETFL
case F_GETFL:
- len = 1;
- break;
+ len = 1;
+ break;
#endif
#ifdef F_SETFL
case F_SETFL:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_GETOWN
case F_GETOWN:
- len = 1;
- break;
+ len = 1;
+ break;
#endif
#ifdef F_SETOWN
case F_SETOWN:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_GETOWN_EX /* linux specific */
case F_GETOWN_EX:
- len = sizeof(struct f_owner_ex);
- break;
+ len = sizeof(struct f_owner_ex);
+ break;
#endif
#ifdef F_SETOWN_EX /* linux specific */
case F_SETOWN_EX:
- len = sizeof(struct f_owner_ex);
- break;
+ len = sizeof(struct f_owner_ex);
+ break;
#endif
#ifdef F_GETLK
case F_GETLK:
- len = sizeof(struct flock);
- break;
+ len = sizeof(struct flock);
+ break;
#endif
#ifdef F_SETLK
case F_SETLK:
- len = sizeof(struct flock);
- break;
+ len = sizeof(struct flock);
+ break;
#endif
#ifdef F_SETLKW
case F_SETLKW:
- len = sizeof(struct flock);
- break;
+ len = sizeof(struct flock);
+ break;
#endif
#ifdef F_READAHEAD /* bsd specific */
case F_READAHEAD:
- len = sizeof(int);
- break;
+ len = sizeof(int);
+ break;
#endif
#ifdef F_RDAHEAD /* Darwin specific */
case F_RDAHEAD:
- len = sizeof(int);
- break;
+ len = sizeof(int);
+ break;
#endif
#ifdef F_GETSIG /* linux specific */
case F_GETSIG:
- len = 1;
- break;
+ len = 1;
+ break;
#endif
#ifdef F_SETSIG /* linux specific */
case F_SETSIG:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_GETLEASE /* linux specific */
case F_GETLEASE:
- len = 1;
- break;
+ len = 1;
+ break;
#endif
#ifdef F_SETLEASE /* linux specific */
case F_SETLEASE:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
#ifdef F_NOTIFY /* linux specific */
case F_NOTIFY:
- len = sizeof(fcntl_arg_t);
- break;
+ len = sizeof(fcntl_arg_t);
+ break;
#endif
default:
- len = 256;
- break;
+ len = 256;
+ break;
}
return len;
}
#else /* HAVE_FCNTL */
static long
-fcntl_narg_len(int cmd)
+fcntl_narg_len(ioctl_req_t cmd)
{
return 0;
}
#endif /* HAVE_FCNTL */
+#define NARG_SENTINEL 17
+
static long
-setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
+setup_narg(ioctl_req_t cmd, VALUE *argp, long (*narg_len)(ioctl_req_t))
{
long narg = 0;
VALUE arg = *argp;
- if (NIL_P(arg) || arg == Qfalse) {
- narg = 0;
+ if (!RTEST(arg)) {
+ narg = 0;
}
else if (FIXNUM_P(arg)) {
- narg = FIX2LONG(arg);
+ narg = FIX2LONG(arg);
}
else if (arg == Qtrue) {
- narg = 1;
+ narg = 1;
}
else {
- VALUE tmp = rb_check_string_type(arg);
-
- if (NIL_P(tmp)) {
- narg = NUM2LONG(arg);
- }
- else {
- char *ptr;
- long len, slen;
-
- *argp = arg = tmp;
- if (io_p)
- len = ioctl_narg_len(cmd);
- else
- len = fcntl_narg_len((int)cmd);
- rb_str_modify(arg);
-
- slen = RSTRING_LEN(arg);
- /* expand for data + sentinel. */
- if (slen < len+1) {
- rb_str_resize(arg, len+1);
- MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
- slen = len+1;
- }
- /* a little sanity check here */
- ptr = RSTRING_PTR(arg);
- ptr[slen - 1] = 17;
- narg = (long)(SIGNED_VALUE)ptr;
- }
+ VALUE tmp = rb_check_string_type(arg);
+
+ if (NIL_P(tmp)) {
+ narg = NUM2LONG(arg);
+ }
+ else {
+ char *ptr;
+ long len, slen;
+
+ *argp = arg = tmp;
+ len = narg_len(cmd);
+ rb_str_modify(arg);
+
+ slen = RSTRING_LEN(arg);
+ /* expand for data + sentinel. */
+ if (slen < len+1) {
+ rb_str_resize(arg, len+1);
+ MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
+ slen = len+1;
+ }
+ /* a little sanity check here */
+ ptr = RSTRING_PTR(arg);
+ ptr[slen - 1] = NARG_SENTINEL;
+ narg = (long)(SIGNED_VALUE)ptr;
+ }
}
return narg;
}
+static VALUE
+finish_narg(int retval, VALUE arg, const rb_io_t *fptr)
+{
+ if (retval < 0) rb_sys_fail_path(fptr->pathv);
+ if (RB_TYPE_P(arg, T_STRING)) {
+ char *ptr;
+ long slen;
+ RSTRING_GETMEM(arg, ptr, slen);
+ if (ptr[slen-1] != NARG_SENTINEL)
+ rb_raise(rb_eArgError, "return value overflowed string");
+ ptr[slen-1] = '\0';
+ }
+
+ return INT2NUM(retval);
+}
+
#ifdef HAVE_IOCTL
static VALUE
rb_ioctl(VALUE io, VALUE req, VALUE arg)
@@ -10156,32 +11326,28 @@ rb_ioctl(VALUE io, VALUE req, VALUE arg)
long narg;
int retval;
- narg = setup_narg(cmd, &arg, 1);
+ narg = setup_narg(cmd, &arg, ioctl_narg_len);
GetOpenFile(io, fptr);
retval = do_ioctl(fptr->fd, cmd, narg);
- if (retval < 0) rb_sys_fail_path(fptr->pathv);
- if (RB_TYPE_P(arg, T_STRING)) {
- char *ptr;
- long slen;
- RSTRING_GETMEM(arg, ptr, slen);
- if (ptr[slen-1] != 17)
- rb_raise(rb_eArgError, "return value overflowed string");
- ptr[slen-1] = '\0';
- }
-
- return INT2NUM(retval);
+ return finish_narg(retval, arg, fptr);
}
/*
* call-seq:
- * ios.ioctl(integer_cmd, arg) -> integer
+ * ioctl(integer_cmd, argument) -> integer
+ *
+ * Invokes Posix system call {ioctl(2)}[https://linux.die.net/man/2/ioctl],
+ * which issues a low-level command to an I/O device.
+ *
+ * Issues a low-level command to an I/O device.
+ * The arguments and returned value are platform-dependent.
+ * The effect of the call is platform-dependent.
+ *
+ * If argument +argument+ is an integer, it is passed directly;
+ * if it is a string, it is interpreted as a binary sequence of bytes.
+ *
+ * Not implemented on all platforms.
*
- * Provides a mechanism for issuing low-level commands to control or
- * query I/O devices. Arguments and results are platform dependent. If
- * <i>arg</i> is a number, its value is passed directly. If it is a
- * string, it is interpreted as a binary sequence of bytes. On Unix
- * platforms, see <code>ioctl(2)</code> for details. Not implemented on
- * all platforms.
*/
static VALUE
@@ -10210,7 +11376,7 @@ nogvl_fcntl(void *ptr)
#if defined(F_DUPFD)
if (arg->cmd == F_DUPFD)
- return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
+ return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
#endif
return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
}
@@ -10227,15 +11393,15 @@ do_fcntl(int fd, int cmd, long narg)
retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
if (retval != -1) {
- switch (cmd) {
+ switch (cmd) {
#if defined(F_DUPFD)
- case F_DUPFD:
+ case F_DUPFD:
#endif
#if defined(F_DUPFD_CLOEXEC)
- case F_DUPFD_CLOEXEC:
+ case F_DUPFD_CLOEXEC:
#endif
- rb_update_max_fd(retval);
- }
+ rb_update_max_fd(retval);
+ }
}
return retval;
@@ -10249,33 +11415,27 @@ rb_fcntl(VALUE io, VALUE req, VALUE arg)
long narg;
int retval;
- narg = setup_narg(cmd, &arg, 0);
+ narg = setup_narg(cmd, &arg, fcntl_narg_len);
GetOpenFile(io, fptr);
retval = do_fcntl(fptr->fd, cmd, narg);
- if (retval < 0) rb_sys_fail_path(fptr->pathv);
- if (RB_TYPE_P(arg, T_STRING)) {
- char *ptr;
- long slen;
- RSTRING_GETMEM(arg, ptr, slen);
- if (ptr[slen-1] != 17)
- rb_raise(rb_eArgError, "return value overflowed string");
- ptr[slen-1] = '\0';
- }
-
- return INT2NUM(retval);
+ return finish_narg(retval, arg, fptr);
}
/*
* call-seq:
- * ios.fcntl(integer_cmd, arg) -> integer
+ * fcntl(integer_cmd, argument) -> integer
+ *
+ * Invokes Posix system call {fcntl(2)}[https://linux.die.net/man/2/fcntl],
+ * which provides a mechanism for issuing low-level commands to control or query
+ * a file-oriented I/O stream. Arguments and results are platform
+ * dependent.
+ *
+ * If +argument is a number, its value is passed directly;
+ * if it is a string, it is interpreted as a binary sequence of bytes.
+ * (Array#pack might be a useful way to build this string.)
+ *
+ * Not implemented on all platforms.
*
- * Provides a mechanism for issuing low-level commands to control or
- * query file-oriented I/O streams. Arguments and results are platform
- * dependent. If <i>arg</i> is a number, its value is passed
- * directly. If it is a string, it is interpreted as a binary sequence
- * of bytes (Array#pack might be a useful way to build this string). On
- * Unix platforms, see <code>fcntl(2)</code> for details. Not
- * implemented on all platforms.
*/
static VALUE
@@ -10293,36 +11453,29 @@ rb_io_fcntl(int argc, VALUE *argv, VALUE io)
#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
/*
* call-seq:
- * syscall(num [, args...]) -> integer
+ * syscall(integer_callno, *arguments) -> integer
*
- * Calls the operating system function identified by _num_ and
- * returns the result of the function or raises SystemCallError if
- * it failed.
+ * Invokes Posix system call {syscall(2)}[https://linux.die.net/man/2/syscall],
+ * which calls a specified function.
*
- * Arguments for the function can follow _num_. They must be either
- * +String+ objects or +Integer+ objects. A +String+ object is passed
- * as a pointer to the byte sequence. An +Integer+ object is passed
- * as an integer whose bit size is the same as a pointer.
- * Up to nine parameters may be passed.
+ * Calls the operating system function identified by +integer_callno+;
+ * returns the result of the function or raises SystemCallError if it failed.
+ * The effect of the call is platform-dependent.
+ * The arguments and returned value are platform-dependent.
*
- * The function identified by _num_ is system
- * dependent. On some Unix systems, the numbers may be obtained from a
- * header file called <code>syscall.h</code>.
+ * For each of +arguments+: if it is an integer, it is passed directly;
+ * if it is a string, it is interpreted as a binary sequence of bytes.
+ * There may be as many as nine such arguments.
*
- * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
+ * Arguments +integer_callno+ and +argument+, as well as the returned value,
+ * are platform-dependent.
*
- * <em>produces:</em>
- *
- * hello
- *
- * Calling +syscall+ on a platform which does not have any way to
- * an arbitrary system function just fails with NotImplementedError.
- *
- * *Note:*
- * +syscall+ is essentially unsafe and unportable.
- * Feel free to shoot your foot.
+ * Note: Method +syscall+ is essentially unsafe and unportable.
* The DL (Fiddle) library is preferred for safer and a bit
* more portable programming.
+ *
+ * Not implemented on all platforms.
+ *
*/
static VALUE
@@ -10366,52 +11519,52 @@ rb_f_syscall(int argc, VALUE *argv, VALUE _)
}
if (argc == 0)
- rb_raise(rb_eArgError, "too few arguments for syscall");
+ rb_raise(rb_eArgError, "too few arguments for syscall");
if (argc > numberof(arg))
- rb_raise(rb_eArgError, "too many arguments for syscall");
+ rb_raise(rb_eArgError, "too many arguments for syscall");
num = NUM2SYSCALLID(argv[0]); ++argv;
for (i = argc - 1; i--; ) {
- VALUE v = rb_check_string_type(argv[i]);
+ VALUE v = rb_check_string_type(argv[i]);
- if (!NIL_P(v)) {
- SafeStringValue(v);
- rb_str_modify(v);
- arg[i] = (VALUE)StringValueCStr(v);
- }
- else {
- arg[i] = (VALUE)NUM2LONG(argv[i]);
- }
+ if (!NIL_P(v)) {
+ SafeStringValue(v);
+ rb_str_modify(v);
+ arg[i] = (VALUE)StringValueCStr(v);
+ }
+ else {
+ arg[i] = (VALUE)NUM2LONG(argv[i]);
+ }
}
switch (argc) {
case 1:
- retval = SYSCALL(num);
- break;
+ retval = SYSCALL(num);
+ break;
case 2:
- retval = SYSCALL(num, arg[0]);
- break;
+ retval = SYSCALL(num, arg[0]);
+ break;
case 3:
- retval = SYSCALL(num, arg[0],arg[1]);
- break;
+ retval = SYSCALL(num, arg[0],arg[1]);
+ break;
case 4:
- retval = SYSCALL(num, arg[0],arg[1],arg[2]);
- break;
+ retval = SYSCALL(num, arg[0],arg[1],arg[2]);
+ break;
case 5:
- retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
- break;
+ retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
+ break;
case 6:
- retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
- break;
+ retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
+ break;
case 7:
- retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
- break;
+ retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
+ break;
case 8:
- retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
- break;
+ retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
+ break;
}
if (retval == -1)
- rb_sys_fail(0);
+ rb_sys_fail(0);
return RETVAL2NUM(retval);
#undef SYSCALL
#undef NUM2SYSCALLID
@@ -10443,51 +11596,51 @@ io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
VALUE ecopts, tmp;
if (!NIL_P(v2)) {
- enc2 = find_encoding(v1);
- tmp = rb_check_string_type(v2);
- if (!NIL_P(tmp)) {
- if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
- /* Special case - "-" => no transcoding */
- enc = enc2;
- enc2 = NULL;
- }
- else
- enc = find_encoding(v2);
- if (enc == enc2) {
- /* Special case - "-" => no transcoding */
- enc2 = NULL;
- }
- }
- else {
- enc = find_encoding(v2);
- if (enc == enc2) {
- /* Special case - "-" => no transcoding */
- enc2 = NULL;
- }
- }
- SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
- ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
+ enc2 = find_encoding(v1);
+ tmp = rb_check_string_type(v2);
+ if (!NIL_P(tmp)) {
+ if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
+ /* Special case - "-" => no transcoding */
+ enc = enc2;
+ enc2 = NULL;
+ }
+ else
+ enc = find_encoding(v2);
+ if (enc == enc2) {
+ /* Special case - "-" => no transcoding */
+ enc2 = NULL;
+ }
+ }
+ else {
+ enc = find_encoding(v2);
+ if (enc == enc2) {
+ /* Special case - "-" => no transcoding */
+ enc2 = NULL;
+ }
+ }
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
+ ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
}
else {
- if (NIL_P(v1)) {
- /* Set to default encodings */
- rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
- SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
+ if (NIL_P(v1)) {
+ /* Set to default encodings */
+ rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
ecopts = Qnil;
- }
- else {
- tmp = rb_check_string_type(v1);
- if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
+ }
+ else {
+ tmp = rb_check_string_type(v1);
+ if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
- SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
- }
- else {
- rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
- SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
+ }
+ else {
+ rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
+ SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
ecopts = Qnil;
- }
- }
+ }
+ }
}
validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
fptr->encs.enc = enc;
@@ -10522,62 +11675,81 @@ pipe_pair_close(VALUE rw)
/*
* call-seq:
- * IO.pipe -> [read_io, write_io]
- * IO.pipe(ext_enc) -> [read_io, write_io]
- * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
- * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
+ * IO.pipe(**opts) -> [read_io, write_io]
+ * IO.pipe(enc, **opts) -> [read_io, write_io]
+ * IO.pipe(ext_enc, int_enc, **opts) -> [read_io, write_io]
+ * IO.pipe(**opts) {|read_io, write_io] ...} -> object
+ * IO.pipe(enc, **opts) {|read_io, write_io] ...} -> object
+ * IO.pipe(ext_enc, int_enc, **opts) {|read_io, write_io] ...} -> object
*
- * IO.pipe(...) {|read_io, write_io| ... }
+ * Creates a pair of pipe endpoints, +read_io+ and +write_io+,
+ * connected to each other.
*
- * Creates a pair of pipe endpoints (connected to each other) and
- * returns them as a two-element array of IO objects:
- * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
+ * If argument +enc_string+ is given, it must be a string containing one of:
*
- * If a block is given, the block is called and
- * returns the value of the block.
- * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
- * If read_io and write_io are not closed when the block exits, they are closed.
- * i.e. closing read_io and/or write_io doesn't cause an error.
+ * - The name of the encoding to be used as the external encoding.
+ * - The colon-separated names of two encodings to be used as the external
+ * and internal encodings.
*
- * Not available on all platforms.
+ * If argument +int_enc+ is given, it must be an Encoding object
+ * or encoding name string that specifies the internal encoding to be used;
+ * if argument +ext_enc+ is also given, it must be an Encoding object
+ * or encoding name string that specifies the external encoding to be used.
+ *
+ * The string read from +read_io+ is tagged with the external encoding;
+ * if an internal encoding is also specified, the string is converted
+ * to, and tagged with, that encoding.
+ *
+ * If any encoding is specified,
+ * optional hash arguments specify the conversion option.
+ *
+ * Optional keyword arguments +opts+ specify:
+ *
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding Options}[rdoc-ref:encodings.rdoc@Encoding+Options].
+ *
+ * With no block given, returns the two endpoints in an array:
+ *
+ * IO.pipe # => [#<IO:fd 4>, #<IO:fd 5>]
+ *
+ * With a block given, calls the block with the two endpoints;
+ * closes both endpoints and returns the value of the block:
+ *
+ * IO.pipe {|read_io, write_io| p read_io; p write_io }
+ *
+ * Output:
*
- * If an encoding (encoding name or encoding object) is specified as an optional argument,
- * read string from pipe is tagged with the encoding specified.
- * If the argument is a colon separated two encoding names "A:B",
- * the read string is converted from encoding A (external encoding)
- * to encoding B (internal encoding), then tagged with B.
- * If two optional arguments are specified, those must be
- * encoding objects or encoding names,
- * and the first one is the external encoding,
- * and the second one is the internal encoding.
- * If the external encoding and the internal encoding is specified,
- * optional hash argument specify the conversion option.
+ * #<IO:fd 6>
+ * #<IO:fd 7>
+ *
+ * Not available on all platforms.
*
* In the example below, the two processes close the ends of the pipe
* that they are not using. This is not just a cosmetic nicety. The
* read end of a pipe will not generate an end of file condition if
* there are any writers with the pipe still open. In the case of the
- * parent process, the <code>rd.read</code> will never return if it
- * does not first issue a <code>wr.close</code>.
- *
- * rd, wr = IO.pipe
- *
- * if fork
- * wr.close
- * puts "Parent got: <#{rd.read}>"
- * rd.close
- * Process.wait
- * else
- * rd.close
- * puts "Sending message to parent"
- * wr.write "Hi Dad"
- * wr.close
- * end
+ * parent process, the <tt>rd.read</tt> will never return if it
+ * does not first issue a <tt>wr.close</tt>:
+ *
+ * rd, wr = IO.pipe
+ *
+ * if fork
+ * wr.close
+ * puts "Parent got: <#{rd.read}>"
+ * rd.close
+ * Process.wait
+ * else
+ * rd.close
+ * puts 'Sending message to parent'
+ * wr.write "Hi Dad"
+ * wr.close
+ * end
*
* <em>produces:</em>
*
* Sending message to parent
* Parent got: <Hi Dad>
+ *
*/
static VALUE
@@ -10600,9 +11772,9 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
args[2] = INT2FIX(O_RDONLY);
r = rb_protect(io_new_instance, (VALUE)args, &state);
if (state) {
- close(pipes[0]);
- close(pipes[1]);
- rb_jump_tag(state);
+ close(pipes[0]);
+ close(pipes[1]);
+ rb_jump_tag(state);
}
GetOpenFile(r, fptr);
@@ -10612,55 +11784,55 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
ies_args.opt = opt;
rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
if (state) {
- close(pipes[1]);
+ close(pipes[1]);
io_close(r);
- rb_jump_tag(state);
+ rb_jump_tag(state);
}
args[1] = INT2NUM(pipes[1]);
args[2] = INT2FIX(O_WRONLY);
w = rb_protect(io_new_instance, (VALUE)args, &state);
if (state) {
- close(pipes[1]);
- if (!NIL_P(r)) rb_io_close(r);
- rb_jump_tag(state);
+ close(pipes[1]);
+ if (!NIL_P(r)) rb_io_close(r);
+ rb_jump_tag(state);
}
GetOpenFile(w, fptr2);
rb_io_synchronized(fptr2);
extract_binmode(opt, &fmode);
- if ((fmode & FMODE_BINMODE) && v1 == Qnil) {
+ if ((fmode & FMODE_BINMODE) && NIL_P(v1)) {
rb_io_ascii8bit_binmode(r);
rb_io_ascii8bit_binmode(w);
}
#if DEFAULT_TEXTMODE
if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
- fptr->mode &= ~FMODE_TEXTMODE;
- setmode(fptr->fd, O_BINARY);
+ fptr->mode &= ~FMODE_TEXTMODE;
+ setmode(fptr->fd, O_BINARY);
}
#if RUBY_CRLF_ENVIRONMENT
if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
- fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
+ fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
}
#endif
#endif
fptr->mode |= fmode;
#if DEFAULT_TEXTMODE
if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
- fptr2->mode &= ~FMODE_TEXTMODE;
- setmode(fptr2->fd, O_BINARY);
+ fptr2->mode &= ~FMODE_TEXTMODE;
+ setmode(fptr2->fd, O_BINARY);
}
#endif
fptr2->mode |= fmode;
ret = rb_assoc_new(r, w);
if (rb_block_given_p()) {
- VALUE rw[2];
- rw[0] = r;
- rw[1] = w;
- return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
+ VALUE rw[2];
+ rw[0] = r;
+ rw[1] = w;
+ return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
}
return ret;
}
@@ -10684,15 +11856,15 @@ open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg
arg->argc = argc;
arg->argv = argv;
if (NIL_P(opt)) {
- vmode = INT2NUM(O_RDONLY);
- vperm = INT2FIX(0666);
+ vmode = INT2NUM(O_RDONLY);
+ vperm = INT2FIX(0666);
}
else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
- int n;
+ int n;
- v = rb_to_array_type(v);
- n = RARRAY_LENINT(v);
- rb_check_arity(n, 0, 3); /* rb_io_open */
+ v = rb_to_array_type(v);
+ n = RARRAY_LENINT(v);
+ rb_check_arity(n, 0, 3); /* rb_io_open */
rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
}
arg->io = rb_io_open(klass, path, vmode, vperm, opt);
@@ -10704,9 +11876,11 @@ io_s_foreach(VALUE v)
struct getline_arg *arg = (void *)v;
VALUE str;
+ if (arg->limit == 0)
+ rb_raise(rb_eArgError, "invalid limit: 0 for foreach");
while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
- rb_lastline_set(str);
- rb_yield(str);
+ rb_lastline_set(str);
+ rb_yield(str);
}
rb_lastline_set(Qnil);
return Qnil;
@@ -10714,38 +11888,93 @@ io_s_foreach(VALUE v)
/*
* call-seq:
- * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
- * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
- * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
- * IO.foreach(...) -> an_enumerator
- * File.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
- * File.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
- * File.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
- * File.foreach(...) -> an_enumerator
+ * IO.foreach(path, sep = $/, **opts) {|line| block } -> nil
+ * IO.foreach(path, limit, **opts) {|line| block } -> nil
+ * IO.foreach(path, sep, limit, **opts) {|line| block } -> nil
+ * IO.foreach(command, sep = $/, **opts) {|line| block } -> nil
+ * IO.foreach(command, limit, **opts) {|line| block } -> nil
+ * IO.foreach(command, sep, limit, **opts) {|line| block } -> nil
+ * IO.foreach(...) -> an_enumerator
*
- * Executes the block for every line in the named I/O port, where lines
- * are separated by <em>sep</em>.
+ * Calls the block with each successive line read from the stream.
*
- * If no block is given, an enumerator is returned instead.
+ * When called from class \IO (but not subclasses of \IO),
+ * this method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
- * is the IO class, a subprocess is created in the same way as Kernel#open,
- * and its output is returned.
- * Consider to use File.foreach to disable the behavior of subprocess invocation.
+ * The first argument must be a string that is one of the following:
*
- * File.foreach("testfile") {|x| print "GOT ", x }
- * IO.foreach("| cat testfile") {|x| print "GOT ", x }
+ * - Path: if +self+ is a subclass of \IO (\File, for example),
+ * or if the string _does_ _not_ start with the pipe character (<tt>'|'</tt>),
+ * the string is the path to a file.
+ * - Command: if +self+ is the class \IO,
+ * and if the string starts with the pipe character,
+ * the rest of the string is a command to be executed as a subprocess.
+ * This usage has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * <em>produces:</em>
+ * With only argument +path+ given, parses lines from the file at the given +path+,
+ * as determined by the default line separator,
+ * and calls the block with each successive line:
*
- * GOT This is line one
- * GOT This is line two
- * GOT This is line three
- * GOT And so on...
+ * File.foreach('t.txt') {|line| p line }
*
- * If the last argument is a hash, it's the keyword argument to open.
- * See IO.readlines for details about getline_args.
- * And see also IO.read for details about open_args.
+ * Output: the same as above.
+ *
+ * For both forms, command and path, the remaining arguments are the same.
+ *
+ * With argument +sep+ given, parses lines as determined by that line separator
+ * (see {Line Separator}[rdoc-ref:IO@Line+Separator]):
+ *
+ * File.foreach('t.txt', 'li') {|line| p line }
+ *
+ * Output:
+ *
+ * "First li"
+ * "ne\nSecond li"
+ * "ne\n\nThird li"
+ * "ne\nFourth li"
+ * "ne\n"
+ *
+ * Each paragraph:
+ *
+ * File.foreach('t.txt', '') {|paragraph| p paragraph }
+ *
+ * Output:
+ *
+ * "First line\nSecond line\n\n"
+ * "Third line\nFourth line\n"
+ *
+ * With argument +limit+ given, parses lines as determined by the default
+ * line separator and the given line-length limit
+ * (see {Line Limit}[rdoc-ref:IO@Line+Limit]):
+ *
+ * File.foreach('t.txt', 7) {|line| p line }
+ *
+ * Output:
+ *
+ * "First l"
+ * "ine\n"
+ * "Second "
+ * "line\n"
+ * "\n"
+ * "Third l"
+ * "ine\n"
+ * "Fourth l"
+ * "line\n"
+ *
+ * With arguments +sep+ and +limit+ given,
+ * parses lines as determined by the given
+ * line separator and the given line-length limit
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]):
+ *
+ * Optional keyword arguments +opts+ specify:
+ *
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
+ * - {Line Options}[rdoc-ref:IO@Line+Options].
+ *
+ * Returns an Enumerator if no block is given.
*
*/
@@ -10757,7 +11986,7 @@ rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
struct foreach_arg arg;
struct getline_arg garg;
- argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
+ argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
RETURN_ENUMERATOR(self, orig_argc, argv);
extract_getline_args(argc-1, argv+1, &garg);
open_key_args(self, argc, argv, opt, &arg);
@@ -10776,42 +12005,73 @@ io_s_readlines(VALUE v)
/*
* call-seq:
- * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
- * IO.readlines(name, limit [, getline_args, open_args]) -> array
- * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
- * File.readlines(name, sep=$/ [, getline_args, open_args]) -> array
- * File.readlines(name, limit [, getline_args, open_args]) -> array
- * File.readlines(name, sep, limit [, getline_args, open_args]) -> array
+ * IO.readlines(command, sep = $/, **opts) -> array
+ * IO.readlines(command, limit, **opts) -> array
+ * IO.readlines(command, sep, limit, **opts) -> array
+ * IO.readlines(path, sep = $/, **opts) -> array
+ * IO.readlines(path, limit, **opts) -> array
+ * IO.readlines(path, sep, limit, **opts) -> array
*
- * Reads the entire file specified by <i>name</i> as individual
- * lines, and returns those lines in an array. Lines are separated by
- * <i>sep</i>.
+ * Returns an array of all lines read from the stream.
*
- * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
- * is the IO class, a subprocess is created in the same way as Kernel#open,
- * and its output is returned.
- * Consider to use File.readlines to disable the behavior of subprocess invocation.
+ * When called from class \IO (but not subclasses of \IO),
+ * this method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * a = File.readlines("testfile")
- * a[0] #=> "This is line one\n"
+ * The first argument must be a string;
+ * its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>):
*
- * b = File.readlines("testfile", chomp: true)
- * b[0] #=> "This is line one"
+ * - If so (and if +self+ is \IO),
+ * the rest of the string is a command to be executed as a subprocess.
+ * - Otherwise, the string is the path to a file.
*
- * IO.readlines("|ls -a") #=> [".\n", "..\n", ...]
+ * With only argument +command+ given, executes the command in a shell,
+ * parses its $stdout into lines, as determined by the default line separator,
+ * and returns those lines in an array:
*
- * If the last argument is a hash, it's the keyword argument to open.
+ * IO.readlines('| cat t.txt')
+ * # => ["First line\n", "Second line\n", "\n", "Third line\n", "Fourth line\n"]
*
- * === Options for getline
+ * With only argument +path+ given, parses lines from the file at the given +path+,
+ * as determined by the default line separator,
+ * and returns those lines in an array:
*
- * The options hash accepts the following keys:
+ * IO.readlines('t.txt')
+ * # => ["First line\n", "Second line\n", "\n", "Third line\n", "Fourth line\n"]
*
- * :chomp::
- * When the optional +chomp+ keyword argument has a true value,
- * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
- * will be removed from the end of each line.
+ * For both forms, command and path, the remaining arguments are the same.
+ *
+ * With argument +sep+ given, parses lines as determined by that line separator
+ * (see {Line Separator}[rdoc-ref:IO@Line+Separator]):
+ *
+ * # Ordinary separator.
+ * IO.readlines('t.txt', 'li')
+ * # =>["First li", "ne\nSecond li", "ne\n\nThird li", "ne\nFourth li", "ne\n"]
+ * # Get-paragraphs separator.
+ * IO.readlines('t.txt', '')
+ * # => ["First line\nSecond line\n\n", "Third line\nFourth line\n"]
+ * # Get-all separator.
+ * IO.readlines('t.txt', nil)
+ * # => ["First line\nSecond line\n\nThird line\nFourth line\n"]
+ *
+ * With argument +limit+ given, parses lines as determined by the default
+ * line separator and the given line-length limit
+ * (see {Line Limit}[rdoc-ref:IO@Line+Limit]):
+ *
+ * IO.readlines('t.txt', 7)
+ * # => ["First l", "ine\n", "Second ", "line\n", "\n", "Third l", "ine\n", "Fourth ", "line\n"]
+ *
+ * With arguments +sep+ and +limit+ given,
+ * parses lines as determined by the given
+ * line separator and the given line-length limit
+ * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]):
+ *
+ * Optional keyword arguments +opts+ specify:
+ *
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
+ * - {Line Options}[rdoc-ref:IO@Line+Options].
*
- * See also IO.read for details about +name+ and open_args.
*/
static VALUE
@@ -10821,7 +12081,7 @@ rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
struct foreach_arg arg;
struct getline_arg garg;
- argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
+ argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
extract_getline_args(argc-1, argv+1, &garg);
open_key_args(io, argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
@@ -10853,48 +12113,58 @@ seek_before_access(VALUE argp)
/*
* call-seq:
- * IO.read(name, [length [, offset]] [, opt]) -> string
- * File.read(name, [length [, offset]] [, opt]) -> string
+ * IO.read(command, length = nil, offset = 0, **opts) -> string or nil
+ * IO.read(path, length = nil, offset = 0, **opts) -> string or nil
*
- * Opens the file, optionally seeks to the given +offset+, then returns
- * +length+ bytes (defaulting to the rest of the file). #read ensures
- * the file is closed before returning.
+ * Opens the stream, reads and returns some or all of its content,
+ * and closes the stream; returns +nil+ if no bytes were read.
*
- * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
- * is the IO class, a subprocess is created in the same way as Kernel#open,
- * and its output is returned.
- * Consider to use File.read to disable the behavior of subprocess invocation.
+ * When called from class \IO (but not subclasses of \IO),
+ * this method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * === Options
+ * The first argument must be a string;
+ * its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>):
*
- * The options hash accepts the following keys:
+ * - If so (and if +self+ is \IO),
+ * the rest of the string is a command to be executed as a subprocess.
+ * - Otherwise, the string is the path to a file.
*
- * :encoding::
- * string or encoding
+ * With only argument +command+ given, executes the command in a shell,
+ * returns its entire $stdout:
*
- * Specifies the encoding of the read string. +:encoding+ will be ignored
- * if +length+ is specified. See Encoding.aliases for possible encodings.
+ * IO.read('| cat t.txt')
+ * # => "First line\nSecond line\n\nThird line\nFourth line\n"
*
- * :mode::
- * string or integer
+ * With only argument +path+ given, reads in text mode and returns the entire content
+ * of the file at the given path:
*
- * Specifies the <i>mode</i> argument for open(). It must start
- * with an "r", otherwise it will cause an error.
- * See IO.new for the list of possible modes.
+ * IO.read('t.txt')
+ * # => "First line\nSecond line\n\nThird line\nFourth line\n"
*
- * :open_args::
- * array
+ * On Windows, text mode can terminate reading and leave bytes in the file
+ * unread when encountering certain special bytes. Consider using
+ * IO.binread if all bytes in the file should be read.
*
- * Specifies arguments for open() as an array. This key can not be used
- * in combination with either +:encoding+ or +:mode+.
+ * For both forms, command and path, the remaining arguments are the same.
*
- * Examples:
+ * With argument +length+, returns +length+ bytes if available:
+ *
+ * IO.read('t.txt', 7) # => "First l"
+ * IO.read('t.txt', 700)
+ * # => "First line\r\nSecond line\r\n\r\nFourth line\r\nFifth line\r\n"
+ *
+ * With arguments +length+ and +offset+, returns +length+ bytes
+ * if available, beginning at the given +offset+:
+ *
+ * IO.read('t.txt', 10, 2) # => "rst line\nS"
+ * IO.read('t.txt', 10, 200) # => nil
+ *
+ * Optional keyword arguments +opts+ specify:
+ *
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
*
- * File.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
- * File.read("testfile", 20) #=> "This is line one\nThi"
- * File.read("testfile", 20, 10) #=> "ne one\nThis is line "
- * File.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
- * IO.read("|ls -a") #=> ".\n..\n"...
*/
static VALUE
@@ -10907,42 +12177,33 @@ rb_io_s_read(int argc, VALUE *argv, VALUE io)
open_key_args(io, argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
if (!NIL_P(offset)) {
- struct seek_arg sarg;
- int state = 0;
- sarg.io = arg.io;
- sarg.offset = offset;
- sarg.mode = SEEK_SET;
- rb_protect(seek_before_access, (VALUE)&sarg, &state);
- if (state) {
- rb_io_close(arg.io);
- rb_jump_tag(state);
- }
- if (arg.argc == 2) arg.argc = 1;
+ struct seek_arg sarg;
+ int state = 0;
+ sarg.io = arg.io;
+ sarg.offset = offset;
+ sarg.mode = SEEK_SET;
+ rb_protect(seek_before_access, (VALUE)&sarg, &state);
+ if (state) {
+ rb_io_close(arg.io);
+ rb_jump_tag(state);
+ }
+ if (arg.argc == 2) arg.argc = 1;
}
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
/*
* call-seq:
- * IO.binread(name, [length [, offset]]) -> string
- * File.binread(name, [length [, offset]]) -> string
- *
- * Opens the file, optionally seeks to the given <i>offset</i>, then
- * returns <i>length</i> bytes (defaulting to the rest of the file).
- * #binread ensures the file is closed before returning. The open mode
- * would be <code>"rb:ASCII-8BIT"</code>.
+ * IO.binread(command, length = nil, offset = 0) -> string or nil
+ * IO.binread(path, length = nil, offset = 0) -> string or nil
*
- * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
- * is the IO class, a subprocess is created in the same way as Kernel#open,
- * and its output is returned.
- * Consider to use File.binread to disable the behavior of subprocess invocation.
+ * Behaves like IO.read, except that the stream is opened in binary mode
+ * with ASCII-8BIT encoding.
*
- * File.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
- * File.binread("testfile", 20) #=> "This is line one\nThi"
- * File.binread("testfile", 20, 10) #=> "ne one\nThis is line "
- * IO.binread("| cat testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
+ * When called from class \IO (but not subclasses of \IO),
+ * this method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * See also IO.read for details about +name+ and open_args.
*/
static VALUE
@@ -10951,10 +12212,10 @@ rb_io_s_binread(int argc, VALUE *argv, VALUE io)
VALUE offset;
struct foreach_arg arg;
enum {
- fmode = FMODE_READABLE|FMODE_BINMODE,
- oflags = O_RDONLY
+ fmode = FMODE_READABLE|FMODE_BINMODE,
+ oflags = O_RDONLY
#ifdef O_BINARY
- |O_BINARY
+ |O_BINARY
#endif
};
convconfig_t convconfig = {NULL, NULL, 0, Qnil};
@@ -10967,16 +12228,16 @@ rb_io_s_binread(int argc, VALUE *argv, VALUE io)
arg.argv = argv+1;
arg.argc = (argc > 1) ? 1 : 0;
if (!NIL_P(offset)) {
- struct seek_arg sarg;
- int state = 0;
- sarg.io = arg.io;
- sarg.offset = offset;
- sarg.mode = SEEK_SET;
- rb_protect(seek_before_access, (VALUE)&sarg, &state);
- if (state) {
- rb_io_close(arg.io);
- rb_jump_tag(state);
- }
+ struct seek_arg sarg;
+ int state = 0;
+ sarg.io = arg.io;
+ sarg.offset = offset;
+ sarg.mode = SEEK_SET;
+ rb_protect(seek_before_access, (VALUE)&sarg, &state);
+ if (state) {
+ rb_io_close(arg.io);
+ rb_jump_tag(state);
+ }
}
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
@@ -11038,56 +12299,63 @@ io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
/*
* call-seq:
- * IO.write(name, string [, offset]) -> integer
- * IO.write(name, string [, offset] [, opt]) -> integer
- * File.write(name, string [, offset]) -> integer
- * File.write(name, string [, offset] [, opt]) -> integer
+ * IO.write(command, data, **opts) -> integer
+ * IO.write(path, data, offset = 0, **opts) -> integer
+ *
+ * Opens the stream, writes the given +data+ to it,
+ * and closes the stream; returns the number of bytes written.
+ *
+ * When called from class \IO (but not subclasses of \IO),
+ * this method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ *
+ * The first argument must be a string;
+ * its meaning depends on whether it starts with the pipe character (<tt>'|'</tt>):
+ *
+ * - If so (and if +self+ is \IO),
+ * the rest of the string is a command to be executed as a subprocess.
+ * - Otherwise, the string is the path to a file.
+ *
+ * With argument +command+ given, executes the command in a shell,
+ * passes +data+ through standard input, writes its output to $stdout,
+ * and returns the length of the given +data+:
+ *
+ * IO.write('| cat', 'Hello World!') # => 12
*
- * Opens the file, optionally seeks to the given <i>offset</i>, writes
- * <i>string</i>, then returns the length written. #write ensures the
- * file is closed before returning. If <i>offset</i> is not given in
- * write mode, the file is truncated. Otherwise, it is not truncated.
+ * Output:
*
- * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
- * is the IO class, a subprocess is created in the same way as Kernel#open,
- * and its output is returned.
- * Consider to use File.write to disable the behavior of subprocess invocation.
+ * Hello World!
*
- * File.write("testfile", "0123456789", 20) #=> 10
- * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
- * File.write("testfile", "0123456789") #=> 10
- * # File would now read: "0123456789"
- * IO.write("|tr a-z A-Z", "abc") #=> 3
- * # Prints "ABC" to the standard output
+ * With argument +path+ given, writes the given +data+ to the file
+ * at that path:
*
- * If the last argument is a hash, it specifies options for the internal
- * open(). It accepts the following keys:
+ * IO.write('t.tmp', 'abc') # => 3
+ * File.read('t.tmp') # => "abc"
*
- * :encoding::
- * string or encoding
+ * If +offset+ is zero (the default), the file is overwritten:
*
- * Specifies the encoding of the read string.
- * See Encoding.aliases for possible encodings.
+ * IO.write('t.tmp', 'A') # => 1
+ * File.read('t.tmp') # => "A"
*
- * :mode::
- * string or integer
+ * If +offset+ in within the file content, the file is partly overwritten:
*
- * Specifies the <i>mode</i> argument for open(). It must start
- * with "w", "a", or "r+", otherwise it will cause an error.
- * See IO.new for the list of possible modes.
+ * IO.write('t.tmp', 'abcdef') # => 3
+ * File.read('t.tmp') # => "abcdef"
+ * # Offset within content.
+ * IO.write('t.tmp', '012', 2) # => 3
+ * File.read('t.tmp') # => "ab012f"
*
- * :perm::
- * integer
+ * If +offset+ is outside the file content,
+ * the file is padded with null characters <tt>"\u0000"</tt>:
*
- * Specifies the <i>perm</i> argument for open().
+ * IO.write('t.tmp', 'xyz', 10) # => 3
+ * File.read('t.tmp') # => "ab012f\u0000\u0000\u0000\u0000xyz"
*
- * :open_args::
- * array
+ * Optional keyword arguments +opts+ specify:
*
- * Specifies arguments for open() as an array.
- * This key can not be used in combination with other keys.
+ * - {Open Options}[rdoc-ref:IO@Open+Options].
+ * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
*
- * See also IO.read for details about +name+ and open_args.
*/
static VALUE
@@ -11098,20 +12366,16 @@ rb_io_s_write(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * IO.binwrite(name, string, [offset]) -> integer
- * IO.binwrite(name, string, [offset], open_args) -> integer
- * File.binwrite(name, string, [offset]) -> integer
- * File.binwrite(name, string, [offset], open_args) -> integer
+ * IO.binwrite(command, string, offset = 0) -> integer
+ * IO.binwrite(path, string, offset = 0) -> integer
*
- * Same as IO.write except opening the file in binary mode and
- * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
+ * Behaves like IO.write, except that the stream is opened in binary mode
+ * with ASCII-8BIT encoding.
*
- * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
- * is the IO class, a subprocess is created in the same way as Kernel#open,
- * and its output is returned.
- * Consider to use File.binwrite to disable the behavior of subprocess invocation.
+ * When called from class \IO (but not subclasses of \IO),
+ * this method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
*
- * See also IO.read for details about +name+ and open_args.
*/
static VALUE
@@ -11123,15 +12387,15 @@ rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
struct copy_stream_struct {
VALUE src;
VALUE dst;
- off_t copy_length; /* (off_t)-1 if not specified */
- off_t src_offset; /* (off_t)-1 if not specified */
+ rb_off_t copy_length; /* (rb_off_t)-1 if not specified */
+ rb_off_t src_offset; /* (rb_off_t)-1 if not specified */
- int src_fd;
- int dst_fd;
+ rb_io_t *src_fptr;
+ rb_io_t *dst_fptr;
unsigned close_src : 1;
unsigned close_dst : 1;
int error_no;
- off_t total;
+ rb_off_t total;
const char *syserr;
const char *notimp;
VALUE th;
@@ -11163,32 +12427,32 @@ maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
#if defined(ERESTART)
case ERESTART:
#endif
- if (rb_thread_interrupted(stp->th)) {
+ if (rb_thread_interrupted(stp->th)) {
if (has_gvl)
rb_thread_execute_interrupts(stp->th);
else
rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
}
- return TRUE;
+ return TRUE;
}
return FALSE;
}
-struct wait_for_single_fd {
+struct fiber_scheduler_wait_for_arguments {
VALUE scheduler;
- int fd;
+ rb_io_t *fptr;
short events;
VALUE result;
};
static void *
-rb_thread_fiber_scheduler_wait_for_single_fd(void * _args)
+fiber_scheduler_wait_for(void * _arguments)
{
- struct wait_for_single_fd *args = (struct wait_for_single_fd *)_args;
+ struct fiber_scheduler_wait_for_arguments *arguments = (struct fiber_scheduler_wait_for_arguments *)_arguments;
- args->result = rb_fiber_scheduler_io_wait(args->scheduler, io_from_fd(args->fd), INT2NUM(args->events), Qnil);
+ arguments->result = rb_fiber_scheduler_io_wait(arguments->scheduler, arguments->fptr->self, INT2NUM(arguments->events), RUBY_IO_TIMEOUT_DEFAULT);
return NULL;
}
@@ -11198,34 +12462,50 @@ rb_thread_fiber_scheduler_wait_for_single_fd(void * _args)
STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
static int
-nogvl_wait_for_single_fd(VALUE th, int fd, short events)
+nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval *timeout)
{
VALUE scheduler = rb_fiber_scheduler_current_for_thread(th);
if (scheduler != Qnil) {
- struct wait_for_single_fd args = {.scheduler = scheduler, .fd = fd, .events = events};
- rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for_single_fd, &args);
+ struct fiber_scheduler_wait_for_arguments args = {.scheduler = scheduler, .fptr = fptr, .events = events};
+ rb_thread_call_with_gvl(fiber_scheduler_wait_for, &args);
return RTEST(args.result);
}
+ int fd = fptr->fd;
+ if (fd == -1) return 0;
+
struct pollfd fds;
fds.fd = fd;
fds.events = events;
- return poll(&fds, 1, -1);
+ int timeout_milliseconds = -1;
+
+ if (timeout) {
+ timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
+ }
+
+ return poll(&fds, 1, timeout_milliseconds);
}
#else /* !USE_POLL */
# define IOWAIT_SYSCALL "select"
static int
-nogvl_wait_for_single_fd(VALUE th, int fd, short events)
+nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval *timeout)
{
VALUE scheduler = rb_fiber_scheduler_current_for_thread(th);
if (scheduler != Qnil) {
- struct wait_for_single_fd args = {.scheduler = scheduler, .fd = fd, .events = events};
- rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for_single_fd, &args);
+ struct fiber_scheduler_wait_for_arguments args = {.scheduler = scheduler, .fptr = fptr, .events = events};
+ rb_thread_call_with_gvl(fiber_scheduler_wait_for, &args);
return RTEST(args.result);
}
+ int fd = fptr->fd;
+
+ if (fd == -1) {
+ errno = EBADF;
+ return -1;
+ }
+
rb_fdset_t fds;
int ret;
@@ -11234,16 +12514,18 @@ nogvl_wait_for_single_fd(VALUE th, int fd, short events)
switch (events) {
case RB_WAITFD_IN:
- ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
+ ret = rb_fd_select(fd + 1, &fds, 0, 0, timeout);
break;
case RB_WAITFD_OUT:
- ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
+ ret = rb_fd_select(fd + 1, 0, &fds, 0, timeout);
break;
default:
- VM_UNREACHABLE(nogvl_wait_for_single_fd);
+ VM_UNREACHABLE(nogvl_wait_for);
}
rb_fd_term(&fds);
+
+ // On timeout, this returns 0.
return ret;
}
#endif /* !USE_POLL */
@@ -11258,7 +12540,7 @@ maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
ret = RB_NUM2INT(rb_io_wait(stp->src, RB_INT2NUM(RUBY_IO_READABLE), Qnil));
}
else {
- ret = nogvl_wait_for_single_fd(stp->th, stp->src_fd, RB_WAITFD_IN);
+ ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
}
} while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
@@ -11276,7 +12558,7 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
int ret;
do {
- ret = nogvl_wait_for_single_fd(stp->th, stp->dst_fd, RB_WAITFD_OUT);
+ ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
} while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
if (ret < 0) {
@@ -11290,7 +12572,7 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
#ifdef USE_COPY_FILE_RANGE
static ssize_t
-simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
+simple_copy_file_range(int in_fd, rb_off_t *in_offset, int out_fd, rb_off_t *out_offset, size_t count, unsigned int flags)
{
#ifdef HAVE_COPY_FILE_RANGE
return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
@@ -11303,47 +12585,47 @@ static int
nogvl_copy_file_range(struct copy_stream_struct *stp)
{
ssize_t ss;
- off_t src_size;
- off_t copy_length, src_offset, *src_offset_ptr;
+ rb_off_t src_size;
+ rb_off_t copy_length, src_offset, *src_offset_ptr;
if (!S_ISREG(stp->src_stat.st_mode))
return 0;
src_size = stp->src_stat.st_size;
src_offset = stp->src_offset;
- if (src_offset >= (off_t)0) {
- src_offset_ptr = &src_offset;
+ if (src_offset >= (rb_off_t)0) {
+ src_offset_ptr = &src_offset;
}
else {
- src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
+ src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
}
copy_length = stp->copy_length;
- if (copy_length < (off_t)0) {
- if (src_offset < (off_t)0) {
- off_t current_offset;
+ if (copy_length < (rb_off_t)0) {
+ if (src_offset < (rb_off_t)0) {
+ rb_off_t current_offset;
errno = 0;
- current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
- if (current_offset < (off_t)0 && errno) {
+ current_offset = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
+ if (current_offset < (rb_off_t)0 && errno) {
stp->syserr = "lseek";
stp->error_no = errno;
return (int)current_offset;
}
copy_length = src_size - current_offset;
- }
- else {
+ }
+ else {
copy_length = src_size - src_offset;
- }
+ }
}
retry_copy_file_range:
# if SIZEOF_OFF_T > SIZEOF_SIZE_T
/* we are limited by the 32-bit ssize_t return value on 32-bit */
- ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
+ ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
# else
ss = (ssize_t)copy_length;
# endif
- ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
+ ss = simple_copy_file_range(stp->src_fptr->fd, src_offset_ptr, stp->dst_fptr->fd, NULL, ss, 0);
if (0 < ss) {
stp->total += ss;
copy_length -= ss;
@@ -11352,39 +12634,39 @@ nogvl_copy_file_range(struct copy_stream_struct *stp)
}
}
if (ss < 0) {
- if (maygvl_copy_stream_continue_p(0, stp)) {
+ if (maygvl_copy_stream_continue_p(0, stp)) {
goto retry_copy_file_range;
- }
+ }
switch (errno) {
- case EINVAL:
- case EPERM: /* copy_file_range(2) doesn't exist (may happen in
- docker container) */
+ case EINVAL:
+ case EPERM: /* copy_file_range(2) doesn't exist (may happen in
+ docker container) */
#ifdef ENOSYS
- case ENOSYS:
+ case ENOSYS:
#endif
#ifdef EXDEV
- case EXDEV: /* in_fd and out_fd are not on the same filesystem */
+ case EXDEV: /* in_fd and out_fd are not on the same filesystem */
#endif
return 0;
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
#endif
{
int ret = nogvl_copy_stream_wait_write(stp);
if (ret < 0) return ret;
}
goto retry_copy_file_range;
- case EBADF:
- {
- int e = errno;
- int flags = fcntl(stp->dst_fd, F_GETFL);
+ case EBADF:
+ {
+ int e = errno;
+ int flags = fcntl(stp->dst_fptr->fd, F_GETFL);
- if (flags != -1 && flags & O_APPEND) {
- return 0;
- }
- errno = e;
- }
+ if (flags != -1 && flags & O_APPEND) {
+ return 0;
+ }
+ errno = e;
+ }
}
stp->syserr = "copy_file_range";
stp->error_no = errno;
@@ -11398,11 +12680,11 @@ nogvl_copy_file_range(struct copy_stream_struct *stp)
static int
nogvl_fcopyfile(struct copy_stream_struct *stp)
{
- off_t cur, ss = 0;
- const off_t src_offset = stp->src_offset;
+ rb_off_t cur, ss = 0;
+ const rb_off_t src_offset = stp->src_offset;
int ret;
- if (stp->copy_length >= (off_t)0) {
+ if (stp->copy_length >= (rb_off_t)0) {
/* copy_length can't be specified in fcopyfile(3) */
return 0;
}
@@ -11412,40 +12694,47 @@ nogvl_fcopyfile(struct copy_stream_struct *stp)
if (!S_ISREG(stp->dst_stat.st_mode))
return 0;
- if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
+ if (lseek(stp->dst_fptr->fd, 0, SEEK_CUR) > (rb_off_t)0) /* if dst IO was already written */
return 0;
+ if (fcntl(stp->dst_fptr->fd, F_GETFL) & O_APPEND) {
+ /* fcopyfile(3) appends src IO to dst IO and then truncates
+ * dst IO to src IO's original size. */
+ rb_off_t end = lseek(stp->dst_fptr->fd, 0, SEEK_END);
+ lseek(stp->dst_fptr->fd, 0, SEEK_SET);
+ if (end > (rb_off_t)0) return 0;
+ }
- if (src_offset > (off_t)0) {
- off_t r;
+ if (src_offset > (rb_off_t)0) {
+ rb_off_t r;
/* get current offset */
errno = 0;
- cur = lseek(stp->src_fd, 0, SEEK_CUR);
- if (cur < (off_t)0 && errno) {
+ cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
+ if (cur < (rb_off_t)0 && errno) {
stp->error_no = errno;
return 1;
}
errno = 0;
- r = lseek(stp->src_fd, src_offset, SEEK_SET);
- if (r < (off_t)0 && errno) {
+ r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET);
+ if (r < (rb_off_t)0 && errno) {
stp->error_no = errno;
return 1;
}
}
stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
- ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
+ ret = fcopyfile(stp->src_fptr->fd, stp->dst_fptr->fd, stp->copyfile_state, COPYFILE_DATA);
copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
if (ret == 0) { /* success */
stp->total = ss;
- if (src_offset > (off_t)0) {
- off_t r;
+ if (src_offset > (rb_off_t)0) {
+ rb_off_t r;
errno = 0;
/* reset offset */
- r = lseek(stp->src_fd, cur, SEEK_SET);
- if (r < (off_t)0 && errno) {
+ r = lseek(stp->src_fptr->fd, cur, SEEK_SET);
+ if (r < (rb_off_t)0 && errno) {
stp->error_no = errno;
return 1;
}
@@ -11476,7 +12765,7 @@ nogvl_fcopyfile(struct copy_stream_struct *stp)
# endif
static ssize_t
-simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
+simple_sendfile(int out_fd, int in_fd, rb_off_t *offset, rb_off_t count)
{
return sendfile(out_fd, in_fd, offset, (size_t)count);
}
@@ -11488,11 +12777,11 @@ simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
# define USE_SENDFILE
static ssize_t
-simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
+simple_sendfile(int out_fd, int in_fd, rb_off_t *offset, rb_off_t count)
{
int r;
- off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
- off_t sbytes;
+ rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
+ rb_off_t sbytes;
# ifdef __APPLE__
r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
sbytes = count;
@@ -11501,10 +12790,10 @@ simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
# endif
if (r != 0 && sbytes == 0) return r;
if (offset) {
- *offset += sbytes;
+ *offset += sbytes;
}
else {
- lseek(in_fd, sbytes, SEEK_CUR);
+ lseek(in_fd, sbytes, SEEK_CUR);
}
return (ssize_t)sbytes;
}
@@ -11518,9 +12807,9 @@ static int
nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
{
ssize_t ss;
- off_t src_size;
- off_t copy_length;
- off_t src_offset;
+ rb_off_t src_size;
+ rb_off_t copy_length;
+ rb_off_t src_offset;
int use_pread;
if (!S_ISREG(stp->src_stat.st_mode))
@@ -11529,21 +12818,21 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
src_size = stp->src_stat.st_size;
#ifndef __linux__
if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
- return 0;
+ return 0;
#endif
src_offset = stp->src_offset;
- use_pread = src_offset >= (off_t)0;
+ use_pread = src_offset >= (rb_off_t)0;
copy_length = stp->copy_length;
- if (copy_length < (off_t)0) {
+ if (copy_length < (rb_off_t)0) {
if (use_pread)
copy_length = src_size - src_offset;
else {
- off_t cur;
+ rb_off_t cur;
errno = 0;
- cur = lseek(stp->src_fd, 0, SEEK_CUR);
- if (cur < (off_t)0 && errno) {
+ cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
+ if (cur < (rb_off_t)0 && errno) {
stp->syserr = "lseek";
stp->error_no = errno;
return (int)cur;
@@ -11555,15 +12844,15 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
retry_sendfile:
# if SIZEOF_OFF_T > SIZEOF_SIZE_T
/* we are limited by the 32-bit ssize_t return value on 32-bit */
- ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
+ ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
# else
ss = (ssize_t)copy_length;
# endif
if (use_pread) {
- ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
+ ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, &src_offset, ss);
}
else {
- ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
+ ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, NULL, ss);
}
if (0 < ss) {
stp->total += ss;
@@ -11573,28 +12862,28 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
}
}
if (ss < 0) {
- if (maygvl_copy_stream_continue_p(0, stp))
- goto retry_sendfile;
+ if (maygvl_copy_stream_continue_p(0, stp))
+ goto retry_sendfile;
switch (errno) {
- case EINVAL:
+ case EINVAL:
#ifdef ENOSYS
- case ENOSYS:
+ case ENOSYS:
#endif
#ifdef EOPNOTSUP
- /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
- see also: [Feature #16965] */
- case 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
- case EWOULDBLOCK:
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
#endif
{
int ret;
#ifndef __linux__
/*
- * Linux requires stp->src_fd to be a mmap-able (regular) file,
+ * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file,
* select() reports regular files to always be "ready", so
* there is no need to select() on it.
* Other OSes may have the same limitation for sendfile() which
@@ -11617,25 +12906,25 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
#endif
static ssize_t
-maygvl_read(int has_gvl, int fd, void *buf, size_t count)
+maygvl_read(int has_gvl, rb_io_t *fptr, void *buf, size_t count)
{
if (has_gvl)
- return rb_read_internal(fd, buf, count);
+ return rb_io_read_memory(fptr, buf, count);
else
- return read(fd, buf, count);
+ return read(fptr->fd, buf, count);
}
static ssize_t
-maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
+maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, rb_off_t offset)
{
ssize_t ss;
retry_read:
- if (offset < (off_t)0) {
- ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
+ if (offset < (rb_off_t)0) {
+ ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
}
else {
#ifdef HAVE_PREAD
- ss = pread(stp->src_fd, buf, len, offset);
+ ss = pread(stp->src_fptr->fd, buf, len, offset);
#else
stp->notimp = "pread";
return -1;
@@ -11645,12 +12934,12 @@ maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf,
return 0;
}
if (ss < 0) {
- if (maygvl_copy_stream_continue_p(has_gvl, stp))
- goto retry_read;
+ if (maygvl_copy_stream_continue_p(has_gvl, stp))
+ goto retry_read;
switch (errno) {
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
#endif
{
int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
@@ -11658,12 +12947,12 @@ maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf,
}
goto retry_read;
#ifdef ENOSYS
- case ENOSYS:
+ case ENOSYS:
stp->notimp = "pread";
return ss;
#endif
}
- stp->syserr = offset < (off_t)0 ? "read" : "pread";
+ stp->syserr = offset < (rb_off_t)0 ? "read" : "pread";
stp->error_no = errno;
}
return ss;
@@ -11675,11 +12964,11 @@ nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
ssize_t ss;
int off = 0;
while (len) {
- ss = write(stp->dst_fd, buf+off, len);
+ ss = write(stp->dst_fptr->fd, buf+off, len);
if (ss < 0) {
if (maygvl_copy_stream_continue_p(0, stp))
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ if (io_again_p(errno)) {
int ret = nogvl_copy_stream_wait_write(stp);
if (ret < 0) return ret;
continue;
@@ -11702,31 +12991,31 @@ nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
size_t len;
ssize_t ss;
int ret;
- off_t copy_length;
+ rb_off_t copy_length;
+ rb_off_t src_offset;
int use_eof;
- off_t src_offset;
int use_pread;
copy_length = stp->copy_length;
- use_eof = copy_length < (off_t)0;
+ use_eof = copy_length < (rb_off_t)0;
src_offset = stp->src_offset;
- use_pread = src_offset >= (off_t)0;
+ use_pread = src_offset >= (rb_off_t)0;
if (use_pread && stp->close_src) {
- off_t r;
- errno = 0;
- r = lseek(stp->src_fd, src_offset, SEEK_SET);
- if (r < (off_t)0 && errno) {
+ rb_off_t r;
+ errno = 0;
+ r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET);
+ if (r < (rb_off_t)0 && errno) {
stp->syserr = "lseek";
stp->error_no = errno;
return;
}
- src_offset = (off_t)-1;
+ src_offset = (rb_off_t)-1;
use_pread = 0;
}
while (use_eof || 0 < copy_length) {
- if (!use_eof && copy_length < (off_t)sizeof(buf)) {
+ if (!use_eof && copy_length < (rb_off_t)sizeof(buf)) {
len = (size_t)copy_length;
}
else {
@@ -11738,7 +13027,7 @@ nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
src_offset += ss;
}
else {
- ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
+ ss = maygvl_copy_stream_read(0, stp, buf, len, (rb_off_t)-1);
}
if (ss <= 0) /* EOF or error */
return;
@@ -11763,7 +13052,7 @@ nogvl_copy_stream_func(void *arg)
#ifdef USE_COPY_FILE_RANGE
ret = nogvl_copy_file_range(stp);
if (ret != 0)
- goto finish; /* error or success */
+ goto finish; /* error or success */
#endif
#ifdef HAVE_FCOPYFILE
@@ -11793,30 +13082,31 @@ copy_stream_fallback_body(VALUE arg)
const int buflen = 16*1024;
VALUE n;
VALUE buf = rb_str_buf_new(buflen);
- off_t rest = stp->copy_length;
- off_t off = stp->src_offset;
+ rb_off_t rest = stp->copy_length;
+ rb_off_t off = stp->src_offset;
ID read_method = id_readpartial;
- if (stp->src_fd < 0) {
- if (!rb_respond_to(stp->src, read_method)) {
- read_method = id_read;
- }
+ if (!stp->src_fptr) {
+ if (!rb_respond_to(stp->src, read_method)) {
+ read_method = id_read;
+ }
}
while (1) {
long numwrote;
long l;
- if (stp->copy_length < (off_t)0) {
+ rb_str_make_independent(buf);
+ if (stp->copy_length < (rb_off_t)0) {
l = buflen;
}
else {
- if (rest == 0) {
- rb_str_resize(buf, 0);
- break;
- }
+ if (rest == 0) {
+ rb_str_resize(buf, 0);
+ break;
+ }
l = buflen < rest ? buflen : (long)rest;
}
- if (stp->src_fd < 0) {
+ if (!stp->src_fptr) {
VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
if (read_method == id_read && NIL_P(rc))
@@ -11831,16 +13121,16 @@ copy_stream_fallback_body(VALUE arg)
return Qnil;
if (ss == 0)
rb_eof_error();
- if (off >= (off_t)0)
+ if (off >= (rb_off_t)0)
off += ss;
}
n = rb_io_write(stp->dst, buf);
numwrote = NUM2LONG(n);
stp->total += numwrote;
rest -= numwrote;
- if (read_method == id_read && RSTRING_LEN(buf) == 0) {
- break;
- }
+ if (read_method == id_read && RSTRING_LEN(buf) == 0) {
+ break;
+ }
}
return Qnil;
@@ -11849,8 +13139,8 @@ copy_stream_fallback_body(VALUE arg)
static VALUE
copy_stream_fallback(struct copy_stream_struct *stp)
{
- if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) {
- rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
+ if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
+ rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
}
rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
(VALUE (*) (VALUE, VALUE))0, (VALUE)0,
@@ -11863,127 +13153,121 @@ copy_stream_body(VALUE arg)
{
struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
VALUE src_io = stp->src, dst_io = stp->dst;
- rb_io_t *src_fptr = 0, *dst_fptr = 0;
- int src_fd, dst_fd;
const int common_oflags = 0
#ifdef O_NOCTTY
- | O_NOCTTY
+ | O_NOCTTY
#endif
- ;
+ ;
stp->th = rb_thread_current();
stp->total = 0;
if (src_io == argf ||
- !(RB_TYPE_P(src_io, T_FILE) ||
- RB_TYPE_P(src_io, T_STRING) ||
- rb_respond_to(src_io, rb_intern("to_path")))) {
- src_fd = -1;
+ !(RB_TYPE_P(src_io, T_FILE) ||
+ RB_TYPE_P(src_io, T_STRING) ||
+ rb_respond_to(src_io, rb_intern("to_path")))) {
+ stp->src_fptr = NULL;
}
else {
int stat_ret;
- VALUE tmp_io = rb_io_check_io(src_io);
- if (!NIL_P(tmp_io)) {
- src_io = tmp_io;
- }
- else if (!RB_TYPE_P(src_io, T_FILE)) {
- VALUE args[2];
- FilePathValue(src_io);
- args[0] = src_io;
- args[1] = INT2NUM(O_RDONLY|common_oflags);
- src_io = rb_class_new_instance(2, args, rb_cFile);
- stp->src = src_io;
- stp->close_src = 1;
- }
- GetOpenFile(src_io, src_fptr);
- rb_io_check_byte_readable(src_fptr);
- src_fd = src_fptr->fd;
-
- stat_ret = fstat(src_fd, &stp->src_stat);
+ VALUE tmp_io = rb_io_check_io(src_io);
+ if (!NIL_P(tmp_io)) {
+ src_io = tmp_io;
+ }
+ else if (!RB_TYPE_P(src_io, T_FILE)) {
+ VALUE args[2];
+ FilePathValue(src_io);
+ args[0] = src_io;
+ args[1] = INT2NUM(O_RDONLY|common_oflags);
+ src_io = rb_class_new_instance(2, args, rb_cFile);
+ stp->src = src_io;
+ stp->close_src = 1;
+ }
+ RB_IO_POINTER(src_io, stp->src_fptr);
+ rb_io_check_byte_readable(stp->src_fptr);
+
+ stat_ret = fstat(stp->src_fptr->fd, &stp->src_stat);
if (stat_ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return Qnil;
}
}
- stp->src_fd = src_fd;
if (dst_io == argf ||
- !(RB_TYPE_P(dst_io, T_FILE) ||
- RB_TYPE_P(dst_io, T_STRING) ||
- rb_respond_to(dst_io, rb_intern("to_path")))) {
- dst_fd = -1;
+ !(RB_TYPE_P(dst_io, T_FILE) ||
+ RB_TYPE_P(dst_io, T_STRING) ||
+ rb_respond_to(dst_io, rb_intern("to_path")))) {
+ stp->dst_fptr = NULL;
}
else {
int stat_ret;
VALUE tmp_io = rb_io_check_io(dst_io);
- if (!NIL_P(tmp_io)) {
- dst_io = GetWriteIO(tmp_io);
- }
- else if (!RB_TYPE_P(dst_io, T_FILE)) {
- VALUE args[3];
- FilePathValue(dst_io);
- args[0] = dst_io;
- args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
- args[2] = INT2FIX(0666);
- dst_io = rb_class_new_instance(3, args, rb_cFile);
- stp->dst = dst_io;
- stp->close_dst = 1;
- }
- else {
- dst_io = GetWriteIO(dst_io);
- stp->dst = dst_io;
- }
- GetOpenFile(dst_io, dst_fptr);
- rb_io_check_writable(dst_fptr);
- dst_fd = dst_fptr->fd;
-
- stat_ret = fstat(dst_fd, &stp->dst_stat);
+ if (!NIL_P(tmp_io)) {
+ dst_io = GetWriteIO(tmp_io);
+ }
+ else if (!RB_TYPE_P(dst_io, T_FILE)) {
+ VALUE args[3];
+ FilePathValue(dst_io);
+ args[0] = dst_io;
+ args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
+ args[2] = INT2FIX(0666);
+ dst_io = rb_class_new_instance(3, args, rb_cFile);
+ stp->dst = dst_io;
+ stp->close_dst = 1;
+ }
+ else {
+ dst_io = GetWriteIO(dst_io);
+ stp->dst = dst_io;
+ }
+ RB_IO_POINTER(dst_io, stp->dst_fptr);
+ rb_io_check_writable(stp->dst_fptr);
+
+ stat_ret = fstat(stp->dst_fptr->fd, &stp->dst_stat);
if (stat_ret < 0) {
stp->syserr = "fstat";
stp->error_no = errno;
return Qnil;
}
}
- stp->dst_fd = dst_fd;
#ifdef O_BINARY
- if (src_fptr)
- SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
+ if (stp->src_fptr)
+ SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
#endif
- if (dst_fptr)
- io_ascii8bit_binmode(dst_fptr);
+ if (stp->dst_fptr)
+ io_ascii8bit_binmode(stp->dst_fptr);
- if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) {
- size_t len = src_fptr->rbuf.len;
+ if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->rbuf.len) {
+ size_t len = stp->src_fptr->rbuf.len;
VALUE str;
- if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
+ if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)len) {
len = (size_t)stp->copy_length;
}
str = rb_str_buf_new(len);
rb_str_resize(str,len);
- read_buffered_data(RSTRING_PTR(str), len, src_fptr);
- if (dst_fptr) { /* IO or filename */
- if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
- rb_sys_fail_on_write(dst_fptr);
+ read_buffered_data(RSTRING_PTR(str), len, stp->src_fptr);
+ if (stp->dst_fptr) { /* IO or filename */
+ if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0)
+ rb_sys_fail_on_write(stp->dst_fptr);
}
else /* others such as StringIO */
- rb_io_write(dst_io, str);
+ rb_io_write(dst_io, str);
rb_str_resize(str, 0);
stp->total += len;
- if (stp->copy_length >= (off_t)0)
+ if (stp->copy_length >= (rb_off_t)0)
stp->copy_length -= len;
}
- if (dst_fptr && io_fflush(dst_fptr) < 0) {
- rb_raise(rb_eIOError, "flush failed");
+ if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
+ rb_raise(rb_eIOError, "flush failed");
}
if (stp->copy_length == 0)
return Qnil;
- if (src_fd < 0 || dst_fd < 0) {
+ if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
return copy_stream_fallback(stp);
}
@@ -12012,41 +13296,60 @@ copy_stream_finalize(VALUE arg)
rb_syserr_fail(stp->error_no, stp->syserr);
}
if (stp->notimp) {
- rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
+ rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
}
return Qnil;
}
/*
* call-seq:
- * IO.copy_stream(src, dst)
- * IO.copy_stream(src, dst, copy_length)
- * IO.copy_stream(src, dst, copy_length, src_offset)
+ * IO.copy_stream(src, dst, src_length = nil, src_offset = 0) -> integer
+ *
+ * Copies from the given +src+ to the given +dst+,
+ * returning the number of bytes copied.
+ *
+ * - The given +src+ must be one of the following:
+ *
+ * - The path to a readable file, from which source data is to be read.
+ * - An \IO-like object, opened for reading and capable of responding
+ * to method +:readpartial+ or method +:read+.
+ *
+ * - The given +dst+ must be one of the following:
+ *
+ * - The path to a writable file, to which data is to be written.
+ * - An \IO-like object, opened for writing and capable of responding
+ * to method +:write+.
*
- * IO.copy_stream copies <i>src</i> to <i>dst</i>.
- * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
- * IO-like object for <i>src</i> should have #readpartial or #read
- * method. IO-like object for <i>dst</i> should have #write method.
- * (Specialized mechanisms, such as sendfile system call, may be used
- * on appropriate situation.)
+ * The examples here use file <tt>t.txt</tt> as source:
*
- * This method returns the number of bytes copied.
+ * File.read('t.txt')
+ * # => "First line\nSecond line\n\nThird line\nFourth line\n"
+ * File.read('t.txt').size # => 47
*
- * If optional arguments are not given,
- * the start position of the copy is
- * the beginning of the filename or
- * the current file offset of the IO.
- * The end position of the copy is the end of file.
+ * If only arguments +src+ and +dst+ are given,
+ * the entire source stream is copied:
*
- * If <i>copy_length</i> is given,
- * No more than <i>copy_length</i> bytes are copied.
+ * # Paths.
+ * IO.copy_stream('t.txt', 't.tmp') # => 47
*
- * If <i>src_offset</i> is given,
- * it specifies the start position of the copy.
+ * # IOs (recall that a File is also an IO).
+ * src_io = File.open('t.txt', 'r') # => #<File:t.txt>
+ * dst_io = File.open('t.tmp', 'w') # => #<File:t.tmp>
+ * IO.copy_stream(src_io, dst_io) # => 47
+ * src_io.close
+ * dst_io.close
*
- * When <i>src_offset</i> is specified and
- * <i>src</i> is an IO,
- * IO.copy_stream doesn't move the current file offset.
+ * With argument +src_length+ a non-negative integer,
+ * no more than that many bytes are copied:
+ *
+ * IO.copy_stream('t.txt', 't.tmp', 10) # => 10
+ * File.read('t.tmp') # => "First line"
+ *
+ * With argument +src_offset+ also given,
+ * the source stream is read beginning at that offset:
+ *
+ * IO.copy_stream('t.txt', 't.tmp', 11, 11) # => 11
+ * IO.read('t.tmp') # => "Second line"
*
*/
static VALUE
@@ -12062,13 +13365,16 @@ rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
st.src = src;
st.dst = dst;
+ st.src_fptr = NULL;
+ st.dst_fptr = NULL;
+
if (NIL_P(length))
- st.copy_length = (off_t)-1;
+ st.copy_length = (rb_off_t)-1;
else
st.copy_length = NUM2OFFT(length);
if (NIL_P(src_offset))
- st.src_offset = (off_t)-1;
+ st.src_offset = (rb_off_t)-1;
else
st.src_offset = NUM2OFFT(src_offset);
@@ -12079,64 +13385,74 @@ rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * io.external_encoding -> encoding
+ * external_encoding -> encoding or nil
+ *
+ * Returns the Encoding object that represents the encoding of the stream,
+ * or +nil+ if the stream is in write mode and no encoding is specified.
+ *
+ * See {Encodings}[rdoc-ref:File@Encodings].
*
- * Returns the Encoding object that represents the encoding of the file.
- * If _io_ is in write mode and no encoding is specified, returns +nil+.
*/
static VALUE
rb_io_external_encoding(VALUE io)
{
- rb_io_t *fptr;
+ rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
- GetOpenFile(io, fptr);
if (fptr->encs.enc2) {
- return rb_enc_from_encoding(fptr->encs.enc2);
+ return rb_enc_from_encoding(fptr->encs.enc2);
}
if (fptr->mode & FMODE_WRITABLE) {
- if (fptr->encs.enc)
- return rb_enc_from_encoding(fptr->encs.enc);
- return Qnil;
+ if (fptr->encs.enc)
+ return rb_enc_from_encoding(fptr->encs.enc);
+ return Qnil;
}
return rb_enc_from_encoding(io_read_encoding(fptr));
}
/*
* call-seq:
- * io.internal_encoding -> encoding
+ * internal_encoding -> encoding or nil
+ *
+ * Returns the Encoding object that represents the encoding of the internal string,
+ * if conversion is specified,
+ * or +nil+ otherwise.
+ *
+ * See {Encodings}[rdoc-ref:File@Encodings].
*
- * Returns the Encoding of the internal string if conversion is
- * specified. Otherwise returns +nil+.
*/
static VALUE
rb_io_internal_encoding(VALUE io)
{
- rb_io_t *fptr;
+ rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
- GetOpenFile(io, fptr);
if (!fptr->encs.enc2) return Qnil;
return rb_enc_from_encoding(io_read_encoding(fptr));
}
/*
* call-seq:
- * io.set_encoding(ext_enc) -> io
- * io.set_encoding("ext_enc:int_enc") -> io
- * io.set_encoding(ext_enc, int_enc) -> io
- * io.set_encoding("ext_enc:int_enc", opt) -> io
- * io.set_encoding(ext_enc, int_enc, opt) -> io
+ * set_encoding(ext_enc) -> self
+ * set_encoding(ext_enc, int_enc, **enc_opts) -> self
+ * set_encoding('ext_enc:int_enc', **enc_opts) -> self
+ *
+ * See {Encodings}[rdoc-ref:File@Encodings].
+ *
+ * Argument +ext_enc+, if given, must be an Encoding object;
+ * it is assigned as the encoding for the stream.
+ *
+ * Argument +int_enc+, if given, must be an Encoding object;
+ * it is assigned as the encoding for the internal string.
+ *
+ * Argument <tt>'ext_enc:int_enc'</tt>, if given, is a string
+ * containing two colon-separated encoding names;
+ * corresponding Encoding objects are assigned as the external
+ * and internal encodings for the stream.
+ *
+ * Optional keyword arguments +enc_opts+ specify
+ * {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
*
- * If single argument is specified, read string from io is tagged
- * with the encoding specified. If encoding is a colon separated two
- * encoding names "A:B", the read string is converted from encoding A
- * (external encoding) to encoding B (internal encoding), then tagged
- * with B. If two arguments are specified, those must be encoding
- * objects or encoding names, and the first one is the external encoding, and the
- * second one is the internal encoding.
- * If the external encoding and the internal encoding is specified,
- * optional hash argument specify the conversion option.
*/
static VALUE
@@ -12160,6 +13476,18 @@ rb_stdio_set_default_encoding(void)
{
VALUE val = Qnil;
+#ifdef _WIN32
+ if (isatty(fileno(stdin))) {
+ rb_encoding *external = rb_locale_encoding();
+ rb_encoding *internal = rb_default_internal_encoding();
+ if (!internal) internal = rb_default_external_encoding();
+ io_encoding_set(RFILE(rb_stdin)->fptr,
+ rb_enc_from_encoding(external),
+ rb_enc_from_encoding(internal),
+ Qnil);
+ }
+ else
+#endif
rb_io_set_encoding(1, &val, rb_stdin);
rb_io_set_encoding(1, &val, rb_stdout);
rb_io_set_encoding(1, &val, rb_stderr);
@@ -12171,16 +13499,27 @@ global_argf_p(VALUE arg)
return arg == argf;
}
+typedef VALUE (*argf_encoding_func)(VALUE io);
+
+static VALUE
+argf_encoding(VALUE argf, argf_encoding_func func)
+{
+ if (!RTEST(ARGF.current_file)) {
+ return rb_enc_default_external();
+ }
+ return func(rb_io_check_io(ARGF.current_file));
+}
+
/*
* call-seq:
* ARGF.external_encoding -> encoding
*
- * Returns the external encoding for files read from +ARGF+ as an +Encoding+
+ * Returns the external encoding for files read from ARGF as an Encoding
* object. The external encoding is the encoding of the text as stored in a
- * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
- * to represent this text within Ruby.
+ * file. Contrast with ARGF.internal_encoding, which is the encoding used to
+ * represent this text within Ruby.
*
- * To set the external encoding use +ARGF.set_encoding+.
+ * To set the external encoding use ARGF.set_encoding.
*
* For example:
*
@@ -12190,20 +13529,17 @@ global_argf_p(VALUE arg)
static VALUE
argf_external_encoding(VALUE argf)
{
- if (!RTEST(ARGF.current_file)) {
- return rb_enc_from_encoding(rb_default_external_encoding());
- }
- return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
+ return argf_encoding(argf, rb_io_external_encoding);
}
/*
* call-seq:
* ARGF.internal_encoding -> encoding
*
- * Returns the internal encoding for strings read from +ARGF+ as an
- * +Encoding+ object.
+ * Returns the internal encoding for strings read from ARGF as an
+ * Encoding object.
*
- * If +ARGF.set_encoding+ has been called with two encoding names, the second
+ * If ARGF.set_encoding has been called with two encoding names, the second
* is returned. Otherwise, if +Encoding.default_external+ has been set, that
* value is returned. Failing that, if a default external encoding was
* specified on the command-line, that value is used. If the encoding is
@@ -12212,10 +13548,7 @@ argf_external_encoding(VALUE argf)
static VALUE
argf_internal_encoding(VALUE argf)
{
- if (!RTEST(ARGF.current_file)) {
- return rb_enc_from_encoding(rb_default_external_encoding());
- }
- return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
+ return argf_encoding(argf, rb_io_internal_encoding);
}
/*
@@ -12239,7 +13572,7 @@ argf_internal_encoding(VALUE argf)
* specifies the internal encoding.
*
* If the external encoding and the internal encoding are specified, the
- * optional +Hash+ argument can be used to adjust the conversion process. The
+ * optional Hash argument can be used to adjust the conversion process. The
* structure of this hash is explained in the String#encode documentation.
*
* For example:
@@ -12255,7 +13588,7 @@ argf_set_encoding(int argc, VALUE *argv, VALUE argf)
rb_io_t *fptr;
if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to set encoding");
+ rb_raise(rb_eArgError, "no stream to set encoding");
}
rb_io_set_encoding(argc, argv, ARGF.current_file);
GetOpenFile(ARGF.current_file, fptr);
@@ -12268,7 +13601,7 @@ argf_set_encoding(int argc, VALUE *argv, VALUE argf)
* ARGF.tell -> Integer
* ARGF.pos -> Integer
*
- * Returns the current offset (in bytes) of the current file in +ARGF+.
+ * Returns the current offset (in bytes) of the current file in ARGF.
*
* ARGF.pos #=> 0
* ARGF.gets #=> "This is line one\n"
@@ -12279,7 +13612,7 @@ static VALUE
argf_tell(VALUE argf)
{
if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to tell");
+ rb_raise(rb_eArgError, "no stream to tell");
}
ARGF_FORWARD(0, 0);
return rb_io_tell(ARGF.current_file);
@@ -12289,14 +13622,14 @@ argf_tell(VALUE argf)
* call-seq:
* ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
*
- * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
+ * Seeks to offset _amount_ (an Integer) in the ARGF stream according to
* the value of _whence_. See IO#seek for further details.
*/
static VALUE
argf_seek_m(int argc, VALUE *argv, VALUE argf)
{
if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to seek");
+ rb_raise(rb_eArgError, "no stream to seek");
}
ARGF_FORWARD(argc, argv);
return rb_io_seek_m(argc, argv, ARGF.current_file);
@@ -12306,7 +13639,7 @@ argf_seek_m(int argc, VALUE *argv, VALUE argf)
* call-seq:
* ARGF.pos = position -> Integer
*
- * Seeks to the position given by _position_ (in bytes) in +ARGF+.
+ * Seeks to the position given by _position_ (in bytes) in ARGF.
*
* For example:
*
@@ -12317,7 +13650,7 @@ static VALUE
argf_set_pos(VALUE argf, VALUE offset)
{
if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to set position");
+ rb_raise(rb_eArgError, "no stream to set position");
}
ARGF_FORWARD(1, &offset);
return rb_io_set_pos(ARGF.current_file, offset);
@@ -12328,7 +13661,7 @@ argf_set_pos(VALUE argf, VALUE offset)
* ARGF.rewind -> 0
*
* Positions the current file to the beginning of input, resetting
- * +ARGF.lineno+ to zero.
+ * ARGF.lineno to zero.
*
* ARGF.readline #=> "This is line one\n"
* ARGF.rewind #=> 0
@@ -12342,13 +13675,13 @@ argf_rewind(VALUE argf)
int old_lineno;
if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to rewind");
+ rb_raise(rb_eArgError, "no stream to rewind");
}
ARGF_FORWARD(0, 0);
old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
ret = rb_io_rewind(ARGF.current_file);
if (!global_argf_p(argf)) {
- ARGF.last_lineno = ARGF.lineno -= old_lineno;
+ ARGF.last_lineno = ARGF.lineno -= old_lineno;
}
return ret;
}
@@ -12359,7 +13692,7 @@ argf_rewind(VALUE argf)
* ARGF.to_i -> integer
*
* Returns an integer representing the numeric file descriptor for
- * the current file. Raises an +ArgumentError+ if there isn't a current file.
+ * the current file. Raises an ArgumentError if there isn't a current file.
*
* ARGF.fileno #=> 3
*/
@@ -12367,7 +13700,7 @@ static VALUE
argf_fileno(VALUE argf)
{
if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream");
+ rb_raise(rb_eArgError, "no stream");
}
ARGF_FORWARD(0, 0);
return rb_io_fileno(ARGF.current_file);
@@ -12377,8 +13710,8 @@ argf_fileno(VALUE argf)
* call-seq:
* ARGF.to_io -> IO
*
- * Returns an +IO+ object representing the current file. This will be a
- * +File+ object unless the current file is a stream such as STDIN.
+ * Returns an IO object representing the current file. This will be a
+ * File object unless the current file is a stream such as STDIN.
*
* For example:
*
@@ -12398,8 +13731,8 @@ argf_to_io(VALUE argf)
* ARGF.eof? -> true or false
* ARGF.eof -> true or false
*
- * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
- * no data to read. The stream must be opened for reading or an +IOError+
+ * Returns true if the current file in ARGF is at end of file, i.e. it has
+ * no data to read. The stream must be opened for reading or an IOError
* will be raised.
*
* $ echo "eof" | ruby argf.rb
@@ -12416,12 +13749,12 @@ argf_eof(VALUE argf)
{
next_argv();
if (RTEST(ARGF.current_file)) {
- if (ARGF.init_p == 0) return Qtrue;
- next_argv();
- ARGF_FORWARD(0, 0);
- if (rb_io_eof(ARGF.current_file)) {
- return Qtrue;
- }
+ if (ARGF.init_p == 0) return Qtrue;
+ next_argv();
+ ARGF_FORWARD(0, 0);
+ if (rb_io_eof(ARGF.current_file)) {
+ return Qtrue;
+ }
}
return Qfalse;
}
@@ -12482,39 +13815,39 @@ argf_read(int argc, VALUE *argv, VALUE argf)
rb_scan_args(argc, argv, "02", &length, &str);
if (!NIL_P(length)) {
- len = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[0]);
}
if (!NIL_P(str)) {
- StringValue(str);
- rb_str_resize(str,0);
- argv[1] = Qnil;
+ StringValue(str);
+ rb_str_resize(str,0);
+ argv[1] = Qnil;
}
retry:
if (!next_argv()) {
- return str;
+ return str;
}
if (ARGF_GENERIC_INPUT_P()) {
- tmp = argf_forward(argc, argv, argf);
+ tmp = argf_forward(argc, argv, argf);
}
else {
- tmp = io_read(argc, argv, ARGF.current_file);
+ tmp = io_read(argc, argv, ARGF.current_file);
}
if (NIL_P(str)) str = tmp;
else if (!NIL_P(tmp)) rb_str_append(str, tmp);
if (NIL_P(tmp) || NIL_P(length)) {
- if (ARGF.next_p != -1) {
- argf_close(argf);
- ARGF.next_p = 1;
- goto retry;
- }
+ if (ARGF.next_p != -1) {
+ argf_close(argf);
+ ARGF.next_p = 1;
+ goto retry;
+ }
}
else if (argc >= 1) {
- long slen = RSTRING_LEN(str);
- if (slen < len) {
+ long slen = RSTRING_LEN(str);
+ if (slen < len) {
argv[0] = LONG2NUM(len - slen);
- goto retry;
- }
+ goto retry;
+ }
}
return str;
}
@@ -12597,18 +13930,18 @@ argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
no_exception = no_exception_p(opts);
if (!next_argv()) {
- if (!NIL_P(str)) {
- rb_str_resize(str, 0);
- }
+ if (!NIL_P(str)) {
+ rb_str_resize(str, 0);
+ }
rb_eof_error();
}
if (ARGF_GENERIC_INPUT_P()) {
VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
- struct argf_call_arg arg;
- arg.argc = argc;
- arg.argv = argv;
- arg.argf = argf;
- tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
+ struct argf_call_arg arg;
+ arg.argc = argc;
+ arg.argv = argv;
+ arg.argf = argf;
+ tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
}
else {
@@ -12622,7 +13955,7 @@ argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
ARGF.next_p = 1;
if (RARRAY_LEN(ARGF.argv) == 0) {
return io_nonblock_eof(no_exception);
- }
+ }
if (NIL_P(str))
str = rb_str_new(NULL, 0);
return str;
@@ -12634,10 +13967,10 @@ argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
* call-seq:
* ARGF.getc -> String or nil
*
- * Reads the next character from +ARGF+ and returns it as a +String+. Returns
+ * Reads the next character from ARGF and returns it as a String. Returns
* +nil+ at the end of the stream.
*
- * +ARGF+ treats the files named on the command line as a single file created
+ * ARGF treats the files named on the command line as a single file created
* by concatenating their contents. After returning the last character of the
* first file, it returns the first character of the second file, and so on.
*
@@ -12661,15 +13994,15 @@ argf_getc(VALUE argf)
retry:
if (!next_argv()) return Qnil;
if (ARGF_GENERIC_INPUT_P()) {
- ch = forward_current(rb_intern("getc"), 0, 0);
+ ch = forward_current(rb_intern("getc"), 0, 0);
}
else {
- ch = rb_io_getc(ARGF.current_file);
+ ch = rb_io_getc(ARGF.current_file);
}
if (NIL_P(ch) && ARGF.next_p != -1) {
- argf_close(argf);
- ARGF.next_p = 1;
- goto retry;
+ argf_close(argf);
+ ARGF.next_p = 1;
+ goto retry;
}
return ch;
@@ -12679,7 +14012,7 @@ argf_getc(VALUE argf)
* call-seq:
* ARGF.getbyte -> Integer or nil
*
- * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
+ * Gets the next 8-bit byte (0..255) from ARGF. Returns +nil+ if called at
* the end of the stream.
*
* For example:
@@ -12701,15 +14034,15 @@ argf_getbyte(VALUE argf)
retry:
if (!next_argv()) return Qnil;
if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
- ch = forward_current(rb_intern("getbyte"), 0, 0);
+ ch = forward_current(rb_intern("getbyte"), 0, 0);
}
else {
- ch = rb_io_getbyte(ARGF.current_file);
+ ch = rb_io_getbyte(ARGF.current_file);
}
if (NIL_P(ch) && ARGF.next_p != -1) {
- argf_close(argf);
- ARGF.next_p = 1;
- goto retry;
+ argf_close(argf);
+ ARGF.next_p = 1;
+ goto retry;
}
return ch;
@@ -12719,8 +14052,8 @@ argf_getbyte(VALUE argf)
* call-seq:
* ARGF.readchar -> String or nil
*
- * Reads the next character from +ARGF+ and returns it as a +String+. Raises
- * an +EOFError+ after the last character of the last file has been read.
+ * Reads the next character from ARGF and returns it as a String. Raises
+ * an EOFError after the last character of the last file has been read.
*
* For example:
*
@@ -12741,15 +14074,15 @@ argf_readchar(VALUE argf)
retry:
if (!next_argv()) rb_eof_error();
if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
- ch = forward_current(rb_intern("getc"), 0, 0);
+ ch = forward_current(rb_intern("getc"), 0, 0);
}
else {
- ch = rb_io_getc(ARGF.current_file);
+ ch = rb_io_getc(ARGF.current_file);
}
if (NIL_P(ch) && ARGF.next_p != -1) {
- argf_close(argf);
- ARGF.next_p = 1;
- goto retry;
+ argf_close(argf);
+ ARGF.next_p = 1;
+ goto retry;
}
return ch;
@@ -12759,8 +14092,8 @@ argf_readchar(VALUE argf)
* call-seq:
* ARGF.readbyte -> Integer
*
- * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
- * an +EOFError+ after the last byte of the last file has been read.
+ * Reads the next 8-bit byte from ARGF and returns it as an Integer. Raises
+ * an EOFError after the last byte of the last file has been read.
*
* For example:
*
@@ -12781,7 +14114,7 @@ argf_readbyte(VALUE argf)
NEXT_ARGF_FORWARD(0, 0);
c = argf_getbyte(argf);
if (NIL_P(c)) {
- rb_eof_error();
+ rb_eof_error();
}
return c;
}
@@ -12794,7 +14127,7 @@ argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
const VALUE current = ARGF.current_file;
rb_yield_values2(argc, argv);
if (ARGF.init_p == -1 || current != ARGF.current_file) {
- rb_iter_break_value(Qundef);
+ rb_iter_break_value(Qundef);
}
return Qnil;
}
@@ -12807,14 +14140,14 @@ static void
argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
{
VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
- if (ret != Qundef) ARGF.next_p = 1;
+ if (!UNDEF_P(ret)) ARGF.next_p = 1;
}
static VALUE
argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
{
if (!global_argf_p(argf)) {
- ARGF.last_lineno = ++ARGF.lineno;
+ ARGF.last_lineno = ++ARGF.lineno;
}
return argf_block_call_i(i, argf, argc, argv, blockarg);
}
@@ -12823,7 +14156,7 @@ static void
argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
{
VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
- if (ret != Qundef) ARGF.next_p = 1;
+ if (!UNDEF_P(ret)) ARGF.next_p = 1;
}
/*
@@ -12840,15 +14173,15 @@ argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
* which defaults to your platform's newline character) of each file in
* +ARGV+. If a block is supplied, each line in turn will be yielded to the
* block, otherwise an enumerator is returned.
- * The optional _limit_ argument is an +Integer+ specifying the maximum
+ * The optional _limit_ argument is an Integer specifying the maximum
* length of each line; longer lines will be split according to this limit.
*
* This method allows you to treat the files supplied on the command line as
* a single file consisting of the concatenation of each named file. After
* the last line of the first file has been returned, the first line of the
- * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
- * be used to determine the filename of the current line and line number of
- * the whole input, respectively.
+ * second file is returned. The ARGF.filename and ARGF.lineno methods can be
+ * used to determine the filename of the current line and line number of the
+ * whole input, respectively.
*
* For example, the following code prints out each line of each named file
* prefixed with its line number, displaying the filename once per file:
@@ -12871,7 +14204,7 @@ argf_each_line(int argc, VALUE *argv, VALUE argf)
{
RETURN_ENUMERATOR(argf, argc, argv);
FOREACH_ARGF() {
- argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
+ argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
}
return argf;
}
@@ -12882,12 +14215,12 @@ argf_each_line(int argc, VALUE *argv, VALUE argf)
* ARGF.each_byte -> an_enumerator
*
* Iterates over each byte of each file in +ARGV+.
- * A byte is returned as an +Integer+ in the range 0..255.
+ * A byte is returned as an Integer in the range 0..255.
*
* This method allows you to treat the files supplied on the command line as
* a single file consisting of the concatenation of each named file. After
* the last byte of the first file has been returned, the first byte of the
- * second file is returned. The +ARGF.filename+ method can be used to
+ * second file is returned. The ARGF.filename method can be used to
* determine the filename of the current byte.
*
* If no block is given, an enumerator is returned instead.
@@ -12902,7 +14235,7 @@ argf_each_byte(VALUE argf)
{
RETURN_ENUMERATOR(argf, 0, 0);
FOREACH_ARGF() {
- argf_block_call(rb_intern("each_byte"), 0, 0, argf);
+ argf_block_call(rb_intern("each_byte"), 0, 0, argf);
}
return argf;
}
@@ -12912,12 +14245,12 @@ argf_each_byte(VALUE argf)
* ARGF.each_char {|char| block } -> ARGF
* ARGF.each_char -> an_enumerator
*
- * Iterates over each character of each file in +ARGF+.
+ * Iterates over each character of each file in ARGF.
*
* This method allows you to treat the files supplied on the command line as
* a single file consisting of the concatenation of each named file. After
* the last character of the first file has been returned, the first
- * character of the second file is returned. The +ARGF.filename+ method can
+ * character of the second file is returned. The ARGF.filename method can
* be used to determine the name of the file in which the current character
* appears.
*
@@ -12928,7 +14261,7 @@ argf_each_char(VALUE argf)
{
RETURN_ENUMERATOR(argf, 0, 0);
FOREACH_ARGF() {
- argf_block_call(rb_intern("each_char"), 0, 0, argf);
+ argf_block_call(rb_intern("each_char"), 0, 0, argf);
}
return argf;
}
@@ -12938,12 +14271,12 @@ argf_each_char(VALUE argf)
* ARGF.each_codepoint {|codepoint| block } -> ARGF
* ARGF.each_codepoint -> an_enumerator
*
- * Iterates over each codepoint of each file in +ARGF+.
+ * Iterates over each codepoint of each file in ARGF.
*
* This method allows you to treat the files supplied on the command line as
* a single file consisting of the concatenation of each named file. After
* the last codepoint of the first file has been returned, the first
- * codepoint of the second file is returned. The +ARGF.filename+ method can
+ * codepoint of the second file is returned. The ARGF.filename method can
* be used to determine the name of the file in which the current codepoint
* appears.
*
@@ -12954,7 +14287,7 @@ argf_each_codepoint(VALUE argf)
{
RETURN_ENUMERATOR(argf, 0, 0);
FOREACH_ARGF() {
- argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
+ argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
}
return argf;
}
@@ -12998,7 +14331,7 @@ argf_filename_getter(ID id, VALUE *var)
* call-seq:
* ARGF.file -> IO or File object
*
- * Returns the current file as an +IO+ or +File+ object.
+ * Returns the current file as an IO or File object.
* <code>$stdin</code> is returned when the current file is STDIN.
*
* For example:
@@ -13023,7 +14356,7 @@ argf_file(VALUE argf)
* call-seq:
* ARGF.binmode -> ARGF
*
- * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
+ * Puts ARGF into binary mode. Once a stream is in binary mode, it cannot
* be reset to non-binary mode. This option has the following effects:
*
* * Newline conversion is disabled.
@@ -13044,8 +14377,8 @@ argf_binmode_m(VALUE argf)
* call-seq:
* ARGF.binmode? -> true or false
*
- * Returns true if +ARGF+ is being read in binary mode; false otherwise.
- * To enable binary mode use +ARGF.binmode+.
+ * Returns true if ARGF is being read in binary mode; false otherwise.
+ * To enable binary mode use ARGF.binmode.
*
* For example:
*
@@ -13077,8 +14410,8 @@ static VALUE
argf_skip(VALUE argf)
{
if (ARGF.init_p && ARGF.next_p == 0) {
- argf_close(argf);
- ARGF.next_p = 1;
+ argf_close(argf);
+ ARGF.next_p = 1;
}
return argf;
}
@@ -13088,7 +14421,7 @@ argf_skip(VALUE argf)
* ARGF.close -> ARGF
*
* Closes the current file and skips to the next file in ARGV. If there are
- * no more files to open, just closes the current file. +STDIN+ will not be
+ * no more files to open, just closes the current file. STDIN will not be
* closed.
*
* For example:
@@ -13106,7 +14439,7 @@ argf_close_m(VALUE argf)
next_argv();
argf_close(argf);
if (ARGF.next_p != -1) {
- ARGF.next_p = 1;
+ ARGF.next_p = 1;
}
ARGF.lineno = 0;
return argf;
@@ -13117,7 +14450,7 @@ argf_close_m(VALUE argf)
* ARGF.closed? -> true or false
*
* Returns _true_ if the current file has been closed; _false_ otherwise. Use
- * +ARGF.close+ to actually close the current file.
+ * ARGF.close to actually close the current file.
*/
static VALUE
argf_closed(VALUE argf)
@@ -13143,9 +14476,9 @@ argf_to_s(VALUE argf)
* call-seq:
* ARGF.inplace_mode -> String
*
- * Returns the file extension appended to the names of modified files under
- * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
- * passing the +-i+ switch to the Ruby binary.
+ * Returns the file extension appended to the names of backup copies of
+ * modified files under in-place edit mode. This value can be set using
+ * ARGF.inplace_mode= or passing the +-i+ switch to the Ruby binary.
*/
static VALUE
argf_inplace_mode_get(VALUE argf)
@@ -13166,8 +14499,8 @@ opt_i_get(ID id, VALUE *var)
* ARGF.inplace_mode = ext -> ARGF
*
* Sets the filename extension for in-place editing mode to the given String.
- * Each file being edited has this value appended to its filename. The
- * modified file is saved under this new name.
+ * The backup copy of each file being edited has this value appended to its
+ * filename.
*
* For example:
*
@@ -13178,20 +14511,21 @@ opt_i_get(ID id, VALUE *var)
* print line.sub("foo","bar")
* end
*
- * Each line of _file.txt_ has the first occurrence of "foo" replaced with
- * "bar", then the new line is written out to _file.txt.bak_.
+ * First, _file.txt.bak_ is created as a backup copy of _file.txt_.
+ * Then, each line of _file.txt_ has the first occurrence of "foo" replaced with
+ * "bar".
*/
static VALUE
argf_inplace_mode_set(VALUE argf, VALUE val)
{
if (!RTEST(val)) {
- ARGF.inplace = Qfalse;
+ ARGF.inplace = Qfalse;
}
else if (StringValueCStr(val), !RSTRING_LEN(val)) {
- ARGF.inplace = Qnil;
+ ARGF.inplace = Qnil;
}
else {
- ARGF.inplace = rb_str_new_frozen(val);
+ ARGF.inplace = rb_str_new_frozen(val);
}
return argf;
}
@@ -13251,7 +14585,7 @@ static VALUE
argf_write_io(VALUE argf)
{
if (!RTEST(ARGF.current_file)) {
- rb_raise(rb_eIOError, "not opened for writing");
+ rb_raise(rb_eIOError, "not opened for writing");
}
return GetWriteIO(ARGF.current_file);
}
@@ -13281,41 +14615,41 @@ rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *m
arg = mesg ? rb_str_new2(mesg) : Qnil;
switch (waiting) {
case RB_IO_WAIT_WRITABLE:
- switch (n) {
- case EAGAIN:
+ switch (n) {
+ case EAGAIN:
c = rb_eEAGAINWaitWritable;
- break;
+ break;
#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
+ case EWOULDBLOCK:
c = rb_eEWOULDBLOCKWaitWritable;
- break;
+ break;
#endif
- case EINPROGRESS:
+ case EINPROGRESS:
c = rb_eEINPROGRESSWaitWritable;
- break;
- default:
+ break;
+ default:
rb_mod_syserr_fail_str(rb_mWaitWritable, n, arg);
- }
+ }
break;
case RB_IO_WAIT_READABLE:
- switch (n) {
- case EAGAIN:
+ switch (n) {
+ case EAGAIN:
c = rb_eEAGAINWaitReadable;
- break;
+ break;
#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
+ case EWOULDBLOCK:
c = rb_eEWOULDBLOCKWaitReadable;
- break;
+ break;
#endif
- case EINPROGRESS:
+ case EINPROGRESS:
c = rb_eEINPROGRESSWaitReadable;
- break;
- default:
+ break;
+ default:
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);
+ rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
}
rb_exc_raise(rb_class_new_instance(1, &arg, c));
}
@@ -13357,24 +14691,25 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* methods exist in two forms,
*
* one that returns +nil+ when the end of file is reached, the other
- * raises +EOFError+.
+ * raises EOFError.
*
- * +EOFError+ is a subclass of +IOError+.
+ * EOFError is a subclass of IOError.
*
* file = File.open("/etc/hosts")
* file.read
* file.gets #=> nil
* file.readline #=> EOFError: end of file reached
+ * file.close
*/
/*
* Document-class: ARGF
*
- * +ARGF+ is a stream designed for use in scripts that process files given as
+ * ARGF is a stream designed for use in scripts that process files given as
* command-line arguments or passed in via STDIN.
*
* The arguments passed to your script are stored in the +ARGV+ Array, one
- * argument per element. +ARGF+ assumes that any arguments that aren't
+ * argument per element. ARGF assumes that any arguments that aren't
* filenames have been removed from +ARGV+. For example:
*
* $ ruby argf.rb --verbose file1 file2
@@ -13383,15 +14718,15 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* option = ARGV.shift #=> "--verbose"
* ARGV #=> ["file1", "file2"]
*
- * You can now use +ARGF+ to work with a concatenation of each of these named
- * files. For instance, +ARGF.read+ will return the contents of _file1_
+ * You can now use ARGF to work with a concatenation of each of these named
+ * files. For instance, ARGF.read will return the contents of _file1_
* followed by the contents of _file2_.
*
- * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
+ * After a file in +ARGV+ has been read ARGF removes it from the Array.
* Thus, after all files have been read +ARGV+ will be empty.
*
- * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
- * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
+ * You can manipulate +ARGV+ yourself to control what ARGF operates on. If
+ * you remove a file from +ARGV+, it is ignored by ARGF; if you add files to
* +ARGV+, they are treated as if they were named on the command line. For
* example:
*
@@ -13401,7 +14736,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* ARGV.replace ["file2", "file3"]
* ARGF.read # Returns the contents of file2 and file3
*
- * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
+ * If +ARGV+ is empty, ARGF acts as if it contained STDIN, i.e. the data
* piped to your script. For example:
*
* $ echo "glark" | ruby -e 'p ARGF.read'
@@ -13409,233 +14744,561 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
*/
/*
- * The IO class is the basis for all input and output in Ruby.
- * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
- * so may use more than one native operating system stream.
+ * An instance of class \IO (commonly called a _stream_)
+ * represents an input/output stream in the underlying operating system.
+ * \Class \IO is the basis for input and output in Ruby.
*
- * Many of the examples in this section use the File class, the only standard
- * subclass of IO. The two classes are closely associated. Like the File
- * class, the Socket library subclasses from IO (such as TCPSocket or
- * UDPSocket).
+ * \Class File is the only class in the Ruby core that is a subclass of \IO.
+ * Some classes in the Ruby standard library are also subclasses of \IO;
+ * these include TCPSocket and UDPSocket.
*
- * The Kernel#open method can create an IO (or File) object for these types
- * of arguments:
+ * The global constant ARGF (also accessible as <tt>$<</tt>)
+ * provides an IO-like stream that allows access to all file paths
+ * found in ARGV (or found in STDIN if ARGV is empty).
+ * ARGF is not itself a subclass of \IO.
*
- * * A plain string represents a filename suitable for the underlying
- * operating system.
+ * \Class StringIO provides an IO-like stream that handles a String.
+ * \StringIO is not itself a subclass of \IO.
+ *
+ * Important objects based on \IO include:
+ *
+ * - $stdin.
+ * - $stdout.
+ * - $stderr.
+ * - Instances of class File.
+ *
+ * An instance of \IO may be created using:
+ *
+ * - IO.new: returns a new \IO object for the given integer file descriptor.
+ * - IO.open: passes a new \IO object to the given block.
+ * - IO.popen: returns a new \IO object that is connected to the $stdin and $stdout
+ * of a newly-launched subprocess.
+ * - Kernel#open: Returns a new \IO object connected to a given source:
+ * stream, file, or subprocess.
+ *
+ * Like a \File stream, an \IO stream has:
+ *
+ * - A read/write mode, which may be read-only, write-only, or read/write;
+ * see {Read/Write Mode}[rdoc-ref:File@Read-2FWrite+Mode].
+ * - A data mode, which may be text-only or binary;
+ * see {Data Mode}[rdoc-ref:File@Data+Mode].
+ * - Internal and external encodings;
+ * see {Encodings}[rdoc-ref:File@Encodings].
+ *
+ * And like other \IO streams, it has:
+ *
+ * - A position, which determines where in the stream the next
+ * read or write is to occur;
+ * see {Position}[rdoc-ref:IO@Position].
+ * - A line number, which is a special, line-oriented, "position"
+ * (different from the position mentioned above);
+ * see {Line Number}[rdoc-ref:IO@Line+Number].
+ *
+ * == Extension <tt>io/console</tt>
+ *
+ * Extension <tt>io/console</tt> provides numerous methods
+ * for interacting with the console;
+ * requiring it adds numerous methods to class \IO.
+ *
+ * == Example Files
+ *
+ * Many examples here use these variables:
*
- * * A string starting with <code>"|"</code> indicates a subprocess.
- * The remainder of the string following the <code>"|"</code> is
- * invoked as a process with appropriate input/output channels
- * connected to it.
- *
- * * A string equal to <code>"|-"</code> will create another Ruby
- * instance as a subprocess.
- *
- * The IO may be opened with different file modes (read-only, write-only) and
- * encodings for proper conversion. See IO.new for these options. See
- * Kernel#open for details of the various command formats described above.
- *
- * IO.popen, the Open3 library, or Process#spawn may also be used to
- * communicate with subprocesses through an IO.
- *
- * Ruby will convert pathnames between different operating system
- * conventions if possible. For instance, on a Windows system the
- * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
- * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
- * filename in a Ruby string, remember to escape the backslashes:
- *
- * "C:\\gumby\\ruby\\test.rb"
- *
- * Our examples here will use the Unix-style forward slashes;
- * File::ALT_SEPARATOR can be used to get the platform-specific separator
- * character.
- *
- * The global constant ARGF (also accessible as <code>$<</code>) provides an
- * IO-like stream which allows access to all files mentioned on the
- * command line (or STDIN if no files are mentioned). ARGF#path and its alias
- * ARGF#filename are provided to access the name of the file currently being
- * read.
- *
- * == io/console
- *
- * The io/console extension provides methods for interacting with the
- * console. The console can be accessed from IO.console or the standard
- * input/output/error IO objects.
- *
- * Requiring io/console adds the following methods:
- *
- * * IO::console
- * * IO#raw
- * * IO#raw!
- * * IO#cooked
- * * IO#cooked!
- * * IO#getch
- * * IO#echo=
- * * IO#echo?
- * * IO#noecho
- * * IO#winsize
- * * IO#winsize=
- * * IO#iflush
- * * IO#ioflush
- * * IO#oflush
+ * :include: doc/examples/files.rdoc
+ *
+ * == Open Options
+ *
+ * A number of \IO methods accept optional keyword arguments
+ * that determine how a new stream is to be opened:
+ *
+ * - +:mode+: Stream mode.
+ * - +:flags+: \Integer file open flags;
+ * If +mode+ is also given, the two are bitwise-ORed.
+ * - +:external_encoding+: External encoding for the stream.
+ * - +:internal_encoding+: Internal encoding for the stream.
+ * <tt>'-'</tt> is a synonym for the default internal encoding.
+ * If the value is +nil+ no conversion occurs.
+ * - +:encoding+: Specifies external and internal encodings as <tt>'extern:intern'</tt>.
+ * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise.
+ * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise.
+ * - +:autoclose+: If a truthy value, specifies that the +fd+ will close
+ * when the stream closes; otherwise it remains open.
+ * - +:path:+ If a string value is provided, it is used in #inspect and is available as
+ * #path method.
+ *
+ * Also available are the options offered in String#encode,
+ * which may control conversion between external internal encoding.
+ *
+ * == Basic \IO
+ *
+ * You can perform basic stream \IO with these methods,
+ * which typically operate on multi-byte strings:
+ *
+ * - IO#read: Reads and returns some or all of the remaining bytes from the stream.
+ * - IO#write: Writes zero or more strings to the stream;
+ * each given object that is not already a string is converted via +to_s+.
+ *
+ * === Position
+ *
+ * An \IO stream has a nonnegative integer _position_,
+ * which is the byte offset at which the next read or write is to occur.
+ * A new stream has position zero (and line number zero);
+ * method +rewind+ resets the position (and line number) to zero.
+ *
+ * The relevant methods:
+ *
+ * - IO#tell (aliased as +#pos+): Returns the current position (in bytes) in the stream.
+ * - IO#pos=: Sets the position of the stream to a given integer +new_position+ (in bytes).
+ * - IO#seek: Sets the position of the stream to a given integer +offset+ (in bytes),
+ * relative to a given position +whence+
+ * (indicating the beginning, end, or current position).
+ * - IO#rewind: Positions the stream at the beginning (also resetting the line number).
+ *
+ * === Open and Closed Streams
+ *
+ * A new \IO stream may be open for reading, open for writing, or both.
+ *
+ * A stream is automatically closed when claimed by the garbage collector.
+ *
+ * Attempted reading or writing on a closed stream raises an exception.
+ *
+ * The relevant methods:
+ *
+ * - IO#close: Closes the stream for both reading and writing.
+ * - IO#close_read: Closes the stream for reading.
+ * - IO#close_write: Closes the stream for writing.
+ * - IO#closed?: Returns whether the stream is closed.
+ *
+ * === End-of-Stream
+ *
+ * You can query whether a stream is positioned at its end:
+ *
+ * - IO#eof? (also aliased as +#eof+): Returns whether the stream is at end-of-stream.
+ *
+ * You can reposition to end-of-stream by using method IO#seek:
+ *
+ * f = File.new('t.txt')
+ * f.eof? # => false
+ * f.seek(0, :END)
+ * f.eof? # => true
+ * f.close
+ *
+ * Or by reading all stream content (which is slower than using IO#seek):
+ *
+ * f.rewind
+ * f.eof? # => false
+ * f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * f.eof? # => true
+ *
+ * == Line \IO
+ *
+ * You can read an \IO stream line-by-line using these methods:
+ *
+ * - IO#each_line: Reads each remaining line, passing it to the given block.
+ * - IO#gets: Returns the next line.
+ * - IO#readline: Like #gets, but raises an exception at end-of-stream.
+ * - IO#readlines: Returns all remaining lines in an array.
+ *
+ * Each of these reader methods accepts:
+ *
+ * - An optional line separator, +sep+;
+ * see {Line Separator}[rdoc-ref:IO@Line+Separator].
+ * - An optional line-size limit, +limit+;
+ * see {Line Limit}[rdoc-ref:IO@Line+Limit].
+ *
+ * For each of these reader methods, reading may begin mid-line,
+ * depending on the stream's position;
+ * see {Position}[rdoc-ref:IO@Position]:
+ *
+ * f = File.new('t.txt')
+ * f.pos = 27
+ * f.each_line {|line| p line }
+ * f.close
+ *
+ * Output:
+ *
+ * "rth line\n"
+ * "Fifth line\n"
+ *
+ * You can write to an \IO stream line-by-line using this method:
+ *
+ * - IO#puts: Writes objects to the stream.
+ *
+ * === Line Separator
+ *
+ * Each of these methods uses a <i>line separator</i>,
+ * which is the string that delimits lines:
+ *
+ * - IO.foreach.
+ * - IO.readlines.
+ * - IO#each_line.
+ * - IO#gets.
+ * - IO#readline.
+ * - IO#readlines.
+ *
+ * The default line separator is the given by the global variable <tt>$/</tt>,
+ * whose value is by default <tt>"\n"</tt>.
+ * The line to be read next is all data from the current position
+ * to the next line separator:
+ *
+ * f = File.new('t.txt')
+ * f.gets # => "First line\n"
+ * f.gets # => "Second line\n"
+ * f.gets # => "\n"
+ * f.gets # => "Fourth line\n"
+ * f.gets # => "Fifth line\n"
+ * f.close
+ *
+ * You can specify a different line separator:
+ *
+ * f = File.new('t.txt')
+ * f.gets('l') # => "First l"
+ * f.gets('li') # => "ine\nSecond li"
+ * f.gets('lin') # => "ne\n\nFourth lin"
+ * f.gets # => "e\n"
+ * f.close
+ *
+ * There are two special line separators:
+ *
+ * - +nil+: The entire stream is read into a single string:
+ *
+ * f = File.new('t.txt')
+ * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+ * f.close
+ *
+ * - <tt>''</tt> (the empty string): The next "paragraph" is read
+ * (paragraphs being separated by two consecutive line separators):
+ *
+ * f = File.new('t.txt')
+ * f.gets('') # => "First line\nSecond line\n\n"
+ * f.gets('') # => "Fourth line\nFifth line\n"
+ * f.close
+ *
+ * === Line Limit
+ *
+ * Each of these methods uses a <i>line limit</i>,
+ * which specifies that the number of bytes returned may not be (much) longer
+ * than the given +limit+;
+ *
+ * - IO.foreach.
+ * - IO.readlines.
+ * - IO#each_line.
+ * - IO#gets.
+ * - IO#readline.
+ * - IO#readlines.
+ *
+ * A multi-byte character will not be split, and so a line may be slightly longer
+ * than the given limit.
+ *
+ * If +limit+ is not given, the line is determined only by +sep+.
+ *
+ * # Text with 1-byte characters.
+ * File.open('t.txt') {|f| f.gets(1) } # => "F"
+ * File.open('t.txt') {|f| f.gets(2) } # => "Fi"
+ * File.open('t.txt') {|f| f.gets(3) } # => "Fir"
+ * File.open('t.txt') {|f| f.gets(4) } # => "Firs"
+ * # No more than one line.
+ * File.open('t.txt') {|f| f.gets(10) } # => "First line"
+ * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
+ * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
+ *
+ * # Text with 2-byte characters, which will not be split.
+ * File.open('t.rus') {|f| f.gets(1).size } # => 1
+ * File.open('t.rus') {|f| f.gets(2).size } # => 1
+ * File.open('t.rus') {|f| f.gets(3).size } # => 2
+ * File.open('t.rus') {|f| f.gets(4).size } # => 2
+ *
+ * === Line Separator and Line Limit
+ *
+ * With arguments +sep+ and +limit+ given,
+ * combines the two behaviors:
+ *
+ * - Returns the next line as determined by line separator +sep+.
+ * - But returns no more bytes than are allowed by the limit.
*
* Example:
*
- * require 'io/console'
- * rows, columns = $stdout.winsize
- * puts "Your screen is #{columns} wide and #{rows} tall"
+ * File.open('t.txt') {|f| f.gets('li', 20) } # => "First li"
+ * File.open('t.txt') {|f| f.gets('li', 2) } # => "Fi"
+ *
+ * === Line Number
+ *
+ * A readable \IO stream has a non-negative integer <i>line number</i>.
+ *
+ * The relevant methods:
+ *
+ * - IO#lineno: Returns the line number.
+ * - IO#lineno=: Resets and returns the line number.
+ *
+ * Unless modified by a call to method IO#lineno=,
+ * the line number is the number of lines read
+ * by certain line-oriented methods,
+ * according to the given line separator +sep+:
+ *
+ * - IO.foreach: Increments the line number on each call to the block.
+ * - IO#each_line: Increments the line number on each call to the block.
+ * - IO#gets: Increments the line number.
+ * - IO#readline: Increments the line number.
+ * - IO#readlines: Increments the line number for each line read.
+ *
+ * A new stream is initially has line number zero (and position zero);
+ * method +rewind+ resets the line number (and position) to zero:
+ *
+ * f = File.new('t.txt')
+ * f.lineno # => 0
+ * f.gets # => "First line\n"
+ * f.lineno # => 1
+ * f.rewind
+ * f.lineno # => 0
+ * f.close
+ *
+ * Reading lines from a stream usually changes its line number:
+ *
+ * f = File.new('t.txt', 'r')
+ * f.lineno # => 0
+ * f.readline # => "This is line one.\n"
+ * f.lineno # => 1
+ * f.readline # => "This is the second line.\n"
+ * f.lineno # => 2
+ * f.readline # => "Here's the third line.\n"
+ * f.lineno # => 3
+ * f.eof? # => true
+ * f.close
+ *
+ * Iterating over lines in a stream usually changes its line number:
+ *
+ * File.open('t.txt') do |f|
+ * f.each_line do |line|
+ * p "position=#{f.pos} eof?=#{f.eof?} lineno=#{f.lineno}"
+ * end
+ * end
+ *
+ * Output:
+ *
+ * "position=11 eof?=false lineno=1"
+ * "position=23 eof?=false lineno=2"
+ * "position=24 eof?=false lineno=3"
+ * "position=36 eof?=false lineno=4"
+ * "position=47 eof?=true lineno=5"
+ *
+ * Unlike the stream's {position}[rdoc-ref:IO@Position],
+ * the line number does not affect where the next read or write will occur:
+ *
+ * f = File.new('t.txt')
+ * f.lineno = 1000
+ * f.lineno # => 1000
+ * f.gets # => "First line\n"
+ * f.lineno # => 1001
+ * f.close
+ *
+ * Associated with the line number is the global variable <tt>$.</tt>:
+ *
+ * - When a stream is opened, <tt>$.</tt> is not set;
+ * its value is left over from previous activity in the process:
+ *
+ * $. = 41
+ * f = File.new('t.txt')
+ * $. = 41
+ * # => 41
+ * f.close
+ *
+ * - When a stream is read, <tt>#.</tt> is set to the line number for that stream:
+ *
+ * f0 = File.new('t.txt')
+ * f1 = File.new('t.dat')
+ * f0.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
+ * $. # => 5
+ * f1.readlines # => ["\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94"]
+ * $. # => 1
+ * f0.close
+ * f1.close
+ *
+ * - Methods IO#rewind and IO#seek do not affect <tt>$.</tt>:
+ *
+ * f = File.new('t.txt')
+ * f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
+ * $. # => 5
+ * f.rewind
+ * f.seek(0, :SET)
+ * $. # => 5
+ * f.close
+ *
+ * == Character \IO
+ *
+ * You can process an \IO stream character-by-character using these methods:
+ *
+ * - IO#getc: Reads and returns the next character from the stream.
+ * - IO#readchar: Like #getc, but raises an exception at end-of-stream.
+ * - IO#ungetc: Pushes back ("unshifts") a character or integer onto the stream.
+ * - IO#putc: Writes a character to the stream.
+ * - IO#each_char: Reads each remaining character in the stream,
+ * passing the character to the given block.
+ * == Byte \IO
+ *
+ * You can process an \IO stream byte-by-byte using these methods:
+ *
+ * - IO#getbyte: Returns the next 8-bit byte as an integer in range 0..255.
+ * - IO#readbyte: Like #getbyte, but raises an exception if at end-of-stream.
+ * - IO#ungetbyte: Pushes back ("unshifts") a byte back onto the stream.
+ * - IO#each_byte: Reads each remaining byte in the stream,
+ * passing the byte to the given block.
+ *
+ * == Codepoint \IO
+ *
+ * You can process an \IO stream codepoint-by-codepoint:
+ *
+ * - IO#each_codepoint: Reads each remaining codepoint, passing it to the given block.
*
* == What's Here
*
* First, what's elsewhere. \Class \IO:
*
- * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
- * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
* Here, class \IO provides methods that are useful for:
*
- * - {Creating}[#class-IO-label-Creating]
- * - {Reading}[#class-IO-label-Reading]
- * - {Writing}[#class-IO-label-Writing]
- * - {Positioning}[#class-IO-label-Positioning]
- * - {Iterating}[#class-IO-label-Iterating]
- * - {Settings}[#class-IO-label-Settings]
- * - {Querying}[#class-IO-label-Querying]
- * - {Buffering}[#class-IO-label-Buffering]
- * - {Low-Level Access}[#class-IO-label-Low-Level+Access]
- * - {Other}[#class-IO-label-Other]
+ * - {Creating}[rdoc-ref:IO@Creating]
+ * - {Reading}[rdoc-ref:IO@Reading]
+ * - {Writing}[rdoc-ref:IO@Writing]
+ * - {Positioning}[rdoc-ref:IO@Positioning]
+ * - {Iterating}[rdoc-ref:IO@Iterating]
+ * - {Settings}[rdoc-ref:IO@Settings]
+ * - {Querying}[rdoc-ref:IO@Querying]
+ * - {Buffering}[rdoc-ref:IO@Buffering]
+ * - {Low-Level Access}[rdoc-ref:IO@Low-Level+Access]
+ * - {Other}[rdoc-ref:IO@Other]
*
* === Creating
*
- * - ::new (aliased as ::for_fd):: Creates and returns a new \IO object for the given
- * integer file descriptor.
- * - ::open:: Creates a new \IO object.
- * - ::pipe:: Creates a connected pair of reader and writer \IO objects.
- * - ::popen:: Creates an \IO object to interact with a subprocess.
- * - ::select:: Selects which given \IO instances are ready for reading,
+ * - ::new (aliased as ::for_fd): Creates and returns a new \IO object for the given
+ * integer file descriptor.
+ * - ::open: Creates a new \IO object.
+ * - ::pipe: Creates a connected pair of reader and writer \IO objects.
+ * - ::popen: Creates an \IO object to interact with a subprocess.
+ * - ::select: Selects which given \IO instances are ready for reading,
* writing, or have pending exceptions.
*
* === Reading
*
- * - ::binread:: Returns a binary string with all or a subset of bytes
- * from the given file.
- * - ::read:: Returns a string with all or a subset of bytes from the given file.
- * - ::readlines:: Returns an array of strings, which are the lines from the given file.
- * - #getbyte:: Returns the next 8-bit byte read from +self+ as an integer.
- * - #getc:: Returns the next character read from +self+ as a string.
- * - #gets:: Returns the line read from +self+.
- * - #pread:: Returns all or the next _n_ bytes read from +self+,
- * not updating the receiver's offset.
- * - #read:: Returns all remaining or the next _n_ bytes read from +self+
- * for a given _n_.
- * - #read_nonblock:: the next _n_ bytes read from +self+ for a given _n_,
- * in non-block mode.
- * - #readbyte:: Returns the next byte read from +self+;
- * same as #getbyte, but raises an exception on end-of-file.
- * - #readchar:: Returns the next character read from +self+;
- * same as #getc, but raises an exception on end-of-file.
- * - #readline:: Returns the next line read from +self+;
- * same as #getline, but raises an exception of end-of-file.
- * - #readlines:: Returns an array of all lines read read from +self+.
- * - #readpartial:: Returns up to the given number of bytes from +self+.
+ * - ::binread: Returns a binary string with all or a subset of bytes
+ * from the given file.
+ * - ::read: Returns a string with all or a subset of bytes from the given file.
+ * - ::readlines: Returns an array of strings, which are the lines from the given file.
+ * - #getbyte: Returns the next 8-bit byte read from +self+ as an integer.
+ * - #getc: Returns the next character read from +self+ as a string.
+ * - #gets: Returns the line read from +self+.
+ * - #pread: Returns all or the next _n_ bytes read from +self+,
+ * not updating the receiver's offset.
+ * - #read: Returns all remaining or the next _n_ bytes read from +self+
+ * for a given _n_.
+ * - #read_nonblock: the next _n_ bytes read from +self+ for a given _n_,
+ * in non-block mode.
+ * - #readbyte: Returns the next byte read from +self+;
+ * same as #getbyte, but raises an exception on end-of-stream.
+ * - #readchar: Returns the next character read from +self+;
+ * same as #getc, but raises an exception on end-of-stream.
+ * - #readline: Returns the next line read from +self+;
+ * same as #getline, but raises an exception of end-of-stream.
+ * - #readlines: Returns an array of all lines read read from +self+.
+ * - #readpartial: Returns up to the given number of bytes from +self+.
*
* === Writing
*
- * - ::binwrite:: Writes the given string to the file at the given filepath,
- in binary mode.
- * - ::write:: Writes the given string to +self+.
- * - {::<<}[#method-i-3C-3C]:: Appends the given string to +self+.
- * - #print:: Prints last read line or given objects to +self+.
- * - #printf:: Writes to +self+ based on the given format string and objects.
- * - #putc:: Writes a character to +self+.
- * - #puts:: Writes lines to +self+, making sure line ends with a newline.
- * - #pwrite:: Writes the given string at the given offset,
- * not updating the receiver's offset.
- * - #write:: Writes one or more given strings to +self+.
- * - #write_nonblock:: Writes one or more given strings to +self+ in non-blocking mode.
+ * - ::binwrite: Writes the given string to the file at the given filepath,
+ * in binary mode.
+ * - ::write: Writes the given string to +self+.
+ * - #<<: Appends the given string to +self+.
+ * - #print: Prints last read line or given objects to +self+.
+ * - #printf: Writes to +self+ based on the given format string and objects.
+ * - #putc: Writes a character to +self+.
+ * - #puts: Writes lines to +self+, making sure line ends with a newline.
+ * - #pwrite: Writes the given string at the given offset,
+ * not updating the receiver's offset.
+ * - #write: Writes one or more given strings to +self+.
+ * - #write_nonblock: Writes one or more given strings to +self+ in non-blocking mode.
*
* === Positioning
*
- * - #lineno:: Returns the current line number in +self+.
- * - #lineno=:: Sets the line number is +self+.
- * - #pos (aliased as #tell):: Returns the current byte offset in +self+.
- * - #pos=:: Sets the byte offset in +self+.
- * - #reopen:: Reassociates +self+ with a new or existing \IO stream.
- * - #rewind:: Positions +self+ to the beginning of input.
- * - #seek:: Sets the offset for +self+ relative to given position.
+ * - #lineno: Returns the current line number in +self+.
+ * - #lineno=: Sets the line number is +self+.
+ * - #pos (aliased as #tell): Returns the current byte offset in +self+.
+ * - #pos=: Sets the byte offset in +self+.
+ * - #reopen: Reassociates +self+ with a new or existing \IO stream.
+ * - #rewind: Positions +self+ to the beginning of input.
+ * - #seek: Sets the offset for +self+ relative to given position.
*
* === Iterating
*
- * - ::foreach:: Yields each line of given file to the block.
- * - #each (aliased as #each_line):: Calls the given block
- * with each successive line in +self+.
- * - #each_byte:: Calls the given block with each successive byte in +self+
- * as an integer.
- * - #each_char:: Calls the given block with each successive character in +self+
- * as a string.
- * - #each_codepoint:: Calls the given block with each successive codepoint in +self+
- * as an integer.
+ * - ::foreach: Yields each line of given file to the block.
+ * - #each (aliased as #each_line): Calls the given block
+ * with each successive line in +self+.
+ * - #each_byte: Calls the given block with each successive byte in +self+
+ * as an integer.
+ * - #each_char: Calls the given block with each successive character in +self+
+ * as a string.
+ * - #each_codepoint: Calls the given block with each successive codepoint in +self+
+ * as an integer.
*
* === Settings
*
- * - #autoclose=:: Sets whether +self+ auto-closes.
- * - #binmode:: Sets +self+ to binary mode.
- * - #close:: Closes +self+.
- * - #close_on_exec=:: Sets the close-on-exec flag.
- * - #close_read:: Closes +self+ for reading.
- * - #close_write:: Closes +self+ for writing.
- * - #set_encoding:: Sets the encoding for +self+.
- * - #set_encoding_by_bom:: Sets the encoding for +self+, based on its
- * Unicode byte-order-mark.
- * - #sync=:: Sets the sync-mode to the given value.
+ * - #autoclose=: Sets whether +self+ auto-closes.
+ * - #binmode: Sets +self+ to binary mode.
+ * - #close: Closes +self+.
+ * - #close_on_exec=: Sets the close-on-exec flag.
+ * - #close_read: Closes +self+ for reading.
+ * - #close_write: Closes +self+ for writing.
+ * - #set_encoding: Sets the encoding for +self+.
+ * - #set_encoding_by_bom: Sets the encoding for +self+, based on its
+ * Unicode byte-order-mark.
+ * - #sync=: Sets the sync-mode to the given value.
*
* === Querying
*
- * - #autoclose?:: Returns whether +self+ auto-closes.
- * - #binmode?:: Returns whether +self+ is in binary mode.
- * - #close_on_exec?:: Returns the close-on-exec flag for +self+.
- * - #closed?:: Returns whether +self+ is closed.
- * - #eof? (aliased as #eof):: Returns whether +self+ is at end-of-file.
- * - #external_encoding:: Returns the external encoding object for +self+.
- * - #fileno (aliased as #to_i):: Returns the integer file descriptor for +self+
- * - #internal_encoding:: Returns the internal encoding object for +self+.
- * - #pid:: Returns the process ID of a child process associated with +self+,
- * if +self+ was created by ::popen.
- * - #stat:: Returns the File::Stat object containing status information for +self+.
- * - #sync:: Returns whether +self+ is in sync-mode.
- * - #tty (aliased as #isatty):: Returns whether +self+ is a terminal.
+ * - #autoclose?: Returns whether +self+ auto-closes.
+ * - #binmode?: Returns whether +self+ is in binary mode.
+ * - #close_on_exec?: Returns the close-on-exec flag for +self+.
+ * - #closed?: Returns whether +self+ is closed.
+ * - #eof? (aliased as #eof): Returns whether +self+ is at end-of-stream.
+ * - #external_encoding: Returns the external encoding object for +self+.
+ * - #fileno (aliased as #to_i): Returns the integer file descriptor for +self+
+ * - #internal_encoding: Returns the internal encoding object for +self+.
+ * - #pid: Returns the process ID of a child process associated with +self+,
+ * if +self+ was created by ::popen.
+ * - #stat: Returns the File::Stat object containing status information for +self+.
+ * - #sync: Returns whether +self+ is in sync-mode.
+ * - #tty? (aliased as #isatty): Returns whether +self+ is a terminal.
*
* === Buffering
*
- * - #fdatasync:: Immediately writes all buffered data in +self+ to disk.
- * - #flush:: Flushes any buffered data within +self+ to the underlying
- * operating system.
- * - #fsync:: Immediately writes all buffered data and attributes in +self+ to disk.
- * - #ungetbyte:: Prepends buffer for +self+ with given integer byte or string.
- * - #ungetc:: Prepends buffer for +self+ with given string.
+ * - #fdatasync: Immediately writes all buffered data in +self+ to disk.
+ * - #flush: Flushes any buffered data within +self+ to the underlying
+ * operating system.
+ * - #fsync: Immediately writes all buffered data and attributes in +self+ to disk.
+ * - #ungetbyte: Prepends buffer for +self+ with given integer byte or string.
+ * - #ungetc: Prepends buffer for +self+ with given string.
*
* === Low-Level Access
*
- * - ::sysopen:: Opens the file given by its path,
- * returning the integer file descriptor.
- * - #advise:: Announces the intention to access data from +self+ in a specific way.
- * - #fcntl:: Passes a low-level command to the file specified
- * by the given file descriptor.
- * - #ioctl:: Passes a low-level command to the device specified
- * by the given file descriptor.
- * - #sysread:: Returns up to the next _n_ bytes read from self using a low-level read.
- * - #sysseek:: Sets the offset for +self+.
- * - #syswrite:: Writes the given string to +self+ using a low-level write.
+ * - ::sysopen: Opens the file given by its path,
+ * returning the integer file descriptor.
+ * - #advise: Announces the intention to access data from +self+ in a specific way.
+ * - #fcntl: Passes a low-level command to the file specified
+ * by the given file descriptor.
+ * - #ioctl: Passes a low-level command to the device specified
+ * by the given file descriptor.
+ * - #sysread: Returns up to the next _n_ bytes read from self using a low-level read.
+ * - #sysseek: Sets the offset for +self+.
+ * - #syswrite: Writes the given string to +self+ using a low-level write.
*
* === Other
*
- * - ::copy_stream:: Copies data from a source to a destination,
- * each of which is a filepath or an \IO-like object.
- * - ::try_convert:: Returns a new \IO object resulting from converting
- * the given object.
- * - #inspect:: Returns the string representation of +self+.
+ * - ::copy_stream: Copies data from a source to a destination,
+ * each of which is a filepath or an \IO-like object.
+ * - ::try_convert: Returns a new \IO object resulting from converting
+ * the given object.
+ * - #inspect: Returns the string representation of +self+.
*
*/
@@ -13647,11 +15310,11 @@ Init_IO(void)
#include <sys/cygwin.h>
static struct __cygwin_perfile pf[] =
{
- {"", O_RDONLY | O_BINARY},
- {"", O_WRONLY | O_BINARY},
- {"", O_RDWR | O_BINARY},
- {"", O_APPEND | O_BINARY},
- {NULL, 0}
+ {"", O_RDONLY | O_BINARY},
+ {"", O_WRONLY | O_BINARY},
+ {"", O_RDWR | O_BINARY},
+ {"", O_APPEND | O_BINARY},
+ {NULL, 0}
};
cygwin_internal(CW_PERFILE, pf);
#endif
@@ -13665,6 +15328,7 @@ Init_IO(void)
id_flush = rb_intern_const("flush");
id_readpartial = rb_intern_const("readpartial");
id_set_encoding = rb_intern_const("set_encoding");
+ id_fileno = rb_intern_const("fileno");
rb_define_global_function("syscall", rb_f_syscall, -1);
@@ -13687,6 +15351,8 @@ Init_IO(void)
rb_cIO = rb_define_class("IO", rb_cObject);
rb_include_module(rb_cIO, rb_mEnumerable);
+ rb_eIOTimeoutError = rb_define_class_under(rb_cIO, "TimeoutError", rb_eIOError);
+
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));
@@ -13785,23 +15451,26 @@ Init_IO(void)
rb_define_alias(rb_cIO, "to_i", "fileno");
rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
- rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
- rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
- rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
- rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
+ rb_define_method(rb_cIO, "timeout", rb_io_timeout, 0);
+ rb_define_method(rb_cIO, "timeout=", rb_io_set_timeout, 1);
+
+ rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
+ rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
+ rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
+ rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
- rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
- rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
+ rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
+ rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
- rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
+ rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
- rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
- rb_define_method(rb_cIO, "read", io_read, -1);
+ rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
+ rb_define_method(rb_cIO, "read", io_read, -1);
rb_define_method(rb_cIO, "write", io_write_m, -1);
- rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
- rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
- rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
- rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
+ rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
+ rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
+ rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
+ rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
@@ -13848,6 +15517,10 @@ Init_IO(void)
rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
+
+ rb_define_method(rb_cIO, "path", rb_io_path, 0);
+ rb_define_method(rb_cIO, "to_path", rb_io_path, 0);
+
rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
@@ -13858,6 +15531,12 @@ 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_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);
+
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);
@@ -13868,13 +15547,12 @@ Init_IO(void)
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_stdin = rb_io_prep_stdin();
rb_global_variable(&rb_stdout);
+ rb_stdout = rb_io_prep_stdout();
rb_global_variable(&rb_stderr);
+ rb_stderr = rb_io_prep_stderr();
orig_stdout = rb_stdout;
orig_stderr = rb_stderr;
diff --git a/io_buffer.c b/io_buffer.c
new file mode 100644
index 0000000000..87b51c0b8c
--- /dev/null
+++ b/io_buffer.c
@@ -0,0 +1,3515 @@
+/**********************************************************************
+
+ io_buffer.c
+
+ Copyright (C) 2021 Samuel Grant Dawson Williams
+
+**********************************************************************/
+
+#include "ruby/io.h"
+#include "ruby/io/buffer.h"
+#include "ruby/fiber/scheduler.h"
+
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/bits.h"
+#include "internal/error.h"
+#include "internal/numeric.h"
+#include "internal/string.h"
+#include "internal/thread.h"
+
+VALUE rb_cIOBuffer;
+VALUE rb_eIOBufferLockedError;
+VALUE rb_eIOBufferAllocationError;
+VALUE rb_eIOBufferAccessError;
+VALUE rb_eIOBufferInvalidatedError;
+VALUE rb_eIOBufferMaskError;
+
+size_t RUBY_IO_BUFFER_PAGE_SIZE;
+size_t RUBY_IO_BUFFER_DEFAULT_SIZE;
+
+#ifdef _WIN32
+#else
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+
+struct rb_io_buffer {
+ void *base;
+ size_t size;
+ enum rb_io_buffer_flags flags;
+
+#if defined(_WIN32)
+ HANDLE mapping;
+#endif
+
+ VALUE source;
+};
+
+static inline void *
+io_buffer_map_memory(size_t size, int flags)
+{
+#if defined(_WIN32)
+ void * base = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
+
+ if (!base) {
+ rb_sys_fail("io_buffer_map_memory:VirtualAlloc");
+ }
+#else
+ int mmap_flags = MAP_ANONYMOUS;
+ if (flags & RB_IO_BUFFER_SHARED) {
+ mmap_flags |= MAP_SHARED;
+ }
+ else {
+ mmap_flags |= MAP_PRIVATE;
+ }
+
+ void * base = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, -1, 0);
+
+ if (base == MAP_FAILED) {
+ rb_sys_fail("io_buffer_map_memory:mmap");
+ }
+#endif
+
+ return base;
+}
+
+static void
+io_buffer_map_file(struct rb_io_buffer *buffer, int descriptor, size_t size, rb_off_t offset, enum rb_io_buffer_flags flags)
+{
+#if defined(_WIN32)
+ HANDLE file = (HANDLE)_get_osfhandle(descriptor);
+ if (!file) rb_sys_fail("io_buffer_map_descriptor:_get_osfhandle");
+
+ DWORD protect = PAGE_READONLY, access = FILE_MAP_READ;
+
+ if (flags & RB_IO_BUFFER_READONLY) {
+ buffer->flags |= RB_IO_BUFFER_READONLY;
+ }
+ else {
+ protect = PAGE_READWRITE;
+ access = FILE_MAP_WRITE;
+ }
+
+ HANDLE mapping = CreateFileMapping(file, NULL, protect, 0, 0, NULL);
+ if (!mapping) rb_sys_fail("io_buffer_map_descriptor:CreateFileMapping");
+
+ if (flags & RB_IO_BUFFER_PRIVATE) {
+ access |= FILE_MAP_COPY;
+ buffer->flags |= RB_IO_BUFFER_PRIVATE;
+ }
+ else {
+ // This buffer refers to external buffer.
+ buffer->flags |= RB_IO_BUFFER_EXTERNAL;
+ buffer->flags |= RB_IO_BUFFER_SHARED;
+ }
+
+ void *base = MapViewOfFile(mapping, access, (DWORD)(offset >> 32), (DWORD)(offset & 0xFFFFFFFF), size);
+
+ if (!base) {
+ CloseHandle(mapping);
+ rb_sys_fail("io_buffer_map_file:MapViewOfFile");
+ }
+
+ buffer->mapping = mapping;
+#else
+ int protect = PROT_READ, access = 0;
+
+ if (flags & RB_IO_BUFFER_READONLY) {
+ buffer->flags |= RB_IO_BUFFER_READONLY;
+ }
+ else {
+ protect |= PROT_WRITE;
+ }
+
+ if (flags & RB_IO_BUFFER_PRIVATE) {
+ buffer->flags |= RB_IO_BUFFER_PRIVATE;
+ }
+ else {
+ // This buffer refers to external buffer.
+ buffer->flags |= RB_IO_BUFFER_EXTERNAL;
+ buffer->flags |= RB_IO_BUFFER_SHARED;
+ access |= MAP_SHARED;
+ }
+
+ void *base = mmap(NULL, size, protect, access, descriptor, offset);
+
+ if (base == MAP_FAILED) {
+ rb_sys_fail("io_buffer_map_file:mmap");
+ }
+#endif
+
+ buffer->base = base;
+ buffer->size = size;
+
+ buffer->flags |= RB_IO_BUFFER_MAPPED;
+}
+
+static inline void
+io_buffer_unmap(void* base, size_t size)
+{
+#ifdef _WIN32
+ VirtualFree(base, 0, MEM_RELEASE);
+#else
+ munmap(base, size);
+#endif
+}
+
+static void
+io_buffer_experimental(void)
+{
+ static int warned = 0;
+
+ if (warned) return;
+
+ warned = 1;
+
+ if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
+ rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL,
+ "IO::Buffer is experimental and both the Ruby and C interface may change in the future!"
+ );
+ }
+}
+
+static void
+io_buffer_zero(struct rb_io_buffer *buffer)
+{
+ buffer->base = NULL;
+ buffer->size = 0;
+#if defined(_WIN32)
+ buffer->mapping = NULL;
+#endif
+ buffer->source = Qnil;
+}
+
+static void
+io_buffer_initialize(struct rb_io_buffer *buffer, void *base, size_t size, enum rb_io_buffer_flags flags, VALUE source)
+{
+ if (base) {
+ // If we are provided a pointer, we use it.
+ }
+ else if (size) {
+ // If we are provided a non-zero size, we allocate it:
+ if (flags & RB_IO_BUFFER_INTERNAL) {
+ base = calloc(size, 1);
+ }
+ else if (flags & RB_IO_BUFFER_MAPPED) {
+ base = io_buffer_map_memory(size, flags);
+ }
+
+ if (!base) {
+ rb_raise(rb_eIOBufferAllocationError, "Could not allocate buffer!");
+ }
+ }
+ else {
+ // Otherwise we don't do anything.
+ return;
+ }
+
+ buffer->base = base;
+ buffer->size = size;
+ buffer->flags = flags;
+ buffer->source = source;
+}
+
+static int
+io_buffer_free(struct rb_io_buffer *buffer)
+{
+ if (buffer->base) {
+ if (buffer->flags & RB_IO_BUFFER_INTERNAL) {
+ free(buffer->base);
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_MAPPED) {
+ io_buffer_unmap(buffer->base, buffer->size);
+ }
+
+ // Previously we had this, but we found out due to the way GC works, we
+ // can't refer to any other Ruby objects here.
+ // if (RB_TYPE_P(buffer->source, T_STRING)) {
+ // rb_str_unlocktmp(buffer->source);
+ // }
+
+ buffer->base = NULL;
+
+#if defined(_WIN32)
+ if (buffer->mapping) {
+ CloseHandle(buffer->mapping);
+ buffer->mapping = NULL;
+ }
+#endif
+ buffer->size = 0;
+ buffer->flags = 0;
+ buffer->source = Qnil;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+rb_io_buffer_type_mark(void *_buffer)
+{
+ struct rb_io_buffer *buffer = _buffer;
+ rb_gc_mark(buffer->source);
+}
+
+void
+rb_io_buffer_type_free(void *_buffer)
+{
+ struct rb_io_buffer *buffer = _buffer;
+
+ io_buffer_free(buffer);
+
+ free(buffer);
+}
+
+size_t
+rb_io_buffer_type_size(const void *_buffer)
+{
+ const struct rb_io_buffer *buffer = _buffer;
+ size_t total = sizeof(struct rb_io_buffer);
+
+ if (buffer->flags) {
+ total += buffer->size;
+ }
+
+ return total;
+}
+
+static const rb_data_type_t rb_io_buffer_type = {
+ .wrap_struct_name = "IO::Buffer",
+ .function = {
+ .dmark = rb_io_buffer_type_mark,
+ .dfree = rb_io_buffer_type_free,
+ .dsize = rb_io_buffer_type_size,
+ },
+ .data = NULL,
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+// Extract an offset argument, which must be a positive integer.
+static inline size_t
+io_buffer_extract_offset(VALUE argument)
+{
+ if (rb_int_negative_p(argument)) {
+ rb_raise(rb_eArgError, "Offset can't be negative!");
+ }
+
+ return NUM2SIZET(argument);
+}
+
+// Extract a length argument, which must be a positive integer.
+// Length is generally considered a mutable property of an object and
+// semantically should be considered a subset of "size" as a concept.
+static inline size_t
+io_buffer_extract_length(VALUE argument)
+{
+ if (rb_int_negative_p(argument)) {
+ rb_raise(rb_eArgError, "Length can't be negative!");
+ }
+
+ return NUM2SIZET(argument);
+}
+
+// Extract a size argument, which must be a positive integer.
+// Size is generally considered an immutable property of an object.
+static inline size_t
+io_buffer_extract_size(VALUE argument)
+{
+ if (rb_int_negative_p(argument)) {
+ rb_raise(rb_eArgError, "Size can't be negative!");
+ }
+
+ return NUM2SIZET(argument);
+}
+
+// Compute the default length for a buffer, given an offset into that buffer.
+// The default length is the size of the buffer minus the offset. The offset
+// must be less than the size of the buffer otherwise the length will be
+// invalid; in that case, an ArgumentError exception will be raised.
+static inline size_t
+io_buffer_default_length(const struct rb_io_buffer *buffer, size_t offset)
+{
+ if (offset > buffer->size) {
+ rb_raise(rb_eArgError, "The given offset is bigger than the buffer size!");
+ }
+
+ // Note that the "length" is computed by the size the offset.
+ return buffer->size - offset;
+}
+
+// Extract the optional length and offset arguments, returning the buffer.
+// The length and offset are optional, but if they are provided, they must be
+// positive integers. If the length is not provided, the default length is
+// computed from the buffer size and offset. If the offset is not provided, it
+// defaults to zero.
+static inline struct rb_io_buffer *
+io_buffer_extract_length_offset(VALUE self, int argc, VALUE argv[], size_t *length, size_t *offset)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (argc >= 2) {
+ *offset = io_buffer_extract_offset(argv[1]);
+ }
+ else {
+ *offset = 0;
+ }
+
+ if (argc >= 1 && !NIL_P(argv[0])) {
+ *length = io_buffer_extract_length(argv[0]);
+ }
+ else {
+ *length = io_buffer_default_length(buffer, *offset);
+ }
+
+ return buffer;
+}
+
+// Extract the optional offset and length arguments, returning the buffer.
+// Similar to `io_buffer_extract_length_offset` but with the order of
+// arguments reversed.
+static inline struct rb_io_buffer *
+io_buffer_extract_offset_length(VALUE self, int argc, VALUE argv[], size_t *offset, size_t *length)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (argc >= 1) {
+ *offset = io_buffer_extract_offset(argv[0]);
+ }
+ else {
+ *offset = 0;
+ }
+
+ if (argc >= 2) {
+ *length = io_buffer_extract_length(argv[1]);
+ }
+ else {
+ *length = io_buffer_default_length(buffer, *offset);
+ }
+
+ return buffer;
+}
+
+VALUE
+rb_io_buffer_type_allocate(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ VALUE instance = TypedData_Make_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_zero(buffer);
+
+ return instance;
+}
+
+static VALUE io_buffer_for_make_instance(VALUE klass, VALUE string, enum rb_io_buffer_flags flags)
+{
+ VALUE instance = rb_io_buffer_type_allocate(klass);
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ flags |= RB_IO_BUFFER_EXTERNAL;
+
+ if (RB_OBJ_FROZEN(string))
+ flags |= RB_IO_BUFFER_READONLY;
+
+ if (!(flags & RB_IO_BUFFER_READONLY))
+ rb_str_modify(string);
+
+ io_buffer_initialize(buffer, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
+
+ return instance;
+}
+
+struct io_buffer_for_yield_instance_arguments {
+ VALUE klass;
+ VALUE string;
+ VALUE instance;
+ enum rb_io_buffer_flags flags;
+};
+
+static VALUE
+io_buffer_for_yield_instance(VALUE _arguments)
+{
+ struct io_buffer_for_yield_instance_arguments *arguments = (struct io_buffer_for_yield_instance_arguments *)_arguments;
+
+ arguments->instance = io_buffer_for_make_instance(arguments->klass, arguments->string, arguments->flags);
+
+ rb_str_locktmp(arguments->string);
+
+ return rb_yield(arguments->instance);
+}
+
+static VALUE
+io_buffer_for_yield_instance_ensure(VALUE _arguments)
+{
+ struct io_buffer_for_yield_instance_arguments *arguments = (struct io_buffer_for_yield_instance_arguments *)_arguments;
+
+ if (arguments->instance != Qnil) {
+ rb_io_buffer_free(arguments->instance);
+ }
+
+ rb_str_unlocktmp(arguments->string);
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * IO::Buffer.for(string) -> readonly io_buffer
+ * IO::Buffer.for(string) {|io_buffer| ... read/write io_buffer ...}
+ *
+ * Creates a IO::Buffer from the given string's memory. Without a block a
+ * frozen internal copy of the string is created efficiently and used as the
+ * buffer source. When a block is provided, the buffer is associated directly
+ * with the string's internal buffer and updating the buffer will update the
+ * string.
+ *
+ * Until #free is invoked on the buffer, either explicitly or via the garbage
+ * collector, the source string will be locked and cannot be modified.
+ *
+ * If the string is frozen, it will create a read-only buffer which cannot be
+ * modified. If the string is shared, it may trigger a copy-on-write when
+ * using the block form.
+ *
+ * string = 'test'
+ * buffer = IO::Buffer.for(string)
+ * buffer.external? #=> true
+ *
+ * buffer.get_string(0, 1)
+ * # => "t"
+ * string
+ * # => "best"
+ *
+ * buffer.resize(100)
+ * # in `resize': Cannot resize external buffer! (IO::Buffer::AccessError)
+ *
+ * IO::Buffer.for(string) do |buffer|
+ * buffer.set_string("T")
+ * string
+ * # => "Test"
+ * end
+ */
+VALUE
+rb_io_buffer_type_for(VALUE klass, VALUE string)
+{
+ StringValue(string);
+
+ // If the string is frozen, both code paths are okay.
+ // If the string is not frozen, if a block is not given, it must be frozen.
+ if (rb_block_given_p()) {
+ struct io_buffer_for_yield_instance_arguments arguments = {
+ .klass = klass,
+ .string = string,
+ .instance = Qnil,
+ .flags = 0,
+ };
+
+ return rb_ensure(io_buffer_for_yield_instance, (VALUE)&arguments, io_buffer_for_yield_instance_ensure, (VALUE)&arguments);
+ }
+ else {
+ // This internally returns the source string if it's already frozen.
+ string = rb_str_tmp_frozen_acquire(string);
+ return io_buffer_for_make_instance(klass, string, RB_IO_BUFFER_READONLY);
+ }
+}
+
+VALUE
+rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags)
+{
+ VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer);
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_initialize(buffer, base, size, flags, Qnil);
+
+ return instance;
+}
+
+VALUE
+rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags flags)
+{
+ io_buffer_experimental();
+
+ VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer);
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ int descriptor = rb_io_descriptor(io);
+
+ io_buffer_map_file(buffer, descriptor, size, offset, flags);
+
+ return instance;
+}
+
+/*
+ * call-seq: IO::Buffer.map(file, [size, [offset, [flags]]]) -> io_buffer
+ *
+ * Create an IO::Buffer for reading from +file+ by memory-mapping the file.
+ * +file_io+ should be a +File+ instance, opened for reading.
+ *
+ * Optional +size+ and +offset+ of mapping can be specified.
+ *
+ * By default, the buffer would be immutable (read only); to create a writable
+ * mapping, you need to open a file in read-write mode, and explicitly pass
+ * +flags+ argument without IO::Buffer::IMMUTABLE.
+ *
+ * Example:
+ *
+ * File.write('test.txt', 'test')
+ *
+ * buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY)
+ * # => #<IO::Buffer 0x00000001014a0000+4 MAPPED READONLY>
+ *
+ * buffer.readonly? # => true
+ *
+ * buffer.get_string
+ * # => "test"
+ *
+ * buffer.set_string('b', 0)
+ * # `set_string': Buffer is not writable! (IO::Buffer::AccessError)
+ *
+ * # create read/write mapping: length 4 bytes, offset 0, flags 0
+ * buffer = IO::Buffer.map(File.open('test.txt', 'r+'), 4, 0)
+ * buffer.set_string('b', 0)
+ * # => 1
+ *
+ * # Check it
+ * File.read('test.txt')
+ * # => "best"
+ *
+ * Note that some operating systems may not have cache coherency between mapped
+ * buffers and file reads.
+ */
+static VALUE
+io_buffer_map(int argc, VALUE *argv, VALUE klass)
+{
+ rb_check_arity(argc, 1, 4);
+
+ // We might like to handle a string path?
+ VALUE io = argv[0];
+
+ size_t size;
+ if (argc >= 2 && !RB_NIL_P(argv[1])) {
+ size = io_buffer_extract_size(argv[1]);
+ }
+ else {
+ rb_off_t file_size = rb_file_size(io);
+
+ // Compiler can confirm that we handled file_size < 0 case:
+ if (file_size < 0) {
+ rb_raise(rb_eArgError, "Invalid negative file size!");
+ }
+ // Here, we assume that file_size is positive:
+ else if ((uintmax_t)file_size > SIZE_MAX) {
+ rb_raise(rb_eArgError, "File larger than address space!");
+ }
+ else {
+ // This conversion should be safe:
+ size = (size_t)file_size;
+ }
+ }
+
+ // This is the file offset, not the buffer offset:
+ rb_off_t offset = 0;
+ if (argc >= 3) {
+ offset = NUM2OFFT(argv[2]);
+ }
+
+ enum rb_io_buffer_flags flags = 0;
+ if (argc >= 4) {
+ flags = RB_NUM2UINT(argv[3]);
+ }
+
+ return rb_io_buffer_map(io, size, offset, flags);
+}
+
+// Compute the optimal allocation flags for a buffer of the given size.
+static inline enum rb_io_buffer_flags
+io_flags_for_size(size_t size)
+{
+ if (size >= RUBY_IO_BUFFER_PAGE_SIZE) {
+ return RB_IO_BUFFER_MAPPED;
+ }
+
+ return RB_IO_BUFFER_INTERNAL;
+}
+
+/*
+ * call-seq: IO::Buffer.new([size = DEFAULT_SIZE, [flags = 0]]) -> io_buffer
+ *
+ * Create a new zero-filled IO::Buffer of +size+ bytes.
+ * By default, the buffer will be _internal_: directly allocated chunk
+ * of the memory. But if the requested +size+ is more than OS-specific
+ * IO::Buffer::PAGE_SIZE, the buffer would be allocated using the
+ * virtual memory mechanism (anonymous +mmap+ on Unix, +VirtualAlloc+
+ * on Windows). The behavior can be forced by passing IO::Buffer::MAPPED
+ * as a second parameter.
+ *
+ * Examples
+ *
+ * buffer = IO::Buffer.new(4)
+ * # =>
+ * # #<IO::Buffer 0x000055b34497ea10+4 INTERNAL>
+ * # 0x00000000 00 00 00 00 ....
+ *
+ * buffer.get_string(0, 1) # => "\x00"
+ *
+ * buffer.set_string("test")
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x000055b34497ea10+4 INTERNAL>
+ * # 0x00000000 74 65 73 74 test
+ */
+VALUE
+rb_io_buffer_initialize(int argc, VALUE *argv, VALUE self)
+{
+ io_buffer_experimental();
+
+ rb_check_arity(argc, 0, 2);
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ size_t size;
+ if (argc > 0) {
+ size = io_buffer_extract_size(argv[0]);
+ }
+ else {
+ size = RUBY_IO_BUFFER_DEFAULT_SIZE;
+ }
+
+ enum rb_io_buffer_flags flags = 0;
+ if (argc >= 2) {
+ flags = RB_NUM2UINT(argv[1]);
+ }
+ else {
+ flags |= io_flags_for_size(size);
+ }
+
+ io_buffer_initialize(buffer, NULL, size, flags, Qnil);
+
+ return self;
+}
+
+static int
+io_buffer_validate_slice(VALUE source, void *base, size_t size)
+{
+ void *source_base = NULL;
+ size_t source_size = 0;
+
+ if (RB_TYPE_P(source, T_STRING)) {
+ RSTRING_GETMEM(source, source_base, source_size);
+ }
+ else {
+ rb_io_buffer_get_bytes(source, &source_base, &source_size);
+ }
+
+ // Source is invalid:
+ if (source_base == NULL) return 0;
+
+ // Base is out of range:
+ if (base < source_base) return 0;
+
+ const void *source_end = (char*)source_base + source_size;
+ const void *end = (char*)base + size;
+
+ // End is out of range:
+ if (end > source_end) return 0;
+
+ // It seems okay:
+ return 1;
+}
+
+static int
+io_buffer_validate(struct rb_io_buffer *buffer)
+{
+ if (buffer->source != Qnil) {
+ // Only slices incur this overhead, unfortunately... better safe than sorry!
+ return io_buffer_validate_slice(buffer->source, buffer->base, buffer->size);
+ }
+ else {
+ return 1;
+ }
+}
+
+/*
+ * call-seq: to_s -> string
+ *
+ * Short representation of the buffer. It includes the address, size and
+ * symbolic flags. This format is subject to change.
+ *
+ * puts IO::Buffer.new(4) # uses to_s internally
+ * # #<IO::Buffer 0x000055769f41b1a0+4 INTERNAL>
+ */
+VALUE
+rb_io_buffer_to_s(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ VALUE result = rb_str_new_cstr("#<");
+
+ rb_str_append(result, rb_class_name(CLASS_OF(self)));
+ rb_str_catf(result, " %p+%"PRIdSIZE, buffer->base, buffer->size);
+
+ if (buffer->base == NULL) {
+ rb_str_cat2(result, " NULL");
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_EXTERNAL) {
+ rb_str_cat2(result, " EXTERNAL");
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_INTERNAL) {
+ rb_str_cat2(result, " INTERNAL");
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_MAPPED) {
+ rb_str_cat2(result, " MAPPED");
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_SHARED) {
+ rb_str_cat2(result, " SHARED");
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ rb_str_cat2(result, " LOCKED");
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_READONLY) {
+ rb_str_cat2(result, " READONLY");
+ }
+
+ if (buffer->source != Qnil) {
+ rb_str_cat2(result, " SLICE");
+ }
+
+ if (!io_buffer_validate(buffer)) {
+ rb_str_cat2(result, " INVALID");
+ }
+
+ return rb_str_cat2(result, ">");
+}
+
+static VALUE
+io_buffer_hexdump(VALUE string, size_t width, char *base, size_t size, int first)
+{
+ char *text = alloca(width+1);
+ text[width] = '\0';
+
+ for (size_t offset = 0; offset < size; offset += width) {
+ memset(text, '\0', width);
+ if (first) {
+ rb_str_catf(string, "0x%08" PRIxSIZE " ", offset);
+ first = 0;
+ }
+ else {
+ rb_str_catf(string, "\n0x%08" PRIxSIZE " ", offset);
+ }
+
+ for (size_t i = 0; i < width; i += 1) {
+ if (offset+i < size) {
+ unsigned char value = ((unsigned char*)base)[offset+i];
+
+ if (value < 127 && isprint(value)) {
+ text[i] = (char)value;
+ }
+ else {
+ text[i] = '.';
+ }
+
+ rb_str_catf(string, " %02x", value);
+ }
+ else {
+ rb_str_cat2(string, " ");
+ }
+ }
+
+ rb_str_catf(string, " %s", text);
+ }
+
+ return string;
+}
+
+static VALUE
+rb_io_buffer_hexdump(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ VALUE result = Qnil;
+
+ if (io_buffer_validate(buffer) && buffer->base) {
+ result = rb_str_buf_new(buffer->size*3 + (buffer->size/16)*12 + 1);
+
+ io_buffer_hexdump(result, 16, buffer->base, buffer->size, 1);
+ }
+
+ return result;
+}
+
+VALUE
+rb_io_buffer_inspect(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ VALUE result = rb_io_buffer_to_s(self);
+
+ if (io_buffer_validate(buffer)) {
+ // Limit the maximum size generated by inspect.
+ if (buffer->size <= 256) {
+ io_buffer_hexdump(result, 16, buffer->base, buffer->size, 0);
+ }
+ }
+
+ return result;
+}
+
+/*
+ * call-seq: size -> integer
+ *
+ * Returns the size of the buffer that was explicitly set (on creation with ::new
+ * or on #resize), or deduced on buffer's creation from string or file.
+ */
+VALUE
+rb_io_buffer_size(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return SIZET2NUM(buffer->size);
+}
+
+/*
+ * call-seq: valid? -> true or false
+ *
+ * Returns whether the buffer buffer is accessible.
+ *
+ * A buffer becomes invalid if it is a slice of another buffer which has been
+ * freed.
+ */
+static VALUE
+rb_io_buffer_valid_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(io_buffer_validate(buffer));
+}
+
+/*
+ * call-seq: null? -> true or false
+ *
+ * If the buffer was freed with #free or was never allocated in the first
+ * place.
+ */
+static VALUE
+rb_io_buffer_null_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->base == NULL);
+}
+
+/*
+ * call-seq: empty? -> true or false
+ *
+ * If the buffer has 0 size: it is created by ::new with size 0, or with ::for
+ * from an empty string. (Note that empty files can't be mapped, so the buffer
+ * created with ::map will never be empty.)
+ */
+static VALUE
+rb_io_buffer_empty_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->size == 0);
+}
+
+/*
+ * call-seq: external? -> true or false
+ *
+ * The buffer is _external_ if it references the memory which is not
+ * allocated or mapped by the buffer itself.
+ *
+ * A buffer created using ::for has an external reference to the string's
+ * memory.
+ *
+ * External buffer can't be resized.
+ */
+static VALUE
+rb_io_buffer_external_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->flags & RB_IO_BUFFER_EXTERNAL);
+}
+
+/*
+ * call-seq: internal? -> true or false
+ *
+ * If the buffer is _internal_, meaning it references memory allocated by the
+ * buffer itself.
+ *
+ * An internal buffer is not associated with any external memory (e.g. string)
+ * or file mapping.
+ *
+ * Internal buffers are created using ::new and is the default when the
+ * requested size is less than the IO::Buffer::PAGE_SIZE and it was not
+ * requested to be mapped on creation.
+ *
+ * Internal buffers can be resized, and such an operation will typically
+ * invalidate all slices, but not always.
+ */
+static VALUE
+rb_io_buffer_internal_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->flags & RB_IO_BUFFER_INTERNAL);
+}
+
+/*
+ * call-seq: mapped? -> true or false
+ *
+ * If the buffer is _mapped_, meaning it references memory mapped by the
+ * buffer.
+ *
+ * Mapped buffers are either anonymous, if created by ::new with the
+ * IO::Buffer::MAPPED flag or if the size was at least IO::Buffer::PAGE_SIZE,
+ * or backed by a file if created with ::map.
+ *
+ * Mapped buffers can usually be resized, and such an operation will typically
+ * invalidate all slices, but not always.
+ */
+static VALUE
+rb_io_buffer_mapped_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->flags & RB_IO_BUFFER_MAPPED);
+}
+
+/*
+ * call-seq: shared? -> true or false
+ *
+ * If the buffer is _shared_, meaning it references memory that can be shared
+ * with other processes (and thus might change without being modified
+ * locally).
+ */
+static VALUE
+rb_io_buffer_shared_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->flags & RB_IO_BUFFER_SHARED);
+}
+
+/*
+ * call-seq: locked? -> true or false
+ *
+ * If the buffer is _locked_, meaning it is inside #locked block execution.
+ * Locked buffer can't be resized or freed, and another lock can't be acquired
+ * on it.
+ *
+ * Locking is not thread safe, but is a semantic used to ensure buffers don't
+ * move while being used by a system call.
+ *
+ * Example:
+ *
+ * buffer.locked do
+ * buffer.write(io) # theoretical system call interface
+ * end
+ */
+static VALUE
+rb_io_buffer_locked_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return RBOOL(buffer->flags & RB_IO_BUFFER_LOCKED);
+}
+
+int
+rb_io_buffer_readonly_p(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ return buffer->flags & RB_IO_BUFFER_READONLY;
+}
+
+/*
+ * call-seq: readonly? -> true or false
+ *
+ * If the buffer is <i>read only</i>, meaning the buffer cannot be modified using
+ * #set_value, #set_string or #copy and similar.
+ *
+ * Frozen strings and read-only files create read-only buffers.
+ */
+static VALUE
+io_buffer_readonly_p(VALUE self)
+{
+ return RBOOL(rb_io_buffer_readonly_p(self));
+}
+
+static void
+io_buffer_lock(struct rb_io_buffer *buffer)
+{
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ rb_raise(rb_eIOBufferLockedError, "Buffer already locked!");
+ }
+
+ buffer->flags |= RB_IO_BUFFER_LOCKED;
+}
+
+VALUE
+rb_io_buffer_lock(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_lock(buffer);
+
+ return self;
+}
+
+static void
+io_buffer_unlock(struct rb_io_buffer *buffer)
+{
+ if (!(buffer->flags & RB_IO_BUFFER_LOCKED)) {
+ rb_raise(rb_eIOBufferLockedError, "Buffer not locked!");
+ }
+
+ buffer->flags &= ~RB_IO_BUFFER_LOCKED;
+}
+
+VALUE
+rb_io_buffer_unlock(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_unlock(buffer);
+
+ return self;
+}
+
+int
+rb_io_buffer_try_unlock(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ buffer->flags &= ~RB_IO_BUFFER_LOCKED;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * call-seq: locked { ... }
+ *
+ * Allows to process a buffer in exclusive way, for concurrency-safety. While
+ * the block is performed, the buffer is considered locked, and no other code
+ * can enter the lock. Also, locked buffer can't be changed with #resize or
+ * #free.
+ *
+ * The following operations acquire a lock: #resize, #free.
+ *
+ * Locking is not thread safe. It is designed as a safety net around
+ * non-blocking system calls. You can only share a buffer between threads with
+ * appropriate synchronisation techniques.
+ *
+ * Example:
+ *
+ * buffer = IO::Buffer.new(4)
+ * buffer.locked? #=> false
+ *
+ * Fiber.schedule do
+ * buffer.locked do
+ * buffer.write(io) # theoretical system call interface
+ * end
+ * end
+ *
+ * Fiber.schedule do
+ * # in `locked': Buffer already locked! (IO::Buffer::LockedError)
+ * buffer.locked do
+ * buffer.set_string("test", 0)
+ * end
+ * end
+ */
+VALUE
+rb_io_buffer_locked(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ rb_raise(rb_eIOBufferLockedError, "Buffer already locked!");
+ }
+
+ buffer->flags |= RB_IO_BUFFER_LOCKED;
+
+ VALUE result = rb_yield(self);
+
+ buffer->flags &= ~RB_IO_BUFFER_LOCKED;
+
+ return result;
+}
+
+/*
+ * call-seq: free -> self
+ *
+ * If the buffer references memory, release it back to the operating system.
+ * * for a _mapped_ buffer (e.g. from file): unmap.
+ * * for a buffer created from scratch: free memory.
+ * * for a buffer created from string: undo the association.
+ *
+ * After the buffer is freed, no further operations can't be performed on it.
+ *
+ * You can resize a freed buffer to re-allocate it.
+ *
+ * Example:
+ *
+ * buffer = IO::Buffer.for('test')
+ * buffer.free
+ * # => #<IO::Buffer 0x0000000000000000+0 NULL>
+ *
+ * buffer.get_value(:U8, 0)
+ * # in `get_value': The buffer is not allocated! (IO::Buffer::AllocationError)
+ *
+ * buffer.get_string
+ * # in `get_string': The buffer is not allocated! (IO::Buffer::AllocationError)
+ *
+ * buffer.null?
+ * # => true
+ */
+VALUE
+rb_io_buffer_free(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ rb_raise(rb_eIOBufferLockedError, "Buffer is locked!");
+ }
+
+ io_buffer_free(buffer);
+
+ return self;
+}
+
+// Validate that access to the buffer is within bounds, assuming you want to
+// access length bytes from the specified offset.
+static inline void
+io_buffer_validate_range(struct rb_io_buffer *buffer, size_t offset, size_t length)
+{
+ // We assume here that offset + length won't overflow:
+ if (offset + length > buffer->size) {
+ rb_raise(rb_eArgError, "Specified offset+length is bigger than the buffer size!");
+ }
+}
+
+static VALUE
+rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_t length)
+{
+ io_buffer_validate_range(buffer, offset, length);
+
+ VALUE instance = rb_io_buffer_type_allocate(rb_class_of(self));
+ struct rb_io_buffer *slice = NULL;
+ TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, slice);
+
+ slice->flags |= (buffer->flags & RB_IO_BUFFER_READONLY);
+ slice->base = (char*)buffer->base + offset;
+ slice->size = length;
+
+ // The source should be the root buffer:
+ if (buffer->source != Qnil)
+ slice->source = buffer->source;
+ else
+ slice->source = self;
+
+ return instance;
+}
+
+/*
+ * call-seq: slice([offset, [length]]) -> io_buffer
+ *
+ * Produce another IO::Buffer which is a slice (or view into) the current one
+ * starting at +offset+ bytes and going for +length+ bytes.
+ *
+ * The slicing happens without copying of memory, and the slice keeps being
+ * associated with the original buffer's source (string, or file), if any.
+ *
+ * If the offset is not given, it will be zero. If the offset is negative, it
+ * will raise an ArgumentError.
+ *
+ * If the length is not given, the slice will be as long as the original
+ * buffer minus the specified offset. If the length is negative, it will raise
+ * an ArgumentError.
+ *
+ * Raises RuntimeError if the <tt>offset+length</tt> is out of the current
+ * buffer's bounds.
+ *
+ * Example:
+ *
+ * string = 'test'
+ * buffer = IO::Buffer.for(string)
+ *
+ * slice = buffer.slice
+ * # =>
+ * # #<IO::Buffer 0x0000000108338e68+4 SLICE>
+ * # 0x00000000 74 65 73 74 test
+ *
+ * buffer.slice(2)
+ * # =>
+ * # #<IO::Buffer 0x0000000108338e6a+2 SLICE>
+ * # 0x00000000 73 74 st
+ *
+ * slice = buffer.slice(1, 2)
+ * # =>
+ * # #<IO::Buffer 0x00007fc3d34ebc49+2 SLICE>
+ * # 0x00000000 65 73 es
+ *
+ * # Put "o" into 0s position of the slice
+ * slice.set_string('o', 0)
+ * slice
+ * # =>
+ * # #<IO::Buffer 0x00007fc3d34ebc49+2 SLICE>
+ * # 0x00000000 6f 73 os
+ *
+ * # it is also visible at position 1 of the original buffer
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x00007fc3d31e2d80+4 SLICE>
+ * # 0x00000000 74 6f 73 74 tost
+ *
+ * # ...and original string
+ * string
+ * # => tost
+ */
+static VALUE
+io_buffer_slice(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 0, 2);
+
+ size_t offset, length;
+ struct rb_io_buffer *buffer = io_buffer_extract_offset_length(self, argc, argv, &offset, &length);
+
+ return rb_io_buffer_slice(buffer, self, offset, length);
+}
+
+int
+rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (io_buffer_validate(buffer)) {
+ if (buffer->base) {
+ *base = buffer->base;
+ *size = buffer->size;
+
+ return buffer->flags;
+ }
+ }
+
+ *base = NULL;
+ *size = 0;
+
+ return 0;
+}
+
+static inline void
+io_buffer_get_bytes_for_writing(struct rb_io_buffer *buffer, void **base, size_t *size)
+{
+ if (buffer->flags & RB_IO_BUFFER_READONLY ||
+ (!NIL_P(buffer->source) && OBJ_FROZEN(buffer->source))) {
+ rb_raise(rb_eIOBufferAccessError, "Buffer is not writable!");
+ }
+
+ if (!io_buffer_validate(buffer)) {
+ rb_raise(rb_eIOBufferInvalidatedError, "Buffer is invalid!");
+ }
+
+ if (buffer->base) {
+ *base = buffer->base;
+ *size = buffer->size;
+
+ return;
+ }
+
+ rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!");
+}
+
+void
+rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_get_bytes_for_writing(buffer, base, size);
+}
+
+static void
+io_buffer_get_bytes_for_reading(struct rb_io_buffer *buffer, const void **base, size_t *size)
+{
+ if (!io_buffer_validate(buffer)) {
+ rb_raise(rb_eIOBufferInvalidatedError, "Buffer has been invalidated!");
+ }
+
+ if (buffer->base) {
+ *base = buffer->base;
+ *size = buffer->size;
+
+ return;
+ }
+
+ rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!");
+}
+
+void
+rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_get_bytes_for_reading(buffer, base, size);
+}
+
+/*
+ * call-seq: transfer -> new_io_buffer
+ *
+ * Transfers ownership to a new buffer, deallocating the current one.
+ *
+ * Example:
+ *
+ * buffer = IO::Buffer.new('test')
+ * other = buffer.transfer
+ * other
+ * # =>
+ * # #<IO::Buffer 0x00007f136a15f7b0+4 SLICE>
+ * # 0x00000000 74 65 73 74 test
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x0000000000000000+0 NULL>
+ * buffer.null?
+ * # => true
+ */
+VALUE
+rb_io_buffer_transfer(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ rb_raise(rb_eIOBufferLockedError, "Cannot transfer ownership of locked buffer!");
+ }
+
+ VALUE instance = rb_io_buffer_type_allocate(rb_class_of(self));
+ struct rb_io_buffer *transferred;
+ TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, transferred);
+
+ *transferred = *buffer;
+ io_buffer_zero(buffer);
+
+ return instance;
+}
+
+static void
+io_buffer_resize_clear(struct rb_io_buffer *buffer, void* base, size_t size)
+{
+ if (size > buffer->size) {
+ memset((unsigned char*)base+buffer->size, 0, size - buffer->size);
+ }
+}
+
+static void
+io_buffer_resize_copy(struct rb_io_buffer *buffer, size_t size)
+{
+ // Slow path:
+ struct rb_io_buffer resized;
+ io_buffer_initialize(&resized, NULL, size, io_flags_for_size(size), Qnil);
+
+ if (buffer->base) {
+ size_t preserve = buffer->size;
+ if (preserve > size) preserve = size;
+ memcpy(resized.base, buffer->base, preserve);
+
+ io_buffer_resize_clear(buffer, resized.base, size);
+ }
+
+ io_buffer_free(buffer);
+ *buffer = resized;
+}
+
+void
+rb_io_buffer_resize(VALUE self, size_t size)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ rb_raise(rb_eIOBufferLockedError, "Cannot resize locked buffer!");
+ }
+
+ if (buffer->base == NULL) {
+ io_buffer_initialize(buffer, NULL, size, io_flags_for_size(size), Qnil);
+ return;
+ }
+
+ if (buffer->flags & RB_IO_BUFFER_EXTERNAL) {
+ rb_raise(rb_eIOBufferAccessError, "Cannot resize external buffer!");
+ }
+
+#if defined(HAVE_MREMAP) && defined(MREMAP_MAYMOVE)
+ if (buffer->flags & RB_IO_BUFFER_MAPPED) {
+ void *base = mremap(buffer->base, buffer->size, size, MREMAP_MAYMOVE);
+
+ if (base == MAP_FAILED) {
+ rb_sys_fail("rb_io_buffer_resize:mremap");
+ }
+
+ io_buffer_resize_clear(buffer, base, size);
+
+ buffer->base = base;
+ buffer->size = size;
+
+ return;
+ }
+#endif
+
+ if (buffer->flags & RB_IO_BUFFER_INTERNAL) {
+ if (size == 0) {
+ io_buffer_free(buffer);
+ return;
+ }
+
+ void *base = realloc(buffer->base, size);
+
+ if (!base) {
+ rb_sys_fail("rb_io_buffer_resize:realloc");
+ }
+
+ io_buffer_resize_clear(buffer, base, size);
+
+ buffer->base = base;
+ buffer->size = size;
+
+ return;
+ }
+
+ io_buffer_resize_copy(buffer, size);
+}
+
+/*
+ * call-seq: resize(new_size) -> self
+ *
+ * Resizes a buffer to a +new_size+ bytes, preserving its content.
+ * Depending on the old and new size, the memory area associated with
+ * the buffer might be either extended, or rellocated at different
+ * address with content being copied.
+ *
+ * buffer = IO::Buffer.new(4)
+ * buffer.set_string("test", 0)
+ * buffer.resize(8) # resize to 8 bytes
+ * # =>
+ * # #<IO::Buffer 0x0000555f5d1a1630+8 INTERNAL>
+ * # 0x00000000 74 65 73 74 00 00 00 00 test....
+ *
+ * External buffer (created with ::for), and locked buffer
+ * can not be resized.
+ */
+static VALUE
+io_buffer_resize(VALUE self, VALUE size)
+{
+ rb_io_buffer_resize(self, io_buffer_extract_size(size));
+
+ return self;
+}
+
+/*
+ * call-seq: <=>(other) -> true or false
+ *
+ * Buffers are compared by size and exact contents of the memory they are
+ * referencing using +memcmp+.
+ */
+static VALUE
+rb_io_buffer_compare(VALUE self, VALUE other)
+{
+ const void *ptr1, *ptr2;
+ size_t size1, size2;
+
+ rb_io_buffer_get_bytes_for_reading(self, &ptr1, &size1);
+ rb_io_buffer_get_bytes_for_reading(other, &ptr2, &size2);
+
+ if (size1 < size2) {
+ return RB_INT2NUM(-1);
+ }
+
+ if (size1 > size2) {
+ return RB_INT2NUM(1);
+ }
+
+ return RB_INT2NUM(memcmp(ptr1, ptr2, size1));
+}
+
+static void
+io_buffer_validate_type(size_t size, size_t offset)
+{
+ if (offset > size) {
+ rb_raise(rb_eArgError, "Type extends beyond end of buffer! (offset=%"PRIdSIZE" > size=%"PRIdSIZE")", offset, size);
+ }
+}
+
+// Lower case: little endian.
+// Upper case: big endian (network endian).
+//
+// :U8 | unsigned 8-bit integer.
+// :S8 | signed 8-bit integer.
+//
+// :u16, :U16 | unsigned 16-bit integer.
+// :s16, :S16 | signed 16-bit integer.
+//
+// :u32, :U32 | unsigned 32-bit integer.
+// :s32, :S32 | signed 32-bit integer.
+//
+// :u64, :U64 | unsigned 64-bit integer.
+// :s64, :S64 | signed 64-bit integer.
+//
+// :f32, :F32 | 32-bit floating point number.
+// :f64, :F64 | 64-bit floating point number.
+
+#define ruby_swap8(value) value
+
+union swapf32 {
+ uint32_t integral;
+ float value;
+};
+
+static float
+ruby_swapf32(float value)
+{
+ union swapf32 swap = {.value = value};
+ swap.integral = ruby_swap32(swap.integral);
+ return swap.value;
+}
+
+union swapf64 {
+ uint64_t integral;
+ double value;
+};
+
+static double
+ruby_swapf64(double value)
+{
+ union swapf64 swap = {.value = value};
+ swap.integral = ruby_swap64(swap.integral);
+ return swap.value;
+}
+
+#define IO_BUFFER_DECLARE_TYPE(name, type, endian, wrap, unwrap, swap) \
+static ID RB_IO_BUFFER_DATA_TYPE_##name; \
+\
+static VALUE \
+io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
+{ \
+ io_buffer_validate_type(size, *offset + sizeof(type)); \
+ type value; \
+ memcpy(&value, (char*)base + *offset, sizeof(type)); \
+ if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
+ *offset += sizeof(type); \
+ return wrap(value); \
+} \
+\
+static void \
+io_buffer_write_##name(const void* base, size_t size, size_t *offset, VALUE _value) \
+{ \
+ io_buffer_validate_type(size, *offset + sizeof(type)); \
+ type value = unwrap(_value); \
+ if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
+ memcpy((char*)base + *offset, &value, sizeof(type)); \
+ *offset += sizeof(type); \
+} \
+\
+enum { \
+ RB_IO_BUFFER_DATA_TYPE_##name##_SIZE = sizeof(type) \
+};
+
+IO_BUFFER_DECLARE_TYPE(U8, uint8_t, RB_IO_BUFFER_BIG_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap8)
+IO_BUFFER_DECLARE_TYPE(S8, int8_t, RB_IO_BUFFER_BIG_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap8)
+
+IO_BUFFER_DECLARE_TYPE(u16, uint16_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap16)
+IO_BUFFER_DECLARE_TYPE(U16, uint16_t, RB_IO_BUFFER_BIG_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap16)
+IO_BUFFER_DECLARE_TYPE(s16, int16_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap16)
+IO_BUFFER_DECLARE_TYPE(S16, int16_t, RB_IO_BUFFER_BIG_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap16)
+
+IO_BUFFER_DECLARE_TYPE(u32, uint32_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap32)
+IO_BUFFER_DECLARE_TYPE(U32, uint32_t, RB_IO_BUFFER_BIG_ENDIAN, RB_UINT2NUM, RB_NUM2UINT, ruby_swap32)
+IO_BUFFER_DECLARE_TYPE(s32, int32_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap32)
+IO_BUFFER_DECLARE_TYPE(S32, int32_t, RB_IO_BUFFER_BIG_ENDIAN, RB_INT2NUM, RB_NUM2INT, ruby_swap32)
+
+IO_BUFFER_DECLARE_TYPE(u64, uint64_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_ULL2NUM, RB_NUM2ULL, ruby_swap64)
+IO_BUFFER_DECLARE_TYPE(U64, uint64_t, RB_IO_BUFFER_BIG_ENDIAN, RB_ULL2NUM, RB_NUM2ULL, ruby_swap64)
+IO_BUFFER_DECLARE_TYPE(s64, int64_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_LL2NUM, RB_NUM2LL, ruby_swap64)
+IO_BUFFER_DECLARE_TYPE(S64, int64_t, RB_IO_BUFFER_BIG_ENDIAN, RB_LL2NUM, RB_NUM2LL, ruby_swap64)
+
+IO_BUFFER_DECLARE_TYPE(f32, float, RB_IO_BUFFER_LITTLE_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf32)
+IO_BUFFER_DECLARE_TYPE(F32, float, RB_IO_BUFFER_BIG_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf32)
+IO_BUFFER_DECLARE_TYPE(f64, double, RB_IO_BUFFER_LITTLE_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf64)
+IO_BUFFER_DECLARE_TYPE(F64, double, RB_IO_BUFFER_BIG_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf64)
+#undef IO_BUFFER_DECLARE_TYPE
+
+static inline size_t
+io_buffer_buffer_type_size(ID buffer_type)
+{
+#define IO_BUFFER_DATA_TYPE_SIZE(name) if (buffer_type == RB_IO_BUFFER_DATA_TYPE_##name) return RB_IO_BUFFER_DATA_TYPE_##name##_SIZE;
+ IO_BUFFER_DATA_TYPE_SIZE(U8)
+ IO_BUFFER_DATA_TYPE_SIZE(S8)
+ IO_BUFFER_DATA_TYPE_SIZE(u16)
+ IO_BUFFER_DATA_TYPE_SIZE(U16)
+ IO_BUFFER_DATA_TYPE_SIZE(s16)
+ IO_BUFFER_DATA_TYPE_SIZE(S16)
+ IO_BUFFER_DATA_TYPE_SIZE(u32)
+ IO_BUFFER_DATA_TYPE_SIZE(U32)
+ IO_BUFFER_DATA_TYPE_SIZE(s32)
+ IO_BUFFER_DATA_TYPE_SIZE(S32)
+ IO_BUFFER_DATA_TYPE_SIZE(u64)
+ IO_BUFFER_DATA_TYPE_SIZE(U64)
+ IO_BUFFER_DATA_TYPE_SIZE(s64)
+ IO_BUFFER_DATA_TYPE_SIZE(S64)
+ IO_BUFFER_DATA_TYPE_SIZE(f32)
+ IO_BUFFER_DATA_TYPE_SIZE(F32)
+ IO_BUFFER_DATA_TYPE_SIZE(f64)
+ IO_BUFFER_DATA_TYPE_SIZE(F64)
+#undef IO_BUFFER_DATA_TYPE_SIZE
+
+ rb_raise(rb_eArgError, "Invalid type name!");
+}
+
+/*
+ * call-seq:
+ * size_of(buffer_type) -> byte size
+ * size_of(array of buffer_type) -> byte size
+ *
+ * Returns the size of the given buffer type(s) in bytes.
+ *
+ * Example:
+ *
+ * IO::Buffer.size_of(:u32) # => 4
+ * IO::Buffer.size_of([:u32, :u32]) # => 8
+ */
+static VALUE
+io_buffer_size_of(VALUE klass, VALUE buffer_type)
+{
+ if (RB_TYPE_P(buffer_type, T_ARRAY)) {
+ size_t total = 0;
+ for (long i = 0; i < RARRAY_LEN(buffer_type); i++) {
+ total += io_buffer_buffer_type_size(RB_SYM2ID(RARRAY_AREF(buffer_type, i)));
+ }
+ return SIZET2NUM(total);
+ }
+ else {
+ return SIZET2NUM(io_buffer_buffer_type_size(RB_SYM2ID(buffer_type)));
+ }
+}
+
+static inline VALUE
+rb_io_buffer_get_value(const void* base, size_t size, ID buffer_type, size_t *offset)
+{
+#define IO_BUFFER_GET_VALUE(name) if (buffer_type == RB_IO_BUFFER_DATA_TYPE_##name) return io_buffer_read_##name(base, size, offset);
+ IO_BUFFER_GET_VALUE(U8)
+ IO_BUFFER_GET_VALUE(S8)
+
+ IO_BUFFER_GET_VALUE(u16)
+ IO_BUFFER_GET_VALUE(U16)
+ IO_BUFFER_GET_VALUE(s16)
+ IO_BUFFER_GET_VALUE(S16)
+
+ IO_BUFFER_GET_VALUE(u32)
+ IO_BUFFER_GET_VALUE(U32)
+ IO_BUFFER_GET_VALUE(s32)
+ IO_BUFFER_GET_VALUE(S32)
+
+ IO_BUFFER_GET_VALUE(u64)
+ IO_BUFFER_GET_VALUE(U64)
+ IO_BUFFER_GET_VALUE(s64)
+ IO_BUFFER_GET_VALUE(S64)
+
+ IO_BUFFER_GET_VALUE(f32)
+ IO_BUFFER_GET_VALUE(F32)
+ IO_BUFFER_GET_VALUE(f64)
+ IO_BUFFER_GET_VALUE(F64)
+#undef IO_BUFFER_GET_VALUE
+
+ rb_raise(rb_eArgError, "Invalid type name!");
+}
+
+/*
+ * call-seq: get_value(buffer_type, offset) -> numeric
+ *
+ * Read from buffer a value of +type+ at +offset+. +buffer_type+ should be one
+ * of symbols:
+ *
+ * * +:U8+: unsigned integer, 1 byte
+ * * +:S8+: signed integer, 1 byte
+ * * +:u16+: unsigned integer, 2 bytes, little-endian
+ * * +:U16+: unsigned integer, 2 bytes, big-endian
+ * * +:s16+: signed integer, 2 bytes, little-endian
+ * * +:S16+: signed integer, 2 bytes, big-endian
+ * * +:u32+: unsigned integer, 4 bytes, little-endian
+ * * +:U32+: unsigned integer, 4 bytes, big-endian
+ * * +:s32+: signed integer, 4 bytes, little-endian
+ * * +:S32+: signed integer, 4 bytes, big-endian
+ * * +:u64+: unsigned integer, 8 bytes, little-endian
+ * * +:U64+: unsigned integer, 8 bytes, big-endian
+ * * +:s64+: signed integer, 8 bytes, little-endian
+ * * +:S64+: signed integer, 8 bytes, big-endian
+ * * +:f32+: float, 4 bytes, little-endian
+ * * +:F32+: float, 4 bytes, big-endian
+ * * +:f64+: double, 8 bytes, little-endian
+ * * +:F64+: double, 8 bytes, big-endian
+ *
+ * A buffer type refers specifically to the type of binary buffer that is stored
+ * in the buffer. For example, a +:u32+ buffer type is a 32-bit unsigned
+ * integer in little-endian format.
+ *
+ * Example:
+ *
+ * string = [1.5].pack('f')
+ * # => "\x00\x00\xC0?"
+ * IO::Buffer.for(string).get_value(:f32, 0)
+ * # => 1.5
+ */
+static VALUE
+io_buffer_get_value(VALUE self, VALUE type, VALUE _offset)
+{
+ const void *base;
+ size_t size;
+ size_t offset = io_buffer_extract_offset(_offset);
+
+ rb_io_buffer_get_bytes_for_reading(self, &base, &size);
+
+ return rb_io_buffer_get_value(base, size, RB_SYM2ID(type), &offset);
+}
+
+/*
+ * call-seq: get_values(buffer_types, offset) -> array
+ *
+ * Similar to #get_value, except that it can handle multiple buffer types and
+ * returns an array of values.
+ *
+ * Example:
+ *
+ * string = [1.5, 2.5].pack('ff')
+ * IO::Buffer.for(string).get_values([:f32, :f32], 0)
+ * # => [1.5, 2.5]
+ */
+static VALUE
+io_buffer_get_values(VALUE self, VALUE buffer_types, VALUE _offset)
+{
+ size_t offset = io_buffer_extract_offset(_offset);
+
+ const void *base;
+ size_t size;
+ rb_io_buffer_get_bytes_for_reading(self, &base, &size);
+
+ if (!RB_TYPE_P(buffer_types, T_ARRAY)) {
+ rb_raise(rb_eArgError, "Argument buffer_types should be an array!");
+ }
+
+ VALUE array = rb_ary_new_capa(RARRAY_LEN(buffer_types));
+
+ for (long i = 0; i < RARRAY_LEN(buffer_types); i++) {
+ VALUE type = rb_ary_entry(buffer_types, i);
+ VALUE value = rb_io_buffer_get_value(base, size, RB_SYM2ID(type), &offset);
+ rb_ary_push(array, value);
+ }
+
+ return array;
+}
+
+// Extract a count argument, which must be a positive integer.
+// Count is generally considered relative to the number of things.
+static inline size_t
+io_buffer_extract_count(VALUE argument)
+{
+ if (rb_int_negative_p(argument)) {
+ rb_raise(rb_eArgError, "Count can't be negative!");
+ }
+
+ return NUM2SIZET(argument);
+}
+
+static inline void
+io_buffer_extract_offset_count(ID buffer_type, size_t size, int argc, VALUE *argv, size_t *offset, size_t *count)
+{
+ if (argc >= 1) {
+ *offset = io_buffer_extract_offset(argv[0]);
+ }
+ else {
+ *offset = 0;
+ }
+
+ if (argc >= 2) {
+ *count = io_buffer_extract_count(argv[1]);
+ }
+ else {
+ if (*offset > size) {
+ rb_raise(rb_eArgError, "The given offset is bigger than the buffer size!");
+ }
+
+ *count = (size - *offset) / io_buffer_buffer_type_size(buffer_type);
+ }
+}
+
+/*
+ * call-seq:
+ * each(buffer_type, [offset, [count]]) {|offset, value| ...} -> self
+ * each(buffer_type, [offset, [count]]) -> enumerator
+ *
+ * Iterates over the buffer, yielding each +value+ of +buffer_type+ starting
+ * from +offset+.
+ *
+ * If +count+ is given, only +count+ values will be yielded.
+ *
+ * Example:
+ *
+ * IO::Buffer.for("Hello World").each(:U8, 2, 2) do |offset, value|
+ * puts "#{offset}: #{value}"
+ * end
+ * # 2: 108
+ * # 3: 108
+ */
+static VALUE
+io_buffer_each(int argc, VALUE *argv, VALUE self)
+{
+ RETURN_ENUMERATOR_KW(self, argc, argv, RB_NO_KEYWORDS);
+
+ const void *base;
+ size_t size;
+
+ rb_io_buffer_get_bytes_for_reading(self, &base, &size);
+
+ ID buffer_type;
+ if (argc >= 1) {
+ buffer_type = RB_SYM2ID(argv[0]);
+ }
+ else {
+ buffer_type = RB_IO_BUFFER_DATA_TYPE_U8;
+ }
+
+ size_t offset, count;
+ io_buffer_extract_offset_count(buffer_type, size, argc-1, argv+1, &offset, &count);
+
+ for (size_t i = 0; i < count; i++) {
+ size_t current_offset = offset;
+ VALUE value = rb_io_buffer_get_value(base, size, buffer_type, &offset);
+ rb_yield_values(2, SIZET2NUM(current_offset), value);
+ }
+
+ return self;
+}
+
+/*
+ * call-seq: values(buffer_type, [offset, [count]]) -> array
+ *
+ * Returns an array of values of +buffer_type+ starting from +offset+.
+ *
+ * If +count+ is given, only +count+ values will be returned.
+ *
+ * Example:
+ *
+ * IO::Buffer.for("Hello World").values(:U8, 2, 2)
+ * # => [108, 108]
+ */
+static VALUE
+io_buffer_values(int argc, VALUE *argv, VALUE self)
+{
+ const void *base;
+ size_t size;
+
+ rb_io_buffer_get_bytes_for_reading(self, &base, &size);
+
+ ID buffer_type;
+ if (argc >= 1) {
+ buffer_type = RB_SYM2ID(argv[0]);
+ }
+ else {
+ buffer_type = RB_IO_BUFFER_DATA_TYPE_U8;
+ }
+
+ size_t offset, count;
+ io_buffer_extract_offset_count(buffer_type, size, argc-1, argv+1, &offset, &count);
+
+ VALUE array = rb_ary_new_capa(count);
+
+ for (size_t i = 0; i < count; i++) {
+ VALUE value = rb_io_buffer_get_value(base, size, buffer_type, &offset);
+ rb_ary_push(array, value);
+ }
+
+ return array;
+}
+
+/*
+ * call-seq:
+ * each_byte([offset, [count]]) {|offset, byte| ...} -> self
+ * each_byte([offset, [count]]) -> enumerator
+ *
+ * Iterates over the buffer, yielding each byte starting from +offset+.
+ *
+ * If +count+ is given, only +count+ bytes will be yielded.
+ *
+ * Example:
+ *
+ * IO::Buffer.for("Hello World").each_byte(2, 2) do |offset, byte|
+ * puts "#{offset}: #{byte}"
+ * end
+ * # 2: 108
+ * # 3: 108
+ */
+static VALUE
+io_buffer_each_byte(int argc, VALUE *argv, VALUE self)
+{
+ RETURN_ENUMERATOR_KW(self, argc, argv, RB_NO_KEYWORDS);
+
+ const void *base;
+ size_t size;
+
+ rb_io_buffer_get_bytes_for_reading(self, &base, &size);
+
+ size_t offset, count;
+ io_buffer_extract_offset_count(RB_IO_BUFFER_DATA_TYPE_U8, size, argc-1, argv+1, &offset, &count);
+
+ for (size_t i = 0; i < count; i++) {
+ unsigned char *value = (unsigned char *)base + i + offset;
+ rb_yield(RB_INT2FIX(*value));
+ }
+
+ return self;
+}
+
+static inline void
+rb_io_buffer_set_value(const void* base, size_t size, ID buffer_type, size_t *offset, VALUE value)
+{
+#define IO_BUFFER_SET_VALUE(name) if (buffer_type == RB_IO_BUFFER_DATA_TYPE_##name) {io_buffer_write_##name(base, size, offset, value); return;}
+ IO_BUFFER_SET_VALUE(U8);
+ IO_BUFFER_SET_VALUE(S8);
+
+ IO_BUFFER_SET_VALUE(u16);
+ IO_BUFFER_SET_VALUE(U16);
+ IO_BUFFER_SET_VALUE(s16);
+ IO_BUFFER_SET_VALUE(S16);
+
+ IO_BUFFER_SET_VALUE(u32);
+ IO_BUFFER_SET_VALUE(U32);
+ IO_BUFFER_SET_VALUE(s32);
+ IO_BUFFER_SET_VALUE(S32);
+
+ IO_BUFFER_SET_VALUE(u64);
+ IO_BUFFER_SET_VALUE(U64);
+ IO_BUFFER_SET_VALUE(s64);
+ IO_BUFFER_SET_VALUE(S64);
+
+ IO_BUFFER_SET_VALUE(f32);
+ IO_BUFFER_SET_VALUE(F32);
+ IO_BUFFER_SET_VALUE(f64);
+ IO_BUFFER_SET_VALUE(F64);
+#undef IO_BUFFER_SET_VALUE
+
+ rb_raise(rb_eArgError, "Invalid type name!");
+}
+
+/*
+ * call-seq: set_value(type, offset, value) -> offset
+ *
+ * Write to a buffer a +value+ of +type+ at +offset+. +type+ should be one of
+ * symbols described in #get_value.
+ *
+ * buffer = IO::Buffer.new(8)
+ * # =>
+ * # #<IO::Buffer 0x0000555f5c9a2d50+8 INTERNAL>
+ * # 0x00000000 00 00 00 00 00 00 00 00
+ *
+ * buffer.set_value(:U8, 1, 111)
+ * # => 1
+ *
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x0000555f5c9a2d50+8 INTERNAL>
+ * # 0x00000000 00 6f 00 00 00 00 00 00 .o......
+ *
+ * Note that if the +type+ is integer and +value+ is Float, the implicit truncation is performed:
+ *
+ * buffer = IO::Buffer.new(8)
+ * buffer.set_value(:U32, 0, 2.5)
+ *
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x0000555f5c9a2d50+8 INTERNAL>
+ * # 0x00000000 00 00 00 02 00 00 00 00
+ * # ^^ the same as if we'd pass just integer 2
+ */
+static VALUE
+io_buffer_set_value(VALUE self, VALUE type, VALUE _offset, VALUE value)
+{
+ void *base;
+ size_t size;
+ size_t offset = io_buffer_extract_offset(_offset);
+
+ rb_io_buffer_get_bytes_for_writing(self, &base, &size);
+
+ rb_io_buffer_set_value(base, size, RB_SYM2ID(type), &offset, value);
+
+ return SIZET2NUM(offset);
+}
+
+/*
+ * call-seq: set_values(buffer_types, offset, values) -> offset
+ *
+ * Write +values+ of +buffer_types+ at +offset+ to the buffer. +buffer_types+
+ * should be an array of symbols as described in #get_value. +values+ should
+ * be an array of values to write.
+ *
+ * Example:
+ *
+ * buffer = IO::Buffer.new(8)
+ * buffer.set_values([:U8, :U16], 0, [1, 2])
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x696f717561746978+8 INTERNAL>
+ * # 0x00000000 01 00 02 00 00 00 00 00 ........
+ */
+static VALUE
+io_buffer_set_values(VALUE self, VALUE buffer_types, VALUE _offset, VALUE values)
+{
+ if (!RB_TYPE_P(buffer_types, T_ARRAY)) {
+ rb_raise(rb_eArgError, "Argument buffer_types should be an array!");
+ }
+
+ if (!RB_TYPE_P(values, T_ARRAY)) {
+ rb_raise(rb_eArgError, "Argument values should be an array!");
+ }
+
+ if (RARRAY_LEN(buffer_types) != RARRAY_LEN(values)) {
+ rb_raise(rb_eArgError, "Argument buffer_types and values should have the same length!");
+ }
+
+ size_t offset = io_buffer_extract_offset(_offset);
+
+ void *base;
+ size_t size;
+ rb_io_buffer_get_bytes_for_writing(self, &base, &size);
+
+ for (long i = 0; i < RARRAY_LEN(buffer_types); i++) {
+ VALUE type = rb_ary_entry(buffer_types, i);
+ VALUE value = rb_ary_entry(values, i);
+ rb_io_buffer_set_value(base, size, RB_SYM2ID(type), &offset, value);
+ }
+
+ return SIZET2NUM(offset);
+}
+
+static void
+io_buffer_memcpy(struct rb_io_buffer *buffer, size_t offset, const void *source_base, size_t source_offset, size_t source_size, size_t length)
+{
+ void *base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ if (source_offset + length > source_size) {
+ rb_raise(rb_eArgError, "The computed source range exceeds the size of the source buffer!");
+ }
+
+ memcpy((unsigned char*)base+offset, (unsigned char*)source_base+source_offset, length);
+}
+
+// (offset, length, source_offset) -> length
+static VALUE
+io_buffer_copy_from(struct rb_io_buffer *buffer, const void *source_base, size_t source_size, int argc, VALUE *argv)
+{
+ size_t offset = 0;
+ size_t length;
+ size_t source_offset;
+
+ // The offset we copy into the buffer:
+ if (argc >= 1) {
+ offset = io_buffer_extract_offset(argv[0]);
+ }
+
+ // The offset we start from within the string:
+ if (argc >= 3) {
+ source_offset = io_buffer_extract_offset(argv[2]);
+
+ if (source_offset > source_size) {
+ rb_raise(rb_eArgError, "The given source offset is bigger than the source itself!");
+ }
+ }
+ else {
+ source_offset = 0;
+ }
+
+ // The length we are going to copy:
+ if (argc >= 2 && !RB_NIL_P(argv[1])) {
+ length = io_buffer_extract_length(argv[1]);
+ }
+ else {
+ // Default to the source offset -> source size:
+ length = source_size - source_offset;
+ }
+
+ io_buffer_memcpy(buffer, offset, source_base, source_offset, source_size, length);
+
+ return SIZET2NUM(length);
+}
+
+/*
+ * call-seq:
+ * dup -> io_buffer
+ * clone -> io_buffer
+ *
+ * Make an internal copy of the source buffer. Updates to the copy will not
+ * affect the source buffer.
+ *
+ * source = IO::Buffer.for("Hello World")
+ * # =>
+ * # #<IO::Buffer 0x00007fd598466830+11 EXTERNAL READONLY SLICE>
+ * # 0x00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 Hello World
+ * buffer = source.dup
+ * # =>
+ * # #<IO::Buffer 0x0000558cbec03320+11 INTERNAL>
+ * # 0x00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 Hello World
+ */
+static VALUE
+rb_io_buffer_initialize_copy(VALUE self, VALUE source)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ const void *source_base;
+ size_t source_size;
+
+ rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
+
+ io_buffer_initialize(buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);
+
+ return io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
+}
+
+/*
+ * call-seq:
+ * copy(source, [offset, [length, [source_offset]]]) -> size
+ *
+ * Efficiently copy buffer from a source IO::Buffer into the buffer,
+ * at +offset+ using +memcpy+. For copying String instances, see #set_string.
+ *
+ * buffer = IO::Buffer.new(32)
+ * # =>
+ * # #<IO::Buffer 0x0000555f5ca22520+32 INTERNAL>
+ * # 0x00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ * # 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ *
+ *
+ * buffer.copy(IO::Buffer.for("test"), 8)
+ * # => 4 -- size of buffer copied
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x0000555f5cf8fe40+32 INTERNAL>
+ * # 0x00000000 00 00 00 00 00 00 00 00 74 65 73 74 00 00 00 00 ........test....
+ * # 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ *
+ *
+ * #copy can be used to put buffer into strings associated with buffer:
+ *
+ * string= "buffer: "
+ * # => "buffer: "
+ * buffer = IO::Buffer.for(string)
+ * buffer.copy(IO::Buffer.for("test"), 5)
+ * # => 4
+ * string
+ * # => "buffer:test"
+ *
+ * Attempt to copy into a read-only buffer will fail:
+ *
+ * File.write('test.txt', 'test')
+ * buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY)
+ * buffer.copy(IO::Buffer.for("test"), 8)
+ * # in `copy': Buffer is not writable! (IO::Buffer::AccessError)
+ *
+ * See ::map for details of creation of mutable file mappings, this will
+ * work:
+ *
+ * buffer = IO::Buffer.map(File.open('test.txt', 'r+'))
+ * buffer.copy(IO::Buffer.for("boom"), 0)
+ * # => 4
+ * File.read('test.txt')
+ * # => "boom"
+ *
+ * Attempt to copy the buffer which will need place outside of buffer's
+ * bounds will fail:
+ *
+ * buffer = IO::Buffer.new(2)
+ * buffer.copy(IO::Buffer.for('test'), 0)
+ * # in `copy': Specified offset+length is bigger than the buffer size! (ArgumentError)
+ */
+static VALUE
+io_buffer_copy(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, 4);
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ VALUE source = argv[0];
+ const void *source_base;
+ size_t source_size;
+
+ rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
+
+ return io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
+}
+
+/*
+ * call-seq: get_string([offset, [length, [encoding]]]) -> string
+ *
+ * Read a chunk or all of the buffer into a string, in the specified
+ * +encoding+. If no encoding is provided +Encoding::BINARY+ is used.
+ *
+ * buffer = IO::Buffer.for('test')
+ * buffer.get_string
+ * # => "test"
+ * buffer.get_string(2)
+ * # => "st"
+ * buffer.get_string(2, 1)
+ * # => "s"
+ */
+static VALUE
+io_buffer_get_string(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 0, 3);
+
+ size_t offset, length;
+ struct rb_io_buffer *buffer = io_buffer_extract_offset_length(self, argc, argv, &offset, &length);
+
+ const void *base;
+ size_t size;
+ io_buffer_get_bytes_for_reading(buffer, &base, &size);
+
+ rb_encoding *encoding;
+ if (argc >= 3) {
+ encoding = rb_find_encoding(argv[2]);
+ }
+ else {
+ encoding = rb_ascii8bit_encoding();
+ }
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ return rb_enc_str_new((const char*)base + offset, length, encoding);
+}
+
+/*
+ * call-seq: set_string(string, [offset, [length, [source_offset]]]) -> size
+ *
+ * Efficiently copy buffer from a source String into the buffer,
+ * at +offset+ using +memcpy+.
+ *
+ * buf = IO::Buffer.new(8)
+ * # =>
+ * # #<IO::Buffer 0x0000557412714a20+8 INTERNAL>
+ * # 0x00000000 00 00 00 00 00 00 00 00 ........
+ *
+ * # set buffer starting from offset 1, take 2 bytes starting from string's
+ * # second
+ * buf.set_string('test', 1, 2, 1)
+ * # => 2
+ * buf
+ * # =>
+ * # #<IO::Buffer 0x0000557412714a20+8 INTERNAL>
+ * # 0x00000000 00 65 73 00 00 00 00 00 .es.....
+ *
+ * See also #copy for examples of how buffer writing might be used for changing
+ * associated strings and files.
+ */
+static VALUE
+io_buffer_set_string(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, 4);
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ VALUE string = rb_str_to_str(argv[0]);
+
+ const void *source_base = RSTRING_PTR(string);
+ size_t source_size = RSTRING_LEN(string);
+
+ return io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
+}
+
+void
+rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ void *base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ memset((char*)base + offset, value, length);
+}
+
+/*
+ * call-seq: clear(value = 0, [offset, [length]]) -> self
+ *
+ * Fill buffer with +value+, starting with +offset+ and going for +length+
+ * bytes.
+ *
+ * buffer = IO::Buffer.for('test')
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 74 65 73 74 test
+ *
+ * buffer.clear
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 00 00 00 00 ....
+ *
+ * buf.clear(1) # fill with 1
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 01 01 01 01 ....
+ *
+ * buffer.clear(2, 1, 2) # fill with 2, starting from offset 1, for 2 bytes
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 01 02 02 01 ....
+ *
+ * buffer.clear(2, 1) # fill with 2, starting from offset 1
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 01 02 02 02 ....
+ */
+static VALUE
+io_buffer_clear(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 0, 3);
+
+ uint8_t value = 0;
+ if (argc >= 1) {
+ value = NUM2UINT(argv[0]);
+ }
+
+ size_t offset, length;
+ io_buffer_extract_offset_length(self, argc-1, argv+1, &offset, &length);
+
+ rb_io_buffer_clear(self, value, offset, length);
+
+ return self;
+}
+
+static size_t
+io_buffer_default_size(size_t page_size)
+{
+ // Platform agnostic default size, based on empirical performance observation:
+ const size_t platform_agnostic_default_size = 64*1024;
+
+ // Allow user to specify custom default buffer size:
+ const char *default_size = getenv("RUBY_IO_BUFFER_DEFAULT_SIZE");
+ if (default_size) {
+ // For the purpose of setting a default size, 2^31 is an acceptable maximum:
+ int value = atoi(default_size);
+
+ // assuming sizeof(int) <= sizeof(size_t)
+ if (value > 0) {
+ return value;
+ }
+ }
+
+ if (platform_agnostic_default_size < page_size) {
+ return page_size;
+ }
+
+ return platform_agnostic_default_size;
+}
+
+struct io_buffer_blocking_region_argument {
+ struct rb_io_buffer *buffer;
+ rb_blocking_function_t *function;
+ void *data;
+ int descriptor;
+};
+
+static VALUE
+io_buffer_blocking_region_begin(VALUE _argument)
+{
+ struct io_buffer_blocking_region_argument *argument = (void*)_argument;
+
+ return rb_thread_io_blocking_region(argument->function, argument->data, argument->descriptor);
+}
+
+static VALUE
+io_buffer_blocking_region_ensure(VALUE _argument)
+{
+ struct io_buffer_blocking_region_argument *argument = (void*)_argument;
+
+ io_buffer_unlock(argument->buffer);
+
+ return Qnil;
+}
+
+static VALUE
+io_buffer_blocking_region(struct rb_io_buffer *buffer, rb_blocking_function_t *function, void *data, int descriptor)
+{
+ struct io_buffer_blocking_region_argument argument = {
+ .buffer = buffer,
+ .function = function,
+ .data = data,
+ .descriptor = descriptor,
+ };
+
+ // If the buffer is already locked, we can skip the ensure (unlock):
+ if (buffer->flags & RB_IO_BUFFER_LOCKED) {
+ return io_buffer_blocking_region_begin((VALUE)&argument);
+ }
+ else {
+ // The buffer should be locked for the duration of the blocking region:
+ io_buffer_lock(buffer);
+
+ return rb_ensure(io_buffer_blocking_region_begin, (VALUE)&argument, io_buffer_blocking_region_ensure, (VALUE)&argument);
+ }
+}
+
+struct io_buffer_read_internal_argument {
+ int descriptor;
+
+ // The base pointer to read from:
+ char *base;
+ // The size of the buffer:
+ size_t size;
+
+ // The minimum number of bytes to read:
+ size_t length;
+};
+
+static VALUE
+io_buffer_read_internal(void *_argument)
+{
+ size_t total = 0;
+ struct io_buffer_read_internal_argument *argument = _argument;
+
+ while (true) {
+ ssize_t result = read(argument->descriptor, argument->base, argument->size);
+
+ if (result < 0) {
+ return rb_fiber_scheduler_io_result(result, errno);
+ }
+ else if (result == 0) {
+ return rb_fiber_scheduler_io_result(total, 0);
+ }
+ else {
+ total += result;
+
+ if (total >= argument->length) {
+ return rb_fiber_scheduler_io_result(total, 0);
+ }
+
+ argument->base = argument->base + result;
+ argument->size = argument->size - result;
+ }
+ }
+}
+
+VALUE
+rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset)
+{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_read(scheduler, io, self, length, offset);
+
+ if (!UNDEF_P(result)) {
+ return result;
+ }
+ }
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ int descriptor = rb_io_descriptor(io);
+
+ void * base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ base = (unsigned char*)base + offset;
+ size = size - offset;
+
+ struct io_buffer_read_internal_argument argument = {
+ .descriptor = descriptor,
+ .base = base,
+ .size = size,
+ .length = length,
+ };
+
+ return io_buffer_blocking_region(buffer, io_buffer_read_internal, &argument, descriptor);
+}
+
+/*
+ * call-seq: read(io, [length, [offset]]) -> read length or -errno
+ *
+ * Read at least +length+ bytes from the +io+, into the buffer starting at
+ * +offset+. If an error occurs, return <tt>-errno</tt>.
+ *
+ * If +length+ is not given or +nil+, it defaults to the size of the buffer
+ * minus the offset, i.e. the entire buffer.
+ *
+ * If +length+ is zero, exactly one <tt>read</tt> operation will occur.
+ *
+ * If +offset+ is not given, it defaults to zero, i.e. the beginning of the
+ * buffer.
+ *
+ * IO::Buffer.for('test') do |buffer|
+ * p buffer
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 74 65 73 74 test
+ * buffer.read(File.open('/dev/urandom', 'rb'), 2)
+ * p buffer
+ * # =>
+ * # <IO::Buffer 0x00007f3bc65f2a58+4 EXTERNAL SLICE>
+ * # 0x00000000 05 35 73 74 .5st
+ * end
+ */
+static VALUE
+io_buffer_read(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, 3);
+
+ VALUE io = argv[0];
+
+ size_t length, offset;
+ io_buffer_extract_length_offset(self, argc-1, argv+1, &length, &offset);
+
+ return rb_io_buffer_read(self, io, length, offset);
+}
+
+struct io_buffer_pread_internal_argument {
+ int descriptor;
+ void *base;
+ size_t size;
+ off_t offset;
+};
+
+static VALUE
+io_buffer_pread_internal(void *_argument)
+{
+ struct io_buffer_pread_internal_argument *argument = _argument;
+
+#if defined(HAVE_PREAD)
+ ssize_t result = pread(argument->descriptor, argument->base, argument->size, argument->offset);
+#else
+ // This emulation is not thread safe.
+ rb_off_t offset = lseek(argument->descriptor, 0, SEEK_CUR);
+ if (offset == (rb_off_t)-1)
+ return rb_fiber_scheduler_io_result(-1, errno);
+
+ if (lseek(argument->descriptor, argument->offset, SEEK_SET) == (rb_off_t)-1)
+ return rb_fiber_scheduler_io_result(-1, errno);
+
+ ssize_t result = read(argument->descriptor, argument->base, argument->size);
+
+ if (lseek(argument->descriptor, offset, SEEK_SET) == (rb_off_t)-1)
+ return rb_fiber_scheduler_io_result(-1, errno);
+#endif
+
+ return rb_fiber_scheduler_io_result(result, errno);
+}
+
+VALUE
+rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset)
+{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, from, self, length, offset);
+
+ if (!UNDEF_P(result)) {
+ return result;
+ }
+ }
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ int descriptor = rb_io_descriptor(io);
+
+ void * base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ struct io_buffer_pread_internal_argument argument = {
+ .descriptor = descriptor,
+
+ // Move the base pointer to the offset:
+ .base = (unsigned char*)base + offset,
+
+ // And the size to the length of buffer we want to read:
+ .size = length,
+
+ // From the offset in the file we want to read from:
+ .offset = from,
+ };
+
+ return io_buffer_blocking_region(buffer, io_buffer_pread_internal, &argument, descriptor);
+}
+
+/*
+ * call-seq: pread(io, from, length, [offset]) -> read length or -errno
+ *
+ * Read at most +length+ bytes from +io+ into the buffer, starting at
+ * +from+, and put it in buffer starting from specified +offset+.
+ * If an error occurs, return <tt>-errno</tt>.
+ *
+ * If +offset+ is not given, put it at the beginning of the buffer.
+ *
+ * Example:
+ *
+ * IO::Buffer.for('test') do |buffer|
+ * p buffer
+ * # =>
+ * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # 0x00000000 74 65 73 74 test
+ *
+ * # take 2 bytes from the beginning of urandom,
+ * # put them in buffer starting from position 2
+ * buffer.pread(File.open('/dev/urandom', 'rb'), 0, 2, 2)
+ * p buffer
+ * # =>
+ * # <IO::Buffer 0x00007f3bc65f2a58+4 EXTERNAL SLICE>
+ * # 0x00000000 05 35 73 74 te.5
+ * end
+ */
+static VALUE
+io_buffer_pread(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 2, 4);
+
+ VALUE io = argv[0];
+ rb_off_t from = NUM2OFFT(argv[1]);
+
+ size_t length, offset;
+ io_buffer_extract_length_offset(self, argc-2, argv+2, &length, &offset);
+
+ return rb_io_buffer_pread(self, io, from, length, offset);
+}
+
+struct io_buffer_write_internal_argument {
+ int descriptor;
+
+ // The base pointer to write from:
+ const char *base;
+ // The size of the buffer:
+ size_t size;
+
+ // The minimum length to write:
+ size_t length;
+};
+
+static VALUE
+io_buffer_write_internal(void *_argument)
+{
+ size_t total = 0;
+ struct io_buffer_write_internal_argument *argument = _argument;
+
+ while (true) {
+ ssize_t result = write(argument->descriptor, argument->base, argument->size);
+
+ if (result < 0) {
+ return rb_fiber_scheduler_io_result(result, errno);
+ }
+ else if (result == 0) {
+ return rb_fiber_scheduler_io_result(total, 0);
+ }
+ else {
+ total += result;
+
+ if (total >= argument->length) {
+ return rb_fiber_scheduler_io_result(total, 0);
+ }
+
+ argument->base = argument->base + result;
+ argument->size = argument->size - result;
+ }
+ }
+}
+
+VALUE
+rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset)
+{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_write(scheduler, io, self, length, offset);
+
+ if (!UNDEF_P(result)) {
+ return result;
+ }
+ }
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ int descriptor = rb_io_descriptor(io);
+
+ const void * base;
+ size_t size;
+ io_buffer_get_bytes_for_reading(buffer, &base, &size);
+
+ base = (unsigned char*)base + offset;
+ size = size - offset;
+
+ struct io_buffer_write_internal_argument argument = {
+ .descriptor = descriptor,
+ .base = base,
+ .size = size,
+ .length = length,
+ };
+
+ return io_buffer_blocking_region(buffer, io_buffer_write_internal, &argument, descriptor);
+}
+
+/*
+ * call-seq: write(io, [length, [offset]]) -> written length or -errno
+ *
+ * Write at least +length+ bytes from the buffer starting at +offset+, into the +io+.
+ * If an error occurs, return <tt>-errno</tt>.
+ *
+ * If +length+ is not given or +nil+, it defaults to the size of the buffer
+ * minus the offset, i.e. the entire buffer.
+ *
+ * If +length+ is zero, exactly one <tt>write</tt> operation will occur.
+ *
+ * If +offset+ is not given, it defaults to zero, i.e. the beginning of the
+ * buffer.
+ *
+ * out = File.open('output.txt', 'wb')
+ * IO::Buffer.for('1234567').write(out, 3)
+ *
+ * This leads to +123+ being written into <tt>output.txt</tt>
+ */
+static VALUE
+io_buffer_write(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 1, 3);
+
+ VALUE io = argv[0];
+
+ size_t length, offset;
+ io_buffer_extract_length_offset(self, argc-1, argv+1, &length, &offset);
+
+ return rb_io_buffer_write(self, io, length, offset);
+}
+
+struct io_buffer_pwrite_internal_argument {
+ int descriptor;
+ const void *base;
+ size_t size;
+ off_t offset;
+};
+
+static VALUE
+io_buffer_pwrite_internal(void *_argument)
+{
+ struct io_buffer_pwrite_internal_argument *argument = _argument;
+
+#if defined(HAVE_PWRITE)
+ ssize_t result = pwrite(argument->descriptor, argument->base, argument->size, argument->offset);
+#else
+ // This emulation is not thread safe.
+ rb_off_t offset = lseek(argument->descriptor, 0, SEEK_CUR);
+ if (offset == (rb_off_t)-1)
+ return rb_fiber_scheduler_io_result(-1, errno);
+
+ if (lseek(argument->descriptor, argument->offset, SEEK_SET) == (rb_off_t)-1)
+ return rb_fiber_scheduler_io_result(-1, errno);
+
+ ssize_t result = write(argument->descriptor, argument->base, argument->size);
+
+ if (lseek(argument->descriptor, offset, SEEK_SET) == (rb_off_t)-1)
+ return rb_fiber_scheduler_io_result(-1, errno);
+#endif
+
+ return rb_fiber_scheduler_io_result(result, errno);
+}
+
+VALUE
+rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset)
+{
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, from, self, length, offset);
+
+ if (!UNDEF_P(result)) {
+ return result;
+ }
+ }
+
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ io_buffer_validate_range(buffer, offset, length);
+
+ int descriptor = rb_io_descriptor(io);
+
+ const void * base;
+ size_t size;
+ io_buffer_get_bytes_for_reading(buffer, &base, &size);
+
+ struct io_buffer_pwrite_internal_argument argument = {
+ .descriptor = descriptor,
+
+ // Move the base pointer to the offset:
+ .base = (unsigned char *)base + offset,
+
+ // And the size to the length of buffer we want to read:
+ .size = length,
+
+ // And the offset in the file we want to write from:
+ .offset = from,
+ };
+
+ return io_buffer_blocking_region(buffer, io_buffer_pwrite_internal, &argument, descriptor);
+}
+
+/*
+ * call-seq: pwrite(io, from, length, [offset]) -> written length or -errno
+ *
+ * Writes +length+ bytes from buffer into +io+, starting at
+ * +offset+ in the buffer. If an error occurs, return <tt>-errno</tt>.
+ *
+ * If +offset+ is not given, the bytes are taken from the beginning of the
+ * buffer. If the +offset+ is given and is beyond the end of the file, the
+ * gap will be filled with null (0 value) bytes.
+ *
+ * out = File.open('output.txt', File::RDWR) # open for read/write, no truncation
+ * IO::Buffer.for('1234567').pwrite(out, 2, 3, 1)
+ *
+ * This leads to +234+ (3 bytes, starting from position 1) being written into
+ * <tt>output.txt</tt>, starting from file position 2.
+ */
+static VALUE
+io_buffer_pwrite(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 2, 4);
+
+ VALUE io = argv[0];
+ rb_off_t from = NUM2OFFT(argv[1]);
+
+ size_t length, offset;
+ io_buffer_extract_length_offset(self, argc-2, argv+2, &length, &offset);
+
+ return rb_io_buffer_pwrite(self, io, from, length, offset);
+}
+
+static inline void
+io_buffer_check_mask(const struct rb_io_buffer *buffer)
+{
+ if (buffer->size == 0)
+ rb_raise(rb_eIOBufferMaskError, "Zero-length mask given!");
+}
+
+static void
+memory_and(unsigned char * restrict output, unsigned char * restrict base, size_t size, unsigned char * restrict mask, size_t mask_size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ output[offset] = base[offset] & mask[offset % mask_size];
+ }
+}
+
+/*
+ * call-seq:
+ * source & mask -> io_buffer
+ *
+ * Generate a new buffer the same size as the source by applying the binary AND
+ * operation to the source, using the mask, repeating as necessary.
+ *
+ * IO::Buffer.for("1234567890") & IO::Buffer.for("\xFF\x00\x00\xFF")
+ * # =>
+ * # #<IO::Buffer 0x00005589b2758480+4 INTERNAL>
+ * # 0x00000000 31 00 00 34 35 00 00 38 39 00 1..45..89.
+ */
+static VALUE
+io_buffer_and(VALUE self, VALUE mask)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ struct rb_io_buffer *mask_buffer = NULL;
+ TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer);
+
+ io_buffer_check_mask(mask_buffer);
+
+ VALUE output = rb_io_buffer_new(NULL, buffer->size, io_flags_for_size(buffer->size));
+ struct rb_io_buffer *output_buffer = NULL;
+ TypedData_Get_Struct(output, struct rb_io_buffer, &rb_io_buffer_type, output_buffer);
+
+ memory_and(output_buffer->base, buffer->base, buffer->size, mask_buffer->base, mask_buffer->size);
+
+ return output;
+}
+
+static void
+memory_or(unsigned char * restrict output, unsigned char * restrict base, size_t size, unsigned char * restrict mask, size_t mask_size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ output[offset] = base[offset] | mask[offset % mask_size];
+ }
+}
+
+/*
+ * call-seq:
+ * source | mask -> io_buffer
+ *
+ * Generate a new buffer the same size as the source by applying the binary OR
+ * operation to the source, using the mask, repeating as necessary.
+ *
+ * IO::Buffer.for("1234567890") | IO::Buffer.for("\xFF\x00\x00\xFF")
+ * # =>
+ * # #<IO::Buffer 0x0000561785ae3480+10 INTERNAL>
+ * # 0x00000000 ff 32 33 ff ff 36 37 ff ff 30 .23..67..0
+ */
+static VALUE
+io_buffer_or(VALUE self, VALUE mask)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ struct rb_io_buffer *mask_buffer = NULL;
+ TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer);
+
+ io_buffer_check_mask(mask_buffer);
+
+ VALUE output = rb_io_buffer_new(NULL, buffer->size, io_flags_for_size(buffer->size));
+ struct rb_io_buffer *output_buffer = NULL;
+ TypedData_Get_Struct(output, struct rb_io_buffer, &rb_io_buffer_type, output_buffer);
+
+ memory_or(output_buffer->base, buffer->base, buffer->size, mask_buffer->base, mask_buffer->size);
+
+ return output;
+}
+
+static void
+memory_xor(unsigned char * restrict output, unsigned char * restrict base, size_t size, unsigned char * restrict mask, size_t mask_size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ output[offset] = base[offset] ^ mask[offset % mask_size];
+ }
+}
+
+/*
+ * call-seq:
+ * source ^ mask -> io_buffer
+ *
+ * Generate a new buffer the same size as the source by applying the binary XOR
+ * operation to the source, using the mask, repeating as necessary.
+ *
+ * IO::Buffer.for("1234567890") ^ IO::Buffer.for("\xFF\x00\x00\xFF")
+ * # =>
+ * # #<IO::Buffer 0x000055a2d5d10480+10 INTERNAL>
+ * # 0x00000000 ce 32 33 cb ca 36 37 c7 c6 30 .23..67..0
+ */
+static VALUE
+io_buffer_xor(VALUE self, VALUE mask)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ struct rb_io_buffer *mask_buffer = NULL;
+ TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer);
+
+ io_buffer_check_mask(mask_buffer);
+
+ VALUE output = rb_io_buffer_new(NULL, buffer->size, io_flags_for_size(buffer->size));
+ struct rb_io_buffer *output_buffer = NULL;
+ TypedData_Get_Struct(output, struct rb_io_buffer, &rb_io_buffer_type, output_buffer);
+
+ memory_xor(output_buffer->base, buffer->base, buffer->size, mask_buffer->base, mask_buffer->size);
+
+ return output;
+}
+
+static void
+memory_not(unsigned char * restrict output, unsigned char * restrict base, size_t size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ output[offset] = ~base[offset];
+ }
+}
+
+/*
+ * call-seq:
+ * ~source -> io_buffer
+ *
+ * Generate a new buffer the same size as the source by applying the binary NOT
+ * operation to the source.
+ *
+ * ~IO::Buffer.for("1234567890")
+ * # =>
+ * # #<IO::Buffer 0x000055a5ac42f120+10 INTERNAL>
+ * # 0x00000000 ce cd cc cb ca c9 c8 c7 c6 cf ..........
+ */
+static VALUE
+io_buffer_not(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ VALUE output = rb_io_buffer_new(NULL, buffer->size, io_flags_for_size(buffer->size));
+ struct rb_io_buffer *output_buffer = NULL;
+ TypedData_Get_Struct(output, struct rb_io_buffer, &rb_io_buffer_type, output_buffer);
+
+ memory_not(output_buffer->base, buffer->base, buffer->size);
+
+ return output;
+}
+
+static inline int
+io_buffer_overlaps(const struct rb_io_buffer *a, const struct rb_io_buffer *b)
+{
+ if (a->base > b->base) {
+ return io_buffer_overlaps(b, a);
+ }
+
+ return (b->base >= a->base) && (b->base <= (void*)((unsigned char *)a->base + a->size));
+}
+
+static inline void
+io_buffer_check_overlaps(struct rb_io_buffer *a, struct rb_io_buffer *b)
+{
+ if (io_buffer_overlaps(a, b))
+ rb_raise(rb_eIOBufferMaskError, "Mask overlaps source buffer!");
+}
+
+static void
+memory_and_inplace(unsigned char * restrict base, size_t size, unsigned char * restrict mask, size_t mask_size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ base[offset] &= mask[offset % mask_size];
+ }
+}
+
+/*
+ * call-seq:
+ * source.and!(mask) -> io_buffer
+ *
+ * Modify the source buffer in place by applying the binary AND
+ * operation to the source, using the mask, repeating as necessary.
+ *
+ * source = IO::Buffer.for("1234567890").dup # Make a read/write copy.
+ * # =>
+ * # #<IO::Buffer 0x000056307a0d0c20+10 INTERNAL>
+ * # 0x00000000 31 32 33 34 35 36 37 38 39 30 1234567890
+ *
+ * source.and!(IO::Buffer.for("\xFF\x00\x00\xFF"))
+ * # =>
+ * # #<IO::Buffer 0x000056307a0d0c20+10 INTERNAL>
+ * # 0x00000000 31 00 00 34 35 00 00 38 39 00 1..45..89.
+ */
+static VALUE
+io_buffer_and_inplace(VALUE self, VALUE mask)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ struct rb_io_buffer *mask_buffer = NULL;
+ TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer);
+
+ io_buffer_check_mask(mask_buffer);
+ io_buffer_check_overlaps(buffer, mask_buffer);
+
+ void *base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ memory_and_inplace(base, size, mask_buffer->base, mask_buffer->size);
+
+ return self;
+}
+
+static void
+memory_or_inplace(unsigned char * restrict base, size_t size, unsigned char * restrict mask, size_t mask_size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ base[offset] |= mask[offset % mask_size];
+ }
+}
+
+/*
+ * call-seq:
+ * source.or!(mask) -> io_buffer
+ *
+ * Modify the source buffer in place by applying the binary OR
+ * operation to the source, using the mask, repeating as necessary.
+ *
+ * source = IO::Buffer.for("1234567890").dup # Make a read/write copy.
+ * # =>
+ * # #<IO::Buffer 0x000056307a272350+10 INTERNAL>
+ * # 0x00000000 31 32 33 34 35 36 37 38 39 30 1234567890
+ *
+ * source.or!(IO::Buffer.for("\xFF\x00\x00\xFF"))
+ * # =>
+ * # #<IO::Buffer 0x000056307a272350+10 INTERNAL>
+ * # 0x00000000 ff 32 33 ff ff 36 37 ff ff 30 .23..67..0
+ */
+static VALUE
+io_buffer_or_inplace(VALUE self, VALUE mask)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ struct rb_io_buffer *mask_buffer = NULL;
+ TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer);
+
+ io_buffer_check_mask(mask_buffer);
+ io_buffer_check_overlaps(buffer, mask_buffer);
+
+ void *base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ memory_or_inplace(base, size, mask_buffer->base, mask_buffer->size);
+
+ return self;
+}
+
+static void
+memory_xor_inplace(unsigned char * restrict base, size_t size, unsigned char * restrict mask, size_t mask_size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ base[offset] ^= mask[offset % mask_size];
+ }
+}
+
+/*
+ * call-seq:
+ * source.xor!(mask) -> io_buffer
+ *
+ * Modify the source buffer in place by applying the binary XOR
+ * operation to the source, using the mask, repeating as necessary.
+ *
+ * source = IO::Buffer.for("1234567890").dup # Make a read/write copy.
+ * # =>
+ * # #<IO::Buffer 0x000056307a25b3e0+10 INTERNAL>
+ * # 0x00000000 31 32 33 34 35 36 37 38 39 30 1234567890
+ *
+ * source.xor!(IO::Buffer.for("\xFF\x00\x00\xFF"))
+ * # =>
+ * # #<IO::Buffer 0x000056307a25b3e0+10 INTERNAL>
+ * # 0x00000000 ce 32 33 cb ca 36 37 c7 c6 30 .23..67..0
+ */
+static VALUE
+io_buffer_xor_inplace(VALUE self, VALUE mask)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ struct rb_io_buffer *mask_buffer = NULL;
+ TypedData_Get_Struct(mask, struct rb_io_buffer, &rb_io_buffer_type, mask_buffer);
+
+ io_buffer_check_mask(mask_buffer);
+ io_buffer_check_overlaps(buffer, mask_buffer);
+
+ void *base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ memory_xor_inplace(base, size, mask_buffer->base, mask_buffer->size);
+
+ return self;
+}
+
+static void
+memory_not_inplace(unsigned char * restrict base, size_t size)
+{
+ for (size_t offset = 0; offset < size; offset += 1) {
+ base[offset] = ~base[offset];
+ }
+}
+
+/*
+ * call-seq:
+ * source.not! -> io_buffer
+ *
+ * Modify the source buffer in place by applying the binary NOT
+ * operation to the source.
+ *
+ * source = IO::Buffer.for("1234567890").dup # Make a read/write copy.
+ * # =>
+ * # #<IO::Buffer 0x000056307a33a450+10 INTERNAL>
+ * # 0x00000000 31 32 33 34 35 36 37 38 39 30 1234567890
+ *
+ * source.not!
+ * # =>
+ * # #<IO::Buffer 0x000056307a33a450+10 INTERNAL>
+ * # 0x00000000 ce cd cc cb ca c9 c8 c7 c6 cf ..........
+ */
+static VALUE
+io_buffer_not_inplace(VALUE self)
+{
+ struct rb_io_buffer *buffer = NULL;
+ TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
+
+ void *base;
+ size_t size;
+ io_buffer_get_bytes_for_writing(buffer, &base, &size);
+
+ memory_not_inplace(base, size);
+
+ return self;
+}
+
+/*
+ * Document-class: IO::Buffer
+ *
+ * IO::Buffer is a low-level efficient buffer for input/output. There are three
+ * ways of using buffer:
+ *
+ * * Create an empty buffer with ::new, fill it with buffer using #copy or
+ * #set_value, #set_string, get buffer with #get_string;
+ * * Create a buffer mapped to some string with ::for, then it could be used
+ * both for reading with #get_string or #get_value, and writing (writing will
+ * change the source string, too);
+ * * Create a buffer mapped to some file with ::map, then it could be used for
+ * reading and writing the underlying file.
+ *
+ * Interaction with string and file memory is performed by efficient low-level
+ * C mechanisms like `memcpy`.
+ *
+ * The class is meant to be an utility for implementing more high-level mechanisms
+ * like Fiber::SchedulerInterface#io_read and Fiber::SchedulerInterface#io_write.
+ *
+ * <b>Examples of usage:</b>
+ *
+ * Empty buffer:
+ *
+ * buffer = IO::Buffer.new(8) # create empty 8-byte buffer
+ * # =>
+ * # #<IO::Buffer 0x0000555f5d1a5c50+8 INTERNAL>
+ * # ...
+ * buffer
+ * # =>
+ * # <IO::Buffer 0x0000555f5d156ab0+8 INTERNAL>
+ * # 0x00000000 00 00 00 00 00 00 00 00
+ * buffer.set_string('test', 2) # put there bytes of the "test" string, starting from offset 2
+ * # => 4
+ * buffer.get_string # get the result
+ * # => "\x00\x00test\x00\x00"
+ *
+ * \Buffer from string:
+ *
+ * string = 'buffer'
+ * buffer = IO::Buffer.for(string)
+ * # =>
+ * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
+ * # ...
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
+ * # 0x00000000 64 61 74 61 buffer
+ *
+ * buffer.get_string(2) # read content starting from offset 2
+ * # => "ta"
+ * buffer.set_string('---', 1) # write content, starting from offset 1
+ * # => 3
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x00007f3f02be9b18+4 SLICE>
+ * # 0x00000000 64 2d 2d 2d d---
+ * string # original string changed, too
+ * # => "d---"
+ *
+ * \Buffer from file:
+ *
+ * File.write('test.txt', 'test buffer')
+ * # => 9
+ * buffer = IO::Buffer.map(File.open('test.txt'))
+ * # =>
+ * # #<IO::Buffer 0x00007f3f0768c000+9 MAPPED IMMUTABLE>
+ * # ...
+ * buffer.get_string(5, 2) # read 2 bytes, starting from offset 5
+ * # => "da"
+ * buffer.set_string('---', 1) # attempt to write
+ * # in `set_string': Buffer is not writable! (IO::Buffer::AccessError)
+ *
+ * # To create writable file-mapped buffer
+ * # Open file for read-write, pass size, offset, and flags=0
+ * buffer = IO::Buffer.map(File.open('test.txt', 'r+'), 9, 0, 0)
+ * buffer.set_string('---', 1)
+ * # => 3 -- bytes written
+ * File.read('test.txt')
+ * # => "t--- buffer"
+ *
+ * <b>The class is experimental and the interface is subject to change.</b>
+ */
+void
+Init_IO_Buffer(void)
+{
+ rb_cIOBuffer = rb_define_class_under(rb_cIO, "Buffer", rb_cObject);
+ rb_eIOBufferLockedError = rb_define_class_under(rb_cIOBuffer, "LockedError", rb_eRuntimeError);
+ rb_eIOBufferAllocationError = rb_define_class_under(rb_cIOBuffer, "AllocationError", rb_eRuntimeError);
+ rb_eIOBufferAccessError = rb_define_class_under(rb_cIOBuffer, "AccessError", rb_eRuntimeError);
+ rb_eIOBufferInvalidatedError = rb_define_class_under(rb_cIOBuffer, "InvalidatedError", rb_eRuntimeError);
+ rb_eIOBufferMaskError = rb_define_class_under(rb_cIOBuffer, "MaskError", rb_eArgError);
+
+ rb_define_alloc_func(rb_cIOBuffer, rb_io_buffer_type_allocate);
+ rb_define_singleton_method(rb_cIOBuffer, "for", rb_io_buffer_type_for, 1);
+
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ RUBY_IO_BUFFER_PAGE_SIZE = info.dwPageSize;
+#else /* not WIN32 */
+ RUBY_IO_BUFFER_PAGE_SIZE = sysconf(_SC_PAGESIZE);
+#endif
+
+ RUBY_IO_BUFFER_DEFAULT_SIZE = io_buffer_default_size(RUBY_IO_BUFFER_PAGE_SIZE);
+
+ // Efficient sizing of mapped buffers:
+ rb_define_const(rb_cIOBuffer, "PAGE_SIZE", SIZET2NUM(RUBY_IO_BUFFER_PAGE_SIZE));
+ rb_define_const(rb_cIOBuffer, "DEFAULT_SIZE", SIZET2NUM(RUBY_IO_BUFFER_DEFAULT_SIZE));
+
+ rb_define_singleton_method(rb_cIOBuffer, "map", io_buffer_map, -1);
+
+ // General use:
+ rb_define_method(rb_cIOBuffer, "initialize", rb_io_buffer_initialize, -1);
+ rb_define_method(rb_cIOBuffer, "initialize_copy", rb_io_buffer_initialize_copy, 1);
+ rb_define_method(rb_cIOBuffer, "inspect", rb_io_buffer_inspect, 0);
+ rb_define_method(rb_cIOBuffer, "hexdump", rb_io_buffer_hexdump, 0);
+ rb_define_method(rb_cIOBuffer, "to_s", rb_io_buffer_to_s, 0);
+ rb_define_method(rb_cIOBuffer, "size", rb_io_buffer_size, 0);
+ rb_define_method(rb_cIOBuffer, "valid?", rb_io_buffer_valid_p, 0);
+
+ // Ownership:
+ rb_define_method(rb_cIOBuffer, "transfer", rb_io_buffer_transfer, 0);
+
+ // Flags:
+ rb_define_const(rb_cIOBuffer, "EXTERNAL", RB_INT2NUM(RB_IO_BUFFER_EXTERNAL));
+ rb_define_const(rb_cIOBuffer, "INTERNAL", RB_INT2NUM(RB_IO_BUFFER_INTERNAL));
+ rb_define_const(rb_cIOBuffer, "MAPPED", RB_INT2NUM(RB_IO_BUFFER_MAPPED));
+ rb_define_const(rb_cIOBuffer, "SHARED", RB_INT2NUM(RB_IO_BUFFER_SHARED));
+ rb_define_const(rb_cIOBuffer, "LOCKED", RB_INT2NUM(RB_IO_BUFFER_LOCKED));
+ rb_define_const(rb_cIOBuffer, "PRIVATE", RB_INT2NUM(RB_IO_BUFFER_PRIVATE));
+ rb_define_const(rb_cIOBuffer, "READONLY", RB_INT2NUM(RB_IO_BUFFER_READONLY));
+
+ // Endian:
+ rb_define_const(rb_cIOBuffer, "LITTLE_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_LITTLE_ENDIAN));
+ rb_define_const(rb_cIOBuffer, "BIG_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_BIG_ENDIAN));
+ rb_define_const(rb_cIOBuffer, "HOST_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_HOST_ENDIAN));
+ rb_define_const(rb_cIOBuffer, "NETWORK_ENDIAN", RB_INT2NUM(RB_IO_BUFFER_NETWORK_ENDIAN));
+
+ rb_define_method(rb_cIOBuffer, "null?", rb_io_buffer_null_p, 0);
+ rb_define_method(rb_cIOBuffer, "empty?", rb_io_buffer_empty_p, 0);
+ rb_define_method(rb_cIOBuffer, "external?", rb_io_buffer_external_p, 0);
+ rb_define_method(rb_cIOBuffer, "internal?", rb_io_buffer_internal_p, 0);
+ rb_define_method(rb_cIOBuffer, "mapped?", rb_io_buffer_mapped_p, 0);
+ rb_define_method(rb_cIOBuffer, "shared?", rb_io_buffer_shared_p, 0);
+ rb_define_method(rb_cIOBuffer, "locked?", rb_io_buffer_locked_p, 0);
+ rb_define_method(rb_cIOBuffer, "readonly?", io_buffer_readonly_p, 0);
+
+ // Locking to prevent changes while using pointer:
+ // rb_define_method(rb_cIOBuffer, "lock", rb_io_buffer_lock, 0);
+ // rb_define_method(rb_cIOBuffer, "unlock", rb_io_buffer_unlock, 0);
+ rb_define_method(rb_cIOBuffer, "locked", rb_io_buffer_locked, 0);
+
+ // Manipulation:
+ rb_define_method(rb_cIOBuffer, "slice", io_buffer_slice, -1);
+ rb_define_method(rb_cIOBuffer, "<=>", rb_io_buffer_compare, 1);
+ rb_define_method(rb_cIOBuffer, "resize", io_buffer_resize, 1);
+ rb_define_method(rb_cIOBuffer, "clear", io_buffer_clear, -1);
+ rb_define_method(rb_cIOBuffer, "free", rb_io_buffer_free, 0);
+
+ rb_include_module(rb_cIOBuffer, rb_mComparable);
+
+#define IO_BUFFER_DEFINE_DATA_TYPE(name) RB_IO_BUFFER_DATA_TYPE_##name = rb_intern_const(#name)
+ IO_BUFFER_DEFINE_DATA_TYPE(U8);
+ IO_BUFFER_DEFINE_DATA_TYPE(S8);
+
+ IO_BUFFER_DEFINE_DATA_TYPE(u16);
+ IO_BUFFER_DEFINE_DATA_TYPE(U16);
+ IO_BUFFER_DEFINE_DATA_TYPE(s16);
+ IO_BUFFER_DEFINE_DATA_TYPE(S16);
+
+ IO_BUFFER_DEFINE_DATA_TYPE(u32);
+ IO_BUFFER_DEFINE_DATA_TYPE(U32);
+ IO_BUFFER_DEFINE_DATA_TYPE(s32);
+ IO_BUFFER_DEFINE_DATA_TYPE(S32);
+
+ IO_BUFFER_DEFINE_DATA_TYPE(u64);
+ IO_BUFFER_DEFINE_DATA_TYPE(U64);
+ IO_BUFFER_DEFINE_DATA_TYPE(s64);
+ IO_BUFFER_DEFINE_DATA_TYPE(S64);
+
+ IO_BUFFER_DEFINE_DATA_TYPE(f32);
+ IO_BUFFER_DEFINE_DATA_TYPE(F32);
+ IO_BUFFER_DEFINE_DATA_TYPE(f64);
+ IO_BUFFER_DEFINE_DATA_TYPE(F64);
+#undef IO_BUFFER_DEFINE_DATA_TYPE
+
+ rb_define_singleton_method(rb_cIOBuffer, "size_of", io_buffer_size_of, 1);
+
+ // Data access:
+ rb_define_method(rb_cIOBuffer, "get_value", io_buffer_get_value, 2);
+ rb_define_method(rb_cIOBuffer, "get_values", io_buffer_get_values, 2);
+ rb_define_method(rb_cIOBuffer, "each", io_buffer_each, -1);
+ rb_define_method(rb_cIOBuffer, "values", io_buffer_values, -1);
+ rb_define_method(rb_cIOBuffer, "each_byte", io_buffer_each_byte, -1);
+ rb_define_method(rb_cIOBuffer, "set_value", io_buffer_set_value, 3);
+ rb_define_method(rb_cIOBuffer, "set_values", io_buffer_set_values, 3);
+
+ rb_define_method(rb_cIOBuffer, "copy", io_buffer_copy, -1);
+
+ rb_define_method(rb_cIOBuffer, "get_string", io_buffer_get_string, -1);
+ rb_define_method(rb_cIOBuffer, "set_string", io_buffer_set_string, -1);
+
+ // Binary buffer manipulations:
+ rb_define_method(rb_cIOBuffer, "&", io_buffer_and, 1);
+ rb_define_method(rb_cIOBuffer, "|", io_buffer_or, 1);
+ rb_define_method(rb_cIOBuffer, "^", io_buffer_xor, 1);
+ rb_define_method(rb_cIOBuffer, "~", io_buffer_not, 0);
+
+ rb_define_method(rb_cIOBuffer, "and!", io_buffer_and_inplace, 1);
+ rb_define_method(rb_cIOBuffer, "or!", io_buffer_or_inplace, 1);
+ rb_define_method(rb_cIOBuffer, "xor!", io_buffer_xor_inplace, 1);
+ rb_define_method(rb_cIOBuffer, "not!", io_buffer_not_inplace, 0);
+
+ // IO operations:
+ rb_define_method(rb_cIOBuffer, "read", io_buffer_read, -1);
+ rb_define_method(rb_cIOBuffer, "pread", io_buffer_pread, -1);
+ rb_define_method(rb_cIOBuffer, "write", io_buffer_write, -1);
+ rb_define_method(rb_cIOBuffer, "pwrite", io_buffer_pwrite, -1);
+}
diff --git a/iseq.c b/iseq.c
index b08f1bb497..d17ce486c5 100644
--- a/iseq.c
+++ b/iseq.c
@@ -38,7 +38,8 @@
#include "ruby/util.h"
#include "vm_core.h"
#include "vm_callinfo.h"
-
+#include "yjit.h"
+#include "ruby/ractor.h"
#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
@@ -59,19 +60,19 @@ static inline VALUE
obj_resurrect(VALUE obj)
{
if (hidden_obj_p(obj)) {
- switch (BUILTIN_TYPE(obj)) {
- case T_STRING:
- obj = rb_str_resurrect(obj);
- break;
- case T_ARRAY:
- obj = rb_ary_resurrect(obj);
- break;
+ switch (BUILTIN_TYPE(obj)) {
+ case T_STRING:
+ obj = rb_str_resurrect(obj);
+ break;
+ case T_ARRAY:
+ obj = rb_ary_resurrect(obj);
+ break;
case T_HASH:
obj = rb_hash_resurrect(obj);
break;
default:
- break;
- }
+ break;
+ }
}
return obj;
}
@@ -92,12 +93,68 @@ static void
compile_data_free(struct iseq_compile_data *compile_data)
{
if (compile_data) {
- free_arena(compile_data->node.storage_head);
- free_arena(compile_data->insn.storage_head);
- if (compile_data->ivar_cache_table) {
- rb_id_table_free(compile_data->ivar_cache_table);
- }
- ruby_xfree(compile_data);
+ free_arena(compile_data->node.storage_head);
+ free_arena(compile_data->insn.storage_head);
+ if (compile_data->ivar_cache_table) {
+ rb_id_table_free(compile_data->ivar_cache_table);
+ }
+ ruby_xfree(compile_data);
+ }
+}
+
+static void
+remove_from_constant_cache(ID id, IC ic)
+{
+ rb_vm_t *vm = GET_VM();
+ VALUE lookup_result;
+ st_data_t ic_data = (st_data_t)ic;
+
+ if (rb_id_table_lookup(vm->constant_cache, id, &lookup_result)) {
+ st_table *ics = (st_table *)lookup_result;
+ st_delete(ics, &ic_data, NULL);
+
+ if (ics->num_entries == 0 &&
+ // See comment in vm_track_constant_cache on why we need this check
+ id != vm->inserting_constant_cache_id) {
+ rb_id_table_delete(vm->constant_cache, id);
+ st_free_table(ics);
+ }
+ }
+}
+
+// When an ISEQ is being freed, all of its associated ICs are going to go away
+// as well. Because of this, we need to iterate over the ICs, and clear them
+// from the VM's constant cache.
+static void
+iseq_clear_ic_references(const rb_iseq_t *iseq)
+{
+ // In some cases (when there is a compilation error), we end up with
+ // ic_size greater than 0, but no allocated is_entries buffer.
+ // If there's no is_entries buffer to loop through, return early.
+ // [Bug #19173]
+ if (!ISEQ_BODY(iseq)->is_entries) {
+ return;
+ }
+
+ for (unsigned int ic_idx = 0; ic_idx < ISEQ_BODY(iseq)->ic_size; ic_idx++) {
+ IC ic = &ISEQ_IS_IC_ENTRY(ISEQ_BODY(iseq), ic_idx);
+
+ // Iterate over the IC's constant path's segments and clean any references to
+ // the ICs out of the VM's constant cache table.
+ const ID *segments = ic->segments;
+
+ // It's possible that segments is NULL if we overallocated an IC but
+ // optimizations removed the instruction using it
+ if (segments == NULL)
+ continue;
+
+ for (int i = 0; segments[i]; i++) {
+ ID id = segments[i];
+ if (id == idNULL) continue;
+ remove_from_constant_cache(id, ic);
+ }
+
+ ruby_xfree((void *)segments);
}
}
@@ -106,32 +163,43 @@ rb_iseq_free(const rb_iseq_t *iseq)
{
RUBY_FREE_ENTER("iseq");
- if (iseq && iseq->body) {
- struct rb_iseq_constant_body *const body = iseq->body;
- mjit_free_iseq(iseq); /* Notify MJIT */
- ruby_xfree((void *)body->iseq_encoded);
- ruby_xfree((void *)body->insns_info.body);
- if (body->insns_info.positions) ruby_xfree((void *)body->insns_info.positions);
+ if (iseq && ISEQ_BODY(iseq)) {
+ iseq_clear_ic_references(iseq);
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ mjit_free_iseq(iseq); /* Notify MJIT */
+#if USE_YJIT
+ rb_yjit_iseq_free(body->yjit_payload);
+#endif
+ ruby_xfree((void *)body->iseq_encoded);
+ ruby_xfree((void *)body->insns_info.body);
+ if (body->insns_info.positions) ruby_xfree((void *)body->insns_info.positions);
#if VM_INSN_INFO_TABLE_IMPL == 2
- if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
+ if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
#endif
if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl))
ruby_xfree((void *)body->local_table);
- ruby_xfree((void *)body->is_entries);
+ ruby_xfree((void *)body->is_entries);
if (body->call_data) {
ruby_xfree(body->call_data);
- }
- ruby_xfree((void *)body->catch_table);
- ruby_xfree((void *)body->param.opt_table);
-
- if (body->param.keyword != NULL) {
- ruby_xfree((void *)body->param.keyword->default_values);
- ruby_xfree((void *)body->param.keyword);
- }
- compile_data_free(ISEQ_COMPILE_DATA(iseq));
+ }
+ ruby_xfree((void *)body->catch_table);
+ ruby_xfree((void *)body->param.opt_table);
+ if (ISEQ_MBITS_BUFLEN(body->iseq_size) > 1 && body->mark_bits.list) {
+ ruby_xfree((void *)body->mark_bits.list);
+ }
+
+ ruby_xfree(body->variable.original_iseq);
+
+ if (body->param.keyword != NULL) {
+ if (body->param.keyword->table != &body->local_table[body->param.keyword->bits_start - body->param.keyword->num])
+ ruby_xfree((void *)body->param.keyword->table);
+ ruby_xfree((void *)body->param.keyword->default_values);
+ 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);
+ ruby_xfree(body);
}
if (iseq && ISEQ_EXECUTABLE_P(iseq) && iseq->aux.exec.local_hooks) {
@@ -141,89 +209,27 @@ rb_iseq_free(const rb_iseq_t *iseq)
RUBY_FREE_LEAVE("iseq");
}
-#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
-static VALUE
-rb_vm_insn_addr2insn2(const void *addr)
-{
- return (VALUE)rb_vm_insn_addr2insn(addr);
-}
-#endif
-
-static VALUE
-rb_vm_insn_null_translator(const void *addr)
-{
- return (VALUE)addr;
-}
-
typedef VALUE iseq_value_itr_t(void *ctx, VALUE obj);
-typedef VALUE rb_vm_insns_translator_t(const void *addr);
-static int
-iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator)
-{
- VALUE insn = translator((void *)code[pos]);
- int len = insn_len(insn);
- int op_no;
- const char *types = insn_op_types(insn);
-
- for (op_no = 0; types[op_no]; op_no++) {
- char type = types[op_no];
- switch (type) {
- case TS_CDHASH:
- case TS_ISEQ:
- case TS_VALUE:
- {
- VALUE op = code[pos + op_no + 1];
- if (!SPECIAL_CONST_P(op)) {
- VALUE newop = func(data, op);
- if (newop != op) {
- code[pos + op_no + 1] = newop;
- }
- }
- }
- 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;
- }
- }
+static inline void
+iseq_scan_bits(unsigned int page, iseq_bits_t bits, VALUE *code, iseq_value_itr_t *func, void *data)
+{
+ unsigned int offset;
+ unsigned int page_offset = (page * ISEQ_MBITS_BITLENGTH);
+
+ while (bits) {
+ offset = ntz_intptr(bits);
+ VALUE op = code[page_offset + offset];
+ VALUE newop = func(data, op);
+ if (newop != op) {
+ code[page_offset + offset] = newop;
+ if (data) {
+ VALUE *original_iseq = (VALUE *)data;
+ original_iseq[page_offset + offset] = newop;
}
- 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];
- if (is->once.value) {
- VALUE nv = func(data, is->once.value);
- if (is->once.value != nv) {
- is->once.value = nv;
- }
- }
- }
- break;
- default:
- break;
- }
+ }
+ bits &= bits - 1; // Reset Lowest Set Bit (BLSR)
}
-
- return len;
}
static void
@@ -231,19 +237,66 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data)
{
unsigned int size;
VALUE *code;
- size_t n;
- rb_vm_insns_translator_t *const translator =
-#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
- (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;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size = body->iseq_size;
code = body->iseq_encoded;
- for (n = 0; n < size;) {
- n += iseq_extract_values(code, n, func, data, translator);
+ union iseq_inline_storage_entry *is_entries = body->is_entries;
+
+ if (body->is_entries) {
+ // Skip iterating over ivc caches
+ is_entries += body->ivc_size;
+
+ // ICVARC entries
+ for (unsigned int i = 0; i < body->icvarc_size; i++, is_entries++) {
+ ICVARC icvarc = (ICVARC)is_entries;
+ if (icvarc->entry) {
+ RUBY_ASSERT(!RB_TYPE_P(icvarc->entry->class_value, T_NONE));
+
+ VALUE nv = func(data, icvarc->entry->class_value);
+ if (icvarc->entry->class_value != nv) {
+ icvarc->entry->class_value = nv;
+ }
+ }
+ }
+
+ // ISE entries
+ for (unsigned int i = 0; i < body->ise_size; i++, is_entries++) {
+ union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)is_entries;
+ if (is->once.value) {
+ VALUE nv = func(data, is->once.value);
+ if (is->once.value != nv) {
+ is->once.value = nv;
+ }
+ }
+ }
+
+ // IC Entries
+ for (unsigned int i = 0; i < body->ic_size; i++, is_entries++) {
+ IC ic = (IC)is_entries;
+ if (ic->entry) {
+ VALUE nv = func(data, (VALUE)ic->entry);
+ if ((VALUE)ic->entry != nv) {
+ ic->entry = (void *)nv;
+ }
+ }
+ }
+ }
+
+ // Embedded VALUEs
+ if (body->mark_bits.list) {
+ if (ISEQ_MBITS_BUFLEN(size) == 1) {
+ iseq_scan_bits(0, body->mark_bits.single, code, func, data);
+ }
+ else {
+ if (body->mark_bits.list) {
+ for (unsigned int i = 0; i < ISEQ_MBITS_BUFLEN(size); i++) {
+ iseq_bits_t bits = body->mark_bits.list[i];
+ iseq_scan_bits(i, bits, code, func, data);
+ }
+ }
+ }
}
}
@@ -256,11 +309,12 @@ update_each_insn_value(void *ctx, VALUE obj)
void
rb_iseq_update_references(rb_iseq_t *iseq)
{
- if (iseq->body) {
- struct rb_iseq_constant_body *body = iseq->body;
+ if (ISEQ_BODY(iseq)) {
+ struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
body->variable.coverage = rb_gc_location(body->variable.coverage);
body->variable.pc2branchindex = rb_gc_location(body->variable.pc2branchindex);
+ body->variable.script_lines = rb_gc_location(body->variable.script_lines);
body->location.label = rb_gc_location(body->location.label);
body->location.base_label = rb_gc_location(body->location.base_label);
body->location.pathobj = rb_gc_location(body->location.pathobj);
@@ -270,6 +324,9 @@ 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 (body->mandatory_only_iseq) {
+ body->mandatory_only_iseq = (struct rb_iseq_struct *)rb_gc_location((VALUE)body->mandatory_only_iseq);
+ }
if (body->call_data) {
for (unsigned int i=0; i<body->ci_size; i++) {
struct rb_call_data *cds = body->call_data;
@@ -279,17 +336,8 @@ rb_iseq_update_references(rb_iseq_t *iseq)
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) {
- size_t n = 0;
- const unsigned int size = body->iseq_size;
- while (n < size) {
- n += iseq_extract_values(original_iseq, n, update_each_insn_value, NULL, rb_vm_insn_null_translator);
- }
- }
- }
+ VALUE *original_iseq = ISEQ_ORIGINAL_ISEQ(iseq);
+ rb_iseq_each_value(iseq, update_each_insn_value, (void *)original_iseq);
if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
int i, j;
@@ -298,7 +346,7 @@ rb_iseq_update_references(rb_iseq_t *iseq)
for (j = 0; i < body->param.keyword->num; i++, j++) {
VALUE obj = body->param.keyword->default_values[j];
- if (obj != Qundef) {
+ if (!UNDEF_P(obj)) {
body->param.keyword->default_values[j] = rb_gc_location(obj);
}
}
@@ -318,6 +366,9 @@ rb_iseq_update_references(rb_iseq_t *iseq)
#if USE_MJIT
mjit_update_references(iseq);
#endif
+#if USE_YJIT
+ rb_yjit_iseq_update_references(body->yjit_payload);
+#endif
}
}
@@ -335,18 +386,18 @@ rb_iseq_mark(const rb_iseq_t *iseq)
RUBY_MARK_UNLESS_NULL(iseq->wrapper);
- if (iseq->body) {
- const struct rb_iseq_constant_body *const body = iseq->body;
+ if (ISEQ_BODY(iseq)) {
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
- if (FL_TEST((VALUE)iseq, ISEQ_MARKABLE_ISEQ)) {
- rb_iseq_each_value(iseq, each_insn_value, NULL);
- }
+ rb_iseq_each_value(iseq, each_insn_value, NULL);
rb_gc_mark_movable(body->variable.coverage);
rb_gc_mark_movable(body->variable.pc2branchindex);
+ rb_gc_mark_movable(body->variable.script_lines);
rb_gc_mark_movable(body->location.label);
rb_gc_mark_movable(body->location.base_label);
rb_gc_mark_movable(body->location.pathobj);
+ RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)body->mandatory_only_iseq);
RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)body->parent_iseq);
if (body->call_data) {
@@ -358,53 +409,61 @@ rb_iseq_mark(const rb_iseq_t *iseq)
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 (cc) {
+ VM_ASSERT((cc->flags & VM_CALLCACHE_ON_STACK) == 0);
+
+ if (vm_cc_markable(cc)) {
+ if (!vm_cc_invalidated_p(cc)) {
+ rb_gc_mark_movable((VALUE)cc);
+ }
+ else {
+ cds[i].cc = rb_vm_empty_cc();
+ }
}
}
}
}
- if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
- const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
- int i, j;
+ if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
+ const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
+ int i, j;
- i = keyword->required_num;
+ i = keyword->required_num;
- for (j = 0; i < keyword->num; i++, j++) {
- VALUE obj = keyword->default_values[j];
- if (!SPECIAL_CONST_P(obj)) {
+ for (j = 0; i < keyword->num; i++, j++) {
+ VALUE obj = keyword->default_values[j];
+ if (!SPECIAL_CONST_P(obj)) {
rb_gc_mark_movable(obj);
- }
- }
- }
-
- if (body->catch_table) {
- const struct iseq_catch_table *table = body->catch_table;
- unsigned int i;
- for (i = 0; i < table->size; i++) {
- const struct iseq_catch_table_entry *entry;
- entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
- if (entry->iseq) {
+ }
+ }
+ }
+
+ if (body->catch_table) {
+ const struct iseq_catch_table *table = body->catch_table;
+ unsigned int i;
+ for (i = 0; i < table->size; i++) {
+ const struct iseq_catch_table_entry *entry;
+ entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
+ if (entry->iseq) {
rb_gc_mark_movable((VALUE)entry->iseq);
- }
- }
- }
+ }
+ }
+ }
#if USE_MJIT
mjit_mark_cc_entries(body);
#endif
+#if USE_YJIT
+ rb_yjit_iseq_mark(body->yjit_payload);
+#endif
}
if (FL_TEST_RAW((VALUE)iseq, ISEQ_NOT_LOADED_YET)) {
- rb_gc_mark(iseq->aux.loader.obj);
+ rb_gc_mark(iseq->aux.loader.obj);
}
else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) {
- const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
+ const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
rb_iseq_mark_insn_storage(compile_data->insn.storage_head);
@@ -442,7 +501,7 @@ size_t
rb_iseq_memsize(const rb_iseq_t *iseq)
{
size_t size = 0; /* struct already counted as RVALUE size */
- const struct rb_iseq_constant_body *body = iseq->body;
+ const struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
const struct iseq_compile_data *compile_data;
/* TODO: should we count original_iseq? */
@@ -452,6 +511,7 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
size += body->iseq_size * sizeof(VALUE);
size += body->insns_info.size * (sizeof(struct iseq_insn_info_entry) + sizeof(unsigned int));
size += body->local_table_size * sizeof(ID);
+ size += ISEQ_MBITS_BUFLEN(body->iseq_size) * ISEQ_MBITS_SIZE;
if (body->catch_table) {
size += iseq_catch_table_bytes(body->catch_table->size);
}
@@ -459,7 +519,20 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
size += param_keyword_size(body->param.keyword);
/* body->is_entries */
- size += body->is_size * sizeof(union iseq_inline_storage_entry);
+ size += ISEQ_IS_SIZE(body) * sizeof(union iseq_inline_storage_entry);
+
+ if (ISEQ_BODY(iseq)->is_entries) {
+ /* IC entries constant segments */
+ for (unsigned int ic_idx = 0; ic_idx < body->ic_size; ic_idx++) {
+ IC ic = &ISEQ_IS_IC_ENTRY(body, ic_idx);
+ const ID *ids = ic->segments;
+ if (!ids) continue;
+ while (*ids++) {
+ size += sizeof(ID);
+ }
+ size += sizeof(ID); // null terminator
+ }
+ }
/* body->call_data */
size += body->ci_size * sizeof(struct rb_call_data);
@@ -468,15 +541,15 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
compile_data = ISEQ_COMPILE_DATA(iseq);
if (compile_data) {
- struct iseq_compile_data_storage *cur;
+ struct iseq_compile_data_storage *cur;
- size += sizeof(struct iseq_compile_data);
+ size += sizeof(struct iseq_compile_data);
- cur = compile_data->node.storage_head;
- while (cur) {
- size += cur->size + offsetof(struct iseq_compile_data_storage, buff);
- cur = cur->next;
- }
+ cur = compile_data->node.storage_head;
+ while (cur) {
+ size += cur->size + offsetof(struct iseq_compile_data_storage, buff);
+ cur = cur->next;
+ }
}
return size;
@@ -494,7 +567,7 @@ static rb_iseq_t *
iseq_alloc(void)
{
rb_iseq_t *iseq = iseq_imemo_alloc();
- iseq->body = rb_iseq_constant_body_alloc();
+ ISEQ_BODY(iseq) = rb_iseq_constant_body_alloc();
return iseq;
}
@@ -503,16 +576,16 @@ rb_iseq_pathobj_new(VALUE path, VALUE realpath)
{
VALUE pathobj;
VM_ASSERT(RB_TYPE_P(path, T_STRING));
- VM_ASSERT(realpath == Qnil || RB_TYPE_P(realpath, T_STRING));
+ VM_ASSERT(NIL_P(realpath) || RB_TYPE_P(realpath, T_STRING));
if (path == realpath ||
- (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) {
- pathobj = rb_fstring(path);
+ (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) {
+ pathobj = rb_fstring(path);
}
else {
- if (!NIL_P(realpath)) realpath = rb_fstring(realpath);
- pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath);
- rb_obj_freeze(pathobj);
+ if (!NIL_P(realpath)) realpath = rb_fstring(realpath);
+ pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath);
+ rb_obj_freeze(pathobj);
}
return pathobj;
}
@@ -520,14 +593,27 @@ rb_iseq_pathobj_new(VALUE path, VALUE realpath)
void
rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
{
- RB_OBJ_WRITE(iseq, &iseq->body->location.pathobj,
- rb_iseq_pathobj_new(path, realpath));
+ RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->location.pathobj,
+ rb_iseq_pathobj_new(path, realpath));
+}
+
+// Make a dummy iseq for a dummy frame that exposes a path for profilers to inspect
+rb_iseq_t *
+rb_iseq_alloc_with_dummy_path(VALUE fname)
+{
+ rb_iseq_t *dummy_iseq = iseq_alloc();
+
+ ISEQ_BODY(dummy_iseq)->type = ISEQ_TYPE_TOP;
+ RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.pathobj, fname);
+ RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.label, fname);
+
+ return dummy_iseq;
}
static rb_iseq_location_t *
-iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id)
+iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id)
{
- rb_iseq_location_t *loc = &iseq->body->location;
+ rb_iseq_location_t *loc = &ISEQ_BODY(iseq)->location;
rb_iseq_pathobj_set(iseq, path, realpath);
RB_OBJ_WRITE(iseq, &loc->label, name);
@@ -535,13 +621,13 @@ iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VAL
loc->first_lineno = first_lineno;
if (code_location) {
loc->node_id = node_id;
- loc->code_location = *code_location;
+ loc->code_location = *code_location;
}
else {
- loc->code_location.beg_pos.lineno = 0;
- loc->code_location.beg_pos.column = 0;
- loc->code_location.end_pos.lineno = -1;
- loc->code_location.end_pos.column = -1;
+ loc->code_location.beg_pos.lineno = 0;
+ loc->code_location.beg_pos.column = 0;
+ loc->code_location.end_pos.lineno = -1;
+ loc->code_location.end_pos.column = -1;
}
return loc;
@@ -550,26 +636,26 @@ iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VAL
static void
set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq)
{
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const VALUE type = body->type;
/* set class nest stack */
if (type == ISEQ_TYPE_TOP) {
- body->local_iseq = iseq;
+ body->local_iseq = iseq;
}
else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
- body->local_iseq = iseq;
+ body->local_iseq = iseq;
}
else if (piseq) {
- body->local_iseq = piseq->body->local_iseq;
+ body->local_iseq = ISEQ_BODY(piseq)->local_iseq;
}
if (piseq) {
- body->parent_iseq = piseq;
+ body->parent_iseq = piseq;
}
if (type == ISEQ_TYPE_MAIN) {
- body->local_iseq = iseq;
+ body->local_iseq = iseq;
}
}
@@ -590,15 +676,16 @@ 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, int isolated_depth, enum iseq_type type, const rb_compile_option_t *option)
+ VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id,
+ const rb_iseq_t *parent, int isolated_depth, enum rb_iseq_type type,
+ VALUE script_lines, const rb_compile_option_t *option)
{
VALUE coverage = Qfalse;
VALUE err_info = Qnil;
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
if (parent && (type == ISEQ_TYPE_MAIN || type == ISEQ_TYPE_TOP))
- err_info = Qfalse;
+ err_info = Qfalse;
body->type = type;
set_relation(iseq, parent);
@@ -606,12 +693,19 @@ prepare_iseq_build(rb_iseq_t *iseq,
name = rb_fstring(name);
iseq_location_setup(iseq, name, path, realpath, first_lineno, code_location, node_id);
if (iseq != body->local_iseq) {
- RB_OBJ_WRITE(iseq, &body->location.base_label, body->local_iseq->body->location.label);
+ RB_OBJ_WRITE(iseq, &body->location.base_label, ISEQ_BODY(body->local_iseq)->location.label);
}
ISEQ_COVERAGE_SET(iseq, Qnil);
ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
body->variable.flip_count = 0;
+ if (NIL_P(script_lines)) {
+ RB_OBJ_WRITE(iseq, &body->variable.script_lines, Qnil);
+ }
+ else {
+ RB_OBJ_WRITE(iseq, &body->variable.script_lines, rb_ractor_make_shareable(script_lines));
+ }
+
ISEQ_COMPILE_DATA_ALLOC(iseq);
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info);
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, Qnil);
@@ -623,17 +717,16 @@ prepare_iseq_build(rb_iseq_t *iseq,
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)) {
- coverage = rb_hash_lookup(coverages, rb_iseq_path(iseq));
- if (NIL_P(coverage)) coverage = Qfalse;
- }
+ VALUE coverages = rb_get_coverages();
+ if (RTEST(coverages)) {
+ coverage = rb_hash_lookup(coverages, rb_iseq_path(iseq));
+ if (NIL_P(coverage)) coverage = Qfalse;
+ }
}
ISEQ_COVERAGE_SET(iseq, coverage);
if (coverage && ISEQ_BRANCH_COVERAGE(iseq))
- ISEQ_PC2BRANCHINDEX_SET(iseq, rb_ary_tmp_new(0));
+ ISEQ_PC2BRANCHINDEX_SET(iseq, rb_ary_hidden_new(0));
return Qtrue;
}
@@ -647,7 +740,7 @@ 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;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
int size = body->insns_info.size;
int max_pos = body->iseq_size;
int *data = (int *)body->insns_info.positions;
@@ -684,7 +777,7 @@ static VALUE
finish_iseq_build(rb_iseq_t *iseq)
{
struct iseq_compile_data *data = ISEQ_COMPILE_DATA(iseq);
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE err = data->err_info;
ISEQ_COMPILE_DATA_CLEAR(iseq);
compile_data_free(data);
@@ -694,14 +787,14 @@ finish_iseq_build(rb_iseq_t *iseq)
#endif
if (RTEST(err)) {
- VALUE path = pathobj_path(body->location.pathobj);
- if (err == Qtrue) err = rb_exc_new_cstr(rb_eSyntaxError, "compile error");
- rb_funcallv(err, rb_intern("set_backtrace"), 1, &path);
- rb_exc_raise(err);
+ VALUE path = pathobj_path(body->location.pathobj);
+ if (err == Qtrue) err = rb_exc_new_cstr(rb_eSyntaxError, "compile error");
+ rb_funcallv(err, rb_intern("set_backtrace"), 1, &path);
+ rb_exc_raise(err);
}
RB_DEBUG_COUNTER_INC(iseq_num);
- RB_DEBUG_COUNTER_ADD(iseq_cd_num, iseq->body->ci_size);
+ RB_DEBUG_COUNTER_ADD(iseq_cd_num, ISEQ_BODY(iseq)->ci_size);
rb_iseq_init_trace(iseq);
return Qtrue;
@@ -759,23 +852,23 @@ rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt)
static void
make_compile_option(rb_compile_option_t *option, VALUE opt)
{
- if (opt == Qnil) {
- *option = COMPILE_OPTION_DEFAULT;
+ if (NIL_P(opt)) {
+ *option = COMPILE_OPTION_DEFAULT;
}
else if (opt == Qfalse) {
- *option = COMPILE_OPTION_FALSE;
+ *option = COMPILE_OPTION_FALSE;
}
else if (opt == Qtrue) {
- int i;
- for (i = 0; i < (int)(sizeof(rb_compile_option_t) / sizeof(int)); ++i)
- ((int *)option)[i] = 1;
+ int i;
+ for (i = 0; i < (int)(sizeof(rb_compile_option_t) / sizeof(int)); ++i)
+ ((int *)option)[i] = 1;
}
else if (RB_TYPE_P(opt, T_HASH)) {
- *option = COMPILE_OPTION_DEFAULT;
- set_compile_option_from_hash(option, opt);
+ *option = COMPILE_OPTION_DEFAULT;
+ set_compile_option_from_hash(option, opt);
}
else {
- rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
+ rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
}
}
@@ -784,21 +877,21 @@ make_compile_option_value(rb_compile_option_t *option)
{
VALUE opt = rb_hash_new_with_size(11);
#define SET_COMPILE_OPTION(o, h, mem) \
- rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
+ rb_hash_aset((h), ID2SYM(rb_intern(#mem)), RBOOL((o)->mem))
#define SET_COMPILE_OPTION_NUM(o, h, mem) \
rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
{
- SET_COMPILE_OPTION(option, opt, inline_const_cache);
- SET_COMPILE_OPTION(option, opt, peephole_optimization);
- SET_COMPILE_OPTION(option, opt, tailcall_optimization);
- SET_COMPILE_OPTION(option, opt, specialized_instruction);
- SET_COMPILE_OPTION(option, opt, operands_unification);
- SET_COMPILE_OPTION(option, opt, instructions_unification);
- SET_COMPILE_OPTION(option, opt, stack_caching);
- SET_COMPILE_OPTION(option, opt, frozen_string_literal);
- SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
- SET_COMPILE_OPTION(option, opt, coverage_enabled);
- SET_COMPILE_OPTION_NUM(option, opt, debug_level);
+ SET_COMPILE_OPTION(option, opt, inline_const_cache);
+ SET_COMPILE_OPTION(option, opt, peephole_optimization);
+ SET_COMPILE_OPTION(option, opt, tailcall_optimization);
+ SET_COMPILE_OPTION(option, opt, specialized_instruction);
+ SET_COMPILE_OPTION(option, opt, operands_unification);
+ SET_COMPILE_OPTION(option, opt, instructions_unification);
+ SET_COMPILE_OPTION(option, opt, stack_caching);
+ SET_COMPILE_OPTION(option, opt, frozen_string_literal);
+ SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
+ SET_COMPILE_OPTION(option, opt, coverage_enabled);
+ SET_COMPILE_OPTION_NUM(option, opt, debug_level);
}
#undef SET_COMPILE_OPTION
#undef SET_COMPILE_OPTION_NUM
@@ -807,9 +900,9 @@ make_compile_option_value(rb_compile_option_t *option)
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)
+ const rb_iseq_t *parent, enum rb_iseq_type type)
{
- return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent,
+ return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent,
0, type, &COMPILE_OPTION_DEFAULT);
}
@@ -826,34 +919,62 @@ ast_line_count(const rb_ast_body_t *ast)
return FIX2INT(ast->script_lines);
}
-rb_iseq_t *
-rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+static VALUE
+iseq_setup_coverage(VALUE coverages, VALUE path, const rb_ast_body_t *ast, int line_offset)
+{
+ int line_count = line_offset + ast_line_count(ast);
+
+ if (line_count >= 0) {
+ int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : line_count;
+
+ VALUE coverage = rb_default_coverage(len);
+ rb_hash_aset(coverages, path, coverage);
+
+ return coverage;
+ }
+
+ return Qnil;
+}
+
+static inline void
+iseq_new_setup_coverage(VALUE path, const rb_ast_body_t *ast, int line_offset)
{
VALUE coverages = rb_get_coverages();
+
if (RTEST(coverages)) {
- int line_count = ast_line_count(ast);
- if (line_count >= 0) {
- int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : line_count;
- VALUE coverage = rb_default_coverage(len);
- rb_hash_aset(coverages, path, coverage);
- }
+ iseq_setup_coverage(coverages, path, ast, 0);
}
+}
- return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, 0,
+rb_iseq_t *
+rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+{
+ iseq_new_setup_coverage(path, ast, 0);
+
+ return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent, 0,
ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
}
rb_iseq_t *
-rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
{
+ iseq_new_setup_coverage(path, ast, 0);
+
return rb_iseq_new_with_opt(ast, rb_fstring_lit("<main>"),
- path, realpath, INT2FIX(0),
- parent, 0, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
+ path, realpath, 0,
+ parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE);
}
rb_iseq_t *
-rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth)
+rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
{
+ if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) {
+ VALUE coverages = rb_get_coverages();
+ if (RTEST(coverages) && RTEST(path) && !RTEST(rb_hash_has_key(coverages, path))) {
+ iseq_setup_coverage(coverages, path, ast, first_lineno - 1);
+ }
+ }
+
return rb_iseq_new_with_opt(ast, name, path, realpath, first_lineno,
parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT);
}
@@ -862,11 +983,11 @@ static inline rb_iseq_t *
iseq_translate(rb_iseq_t *iseq)
{
if (rb_respond_to(rb_cISeq, rb_intern("translate"))) {
- VALUE v1 = iseqw_new(iseq);
- VALUE v2 = rb_funcall(rb_cISeq, rb_intern("translate"), 1, v1);
- if (v1 != v2 && CLASS_OF(v2) == rb_cISeq) {
- iseq = (rb_iseq_t *)iseqw_check(v2);
- }
+ VALUE v1 = iseqw_new(iseq);
+ VALUE v2 = rb_funcall(rb_cISeq, rb_intern("translate"), 1, v1);
+ if (v1 != v2 && CLASS_OF(v2) == rb_cISeq) {
+ iseq = (rb_iseq_t *)iseqw_check(v2);
+ }
}
return iseq;
@@ -874,8 +995,8 @@ 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, int isolated_depth,
- enum iseq_type type, const rb_compile_option_t *option)
+ int first_lineno, const rb_iseq_t *parent, int isolated_depth,
+ enum rb_iseq_type type, const rb_compile_option_t *option)
{
const NODE *node = ast ? ast->root : 0;
/* TODO: argument check */
@@ -890,7 +1011,17 @@ rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE rea
}
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, isolated_depth, type, &new_opt);
+ VALUE script_lines = Qnil;
+
+ if (ast && !FIXNUM_P(ast->script_lines) && ast->script_lines) {
+ script_lines = ast->script_lines;
+ }
+ else if (parent) {
+ script_lines = ISEQ_BODY(parent)->variable.script_lines;
+ }
+
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1,
+ parent, isolated_depth, type, script_lines, &new_opt);
rb_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
@@ -902,14 +1033,14 @@ rb_iseq_t *
rb_iseq_new_with_callback(
const struct rb_iseq_new_with_callback_callback_func * ifunc,
VALUE name, VALUE path, VALUE realpath,
- VALUE first_lineno, const rb_iseq_t *parent,
- enum iseq_type type, const rb_compile_option_t *option)
+ int first_lineno, const rb_iseq_t *parent,
+ enum rb_iseq_type type, const rb_compile_option_t *option)
{
/* TODO: argument check */
rb_iseq_t *iseq = iseq_alloc();
if (!option) option = &COMPILE_OPTION_DEFAULT;
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, option);
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, Qnil, option);
rb_iseq_compile_callback(iseq, ifunc);
finish_iseq_build(iseq);
@@ -923,7 +1054,7 @@ rb_iseq_load_iseq(VALUE fname)
VALUE iseqv = rb_check_funcall(rb_cISeq, rb_intern("load_iseq"), 1, &fname);
if (!SPECIAL_CONST_P(iseqv) && RBASIC_CLASS(iseqv) == rb_cISeq) {
- return iseqw_check(iseqv);
+ return iseqw_check(iseqv);
}
return NULL;
@@ -935,7 +1066,7 @@ rb_iseq_load_iseq(VALUE fname)
#define CHECK_SYMBOL(v) rb_to_symbol_type(v)
static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
-static enum iseq_type
+static enum rb_iseq_type
iseq_type_from_sym(VALUE type)
{
const ID id_top = rb_intern("top");
@@ -959,7 +1090,7 @@ iseq_type_from_sym(VALUE type)
if (typeid == id_eval) return ISEQ_TYPE_EVAL;
if (typeid == id_main) return ISEQ_TYPE_MAIN;
if (typeid == id_plain) return ISEQ_TYPE_PLAIN;
- return (enum iseq_type)-1;
+ return (enum rb_iseq_type)-1;
}
static VALUE
@@ -968,7 +1099,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
rb_iseq_t *iseq = iseq_alloc();
VALUE magic, version1, version2, format_type, misc;
- VALUE name, path, realpath, first_lineno, code_location, node_id;
+ VALUE name, path, realpath, code_location, node_id;
VALUE type, body, locals, params, exception;
st_data_t iseq_type;
@@ -994,7 +1125,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
path = CHECK_STRING(rb_ary_entry(data, i++));
realpath = rb_ary_entry(data, i++);
realpath = NIL_P(realpath) ? Qnil : CHECK_STRING(realpath);
- first_lineno = CHECK_INTEGER(rb_ary_entry(data, i++));
+ int first_lineno = RB_NUM2INT(rb_ary_entry(data, i++));
type = CHECK_SYMBOL(rb_ary_entry(data, i++));
locals = CHECK_ARRAY(rb_ary_entry(data, i++));
@@ -1002,27 +1133,27 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
exception = CHECK_ARRAY(rb_ary_entry(data, i++));
body = CHECK_ARRAY(rb_ary_entry(data, i++));
- iseq->body->local_iseq = iseq;
+ ISEQ_BODY(iseq)->local_iseq = iseq;
iseq_type = iseq_type_from_sym(type);
- if (iseq_type == (enum iseq_type)-1) {
- rb_raise(rb_eTypeError, "unsupported type: :%"PRIsVALUE, rb_sym2str(type));
+ if (iseq_type == (enum rb_iseq_type)-1) {
+ rb_raise(rb_eTypeError, "unsupported type: :%"PRIsVALUE, rb_sym2str(type));
}
node_id = rb_hash_aref(misc, ID2SYM(rb_intern("node_id")));
code_location = rb_hash_aref(misc, ID2SYM(rb_intern("code_location")));
if (RB_TYPE_P(code_location, T_ARRAY) && RARRAY_LEN(code_location) == 4) {
- tmp_loc.beg_pos.lineno = NUM2INT(rb_ary_entry(code_location, 0));
- tmp_loc.beg_pos.column = NUM2INT(rb_ary_entry(code_location, 1));
- tmp_loc.end_pos.lineno = NUM2INT(rb_ary_entry(code_location, 2));
- tmp_loc.end_pos.column = NUM2INT(rb_ary_entry(code_location, 3));
+ tmp_loc.beg_pos.lineno = NUM2INT(rb_ary_entry(code_location, 0));
+ tmp_loc.beg_pos.column = NUM2INT(rb_ary_entry(code_location, 1));
+ tmp_loc.end_pos.lineno = NUM2INT(rb_ary_entry(code_location, 2));
+ tmp_loc.end_pos.column = NUM2INT(rb_ary_entry(code_location, 3));
}
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, 0, (enum iseq_type)iseq_type, &option);
+ parent, 0, (enum rb_iseq_type)iseq_type, Qnil, &option);
rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
@@ -1061,37 +1192,36 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
rb_ast_t *(*parse)(VALUE vparser, VALUE fname, VALUE file, int start);
int ln;
rb_ast_t *INITIALIZED ast;
+ VALUE name = rb_fstring_lit("<compiled>");
/* safe results first */
make_compile_option(&option, opt);
ln = NUM2INT(line);
StringValueCStr(file);
if (RB_TYPE_P(src, T_FILE)) {
- parse = rb_parser_compile_file_path;
+ parse = rb_parser_compile_file_path;
}
else {
- parse = rb_parser_compile_string_path;
- StringValue(src);
+ parse = rb_parser_compile_string_path;
+ StringValue(src);
}
{
- const VALUE parser = rb_parser_new();
- VALUE name = rb_fstring_lit("<compiled>");
+ const VALUE parser = rb_parser_new();
const rb_iseq_t *outer_scope = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP);
VALUE outer_scope_v = (VALUE)outer_scope;
rb_parser_set_context(parser, outer_scope, FALSE);
RB_GC_GUARD(outer_scope_v);
- ast = (*parse)(parser, file, src, ln);
+ ast = (*parse)(parser, file, src, ln);
}
if (!ast->body.root) {
- rb_ast_dispose(ast);
- rb_exc_raise(GET_EC()->errinfo);
+ rb_ast_dispose(ast);
+ rb_exc_raise(GET_EC()->errinfo);
}
else {
- INITIALIZED VALUE label = rb_fstring_lit("<compiled>");
- iseq = rb_iseq_new_with_opt(&ast->body, label, file, realpath, line,
- NULL, 0, ISEQ_TYPE_TOP, &option);
- rb_ast_dispose(ast);
+ iseq = rb_iseq_new_with_opt(&ast->body, name, file, realpath, ln,
+ NULL, 0, ISEQ_TYPE_TOP, &option);
+ rb_ast_dispose(ast);
}
return iseq;
@@ -1100,13 +1230,13 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
VALUE
rb_iseq_path(const rb_iseq_t *iseq)
{
- return pathobj_path(iseq->body->location.pathobj);
+ return pathobj_path(ISEQ_BODY(iseq)->location.pathobj);
}
VALUE
rb_iseq_realpath(const rb_iseq_t *iseq)
{
- return pathobj_realpath(iseq->body->location.pathobj);
+ return pathobj_realpath(ISEQ_BODY(iseq)->location.pathobj);
}
VALUE
@@ -1124,44 +1254,52 @@ rb_iseq_from_eval_p(const rb_iseq_t *iseq)
VALUE
rb_iseq_label(const rb_iseq_t *iseq)
{
- return iseq->body->location.label;
+ return ISEQ_BODY(iseq)->location.label;
}
VALUE
rb_iseq_base_label(const rb_iseq_t *iseq)
{
- return iseq->body->location.base_label;
+ return ISEQ_BODY(iseq)->location.base_label;
}
VALUE
rb_iseq_first_lineno(const rb_iseq_t *iseq)
{
- return iseq->body->location.first_lineno;
+ return RB_INT2NUM(ISEQ_BODY(iseq)->location.first_lineno);
}
VALUE
rb_iseq_method_name(const rb_iseq_t *iseq)
{
- struct rb_iseq_constant_body *const body = iseq->body->local_iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq);
if (body->type == ISEQ_TYPE_METHOD) {
- return body->location.base_label;
+ return body->location.base_label;
}
else {
- return Qnil;
+ return Qnil;
}
}
void
rb_iseq_code_location(const rb_iseq_t *iseq, int *beg_pos_lineno, int *beg_pos_column, int *end_pos_lineno, int *end_pos_column)
{
- const rb_code_location_t *loc = &iseq->body->location.code_location;
+ const rb_code_location_t *loc = &ISEQ_BODY(iseq)->location.code_location;
if (beg_pos_lineno) *beg_pos_lineno = loc->beg_pos.lineno;
if (beg_pos_column) *beg_pos_column = loc->beg_pos.column;
if (end_pos_lineno) *end_pos_lineno = loc->end_pos.lineno;
if (end_pos_column) *end_pos_column = loc->end_pos.column;
}
+static ID iseq_type_id(enum rb_iseq_type type);
+
+VALUE
+rb_iseq_type(const rb_iseq_t *iseq)
+{
+ return ID2SYM(iseq_type_id(ISEQ_BODY(iseq)->type));
+}
+
VALUE
rb_iseq_coverage(const rb_iseq_t *iseq)
{
@@ -1176,10 +1314,10 @@ remove_coverage_i(void *vstart, void *vend, size_t stride, void *data)
void *ptr = asan_poisoned_object_p(v);
asan_unpoison_object(v, false);
- if (rb_obj_is_iseq(v)) {
+ if (rb_obj_is_iseq(v)) {
rb_iseq_t *iseq = (rb_iseq_t *)v;
ISEQ_COVERAGE_SET(iseq, Qnil);
- }
+ }
asan_poison_object_if(ptr, v);
}
@@ -1320,7 +1458,7 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
static VALUE
iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
{
- VALUE file, line = INT2FIX(1), opt = Qnil;
+ VALUE file, opt = Qnil;
VALUE parser, f, exc = Qnil, ret;
rb_ast_t *ast;
rb_compile_option_t option;
@@ -1336,6 +1474,9 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
f = rb_file_open_str(file, "r");
+ rb_execution_context_t *ec = GET_EC();
+ VALUE v = rb_vm_push_frame_fname(ec, file);
+
parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
ast = (rb_ast_t *)rb_parser_load_file(parser, file);
@@ -1343,17 +1484,20 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
rb_io_close(f);
if (!ast->body.root) {
- rb_ast_dispose(ast);
- rb_exc_raise(exc);
+ rb_ast_dispose(ast);
+ rb_exc_raise(exc);
}
make_compile_option(&option, opt);
ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("<main>"),
- file,
- rb_realpath_internal(Qnil, file, 1),
- line, NULL, 0, ISEQ_TYPE_TOP, &option));
+ file,
+ rb_realpath_internal(Qnil, file, 1),
+ 1, NULL, 0, ISEQ_TYPE_TOP, &option));
rb_ast_dispose(ast);
+
+ rb_vm_pop_frame(ec);
+ RB_GC_GUARD(v);
return ret;
}
@@ -1416,12 +1560,12 @@ iseqw_check(VALUE iseqw)
{
rb_iseq_t *iseq = DATA_PTR(iseqw);
- if (!iseq->body) {
- rb_ibf_load_iseq_complete(iseq);
+ if (!ISEQ_BODY(iseq)) {
+ rb_ibf_load_iseq_complete(iseq);
}
- if (!iseq->body->location.label) {
- rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
+ if (!ISEQ_BODY(iseq)->location.label) {
+ rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
}
return iseq;
}
@@ -1443,7 +1587,11 @@ rb_iseqw_to_iseq(VALUE iseqw)
static VALUE
iseqw_eval(VALUE self)
{
- return rb_iseq_eval(iseqw_check(self));
+ const rb_iseq_t *iseq = iseqw_check(self);
+ if (0 == ISEQ_BODY(iseq)->iseq_size) {
+ rb_raise(rb_eTypeError, "attempt to evaluate dummy InstructionSequence");
+ }
+ return rb_iseq_eval(iseq);
}
/*
@@ -1454,17 +1602,17 @@ static VALUE
iseqw_inspect(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE klass = rb_class_name(rb_obj_class(self));
if (!body->location.label) {
- return rb_sprintf("#<%"PRIsVALUE": uninitialized>", klass);
+ return rb_sprintf("#<%"PRIsVALUE": uninitialized>", klass);
}
else {
- return rb_sprintf("<%"PRIsVALUE":%"PRIsVALUE"@%"PRIsVALUE":%d>",
- klass,
- body->location.label, rb_iseq_path(iseq),
- FIX2INT(rb_iseq_first_lineno(iseq)));
+ return rb_sprintf("<%"PRIsVALUE":%"PRIsVALUE"@%"PRIsVALUE":%d>",
+ klass,
+ body->location.label, rb_iseq_path(iseq),
+ FIX2INT(rb_iseq_first_lineno(iseq)));
}
}
@@ -1684,45 +1832,45 @@ iseqw_to_a(VALUE self)
static const struct iseq_insn_info_entry *
get_insn_info_binary_search(const rb_iseq_t *iseq, size_t pos)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t size = body->insns_info.size;
const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
const unsigned int *positions = body->insns_info.positions;
const int debug = 0;
if (debug) {
- printf("size: %"PRIuSIZE"\n", size);
- printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
- (size_t)0, positions[0], insns_info[0].line_no, pos);
+ printf("size: %"PRIuSIZE"\n", size);
+ printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
+ (size_t)0, positions[0], insns_info[0].line_no, pos);
}
if (size == 0) {
- return NULL;
+ return NULL;
}
else if (size == 1) {
- return &insns_info[0];
+ return &insns_info[0];
}
else {
- size_t l = 1, r = size - 1;
- while (l <= r) {
- size_t m = l + (r - l) / 2;
- if (positions[m] == pos) {
- return &insns_info[m];
- }
- if (positions[m] < pos) {
- l = m + 1;
- }
- else {
- r = m - 1;
- }
- }
- if (l >= size) {
- return &insns_info[size-1];
- }
- if (positions[l] > pos) {
- return &insns_info[l-1];
- }
- return &insns_info[l];
+ size_t l = 1, r = size - 1;
+ while (l <= r) {
+ size_t m = l + (r - l) / 2;
+ if (positions[m] == pos) {
+ return &insns_info[m];
+ }
+ if (positions[m] < pos) {
+ l = m + 1;
+ }
+ else {
+ r = m - 1;
+ }
+ }
+ if (l >= size) {
+ return &insns_info[size-1];
+ }
+ if (positions[l] > pos) {
+ return &insns_info[l-1];
+ }
+ return &insns_info[l];
}
}
@@ -1737,7 +1885,7 @@ get_insn_info(const rb_iseq_t *iseq, size_t pos)
static const struct iseq_insn_info_entry *
get_insn_info_succinct_bitvector(const rb_iseq_t *iseq, size_t pos)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t size = body->insns_info.size;
const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
const int debug = 0;
@@ -1756,16 +1904,16 @@ get_insn_info_succinct_bitvector(const rb_iseq_t *iseq, size_t pos)
}
if (size == 0) {
- return NULL;
+ return NULL;
}
else if (size == 1) {
- return &insns_info[0];
+ return &insns_info[0];
}
else {
- int index;
- VM_ASSERT(body->insns_info.succ_index_table != NULL);
- index = succ_index_lookup(body->insns_info.succ_index_table, (int)pos);
- return &insns_info[index-1];
+ int index;
+ VM_ASSERT(body->insns_info.succ_index_table != NULL);
+ index = succ_index_lookup(body->insns_info.succ_index_table, (int)pos);
+ return &insns_info[index-1];
}
}
@@ -1780,36 +1928,36 @@ get_insn_info(const rb_iseq_t *iseq, size_t pos)
static const struct iseq_insn_info_entry *
get_insn_info_linear_search(const rb_iseq_t *iseq, size_t pos)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t i = 0, size = body->insns_info.size;
const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
const unsigned int *positions = body->insns_info.positions;
const int debug = 0;
if (debug) {
- printf("size: %"PRIuSIZE"\n", size);
- printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
- i, positions[i], insns_info[i].line_no, pos);
+ printf("size: %"PRIuSIZE"\n", size);
+ printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
+ i, positions[i], insns_info[i].line_no, pos);
}
if (size == 0) {
- return NULL;
+ return NULL;
}
else if (size == 1) {
- return &insns_info[0];
+ return &insns_info[0];
}
else {
- for (i=1; i<size; i++) {
- if (debug) printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
- i, positions[i], insns_info[i].line_no, pos);
-
- if (positions[i] == pos) {
- return &insns_info[i];
- }
- if (positions[i] > pos) {
- return &insns_info[i-1];
- }
- }
+ for (i=1; i<size; i++) {
+ if (debug) printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
+ i, positions[i], insns_info[i].line_no, pos);
+
+ if (positions[i] == pos) {
+ return &insns_info[i];
+ }
+ if (positions[i] > pos) {
+ return &insns_info[i-1];
+ }
+ }
}
return &insns_info[i-1];
}
@@ -1827,12 +1975,12 @@ get_insn_info(const rb_iseq_t *iseq, size_t pos)
static void
validate_get_insn_info(const rb_iseq_t *iseq)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
size_t i;
for (i = 0; i < body->iseq_size; i++) {
- if (get_insn_info_linear_search(iseq, i) != get_insn_info(iseq, i)) {
- rb_bug("validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info(iseq, %"PRIuSIZE")", i, i);
- }
+ if (get_insn_info_linear_search(iseq, i) != get_insn_info(iseq, i)) {
+ rb_bug("validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info(iseq, %"PRIuSIZE")", i, i);
+ }
}
}
#endif
@@ -1843,10 +1991,10 @@ rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
if (entry) {
- return entry->line_no;
+ return entry->line_no;
}
else {
- return 0;
+ return 0;
}
}
@@ -1857,10 +2005,10 @@ rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos)
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
if (entry) {
- return entry->node_id;
+ return entry->node_id;
}
else {
- return 0;
+ return 0;
}
}
#endif
@@ -1870,10 +2018,10 @@ rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
{
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
if (entry) {
- return entry->events;
+ return entry->events;
}
else {
- return 0;
+ return 0;
}
}
@@ -1899,19 +2047,19 @@ local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op)
int idx;
for (i = 0; i < level; i++) {
- diseq = diseq->body->parent_iseq;
+ diseq = ISEQ_BODY(diseq)->parent_iseq;
}
- idx = diseq->body->local_table_size - (int)op - 1;
- lid = diseq->body->local_table[idx];
+ idx = ISEQ_BODY(diseq)->local_table_size - (int)op - 1;
+ lid = ISEQ_BODY(diseq)->local_table[idx];
name = rb_id2str(lid);
if (!name) {
- name = rb_str_new_cstr("?");
+ name = rb_str_new_cstr("?");
}
else if (!rb_str_symname_p(name)) {
- name = rb_str_inspect(name);
+ name = rb_str_inspect(name);
}
else {
- name = rb_str_dup(name);
+ name = rb_str_dup(name);
}
rb_str_catf(name, "@%d", idx);
return name;
@@ -1922,8 +2070,8 @@ VALUE rb_dump_literal(VALUE lit);
VALUE
rb_insn_operand_intern(const rb_iseq_t *iseq,
- VALUE insn, int op_no, VALUE op,
- int len, size_t pos, const VALUE *pnop, VALUE child)
+ VALUE insn, int op_no, VALUE op,
+ int len, size_t pos, const VALUE *pnop, VALUE child)
{
const char *types = insn_op_types(insn);
char type = types[op_no];
@@ -1931,156 +2079,167 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
switch (type) {
case TS_OFFSET: /* LONG */
- ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
- break;
+ ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
+ break;
case TS_NUM: /* ULONG */
- if (insn == BIN(defined) && op_no == 0) {
- enum defined_type deftype = (enum defined_type)op;
- switch (deftype) {
- case DEFINED_FUNC:
- ret = rb_fstring_lit("func");
- break;
- case DEFINED_REF:
- ret = rb_fstring_lit("ref");
- break;
- case DEFINED_CONST_FROM:
- ret = rb_fstring_lit("constant-from");
- break;
- default:
- ret = rb_iseq_defined_string(deftype);
- break;
- }
- if (ret) break;
- }
- else if (insn == BIN(checktype) && op_no == 0) {
- const char *type_str = rb_type_str((enum ruby_value_type)op);
- if (type_str) {
- ret = rb_str_new_cstr(type_str); break;
- }
- }
- ret = rb_sprintf("%"PRIuVALUE, op);
- break;
+ if (insn == BIN(defined) && op_no == 0) {
+ enum defined_type deftype = (enum defined_type)op;
+ switch (deftype) {
+ case DEFINED_FUNC:
+ ret = rb_fstring_lit("func");
+ break;
+ case DEFINED_REF:
+ ret = rb_fstring_lit("ref");
+ break;
+ case DEFINED_CONST_FROM:
+ ret = rb_fstring_lit("constant-from");
+ break;
+ default:
+ ret = rb_iseq_defined_string(deftype);
+ break;
+ }
+ if (ret) break;
+ }
+ else if (insn == BIN(checktype) && op_no == 0) {
+ const char *type_str = rb_type_str((enum ruby_value_type)op);
+ if (type_str) {
+ ret = rb_str_new_cstr(type_str); break;
+ }
+ }
+ ret = rb_sprintf("%"PRIuVALUE, op);
+ break;
case TS_LINDEX:{
- int level;
- if (types[op_no+1] == TS_NUM && pnop) {
- ret = local_var_name(iseq, *pnop, op - VM_ENV_DATA_SIZE);
- }
- else if ((level = rb_insn_unified_local_var_level(insn)) >= 0) {
- ret = local_var_name(iseq, (VALUE)level, op - VM_ENV_DATA_SIZE);
- }
- else {
- ret = rb_inspect(INT2FIX(op));
- }
- break;
+ int level;
+ if (types[op_no+1] == TS_NUM && pnop) {
+ ret = local_var_name(iseq, *pnop, op - VM_ENV_DATA_SIZE);
+ }
+ else if ((level = rb_insn_unified_local_var_level(insn)) >= 0) {
+ ret = local_var_name(iseq, (VALUE)level, op - VM_ENV_DATA_SIZE);
+ }
+ else {
+ ret = rb_inspect(INT2FIX(op));
+ }
+ break;
}
case TS_ID: /* ID (symbol) */
- ret = rb_inspect(ID2SYM(op));
- break;
+ ret = rb_inspect(ID2SYM(op));
+ break;
case TS_VALUE: /* VALUE */
- op = obj_resurrect(op);
- if (insn == BIN(defined) && op_no == 1 && FIXNUM_P(op)) {
- /* should be DEFINED_REF */
- int type = NUM2INT(op);
- if (type) {
- if (type & 1) {
- ret = rb_sprintf(":$%c", (type >> 1));
- }
- else {
- ret = rb_sprintf(":$%d", (type >> 1));
- }
- break;
- }
- }
- ret = rb_dump_literal(op);
- if (CLASS_OF(op) == rb_cISeq) {
- if (child) {
- rb_ary_push(child, op);
- }
- }
- break;
+ op = obj_resurrect(op);
+ if (insn == BIN(defined) && op_no == 1 && FIXNUM_P(op)) {
+ /* should be DEFINED_REF */
+ int type = NUM2INT(op);
+ if (type) {
+ if (type & 1) {
+ ret = rb_sprintf(":$%c", (type >> 1));
+ }
+ else {
+ ret = rb_sprintf(":$%d", (type >> 1));
+ }
+ break;
+ }
+ }
+ ret = rb_dump_literal(op);
+ if (CLASS_OF(op) == rb_cISeq) {
+ if (child) {
+ rb_ary_push(child, op);
+ }
+ }
+ break;
case TS_ISEQ: /* iseq */
- {
- if (op) {
- const rb_iseq_t *iseq = rb_iseq_check((rb_iseq_t *)op);
- ret = iseq->body->location.label;
- if (child) {
- rb_ary_push(child, (VALUE)iseq);
- }
- }
- else {
- ret = rb_str_new2("nil");
- }
- break;
- }
+ {
+ if (op) {
+ const rb_iseq_t *iseq = rb_iseq_check((rb_iseq_t *)op);
+ ret = ISEQ_BODY(iseq)->location.label;
+ if (child) {
+ rb_ary_push(child, (VALUE)iseq);
+ }
+ }
+ else {
+ ret = rb_str_new2("nil");
+ }
+ break;
+ }
case TS_IC:
+ {
+ ret = rb_sprintf("<ic:%"PRIdPTRDIFF" ", (union iseq_inline_storage_entry *)op - ISEQ_BODY(iseq)->is_entries);
+ const ID *segments = ((IC)op)->segments;
+ rb_str_cat2(ret, rb_id2name(*segments++));
+ while (*segments) {
+ rb_str_catf(ret, "::%s", rb_id2name(*segments++));
+ }
+ rb_str_cat2(ret, ">");
+ }
+ break;
case TS_IVC:
+ case TS_ICVARC:
case TS_ISE:
- ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - iseq->body->is_entries);
- break;
+ ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - ISEQ_BODY(iseq)->is_entries);
+ break;
case TS_CALLDATA:
- {
+ {
struct rb_call_data *cd = (struct rb_call_data *)op;
const struct rb_callinfo *ci = cd->ci;
- VALUE ary = rb_ary_new();
+ VALUE ary = rb_ary_new();
ID mid = vm_ci_mid(ci);
if (mid) {
- rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(mid)));
- }
+ rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(mid)));
+ }
- rb_ary_push(ary, rb_sprintf("argc:%d", vm_ci_argc(ci)));
+ rb_ary_push(ary, rb_sprintf("argc:%d", vm_ci_argc(ci)));
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 (vm_ci_flag(ci)) {
- VALUE flags = rb_ary_new();
+ VALUE flags = rb_ary_new();
# 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);
- CALL_FLAG(VCALL);
- CALL_FLAG(ARGS_SIMPLE);
- CALL_FLAG(BLOCKISEQ);
- CALL_FLAG(TAILCALL);
- CALL_FLAG(SUPER);
- CALL_FLAG(ZSUPER);
- CALL_FLAG(KWARG);
- CALL_FLAG(KW_SPLAT);
+ CALL_FLAG(ARGS_SPLAT);
+ CALL_FLAG(ARGS_BLOCKARG);
+ CALL_FLAG(FCALL);
+ CALL_FLAG(VCALL);
+ CALL_FLAG(ARGS_SIMPLE);
+ CALL_FLAG(BLOCKISEQ);
+ CALL_FLAG(TAILCALL);
+ CALL_FLAG(SUPER);
+ 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("|")));
- }
+ CALL_FLAG(OPT_SEND); /* maybe not reachable */
+ rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
+ }
ret = rb_sprintf("<calldata!%"PRIsVALUE">", rb_ary_join(ary, rb_str_new2(", ")));
}
- break;
+ break;
case TS_CDHASH:
- ret = rb_str_new2("<cdhash>");
- break;
+ ret = rb_str_new2("<cdhash>");
+ break;
case TS_FUNCPTR:
- {
+ {
#ifdef HAVE_DLADDR
- Dl_info info;
- if (dladdr((void *)op, &info) && info.dli_sname) {
- ret = rb_str_new_cstr(info.dli_sname);
- break;
- }
+ Dl_info info;
+ if (dladdr((void *)op, &info) && info.dli_sname) {
+ ret = rb_str_new_cstr(info.dli_sname);
+ break;
+ }
#endif
- ret = rb_str_new2("<funcptr>");
- }
- break;
+ ret = rb_str_new2("<funcptr>");
+ }
+ break;
case TS_BUILTIN:
{
@@ -2091,7 +2250,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
break;
default:
- rb_bug("unknown operand type: %c", type);
+ rb_bug("unknown operand type: %c", type);
}
return ret;
}
@@ -2111,7 +2270,7 @@ right_strip(VALUE str)
*/
int
rb_iseq_disasm_insn(VALUE ret, const VALUE *code, size_t pos,
- const rb_iseq_t *iseq, VALUE child)
+ const rb_iseq_t *iseq, VALUE child)
{
VALUE insn = code[pos];
int len = insn_len(insn);
@@ -2122,60 +2281,60 @@ rb_iseq_disasm_insn(VALUE ret, const VALUE *code, size_t pos,
insn_name_buff = insn_name(insn);
if (1) {
- extern const int rb_vm_max_insn_name_size;
- rb_str_catf(str, "%04"PRIuSIZE" %-*s ", pos, rb_vm_max_insn_name_size, insn_name_buff);
+ extern const int rb_vm_max_insn_name_size;
+ rb_str_catf(str, "%04"PRIuSIZE" %-*s ", pos, rb_vm_max_insn_name_size, insn_name_buff);
}
else {
- rb_str_catf(str, "%04"PRIuSIZE" %-28.*s ", pos,
- (int)strcspn(insn_name_buff, "_"), insn_name_buff);
+ rb_str_catf(str, "%04"PRIuSIZE" %-28.*s ", pos,
+ (int)strcspn(insn_name_buff, "_"), insn_name_buff);
}
for (j = 0; types[j]; j++) {
- VALUE opstr = rb_insn_operand_intern(iseq, insn, j, code[pos + j + 1],
- len, pos, &code[pos + j + 2],
- child);
- rb_str_concat(str, opstr);
+ VALUE opstr = rb_insn_operand_intern(iseq, insn, j, code[pos + j + 1],
+ len, pos, &code[pos + j + 2],
+ child);
+ rb_str_concat(str, opstr);
- if (types[j + 1]) {
- rb_str_cat2(str, ", ");
- }
+ if (types[j + 1]) {
+ rb_str_cat2(str, ", ");
+ }
}
{
- unsigned int line_no = rb_iseq_line_no(iseq, pos);
- unsigned int prev = pos == 0 ? 0 : rb_iseq_line_no(iseq, pos - 1);
- if (line_no && line_no != prev) {
- long slen = RSTRING_LEN(str);
- slen = (slen > 70) ? 0 : (70 - slen);
- str = rb_str_catf(str, "%*s(%4d)", (int)slen, "", line_no);
- }
+ unsigned int line_no = rb_iseq_line_no(iseq, pos);
+ unsigned int prev = pos == 0 ? 0 : rb_iseq_line_no(iseq, pos - 1);
+ if (line_no && line_no != prev) {
+ long slen = RSTRING_LEN(str);
+ slen = (slen > 70) ? 0 : (70 - slen);
+ str = rb_str_catf(str, "%*s(%4d)", (int)slen, "", line_no);
+ }
}
{
- rb_event_flag_t events = rb_iseq_event_flags(iseq, pos);
- if (events) {
+ rb_event_flag_t events = rb_iseq_event_flags(iseq, pos);
+ if (events) {
str = rb_str_catf(str, "[%s%s%s%s%s%s%s%s%s%s%s]",
- events & RUBY_EVENT_LINE ? "Li" : "",
- events & RUBY_EVENT_CLASS ? "Cl" : "",
- events & RUBY_EVENT_END ? "En" : "",
- events & RUBY_EVENT_CALL ? "Ca" : "",
- events & RUBY_EVENT_RETURN ? "Re" : "",
- events & RUBY_EVENT_C_CALL ? "Cc" : "",
- events & RUBY_EVENT_C_RETURN ? "Cr" : "",
- events & RUBY_EVENT_B_CALL ? "Bc" : "",
+ events & RUBY_EVENT_LINE ? "Li" : "",
+ events & RUBY_EVENT_CLASS ? "Cl" : "",
+ events & RUBY_EVENT_END ? "En" : "",
+ events & RUBY_EVENT_CALL ? "Ca" : "",
+ events & RUBY_EVENT_RETURN ? "Re" : "",
+ events & RUBY_EVENT_C_CALL ? "Cc" : "",
+ events & RUBY_EVENT_C_RETURN ? "Cr" : "",
+ events & RUBY_EVENT_B_CALL ? "Bc" : "",
events & RUBY_EVENT_B_RETURN ? "Br" : "",
events & RUBY_EVENT_COVERAGE_LINE ? "Cli" : "",
events & RUBY_EVENT_COVERAGE_BRANCH ? "Cbr" : "");
- }
+ }
}
right_strip(str);
if (ret) {
- rb_str_cat2(str, "\n");
- rb_str_concat(ret, str);
+ rb_str_cat2(str, "\n");
+ rb_str_concat(ret, str);
}
else {
- printf("%.*s\n", (int)RSTRING_LEN(str), RSTRING_PTR(str));
+ printf("%.*s\n", (int)RSTRING_LEN(str), RSTRING_PTR(str));
}
return len;
}
@@ -2185,39 +2344,39 @@ catch_type(int type)
{
switch (type) {
case CATCH_TYPE_RESCUE:
- return "rescue";
+ return "rescue";
case CATCH_TYPE_ENSURE:
- return "ensure";
+ return "ensure";
case CATCH_TYPE_RETRY:
- return "retry";
+ return "retry";
case CATCH_TYPE_BREAK:
- return "break";
+ return "break";
case CATCH_TYPE_REDO:
- return "redo";
+ return "redo";
case CATCH_TYPE_NEXT:
- return "next";
+ return "next";
default:
- rb_bug("unknown catch type: %d", type);
- return 0;
+ rb_bug("unknown catch type: %d", type);
+ return 0;
}
}
static VALUE
iseq_inspect(const rb_iseq_t *iseq)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
if (!body->location.label) {
- return rb_sprintf("#<ISeq: uninitialized>");
+ return rb_sprintf("#<ISeq: uninitialized>");
}
else {
- const rb_code_location_t *loc = &body->location.code_location;
- return rb_sprintf("#<ISeq:%"PRIsVALUE"@%"PRIsVALUE":%d (%d,%d)-(%d,%d)>",
- body->location.label, rb_iseq_path(iseq),
- loc->beg_pos.lineno,
- loc->beg_pos.lineno,
- loc->beg_pos.column,
- loc->end_pos.lineno,
- loc->end_pos.column);
+ const rb_code_location_t *loc = &body->location.code_location;
+ return rb_sprintf("#<ISeq:%"PRIsVALUE"@%"PRIsVALUE":%d (%d,%d)-(%d,%d)>",
+ body->location.label, rb_iseq_path(iseq),
+ loc->beg_pos.lineno,
+ loc->beg_pos.lineno,
+ loc->beg_pos.column,
+ loc->end_pos.lineno,
+ loc->end_pos.column);
}
}
@@ -2230,10 +2389,10 @@ static const rb_data_type_t tmp_set = {
static VALUE
rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE *code;
VALUE str = rb_str_new(0, 0);
- VALUE child = rb_ary_tmp_new(3);
+ VALUE child = rb_ary_hidden_new(3);
unsigned int size;
unsigned int i;
long l;
@@ -2253,113 +2412,113 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
rb_str_cat2(str, "== disasm: ");
rb_str_append(str, iseq_inspect(iseq));
- rb_str_catf(str, " (catch: %s)", body->catch_except_p ? "TRUE" : "FALSE");
+ rb_str_catf(str, " (catch: %s)", body->catch_except_p ? "true" : "false");
if ((l = RSTRING_LEN(str) - indent_len) < header_minlen) {
- rb_str_modify_expand(str, header_minlen - l);
- memset(RSTRING_END(str), '=', header_minlen - l);
+ rb_str_modify_expand(str, header_minlen - l);
+ memset(RSTRING_END(str), '=', header_minlen - l);
}
rb_str_cat2(str, "\n");
/* show catch table information */
if (body->catch_table) {
- rb_str_cat(str, indent_str, indent_len);
- rb_str_cat2(str, "== catch table\n");
+ rb_str_cat(str, indent_str, indent_len);
+ rb_str_cat2(str, "== catch table\n");
}
if (body->catch_table) {
- rb_str_cat_cstr(indent, "| ");
- indent_str = RSTRING_PTR(indent);
- for (i = 0; i < body->catch_table->size; i++) {
- const struct iseq_catch_table_entry *entry =
- UNALIGNED_MEMBER_PTR(body->catch_table, entries[i]);
- rb_str_cat(str, indent_str, indent_len);
- rb_str_catf(str,
- "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
- catch_type((int)entry->type), (int)entry->start,
- (int)entry->end, (int)entry->sp, (int)entry->cont);
- if (entry->iseq && !(done_iseq && st_is_member(done_iseq, (st_data_t)entry->iseq))) {
- rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check(entry->iseq), indent));
- if (!done_iseq) {
+ rb_str_cat_cstr(indent, "| ");
+ indent_str = RSTRING_PTR(indent);
+ for (i = 0; i < body->catch_table->size; i++) {
+ const struct iseq_catch_table_entry *entry =
+ UNALIGNED_MEMBER_PTR(body->catch_table, entries[i]);
+ rb_str_cat(str, indent_str, indent_len);
+ rb_str_catf(str,
+ "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
+ catch_type((int)entry->type), (int)entry->start,
+ (int)entry->end, (int)entry->sp, (int)entry->cont);
+ if (entry->iseq && !(done_iseq && st_is_member(done_iseq, (st_data_t)entry->iseq))) {
+ rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check(entry->iseq), indent));
+ if (!done_iseq) {
done_iseq = st_init_numtable();
done_iseq_wrapper = TypedData_Wrap_Struct(0, &tmp_set, done_iseq);
}
- st_insert(done_iseq, (st_data_t)entry->iseq, (st_data_t)0);
- indent_str = RSTRING_PTR(indent);
- }
- }
- rb_str_resize(indent, indent_len);
- indent_str = RSTRING_PTR(indent);
+ st_insert(done_iseq, (st_data_t)entry->iseq, (st_data_t)0);
+ indent_str = RSTRING_PTR(indent);
+ }
+ }
+ rb_str_resize(indent, indent_len);
+ indent_str = RSTRING_PTR(indent);
}
if (body->catch_table) {
- rb_str_cat(str, indent_str, indent_len);
- rb_str_cat2(str, "|-------------------------------------"
- "-----------------------------------\n");
+ rb_str_cat(str, indent_str, indent_len);
+ rb_str_cat2(str, "|-------------------------------------"
+ "-----------------------------------\n");
}
/* show local table information */
if (body->local_table) {
- const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
- rb_str_cat(str, indent_str, indent_len);
- rb_str_catf(str,
- "local table (size: %d, argc: %d "
- "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n",
- body->local_table_size,
- body->param.lead_num,
- body->param.opt_num,
- body->param.flags.has_rest ? body->param.rest_start : -1,
- body->param.post_num,
- body->param.flags.has_block ? body->param.block_start : -1,
- body->param.flags.has_kw ? keyword->num : -1,
- body->param.flags.has_kw ? keyword->required_num : -1,
- body->param.flags.has_kwrest ? keyword->rest_start : -1);
-
- for (i = body->local_table_size; i > 0;) {
- int li = body->local_table_size - --i - 1;
- long width;
- VALUE name = local_var_name(iseq, 0, i);
+ const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
+ rb_str_cat(str, indent_str, indent_len);
+ rb_str_catf(str,
+ "local table (size: %d, argc: %d "
+ "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n",
+ body->local_table_size,
+ body->param.lead_num,
+ body->param.opt_num,
+ body->param.flags.has_rest ? body->param.rest_start : -1,
+ body->param.post_num,
+ body->param.flags.has_block ? body->param.block_start : -1,
+ body->param.flags.has_kw ? keyword->num : -1,
+ body->param.flags.has_kw ? keyword->required_num : -1,
+ body->param.flags.has_kwrest ? keyword->rest_start : -1);
+
+ for (i = body->local_table_size; i > 0;) {
+ int li = body->local_table_size - --i - 1;
+ long width;
+ VALUE name = local_var_name(iseq, 0, i);
char argi[0x100];
char opti[0x100];
opti[0] = '\0';
- if (body->param.flags.has_opt) {
- int argc = body->param.lead_num;
- int opts = body->param.opt_num;
- if (li >= argc && li < argc + opts) {
- snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
- body->param.opt_table[li - argc]);
- }
- }
-
- snprintf(argi, sizeof(argi), "%s%s%s%s%s%s", /* arg, opts, rest, post, kwrest, block */
- body->param.lead_num > li ? "Arg" : "",
- opti,
- (body->param.flags.has_rest && body->param.rest_start == li) ? "Rest" : "",
- (body->param.flags.has_post && body->param.post_start <= li && li < body->param.post_start + body->param.post_num) ? "Post" : "",
- (body->param.flags.has_kwrest && keyword->rest_start == li) ? "Kwrest" : "",
- (body->param.flags.has_block && body->param.block_start == li) ? "Block" : "");
-
- rb_str_cat(str, indent_str, indent_len);
- rb_str_catf(str, "[%2d] ", i + 1);
- width = RSTRING_LEN(str) + 11;
- rb_str_append(str, name);
- if (*argi) rb_str_catf(str, "<%s>", argi);
- if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
- }
- rb_str_cat_cstr(right_strip(str), "\n");
+ if (body->param.flags.has_opt) {
+ int argc = body->param.lead_num;
+ int opts = body->param.opt_num;
+ if (li >= argc && li < argc + opts) {
+ snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
+ body->param.opt_table[li - argc]);
+ }
+ }
+
+ snprintf(argi, sizeof(argi), "%s%s%s%s%s%s", /* arg, opts, rest, post, kwrest, block */
+ body->param.lead_num > li ? "Arg" : "",
+ opti,
+ (body->param.flags.has_rest && body->param.rest_start == li) ? "Rest" : "",
+ (body->param.flags.has_post && body->param.post_start <= li && li < body->param.post_start + body->param.post_num) ? "Post" : "",
+ (body->param.flags.has_kwrest && keyword->rest_start == li) ? "Kwrest" : "",
+ (body->param.flags.has_block && body->param.block_start == li) ? "Block" : "");
+
+ rb_str_cat(str, indent_str, indent_len);
+ rb_str_catf(str, "[%2d] ", i + 1);
+ width = RSTRING_LEN(str) + 11;
+ rb_str_append(str, name);
+ if (*argi) rb_str_catf(str, "<%s>", argi);
+ if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
+ }
+ rb_str_cat_cstr(right_strip(str), "\n");
}
/* show each line */
code = rb_iseq_original_iseq(iseq);
for (n = 0; n < size;) {
- rb_str_cat(str, indent_str, indent_len);
- n += rb_iseq_disasm_insn(str, code, n, iseq, child);
+ rb_str_cat(str, indent_str, indent_len);
+ n += rb_iseq_disasm_insn(str, code, n, iseq, child);
}
for (l = 0; l < RARRAY_LEN(child); l++) {
- VALUE isv = rb_ary_entry(child, l);
- if (done_iseq && st_is_member(done_iseq, (st_data_t)isv)) continue;
- rb_str_cat_cstr(str, "\n");
- rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check((rb_iseq_t *)isv), indent));
- indent_str = RSTRING_PTR(indent);
+ VALUE isv = rb_ary_entry(child, l);
+ if (done_iseq && st_is_member(done_iseq, (st_data_t)isv)) continue;
+ rb_str_cat_cstr(str, "\n");
+ rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check((rb_iseq_t *)isv), indent));
+ indent_str = RSTRING_PTR(indent);
}
RB_GC_GUARD(done_iseq_wrapper);
@@ -2375,6 +2534,34 @@ rb_iseq_disasm(const rb_iseq_t *iseq)
}
/*
+ * Estimates the number of instance variables that will be set on
+ * a given `class` with the initialize method defined in
+ * `initialize_iseq`
+ */
+attr_index_t
+rb_estimate_iv_count(VALUE klass, const rb_iseq_t * initialize_iseq)
+{
+ struct rb_id_table * iv_names = rb_id_table_create(0);
+
+ for (unsigned int i = 0; i < ISEQ_BODY(initialize_iseq)->ivc_size; i++) {
+ IVC cache = (IVC)&ISEQ_BODY(initialize_iseq)->is_entries[i];
+
+ if (cache->iv_set_name) {
+ rb_id_table_insert(iv_names, cache->iv_set_name, Qtrue);
+ }
+ }
+
+ attr_index_t count = (attr_index_t)rb_id_table_size(iv_names);
+
+ VALUE superclass = rb_class_superclass(klass);
+ count += RCLASS_EXT(superclass)->max_iv_count;
+
+ rb_id_table_free(iv_names);
+
+ return count;
+}
+
+/*
* call-seq:
* iseq.disasm -> str
* iseq.disassemble -> str
@@ -2403,7 +2590,7 @@ iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t *
{
unsigned int i;
VALUE *code = rb_iseq_original_iseq(iseq);
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const rb_iseq_t *child;
VALUE all_children = rb_obj_hide(rb_ident_hash_new());
@@ -2413,7 +2600,7 @@ iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t *
UNALIGNED_MEMBER_PTR(body->catch_table, entries[i]);
child = entry->iseq;
if (child) {
- if (rb_hash_aref(all_children, (VALUE)child) == Qnil) {
+ if (NIL_P(rb_hash_aref(all_children, (VALUE)child))) {
rb_hash_aset(all_children, (VALUE)child, Qtrue);
(*iter_func)(child, data);
}
@@ -2432,7 +2619,7 @@ iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t *
case TS_ISEQ:
child = (const rb_iseq_t *)code[i+j+1];
if (child) {
- if (rb_hash_aref(all_children, (VALUE)child) == Qnil) {
+ if (NIL_P(rb_hash_aref(all_children, (VALUE)child))) {
rb_hash_aset(all_children, (VALUE)child, Qtrue);
(*iter_func)(child, data);
}
@@ -2495,15 +2682,15 @@ static VALUE
iseqw_trace_points(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
unsigned int i;
VALUE ary = rb_ary_new();
for (i=0; i<body->insns_info.size; i++) {
- const struct iseq_insn_info_entry *entry = &body->insns_info.body[i];
- if (entry->events) {
- push_event_info(iseq, entry->events, entry->line_no, ary);
- }
+ const struct iseq_insn_info_entry *entry = &body->insns_info.body[i];
+ if (entry->events) {
+ push_event_info(iseq, entry->events, entry->line_no, ary);
+ }
}
return ary;
}
@@ -2630,17 +2817,11 @@ ruby_node_name(int node)
switch (node) {
#include "node_name.inc"
default:
- rb_bug("unknown node: %d", node);
- return 0;
+ rb_bug("unknown node: %d", node);
+ return 0;
}
}
-#define DECL_SYMBOL(name) \
- static ID sym_##name
-
-#define INIT_SYMBOL(name) \
- sym_##name = rb_intern(#name)
-
static VALUE
register_label(struct st_table *table, unsigned long idx)
{
@@ -2661,7 +2842,7 @@ exception_type2symbol(VALUE type)
case CATCH_TYPE_REDO: CONST_ID(id, "redo"); break;
case CATCH_TYPE_NEXT: CONST_ID(id, "next"); break;
default:
- rb_bug("unknown exception type: %d", (int)type);
+ rb_bug("unknown exception type: %d", (int)type);
}
return ID2SYM(id);
}
@@ -2680,12 +2861,58 @@ static const rb_data_type_t label_wrapper = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
+#define DECL_ID(name) \
+ static ID id_##name
+
+#define INIT_ID(name) \
+ id_##name = rb_intern(#name)
+
+static VALUE
+iseq_type_id(enum rb_iseq_type type)
+{
+ DECL_ID(top);
+ DECL_ID(method);
+ DECL_ID(block);
+ DECL_ID(class);
+ DECL_ID(rescue);
+ DECL_ID(ensure);
+ DECL_ID(eval);
+ DECL_ID(main);
+ DECL_ID(plain);
+
+ if (id_top == 0) {
+ INIT_ID(top);
+ INIT_ID(method);
+ INIT_ID(block);
+ INIT_ID(class);
+ INIT_ID(rescue);
+ INIT_ID(ensure);
+ INIT_ID(eval);
+ INIT_ID(main);
+ INIT_ID(plain);
+ }
+
+ switch (type) {
+ case ISEQ_TYPE_TOP: return id_top;
+ case ISEQ_TYPE_METHOD: return id_method;
+ case ISEQ_TYPE_BLOCK: return id_block;
+ case ISEQ_TYPE_CLASS: return id_class;
+ case ISEQ_TYPE_RESCUE: return id_rescue;
+ case ISEQ_TYPE_ENSURE: return id_ensure;
+ case ISEQ_TYPE_EVAL: return id_eval;
+ case ISEQ_TYPE_MAIN: return id_main;
+ case ISEQ_TYPE_PLAIN: return id_plain;
+ };
+
+ rb_bug("unsupported iseq type: %d", (int)type);
+}
+
static VALUE
iseq_data_to_ary(const rb_iseq_t *iseq)
{
unsigned int i;
long l;
- const struct rb_iseq_constant_body *const iseq_body = iseq->body;
+ const struct rb_iseq_constant_body *const iseq_body = ISEQ_BODY(iseq);
const struct iseq_insn_info_entry *prev_insn_info;
unsigned int pos;
int last_line = 0;
@@ -2704,209 +2931,191 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
struct st_table *labels_table = st_init_numtable();
VALUE labels_wrapper = TypedData_Wrap_Struct(0, &label_wrapper, labels_table);
- DECL_SYMBOL(top);
- DECL_SYMBOL(method);
- DECL_SYMBOL(block);
- DECL_SYMBOL(class);
- DECL_SYMBOL(rescue);
- DECL_SYMBOL(ensure);
- DECL_SYMBOL(eval);
- DECL_SYMBOL(main);
- DECL_SYMBOL(plain);
-
- if (sym_top == 0) {
- int i;
- for (i=0; i<numberof(insn_syms); i++) {
+ if (insn_syms[0] == 0) {
+ int i;
+ for (i=0; i<numberof(insn_syms); i++) {
insn_syms[i] = rb_intern(insn_name(i));
- }
- INIT_SYMBOL(top);
- INIT_SYMBOL(method);
- INIT_SYMBOL(block);
- INIT_SYMBOL(class);
- INIT_SYMBOL(rescue);
- INIT_SYMBOL(ensure);
- INIT_SYMBOL(eval);
- INIT_SYMBOL(main);
- INIT_SYMBOL(plain);
+ }
}
/* type */
- switch (iseq_body->type) {
- case ISEQ_TYPE_TOP: type = sym_top; break;
- case ISEQ_TYPE_METHOD: type = sym_method; break;
- case ISEQ_TYPE_BLOCK: type = sym_block; break;
- case ISEQ_TYPE_CLASS: type = sym_class; break;
- case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
- case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
- case ISEQ_TYPE_EVAL: type = sym_eval; break;
- case ISEQ_TYPE_MAIN: type = sym_main; break;
- case ISEQ_TYPE_PLAIN: type = sym_plain; break;
- default: rb_bug("unsupported iseq type: %d", (int)iseq_body->type);
- };
+ type = iseq_type_id(iseq_body->type);
/* locals */
for (i=0; i<iseq_body->local_table_size; i++) {
- ID lid = iseq_body->local_table[i];
- if (lid) {
- if (rb_id2str(lid)) {
- rb_ary_push(locals, ID2SYM(lid));
- }
- else { /* hidden variable from id_internal() */
- rb_ary_push(locals, ULONG2NUM(iseq_body->local_table_size-i+1));
- }
- }
- else {
- rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
- }
+ ID lid = iseq_body->local_table[i];
+ if (lid) {
+ if (rb_id2str(lid)) {
+ rb_ary_push(locals, ID2SYM(lid));
+ }
+ else { /* hidden variable from id_internal() */
+ rb_ary_push(locals, ULONG2NUM(iseq_body->local_table_size-i+1));
+ }
+ }
+ else {
+ rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
+ }
}
/* params */
{
- const struct rb_iseq_param_keyword *const keyword = iseq_body->param.keyword;
- int j;
-
- if (iseq_body->param.flags.has_opt) {
- int len = iseq_body->param.opt_num + 1;
- VALUE arg_opt_labels = rb_ary_new2(len);
-
- for (j = 0; j < len; j++) {
- VALUE l = register_label(labels_table, iseq_body->param.opt_table[j]);
- rb_ary_push(arg_opt_labels, l);
- }
- rb_hash_aset(params, ID2SYM(rb_intern("opt")), arg_opt_labels);
- }
-
- /* commit */
- if (iseq_body->param.flags.has_lead) rb_hash_aset(params, ID2SYM(rb_intern("lead_num")), INT2FIX(iseq_body->param.lead_num));
- if (iseq_body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_num")), INT2FIX(iseq_body->param.post_num));
- if (iseq_body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_start")), INT2FIX(iseq_body->param.post_start));
- if (iseq_body->param.flags.has_rest) rb_hash_aset(params, ID2SYM(rb_intern("rest_start")), INT2FIX(iseq_body->param.rest_start));
- if (iseq_body->param.flags.has_block) rb_hash_aset(params, ID2SYM(rb_intern("block_start")), INT2FIX(iseq_body->param.block_start));
- if (iseq_body->param.flags.has_kw) {
- VALUE keywords = rb_ary_new();
- int i, j;
- for (i=0; i<keyword->required_num; i++) {
- rb_ary_push(keywords, ID2SYM(keyword->table[i]));
- }
- for (j=0; i<keyword->num; i++, j++) {
- VALUE key = rb_ary_new_from_args(1, ID2SYM(keyword->table[i]));
- if (keyword->default_values[j] != Qundef) {
- rb_ary_push(key, keyword->default_values[j]);
- }
- rb_ary_push(keywords, key);
- }
-
- rb_hash_aset(params, ID2SYM(rb_intern("kwbits")),
- INT2FIX(keyword->bits_start));
- rb_hash_aset(params, ID2SYM(rb_intern("keyword")), keywords);
- }
- if (iseq_body->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(keyword->rest_start));
- if (iseq_body->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue);
+ const struct rb_iseq_param_keyword *const keyword = iseq_body->param.keyword;
+ int j;
+
+ if (iseq_body->param.flags.has_opt) {
+ int len = iseq_body->param.opt_num + 1;
+ VALUE arg_opt_labels = rb_ary_new2(len);
+
+ for (j = 0; j < len; j++) {
+ VALUE l = register_label(labels_table, iseq_body->param.opt_table[j]);
+ rb_ary_push(arg_opt_labels, l);
+ }
+ rb_hash_aset(params, ID2SYM(rb_intern("opt")), arg_opt_labels);
+ }
+
+ /* commit */
+ if (iseq_body->param.flags.has_lead) rb_hash_aset(params, ID2SYM(rb_intern("lead_num")), INT2FIX(iseq_body->param.lead_num));
+ if (iseq_body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_num")), INT2FIX(iseq_body->param.post_num));
+ if (iseq_body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_start")), INT2FIX(iseq_body->param.post_start));
+ if (iseq_body->param.flags.has_rest) rb_hash_aset(params, ID2SYM(rb_intern("rest_start")), INT2FIX(iseq_body->param.rest_start));
+ if (iseq_body->param.flags.has_block) rb_hash_aset(params, ID2SYM(rb_intern("block_start")), INT2FIX(iseq_body->param.block_start));
+ if (iseq_body->param.flags.has_kw) {
+ VALUE keywords = rb_ary_new();
+ int i, j;
+ for (i=0; i<keyword->required_num; i++) {
+ rb_ary_push(keywords, ID2SYM(keyword->table[i]));
+ }
+ for (j=0; i<keyword->num; i++, j++) {
+ VALUE key = rb_ary_new_from_args(1, ID2SYM(keyword->table[i]));
+ if (!UNDEF_P(keyword->default_values[j])) {
+ rb_ary_push(key, keyword->default_values[j]);
+ }
+ rb_ary_push(keywords, key);
+ }
+
+ rb_hash_aset(params, ID2SYM(rb_intern("kwbits")),
+ INT2FIX(keyword->bits_start));
+ rb_hash_aset(params, ID2SYM(rb_intern("keyword")), keywords);
+ }
+ if (iseq_body->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(keyword->rest_start));
+ if (iseq_body->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue);
}
/* body */
iseq_original = rb_iseq_original_iseq((rb_iseq_t *)iseq);
for (seq = iseq_original; seq < iseq_original + iseq_body->iseq_size; ) {
- VALUE insn = *seq++;
- int j, len = insn_len(insn);
- VALUE *nseq = seq + len - 1;
- VALUE ary = rb_ary_new2(len);
+ VALUE insn = *seq++;
+ int j, len = insn_len(insn);
+ VALUE *nseq = seq + len - 1;
+ VALUE ary = rb_ary_new2(len);
rb_ary_push(ary, ID2SYM(insn_syms[insn%numberof(insn_syms)]));
- for (j=0; j<len-1; j++, seq++) {
- switch (insn_op_type(insn, j)) {
- case TS_OFFSET: {
- unsigned long idx = nseq - iseq_original + *seq;
- rb_ary_push(ary, register_label(labels_table, idx));
- break;
- }
- case TS_LINDEX:
- case TS_NUM:
- rb_ary_push(ary, INT2FIX(*seq));
- break;
- case TS_VALUE:
- rb_ary_push(ary, obj_resurrect(*seq));
- break;
- case TS_ISEQ:
- {
- const rb_iseq_t *iseq = (rb_iseq_t *)*seq;
- if (iseq) {
- VALUE val = iseq_data_to_ary(rb_iseq_check(iseq));
- rb_ary_push(ary, val);
- }
- else {
- rb_ary_push(ary, Qnil);
- }
- }
- break;
- case TS_IC:
+ for (j=0; j<len-1; j++, seq++) {
+ enum ruby_insn_type_chars op_type = insn_op_type(insn, j);
+
+ switch (op_type) {
+ case TS_OFFSET: {
+ unsigned long idx = nseq - iseq_original + *seq;
+ rb_ary_push(ary, register_label(labels_table, idx));
+ break;
+ }
+ case TS_LINDEX:
+ case TS_NUM:
+ rb_ary_push(ary, INT2FIX(*seq));
+ break;
+ case TS_VALUE:
+ rb_ary_push(ary, obj_resurrect(*seq));
+ break;
+ case TS_ISEQ:
+ {
+ const rb_iseq_t *iseq = (rb_iseq_t *)*seq;
+ if (iseq) {
+ VALUE val = iseq_data_to_ary(rb_iseq_check(iseq));
+ rb_ary_push(ary, val);
+ }
+ else {
+ rb_ary_push(ary, Qnil);
+ }
+ }
+ break;
+ case TS_IC:
+ {
+ VALUE list = rb_ary_new();
+ const ID *ids = ((IC)*seq)->segments;
+ while (*ids) {
+ rb_ary_push(list, ID2SYM(*ids++));
+ }
+ rb_ary_push(ary, list);
+ }
+ break;
case TS_IVC:
- case TS_ISE:
- {
- union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
- rb_ary_push(ary, INT2FIX(is - iseq_body->is_entries));
- }
- break;
+ case TS_ICVARC:
+ case TS_ISE:
+ {
+ union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
+ rb_ary_push(ary, INT2FIX(is - ISEQ_IS_ENTRY_START(ISEQ_BODY(iseq), op_type)));
+ }
+ break;
case TS_CALLDATA:
- {
+ {
struct rb_call_data *cd = (struct rb_call_data *)*seq;
const struct rb_callinfo *ci = cd->ci;
- VALUE e = rb_hash_new();
+ VALUE e = rb_hash_new();
int argc = vm_ci_argc(ci);
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)));
+ 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 (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);
+ VALUE kw = rb_ary_new2((long)kwarg->keyword_len);
- argc -= kwarg->keyword_len;
+ 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(argc));
- rb_ary_push(ary, e);
- }
- break;
- case TS_ID:
- rb_ary_push(ary, ID2SYM(*seq));
- break;
- case TS_CDHASH:
- {
- VALUE hash = *seq;
- VALUE val = rb_ary_new();
- int i;
-
- rb_hash_foreach(hash, cdhash_each, val);
-
- for (i=0; i<RARRAY_LEN(val); i+=2) {
- VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
- unsigned long idx = nseq - iseq_original + pos;
-
- rb_ary_store(val, i+1,
- register_label(labels_table, idx));
- }
- rb_ary_push(ary, val);
- }
- break;
- case TS_FUNCPTR:
- {
+ 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(argc));
+ rb_ary_push(ary, e);
+ }
+ break;
+ case TS_ID:
+ rb_ary_push(ary, ID2SYM(*seq));
+ break;
+ case TS_CDHASH:
+ {
+ VALUE hash = *seq;
+ VALUE val = rb_ary_new();
+ int i;
+
+ rb_hash_foreach(hash, cdhash_each, val);
+
+ for (i=0; i<RARRAY_LEN(val); i+=2) {
+ VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
+ unsigned long idx = nseq - iseq_original + pos;
+
+ rb_ary_store(val, i+1,
+ register_label(labels_table, idx));
+ }
+ rb_ary_push(ary, val);
+ }
+ break;
+ case TS_FUNCPTR:
+ {
#if SIZEOF_VALUE <= SIZEOF_LONG
- VALUE val = LONG2NUM((SIGNED_VALUE)*seq);
+ VALUE val = LONG2NUM((SIGNED_VALUE)*seq);
#else
- VALUE val = LL2NUM((SIGNED_VALUE)*seq);
+ VALUE val = LL2NUM((SIGNED_VALUE)*seq);
#endif
- rb_ary_push(ary, val);
- }
- break;
+ rb_ary_push(ary, val);
+ }
+ break;
case TS_BUILTIN:
{
VALUE val = rb_hash_new();
@@ -2922,32 +3131,32 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
rb_ary_push(ary, val);
}
break;
- default:
- rb_bug("unknown operand: %c", insn_op_type(insn, j));
- }
- }
- rb_ary_push(body, ary);
+ default:
+ rb_bug("unknown operand: %c", insn_op_type(insn, j));
+ }
+ }
+ rb_ary_push(body, ary);
}
nbody = body;
/* exception */
if (iseq_body->catch_table) for (i=0; i<iseq_body->catch_table->size; i++) {
- VALUE ary = rb_ary_new();
- const struct iseq_catch_table_entry *entry =
- UNALIGNED_MEMBER_PTR(iseq_body->catch_table, entries[i]);
- rb_ary_push(ary, exception_type2symbol(entry->type));
- if (entry->iseq) {
- rb_ary_push(ary, iseq_data_to_ary(rb_iseq_check(entry->iseq)));
- }
- else {
- rb_ary_push(ary, Qnil);
- }
- rb_ary_push(ary, register_label(labels_table, entry->start));
- rb_ary_push(ary, register_label(labels_table, entry->end));
- rb_ary_push(ary, register_label(labels_table, entry->cont));
- rb_ary_push(ary, UINT2NUM(entry->sp));
- rb_ary_push(exception, ary);
+ VALUE ary = rb_ary_new();
+ const struct iseq_catch_table_entry *entry =
+ UNALIGNED_MEMBER_PTR(iseq_body->catch_table, entries[i]);
+ rb_ary_push(ary, exception_type2symbol(entry->type));
+ if (entry->iseq) {
+ rb_ary_push(ary, iseq_data_to_ary(rb_iseq_check(entry->iseq)));
+ }
+ else {
+ rb_ary_push(ary, Qnil);
+ }
+ rb_ary_push(ary, register_label(labels_table, entry->start));
+ rb_ary_push(ary, register_label(labels_table, entry->end));
+ rb_ary_push(ary, register_label(labels_table, entry->cont));
+ rb_ary_push(ary, UINT2NUM(entry->sp));
+ rb_ary_push(exception, ary);
}
/* make body with labels and insert line number */
@@ -2958,41 +3167,41 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
#endif
for (l=0, pos=0; l<RARRAY_LEN(nbody); l++) {
- const struct iseq_insn_info_entry *info;
- VALUE ary = RARRAY_AREF(nbody, l);
- st_data_t label;
+ const struct iseq_insn_info_entry *info;
+ VALUE ary = RARRAY_AREF(nbody, l);
+ st_data_t label;
- if (st_lookup(labels_table, pos, &label)) {
- rb_ary_push(body, (VALUE)label);
- }
+ if (st_lookup(labels_table, pos, &label)) {
+ rb_ary_push(body, (VALUE)label);
+ }
- info = get_insn_info(iseq, pos);
+ info = get_insn_info(iseq, pos);
#ifdef USE_ISEQ_NODE_ID
rb_ary_push(node_ids, INT2FIX(info->node_id));
#endif
- if (prev_insn_info != info) {
- int line = info->line_no;
- rb_event_flag_t events = info->events;
+ if (prev_insn_info != info) {
+ int line = info->line_no;
+ rb_event_flag_t events = info->events;
- if (line > 0 && last_line != line) {
- rb_ary_push(body, INT2FIX(line));
- last_line = line;
- }
+ if (line > 0 && last_line != line) {
+ rb_ary_push(body, INT2FIX(line));
+ last_line = line;
+ }
#define CHECK_EVENT(ev) if (events & ev) rb_ary_push(body, ID2SYM(rb_intern(#ev)));
- CHECK_EVENT(RUBY_EVENT_LINE);
- CHECK_EVENT(RUBY_EVENT_CLASS);
- CHECK_EVENT(RUBY_EVENT_END);
- CHECK_EVENT(RUBY_EVENT_CALL);
- CHECK_EVENT(RUBY_EVENT_RETURN);
- CHECK_EVENT(RUBY_EVENT_B_CALL);
- CHECK_EVENT(RUBY_EVENT_B_RETURN);
+ CHECK_EVENT(RUBY_EVENT_LINE);
+ CHECK_EVENT(RUBY_EVENT_CLASS);
+ CHECK_EVENT(RUBY_EVENT_END);
+ CHECK_EVENT(RUBY_EVENT_CALL);
+ CHECK_EVENT(RUBY_EVENT_RETURN);
+ CHECK_EVENT(RUBY_EVENT_B_CALL);
+ CHECK_EVENT(RUBY_EVENT_B_RETURN);
#undef CHECK_EVENT
- prev_insn_info = info;
- }
+ prev_insn_info = info;
+ }
- rb_ary_push(body, ary);
- pos += RARRAY_LENINT(ary); /* reject too huge data */
+ rb_ary_push(body, ary);
+ pos += RARRAY_LENINT(ary); /* reject too huge data */
}
RB_GC_GUARD(nbody);
RB_GC_GUARD(labels_wrapper);
@@ -3002,11 +3211,11 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq_body->stack_max));
rb_hash_aset(misc, ID2SYM(rb_intern("node_id")), INT2FIX(iseq_body->location.node_id));
rb_hash_aset(misc, ID2SYM(rb_intern("code_location")),
- rb_ary_new_from_args(4,
- INT2FIX(iseq_body->location.code_location.beg_pos.lineno),
- INT2FIX(iseq_body->location.code_location.beg_pos.column),
- INT2FIX(iseq_body->location.code_location.end_pos.lineno),
- INT2FIX(iseq_body->location.code_location.end_pos.column)));
+ rb_ary_new_from_args(4,
+ INT2FIX(iseq_body->location.code_location.beg_pos.lineno),
+ INT2FIX(iseq_body->location.code_location.beg_pos.column),
+ INT2FIX(iseq_body->location.code_location.end_pos.lineno),
+ INT2FIX(iseq_body->location.code_location.end_pos.column)));
#ifdef USE_ISEQ_NODE_ID
rb_hash_aset(misc, ID2SYM(rb_intern("node_ids")), node_ids);
#endif
@@ -3024,7 +3233,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
rb_ary_push(val, iseq_body->location.label);
rb_ary_push(val, rb_iseq_path(iseq));
rb_ary_push(val, rb_iseq_realpath(iseq));
- rb_ary_push(val, iseq_body->location.first_lineno);
+ rb_ary_push(val, RB_INT2NUM(iseq_body->location.first_lineno));
rb_ary_push(val, ID2SYM(type));
rb_ary_push(val, locals);
rb_ary_push(val, params);
@@ -3037,88 +3246,88 @@ VALUE
rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
{
int i, r;
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
VALUE a, args = rb_ary_new2(body->param.size);
ID req, opt, rest, block, key, keyrest;
#define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
#define PARAM_ID(i) body->local_table[(i)]
#define PARAM(i, type) ( \
- PARAM_TYPE(type), \
- rb_id2str(PARAM_ID(i)) ? \
- rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
- a)
+ PARAM_TYPE(type), \
+ rb_id2str(PARAM_ID(i)) ? \
+ rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
+ a)
CONST_ID(req, "req");
CONST_ID(opt, "opt");
if (is_proc) {
- for (i = 0; i < body->param.lead_num; i++) {
- PARAM_TYPE(opt);
- rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
- rb_ary_push(args, a);
- }
+ for (i = 0; i < body->param.lead_num; i++) {
+ PARAM_TYPE(opt);
+ rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
+ rb_ary_push(args, a);
+ }
}
else {
- for (i = 0; i < body->param.lead_num; i++) {
- rb_ary_push(args, PARAM(i, req));
- }
+ for (i = 0; i < body->param.lead_num; i++) {
+ rb_ary_push(args, PARAM(i, req));
+ }
}
r = body->param.lead_num + body->param.opt_num;
for (; i < r; i++) {
- PARAM_TYPE(opt);
- if (rb_id2str(PARAM_ID(i))) {
- rb_ary_push(a, ID2SYM(PARAM_ID(i)));
- }
- rb_ary_push(args, a);
+ PARAM_TYPE(opt);
+ if (rb_id2str(PARAM_ID(i))) {
+ rb_ary_push(a, ID2SYM(PARAM_ID(i)));
+ }
+ rb_ary_push(args, a);
}
if (body->param.flags.has_rest) {
- CONST_ID(rest, "rest");
- rb_ary_push(args, PARAM(body->param.rest_start, rest));
+ CONST_ID(rest, "rest");
+ rb_ary_push(args, PARAM(body->param.rest_start, rest));
}
r = body->param.post_start + body->param.post_num;
if (is_proc) {
- for (i = body->param.post_start; i < r; i++) {
- PARAM_TYPE(opt);
- rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
- rb_ary_push(args, a);
- }
+ for (i = body->param.post_start; i < r; i++) {
+ PARAM_TYPE(opt);
+ rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
+ rb_ary_push(args, a);
+ }
}
else {
- for (i = body->param.post_start; i < r; i++) {
- rb_ary_push(args, PARAM(i, req));
- }
+ for (i = body->param.post_start; i < r; i++) {
+ rb_ary_push(args, PARAM(i, req));
+ }
}
if (body->param.flags.accepts_no_kwarg) {
- ID nokey;
- CONST_ID(nokey, "nokey");
- PARAM_TYPE(nokey);
- rb_ary_push(args, a);
+ ID nokey;
+ CONST_ID(nokey, "nokey");
+ PARAM_TYPE(nokey);
+ rb_ary_push(args, a);
}
if (body->param.flags.has_kw) {
- i = 0;
- if (keyword->required_num > 0) {
- ID keyreq;
- CONST_ID(keyreq, "keyreq");
- for (; i < keyword->required_num; i++) {
- PARAM_TYPE(keyreq);
- if (rb_id2str(keyword->table[i])) {
- rb_ary_push(a, ID2SYM(keyword->table[i]));
- }
- rb_ary_push(args, a);
- }
- }
- CONST_ID(key, "key");
- for (; i < keyword->num; i++) {
- PARAM_TYPE(key);
- if (rb_id2str(keyword->table[i])) {
- rb_ary_push(a, ID2SYM(keyword->table[i]));
- }
- rb_ary_push(args, a);
- }
+ i = 0;
+ if (keyword->required_num > 0) {
+ ID keyreq;
+ CONST_ID(keyreq, "keyreq");
+ for (; i < keyword->required_num; i++) {
+ PARAM_TYPE(keyreq);
+ if (rb_id2str(keyword->table[i])) {
+ rb_ary_push(a, ID2SYM(keyword->table[i]));
+ }
+ rb_ary_push(args, a);
+ }
+ }
+ CONST_ID(key, "key");
+ for (; i < keyword->num; i++) {
+ PARAM_TYPE(key);
+ if (rb_id2str(keyword->table[i])) {
+ rb_ary_push(a, ID2SYM(keyword->table[i]));
+ }
+ rb_ary_push(args, a);
+ }
}
if (body->param.flags.has_kwrest || body->param.flags.ruby2_keywords) {
ID param;
- CONST_ID(keyrest, "keyrest");
+ CONST_ID(keyrest, "keyrest");
PARAM_TYPE(keyrest);
if (body->param.flags.has_kwrest &&
rb_id2str(param = PARAM_ID(keyword->rest_start))) {
@@ -3127,11 +3336,11 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
else if (body->param.flags.ruby2_keywords) {
rb_ary_push(a, ID2SYM(idPow));
}
- rb_ary_push(args, a);
+ rb_ary_push(args, a);
}
if (body->param.flags.has_block) {
- CONST_ID(block, "block");
- rb_ary_push(args, PARAM(body->param.block_start, block));
+ CONST_ID(block, "block");
+ rb_ary_push(args, PARAM(body->param.block_start, block));
}
return args;
}
@@ -3140,20 +3349,20 @@ VALUE
rb_iseq_defined_string(enum defined_type type)
{
static const char expr_names[][18] = {
- "nil",
- "instance-variable",
- "local-variable",
- "global-variable",
- "class variable",
- "constant",
- "method",
- "yield",
- "super",
- "self",
- "true",
- "false",
- "assignment",
- "expression",
+ "nil",
+ "instance-variable",
+ "local-variable",
+ "global-variable",
+ "class variable",
+ "constant",
+ "method",
+ "yield",
+ "super",
+ "self",
+ "true",
+ "false",
+ "assignment",
+ "expression",
};
const char *estr;
@@ -3181,7 +3390,7 @@ rb_vm_encoded_insn_data_table_init(void)
const void * const *table = rb_vm_get_insns_address_table();
#define INSN_CODE(insn) ((VALUE)table[insn])
#else
-#define INSN_CODE(insn) (insn)
+#define INSN_CODE(insn) ((VALUE)(insn))
#endif
st_data_t insn;
encoded_insn_data = st_init_numtable_with_size(VM_INSTRUCTION_SIZE / 2);
@@ -3221,7 +3430,26 @@ rb_vm_insn_addr2insn(const void *addr)
rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr);
}
-// Decode `iseq->body->iseq_encoded[i]` to an insn.
+// Unlike rb_vm_insn_addr2insn, this function can return trace opcode variants.
+int
+rb_vm_insn_addr2opcode(const void *addr)
+{
+ st_data_t key = (st_data_t)addr;
+ st_data_t val;
+
+ if (st_lookup(encoded_insn_data, key, &val)) {
+ insn_data_t *e = (insn_data_t *)val;
+ int opcode = e->insn;
+ if (addr == e->trace_encoded_insn) {
+ opcode += VM_INSTRUCTION_SIZE/2;
+ }
+ return opcode;
+ }
+
+ rb_bug("rb_vm_insn_addr2opcode: invalid insn address: %p", addr);
+}
+
+// Decode `ISEQ_BODY(iseq)->iseq_encoded[i]` to an insn.
int
rb_vm_insn_decode(const VALUE encoded)
{
@@ -3254,17 +3482,34 @@ encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon,
void
rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos)
{
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
encoded_iseq_trace_instrument(&iseq_encoded[pos], 0, false);
}
+// We need to fire call events on instructions with b_call events if the block
+// is running as a method. So, if we are listening for call events, then
+// instructions that have b_call events need to become trace variants.
+// Use this function when making decisions about recompiling to trace variants.
+static inline rb_event_flag_t
+add_bmethod_events(rb_event_flag_t events)
+{
+ if (events & RUBY_EVENT_CALL) {
+ events |= RUBY_EVENT_B_CALL;
+ }
+ if (events & RUBY_EVENT_RETURN) {
+ events |= RUBY_EVENT_B_RETURN;
+ }
+ return events;
+}
+
+// Note, to support call/return events for bmethods, turnon_event can have more events than tpval.
static int
iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line)
{
unsigned int pc;
int n = 0;
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
VM_ASSERT(ISEQ_EXECUTABLE_P(iseq));
@@ -3291,6 +3536,7 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events,
if (n > 0) {
if (iseq->aux.exec.local_hooks == NULL) {
((rb_iseq_t *)iseq)->aux.exec.local_hooks = RB_ZALLOC(rb_hook_list_t);
+ iseq->aux.exec.local_hooks->is_local = true;
}
rb_hook_list_connect_tracepoint((VALUE)iseq, iseq->aux.exec.local_hooks, tpval, target_line);
}
@@ -3314,9 +3560,12 @@ iseq_add_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
}
int
-rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line)
+rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod)
{
struct trace_set_local_events_struct data;
+ if (target_bmethod) {
+ turnon_events = add_bmethod_events(turnon_events);
+ }
data.turnon_events = turnon_events;
data.tpval = tpval;
data.target_line = target_line;
@@ -3334,7 +3583,7 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
if (iseq->aux.exec.local_hooks) {
unsigned int pc;
- const struct rb_iseq_constant_body *const body = iseq->body;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
rb_event_flag_t local_events = 0;
@@ -3342,12 +3591,11 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
local_events = iseq->aux.exec.local_hooks->events;
if (local_events == 0) {
- if (iseq->aux.exec.local_hooks->running == 0) {
- rb_hook_list_free(iseq->aux.exec.local_hooks);
- }
+ rb_hook_list_free(iseq->aux.exec.local_hooks);
((rb_iseq_t *)iseq)->aux.exec.local_hooks = NULL;
}
+ local_events = add_bmethod_events(local_events);
for (pc = 0; pc<body->iseq_size;) {
rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events), false);
@@ -3384,29 +3632,55 @@ void
rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
{
if (iseq->aux.exec.global_trace_events == turnon_events) {
- return;
+ return;
}
if (!ISEQ_EXECUTABLE_P(iseq)) {
- /* this is building ISeq */
- return;
+ /* this is building ISeq */
+ return;
}
else {
unsigned int pc;
- const struct rb_iseq_constant_body *const body = iseq->body;
- VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
rb_event_flag_t enabled_events;
rb_event_flag_t local_events = iseq->aux.exec.local_hooks ? iseq->aux.exec.local_hooks->events : 0;
((rb_iseq_t *)iseq)->aux.exec.global_trace_events = turnon_events;
- enabled_events = turnon_events | local_events;
+ enabled_events = add_bmethod_events(turnon_events | local_events);
for (pc=0; 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, true);
- }
+ }
}
}
+bool rb_vm_call_ivar_attrset_p(const vm_call_handler ch);
+void rb_vm_cc_general(const struct rb_callcache *cc);
+
+static int
+clear_attr_ccs_i(void *vstart, void *vend, size_t stride, void *data)
+{
+ VALUE v = (VALUE)vstart;
+ for (; v != (VALUE)vend; v += stride) {
+ void *ptr = asan_poisoned_object_p(v);
+ asan_unpoison_object(v, false);
+
+ if (imemo_type_p(v, imemo_callcache) && rb_vm_call_ivar_attrset_p(((const struct rb_callcache *)v)->call_)) {
+ rb_vm_cc_general((struct rb_callcache *)v);
+ }
+
+ asan_poison_object_if(ptr, v);
+ }
+ return 0;
+}
+
+void
+rb_clear_attr_ccs(void)
+{
+ rb_objspace_each_objects(clear_attr_ccs_i, NULL);
+}
+
static int
trace_set_i(void *vstart, void *vend, size_t stride, void *data)
{
@@ -3417,9 +3691,12 @@ trace_set_i(void *vstart, void *vend, size_t stride, void *data)
void *ptr = asan_poisoned_object_p(v);
asan_unpoison_object(v, false);
- if (rb_obj_is_iseq(v)) {
- rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events);
- }
+ if (rb_obj_is_iseq(v)) {
+ rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events);
+ }
+ else if (imemo_type_p(v, imemo_callcache) && rb_vm_call_ivar_attrset_p(((const struct rb_callcache *)v)->call_)) {
+ rb_vm_cc_general((struct rb_callcache *)v);
+ }
asan_poison_object_if(ptr, v);
}
@@ -3531,9 +3808,9 @@ iseqw_s_load_from_binary_extra_data(VALUE self, VALUE str)
struct succ_index_table {
uint64_t imm_part[IMMEDIATE_TABLE_SIZE / 9];
struct succ_dict_block {
- unsigned int rank;
- uint64_t small_block_ranks; /* 9 bits * 7 = 63 bits */
- uint64_t bits[512/64];
+ unsigned int rank;
+ uint64_t small_block_ranks; /* 9 bits * 7 = 63 bits */
+ uint64_t bits[512/64];
} succ_part[FLEX_ARY_LEN];
};
@@ -3555,27 +3832,27 @@ succ_index_table_create(int max_pos, int *data, int size)
r = 0;
for (j = 0; j < imm_size; j++) {
- for (i = 0; i < 9; i++) {
- if (r < size && data[r] == j * 9 + i) r++;
- imm_block_rank_set(sd->imm_part[j], i, r);
- }
+ for (i = 0; i < 9; i++) {
+ if (r < size && data[r] == j * 9 + i) r++;
+ imm_block_rank_set(sd->imm_part[j], i, r);
+ }
}
for (k = 0; k < succ_size; k++) {
- struct succ_dict_block *sd_block = &sd->succ_part[k];
- int small_rank = 0;
- sd_block->rank = r;
- for (j = 0; j < 8; j++) {
- uint64_t bits = 0;
- if (j) small_block_rank_set(sd_block->small_block_ranks, j, small_rank);
- for (i = 0; i < 64; i++) {
- if (r < size && data[r] == k * 512 + j * 64 + i + IMMEDIATE_TABLE_SIZE) {
- bits |= ((uint64_t)1) << i;
- r++;
- }
- }
- sd_block->bits[j] = bits;
- small_rank += rb_popcount64(bits);
- }
+ struct succ_dict_block *sd_block = &sd->succ_part[k];
+ int small_rank = 0;
+ sd_block->rank = r;
+ for (j = 0; j < 8; j++) {
+ uint64_t bits = 0;
+ if (j) small_block_rank_set(sd_block->small_block_ranks, j, small_rank);
+ for (i = 0; i < 64; i++) {
+ if (r < size && data[r] == k * 512 + j * 64 + i + IMMEDIATE_TABLE_SIZE) {
+ bits |= ((uint64_t)1) << i;
+ r++;
+ }
+ }
+ sd_block->bits[j] = bits;
+ small_rank += rb_popcount64(bits);
+ }
}
return sd;
}
@@ -3589,20 +3866,20 @@ succ_index_table_invert(int max_pos, struct succ_index_table *sd, int size)
int i, j, k, r = -1;
p = positions;
for (j = 0; j < imm_size; j++) {
- for (i = 0; i < 9; i++) {
- int nr = imm_block_rank_get(sd->imm_part[j], i);
- if (r != nr) *p++ = j * 9 + i;
- r = nr;
- }
+ for (i = 0; i < 9; i++) {
+ int nr = imm_block_rank_get(sd->imm_part[j], i);
+ if (r != nr) *p++ = j * 9 + i;
+ r = nr;
+ }
}
for (k = 0; k < succ_size; k++) {
- for (j = 0; j < 8; j++) {
- for (i = 0; i < 64; i++) {
- if (sd->succ_part[k].bits[j] & (((uint64_t)1) << i)) {
- *p++ = k * 512 + j * 64 + i + IMMEDIATE_TABLE_SIZE;
- }
- }
- }
+ for (j = 0; j < 8; j++) {
+ for (i = 0; i < 64; i++) {
+ if (sd->succ_part[k].bits[j] & (((uint64_t)1) << i)) {
+ *p++ = k * 512 + j * 64 + i + IMMEDIATE_TABLE_SIZE;
+ }
+ }
+ }
}
return positions;
}
@@ -3611,23 +3888,43 @@ static int
succ_index_lookup(const struct succ_index_table *sd, int x)
{
if (x < IMMEDIATE_TABLE_SIZE) {
- const int i = x / 9;
- const int j = x % 9;
- return imm_block_rank_get(sd->imm_part[i], j);
+ const int i = x / 9;
+ const int j = x % 9;
+ return imm_block_rank_get(sd->imm_part[i], j);
}
else {
- const int block_index = (x - IMMEDIATE_TABLE_SIZE) / 512;
- const struct succ_dict_block *block = &sd->succ_part[block_index];
- const int block_bit_index = (x - IMMEDIATE_TABLE_SIZE) % 512;
- const int small_block_index = block_bit_index / 64;
- const int small_block_popcount = small_block_rank_get(block->small_block_ranks, small_block_index);
- const int popcnt = rb_popcount64(block->bits[small_block_index] << (63 - block_bit_index % 64));
+ const int block_index = (x - IMMEDIATE_TABLE_SIZE) / 512;
+ const struct succ_dict_block *block = &sd->succ_part[block_index];
+ const int block_bit_index = (x - IMMEDIATE_TABLE_SIZE) % 512;
+ const int small_block_index = block_bit_index / 64;
+ const int small_block_popcount = small_block_rank_get(block->small_block_ranks, small_block_index);
+ const int popcnt = rb_popcount64(block->bits[small_block_index] << (63 - block_bit_index % 64));
- return block->rank + small_block_popcount + popcnt;
+ return block->rank + small_block_popcount + popcnt;
}
}
#endif
+
+/*
+ * call-seq:
+ * iseq.script_lines -> array or nil
+ *
+ * It returns recorded script lines if it is availalble.
+ * The script lines are not limited to the iseq range, but
+ * are entire lines of the source file.
+ *
+ * Note that this is an API for ruby internal use, debugging,
+ * and research. Do not use this for any other purpose.
+ * The compatibility is not guaranteed.
+ */
+static VALUE
+iseqw_script_lines(VALUE self)
+{
+ const rb_iseq_t *iseq = iseqw_check(self);
+ return ISEQ_BODY(iseq)->variable.script_lines;
+}
+
/*
* Document-class: RubyVM::InstructionSequence
*
@@ -3668,7 +3965,6 @@ Init_ISeq(void)
rb_define_singleton_method(rb_cISeq, "load_from_binary", iseqw_s_load_from_binary, 1);
rb_define_singleton_method(rb_cISeq, "load_from_binary_extra_data", iseqw_s_load_from_binary_extra_data, 1);
-
/* location APIs */
rb_define_method(rb_cISeq, "path", iseqw_path, 0);
rb_define_method(rb_cISeq, "absolute_path", iseqw_absolute_path, 0);
@@ -3695,6 +3991,9 @@ Init_ISeq(void)
rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1);
rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1);
+ // script lines
+ rb_define_method(rb_cISeq, "script_lines", iseqw_script_lines, 0);
+
rb_undef_method(CLASS_OF(rb_cISeq), "translate");
rb_undef_method(CLASS_OF(rb_cISeq), "load_iseq");
}
diff --git a/iseq.h b/iseq.h
index b792e13703..2f83e7336d 100644
--- a/iseq.h
+++ b/iseq.h
@@ -17,6 +17,12 @@ RUBY_EXTERN const int ruby_api_version[];
#define ISEQ_MAJOR_VERSION ((unsigned int)ruby_api_version[0])
#define ISEQ_MINOR_VERSION ((unsigned int)ruby_api_version[1])
+#define ISEQ_MBITS_SIZE sizeof(iseq_bits_t)
+#define ISEQ_MBITS_BITLENGTH (ISEQ_MBITS_SIZE * CHAR_BIT)
+#define ISEQ_MBITS_SET(buf, i) (buf[(i) / ISEQ_MBITS_BITLENGTH] |= ((iseq_bits_t)1 << ((i) % ISEQ_MBITS_BITLENGTH)))
+#define ISEQ_MBITS_SET_P(buf, i) ((buf[(i) / ISEQ_MBITS_BITLENGTH] >> ((i) % ISEQ_MBITS_BITLENGTH)) & 0x1)
+#define ISEQ_MBITS_BUFLEN(size) roomof(size, ISEQ_MBITS_BITLENGTH)
+
#ifndef USE_ISEQ_NODE_ID
#define USE_ISEQ_NODE_ID 1
#endif
@@ -25,38 +31,39 @@ RUBY_EXTERN const int ruby_api_version[];
typedef struct rb_iseq_struct rb_iseq_t;
#define rb_iseq_t rb_iseq_t
#endif
+typedef void (*rb_iseq_callback)(const rb_iseq_t *, void *);
extern const ID rb_iseq_shared_exc_local_tbl[];
-#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_COVERAGE(iseq) ISEQ_BODY(iseq)->variable.coverage
+#define ISEQ_COVERAGE_SET(iseq, cov) RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->variable.coverage, cov)
#define ISEQ_LINE_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_LINES)
#define ISEQ_BRANCH_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_BRANCHES)
-#define ISEQ_PC2BRANCHINDEX(iseq) iseq->body->variable.pc2branchindex
-#define ISEQ_PC2BRANCHINDEX_SET(iseq, h) RB_OBJ_WRITE(iseq, &iseq->body->variable.pc2branchindex, h)
+#define ISEQ_PC2BRANCHINDEX(iseq) ISEQ_BODY(iseq)->variable.pc2branchindex
+#define ISEQ_PC2BRANCHINDEX_SET(iseq, h) RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->variable.pc2branchindex, h)
-#define ISEQ_FLIP_CNT(iseq) (iseq)->body->variable.flip_count
+#define ISEQ_FLIP_CNT(iseq) ISEQ_BODY(iseq)->variable.flip_count
static inline rb_snum_t
ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq)
{
- rb_snum_t cnt = iseq->body->variable.flip_count;
- iseq->body->variable.flip_count += 1;
+ rb_snum_t cnt = ISEQ_BODY(iseq)->variable.flip_count;
+ ISEQ_BODY(iseq)->variable.flip_count += 1;
return cnt;
}
static inline VALUE *
ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq)
{
- return iseq->body->variable.original_iseq;
+ return ISEQ_BODY(iseq)->variable.original_iseq;
}
static inline void
ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq)
{
- void *ptr = iseq->body->variable.original_iseq;
- iseq->body->variable.original_iseq = NULL;
+ void *ptr = ISEQ_BODY(iseq)->variable.original_iseq;
+ ISEQ_BODY(iseq)->variable.original_iseq = NULL;
if (ptr) {
ruby_xfree(ptr);
}
@@ -65,24 +72,25 @@ ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq)
static inline VALUE *
ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size)
{
- return iseq->body->variable.original_iseq =
+ return ISEQ_BODY(iseq)->variable.original_iseq =
ALLOC_N(VALUE, size);
}
#define ISEQ_TRACE_EVENTS (RUBY_EVENT_LINE | \
- RUBY_EVENT_CLASS | \
- RUBY_EVENT_END | \
- RUBY_EVENT_CALL | \
- RUBY_EVENT_RETURN| \
- RUBY_EVENT_B_CALL| \
- RUBY_EVENT_B_RETURN| \
+ RUBY_EVENT_CLASS | \
+ RUBY_EVENT_END | \
+ RUBY_EVENT_CALL | \
+ RUBY_EVENT_RETURN| \
+ RUBY_EVENT_C_CALL| \
+ RUBY_EVENT_C_RETURN| \
+ RUBY_EVENT_B_CALL| \
+ RUBY_EVENT_B_RETURN| \
RUBY_EVENT_COVERAGE_LINE| \
RUBY_EVENT_COVERAGE_BRANCH)
#define ISEQ_NOT_LOADED_YET IMEMO_FL_USER1
#define ISEQ_USE_COMPILE_DATA IMEMO_FL_USER2
#define ISEQ_TRANSLATED IMEMO_FL_USER3
-#define ISEQ_MARKABLE_ISEQ IMEMO_FL_USER4
#define ISEQ_EXECUTABLE_P(iseq) (FL_TEST_RAW(((VALUE)iseq), ISEQ_NOT_LOADED_YET | ISEQ_USE_COMPILE_DATA) == 0)
@@ -106,15 +114,18 @@ struct iseq_compile_data {
struct iseq_compile_data_storage *storage_current;
} insn;
bool in_rescue;
+ bool in_masgn;
int loopval_popped; /* used by NODE_BREAK */
int last_line;
int label_no;
int node_level;
int isolated_depth;
unsigned int ci_index;
+ unsigned int ic_index;
const rb_compile_option_t *option;
struct rb_id_table *ivar_cache_table;
const struct rb_builtin_function *builtin_function_table;
+ const NODE *root_node;
#if OPT_SUPPORT_JOKE
st_table *labels_table;
#endif
@@ -124,10 +135,10 @@ static inline struct iseq_compile_data *
ISEQ_COMPILE_DATA(const rb_iseq_t *iseq)
{
if (iseq->flags & ISEQ_USE_COMPILE_DATA) {
- return iseq->aux.compile_data;
+ return iseq->aux.compile_data;
}
else {
- return NULL;
+ return NULL;
}
}
@@ -157,7 +168,7 @@ const rb_iseq_t *rb_iseq_ibf_load(VALUE str);
const rb_iseq_t *rb_iseq_ibf_load_bytes(const char *cstr, size_t);
VALUE rb_iseq_ibf_load_extra_data(VALUE str);
void rb_iseq_init_trace(rb_iseq_t *iseq);
-int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line);
+int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod);
int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval);
const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
@@ -165,6 +176,8 @@ const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body);
#endif
+int rb_vm_insn_addr2opcode(const void *addr);
+
RUBY_SYMBOL_EXPORT_BEGIN
/* compile.c */
@@ -172,11 +185,10 @@ VALUE rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node);
VALUE rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func * ifunc);
VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq);
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc,
- VALUE locals, VALUE args,
- VALUE exception, VALUE body);
+ VALUE locals, VALUE args,
+ VALUE exception, VALUE body);
void rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *arena);
-/* iseq.c */
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc);
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos);
@@ -193,6 +205,7 @@ const rb_iseq_t *rb_iseqw_to_iseq(VALUE iseqw);
VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq); /* obsolete */
int rb_iseq_from_eval_p(const rb_iseq_t *iseq);
+VALUE rb_iseq_type(const rb_iseq_t *iseq);
VALUE rb_iseq_label(const rb_iseq_t *iseq);
VALUE rb_iseq_base_label(const rb_iseq_t *iseq);
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq);
@@ -227,28 +240,29 @@ struct iseq_insn_info_entry {
rb_event_flag_t events;
};
+/*
+ * iseq type:
+ * CATCH_TYPE_RESCUE, CATCH_TYPE_ENSURE:
+ * use iseq as continuation.
+ *
+ * CATCH_TYPE_BREAK (iter):
+ * use iseq as key.
+ *
+ * CATCH_TYPE_BREAK (while), CATCH_TYPE_RETRY,
+ * CATCH_TYPE_REDO, CATCH_TYPE_NEXT:
+ * NULL.
+ */
+enum rb_catch_type {
+ CATCH_TYPE_RESCUE = INT2FIX(1),
+ CATCH_TYPE_ENSURE = INT2FIX(2),
+ CATCH_TYPE_RETRY = INT2FIX(3),
+ CATCH_TYPE_BREAK = INT2FIX(4),
+ CATCH_TYPE_REDO = INT2FIX(5),
+ CATCH_TYPE_NEXT = INT2FIX(6)
+};
+
struct iseq_catch_table_entry {
- enum catch_type {
- CATCH_TYPE_RESCUE = INT2FIX(1),
- CATCH_TYPE_ENSURE = INT2FIX(2),
- CATCH_TYPE_RETRY = INT2FIX(3),
- CATCH_TYPE_BREAK = INT2FIX(4),
- CATCH_TYPE_REDO = INT2FIX(5),
- CATCH_TYPE_NEXT = INT2FIX(6)
- } type;
-
- /*
- * iseq type:
- * CATCH_TYPE_RESCUE, CATCH_TYPE_ENSURE:
- * use iseq as continuation.
- *
- * CATCH_TYPE_BREAK (iter):
- * use iseq as key.
- *
- * CATCH_TYPE_BREAK (while), CATCH_TYPE_RETRY,
- * CATCH_TYPE_REDO, CATCH_TYPE_NEXT:
- * NULL.
- */
+ enum rb_catch_type type;
rb_iseq_t *iseq;
unsigned int start;
@@ -266,12 +280,12 @@ static inline int
iseq_catch_table_bytes(int n)
{
enum {
- catch_table_entry_size = sizeof(struct iseq_catch_table_entry),
- catch_table_entries_max = (INT_MAX - offsetof(struct iseq_catch_table, entries)) / catch_table_entry_size
+ catch_table_entry_size = sizeof(struct iseq_catch_table_entry),
+ catch_table_entries_max = (INT_MAX - offsetof(struct iseq_catch_table, entries)) / catch_table_entry_size
};
if (n > catch_table_entries_max) rb_fatal("too large iseq_catch_table - %d", n);
return (int)(offsetof(struct iseq_catch_table, entries) +
- n * catch_table_entry_size);
+ n * catch_table_entry_size);
}
#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE (512)
diff --git a/kernel.rb b/kernel.rb
index de20fffcf9..9cc58bc1d9 100644
--- a/kernel.rb
+++ b/kernel.rb
@@ -169,6 +169,10 @@ module Kernel
# Float("123.0_badstring", exception: false) #=> nil
#
def Float(arg, exception: true)
- Primitive.rb_f_float(arg, exception)
+ if Primitive.mandatory_only?
+ Primitive.rb_f_float1(arg)
+ else
+ Primitive.rb_f_float(arg, exception)
+ end
end
end
diff --git a/lex.c.blt b/lex.c.blt
index 92a4793b00..85727ed00f 100644
--- a/lex.c.blt
+++ b/lex.c.blt
@@ -34,7 +34,7 @@
struct kwtable {short name, id[2], state;};
const struct kwtable *rb_reserved_word(const char *, unsigned int);
#ifndef RIPPER
-static const struct kwtable *reserved_word(/*const char *, unsigned int*/);
+static const struct kwtable *reserved_word(register const char *str, register size_t len);
#define rb_reserved_word(str, len) reserved_word(str, len)
#line 9 "defs/keywords"
struct kwtable;
diff --git a/lib/.document b/lib/.document
deleted file mode 100644
index 0d612d1077..0000000000
--- a/lib/.document
+++ /dev/null
@@ -1,26 +0,0 @@
-# Add files to this as they become documented
-
-*.rb
-
-# bundler # not in RDoc
-cgi
-csv
-drb
-forwardable
-irb
-matrix
-net
-optparse
-racc/*.rb
-racc/rdoc
-rdoc
-rexml
-rinda
-rss
-rubygems
-scanf.rb
-shell
-unicode_normalize
-uri
-webrick
-yaml
diff --git a/lib/English.gemspec b/lib/English.gemspec
index ad6eb7aced..a08542bcda 100644
--- a/lib/English.gemspec
+++ b/lib/English.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "english"
- spec.version = "0.7.1"
+ spec.version = "0.7.2"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
@@ -18,7 +18,5 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
diff --git a/lib/abbrev.gemspec b/lib/abbrev.gemspec
index 72837ed2ab..c28b960c8c 100644
--- a/lib/abbrev.gemspec
+++ b/lib/abbrev.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "abbrev"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Akinori MUSHA"]
spec.email = ["knu@idaemons.org"]
diff --git a/lib/base64.gemspec b/lib/base64.gemspec
index 1863a3fd3d..daa0b7fa14 100644
--- a/lib/base64.gemspec
+++ b/lib/base64.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "base64"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Yusuke Endoh"]
spec.email = ["mame@ruby-lang.org"]
diff --git a/lib/base64.rb b/lib/base64.rb
index 5c8df841f1..693aa1f519 100644
--- a/lib/base64.rb
+++ b/lib/base64.rb
@@ -82,8 +82,8 @@ module Base64
# You can remove the padding by setting +padding+ as false.
def urlsafe_encode64(bin, padding: true)
str = strict_encode64(bin)
+ str.chomp!("==") or str.chomp!("=") unless padding
str.tr!("+/", "-_")
- str.delete!("=") unless padding
str
end
@@ -99,9 +99,11 @@ module Base64
# NOTE: RFC 4648 does say nothing about unpadded input, but says that
# "the excess pad characters MAY also be ignored", so it is inferred that
# unpadded input is also acceptable.
- str = str.tr("-_", "+/")
if !str.end_with?("=") && str.length % 4 != 0
str = str.ljust((str.length + 3) & ~3, "=")
+ str.tr!("-_", "+/")
+ else
+ str = str.tr("-_", "+/")
end
strict_decode64(str)
end
diff --git a/lib/benchmark/version.rb b/lib/benchmark/version.rb
index 90d1a3900c..645966fd80 100644
--- a/lib/benchmark/version.rb
+++ b/lib/benchmark/version.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: true
module Benchmark
- VERSION = "0.1.1"
+ VERSION = "0.2.1"
end
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 791831d0e7..f83268e9cd 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -19,7 +19,7 @@ require_relative "bundler/build_metadata"
#
# Since Ruby 2.6, Bundler is a part of Ruby's standard library.
#
-# Bunder is used by creating _gemfiles_ listing all the project dependencies
+# Bundler is used by creating _gemfiles_ listing all the project dependencies
# and (optionally) their versions and then using
#
# require 'bundler/setup'
@@ -41,8 +41,8 @@ module Bundler
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__)
@@ -57,7 +57,7 @@ module Bundler
autoload :Installer, File.expand_path("bundler/installer", __dir__)
autoload :LazySpecification, File.expand_path("bundler/lazy_specification", __dir__)
autoload :LockfileParser, File.expand_path("bundler/lockfile_parser", __dir__)
- autoload :MatchPlatform, File.expand_path("bundler/match_platform", __dir__)
+ autoload :MatchRemoteMetadata, File.expand_path("bundler/match_remote_metadata", __dir__)
autoload :ProcessLock, File.expand_path("bundler/process_lock", __dir__)
autoload :RemoteSpecification, File.expand_path("bundler/remote_specification", __dir__)
autoload :Resolver, File.expand_path("bundler/resolver", __dir__)
@@ -65,6 +65,7 @@ module Bundler
autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__)
autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__)
autoload :Runtime, File.expand_path("bundler/runtime", __dir__)
+ autoload :SelfManager, File.expand_path("bundler/self_manager", __dir__)
autoload :Settings, File.expand_path("bundler/settings", __dir__)
autoload :SharedHelpers, File.expand_path("bundler/shared_helpers", __dir__)
autoload :Source, File.expand_path("bundler/source", __dir__)
@@ -74,11 +75,12 @@ module Bundler
autoload :StubSpecification, File.expand_path("bundler/stub_specification", __dir__)
autoload :UI, File.expand_path("bundler/ui", __dir__)
autoload :URICredentialsFilter, File.expand_path("bundler/uri_credentials_filter", __dir__)
- autoload :VersionRanges, File.expand_path("bundler/version_ranges", __dir__)
+ autoload :URINormalizer, File.expand_path("bundler/uri_normalizer", __dir__)
+ autoload :SafeMarshal, File.expand_path("bundler/safe_marshal", __dir__)
class << self
def configure
- @configured ||= configure_gem_home_and_path
+ @configure ||= configure_gem_home_and_path
end
def ui
@@ -95,6 +97,17 @@ module Bundler
@bundle_path ||= Pathname.new(configured_bundle_path.path).expand_path(root)
end
+ def create_bundle_path
+ SharedHelpers.filesystem_access(bundle_path.to_s) do |p|
+ mkdir_p(p)
+ end unless bundle_path.exist?
+
+ @bundle_path = bundle_path.realpath
+ rescue Errno::EEXIST
+ raise PathError, "Could not install to path `#{bundle_path}` " \
+ "because a file already exists at that path. Either remove or rename the file so the directory can be created."
+ end
+
def configured_bundle_path
@configured_bundle_path ||= settings.path.tap(&:validate!)
end
@@ -197,9 +210,10 @@ module Bundler
end
def frozen_bundle?
- frozen = settings[:deployment]
- frozen ||= settings[:frozen]
- frozen
+ frozen = settings[:frozen]
+ return frozen unless frozen.nil?
+
+ settings[:deployment]
end
def locked_gems
@@ -318,9 +332,9 @@ module Bundler
FileUtils.remove_entry_secure(path) if path && File.exist?(path)
rescue ArgumentError
message = <<EOF
-It is a security vulnerability to allow your home directory to be world-writable, and bundler can not continue.
+It is a security vulnerability to allow your home directory to be world-writable, and bundler cannot continue.
You should probably consider fixing this issue by running `chmod o-w ~` on *nix.
-Please refer to https://ruby-doc.org/stdlib-2.1.2/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure for details.
+Please refer to https://ruby-doc.org/stdlib-3.1.2/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure for details.
EOF
File.world_writable?(path) ? Bundler.ui.warn(message) : raise
raise PathError, "Please fix the world-writable issue with your #{path} directory"
@@ -368,7 +382,7 @@ EOF
if env.key?("RUBYLIB")
rubylib = env["RUBYLIB"].split(File::PATH_SEPARATOR)
- rubylib.delete(File.expand_path("..", __FILE__))
+ rubylib.delete(__dir__)
env["RUBYLIB"] = rubylib.join(File::PATH_SEPARATOR)
end
@@ -442,7 +456,7 @@ EOF
end
def local_platform
- return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY]
+ return Gem::Platform::RUBY if settings[:force_ruby_platform]
Gem::Platform.local
end
@@ -475,41 +489,9 @@ EOF
configured_bundle_path.use_system_gems?
end
- def requires_sudo?
- return @requires_sudo if defined?(@requires_sudo_ran)
-
- sudo_present = which "sudo" if settings.allow_sudo?
-
- if sudo_present
- # the bundle path and subdirectories need to be writable for RubyGems
- # to be able to unpack and install gems without exploding
- path = bundle_path
- path = path.parent until path.exist?
-
- # bins are written to a different location on OS X
- bin_dir = Pathname.new(Bundler.system_bindir)
- bin_dir = bin_dir.parent until bin_dir.exist?
-
- # if any directory is not writable, we need sudo
- files = [path, bin_dir] | Dir[bundle_path.join("build_info/*").to_s] | Dir[bundle_path.join("*").to_s]
- unwritable_files = files.reject {|f| File.writable?(f) }
- sudo_needed = !unwritable_files.empty?
- if sudo_needed
- Bundler.ui.warn "Following files may not be writable, so sudo is needed:\n #{unwritable_files.map(&:to_s).sort.join("\n ")}"
- end
- end
-
- @requires_sudo_ran = true
- @requires_sudo = settings.allow_sudo? && sudo_present && sudo_needed
- end
-
def mkdir_p(path, options = {})
- if requires_sudo? && !options[:no_sudo]
- sudo "mkdir -p '#{path}'" unless File.exist?(path)
- else
- SharedHelpers.filesystem_access(path, :write) do |p|
- FileUtils.mkdir_p(p)
- end
+ SharedHelpers.filesystem_access(path, :write) do |p|
+ FileUtils.mkdir_p(p)
end
end
@@ -517,7 +499,7 @@ EOF
if File.file?(executable) && File.executable?(executable)
executable
elsif paths = ENV["PATH"]
- quote = '"'.freeze
+ quote = '"'
paths.split(File::PATH_SEPARATOR).find do |path|
path = path[1..-2] if path.start_with?(quote) && path.end_with?(quote)
executable_path = File.expand_path(executable, path)
@@ -526,41 +508,14 @@ EOF
end
end
- def sudo(str)
- SUDO_MUTEX.synchronize do
- prompt = "\n\n" + <<-PROMPT.gsub(/^ {6}/, "").strip + " "
- Your user account isn't allowed to install to the system RubyGems.
- You can cancel this installation and run:
-
- 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.
-
- Password:
- PROMPT
-
- unless @prompted_for_sudo ||= system(%(sudo -k -p "#{prompt}" true))
- raise SudoNotPermittedError,
- "Bundler requires sudo access to install at the moment. " \
- "Try installing again, granting Bundler sudo access when prompted, or installing into a different path."
- end
-
- `sudo -p "#{prompt}" #{str}`
- end
- end
-
def read_file(file)
SharedHelpers.filesystem_access(file, :read) do
File.open(file, "r:UTF-8", &:read)
end
end
- def load_marshal(data)
- Marshal.load(data)
- rescue StandardError => e
- raise MarshalError, "#{e.class}: #{e.message}"
+ def safe_load_marshal(data)
+ load_marshal(data, :marshal_proc => SafeMarshal.proc)
end
def load_gemspec(file, validate = false)
@@ -569,7 +524,7 @@ EOF
@gemspec_cache[key] ||= load_gemspec_uncached(file, validate)
# Protect against caching side-effected gemspecs by returning a
# new instance each time.
- @gemspec_cache[key].dup if @gemspec_cache[key]
+ @gemspec_cache[key]&.dup
end
def load_gemspec_uncached(file, validate = false)
@@ -596,7 +551,7 @@ EOF
def git_present?
return @git_present if defined?(@git_present)
- @git_present = Bundler.which("git") || Bundler.which("git.exe")
+ @git_present = Bundler.which("git#{RbConfig::CONFIG["EXEEXT"]}")
end
def feature_flag
@@ -618,7 +573,7 @@ EOF
@bin_path = nil
@bundler_major_version = nil
@bundle_path = nil
- @configured = nil
+ @configure = nil
@configured_bundle_path = nil
@definition = nil
@load = nil
@@ -636,15 +591,32 @@ EOF
@rubygems = nil
end
+ def configure_gem_home_and_path(path = bundle_path)
+ configure_gem_path
+ configure_gem_home(path)
+ Bundler.rubygems.clear_paths
+ end
+
+ def self_manager
+ @self_manager ||= begin
+ require_relative "bundler/self_manager"
+ Bundler::SelfManager.new
+ end
+ end
+
private
+ def load_marshal(data, marshal_proc: nil)
+ Marshal.load(data, marshal_proc)
+ rescue TypeError => e
+ raise MarshalError, "#{e.class}: #{e.message}"
+ end
+
def eval_yaml_gemspec(path, contents)
- require_relative "bundler/psyched_yaml"
+ Kernel.require "psych"
- # If the YAML is invalid, Syck raises an ArgumentError, and Psych
- # raises a Psych::SyntaxError. See psyched_yaml.rb for more info.
Gem::Specification.from_yaml(contents)
- rescue YamlLibrarySyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception
+ rescue ::Psych::SyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception
eval_gemspec(path, contents)
end
@@ -656,29 +628,17 @@ EOF
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
diff --git a/lib/bundler/.document b/lib/bundler/.document
new file mode 100644
index 0000000000..238bbd8705
--- /dev/null
+++ b/lib/bundler/.document
@@ -0,0 +1 @@
+# not in RDoc
diff --git a/lib/bundler/build_metadata.rb b/lib/bundler/build_metadata.rb
index 0846e82e06..8bffb2fae7 100644
--- a/lib/bundler/build_metadata.rb
+++ b/lib/bundler/build_metadata.rb
@@ -27,7 +27,7 @@ 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.expand_path("../../../.git", __dir__)
if File.directory?(git_dir)
return @git_commit_sha = Dir.chdir(git_dir) { `git rev-parse --short HEAD`.strip.freeze }
end
diff --git a/lib/bundler/bundler.gemspec b/lib/bundler/bundler.gemspec
index 38c533b0c1..da50b46225 100644
--- a/lib/bundler/bundler.gemspec
+++ b/lib/bundler/bundler.gemspec
@@ -22,17 +22,15 @@ Gem::Specification.new do |s|
s.summary = "The best way to manage your application's dependencies"
s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
- if s.respond_to?(:metadata=)
- s.metadata = {
- "bug_tracker_uri" => "https://github.com/rubygems/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
- "changelog_uri" => "https://github.com/rubygems/rubygems/blob/master/bundler/CHANGELOG.md",
- "homepage_uri" => "https://bundler.io/",
- "source_code_uri" => "https://github.com/rubygems/rubygems/",
- }
- end
+ s.metadata = {
+ "bug_tracker_uri" => "https://github.com/rubygems/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
+ "changelog_uri" => "https://github.com/rubygems/rubygems/blob/master/bundler/CHANGELOG.md",
+ "homepage_uri" => "https://bundler.io/",
+ "source_code_uri" => "https://github.com/rubygems/rubygems/tree/master/bundler",
+ }
- s.required_ruby_version = ">= 2.3.0"
- s.required_rubygems_version = ">= 2.5.2"
+ s.required_ruby_version = ">= 2.6.0"
+ s.required_rubygems_version = ">= 3.0.1"
s.files = Dir.glob("lib/bundler{.rb,/**/*}", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index aa94ad2da0..a3eb494db2 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -10,6 +10,7 @@ module Bundler
AUTO_INSTALL_CMDS = %w[show binstubs outdated exec open console licenses clean].freeze
PARSEABLE_COMMANDS = %w[check config help exec platform show version].freeze
+ EXTENSIONS = ["c", "rust"].freeze
COMMAND_ALIASES = {
"check" => "c",
@@ -22,6 +23,8 @@ module Bundler
}.freeze
def self.start(*)
+ check_deprecated_ext_option(ARGV) if ARGV.include?("--ext")
+
super
ensure
Bundler::SharedHelpers.print_major_deprecations!
@@ -61,6 +64,8 @@ module Bundler
Bundler.reset_settings_and_root!
end
+ Bundler.self_manager.restart_with_locked_bundler_if_needed
+
Bundler.settings.set_command_option_if_given :retry, options[:retry]
current_cmd = args.last[:current_command].name
@@ -73,14 +78,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])
@@ -159,6 +156,7 @@ module Bundler
dependency listed in the gemspec file to the newly created Gemfile.
D
method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
+ method_option "gemfile", :type => :string, :banner => "Use the specified name for the gemfile instead of 'Gemfile'"
def init
require_relative "cli/init"
Init.new(options.dup).run
@@ -192,6 +190,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
@@ -223,6 +222,8 @@ module Bundler
"Specify the number of jobs to run in parallel"
method_option "local", :type => :boolean, :banner =>
"Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "prefer-local", :type => :boolean, :banner =>
+ "Only attempt to fetch gems remotely if not present locally, even if newer versions are available remotely"
method_option "no-cache", :type => :boolean, :banner =>
"Don't update the existing gem cache."
method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
@@ -241,7 +242,7 @@ module Bundler
"Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
method_option "trust-policy", :alias => "P", :type => :string, :banner =>
"Gem trust policy (like gem install -P). Must be one of " +
- Bundler.rubygems.security_policy_keys.join("|")
+ Bundler.rubygems.security_policy_keys.join("|")
method_option "without", :type => :array, :banner =>
"Exclude gems that are part of the specified named group."
method_option "with", :type => :array, :banner =>
@@ -295,6 +296,8 @@ module Bundler
"Prefer updating only to next minor version"
method_option "major", :type => :boolean, :banner =>
"Prefer updating to next major version (default)"
+ method_option "pre", :type => :boolean, :banner =>
+ "Always choose the highest allowed version when updating gems, regardless of prerelease status"
method_option "strict", :type => :boolean, :banner =>
"Do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "conservative", :type => :boolean, :banner =>
@@ -338,6 +341,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
@@ -373,8 +377,12 @@ module Bundler
method_option "version", :aliases => "-v", :type => :string
method_option "group", :aliases => "-g", :type => :string
method_option "source", :aliases => "-s", :type => :string
+ method_option "require", :aliases => "-r", :type => :string, :banner => "Adds require path to gem. Provide false, or a path as a string."
+ method_option "path", :type => :string
method_option "git", :type => :string
+ method_option "github", :type => :string
method_option "branch", :type => :string
+ method_option "ref", :type => :string
method_option "skip-install", :type => :boolean, :banner =>
"Adds gem to the Gemfile but does not install it"
method_option "optimistic", :type => :boolean, :banner => "Adds optimistic declaration of version to gem"
@@ -392,7 +400,7 @@ module Bundler
are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
For more information on patch level options (--major, --minor, --patch,
- --update-strict) see documentation on the same options on the update command.
+ --strict) see documentation on the same options on the update command.
D
method_option "group", :type => :string, :banner => "List gems from a specific group"
method_option "groups", :type => :boolean, :banner => "List gems organized by groups"
@@ -400,10 +408,9 @@ module Bundler
"Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
method_option "source", :type => :array, :banner => "Check against a specific source"
- strict_is_update = Bundler.feature_flag.forget_cli_options?
- method_option "filter-strict", :type => :boolean, :aliases => strict_is_update ? [] : %w[--strict], :banner =>
+ method_option "filter-strict", :type => :boolean, :aliases => "--strict", :banner =>
"Only list newer versions allowed by your Gemfile requirements"
- method_option "update-strict", :type => :boolean, :aliases => strict_is_update ? %w[--strict] : [], :banner =>
+ method_option "update-strict", :type => :boolean, :banner =>
"Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "minor", :type => :boolean, :banner => "Prefer updating only to next minor version"
method_option "major", :type => :boolean, :banner => "Prefer updating to next major version (default)"
@@ -469,7 +476,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
@@ -477,6 +484,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
@@ -499,6 +510,7 @@ module Bundler
subcommand "config", Config
desc "open GEM", "Opens the source directory of the given bundled gem"
+ method_option "path", :type => :string, :lazy_default => "", :banner => "Open relative path of the gem source."
def open(name)
require_relative "cli/open"
Open.new(options, name).run
@@ -512,7 +524,7 @@ module Bundler
end
end
- desc "version", "Prints the bundler's version information"
+ desc "version", "Prints Bundler version information"
def version
cli_help = current_command.name == "cli_help"
if cli_help || ARGV.include?("version")
@@ -555,7 +567,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
@@ -569,7 +581,7 @@ module Bundler
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 :ext, :type => :string, :desc => "Generate the boilerplate for C extension code.", :enum => EXTENSIONS
method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library."
method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
@@ -577,7 +589,7 @@ module Bundler
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)`"
+ :desc => "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`"
method_option :linter, :type => :string, :lazy_default => Bundler.settings["gem.linter"] || "",
:desc => "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
method_option :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>`."
@@ -608,14 +620,14 @@ module Bundler
private :gem
def self.source_root
- File.expand_path(File.join(File.dirname(__FILE__), "templates"))
+ File.expand_path("templates", __dir__)
end
desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", :hide => true
method_option "dry-run", :type => :boolean, :default => false, :banner =>
"Only print out changes, do not clean gems"
method_option "force", :type => :boolean, :default => false, :banner =>
- "Forces clean even if --path is not set"
+ "Forces cleaning up unused gems even if Bundler is configured to use globally installed gems. As a consequence, removes all system gems except for the ones in the current application."
def clean
require_relative "cli/clean"
Clean.new(options.dup).run
@@ -663,10 +675,14 @@ module Bundler
"If updating, prefer updating only to next minor version"
method_option "major", :type => :boolean, :banner =>
"If updating, prefer updating to next major version (default)"
+ method_option "pre", :type => :boolean, :banner =>
+ "If updating, always choose the highest allowed version, regardless of prerelease status"
method_option "strict", :type => :boolean, :banner =>
"If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "conservative", :type => :boolean, :banner =>
"If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
+ method_option "bundler", :type => :string, :lazy_default => "> 0.a", :banner =>
+ "Update the locked version of bundler"
def lock
require_relative "cli/lock"
Lock.new(options).run
@@ -744,6 +760,38 @@ module Bundler
end
end
+ def self.check_deprecated_ext_option(arguments)
+ # when deprecated version of `--ext` is called
+ # print out deprecation warning and pretend `--ext=c` was provided
+ if deprecated_ext_value?(arguments)
+ SharedHelpers.major_deprecation 2, "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been deprecated. Please select a language, e.g. `--ext=rust` to generate a Rust extension. This gem will now be generated as if `--ext=c` was used."
+ arguments[arguments.index("--ext")] = "--ext=c"
+ end
+ end
+
+ def self.deprecated_ext_value?(arguments)
+ index = arguments.index("--ext")
+ next_argument = arguments[index+1]
+
+ # it is ok when --ext is followed with valid extension value
+ # for example `bundle gem hello --ext c`
+ return false if EXTENSIONS.include?(next_argument)
+
+ # deprecated call when --ext is called with no value in last position
+ # for example `bundle gem hello_gem --ext`
+ return true if next_argument.nil?
+
+ # deprecated call when --ext is followed by other parameter
+ # for example `bundle gem --ext --no-ci hello_gem`
+ return true if next_argument.start_with?("-")
+
+ # deprecated call when --ext is followed by gem name
+ # for example `bundle gem --ext hello_gem`
+ return true if next_argument
+
+ false
+ end
+
private
# Automatically invoke `bundle install` and resume if
@@ -806,17 +854,10 @@ module Bundler
current = Gem::Version.new(VERSION)
return if current >= latest
- latest_installed = Bundler.rubygems.find_name("bundler").map(&:version).max
-
- installation = "To install the latest version, run `gem install bundler#{" --pre" if latest.prerelease?}`"
- if latest_installed && latest_installed > current
- suggestion = "To update to the most recent installed version (#{latest_installed}), run `bundle update --bundler`"
- suggestion = "#{installation}\n#{suggestion}" if latest_installed < latest
- else
- suggestion = installation
- end
- Bundler.ui.warn "The latest bundler is #{latest}, but you are currently running #{current}.\n#{suggestion}"
+ Bundler.ui.warn \
+ "The latest bundler is #{latest}, but you are currently running #{current}.\n" \
+ "To update to the most recent version, run `bundle update --bundler`"
rescue RuntimeError
nil
end
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb
index 5bcf30d82d..08fa6547fb 100644
--- a/lib/bundler/cli/add.rb
+++ b/lib/bundler/cli/add.rb
@@ -40,7 +40,7 @@ module Bundler
raise InvalidOption, "Please specify gems to add." if gems.empty?
version.to_a.each do |v|
- raise InvalidOption, "Invalid gem requirement pattern '#{v}'" unless Gem::Requirement::PATTERN =~ v.to_s
+ raise InvalidOption, "Invalid gem requirement pattern '#{v}'" unless Gem::Requirement::PATTERN.match?(v.to_s)
end
end
end
diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb
index 639c01ff39..fc2fad47a5 100644
--- a/lib/bundler/cli/binstubs.rb
+++ b/lib/bundler/cli/binstubs.rb
@@ -11,7 +11,7 @@ module Bundler
def run
Bundler.definition.validate_runtime!
path_option = options["path"]
- path_option = nil if path_option && path_option.empty?
+ path_option = nil if path_option&.empty?
Bundler.settings.set_command_option :bin, path_option if options["path"]
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
installer = Installer.new(Bundler.root, Bundler.definition)
@@ -40,7 +40,11 @@ module Bundler
end
if options[:standalone]
- next Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") if gem_name == "bundler"
+ if gem_name == "bundler"
+ Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") unless options[:all]
+ next
+ end
+
Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do
installer.generate_standalone_bundler_executable_stubs(spec, installer_opts)
end
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index 65c51337d2..cc1f37f0c3 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -17,7 +17,7 @@ module Bundler
begin
definition.resolve_only_locally!
not_installed = definition.missing_specs
- rescue GemNotFound, VersionConflict
+ rescue GemNotFound, SolveFailure
Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
Bundler.ui.warn "Install missing gems with `bundle install`."
exit 1
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
index ba259143b7..d654406f65 100644
--- a/lib/bundler/cli/common.rb
+++ b/lib/bundler/cli/common.rb
@@ -15,6 +15,7 @@ module Bundler
end
def self.output_fund_metadata_summary
+ return if Bundler.settings["ignore_funding_requests"]
definition = Bundler.definition
current_dependencies = definition.requested_dependencies
current_specs = definition.specs
@@ -40,7 +41,7 @@ module Bundler
end
def self.verbalize_groups(groups)
- groups.map!{|g| "'#{g}'" }
+ 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"
@@ -109,7 +110,8 @@ module Bundler
definition.gem_version_promoter.tap do |gvp|
gvp.level = patch_level.first || :major
- gvp.strict = options[:strict] || options["update-strict"] || options["filter-strict"]
+ gvp.strict = options[:strict] || options["filter-strict"]
+ gvp.pre = options[:pre]
end
end
diff --git a/lib/bundler/cli/config.rb b/lib/bundler/cli/config.rb
index 8d2aba0916..e1222c75dd 100644
--- a/lib/bundler/cli/config.rb
+++ b/lib/bundler/cli/config.rb
@@ -180,7 +180,7 @@ module Bundler
scopes = %w[global local].select {|s| options[s] }
case scopes.size
when 0
- @scope = "global"
+ @scope = inside_app? ? "local" : "global"
@explicit_scope = false
when 1
@scope = scopes.first
@@ -189,6 +189,15 @@ module Bundler
"The options #{scopes.join " and "} were specified. Please only use one of the switches at a time."
end
end
+
+ private
+
+ def inside_app?
+ Bundler.root
+ true
+ rescue GemfileNotFound
+ false
+ end
end
end
end
diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb
index 97b8dc0663..1eb8ea8254 100644
--- a/lib/bundler/cli/console.rb
+++ b/lib/bundler/cli/console.rb
@@ -30,9 +30,9 @@ module Bundler
def get_constant(name)
const_name = {
- "pry" => :Pry,
+ "pry" => :Pry,
"ripl" => :Ripl,
- "irb" => :IRB,
+ "irb" => :IRB,
}[name]
Object.const_get(const_name)
rescue NameError
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb
index c28997bc7d..e299a5a8c2 100644
--- a/lib/bundler/cli/doctor.rb
+++ b/lib/bundler/cli/doctor.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
require "rbconfig"
+require "shellwords"
+require "fiddle"
module Bundler
class CLI::Doctor
@@ -22,14 +24,14 @@ 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?
@@ -70,7 +72,12 @@ module Bundler
definition.specs.each do |spec|
bundles_for_gem(spec).each do |bundle|
- bad_paths = dylibs(bundle).select {|f| !File.exist?(f) }
+ bad_paths = dylibs(bundle).select do |f|
+ Fiddle.dlopen(f)
+ false
+ rescue Fiddle::DLError
+ true
+ end
if bad_paths.any?
broken_links[spec] ||= []
broken_links[spec].concat(bad_paths)
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index 318d57fb06..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
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index c9794c4003..7f1200f4a0 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -15,7 +15,7 @@ module Bundler
"test-unit" => "3.0",
}.freeze
- attr_reader :options, :gem_name, :thor, :name, :target
+ attr_reader :options, :gem_name, :thor, :name, :target, :extension
def initialize(options, gem_name, thor)
@options = options
@@ -28,7 +28,11 @@ module Bundler
@name = @gem_name
@target = SharedHelpers.pwd.join(gem_name)
- validate_ext_name if options[:ext]
+ @extension = options[:ext]
+
+ validate_ext_name if @extension
+ validate_rust_builder_rubygems_version if @extension == "rust"
+ travis_removal_info
end
def run
@@ -38,6 +42,7 @@ module Bundler
namespaced_path = name.tr("-", "/")
constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase }
constant_array = constant_name.split("::")
+ minitest_constant_name = constant_array.clone.tap {|a| a[-1] = "Test#{a[-1]}" }.join("::") # Foo::Bar => Foo::TestBar
use_git = Bundler.git_present? && options[:git]
@@ -54,21 +59,23 @@ module Bundler
end
config = {
- :name => name,
+ :name => name,
:underscored_name => underscored_name,
- :namespaced_path => namespaced_path,
- :makefile_path => "#{underscored_name}/#{underscored_name}",
- :constant_name => constant_name,
- :constant_array => constant_array,
- :author => git_author_name.empty? ? "TODO: Write your name" : git_author_name,
- :email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
- :test => options[:test],
- :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 => Gem.ruby_version < Gem::Version.new("2.4.a") ? "2.3.0" : "2.4.0",
+ :namespaced_path => namespaced_path,
+ :makefile_path => "#{underscored_name}/#{underscored_name}",
+ :constant_name => constant_name,
+ :constant_array => constant_array,
+ :author => git_author_name.empty? ? "TODO: Write your name" : git_author_name,
+ :email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email,
+ :test => options[:test],
+ :ext => extension,
+ :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,
+ :rust_builder_required_rubygems_version => rust_builder_required_rubygems_version,
+ :minitest_constant_name => minitest_constant_name,
}
ensure_safe_gem_name(name, constant_array)
@@ -76,6 +83,7 @@ module Bundler
"#{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",
@@ -103,9 +111,17 @@ module Bundler
)
config[:test_task] = :spec
when "minitest"
+ # Generate path for minitest target file (FileList["test/**/test_*.rb"])
+ # foo => test/test_foo.rb
+ # foo-bar => test/foo/test_bar.rb
+ # foo_bar => test/test_foo_bar.rb
+ paths = namespaced_path.rpartition("/")
+ paths[2] = "test_#{paths[2]}"
+ minitest_namespaced_path = paths.join("")
+
templates.merge!(
"test/minitest/test_helper.rb.tt" => "test/test_helper.rb",
- "test/minitest/test_newgem.rb.tt" => "test/test_#{namespaced_path}.rb"
+ "test/minitest/test_newgem.rb.tt" => "test/#{minitest_namespaced_path}.rb"
)
config[:test_task] = :test
when "test-unit"
@@ -121,8 +137,6 @@ module Bundler
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"
@@ -166,33 +180,43 @@ module Bundler
config[:linter] = ask_and_set_linter
case config[:linter]
when "rubocop"
- config[:linter_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.81.0" : "1.7"
+ config[:linter_version] = rubocop_version
Bundler.ui.info "RuboCop enabled in config"
templates.merge!("rubocop.yml.tt" => ".rubocop.yml")
when "standard"
- config[:linter_version] = Gem.ruby_version < Gem::Version.new("2.4.a") ? "0.2.5" : "1.0"
+ 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]
+ if extension == "c"
templates.merge!(
- "ext/newgem/extconf.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/extconf-c.rb.tt" => "ext/#{name}/extconf.rb",
"ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h",
"ext/newgem/newgem.c.tt" => "ext/#{name}/#{underscored_name}.c"
)
end
- if File.exist?(target) && !File.directory?(target)
+ if extension == "rust"
+ templates.merge!(
+ "Cargo.toml.tt" => "Cargo.toml",
+ "ext/newgem/Cargo.toml.tt" => "ext/#{name}/Cargo.toml",
+ "ext/newgem/extconf-rust.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/src/lib.rs.tt" => "ext/#{name}/src/lib.rs",
+ )
+ 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}"
- `git init #{target}`
+ require "shellwords"
+ `git init #{target.to_s.shellescape}`
config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp
end
@@ -258,7 +282,7 @@ module Bundler
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/
+ if /rspec|minitest|test-unit/.match?(result)
test_framework = result
else
test_framework = false
@@ -294,12 +318,11 @@ module Bundler
"* 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/
+ result = Bundler.ui.ask "Enter a CI service. github/gitlab/circle/(none):"
+ if /github|gitlab|circle/.match?(result)
ci_template = result
else
ci_template = false
@@ -330,7 +353,7 @@ module Bundler
Bundler.ui.info hint_text("linter")
result = Bundler.ui.ask "Enter a linter. rubocop/standard/(none):"
- if result =~ /rubocop|standard/
+ if /rubocop|standard/.match?(result)
linter_template = result
else
linter_template = false
@@ -377,7 +400,7 @@ module Bundler
end
def ensure_safe_gem_name(name, constant_array)
- if name =~ /^\d/
+ if /^\d/.match?(name)
Bundler.ui.error "Invalid gem name #{name} Please give a name which does not start with numbers."
exit 1
end
@@ -402,5 +425,41 @@ module Bundler
def open_editor(editor, file)
thor.run(%(#{editor} "#{file}"))
end
+
+ def rust_builder_required_rubygems_version
+ "3.3.11"
+ end
+
+ def required_ruby_version
+ "2.6.0"
+ end
+
+ def rubocop_version
+ "1.21"
+ end
+
+ def standard_version
+ "1.3"
+ end
+
+ # TODO: remove at next minor release
+ def travis_removal_info
+ if options[:ci] == "travis"
+ Bundler.ui.error "Support for Travis CI was removed from gem skeleton generator."
+ exit 1
+ end
+
+ if Bundler.settings["gem.ci"] == "travis"
+ Bundler.ui.error "Support for Travis CI was removed from gem skeleton generator, but it is present in bundle config. Please configure another provider using `bundle config set gem.ci SERVICE` (where SERVICE is one of github/gitlab/circle) or unset configuration using `bundle config unset gem.ci`."
+ exit 1
+ end
+ end
+
+ def validate_rust_builder_rubygems_version
+ if Gem::Version.new(rust_builder_required_rubygems_version) > Gem.rubygems_version
+ Bundler.ui.error "Your RubyGems version (#{Gem.rubygems_version}) is too old to build Rust extension. Please update your RubyGems using `gem update --system` or any other way and try again."
+ exit 1
+ end
+ end
end
end
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 3111b64a33..36c7a58f12 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -18,6 +18,7 @@ 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
@@ -32,20 +33,25 @@ module Bundler
def default_gem_spec(gem_name)
return unless Gem::Specification.respond_to?(:find_all_by_name)
gem_spec = Gem::Specification.find_all_by_name(gem_name).last
- return gem_spec if gem_spec && gem_spec.respond_to?(:default_gem?) && gem_spec.default_gem?
+ return gem_spec if gem_spec&.default_gem?
end
def spec_not_found(gem_name)
raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies)
end
+ def print_gem_version(spec)
+ Bundler.ui.info spec.version.to_s
+ end
+
def print_gem_path(spec)
- if spec.name == "bundler"
- path = File.expand_path("../../../..", __FILE__)
+ name = spec.name
+ if name == "bundler"
+ path = File.expand_path("../../..", __dir__)
else
path = spec.full_gem_path
- unless File.directory?(path)
- return Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at: #{path}"
+ if spec.deleted_gem?
+ return Bundler.ui.warn "The gem #{name} has been deleted. It was installed at: #{path}"
end
end
@@ -54,8 +60,9 @@ module Bundler
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")
@@ -66,8 +73,22 @@ module Bundler
gem_info << "\tBug Tracker: #{metadata["bug_tracker_uri"]}\n" if metadata.key?("bug_tracker_uri")
gem_info << "\tMailing List: #{metadata["mailing_list_uri"]}\n" if metadata.key?("mailing_list_uri")
gem_info << "\tPath: #{spec.full_gem_path}\n"
- gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem?
+ gem_info << "\tDefault Gem: yes\n" if spec.respond_to?(:default_gem?) && spec.default_gem?
+ gem_info << "\tReverse Dependencies: \n\t\t#{gem_dependencies.join("\n\t\t")}" if gem_dependencies.any?
+
+ if name != "bundler" && spec.deleted_gem?
+ return Bundler.ui.warn "The gem #{name} has been deleted. Gemspec information is still available though:\n#{gem_info}"
+ end
+
Bundler.ui.info gem_info
end
+
+ def gem_dependencies
+ @gem_dependencies ||= Bundler.definition.specs.map do |spec|
+ dependency = spec.dependencies.find {|dep| dep.name == gem_name }
+ next unless dependency
+ "#{spec.name} (#{spec.version}) depends on #{gem_name} (#{dependency.requirements_list.join(", ")})"
+ end.compact.sort
+ end
end
end
diff --git a/lib/bundler/cli/init.rb b/lib/bundler/cli/init.rb
index d851d02d42..246b9d6460 100644
--- a/lib/bundler/cli/init.rb
+++ b/lib/bundler/cli/init.rb
@@ -32,7 +32,11 @@ module Bundler
file << spec.to_gemfile
end
else
- FileUtils.cp(File.expand_path("../../templates/#{gemfile}", __FILE__), gemfile)
+ File.open(File.expand_path("../templates/Gemfile", __dir__), "r") do |template|
+ File.open(gemfile, "wb") do |destination|
+ IO.copy_stream(template, destination)
+ end
+ end
end
puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}"
@@ -41,7 +45,7 @@ module Bundler
private
def gemfile
- @gemfile ||= Bundler.preferred_gemfile_name
+ @gemfile ||= options[:gemfile] || Bundler.preferred_gemfile_name
end
end
end
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index e4f59e4437..c71bcf159f 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -12,6 +12,8 @@ module Bundler
warn_if_root
+ Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
+
Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD
# Disable color in deployment mode
@@ -60,7 +62,7 @@ module Bundler
installer = Installer.install(Bundler.root, definition, options)
Bundler.settings.temporary(:cache_all_platforms => options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
- Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
+ 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)}."
@@ -83,24 +85,17 @@ module Bundler
end
Bundler::CLI::Common.output_fund_metadata_summary
- rescue GemNotFound => 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
-
- raise e
- rescue Gem::InvalidSpecificationException => e
+ rescue Gem::InvalidSpecificationException
Bundler.ui.warn "You have one or more invalid gemspecs that need to be fixed."
- raise e
+ raise
end
private
def warn_if_root
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
+ Bundler.ui.warn "Don't run Bundler as root. Installing your bundle as root " \
+ "will break this application for all non-root users on this machine.", :wrap => true
end
def dependencies_count_for(definition)
@@ -139,46 +134,27 @@ module Bundler
end
def normalize_groups
- options[:with] &&= options[:with].join(":").tr(" ", ":").split(":")
- options[:without] &&= options[:without].join(":").tr(" ", ":").split(":")
-
check_for_group_conflicts_in_cli_options
- Bundler.settings.set_command_option :with, nil if options[:with] == []
- Bundler.settings.set_command_option :without, nil if options[:without] == []
-
- with = options.fetch(:with, [])
- with |= Bundler.settings[:with].map(&:to_s)
- with -= options[:without] if options[:without]
-
- without = options.fetch(:without, [])
- without |= Bundler.settings[:without].map(&:to_s)
- without -= options[:with] if options[:with]
-
- options[:with] = with
- options[:without] = without
-
- 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
+ # need to nil them out first to get around validation for backwards compatibility
+ Bundler.settings.set_command_option :without, nil
+ Bundler.settings.set_command_option :with, nil
+ Bundler.settings.set_command_option :without, options[:without]
+ Bundler.settings.set_command_option :with, options[:with]
end
def normalize_settings
Bundler.settings.set_command_option :path, nil if options[:system]
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
- Bundler.settings.set_command_option :path, "vendor/bundle" if Bundler.settings[:deployment] && Bundler.settings[:path].nil?
- end
Bundler.settings.set_command_option_if_given :path, options[:path]
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
- Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil?
+
+ if options["standalone"] && Bundler.settings[:path].nil? && !options["local"]
+ Bundler.settings.temporary(:path_relative_to_cwd => false) do
+ Bundler.settings.set_command_option :path, "bundle"
+ end
end
bin_option = options["binstubs"]
- bin_option = nil if bin_option && bin_option.empty?
+ bin_option = nil if bin_option&.empty?
Bundler.settings.set_command_option :bin, bin_option if options["binstubs"]
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
@@ -191,7 +167,7 @@ module Bundler
Bundler.settings.set_command_option_if_given :clean, options["clean"]
- normalize_groups
+ normalize_groups if options[:without] || options[:with]
options[:force] = options[:redownload]
end
diff --git a/lib/bundler/cli/issue.rb b/lib/bundler/cli/issue.rb
index f4cd5ac4df..b891ecb1d2 100644
--- a/lib/bundler/cli/issue.rb
+++ b/lib/bundler/cli/issue.rb
@@ -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/rubygems/rubygems/blob/master/bundler/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 66abd32650..f56bf5b86a 100644
--- a/lib/bundler/cli/list.rb
+++ b/lib/bundler/cli/list.rb
@@ -16,7 +16,13 @@ module Bundler
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?
diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb
index 7d613a6644..cb3ed27138 100644
--- a/lib/bundler/cli/lock.rb
+++ b/lib/bundler/cli/lock.rb
@@ -15,19 +15,22 @@ module Bundler
end
print = options[:print]
- ui = Bundler.ui
- Bundler.ui = UI::Silent.new if print
+ previous_ui_level = Bundler.ui.level
+ Bundler.ui.level = "silent" if print
Bundler::Fetcher.disable_endpoint = options["full-index"]
update = options[:update]
conservative = options[:conservative]
+ bundler = options[:bundler]
if update.is_a?(Array) # unlocking specific gems
Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update)
update = { :gems => update, :conservative => conservative }
- elsif update
- update = { :conservative => conservative } if conservative
+ elsif update && conservative
+ update = { :conservative => conservative }
+ elsif update && bundler
+ update = { :bundler => bundler }
end
definition = Bundler.definition(update)
@@ -61,7 +64,7 @@ module Bundler
definition.lock(file)
end
- Bundler.ui = ui
+ Bundler.ui.level = previous_ui_level
end
end
end
diff --git a/lib/bundler/cli/open.rb b/lib/bundler/cli/open.rb
index ea504344f3..8522ec92d6 100644
--- a/lib/bundler/cli/open.rb
+++ b/lib/bundler/cli/open.rb
@@ -2,23 +2,25 @@
module Bundler
class CLI::Open
- attr_reader :options, :name
+ attr_reader :options, :name, :path
def initialize(options, name)
@options = options
@name = name
+ @path = options[:path] unless options[:path].nil?
end
def run
+ raise InvalidOption, "Cannot specify `--path` option without a value" if !@path.nil? && @path.empty?
editor = [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }
return Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR") unless editor
return unless spec = Bundler::CLI::Common.select_spec(name, :regex_match)
if spec.default_gem?
Bundler.ui.info "Unable to open #{name} because it's a default gem, so the directory it would normally be installed to does not exist."
else
- path = spec.full_gem_path
- Dir.chdir(path) do
+ root_path = spec.full_gem_path
+ Dir.chdir(root_path) do
require "shellwords"
- command = Shellwords.split(editor) + [path]
+ command = Shellwords.split(editor) << File.join([root_path, path].compact)
Bundler.with_original_env do
system(*command)
end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index d5183b060b..68c701aefb 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -46,7 +46,7 @@ module Bundler
Bundler::CLI::Common.configure_gem_version_promoter(
Bundler.definition,
- options
+ options.merge(:strict => @strict)
)
definition_resolution = proc do
@@ -111,9 +111,7 @@ module Bundler
end.compact
if options[:parseable]
- relevant_outdated_gems.each do |gems|
- print_gems(gems)
- end
+ print_gems(relevant_outdated_gems)
else
print_gems_table(relevant_outdated_gems)
end
@@ -129,6 +127,12 @@ module Bundler
private
+ def loaded_from_for(spec)
+ return unless spec.respond_to?(:loaded_from)
+
+ spec.loaded_from
+ end
+
def groups_text(group_text, groups)
"#{group_text}#{groups.split(",").size > 1 ? "s" : ""} \"#{groups}\""
end
@@ -184,10 +188,13 @@ module Bundler
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
+ if Bundler.ui.debug?
+ loaded_from = loaded_from_for(active_spec)
+ spec_version += " (from #{loaded_from})" if loaded_from
+ end
current_version = "#{current_spec.version}#{current_spec.git_version}"
- if dependency && dependency.specific?
+ if dependency&.specific?
dependency_version = %(, requested #{dependency.requirement})
end
@@ -211,7 +218,7 @@ module Bundler
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 << loaded_from_for(active_spec).to_s if Bundler.ui.debug?
ret_val
end
diff --git a/lib/bundler/cli/platform.rb b/lib/bundler/cli/platform.rb
index e97cad49a4..32d68abbb1 100644
--- a/lib/bundler/cli/platform.rb
+++ b/lib/bundler/cli/platform.rb
@@ -8,12 +8,12 @@ module Bundler
end
def run
- platforms, ruby_version = Bundler.ui.silence do
- locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version
- gemfile_ruby_version = Bundler.definition.ruby_version && Bundler.definition.ruby_version.single_version_string
- [Bundler.definition.platforms.map {|p| "* #{p}" },
- locked_ruby_version || gemfile_ruby_version]
+ ruby_version = if Bundler.locked_gems
+ Bundler.locked_gems.ruby_version&.gsub(/p\d+\Z/, "")
+ else
+ Bundler.definition.ruby_version&.single_version_string
end
+
output = []
if options[:ruby]
@@ -23,7 +23,9 @@ module Bundler
output << "No ruby version specified"
end
else
- output << "Your platform is: #{RUBY_PLATFORM}"
+ platforms = Bundler.definition.platforms.map {|p| "* #{p}" }
+
+ output << "Your platform is: #{Gem::Platform.local}"
output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}"
if ruby_version
diff --git a/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 5eaaba1ef7..2df13db1fa 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -18,7 +18,7 @@ module Bundler
if gem_name
if gem_name == "bundler"
- path = File.expand_path("../../../..", __FILE__)
+ path = File.expand_path("../../..", __dir__)
else
spec = Bundler::CLI::Common.select_spec(gem_name, :regex_match)
return unless spec
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index 1adcaef67c..b49182655b 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -11,12 +11,16 @@ module Bundler
def run
Bundler.ui.level = "warn" if options[:quiet]
+ update_bundler = options[:bundler]
+
+ Bundler.self_manager.update_bundler_and_restart_with_it_if_needed(update_bundler) if update_bundler
+
Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
sources = Array(options[:source])
groups = Array(options[:group]).map(&:to_sym)
- full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !options[:bundler]
+ full_update = gems.empty? && sources.empty? && groups.empty? && !options[:ruby] && !update_bundler
if full_update && !options[:all]
if Bundler.feature_flag.update_requires_all_flag?
@@ -49,7 +53,7 @@ module Bundler
Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
:conservative => conservative,
- :bundler => options[:bundler])
+ :bundler => update_bundler)
end
Bundler::CLI::Common.configure_gem_version_promoter(Bundler.definition, options)
@@ -66,7 +70,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
@@ -95,7 +99,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
diff --git a/lib/bundler/cli/viz.rb b/lib/bundler/cli/viz.rb
index 644f9b25cf..5c09e00995 100644
--- a/lib/bundler/cli/viz.rb
+++ b/lib/bundler/cli/viz.rb
@@ -23,7 +23,7 @@ module Bundler
Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:"
Bundler.ui.warn "`gem install ruby-graphviz`"
rescue StandardError => e
- raise unless e.message =~ /GraphViz not installed or dot not in PATH/
+ raise unless e.message.to_s.include?("GraphViz not installed or dot not in PATH")
Bundler.ui.error e.message
Bundler.ui.warn "Please install GraphViz. On a Mac with Homebrew, you can run `brew install graphviz`."
end
diff --git a/lib/bundler/compact_index_client.rb b/lib/bundler/compact_index_client.rb
index d5dbeb3b10..127a50e810 100644
--- a/lib/bundler/compact_index_client.rb
+++ b/lib/bundler/compact_index_client.rb
@@ -73,12 +73,6 @@ module Bundler
end.flatten(1)
end
- def spec(name, version, platform = nil)
- Bundler::CompactIndexClient.debug { "spec(name = #{name}, version = #{version}, platform = #{platform})" }
- update_info(name)
- @cache.specific_dependency(name, version, platform)
- end
-
def update_and_parse_checksums!
Bundler::CompactIndexClient.debug { "update_and_parse_checksums!" }
return @info_checksums_by_name if @parsed_checksums
diff --git a/lib/bundler/compact_index_client/cache.rb b/lib/bundler/compact_index_client/cache.rb
index c2cd069ec1..0b43581c11 100644
--- a/lib/bundler/compact_index_client/cache.rb
+++ b/lib/bundler/compact_index_client/cache.rb
@@ -68,7 +68,7 @@ module Bundler
def info_path(name)
name = name.to_s
- if name =~ /[^a-z0-9_-]/
+ if /[^a-z0-9_-]/.match?(name)
name += "-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}"
info_roots.last.join(name)
else
@@ -76,15 +76,6 @@ module Bundler
end
end
- def specific_dependency(name, version, platform)
- pattern = [version, platform].compact.join("-")
- return nil if pattern.empty?
-
- gem_lines = info_path(name).read
- gem_line = gem_lines[/^#{Regexp.escape(pattern)}\b.*/, 0]
- gem_line ? parse_gem(gem_line) : nil
- end
-
private
def lines(path)
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 06486f98cb..0f7bf9bb50 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -20,69 +20,64 @@ module Bundler
def initialize(fetcher)
@fetcher = fetcher
- require_relative "../vendored_tmpdir"
end
def update(local_path, remote_path, retrying = nil)
headers = {}
- Bundler::Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir|
- local_temp_path = Pathname.new(local_temp_dir).join(local_path.basename)
+ local_temp_path = local_path.sub(/$/, ".#{$$}")
+ local_temp_path = local_temp_path.sub(/$/, ".retrying") if retrying
+ local_temp_path = local_temp_path.sub(/$/, ".tmp")
- # first try to fetch any new bytes on the existing file
- if retrying.nil? && local_path.file?
- SharedHelpers.filesystem_access(local_temp_path) do
- FileUtils.cp local_path, local_temp_path
- end
- headers["If-None-Match"] = etag_for(local_temp_path)
- headers["Range"] =
- if local_temp_path.size.nonzero?
- # Subtract a byte to ensure the range won't be empty.
- # Avoids 416 (Range Not Satisfiable) responses.
- "bytes=#{local_temp_path.size - 1}-"
- else
- "bytes=#{local_temp_path.size}-"
- end
- end
+ # first try to fetch any new bytes on the existing file
+ if retrying.nil? && local_path.file?
+ copy_file local_path, local_temp_path
- response = @fetcher.call(remote_path, headers)
- return nil if response.is_a?(Net::HTTPNotModified)
+ headers["If-None-Match"] = etag_for(local_temp_path)
+ headers["Range"] =
+ if local_temp_path.size.nonzero?
+ # Subtract a byte to ensure the range won't be empty.
+ # Avoids 416 (Range Not Satisfiable) responses.
+ "bytes=#{local_temp_path.size - 1}-"
+ else
+ "bytes=#{local_temp_path.size}-"
+ end
+ end
- content = response.body
+ response = @fetcher.call(remote_path, headers)
+ return nil if response.is_a?(Net::HTTPNotModified)
- 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) }
+ content = response.body
- etag_for(local_temp_path) == etag
- else
- local_temp_path.open("wb") {|f| f << content }
+ 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.length.zero? || etag_for(local_temp_path) == etag
- end
- end
+ etag_for(local_temp_path) == etag
+ else
+ local_temp_path.open("wb") {|f| f << content }
- if correct_response
- SharedHelpers.filesystem_access(local_path) do
- FileUtils.mv(local_temp_path, local_path)
- end
- return nil
+ etag.length.zero? || etag_for(local_temp_path) == etag
end
+ end
- if retrying
- raise MisMatchedChecksumError.new(remote_path, etag, etag_for(local_temp_path))
+ if correct_response
+ SharedHelpers.filesystem_access(local_path) do
+ FileUtils.mv(local_temp_path, local_path)
end
+ return nil
+ end
- update(local_path, remote_path, :retrying)
+ if retrying
+ raise MisMatchedChecksumError.new(remote_path, etag, etag_for(local_temp_path))
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. "
+
+ update(local_path, remote_path, :retrying)
rescue Zlib::GzipFile::Error
raise Bundler::HTTPError
+ ensure
+ FileUtils.remove_file(local_temp_path) if File.exist?(local_temp_path)
end
def etag_for(path)
@@ -103,6 +98,20 @@ module Bundler
SharedHelpers.digest(:MD5).hexdigest(File.read(path))
end
end
+
+ private
+
+ def copy_file(source, dest)
+ SharedHelpers.filesystem_access(source, :read) do
+ File.open(source, "r") do |s|
+ SharedHelpers.filesystem_access(dest, :write) do
+ File.open(dest, "wb", s.stat.mode) do |f|
+ IO.copy_stream(s, f)
+ end
+ end
+ end
+ end
+ end
end
end
end
diff --git a/lib/bundler/constants.rb b/lib/bundler/constants.rb
index 2e4ebb37ee..8dd8a53815 100644
--- a/lib/bundler/constants.rb
+++ b/lib/bundler/constants.rb
@@ -2,6 +2,6 @@
module Bundler
WINDOWS = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw)/
- FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/
+ FREEBSD = RbConfig::CONFIG["host_os"].to_s.include?("bsd")
NULL = WINDOWS ? "NUL" : "/dev/null"
end
diff --git a/lib/bundler/current_ruby.rb b/lib/bundler/current_ruby.rb
index f84d68e262..f009b07ad7 100644
--- a/lib/bundler/current_ruby.rb
+++ b/lib/bundler/current_ruby.rb
@@ -21,6 +21,9 @@ module Bundler
2.6
2.7
3.0
+ 3.1
+ 3.2
+ 3.3
].freeze
KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
@@ -35,17 +38,18 @@ module Bundler
rbx
ruby
truffleruby
+ windows
x64_mingw
].freeze
def ruby?
return true if Bundler::GemHelpers.generic_local_platform == Gem::Platform::RUBY
- !mswin? && (RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev" || RUBY_ENGINE == "truffleruby")
+ !windows? && (RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev" || RUBY_ENGINE == "truffleruby")
end
def mri?
- !mswin? && RUBY_ENGINE == "ruby"
+ !windows? && RUBY_ENGINE == "ruby"
end
def rbx?
@@ -64,20 +68,28 @@ module Bundler
RUBY_ENGINE == "truffleruby"
end
- def mswin?
+ def windows?
Gem.win_platform?
end
+ def mswin?
+ # For backwards compatibility
+ windows?
+
+ # TODO: This should correctly be:
+ # windows? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin32" && Bundler.local_platform.cpu == "x86"
+ end
+
def mswin64?
- Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
+ windows? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
end
def mingw?
- Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
+ windows? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
end
def x64_mingw?
- Gem.win_platform? && 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.start_with?("mingw") && 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 81cd94eb5f..564530a98c 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -16,7 +16,6 @@ module Bundler
:locked_deps,
:locked_gems,
:platforms,
- :requires,
:ruby_version,
:lockfile,
:gemfiles
@@ -70,16 +69,20 @@ module Bundler
@unlock = unlock
@optional_groups = optional_groups
@remote = false
+ @prefer_local = false
@specs = nil
@ruby_version = ruby_version
@gemfiles = gemfiles
@lockfile = lockfile
@lockfile_contents = String.new
+
@locked_bundler_version = nil
- @locked_ruby_version = nil
- @locked_specs_incomplete_for_platform = false
+ @resolved_bundler_version = nil
+
+ @locked_ruby_version = nil
@new_platform = nil
+ @removed_platform = nil
if lockfile && File.exist?(lockfile)
@lockfile_contents = Bundler.read_file(lockfile)
@@ -88,10 +91,11 @@ module Bundler
@platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version
+ @originally_locked_specs = SpecSet.new(@locked_gems.specs)
if unlock != true
@locked_deps = @locked_gems.dependencies
- @locked_specs = SpecSet.new(@locked_gems.specs)
+ @locked_specs = @originally_locked_specs
@locked_sources = @locked_gems.sources
else
@unlock = {}
@@ -105,6 +109,7 @@ module Bundler
@locked_gems = nil
@locked_deps = {}
@locked_specs = SpecSet.new([])
+ @originally_locked_specs = @locked_specs
@locked_sources = []
@locked_platforms = []
end
@@ -128,7 +133,7 @@ module Bundler
end
@unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
- add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?
+ add_current_platform unless Bundler.frozen_bundle?
converge_path_sources_to_gemspec_sources
@path_changes = converge_paths
@@ -137,33 +142,18 @@ module Bundler
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, false).map(&:name)
+ eager_unlock = (@unlock[:gems] || []).map {|name| Dependency.new(name, ">= 0") }
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
end
@dependency_changes = converge_dependencies
@local_changes = converge_locals
- @requires = compute_requires
+ @missing_lockfile_dep = check_missing_lockfile_dep
end
def gem_version_promoter
- @gem_version_promoter ||= begin
- locked_specs =
- if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
- # Definition uses an empty set of locked_specs to indicate all gems
- # are unlocked, but GemVersionPromoter needs the locked_specs
- # for conservative comparison.
- Bundler::SpecSet.new(@locked_gems.specs)
- else
- @locked_specs
- end
- GemVersionPromoter.new(locked_specs, @unlock[:gems])
- end
- end
-
- def multisource_allowed?
- @multisource_allowed
+ @gem_version_promoter ||= GemVersionPromoter.new
end
def resolve_only_locally!
@@ -183,6 +173,23 @@ module Bundler
resolve
end
+ def resolution_mode=(options)
+ if options["local"]
+ @remote = false
+ else
+ @remote = true
+ @prefer_local = options["prefer-local"]
+ end
+ end
+
+ def setup_sources_for_resolve
+ if @remote == false
+ sources.cached!
+ else
+ sources.remote!
+ end
+ end
+
# For given dependency list returns a SpecSet with Gemspec of all the required
# dependencies.
# 1. The method first resolves the dependencies specified in Gemfile
@@ -190,15 +197,7 @@ module Bundler
#
# @return [Bundler::SpecSet]
def specs
- @specs ||= add_bundler_to(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} 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."
+ @specs ||= materialize(requested_dependencies)
end
def new_specs
@@ -210,9 +209,7 @@ module Bundler
end
def missing_specs
- missing = []
- resolve.materialize(requested_dependencies, missing)
- missing
+ resolve.materialize(requested_dependencies).missing_specs
end
def missing_specs?
@@ -222,6 +219,8 @@ module Bundler
true
rescue BundlerError => e
@resolve = nil
+ @resolver = nil
+ @resolution_packages = nil
@specs = nil
@gem_version_promoter = nil
@@ -238,15 +237,35 @@ module Bundler
end
def current_dependencies
+ filter_relevant(dependencies)
+ end
+
+ def current_locked_dependencies
+ filter_relevant(locked_dependencies)
+ end
+
+ def filter_relevant(dependencies)
dependencies.select do |d|
- d.should_include? && !d.gem_platforms(@platforms).empty?
+ d.should_include? && !d.gem_platforms([generic_local_platform]).empty?
end
end
+ def locked_dependencies
+ @locked_deps.values
+ end
+
+ def new_deps
+ @new_deps ||= @dependencies - locked_dependencies
+ end
+
+ def deleted_deps
+ @deleted_deps ||= locked_dependencies - @dependencies
+ end
+
def specs_for(groups)
- groups = requested_groups if groups.empty?
+ return specs if groups.empty?
deps = dependencies_for(groups)
- add_bundler_to(resolve.materialize(expand_dependencies(deps)))
+ materialize(deps)
end
def dependencies_for(groups)
@@ -262,20 +281,24 @@ module Bundler
#
# @return [SpecSet] resolved dependencies
def resolve
- @resolve ||= begin
- last_resolve = converge_locked_specs
- 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
+ @resolve ||= if Bundler.frozen_bundle?
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
+ @locked_specs
+ elsif no_resolve_needed?
+ if deleted_deps.any?
+ Bundler.ui.debug "Some dependencies were deleted, using a subset of the resolution from the lockfile"
+ SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
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)
+ Bundler.ui.debug "Found no changes, using resolution from the lockfile"
+ if @removed_platform || @locked_gems.may_include_redundant_platform_specific_gems?
+ SpecSet.new(filter_specs(@locked_specs, @dependencies))
+ else
+ @locked_specs
+ end
end
+ else
+ Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
+ start_resolution
end
end
@@ -294,16 +317,13 @@ module Bundler
# Convert to \r\n if the existing lock has them
# i.e., Windows with `git config core.autocrlf=true`
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n")
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
if @locked_bundler_version
locked_major = @locked_bundler_version.segments.first
- current_major = Gem::Version.create(Bundler::VERSION).segments.first
+ current_major = bundler_version_to_lock.segments.first
- if updating_major = locked_major < current_major
- Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
- "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
- end
+ updating_major = locked_major < current_major
end
preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
@@ -320,14 +340,6 @@ module Bundler
end
end
- def locked_bundler_version
- if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
- new_version = Bundler::VERSION
- end
-
- new_version || @locked_bundler_version || Bundler::VERSION
- end
-
def locked_ruby_version
return unless ruby_version
if @unlock[:ruby] || !@locked_ruby_version
@@ -349,27 +361,16 @@ module Bundler
end
end
+ def bundler_version_to_lock
+ @resolved_bundler_version || Bundler.gem_version
+ end
+
def to_lock
require_relative "lockfile_generator"
LockfileGenerator.generate(self)
end
def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
- msg = String.new
- msg << "You are trying to install in deployment mode after changing\n" \
- "your Gemfile. Run `bundle install` elsewhere and add the\n" \
- "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
-
- unless explicit_flag
- 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"
- end
- msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
- "freeze \nby running `#{suggested_command}`."
- end
-
added = []
deleted = []
changed = []
@@ -379,52 +380,40 @@ 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
-
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 }
+ current_dependencies.each {|d| both_sources[d.name][0] = d }
+ current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
+
+ both_sources.each do |name, (dep, lock_dep)|
+ next if dep.nil? || lock_dep.nil?
- both_sources.each do |name, (dep, lock_source)|
- next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
- gemfile_source_name = (dep && dep.source) || "no specified source"
- lockfile_source_name = lock_source
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
+ gemfile_source = dep.source || default_source
+ lock_source = lock_dep.source || default_source
+ next if lock_source.include?(gemfile_source)
+
+ gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
+ lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
end
reason = change_reason
- msg << "\n\n#{reason.split(", ").map(&:capitalize).join("\n")}" unless reason.strip.empty?
+ msg = String.new
+ msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
- msg << "\n"
+ msg << "\n\nRun `bundle install` elsewhere and add the updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control.\n"
+
+ unless explicit_flag
+ suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env)
+ "bundle config set frozen false"
+ end
+ msg << "If this is a development machine, remove the #{Bundler.default_gemfile.relative_path_from(SharedHelpers.pwd)} " \
+ "freeze by running `#{suggested_command}`." if suggested_command
+ end
raise ProductionError, msg if added.any? || deleted.any? || changed.any? || !nothing_changed?
end
@@ -464,7 +453,7 @@ module Bundler
raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
"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."
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{Bundler.local_platform}` and try again."
end
def add_platform(platform)
@@ -473,7 +462,9 @@ module Bundler
end
def remove_platform(platform)
- return if @platforms.delete(Gem::Platform.new(platform))
+ removed_platform = @platforms.delete(Gem::Platform.new(platform))
+ @removed_platform ||= removed_platform
+ return if removed_platform
raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
end
@@ -487,7 +478,11 @@ module Bundler
private :sources
def nothing_changed?
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
+ !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@missing_lockfile_dep && !@unlocking_bundler
+ end
+
+ def no_resolve_needed?
+ !unlocking? && nothing_changed?
end
def unlocking?
@@ -496,21 +491,109 @@ module Bundler
private
- def add_bundler_to(specs)
- unless specs["bundler"].any?
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
- specs["bundler"] = bundler
+ def resolver
+ @resolver ||= Resolver.new(resolution_packages, gem_version_promoter)
+ end
+
+ def expanded_dependencies
+ dependencies_with_bundler + metadata_dependencies
+ end
+
+ def dependencies_with_bundler
+ return dependencies unless @unlocking_bundler
+ return dependencies if dependencies.map(&:name).include?("bundler")
+
+ [Dependency.new("bundler", @unlocking_bundler)] + dependencies
+ end
+
+ def resolution_packages
+ @resolution_packages ||= begin
+ last_resolve = converge_locked_specs
+ remove_ruby_from_platforms_if_necessary!(current_dependencies)
+ packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, :locked_specs => @originally_locked_specs, :unlock => @unlock[:gems], :prerelease => gem_version_promoter.pre?)
+ additional_base_requirements_for_resolve(packages, last_resolve)
+ end
+ end
+
+ def filter_specs(specs, deps)
+ SpecSet.new(specs).for(deps, false, platforms)
+ end
+
+ 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
+
+ missing_specs_list = missing_specs.group_by(&:source).map do |source, missing_specs_for_source|
+ "#{missing_specs_for_source.map(&:full_name).join(", ")} in #{source}"
+ end
+
+ raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
end
+ incomplete_specs = specs.incomplete_specs
+ loop do
+ break if incomplete_specs.empty?
+
+ Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
+ setup_sources_for_resolve
+ resolution_packages.delete(incomplete_specs)
+ @resolve = start_resolution
+ specs = resolve.materialize(dependencies)
+
+ still_incomplete_specs = specs.incomplete_specs
+
+ if still_incomplete_specs == incomplete_specs
+ package = resolution_packages.get_package(incomplete_specs.first.name)
+ resolver.raise_not_found! package
+ end
+
+ incomplete_specs = still_incomplete_specs
+ end
+
+ bundler = sources.metadata_source.specs.search(["bundler", Bundler.gem_version]).last
+ specs["bundler"] = bundler
+
specs
end
+ def start_resolution
+ result = resolver.start
+
+ @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
+
+ SpecSet.new(SpecSet.new(result).for(dependencies, false, @platforms))
+ end
+
def precompute_source_requirements_for_indirect_dependencies?
sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
+ def pin_locally_available_names(source_requirements)
+ source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
+ local_source = original_source.dup
+ local_source.local_only!
+
+ new_source_requirements[name] = if local_source.specs.search(name).any?
+ local_source
+ else
+ original_source
+ end
+ end
+ end
+
def current_ruby_platform_locked?
return false unless generic_local_platform == Gem::Platform::RUBY
+ return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
current_platform_locked?
end
@@ -522,6 +605,8 @@ module Bundler
end
def add_current_platform
+ return if current_ruby_platform_locked?
+
add_platform(local_platform)
end
@@ -543,12 +628,13 @@ module Bundler
[@new_platform, "you added a new platform to your gemfile"],
[@path_changes, "the gemspecs for path gems changed"],
[@local_changes, "the gemspecs for git local gems changed"],
- [@locked_specs_incomplete_for_platform, "the lockfile does not have all gems needed for the current platform"],
+ [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
+ [@unlocking_bundler, "an update to the version of Bundler itself was requested"],
].select(&:first).map(&:last).join(", ")
end
- def pretty_dep(dep, source = false)
- SharedHelpers.pretty_dependency(dep, source)
+ def pretty_dep(dep)
+ SharedHelpers.pretty_dependency(dep)
end
# Check if the specs of the given source changed
@@ -561,7 +647,7 @@ 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 }
deps_for_source.uniq.sort != locked_deps_for_source.sort
end
@@ -585,8 +671,8 @@ module Bundler
Bundler.settings.local_overrides.map do |k, v|
spec = @dependencies.find {|s| s.name == k }
- source = spec && spec.source
- if source && source.respond_to?(:local_override!)
+ source = spec&.source
+ if source&.respond_to?(:local_override!)
source.unlock! if @unlock[:gems].include?(spec.name)
locals << [source, source.local_override!(v)]
end
@@ -598,6 +684,26 @@ module Bundler
!sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
end
+ def check_missing_lockfile_dep
+ all_locked_specs = @locked_specs.map(&:name) << "bundler"
+
+ missing = @locked_specs.select do |s|
+ s.dependencies.any? {|dep| !all_locked_specs.include?(dep.name) }
+ end
+
+ if missing.any?
+ @locked_specs.delete(missing)
+
+ return missing.first.name
+ end
+
+ return if @dependency_changes
+
+ current_dependencies.find do |d|
+ @locked_specs[d.name].empty? && d.name != "bundler"
+ end&.name
+ end
+
def converge_paths
sources.path_sources.any? do |source|
specs_changed?(source)
@@ -644,25 +750,16 @@ 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
- 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]
+ next if unlocking?
+
+ unless locked_dep = @locked_deps[dep.name]
changes = true
next
end
@@ -673,11 +770,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
@@ -687,140 +784,91 @@ module Bundler
# commonly happen if the Gemfile has changed since the lockfile was last
# generated
def converge_locked_specs
- deps = []
+ converged = converge_specs(@locked_specs)
- # 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 = SpecSet.new(converged.reject {|s| @unlock[:gems].include?(s.name) })
- # 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
+ resolve
+ end
+
+ def converge_specs(specs)
converged = []
- @locked_specs.each do |s|
- # Replace the locked dependency's source with the equivalent source from the Gemfile
+ deps = []
+
+ @specs_that_changed_sources = []
+
+ specs.each do |s|
+ name = s.name
dep = @dependencies.find {|d| s.satisfies?(d) }
- s.source = (dep && dep.source) || sources.get(s.source)
+ lockfile_source = 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
+ gemfile_source = dep.source || default_source
+
+ @specs_that_changed_sources << s if gemfile_source != lockfile_source
+ deps << dep if !dep.source || lockfile_source.include?(dep.source)
+ @unlock[:gems] << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
- # If the spec is from a path source and it doesn't exist anymore
- # then we unlock it.
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
+ s.source = gemfile_source
+ else
+ # Replace the locked dependency's source with the default source, if the locked source is no longer in the Gemfile
+ s.source = default_source unless sources.get(lockfile_source)
+ end
+
+ next if @unlock[:sources].include?(s.source.name)
# Path sources have special logic
if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
new_specs = begin
s.source.specs
- rescue PathError, GitError
+ rescue PathError
# 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).
+ # don't error if the path source isn't available
+ next if specs.
+ for(requested_dependencies, false).
none? {|locked_spec| locked_spec.source == s.source }
raise
end
new_spec = new_specs[s].first
-
- # If the spec is no longer in the path source, unlock it. This
- # commonly happens if the version changed in the gemspec
- next unless new_spec
-
- s.dependencies.replace(new_spec.dependencies)
+ if new_spec
+ s.dependencies.replace(new_spec.dependencies)
+ else
+ # If the spec is no longer in the path source, unlock it. This
+ # commonly happens if the version changed in the gemspec
+ @unlock[:gems] << name
+ end
end
- converged << s
- end
-
- resolve = SpecSet.new(converged)
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), true, true)
- resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false, false).reject{|s| @unlock[:gems].include?(s.name) })
- 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| 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)) }
+ filter_specs(converged, deps)
end
def metadata_dependencies
- @metadata_dependencies ||= begin
- ruby_versions = ruby_version_requirements(@ruby_version)
- [
- Dependency.new("Ruby\0", ruby_versions),
- Dependency.new("RubyGems\0", Gem::VERSION),
- ]
- end
- end
-
- def ruby_version_requirements(ruby_version)
- return [] unless ruby_version
- if ruby_version.patchlevel
- [ruby_version.to_gem_version_with_patchlevel]
- else
- ruby_version.versions.map do |version|
- requirement = Gem::Requirement.new(version)
- if requirement.exact?
- "~> #{version}.0"
- else
- requirement
- end
- end
- end
- end
-
- def expand_dependencies(dependencies, remote = false)
- deps = []
- dependencies.each do |dep|
- dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
- 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 expand_dependency_with_platforms(dep, platforms)
- platforms.map do |p|
- DepProxy.get_proxy(dep, p)
- end
+ @metadata_dependencies ||= [
+ Dependency.new("Ruby\0", Gem.ruby_version),
+ Dependency.new("RubyGems\0", Gem::VERSION),
+ ]
end
def source_requirements
@@ -828,27 +876,54 @@ module Bundler
# specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies)
source_requirements = if precompute_source_requirements_for_indirect_dependencies?
- { :default => sources.default_source }.merge(source_map.all_requirements)
+ all_requirements = source_map.all_requirements
+ all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
+ { :default => default_source }.merge(all_requirements)
else
{ :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
end
+ source_requirements.merge!(source_map.locked_requirements) unless @remote
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
+
+ default_bundler_source = source_requirements["bundler"] || default_source
+
+ if @unlocking_bundler
+ default_bundler_source.add_dependency_names("bundler")
+ else
+ source_requirements[:default_bundler] = default_bundler_source
+ source_requirements["bundler"] = sources.metadata_source # needs to come last to override
+ end
+
+ verify_changed_sources!
source_requirements
end
+ def default_source
+ sources.default_source
+ end
+
+ def verify_changed_sources!
+ @specs_that_changed_sources.each do |s|
+ if s.source.specs.search(s.name).empty?
+ raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
+ end
+ end
+ end
+
def requested_groups
- groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
+ values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
+ values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?
+ values
end
def lockfiles_equal?(current, proposed, preserve_unknown_sections)
if preserve_unknown_sections
sections_to_ignore = LockfileParser.sections_to_ignore(@locked_bundler_version)
sections_to_ignore += LockfileParser.unknown_sections_in_lockfile(current)
- sections_to_ignore += LockfileParser::ENVIRONMENT_VERSION_SECTIONS
+ sections_to_ignore << LockfileParser::RUBY
+ sections_to_ignore << LockfileParser::BUNDLED unless @unlocking_bundler
pattern = /#{Regexp.union(sections_to_ignore)}\n(\s{2,}.*\n)+/
whitespace_cleanup = /\n{2,}/
current = current.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
@@ -857,45 +932,30 @@ 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?
- requires[dep.name] = Array(dep.autorequire || dep.name).map do |file|
- # Allow `require: true` as an alias for `require: <name>`
- file == true ? dep.name : file
- end
- requires
+ def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
+ return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
+ converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
+ next if locked_spec.source.is_a?(Source::Path)
+ resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
end
+ resolution_packages
end
- def additional_base_requirements_for_resolve
- return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
- dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
- @locked_gems.specs.reduce({}) do |requirements, 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.get_proxy(dep, locked_spec.platform)
- requirements
- end.values
- end
-
- def equivalent_rubygems_remotes?(source)
- return false unless source.is_a?(Source::Rubygems)
+ def remove_ruby_from_platforms_if_necessary!(dependencies)
+ return if Bundler.frozen_bundle? ||
+ Bundler.local_platform == Gem::Platform::RUBY ||
+ !platforms.include?(Gem::Platform::RUBY) ||
+ (@new_platform && platforms.last == Gem::Platform::RUBY) ||
+ @path_changes ||
+ @dependency_changes ||
+ !@originally_locked_specs.incomplete_ruby_specs?(dependencies)
- Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
+ remove_platform(Gem::Platform::RUBY)
+ add_current_platform
end
def source_map
- @source_map ||= SourceMap.new(sources, dependencies)
+ @source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
end
end
end
diff --git a/lib/bundler/dep_proxy.rb b/lib/bundler/dep_proxy.rb
deleted file mode 100644
index a32dc37b49..0000000000
--- a/lib/bundler/dep_proxy.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-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
-
- private_class_method :new
-
- alias_method :eql?, :==
-
- def type
- @dep.type
- end
-
- def name
- @dep.name
- end
-
- def requirement
- @dep.requirement
- end
-
- def to_s
- s = name.dup
- s << " (#{requirement})" unless requirement == Gem::Requirement.default
- s << " #{__platform}" unless __platform == Gem::Platform::RUBY
- s
- end
-
- 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)
- end
- end
-end
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 27206b1bac..5f17943629 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -7,72 +7,24 @@ require_relative "rubygems_ext"
module Bundler
class Dependency < Gem::Dependency
attr_reader :autorequire
- attr_reader :groups, :platforms, :gemfile, :git, :branch
+ attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref
+ ALL_RUBY_VERSIONS = ((18..27).to_a + (30..33).to_a).freeze
PLATFORM_MAP = {
- :ruby => Gem::Platform::RUBY,
- :ruby_18 => Gem::Platform::RUBY,
- :ruby_19 => Gem::Platform::RUBY,
- :ruby_20 => Gem::Platform::RUBY,
- :ruby_21 => Gem::Platform::RUBY,
- :ruby_22 => Gem::Platform::RUBY,
- :ruby_23 => Gem::Platform::RUBY,
- :ruby_24 => Gem::Platform::RUBY,
- :ruby_25 => Gem::Platform::RUBY,
- :ruby_26 => Gem::Platform::RUBY,
- :mri => Gem::Platform::RUBY,
- :mri_18 => Gem::Platform::RUBY,
- :mri_19 => Gem::Platform::RUBY,
- :mri_20 => Gem::Platform::RUBY,
- :mri_21 => Gem::Platform::RUBY,
- :mri_22 => Gem::Platform::RUBY,
- :mri_23 => Gem::Platform::RUBY,
- :mri_24 => Gem::Platform::RUBY,
- :mri_25 => Gem::Platform::RUBY,
- :mri_26 => Gem::Platform::RUBY,
- :rbx => Gem::Platform::RUBY,
- :truffleruby => Gem::Platform::RUBY,
- :jruby => Gem::Platform::JAVA,
- :jruby_18 => Gem::Platform::JAVA,
- :jruby_19 => Gem::Platform::JAVA,
- :mswin => Gem::Platform::MSWIN,
- :mswin_18 => Gem::Platform::MSWIN,
- :mswin_19 => Gem::Platform::MSWIN,
- :mswin_20 => Gem::Platform::MSWIN,
- :mswin_21 => Gem::Platform::MSWIN,
- :mswin_22 => Gem::Platform::MSWIN,
- :mswin_23 => Gem::Platform::MSWIN,
- :mswin_24 => Gem::Platform::MSWIN,
- :mswin_25 => Gem::Platform::MSWIN,
- :mswin_26 => Gem::Platform::MSWIN,
- :mswin64 => Gem::Platform::MSWIN64,
- :mswin64_19 => Gem::Platform::MSWIN64,
- :mswin64_20 => Gem::Platform::MSWIN64,
- :mswin64_21 => Gem::Platform::MSWIN64,
- :mswin64_22 => Gem::Platform::MSWIN64,
- :mswin64_23 => Gem::Platform::MSWIN64,
- :mswin64_24 => Gem::Platform::MSWIN64,
- :mswin64_25 => Gem::Platform::MSWIN64,
- :mswin64_26 => Gem::Platform::MSWIN64,
- :mingw => Gem::Platform::MINGW,
- :mingw_18 => Gem::Platform::MINGW,
- :mingw_19 => Gem::Platform::MINGW,
- :mingw_20 => Gem::Platform::MINGW,
- :mingw_21 => Gem::Platform::MINGW,
- :mingw_22 => Gem::Platform::MINGW,
- :mingw_23 => Gem::Platform::MINGW,
- :mingw_24 => Gem::Platform::MINGW,
- :mingw_25 => Gem::Platform::MINGW,
- :mingw_26 => Gem::Platform::MINGW,
- :x64_mingw => Gem::Platform::X64_MINGW,
- :x64_mingw_20 => Gem::Platform::X64_MINGW,
- :x64_mingw_21 => Gem::Platform::X64_MINGW,
- :x64_mingw_22 => Gem::Platform::X64_MINGW,
- :x64_mingw_23 => Gem::Platform::X64_MINGW,
- :x64_mingw_24 => Gem::Platform::X64_MINGW,
- :x64_mingw_25 => Gem::Platform::X64_MINGW,
- :x64_mingw_26 => Gem::Platform::X64_MINGW,
- }.freeze
+ :ruby => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
+ :mri => [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
+ :rbx => [Gem::Platform::RUBY],
+ :truffleruby => [Gem::Platform::RUBY],
+ :jruby => [Gem::Platform::JAVA, [18, 19]],
+ :windows => [Gem::Platform::WINDOWS, ALL_RUBY_VERSIONS],
+ :mswin => [Gem::Platform::MSWIN, ALL_RUBY_VERSIONS],
+ :mswin64 => [Gem::Platform::MSWIN64, ALL_RUBY_VERSIONS - [18]],
+ :mingw => [Gem::Platform::MINGW, ALL_RUBY_VERSIONS],
+ :x64_mingw => [Gem::Platform::X64_MINGW, ALL_RUBY_VERSIONS - [18, 19]],
+ }.each_with_object({}) do |(platform, spec), hash|
+ hash[platform] = spec[0]
+ spec[1]&.each {|version| hash[:"#{platform}_#{version}"] = spec[0] }
+ end.freeze
def initialize(name, version, options = {}, &blk)
type = options["type"] || :runtime
@@ -81,12 +33,16 @@ module Bundler
@autorequire = nil
@groups = Array(options["group"] || :default).map(&:to_sym)
@source = options["source"]
+ @path = options["path"]
@git = options["git"]
+ @github = options["github"]
@branch = options["branch"]
+ @ref = options["ref"]
@platforms = Array(options["platforms"])
@env = options["env"]
@should_include = options.fetch("should_include", true)
@gemfile = options["gemfile"]
+ @force_ruby_platform = options["force_ruby_platform"] if options.key?("force_ruby_platform")
@autorequire = Array(options["require"] || []) if options.key?("require")
end
@@ -94,13 +50,14 @@ module Bundler
# Returns the platforms this dependency is valid for, in the same order as
# passed in the `valid_platforms` parameter
def gem_platforms(valid_platforms)
+ return [Gem::Platform::RUBY] if force_ruby_platform
return valid_platforms if @platforms.empty?
valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
end
def expanded_platforms
- @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.uniq
+ @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.flatten.uniq
end
def should_include?
@@ -128,7 +85,7 @@ module Bundler
def to_lock
out = super
out << "!" if source
- out << "\n"
+ out
end
def specific?
diff --git a/lib/bundler/digest.rb b/lib/bundler/digest.rb
new file mode 100644
index 0000000000..f11f5edd38
--- /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 & 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 3517a109ed..03c80a408c 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -16,7 +16,9 @@ module Bundler
VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
- platform platforms type source install_if gemfile].freeze
+ platform platforms type source install_if gemfile force_ruby_platform].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
@@ -39,12 +41,12 @@ module Bundler
end
def eval_gemfile(gemfile, contents = nil)
- expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile && @gemfile.parent)
+ expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile&.parent)
original_gemfile = @gemfile
@gemfile = expanded_gemfile_path
@gemfiles << expanded_gemfile_path
contents ||= Bundler.read_file(@gemfile.to_s)
- instance_eval(contents.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
+ instance_eval(contents.dup.tap {|x| x.untaint if RUBY_VERSION < "2.7" }, gemfile.to_s, 1)
rescue Exception => e # rubocop:disable Lint/RescueException
message = "There was an error " \
"#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
@@ -65,7 +67,6 @@ module Bundler
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] }
case specs_by_name_and_version.size
@@ -122,19 +123,17 @@ 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}"
+ elsif 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 " \
+ "#{current.source || "an unspecified source"} and #{dep.source}\n"
else
Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
"You should probably keep only one of them.\n" \
"Remove any duplicate entries and specify the gem only once.\n" \
"While it's not a problem now, it could cause errors if you change the version of one of them later."
end
-
- 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 " \
- "#{current.source || "an unspecified source"} and #{dep.source}\n"
- end
end
end
@@ -275,26 +274,24 @@ module Bundler
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" => nil,
+ "ref" => "refs/pull/#{$2}/head",
+ "tag" => nil,
+ }
+ else
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
+ "https://github.com/#{repo_name}.git"
+ end
end
git_source(:gist) do |repo_name|
- warn_deprecated_git_source(:gist, '"https://gist.github.com/#{repo_name}.git"')
-
"https://gist.github.com/#{repo_name}.git"
end
git_source(:bitbucket) do |repo_name|
- warn_deprecated_git_source(:bitbucket, <<-'RUBY'.strip)
-user_name, repo_name = repo_name.split("/")
-repo_name ||= user_name
-"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
- RUBY
-
user_name, repo_name = repo_name.split("/")
repo_name ||= user_name
"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
@@ -327,7 +324,7 @@ repo_name ||= user_name
if name.is_a?(Symbol)
raise GemfileError, %(You need to specify gem names as Strings. Use 'gem "#{name}"' instead)
end
- if name =~ /\s/
+ if /\s/.match?(name)
raise GemfileError, %('#{name}' is not a valid gem name because it contains whitespace)
end
raise GemfileError, %(an empty gem name is not valid) if name.empty?
@@ -365,7 +362,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|
@@ -457,40 +458,24 @@ repo_name ||= user_name
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." \
+ "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. " \
+ msg = "This Gemfile contains multiple global sources. " \
"Each source after the first must include a block to indicate which gems " \
"should come from that source"
raise GemfileEvalError, msg
else
- Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
+ Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple global sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source."
end
end
- def warn_deprecated_git_source(name, replacement, additional_message = nil)
- additional_message &&= " #{additional_message}"
- replacement = if replacement.count("\n").zero?
- "{|repo_name| #{replacement} }"
- else
- "do |repo_name|\n#{replacement.to_s.gsub(/^/, " ")}\n end"
- end
-
- Bundler::SharedHelpers.major_deprecation 3, <<-EOS
-The :#{name} git source is deprecated, and will be removed in the future.#{additional_message} Add this code to the top of your Gemfile to ensure it continues to work:
-
- git_source(:#{name}) #{replacement}
-
- EOS
- end
-
class DSLError < GemfileError
# @return [String] the description that should be presented to the user.
#
@@ -525,9 +510,7 @@ The :#{name} git source is deprecated, and will be removed in the future.#{addit
# be raised.
#
def contents
- @contents ||= begin
- dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
- end
+ @contents ||= dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
end
# The message of the exception reports the content of podspec for the
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index 476151ae56..863544b1f9 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -3,17 +3,17 @@
module Bundler
# used for Creating Specifications from the Gemcutter Endpoint
class EndpointSpecification < Gem::Specification
- ILLFORMED_MESSAGE = 'Ill-formed requirement ["#<YAML::Syck::DefaultKey'.freeze
- include MatchPlatform
+ include MatchRemoteMetadata
- attr_reader :name, :version, :platform, :required_rubygems_version, :required_ruby_version, :checksum
+ attr_reader :name, :version, :platform, :checksum
attr_accessor :source, :remote, :dependencies
- def initialize(name, version, platform, dependencies, metadata = nil)
+ def initialize(name, version, platform, spec_fetcher, dependencies, metadata = nil)
super()
@name = name
@version = Gem::Version.create version
- @platform = platform
+ @platform = Gem::Platform.new(platform)
+ @spec_fetcher = spec_fetcher
@dependencies = dependencies.map {|dep, reqs| build_dependency(dep, reqs) }
@loaded_from = nil
@@ -106,12 +106,21 @@ module Bundler
private
+ def _remote_specification
+ @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @platform])
+ end
+
def local_specification_path
"#{base_dir}/specifications/#{full_name}.gemspec"
end
def parse_metadata(data)
- return unless data
+ unless data
+ @required_ruby_version = nil
+ @required_rubygems_version = nil
+ return
+ end
+
data.each do |k, v|
next unless v
case k.to_s
@@ -129,13 +138,6 @@ module Bundler
def build_dependency(name, requirements)
Gem::Dependency.new(name, requirements)
- rescue ArgumentError => e
- raise unless e.message.include?(ILLFORMED_MESSAGE)
- puts # we shouldn't print the error message on the "fetching info" status line
- raise GemspecError,
- "Unfortunately, the gem #{name} (#{version}) has an invalid " \
- "gemspec.\nPlease ask the gem author to yank the bad version to fix " \
- "this issue. For more information, see http://bit.ly/syck-defaultkey."
end
end
end
diff --git a/lib/bundler/env.rb b/lib/bundler/env.rb
index 00d4ef2196..7b1152930e 100644
--- a/lib/bundler/env.rb
+++ b/lib/bundler/env.rb
@@ -71,11 +71,11 @@ module Bundler
def self.ruby_version
str = String.new(RUBY_VERSION)
str << "p#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
- str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{RUBY_PLATFORM}]"
+ str << " (#{RUBY_RELEASE_DATE} revision #{RUBY_REVISION}) [#{Gem::Platform.local}]"
end
def self.git_version
- Bundler::Source::Git::GitProxy.new(nil, nil, nil).full_version
+ Bundler::Source::Git::GitProxy.new(nil, nil).full_version
rescue Bundler::Source::Git::GitNotInstalledError
"not installed"
end
@@ -122,7 +122,7 @@ module Bundler
specs = Bundler.rubygems.find_name(name)
out << [" #{name}", "(#{specs.map(&:version).join(",")})"] unless specs.empty?
end
- if (exe = caller.last.split(":").first) && exe =~ %r{(exe|bin)/bundler?\z}
+ if (exe = caller.last.split(":").first)&.match? %r{(exe|bin)/bundler?\z}
shebang = File.read(exe).lines.first
shebang.sub!(/^#!\s*/, "")
unless shebang.start_with?(Gem.ruby, "/usr/bin/env ruby")
diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb
index a77f7e0816..57013f5d50 100644
--- a/lib/bundler/environment_preserver.rb
+++ b/lib/bundler/environment_preserver.rb
@@ -2,11 +2,12 @@
module Bundler
class EnvironmentPreserver
- INTENTIONALLY_NIL = "BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL".freeze
+ INTENTIONALLY_NIL = "BUNDLER_ENVIRONMENT_PRESERVER_INTENTIONALLY_NIL"
BUNDLER_KEYS = %w[
BUNDLE_BIN_PATH
BUNDLE_GEMFILE
BUNDLER_VERSION
+ BUNDLER_SETUP
GEM_HOME
GEM_PATH
MANPATH
@@ -15,7 +16,7 @@ module Bundler
RUBYLIB
RUBYOPT
].map(&:freeze).freeze
- BUNDLER_PREFIX = "BUNDLER_ORIG_".freeze
+ BUNDLER_PREFIX = "BUNDLER_ORIG_"
def self.from_env
new(env_to_hash(ENV), BUNDLER_KEYS)
@@ -38,7 +39,10 @@ module Bundler
# Replaces `ENV` with the bundler environment variables backed up
def replace_with_backup
- ENV.replace(backup) unless Gem.win_platform?
+ 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
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb
index 11763b4e88..5839fc6a73 100644
--- a/lib/bundler/errors.rb
+++ b/lib/bundler/errors.rb
@@ -21,16 +21,7 @@ module Bundler
class InstallError < BundlerError; status_code(5); end
# Internal error, should be rescued
- class VersionConflict < BundlerError
- attr_reader :conflicts
-
- def initialize(conflicts, msg = nil)
- super(msg)
- @conflicts = conflicts
- end
-
- status_code(6)
- end
+ class SolveFailure < BundlerError; status_code(6); end
class GemNotFound < BundlerError; status_code(7); end
class InstallHookError < BundlerError; status_code(8); end
@@ -41,19 +32,20 @@ module Bundler
class GemspecError < BundlerError; status_code(14); end
class InvalidOption < BundlerError; status_code(15); end
class ProductionError < BundlerError; status_code(16); end
+
class HTTPError < BundlerError
status_code(17)
def filter_uri(uri)
URICredentialsFilter.credential_filtered_uri(uri)
end
end
+
class RubyVersionMismatch < BundlerError; status_code(18); end
class SecurityError < BundlerError; status_code(19); end
class LockfileError < BundlerError; status_code(20); end
class CyclicDependencyError < BundlerError; status_code(21); end
class GemfileLockNotFound < BundlerError; status_code(22); end
class PluginError < BundlerError; status_code(29); end
- class SudoNotPermittedError < BundlerError; status_code(30); end
class ThreadCreationError < BundlerError; status_code(33); end
class APIResponseMismatchError < BundlerError; status_code(34); end
class APIResponseInvalidDependenciesError < BundlerError; status_code(35); end
@@ -75,10 +67,22 @@ module Bundler
end
end
+ def permission_type
+ case @permission_type
+ when :create
+ "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
+ 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)
@@ -122,7 +126,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
@@ -156,4 +160,16 @@ module Bundler
status_code(32)
end
+
+ class DirectoryRemovalError < BundlerError
+ def initialize(orig_exception, msg)
+ full_message = "#{msg}.\n" \
+ "The underlying error was #{orig_exception.class}: #{orig_exception.message}, with backtrace:\n" \
+ " #{orig_exception.backtrace.join("\n ")}\n\n" \
+ "Bundler Error Backtrace:"
+ super(full_message)
+ end
+
+ status_code(36)
+ end
end
diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb
index e441b941c2..ab2189f7f0 100644
--- a/lib/bundler/feature_flag.rb
+++ b/lib/bundler/feature_flag.rb
@@ -37,9 +37,7 @@ module Bundler
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(:suppress_install_using_messages) { bundler_3_mode? }
settings_flag(:update_requires_all_flag) { bundler_4_mode? }
- settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? }
settings_option(:default_cli_command) { bundler_3_mode? ? :cli_help : :install }
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index d237837948..2119799f68 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -20,6 +20,7 @@ module Bundler
class TooManyRequestsError < HTTPError; end
# This error is raised if the API returns a 413 (only printed in verbose)
class FallbackError < HTTPError; end
+
# This is the error raised if OpenSSL fails the cert verification
class CertificateFailureError < HTTPError
def initialize(remote_uri)
@@ -28,19 +29,18 @@ 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" \
- " sources and change 'https' to 'http'."
+ " https://railsapps.github.io/openssl-certificate-verify-failed.html."
end
end
+
# This is the error raised when a source is HTTPS and OpenSSL didn't load
class SSLError < HTTPError
def initialize(msg = nil)
super msg || "Could not load OpenSSL.\n" \
- "You must recompile Ruby with OpenSSL support or change the sources in your " \
- "Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL " \
- "using RVM are available at rvm.io/packages/openssl."
+ "You must recompile Ruby with OpenSSL support."
end
end
+
# This error is raised if HTTP authentication is required, but not provided.
class AuthenticationRequiredError < HTTPError
def initialize(remote_uri)
@@ -51,6 +51,7 @@ module Bundler
"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.
class BadAuthenticationError < HTTPError
def initialize(remote_uri)
@@ -60,6 +61,16 @@ module Bundler
end
end
+ # This error is raised if HTTP authentication is correct, but lacks
+ # necessary permissions.
+ class AuthenticationForbiddenError < HTTPError
+ def initialize(remote_uri)
+ remote_uri = filter_uri(remote_uri)
+ super "Access token could not be authenticated for #{remote_uri}.\n" \
+ "Make sure it's valid and has the necessary scopes configured."
+ end
+ end
+
# Exceptions classes that should bypass retry attempts. If your password didn't work the
# first time, it's not going to the third time.
NET_ERRORS = [:HTTPBadGateway, :HTTPBadRequest, :HTTPFailedDependency,
@@ -69,7 +80,7 @@ module Bundler
:HTTPRequestURITooLong, :HTTPUnauthorized, :HTTPUnprocessableEntity,
:HTTPUnsupportedMediaType, :HTTPVersionNotSupported].freeze
FAIL_ERRORS = begin
- fail_errors = [AuthenticationRequiredError, BadAuthenticationError, FallbackError]
+ fail_errors = [AuthenticationRequiredError, BadAuthenticationError, AuthenticationForbiddenError, FallbackError]
fail_errors << Gem::Requirement::BadRequirementError
fail_errors.concat(NET_ERRORS.map {|e| Net.const_get(e) })
end.freeze
@@ -101,11 +112,11 @@ module Bundler
uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
if uri.scheme == "file"
path = Bundler.rubygems.correct_for_windows_path(uri.path)
- Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
+ Bundler.safe_load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
Bundler.load_gemspec(cached_spec_path)
else
- Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
+ Bundler.safe_load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
end
rescue MarshalError
raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
@@ -121,7 +132,6 @@ module Bundler
# return the specs in the bundler format as an index
def specs(gem_names, source)
- old = Bundler.rubygems.sources
index = Bundler::Index.new
if Bundler::Fetcher.disable_endpoint
@@ -129,17 +139,15 @@ module Bundler
specs = fetchers.last.specs(gem_names)
else
specs = []
- fetchers.shift until fetchers.first.available? || fetchers.empty?
- fetchers.dup.each do |f|
- break unless f.api_fetcher? && !gem_names || !specs = f.specs(gem_names)
- fetchers.delete(f)
+ @fetchers = fetchers.drop_while do |f|
+ !f.available? || (f.api_fetcher? && !gem_names) || !specs = f.specs(gem_names)
end
@use_api = false if fetchers.none?(&:api_fetcher?)
end
specs.each do |name, version, platform, dependencies, metadata|
spec = if dependencies
- EndpointSpecification.new(name, version, platform, dependencies, metadata)
+ EndpointSpecification.new(name, version, platform, self, dependencies, metadata)
else
RemoteSpecification.new(name, version, platform, self)
end
@@ -152,8 +160,6 @@ module Bundler
rescue CertificateFailureError
Bundler.ui.info "" if gem_names && use_api # newline after dots
raise
- ensure
- Bundler.rubygems.sources = old
end
def use_api
@@ -230,6 +236,7 @@ module Bundler
"GO_SERVER_URL" => "go",
"SNAP_CI" => "snap",
"GITLAB_CI" => "gitlab",
+ "GITHUB_ACTIONS" => "github",
"CI_NAME" => ENV["CI_NAME"],
"CI" => "ci",
}
@@ -239,12 +246,12 @@ module Bundler
def connection
@connection ||= begin
needs_ssl = remote_uri.scheme == "https" ||
- Bundler.settings[:ssl_verify_mode] ||
- Bundler.settings[:ssl_client_cert]
+ Bundler.settings[:ssl_verify_mode] ||
+ Bundler.settings[:ssl_client_cert]
raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
con = PersistentHTTP.new :name => "bundler", :proxy => :ENV
- if gem_proxy = Bundler.rubygems.configuration[:http_proxy]
+ if gem_proxy = Gem.configuration[:http_proxy]
con.proxy = Bundler::URI.parse(gem_proxy) if gem_proxy != :no_proxy
end
@@ -255,8 +262,8 @@ module Bundler
end
ssl_client_cert = Bundler.settings[:ssl_client_cert] ||
- (Bundler.rubygems.configuration.ssl_client_cert if
- Bundler.rubygems.configuration.respond_to?(:ssl_client_cert))
+ (Gem.configuration.ssl_client_cert if
+ Gem.configuration.respond_to?(:ssl_client_cert))
if ssl_client_cert
pem = File.read(ssl_client_cert)
con.cert = OpenSSL::X509::Certificate.new(pem)
@@ -274,8 +281,7 @@ module Bundler
# cached gem specification path, if one exists
def gemspec_cached_path(spec_file_name)
paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) }
- paths = paths.select {|path| File.file? path }
- paths.first
+ paths.find {|path| File.file? path }
end
HTTP_ERRORS = [
@@ -288,8 +294,8 @@ module Bundler
def bundler_cert_store
store = OpenSSL::X509::Store.new
ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
- (Bundler.rubygems.configuration.ssl_ca_cert if
- Bundler.rubygems.configuration.respond_to?(:ssl_ca_cert))
+ (Gem.configuration.ssl_ca_cert if
+ Gem.configuration.respond_to?(:ssl_ca_cert))
if ssl_ca_cert
if File.directory? ssl_ca_cert
store.add_path ssl_ca_cert
@@ -303,8 +309,6 @@ module Bundler
store
end
- private
-
def remote_uri
@remote.uri
end
diff --git a/lib/bundler/fetcher/base.rb b/lib/bundler/fetcher/base.rb
index 16cc98273a..62cc75add8 100644
--- a/lib/bundler/fetcher/base.rb
+++ b/lib/bundler/fetcher/base.rb
@@ -19,14 +19,12 @@ module Bundler
end
def fetch_uri
- @fetch_uri ||= begin
- if remote_uri.host == "rubygems.org"
- uri = remote_uri.dup
- uri.host = "index.rubygems.org"
- uri
- else
- remote_uri
- end
+ @fetch_uri ||= if remote_uri.host == "rubygems.org"
+ uri = remote_uri.dup
+ uri.host = "index.rubygems.org"
+ uri
+ else
+ remote_uri
end
end
diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb
index aa828af6b1..8d30dec471 100644
--- a/lib/bundler/fetcher/compact_index.rb
+++ b/lib/bundler/fetcher/compact_index.rb
@@ -12,17 +12,15 @@ module Bundler
method = instance_method(method_name)
undef_method(method_name)
define_method(method_name) do |*args, &blk|
- begin
- method.bind(self).call(*args, &blk)
- rescue NetworkDownError, CompactIndexClient::Updater::MisMatchedChecksumError => e
- raise HTTPError, e.message
- rescue AuthenticationRequiredError
- # Fail since we got a 401 from the server.
- raise
- rescue HTTPError => e
- Bundler.ui.trace(e)
- nil
- end
+ method.bind(self).call(*args, &blk)
+ rescue NetworkDownError, CompactIndexClient::Updater::MisMatchedChecksumError => e
+ raise HTTPError, e.message
+ rescue AuthenticationRequiredError, BadAuthenticationError
+ # Fail since we got a 401 from the server.
+ raise
+ rescue HTTPError => e
+ Bundler.ui.trace(e)
+ nil
end
end
@@ -42,7 +40,7 @@ module Bundler
deps = begin
parallel_compact_index_client.dependencies(remaining_gems)
rescue TooManyRequestsError
- @bundle_worker.stop if @bundle_worker
+ @bundle_worker&.stop
@bundle_worker = nil # reset it. Not sure if necessary
serial_compact_index_client.dependencies(remaining_gems)
end
@@ -51,22 +49,12 @@ module Bundler
complete_gems.concat(deps.map(&:first)).uniq!
remaining_gems = next_gems - complete_gems
end
- @bundle_worker.stop if @bundle_worker
+ @bundle_worker&.stop
@bundle_worker = nil # reset it. Not sure if necessary
gem_info
end
- def fetch_spec(spec)
- spec -= [nil, "ruby", ""]
- contents = compact_index_client.spec(*spec)
- return nil if contents.nil?
- contents.unshift(spec.first)
- contents[3].map! {|d| Gem::Dependency.new(*d) }
- EndpointSpecification.new(*contents)
- end
- compact_index_request :fetch_spec
-
def available?
unless SharedHelpers.md5_available?
Bundler.ui.debug("FIPS mode is enabled, bundler can't use the CompactIndex API")
diff --git a/lib/bundler/fetcher/dependency.rb b/lib/bundler/fetcher/dependency.rb
index c52c32fb5b..18b606abb6 100644
--- a/lib/bundler/fetcher/dependency.rb
+++ b/lib/bundler/fetcher/dependency.rb
@@ -34,14 +34,10 @@ module Bundler
returned_gems = spec_list.map(&:first).uniq
specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list)
- rescue MarshalError
+ rescue MarshalError, HTTPError, GemspecError
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
Bundler.ui.debug "could not fetch from the dependency API, trying the full index"
nil
- rescue HTTPError, GemspecError
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
- Bundler.ui.debug "could not fetch from the dependency API\nit's suggested to retry using the full index via `bundle install --full-index`"
- nil
end
def dependency_specs(gem_names)
@@ -55,7 +51,7 @@ module Bundler
gem_list = []
gem_names.each_slice(Source::Rubygems::API_REQUEST_SIZE) do |names|
marshalled_deps = downloader.fetch(dependency_api_uri(names)).body
- gem_list.concat(Bundler.load_marshal(marshalled_deps))
+ gem_list.concat(Bundler.safe_load_marshal(marshalled_deps))
end
gem_list
end
diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb
index f2aad3a500..3062899e0e 100644
--- a/lib/bundler/fetcher/downloader.rb
+++ b/lib/bundler/fetcher/downloader.rb
@@ -41,6 +41,8 @@ module Bundler
when Net::HTTPUnauthorized
raise BadAuthenticationError, uri.host if uri.userinfo
raise AuthenticationRequiredError, uri.host
+ when Net::HTTPForbidden
+ raise AuthenticationForbiddenError, uri.host
when Net::HTTPNotFound
raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}"
else
@@ -61,14 +63,11 @@ module Bundler
req.basic_auth(user, password)
end
connection.request(uri, req)
- rescue NoMethodError => e
- raise unless ["undefined method", "use_ssl="].all? {|snippet| e.message.include? snippet }
- raise LoadError.new("cannot load such file -- openssl")
rescue OpenSSL::SSL::SSLError
raise CertificateFailureError.new(uri)
rescue *HTTP_ERRORS => e
Bundler.ui.trace e
- if e.is_a?(SocketError) || e.message =~ /host down:/
+ if e.is_a?(SocketError) || e.message.to_s.include?("host down:")
raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
"connection and try again."
else
@@ -80,7 +79,7 @@ module Bundler
private
def validate_uri_scheme!(uri)
- return if uri.scheme =~ /\Ahttps?\z/
+ return if /\Ahttps?\z/.match?(uri.scheme)
raise InvalidOption,
"The request uri `#{uri}` has an invalid scheme (`#{uri.scheme}`). " \
"Did you mean `http` or `https`?"
diff --git a/lib/bundler/fetcher/index.rb b/lib/bundler/fetcher/index.rb
index 0d14c47aa7..c623647f01 100644
--- a/lib/bundler/fetcher/index.rb
+++ b/lib/bundler/fetcher/index.rb
@@ -15,38 +15,11 @@ module Bundler
raise BadAuthenticationError, remote_uri if remote_uri.userinfo
raise AuthenticationRequiredError, remote_uri
when /403/
- raise BadAuthenticationError, remote_uri if remote_uri.userinfo
- raise AuthenticationRequiredError, remote_uri
+ raise AuthenticationForbiddenError, remote_uri
else
raise HTTPError, "Could not fetch specs from #{display_uri} due to underlying error <#{e.message}>"
end
end
-
- def fetch_spec(spec)
- spec -= [nil, "ruby", ""]
- spec_file_name = "#{spec.join "-"}.gemspec"
-
- uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
- if uri.scheme == "file"
- path = Bundler.rubygems.correct_for_windows_path(uri.path)
- Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
- elsif cached_spec_path = gemspec_cached_path(spec_file_name)
- Bundler.load_gemspec(cached_spec_path)
- else
- Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
- end
- rescue MarshalError
- raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
- "Your network or your gem server is probably having issues right now."
- end
-
- private
-
- # cached gem specification path, if one exists
- def gemspec_cached_path(spec_file_name)
- paths = Bundler.rubygems.spec_cache_dirs.map {|dir| File.join(dir, spec_file_name) }
- paths.find {|path| File.file? path }
- end
end
end
end
diff --git a/lib/bundler/force_platform.rb b/lib/bundler/force_platform.rb
new file mode 100644
index 0000000000..249a24ecd1
--- /dev/null
+++ b/lib/bundler/force_platform.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Bundler
+ module ForcePlatform
+ private
+
+ # The `:force_ruby_platform` value used by dependencies for resolution, and
+ # by locked specifications for materialization is `false` by default, except
+ # for TruffleRuby. TruffleRuby generally needs to force the RUBY platform
+ # variant unless the name is explicitly allowlisted.
+
+ def default_force_ruby_platform
+ return false unless RUBY_ENGINE == "truffleruby"
+
+ !Gem::Platform::REUSE_AS_BINARY_ON_TRUFFLERUBY.include?(name)
+ end
+ end
+end
diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb
index db43e0f654..39afe8a071 100644
--- a/lib/bundler/friendly_errors.rb
+++ b/lib/bundler/friendly_errors.rb
@@ -29,13 +29,13 @@ module Bundler
Bundler.ui.error error.message
Bundler.ui.trace error.orig_exception
when BundlerError
- Bundler.ui.error error.message, :wrap => true
- Bundler.ui.trace error
+ if Bundler.ui.debug?
+ Bundler.ui.trace error
+ else
+ Bundler.ui.error error.message, :wrap => true
+ end
when Thor::Error
Bundler.ui.error error.message
- when LoadError
- raise error unless error.message =~ /cannot load such file -- openssl|openssl.so|libcrypto.so/
- Bundler.ui.error "\nCould not load OpenSSL. #{error.class}: #{error}\n#{error.backtrace.join("\n ")}"
when Interrupt
Bundler.ui.error "\nQuitting..."
Bundler.ui.trace error
@@ -63,38 +63,9 @@ module Bundler
def request_issue_report_for(e)
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/rubygems/rubygems/blob/master/bundler/doc/contributing/ISSUES.md?**
-
- ...
-
- ## Backtrace
```
- #{e.class}: #{e.message}
- #{e.backtrace && e.backtrace.join("\n ").chomp}
+ #{exception_message(e)}
```
#{Bundler::Env.report}
@@ -109,8 +80,22 @@ module Bundler
First, try this link to see if there are any existing issue reports for this error:
#{issues_url(e)}
- If there aren't any reports for this error yet, please 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/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md
+ 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
+
+ def exception_message(error)
+ message = serialized_exception_for(error)
+ cause = error.cause
+ return message unless cause
+
+ message + serialized_exception_for(cause)
+ end
+
+ def serialized_exception_for(e)
+ <<-EOS.gsub(/^ {8}/, "")
+ #{e.class}: #{e.message}
+ #{e.backtrace&.join("\n ")&.chomp}
EOS
end
@@ -121,6 +106,10 @@ module Bundler
"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
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index 6096adfa27..dcf759cded 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -21,7 +21,7 @@ module Bundler
def gemspec(&block)
gemspec = instance.gemspec
- block.call(gemspec) if block
+ block&.call(gemspec)
gemspec
end
end
@@ -76,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
@@ -98,10 +98,7 @@ module Bundler
built_gem_path ||= build_gem
cmd = [*gem_command, "install", built_gem_path.to_s]
cmd << "--local" if local
- _, status = sh_with_status(cmd)
- unless status.success?
- raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output"
- end
+ sh(cmd)
Bundler.ui.confirm "#{name} (#{version}) installed."
end
@@ -110,9 +107,9 @@ module Bundler
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)
+ checksum = ::Digest::SHA512.file(built_gem_path).hexdigest
target = File.join(base, "checksums", file_name)
- File.write(target, checksum)
+ File.write(target, checksum + "\n")
Bundler.ui.confirm "#{name} #{version} checksum written to checksums/#{file_name}."
end
@@ -132,8 +129,8 @@ module Bundler
def git_push(remote = nil)
remote ||= default_remote
- perform_git_push "#{remote} refs/heads/#{current_branch}"
- perform_git_push "#{remote} refs/tags/#{version_tag}"
+ 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
@@ -155,19 +152,11 @@ module Bundler
def gem_push_host
env_rubygems_host = ENV["RUBYGEMS_HOST"]
- env_rubygems_host = nil if
- env_rubygems_host && env_rubygems_host.empty?
+ env_rubygems_host = nil if env_rubygems_host&.empty?
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."
@@ -218,8 +207,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
@@ -229,7 +217,7 @@ module Bundler
SharedHelpers.chdir(base) do
outbuf = IO.popen(cmd, :err => [:child, :out], &:read)
status = $?
- block.call(outbuf) if status.success? && block
+ block&.call(outbuf) if status.success?
[outbuf, status]
end
end
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
index b271b8d229..2e6d788f9c 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -10,6 +10,7 @@ module Bundler
[Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")],
[Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw32")],
[Gem::Platform.new("x86_64-mingw32"), Gem::Platform.new("x64-mingw32")],
+ [Gem::Platform.new("x64-mingw-ucrt"), Gem::Platform.new("x64-mingw-ucrt")],
[Gem::Platform.new("mingw32"), Gem::Platform.new("x86-mingw32")],
].freeze
@@ -42,15 +43,21 @@ module Bundler
def select_best_platform_match(specs, platform)
matching = specs.select {|spec| spec.match_platform(platform) }
+
+ sort_best_platform_match(matching, platform)
+ end
+ module_function :select_best_platform_match
+
+ def sort_best_platform_match(matching, platform)
exact = matching.select {|spec| spec.platform == platform }
return exact if exact.any?
sorted_matching = matching.sort_by {|spec| platform_specificity_match(spec.platform, platform) }
exemplary_spec = sorted_matching.first
- sorted_matching.take_while{|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
+ sorted_matching.take_while {|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
end
- module_function :select_best_platform_match
+ module_function :sort_best_platform_match
class PlatformMatch
def self.specificity_score(spec_platform, user_platform)
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb
index 3cce3f2139..d281f46eeb 100644
--- a/lib/bundler/gem_version_promoter.rb
+++ b/lib/bundler/gem_version_promoter.rb
@@ -7,14 +7,13 @@ 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["BUNDLER_DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER"]
-
- attr_reader :level, :locked_specs, :unlock_gems
+ attr_reader :level
+ attr_accessor :pre
# By default, strict is false, meaning every available version of a gem
# is returned from sort_versions. The order gives preference to the
# requested level (:patch, :minor, :major) but in complicated requirement
- # cases some gems will by necessity by promoted past the requested level,
+ # cases some gems will by necessity be promoted past the requested level,
# or even reverted to older versions.
#
# If strict is set to true, the results from sort_versions will be
@@ -24,24 +23,13 @@ module Bundler
# existing in the referenced source.
attr_accessor :strict
- attr_accessor :prerelease_specified
-
- # Given a list of locked_specs and a list of gems to unlock creates a
- # GemVersionPromoter instance.
+ # Creates a GemVersionPromoter instance.
#
- # @param locked_specs [SpecSet] All current locked specs. Unlike Definition
- # where this list is empty if all gems are being updated, this should
- # always be populated for all gems so this class can properly function.
- # @param unlock_gems [String] List of gem names being unlocked. If empty,
- # all gems will be considered unlocked.
# @return [GemVersionPromoter]
- def initialize(locked_specs = SpecSet.new([]), unlock_gems = [])
+ def initialize
@level = :major
@strict = false
- @locked_specs = locked_specs
- @unlock_gems = unlock_gems
- @sort_versions = {}
- @prerelease_specified = {}
+ @pre = false
end
# @param value [Symbol] One of three Symbols: :major, :minor or :patch.
@@ -55,37 +43,19 @@ module Bundler
@level = v
end
- # Given a Dependency and an Array of SpecGroups of available versions for a
- # gem, this method will return the Array of SpecGroups sorted (and possibly
- # truncated if strict is true) in an order to give preference to the current
- # level (:major, :minor or :patch) when resolution is deciding what versions
- # best resolve all dependencies in the bundle.
- # @param dep [Dependency] The Dependency of the gem.
- # @param spec_groups [SpecGroup] An array of SpecGroups for the same gem
- # named in the @dep param.
- # @return [SpecGroup] A new instance of the SpecGroup Array sorted and
+ # Given a Resolver::Package and an Array of Specifications of available
+ # versions for a gem, this method will return the Array of Specifications
+ # sorted (and possibly truncated if strict is true) in an order to give
+ # preference to the current level (:major, :minor or :patch) when resolution
+ # is deciding what versions best resolve all dependencies in the bundle.
+ # @param package [Resolver::Package] The package being resolved.
+ # @param specs [Specification] An array of Specifications for the package.
+ # @return [Specification] A new instance of the Specification Array sorted and
# possibly filtered.
- def sort_versions(dep, spec_groups)
- before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if DEBUG
-
- @sort_versions[dep] ||= begin
- gem_name = dep.name
+ def sort_versions(package, specs)
+ specs = filter_dep_specs(specs, package) if strict
- # An Array per version returned, different entries for different platforms.
- # We only need the version here so it's ok to hard code this to the first instance.
- locked_spec = locked_specs[gem_name].first
-
- if strict
- filter_dep_specs(spec_groups, locked_spec)
- else
- sort_dep_specs(spec_groups, locked_spec)
- end.tap do |specs|
- if DEBUG
- puts before_result
- puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
- end
- end
- end
+ sort_dep_specs(specs, package)
end
# @return [bool] Convenience method for testing value of level variable.
@@ -98,80 +68,72 @@ module Bundler
level == :minor
end
+ # @return [bool] Convenience method for testing value of pre variable.
+ def pre?
+ pre == true
+ end
+
private
- def filter_dep_specs(spec_groups, locked_spec)
- res = spec_groups.select do |spec_group|
- if locked_spec && !major?
- gsv = spec_group.version
- lsv = locked_spec.version
+ def filter_dep_specs(specs, package)
+ locked_version = package.locked_version
+ return specs if locked_version.nil? || major?
- must_match = minor? ? [0] : [0, 1]
+ specs.select do |spec|
+ gsv = spec.version
- matches = must_match.map {|idx| gsv.segments[idx] == lsv.segments[idx] }
- matches.uniq == [true] ? (gsv >= lsv) : false
- else
- true
- end
- end
+ must_match = minor? ? [0] : [0, 1]
- sort_dep_specs(res, locked_spec)
+ all_match = must_match.all? {|idx| gsv.segments[idx] == locked_version.segments[idx] }
+ all_match && gsv >= locked_version
+ end
end
- def sort_dep_specs(spec_groups, locked_spec)
- return spec_groups unless locked_spec
- @gem_name = locked_spec.name
- @locked_version = locked_spec.version
-
- result = spec_groups.sort do |a, b|
- @a_ver = a.version
- @b_ver = b.version
+ def sort_dep_specs(specs, package)
+ locked_version = package.locked_version
- unless @prerelease_specified[@gem_name]
- a_pre = @a_ver.prerelease?
- b_pre = @b_ver.prerelease?
+ result = specs.sort do |a, b|
+ unless package.prerelease_specified? || pre?
+ a_pre = a.prerelease?
+ b_pre = b.prerelease?
next -1 if a_pre && !b_pre
next 1 if b_pre && !a_pre
end
if major?
- @a_ver <=> @b_ver
- elsif either_version_older_than_locked
- @a_ver <=> @b_ver
- elsif segments_do_not_match(:major)
- @b_ver <=> @a_ver
- elsif !minor? && segments_do_not_match(:minor)
- @b_ver <=> @a_ver
+ a <=> b
+ elsif either_version_older_than_locked?(a, b, locked_version)
+ a <=> b
+ elsif segments_do_not_match?(a, b, :major)
+ b <=> a
+ elsif !minor? && segments_do_not_match?(a, b, :minor)
+ b <=> a
else
- @a_ver <=> @b_ver
+ a <=> b
end
end
- post_sort(result)
+ post_sort(result, package.unlock?, locked_version)
end
- def either_version_older_than_locked
- @a_ver < @locked_version || @b_ver < @locked_version
+ def either_version_older_than_locked?(a, b, locked_version)
+ locked_version && (a.version < locked_version || b.version < locked_version)
end
- def segments_do_not_match(level)
+ def segments_do_not_match?(a, b, level)
index = [:major, :minor].index(level)
- @a_ver.segments[index] != @b_ver.segments[index]
- end
-
- def unlocking_gem?
- unlock_gems.empty? || unlock_gems.include?(@gem_name)
+ a.segments[index] != b.segments[index]
end
# Specific version moves can't always reliably be done during sorting
# as not all elements are compared against each other.
- def post_sort(result)
+ def post_sort(result, unlock, locked_version)
# default :major behavior in Bundler does not do this
return result if major?
- if unlocking_gem?
+ if unlock || locked_version.nil?
result
else
- move_version_to_end(result, @locked_version)
+ move_version_to_end(result, locked_version)
end
end
@@ -179,12 +141,5 @@ module Bundler
move, keep = result.partition {|s| s.version.to_s == version.to_s }
keep.concat(move)
end
-
- def debug_format_result(dep, spec_groups)
- a = [dep.to_s,
- spec_groups.map {|sg| [sg.version, sg.dependencies_for_activated_platforms.map {|dp| [dp.name, dp.requirement.to_s] }] }]
- last_map = a.last.map {|sg_data| [sg_data.first.version, sg_data.last.map {|aa| aa.join(" ") }] }
- [a.first, last_map, level, strict ? :strict : :not_strict]
- end
end
end
diff --git a/lib/bundler/gemdeps.rb b/lib/bundler/gemdeps.rb
deleted file mode 100644
index cd4b25d0e6..0000000000
--- a/lib/bundler/gemdeps.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class Gemdeps
- def initialize(runtime)
- @runtime = runtime
- end
-
- def requested_specs
- @runtime.requested_specs
- end
-
- def specs
- @runtime.specs
- end
-
- def dependencies
- @runtime.dependencies
- end
-
- def current_dependencies
- @runtime.current_dependencies
- end
-
- def requires
- @runtime.requires
- end
- end
-end
diff --git a/lib/bundler/graph.rb b/lib/bundler/graph.rb
index 8f52e2f0f0..3c008e63e3 100644
--- a/lib/bundler/graph.rb
+++ b/lib/bundler/graph.rb
@@ -114,10 +114,10 @@ module Bundler
@groups.each do |group|
g.add_nodes(
group, {
- :style => "filled",
+ :style => "filled",
:fillcolor => "#B9B9D5",
- :shape => "box3d",
- :fontsize => 16,
+ :shape => "box3d",
+ :fontsize => 16,
}.merge(@node_options[group])
)
end
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index 8930fca6d0..b8c599f63a 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -13,8 +13,8 @@ module Bundler
attr_reader :specs, :all_specs, :sources
protected :specs, :all_specs
- RUBY = "ruby".freeze
- NULL = "\0".freeze
+ RUBY = "ruby"
+ NULL = "\0"
def initialize
@sources = []
@@ -56,45 +56,21 @@ module Bundler
# Search this index's specs, and any source indexes that this index knows
# about, returning all of the results.
- def search(query, base = nil)
- sort_specs(unsorted_search(query, base))
- end
-
- def unsorted_search(query, base)
- results = local_search(query, base)
-
- seen = results.map(&:full_name).uniq unless @sources.empty?
+ def search(query)
+ results = local_search(query)
+ return results unless @sources.any?
@sources.each do |source|
- source.unsorted_search(query, base).each do |spec|
- next if seen.include?(spec.full_name)
-
- seen << spec.full_name
- results << spec
- end
- end
-
- results
- end
- protected :unsorted_search
-
- def self.sort_specs(specs)
- specs.sort_by do |s|
- platform_string = s.platform.to_s
- [s.version, platform_string == RUBY ? NULL : platform_string]
+ results.concat(source.search(query))
end
+ results.uniq(&:full_name)
end
- def sort_specs(specs)
- self.class.sort_specs(specs)
- end
-
- def local_search(query, base = nil)
+ def local_search(query)
case query
when Gem::Specification, RemoteSpecification, LazySpecification, EndpointSpecification then search_by_spec(query)
when String then specs_by_name(query)
- when Gem::Dependency then search_by_dependency(query, base)
- when DepProxy then search_by_dependency(query.dep, base)
+ when Array then specs_by_name_and_version(*query)
else
raise "You can't search for a #{query.inspect}."
end
@@ -181,26 +157,12 @@ module Bundler
private
- def specs_by_name(name)
- @specs[name].values
+ def specs_by_name_and_version(name, version)
+ specs_by_name(name).select {|spec| spec.version == version }
end
- def search_by_dependency(dependency, base = nil)
- @cache[base || false] ||= {}
- @cache[base || false][dependency] ||= begin
- specs = specs_by_name(dependency.name)
- specs += base if base
- found = specs.select do |spec|
- next true if spec.source.is_a?(Source::Gemspec)
- if base # allow all platforms when searching from a lockfile
- dependency.matches_spec?(spec)
- else
- dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec)
- end
- end
-
- found
- end
+ def specs_by_name(name)
+ @specs[name].values
end
EMPTY_SEARCH = [].freeze
diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb
index 613bda4f84..cb644a7f69 100644
--- a/lib/bundler/injector.rb
+++ b/lib/bundler/injector.rb
@@ -2,7 +2,7 @@
module Bundler
class Injector
- INJECTED_GEMS = "injected gems".freeze
+ INJECTED_GEMS = "injected gems"
def self.inject(new_deps, options = {})
injector = new(new_deps, options)
@@ -70,8 +70,12 @@ module Bundler
show_warning("No gems were removed from the gemfile.") if deps.empty?
- deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep, false)} was removed." }
+ deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep)} was removed." }
end
+
+ # Invalidate the cached Bundler.definition.
+ # This prevents e.g. `bundle remove ...` from using outdated information.
+ Bundler.reset_paths!
end
private
@@ -111,10 +115,14 @@ module Bundler
end
source = ", :source => \"#{d.source}\"" unless d.source.nil?
+ path = ", :path => \"#{d.path}\"" unless d.path.nil?
git = ", :git => \"#{d.git}\"" unless d.git.nil?
+ github = ", :github => \"#{d.github}\"" unless d.github.nil?
branch = ", :branch => \"#{d.branch}\"" unless d.branch.nil?
+ ref = ", :ref => \"#{d.ref}\"" unless d.ref.nil?
+ require_path = ", :require => #{convert_autorequire(d.autorequire)}" unless d.autorequire.nil?
- %(gem #{name}#{requirement}#{group}#{source}#{git}#{branch})
+ %(gem #{name}#{requirement}#{group}#{source}#{path}#{git}#{github}#{branch}#{ref}#{require_path})
end.join("\n")
end
@@ -227,7 +235,7 @@ module Bundler
gemfile.each_with_index do |line, index|
next unless !line.nil? && line.strip.start_with?(block_name)
- if gemfile[index + 1] =~ /^\s*end\s*$/
+ if /^\s*end\s*$/.match?(gemfile[index + 1])
gemfile[index] = nil
gemfile[index + 1] = nil
end
@@ -269,5 +277,11 @@ module Bundler
def show_warning(message)
Bundler.ui.info Bundler.ui.add_color(message, :yellow)
end
+
+ def convert_autorequire(autorequire)
+ autorequire = autorequire.first
+ return autorequire if autorequire == "false"
+ autorequire.inspect
+ end
end
end
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index a718418fce..5c184f67a1 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -31,20 +31,16 @@
#
def gemfile(install = false, options = {}, &gemfile)
require_relative "../bundler"
+ Bundler.reset!
opts = options.dup
ui = opts.delete(:ui) { Bundler::UI::Shell.new }
- ui.level = "silent" if opts.delete(:quiet)
+ ui.level = "silent" if opts.delete(:quiet) || !install
+ Bundler.ui = ui
raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
- begin
- old_root = Bundler.method(:root)
- bundler_module = class << Bundler; self; end
- bundler_module.send(:remove_method, :root)
- def Bundler.root
- Bundler::SharedHelpers.pwd.expand_path
- end
- old_gemfile = ENV["BUNDLE_GEMFILE"]
+ Bundler.with_unbundled_env do
+ Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
@@ -57,9 +53,8 @@ def gemfile(install = false, options = {}, &gemfile)
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) do
+ Bundler.settings.temporary(:inline => true, :no_install => false) do
installer = Bundler::Installer.install(Bundler.root, definition, :system => true)
installer.post_install_messages.each do |name, message|
Bundler.ui.info "Post-install message from #{name}:\n#{message}"
@@ -70,16 +65,9 @@ def gemfile(install = false, options = {}, &gemfile)
runtime = Bundler::Runtime.new(nil, definition)
runtime.setup.require
end
- ensure
- if bundler_module
- bundler_module.send(:remove_method, :root)
- bundler_module.send(:define_method, :root, old_root)
- end
+ end
- if old_gemfile
- ENV["BUNDLE_GEMFILE"] = old_gemfile
- else
- ENV["BUNDLE_GEMFILE"] = ""
- end
+ if ENV["BUNDLE_GEMFILE"].nil?
+ ENV["BUNDLE_GEMFILE"] = ""
end
end
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 2624ac4b18..59b6a6ad22 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "rubygems/dependency_installer"
require_relative "worker"
require_relative "installer/parallel_installer"
require_relative "installer/standalone"
@@ -14,7 +13,7 @@ module Bundler
Installer.ambiguous_gems = []
end
- attr_reader :post_install_messages
+ attr_reader :post_install_messages, :definition
# Begins the installation process for Bundler.
# For more information see the #run method on this class.
@@ -67,7 +66,7 @@ module Bundler
# require paths and save them in a `setup.rb` file. See `bundle standalone --help` for more
# information.
def run(options)
- create_bundle_path
+ Bundler.create_bundle_path
ProcessLock.lock do
if Bundler.frozen_bundle?
@@ -91,7 +90,7 @@ module Bundler
Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available
- lock unless Bundler.frozen_bundle?
+ lock
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
end
end
@@ -120,7 +119,7 @@ module Bundler
relative_gemfile_path = relative_gemfile_path
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
- template_path = File.expand_path("../templates/Executable", __FILE__)
+ template_path = File.expand_path("templates/Executable", __dir__)
if spec.name == "bundler"
template_path += ".bundler"
spec.executables = %(bundle)
@@ -137,11 +136,7 @@ module Bundler
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
+ content = ERB.new(template, :trim_mode => "-").result(binding)
File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask)
if Gem.win_platform? || options[:all_platforms]
@@ -173,7 +168,7 @@ module Bundler
end
standalone_path = Bundler.root.join(path).relative_path_from(bin_path)
standalone_path = standalone_path
- template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
+ template = File.read(File.expand_path("templates/Executable.standalone", __dir__))
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
@@ -184,11 +179,7 @@ module Bundler
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
+ content = ERB.new(template, :trim_mode => "-").result(binding)
File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755)
if Gem.win_platform? || options[:all_platforms]
@@ -219,9 +210,6 @@ module Bundler
return jobs
end
- # Parallelization has some issues on Windows, so it's not yet the default
- return 1 if Gem.win_platform?
-
Bundler.settings.processor_count
end
@@ -230,31 +218,24 @@ module Bundler
requested_path_gems = @definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
path_plugin_files = requested_path_gems.map do |spec|
- begin
- Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
- rescue TypeError
- error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
- raise Gem::InvalidSpecificationException, error_message
- end
+ Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
+ rescue TypeError
+ error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
+ raise Gem::InvalidSpecificationException, error_message
end.flatten
Bundler.rubygems.load_plugin_files(path_plugin_files)
Bundler.rubygems.load_env_plugins
end
def ensure_specs_are_compatible!
- system_ruby = Bundler::RubyVersion.system
- rubygems_version = Gem::Version.create(Gem::VERSION)
@definition.specs.each do |spec|
- if required_ruby_version = spec.required_ruby_version
- unless required_ruby_version.satisfied_by?(system_ruby.gem_version)
- raise InstallError, "#{spec.full_name} requires ruby version #{required_ruby_version}, " \
- "which is incompatible with the current version, #{system_ruby}"
- end
+ unless spec.matches_current_ruby?
+ raise InstallError, "#{spec.full_name} requires ruby version #{spec.required_ruby_version}, " \
+ "which is incompatible with the current version, #{Gem.ruby_version}"
end
- next unless required_rubygems_version = spec.required_rubygems_version
- unless required_rubygems_version.satisfied_by?(rubygems_version)
- raise InstallError, "#{spec.full_name} requires rubygems version #{required_rubygems_version}, " \
- "which is incompatible with the current version, #{rubygems_version}"
+ unless spec.matches_current_rubygems?
+ raise InstallError, "#{spec.full_name} requires rubygems version #{spec.required_rubygems_version}, " \
+ "which is incompatible with the current version, #{Gem.rubygems_version}"
end
end
end
@@ -266,22 +247,16 @@ module Bundler
end
end
- def create_bundle_path
- SharedHelpers.filesystem_access(Bundler.bundle_path.to_s) do |p|
- Bundler.mkdir_p(p)
- end unless Bundler.bundle_path.exist?
- rescue Errno::EEXIST
- raise PathError, "Could not install to path `#{Bundler.bundle_path}` " \
- "because a file already exists at that path. Either remove or rename the file so the directory can be created."
- end
-
# returns whether or not a re-resolve was needed
def resolve_if_needed(options)
+ @definition.resolution_mode = options
+
if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
return false if @definition.nothing_changed? && !@definition.missing_specs?
end
- options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
+ @definition.setup_sources_for_resolve
+
true
end
diff --git a/lib/bundler/installer/gem_installer.rb b/lib/bundler/installer/gem_installer.rb
index 1df86ccfbc..9a013eea4d 100644
--- a/lib/bundler/installer/gem_installer.rb
+++ b/lib/bundler/installer/gem_installer.rb
@@ -13,7 +13,7 @@ module Bundler
end
def install_from_spec
- post_install_message = spec_settings ? install_with_settings : install
+ post_install_message = install
Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
generate_executable_stubs
return true, post_install_message
@@ -51,12 +51,20 @@ module Bundler
end
def install
- spec.source.install(spec, :force => force, :ensure_builtin_gems_cached => standalone, :build_args => Array(spec_settings))
+ spec.source.install(
+ spec,
+ :force => force,
+ :ensure_builtin_gems_cached => standalone,
+ :build_args => Array(spec_settings),
+ :previous_spec => previous_spec,
+ )
end
- def install_with_settings
- # Build arguments are global, so this is mutexed
- Bundler.rubygems.install_with_build_args([spec_settings]) { install }
+ def previous_spec
+ locked_gems = installer.definition.locked_gems
+ return unless locked_gems
+
+ locked_gems.specs.find {|s| s.name == spec.name }
end
def out_of_space_message
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb
index 5b6680e5e1..83a381f592 100644
--- a/lib/bundler/installer/parallel_installer.rb
+++ b/lib/bundler/installer/parallel_installer.rb
@@ -53,10 +53,6 @@ module Bundler
@dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep }
end
- def missing_lockfile_dependencies(all_spec_names)
- dependencies.reject {|dep| all_spec_names.include? dep.name }
- end
-
# Represents all dependencies
def all_dependencies
@spec.dependencies
@@ -84,8 +80,6 @@ module Bundler
end
def call
- check_for_corrupt_lockfile
-
if @rake
do_install(@rake, 0)
Gem::Specification.reset
@@ -102,7 +96,7 @@ module Bundler
handle_error if failed_specs.any?
@specs
ensure
- worker_pool && worker_pool.stop
+ worker_pool&.stop
end
def check_for_unmet_dependencies
@@ -116,43 +110,19 @@ module Bundler
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 << "You can fix this by regenerating your lockfile or 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}"
+ found = @specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }
+ warning << "* #{unmet_spec_dependency}, dependency of #{spec.full_name}, unsatisfied by #{found.full_name}"
end
end
Bundler.ui.warn(warning.join("\n"))
end
- def check_for_corrupt_lockfile
- missing_dependencies = @specs.map do |s|
- [
- s,
- s.missing_lockfile_dependencies(@specs.map(&:name)),
- ]
- end.reject {|a| a.last.empty? }
- return if missing_dependencies.empty?
-
- warning = []
- warning << "Your lockfile was created by an old Bundler that left some things out."
- if @size != 1
- warning << "Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing #{@size} at a time."
- @size = 1
- end
- warning << "You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile."
- warning << "The missing gems are:"
-
- missing_dependencies.each do |spec, missing|
- warning << "* #{missing.map(&:name).join(", ")} depended upon by #{spec.name}"
- end
-
- Bundler.ui.warn(warning.join("\n"))
- end
-
private
def failed_specs
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index f16135cb48..2a8c9a432d 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -12,12 +12,14 @@ 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 define_path_helpers
file.puts reverse_rubygems_kernel_mixin
paths.each do |path|
- file.puts %($:.unshift File.expand_path("\#{path}/#{path}"))
+ if Pathname.new(path).absolute?
+ file.puts %($:.unshift "#{path}")
+ else
+ file.puts %($:.unshift File.expand_path("\#{__dir__}/#{path}"))
+ end
end
end
end
@@ -28,37 +30,71 @@ module Bundler
@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}/#{Gem.ruby_api_version}').
+ sub(extensions_dir, 'extensions/\k<platform>/#{Gem.extension_api_version}')
# This is a static string intentionally. It's interpolated at a later time.
end
- end.flatten
+ end.flatten.compact
end
def version_dir
- "#{Bundler::RubyVersion.system.engine}/#{RbConfig::CONFIG["ruby_version"]}"
+ "#{RUBY_ENGINE}/#{Gem.ruby_api_version}"
+ end
+
+ def extensions_dir
+ %r{extensions/(?<platform>[^/]+)/#{Regexp.escape(Gem.extension_api_version)}}
end
def bundler_path
- Bundler.root.join(Bundler.settings[:path], "bundler")
+ Bundler.root.join(Bundler.settings[:path].to_s, "bundler")
end
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) && spec.source.path.absolute?
+ 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 define_path_helpers
+ <<~'END'
+ unless defined?(Gem)
+ module Gem
+ def self.ruby_api_version
+ RbConfig::CONFIG["ruby_version"]
+ end
+
+ def self.extension_api_version
+ if 'no' == RbConfig::CONFIG['ENABLE_SHARED']
+ "#{ruby_api_version}-static"
+ else
+ ruby_api_version
+ end
+ end
+ end
+ end
+ END
+ 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
+ if Gem.respond_to?(:discover_gems_on_require=)
+ Gem.discover_gems_on_require = false
+ else
+ 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
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 6760edba42..c9b161dc0e 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require_relative "match_platform"
+require_relative "force_platform"
module Bundler
class LazySpecification
include MatchPlatform
+ include ForcePlatform
attr_reader :name, :version, :dependencies, :platform
- attr_accessor :source, :remote
+ attr_accessor :source, :remote, :force_ruby_platform
def initialize(name, version, platform, source = nil)
@name = name
@@ -15,11 +16,11 @@ module Bundler
@dependencies = []
@platform = platform || Gem::Platform::RUBY
@source = source
- @specification = nil
+ @force_ruby_platform = default_force_ruby_platform
end
def full_name
- if platform == Gem::Platform::RUBY || platform.nil?
+ @full_name ||= if platform == Gem::Platform::RUBY
"#{@name}-#{@version}"
else
"#{@name}-#{@version}-#{platform}"
@@ -27,25 +28,41 @@ module Bundler
end
def ==(other)
- identifier == other.identifier
+ full_name == other.full_name
end
def eql?(other)
- identifier.eql?(other.identifier)
+ full_name.eql?(other.full_name)
end
def hash
- identifier.hash
+ full_name.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
out = String.new
- if platform == Gem::Platform::RUBY || platform.nil?
+ if platform == Gem::Platform::RUBY
out << " #{name} (#{version})\n"
else
out << " #{name} (#{version}-#{platform})\n"
@@ -59,76 +76,74 @@ module Bundler
out
end
- def __materialize__
- @specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name
- source.gemspec.tap {|s| s.source = source }
+ def materialize_for_installation
+ source.local!
+
+ matching_specs = source.specs.search(use_exact_resolved_specifications? ? self : [name, version])
+ return self if matching_specs.empty?
+
+ candidates = if use_exact_resolved_specifications?
+ matching_specs
else
- 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))
+ target_platform = ruby_platform_materializes_to_ruby_platform? ? platform : local_platform
+
+ installable_candidates = GemHelpers.select_best_platform_match(matching_specs, target_platform)
+
+ specification = __materialize__(installable_candidates, :fallback_to_non_installable => false)
+ return specification unless specification.nil?
+
+ if target_platform != platform
+ installable_candidates = GemHelpers.select_best_platform_match(matching_specs, platform)
end
- search = installable_candidates.last || same_platform_candidates.last
- search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
- search
+
+ installable_candidates
end
+
+ __materialize__(candidates)
end
- def respond_to?(*args)
- super || @specification ? @specification.respond_to?(*args) : nil
+ # If in frozen mode, we fallback to a non-installable candidate because by
+ # doing this we avoid re-resolving and potentially end up changing the
+ # lock file, which is not allowed. In that case, we will give a proper error
+ # about the mismatch higher up the stack, right before trying to install the
+ # bad gem.
+ def __materialize__(candidates, fallback_to_non_installable: Bundler.frozen_bundle?)
+ search = candidates.reverse.find do |spec|
+ spec.is_a?(StubSpecification) ||
+ (spec.matches_current_ruby? &&
+ spec.matches_current_rubygems?)
+ end
+ if search.nil? && fallback_to_non_installable
+ search = candidates.last
+ else
+ search.dependencies = dependencies if search && search.full_name == full_name && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
+ end
+ search
end
def to_s
- @__to_s ||= if platform == Gem::Platform::RUBY || platform.nil?
+ @to_s ||= if platform == Gem::Platform::RUBY
"#{name} (#{version})"
else
"#{name} (#{version}-#{platform})"
end
end
- def identifier
- @__identifier ||= [name, version, platform_string]
- end
-
def git_version
return unless source.is_a?(Bundler::Source::Git)
" #{source.revision[0..6]}"
end
- protected
-
- def platform_string
- platform_string = platform.to_s
- platform_string == Index::RUBY ? Index::NULL : platform_string
- end
-
private
- def to_ary
- nil
- end
-
- def method_missing(method, *args, &blk)
- raise "LazySpecification has not been materialized yet (calling :#{method} #{args.inspect})" unless @specification
-
- return super unless respond_to?(method)
-
- @specification.send(method, *args, &blk)
+ def use_exact_resolved_specifications?
+ @use_exact_resolved_specifications ||= !source.is_a?(Source::Path) && ruby_platform_materializes_to_ruby_platform?
end
#
# For backwards compatibility with existing lockfiles, if the most specific
- # locked platform is RUBY, we keep the previous behaviour of resolving the
+ # locked platform is not a specific platform like x86_64-linux or
+ # universal-java-11, then we keep the previous behaviour of resolving the
# best platform variant at materiliazation time. For previous bundler
# versions (before 2.2.0) this was always the case (except when the lockfile
# only included non-ruby platforms), but we're also keeping this behaviour
@@ -136,7 +151,9 @@ module Bundler
# 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]
+ generic_platform = generic_local_platform == Gem::Platform::JAVA ? Gem::Platform::JAVA : Gem::Platform::RUBY
+
+ !Bundler.most_specific_locked_platform?(generic_platform) || force_ruby_platform || Bundler.settings[:force_ruby_platform]
end
end
end
diff --git a/lib/bundler/lockfile_generator.rb b/lib/bundler/lockfile_generator.rb
index 3bc6bd7339..f7ba51b3e6 100644
--- a/lib/bundler/lockfile_generator.rb
+++ b/lib/bundler/lockfile_generator.rb
@@ -45,7 +45,7 @@ module Bundler
# gems with the same name, but different platform
# are ordered consistently
specs.sort_by(&:full_name).each do |spec|
- next if spec.name == "bundler".freeze
+ next if spec.name == "bundler"
out << spec.to_lock
end
end
@@ -60,7 +60,7 @@ module Bundler
handled = []
definition.dependencies.sort_by(&:to_s).each do |dep|
next if handled.include?(dep.name)
- out << dep.to_lock
+ out << dep.to_lock << "\n"
handled << dep.name
end
end
@@ -71,7 +71,7 @@ module Bundler
end
def add_bundled_with
- add_section("BUNDLED WITH", definition.locked_bundler_version.to_s)
+ add_section("BUNDLED WITH", definition.bundler_version_to_lock.to_s)
end
def add_section(name, value)
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index afc21fd006..7360a36752 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -4,15 +4,15 @@ module Bundler
class LockfileParser
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version
- BUNDLED = "BUNDLED WITH".freeze
- DEPENDENCIES = "DEPENDENCIES".freeze
- PLATFORMS = "PLATFORMS".freeze
- RUBY = "RUBY VERSION".freeze
- GIT = "GIT".freeze
- GEM = "GEM".freeze
- PATH = "PATH".freeze
- PLUGIN = "PLUGIN SOURCE".freeze
- SPECS = " specs:".freeze
+ BUNDLED = "BUNDLED WITH"
+ DEPENDENCIES = "DEPENDENCIES"
+ PLATFORMS = "PLATFORMS"
+ RUBY = "RUBY VERSION"
+ GIT = "GIT"
+ GEM = "GEM"
+ PATH = "PATH"
+ PLUGIN = "PLUGIN SOURCE"
+ SPECS = " specs:"
OPTIONS = /^ ([a-z]+): (.*)$/i.freeze
SOURCE = [GIT, GEM, PATH, PLUGIN].freeze
@@ -26,6 +26,7 @@ module Bundler
KNOWN_SECTIONS = SECTIONS_BY_VERSION_INTRODUCED.values.flatten.freeze
ENVIRONMENT_VERSION_SECTIONS = [BUNDLED, RUBY].freeze
+ deprecate_constant(:ENVIRONMENT_VERSION_SECTIONS)
def self.sections_in_lockfile(lockfile_contents)
lockfile_contents.scan(/^\w[\w ]*$/).uniq
@@ -46,6 +47,16 @@ module Bundler
attributes
end
+ def self.bundled_with
+ lockfile = Bundler.default_lockfile
+ return unless lockfile.file?
+
+ lockfile_contents = Bundler.read_file(lockfile)
+ return unless lockfile_contents.include?(BUNDLED)
+
+ lockfile_contents.split(BUNDLED).last.strip
+ end
+
def initialize(lockfile)
@platforms = []
@sources = []
@@ -53,7 +64,7 @@ module Bundler
@state = nil
@specs = {}
- if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
+ 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."
end
@@ -70,37 +81,29 @@ module Bundler
@state = :ruby
elsif line == BUNDLED
@state = :bundled_with
- elsif line =~ /^[^\s]/
+ elsif /^[^\s]/.match?(line)
@state = nil
elsif @state
send("parse_#{@state}", line)
end
end
- @specs = @specs.values.sort_by(&:identifier)
- warn_for_outdated_bundler_version
+ @specs = @specs.values.sort_by(&:full_name)
rescue ArgumentError => e
Bundler.ui.debug(e)
raise LockfileError, "Your lockfile is unreadable. Run `rm #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` " \
"and then `bundle install` to generate a new lockfile."
end
- def warn_for_outdated_bundler_version
- return unless bundler_version
- prerelease_text = bundler_version.prerelease? ? " --pre" : ""
- current_version = Gem::Version.create(Bundler::VERSION)
- return unless current_version < bundler_version
- Bundler.ui.warn "Warning: the running version of Bundler (#{current_version}) is older " \
- "than the version that created the lockfile (#{bundler_version}). We suggest you to " \
- "upgrade to the version that created the lockfile by running `gem install " \
- "bundler:#{bundler_version}#{prerelease_text}`.\n"
+ def may_include_redundant_platform_specific_gems?
+ bundler_version.nil? || bundler_version < Gem::Version.new("1.16.2")
end
private
TYPES = {
- GIT => Bundler::Source::Git,
- GEM => Bundler::Source::Rubygems,
- PATH => Bundler::Source::Path,
+ GIT => Bundler::Source::Git,
+ GEM => Bundler::Source::Rubygems,
+ PATH => Bundler::Source::Path,
PLUGIN => Bundler::Plugin,
}.freeze
@@ -195,8 +198,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)
- @specs[@current_spec.identifier] = @current_spec
+ @specs[@current_spec.full_name] = @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/bundle-add.1 b/lib/bundler/man/bundle-add.1
index 4945747f42..8549855b0d 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,13 +1,13 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-ADD" "1" "June 2021" "" ""
+.TH "BUNDLE\-ADD" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
.
.SH "SYNOPSIS"
-\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-git=GIT] [\-\-branch=BRANCH] [\-\-skip\-install] [\-\-strict] [\-\-optimistic]
+\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-path=PATH] [\-\-git=GIT] [\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-skip\-install] [\-\-strict] [\-\-optimistic]
.
.SH "DESCRIPTION"
Adds the named gem to the Gemfile and run \fBbundle install\fR\. \fBbundle install\fR can be avoided by using the flag \fB\-\-skip\-install\fR\.
@@ -41,26 +41,42 @@ Specify version requirements(s) for the added gem\.
Specify the group(s) for the added gem\. Multiple groups should be separated by commas\.
.
.TP
-\fB\-\-source\fR, , \fB\-s\fR
+\fB\-\-source\fR, \fB\-s\fR
Specify the source for the added gem\.
.
.TP
+\fB\-\-require\fR, \fB\-r\fR
+Adds require path to gem\. Provide false, or a path as a string\.
+.
+.TP
+\fB\-\-path\fR
+Specify the file system path for the added gem\.
+.
+.TP
\fB\-\-git\fR
Specify the git source for the added gem\.
.
.TP
+\fB\-\-github\fR
+Specify the github source for the added gem\.
+.
+.TP
\fB\-\-branch\fR
Specify the git branch for the added gem\.
.
.TP
+\fB\-\-ref\fR
+Specify the git ref for the added gem\.
+.
+.TP
\fB\-\-skip\-install\fR
Adds the gem to the Gemfile but does not install it\.
.
.TP
\fB\-\-optimistic\fR
-Adds optimistic declaration of version
+Adds optimistic declaration of version\.
.
.TP
\fB\-\-strict\fR
-Adds strict declaration of version
+Adds strict declaration of version\.
diff --git a/lib/bundler/man/bundle-add.1.ronn b/lib/bundler/man/bundle-add.1.ronn
index 26cbe55647..37c92e5fcd 100644
--- a/lib/bundler/man/bundle-add.1.ronn
+++ b/lib/bundler/man/bundle-add.1.ronn
@@ -3,7 +3,7 @@ bundle-add(1) -- 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]
+`bundle add` <GEM_NAME> [--group=GROUP] [--version=VERSION] [--source=SOURCE] [--path=PATH] [--git=GIT] [--github=GITHUB] [--branch=BRANCH] [--ref=REF] [--skip-install] [--strict] [--optimistic]
## DESCRIPTION
Adds the named gem to the Gemfile and run `bundle install`. `bundle install` can be avoided by using the flag `--skip-install`.
@@ -27,20 +27,32 @@ bundle add rails --group "development, test"
* `--group`, `-g`:
Specify the group(s) for the added gem. Multiple groups should be separated by commas.
-* `--source`, , `-s`:
+* `--source`, `-s`:
Specify the source for the added gem.
+* `--require`, `-r`:
+ Adds require path to gem. Provide false, or a path as a string.
+
+* `--path`:
+ Specify the file system path for the added gem.
+
* `--git`:
Specify the git source for the added gem.
+* `--github`:
+ Specify the github source for the added gem.
+
* `--branch`:
Specify the git branch for the added gem.
+* `--ref`:
+ Specify the git ref for the added gem.
+
* `--skip-install`:
Adds the gem to the Gemfile but does not install it.
* `--optimistic`:
- Adds optimistic declaration of version
+ Adds optimistic declaration of version.
* `--strict`:
- Adds strict declaration of version
+ Adds strict declaration of version.
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index dd43180b19..40c338916a 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-BINSTUBS" "1" "June 2021" "" ""
+.TH "BUNDLE\-BINSTUBS" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index 22ce1dfc76..69b1e1e3dd 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CACHE" "1" "June 2021" "" ""
+.TH "BUNDLE\-CACHE" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
@@ -9,8 +9,11 @@
.SH "SYNOPSIS"
\fBbundle cache\fR
.
+.P
+alias: \fBpackage\fR, \fBpack\fR
+.
.SH "DESCRIPTION"
-Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running [bundle install(1)][bundle\-install], use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
+Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR, use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
.
.SH "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\.
@@ -19,7 +22,7 @@ The \fBbundle cache\fR command can also package \fB:git\fR and \fB:path\fR depen
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\.
+By default, if you run \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR 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):
@@ -53,3 +56,6 @@ One way to be sure that you have the right platformed versions of all your gems
.
.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\.
+.
+.SH "HISTORY"
+In Bundler 2\.1, \fBcache\fR took in the functionalities of \fBpackage\fR and now \fBpackage\fR and \fBpack\fR are aliases of \fBcache\fR\.
diff --git a/lib/bundler/man/bundle-cache.1.ronn b/lib/bundler/man/bundle-cache.1.ronn
index 383adb2ba3..8112c2c551 100644
--- a/lib/bundler/man/bundle-cache.1.ronn
+++ b/lib/bundler/man/bundle-cache.1.ronn
@@ -5,10 +5,12 @@ bundle-cache(1) -- Package your needed `.gem` files into your application
`bundle cache`
+alias: `package`, `pack`
+
## 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],
+`vendor/cache` directory. In the future, when running [`bundle install(1)`](bundle-install.1.html),
use the gems in the cache in preference to the ones on `rubygems.org`.
## GIT AND PATH GEMS
@@ -27,7 +29,7 @@ bundler configuration.
## REMOTE FETCHING
-By default, if you run `bundle install(1)`](bundle-install.1.html) after running
+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`.
@@ -70,3 +72,8 @@ 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`.
+
+## HISTORY
+
+In Bundler 2.1, `cache` took in the functionalities of `package` and now
+`package` and `pack` are aliases of `cache`.
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index 6e1b38ab05..748a37e7d1 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CHECK" "1" "June 2021" "" ""
+.TH "BUNDLE\-CHECK" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index eb658e1c73..af8f13cd89 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CLEAN" "1" "June 2021" "" ""
+.TH "BUNDLE\-CLEAN" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
@@ -20,5 +20,5 @@ 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\.
+Forces cleaning up unused gems even if Bundler is configured to use globally installed gems\. As a consequence, removes all system gems except for the ones in the current application\.
diff --git a/lib/bundler/man/bundle-clean.1.ronn b/lib/bundler/man/bundle-clean.1.ronn
index de23991782..dae27c21ee 100644
--- a/lib/bundler/man/bundle-clean.1.ronn
+++ b/lib/bundler/man/bundle-clean.1.ronn
@@ -15,4 +15,4 @@ useful when you have made many changes to your gem dependencies.
* `--dry-run`:
Print the changes, but do not clean the unused gems.
* `--force`:
- Force a clean even if `--path` is not set.
+ Forces cleaning up unused gems even if Bundler is configured to use globally installed gems. As a consequence, removes all system gems except for the ones in the current application.
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 323fcc8121..4442f33105 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,13 +1,22 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CONFIG" "1" "June 2021" "" ""
+.TH "BUNDLE\-CONFIG" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
.
.SH "SYNOPSIS"
-\fBbundle config\fR [list|get|set|unset] [\fIname\fR [\fIvalue\fR]]
+\fBbundle config\fR list
+.
+.br
+\fBbundle config\fR [get] NAME
+.
+.br
+\fBbundle config\fR [set] NAME VALUE
+.
+.br
+\fBbundle config\fR unset NAME
.
.SH "DESCRIPTION"
This command allows you to interact with Bundler\'s configuration system\.
@@ -30,19 +39,19 @@ 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\.
+Executing \fBbundle config list\fR 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\.
+Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\.
.
.P
-Executing \fBbundle config set \-\-global <name> <value>\fR works the same as above\.
+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 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\.
+Executing \fBbundle config set \-\-global <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
.
.P
Executing \fBbundle config unset <name>\fR will delete the configuration in both local and global sources\.
@@ -51,7 +60,7 @@ Executing \fBbundle config unset <name>\fR will delete the configuration in both
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\.
+Executing \fBbundle config unset \-\-local <name>\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\.
@@ -74,6 +83,10 @@ Creates a directory (defaults to \fB~/bin\fR) and place any executables from the
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
+\fBonly\fR
+A space\-separated list of groups to install only gems of the specified groups\.
+.
+.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\.
.
@@ -83,7 +96,7 @@ 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\.
+A space\-separated list of \fBoptional\fR 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\.
@@ -205,13 +218,16 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBglobal_gem_cache\fR (\fBBUNDLE_GLOBAL_GEM_CACHE\fR): Whether Bundler should cache all gems globally, rather than locally to the installing Ruby installation\.
.
.IP "\(bu" 4
+\fBignore_funding_requests\fR (\fBBUNDLE_IGNORE_FUNDING_REQUESTS\fR): When set, no funding requests will be printed\.
+.
+.IP "\(bu" 4
\fBignore_messages\fR (\fBBUNDLE_IGNORE_MESSAGES\fR): When set, no post install messages will be printed\. To silence a single gem, use dot notation like \fBignore_messages\.httparty true\fR\.
.
.IP "\(bu" 4
\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR): Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
.
.IP "\(bu" 4
-\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to 1 on Windows, and to the the number of processors on other platforms\.
+\fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can install in parallel\. Defaults to the number of available processors\.
.
.IP "\(bu" 4
\fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR): Whether \fBbundle package\fR should skip installing gems\.
@@ -220,6 +236,9 @@ The following is a list of all configuration keys and their purpose\. You can le
\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\.
.
.IP "\(bu" 4
+\fBonly\fR (\fBBUNDLE_ONLY\fR): A space\-separated list of groups to install only gems of the specified groups\.
+.
+.IP "\(bu" 4
\fBpath\fR (\fBBUNDLE_PATH\fR): The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. Defaults to \fBGem\.dir\fR\. When \-\-deployment is used, defaults to vendor/bundle\.
.
.IP "\(bu" 4
@@ -265,9 +284,6 @@ The following is a list of all configuration keys and their purpose\. You can le
\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
@@ -288,7 +304,7 @@ The following is a list of all configuration keys and their purpose\. You can le
.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\.
+In general, you should set these settings per\-application by using the applicable flag to the bundle install(1) \fIbundle\-install\.1\.html\fR or bundle cache(1) \fIbundle\-cache\.1\.html\fR command\.
.
.P
You can set them globally either via environment variables or \fBbundle config\fR, whichever is preferable for your setup\. If you use both, environment variables will take preference over global settings\.
@@ -342,13 +358,13 @@ bundle config set \-\-global mirror\.SOURCE_URL MIRROR_URL
.IP "" 0
.
.P
-For example, to use a mirror of rubygems\.org hosted at rubygems\-mirror\.org:
+For example, to use a mirror of https://rubygems\.org hosted at https://example\.org:
.
.IP "" 4
.
.nf
-bundle config set \-\-global mirror\.http://rubygems\.org http://rubygems\-mirror\.org
+bundle config set \-\-global mirror\.https://rubygems\.org https://example\.org
.
.fi
.
@@ -462,13 +478,13 @@ export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x\-oauth\-basic
.IP "" 0
.
.P
-Note that any configured credentials will be redacted by informative commands such as \fBbundle config list\fR or \fBbundle config get\fR, unless you use the \fB\-\-parseable\fR flag\. This is to avoid unintentially leaking credentials when copy\-pasting bundler output\.
+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 enviroment variable\.
+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\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index 05ba0dc255..adc273ec62 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -3,7 +3,10 @@ bundle-config(1) -- Set bundler configuration options
## SYNOPSIS
-`bundle config` [list|get|set|unset] [<name> [<value>]]
+`bundle config` list<br>
+`bundle config` [get] NAME<br>
+`bundle config` [set] NAME VALUE<br>
+`bundle config` unset NAME
## DESCRIPTION
@@ -16,33 +19,35 @@ Bundler loads configuration settings in this order:
3. Global config (`~/.bundle/config`)
4. Bundler default config
-Executing `bundle config list` with will print a list of all bundler
+Executing `bundle config list` will print a list of all bundler
configuration for the current bundle, and where that configuration
was set.
Executing `bundle config get <name>` will print the value of that configuration
setting, and where it was set.
-Executing `bundle config set <name> <value>` 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 <name> <value>` defaults to setting `local`
+configuration if executing from within a local application, otherwise it will
+set `global` configuration. See `--local` and `--global` options below.
Executing `bundle config set --local <name> <value>` will set that configuration
in the directory for the local application. The configuration will be stored in
`<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
will be stored in `$BUNDLE_APP_CONFIG/config`.
+Executing `bundle config set --global <name> <value>` will set that
+configuration to the value specified for all bundles executed as the current
+user. The configuration will be stored in `~/.bundle/config`. If <name> already
+is set, <name> will be overridden and user will be warned.
+
Executing `bundle config unset <name>` will delete the configuration in both
local and global sources.
Executing `bundle config unset --global <name>` will delete the configuration
only from the user configuration.
-Executing `bundle config unset --local <name> <value>` will delete the
-configuration only from the local application.
+Executing `bundle config unset --local <name>` will delete the configuration
+only from the local application.
Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
cause it to ignore all configuration.
@@ -72,6 +77,9 @@ The options that can be configured are:
`production` use. Please check carefully if you want to have this option
enabled in `development` or `test` environments.
+* `only`:
+ A space-separated list of groups to install only gems of the specified groups.
+
* `path`:
The location to install the specified gems to. This defaults to Rubygems'
setting. Bundler shares this location with Rubygems, `gem install ...` will
@@ -83,7 +91,7 @@ The options that can be configured are:
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.
+ A space-separated list of **optional** groups referencing gems to include during installation.
## BUILD OPTIONS
@@ -202,18 +210,22 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `global_gem_cache` (`BUNDLE_GLOBAL_GEM_CACHE`):
Whether Bundler should cache all gems globally, rather than locally to the
installing Ruby installation.
+* `ignore_funding_requests` (`BUNDLE_IGNORE_FUNDING_REQUESTS`):
+ When set, no funding requests will be printed.
* `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.
+ The number of gems Bundler can install in parallel. Defaults to the number of
+ available processors.
* `no_install` (`BUNDLE_NO_INSTALL`):
Whether `bundle package` should skip installing gems.
* `no_prune` (`BUNDLE_NO_PRUNE`):
Whether Bundler should leave outdated gems unpruned when caching.
+* `only` (`BUNDLE_ONLY`):
+ A space-separated list of groups to install only gems of the specified groups.
* `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
@@ -253,9 +265,6 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `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`):
@@ -271,7 +280,7 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
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.
+flag to the [bundle install(1)](bundle-install.1.html) or [bundle cache(1)](bundle-cache.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
@@ -319,9 +328,9 @@ 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:
+For example, to use a mirror of https://rubygems.org hosted at https://example.org:
- bundle config set --global mirror.http://rubygems.org http://rubygems-mirror.org
+ bundle config set --global mirror.https://rubygems.org https://example.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
@@ -367,14 +376,14 @@ where you can use personal OAuth tokens:
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 unintentially leaking credentials when
+`--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 enviroment variable.
+ corresponding environment variable.
* Any `.` characters in a host name are mapped to a double dash (`__`) in the
corresponding environment variable.
diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1
new file mode 100644
index 0000000000..24fff46cec
--- /dev/null
+++ b/lib/bundler/man/bundle-console.1
@@ -0,0 +1,53 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-CONSOLE" "1" "August 2023" "" ""
+.
+.SH "NAME"
+\fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded
+.
+.SH "SYNOPSIS"
+\fBbundle console\fR [GROUP]
+.
+.SH "DESCRIPTION"
+Starts an interactive Ruby console session in the context of the current bundle\.
+.
+.P
+If no \fBGROUP\fR is specified, all gems in the \fBdefault\fR group in the Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR are preliminarily loaded\.
+.
+.P
+If \fBGROUP\fR is specified, all gems in the given group in the Gemfile in addition to the gems in \fBdefault\fR group are loaded\. Even if the given group does not exist in the Gemfile, IRB console starts without any warning or error\.
+.
+.P
+The environment variable \fBBUNDLE_CONSOLE\fR or \fBbundle config set console\fR can be used to change the shell from the following:
+.
+.IP "\(bu" 4
+\fBirb\fR (default)
+.
+.IP "\(bu" 4
+\fBpry\fR (https://github\.com/pry/pry)
+.
+.IP "\(bu" 4
+\fBripl\fR (https://github\.com/cldwalker/ripl)
+.
+.IP "" 0
+.
+.P
+\fBbundle console\fR uses irb by default\. An alternative Pry or Ripl can be used with \fBbundle console\fR by adjusting the \fBconsole\fR Bundler setting\. Also make sure that \fBpry\fR or \fBripl\fR is in your Gemfile\.
+.
+.SH "EXAMPLE"
+.
+.nf
+
+$ bundle config set console pry
+$ bundle console
+Resolving dependencies\.\.\.
+[1] pry(main)>
+.
+.fi
+.
+.SH "NOTES"
+This command was deprecated in Bundler 2\.1 and will be removed in 3\.0\. Use \fBbin/console\fR script, which can be generated by \fBbundle gem <NAME>\fR\.
+.
+.SH "SEE ALSO"
+Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR
diff --git a/lib/bundler/man/bundle-console.1.ronn b/lib/bundler/man/bundle-console.1.ronn
new file mode 100644
index 0000000000..f9096d386a
--- /dev/null
+++ b/lib/bundler/man/bundle-console.1.ronn
@@ -0,0 +1,44 @@
+bundle-console(1) -- Deprecated way to open an IRB session with the bundle pre-loaded
+=====================================================================================
+
+## SYNOPSIS
+
+`bundle console` [GROUP]
+
+## DESCRIPTION
+
+Starts an interactive Ruby console session in the context of the current bundle.
+
+If no `GROUP` is specified, all gems in the `default` group in the [Gemfile(5)](https://bundler.io/man/gemfile.5.html) are
+preliminarily loaded.
+
+If `GROUP` is specified, all gems in the given group in the Gemfile in addition
+to the gems in `default` group are loaded. Even if the given group does not
+exist in the Gemfile, IRB console starts without any warning or error.
+
+The environment variable `BUNDLE_CONSOLE` or `bundle config set console` can be used to change
+the shell from the following:
+
+* `irb` (default)
+* `pry` (https://github.com/pry/pry)
+* `ripl` (https://github.com/cldwalker/ripl)
+
+`bundle console` uses irb by default. An alternative Pry or Ripl can be used with
+`bundle console` by adjusting the `console` Bundler setting. Also make sure that
+`pry` or `ripl` is in your Gemfile.
+
+## EXAMPLE
+
+ $ bundle config set console pry
+ $ bundle console
+ Resolving dependencies...
+ [1] pry(main)>
+
+## NOTES
+
+This command was deprecated in Bundler 2.1 and will be removed in 3.0.
+Use `bin/console` script, which can be generated by `bundle gem <NAME>`.
+
+## SEE ALSO
+
+[Gemfile(5)](https://bundler.io/man/gemfile.5.html)
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index 84d1f4c9df..57da8216cb 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-DOCTOR" "1" "June 2021" "" ""
+.TH "BUNDLE\-DOCTOR" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index b3c60fbbfd..852788db7a 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-EXEC" "1" "June 2021" "" ""
+.TH "BUNDLE\-EXEC" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
@@ -74,13 +74,13 @@ Finally, \fBbundle exec\fR also implicitly modifies \fBGemfile\.lock\fR if the l
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:
+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_unbundled_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
+Bundler\.with_unbundled_env do
`brew install wget`
end
.
@@ -89,13 +89,13 @@ end
.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\.
+Using \fBwith_unbundled_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_unbundled_env\fR\.
.
.IP "" 4
.
.nf
-Bundler\.with_clean_env do
+Bundler\.with_unbundled_env do
Dir\.chdir "/other/bundler/project" do
`bundle exec \./script`
end
@@ -155,7 +155,7 @@ You can find a list of all the gems containing gem plugins by running
.
.nf
-ruby \-rrubygems \-e "puts Gem\.find_files(\'rubygems_plugin\.rb\')"
+ruby \-e "puts Gem\.find_files(\'rubygems_plugin\.rb\')"
.
.fi
.
diff --git a/lib/bundler/man/bundle-exec.1.ronn b/lib/bundler/man/bundle-exec.1.ronn
index dec3c7cb82..05948095e2 100644
--- a/lib/bundler/man/bundle-exec.1.ronn
+++ b/lib/bundler/man/bundle-exec.1.ronn
@@ -84,20 +84,20 @@ the `disable_exec_load` setting.
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
+`with_unbundled_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
+ Bundler.with_unbundled_env do
`brew install wget`
end
-Using `with_clean_env` is also necessary if you are shelling out to a different
+Using `with_unbundled_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`.
+need to use `with_unbundled_env`.
- Bundler.with_clean_env do
+ Bundler.with_unbundled_env do
Dir.chdir "/other/bundler/project" do
`bundle exec ./script`
end
@@ -145,7 +145,7 @@ 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')"
+ ruby -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
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 3f711c2bed..8339b727ce 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-GEM" "1" "June 2021" "" ""
+.TH "BUNDLE\-GEM" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
@@ -31,41 +31,32 @@ The generated project skeleton can be customized with OPTIONS, as explained belo
.
.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\.
+.IP "\(bu" 4
+\fB\-\-exe\fR or \fB\-b\fR or \fB\-\-bin\fR: Specify that Bundler should create a binary executable (as \fBexe/GEM_NAME\fR) in the generated rubygem project\. This binary will also be added to the \fBGEM_NAME\.gemspec\fR manifest\. This behavior is disabled by default\.
.
-.TP
-\fB\-\-no\-exe\fR
-Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\.
+.IP "\(bu" 4
+\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\.
+.IP "\(bu" 4
+\fB\-\-coc\fR: Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
.
-.TP
-\fB\-\-no\-coc\fR
-Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\.
+.IP "\(bu" 4
+\fB\-\-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\.
+.IP "\(bu" 4
+\fB\-\-ext=c\fR, \fB\-\-ext=rust\fR Add boilerplate for C or Rust (currently magnus \fIhttps://docs\.rs/magnus\fR based) extension code to the generated project\. This behavior is disabled by default\.
.
-.TP
-\fB\-\-no\-ext\fR
-Do not add C extension code (overrides \fB\-\-ext\fR specified in the global config)\.
+.IP "\(bu" 4
+\fB\-\-no\-ext\fR: Do not add 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\.
+.IP "\(bu" 4
+\fB\-\-mit\fR: Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
.
-.TP
-\fB\-\-no\-mit\fR
-Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\.
+.IP "\(bu" 4
+\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 "\(bu" 4
+\fB\-t\fR, \fB\-\-test=minitest\fR, \fB\-\-test=rspec\fR, \fB\-\-test=test\-unit\fR: Specify the test framework that Bundler should use when generating the project\. Acceptable values are \fBminitest\fR, \fBrspec\fR and \fBtest\-unit\fR\. The \fBGEM_NAME\.gemspec\fR will be configured and a skeleton test/spec directory will be created based on this option\. Given no option is specified:
.
.IP
When Bundler is configured to generate tests, this defaults to Bundler\'s global config setting \fBgem\.test\fR\.
@@ -76,9 +67,8 @@ When Bundler is configured to not generate tests, an interactive prompt will be
.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 "\(bu" 4
+\fB\-\-ci\fR, \fB\-\-ci=github\fR, \fB\-\-ci=gitlab\fR, \fB\-\-ci=circle\fR: Specify the continuous integration service that Bundler should use when generating the project\. Acceptable values are \fBgithub\fR, \fBgitlab\fR and \fBcircle\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
.
.IP
When Bundler is configured to generate CI files, this defaults to Bundler\'s global config setting \fBgem\.ci\fR\.
@@ -89,9 +79,8 @@ When Bundler is configured to not generate CI files, an interactive prompt will
.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 "\(bu" 4
+\fB\-\-linter\fR, \fB\-\-linter=rubocop\fR, \fB\-\-linter=standard\fR: Specify the linter and code formatter that Bundler should add to the project\'s development dependencies\. Acceptable values are \fBrubocop\fR and \fBstandard\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
.
.IP
When Bundler is configured to add a linter, this defaults to Bundler\'s global config setting \fBgem\.linter\fR\.
@@ -102,9 +91,10 @@ When Bundler is configured not to add a linter, an interactive prompt will be di
.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\.
+.IP "\(bu" 4
+\fB\-e\fR, \fB\-\-edit[=EDITOR]\fR: Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\.
+.
+.IP "" 0
.
.SH "SEE ALSO"
.
diff --git a/lib/bundler/man/bundle-gem.1.ronn b/lib/bundler/man/bundle-gem.1.ronn
index 61c741fb24..46fa2f179f 100644
--- a/lib/bundler/man/bundle-gem.1.ronn
+++ b/lib/bundler/man/bundle-gem.1.ronn
@@ -41,12 +41,12 @@ configuration file using the following names:
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
+* `--ext=c`, `--ext=rust`
+ Add boilerplate for C or Rust (currently [magnus](https://docs.rs/magnus) based) extension code to the generated project. This behavior
is disabled by default.
* `--no-ext`:
- Do not add C extension code (overrides `--ext` specified in the global
+ Do not add extension code (overrides `--ext` specified in the global
config).
* `--mit`:
@@ -76,9 +76,9 @@ configuration file using the following names:
the answer will be saved in Bundler's global config for future `bundle gem`
use.
-* `--ci`, `--ci=github`, `--ci=travis`, `--ci=gitlab`, `--ci=circle`:
+* `--ci`, `--ci=github`, `--ci=gitlab`, `--ci=circle`:
Specify the continuous integration service that Bundler should use when
- generating the project. Acceptable values are `github`, `travis`, `gitlab`
+ generating the project. Acceptable values are `github`, `gitlab`
and `circle`. A configuration file will be generated in the project directory.
Given no option is specified:
diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1
new file mode 100644
index 0000000000..9787c2d49f
--- /dev/null
+++ b/lib/bundler/man/bundle-help.1
@@ -0,0 +1,13 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-HELP" "1" "August 2023" "" ""
+.
+.SH "NAME"
+\fBbundle\-help\fR \- Displays detailed help for each subcommand
+.
+.SH "SYNOPSIS"
+\fBbundle help\fR [COMMAND]
+.
+.SH "DESCRIPTION"
+Displays detailed help for the given subcommand\. You can specify a single \fBCOMMAND\fR at the same time\. When \fBCOMMAND\fR is omitted, help for \fBhelp\fR command will be displayed\.
diff --git a/lib/bundler/man/bundle-help.1.ronn b/lib/bundler/man/bundle-help.1.ronn
new file mode 100644
index 0000000000..0e144aead7
--- /dev/null
+++ b/lib/bundler/man/bundle-help.1.ronn
@@ -0,0 +1,12 @@
+bundle-help(1) -- Displays detailed help for each subcommand
+============================================================
+
+## SYNOPSIS
+
+`bundle help` [COMMAND]
+
+## DESCRIPTION
+
+Displays detailed help for the given subcommand.
+You can specify a single `COMMAND` at the same time.
+When `COMMAND` is omitted, help for `help` command will be displayed.
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index 337e7bdd38..2cced71520 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,16 +1,16 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INFO" "1" "June 2021" "" ""
+.TH "BUNDLE\-INFO" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
.
.SH "SYNOPSIS"
-\fBbundle info\fR [GEM] [\-\-path]
+\fBbundle info\fR [GEM_NAME] [\-\-path]
.
.SH "DESCRIPTION"
-Print the basic information about the provided GEM such as homepage, version, path and summary\.
+Given a gem name present in your bundle, print the basic information about it such as homepage, version, path and summary\.
.
.SH "OPTIONS"
.
diff --git a/lib/bundler/man/bundle-info.1.ronn b/lib/bundler/man/bundle-info.1.ronn
index 47e457aa3c..cecdeb564f 100644
--- a/lib/bundler/man/bundle-info.1.ronn
+++ b/lib/bundler/man/bundle-info.1.ronn
@@ -3,13 +3,13 @@ bundle-info(1) -- Show information for the given gem in your bundle
## SYNOPSIS
-`bundle info` [GEM]
+`bundle info` [GEM_NAME]
[--path]
## DESCRIPTION
-Print the basic information about the provided GEM such as homepage, version,
-path and summary.
+Given a gem name present in your bundle, print the basic information about it
+ such as homepage, version, path and summary.
## OPTIONS
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index 0c5b8c7a39..c7a9a155b5 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INIT" "1" "June 2021" "" ""
+.TH "BUNDLE\-INIT" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
@@ -18,6 +18,10 @@ Init generates a default [\fBGemfile(5)\fR][Gemfile(5)] in the current working d
\fB\-\-gemspec\fR
Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)]
.
+.TP
+\fB\-\-gemfile\fR
+Use the specified name for the gemfile instead of \fBGemfile\fR
+.
.SH "FILES"
Included in the default [\fBGemfile(5)\fR][Gemfile(5)] generated is the line \fB# frozen_string_literal: true\fR\. This is a magic comment supported for the first time in Ruby 2\.3\. The presence of this line results in all string literals in the file being implicitly frozen\.
.
diff --git a/lib/bundler/man/bundle-init.1.ronn b/lib/bundler/man/bundle-init.1.ronn
index 9d3d97deea..7d3cede1f6 100644
--- a/lib/bundler/man/bundle-init.1.ronn
+++ b/lib/bundler/man/bundle-init.1.ronn
@@ -16,6 +16,8 @@ created [`Gemfile(5)`][Gemfile(5)].
* `--gemspec`:
Use the specified .gemspec to create the [`Gemfile(5)`][Gemfile(5)]
+* `--gemfile`:
+ Use the specified name for the gemfile instead of `Gemfile`
## FILES
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
index f228ed247f..9e25c29085 100644
--- a/lib/bundler/man/bundle-inject.1
+++ b/lib/bundler/man/bundle-inject.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INJECT" "1" "June 2021" "" ""
+.TH "BUNDLE\-INJECT" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
@@ -30,4 +30,7 @@ bundle inject \'rack\' \'> 0\'
.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
+This will inject the \'rack\' gem with a version greater than 0 in your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock\.
+.
+.P
+The \fBbundle inject\fR command was deprecated in Bundler 2\.1 and will be removed in Bundler 3\.0\.
diff --git a/lib/bundler/man/bundle-inject.1.ronn b/lib/bundler/man/bundle-inject.1.ronn
index f454341896..95704eddad 100644
--- a/lib/bundler/man/bundle-inject.1.ronn
+++ b/lib/bundler/man/bundle-inject.1.ronn
@@ -19,4 +19,6 @@ Example:
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
+[`Gemfile(5)`][Gemfile(5)] and Gemfile.lock.
+
+The `bundle inject` command was deprecated in Bundler 2.1 and will be removed in Bundler 3.0.
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index ae9747bd83..337683af06 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INSTALL" "1" "June 2021" "" ""
+.TH "BUNDLE\-INSTALL" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
@@ -63,13 +63,17 @@ The location of the Gemfile(5) which Bundler should use\. This defaults to a Gem
.
.TP
\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
-The maximum number of parallel download and install jobs\. The default is \fB1\fR\.
+The maximum number of parallel download and install jobs\. The default is the number of available processors\.
.
.TP
\fB\-\-local\fR
Do not attempt to connect to \fBrubygems\.org\fR\. Instead, Bundler will use the gems already present in Rubygems\' cache or in \fBvendor/cache\fR\. Note that if an appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
.
.TP
+\fB\-\-prefer\-local\fR
+Force using locally installed gems, or gems already present in Rubygems\' cache or in \fBvendor/cache\fR, when resolving, even if newer versions are available remotely\. Only attempt to connect to \fBrubygems\.org\fR for gems that are not present locally\.
+.
+.TP
\fB\-\-no\-cache\fR
Do not update the cache in \fBvendor/cache\fR with the newly bundled gems\. This does not remove any gems in the cache but keeps the newly bundled gems from being cached during the install\.
.
@@ -166,35 +170,6 @@ As a result, \fBbundle install \-\-deployment\fR installs gems to the \fBvendor/
.
.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\.
.
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
index 5ea777f1d4..be9ed0f974 100644
--- a/lib/bundler/man/bundle-install.1.ronn
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -100,8 +100,8 @@ automatically and that requires `bundler` to silently remember them. Since
to this location.
* `--jobs=[<number>]`, `-j[<number>]`:
- The maximum number of parallel download and install jobs. The default
- is `1`.
+ The maximum number of parallel download and install jobs. The default is the
+ number of available processors.
* `--local`:
Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the
@@ -109,6 +109,12 @@ automatically and that requires `bundler` to silently remember them. Since
appropriate platform-specific gem exists on `rubygems.org` it will not be
found.
+* `--prefer-local`:
+ Force using locally installed gems, or gems already present in Rubygems' cache
+ or in `vendor/cache`, when resolving, even if newer versions are available
+ remotely. Only attempt to connect to `rubygems.org` for gems that are not
+ present locally.
+
* `--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
@@ -218,35 +224,6 @@ will cause an error when the Gemfile(5) is modified.
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
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index cce8881059..1680e6007a 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LIST" "1" "June 2021" "" ""
+.TH "BUNDLE\-LIST" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index 23388daaee..8722c44b3d 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LOCK" "1" "June 2021" "" ""
+.TH "BUNDLE\-LOCK" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index 8cc104b81d..3513f0d09b 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,13 +1,13 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OPEN" "1" "June 2021" "" ""
+.TH "BUNDLE\-OPEN" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
.
.SH "SYNOPSIS"
-\fBbundle open\fR [GEM]
+\fBbundle open\fR [GEM] [\-\-path=PATH]
.
.SH "DESCRIPTION"
Opens the source directory of the provided GEM in your editor\.
@@ -30,3 +30,23 @@ bundle open \'rack\'
.
.P
Will open the source directory for the \'rack\' gem in your bundle\.
+.
+.IP "" 4
+.
+.nf
+
+bundle open \'rack\' \-\-path \'README\.md\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Will open the README\.md file of the \'rack\' gem source in your bundle\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-path\fR
+Specify GEM source relative path to open\.
+
diff --git a/lib/bundler/man/bundle-open.1.ronn b/lib/bundler/man/bundle-open.1.ronn
index 497beac93f..a857f3a965 100644
--- a/lib/bundler/man/bundle-open.1.ronn
+++ b/lib/bundler/man/bundle-open.1.ronn
@@ -3,7 +3,7 @@ bundle-open(1) -- Opens the source directory for a gem in your bundle
## SYNOPSIS
-`bundle open` [GEM]
+`bundle open` [GEM] [--path=PATH]
## DESCRIPTION
@@ -17,3 +17,11 @@ Example:
bundle open 'rack'
Will open the source directory for the 'rack' gem in your bundle.
+
+ bundle open 'rack' --path 'README.md'
+
+Will open the README.md file of the 'rack' gem source in your bundle.
+
+## OPTIONS
+* `--path`:
+ Specify GEM source relative path to open.
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index bdd81a66af..129ff00f58 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,13 +1,13 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OUTDATED" "1" "June 2021" "" ""
+.TH "BUNDLE\-OUTDATED" "1" "August 2023" "" ""
.
.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]
+\fBbundle outdated\fR [GEM] [\-\-local] [\-\-pre] [\-\-source] [\-\-strict] [\-\-parseable | \-\-porcelain] [\-\-group=GROUP] [\-\-groups] [\-\-patch|\-\-minor|\-\-major] [\-\-filter\-major] [\-\-filter\-minor] [\-\-filter\-patch] [\-\-only\-explicit]
.
.SH "DESCRIPTION"
Outdated lists the names and versions of gems that have a newer version available in the given source\. Calling outdated with [GEM [GEM]] will only check for newer versions of the given gems\. Prerelease gems are ignored by default\. If your gems are up to date, Bundler will exit with a status of 0\. Otherwise, it will exit 1\.
@@ -28,7 +28,7 @@ Check against a specific source\.
.
.TP
\fB\-\-strict\fR
-Only list newer versions allowed by your Gemfile requirements\.
+Only list newer versions allowed by your Gemfile requirements, also respecting conservative update flags (\-\-patch, \-\-minor, \-\-major)\.
.
.TP
\fB\-\-parseable\fR, \fB\-\-porcelain\fR
@@ -43,10 +43,6 @@ List gems from a specific group\.
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\.
.
@@ -77,9 +73,6 @@ 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\.
.
@@ -90,9 +83,10 @@ If the regular output shows the following:
.
.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"
+* Gem Current Latest Requested Groups
+* faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
+* hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default
+* headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test
.
.fi
.
@@ -105,7 +99,8 @@ If the regular output shows the following:
.
.nf
-* hashie (newest 3\.4\.6, installed 1\.2\.0, requested = 1\.2\.0) in groups "default"
+* Gem Current Latest Requested Groups
+* hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default
.
.fi
.
@@ -118,7 +113,8 @@ If the regular output shows the following:
.
.nf
-* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
+* Gem Current Latest Requested Groups
+* headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test
.
.fi
.
@@ -131,7 +127,8 @@ If the regular output shows the following:
.
.nf
-* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
+* Gem Current Latest Requested Groups
+* faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
.
.fi
.
@@ -144,8 +141,8 @@ Filter options can be combined\. \fB\-\-filter\-minor\fR and \fB\-\-filter\-patc
.
.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"
+* Gem Current Latest Requested Groups
+* faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
.
.fi
.
diff --git a/lib/bundler/man/bundle-outdated.1.ronn b/lib/bundler/man/bundle-outdated.1.ronn
index a991d23789..27bf21ab9d 100644
--- a/lib/bundler/man/bundle-outdated.1.ronn
+++ b/lib/bundler/man/bundle-outdated.1.ronn
@@ -10,7 +10,6 @@ bundle-outdated(1) -- List installed gems with newer versions available
[--parseable | --porcelain]
[--group=GROUP]
[--groups]
- [--update-strict]
[--patch|--minor|--major]
[--filter-major]
[--filter-minor]
@@ -36,7 +35,7 @@ are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
Check against a specific source.
* `--strict`:
- Only list newer versions allowed by your Gemfile requirements.
+ Only list newer versions allowed by your Gemfile requirements, also respecting conservative update flags (--patch, --minor, --major).
* `--parseable`, `--porcelain`:
Use minimal formatting for more parseable output.
@@ -47,9 +46,6 @@ are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
* `--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.
@@ -75,11 +71,6 @@ are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
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
@@ -87,25 +78,28 @@ 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"
+ * Gem Current Latest Requested Groups
+ * faker 1.6.5 1.6.6 ~> 1.4 development, test
+ * hashie 1.2.0 3.4.6 = 1.2.0 default
+ * headless 2.2.3 2.3.1 = 2.2.3 test
`--filter-major` would only show:
- * hashie (newest 3.4.6, installed 1.2.0, requested = 1.2.0) in groups "default"
+ * Gem Current Latest Requested Groups
+ * hashie 1.2.0 3.4.6 = 1.2.0 default
`--filter-minor` would only show:
- * headless (newest 2.3.1, installed 2.2.3) in groups "test"
+ * Gem Current Latest Requested Groups
+ * headless 2.2.3 2.3.1 = 2.2.3 test
`--filter-patch` would only show:
- * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test"
+ * Gem Current Latest Requested Groups
+ * faker 1.6.5 1.6.6 ~> 1.4 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"
-
+ * Gem Current Latest Requested Groups
+ * faker 1.6.5 1.6.6 ~> 1.4 development, test
Combining all three `filter` options would be the same result as providing none of them.
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index dab5269c04..5021c46b4c 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PLATFORM" "1" "June 2021" "" ""
+.TH "BUNDLE\-PLATFORM" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
@@ -10,7 +10,7 @@
\fBbundle platform\fR [\-\-ruby]
.
.SH "DESCRIPTION"
-\fBplatform\fR will display information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
+\fBplatform\fR displays information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
.
.P
For instance, using this Gemfile(5):
@@ -21,7 +21,7 @@ For instance, using this Gemfile(5):
source "https://rubygems\.org"
-ruby "1\.9\.3"
+ruby "3\.1\.2"
gem "rack"
.
@@ -30,7 +30,7 @@ gem "rack"
.IP "" 0
.
.P
-If you run \fBbundle platform\fR on Ruby 1\.9\.3, it will display the following output:
+If you run \fBbundle platform\fR on Ruby 3\.1\.2, it displays the following output:
.
.IP "" 4
.
@@ -39,10 +39,13 @@ If you run \fBbundle platform\fR on Ruby 1\.9\.3, it will display the following
Your platform is: x86_64\-linux
Your app has gems that work on these platforms:
+* arm64\-darwin\-21
* ruby
+* x64\-mingw\-ucrt
+* x86_64\-linux
Your Gemfile specifies a Ruby version requirement:
-* ruby 1\.9\.3
+* ruby 3\.1\.2
Your current platform satisfies the Ruby version requirement\.
.
@@ -51,11 +54,18 @@ Your current platform satisfies the Ruby version requirement\.
.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\.
+\fBplatform\fR lists all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It also lets you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn\'t match the running Ruby VM, it tells 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)\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+bundle\-lock(1) \fIbundle\-lock\.1\.html\fR
+.
+.IP "" 0
diff --git a/lib/bundler/man/bundle-platform.1.ronn b/lib/bundler/man/bundle-platform.1.ronn
index b5d3283fb6..744acd1b43 100644
--- a/lib/bundler/man/bundle-platform.1.ronn
+++ b/lib/bundler/man/bundle-platform.1.ronn
@@ -7,36 +7,43 @@ bundle-platform(1) -- Displays platform compatibility information
## DESCRIPTION
-`platform` will display information from your Gemfile, Gemfile.lock, and Ruby
+`platform` displays 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"
+ ruby "3.1.2"
gem "rack"
-If you run `bundle platform` on Ruby 1.9.3, it will display the following output:
+If you run `bundle platform` on Ruby 3.1.2, it displays the following output:
Your platform is: x86_64-linux
Your app has gems that work on these platforms:
+ * arm64-darwin-21
* ruby
+ * x64-mingw-ucrt
+ * x86_64-linux
Your Gemfile specifies a Ruby version requirement:
- * ruby 1.9.3
+ * ruby 3.1.2
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
+`platform` lists all the platforms in your `Gemfile.lock` as well as the
+`ruby` directive if applicable from your Gemfile(5). It also lets you know
if the `ruby` directive requirement has been met. If `ruby` directive doesn't
-match the running Ruby VM, it will tell you what part does not.
+match the running Ruby VM, it tells 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).
+
+## SEE ALSO
+
+* [bundle-lock(1)](bundle-lock.1.html)
diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1
new file mode 100644
index 0000000000..ec30e1d0fd
--- /dev/null
+++ b/lib/bundler/man/bundle-plugin.1
@@ -0,0 +1,81 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-PLUGIN" "1" "August 2023" "" ""
+.
+.SH "NAME"
+\fBbundle\-plugin\fR \- Manage Bundler plugins
+.
+.SH "SYNOPSIS"
+\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git|\-\-local_git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR]
+.
+.br
+\fBbundle plugin\fR uninstall PLUGINS
+.
+.br
+\fBbundle plugin\fR list
+.
+.br
+\fBbundle plugin\fR help [COMMAND]
+.
+.SH "DESCRIPTION"
+You can install, uninstall, and list plugin(s) with this command to extend functionalities of Bundler\.
+.
+.SH "SUB\-COMMANDS"
+.
+.SS "install"
+Install the given plugin(s)\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph\fR: Install bundler\-graph gem from RubyGems\.org\. The global source, specified in source in Gemfile is ignored\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR: Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR: You can specify the version of the gem via \fB\-\-version\fR\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR: Install bundler\-graph gem from Git repository\. \fB\-\-git\fR can be replaced with \fB\-\-local\-git\fR\. You cannot use both \fB\-\-git\fR and \fB\-\-local\-git\fR\. You can use standard Git URLs like:
+.
+.IP "\(bu" 4
+\fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR
+.
+.IP "\(bu" 4
+\fBhttp[s]://host\.xz[:port]/path/to/repo\.git\fR
+.
+.IP "\(bu" 4
+\fB/path/to/repo\fR
+.
+.IP "\(bu" 4
+\fBfile:///path/to/repo\fR
+.
+.IP "" 0
+.
+.IP
+When you specify \fB\-\-git\fR/\fB\-\-local\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. When you specify both, only the latter is used\.
+.
+.IP "" 0
+.
+.SS "uninstall"
+Uninstall the plugin(s) specified in PLUGINS\.
+.
+.SS "list"
+List the installed plugins and available commands\.
+.
+.P
+No options\.
+.
+.SS "help"
+Describe subcommands or one specific subcommand\.
+.
+.P
+No options\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+How to write a Bundler plugin \fIhttps://bundler\.io/guides/bundler_plugins\.html\fR
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn
new file mode 100644
index 0000000000..4f234eeba7
--- /dev/null
+++ b/lib/bundler/man/bundle-plugin.1.ronn
@@ -0,0 +1,59 @@
+bundle-plugin(1) -- Manage Bundler plugins
+==========================================
+
+## SYNOPSIS
+
+`bundle plugin` install PLUGINS [--source=<SOURCE>] [--version=<version>]
+ [--git|--local_git=<git-url>] [--branch=<branch>|--ref=<rev>]<br>
+`bundle plugin` uninstall PLUGINS<br>
+`bundle plugin` list<br>
+`bundle plugin` help [COMMAND]
+
+## DESCRIPTION
+
+You can install, uninstall, and list plugin(s) with this command to extend functionalities of Bundler.
+
+## SUB-COMMANDS
+
+### install
+
+Install the given plugin(s).
+
+* `bundle plugin install bundler-graph`:
+ Install bundler-graph gem from RubyGems.org. The global source, specified in source in Gemfile is ignored.
+
+* `bundle plugin install bundler-graph --source https://example.com`:
+ Install bundler-graph gem from example.com. The global source, specified in source in Gemfile is not considered.
+
+* `bundle plugin install bundler-graph --version 0.2.1`:
+ You can specify the version of the gem via `--version`.
+
+* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`:
+ Install bundler-graph gem from Git repository. `--git` can be replaced with `--local-git`. You cannot use both `--git` and `--local-git`. You can use standard Git URLs like:
+
+ * `ssh://[user@]host.xz[:port]/path/to/repo.git`
+ * `http[s]://host.xz[:port]/path/to/repo.git`
+ * `/path/to/repo`
+ * `file:///path/to/repo`
+
+ When you specify `--git`/`--local-git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. When you specify both, only the latter is used.
+
+### uninstall
+
+Uninstall the plugin(s) specified in PLUGINS.
+
+### list
+
+List the installed plugins and available commands.
+
+No options.
+
+### help
+
+Describe subcommands or one specific subcommand.
+
+No options.
+
+## SEE ALSO
+
+* [How to write a Bundler plugin](https://bundler.io/guides/bundler_plugins.html)
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index e5b0dab334..af81c48d2b 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PRISTINE" "1" "June 2021" "" ""
+.TH "BUNDLE\-PRISTINE" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index 8af691283d..d86cf134bd 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-REMOVE" "1" "June 2021" "" ""
+.TH "BUNDLE\-REMOVE" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index c08c7205aa..aa91176bf2 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-SHOW" "1" "June 2021" "" ""
+.TH "BUNDLE\-SHOW" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index 7da2ce3438..e4e10ad23b 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-UPDATE" "1" "June 2021" "" ""
+.TH "BUNDLE\-UPDATE" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
@@ -47,7 +47,7 @@ Fall back to using the single\-file index of all gems\.
.
.TP
\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
-Specify the number of jobs to run in parallel\. The default is \fB1\fR\.
+Specify the number of jobs to run in parallel\. The default is the number of available processors\.
.
.TP
\fB\-\-retry=[<number>]\fR
diff --git a/lib/bundler/man/bundle-update.1.ronn b/lib/bundler/man/bundle-update.1.ronn
index 3a16f29149..fe500cdc96 100644
--- a/lib/bundler/man/bundle-update.1.ronn
+++ b/lib/bundler/man/bundle-update.1.ronn
@@ -56,7 +56,8 @@ gem.
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`.
+ Specify the number of jobs to run in parallel. The default is the number of
+ available processors.
* `--retry=[<number>]`:
Retry failed network or git requests for <number> times.
diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1
new file mode 100644
index 0000000000..5e3ed44600
--- /dev/null
+++ b/lib/bundler/man/bundle-version.1
@@ -0,0 +1,35 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-VERSION" "1" "August 2023" "" ""
+.
+.SH "NAME"
+\fBbundle\-version\fR \- Prints Bundler version information
+.
+.SH "SYNOPSIS"
+\fBbundle version\fR
+.
+.SH "DESCRIPTION"
+Prints Bundler version information\.
+.
+.SH "OPTIONS"
+No options\.
+.
+.SH "EXAMPLE"
+Print the version of Bundler with build date and commit hash of the in the Git source\.
+.
+.IP "" 4
+.
+.nf
+
+bundle version
+.
+.fi
+.
+.IP "" 0
+.
+.P
+shows \fBBundler version 2\.3\.21 (2022\-08\-24 commit d54be5fdd8)\fR for example\.
+.
+.P
+cf\. \fBbundle \-\-version\fR shows \fBBundler version 2\.3\.21\fR\.
diff --git a/lib/bundler/man/bundle-version.1.ronn b/lib/bundler/man/bundle-version.1.ronn
new file mode 100644
index 0000000000..46c6f0b30a
--- /dev/null
+++ b/lib/bundler/man/bundle-version.1.ronn
@@ -0,0 +1,24 @@
+bundle-version(1) -- Prints Bundler version information
+=======================================================
+
+## SYNOPSIS
+
+`bundle version`
+
+## DESCRIPTION
+
+Prints Bundler version information.
+
+## OPTIONS
+
+No options.
+
+## EXAMPLE
+
+Print the version of Bundler with build date and commit hash of the in the Git source.
+
+ bundle version
+
+shows `Bundler version 2.3.21 (2022-08-24 commit d54be5fdd8)` for example.
+
+cf. `bundle --version` shows `Bundler version 2.3.21`.
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
index 9683f0678b..d5330ec754 100644
--- a/lib/bundler/man/bundle-viz.1
+++ b/lib/bundler/man/bundle-viz.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-VIZ" "1" "June 2021" "" ""
+.TH "BUNDLE\-VIZ" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
@@ -15,6 +15,9 @@
.P
The associated gems must also be installed via \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR\.
.
+.P
+\fBviz\fR command was deprecated in Bundler 2\.2\. Use bundler\-graph plugin \fIhttps://github\.com/rubygems/bundler\-graph\fR instead\.
+.
.SH "OPTIONS"
.
.TP
diff --git a/lib/bundler/man/bundle-viz.1.ronn b/lib/bundler/man/bundle-viz.1.ronn
index 701df5415e..f220256943 100644
--- a/lib/bundler/man/bundle-viz.1.ronn
+++ b/lib/bundler/man/bundle-viz.1.ronn
@@ -16,6 +16,8 @@ bundle-viz(1) -- Generates a visual dependency graph for your Gemfile
The associated gems must also be installed via [`bundle install(1)`](bundle-install.1.html).
+`viz` command was deprecated in Bundler 2.2. Use [bundler-graph plugin](https://github.com/rubygems/bundler-graph) instead.
+
## OPTIONS
* `--file`, `-f`:
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index b741f7cf6a..99c65a72b5 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE" "1" "June 2021" "" ""
+.TH "BUNDLE" "1" "August 2023" "" ""
.
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
@@ -43,8 +43,8 @@ Install the gems specified by the \fBGemfile\fR or \fBGemfile\.lock\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
+\fBbundle cache(1)\fR \fIbundle\-cache\.1\.html\fR
+Package the \.gem files required by your application into the \fBvendor/cache\fR directory (aliases: \fBbundle package\fR, \fBbundle pack\fR)
.
.TP
\fBbundle exec(1)\fR \fIbundle\-exec\.1\.html\fR
@@ -55,7 +55,7 @@ Execute a script in the current bundle
Specify and read configuration options for Bundler
.
.TP
-\fBbundle help(1)\fR
+\fBbundle help(1)\fR \fIbundle\-help\.1\.html\fR
Display detailed help for each subcommand
.
.SH "UTILITIES"
@@ -81,7 +81,7 @@ Show the source location of a particular gem in the bundle
Show all of the outdated gems in the current bundle
.
.TP
-\fBbundle console(1)\fR
+\fBbundle console(1)\fR (deprecated)
Start an IRB session in the current bundle
.
.TP
@@ -93,7 +93,7 @@ Open an installed gem in the editor
Generate a lockfile for your dependencies
.
.TP
-\fBbundle viz(1)\fR \fIbundle\-viz\.1\.html\fR
+\fBbundle viz(1)\fR \fIbundle\-viz\.1\.html\fR (deprecated)
Generate a visual representation of your dependencies
.
.TP
@@ -120,6 +120,14 @@ Display warnings about common problems
\fBbundle remove(1)\fR \fIbundle\-remove\.1\.html\fR
Removes gems from the Gemfile
.
+.TP
+\fBbundle plugin(1)\fR \fIbundle\-plugin\.1\.html\fR
+Manage Bundler plugins
+.
+.TP
+\fBbundle version(1)\fR \fIbundle\-version\.1\.html\fR
+Prints Bundler version information
+.
.SH "PLUGINS"
When running a command that isn\'t listed in PRIMARY COMMANDS or UTILITIES, Bundler will try to find an executable on your path named \fBbundler\-<command>\fR and execute it, passing down any extra arguments to it\.
.
@@ -127,10 +135,7 @@ When running a command that isn\'t listed in PRIMARY COMMANDS or UTILITIES, Bund
These commands are obsolete and should no longer be used:
.
.IP "\(bu" 4
-\fBbundle cache(1)\fR
-.
-.IP "\(bu" 4
-\fBbundle show(1)\fR
+\fBbundle inject(1)\fR
.
.IP "" 0
diff --git a/lib/bundler/man/bundle.1.ronn b/lib/bundler/man/bundle.1.ronn
index 5b1712394a..8245effabd 100644
--- a/lib/bundler/man/bundle.1.ronn
+++ b/lib/bundler/man/bundle.1.ronn
@@ -36,9 +36,9 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle update(1)`](bundle-update.1.html):
Update dependencies to their latest versions
-* [`bundle package(1)`](bundle-package.1.html):
+* [`bundle cache(1)`](bundle-cache.1.html):
Package the .gem files required by your application into the
- `vendor/cache` directory
+ `vendor/cache` directory (aliases: `bundle package`, `bundle pack`)
* [`bundle exec(1)`](bundle-exec.1.html):
Execute a script in the current bundle
@@ -46,7 +46,7 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle config(1)`](bundle-config.1.html):
Specify and read configuration options for Bundler
-* `bundle help(1)`:
+* [`bundle help(1)`](bundle-help.1.html):
Display detailed help for each subcommand
## UTILITIES
@@ -67,7 +67,7 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle outdated(1)`](bundle-outdated.1.html):
Show all of the outdated gems in the current bundle
-* `bundle console(1)`:
+* `bundle console(1)` (deprecated):
Start an IRB session in the current bundle
* [`bundle open(1)`](bundle-open.1.html):
@@ -76,7 +76,7 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle lock(1)`](bundle-lock.1.html):
Generate a lockfile for your dependencies
-* [`bundle viz(1)`](bundle-viz.1.html):
+* [`bundle viz(1)`](bundle-viz.1.html) (deprecated):
Generate a visual representation of your dependencies
* [`bundle init(1)`](bundle-init.1.html):
@@ -97,6 +97,12 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle remove(1)`](bundle-remove.1.html):
Removes gems from the Gemfile
+* [`bundle plugin(1)`](bundle-plugin.1.html):
+ Manage Bundler plugins
+
+* [`bundle version(1)`](bundle-version.1.html):
+ Prints Bundler version information
+
## PLUGINS
When running a command that isn't listed in PRIMARY COMMANDS or UTILITIES,
@@ -107,5 +113,4 @@ and execute it, passing down any extra arguments to it.
These commands are obsolete and should no longer be used:
-* `bundle cache(1)`
-* `bundle show(1)`
+* `bundle inject(1)`
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index f30f71ac7c..352fa0f545 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "GEMFILE" "5" "June 2021" "" ""
+.TH "GEMFILE" "5" "August 2023" "" ""
.
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
@@ -15,8 +15,8 @@ Place the \fBGemfile\fR in the root of the directory containing the associated c
.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\.
+.SH "GLOBAL SOURCE"
+At the top of the \fBGemfile\fR, add a single line for the \fBRubyGems\fR source that contains the gems listed in the \fBGemfile\fR\.
.
.IP "" 4
.
@@ -29,10 +29,16 @@ source "https://rubygems\.org"
.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\.
+You can add only one global source\. In Bundler 1\.13, adding multiple global sources was deprecated\. The \fBsource\fR \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\.
+To use more than one source of RubyGems, you should use \fI\fBsource\fR block\fR\.
+.
+.P
+A source is checked for gems following the heuristics described in \fISOURCE PRIORITY\fR\.
+.
+.P
+\fBNote about a behavior of the feature deprecated in Bundler 1\.13\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 \fBsource\fR block\.
.
.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\.
@@ -67,13 +73,26 @@ Credentials in the source URL will take precedence over credentials set using \f
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\.
+The version of Ruby that your application requires\. If your application requires an alternate Ruby engine, such as JRuby, TruffleRuby, etc\., this should be the Ruby version that the engine is compatible with\.
.
.IP "" 4
.
.nf
-ruby "1\.9\.3"
+ruby "3\.1\.2"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+If you wish to derive your Ruby version from a version file (ie \.ruby\-version), you can use the \fBfile\fR option instead\.
+.
+.IP "" 4
+.
+.nf
+
+ruby file: "\.ruby\-version"
.
.fi
.
@@ -89,7 +108,7 @@ What exactly is an Engine? \- A Ruby engine is an implementation of the Ruby lan
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\.
+Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include JRuby \fIhttp://jruby\.org/\fR and TruffleRuby \fIhttps://www\.graalvm\.org/ruby/\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\. TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM\.
.
.IP "" 0
.
@@ -100,20 +119,23 @@ Each application \fImay\fR specify a Ruby engine version\. If an engine version
.
.nf
-ruby "1\.8\.7", :engine => "jruby", :engine_version => "1\.6\.7"
+ruby "2\.6\.8", engine: "jruby", engine_version: "9\.3\.8\.0"
.
.fi
.
.IP "" 0
.
.SS "PATCHLEVEL"
-Each application \fImay\fR specify a Ruby patchlevel\.
+Each application \fImay\fR specify a Ruby patchlevel\. Specifying the patchlevel has been meaningless since Ruby 2\.1\.0 was released as the patchlevel is now uniquely determined by a combination of major, minor, and teeny version numbers\.
+.
+.P
+This option was implemented in Bundler 1\.4\.0 for Ruby 2\.0 or earlier\.
.
.IP "" 4
.
.nf
-ruby "2\.0\.0", :patchlevel => "247"
+ruby "3\.1\.2", patchlevel: "20"
.
.fi
.
@@ -156,9 +178,9 @@ Each \fIgem\fR \fBMAY\fR specify files that should be used when autorequiring vi
.
.nf
-gem "redis", :require => ["redis/connection/hiredis", "redis"]
-gem "webmock", :require => false
-gem "byebug", :require => true
+gem "redis", require: ["redis/connection/hiredis", "redis"]
+gem "webmock", require: false
+gem "byebug", require: true
.
.fi
.
@@ -172,8 +194,8 @@ The argument defaults to the name of the gem\. For example, these are identical:
.nf
gem "nokogiri"
-gem "nokogiri", :require => "nokogiri"
-gem "nokogiri", :require => true
+gem "nokogiri", require: "nokogiri"
+gem "nokogiri", require: true
.
.fi
.
@@ -186,8 +208,8 @@ Each \fIgem\fR \fBMAY\fR specify membership in one or more groups\. Any \fIgem\f
.
.nf
-gem "rspec", :group => :test
-gem "wirble", :groups => [:development, :test]
+gem "rspec", group: :test
+gem "wirble", groups: [:development, :test]
.
.fi
.
@@ -248,19 +270,23 @@ There are a number of \fBGemfile\fR platforms:
.
.TP
\fBruby\fR
-C Ruby (MRI), Rubinius or TruffleRuby, but \fBNOT\fR Windows
+C Ruby (MRI), Rubinius, or TruffleRuby, but not Windows
.
.TP
\fBmri\fR
-Same as \fIruby\fR, but only C Ruby (MRI)
+C Ruby (MRI) only, but not Windows
.
.TP
-\fBmingw\fR
-Windows 32 bit \'mingw32\' platform (aka RubyInstaller)
+\fBwindows\fR
+Windows C Ruby (MRI), including RubyInstaller 32\-bit and 64\-bit versions
.
.TP
-\fBx64_mingw\fR
-Windows 64 bit \'mingw32\' platform (aka RubyInstaller x64)
+\fBmswin\fR
+Windows C Ruby (MRI), including RubyInstaller 32\-bit versions
+.
+.TP
+\fBmswin64\fR
+Windows C Ruby (MRI), including RubyInstaller 64\-bit versions
.
.TP
\fBrbx\fR
@@ -274,84 +300,82 @@ JRuby
\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:
+On platforms \fBruby\fR, \fBmri\fR, \fBmswin\fR, \fBmswin64\fR, and \fBwindows\fR, you may additionally specify a version by appending the major and minor version numbers without a delimiter\. For example, to specify that a gem should only be used on platform \fBruby\fR version 3\.1, use:
.
.IP "" 4
.
.nf
-ruby_23
+ruby_31
.
.fi
.
.IP "" 0
.
.P
-The full list of platforms and supported versions includes:
+As with groups (above), you may specify one or more platforms:
.
-.TP
-\fBruby\fR
-1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.IP "" 4
.
-.TP
-\fBmri\fR
-1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.nf
+
+gem "weakling", platforms: :jruby
+gem "ruby\-debug", platforms: :mri_31
+gem "nokogiri", platforms: [:windows_31, :jruby]
.
-.TP
-\fBmingw\fR
-1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.fi
.
-.TP
-\fBx64_mingw\fR
-2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.IP "" 0
.
.P
-As with groups, you can specify one or more platforms:
+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 "FORCE_RUBY_PLATFORM"
+If you always want the pure ruby variant of a gem to be chosen over platform specific variants, you can use the \fBforce_ruby_platform\fR option:
.
.IP "" 4
.
.nf
-gem "weakling", :platforms => :jruby
-gem "ruby\-debug", :platforms => :mri_18
-gem "nokogiri", :platforms => [:mri_18, :jruby]
+gem "ffi", force_ruby_platform: true
.
.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\.
+This can be handy (assuming the pure ruby variant works fine) when:
+.
+.IP "\(bu" 4
+You\'re having issues with the platform specific variant\.
+.
+.IP "\(bu" 4
+The platform specific variant does not yet support a newer ruby (and thus has a \fBrequired_ruby_version\fR upper bound), but you still want your Gemfile{\.lock} files to resolve under that ruby\.
+.
+.IP "" 0
.
.SS "SOURCE"
-You can select an alternate Rubygems repository for a gem using the \':source\' option\.
+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"
+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\.
+This forces the gem to be loaded from this source and ignores the global source 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\.
+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 the global source\.
.
.P
-Selecting a specific source repository this way also suppresses the ambiguous gem warning described above in \fIGLOBAL SOURCES (#source)\fR\.
+\fBNote about a behavior of the feature deprecated in Bundler 1\.13\fR: Selecting a specific source repository this way also suppresses the ambiguous gem warning described above in \fIGLOBAL 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\.
@@ -361,15 +385,15 @@ If necessary, you can specify that a gem is located at a particular git reposito
.
.TP
\fBHTTP(S)\fR
-gem "rails", :git => "https://github\.com/rails/rails\.git"
+gem "rails", git: "https://github\.com/rails/rails\.git"
.
.TP
\fBSSH\fR
-gem "rails", :git => "git@github\.com:rails/rails\.git"
+gem "rails", git: "git@github\.com:rails/rails\.git"
.
.TP
\fBgit\fR
-gem "rails", :git => "git://github\.com/rails/rails\.git"
+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\.
@@ -393,7 +417,7 @@ If a git repository does have a \fB\.gemspec\fR for the gem you attached it to,
.
.nf
-gem "rails", "2\.3\.8", :git => "https://github\.com/rails/rails\.git"
+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
.
@@ -409,20 +433,20 @@ 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:
+You \fBMUST\fR only specify at most one of these options\. The default is \fBbranch: "master"\fR\. For example:
.
.IP
-gem "rails", :git => "https://github\.com/rails/rails\.git", :branch => "5\-0\-stable"
+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"
+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"
+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
+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 \fBsubmodules: 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\.
@@ -454,7 +478,7 @@ A custom git source can be defined via the \fBgit_source\fR method\. Provide the
.nf
git_source(:stash){ |repo_name| "https://stash\.corp\.acme\.pl/#{repo_name}\.git" }
-gem \'rails\', :stash => \'forks/rails\'
+gem \'rails\', stash: \'forks/rails\'
.
.fi
.
@@ -467,7 +491,7 @@ In addition, if you wish to choose a specific branch:
.
.nf
-gem "rails", :stash => "forks/rails", :branch => "branch_name"
+gem "rails", stash: "forks/rails", branch: "branch_name"
.
.fi
.
@@ -483,8 +507,8 @@ If the git repository you want to use is hosted on GitHub and is public, you can
.
.nf
-gem "rails", :github => "rails/rails"
-gem "rails", :github => "rails"
+gem "rails", github: "rails/rails"
+gem "rails", github: "rails"
.
.fi
.
@@ -497,7 +521,7 @@ Are both equivalent to
.
.nf
-gem "rails", :git => "git://github\.com/rails/rails\.git"
+gem "rails", git: "https://github\.com/rails/rails\.git"
.
.fi
.
@@ -506,6 +530,32 @@ gem "rails", :git => "git://github\.com/rails/rails\.git"
.P
Since the \fBgithub\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
.
+.P
+You can also directly pass a pull request URL:
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", github: "https://github\.com/rails/rails/pull/43753"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Which is equivalent to:
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", github: "rails/rails", branch: "refs/pull/43753/head"
+.
+.fi
+.
+.IP "" 0
+.
.SS "GIST"
If the git repository you want to use is hosted as a GitHub Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing "\.git")\.
.
@@ -513,7 +563,7 @@ If the git repository you want to use is hosted as a GitHub Gist and is public,
.
.nf
-gem "the_hatch", :gist => "4815162342"
+gem "the_hatch", gist: "4815162342"
.
.fi
.
@@ -526,7 +576,7 @@ Is equivalent to:
.
.nf
-gem "the_hatch", :git => "https://gist\.github\.com/4815162342\.git"
+gem "the_hatch", git: "https://gist\.github\.com/4815162342\.git"
.
.fi
.
@@ -542,8 +592,8 @@ If the git repository you want to use is hosted on Bitbucket and is public, you
.
.nf
-gem "rails", :bitbucket => "rails/rails"
-gem "rails", :bitbucket => "rails"
+gem "rails", bitbucket: "rails/rails"
+gem "rails", bitbucket: "rails"
.
.fi
.
@@ -556,7 +606,7 @@ Are both equivalent to
.
.nf
-gem "rails", :git => "https://rails@bitbucket\.org/rails/rails\.git"
+gem "rails", git: "https://rails@bitbucket\.org/rails/rails\.git"
.
.fi
.
@@ -578,7 +628,7 @@ Unlike \fB:git\fR, bundler does not compile C extensions for gems specified as p
.
.nf
-gem "rails", :path => "vendor/rails"
+gem "rails", path: "vendor/rails"
.
.fi
.
@@ -622,7 +672,7 @@ platforms :ruby do
gem "sqlite3"
end
-group :development, :optional => true do
+group :development, optional: true do
gem "wirble"
gem "faker"
end
@@ -662,10 +712,10 @@ The \fB\.gemspec\fR \fIhttp://guides\.rubygems\.org/specification\-reference/\fR
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\.
+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 (\fBpath: \'\.\'\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\.
+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: \fB{,*,*/*}\.gemspec\fR), 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\.
@@ -680,7 +730,7 @@ The source explicitly attached to the gem (using \fB:source\fR, \fB:path\fR, or
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\.
+If neither of the above conditions are met, the global source will be used\. If multiple global sources are specified, they will be prioritized from last to first, but this is deprecated since Bundler 1\.13, so Bundler prints a warning and will abort with an error in the future\.
.
.IP "" 0
diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn
index ea7cf40e63..6749c33f59 100644
--- a/lib/bundler/man/gemfile.5.ronn
+++ b/lib/bundler/man/gemfile.5.ronn
@@ -15,23 +15,28 @@ directory as the `Rakefile`.
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
+## GLOBAL SOURCE
-At the top of the `Gemfile`, add a line for the `Rubygems` source that contains
-the gems listed in the `Gemfile`.
+At the top of the `Gemfile`, add a single 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.
+You can add only one global source. In Bundler 1.13, adding multiple global
+sources was deprecated. The `source` `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
+To use more than one source of RubyGems, you should use [`source` block
+](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS).
+
+A source is checked for gems following the heuristics described in
+[SOURCE PRIORITY][].
+
+**Note about a behavior of the feature deprecated in Bundler 1.13**:
+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).
+this warning, by using the [`:source` option](#SOURCE) or `source` block.
### CREDENTIALS
@@ -59,10 +64,15 @@ 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
+requires an alternate Ruby engine, such as JRuby, TruffleRuby, etc., this
should be the Ruby version that the engine is compatible with.
- ruby "1.9.3"
+ ruby "3.1.2"
+
+If you wish to derive your Ruby version from a version file (ie .ruby-version),
+you can use the `file` option instead.
+
+ ruby file: ".ruby-version"
### ENGINE
@@ -81,9 +91,10 @@ What exactly is an 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/).
+ [JRuby](http://jruby.org/) and [TruffleRuby](https://www.graalvm.org/ruby/).
Rubinius is an alternative implementation of Ruby written in Ruby.
JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine.
+ TruffleRuby is a Ruby implementation on the GraalVM, a language toolkit built on the JVM.
### ENGINE VERSION
@@ -91,13 +102,17 @@ 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"
+ ruby "2.6.8", engine: "jruby", engine_version: "9.3.8.0"
### PATCHLEVEL
-Each application _may_ specify a Ruby patchlevel.
+Each application _may_ specify a Ruby patchlevel. Specifying the patchlevel has
+been meaningless since Ruby 2.1.0 was released as the patchlevel is now
+uniquely determined by a combination of major, minor, and teeny version numbers.
+
+This option was implemented in Bundler 1.4.0 for Ruby 2.0 or earlier.
- ruby "2.0.0", :patchlevel => "247"
+ ruby "3.1.2", patchlevel: "20"
## GEMS
@@ -124,23 +139,23 @@ Each _gem_ `MAY` specify files that should be used when autorequiring via
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
+ 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
+ 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]
+ 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.
@@ -185,70 +200,71 @@ platforms.
There are a number of `Gemfile` platforms:
* `ruby`:
- C Ruby (MRI), Rubinius or TruffleRuby, but `NOT` Windows
+ 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)
+ C Ruby (MRI) only, but not Windows
+ * `windows`:
+ Windows C Ruby (MRI), including RubyInstaller 32-bit and 64-bit versions
+ * `mswin`:
+ Windows C Ruby (MRI), including RubyInstaller 32-bit versions
+ * `mswin64`:
+ Windows C Ruby (MRI), including RubyInstaller 64-bit versions
* `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
+On platforms `ruby`, `mri`, `mswin`, `mswin64`, and `windows`, you may
+additionally specify a version by appending the major and minor version numbers
+without a delimiter. For example, to specify that a gem should only be used on
+platform `ruby` version 3.1, use:
-The full list of platforms and supported versions includes:
+ ruby_31
- * `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 (above), you may specify one or more platforms:
-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]
+ gem "weakling", platforms: :jruby
+ gem "ruby-debug", platforms: :mri_31
+ gem "nokogiri", platforms: [:windows_31, :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.
+### FORCE_RUBY_PLATFORM
+
+If you always want the pure ruby variant of a gem to be chosen over platform
+specific variants, you can use the `force_ruby_platform` option:
+
+ gem "ffi", force_ruby_platform: true
+
+This can be handy (assuming the pure ruby variant works fine) when:
+
+* You're having issues with the platform specific variant.
+* The platform specific variant does not yet support a newer ruby (and thus has
+ a `required_ruby_version` upper bound), but you still want your Gemfile{.lock}
+ files to resolve under that ruby.
+
### SOURCE
-You can select an alternate Rubygems repository for a gem using the ':source'
+You can select an alternate RubyGems repository for a gem using the ':source'
option.
- gem "some_internal_gem", :source => "https://gems.example.com"
+ gem "some_internal_gem", source: "https://gems.example.com"
-This forces the gem to be loaded from this source and ignores any global sources
+This forces the gem to be loaded from this source and ignores the global source
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][].
+back on the global source.
+**Note about a behavior of the feature deprecated in Bundler 1.13**:
Selecting a specific source repository this way also suppresses the ambiguous
-gem warning described above in
-[GLOBAL SOURCES (#source)](#GLOBAL-SOURCES).
+gem warning described above in [GLOBAL SOURCE](#GLOBAL-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
@@ -263,11 +279,11 @@ 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"
+ gem "rails", git: "https://github.com/rails/rails.git"
* `SSH`:
- gem "rails", :git => "git@github.com:rails/rails.git"
+ gem "rails", git: "git@github.com:rails/rails.git"
* `git`:
- gem "rails", :git => "git://github.com/rails/rails.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`.
@@ -295,7 +311,7 @@ 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"
+ 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
@@ -307,18 +323,18 @@ 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:
+ 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", 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", tag: "v5.0.0"
- gem "rails", :git => "https://github.com/rails/rails.git", :ref => "4aded"
+ 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
+ Specify `submodules: true` to cause bundler to expand any
submodules included in the git repository
If a git repository contains multiple `.gemspecs`, each `.gemspec`
@@ -346,11 +362,11 @@ as an argument, and a block which receives a single argument and interpolates it
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'
+ gem 'rails', stash: 'forks/rails'
In addition, if you wish to choose a specific branch:
- gem "rails", :stash => "forks/rails", :branch => "branch_name"
+ gem "rails", stash: "forks/rails", branch: "branch_name"
### GITHUB
@@ -363,25 +379,33 @@ If the git repository you want to use is hosted on GitHub and is public, you can
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"
+ gem "rails", github: "rails/rails"
+ gem "rails", github: "rails"
Are both equivalent to
- gem "rails", :git => "git://github.com/rails/rails.git"
+ gem "rails", git: "https://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"
+ gem "the_hatch", gist: "4815162342"
Is equivalent to:
- gem "the_hatch", :git => "https://gist.github.com/4815162342.git"
+ 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.
@@ -392,12 +416,12 @@ If the git repository you want to use is hosted on Bitbucket and is public, you
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"
+ gem "rails", bitbucket: "rails/rails"
+ gem "rails", bitbucket: "rails"
Are both equivalent to
- gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git"
+ 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.
@@ -415,7 +439,7 @@ version that bundler should use.
Unlike `:git`, bundler does not compile C extensions for
gems specified as paths.
- gem "rails", :path => "vendor/rails"
+ 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.
@@ -444,7 +468,7 @@ applied to a group of gems by using block form.
gem "sqlite3"
end
- group :development, :optional => true do
+ group :development, optional: true do
gem "wirble"
gem "faker"
end
@@ -487,15 +511,15 @@ 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
+`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
+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
@@ -513,5 +537,7 @@ bundler uses the following priority order:
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.
+ 3. If neither of the above conditions are met, the global source will be used.
+ If multiple global sources are specified, they will be prioritized from
+ last to first, but this is deprecated since Bundler 1.13, so Bundler prints
+ a warning and will abort with an error in the future.
diff --git a/lib/bundler/man/index.txt b/lib/bundler/man/index.txt
index ef2956b2f9..24f7633e66 100644
--- a/lib/bundler/man/index.txt
+++ b/lib/bundler/man/index.txt
@@ -6,9 +6,11 @@ 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-console(1) bundle-console.1
bundle-doctor(1) bundle-doctor.1
bundle-exec(1) bundle-exec.1
bundle-gem(1) bundle-gem.1
+bundle-help(1) bundle-help.1
bundle-info(1) bundle-info.1
bundle-init(1) bundle-init.1
bundle-inject(1) bundle-inject.1
@@ -18,8 +20,10 @@ 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-plugin(1) bundle-plugin.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-version(1) bundle-version.1
bundle-viz(1) bundle-viz.1
diff --git a/lib/bundler/match_metadata.rb b/lib/bundler/match_metadata.rb
new file mode 100644
index 0000000000..499036ca93
--- /dev/null
+++ b/lib/bundler/match_metadata.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Bundler
+ module MatchMetadata
+ def matches_current_ruby?
+ @required_ruby_version.satisfied_by?(Gem.ruby_version)
+ end
+
+ def matches_current_rubygems?
+ @required_rubygems_version.satisfied_by?(Gem.rubygems_version)
+ end
+ end
+end
diff --git a/lib/bundler/match_platform.rb b/lib/bundler/match_platform.rb
index 69074925a6..7f7e8227f9 100644
--- a/lib/bundler/match_platform.rb
+++ b/lib/bundler/match_platform.rb
@@ -15,7 +15,6 @@ module Bundler
return true if Gem::Platform::RUBY == gemspec_platform
return true if local_platform == gemspec_platform
gemspec_platform = Gem::Platform.new(gemspec_platform)
- return true if GemHelpers.generic(gemspec_platform) === local_platform
return true if gemspec_platform === local_platform
false
diff --git a/lib/bundler/match_remote_metadata.rb b/lib/bundler/match_remote_metadata.rb
new file mode 100644
index 0000000000..5e46d52441
--- /dev/null
+++ b/lib/bundler/match_remote_metadata.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Bundler
+ module FetchMetadata
+ # 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 matches_current_ruby?
+ @required_ruby_version ||= _remote_specification.required_ruby_version || Gem::Requirement.default
+
+ super
+ end
+
+ def matches_current_rubygems?
+ # 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+.
+ @required_rubygems_version ||= _remote_specification.required_rubygems_version || Gem::Requirement.default
+
+ super
+ end
+ end
+
+ module MatchRemoteMetadata
+ include MatchMetadata
+
+ prepend FetchMetadata
+ end
+end
diff --git a/lib/bundler/mirror.rb b/lib/bundler/mirror.rb
index a63b45b47d..9d437a0951 100644
--- a/lib/bundler/mirror.rb
+++ b/lib/bundler/mirror.rb
@@ -148,13 +148,11 @@ module Bundler
class TCPSocketProbe
def replies?(mirror)
MirrorSockets.new(mirror).any? do |socket, address, timeout|
- begin
- socket.connect_nonblock(address)
- rescue Errno::EINPROGRESS
- wait_for_writtable_socket(socket, address, timeout)
- rescue RuntimeError # Connection failed somehow, again
- false
- end
+ socket.connect_nonblock(address)
+ rescue Errno::EINPROGRESS
+ wait_for_writtable_socket(socket, address, timeout)
+ rescue RuntimeError # Connection failed somehow, again
+ false
end
end
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index bfe4fd7286..f3caff8963 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -13,8 +13,9 @@ module Bundler
class MalformattedPlugin < PluginError; end
class UndefinedCommandError < PluginError; end
class UnknownSourceError < PluginError; end
+ class PluginInstallError < PluginError; end
- PLUGIN_FILE_NAME = "plugins.rb".freeze
+ PLUGIN_FILE_NAME = "plugins.rb"
module_function
@@ -35,15 +36,16 @@ module Bundler
# @param [Hash] options various parameters as described in description.
# Refer to cli/plugin for available options
def install(names, options)
+ raise InvalidOption, "You cannot specify `--branch` and `--ref` at the same time." if options["branch"] && options["ref"]
+
specs = Installer.new.install(names, options)
save_plugins names, specs
- rescue PluginError => e
+ 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) }
- names_list = names.map {|name| "`#{name}`" }.join(", ")
- Bundler.ui.error "Failed to install the following plugins: #{names_list}. The underlying error was: #{e.message}.\n #{e.backtrace.join("\n ")}"
+ raise
end
# Uninstalls plugins by the given names
@@ -245,10 +247,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
@@ -263,6 +266,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.
#
diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb
index f6f4ac4f0a..67c45bd204 100644
--- a/lib/bundler/plugin/api/source.rb
+++ b/lib/bundler/plugin/api/source.rb
@@ -258,7 +258,7 @@ module Bundler
@dependencies |= Array(names)
end
- # Note: Do not override if you don't know what you are doing.
+ # NOTE: Do not override if you don't know what you are doing.
def can_lock?(spec)
spec.source == self
end
@@ -283,8 +283,9 @@ module Bundler
def to_s
"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.
+ # NOTE: Do not override if you don't know what you are doing.
def include?(other)
other == self
end
@@ -293,7 +294,7 @@ module Bundler
SharedHelpers.digest(:SHA1).hexdigest(uri)
end
- # Note: Do not override if you don't know what you are doing.
+ # NOTE: Do not override if you don't know what you are doing.
def gem_install_dir
Bundler.install_path
end
@@ -308,12 +309,6 @@ module Bundler
end
# @private
- # Returns true
- def bundler_plugin_api_source?
- true
- end
-
- # @private
# This API on source might not be stable, and for now we expect plugins
# to download all specs in `#specs`, so we implement the method for
# compatibility purposes and leave it undocumented (and don't support)
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb
index 29d33be718..a2d5eaa38a 100644
--- a/lib/bundler/plugin/index.rb
+++ b/lib/bundler/plugin/index.rb
@@ -146,7 +146,7 @@ module Bundler
# @param [Boolean] is the index file global index
def load_index(index_file, global = false)
SharedHelpers.filesystem_access(index_file, :read) do |index_f|
- valid_file = index_f && index_f.exist? && !index_f.size.zero?
+ valid_file = index_f&.exist? && !index_f.size.zero?
break unless valid_file
data = index_f.read
@@ -167,11 +167,11 @@ module Bundler
# to be only String key value pairs)
def save_index
index = {
- "commands" => @commands,
- "hooks" => @hooks,
- "load_paths" => @load_paths,
+ "commands" => @commands,
+ "hooks" => @hooks,
+ "load_paths" => @load_paths,
"plugin_paths" => @plugin_paths,
- "sources" => @sources,
+ "sources" => @sources,
}
require_relative "../yaml_serializer"
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index 54ce8528cf..c9ff12ce4b 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -21,7 +21,7 @@ module Bundler
elsif options[:local_git]
install_local_git(names, version, options)
else
- sources = options[:source] || Bundler.rubygems.sources
+ sources = options[:source] || Gem.sources
install_rubygems(names, version, sources)
end
end
@@ -81,8 +81,13 @@ module Bundler
deps = names.map {|name| Dependency.new name, version }
- definition = Definition.new(nil, deps, source_list, true)
- install_definition(definition)
+ Bundler.configure_gem_home_and_path(Plugin.root)
+
+ Bundler.settings.temporary(:deployment => false, :frozen => false) do
+ definition = Definition.new(nil, deps, source_list, true)
+
+ install_definition(definition)
+ end
end
# Installs the plugins and deps from the provided specs and returns map of
diff --git a/lib/bundler/plugin/installer/git.rb b/lib/bundler/plugin/installer/git.rb
index fbb6c5e40e..deec5e99b3 100644
--- a/lib/bundler/plugin/installer/git.rb
+++ b/lib/bundler/plugin/installer/git.rb
@@ -20,10 +20,6 @@ module Bundler
end
end
- def version_message(spec)
- "#{spec.name} #{spec.version}"
- end
-
def root
Plugin.root
end
diff --git a/lib/bundler/plugin/installer/rubygems.rb b/lib/bundler/plugin/installer/rubygems.rb
index e144c14b24..cb5db9c30e 100644
--- a/lib/bundler/plugin/installer/rubygems.rb
+++ b/lib/bundler/plugin/installer/rubygems.rb
@@ -4,16 +4,8 @@ module Bundler
module Plugin
class Installer
class Rubygems < Bundler::Source::Rubygems
- def version_message(spec)
- "#{spec.name} #{spec.version}"
- end
-
private
- def requires_sudo?
- false # Will change on implementation of project level plugins
- end
-
def rubygems_dir
Plugin.root
end
diff --git a/lib/bundler/process_lock.rb b/lib/bundler/process_lock.rb
index a5cc614e20..0297f80e2c 100644
--- a/lib/bundler/process_lock.rb
+++ b/lib/bundler/process_lock.rb
@@ -12,7 +12,7 @@ module Bundler
yield
f.flock(File::LOCK_UN)
end
- rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP
+ rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP, Errno::EPERM, Errno::EROFS
# In the case the user does not have access to
# create the lock file or is using NFS where
# locks are not available we skip locking.
diff --git a/lib/bundler/psyched_yaml.rb b/lib/bundler/psyched_yaml.rb
deleted file mode 100644
index 463d52dc4a..0000000000
--- a/lib/bundler/psyched_yaml.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# Psych could be in the stdlib
-# but it's too late if Syck is already loaded
-begin
- require "psych" unless defined?(Syck)
-rescue LoadError
- # Apparently Psych wasn't available. Oh well.
-end
-
-# At least load the YAML stdlib, whatever that may be
-require "yaml" unless defined?(YAML.dump)
-
-module Bundler
- # On encountering invalid YAML,
- # Psych raises Psych::SyntaxError
- if defined?(::Psych::SyntaxError)
- YamlLibrarySyntaxError = ::Psych::SyntaxError
- else # Syck raises ArgumentError
- YamlLibrarySyntaxError = ::ArgumentError
- end
-end
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index 89b69e1045..f626a3218e 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -6,6 +6,7 @@ module Bundler
# be seeded with what we're given from the source's abbreviated index - the
# full specification will only be fetched when necessary.
class RemoteSpecification
+ include MatchRemoteMetadata
include MatchPlatform
include Comparable
@@ -16,7 +17,8 @@ module Bundler
def initialize(name, version, platform, spec_fetcher)
@name = name
@version = Gem::Version.create version
- @platform = platform
+ @original_platform = platform || Gem::Platform::RUBY
+ @platform = Gem::Platform.new(platform)
@spec_fetcher = spec_fetcher
@dependencies = nil
end
@@ -28,10 +30,10 @@ module Bundler
end
def full_name
- if platform == Gem::Platform::RUBY || platform.nil?
+ @full_name ||= if @platform == Gem::Platform::RUBY
"#{@name}-#{@version}"
else
- "#{@name}-#{@version}-#{platform}"
+ "#{@name}-#{@version}-#{@platform}"
end
end
@@ -98,9 +100,9 @@ module Bundler
end
def _remote_specification
- @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @platform])
+ @_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @original_platform])
@_remote_specification || raise(GemspecError, "Gemspec data for #{full_name} was" \
- " missing from the server! Try installing with `--full-index` as a workaround.")
+ " missing from the server!")
end
def method_missing(method, *args, &blk)
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index a78b2db157..2ad35bc931 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -1,183 +1,271 @@
# frozen_string_literal: true
module Bundler
+ #
+ # This class implements the interface needed by PubGrub for resolution. It is
+ # equivalent to the `PubGrub::BasicPackageSource` class provided by PubGrub by
+ # default and used by the most simple PubGrub consumers.
+ #
class Resolver
- require_relative "vendored_molinillo"
- require_relative "resolver/spec_group"
+ require_relative "vendored_pub_grub"
+ require_relative "resolver/base"
+ require_relative "resolver/candidate"
+ require_relative "resolver/incompatibility"
+ require_relative "resolver/root"
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.
- #
- # ==== Parameters
- # *dependencies<Gem::Dependency>:: The list of dependencies to resolve
- #
- # ==== 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, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
- base = SpecSet.new(base) unless base.is_a?(SpecSet)
- resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
- result = resolver.start(requirements)
- SpecSet.new(SpecSet.new(result).for(requirements.reject{|dep| dep.name.end_with?("\0") }))
- end
-
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
- @source_requirements = source_requirements
+ def initialize(base, gem_version_promoter)
+ @source_requirements = base.source_requirements
@base = base
- @resolver = Molinillo::Resolver.new(self, self)
- @search_for = {}
- @base_dg = Molinillo::DependencyGraph.new
- aggregate_global_source = @source_requirements[:default].is_a?(Source::RubygemsAggregate)
- @base.each do |ls|
- dep = Dependency.new(ls.name, ls.version)
- ls.source = source_for(ls.name) unless aggregate_global_source
- @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.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
- @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
end
- def start(requirements)
- @gem_version_promoter.prerelease_specified = @prerelease_specified = {}
- requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }
-
- verify_gemfile_dependencies_are_found!(requirements)
- dg = @resolver.resolve(requirements, @base_dg)
- dg.
- map(&:payload).
- reject {|sg| sg.name.end_with?("\0") }.
- map(&:to_specs).
- flatten
- rescue Molinillo::VersionConflict => e
- message = version_conflict_message(e)
- raise VersionConflict.new(e.conflicts.keys.uniq, message)
- rescue Molinillo::CircularDependencyError => e
- names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
- raise CyclicDependencyError, "Your bundle requires gems that depend" \
- " on each other, creating an infinite loop. Please remove" \
- " #{names.count > 1 ? "either " : ""}#{names.join(" or ")}" \
- " and try again."
+ def start
+ @requirements = @base.requirements
+ @packages = @base.packages
+
+ root, logger = setup_solver
+
+ Bundler.ui.info "Resolving dependencies...", true
+
+ solve_versions(:root => root, :logger => logger)
end
- include Molinillo::UI
-
- # Conveys debug information to the user.
- #
- # @param [Integer] depth the current depth of the resolution process.
- # @return [void]
- def debug(depth = 0)
- return unless debug?
- debug_info = yield
- debug_info = debug_info.inspect unless debug_info.is_a?(String)
- puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" }
+ def setup_solver
+ root = Resolver::Root.new(name_for_explicit_dependency_source)
+ root_version = Resolver::Candidate.new(0)
+
+ @all_specs = Hash.new do |specs, name|
+ specs[name] = source_for(name).specs.search(name).reject do |s|
+ s.dependencies.any? {|d| d.name == name && !d.requirement.satisfied_by?(s.version) } # ignore versions that depend on themselves incorrectly
+ end.sort_by {|s| [s.version, s.platform.to_s] }
+ end
+
+ @sorted_versions = Hash.new do |candidates, package|
+ candidates[package] = if package.root?
+ [root_version]
+ else
+ all_versions_for(package).sort
+ end
+ end
+
+ root_dependencies = prepare_dependencies(@requirements, @packages)
+
+ @cached_dependencies = Hash.new do |dependencies, package|
+ dependencies[package] = if package.root?
+ { root_version => root_dependencies }
+ else
+ Hash.new do |versions, version|
+ versions[version] = to_dependency_hash(version.dependencies.reject {|d| d.name == package.name }, @packages)
+ end
+ end
+ end
+
+ logger = Bundler::UI::Shell.new
+ logger.level = debug? ? "debug" : "warn"
+
+ [root, logger]
end
- def debug?
- return @debug_mode if defined?(@debug_mode)
- @debug_mode =
- ENV["BUNDLER_DEBUG_RESOLVER"] ||
- ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
- ENV["DEBUG_RESOLVER"] ||
- ENV["DEBUG_RESOLVER_TREE"] ||
- false
+ def solve_versions(root:, logger:)
+ solver = PubGrub::VersionSolver.new(:source => self, :root => root, :logger => logger)
+ result = solver.solve
+ result.map {|package, version| version.to_specs(package) }.flatten.uniq
+ rescue PubGrub::SolveFailure => e
+ incompatibility = e.incompatibility
+
+ names_to_unlock, names_to_allow_prereleases_for, extended_explanation = find_names_to_relax(incompatibility)
+
+ names_to_relax = names_to_unlock + names_to_allow_prereleases_for
+
+ if names_to_relax.any?
+ if names_to_unlock.any?
+ Bundler.ui.debug "Found conflicts with locked dependencies. Will retry with #{names_to_unlock.join(", ")} unlocked...", true
+
+ @base.unlock_names(names_to_unlock)
+ end
+
+ if names_to_allow_prereleases_for.any?
+ Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retrying considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
+
+ @base.include_prereleases(names_to_allow_prereleases_for)
+ end
+
+ root, logger = setup_solver
+
+ Bundler.ui.debug "Retrying resolution...", true
+ retry
+ end
+
+ explanation = e.message
+
+ if extended_explanation
+ explanation << "\n\n"
+ explanation << extended_explanation
+ end
+
+ raise SolveFailure.new(explanation)
end
- def before_resolution
- Bundler.ui.info "Resolving dependencies...", debug?
+ def find_names_to_relax(incompatibility)
+ names_to_unlock = []
+ names_to_allow_prereleases_for = []
+ extended_explanation = nil
+
+ while incompatibility.conflict?
+ cause = incompatibility.cause
+ incompatibility = cause.incompatibility
+
+ incompatibility.terms.each do |term|
+ package = term.package
+ name = package.name
+
+ if base_requirements[name]
+ names_to_unlock << name
+ elsif package.ignores_prereleases?
+ names_to_allow_prereleases_for << name
+ end
+
+ no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
+ next unless no_versions_incompat
+
+ extended_explanation = no_versions_incompat.extended_explanation
+ end
+ end
+
+ [names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, extended_explanation]
end
- def after_resolution
- Bundler.ui.info ""
+ def parse_dependency(package, dependency)
+ range = if repository_for(package).is_a?(Source::Gemspec)
+ PubGrub::VersionRange.any
+ else
+ requirement_to_range(dependency)
+ end
+
+ PubGrub::VersionConstraint.new(package, :range => range)
end
- def indicate_progress
- Bundler.ui.info ".", false unless debug?
+ def versions_for(package, range=VersionRange.any)
+ versions = range.select_versions(@sorted_versions[package])
+
+ sort_versions(package, versions)
end
- include Molinillo::SpecificationProvider
+ def no_versions_incompatibility_for(package, unsatisfied_term)
+ cause = PubGrub::Incompatibility::NoVersions.new(unsatisfied_term)
+ name = package.name
+ constraint = unsatisfied_term.constraint
+ constraint_string = constraint.constraint_string
+ requirements = constraint_string.split(" OR ").map {|req| Gem::Requirement.new(req.split(",")) }
+
+ if name == "bundler" && bundler_pinned_to_current_version?
+ custom_explanation = "the current Bundler version (#{Bundler::VERSION}) does not satisfy #{constraint}"
+ extended_explanation = bundler_not_found_message(requirements)
+ else
+ specs_matching_other_platforms = filter_matching_specs(@all_specs[name], requirements)
- def dependencies_for(specification)
- specification.dependencies_for_activated_platforms
+ platforms_explanation = specs_matching_other_platforms.any? ? " for any resolution platforms (#{package.platforms.join(", ")})" : ""
+ custom_explanation = "#{constraint} could not be found in #{repository_for(package)}#{platforms_explanation}"
+
+ label = "#{name} (#{constraint_string})"
+ extended_explanation = other_specs_matching_message(specs_matching_other_platforms, label) if specs_matching_other_platforms.any?
+ end
+
+ Incompatibility.new([unsatisfied_term], :cause => cause, :custom_explanation => custom_explanation, :extended_explanation => extended_explanation)
end
- 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])
+ def debug?
+ ENV["BUNDLER_DEBUG_RESOLVER"] ||
+ ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
+ ENV["DEBUG_RESOLVER"] ||
+ ENV["DEBUG_RESOLVER_TREE"] ||
+ false
+ end
- if vertex = @base_dg.vertex_named(name)
- locked_requirement = vertex.payload.requirement
- end
+ def incompatibilities_for(package, version)
+ package_deps = @cached_dependencies[package]
+ sorted_versions = @sorted_versions[package]
+ package_deps[version].map do |dep_package, dep_constraint|
+ low = high = sorted_versions.index(version)
- 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? }
- results = pre + results
+ # find version low such that all >= low share the same dep
+ while low > 0 && package_deps[sorted_versions[low - 1]][dep_package] == dep_constraint
+ low -= 1
end
-
- spec_groups = if results.any?
- nested = []
- results.each do |spec|
- version, specs = nested.last
- if version == spec.version
- specs << spec
- else
- nested << [spec.version, [spec]]
- end
+ low =
+ if low == 0
+ nil
+ else
+ sorted_versions[low]
end
- nested.reduce([]) do |groups, (version, specs)|
- next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
- specs_by_platform = Hash.new do |current_specs, current_platform|
- current_specs[current_platform] = select_best_platform_match(specs, current_platform)
- end
+ # find version high such that all < high share the same dep
+ while high < sorted_versions.length && package_deps[sorted_versions[high]][dep_package] == dep_constraint
+ high += 1
+ end
+ high =
+ if high == sorted_versions.length
+ nil
+ else
+ sorted_versions[high]
+ end
- spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY)
- groups << spec_group_ruby if spec_group_ruby
+ range = PubGrub::VersionRange.new(:min => low, :max => high, :include_min => true)
- next groups if @resolving_only_for_ruby
+ self_constraint = PubGrub::VersionConstraint.new(package, :range => range)
- spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform)
- groups << spec_group if spec_group
+ dep_term = PubGrub::Term.new(dep_constraint, false)
+ self_term = PubGrub::Term.new(self_constraint, true)
- groups
- end
- else
- []
- end
- # GVP handles major itself, but it's still a bit risky to trust it with it
- # until we get it settled with new behavior. For 2.x it can take over all cases.
- if !@use_gvp
- spec_groups
- else
- @gem_version_promoter.sort_versions(dependency, spec_groups)
+ custom_explanation = if dep_package.meta? && package.root?
+ "current #{dep_package} version is #{dep_constraint.constraint_string}"
end
+
+ PubGrub::Incompatibility.new([self_term, dep_term], :cause => :dependency, :custom_explanation => custom_explanation)
end
end
- def index_for(dependency)
- source_for(dependency.name).specs
+ def all_versions_for(package)
+ name = package.name
+ results = (@base[name] + filter_prereleases(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
+
+ if name == "bundler" && !bundler_pinned_to_current_version?
+ bundler_spec = Gem.loaded_specs["bundler"]
+ results << bundler_spec if bundler_spec
+ end
+
+ locked_requirement = base_requirements[name]
+ results = filter_matching_specs(results, locked_requirement) if locked_requirement
+
+ versions = results.group_by(&:version).reduce([]) do |groups, (version, specs)|
+ platform_specs = package.platforms.flat_map {|platform| select_best_platform_match(specs, platform) }
+ next groups if platform_specs.empty?
+
+ ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
+ groups << Resolver::Candidate.new(version, :specs => ruby_specs) if ruby_specs.any?
+
+ next groups if platform_specs == ruby_specs || package.force_ruby_platform?
+
+ groups << Resolver::Candidate.new(version, :specs => platform_specs)
+
+ groups
+ end
+
+ sort_versions(package, versions)
end
def source_for(name)
@source_requirements[name] || @source_requirements[:default]
end
- def results_for(dependency, base)
- index_for(dependency).search(dependency, base)
+ def default_bundler_source
+ @source_requirements[:default_bundler]
end
- def name_for(dependency)
- dependency.name
+ def bundler_pinned_to_current_version?
+ !default_bundler_source.nil?
end
def name_for_explicit_dependency_source
@@ -186,211 +274,154 @@ module Bundler
"Gemfile"
end
- def name_for_locking_dependency_source
- Bundler.default_lockfile.basename.to_s
- rescue StandardError
- "Gemfile.lock"
+ def raise_not_found!(package)
+ name = package.name
+ source = source_for(name)
+ specs = @all_specs[name]
+ matching_part = name
+ requirement_label = SharedHelpers.pretty_dependency(package.dependency)
+ cache_message = begin
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
+ rescue GemfileNotFound
+ nil
+ end
+ specs_matching_requirement = filter_matching_specs(specs, package.dependency.requirement)
+
+ if specs_matching_requirement.any?
+ specs = specs_matching_requirement
+ matching_part = requirement_label
+ platforms = package.platforms
+ platform_label = platforms.size == 1 ? "platform '#{platforms.first}" : "platforms '#{platforms.join("', '")}"
+ requirement_label = "#{requirement_label}' with #{platform_label}"
+ end
+
+ message = String.new("Could not find gem '#{requirement_label}' in #{source}#{cache_message}.\n")
+
+ if specs.any?
+ message << "\n#{other_specs_matching_message(specs, matching_part)}"
+ end
+
+ raise GemNotFound, message
end
- def requirement_satisfied_by?(requirement, activated, spec)
- requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
+ private
+
+ def filter_matching_specs(specs, requirements)
+ Array(requirements).flat_map do |requirement|
+ specs.select {| spec| requirement_satisfied_by?(requirement, spec) }
+ end
+ end
+
+ def filter_prereleases(specs, package)
+ return specs unless package.ignores_prereleases? && specs.size > 1
+
+ specs.reject {|s| s.version.prerelease? }
end
- def dependencies_equal?(dependencies, other_dependencies)
- dependencies.map(&:dep) == other_dependencies.map(&:dep)
+ def requirement_satisfied_by?(requirement, spec)
+ requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
end
- def sort_dependencies(dependencies, activated, conflicts)
- dependencies.sort_by do |dependency|
- name = name_for(dependency)
- vertex = activated.vertex_named(name)
- [
- @base_dg.vertex_named(name) ? 0 : 1,
- vertex.payload ? 0 : 1,
- vertex.root? ? 0 : 1,
- amount_constrained(dependency),
- conflicts[name] ? 0 : 1,
- vertex.payload ? 0 : search_for(dependency).count,
- self.class.platform_sort_key(dependency.__platform),
- ]
+ def sort_versions(package, versions)
+ if versions.size > 1
+ @gem_version_promoter.sort_versions(package, versions).reverse
+ else
+ versions
end
end
- def self.platform_sort_key(platform)
- # Prefer specific platform to not specific platform
- return ["99-LAST", "", "", ""] if Gem::Platform::RUBY == platform
- ["00", *platform.to_a.map {|part| part || "" }]
+ def repository_for(package)
+ source_for(package.name)
end
- private
+ def base_requirements
+ @base.base_requirements
+ end
- # returns an integer \in (-\infty, 0]
- # a number closer to 0 means the dependency is less constraining
- #
- # dependencies w/ 0 or 1 possibilities (ignoring version requirements)
- # are given very negative values, so they _always_ sort first,
- # before dependencies that are unconstrained
- def amount_constrained(dependency)
- @amount_constrained ||= {}
- @amount_constrained[dependency.name] ||= begin
- if (base = @base[dependency.name]) && !base.empty?
- dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
- else
- all = index_for(dependency).search(dependency.name).size
+ def prepare_dependencies(requirements, packages)
+ to_dependency_hash(requirements, packages).map do |dep_package, dep_constraint|
+ name = dep_package.name
- if all <= 1
- all - 1_000_000
- else
- search = search_for(dependency)
- search = @prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
- search - all
- end
+ next [dep_package, dep_constraint] if name == "bundler"
+
+ versions = versions_for(dep_package, dep_constraint.range)
+ if versions.empty? && dep_package.ignores_prereleases?
+ @sorted_versions.delete(dep_package)
+ dep_package.consider_prereleases!
+ versions = versions_for(dep_package, dep_constraint.range)
end
- end
+ next [dep_package, dep_constraint] unless versions.empty?
+
+ next unless dep_package.current_platform?
+
+ raise_not_found!(dep_package)
+ end.compact.to_h
end
- def verify_gemfile_dependencies_are_found!(requirements)
- requirements.each do |requirement|
- name = requirement.name
- next if name == "bundler"
- next unless search_for(requirement).empty?
-
- cache_message = begin
- " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
- rescue GemfileNotFound
- nil
- end
-
- if (base = @base[name]) && !base.empty?
- version = base.first.version
- message = "You have requested:\n" \
- " #{name} #{requirement.requirement}\n\n" \
- "The bundle currently has #{name} locked at #{version}.\n" \
- "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.search(name)
- versions_with_platforms = specs.map {|s| [s.version, s.platform] }
- message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
- message << if versions_with_platforms.any?
- "The source contains the following versions of '#{name}': #{formatted_versions_with_platforms(versions_with_platforms)}"
- else
- "The source does not contain any versions of '#{name}'"
- end
+ def other_specs_matching_message(specs, requirement)
+ message = String.new("The source contains the following gems matching '#{requirement}':\n")
+ message << specs.map {|s| " * #{s.full_name}" }.join("\n")
+ message
+ end
+
+ def requirement_to_range(requirement)
+ ranges = requirement.requirements.map do |(op, version)|
+ ver = Resolver::Candidate.new(version).generic!
+ platform_ver = Resolver::Candidate.new(version).platform_specific!
+
+ case op
+ when "~>"
+ name = "~> #{ver}"
+ bump = Resolver::Candidate.new(version.bump.to_s + ".A")
+ PubGrub::VersionRange.new(:name => name, :min => ver, :max => bump, :include_min => true)
+ when ">"
+ PubGrub::VersionRange.new(:min => platform_ver)
+ when ">="
+ PubGrub::VersionRange.new(:min => ver, :include_min => true)
+ when "<"
+ PubGrub::VersionRange.new(:max => ver)
+ when "<="
+ PubGrub::VersionRange.new(:max => platform_ver, :include_max => true)
+ when "="
+ PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true)
+ when "!="
+ PubGrub::VersionRange.new(:min => ver, :max => platform_ver, :include_min => true, :include_max => true).invert
else
- message = "Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in any of the gem sources " \
- "listed in your Gemfile#{cache_message}."
+ raise "bad version specifier: #{op}"
end
- raise GemNotFound, message
end
+
+ ranges.inject(&:intersect)
end
- def formatted_versions_with_platforms(versions_with_platforms)
- version_platform_strs = versions_with_platforms.map do |vwp|
- version = vwp.first
- platform = vwp.last
- version_platform_str = String.new(version.to_s)
- version_platform_str << " #{platform}" unless platform.nil? || platform == Gem::Platform::RUBY
- version_platform_str
+ def to_dependency_hash(dependencies, packages)
+ dependencies.inject({}) do |deps, dep|
+ package = packages[dep.name]
+
+ current_req = deps[package]
+ new_req = parse_dependency(package, dep.requirement)
+
+ deps[package] = if current_req
+ current_req.intersect(new_req)
+ else
+ new_req
+ end
+
+ deps
end
- version_platform_strs.join(", ")
end
- def version_conflict_message(e)
- # only show essential conflicts, if possible
- conflicts = e.conflicts.dup
+ def bundler_not_found_message(conflict_dependencies)
+ candidate_specs = filter_matching_specs(default_bundler_source.specs.search("bundler"), conflict_dependencies)
- if conflicts["bundler"]
- conflicts.replace("bundler" => conflicts["bundler"])
+ if candidate_specs.any?
+ target_version = candidate_specs.last.version
+ new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
+ "Your bundle requires a different version of Bundler than the one you're running.\n" \
+ "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
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
+ "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
end
-
- e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
-
- solver_name = "Bundler"
- possibility_type = "gem"
- e.message_with_trees(
- :solver_name => solver_name,
- :possibility_type => possibility_type,
- :reduce_trees => lambda do |trees|
- # called first, because we want to reduce the amount of work required to find maximal empty sets
- trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
-
- # bail out if tree size is too big for Array#combination to make any sense
- return trees if trees.size > 15
- maximal = 1.upto(trees.size).map do |size|
- trees.map(&:last).flatten(1).combination(size).to_a
- end.flatten(1).select do |deps|
- Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
- end.min_by(&:size)
-
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
-
- trees.sort_by {|t| t.reverse.map(&:name) }
- end,
- :printable_requirement => lambda {|req| SharedHelpers.pretty_dependency(req) },
- :additional_message_for_conflict => lambda do |o, name, conflict|
- if name == "bundler"
- o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
-
- 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_source = conflict.requirement.source || source_for(name)
-
- metadata_requirement = name.end_with?("\0")
-
- o << "Could not find gem '" unless metadata_requirement
- o << SharedHelpers.pretty_dependency(conflict.requirement)
- o << "'" unless metadata_requirement
- if conflict.requirement_trees.first.size > 1
- o << ", which is required by "
- o << "gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
- end
- o << " "
-
- o << if metadata_requirement
- "is not available in #{relevant_source}"
- else
- "in #{relevant_source}.\n"
- end
- end
- end,
- :version_for_spec => lambda {|spec| spec.version },
- :incompatible_version_message_for_conflict => lambda do |name, _conflict|
- if name.end_with?("\0")
- %(#{solver_name} found conflicting requirements for the #{name} version:)
- else
- %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
- end
- end
- )
end
end
end
diff --git a/lib/bundler/resolver/base.rb b/lib/bundler/resolver/base.rb
new file mode 100644
index 0000000000..e5c3763c3f
--- /dev/null
+++ b/lib/bundler/resolver/base.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require_relative "package"
+
+module Bundler
+ class Resolver
+ class Base
+ attr_reader :packages, :requirements, :source_requirements
+
+ def initialize(source_requirements, dependencies, base, platforms, options)
+ @source_requirements = source_requirements
+
+ @base = base
+
+ @packages = Hash.new do |hash, name|
+ hash[name] = Package.new(name, platforms, **options)
+ end
+
+ @requirements = dependencies.map do |dep|
+ dep_platforms = dep.gem_platforms(platforms)
+
+ # Dependencies scoped to external platforms are ignored
+ next if dep_platforms.empty?
+
+ name = dep.name
+
+ @packages[name] = Package.new(name, dep_platforms, **options.merge(:dependency => dep))
+
+ dep
+ end.compact
+ end
+
+ def [](name)
+ @base[name]
+ end
+
+ def delete(specs)
+ @base.delete(specs)
+ end
+
+ def get_package(name)
+ @packages[name]
+ end
+
+ def base_requirements
+ @base_requirements ||= build_base_requirements
+ end
+
+ def unlock_names(names)
+ indirect_pins = indirect_pins(names)
+
+ if indirect_pins.any?
+ loosen_names(indirect_pins)
+ else
+ pins = pins(names)
+
+ if pins.any?
+ loosen_names(pins)
+ else
+ unrestrict_names(names)
+ end
+ end
+ end
+
+ def include_prereleases(names)
+ names.each do |name|
+ get_package(name).consider_prereleases!
+ end
+ end
+
+ private
+
+ def indirect_pins(names)
+ names.select {|name| @base_requirements[name].exact? && @requirements.none? {|dep| dep.name == name } }
+ end
+
+ def pins(names)
+ names.select {|name| @base_requirements[name].exact? }
+ end
+
+ def loosen_names(names)
+ names.each do |name|
+ version = @base_requirements[name].requirements.first[1]
+
+ @base_requirements[name] = Gem::Requirement.new(">= #{version}")
+
+ @base.delete_by_name(name)
+ end
+ end
+
+ def unrestrict_names(names)
+ names.each do |name|
+ @base_requirements.delete(name)
+ end
+ end
+
+ def build_base_requirements
+ base_requirements = {}
+ @base.each do |ls|
+ req = Gem::Requirement.new(ls.version)
+ base_requirements[ls.name] = req
+ end
+ base_requirements
+ end
+ end
+ end
+end
diff --git a/lib/bundler/resolver/candidate.rb b/lib/bundler/resolver/candidate.rb
new file mode 100644
index 0000000000..e695ef08ee
--- /dev/null
+++ b/lib/bundler/resolver/candidate.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require_relative "spec_group"
+
+module Bundler
+ class Resolver
+ #
+ # This class is a PubGrub compatible "Version" class that takes Bundler
+ # resolution complexities into account.
+ #
+ # Each Resolver::Candidate has a underlying `Gem::Version` plus a set of
+ # platforms. For example, 1.1.0-x86_64-linux is a different resolution candidate
+ # from 1.1.0 (generic). This is because different platform variants of the
+ # same gem version can bring different dependencies, so they need to be
+ # considered separately.
+ #
+ # Some candidates may also keep some information explicitly about the
+ # package the refer to. These candidates are referred to as "canonical" and
+ # are used when materializing resolution results back into RubyGems
+ # specifications that can be installed, written to lock files, and so on.
+ #
+ class Candidate
+ include Comparable
+
+ attr_reader :version
+
+ def initialize(version, specs: [])
+ @spec_group = Resolver::SpecGroup.new(specs)
+ @version = Gem::Version.new(version)
+ @ruby_only = specs.map(&:platform).uniq == [Gem::Platform::RUBY]
+ end
+
+ def dependencies
+ @spec_group.dependencies
+ end
+
+ def to_specs(package)
+ return [] if package.meta?
+
+ @spec_group.to_specs(package.force_ruby_platform?)
+ end
+
+ def generic!
+ @ruby_only = true
+
+ self
+ end
+
+ def platform_specific!
+ @ruby_only = false
+
+ self
+ end
+
+ def prerelease?
+ @version.prerelease?
+ end
+
+ def segments
+ @version.segments
+ end
+
+ def sort_obj
+ [@version, @ruby_only ? -1 : 1]
+ end
+
+ def <=>(other)
+ return unless other.is_a?(self.class)
+
+ sort_obj <=> other.sort_obj
+ end
+
+ def ==(other)
+ return unless other.is_a?(self.class)
+
+ sort_obj == other.sort_obj
+ end
+
+ def eql?(other)
+ return unless other.is_a?(self.class)
+
+ sort_obj.eql?(other.sort_obj)
+ end
+
+ def hash
+ sort_obj.hash
+ end
+
+ def to_s
+ @version.to_s
+ end
+ end
+ end
+end
diff --git a/lib/bundler/resolver/incompatibility.rb b/lib/bundler/resolver/incompatibility.rb
new file mode 100644
index 0000000000..c61151fbeb
--- /dev/null
+++ b/lib/bundler/resolver/incompatibility.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Bundler
+ class Resolver
+ class Incompatibility < PubGrub::Incompatibility
+ attr_reader :extended_explanation
+
+ def initialize(terms, cause:, custom_explanation: nil, extended_explanation: nil)
+ @extended_explanation = extended_explanation
+
+ super(terms, :cause => cause, :custom_explanation => custom_explanation)
+ end
+ end
+ end
+end
diff --git a/lib/bundler/resolver/package.rb b/lib/bundler/resolver/package.rb
new file mode 100644
index 0000000000..7499a75006
--- /dev/null
+++ b/lib/bundler/resolver/package.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Bundler
+ class Resolver
+ #
+ # Represents a gem being resolved, in a format PubGrub likes.
+ #
+ # The class holds the following information:
+ #
+ # * Platforms this gem will be resolved on.
+ # * The locked version of this gem resolution should favor (if any).
+ # * Whether the gem should be unlocked to its latest version.
+ # * The dependency explicit set in the Gemfile for this gem (if any).
+ #
+ class Package
+ attr_reader :name, :platforms, :dependency, :locked_version
+
+ def initialize(name, platforms, locked_specs:, unlock:, prerelease: false, dependency: nil)
+ @name = name
+ @platforms = platforms
+ @locked_version = locked_specs[name].first&.version
+ @unlock = unlock
+ @dependency = dependency || Dependency.new(name, @locked_version)
+ @prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
+ end
+
+ def to_s
+ @name.delete("\0")
+ end
+
+ def root?
+ false
+ end
+
+ def meta?
+ @name.end_with?("\0")
+ end
+
+ def ==(other)
+ self.class == other.class && @name == other.name
+ end
+
+ def hash
+ @name.hash
+ end
+
+ def unlock?
+ @unlock.empty? || @unlock.include?(name)
+ end
+
+ def ignores_prereleases?
+ @prerelease == :ignore
+ end
+
+ def prerelease_specified?
+ @prerelease == :consider_first
+ end
+
+ def consider_prereleases!
+ @prerelease = :consider_last
+ end
+
+ def force_ruby_platform?
+ @dependency.force_ruby_platform
+ end
+
+ def current_platform?
+ @dependency.current_platform?
+ end
+ end
+ end
+end
diff --git a/lib/bundler/resolver/root.rb b/lib/bundler/resolver/root.rb
new file mode 100644
index 0000000000..e5eb634fb8
--- /dev/null
+++ b/lib/bundler/resolver/root.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require_relative "package"
+
+module Bundler
+ class Resolver
+ #
+ # Represents the Gemfile from the resolver's perspective. It's the root
+ # package and Gemfile entries depend on it.
+ #
+ class Root < Package
+ def initialize(name)
+ @name = name
+ end
+
+ def meta?
+ true
+ end
+
+ def root?
+ true
+ end
+ end
+ end
+end
diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb
index 8f4fd18c46..b44c19a73f 100644
--- a/lib/bundler/resolver/spec_group.rb
+++ b/lib/bundler/resolver/spec_group.rb
@@ -3,107 +3,79 @@
module Bundler
class Resolver
class SpecGroup
- attr_accessor :name, :version, :source
- 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)
+ def initialize(specs)
+ @specs = specs
end
- 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 = relevant_platforms
- @dependencies = Hash.new do |dependencies, platforms|
- dependencies[platforms] = dependencies_for(platforms)
- end
- @specs = specs
+ def empty?
+ @specs.empty?
end
- def to_specs
- activated_platforms.map do |p|
- specs = @specs[p]
- next unless specs.any?
-
- 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
+ def name
+ @name ||= exemplary_spec.name
end
- def to_s
- activated_platforms_string = sorted_activated_platforms.join(", ")
- "#{name} (#{version}) (#{activated_platforms_string})"
+ def version
+ @version ||= exemplary_spec.version
end
- def dependencies_for_activated_platforms
- @dependencies[activated_platforms]
+ def source
+ @source ||= exemplary_spec.source
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
+ def to_specs(force_ruby_platform)
+ @specs.map do |s|
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
+ lazy_spec.force_ruby_platform = force_ruby_platform
+ lazy_spec.dependencies.replace s.dependencies
+ lazy_spec
+ end
end
- def eql?(other)
- return unless other.is_a?(SpecGroup)
- name.eql?(other.name) &&
- version.eql?(other.version) &&
- sorted_activated_platforms.eql?(other.sorted_activated_platforms) &&
- source.eql?(other.source)
+ def to_s
+ sorted_spec_names.join(", ")
end
- def hash
- name.hash ^ version.hash ^ sorted_activated_platforms.hash ^ source.hash
+ def dependencies
+ @dependencies ||= @specs.map do |spec|
+ __dependencies(spec) + metadata_dependencies(spec)
+ end.flatten.uniq
end
protected
- def sorted_activated_platforms
- activated_platforms.sort_by(&:to_s)
+ def sorted_spec_names
+ @sorted_spec_names ||= @specs.map(&:full_name).sort
end
private
- def dependencies_for(platforms)
- platforms.map do |platform|
- __dependencies(platform) + metadata_dependencies(platform)
- end.flatten
+ def exemplary_spec
+ @specs.first
end
- def __dependencies(platform)
+ def __dependencies(spec)
dependencies = []
- @specs[platform].first.dependencies.each do |dep|
+ spec.dependencies.each do |dep|
next if dep.type == :development
- dependencies << DepProxy.get_proxy(dep, platform)
+ dependencies << Dependency.new(dep.name, dep.requirement)
end
dependencies
end
- 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.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.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
- end
- dependencies
+ def metadata_dependencies(spec)
+ return [] if spec.is_a?(LazySpecification)
+
+ [
+ metadata_dependency("Ruby", spec.required_ruby_version),
+ metadata_dependency("RubyGems", spec.required_rubygems_version),
+ ].compact
+ end
+
+ def metadata_dependency(name, requirement)
+ return if requirement.nil? || requirement.none?
+
+ Dependency.new("#{name}\0", requirement)
end
end
end
diff --git a/lib/bundler/ruby_dsl.rb b/lib/bundler/ruby_dsl.rb
index f6ba220cd5..d054969e8d 100644
--- a/lib/bundler/ruby_dsl.rb
+++ b/lib/bundler/ruby_dsl.rb
@@ -5,11 +5,17 @@ module Bundler
def ruby(*ruby_version)
options = ruby_version.last.is_a?(Hash) ? ruby_version.pop : {}
ruby_version.flatten!
+
raise GemfileError, "Please define :engine_version" if options[:engine] && options[:engine_version].nil?
raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil?
+ if options[:file]
+ raise GemfileError, "Cannot specify version when using the file option" if ruby_version.any?
+ ruby_version << Bundler.read_file(options[:file]).strip
+ end
+
if options[:engine] == "ruby" && options[:engine_version] &&
- ruby_version != Array(options[:engine_version])
+ ruby_version != Array(options[:engine_version])
raise GemfileEvalError, "ruby_version must match the :engine_version for MRI"
end
@ruby_version = RubyVersion.new(ruby_version, options[:patchlevel], options[:engine], options[:engine_version])
diff --git a/lib/bundler/ruby_version.rb b/lib/bundler/ruby_version.rb
index 491f8c55a4..b5396abb6e 100644
--- a/lib/bundler/ruby_version.rb
+++ b/lib/bundler/ruby_version.rb
@@ -28,16 +28,16 @@ module Bundler
end
@gem_version = Gem::Requirement.create(@versions.first).requirements.first.last
- @input_engine = engine && engine.to_s
- @engine = engine && engine.to_s || "ruby"
+ @input_engine = engine&.to_s
+ @engine = engine&.to_s || "ruby"
@engine_versions = (engine_version && Array(engine_version)) || @versions
@engine_gem_version = Gem::Requirement.create(@engine_versions.first).requirements.first.last
- @patchlevel = patchlevel
+ @patchlevel = patchlevel || (@gem_version.prerelease? ? "-1" : nil)
end
def to_s(versions = self.versions)
output = String.new("ruby #{versions_string(versions)}")
- output << "p#{patchlevel}" if patchlevel
+ output << "p#{patchlevel}" if patchlevel && patchlevel != "-1"
output << " (#{engine} #{versions_string(engine_versions)})" unless engine == "ruby"
output
@@ -46,7 +46,7 @@ module Bundler
# @private
PATTERN = /
ruby\s
- ([\d.]+) # ruby version
+ (\d+\.\d+\.\d+(?:\.\S+)?) # ruby version
(?:p(-?\d+))? # optional patchlevel
(?:\s\((\S+)\s(.+)\))? # optional engine info
/xo.freeze
@@ -103,24 +103,11 @@ module Bundler
def self.system
ruby_engine = RUBY_ENGINE.dup
- ruby_version = ENV.fetch("BUNDLER_SPEC_RUBY_VERSION") { RUBY_VERSION }.dup
- ruby_engine_version = RUBY_ENGINE_VERSION.dup
+ ruby_version = Gem.ruby_version.to_s
+ ruby_engine_version = RUBY_ENGINE == "ruby" ? ruby_version : RUBY_ENGINE_VERSION.dup
patchlevel = RUBY_PATCHLEVEL.to_s
- @ruby_version ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
- end
-
- def to_gem_version_with_patchlevel
- @gem_version_with_patch ||= begin
- Gem::Version.create("#{@gem_version}.#{@patchlevel}")
- rescue ArgumentError
- @gem_version
- end
- end
-
- def exact?
- return @exact if defined?(@exact)
- @exact = versions.all? {|v| Gem::Requirement.create(v).exact? }
+ @system ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
end
private
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 2613207826..8981612706 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -4,14 +4,35 @@ require "pathname"
require "rubygems/specification"
-# Possible use in Gem::Specification#source below and require
-# shouldn't be deferred.
+# We can't let `Gem::Source` be autoloaded in the `Gem::Specification#source`
+# redefinition below, so we need to load it upfront. The reason is that if
+# Bundler monkeypatches are loaded before RubyGems activates an executable (for
+# example, through `ruby -rbundler -S irb`), gem activation might end up calling
+# the redefined `Gem::Specification#source` and triggering the `Gem::Source`
+# autoload. That would result in requiring "rubygems/source" inside another
+# require, which would trigger a monitor error and cause the `autoload` to
+# eventually fail. A better solution is probably to completely avoid autoloading
+# `Gem::Source` from the redefined `Gem::Specification#source`.
require "rubygems/source"
+require_relative "match_metadata"
+require_relative "force_platform"
require_relative "match_platform"
+# Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
+# versions and ignore patchlevels
+# (https://github.com/rubygems/rubygems/pull/5472,
+# https://github.com/rubygems/rubygems/pull/5486). May be removed once RubyGems
+# 3.3.12 support is dropped.
+unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
+ Gem.instance_variable_set(:@ruby_version, Gem::Version.new(RUBY_VERSION))
+end
+
module Gem
class Specification
+ include ::Bundler::MatchMetadata
+ include ::Bundler::MatchPlatform
+
attr_accessor :remote, :location, :relative_loaded_from
remove_method :source
@@ -24,12 +45,8 @@ module Gem
alias_method :rg_loaded_from, :loaded_from
def full_gem_path
- # this cannot check source.is_a?(Bundler::Plugin::API::Source)
- # because that _could_ trip the autoload, and if there are unresolved
- # gems at that time, this method could be called inside another require,
- # thus raising with that constant being undefined. Better to check a method
- if source.respond_to?(:path) || (source.respond_to?(:bundler_plugin_api_source?) && source.bundler_plugin_api_source?)
- Pathname.new(loaded_from).dirname.expand_path(source.root).to_s.tap{|x| x.untaint if RUBY_VERSION < "2.7" }
+ if source.respond_to?(:root)
+ Pathname.new(loaded_from).dirname.expand_path(source.root).to_s.tap {|x| x.untaint if RUBY_VERSION < "2.7" }
else
rg_full_gem_path
end
@@ -49,7 +66,9 @@ module Gem
alias_method :rg_extension_dir, :extension_dir
def extension_dir
- @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name)
+ # following instance variable is already used in original method
+ # and that is the reason to prefix it with bundler_ and add rubocop exception
+ @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name) # rubocop:disable Naming/MemoizedInstanceVariableName
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
@@ -62,6 +81,23 @@ module Gem
full_gem_path
end
+ unless const_defined?(:LATEST_RUBY_WITHOUT_PATCH_VERSIONS)
+ LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")
+
+ alias_method :rg_required_ruby_version=, :required_ruby_version=
+ def required_ruby_version=(req)
+ self.rg_required_ruby_version = req
+
+ @required_ruby_version.requirements.map! do |op, v|
+ if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
+ [op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
+ else
+ [op, v]
+ end
+ end
+ end
+ end
+
def groups
@groups ||= []
end
@@ -81,10 +117,25 @@ module Gem
gemfile
end
+ # Backfill missing YAML require when not defined. Fixed since 3.1.0.pre1.
+ module YamlBackfiller
+ def to_yaml(opts = {})
+ Gem.load_yaml unless defined?(::YAML)
+
+ super(opts)
+ end
+ end
+
+ prepend YamlBackfiller
+
def nondevelopment_dependencies
dependencies - development_dependencies
end
+ def deleted_gem?
+ !default_gem? && !File.directory?(full_gem_path)
+ end
+
private
def dependencies_to_gemfile(dependencies, group = nil)
@@ -105,10 +156,18 @@ module Gem
end
class Dependency
+ include ::Bundler::ForcePlatform
+
attr_accessor :source, :groups
alias_method :eql?, :==
+ def force_ruby_platform
+ return @force_ruby_platform if defined?(@force_ruby_platform) && !@force_ruby_platform.nil?
+
+ @force_ruby_platform = default_force_ruby_platform
+ end
+
def encode_with(coder)
to_yaml_properties.each do |ivar|
coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
@@ -146,9 +205,9 @@ module Gem
protected
def _requirements_sorted?
- return @_are_requirements_sorted if defined?(@_are_requirements_sorted)
+ return @_requirements_sorted if defined?(@_requirements_sorted)
strings = as_list
- @_are_requirements_sorted = strings == strings.sort
+ @_requirements_sorted = strings == strings.sort
end
def _with_sorted_requirements
@@ -179,11 +238,56 @@ module Gem
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)
+ JAVA = Gem::Platform.new("java")
+ MSWIN = Gem::Platform.new("mswin32")
+ MSWIN64 = Gem::Platform.new("mswin64")
+ MINGW = Gem::Platform.new("x86-mingw32")
+ X64_MINGW = [Gem::Platform.new("x64-mingw32"),
+ Gem::Platform.new("x64-mingw-ucrt")].freeze
+ WINDOWS = [MSWIN, MSWIN64, MINGW, X64_MINGW].flatten.freeze
+ X64_LINUX = Gem::Platform.new("x86_64-linux")
+ X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl")
+
+ if X64_LINUX === X64_LINUX_MUSL
+ remove_method :===
+
+ def ===(other)
+ return nil unless Gem::Platform === other
+
+ # universal-mingw32 matches x64-mingw-ucrt
+ return true if (@cpu == "universal" || other.cpu == "universal") &&
+ @os.start_with?("mingw") && other.os.start_with?("mingw")
+
+ # cpu
+ ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
+ (@cpu == "arm" && other.cpu.start_with?("arm"))) &&
+
+ # os
+ @os == other.os &&
+
+ # version
+ (
+ (@os != "linux" && (@version.nil? || other.version.nil?)) ||
+ (@os == "linux" && (normalized_linux_version_ext == other.normalized_linux_version_ext || ["musl#{@version}", "musleabi#{@version}", "musleabihf#{@version}"].include?(other.version))) ||
+ @version == other.version
+ )
+ end
+
+ # This is a copy of RubyGems 3.3.23 or higher `normalized_linux_method`.
+ # Once only 3.3.23 is supported, we can use the method in RubyGems.
+ def normalized_linux_version_ext
+ return nil unless @version
+
+ without_gnu_nor_abi_modifiers = @version.sub(/\Agnu/, "").sub(/eabi(hf)?\Z/, "")
+ return nil if without_gnu_nor_abi_modifiers.empty?
+
+ without_gnu_nor_abi_modifiers
+ end
+ end
+
+ if RUBY_ENGINE == "truffleruby" && !defined?(REUSE_AS_BINARY_ON_TRUFFLERUBY)
+ REUSE_AS_BINARY_ON_TRUFFLERUBY = %w[libv8 libv8-node sorbet-static].freeze
+ end
end
Platform.singleton_class.module_eval do
@@ -195,14 +299,43 @@ module Gem
def match_gem?(platform, gem_name)
match_platforms?(platform, Gem.platforms)
end
+ end
+
+ match_platforms_defined = Gem::Platform.respond_to?(:match_platforms?, true)
+
+ if !match_platforms_defined || Gem::Platform.send(:match_platforms?, Gem::Platform::X64_LINUX_MUSL, [Gem::Platform::X64_LINUX])
private
+ remove_method :match_platforms? if match_platforms_defined
+
def match_platforms?(platform, platforms)
platforms.any? do |local_platform|
platform.nil? ||
local_platform == platform ||
- (local_platform != Gem::Platform::RUBY && local_platform =~ platform)
+ (local_platform != Gem::Platform::RUBY && platform =~ local_platform)
+ end
+ end
+ end
+ end
+
+ # On universal Rubies, resolve the "universal" arch to the real CPU arch, without changing the extension directory.
+ class Specification
+ if /^universal\.(?<arch>.*?)-/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
+ local_platform = Platform.local
+ if local_platform.cpu == "universal"
+ ORIGINAL_LOCAL_PLATFORM = local_platform.to_s.freeze
+
+ local_platform.cpu = if arch == "arm64e" # arm64e is only permitted for Apple system binaries
+ "arm64"
+ else
+ arch
+ end
+
+ def extensions_dir
+ Gem.default_ext_dir_for(base_dir) ||
+ File.join(base_dir, "extensions", ORIGINAL_LOCAL_PLATFORM,
+ Gem.extension_api_version)
end
end
end
@@ -216,17 +349,7 @@ module Gem
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
+ Dir.glob(glob, :base => base_path).map! {|f| File.expand_path(f, base_path) }
end
end
end
-
-module Gem
- class Specification
- include ::Bundler::MatchPlatform
- end
-end
diff --git a/lib/bundler/rubygems_gem_installer.rb b/lib/bundler/rubygems_gem_installer.rb
index 8890582318..38035a00ac 100644
--- a/lib/bundler/rubygems_gem_installer.rb
+++ b/lib/bundler/rubygems_gem_installer.rb
@@ -16,14 +16,16 @@ module Bundler
spec.loaded_from = spec_file
# Completely remove any previous gem files
- FileUtils.rm_rf gem_dir
- FileUtils.rm_rf spec.extension_dir
+ strict_rm_rf gem_dir
+ strict_rm_rf spec.extension_dir
- FileUtils.mkdir_p gem_dir, :mode => 0o755
+ SharedHelpers.filesystem_access(gem_dir, :create) do
+ FileUtils.mkdir_p gem_dir, :mode => 0o755
+ end
extract_files
- build_extensions
+ build_extensions if spec.extensions.any?
write_build_info_file
run_post_build_hooks
@@ -31,7 +33,10 @@ module Bundler
generate_plugins
write_spec
- write_cache_file
+
+ SharedHelpers.filesystem_access("#{gem_home}/cache", :write) do
+ write_cache_file
+ end
say spec.post_install_message unless spec.post_install_message.nil?
@@ -61,32 +66,55 @@ module Bundler
def build_extensions
extension_cache_path = options[:bundler_extension_cache_path]
- unless extension_cache_path && extension_dir = spec.extension_dir
- require "shellwords" # compensate missing require in rubygems before version 3.2.25
+ extension_dir = spec.extension_dir
+ unless extension_cache_path && extension_dir
+ prepare_extension_build(extension_dir)
return super
end
- extension_dir = Pathname.new(extension_dir)
build_complete = SharedHelpers.filesystem_access(extension_cache_path.join("gem.build_complete"), :read, &:file?)
if build_complete && !options[:force]
- SharedHelpers.filesystem_access(extension_dir.parent, &:mkpath)
+ SharedHelpers.filesystem_access(File.dirname(extension_dir)) do |p|
+ FileUtils.mkpath p
+ end
SharedHelpers.filesystem_access(extension_cache_path) do
- FileUtils.cp_r extension_cache_path, spec.extension_dir
+ FileUtils.cp_r extension_cache_path, extension_dir
end
else
- require "shellwords" # compensate missing require in rubygems before version 3.2.25
+ prepare_extension_build(extension_dir)
super
- if extension_dir.directory? # not made for gems without extensions
- SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
- SharedHelpers.filesystem_access(extension_cache_path) do
- FileUtils.cp_r extension_dir, extension_cache_path
- end
+ SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
+ SharedHelpers.filesystem_access(extension_cache_path) do
+ FileUtils.cp_r extension_dir, extension_cache_path
end
end
end
+ def spec
+ if Bundler.rubygems.provides?("< 3.3.12") # RubyGems implementation rescues and re-raises errors before 3.3.12 and we don't want that
+ @package.spec
+ else
+ super
+ end
+ end
+
private
+ def prepare_extension_build(extension_dir)
+ SharedHelpers.filesystem_access(extension_dir, :create) do
+ FileUtils.mkdir_p extension_dir
+ end
+ require "shellwords" unless Bundler.rubygems.provides?(">= 3.2.25")
+ end
+
+ def strict_rm_rf(dir)
+ Bundler.rm_rf dir
+ rescue StandardError => e
+ raise unless File.exist?(dir)
+
+ raise DirectoryRemovalError.new(e, "Could not delete previous installation of `#{dir}`")
+ end
+
def validate_bundler_checksum(checksum)
return true if Bundler.settings[:disable_checksum_validation]
return true unless checksum
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index 21ce12ecda..d8b7886af7 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -12,32 +12,30 @@ module Bundler
EXT_LOCK = Monitor.new
end
- def self.version
- @version ||= Gem::Version.new(Gem::VERSION)
- end
-
- def self.provides?(req_str)
- Gem::Requirement.new(req_str).satisfied_by?(version)
- end
-
def initialize
@replaced_methods = {}
backport_ext_builder_monitor
end
def version
- self.class.version
+ @version ||= Gem.rubygems_version
end
def provides?(req_str)
- self.class.provides?(req_str)
+ Gem::Requirement.new(req_str).satisfied_by?(version)
+ end
+
+ def supports_bundler_trampolining?
+ provides?(">= 3.3.0.a")
end
def build_args
+ require "rubygems/command"
Gem::Command.build_args
end
def build_args=(args)
+ require "rubygems/command"
Gem::Command.build_args = args
end
@@ -84,16 +82,12 @@ 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)
@@ -110,18 +104,6 @@ module Bundler
obj.to_s
end
- def configuration
- require_relative "psyched_yaml"
- Gem.configuration
- rescue Gem::SystemExitException, LoadError => e
- Bundler.ui.error "#{e.class}: #{e.message}"
- Bundler.ui.trace e
- raise
- rescue YamlLibrarySyntaxError => e
- raise YamlSyntaxError.new(e, "Your RubyGems configuration, which is " \
- "usually located in ~/.gemrc, contains invalid YAML syntax.")
- end
-
def ruby_engine
Gem.ruby_engine
end
@@ -144,19 +126,6 @@ module Bundler
end
end
- def sources=(val)
- # Gem.configuration creates a new Gem::ConfigFile, which by default will read ~/.gemrc
- # If that file exists, its settings (including sources) will overwrite the values we
- # are about to set here. In order to avoid that, we force memoizing the config file now.
- configuration
-
- Gem.sources = val
- end
-
- def sources
- Gem.sources
- end
-
def gem_dir
Gem.dir
end
@@ -234,32 +203,9 @@ module Bundler
EXT_LOCK
end
- def with_build_args(args)
- ext_lock.synchronize do
- old_args = build_args
- begin
- self.build_args = args
- yield
- ensure
- self.build_args = old_args
- end
- end
- end
-
- def spec_from_gem(path, policy = nil)
- require "rubygems/security"
- require_relative "psyched_yaml"
- gem_from_path(path, security_policies[policy]).spec
- 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 ||
- e.message =~ /couldn't verify (meta)?data signature/i
- raise SecurityError,
- "The gem #{File.basename(path, ".gem")} can't be installed because " \
- "the security policy didn't allow it, with the message: #{e.message}"
- else
- raise e
- end
+ def spec_from_gem(path)
+ require "rubygems/package"
+ Gem::Package.new(path).spec
end
def build_gem(gem_dir, spec)
@@ -281,10 +227,14 @@ module Bundler
def reverse_rubygems_kernel_mixin
# Disable rubygems' gem activation system
- kernel = (class << ::Kernel; self; end)
- [kernel, ::Kernel].each do |k|
- if k.private_method_defined?(:gem_original_require)
- redefine_method(k, :require, k.instance_method(:gem_original_require))
+ if Gem.respond_to?(:discover_gems_on_require=)
+ Gem.discover_gems_on_require = false
+ else
+ kernel = (class << ::Kernel; self; end)
+ [kernel, ::Kernel].each do |k|
+ if k.private_method_defined?(:gem_original_require)
+ redefine_method(k, :require, k.instance_method(:gem_original_require))
+ end
end
end
end
@@ -297,7 +247,7 @@ module Bundler
kernel = (class << ::Kernel; self; end)
[kernel, ::Kernel].each do |kernel_class|
redefine_method(kernel_class, :gem) do |dep, *reqs|
- if executables && executables.include?(File.basename(caller.first.split(":").first))
+ if executables&.include?(File.basename(caller.first.split(":").first))
break
end
@@ -326,11 +276,7 @@ module Bundler
e = Gem::LoadError.new(message)
e.name = dep.name
- if e.respond_to?(:requirement=)
- e.requirement = dep.requirement
- elsif e.respond_to?(:version_requirement=)
- e.version_requirement = dep.requirement
- end
+ e.requirement = dep.requirement
raise e
end
@@ -502,14 +448,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
+ Bundler.safe_load_marshal(string)
+ 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)
@@ -519,12 +466,32 @@ 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}>"
@@ -532,30 +499,15 @@ module Bundler
def gem_remote_fetcher
require "rubygems/remote_fetcher"
- proxy = configuration[:http_proxy]
+ proxy = Gem.configuration[:http_proxy]
Gem::RemoteFetcher.new(proxy)
end
- def gem_from_path(path, policy = nil)
- require "rubygems/package"
- p = Gem::Package.new(path)
- p.security_policy = policy if policy
- p
- end
-
def build(spec, skip_validation = false)
require "rubygems/package"
Gem::Package.build(spec, skip_validation)
end
- def repository_subdirectories
- Gem::REPOSITORY_SUBDIRECTORIES
- end
-
- def install_with_build_args(args)
- yield
- end
-
def path_separator
Gem.path_separator
end
@@ -585,6 +537,10 @@ module Bundler
end
end
+ def find_bundler(version)
+ find_name("bundler").find {|s| s.version.to_s == version }
+ end
+
def find_name(name)
Gem::Specification.stubs_for(name).map(&:to_spec)
end
@@ -598,14 +554,6 @@ module Bundler
Gem::Specification.send(:default_stubs, "*.gemspec")
end
end
-
- def use_gemdeps(gemfile)
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile)
- require_relative "gemdeps"
- runtime = Bundler.setup
- activated_spec_names = runtime.requested_specs.map(&:to_spec).sort_by(&:name)
- [Gemdeps.new(runtime), activated_spec_names]
- end
end
def self.rubygems
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 287fa1cfe9..95cf78dd41 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -22,10 +22,6 @@ module Bundler
# 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)
@@ -98,13 +94,13 @@ module Bundler
definition_method :requires
def lock(opts = {})
- return if @definition.nothing_changed? && !@definition.unlocking?
+ return if @definition.no_resolve_needed?
@definition.lock(Bundler.default_lockfile, opts[:preserve_unknown_sections])
end
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)
@@ -112,11 +108,23 @@ 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)
- spec.source.send(:fetch_gem, spec) if Bundler.settings[:cache_all_platforms] && spec.source.respond_to?(:fetch_gem, true)
spec.source.cache(spec, custom_path) if spec.source.respond_to?(:cache)
end
@@ -256,7 +264,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
@@ -282,7 +290,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
@@ -292,11 +300,7 @@ module Bundler
e = Gem::LoadError.new "You have already activated #{activated_spec.name} #{activated_spec.version}, " \
"but your Gemfile requires #{spec.name} #{spec.version}. #{suggestion}"
e.name = spec.name
- if e.respond_to?(:requirement=)
- e.requirement = Gem::Requirement.new(spec.version.to_s)
- else
- e.version_requirement = Gem::Requirement.new(spec.version.to_s)
- end
+ e.requirement = Gem::Requirement.new(spec.version.to_s)
raise e
end
end
diff --git a/lib/bundler/safe_marshal.rb b/lib/bundler/safe_marshal.rb
new file mode 100644
index 0000000000..50aa0f60a6
--- /dev/null
+++ b/lib/bundler/safe_marshal.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Bundler
+ module SafeMarshal
+ ALLOWED_CLASSES = [
+ Array,
+ FalseClass,
+ Gem::Specification,
+ Gem::Version,
+ Hash,
+ String,
+ Symbol,
+ Time,
+ TrueClass,
+ ].freeze
+
+ ERROR = "Unexpected class %s present in marshaled data. Only %s are allowed."
+
+ PROC = proc do |object|
+ object.tap do
+ unless ALLOWED_CLASSES.include?(object.class)
+ raise TypeError, format(ERROR, object.class, ALLOWED_CLASSES.join(", "))
+ end
+ end
+ end
+
+ def self.proc
+ PROC
+ end
+ end
+end
diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb
new file mode 100644
index 0000000000..827f3f9222
--- /dev/null
+++ b/lib/bundler/self_manager.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+module Bundler
+ #
+ # This class handles installing and switching to the version of bundler needed
+ # by an application.
+ #
+ class SelfManager
+ def restart_with_locked_bundler_if_needed
+ return unless needs_switching? && installed?
+
+ restart_with(lockfile_version)
+ end
+
+ def install_locked_bundler_and_restart_with_it_if_needed
+ return unless needs_switching?
+
+ Bundler.ui.info \
+ "Bundler #{current_version} is running, but your lockfile was generated with #{lockfile_version}. " \
+ "Installing Bundler #{lockfile_version} and restarting using that version."
+
+ install_and_restart_with(lockfile_version)
+ end
+
+ def update_bundler_and_restart_with_it_if_needed(target)
+ return unless autoswitching_applies?
+
+ spec = resolve_update_version_from(target)
+ return unless spec
+
+ version = spec.version
+
+ Bundler.ui.info "Updating bundler to #{version}."
+
+ install(spec)
+
+ restart_with(version)
+ end
+
+ private
+
+ def install_and_restart_with(version)
+ requirement = Gem::Requirement.new(version)
+ spec = find_latest_matching_spec(requirement)
+
+ if spec.nil?
+ Bundler.ui.warn "Your lockfile is locked to a version of bundler (#{lockfile_version}) that doesn't exist at https://rubygems.org/. Going on using #{current_version}"
+ return
+ end
+
+ install(spec)
+ rescue StandardError => e
+ Bundler.ui.trace e
+ Bundler.ui.warn "There was an error installing the locked bundler version (#{lockfile_version}), rerun with the `--verbose` flag for more details. Going on using bundler #{current_version}."
+ else
+ restart_with(version)
+ end
+
+ def install(spec)
+ spec.source.install(spec)
+ end
+
+ def restart_with(version)
+ configured_gem_home = ENV["GEM_HOME"]
+ configured_gem_path = ENV["GEM_PATH"]
+
+ cmd = [$PROGRAM_NAME, *ARGV]
+ cmd.unshift(Gem.ruby) unless File.executable?($PROGRAM_NAME)
+
+ Bundler.with_original_env do
+ Kernel.exec(
+ { "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => version.to_s },
+ *cmd
+ )
+ end
+ end
+
+ def needs_switching?
+ autoswitching_applies? &&
+ released?(lockfile_version) &&
+ !running?(lockfile_version) &&
+ !updating?
+ end
+
+ def autoswitching_applies?
+ ENV["BUNDLER_VERSION"].nil? &&
+ Bundler.rubygems.supports_bundler_trampolining? &&
+ SharedHelpers.in_bundle? &&
+ lockfile_version
+ end
+
+ def resolve_update_version_from(target)
+ requirement = Gem::Requirement.new(target)
+ update_candidate = find_latest_matching_spec(requirement)
+
+ if update_candidate.nil?
+ raise InvalidOption, "The `bundle update --bundler` target version (#{target}) does not exist"
+ end
+
+ resolved_version = update_candidate.version
+ needs_update = requirement.specific? ? !running?(resolved_version) : running_older_than?(resolved_version)
+
+ return unless needs_update
+
+ update_candidate
+ end
+
+ def local_specs
+ @local_specs ||= Bundler::Source::Rubygems.new("allow_local" => true).specs.select {|spec| spec.name == "bundler" }
+ end
+
+ def remote_specs
+ @remote_specs ||= begin
+ source = Bundler::Source::Rubygems.new("remotes" => "https://rubygems.org")
+ source.remote!
+ source.add_dependency_names("bundler")
+ source.specs
+ end
+ end
+
+ def find_latest_matching_spec(requirement)
+ local_result = find_latest_matching_spec_from_collection(local_specs, requirement)
+ return local_result if local_result && requirement.specific?
+
+ remote_result = find_latest_matching_spec_from_collection(remote_specs, requirement)
+ return remote_result if local_result.nil?
+
+ [local_result, remote_result].max
+ end
+
+ def find_latest_matching_spec_from_collection(specs, requirement)
+ specs.sort.reverse_each.find {|spec| requirement.satisfied_by?(spec.version) }
+ end
+
+ def running?(version)
+ version == current_version
+ end
+
+ def running_older_than?(version)
+ current_version < version
+ end
+
+ def released?(version)
+ !version.to_s.end_with?(".dev")
+ end
+
+ def updating?
+ "update".start_with?(ARGV.first || " ") && ARGV[1..-1].any? {|a| a.start_with?("--bundler") }
+ end
+
+ def installed?
+ Bundler.configure
+
+ Bundler.rubygems.find_bundler(lockfile_version.to_s)
+ end
+
+ def current_version
+ @current_version ||= Gem::Version.new(Bundler::VERSION)
+ end
+
+ def lockfile_version
+ return @lockfile_version if defined?(@lockfile_version)
+
+ parsed_version = Bundler::LockfileParser.bundled_with
+ @lockfile_version = parsed_version ? Gem::Version.new(parsed_version) : nil
+ end
+ end
+end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index de42cc16af..0af2236a45 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -43,9 +43,7 @@ module Bundler
setup_makes_kernel_gem_public
silence_deprecations
silence_root_warning
- suppress_install_using_messages
update_requires_all_flag
- use_gem_version_promoter_for_major_updates
].freeze
NUMBER_KEYS = %w[
@@ -57,6 +55,7 @@ module Bundler
].freeze
ARRAY_KEYS = %w[
+ only
with
without
].freeze
@@ -226,7 +225,9 @@ module Bundler
return Path.new(path, system_path)
end
- Path.new(nil, false)
+ path = "vendor/bundle" if self[:deployment]
+
+ Path.new(path, false)
end
Path = Struct.new(:explicit_path, :system_path) do
@@ -276,12 +277,6 @@ module Bundler
end
end
- def allow_sudo?
- key = key_for(:path)
- path_configured = @temporary.key?(key) || @local_config.key?(key)
- !path_configured
- end
-
def ignore_config?
ENV["BUNDLE_IGNORE_CONFIG"]
end
@@ -366,7 +361,7 @@ module Bundler
def to_array(value)
return [] unless value
- value.split(":").map(&:to_sym)
+ value.tr(" ", ":").split(":").map(&:to_sym)
end
def array_to_s(array)
@@ -419,7 +414,15 @@ module Bundler
elsif is_credential(key)
"[REDACTED]"
elsif is_userinfo(converted)
- converted.gsub(/:.*$/, ":[REDACTED]")
+ username, pass = converted.split(":", 2)
+
+ if pass == "x-oauth-basic"
+ username = "[REDACTED]"
+ else
+ pass = "[REDACTED]"
+ end
+
+ [username, pass].join(":")
else
converted
end
@@ -428,6 +431,10 @@ module Bundler
def global_config_file
if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
Pathname.new(ENV["BUNDLE_CONFIG"])
+ 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
@@ -474,7 +481,7 @@ module Bundler
/ix.freeze
def self.key_for(key)
- key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
+ key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http")
key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
"BUNDLE_#{key}"
end
@@ -488,7 +495,7 @@ module Bundler
uri = $2
suffix = $3
end
- uri = "#{uri}/" unless uri.end_with?("/")
+ uri = URINormalizer.normalize_suffix(uri)
require_relative "vendored_uri"
uri = Bundler::URI(uri)
unless uri.absolute?
diff --git a/lib/bundler/setup.rb b/lib/bundler/setup.rb
index 27911dc1ad..801fd5312a 100644
--- a/lib/bundler/setup.rb
+++ b/lib/bundler/setup.rb
@@ -9,10 +9,13 @@ 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"
+ suggested_cmd = "bundle install"
+ original_gemfile = Bundler.original_env["BUNDLE_GEMFILE"]
+ suggested_cmd += " --gemfile #{original_gemfile}" if original_gemfile
+ Bundler.ui.warn "Run `#{suggested_cmd}` 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 405ade95dd..d1d4e1d07a 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -13,13 +13,13 @@ module Bundler
def root
gemfile = find_gemfile
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
- Pathname.new(gemfile).tap{|x| x.untaint if RUBY_VERSION < "2.7" }.expand_path.parent
+ Pathname.new(gemfile).tap {|x| x.untaint if RUBY_VERSION < "2.7" }.expand_path.parent
end
def default_gemfile
gemfile = find_gemfile
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
- Pathname.new(gemfile).tap{|x| x.untaint if RUBY_VERSION < "2.7" }.expand_path
+ Pathname.new(gemfile).tap {|x| x.untaint if RUBY_VERSION < "2.7" }.expand_path
end
def default_lockfile
@@ -28,7 +28,7 @@ module Bundler
case gemfile.basename.to_s
when "gems.rb" then Pathname.new(gemfile.sub(/.rb$/, ".locked"))
else Pathname.new("#{gemfile}.lock")
- end.tap{|x| x.untaint if RUBY_VERSION < "2.7" }
+ end.tap {|x| x.untaint if RUBY_VERSION < "2.7" }
end
def default_bundle_dir
@@ -100,7 +100,7 @@ module Bundler
#
# @see {Bundler::PermissionError}
def filesystem_access(path, action = :write, &block)
- yield(path.dup.tap{|x| x.untaint if RUBY_VERSION < "2.7" })
+ yield(path.dup.tap {|x| x.untaint if RUBY_VERSION < "2.7" })
rescue Errno::EACCES
raise PermissionError.new(path, action)
rescue Errno::EAGAIN
@@ -141,7 +141,7 @@ module Bundler
end
return unless multiple_gemfiles
message = "Multiple gemfiles (gems.rb and Gemfile) detected. " \
- "Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.rb.locked."
+ "Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.locked."
Bundler.ui.warn message
end
@@ -160,10 +160,10 @@ module Bundler
" (was expecting #{old_deps.map(&:to_s)}, but the real spec has #{new_deps.map(&:to_s)})"
raise APIResponseMismatchError,
"Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.join(", ")})." \
- "\nEither installing with `--full-index` or running `bundle update #{spec.name}` should fix the problem."
+ "\nRunning `bundle update #{spec.name}` should fix the problem."
end
- def pretty_dependency(dep, print_source = false)
+ def pretty_dependency(dep)
msg = String.new(dep.name)
msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
@@ -172,7 +172,6 @@ module Bundler
msg << " " << platform_string if !platform_string.empty? && platform_string != Gem::Platform::RUBY
end
- msg << " from the `#{dep.source}` source" if print_source && dep.source
msg
end
@@ -236,10 +235,10 @@ module Bundler
def search_up(*names)
previous = nil
- current = File.expand_path(SharedHelpers.pwd).tap{|x| x.untaint if RUBY_VERSION < "2.7" }
+ current = File.expand_path(SharedHelpers.pwd).tap {|x| x.untaint if RUBY_VERSION < "2.7" }
until !File.directory?(current) || current == previous
- if ENV["BUNDLE_SPEC_RUN"]
+ if ENV["BUNDLER_SPEC_RUN"]
# avoid stepping above the tmp directory when testing
gemspec = if ENV["GEM_COMMAND"]
# for Ruby Core
@@ -274,10 +273,10 @@ module Bundler
def set_bundle_variables
# bundler exe & lib folders have same root folder, typical gem installation
- exe_file = File.expand_path("../../../exe/bundle", __FILE__)
+ exe_file = File.expand_path("../../exe/bundle", __dir__)
# for Ruby core repository testing
- exe_file = File.expand_path("../../../libexec/bundle", __FILE__) unless File.exist?(exe_file)
+ exe_file = File.expand_path("../../libexec/bundle", __dir__) unless File.exist?(exe_file)
# bundler is a default gem, exe path is separate
exe_file = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) unless File.exist?(exe_file)
@@ -285,6 +284,7 @@ module Bundler
Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", exe_file
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
+ Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__) unless RUBY_VERSION < "2.7"
end
def set_path
@@ -309,16 +309,15 @@ module Bundler
end
def bundler_ruby_lib
- resolve_path File.expand_path("../..", __FILE__)
+ File.expand_path("..", __dir__)
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!
@@ -326,7 +325,7 @@ module Bundler
def resolve_path(path)
expanded = File.expand_path(path)
- return expanded unless File.respond_to?(:realpath) && File.exist?(expanded)
+ return expanded unless File.exist?(expanded)
File.realpath(expanded)
end
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 5388a7681e..f7f5ea7865 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -15,13 +15,12 @@ module Bundler
specs.unmet_dependency_names
end
- def version_message(spec)
+ def version_message(spec, locked_spec = nil)
message = "#{spec.name} #{spec.version}"
message += " (#{spec.platform})" if spec.platform != Gem::Platform::RUBY && !spec.platform.nil?
- if Bundler.locked_gems
- locked_spec = Bundler.locked_gems.specs.find {|s| s.name == spec.name }
- locked_spec_version = locked_spec.version if locked_spec
+ if locked_spec
+ locked_spec_version = locked_spec.version
if locked_spec_version && spec.version != locked_spec_version
message += Bundler.ui.add_color(" (was #{locked_spec_version})", version_color(spec.version, locked_spec_version))
end
@@ -67,6 +66,10 @@ module Bundler
"#<#{self.class}:0x#{object_id} #{self}>"
end
+ def identifier
+ to_s
+ end
+
def path?
instance_of?(Bundler::Source::Path)
end
@@ -97,7 +100,7 @@ module Bundler
end
def print_using_message(message)
- if !message.include?("(was ") && Bundler.feature_flag.suppress_install_using_messages?
+ if !message.include?("(was ")
Bundler.ui.debug message
else
Bundler.ui.info message
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index fb13ca0578..adbce5fce4 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -19,7 +19,7 @@ module Bundler
# Stringify options that could be set as symbols
%w[ref branch tag revision].each {|k| options[k] = options[k].to_s if options[k] }
- @uri = options["uri"] || ""
+ @uri = URINormalizer.normalize_suffix(options["uri"] || "", :trailing_slash => false)
@safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"]
@ref = options["ref"] || options["branch"] || options["tag"]
@@ -42,10 +42,18 @@ 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
+ def to_gemfile
+ specifiers = %w[ref branch tag submodules glob].map do |opt|
+ "#{opt}: #{options[opt]}" if options[opt]
+ end
+
+ uri_with_specifiers(specifiers)
+ end
+
def hash
[self.class, uri, ref, branch, name, version, glob, submodules].hash
end
@@ -59,28 +67,40 @@ module Bundler
alias_method :==, :eql?
+ def include?(other)
+ other.is_a?(Git) && uri == other.uri &&
+ name == other.name &&
+ glob == other.glob &&
+ submodules == other.submodules
+ end
+
def to_s
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
- git_proxy.branch
- end
+ at = humanized_ref || current_branch
- rev = " (at #{at}@#{shortref_for_display(revision)})"
+ rev = "at #{at}@#{shortref_for_display(revision)}"
rescue GitError
""
end
- "#{@safe_uri}#{rev}"
+ uri_with_specifiers([rev, glob_for_display])
+ end
+
+ def identifier
+ uri_with_specifiers([humanized_ref, cached_revision, glob_for_display])
+ end
+
+ def uri_with_specifiers(specifiers)
+ specifiers.compact!
+
+ suffix =
+ if specifiers.any?
+ " (#{specifiers.join(", ")})"
+ else
+ ""
+ end
+
+ "#{@safe_uri}#{suffix}"
end
def name
@@ -94,13 +114,7 @@ module Bundler
@install_path ||= begin
git_scope = "#{base_name}-#{shortref_for_path(revision)}"
- path = Bundler.install_path.join(git_scope)
-
- if !path.exist? && Bundler.requires_sudo?
- Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope)
- else
- path
- end
+ Bundler.install_path.join(git_scope)
end
end
@@ -124,7 +138,7 @@ module Bundler
path = Pathname.new(path)
path = path.expand_path(Bundler.root) unless path.relative?
- unless options["branch"] || Bundler.settings[:disable_local_branch_check]
+ unless branch || Bundler.settings[:disable_local_branch_check]
raise GitError, "Cannot use local override for #{name} at #{path} because " \
":branch is not specified in Gemfile. Specify a branch or run " \
"`bundle config unset local.#{override_for(original_path)}` to remove the local override"
@@ -139,14 +153,14 @@ module Bundler
# Create a new git proxy without the cached revision
# so the Gemfile.lock always picks up the new revision.
- @git_proxy = GitProxy.new(path, uri, ref)
+ @git_proxy = GitProxy.new(path, uri, options)
- if git_proxy.branch != options["branch"] && !Bundler.settings[:disable_local_branch_check]
+ if current_branch != branch && !Bundler.settings[:disable_local_branch_check]
raise GitError, "Local override for #{name} at #{path} is using branch " \
- "#{git_proxy.branch} but Gemfile specifies #{options["branch"]}"
+ "#{current_branch} but Gemfile specifies #{branch}"
end
- changed = cached_revision && cached_revision != git_proxy.revision
+ changed = cached_revision && cached_revision != revision
if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision)
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
@@ -171,9 +185,10 @@ module Bundler
end
def install(spec, options = {})
+ return if Bundler.settings[:no_install]
force = options[:force]
- print_using_message "Using #{version_message(spec)} from #{self}"
+ print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}"
if (requires_checkout? && !@copied) || force
Bundler.ui.debug " * Checking out revision: #{ref}"
@@ -211,13 +226,11 @@ module Bundler
# across different projects, this cache will be shared.
# When using local git repos, this is set to the local repo.
def cache_path
- @cache_path ||= begin
- if Bundler.requires_sudo? || Bundler.feature_flag.global_gem_cache?
- Bundler.user_cache
- else
- Bundler.bundle_path.join("cache", "bundler")
- end.join("git", git_scope)
- end
+ @cache_path ||= if Bundler.feature_flag.global_gem_cache?
+ Bundler.user_cache
+ else
+ Bundler.bundle_path.join("cache", "bundler")
+ end.join("git", git_scope)
end
def app_cache_dirname
@@ -228,6 +241,10 @@ module Bundler
git_proxy.revision
end
+ def current_branch
+ git_proxy.current_branch
+ end
+
def allow_git_ops?
@allow_remote || @allow_cached
end
@@ -238,6 +255,20 @@ module Bundler
private
+ def humanized_ref
+ if local?
+ path
+ elsif user_ref = options["ref"]
+ if /\A[a-z0-9]{4,}\z/i.match?(ref)
+ shortref_for_display(user_ref)
+ else
+ user_ref
+ end
+ elsif ref
+ ref
+ end
+ end
+
def serialize_gemspecs_in(destination)
destination = destination.expand_path(Bundler.root) if destination.relative?
Dir["#{destination}/#{@glob}"].each do |spec_path|
@@ -282,8 +313,16 @@ 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+@)?}
+ if %r{^\w+://(\w+@)?}.match?(uri)
# Downcase the domain component of the URI
# and strip off a trailing slash, if one is present
input = Bundler::URI.parse(uri).normalize.to_s.sub(%r{/$}, "")
@@ -291,7 +330,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
@@ -303,7 +344,7 @@ module Bundler
end
def git_proxy
- @git_proxy ||= GitProxy.new(cache_path, uri, ref, cached_revision, self)
+ @git_proxy ||= GitProxy.new(cache_path, uri, options, cached_revision, self)
end
def fetch
@@ -318,7 +359,7 @@ module Bundler
def load_gemspec(file)
stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent)
- stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s.tap{|x| x.untaint if RUBY_VERSION < "2.7" }
+ stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s.tap {|x| x.untaint if RUBY_VERSION < "2.7" }
StubSpecification.from_stub(stub)
end
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index 7555561edd..fdb738e52e 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -28,10 +28,10 @@ module Bundler
def initialize(command, path, extra_info = nil)
@command = command
- msg = String.new
- msg << "Git error: command `#{command}` in directory #{path} has failed."
+ msg = String.new("Git error: command `#{command}`")
+ msg << " in directory #{path}" if path
+ msg << " has failed."
msg << "\n#{extra_info}" if extra_info
- msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
super msg
end
end
@@ -47,25 +47,28 @@ module Bundler
# All actions required by the Git source is encapsulated in this
# object.
class GitProxy
- attr_accessor :path, :uri, :ref
+ attr_accessor :path, :uri, :branch, :tag, :ref, :explicit_ref
attr_writer :revision
- def initialize(path, uri, ref, revision = nil, git = nil)
+ def initialize(path, uri, options = {}, revision = nil, git = nil)
@path = path
@uri = uri
- @ref = ref
+ @branch = options["branch"]
+ @tag = options["tag"]
+ @ref = options["ref"]
+ @explicit_ref = branch || tag || ref
@revision = revision
@git = git
- raise GitNotInstalledError.new if allow? && !Bundler.git_present?
+ @commit_ref = nil
end
def revision
- @revision ||= find_local_revision
+ @revision ||= allowed_with_path { find_local_revision }
end
- def branch
- @branch ||= allowed_with_path do
- git("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
+ def current_branch
+ @current_branch ||= with_path do
+ git_local("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
end
end
@@ -77,36 +80,26 @@ module Bundler
end
def version
- git("--version").match(/(git version\s*)?((\.?\d+)+).*/)[2]
+ @version ||= full_version.match(/((\.?\d+)+).*/)[1]
end
def full_version
- git("--version").sub("git version", "").strip
+ @full_version ||= git_local("--version").sub(/git version\s*/, "").strip
end
def checkout
- return if path.exist? && has_revision_cached?
- extra_ref = "#{ref}:#{ref}" if ref && ref.start_with?("refs/")
-
- Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
+ return if has_revision_cached?
- configured_uri = configured_uri_for(uri).to_s
+ Bundler.ui.info "Fetching #{credential_filtered_uri}"
- unless path.exist?
- SharedHelpers.filesystem_access(path.dirname) do |p|
- FileUtils.mkdir_p(p)
- end
- git_retry "clone", configured_uri, path.to_s, "--bare", "--no-hardlinks", "--quiet"
- return unless extra_ref
- end
+ extra_fetch_needed = clone_needs_extra_fetch?
+ unshallow_needed = clone_needs_unshallow?
+ return unless extra_fetch_needed || unshallow_needed
- with_path do
- git_retry(*["fetch", "--force", "--quiet", "--tags", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
- end
+ git_remote_fetch(unshallow_needed ? ["--unshallow"] : depth_args)
end
def copy_to(destination, submodules = false)
- # method 1
unless File.exist?(destination.join(".git"))
begin
SharedHelpers.filesystem_access(destination.dirname) do |p|
@@ -115,7 +108,7 @@ module Bundler
SharedHelpers.filesystem_access(destination) do |p|
FileUtils.rm_rf(p)
end
- git_retry "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
+ git "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{.*?((?:[a-zA-Z]:)?/.*)}, 1]
@@ -124,14 +117,10 @@ module Bundler
"this file and try again."
end
end
- # method 2
- git_retry "fetch", "--force", "--quiet", "--tags", path.to_s, :dir => destination
- begin
- git "reset", "--hard", @revision, :dir => destination
- rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
- end
+ git "fetch", "--force", "--quiet", *extra_fetch_args, :dir => destination if @commit_ref
+
+ git "reset", "--hard", @revision, :dir => destination
if submodules
git_retry "submodule", "update", "--init", "--recursive", :dir => destination
@@ -143,14 +132,117 @@ module Bundler
private
- def git_null(*command, dir: nil)
- check_allowed(command)
+ def git_remote_fetch(args)
+ command = ["fetch", "--force", "--quiet", "--no-tags", *args, "--", configured_uri, refspec].compact
+ command_with_no_credentials = check_allowed(command)
+
+ Bundler::Retry.new("`#{command_with_no_credentials}` at #{path}", [MissingGitRevisionError]).attempts do
+ out, err, status = capture(command, path)
+ return out if status.success?
+
+ if err.include?("couldn't find remote ref") || err.include?("not our ref")
+ raise MissingGitRevisionError.new(command_with_no_credentials, path, commit || explicit_ref, credential_filtered_uri)
+ else
+ raise GitCommandError.new(command_with_no_credentials, path, err)
+ end
+ end
+ end
- out, status = SharedHelpers.with_clean_git_env do
- capture_and_ignore_stderr(*capture3_args_for(command, dir))
+ def clone_needs_extra_fetch?
+ return true if path.exist?
+
+ SharedHelpers.filesystem_access(path.dirname) do |p|
+ FileUtils.mkdir_p(p)
end
- [URICredentialsFilter.credential_filtered_string(out, uri), status]
+ command = ["clone", "--bare", "--no-hardlinks", "--quiet", *extra_clone_args, "--", configured_uri, path.to_s]
+ command_with_no_credentials = check_allowed(command)
+
+ Bundler::Retry.new("`#{command_with_no_credentials}`", [MissingGitRevisionError]).attempts do
+ _, err, status = capture(command, nil)
+ return extra_ref if status.success?
+
+ if err.include?("Could not find remote branch") || # git up to 2.49
+ err.include?("Remote branch #{branch_option} not found") # git 2.49 or higher
+ raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
+ else
+ raise GitCommandError.new(command_with_no_credentials, path, err)
+ end
+ end
+ end
+
+ def clone_needs_unshallow?
+ return false unless path.join("shallow").exist?
+ return true if full_clone?
+
+ @revision && @revision != head_revision
+ end
+
+ def extra_ref
+ return false if not_pinned?
+ return true unless full_clone?
+
+ ref.start_with?("refs/")
+ end
+
+ def depth
+ return @depth if defined?(@depth)
+
+ @depth = if !supports_fetching_unreachable_refs?
+ nil
+ elsif not_pinned? || pinned_to_full_sha?
+ 1
+ elsif ref.include?("~")
+ parsed_depth = ref.split("~").last
+ parsed_depth.to_i + 1
+ end
+ end
+
+ def refspec
+ if commit
+ @commit_ref = "refs/#{commit}-sha"
+ return "#{commit}:#{@commit_ref}"
+ end
+
+ reference = fully_qualified_ref
+
+ reference ||= if ref.include?("~")
+ ref.split("~").first
+ elsif ref.start_with?("refs/")
+ ref
+ else
+ "refs/*"
+ end
+
+ "#{reference}:#{reference}"
+ end
+
+ def commit
+ @commit ||= pinned_to_full_sha? ? ref : @revision
+ end
+
+ def fully_qualified_ref
+ if branch
+ "refs/heads/#{branch}"
+ elsif tag
+ "refs/tags/#{tag}"
+ elsif ref.nil?
+ "refs/heads/#{current_branch}"
+ end
+ end
+
+ def not_pinned?
+ branch_option || ref.nil?
+ end
+
+ def pinned_to_full_sha?
+ ref =~ /\A\h{40}\z/
+ end
+
+ def git_null(*command, dir: nil)
+ check_allowed(command)
+
+ capture(command, dir, :ignore_err => true)
end
def git_retry(*command, dir: nil)
@@ -162,53 +254,70 @@ module Bundler
end
def git(*command, dir: nil)
- command_with_no_credentials = check_allowed(command)
-
- out, status = SharedHelpers.with_clean_git_env do
- capture_and_filter_stderr(*capture3_args_for(command, dir))
+ run_command(*command, :dir => dir) do |unredacted_command|
+ check_allowed(unredacted_command)
end
+ end
- 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
+ def git_local(*command, dir: nil)
+ run_command(*command, :dir => dir) do |unredacted_command|
+ redact_and_check_presence(unredacted_command)
+ end
end
def has_revision_cached?
- return unless @revision
- with_path { git("cat-file", "-e", @revision, :dir => path) }
+ return unless @revision && path.exist?
+ git("cat-file", "-e", @revision, :dir => path)
true
rescue GitError
false
end
- def remove_cache
- FileUtils.rm_rf(path)
+ def find_local_revision
+ return head_revision if explicit_ref.nil?
+
+ find_revision_for(explicit_ref)
end
- def find_local_revision
- allowed_with_path do
- git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
- end
+ def head_revision
+ verify("HEAD")
+ end
+
+ def find_revision_for(reference)
+ verify(reference)
rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
+ raise MissingGitRevisionError.new(e.command, path, reference, credential_filtered_uri)
+ end
+
+ def verify(reference)
+ git("rev-parse", "--verify", reference, :dir => path).strip
end
- # Adds credentials to the URI as Fetcher#configured_uri_for does
- def configured_uri_for(uri)
- if /https?:/ =~ uri
+ # Adds credentials to the URI
+ def configured_uri
+ if /https?:/.match?(uri)
remote = Bundler::URI(uri)
config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
remote.userinfo ||= config_auth
remote.to_s
+ elsif File.exist?(uri)
+ "file://#{uri}"
else
- uri
+ uri.to_s
end
end
+ # Removes credentials from the URI
+ def credential_filtered_uri
+ URICredentialsFilter.credential_filtered_uri(uri)
+ end
+
def allow?
- @git ? @git.allow_git_ops? : true
+ allowed = @git ? @git.allow_git_ops? : true
+
+ raise GitNotInstalledError.new if allowed && !Bundler.git_present?
+
+ allowed
end
def with_path(&blk)
@@ -222,23 +331,41 @@ module Bundler
end
def check_allowed(command)
- require "shellwords"
- command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
+ command_with_no_credentials = redact_and_check_presence(command)
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) unless captured_err.empty?
- [return_value, status]
+ def redact_and_check_presence(command)
+ raise GitNotInstalledError.new unless Bundler.git_present?
+
+ require "shellwords"
+ URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
end
- def capture_and_ignore_stderr(*cmd)
- require "open3"
- return_value, _, status = Open3.capture3(*cmd)
- [return_value, status]
+ def run_command(*command, dir: nil)
+ command_with_no_credentials = yield(command)
+
+ out, err, status = capture(command, dir)
+
+ raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, err) unless status.success?
+
+ Bundler.ui.warn err unless err.empty?
+
+ out
+ end
+
+ def capture(cmd, dir, ignore_err: false)
+ SharedHelpers.with_clean_git_env do
+ require "open3"
+ out, err, status = Open3.capture3(*capture3_args_for(cmd, dir))
+
+ filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
+ return [filtered_out, status] if ignore_err
+
+ filtered_err = URICredentialsFilter.credential_filtered_string(err, uri)
+ [filtered_out, filtered_err, status]
+ end
end
def capture3_args_for(cmd, dir)
@@ -251,9 +378,53 @@ module Bundler
end
end
+ def extra_clone_args
+ args = depth_args
+ return [] if args.empty?
+
+ args += ["--single-branch"]
+ args.unshift("--no-tags") if supports_cloning_with_no_tags?
+
+ # If there's a locked revision, no need to clone any specific branch
+ # or tag, since we will end up checking out that locked revision
+ # anyways.
+ return args if @revision
+
+ args += ["--branch", branch_option] if branch_option
+ args
+ end
+
+ def depth_args
+ return [] if full_clone?
+
+ ["--depth", depth.to_s]
+ end
+
+ def extra_fetch_args
+ extra_args = [path.to_s, *depth_args]
+ extra_args.push(@commit_ref)
+ extra_args
+ end
+
+ def branch_option
+ branch || tag
+ end
+
+ def full_clone?
+ depth.nil?
+ end
+
def supports_minus_c?
@supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
end
+
+ def supports_fetching_unreachable_refs?
+ @supports_fetching_unreachable_refs ||= Gem::Version.new(version) >= Gem::Version.new("2.5.0")
+ end
+
+ def supports_cloning_with_no_tags?
+ @supports_cloning_with_no_tags ||= Gem::Version.new(version) >= Gem::Version.new("2.14.0-rc0")
+ end
end
end
end
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 50b65ce0ea..593da6d1a7 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -5,7 +5,7 @@ module Bundler
class Metadata < Source
def specs
@specs ||= Index.build do |idx|
- idx << Gem::Specification.new("Ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
+ idx << Gem::Specification.new("Ruby\0", Gem.ruby_version)
idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
s.required_rubygems_version = Gem::Requirement.default
end
@@ -15,17 +15,16 @@ module Bundler
s.version = VERSION
s.license = "MIT"
s.platform = Gem::Platform::RUBY
- s.source = self
s.authors = ["bundler team"]
s.bindir = "exe"
s.homepage = "https://bundler.io"
s.summary = "The best way to manage your application's dependencies"
s.executables = %w[bundle]
# can't point to the actual gemspec or else the require paths will be wrong
- s.loaded_from = File.expand_path("..", __FILE__)
+ s.loaded_from = __dir__
end
- if local_spec = Bundler.rubygems.find_name("bundler").find {|s| s.version.to_s == VERSION }
+ if local_spec = Bundler.rubygems.find_bundler(VERSION)
idx << local_spec
end
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb
index 01f89b204d..bdfcf8274a 100644
--- a/lib/bundler/source/path.rb
+++ b/lib/bundler/source/path.rb
@@ -11,7 +11,7 @@ module Bundler
protected :original_path
- DEFAULT_GLOB = "{,*,*/*}.gemspec".freeze
+ DEFAULT_GLOB = "{,*,*/*}.gemspec"
def initialize(options)
@options = options.dup
@@ -82,7 +82,7 @@ module Bundler
end
def install(spec, options = {})
- using_message = "Using #{version_message(spec)} from #{self}"
+ using_message = "Using #{version_message(spec, options[:previous_spec])} from #{self}"
using_message += " and installing its executables" unless spec.executables.empty?
print_using_message using_message
generate_bin(spec, :disable_extensions => true)
@@ -224,13 +224,13 @@ module Bundler
# Some gem authors put absolute paths in their gemspec
# and we have to save them from themselves
- spec.files = spec.files.map do |p|
- next p unless p =~ /\A#{Pathname::SEPARATOR_PAT}/
- next if File.directory?(p)
+ spec.files = spec.files.map do |path|
+ next path unless /\A#{Pathname::SEPARATOR_PAT}/.match?(path)
+ next if File.directory?(path)
begin
- Pathname.new(p).relative_path_from(gem_dir).to_s
+ Pathname.new(path).relative_path_from(gem_dir).to_s
rescue ArgumentError
- p
+ path
end
end.compact
diff --git a/lib/bundler/source/path/installer.rb b/lib/bundler/source/path/installer.rb
index a70973bde7..0af28fe770 100644
--- a/lib/bundler/source/path/installer.rb
+++ b/lib/bundler/source/path/installer.rb
@@ -18,13 +18,7 @@ module Bundler
@build_args = options[:build_args] || Bundler.rubygems.build_args
@gem_bin_dir = "#{Bundler.rubygems.gem_dir}/bin"
@disable_extensions = options[:disable_extensions]
-
- if Bundler.requires_sudo?
- @tmp_dir = Bundler.tmp(spec.full_name).to_s
- @bin_dir = "#{@tmp_dir}/bin"
- else
- @bin_dir = @gem_bin_dir
- end
+ @bin_dir = @gem_bin_dir
end
def post_install
@@ -38,25 +32,10 @@ module Bundler
generate_bin unless spec.executables.empty?
run_hooks(:post_install)
- ensure
- Bundler.rm_rf(@tmp_dir) if Bundler.requires_sudo?
end
private
- def generate_bin
- super
-
- if Bundler.requires_sudo?
- SharedHelpers.filesystem_access(@gem_bin_dir) do |p|
- Bundler.mkdir_p(p)
- end
- spec.executables.each do |exe|
- Bundler.sudo "cp -R #{@bin_dir}/#{exe} #{@gem_bin_dir}"
- end
- end
- end
-
def run_hooks(type)
hooks_meth = "#{type}_hooks"
return unless Gem.respond_to?(hooks_meth)
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 858a69a48b..af57acbbc2 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -7,12 +7,10 @@ module Bundler
class Rubygems < Source
autoload :Remote, File.expand_path("rubygems/remote", __dir__)
- # Use the API when installing less than X gems
- API_REQUEST_LIMIT = 500
# Ask for X gems per API request
API_REQUEST_SIZE = 50
- attr_reader :remotes, :caches
+ attr_reader :remotes
def initialize(options = {})
@options = options
@@ -21,14 +19,18 @@ module Bundler
@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) }
end
+ def caches
+ @caches ||= [cache_path, *Bundler.rubygems.gem_cache]
+ end
+
def local_only!
@specs = nil
@allow_local = true
+ @allow_cached = false
@allow_remote = false
end
@@ -50,6 +52,7 @@ module Bundler
return if @allow_cached
@specs = nil
+ @allow_local = true
@allow_cached = true
end
@@ -99,12 +102,28 @@ 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
+
+ def identifier
+ if remotes.empty?
+ "locally installed gems"
+ else
+ "rubygems repository #{remote_names}"
end
end
- alias_method :name, :to_s
+ alias_method :name, :identifier
+ alias_method :to_gemfile, :identifier
def specs
@specs ||= begin
@@ -118,114 +137,79 @@ module Bundler
end
end
- def install(spec, opts = {})
- force = opts[:force]
- ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
+ def install(spec, options = {})
+ force = options[:force]
+ ensure_builtin_gems_cached = options[:ensure_builtin_gems_cached]
- if ensure_builtin_gems_cached && builtin_gem?(spec)
- if !cached_path(spec)
- cached_built_in_gem(spec) unless spec.remote
- force = true
- else
- spec.loaded_from = loaded_from(spec)
- end
+ if ensure_builtin_gems_cached && spec.default_gem? && !cached_path(spec)
+ cached_built_in_gem(spec) unless spec.remote
+ force = true
end
- if (installed?(spec) || Plugin.installed?(spec.name)) && !force
- print_using_message "Using #{version_message(spec)}"
+ if installed?(spec) && !force
+ print_using_message "Using #{version_message(spec, options[:previous_spec])}"
return nil # no post-install message
end
- # Download the gem to get the spec, because some specs that are returned
- # by rubygems.org are broken and wrong.
if spec.remote
# Check for this spec from other sources
- uris = [spec.remote.anonymized_uri]
- uris += remotes_for_spec(spec).map(&:anonymized_uri)
- uris.uniq!
+ uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq
Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
+ end
+
+ path = fetch_gem_if_possible(spec, options[:previous_spec])
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
+
+ return if Bundler.settings[:no_install]
- path = fetch_gem(spec)
- begin
- s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
- spec.__swap__(s)
- rescue StandardError
+ install_path = rubygems_dir
+ bin_path = Bundler.system_bindir
+
+ require_relative "../rubygems_gem_installer"
+
+ installer = Bundler::RubyGemsGemInstaller.at(
+ path,
+ :security_policy => Bundler.rubygems.security_policies[Bundler.settings["trust-policy"]],
+ :install_dir => install_path.to_s,
+ :bin_dir => bin_path.to_s,
+ :ignore_dependencies => true,
+ :wrappers => true,
+ :env_shebang => true,
+ :build_args => options[:build_args],
+ :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
+ :bundler_extension_cache_path => extension_cache_path(spec)
+ )
+
+ if spec.remote
+ s = begin
+ installer.spec
+ rescue Gem::Package::FormatError
Bundler.rm_rf(path)
raise
+ rescue Gem::Security::Exception => e
+ raise SecurityError,
+ "The gem #{File.basename(path, ".gem")} can't be installed because " \
+ "the security policy didn't allow it, with the message: #{e.message}"
end
- end
- unless Bundler.settings[:no_install]
- message = "Installing #{version_message(spec)}"
- message += " with native extensions" if spec.extensions.any?
- Bundler.ui.confirm message
+ spec.__swap__(s)
+ end
- path = cached_gem(spec)
- if requires_sudo?
- install_path = Bundler.tmp(spec.full_name)
- bin_path = install_path.join("bin")
- else
- install_path = rubygems_dir
- bin_path = Bundler.system_bindir
- end
+ message = "Installing #{version_message(spec, options[:previous_spec])}"
+ message += " with native extensions" if spec.extensions.any?
+ Bundler.ui.confirm message
- Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
-
- 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
- if requires_sudo?
- Bundler.rubygems.repository_subdirectories.each do |name|
- src = File.join(install_path, name, "*")
- dst = File.join(rubygems_dir, name)
- if name == "extensions" && Dir.glob(src).any?
- src = File.join(src, "*/*")
- ext_src = Dir.glob(src).first
- ext_src.gsub!(src[0..-6], "")
- dst = File.dirname(File.join(dst, ext_src))
- end
- SharedHelpers.filesystem_access(dst) do |p|
- Bundler.mkdir_p(p)
- end
- Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
- end
+ installed_spec = installer.install
- spec.executables.each do |exe|
- SharedHelpers.filesystem_access(Bundler.system_bindir) do |p|
- Bundler.mkdir_p(p)
- end
- Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
- end
- end
- installed_spec.loaded_from = loaded_from(spec)
- end
- spec.loaded_from = loaded_from(spec)
+ spec.full_gem_path = installed_spec.full_gem_path
+ spec.loaded_from = installed_spec.loaded_from
spec.post_install_message
- ensure
- Bundler.rm_rf(install_path) if requires_sudo?
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 = Bundler.settings[:cache_all_platforms] ? fetch_gem_if_possible(spec) : 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))
@@ -252,10 +236,6 @@ 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 spec_names
if @allow_remote && dependency_api_available?
remote_specs.spec_names
@@ -314,13 +294,21 @@ module Bundler
end
def dependency_api_available?
- api_fetchers.any?
+ @allow_remote && 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)
@@ -330,26 +318,28 @@ module Bundler
end
end
- def loaded_from(spec)
- "#{rubygems_dir}/specifications/#{spec.full_name}.gemspec"
- 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)
- possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" }
+ global_cache_path = download_cache_path(spec)
+ caches << global_cache_path if global_cache_path
+
+ possibilities = caches.map {|p| package_path(p, spec) }
possibilities.find {|p| File.exist?(p) }
end
+ def package_path(cache_path, spec)
+ "#{cache_path}/#{spec.file_name}"
+ end
+
def normalize_uri(uri)
- uri = uri.to_s
- uri = "#{uri}/" unless uri =~ %r{/$}
+ uri = URINormalizer.normalize_suffix(uri.to_s)
require_relative "../vendored_uri"
uri = Bundler::URI(uri)
raise ArgumentError, "The source must be an absolute URI. For example:\n" \
@@ -392,7 +382,6 @@ module Bundler
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
idx << s
@@ -413,12 +402,11 @@ module Bundler
# gather lists from non-api sites
fetch_names(index_fetchers, nil, idx, false)
- # because ensuring we have all the gems we need involves downloading
- # the gemspecs of those gems, if the non-api sites contain more than
- # about 500 gems, we treat all sites as non-api for speed.
- allow_api = idx.size < API_REQUEST_LIMIT && dependency_names.size < API_REQUEST_LIMIT
- Bundler.ui.debug "Need to query more than #{API_REQUEST_LIMIT} gems." \
- " Downloading full index instead..." unless allow_api
+ # legacy multi-remote sources need special logic to figure out
+ # dependency names and that logic can be very costly if one remote
+ # uses the dependency API but others don't. So use full indexes
+ # consistently in that particular case.
+ allow_api = !multiple_remotes?
fetch_names(api_fetchers, allow_api && dependency_names, idx, false)
end
@@ -437,49 +425,39 @@ module Bundler
end
end
- def fetch_gem(spec)
- return false unless spec.remote
+ def fetch_gem_if_possible(spec, previous_spec = nil)
+ if spec.remote
+ fetch_gem(spec, previous_spec)
+ else
+ cached_gem(spec)
+ end
+ end
+ def fetch_gem(spec, previous_spec = nil)
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 = package_path(cache_path, spec)
+ return gem_path if File.exist?(gem_path)
- SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
+ SharedHelpers.filesystem_access(cache_path) do |p|
FileUtils.mkdir_p(p)
end
- download_gem(spec, download_path)
-
- if requires_sudo?
- SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
- Bundler.mkdir_p(p)
- end
- Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}"
- end
+ download_gem(spec, cache_path, previous_spec)
gem_path
- ensure
- 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?
- Bundler.requires_sudo?
+ def rubygems_dir
+ Bundler.bundle_path
end
- def rubygems_dir
- Bundler.rubygems.gem_dir
+ def default_cache_path_for(dir)
+ "#{dir}/cache"
end
def cache_path
@@ -494,52 +472,16 @@ 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)
-
- # older rubygems return varying file:// variants depending on version
- rubygems_local_path = rubygems_local_path.gsub(/\Afile:/, "") unless Bundler.rubygems.provides?(">= 3.2.0.rc.2")
- rubygems_local_path = rubygems_local_path.gsub(%r{\A//}, "") if Bundler.rubygems.provides?("< 3.1.0")
-
- if rubygems_local_path != local_path
- SharedHelpers.filesystem_access(local_path) do
- FileUtils.mv(rubygems_local_path, local_path)
- end
- 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.
+ # @param [Specification] previous_spec
+ # the spec previously locked
#
- 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, previous_spec = nil)
+ uri = spec.remote.uri
+ Bundler.ui.confirm("Fetching #{version_message(spec, previous_spec)}")
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path)
end
# Returns the global cache path of the calling Rubygems::Source object.
@@ -558,7 +500,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_aggregate.rb b/lib/bundler/source/rubygems_aggregate.rb
index 685bf7e90a..99ef81ad54 100644
--- a/lib/bundler/source/rubygems_aggregate.rb
+++ b/lib/bundler/source/rubygems_aggregate.rb
@@ -16,6 +16,10 @@ module Bundler
@index
end
+ def identifier
+ to_s
+ end
+
def to_s
"any of the sources"
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index c7dfa3d797..4419695b7f 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -98,7 +98,7 @@ module Bundler
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
@@ -106,14 +106,14 @@ module Bundler
end
def lock_other_sources
- (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
+ (path_sources + git_sources + plugin_sources).sort_by(&:identifier)
end
def lock_rubygems_sources
if merged_gem_lockfile_sections?
[combine_rubygems_sources]
else
- rubygems_sources.sort_by(&:to_s)
+ rubygems_sources.sort_by(&:identifier)
end
end
@@ -121,7 +121,8 @@ module Bundler
def replace_sources!(replacement_sources)
return false if replacement_sources.empty?
- @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
+ @rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
+ @global_rubygems_source = global_replacement_source(replacement_sources)
different_sources?(lock_sources, replacement_sources)
end
@@ -156,15 +157,29 @@ module Bundler
end
def map_sources(replacement_sources)
- [path_sources, git_sources, plugin_sources].map do |sources|
+ rubygems, git, plugin = [@rubygems_sources, @git_sources, @plugin_sources].map do |sources|
sources.map do |source|
replacement_sources.find {|s| s == source } || source
end
end
+
+ path = @path_sources.map do |source|
+ replacement_sources.find {|s| s == (source.is_a?(Source::Gemspec) ? source.as_path_source : source) } || source
+ end
+
+ [rubygems, path, git, plugin]
+ end
+
+ 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)
- !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
+ !equivalent_sources?(lock_sources, replacement_sources)
end
def rubygems_aggregate_class
@@ -193,7 +208,7 @@ module Bundler
def warn_on_git_protocol(source)
return if Bundler.settings["git.allow_insecure"]
- if source.uri =~ /^git\:/
+ if /^git\:/.match?(source.uri)
Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \
"which transmits data without encryption. Disable this warning with " \
"`bundle config set --local git.allow_insecure true`, or switch to the `https` " \
@@ -201,34 +216,12 @@ module Bundler
end
end
- def equal_sources?(lock_sources, replacement_sources)
- lock_sources.sort_by(&:to_s) == replacement_sources.sort_by(&:to_s)
- end
-
- def equal_source?(source, other_source)
- return source.include?(other_source) if source.is_a?(Source::Rubygems) && other_source.is_a?(Source::Rubygems) && !merged_gem_lockfile_sections?
-
- 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
index a554f26f76..ca73e01f9d 100644
--- a/lib/bundler/source_map.rb
+++ b/lib/bundler/source_map.rb
@@ -2,11 +2,12 @@
module Bundler
class SourceMap
- attr_reader :sources, :dependencies
+ attr_reader :sources, :dependencies, :locked_specs
- def initialize(sources, dependencies)
+ def initialize(sources, dependencies, locked_specs)
@sources = sources
@dependencies = dependencies
+ @locked_specs = locked_specs
end
def pinned_spec_names(skip = nil)
@@ -54,5 +55,17 @@ module Bundler
requirements
end
end
+
+ def locked_requirements
+ @locked_requirements ||= begin
+ requirements = {}
+ locked_specs.each do |locked_spec|
+ source = locked_spec.source
+ source.add_dependency_names(locked_spec.name)
+ requirements[locked_spec.name] = source
+ end
+ requirements
+ end
+ end
end
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 1a8906c47e..21630e3a3e 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -1,51 +1,55 @@
# frozen_string_literal: true
-require "tsort"
+require_relative "vendored_tsort"
module Bundler
class SpecSet
include Enumerable
include TSort
- def initialize(specs)
+ attr_reader :incomplete_specs
+
+ def initialize(specs, incomplete_specs = [])
@specs = specs
+ @incomplete_specs = incomplete_specs
end
- def for(dependencies, check = false, match_current_platform = false, raise_on_missing = true)
- handled = []
- deps = dependencies.dup
+ def for(dependencies, check = false, platforms = [nil])
+ handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
+ deps = dependencies.product(platforms)
specs = []
loop do
break unless dep = deps.shift
- next if handled.any?{|d| d.name == dep.name && (match_current_platform || d.__platform == dep.__platform) } || dep.name == "bundler"
- handled << dep
+ name = dep[0].name
+ platform = dep[1]
+ incomplete = false
+
+ key = [name, platform]
+ next if handled.key?(key)
+
+ handled[key] = true
- specs_for_dep = spec_for_dependency(dep, match_current_platform)
+ specs_for_dep = specs_for_dependency(*dep)
if specs_for_dep.any?
- specs += specs_for_dep
+ specs.concat(specs_for_dep)
specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
- d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform
- deps << d
+ incomplete = true if d.name != "bundler" && lookup[d.name].empty?
+ deps << [d, dep[1]]
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
+ else
+ incomplete = true
end
- end
- if spec = lookup["bundler"].first
- specs << spec
+ if incomplete && check
+ @incomplete_specs += lookup[name].any? ? lookup[name] : [LazySpecification.new(name, nil, nil)]
+ end
end
- check ? true : specs
+ specs.uniq
end
def [](key)
@@ -59,6 +63,12 @@ module Bundler
@sorted = nil
end
+ def delete(specs)
+ specs.each {|spec| @specs.delete(spec) }
+ @lookup = nil
+ @sorted = nil
+ end
+
def sort!
self
end
@@ -71,52 +81,39 @@ module Bundler
lookup.dup
end
- def materialize(deps, missing_specs = nil)
- materialized = self.for(deps, false, true, !missing_specs)
+ def materialize(deps)
+ materialized = self.for(deps, true)
- materialized.group_by(&:source).each do |source, specs|
- next unless specs.any?{|s| s.is_a?(LazySpecification) }
-
- source.local!
- names = -> { specs.map(&:name).uniq }
- source.double_check_for(names)
- end
-
- materialized.map! do |s|
- next s unless s.is_a?(LazySpecification)
- 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
- end
- SpecSet.new(missing_specs ? materialized.compact : materialized)
+ SpecSet.new(materialized, incomplete_specs)
end
# Materialize for all the specs in the spec set, regardless of what platform they're for
# This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
# @return [Array<Gem::Specification>]
def materialized_for_all_platforms
- @specs.group_by(&:source).each do |source, specs|
- next unless specs.any?{|s| s.is_a?(LazySpecification) }
-
- source.local!
- source.remote!
- names = -> { specs.map(&:name).uniq }
- source.double_check_for(names)
- end
-
@specs.map do |s|
next s unless s.is_a?(LazySpecification)
- spec = s.__materialize__
+ s.source.remote!
+ spec = s.materialize_for_installation
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
spec
end
end
+ def incomplete_ruby_specs?(deps)
+ return false if @specs.empty?
+
+ @incomplete_specs = []
+
+ self.for(deps, true, [Gem::Platform::RUBY])
+
+ @incomplete_specs.any?
+ end
+
+ def missing_specs
+ @specs.select {|s| s.is_a?(LazySpecification) }
+ end
+
def merge(set)
arr = sorted.dup
set.each do |set_spec|
@@ -127,10 +124,20 @@ module Bundler
SpecSet.new(arr)
end
+ def -(other)
+ SpecSet.new(to_a - other.to_a)
+ end
+
def find_by_name_and_platform(name, platform)
@specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
end
+ def delete_by_name(name)
+ @specs.reject! {|spec| spec.name == name }
+ @lookup = nil
+ @sorted = nil
+ end
+
def what_required(spec)
unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
return [spec]
@@ -168,7 +175,7 @@ module Bundler
cgems = extract_circular_gems(error)
raise CyclicDependencyError, "Your bundle requires gems that depend" \
" on each other, creating an infinite loop. Please remove either" \
- " gem '#{cgems[1]}' or gem '#{cgems[0]}' and try again."
+ " gem '#{cgems[0]}' or gem '#{cgems[1]}' and try again."
end
end
@@ -179,7 +186,7 @@ module Bundler
def lookup
@lookup ||= begin
lookup = Hash.new {|h, k| h[k] = [] }
- Index.sort_specs(@specs).reverse_each do |s|
+ @specs.each do |s|
lookup[s.name] << s
end
lookup
@@ -191,13 +198,12 @@ module Bundler
@specs.sort_by(&:name).each {|s| yield s }
end
- def spec_for_dependency(dep, match_current_platform)
- specs_for_platforms = lookup[dep.name]
- if match_current_platform
- 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
+ def specs_for_dependency(dep, platform)
+ specs_for_name = lookup[dep.name]
+ target_platform = dep.force_ruby_platform ? Gem::Platform::RUBY : (platform || Bundler.local_platform)
+ matching_specs = GemHelpers.select_best_platform_match(specs_for_name, target_platform)
+ matching_specs.map!(&:materialize_for_installation).compact! if platform.nil?
+ matching_specs
end
def tsort_each_child(s)
diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb
index fa071901e5..88a4257fa4 100644
--- a/lib/bundler/stub_specification.rb
+++ b/lib/bundler/stub_specification.rb
@@ -64,9 +64,11 @@ module Bundler
end
def full_gem_path
- # deleted gems can have their stubs return nil, so in that case grab the
- # expired path from the full spec
- stub.full_gem_path || method_missing(:full_gem_path)
+ stub.full_gem_path
+ end
+
+ def full_gem_path=(path)
+ stub.full_gem_path = path
end
def full_require_paths
diff --git a/lib/bundler/templates/Executable b/lib/bundler/templates/Executable
index 3e8d5b317a..9ff6f00898 100644
--- a/lib/bundler/templates/Executable
+++ b/lib/bundler/templates/Executable
@@ -8,14 +8,12 @@
# this file is here to facilitate running it.
#
-require "pathname"
-ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
- Pathname.new(__FILE__).realpath)
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("<%= relative_gemfile_path %>", __dir__)
-bundle_binstub = File.expand_path("../bundle", __FILE__)
+bundle_binstub = File.expand_path("bundle", __dir__)
if File.file?(bundle_binstub)
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
diff --git a/lib/bundler/templates/Executable.bundler b/lib/bundler/templates/Executable.bundler
index 8009412ea2..e290fe91eb 100644
--- a/lib/bundler/templates/Executable.bundler
+++ b/lib/bundler/templates/Executable.bundler
@@ -41,13 +41,13 @@ m = Module.new do
gemfile = ENV["BUNDLE_GEMFILE"]
return gemfile if gemfile && !gemfile.empty?
- File.expand_path("../<%= relative_gemfile_path %>", __FILE__)
+ File.expand_path("<%= relative_gemfile_path %>", __dir__)
end
def lockfile
lockfile =
case File.basename(gemfile)
- when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
+ when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
else "#{gemfile}.lock"
end
File.expand_path(lockfile)
@@ -62,8 +62,9 @@ m = Module.new do
def bundler_requirement
@bundler_requirement ||=
- env_var_version || cli_arg_version ||
- bundler_requirement_for(lockfile_version)
+ env_var_version ||
+ cli_arg_version ||
+ bundler_requirement_for(lockfile_version)
end
def bundler_requirement_for(version)
@@ -71,13 +72,7 @@ m = Module.new do
bundler_gem_version = Gem::Version.new(version)
- requirement = bundler_gem_version.approximate_recommendation
-
- return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
-
- requirement += ".a" if bundler_gem_version.prerelease?
-
- requirement
+ bundler_gem_version.approximate_recommendation
end
def load_bundler!
diff --git a/lib/bundler/templates/Executable.standalone b/lib/bundler/templates/Executable.standalone
index 4bf0753f44..3117a27e86 100644
--- a/lib/bundler/templates/Executable.standalone
+++ b/lib/bundler/templates/Executable.standalone
@@ -1,4 +1,6 @@
#!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG["ruby_install_name"] %>
+# frozen_string_literal: true
+
#
# This file was generated by Bundler.
#
@@ -6,9 +8,7 @@
# this file is here to facilitate running it.
#
-require "pathname"
-path = Pathname.new(__FILE__)
-$:.unshift File.expand_path "../<%= standalone_path %>", path.realpath
+$:.unshift File.expand_path "<%= standalone_path %>", __dir__
require "bundler/setup"
-load File.expand_path "../<%= executable_path %>", path.realpath
+load File.expand_path "<%= executable_path %>", __dir__
diff --git a/lib/bundler/templates/Gemfile b/lib/bundler/templates/Gemfile
index d41f2719b4..d2403f18b2 100644
--- a/lib/bundler/templates/Gemfile
+++ b/lib/bundler/templates/Gemfile
@@ -2,6 +2,4 @@
source "https://rubygems.org"
-git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
-
# gem "rails"
diff --git a/lib/bundler/templates/gems.rb b/lib/bundler/templates/gems.rb
deleted file mode 100644
index 56a62a7a82..0000000000
--- a/lib/bundler/templates/gems.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-# A sample gems.rb
-source "https://rubygems.org"
-
-git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
-
-# gem "rails"
diff --git a/lib/bundler/templates/newgem/Cargo.toml.tt b/lib/bundler/templates/newgem/Cargo.toml.tt
new file mode 100644
index 0000000000..f5a460c9bb
--- /dev/null
+++ b/lib/bundler/templates/newgem/Cargo.toml.tt
@@ -0,0 +1,7 @@
+# This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is
+# a Rust project. Your extensions dependencies should be added to the Cargo.toml
+# in the ext/ directory.
+
+[workspace]
+members = ["./ext/<%= config[:name] %>"]
+resolver = "2"
diff --git a/lib/bundler/templates/newgem/Gemfile.tt b/lib/bundler/templates/newgem/Gemfile.tt
index de82a63c5f..a0d2ac2826 100644
--- a/lib/bundler/templates/newgem/Gemfile.tt
+++ b/lib/bundler/templates/newgem/Gemfile.tt
@@ -9,6 +9,9 @@ gem "rake", "~> 13.0"
<%- if config[:ext] -%>
gem "rake-compiler"
+<%- if config[:ext] == 'rust' -%>
+gem "rb_sys", "~> 0.9.63"
+<%- end -%>
<%- end -%>
<%- if config[:test] -%>
diff --git a/lib/bundler/templates/newgem/README.md.tt b/lib/bundler/templates/newgem/README.md.tt
index 8fd87abe9a..20eaac8a62 100644
--- a/lib/bundler/templates/newgem/README.md.tt
+++ b/lib/bundler/templates/newgem/README.md.tt
@@ -1,24 +1,20 @@
# <%= config[:constant_name] %>
-Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/<%= config[:namespaced_path] %>`. To experiment with that code, run `bin/console` for an interactive prompt.
+TODO: Delete this and the text below, and describe your gem
-TODO: Delete this and the text above, and describe your gem
+Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/<%= config[:namespaced_path] %>`. To experiment with that code, run `bin/console` for an interactive prompt.
## Installation
-Add this line to your application's Gemfile:
-
-```ruby
-gem '<%= config[:name] %>'
-```
+TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
-And then execute:
+Install the gem and add to the application's Gemfile by executing:
- $ bundle install
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
-Or install it yourself as:
+If bundler is not being used to manage dependencies, install the gem by executing:
- $ gem install <%= config[:name] %>
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
## Usage
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index b02ada9b6c..b5a5c4e392 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -39,7 +39,17 @@ require "standard/rake"
<% end -%>
<% if config[:ext] -%>
-<% default_task_names.unshift(:clobber, :compile) -%>
+<% default_task_names.unshift(:compile) -%>
+<% default_task_names.unshift(:clobber) unless config[:ext] == 'rust' -%>
+<% if config[:ext] == 'rust' -%>
+require "rb_sys/extensiontask"
+
+task build: :compile
+
+RbSys::ExtensionTask.new(<%= config[:name].inspect %>) do |ext|
+ ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
+end
+<% else -%>
require "rake/extensiontask"
task build: :compile
@@ -47,6 +57,7 @@ task build: :compile
Rake::ExtensionTask.new("<%= config[:underscored_name] %>") do |ext|
ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
end
+<% end -%>
<% end -%>
<% if default_task_names.size == 1 -%>
diff --git a/lib/bundler/templates/newgem/bin/console.tt b/lib/bundler/templates/newgem/bin/console.tt
index 08dfaaef69..c91ee65f93 100644
--- a/lib/bundler/templates/newgem/bin/console.tt
+++ b/lib/bundler/templates/newgem/bin/console.tt
@@ -7,9 +7,5 @@ require "<%= config[:namespaced_path] %>"
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
-# (If you use this, don't forget to add pry to your Gemfile!)
-# require "pry"
-# Pry.start
-
require "irb"
IRB.start(__FILE__)
diff --git a/lib/bundler/templates/newgem/circleci/config.yml.tt b/lib/bundler/templates/newgem/circleci/config.yml.tt
index 79fd0dcc0f..f40f029bf1 100644
--- a/lib/bundler/templates/newgem/circleci/config.yml.tt
+++ b/lib/bundler/templates/newgem/circleci/config.yml.tt
@@ -3,8 +3,20 @@ jobs:
build:
docker:
- image: ruby:<%= RUBY_VERSION %>
+<%- if config[:ext] == 'rust' -%>
+ environment:
+ RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN: 'true'
+<%- end -%>
steps:
- checkout
+<%- if config[:ext] == 'rust' -%>
+ - run:
+ name: Install Rust/Cargo dependencies
+ command: apt-get update && apt-get install -y clang
+ - run:
+ name: Install a RubyGems version that can compile rust extensions
+ command: gem update --system '<%= ::Gem.rubygems_version %>'
+<%- end -%>
- run:
name: Run the default task
command: |
diff --git a/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt b/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
new file mode 100644
index 0000000000..c64385486e
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
@@ -0,0 +1,15 @@
+[package]
+name = <%= config[:name].inspect %>
+version = "0.1.0"
+edition = "2021"
+authors = ["<%= config[:author] %> <<%= config[:email] %>>"]
+<%- if config[:mit] -%>
+license = "MIT"
+<%- end -%>
+publish = false
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+magnus = { version = "0.6" }
diff --git a/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt b/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt
new file mode 100644
index 0000000000..0a0c5a3d09
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require "mkmf"
+
+# Makes all symbols private by default to avoid unintended conflict
+# with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED
+# selectively, or entirely remove this flag.
+append_cflags("-fvisibility=hidden")
+
+create_makefile(<%= config[:makefile_path].inspect %>)
diff --git a/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt b/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt
new file mode 100644
index 0000000000..e24566a17a
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+require "mkmf"
+require "rb_sys/mkmf"
+
+create_rust_makefile(<%= config[:makefile_path].inspect %>)
diff --git a/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt b/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt
deleted file mode 100644
index e918063ddf..0000000000
--- a/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-require "mkmf"
-
-create_makefile(<%= config[:makefile_path].inspect %>)
diff --git a/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt b/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt
index 8177c4d202..bcd5148569 100644
--- a/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt
+++ b/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt
@@ -2,7 +2,7 @@
VALUE rb_m<%= config[:constant_array].join %>;
-void
+RUBY_FUNC_EXPORTED void
Init_<%= config[:underscored_name] %>(void)
{
rb_m<%= config[:constant_array].join %> = rb_define_module(<%= config[:constant_name].inspect %>);
diff --git a/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt b/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt
new file mode 100644
index 0000000000..ba234529a3
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt
@@ -0,0 +1,12 @@
+use magnus::{function, prelude::*, Error, Ruby};
+
+fn hello(subject: String) -> String {
+ format!("Hello from Rust, {subject}!")
+}
+
+#[magnus::init]
+fn init(ruby: &Ruby) -> Result<(), Error> {
+ let module = ruby.<%= config[:constant_array].map {|c| "define_module(#{c.dump})?"}.join(".") %>;
+ module.define_singleton_method("hello", function!(hello, 1))?;
+ Ok(())
+}
diff --git a/lib/bundler/templates/newgem/github/workflows/main.yml.tt b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
index 654978033f..be58dd8156 100644
--- a/lib/bundler/templates/newgem/github/workflows/main.yml.tt
+++ b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
@@ -1,16 +1,37 @@
name: Ruby
-on: [push,pull_request]
+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
+ - uses: actions/checkout@v3
+<%- if config[:ext] == 'rust' -%>
+ - name: Set up Ruby & Rust
+ uses: oxidize-rb/actions/setup-ruby-and-rust@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
+ cargo-cache: true
+ rubygems: '<%= ::Gem.rubygems_version %>'
+<%- else -%>
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: <%= RUBY_VERSION %>
+ ruby-version: ${{ matrix.ruby }}
bundler-cache: true
+<%- end -%>
- name: Run the default task
run: bundle exec rake
diff --git a/lib/bundler/templates/newgem/gitignore.tt b/lib/bundler/templates/newgem/gitignore.tt
index b1c9f9986c..9b40ba5a58 100644
--- a/lib/bundler/templates/newgem/gitignore.tt
+++ b/lib/bundler/templates/newgem/gitignore.tt
@@ -12,6 +12,9 @@
*.o
*.a
mkmf.log
+<%- if config[:ext] == 'rust' -%>
+target/
+<%- end -%>
<%- end -%>
<%- if config[:test] == "rspec" -%>
diff --git a/lib/bundler/templates/newgem/gitlab-ci.yml.tt b/lib/bundler/templates/newgem/gitlab-ci.yml.tt
index 0e71ff26a4..d2e1f33736 100644
--- a/lib/bundler/templates/newgem/gitlab-ci.yml.tt
+++ b/lib/bundler/templates/newgem/gitlab-ci.yml.tt
@@ -1,9 +1,18 @@
-image: ruby:<%= RUBY_VERSION %>
+default:
+ image: ruby:<%= RUBY_VERSION %>
-before_script:
- - gem install bundler -v <%= Bundler::VERSION %>
- - bundle install
+ before_script:
+<%- if config[:ext] == 'rust' -%>
+ - apt-get update && apt-get install -y clang
+ - gem update --system '<%= ::Gem.rubygems_version %>'
+<%- end -%>
+ - gem install bundler -v <%= Bundler::VERSION %>
+ - bundle install
example_job:
+<%- if config[:ext] == 'rust' -%>
+ variables:
+ RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN: 'true'
+<%- end -%>
script:
- bundle exec rake
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index eddb8b4a30..bb76680379 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -15,8 +15,11 @@ Gem::Specification.new do |spec|
spec.license = "MIT"
<%- end -%>
spec.required_ruby_version = ">= <%= config[:required_ruby_version] %>"
+<%- if config[:ext] == 'rust' -%>
+ spec.required_rubygems_version = ">= <%= config[:rust_builder_required_rubygems_version] %>"
+<%- end -%>
- spec.metadata["allowed_push_host"] = "TODO: Set to 'https://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."
@@ -24,17 +27,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(__dir__)) do
+ spec.files = Dir.chdir(__dir__) do
`git ls-files -z`.split("\x0").reject do |f|
- f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
+ (File.expand_path(f) == __FILE__) ||
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
end
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
-<%- if config[:ext] -%>
+<%- if config[:ext] == 'c' -%>
spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
<%- end -%>
+<%- if config[:ext] == 'rust' -%>
+ spec.extensions = ["ext/<%= config[:underscored_name] %>/Cargo.toml"]
+<%- end -%>
# Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0"
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/standard.yml.tt b/lib/bundler/templates/newgem/standard.yml.tt
index e720f41031..934b0b2c37 100644
--- a/lib/bundler/templates/newgem/standard.yml.tt
+++ b/lib/bundler/templates/newgem/standard.yml.tt
@@ -1,4 +1,3 @@
# For available configuration options, see:
# https://github.com/testdouble/standard
-
-default_ignores: false
+ruby_version: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %>
diff --git a/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt b/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt
index 5eb8fcbf9d..4b35a63071 100644
--- a/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt
+++ b/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt
@@ -2,7 +2,7 @@
require "test_helper"
-class Test<%= config[:constant_name] %> < Minitest::Test
+class <%= config[:minitest_constant_name] %> < Minitest::Test
def test_that_it_has_a_version_number
refute_nil ::<%= config[:constant_name] %>::VERSION
end
diff --git a/lib/bundler/templates/newgem/travis.yml.tt b/lib/bundler/templates/newgem/travis.yml.tt
deleted file mode 100644
index eab16addca..0000000000
--- a/lib/bundler/templates/newgem/travis.yml.tt
+++ /dev/null
@@ -1,6 +0,0 @@
----
-language: ruby
-cache: bundler
-rvm:
- - <%= RUBY_VERSION %>
-before_install: gem install bundler -v <%= Bundler::VERSION %>
diff --git a/lib/bundler/ui/rg_proxy.rb b/lib/bundler/ui/rg_proxy.rb
index ef6def225b..b17ca65f53 100644
--- a/lib/bundler/ui/rg_proxy.rb
+++ b/lib/bundler/ui/rg_proxy.rb
@@ -12,7 +12,7 @@ module Bundler
end
def say(message)
- @ui && @ui.debug(message)
+ @ui&.debug(message)
end
end
end
diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb
index 17777af4ac..4139585c47 100644
--- a/lib/bundler/ui/shell.rb
+++ b/lib/bundler/ui/shell.rb
@@ -20,29 +20,52 @@ module Bundler
@shell.set_color(string, *color)
end
- def info(msg, newline = nil)
- tell_me(msg, nil, newline) if level("info")
+ def info(msg = nil, newline = nil)
+ return unless info?
+
+ tell_me(msg || yield, nil, newline)
end
- def confirm(msg, newline = nil)
- tell_me(msg, :green, newline) if level("confirm")
+ def confirm(msg = nil, newline = nil)
+ return unless confirm?
+
+ tell_me(msg || yield, :green, newline)
end
- def warn(msg, newline = nil, color = :yellow)
- return unless level("warn")
+ def warn(msg = nil, newline = nil, color = :yellow)
+ return unless warn?
return if @warning_history.include? msg
@warning_history << msg
- tell_err(msg, color, newline)
+ tell_err(msg || yield, color, newline)
+ end
+
+ def error(msg = nil, newline = nil, color = :red)
+ return unless error?
+
+ tell_err(msg || yield, color, newline)
+ end
+
+ def debug(msg = nil, newline = nil)
+ return unless debug?
+
+ tell_me(msg || yield, nil, newline)
+ end
+
+ def info?
+ level("info")
+ end
+
+ def confirm?
+ level("confirm")
end
- def error(msg, newline = nil, color = :red)
- return unless level("error")
- tell_err(msg, color, newline)
+ def warn?
+ level("warn")
end
- def debug(msg, newline = nil)
- tell_me(msg, nil, newline) if debug?
+ def error?
+ level("error")
end
def debug?
@@ -81,7 +104,7 @@ module Bundler
def trace(e, newline = nil, force = false)
return unless debug? || force
msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n ")}"
- tell_me(msg, nil, newline)
+ tell_err(msg, nil, newline)
end
def silence(&blk)
diff --git a/lib/bundler/ui/silent.rb b/lib/bundler/ui/silent.rb
index dca1b2ac86..fa3292bdc9 100644
--- a/lib/bundler/ui/silent.rb
+++ b/lib/bundler/ui/silent.rb
@@ -13,30 +13,46 @@ module Bundler
string
end
- def info(message, newline = nil)
+ def info(message = nil, newline = nil)
end
- def confirm(message, newline = nil)
+ def confirm(message = nil, newline = nil)
end
- def warn(message, newline = nil)
+ def warn(message = nil, newline = nil)
@warnings |= [message]
end
- def error(message, newline = nil)
+ def error(message = nil, newline = nil)
end
- def debug(message, newline = nil)
+ def debug(message = nil, newline = nil)
+ end
+
+ def confirm?
+ false
+ end
+
+ def error?
+ false
end
def debug?
false
end
+ def info?
+ false
+ end
+
def quiet?
false
end
+ def warn?
+ false
+ end
+
def ask(message)
end
diff --git a/lib/bundler/uri_normalizer.rb b/lib/bundler/uri_normalizer.rb
new file mode 100644
index 0000000000..ad08593256
--- /dev/null
+++ b/lib/bundler/uri_normalizer.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Bundler
+ module URINormalizer
+ module_function
+
+ # Normalizes uri to a consistent version, either with or without trailing
+ # slash.
+ #
+ # TODO: Currently gem sources are locked with a trailing slash, while git
+ # sources are locked without a trailing slash. This should be normalized but
+ # the inconsistency is there for now to avoid changing all lockfiles
+ # including GIT sources. We could normalize this on the next major.
+ #
+ def normalize_suffix(uri, trailing_slash: true)
+ if trailing_slash
+ uri.end_with?("/") ? uri : "#{uri}/"
+ else
+ uri.end_with?("/") ? uri.delete_suffix("/") : uri
+ end
+ end
+ end
+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/lib/connection_pool.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
index 984c1c3dcb..455319efe3 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
@@ -3,7 +3,9 @@ require_relative "connection_pool/version"
class Bundler::ConnectionPool
class Error < ::RuntimeError; end
+
class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end
+
class TimeoutError < ::Timeout::Error; end
end
@@ -67,7 +69,7 @@ class Bundler::ConnectionPool
end
end
end
- alias then with
+ alias_method :then, :with
def checkout(options = {})
if ::Thread.current[@key]
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 a7b1cf06a8..35d1d7cc35 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
@@ -49,7 +49,7 @@ class Bundler::ConnectionPool::TimedStack
@resource.broadcast
end
end
- alias << push
+ alias_method :<<, :push
##
# Retrieves a connection from the stack. If a connection is available it is
@@ -74,7 +74,7 @@ class Bundler::ConnectionPool::TimedStack
return connection if connection
to_wait = deadline - current_time
- raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec" if to_wait <= 0
+ raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available" if to_wait <= 0
@resource.wait(@mutex, to_wait)
end
end
@@ -87,7 +87,7 @@ class Bundler::ConnectionPool::TimedStack
# +:reload+ is +true+.
def shutdown(reload: false, &block)
- raise ArgumentError, "shutdown must receive a block" unless block_given?
+ raise ArgumentError, "shutdown must receive a block" unless block
@mutex.synchronize do
@shutdown_block = block
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
index 880170c06b..dd796d1021 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
@@ -30,7 +30,6 @@ class Bundler::ConnectionPool
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)
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils.rb b/lib/bundler/vendor/fileutils/lib/fileutils.rb
index 8f8faf30c8..211311c069 100644
--- a/lib/bundler/vendor/fileutils/lib/fileutils.rb
+++ b/lib/bundler/vendor/fileutils/lib/fileutils.rb
@@ -3,106 +3,184 @@
begin
require 'rbconfig'
rescue LoadError
- # for make mjit-headers
+ # for make rjit-headers
end
+# Namespace for file utility methods for copying, moving, removing, etc.
#
-# = fileutils.rb
+# == What's Here
#
-# Copyright (c) 2000-2007 Minero Aoki
+# First, what’s elsewhere. \Module \Bundler::FileUtils:
#
-# This program is free software.
-# You can distribute/modify this program under the same terms of ruby.
+# - Inherits from {class Object}[rdoc-ref:Object].
+# - Supplements {class File}[rdoc-ref:File]
+# (but is not included or extended there).
#
-# == module Bundler::FileUtils
+# Here, module \Bundler::FileUtils provides methods that are useful for:
#
-# Namespace for several file utility methods for copying, moving, removing, etc.
+# - {Creating}[rdoc-ref:FileUtils@Creating].
+# - {Deleting}[rdoc-ref:FileUtils@Deleting].
+# - {Querying}[rdoc-ref:FileUtils@Querying].
+# - {Setting}[rdoc-ref:FileUtils@Setting].
+# - {Comparing}[rdoc-ref:FileUtils@Comparing].
+# - {Copying}[rdoc-ref:FileUtils@Copying].
+# - {Moving}[rdoc-ref:FileUtils@Moving].
+# - {Options}[rdoc-ref:FileUtils@Options].
#
-# === Module Functions
+# === Creating
#
-# require 'bundler/vendor/fileutils/lib/fileutils'
+# - ::mkdir: Creates directories.
+# - ::mkdir_p, ::makedirs, ::mkpath: Creates directories,
+# also creating ancestor directories as needed.
+# - ::link_entry: Creates a hard link.
+# - ::ln, ::link: Creates hard links.
+# - ::ln_s, ::symlink: Creates symbolic links.
+# - ::ln_sf: Creates symbolic links, overwriting if necessary.
+# - ::ln_sr: Creates symbolic links relative to targets
#
-# Bundler::FileUtils.cd(dir, **options)
-# Bundler::FileUtils.cd(dir, **options) {|dir| block }
-# Bundler::FileUtils.pwd()
-# Bundler::FileUtils.mkdir(dir, **options)
-# Bundler::FileUtils.mkdir(list, **options)
-# Bundler::FileUtils.mkdir_p(dir, **options)
-# Bundler::FileUtils.mkdir_p(list, **options)
-# Bundler::FileUtils.rmdir(dir, **options)
-# Bundler::FileUtils.rmdir(list, **options)
-# Bundler::FileUtils.ln(target, link, **options)
-# Bundler::FileUtils.ln(targets, dir, **options)
-# Bundler::FileUtils.ln_s(target, link, **options)
-# Bundler::FileUtils.ln_s(targets, dir, **options)
-# Bundler::FileUtils.ln_sf(target, link, **options)
-# Bundler::FileUtils.cp(src, dest, **options)
-# Bundler::FileUtils.cp(list, dir, **options)
-# Bundler::FileUtils.cp_r(src, dest, **options)
-# Bundler::FileUtils.cp_r(list, dir, **options)
-# Bundler::FileUtils.mv(src, dest, **options)
-# Bundler::FileUtils.mv(list, dir, **options)
-# Bundler::FileUtils.rm(list, **options)
-# Bundler::FileUtils.rm_r(list, **options)
-# Bundler::FileUtils.rm_rf(list, **options)
-# Bundler::FileUtils.install(src, dest, **options)
-# Bundler::FileUtils.chmod(mode, list, **options)
-# Bundler::FileUtils.chmod_R(mode, list, **options)
-# Bundler::FileUtils.chown(user, group, list, **options)
-# Bundler::FileUtils.chown_R(user, group, list, **options)
-# Bundler::FileUtils.touch(list, **options)
+# === Deleting
#
-# Possible <tt>options</tt> are:
+# - ::remove_dir: Removes a directory and its descendants.
+# - ::remove_entry: Removes an entry, including its descendants if it is a directory.
+# - ::remove_entry_secure: Like ::remove_entry, but removes securely.
+# - ::remove_file: Removes a file entry.
+# - ::rm, ::remove: Removes entries.
+# - ::rm_f, ::safe_unlink: Like ::rm, but removes forcibly.
+# - ::rm_r: Removes entries and their descendants.
+# - ::rm_rf, ::rmtree: Like ::rm_r, but removes forcibly.
+# - ::rmdir: Removes directories.
#
-# <tt>:force</tt> :: forced operation (rewrite files if exist, remove
-# directories if not empty, etc.);
-# <tt>:verbose</tt> :: print command to be run, in bash syntax, before
-# performing it;
-# <tt>:preserve</tt> :: preserve object's group, user and modification
-# time on copying;
-# <tt>:noop</tt> :: no changes are made (usable in combination with
-# <tt>:verbose</tt> which will print the command to run)
+# === Querying
#
-# Each method documents the options that it honours. See also ::commands,
-# ::options and ::options_of methods to introspect which command have which
-# options.
+# - ::pwd, ::getwd: Returns the path to the working directory.
+# - ::uptodate?: Returns whether a given entry is newer than given other entries.
#
-# All methods that have the concept of a "source" file or directory can take
-# either one file or a list of files in that argument. See the method
-# documentation for examples.
+# === Setting
#
-# There are some `low level' methods, which do not accept keyword arguments:
+# - ::cd, ::chdir: Sets the working directory.
+# - ::chmod: Sets permissions for an entry.
+# - ::chmod_R: Sets permissions for an entry and its descendants.
+# - ::chown: Sets the owner and group for entries.
+# - ::chown_R: Sets the owner and group for entries and their descendants.
+# - ::touch: Sets modification and access times for entries,
+# creating if necessary.
#
-# Bundler::FileUtils.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
-# Bundler::FileUtils.copy_file(src, dest, preserve = false, dereference = true)
-# Bundler::FileUtils.copy_stream(srcstream, deststream)
-# Bundler::FileUtils.remove_entry(path, force = false)
-# Bundler::FileUtils.remove_entry_secure(path, force = false)
-# Bundler::FileUtils.remove_file(path, force = false)
-# Bundler::FileUtils.compare_file(path_a, path_b)
-# Bundler::FileUtils.compare_stream(stream_a, stream_b)
-# Bundler::FileUtils.uptodate?(file, cmp_list)
+# === Comparing
#
-# == module Bundler::FileUtils::Verbose
+# - ::compare_file, ::cmp, ::identical?: Returns whether two entries are identical.
+# - ::compare_stream: Returns whether two streams are identical.
#
-# This module has all methods of Bundler::FileUtils module, but it outputs messages
-# before acting. This equates to passing the <tt>:verbose</tt> flag to methods
-# in Bundler::FileUtils.
+# === Copying
#
-# == module Bundler::FileUtils::NoWrite
+# - ::copy_entry: Recursively copies an entry.
+# - ::copy_file: Copies an entry.
+# - ::copy_stream: Copies a stream.
+# - ::cp, ::copy: Copies files.
+# - ::cp_lr: Recursively creates hard links.
+# - ::cp_r: Recursively copies files, retaining mode, owner, and group.
+# - ::install: Recursively copies files, optionally setting mode,
+# owner, and group.
#
-# This module has all methods of Bundler::FileUtils module, but never changes
-# files/directories. This equates to passing the <tt>:noop</tt> flag to methods
-# in Bundler::FileUtils.
+# === Moving
#
-# == module Bundler::FileUtils::DryRun
+# - ::mv, ::move: Moves entries.
#
-# This module has all methods of Bundler::FileUtils module, but never changes
-# files/directories. This equates to passing the <tt>:noop</tt> and
-# <tt>:verbose</tt> flags to methods in Bundler::FileUtils.
+# === Options
+#
+# - ::collect_method: Returns the names of methods that accept a given option.
+# - ::commands: Returns the names of methods that accept options.
+# - ::have_option?: Returns whether a given method accepts a given option.
+# - ::options: Returns all option names.
+# - ::options_of: Returns the names of the options for a given method.
+#
+# == Path Arguments
+#
+# Some methods in \Bundler::FileUtils accept _path_ arguments,
+# which are interpreted as paths to filesystem entries:
+#
+# - If the argument is a string, that value is the path.
+# - If the argument has method +:to_path+, it is converted via that method.
+# - If the argument has method +:to_str+, it is converted via that method.
+#
+# == About the Examples
+#
+# Some examples here involve trees of file entries.
+# For these, we sometimes display trees using the
+# {tree command-line utility}[https://en.wikipedia.org/wiki/Tree_(command)],
+# which is a recursive directory-listing utility that produces
+# a depth-indented listing of files and directories.
+#
+# We use a helper method to launch the command and control the format:
+#
+# def tree(dirpath = '.')
+# command = "tree --noreport --charset=ascii #{dirpath}"
+# system(command)
+# end
+#
+# To illustrate:
+#
+# tree('src0')
+# # => src0
+# # |-- sub0
+# # | |-- src0.txt
+# # | `-- src1.txt
+# # `-- sub1
+# # |-- src2.txt
+# # `-- src3.txt
+#
+# == Avoiding the TOCTTOU Vulnerability
+#
+# For certain methods that recursively remove entries,
+# there is a potential vulnerability called the
+# {Time-of-check to time-of-use}[https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use],
+# or TOCTTOU, vulnerability that can exist when:
+#
+# - An ancestor directory of the entry at the target path is world writable;
+# such directories include <tt>/tmp</tt>.
+# - The directory tree at the target path includes:
+#
+# - A world-writable descendant directory.
+# - A symbolic link.
+#
+# To avoid that vulnerability, you can use this method to remove entries:
+#
+# - Bundler::FileUtils.remove_entry_secure: removes recursively
+# if the target path points to a directory.
+#
+# Also available are these methods,
+# each of which calls \Bundler::FileUtils.remove_entry_secure:
+#
+# - Bundler::FileUtils.rm_r with keyword argument <tt>secure: true</tt>.
+# - Bundler::FileUtils.rm_rf with keyword argument <tt>secure: true</tt>.
+#
+# Finally, this method for moving entries calls \Bundler::FileUtils.remove_entry_secure
+# if the source and destination are on different file systems
+# (which means that the "move" is really a copy and remove):
+#
+# - Bundler::FileUtils.mv with keyword argument <tt>secure: true</tt>.
+#
+# \Method \Bundler::FileUtils.remove_entry_secure removes securely
+# by applying a special pre-process:
+#
+# - If the target path points to a directory, this method uses methods
+# {File#chown}[rdoc-ref:File#chown]
+# and {File#chmod}[rdoc-ref:File#chmod]
+# in removing directories.
+# - The owner of the target directory should be either the current process
+# or the super user (root).
+#
+# WARNING: You must ensure that *ALL* parent directories cannot be
+# moved by other untrusted users. For example, parent directories
+# should not be owned by untrusted users, and should not be world
+# writable except when the sticky bit is set.
+#
+# For details of this security vulnerability, see Perl cases:
+#
+# - {CVE-2005-0448}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448].
+# - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
#
module Bundler::FileUtils
- VERSION = "1.4.1"
+ VERSION = "1.7.0"
def self.private_module_function(name) #:nodoc:
module_function name
@@ -110,7 +188,13 @@ module Bundler::FileUtils
end
#
- # Returns the name of the current directory.
+ # Returns a string containing the path to the current directory:
+ #
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
+ #
+ # Bundler::FileUtils.getwd is an alias for Bundler::FileUtils.pwd.
+ #
+ # Related: Bundler::FileUtils.cd.
#
def pwd
Dir.pwd
@@ -120,19 +204,40 @@ module Bundler::FileUtils
alias getwd pwd
module_function :getwd
+ # Changes the working directory to the given +dir+, which
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments]:
+ #
+ # With no block given,
+ # changes the current directory to the directory at +dir+; returns zero:
+ #
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
+ # Bundler::FileUtils.cd('..')
+ # Bundler::FileUtils.pwd # => "/rdoc"
+ # Bundler::FileUtils.cd('fileutils')
+ #
+ # With a block given, changes the current directory to the directory
+ # at +dir+, calls the block with argument +dir+,
+ # and restores the original current directory; returns the block's value:
#
- # Changes the current directory to the directory +dir+.
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
+ # Bundler::FileUtils.cd('..') { |arg| [arg, Bundler::FileUtils.pwd] } # => ["..", "/rdoc"]
+ # Bundler::FileUtils.pwd # => "/rdoc/fileutils"
#
- # If this method is called with block, resumes to the previous
- # working directory after the block execution has finished.
+ # Keyword arguments:
#
- # Bundler::FileUtils.cd('/') # change directory
+ # - <tt>verbose: true</tt> - prints an equivalent command:
#
- # Bundler::FileUtils.cd('/', verbose: true) # change directory and report it
+ # Bundler::FileUtils.cd('..')
+ # Bundler::FileUtils.cd('fileutils')
#
- # Bundler::FileUtils.cd('/') do # change directory
- # # ... # do something
- # end # return to original directory
+ # Output:
+ #
+ # cd ..
+ # cd fileutils
+ #
+ # Bundler::FileUtils.chdir is an alias for Bundler::FileUtils.cd.
+ #
+ # Related: Bundler::FileUtils.pwd.
#
def cd(dir, verbose: nil, &block) # :yield: dir
fu_output_message "cd #{dir}" if verbose
@@ -146,11 +251,19 @@ module Bundler::FileUtils
module_function :chdir
#
- # Returns true if +new+ is newer than all +old_list+.
- # Non-existent files are older than any file.
+ # Returns +true+ if the file at path +new+
+ # is newer than all the files at paths in array +old_list+;
+ # +false+ otherwise.
+ #
+ # Argument +new+ and the elements of +old_list+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments]:
#
- # Bundler::FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \
- # system 'make hello.o'
+ # Bundler::FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
+ # Bundler::FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
+ #
+ # A non-existent file is considered to be infinitely old.
+ #
+ # Related: Bundler::FileUtils.touch.
#
def uptodate?(new, old_list)
return false unless File.exist?(new)
@@ -170,12 +283,39 @@ module Bundler::FileUtils
private_module_function :remove_trailing_slash
#
- # Creates one or more directories.
+ # Creates directories at the paths in the given +list+
+ # (a single path or an array of paths);
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, creates a directory at each +path+ in +list+
+ # by calling: <tt>Dir.mkdir(path, mode)</tt>;
+ # see {Dir.mkdir}[rdoc-ref:Dir.mkdir]:
+ #
+ # Bundler::FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
+ # Bundler::FileUtils.mkdir('tmp4') # => ["tmp4"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
+ # see {File.chmod}[rdoc-ref:File.chmod].
+ # - <tt>noop: true</tt> - does not create directories.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.mkdir(%w[tmp0 tmp1], verbose: true)
+ # Bundler::FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
+ #
+ # Output:
#
- # Bundler::FileUtils.mkdir 'test'
- # Bundler::FileUtils.mkdir %w(tmp data)
- # Bundler::FileUtils.mkdir 'notexist', noop: true # Does not really create.
- # Bundler::FileUtils.mkdir 'tmp', mode: 0700
+ # mkdir tmp0 tmp1
+ # mkdir -m 700 tmp2 tmp3
+ #
+ # Raises an exception if any path points to an existing
+ # file or directory, or if for any reason a directory cannot be created.
+ #
+ # Related: Bundler::FileUtils.mkdir_p.
#
def mkdir(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -189,40 +329,56 @@ module Bundler::FileUtils
module_function :mkdir
#
- # Creates a directory and all its parent directories.
- # For example,
+ # Creates directories at the paths in the given +list+
+ # (a single path or an array of paths),
+ # also creating ancestor directories as needed;
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, creates a directory at each +path+ in +list+,
+ # along with any needed ancestor directories,
+ # by calling: <tt>Dir.mkdir(path, mode)</tt>;
+ # see {Dir.mkdir}[rdoc-ref:Dir.mkdir]:
+ #
+ # Bundler::FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
+ # Bundler::FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
+ # see {File.chmod}[rdoc-ref:File.chmod].
+ # - <tt>noop: true</tt> - does not create directories.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true)
+ # Bundler::FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
#
- # Bundler::FileUtils.mkdir_p '/usr/local/lib/ruby'
+ # Output:
#
- # causes to make following directories, if they do not exist.
+ # mkdir -p tmp0 tmp1
+ # mkdir -p -m 700 tmp2 tmp3
#
- # * /usr
- # * /usr/local
- # * /usr/local/lib
- # * /usr/local/lib/ruby
+ # Raises an exception if for any reason a directory cannot be created.
#
- # You can pass several directories at a time in a list.
+ # Bundler::FileUtils.mkpath and Bundler::FileUtils.makedirs are aliases for Bundler::FileUtils.mkdir_p.
+ #
+ # Related: Bundler::FileUtils.mkdir.
#
def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
return *list if noop
- list.map {|path| remove_trailing_slash(path)}.each do |path|
- # optimize for the most common case
- begin
- fu_mkdir path, mode
- next
- rescue SystemCallError
- next if File.directory?(path)
- end
+ list.each do |item|
+ path = remove_trailing_slash(item)
stack = []
- until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/"
+ until File.directory?(path) || File.dirname(path) == path
stack.push path
path = File.dirname(path)
end
- stack.pop # root directory should exist
stack.reverse_each do |dir|
begin
fu_mkdir dir, mode
@@ -253,12 +409,39 @@ module Bundler::FileUtils
private_module_function :fu_mkdir
#
- # Removes one or more directories.
+ # Removes directories at the paths in the given +list+
+ # (a single path or an array of paths);
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, removes the directory at each +path+ in +list+,
+ # by calling: <tt>Dir.rmdir(path)</tt>;
+ # see {Dir.rmdir}[rdoc-ref:Dir.rmdir]:
+ #
+ # Bundler::FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
+ # Bundler::FileUtils.rmdir('tmp4/tmp5') # => ["tmp4/tmp5"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>parents: true</tt> - removes successive ancestor directories
+ # if empty.
+ # - <tt>noop: true</tt> - does not remove directories.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
#
- # Bundler::FileUtils.rmdir 'somedir'
- # Bundler::FileUtils.rmdir %w(somedir anydir otherdir)
- # # Does not really remove directory; outputs message.
- # Bundler::FileUtils.rmdir 'somedir', verbose: true, noop: true
+ # Bundler::FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true)
+ # Bundler::FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)
+ #
+ # Output:
+ #
+ # rmdir -p tmp0/tmp1 tmp2/tmp3
+ # rmdir -p tmp4/tmp5
+ #
+ # Raises an exception if a directory does not exist
+ # or if for any reason a directory cannot be removed.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rmdir(list, parents: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -279,26 +462,62 @@ module Bundler::FileUtils
end
module_function :rmdir
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # When +src+ is the path to an existing file
+ # and +dest+ is the path to a non-existent file,
+ # creates a hard link at +dest+ pointing to +src+; returns zero:
+ #
+ # Dir.children('tmp0/') # => ["t.txt"]
+ # Dir.children('tmp1/') # => []
+ # Bundler::FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
+ # Dir.children('tmp1/') # => ["t.lnk"]
+ #
+ # When +src+ is the path to an existing file
+ # and +dest+ is the path to an existing directory,
+ # creates a hard link at <tt>dest/src</tt> pointing to +src+; returns zero:
#
- # :call-seq:
- # Bundler::FileUtils.ln(target, link, force: nil, noop: nil, verbose: nil)
- # Bundler::FileUtils.ln(target, dir, force: nil, noop: nil, verbose: nil)
- # Bundler::FileUtils.ln(targets, dir, force: nil, noop: nil, verbose: nil)
+ # Dir.children('tmp2') # => ["t.dat"]
+ # Dir.children('tmp3') # => []
+ # Bundler::FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
+ # Dir.children('tmp3') # => ["t.dat"]
#
- # In the first form, creates a hard link +link+ which points to +target+.
- # If +link+ already exists, raises Errno::EEXIST.
- # But if the +force+ option is set, overwrites +link+.
+ # When +src+ is an array of paths to existing files
+ # and +dest+ is the path to an existing directory,
+ # then for each path +target+ in +src+,
+ # creates a hard link at <tt>dest/target</tt> pointing to +target+;
+ # returns +src+:
#
- # Bundler::FileUtils.ln 'gcc', 'cc', verbose: true
- # Bundler::FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'
+ # Dir.children('tmp4/') # => []
+ # Bundler::FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
+ # Dir.children('tmp4/') # => ["t.dat", "t.txt"]
#
- # In the second form, creates a link +dir/target+ pointing to +target+.
- # In the third form, creates several hard links in the directory +dir+,
- # pointing to each item in +targets+.
- # If +dir+ is not a directory, raises Errno::ENOTDIR.
+ # Keyword arguments:
#
- # Bundler::FileUtils.cd '/sbin'
- # Bundler::FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked.
+ # - <tt>force: true</tt> - overwrites +dest+ if it exists.
+ # - <tt>noop: true</tt> - does not create links.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true)
+ # Bundler::FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true)
+ # Bundler::FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)
+ #
+ # Output:
+ #
+ # ln tmp0/t.txt tmp1/t.lnk
+ # ln tmp2/t.dat tmp3
+ # ln tmp0/t.txt tmp2/t.dat tmp4/
+ #
+ # Raises an exception if +dest+ is the path to an existing file
+ # and keyword argument +force+ is not +true+.
+ #
+ # Bundler::FileUtils#link is an alias for Bundler::FileUtils#ln.
+ #
+ # Related: Bundler::FileUtils.link_entry (has different options).
#
def ln(src, dest, force: nil, noop: nil, verbose: nil)
fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -313,28 +532,103 @@ module Bundler::FileUtils
alias link ln
module_function :link
- #
- # Hard link +src+ to +dest+. If +src+ is a directory, this method links
- # all its contents recursively. If +dest+ is a directory, links
- # +src+ to +dest/src+.
- #
- # +src+ can be a list of files.
- #
- # If +dereference_root+ is true, this method dereference tree root.
- #
- # If +remove_destination+ is true, this method removes each destination file before copy.
- #
- # Bundler::FileUtils.rm_r site_ruby + '/mylib', force: true
- # Bundler::FileUtils.cp_lr 'lib/', site_ruby + '/mylib'
- #
- # # Examples of linking several files to target directory.
- # Bundler::FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
- # Bundler::FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', noop: true, verbose: true
- #
- # # If you want to link all contents of a directory instead of the
- # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
- # # use the following code.
- # Bundler::FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't.
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ is the path to a directory and +dest+ does not exist,
+ # creates links +dest+ and descendents pointing to +src+ and its descendents:
+ #
+ # tree('src0')
+ # # => src0
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # File.exist?('dest0') # => false
+ # Bundler::FileUtils.cp_lr('src0', 'dest0')
+ # tree('dest0')
+ # # => dest0
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ and +dest+ are both paths to directories,
+ # creates links <tt>dest/src</tt> and descendents
+ # pointing to +src+ and its descendents:
+ #
+ # tree('src1')
+ # # => src1
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # Bundler::FileUtils.mkdir('dest1')
+ # Bundler::FileUtils.cp_lr('src1', 'dest1')
+ # tree('dest1')
+ # # => dest1
+ # # `-- src1
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ is an array of paths to entries and +dest+ is the path to a directory,
+ # for each path +filepath+ in +src+, creates a link at <tt>dest/filepath</tt>
+ # pointing to that path:
+ #
+ # tree('src2')
+ # # => src2
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # Bundler::FileUtils.mkdir('dest2')
+ # Bundler::FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
+ # tree('dest2')
+ # # => dest2
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
+ # does not dereference it.
+ # - <tt>noop: true</tt> - does not create links.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true)
+ # Bundler::FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true)
+ # Bundler::FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # cp -lr src0 dest0
+ # cp -lr src1 dest1
+ # cp -lr src2/sub0 src2/sub1 dest2
+ #
+ # Raises an exception if +dest+ is the path to an existing file or directory
+ # and keyword argument <tt>remove_destination: true</tt> is not given.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp_lr(src, dest, noop: nil, verbose: nil,
dereference_root: true, remove_destination: false)
@@ -346,27 +640,81 @@ module Bundler::FileUtils
end
module_function :cp_lr
+ # Creates {symbolic links}[https://en.wikipedia.org/wiki/Symbolic_link].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ is the path to an existing file:
+ #
+ # - When +dest+ is the path to a non-existent file,
+ # creates a symbolic link at +dest+ pointing to +src+:
+ #
+ # Bundler::FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # Bundler::FileUtils.ln_s('src0.txt', 'dest0.txt')
+ # File.symlink?('dest0.txt') # => true
#
- # :call-seq:
- # Bundler::FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
- # Bundler::FileUtils.ln_s(target, dir, force: nil, noop: nil, verbose: nil)
- # Bundler::FileUtils.ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
+ # - When +dest+ is the path to an existing file,
+ # creates a symbolic link at +dest+ pointing to +src+
+ # if and only if keyword argument <tt>force: true</tt> is given
+ # (raises an exception otherwise):
#
- # In the first form, creates a symbolic link +link+ which points to +target+.
- # If +link+ already exists, raises Errno::EEXIST.
- # But if the <tt>force</tt> option is set, overwrites +link+.
+ # Bundler::FileUtils.touch('src1.txt')
+ # Bundler::FileUtils.touch('dest1.txt')
+ # Bundler::FileUtils.ln_s('src1.txt', 'dest1.txt', force: true)
+ # FileTest.symlink?('dest1.txt') # => true
#
- # Bundler::FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
- # Bundler::FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true
+ # Bundler::FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
#
- # In the second form, creates a link +dir/target+ pointing to +target+.
- # In the third form, creates several symbolic links in the directory +dir+,
- # pointing to each item in +targets+.
- # If +dir+ is not a directory, raises Errno::ENOTDIR.
+ # If +dest+ is the path to a directory,
+ # creates a symbolic link at <tt>dest/src</tt> pointing to +src+:
#
- # Bundler::FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin'
+ # Bundler::FileUtils.touch('src2.txt')
+ # Bundler::FileUtils.mkdir('destdir2')
+ # Bundler::FileUtils.ln_s('src2.txt', 'destdir2')
+ # File.symlink?('destdir2/src2.txt') # => true
#
- def ln_s(src, dest, force: nil, noop: nil, verbose: nil)
+ # If +src+ is an array of paths to existing files and +dest+ is a directory,
+ # for each child +child+ in +src+ creates a symbolic link <tt>dest/child</tt>
+ # pointing to +child+:
+ #
+ # Bundler::FileUtils.mkdir('srcdir3')
+ # Bundler::FileUtils.touch('srcdir3/src0.txt')
+ # Bundler::FileUtils.touch('srcdir3/src1.txt')
+ # Bundler::FileUtils.mkdir('destdir3')
+ # Bundler::FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
+ # File.symlink?('destdir3/src0.txt') # => true
+ # File.symlink?('destdir3/src1.txt') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - overwrites +dest+ if it exists.
+ # - <tt>relative: false</tt> - create links relative to +dest+.
+ # - <tt>noop: true</tt> - does not create links.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true)
+ # Bundler::FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true)
+ # Bundler::FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # ln -s src0.txt dest0.txt
+ # ln -s src1.txt destdir1
+ # ln -sf src2.txt dest2.txt
+ # ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
+ #
+ # Bundler::FileUtils.symlink is an alias for Bundler::FileUtils.ln_s.
+ #
+ # Related: Bundler::FileUtils.ln_sf.
+ #
+ def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
+ if relative
+ return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
+ end
fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest0(src, dest) do |s,d|
@@ -379,29 +727,95 @@ module Bundler::FileUtils
alias symlink ln_s
module_function :symlink
- #
- # :call-seq:
- # Bundler::FileUtils.ln_sf(*args)
- #
- # Same as
- #
- # Bundler::FileUtils.ln_s(*args, force: true)
+ # Like Bundler::FileUtils.ln_s, but always with keyword argument <tt>force: true</tt> given.
#
def ln_sf(src, dest, noop: nil, verbose: nil)
ln_s src, dest, force: true, noop: noop, verbose: verbose
end
module_function :ln_sf
+ # Like Bundler::FileUtils.ln_s, but create links relative to +dest+.
+ #
+ def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
+ options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
+ dest = File.path(dest)
+ srcs = Array(src)
+ link = proc do |s, target_dir_p = true|
+ s = File.path(s)
+ if target_dir_p
+ d = File.join(destdirs = dest, File.basename(s))
+ else
+ destdirs = File.dirname(d = dest)
+ end
+ destdirs = fu_split_path(File.realpath(destdirs))
+ if fu_starting_path?(s)
+ srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
+ base = fu_relative_components_from(srcdirs, destdirs)
+ s = File.join(*base)
+ else
+ srcdirs = fu_clean_components(*fu_split_path(s))
+ base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
+ while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
+ srcdirs.shift
+ base.pop
+ end
+ s = File.join(*base, *srcdirs)
+ end
+ fu_output_message "ln -s#{options} #{s} #{d}" if verbose
+ next if noop
+ remove_file d, true if force
+ File.symlink s, d
+ end
+ case srcs.size
+ when 0
+ when 1
+ link[srcs[0], target_directory && File.directory?(dest)]
+ else
+ srcs.each(&link)
+ end
+ end
+ module_function :ln_sr
+
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link]; returns +nil+.
#
- # Hard links a file system entry +src+ to +dest+.
- # If +src+ is a directory, this method links its contents recursively.
+ # Arguments +src+ and +dest+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Both of +src+ and +dest+ must be a path name.
- # +src+ must exist, +dest+ must not exist.
+ # If +src+ is the path to a file and +dest+ does not exist,
+ # creates a hard link at +dest+ pointing to +src+:
#
- # If +dereference_root+ is true, this method dereferences the tree root.
+ # Bundler::FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # Bundler::FileUtils.link_entry('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
#
- # If +remove_destination+ is true, this method removes each destination file before copy.
+ # If +src+ is the path to a directory and +dest+ does not exist,
+ # recursively creates hard links at +dest+ pointing to paths in +src+:
+ #
+ # Bundler::FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
+ # src_file_paths = [
+ # 'src1/dir0/t0.txt',
+ # 'src1/dir0/t1.txt',
+ # 'src1/dir1/t2.txt',
+ # 'src1/dir1/t3.txt',
+ # ]
+ # Bundler::FileUtils.touch(src_file_paths)
+ # File.directory?('dest1') # => true
+ # Bundler::FileUtils.link_entry('src1', 'dest1')
+ # File.file?('dest1/dir0/t0.txt') # => true
+ # File.file?('dest1/dir0/t1.txt') # => true
+ # File.file?('dest1/dir1/t2.txt') # => true
+ # File.file?('dest1/dir1/t3.txt') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: true</tt> - dereferences +src+ if it is a symbolic link.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
+ #
+ # Raises an exception if +dest+ is the path to an existing file or directory
+ # and keyword argument <tt>remove_destination: true</tt> is not given.
+ #
+ # Related: Bundler::FileUtils.ln (has different options).
#
def link_entry(src, dest, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).traverse do |ent|
@@ -412,16 +826,59 @@ module Bundler::FileUtils
end
module_function :link_entry
+ # Copies files.
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ is the path to a file and +dest+ is not the path to a directory,
+ # copies +src+ to +dest+:
+ #
+ # Bundler::FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # Bundler::FileUtils.cp('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
#
- # Copies a file content +src+ to +dest+. If +dest+ is a directory,
- # copies +src+ to +dest/src+.
+ # If +src+ is the path to a file and +dest+ is the path to a directory,
+ # copies +src+ to <tt>dest/src</tt>:
#
- # If +src+ is a list of files, then +dest+ must be a directory.
+ # Bundler::FileUtils.touch('src1.txt')
+ # Bundler::FileUtils.mkdir('dest1')
+ # Bundler::FileUtils.cp('src1.txt', 'dest1')
+ # File.file?('dest1/src1.txt') # => true
#
- # Bundler::FileUtils.cp 'eval.c', 'eval.c.org'
- # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
- # Bundler::FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true
- # Bundler::FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink
+ # If +src+ is an array of paths to files and +dest+ is the path to a directory,
+ # copies from each +src+ to +dest+:
+ #
+ # src_file_paths = ['src2.txt', 'src2.dat']
+ # Bundler::FileUtils.touch(src_file_paths)
+ # Bundler::FileUtils.mkdir('dest2')
+ # Bundler::FileUtils.cp(src_file_paths, 'dest2')
+ # File.file?('dest2/src2.txt') # => true
+ # File.file?('dest2/src2.dat') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>noop: true</tt> - does not copy files.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true)
+ # Bundler::FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # cp src0.txt dest0.txt
+ # cp src1.txt dest1
+ # cp src2.txt src2.dat dest2
+ #
+ # Raises an exception if +src+ is a directory.
+ #
+ # Bundler::FileUtils.copy is an alias for Bundler::FileUtils.cp.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -435,30 +892,105 @@ module Bundler::FileUtils
alias copy cp
module_function :copy
- #
- # Copies +src+ to +dest+. If +src+ is a directory, this method copies
- # all its contents recursively. If +dest+ is a directory, copies
- # +src+ to +dest/src+.
- #
- # +src+ can be a list of files.
- #
- # If +dereference_root+ is true, this method dereference tree root.
- #
- # If +remove_destination+ is true, this method removes each destination file before copy.
- #
- # # Installing Ruby library "mylib" under the site_ruby
- # Bundler::FileUtils.rm_r site_ruby + '/mylib', force: true
- # Bundler::FileUtils.cp_r 'lib/', site_ruby + '/mylib'
- #
- # # Examples of copying several files to target directory.
- # Bundler::FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
- # Bundler::FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', noop: true, verbose: true
- #
- # # If you want to copy all contents of a directory instead of the
- # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
- # # use following code.
- # Bundler::FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src,
- # # but this doesn't.
+ # Recursively copies files.
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # The mode, owner, and group are retained in the copy;
+ # to change those, use Bundler::FileUtils.install instead.
+ #
+ # If +src+ is the path to a file and +dest+ is not the path to a directory,
+ # copies +src+ to +dest+:
+ #
+ # Bundler::FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # Bundler::FileUtils.cp_r('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
+ #
+ # If +src+ is the path to a file and +dest+ is the path to a directory,
+ # copies +src+ to <tt>dest/src</tt>:
+ #
+ # Bundler::FileUtils.touch('src1.txt')
+ # Bundler::FileUtils.mkdir('dest1')
+ # Bundler::FileUtils.cp_r('src1.txt', 'dest1')
+ # File.file?('dest1/src1.txt') # => true
+ #
+ # If +src+ is the path to a directory and +dest+ does not exist,
+ # recursively copies +src+ to +dest+:
+ #
+ # tree('src2')
+ # # => src2
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # Bundler::FileUtils.exist?('dest2') # => false
+ # Bundler::FileUtils.cp_r('src2', 'dest2')
+ # tree('dest2')
+ # # => dest2
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ and +dest+ are paths to directories,
+ # recursively copies +src+ to <tt>dest/src</tt>:
+ #
+ # tree('src3')
+ # # => src3
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # Bundler::FileUtils.mkdir('dest3')
+ # Bundler::FileUtils.cp_r('src3', 'dest3')
+ # tree('dest3')
+ # # => dest3
+ # # `-- src3
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ is an array of paths and +dest+ is a directory,
+ # recursively copies from each path in +src+ to +dest+;
+ # the paths in +src+ may point to files and/or directories.
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
+ # does not dereference it.
+ # - <tt>noop: true</tt> - does not copy files.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true)
+ # Bundler::FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true)
+ # Bundler::FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # cp -r src0.txt dest0.txt
+ # cp -r src1.txt dest1
+ # cp -r src2 dest2
+ # cp -r src3 dest3
+ #
+ # Raises an exception of +src+ is the path to a directory
+ # and +dest+ is the path to a file.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil,
dereference_root: true, remove_destination: nil)
@@ -470,21 +1002,50 @@ module Bundler::FileUtils
end
module_function :cp_r
+ # Recursively copies files from +src+ to +dest+.
+ #
+ # Arguments +src+ and +dest+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Copies a file system entry +src+ to +dest+.
- # If +src+ is a directory, this method copies its contents recursively.
- # This method preserves file types, c.f. symlink, directory...
- # (FIFO, device files and etc. are not supported yet)
+ # If +src+ is the path to a file, copies +src+ to +dest+:
#
- # Both of +src+ and +dest+ must be a path name.
- # +src+ must exist, +dest+ must not exist.
+ # Bundler::FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # Bundler::FileUtils.copy_entry('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
#
- # If +preserve+ is true, this method preserves owner, group, and
- # modified time. Permissions are copied regardless +preserve+.
+ # If +src+ is a directory, recursively copies +src+ to +dest+:
#
- # If +dereference_root+ is true, this method dereference tree root.
+ # tree('src1')
+ # # => src1
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # Bundler::FileUtils.copy_entry('src1', 'dest1')
+ # tree('dest1')
+ # # => dest1
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
#
- # If +remove_destination+ is true, this method removes each destination file before copy.
+ # The recursive copying preserves file types for regular files,
+ # directories, and symbolic links;
+ # other file types (FIFO streams, device files, etc.) are not supported.
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: true</tt> - if +src+ is a symbolic link,
+ # follows the link.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
if dereference_root
@@ -502,9 +1063,25 @@ module Bundler::FileUtils
end
module_function :copy_entry
+ # Copies file from +src+ to +dest+, which should not be directories.
+ #
+ # Arguments +src+ and +dest+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Examples:
#
- # Copies file contents of +src+ to +dest+.
- # Both of +src+ and +dest+ must be a path name.
+ # Bundler::FileUtils.touch('src0.txt')
+ # Bundler::FileUtils.copy_file('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference: false</tt> - if +src+ is a symbolic link,
+ # does not follow the link.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def copy_file(src, dest, preserve = false, dereference = true)
ent = Entry_.new(src, nil, dereference)
@@ -513,25 +1090,81 @@ module Bundler::FileUtils
end
module_function :copy_file
+ # Copies \IO stream +src+ to \IO stream +dest+ via
+ # {IO.copy_stream}[rdoc-ref:IO.copy_stream].
#
- # Copies stream +src+ to +dest+.
- # +src+ must respond to #read(n) and
- # +dest+ must respond to #write(str).
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def copy_stream(src, dest)
IO.copy_stream(src, dest)
end
module_function :copy_stream
- #
- # Moves file(s) +src+ to +dest+. If +file+ and +dest+ exist on the different
- # disk partition, the file is copied then the original file is removed.
- #
- # Bundler::FileUtils.mv 'badname.rb', 'goodname.rb'
- # Bundler::FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', force: true # no error
- #
- # Bundler::FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/'
- # Bundler::FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true
+ # Moves entries.
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ and +dest+ are on different file systems,
+ # first copies, then removes +src+.
+ #
+ # May cause a local vulnerability if not called with keyword argument
+ # <tt>secure: true</tt>;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
+ #
+ # If +src+ is the path to a single file or directory and +dest+ does not exist,
+ # moves +src+ to +dest+:
+ #
+ # tree('src0')
+ # # => src0
+ # # |-- src0.txt
+ # # `-- src1.txt
+ # File.exist?('dest0') # => false
+ # Bundler::FileUtils.mv('src0', 'dest0')
+ # File.exist?('src0') # => false
+ # tree('dest0')
+ # # => dest0
+ # # |-- src0.txt
+ # # `-- src1.txt
+ #
+ # If +src+ is an array of paths to files and directories
+ # and +dest+ is the path to a directory,
+ # copies from each path in the array to +dest+:
+ #
+ # File.file?('src1.txt') # => true
+ # tree('src1')
+ # # => src1
+ # # |-- src.dat
+ # # `-- src.txt
+ # Dir.empty?('dest1') # => true
+ # Bundler::FileUtils.mv(['src1.txt', 'src1'], 'dest1')
+ # tree('dest1')
+ # # => dest1
+ # # |-- src1
+ # # | |-- src.dat
+ # # | `-- src.txt
+ # # `-- src1.txt
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - if the move includes removing +src+
+ # (that is, if +src+ and +dest+ are on different file systems),
+ # ignores raised exceptions of StandardError and its descendants.
+ # - <tt>noop: true</tt> - does not move files.
+ # - <tt>secure: true</tt> - removes +src+ securely;
+ # see details at Bundler::FileUtils.remove_entry_secure.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.mv('src0', 'dest0', noop: true, verbose: true)
+ # Bundler::FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # mv src0 dest0
+ # mv src1.txt src1 dest1
+ #
+ # Bundler::FileUtils.move is an alias for Bundler::FileUtils.mv.
#
def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -565,13 +1198,34 @@ module Bundler::FileUtils
alias move mv
module_function :move
+ # Removes entries at the paths in the given +list+
+ # (a single path or an array of paths)
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, removes files at the paths given in +list+:
+ #
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
+ # Bundler::FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - ignores raised exceptions of StandardError
+ # and its descendants.
+ # - <tt>noop: true</tt> - does not remove files; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
#
- # Remove file(s) specified in +list+. This method cannot remove directories.
- # All StandardErrors are ignored when the :force option is set.
+ # Output:
#
- # Bundler::FileUtils.rm %w( junk.txt dust.txt )
- # Bundler::FileUtils.rm Dir.glob('*.so')
- # Bundler::FileUtils.rm 'NotExistFile', force: true # never raises exception
+ # rm src0.dat src0.txt
+ #
+ # Bundler::FileUtils.remove is an alias for Bundler::FileUtils.rm.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm(list, force: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -587,10 +1241,18 @@ module Bundler::FileUtils
alias remove rm
module_function :remove
+ # Equivalent to:
+ #
+ # Bundler::FileUtils.rm(list, force: true, **kwargs)
+ #
+ # Argument +list+ (a single path or an array of paths)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # See Bundler::FileUtils.rm for keyword arguments.
#
- # Equivalent to
+ # Bundler::FileUtils.safe_unlink is an alias for Bundler::FileUtils.rm_f.
#
- # Bundler::FileUtils.rm(list, force: true)
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_f(list, noop: nil, verbose: nil)
rm list, force: true, noop: noop, verbose: verbose
@@ -600,24 +1262,55 @@ module Bundler::FileUtils
alias safe_unlink rm_f
module_function :safe_unlink
+ # Removes entries at the paths in the given +list+
+ # (a single path or an array of paths);
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # May cause a local vulnerability if not called with keyword argument
+ # <tt>secure: true</tt>;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
+ #
+ # For each file path, removes the file at that path:
+ #
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
+ # Bundler::FileUtils.rm_r(['src0.dat', 'src0.txt'])
+ # File.exist?('src0.txt') # => false
+ # File.exist?('src0.dat') # => false
#
- # remove files +list+[0] +list+[1]... If +list+[n] is a directory,
- # removes its all contents recursively. This method ignores
- # StandardError when :force option is set.
+ # For each directory path, recursively removes files and directories:
#
- # Bundler::FileUtils.rm_r Dir.glob('/tmp/*')
- # Bundler::FileUtils.rm_r 'some_dir', force: true
+ # tree('src1')
+ # # => src1
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # Bundler::FileUtils.rm_r('src1')
+ # File.exist?('src1') # => false
#
- # WARNING: This method causes local vulnerability
- # if one of parent directories or removing directory tree are world
- # writable (including /tmp, whose permission is 1777), and the current
- # process has strong privilege such as Unix super user (root), and the
- # system has symbolic link. For secure removing, read the documentation
- # of remove_entry_secure carefully, and set :secure option to true.
- # Default is <tt>secure: false</tt>.
+ # Keyword arguments:
#
- # NOTE: This method calls remove_entry_secure if :secure option is set.
- # See also remove_entry_secure.
+ # - <tt>force: true</tt> - ignores raised exceptions of StandardError
+ # and its descendants.
+ # - <tt>noop: true</tt> - does not remove entries; returns +nil+.
+ # - <tt>secure: true</tt> - removes +src+ securely;
+ # see details at Bundler::FileUtils.remove_entry_secure.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true)
+ # Bundler::FileUtils.rm_r('src1', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # rm -r src0.dat src0.txt
+ # rm -r src1
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
list = fu_list(list)
@@ -633,13 +1326,22 @@ module Bundler::FileUtils
end
module_function :rm_r
+ # Equivalent to:
#
- # Equivalent to
+ # Bundler::FileUtils.rm_r(list, force: true, **kwargs)
#
- # Bundler::FileUtils.rm_r(list, force: true)
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # WARNING: This method causes local vulnerability.
- # Read the documentation of rm_r first.
+ # May cause a local vulnerability if not called with keyword argument
+ # <tt>secure: true</tt>;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
+ #
+ # See Bundler::FileUtils.rm_r for keyword arguments.
+ #
+ # Bundler::FileUtils.rmtree is an alias for Bundler::FileUtils.rm_rf.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_rf(list, noop: nil, verbose: nil, secure: nil)
rm_r list, force: true, noop: noop, verbose: verbose, secure: secure
@@ -649,37 +1351,20 @@ module Bundler::FileUtils
alias rmtree rm_rf
module_function :rmtree
+ # Securely removes the entry given by +path+,
+ # which should be the entry for a regular file, a symbolic link,
+ # or a directory.
#
- # This method removes a file system entry +path+. +path+ shall be a
- # regular file, a directory, or something. If +path+ is a directory,
- # remove it recursively. This method is required to avoid TOCTTOU
- # (time-of-check-to-time-of-use) local security vulnerability of rm_r.
- # #rm_r causes security hole when:
- #
- # * Parent directory is world writable (including /tmp).
- # * Removing directory tree includes world writable directory.
- # * The system has symbolic link.
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # To avoid this security hole, this method applies special preprocess.
- # If +path+ is a directory, this method chown(2) and chmod(2) all
- # removing directories. This requires the current process is the
- # owner of the removing whole directory tree, or is the super user (root).
+ # Avoids a local vulnerability that can exist in certain circumstances;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
#
- # WARNING: You must ensure that *ALL* parent directories cannot be
- # moved by other untrusted users. For example, parent directories
- # should not be owned by untrusted users, and should not be world
- # writable except when the sticky bit set.
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
#
- # WARNING: Only the owner of the removing directory tree, or Unix super
- # user (root) should invoke this method. Otherwise this method does not
- # work.
- #
- # For details of this security vulnerability, see Perl's case:
- #
- # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
- # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
- #
- # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_entry_secure(path, force = false)
unless fu_have_symlink?
@@ -767,12 +1452,17 @@ module Bundler::FileUtils
end
private_module_function :fu_stat_identical_entry?
+ # Removes the entry given by +path+,
+ # which should be the entry for a regular file, a symbolic link,
+ # or a directory.
#
- # This method removes a file system entry +path+.
- # +path+ might be a regular file, a directory, or something.
- # If +path+ is a directory, remove it recursively.
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # See also remove_entry_secure.
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
+ #
+ # Related: Bundler::FileUtils.remove_entry_secure.
#
def remove_entry(path, force = false)
Entry_.new(path).postorder_traverse do |ent|
@@ -787,9 +1477,16 @@ module Bundler::FileUtils
end
module_function :remove_entry
+ # Removes the file entry given by +path+,
+ # which should be the entry for a regular file or a symbolic link.
+ #
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Removes a file +path+.
- # This method ignores StandardError if +force+ is true.
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_file(path, force = false)
Entry_.new(path).remove_file
@@ -798,20 +1495,32 @@ module Bundler::FileUtils
end
module_function :remove_file
+ # Recursively removes the directory entry given by +path+,
+ # which should be the entry for a regular file, a symbolic link,
+ # or a directory.
+ #
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Removes a directory +dir+ and its contents recursively.
- # This method ignores StandardError if +force+ is true.
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_dir(path, force = false)
remove_entry path, force # FIXME?? check if it is a directory
end
module_function :remove_dir
+ # Returns +true+ if the contents of files +a+ and +b+ are identical,
+ # +false+ otherwise.
+ #
+ # Arguments +a+ and +b+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Returns true if the contents of a file +a+ and a file +b+ are identical.
+ # Bundler::FileUtils.identical? and Bundler::FileUtils.cmp are aliases for Bundler::FileUtils.compare_file.
#
- # Bundler::FileUtils.compare_file('somefile', 'somefile') #=> true
- # Bundler::FileUtils.compare_file('/dev/null', '/dev/urandom') #=> false
+ # Related: Bundler::FileUtils.compare_stream.
#
def compare_file(a, b)
return false unless File.size(a) == File.size(b)
@@ -828,19 +1537,19 @@ module Bundler::FileUtils
module_function :identical?
module_function :cmp
+ # Returns +true+ if the contents of streams +a+ and +b+ are identical,
+ # +false+ otherwise.
#
- # Returns true if the contents of a stream +a+ and +b+ are identical.
+ # Arguments +a+ and +b+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Related: Bundler::FileUtils.compare_file.
#
def compare_stream(a, b)
bsize = fu_stream_blksize(a, b)
- if RUBY_VERSION > "2.4"
- sa = String.new(capacity: bsize)
- sb = String.new(capacity: bsize)
- else
- sa = String.new
- sb = String.new
- end
+ sa = String.new(capacity: bsize)
+ sb = String.new(capacity: bsize)
begin
a.read(bsize, sa)
@@ -851,13 +1560,69 @@ module Bundler::FileUtils
end
module_function :compare_stream
+ # Copies a file entry.
+ # See {install(1)}[https://man7.org/linux/man-pages/man1/install.1.html].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments];
+ #
+ # If the entry at +dest+ does not exist, copies from +src+ to +dest+:
+ #
+ # File.read('src0.txt') # => "aaa\n"
+ # File.exist?('dest0.txt') # => false
+ # Bundler::FileUtils.install('src0.txt', 'dest0.txt')
+ # File.read('dest0.txt') # => "aaa\n"
+ #
+ # If +dest+ is a file entry, copies from +src+ to +dest+, overwriting:
+ #
+ # File.read('src1.txt') # => "aaa\n"
+ # File.read('dest1.txt') # => "bbb\n"
+ # Bundler::FileUtils.install('src1.txt', 'dest1.txt')
+ # File.read('dest1.txt') # => "aaa\n"
#
- # If +src+ is not same as +dest+, copies it and changes the permission
- # mode to +mode+. If +dest+ is a directory, destination is +dest+/+src+.
- # This method removes destination before copy.
+ # If +dest+ is a directory entry, copies from +src+ to <tt>dest/src</tt>,
+ # overwriting if necessary:
#
- # Bundler::FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true
- # Bundler::FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true
+ # File.read('src2.txt') # => "aaa\n"
+ # File.read('dest2/src2.txt') # => "bbb\n"
+ # Bundler::FileUtils.install('src2.txt', 'dest2')
+ # File.read('dest2/src2.txt') # => "aaa\n"
+ #
+ # If +src+ is an array of paths and +dest+ points to a directory,
+ # copies each path +path+ in +src+ to <tt>dest/path</tt>:
+ #
+ # File.file?('src3.txt') # => true
+ # File.file?('src3.dat') # => true
+ # Bundler::FileUtils.mkdir('dest3')
+ # Bundler::FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
+ # File.file?('dest3/src3.txt') # => true
+ # File.file?('dest3/src3.dat') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>group: <i>group</i></tt> - changes the group if not +nil+,
+ # using {File.chown}[rdoc-ref:File.chown].
+ # - <tt>mode: <i>permissions</i></tt> - changes the permissions.
+ # using {File.chmod}[rdoc-ref:File.chmod].
+ # - <tt>noop: true</tt> - does not copy entries; returns +nil+.
+ # - <tt>owner: <i>owner</i></tt> - changes the owner if not +nil+,
+ # using {File.chown}[rdoc-ref:File.chown].
+ # - <tt>preserve: true</tt> - preserve timestamps
+ # using {File.utime}[rdoc-ref:File.utime].
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # install -c src0.txt dest0.txt
+ # install -c src1.txt dest1.txt
+ # install -c src2.txt dest2
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
noop: nil, verbose: nil)
@@ -917,11 +1682,8 @@ module Bundler::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 +1700,7 @@ module Bundler::FileUtils
when "x"
mask | 0111
when "X"
- if FileTest.directory? path
+ if path.directory?
mask | 0111
else
mask
@@ -978,37 +1740,78 @@ module Bundler::FileUtils
end
private_module_function :mode_to_s
+ # Changes permissions on the entries at the paths given in +list+
+ # (a single path or an array of paths)
+ # to the permissions given by +mode+;
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise:
+ #
+ # - Modifies each entry that is a regular file using
+ # {File.chmod}[rdoc-ref:File.chmod].
+ # - Modifies each entry that is a symbolic link using
+ # {File.lchmod}[rdoc-ref:File.lchmod].
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Argument +mode+ may be either an integer or a string:
+ #
+ # - \Integer +mode+: represents the permission bits to be set:
+ #
+ # Bundler::FileUtils.chmod(0755, 'src0.txt')
+ # Bundler::FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
+ #
+ # - \String +mode+: represents the permissions to be set:
+ #
+ # The string is of the form <tt>[targets][[operator][perms[,perms]]</tt>, where:
+ #
+ # - +targets+ may be any combination of these letters:
+ #
+ # - <tt>'u'</tt>: permissions apply to the file's owner.
+ # - <tt>'g'</tt>: permissions apply to users in the file's group.
+ # - <tt>'o'</tt>: permissions apply to other users not in the file's group.
+ # - <tt>'a'</tt> (the default): permissions apply to all users.
+ #
+ # - +operator+ may be one of these letters:
+ #
+ # - <tt>'+'</tt>: adds permissions.
+ # - <tt>'-'</tt>: removes permissions.
+ # - <tt>'='</tt>: sets (replaces) permissions.
+ #
+ # - +perms+ (may be repeated, with separating commas)
+ # may be any combination of these letters:
+ #
+ # - <tt>'r'</tt>: Read.
+ # - <tt>'w'</tt>: Write.
+ # - <tt>'x'</tt>: Execute (search, for a directory).
+ # - <tt>'X'</tt>: Search (for a directories only;
+ # must be used with <tt>'+'</tt>)
+ # - <tt>'s'</tt>: Uid or gid.
+ # - <tt>'t'</tt>: Sticky bit.
+ #
+ # Examples:
+ #
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', 'src1.txt')
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby')
+ #
+ # Keyword arguments:
+ #
+ # - <tt>noop: true</tt> - does not change permissions; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # chmod 755 src0.txt
+ # chmod 644 src0.txt src0.dat
+ # chmod u=wrx,go=rx src1.txt
+ # chmod u=wrx,go=rx /usr/bin/ruby
+ #
+ # Related: Bundler::FileUtils.chmod_R.
#
- # Changes permission bits on the named files (in +list+) to the bit pattern
- # represented by +mode+.
- #
- # +mode+ is the symbolic and absolute mode can be used.
- #
- # Absolute mode is
- # Bundler::FileUtils.chmod 0755, 'somecommand'
- # Bundler::FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
- # Bundler::FileUtils.chmod 0755, '/usr/bin/ruby', verbose: true
- #
- # Symbolic mode is
- # Bundler::FileUtils.chmod "u=wrx,go=rx", 'somecommand'
- # Bundler::FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
- # Bundler::FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', verbose: true
- #
- # "a" :: is user, group, other mask.
- # "u" :: is user's mask.
- # "g" :: is group's mask.
- # "o" :: is other's mask.
- # "w" :: is write permission.
- # "r" :: is read permission.
- # "x" :: is execute permission.
- # "X" ::
- # is execute permission for directories only, must be used in conjunction with "+"
- # "s" :: is uid, gid.
- # "t" :: is sticky bit.
- # "+" :: is added to a class given the specified mode.
- # "-" :: Is removed from a given class given mode.
- # "=" :: Is the exact nature of the class will be given a specified mode.
-
def chmod(mode, list, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose
@@ -1019,12 +1822,7 @@ module Bundler::FileUtils
end
module_function :chmod
- #
- # Changes permission bits on the named files (in +list+)
- # to the bit pattern represented by +mode+.
- #
- # Bundler::FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
- # Bundler::FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}"
+ # Like Bundler::FileUtils.chmod, but changes permissions recursively.
#
def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
@@ -1044,15 +1842,68 @@ module Bundler::FileUtils
end
module_function :chmod_R
+ # Changes the owner and group on the entries at the paths given in +list+
+ # (a single path or an array of paths)
+ # to the given +user+ and +group+;
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise:
+ #
+ # - Modifies each entry that is a regular file using
+ # {File.chown}[rdoc-ref:File.chown].
+ # - Modifies each entry that is a symbolic link using
+ # {File.lchown}[rdoc-ref:File.lchown].
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Changes owner and group on the named files (in +list+)
- # to the user +user+ and the group +group+. +user+ and +group+
- # may be an ID (Integer/String) or a name (String).
- # If +user+ or +group+ is nil, this method does not change
- # the attribute.
+ # User and group:
#
- # Bundler::FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
- # Bundler::FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true
+ # - Argument +user+ may be a user name or a user id;
+ # if +nil+ or +-1+, the user is not changed.
+ # - Argument +group+ may be a group name or a group id;
+ # if +nil+ or +-1+, the group is not changed.
+ # - The user must be a member of the group.
+ #
+ # Examples:
+ #
+ # # One path.
+ # # User and group as string names.
+ # File.stat('src0.txt').uid # => 1004
+ # File.stat('src0.txt').gid # => 1004
+ # Bundler::FileUtils.chown('user2', 'group1', 'src0.txt')
+ # File.stat('src0.txt').uid # => 1006
+ # File.stat('src0.txt').gid # => 1005
+ #
+ # # User and group as uid and gid.
+ # Bundler::FileUtils.chown(1004, 1004, 'src0.txt')
+ # File.stat('src0.txt').uid # => 1004
+ # File.stat('src0.txt').gid # => 1004
+ #
+ # # Array of paths.
+ # Bundler::FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
+ #
+ # # Directory (not recursive).
+ # Bundler::FileUtils.chown('user2', 'group1', '.')
+ #
+ # Keyword arguments:
+ #
+ # - <tt>noop: true</tt> - does not change permissions; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
+ # Bundler::FileUtils.chown('user2', 'group1', path, noop: true, verbose: true)
+ # Bundler::FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # chown user2:group1 src0.txt
+ # chown 1004:1004 src0.txt
+ # chown 1006:1005 src0.txt src0.dat
+ # chown user2:group1 src0.txt
+ # chown user2:group1 .
+ #
+ # Related: Bundler::FileUtils.chown_R.
#
def chown(user, group, list, noop: nil, verbose: nil)
list = fu_list(list)
@@ -1068,15 +1919,7 @@ module Bundler::FileUtils
end
module_function :chown
- #
- # Changes owner and group on the named files (in +list+)
- # to the user +user+ and the group +group+ recursively.
- # +user+ and +group+ may be an ID (Integer/String) or
- # a name (String). If +user+ or +group+ is nil, this
- # method does not change the attribute.
- #
- # Bundler::FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
- # Bundler::FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true
+ # Like Bundler::FileUtils.chown, but changes owner and group recursively.
#
def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
@@ -1127,12 +1970,50 @@ module Bundler::FileUtils
end
private_module_function :fu_get_gid
+ # Updates modification times (mtime) and access times (atime)
+ # of the entries given by the paths in +list+
+ # (a single path or an array of paths);
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # By default, creates an empty file for any path to a non-existent entry;
+ # use keyword argument +nocreate+ to raise an exception instead.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Examples:
+ #
+ # # Single path.
+ # f = File.new('src0.txt') # Existing file.
+ # f.atime # => 2022-06-10 11:11:21.200277 -0700
+ # f.mtime # => 2022-06-10 11:11:21.200277 -0700
+ # Bundler::FileUtils.touch('src0.txt')
+ # f = File.new('src0.txt')
+ # f.atime # => 2022-06-11 08:28:09.8185343 -0700
+ # f.mtime # => 2022-06-11 08:28:09.8185343 -0700
#
- # Updates modification time (mtime) and access time (atime) of file(s) in
- # +list+. Files are created if they don't exist.
+ # # Array of paths.
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'])
#
- # Bundler::FileUtils.touch 'timestamp'
- # Bundler::FileUtils.touch Dir.glob('*.c'); system 'make'
+ # Keyword arguments:
+ #
+ # - <tt>mtime: <i>time</i></tt> - sets the entry's mtime to the given time,
+ # instead of the current time.
+ # - <tt>nocreate: true</tt> - raises an exception if the entry does not exist.
+ # - <tt>noop: true</tt> - does not touch entries; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # Bundler::FileUtils.touch('src0.txt', noop: true, verbose: true)
+ # Bundler::FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true)
+ # Bundler::FileUtils.touch(path, noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # touch src0.txt
+ # touch src0.txt src0.dat
+ # touch src0.txt
+ #
+ # Related: Bundler::FileUtils.uptodate?.
#
def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
list = fu_list(list)
@@ -1290,14 +2171,9 @@ module Bundler::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)
- else
- Dir.entries(path(), **opts)
- .reject {|n| n == '.' or n == '..' }
- end
+ files = Dir.children(path, **opts)
untaint = RUBY_VERSION < '2.7'
files.map {|n| Entry_.new(prefix(), join(rel(), untaint ? n.untaint : n)) }
@@ -1345,6 +2221,7 @@ module Bundler::FileUtils
else
File.chmod mode, path()
end
+ rescue Errno::EOPNOTSUPP
end
def chown(uid, gid)
@@ -1439,7 +2316,7 @@ module Bundler::FileUtils
if st.symlink?
begin
File.lchmod mode, path
- rescue NotImplementedError
+ rescue NotImplementedError, Errno::EOPNOTSUPP
end
else
File.chmod mode, path
@@ -1498,13 +2375,21 @@ module Bundler::FileUtils
def postorder_traverse
if directory?
- entries().each do |ent|
+ begin
+ children = entries()
+ rescue Errno::EACCES
+ # Failed to get the list of children.
+ # Assuming there is no children, try to process the parent directory.
+ yield self
+ return
+ end
+
+ children.each do |ent|
ent.postorder_traverse do |e|
yield e
end
end
end
- ensure
yield self
end
@@ -1559,7 +2444,15 @@ module Bundler::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
@@ -1590,15 +2483,15 @@ module Bundler::FileUtils
end
private_module_function :fu_each_src_dest
- def fu_each_src_dest0(src, dest) #:nodoc:
+ def fu_each_src_dest0(src, dest, target_directory = true) #:nodoc:
if tmp = Array.try_convert(src)
tmp.each do |s|
s = File.path(s)
- yield s, File.join(dest, File.basename(s))
+ yield s, (target_directory ? File.join(dest, File.basename(s)) : dest)
end
else
src = File.path(src)
- if File.directory?(dest)
+ if target_directory and File.directory?(dest)
yield src, File.join(dest, File.basename(src))
else
yield src, File.path(dest)
@@ -1614,7 +2507,7 @@ module Bundler::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
@@ -1622,6 +2515,56 @@ module Bundler::FileUtils
end
private_module_function :fu_output_message
+ def fu_split_path(path)
+ path = File.path(path)
+ list = []
+ until (parent, base = File.split(path); parent == path or parent == ".")
+ list << base
+ path = parent
+ end
+ list << path
+ list.reverse!
+ end
+ private_module_function :fu_split_path
+
+ def fu_relative_components_from(target, base) #:nodoc:
+ i = 0
+ while target[i]&.== base[i]
+ i += 1
+ end
+ Array.new(base.size-i, '..').concat(target[i..-1])
+ end
+ private_module_function :fu_relative_components_from
+
+ def fu_clean_components(*comp)
+ comp.shift while comp.first == "."
+ return comp if comp.empty?
+ clean = [comp.shift]
+ path = File.join(*clean, "") # ending with File::SEPARATOR
+ while c = comp.shift
+ if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
+ clean.pop
+ path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
+ else
+ clean << c
+ path << c << "/"
+ end
+ end
+ clean
+ end
+ private_module_function :fu_clean_components
+
+ if fu_windows?
+ def fu_starting_path?(path)
+ path&.start_with?(%r(\w:|/))
+ end
+ else
+ def fu_starting_path?(path)
+ path&.start_with?("/")
+ end
+ end
+ private_module_function :fu_starting_path?
+
# This hash table holds command options.
OPT_TABLE = {} #:nodoc: internal use only
(private_instance_methods & methods(false)).inject(OPT_TABLE) {|tbl, name|
@@ -1631,50 +2574,49 @@ module Bundler::FileUtils
public
+ # Returns an array of the string names of \Bundler::FileUtils methods
+ # that accept one or more keyword arguments:
#
- # Returns an Array of names of high-level methods that accept any keyword
- # arguments.
- #
- # p Bundler::FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...]
+ # Bundler::FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]
#
def self.commands
OPT_TABLE.keys
end
+ # Returns an array of the string keyword names:
#
- # Returns an Array of option names.
- #
- # p Bundler::FileUtils.options #=> ["noop", "force", "verbose", "preserve", "mode"]
+ # Bundler::FileUtils.options.take(3) # => ["noop", "verbose", "force"]
#
def self.options
OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
end
+ # Returns +true+ if method +mid+ accepts the given option +opt+, +false+ otherwise;
+ # the arguments may be strings or symbols:
#
- # Returns true if the method +mid+ have an option +opt+.
- #
- # p Bundler::FileUtils.have_option?(:cp, :noop) #=> true
- # p Bundler::FileUtils.have_option?(:rm, :force) #=> true
- # p Bundler::FileUtils.have_option?(:rm, :preserve) #=> false
+ # Bundler::FileUtils.have_option?(:chmod, :noop) # => true
+ # Bundler::FileUtils.have_option?('chmod', 'secure') # => false
#
def self.have_option?(mid, opt)
li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}"
li.include?(opt)
end
+ # Returns an array of the string keyword name for method +mid+;
+ # the argument may be a string or a symbol:
#
- # Returns an Array of option names of the method +mid+.
- #
- # p Bundler::FileUtils.options_of(:rm) #=> ["noop", "verbose", "force"]
+ # Bundler::FileUtils.options_of(:rm) # => ["force", "noop", "verbose"]
+ # Bundler::FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]
#
def self.options_of(mid)
OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
end
+ # Returns an array of the string method names of the methods
+ # that accept the given keyword option +opt+;
+ # the argument must be a symbol:
#
- # Returns an Array of methods names which have the option +opt+.
- #
- # p Bundler::FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"]
+ # Bundler::FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]
#
def self.collect_method(opt)
OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo.rb b/lib/bundler/vendor/molinillo/lib/molinillo.rb
deleted file mode 100644
index a52b96deaf..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'molinillo/gem_metadata'
-require_relative 'molinillo/errors'
-require_relative 'molinillo/resolver'
-require_relative 'molinillo/modules/ui'
-require_relative 'molinillo/modules/specification_provider'
-
-# Bundler::Molinillo is a generic dependency resolution algorithm.
-module Bundler::Molinillo
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb
deleted file mode 100644
index bcacf35243..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # @!visibility private
- module Delegates
- # Delegates all {Bundler::Molinillo::ResolutionState} methods to a `#state` property.
- module ResolutionState
- # (see Bundler::Molinillo::ResolutionState#name)
- def name
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.name
- end
-
- # (see Bundler::Molinillo::ResolutionState#requirements)
- def requirements
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.requirements
- end
-
- # (see Bundler::Molinillo::ResolutionState#activated)
- def activated
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.activated
- end
-
- # (see Bundler::Molinillo::ResolutionState#requirement)
- def requirement
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.requirement
- end
-
- # (see Bundler::Molinillo::ResolutionState#possibilities)
- def possibilities
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.possibilities
- end
-
- # (see Bundler::Molinillo::ResolutionState#depth)
- def depth
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.depth
- end
-
- # (see Bundler::Molinillo::ResolutionState#conflicts)
- def conflicts
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.conflicts
- end
-
- # (see Bundler::Molinillo::ResolutionState#unused_unwind_options)
- def unused_unwind_options
- current_state = state || Bundler::Molinillo::ResolutionState.empty
- current_state.unused_unwind_options
- 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
deleted file mode 100644
index f8c695c1ed..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- module Delegates
- # Delegates all {Bundler::Molinillo::SpecificationProvider} methods to a
- # `#specification_provider` property.
- module SpecificationProvider
- # (see Bundler::Molinillo::SpecificationProvider#search_for)
- def search_for(dependency)
- with_no_such_dependency_error_handling do
- specification_provider.search_for(dependency)
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#dependencies_for)
- def dependencies_for(specification)
- with_no_such_dependency_error_handling do
- specification_provider.dependencies_for(specification)
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#requirement_satisfied_by?)
- def requirement_satisfied_by?(requirement, activated, spec)
- with_no_such_dependency_error_handling do
- specification_provider.requirement_satisfied_by?(requirement, activated, spec)
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#dependencies_equal?)
- def dependencies_equal?(dependencies, other_dependencies)
- with_no_such_dependency_error_handling do
- specification_provider.dependencies_equal?(dependencies, other_dependencies)
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#name_for)
- def name_for(dependency)
- with_no_such_dependency_error_handling do
- specification_provider.name_for(dependency)
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#name_for_explicit_dependency_source)
- def name_for_explicit_dependency_source
- with_no_such_dependency_error_handling do
- specification_provider.name_for_explicit_dependency_source
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#name_for_locking_dependency_source)
- def name_for_locking_dependency_source
- with_no_such_dependency_error_handling do
- specification_provider.name_for_locking_dependency_source
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#sort_dependencies)
- def sort_dependencies(dependencies, activated, conflicts)
- with_no_such_dependency_error_handling do
- specification_provider.sort_dependencies(dependencies, activated, conflicts)
- end
- end
-
- # (see Bundler::Molinillo::SpecificationProvider#allow_missing?)
- def allow_missing?(dependency)
- with_no_such_dependency_error_handling do
- specification_provider.allow_missing?(dependency)
- end
- end
-
- private
-
- # Ensures any raised {NoSuchDependencyError} has its
- # {NoSuchDependencyError#required_by} set.
- # @yield
- def with_no_such_dependency_error_handling
- yield
- rescue NoSuchDependencyError => error
- if state
- vertex = activated.vertex_named(name_for(error.dependency))
- error.required_by += vertex.incoming_edges.map { |e| e.origin.name }
- error.required_by << name_for_explicit_dependency_source unless vertex.explicit_requirements.empty?
- end
- raise
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
deleted file mode 100644
index 936399ed2f..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
+++ /dev/null
@@ -1,255 +0,0 @@
-# frozen_string_literal: true
-
-require 'tsort'
-
-require_relative 'dependency_graph/log'
-require_relative 'dependency_graph/vertex'
-
-module Bundler::Molinillo
- # A directed acyclic graph that is tuned to hold named dependencies
- class DependencyGraph
- include Enumerable
-
- # Enumerates through the vertices of the graph.
- # @return [Array<Vertex>] The graph's vertices.
- def each
- return vertices.values.each unless block_given?
- vertices.values.each { |v| yield v }
- end
-
- include TSort
-
- # @!visibility private
- alias tsort_each_node each
-
- # @!visibility private
- def tsort_each_child(vertex, &block)
- vertex.successors.each(&block)
- end
-
- # Topologically sorts the given vertices.
- # @param [Enumerable<Vertex>] vertices the vertices to be sorted, which must
- # all belong to the same graph.
- # @return [Array<Vertex>] The sorted vertices.
- def self.tsort(vertices)
- TSort.tsort(
- lambda { |b| vertices.each(&b) },
- lambda { |v, &b| (v.successors & vertices).each(&b) }
- )
- end
-
- # A directed edge of a {DependencyGraph}
- # @attr [Vertex] origin The origin of the directed edge
- # @attr [Vertex] destination The destination of the directed edge
- # @attr [Object] requirement The requirement the directed edge represents
- Edge = Struct.new(:origin, :destination, :requirement)
-
- # @return [{String => Vertex}] the vertices of the dependency graph, keyed
- # by {Vertex#name}
- attr_reader :vertices
-
- # @return [Log] the op log for this graph
- attr_reader :log
-
- # Initializes an empty dependency graph
- def initialize
- @vertices = {}
- @log = Log.new
- end
-
- # Tags the current state of the dependency as the given tag
- # @param [Object] tag an opaque tag for the current state of the graph
- # @return [Void]
- def tag(tag)
- log.tag(self, tag)
- end
-
- # Rewinds the graph to the state tagged as `tag`
- # @param [Object] tag the tag to rewind to
- # @return [Void]
- def rewind_to(tag)
- log.rewind_to(self, tag)
- end
-
- # Initializes a copy of a {DependencyGraph}, ensuring that all {#vertices}
- # are properly copied.
- # @param [DependencyGraph] other the graph to copy.
- def initialize_copy(other)
- super
- @vertices = {}
- @log = other.log.dup
- traverse = lambda do |new_v, old_v|
- return if new_v.outgoing_edges.size == old_v.outgoing_edges.size
- old_v.outgoing_edges.each do |edge|
- destination = add_vertex(edge.destination.name, edge.destination.payload)
- add_edge_no_circular(new_v, destination, edge.requirement)
- traverse.call(destination, edge.destination)
- end
- end
- other.vertices.each do |name, vertex|
- new_vertex = add_vertex(name, vertex.payload, vertex.root?)
- new_vertex.explicit_requirements.replace(vertex.explicit_requirements)
- traverse.call(new_vertex, vertex)
- end
- end
-
- # @return [String] a string suitable for debugging
- def inspect
- "#{self.class}:#{vertices.values.inspect}"
- end
-
- # @param [Hash] options options for dot output.
- # @return [String] Returns a dot format representation of the graph
- def to_dot(options = {})
- edge_label = options.delete(:edge_label)
- raise ArgumentError, "Unknown options: #{options.keys}" unless options.empty?
-
- dot_vertices = []
- dot_edges = []
- vertices.each do |n, v|
- dot_vertices << " #{n} [label=\"{#{n}|#{v.payload}}\"]"
- v.outgoing_edges.each do |e|
- label = edge_label ? edge_label.call(e) : e.requirement
- dot_edges << " #{e.origin.name} -> #{e.destination.name} [label=#{label.to_s.dump}]"
- end
- end
-
- dot_vertices.uniq!
- dot_vertices.sort!
- dot_edges.uniq!
- dot_edges.sort!
-
- dot = dot_vertices.unshift('digraph G {').push('') + dot_edges.push('}')
- 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}
- def ==(other)
- return false unless other
- return true if equal?(other)
- vertices.each do |name, vertex|
- other_vertex = other.vertex_named(name)
- return false unless other_vertex
- return false unless vertex.payload == other_vertex.payload
- return false unless other_vertex.successors.to_set == vertex.successors.to_set
- end
- end
-
- # @param [String] name
- # @param [Object] payload
- # @param [Array<String>] parent_names
- # @param [Object] requirement the requirement that is requiring the child
- # @return [void]
- def add_child_vertex(name, payload, parent_names, requirement)
- root = !parent_names.delete(nil) { true }
- vertex = add_vertex(name, payload, root)
- vertex.explicit_requirements << requirement if root
- parent_names.each do |parent_name|
- parent_vertex = vertex_named(parent_name)
- add_edge(parent_vertex, vertex, requirement)
- end
- vertex
- end
-
- # Adds a vertex with the given name, or updates the existing one.
- # @param [String] name
- # @param [Object] payload
- # @return [Vertex] the vertex that was added to `self`
- def add_vertex(name, payload, root = false)
- log.add_vertex(self, name, payload, root)
- end
-
- # Detaches the {#vertex_named} `name` {Vertex} from the graph, recursively
- # removing any non-root vertices that were orphaned in the process
- # @param [String] name
- # @return [Array<Vertex>] the vertices which have been detached
- def detach_vertex_named(name)
- log.detach_vertex_named(self, name)
- end
-
- # @param [String] name
- # @return [Vertex,nil] the vertex with the given name
- def vertex_named(name)
- vertices[name]
- end
-
- # @param [String] name
- # @return [Vertex,nil] the root vertex with the given name
- def root_vertex_named(name)
- vertex = vertex_named(name)
- vertex if vertex && vertex.root?
- end
-
- # Adds a new {Edge} to the dependency graph
- # @param [Vertex] origin
- # @param [Vertex] destination
- # @param [Object] requirement the requirement that this edge represents
- # @return [Edge] the added edge
- def add_edge(origin, destination, requirement)
- if destination.path_to?(origin)
- raise CircularDependencyError.new(path(destination, origin))
- end
- add_edge_no_circular(origin, destination, requirement)
- end
-
- # Deletes an {Edge} from the dependency graph
- # @param [Edge] edge
- # @return [Void]
- def delete_edge(edge)
- log.delete_edge(self, edge.origin.name, edge.destination.name, edge.requirement)
- end
-
- # Sets the payload of the vertex with the given name
- # @param [String] name the name of the vertex
- # @param [Object] payload the payload
- # @return [Void]
- def set_payload(name, payload)
- log.set_payload(self, name, payload)
- end
-
- private
-
- # Adds a new {Edge} to the dependency graph without checking for
- # circularity.
- # @param (see #add_edge)
- # @return (see #add_edge)
- 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/action.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb
deleted file mode 100644
index c04c7eec9c..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- class DependencyGraph
- # An action that modifies a {DependencyGraph} that is reversible.
- # @abstract
- class Action
- # rubocop:disable Lint/UnusedMethodArgument
-
- # @return [Symbol] The name of the action.
- def self.action_name
- raise 'Abstract'
- end
-
- # Performs the action on the given graph.
- # @param [DependencyGraph] graph the graph to perform the action on.
- # @return [Void]
- def up(graph)
- raise 'Abstract'
- end
-
- # Reverses the action on the given graph.
- # @param [DependencyGraph] graph the graph to reverse the action on.
- # @return [Void]
- def down(graph)
- raise 'Abstract'
- end
-
- # @return [Action,Nil] The previous action
- attr_accessor :previous
-
- # @return [Action,Nil] The next action
- attr_accessor :next
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
deleted file mode 100644
index 946a08236e..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'action'
-module Bundler::Molinillo
- class DependencyGraph
- # @!visibility private
- # (see DependencyGraph#add_edge_no_circular)
- class AddEdgeNoCircular < Action
- # @!group Action
-
- # (see Action.action_name)
- def self.action_name
- :add_vertex
- end
-
- # (see Action#up)
- def up(graph)
- edge = make_edge(graph)
- edge.origin.outgoing_edges << edge
- edge.destination.incoming_edges << edge
- edge
- end
-
- # (see Action#down)
- def down(graph)
- edge = make_edge(graph)
- delete_first(edge.origin.outgoing_edges, edge)
- delete_first(edge.destination.incoming_edges, edge)
- end
-
- # @!group AddEdgeNoCircular
-
- # @return [String] the name of the origin of the edge
- attr_reader :origin
-
- # @return [String] the name of the destination of the edge
- attr_reader :destination
-
- # @return [Object] the requirement that the edge represents
- attr_reader :requirement
-
- # @param [DependencyGraph] graph the graph to find vertices from
- # @return [Edge] The edge this action adds
- def make_edge(graph)
- Edge.new(graph.vertex_named(origin), graph.vertex_named(destination), requirement)
- end
-
- # Initialize an action to add an edge to a dependency graph
- # @param [String] origin the name of the origin of the edge
- # @param [String] destination the name of the destination of the edge
- # @param [Object] requirement the requirement that the edge represents
- def initialize(origin, destination, requirement)
- @origin = origin
- @destination = destination
- @requirement = requirement
- end
-
- private
-
- def delete_first(array, item)
- return unless index = array.index(item)
- array.delete_at(index)
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
deleted file mode 100644
index 483527daf8..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'action'
-module Bundler::Molinillo
- class DependencyGraph
- # @!visibility private
- # (see DependencyGraph#add_vertex)
- class AddVertex < Action # :nodoc:
- # @!group Action
-
- # (see Action.action_name)
- def self.action_name
- :add_vertex
- end
-
- # (see Action#up)
- def up(graph)
- if existing = graph.vertices[name]
- @existing_payload = existing.payload
- @existing_root = existing.root
- end
- vertex = existing || Vertex.new(name, payload)
- graph.vertices[vertex.name] = vertex
- vertex.payload ||= payload
- vertex.root ||= root
- vertex
- end
-
- # (see Action#down)
- def down(graph)
- if defined?(@existing_payload)
- vertex = graph.vertices[name]
- vertex.payload = @existing_payload
- vertex.root = @existing_root
- else
- graph.vertices.delete(name)
- end
- end
-
- # @!group AddVertex
-
- # @return [String] the name of the vertex
- attr_reader :name
-
- # @return [Object] the payload for the vertex
- attr_reader :payload
-
- # @return [Boolean] whether the vertex is root or not
- attr_reader :root
-
- # Initialize an action to add a vertex to a dependency graph
- # @param [String] name the name of the vertex
- # @param [Object] payload the payload for the vertex
- # @param [Boolean] root whether the vertex is root or not
- def initialize(name, payload, root)
- @name = name
- @payload = payload
- @root = root
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
deleted file mode 100644
index d81940585a..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'action'
-module Bundler::Molinillo
- class DependencyGraph
- # @!visibility private
- # (see DependencyGraph#delete_edge)
- class DeleteEdge < Action
- # @!group Action
-
- # (see Action.action_name)
- def self.action_name
- :delete_edge
- end
-
- # (see Action#up)
- def up(graph)
- edge = make_edge(graph)
- edge.origin.outgoing_edges.delete(edge)
- edge.destination.incoming_edges.delete(edge)
- end
-
- # (see Action#down)
- def down(graph)
- edge = make_edge(graph)
- edge.origin.outgoing_edges << edge
- edge.destination.incoming_edges << edge
- edge
- end
-
- # @!group DeleteEdge
-
- # @return [String] the name of the origin of the edge
- attr_reader :origin_name
-
- # @return [String] the name of the destination of the edge
- attr_reader :destination_name
-
- # @return [Object] the requirement that the edge represents
- attr_reader :requirement
-
- # @param [DependencyGraph] graph the graph to find vertices from
- # @return [Edge] The edge this action adds
- def make_edge(graph)
- Edge.new(
- graph.vertex_named(origin_name),
- graph.vertex_named(destination_name),
- requirement
- )
- end
-
- # Initialize an action to add an edge to a dependency graph
- # @param [String] origin_name the name of the origin of the edge
- # @param [String] destination_name the name of the destination of the edge
- # @param [Object] requirement the requirement that the edge represents
- def initialize(origin_name, destination_name, requirement)
- @origin_name = origin_name
- @destination_name = destination_name
- @requirement = requirement
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
deleted file mode 100644
index 36fce7c526..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'action'
-module Bundler::Molinillo
- class DependencyGraph
- # @!visibility private
- # @see DependencyGraph#detach_vertex_named
- class DetachVertexNamed < Action
- # @!group Action
-
- # (see Action#name)
- def self.action_name
- :add_vertex
- end
-
- # (see Action#up)
- def up(graph)
- return [] unless @vertex = graph.vertices.delete(name)
-
- removed_vertices = [@vertex]
- @vertex.outgoing_edges.each do |e|
- v = e.destination
- v.incoming_edges.delete(e)
- if !v.root? && v.incoming_edges.empty?
- removed_vertices.concat graph.detach_vertex_named(v.name)
- end
- end
-
- @vertex.incoming_edges.each do |e|
- v = e.origin
- v.outgoing_edges.delete(e)
- end
-
- removed_vertices
- end
-
- # (see Action#down)
- def down(graph)
- return unless @vertex
- graph.vertices[@vertex.name] = @vertex
- @vertex.outgoing_edges.each do |e|
- e.destination.incoming_edges << e
- end
- @vertex.incoming_edges.each do |e|
- e.origin.outgoing_edges << e
- end
- end
-
- # @!group DetachVertexNamed
-
- # @return [String] the name of the vertex to detach
- attr_reader :name
-
- # Initialize an action to detach a vertex from a dependency graph
- # @param [String] name the name of the vertex to detach
- def initialize(name)
- @name = name
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb
deleted file mode 100644
index 6f0de19886..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: true
-
-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 Bundler::Molinillo
- class DependencyGraph
- # A log for dependency graph actions
- class Log
- # Initializes an empty log
- def initialize
- @current_action = @first_action = nil
- end
-
- # @!macro [new] action
- # {include:DependencyGraph#$0}
- # @param [Graph] graph the graph to perform the action on
- # @param (see DependencyGraph#$0)
- # @return (see DependencyGraph#$0)
-
- # @macro action
- def tag(graph, tag)
- push_action(graph, Tag.new(tag))
- end
-
- # @macro action
- def add_vertex(graph, name, payload, root)
- push_action(graph, AddVertex.new(name, payload, root))
- end
-
- # @macro action
- def detach_vertex_named(graph, name)
- push_action(graph, DetachVertexNamed.new(name))
- end
-
- # @macro action
- def add_edge_no_circular(graph, origin, destination, requirement)
- push_action(graph, AddEdgeNoCircular.new(origin, destination, requirement))
- end
-
- # {include:DependencyGraph#delete_edge}
- # @param [Graph] graph the graph to perform the action on
- # @param [String] origin_name
- # @param [String] destination_name
- # @param [Object] requirement
- # @return (see DependencyGraph#delete_edge)
- def delete_edge(graph, origin_name, destination_name, requirement)
- push_action(graph, DeleteEdge.new(origin_name, destination_name, requirement))
- end
-
- # @macro action
- def set_payload(graph, name, payload)
- push_action(graph, SetPayload.new(name, payload))
- end
-
- # Pops the most recent action from the log and undoes the action
- # @param [DependencyGraph] graph
- # @return [Action] the action that was popped off the log
- def pop!(graph)
- return unless action = @current_action
- unless @current_action = action.previous
- @first_action = nil
- end
- action.down(graph)
- action
- end
-
- extend Enumerable
-
- # @!visibility private
- # Enumerates each action in the log
- # @yield [Action]
- def each
- return enum_for unless block_given?
- action = @first_action
- loop do
- break unless action
- yield action
- action = action.next
- end
- self
- end
-
- # @!visibility private
- # Enumerates each action in the log in reverse order
- # @yield [Action]
- def reverse_each
- return enum_for(:reverse_each) unless block_given?
- action = @current_action
- loop do
- break unless action
- yield action
- action = action.previous
- end
- self
- end
-
- # @macro action
- def rewind_to(graph, tag)
- loop do
- action = pop!(graph)
- raise "No tag #{tag.inspect} found" unless action
- break if action.class.action_name == :tag && action.tag == tag
- end
- end
-
- private
-
- # Adds the given action to the log, running the action
- # @param [DependencyGraph] graph
- # @param [Action] action
- # @return The value returned by `action.up`
- def push_action(graph, action)
- action.previous = @current_action
- @current_action.next = action if @current_action
- @current_action = action
- @first_action ||= action
- action.up(graph)
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb
deleted file mode 100644
index 2e9b90e6cd..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'action'
-module Bundler::Molinillo
- class DependencyGraph
- # @!visibility private
- # @see DependencyGraph#set_payload
- class SetPayload < Action # :nodoc:
- # @!group Action
-
- # (see Action.action_name)
- def self.action_name
- :set_payload
- end
-
- # (see Action#up)
- def up(graph)
- vertex = graph.vertex_named(name)
- @old_payload = vertex.payload
- vertex.payload = payload
- end
-
- # (see Action#down)
- def down(graph)
- graph.vertex_named(name).payload = @old_payload
- end
-
- # @!group SetPayload
-
- # @return [String] the name of the vertex
- attr_reader :name
-
- # @return [Object] the payload for the vertex
- attr_reader :payload
-
- # Initialize an action to add set the payload for a vertex in a dependency
- # graph
- # @param [String] name the name of the vertex
- # @param [Object] payload the payload for the vertex
- def initialize(name, payload)
- @name = name
- @payload = payload
- end
- 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
deleted file mode 100644
index 5b5da3e4f9..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'action'
-module Bundler::Molinillo
- class DependencyGraph
- # @!visibility private
- # @see DependencyGraph#tag
- class Tag < Action
- # @!group Action
-
- # (see Action.action_name)
- def self.action_name
- :tag
- end
-
- # (see Action#up)
- def up(graph)
- end
-
- # (see Action#down)
- def down(graph)
- end
-
- # @!group Tag
-
- # @return [Object] An opaque tag
- attr_reader :tag
-
- # Initialize an action to tag a state of a dependency graph
- # @param [Object] tag an opaque tag
- def initialize(tag)
- @tag = tag
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
deleted file mode 100644
index 1185a8ab05..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- class DependencyGraph
- # A vertex in a {DependencyGraph} that encapsulates a {#name} and a
- # {#payload}
- class Vertex
- # @return [String] the name of the vertex
- attr_accessor :name
-
- # @return [Object] the payload the vertex holds
- attr_accessor :payload
-
- # @return [Array<Object>] the explicit requirements that required
- # this vertex
- attr_reader :explicit_requirements
-
- # @return [Boolean] whether the vertex is considered a root vertex
- attr_accessor :root
- alias root? root
-
- # Initializes a vertex with the given name and payload.
- # @param [String] name see {#name}
- # @param [Object] payload see {#payload}
- def initialize(name, payload)
- @name = name.frozen? ? name : name.dup.freeze
- @payload = payload
- @explicit_requirements = []
- @outgoing_edges = []
- @incoming_edges = []
- end
-
- # @return [Array<Object>] all of the requirements that required
- # this vertex
- def requirements
- (incoming_edges.map(&:requirement) + explicit_requirements).uniq
- end
-
- # @return [Array<Edge>] the edges of {#graph} that have `self` as their
- # {Edge#origin}
- attr_accessor :outgoing_edges
-
- # @return [Array<Edge>] the edges of {#graph} that have `self` as their
- # {Edge#destination}
- attr_accessor :incoming_edges
-
- # @return [Array<Vertex>] the vertices of {#graph} that have an edge with
- # `self` as their {Edge#destination}
- def predecessors
- incoming_edges.map(&:origin)
- end
-
- # @return [Set<Vertex>] the vertices of {#graph} where `self` is a
- # {#descendent?}
- def recursive_predecessors
- _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}
- def successors
- outgoing_edges.map(&:destination)
- end
-
- # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
- # {#ancestor?}
- def recursive_successors
- _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
- "#{self.class}:#{name}(#{payload.inspect})"
- end
-
- # @return [Boolean] whether the two vertices are equal, determined
- # by a recursive traversal of each {Vertex#successors}
- def ==(other)
- return true if equal?(other)
- shallow_eql?(other) &&
- successors.to_set == other.successors.to_set
- end
-
- # @param [Vertex] other the other vertex to compare to
- # @return [Boolean] whether the two vertices are equal, determined
- # solely by {#name} and {#payload} equality
- def shallow_eql?(other)
- return true if equal?(other)
- other &&
- name == other.name &&
- payload == other.payload
- end
-
- alias eql? ==
-
- # @return [Fixnum] a hash for the vertex based upon its {#name}
- def hash
- name.hash
- end
-
- # Is there a path from `self` to `other` following edges in the
- # dependency graph?
- # @return whether there is a path following edges within this {#graph}
- def 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 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
deleted file mode 100644
index e210202b69..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # An error that occurred during the resolution process
- class ResolverError < StandardError; end
-
- # An error caused by searching for a dependency that is completely unknown,
- # i.e. has no versions available whatsoever.
- class NoSuchDependencyError < ResolverError
- # @return [Object] the dependency that could not be found
- attr_accessor :dependency
-
- # @return [Array<Object>] the specifications that depended upon {#dependency}
- attr_accessor :required_by
-
- # Initializes a new error with the given missing dependency.
- # @param [Object] dependency @see {#dependency}
- # @param [Array<Object>] required_by @see {#required_by}
- def initialize(dependency, required_by = [])
- @dependency = dependency
- @required_by = required_by.uniq
- super()
- end
-
- # The error message for the missing dependency, including the specifications
- # that had this dependency.
- def message
- sources = required_by.map { |r| "`#{r}`" }.join(' and ')
- message = "Unable to find a specification for `#{dependency}`"
- message += " depended upon by #{sources}" unless sources.empty?
- message
- end
- end
-
- # An error caused by attempting to fulfil a dependency that was circular
- #
- # @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
- # [Set<Object>] the dependencies responsible for causing the error
- attr_reader :dependencies
-
- # Initializes a new error with the given circular vertices.
- # @param [Array<DependencyGraph::Vertex>] vertices the vertices in the dependency
- # that caused the error
- 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
-
- # An error caused by conflicts in version
- class VersionConflict < ResolverError
- # @return [{String => Resolution::Conflict}] the conflicts that caused
- # 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}
- # @param [SpecificationProvider] specification_provider see {#specification_provider}
- def initialize(conflicts, specification_provider)
- pairs = []
- conflicts.values.flat_map(&:requirements).each do |conflicting|
- conflicting.each do |source, conflict_requirements|
- conflict_requirements.each do |c|
- pairs << [c, source]
- end
- end
- end
-
- 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/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb b/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
deleted file mode 100644
index e13a781a50..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # The version of Bundler::Molinillo.
- 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
deleted file mode 100644
index eeae79af3c..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # Provides information about specifications and dependencies to the resolver,
- # allowing the {Resolver} class to remain generic while still providing power
- # and flexibility.
- #
- # This module contains the methods that users of Bundler::Molinillo must to implement,
- # using knowledge of their own model classes.
- module SpecificationProvider
- # Search for the specifications that match the given dependency.
- # The specifications in the returned array will be considered in reverse
- # order, so the latest version ought to be last.
- # @note This method should be 'pure', i.e. the return value should depend
- # only on the `dependency` parameter.
- #
- # @param [Object] dependency
- # @return [Array<Object>] the specifications that satisfy the given
- # `dependency`.
- def search_for(dependency)
- []
- end
-
- # Returns the dependencies of `specification`.
- # @note This method should be 'pure', i.e. the return value should depend
- # only on the `specification` parameter.
- #
- # @param [Object] specification
- # @return [Array<Object>] the dependencies that are required by the given
- # `specification`.
- def dependencies_for(specification)
- []
- end
-
- # Determines whether the given `requirement` is satisfied by the given
- # `spec`, in the context of the current `activated` dependency graph.
- #
- # @param [Object] requirement
- # @param [DependencyGraph] activated the current dependency graph in the
- # resolution process.
- # @param [Object] spec
- # @return [Boolean] whether `requirement` is satisfied by `spec` in the
- # context of the current `activated` dependency graph.
- def requirement_satisfied_by?(requirement, activated, spec)
- 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.
- #
- # @param [Object] dependency
- # @return [String] the name for the given `dependency`.
- def name_for(dependency)
- dependency.to_s
- end
-
- # @return [String] the name of the source of explicit dependencies, i.e.
- # those passed to {Resolver#resolve} directly.
- def name_for_explicit_dependency_source
- 'user-specified dependency'
- end
-
- # @return [String] the name of the source of 'locked' dependencies, i.e.
- # those passed to {Resolver#resolve} directly as the `base`
- def name_for_locking_dependency_source
- 'Lockfile'
- end
-
- # Sort dependencies so that the ones that are easiest to resolve are first.
- # Easiest to resolve is (usually) defined by:
- # 1) Is this dependency already activated?
- # 2) How relaxed are the requirements?
- # 3) Are there any conflicts for this dependency?
- # 4) How many possibilities are there to satisfy this dependency?
- #
- # @param [Array<Object>] dependencies
- # @param [DependencyGraph] activated the current dependency graph in the
- # resolution process.
- # @param [{String => Array<Conflict>}] conflicts
- # @return [Array<Object>] a sorted copy of `dependencies`.
- def sort_dependencies(dependencies, activated, conflicts)
- dependencies.sort_by do |dependency|
- name = name_for(dependency)
- [
- activated.vertex_named(name).payload ? 0 : 1,
- conflicts[name] ? 0 : 1,
- ]
- end
- end
-
- # Returns whether this dependency, which has no possible matching
- # specifications, can safely be ignored.
- #
- # @param [Object] dependency
- # @return [Boolean] whether this dependency can safely be skipped.
- def allow_missing?(dependency)
- false
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb
deleted file mode 100644
index a166bc6991..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # Conveys information about the resolution process to a user.
- module UI
- # The {IO} object that should be used to print output. `STDOUT`, by default.
- #
- # @return [IO]
- def output
- STDOUT
- end
-
- # Called roughly every {#progress_rate}, this method should convey progress
- # to the user.
- #
- # @return [void]
- def indicate_progress
- output.print '.' unless debug?
- end
-
- # How often progress should be conveyed to the user via
- # {#indicate_progress}, in seconds. A third of a second, by default.
- #
- # @return [Float]
- def progress_rate
- 0.33
- end
-
- # Called before resolution begins.
- #
- # @return [void]
- def before_resolution
- output.print 'Resolving dependencies...'
- end
-
- # Called after resolution ends (either successfully or with an error).
- # By default, prints a newline.
- #
- # @return [void]
- def after_resolution
- output.puts
- end
-
- # Conveys debug information to the user.
- #
- # @param [Integer] depth the current depth of the resolution process.
- # @return [void]
- def debug(depth = 0)
- if debug?
- debug_info = yield
- debug_info = debug_info.inspect unless debug_info.is_a?(String)
- debug_info = debug_info.split("\n").map { |s| ":#{depth.to_s.rjust 4}: #{s}" }
- output.puts debug_info
- end
- end
-
- # Whether or not debug messages should be printed.
- # By default, whether or not the `MOLINILLO_DEBUG` environment variable is
- # set.
- #
- # @return [Boolean]
- def debug?
- return @debug_mode if defined?(@debug_mode)
- @debug_mode = ENV['MOLINILLO_DEBUG']
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
deleted file mode 100644
index c689ca7635..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
+++ /dev/null
@@ -1,839 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- class Resolver
- # A specific resolution from a given {Resolver}
- class Resolution
- # A conflict that the resolution process encountered
- # @attr [Object] requirement the requirement that immediately led to the conflict
- # @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_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_set,
- :locked_requirement,
- :requirement_trees,
- :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
-
- # @return [UI] the UI that knows how to communicate feedback about the
- # resolution process back to the user
- attr_reader :resolver_ui
-
- # @return [DependencyGraph] the base dependency graph to which
- # dependencies should be 'locked'
- attr_reader :base
-
- # @return [Array] the dependencies that were explicitly required
- attr_reader :original_requested
-
- # Initializes a new resolution.
- # @param [SpecificationProvider] specification_provider
- # see {#specification_provider}
- # @param [UI] resolver_ui see {#resolver_ui}
- # @param [Array] requested see {#original_requested}
- # @param [DependencyGraph] base see {#base}
- def initialize(specification_provider, resolver_ui, requested, base)
- @specification_provider = specification_provider
- @resolver_ui = resolver_ui
- @original_requested = requested
- @base = base
- @states = []
- @iteration_counter = 0
- @parents_of = Hash.new { |h, k| h[k] = [] }
- end
-
- # Resolves the {#original_requested} dependencies into a full dependency
- # graph
- # @raise [ResolverError] if successful resolution is impossible
- # @return [DependencyGraph] the dependency graph of successfully resolved
- # dependencies
- def resolve
- start_resolution
-
- while state
- 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)" }
- state.pop_possibility_state.tap do |s|
- if s
- states.push(s)
- activated.tag(s)
- end
- end
- end
- process_topmost_state
- end
-
- resolve_activated_specs
- ensure
- end_resolution
- end
-
- # @return [Integer] the number of resolver iterations in between calls to
- # {#resolver_ui}'s {UI#indicate_progress} method
- attr_accessor :iteration_rate
- private :iteration_rate
-
- # @return [Time] the time at which resolution began
- attr_accessor :started_at
- private :started_at
-
- # @return [Array<ResolutionState>] the stack of states for the resolution
- attr_accessor :states
- private :states
-
- private
-
- # Sets up the resolution process
- # @return [void]
- def start_resolution
- @started_at = Time.now
-
- 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
- resolver_ui.after_resolution
- debug do
- "Finished resolution (#{@iteration_counter} steps) " \
- "(Took #{(ended_at = Time.now) - @started_at} seconds) (#{ended_at})"
- end
- debug { 'Unactivated: ' + Hash[activated.vertices.reject { |_n, v| v.payload }].keys.join(', ') } if state
- debug { 'Activated: ' + Hash[activated.vertices.select { |_n, v| v.payload }].keys.join(', ') } if state
- end
-
- require_relative 'state'
- require_relative 'modules/specification_provider'
-
- require_relative 'delegates/resolution_state'
- require_relative 'delegates/specification_provider'
-
- include Bundler::Molinillo::Delegates::ResolutionState
- include Bundler::Molinillo::Delegates::SpecificationProvider
-
- # Processes the topmost available {RequirementState} on the stack
- # @return [void]
- def process_topmost_state
- if possibility
- attempt_to_activate
- else
- 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
- # to activate
- def possibility
- possibilities.last
- end
-
- # @return [RequirementState] the current state the resolution is
- # operating upon
- def state
- states.last
- end
-
- # Creates and pushes the initial state for the resolution, based upon the
- # {#requested} dependencies
- # @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)
- vertex.explicit_requirements << requested
- end
- dg.tag(:initial_state)
- end
-
- 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
- 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!((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
-
- # 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
- 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
-
- # @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)
- return unless requirement
- return unless index = @parents_of[requirement].last
- return unless parent_state = @states[index]
- 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 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.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)
- vertex = activated.vertex_named(name)
- locked_requirement = locked_requirement_named(name)
-
- requirements = {}
- unless vertex.explicit_requirements.empty?
- 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 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.latest_version if v.payload }
- conflicts[name] = Conflict.new(
- requirement,
- requirements,
- vertex.payload && vertex.payload.latest_version,
- possibility,
- locked_requirement,
- requirement_trees,
- activated_by_name,
- underlying_error
- )
- end
-
- # @return [Array<Array<Object>>] The different requirement
- # trees that led to every requirement for the current spec.
- def requirement_trees
- vertex = activated.vertex_named(name)
- 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)
- tree = []
- while requirement
- tree.unshift(requirement)
- requirement = parent_of(requirement)
- end
- tree
- end
-
- # Indicates progress roughly once every second
- # @return [void]
- def indicate_progress
- @iteration_counter += 1
- @progress_rate ||= resolver_ui.progress_rate
- if iteration_rate.nil?
- if Time.now - started_at >= @progress_rate
- self.iteration_rate = @iteration_counter
- end
- end
-
- if iteration_rate && (@iteration_counter % iteration_rate) == 0
- resolver_ui.indicate_progress
- end
- end
-
- # Calls the {#resolver_ui}'s {UI#debug} method
- # @param [Integer] depth the depth of the {#states} stack
- # @param [Proc] block a block that yields a {#to_s}
- # @return [void]
- def debug(depth = 0, &block)
- resolver_ui.debug(depth, &block)
- end
-
- # Attempts to activate the current {#possibility}
- # @return [void]
- def attempt_to_activate
- debug(depth) { 'Attempting to activate ' + possibility.to_s }
- 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
- latest = possibility.latest_version
- 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
- possibility.possibilities << latest if latest
- create_conflict
- unwind_for_conflict
- else
- activate_new_spec
- end
- end
- end
-
- # Attempts to update the existing vertex's `PossibilitySet` with a filtered version
- # @return [void]
- 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
-
- # 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
- # @return [Object] the locked spec named `requirement_name`, if one
- # is found on {#base}
- def locked_requirement_named(requirement_name)
- vertex = base.vertex_named(requirement_name)
- vertex && vertex.payload
- end
-
- # Add the current {#possibility} to the dependency graph of the current
- # {#state}
- # @return [void]
- def activate_new_spec
- conflicts.delete(name)
- debug(depth) { "Activated #{name} at #{possibility}" }
- activated.set_payload(name, possibility)
- require_nested_dependencies_for(possibility)
- end
-
- # Requires the dependencies that the recently activated spec has
- # @param [Object] possibility_set the PossibilitySet that has just been
- # activated
- # @return [void]
- 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(possibility_set.latest_version)], d)
- parent_index = states.size - 1
- parents = @parents_of[d]
- parents << parent_index if parents.empty?
- end
-
- push_state_for_requirements(requirements + nested_dependencies, !nested_dependencies.empty?)
- end
-
- # 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 = 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 = 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, 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 vertex in {#activated} is removed, and we continue
- # resolving the remaining requirements.
- # @param [DependencyState] state
- # @return [void]
- def handle_missing_or_push_dependency_state(state)
- if state.requirement && state.possibilities.empty? && allow_missing?(state.requirement)
- state.activated.detach_vertex_named(state.name)
- push_state_for_requirements(state.requirements.dup, false, state.activated)
- else
- states.push(state).tap { activated.tag(state) }
- end
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb
deleted file mode 100644
index 95eaab5991..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'dependency_graph'
-
-module Bundler::Molinillo
- # This class encapsulates a dependency resolver.
- # The resolver is responsible for determining which set of dependencies to
- # activate, with feedback from the {#specification_provider}
- #
- #
- class Resolver
- require_relative 'resolution'
-
- # @return [SpecificationProvider] the specification provider used
- # in the resolution process
- attr_reader :specification_provider
-
- # @return [UI] the UI module used to communicate back to the user
- # during the resolution process
- attr_reader :resolver_ui
-
- # Initializes a new resolver.
- # @param [SpecificationProvider] specification_provider
- # see {#specification_provider}
- # @param [UI] resolver_ui
- # see {#resolver_ui}
- def initialize(specification_provider, resolver_ui)
- @specification_provider = specification_provider
- @resolver_ui = resolver_ui
- end
-
- # Resolves the requested dependencies into a {DependencyGraph},
- # locking to the base dependency graph (if specified)
- # @param [Array] requested an array of 'requested' dependencies that the
- # {#specification_provider} can understand
- # @param [DependencyGraph,nil] base the base dependency graph to which
- # dependencies should be 'locked'
- def resolve(requested, base = DependencyGraph.new)
- Resolution.new(specification_provider,
- resolver_ui,
- requested,
- base).
- resolve
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/state.rb b/lib/bundler/vendor/molinillo/lib/molinillo/state.rb
deleted file mode 100644
index 68fa1f54e3..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/state.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # A state that a {Resolution} can be in
- # @attr [String] name the name of the current requirement
- # @attr [Array<Object>] requirements currently unsatisfied requirements
- # @attr [DependencyGraph] activated the graph of activated dependencies
- # @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 [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,
- :activated,
- :requirement,
- :possibilities,
- :depth,
- :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, {}, [])
- end
- end
-
- # A state that encapsulates a set of {#requirements} with an {Array} of
- # possibilities
- class DependencyState < ResolutionState
- # Removes a possibility from `self`
- # @return [PossibilityState] a state with a single possibility,
- # the possibility that was removed from `self`
- def pop_possibility_state
- PossibilityState.new(
- name,
- requirements.dup,
- activated,
- requirement,
- [possibilities.pop],
- depth + 1,
- conflicts.dup,
- unused_unwind_options.dup
- ).tap do |state|
- state.activated.tag(state)
- end
- end
- end
-
- # A state that encapsulates a single possibility to fulfill the given
- # {#requirement}
- class PossibilityState < ResolutionState
- end
-end
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 beff6d658b..a4e1c5a750 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
@@ -174,7 +174,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
##
# The version of Bundler::Persistent::Net::HTTP::Persistent you are using
- VERSION = '4.0.0'
+ VERSION = '4.0.1'
##
# Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub.rb
new file mode 100644
index 0000000000..eaaba3fc98
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub.rb
@@ -0,0 +1,31 @@
+require_relative "pub_grub/package"
+require_relative "pub_grub/static_package_source"
+require_relative "pub_grub/term"
+require_relative "pub_grub/version_range"
+require_relative "pub_grub/version_constraint"
+require_relative "pub_grub/version_union"
+require_relative "pub_grub/version_solver"
+require_relative "pub_grub/incompatibility"
+require_relative 'pub_grub/solve_failure'
+require_relative 'pub_grub/failure_writer'
+require_relative 'pub_grub/version'
+
+module Bundler::PubGrub
+ class << self
+ attr_writer :logger
+
+ def logger
+ @logger || default_logger
+ end
+
+ private
+
+ def default_logger
+ require "logger"
+
+ logger = ::Logger.new(STDERR)
+ logger.level = $DEBUG ? ::Logger::DEBUG : ::Logger::WARN
+ @logger = logger
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb
new file mode 100644
index 0000000000..2236a97b5b
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb
@@ -0,0 +1,20 @@
+module Bundler::PubGrub
+ class Assignment
+ attr_reader :term, :cause, :decision_level, :index
+ def initialize(term, cause, decision_level, index)
+ @term = term
+ @cause = cause
+ @decision_level = decision_level
+ @index = index
+ end
+
+ def self.decision(package, version, decision_level, index)
+ term = Term.new(VersionConstraint.exact(package, version), true)
+ new(term, :decision, decision_level, index)
+ end
+
+ def decision?
+ cause == :decision
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb
new file mode 100644
index 0000000000..dce20d37ad
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb
@@ -0,0 +1,189 @@
+require_relative 'version_constraint'
+require_relative 'incompatibility'
+
+module Bundler::PubGrub
+ # Types:
+ #
+ # Where possible, Bundler::PubGrub will accept user-defined types, so long as they quack.
+ #
+ # ## "Package":
+ #
+ # This class will be used to represent the various packages being solved for.
+ # .to_s will be called when displaying errors and debugging info, it should
+ # probably return the package's name.
+ # It must also have a reasonable definition of #== and #hash
+ #
+ # Example classes: String ("rails")
+ #
+ #
+ # ## "Version":
+ #
+ # This class will be used to represent a single version number.
+ #
+ # Versions don't need to store their associated package, however they will
+ # only be compared against other versions of the same package.
+ #
+ # It must be Comparible (and implement <=> reasonably)
+ #
+ # Example classes: Gem::Version, Integer
+ #
+ #
+ # ## "Dependency"
+ #
+ # This class represents the requirement one package has on another. It is
+ # returned by dependencies_for(package, version) and will be passed to
+ # parse_dependency to convert it to a format Bundler::PubGrub understands.
+ #
+ # It must also have a reasonable definition of #==
+ #
+ # Example classes: String ("~> 1.0"), Gem::Requirement
+ #
+ class BasicPackageSource
+ # Override me!
+ #
+ # This is called per package to find all possible versions of a package.
+ #
+ # It is called at most once per-package
+ #
+ # Returns: Array of versions for a package, in preferred order of selection
+ def all_versions_for(package)
+ raise NotImplementedError
+ end
+
+ # Override me!
+ #
+ # Returns: Hash in the form of { package => requirement, ... }
+ def dependencies_for(package, version)
+ raise NotImplementedError
+ end
+
+ # Override me!
+ #
+ # Convert a (user-defined) dependency into a format Bundler::PubGrub understands.
+ #
+ # Package is passed to this method but for many implementations is not
+ # needed.
+ #
+ # Returns: either a Bundler::PubGrub::VersionRange, Bundler::PubGrub::VersionUnion, or a
+ # Bundler::PubGrub::VersionConstraint
+ def parse_dependency(package, dependency)
+ raise NotImplementedError
+ end
+
+ # Override me!
+ #
+ # If not overridden, this will call dependencies_for with the root package.
+ #
+ # Returns: Hash in the form of { package => requirement, ... } (see dependencies_for)
+ def root_dependencies
+ dependencies_for(@root_package, @root_version)
+ end
+
+ # Override me (maybe)
+ #
+ # If not overridden, the order returned by all_versions_for will be used
+ #
+ # Returns: Array of versions in preferred order
+ def sort_versions_by_preferred(package, sorted_versions)
+ indexes = @version_indexes[package]
+ sorted_versions.sort_by { |version| indexes[version] }
+ end
+
+ def initialize
+ @root_package = Package.root
+ @root_version = Package.root_version
+
+ @cached_versions = Hash.new do |h,k|
+ if k == @root_package
+ h[k] = [@root_version]
+ else
+ h[k] = all_versions_for(k)
+ end
+ end
+ @sorted_versions = Hash.new { |h,k| h[k] = @cached_versions[k].sort }
+ @version_indexes = Hash.new { |h,k| h[k] = @cached_versions[k].each.with_index.to_h }
+
+ @cached_dependencies = Hash.new do |packages, package|
+ if package == @root_package
+ packages[package] = {
+ @root_version => root_dependencies
+ }
+ else
+ packages[package] = Hash.new do |versions, version|
+ versions[version] = dependencies_for(package, version)
+ end
+ end
+ end
+ end
+
+ def versions_for(package, range=VersionRange.any)
+ versions = range.select_versions(@sorted_versions[package])
+
+ # Conditional avoids (among other things) calling
+ # sort_versions_by_preferred with the root package
+ if versions.size > 1
+ sort_versions_by_preferred(package, versions)
+ else
+ versions
+ end
+ end
+
+ def no_versions_incompatibility_for(_package, unsatisfied_term)
+ cause = Incompatibility::NoVersions.new(unsatisfied_term)
+
+ Incompatibility.new([unsatisfied_term], cause: cause)
+ end
+
+ def incompatibilities_for(package, version)
+ package_deps = @cached_dependencies[package]
+ sorted_versions = @sorted_versions[package]
+ package_deps[version].map do |dep_package, dep_constraint_name|
+ low = high = sorted_versions.index(version)
+
+ # find version low such that all >= low share the same dep
+ while low > 0 &&
+ package_deps[sorted_versions[low - 1]][dep_package] == dep_constraint_name
+ low -= 1
+ end
+ low =
+ if low == 0
+ nil
+ else
+ sorted_versions[low]
+ end
+
+ # find version high such that all < high share the same dep
+ while high < sorted_versions.length &&
+ package_deps[sorted_versions[high]][dep_package] == dep_constraint_name
+ high += 1
+ end
+ high =
+ if high == sorted_versions.length
+ nil
+ else
+ sorted_versions[high]
+ end
+
+ range = VersionRange.new(min: low, max: high, include_min: true)
+
+ self_constraint = VersionConstraint.new(package, range: range)
+
+ if !@packages.include?(dep_package)
+ # no such package -> this version is invalid
+ end
+
+ dep_constraint = parse_dependency(dep_package, dep_constraint_name)
+ if !dep_constraint
+ # falsey indicates this dependency was invalid
+ cause = Bundler::PubGrub::Incompatibility::InvalidDependency.new(dep_package, dep_constraint_name)
+ return [Incompatibility.new([Term.new(self_constraint, true)], cause: cause)]
+ elsif !dep_constraint.is_a?(VersionConstraint)
+ # Upgrade range/union to VersionConstraint
+ dep_constraint = VersionConstraint.new(dep_package, range: dep_constraint)
+ end
+
+ Incompatibility.new([Term.new(self_constraint, true), Term.new(dep_constraint, false)], cause: :dependency)
+ end
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb
new file mode 100644
index 0000000000..ee099b23f4
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb
@@ -0,0 +1,182 @@
+module Bundler::PubGrub
+ class FailureWriter
+ def initialize(root)
+ @root = root
+
+ # { Incompatibility => Integer }
+ @derivations = {}
+
+ # [ [ String, Integer or nil ] ]
+ @lines = []
+
+ # { Incompatibility => Integer }
+ @line_numbers = {}
+
+ count_derivations(root)
+ end
+
+ def write
+ return @root.to_s unless @root.conflict?
+
+ visit(@root)
+
+ padding = @line_numbers.empty? ? 0 : "(#{@line_numbers.values.last}) ".length
+
+ @lines.map do |message, number|
+ next "" if message.empty?
+
+ lead = number ? "(#{number}) " : ""
+ lead = lead.ljust(padding)
+ message = message.gsub("\n", "\n" + " " * (padding + 2))
+ "#{lead}#{message}"
+ end.join("\n")
+ end
+
+ private
+
+ def write_line(incompatibility, message, numbered:)
+ if numbered
+ number = @line_numbers.length + 1
+ @line_numbers[incompatibility] = number
+ end
+
+ @lines << [message, number]
+ end
+
+ def visit(incompatibility, conclusion: false)
+ raise unless incompatibility.conflict?
+
+ numbered = conclusion || @derivations[incompatibility] > 1;
+ conjunction = conclusion || incompatibility == @root ? "So," : "And"
+
+ cause = incompatibility.cause
+
+ if cause.conflict.conflict? && cause.other.conflict?
+ conflict_line = @line_numbers[cause.conflict]
+ other_line = @line_numbers[cause.other]
+
+ if conflict_line && other_line
+ write_line(
+ incompatibility,
+ "Because #{cause.conflict} (#{conflict_line})\nand #{cause.other} (#{other_line}),\n#{incompatibility}.",
+ numbered: numbered
+ )
+ elsif conflict_line || other_line
+ with_line = conflict_line ? cause.conflict : cause.other
+ without_line = conflict_line ? cause.other : cause.conflict
+ line = @line_numbers[with_line]
+
+ visit(without_line);
+ write_line(
+ incompatibility,
+ "#{conjunction} because #{with_line} (#{line}),\n#{incompatibility}.",
+ numbered: numbered
+ )
+ else
+ single_line_conflict = single_line?(cause.conflict.cause)
+ single_line_other = single_line?(cause.other.cause)
+
+ if single_line_conflict || single_line_other
+ first = single_line_other ? cause.conflict : cause.other
+ second = single_line_other ? cause.other : cause.conflict
+ visit(first)
+ visit(second)
+ write_line(
+ incompatibility,
+ "Thus, #{incompatibility}.",
+ numbered: numbered
+ )
+ else
+ visit(cause.conflict, conclusion: true)
+ @lines << ["", nil]
+ visit(cause.other)
+
+ write_line(
+ incompatibility,
+ "#{conjunction} because #{cause.conflict} (#{@line_numbers[cause.conflict]}),\n#{incompatibility}.",
+ numbered: numbered
+ )
+ end
+ end
+ elsif cause.conflict.conflict? || cause.other.conflict?
+ derived = cause.conflict.conflict? ? cause.conflict : cause.other
+ ext = cause.conflict.conflict? ? cause.other : cause.conflict
+
+ derived_line = @line_numbers[derived]
+ if derived_line
+ write_line(
+ incompatibility,
+ "Because #{ext}\nand #{derived} (#{derived_line}),\n#{incompatibility}.",
+ numbered: numbered
+ )
+ elsif collapsible?(derived)
+ derived_cause = derived.cause
+ if derived_cause.conflict.conflict?
+ collapsed_derived = derived_cause.conflict
+ collapsed_ext = derived_cause.other
+ else
+ collapsed_derived = derived_cause.other
+ collapsed_ext = derived_cause.conflict
+ end
+
+ visit(collapsed_derived)
+
+ write_line(
+ incompatibility,
+ "#{conjunction} because #{collapsed_ext}\nand #{ext},\n#{incompatibility}.",
+ numbered: numbered
+ )
+ else
+ visit(derived)
+ write_line(
+ incompatibility,
+ "#{conjunction} because #{ext},\n#{incompatibility}.",
+ numbered: numbered
+ )
+ end
+ else
+ write_line(
+ incompatibility,
+ "Because #{cause.conflict}\nand #{cause.other},\n#{incompatibility}.",
+ numbered: numbered
+ )
+ end
+ end
+
+ def single_line?(cause)
+ !cause.conflict.conflict? && !cause.other.conflict?
+ end
+
+ def collapsible?(incompatibility)
+ return false if @derivations[incompatibility] > 1
+
+ cause = incompatibility.cause
+ # If incompatibility is derived from two derived incompatibilities,
+ # there are too many transitive causes to display concisely.
+ return false if cause.conflict.conflict? && cause.other.conflict?
+
+ # If incompatibility is derived from two external incompatibilities, it
+ # tends to be confusing to collapse it.
+ return false unless cause.conflict.conflict? || cause.other.conflict?
+
+ # If incompatibility's internal cause is numbered, collapsing it would
+ # get too noisy.
+ complex = cause.conflict.conflict? ? cause.conflict : cause.other
+
+ !@line_numbers.has_key?(complex)
+ end
+
+ def count_derivations(incompatibility)
+ if @derivations.has_key?(incompatibility)
+ @derivations[incompatibility] += 1
+ else
+ @derivations[incompatibility] = 1
+ if incompatibility.conflict?
+ cause = incompatibility.cause
+ count_derivations(cause.conflict)
+ count_derivations(cause.other)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb
new file mode 100644
index 0000000000..239eaf3401
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb
@@ -0,0 +1,150 @@
+module Bundler::PubGrub
+ class Incompatibility
+ ConflictCause = Struct.new(:incompatibility, :satisfier) do
+ alias_method :conflict, :incompatibility
+ alias_method :other, :satisfier
+ end
+
+ InvalidDependency = Struct.new(:package, :constraint) do
+ end
+
+ NoVersions = Struct.new(:constraint) do
+ end
+
+ attr_reader :terms, :cause
+
+ def initialize(terms, cause:, custom_explanation: nil)
+ @cause = cause
+ @terms = cleanup_terms(terms)
+ @custom_explanation = custom_explanation
+
+ if cause == :dependency && @terms.length != 2
+ raise ArgumentError, "a dependency Incompatibility must have exactly two terms. Got #{@terms.inspect}"
+ end
+ end
+
+ def hash
+ cause.hash ^ terms.hash
+ end
+
+ def eql?(other)
+ cause.eql?(other.cause) &&
+ terms.eql?(other.terms)
+ end
+
+ def failure?
+ terms.empty? || (terms.length == 1 && Package.root?(terms[0].package) && terms[0].positive?)
+ end
+
+ def conflict?
+ ConflictCause === cause
+ end
+
+ # Returns all external incompatibilities in this incompatibility's
+ # derivation graph
+ def external_incompatibilities
+ if conflict?
+ [
+ cause.conflict,
+ cause.other
+ ].flat_map(&:external_incompatibilities)
+ else
+ [this]
+ end
+ end
+
+ def to_s
+ return @custom_explanation if @custom_explanation
+
+ case cause
+ when :root
+ "(root dependency)"
+ when :dependency
+ "#{terms[0].to_s(allow_every: true)} depends on #{terms[1].invert}"
+ when Bundler::PubGrub::Incompatibility::InvalidDependency
+ "#{terms[0].to_s(allow_every: true)} depends on unknown package #{cause.package}"
+ when Bundler::PubGrub::Incompatibility::NoVersions
+ "no versions satisfy #{cause.constraint}"
+ when Bundler::PubGrub::Incompatibility::ConflictCause
+ if failure?
+ "version solving has failed"
+ elsif terms.length == 1
+ term = terms[0]
+ if term.positive?
+ if term.constraint.any?
+ "#{term.package} cannot be used"
+ else
+ "#{term.to_s(allow_every: true)} cannot be used"
+ end
+ else
+ "#{term.invert} is required"
+ end
+ else
+ if terms.all?(&:positive?)
+ if terms.length == 2
+ "#{terms[0].to_s(allow_every: true)} is incompatible with #{terms[1]}"
+ else
+ "one of #{terms.map(&:to_s).join(" or ")} must be false"
+ end
+ elsif terms.all?(&:negative?)
+ if terms.length == 2
+ "either #{terms[0].invert} or #{terms[1].invert}"
+ else
+ "one of #{terms.map(&:invert).join(" or ")} must be true";
+ end
+ else
+ positive = terms.select(&:positive?)
+ negative = terms.select(&:negative?).map(&:invert)
+
+ if positive.length == 1
+ "#{positive[0].to_s(allow_every: true)} requires #{negative.join(" or ")}"
+ else
+ "if #{positive.join(" and ")} then #{negative.join(" or ")}"
+ end
+ end
+ end
+ else
+ raise "unhandled cause: #{cause.inspect}"
+ end
+ end
+
+ def inspect
+ "#<#{self.class} #{to_s}>"
+ end
+
+ def pretty_print(q)
+ q.group 2, "#<#{self.class}", ">" do
+ q.breakable
+ q.text to_s
+
+ q.breakable
+ q.text " caused by "
+ q.pp @cause
+ end
+ end
+
+ private
+
+ def cleanup_terms(terms)
+ terms.each do |term|
+ raise "#{term.inspect} must be a term" unless term.is_a?(Term)
+ end
+
+ if terms.length != 1 && ConflictCause === cause
+ terms = terms.reject do |term|
+ term.positive? && Package.root?(term.package)
+ end
+ end
+
+ # Optimized simple cases
+ return terms if terms.length <= 1
+ return terms if terms.length == 2 && terms[0].package != terms[1].package
+
+ terms.group_by(&:package).map do |package, common_terms|
+ common_terms.inject do |acc, term|
+ acc.intersect(term)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb
new file mode 100644
index 0000000000..efb9d3da16
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Bundler::PubGrub
+ class Package
+
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def inspect
+ "#<#{self.class} #{name.inspect}>"
+ end
+
+ def <=>(other)
+ name <=> other.name
+ end
+
+ ROOT = Package.new(:root)
+ ROOT_VERSION = 0
+
+ def self.root
+ ROOT
+ end
+
+ def self.root_version
+ ROOT_VERSION
+ end
+
+ def self.root?(package)
+ if package.respond_to?(:root?)
+ package.root?
+ else
+ package == root
+ end
+ end
+
+ def to_s
+ name.to_s
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb
new file mode 100644
index 0000000000..4c4b8ca844
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb
@@ -0,0 +1,121 @@
+require_relative 'assignment'
+
+module Bundler::PubGrub
+ class PartialSolution
+ attr_reader :assignments, :decisions
+ attr_reader :attempted_solutions
+
+ def initialize
+ reset!
+
+ @attempted_solutions = 1
+ @backtracking = false
+ end
+
+ def decision_level
+ @decisions.length
+ end
+
+ def relation(term)
+ package = term.package
+ return :overlap if !@terms.key?(package)
+
+ @relation_cache[package][term] ||=
+ @terms[package].relation(term)
+ end
+
+ def satisfies?(term)
+ relation(term) == :subset
+ end
+
+ def derive(term, cause)
+ add_assignment(Assignment.new(term, cause, decision_level, assignments.length))
+ end
+
+ def satisfier(term)
+ assignment =
+ @assignments_by[term.package].bsearch do |assignment_by|
+ @cumulative_assignments[assignment_by].satisfies?(term)
+ end
+
+ assignment || raise("#{term} unsatisfied")
+ end
+
+ # A list of unsatisfied terms
+ def unsatisfied
+ @required.keys.reject do |package|
+ @decisions.key?(package)
+ end.map do |package|
+ @terms[package]
+ end
+ end
+
+ def decide(package, version)
+ @attempted_solutions += 1 if @backtracking
+ @backtracking = false;
+
+ decisions[package] = version
+ assignment = Assignment.decision(package, version, decision_level, assignments.length)
+ add_assignment(assignment)
+ end
+
+ def backtrack(previous_level)
+ @backtracking = true
+
+ new_assignments = assignments.select do |assignment|
+ assignment.decision_level <= previous_level
+ end
+
+ new_decisions = Hash[decisions.first(previous_level)]
+
+ reset!
+
+ @decisions = new_decisions
+
+ new_assignments.each do |assignment|
+ add_assignment(assignment)
+ end
+ end
+
+ private
+
+ def reset!
+ # { Array<Assignment> }
+ @assignments = []
+
+ # { Package => Array<Assignment> }
+ @assignments_by = Hash.new { |h,k| h[k] = [] }
+ @cumulative_assignments = {}.compare_by_identity
+
+ # { Package => Package::Version }
+ @decisions = {}
+
+ # { Package => Term }
+ @terms = {}
+ @relation_cache = Hash.new { |h,k| h[k] = {} }
+
+ # { Package => Boolean }
+ @required = {}
+ end
+
+ def add_assignment(assignment)
+ term = assignment.term
+ package = term.package
+
+ @assignments << assignment
+ @assignments_by[package] << assignment
+
+ @required[package] = true if term.positive?
+
+ if @terms.key?(package)
+ old_term = @terms[package]
+ @terms[package] = old_term.intersect(term)
+ else
+ @terms[package] = term
+ end
+ @relation_cache[package].clear
+
+ @cumulative_assignments[assignment] = @terms[package]
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb
new file mode 100644
index 0000000000..245c23be22
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb
@@ -0,0 +1,45 @@
+module Bundler::PubGrub
+ module RubyGems
+ extend self
+
+ def requirement_to_range(requirement)
+ ranges = requirement.requirements.map do |(op, ver)|
+ case op
+ when "~>"
+ name = "~> #{ver}"
+ bump = ver.class.new(ver.bump.to_s + ".A")
+ VersionRange.new(name: name, min: ver, max: bump, include_min: true)
+ when ">"
+ VersionRange.new(min: ver)
+ when ">="
+ VersionRange.new(min: ver, include_min: true)
+ when "<"
+ VersionRange.new(max: ver)
+ when "<="
+ VersionRange.new(max: ver, include_max: true)
+ when "="
+ VersionRange.new(min: ver, max: ver, include_min: true, include_max: true)
+ when "!="
+ VersionRange.new(min: ver, max: ver, include_min: true, include_max: true).invert
+ else
+ raise "bad version specifier: #{op}"
+ end
+ end
+
+ ranges.inject(&:intersect)
+ end
+
+ def requirement_to_constraint(package, requirement)
+ Bundler::PubGrub::VersionConstraint.new(package, range: requirement_to_range(requirement))
+ end
+
+ def parse_range(dep)
+ requirement_to_range(Gem::Requirement.new(dep))
+ end
+
+ def parse_constraint(package, dep)
+ range = parse_range(dep)
+ Bundler::PubGrub::VersionConstraint.new(package, range: range)
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb
new file mode 100644
index 0000000000..961a7a7c0c
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb
@@ -0,0 +1,19 @@
+require_relative 'failure_writer'
+
+module Bundler::PubGrub
+ class SolveFailure < StandardError
+ attr_reader :incompatibility
+
+ def initialize(incompatibility)
+ @incompatibility = incompatibility
+ end
+
+ def to_s
+ "Could not find compatible versions\n\n#{explanation}"
+ end
+
+ def explanation
+ @explanation ||= FailureWriter.new(@incompatibility).write
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb
new file mode 100644
index 0000000000..4bf61461b2
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb
@@ -0,0 +1,60 @@
+require_relative 'package'
+require_relative 'version_constraint'
+require_relative 'incompatibility'
+require_relative 'basic_package_source'
+
+module Bundler::PubGrub
+ class StaticPackageSource < BasicPackageSource
+ class DSL
+ def initialize(packages, root_deps)
+ @packages = packages
+ @root_deps = root_deps
+ end
+
+ def root(deps:)
+ @root_deps.update(deps)
+ end
+
+ def add(name, version, deps: {})
+ version = Gem::Version.new(version)
+ @packages[name] ||= {}
+ raise ArgumentError, "#{name} #{version} declared twice" if @packages[name].key?(version)
+ @packages[name][version] = clean_deps(name, version, deps)
+ end
+
+ private
+
+ # Exclude redundant self-referencing dependencies
+ def clean_deps(name, version, deps)
+ deps.reject {|dep_name, req| name == dep_name && Bundler::PubGrub::RubyGems.parse_range(req).include?(version) }
+ end
+ end
+
+ def initialize
+ @root_deps = {}
+ @packages = {}
+
+ yield DSL.new(@packages, @root_deps)
+
+ super()
+ end
+
+ def all_versions_for(package)
+ @packages[package].keys
+ end
+
+ def root_dependencies
+ @root_deps
+ end
+
+ def dependencies_for(package, version)
+ @packages[package][version]
+ end
+
+ def parse_dependency(package, dependency)
+ return false unless @packages.key?(package)
+
+ Bundler::PubGrub::RubyGems.parse_constraint(package, dependency)
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb
new file mode 100644
index 0000000000..1d0f763378
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb
@@ -0,0 +1,105 @@
+module Bundler::PubGrub
+ class Term
+ attr_reader :package, :constraint, :positive
+
+ def initialize(constraint, positive)
+ @constraint = constraint
+ @package = @constraint.package
+ @positive = positive
+ end
+
+ def to_s(allow_every: false)
+ if positive
+ @constraint.to_s(allow_every: allow_every)
+ else
+ "not #{@constraint}"
+ end
+ end
+
+ def hash
+ constraint.hash ^ positive.hash
+ end
+
+ def eql?(other)
+ positive == other.positive &&
+ constraint.eql?(other.constraint)
+ end
+
+ def invert
+ self.class.new(@constraint, !@positive)
+ end
+ alias_method :inverse, :invert
+
+ def intersect(other)
+ raise ArgumentError, "packages must match" if package != other.package
+
+ if positive? && other.positive?
+ self.class.new(constraint.intersect(other.constraint), true)
+ elsif negative? && other.negative?
+ self.class.new(constraint.union(other.constraint), false)
+ else
+ positive = positive? ? self : other
+ negative = negative? ? self : other
+ self.class.new(positive.constraint.intersect(negative.constraint.invert), true)
+ end
+ end
+
+ def difference(other)
+ intersect(other.invert)
+ end
+
+ def relation(other)
+ if positive? && other.positive?
+ constraint.relation(other.constraint)
+ elsif negative? && other.positive?
+ if constraint.allows_all?(other.constraint)
+ :disjoint
+ else
+ :overlap
+ end
+ elsif positive? && other.negative?
+ if !other.constraint.allows_any?(constraint)
+ :subset
+ elsif other.constraint.allows_all?(constraint)
+ :disjoint
+ else
+ :overlap
+ end
+ elsif negative? && other.negative?
+ if constraint.allows_all?(other.constraint)
+ :subset
+ else
+ :overlap
+ end
+ else
+ raise
+ end
+ end
+
+ def normalized_constraint
+ @normalized_constraint ||= positive ? constraint : constraint.invert
+ end
+
+ def satisfies?(other)
+ raise ArgumentError, "packages must match" unless package == other.package
+
+ relation(other) == :subset
+ end
+
+ def positive?
+ @positive
+ end
+
+ def negative?
+ !positive?
+ end
+
+ def empty?
+ @empty ||= normalized_constraint.empty?
+ end
+
+ def inspect
+ "#<#{self.class} #{self}>"
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb
new file mode 100644
index 0000000000..d7984b3863
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb
@@ -0,0 +1,3 @@
+module Bundler::PubGrub
+ VERSION = "0.5.0"
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb
new file mode 100644
index 0000000000..b71f3eaf53
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb
@@ -0,0 +1,129 @@
+require_relative 'version_range'
+
+module Bundler::PubGrub
+ class VersionConstraint
+ attr_reader :package, :range
+
+ # @param package [Bundler::PubGrub::Package]
+ # @param range [Bundler::PubGrub::VersionRange]
+ def initialize(package, range: nil)
+ @package = package
+ @range = range
+ end
+
+ def hash
+ package.hash ^ range.hash
+ end
+
+ def ==(other)
+ package == other.package &&
+ range == other.range
+ end
+
+ def eql?(other)
+ package.eql?(other.package) &&
+ range.eql?(other.range)
+ end
+
+ class << self
+ def exact(package, version)
+ range = VersionRange.new(min: version, max: version, include_min: true, include_max: true)
+ new(package, range: range)
+ end
+
+ def any(package)
+ new(package, range: VersionRange.any)
+ end
+
+ def empty(package)
+ new(package, range: VersionRange.empty)
+ end
+ end
+
+ def intersect(other)
+ unless package == other.package
+ raise ArgumentError, "Can only intersect between VersionConstraint of the same package"
+ end
+
+ self.class.new(package, range: range.intersect(other.range))
+ end
+
+ def union(other)
+ unless package == other.package
+ raise ArgumentError, "Can only intersect between VersionConstraint of the same package"
+ end
+
+ self.class.new(package, range: range.union(other.range))
+ end
+
+ def invert
+ new_range = range.invert
+ self.class.new(package, range: new_range)
+ end
+
+ def difference(other)
+ intersect(other.invert)
+ end
+
+ def allows_all?(other)
+ range.allows_all?(other.range)
+ end
+
+ def allows_any?(other)
+ range.intersects?(other.range)
+ end
+
+ def subset?(other)
+ other.allows_all?(self)
+ end
+
+ def overlap?(other)
+ other.allows_any?(self)
+ end
+
+ def disjoint?(other)
+ !overlap?(other)
+ end
+
+ def relation(other)
+ if subset?(other)
+ :subset
+ elsif overlap?(other)
+ :overlap
+ else
+ :disjoint
+ end
+ end
+
+ def to_s(allow_every: false)
+ if Package.root?(package)
+ package.to_s
+ elsif allow_every && any?
+ "every version of #{package}"
+ else
+ "#{package} #{constraint_string}"
+ end
+ end
+
+ def constraint_string
+ if any?
+ ">= 0"
+ else
+ range.to_s
+ end
+ end
+
+ def empty?
+ range.empty?
+ end
+
+ # Does this match every version of the package
+ def any?
+ range.any?
+ end
+
+ def inspect
+ "#<#{self.class} #{self}>"
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb
new file mode 100644
index 0000000000..8d73c3f7b5
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb
@@ -0,0 +1,411 @@
+# frozen_string_literal: true
+
+module Bundler::PubGrub
+ class VersionRange
+ attr_reader :min, :max, :include_min, :include_max
+
+ alias_method :include_min?, :include_min
+ alias_method :include_max?, :include_max
+
+ class Empty < VersionRange
+ undef_method :min, :max
+ undef_method :include_min, :include_min?
+ undef_method :include_max, :include_max?
+
+ def initialize
+ end
+
+ def empty?
+ true
+ end
+
+ def eql?(other)
+ other.empty?
+ end
+
+ def hash
+ [].hash
+ end
+
+ def intersects?(_)
+ false
+ end
+
+ def intersect(other)
+ self
+ end
+
+ def allows_all?(other)
+ other.empty?
+ end
+
+ def include?(_)
+ false
+ end
+
+ def any?
+ false
+ end
+
+ def to_s
+ "(no versions)"
+ end
+
+ def ==(other)
+ other.class == self.class
+ end
+
+ def invert
+ VersionRange.any
+ end
+
+ def select_versions(_)
+ []
+ end
+ end
+
+ EMPTY = Empty.new
+ Empty.singleton_class.undef_method(:new)
+
+ def self.empty
+ EMPTY
+ end
+
+ def self.any
+ new
+ end
+
+ def initialize(min: nil, max: nil, include_min: false, include_max: false, name: nil)
+ @min = min
+ @max = max
+ @include_min = include_min
+ @include_max = include_max
+ @name = name
+ end
+
+ def hash
+ @hash ||= min.hash ^ max.hash ^ include_min.hash ^ include_max.hash
+ end
+
+ def eql?(other)
+ if other.is_a?(VersionRange)
+ !other.empty? &&
+ min.eql?(other.min) &&
+ max.eql?(other.max) &&
+ include_min.eql?(other.include_min) &&
+ include_max.eql?(other.include_max)
+ else
+ ranges.eql?(other.ranges)
+ end
+ end
+
+ def ranges
+ [self]
+ end
+
+ def include?(version)
+ compare_version(version) == 0
+ end
+
+ # Partitions passed versions into [lower, within, higher]
+ #
+ # versions must be sorted
+ def partition_versions(versions)
+ min_index =
+ if !min || versions.empty?
+ 0
+ elsif include_min?
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] >= min }
+ else
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] > min }
+ end
+
+ lower = versions.slice(0, min_index)
+ versions = versions.slice(min_index, versions.size)
+
+ max_index =
+ if !max || versions.empty?
+ versions.size
+ elsif include_max?
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] > max }
+ else
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] >= max }
+ end
+
+ [
+ lower,
+ versions.slice(0, max_index),
+ versions.slice(max_index, versions.size)
+ ]
+ end
+
+ # Returns versions which are included by this range.
+ #
+ # versions must be sorted
+ def select_versions(versions)
+ return versions if any?
+
+ partition_versions(versions)[1]
+ end
+
+ def compare_version(version)
+ if min
+ case version <=> min
+ when -1
+ return -1
+ when 0
+ return -1 if !include_min
+ when 1
+ end
+ end
+
+ if max
+ case version <=> max
+ when -1
+ when 0
+ return 1 if !include_max
+ when 1
+ return 1
+ end
+ end
+
+ 0
+ end
+
+ def strictly_lower?(other)
+ return false if !max || !other.min
+
+ case max <=> other.min
+ when 0
+ !include_max || !other.include_min
+ when -1
+ true
+ when 1
+ false
+ end
+ end
+
+ def strictly_higher?(other)
+ other.strictly_lower?(self)
+ end
+
+ def intersects?(other)
+ return false if other.empty?
+ return other.intersects?(self) if other.is_a?(VersionUnion)
+ !strictly_lower?(other) && !strictly_higher?(other)
+ end
+ alias_method :allows_any?, :intersects?
+
+ def intersect(other)
+ return other if other.empty?
+ return other.intersect(self) if other.is_a?(VersionUnion)
+
+ min_range =
+ if !min
+ other
+ elsif !other.min
+ self
+ else
+ case min <=> other.min
+ when 0
+ include_min ? other : self
+ when -1
+ other
+ when 1
+ self
+ end
+ end
+
+ max_range =
+ if !max
+ other
+ elsif !other.max
+ self
+ else
+ case max <=> other.max
+ when 0
+ include_max ? other : self
+ when -1
+ self
+ when 1
+ other
+ end
+ end
+
+ if !min_range.equal?(max_range) && min_range.min && max_range.max
+ case min_range.min <=> max_range.max
+ when -1
+ when 0
+ if !min_range.include_min || !max_range.include_max
+ return EMPTY
+ end
+ when 1
+ return EMPTY
+ end
+ end
+
+ VersionRange.new(
+ min: min_range.min,
+ include_min: min_range.include_min,
+ max: max_range.max,
+ include_max: max_range.include_max
+ )
+ end
+
+ # The span covered by two ranges
+ #
+ # If self and other are contiguous, this builds a union of the two ranges.
+ # (if they aren't you are probably calling the wrong method)
+ def span(other)
+ return self if other.empty?
+
+ min_range =
+ if !min
+ self
+ elsif !other.min
+ other
+ else
+ case min <=> other.min
+ when 0
+ include_min ? self : other
+ when -1
+ self
+ when 1
+ other
+ end
+ end
+
+ max_range =
+ if !max
+ self
+ elsif !other.max
+ other
+ else
+ case max <=> other.max
+ when 0
+ include_max ? self : other
+ when -1
+ other
+ when 1
+ self
+ end
+ end
+
+ VersionRange.new(
+ min: min_range.min,
+ include_min: min_range.include_min,
+ max: max_range.max,
+ include_max: max_range.include_max
+ )
+ end
+
+ def union(other)
+ return other.union(self) if other.is_a?(VersionUnion)
+
+ if contiguous_to?(other)
+ span(other)
+ else
+ VersionUnion.union([self, other])
+ end
+ end
+
+ def contiguous_to?(other)
+ return false if other.empty?
+
+ intersects?(other) ||
+ (min == other.max && (include_min || other.include_max)) ||
+ (max == other.min && (include_max || other.include_min))
+ end
+
+ def allows_all?(other)
+ return true if other.empty?
+
+ if other.is_a?(VersionUnion)
+ return VersionUnion.new([self]).allows_all?(other)
+ end
+
+ return false if max && !other.max
+ return false if min && !other.min
+
+ if min
+ case min <=> other.min
+ when -1
+ when 0
+ return false if !include_min && other.include_min
+ when 1
+ return false
+ end
+ end
+
+ if max
+ case max <=> other.max
+ when -1
+ return false
+ when 0
+ return false if !include_max && other.include_max
+ when 1
+ end
+ end
+
+ true
+ end
+
+ def any?
+ !min && !max
+ end
+
+ def empty?
+ false
+ end
+
+ def to_s
+ @name ||= constraints.join(", ")
+ end
+
+ def inspect
+ "#<#{self.class} #{to_s}>"
+ end
+
+ def upper_invert
+ return self.class.empty unless max
+
+ VersionRange.new(min: max, include_min: !include_max)
+ end
+
+ def invert
+ return self.class.empty if any?
+
+ low = VersionRange.new(max: min, include_max: !include_min)
+ high = VersionRange.new(min: max, include_min: !include_max)
+
+ if !min
+ high
+ elsif !max
+ low
+ else
+ low.union(high)
+ end
+ end
+
+ def ==(other)
+ self.class == other.class &&
+ min == other.min &&
+ max == other.max &&
+ include_min == other.include_min &&
+ include_max == other.include_max
+ end
+
+ private
+
+ def constraints
+ return ["any"] if any?
+ return ["= #{min}"] if min.to_s == max.to_s
+
+ c = []
+ c << "#{include_min ? ">=" : ">"} #{min}" if min
+ c << "#{include_max ? "<=" : "<"} #{max}" if max
+ c
+ end
+
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb
new file mode 100644
index 0000000000..4caf6b355b
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb
@@ -0,0 +1,248 @@
+require_relative 'partial_solution'
+require_relative 'term'
+require_relative 'incompatibility'
+require_relative 'solve_failure'
+
+module Bundler::PubGrub
+ class VersionSolver
+ attr_reader :logger
+ attr_reader :source
+ attr_reader :solution
+
+ def initialize(source:, root: Package.root, logger: Bundler::PubGrub.logger)
+ @logger = logger
+
+ @source = source
+
+ # { package => [incompatibility, ...]}
+ @incompatibilities = Hash.new do |h, k|
+ h[k] = []
+ end
+
+ @seen_incompatibilities = {}
+
+ @solution = PartialSolution.new
+
+ add_incompatibility Incompatibility.new([
+ Term.new(VersionConstraint.any(root), false)
+ ], cause: :root)
+
+ propagate(root)
+ end
+
+ def solved?
+ solution.unsatisfied.empty?
+ end
+
+ # Returns true if there is more work to be done, false otherwise
+ def work
+ return false if solved?
+
+ next_package = choose_package_version
+ propagate(next_package)
+
+ if solved?
+ logger.info { "Solution found after #{solution.attempted_solutions} attempts:" }
+ solution.decisions.each do |package, version|
+ next if Package.root?(package)
+ logger.info { "* #{package} #{version}" }
+ end
+
+ false
+ else
+ true
+ end
+ end
+
+ def solve
+ work until solved?
+
+ solution.decisions
+ end
+
+ alias_method :result, :solve
+
+ private
+
+ def propagate(initial_package)
+ changed = [initial_package]
+ while package = changed.shift
+ @incompatibilities[package].reverse_each do |incompatibility|
+ result = propagate_incompatibility(incompatibility)
+ if result == :conflict
+ root_cause = resolve_conflict(incompatibility)
+ changed.clear
+ changed << propagate_incompatibility(root_cause)
+ elsif result # should be a Package
+ changed << result
+ end
+ end
+ changed.uniq!
+ end
+ end
+
+ def propagate_incompatibility(incompatibility)
+ unsatisfied = nil
+ incompatibility.terms.each do |term|
+ relation = solution.relation(term)
+ if relation == :disjoint
+ return nil
+ elsif relation == :overlap
+ # If more than one term is inconclusive, we can't deduce anything
+ return nil if unsatisfied
+ unsatisfied = term
+ end
+ end
+
+ if !unsatisfied
+ return :conflict
+ end
+
+ logger.debug { "derived: #{unsatisfied.invert}" }
+
+ solution.derive(unsatisfied.invert, incompatibility)
+
+ unsatisfied.package
+ end
+
+ def next_package_to_try
+ solution.unsatisfied.min_by do |term|
+ package = term.package
+ range = term.constraint.range
+ matching_versions = source.versions_for(package, range)
+ higher_versions = source.versions_for(package, range.upper_invert)
+
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
+ end.package
+ end
+
+ def choose_package_version
+ if solution.unsatisfied.empty?
+ logger.info "No packages unsatisfied. Solving complete!"
+ return nil
+ end
+
+ package = next_package_to_try
+ unsatisfied_term = solution.unsatisfied.find { |t| t.package == package }
+ version = source.versions_for(package, unsatisfied_term.constraint.range).first
+ logger.debug { "attempting #{package} #{version}" }
+
+ if version.nil?
+ add_incompatibility source.no_versions_incompatibility_for(package, unsatisfied_term)
+ return package
+ end
+
+ conflict = false
+
+ source.incompatibilities_for(package, version).each do |incompatibility|
+ if @seen_incompatibilities.include?(incompatibility)
+ logger.debug { "knew: #{incompatibility}" }
+ next
+ end
+ @seen_incompatibilities[incompatibility] = true
+
+ add_incompatibility incompatibility
+
+ conflict ||= incompatibility.terms.all? do |term|
+ term.package == package || solution.satisfies?(term)
+ end
+ end
+
+ unless conflict
+ logger.info { "selected #{package} #{version}" }
+
+ solution.decide(package, version)
+ else
+ logger.info { "conflict: #{conflict.inspect}" }
+ end
+
+ package
+ end
+
+ def resolve_conflict(incompatibility)
+ logger.info { "conflict: #{incompatibility}" }
+
+ new_incompatibility = nil
+
+ while !incompatibility.failure?
+ most_recent_term = nil
+ most_recent_satisfier = nil
+ difference = nil
+
+ previous_level = 1
+
+ incompatibility.terms.each do |term|
+ satisfier = solution.satisfier(term)
+
+ if most_recent_satisfier.nil?
+ most_recent_term = term
+ most_recent_satisfier = satisfier
+ elsif most_recent_satisfier.index < satisfier.index
+ previous_level = [previous_level, most_recent_satisfier.decision_level].max
+ most_recent_term = term
+ most_recent_satisfier = satisfier
+ difference = nil
+ else
+ previous_level = [previous_level, satisfier.decision_level].max
+ end
+
+ if most_recent_term == term
+ difference = most_recent_satisfier.term.difference(most_recent_term)
+ if difference.empty?
+ difference = nil
+ else
+ difference_satisfier = solution.satisfier(difference.inverse)
+ previous_level = [previous_level, difference_satisfier.decision_level].max
+ end
+ end
+ end
+
+ if previous_level < most_recent_satisfier.decision_level ||
+ most_recent_satisfier.decision?
+
+ logger.info { "backtracking to #{previous_level}" }
+ solution.backtrack(previous_level)
+
+ if new_incompatibility
+ add_incompatibility(new_incompatibility)
+ end
+
+ return incompatibility
+ end
+
+ new_terms = []
+ new_terms += incompatibility.terms - [most_recent_term]
+ new_terms += most_recent_satisfier.cause.terms.reject { |term|
+ term.package == most_recent_satisfier.term.package
+ }
+ if difference
+ new_terms << difference.invert
+ end
+
+ new_incompatibility = Incompatibility.new(new_terms, cause: Incompatibility::ConflictCause.new(incompatibility, most_recent_satisfier.cause))
+
+ if incompatibility.to_s == new_incompatibility.to_s
+ logger.info { "!! failed to resolve conflicts, this shouldn't have happened" }
+ break
+ end
+
+ incompatibility = new_incompatibility
+
+ partially = difference ? " partially" : ""
+ logger.info { "! #{most_recent_term} is#{partially} satisfied by #{most_recent_satisfier.term}" }
+ logger.info { "! which is caused by #{most_recent_satisfier.cause}" }
+ logger.info { "! thus #{incompatibility}" }
+ end
+
+ raise SolveFailure.new(incompatibility)
+ end
+
+ def add_incompatibility(incompatibility)
+ logger.debug { "fact: #{incompatibility}" }
+ incompatibility.terms.each do |term|
+ package = term.package
+ @incompatibilities[package] << incompatibility
+ end
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb
new file mode 100644
index 0000000000..bbc10c3804
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb
@@ -0,0 +1,178 @@
+# frozen_string_literal: true
+
+module Bundler::PubGrub
+ class VersionUnion
+ attr_reader :ranges
+
+ def self.normalize_ranges(ranges)
+ ranges = ranges.flat_map do |range|
+ range.ranges
+ end
+
+ ranges.reject!(&:empty?)
+
+ return [] if ranges.empty?
+
+ mins, ranges = ranges.partition { |r| !r.min }
+ original_ranges = mins + ranges.sort_by { |r| [r.min, r.include_min ? 0 : 1] }
+ ranges = [original_ranges.shift]
+ original_ranges.each do |range|
+ if ranges.last.contiguous_to?(range)
+ ranges << ranges.pop.span(range)
+ else
+ ranges << range
+ end
+ end
+
+ ranges
+ end
+
+ def self.union(ranges, normalize: true)
+ ranges = normalize_ranges(ranges) if normalize
+
+ if ranges.size == 0
+ VersionRange.empty
+ elsif ranges.size == 1
+ ranges[0]
+ else
+ new(ranges)
+ end
+ end
+
+ def initialize(ranges)
+ raise ArgumentError unless ranges.all? { |r| r.instance_of?(VersionRange) }
+ @ranges = ranges
+ end
+
+ def hash
+ ranges.hash
+ end
+
+ def eql?(other)
+ ranges.eql?(other.ranges)
+ end
+
+ def include?(version)
+ !!ranges.bsearch {|r| r.compare_version(version) }
+ end
+
+ def select_versions(all_versions)
+ versions = []
+ ranges.inject(all_versions) do |acc, range|
+ _, matching, higher = range.partition_versions(acc)
+ versions.concat matching
+ higher
+ end
+ versions
+ end
+
+ def intersects?(other)
+ my_ranges = ranges.dup
+ other_ranges = other.ranges.dup
+
+ my_range = my_ranges.shift
+ other_range = other_ranges.shift
+ while my_range && other_range
+ if my_range.intersects?(other_range)
+ return true
+ end
+
+ if !my_range.max || other_range.empty? || (other_range.max && other_range.max < my_range.max)
+ other_range = other_ranges.shift
+ else
+ my_range = my_ranges.shift
+ end
+ end
+ end
+ alias_method :allows_any?, :intersects?
+
+ def allows_all?(other)
+ my_ranges = ranges.dup
+
+ my_range = my_ranges.shift
+
+ other.ranges.all? do |other_range|
+ while my_range
+ break if my_range.allows_all?(other_range)
+ my_range = my_ranges.shift
+ end
+
+ !!my_range
+ end
+ end
+
+ def empty?
+ false
+ end
+
+ def any?
+ false
+ end
+
+ def intersect(other)
+ my_ranges = ranges.dup
+ other_ranges = other.ranges.dup
+ new_ranges = []
+
+ my_range = my_ranges.shift
+ other_range = other_ranges.shift
+ while my_range && other_range
+ new_ranges << my_range.intersect(other_range)
+
+ if !my_range.max || other_range.empty? || (other_range.max && other_range.max < my_range.max)
+ other_range = other_ranges.shift
+ else
+ my_range = my_ranges.shift
+ end
+ end
+ new_ranges.reject!(&:empty?)
+ VersionUnion.union(new_ranges, normalize: false)
+ end
+
+ def upper_invert
+ ranges.last.upper_invert
+ end
+
+ def invert
+ ranges.map(&:invert).inject(:intersect)
+ end
+
+ def union(other)
+ VersionUnion.union([self, other])
+ end
+
+ def to_s
+ output = []
+
+ ranges = self.ranges.dup
+ while !ranges.empty?
+ ne = []
+ range = ranges.shift
+ while !ranges.empty? && ranges[0].min.to_s == range.max.to_s
+ ne << range.max
+ range = range.span(ranges.shift)
+ end
+
+ ne.map! {|x| "!= #{x}" }
+ if ne.empty?
+ output << range.to_s
+ elsif range.any?
+ output << ne.join(', ')
+ else
+ output << "#{range}, #{ne.join(', ')}"
+ end
+ end
+
+ output.join(" OR ")
+ end
+
+ def inspect
+ "#<#{self.class} #{to_s}>"
+ end
+
+ def ==(other)
+ self.class == other.class &&
+ self.ranges == other.ranges
+ end
+ end
+end
diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb
index de9323b2db..de9b3b4c86 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions.rb
@@ -161,6 +161,8 @@ class Bundler::Thor
# to the block you provide. The path is set back to the previous path when
# the method exits.
#
+ # Returns the value yielded by the block.
+ #
# ==== Parameters
# dir<String>:: the directory to move to.
# config<Hash>:: give :verbose => true to log and use padding.
@@ -179,16 +181,18 @@ class Bundler::Thor
FileUtils.mkdir_p(destination_root)
end
+ result = nil
if pretend
# In pretend mode, just yield down to the block
- block.arity == 1 ? yield(destination_root) : yield
+ result = block.arity == 1 ? yield(destination_root) : yield
else
require "fileutils"
- FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
+ FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield }
end
@destination_stack.pop
shell.padding -= 1 if verbose
+ result
end
# Goes to the root and execute the given block.
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 90a8d2e847..bf2a737c84 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
@@ -210,9 +210,9 @@ class Bundler::Thor
#
# ==== Examples
#
- # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
+ # inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " filter_parameter :password\n"
#
- # inject_into_class "app/controllers/application_controller.rb", ApplicationController do
+ # inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do
# " filter_parameter :password\n"
# end
#
@@ -233,9 +233,9 @@ class Bundler::Thor
#
# ==== Examples
#
- # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper, " def help; 'help'; end\n"
+ # inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", " def help; 'help'; end\n"
#
- # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper do
+ # inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper" do
# " def help; 'help'; end\n"
# end
#
@@ -252,7 +252,7 @@ class Bundler::Thor
# flag<Regexp|String>:: the regexp or string to be replaced
# replacement<String>:: the replacement, can be also given as a block
# config<Hash>:: give :verbose => false to not log the status, and
- # :force => true, to force the replacement regardless of runner behavior.
+ # :force => true, to force the replacement regardles of runner behavior.
#
# ==== Example
#
@@ -331,7 +331,7 @@ class Bundler::Thor
path = File.expand_path(path, destination_root)
say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
- if !options[:pretend] && File.exist?(path)
+ if !options[:pretend] && (File.exist?(path) || File.symlink?(path))
require "fileutils"
::FileUtils.rm_rf(path)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
index 09ce0864f0..bf013307f1 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
@@ -106,12 +106,11 @@ class Bundler::Thor
# Adds the content to the file.
#
def replace!(regexp, string, force)
- return if pretend?
content = File.read(destination)
if force || !content.include?(replacement)
success = content.gsub!(regexp, string)
- File.open(destination, "wb") { |file| file.write(content) }
+ File.open(destination, "wb") { |file| file.write(content) } unless pretend?
success
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
index c167aa33b8..3c4483e5dd 100644
--- a/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
+++ b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
@@ -28,6 +28,12 @@ class Bundler::Thor
super(convert_key(key))
end
+ def except(*keys)
+ dup.tap do |hash|
+ keys.each { |key| hash.delete(convert_key(key)) }
+ end
+ end
+
def fetch(key, *args)
super(convert_key(key), *args)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb
index 7d57129b83..03f2ce85bb 100644
--- a/lib/bundler/vendor/thor/lib/thor/error.rb
+++ b/lib/bundler/vendor/thor/lib/thor/error.rb
@@ -102,9 +102,14 @@ class Bundler::Thor
end
if Correctable
- DidYouMean::SPELL_CHECKERS.merge!(
- 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
- 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
- )
+ if DidYouMean.respond_to?(:correct_error)
+ DidYouMean.correct_error(Bundler::Thor::UndefinedCommandError, UndefinedCommandError::SpellChecker)
+ DidYouMean.correct_error(Bundler::Thor::UnknownArgumentError, UnknownArgumentError::SpellChecker)
+ else
+ DidYouMean::SPELL_CHECKERS.merge!(
+ 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
+ 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
+ )
+ end
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index 3a8927d09c..5bd97aba6f 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
@@ -45,6 +45,7 @@ class Bundler::Thor
@switches = {}
@extra = []
@stopped_parsing_after_extra_index = nil
+ @is_treated_as_value = false
options.each do |option|
@switches[option.switch_name] = option
@@ -74,8 +75,19 @@ class Bundler::Thor
end
end
+ def shift
+ @is_treated_as_value = false
+ super
+ end
+
+ def unshift(arg, is_value: false)
+ @is_treated_as_value = is_value
+ super(arg)
+ end
+
def parse(args) # rubocop:disable MethodLength
@pile = args.dup
+ @is_treated_as_value = false
@parsing_options = true
while peek
@@ -88,7 +100,10 @@ class Bundler::Thor
when SHORT_SQ_RE
unshift($1.split("").map { |f| "-#{f}" })
next
- when EQ_RE, SHORT_NUM
+ when EQ_RE
+ unshift($2, is_value: true)
+ switch = $1
+ when SHORT_NUM
unshift($2)
switch = $1
when LONG_RE, SHORT_RE
@@ -148,6 +163,7 @@ class Bundler::Thor
# Two booleans are returned. The first is true if the current value
# starts with a hyphen; the second is true if it is a registered switch.
def current_is_switch?
+ return [false, false] if @is_treated_as_value
case peek
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
[true, switch?($1)]
@@ -159,6 +175,7 @@ class Bundler::Thor
end
def current_is_switch_formatted?
+ return false if @is_treated_as_value
case peek
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
true
@@ -168,6 +185,7 @@ class Bundler::Thor
end
def current_is_value?
+ return true if @is_treated_as_value
peek && (!parsing_options? || super)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/shell.rb b/lib/bundler/vendor/thor/lib/thor/shell.rb
index e36fa472d6..a4137d1bde 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell.rb
@@ -21,7 +21,7 @@ class Bundler::Thor
end
module Shell
- SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
+ SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_error, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
attr_writer :shell
autoload :Basic, File.expand_path("shell/basic", __dir__)
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index 2dddd4a53a..ef97d52ae7 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
@@ -103,6 +103,23 @@ class Bundler::Thor
stdout.flush
end
+ # Say (print) an error to the user. If the sentence ends with a whitespace
+ # or tab character, a new line is not appended (print + flush). Otherwise
+ # are passed straight to puts (behavior got from Highline).
+ #
+ # ==== Example
+ # say_error("error: something went wrong")
+ #
+ def say_error(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
+ return if quiet?
+
+ buffer = prepare_message(message, *color)
+ buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
+
+ stderr.print(buffer)
+ stderr.flush
+ end
+
# Say a status with the given color and appends the message. Since this
# method is used frequently by actions, it allows nil or false to be given
# in log_status, avoiding the message from being shown. If a Symbol is
@@ -111,13 +128,14 @@ class Bundler::Thor
def say_status(status, message, log_status = true)
return if quiet? || log_status == false
spaces = " " * (padding + 1)
- color = log_status.is_a?(Symbol) ? log_status : :green
-
status = status.to_s.rjust(12)
+ margin = " " * status.length + spaces
+
+ color = log_status.is_a?(Symbol) ? log_status : :green
status = set_color status, color, true if color
- buffer = "#{status}#{spaces}#{message}"
- buffer = "#{buffer}\n" unless buffer.end_with?("\n")
+ message = message.to_s.chomp.gsub(/(?<!\A)^/, margin)
+ buffer = "#{status}#{spaces}#{message}\n"
stdout.print(buffer)
stdout.flush
@@ -407,7 +425,7 @@ class Bundler::Thor
end
def unix?
- RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris)/i
end
def truncate(string, width)
diff --git a/lib/bundler/vendor/thor/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb
index ddf4d21b90..d2572a4249 100644
--- a/lib/bundler/vendor/thor/lib/thor/util.rb
+++ b/lib/bundler/vendor/thor/lib/thor/util.rb
@@ -211,7 +211,7 @@ class Bundler::Thor
#
def globs_for(path)
path = escape_globs(path)
- ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"]
+ ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/**/*.thor"]
end
# Return the path to the ruby interpreter taking into account multiple
diff --git a/lib/bundler/vendor/thor/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb
index a3efa9f762..48a4788b3b 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.1.0"
+ VERSION = "1.2.1"
end
diff --git a/lib/bundler/vendor/tmpdir/lib/tmpdir.rb b/lib/bundler/vendor/tmpdir/lib/tmpdir.rb
deleted file mode 100644
index 70d43e0c6b..0000000000
--- a/lib/bundler/vendor/tmpdir/lib/tmpdir.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-# 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/lib/tsort.rb b/lib/bundler/vendor/tsort/lib/tsort.rb
new file mode 100644
index 0000000000..4a0e1a4e25
--- /dev/null
+++ b/lib/bundler/vendor/tsort/lib/tsort.rb
@@ -0,0 +1,452 @@
+# frozen_string_literal: true
+
+#--
+# tsort.rb - provides a module for topological sorting and strongly connected components.
+#++
+#
+
+#
+# Bundler::TSort implements topological sorting using Tarjan's algorithm for
+# strongly connected components.
+#
+# Bundler::TSort is designed to be able to be used with any object which can be
+# interpreted as a directed graph.
+#
+# Bundler::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
+# Bundler::TSort uses Hash internally.
+#
+# == A Simple Example
+#
+# The following example demonstrates how to mix the Bundler::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 'bundler/vendor/tsort/lib/tsort'
+#
+# class Hash
+# include Bundler::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 'bundler/vendor/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 Bundler::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 Bundler::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::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, Bundler::TSort::Cyclic is raised.
+ #
+ # class G
+ # include Bundler::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 Bundler::TSort::Cyclic
+ #
+ def tsort
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ Bundler::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, Bundler::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 Bundler::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 Bundler::TSort.tsort(each_node, each_child) # raises Bundler::TSort::Cyclic
+ #
+ def self.tsort(each_node, each_child)
+ tsort_each(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #tsort method.
+ # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
+ # modification of _obj_ during the iteration may lead to unexpected results.
+ #
+ # #tsort_each returns +nil+.
+ # If there is a cycle, Bundler::TSort::Cyclic is raised.
+ #
+ # class G
+ # include Bundler::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)
+ Bundler::TSort.tsort_each(each_node, each_child, &block)
+ end
+
+ # The iterator version of the Bundler::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) }
+ # Bundler::TSort.tsort_each(each_node, each_child) {|n| p n }
+ # #=> 4
+ # # 2
+ # # 3
+ # # 1
+ #
+ def self.tsort_each(each_node, each_child) # :yields: node
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ each_strongly_connected_component(each_node, each_child) {|component|
+ if component.size == 1
+ yield component.first
+ else
+ raise Cyclic.new("topological sort failed: #{component.inspect}")
+ end
+ }
+ end
+
+ # Returns strongly connected components as an array of arrays of nodes.
+ # The array is sorted from children to parents.
+ # Each elements of the array represents a strongly connected component.
+ #
+ # class G
+ # include Bundler::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)
+ Bundler::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 Bundler::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 Bundler::TSort.strongly_connected_components(each_node, each_child)
+ # #=> [[4], [2, 3], [1]]
+ #
+ def self.strongly_connected_components(each_node, each_child)
+ each_strongly_connected_component(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #strongly_connected_components method.
+ # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
+ # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
+ # modification of _obj_ during the iteration may lead to unexpected results.
+ #
+ # #each_strongly_connected_component returns +nil+.
+ #
+ # class G
+ # include Bundler::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)
+ Bundler::TSort.each_strongly_connected_component(each_node, each_child, &block)
+ end
+
+ # The iterator version of the Bundler::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) }
+ # Bundler::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) }
+ # Bundler::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
+ # #=> [4]
+ # # [2, 3]
+ # # [1]
+ #
+ def self.each_strongly_connected_component(each_node, each_child) # :yields: nodes
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ id_map = {}
+ stack = []
+ each_node.call {|node|
+ unless id_map.include? node
+ each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
+ yield c
+ }
+ end
+ }
+ nil
+ end
+
+ # Iterates over strongly connected component in the subgraph reachable from
+ # _node_.
+ #
+ # Return value is unspecified.
+ #
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
+ #
+ # class G
+ # include Bundler::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
+ Bundler::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.
+ #
+ # #Bundler::TSort.each_strongly_connected_component_from is a class method and
+ # it doesn't need a class to represent a graph which includes Bundler::TSort.
+ #
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
+ # Bundler::TSort.each_strongly_connected_component_from(1, each_child) {|scc|
+ # p scc
+ # }
+ # #=> [4]
+ # # [2, 3]
+ # # [1]
+ #
+ def self.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
+ return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
+
+ minimum_id = node_id = id_map[node] = id_map.size
+ stack_length = stack.length
+ stack << node
+
+ each_child.call(node) {|child|
+ if id_map.include? child
+ child_id = id_map[child]
+ minimum_id = child_id if child_id && child_id < minimum_id
+ else
+ sub_minimum_id =
+ each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
+ yield c
+ }
+ minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
+ end
+ }
+
+ if node_id == minimum_id
+ component = stack.slice!(stack_length .. -1)
+ component.each {|n| id_map[n] = nil}
+ yield component
+ end
+
+ minimum_id
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_node is used to iterate for all nodes over a graph.
+ #
+ def tsort_each_node # :yields: node
+ raise NotImplementedError.new
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_child is used to iterate for child nodes of _node_.
+ #
+ def tsort_each_child(node) # :yields: child
+ raise NotImplementedError.new
+ end
+end
diff --git a/lib/bundler/vendor/uri/lib/uri.rb b/lib/bundler/vendor/uri/lib/uri.rb
index 0e574dd2b1..976320f6bd 100644
--- a/lib/bundler/vendor/uri/lib/uri.rb
+++ b/lib/bundler/vendor/uri/lib/uri.rb
@@ -30,7 +30,7 @@
# class RSYNC < Generic
# DEFAULT_PORT = 873
# end
-# @@schemes['RSYNC'] = RSYNC
+# register_scheme 'RSYNC', RSYNC
# end
# #=> Bundler::URI::RSYNC
#
@@ -70,7 +70,6 @@
# - Bundler::URI::REGEXP - (in uri/common.rb)
# - Bundler::URI::REGEXP::PATTERN - (in uri/common.rb)
# - Bundler::URI::Util - (in uri/common.rb)
-# - Bundler::URI::Escape - (in uri/common.rb)
# - Bundler::URI::Error - (in uri/common.rb)
# - Bundler::URI::InvalidURIError - (in uri/common.rb)
# - Bundler::URI::InvalidComponentError - (in uri/common.rb)
@@ -101,3 +100,5 @@ require_relative 'uri/https'
require_relative 'uri/ldap'
require_relative 'uri/ldaps'
require_relative 'uri/mailto'
+require_relative 'uri/ws'
+require_relative 'uri/wss'
diff --git a/lib/bundler/vendor/uri/lib/uri/common.rb b/lib/bundler/vendor/uri/lib/uri/common.rb
index 6539e1810f..914a4c7581 100644
--- a/lib/bundler/vendor/uri/lib/uri/common.rb
+++ b/lib/bundler/vendor/uri/lib/uri/common.rb
@@ -13,9 +13,12 @@ require_relative "rfc2396_parser"
require_relative "rfc3986_parser"
module Bundler::URI
+ include RFC2396_REGEXP
+
REGEXP = RFC2396_REGEXP
Parser = RFC2396_Parser
RFC3986_PARSER = RFC3986_Parser.new
+ Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
# Bundler::URI::Parser.new
DEFAULT_PARSER = Parser.new
@@ -27,6 +30,7 @@ module Bundler::URI
DEFAULT_PARSER.regexp.each_pair do |sym, str|
const_set(sym, str)
end
+ Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
module Util # :nodoc:
def make_components_hash(klass, array_hash)
@@ -60,24 +64,42 @@ module Bundler::URI
module_function :make_components_hash
end
- include REGEXP
+ module Schemes
+ end
+ private_constant :Schemes
+
+ #
+ # Register the given +klass+ to be instantiated when parsing URLs with the given +scheme+.
+ # Note that currently only schemes which after .upcase are valid constant names
+ # can be registered (no -/+/. allowed).
+ #
+ def self.register_scheme(scheme, klass)
+ Schemes.const_set(scheme.to_s.upcase, klass)
+ end
- @@schemes = {}
# Returns a Hash of the defined schemes.
def self.scheme_list
- @@schemes
+ Schemes.constants.map { |name|
+ [name.to_s.upcase, Schemes.const_get(name)]
+ }.to_h
end
+ INITIAL_SCHEMES = scheme_list
+ private_constant :INITIAL_SCHEMES
+ Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
+
#
# Construct a Bundler::URI instance, using the scheme to detect the appropriate class
# from +Bundler::URI.scheme_list+.
#
def self.for(scheme, *arguments, default: Generic)
- if scheme
- uri_class = @@schemes[scheme.upcase] || default
- else
- uri_class = default
+ const_name = scheme.to_s.upcase
+
+ uri_class = INITIAL_SCHEMES[const_name]
+ uri_class ||= if /\A[A-Z]\w*\z/.match?(const_name) && Schemes.const_defined?(const_name, false)
+ Schemes.const_get(const_name, false)
end
+ uri_class ||= default
return uri_class.new(scheme, *arguments)
end
@@ -278,6 +300,7 @@ module Bundler::URI
256.times do |i|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
end
+ TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
@@ -303,6 +326,33 @@ module Bundler::URI
#
# See Bundler::URI.decode_www_form_component, Bundler::URI.encode_www_form.
def self.encode_www_form_component(str, enc=nil)
+ _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
+ end
+
+ # Decodes given +str+ of URL-encoded form data.
+ #
+ # This decodes + to SP.
+ #
+ # See Bundler::URI.encode_www_form_component, Bundler::URI.decode_www_form.
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
+ _decode_uri_component(/\+|%\h\h/, str, enc)
+ end
+
+ # Encodes +str+ using URL encoding
+ #
+ # This encodes SP to %20 instead of +.
+ def self.encode_uri_component(str, enc=nil)
+ _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
+ end
+
+ # Decodes given +str+ of URL-encoded data.
+ #
+ # This does not decode + to SP.
+ def self.decode_uri_component(str, enc=Encoding::UTF_8)
+ _decode_uri_component(/%\h\h/, str, enc)
+ end
+
+ def self._encode_uri_component(regexp, table, str, enc)
str = str.to_s.dup
if str.encoding != Encoding::ASCII_8BIT
if enc && enc != Encoding::ASCII_8BIT
@@ -311,19 +361,16 @@ module Bundler::URI
end
str.force_encoding(Encoding::ASCII_8BIT)
end
- str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
+ str.gsub!(regexp, table)
str.force_encoding(Encoding::US_ASCII)
end
+ private_class_method :_encode_uri_component
- # Decodes given +str+ of URL-encoded form data.
- #
- # This decodes + to SP.
- #
- # See Bundler::URI.encode_www_form_component, Bundler::URI.decode_www_form.
- def self.decode_www_form_component(str, enc=Encoding::UTF_8)
- raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/ =~ str
- str.b.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
+ def self._decode_uri_component(regexp, str, enc)
+ raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
+ str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
end
+ private_class_method :_decode_uri_component
# Generates URL-encoded form data from given +enum+.
#
@@ -653,6 +700,7 @@ module Bundler::URI
"utf-16"=>"utf-16le",
"utf-16le"=>"utf-16le",
} # :nodoc:
+ Ractor.make_shareable(WEB_ENCODINGS_) if defined?(Ractor)
# :nodoc:
# return encoding or nil
diff --git a/lib/bundler/vendor/uri/lib/uri/file.rb b/lib/bundler/vendor/uri/lib/uri/file.rb
index df42f8bcdd..8d75a9de7a 100644
--- a/lib/bundler/vendor/uri/lib/uri/file.rb
+++ b/lib/bundler/vendor/uri/lib/uri/file.rb
@@ -33,6 +33,9 @@ module Bundler::URI
# If an Array is used, the components must be passed in the
# order <code>[host, path]</code>.
#
+ # A path from e.g. the File class should be escaped before
+ # being passed.
+ #
# Examples:
#
# require 'bundler/vendor/uri/lib/uri'
@@ -44,6 +47,9 @@ module Bundler::URI
# :path => '/ruby/src'})
# uri2.to_s # => "file://host.example.com/ruby/src"
#
+ # uri3 = Bundler::URI::File.build({:path => Bundler::URI::escape('/path/my file.txt')})
+ # uri3.to_s # => "file:///path/my%20file.txt"
+ #
def self.build(args)
tmp = Util::make_components_hash(self, args)
super(tmp)
@@ -90,5 +96,5 @@ module Bundler::URI
end
end
- @@schemes['FILE'] = File
+ register_scheme 'FILE', File
end
diff --git a/lib/bundler/vendor/uri/lib/uri/ftp.rb b/lib/bundler/vendor/uri/lib/uri/ftp.rb
index 2252e405d5..48b4c6718d 100644
--- a/lib/bundler/vendor/uri/lib/uri/ftp.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ftp.rb
@@ -262,5 +262,6 @@ module Bundler::URI
return str
end
end
- @@schemes['FTP'] = FTP
+
+ register_scheme 'FTP', FTP
end
diff --git a/lib/bundler/vendor/uri/lib/uri/generic.rb b/lib/bundler/vendor/uri/lib/uri/generic.rb
index f29ba6cf18..9ae6915826 100644
--- a/lib/bundler/vendor/uri/lib/uri/generic.rb
+++ b/lib/bundler/vendor/uri/lib/uri/generic.rb
@@ -564,16 +564,26 @@ module Bundler::URI
end
end
- # Returns the user component.
+ # Returns the user component (without Bundler::URI decoding).
def user
@user
end
- # Returns the password component.
+ # Returns the password component (without Bundler::URI decoding).
def password
@password
end
+ # Returns the user component after Bundler::URI decoding.
+ def decoded_user
+ Bundler::URI.decode_uri_component(@user) if @user
+ end
+
+ # Returns the password component after Bundler::URI decoding.
+ def decoded_password
+ Bundler::URI.decode_uri_component(@password) if @password
+ end
+
#
# Checks the host +v+ component for RFC2396 compliance
# and against the Bundler::URI::Parser Regexp for :HOST.
@@ -643,7 +653,7 @@ module Bundler::URI
#
def hostname
v = self.host
- /\A\[(.*)\]\z/ =~ v ? $1 : v
+ v&.start_with?('[') && v.end_with?(']') ? v[1..-2] : v
end
# Sets the host part of the Bundler::URI as the argument with brackets for IPv6 addresses.
@@ -659,7 +669,7 @@ module Bundler::URI
# it is wrapped with brackets.
#
def hostname=(v)
- v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v
+ v = "[#{v}]" if !(v&.start_with?('[') && v&.end_with?(']')) && v&.index(':')
self.host = v
end
@@ -1514,9 +1524,19 @@ module Bundler::URI
proxy_uri = env["CGI_#{name.upcase}"]
end
elsif name == 'http_proxy'
- unless proxy_uri = env[name]
- if proxy_uri = env[name.upcase]
- warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.', uplevel: 1
+ if RUBY_ENGINE == 'jruby' && p_addr = ENV_JAVA['http.proxyHost']
+ p_port = ENV_JAVA['http.proxyPort']
+ if p_user = ENV_JAVA['http.proxyUser']
+ p_pass = ENV_JAVA['http.proxyPass']
+ proxy_uri = "http://#{p_user}:#{p_pass}@#{p_addr}:#{p_port}"
+ else
+ proxy_uri = "http://#{p_addr}:#{p_port}"
+ end
+ else
+ unless proxy_uri = env[name]
+ if proxy_uri = env[name.upcase]
+ warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.', uplevel: 1
+ end
end
end
else
diff --git a/lib/bundler/vendor/uri/lib/uri/http.rb b/lib/bundler/vendor/uri/lib/uri/http.rb
index 50d7e427a5..2c44810644 100644
--- a/lib/bundler/vendor/uri/lib/uri/http.rb
+++ b/lib/bundler/vendor/uri/lib/uri/http.rb
@@ -80,8 +80,46 @@ module Bundler::URI
url = @query ? "#@path?#@query" : @path.dup
url.start_with?(?/.freeze) ? url : ?/ + url
end
- end
- @@schemes['HTTP'] = HTTP
+ #
+ # == Description
+ #
+ # Returns the authority for an HTTP uri, as defined in
+ # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.
+ #
+ #
+ # Example:
+ #
+ # Bundler::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').authority #=> "www.example.com"
+ # Bundler::URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').authority #=> "www.example.com:8000"
+ # Bundler::URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').authority #=> "www.example.com"
+ #
+ def authority
+ if port == default_port
+ host
+ else
+ "#{host}:#{port}"
+ end
+ end
+
+ #
+ # == Description
+ #
+ # Returns the origin for an HTTP uri, as defined in
+ # https://datatracker.ietf.org/doc/html/rfc6454.
+ #
+ #
+ # Example:
+ #
+ # Bundler::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').origin #=> "http://www.example.com"
+ # Bundler::URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').origin #=> "http://www.example.com:8000"
+ # Bundler::URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').origin #=> "http://www.example.com"
+ # Bundler::URI::HTTPS.build(host: 'www.example.com', path: '/foo/bar').origin #=> "https://www.example.com"
+ #
+ def origin
+ "#{scheme}://#{authority}"
+ end
+ end
+ register_scheme 'HTTP', HTTP
end
diff --git a/lib/bundler/vendor/uri/lib/uri/https.rb b/lib/bundler/vendor/uri/lib/uri/https.rb
index 4fd4e9af7b..e4556e3ecb 100644
--- a/lib/bundler/vendor/uri/lib/uri/https.rb
+++ b/lib/bundler/vendor/uri/lib/uri/https.rb
@@ -18,5 +18,6 @@ module Bundler::URI
# A Default port of 443 for Bundler::URI::HTTPS
DEFAULT_PORT = 443
end
- @@schemes['HTTPS'] = HTTPS
+
+ register_scheme 'HTTPS', HTTPS
end
diff --git a/lib/bundler/vendor/uri/lib/uri/ldap.rb b/lib/bundler/vendor/uri/lib/uri/ldap.rb
index 6e9e1918f6..9811b6e2f5 100644
--- a/lib/bundler/vendor/uri/lib/uri/ldap.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ldap.rb
@@ -257,5 +257,5 @@ module Bundler::URI
end
end
- @@schemes['LDAP'] = LDAP
+ register_scheme 'LDAP', LDAP
end
diff --git a/lib/bundler/vendor/uri/lib/uri/ldaps.rb b/lib/bundler/vendor/uri/lib/uri/ldaps.rb
index 0af35bb16b..c786168450 100644
--- a/lib/bundler/vendor/uri/lib/uri/ldaps.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ldaps.rb
@@ -17,5 +17,6 @@ module Bundler::URI
# A Default port of 636 for Bundler::URI::LDAPS
DEFAULT_PORT = 636
end
- @@schemes['LDAPS'] = LDAPS
+
+ register_scheme 'LDAPS', LDAPS
end
diff --git a/lib/bundler/vendor/uri/lib/uri/mailto.rb b/lib/bundler/vendor/uri/lib/uri/mailto.rb
index ff7ab7e114..ff2e30be86 100644
--- a/lib/bundler/vendor/uri/lib/uri/mailto.rb
+++ b/lib/bundler/vendor/uri/lib/uri/mailto.rb
@@ -15,7 +15,7 @@ module Bundler::URI
# RFC6068, the mailto URL scheme.
#
class MailTo < Generic
- include REGEXP
+ include RFC2396_REGEXP
# A Default port of nil for Bundler::URI::MailTo.
DEFAULT_PORT = nil
@@ -289,5 +289,5 @@ module Bundler::URI
alias to_rfc822text to_mailtext
end
- @@schemes['MAILTO'] = MailTo
+ register_scheme 'MAILTO', MailTo
end
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
index e48e164f4c..09c22c9906 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
@@ -116,7 +116,7 @@ module Bundler::URI
# See also Bundler::URI::Parser.initialize_regexp.
attr_reader :regexp
- # Returns a split Bundler::URI against regexp[:ABS_URI].
+ # Returns a split Bundler::URI against +regexp[:ABS_URI]+.
def split(uri)
case uri
when ''
@@ -257,8 +257,8 @@ module Bundler::URI
end
end
- # Returns Regexp that is default self.regexp[:ABS_URI_REF],
- # unless +schemes+ is provided. Then it is a Regexp.union with self.pattern[:X_ABS_URI].
+ # Returns Regexp that is default +self.regexp[:ABS_URI_REF]+,
+ # unless +schemes+ is provided. Then it is a Regexp.union with +self.pattern[:X_ABS_URI]+.
def make_regexp(schemes = nil)
unless schemes
@regexp[:ABS_URI_REF]
@@ -277,7 +277,7 @@ module Bundler::URI
# +str+::
# String to make safe
# +unsafe+::
- # Regexp to apply. Defaults to self.regexp[:UNSAFE]
+ # Regexp to apply. Defaults to +self.regexp[:UNSAFE]+
#
# == Description
#
@@ -309,7 +309,7 @@ module Bundler::URI
# +str+::
# String to remove escapes from
# +escaped+::
- # Regexp to apply. Defaults to self.regexp[:ESCAPED]
+ # Regexp to apply. Defaults to +self.regexp[:ESCAPED]+
#
# == Description
#
@@ -322,8 +322,14 @@ module Bundler::URI
end
@@to_s = Kernel.instance_method(:to_s)
- def inspect
- @@to_s.bind_call(self)
+ if @@to_s.respond_to?(:bind_call)
+ def inspect
+ @@to_s.bind_call(self)
+ end
+ else
+ def inspect
+ @@to_s.bind(self).call
+ end
end
private
@@ -491,8 +497,8 @@ module Bundler::URI
ret = {}
# for Bundler::URI::split
- ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
- ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
+ ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
+ ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
# for Bundler::URI::extract
ret[:URI_REF] = Regexp.new(pattern[:URI_REF])
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
index 2029cfd056..a85511c146 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
@@ -2,9 +2,8 @@
module Bundler::URI
class RFC3986_Parser # :nodoc:
# Bundler::URI defined in RFC3986
- # this regexp is modified not to host is not empty string
- RFC3986_URI = /\A(?<Bundler::URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
- RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
+ RFC3986_URI = /\A(?<Bundler::URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*+):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+))(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
+ RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])++)(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
attr_reader :regexp
def initialize
@@ -79,8 +78,14 @@ module Bundler::URI
end
@@to_s = Kernel.instance_method(:to_s)
- def inspect
- @@to_s.bind_call(self)
+ if @@to_s.respond_to?(:bind_call)
+ def inspect
+ @@to_s.bind_call(self)
+ end
+ else
+ def inspect
+ @@to_s.bind(self).call
+ end
end
private
@@ -95,7 +100,7 @@ module Bundler::URI
QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
OPAQUE: /\A(?:[^\/].*)?\z/,
- PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/,
+ PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
}
end
diff --git a/lib/bundler/vendor/uri/lib/uri/version.rb b/lib/bundler/vendor/uri/lib/uri/version.rb
index f2bb0ebad2..84b08eee30 100644
--- a/lib/bundler/vendor/uri/lib/uri/version.rb
+++ b/lib/bundler/vendor/uri/lib/uri/version.rb
@@ -1,6 +1,6 @@
module Bundler::URI
# :stopdoc:
- VERSION_CODE = '001001'.freeze
+ VERSION_CODE = '001202'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/lib/bundler/vendor/uri/lib/uri/ws.rb b/lib/bundler/vendor/uri/lib/uri/ws.rb
index 58e08bf98e..10ae6f5834 100644
--- a/lib/bundler/vendor/uri/lib/uri/ws.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ws.rb
@@ -79,6 +79,5 @@ module Bundler::URI
end
end
- @@schemes['WS'] = WS
-
+ register_scheme 'WS', WS
end
diff --git a/lib/bundler/vendor/uri/lib/uri/wss.rb b/lib/bundler/vendor/uri/lib/uri/wss.rb
index 3827053c7b..e8db1ceabf 100644
--- a/lib/bundler/vendor/uri/lib/uri/wss.rb
+++ b/lib/bundler/vendor/uri/lib/uri/wss.rb
@@ -18,5 +18,6 @@ module Bundler::URI
# A Default port of 443 for Bundler::URI::WSS
DEFAULT_PORT = 443
end
- @@schemes['WSS'] = WSS
+
+ register_scheme 'WSS', WSS
end
diff --git a/lib/bundler/vendored_persistent.rb b/lib/bundler/vendored_persistent.rb
index dc9573e025..e29f27cdfd 100644
--- a/lib/bundler/vendored_persistent.rb
+++ b/lib/bundler/vendored_persistent.rb
@@ -11,37 +11,5 @@ end
require_relative "vendor/net-http-persistent/lib/net/http/persistent"
module Bundler
- class PersistentHTTP < Persistent::Net::HTTP::Persistent
- def connection_for(uri)
- super(uri) do |connection|
- result = yield connection
- warn_old_tls_version_rubygems_connection(uri, connection)
- result
- end
- end
-
- def warn_old_tls_version_rubygems_connection(uri, connection)
- return unless connection.http.use_ssl?
- return unless (uri.host || "").end_with?("rubygems.org")
-
- socket = connection.instance_variable_get(:@socket)
- return unless socket
- socket_io = socket.io
- return unless socket_io.respond_to?(:ssl_version)
- ssl_version = socket_io.ssl_version
-
- case ssl_version
- when /TLSv([\d\.]+)/
- version = Gem::Version.new($1)
- if version < Gem::Version.new("1.2")
- Bundler.ui.warn \
- "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \
- "Starting in January 2018, RubyGems.org will refuse connection requests from these " \
- "very old versions of OpenSSL. If you will need to continue installing gems after " \
- "January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.",
- :wrap => true
- end
- end
- end
- end
+ PersistentHTTP = Persistent::Net::HTTP::Persistent
end
diff --git a/lib/bundler/vendored_molinillo.rb b/lib/bundler/vendored_pub_grub.rb
index d1976f5cb4..b36a996b29 100644
--- a/lib/bundler/vendored_molinillo.rb
+++ b/lib/bundler/vendored_pub_grub.rb
@@ -1,4 +1,4 @@
# frozen_string_literal: true
module Bundler; end
-require_relative "vendor/molinillo/lib/molinillo"
+require_relative "vendor/pub_grub/lib/pub_grub"
diff --git a/lib/bundler/vendored_tmpdir.rb b/lib/bundler/vendored_tsort.rb
index 43b4fa75fe..38aed0b5de 100644
--- a/lib/bundler/vendored_tmpdir.rb
+++ b/lib/bundler/vendored_tsort.rb
@@ -1,4 +1,4 @@
# frozen_string_literal: true
module Bundler; end
-require_relative "vendor/tmpdir/lib/tmpdir"
+require_relative "vendor/tsort/lib/tsort"
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 0c0d9d360d..8ef7be935b 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,9 +1,13 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.3.0.dev".freeze
+ VERSION = "2.4.19".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i
end
+
+ def self.gem_version
+ @gem_version ||= Gem::Version.create(VERSION)
+ end
end
diff --git a/lib/bundler/version_ranges.rb b/lib/bundler/version_ranges.rb
deleted file mode 100644
index 12a956d6a0..0000000000
--- a/lib/bundler/version_ranges.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- module VersionRanges
- NEq = Struct.new(:version)
- ReqR = Struct.new(:left, :right)
- class ReqR
- Endpoint = Struct.new(:version, :inclusive) do
- def <=>(other)
- if version.equal?(INFINITY)
- return 0 if other.version.equal?(INFINITY)
- return 1
- elsif other.version.equal?(INFINITY)
- return -1
- end
-
- comp = version <=> other.version
- return comp unless comp.zero?
-
- if inclusive && !other.inclusive
- 1
- elsif !inclusive && other.inclusive
- -1
- else
- 0
- end
- end
- end
-
- def to_s
- "#{left.inclusive ? "[" : "("}#{left.version}, #{right.version}#{right.inclusive ? "]" : ")"}"
- end
- INFINITY = begin
- inf = Object.new
- def inf.to_s
- "∞"
- end
- def inf.<=>(other)
- return 0 if other.equal?(self)
- 1
- end
- inf.freeze
- end
- ZERO = Gem::Version.new("0.a")
-
- def cover?(v)
- return false if left.inclusive && left.version > v
- return false if !left.inclusive && left.version >= v
-
- if right.version != INFINITY
- return false if right.inclusive && right.version < v
- return false if !right.inclusive && right.version <= v
- end
-
- true
- end
-
- def empty?
- left.version == right.version && !(left.inclusive && right.inclusive)
- end
-
- def single?
- left.version == right.version
- end
-
- def <=>(other)
- return -1 if other.equal?(INFINITY)
-
- comp = left <=> other.left
- return comp unless comp.zero?
-
- right <=> other.right
- end
-
- UNIVERSAL = ReqR.new(ReqR::Endpoint.new(Gem::Version.new("0.a"), true), ReqR::Endpoint.new(ReqR::INFINITY, false)).freeze
- end
-
- def self.for_many(requirements)
- requirements = requirements.map(&:requirements).flatten(1).map {|r| r.join(" ") }
- requirements << ">= 0.a" if requirements.empty?
- requirement = Gem::Requirement.new(requirements)
- self.for(requirement)
- end
-
- def self.for(requirement)
- ranges = requirement.requirements.map do |op, v|
- case op
- when "=" then ReqR.new(ReqR::Endpoint.new(v, true), ReqR::Endpoint.new(v, true))
- when "!=" then NEq.new(v)
- when ">=" then ReqR.new(ReqR::Endpoint.new(v, true), ReqR::Endpoint.new(ReqR::INFINITY, false))
- when ">" then ReqR.new(ReqR::Endpoint.new(v, false), ReqR::Endpoint.new(ReqR::INFINITY, false))
- when "<" then ReqR.new(ReqR::Endpoint.new(ReqR::ZERO, true), ReqR::Endpoint.new(v, false))
- when "<=" then ReqR.new(ReqR::Endpoint.new(ReqR::ZERO, true), ReqR::Endpoint.new(v, true))
- when "~>" then ReqR.new(ReqR::Endpoint.new(v, true), ReqR::Endpoint.new(v.bump, false))
- else raise "unknown version op #{op} in requirement #{requirement}"
- end
- end.uniq
- ranges, neqs = ranges.partition {|r| !r.is_a?(NEq) }
-
- [ranges.sort, neqs.map(&:version)]
- end
-
- def self.empty?(ranges, neqs)
- !ranges.reduce(ReqR::UNIVERSAL) do |last_range, curr_range|
- next false unless last_range
- next false if curr_range.single? && neqs.include?(curr_range.left.version)
- next curr_range if last_range.right.version == ReqR::INFINITY
- case last_range.right.version <=> curr_range.left.version
- # higher
- when 1 then next ReqR.new(curr_range.left, last_range.right)
- # equal
- when 0
- if last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version)
- ReqR.new(curr_range.left, [curr_range.right, last_range.right].max)
- end
- # lower
- when -1 then next false
- end
- end
- end
- end
-end
diff --git a/lib/bundler/worker.rb b/lib/bundler/worker.rb
index 5e4ee21c51..3ebd6f01db 100644
--- a/lib/bundler/worker.rb
+++ b/lib/bundler/worker.rb
@@ -87,14 +87,12 @@ module Bundler
creation_errors = []
@threads = Array.new(@size) do |i|
- begin
- Thread.start { process_queue(i) }.tap do |thread|
- thread.name = "#{name} Worker ##{i}" if thread.respond_to?(:name=)
- end
- rescue ThreadError => e
- creation_errors << e
- nil
+ Thread.start { process_queue(i) }.tap do |thread|
+ thread.name = "#{name} Worker ##{i}" if thread.respond_to?(:name=)
end
+ rescue ThreadError => e
+ creation_errors << e
+ nil
end.compact
add_interrupt_handler unless @threads.empty?
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 3b53d27a2e..7dc3a64941 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -162,7 +162,7 @@
# cgi.has_key?('field_name')
# cgi.include?('field_name')
#
-# CAUTION! cgi['field_name'] returned an Array with the old
+# CAUTION! <code>cgi['field_name']</code> returned an Array with the old
# cgi.rb(included in Ruby 1.6)
#
# === Get form values as hash
@@ -288,7 +288,7 @@
#
class CGI
- VERSION = "0.2.0"
+ VERSION = "0.3.7"
end
require 'cgi/core'
diff --git a/lib/cgi/cgi.gemspec b/lib/cgi/cgi.gemspec
index 5d23ef0f61..381c55a5ca 100644
--- a/lib/cgi/cgi.gemspec
+++ b/lib/cgi/cgi.gemspec
@@ -22,10 +22,21 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
spec.executables = []
+
+ spec.files = [
+ "LICENSE.txt",
+ "README.md",
+ *Dir["lib{.rb,/**/*.rb}", "bin/*"] ]
+
spec.require_paths = ["lib"]
+
+ if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
+ spec.platform = 'java'
+ spec.require_paths << "ext/java/org/jruby/ext/cgi/escape/lib"
+ spec.files += Dir["ext/java/**/*.{rb}", "lib/cgi/escape.jar"]
+ else
+ spec.files += Dir["ext/cgi/**/*.{rb,c,h,sh}", "ext/cgi/escape/depend", "lib/cgi/escape.so"]
+ spec.extensions = ["ext/cgi/escape/extconf.rb"]
+ end
end
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
index ae9ab58ede..1c4ef6a600 100644
--- a/lib/cgi/cookie.rb
+++ b/lib/cgi/cookie.rb
@@ -40,6 +40,10 @@ 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:
@@ -72,8 +76,8 @@ class CGI
@domain = nil
@expires = nil
if name.kind_of?(String)
- @name = name
- @path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
+ self.name = name
+ self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
@secure = false
@httponly = false
return super(value)
@@ -84,11 +88,11 @@ class CGI
raise ArgumentError, "`name' required"
end
- @name = options["name"]
+ self.name = options["name"]
value = Array(options["value"])
# simple support for IE
- @path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
- @domain = options["domain"]
+ self.path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
+ self.domain = options["domain"]
@expires = options["expires"]
@secure = options["secure"] == true
@httponly = options["httponly"] == true
@@ -97,11 +101,35 @@ class CGI
end
# Name of this cookie, as a +String+
- attr_accessor :name
+ attr_reader :name
+ # Set name of this cookie
+ def name=(str)
+ if str and !TOKEN_RE.match?(str)
+ raise ArgumentError, "invalid name: #{str.dump}"
+ end
+ @name = str
+ end
+
# Path for which this cookie applies, as a +String+
- attr_accessor :path
+ attr_reader :path
+ # Set path for which this cookie applies
+ def path=(str)
+ if str and !PATH_VALUE_RE.match?(str)
+ raise ArgumentError, "invalid path: #{str.dump}"
+ end
+ @path = str
+ end
+
# Domain for which this cookie applies, as a +String+
- attr_accessor :domain
+ attr_reader :domain
+ # Set domain for which this cookie applies
+ def domain=(str)
+ if str and ((str = str.b).bytesize > 255 or !DOMAIN_VALUE_RE.match?(str))
+ raise ArgumentError, "invalid domain: #{str.dump}"
+ end
+ @domain = str
+ end
+
# Time at which this cookie expires, as a +Time+
attr_accessor :expires
# True if this cookie is secure; false otherwise
@@ -159,13 +187,13 @@ class CGI
raw_cookie.split(/;\s?/).each do |pairs|
name, values = pairs.split('=',2)
next unless name and values
- name = CGI.unescape(name)
values ||= ""
values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) }
if cookies.has_key?(name)
- values = cookies[name].value + values
+ cookies[name].concat(values)
+ else
+ cookies[name] = Cookie.new(name, *values)
end
- cookies[name] = Cookie.new(name, *values)
end
cookies
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
index bec76e0749..62e606837a 100644
--- a/lib/cgi/core.rb
+++ b/lib/cgi/core.rb
@@ -188,17 +188,28 @@ 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 << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
+ buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}"
buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
- buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
+ buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}"
buf << "Connection: close#{EOL}"
end
- buf << "Content-Type: #{content_type}#{EOL}"
+ buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
if @output_cookies
- @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
end
return buf
end # _header_for_string
@@ -213,9 +224,9 @@ class CGI
## NPH
options.delete('nph') if defined?(MOD_RUBY)
if options.delete('nph') || nph?()
- protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
+ protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
status = options.delete('status')
- status = HTTP_STATUS[status] || status || '200 OK'
+ status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
buf << "#{protocol} #{status}#{EOL}"
buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
@@ -223,38 +234,38 @@ class CGI
end
## common headers
status = options.delete('status')
- buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
+ buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
server = options.delete('server')
- buf << "Server: #{server}#{EOL}" if server
+ buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
connection = options.delete('connection')
- buf << "Connection: #{connection}#{EOL}" if connection
+ buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
type = options.delete('type')
- buf << "Content-Type: #{type}#{EOL}" #if type
+ buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
length = options.delete('length')
- buf << "Content-Length: #{length}#{EOL}" if length
+ buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
language = options.delete('language')
- buf << "Content-Language: #{language}#{EOL}" if language
+ buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
expires = options.delete('expires')
buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
## cookie
if cookie = options.delete('cookie')
case cookie
when String, Cookie
- buf << "Set-Cookie: #{cookie}#{EOL}"
+ buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}"
when Array
arr = cookie
- arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
when Hash
hash = cookie
- hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
end
end
if @output_cookies
- @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
end
## other headers
options.each do |key, value|
- buf << "#{key}: #{value}#{EOL}"
+ buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
end
return buf
end # _header_for_hash
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index 29e7b3ece3..70c7ebca42 100644
--- a/lib/cgi/session.rb
+++ b/lib/cgi/session.rb
@@ -189,6 +189,47 @@ class CGI
end
private :create_new_id
+
+ # Create a new file to store the session data.
+ #
+ # This file will be created if it does not exist, or opened if it
+ # does.
+ #
+ # This path is generated under _tmpdir_ from _prefix_, the
+ # digested session id, and _suffix_.
+ #
+ # +option+ is a hash of options for the initializer. The
+ # following options are recognised:
+ #
+ # tmpdir:: the directory to use for storing the FileStore
+ # file. Defaults to Dir::tmpdir (generally "/tmp"
+ # on Unix systems).
+ # prefix:: the prefix to add to the session id when generating
+ # the filename for this session's FileStore file.
+ # Defaults to "cgi_sid_".
+ # suffix:: the prefix to add to the session id when generating
+ # the filename for this session's FileStore file.
+ # Defaults to the empty string.
+ def new_store_file(option={}) # :nodoc:
+ dir = option['tmpdir'] || Dir::tmpdir
+ prefix = option['prefix']
+ suffix = option['suffix']
+ require 'digest/md5'
+ md5 = Digest::MD5.hexdigest(session_id)[0,16]
+ path = dir+"/"
+ path << prefix if prefix
+ path << md5
+ path << suffix if suffix
+ if File::exist? path
+ hash = nil
+ elsif new_session
+ hash = {}
+ else
+ raise NoSession, "uninitialized session"
+ end
+ return path, hash
+ end
+
# Create a new CGI::Session object for +request+.
#
# +request+ is an instance of the +CGI+ class (see cgi.rb).
@@ -373,21 +414,8 @@ class CGI
# This session's FileStore file will be created if it does
# not exist, or opened if it does.
def initialize(session, option={})
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix'] || 'cgi_sid_'
- suffix = option['suffix'] || ''
- id = session.session_id
- require 'digest/md5'
- md5 = Digest::MD5.hexdigest(id)[0,16]
- @path = dir+"/"+prefix+md5+suffix
- if File::exist? @path
- @hash = nil
- else
- unless session.new_session
- raise CGI::Session::NoSession, "uninitialized session"
- end
- @hash = {}
- end
+ option = {'prefix' => 'cgi_sid_'}.update(option)
+ @path, @hash = session.new_store_file(option)
end
# Restore session state from the session's FileStore file.
diff --git a/lib/cgi/session/pstore.rb b/lib/cgi/session/pstore.rb
index cc3006400f..45d0d8ae2c 100644
--- a/lib/cgi/session/pstore.rb
+++ b/lib/cgi/session/pstore.rb
@@ -44,20 +44,8 @@ class CGI
# This session's PStore file will be created if it does
# not exist, or opened if it does.
def initialize(session, option={})
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix'] || ''
- id = session.session_id
- require 'digest/md5'
- md5 = Digest::MD5.hexdigest(id)[0,16]
- path = dir+"/"+prefix+md5
- if File::exist?(path)
- @hash = nil
- else
- unless session.new_session
- raise CGI::Session::NoSession, "uninitialized session"
- end
- @hash = {}
- end
+ option = {'suffix'=>''}.update(option)
+ path, @hash = session.new_store_file(option)
@p = ::PStore.new(path)
@p.transaction do |p|
File.chmod(0600, p.path)
diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb
index 69a252b5e3..ce77a0ccd5 100644
--- a/lib/cgi/util.rb
+++ b/lib/cgi/util.rb
@@ -5,24 +5,57 @@ class CGI
extend Util
end
module CGI::Util
- @@accept_charset="UTF-8" unless defined?(@@accept_charset)
- # URL-encode a string.
+ @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
+
+ # URL-encode a string into application/x-www-form-urlencoded.
+ # Space characters (+" "+) are encoded with plus signs (+"+"+)
# url_encoded_string = CGI.escape("'Stop!' said Fred")
# # => "%27Stop%21%27+said+Fred"
def escape(string)
encoding = string.encoding
- string.b.gsub(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
+ buffer = string.b
+ buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
'%' + m.unpack('H2' * m.bytesize).join('%').upcase
- end.tr(' ', '+').force_encoding(encoding)
+ end
+ buffer.tr!(' ', '+')
+ buffer.force_encoding(encoding)
end
- # URL-decode a string with encoding(optional).
+ # URL-decode an application/x-www-form-urlencoded string with encoding(optional).
# string = CGI.unescape("%27Stop%21%27+said+Fred")
# # => "'Stop!' said Fred"
- def unescape(string,encoding=@@accept_charset)
- str=string.tr('+', ' ').b.gsub(/((?:%[0-9a-fA-F]{2})+)/) do |m|
+ def unescape(string, encoding = @@accept_charset)
+ str = string.tr('+', ' ')
+ str = str.b
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
+ [m.delete('%')].pack('H*')
+ end
+ str.force_encoding(encoding)
+ str.valid_encoding? ? str : str.force_encoding(string.encoding)
+ end
+
+ # URL-encode a string following RFC 3986
+ # Space characters (+" "+) are encoded with (+"%20"+)
+ # url_encoded_string = CGI.escape("'Stop!' said Fred")
+ # # => "%27Stop%21%27%20said%20Fred"
+ def escapeURIComponent(string)
+ encoding = string.encoding
+ buffer = string.b
+ buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m|
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
+ end
+ buffer.force_encoding(encoding)
+ end
+
+ # URL-decode a string following RFC 3986 with encoding(optional).
+ # string = CGI.unescape("%27Stop%21%27+said%20Fred")
+ # # => "'Stop!'+said Fred"
+ def unescapeURIComponent(string, encoding = @@accept_charset)
+ str = string.b
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
[m.delete('%')].pack('H*')
- end.force_encoding(encoding)
+ end
+ str.force_encoding(encoding)
str.valid_encoding? ? str : str.force_encoding(string.encoding)
end
@@ -145,7 +178,7 @@ module CGI::Util
def escapeElement(string, *elements)
elements = elements[0] if elements[0].kind_of?(Array)
unless elements.empty?
- string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
+ string.gsub(/<\/?(?:#{elements.join("|")})\b[^<>]*+>?/im) do
CGI.escapeHTML($&)
end
else
@@ -165,7 +198,7 @@ module CGI::Util
def unescapeElement(string, *elements)
elements = elements[0] if elements[0].kind_of?(Array)
unless elements.empty?
- string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/i) do
+ string.gsub(/&lt;\/?(?:#{elements.join("|")})\b(?>[^&]+|&(?![gl]t;)\w+;)*(?:&gt;)?/im) do
unescapeHTML($&)
end
else
@@ -179,21 +212,12 @@ module CGI::Util
# Synonym for CGI.unescapeElement(str)
alias unescape_element unescapeElement
- # Abbreviated day-of-week names specified by RFC 822
- RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
-
- # Abbreviated month names specified by RFC 822
- RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
-
# Format a +Time+ object as a String using the format specified by RFC 1123.
#
# CGI.rfc1123_date(Time.now)
# # Sat, 01 Jan 2000 00:00:00 GMT
def rfc1123_date(time)
- t = time.clone.gmtime
- return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
- RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
- t.hour, t.min, t.sec)
+ time.getgm.strftime("%a, %d %b %Y %T GMT")
end
# Prettify (indent) an HTML string.
diff --git a/lib/csv.rb b/lib/csv.rb
index 868f8e5b0e..0307033941 100644
--- a/lib/csv.rb
+++ b/lib/csv.rb
@@ -48,7 +48,7 @@
#
# === Interface
#
-# * CSV now uses Hash-style parameters to set options.
+# * CSV now uses keyword parameters to set options.
# * CSV no longer has generate_row() or parse_row().
# * The old CSV's Reader and Writer classes have been dropped.
# * CSV::open() is now more like Ruby's open().
@@ -90,21 +90,29 @@
# with any questions.
require "forwardable"
-require "English"
require "date"
require "stringio"
require_relative "csv/fields_converter"
-require_relative "csv/match_p"
+require_relative "csv/input_record_separator"
require_relative "csv/parser"
require_relative "csv/row"
require_relative "csv/table"
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:
+#
+# === In a Hurry?
+#
+# If you are familiar with \CSV data and have a particular task in mind,
+# you may want to go directly to the:
+# - {Recipes for CSV}[doc/csv/recipes/recipes_rdoc.html].
+#
+# Otherwise, read on here, about the API: classes, methods, and constants.
+#
+# === \CSV Data
+#
+# \CSV (comma-separated values) data is a text representation of a table:
# - A _row_ _separator_ delimits table rows.
# A common row separator is the newline character <tt>"\n"</tt>.
# - A _column_ _separator_ delimits fields in a row.
@@ -330,6 +338,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# liberal_parsing: false,
# nil_value: nil,
# empty_value: "",
+# strip: false,
# # For generating.
# write_headers: nil,
# quote_empty: true,
@@ -337,7 +346,6 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# write_converters: nil,
# write_nil_value: nil,
# write_empty_value: "",
-# strip: false,
# }
#
# ==== Options for Parsing
@@ -346,7 +354,9 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# - +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.
+# - +field_size_limit+: Specifies the maximum field size + 1 allowed.
+# Deprecated since 3.2.3. Use +max_field_size+ instead.
+# - +max_field_size+: Specifies the maximum field size allowed.
# - +converters+: Specifies the field converters to be used.
# - +unconverted_fields+: Specifies whether unconverted fields are to be available.
# - +headers+: Specifies whether data contains headers,
@@ -355,8 +365,9 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# - +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..
+# - +strip+: Specifies whether leading and trailing whitespace are to be
+# stripped from fields. This must be compatible with +col_sep+; if it is not,
+# then an +ArgumentError+ exception will be raised.
# - +liberal_parsing+: Specifies whether \CSV should attempt to parse
# non-compliant data.
# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field.
@@ -502,7 +513,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# [" 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:
+# Each CSV::FieldInfo object shows:
# - The 0-based field index.
# - The 1-based line index.
# - The field header, if any.
@@ -536,6 +547,14 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
#
# There is no such storage structure for write headers.
#
+# In order for the parsing methods to access stored converters in non-main-Ractors, the
+# storage structure must be made shareable first.
+# Therefore, <tt>Ractor.make_shareable(CSV::Converters)</tt> and
+# <tt>Ractor.make_shareable(CSV::HeaderConverters)</tt> must be called before the creation
+# of Ractors that use the converters stored in these structures. (Since making the storage
+# structures shareable involves freezing them, any custom converters that are to be used
+# must be added first.)
+#
# ===== Converter Lists
#
# A _converter_ _list_ is an \Array that may include any assortment of:
@@ -694,7 +713,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# 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+,
+# these examples use built-in header converter +:downcase+,
# which downcases each parsed header.
#
# - Option +header_converters+ with a singleton parsing method:
@@ -844,8 +863,9 @@ class CSV
# <b><tt>index</tt></b>:: The zero-based index of the field in its row.
# <b><tt>line</tt></b>:: The line of the data source this row is from.
# <b><tt>header</tt></b>:: The header for the column, when available.
+ # <b><tt>quoted?</tt></b>:: True or false, whether the original value is quoted or not.
#
- FieldInfo = Struct.new(:index, :line, :header)
+ FieldInfo = Struct.new(:index, :line, :header, :quoted?)
# A Regexp used to find and convert some common Date formats.
DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} |
@@ -853,10 +873,9 @@ class CSV
# A Regexp used to find and convert some common DateTime formats.
DateTimeMatcher =
/ \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} |
- \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2} |
- # ISO-8601
+ # ISO-8601 and RFC-3339 (space instead of T) recognized by DateTime.parse
\d{4}-\d{2}-\d{2}
- (?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?(?:[+-]\d{2}(?::\d{2})|Z)?)?)?
+ (?:[T\s]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?(?:[+-]\d{2}(?::\d{2})|Z)?)?)?
)\z /x
# The encoding used by all converters.
@@ -906,8 +925,10 @@ class CSV
symbol: lambda { |h|
h.encode(ConverterEncoding).downcase.gsub(/[^\s\w]+/, "").strip.
gsub(/\s+/, "_").to_sym
- }
+ },
+ symbol_raw: lambda { |h| h.encode(ConverterEncoding).to_sym }
}
+
# Default values for method options.
DEFAULT_OPTIONS = {
# For both parsing and generating.
@@ -916,6 +937,7 @@ class CSV
quote_char: '"',
# For parsing.
field_size_limit: nil,
+ max_field_size: nil,
converters: nil,
unconverted_fields: nil,
headers: false,
@@ -926,6 +948,7 @@ class CSV
liberal_parsing: false,
nil_value: nil,
empty_value: "",
+ strip: false,
# For generating.
write_headers: nil,
quote_empty: true,
@@ -933,7 +956,6 @@ class CSV
write_converters: nil,
write_nil_value: nil,
write_empty_value: "",
- strip: false,
}.freeze
class << self
@@ -946,6 +968,8 @@ class CSV
# Creates or retrieves cached \CSV objects.
# For arguments and options, see CSV.new.
#
+ # This API is not Ractor-safe.
+ #
# ---
#
# With no block given, returns a \CSV object.
@@ -981,7 +1005,7 @@ class CSV
def instance(data = $stdout, **options)
# create a _signature_ for this method call, data object and options
sig = [data.object_id] +
- options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
+ options.values_at(*DEFAULT_OPTIONS.keys)
# fetch or create the instance for this signature
@@instances ||= Hash.new
@@ -995,65 +1019,190 @@ class CSV
end
# :call-seq:
- # 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| ... }
- #
- # Reads \CSV input and writes \CSV output.
- #
- # 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.
+ # filter(in_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table
+ # filter(in_string_or_io, out_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table
+ # filter(**options) {|row| ... } -> array_of_arrays or csv_table
#
- # 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].
+ # - Parses \CSV from a source (\String, \IO stream, or ARGF).
+ # - Calls the given block with each parsed row:
+ # - Without headers, each row is an \Array.
+ # - With headers, each row is a CSV::Row.
+ # - Generates \CSV to an output (\String, \IO stream, or STDOUT).
+ # - Returns the parsed source:
+ # - Without headers, an \Array of \Arrays.
+ # - With headers, a CSV::Table.
#
- # Example:
- # in_string = "foo,0\nbar,1\nbaz,2\n"
+ # When +in_string_or_io+ is given, but not +out_string_or_io+,
+ # parses from the given +in_string_or_io+
+ # and generates to STDOUT.
+ #
+ # \String input without headers:
+ #
+ # in_string = "foo,0\nbar,1\nbaz,2"
+ # CSV.filter(in_string) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
+ #
+ # Output (to STDOUT):
+ #
+ # FOO,0
+ # BAR,-1
+ # BAZ,-2
+ #
+ # \String input with headers:
+ #
+ # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
+ # CSV.filter(in_string, headers: true) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end # => #<CSV::Table mode:col_or_row row_count:4>
+ #
+ # Output (to STDOUT):
+ #
+ # Name,Value
+ # FOO,0
+ # BAR,-1
+ # BAZ,-2
+ #
+ # \IO stream input without headers:
+ #
+ # File.write('t.csv', "foo,0\nbar,1\nbaz,2")
+ # File.open('t.csv') do |in_io|
+ # CSV.filter(in_io) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end
+ # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
+ #
+ # Output (to STDOUT):
+ #
+ # FOO,0
+ # BAR,-1
+ # BAZ,-2
+ #
+ # \IO stream input with headers:
+ #
+ # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2")
+ # File.open('t.csv') do |in_io|
+ # CSV.filter(in_io, headers: true) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end
+ # end # => #<CSV::Table mode:col_or_row row_count:4>
+ #
+ # Output (to STDOUT):
+ #
+ # Name,Value
+ # FOO,0
+ # BAR,-1
+ # BAZ,-2
+ #
+ # When both +in_string_or_io+ and +out_string_or_io+ are given,
+ # parses from +in_string_or_io+ and generates to +out_string_or_io+.
+ #
+ # \String output without headers:
+ #
+ # in_string = "foo,0\nbar,1\nbaz,2"
# out_string = ''
# CSV.filter(in_string, out_string) do |row|
- # row[0] = row[0].upcase
- # row[1] *= 4
- # end
- # out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
+ # out_string # => "FOO,0\nBAR,-1\nBAZ,-2\n"
+ #
+ # \String output with headers:
+ #
+ # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
+ # out_string = ''
+ # CSV.filter(in_string, out_string, headers: true) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end # => #<CSV::Table mode:col_or_row row_count:4>
+ # out_string # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n"
+ #
+ # \IO stream output without headers:
+ #
+ # in_string = "foo,0\nbar,1\nbaz,2"
+ # File.open('t.csv', 'w') do |out_io|
+ # CSV.filter(in_string, out_io) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end
+ # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
+ # File.read('t.csv') # => "FOO,0\nBAR,-1\nBAZ,-2\n"
+ #
+ # \IO stream output with headers:
+ #
+ # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
+ # File.open('t.csv', 'w') do |out_io|
+ # CSV.filter(in_string, out_io, headers: true) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end
+ # end # => #<CSV::Table mode:col_or_row row_count:4>
+ # File.read('t.csv') # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n"
+ #
+ # When neither +in_string_or_io+ nor +out_string_or_io+ given,
+ # parses from {ARGF}[rdoc-ref:ARGF]
+ # and generates to STDOUT.
+ #
+ # Without headers:
+ #
+ # # Put Ruby code into a file.
+ # ruby = <<-EOT
+ # require 'csv'
+ # CSV.filter do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end
+ # EOT
+ # File.write('t.rb', ruby)
+ # # Put some CSV into a file.
+ # File.write('t.csv', "foo,0\nbar,1\nbaz,2")
+ # # Run the Ruby code with CSV filename as argument.
+ # system(Gem.ruby, "t.rb", "t.csv")
+ #
+ # Output (to STDOUT):
+ #
+ # FOO,0
+ # BAR,-1
+ # BAZ,-2
+ #
+ # With headers:
+ #
+ # # Put Ruby code into a file.
+ # ruby = <<-EOT
+ # require 'csv'
+ # CSV.filter(headers: true) do |row|
+ # row[0].upcase!
+ # row[1] = - row[1].to_i
+ # end
+ # EOT
+ # File.write('t.rb', ruby)
+ # # Put some CSV into a file.
+ # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2")
+ # # Run the Ruby code with CSV filename as argument.
+ # system(Gem.ruby, "t.rb", "t.csv")
+ #
+ # Output (to STDOUT):
+ #
+ # Name,Value
+ # FOO,0
+ # BAR,-1
+ # BAZ,-2
+ #
+ # Arguments:
+ #
+ # * Argument +in_string_or_io+ must be a \String or an \IO stream.
+ # * Argument +out_string_or_io+ must be a \String or an \IO stream.
+ # * Arguments <tt>**options</tt> must be keyword options.
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
def filter(input=nil, output=nil, **options)
# parse options for input, output, or both
- in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
+ in_options, out_options = Hash.new, {row_sep: InputRecordSeparator.value}
options.each do |key, value|
- case key.to_s
+ case key
when /\Ain(?:put)?_(.+)\Z/
in_options[$1.to_sym] = value
when /\Aout(?:put)?_(.+)\Z/
@@ -1095,111 +1244,90 @@ class CSV
#
# :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
+ # foreach(path_or_io, mode='r', **options) {|row| ... )
+ # foreach(path_or_io, mode='r', **options) -> new_enumerator
#
- # Calls the block with each row read from source +path+ or +io+.
+ # 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.
+ # \Path input without headers:
#
- # These examples assume prior execution of:
# string = "foo,0\nbar,1\nbaz,2\n"
- # path = 't.csv'
- # File.write(path, string)
+ # in_path = 't.csv'
+ # File.write(in_path, string)
+ # CSV.foreach(in_path) {|row| p row }
#
- # 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")>
+ # \Path input with headers:
+ #
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # in_path = 't.csv'
+ # File.write(in_path, string)
+ # CSV.foreach(in_path, headers: true) {|row| p row }
#
- # 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+
+ # <CSV::Row "Name":"foo" "Value":"0">
+ # <CSV::Row "Name":"bar" "Value":"1">
+ # <CSV::Row "Name":"baz" "Value":"2">
#
- # With {option +headers+}[#class-CSV-label-Option+headers],
- # returns each row as a CSV::Row object.
+ # \IO stream input without headers:
#
- # These examples assume prior execution of:
- # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
+ # 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, headers: true) {|row| p row }
+ # File.open('t.csv') do |in_io|
+ # CSV.foreach(in_io) {|row| p row }
+ # end
#
# 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 }
+ # ["foo", "0"]
+ # ["bar", "1"]
+ # ["baz", "2"]
+ #
+ # \IO stream input with headers:
+ #
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # File.open('t.csv') do |in_io|
+ # CSV.foreach(in_io, headers: true) {|row| p row }
# end
#
# Output:
- # #<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| }
+ # <CSV::Row "Name":"foo" "Value":"0">
+ # <CSV::Row "Name":"bar" "Value":"1">
+ # <CSV::Row "Name":"baz" "Value":"2">
#
- # 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| }
+ # With no block given, returns an \Enumerator:
#
- # Raises an exception if +mode+ is invalid:
- # # Raises ArgumentError (invalid access mode nosuch):
- # CSV.foreach(path, 'nosuch') {|row| }
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
#
+ # Arguments:
+ # * Argument +path_or_io+ must be a file path or an \IO stream.
+ # * Argument +mode+, if given, must be a \File mode
+ # See {Open Mode}[https://ruby-doc.org/core/IO.html#method-c-new-label-Open+Mode].
+ # * Arguments <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.
def foreach(path, mode="r", **options, &block)
return to_enum(__method__, path, mode, **options) unless block_given?
open(path, mode, **options) do |csv|
@@ -1292,8 +1420,8 @@ class CSV
# Argument +ary+ must be an \Array.
#
# Special options:
- # * Option <tt>:row_sep</tt> defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
- # (<tt>$/</tt>).:
+ # * Option <tt>:row_sep</tt> defaults to <tt>"\n"> on Ruby 3.0 or later
+ # and <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) otherwise.:
# $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
@@ -1315,7 +1443,7 @@ class CSV
# CSV.generate_line(:foo)
#
def generate_line(row, **options)
- options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
+ options = {row_sep: InputRecordSeparator.value}.merge(options)
str = +""
if options[:encoding]
str.force_encoding(options[:encoding])
@@ -1337,6 +1465,46 @@ class CSV
(new(str, **options) << row).string
end
+ # :call-seq:
+ # CSV.generate_lines(rows)
+ # CSV.generate_lines(rows, **options)
+ #
+ # Returns the \String created by generating \CSV from
+ # using the specified +options+.
+ #
+ # Argument +rows+ must be an \Array of row. Row is \Array of \String or \CSV::Row.
+ #
+ # Special options:
+ # * Option <tt>:row_sep</tt> defaults to <tt>"\n"</tt> on Ruby 3.0 or later
+ # and <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) otherwise.:
+ # $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].
+ #
+ # ---
+ #
+ # Returns the \String generated from an
+ # CSV.generate_lines([['foo', '0'], ['bar', '1'], ['baz', '2']]) # => "foo,0\nbar,1\nbaz,2\n"
+ #
+ # ---
+ #
+ # Raises an exception
+ # # Raises NoMethodError (undefined method `each' for :foo:Symbol)
+ # CSV.generate_lines(:foo)
+ #
+ def generate_lines(rows, **options)
+ self.generate(**options) do |csv|
+ rows.each do |row|
+ csv << row
+ end
+ end
+ end
+
#
# :call-seq:
# open(file_path, mode = "rb", **options ) -> new_csv
@@ -1345,7 +1513,7 @@ class CSV
# open(io, mode = "rb", **options ) { |csv| ... } -> object
#
# possible options elements:
- # hash form:
+ # keyword form:
# :invalid => nil # raise error on invalid byte sequence (default)
# :invalid => :replace # replace invalid byte sequence
# :undef => :replace # replace undefined conversion
@@ -1412,10 +1580,14 @@ class CSV
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)
+ file_opts = options.dup
+ unless file_opts.key?(:newline)
+ file_opts[:universal_newline] ||= false
+ end
options.delete(:invalid)
options.delete(:undef)
options.delete(:replace)
+ options.delete_if {|k, _| /newline\z/.match?(k)}
begin
f = File.open(filename, mode, **file_opts)
@@ -1734,6 +1906,7 @@ class CSV
row_sep: :auto,
quote_char: '"',
field_size_limit: nil,
+ max_field_size: nil,
converters: nil,
unconverted_fields: nil,
headers: false,
@@ -1749,16 +1922,27 @@ class CSV
encoding: nil,
nil_value: nil,
empty_value: "",
+ strip: false,
quote_empty: true,
write_converters: nil,
write_nil_value: nil,
- write_empty_value: "",
- strip: false)
+ write_empty_value: "")
raise ArgumentError.new("Cannot parse nil as CSV") if data.nil?
if data.is_a?(String)
+ if encoding
+ if encoding.is_a?(String)
+ data_external_encoding, data_internal_encoding = encoding.split(":", 2)
+ if data_internal_encoding
+ data = data.encode(data_internal_encoding, data_external_encoding)
+ else
+ data = data.dup.force_encoding(data_external_encoding)
+ end
+ else
+ data = data.dup.force_encoding(encoding)
+ end
+ end
@io = StringIO.new(data)
- @io.set_encoding(encoding || data.encoding)
else
@io = data
end
@@ -1776,11 +1960,14 @@ class CSV
@initial_header_converters = header_converters
@initial_write_converters = write_converters
+ if max_field_size.nil? and field_size_limit
+ max_field_size = field_size_limit - 1
+ end
@parser_options = {
column_separator: col_sep,
row_separator: row_sep,
quote_character: quote_char,
- field_size_limit: field_size_limit,
+ max_field_size: max_field_size,
unconverted_fields: unconverted_fields,
headers: headers,
return_headers: return_headers,
@@ -1848,11 +2035,25 @@ class CSV
# Returns the limit for field size; used for parsing;
# see {Option +field_size_limit+}[#class-CSV-label-Option+field_size_limit]:
# CSV.new('').field_size_limit # => nil
+ #
+ # Deprecated since 3.2.3. Use +max_field_size+ instead.
def field_size_limit
parser.field_size_limit
end
# :call-seq:
+ # csv.max_field_size -> integer or nil
+ #
+ # Returns the limit for field size; used for parsing;
+ # see {Option +max_field_size+}[#class-CSV-label-Option+max_field_size]:
+ # CSV.new('').max_field_size # => nil
+ #
+ # Since 3.2.3.
+ def max_field_size
+ parser.max_field_size
+ end
+
+ # :call-seq:
# csv.skip_lines -> regexp or nil
#
# Returns the \Regexp used to identify comment lines; used for parsing;
@@ -1873,6 +2074,10 @@ class CSV
# csv.converters # => [:integer]
# csv.convert(proc {|x| x.to_s })
# csv.converters
+ #
+ # Notes that you need to call
+ # +Ractor.make_shareable(CSV::Converters)+ on the main Ractor to use
+ # this method.
def converters
parser_fields_converter.map do |converter|
name = Converters.rassoc(converter)
@@ -1935,6 +2140,10 @@ class CSV
# Returns an \Array containing header converters; used for parsing;
# see {Header Converters}[#class-CSV-label-Header+Converters]:
# CSV.new('').header_converters # => []
+ #
+ # Notes that you need to call
+ # +Ractor.make_shareable(CSV::HeaderConverters)+ on the main Ractor
+ # to use this method.
def header_converters
header_fields_converter.map do |converter|
name = HeaderConverters.rassoc(converter)
@@ -1974,7 +2183,7 @@ class CSV
end
# :call-seq:
- # csv.encoding -> endcoding
+ # csv.encoding -> encoding
#
# Returns the encoding used for parsing and generating;
# see {Character Encodings (M17n or Multilingualization)}[#class-CSV-label-Character+Encodings+-28M17n+or+Multilingualization-29]:
@@ -2342,7 +2551,13 @@ class CSV
# p row
# end
def each(&block)
- parser_enumerator.each(&block)
+ return to_enum(__method__) unless block_given?
+ begin
+ while true
+ yield(parser_enumerator.next)
+ end
+ rescue StopIteration
+ end
end
# :call-seq:
@@ -2575,7 +2790,7 @@ class CSV
def build_parser_fields_converter
specific_options = {
- builtin_converters: Converters,
+ builtin_converters_name: :Converters,
}
options = @base_fields_converter_options.merge(specific_options)
build_fields_converter(@initial_converters, options)
@@ -2587,7 +2802,7 @@ class CSV
def build_header_fields_converter
specific_options = {
- builtin_converters: HeaderConverters,
+ builtin_converters_name: :HeaderConverters,
accept_nil: true,
}
options = @base_fields_converter_options.merge(specific_options)
@@ -2650,8 +2865,15 @@ end
# c.read.any? { |a| a.include?("zombies") }
# } #=> false
#
-def CSV(*args, &block)
- CSV.instance(*args, &block)
+# CSV options may also be given.
+#
+# io = StringIO.new
+# CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }
+#
+# This API is not Ractor-safe.
+#
+def CSV(*args, **options, &block)
+ CSV.instance(*args, **options, &block)
end
require_relative "csv/version"
diff --git a/lib/csv/csv.gemspec b/lib/csv/csv.gemspec
index d0284728f7..11c5b0f2a6 100644
--- a/lib/csv/csv.gemspec
+++ b/lib/csv/csv.gemspec
@@ -60,5 +60,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "benchmark_driver"
- spec.add_development_dependency "simplecov"
+ spec.add_development_dependency "test-unit", ">= 3.4.8"
end
diff --git a/lib/csv/fields_converter.rb b/lib/csv/fields_converter.rb
index 178ffb37bc..d15977d379 100644
--- a/lib/csv/fields_converter.rb
+++ b/lib/csv/fields_converter.rb
@@ -16,7 +16,7 @@ class CSV
@empty_value = options[:empty_value]
@empty_value_is_empty_string = (@empty_value == "")
@accept_nil = options[:accept_nil]
- @builtin_converters = options[:builtin_converters]
+ @builtin_converters_name = options[:builtin_converters_name]
@need_static_convert = need_static_convert?
end
@@ -24,7 +24,7 @@ class CSV
if name.nil? # custom converter
@converters << converter
else # named converter
- combo = @builtin_converters[name]
+ combo = builtin_converters[name]
case combo
when Array # combo converter
combo.each do |sub_name|
@@ -44,7 +44,7 @@ class CSV
@converters.empty?
end
- def convert(fields, headers, lineno)
+ def convert(fields, headers, lineno, quoted_fields)
return fields unless need_convert?
fields.collect.with_index do |field, index|
@@ -63,7 +63,8 @@ class CSV
else
header = nil
end
- field = converter[field, FieldInfo.new(index, lineno, header)]
+ quoted = quoted_fields[index]
+ field = converter[field, FieldInfo.new(index, lineno, header, quoted)]
end
break unless field.is_a?(String) # short-circuit pipeline for speed
end
@@ -80,5 +81,9 @@ class CSV
@need_static_convert or
(not @converters.empty?)
end
+
+ def builtin_converters
+ @builtin_converters ||= ::CSV.const_get(@builtin_converters_name)
+ end
end
end
diff --git a/lib/csv/input_record_separator.rb b/lib/csv/input_record_separator.rb
new file mode 100644
index 0000000000..7a99343c0c
--- /dev/null
+++ b/lib/csv/input_record_separator.rb
@@ -0,0 +1,18 @@
+require "English"
+require "stringio"
+
+class CSV
+ module InputRecordSeparator
+ class << self
+ if RUBY_VERSION >= "3.0.0"
+ def value
+ "\n"
+ end
+ else
+ def value
+ $INPUT_RECORD_SEPARATOR
+ end
+ end
+ end
+ end
+end
diff --git a/lib/csv/parser.rb b/lib/csv/parser.rb
index 2fb3b0a46e..afb3131cd5 100644
--- a/lib/csv/parser.rb
+++ b/lib/csv/parser.rb
@@ -2,14 +2,10 @@
require "strscan"
-require_relative "delete_suffix"
-require_relative "match_p"
+require_relative "input_record_separator"
require_relative "row"
require_relative "table"
-using CSV::DeleteSuffix if CSV.const_defined?(:DeleteSuffix)
-using CSV::MatchP if CSV.const_defined?(:MatchP)
-
class CSV
# Note: Don't use this class directly. This is an internal class.
class Parser
@@ -26,6 +22,10 @@ class CSV
class InvalidEncoding < StandardError
end
+ # Raised when unexpected case is happen.
+ class UnexpectedError < StandardError
+ end
+
#
# CSV::Scanner receives a CSV output, scans it and return the content.
# It also controls the life cycle of the object with its methods +keep_start+,
@@ -77,16 +77,17 @@ class CSV
# +keep_end+, +keep_back+, +keep_drop+.
#
# CSV::InputsScanner.scan() tries to match with pattern at the current position.
- # If there's a match, the scanner advances the “scan pointer” and returns the matched string.
+ # If there's a match, the scanner advances the "scan pointer" and returns the matched string.
# Otherwise, the scanner returns nil.
#
- # CSV::InputsScanner.rest() returns the “rest” of the string (i.e. everything after the scan pointer).
+ # CSV::InputsScanner.rest() returns the "rest" of the string (i.e. everything after the scan pointer).
# If there is no more data (eos? = true), it returns "".
#
class InputsScanner
- def initialize(inputs, encoding, chunk_size: 8192)
+ def initialize(inputs, encoding, row_separator, chunk_size: 8192)
@inputs = inputs.dup
@encoding = encoding
+ @row_separator = row_separator
@chunk_size = chunk_size
@last_scanner = @inputs.empty?
@keeps = []
@@ -94,11 +95,13 @@ class CSV
end
def each_line(row_separator)
+ return enum_for(__method__, row_separator) unless block_given?
buffer = nil
input = @scanner.rest
position = @scanner.pos
offset = 0
n_row_separator_chars = row_separator.size
+ # trace(__method__, :start, line, input)
while true
input.each_line(row_separator) do |line|
@scanner.pos += line.bytesize
@@ -138,25 +141,28 @@ class CSV
end
def scan(pattern)
+ # trace(__method__, pattern, :start)
value = @scanner.scan(pattern)
+ # trace(__method__, pattern, :done, :last, value) if @last_scanner
return value if @last_scanner
- if value
- read_chunk if @scanner.eos?
- return value
- else
- nil
- end
+ read_chunk if value and @scanner.eos?
+ # trace(__method__, pattern, :done, value)
+ value
end
def scan_all(pattern)
+ # trace(__method__, pattern, :start)
value = @scanner.scan(pattern)
+ # trace(__method__, pattern, :done, :last, value) if @last_scanner
return value if @last_scanner
return nil if value.nil?
while @scanner.eos? and read_chunk and (sub_value = @scanner.scan(pattern))
+ # trace(__method__, pattern, :sub, sub_value)
value << sub_value
end
+ # trace(__method__, pattern, :done, value)
value
end
@@ -165,76 +171,135 @@ class CSV
end
def keep_start
- @keeps.push([@scanner.pos, nil])
+ # trace(__method__, :start)
+ adjust_last_keep
+ @keeps.push([@scanner, @scanner.pos, nil])
+ # trace(__method__, :done)
end
def keep_end
- start, buffer = @keeps.pop
- keep = @scanner.string.byteslice(start, @scanner.pos - start)
+ # trace(__method__, :start)
+ scanner, start, buffer = @keeps.pop
+ if scanner == @scanner
+ keep = @scanner.string.byteslice(start, @scanner.pos - start)
+ else
+ keep = @scanner.string.byteslice(0, @scanner.pos)
+ end
if buffer
buffer << keep
keep = buffer
end
+ # trace(__method__, :done, keep)
keep
end
def keep_back
- start, buffer = @keeps.pop
+ # trace(__method__, :start)
+ scanner, start, buffer = @keeps.pop
if buffer
+ # trace(__method__, :rescan, start, buffer)
string = @scanner.string
- keep = string.byteslice(start, string.bytesize - start)
+ if scanner == @scanner
+ keep = string.byteslice(start, string.bytesize - start)
+ else
+ keep = string
+ end
if keep and not keep.empty?
@inputs.unshift(StringIO.new(keep))
@last_scanner = false
end
@scanner = StringScanner.new(buffer)
else
+ if @scanner != scanner
+ message = "scanners are different but no buffer: "
+ message += "#{@scanner.inspect}(#{@scanner.object_id}): "
+ message += "#{scanner.inspect}(#{scanner.object_id})"
+ raise UnexpectedError, message
+ end
+ # trace(__method__, :repos, start, buffer)
@scanner.pos = start
end
read_chunk if @scanner.eos?
end
def keep_drop
- @keeps.pop
+ _, _, buffer = @keeps.pop
+ # trace(__method__, :done, :empty) unless buffer
+ return unless buffer
+
+ last_keep = @keeps.last
+ # trace(__method__, :done, :no_last_keep) unless last_keep
+ return unless last_keep
+
+ if last_keep[2]
+ last_keep[2] << buffer
+ else
+ last_keep[2] = buffer
+ end
+ # trace(__method__, :done)
end
def rest
@scanner.rest
end
+ def check(pattern)
+ @scanner.check(pattern)
+ end
+
private
- def read_chunk
- return false if @last_scanner
+ def trace(*args)
+ pp([*args, @scanner, @scanner&.string, @scanner&.pos, @keeps])
+ end
- unless @keeps.empty?
- keep = @keeps.last
- keep_start = keep[0]
- string = @scanner.string
- keep_data = string.byteslice(keep_start, @scanner.pos - keep_start)
- if keep_data
- keep_buffer = keep[1]
- if keep_buffer
- keep_buffer << keep_data
- else
- keep[1] = keep_data.dup
- end
+ def adjust_last_keep
+ # trace(__method__, :start)
+
+ keep = @keeps.last
+ # trace(__method__, :done, :empty) if keep.nil?
+ return if keep.nil?
+
+ scanner, start, buffer = keep
+ string = @scanner.string
+ if @scanner != scanner
+ start = 0
+ end
+ if start == 0 and @scanner.eos?
+ keep_data = string
+ else
+ keep_data = string.byteslice(start, @scanner.pos - start)
+ end
+ if keep_data
+ if buffer
+ buffer << keep_data
+ else
+ keep[2] = keep_data.dup
end
- keep[0] = 0
end
+ # trace(__method__, :done)
+ end
+
+ def read_chunk
+ return false if @last_scanner
+
+ adjust_last_keep
+
input = @inputs.first
case input
when StringIO
string = input.read
raise InvalidEncoding unless string.valid_encoding?
+ # trace(__method__, :stringio, string)
@scanner = StringScanner.new(string)
@inputs.shift
@last_scanner = @inputs.empty?
true
else
- chunk = input.gets(nil, @chunk_size)
+ chunk = input.gets(@row_separator, @chunk_size)
if chunk
raise InvalidEncoding unless chunk.valid_encoding?
+ # trace(__method__, :chunk, chunk)
@scanner = StringScanner.new(chunk)
if input.respond_to?(:eof?) and input.eof?
@inputs.shift
@@ -242,6 +307,7 @@ class CSV
end
true
else
+ # trace(__method__, :no_chunk)
@scanner = StringScanner.new("".encode(@encoding))
@inputs.shift
@last_scanner = @inputs.empty?
@@ -276,7 +342,11 @@ class CSV
end
def field_size_limit
- @field_size_limit
+ @max_field_size&.succ
+ end
+
+ def max_field_size
+ @max_field_size
end
def skip_lines
@@ -344,6 +414,16 @@ class CSV
end
message = "Invalid byte sequence in #{@encoding}"
raise MalformedCSVError.new(message, lineno)
+ rescue UnexpectedError => error
+ if @scanner
+ ignore_broken_line
+ lineno = @lineno
+ else
+ lineno = @lineno + 1
+ end
+ message = "This should not be happen: #{error.message}: "
+ message += "Please report this to https://github.com/ruby/csv/issues"
+ raise MalformedCSVError.new(message, lineno)
end
end
@@ -360,6 +440,7 @@ class CSV
prepare_skip_lines
prepare_strip
prepare_separators
+ validate_strip_and_col_sep_options
prepare_quoted
prepare_unquoted
prepare_line
@@ -387,7 +468,7 @@ class CSV
@backslash_quote = false
end
@unconverted_fields = @options[:unconverted_fields]
- @field_size_limit = @options[:field_size_limit]
+ @max_field_size = @options[:max_field_size]
@skip_blanks = @options[:skip_blanks]
@fields_converter = @options[:fields_converter]
@header_fields_converter = @options[:header_fields_converter]
@@ -479,9 +560,9 @@ class CSV
begin
StringScanner.new("x").scan("x")
rescue TypeError
- @@string_scanner_scan_accept_string = false
+ STRING_SCANNER_SCAN_ACCEPT_STRING = false
else
- @@string_scanner_scan_accept_string = true
+ STRING_SCANNER_SCAN_ACCEPT_STRING = true
end
def prepare_separators
@@ -505,7 +586,7 @@ class CSV
@first_column_separators = Regexp.new(@escaped_first_column_separator +
"+".encode(@encoding))
else
- if @@string_scanner_scan_accept_string
+ if STRING_SCANNER_SCAN_ACCEPT_STRING
@column_end = @column_separator
else
@column_end = Regexp.new(@escaped_column_separator)
@@ -526,10 +607,32 @@ class CSV
@cr = "\r".encode(@encoding)
@lf = "\n".encode(@encoding)
- @cr_or_lf = Regexp.new("[\r\n]".encode(@encoding))
+ @line_end = Regexp.new("\r\n|\n|\r".encode(@encoding))
@not_line_end = Regexp.new("[^\r\n]+".encode(@encoding))
end
+ # This method verifies that there are no (obvious) ambiguities with the
+ # provided +col_sep+ and +strip+ parsing options. For example, if +col_sep+
+ # and +strip+ were both equal to +\t+, then there would be no clear way to
+ # parse the input.
+ def validate_strip_and_col_sep_options
+ return unless @strip
+
+ if @strip.is_a?(String)
+ if @column_separator.start_with?(@strip) || @column_separator.end_with?(@strip)
+ raise ArgumentError,
+ "The provided strip (#{@escaped_strip}) and " \
+ "col_sep (#{@escaped_column_separator}) options are incompatible."
+ end
+ else
+ if Regexp.new("\\A[#{@escaped_strip}]|[#{@escaped_strip}]\\z").match?(@column_separator)
+ raise ArgumentError,
+ "The provided strip (true) and " \
+ "col_sep (#{@escaped_column_separator}) options are incompatible."
+ end
+ end
+ end
+
def prepare_quoted
if @quote_character
@quotes = Regexp.new(@escaped_quote_character +
@@ -605,7 +708,7 @@ class CSV
# do nothing: ensure will set default
end
end
- separator = $INPUT_RECORD_SEPARATOR if separator == :auto
+ separator = InputRecordSeparator.value if separator == :auto
end
separator.to_s.encode(@encoding)
end
@@ -655,9 +758,10 @@ class CSV
case headers
when Array
@raw_headers = headers
+ quoted_fields = [false] * @raw_headers.size
@use_headers = true
when String
- @raw_headers = parse_headers(headers)
+ @raw_headers, quoted_fields = parse_headers(headers)
@use_headers = true
when nil, false
@raw_headers = nil
@@ -667,21 +771,28 @@ class CSV
@use_headers = true
end
if @raw_headers
- @headers = adjust_headers(@raw_headers)
+ @headers = adjust_headers(@raw_headers, quoted_fields)
else
@headers = nil
end
end
def parse_headers(row)
- CSV.parse_line(row,
- col_sep: @column_separator,
- row_sep: @row_separator,
- quote_char: @quote_character)
+ quoted_fields = []
+ converter = lambda do |field, info|
+ quoted_fields << info.quoted?
+ field
+ end
+ headers = CSV.parse_line(row,
+ col_sep: @column_separator,
+ row_sep: @row_separator,
+ quote_char: @quote_character,
+ converters: [converter])
+ [headers, quoted_fields]
end
- def adjust_headers(headers)
- adjusted_headers = @header_fields_converter.convert(headers, nil, @lineno)
+ def adjust_headers(headers, quoted_fields)
+ adjusted_headers = @header_fields_converter.convert(headers, nil, @lineno, quoted_fields)
adjusted_headers.each {|h| h.freeze if h.is_a? String}
adjusted_headers
end
@@ -704,26 +815,28 @@ class CSV
sample[0, 128].index(@quote_character)
end
- SCANNER_TEST = (ENV["CSV_PARSER_SCANNER_TEST"] == "yes")
- if SCANNER_TEST
- class UnoptimizedStringIO
- def initialize(string)
- @io = StringIO.new(string, "rb:#{string.encoding}")
- end
+ class UnoptimizedStringIO # :nodoc:
+ def initialize(string)
+ @io = StringIO.new(string, "rb:#{string.encoding}")
+ end
- def gets(*args)
- @io.gets(*args)
- end
+ def gets(*args)
+ @io.gets(*args)
+ end
- def each_line(*args, &block)
- @io.each_line(*args, &block)
- end
+ def each_line(*args, &block)
+ @io.each_line(*args, &block)
+ end
- def eof?
- @io.eof?
- end
+ def eof?
+ @io.eof?
end
+ end
+ SCANNER_TEST = (ENV["CSV_PARSER_SCANNER_TEST"] == "yes")
+ if SCANNER_TEST
+ SCANNER_TEST_CHUNK_SIZE_NAME = "CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"
+ SCANNER_TEST_CHUNK_SIZE_VALUE = ENV[SCANNER_TEST_CHUNK_SIZE_NAME]
def build_scanner
inputs = @samples.collect do |sample|
UnoptimizedStringIO.new(sample)
@@ -733,17 +846,27 @@ class CSV
else
inputs << @input
end
- chunk_size = ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] || "1"
+ begin
+ chunk_size_value = ENV[SCANNER_TEST_CHUNK_SIZE_NAME]
+ rescue # Ractor::IsolationError
+ # Ractor on Ruby 3.0 can't read ENV value.
+ chunk_size_value = SCANNER_TEST_CHUNK_SIZE_VALUE
+ end
+ chunk_size = Integer((chunk_size_value || "1"), 10)
InputsScanner.new(inputs,
@encoding,
- chunk_size: Integer(chunk_size, 10))
+ @row_separator,
+ chunk_size: chunk_size)
end
else
def build_scanner
string = nil
if @samples.empty? and @input.is_a?(StringIO)
string = @input.read
- elsif @samples.size == 1 and @input.respond_to?(:eof?) and @input.eof?
+ elsif @samples.size == 1 and
+ @input != ARGF and
+ @input.respond_to?(:eof?) and
+ @input.eof?
string = @samples[0]
end
if string
@@ -762,7 +885,7 @@ class CSV
StringIO.new(sample)
end
inputs << @input
- InputsScanner.new(inputs, @encoding)
+ InputsScanner.new(inputs, @encoding, @row_separator)
end
end
end
@@ -796,6 +919,14 @@ class CSV
end
end
+ def validate_field_size(field)
+ return unless @max_field_size
+ return if field.size <= @max_field_size
+ ignore_broken_line
+ message = "Field size exceeded: #{field.size} > #{@max_field_size}"
+ raise MalformedCSVError.new(message, @lineno)
+ end
+
def parse_no_quote(&block)
@scanner.each_line(@row_separator) do |line|
next if @skip_lines and skip_line?(line)
@@ -805,9 +936,16 @@ class CSV
if line.empty?
next if @skip_blanks
row = []
+ quoted_fields = []
else
line = strip_value(line)
row = line.split(@split_column_separator, -1)
+ quoted_fields = [false] * row.size
+ if @max_field_size
+ row.each do |column|
+ validate_field_size(column)
+ end
+ end
n_columns = row.size
i = 0
while i < n_columns
@@ -816,7 +954,7 @@ class CSV
end
end
@last_line = original_line
- emit_row(row, &block)
+ emit_row(row, quoted_fields, &block)
end
end
@@ -838,31 +976,37 @@ class CSV
next
end
row = []
+ quoted_fields = []
elsif line.include?(@cr) or line.include?(@lf)
@scanner.keep_back
@need_robust_parsing = true
return parse_quotable_robust(&block)
else
row = line.split(@split_column_separator, -1)
+ quoted_fields = []
n_columns = row.size
i = 0
while i < n_columns
column = row[i]
if column.empty?
+ quoted_fields << false
row[i] = nil
else
n_quotes = column.count(@quote_character)
if n_quotes.zero?
+ quoted_fields << false
# no quote
elsif n_quotes == 2 and
column.start_with?(@quote_character) and
column.end_with?(@quote_character)
+ quoted_fields << true
row[i] = column[1..-2]
else
@scanner.keep_back
@need_robust_parsing = true
return parse_quotable_robust(&block)
end
+ validate_field_size(row[i])
end
i += 1
end
@@ -870,13 +1014,14 @@ class CSV
@scanner.keep_drop
@scanner.keep_start
@last_line = original_line
- emit_row(row, &block)
+ emit_row(row, quoted_fields, &block)
end
@scanner.keep_drop
end
def parse_quotable_robust(&block)
row = []
+ quoted_fields = []
skip_needless_lines
start_row
while true
@@ -886,35 +1031,42 @@ class CSV
value = parse_column_value
if value
@scanner.scan_all(@strip_value) if @strip_value
- if @field_size_limit and value.size >= @field_size_limit
- ignore_broken_line
- raise MalformedCSVError.new("Field size exceeded", @lineno)
- end
+ validate_field_size(value)
end
if parse_column_end
row << value
+ quoted_fields << @quoted_column_value
elsif parse_row_end
if row.empty? and value.nil?
- emit_row([], &block) unless @skip_blanks
+ emit_row([], [], &block) unless @skip_blanks
else
row << value
- emit_row(row, &block)
+ quoted_fields << @quoted_column_value
+ emit_row(row, quoted_fields, &block)
row = []
+ quoted_fields = []
end
skip_needless_lines
start_row
elsif @scanner.eos?
break if row.empty? and value.nil?
row << value
- emit_row(row, &block)
+ quoted_fields << @quoted_column_value
+ emit_row(row, quoted_fields, &block)
break
else
if @quoted_column_value
+ if liberal_parsing? and (new_line = @scanner.check(@line_end))
+ message =
+ "Illegal end-of-line sequence outside of a quoted field " +
+ "<#{new_line.inspect}>"
+ else
+ message = "Any value after quoted field isn't allowed"
+ end
ignore_broken_line
- message = "Any value after quoted field isn't allowed"
raise MalformedCSVError.new(message, @lineno)
elsif @unquoted_column_value and
- (new_line = @scanner.scan(@cr_or_lf))
+ (new_line = @scanner.scan(@line_end))
ignore_broken_line
message = "Unquoted fields do not allow new line " +
"<#{new_line.inspect}>"
@@ -923,7 +1075,7 @@ class CSV
ignore_broken_line
message = "Illegal quoting"
raise MalformedCSVError.new(message, @lineno)
- elsif (new_line = @scanner.scan(@cr_or_lf))
+ elsif (new_line = @scanner.scan(@line_end))
ignore_broken_line
message = "New line must be <#{@row_separator.inspect}> " +
"not <#{new_line.inspect}>"
@@ -1004,7 +1156,7 @@ class CSV
if (n_quotes % 2).zero?
quotes[0, (n_quotes - 2) / 2]
else
- value = quotes[0, (n_quotes - 1) / 2]
+ value = quotes[0, n_quotes / 2]
while true
quoted_value = @scanner.scan_all(@quoted_value)
value << quoted_value if quoted_value
@@ -1028,11 +1180,9 @@ class CSV
n_quotes = quotes.size
if n_quotes == 1
break
- elsif (n_quotes % 2) == 1
- value << quotes[0, (n_quotes - 1) / 2]
- break
else
value << quotes[0, n_quotes / 2]
+ break if (n_quotes % 2) == 1
end
end
value
@@ -1068,18 +1218,15 @@ class CSV
def strip_value(value)
return value unless @strip
- return nil if value.nil?
+ return value if value.nil?
case @strip
when String
- size = value.size
- while value.start_with?(@strip)
- size -= 1
- value = value[1, size]
+ while value.delete_prefix!(@strip)
+ # do nothing
end
- while value.end_with?(@strip)
- size -= 1
- value = value[0, size]
+ while value.delete_suffix!(@strip)
+ # do nothing
end
else
value.strip!
@@ -1089,7 +1236,7 @@ class CSV
def ignore_broken_line
@scanner.scan_all(@not_line_end)
- @scanner.scan_all(@cr_or_lf)
+ @scanner.scan_all(@line_end)
@lineno += 1
end
@@ -1102,22 +1249,22 @@ class CSV
@scanner.keep_start
end
- def emit_row(row, &block)
+ def emit_row(row, quoted_fields, &block)
@lineno += 1
raw_row = row
if @use_headers
if @headers.nil?
- @headers = adjust_headers(row)
+ @headers = adjust_headers(row, quoted_fields)
return unless @return_headers
row = Row.new(@headers, row, true)
else
row = Row.new(@headers,
- @fields_converter.convert(raw_row, @headers, @lineno))
+ @fields_converter.convert(raw_row, @headers, @lineno, quoted_fields))
end
else
# convert fields, if needed...
- row = @fields_converter.convert(raw_row, nil, @lineno)
+ row = @fields_converter.convert(raw_row, nil, @lineno, quoted_fields)
end
# inject unconverted fields and accessor, if requested...
diff --git a/lib/csv/row.rb b/lib/csv/row.rb
index 0f465ea2a3..86323f7d0a 100644
--- a/lib/csv/row.rb
+++ b/lib/csv/row.rb
@@ -3,30 +3,105 @@
require "forwardable"
class CSV
+ # = \CSV::Row
+ # A \CSV::Row instance represents a \CSV table row.
+ # (see {class CSV}[../CSV.html]).
#
- # A CSV::Row is part Array and part Hash. It retains an order for the fields
- # and allows duplicates just as an Array would, but also allows you to access
- # fields by name just as you could if they were in a Hash.
+ # The instance may have:
+ # - Fields: each is an object, not necessarily a \String.
+ # - Headers: each serves a key, and also need not be a \String.
#
- # All rows returned by CSV will be constructed from this class, if header row
- # processing is activated.
+ # === Instance Methods
+ #
+ # \CSV::Row has three groups of instance methods:
+ # - Its own internally defined instance methods.
+ # - Methods included by module Enumerable.
+ # - Methods delegated to class Array.:
+ # * Array#empty?
+ # * Array#length
+ # * Array#size
+ #
+ # == Creating a \CSV::Row Instance
+ #
+ # Commonly, a new \CSV::Row instance is created by parsing \CSV source
+ # that has headers:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.each {|row| p row }
+ # Output:
+ # #<CSV::Row "Name":"foo" "Value":"0">
+ # #<CSV::Row "Name":"bar" "Value":"1">
+ # #<CSV::Row "Name":"baz" "Value":"2">
+ #
+ # You can also create a row directly. See ::new.
+ #
+ # == Headers
+ #
+ # Like a \CSV::Table, a \CSV::Row has headers.
+ #
+ # A \CSV::Row that was created by parsing \CSV source
+ # inherits its headers from the table:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table.first
+ # row.headers # => ["Name", "Value"]
+ #
+ # You can also create a new row with headers;
+ # like the keys in a \Hash, the headers need not be Strings:
+ # row = CSV::Row.new([:name, :value], ['foo', 0])
+ # row.headers # => [:name, :value]
+ #
+ # The new row retains its headers even if added to a table
+ # that has headers:
+ # table << row # => #<CSV::Table mode:col_or_row row_count:5>
+ # row.headers # => [:name, :value]
+ # row[:name] # => "foo"
+ # row['Name'] # => nil
+ #
+ #
+ #
+ # == Accessing Fields
+ #
+ # You may access a field in a \CSV::Row with either its \Integer index
+ # (\Array-style) or its header (\Hash-style).
+ #
+ # Fetch a field using method #[]:
+ # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
+ # row[1] # => 0
+ # row['Value'] # => 0
+ #
+ # Set a field using method #[]=:
+ # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
+ # row # => #<CSV::Row "Name":"foo" "Value":0>
+ # row[0] = 'bar'
+ # row['Value'] = 1
+ # row # => #<CSV::Row "Name":"bar" "Value":1>
#
class Row
- #
- # Constructs a new CSV::Row from +headers+ and +fields+, which are expected
- # to be Arrays. If one Array is shorter than the other, it will be padded
- # with +nil+ objects.
- #
- # The optional +header_row+ parameter can be set to +true+ to indicate, via
- # CSV::Row.header_row?() and CSV::Row.field_row?(), that this is a header
- # row. Otherwise, the row assumes to be a field row.
- #
- # A CSV::Row object supports the following Array methods through delegation:
- #
- # * empty?()
- # * length()
- # * size()
- #
+ # :call-seq:
+ # CSV::Row.new(headers, fields, header_row = false) -> csv_row
+ #
+ # Returns the new \CSV::Row instance constructed from
+ # arguments +headers+ and +fields+; both should be Arrays;
+ # note that the fields need not be Strings:
+ # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
+ # row # => #<CSV::Row "Name":"foo" "Value":0>
+ #
+ # If the \Array lengths are different, the shorter is +nil+-filled:
+ # row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0])
+ # row # => #<CSV::Row "Name":"foo" "Value":0 "Date":nil "Size":nil>
+ #
+ # Each \CSV::Row object is either a <i>field row</i> or a <i>header row</i>;
+ # by default, a new row is a field row; for the row created above:
+ # row.field_row? # => true
+ # row.header_row? # => false
+ #
+ # If the optional argument +header_row+ is given as +true+,
+ # the created row is a header row:
+ # row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true)
+ # row # => #<CSV::Row "Name":"foo" "Value":0>
+ # row.field_row? # => false
+ # row.header_row? # => true
def initialize(headers, fields, header_row = false)
@header_row = header_row
headers.each { |h| h.freeze if h.is_a? String }
@@ -48,6 +123,10 @@ class CSV
extend Forwardable
def_delegators :@row, :empty?, :length, :size
+ # :call-seq:
+ # row.initialize_copy(other_row) -> self
+ #
+ # Calls superclass method.
def initialize_copy(other)
super_return_value = super
@row = @row.collect(&:dup)
@@ -71,7 +150,7 @@ class CSV
end
# :call-seq:
- # row.headers
+ # row.headers -> array_of_headers
#
# Returns the headers for this row:
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
@@ -83,9 +162,9 @@ class CSV
end
# :call-seq:
- # field(index)
- # field(header)
- # field(header, offset)
+ # field(index) -> value
+ # field(header) -> value
+ # field(header, offset) -> value
#
# Returns the field value for the given +index+ or +header+.
#
@@ -137,9 +216,9 @@ class CSV
#
# :call-seq:
- # fetch(header)
- # fetch(header, default)
- # fetch(header) {|row| ... }
+ # fetch(header) -> value
+ # fetch(header, default) -> value
+ # fetch(header) {|row| ... } -> value
#
# Returns the field value as specified by +header+.
#
@@ -193,7 +272,7 @@ class CSV
end
# :call-seq:
- # row.has_key?(header)
+ # row.has_key?(header) -> true or false
#
# Returns +true+ if there is a field with the given +header+,
# +false+ otherwise.
@@ -320,7 +399,7 @@ class CSV
end
# :call-seq:
- # row.push(*values) ->self
+ # 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"
@@ -403,7 +482,7 @@ class CSV
end
# :call-seq:
- # self.fields(*specifiers)
+ # self.fields(*specifiers) -> array_of_fields
#
# Returns field values per the given +specifiers+, which may be any mixture of:
# - \Integer index.
@@ -471,15 +550,26 @@ class CSV
end
alias_method :values_at, :fields
- #
# :call-seq:
- # index( header )
- # index( header, offset )
+ # index(header) -> index
+ # index(header, offset) -> index
#
- # This method will return the index of a field with the provided +header+.
- # The +offset+ can be used to locate duplicate header names, as described in
- # CSV::Row.field().
+ # Returns the index for the given header, if it exists;
+ # otherwise returns +nil+.
#
+ # With the single argument +header+, returns the index
+ # of the first-found field with the given +header+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.index('Name') # => 0
+ # row.index('NAME') # => nil
+ #
+ # With arguments +header+ and +offset+,
+ # returns the index of the first-found field with given +header+,
+ # but ignoring the first +offset+ fields:
+ # row.index('Name', 1) # => 1
+ # row.index('Name', 3) # => nil
def index(header, minimum_index = 0)
# find the pair
index = headers[minimum_index..-1].index(header)
@@ -487,24 +577,36 @@ class CSV
index.nil? ? nil : index + minimum_index
end
+ # :call-seq:
+ # row.field?(value) -> true or false
#
- # Returns +true+ if +data+ matches a field in this row, and +false+
- # otherwise.
- #
+ # Returns +true+ if +value+ is a field in this row, +false+ otherwise:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.field?('Bar') # => true
+ # row.field?('BAR') # => false
def field?(data)
fields.include? data
end
include Enumerable
+ # :call-seq:
+ # row.each {|header, value| ... } -> self
#
- # Yields each pair of the row as header and field tuples (much like
- # iterating over a Hash). This method returns the row for chaining.
- #
- # If no block is given, an Enumerator is returned.
- #
- # Support for Enumerable.
+ # Calls the block with each header-value pair; returns +self+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.each {|header, value| p [header, value] }
+ # Output:
+ # ["Name", "Foo"]
+ # ["Name", "Bar"]
+ # ["Name", "Baz"]
#
+ # If no block is given, returns a new Enumerator:
+ # row.each # => #<Enumerator: #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz">:each>
def each(&block)
return enum_for(__method__) { size } unless block_given?
@@ -515,10 +617,19 @@ class CSV
alias_method :each_pair, :each
+ # :call-seq:
+ # row == other -> true or false
#
- # Returns +true+ if this row contains the same headers and fields in the
- # same order as +other+.
- #
+ # Returns +true+ if +other+ is a /CSV::Row that has the same
+ # fields (headers and values) in the same order as +self+;
+ # otherwise returns +false+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # other_row = table[0]
+ # row == other_row # => true
+ # other_row = table[1]
+ # row == other_row # => false
def ==(other)
return @row == other.row if other.is_a? CSV::Row
@row == other
@@ -548,9 +659,31 @@ class CSV
end
alias_method :to_hash, :to_h
+ # :call-seq:
+ # row.deconstruct_keys(keys) -> hash
+ #
+ # Returns the new \Hash suitable for pattern matching containing only the
+ # keys specified as an argument.
+ def deconstruct_keys(keys)
+ if keys.nil?
+ to_h
+ else
+ keys.to_h { |key| [key, self[key]] }
+ end
+ end
+
alias_method :to_ary, :to_a
# :call-seq:
+ # row.deconstruct -> array
+ #
+ # Returns the new \Array suitable for pattern matching containing the values
+ # of the row.
+ def deconstruct
+ fields
+ end
+
+ # :call-seq:
# row.to_csv -> csv_string
#
# Returns the row as a \CSV String. Headers are not included:
@@ -570,7 +703,7 @@ class CSV
# by +index_or_header+ and +specifiers+.
#
# The nested objects may be instances of various classes.
- # See {Dig Methods}[https://docs.ruby-lang.org/en/master/doc/dig_methods_rdoc.html].
+ # See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
#
# Examples:
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
diff --git a/lib/csv/table.rb b/lib/csv/table.rb
index 1ce0dd6daf..fb19f5453f 100644
--- a/lib/csv/table.rb
+++ b/lib/csv/table.rb
@@ -3,31 +3,199 @@
require "forwardable"
class CSV
+ # = \CSV::Table
+ # A \CSV::Table instance represents \CSV data.
+ # (see {class CSV}[../CSV.html]).
#
- # A CSV::Table is a two-dimensional data structure for representing CSV
- # documents. Tables allow you to work with the data by row or column,
- # manipulate the data, and even convert the results back to CSV, if needed.
+ # The instance may have:
+ # - Rows: each is a Table::Row object.
+ # - Headers: names for the columns.
#
- # All tables returned by CSV will be constructed from this class, if header
- # row processing is activated.
+ # === Instance Methods
#
+ # \CSV::Table has three groups of instance methods:
+ # - Its own internally defined instance methods.
+ # - Methods included by module Enumerable.
+ # - Methods delegated to class Array.:
+ # * Array#empty?
+ # * Array#length
+ # * Array#size
+ #
+ # == Creating a \CSV::Table Instance
+ #
+ # Commonly, a new \CSV::Table instance is created by parsing \CSV source
+ # using headers:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.class # => CSV::Table
+ #
+ # You can also create an instance directly. See ::new.
+ #
+ # == Headers
+ #
+ # If a table has headers, the headers serve as labels for the columns of data.
+ # Each header serves as the label for its column.
+ #
+ # The headers for a \CSV::Table object are stored as an \Array of Strings.
+ #
+ # Commonly, headers are defined in the first row of \CSV source:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.headers # => ["Name", "Value"]
+ #
+ # If no headers are defined, the \Array is empty:
+ # table = CSV::Table.new([])
+ # table.headers # => []
+ #
+ # == Access Modes
+ #
+ # \CSV::Table provides three modes for accessing table data:
+ # - \Row mode.
+ # - Column mode.
+ # - Mixed mode (the default for a new table).
+ #
+ # The access mode for a\CSV::Table instance affects the behavior
+ # of some of its instance methods:
+ # - #[]
+ # - #[]=
+ # - #delete
+ # - #delete_if
+ # - #each
+ # - #values_at
+ #
+ # === \Row Mode
+ #
+ # Set a table to row mode with method #by_row!:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ #
+ # Specify a single row by an \Integer index:
+ # # Get a row.
+ # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
+ # # Set a row, then get it.
+ # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
+ # table[1] # => #<CSV::Row "Name":"bam" "Value":3>
+ #
+ # Specify a sequence of rows by a \Range:
+ # # Get rows.
+ # table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
+ # # Set rows, then get them.
+ # table[1..2] = [
+ # CSV::Row.new(['Name', 'Value'], ['bat', 4]),
+ # CSV::Row.new(['Name', 'Value'], ['bad', 5]),
+ # ]
+ # table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
+ #
+ # === Column Mode
+ #
+ # Set a table to column mode with method #by_col!:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ #
+ # Specify a column by an \Integer index:
+ # # Get a column.
+ # table[0]
+ # # Set a column, then get it.
+ # table[0] = ['FOO', 'BAR', 'BAZ']
+ # table[0] # => ["FOO", "BAR", "BAZ"]
+ #
+ # Specify a column by its \String header:
+ # # Get a column.
+ # table['Name'] # => ["FOO", "BAR", "BAZ"]
+ # # Set a column, then get it.
+ # table['Name'] = ['Foo', 'Bar', 'Baz']
+ # table['Name'] # => ["Foo", "Bar", "Baz"]
+ #
+ # === Mixed Mode
+ #
+ # In mixed mode, you can refer to either rows or columns:
+ # - An \Integer index refers to a row.
+ # - A \Range index refers to multiple rows.
+ # - A \String index refers to a column.
+ #
+ # Set a table to mixed mode with method #by_col_or_row!:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
+ #
+ # Specify a single row by an \Integer index:
+ # # Get a row.
+ # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
+ # # Set a row, then get it.
+ # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
+ # table[1] # => #<CSV::Row "Name":"bam" "Value":3>
+ #
+ # Specify a sequence of rows by a \Range:
+ # # Get rows.
+ # table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
+ # # Set rows, then get them.
+ # table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4])
+ # table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5])
+ # table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
+ #
+ # Specify a column by its \String header:
+ # # Get a column.
+ # table['Name'] # => ["foo", "bat", "bad"]
+ # # Set a column, then get it.
+ # table['Name'] = ['Foo', 'Bar', 'Baz']
+ # table['Name'] # => ["Foo", "Bar", "Baz"]
class Table
+ # :call-seq:
+ # CSV::Table.new(array_of_rows, headers = nil) -> csv_table
+ #
+ # Returns a new \CSV::Table object.
+ #
+ # - Argument +array_of_rows+ must be an \Array of CSV::Row objects.
+ # - Argument +headers+, if given, may be an \Array of Strings.
+ #
+ # ---
+ #
+ # Create an empty \CSV::Table object:
+ # table = CSV::Table.new([])
+ # table # => #<CSV::Table mode:col_or_row row_count:1>
+ #
+ # Create a non-empty \CSV::Table object:
+ # rows = [
+ # CSV::Row.new([], []),
+ # CSV::Row.new([], []),
+ # CSV::Row.new([], []),
+ # ]
+ # table = CSV::Table.new(rows)
+ # table # => #<CSV::Table mode:col_or_row row_count:4>
+ #
+ # ---
#
- # Constructs a new CSV::Table from +array_of_rows+, which are expected
- # to be CSV::Row objects. All rows are assumed to have the same headers.
+ # If argument +headers+ is an \Array of Strings,
+ # those Strings become the table's headers:
+ # table = CSV::Table.new([], headers: ['Name', 'Age'])
+ # table.headers # => ["Name", "Age"]
#
- # The optional +headers+ parameter can be set to Array of headers.
- # If headers aren't set, headers are fetched from CSV::Row objects.
- # Otherwise, headers() method will return headers being set in
- # headers argument.
+ # If argument +headers+ is not given and the table has rows,
+ # the headers are taken from the first row:
+ # rows = [
+ # CSV::Row.new(['Foo', 'Bar'], []),
+ # CSV::Row.new(['foo', 'bar'], []),
+ # CSV::Row.new(['FOO', 'BAR'], []),
+ # ]
+ # table = CSV::Table.new(rows)
+ # table.headers # => ["Foo", "Bar"]
#
- # A CSV::Table object supports the following Array methods through
- # delegation:
+ # If argument +headers+ is not given and the table is empty (has no rows),
+ # the headers are also empty:
+ # table = CSV::Table.new([])
+ # table.headers # => []
#
- # * empty?()
- # * length()
- # * size()
+ # ---
#
+ # Raises an exception if argument +array_of_rows+ is not an \Array object:
+ # # Raises NoMethodError (undefined method `first' for :foo:Symbol):
+ # CSV::Table.new(:foo)
+ #
+ # Raises an exception if an element of +array_of_rows+ is not a \CSV::Table object:
+ # # Raises NoMethodError (undefined method `headers' for :foo:Symbol):
+ # CSV::Table.new([:foo])
def initialize(array_of_rows, headers: nil)
@table = array_of_rows
@headers = headers
@@ -54,88 +222,141 @@ class CSV
extend Forwardable
def_delegators :@table, :empty?, :length, :size
+ # :call-seq:
+ # table.by_col -> table_dup
#
- # Returns a duplicate table object, in column mode. This is handy for
- # chaining in a single call without changing the table mode, but be aware
- # that this method can consume a fair amount of memory for bigger data sets.
+ # Returns a duplicate of +self+, in column mode
+ # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]):
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.mode # => :col_or_row
+ # dup_table = table.by_col
+ # dup_table.mode # => :col
+ # dup_table.equal?(table) # => false # It's a dup
#
- # This method returns the duplicate table for chaining. Don't chain
- # destructive methods (like []=()) this way though, since you are working
- # with a duplicate.
+ # This may be used to chain method calls without changing the mode
+ # (but also will affect performance and memory usage):
+ # dup_table.by_col['Name']
#
+ # Also note that changes to the duplicate table will not affect the original.
def by_col
self.class.new(@table.dup).by_col!
end
+ # :call-seq:
+ # table.by_col! -> self
#
- # Switches the mode of this table to column mode. All calls to indexing and
- # iteration methods will work with columns until the mode is changed again.
- #
- # This method returns the table and is safe to chain.
- #
+ # Sets the mode for +self+ to column mode
+ # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]); returns +self+:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.mode # => :col_or_row
+ # table1 = table.by_col!
+ # table.mode # => :col
+ # table1.equal?(table) # => true # Returned self
def by_col!
@mode = :col
self
end
+ # :call-seq:
+ # table.by_col_or_row -> table_dup
#
- # Returns a duplicate table object, in mixed mode. This is handy for
- # chaining in a single call without changing the table mode, but be aware
- # that this method can consume a fair amount of memory for bigger data sets.
+ # Returns a duplicate of +self+, in mixed mode
+ # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]):
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true).by_col!
+ # table.mode # => :col
+ # dup_table = table.by_col_or_row
+ # dup_table.mode # => :col_or_row
+ # dup_table.equal?(table) # => false # It's a dup
#
- # This method returns the duplicate table for chaining. Don't chain
- # destructive methods (like []=()) this way though, since you are working
- # with a duplicate.
+ # This may be used to chain method calls without changing the mode
+ # (but also will affect performance and memory usage):
+ # dup_table.by_col_or_row['Name']
#
+ # Also note that changes to the duplicate table will not affect the original.
def by_col_or_row
self.class.new(@table.dup).by_col_or_row!
end
+ # :call-seq:
+ # table.by_col_or_row! -> self
#
- # Switches the mode of this table to mixed mode. All calls to indexing and
- # iteration methods will use the default intelligent indexing system until
- # the mode is changed again. In mixed mode an index is assumed to be a row
- # reference while anything else is assumed to be column access by headers.
- #
- # This method returns the table and is safe to chain.
- #
+ # Sets the mode for +self+ to mixed mode
+ # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]); returns +self+:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true).by_col!
+ # table.mode # => :col
+ # table1 = table.by_col_or_row!
+ # table.mode # => :col_or_row
+ # table1.equal?(table) # => true # Returned self
def by_col_or_row!
@mode = :col_or_row
self
end
+ # :call-seq:
+ # table.by_row -> table_dup
#
- # Returns a duplicate table object, in row mode. This is handy for chaining
- # in a single call without changing the table mode, but be aware that this
- # method can consume a fair amount of memory for bigger data sets.
+ # Returns a duplicate of +self+, in row mode
+ # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]):
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.mode # => :col_or_row
+ # dup_table = table.by_row
+ # dup_table.mode # => :row
+ # dup_table.equal?(table) # => false # It's a dup
#
- # This method returns the duplicate table for chaining. Don't chain
- # destructive methods (like []=()) this way though, since you are working
- # with a duplicate.
+ # This may be used to chain method calls without changing the mode
+ # (but also will affect performance and memory usage):
+ # dup_table.by_row[1]
#
+ # Also note that changes to the duplicate table will not affect the original.
def by_row
self.class.new(@table.dup).by_row!
end
+ # :call-seq:
+ # table.by_row! -> self
#
- # Switches the mode of this table to row mode. All calls to indexing and
- # iteration methods will work with rows until the mode is changed again.
- #
- # This method returns the table and is safe to chain.
- #
+ # Sets the mode for +self+ to row mode
+ # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]); returns +self+:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.mode # => :col_or_row
+ # table1 = table.by_row!
+ # table.mode # => :row
+ # table1.equal?(table) # => true # Returned self
def by_row!
@mode = :row
self
end
+ # :call-seq:
+ # table.headers -> array_of_headers
#
- # Returns the headers for the first row of this table (assumed to match all
- # other rows). The headers Array passed to CSV::Table.new is returned for
- # empty tables.
+ # Returns a new \Array containing the \String headers for the table.
#
+ # If the table is not empty, returns the headers from the first row:
+ # rows = [
+ # CSV::Row.new(['Foo', 'Bar'], []),
+ # CSV::Row.new(['FOO', 'BAR'], []),
+ # CSV::Row.new(['foo', 'bar'], []),
+ # ]
+ # table = CSV::Table.new(rows)
+ # table.headers # => ["Foo", "Bar"]
+ # table.delete(0)
+ # table.headers # => ["FOO", "BAR"]
+ # table.delete(0)
+ # table.headers # => ["foo", "bar"]
+ #
+ # If the table is empty, returns a copy of the headers in the table itself:
+ # table.delete(0)
+ # table.headers # => ["Foo", "Bar"]
def headers
if @table.empty?
@headers.dup
@@ -145,17 +366,21 @@ class CSV
end
# :call-seq:
- # table[n] -> row
- # table[range] -> array_of_rows
- # table[header] -> array_of_fields
+ # table[n] -> row or column_data
+ # table[range] -> array_of_rows or array_of_column_data
+ # table[header] -> array_of_column_data
#
# Returns data from the table; does not modify the table.
#
# ---
#
- # 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>:
+ # Fetch a \Row by Its \Integer Index::
+ # - Form: <tt>table[n]</tt>, +n+ an integer.
+ # - Access mode: <tt>:row</tt> or <tt>:col_or_row</tt>.
+ # - Return value: _nth_ row of the table, if that row exists;
+ # otherwise +nil+.
+ #
+ # Returns the _nth_ row of the table if that row exists:
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
# table = CSV.parse(source, headers: true)
# table.by_row! # => #<CSV::Table mode:row row_count:4>
@@ -168,20 +393,45 @@ class CSV
#
# Returns +nil+ if +n+ is too large or too small:
# table[4] # => nil
- # 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].
+ # and +n+ is not an \Integer:
# 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>:
+ # Fetch a Column by Its \Integer Index::
+ # - Form: <tt>table[n]</tt>, +n+ an \Integer.
+ # - Access mode: <tt>:col</tt>.
+ # - Return value: _nth_ column of the table, if that column exists;
+ # otherwise an \Array of +nil+ fields of length <tt>self.size</tt>.
+ #
+ # Returns the _nth_ column of the table if that column exists:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ # table[1] # => ["0", "1", "2"]
+ #
+ # Counts backward from the last column if +n+ is negative:
+ # table[-2] # => ["foo", "bar", "baz"]
+ #
+ # Returns an \Array of +nil+ fields if +n+ is too large or too small:
+ # table[4] # => [nil, nil, nil]
+ # table[-4] # => [nil, nil, nil]
+ #
+ # ---
+ #
+ # Fetch Rows by \Range::
+ # - Form: <tt>table[range]</tt>, +range+ a \Range object.
+ # - Access mode: <tt>:row</tt> or <tt>:col_or_row</tt>.
+ # - Return value: rows from the table, beginning at row <tt>range.start</tt>,
+ # if those rows exists.
+ #
+ # Returns rows from the table, beginning at row <tt>range.first</tt>,
+ # if those rows exist:
# 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>
@@ -191,11 +441,11 @@ class CSV
# 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:
+ # If there are too few rows, returns all from <tt>range.start</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:
+ # 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:
@@ -211,9 +461,41 @@ class CSV
#
# ---
#
- # 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>:
+ # Fetch Columns by \Range::
+ # - Form: <tt>table[range]</tt>, +range+ a \Range object.
+ # - Access mode: <tt>:col</tt>.
+ # - Return value: column data from the table, beginning at column <tt>range.start</tt>,
+ # if those columns exist.
+ #
+ # Returns column values from the table, if the column exists;
+ # the values are arranged by row:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col!
+ # table[0..1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # Special case: if <tt>range.start == headers.size</tt>,
+ # returns an \Array (size: <tt>table.size</tt>) of empty \Arrays:
+ # table[table.headers.size..50] # => [[], [], []]
+ #
+ # If <tt>range.end</tt> is negative, calculates the ending index from the end:
+ # table[0..-1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # If <tt>range.start</tt> is negative, calculates the starting index from the end:
+ # table[-2..2] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # If <tt>range.start</tt> is larger than <tt>table.size</tt>,
+ # returns an \Array of +nil+ values:
+ # table[4..4] # => [nil, nil, nil]
+ #
+ # ---
+ #
+ # Fetch a Column by Its \String Header::
+ # - Form: <tt>table[header]</tt>, +header+ a \String header.
+ # - Access mode: <tt>:col</tt> or <tt>:col_or_row</tt>
+ # - Return value: column data from the table, if that +header+ exists.
+ #
+ # Returns column values from the table, if the column exists:
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
# table = CSV.parse(source, headers: true)
# table.by_col! # => #<CSV::Table mode:col row_count:4>
@@ -238,22 +520,132 @@ class CSV
end
end
+ # :call-seq:
+ # table[n] = row -> row
+ # table[n] = field_or_array_of_fields -> field_or_array_of_fields
+ # table[header] = field_or_array_of_fields -> field_or_array_of_fields
#
- # In the default mixed mode, this method assigns rows for index access and
- # columns for header access. You can force the index association by first
- # calling by_col!() or by_row!().
+ # Puts data onto the table.
#
- # Rows may be set to an Array of values (which will inherit the table's
- # headers()) or a CSV::Row.
+ # ---
+ #
+ # Set a \Row by Its \Integer Index::
+ # - Form: <tt>table[n] = row</tt>, +n+ an \Integer,
+ # +row+ a \CSV::Row instance or an \Array of fields.
+ # - Access mode: <tt>:row</tt> or <tt>:col_or_row</tt>.
+ # - Return value: +row+.
+ #
+ # If the row exists, it is replaced:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # new_row = CSV::Row.new(['Name', 'Value'], ['bat', 3])
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # return_value = table[0] = new_row
+ # return_value.equal?(new_row) # => true # Returned the row
+ # table[0].to_h # => {"Name"=>"bat", "Value"=>3}
+ #
+ # With access mode <tt>:col_or_row</tt>:
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
+ # table[0] = CSV::Row.new(['Name', 'Value'], ['bam', 4])
+ # table[0].to_h # => {"Name"=>"bam", "Value"=>4}
+ #
+ # With an \Array instead of a \CSV::Row, inherits headers from the table:
+ # array = ['bad', 5]
+ # return_value = table[0] = array
+ # return_value.equal?(array) # => true # Returned the array
+ # table[0].to_h # => {"Name"=>"bad", "Value"=>5}
#
- # Columns may be set to a single value, which is copied to each row of the
- # column, or an Array of values. Arrays of values are assigned to rows top
- # to bottom in row major order. Excess values are ignored and if the Array
- # does not have a value for each row the extra rows will receive a +nil+.
+ # If the row does not exist, extends the table by adding rows:
+ # assigns rows with +nil+ as needed:
+ # table.size # => 3
+ # table[5] = ['bag', 6]
+ # table.size # => 6
+ # table[3] # => nil
+ # table[4]# => nil
+ # table[5].to_h # => {"Name"=>"bag", "Value"=>6}
+ #
+ # Note that the +nil+ rows are actually +nil+, not a row of +nil+ fields.
#
- # Assigning to an existing column or row clobbers the data. Assigning to
- # new columns creates them at the right end of the table.
+ # ---
#
+ # Set a Column by Its \Integer Index::
+ # - Form: <tt>table[n] = array_of_fields</tt>, +n+ an \Integer,
+ # +array_of_fields+ an \Array of \String fields.
+ # - Access mode: <tt>:col</tt>.
+ # - Return value: +array_of_fields+.
+ #
+ # If the column exists, it is replaced:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # new_col = [3, 4, 5]
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ # return_value = table[1] = new_col
+ # return_value.equal?(new_col) # => true # Returned the column
+ # table[1] # => [3, 4, 5]
+ # # The rows, as revised:
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # table[0].to_h # => {"Name"=>"foo", "Value"=>3}
+ # table[1].to_h # => {"Name"=>"bar", "Value"=>4}
+ # table[2].to_h # => {"Name"=>"baz", "Value"=>5}
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ #
+ # If there are too few values, fills with +nil+ values:
+ # table[1] = [0]
+ # table[1] # => [0, nil, nil]
+ #
+ # If there are too many values, ignores the extra values:
+ # table[1] = [0, 1, 2, 3, 4]
+ # table[1] # => [0, 1, 2]
+ #
+ # If a single value is given, replaces all fields in the column with that value:
+ # table[1] = 'bat'
+ # table[1] # => ["bat", "bat", "bat"]
+ #
+ # ---
+ #
+ # Set a Column by Its \String Header::
+ # - Form: <tt>table[header] = field_or_array_of_fields</tt>,
+ # +header+ a \String header, +field_or_array_of_fields+ a field value
+ # or an \Array of \String fields.
+ # - Access mode: <tt>:col</tt> or <tt>:col_or_row</tt>.
+ # - Return value: +field_or_array_of_fields+.
+ #
+ # If the column exists, it is replaced:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # new_col = [3, 4, 5]
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ # return_value = table['Value'] = new_col
+ # return_value.equal?(new_col) # => true # Returned the column
+ # table['Value'] # => [3, 4, 5]
+ # # The rows, as revised:
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # table[0].to_h # => {"Name"=>"foo", "Value"=>3}
+ # table[1].to_h # => {"Name"=>"bar", "Value"=>4}
+ # table[2].to_h # => {"Name"=>"baz", "Value"=>5}
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ #
+ # If there are too few values, fills with +nil+ values:
+ # table['Value'] = [0]
+ # table['Value'] # => [0, nil, nil]
+ #
+ # If there are too many values, ignores the extra values:
+ # table['Value'] = [0, 1, 2, 3, 4]
+ # table['Value'] # => [0, 1, 2]
+ #
+ # If the column does not exist, extends the table by adding columns:
+ # table['Note'] = ['x', 'y', 'z']
+ # table['Note'] # => ["x", "y", "z"]
+ # # The rows, as revised:
+ # table.by_row!
+ # table[0].to_h # => {"Name"=>"foo", "Value"=>0, "Note"=>"x"}
+ # table[1].to_h # => {"Name"=>"bar", "Value"=>1, "Note"=>"y"}
+ # table[2].to_h # => {"Name"=>"baz", "Value"=>2, "Note"=>"z"}
+ # table.by_col!
+ #
+ # If a single value is given, replaces all fields in the column with that value:
+ # table['Value'] = 'bat'
+ # table['Value'] # => ["bat", "bat", "bat"]
def []=(index_or_header, value)
if @mode == :row or # by index
(@mode == :col_or_row and index_or_header.is_a? Integer)
@@ -463,6 +855,9 @@ class CSV
end
end
+ # :call-seq:
+ # table.delete_if {|row_or_column| ... } -> self
+ #
# Removes rows or columns for which the block returns a truthy value;
# returns +self+.
#
@@ -495,9 +890,8 @@ class CSV
if @mode == :row or @mode == :col_or_row # by index
@table.delete_if(&block)
else # by header
- deleted = []
headers.each do |header|
- deleted << delete(header) if yield([header, self[header]])
+ delete(header) if yield([header, self[header]])
end
end
@@ -506,6 +900,9 @@ class CSV
include Enumerable
+ # :call-seq:
+ # table.each {|row_or_column| ... ) -> self
+ #
# Calls the block with each row or column; returns +self+.
#
# When the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
@@ -534,7 +931,9 @@ class CSV
return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given?
if @mode == :col
- headers.each { |header| yield([header, self[header]]) }
+ headers.each.with_index do |header, i|
+ yield([header, @table.map {|row| row[header, i]}])
+ end
else
@table.each(&block)
end
@@ -542,6 +941,9 @@ class CSV
self # for chaining
end
+ # :call-seq:
+ # table == other_table -> true or false
+ #
# Returns +true+ if all each row of +self+ <tt>==</tt>
# the corresponding row of +other_table+, otherwise, +false+.
#
@@ -565,10 +967,14 @@ class CSV
@table == other
end
+ # :call-seq:
+ # table.to_a -> array_of_arrays
#
- # Returns the table as an Array of Arrays. Headers will be the first row,
- # then all of the field rows will follow.
- #
+ # Returns the table as an \Array of \Arrays;
+ # the headers are in the first row:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.to_a # => [["Name", "Value"], ["foo", "0"], ["bar", "1"], ["baz", "2"]]
def to_a
array = [headers]
@table.each do |row|
@@ -578,16 +984,29 @@ class CSV
array
end
+ # :call-seq:
+ # table.to_csv(**options) -> csv_string
#
- # Returns the table as a complete CSV String. Headers will be listed first,
- # then all of the field rows.
+ # Returns the table as \CSV string.
+ # See {Options for Generating}[../CSV.html#class-CSV-label-Options+for+Generating].
#
- # This method assumes you want the Table.headers(), unless you explicitly
- # pass <tt>:write_headers => false</tt>.
+ # Defaults option +write_headers+ to +true+:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.to_csv # => "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
#
- def to_csv(write_headers: true, **options)
+ # Omits the headers if option +write_headers+ is given as +false+
+ # (see {Option +write_headers+}[../CSV.html#class-CSV-label-Option+write_headers]):
+ # table.to_csv(write_headers: false) # => "foo,0\nbar,1\nbaz,2\n"
+ #
+ # Limit rows if option +limit+ is given like +2+:
+ # table.to_csv(limit: 2) # => "Name,Value\nfoo,0\nbar,1\n"
+ def to_csv(write_headers: true, limit: nil, **options)
array = write_headers ? [headers.to_csv(**options)] : []
- @table.each do |row|
+ limit ||= @table.size
+ limit = @table.size + 1 + limit if limit < 0
+ limit = 0 if limit < 0
+ @table.first(limit).each do |row|
array.push(row.fields.to_csv(**options)) unless row.header_row?
end
@@ -613,9 +1032,24 @@ class CSV
end
end
- # Shows the mode and size of this table in a US-ASCII String.
+ # :call-seq:
+ # table.inspect => string
+ #
+ # Returns a <tt>US-ASCII</tt>-encoded \String showing table:
+ # - Class: <tt>CSV::Table</tt>.
+ # - Access mode: <tt>:row</tt>, <tt>:col</tt>, or <tt>:col_or_row</tt>.
+ # - Size: Row count, including the header row.
+ #
+ # Example:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.inspect # => "#<CSV::Table mode:col_or_row row_count:4>\nName,Value\nfoo,0\nbar,1\nbaz,2\n"
+ #
def inspect
- "#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>".encode("US-ASCII")
+ inspected = +"#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>"
+ summary = to_csv(limit: 5)
+ inspected << "\n" << summary if summary.encoding.ascii_compatible?
+ inspected
end
end
end
diff --git a/lib/csv/version.rb b/lib/csv/version.rb
index b509299d96..e05d63d801 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.2.0"
+ VERSION = "3.2.6"
end
diff --git a/lib/csv/writer.rb b/lib/csv/writer.rb
index d49115fccf..030a295bc9 100644
--- a/lib/csv/writer.rb
+++ b/lib/csv/writer.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
-require_relative "match_p"
+require_relative "input_record_separator"
require_relative "row"
-using CSV::MatchP if CSV.const_defined?(:MatchP)
-
class CSV
# Note: Don't use this class directly. This is an internal class.
class Writer
@@ -41,7 +39,10 @@ class CSV
@headers ||= row if @use_headers
@lineno += 1
- row = @fields_converter.convert(row, nil, lineno) if @fields_converter
+ if @fields_converter
+ quoted_fields = [false] * row.size
+ row = @fields_converter.convert(row, nil, lineno, quoted_fields)
+ end
i = -1
converted_row = row.collect do |field|
@@ -96,7 +97,7 @@ class CSV
return unless @headers
converter = @options[:header_fields_converter]
- @headers = converter.convert(@headers, nil, 0)
+ @headers = converter.convert(@headers, nil, 0, [])
@headers.each do |header|
header.freeze if header.is_a?(String)
end
@@ -133,7 +134,7 @@ class CSV
@column_separator = @options[:column_separator].to_s.encode(@encoding)
row_separator = @options[:row_separator]
if row_separator == :auto
- @row_separator = $INPUT_RECORD_SEPARATOR.encode(@encoding)
+ @row_separator = InputRecordSeparator.value.encode(@encoding)
else
@row_separator = row_separator.to_s.encode(@encoding)
end
diff --git a/lib/debug.gemspec b/lib/debug.gemspec
deleted file mode 100644
index 71f93f7409..0000000000
--- a/lib/debug.gemspec
+++ /dev/null
@@ -1,22 +0,0 @@
-Gem::Specification.new do |spec|
- spec.name = "debug"
- spec.version = "0.1.0"
- 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.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/debug.rb b/lib/debug.rb
deleted file mode 100644
index bf53eb80a4..0000000000
--- a/lib/debug.rb
+++ /dev/null
@@ -1,1106 +0,0 @@
-# frozen_string_literal: true
-# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
-# Copyright (C) 2000 Information-technology Promotion Agency, Japan
-# Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
-
-require 'continuation'
-
-require 'tracer'
-require 'pp'
-
-class Tracer # :nodoc:
- def Tracer.trace_func(*vars)
- Single.trace_func(*vars)
- end
-end
-
-SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc:
-
-##
-# This library provides debugging functionality to Ruby.
-#
-# To add a debugger to your code, start by requiring +debug+ in your
-# program:
-#
-# def say(word)
-# require 'debug'
-# puts word
-# end
-#
-# This will cause Ruby to interrupt execution and show a prompt when the +say+
-# method is run.
-#
-# Once you're inside the prompt, you can start debugging your program.
-#
-# (rdb:1) p word
-# "hello"
-#
-# == Getting help
-#
-# You can get help at any time by pressing +h+.
-#
-# (rdb:1) h
-# Debugger help v.-0.002b
-# Commands
-# b[reak] [file:|class:]<line|method>
-# b[reak] [class.]<line|method>
-# set breakpoint to some position
-# wat[ch] <expression> set watchpoint to some expression
-# cat[ch] (<exception>|off) set catchpoint to an exception
-# b[reak] list breakpoints
-# cat[ch] show catchpoint
-# del[ete][ nnn] delete some or all breakpoints
-# disp[lay] <expression> add expression into display expression list
-# undisp[lay][ nnn] delete one particular or all display expressions
-# c[ont] run until program ends or hit breakpoint
-# s[tep][ nnn] step (into methods) one line or till line nnn
-# n[ext][ nnn] go over one line or till line nnn
-# w[here] display frames
-# f[rame] alias for where
-# l[ist][ (-|nn-mm)] list program, - lists backwards
-# nn-mm lists given lines
-# up[ nn] move to higher frame
-# down[ nn] move to lower frame
-# fin[ish] return to outer frame
-# tr[ace] (on|off) set trace mode of current thread
-# tr[ace] (on|off) all set trace mode of all threads
-# q[uit] exit from debugger
-# v[ar] g[lobal] show global variables
-# v[ar] l[ocal] show local variables
-# v[ar] i[nstance] <object> show instance variables of object
-# v[ar] c[onst] <object> show constants of object
-# m[ethod] i[nstance] <obj> show methods of object
-# m[ethod] <class|module> show instance methods of class or module
-# th[read] l[ist] list all threads
-# th[read] c[ur[rent]] show current thread
-# th[read] [sw[itch]] <nnn> switch thread context to nnn
-# th[read] stop <nnn> stop thread nnn
-# th[read] resume <nnn> resume thread nnn
-# p expression evaluate expression and print its value
-# h[elp] print this help
-# <everything else> evaluate
-#
-# == Usage
-#
-# The following is a list of common functionalities that the debugger
-# provides.
-#
-# === Navigating through your code
-#
-# In general, a debugger is used to find bugs in your program, which
-# often means pausing execution and inspecting variables at some point
-# in time.
-#
-# Let's look at an example:
-#
-# def my_method(foo)
-# require 'debug'
-# foo = get_foo if foo.nil?
-# raise if foo.nil?
-# end
-#
-# When you run this program, the debugger will kick in just before the
-# +foo+ assignment.
-#
-# (rdb:1) p foo
-# nil
-#
-# In this example, it'd be interesting to move to the next line and
-# inspect the value of +foo+ again. You can do that by pressing +n+:
-#
-# (rdb:1) n # goes to next line
-# (rdb:1) p foo
-# nil
-#
-# You now know that the original value of +foo+ was nil, and that it
-# still was nil after calling +get_foo+.
-#
-# Other useful commands for navigating through your code are:
-#
-# +c+::
-# Runs the program until it either exists or encounters another breakpoint.
-# You usually press +c+ when you are finished debugging your program and
-# want to resume its execution.
-# +s+::
-# Steps into method definition. In the previous example, +s+ would take you
-# inside the method definition of +get_foo+.
-# +r+::
-# Restart the program.
-# +q+::
-# Quit the program.
-#
-# === Inspecting variables
-#
-# You can use the debugger to easily inspect both local and global variables.
-# We've seen how to inspect local variables before:
-#
-# (rdb:1) p my_arg
-# 42
-#
-# You can also pretty print the result of variables or expressions:
-#
-# (rdb:1) pp %w{a very long long array containing many words}
-# ["a",
-# "very",
-# "long",
-# ...
-# ]
-#
-# You can list all local variables with +v l+:
-#
-# (rdb:1) v l
-# foo => "hello"
-#
-# Similarly, you can show all global variables with +v g+:
-#
-# (rdb:1) v g
-# all global variables
-#
-# Finally, you can omit +p+ if you simply want to evaluate a variable or
-# expression
-#
-# (rdb:1) 5**2
-# 25
-#
-# === Going beyond basics
-#
-# Ruby Debug provides more advanced functionalities like switching
-# between threads, setting breakpoints and watch expressions, and more.
-# The full list of commands is available at any time by pressing +h+.
-#
-# == Staying out of trouble
-#
-# Make sure you remove every instance of +require 'debug'+ before
-# shipping your code. Failing to do so may result in your program
-# hanging unpredictably.
-#
-# Debug is not available in safe mode.
-
-class DEBUGGER__
- MUTEX = Thread::Mutex.new # :nodoc:
-
- class Context # :nodoc:
- DEBUG_LAST_CMD = []
-
- begin
- require 'readline'
- def readline(prompt, hist)
- Readline::readline(prompt, hist)
- end
- rescue LoadError
- def readline(prompt, hist)
- STDOUT.print prompt
- STDOUT.flush
- line = STDIN.gets
- exit unless line
- line.chomp!
- line
- end
- USE_READLINE = false
- end
-
- def initialize
- if Thread.current == Thread.main
- @stop_next = 1
- else
- @stop_next = 0
- end
- @last_file = nil
- @file = nil
- @line = nil
- @no_step = nil
- @frames = []
- @finish_pos = 0
- @trace = false
- @catch = "StandardError"
- @suspend_next = false
- end
-
- def stop_next(n=1)
- @stop_next = n
- end
-
- def set_suspend
- @suspend_next = true
- end
-
- def clear_suspend
- @suspend_next = false
- end
-
- def suspend_all
- DEBUGGER__.suspend
- end
-
- def resume_all
- DEBUGGER__.resume
- end
-
- def check_suspend
- while MUTEX.synchronize {
- if @suspend_next
- DEBUGGER__.waiting.push Thread.current
- @suspend_next = false
- true
- end
- }
- end
- end
-
- def trace?
- @trace
- end
-
- def set_trace(arg)
- @trace = arg
- end
-
- def stdout
- DEBUGGER__.stdout
- end
-
- def break_points
- DEBUGGER__.break_points
- end
-
- def display
- DEBUGGER__.display
- end
-
- def context(th)
- DEBUGGER__.context(th)
- end
-
- def set_trace_all(arg)
- DEBUGGER__.set_trace(arg)
- end
-
- def set_last_thread(th)
- DEBUGGER__.set_last_thread(th)
- end
-
- def debug_eval(str, binding)
- begin
- eval(str, binding)
- rescue StandardError, ScriptError => e
- at = eval("caller(1)", binding)
- stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
- for i in at
- stdout.printf "\tfrom %s\n", i
- end
- throw :debug_error
- end
- end
-
- def debug_silent_eval(str, binding)
- begin
- eval(str, binding)
- rescue StandardError, ScriptError
- nil
- end
- end
-
- def var_list(ary, binding)
- ary.sort!
- for v in ary
- stdout.printf " %s => %s\n", v, eval(v.to_s, binding).inspect
- end
- end
-
- def debug_variable_info(input, binding)
- case input
- when /^\s*g(?:lobal)?\s*$/
- var_list(global_variables, binding)
-
- when /^\s*l(?:ocal)?\s*$/
- var_list(eval("local_variables", binding), binding)
-
- when /^\s*i(?:nstance)?\s+/
- obj = debug_eval($', binding)
- var_list(obj.instance_variables, obj.instance_eval{binding()})
-
- when /^\s*c(?:onst(?:ant)?)?\s+/
- obj = debug_eval($', binding)
- unless obj.kind_of? Module
- stdout.print "Should be Class/Module: ", $', "\n"
- else
- var_list(obj.constants, obj.module_eval{binding()})
- end
- end
- end
-
- def debug_method_info(input, binding)
- case input
- when /^i(:?nstance)?\s+/
- obj = debug_eval($', binding)
-
- len = 0
- for v in obj.methods.sort
- len += v.size + 1
- if len > 70
- len = v.size + 1
- stdout.print "\n"
- end
- stdout.print v, " "
- end
- stdout.print "\n"
-
- else
- obj = debug_eval(input, binding)
- unless obj.kind_of? Module
- stdout.print "Should be Class/Module: ", input, "\n"
- else
- len = 0
- for v in obj.instance_methods(false).sort
- len += v.size + 1
- if len > 70
- len = v.size + 1
- stdout.print "\n"
- end
- stdout.print v, " "
- end
- stdout.print "\n"
- end
- end
- end
-
- def thnum
- num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
- unless num
- DEBUGGER__.make_thread_list
- num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
- end
- num
- end
-
- def debug_command(file, line, id, binding)
- MUTEX.lock
- unless defined?($debugger_restart) and $debugger_restart
- callcc{|c| $debugger_restart = c}
- end
- set_last_thread(Thread.current)
- frame_pos = 0
- binding_file = file
- binding_line = line
- previous_line = nil
- if ENV['EMACS']
- stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
- else
- stdout.printf "%s:%d:%s", binding_file, binding_line,
- line_at(binding_file, binding_line)
- end
- @frames[0] = [binding, file, line, id]
- display_expressions(binding)
- prompt = true
- while prompt and input = readline("(rdb:%d) "%thnum(), true)
- catch(:debug_error) do
- if input == ""
- next unless DEBUG_LAST_CMD[0]
- input = DEBUG_LAST_CMD[0]
- stdout.print input, "\n"
- else
- DEBUG_LAST_CMD[0] = input
- end
-
- case input
- when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
- if defined?( $2 )
- if $1 == 'on'
- set_trace_all true
- else
- set_trace_all false
- end
- elsif defined?( $1 )
- if $1 == 'on'
- set_trace true
- else
- set_trace false
- end
- end
- if trace?
- stdout.print "Trace on.\n"
- else
- stdout.print "Trace off.\n"
- end
-
- when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
- pos = $2
- if $1
- klass = debug_silent_eval($1, binding)
- file = File.expand_path($1)
- end
- if pos =~ /^\d+$/
- pname = pos
- pos = pos.to_i
- else
- pname = pos = pos.intern.id2name
- end
- break_points.push [true, 0, klass || file, pos]
- stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
-
- when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
- pos = $2.intern.id2name
- klass = debug_eval($1, binding)
- break_points.push [true, 0, klass, pos]
- stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
-
- when /^\s*wat(?:ch)?\s+(.+)$/
- exp = $1
- break_points.push [true, 1, exp]
- stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp
-
- when /^\s*b(?:reak)?$/
- if break_points.find{|b| b[1] == 0}
- n = 1
- stdout.print "Breakpoints:\n"
- break_points.each do |b|
- if b[0] and b[1] == 0
- stdout.printf " %d %s:%s\n", n, b[2], b[3]
- end
- n += 1
- end
- end
- if break_points.find{|b| b[1] == 1}
- n = 1
- stdout.print "\n"
- stdout.print "Watchpoints:\n"
- for b in break_points
- if b[0] and b[1] == 1
- stdout.printf " %d %s\n", n, b[2]
- end
- n += 1
- end
- end
- if break_points.size == 0
- stdout.print "No breakpoints\n"
- else
- stdout.print "\n"
- end
-
- when /^\s*del(?:ete)?(?:\s+(\d+))?$/
- pos = $1
- unless pos
- input = readline("Clear all breakpoints? (y/n) ", false)
- if input == "y"
- for b in break_points
- b[0] = false
- end
- end
- else
- pos = pos.to_i
- if break_points[pos-1]
- break_points[pos-1][0] = false
- else
- stdout.printf "Breakpoint %d is not defined\n", pos
- end
- end
-
- when /^\s*disp(?:lay)?\s+(.+)$/
- exp = $1
- display.push [true, exp]
- stdout.printf "%d: ", display.size
- display_expression(exp, binding)
-
- when /^\s*disp(?:lay)?$/
- display_expressions(binding)
-
- when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
- pos = $1
- unless pos
- input = readline("Clear all expressions? (y/n) ", false)
- if input == "y"
- for d in display
- d[0] = false
- end
- end
- else
- pos = pos.to_i
- if display[pos-1]
- display[pos-1][0] = false
- else
- stdout.printf "Display expression %d is not defined\n", pos
- end
- end
-
- when /^\s*c(?:ont)?$/
- prompt = false
-
- when /^\s*s(?:tep)?(?:\s+(\d+))?$/
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- @stop_next = lev
- prompt = false
-
- when /^\s*n(?:ext)?(?:\s+(\d+))?$/
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- @stop_next = lev
- @no_step = @frames.size - frame_pos
- prompt = false
-
- when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
- display_frames(frame_pos)
-
- when /^\s*l(?:ist)?(?:\s+(.+))?$/
- if not $1
- b = previous_line ? previous_line + 10 : binding_line - 5
- e = b + 9
- elsif $1 == '-'
- b = previous_line ? previous_line - 10 : binding_line - 5
- e = b + 9
- else
- b, e = $1.split(/[-,]/)
- if e
- b = b.to_i
- e = e.to_i
- else
- b = b.to_i - 5
- e = b + 9
- end
- end
- previous_line = b
- display_list(b, e, binding_file, binding_line)
-
- when /^\s*up(?:\s+(\d+))?$/
- previous_line = nil
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- frame_pos += lev
- if frame_pos >= @frames.size
- frame_pos = @frames.size - 1
- stdout.print "At toplevel\n"
- end
- binding, binding_file, binding_line = @frames[frame_pos]
- stdout.print format_frame(frame_pos)
-
- when /^\s*down(?:\s+(\d+))?$/
- previous_line = nil
- if $1
- lev = $1.to_i
- else
- lev = 1
- end
- frame_pos -= lev
- if frame_pos < 0
- frame_pos = 0
- stdout.print "At stack bottom\n"
- end
- binding, binding_file, binding_line = @frames[frame_pos]
- stdout.print format_frame(frame_pos)
-
- when /^\s*fin(?:ish)?$/
- if frame_pos == @frames.size
- stdout.print "\"finish\" not meaningful in the outermost frame.\n"
- else
- @finish_pos = @frames.size - frame_pos
- frame_pos = 0
- prompt = false
- end
-
- when /^\s*cat(?:ch)?(?:\s+(.+))?$/
- if $1
- excn = $1
- if excn == 'off'
- @catch = nil
- stdout.print "Clear catchpoint.\n"
- else
- @catch = excn
- stdout.printf "Set catchpoint %s.\n", @catch
- end
- else
- if @catch
- stdout.printf "Catchpoint %s.\n", @catch
- else
- stdout.print "No catchpoint.\n"
- end
- end
-
- when /^\s*q(?:uit)?$/
- input = readline("Really quit? (y/n) ", false)
- if input == "y"
- exit! # exit -> exit!: No graceful way to stop threads...
- end
-
- when /^\s*v(?:ar)?\s+/
- debug_variable_info($', binding)
-
- when /^\s*m(?:ethod)?\s+/
- debug_method_info($', binding)
-
- when /^\s*th(?:read)?\s+/
- if DEBUGGER__.debug_thread_info($', binding) == :cont
- prompt = false
- end
-
- when /^\s*pp\s+/
- PP.pp(debug_eval($', binding), stdout)
-
- when /^\s*p\s+/
- stdout.printf "%s\n", debug_eval($', binding).inspect
-
- when /^\s*r(?:estart)?$/
- $debugger_restart.call
-
- when /^\s*h(?:elp)?$/
- debug_print_help()
-
- else
- v = debug_eval(input, binding)
- stdout.printf "%s\n", v.inspect
- end
- end
- end
- MUTEX.unlock
- resume_all
- end
-
- def debug_print_help
- stdout.print <<EOHELP
-Debugger help v.-0.002b
-Commands
- b[reak] [file:|class:]<line|method>
- b[reak] [class.]<line|method>
- set breakpoint to some position
- wat[ch] <expression> set watchpoint to some expression
- cat[ch] (<exception>|off) set catchpoint to an exception
- b[reak] list breakpoints
- cat[ch] show catchpoint
- del[ete][ nnn] delete some or all breakpoints
- disp[lay] <expression> add expression into display expression list
- undisp[lay][ nnn] delete one particular or all display expressions
- c[ont] run until program ends or hit breakpoint
- s[tep][ nnn] step (into methods) one line or till line nnn
- n[ext][ nnn] go over one line or till line nnn
- w[here] display frames
- f[rame] alias for where
- l[ist][ (-|nn-mm)] list program, - lists backwards
- nn-mm lists given lines
- up[ nn] move to higher frame
- down[ nn] move to lower frame
- fin[ish] return to outer frame
- tr[ace] (on|off) set trace mode of current thread
- tr[ace] (on|off) all set trace mode of all threads
- q[uit] exit from debugger
- v[ar] g[lobal] show global variables
- v[ar] l[ocal] show local variables
- v[ar] i[nstance] <object> show instance variables of object
- v[ar] c[onst] <object> show constants of object
- m[ethod] i[nstance] <obj> show methods of object
- m[ethod] <class|module> show instance methods of class or module
- th[read] l[ist] list all threads
- th[read] c[ur[rent]] show current thread
- th[read] [sw[itch]] <nnn> switch thread context to nnn
- th[read] stop <nnn> stop thread nnn
- th[read] resume <nnn> resume thread nnn
- pp expression evaluate expression and pretty_print its value
- p expression evaluate expression and print its value
- r[estart] restart program
- h[elp] print this help
- <everything else> evaluate
-EOHELP
- end
-
- def display_expressions(binding)
- n = 1
- for d in display
- if d[0]
- stdout.printf "%d: ", n
- display_expression(d[1], binding)
- end
- n += 1
- end
- end
-
- def display_expression(exp, binding)
- stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
- end
-
- def frame_set_pos(file, line)
- if @frames[0]
- @frames[0][1] = file
- @frames[0][2] = line
- end
- end
-
- def display_frames(pos)
- 0.upto(@frames.size - 1) do |n|
- if n == pos
- stdout.print "--> "
- else
- stdout.print " "
- end
- stdout.print format_frame(n)
- end
- end
-
- def format_frame(pos)
- _, file, line, id = @frames[pos]
- sprintf "#%d %s:%s%s\n", pos + 1, file, line,
- (id ? ":in `#{id.id2name}'" : "")
- end
-
- def script_lines(file, line)
- unless (lines = SCRIPT_LINES__[file]) and lines != true
- Tracer::Single.get_line(file, line) if File.exist?(file)
- lines = SCRIPT_LINES__[file]
- lines = nil if lines == true
- end
- lines
- end
-
- def display_list(b, e, file, line)
- if lines = script_lines(file, line)
- stdout.printf "[%d, %d] in %s\n", b, e, file
- b.upto(e) do |n|
- if n > 0 && lines[n-1]
- if n == line
- stdout.printf "=> %d %s\n", n, lines[n-1].chomp
- else
- stdout.printf " %d %s\n", n, lines[n-1].chomp
- end
- end
- end
- else
- stdout.printf "No sourcefile available for %s\n", file
- end
- end
-
- def line_at(file, line)
- lines = script_lines(file, line)
- if lines and line = lines[line-1]
- return line
- end
- return "\n"
- end
-
- def debug_funcname(id)
- if id.nil?
- "toplevel"
- else
- id.id2name
- end
- end
-
- def check_break_points(file, klass, pos, binding, id)
- return false if break_points.empty?
- n = 1
- for b in break_points
- if b[0] # valid
- if b[1] == 0 # breakpoint
- if (b[2] == file and b[3] == pos) or
- (klass and b[2] == klass and b[3] == pos)
- stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
- return true
- end
- elsif b[1] == 1 # watchpoint
- if debug_silent_eval(b[2], binding)
- stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
- return true
- end
- end
- end
- n += 1
- end
- return false
- end
-
- def excn_handle(file, line, id, binding)
- if $!.class <= SystemExit
- set_trace_func nil
- exit
- end
-
- if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
- stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
- fs = @frames.size
- tb = caller(0)[-fs..-1]
- if tb
- for i in tb
- stdout.printf "\tfrom %s\n", i
- end
- end
- suspend_all
- debug_command(file, line, id, binding)
- end
- end
-
- def trace_func(event, file, line, id, binding, klass)
- Tracer.trace_func(event, file, line, id, binding, klass) if trace?
- context(Thread.current).check_suspend
- @file = file
- @line = line
- case event
- when 'line'
- frame_set_pos(file, line)
- if !@no_step or @frames.size == @no_step
- @stop_next -= 1
- @stop_next = -1 if @stop_next < 0
- elsif @frames.size < @no_step
- @stop_next = 0 # break here before leaving...
- else
- # nothing to do. skipped.
- end
- if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
- @no_step = nil
- suspend_all
- debug_command(file, line, id, binding)
- end
-
- when 'call'
- @frames.unshift [binding, file, line, id]
- if check_break_points(file, klass, id.id2name, binding, id)
- suspend_all
- debug_command(file, line, id, binding)
- end
-
- when 'c-call'
- frame_set_pos(file, line)
-
- when 'class'
- @frames.unshift [binding, file, line, id]
-
- when 'return', 'end'
- if @frames.size == @finish_pos
- @stop_next = 1
- @finish_pos = 0
- end
- @frames.shift
-
- when 'raise'
- excn_handle(file, line, id, binding)
-
- end
- @last_file = file
- end
- end
-
- trap("INT") { DEBUGGER__.interrupt }
- @last_thread = Thread::main
- @max_thread = 1
- @thread_list = {Thread::main => 1}
- @break_points = []
- @display = []
- @waiting = []
- @stdout = STDOUT
-
- class << DEBUGGER__
- # Returns the IO used as stdout. Defaults to STDOUT
- def stdout
- @stdout
- end
-
- # Sets the IO used as stdout. Defaults to STDOUT
- def stdout=(s)
- @stdout = s
- end
-
- # Returns the display expression list
- #
- # See DEBUGGER__ for more usage
- def display
- @display
- end
-
- # Returns the list of break points where execution will be stopped.
- #
- # See DEBUGGER__ for more usage
- def break_points
- @break_points
- end
-
- # Returns the list of waiting threads.
- #
- # When stepping through the traces of a function, thread gets suspended, to
- # be resumed later.
- def waiting
- @waiting
- end
-
- def set_trace( arg )
- MUTEX.synchronize do
- make_thread_list
- for th, in @thread_list
- context(th).set_trace arg
- end
- end
- arg
- end
-
- def set_last_thread(th)
- @last_thread = th
- end
-
- def suspend
- MUTEX.synchronize do
- make_thread_list
- for th, in @thread_list
- next if th == Thread.current
- context(th).set_suspend
- end
- end
- # Schedule other threads to suspend as soon as possible.
- Thread.pass
- end
-
- def resume
- MUTEX.synchronize do
- make_thread_list
- @thread_list.each do |th,|
- next if th == Thread.current
- context(th).clear_suspend
- end
- waiting.each do |th|
- th.run
- end
- waiting.clear
- end
- # Schedule other threads to restart as soon as possible.
- Thread.pass
- end
-
- def context(thread=Thread.current)
- c = thread[:__debugger_data__]
- unless c
- thread[:__debugger_data__] = c = Context.new
- end
- c
- end
-
- def interrupt
- context(@last_thread).stop_next
- end
-
- def get_thread(num)
- th = @thread_list.key(num)
- unless th
- @stdout.print "No thread ##{num}\n"
- throw :debug_error
- end
- th
- end
-
- def thread_list(num)
- th = get_thread(num)
- if th == Thread.current
- @stdout.print "+"
- else
- @stdout.print " "
- end
- @stdout.printf "%d ", num
- @stdout.print th.inspect, "\t"
- file = context(th).instance_eval{@file}
- if file
- @stdout.print file,":",context(th).instance_eval{@line}
- end
- @stdout.print "\n"
- end
-
- # Prints all threads in @thread_list to @stdout. Returns a sorted array of
- # values from the @thread_list hash.
- #
- # While in the debugger you can list all of
- # the threads with: <b>DEBUGGER__.thread_list_all</b>
- #
- # (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>
- # [1, 2, 3]
- #
- # Your current thread is indicated by a <b>+</b>
- #
- # Additionally you can list all threads with <b>th l</b>
- #
- # (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
- #
- # See DEBUGGER__ for more usage.
-
- def thread_list_all
- for th in @thread_list.values.sort
- thread_list(th)
- end
- end
-
- def make_thread_list
- hash = {}
- for th in Thread::list
- if @thread_list.key? th
- hash[th] = @thread_list[th]
- else
- @max_thread += 1
- hash[th] = @max_thread
- end
- end
- @thread_list = hash
- end
-
- def debug_thread_info(input, binding)
- case input
- when /^l(?:ist)?/
- make_thread_list
- thread_list_all
-
- when /^c(?:ur(?:rent)?)?$/
- make_thread_list
- thread_list(@thread_list[Thread.current])
-
- when /^(?:sw(?:itch)?\s+)?(\d+)/
- make_thread_list
- th = get_thread($1.to_i)
- if th == Thread.current
- @stdout.print "It's the current thread.\n"
- else
- thread_list(@thread_list[th])
- context(th).stop_next
- th.run
- return :cont
- end
-
- when /^stop\s+(\d+)/
- make_thread_list
- th = get_thread($1.to_i)
- if th == Thread.current
- @stdout.print "It's the current thread.\n"
- elsif th.stop?
- @stdout.print "Already stopped.\n"
- else
- thread_list(@thread_list[th])
- context(th).suspend
- end
-
- when /^resume\s+(\d+)/
- make_thread_list
- th = get_thread($1.to_i)
- if th == Thread.current
- @stdout.print "It's the current thread.\n"
- elsif !th.stop?
- @stdout.print "Already running."
- else
- thread_list(@thread_list[th])
- th.run
- end
- end
- end
- end
-
- stdout.printf "Debug.rb\n"
- stdout.printf "Emacs support available.\n\n"
- RubyVM::InstructionSequence.compile_option = {
- trace_instruction: true
- }
- set_trace_func proc { |event, file, line, id, binding, klass, *rest|
- DEBUGGER__.context.trace_func event, file, line, id, binding, klass
- }
-end
diff --git a/lib/delegate.rb b/lib/delegate.rb
index a5ae605e9e..387a5f063d 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -39,12 +39,12 @@
# Be advised, RDoc will not detect delegated methods.
#
class Delegator < BasicObject
- VERSION = "0.2.0"
+ VERSION = "0.3.0"
kernel = ::Kernel.dup
kernel.class_eval do
alias __raise__ raise
- [:to_s, :inspect, :=~, :!~, :===, :<=>, :hash].each do |m|
+ [:to_s, :inspect, :!~, :===, :<=>, :hash].each do |m|
undef_method m
end
private_instance_methods.each do |m|
diff --git a/lib/delegate/delegate.gemspec b/lib/delegate/delegate.gemspec
index 05d9ced175..1cfacfeb2f 100644
--- a/lib/delegate/delegate.gemspec
+++ b/lib/delegate/delegate.gemspec
@@ -24,8 +24,6 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.required_ruby_version = '>= 2.7'
end
diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb
index ab7e6b01a8..2df238da06 100644
--- a/lib/did_you_mean.rb
+++ b/lib/did_you_mean.rb
@@ -7,7 +7,8 @@ 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/spell_checkers/pattern_key_name_checker'
+require_relative 'did_you_mean/formatter'
require_relative 'did_you_mean/tree_spell_checker'
# The +DidYouMean+ gem adds functionality to suggest possible method/class
@@ -85,28 +86,70 @@ require_relative 'did_you_mean/tree_spell_checker'
#
module DidYouMean
# Map of error types and spell checker objects.
- SPELL_CHECKERS = Hash.new(NullChecker)
+ @spell_checkers = Hash.new(NullChecker)
+
+ # Returns a sharable hash map of error types and spell checker objects.
+ def self.spell_checkers
+ @spell_checkers
+ end
# Adds +DidYouMean+ functionality to an error using a given spell checker
def self.correct_error(error_class, spell_checker)
- SPELL_CHECKERS[error_class.name] = spell_checker
- error_class.prepend(Correctable) unless error_class < Correctable
+ if defined?(Ractor)
+ new_mapping = { **@spell_checkers, error_class.to_s => spell_checker }
+ new_mapping.default = NullChecker
+
+ @spell_checkers = Ractor.make_shareable(new_mapping)
+ else
+ spell_checkers[error_class.to_s] = spell_checker
+ end
+
+ error_class.prepend(Correctable) if error_class.is_a?(Class) && !(error_class < Correctable)
end
correct_error NameError, NameErrorCheckers
correct_error KeyError, KeyErrorChecker
correct_error NoMethodError, MethodNameChecker
correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0'
+ correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError)
+
+ # TODO: Remove on 3.3:
+ class DeprecatedMapping # :nodoc:
+ def []=(key, value)
+ warn "Calling `DidYouMean::SPELL_CHECKERS[#{key.to_s}] = #{value.to_s}' has been deprecated. " \
+ "Please call `DidYouMean.correct_error(#{key.to_s}, #{value.to_s})' instead."
+
+ DidYouMean.correct_error(key, value)
+ end
+
+ def merge!(hash)
+ warn "Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. " \
+ "Please call `DidYouMean.correct_error(error_name, spell_checker)' instead."
+
+ hash.each do |error_class, spell_checker|
+ DidYouMean.correct_error(error_class, spell_checker)
+ end
+ end
+ end
+
+ # TODO: Remove on 3.3:
+ SPELL_CHECKERS = DeprecatedMapping.new
+ deprecate_constant :SPELL_CHECKERS
+ private_constant :DeprecatedMapping
# Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+.
def self.formatter
- @@formatter
+ if defined?(Ractor)
+ Ractor.current[:__did_you_mean_formatter__] || Formatter
+ else
+ Formatter
+ end
end
# Updates the primary formatter used to format the suggestions.
def self.formatter=(formatter)
- @@formatter = formatter
+ if defined?(Ractor)
+ Ractor.current[:__did_you_mean_formatter__] = formatter
+ end
end
-
- self.formatter = PlainFormatter.new
end
diff --git a/lib/did_you_mean/core_ext/name_error.rb b/lib/did_you_mean/core_ext/name_error.rb
index 7e99282b41..8c170c4b90 100644
--- a/lib/did_you_mean/core_ext/name_error.rb
+++ b/lib/did_you_mean/core_ext/name_error.rb
@@ -1,24 +1,49 @@
module DidYouMean
module Correctable
- SKIP_TO_S_FOR_SUPER_LOOKUP = true
- private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
+ if Exception.method_defined?(:detailed_message)
+ # just for compatibility
+ def original_message
+ # we cannot use alias here because
+ to_s
+ end
+
+ def detailed_message(highlight: true, did_you_mean: true, **)
+ msg = super.dup
+
+ return msg unless did_you_mean
+
+ suggestion = DidYouMean.formatter.message_for(corrections)
+
+ if highlight
+ suggestion = suggestion.gsub(/.+/) { "\e[1m" + $& + "\e[m" }
+ end
- def original_message
- meth = method(:to_s)
- while meth.owner.const_defined?(:SKIP_TO_S_FOR_SUPER_LOOKUP)
- meth = meth.super_method
+ msg << suggestion
+ msg
+ rescue
+ super
+ end
+ else
+ SKIP_TO_S_FOR_SUPER_LOOKUP = true
+ private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
+
+ def original_message
+ meth = method(:to_s)
+ while meth.owner.const_defined?(:SKIP_TO_S_FOR_SUPER_LOOKUP)
+ meth = meth.super_method
+ end
+ meth.call
end
- meth.call
- end
- def to_s
- msg = super.dup
- suggestion = DidYouMean.formatter.message_for(corrections)
+ def to_s
+ msg = super.dup
+ suggestion = DidYouMean.formatter.message_for(corrections)
- msg << suggestion if !msg.include?(suggestion)
- msg
- rescue
- super
+ msg << suggestion if !msg.include?(suggestion)
+ msg
+ rescue
+ super
+ end
end
def corrections
@@ -26,7 +51,7 @@ module DidYouMean
end
def spell_checker
- SPELL_CHECKERS[self.class.to_s].new(self)
+ DidYouMean.spell_checkers[self.class.to_s].new(self)
end
end
end
diff --git a/lib/did_you_mean/formatter.rb b/lib/did_you_mean/formatter.rb
new file mode 100644
index 0000000000..c43748f707
--- /dev/null
+++ b/lib/did_you_mean/formatter.rb
@@ -0,0 +1,44 @@
+# frozen-string-literal: true
+
+module DidYouMean
+ # The +DidYouMean::Formatter+ is the basic, default formatter for the
+ # gem. The formatter responds to the +message_for+ method and it returns a
+ # human readable string.
+ class Formatter
+
+ # Returns a human readable string that contains +corrections+. This
+ # formatter is designed to be less verbose to not take too much screen
+ # space while being helpful enough to the user.
+ #
+ # @example
+ #
+ # formatter = DidYouMean::Formatter.new
+ #
+ # # displays suggestions in two lines with the leading empty line
+ # puts formatter.message_for(["methods", "method"])
+ #
+ # Did you mean? methods
+ # method
+ # # => nil
+ #
+ # # displays an empty line
+ # puts formatter.message_for([])
+ #
+ # # => nil
+ #
+ def self.message_for(corrections)
+ corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}"
+ end
+
+ def message_for(corrections)
+ warn "The instance method #message_for has been deprecated. Please use the class method " \
+ "DidYouMean::Formatter.message_for(...) instead."
+
+ self.class.message_for(corrections)
+ end
+ end
+
+ PlainFormatter = Formatter
+
+ deprecate_constant :PlainFormatter
+end
diff --git a/lib/did_you_mean/formatters/plain_formatter.rb b/lib/did_you_mean/formatters/plain_formatter.rb
index e2d995f587..d669588e0f 100644
--- a/lib/did_you_mean/formatters/plain_formatter.rb
+++ b/lib/did_you_mean/formatters/plain_formatter.rb
@@ -1,33 +1,4 @@
-# frozen-string-literal: true
+require_relative '../formatter'
-module DidYouMean
- # The +DidYouMean::PlainFormatter+ is the basic, default formatter for the
- # gem. The formatter responds to the +message_for+ method and it returns a
- # human readable string.
- class PlainFormatter
-
- # Returns a human readable string that contains +corrections+. This
- # formatter is designed to be less verbose to not take too much screen
- # space while being helpful enough to the user.
- #
- # @example
- #
- # formatter = DidYouMean::PlainFormatter.new
- #
- # # displays suggestions in two lines with the leading empty line
- # puts formatter.message_for(["methods", "method"])
- #
- # Did you mean? methods
- # method
- # # => nil
- #
- # # displays an empty line
- # puts formatter.message_for([])
- #
- # # => nil
- #
- def message_for(corrections)
- corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}"
- end
- end
-end
+warn "`require 'did_you_mean/formatters/plain_formatter'` is deprecated. Please `require 'did_you_mean/formatter'` " \
+ "instead."
diff --git a/lib/did_you_mean/formatters/verbose_formatter.rb b/lib/did_you_mean/formatters/verbose_formatter.rb
index b8fe214d57..f6623681f2 100644
--- a/lib/did_you_mean/formatters/verbose_formatter.rb
+++ b/lib/did_you_mean/formatters/verbose_formatter.rb
@@ -1,49 +1,10 @@
# frozen-string-literal: true
-module DidYouMean
- # The +DidYouMean::VerboseFormatter+ uses extra empty lines to make the
- # suggestion stand out more in the error message.
- #
- # In order to activate the verbose formatter,
- #
- # @example
- #
- # OBject
- # # => NameError: uninitialized constant OBject
- # # Did you mean? Object
- #
- # require 'did_you_mean/verbose'
- #
- # OBject
- # # => NameError: uninitialized constant OBject
- # #
- # # Did you mean? Object
- # #
- #
- class VerboseFormatter
+warn "`require 'did_you_mean/formatters/verbose_formatter'` is deprecated and falls back to the default formatter. "
- # Returns a human readable string that contains +corrections+. This
- # formatter is designed to be less verbose to not take too much screen
- # space while being helpful enough to the user.
- #
- # @example
- #
- # formatter = DidYouMean::PlainFormatter.new
- #
- # puts formatter.message_for(["methods", "method"])
- #
- #
- # Did you mean? methods
- # method
- #
- # # => nil
- #
- def message_for(corrections)
- return "" if corrections.empty?
+require_relative '../formatter'
- output = "\n\n Did you mean? ".dup
- output << corrections.join("\n ")
- output << "\n "
- end
- end
+module DidYouMean
+ # For compatibility:
+ VerboseFormatter = Formatter
end
diff --git a/lib/did_you_mean/spell_checker.rb b/lib/did_you_mean/spell_checker.rb
index e5106abba2..37da2fc7a6 100644
--- a/lib/did_you_mean/spell_checker.rb
+++ b/lib/did_you_mean/spell_checker.rb
@@ -10,25 +10,25 @@ module DidYouMean
end
def correct(input)
- input = normalize(input)
- threshold = input.length > 3 ? 0.834 : 0.77
+ normalized_input = normalize(input)
+ threshold = normalized_input.length > 3 ? 0.834 : 0.77
- words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), input) >= threshold }
- words.reject! { |word| input == word.to_s }
- words.sort_by! { |word| JaroWinkler.distance(word.to_s, input) }
+ words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), normalized_input) >= threshold }
+ words.reject! { |word| input.to_s == word.to_s }
+ words.sort_by! { |word| JaroWinkler.distance(word.to_s, normalized_input) }
words.reverse!
# Correct mistypes
- threshold = (input.length * 0.25).ceil
- corrections = words.select { |c| Levenshtein.distance(normalize(c), input) <= threshold }
+ threshold = (normalized_input.length * 0.25).ceil
+ corrections = words.select { |c| Levenshtein.distance(normalize(c), normalized_input) <= threshold }
# Correct misspells
if corrections.empty?
corrections = words.select do |word|
word = normalize(word)
- length = input.length < word.length ? input.length : word.length
+ length = normalized_input.length < word.length ? normalized_input.length : word.length
- Levenshtein.distance(word, input) < length
+ Levenshtein.distance(word, normalized_input) < length
end.first(1)
end
diff --git a/lib/did_you_mean/spell_checkers/method_name_checker.rb b/lib/did_you_mean/spell_checkers/method_name_checker.rb
index 0483127d6f..b5cbbb5da6 100644
--- a/lib/did_you_mean/spell_checkers/method_name_checker.rb
+++ b/lib/did_you_mean/spell_checkers/method_name_checker.rb
@@ -6,6 +6,7 @@ module DidYouMean
NAMES_TO_EXCLUDE = { NilClass => nil.methods }
NAMES_TO_EXCLUDE.default = []
+ Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor)
# +MethodNameChecker::RB_RESERVED_WORDS+ is the list of reserved words in
# Ruby that take an argument. Unlike
@@ -36,6 +37,8 @@ module DidYouMean
yield
)
+ Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor)
+
def initialize(exception)
@method_name = exception.name
@receiver = exception.receiver
@@ -56,6 +59,13 @@ module DidYouMean
method_names = receiver.methods + receiver.singleton_methods
method_names += receiver.private_methods if @private_call
method_names.uniq!
+ # Assume that people trying to use a writer are not interested in a reader
+ # and vice versa
+ if method_name.match?(/=\Z/)
+ method_names.select! { |name| name.match?(/=\Z/) }
+ else
+ method_names.reject! { |name| name.match?(/=\Z/) }
+ end
method_names
else
[]
diff --git a/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb b/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
index 3e51b4fa3a..9a6e04fe64 100644
--- a/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
+++ b/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
@@ -8,6 +8,7 @@ module DidYouMean
NAMES_TO_EXCLUDE = { 'foo' => [:fork, :for] }
NAMES_TO_EXCLUDE.default = []
+ Ractor.make_shareable(NAMES_TO_EXCLUDE) if defined?(Ractor)
# +VariableNameChecker::RB_RESERVED_WORDS+ is the list of all reserved
# words in Ruby. They could be declared like methods are, and a typo would
@@ -62,6 +63,8 @@ module DidYouMean
__ENCODING__
)
+ Ractor.make_shareable(RB_RESERVED_WORDS) if defined?(Ractor)
+
def initialize(exception)
@name = exception.name.to_s.tr("@", "")
@lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : []
@@ -76,7 +79,7 @@ module DidYouMean
def corrections
@corrections ||= SpellChecker
.new(dictionary: (RB_RESERVED_WORDS + lvar_names + method_names + ivar_names + cvar_names))
- .correct(name) - NAMES_TO_EXCLUDE[@name]
+ .correct(name).uniq - NAMES_TO_EXCLUDE[@name]
end
end
end
diff --git a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb
new file mode 100644
index 0000000000..ed263c8f93
--- /dev/null
+++ b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb
@@ -0,0 +1,20 @@
+require_relative "../spell_checker"
+
+module DidYouMean
+ class PatternKeyNameChecker
+ def initialize(no_matching_pattern_key_error)
+ @key = no_matching_pattern_key_error.key
+ @keys = no_matching_pattern_key_error.matchee.keys
+ end
+
+ def corrections
+ @corrections ||= exact_matches.empty? ? SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect) : exact_matches
+ end
+
+ private
+
+ def exact_matches
+ @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect)
+ end
+ end
+end
diff --git a/lib/did_you_mean/spell_checkers/require_path_checker.rb b/lib/did_you_mean/spell_checkers/require_path_checker.rb
index e4cdb9f43d..586ced37de 100644
--- a/lib/did_you_mean/spell_checkers/require_path_checker.rb
+++ b/lib/did_you_mean/spell_checkers/require_path_checker.rb
@@ -9,7 +9,10 @@ module DidYouMean
attr_reader :path
INITIAL_LOAD_PATH = $LOAD_PATH.dup.freeze
- ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}"
+ Ractor.make_shareable(INITIAL_LOAD_PATH) if defined?(Ractor)
+
+ ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}"
+ Ractor.make_shareable(ENV_SPECIFIC_EXT) if defined?(Ractor)
private_constant :INITIAL_LOAD_PATH, :ENV_SPECIFIC_EXT
diff --git a/lib/did_you_mean/verbose.rb b/lib/did_you_mean/verbose.rb
index 4e86f167ea..1ff19aef80 100644
--- a/lib/did_you_mean/verbose.rb
+++ b/lib/did_you_mean/verbose.rb
@@ -1,4 +1,2 @@
-require_relative '../did_you_mean'
-require_relative 'formatters/verbose_formatter'
-
-DidYouMean.formatter = DidYouMean::VerboseFormatter.new
+warn "The verbose formatter has been removed and now `require 'did_you_mean/verbose'` has no effect. Please " \
+ "remove this call."
diff --git a/lib/did_you_mean/version.rb b/lib/did_you_mean/version.rb
index 8df73e1d62..5745ca1efd 100644
--- a/lib/did_you_mean/version.rb
+++ b/lib/did_you_mean/version.rb
@@ -1,3 +1,3 @@
module DidYouMean
- VERSION = "1.6.0-alpha"
+ VERSION = "1.6.3".freeze
end
diff --git a/lib/drb/drb.gemspec b/lib/drb/drb.gemspec
index 0ac525705b..c9d7e40a51 100644
--- a/lib/drb/drb.gemspec
+++ b/lib/drb/drb.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
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.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
@@ -37,8 +37,6 @@ Gem::Specification.new do |spec|
lib/drb/version.rb
lib/drb/weakidconv.rb
]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "ruby2_keywords"
diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
index 3e23213911..23181bb834 100644
--- a/lib/drb/drb.rb
+++ b/lib/drb/drb.rb
@@ -1627,9 +1627,12 @@ module DRb
end
def perform
- @result = nil
- @succ = false
- setup_message
+ begin
+ setup_message
+ ensure
+ @result = nil
+ @succ = false
+ end
if @block
@result = perform_with_block
@@ -1718,6 +1721,7 @@ module DRb
client_uri = client.uri
@exported_uri << client_uri unless @exported_uri.include?(client_uri)
end
+ _last_invoke_method = nil
loop do
begin
succ = false
@@ -1730,6 +1734,7 @@ module DRb
rescue Exception => e
error_print(e) if verbose
ensure
+ _last_invoke_method = invoke_method
client.close unless succ
if Thread.current['DRb']['stop_service']
shutdown
diff --git a/lib/drb/extserv.rb b/lib/drb/extserv.rb
index a93d5d1576..9523fe84e3 100644
--- a/lib/drb/extserv.rb
+++ b/lib/drb/extserv.rb
@@ -18,7 +18,7 @@ module DRb
@name = name
ro = DRbObject.new(nil, there)
synchronize do
- @invoker = ro.regist(name, DRbObject.new(self, @server.uri))
+ @invoker = ro.register(name, DRbObject.new(self, @server.uri))
end
end
attr_reader :server
@@ -29,7 +29,7 @@ module DRb
def stop_service
synchronize do
- @invoker.unregist(@name)
+ @invoker.unregister(@name)
server = @server
@server = nil
server.stop_service
diff --git a/lib/drb/extservm.rb b/lib/drb/extservm.rb
index 040e4e3e08..9333a108e5 100644
--- a/lib/drb/extservm.rb
+++ b/lib/drb/extservm.rb
@@ -44,19 +44,21 @@ module DRb
end
end
- def regist(name, ro)
+ def register(name, ro)
synchronize do
@servers[name] = ro
@cond.signal
end
self
end
+ alias regist register
- def unregist(name)
+ def unregister(name)
synchronize do
@servers.delete(name)
end
end
+ alias unregist unregister
private
def invoke_thread
diff --git a/lib/drb/version.rb b/lib/drb/version.rb
index ffba81d48e..10d33445b6 100644
--- a/lib/drb/version.rb
+++ b/lib/drb/version.rb
@@ -1,3 +1,3 @@
module DRb
- VERSION = "2.0.4"
+ VERSION = "2.1.1"
end
diff --git a/lib/erb.gemspec b/lib/erb.gemspec
index 43ffc89c69..d973cc10de 100644
--- a/lib/erb.gemspec
+++ b/lib/erb.gemspec
@@ -8,8 +8,8 @@ end
Gem::Specification.new do |spec|
spec.name = 'erb'
spec.version = ERB.const_get(:VERSION, false)
- spec.authors = ['Masatoshi SEKI']
- spec.email = ['seki@ruby-lang.org']
+ spec.authors = ['Masatoshi SEKI', 'Takashi Kokubun']
+ spec.email = ['seki@ruby-lang.org', 'takashikkbn@gmail.com']
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.}
@@ -27,5 +27,12 @@ Gem::Specification.new do |spec|
spec.executables = ['erb']
spec.require_paths = ['lib']
- spec.add_dependency 'cgi'
+ if RUBY_ENGINE == 'jruby'
+ spec.platform = 'java'
+ else
+ spec.required_ruby_version = '>= 2.7.0'
+ spec.extensions = ['ext/erb/escape/extconf.rb']
+ end
+
+ spec.add_dependency 'cgi', '>= 0.3.3'
end
diff --git a/lib/erb.rb b/lib/erb.rb
index 3045106c92..754419f819 100644
--- a/lib/erb.rb
+++ b/lib/erb.rb
@@ -14,6 +14,9 @@
require 'cgi/util'
require 'erb/version'
+require 'erb/compiler'
+require 'erb/def_method'
+require 'erb/util'
#
# = ERB -- Ruby Templating
@@ -264,486 +267,7 @@ class ERB
def self.version
VERSION
end
-end
-#--
-# ERB::Compiler
-class ERB
- # = ERB::Compiler
- #
- # Compiles ERB templates into Ruby code; the compiled code produces the
- # template result when evaluated. ERB::Compiler provides hooks to define how
- # generated output is handled.
- #
- # Internally ERB does something like this to generate the code returned by
- # ERB#src:
- #
- # compiler = ERB::Compiler.new('<>')
- # compiler.pre_cmd = ["_erbout=+''"]
- # compiler.put_cmd = "_erbout.<<"
- # compiler.insert_cmd = "_erbout.<<"
- # compiler.post_cmd = ["_erbout"]
- #
- # code, enc = compiler.compile("Got <%= obj %>!\n")
- # puts code
- #
- # <i>Generates</i>:
- #
- # #coding:UTF-8
- # _erbout=+''; _erbout.<< "Got ".freeze; _erbout.<<(( obj ).to_s); _erbout.<< "!\n".freeze; _erbout
- #
- # By default the output is sent to the print method. For example:
- #
- # compiler = ERB::Compiler.new('<>')
- # code, enc = compiler.compile("Got <%= obj %>!\n")
- # puts code
- #
- # <i>Generates</i>:
- #
- # #coding:UTF-8
- # print "Got ".freeze; print(( obj ).to_s); print "!\n".freeze
- #
- # == Evaluation
- #
- # The compiled code can be used in any context where the names in the code
- # correctly resolve. Using the last example, each of these print 'Got It!'
- #
- # Evaluate using a variable:
- #
- # obj = 'It'
- # eval code
- #
- # Evaluate using an input:
- #
- # mod = Module.new
- # mod.module_eval %{
- # def get(obj)
- # #{code}
- # end
- # }
- # extend mod
- # get('It')
- #
- # Evaluate using an accessor:
- #
- # klass = Class.new Object
- # klass.class_eval %{
- # attr_accessor :obj
- # def initialize(obj)
- # @obj = obj
- # end
- # def get_it
- # #{code}
- # end
- # }
- # klass.new('It').get_it
- #
- # Good! See also ERB#def_method, ERB#def_module, and ERB#def_class.
- class Compiler # :nodoc:
- class PercentLine # :nodoc:
- def initialize(str)
- @value = str
- end
- attr_reader :value
- alias :to_s :value
- end
-
- class Scanner # :nodoc:
- @scanner_map = {}
- class << self
- def register_scanner(klass, trim_mode, percent)
- @scanner_map[[trim_mode, percent]] = klass
- end
- alias :regist_scanner :register_scanner
- end
-
- def self.default_scanner=(klass)
- @default_scanner = klass
- end
-
- def self.make_scanner(src, trim_mode, percent)
- klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
- klass.new(src, trim_mode, percent)
- end
-
- DEFAULT_STAGS = %w(<%% <%= <%# <%).freeze
- DEFAULT_ETAGS = %w(%%> %>).freeze
- def initialize(src, trim_mode, percent)
- @src = src
- @stag = nil
- @stags = DEFAULT_STAGS
- @etags = DEFAULT_ETAGS
- end
- attr_accessor :stag
- attr_reader :stags, :etags
-
- def scan; end
- end
-
- class TrimScanner < Scanner # :nodoc:
- def initialize(src, trim_mode, percent)
- super
- @trim_mode = trim_mode
- @percent = percent
- if @trim_mode == '>'
- @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
- @scan_line = self.method(:trim_line1)
- elsif @trim_mode == '<>'
- @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
- @scan_line = self.method(:trim_line2)
- elsif @trim_mode == '-'
- @scan_reg = /(.*?)(^[ \t]*<%\-|<%\-|-%>\r?\n|-%>|#{(stags + etags).join('|')}|\z)/m
- @scan_line = self.method(:explicit_trim_line)
- else
- @scan_reg = /(.*?)(#{(stags + etags).join('|')}|\n|\z)/m
- @scan_line = self.method(:scan_line)
- end
- end
-
- def scan(&block)
- @stag = nil
- if @percent
- @src.each_line do |line|
- percent_line(line, &block)
- end
- else
- @scan_line.call(@src, &block)
- end
- nil
- end
-
- def percent_line(line, &block)
- if @stag || line[0] != ?%
- return @scan_line.call(line, &block)
- end
-
- line[0] = ''
- if line[0] == ?%
- @scan_line.call(line, &block)
- else
- yield(PercentLine.new(line.chomp))
- end
- end
-
- def scan_line(line)
- line.scan(@scan_reg) do |tokens|
- tokens.each do |token|
- next if token.empty?
- yield(token)
- end
- end
- end
-
- def trim_line1(line)
- line.scan(@scan_reg) do |tokens|
- tokens.each do |token|
- next if token.empty?
- if token == "%>\n" || token == "%>\r\n"
- yield('%>')
- yield(:cr)
- else
- yield(token)
- end
- end
- end
- end
-
- def trim_line2(line)
- head = nil
- line.scan(@scan_reg) do |tokens|
- tokens.each do |token|
- next if token.empty?
- head = token unless head
- if token == "%>\n" || token == "%>\r\n"
- yield('%>')
- if is_erb_stag?(head)
- yield(:cr)
- else
- yield("\n")
- end
- head = nil
- else
- yield(token)
- head = nil if token == "\n"
- end
- end
- end
- end
-
- def explicit_trim_line(line)
- line.scan(@scan_reg) do |tokens|
- tokens.each do |token|
- next if token.empty?
- if @stag.nil? && /[ \t]*<%-/ =~ token
- yield('<%')
- elsif @stag && (token == "-%>\n" || token == "-%>\r\n")
- yield('%>')
- yield(:cr)
- elsif @stag && token == '-%>'
- yield('%>')
- else
- yield(token)
- end
- end
- end
- end
-
- ERB_STAG = %w(<%= <%# <%)
- def is_erb_stag?(s)
- ERB_STAG.member?(s)
- end
- end
-
- Scanner.default_scanner = TrimScanner
-
- begin
- require 'strscan'
- rescue LoadError
- else
- class SimpleScanner < Scanner # :nodoc:
- def scan
- stag_reg = (stags == DEFAULT_STAGS) ? /(.*?)(<%[%=#]?|\z)/m : /(.*?)(#{stags.join('|')}|\z)/m
- etag_reg = (etags == DEFAULT_ETAGS) ? /(.*?)(%%?>|\z)/m : /(.*?)(#{etags.join('|')}|\z)/m
- scanner = StringScanner.new(@src)
- while ! scanner.eos?
- scanner.scan(@stag ? etag_reg : stag_reg)
- yield(scanner[1])
- yield(scanner[2])
- end
- end
- end
- Scanner.register_scanner(SimpleScanner, nil, false)
-
- class ExplicitScanner < Scanner # :nodoc:
- def scan
- stag_reg = /(.*?)(^[ \t]*<%-|<%-|#{stags.join('|')}|\z)/m
- etag_reg = /(.*?)(-%>|#{etags.join('|')}|\z)/m
- scanner = StringScanner.new(@src)
- while ! scanner.eos?
- scanner.scan(@stag ? etag_reg : stag_reg)
- yield(scanner[1])
-
- elem = scanner[2]
- if /[ \t]*<%-/ =~ elem
- yield('<%')
- elsif elem == '-%>'
- yield('%>')
- yield(:cr) if scanner.scan(/(\r?\n|\z)/)
- else
- yield(elem)
- end
- end
- end
- end
- Scanner.register_scanner(ExplicitScanner, '-', false)
- end
-
- class Buffer # :nodoc:
- def initialize(compiler, enc=nil, frozen=nil)
- @compiler = compiler
- @line = []
- @script = +''
- @script << "#coding:#{enc}\n" if enc
- @script << "#frozen-string-literal:#{frozen}\n" unless frozen.nil?
- @compiler.pre_cmd.each do |x|
- push(x)
- end
- end
- attr_reader :script
-
- def push(cmd)
- @line << cmd
- end
-
- def cr
- @script << (@line.join('; '))
- @line = []
- @script << "\n"
- end
-
- def close
- return unless @line
- @compiler.post_cmd.each do |x|
- push(x)
- end
- @script << (@line.join('; '))
- @line = nil
- end
- end
-
- def add_put_cmd(out, content)
- out.push("#{@put_cmd} #{content.dump}.freeze#{"\n" * content.count("\n")}")
- end
-
- def add_insert_cmd(out, content)
- out.push("#{@insert_cmd}((#{content}).to_s)")
- end
-
- # Compiles an ERB template into Ruby code. Returns an array of the code
- # and encoding like ["code", Encoding].
- def compile(s)
- enc = s.encoding
- raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
- s = s.b # see String#b
- magic_comment = detect_magic_comment(s, enc)
- out = Buffer.new(self, *magic_comment)
-
- self.content = +''
- scanner = make_scanner(s)
- scanner.scan do |token|
- next if token.nil?
- next if token == ''
- if scanner.stag.nil?
- compile_stag(token, out, scanner)
- else
- compile_etag(token, out, scanner)
- end
- end
- add_put_cmd(out, content) if content.size > 0
- out.close
- return out.script, *magic_comment
- end
-
- def compile_stag(stag, out, scanner)
- case stag
- when PercentLine
- add_put_cmd(out, content) if content.size > 0
- self.content = +''
- out.push(stag.to_s)
- out.cr
- when :cr
- out.cr
- when '<%', '<%=', '<%#'
- scanner.stag = stag
- add_put_cmd(out, content) if content.size > 0
- self.content = +''
- when "\n"
- content << "\n"
- add_put_cmd(out, content)
- self.content = +''
- when '<%%'
- content << '<%'
- else
- content << stag
- end
- end
-
- def compile_etag(etag, out, scanner)
- case etag
- when '%>'
- compile_content(scanner.stag, out)
- scanner.stag = nil
- self.content = +''
- when '%%>'
- content << '%>'
- else
- content << etag
- end
- end
-
- def compile_content(stag, out)
- case stag
- when '<%'
- if content[-1] == ?\n
- content.chop!
- out.push(content)
- out.cr
- else
- out.push(content)
- end
- when '<%='
- add_insert_cmd(out, content)
- when '<%#'
- # commented out
- end
- end
-
- def prepare_trim_mode(mode) # :nodoc:
- case mode
- when 1
- return [false, '>']
- when 2
- return [false, '<>']
- when 0, nil
- return [false, nil]
- when String
- unless mode.match?(/\A(%|-|>|<>){1,2}\z/)
- warn_invalid_trim_mode(mode, uplevel: 5)
- end
-
- perc = mode.include?('%')
- if mode.include?('-')
- return [perc, '-']
- elsif mode.include?('<>')
- return [perc, '<>']
- elsif mode.include?('>')
- return [perc, '>']
- else
- [perc, nil]
- end
- else
- warn_invalid_trim_mode(mode, uplevel: 5)
- return [false, nil]
- end
- end
-
- def make_scanner(src) # :nodoc:
- Scanner.make_scanner(src, @trim_mode, @percent)
- end
-
- # Construct a new compiler using the trim_mode. See ERB::new for available
- # trim modes.
- def initialize(trim_mode)
- @percent, @trim_mode = prepare_trim_mode(trim_mode)
- @put_cmd = 'print'
- @insert_cmd = @put_cmd
- @pre_cmd = []
- @post_cmd = []
- end
- attr_reader :percent, :trim_mode
-
- # The command to handle text that ends with a newline
- attr_accessor :put_cmd
-
- # The command to handle text that is inserted prior to a newline
- attr_accessor :insert_cmd
-
- # An array of commands prepended to compiled code
- attr_accessor :pre_cmd
-
- # An array of commands appended to compiled code
- attr_accessor :post_cmd
-
- private
-
- # A buffered text in #compile
- attr_accessor :content
-
- def detect_magic_comment(s, enc = nil)
- re = @percent ? /\G(?:<%#(.*)%>|%#(.*)\n)/ : /\G<%#(.*)%>/
- frozen = nil
- s.scan(re) do
- comment = $+
- comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
- case comment
- when %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
- enc = Encoding.find($1.sub(/-(?:mac|dos|unix)/i, ''))
- when %r"frozen[-_]string[-_]literal\s*:\s*([[:alnum:]]+)"
- frozen = $1
- end
- end
- return enc, frozen
- end
-
- def warn_invalid_trim_mode(mode, uplevel:)
- warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
- end
- end
-end
-
-#--
-# ERB
-class ERB
#
# Constructs a new ERB object with the template specified in _str_.
#
@@ -980,100 +504,3 @@ class ERB
cls
end
end
-
-#--
-# ERB::Util
-class ERB
- # A utility module for conversion routines, often handy in HTML generation.
- module Util
- public
- #
- # A utility method for escaping HTML tag characters in _s_.
- #
- # require "erb"
- # include ERB::Util
- #
- # puts html_escape("is a > 0 & a < 10?")
- #
- # _Generates_
- #
- # is a &gt; 0 &amp; a &lt; 10?
- #
- def html_escape(s)
- CGI.escapeHTML(s.to_s)
- end
- alias h html_escape
- module_function :h
- module_function :html_escape
-
- #
- # A utility method for encoding the String _s_ as a URL.
- #
- # require "erb"
- # include ERB::Util
- #
- # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
- #
- # _Generates_
- #
- # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
- #
- def url_encode(s)
- s.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) { |m|
- sprintf("%%%02X", m.unpack1("C"))
- }
- end
- alias u url_encode
- module_function :u
- module_function :url_encode
- end
-end
-
-#--
-# ERB::DefMethod
-class ERB
- # Utility module to define eRuby script as instance method.
- #
- # === Example
- #
- # example.rhtml:
- # <% for item in @items %>
- # <b><%= item %></b>
- # <% end %>
- #
- # example.rb:
- # require 'erb'
- # class MyClass
- # extend ERB::DefMethod
- # def_erb_method('render()', 'example.rhtml')
- # def initialize(items)
- # @items = items
- # end
- # end
- # print MyClass.new([10,20,30]).render()
- #
- # result:
- #
- # <b>10</b>
- #
- # <b>20</b>
- #
- # <b>30</b>
- #
- module DefMethod
- public
- # define _methodname_ as instance method of current module, using ERB
- # object or eRuby file
- def def_erb_method(methodname, erb_or_fname)
- if erb_or_fname.kind_of? String
- fname = erb_or_fname
- erb = ERB.new(File.read(fname))
- erb.def_method(self, methodname, fname)
- else
- erb = erb_or_fname
- erb.def_method(self, methodname, erb.filename || '(ERB)')
- end
- end
- module_function :def_erb_method
- end
-end
diff --git a/lib/erb/compiler.rb b/lib/erb/compiler.rb
new file mode 100644
index 0000000000..547d2c4c44
--- /dev/null
+++ b/lib/erb/compiler.rb
@@ -0,0 +1,471 @@
+#--
+# ERB::Compiler
+#
+# Compiles ERB templates into Ruby code; the compiled code produces the
+# template result when evaluated. ERB::Compiler provides hooks to define how
+# generated output is handled.
+#
+# Internally ERB does something like this to generate the code returned by
+# ERB#src:
+#
+# compiler = ERB::Compiler.new('<>')
+# compiler.pre_cmd = ["_erbout=+''"]
+# compiler.put_cmd = "_erbout.<<"
+# compiler.insert_cmd = "_erbout.<<"
+# compiler.post_cmd = ["_erbout"]
+#
+# code, enc = compiler.compile("Got <%= obj %>!\n")
+# puts code
+#
+# <i>Generates</i>:
+#
+# #coding:UTF-8
+# _erbout=+''; _erbout.<< "Got ".freeze; _erbout.<<(( obj ).to_s); _erbout.<< "!\n".freeze; _erbout
+#
+# By default the output is sent to the print method. For example:
+#
+# compiler = ERB::Compiler.new('<>')
+# code, enc = compiler.compile("Got <%= obj %>!\n")
+# puts code
+#
+# <i>Generates</i>:
+#
+# #coding:UTF-8
+# print "Got ".freeze; print(( obj ).to_s); print "!\n".freeze
+#
+# == Evaluation
+#
+# The compiled code can be used in any context where the names in the code
+# correctly resolve. Using the last example, each of these print 'Got It!'
+#
+# Evaluate using a variable:
+#
+# obj = 'It'
+# eval code
+#
+# Evaluate using an input:
+#
+# mod = Module.new
+# mod.module_eval %{
+# def get(obj)
+# #{code}
+# end
+# }
+# extend mod
+# get('It')
+#
+# Evaluate using an accessor:
+#
+# klass = Class.new Object
+# klass.class_eval %{
+# attr_accessor :obj
+# def initialize(obj)
+# @obj = obj
+# end
+# def get_it
+# #{code}
+# end
+# }
+# klass.new('It').get_it
+#
+# Good! See also ERB#def_method, ERB#def_module, and ERB#def_class.
+class ERB::Compiler # :nodoc:
+ class PercentLine # :nodoc:
+ def initialize(str)
+ @value = str
+ end
+ attr_reader :value
+ alias :to_s :value
+ end
+
+ class Scanner # :nodoc:
+ @scanner_map = {}
+ class << self
+ def register_scanner(klass, trim_mode, percent)
+ @scanner_map[[trim_mode, percent]] = klass
+ end
+ alias :regist_scanner :register_scanner
+ end
+
+ def self.default_scanner=(klass)
+ @default_scanner = klass
+ end
+
+ def self.make_scanner(src, trim_mode, percent)
+ klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
+ klass.new(src, trim_mode, percent)
+ end
+
+ DEFAULT_STAGS = %w(<%% <%= <%# <%).freeze
+ DEFAULT_ETAGS = %w(%%> %>).freeze
+ def initialize(src, trim_mode, percent)
+ @src = src
+ @stag = nil
+ @stags = DEFAULT_STAGS
+ @etags = DEFAULT_ETAGS
+ end
+ attr_accessor :stag
+ attr_reader :stags, :etags
+
+ def scan; end
+ end
+
+ class TrimScanner < Scanner # :nodoc:
+ def initialize(src, trim_mode, percent)
+ super
+ @trim_mode = trim_mode
+ @percent = percent
+ if @trim_mode == '>'
+ @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
+ @scan_line = self.method(:trim_line1)
+ elsif @trim_mode == '<>'
+ @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join('|')}|\n|\z)/m
+ @scan_line = self.method(:trim_line2)
+ elsif @trim_mode == '-'
+ @scan_reg = /(.*?)(^[ \t]*<%\-|<%\-|-%>\r?\n|-%>|#{(stags + etags).join('|')}|\z)/m
+ @scan_line = self.method(:explicit_trim_line)
+ else
+ @scan_reg = /(.*?)(#{(stags + etags).join('|')}|\n|\z)/m
+ @scan_line = self.method(:scan_line)
+ end
+ end
+
+ def scan(&block)
+ @stag = nil
+ if @percent
+ @src.each_line do |line|
+ percent_line(line, &block)
+ end
+ else
+ @scan_line.call(@src, &block)
+ end
+ nil
+ end
+
+ def percent_line(line, &block)
+ if @stag || line[0] != ?%
+ return @scan_line.call(line, &block)
+ end
+
+ line[0] = ''
+ if line[0] == ?%
+ @scan_line.call(line, &block)
+ else
+ yield(PercentLine.new(line.chomp))
+ end
+ end
+
+ def scan_line(line)
+ line.scan(@scan_reg) do |tokens|
+ tokens.each do |token|
+ next if token.empty?
+ yield(token)
+ end
+ end
+ end
+
+ def trim_line1(line)
+ line.scan(@scan_reg) do |tokens|
+ tokens.each do |token|
+ next if token.empty?
+ if token == "%>\n" || token == "%>\r\n"
+ yield('%>')
+ yield(:cr)
+ else
+ yield(token)
+ end
+ end
+ end
+ end
+
+ def trim_line2(line)
+ head = nil
+ line.scan(@scan_reg) do |tokens|
+ tokens.each do |token|
+ next if token.empty?
+ head = token unless head
+ if token == "%>\n" || token == "%>\r\n"
+ yield('%>')
+ if is_erb_stag?(head)
+ yield(:cr)
+ else
+ yield("\n")
+ end
+ head = nil
+ else
+ yield(token)
+ head = nil if token == "\n"
+ end
+ end
+ end
+ end
+
+ def explicit_trim_line(line)
+ line.scan(@scan_reg) do |tokens|
+ tokens.each do |token|
+ next if token.empty?
+ if @stag.nil? && /[ \t]*<%-/ =~ token
+ yield('<%')
+ elsif @stag && (token == "-%>\n" || token == "-%>\r\n")
+ yield('%>')
+ yield(:cr)
+ elsif @stag && token == '-%>'
+ yield('%>')
+ else
+ yield(token)
+ end
+ end
+ end
+ end
+
+ ERB_STAG = %w(<%= <%# <%)
+ def is_erb_stag?(s)
+ ERB_STAG.member?(s)
+ end
+ end
+
+ Scanner.default_scanner = TrimScanner
+
+ begin
+ require 'strscan'
+ rescue LoadError
+ else
+ class SimpleScanner < Scanner # :nodoc:
+ def scan
+ stag_reg = (stags == DEFAULT_STAGS) ? /(.*?)(<%[%=#]?|\z)/m : /(.*?)(#{stags.join('|')}|\z)/m
+ etag_reg = (etags == DEFAULT_ETAGS) ? /(.*?)(%%?>|\z)/m : /(.*?)(#{etags.join('|')}|\z)/m
+ scanner = StringScanner.new(@src)
+ while ! scanner.eos?
+ scanner.scan(@stag ? etag_reg : stag_reg)
+ yield(scanner[1])
+ yield(scanner[2])
+ end
+ end
+ end
+ Scanner.register_scanner(SimpleScanner, nil, false)
+
+ class ExplicitScanner < Scanner # :nodoc:
+ def scan
+ stag_reg = /(.*?)(^[ \t]*<%-|<%-|#{stags.join('|')}|\z)/m
+ etag_reg = /(.*?)(-%>|#{etags.join('|')}|\z)/m
+ scanner = StringScanner.new(@src)
+ while ! scanner.eos?
+ scanner.scan(@stag ? etag_reg : stag_reg)
+ yield(scanner[1])
+
+ elem = scanner[2]
+ if /[ \t]*<%-/ =~ elem
+ yield('<%')
+ elsif elem == '-%>'
+ yield('%>')
+ yield(:cr) if scanner.scan(/(\r?\n|\z)/)
+ else
+ yield(elem)
+ end
+ end
+ end
+ end
+ Scanner.register_scanner(ExplicitScanner, '-', false)
+ end
+
+ class Buffer # :nodoc:
+ def initialize(compiler, enc=nil, frozen=nil)
+ @compiler = compiler
+ @line = []
+ @script = +''
+ @script << "#coding:#{enc}\n" if enc
+ @script << "#frozen-string-literal:#{frozen}\n" unless frozen.nil?
+ @compiler.pre_cmd.each do |x|
+ push(x)
+ end
+ end
+ attr_reader :script
+
+ def push(cmd)
+ @line << cmd
+ end
+
+ def cr
+ @script << (@line.join('; '))
+ @line = []
+ @script << "\n"
+ end
+
+ def close
+ return unless @line
+ @compiler.post_cmd.each do |x|
+ push(x)
+ end
+ @script << (@line.join('; '))
+ @line = nil
+ end
+ end
+
+ def add_put_cmd(out, content)
+ out.push("#{@put_cmd} #{content.dump}.freeze#{"\n" * content.count("\n")}")
+ end
+
+ def add_insert_cmd(out, content)
+ out.push("#{@insert_cmd}((#{content}).to_s)")
+ end
+
+ # Compiles an ERB template into Ruby code. Returns an array of the code
+ # and encoding like ["code", Encoding].
+ def compile(s)
+ enc = s.encoding
+ raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
+ s = s.b # see String#b
+ magic_comment = detect_magic_comment(s, enc)
+ out = Buffer.new(self, *magic_comment)
+
+ self.content = +''
+ scanner = make_scanner(s)
+ scanner.scan do |token|
+ next if token.nil?
+ next if token == ''
+ if scanner.stag.nil?
+ compile_stag(token, out, scanner)
+ else
+ compile_etag(token, out, scanner)
+ end
+ end
+ add_put_cmd(out, content) if content.size > 0
+ out.close
+ return out.script, *magic_comment
+ end
+
+ def compile_stag(stag, out, scanner)
+ case stag
+ when PercentLine
+ add_put_cmd(out, content) if content.size > 0
+ self.content = +''
+ out.push(stag.to_s)
+ out.cr
+ when :cr
+ out.cr
+ when '<%', '<%=', '<%#'
+ scanner.stag = stag
+ add_put_cmd(out, content) if content.size > 0
+ self.content = +''
+ when "\n"
+ content << "\n"
+ add_put_cmd(out, content)
+ self.content = +''
+ when '<%%'
+ content << '<%'
+ else
+ content << stag
+ end
+ end
+
+ def compile_etag(etag, out, scanner)
+ case etag
+ when '%>'
+ compile_content(scanner.stag, out)
+ scanner.stag = nil
+ self.content = +''
+ when '%%>'
+ content << '%>'
+ else
+ content << etag
+ end
+ end
+
+ def compile_content(stag, out)
+ case stag
+ when '<%'
+ if content[-1] == ?\n
+ content.chop!
+ out.push(content)
+ out.cr
+ else
+ out.push(content)
+ end
+ when '<%='
+ add_insert_cmd(out, content)
+ when '<%#'
+ out.push("\n" * content.count("\n")) # only adjust lineno
+ end
+ end
+
+ def prepare_trim_mode(mode) # :nodoc:
+ case mode
+ when 1
+ return [false, '>']
+ when 2
+ return [false, '<>']
+ when 0, nil
+ return [false, nil]
+ when String
+ unless mode.match?(/\A(%|-|>|<>){1,2}\z/)
+ warn_invalid_trim_mode(mode, uplevel: 5)
+ end
+
+ perc = mode.include?('%')
+ if mode.include?('-')
+ return [perc, '-']
+ elsif mode.include?('<>')
+ return [perc, '<>']
+ elsif mode.include?('>')
+ return [perc, '>']
+ else
+ [perc, nil]
+ end
+ else
+ warn_invalid_trim_mode(mode, uplevel: 5)
+ return [false, nil]
+ end
+ end
+
+ def make_scanner(src) # :nodoc:
+ Scanner.make_scanner(src, @trim_mode, @percent)
+ end
+
+ # Construct a new compiler using the trim_mode. See ERB::new for available
+ # trim modes.
+ def initialize(trim_mode)
+ @percent, @trim_mode = prepare_trim_mode(trim_mode)
+ @put_cmd = 'print'
+ @insert_cmd = @put_cmd
+ @pre_cmd = []
+ @post_cmd = []
+ end
+ attr_reader :percent, :trim_mode
+
+ # The command to handle text that ends with a newline
+ attr_accessor :put_cmd
+
+ # The command to handle text that is inserted prior to a newline
+ attr_accessor :insert_cmd
+
+ # An array of commands prepended to compiled code
+ attr_accessor :pre_cmd
+
+ # An array of commands appended to compiled code
+ attr_accessor :post_cmd
+
+ private
+
+ # A buffered text in #compile
+ attr_accessor :content
+
+ def detect_magic_comment(s, enc = nil)
+ re = @percent ? /\G(?:<%#(.*)%>|%#(.*)\n)/ : /\G<%#(.*)%>/
+ frozen = nil
+ s.scan(re) do
+ comment = $+
+ comment = $1 if comment[/-\*-\s*([^\s].*?)\s*-\*-$/]
+ case comment
+ when %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
+ enc = Encoding.find($1.sub(/-(?:mac|dos|unix)/i, ''))
+ when %r"frozen[-_]string[-_]literal\s*:\s*([[:alnum:]]+)"
+ frozen = $1
+ end
+ end
+ return enc, frozen
+ end
+
+ def warn_invalid_trim_mode(mode, uplevel:)
+ warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
+ end
+end
diff --git a/lib/erb/def_method.rb b/lib/erb/def_method.rb
new file mode 100644
index 0000000000..17f9c0f9fa
--- /dev/null
+++ b/lib/erb/def_method.rb
@@ -0,0 +1,46 @@
+#--
+# ERB::DefMethod
+#
+# Utility module to define eRuby script as instance method.
+#
+# === Example
+#
+# example.rhtml:
+# <% for item in @items %>
+# <b><%= item %></b>
+# <% end %>
+#
+# example.rb:
+# require 'erb'
+# class MyClass
+# extend ERB::DefMethod
+# def_erb_method('render()', 'example.rhtml')
+# def initialize(items)
+# @items = items
+# end
+# end
+# print MyClass.new([10,20,30]).render()
+#
+# result:
+#
+# <b>10</b>
+#
+# <b>20</b>
+#
+# <b>30</b>
+#
+module ERB::DefMethod
+ # define _methodname_ as instance method of current module, using ERB
+ # object or eRuby file
+ def def_erb_method(methodname, erb_or_fname)
+ if erb_or_fname.kind_of? String
+ fname = erb_or_fname
+ erb = ERB.new(File.read(fname))
+ erb.def_method(self, methodname, fname)
+ else
+ erb = erb_or_fname
+ erb.def_method(self, methodname, erb.filename || '(ERB)')
+ end
+ end
+ module_function :def_erb_method
+end
diff --git a/lib/erb/util.rb b/lib/erb/util.rb
new file mode 100644
index 0000000000..0c1e7482a8
--- /dev/null
+++ b/lib/erb/util.rb
@@ -0,0 +1,62 @@
+#--
+# ERB::Escape
+#
+# A subset of ERB::Util. Unlike ERB::Util#html_escape, we expect/hope
+# Rails will not monkey-patch ERB::Escape#html_escape.
+begin
+ # We don't build the C extension for JRuby, TruffleRuby, and WASM
+ if $LOAD_PATH.resolve_feature_path('erb/escape')
+ require 'erb/escape'
+ end
+rescue LoadError # resolve_feature_path raises LoadError on TruffleRuby 22.3.0
+end
+unless defined?(ERB::Escape)
+ module ERB::Escape
+ def html_escape(s)
+ CGI.escapeHTML(s.to_s)
+ end
+ module_function :html_escape
+ end
+end
+
+#--
+# ERB::Util
+#
+# A utility module for conversion routines, often handy in HTML generation.
+module ERB::Util
+ #
+ # A utility method for escaping HTML tag characters in _s_.
+ #
+ # require "erb"
+ # include ERB::Util
+ #
+ # puts html_escape("is a > 0 & a < 10?")
+ #
+ # _Generates_
+ #
+ # is a &gt; 0 &amp; a &lt; 10?
+ #
+ include ERB::Escape # html_escape
+ module_function :html_escape
+ alias h html_escape
+ module_function :h
+
+ #
+ # A utility method for encoding the String _s_ as a URL.
+ #
+ # require "erb"
+ # include ERB::Util
+ #
+ # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
+ #
+ # _Generates_
+ #
+ # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
+ #
+ def url_encode(s)
+ CGI.escapeURIComponent(s.to_s)
+ end
+ alias u url_encode
+ module_function :u
+ module_function :url_encode
+end
diff --git a/lib/erb/version.rb b/lib/erb/version.rb
index 0aaa38258f..38e1b76ff4 100644
--- a/lib/erb/version.rb
+++ b/lib/erb/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class ERB
- VERSION = '2.2.3'
+ VERSION = '4.0.2'
private_constant :VERSION
end
diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb
index 8392979e24..062871ee16 100644
--- a/lib/error_highlight/base.rb
+++ b/lib/error_highlight/base.rb
@@ -1,12 +1,17 @@
require_relative "version"
module ErrorHighlight
- # Identify the code fragment that seems associated with a given error
+ # Identify the code fragment at that a given exception occurred.
#
- # Arguments:
- # node: RubyVM::AbstractSyntaxTree::Node (script_lines should be enabled)
- # point_type: :name | :args
- # name: The name associated with the NameError/NoMethodError
+ # Options:
+ #
+ # point_type: :name | :args
+ # :name (default) points the method/variable name that the exception occurred.
+ # :args points the arguments of the method call that the exception occurred.
+ #
+ # backtrace_location: Thread::Backtrace::Location
+ # It locates the code fragment of the given backtrace_location.
+ # By default, it uses the first frame of backtrace_locations of the given exception.
#
# Returns:
# {
@@ -15,9 +20,56 @@ module ErrorHighlight
# last_lineno: Integer,
# last_column: Integer,
# snippet: String,
+ # script_lines: [String],
# } | nil
- def self.spot(...)
- Spotter.new(...).spot
+ #
+ # Limitations:
+ #
+ # Currently, ErrorHighlight.spot only supports a single-line code fragment.
+ # Therefore, if the return value is not nil, first_lineno and last_lineno will have
+ # the same value. If the relevant code fragment spans multiple lines
+ # (e.g., Array#[] of +ary[(newline)expr(newline)]+), the method will return nil.
+ # This restriction may be removed in the future.
+ def self.spot(obj, **opts)
+ case obj
+ when Exception
+ exc = obj
+ loc = opts[:backtrace_location]
+ opts = { point_type: opts.fetch(:point_type, :name) }
+
+ unless loc
+ case exc
+ when TypeError, ArgumentError
+ opts[:point_type] = :args
+ end
+
+ locs = exc.backtrace_locations
+ return nil unless locs
+
+ loc = locs.first
+ return nil unless loc
+
+ opts[:name] = exc.name if NameError === obj
+ end
+
+ return nil unless Thread::Backtrace::Location === loc
+
+ node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
+
+ Spotter.new(node, **opts).spot
+
+ when RubyVM::AbstractSyntaxTree::Node
+ Spotter.new(obj, **opts).spot
+
+ else
+ raise TypeError, "Exception is expected"
+ end
+
+ rescue SyntaxError,
+ SystemCallError, # file not found or something
+ ArgumentError # eval'ed code
+
+ return nil
end
class Spotter
@@ -122,6 +174,7 @@ module ErrorHighlight
last_lineno: @end_lineno,
last_column: @end_column,
snippet: @snippet,
+ script_lines: @node.script_lines,
}
else
return nil
diff --git a/lib/error_highlight/core_ext.rb b/lib/error_highlight/core_ext.rb
index 1e91debc0c..b69093f74e 100644
--- a/lib/error_highlight/core_ext.rb
+++ b/lib/error_highlight/core_ext.rb
@@ -2,49 +2,46 @@ require_relative "formatter"
module ErrorHighlight
module CoreExt
- # This is a marker to let `DidYouMean::Correctable#original_message` skip
- # the following method definition of `to_s`.
- # See https://github.com/ruby/did_you_mean/pull/152
- SKIP_TO_S_FOR_SUPER_LOOKUP = true
- private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
-
- def to_s
- msg = super.dup
-
- locs = backtrace_locations
- return msg unless locs
-
- loc = locs.first
- begin
- node = RubyVM::AbstractSyntaxTree.of(loc, save_script_lines: true)
- opts = {}
+ private def generate_snippet
+ spot = ErrorHighlight.spot(self)
+ return "" unless spot
+ return ErrorHighlight.formatter.message_for(spot)
+ end
- case self
- when NoMethodError, NameError
- opts[:point_type] = :name
- opts[:name] = name
- when TypeError, ArgumentError
- opts[:point_type] = :args
+ if Exception.method_defined?(:detailed_message)
+ def detailed_message(highlight: false, error_highlight: true, **)
+ return super unless error_highlight
+ snippet = generate_snippet
+ if highlight
+ snippet = snippet.gsub(/.+/) { "\e[1m" + $& + "\e[m" }
end
-
- spot = ErrorHighlight.spot(node, **opts)
-
- rescue Errno::ENOENT, SyntaxError
+ super + snippet
end
-
- if spot
- points = ErrorHighlight.formatter.message_for(spot)
- msg << points if !msg.include?(points)
+ else
+ # This is a marker to let `DidYouMean::Correctable#original_message` skip
+ # the following method definition of `to_s`.
+ # See https://github.com/ruby/did_you_mean/pull/152
+ SKIP_TO_S_FOR_SUPER_LOOKUP = true
+ private_constant :SKIP_TO_S_FOR_SUPER_LOOKUP
+
+ def to_s
+ msg = super
+ snippet = generate_snippet
+ if snippet != "" && !msg.include?(snippet)
+ msg + snippet
+ else
+ msg
+ end
end
-
- msg
end
end
NameError.prepend(CoreExt)
- # The extension for TypeError/ArgumentError is temporarily disabled due to many test failures
-
- #TypeError.prepend(CoreExt)
- #ArgumentError.prepend(CoreExt)
+ if Exception.method_defined?(:detailed_message)
+ # ErrorHighlight is enabled for TypeError and ArgumentError only when Exception#detailed_message is available.
+ # This is because changing ArgumentError#message is highly incompatible.
+ TypeError.prepend(CoreExt)
+ ArgumentError.prepend(CoreExt)
+ end
end
diff --git a/lib/error_highlight/formatter.rb b/lib/error_highlight/formatter.rb
index ce687fb2a2..20ca78d468 100644
--- a/lib/error_highlight/formatter.rb
+++ b/lib/error_highlight/formatter.rb
@@ -1,6 +1,6 @@
module ErrorHighlight
class DefaultFormatter
- def message_for(spot)
+ def self.message_for(spot)
# currently only a one-line code snippet is supported
if spot[:first_lineno] == spot[:last_lineno]
indent = spot[:snippet][0...spot[:first_column]].gsub(/[^\t]/, " ")
@@ -14,12 +14,10 @@ module ErrorHighlight
end
def self.formatter
- @@formatter
+ Ractor.current[:__error_highlight_formatter__] || DefaultFormatter
end
def self.formatter=(formatter)
- @@formatter = formatter
+ Ractor.current[:__error_highlight_formatter__] = formatter
end
-
- self.formatter = DefaultFormatter.new
end
diff --git a/lib/error_highlight/version.rb b/lib/error_highlight/version.rb
index 0dda1ba375..5afe5f06d6 100644
--- a/lib/error_highlight/version.rb
+++ b/lib/error_highlight/version.rb
@@ -1,3 +1,3 @@
module ErrorHighlight
- VERSION = "0.2.0"
+ VERSION = "0.5.1"
end
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 69de458665..b495078f93 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -6,103 +6,181 @@ rescue LoadError
# for make mjit-headers
end
+# Namespace for file utility methods for copying, moving, removing, etc.
#
-# = fileutils.rb
+# == What's Here
#
-# Copyright (c) 2000-2007 Minero Aoki
+# First, what’s elsewhere. \Module \FileUtils:
#
-# This program is free software.
-# You can distribute/modify this program under the same terms of ruby.
+# - Inherits from {class Object}[rdoc-ref:Object].
+# - Supplements {class File}[rdoc-ref:File]
+# (but is not included or extended there).
#
-# == module FileUtils
+# Here, module \FileUtils provides methods that are useful for:
#
-# Namespace for several file utility methods for copying, moving, removing, etc.
+# - {Creating}[rdoc-ref:FileUtils@Creating].
+# - {Deleting}[rdoc-ref:FileUtils@Deleting].
+# - {Querying}[rdoc-ref:FileUtils@Querying].
+# - {Setting}[rdoc-ref:FileUtils@Setting].
+# - {Comparing}[rdoc-ref:FileUtils@Comparing].
+# - {Copying}[rdoc-ref:FileUtils@Copying].
+# - {Moving}[rdoc-ref:FileUtils@Moving].
+# - {Options}[rdoc-ref:FileUtils@Options].
#
-# === Module Functions
+# === Creating
#
-# require 'fileutils'
+# - ::mkdir: Creates directories.
+# - ::mkdir_p, ::makedirs, ::mkpath: Creates directories,
+# also creating ancestor directories as needed.
+# - ::link_entry: Creates a hard link.
+# - ::ln, ::link: Creates hard links.
+# - ::ln_s, ::symlink: Creates symbolic links.
+# - ::ln_sf: Creates symbolic links, overwriting if necessary.
+# - ::ln_sr: Creates symbolic links relative to targets
#
-# FileUtils.cd(dir, **options)
-# FileUtils.cd(dir, **options) {|dir| block }
-# FileUtils.pwd()
-# FileUtils.mkdir(dir, **options)
-# FileUtils.mkdir(list, **options)
-# FileUtils.mkdir_p(dir, **options)
-# FileUtils.mkdir_p(list, **options)
-# FileUtils.rmdir(dir, **options)
-# FileUtils.rmdir(list, **options)
-# FileUtils.ln(target, link, **options)
-# FileUtils.ln(targets, dir, **options)
-# FileUtils.ln_s(target, link, **options)
-# FileUtils.ln_s(targets, dir, **options)
-# FileUtils.ln_sf(target, link, **options)
-# FileUtils.cp(src, dest, **options)
-# FileUtils.cp(list, dir, **options)
-# FileUtils.cp_r(src, dest, **options)
-# FileUtils.cp_r(list, dir, **options)
-# FileUtils.mv(src, dest, **options)
-# FileUtils.mv(list, dir, **options)
-# FileUtils.rm(list, **options)
-# FileUtils.rm_r(list, **options)
-# FileUtils.rm_rf(list, **options)
-# FileUtils.install(src, dest, **options)
-# FileUtils.chmod(mode, list, **options)
-# FileUtils.chmod_R(mode, list, **options)
-# FileUtils.chown(user, group, list, **options)
-# FileUtils.chown_R(user, group, list, **options)
-# FileUtils.touch(list, **options)
+# === Deleting
#
-# Possible <tt>options</tt> are:
+# - ::remove_dir: Removes a directory and its descendants.
+# - ::remove_entry: Removes an entry, including its descendants if it is a directory.
+# - ::remove_entry_secure: Like ::remove_entry, but removes securely.
+# - ::remove_file: Removes a file entry.
+# - ::rm, ::remove: Removes entries.
+# - ::rm_f, ::safe_unlink: Like ::rm, but removes forcibly.
+# - ::rm_r: Removes entries and their descendants.
+# - ::rm_rf, ::rmtree: Like ::rm_r, but removes forcibly.
+# - ::rmdir: Removes directories.
#
-# <tt>:force</tt> :: forced operation (rewrite files if exist, remove
-# directories if not empty, etc.);
-# <tt>:verbose</tt> :: print command to be run, in bash syntax, before
-# performing it;
-# <tt>:preserve</tt> :: preserve object's group, user and modification
-# time on copying;
-# <tt>:noop</tt> :: no changes are made (usable in combination with
-# <tt>:verbose</tt> which will print the command to run)
+# === Querying
#
-# Each method documents the options that it honours. See also ::commands,
-# ::options and ::options_of methods to introspect which command have which
-# options.
+# - ::pwd, ::getwd: Returns the path to the working directory.
+# - ::uptodate?: Returns whether a given entry is newer than given other entries.
#
-# All methods that have the concept of a "source" file or directory can take
-# either one file or a list of files in that argument. See the method
-# documentation for examples.
+# === Setting
#
-# There are some `low level' methods, which do not accept keyword arguments:
+# - ::cd, ::chdir: Sets the working directory.
+# - ::chmod: Sets permissions for an entry.
+# - ::chmod_R: Sets permissions for an entry and its descendants.
+# - ::chown: Sets the owner and group for entries.
+# - ::chown_R: Sets the owner and group for entries and their descendants.
+# - ::touch: Sets modification and access times for entries,
+# creating if necessary.
#
-# FileUtils.copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
-# FileUtils.copy_file(src, dest, preserve = false, dereference = true)
-# FileUtils.copy_stream(srcstream, deststream)
-# FileUtils.remove_entry(path, force = false)
-# FileUtils.remove_entry_secure(path, force = false)
-# FileUtils.remove_file(path, force = false)
-# FileUtils.compare_file(path_a, path_b)
-# FileUtils.compare_stream(stream_a, stream_b)
-# FileUtils.uptodate?(file, cmp_list)
+# === Comparing
#
-# == module FileUtils::Verbose
+# - ::compare_file, ::cmp, ::identical?: Returns whether two entries are identical.
+# - ::compare_stream: Returns whether two streams are identical.
#
-# This module has all methods of FileUtils module, but it outputs messages
-# before acting. This equates to passing the <tt>:verbose</tt> flag to methods
-# in FileUtils.
+# === Copying
#
-# == module FileUtils::NoWrite
+# - ::copy_entry: Recursively copies an entry.
+# - ::copy_file: Copies an entry.
+# - ::copy_stream: Copies a stream.
+# - ::cp, ::copy: Copies files.
+# - ::cp_lr: Recursively creates hard links.
+# - ::cp_r: Recursively copies files, retaining mode, owner, and group.
+# - ::install: Recursively copies files, optionally setting mode,
+# owner, and group.
#
-# This module has all methods of FileUtils module, but never changes
-# files/directories. This equates to passing the <tt>:noop</tt> flag to methods
-# in FileUtils.
+# === Moving
#
-# == module FileUtils::DryRun
+# - ::mv, ::move: Moves entries.
#
-# This module has all methods of FileUtils module, but never changes
-# files/directories. This equates to passing the <tt>:noop</tt> and
-# <tt>:verbose</tt> flags to methods in FileUtils.
+# === Options
+#
+# - ::collect_method: Returns the names of methods that accept a given option.
+# - ::commands: Returns the names of methods that accept options.
+# - ::have_option?: Returns whether a given method accepts a given option.
+# - ::options: Returns all option names.
+# - ::options_of: Returns the names of the options for a given method.
+#
+# == Path Arguments
+#
+# Some methods in \FileUtils accept _path_ arguments,
+# which are interpreted as paths to filesystem entries:
+#
+# - If the argument is a string, that value is the path.
+# - If the argument has method +:to_path+, it is converted via that method.
+# - If the argument has method +:to_str+, it is converted via that method.
+#
+# == About the Examples
+#
+# Some examples here involve trees of file entries.
+# For these, we sometimes display trees using the
+# {tree command-line utility}[https://en.wikipedia.org/wiki/Tree_(command)],
+# which is a recursive directory-listing utility that produces
+# a depth-indented listing of files and directories.
+#
+# We use a helper method to launch the command and control the format:
+#
+# def tree(dirpath = '.')
+# command = "tree --noreport --charset=ascii #{dirpath}"
+# system(command)
+# end
+#
+# To illustrate:
+#
+# tree('src0')
+# # => src0
+# # |-- sub0
+# # | |-- src0.txt
+# # | `-- src1.txt
+# # `-- sub1
+# # |-- src2.txt
+# # `-- src3.txt
+#
+# == Avoiding the TOCTTOU Vulnerability
+#
+# For certain methods that recursively remove entries,
+# there is a potential vulnerability called the
+# {Time-of-check to time-of-use}[https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use],
+# or TOCTTOU, vulnerability that can exist when:
+#
+# - An ancestor directory of the entry at the target path is world writable;
+# such directories include <tt>/tmp</tt>.
+# - The directory tree at the target path includes:
+#
+# - A world-writable descendant directory.
+# - A symbolic link.
+#
+# To avoid that vulnerability, you can use this method to remove entries:
+#
+# - FileUtils.remove_entry_secure: removes recursively
+# if the target path points to a directory.
+#
+# Also available are these methods,
+# each of which calls \FileUtils.remove_entry_secure:
+#
+# - FileUtils.rm_r with keyword argument <tt>secure: true</tt>.
+# - FileUtils.rm_rf with keyword argument <tt>secure: true</tt>.
+#
+# Finally, this method for moving entries calls \FileUtils.remove_entry_secure
+# if the source and destination are on different file systems
+# (which means that the "move" is really a copy and remove):
+#
+# - FileUtils.mv with keyword argument <tt>secure: true</tt>.
+#
+# \Method \FileUtils.remove_entry_secure removes securely
+# by applying a special pre-process:
+#
+# - If the target path points to a directory, this method uses methods
+# {File#chown}[rdoc-ref:File#chown]
+# and {File#chmod}[rdoc-ref:File#chmod]
+# in removing directories.
+# - The owner of the target directory should be either the current process
+# or the super user (root).
+#
+# WARNING: You must ensure that *ALL* parent directories cannot be
+# moved by other untrusted users. For example, parent directories
+# should not be owned by untrusted users, and should not be world
+# writable except when the sticky bit is set.
+#
+# For details of this security vulnerability, see Perl cases:
+#
+# - {CVE-2005-0448}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448].
+# - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
#
module FileUtils
- VERSION = "1.5.0"
+ VERSION = "1.7.0"
def self.private_module_function(name) #:nodoc:
module_function name
@@ -110,7 +188,13 @@ module FileUtils
end
#
- # Returns the name of the current directory.
+ # Returns a string containing the path to the current directory:
+ #
+ # FileUtils.pwd # => "/rdoc/fileutils"
+ #
+ # FileUtils.getwd is an alias for FileUtils.pwd.
+ #
+ # Related: FileUtils.cd.
#
def pwd
Dir.pwd
@@ -120,19 +204,40 @@ module FileUtils
alias getwd pwd
module_function :getwd
+ # Changes the working directory to the given +dir+, which
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments]:
+ #
+ # With no block given,
+ # changes the current directory to the directory at +dir+; returns zero:
+ #
+ # FileUtils.pwd # => "/rdoc/fileutils"
+ # FileUtils.cd('..')
+ # FileUtils.pwd # => "/rdoc"
+ # FileUtils.cd('fileutils')
+ #
+ # With a block given, changes the current directory to the directory
+ # at +dir+, calls the block with argument +dir+,
+ # and restores the original current directory; returns the block's value:
+ #
+ # FileUtils.pwd # => "/rdoc/fileutils"
+ # FileUtils.cd('..') { |arg| [arg, FileUtils.pwd] } # => ["..", "/rdoc"]
+ # FileUtils.pwd # => "/rdoc/fileutils"
+ #
+ # Keyword arguments:
+ #
+ # - <tt>verbose: true</tt> - prints an equivalent command:
#
- # Changes the current directory to the directory +dir+.
+ # FileUtils.cd('..')
+ # FileUtils.cd('fileutils')
#
- # If this method is called with block, resumes to the previous
- # working directory after the block execution has finished.
+ # Output:
#
- # FileUtils.cd('/') # change directory
+ # cd ..
+ # cd fileutils
#
- # FileUtils.cd('/', verbose: true) # change directory and report it
+ # FileUtils.chdir is an alias for FileUtils.cd.
#
- # FileUtils.cd('/') do # change directory
- # # ... # do something
- # end # return to original directory
+ # Related: FileUtils.pwd.
#
def cd(dir, verbose: nil, &block) # :yield: dir
fu_output_message "cd #{dir}" if verbose
@@ -146,11 +251,19 @@ module FileUtils
module_function :chdir
#
- # Returns true if +new+ is newer than all +old_list+.
- # Non-existent files are older than any file.
+ # Returns +true+ if the file at path +new+
+ # is newer than all the files at paths in array +old_list+;
+ # +false+ otherwise.
#
- # FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \
- # system 'make hello.o'
+ # Argument +new+ and the elements of +old_list+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments]:
+ #
+ # FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
+ # FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false
+ #
+ # A non-existent file is considered to be infinitely old.
+ #
+ # Related: FileUtils.touch.
#
def uptodate?(new, old_list)
return false unless File.exist?(new)
@@ -170,12 +283,39 @@ module FileUtils
private_module_function :remove_trailing_slash
#
- # Creates one or more directories.
+ # Creates directories at the paths in the given +list+
+ # (a single path or an array of paths);
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, creates a directory at each +path+ in +list+
+ # by calling: <tt>Dir.mkdir(path, mode)</tt>;
+ # see {Dir.mkdir}[rdoc-ref:Dir.mkdir]:
+ #
+ # FileUtils.mkdir(%w[tmp0 tmp1]) # => ["tmp0", "tmp1"]
+ # FileUtils.mkdir('tmp4') # => ["tmp4"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
+ # see {File.chmod}[rdoc-ref:File.chmod].
+ # - <tt>noop: true</tt> - does not create directories.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.mkdir(%w[tmp0 tmp1], verbose: true)
+ # FileUtils.mkdir(%w[tmp2 tmp3], mode: 0700, verbose: true)
#
- # FileUtils.mkdir 'test'
- # FileUtils.mkdir %w(tmp data)
- # FileUtils.mkdir 'notexist', noop: true # Does not really create.
- # FileUtils.mkdir 'tmp', mode: 0700
+ # Output:
+ #
+ # mkdir tmp0 tmp1
+ # mkdir -m 700 tmp2 tmp3
+ #
+ # Raises an exception if any path points to an existing
+ # file or directory, or if for any reason a directory cannot be created.
+ #
+ # Related: FileUtils.mkdir_p.
#
def mkdir(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -189,19 +329,42 @@ module FileUtils
module_function :mkdir
#
- # Creates a directory and all its parent directories.
- # For example,
+ # Creates directories at the paths in the given +list+
+ # (a single path or an array of paths),
+ # also creating ancestor directories as needed;
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, creates a directory at each +path+ in +list+,
+ # along with any needed ancestor directories,
+ # by calling: <tt>Dir.mkdir(path, mode)</tt>;
+ # see {Dir.mkdir}[rdoc-ref:Dir.mkdir]:
+ #
+ # FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
+ # FileUtils.mkdir_p('tmp4/tmp5') # => ["tmp4/tmp5"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>mode: <i>mode</i></tt> - also calls <tt>File.chmod(mode, path)</tt>;
+ # see {File.chmod}[rdoc-ref:File.chmod].
+ # - <tt>noop: true</tt> - does not create directories.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
#
- # FileUtils.mkdir_p '/usr/local/lib/ruby'
+ # FileUtils.mkdir_p(%w[tmp0 tmp1], verbose: true)
+ # FileUtils.mkdir_p(%w[tmp2 tmp3], mode: 0700, verbose: true)
#
- # causes to make following directories, if they do not exist.
+ # Output:
#
- # * /usr
- # * /usr/local
- # * /usr/local/lib
- # * /usr/local/lib/ruby
+ # mkdir -p tmp0 tmp1
+ # mkdir -p -m 700 tmp2 tmp3
#
- # You can pass several directories at a time in a list.
+ # Raises an exception if for any reason a directory cannot be created.
+ #
+ # FileUtils.mkpath and FileUtils.makedirs are aliases for FileUtils.mkdir_p.
+ #
+ # Related: FileUtils.mkdir.
#
def mkdir_p(list, mode: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -211,21 +374,11 @@ module FileUtils
list.each do |item|
path = remove_trailing_slash(item)
- # optimize for the most common case
- begin
- fu_mkdir path, mode
- next
- rescue SystemCallError
- next if File.directory?(path)
- end
-
stack = []
- until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/"
+ until File.directory?(path) || File.dirname(path) == path
stack.push path
path = File.dirname(path)
- break if File.directory?(path)
end
- stack.pop if path == stack.last # root directory should exist
stack.reverse_each do |dir|
begin
fu_mkdir dir, mode
@@ -256,12 +409,39 @@ module FileUtils
private_module_function :fu_mkdir
#
- # Removes one or more directories.
+ # Removes directories at the paths in the given +list+
+ # (a single path or an array of paths);
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # With no keyword arguments, removes the directory at each +path+ in +list+,
+ # by calling: <tt>Dir.rmdir(path)</tt>;
+ # see {Dir.rmdir}[rdoc-ref:Dir.rmdir]:
#
- # FileUtils.rmdir 'somedir'
- # FileUtils.rmdir %w(somedir anydir otherdir)
- # # Does not really remove directory; outputs message.
- # FileUtils.rmdir 'somedir', verbose: true, noop: true
+ # FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]
+ # FileUtils.rmdir('tmp4/tmp5') # => ["tmp4/tmp5"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>parents: true</tt> - removes successive ancestor directories
+ # if empty.
+ # - <tt>noop: true</tt> - does not remove directories.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.rmdir(%w[tmp0/tmp1 tmp2/tmp3], parents: true, verbose: true)
+ # FileUtils.rmdir('tmp4/tmp5', parents: true, verbose: true)
+ #
+ # Output:
+ #
+ # rmdir -p tmp0/tmp1 tmp2/tmp3
+ # rmdir -p tmp4/tmp5
+ #
+ # Raises an exception if a directory does not exist
+ # or if for any reason a directory cannot be removed.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rmdir(list, parents: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -282,26 +462,62 @@ module FileUtils
end
module_function :rmdir
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # :call-seq:
- # FileUtils.ln(target, link, force: nil, noop: nil, verbose: nil)
- # FileUtils.ln(target, dir, force: nil, noop: nil, verbose: nil)
- # FileUtils.ln(targets, dir, force: nil, noop: nil, verbose: nil)
+ # When +src+ is the path to an existing file
+ # and +dest+ is the path to a non-existent file,
+ # creates a hard link at +dest+ pointing to +src+; returns zero:
#
- # In the first form, creates a hard link +link+ which points to +target+.
- # If +link+ already exists, raises Errno::EEXIST.
- # But if the +force+ option is set, overwrites +link+.
+ # Dir.children('tmp0/') # => ["t.txt"]
+ # Dir.children('tmp1/') # => []
+ # FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk') # => 0
+ # Dir.children('tmp1/') # => ["t.lnk"]
#
- # FileUtils.ln 'gcc', 'cc', verbose: true
- # FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'
+ # When +src+ is the path to an existing file
+ # and +dest+ is the path to an existing directory,
+ # creates a hard link at <tt>dest/src</tt> pointing to +src+; returns zero:
#
- # In the second form, creates a link +dir/target+ pointing to +target+.
- # In the third form, creates several hard links in the directory +dir+,
- # pointing to each item in +targets+.
- # If +dir+ is not a directory, raises Errno::ENOTDIR.
+ # Dir.children('tmp2') # => ["t.dat"]
+ # Dir.children('tmp3') # => []
+ # FileUtils.ln('tmp2/t.dat', 'tmp3') # => 0
+ # Dir.children('tmp3') # => ["t.dat"]
#
- # FileUtils.cd '/sbin'
- # FileUtils.ln %w(cp mv mkdir), '/bin' # Now /sbin/cp and /bin/cp are linked.
+ # When +src+ is an array of paths to existing files
+ # and +dest+ is the path to an existing directory,
+ # then for each path +target+ in +src+,
+ # creates a hard link at <tt>dest/target</tt> pointing to +target+;
+ # returns +src+:
+ #
+ # Dir.children('tmp4/') # => []
+ # FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/') # => ["tmp0/t.txt", "tmp2/t.dat"]
+ # Dir.children('tmp4/') # => ["t.dat", "t.txt"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - overwrites +dest+ if it exists.
+ # - <tt>noop: true</tt> - does not create links.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.ln('tmp0/t.txt', 'tmp1/t.lnk', verbose: true)
+ # FileUtils.ln('tmp2/t.dat', 'tmp3', verbose: true)
+ # FileUtils.ln(['tmp0/t.txt', 'tmp2/t.dat'], 'tmp4/', verbose: true)
+ #
+ # Output:
+ #
+ # ln tmp0/t.txt tmp1/t.lnk
+ # ln tmp2/t.dat tmp3
+ # ln tmp0/t.txt tmp2/t.dat tmp4/
+ #
+ # Raises an exception if +dest+ is the path to an existing file
+ # and keyword argument +force+ is not +true+.
+ #
+ # FileUtils#link is an alias for FileUtils#ln.
+ #
+ # Related: FileUtils.link_entry (has different options).
#
def ln(src, dest, force: nil, noop: nil, verbose: nil)
fu_output_message "ln#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -316,28 +532,103 @@ module FileUtils
alias link ln
module_function :link
- #
- # Hard link +src+ to +dest+. If +src+ is a directory, this method links
- # all its contents recursively. If +dest+ is a directory, links
- # +src+ to +dest/src+.
- #
- # +src+ can be a list of files.
- #
- # If +dereference_root+ is true, this method dereference tree root.
- #
- # If +remove_destination+ is true, this method removes each destination file before copy.
- #
- # FileUtils.rm_r site_ruby + '/mylib', force: true
- # FileUtils.cp_lr 'lib/', site_ruby + '/mylib'
- #
- # # Examples of linking several files to target directory.
- # FileUtils.cp_lr %w(mail.rb field.rb debug/), site_ruby + '/tmail'
- # FileUtils.cp_lr Dir.glob('*.rb'), '/home/aamine/lib/ruby', noop: true, verbose: true
- #
- # # If you want to link all contents of a directory instead of the
- # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
- # # use the following code.
- # FileUtils.cp_lr 'src/.', 'dest' # cp_lr('src', 'dest') makes dest/src, but this doesn't.
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ is the path to a directory and +dest+ does not exist,
+ # creates links +dest+ and descendents pointing to +src+ and its descendents:
+ #
+ # tree('src0')
+ # # => src0
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # File.exist?('dest0') # => false
+ # FileUtils.cp_lr('src0', 'dest0')
+ # tree('dest0')
+ # # => dest0
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ and +dest+ are both paths to directories,
+ # creates links <tt>dest/src</tt> and descendents
+ # pointing to +src+ and its descendents:
+ #
+ # tree('src1')
+ # # => src1
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # FileUtils.mkdir('dest1')
+ # FileUtils.cp_lr('src1', 'dest1')
+ # tree('dest1')
+ # # => dest1
+ # # `-- src1
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ is an array of paths to entries and +dest+ is the path to a directory,
+ # for each path +filepath+ in +src+, creates a link at <tt>dest/filepath</tt>
+ # pointing to that path:
+ #
+ # tree('src2')
+ # # => src2
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # FileUtils.mkdir('dest2')
+ # FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2')
+ # tree('dest2')
+ # # => dest2
+ # # |-- sub0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- sub1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
+ # does not dereference it.
+ # - <tt>noop: true</tt> - does not create links.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.cp_lr('src0', 'dest0', noop: true, verbose: true)
+ # FileUtils.cp_lr('src1', 'dest1', noop: true, verbose: true)
+ # FileUtils.cp_lr(['src2/sub0', 'src2/sub1'], 'dest2', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # cp -lr src0 dest0
+ # cp -lr src1 dest1
+ # cp -lr src2/sub0 src2/sub1 dest2
+ #
+ # Raises an exception if +dest+ is the path to an existing file or directory
+ # and keyword argument <tt>remove_destination: true</tt> is not given.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp_lr(src, dest, noop: nil, verbose: nil,
dereference_root: true, remove_destination: false)
@@ -349,27 +640,81 @@ module FileUtils
end
module_function :cp_lr
+ # Creates {symbolic links}[https://en.wikipedia.org/wiki/Symbolic_link].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # :call-seq:
- # FileUtils.ln_s(target, link, force: nil, noop: nil, verbose: nil)
- # FileUtils.ln_s(target, dir, force: nil, noop: nil, verbose: nil)
- # FileUtils.ln_s(targets, dir, force: nil, noop: nil, verbose: nil)
+ # If +src+ is the path to an existing file:
#
- # In the first form, creates a symbolic link +link+ which points to +target+.
- # If +link+ already exists, raises Errno::EEXIST.
- # But if the <tt>force</tt> option is set, overwrites +link+.
+ # - When +dest+ is the path to a non-existent file,
+ # creates a symbolic link at +dest+ pointing to +src+:
#
- # FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
- # FileUtils.ln_s 'verylongsourcefilename.c', 'c', force: true
+ # FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # FileUtils.ln_s('src0.txt', 'dest0.txt')
+ # File.symlink?('dest0.txt') # => true
#
- # In the second form, creates a link +dir/target+ pointing to +target+.
- # In the third form, creates several symbolic links in the directory +dir+,
- # pointing to each item in +targets+.
- # If +dir+ is not a directory, raises Errno::ENOTDIR.
+ # - When +dest+ is the path to an existing file,
+ # creates a symbolic link at +dest+ pointing to +src+
+ # if and only if keyword argument <tt>force: true</tt> is given
+ # (raises an exception otherwise):
#
- # FileUtils.ln_s Dir.glob('/bin/*.rb'), '/home/foo/bin'
+ # FileUtils.touch('src1.txt')
+ # FileUtils.touch('dest1.txt')
+ # FileUtils.ln_s('src1.txt', 'dest1.txt', force: true)
+ # FileTest.symlink?('dest1.txt') # => true
#
- def ln_s(src, dest, force: nil, noop: nil, verbose: nil)
+ # FileUtils.ln_s('src1.txt', 'dest1.txt') # Raises Errno::EEXIST.
+ #
+ # If +dest+ is the path to a directory,
+ # creates a symbolic link at <tt>dest/src</tt> pointing to +src+:
+ #
+ # FileUtils.touch('src2.txt')
+ # FileUtils.mkdir('destdir2')
+ # FileUtils.ln_s('src2.txt', 'destdir2')
+ # File.symlink?('destdir2/src2.txt') # => true
+ #
+ # If +src+ is an array of paths to existing files and +dest+ is a directory,
+ # for each child +child+ in +src+ creates a symbolic link <tt>dest/child</tt>
+ # pointing to +child+:
+ #
+ # FileUtils.mkdir('srcdir3')
+ # FileUtils.touch('srcdir3/src0.txt')
+ # FileUtils.touch('srcdir3/src1.txt')
+ # FileUtils.mkdir('destdir3')
+ # FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3')
+ # File.symlink?('destdir3/src0.txt') # => true
+ # File.symlink?('destdir3/src1.txt') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - overwrites +dest+ if it exists.
+ # - <tt>relative: false</tt> - create links relative to +dest+.
+ # - <tt>noop: true</tt> - does not create links.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.ln_s('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # FileUtils.ln_s('src1.txt', 'destdir1', noop: true, verbose: true)
+ # FileUtils.ln_s('src2.txt', 'dest2.txt', force: true, noop: true, verbose: true)
+ # FileUtils.ln_s(['srcdir3/src0.txt', 'srcdir3/src1.txt'], 'destdir3', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # ln -s src0.txt dest0.txt
+ # ln -s src1.txt destdir1
+ # ln -sf src2.txt dest2.txt
+ # ln -s srcdir3/src0.txt srcdir3/src1.txt destdir3
+ #
+ # FileUtils.symlink is an alias for FileUtils.ln_s.
+ #
+ # Related: FileUtils.ln_sf.
+ #
+ def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
+ if relative
+ return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
+ end
fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
return if noop
fu_each_src_dest0(src, dest) do |s,d|
@@ -382,29 +727,95 @@ module FileUtils
alias symlink ln_s
module_function :symlink
- #
- # :call-seq:
- # FileUtils.ln_sf(*args)
- #
- # Same as
- #
- # FileUtils.ln_s(*args, force: true)
+ # Like FileUtils.ln_s, but always with keyword argument <tt>force: true</tt> given.
#
def ln_sf(src, dest, noop: nil, verbose: nil)
ln_s src, dest, force: true, noop: noop, verbose: verbose
end
module_function :ln_sf
+ # Like FileUtils.ln_s, but create links relative to +dest+.
#
- # Hard links a file system entry +src+ to +dest+.
- # If +src+ is a directory, this method links its contents recursively.
+ def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
+ options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
+ dest = File.path(dest)
+ srcs = Array(src)
+ link = proc do |s, target_dir_p = true|
+ s = File.path(s)
+ if target_dir_p
+ d = File.join(destdirs = dest, File.basename(s))
+ else
+ destdirs = File.dirname(d = dest)
+ end
+ destdirs = fu_split_path(File.realpath(destdirs))
+ if fu_starting_path?(s)
+ srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
+ base = fu_relative_components_from(srcdirs, destdirs)
+ s = File.join(*base)
+ else
+ srcdirs = fu_clean_components(*fu_split_path(s))
+ base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
+ while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
+ srcdirs.shift
+ base.pop
+ end
+ s = File.join(*base, *srcdirs)
+ end
+ fu_output_message "ln -s#{options} #{s} #{d}" if verbose
+ next if noop
+ remove_file d, true if force
+ File.symlink s, d
+ end
+ case srcs.size
+ when 0
+ when 1
+ link[srcs[0], target_directory && File.directory?(dest)]
+ else
+ srcs.each(&link)
+ end
+ end
+ module_function :ln_sr
+
+ # Creates {hard links}[https://en.wikipedia.org/wiki/Hard_link]; returns +nil+.
+ #
+ # Arguments +src+ and +dest+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ is the path to a file and +dest+ does not exist,
+ # creates a hard link at +dest+ pointing to +src+:
+ #
+ # FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # FileUtils.link_entry('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
+ #
+ # If +src+ is the path to a directory and +dest+ does not exist,
+ # recursively creates hard links at +dest+ pointing to paths in +src+:
+ #
+ # FileUtils.mkdir_p(['src1/dir0', 'src1/dir1'])
+ # src_file_paths = [
+ # 'src1/dir0/t0.txt',
+ # 'src1/dir0/t1.txt',
+ # 'src1/dir1/t2.txt',
+ # 'src1/dir1/t3.txt',
+ # ]
+ # FileUtils.touch(src_file_paths)
+ # File.directory?('dest1') # => true
+ # FileUtils.link_entry('src1', 'dest1')
+ # File.file?('dest1/dir0/t0.txt') # => true
+ # File.file?('dest1/dir0/t1.txt') # => true
+ # File.file?('dest1/dir1/t2.txt') # => true
+ # File.file?('dest1/dir1/t3.txt') # => true
#
- # Both of +src+ and +dest+ must be a path name.
- # +src+ must exist, +dest+ must not exist.
+ # Keyword arguments:
#
- # If +dereference_root+ is true, this method dereferences the tree root.
+ # - <tt>dereference_root: true</tt> - dereferences +src+ if it is a symbolic link.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
#
- # If +remove_destination+ is true, this method removes each destination file before copy.
+ # Raises an exception if +dest+ is the path to an existing file or directory
+ # and keyword argument <tt>remove_destination: true</tt> is not given.
+ #
+ # Related: FileUtils.ln (has different options).
#
def link_entry(src, dest, dereference_root = false, remove_destination = false)
Entry_.new(src, nil, dereference_root).traverse do |ent|
@@ -415,16 +826,59 @@ module FileUtils
end
module_function :link_entry
+ # Copies files.
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ is the path to a file and +dest+ is not the path to a directory,
+ # copies +src+ to +dest+:
+ #
+ # FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # FileUtils.cp('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
+ #
+ # If +src+ is the path to a file and +dest+ is the path to a directory,
+ # copies +src+ to <tt>dest/src</tt>:
+ #
+ # FileUtils.touch('src1.txt')
+ # FileUtils.mkdir('dest1')
+ # FileUtils.cp('src1.txt', 'dest1')
+ # File.file?('dest1/src1.txt') # => true
+ #
+ # If +src+ is an array of paths to files and +dest+ is the path to a directory,
+ # copies from each +src+ to +dest+:
+ #
+ # src_file_paths = ['src2.txt', 'src2.dat']
+ # FileUtils.touch(src_file_paths)
+ # FileUtils.mkdir('dest2')
+ # FileUtils.cp(src_file_paths, 'dest2')
+ # File.file?('dest2/src2.txt') # => true
+ # File.file?('dest2/src2.dat') # => true
#
- # Copies a file content +src+ to +dest+. If +dest+ is a directory,
- # copies +src+ to +dest/src+.
+ # Keyword arguments:
#
- # If +src+ is a list of files, then +dest+ must be a directory.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>noop: true</tt> - does not copy files.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
#
- # FileUtils.cp 'eval.c', 'eval.c.org'
- # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
- # FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', verbose: true
- # FileUtils.cp 'symlink', 'dest' # copy content, "dest" is not a symlink
+ # FileUtils.cp('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # FileUtils.cp('src1.txt', 'dest1', noop: true, verbose: true)
+ # FileUtils.cp(src_file_paths, 'dest2', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # cp src0.txt dest0.txt
+ # cp src1.txt dest1
+ # cp src2.txt src2.dat dest2
+ #
+ # Raises an exception if +src+ is a directory.
+ #
+ # FileUtils.copy is an alias for FileUtils.cp.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp(src, dest, preserve: nil, noop: nil, verbose: nil)
fu_output_message "cp#{preserve ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -438,30 +892,105 @@ module FileUtils
alias copy cp
module_function :copy
- #
- # Copies +src+ to +dest+. If +src+ is a directory, this method copies
- # all its contents recursively. If +dest+ is a directory, copies
- # +src+ to +dest/src+.
- #
- # +src+ can be a list of files.
- #
- # If +dereference_root+ is true, this method dereference tree root.
- #
- # If +remove_destination+ is true, this method removes each destination file before copy.
- #
- # # Installing Ruby library "mylib" under the site_ruby
- # FileUtils.rm_r site_ruby + '/mylib', force: true
- # FileUtils.cp_r 'lib/', site_ruby + '/mylib'
- #
- # # Examples of copying several files to target directory.
- # FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
- # FileUtils.cp_r Dir.glob('*.rb'), '/home/foo/lib/ruby', noop: true, verbose: true
- #
- # # If you want to copy all contents of a directory instead of the
- # # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
- # # use following code.
- # FileUtils.cp_r 'src/.', 'dest' # cp_r('src', 'dest') makes dest/src,
- # # but this doesn't.
+ # Recursively copies files.
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # The mode, owner, and group are retained in the copy;
+ # to change those, use FileUtils.install instead.
+ #
+ # If +src+ is the path to a file and +dest+ is not the path to a directory,
+ # copies +src+ to +dest+:
+ #
+ # FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # FileUtils.cp_r('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
+ #
+ # If +src+ is the path to a file and +dest+ is the path to a directory,
+ # copies +src+ to <tt>dest/src</tt>:
+ #
+ # FileUtils.touch('src1.txt')
+ # FileUtils.mkdir('dest1')
+ # FileUtils.cp_r('src1.txt', 'dest1')
+ # File.file?('dest1/src1.txt') # => true
+ #
+ # If +src+ is the path to a directory and +dest+ does not exist,
+ # recursively copies +src+ to +dest+:
+ #
+ # tree('src2')
+ # # => src2
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # FileUtils.exist?('dest2') # => false
+ # FileUtils.cp_r('src2', 'dest2')
+ # tree('dest2')
+ # # => dest2
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ and +dest+ are paths to directories,
+ # recursively copies +src+ to <tt>dest/src</tt>:
+ #
+ # tree('src3')
+ # # => src3
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # FileUtils.mkdir('dest3')
+ # FileUtils.cp_r('src3', 'dest3')
+ # tree('dest3')
+ # # => dest3
+ # # `-- src3
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ #
+ # If +src+ is an array of paths and +dest+ is a directory,
+ # recursively copies from each path in +src+ to +dest+;
+ # the paths in +src+ may point to files and/or directories.
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: false</tt> - if +src+ is a symbolic link,
+ # does not dereference it.
+ # - <tt>noop: true</tt> - does not copy files.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.cp_r('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # FileUtils.cp_r('src1.txt', 'dest1', noop: true, verbose: true)
+ # FileUtils.cp_r('src2', 'dest2', noop: true, verbose: true)
+ # FileUtils.cp_r('src3', 'dest3', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # cp -r src0.txt dest0.txt
+ # cp -r src1.txt dest1
+ # cp -r src2 dest2
+ # cp -r src3 dest3
+ #
+ # Raises an exception of +src+ is the path to a directory
+ # and +dest+ is the path to a file.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def cp_r(src, dest, preserve: nil, noop: nil, verbose: nil,
dereference_root: true, remove_destination: nil)
@@ -473,21 +1002,50 @@ module FileUtils
end
module_function :cp_r
+ # Recursively copies files from +src+ to +dest+.
+ #
+ # Arguments +src+ and +dest+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Copies a file system entry +src+ to +dest+.
- # If +src+ is a directory, this method copies its contents recursively.
- # This method preserves file types, c.f. symlink, directory...
- # (FIFO, device files and etc. are not supported yet)
+ # If +src+ is the path to a file, copies +src+ to +dest+:
#
- # Both of +src+ and +dest+ must be a path name.
- # +src+ must exist, +dest+ must not exist.
+ # FileUtils.touch('src0.txt')
+ # File.exist?('dest0.txt') # => false
+ # FileUtils.copy_entry('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
#
- # If +preserve+ is true, this method preserves owner, group, and
- # modified time. Permissions are copied regardless +preserve+.
+ # If +src+ is a directory, recursively copies +src+ to +dest+:
#
- # If +dereference_root+ is true, this method dereference tree root.
+ # tree('src1')
+ # # => src1
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # FileUtils.copy_entry('src1', 'dest1')
+ # tree('dest1')
+ # # => dest1
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
#
- # If +remove_destination+ is true, this method removes each destination file before copy.
+ # The recursive copying preserves file types for regular files,
+ # directories, and symbolic links;
+ # other file types (FIFO streams, device files, etc.) are not supported.
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference_root: true</tt> - if +src+ is a symbolic link,
+ # follows the link.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
if dereference_root
@@ -505,9 +1063,25 @@ module FileUtils
end
module_function :copy_entry
+ # Copies file from +src+ to +dest+, which should not be directories.
+ #
+ # Arguments +src+ and +dest+
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Copies file contents of +src+ to +dest+.
- # Both of +src+ and +dest+ must be a path name.
+ # Examples:
+ #
+ # FileUtils.touch('src0.txt')
+ # FileUtils.copy_file('src0.txt', 'dest0.txt')
+ # File.file?('dest0.txt') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>dereference: false</tt> - if +src+ is a symbolic link,
+ # does not follow the link.
+ # - <tt>preserve: true</tt> - preserves file times.
+ # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def copy_file(src, dest, preserve = false, dereference = true)
ent = Entry_.new(src, nil, dereference)
@@ -516,25 +1090,81 @@ module FileUtils
end
module_function :copy_file
+ # Copies \IO stream +src+ to \IO stream +dest+ via
+ # {IO.copy_stream}[rdoc-ref:IO.copy_stream].
#
- # Copies stream +src+ to +dest+.
- # +src+ must respond to #read(n) and
- # +dest+ must respond to #write(str).
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def copy_stream(src, dest)
IO.copy_stream(src, dest)
end
module_function :copy_stream
- #
- # Moves file(s) +src+ to +dest+. If +file+ and +dest+ exist on the different
- # disk partition, the file is copied then the original file is removed.
- #
- # FileUtils.mv 'badname.rb', 'goodname.rb'
- # FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', force: true # no error
- #
- # FileUtils.mv %w(junk.txt dust.txt), '/home/foo/.trash/'
- # FileUtils.mv Dir.glob('test*.rb'), 'test', noop: true, verbose: true
+ # Moves entries.
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # If +src+ and +dest+ are on different file systems,
+ # first copies, then removes +src+.
+ #
+ # May cause a local vulnerability if not called with keyword argument
+ # <tt>secure: true</tt>;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
+ #
+ # If +src+ is the path to a single file or directory and +dest+ does not exist,
+ # moves +src+ to +dest+:
+ #
+ # tree('src0')
+ # # => src0
+ # # |-- src0.txt
+ # # `-- src1.txt
+ # File.exist?('dest0') # => false
+ # FileUtils.mv('src0', 'dest0')
+ # File.exist?('src0') # => false
+ # tree('dest0')
+ # # => dest0
+ # # |-- src0.txt
+ # # `-- src1.txt
+ #
+ # If +src+ is an array of paths to files and directories
+ # and +dest+ is the path to a directory,
+ # copies from each path in the array to +dest+:
+ #
+ # File.file?('src1.txt') # => true
+ # tree('src1')
+ # # => src1
+ # # |-- src.dat
+ # # `-- src.txt
+ # Dir.empty?('dest1') # => true
+ # FileUtils.mv(['src1.txt', 'src1'], 'dest1')
+ # tree('dest1')
+ # # => dest1
+ # # |-- src1
+ # # | |-- src.dat
+ # # | `-- src.txt
+ # # `-- src1.txt
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - if the move includes removing +src+
+ # (that is, if +src+ and +dest+ are on different file systems),
+ # ignores raised exceptions of StandardError and its descendants.
+ # - <tt>noop: true</tt> - does not move files.
+ # - <tt>secure: true</tt> - removes +src+ securely;
+ # see details at FileUtils.remove_entry_secure.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.mv('src0', 'dest0', noop: true, verbose: true)
+ # FileUtils.mv(['src1.txt', 'src1'], 'dest1', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # mv src0 dest0
+ # mv src1.txt src1 dest1
+ #
+ # FileUtils.move is an alias for FileUtils.mv.
#
def mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil)
fu_output_message "mv#{force ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if verbose
@@ -568,13 +1198,34 @@ module FileUtils
alias move mv
module_function :move
+ # Removes entries at the paths in the given +list+
+ # (a single path or an array of paths)
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Remove file(s) specified in +list+. This method cannot remove directories.
- # All StandardErrors are ignored when the :force option is set.
+ # With no keyword arguments, removes files at the paths given in +list+:
#
- # FileUtils.rm %w( junk.txt dust.txt )
- # FileUtils.rm Dir.glob('*.so')
- # FileUtils.rm 'NotExistFile', force: true # never raises exception
+ # FileUtils.touch(['src0.txt', 'src0.dat'])
+ # FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
+ #
+ # Keyword arguments:
+ #
+ # - <tt>force: true</tt> - ignores raised exceptions of StandardError
+ # and its descendants.
+ # - <tt>noop: true</tt> - does not remove files; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # rm src0.dat src0.txt
+ #
+ # FileUtils.remove is an alias for FileUtils.rm.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm(list, force: nil, noop: nil, verbose: nil)
list = fu_list(list)
@@ -590,10 +1241,18 @@ module FileUtils
alias remove rm
module_function :remove
+ # Equivalent to:
+ #
+ # FileUtils.rm(list, force: true, **kwargs)
+ #
+ # Argument +list+ (a single path or an array of paths)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Equivalent to
+ # See FileUtils.rm for keyword arguments.
#
- # FileUtils.rm(list, force: true)
+ # FileUtils.safe_unlink is an alias for FileUtils.rm_f.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_f(list, noop: nil, verbose: nil)
rm list, force: true, noop: noop, verbose: verbose
@@ -603,24 +1262,55 @@ module FileUtils
alias safe_unlink rm_f
module_function :safe_unlink
+ # Removes entries at the paths in the given +list+
+ # (a single path or an array of paths);
+ # returns +list+, if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # May cause a local vulnerability if not called with keyword argument
+ # <tt>secure: true</tt>;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
+ #
+ # For each file path, removes the file at that path:
+ #
+ # FileUtils.touch(['src0.txt', 'src0.dat'])
+ # FileUtils.rm_r(['src0.dat', 'src0.txt'])
+ # File.exist?('src0.txt') # => false
+ # File.exist?('src0.dat') # => false
+ #
+ # For each directory path, recursively removes files and directories:
+ #
+ # tree('src1')
+ # # => src1
+ # # |-- dir0
+ # # | |-- src0.txt
+ # # | `-- src1.txt
+ # # `-- dir1
+ # # |-- src2.txt
+ # # `-- src3.txt
+ # FileUtils.rm_r('src1')
+ # File.exist?('src1') # => false
+ #
+ # Keyword arguments:
#
- # remove files +list+[0] +list+[1]... If +list+[n] is a directory,
- # removes its all contents recursively. This method ignores
- # StandardError when :force option is set.
+ # - <tt>force: true</tt> - ignores raised exceptions of StandardError
+ # and its descendants.
+ # - <tt>noop: true</tt> - does not remove entries; returns +nil+.
+ # - <tt>secure: true</tt> - removes +src+ securely;
+ # see details at FileUtils.remove_entry_secure.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
#
- # FileUtils.rm_r Dir.glob('/tmp/*')
- # FileUtils.rm_r 'some_dir', force: true
+ # FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true)
+ # FileUtils.rm_r('src1', noop: true, verbose: true)
#
- # WARNING: This method causes local vulnerability
- # if one of parent directories or removing directory tree are world
- # writable (including /tmp, whose permission is 1777), and the current
- # process has strong privilege such as Unix super user (root), and the
- # system has symbolic link. For secure removing, read the documentation
- # of remove_entry_secure carefully, and set :secure option to true.
- # Default is <tt>secure: false</tt>.
+ # Output:
#
- # NOTE: This method calls remove_entry_secure if :secure option is set.
- # See also remove_entry_secure.
+ # rm -r src0.dat src0.txt
+ # rm -r src1
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
list = fu_list(list)
@@ -636,13 +1326,22 @@ module FileUtils
end
module_function :rm_r
+ # Equivalent to:
+ #
+ # FileUtils.rm_r(list, force: true, **kwargs)
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Equivalent to
+ # May cause a local vulnerability if not called with keyword argument
+ # <tt>secure: true</tt>;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
#
- # FileUtils.rm_r(list, force: true)
+ # See FileUtils.rm_r for keyword arguments.
#
- # WARNING: This method causes local vulnerability.
- # Read the documentation of rm_r first.
+ # FileUtils.rmtree is an alias for FileUtils.rm_rf.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def rm_rf(list, noop: nil, verbose: nil, secure: nil)
rm_r list, force: true, noop: noop, verbose: verbose, secure: secure
@@ -652,37 +1351,20 @@ module FileUtils
alias rmtree rm_rf
module_function :rmtree
+ # Securely removes the entry given by +path+,
+ # which should be the entry for a regular file, a symbolic link,
+ # or a directory.
#
- # This method removes a file system entry +path+. +path+ shall be a
- # regular file, a directory, or something. If +path+ is a directory,
- # remove it recursively. This method is required to avoid TOCTTOU
- # (time-of-check-to-time-of-use) local security vulnerability of rm_r.
- # #rm_r causes security hole when:
- #
- # * Parent directory is world writable (including /tmp).
- # * Removing directory tree includes world writable directory.
- # * The system has symbolic link.
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # To avoid this security hole, this method applies special preprocess.
- # If +path+ is a directory, this method chown(2) and chmod(2) all
- # removing directories. This requires the current process is the
- # owner of the removing whole directory tree, or is the super user (root).
+ # Avoids a local vulnerability that can exist in certain circumstances;
+ # see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
#
- # WARNING: You must ensure that *ALL* parent directories cannot be
- # moved by other untrusted users. For example, parent directories
- # should not be owned by untrusted users, and should not be world
- # writable except when the sticky bit set.
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
#
- # WARNING: Only the owner of the removing directory tree, or Unix super
- # user (root) should invoke this method. Otherwise this method does not
- # work.
- #
- # For details of this security vulnerability, see Perl's case:
- #
- # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
- # * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
- #
- # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_entry_secure(path, force = false)
unless fu_have_symlink?
@@ -770,12 +1452,17 @@ module FileUtils
end
private_module_function :fu_stat_identical_entry?
+ # Removes the entry given by +path+,
+ # which should be the entry for a regular file, a symbolic link,
+ # or a directory.
+ #
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # This method removes a file system entry +path+.
- # +path+ might be a regular file, a directory, or something.
- # If +path+ is a directory, remove it recursively.
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
#
- # See also remove_entry_secure.
+ # Related: FileUtils.remove_entry_secure.
#
def remove_entry(path, force = false)
Entry_.new(path).postorder_traverse do |ent|
@@ -790,9 +1477,16 @@ module FileUtils
end
module_function :remove_entry
+ # Removes the file entry given by +path+,
+ # which should be the entry for a regular file or a symbolic link.
#
- # Removes a file +path+.
- # This method ignores StandardError if +force+ is true.
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
+ #
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_file(path, force = false)
Entry_.new(path).remove_file
@@ -801,20 +1495,32 @@ module FileUtils
end
module_function :remove_file
+ # Recursively removes the directory entry given by +path+,
+ # which should be the entry for a regular file, a symbolic link,
+ # or a directory.
+ #
+ # Argument +path+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Optional argument +force+ specifies whether to ignore
+ # raised exceptions of StandardError and its descendants.
#
- # Removes a directory +dir+ and its contents recursively.
- # This method ignores StandardError if +force+ is true.
+ # Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_dir(path, force = false)
remove_entry path, force # FIXME?? check if it is a directory
end
module_function :remove_dir
+ # Returns +true+ if the contents of files +a+ and +b+ are identical,
+ # +false+ otherwise.
#
- # Returns true if the contents of a file +a+ and a file +b+ are identical.
+ # Arguments +a+ and +b+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # FileUtils.compare_file('somefile', 'somefile') #=> true
- # FileUtils.compare_file('/dev/null', '/dev/urandom') #=> false
+ # FileUtils.identical? and FileUtils.cmp are aliases for FileUtils.compare_file.
+ #
+ # Related: FileUtils.compare_stream.
#
def compare_file(a, b)
return false unless File.size(a) == File.size(b)
@@ -831,8 +1537,13 @@ module FileUtils
module_function :identical?
module_function :cmp
+ # Returns +true+ if the contents of streams +a+ and +b+ are identical,
+ # +false+ otherwise.
+ #
+ # Arguments +a+ and +b+
+ # should be {interpretable as a path}[rdoc-ref:FileUtils@Path+Arguments].
#
- # Returns true if the contents of a stream +a+ and +b+ are identical.
+ # Related: FileUtils.compare_file.
#
def compare_stream(a, b)
bsize = fu_stream_blksize(a, b)
@@ -849,13 +1560,69 @@ module FileUtils
end
module_function :compare_stream
+ # Copies a file entry.
+ # See {install(1)}[https://man7.org/linux/man-pages/man1/install.1.html].
+ #
+ # Arguments +src+ (a single path or an array of paths)
+ # and +dest+ (a single path)
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments];
+ #
+ # If the entry at +dest+ does not exist, copies from +src+ to +dest+:
#
- # If +src+ is not same as +dest+, copies it and changes the permission
- # mode to +mode+. If +dest+ is a directory, destination is +dest+/+src+.
- # This method removes destination before copy.
+ # File.read('src0.txt') # => "aaa\n"
+ # File.exist?('dest0.txt') # => false
+ # FileUtils.install('src0.txt', 'dest0.txt')
+ # File.read('dest0.txt') # => "aaa\n"
#
- # FileUtils.install 'ruby', '/usr/local/bin/ruby', mode: 0755, verbose: true
- # FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', verbose: true
+ # If +dest+ is a file entry, copies from +src+ to +dest+, overwriting:
+ #
+ # File.read('src1.txt') # => "aaa\n"
+ # File.read('dest1.txt') # => "bbb\n"
+ # FileUtils.install('src1.txt', 'dest1.txt')
+ # File.read('dest1.txt') # => "aaa\n"
+ #
+ # If +dest+ is a directory entry, copies from +src+ to <tt>dest/src</tt>,
+ # overwriting if necessary:
+ #
+ # File.read('src2.txt') # => "aaa\n"
+ # File.read('dest2/src2.txt') # => "bbb\n"
+ # FileUtils.install('src2.txt', 'dest2')
+ # File.read('dest2/src2.txt') # => "aaa\n"
+ #
+ # If +src+ is an array of paths and +dest+ points to a directory,
+ # copies each path +path+ in +src+ to <tt>dest/path</tt>:
+ #
+ # File.file?('src3.txt') # => true
+ # File.file?('src3.dat') # => true
+ # FileUtils.mkdir('dest3')
+ # FileUtils.install(['src3.txt', 'src3.dat'], 'dest3')
+ # File.file?('dest3/src3.txt') # => true
+ # File.file?('dest3/src3.dat') # => true
+ #
+ # Keyword arguments:
+ #
+ # - <tt>group: <i>group</i></tt> - changes the group if not +nil+,
+ # using {File.chown}[rdoc-ref:File.chown].
+ # - <tt>mode: <i>permissions</i></tt> - changes the permissions.
+ # using {File.chmod}[rdoc-ref:File.chmod].
+ # - <tt>noop: true</tt> - does not copy entries; returns +nil+.
+ # - <tt>owner: <i>owner</i></tt> - changes the owner if not +nil+,
+ # using {File.chown}[rdoc-ref:File.chown].
+ # - <tt>preserve: true</tt> - preserve timestamps
+ # using {File.utime}[rdoc-ref:File.utime].
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.install('src0.txt', 'dest0.txt', noop: true, verbose: true)
+ # FileUtils.install('src1.txt', 'dest1.txt', noop: true, verbose: true)
+ # FileUtils.install('src2.txt', 'dest2', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # install -c src0.txt dest0.txt
+ # install -c src1.txt dest1.txt
+ # install -c src2.txt dest2
+ #
+ # Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
def install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil,
noop: nil, verbose: nil)
@@ -973,37 +1740,78 @@ module FileUtils
end
private_module_function :mode_to_s
+ # Changes permissions on the entries at the paths given in +list+
+ # (a single path or an array of paths)
+ # to the permissions given by +mode+;
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise:
+ #
+ # - Modifies each entry that is a regular file using
+ # {File.chmod}[rdoc-ref:File.chmod].
+ # - Modifies each entry that is a symbolic link using
+ # {File.lchmod}[rdoc-ref:File.lchmod].
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Argument +mode+ may be either an integer or a string:
+ #
+ # - \Integer +mode+: represents the permission bits to be set:
+ #
+ # FileUtils.chmod(0755, 'src0.txt')
+ # FileUtils.chmod(0644, ['src0.txt', 'src0.dat'])
+ #
+ # - \String +mode+: represents the permissions to be set:
+ #
+ # The string is of the form <tt>[targets][[operator][perms[,perms]]</tt>, where:
+ #
+ # - +targets+ may be any combination of these letters:
+ #
+ # - <tt>'u'</tt>: permissions apply to the file's owner.
+ # - <tt>'g'</tt>: permissions apply to users in the file's group.
+ # - <tt>'o'</tt>: permissions apply to other users not in the file's group.
+ # - <tt>'a'</tt> (the default): permissions apply to all users.
+ #
+ # - +operator+ may be one of these letters:
+ #
+ # - <tt>'+'</tt>: adds permissions.
+ # - <tt>'-'</tt>: removes permissions.
+ # - <tt>'='</tt>: sets (replaces) permissions.
+ #
+ # - +perms+ (may be repeated, with separating commas)
+ # may be any combination of these letters:
+ #
+ # - <tt>'r'</tt>: Read.
+ # - <tt>'w'</tt>: Write.
+ # - <tt>'x'</tt>: Execute (search, for a directory).
+ # - <tt>'X'</tt>: Search (for a directories only;
+ # must be used with <tt>'+'</tt>)
+ # - <tt>'s'</tt>: Uid or gid.
+ # - <tt>'t'</tt>: Sticky bit.
+ #
+ # Examples:
+ #
+ # FileUtils.chmod('u=wrx,go=rx', 'src1.txt')
+ # FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby')
+ #
+ # Keyword arguments:
+ #
+ # - <tt>noop: true</tt> - does not change permissions; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.chmod(0755, 'src0.txt', noop: true, verbose: true)
+ # FileUtils.chmod(0644, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
+ # FileUtils.chmod('u=wrx,go=rx', 'src1.txt', noop: true, verbose: true)
+ # FileUtils.chmod('u=wrx,go=rx', '/usr/bin/ruby', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # chmod 755 src0.txt
+ # chmod 644 src0.txt src0.dat
+ # chmod u=wrx,go=rx src1.txt
+ # chmod u=wrx,go=rx /usr/bin/ruby
+ #
+ # Related: FileUtils.chmod_R.
#
- # Changes permission bits on the named files (in +list+) to the bit pattern
- # represented by +mode+.
- #
- # +mode+ is the symbolic and absolute mode can be used.
- #
- # Absolute mode is
- # FileUtils.chmod 0755, 'somecommand'
- # FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
- # FileUtils.chmod 0755, '/usr/bin/ruby', verbose: true
- #
- # Symbolic mode is
- # FileUtils.chmod "u=wrx,go=rx", 'somecommand'
- # FileUtils.chmod "u=wr,go=rr", %w(my.rb your.rb his.rb her.rb)
- # FileUtils.chmod "u=wrx,go=rx", '/usr/bin/ruby', verbose: true
- #
- # "a" :: is user, group, other mask.
- # "u" :: is user's mask.
- # "g" :: is group's mask.
- # "o" :: is other's mask.
- # "w" :: is write permission.
- # "r" :: is read permission.
- # "x" :: is execute permission.
- # "X" ::
- # is execute permission for directories only, must be used in conjunction with "+"
- # "s" :: is uid, gid.
- # "t" :: is sticky bit.
- # "+" :: is added to a class given the specified mode.
- # "-" :: Is removed from a given class given mode.
- # "=" :: Is the exact nature of the class will be given a specified mode.
-
def chmod(mode, list, noop: nil, verbose: nil)
list = fu_list(list)
fu_output_message sprintf('chmod %s %s', mode_to_s(mode), list.join(' ')) if verbose
@@ -1014,12 +1822,7 @@ module FileUtils
end
module_function :chmod
- #
- # Changes permission bits on the named files (in +list+)
- # to the bit pattern represented by +mode+.
- #
- # FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
- # FileUtils.chmod_R "u=wrx", "/tmp/app.#{$$}"
+ # Like FileUtils.chmod, but changes permissions recursively.
#
def chmod_R(mode, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
@@ -1039,15 +1842,68 @@ module FileUtils
end
module_function :chmod_R
+ # Changes the owner and group on the entries at the paths given in +list+
+ # (a single path or an array of paths)
+ # to the given +user+ and +group+;
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise:
+ #
+ # - Modifies each entry that is a regular file using
+ # {File.chown}[rdoc-ref:File.chown].
+ # - Modifies each entry that is a symbolic link using
+ # {File.lchown}[rdoc-ref:File.lchown].
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # User and group:
+ #
+ # - Argument +user+ may be a user name or a user id;
+ # if +nil+ or +-1+, the user is not changed.
+ # - Argument +group+ may be a group name or a group id;
+ # if +nil+ or +-1+, the group is not changed.
+ # - The user must be a member of the group.
+ #
+ # Examples:
+ #
+ # # One path.
+ # # User and group as string names.
+ # File.stat('src0.txt').uid # => 1004
+ # File.stat('src0.txt').gid # => 1004
+ # FileUtils.chown('user2', 'group1', 'src0.txt')
+ # File.stat('src0.txt').uid # => 1006
+ # File.stat('src0.txt').gid # => 1005
#
- # Changes owner and group on the named files (in +list+)
- # to the user +user+ and the group +group+. +user+ and +group+
- # may be an ID (Integer/String) or a name (String).
- # If +user+ or +group+ is nil, this method does not change
- # the attribute.
+ # # User and group as uid and gid.
+ # FileUtils.chown(1004, 1004, 'src0.txt')
+ # File.stat('src0.txt').uid # => 1004
+ # File.stat('src0.txt').gid # => 1004
#
- # FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
- # FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), verbose: true
+ # # Array of paths.
+ # FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'])
+ #
+ # # Directory (not recursive).
+ # FileUtils.chown('user2', 'group1', '.')
+ #
+ # Keyword arguments:
+ #
+ # - <tt>noop: true</tt> - does not change permissions; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.chown('user2', 'group1', 'src0.txt', noop: true, verbose: true)
+ # FileUtils.chown(1004, 1004, 'src0.txt', noop: true, verbose: true)
+ # FileUtils.chown(1006, 1005, ['src0.txt', 'src0.dat'], noop: true, verbose: true)
+ # FileUtils.chown('user2', 'group1', path, noop: true, verbose: true)
+ # FileUtils.chown('user2', 'group1', '.', noop: true, verbose: true)
+ #
+ # Output:
+ #
+ # chown user2:group1 src0.txt
+ # chown 1004:1004 src0.txt
+ # chown 1006:1005 src0.txt src0.dat
+ # chown user2:group1 src0.txt
+ # chown user2:group1 .
+ #
+ # Related: FileUtils.chown_R.
#
def chown(user, group, list, noop: nil, verbose: nil)
list = fu_list(list)
@@ -1063,15 +1919,7 @@ module FileUtils
end
module_function :chown
- #
- # Changes owner and group on the named files (in +list+)
- # to the user +user+ and the group +group+ recursively.
- # +user+ and +group+ may be an ID (Integer/String) or
- # a name (String). If +user+ or +group+ is nil, this
- # method does not change the attribute.
- #
- # FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
- # FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', verbose: true
+ # Like FileUtils.chown, but changes owner and group recursively.
#
def chown_R(user, group, list, noop: nil, verbose: nil, force: nil)
list = fu_list(list)
@@ -1122,12 +1970,50 @@ module FileUtils
end
private_module_function :fu_get_gid
+ # Updates modification times (mtime) and access times (atime)
+ # of the entries given by the paths in +list+
+ # (a single path or an array of paths);
+ # returns +list+ if it is an array, <tt>[list]</tt> otherwise.
+ #
+ # By default, creates an empty file for any path to a non-existent entry;
+ # use keyword argument +nocreate+ to raise an exception instead.
+ #
+ # Argument +list+ or its elements
+ # should be {interpretable as paths}[rdoc-ref:FileUtils@Path+Arguments].
+ #
+ # Examples:
+ #
+ # # Single path.
+ # f = File.new('src0.txt') # Existing file.
+ # f.atime # => 2022-06-10 11:11:21.200277 -0700
+ # f.mtime # => 2022-06-10 11:11:21.200277 -0700
+ # FileUtils.touch('src0.txt')
+ # f = File.new('src0.txt')
+ # f.atime # => 2022-06-11 08:28:09.8185343 -0700
+ # f.mtime # => 2022-06-11 08:28:09.8185343 -0700
+ #
+ # # Array of paths.
+ # FileUtils.touch(['src0.txt', 'src0.dat'])
+ #
+ # Keyword arguments:
+ #
+ # - <tt>mtime: <i>time</i></tt> - sets the entry's mtime to the given time,
+ # instead of the current time.
+ # - <tt>nocreate: true</tt> - raises an exception if the entry does not exist.
+ # - <tt>noop: true</tt> - does not touch entries; returns +nil+.
+ # - <tt>verbose: true</tt> - prints an equivalent command:
+ #
+ # FileUtils.touch('src0.txt', noop: true, verbose: true)
+ # FileUtils.touch(['src0.txt', 'src0.dat'], noop: true, verbose: true)
+ # FileUtils.touch(path, noop: true, verbose: true)
#
- # Updates modification time (mtime) and access time (atime) of file(s) in
- # +list+. Files are created if they don't exist.
+ # Output:
#
- # FileUtils.touch 'timestamp'
- # FileUtils.touch Dir.glob('*.c'); system 'make'
+ # touch src0.txt
+ # touch src0.txt src0.dat
+ # touch src0.txt
+ #
+ # Related: FileUtils.uptodate?.
#
def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil)
list = fu_list(list)
@@ -1489,13 +2375,21 @@ module FileUtils
def postorder_traverse
if directory?
- entries().each do |ent|
+ begin
+ children = entries()
+ rescue Errno::EACCES
+ # Failed to get the list of children.
+ # Assuming there is no children, try to process the parent directory.
+ yield self
+ return
+ end
+
+ children.each do |ent|
ent.postorder_traverse do |e|
yield e
end
end
end
- ensure
yield self
end
@@ -1589,15 +2483,15 @@ module FileUtils
end
private_module_function :fu_each_src_dest
- def fu_each_src_dest0(src, dest) #:nodoc:
+ def fu_each_src_dest0(src, dest, target_directory = true) #:nodoc:
if tmp = Array.try_convert(src)
tmp.each do |s|
s = File.path(s)
- yield s, File.join(dest, File.basename(s))
+ yield s, (target_directory ? File.join(dest, File.basename(s)) : dest)
end
else
src = File.path(src)
- if File.directory?(dest)
+ if target_directory and File.directory?(dest)
yield src, File.join(dest, File.basename(src))
else
yield src, File.path(dest)
@@ -1621,6 +2515,56 @@ module FileUtils
end
private_module_function :fu_output_message
+ def fu_split_path(path)
+ path = File.path(path)
+ list = []
+ until (parent, base = File.split(path); parent == path or parent == ".")
+ list << base
+ path = parent
+ end
+ list << path
+ list.reverse!
+ end
+ private_module_function :fu_split_path
+
+ def fu_relative_components_from(target, base) #:nodoc:
+ i = 0
+ while target[i]&.== base[i]
+ i += 1
+ end
+ Array.new(base.size-i, '..').concat(target[i..-1])
+ end
+ private_module_function :fu_relative_components_from
+
+ def fu_clean_components(*comp)
+ comp.shift while comp.first == "."
+ return comp if comp.empty?
+ clean = [comp.shift]
+ path = File.join(*clean, "") # ending with File::SEPARATOR
+ while c = comp.shift
+ if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
+ clean.pop
+ path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
+ else
+ clean << c
+ path << c << "/"
+ end
+ end
+ clean
+ end
+ private_module_function :fu_clean_components
+
+ if fu_windows?
+ def fu_starting_path?(path)
+ path&.start_with?(%r(\w:|/))
+ end
+ else
+ def fu_starting_path?(path)
+ path&.start_with?("/")
+ end
+ end
+ private_module_function :fu_starting_path?
+
# This hash table holds command options.
OPT_TABLE = {} #:nodoc: internal use only
(private_instance_methods & methods(false)).inject(OPT_TABLE) {|tbl, name|
@@ -1630,50 +2574,49 @@ module FileUtils
public
+ # Returns an array of the string names of \FileUtils methods
+ # that accept one or more keyword arguments:
#
- # Returns an Array of names of high-level methods that accept any keyword
- # arguments.
- #
- # p FileUtils.commands #=> ["chmod", "cp", "cp_r", "install", ...]
+ # FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]
#
def self.commands
OPT_TABLE.keys
end
+ # Returns an array of the string keyword names:
#
- # Returns an Array of option names.
- #
- # p FileUtils.options #=> ["noop", "force", "verbose", "preserve", "mode"]
+ # FileUtils.options.take(3) # => ["noop", "verbose", "force"]
#
def self.options
OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
end
+ # Returns +true+ if method +mid+ accepts the given option +opt+, +false+ otherwise;
+ # the arguments may be strings or symbols:
#
- # Returns true if the method +mid+ have an option +opt+.
- #
- # p FileUtils.have_option?(:cp, :noop) #=> true
- # p FileUtils.have_option?(:rm, :force) #=> true
- # p FileUtils.have_option?(:rm, :preserve) #=> false
+ # FileUtils.have_option?(:chmod, :noop) # => true
+ # FileUtils.have_option?('chmod', 'secure') # => false
#
def self.have_option?(mid, opt)
li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}"
li.include?(opt)
end
+ # Returns an array of the string keyword name for method +mid+;
+ # the argument may be a string or a symbol:
#
- # Returns an Array of option names of the method +mid+.
- #
- # p FileUtils.options_of(:rm) #=> ["noop", "verbose", "force"]
+ # FileUtils.options_of(:rm) # => ["force", "noop", "verbose"]
+ # FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]
#
def self.options_of(mid)
OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
end
+ # Returns an array of the string method names of the methods
+ # that accept the given keyword option +opt+;
+ # the argument must be a symbol:
#
- # Returns an Array of methods names which have the option +opt+.
- #
- # p FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"]
+ # FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]
#
def self.collect_method(opt)
OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
diff --git a/lib/find.gemspec b/lib/find.gemspec
index fff0f706cd..3f0aadcdae 100644
--- a/lib/find.gemspec
+++ b/lib/find.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "find"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ['Kazuki Tsujimoto']
spec.email = ['kazuki@callcc.net']
diff --git a/lib/forwardable.rb b/lib/forwardable.rb
index c9c4128f9f..71b4e6adad 100644
--- a/lib/forwardable.rb
+++ b/lib/forwardable.rb
@@ -112,8 +112,10 @@ module Forwardable
require 'forwardable/impl'
# Version of +forwardable.rb+
- VERSION = "1.3.2"
+ VERSION = "1.3.3"
+ VERSION.freeze
FORWARDABLE_VERSION = VERSION
+ FORWARDABLE_VERSION.freeze
@debug = nil
class << self
diff --git a/lib/forwardable/impl.rb b/lib/forwardable/impl.rb
index 58a9dfb69c..0322c136db 100644
--- a/lib/forwardable/impl.rb
+++ b/lib/forwardable/impl.rb
@@ -1,5 +1,6 @@
-# :stopdoc:
module Forwardable
+ # :stopdoc:
+
def self._valid_method?(method)
catch {|tag|
eval("BEGIN{throw tag}; ().#{method}", binding, __FILE__, __LINE__)
diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb
index d3fff34beb..5ae0e1497c 100644
--- a/lib/getoptlong.rb
+++ b/lib/getoptlong.rb
@@ -6,87 +6,369 @@
#
# You may redistribute and/or modify this library under the same license
# terms as Ruby.
+
+# \Class \GetoptLong provides parsing both for options
+# and for regular arguments.
#
-# See GetoptLong for documentation.
+# Using \GetoptLong, you can define options for your program.
+# The program can then capture and respond to whatever options
+# are included in the command that executes the program.
#
-# Additional documents and the latest version of `getoptlong.rb' can be
-# found at http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
-
-# The GetoptLong class allows you to parse command line options similarly to
-# the GNU getopt_long() C library call. Note, however, that GetoptLong is a
-# pure Ruby implementation.
+# A simple example: file <tt>simple.rb</tt>:
+#
+# :include: ../sample/getoptlong/simple.rb
+#
+# If you are somewhat familiar with options,
+# you may want to skip to this
+# {full example}[#class-GetoptLong-label-Full+Example].
+#
+# == Options
+#
+# A \GetoptLong option has:
+#
+# - A string <em>option name</em>.
+# - Zero or more string <em>aliases</em> for the name.
+# - An <em>option type</em>.
+#
+# Options may be defined by calling singleton method GetoptLong.new,
+# which returns a new \GetoptLong object.
+# Options may then be processed by calling other methods
+# such as GetoptLong#each.
+#
+# === Option Name and Aliases
+#
+# In the array that defines an option,
+# the first element is the string option name.
+# Often the name takes the 'long' form, beginning with two hyphens.
+#
+# The option name may have any number of aliases,
+# which are defined by additional string elements.
+#
+# The name and each alias must be of one of two forms:
+#
+# - Two hyphens, followed by one or more letters.
+# - One hyphen, followed by a single letter.
+#
+# File <tt>aliases.rb</tt>:
+#
+# :include: ../sample/getoptlong/aliases.rb
+#
+# An option may be cited by its name,
+# or by any of its aliases;
+# the parsed option always reports the name, not an alias:
+#
+# $ ruby aliases.rb -a -p --xxx --aaa -x
+#
+# Output:
+#
+# ["--xxx", ""]
+# ["--xxx", ""]
+# ["--xxx", ""]
+# ["--xxx", ""]
+# ["--xxx", ""]
+#
+#
+# An option may also be cited by an abbreviation of its name or any alias,
+# as long as that abbreviation is unique among the options.
+#
+# File <tt>abbrev.rb</tt>:
+#
+# :include: ../sample/getoptlong/abbrev.rb
+#
+# Command line:
+#
+# $ ruby abbrev.rb --xxx --xx --xyz --xy
+#
+# Output:
+#
+# ["--xxx", ""]
+# ["--xxx", ""]
+# ["--xyz", ""]
+# ["--xyz", ""]
+#
+# This command line raises GetoptLong::AmbiguousOption:
+#
+# $ ruby abbrev.rb --x
+#
+# === Repetition
+#
+# An option may be cited more than once:
+#
+# $ ruby abbrev.rb --xxx --xyz --xxx --xyz
+#
+# Output:
+#
+# ["--xxx", ""]
+# ["--xyz", ""]
+# ["--xxx", ""]
+# ["--xyz", ""]
+#
+# === Treating Remaining Options as Arguments
+#
+# A option-like token that appears
+# anywhere after the token <tt>--</tt> is treated as an ordinary argument,
+# and is not processed as an option:
+#
+# $ ruby abbrev.rb --xxx --xyz -- --xxx --xyz
+#
+# Output:
+#
+# ["--xxx", ""]
+# ["--xyz", ""]
+#
+# === Option Types
+#
+# Each option definition includes an option type,
+# which controls whether the option takes an argument.
+#
+# File <tt>types.rb</tt>:
+#
+# :include: ../sample/getoptlong/types.rb
+#
+# Note that an option type has to do with the <em>option argument</em>
+# (whether it is required, optional, or forbidden),
+# not with whether the option itself is required.
+#
+# ==== Option with Required Argument
+#
+# An option of type <tt>GetoptLong::REQUIRED_ARGUMENT</tt>
+# must be followed by an argument, which is associated with that option:
+#
+# $ ruby types.rb --xxx foo
+#
+# Output:
+#
+# ["--xxx", "foo"]
+#
+# If the option is not last, its argument is whatever follows it
+# (even if the argument looks like another option):
+#
+# $ ruby types.rb --xxx --yyy
+#
+# Output:
+#
+# ["--xxx", "--yyy"]
+#
+# If the option is last, an exception is raised:
+#
+# $ ruby types.rb
+# # Raises GetoptLong::MissingArgument
+#
+# ==== Option with Optional Argument
+#
+# An option of type <tt>GetoptLong::OPTIONAL_ARGUMENT</tt>
+# may be followed by an argument, which if given is associated with that option.
+#
+# If the option is last, it does not have an argument:
+#
+# $ ruby types.rb --yyy
+#
+# Output:
+#
+# ["--yyy", ""]
+#
+# If the option is followed by another option, it does not have an argument:
+#
+# $ ruby types.rb --yyy --zzz
+#
+# Output:
+#
+# ["--yyy", ""]
+# ["--zzz", ""]
+#
+# Otherwise the option is followed by its argument, which is associated
+# with that option:
+#
+# $ ruby types.rb --yyy foo
+#
+# Output:
+#
+# ["--yyy", "foo"]
+#
+# ==== Option with No Argument
+#
+# An option of type <tt>GetoptLong::NO_ARGUMENT</tt> takes no argument:
+#
+# ruby types.rb --zzz foo
+#
+# Output:
+#
+# ["--zzz", ""]
+#
+# === ARGV
+#
+# You can process options either with method #each and a block,
+# or with method #get.
+#
+# During processing, each found option is removed, along with its argument
+# if there is one.
+# After processing, each remaining element was neither an option
+# nor the argument for an option.
+#
+# File <tt>argv.rb</tt>:
+#
+# :include: ../sample/getoptlong/argv.rb
+#
+# Command line:
#
-# GetoptLong allows for POSIX-style options like <tt>--file</tt> as well
-# as single letter options like <tt>-f</tt>
+# $ ruby argv.rb --xxx Foo --yyy Bar Baz --zzz Bat Bam
#
-# The empty option <tt>--</tt> (two minus symbols) is used to end option
-# processing. This can be particularly important if options have optional
-# arguments.
+# Output:
#
-# Here is a simple example of usage:
+# Original ARGV: ["--xxx", "Foo", "--yyy", "Bar", "Baz", "--zzz", "Bat", "Bam"]
+# ["--xxx", "Foo"]
+# ["--yyy", "Bar"]
+# ["--zzz", ""]
+# Remaining ARGV: ["Baz", "Bat", "Bam"]
#
-# require 'getoptlong'
+# === Ordering
#
-# opts = GetoptLong.new(
-# [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
-# [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
-# [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
-# )
+# There are three settings that control the way the options
+# are interpreted:
#
-# dir = nil
-# name = nil
-# repetitions = 1
-# opts.each do |opt, arg|
-# case opt
-# when '--help'
-# puts <<-EOF
-# hello [OPTION] ... DIR
+# - +PERMUTE+.
+# - +REQUIRE_ORDER+.
+# - +RETURN_IN_ORDER+.
#
+# The initial setting for a new \GetoptLong object is +REQUIRE_ORDER+
+# if environment variable +POSIXLY_CORRECT+ is defined, +PERMUTE+ otherwise.
+#
+# ==== PERMUTE Ordering
+#
+# In the +PERMUTE+ ordering, options and other, non-option,
+# arguments may appear in any order and any mixture.
+#
+# File <tt>permute.rb</tt>:
+#
+# :include: ../sample/getoptlong/permute.rb
+#
+# Command line:
+#
+# $ ruby permute.rb Foo --zzz Bar --xxx Baz --yyy Bat Bam --xxx Bag Bah
+#
+# Output:
+#
+# Original ARGV: ["Foo", "--zzz", "Bar", "--xxx", "Baz", "--yyy", "Bat", "Bam", "--xxx", "Bag", "Bah"]
+# ["--zzz", ""]
+# ["--xxx", "Baz"]
+# ["--yyy", "Bat"]
+# ["--xxx", "Bag"]
+# Remaining ARGV: ["Foo", "Bar", "Bam", "Bah"]
+#
+# ==== REQUIRE_ORDER Ordering
+#
+# In the +REQUIRE_ORDER+ ordering, all options precede all non-options;
+# that is, each word after the first non-option word
+# is treated as a non-option word (even if it begins with a hyphen).
+#
+# File <tt>require_order.rb</tt>:
+#
+# :include: ../sample/getoptlong/require_order.rb
+#
+# Command line:
+#
+# $ ruby require_order.rb --xxx Foo Bar --xxx Baz --yyy Bat -zzz
+#
+# Output:
+#
+# Original ARGV: ["--xxx", "Foo", "Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"]
+# ["--xxx", "Foo"]
+# Remaining ARGV: ["Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"]
+#
+# ==== RETURN_IN_ORDER Ordering
+#
+# In the +RETURN_IN_ORDER+ ordering, every word is treated as an option.
+# A word that begins with a hyphen (or two) is treated in the usual way;
+# a word +word+ that does not so begin is treated as an option
+# whose name is an empty string, and whose value is +word+.
+#
+# File <tt>return_in_order.rb</tt>:
+#
+# :include: ../sample/getoptlong/return_in_order.rb
+#
+# Command line:
+#
+# $ ruby return_in_order.rb Foo --xxx Bar Baz --zzz Bat Bam
+#
+# Output:
+#
+# Original ARGV: ["Foo", "--xxx", "Bar", "Baz", "--zzz", "Bat", "Bam"]
+# ["", "Foo"]
+# ["--xxx", "Bar"]
+# ["", "Baz"]
+# ["--zzz", ""]
+# ["", "Bat"]
+# ["", "Bam"]
+# Remaining ARGV: []
+#
+# === Full Example
+#
+# File <tt>fibonacci.rb</tt>:
+#
+# :include: ../sample/getoptlong/fibonacci.rb
+#
+# Command line:
+#
+# $ ruby fibonacci.rb
+#
+# Output:
+#
+# Option --number is required.
+# Usage:
+#
+# -n n, --number n:
+# Compute Fibonacci number for n.
+# -v [boolean], --verbose [boolean]:
+# Show intermediate results; default is 'false'.
+# -h, --help:
+# Show this help.
+#
+# Command line:
+#
+# $ ruby fibonacci.rb --number
+#
+# Raises GetoptLong::MissingArgument:
+#
+# fibonacci.rb: option `--number' requires an argument
+#
+# Command line:
+#
+# $ ruby fibonacci.rb --number 6
+#
+# Output:
+#
+# 8
+#
+# Command line:
+#
+# $ ruby fibonacci.rb --number 6 --verbose
+#
+# Output:
+# 1
+# 2
+# 3
+# 5
+# 8
+#
+# Command line:
+#
+# $ ruby fibonacci.rb --number 6 --verbose yes
+#
+# Output:
+#
+# --verbose argument must be true or false
+# Usage:
+#
+# -n n, --number n:
+# Compute Fibonacci number for n.
+# -v [boolean], --verbose [boolean]:
+# Show intermediate results; default is 'false'.
# -h, --help:
-# show help
-#
-# --repeat x, -n x:
-# repeat x times
-#
-# --name [name]:
-# greet user by name, if name not supplied default is John
-#
-# DIR: The directory in which to issue the greeting.
-# EOF
-# when '--repeat'
-# repetitions = arg.to_i
-# when '--name'
-# if arg == ''
-# name = 'John'
-# else
-# name = arg
-# end
-# end
-# end
-#
-# if ARGV.length != 1
-# puts "Missing dir argument (try --help)"
-# exit 0
-# end
-#
-# dir = ARGV.shift
-#
-# Dir.chdir(dir)
-# for i in (1..repetitions)
-# print "Hello"
-# if name
-# print ", #{name}"
-# end
-# puts
-# end
-#
-# Example command line:
-#
-# hello -n 6 --name -- /tmp
+# Show this help.
#
class GetoptLong
# Version.
- VERSION = "0.1.1"
+ VERSION = "0.2.0"
#
# Orderings.
@@ -114,20 +396,18 @@ class GetoptLong
class InvalidOption < Error; end
#
- # \Set up option processing.
- #
- # The options to support are passed to new() as an array of arrays.
- # Each sub-array contains any number of String option names which carry
- # the same meaning, and one of the following flags:
+ # Returns a new \GetoptLong object based on the given +arguments+.
+ # See {Options}[#class-GetoptLong-label-Options].
#
- # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
+ # Example:
#
- # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
+ # :include: ../sample/getoptlong/simple.rb
#
- # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
+ # Raises an exception if:
#
- # The first option name is considered to be the preferred (canonical) name.
- # Other than that, the elements of each sub-array can be in any order.
+ # - Any of +arguments+ is not an array.
+ # - Any option name or alias is not a string.
+ # - Any option type is invalid.
#
def initialize(*arguments)
#
@@ -189,54 +469,22 @@ class GetoptLong
end
end
+ # Sets the ordering; see {Ordering}[#class-GetoptLong-label-Ordering];
+ # returns the new ordering.
#
- # \Set the handling of the ordering of options and arguments.
- # A RuntimeError is raised if option processing has already started.
- #
- # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
- # the processing of options as follows:
- #
- # <b>REQUIRE_ORDER</b> :
- #
- # Options are required to occur before non-options.
- #
- # Processing of options ends as soon as a word is encountered that has not
- # been preceded by an appropriate option flag.
- #
- # For example, if -a and -b are options which do not take arguments,
- # parsing command line arguments of '-a one -b two' would result in
- # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being
- # processed as an option/arg pair.
- #
- # This is the default ordering, if the environment variable
- # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
- #
- # <b>PERMUTE</b> :
- #
- # Options can occur anywhere in the command line parsed. This is the
- # default behavior.
- #
- # Every sequence of words which can be interpreted as an option (with or
- # without argument) is treated as an option; non-option words are skipped.
- #
- # For example, if -a does not require an argument and -b optionally takes
- # an argument, parsing '-a one -b two three' would result in ('-a','') and
- # ('-b', 'two') being processed as option/arg pairs, and 'one','three'
- # being left in ARGV.
+ # If the given +ordering+ is +PERMUTE+ and environment variable
+ # +POSIXLY_CORRECT+ is defined, sets the ordering to +REQUIRE_ORDER+;
+ # otherwise sets the ordering to +ordering+:
#
- # If the ordering is set to PERMUTE but the environment variable
- # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for
- # compatibility with GNU getopt_long.
+ # options = GetoptLong.new
+ # options.ordering == GetoptLong::PERMUTE # => true
+ # options.ordering = GetoptLong::RETURN_IN_ORDER
+ # options.ordering == GetoptLong::RETURN_IN_ORDER # => true
+ # ENV['POSIXLY_CORRECT'] = 'true'
+ # options.ordering = GetoptLong::PERMUTE
+ # options.ordering == GetoptLong::REQUIRE_ORDER # => true
#
- # <b>RETURN_IN_ORDER</b> :
- #
- # All words on the command line are processed as options. Words not
- # preceded by a short or long option flag are passed as arguments
- # with an option of '' (empty string).
- #
- # For example, if -a requires an argument but -b does not, a command line
- # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one')
- # ('-b', ''), ('', 'two'), ('', 'three') being processed.
+ # Raises an exception if +ordering+ is invalid.
#
def ordering=(ordering)
#
@@ -262,14 +510,16 @@ class GetoptLong
end
#
- # Return ordering.
+ # Returns the ordering setting.
#
attr_reader :ordering
#
- # \Set options. Takes the same argument as GetoptLong.new.
+ # Replaces existing options with those given by +arguments+,
+ # which have the same form as the arguments to ::new;
+ # returns +self+.
#
- # Raises a RuntimeError if option processing has already started.
+ # Raises an exception if option processing has begun.
#
def set_options(*arguments)
#
@@ -341,22 +591,23 @@ class GetoptLong
end
#
- # \Set/Unset `quiet' mode.
+ # Sets quiet mode and returns the given argument:
+ #
+ # - When +false+ or +nil+, error messages are written to <tt>$stdout</tt>.
+ # - Otherwise, error messages are not written.
#
attr_writer :quiet
#
- # Return the flag of `quiet' mode.
+ # Returns the quiet mode setting.
#
attr_reader :quiet
-
- #
- # `quiet?' is an alias of `quiet'.
- #
alias quiet? quiet
#
- # Explicitly terminate option processing.
+ # Terminate option processing;
+ # returns +nil+ if processing has already terminated;
+ # otherwise returns +self+.
#
def terminate
return nil if @status == STATUS_TERMINATED
@@ -376,7 +627,7 @@ class GetoptLong
end
#
- # Returns true if option processing has terminated, false otherwise.
+ # Returns +true+ if option processing has terminated, +false+ otherwise.
#
def terminated?
return @status == STATUS_TERMINATED
@@ -400,32 +651,25 @@ class GetoptLong
protected :set_error
#
- # Examine whether an option processing is failed.
+ # Returns whether option processing has failed.
#
attr_reader :error
-
- #
- # `error?' is an alias of `error'.
- #
alias error? error
# Return the appropriate error message in POSIX-defined format.
- # If no error has occurred, returns nil.
+ # If no error has occurred, returns +nil+.
#
def error_message
return @error_message
end
#
- # Get next option name and its argument, as an Array of two elements.
- #
- # The option name is always converted to the first (preferred)
- # name given in the original options to GetoptLong.new.
+ # Returns the next option as a 2-element array containing:
#
- # Example: ['--option', 'value']
+ # - The option name (the name itself, not an alias).
+ # - The option value.
#
- # Returns nil if the processing is complete (as determined by
- # STATUS_TERMINATED).
+ # Returns +nil+ if there are no more options.
#
def get
option_name, option_argument = nil, ''
@@ -585,21 +829,32 @@ class GetoptLong
return @canonical_names[option_name], option_argument
end
+ alias get_option get
#
- # `get_option' is an alias of `get'.
+ # Calls the given block with each option;
+ # each option is a 2-element array containing:
#
- alias get_option get
-
- # Iterator version of `get'.
+ # - The option name (the name itself, not an alias).
+ # - The option value.
+ #
+ # Example:
+ #
+ # :include: ../sample/getoptlong/each.rb
#
- # The block is called repeatedly with two arguments:
- # The first is the option name.
- # The second is the argument which followed it (if any).
- # Example: ('--opt', 'value')
+ # Command line:
#
- # The option name is always converted to the first (preferred)
- # name given in the original options to GetoptLong.new.
+ # ruby each.rb -xxx Foo -x Bar --yyy Baz -y Bat --zzz
+ #
+ # Output:
+ #
+ # Original ARGV: ["-xxx", "Foo", "-x", "Bar", "--yyy", "Baz", "-y", "Bat", "--zzz"]
+ # ["--xxx", "xx"]
+ # ["--xxx", "Bar"]
+ # ["--yyy", "Baz"]
+ # ["--yyy", "Bat"]
+ # ["--zzz", ""]
+ # Remaining ARGV: ["Foo"]
#
def each
loop do
@@ -608,9 +863,5 @@ class GetoptLong
yield option_name, option_argument
end
end
-
- #
- # `each_option' is an alias of `each'.
- #
alias each_option each
end
diff --git a/lib/ipaddr.gemspec b/lib/ipaddr.gemspec
index 5187f3be11..1f4798e43a 100644
--- a/lib/ipaddr.gemspec
+++ b/lib/ipaddr.gemspec
@@ -1,11 +1,23 @@
# frozen_string_literal: true
# coding: utf-8
-lib = File.expand_path("../lib", __FILE__)
-$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+
+if File.exist?(File.expand_path("ipaddr.gemspec"))
+ lib = File.expand_path("../lib", __FILE__)
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+
+ file = File.expand_path("ipaddr.rb", lib)
+else
+ # for ruby-core
+ file = File.expand_path("../ipaddr.rb", __FILE__)
+end
+
+version = File.foreach(file).find do |line|
+ /^\s*VERSION\s*=\s*["'](.*)["']/ =~ line and break $1
+end
Gem::Specification.new do |spec|
spec.name = "ipaddr"
- spec.version = "1.2.2"
+ spec.version = version
spec.authors = ["Akinori MUSHA", "Hajimu UMEMOTO"]
spec.email = ["knu@idaemons.org", "ume@mahoroba.org"]
diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb
index 7fff54b9d0..7a5cf94830 100644
--- a/lib/ipaddr.rb
+++ b/lib/ipaddr.rb
@@ -40,13 +40,14 @@ require 'socket'
# p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
class IPAddr
+ VERSION = "1.2.5"
# 32 bit mask for IPv4
IN4MASK = 0xffffffff
# 128 bit mask for IPv6
IN6MASK = 0xffffffffffffffffffffffffffffffff
# Format string for IPv6
- IN6FORMAT = (["%.4x"] * 8).join(':')
+ IN6FORMAT = (["%.4x"] * 8).join(':').freeze
# Regexp _internally_ used for parsing IPv4 address.
RE_IPV4ADDRLIKE = %r{
@@ -112,13 +113,12 @@ class IPAddr
def self.ntop(addr)
case addr.size
when 4
- s = addr.unpack('C4').join('.')
+ addr.unpack('C4').join('.')
when 16
- s = IN6FORMAT % addr.unpack('n8')
+ IN6FORMAT % addr.unpack('n8')
else
raise AddressFamilyError, "unsupported address family"
end
- return s
end
# Returns a new ipaddr built by bitwise AND.
@@ -168,34 +168,17 @@ class IPAddr
# net1 = IPAddr.new("192.168.2.0/24")
# net2 = IPAddr.new("192.168.2.100")
# net3 = IPAddr.new("192.168.3.0")
+ # net4 = IPAddr.new("192.168.2.0/16")
# p net1.include?(net2) #=> true
# p net1.include?(net3) #=> false
+ # p net1.include?(net4) #=> false
+ # p net4.include?(net1) #=> true
def include?(other)
other = coerce_other(other)
- if ipv4_mapped?
- if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
- return false
- end
- mask_addr = (@mask_addr & IN4MASK)
- addr = (@addr & IN4MASK)
- family = Socket::AF_INET
- else
- mask_addr = @mask_addr
- addr = @addr
- family = @family
- end
- if other.ipv4_mapped?
- other_addr = (other.to_i & IN4MASK)
- other_family = Socket::AF_INET
- else
- other_addr = other.to_i
- other_family = other.family
- end
-
- if family != other_family
- return false
- end
- return ((addr & mask_addr) == (other_addr & mask_addr))
+ return false unless other.family == family
+ range = to_range
+ other = other.to_range
+ range.begin <= other.begin && range.end >= other.end
end
alias === include?
@@ -232,7 +215,13 @@ class IPAddr
# Returns a string containing the IP address representation in
# canonical form.
def to_string
- return _to_string(@addr)
+ str = _to_string(@addr)
+
+ if @family == Socket::AF_INET6
+ str << zone_id.to_s
+ end
+
+ return str
end
# Returns a network byte ordered string form of the IP address.
@@ -328,9 +317,11 @@ class IPAddr
# into an IPv4-mapped IPv6 address.
def ipv4_mapped
if !ipv4?
- raise InvalidAddressError, "not an IPv4 address"
+ raise InvalidAddressError, "not an IPv4 address: #{@addr}"
end
- return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
+ clone = self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
+ clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000)
+ clone
end
# Returns a new ipaddr built by converting the native IPv4 address
@@ -338,7 +329,7 @@ class IPAddr
def ipv4_compat
warn "IPAddr\##{__callee__} is obsolete", uplevel: 1 if $VERBOSE
if !ipv4?
- raise InvalidAddressError, "not an IPv4 address"
+ raise InvalidAddressError, "not an IPv4 address: #{@addr}"
end
return self.clone.set(@addr, Socket::AF_INET6)
end
@@ -369,7 +360,7 @@ class IPAddr
# Returns a string for DNS reverse lookup compatible with RFC3172.
def ip6_arpa
if !ipv6?
- raise InvalidAddressError, "not an IPv6 address"
+ raise InvalidAddressError, "not an IPv6 address: #{@addr}"
end
return _reverse + ".ip6.arpa"
end
@@ -377,7 +368,7 @@ class IPAddr
# Returns a string for DNS reverse lookup compatible with RFC1886.
def ip6_int
if !ipv6?
- raise InvalidAddressError, "not an IPv6 address"
+ raise InvalidAddressError, "not an IPv6 address: #{@addr}"
end
return _reverse + ".ip6.int"
end
@@ -404,7 +395,7 @@ class IPAddr
# Returns a hash value used by Hash, Set, and Array classes
def hash
- return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1)
+ return ([@addr, @mask_addr, @zone_id].hash << 1) | (ipv4? ? 0 : 1)
end
# Creates a Range object for the network address.
@@ -420,7 +411,7 @@ class IPAddr
raise AddressFamilyError, "unsupported address family"
end
- return clone.set(begin_addr, @family)..clone.set(end_addr, @family)
+ self.class.new(begin_addr, @family)..self.class.new(end_addr, @family)
end
# Returns the prefix length in bits for the ipaddr.
@@ -448,7 +439,7 @@ class IPAddr
when Integer
mask!(prefix)
else
- raise InvalidPrefixError, "prefix must be an integer"
+ raise InvalidPrefixError, "prefix must be an integer: #{@addr}"
end
end
@@ -460,11 +451,42 @@ class IPAddr
af = "IPv4"
when Socket::AF_INET6
af = "IPv6"
+ zone_id = @zone_id.to_s
else
raise AddressFamilyError, "unsupported address family"
end
- return sprintf("#<%s: %s:%s/%s>", self.class.name,
- af, _to_string(@addr), _to_string(@mask_addr))
+ return sprintf("#<%s: %s:%s%s/%s>", self.class.name,
+ af, _to_string(@addr), zone_id, _to_string(@mask_addr))
+ end
+
+ # Returns the netmask in string format e.g. 255.255.0.0
+ def netmask
+ _to_string(@mask_addr)
+ end
+
+ # Returns the IPv6 zone identifier, if present.
+ # Raises InvalidAddressError if not an IPv6 address.
+ def zone_id
+ if @family == Socket::AF_INET6
+ @zone_id
+ else
+ raise InvalidAddressError, "not an IPv6 address"
+ end
+ end
+
+ # Returns the IPv6 zone identifier, if present.
+ # Raises InvalidAddressError if not an IPv6 address.
+ def zone_id=(zid)
+ if @family == Socket::AF_INET6
+ case zid
+ when nil, /\A%(\w+)\z/
+ @zone_id = zid
+ else
+ raise InvalidAddressError, "invalid zone identifier for address"
+ end
+ else
+ raise InvalidAddressError, "not an IPv6 address"
+ end
end
protected
@@ -476,11 +498,11 @@ class IPAddr
case family[0] ? family[0] : @family
when Socket::AF_INET
if addr < 0 || addr > IN4MASK
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
end
when Socket::AF_INET6
if addr < 0 || addr > IN6MASK
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
end
else
raise AddressFamilyError, "unsupported address family"
@@ -488,6 +510,9 @@ class IPAddr
@addr = addr
if family[0]
@family = family[0]
+ if @family == Socket::AF_INET
+ @mask_addr &= IN4MASK
+ end
end
return self
end
@@ -496,17 +521,20 @@ class IPAddr
def mask!(mask)
case mask
when String
- if mask =~ /\A\d+\z/
+ case mask
+ when /\A(0|[1-9]+\d*)\z/
prefixlen = mask.to_i
+ when /\A\d+\z/
+ raise InvalidPrefixError, "leading zeros in prefix"
else
m = IPAddr.new(mask)
if m.family != @family
- raise InvalidPrefixError, "address family is not same"
+ raise InvalidPrefixError, "address family is not same: #{@addr}"
end
@mask_addr = m.to_i
n = @mask_addr ^ m.instance_variable_get(:@mask_addr)
unless ((n + 1) & n).zero?
- raise InvalidPrefixError, "invalid mask #{mask}"
+ raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}"
end
@addr &= @mask_addr
return self
@@ -517,13 +545,13 @@ class IPAddr
case @family
when Socket::AF_INET
if prefixlen < 0 || prefixlen > 32
- raise InvalidPrefixError, "invalid length"
+ raise InvalidPrefixError, "invalid length: #{@addr}"
end
masklen = 32 - prefixlen
@mask_addr = ((IN4MASK >> masklen) << masklen)
when Socket::AF_INET6
if prefixlen < 0 || prefixlen > 128
- raise InvalidPrefixError, "invalid length"
+ raise InvalidPrefixError, "invalid length: #{@addr}"
end
masklen = 128 - prefixlen
@mask_addr = ((IN6MASK >> masklen) << masklen)
@@ -555,6 +583,7 @@ class IPAddr
# those, such as &, |, include? and ==, accept a string, or a packed
# in_addr value instead of an IPAddr object.
def initialize(addr = '::', family = Socket::AF_UNSPEC)
+ @mask_addr = nil
if !addr.kind_of?(String)
case family
when Socket::AF_INET, Socket::AF_INET6
@@ -567,11 +596,16 @@ class IPAddr
raise AddressFamilyError, "unsupported address family: #{family}"
end
end
- prefix, prefixlen = addr.split('/')
+ prefix, prefixlen = addr.split('/', 2)
if prefix =~ /\A\[(.*)\]\z/i
prefix = $1
family = Socket::AF_INET6
end
+ if prefix =~ /\A(.*)(%\w+)\z/
+ prefix = $1
+ zone_id = $2
+ family = Socket::AF_INET6
+ end
# It seems AI_NUMERICHOST doesn't do the job.
#Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
# Socket::AI_NUMERICHOST)
@@ -586,6 +620,7 @@ class IPAddr
@addr = in6_addr(prefix)
@family = Socket::AF_INET6
end
+ @zone_id = zone_id
if family != Socket::AF_UNSPEC && @family != family
raise AddressFamilyError, "address family mismatch"
end
@@ -594,8 +629,6 @@ class IPAddr
else
@mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK
end
- rescue InvalidAddressError => e
- raise e.class, "#{e.message}: #{addr}"
end
def coerce_other(other)
@@ -618,8 +651,8 @@ class IPAddr
octets = m.captures
end
octets.inject(0) { |i, s|
- (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address"
- s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous"
+ (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
+ s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
i << 8 | n
}
end
@@ -636,19 +669,19 @@ class IPAddr
right = ''
when RE_IPV6ADDRLIKE_COMPRESSED
if $4
- left.count(':') <= 6 or raise InvalidAddressError, "invalid address"
+ left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{@addr}"
addr = in_addr($~[4,4])
left = $1
right = $3 + '0:0'
else
left.count(':') <= ($1.empty? || $2.empty? ? 8 : 7) or
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
left = $1
right = $2
addr = 0
end
else
- raise InvalidAddressError, "invalid address"
+ raise InvalidAddressError, "invalid address: #{@addr}"
end
l = left.split(':')
r = right.split(':')
@@ -703,7 +736,7 @@ end
unless Socket.const_defined? :AF_INET6
class Socket < BasicSocket
# IPv6 protocol family
- AF_INET6 = Object.new
+ AF_INET6 = Object.new.freeze
end
class << IPSocket
diff --git a/lib/irb.rb b/lib/irb.rb
index 661c550486..2db99bcd43 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -51,52 +51,63 @@ require_relative "irb/easter-egg"
#
# == Command line options
#
-# Usage: irb.rb [options] [programfile] [arguments]
-# -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
-# -U Same as `ruby -U`
-# -E enc Same as `ruby -E`
-# -w Same as `ruby -w`
-# -W[level=2] Same as `ruby -W`
-# --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
-# --singleline Use singleline editor module
-# --nosingleline Don't use singleline editor module
-# --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'
-# --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
-# Suppresses --multiline and --singleline.
-# --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.
-# --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
+# :include: ./irb/lc/help-message
+#
+# == Commands
+#
+# The following commands are available on IRB.
+#
+# * cwws
+# * Show the current workspace.
+# * cb, cws, chws
+# * Change the current workspace to an object.
+# * bindings, workspaces
+# * Show workspaces.
+# * pushb, pushws
+# * Push an object to the workspace stack.
+# * popb, popws
+# * Pop a workspace from the workspace stack.
+# * load
+# * Load a Ruby file.
+# * require
+# * Require a Ruby file.
+# * source
+# * Loads a given file in the current session.
+# * irb
+# * Start a child IRB.
+# * jobs
+# * List of current sessions.
+# * fg
+# * Switches to the session of the given number.
+# * kill
+# * Kills the session with the given number.
+# * help
+# * Enter the mode to look up RI documents.
+# * irb_info
+# * Show information about IRB.
+# * ls
+# * Show methods, constants, and variables.
+# -g [query] or -G [query] allows you to filter out the output.
+# * measure
+# * measure enables the mode to measure processing time. measure :off disables it.
+# * $, show_source
+# * Show the source code of a given method or constant.
+# * @, whereami
+# * Show the source code around binding.irb again.
+# * debug
+# * Start the debugger of debug.gem.
+# * break, delete, next, step, continue, finish, backtrace, info, catch
+# * Start the debugger of debug.gem and run the command on it.
#
# == Configuration
#
-# IRB reads from <code>~/.irbrc</code> when it's invoked.
-#
-# If <code>~/.irbrc</code> doesn't exist, +irb+ will try to read in the following order:
+# IRB reads a personal initialization file when it's invoked.
+# IRB searches a file in the following order and loads the first one found.
#
+# * <tt>$IRBRC</tt> (if <tt>$IRBRC</tt> is set)
+# * <tt>$XDG_CONFIG_HOME/irb/irbrc</tt> (if <tt>$XDG_CONFIG_HOME</tt> is set)
+# * <tt>~/.irbrc</tt>
+# * +.config/irb/irbrc+
# * +.irbrc+
# * +irb.rc+
# * +_irbrc+
@@ -114,6 +125,7 @@ require_relative "irb/easter-egg"
# IRB.conf[:USE_SINGLELINE] = nil
# IRB.conf[:USE_COLORIZE] = true
# IRB.conf[:USE_TRACER] = false
+# IRB.conf[:USE_AUTOCOMPLETE] = true
# IRB.conf[:IGNORE_SIGINT] = true
# IRB.conf[:IGNORE_EOF] = false
# IRB.conf[:PROMPT_MODE] = :DEFAULT
@@ -127,9 +139,9 @@ require_relative "irb/easter-egg"
#
# === Autocompletion
#
-# To enable autocompletion for irb, add the following to your +.irbrc+:
+# To disable autocompletion for irb, add the following to your +.irbrc+:
#
-# require 'irb/completion'
+# IRB.conf[:USE_AUTOCOMPLETE] = false
#
# === History
#
@@ -423,11 +435,7 @@ module IRB
#
# Will raise an Abort exception, or the given +exception+.
def IRB.irb_abort(irb, exception = Abort)
- if defined? Thread
- irb.context.thread.raise exception, "abort then interrupt!"
- else
- raise exception, "abort then interrupt!"
- end
+ irb.context.thread.raise exception, "abort then interrupt!"
end
class Irb
@@ -468,6 +476,17 @@ module IRB
@scanner = RubyLex.new
end
+ # A hook point for `debug` command's TracePoint after :IRB_EXIT as well as its clean-up
+ def debug_break
+ # it means the debug command is executed
+ if defined?(DEBUGGER__) && DEBUGGER__.respond_to?(:capture_frames_without_irb)
+ # after leaving this initial breakpoint, revert the capture_frames patch
+ DEBUGGER__.singleton_class.send(:alias_method, :capture_frames, :capture_frames_without_irb)
+ # and remove the redundant method
+ DEBUGGER__.singleton_class.send(:undef_method, :capture_frames_without_irb)
+ end
+ end
+
def run(conf = IRB.conf)
conf[:IRB_RC].call(context) if conf[:IRB_RC]
conf[:MAIN_CONTEXT] = context
@@ -544,13 +563,15 @@ module IRB
@scanner.set_auto_indent(@context) if @context.auto_indent_mode
- @scanner.each_top_level_statement do |line, line_no|
+ @scanner.each_top_level_statement(@context) do |line, line_no|
signal_status(:IN_EVAL) do
begin
line.untaint if RUBY_VERSION < '2.7'
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
IRB.set_measure_callback
end
+ # Assignment expression check should be done before @context.evaluate to handle code like `a /2#/ if false; a = 1`
+ is_assignment = assignment_expression?(line)
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
result = nil
last_proc = proc{ result = @context.evaluate(line, line_no, exception: exc) }
@@ -567,7 +588,7 @@ module IRB
@context.evaluate(line, line_no, exception: exc)
end
if @context.echo?
- if assignment_expression?(line)
+ if is_assignment
if @context.echo_on_assignment?
output_value(@context.echo_on_assignment? == :truncate)
end
@@ -604,7 +625,7 @@ module IRB
ret = conv.primitive_convert(str, dst)
case ret
when :invalid_byte_sequence
- conv.insert_output(conf.primitive_errinfo[3].dump[1..-2])
+ conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
redo
when :undefined_conversion
c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
@@ -630,11 +651,7 @@ module IRB
if exc.backtrace
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 RUBY_VERSION < '3.0.0'
if STDOUT.tty?
message = exc.full_message(order: :bottom)
order = :bottom
@@ -666,6 +683,8 @@ module IRB
lines = lines.reverse if order == :bottom
lines.map{ |l| l + "\n" }.join
}
+ # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
+ message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
puts message
end
print "Maybe IRB bug!\n" if irb_bug
@@ -812,17 +831,20 @@ module IRB
diff_size = output_width - Reline::Unicode.calculate_width(first_line, true)
if diff_size.positive? and output_width > winwidth
lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3)
- str = "%s...\e[0m" % lines.first
+ str = "%s..." % lines.first
+ str += "\e[0m" if Color.colorable?
multiline_p = false
else
str = str.gsub(/(\A.*?\n).*/m, "\\1...")
+ str += "\e[0m" if Color.colorable?
end
else
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
diff_size = output_width - Reline::Unicode.calculate_width(str, true)
if diff_size.positive? and output_width > winwidth
lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
- str = "%s...\e[0m" % lines.first
+ str = "%s..." % lines.first
+ str += "\e[0m" if Color.colorable?
end
end
end
@@ -856,13 +878,16 @@ module IRB
# If the expression is invalid, Ripper.sexp should return nil which will
# result in false being returned. Any valid expression should return an
- # s-expression where the second selement of the top level array is an
+ # s-expression where the second element of the top level array is an
# array of parsed expressions. The first element of each expression is the
# expression's type.
verbose, $VERBOSE = $VERBOSE, nil
- result = ASSIGNMENT_NODE_TYPES.include?(Ripper.sexp(line)&.dig(1,-1,0))
+ code = "#{RubyLex.generate_local_variables_assign_code(@context.local_variables) || 'nil;'}\n#{line}"
+ # Get the last node_type of the line. drop(1) is to ignore the local_variables_assign_code part.
+ node_type = Ripper.sexp(code)&.dig(1)&.drop(1)&.dig(-1, 0)
+ ASSIGNMENT_NODE_TYPES.include?(node_type)
+ ensure
$VERBOSE = verbose
- result
end
ATTR_TTY = "\e[%sm"
@@ -952,12 +977,13 @@ class Binding
#
#
# See IRB@IRB+Usage for more information.
- def irb
+ def irb(show_code: true)
IRB.setup(source_location[0], argv: [])
workspace = IRB::WorkSpace.new(self)
- STDOUT.print(workspace.code_around_binding)
+ STDOUT.print(workspace.code_around_binding) if show_code
binding_irb = IRB::Irb.new(workspace)
binding_irb.context.irb_path = File.expand_path(source_location[0])
binding_irb.run(IRB.conf)
+ binding_irb.debug_break
end
end
diff --git a/lib/irb/cmd/backtrace.rb b/lib/irb/cmd/backtrace.rb
new file mode 100644
index 0000000000..f632894618
--- /dev/null
+++ b/lib/irb/cmd/backtrace.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Backtrace < DebugCommand
+ def self.transform_args(args)
+ args&.dump
+ end
+
+ def execute(*args)
+ super(pre_cmds: ["backtrace", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/break.rb b/lib/irb/cmd/break.rb
new file mode 100644
index 0000000000..df259a90ca
--- /dev/null
+++ b/lib/irb/cmd/break.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Break < DebugCommand
+ def self.transform_args(args)
+ args&.dump
+ end
+
+ def execute(args = nil)
+ super(pre_cmds: "break #{args}")
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/catch.rb b/lib/irb/cmd/catch.rb
new file mode 100644
index 0000000000..40b62c7533
--- /dev/null
+++ b/lib/irb/cmd/catch.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Catch < DebugCommand
+ def self.transform_args(args)
+ args&.dump
+ end
+
+ def execute(*args)
+ super(pre_cmds: ["catch", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/chws.rb b/lib/irb/cmd/chws.rb
index e9f257791c..7c84ba0a4b 100644
--- a/lib/irb/cmd/chws.rb
+++ b/lib/irb/cmd/chws.rb
@@ -13,22 +13,30 @@
require_relative "nop"
require_relative "../ext/change-ws"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class CurrentWorkingWorkspace < Nop
+ category "IRB"
+ description "Show the current workspace."
+
def execute(*obj)
irb_context.main
end
end
class ChangeWorkspace < Nop
+ category "IRB"
+ description "Change the current workspace to an object."
+
def execute(*obj)
irb_context.change_workspace(*obj)
irb_context.main
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/continue.rb b/lib/irb/cmd/continue.rb
new file mode 100644
index 0000000000..9136177eef
--- /dev/null
+++ b/lib/irb/cmd/continue.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Continue < DebugCommand
+ def execute(*args)
+ super(do_cmds: ["continue", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/debug.rb b/lib/irb/cmd/debug.rb
new file mode 100644
index 0000000000..7d39b9fa27
--- /dev/null
+++ b/lib/irb/cmd/debug.rb
@@ -0,0 +1,136 @@
+require_relative "nop"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Debug < Nop
+ category "Debugging"
+ description "Start the debugger of debug.gem."
+
+ BINDING_IRB_FRAME_REGEXPS = [
+ '<internal:prelude>',
+ binding.method(:irb).source_location.first,
+ ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
+ IRB_DIR = File.expand_path('..', __dir__)
+
+ def execute(pre_cmds: nil, do_cmds: nil)
+ unless binding_irb?
+ puts "`debug` command is only available when IRB is started with binding.irb"
+ return
+ end
+
+ unless setup_debugger
+ puts <<~MSG
+ You need to install the debug gem before using this command.
+ If you use `bundle exec`, please add `gem "debug"` into your Gemfile.
+ MSG
+ return
+ end
+
+ options = { oneshot: true, hook_call: false }
+ if pre_cmds || do_cmds
+ options[:command] = ['irb', pre_cmds, do_cmds]
+ end
+ if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
+ options[:skip_src] = true
+ end
+
+ # To make debugger commands like `next` or `continue` work without asking
+ # the user to quit IRB after that, we need to exit IRB first and then hit
+ # a TracePoint on #debug_break.
+ file, lineno = IRB::Irb.instance_method(:debug_break).source_location
+ DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
+ # exit current Irb#run call
+ throw :IRB_EXIT
+ end
+
+ private
+
+ def binding_irb?
+ caller.any? do |frame|
+ BINDING_IRB_FRAME_REGEXPS.any? do |regexp|
+ frame.match?(regexp)
+ end
+ end
+ end
+
+ module SkipPathHelperForIRB
+ def skip_internal_path?(path)
+ # The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved
+ super || path.match?(IRB_DIR) || path.match?('<internal:prelude>')
+ end
+ end
+
+ def setup_debugger
+ unless defined?(DEBUGGER__::SESSION)
+ begin
+ require "debug/session"
+ rescue LoadError # debug.gem is not written in Gemfile
+ return false unless load_bundled_debug_gem
+ end
+ DEBUGGER__.start(nonstop: true)
+ end
+
+ unless DEBUGGER__.respond_to?(:capture_frames_without_irb)
+ DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames)
+
+ def DEBUGGER__.capture_frames(*args)
+ frames = capture_frames_without_irb(*args)
+ frames.reject! do |frame|
+ frame.realpath&.start_with?(IRB_DIR) || frame.path == "<internal:prelude>"
+ end
+ frames
+ end
+
+ DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
+ end
+
+ true
+ end
+
+ # This is used when debug.gem is not written in Gemfile. Even if it's not
+ # installed by `bundle install`, debug.gem is installed by default because
+ # it's a bundled gem. This method tries to activate and load that.
+ def load_bundled_debug_gem
+ # Discover latest debug.gem under GEM_PATH
+ debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path|
+ File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/)
+ end.sort_by do |path|
+ Gem::Version.new(File.basename(path).delete_prefix('debug-'))
+ end.last
+ return false unless debug_gem
+
+ # Discover debug/debug.so under extensions for Ruby 3.2+
+ ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}"
+ ext_path = Gem.paths.path.flat_map do |path|
+ Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}")
+ end.first
+
+ # Attempt to forcibly load the bundled gem
+ if ext_path
+ $LOAD_PATH << ext_path.delete_suffix(ext_name)
+ end
+ $LOAD_PATH << "#{debug_gem}/lib"
+ begin
+ require "debug/session"
+ puts "Loaded #{File.basename(debug_gem)}"
+ true
+ rescue LoadError
+ false
+ end
+ end
+ end
+
+ class DebugCommand < Debug
+ def self.category
+ "Debugging"
+ end
+
+ def self.description
+ command_name = self.name.split("::").last.downcase
+ "Start the debugger of debug.gem and run its `#{command_name}` command."
+ end
+ end
+ end
+end
diff --git a/lib/irb/cmd/delete.rb b/lib/irb/cmd/delete.rb
new file mode 100644
index 0000000000..aeb26d2572
--- /dev/null
+++ b/lib/irb/cmd/delete.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Delete < DebugCommand
+ def execute(*args)
+ super(pre_cmds: ["delete", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/edit.rb b/lib/irb/cmd/edit.rb
new file mode 100644
index 0000000000..0103891cf4
--- /dev/null
+++ b/lib/irb/cmd/edit.rb
@@ -0,0 +1,61 @@
+require 'shellwords'
+require_relative "nop"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Edit < Nop
+ category "Misc"
+ description 'Open a file with the editor command defined with `ENV["EDITOR"]`.'
+
+ class << self
+ def transform_args(args)
+ # Return a string literal as is for backward compatibility
+ if args.nil? || args.empty? || string_literal?(args)
+ args
+ else # Otherwise, consider the input as a String for convenience
+ args.strip.dump
+ end
+ end
+ end
+
+ def execute(*args)
+ path = args.first
+
+ if path.nil? && (irb_path = @irb_context.irb_path)
+ path = irb_path
+ end
+
+ if !File.exist?(path)
+ require_relative "show_source"
+
+ source =
+ begin
+ ShowSource.find_source(path, @irb_context)
+ rescue NameError
+ # if user enters a path that doesn't exist, it'll cause NameError when passed here because find_source would try to evaluate it as well
+ # in this case, we should just ignore the error
+ end
+
+ if source && File.exist?(source.file)
+ path = source.file
+ else
+ puts "Can not find file: #{path}"
+ return
+ end
+ end
+
+ if editor = ENV['EDITOR']
+ puts "command: '#{editor}'"
+ puts " path: #{path}"
+ system(*Shellwords.split(editor), path)
+ else
+ puts "Can not find editor setting: ENV['EDITOR']"
+ end
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/finish.rb b/lib/irb/cmd/finish.rb
new file mode 100644
index 0000000000..29f100feb5
--- /dev/null
+++ b/lib/irb/cmd/finish.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Finish < DebugCommand
+ def execute(*args)
+ super(do_cmds: ["finish", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/fork.rb b/lib/irb/cmd/fork.rb
index 7566d10be0..255a670dce 100644
--- a/lib/irb/cmd/fork.rb
+++ b/lib/irb/cmd/fork.rb
@@ -10,9 +10,11 @@
#
#
+require_relative "nop"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class Fork < Nop
def execute
@@ -33,5 +35,6 @@ module IRB
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/help.rb b/lib/irb/cmd/help.rb
index 0629479e92..2a135cdb14 100644
--- a/lib/irb/cmd/help.rb
+++ b/lib/irb/cmd/help.rb
@@ -11,13 +11,29 @@
require_relative "nop"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class Help < Nop
+ class << self
+ def transform_args(args)
+ # Return a string literal as is for backward compatibility
+ if args.empty? || string_literal?(args)
+ args
+ else # Otherwise, consider the input as a String for convenience
+ args.strip.dump
+ end
+ end
+ end
+
+ category "Context"
+ description "Enter the mode to look up RI documents."
+
def execute(*names)
require 'rdoc/ri/driver'
- IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new)
+ opts = RDoc::RI::Driver.process_args([])
+ IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new(opts))
rescue LoadError, SystemExit
IRB::ExtendCommand::Help.remove_method(:execute)
# raise NoMethodError in ensure
@@ -42,5 +58,6 @@ module IRB
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/info.rb b/lib/irb/cmd/info.rb
index 8ad0c2a438..2c0a32b34f 100644
--- a/lib/irb/cmd/info.rb
+++ b/lib/irb/cmd/info.rb
@@ -1,31 +1,21 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
-require_relative "nop"
+require_relative "debug"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
- class Info < Nop
- def execute
- Class.new {
- def inspect
- str = "Ruby version: #{RUBY_VERSION}\n"
- str += "IRB version: #{IRB.version}\n"
- str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
- str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
- str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
- str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
- str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
- if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
- codepage = `chcp`.sub(/.*: (\d+)\n/, '\1')
- str += "Code page: #{codepage}\n"
- end
- str
- end
- alias_method :to_s, :inspect
- }.new
+ class Info < DebugCommand
+ def self.transform_args(args)
+ args&.dump
+ end
+
+ def execute(*args)
+ super(pre_cmds: ["info", *args].join(" "))
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/irb_info.rb b/lib/irb/cmd/irb_info.rb
new file mode 100644
index 0000000000..da11e8d40b
--- /dev/null
+++ b/lib/irb/cmd/irb_info.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: false
+
+require_relative "nop"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class IrbInfo < Nop
+ category "IRB"
+ description "Show information about IRB."
+
+ def execute
+ Class.new {
+ def inspect
+ str = "Ruby version: #{RUBY_VERSION}\n"
+ str += "IRB version: #{IRB.version}\n"
+ str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
+ str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
+ str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
+ str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
+ str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
+ str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
+ if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
+ codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
+ str += "Code page: #{codepage}\n"
+ end
+ str
+ end
+ alias_method :to_s, :inspect
+ }.new
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/load.rb b/lib/irb/cmd/load.rb
index b6769a4124..2897bbd975 100644
--- a/lib/irb/cmd/load.rb
+++ b/lib/irb/cmd/load.rb
@@ -13,21 +13,33 @@
require_relative "nop"
require_relative "../ext/loader"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
- class Load < Nop
+ class LoaderCommand < Nop
include IrbLoader
- def execute(file_name, priv = nil)
- return irb_load(file_name, priv)
+ def raise_cmd_argument_error
+ raise CommandArgumentError.new("Please specify the file name.")
end
end
- class Require < Nop
- include IrbLoader
+ class Load < LoaderCommand
+ category "IRB"
+ description "Load a Ruby file."
+
+ def execute(file_name = nil, priv = nil)
+ raise_cmd_argument_error unless file_name
+ irb_load(file_name, priv)
+ end
+ end
- def execute(file_name)
+ class Require < LoaderCommand
+ category "IRB"
+ description "Require a Ruby file."
+ def execute(file_name = nil)
+ raise_cmd_argument_error unless file_name
rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
return false if $".find{|f| f =~ rex}
@@ -55,13 +67,16 @@ module IRB
end
end
- class Source < Nop
- include IrbLoader
- def execute(file_name)
+ class Source < LoaderCommand
+ category "IRB"
+ description "Loads a given file in the current session."
+
+ def execute(file_name = nil)
+ raise_cmd_argument_error unless file_name
+
source_file(file_name)
end
end
end
-
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb
index cbbf96210e..b65fae2bf1 100644
--- a/lib/irb/cmd/ls.rb
+++ b/lib/irb/cmd/ls.rb
@@ -4,10 +4,23 @@ require "reline"
require_relative "nop"
require_relative "../color"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class Ls < Nop
+ category "Context"
+ description "Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output."
+
+ def self.transform_args(args)
+ if match = args&.match(/\A(?<args>.+\s|)(-g|-G)\s+(?<grep>[^\s]+)\s*\n\z/)
+ args = match[:args]
+ "#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/"
+ else
+ args
+ end
+ end
+
def execute(*arg, grep: nil)
o = Output.new(grep: grep)
@@ -20,6 +33,7 @@ module IRB
o.dump("instance variables", obj.instance_variables)
o.dump("class variables", klass.class_variables)
o.dump("locals", locals)
+ nil
end
def dump_methods(o, klass, obj)
@@ -97,5 +111,6 @@ module IRB
private_constant :Output
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/measure.rb b/lib/irb/cmd/measure.rb
index adea540e92..9122e2dac9 100644
--- a/lib/irb/cmd/measure.rb
+++ b/lib/irb/cmd/measure.rb
@@ -1,9 +1,13 @@
require_relative "nop"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class Measure < Nop
+ category "Misc"
+ description "`measure` enables the mode to measure processing time. `measure :off` disables it."
+
def initialize(*args)
super(*args)
end
@@ -39,5 +43,6 @@ module IRB
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/next.rb b/lib/irb/cmd/next.rb
new file mode 100644
index 0000000000..d29c82e7fc
--- /dev/null
+++ b/lib/irb/cmd/next.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Next < DebugCommand
+ def execute(*args)
+ super(do_cmds: ["next", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb
index d6f7a611a6..c616c054a8 100644
--- a/lib/irb/cmd/nop.rb
+++ b/lib/irb/cmd/nop.rb
@@ -9,20 +9,45 @@
#
#
#
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
+ class CommandArgumentError < StandardError; end
+
class Nop
+ class << self
+ def category(category = nil)
+ @category = category if category
+ @category
+ end
+
+ def description(description = nil)
+ @description = description if description
+ @description
+ end
+
+ private
+
+ def string_literal?(args)
+ sexp = Ripper.sexp(args)
+ sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
+ end
+ end
if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
def self.execute(conf, *opts, **kwargs, &block)
command = new(conf)
command.execute(*opts, **kwargs, &block)
+ rescue CommandArgumentError => e
+ puts e.message
end
else
def self.execute(conf, *opts, &block)
command = new(conf)
command.execute(*opts, &block)
+ rescue CommandArgumentError => e
+ puts e.message
end
end
@@ -41,5 +66,6 @@ module IRB
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/pushws.rb b/lib/irb/cmd/pushws.rb
index 612157d8a0..41d2e705f1 100644
--- a/lib/irb/cmd/pushws.rb
+++ b/lib/irb/cmd/pushws.rb
@@ -13,16 +13,23 @@
require_relative "nop"
require_relative "../ext/workspaces"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class Workspaces < Nop
+ category "IRB"
+ description "Show workspaces."
+
def execute(*obj)
irb_context.workspaces.collect{|ws| ws.main}
end
end
class PushWorkspace < Workspaces
+ category "IRB"
+ description "Push an object to the workspace stack."
+
def execute(*obj)
irb_context.push_workspace(*obj)
super
@@ -30,11 +37,15 @@ module IRB
end
class PopWorkspace < Workspaces
+ category "IRB"
+ description "Pop a workspace from the workspace stack."
+
def execute(*obj)
irb_context.pop_workspace(*obj)
super
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/show_cmds.rb b/lib/irb/cmd/show_cmds.rb
new file mode 100644
index 0000000000..acced27d48
--- /dev/null
+++ b/lib/irb/cmd/show_cmds.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "stringio"
+require_relative "nop"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class ShowCmds < Nop
+ category "IRB"
+ description "List all available commands and their description."
+
+ def execute(*args)
+ commands_info = IRB::ExtendCommandBundle.all_commands_info
+ commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
+ longest_cmd_name_length = commands_info.map { |c| c[:display_name] }.max { |a, b| a.length <=> b.length }.length
+
+ output = StringIO.new
+
+ commands_grouped_by_categories.each do |category, cmds|
+ output.puts Color.colorize(category, [:BOLD])
+
+ cmds.each do |cmd|
+ output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}"
+ end
+
+ output.puts
+ end
+
+ puts output.string
+
+ nil
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb
index feff8315f6..ea700be4bf 100644
--- a/lib/irb/cmd/show_source.rb
+++ b/lib/irb/cmd/show_source.rb
@@ -4,16 +4,76 @@ require_relative "nop"
require_relative "../color"
require_relative "../ruby-lex"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class ShowSource < Nop
+ category "Context"
+ description "Show the source code of a given method or constant."
+
+ class << self
+ def transform_args(args)
+ # Return a string literal as is for backward compatibility
+ if args.empty? || string_literal?(args)
+ args
+ else # Otherwise, consider the input as a String for convenience
+ args.strip.dump
+ end
+ end
+
+ def find_source(str, irb_context)
+ 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
+
+ private
+
+ def find_end(file, first_line)
+ return first_line unless File.exist?(file)
+ lex = RubyLex.new
+ lines = File.read(file).lines[(first_line - 1)..-1]
+ tokens = RubyLex.ripper_lex_without_warning(lines.join)
+ prev_tokens = []
+
+ # chunk with line number
+ tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
+ code = lines[0..lnum].join
+ prev_tokens.concat chunk
+ continue = lex.process_continue(prev_tokens)
+ code_block_open = lex.check_code_block(code, prev_tokens)
+ if !continue && !code_block_open
+ return first_line + lnum
+ end
+ end
+ first_line
+ end
+ end
+
def execute(str = nil)
unless str.is_a?(String)
puts "Error: Expected a string but got #{str.inspect}"
return
end
- source = find_source(str)
+
+ source = self.class.find_source(str, @irb_context)
if source && File.exist?(source.file)
show_source(source)
else
@@ -34,51 +94,6 @@ module IRB
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
- lines = File.read(file).lines[(first_line - 1)..-1]
- tokens = RubyLex.ripper_lex_without_warning(lines.join)
-
- code = +""
- prev_tokens = []
-
- # chunk with line number
- tokens.chunk { |tok| tok[0][0] }.each do |lnum, chunk|
- code << lines[lnum]
- prev_tokens.concat chunk
-
- continue = lex.process_continue(prev_tokens)
- code_block_open = lex.check_code_block(code, prev_tokens)
- if !continue && !code_block_open
- return first_line + lnum
- end
- end
- first_line
- end
-
def bold(str)
Color.colorize(str, [:BOLD])
end
@@ -92,5 +107,6 @@ module IRB
private_constant :Source
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/step.rb b/lib/irb/cmd/step.rb
new file mode 100644
index 0000000000..2bc74a9d79
--- /dev/null
+++ b/lib/irb/cmd/step.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require_relative "debug"
+
+module IRB
+ # :stopdoc:
+
+ module ExtendCommand
+ class Step < DebugCommand
+ def execute(*args)
+ super(do_cmds: ["step", *args].join(" "))
+ end
+ end
+ end
+
+ # :startdoc:
+end
diff --git a/lib/irb/cmd/subirb.rb b/lib/irb/cmd/subirb.rb
index 1e18607d1a..699b35fcb4 100644
--- a/lib/irb/cmd/subirb.rb
+++ b/lib/irb/cmd/subirb.rb
@@ -10,34 +10,62 @@
#
require_relative "nop"
-require_relative "../ext/multi-irb"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
- class IrbCommand < Nop
+ class MultiIRBCommand < Nop
+ def initialize(conf)
+ super
+ extend_irb_context
+ end
+
+ private
+
+ def extend_irb_context
+ # this extension patches IRB context like IRB.CurrentContext
+ require_relative "../ext/multi-irb"
+ end
+ end
+
+ class IrbCommand < MultiIRBCommand
+ category "IRB"
+ description "Start a child IRB."
+
def execute(*obj)
IRB.irb(nil, *obj)
end
end
- class Jobs < Nop
+ class Jobs < MultiIRBCommand
+ category "IRB"
+ description "List of current sessions."
+
def execute
IRB.JobManager
end
end
- class Foreground < Nop
- def execute(key)
+ class Foreground < MultiIRBCommand
+ category "IRB"
+ description "Switches to the session of the given number."
+
+ def execute(key = nil)
+ raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
IRB.JobManager.switch(key)
end
end
- class Kill < Nop
+ class Kill < MultiIRBCommand
+ category "IRB"
+ description "Kills the session with the given number."
+
def execute(*keys)
IRB.JobManager.kill(*keys)
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/cmd/whereami.rb b/lib/irb/cmd/whereami.rb
index b3def11b93..8f56ba073d 100644
--- a/lib/irb/cmd/whereami.rb
+++ b/lib/irb/cmd/whereami.rb
@@ -2,10 +2,14 @@
require_relative "nop"
-# :stopdoc:
module IRB
+ # :stopdoc:
+
module ExtendCommand
class Whereami < Nop
+ category "Context"
+ description "Show the source code around binding.irb again."
+
def execute(*)
code = irb_context.workspace.code_around_binding
if code
@@ -16,5 +20,6 @@ module IRB
end
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/color.rb b/lib/irb/color.rb
index 40e9e04c97..6378e14856 100644
--- a/lib/irb/color.rb
+++ b/lib/irb/color.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'reline'
require 'ripper'
-require 'irb/ruby-lex'
+require_relative 'ruby-lex'
module IRB # :nodoc:
module Color
@@ -77,7 +77,15 @@ module IRB # :nodoc:
class << self
def colorable?
- $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
+ supported = $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
+
+ # because ruby/debug also uses irb's color module selectively,
+ # irb won't be activated in that case.
+ if IRB.respond_to?(:conf)
+ supported && IRB.conf.fetch(:USE_COLORIZE, true)
+ else
+ supported
+ end
end
def inspect_colorable?(obj, seen: {}.compare_by_identity)
@@ -115,15 +123,21 @@ 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, ignore_error: false, colorable: colorable?)
+ def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, local_variables: [])
return code unless colorable
symbol_state = SymbolState.new
colored = +''
- length = 0
- end_seen = false
+ lvars_code = RubyLex.generate_local_variables_assign_code(local_variables)
+ code_with_lvars = lvars_code ? "#{lvars_code}\n#{code}" : code
+
+ scan(code_with_lvars, allow_last_error: !complete) do |token, str, expr|
+ # handle uncolorable code
+ if token.nil?
+ colored << Reline::Unicode.escape_for_print(str)
+ next
+ end
- 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)
@@ -139,15 +153,12 @@ module IRB # :nodoc:
colored << line
end
end
- length += str.bytesize
- end_seen = true if token == :on___end__
end
- # give up colorizing incomplete Ripper tokens
- unless end_seen or length == code.bytesize
- return Reline::Unicode.escape_for_print(code)
+ if lvars_code
+ raise "#{lvars_code.dump} should have no \\n" if lvars_code.include?("\n")
+ colored.sub!(/\A.+\n/, '') # delete_prefix lvars_code with colors
end
-
colored
end
@@ -162,33 +173,42 @@ module IRB # :nodoc:
end
def scan(code, allow_last_error:)
- pos = [1, 0]
-
verbose, $VERBOSE = $VERBOSE, nil
RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no|
lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no)
- if lexer.respond_to?(:scan) # Ruby 2.7+
- lexer.scan.each do |elem|
- str = elem.tok
- next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
- next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0
+ byte_pos = 0
+ line_positions = [0]
+ inner_code.lines.each do |line|
+ line_positions << line_positions.last + line.bytesize
+ end
+
+ on_scan = proc do |elem|
+ start_pos = line_positions[elem.pos[0] - 1] + elem.pos[1]
- str.each_line do |line|
- if line.end_with?("\n")
- pos[0] += 1
- pos[1] = 0
- else
- pos[1] += line.bytesize
- end
- end
+ # yield uncolorable code
+ if byte_pos < start_pos
+ yield(nil, inner_code.byteslice(byte_pos...start_pos), nil)
+ end
+ if byte_pos <= start_pos
+ str = elem.tok
yield(elem.event, str, elem.state)
+ byte_pos = start_pos + str.bytesize
+ end
+ end
+
+ if lexer.respond_to?(:scan) # Ruby 2.7+
+ lexer.scan.each do |elem|
+ next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
+ on_scan.call(elem)
end
else
- lexer.parse.each do |elem|
- yield(elem.event, elem.tok, elem.state)
+ lexer.parse.sort_by(&:pos).each do |elem|
+ on_scan.call(elem)
end
end
+ # yield uncolorable DATA section
+ yield(nil, inner_code.byteslice(byte_pos...inner_code.bytesize), nil) if byte_pos < inner_code.bytesize
end
ensure
$VERBOSE = verbose
diff --git a/lib/irb/color_printer.rb b/lib/irb/color_printer.rb
index 30c6825750..1127bcecb4 100644
--- a/lib/irb/color_printer.rb
+++ b/lib/irb/color_printer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'pp'
-require 'irb/color'
+require_relative 'color'
module IRB
class ColorPrinter < ::PP
@@ -37,6 +37,9 @@ module IRB
width ||= str.length
case str
+ when ''
+ when ',', '=>', '[', ']', '{', '}', '..', '...', /\A@\w+\z/
+ super(str, width)
when /\A#</, '=', '>'
super(Color.colorize(str, [:GREEN]), width)
else
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
index d1bb82122e..34640e17f9 100644
--- a/lib/irb/completion.rb
+++ b/lib/irb/completion.rb
@@ -11,7 +11,29 @@ require_relative 'ruby-lex'
module IRB
module InputCompletor # :nodoc:
+ using Module.new {
+ refine ::Binding do
+ def eval_methods
+ ::Kernel.instance_method(:methods).bind(eval("self")).call
+ end
+
+ def eval_private_methods
+ ::Kernel.instance_method(:private_methods).bind(eval("self")).call
+ end
+
+ def eval_instance_variables
+ ::Kernel.instance_method(:instance_variables).bind(eval("self")).call
+ end
+
+ def eval_global_variables
+ ::Kernel.instance_method(:global_variables).bind(eval("self")).call
+ end
+ def eval_class_constants
+ ::Module.instance_method(:constants).bind(eval("self.class")).call
+ end
+ end
+ }
# Set of reserved words used by Ruby, you should not use these for
# constants or variables
@@ -38,16 +60,57 @@ module IRB
BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
- 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
- []
+ def self.absolute_path?(p) # TODO Remove this method after 2.6 EOL.
+ if File.respond_to?(:absolute_path?)
+ File.absolute_path?(p)
+ else
+ File.absolute_path(p) == p
+ end
+ end
+
+ GEM_PATHS =
+ if defined?(Gem::Specification)
+ Gem::Specification.latest_specs(true).map { |s|
+ s.require_paths.map { |p|
+ if absolute_path?(p)
+ p
+ else
+ File.join(s.full_gem_path, p)
+ end
+ }
+ }.flatten
+ else
+ []
+ end.freeze
+
+ def self.retrieve_gem_and_system_load_path
+ candidates = (GEM_PATHS | $LOAD_PATH)
+ candidates.map do |p|
+ if p.respond_to?(:to_path)
+ p.to_path
+ else
+ String(p) rescue nil
end
- }.uniq.map { |path|
- path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
- }
+ end.compact.sort
+ end
+
+ def self.retrieve_files_to_require_from_load_path
+ @@files_from_load_path ||=
+ (
+ shortest = []
+ rest = retrieve_gem_and_system_load_path.each_with_object([]) { |path, result|
+ begin
+ names = Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
+ rescue Errno::ENOENT
+ nil
+ end
+ next if names.empty?
+ names.map! { |n| n.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '') }.sort!
+ shortest << names.shift
+ result.concat(names)
+ }
+ shortest.sort! | rest
+ )
end
def self.retrieve_files_to_require_relative_from_current_dir
@@ -110,10 +173,10 @@ module IRB
receiver = $1
message = $3
- candidates = String.instance_methods.collect{|m| m.to_s}
if doc_namespace
"String.#{message}"
else
+ candidates = String.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
end
@@ -122,10 +185,10 @@ module IRB
receiver = $1
message = $2
- candidates = Regexp.instance_methods.collect{|m| m.to_s}
if doc_namespace
"Regexp.#{message}"
else
+ candidates = Regexp.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
end
@@ -134,10 +197,10 @@ module IRB
receiver = $1
message = $2
- candidates = Array.instance_methods.collect{|m| m.to_s}
if doc_namespace
"Array.#{message}"
else
+ candidates = Array.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates)
end
@@ -146,29 +209,33 @@ module IRB
receiver = $1
message = $2
- proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
- hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
if doc_namespace
["Proc.#{message}", "Hash.#{message}"]
else
+ proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
+ hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, proc_candidates | hash_candidates)
end
when /^(:[^:.]*)$/
# Symbol
- return nil if doc_namespace
- sym = $1
- candidates = Symbol.all_symbols.collect do |s|
- ":" + s.id2name.encode(Encoding.default_external)
- rescue Encoding::UndefinedConversionError
- # ignore
+ if doc_namespace
+ nil
+ else
+ sym = $1
+ candidates = Symbol.all_symbols.collect do |s|
+ ":" + s.id2name.encode(Encoding.default_external)
+ rescue EncodingError
+ # ignore
+ end
+ candidates.grep(/^#{Regexp.quote(sym)}/)
end
- candidates.grep(/^#{Regexp.quote(sym)}/)
-
- when /^::([A-Z][^:\.\(]*)$/
+ when /^::([A-Z][^:\.\(\)]*)$/
# Absolute Constant or class methods
receiver = $1
+
candidates = Object.constants.collect{|m| m.to_s}
+
if doc_namespace
candidates.find { |i| i == receiver }
else
@@ -179,16 +246,18 @@ module IRB
# Constant or class methods
receiver = $1
message = $2
- begin
- candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
- candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
- rescue Exception
- candidates = []
- end
+
if doc_namespace
"#{receiver}::#{message}"
else
- select_message(receiver, message, candidates, "::")
+ begin
+ candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
+ candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
+ rescue Exception
+ candidates = []
+ end
+
+ select_message(receiver, message, candidates.sort, "::")
end
when /^(:[^:.]+)(\.|::)([^.]*)$/
@@ -197,10 +266,10 @@ module IRB
sep = $2
message = $3
- candidates = Symbol.instance_methods.collect{|m| m.to_s}
if doc_namespace
"Symbol.#{message}"
else
+ candidates = Symbol.instance_methods.collect{|m| m.to_s}
select_message(receiver, message, candidates, sep)
end
@@ -212,6 +281,7 @@ module IRB
begin
instance = eval(receiver, bind)
+
if doc_namespace
"#{instance.class.name}.#{message}"
else
@@ -222,7 +292,7 @@ module IRB
if doc_namespace
nil
else
- candidates = []
+ []
end
end
@@ -244,7 +314,7 @@ module IRB
if doc_namespace
nil
else
- candidates = []
+ []
end
end
@@ -252,22 +322,23 @@ module IRB
# global var
gvar = $1
all_gvars = global_variables.collect{|m| m.to_s}
+
if doc_namespace
all_gvars.find{ |i| i == gvar }
else
all_gvars.grep(Regexp.new(Regexp.quote(gvar)))
end
- when /^([^."].*)(\.|::)([^.]*)$/
+ when /^([^.:"].*)(\.|::)([^.]*)$/
# variable.func or func.func
receiver = $1
sep = $2
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}
- iv = eval("instance_variables", bind).collect{|m| m.to_s}
- cv = eval("self.class.constants", bind).collect{|m| m.to_s}
+ gv = bind.eval_global_variables.collect{|m| m.to_s}.push("true", "false", "nil")
+ lv = bind.local_variables.collect{|m| m.to_s}
+ iv = bind.eval_instance_variables.collect{|m| m.to_s}
+ cv = bind.eval_class_constants.collect{|m| m.to_s}
if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
# foo.func and foo is var. OR
@@ -290,13 +361,16 @@ module IRB
to_ignore = ignored_modules
ObjectSpace.each_object(Module){|m|
next if (to_ignore.include?(m) rescue true)
+ next unless m.respond_to?(:instance_methods) # JRuby has modules that represent java packages. They don't include many common ruby methods
candidates.concat m.instance_methods(false).collect{|x| x.to_s}
}
candidates.sort!
candidates.uniq!
end
+
if doc_namespace
- "#{rec.class.name}#{sep}#{candidates.find{ |i| i == message }}"
+ rec_class = rec.is_a?(Module) ? rec : rec.class
+ "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}"
else
select_message(receiver, message, candidates, sep)
end
@@ -308,20 +382,28 @@ module IRB
message = $1
candidates = String.instance_methods(true).collect{|m| m.to_s}
+
if doc_namespace
"String.#{candidates.find{ |i| i == message }}"
else
- select_message(receiver, message, candidates)
+ select_message(receiver, message, candidates.sort)
end
else
- candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s}
- candidates |= ReservedWords
-
if doc_namespace
- candidates.find{ |i| i == input }
+ vars = (bind.local_variables | bind.eval_instance_variables).collect{|m| m.to_s}
+ perfect_match_var = vars.find{|m| m.to_s == input}
+ if perfect_match_var
+ eval("#{perfect_match_var}.class.name", bind)
+ else
+ candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
+ candidates |= ReservedWords
+ candidates.find{ |i| i == input }
+ end
else
- candidates.grep(/^#{Regexp.quote(input)}/)
+ candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
+ candidates |= ReservedWords
+ candidates.grep(/^#{Regexp.quote(input)}/).sort
end
end
end
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
index 0d358de6ff..91fbb2fcf1 100644
--- a/lib/irb/context.rb
+++ b/lib/irb/context.rb
@@ -22,7 +22,7 @@ module IRB
#
# The optional +input_method+ argument:
#
- # +nil+:: uses stdin or Reidline or Readline
+ # +nil+:: uses stdin or Reline or Readline
# +String+:: uses a File
# +other+:: uses this as InputMethod
def initialize(irb, workspace = nil, input_method = nil)
@@ -32,7 +32,7 @@ module IRB
else
@workspace = WorkSpace.new
end
- @thread = Thread.current if defined? Thread
+ @thread = Thread.current
# copy of default configuration
@ap_name = IRB.conf[:AP_NAME]
@@ -48,12 +48,20 @@ module IRB
end
if IRB.conf.has_key?(:USE_MULTILINE)
@use_multiline = IRB.conf[:USE_MULTILINE]
- elsif IRB.conf.has_key?(:USE_REIDLINE) # backward compatibility
+ elsif IRB.conf.has_key?(:USE_RELINE) # backward compatibility
+ warn <<~MSG.strip
+ USE_RELINE is deprecated, please use USE_MULTILINE instead.
+ MSG
+ @use_multiline = IRB.conf[:USE_RELINE]
+ elsif IRB.conf.has_key?(:USE_REIDLINE)
+ warn <<~MSG.strip
+ USE_REIDLINE is deprecated, please use USE_MULTILINE instead.
+ MSG
@use_multiline = IRB.conf[:USE_REIDLINE]
else
@use_multiline = nil
end
- @use_colorize = IRB.conf[:USE_COLORIZE]
+ @use_autocomplete = IRB.conf[:USE_AUTOCOMPLETE]
@verbose = IRB.conf[:VERBOSE]
@io = nil
@@ -83,14 +91,14 @@ module IRB
when nil
if STDIN.tty? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
# Both of multiline mode and singleline mode aren't specified.
- @io = ReidlineInputMethod.new
+ @io = RelineInputMethod.new
else
@io = nil
end
when false
@io = nil
when true
- @io = ReidlineInputMethod.new
+ @io = RelineInputMethod.new
end
unless @io
case use_singleline?
@@ -115,6 +123,10 @@ module IRB
end
@io = StdioInputMethod.new unless @io
+ when '-'
+ @io = FileInputMethod.new($stdin)
+ @irb_name = '-'
+ @irb_path = '-'
when String
@io = FileInputMethod.new(input_method)
@irb_name = File.basename(input_method)
@@ -124,6 +136,8 @@ module IRB
end
self.save_history = IRB.conf[:SAVE_HISTORY] if IRB.conf[:SAVE_HISTORY]
+ @extra_doc_dirs = IRB.conf[:EXTRA_DOC_DIRS]
+
@echo = IRB.conf[:ECHO]
if @echo.nil?
@echo = true
@@ -138,6 +152,8 @@ module IRB
if @newline_before_multiline_output.nil?
@newline_before_multiline_output = true
end
+
+ @command_aliases = IRB.conf[:COMMAND_ALIASES]
end
# The top-level workspace, see WorkSpace#main
@@ -147,18 +163,18 @@ module IRB
# The toplevel workspace, see #home_workspace
attr_reader :workspace_home
- # WorkSpace in the current context
+ # WorkSpace in the current context.
attr_accessor :workspace
- # The current thread in this context
+ # The current thread in this context.
attr_reader :thread
- # The current input method
+ # The current input method.
#
# Can be either StdioInputMethod, ReadlineInputMethod,
- # ReidlineInputMethod, FileInputMethod or other specified when the
+ # RelineInputMethod, FileInputMethod or other specified when the
# context is created. See ::new for more # information on +input_method+.
attr_accessor :io
- # Current irb session
+ # Current irb session.
attr_accessor :irb
# A copy of the default <code>IRB.conf[:AP_NAME]</code>
attr_accessor :ap_name
@@ -183,22 +199,22 @@ module IRB
attr_reader :use_singleline
# Whether colorization is enabled or not.
#
- # A copy of the default <code>IRB.conf[:USE_COLORIZE]</code>
- attr_reader :use_colorize
+ # A copy of the default <code>IRB.conf[:USE_AUTOCOMPLETE]</code>
+ attr_reader :use_autocomplete
# A copy of the default <code>IRB.conf[:INSPECT_MODE]</code>
attr_reader :inspect_mode
# A copy of the default <code>IRB.conf[:PROMPT_MODE]</code>
attr_reader :prompt_mode
- # Standard IRB prompt
+ # Standard IRB prompt.
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_i
- # IRB prompt for continuated strings
+ # IRB prompt for continuated strings.
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_s
- # IRB prompt for continuated statement (e.g. immediately after an +if+)
+ # IRB prompt for continuated statement. (e.g. immediately after an +if+)
#
# See IRB@Customizing+the+IRB+Prompt for more information.
attr_accessor :prompt_c
@@ -238,6 +254,9 @@ module IRB
#
# If set to +false+, <code>^D</code> will quit irb.
attr_accessor :ignore_eof
+ # Specify the installation locations of the ri file to be displayed in the
+ # document dialog.
+ attr_accessor :extra_doc_dirs
# Whether to echo the return value to output or not.
#
# Uses <code>IRB.conf[:ECHO]</code> if available, or defaults to +true+.
@@ -249,7 +268,7 @@ module IRB
# puts "omg"
# # omg
attr_accessor :echo
- # Whether to echo for assignment expressions
+ # Whether to echo for assignment expressions.
#
# If set to +false+, the value of assignment will not be shown.
#
@@ -261,13 +280,28 @@ module IRB
#
# a = "omg"
# #=> omg
+ #
# a = "omg" * 10
# #=> omgomgomgomgomgomgomg...
+ #
# IRB.CurrentContext.echo_on_assignment = false
# a = "omg"
+ #
# IRB.CurrentContext.echo_on_assignment = true
- # a = "omg"
+ # a = "omg" * 10
# #=> omgomgomgomgomgomgomgomgomgomg
+ #
+ # To set the behaviour of showing on assignment in irb:
+ #
+ # IRB.conf[:ECHO_ON_ASSIGNMENT] = :truncate or true or false
+ #
+ # or
+ #
+ # irb_context.echo_on_assignment = :truncate or true or false
+ #
+ # or
+ #
+ # IRB.CurrentContext.echo_on_assignment = :truncate or true or false
attr_accessor :echo_on_assignment
# Whether a newline is put before multiline output.
#
@@ -297,20 +331,23 @@ module IRB
# See IRB@Command+line+options for more command line options.
attr_accessor :back_trace_limit
+ # User-defined IRB command aliases
+ attr_accessor :command_aliases
+
# Alias for #use_multiline
alias use_multiline? use_multiline
# Alias for #use_singleline
alias use_singleline? use_singleline
# backward compatibility
- alias use_reidline use_multiline
+ alias use_reline use_multiline
# backward compatibility
- alias use_reidline? use_multiline
+ alias use_reline? use_multiline
# backward compatibility
alias use_readline use_singleline
# backward compatibility
alias use_readline? use_singleline
- # Alias for #use_colorize
- alias use_colorize? use_colorize
+ # Alias for #use_autocomplete
+ alias use_autocomplete? use_autocomplete
# Alias for #rc
alias rc? rc
alias ignore_sigint? ignore_sigint
@@ -322,7 +359,7 @@ module IRB
# Returns whether messages are displayed or not.
def verbose?
if @verbose.nil?
- if @io.kind_of?(ReidlineInputMethod)
+ if @io.kind_of?(RelineInputMethod)
false
elsif defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)
false
@@ -337,11 +374,11 @@ module IRB
end
# Whether #verbose? is +true+, and +input_method+ is either
- # StdioInputMethod or ReidlineInputMethod or ReadlineInputMethod, see #io
+ # StdioInputMethod or RelineInputMethod or ReadlineInputMethod, see #io
# for more information.
def prompting?
verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
- @io.kind_of?(ReidlineInputMethod) ||
+ @io.kind_of?(RelineInputMethod) ||
(defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)))
end
@@ -366,6 +403,7 @@ module IRB
@prompt_c = pconf[:PROMPT_C]
@prompt_n = pconf[:PROMPT_N]
@return_format = pconf[:RETURN]
+ @return_format = "%s\n" if @return_format == nil
if ai = pconf.include?(:AUTO_INDENT)
@auto_indent_mode = ai
else
@@ -447,6 +485,20 @@ module IRB
line = "begin ::Kernel.raise _; rescue _.class\n#{line}\n""end"
@workspace.local_variable_set(:_, exception)
end
+
+ # Transform a non-identifier alias (@, $) or keywords (next, break)
+ command, args = line.split(/\s/, 2)
+ if original = command_aliases[command.to_sym]
+ line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
+ command = original
+ end
+
+ # Hook command-specific transformation
+ command_class = ExtendCommandBundle.load_command(command)
+ if command_class&.respond_to?(:transform_args)
+ line = "#{command} #{command_class.transform_args(args)}"
+ end
+
set_last_value(@workspace.evaluate(self, line, irb_path, line_no))
end
@@ -458,6 +510,8 @@ module IRB
# Exits the current session, see IRB.irb_exit
def exit(ret = 0)
IRB.irb_exit(@irb, ret)
+ rescue UncaughtThrowError
+ super
end
NOPRINTING_IVARS = ["@last_value"] # :nodoc:
@@ -486,5 +540,21 @@ module IRB
end
alias __to_s__ to_s
alias to_s inspect
+
+ def local_variables # :nodoc:
+ workspace.binding.local_variables
+ end
+
+ # Return true if it's aliased from the argument and it's not an identifier.
+ def symbol_alias?(command)
+ return nil if command.match?(/\A\w+\z/)
+ command_aliases.key?(command.to_sym)
+ end
+
+ # Return true if the command supports transforming args
+ def transform_args?(command)
+ command = command_aliases.fetch(command.to_sym, command)
+ ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
+ end
end
end
diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb
index 74de1ecde5..e57d43a569 100644
--- a/lib/irb/ext/multi-irb.rb
+++ b/lib/irb/ext/multi-irb.rb
@@ -9,7 +9,6 @@
#
#
#
-fail CantShiftToMultiIrbMode unless defined?(Thread)
module IRB
class JobManager
diff --git a/lib/irb/ext/save-history.rb b/lib/irb/ext/save-history.rb
index 7acaebe36a..9e7620545a 100644
--- a/lib/irb/ext/save-history.rb
+++ b/lib/irb/ext/save-history.rb
@@ -70,10 +70,10 @@ module IRB
end
history_file = IRB.rc_file("_history") unless history_file
if File.exist?(history_file)
- open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
+ File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
f.each { |l|
l = l.chomp
- if self.class == ReidlineInputMethod and history.last&.end_with?("\\")
+ if self.class == RelineInputMethod and history.last&.end_with?("\\")
history.last.delete_suffix!("\\")
history.last << "\n" << l
else
@@ -107,13 +107,13 @@ module IRB
raise
end
- if File.exist?(history_file) && @loaded_history_mtime &&
+ if File.exist?(history_file) &&
File.mtime(history_file) != @loaded_history_mtime
- history = history[@loaded_history_lines..-1]
+ history = history[@loaded_history_lines..-1] if @loaded_history_lines
append_history = true
end
- open(history_file, "#{append_history ? 'a' : 'w'}:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
+ File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
hist = history.map{ |l| l.split("\n").join("\\\n") }
unless append_history
begin
diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb
index 339e9e6084..d0829a06c4 100644
--- a/lib/irb/extend-command.rb
+++ b/lib/irb/extend-command.rb
@@ -45,123 +45,200 @@ module IRB # :nodoc:
[:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
]
+
@EXTEND_COMMANDS = [
[
- :irb_current_working_workspace, :CurrentWorkingWorkspace, "irb/cmd/chws",
+ :irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws",
+ [:cwws, NO_OVERRIDE],
+ [:pwws, NO_OVERRIDE],
[:irb_print_working_workspace, OVERRIDE_ALL],
[:irb_cwws, OVERRIDE_ALL],
[:irb_pwws, OVERRIDE_ALL],
- [:cwws, NO_OVERRIDE],
- [:pwws, NO_OVERRIDE],
[:irb_current_working_binding, OVERRIDE_ALL],
[:irb_print_working_binding, OVERRIDE_ALL],
[:irb_cwb, OVERRIDE_ALL],
[:irb_pwb, OVERRIDE_ALL],
],
[
- :irb_change_workspace, :ChangeWorkspace, "irb/cmd/chws",
- [:irb_chws, OVERRIDE_ALL],
- [:irb_cws, OVERRIDE_ALL],
+ :irb_change_workspace, :ChangeWorkspace, "cmd/chws",
[:chws, NO_OVERRIDE],
[:cws, NO_OVERRIDE],
+ [:irb_chws, OVERRIDE_ALL],
+ [:irb_cws, OVERRIDE_ALL],
[:irb_change_binding, OVERRIDE_ALL],
[:irb_cb, OVERRIDE_ALL],
[:cb, NO_OVERRIDE],
],
[
- :irb_workspaces, :Workspaces, "irb/cmd/pushws",
+ :irb_workspaces, :Workspaces, "cmd/pushws",
[:workspaces, NO_OVERRIDE],
[:irb_bindings, OVERRIDE_ALL],
[:bindings, NO_OVERRIDE],
],
[
- :irb_push_workspace, :PushWorkspace, "irb/cmd/pushws",
- [:irb_pushws, OVERRIDE_ALL],
+ :irb_push_workspace, :PushWorkspace, "cmd/pushws",
[:pushws, NO_OVERRIDE],
+ [:irb_pushws, OVERRIDE_ALL],
[:irb_push_binding, OVERRIDE_ALL],
[:irb_pushb, OVERRIDE_ALL],
[:pushb, NO_OVERRIDE],
],
[
- :irb_pop_workspace, :PopWorkspace, "irb/cmd/pushws",
- [:irb_popws, OVERRIDE_ALL],
+ :irb_pop_workspace, :PopWorkspace, "cmd/pushws",
[:popws, NO_OVERRIDE],
+ [:irb_popws, OVERRIDE_ALL],
[:irb_pop_binding, OVERRIDE_ALL],
[:irb_popb, OVERRIDE_ALL],
[:popb, NO_OVERRIDE],
],
[
- :irb_load, :Load, "irb/cmd/load"],
+ :irb_load, :Load, "cmd/load"],
[
- :irb_require, :Require, "irb/cmd/load"],
+ :irb_require, :Require, "cmd/load"],
[
- :irb_source, :Source, "irb/cmd/load",
+ :irb_source, :Source, "cmd/load",
[:source, NO_OVERRIDE],
],
[
- :irb, :IrbCommand, "irb/cmd/subirb"],
+ :irb, :IrbCommand, "cmd/subirb"],
[
- :irb_jobs, :Jobs, "irb/cmd/subirb",
+ :irb_jobs, :Jobs, "cmd/subirb",
[:jobs, NO_OVERRIDE],
],
[
- :irb_fg, :Foreground, "irb/cmd/subirb",
+ :irb_fg, :Foreground, "cmd/subirb",
[:fg, NO_OVERRIDE],
],
[
- :irb_kill, :Kill, "irb/cmd/subirb",
+ :irb_kill, :Kill, "cmd/subirb",
[:kill, OVERRIDE_PRIVATE_ONLY],
],
[
- :irb_help, :Help, "irb/cmd/help",
+ :irb_debug, :Debug, "cmd/debug",
+ [:debug, NO_OVERRIDE],
+ ],
+ [
+ :irb_edit, :Edit, "cmd/edit",
+ [:edit, NO_OVERRIDE],
+ ],
+ [
+ :irb_break, :Break, "cmd/break",
+ ],
+ [
+ :irb_catch, :Catch, "cmd/catch",
+ ],
+ [
+ :irb_next, :Next, "cmd/next"
+ ],
+ [
+ :irb_delete, :Delete, "cmd/delete",
+ [:delete, NO_OVERRIDE],
+ ],
+ [
+ :irb_step, :Step, "cmd/step",
+ [:step, NO_OVERRIDE],
+ ],
+ [
+ :irb_continue, :Continue, "cmd/continue",
+ [:continue, NO_OVERRIDE],
+ ],
+ [
+ :irb_finish, :Finish, "cmd/finish",
+ [:finish, NO_OVERRIDE],
+ ],
+ [
+ :irb_backtrace, :Backtrace, "cmd/backtrace",
+ [:backtrace, NO_OVERRIDE],
+ [:bt, NO_OVERRIDE],
+ ],
+ [
+ :irb_debug_info, :Info, "cmd/info",
+ [:info, NO_OVERRIDE],
+ ],
+
+ [
+ :irb_help, :Help, "cmd/help",
+ [:show_doc, NO_OVERRIDE],
[:help, NO_OVERRIDE],
],
[
- :irb_info, :Info, "irb/cmd/info"
+ :irb_info, :IrbInfo, "cmd/irb_info"
],
[
- :irb_ls, :Ls, "irb/cmd/ls",
+ :irb_ls, :Ls, "cmd/ls",
[:ls, NO_OVERRIDE],
],
[
- :irb_measure, :Measure, "irb/cmd/measure",
+ :irb_measure, :Measure, "cmd/measure",
[:measure, NO_OVERRIDE],
],
[
- :irb_show_source, :ShowSource, "irb/cmd/show_source",
+ :irb_show_source, :ShowSource, "cmd/show_source",
[:show_source, NO_OVERRIDE],
],
[
- :irb_whereami, :Whereami, "irb/cmd/whereami",
+ :irb_whereami, :Whereami, "cmd/whereami",
[:whereami, NO_OVERRIDE],
],
-
+ [
+ :irb_show_cmds, :ShowCmds, "cmd/show_cmds",
+ [:show_cmds, NO_OVERRIDE],
+ ]
]
- # Installs the default irb commands:
- #
- # +irb_current_working_workspace+:: Context#main
- # +irb_change_workspace+:: Context#change_workspace
- # +irb_workspaces+:: Context#workspaces
- # +irb_push_workspace+:: Context#push_workspace
- # +irb_pop_workspace+:: Context#pop_workspace
- # +irb_load+:: #irb_load
- # +irb_require+:: #irb_require
- # +irb_source+:: IrbLoader#source_file
- # +irb+:: IRB.irb
- # +irb_jobs+:: JobManager
- # +irb_fg+:: JobManager#switch
- # +irb_kill+:: JobManager#kill
- # +irb_help+:: IRB@Command+line+options
+
+ @@commands = []
+
+ def self.all_commands_info
+ return @@commands unless @@commands.empty?
+ user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
+ result[target] ||= []
+ result[target] << alias_name
+ end
+
+ @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
+ if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
+ require_relative load_file
+ end
+
+ klass = ExtendCommand.const_get(cmd_class, false)
+ aliases = aliases.map { |a| a.first }
+
+ if additional_aliases = user_aliases[cmd_name]
+ aliases += additional_aliases
+ end
+
+ display_name = aliases.shift || cmd_name
+ @@commands << { display_name: display_name, description: klass.description, category: klass.category }
+ end
+
+ @@commands
+ end
+
+ # Convert a command name to its implementation class if such command exists
+ def self.load_command(command)
+ command = command.to_sym
+ @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases|
+ next if cmd_name != command && aliases.all? { |alias_name, _| alias_name != command }
+
+ if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false)
+ require_relative load_file
+ end
+ return ExtendCommand.const_get(cmd_class, false)
+ end
+ nil
+ end
+
+ # Installs the default irb commands.
def self.install_extend_commands
for args in @EXTEND_COMMANDS
def_extend_command(*args)
@@ -187,7 +264,7 @@ module IRB # :nodoc:
kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
line = __LINE__; eval %[
def #{cmd_name}(*opts#{kwargs}, &b)
- require "#{load_file}"
+ require_relative "#{load_file}"
arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity
args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
args << "*opts#{kwargs}" if arity < 0
@@ -235,7 +312,7 @@ module IRB # :nodoc:
alias_method to, from
}
else
- print "irb: warn: can't alias #{to} from #{from}.\n"
+ Kernel.print "irb: warn: can't alias #{to} from #{from}.\n"
end
end
@@ -262,10 +339,10 @@ module IRB # :nodoc:
CE = ContextExtender # :nodoc:
@EXTEND_COMMANDS = [
- [:eval_history=, "irb/ext/history.rb"],
- [:use_tracer=, "irb/ext/tracer.rb"],
- [:use_loader=, "irb/ext/use-loader.rb"],
- [:save_history=, "irb/ext/save-history.rb"],
+ [:eval_history=, "ext/history.rb"],
+ [:use_tracer=, "ext/tracer.rb"],
+ [:use_loader=, "ext/use-loader.rb"],
+ [:save_history=, "ext/save-history.rb"],
]
# Installs the default context extensions as irb commands:
@@ -288,7 +365,7 @@ module IRB # :nodoc:
line = __LINE__; Context.module_eval %[
def #{cmd_name}(*opts, &b)
Context.module_eval {remove_method(:#{cmd_name})}
- require "#{load_file}"
+ require_relative "#{load_file}"
__send__ :#{cmd_name}, *opts, &b
end
for ali in aliases
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
index 5923c54a29..55453cc8f7 100644
--- a/lib/irb/init.rb
+++ b/lib/irb/init.rb
@@ -44,12 +44,14 @@ module IRB # :nodoc:
@CONF[:IRB_RC] = nil
@CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
- @CONF[:USE_COLORIZE] = !ENV['NO_COLOR']
+ @CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
+ @CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
@CONF[:INSPECT_MODE] = true
@CONF[:USE_TRACER] = false
@CONF[:USE_LOADER] = false
@CONF[:IGNORE_SIGINT] = true
@CONF[:IGNORE_EOF] = false
+ @CONF[:EXTRA_DOC_DIRS] = []
@CONF[:ECHO] = nil
@CONF[:ECHO_ON_ASSIGNMENT] = nil
@CONF[:VERBOSE] = nil
@@ -156,6 +158,16 @@ module IRB # :nodoc:
@CONF[:LC_MESSAGES] = Locale.new
@CONF[:AT_EXIT] = []
+
+ @CONF[:COMMAND_ALIASES] = {
+ # Symbol aliases
+ :'$' => :show_source,
+ :'@' => :whereami,
+ # Keyword aliases
+ :break => :irb_break,
+ :catch => :irb_catch,
+ :next => :irb_next,
+ }
end
def IRB.set_measure_callback(type = nil, arg = nil, &block)
@@ -253,9 +265,24 @@ module IRB # :nodoc:
when "--nosingleline", "--noreadline"
@CONF[:USE_SINGLELINE] = false
when "--multiline", "--reidline"
+ if opt == "--reidline"
+ warn <<~MSG.strip
+ --reidline is deprecated, please use --multiline instead.
+ MSG
+ end
+
@CONF[:USE_MULTILINE] = true
when "--nomultiline", "--noreidline"
+ if opt == "--noreidline"
+ warn <<~MSG.strip
+ --noreidline is deprecated, please use --nomultiline instead.
+ MSG
+ end
+
@CONF[:USE_MULTILINE] = false
+ when /^--extra-doc-dir(?:=(.+))?/
+ opt = $1 || argv.shift
+ @CONF[:EXTRA_DOC_DIRS] << opt
when "--echo"
@CONF[:ECHO] = true
when "--noecho"
@@ -274,12 +301,20 @@ module IRB # :nodoc:
@CONF[:USE_COLORIZE] = true
when "--nocolorize"
@CONF[:USE_COLORIZE] = false
+ when "--autocomplete"
+ @CONF[:USE_AUTOCOMPLETE] = true
+ when "--noautocomplete"
+ @CONF[:USE_AUTOCOMPLETE] = false
when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/
opt = $1 || argv.shift
prompt_mode = opt.upcase.tr("-", "_").intern
@CONF[:PROMPT_MODE] = prompt_mode
when "--noprompt"
@CONF[:PROMPT_MODE] = :NULL
+ when "--script"
+ noscript = false
+ when "--noscript"
+ noscript = true
when "--inf-ruby-mode"
@CONF[:PROMPT_MODE] = :INF_RUBY
when "--sample-book-mode", "--simple-prompt"
@@ -300,16 +335,20 @@ module IRB # :nodoc:
IRB.print_usage
exit 0
when "--"
- if opt = argv.shift
+ if !noscript && (opt = argv.shift)
@CONF[:SCRIPT] = opt
$0 = opt
end
break
- when /^-/
+ when /^-./
fail UnrecognizedSwitch, opt
else
- @CONF[:SCRIPT] = opt
- $0 = opt
+ if noscript
+ argv.unshift(opt)
+ else
+ @CONF[:SCRIPT] = opt
+ $0 = opt
+ end
break
end
end
@@ -362,11 +401,9 @@ module IRB # :nodoc:
end
if xdg_config_home = ENV["XDG_CONFIG_HOME"]
irb_home = File.join(xdg_config_home, "irb")
- unless File.exist? irb_home
- require 'fileutils'
- FileUtils.mkdir_p irb_home
+ if File.directory?(irb_home)
+ yield proc{|rc| irb_home + "/irb#{rc}"}
end
- yield proc{|rc| irb_home + "/irb#{rc}"}
end
if home = ENV["HOME"]
yield proc{|rc| home+"/.irb#{rc}"}
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
index 1854567a2d..9480573195 100644
--- a/lib/irb/input-method.rb
+++ b/lib/irb/input-method.rb
@@ -38,7 +38,7 @@ module IRB
public :gets
def winsize
- if instance_variable_defined?(:@stdout)
+ if instance_variable_defined?(:@stdout) && @stdout.tty?
@stdout.winsize
else
[24, 80]
@@ -83,8 +83,7 @@ module IRB
#
# See IO#eof? for more information.
def eof?
- rs, = IO.select([@stdin], [], [], 0.00001)
- if rs and rs[0]
+ if @stdin.wait_readable(0.00001)
c = @stdin.getc
result = c.nil? ? true : false
@stdin.ungetc(c) unless c.nil?
@@ -138,7 +137,7 @@ module IRB
# Creates a new input method object
def initialize(file)
super
- @io = IRB::MagicFile.open(file)
+ @io = file.is_a?(IO) ? file : IRB::MagicFile.open(file)
@external_encoding = @io.external_encoding
end
# The file name of this input method, usually given during initialization.
@@ -262,9 +261,10 @@ module IRB
end
end
- class ReidlineInputMethod < InputMethod
+ class RelineInputMethod < InputMethod
include Reline
- # Creates a new input method object using Readline
+
+ # Creates a new input method object using Reline
def initialize
IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
super
@@ -286,7 +286,8 @@ module IRB
if IRB.conf[:USE_COLORIZE]
proc do |output, complete: |
next unless IRB::Color.colorable?
- IRB::Color.colorize_code(output, complete: complete)
+ lvars = IRB.CurrentContext&.local_variables || []
+ IRB::Color.colorize_code(output, complete: complete, local_variables: lvars)
end
else
proc do |output|
@@ -294,6 +295,15 @@ module IRB
end
end
Reline.dig_perfect_match_proc = IRB::InputCompletor::PerfectMatchedProc
+ Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
+
+ if IRB.conf[:USE_AUTOCOMPLETE]
+ begin
+ require 'rdoc'
+ Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT)
+ rescue LoadError
+ end
+ end
end
def check_termination(&block)
@@ -308,6 +318,99 @@ module IRB
@auto_indent_proc = block
end
+ SHOW_DOC_DIALOG = ->() {
+ dialog.trap_key = nil
+ alt_d = [
+ [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
+ [27, 100], # Normal Alt+d when convert-meta isn't used.
+ [195, 164], # The "ä" that appears when Alt+d is pressed on xterm.
+ [226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2.
+ ]
+
+ if just_cursor_moving and completion_journey_data.nil?
+ return nil
+ end
+ cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
+ return nil if result.nil? or pointer.nil? or pointer < 0
+ name = result[pointer]
+ name = IRB::InputCompletor.retrieve_completion_data(name, doc_namespace: true)
+
+ options = {}
+ options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
+ driver = RDoc::RI::Driver.new(options)
+
+ if key.match?(dialog.name)
+ begin
+ driver.display_names([name])
+ rescue RDoc::RI::Driver::NotFoundError
+ end
+ end
+
+ begin
+ name = driver.expand_name(name)
+ rescue RDoc::RI::Driver::NotFoundError
+ return nil
+ rescue
+ return nil # unknown error
+ end
+ doc = nil
+ used_for_class = false
+ if not name =~ /#|\./
+ found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
+ if not found.empty?
+ doc = driver.class_document(name, found, klasses, includes, extends)
+ used_for_class = true
+ end
+ end
+ unless used_for_class
+ doc = RDoc::Markup::Document.new
+ begin
+ driver.add_method(doc, name)
+ rescue RDoc::RI::Driver::NotFoundError
+ doc = nil
+ rescue
+ return nil # unknown error
+ end
+ end
+ return nil if doc.nil?
+ width = 40
+
+ right_x = cursor_pos_to_render.x + autocomplete_dialog.width
+ if right_x + width > screen_width
+ right_width = screen_width - (right_x + 1)
+ left_x = autocomplete_dialog.column - width
+ left_x = 0 if left_x < 0
+ left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
+ if right_width.positive? and left_width.positive?
+ if right_width >= left_width
+ width = right_width
+ x = right_x
+ else
+ width = left_width
+ x = left_x
+ end
+ elsif right_width.positive? and left_width <= 0
+ width = right_width
+ x = right_x
+ elsif right_width <= 0 and left_width.positive?
+ width = left_width
+ x = left_x
+ else # Both are negative width.
+ return nil
+ end
+ else
+ x = right_x
+ end
+ formatter = RDoc::Markup::ToAnsi.new
+ formatter.width = width
+ dialog.trap_key = alt_d
+ message = 'Press Alt+d to read the full document'
+ contents = [message] + doc.accept(formatter).split("\n")
+
+ y = cursor_pos_to_render.y
+ DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
+ }
+
# Reads the next line from this input method.
#
# See IO#gets for more information.
@@ -358,7 +461,7 @@ module IRB
# For debug message
def inspect
config = Reline::Config.new
- str = "ReidlineInputMethod with Reline #{Reline::VERSION}"
+ str = "RelineInputMethod with Reline #{Reline::VERSION}"
if config.respond_to?(:inputrc_path)
inputrc_path = File.expand_path(config.inputrc_path)
else
@@ -368,4 +471,13 @@ module IRB
str
end
end
+
+ class ReidlineInputMethod < RelineInputMethod
+ def initialize
+ warn <<~MSG.strip
+ IRB::ReidlineInputMethod is deprecated, please use IRB::RelineInputMethod instead.
+ MSG
+ super
+ end
+ end
end
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
index c2f3b605db..d8c0ba90cf 100644
--- a/lib/irb/inspector.rb
+++ b/lib/irb/inspector.rb
@@ -108,18 +108,10 @@ module IRB # :nodoc:
Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
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
+ Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v))
}
- 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([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
+ IRB::ColorPrinter.pp(v, '').chomp
}
Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
begin
diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec
index e75592270a..c3e8a4dc58 100644
--- a/lib/irb/irb.gemspec
+++ b/lib/irb/irb.gemspec
@@ -8,8 +8,8 @@ end
Gem::Specification.new do |spec|
spec.name = "irb"
spec.version = IRB::VERSION
- spec.authors = ["Keiju ISHITSUKA"]
- spec.email = ["keiju@ruby-lang.org"]
+ spec.authors = ["aycabta", "Keiju ISHITSUKA"]
+ spec.email = ["aycabta@gmail.com", "keiju@ruby-lang.org"]
spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5")
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6")
- spec.add_dependency "reline", ">= 0.2.7"
+ spec.add_dependency "reline", ">= 0.3.0"
end
diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb
index 798994e92c..cb5c21cdb4 100644
--- a/lib/irb/lc/error.rb
+++ b/lib/irb/lc/error.rb
@@ -10,8 +10,9 @@
#
#
-# :stopdoc:
module IRB
+ # :stopdoc:
+
class UnrecognizedSwitch < StandardError
def initialize(val)
super("Unrecognized switch: #{val}")
@@ -47,11 +48,6 @@ module IRB
super("No such job(#{val}).")
end
end
- class CantShiftToMultiIrbMode < StandardError
- def initialize
- super("Can't shift to multi irb mode.")
- end
- end
class CantChangeBinding < StandardError
def initialize(val)
super("Can't change binding to (#{val}).")
@@ -67,5 +63,6 @@ module IRB
super("Define illegal RC_NAME_GENERATOR.")
end
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message
index 9c3ea859ad..5b23f4c41e 100644
--- a/lib/irb/lc/help-message
+++ b/lib/irb/lc/help-message
@@ -1,52 +1,51 @@
-# -*- coding: utf-8 -*-
-#
-# irb/lc/help-message.rb -
-# $Release Version: 0.9.6$
-# $Revision$
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-# --
-#
-#
-#
Usage: irb.rb [options] [programfile] [arguments]
- -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
- -U Same as `ruby -U`
- -E enc Same as `ruby -E`
- -w Same as `ruby -w`
- -W[level=2] Same as `ruby -W`
+ -f Don't initialize from configuration file.
+ -d Set $DEBUG and $VERBOSE to true (same as 'ruby -d').
+ -r load-module Require load-module (same as 'ruby -r').
+ -I path Specify $LOAD_PATH directory (same as 'ruby -I').
+ -U Set external and internal encodings to UTF-8.
+ -E ex[:in] Set default external (ex) and internal (in) encodings
+ (same as 'ruby -E').
+ -w Suppress warnings (same as 'ruby -w').
+ -W[level=2] Set warning level: 0=silence, 1=medium, 2=verbose
+ (same as 'ruby -W').
--context-mode n Set n[0-4] to method to create Binding Object,
- when new workspace was created
- --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
- --singleline Use singleline editor module
- --nosingleline Don't use singleline editor module
- --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'
+ when new workspace was created.
+ --extra-doc-dir Add an extra doc dir for the doc dialog.
+ --echo Show result (default).
+ --noecho Don't show result.
+ --echo-on-assignment
+ Show result on assignment.
+ --noecho-on-assignment
+ Don't show result on assignment.
+ --truncate-echo-on-assignment
+ Show truncated result on assignment (default).
+ --inspect Use 'inspect' for output.
+ --noinspect Don't use 'inspect' for output.
+ --multiline Use multiline editor module.
+ --nomultiline Don't use multiline editor module (default).
+ --singleline Use single line editor module.
+ --nosingleline Don't use single line editor module (default).
+ --colorize Use color-highlighting (default).
+ --nocolorize Don't use color-highlighting.
+ --autocomplete Use auto-completion (default).
+ --noautocomplete Don't use auto-completion.
+ --prompt prompt-mode, --prompt-mode prompt-mode
+ Set prompt mode. Pre-defined prompt modes are:
+ 'default', 'classic', 'simple', 'inf-ruby', 'xmp', 'null'.
--inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
Suppresses --multiline and --singleline.
- --sample-book-mode/--simple-prompt
- Simple prompt mode
- --noprompt No prompt mode
+ --sample-book-mode, --simple-prompt
+ Set prompt mode to 'simple'.
+ --noprompt Don't output prompt.
+ --script Script mode (default, treat first argument as script)
+ --noscript No script mode (leave arguments in argv)
--single-irb Share self with sub-irb.
- --tracer Display trace for each execution of commands.
- --back-trace-limit n
- 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
- -h, --help Print help
- -- Separate options of irb from the list of command-line args
-
-# vim:fileencoding=utf-8
+ --tracer Show stack trace for each command.
+ --back-trace-limit n[=16]
+ Display backtrace top n and bottom n.
+ --verbose Show details.
+ --noverbose Don't show details.
+ -v, --version Print the version of irb.
+ -h, --help Print help.
+ -- Separate options of irb from the list of command-line args.
diff --git a/lib/irb/lc/ja/encoding_aliases.rb b/lib/irb/lc/ja/encoding_aliases.rb
index c534bf0fef..08180c3ec2 100644
--- a/lib/irb/lc/ja/encoding_aliases.rb
+++ b/lib/irb/lc/ja/encoding_aliases.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: false
-# :stopdoc:
module IRB
+ # :stopdoc:
+
class Locale
@@legacy_encoding_alias_map = {
'ujis' => Encoding::EUC_JP,
'euc' => Encoding::EUC_JP
}.freeze
end
+
+ # :startdoc:
end
-# :startdoc:
diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb
index 31ebb3b5f0..5e3622cbae 100644
--- a/lib/irb/lc/ja/error.rb
+++ b/lib/irb/lc/ja/error.rb
@@ -10,8 +10,9 @@
#
#
-# :stopdoc:
module IRB
+ # :stopdoc:
+
class UnrecognizedSwitch < StandardError
def initialize(val)
super("スイッチ(#{val})が分りません")
@@ -47,11 +48,6 @@ module IRB
super("そのようなジョブ(#{val})はありません.")
end
end
- class CantShiftToMultiIrbMode < StandardError
- def initialize
- super("multi-irb modeに移れません.")
- end
- end
class CantChangeBinding < StandardError
def initialize(val)
super("バインディング(#{val})に変更できません.")
@@ -67,6 +63,7 @@ module IRB
super("RC_NAME_GENERATORが正しく定義されていません.")
end
end
+
+ # :startdoc:
end
-# :startdoc:
# vim:fileencoding=utf-8
diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message
index 9794a8e24e..1c15d331ea 100644
--- a/lib/irb/lc/ja/help-message
+++ b/lib/irb/lc/ja/help-message
@@ -1,13 +1,3 @@
-# -*- coding: utf-8 -*-
-# irb/lc/ja/help-message.rb -
-# $Release Version: 0.9.6$
-# $Revision$
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-# --
-#
-#
-#
Usage: irb.rb [options] [programfile] [arguments]
-f ~/.irbrc を読み込まない.
-d $DEBUG をtrueにする(ruby -d と同じ)
@@ -29,6 +19,8 @@ Usage: irb.rb [options] [programfile] [arguments]
--nosingleline シングルラインエディタを利用しない.
--colorize 色付けを利用する.
--nocolorize 色付けを利用しない.
+ --autocomplete オートコンプリートを利用する.
+ --noautocomplete オートコンプリートを利用しない.
--prompt prompt-mode/--prompt-mode prompt-mode
プロンプトモードを切替えます. 現在定義されているプ
ロンプトモードは, default, simple, xmp, inf-rubyが
@@ -51,5 +43,3 @@ Usage: irb.rb [options] [programfile] [arguments]
-v, --version irbのバージョンを表示する.
-h, --help irb のヘルプを表示する.
-- 以降のコマンドライン引数をオプションとして扱わない.
-
-# vim:fileencoding=utf-8
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index f744f36155..85b336fbe1 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -48,7 +48,7 @@ class RubyLex
end
# io functions
- def set_input(io, p = nil, context: nil, &block)
+ def set_input(io, p = nil, context:, &block)
@io = io
if @io.respond_to?(:check_termination)
@io.check_termination do |code|
@@ -65,6 +65,12 @@ class RubyLex
false
end
else
+ # Accept any single-line input for symbol aliases or commands that transform args
+ command = code.split(/\s/, 2).first
+ if context.symbol_alias?(command) || context.transform_args?(command)
+ next true
+ end
+
code.gsub!(/\s*\z/, '').concat("\n")
ltype, indent, continue, code_block_open = check_state(code, context: context)
if ltype or indent > 0 or continue or code_block_open
@@ -87,8 +93,8 @@ class RubyLex
tokens.each do |t|
partial_tokens << t
unprocessed_tokens << t
- if t[2].include?("\n")
- t_str = t[2]
+ if t.tok.include?("\n")
+ t_str = t.tok
t_str.each_line("\n") do |s|
code << s << "\n"
ltype, indent, continue, code_block_open = check_state(code, partial_tokens, context: context)
@@ -97,9 +103,10 @@ class RubyLex
end
unprocessed_tokens = []
else
- code << t[2]
+ code << t.tok
end
end
+
unless unprocessed_tokens.empty?
ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens, context: context)
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
@@ -107,6 +114,7 @@ class RubyLex
result
end
end
+
if p.respond_to?(:call)
@input = p
elsif block_given?
@@ -134,58 +142,54 @@ class RubyLex
:on_param_error
]
+ def self.generate_local_variables_assign_code(local_variables)
+ "#{local_variables.join('=')}=nil;" unless local_variables.empty?
+ end
+
def self.ripper_lex_without_warning(code, context: nil)
verbose, $VERBOSE = $VERBOSE, nil
- if context
- lvars = context&.workspace&.binding&.local_variables
- if lvars && !lvars.empty?
- code = "#{lvars.join('=')}=nil\n#{code}"
- line_no = 0
- else
- line_no = 1
- end
+ lvars_code = generate_local_variables_assign_code(context&.local_variables || [])
+ if lvars_code
+ code = "#{lvars_code}\n#{code}"
+ line_no = 0
+ else
+ line_no = 1
end
- tokens = nil
+
compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
lexer = Ripper::Lexer.new(inner_code, '-', line_no)
if lexer.respond_to?(:scan) # Ruby 2.7+
- tokens = []
- pos_to_index = {}
- lexer.scan.each do |t|
+ lexer.scan.each_with_object([]) do |t, tokens|
next if t.pos.first == 0
- 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
+ prev_tk = tokens.last
+ position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize
+ if position_overlapped
+ tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event)
else
- pos_to_index[t[0]] = tokens.size
tokens << t
end
end
else
- tokens = lexer.parse
+ lexer.parse.reject { |it| it.pos.first == 0 }.sort_by(&:pos)
end
end
- tokens
ensure
$VERBOSE = verbose
end
def find_prev_spaces(line_index)
return 0 if @tokens.size == 0
- md = @tokens[0][2].match(/(\A +)/)
+ md = @tokens[0].tok.match(/(\A +)/)
prev_spaces = md.nil? ? 0 : md[1].count(' ')
line_count = 0
@tokens.each_with_index do |t, i|
- if t[2].include?("\n")
- line_count += t[2].count("\n")
+ if t.tok.include?("\n")
+ line_count += t.tok.count("\n")
if line_count >= line_index
return prev_spaces
end
if (@tokens.size - 1) > i
- md = @tokens[i + 1][2].match(/(\A +)/)
+ md = @tokens[i + 1].tok.match(/(\A +)/)
prev_spaces = md.nil? ? 0 : md[1].count(' ')
end
end
@@ -207,12 +211,7 @@ class RubyLex
last_line = lines[line_index]&.byteslice(0, byte_pointer)
code += last_line if last_line
@tokens = self.class.ripper_lex_without_warning(code, context: context)
- corresponding_token_depth = check_corresponding_token_depth
- if corresponding_token_depth
- corresponding_token_depth
- else
- nil
- end
+ check_corresponding_token_depth(lines, line_index)
end
end
end
@@ -223,6 +222,8 @@ class RubyLex
ltype = process_literal_type(tokens)
indent = process_nesting_level(tokens)
continue = process_continue(tokens)
+ lvars_code = self.class.generate_local_variables_assign_code(context.local_variables)
+ code = "#{lvars_code}\n#{code}" if lvars_code
code_block_open = check_code_block(code, tokens)
[ltype, indent, continue, code_block_open]
end
@@ -242,13 +243,13 @@ class RubyLex
@code_block_open = false
end
- def each_top_level_statement
+ def each_top_level_statement(context)
initialize_input
catch(:TERM_INPUT) do
loop do
begin
prompt
- unless l = lex
+ unless l = lex(context)
throw :TERM_INPUT if @line == ''
else
@line_no += l.count("\n")
@@ -278,35 +279,32 @@ class RubyLex
end
end
- def lex
+ def lex(context)
line = @input.call
if @io.respond_to?(:check_termination)
return line # multiline
end
code = @line + (line.nil? ? '' : line)
code.gsub!(/\s*\z/, '').concat("\n")
- @tokens = self.class.ripper_lex_without_warning(code)
- @continue = process_continue
- @code_block_open = check_code_block(code)
- @indent = process_nesting_level
- @ltype = process_literal_type
+ @tokens = self.class.ripper_lex_without_warning(code, context: context)
+ @ltype, @indent, @continue, @code_block_open = check_state(code, @tokens, context: context)
line
end
def process_continue(tokens = @tokens)
# last token is always newline
- if tokens.size >= 2 and tokens[-2][1] == :on_regexp_end
+ if tokens.size >= 2 and tokens[-2].event == :on_regexp_end
# end of regexp literal
return false
- elsif tokens.size >= 2 and tokens[-2][1] == :on_semicolon
+ elsif tokens.size >= 2 and tokens[-2].event == :on_semicolon
return false
- elsif tokens.size >= 2 and tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2][2])
+ elsif tokens.size >= 2 and tokens[-2].event == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2].tok)
return false
- elsif !tokens.empty? and tokens.last[2] == "\\\n"
+ elsif !tokens.empty? and tokens.last.tok == "\\\n"
return true
- elsif tokens.size >= 1 and tokens[-1][1] == :on_heredoc_end # "EOH\n"
+ elsif tokens.size >= 1 and tokens[-1].event == :on_heredoc_end # "EOH\n"
return false
- elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2][2] !~ /\A\.\.\.?\z/
+ elsif tokens.size >= 2 and tokens[-2].state.anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2].tok !~ /\A\.\.\.?\z/
# end of literal except for regexp
# endless range at end of line is not a continue
return true
@@ -316,7 +314,7 @@ class RubyLex
def check_code_block(code, tokens = @tokens)
return true if tokens.empty?
- if tokens.last[1] == :on_heredoc_beg
+ if tokens.last.event == :on_heredoc_beg
return true
end
@@ -387,21 +385,20 @@ class RubyLex
$VERBOSE = verbose
end
- if defined?(Ripper::EXPR_BEG)
- last_lex_state = tokens.last[3]
- if last_lex_state.allbits?(Ripper::EXPR_BEG)
- return false
- elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_CLASS)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_FNAME)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_VALUE)
- return true
- elsif last_lex_state.allbits?(Ripper::EXPR_ARG)
- return false
- end
+ last_lex_state = tokens.last.state
+
+ if last_lex_state.allbits?(Ripper::EXPR_BEG)
+ return false
+ elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
+ return true
+ elsif last_lex_state.allbits?(Ripper::EXPR_CLASS)
+ return true
+ elsif last_lex_state.allbits?(Ripper::EXPR_FNAME)
+ return true
+ elsif last_lex_state.allbits?(Ripper::EXPR_VALUE)
+ return true
+ elsif last_lex_state.allbits?(Ripper::EXPR_ARG)
+ return false
end
false
@@ -413,14 +410,14 @@ class RubyLex
tokens.each_with_index { |t, index|
# detecting one-liner method definition
if in_oneliner_def.nil?
- if t[3].allbits?(Ripper::EXPR_ENDFN)
+ if t.state.allbits?(Ripper::EXPR_ENDFN)
in_oneliner_def = :ENDFN
end
else
- if t[3].allbits?(Ripper::EXPR_ENDFN)
+ if t.state.allbits?(Ripper::EXPR_ENDFN)
# continuing
- elsif t[3].allbits?(Ripper::EXPR_BEG)
- if t[2] == '='
+ elsif t.state.allbits?(Ripper::EXPR_BEG)
+ if t.tok == '='
in_oneliner_def = :BODY
end
else
@@ -432,14 +429,14 @@ class RubyLex
end
end
- case t[1]
+ case t.event
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
indent += 1
when :on_rbracket, :on_rbrace, :on_rparen
indent -= 1
when :on_kw
- next if index > 0 and tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
- case t[2]
+ next if index > 0 and tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
+ case t.tok
when 'do'
syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index)
indent += 1 if syntax_of_do == :method_calling
@@ -447,7 +444,7 @@ class RubyLex
indent += 1
when 'if', 'unless', 'while', 'until'
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
- indent += 1 unless t[3].allbits?(Ripper::EXPR_LABEL)
+ indent += 1 unless t.state.allbits?(Ripper::EXPR_LABEL)
when 'end'
indent -= 1
end
@@ -459,14 +456,14 @@ class RubyLex
def is_method_calling?(tokens, index)
tk = tokens[index]
- if tk[3].anybits?(Ripper::EXPR_CMDARG) and tk[1] == :on_ident
+ if tk.state.anybits?(Ripper::EXPR_CMDARG) and tk.event == :on_ident
# The target method call to pass the block with "do".
return true
- elsif tk[3].anybits?(Ripper::EXPR_ARG) and tk[1] == :on_ident
- non_sp_index = tokens[0..(index - 1)].rindex{ |t| t[1] != :on_sp }
+ elsif tk.state.anybits?(Ripper::EXPR_ARG) and tk.event == :on_ident
+ non_sp_index = tokens[0..(index - 1)].rindex{ |t| t.event != :on_sp }
if non_sp_index
prev_tk = tokens[non_sp_index]
- if prev_tk[3].anybits?(Ripper::EXPR_DOT) and prev_tk[1] == :on_period
+ if prev_tk.state.anybits?(Ripper::EXPR_DOT) and prev_tk.event == :on_period
# The target method call with receiver to pass the block with "do".
return true
end
@@ -477,21 +474,21 @@ class RubyLex
def take_corresponding_syntax_to_kw_do(tokens, index)
syntax_of_do = nil
- # Finding a syntax correnponding to "do".
+ # Finding a syntax corresponding to "do".
index.downto(0) do |i|
tk = tokens[i]
# In "continue", the token isn't the corresponding syntax to "do".
- non_sp_index = tokens[0..(i - 1)].rindex{ |t| t[1] != :on_sp }
+ non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
first_in_fomula = false
if non_sp_index.nil?
first_in_fomula = true
- elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index][1])
+ elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event)
first_in_fomula = true
end
if is_method_calling?(tokens, i)
syntax_of_do = :method_calling
break if first_in_fomula
- elsif tk[1] == :on_kw && %w{while until for}.include?(tk[2])
+ elsif tk.event == :on_kw && %w{while until for}.include?(tk.tok)
# A loop syntax in front of "do" found.
#
# while cond do # also "until" or "for"
@@ -508,18 +505,18 @@ class RubyLex
def is_the_in_correspond_to_a_for(tokens, index)
syntax_of_in = nil
- # Finding a syntax correnponding to "do".
+ # Finding a syntax corresponding to "do".
index.downto(0) do |i|
tk = tokens[i]
# In "continue", the token isn't the corresponding syntax to "do".
- non_sp_index = tokens[0..(i - 1)].rindex{ |t| t[1] != :on_sp }
+ non_sp_index = tokens[0..(i - 1)].rindex{ |t| t.event != :on_sp }
first_in_fomula = false
if non_sp_index.nil?
first_in_fomula = true
- elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index][1])
+ elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index].event)
first_in_fomula = true
end
- if tk[1] == :on_kw && tk[2] == 'for'
+ if tk.event == :on_kw && tk.tok == 'for'
# A loop syntax in front of "do" found.
#
# while cond do # also "until" or "for"
@@ -541,14 +538,14 @@ class RubyLex
@tokens.each_with_index do |t, index|
# detecting one-liner method definition
if in_oneliner_def.nil?
- if t[3].allbits?(Ripper::EXPR_ENDFN)
+ if t.state.allbits?(Ripper::EXPR_ENDFN)
in_oneliner_def = :ENDFN
end
else
- if t[3].allbits?(Ripper::EXPR_ENDFN)
+ if t.state.allbits?(Ripper::EXPR_ENDFN)
# continuing
- elsif t[3].allbits?(Ripper::EXPR_BEG)
- if t[2] == '='
+ elsif t.state.allbits?(Ripper::EXPR_BEG)
+ if t.tok == '='
in_oneliner_def = :BODY
end
else
@@ -560,7 +557,7 @@ class RubyLex
end
end
- case t[1]
+ case t.event
when :on_ignored_nl, :on_nl, :on_comment
if index != (@tokens.size - 1) and in_oneliner_def != :BODY
depth_difference = 0
@@ -570,15 +567,16 @@ class RubyLex
when :on_sp
next
end
- case t[1]
+
+ case t.event
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
depth_difference += 1
open_brace_on_line += 1
when :on_rbracket, :on_rbrace, :on_rparen
depth_difference -= 1 if open_brace_on_line > 0
when :on_kw
- next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
- case t[2]
+ next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
+ case t.tok
when 'do'
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
depth_difference += 1 if syntax_of_do == :method_calling
@@ -586,7 +584,7 @@ class RubyLex
depth_difference += 1
when 'if', 'unless', 'while', 'until', 'rescue'
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
- unless t[3].allbits?(Ripper::EXPR_LABEL)
+ unless t.state.allbits?(Ripper::EXPR_LABEL)
depth_difference += 1
end
when 'else', 'elsif', 'ensure', 'when'
@@ -603,7 +601,7 @@ class RubyLex
depth_difference
end
- def check_corresponding_token_depth
+ def check_corresponding_token_depth(lines, line_index)
corresponding_token_depth = nil
is_first_spaces_of_line = true
is_first_printable_of_line = true
@@ -611,17 +609,22 @@ class RubyLex
spaces_at_line_head = 0
open_brace_on_line = 0
in_oneliner_def = nil
+
+ if heredoc_scope?
+ return lines[line_index][/^ */].length
+ end
+
@tokens.each_with_index do |t, index|
# detecting one-liner method definition
if in_oneliner_def.nil?
- if t[3].allbits?(Ripper::EXPR_ENDFN)
+ if t.state.allbits?(Ripper::EXPR_ENDFN)
in_oneliner_def = :ENDFN
end
else
- if t[3].allbits?(Ripper::EXPR_ENDFN)
+ if t.state.allbits?(Ripper::EXPR_ENDFN)
# continuing
- elsif t[3].allbits?(Ripper::EXPR_BEG)
- if t[2] == '='
+ elsif t.state.allbits?(Ripper::EXPR_BEG)
+ if t.tok == '='
in_oneliner_def = :BODY
end
else
@@ -638,7 +641,7 @@ class RubyLex
end
end
- case t[1]
+ case t.event
when :on_ignored_nl, :on_nl, :on_comment
if in_oneliner_def != :BODY
corresponding_token_depth = nil
@@ -649,11 +652,12 @@ class RubyLex
end
next
when :on_sp
- spaces_at_line_head = t[2].count(' ') if is_first_spaces_of_line
+ spaces_at_line_head = t.tok.count(' ') if is_first_spaces_of_line
is_first_spaces_of_line = false
next
end
- case t[1]
+
+ case t.event
when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
open_brace_on_line += 1
@@ -666,8 +670,8 @@ class RubyLex
end
open_brace_on_line -= 1
when :on_kw
- next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
- case t[2]
+ next if index > 0 and @tokens[index - 1].state.allbits?(Ripper::EXPR_FNAME)
+ case t.tok
when 'do'
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
if syntax_of_do == :method_calling
@@ -676,16 +680,20 @@ class RubyLex
when 'def', 'case', 'for', 'begin', 'class', 'module'
spaces_of_nest.push(spaces_at_line_head)
when 'rescue'
- unless t[3].allbits?(Ripper::EXPR_LABEL)
+ unless t.state.allbits?(Ripper::EXPR_LABEL)
corresponding_token_depth = spaces_of_nest.last
end
when 'if', 'unless', 'while', 'until'
# postfix if/unless/while/until must be Ripper::EXPR_LABEL
- unless t[3].allbits?(Ripper::EXPR_LABEL)
+ unless t.state.allbits?(Ripper::EXPR_LABEL)
spaces_of_nest.push(spaces_at_line_head)
end
- when 'else', 'elsif', 'ensure', 'when', 'in'
+ when 'else', 'elsif', 'ensure', 'when'
corresponding_token_depth = spaces_of_nest.last
+ when 'in'
+ if in_keyword_case_scope?
+ corresponding_token_depth = spaces_of_nest.last
+ end
when 'end'
if is_first_printable_of_line
corresponding_token_depth = spaces_of_nest.pop
@@ -705,9 +713,13 @@ class RubyLex
i = 0
start_token = []
end_type = []
+ pending_heredocs = []
while i < tokens.size
t = tokens[i]
- case t[1]
+ case t.event
+ when *end_type.last
+ start_token.pop
+ end_type.pop
when :on_tstring_beg
start_token << t
end_type << [:on_tstring_end, :on_label_end]
@@ -715,34 +727,46 @@ class RubyLex
start_token << t
end_type << :on_regexp_end
when :on_symbeg
- acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int}
- if (i + 1) < tokens.size and acceptable_single_tokens.all?{ |st| tokens[i + 1][1] != st }
+ acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int on_backtick}
+ if (i + 1) < tokens.size
+ if acceptable_single_tokens.all?{ |st| tokens[i + 1].event != st }
+ start_token << t
+ end_type << :on_tstring_end
+ else
+ i += 1
+ end
+ end
+ when :on_backtick
+ if t.state.allbits?(Ripper::EXPR_BEG)
start_token << t
end_type << :on_tstring_end
end
- when :on_backtick
- start_token << t
- end_type << :on_tstring_end
when :on_qwords_beg, :on_words_beg, :on_qsymbols_beg, :on_symbols_beg
start_token << t
end_type << :on_tstring_end
when :on_heredoc_beg
- start_token << t
- end_type << :on_heredoc_end
- when *end_type.last
- start_token.pop
- end_type.pop
+ pending_heredocs << t
+ end
+
+ if pending_heredocs.any? && t.tok.include?("\n")
+ pending_heredocs.reverse_each do |t|
+ start_token << t
+ end_type << :on_heredoc_end
+ end
+ pending_heredocs = []
end
i += 1
end
- start_token.last.nil? ? '' : start_token.last
+ pending_heredocs.first || start_token.last
end
def process_literal_type(tokens = @tokens)
start_token = check_string_literal(tokens)
- case start_token[1]
+ return nil if start_token == ""
+
+ case start_token&.event
when :on_tstring_beg
- case start_token[2]
+ case start_token&.tok
when ?" then ?"
when /^%.$/ then ?"
when /^%Q.$/ then ?"
@@ -757,7 +781,7 @@ class RubyLex
when :on_qsymbols_beg then ?]
when :on_symbols_beg then ?]
when :on_heredoc_beg
- start_token[2] =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/
+ start_token&.tok =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/
case $1
when ?" then ?"
when ?' then ?'
@@ -785,6 +809,7 @@ class RubyLex
false
end
end
+
if index
first_token = nil
last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
@@ -794,6 +819,7 @@ class RubyLex
break
end
end
+
if first_token.nil?
return false
elsif first_token && first_token.state == Ripper::EXPR_DOT
@@ -813,5 +839,28 @@ class RubyLex
end
false
end
+
+ private
+
+ def heredoc_scope?
+ heredoc_tokens = @tokens.select { |t| [:on_heredoc_beg, :on_heredoc_end].include?(t.event) }
+ heredoc_tokens[-1]&.event == :on_heredoc_beg
+ end
+
+ def in_keyword_case_scope?
+ kw_tokens = @tokens.select { |t| t.event == :on_kw && ['case', 'for', 'end'].include?(t.tok) }
+ counter = 0
+ kw_tokens.reverse.each do |t|
+ if t.tok == 'case'
+ return true if counter.zero?
+ counter += 1
+ elsif t.tok == 'for'
+ counter += 1
+ elsif t.tok == 'end'
+ counter -= 1
+ end
+ end
+ false
+ end
end
# :startdoc:
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
index 7d83421b2b..d1c0e54fdc 100644
--- a/lib/irb/version.rb
+++ b/lib/irb/version.rb
@@ -11,7 +11,7 @@
#
module IRB # :nodoc:
- VERSION = "1.3.7"
+ VERSION = "1.6.2"
@RELEASE_VERSION = VERSION
- @LAST_UPDATE_DATE = "2021-08-12"
+ @LAST_UPDATE_DATE = "2022-12-13"
end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
index 78d434d106..e5ef52528a 100644
--- a/lib/irb/workspace.rb
+++ b/lib/irb/workspace.rb
@@ -12,6 +12,7 @@
require "delegate"
+IRB::TOPLEVEL_BINDING = binding
module IRB # :nodoc:
class WorkSpace
# Creates a new workspace.
@@ -57,6 +58,8 @@ EOF
__FILE__,
__LINE__ - 3)
when 4 # binding is a copy of TOPLEVEL_BINDING (default)
+ # Note that this will typically be IRB::TOPLEVEL_BINDING
+ # This is to avoid RubyGems' local variables (see issue #17623)
@binding = TOPLEVEL_BINDING.dup
end
end
@@ -155,27 +158,20 @@ EOF
end
end
- # NOT using #use_colorize? of IRB.conf[:MAIN_CONTEXT] because this method may be called before IRB::Irb#run
- use_colorize = IRB.conf.fetch(:USE_COLORIZE, true)
- if use_colorize
- lines = Color.colorize_code(code).lines
- else
- lines = code.lines
- end
+ lines = Color.colorize_code(code).lines
pos -= 1
start_pos = [pos - 5, 0].max
end_pos = [pos + 5, lines.size - 1].min
- if use_colorize
- fmt = " %2s #{Color.colorize("%#{end_pos.to_s.length}d", [:BLUE, :BOLD])}: %s"
- else
- fmt = " %2s %#{end_pos.to_s.length}d: %s"
- end
+ line_number_fmt = Color.colorize("%#{end_pos.to_s.length}d", [:BLUE, :BOLD])
+ fmt = " %2s #{line_number_fmt}: %s"
+
body = (start_pos..end_pos).map do |current_pos|
sprintf(fmt, pos == current_pos ? '=>' : '', current_pos + 1, lines[current_pos])
end.join("")
- "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear if use_colorize}\n"
+
+ "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
end
def IRB.delete_caller
diff --git a/lib/logger.rb b/lib/logger.rb
index 4205380a6a..7e4dacc911 100644
--- a/lib/logger.rb
+++ b/lib/logger.rb
@@ -11,6 +11,7 @@
# A simple system for logging messages. See Logger for more documentation.
require 'monitor'
+require 'rbconfig'
require_relative 'logger/version'
require_relative 'logger/formatter'
@@ -18,216 +19,353 @@ require_relative 'logger/log_device'
require_relative 'logger/severity'
require_relative 'logger/errors'
-# == Description
+# \Class \Logger provides a simple but sophisticated logging utility that
+# you can use to create one or more
+# {event logs}[https://en.wikipedia.org/wiki/Logging_(software)#Event_logs]
+# for your program.
+# Each such log contains a chronological sequence of entries
+# that provides a record of the program's activities.
#
-# The Logger class provides a simple but sophisticated logging utility that
-# you can use to output messages.
+# == About the Examples
#
-# The messages have associated levels, such as +INFO+ or +ERROR+ that indicate
-# their importance. You can then give the Logger a level, and only messages
-# at that level or higher will be printed.
+# All examples on this page assume that \Logger has been required:
#
-# The levels are:
+# require 'logger'
#
-# +UNKNOWN+:: An unknown message that should always be logged.
-# +FATAL+:: An unhandleable error that results in a program crash.
-# +ERROR+:: A handleable error condition.
-# +WARN+:: A warning.
-# +INFO+:: Generic (useful) information about system operation.
-# +DEBUG+:: Low-level information for developers.
+# == Synopsis
#
-# For instance, in a production system, you may have your Logger set to
-# +INFO+ or even +WARN+.
-# When you are developing the system, however, you probably
-# want to know about the program's internal state, and would set the Logger to
-# +DEBUG+.
+# Create a log with Logger.new:
#
-# *Note*: Logger does not escape or sanitize any messages passed to it.
-# Developers should be aware of when potentially malicious data (user-input)
-# is passed to Logger, and manually escape the untrusted data:
+# # Single log file.
+# logger = Logger.new('t.log')
+# # Size-based rotated logging: 3 10-megabyte files.
+# logger = Logger.new('t.log', 3, 10485760)
+# # Period-based rotated logging: daily (also allowed: 'weekly', 'monthly').
+# logger = Logger.new('t.log', 'daily')
+# # Log to an IO stream.
+# logger = Logger.new($stdout)
#
-# logger.info("User-input: #{input.dump}")
-# logger.info("User-input: %p" % input)
+# Add entries (level, message) with Logger#add:
#
-# You can use #formatter= for escaping all data.
+# logger.add(Logger::DEBUG, 'Maximal debugging info')
+# logger.add(Logger::INFO, 'Non-error information')
+# logger.add(Logger::WARN, 'Non-error warning')
+# logger.add(Logger::ERROR, 'Non-fatal error')
+# logger.add(Logger::FATAL, 'Fatal error')
+# logger.add(Logger::UNKNOWN, 'Most severe')
#
-# original_formatter = Logger::Formatter.new
-# logger.formatter = proc { |severity, datetime, progname, msg|
-# original_formatter.call(severity, datetime, progname, msg.dump)
-# }
-# logger.info(input)
+# Close the log with Logger#close:
#
-# === Example
+# logger.close
#
-# This creates a Logger that outputs to the standard output stream, with a
-# level of +WARN+:
+# == Entries
#
-# require 'logger'
+# You can add entries with method Logger#add:
+#
+# logger.add(Logger::DEBUG, 'Maximal debugging info')
+# logger.add(Logger::INFO, 'Non-error information')
+# logger.add(Logger::WARN, 'Non-error warning')
+# logger.add(Logger::ERROR, 'Non-fatal error')
+# logger.add(Logger::FATAL, 'Fatal error')
+# logger.add(Logger::UNKNOWN, 'Most severe')
+#
+# These shorthand methods also add entries:
+#
+# logger.debug('Maximal debugging info')
+# logger.info('Non-error information')
+# logger.warn('Non-error warning')
+# logger.error('Non-fatal error')
+# logger.fatal('Fatal error')
+# logger.unknown('Most severe')
+#
+# When you call any of these methods,
+# the entry may or may not be written to the log,
+# depending on the entry's severity and on the log level;
+# see {Log Level}[rdoc-ref:Logger@Log+Level]
+#
+# An entry always has:
+#
+# - A severity (the required argument to #add).
+# - An automatically created timestamp.
+#
+# And may also have:
+#
+# - A message.
+# - A program name.
+#
+# Example:
+#
+# logger = Logger.new($stdout)
+# logger.add(Logger::INFO, 'My message.', 'mung')
+# # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- mung: My message.
+#
+# The default format for an entry is:
+#
+# "%s, [%s #%d] %5s -- %s: %s\n"
+#
+# where the values to be formatted are:
+#
+# - \Severity (one letter).
+# - Timestamp.
+# - Process id.
+# - \Severity (word).
+# - Program name.
+# - Message.
+#
+# You can use a different entry format by:
+#
+# - Setting a custom format proc (affects following entries);
+# see {formatter=}[Logger.html#attribute-i-formatter].
+# - Calling any of the methods above with a block
+# (affects only the one entry).
+# Doing so can have two benefits:
+#
+# - Context: the block can evaluate the entire program context
+# and create a context-dependent message.
+# - Performance: the block is not evaluated unless the log level
+# permits the entry actually to be written:
+#
+# logger.error { my_slow_message_generator }
+#
+# Contrast this with the string form, where the string is
+# always evaluated, regardless of the log level:
+#
+# logger.error("#{my_slow_message_generator}")
+#
+# === \Severity
+#
+# The severity of a log entry has two effects:
+#
+# - Determines whether the entry is selected for inclusion in the log;
+# see {Log Level}[rdoc-ref:Logger@Log+Level].
+# - Indicates to any log reader (whether a person or a program)
+# the relative importance of the entry.
+#
+# === Timestamp
#
-# logger = Logger.new(STDOUT)
-# logger.level = Logger::WARN
+# The timestamp for a log entry is generated automatically
+# when the entry is created.
#
-# logger.debug("Created logger")
-# logger.info("Program started")
-# logger.warn("Nothing to do!")
+# The logged timestamp is formatted by method
+# {Time#strftime}[rdoc-ref:Time#strftime]
+# using this format string:
#
-# path = "a_non_existent_file"
+# '%Y-%m-%dT%H:%M:%S.%6N'
#
-# begin
-# File.foreach(path) do |line|
-# unless line =~ /^(\w+) = (.*)$/
-# logger.error("Line in wrong format: #{line.chomp}")
-# end
-# end
-# rescue => err
-# logger.fatal("Caught exception; exiting")
-# logger.fatal(err)
-# end
+# Example:
#
-# Because the Logger's level is set to +WARN+, only the warning, error, and
-# fatal messages are recorded. The debug and info messages are silently
-# discarded.
+# logger = Logger.new($stdout)
+# logger.add(Logger::INFO)
+# # => I, [2022-05-07T17:04:32.318331 #20536] INFO -- : nil
#
-# === Features
+# You can set a different format using method #datetime_format=.
#
-# There are several interesting features that Logger provides, like
-# auto-rolling of log files, setting the format of log messages, and
-# specifying a program name in conjunction with the message. The next section
-# shows you how to achieve these things.
+# === Message
#
+# The message is an optional argument to an entry method:
#
-# == HOWTOs
+# logger = Logger.new($stdout)
+# logger.add(Logger::INFO, 'My message')
+# # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message
#
-# === How to create a logger
+# For the default entry formatter, <tt>Logger::Formatter</tt>,
+# the message object may be:
#
-# The options below give you various choices, in more or less increasing
-# complexity.
+# - A string: used as-is.
+# - An Exception: <tt>message.message</tt> is used.
+# - Anything else: <tt>message.inspect</tt> is used.
#
-# 1. Create a logger which logs messages to STDERR/STDOUT.
+# *Note*: Logger::Formatter does not escape or sanitize
+# the message passed to it.
+# Developers should be aware that malicious data (user input)
+# may be in the message, and should explicitly escape untrusted data.
#
-# logger = Logger.new(STDERR)
-# logger = Logger.new(STDOUT)
+# You can use a custom formatter to escape message data;
+# see the example at {formatter=}[Logger.html#attribute-i-formatter].
#
-# 2. Create a logger for the file which has the specified name.
+# === Program Name
#
-# logger = Logger.new('logfile.log')
+# The program name is an optional argument to an entry method:
#
-# 3. Create a logger for the specified file.
+# logger = Logger.new($stdout)
+# logger.add(Logger::INFO, 'My message', 'mung')
+# # => I, [2022-05-07T18:17:38.084716 #20536] INFO -- mung: My message
#
-# file = File.open('foo.log', File::WRONLY | File::APPEND)
-# # To create new logfile, add File::CREAT like:
-# # file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT)
-# logger = Logger.new(file)
+# The default program name for a new logger may be set in the call to
+# Logger.new via optional keyword argument +progname+:
#
-# 4. Create a logger which ages the logfile once it reaches a certain size.
-# Leave 10 "old" log files where each file is about 1,024,000 bytes.
+# logger = Logger.new('t.log', progname: 'mung')
#
-# logger = Logger.new('foo.log', 10, 1024000)
+# The default program name for an existing logger may be set
+# by a call to method #progname=:
#
-# 5. Create a logger which ages the logfile daily/weekly/monthly.
+# logger.progname = 'mung'
#
-# logger = Logger.new('foo.log', 'daily')
-# logger = Logger.new('foo.log', 'weekly')
-# logger = Logger.new('foo.log', 'monthly')
+# The current program name may be retrieved with method
+# {progname}[Logger.html#attribute-i-progname]:
#
-# === How to log a message
+# logger.progname # => "mung"
#
-# Notice the different methods (+fatal+, +error+, +info+) being used to log
-# messages of various levels? Other methods in this family are +warn+ and
-# +debug+. +add+ is used below to log a message of an arbitrary (perhaps
-# dynamic) level.
+# == Log Level
#
-# 1. Message in a block.
+# The log level setting determines whether an entry is actually
+# written to the log, based on the entry's severity.
#
-# logger.fatal { "Argument 'foo' not given." }
+# These are the defined severities (least severe to most severe):
#
-# 2. Message as a string.
+# logger = Logger.new($stdout)
+# logger.add(Logger::DEBUG, 'Maximal debugging info')
+# # => D, [2022-05-07T17:57:41.776220 #20536] DEBUG -- : Maximal debugging info
+# logger.add(Logger::INFO, 'Non-error information')
+# # => I, [2022-05-07T17:59:14.349167 #20536] INFO -- : Non-error information
+# logger.add(Logger::WARN, 'Non-error warning')
+# # => W, [2022-05-07T18:00:45.337538 #20536] WARN -- : Non-error warning
+# logger.add(Logger::ERROR, 'Non-fatal error')
+# # => E, [2022-05-07T18:02:41.592912 #20536] ERROR -- : Non-fatal error
+# logger.add(Logger::FATAL, 'Fatal error')
+# # => F, [2022-05-07T18:05:24.703931 #20536] FATAL -- : Fatal error
+# logger.add(Logger::UNKNOWN, 'Most severe')
+# # => A, [2022-05-07T18:07:54.657491 #20536] ANY -- : Most severe
#
-# logger.error "Argument #{@foo} mismatch."
+# The default initial level setting is Logger::DEBUG, the lowest level,
+# which means that all entries are to be written, regardless of severity:
#
-# 3. With progname.
+# logger = Logger.new($stdout)
+# logger.level # => 0
+# logger.add(0, "My message")
+# # => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message
#
-# logger.info('initialize') { "Initializing..." }
+# You can specify a different setting in a new logger
+# using keyword argument +level+ with an appropriate value:
#
-# 4. With severity.
+# logger = Logger.new($stdout, level: Logger::ERROR)
+# logger = Logger.new($stdout, level: 'error')
+# logger = Logger.new($stdout, level: :error)
+# logger.level # => 3
#
-# logger.add(Logger::FATAL) { 'Fatal error!' }
+# With this level, entries with severity Logger::ERROR and higher
+# are written, while those with lower severities are not written:
#
-# The block form allows you to create potentially complex log messages,
-# but to delay their evaluation until and unless the message is
-# logged. For example, if we have the following:
+# logger = Logger.new($stdout, level: Logger::ERROR)
+# logger.add(3)
+# # => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil
+# logger.add(2) # Silent.
#
-# logger.debug { "This is a " + potentially + " expensive operation" }
+# You can set the log level for an existing logger
+# with method #level=:
#
-# If the logger's level is +INFO+ or higher, no debug messages will be logged,
-# and the entire block will not even be evaluated. Compare to this:
+# logger.level = Logger::ERROR
#
-# logger.debug("This is a " + potentially + " expensive operation")
+# These shorthand methods also set the level:
#
-# Here, the string concatenation is done every time, even if the log
-# level is not set to show the debug message.
+# logger.debug! # => 0
+# logger.info! # => 1
+# logger.warn! # => 2
+# logger.error! # => 3
+# logger.fatal! # => 4
#
-# === How to close a logger
+# You can retrieve the log level with method
+# {level}[Logger.html#attribute-i-level]:
#
-# logger.close
+# logger.level = Logger::ERROR
+# logger.level # => 3
#
-# === Setting severity threshold
+# These methods return whether a given
+# level is to be written:
#
-# 1. Original interface.
+# logger.level = Logger::ERROR
+# logger.debug? # => false
+# logger.info? # => false
+# logger.warn? # => false
+# logger.error? # => true
+# logger.fatal? # => true
#
-# logger.sev_threshold = Logger::WARN
+# == Log File Rotation
#
-# 2. Log4r (somewhat) compatible interface.
+# By default, a log file is a single file that grows indefinitely
+# (until explicitly closed); there is no file rotation.
#
-# logger.level = Logger::INFO
+# To keep log files to a manageable size,
+# you can use _log_ _file_ _rotation_, which uses multiple log files:
#
-# # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
+# - Each log file has entries for a non-overlapping
+# time interval.
+# - Only the most recent log file is open and active;
+# the others are closed and inactive.
#
-# 3. Symbol or String (case insensitive)
+# === Size-Based Rotation
#
-# logger.level = :info
-# logger.level = 'INFO'
+# For size-based log file rotation, call Logger.new with:
#
-# # :debug < :info < :warn < :error < :fatal < :unknown
+# - Argument +logdev+ as a file path.
+# - Argument +shift_age+ with a positive integer:
+# the number of log files to be in the rotation.
+# - Argument +shift_size+ as a positive integer:
+# the maximum size (in bytes) of each log file;
+# defaults to 1048576 (1 megabyte).
#
-# 4. Constructor
+# Examples:
#
-# Logger.new(logdev, level: Logger::INFO)
-# Logger.new(logdev, level: :info)
-# Logger.new(logdev, level: 'INFO')
+# logger = Logger.new('t.log', 3) # Three 1-megabyte files.
+# logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files.
#
-# == Format
+# For these examples, suppose:
#
-# Log messages are rendered in the output stream in a certain format by
-# default. The default format and a sample are shown below:
+# logger = Logger.new('t.log', 3)
#
-# Log format:
-# SeverityID, [DateTime #pid] SeverityLabel -- ProgName: message
+# Logging begins in the new log file, +t.log+;
+# the log file is "full" and ready for rotation
+# when a new entry would cause its size to exceed +shift_size+.
#
-# Log sample:
-# I, [1999-03-03T02:34:24.895701 #19074] INFO -- Main: info.
+# The first time +t.log+ is full:
#
-# You may change the date and time format via #datetime_format=.
+# - +t.log+ is closed and renamed to +t.log.0+.
+# - A new file +t.log+ is opened.
#
-# logger.datetime_format = '%Y-%m-%d %H:%M:%S'
-# # e.g. "2004-01-03 00:54:26"
+# The second time +t.log+ is full:
#
-# or via the constructor.
+# - +t.log.0 is renamed as +t.log.1+.
+# - +t.log+ is closed and renamed to +t.log.0+.
+# - A new file +t.log+ is opened.
#
-# Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
+# Each subsequent time that +t.log+ is full,
+# the log files are rotated:
#
-# Or, you may change the overall format via the #formatter= method.
+# - +t.log.1+ is removed.
+# - +t.log.0 is renamed as +t.log.1+.
+# - +t.log+ is closed and renamed to +t.log.0+.
+# - A new file +t.log+ is opened.
#
-# logger.formatter = proc do |severity, datetime, progname, msg|
-# "#{datetime}: #{msg}\n"
-# end
-# # e.g. "2005-09-22 08:51:08 +0900: hello world"
+# === Periodic Rotation
#
-# or via the constructor.
+# For periodic rotation, call Logger.new with:
#
-# Logger.new(logdev, formatter: proc {|severity, datetime, progname, msg|
-# "#{datetime}: #{msg}\n"
-# })
+# - Argument +logdev+ as a file path.
+# - Argument +shift_age+ as a string period indicator.
+#
+# Examples:
+#
+# logger = Logger.new('t.log', 'daily') # Rotate log files daily.
+# logger = Logger.new('t.log', 'weekly') # Rotate log files weekly.
+# logger = Logger.new('t.log', 'monthly') # Rotate log files monthly.
+#
+# Example:
+#
+# logger = Logger.new('t.log', 'daily')
+#
+# When the given period expires:
+#
+# - The base log file, +t.log+ is closed and renamed
+# with a date-based suffix such as +t.log.20220509+.
+# - A new log file +t.log+ is opened.
+# - Nothing is removed.
+#
+# The default format for the suffix is <tt>'%Y%m%d'</tt>,
+# which produces a suffix similar to the one above.
+# You can set a different format using create-time option
+# +shift_period_suffix+;
+# see details and suggestions at
+# {Time#strftime}[rdoc-ref:Time#strftime].
#
class Logger
_, name, rev = %w$Id$
@@ -244,9 +382,18 @@ class Logger
# Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
attr_reader :level
- # Set logging severity threshold.
+ # Sets the log level; returns +severity+.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
+ # Argument +severity+ may be an integer, a string, or a symbol:
+ #
+ # logger.level = Logger::ERROR # => 3
+ # logger.level = 3 # => 3
+ # logger.level = 'error' # => "error"
+ # logger.level = :error # => :error
+ #
+ # Logger#sev_threshold= is an alias for Logger#level=.
#
- # +severity+:: The Severity of the log message.
def level=(severity)
if severity.is_a?(Integer)
@level = severity
@@ -273,109 +420,159 @@ class Logger
# Program name to include in log messages.
attr_accessor :progname
- # Set date-time format.
+ # Sets the date-time format.
+ #
+ # Argument +datetime_format+ should be either of these:
+ #
+ # - A string suitable for use as a format for method
+ # {Time#strftime}[rdoc-ref:Time#strftime].
+ # - +nil+: the logger uses <tt>'%Y-%m-%dT%H:%M:%S.%6N'</tt>.
#
- # +datetime_format+:: A string suitable for passing to +strftime+.
def datetime_format=(datetime_format)
@default_formatter.datetime_format = datetime_format
end
- # Returns the date format being used. See #datetime_format=
+ # Returns the date-time format; see #datetime_format=.
+ #
def datetime_format
@default_formatter.datetime_format
end
- # Logging formatter, as a +Proc+ that will take four arguments and
- # return the formatted message. The arguments are:
+ # Sets or retrieves the logger entry formatter proc.
#
- # +severity+:: The Severity of the log message.
- # +time+:: A Time instance representing when the message was logged.
- # +progname+:: The #progname configured, or passed to the logger method.
- # +msg+:: The _Object_ the user passed to the log message; not necessarily a
- # String.
+ # When +formatter+ is +nil+, the logger uses Logger::Formatter.
+ #
+ # When +formatter+ is a proc, a new entry is formatted by the proc,
+ # which is called with four arguments:
+ #
+ # - +severity+: The severity of the entry.
+ # - +time+: A Time object representing the entry's timestamp.
+ # - +progname+: The program name for the entry.
+ # - +msg+: The message for the entry (string or string-convertible object).
+ #
+ # The proc should return a string containing the formatted entry.
+ #
+ # This custom formatter uses
+ # {String#dump}[rdoc-ref:String#dump]
+ # to escape the message string:
+ #
+ # logger = Logger.new($stdout, progname: 'mung')
+ # original_formatter = logger.formatter || Logger::Formatter.new
+ # logger.formatter = proc { |severity, time, progname, msg|
+ # original_formatter.call(severity, time, progname, msg.dump)
+ # }
+ # logger.add(Logger::INFO, "hello \n ''")
+ # logger.add(Logger::INFO, "\f\x00\xff\\\"")
+ #
+ # Output:
+ #
+ # I, [2022-05-13T13:16:29.637488 #8492] INFO -- mung: "hello \n ''"
+ # I, [2022-05-13T13:16:29.637610 #8492] INFO -- mung: "\f\x00\xFF\\\""
#
- # The block should return an Object that can be written to the logging
- # device via +write+. The default formatter is used when no formatter is
- # set.
attr_accessor :formatter
alias sev_threshold level
alias sev_threshold= level=
- # Returns +true+ if and only if the current severity level allows for the printing of
- # +DEBUG+ messages.
+ # Returns +true+ if the log level allows entries with severity
+ # Logger::DEBUG to be written, +false+ otherwise.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def debug?; level <= DEBUG; end
- # Sets the severity to DEBUG.
+ # Sets the log level to Logger::DEBUG.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def debug!; self.level = DEBUG; end
- # Returns +true+ if and only if the current severity level allows for the printing of
- # +INFO+ messages.
+ # Returns +true+ if the log level allows entries with severity
+ # Logger::INFO to be written, +false+ otherwise.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def info?; level <= INFO; end
- # Sets the severity to INFO.
+ # Sets the log level to Logger::INFO.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def info!; self.level = INFO; end
- # Returns +true+ if and only if the current severity level allows for the printing of
- # +WARN+ messages.
+ # Returns +true+ if the log level allows entries with severity
+ # Logger::WARN to be written, +false+ otherwise.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def warn?; level <= WARN; end
- # Sets the severity to WARN.
+ # Sets the log level to Logger::WARN.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def warn!; self.level = WARN; end
- # Returns +true+ if and only if the current severity level allows for the printing of
- # +ERROR+ messages.
+ # Returns +true+ if the log level allows entries with severity
+ # Logger::ERROR to be written, +false+ otherwise.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def error?; level <= ERROR; end
- # Sets the severity to ERROR.
+ # Sets the log level to Logger::ERROR.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def error!; self.level = ERROR; end
- # Returns +true+ if and only if the current severity level allows for the printing of
- # +FATAL+ messages.
+ # Returns +true+ if the log level allows entries with severity
+ # Logger::FATAL to be written, +false+ otherwise.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def fatal?; level <= FATAL; end
- # Sets the severity to FATAL.
+ # Sets the log level to Logger::FATAL.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
+ #
def fatal!; self.level = FATAL; end
- #
# :call-seq:
- # Logger.new(logdev, shift_age = 0, shift_size = 1048576)
- # Logger.new(logdev, shift_age = 'weekly')
- # Logger.new(logdev, level: :info)
- # Logger.new(logdev, progname: 'progname')
- # Logger.new(logdev, formatter: formatter)
- # Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
- #
- # === Args
- #
- # +logdev+::
- # 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
- # rotation.
- # +shift_size+::
- # Maximum logfile size in bytes (only applies when +shift_age+ is a positive
- # Integer). Defaults to +1048576+ (1MB).
- # +level+::
- # Logging severity threshold. Default values is Logger::DEBUG.
- # +progname+::
- # Program name to include in log messages. Default value is nil.
- # +formatter+::
- # Logging formatter. Default values is an instance of Logger::Formatter.
- # +datetime_format+::
- # Date and time format. Default value is '%Y-%m-%d %H:%M:%S'.
- # +binmode+::
- # Use binary mode on the log device. Default value is false.
- # +shift_period_suffix+::
- # The log file suffix format for +daily+, +weekly+ or +monthly+ rotation.
- # Default is '%Y%m%d'.
- #
- # === Description
- #
- # Create an instance.
+ # Logger.new(logdev, shift_age = 0, shift_size = 1048576, **options)
+ #
+ # With the single argument +logdev+,
+ # returns a new logger with all default options:
+ #
+ # Logger.new('t.log') # => #<Logger:0x000001e685dc6ac8>
+ #
+ # Argument +logdev+ must be one of:
+ #
+ # - A string filepath: entries are to be written
+ # to the file at that path; if the file at that path exists,
+ # new entries are appended.
+ # - An IO stream (typically +$stdout+, +$stderr+. or an open file):
+ # entries are to be written to the given stream.
+ # - +nil+ or +File::NULL+: no entries are to be written.
+ #
+ # Examples:
+ #
+ # Logger.new('t.log')
+ # Logger.new($stdout)
+ #
+ # The keyword options are:
+ #
+ # - +level+: sets the log level; default value is Logger::DEBUG.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level]:
+ #
+ # Logger.new('t.log', level: Logger::ERROR)
+ #
+ # - +progname+: sets the default program name; default is +nil+.
+ # See {Program Name}[rdoc-ref:Logger@Program+Name]:
+ #
+ # Logger.new('t.log', progname: 'mung')
+ #
+ # - +formatter+: sets the entry formatter; default is +nil+.
+ # See {formatter=}[Logger.html#attribute-i-formatter].
+ # - +datetime_format+: sets the format for entry timestamp;
+ # default is +nil+.
+ # See #datetime_format=.
+ # - +binmode+: sets whether the logger writes in binary mode;
+ # default is +false+.
+ # - +shift_period_suffix+: sets the format for the filename suffix
+ # for periodic log file rotation; default is <tt>'%Y%m%d'</tt>.
+ # See {Periodic Rotation}[rdoc-ref:Logger@Periodic+Rotation].
#
def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
progname: nil, formatter: nil, datetime_format: nil,
@@ -394,67 +591,60 @@ class Logger
end
end
- #
- # :call-seq:
- # Logger#reopen
- # Logger#reopen(logdev)
- #
- # === Args
- #
- # +logdev+::
- # The log device. This is a filename (String) or IO object (typically
- # +STDOUT+, +STDERR+, or an open file). reopen the same filename if
- # it is +nil+, do nothing for IO. Default is +nil+.
- #
- # === Description
- #
- # Reopen a log device.
+ # Sets the logger's output stream:
+ #
+ # - If +logdev+ is +nil+, reopens the current output stream.
+ # - If +logdev+ is a filepath, opens the indicated file for append.
+ # - If +logdev+ is an IO stream
+ # (usually <tt>$stdout</tt>, <tt>$stderr</tt>, or an open File object),
+ # opens the stream for append.
+ #
+ # Example:
+ #
+ # logger = Logger.new('t.log')
+ # logger.add(Logger::ERROR, 'one')
+ # logger.close
+ # logger.add(Logger::ERROR, 'two') # Prints 'log writing failed. closed stream'
+ # logger.reopen
+ # logger.add(Logger::ERROR, 'three')
+ # logger.close
+ # File.readlines('t.log')
+ # # =>
+ # # ["# Logfile created on 2022-05-12 14:21:19 -0500 by logger.rb/v1.5.0\n",
+ # # "E, [2022-05-12T14:21:27.596726 #22428] ERROR -- : one\n",
+ # # "E, [2022-05-12T14:23:05.847241 #22428] ERROR -- : three\n"]
#
def reopen(logdev = nil)
@logdev&.reopen(logdev)
self
end
+ # Creates a log entry, which may or may not be written to the log,
+ # depending on the entry's severity and on the log level.
+ # See {Log Level}[rdoc-ref:Logger@Log+Level]
+ # and {Entries}[rdoc-ref:Logger@Entries] for details.
#
- # :call-seq:
- # Logger#add(severity, message = nil, progname = nil) { ... }
- #
- # === Args
- #
- # +severity+::
- # Severity. Constants are defined in Logger namespace: +DEBUG+, +INFO+,
- # +WARN+, +ERROR+, +FATAL+, or +UNKNOWN+.
- # +message+::
- # The log message. A String or Exception.
- # +progname+::
- # Program name string. Can be omitted. Treated as a message if no
- # +message+ and +block+ are given.
- # +block+::
- # Can be omitted. Called to get a message string if +message+ is nil.
- #
- # === Return
- #
- # When the given severity is not high enough (for this particular logger),
- # log no message, and return +true+.
+ # Examples:
#
- # === Description
+ # logger = Logger.new($stdout, progname: 'mung')
+ # logger.add(Logger::INFO)
+ # logger.add(Logger::ERROR, 'No good')
+ # logger.add(Logger::ERROR, 'No good', 'gnum')
#
- # Log a message if the given severity is high enough. This is the generic
- # logging method. Users will be more inclined to use #debug, #info, #warn,
- # #error, and #fatal.
+ # Output:
#
- # <b>Message format</b>: +message+ can be any object, but it has to be
- # converted to a String in order to log it. Generally, +inspect+ is used
- # if the given object is not a String.
- # A special case is an +Exception+ object, which will be printed in detail,
- # including message, class, and backtrace. See #msg2str for the
- # implementation if required.
+ # I, [2022-05-12T16:25:31.469726 #36328] INFO -- mung: mung
+ # E, [2022-05-12T16:25:55.349414 #36328] ERROR -- mung: No good
+ # E, [2022-05-12T16:26:35.841134 #36328] ERROR -- gnum: No good
#
- # === Bugs
+ # These convenience methods have implicit severity:
#
- # * Logfile is not locked.
- # * Append open does not need to lock file.
- # * If the OS supports multi I/O, records possibly may be mixed.
+ # - #debug.
+ # - #info.
+ # - #warn.
+ # - #error.
+ # - #fatal.
+ # - #unknown.
#
def add(severity, message = nil, progname = nil)
severity ||= UNKNOWN
@@ -478,104 +668,71 @@ class Logger
end
alias log add
+ # Writes the given +msg+ to the log with no formatting;
+ # returns the number of characters written,
+ # or +nil+ if no log device exists:
#
- # Dump given message to the log device without any formatting. If no log
- # device exists, return +nil+.
+ # logger = Logger.new($stdout)
+ # logger << 'My message.' # => 10
+ #
+ # Output:
+ #
+ # My message.
#
def <<(msg)
@logdev&.write(msg)
end
- #
- # Log a +DEBUG+ message.
- #
- # See #info for more information.
+ # Equivalent to calling #add with severity <tt>Logger::DEBUG</tt>.
#
def debug(progname = nil, &block)
add(DEBUG, nil, progname, &block)
end
- #
- # :call-seq:
- # info(message)
- # info(progname, &block)
- #
- # Log an +INFO+ message.
- #
- # +message+:: The message to log; does not need to be a String.
- # +progname+:: In the block form, this is the #progname to use in the
- # log message. The default can be set with #progname=.
- # +block+:: Evaluates to the message to log. This is not evaluated unless
- # the logger's level is sufficient to log the message. This
- # allows you to create potentially expensive logging messages that
- # are only called when the logger is configured to show them.
- #
- # === Examples
- #
- # logger.info("MainApp") { "Received connection from #{ip}" }
- # # ...
- # logger.info "Waiting for input from user"
- # # ...
- # logger.info { "User typed #{input}" }
- #
- # You'll probably stick to the second form above, unless you want to provide a
- # program name (which you can do with #progname= as well).
- #
- # === Return
- #
- # See #add.
+ # Equivalent to calling #add with severity <tt>Logger::INFO</tt>.
#
def info(progname = nil, &block)
add(INFO, nil, progname, &block)
end
- #
- # Log a +WARN+ message.
- #
- # See #info for more information.
+ # Equivalent to calling #add with severity <tt>Logger::WARN</tt>.
#
def warn(progname = nil, &block)
add(WARN, nil, progname, &block)
end
- #
- # Log an +ERROR+ message.
- #
- # See #info for more information.
+ # Equivalent to calling #add with severity <tt>Logger::ERROR</tt>.
#
def error(progname = nil, &block)
add(ERROR, nil, progname, &block)
end
- #
- # Log a +FATAL+ message.
- #
- # See #info for more information.
+ # Equivalent to calling #add with severity <tt>Logger::FATAL</tt>.
#
def fatal(progname = nil, &block)
add(FATAL, nil, progname, &block)
end
- #
- # Log an +UNKNOWN+ message. This will be printed no matter what the logger's
- # level is.
- #
- # See #info for more information.
+ # Equivalent to calling #add with severity <tt>Logger::UNKNOWN</tt>.
#
def unknown(progname = nil, &block)
add(UNKNOWN, nil, progname, &block)
end
+ # Closes the logger; returns +nil+:
#
- # Close the logging device.
+ # logger = Logger.new('t.log')
+ # logger.close # => nil
+ # logger.info('foo') # Prints "log writing failed. closed stream"
#
+ # Related: Logger#reopen.
def close
@logdev&.close
end
private
- # Severity label for logging (max 5 chars).
+ # \Severity label for logging (max 5 chars).
SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).freeze
def format_severity(severity)
diff --git a/lib/logger/errors.rb b/lib/logger/errors.rb
index e8925e14ac..88581793f0 100644
--- a/lib/logger/errors.rb
+++ b/lib/logger/errors.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-# not used after 1.2.7. just for compat.
class Logger
+ # not used after 1.2.7. just for compat.
class Error < RuntimeError # :nodoc:
end
class ShiftingError < Error # :nodoc:
diff --git a/lib/logger/formatter.rb b/lib/logger/formatter.rb
index 6a135b6fab..c634dbf34d 100644
--- a/lib/logger/formatter.rb
+++ b/lib/logger/formatter.rb
@@ -3,7 +3,8 @@
class Logger
# Default formatter for log messages.
class Formatter
- Format = "%s, [%s#%d] %5s -- %s: %s\n"
+ Format = "%.1s, [%s #%d] %5s -- %s: %s\n"
+ DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N"
attr_accessor :datetime_format
@@ -12,14 +13,13 @@ class Logger
end
def call(severity, time, progname, msg)
- Format % [severity[0..0], format_datetime(time), Process.pid, severity, progname,
- msg2str(msg)]
+ sprintf(Format, severity, format_datetime(time), Process.pid, severity, progname, msg2str(msg))
end
private
def format_datetime(time)
- time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ")
+ time.strftime(@datetime_format || DatetimeFormat)
end
def msg2str(msg)
diff --git a/lib/logger/log_device.rb b/lib/logger/log_device.rb
index 96d77b7b6a..84277a2656 100644
--- a/lib/logger/log_device.rb
+++ b/lib/logger/log_device.rb
@@ -79,8 +79,10 @@ class Logger
def set_dev(log)
if log.respond_to?(:write) and log.respond_to?(:close)
@dev = log
- if log.respond_to?(:path)
- @filename = log.path
+ if log.respond_to?(:path) and path = log.path
+ if File.exist?(path)
+ @filename = path
+ end
end
else
@dev = open_logfile(log)
@@ -135,7 +137,7 @@ class Logger
end
end
- if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
+ if /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os']
def lock_shift_log
yield
end
diff --git a/lib/logger/logger.gemspec b/lib/logger/logger.gemspec
index cd6d97de3d..d12db625d9 100644
--- a/lib/logger/logger.gemspec
+++ b/lib/logger/logger.gemspec
@@ -16,8 +16,6 @@ Gem::Specification.new do |spec|
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.required_ruby_version = ">= 2.3.0"
@@ -25,5 +23,4 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "bundler", ">= 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 e0f71830d2..f85c72eed3 100644
--- a/lib/logger/version.rb
+++ b/lib/logger/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class Logger
- VERSION = "1.4.3"
+ VERSION = "1.5.3"
end
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 04b5f26a5e..0fbc1cc2e5 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -7,9 +7,7 @@ require 'rbconfig'
require 'fileutils'
require 'shellwords'
-class String
- # :stopdoc:
-
+class String # :nodoc:
# Wraps a string in escaped quotes if it contains whitespace.
def quote
/\s/ =~ self ? "\"#{self}\"" : "#{self}"
@@ -32,19 +30,13 @@ class String
def sans_arguments
self[/\A[^()]+/]
end
-
- # :startdoc:
end
-class Array
- # :stopdoc:
-
+class Array # :nodoc:
# Wraps all strings in escaped quotes if they contain whitespace.
def quote
map {|s| s.quote}
end
-
- # :startdoc:
end
##
@@ -75,7 +67,7 @@ module MakeMakefile
C_EXT = %w[c m]
##
- # Extensions for files complied with a C++ compiler
+ # Extensions for files compiled with a C++ compiler
CXX_EXT = %w[cc mm cxx cpp]
unless File.exist?(File.join(*File.split(__FILE__).tap {|d, b| b.swapcase}))
@@ -285,7 +277,7 @@ MESSAGE
def split_libs(*strs)
sep = $mswin ? /\s+/ : /\s+(?=-|\z)/
- strs.map {|s| s.lstrip.split(sep)}.flatten
+ strs.flat_map {|s| s.lstrip.split(sep)}
end
def merge_libs(*libs)
@@ -386,38 +378,64 @@ MESSAGE
end
end
- def xsystem command, opts = nil
+ def expand_command(commands, envs = libpath_env)
varpat = /\$\((\w+)\)|\$\{(\w+)\}/
- if varpat =~ command
- vars = Hash.new {|h, k| h[k] = ENV[k]}
- command = command.dup
- nil while command.gsub!(varpat) {vars[$1||$2]}
+ vars = nil
+ expand = proc do |command|
+ case command
+ when Array
+ command.map(&expand)
+ when String
+ if varpat =~ command
+ vars ||= Hash.new {|h, k| h[k] = ENV[k]}
+ command = command.dup
+ nil while command.gsub!(varpat) {vars[$1||$2]}
+ end
+ command
+ else
+ command
+ end
end
+ if Array === commands
+ env, *commands = commands if Hash === commands.first
+ envs.merge!(env) if env
+ end
+ return envs, expand[commands]
+ end
+
+ def env_quote(envs)
+ envs.map {|e, v| "#{e}=#{v.quote}"}
+ end
+
+ def xsystem command, opts = nil
+ env, command = expand_command(command)
Logging::open do
- puts command.quote
+ puts [env_quote(env), command.quote].join(' ')
if opts and opts[:werror]
result = nil
Logging.postpone do |log|
- output = IO.popen(libpath_env, command, &:read)
+ output = IO.popen(env, command, &:read)
result = ($?.success? and File.zero?(log.path))
output
end
result
else
- system(libpath_env, command)
+ system(env, *command)
end
end
end
def xpopen command, *mode, &block
+ env, commands = expand_command(command)
+ command = [env_quote(env), command].join(' ')
Logging::open do
case mode[0]
- when nil, /^r/
+ when nil, Hash, /^r/
puts "#{command} |"
else
puts "| #{command}"
end
- IO.popen(libpath_env, command, *mode, &block)
+ IO.popen(env, commands, *mode, &block)
end
end
@@ -447,7 +465,7 @@ EOM
src.sub!(/[^\n]\z/, "\\&\n")
count = 0
begin
- open(conftest_source, "wb") do |cfile|
+ File.open(conftest_source, "wb") do |cfile|
cfile.print src
end
rescue Errno::EACCES
@@ -662,16 +680,6 @@ MSG
try_compile(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
end
- def append_cflags(flags, *opts)
- Array(flags).each do |flag|
- if checking_for("whether #{flag} is accepted as CFLAGS") {
- try_cflags(flag, *opts)
- }
- $CFLAGS << " " << flag
- end
- end
- end
-
def with_ldflags(flags)
ldflags = $LDFLAGS
$LDFLAGS = flags.dup
@@ -771,11 +779,20 @@ int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const
# files.
def try_func(func, libs, headers = nil, opt = "", &b)
headers = cpp_include(headers)
+ prepare = String.new
case func
when /^&/
decltype = proc {|x|"const volatile void *#{x}"}
when /\)$/
- call = func
+ strvars = []
+ call = func.gsub(/""/) {
+ v = "s#{strvars.size + 1}"
+ strvars << v
+ v
+ }
+ unless strvars.empty?
+ prepare << "char " << strvars.map {|v| "#{v}[1024]"}.join(", ") << "; "
+ end
when nil
call = ""
else
@@ -805,26 +822,18 @@ SRC
extern int t(void);
#{MAIN_DOES_NOTHING 't'}
#{"extern void #{call};" if decltype}
-int t(void) { #{call}; return 0; }
+int t(void) { #{prepare}#{call}; return 0; }
SRC
end
# You should use +have_var+ rather than +try_var+.
def try_var(var, headers = nil, opt = "", &b)
headers = cpp_include(headers)
- try_compile(<<"SRC", opt, &b) or
-#{headers}
-/*top*/
-extern int t(void);
-#{MAIN_DOES_NOTHING 't'}
-int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
-SRC
- try_link(<<"SRC", opt, &b)
+ try_compile(<<"SRC", opt, &b)
#{headers}
/*top*/
extern int t(void);
#{MAIN_DOES_NOTHING 't'}
-extern int #{var};
int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
SRC
end
@@ -1005,6 +1014,21 @@ SRC
# :startdoc:
+ # Check whether each given C compiler flag is acceptable and append it
+ # to <tt>$CFLAGS</tt> if so.
+ #
+ # [+flags+] a C compiler flag as a +String+ or an +Array+ of them
+ #
+ def append_cflags(flags, *opts)
+ Array(flags).each do |flag|
+ if checking_for("whether #{flag} is accepted as CFLAGS") {
+ try_cflags(flag, *opts)
+ }
+ $CFLAGS << " " << flag
+ end
+ end
+ end
+
# Returns whether or not +macro+ is defined either in the common header
# files or within any +headers+ you provide.
#
@@ -1056,7 +1080,7 @@ SRC
def find_library(lib, func, *paths, &b)
dir_config(lib)
lib = with_config(lib+'lib', lib)
- paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
+ paths = paths.flat_map {|path| path.split(File::PATH_SEPARATOR)}
checking_for checking_message(func && func.funcall_style, LIBARG%lib) do
libpath = $LIBPATH
libs = append_library($libs, lib)
@@ -1332,8 +1356,10 @@ SRC
# :stopdoc:
STRING_OR_FAILED_FORMAT = "%s"
- def STRING_OR_FAILED_FORMAT.%(x) # :nodoc:
- x ? super : "failed"
+ class << STRING_OR_FAILED_FORMAT # :nodoc:
+ def %(x)
+ x ? super : "failed"
+ end
end
def typedef_expr(type, headers)
@@ -1736,8 +1762,8 @@ SRC
hdr << "#endif\n"
hdr = hdr.join("")
log_src(hdr, "#{header} is")
- unless (IO.read(header) == hdr rescue false)
- open(header, "wb") do |hfile|
+ unless (File.read(header) == hdr rescue false)
+ File.open(header, "wb") do |hfile|
hfile.write(hdr)
end
end
@@ -1809,54 +1835,59 @@ SRC
$config_dirs[target] = [idir, ldir]
end
- # Returns compile/link information about an installed library in a
- # tuple of <code>[cflags, ldflags, libs]</code>, by using the
- # command found first in the following commands:
+ # Returns compile/link information about an installed library in a tuple of <code>[cflags,
+ # ldflags, libs]</code>, by using the command found first in the following commands:
#
# 1. If <code>--with-{pkg}-config={command}</code> is given via
- # command line option: <code>{command} {option}</code>
+ # command line option: <code>{command} {options}</code>
#
- # 2. <code>{pkg}-config {option}</code>
+ # 2. <code>{pkg}-config {options}</code>
#
- # 3. <code>pkg-config {option} {pkg}</code>
+ # 3. <code>pkg-config {options} {pkg}</code>
#
- # Where {option} is, for instance, <code>--cflags</code>.
+ # Where +options+ is the option name without dashes, for instance <code>"cflags"</code> for the
+ # <code>--cflags</code> flag.
#
- # The values obtained are appended to +$INCFLAGS+, +$CFLAGS+, +$LDFLAGS+ and
- # +$libs+.
+ # The values obtained are appended to <code>$INCFLAGS</code>, <code>$CFLAGS</code>,
+ # <code>$LDFLAGS</code> and <code>$libs</code>.
#
- # If an <code>option</code> argument is given, the config command is
- # invoked with the option and a stripped output string is returned
- # without modifying any of the global values mentioned above.
- def pkg_config(pkg, option=nil)
+ # If one or more <code>options</code> argument is given, the config command is
+ # invoked with the options and a stripped output string is returned without
+ # modifying any of the global values mentioned above.
+ def pkg_config(pkg, *options)
+ _, ldir = dir_config(pkg)
+ if ldir
+ pkg_config_path = "#{ldir}/pkgconfig"
+ if File.directory?(pkg_config_path)
+ Logging.message("PKG_CONFIG_PATH = %s\n", pkg_config_path)
+ envs = ["PKG_CONFIG_PATH"=>[pkg_config_path, ENV["PKG_CONFIG_PATH"]].compact.join(File::PATH_SEPARATOR)]
+ end
+ end
if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
# if and only if package specific config command is given
elsif ($PKGCONFIG ||=
- (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
+ (pkgconfig = with_config("pkg-config") {config_string("PKG_CONFIG") || "pkg-config"}) &&
find_executable0(pkgconfig) && pkgconfig) and
- xsystem("#{$PKGCONFIG} --exists #{pkg}")
+ xsystem([*envs, $PKGCONFIG, "--exists", pkg])
# default to pkg-config command
pkgconfig = $PKGCONFIG
- get = proc {|opt|
- opt = xpopen("#{$PKGCONFIG} --#{opt} #{pkg}", err:[:child, :out], &:read)
- Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}}
- opt.strip if $?.success?
- }
+ args = [pkg]
elsif find_executable0(pkgconfig = "#{pkg}-config")
# default to package specific config command, as a last resort.
else
pkgconfig = nil
end
if pkgconfig
- get ||= proc {|opt|
- opt = xpopen("#{pkgconfig} --#{opt}", err:[:child, :out], &:read)
- Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}}
- opt.strip if $?.success?
+ get = proc {|opts|
+ opts = Array(opts).map { |o| "--#{o}" }
+ opts = xpopen([*envs, pkgconfig, *opts, *args], err:[:child, :out], &:read)
+ Logging.open {puts opts.each_line.map{|s|"=> #{s.inspect}"}}
+ opts.strip if $?.success?
}
end
orig_ldflags = $LDFLAGS
- if get and option
- get[option]
+ if get and !options.empty?
+ get[options]
elsif get and try_ldflags(ldflags = get['libs'])
if incflags = get['cflags-only-I']
$INCFLAGS << " " << incflags
@@ -1933,13 +1964,14 @@ SRC
def configuration(srcdir)
mk = []
+ CONFIG['MKMF_VERBOSE'] ||= "0"
vpath = $VPATH.dup
CONFIG["hdrdir"] ||= $hdrdir
mk << %{
SHELL = /bin/sh
# V=0 quiet, V=1 verbose. other values don't work.
-V = 0
+V = #{CONFIG['MKMF_VERBOSE']}
V0 = $(V:0=)
Q1 = $(V:1=)
Q = $(Q1:0=@)
@@ -2044,6 +2076,11 @@ 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'}
@@ -2078,7 +2115,7 @@ preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
end
# :startdoc:
- # creates a stub Makefile.
+ # Creates a stub Makefile.
#
def dummy_makefile(srcdir)
configuration(srcdir) << <<RULES << CLEANINGS
@@ -2249,7 +2286,7 @@ RULES
RbConfig.expand(srcdir = srcprefix.dup)
ext = ".#{$OBJEXT}"
- orig_srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")].sort
+ orig_srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
if not $objs
srcs = $srcs || orig_srcs
$objs = []
@@ -2259,7 +2296,7 @@ RULES
h
}
unless objs.delete_if {|b, f| f.size == 1}.empty?
- dups = objs.sort.map {|b, f|
+ dups = objs.map {|b, f|
"#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
}
abort "source files duplication - #{dups.join(", ")}"
@@ -2341,15 +2378,23 @@ TIMESTAMP_DIR = #{$extout && $extmk ? '$(extout)/.timestamp' : '.'}
install_dirs.each {|d| conf << ("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
sodir = $extout ? '$(TARGET_SO_DIR)' : '$(RUBYARCHDIR)'
n = '$(TARGET_SO_DIR)$(TARGET)'
+ cleanobjs = ["$(OBJS)"]
+ if $extmk
+ %w[bc i s].each {|ex| cleanobjs << "$(OBJS:.#{$OBJEXT}=.#{ex})"}
+ end
+ if target
+ config_string('cleanobjs') {|t| cleanobjs << t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")}
+ end
conf << "\
TARGET_SO_DIR =#{$extout ? " $(RUBYARCHDIR)/" : ''}
TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
CLEANLIBS = #{'$(TARGET_SO) ' if target}#{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
-CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
+CLEANOBJS = #{cleanobjs.join(' ')} *.bak
+TARGET_SO_DIR_TIMESTAMP = #{timestamp_file(sodir, target_prefix)}
" #"
conf = yield(conf) if block_given?
- mfile = open("Makefile", "wb")
+ mfile = File.open("Makefile", "wb")
mfile.puts(conf)
mfile.print "
all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
@@ -2379,7 +2424,7 @@ static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" :
if target
f = "$(DLLIB)"
dest = "$(TARGET_SO)"
- stamp = timestamp_file(dir, target_prefix)
+ stamp = '$(TARGET_SO_DIR_TIMESTAMP)'
if $extout
mfile.puts dest
mfile.print "clean-so::\n"
@@ -2448,7 +2493,9 @@ static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" :
end
end
end
- dirs.unshift(sodir) if target and !dirs.include?(sodir)
+ if target and !dirs.include?(sodir)
+ mfile.print "$(TARGET_SO_DIR_TIMESTAMP):\n\t$(Q) $(MAKEDIRS) $(@D) #{sodir}\n\t$(Q) $(TOUCH) $@\n"
+ end
dirs.each do |d|
t = timestamp_file(d, target_prefix)
mfile.print "#{t}:\n\t$(Q) $(MAKEDIRS) $(@D) #{d}\n\t$(Q) $(TOUCH) $@\n"
@@ -2492,7 +2539,7 @@ site-install-rb: install-rb
mfile.print "$(TARGET_SO): "
mfile.print "$(DEFFILE) " if makedef
mfile.print "$(OBJS) Makefile"
- mfile.print " #{timestamp_file(sodir, target_prefix)}" if $extout
+ mfile.print " $(TARGET_SO_DIR_TIMESTAMP)" if $extout
mfile.print "\n"
mfile.print "\t$(ECHO) linking shared-object #{target_prefix.sub(/\A\/(.*)/, '\1/')}$(DLLIB)\n"
mfile.print "\t-$(Q)$(RM) $(@#{sep})\n"
@@ -2540,7 +2587,7 @@ site-install-rb: install-rb
if $warnflags = CONFIG['warnflags'] and CONFIG['GCC'] == 'yes'
# turn warnings into errors only for bundled extensions.
- config['warnflags'] = $warnflags.gsub(/(\A|\s)-Werror[-=]/, '\1-W')
+ config['warnflags'] = $warnflags.gsub(/(?:\A|\s)-W\Kerror[-=](?!implicit-function-declaration)/, '')
if /icc\z/ =~ config['CC']
config['warnflags'].gsub!(/(\A|\s)-W(?:division-by-zero|deprecated-declarations)/, '\1')
end
@@ -2562,6 +2609,7 @@ 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
diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb
index 706d3c1b3c..17ec9924e4 100644
--- a/lib/mutex_m.rb
+++ b/lib/mutex_m.rb
@@ -40,7 +40,8 @@
#
module Mutex_m
- VERSION = "0.1.1"
+ VERSION = "0.1.2"
+ Ractor.make_shareable(VERSION) if defined?(Ractor)
def Mutex_m.define_aliases(cl) # :nodoc:
cl.module_eval %q{
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 1fcf13530d..387df4b8f4 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#
# = net/http.rb
#
@@ -22,6 +22,7 @@
require 'net/protocol'
require 'uri'
+require 'resolv'
autoload :OpenSSL, 'openssl'
module Net #:nodoc:
@@ -31,365 +32,697 @@ module Net #:nodoc:
class HTTPHeaderSyntaxError < StandardError; end
# :startdoc:
- # == An HTTP client API for Ruby.
+ # \Class \Net::HTTP provides a rich library that implements the client
+ # in a client-server model that uses the \HTTP request-response protocol.
+ # For information about \HTTP, see:
+ #
+ # - {Hypertext Transfer Protocol}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol].
+ # - {Technical overview}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Technical_overview].
+ #
+ # == About the Examples
+ #
+ # :include: doc/net-http/examples.rdoc
+ #
+ # == Strategies
+ #
+ # - If you will make only a few GET requests,
+ # consider using {OpenURI}[rdoc-ref:OpenURI].
+ # - If you will make only a few requests of all kinds,
+ # consider using the various singleton convenience methods in this class.
+ # Each of the following methods automatically starts and finishes
+ # a {session}[rdoc-ref:Net::HTTP@Sessions] that sends a single request:
+ #
+ # # Return string response body.
+ # Net::HTTP.get(hostname, path)
+ # Net::HTTP.get(uri)
+ #
+ # # Write string response body to $stdout.
+ # Net::HTTP.get_print(hostname, path)
+ # Net::HTTP.get_print(uri)
+ #
+ # # Return response as Net::HTTPResponse object.
+ # Net::HTTP.get_response(hostname, path)
+ # Net::HTTP.get_response(uri)
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
+ # Net::HTTP.post(uri, data)
+ # params = {title: 'foo', body: 'bar', userId: 1}
+ # Net::HTTP.post_form(uri, params)
+ #
+ # - If performance is important, consider using sessions, which lower request overhead.
+ # This {session}[rdoc-ref:Net::HTTP@Sessions] has multiple requests for
+ # {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods]
+ # and {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]:
+ #
+ # Net::HTTP.start(hostname) do |http|
+ # # Session started automatically before block execution.
+ # http.get(path)
+ # http.head(path)
+ # body = 'Some text'
+ # http.post(path, body) # Can also have a block.
+ # http.put(path, body)
+ # http.delete(path)
+ # http.options(path)
+ # http.trace(path)
+ # http.patch(path, body) # Can also have a block.
+ # http.copy(path)
+ # http.lock(path, body)
+ # http.mkcol(path, body)
+ # http.move(path)
+ # http.propfind(path, body)
+ # http.proppatch(path, body)
+ # http.unlock(path, body)
+ # # Session finished automatically at block exit.
+ # end
#
- # Net::HTTP provides a rich library which can be used to build HTTP
- # user-agents. For more details about HTTP see
- # [RFC2616](http://www.ietf.org/rfc/rfc2616.txt).
+ # The methods cited above are convenience methods that, via their few arguments,
+ # allow minimal control over the requests.
+ # For greater control, consider using {request objects}[rdoc-ref:Net::HTTPRequest].
#
- # Net::HTTP is designed to work closely with URI. URI::HTTP#host,
- # URI::HTTP#port and URI::HTTP#request_uri are designed to work with
- # Net::HTTP.
+ # == URIs
#
- # If you are only performing a few GET requests you should try OpenURI.
+ # On the internet, a URI
+ # ({Universal Resource Identifier}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier])
+ # is a string that identifies a particular resource.
+ # It consists of some or all of: scheme, hostname, path, query, and fragment;
+ # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax].
#
- # == Simple Examples
+ # A Ruby {URI::Generic}[rdoc-ref:URI::Generic] object
+ # represents an internet URI.
+ # It provides, among others, methods
+ # +scheme+, +hostname+, +path+, +query+, and +fragment+.
#
- # All examples assume you have loaded Net::HTTP with:
+ # === Schemes
#
- # require 'net/http'
+ # An internet \URI has
+ # a {scheme}[https://en.wikipedia.org/wiki/List_of_URI_schemes].
#
- # This will also require 'uri' so you don't need to require it separately.
+ # The two schemes supported in \Net::HTTP are <tt>'https'</tt> and <tt>'http'</tt>:
#
- # The Net::HTTP methods in the following section do not persist
- # connections. They are not recommended if you are performing many HTTP
- # requests.
+ # uri.scheme # => "https"
+ # URI('http://example.com').scheme # => "http"
#
- # === GET
+ # === Hostnames
#
- # Net::HTTP.get('example.com', '/index.html') # => String
+ # A hostname identifies a server (host) to which requests may be sent:
#
- # === GET by URI
+ # hostname = uri.hostname # => "jsonplaceholder.typicode.com"
+ # Net::HTTP.start(hostname) do |http|
+ # # Some HTTP stuff.
+ # end
#
- # uri = URI('http://example.com/index.html?count=10')
- # Net::HTTP.get(uri) # => String
+ # === Paths
#
- # === GET with Dynamic Parameters
+ # A host-specific path identifies a resource on the host:
#
- # uri = URI('http://example.com/index.html')
- # params = { :limit => 10, :page => 3 }
- # uri.query = URI.encode_www_form(params)
+ # _uri = uri.dup
+ # _uri.path = '/todos/1'
+ # hostname = _uri.hostname
+ # path = _uri.path
+ # Net::HTTP.get(hostname, path)
#
- # res = Net::HTTP.get_response(uri)
- # puts res.body if res.is_a?(Net::HTTPSuccess)
+ # === Queries
#
- # === POST
+ # A host-specific query adds name/value pairs to the URI:
#
- # uri = URI('http://www.example.com/search.cgi')
- # res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
- # puts res.body
+ # _uri = uri.dup
+ # params = {userId: 1, completed: false}
+ # _uri.query = URI.encode_www_form(params)
+ # _uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com?userId=1&completed=false>
+ # Net::HTTP.get(_uri)
#
- # === POST with Multiple Values
+ # === Fragments
#
- # uri = URI('http://www.example.com/search.cgi')
- # res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
- # puts res.body
+ # A {URI fragment}[https://en.wikipedia.org/wiki/URI_fragment] has no effect
+ # in \Net::HTTP;
+ # the same data is returned, regardless of whether a fragment is included.
#
- # == How to use Net::HTTP
+ # == Request Headers
#
- # The following example code can be used as the basis of an HTTP user-agent
- # which can perform a variety of request types using persistent
- # connections.
+ # Request headers may be used to pass additional information to the host,
+ # similar to arguments passed in a method call;
+ # each header is a name/value pair.
#
- # uri = URI('http://example.com/some_path?query=string')
+ # Each of the \Net::HTTP methods that sends a request to the host
+ # has optional argument +headers+,
+ # where the headers are expressed as a hash of field-name/value pairs:
#
- # Net::HTTP.start(uri.host, uri.port) do |http|
- # request = Net::HTTP::Get.new uri
+ # headers = {Accept: 'application/json', Connection: 'Keep-Alive'}
+ # Net::HTTP.get(uri, headers)
#
- # response = http.request request # Net::HTTPResponse object
- # end
+ # See lists of both standard request fields and common request fields at
+ # {Request Fields}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields].
+ # A host may also accept other custom fields.
#
- # Net::HTTP::start immediately creates a connection to an HTTP server which
- # is kept open for the duration of the block. The connection will remain
- # open for multiple requests in the block if the server indicates it
- # supports persistent connections.
+ # == \HTTP Sessions
#
- # If you wish to re-use a connection across multiple HTTP requests without
- # automatically closing it you can use ::new and then call #start and
- # #finish manually.
+ # A _session_ is a connection between a server (host) and a client that:
#
- # The request types Net::HTTP supports are listed below in the section "HTTP
- # Request Classes".
+ # - Is begun by instance method Net::HTTP#start.
+ # - May contain any number of requests.
+ # - Is ended by instance method Net::HTTP#finish.
#
- # For all the Net::HTTP request objects and shortcut request methods you may
- # supply either a String for the request path or a URI from which Net::HTTP
- # will extract the request path.
+ # See example sessions at {Strategies}[rdoc-ref:Net::HTTP@Strategies].
#
- # === Response Data
+ # === Session Using \Net::HTTP.start
#
- # uri = URI('http://example.com/index.html')
- # res = Net::HTTP.get_response(uri)
+ # If you have many requests to make to a single host (and port),
+ # consider using singleton method Net::HTTP.start with a block;
+ # the method handles the session automatically by:
#
- # # Headers
- # res['Set-Cookie'] # => String
- # res.get_fields('set-cookie') # => Array
- # res.to_hash['set-cookie'] # => Array
- # puts "Headers: #{res.to_hash.inspect}"
+ # - Calling #start before block execution.
+ # - Executing the block.
+ # - Calling #finish after block execution.
#
- # # Status
- # puts res.code # => '200'
- # puts res.message # => 'OK'
- # puts res.class.name # => 'HTTPOK'
+ # In the block, you can use these instance methods,
+ # each of which that sends a single request:
#
- # # Body
- # puts res.body if res.response_body_permitted?
+ # - {HTTP methods}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods]:
#
- # === Following Redirection
+ # - #get, #request_get: GET.
+ # - #head, #request_head: HEAD.
+ # - #post, #request_post: POST.
+ # - #delete: DELETE.
+ # - #options: OPTIONS.
+ # - #trace: TRACE.
+ # - #patch: PATCH.
#
- # Each Net::HTTPResponse object belongs to a class for its response code.
+ # - {WebDAV methods}[https://en.wikipedia.org/wiki/WebDAV#Implementation]:
#
- # For example, all 2XX responses are instances of a Net::HTTPSuccess
- # subclass, a 3XX response is an instance of a Net::HTTPRedirection
- # subclass and a 200 response is an instance of the Net::HTTPOK class. For
- # details of response classes, see the section "HTTP Response Classes"
- # below.
+ # - #copy: COPY.
+ # - #lock: LOCK.
+ # - #mkcol: MKCOL.
+ # - #move: MOVE.
+ # - #propfind: PROPFIND.
+ # - #proppatch: PROPPATCH.
+ # - #unlock: UNLOCK.
#
- # Using a case statement you can handle various types of responses properly:
+ # === Session Using \Net::HTTP.start and \Net::HTTP.finish
#
- # def fetch(uri_str, limit = 10)
- # # You should choose a better exception.
- # raise ArgumentError, 'too many HTTP redirects' if limit == 0
+ # You can manage a session manually using methods #start and #finish:
#
- # response = Net::HTTP.get_response(URI(uri_str))
+ # http = Net::HTTP.new(hostname)
+ # http.start
+ # http.get('/todos/1')
+ # http.get('/todos/2')
+ # http.delete('/posts/1')
+ # http.finish # Needed to free resources.
#
- # case response
- # when Net::HTTPSuccess then
- # response
- # when Net::HTTPRedirection then
- # location = response['location']
- # warn "redirected to #{location}"
- # fetch(location, limit - 1)
- # else
- # response.value
- # end
- # end
+ # === Single-Request Session
#
- # print fetch('http://www.ruby-lang.org')
+ # Certain convenience methods automatically handle a session by:
#
- # === POST
+ # - Creating an \HTTP object
+ # - Starting a session.
+ # - Sending a single request.
+ # - Finishing the session.
+ # - Destroying the object.
#
- # A POST can be made using the Net::HTTP::Post request class. This example
- # creates a URL encoded POST body:
+ # Such methods that send GET requests:
#
- # uri = URI('http://www.example.com/todo.cgi')
- # req = Net::HTTP::Post.new(uri)
- # req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')
+ # - ::get: Returns the string response body.
+ # - ::get_print: Writes the string response body to $stdout.
+ # - ::get_response: Returns a Net::HTTPResponse object.
#
- # res = Net::HTTP.start(uri.hostname, uri.port) do |http|
- # http.request(req)
- # end
+ # Such methods that send POST requests:
#
- # case res
- # when Net::HTTPSuccess, Net::HTTPRedirection
- # # OK
- # else
- # res.value
- # end
+ # - ::post: Posts data to the host.
+ # - ::post_form: Posts form data to the host.
#
- # To send multipart/form-data use Net::HTTPHeader#set_form:
+ # == \HTTP Requests and Responses
#
- # req = Net::HTTP::Post.new(uri)
- # req.set_form([['upload', File.open('foo.bar')]], 'multipart/form-data')
+ # Many of the methods above are convenience methods,
+ # each of which sends a request and returns a string
+ # without directly using \Net::HTTPRequest and \Net::HTTPResponse objects.
#
- # Other requests that can contain a body such as PUT can be created in the
- # same way using the corresponding request class (Net::HTTP::Put).
+ # You can, however, directly create a request object, send the request,
+ # and retrieve the response object; see:
#
- # === Setting Headers
+ # - Net::HTTPRequest.
+ # - Net::HTTPResponse.
#
- # The following example performs a conditional GET using the
- # If-Modified-Since header. If the files has not been modified since the
- # time in the header a Not Modified response will be returned. See RFC 2616
- # section 9.3 for further details.
+ # == Following Redirection
#
- # uri = URI('http://example.com/cached_response')
- # file = File.stat 'cached_response'
+ # Each returned response is an instance of a subclass of Net::HTTPResponse.
+ # See the {response class hierarchy}[rdoc-ref:Net::HTTPResponse@Response+Subclasses].
#
- # req = Net::HTTP::Get.new(uri)
- # req['If-Modified-Since'] = file.mtime.rfc2822
+ # In particular, class Net::HTTPRedirection is the parent
+ # of all redirection classes.
+ # This allows you to craft a case statement to handle redirections properly:
#
- # res = Net::HTTP.start(uri.hostname, uri.port) {|http|
- # http.request(req)
- # }
+ # def fetch(uri, limit = 10)
+ # # You should choose a better exception.
+ # raise ArgumentError, 'Too many HTTP redirects' if limit == 0
+ #
+ # res = Net::HTTP.get_response(URI(uri))
+ # case res
+ # when Net::HTTPSuccess # Any success class.
+ # res
+ # when Net::HTTPRedirection # Any redirection class.
+ # location = res['Location']
+ # warn "Redirected to #{location}"
+ # fetch(location, limit - 1)
+ # else # Any other class.
+ # res.value
+ # end
+ # end
#
- # open 'cached_response', 'w' do |io|
- # io.write res.body
- # end if res.is_a?(Net::HTTPSuccess)
+ # fetch(uri)
#
- # === Basic Authentication
+ # == Basic Authentication
#
# Basic authentication is performed according to
- # [RFC2617](http://www.ietf.org/rfc/rfc2617.txt).
- #
- # uri = URI('http://example.com/index.html?key=value')
+ # {RFC2617}[http://www.ietf.org/rfc/rfc2617.txt]:
#
# req = Net::HTTP::Get.new(uri)
- # req.basic_auth 'user', 'pass'
- #
- # res = Net::HTTP.start(uri.hostname, uri.port) {|http|
+ # req.basic_auth('user', 'pass')
+ # res = Net::HTTP.start(hostname) do |http|
# http.request(req)
- # }
- # puts res.body
+ # end
#
- # === Streaming Response Bodies
+ # == Streaming Response Bodies
#
- # By default Net::HTTP reads an entire response into memory. If you are
+ # By default \Net::HTTP reads an entire response into memory. If you are
# handling large files or wish to implement a progress bar you can instead
# stream the body directly to an IO.
#
- # uri = URI('http://example.com/large_file')
- #
- # Net::HTTP.start(uri.host, uri.port) do |http|
- # request = Net::HTTP::Get.new uri
- #
- # http.request request do |response|
- # open 'large_file', 'w' do |io|
- # response.read_body do |chunk|
- # io.write chunk
+ # Net::HTTP.start(hostname) do |http|
+ # req = Net::HTTP::Get.new(uri)
+ # http.request(req) do |res|
+ # open('t.tmp', 'w') do |f|
+ # res.read_body do |chunk|
+ # f.write chunk
# end
# end
# end
# end
#
- # === HTTPS
- #
- # HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=.
+ # == HTTPS
#
- # uri = URI('https://secure.example.com/some_path?query=string')
+ # HTTPS is enabled for an \HTTP connection by Net::HTTP#use_ssl=:
#
- # Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
- # request = Net::HTTP::Get.new uri
- # response = http.request request # Net::HTTPResponse object
+ # Net::HTTP.start(hostname, :use_ssl => true) do |http|
+ # req = Net::HTTP::Get.new(uri)
+ # res = http.request(req)
# end
#
- # Or if you simply want to make a GET request, you may pass in an URI
- # object that has an HTTPS URL. Net::HTTP automatically turns on TLS
- # verification if the URI object has a 'https' URI scheme.
+ # Or if you simply want to make a GET request, you may pass in a URI
+ # object that has an \HTTPS URL. \Net::HTTP automatically turns on TLS
+ # verification if the URI object has a 'https' URI scheme:
+ #
+ # uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com/>
+ # Net::HTTP.get(uri)
+ #
+ # == Proxy Server
+ #
+ # An \HTTP object can have
+ # a {proxy server}[https://en.wikipedia.org/wiki/Proxy_server].
+ #
+ # You can create an \HTTP object with a proxy server
+ # using method Net::HTTP.new or method Net::HTTP.start.
+ #
+ # The proxy may be defined either by argument +p_addr+
+ # or by environment variable <tt>'http_proxy'</tt>.
+ #
+ # === Proxy Using Argument +p_addr+ as a \String
+ #
+ # When argument +p_addr+ is a string hostname,
+ # the returned +http+ has the given host as its proxy:
+ #
+ # http = Net::HTTP.new(hostname, nil, 'proxy.example')
+ # http.proxy? # => true
+ # http.proxy_from_env? # => false
+ # http.proxy_address # => "proxy.example"
+ # # These use default values.
+ # http.proxy_port # => 80
+ # http.proxy_user # => nil
+ # http.proxy_pass # => nil
+ #
+ # The port, username, and password for the proxy may also be given:
#
- # uri = URI('https://example.com/')
- # Net::HTTP.get(uri) # => String
+ # http = Net::HTTP.new(hostname, nil, 'proxy.example', 8000, 'pname', 'ppass')
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
+ # http.proxy? # => true
+ # http.proxy_from_env? # => false
+ # http.proxy_address # => "proxy.example"
+ # http.proxy_port # => 8000
+ # http.proxy_user # => "pname"
+ # http.proxy_pass # => "ppass"
#
- # In previous versions of Ruby you would need to require 'net/https' to use
- # HTTPS. This is no longer true.
+ # === Proxy Using '<tt>ENV['http_proxy']</tt>'
+ #
+ # When environment variable <tt>'http_proxy'</tt>
+ # is set to a \URI string,
+ # the returned +http+ will have the server at that URI as its proxy;
+ # note that the \URI string must have a protocol
+ # such as <tt>'http'</tt> or <tt>'https'</tt>:
+ #
+ # ENV['http_proxy'] = 'http://example.com'
+ # http = Net::HTTP.new(hostname)
+ # http.proxy? # => true
+ # http.proxy_from_env? # => true
+ # http.proxy_address # => "example.com"
+ # # These use default values.
+ # http.proxy_port # => 80
+ # http.proxy_user # => nil
+ # http.proxy_pass # => nil
+ #
+ # The \URI string may include proxy username, password, and port number:
+ #
+ # ENV['http_proxy'] = 'http://pname:ppass@example.com:8000'
+ # http = Net::HTTP.new(hostname)
+ # http.proxy? # => true
+ # http.proxy_from_env? # => true
+ # http.proxy_address # => "example.com"
+ # http.proxy_port # => 8000
+ # http.proxy_user # => "pname"
+ # http.proxy_pass # => "ppass"
+ #
+ # === Filtering Proxies
+ #
+ # With method Net::HTTP.new (but not Net::HTTP.start),
+ # you can use argument +p_no_proxy+ to filter proxies:
+ #
+ # - Reject a certain address:
+ #
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example')
+ # http.proxy_address # => nil
+ #
+ # - Reject certain domains or subdomains:
+ #
+ # http = Net::HTTP.new('example.com', nil, 'my.proxy.example', 8000, 'pname', 'ppass', 'proxy.example')
+ # http.proxy_address # => nil
+ #
+ # - Reject certain addresses and port combinations:
+ #
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:1234')
+ # http.proxy_address # => "proxy.example"
+ #
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:8000')
+ # http.proxy_address # => nil
+ #
+ # - Reject a list of the types above delimited using a comma:
+ #
+ # http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000')
+ # http.proxy_address # => nil
+ #
+ # http = Net::HTTP.new('example.com', nil, 'my.proxy', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000')
+ # http.proxy_address # => nil
+ #
+ # == Compression and Decompression
+ #
+ # \Net::HTTP does not compress the body of a request before sending.
+ #
+ # By default, \Net::HTTP adds header <tt>'Accept-Encoding'</tt>
+ # to a new {request object}[rdoc-ref:Net::HTTPRequest]:
+ #
+ # Net::HTTP::Get.new(uri)['Accept-Encoding']
+ # # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
+ #
+ # This requests the server to zip-encode the response body if there is one;
+ # the server is not required to do so.
+ #
+ # \Net::HTTP does not automatically decompress a response body
+ # if the response has header <tt>'Content-Range'</tt>.
+ #
+ # Otherwise decompression (or not) depends on the value of header
+ # {Content-Encoding}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-encoding-response-header]:
+ #
+ # - <tt>'deflate'</tt>, <tt>'gzip'</tt>, or <tt>'x-gzip'</tt>:
+ # decompresses the body and deletes the header.
+ # - <tt>'none'</tt> or <tt>'identity'</tt>:
+ # does not decompress the body, but deletes the header.
+ # - Any other value:
+ # leaves the body and header unchanged.
+ #
+ # == What's Here
+ #
+ # This is a categorized summary of methods and attributes.
+ #
+ # === \Net::HTTP Objects
+ #
+ # - {::new}[rdoc-ref:Net::HTTP.new]:
+ # Creates a new instance.
+ # - {#inspect}[rdoc-ref:Net::HTTP#inspect]:
+ # Returns a string representation of +self+.
+ #
+ # === Sessions
+ #
+ # - {::start}[rdoc-ref:Net::HTTP.start]:
+ # Begins a new session in a new \Net::HTTP object.
+ # - {#started?}[rdoc-ref:Net::HTTP#started?]
+ # (aliased as {#active?}[rdoc-ref:Net::HTTP#active?]):
+ # Returns whether in a session.
+ # - {#finish}[rdoc-ref:Net::HTTP#finish]:
+ # Ends an active session.
+ # - {#start}[rdoc-ref:Net::HTTP#start]:
+ # Begins a new session in an existing \Net::HTTP object (+self+).
+ #
+ # === Connections
+ #
+ # - {:continue_timeout}[rdoc-ref:Net::HTTP#continue_timeout]:
+ # Returns the continue timeout.
+ # - {#continue_timeout=}[rdoc-ref:Net::HTTP#continue_timeout=]:
+ # Sets the continue timeout seconds.
+ # - {:keep_alive_timeout}[rdoc-ref:Net::HTTP#keep_alive_timeout]:
+ # Returns the keep-alive timeout.
+ # - {:keep_alive_timeout=}[rdoc-ref:Net::HTTP#keep_alive_timeout=]:
+ # Sets the keep-alive timeout.
+ # - {:max_retries}[rdoc-ref:Net::HTTP#max_retries]:
+ # Returns the maximum retries.
+ # - {#max_retries=}[rdoc-ref:Net::HTTP#max_retries=]:
+ # Sets the maximum retries.
+ # - {:open_timeout}[rdoc-ref:Net::HTTP#open_timeout]:
+ # Returns the open timeout.
+ # - {:open_timeout=}[rdoc-ref:Net::HTTP#open_timeout=]:
+ # Sets the open timeout.
+ # - {:read_timeout}[rdoc-ref:Net::HTTP#read_timeout]:
+ # Returns the open timeout.
+ # - {:read_timeout=}[rdoc-ref:Net::HTTP#read_timeout=]:
+ # Sets the read timeout.
+ # - {:ssl_timeout}[rdoc-ref:Net::HTTP#ssl_timeout]:
+ # Returns the ssl timeout.
+ # - {:ssl_timeout=}[rdoc-ref:Net::HTTP#ssl_timeout=]:
+ # Sets the ssl timeout.
+ # - {:write_timeout}[rdoc-ref:Net::HTTP#write_timeout]:
+ # Returns the write timeout.
+ # - {write_timeout=}[rdoc-ref:Net::HTTP#write_timeout=]:
+ # Sets the write timeout.
+ #
+ # === Requests
+ #
+ # - {::get}[rdoc-ref:Net::HTTP.get]:
+ # Sends a GET request and returns the string response body.
+ # - {::get_print}[rdoc-ref:Net::HTTP.get_print]:
+ # Sends a GET request and write the string response body to $stdout.
+ # - {::get_response}[rdoc-ref:Net::HTTP.get_response]:
+ # Sends a GET request and returns a response object.
+ # - {::post_form}[rdoc-ref:Net::HTTP.post_form]:
+ # Sends a POST request with form data and returns a response object.
+ # - {::post}[rdoc-ref:Net::HTTP.post]:
+ # Sends a POST request with data and returns a response object.
+ # - {#copy}[rdoc-ref:Net::HTTP#copy]:
+ # Sends a COPY request and returns a response object.
+ # - {#delete}[rdoc-ref:Net::HTTP#delete]:
+ # Sends a DELETE request and returns a response object.
+ # - {#get}[rdoc-ref:Net::HTTP#get]:
+ # Sends a GET request and returns a response object.
+ # - {#head}[rdoc-ref:Net::HTTP#head]:
+ # Sends a HEAD request and returns a response object.
+ # - {#lock}[rdoc-ref:Net::HTTP#lock]:
+ # Sends a LOCK request and returns a response object.
+ # - {#mkcol}[rdoc-ref:Net::HTTP#mkcol]:
+ # Sends a MKCOL request and returns a response object.
+ # - {#move}[rdoc-ref:Net::HTTP#move]:
+ # Sends a MOVE request and returns a response object.
+ # - {#options}[rdoc-ref:Net::HTTP#options]:
+ # Sends a OPTIONS request and returns a response object.
+ # - {#patch}[rdoc-ref:Net::HTTP#patch]:
+ # Sends a PATCH request and returns a response object.
+ # - {#post}[rdoc-ref:Net::HTTP#post]:
+ # Sends a POST request and returns a response object.
+ # - {#propfind}[rdoc-ref:Net::HTTP#propfind]:
+ # Sends a PROPFIND request and returns a response object.
+ # - {#proppatch}[rdoc-ref:Net::HTTP#proppatch]:
+ # Sends a PROPPATCH request and returns a response object.
+ # - {#put}[rdoc-ref:Net::HTTP#put]:
+ # Sends a PUT request and returns a response object.
+ # - {#request}[rdoc-ref:Net::HTTP#request]:
+ # Sends a request and returns a response object.
+ # - {#request_get}[rdoc-ref:Net::HTTP#request_get]
+ # (aliased as {#get2}[rdoc-ref:Net::HTTP#get2]):
+ # Sends a GET request and forms a response object;
+ # if a block given, calls the block with the object,
+ # otherwise returns the object.
+ # - {#request_head}[rdoc-ref:Net::HTTP#request_head]
+ # (aliased as {#head2}[rdoc-ref:Net::HTTP#head2]):
+ # Sends a HEAD request and forms a response object;
+ # if a block given, calls the block with the object,
+ # otherwise returns the object.
+ # - {#request_post}[rdoc-ref:Net::HTTP#request_post]
+ # (aliased as {#post2}[rdoc-ref:Net::HTTP#post2]):
+ # Sends a POST request and forms a response object;
+ # if a block given, calls the block with the object,
+ # otherwise returns the object.
+ # - {#send_request}[rdoc-ref:Net::HTTP#send_request]:
+ # Sends a request and returns a response object.
+ # - {#trace}[rdoc-ref:Net::HTTP#trace]:
+ # Sends a TRACE request and returns a response object.
+ # - {#unlock}[rdoc-ref:Net::HTTP#unlock]:
+ # Sends an UNLOCK request and returns a response object.
+ #
+ # === Responses
+ #
+ # - {:close_on_empty_response}[rdoc-ref:Net::HTTP#close_on_empty_response]:
+ # Returns whether to close connection on empty response.
+ # - {:close_on_empty_response=}[rdoc-ref:Net::HTTP#close_on_empty_response=]:
+ # Sets whether to close connection on empty response.
+ # - {:ignore_eof}[rdoc-ref:Net::HTTP#ignore_eof]:
+ # Returns whether to ignore end-of-file when reading a response body
+ # with <tt>Content-Length</tt> headers.
+ # - {:ignore_eof=}[rdoc-ref:Net::HTTP#ignore_eof=]:
+ # Sets whether to ignore end-of-file when reading a response body
+ # with <tt>Content-Length</tt> headers.
+ # - {:response_body_encoding}[rdoc-ref:Net::HTTP#response_body_encoding]:
+ # Returns the encoding to use for the response body.
+ # - {#response_body_encoding=}[rdoc-ref:Net::HTTP#response_body_encoding=]:
+ # Sets the response body encoding.
#
# === Proxies
#
- # Net::HTTP will automatically create a proxy from the +http_proxy+
- # environment variable if it is present. To disable use of +http_proxy+,
- # pass +nil+ for the proxy address.
- #
- # You may also create a custom proxy:
- #
- # proxy_addr = 'your.proxy.host'
- # proxy_port = 8080
- #
- # Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http|
- # # always proxy via your.proxy.addr:8080
- # }
- #
- # See Net::HTTP.new for further details and examples such as proxies that
- # require a username and password.
- #
- # === Compression
- #
- # Net::HTTP automatically adds Accept-Encoding for compression of response
- # bodies and automatically decompresses gzip and deflate responses unless a
- # Range header was sent.
- #
- # Compression can be disabled through the Accept-Encoding: identity header.
- #
- # == HTTP Request Classes
- #
- # Here is the HTTP request class hierarchy.
- #
- # * Net::HTTPRequest
- # * Net::HTTP::Get
- # * Net::HTTP::Head
- # * Net::HTTP::Post
- # * Net::HTTP::Patch
- # * Net::HTTP::Put
- # * Net::HTTP::Proppatch
- # * Net::HTTP::Lock
- # * Net::HTTP::Unlock
- # * Net::HTTP::Options
- # * Net::HTTP::Propfind
- # * Net::HTTP::Delete
- # * Net::HTTP::Move
- # * Net::HTTP::Copy
- # * Net::HTTP::Mkcol
- # * Net::HTTP::Trace
- #
- # == HTTP Response Classes
- #
- # Here is HTTP response class hierarchy. All classes are defined in Net
- # module and are subclasses of Net::HTTPResponse.
- #
- # HTTPUnknownResponse:: For unhandled HTTP extensions
- # HTTPInformation:: 1xx
- # HTTPContinue:: 100
- # HTTPSwitchProtocol:: 101
- # HTTPSuccess:: 2xx
- # HTTPOK:: 200
- # HTTPCreated:: 201
- # HTTPAccepted:: 202
- # HTTPNonAuthoritativeInformation:: 203
- # HTTPNoContent:: 204
- # HTTPResetContent:: 205
- # HTTPPartialContent:: 206
- # HTTPMultiStatus:: 207
- # HTTPIMUsed:: 226
- # HTTPRedirection:: 3xx
- # HTTPMultipleChoices:: 300
- # HTTPMovedPermanently:: 301
- # HTTPFound:: 302
- # HTTPSeeOther:: 303
- # HTTPNotModified:: 304
- # HTTPUseProxy:: 305
- # HTTPTemporaryRedirect:: 307
- # HTTPClientError:: 4xx
- # HTTPBadRequest:: 400
- # HTTPUnauthorized:: 401
- # HTTPPaymentRequired:: 402
- # HTTPForbidden:: 403
- # HTTPNotFound:: 404
- # HTTPMethodNotAllowed:: 405
- # HTTPNotAcceptable:: 406
- # HTTPProxyAuthenticationRequired:: 407
- # HTTPRequestTimeOut:: 408
- # HTTPConflict:: 409
- # HTTPGone:: 410
- # HTTPLengthRequired:: 411
- # HTTPPreconditionFailed:: 412
- # HTTPRequestEntityTooLarge:: 413
- # HTTPRequestURITooLong:: 414
- # HTTPUnsupportedMediaType:: 415
- # HTTPRequestedRangeNotSatisfiable:: 416
- # HTTPExpectationFailed:: 417
- # HTTPUnprocessableEntity:: 422
- # HTTPLocked:: 423
- # HTTPFailedDependency:: 424
- # HTTPUpgradeRequired:: 426
- # HTTPPreconditionRequired:: 428
- # HTTPTooManyRequests:: 429
- # HTTPRequestHeaderFieldsTooLarge:: 431
- # HTTPUnavailableForLegalReasons:: 451
- # HTTPServerError:: 5xx
- # HTTPInternalServerError:: 500
- # HTTPNotImplemented:: 501
- # HTTPBadGateway:: 502
- # HTTPServiceUnavailable:: 503
- # HTTPGatewayTimeOut:: 504
- # HTTPVersionNotSupported:: 505
- # HTTPInsufficientStorage:: 507
- # HTTPNetworkAuthenticationRequired:: 511
- #
- # There is also the Net::HTTPBadResponse exception which is raised when
- # there is a protocol error.
+ # - {:proxy_address}[rdoc-ref:Net::HTTP#proxy_address]:
+ # Returns the proxy address.
+ # - {:proxy_address=}[rdoc-ref:Net::HTTP#proxy_address=]:
+ # Sets the proxy address.
+ # - {::proxy_class?}[rdoc-ref:Net::HTTP.proxy_class?]:
+ # Returns whether +self+ is a proxy class.
+ # - {#proxy?}[rdoc-ref:Net::HTTP#proxy?]:
+ # Returns whether +self+ has a proxy.
+ # - {#proxy_address}[rdoc-ref:Net::HTTP#proxy_address]
+ # (aliased as {#proxyaddr}[rdoc-ref:Net::HTTP#proxyaddr]):
+ # Returns the proxy address.
+ # - {#proxy_from_env?}[rdoc-ref:Net::HTTP#proxy_from_env?]:
+ # Returns whether the proxy is taken from an environment variable.
+ # - {:proxy_from_env=}[rdoc-ref:Net::HTTP#proxy_from_env=]:
+ # Sets whether the proxy is to be taken from an environment variable.
+ # - {:proxy_pass}[rdoc-ref:Net::HTTP#proxy_pass]:
+ # Returns the proxy password.
+ # - {:proxy_pass=}[rdoc-ref:Net::HTTP#proxy_pass=]:
+ # Sets the proxy password.
+ # - {:proxy_port}[rdoc-ref:Net::HTTP#proxy_port]:
+ # Returns the proxy port.
+ # - {:proxy_port=}[rdoc-ref:Net::HTTP#proxy_port=]:
+ # Sets the proxy port.
+ # - {#proxy_user}[rdoc-ref:Net::HTTP#proxy_user]:
+ # Returns the proxy user name.
+ # - {:proxy_user=}[rdoc-ref:Net::HTTP#proxy_user=]:
+ # Sets the proxy user.
+ #
+ # === Security
+ #
+ # - {:ca_file}[rdoc-ref:Net::HTTP#ca_file]:
+ # Returns the path to a CA certification file.
+ # - {:ca_file=}[rdoc-ref:Net::HTTP#ca_file=]:
+ # Sets the path to a CA certification file.
+ # - {:ca_path}[rdoc-ref:Net::HTTP#ca_path]:
+ # Returns the path of to CA directory containing certification files.
+ # - {:ca_path=}[rdoc-ref:Net::HTTP#ca_path=]:
+ # Sets the path of to CA directory containing certification files.
+ # - {:cert}[rdoc-ref:Net::HTTP#cert]:
+ # Returns the OpenSSL::X509::Certificate object to be used for client certification.
+ # - {:cert=}[rdoc-ref:Net::HTTP#cert=]:
+ # Sets the OpenSSL::X509::Certificate object to be used for client certification.
+ # - {:cert_store}[rdoc-ref:Net::HTTP#cert_store]:
+ # Returns the X509::Store to be used for verifying peer certificate.
+ # - {:cert_store=}[rdoc-ref:Net::HTTP#cert_store=]:
+ # Sets the X509::Store to be used for verifying peer certificate.
+ # - {:ciphers}[rdoc-ref:Net::HTTP#ciphers]:
+ # Returns the available SSL ciphers.
+ # - {:ciphers=}[rdoc-ref:Net::HTTP#ciphers=]:
+ # Sets the available SSL ciphers.
+ # - {:extra_chain_cert}[rdoc-ref:Net::HTTP#extra_chain_cert]:
+ # Returns the extra X509 certificates to be added to the certificate chain.
+ # - {:extra_chain_cert=}[rdoc-ref:Net::HTTP#extra_chain_cert=]:
+ # Sets the extra X509 certificates to be added to the certificate chain.
+ # - {:key}[rdoc-ref:Net::HTTP#key]:
+ # Returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
+ # - {:key=}[rdoc-ref:Net::HTTP#key=]:
+ # Sets the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
+ # - {:max_version}[rdoc-ref:Net::HTTP#max_version]:
+ # Returns the maximum SSL version.
+ # - {:max_version=}[rdoc-ref:Net::HTTP#max_version=]:
+ # Sets the maximum SSL version.
+ # - {:min_version}[rdoc-ref:Net::HTTP#min_version]:
+ # Returns the minimum SSL version.
+ # - {:min_version=}[rdoc-ref:Net::HTTP#min_version=]:
+ # Sets the minimum SSL version.
+ # - {#peer_cert}[rdoc-ref:Net::HTTP#peer_cert]:
+ # Returns the X509 certificate chain for the session's socket peer.
+ # - {:ssl_version}[rdoc-ref:Net::HTTP#ssl_version]:
+ # Returns the SSL version.
+ # - {:ssl_version=}[rdoc-ref:Net::HTTP#ssl_version=]:
+ # Sets the SSL version.
+ # - {#use_ssl=}[rdoc-ref:Net::HTTP#use_ssl=]:
+ # Sets whether a new session is to use Transport Layer Security.
+ # - {#use_ssl?}[rdoc-ref:Net::HTTP#use_ssl?]:
+ # Returns whether +self+ uses SSL.
+ # - {:verify_callback}[rdoc-ref:Net::HTTP#verify_callback]:
+ # Returns the callback for the server certification verification.
+ # - {:verify_callback=}[rdoc-ref:Net::HTTP#verify_callback=]:
+ # Sets the callback for the server certification verification.
+ # - {:verify_depth}[rdoc-ref:Net::HTTP#verify_depth]:
+ # Returns the maximum depth for the certificate chain verification.
+ # - {:verify_depth=}[rdoc-ref:Net::HTTP#verify_depth=]:
+ # Sets the maximum depth for the certificate chain verification.
+ # - {:verify_hostname}[rdoc-ref:Net::HTTP#verify_hostname]:
+ # Returns the flags for server the certification verification at the beginning of the SSL/TLS session.
+ # - {:verify_hostname=}[rdoc-ref:Net::HTTP#verify_hostname=]:
+ # Sets he flags for server the certification verification at the beginning of the SSL/TLS session.
+ # - {:verify_mode}[rdoc-ref:Net::HTTP#verify_mode]:
+ # Returns the flags for server the certification verification at the beginning of the SSL/TLS session.
+ # - {:verify_mode=}[rdoc-ref:Net::HTTP#verify_mode=]:
+ # Sets the flags for server the certification verification at the beginning of the SSL/TLS session.
+ #
+ # === Addresses and Ports
+ #
+ # - {:address}[rdoc-ref:Net::HTTP#address]:
+ # Returns the string host name or host IP.
+ # - {::default_port}[rdoc-ref:Net::HTTP.default_port]:
+ # Returns integer 80, the default port to use for HTTP requests.
+ # - {::http_default_port}[rdoc-ref:Net::HTTP.http_default_port]:
+ # Returns integer 80, the default port to use for HTTP requests.
+ # - {::https_default_port}[rdoc-ref:Net::HTTP.https_default_port]:
+ # Returns integer 443, the default port to use for HTTPS requests.
+ # - {#ipaddr}[rdoc-ref:Net::HTTP#ipaddr]:
+ # Returns the IP address for the connection.
+ # - {#ipaddr=}[rdoc-ref:Net::HTTP#ipaddr=]:
+ # Sets the IP address for the connection.
+ # - {:local_host}[rdoc-ref:Net::HTTP#local_host]:
+ # Returns the string local host used to establish the connection.
+ # - {:local_host=}[rdoc-ref:Net::HTTP#local_host=]:
+ # Sets the string local host used to establish the connection.
+ # - {:local_port}[rdoc-ref:Net::HTTP#local_port]:
+ # Returns the integer local port used to establish the connection.
+ # - {:local_port=}[rdoc-ref:Net::HTTP#local_port=]:
+ # Sets the integer local port used to establish the connection.
+ # - {:port}[rdoc-ref:Net::HTTP#port]:
+ # Returns the integer port number.
+ #
+ # === \HTTP Version
+ #
+ # - {::version_1_2?}[rdoc-ref:Net::HTTP.version_1_2?]
+ # (aliased as {::is_version_1_2?}[rdoc-ref:Net::HTTP.is_version_1_2?]
+ # and {::version_1_2}[rdoc-ref:Net::HTTP.version_1_2]):
+ # Returns true; retained for compatibility.
+ #
+ # === Debugging
+ #
+ # - {#set_debug_output}[rdoc-ref:Net::HTTP#set_debug_output]:
+ # Sets the output stream for debugging.
#
class HTTP < Protocol
# :stopdoc:
- VERSION = "0.1.1"
- Revision = %q$Revision$.split[1]
+ VERSION = "0.4.1"
HTTPVersion = '1.1'
begin
require 'zlib'
@@ -399,18 +732,17 @@ module Net #:nodoc:
end
# :startdoc:
- # Turns on net/http 1.2 (Ruby 1.8) features.
- # Defaults to ON in Ruby 1.8 or later.
+ # Returns +true+; retained for compatibility.
def HTTP.version_1_2
true
end
- # Returns true if net/http is in version 1.2 mode.
- # Defaults to true.
+ # Returns +true+; retained for compatibility.
def HTTP.version_1_2?
true
end
+ # Returns +false+; retained for compatibility.
def HTTP.version_1_1? #:nodoc:
false
end
@@ -420,25 +752,12 @@ module Net #:nodoc:
alias is_version_1_2? version_1_2? #:nodoc:
end
+ # :call-seq:
+ # Net::HTTP.get_print(hostname, path, port = 80) -> nil
+ # Net::HTTP:get_print(uri, headers = {}, port = uri.port) -> nil
#
- # short cut methods
- #
-
- #
- # Gets the body text from the target and outputs it to $stdout. The
- # target can either be specified as
- # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
- #
- # Net::HTTP.get_print URI('http://www.example.com/index.html')
- #
- # or:
- #
- # Net::HTTP.get_print 'www.example.com', '/index.html'
- #
- # you can also specify request headers:
- #
- # Net::HTTP.get_print URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }
- #
+ # Like Net::HTTP.get, but writes the returned body to $stdout;
+ # returns +nil+.
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|
@@ -448,40 +767,48 @@ module Net #:nodoc:
nil
end
- # Sends a GET request to the target and returns the HTTP response
- # as a string. The target can either be specified as
- # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
- #
- # print Net::HTTP.get(URI('http://www.example.com/index.html'))
+ # :call-seq:
+ # Net::HTTP.get(hostname, path, port = 80) -> body
+ # Net::HTTP:get(uri, headers = {}, port = uri.port) -> body
#
- # or:
+ # Sends a GET request and returns the \HTTP response body as a string.
#
- # print Net::HTTP.get('www.example.com', '/index.html')
+ # With string arguments +hostname+ and +path+:
#
- # you can also specify request headers:
+ # hostname = 'jsonplaceholder.typicode.com'
+ # path = '/todos/1'
+ # puts Net::HTTP.get(hostname, path)
#
- # Net::HTTP.get(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' })
+ # Output:
#
- 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+, +headers+), or as (+host+, +path+, +port+ = 80); so:
+ # {
+ # "userId": 1,
+ # "id": 1,
+ # "title": "delectus aut autem",
+ # "completed": false
+ # }
#
- # res = Net::HTTP.get_response(URI('http://www.example.com/index.html'))
- # print res.body
+ # With URI object +uri+ and optional hash argument +headers+:
#
- # or:
+ # uri = URI('https://jsonplaceholder.typicode.com/todos/1')
+ # headers = {'Content-type' => 'application/json; charset=UTF-8'}
+ # Net::HTTP.get(uri, headers)
#
- # res = Net::HTTP.get_response('www.example.com', '/index.html')
- # print res.body
+ # Related:
#
- # you can also specify request headers:
+ # - Net::HTTP::Get: request class for \HTTP method +GET+.
+ # - Net::HTTP#get: convenience method for \HTTP method +GET+.
#
- # Net::HTTP.get_response(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
+
+ # :call-seq:
+ # Net::HTTP.get_response(hostname, path, port = 80) -> http_response
+ # Net::HTTP:get_response(uri, headers = {}, port = uri.port) -> http_response
#
+ # Like Net::HTTP.get, but returns a Net::HTTPResponse object
+ # instead of the body string.
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
@@ -499,16 +826,31 @@ module Net #:nodoc:
end
end
- # Posts data to the specified URI object.
+ # Posts data to a host; returns a Net::HTTPResponse object.
#
- # Example:
+ # Argument +url+ must be a URL;
+ # argument +data+ must be a string:
+ #
+ # _uri = uri.dup
+ # _uri.path = '/posts'
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
+ # headers = {'content-type': 'application/json'}
+ # res = Net::HTTP.post(_uri, data, headers) # => #<Net::HTTPCreated 201 Created readbody=true>
+ # puts res.body
+ #
+ # Output:
#
- # require 'net/http'
- # require 'uri'
+ # {
+ # "title": "foo",
+ # "body": "bar",
+ # "userId": 1,
+ # "id": 101
+ # }
#
- # Net::HTTP.post URI('http://www.example.com/api/search'),
- # { "q" => "ruby", "max" => "50" }.to_json,
- # "Content-Type" => "application/json"
+ # Related:
+ #
+ # - Net::HTTP::Post: request class for \HTTP method +POST+.
+ # - Net::HTTP#post: convenience method for \HTTP method +POST+.
#
def HTTP.post(url, data, header = nil)
start(url.hostname, url.port,
@@ -517,22 +859,25 @@ module Net #:nodoc:
}
end
- # Posts HTML form data to the specified URI object.
- # The form data must be provided as a Hash mapping from String to String.
- # Example:
+ # Posts data to a host; returns a Net::HTTPResponse object.
#
- # { "cmd" => "search", "q" => "ruby", "max" => "50" }
+ # Argument +url+ must be a URI;
+ # argument +data+ must be a hash:
#
- # This method also does Basic Authentication if and only if +url+.user exists.
- # But userinfo for authentication is deprecated (RFC3986).
- # So this feature will be removed.
- #
- # Example:
+ # _uri = uri.dup
+ # _uri.path = '/posts'
+ # data = {title: 'foo', body: 'bar', userId: 1}
+ # res = Net::HTTP.post_form(_uri, data) # => #<Net::HTTPCreated 201 Created readbody=true>
+ # puts res.body
#
- # require 'net/http'
+ # Output:
#
- # Net::HTTP.post_form URI('http://www.example.com/search.cgi'),
- # { "q" => "ruby", "max" => "50" }
+ # {
+ # "title": "foo",
+ # "body": "bar",
+ # "userId": "1",
+ # "id": 101
+ # }
#
def HTTP.post_form(url, params)
req = Post.new(url)
@@ -545,20 +890,29 @@ module Net #:nodoc:
end
#
- # HTTP session management
+ # \HTTP session management
#
- # The default port to use for HTTP requests; defaults to 80.
+ # Returns integer +80+, the default port to use for \HTTP requests:
+ #
+ # Net::HTTP.default_port # => 80
+ #
def HTTP.default_port
http_default_port()
end
- # The default port to use for HTTP requests; defaults to 80.
+ # Returns integer +80+, the default port to use for \HTTP requests:
+ #
+ # Net::HTTP.http_default_port # => 80
+ #
def HTTP.http_default_port
80
end
- # The default port to use for HTTPS requests; defaults to 443.
+ # Returns integer +443+, the default port to use for HTTPS requests:
+ #
+ # Net::HTTP.https_default_port # => 443
+ #
def HTTP.https_default_port
443
end
@@ -568,35 +922,91 @@ module Net #:nodoc:
end
# :call-seq:
- # HTTP.start(address, port, p_addr, p_port, p_user, p_pass, &block)
- # HTTP.start(address, port=nil, p_addr=:ENV, p_port=nil, p_user=nil, p_pass=nil, opt, &block)
- #
- # Creates a new Net::HTTP object, then additionally opens the TCP
- # connection and HTTP session.
- #
- # Arguments are the following:
- # _address_ :: hostname or IP address of the server
- # _port_ :: port of the server
- # _p_addr_ :: address of proxy
- # _p_port_ :: port of proxy
- # _p_user_ :: user of proxy
- # _p_pass_ :: pass of proxy
- # _opt_ :: optional hash
- #
- # _opt_ sets following values by its accessor.
- # 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
- # verify_mode is set as OpenSSL::SSL::VERIFY_PEER.
- #
- # If the optional block is given, the newly
- # created Net::HTTP object is passed to it and closed when the
- # block finishes. In this case, the return value of this method
- # is the return value of the block. If no block is given, the
- # return value of this method is the newly created Net::HTTP object
- # itself, and the caller is responsible for closing it upon completion
- # using the finish() method.
+ # HTTP.start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) -> http
+ # HTTP.start(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, opts) {|http| ... } -> object
+ #
+ # Creates a new \Net::HTTP object, +http+, via \Net::HTTP.new:
+ #
+ # - For arguments +address+ and +port+, see Net::HTTP.new.
+ # - For proxy-defining arguments +p_addr+ through +p_pass+,
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
+ # - For argument +opts+, see below.
+ #
+ # With no block given:
+ #
+ # - Calls <tt>http.start</tt> with no block (see #start),
+ # which opens a TCP connection and \HTTP session.
+ # - Returns +http+.
+ # - The caller should call #finish to close the session:
+ #
+ # http = Net::HTTP.start(hostname)
+ # http.started? # => true
+ # http.finish
+ # http.started? # => false
+ #
+ # With a block given:
+ #
+ # - Calls <tt>http.start</tt> with the block (see #start), which:
+ #
+ # - Opens a TCP connection and \HTTP session.
+ # - Calls the block,
+ # which may make any number of requests to the host.
+ # - Closes the \HTTP session and TCP connection on block exit.
+ # - Returns the block's value +object+.
+ #
+ # - Returns +object+.
+ #
+ # Example:
+ #
+ # hostname = 'jsonplaceholder.typicode.com'
+ # Net::HTTP.start(hostname) do |http|
+ # puts http.get('/todos/1').body
+ # puts http.get('/todos/2').body
+ # end
+ #
+ # Output:
+ #
+ # {
+ # "userId": 1,
+ # "id": 1,
+ # "title": "delectus aut autem",
+ # "completed": false
+ # }
+ # {
+ # "userId": 1,
+ # "id": 2,
+ # "title": "quis ut nam facilis et officia qui",
+ # "completed": false
+ # }
+ #
+ # If the last argument given is a hash, it is the +opts+ hash,
+ # where each key is a method or accessor to be called,
+ # and its value is the value to be set.
+ #
+ # The keys may include:
+ #
+ # - #ca_file
+ # - #ca_path
+ # - #cert
+ # - #cert_store
+ # - #ciphers
+ # - #close_on_empty_response
+ # - +ipaddr+ (calls #ipaddr=)
+ # - #keep_alive_timeout
+ # - #key
+ # - #open_timeout
+ # - #read_timeout
+ # - #ssl_timeout
+ # - #ssl_version
+ # - +use_ssl+ (calls #use_ssl=)
+ # - #verify_callback
+ # - #verify_depth
+ # - #verify_mode
+ # - #write_timeout
+ #
+ # Note: If +port+ is +nil+ and <tt>opts[:use_ssl]</tt> is a truthy value,
+ # the value passed to +new+ is Net::HTTP.https_default_port, not +port+.
+ #
def HTTP.start(address, *arg, &block) # :yield: +http+
arg.pop if opt = Hash.try_convert(arg[-1])
port, p_addr, p_port, p_user, p_pass = *arg
@@ -623,25 +1033,34 @@ module Net #:nodoc:
alias newobj new # :nodoc:
end
- # Creates a new Net::HTTP object without opening a TCP connection or
- # HTTP session.
+ # Returns a new \Net::HTTP object +http+
+ # (but does not open a TCP connection or \HTTP session).
#
- # The +address+ should be a DNS hostname or IP address, the +port+ is the
- # port the server operates on. If no +port+ is given the default port for
- # HTTP or HTTPS is used.
+ # With only string argument +address+ given
+ # (and <tt>ENV['http_proxy']</tt> undefined or +nil+),
+ # the returned +http+:
#
- # If none of the +p_+ arguments are given, the proxy host and port are
- # taken from the +http_proxy+ environment variable (or its uppercase
- # equivalent) if present. If the proxy requires authentication you must
- # supply it by hand. See URI::Generic#find_proxy for details of proxy
- # detection from the environment. To disable proxy detection set +p_addr+
- # to nil.
+ # - Has the given address.
+ # - Has the default port number, Net::HTTP.default_port (80).
+ # - Has no proxy.
#
- # If you are connecting to a custom proxy, +p_addr+ specifies the DNS name
- # or IP address of the proxy host, +p_port+ the port to use to access the
- # proxy, +p_user+ and +p_pass+ the username and password if authorization
- # is required to use the proxy, and p_no_proxy hosts which do not
- # use the proxy.
+ # Example:
+ #
+ # http = Net::HTTP.new(hostname)
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
+ # http.address # => "jsonplaceholder.typicode.com"
+ # http.port # => 80
+ # http.proxy? # => false
+ #
+ # With integer argument +port+ also given,
+ # the returned +http+ has the given port:
+ #
+ # http = Net::HTTP.new(hostname, 8000)
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:8000 open=false>
+ # http.port # => 8000
+ #
+ # For proxy-defining arguments +p_addr+ through +p_no_proxy+,
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
#
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
http = super address, port
@@ -655,7 +1074,7 @@ module Net #:nodoc:
elsif p_addr == :ENV then
http.proxy_from_env = true
else
- if p_addr && p_no_proxy && !URI::Generic.use_proxy?(p_addr, p_addr, p_port, p_no_proxy)
+ if p_addr && p_no_proxy && !URI::Generic.use_proxy?(address, address, port, p_no_proxy)
p_addr = nil
p_port = nil
end
@@ -668,10 +1087,10 @@ module Net #:nodoc:
http
end
- # Creates a new Net::HTTP object for the specified server address,
- # without opening the TCP connection or initializing the HTTP session.
+ # Creates a new \Net::HTTP object for the specified server address,
+ # without opening the TCP connection or initializing the \HTTP session.
# The +address+ should be a DNS hostname or IP address.
- def initialize(address, port = nil)
+ def initialize(address, port = nil) # :nodoc:
@address = address
@port = (port || HTTP.default_port)
@ipaddr = nil
@@ -689,6 +1108,8 @@ module Net #:nodoc:
@continue_timeout = nil
@max_retries = 1
@debug_output = nil
+ @response_body_encoding = false
+ @ignore_eof = true
@proxy_from_env = false
@proxy_uri = nil
@@ -706,6 +1127,11 @@ module Net #:nodoc:
end
end
+ # Returns a string representation of +self+:
+ #
+ # Net::HTTP.new(hostname).inspect
+ # # => "#<Net::HTTP jsonplaceholder.typicode.com:80 open=false>"
+ #
def inspect
"#<#{self.class} #{@address}:#{@port} open=#{started?}>"
end
@@ -713,71 +1139,184 @@ module Net #:nodoc:
# *WARNING* This method opens a serious security hole.
# Never use this method in production code.
#
- # Sets an output stream for debugging.
+ # Sets the output stream for debugging:
#
# http = Net::HTTP.new(hostname)
- # http.set_debug_output $stderr
- # http.start { .... }
+ # File.open('t.tmp', 'w') do |file|
+ # http.set_debug_output(file)
+ # http.start
+ # http.get('/nosuch/1')
+ # http.finish
+ # end
+ # puts File.read('t.tmp')
+ #
+ # Output:
+ #
+ # opening connection to jsonplaceholder.typicode.com:80...
+ # opened
+ # <- "GET /nosuch/1 HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: jsonplaceholder.typicode.com\r\n\r\n"
+ # -> "HTTP/1.1 404 Not Found\r\n"
+ # -> "Date: Mon, 12 Dec 2022 21:14:11 GMT\r\n"
+ # -> "Content-Type: application/json; charset=utf-8\r\n"
+ # -> "Content-Length: 2\r\n"
+ # -> "Connection: keep-alive\r\n"
+ # -> "X-Powered-By: Express\r\n"
+ # -> "X-Ratelimit-Limit: 1000\r\n"
+ # -> "X-Ratelimit-Remaining: 999\r\n"
+ # -> "X-Ratelimit-Reset: 1670879660\r\n"
+ # -> "Vary: Origin, Accept-Encoding\r\n"
+ # -> "Access-Control-Allow-Credentials: true\r\n"
+ # -> "Cache-Control: max-age=43200\r\n"
+ # -> "Pragma: no-cache\r\n"
+ # -> "Expires: -1\r\n"
+ # -> "X-Content-Type-Options: nosniff\r\n"
+ # -> "Etag: W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"\r\n"
+ # -> "Via: 1.1 vegur\r\n"
+ # -> "CF-Cache-Status: MISS\r\n"
+ # -> "Server-Timing: cf-q-config;dur=1.3000000762986e-05\r\n"
+ # -> "Report-To: {\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=yOr40jo%2BwS1KHzhTlVpl54beJ5Wx2FcG4gGV0XVrh3X9OlR5q4drUn2dkt5DGO4GDcE%2BVXT7CNgJvGs%2BZleIyMu8CLieFiDIvOviOY3EhHg94m0ZNZgrEdpKD0S85S507l1vsEwEHkoTm%2Ff19SiO\"}],\"group\":\"cf-nel\",\"max_age\":604800}\r\n"
+ # -> "NEL: {\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}\r\n"
+ # -> "Server: cloudflare\r\n"
+ # -> "CF-RAY: 778977dc484ce591-DFW\r\n"
+ # -> "alt-svc: h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400\r\n"
+ # -> "\r\n"
+ # reading 2 bytes...
+ # -> "{}"
+ # read 2 bytes
+ # Conn keep-alive
#
def set_debug_output(output)
warn 'Net::HTTP#set_debug_output called after HTTP started', uplevel: 1 if started?
@debug_output = output
end
- # The DNS host name or IP address to connect to.
+ # Returns the string host name or host IP given as argument +address+ in ::new.
attr_reader :address
- # The port number to connect to.
+ # Returns the integer port number given as argument +port+ in ::new.
attr_reader :port
- # The local host used to establish the connection.
+ # Sets or returns the string local host used to establish the connection;
+ # initially +nil+.
attr_accessor :local_host
- # The local port used to establish the connection.
+ # Sets or returns the integer local port used to establish the connection;
+ # initially +nil+.
attr_accessor :local_port
+ # Returns the encoding to use for the response body;
+ # see #response_body_encoding=.
+ attr_reader :response_body_encoding
+
+ # Sets the encoding to be used for the response body;
+ # returns the encoding.
+ #
+ # The given +value+ may be:
+ #
+ # - An Encoding object.
+ # - The name of an encoding.
+ # - An alias for an encoding name.
+ #
+ # See {Encoding}[rdoc-ref:Encoding].
+ #
+ # Examples:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.response_body_encoding = Encoding::US_ASCII # => #<Encoding:US-ASCII>
+ # http.response_body_encoding = 'US-ASCII' # => "US-ASCII"
+ # http.response_body_encoding = 'ASCII' # => "ASCII"
+ #
+ def response_body_encoding=(value)
+ value = Encoding.find(value) if value.is_a?(String)
+ @response_body_encoding = value
+ end
+
+ # Sets whether to determine the proxy from environment variable
+ # '<tt>ENV['http_proxy']</tt>';
+ # see {Proxy Using ENV['http_proxy']}[rdoc-ref:Net::HTTP@Proxy+Using+-27ENV-5B-27http_proxy-27-5D-27].
attr_writer :proxy_from_env
+
+ # Sets the proxy address;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
attr_writer :proxy_address
+
+ # Sets the proxy port;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
attr_writer :proxy_port
+
+ # Sets the proxy user;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
attr_writer :proxy_user
+
+ # Sets the proxy password;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
attr_writer :proxy_pass
- # The IP address to connect to/used to connect to
+ # Returns the IP address for the connection.
+ #
+ # If the session has not been started,
+ # returns the value set by #ipaddr=,
+ # or +nil+ if it has not been set:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.ipaddr # => nil
+ # http.ipaddr = '172.67.155.76'
+ # http.ipaddr # => "172.67.155.76"
+ #
+ # If the session has been started,
+ # returns the IP address from the socket:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.start
+ # http.ipaddr # => "172.67.155.76"
+ # http.finish
+ #
def ipaddr
started? ? @socket.io.peeraddr[3] : @ipaddr
end
- # Set the IP address to connect to
+ # Sets the IP address for the connection:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.ipaddr # => nil
+ # http.ipaddr = '172.67.155.76'
+ # http.ipaddr # => "172.67.155.76"
+ #
+ # The IP address may not be set if the session has been started.
def ipaddr=(addr)
raise IOError, "ipaddr value changed, but session already started" if started?
@ipaddr = addr
end
- # Number of seconds to wait for the connection to open. Any number
- # may be used, including Floats for fractional seconds. If the HTTP
- # object cannot open a connection in this many seconds, it raises a
- # Net::OpenTimeout exception. The default value is 60 seconds.
+ # Sets or returns the numeric (\Integer or \Float) number of seconds
+ # to wait for a connection to open;
+ # initially 60.
+ # If the connection is not made in the given interval,
+ # an exception is raised.
attr_accessor :open_timeout
- # Number of seconds to wait for one block to be read (via one read(2)
- # call). Any number may be used, including Floats for fractional
- # seconds. If the HTTP object cannot read data in this many seconds,
- # it raises a Net::ReadTimeout exception. The default value is 60 seconds.
+ # Returns the numeric (\Integer or \Float) number of seconds
+ # to wait for one block to be read (via one read(2) call);
+ # see #read_timeout=.
attr_reader :read_timeout
- # Number of seconds to wait for one block to be written (via one write(2)
- # call). Any number may be used, including Floats for fractional
- # seconds. If the HTTP object cannot write data in this many seconds,
- # it raises a Net::WriteTimeout exception. The default value is 60 seconds.
- # Net::WriteTimeout is not raised on Windows.
+ # Returns the numeric (\Integer or \Float) number of seconds
+ # to wait for one block to be written (via one write(2) call);
+ # see #write_timeout=.
attr_reader :write_timeout
- # Maximum number of times to retry an idempotent request in case of
- # Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET,
+ # Sets the maximum number of times to retry an idempotent request in case of
+ # \Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET,
# Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError,
# Timeout::Error.
- # Should be a non-negative integer number. Zero means no retries.
- # The default value is 1.
+ # The initial value is 1.
+ #
+ # Argument +retries+ must be a non-negative numeric value:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.max_retries = 2 # => 2
+ # http.max_retries # => 2
+ #
def max_retries=(retries)
retries = retries.to_int
if retries < 0
@@ -786,55 +1325,113 @@ module Net #:nodoc:
@max_retries = retries
end
+ # Returns the maximum number of times to retry an idempotent request;
+ # see #max_retries=.
attr_reader :max_retries
- # Setter for the read_timeout attribute.
+ # Sets the read timeout, in seconds, for +self+ to integer +sec+;
+ # the initial value is 60.
+ #
+ # Argument +sec+ must be a non-negative numeric value:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.read_timeout # => 60
+ # http.get('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
+ # http.read_timeout = 0
+ # http.get('/todos/1') # Raises Net::ReadTimeout.
+ #
def read_timeout=(sec)
@socket.read_timeout = sec if @socket
@read_timeout = sec
end
- # Setter for the write_timeout attribute.
+ # Sets the write timeout, in seconds, for +self+ to integer +sec+;
+ # the initial value is 60.
+ #
+ # Argument +sec+ must be a non-negative numeric value:
+ #
+ # _uri = uri.dup
+ # _uri.path = '/posts'
+ # body = 'bar' * 200000
+ # data = <<EOF
+ # {"title": "foo", "body": "#{body}", "userId": "1"}
+ # EOF
+ # headers = {'content-type': 'application/json'}
+ # http = Net::HTTP.new(hostname)
+ # http.write_timeout # => 60
+ # http.post(_uri.path, data, headers)
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
+ # http.write_timeout = 0
+ # http.post(_uri.path, data, headers) # Raises Net::WriteTimeout.
+ #
def write_timeout=(sec)
@socket.write_timeout = sec if @socket
@write_timeout = sec
end
- # Seconds to wait for 100 Continue response. If the HTTP object does not
- # receive a response in this many seconds it sends the request body. The
- # default value is +nil+.
+ # Returns the continue timeout value;
+ # see continue_timeout=.
attr_reader :continue_timeout
- # Setter for the continue_timeout attribute.
+ # Sets the continue timeout value,
+ # which is the number of seconds to wait for an expected 100 Continue response.
+ # If the \HTTP object does not receive a response in this many seconds
+ # it sends the request body.
def continue_timeout=(sec)
@socket.continue_timeout = sec if @socket
@continue_timeout = sec
end
- # Seconds to reuse the connection of the previous request.
- # If the idle time is less than this Keep-Alive Timeout,
- # Net::HTTP reuses the TCP/IP socket used by the previous communication.
- # The default value is 2 seconds.
+ # Sets or returns the numeric (\Integer or \Float) number of seconds
+ # to keep the connection open after a request is sent;
+ # initially 2.
+ # If a new request is made during the given interval,
+ # the still-open connection is used;
+ # otherwise the connection will have been closed
+ # and a new connection is opened.
attr_accessor :keep_alive_timeout
- # Returns true if the HTTP session has been started.
+ # Sets or returns whether to ignore end-of-file when reading a response body
+ # with <tt>Content-Length</tt> headers;
+ # initially +true+.
+ attr_accessor :ignore_eof
+
+ # Returns +true+ if the \HTTP session has been started:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.started? # => false
+ # http.start
+ # http.started? # => true
+ # http.finish # => nil
+ # http.started? # => false
+ #
+ # Net::HTTP.start(hostname) do |http|
+ # http.started?
+ # end # => true
+ # http.started? # => false
+ #
def started?
@started
end
alias active? started? #:nodoc: obsolete
+ # Sets or returns whether to close the connection when the response is empty;
+ # initially +false+.
attr_accessor :close_on_empty_response
- # Returns true if SSL/TLS is being used with HTTP.
+ # Returns +true+ if +self+ uses SSL, +false+ otherwise.
+ # See Net::HTTP#use_ssl=.
def use_ssl?
@use_ssl
end
- # Turn on/off SSL.
- # This flag must be set before starting session.
- # If you change use_ssl value after session started,
- # a Net::HTTP object raises IOError.
+ # Sets whether a new session is to use
+ # {Transport Layer Security}[https://en.wikipedia.org/wiki/Transport_Layer_Security]:
+ #
+ # Raises IOError if attempting to change during a session.
+ #
+ # Raises OpenSSL::SSL::SSLError if the port is not an HTTPS port.
def use_ssl=(flag)
flag = flag ? true : false
if started? and @use_ssl != flag
@@ -859,7 +1456,7 @@ module Net #:nodoc:
:@verify_depth,
:@verify_mode,
:@verify_hostname,
- ]
+ ] # :nodoc:
SSL_ATTRIBUTES = [
:ca_file,
:ca_path,
@@ -876,64 +1473,67 @@ module Net #:nodoc:
:verify_depth,
:verify_mode,
:verify_hostname,
- ]
+ ] # :nodoc:
- # Sets path of a CA certification file in PEM format.
- #
- # The file can contain several CA certificates.
+ # Sets or returns the path to a CA certification file in PEM format.
attr_accessor :ca_file
- # Sets path of a CA certification directory containing certifications in
- # PEM format.
+ # Sets or returns the path of to CA directory
+ # containing certification files in PEM format.
attr_accessor :ca_path
- # Sets an OpenSSL::X509::Certificate object as client certificate.
- # (This method is appeared in Michal Rokos's OpenSSL extension).
+ # Sets or returns the OpenSSL::X509::Certificate object
+ # to be used for client certification.
attr_accessor :cert
- # Sets the X509::Store to verify peer certificate.
+ # Sets or returns the X509::Store to be used for verifying peer certificate.
attr_accessor :cert_store
- # Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers=
+ # Sets or returns the available SSL ciphers.
+ # See {OpenSSL::SSL::SSLContext#ciphers=}[rdoc-ref:OpenSSL::SSL::SSLContext#ciphers-3D].
attr_accessor :ciphers
- # Sets the extra X509 certificates to be added to the certificate chain.
- # See OpenSSL::SSL::SSLContext#extra_chain_cert=
+ # Sets or returns the extra X509 certificates to be added to the certificate chain.
+ # See {OpenSSL::SSL::SSLContext#add_certificate}[rdoc-ref:OpenSSL::SSL::SSLContext#add_certificate].
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.)
+ # Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
attr_accessor :key
- # Sets the SSL timeout seconds.
+ # Sets or returns the SSL timeout seconds.
attr_accessor :ssl_timeout
- # Sets the SSL version. See OpenSSL::SSL::SSLContext#ssl_version=
+ # Sets or returns the SSL version.
+ # See {OpenSSL::SSL::SSLContext#ssl_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#ssl_version-3D].
attr_accessor :ssl_version
- # Sets the minimum SSL version. See OpenSSL::SSL::SSLContext#min_version=
+ # Sets or returns the minimum SSL version.
+ # See {OpenSSL::SSL::SSLContext#min_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#min_version-3D].
attr_accessor :min_version
- # Sets the maximum SSL version. See OpenSSL::SSL::SSLContext#max_version=
+ # Sets or returns the maximum SSL version.
+ # See {OpenSSL::SSL::SSLContext#max_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#max_version-3D].
attr_accessor :max_version
- # Sets the verify callback for the server certification verification.
+ # Sets or returns the callback for the server certification verification.
attr_accessor :verify_callback
- # Sets the maximum depth for the certificate chain verification.
+ # Sets or returns the maximum depth for the certificate chain verification.
attr_accessor :verify_depth
- # Sets the flags for server the certification verification at beginning of
- # SSL/TLS session.
- #
+ # Sets or returns the flags for server the certification verification
+ # at the beginning of the SSL/TLS session.
# 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=
+ # Sets or returns whether to verify that the server certificate is valid
+ # for the hostname.
+ # See {OpenSSL::SSL::SSLContext#verify_hostname=}[rdoc-ref:OpenSSL::SSL::SSLContext#attribute-i-verify_mode].
attr_accessor :verify_hostname
- # Returns the X.509 certificates the server presented.
+ # Returns the X509 certificate chain (an array of strings)
+ # for the session's socket peer,
+ # or +nil+ if none.
def peer_cert
if not use_ssl? or not @socket
return nil
@@ -941,14 +1541,26 @@ module Net #:nodoc:
@socket.io.peer_cert
end
- # Opens a TCP connection and HTTP session.
+ # Starts an \HTTP session.
#
- # When this method is called with a block, it passes the Net::HTTP
- # object to the block, and closes the TCP connection and HTTP session
- # after the block has been executed.
+ # Without a block, returns +self+:
#
- # When called with a block, it returns the return value of the
- # block; otherwise, it returns self.
+ # http = Net::HTTP.new(hostname)
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
+ # http.start
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=true>
+ # http.started? # => true
+ # http.finish
+ #
+ # With a block, calls the block with +self+,
+ # finishes the session when the block exits,
+ # and returns the block's value:
+ #
+ # http.start do |http|
+ # http
+ # end
+ # # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false>
+ # http.started? # => false
#
def start # :yield: http
raise IOError, 'HTTP session already opened' if @started
@@ -985,24 +1597,25 @@ module Net #:nodoc:
conn_port = port
end
- D "opening connection to #{conn_addr}:#{conn_port}..."
- begin
- s = Socket.tcp conn_addr, conn_port, @local_host, @local_port, connect_timeout: @open_timeout
- rescue => e
- e = Net::OpenTimeout.new(e) if e.is_a?(Errno::ETIMEDOUT) #for compatibility with previous versions
- raise e, "Failed to open TCP connection to " +
- "#{conn_addr}:#{conn_port} (#{e.message})"
- end
+ debug "opening connection to #{conn_addr}:#{conn_port}..."
+ s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
+ begin
+ TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
+ rescue => e
+ raise e, "Failed to open TCP connection to " +
+ "#{conn_addr}:#{conn_port} (#{e.message})"
+ end
+ }
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
- D "opened"
+ debug "opened"
if use_ssl?
if proxy?
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
write_timeout: @write_timeout,
continue_timeout: @continue_timeout,
debug_output: @debug_output)
- buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
- buf << "Host: #{@address}:#{@port}\r\n"
+ buf = +"CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n" \
+ "Host: #{@address}:#{@port}\r\n"
if proxy_user
credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0')
buf << "Proxy-Authorization: Basic #{credential}\r\n"
@@ -1024,33 +1637,55 @@ module Net #:nodoc:
end
end
@ssl_context.set_params(ssl_parameters)
- @ssl_context.session_cache_mode =
- OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
- OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
- @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
- D "starting SSL for #{conn_addr}:#{conn_port}..."
+ unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
+ @ssl_context.session_cache_mode =
+ OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
+ OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
+ end
+ if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
+ @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
+ end
+
+ # Still do the post_connection_check below even if connecting
+ # to IP address
+ verify_hostname = @ssl_context.verify_hostname
+
+ # Server Name Indication (SNI) RFC 3546/6066
+ case @address
+ when Resolv::IPv4::Regex, Resolv::IPv6::Regex
+ # don't set SNI, as IP addresses in SNI is not valid
+ # per RFC 6066, section 3.
+
+ # Avoid openssl warning
+ @ssl_context.verify_hostname = false
+ else
+ ssl_host_address = @address
+ end
+
+ debug "starting SSL for #{conn_addr}:#{conn_port}..."
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
s.sync_close = true
- # Server Name Indication (SNI) RFC 3546
- s.hostname = @address if s.respond_to? :hostname=
+ s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
+
if @ssl_session and
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
s.session = @ssl_session
end
ssl_socket_connect(s, @open_timeout)
- if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
+ if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
s.post_connection_check(@address)
end
- D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
+ debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
end
@socket = BufferedIO.new(s, read_timeout: @read_timeout,
write_timeout: @write_timeout,
continue_timeout: @continue_timeout,
debug_output: @debug_output)
+ @last_communicated = nil
on_connect
rescue => exception
if s
- D "Conn close because of connect error #{exception}"
+ debug "Conn close because of connect error #{exception}"
s.close
end
raise
@@ -1061,8 +1696,15 @@ module Net #:nodoc:
end
private :on_connect
- # Finishes the HTTP session and closes the TCP connection.
- # Raises IOError if the session has not been started.
+ # Finishes the \HTTP session:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.start
+ # http.started? # => true
+ # http.finish # => nil
+ # http.started? # => false
+ #
+ # Raises IOError if not in a session.
def finish
raise IOError, 'HTTP session not yet started' unless started?
do_finish
@@ -1089,12 +1731,12 @@ module Net #:nodoc:
@proxy_user = nil
@proxy_pass = nil
- # Creates an HTTP proxy class which behaves like Net::HTTP, but
+ # Creates an \HTTP proxy class which behaves like \Net::HTTP, but
# performs all access via the specified proxy.
#
# This class is obsolete. You may pass these same parameters directly to
- # Net::HTTP.new. See Net::HTTP.new for details of the arguments.
- def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil)
+ # \Net::HTTP.new. See Net::HTTP.new for details of the arguments.
+ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc:
return self unless p_addr
Class.new(self) {
@@ -1116,31 +1758,37 @@ module Net #:nodoc:
end
class << HTTP
- # returns true if self is a class which was created by HTTP::Proxy.
+ # Returns true if self is a class which was created by HTTP::Proxy.
def proxy_class?
defined?(@is_proxy_class) ? @is_proxy_class : false
end
- # Address of proxy host. If Net::HTTP does not use a proxy, nil.
+ # Returns the address of the proxy host, or +nil+ if none;
+ # see Net::HTTP@Proxy+Server.
attr_reader :proxy_address
- # Port number of proxy host. If Net::HTTP does not use a proxy, nil.
+ # Returns the port number of the proxy host, or +nil+ if none;
+ # see Net::HTTP@Proxy+Server.
attr_reader :proxy_port
- # User name for accessing proxy. If Net::HTTP does not use a proxy, nil.
+ # Returns the user name for accessing the proxy, or +nil+ if none;
+ # see Net::HTTP@Proxy+Server.
attr_reader :proxy_user
- # User password for accessing proxy. If Net::HTTP does not use a proxy,
- # nil.
+ # Returns the password for accessing the proxy, or +nil+ if none;
+ # see Net::HTTP@Proxy+Server.
attr_reader :proxy_pass
end
- # True if requests for this connection will be proxied
+ # Returns +true+ if a proxy server is defined, +false+ otherwise;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
def proxy?
!!(@proxy_from_env ? proxy_uri : @proxy_address)
end
- # True if the proxy for this connection is determined from the environment
+ # Returns +true+ if the proxy server is defined in the environment,
+ # +false+ otherwise;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
def proxy_from_env?
@proxy_from_env
end
@@ -1149,12 +1797,13 @@ module Net #:nodoc:
def proxy_uri # :nodoc:
return if @proxy_uri == false
@proxy_uri ||= URI::HTTP.new(
- "http".freeze, nil, address, port, nil, nil, nil, nil, nil
+ "http", nil, address, port, nil, nil, nil, nil, nil
).find_proxy || false
@proxy_uri || nil
end
- # The address of the proxy server, if one is configured.
+ # Returns the address of the proxy server, if defined, +nil+ otherwise;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
def proxy_address
if @proxy_from_env then
proxy_uri&.hostname
@@ -1163,7 +1812,8 @@ module Net #:nodoc:
end
end
- # The port of the proxy server, if one is configured.
+ # Returns the port number of the proxy server, if defined, +nil+ otherwise;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
def proxy_port
if @proxy_from_env then
proxy_uri&.port
@@ -1172,16 +1822,10 @@ module Net #:nodoc:
end
end
- # [Bug #12921]
- if /linux|freebsd|darwin/ =~ RUBY_PLATFORM
- ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = true
- else
- ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = false
- end
-
- # The username of the proxy server, if one is configured.
+ # Returns the user name of the proxy server, if defined, +nil+ otherwise;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
def proxy_user
- if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
+ if @proxy_from_env
user = proxy_uri&.user
unescape(user) if user
else
@@ -1189,9 +1833,10 @@ module Net #:nodoc:
end
end
- # The password of the proxy server, if one is configured.
+ # Returns the password of the proxy server, if defined, +nil+ otherwise;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
def proxy_pass
- if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
+ if @proxy_from_env
pass = proxy_uri&.password
unescape(pass) if pass
else
@@ -1237,45 +1882,38 @@ module Net #:nodoc:
public
- # Retrieves data from +path+ on the connected-to host which may be an
- # absolute path String or a URI to extract the path from.
+ # :call-seq:
+ # get(path, initheader = nil) {|res| ... }
+ #
+ # Sends a GET request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Get object
+ # created from string +path+ and initial headers hash +initheader+.
#
- # +initheader+ must be a Hash like { 'Accept' => '*/*', ... },
- # and it defaults to an empty hash.
- # If +initheader+ doesn't have the key 'accept-encoding', then
- # a value of "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" is used,
- # so that gzip compression is used in preference to deflate
- # compression, which is used in preference to no compression.
- # Ruby doesn't have libraries to support the compress (Lempel-Ziv)
- # compression, so that is not supported. The intent of this is
- # to reduce bandwidth by default. If this routine sets up
- # compression, then it does the decompression also, removing
- # the header as well to prevent confusion. Otherwise
- # it leaves the body as it found it.
+ # With a block given, calls the block with the response body:
#
- # This method returns a Net::HTTPResponse object.
+ # http = Net::HTTP.new(hostname)
+ # http.get('/todos/1') do |res|
+ # p res
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
+ #
+ # Output:
#
- # If called with a block, yields each fragment of the
- # entity body in turn as a string as it is read from
- # the socket. Note that in this case, the returned response
- # object will *not* contain a (meaningful) body.
+ # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n}"
#
- # +dest+ argument is obsolete.
- # It still works but you must not use it.
+ # With no block given, simply returns the response object:
#
- # This method never raises an exception.
+ # http.get('/') # => #<Net::HTTPOK 200 OK readbody=true>
#
- # response = http.get('/index.html')
+ # Related:
#
- # # using block
- # File.open('result.txt', 'w') {|f|
- # http.get('/~foo/') do |str|
- # f.write str
- # end
- # }
+ # - Net::HTTP::Get: request class for \HTTP method GET.
+ # - Net::HTTP.get: sends GET request, returns response body.
#
def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+
res = nil
+
request(Get.new(path, initheader)) {|r|
r.read_body dest, &block
res = r
@@ -1283,198 +1921,312 @@ module Net #:nodoc:
res
end
- # Gets only the header from +path+ on the connected-to host.
- # +header+ is a Hash like { 'Accept' => '*/*', ... }.
- #
- # This method returns a Net::HTTPResponse object.
+ # Sends a HEAD request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
#
- # This method never raises an exception.
+ # The request is based on the Net::HTTP::Head object
+ # created from string +path+ and initial headers hash +initheader+:
#
- # response = nil
- # Net::HTTP.start('some.www.server', 80) {|http|
- # response = http.head('/index.html')
- # }
- # p response['content-type']
+ # res = http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
+ # res.body # => nil
+ # res.to_hash.take(3)
+ # # =>
+ # [["date", ["Wed, 15 Feb 2023 15:25:42 GMT"]],
+ # ["content-type", ["application/json; charset=utf-8"]],
+ # ["connection", ["close"]]]
#
def head(path, initheader = nil)
request(Head.new(path, initheader))
end
- # Posts +data+ (must be a String) to +path+. +header+ must be a Hash
- # like { 'Accept' => '*/*', ... }.
+ # :call-seq:
+ # post(path, data, initheader = nil) {|res| ... }
+ #
+ # Sends a POST request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
#
- # This method returns a Net::HTTPResponse object.
+ # The request is based on the Net::HTTP::Post object
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
#
- # If called with a block, yields each fragment of the
- # entity body in turn as a string as it is read from
- # the socket. Note that in this case, the returned response
- # object will *not* contain a (meaningful) body.
+ # With a block given, calls the block with the response body:
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.post('/todos', data) do |res|
+ # p res
+ # end # => #<Net::HTTPCreated 201 Created readbody=true>
#
- # +dest+ argument is obsolete.
- # It still works but you must not use it.
+ # Output:
#
- # This method never raises exception.
+ # "{\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\",\n \"id\": 201\n}"
#
- # response = http.post('/cgi-bin/search.rb', 'query=foo')
+ # With no block given, simply returns the response object:
#
- # # using block
- # File.open('result.txt', 'w') {|f|
- # http.post('/cgi-bin/search.rb', 'query=foo') do |str|
- # f.write str
- # end
- # }
+ # http.post('/todos', data) # => #<Net::HTTPCreated 201 Created readbody=true>
#
- # You should set Content-Type: header field for POST.
- # If no Content-Type: field given, this method uses
- # "application/x-www-form-urlencoded" by default.
+ # Related:
+ #
+ # - Net::HTTP::Post: request class for \HTTP method POST.
+ # - Net::HTTP.post: sends POST request, returns response body.
#
def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
send_entity(path, data, initheader, dest, Post, &block)
end
- # Sends a PATCH request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # :call-seq:
+ # patch(path, data, initheader = nil) {|res| ... }
+ #
+ # Sends a PATCH request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Patch object
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
+ #
+ # With a block given, calls the block with the response body:
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.patch('/todos/1', data) do |res|
+ # p res
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
+ #
+ # Output:
+ #
+ # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false,\n \"{\\\"userId\\\": 1, \\\"id\\\": 1, \\\"title\\\": \\\"delectus aut autem\\\", \\\"completed\\\": false}\": \"\"\n}"
+ #
+ # With no block given, simply returns the response object:
+ #
+ # http.patch('/todos/1', data) # => #<Net::HTTPCreated 201 Created readbody=true>
+ #
def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
send_entity(path, data, initheader, dest, Patch, &block)
end
- def put(path, data, initheader = nil) #:nodoc:
+ # Sends a PUT request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Put object
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.put('/todos/1', data) # => #<Net::HTTPOK 200 OK readbody=true>
+ #
+ def put(path, data, initheader = nil)
request(Put.new(path, initheader), data)
end
- # Sends a PROPPATCH request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a PROPPATCH request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Proppatch object
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.proppatch('/todos/1', data)
+ #
def proppatch(path, body, initheader = nil)
request(Proppatch.new(path, initheader), body)
end
- # Sends a LOCK request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a LOCK request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Lock object
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.lock('/todos/1', data)
+ #
def lock(path, body, initheader = nil)
request(Lock.new(path, initheader), body)
end
- # Sends a UNLOCK request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends an UNLOCK request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Unlock object
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.unlock('/todos/1', data)
+ #
def unlock(path, body, initheader = nil)
request(Unlock.new(path, initheader), body)
end
- # Sends a OPTIONS request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends an Options request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Options object
+ # created from string +path+ and initial headers hash +initheader+.
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.options('/')
+ #
def options(path, initheader = nil)
request(Options.new(path, initheader))
end
- # Sends a PROPFIND request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a PROPFIND request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Propfind object
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http = Net::HTTP.new(hostname)
+ # http.propfind('/todos/1', data)
+ #
def propfind(path, body = nil, initheader = {'Depth' => '0'})
request(Propfind.new(path, initheader), body)
end
- # Sends a DELETE request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a DELETE request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Delete object
+ # created from string +path+ and initial headers hash +initheader+.
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.delete('/todos/1')
+ #
def delete(path, initheader = {'Depth' => 'Infinity'})
request(Delete.new(path, initheader))
end
- # Sends a MOVE request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a MOVE request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Move object
+ # created from string +path+ and initial headers hash +initheader+.
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.move('/todos/1')
+ #
def move(path, initheader = nil)
request(Move.new(path, initheader))
end
- # Sends a COPY request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a COPY request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Copy object
+ # created from string +path+ and initial headers hash +initheader+.
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.copy('/todos/1')
+ #
def copy(path, initheader = nil)
request(Copy.new(path, initheader))
end
- # Sends a MKCOL request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a MKCOL request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Mkcol object
+ # created from string +path+, string +body+, and initial headers hash +initheader+.
+ #
+ # data = '{"userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}'
+ # http.mkcol('/todos/1', data)
+ # http = Net::HTTP.new(hostname)
+ #
def mkcol(path, body = nil, initheader = nil)
request(Mkcol.new(path, initheader), body)
end
- # Sends a TRACE request to the +path+ and gets a response,
- # as an HTTPResponse object.
+ # Sends a TRACE request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Trace object
+ # created from string +path+ and initial headers hash +initheader+.
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.trace('/todos/1')
+ #
def trace(path, initheader = nil)
request(Trace.new(path, initheader))
end
- # Sends a GET request to the +path+.
- # Returns the response as a Net::HTTPResponse object.
+ # Sends a GET request to the server;
+ # forms the response into a Net::HTTPResponse object.
#
- # When called with a block, passes an HTTPResponse object to the block.
- # The body of the response will not have been read yet;
- # the block can process it using HTTPResponse#read_body,
- # if desired.
+ # The request is based on the Net::HTTP::Get object
+ # created from string +path+ and initial headers hash +initheader+.
#
- # Returns the response.
+ # With no block given, returns the response object:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.request_get('/todos') # => #<Net::HTTPOK 200 OK readbody=true>
#
- # This method never raises Net::* exceptions.
+ # With a block given, calls the block with the response object
+ # and returns the response object:
#
- # response = http.request_get('/index.html')
- # # The entity body is already read in this case.
- # p response['content-type']
- # puts response.body
+ # http.request_get('/todos') do |res|
+ # p res
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
#
- # # Using a block
- # http.request_get('/index.html') {|response|
- # p response['content-type']
- # response.read_body do |str| # read body now
- # print str
- # end
- # }
+ # Output:
+ #
+ # #<Net::HTTPOK 200 OK readbody=false>
#
def request_get(path, initheader = nil, &block) # :yield: +response+
request(Get.new(path, initheader), &block)
end
- # Sends a HEAD request to the +path+ and returns the response
- # as a Net::HTTPResponse object.
- #
- # Returns the response.
+ # Sends a HEAD request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
#
- # This method never raises Net::* exceptions.
+ # The request is based on the Net::HTTP::Head object
+ # created from string +path+ and initial headers hash +initheader+.
#
- # response = http.request_head('/index.html')
- # p response['content-type']
+ # http = Net::HTTP.new(hostname)
+ # http.head('/todos/1') # => #<Net::HTTPOK 200 OK readbody=true>
#
def request_head(path, initheader = nil, &block)
request(Head.new(path, initheader), &block)
end
- # Sends a POST request to the +path+.
+ # Sends a POST request to the server;
+ # forms the response into a Net::HTTPResponse object.
#
- # Returns the response as a Net::HTTPResponse object.
+ # The request is based on the Net::HTTP::Post object
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
#
- # When called with a block, the block is passed an HTTPResponse
- # object. The body of that response will not have been read yet;
- # the block can process it using HTTPResponse#read_body, if desired.
+ # With no block given, returns the response object:
#
- # Returns the response.
+ # http = Net::HTTP.new(hostname)
+ # http.post('/todos', 'xyzzy')
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
+ #
+ # With a block given, calls the block with the response body
+ # and returns the response object:
#
- # This method never raises Net::* exceptions.
+ # http.post('/todos', 'xyzzy') do |res|
+ # p res
+ # end # => #<Net::HTTPCreated 201 Created readbody=true>
#
- # # example
- # response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
- # p response.status
- # puts response.body # body is already read in this case
+ # Output:
#
- # # using block
- # http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
- # p response.status
- # p response['content-type']
- # response.read_body do |str| # read body now
- # print str
- # end
- # }
+ # "{\n \"xyzzy\": \"\",\n \"id\": 201\n}"
#
def request_post(path, data, initheader = nil, &block) # :yield: +response+
request Post.new(path, initheader), data, &block
end
+ # Sends a PUT request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
+ #
+ # The request is based on the Net::HTTP::Put object
+ # created from string +path+, string +data+, and initial headers hash +initheader+.
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.put('/todos/1', 'xyzzy')
+ # # => #<Net::HTTPOK 200 OK readbody=true>
+ #
def request_put(path, data, initheader = nil, &block) #:nodoc:
request Put.new(path, initheader), data, &block
end
@@ -1484,16 +2236,25 @@ module Net #:nodoc:
alias post2 request_post #:nodoc: obsolete
alias put2 request_put #:nodoc: obsolete
-
- # Sends an HTTP request to the HTTP server.
- # Also sends a DATA string if +data+ is given.
+ # Sends an \HTTP request to the server;
+ # returns an instance of a subclass of Net::HTTPResponse.
#
- # Returns a Net::HTTPResponse object.
+ # The request is based on the Net::HTTPRequest object
+ # created from string +path+, string +data+, and initial headers hash +header+.
+ # That object is an instance of the
+ # {subclass of Net::HTTPRequest}[rdoc-ref:Net::HTTPRequest@Request+Subclasses],
+ # that corresponds to the given uppercase string +name+,
+ # which must be
+ # an {HTTP request method}[https://en.wikipedia.org/wiki/HTTP#Request_methods]
+ # or a {WebDAV request method}[https://en.wikipedia.org/wiki/WebDAV#Implementation].
#
- # This method never raises Net::* exceptions.
+ # Examples:
#
- # response = http.send_request('GET', '/index.html')
- # puts response.body
+ # http = Net::HTTP.new(hostname)
+ # http.send_request('GET', '/todos/1')
+ # # => #<Net::HTTPOK 200 OK readbody=true>
+ # http.send_request('POST', '/todos', 'xyzzy')
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
#
def send_request(name, path, data = nil, header = nil)
has_response_body = name != 'HEAD'
@@ -1501,20 +2262,35 @@ module Net #:nodoc:
request r, data
end
- # Sends an HTTPRequest object +req+ to the HTTP server.
+ # Sends the given request +req+ to the server;
+ # forms the response into a Net::HTTPResponse object.
#
- # If +req+ is a Net::HTTP::Post or Net::HTTP::Put request containing
- # data, the data is also sent. Providing data for a Net::HTTP::Head or
- # Net::HTTP::Get request results in an ArgumentError.
+ # The given +req+ must be an instance of a
+ # {subclass of Net::HTTPRequest}[rdoc-ref:Net::HTTPRequest@Request+Subclasses].
+ # Argument +body+ should be given only if needed for the request.
#
- # Returns an HTTPResponse object.
+ # With no block given, returns the response object:
#
- # When called with a block, passes an HTTPResponse object to the block.
- # The body of the response will not have been read yet;
- # the block can process it using HTTPResponse#read_body,
- # if desired.
+ # http = Net::HTTP.new(hostname)
+ #
+ # req = Net::HTTP::Get.new('/todos/1')
+ # http.request(req)
+ # # => #<Net::HTTPOK 200 OK readbody=true>
+ #
+ # req = Net::HTTP::Post.new('/todos')
+ # http.request(req, 'xyzzy')
+ # # => #<Net::HTTPCreated 201 Created readbody=true>
+ #
+ # With a block given, calls the block with the response and returns the response:
#
- # This method never raises Net::* exceptions.
+ # req = Net::HTTP::Get.new('/todos/1')
+ # http.request(req) do |res|
+ # p res
+ # end # => #<Net::HTTPOK 200 OK readbody=true>
+ #
+ # Output:
+ #
+ # #<Net::HTTPOK 200 OK readbody=false>
#
def request(req, body = nil, &block) # :yield: +response+
unless started?
@@ -1565,6 +2341,8 @@ module Net #:nodoc:
begin
res = HTTPResponse.read_new(@socket)
res.decode_content = req.decode_content
+ res.body_encoding = @response_body_encoding
+ res.ignore_eof = @ignore_eof
end while res.kind_of?(HTTPInformation)
res.uri = req.uri
@@ -1584,10 +2362,10 @@ module Net #:nodoc:
if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method)
count += 1
@socket.close if @socket
- D "Conn close because of error #{exception}, and retry"
+ debug "Conn close because of error #{exception}, and retry"
retry
end
- D "Conn close because of error #{exception}"
+ debug "Conn close because of error #{exception}"
@socket.close if @socket
raise
end
@@ -1595,7 +2373,7 @@ module Net #:nodoc:
end_transport req, res
res
rescue => exception
- D "Conn close because of error #{exception}"
+ debug "Conn close because of error #{exception}"
@socket.close if @socket
raise exception
end
@@ -1605,11 +2383,11 @@ module Net #:nodoc:
connect
elsif @last_communicated
if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
- D 'Conn close because of keep_alive_timeout'
+ debug 'Conn close because of keep_alive_timeout'
@socket.close
connect
elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
- D "Conn close because of EOF"
+ debug "Conn close because of EOF"
@socket.close
connect
end
@@ -1627,15 +2405,15 @@ module Net #:nodoc:
@curr_http_version = res.http_version
@last_communicated = nil
if @socket.closed?
- D 'Conn socket closed'
+ debug 'Conn socket closed'
elsif not res.body and @close_on_empty_response
- D 'Conn close'
+ debug 'Conn close'
@socket.close
elsif keep_alive?(req, res)
- D 'Conn keep-alive'
+ debug 'Conn keep-alive'
@last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
else
- D 'Conn close'
+ debug 'Conn close'
@socket.close
end
end
@@ -1690,11 +2468,14 @@ module Net #:nodoc:
default_port == port ? addr : "#{addr}:#{port}"
end
- def D(msg)
+ # Adds a message to debugging output
+ def debug(msg)
return unless @debug_output
@debug_output << msg
@debug_output << "\n"
end
+
+ alias_method :D, :debug
end
end
diff --git a/lib/net/http/backward.rb b/lib/net/http/backward.rb
index 9e24eae32c..b44577edbd 100644
--- a/lib/net/http/backward.rb
+++ b/lib/net/http/backward.rb
@@ -1,26 +1,40 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
# for backward compatibility
# :enddoc:
class Net::HTTP
ProxyMod = ProxyDelta
-end
-
-module Net
- HTTPSession = Net::HTTP
+ deprecate_constant :ProxyMod
end
module Net::NetPrivate
HTTPRequest = ::Net::HTTPRequest
+ deprecate_constant :HTTPRequest
end
-Net::HTTPInformationCode = Net::HTTPInformation
-Net::HTTPSuccessCode = Net::HTTPSuccess
-Net::HTTPRedirectionCode = Net::HTTPRedirection
-Net::HTTPRetriableCode = Net::HTTPRedirection
-Net::HTTPClientErrorCode = Net::HTTPClientError
-Net::HTTPFatalErrorCode = Net::HTTPClientError
-Net::HTTPServerErrorCode = Net::HTTPServerError
-Net::HTTPResponceReceiver = Net::HTTPResponse
+module Net
+ HTTPSession = HTTP
+ HTTPInformationCode = HTTPInformation
+ HTTPSuccessCode = HTTPSuccess
+ HTTPRedirectionCode = HTTPRedirection
+ HTTPRetriableCode = HTTPRedirection
+ HTTPClientErrorCode = HTTPClientError
+ HTTPFatalErrorCode = HTTPClientError
+ HTTPServerErrorCode = HTTPServerError
+ HTTPResponseReceiver = HTTPResponse
+
+ HTTPResponceReceiver = HTTPResponse # Typo since 2001
+
+ deprecate_constant :HTTPSession,
+ :HTTPInformationCode,
+ :HTTPSuccessCode,
+ :HTTPRedirectionCode,
+ :HTTPRetriableCode,
+ :HTTPClientErrorCode,
+ :HTTPFatalErrorCode,
+ :HTTPServerErrorCode,
+ :HTTPResponseReceiver,
+ :HTTPResponceReceiver
+end
diff --git a/lib/net/http/exceptions.rb b/lib/net/http/exceptions.rb
index da5f7a70fc..ceec8f7b0a 100644
--- a/lib/net/http/exceptions.rb
+++ b/lib/net/http/exceptions.rb
@@ -1,33 +1,34 @@
-# frozen_string_literal: false
-# Net::HTTP exception class.
-# You cannot use Net::HTTPExceptions directly; instead, you must use
-# its subclasses.
-module Net::HTTPExceptions
- def initialize(msg, res) #:nodoc:
- super msg
- @response = res
+# frozen_string_literal: true
+module Net
+ # Net::HTTP exception class.
+ # You cannot use Net::HTTPExceptions directly; instead, you must use
+ # its subclasses.
+ module HTTPExceptions
+ def initialize(msg, res) #:nodoc:
+ super msg
+ @response = res
+ end
+ attr_reader :response
+ alias data response #:nodoc: obsolete
end
- attr_reader :response
- alias data response #:nodoc: obsolete
-end
-class Net::HTTPError < Net::ProtocolError
- include Net::HTTPExceptions
-end
-class Net::HTTPRetriableError < Net::ProtoRetriableError
- include Net::HTTPExceptions
-end
-class Net::HTTPServerException < Net::ProtoServerError
- # We cannot use the name "HTTPServerError", it is the name of the response.
- include Net::HTTPExceptions
-end
-# for compatibility
-Net::HTTPClientException = Net::HTTPServerException
+ class HTTPError < ProtocolError
+ include HTTPExceptions
+ end
-class Net::HTTPFatalError < Net::ProtoFatalError
- include Net::HTTPExceptions
-end
+ class HTTPRetriableError < ProtoRetriableError
+ include HTTPExceptions
+ end
-module Net
+ class HTTPClientException < ProtoServerError
+ include HTTPExceptions
+ end
+
+ class HTTPFatalError < ProtoFatalError
+ include HTTPExceptions
+ end
+
+ # We cannot use the name "HTTPServerError", it is the name of the response.
+ HTTPServerException = HTTPClientException # :nodoc:
deprecate_constant(:HTTPServerException)
end
diff --git a/lib/net/http/generic_request.rb b/lib/net/http/generic_request.rb
index d6198cd624..44e329a0c8 100644
--- a/lib/net/http/generic_request.rb
+++ b/lib/net/http/generic_request.rb
@@ -1,24 +1,29 @@
-# frozen_string_literal: false
-# HTTPGenericRequest is the parent of the Net::HTTPRequest class.
-# Do not use this directly; use a subclass of Net::HTTPRequest.
+# frozen_string_literal: true
#
-# Mixes in the Net::HTTPHeader module to provide easier access to HTTP headers.
+# \HTTPGenericRequest is the parent of the Net::HTTPRequest class.
+#
+# Do not use this directly; instead, use a subclass of Net::HTTPRequest.
+#
+# == About the Examples
+#
+# :include: doc/net-http/examples.rdoc
#
class Net::HTTPGenericRequest
include Net::HTTPHeader
- def initialize(m, reqbody, resbody, uri_or_path, initheader = nil)
+ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc:
@method = m
@request_has_body = reqbody
@response_has_body = resbody
if URI === uri_or_path then
raise ArgumentError, "not an HTTP URI" unless URI::HTTP === uri_or_path
- raise ArgumentError, "no host component for URI" unless uri_or_path.hostname
+ hostname = uri_or_path.hostname
+ raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0)
@uri = uri_or_path.dup
host = @uri.hostname.dup
- host << ":".freeze << @uri.port.to_s if @uri.port != @uri.default_port
+ host << ":" << @uri.port.to_s if @uri.port != @uri.default_port
@path = uri_or_path.request_uri
raise ArgumentError, "no HTTP request path given" unless @path
else
@@ -31,12 +36,12 @@ class Net::HTTPGenericRequest
@decode_content = false
- if @response_has_body and Net::HTTP::HAVE_ZLIB then
+ if Net::HTTP::HAVE_ZLIB then
if !initheader ||
!initheader.keys.any? { |k|
%w[accept-encoding range].include? k.downcase
} then
- @decode_content = true
+ @decode_content = true if @response_has_body
initheader = initheader ? initheader.dup : {}
initheader["accept-encoding"] =
"gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
@@ -52,15 +57,47 @@ class Net::HTTPGenericRequest
@body_data = nil
end
+ # Returns the string method name for the request:
+ #
+ # Net::HTTP::Get.new(uri).method # => "GET"
+ # Net::HTTP::Post.new(uri).method # => "POST"
+ #
attr_reader :method
+
+ # Returns the string path for the request:
+ #
+ # Net::HTTP::Get.new(uri).path # => "/"
+ # Net::HTTP::Post.new('example.com').path # => "example.com"
+ #
attr_reader :path
+
+ # Returns the URI object for the request, or +nil+ if none:
+ #
+ # Net::HTTP::Get.new(uri).uri
+ # # => #<URI::HTTPS https://jsonplaceholder.typicode.com/>
+ # Net::HTTP::Get.new('example.com').uri # => nil
+ #
attr_reader :uri
- # Automatically set to false if the user sets the Accept-Encoding header.
- # This indicates they wish to handle Content-encoding in responses
- # themselves.
+ # Returns +false+ if the request's header <tt>'Accept-Encoding'</tt>
+ # has been set manually or deleted
+ # (indicating that the user intends to handle encoding in the response),
+ # +true+ otherwise:
+ #
+ # req = Net::HTTP::Get.new(uri) # => #<Net::HTTP::Get GET>
+ # req['Accept-Encoding'] # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
+ # req.decode_content # => true
+ # req['Accept-Encoding'] = 'foo'
+ # req.decode_content # => false
+ # req.delete('Accept-Encoding')
+ # req.decode_content # => false
+ #
attr_reader :decode_content
+ # Returns a string representation of the request:
+ #
+ # Net::HTTP::Post.new(uri).inspect # => "#<Net::HTTP::Post POST>"
+ #
def inspect
"\#<#{self.class} #{@method}>"
end
@@ -75,21 +112,45 @@ class Net::HTTPGenericRequest
super key, val
end
+ # Returns whether the request may have a body:
+ #
+ # Net::HTTP::Post.new(uri).request_body_permitted? # => true
+ # Net::HTTP::Get.new(uri).request_body_permitted? # => false
+ #
def request_body_permitted?
@request_has_body
end
+ # Returns whether the response may have a body:
+ #
+ # Net::HTTP::Post.new(uri).response_body_permitted? # => true
+ # Net::HTTP::Head.new(uri).response_body_permitted? # => false
+ #
def response_body_permitted?
@response_has_body
end
- def body_exist?
+ def body_exist? # :nodoc:
warn "Net::HTTPRequest#body_exist? is obsolete; use response_body_permitted?", uplevel: 1 if $VERBOSE
response_body_permitted?
end
+ # Returns the string body for the request, or +nil+ if there is none:
+ #
+ # req = Net::HTTP::Post.new(uri)
+ # req.body # => nil
+ # req.body = '{"title": "foo","body": "bar","userId": 1}'
+ # req.body # => "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}"
+ #
attr_reader :body
+ # Sets the body for the request:
+ #
+ # req = Net::HTTP::Post.new(uri)
+ # req.body # => nil
+ # req.body = '{"title": "foo","body": "bar","userId": 1}'
+ # req.body # => "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}"
+ #
def body=(str)
@body = str
@body_stream = nil
@@ -97,8 +158,24 @@ class Net::HTTPGenericRequest
str
end
+ # Returns the body stream object for the request, or +nil+ if there is none:
+ #
+ # req = Net::HTTP::Post.new(uri) # => #<Net::HTTP::Post POST>
+ # req.body_stream # => nil
+ # require 'stringio'
+ # req.body_stream = StringIO.new('xyzzy') # => #<StringIO:0x0000027d1e5affa8>
+ # req.body_stream # => #<StringIO:0x0000027d1e5affa8>
+ #
attr_reader :body_stream
+ # Sets the body stream for the request:
+ #
+ # req = Net::HTTP::Post.new(uri) # => #<Net::HTTP::Post POST>
+ # req.body_stream # => nil
+ # require 'stringio'
+ # req.body_stream = StringIO.new('xyzzy') # => #<StringIO:0x0000027d1e5affa8>
+ # req.body_stream # => #<StringIO:0x0000027d1e5affa8>
+ #
def body_stream=(input)
@body = nil
@body_stream = input
@@ -135,15 +212,15 @@ class Net::HTTPGenericRequest
return unless @uri
if ssl
- scheme = 'https'.freeze
+ scheme = 'https'
klass = URI::HTTPS
else
- scheme = 'http'.freeze
+ scheme = 'http'
klass = URI::HTTP
end
if host = self['host']
- host.sub!(/:.*/m, ''.freeze)
+ host.sub!(/:.*/m, '')
elsif host = @uri.host
else
host = addr
@@ -239,7 +316,7 @@ class Net::HTTPGenericRequest
boundary ||= SecureRandom.urlsafe_base64(40)
chunked_p = chunked?
- buf = ''
+ buf = +''
params.each do |key, value, h={}|
key = quote_string(key, charset)
filename =
@@ -324,7 +401,7 @@ class Net::HTTPGenericRequest
if /[\r\n]/ =~ reqline
raise ArgumentError, "A Request-Line must not contain CR or LF"
end
- buf = ""
+ buf = +''
buf << reqline << "\r\n"
each_capitalized do |k,v|
buf << "#{k}: #{v}\r\n"
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index a8901e79cb..6660c8075a 100644
--- a/lib/net/http/header.rb
+++ b/lib/net/http/header.rb
@@ -1,16 +1,188 @@
-# frozen_string_literal: false
-# The HTTPHeader module defines methods for reading and writing
-# HTTP headers.
+# frozen_string_literal: true
#
-# It is used as a mixin by other classes, to provide hash-like
-# access to HTTP header values. Unlike raw hash access, HTTPHeader
-# provides access via case-insensitive keys. It also provides
-# methods for accessing commonly-used HTTP header values in more
-# convenient formats.
+# The \HTTPHeader module provides access to \HTTP headers.
+#
+# The module is included in:
+#
+# - Net::HTTPGenericRequest (and therefore Net::HTTPRequest).
+# - Net::HTTPResponse.
+#
+# The headers are a hash-like collection of key/value pairs called _fields_.
+#
+# == Request and Response Fields
+#
+# Headers may be included in:
+#
+# - A Net::HTTPRequest object:
+# the object's headers will be sent with the request.
+# Any fields may be defined in the request;
+# see {Setters}[rdoc-ref:Net::HTTPHeader@Setters].
+# - A Net::HTTPResponse object:
+# the objects headers are usually those returned from the host.
+# Fields may be retrieved from the object;
+# see {Getters}[rdoc-ref:Net::HTTPHeader@Getters]
+# and {Iterators}[rdoc-ref:Net::HTTPHeader@Iterators].
+#
+# Exactly which fields should be sent or expected depends on the host;
+# see:
+#
+# - {Request fields}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields].
+# - {Response fields}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Response_fields].
+#
+# == About the Examples
+#
+# :include: doc/net-http/examples.rdoc
+#
+# == Fields
+#
+# A header field is a key/value pair.
+#
+# === Field Keys
+#
+# A field key may be:
+#
+# - A string: Key <tt>'Accept'</tt> is treated as if it were
+# <tt>'Accept'.downcase</tt>; i.e., <tt>'accept'</tt>.
+# - A symbol: Key <tt>:Accept</tt> is treated as if it were
+# <tt>:Accept.to_s.downcase</tt>; i.e., <tt>'accept'</tt>.
+#
+# Examples:
+#
+# req = Net::HTTP::Get.new(uri)
+# req[:accept] # => "*/*"
+# req['Accept'] # => "*/*"
+# req['ACCEPT'] # => "*/*"
+#
+# req['accept'] = 'text/html'
+# req[:accept] = 'text/html'
+# req['ACCEPT'] = 'text/html'
+#
+# === Field Values
+#
+# A field value may be returned as an array of strings or as a string:
+#
+# - These methods return field values as arrays:
+#
+# - #get_fields: Returns the array value for the given key,
+# or +nil+ if it does not exist.
+# - #to_hash: Returns a hash of all header fields:
+# each key is a field name; its value is the array value for the field.
+#
+# - These methods return field values as string;
+# the string value for a field is equivalent to
+# <tt>self[key.downcase.to_s].join(', '))</tt>:
+#
+# - #[]: Returns the string value for the given key,
+# or +nil+ if it does not exist.
+# - #fetch: Like #[], but accepts a default value
+# to be returned if the key does not exist.
+#
+# The field value may be set:
+#
+# - #[]=: Sets the value for the given key;
+# the given value may be a string, a symbol, an array, or a hash.
+# - #add_field: Adds a given value to a value for the given key
+# (not overwriting the existing value).
+# - #delete: Deletes the field for the given key.
+#
+# Example field values:
+#
+# - \String:
+#
+# req['Accept'] = 'text/html' # => "text/html"
+# req['Accept'] # => "text/html"
+# req.get_fields('Accept') # => ["text/html"]
+#
+# - \Symbol:
+#
+# req['Accept'] = :text # => :text
+# req['Accept'] # => "text"
+# req.get_fields('Accept') # => ["text"]
+#
+# - Simple array:
+#
+# req[:foo] = %w[bar baz bat]
+# req[:foo] # => "bar, baz, bat"
+# req.get_fields(:foo) # => ["bar", "baz", "bat"]
+#
+# - Simple hash:
+#
+# req[:foo] = {bar: 0, baz: 1, bat: 2}
+# req[:foo] # => "bar, 0, baz, 1, bat, 2"
+# req.get_fields(:foo) # => ["bar", "0", "baz", "1", "bat", "2"]
+#
+# - Nested:
+#
+# req[:foo] = [%w[bar baz], {bat: 0, bam: 1}]
+# req[:foo] # => "bar, baz, bat, 0, bam, 1"
+# req.get_fields(:foo) # => ["bar", "baz", "bat", "0", "bam", "1"]
+#
+# req[:foo] = {bar: %w[baz bat], bam: {bah: 0, bad: 1}}
+# req[:foo] # => "bar, baz, bat, bam, bah, 0, bad, 1"
+# req.get_fields(:foo) # => ["bar", "baz", "bat", "bam", "bah", "0", "bad", "1"]
+#
+# == Convenience Methods
+#
+# Various convenience methods retrieve values, set values, query values,
+# set form values, or iterate over fields.
+#
+# === Setters
+#
+# \Method #[]= can set any field, but does little to validate the new value;
+# some of the other setter methods provide some validation:
+#
+# - #[]=: Sets the string or array value for the given key.
+# - #add_field: Creates or adds to the array value for the given key.
+# - #basic_auth: Sets the string authorization header for <tt>'Authorization'</tt>.
+# - #content_length=: Sets the integer length for field <tt>'Content-Length</tt>.
+# - #content_type=: Sets the string value for field <tt>'Content-Type'</tt>.
+# - #proxy_basic_auth: Sets the string authorization header for <tt>'Proxy-Authorization'</tt>.
+# - #set_range: Sets the value for field <tt>'Range'</tt>.
+#
+# === Form Setters
+#
+# - #set_form: Sets an HTML form data set.
+# - #set_form_data: Sets header fields and a body from HTML form data.
+#
+# === Getters
+#
+# \Method #[] can retrieve the value of any field that exists,
+# but always as a string;
+# some of the other getter methods return something different
+# from the simple string value:
+#
+# - #[]: Returns the string field value for the given key.
+# - #content_length: Returns the integer value of field <tt>'Content-Length'</tt>.
+# - #content_range: Returns the Range value of field <tt>'Content-Range'</tt>.
+# - #content_type: Returns the string value of field <tt>'Content-Type'</tt>.
+# - #fetch: Returns the string field value for the given key.
+# - #get_fields: Returns the array field value for the given +key+.
+# - #main_type: Returns first part of the string value of field <tt>'Content-Type'</tt>.
+# - #sub_type: Returns second part of the string value of field <tt>'Content-Type'</tt>.
+# - #range: Returns an array of Range objects of field <tt>'Range'</tt>, or +nil+.
+# - #range_length: Returns the integer length of the range given in field <tt>'Content-Range'</tt>.
+# - #type_params: Returns the string parameters for <tt>'Content-Type'</tt>.
+#
+# === Queries
+#
+# - #chunked?: Returns whether field <tt>'Transfer-Encoding'</tt> is set to <tt>'chunked'</tt>.
+# - #connection_close?: Returns whether field <tt>'Connection'</tt> is set to <tt>'close'</tt>.
+# - #connection_keep_alive?: Returns whether field <tt>'Connection'</tt> is set to <tt>'keep-alive'</tt>.
+# - #key?: Returns whether a given key exists.
+#
+# === Iterators
+#
+# - #each_capitalized: Passes each field capitalized-name/value pair to the block.
+# - #each_capitalized_name: Passes each capitalized field name to the block.
+# - #each_header: Passes each field name/value pair to the block.
+# - #each_name: Passes each field name to the block.
+# - #each_value: Passes each string field value to the block.
#
module Net::HTTPHeader
+ MAX_KEY_LENGTH = 1024
+ MAX_FIELD_LENGTH = 65536
- def initialize_http_header(initheader)
+ def initialize_http_header(initheader) #:nodoc:
@header = {}
return unless initheader
initheader.each do |key, value|
@@ -19,6 +191,12 @@ module Net::HTTPHeader
warn "net/http: nil HTTP header: #{key}", uplevel: 3 if $VERBOSE
else
value = value.strip # raise error for invalid byte sequences
+ if key.to_s.bytesize > MAX_KEY_LENGTH
+ raise ArgumentError, "too long (#{key.bytesize} bytes) header: #{key[0, 30].inspect}..."
+ end
+ if value.to_s.bytesize > MAX_FIELD_LENGTH
+ raise ArgumentError, "header #{key} has too long field value: #{value.bytesize}"
+ end
if value.count("\r\n") > 0
raise ArgumentError, "header #{key} has field value #{value.inspect}, this cannot include CR/LF"
end
@@ -33,14 +211,32 @@ module Net::HTTPHeader
alias length size #:nodoc: obsolete
- # Returns the header field corresponding to the case-insensitive key.
- # For example, a key of "Content-Type" might return "text/html"
+ # Returns the string field value for the case-insensitive field +key+,
+ # or +nil+ if there is no such key;
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['Connection'] # => "keep-alive"
+ # res['Nosuch'] # => nil
+ #
+ # Note that some field values may be retrieved via convenience methods;
+ # see {Getters}[rdoc-ref:Net::HTTPHeader@Getters].
def [](key)
a = @header[key.downcase.to_s] or return nil
a.join(', ')
end
- # Sets the header field corresponding to the case-insensitive key.
+ # Sets the value for the case-insensitive +key+ to +val+,
+ # overwriting the previous value if the field exists;
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req['Accept'] # => "*/*"
+ # req['Accept'] = 'text/html'
+ # req['Accept'] # => "text/html"
+ #
+ # Note that some field values may be set via convenience methods;
+ # see {Setters}[rdoc-ref:Net::HTTPHeader@Setters].
def []=(key, val)
unless val
@header.delete key.downcase.to_s
@@ -49,20 +245,18 @@ module Net::HTTPHeader
set_field(key, val)
end
- # [Ruby 1.8.3]
- # Adds a value to a named header field, instead of replacing its value.
- # Second argument +val+ must be a String.
- # See also #[]=, #[] and #get_fields.
+ # Adds value +val+ to the value array for field +key+ if the field exists;
+ # creates the field with the given +key+ and +val+ if it does not exist.
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
#
- # request.add_field 'X-My-Header', 'a'
- # p request['X-My-Header'] #=> "a"
- # p request.get_fields('X-My-Header') #=> ["a"]
- # request.add_field 'X-My-Header', 'b'
- # p request['X-My-Header'] #=> "a, b"
- # p request.get_fields('X-My-Header') #=> ["a", "b"]
- # request.add_field 'X-My-Header', 'c'
- # p request['X-My-Header'] #=> "a, b, c"
- # p request.get_fields('X-My-Header') #=> ["a", "b", "c"]
+ # req = Net::HTTP::Get.new(uri)
+ # req.add_field('Foo', 'bar')
+ # req['Foo'] # => "bar"
+ # req.add_field('Foo', 'baz')
+ # req['Foo'] # => "bar, baz"
+ # req.add_field('Foo', %w[baz bam])
+ # req['Foo'] # => "bar, baz, baz, bam"
+ # req.get_fields('Foo') # => ["bar", "baz", "baz", "bam"]
#
def add_field(key, val)
stringified_downcased_key = key.downcase.to_s
@@ -101,16 +295,13 @@ module Net::HTTPHeader
end
end
- # [Ruby 1.8.3]
- # Returns an array of header field strings corresponding to the
- # case-insensitive +key+. This method allows you to get duplicated
- # header fields without any processing. See also #[].
+ # Returns the array field value for the given +key+,
+ # or +nil+ if there is no such field;
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
#
- # p response.get_fields('Set-Cookie')
- # #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23",
- # "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"]
- # p response['Set-Cookie']
- # #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res.get_fields('Connection') # => ["keep-alive"]
+ # res.get_fields('Nosuch') # => nil
#
def get_fields(key)
stringified_downcased_key = key.downcase.to_s
@@ -118,24 +309,58 @@ module Net::HTTPHeader
@header[stringified_downcased_key].dup
end
- # Returns the header field corresponding to the case-insensitive key.
- # Returns the default value +args+, or the result of the block, or
- # raises an IndexError if there's no header field named +key+
- # See Hash#fetch
+ # call-seq:
+ # fetch(key, default_val = nil) {|key| ... } -> object
+ # fetch(key, default_val = nil) -> value or default_val
+ #
+ # With a block, returns the string value for +key+ if it exists;
+ # otherwise returns the value of the block;
+ # ignores the +default_val+;
+ # see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ #
+ # # Field exists; block not called.
+ # res.fetch('Connection') do |value|
+ # fail 'Cannot happen'
+ # end # => "keep-alive"
+ #
+ # # Field does not exist; block called.
+ # res.fetch('Nosuch') do |value|
+ # value.downcase
+ # end # => "nosuch"
+ #
+ # With no block, returns the string value for +key+ if it exists;
+ # otherwise, returns +default_val+ if it was given;
+ # otherwise raises an exception:
+ #
+ # res.fetch('Connection', 'Foo') # => "keep-alive"
+ # res.fetch('Nosuch', 'Foo') # => "Foo"
+ # res.fetch('Nosuch') # Raises KeyError.
+ #
def fetch(key, *args, &block) #:yield: +key+
a = @header.fetch(key.downcase.to_s, *args, &block)
a.kind_of?(Array) ? a.join(', ') : a
end
- # Iterates through the header names and values, passing in the name
- # and value to the code block supplied.
+ # Calls the block with each key/value pair:
#
- # Returns an enumerator if no block is given.
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res.each_header do |key, value|
+ # p [key, value] if key.start_with?('c')
+ # end
#
- # Example:
+ # Output:
#
- # response.header.each_header {|key,value| puts "#{key} = #{value}" }
+ # ["content-type", "application/json; charset=utf-8"]
+ # ["connection", "keep-alive"]
+ # ["cache-control", "max-age=43200"]
+ # ["cf-cache-status", "HIT"]
+ # ["cf-ray", "771d17e9bc542cf5-ORD"]
#
+ # Returns an enumerator if no block is given.
+ #
+ # Net::HTTPHeader#each is an alias for Net::HTTPHeader#each_header.
def each_header #:yield: +key+, +value+
block_given? or return enum_for(__method__) { @header.size }
@header.each do |k,va|
@@ -145,10 +370,24 @@ module Net::HTTPHeader
alias each each_header
- # Iterates through the header names in the header, passing
- # each header name to the code block.
+ # Calls the block with each field key:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res.each_key do |key|
+ # p key if key.start_with?('c')
+ # end
+ #
+ # Output:
+ #
+ # "content-type"
+ # "connection"
+ # "cache-control"
+ # "cf-cache-status"
+ # "cf-ray"
#
# Returns an enumerator if no block is given.
+ #
+ # Net::HTTPHeader#each_name is an alias for Net::HTTPHeader#each_key.
def each_name(&block) #:yield: +key+
block_given? or return enum_for(__method__) { @header.size }
@header.each_key(&block)
@@ -156,12 +395,23 @@ module Net::HTTPHeader
alias each_key each_name
- # Iterates through the header names in the header, passing
- # capitalized header names to the code block.
+ # Calls the block with each capitalized field name:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res.each_capitalized_name do |key|
+ # p key if key.start_with?('C')
+ # end
+ #
+ # Output:
#
- # Note that header names are capitalized systematically;
- # capitalization may not match that used by the remote HTTP
- # server in its response.
+ # "Content-Type"
+ # "Connection"
+ # "Cache-Control"
+ # "Cf-Cache-Status"
+ # "Cf-Ray"
+ #
+ # The capitalization is system-dependent;
+ # see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
#
# Returns an enumerator if no block is given.
def each_capitalized_name #:yield: +key+
@@ -171,8 +421,18 @@ module Net::HTTPHeader
end
end
- # Iterates through header values, passing each value to the
- # code block.
+ # Calls the block with each string field value:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res.each_value do |value|
+ # p value if value.start_with?('c')
+ # end
+ #
+ # Output:
+ #
+ # "chunked"
+ # "cf-q-config;dur=6.0000002122251e-06"
+ # "cloudflare"
#
# Returns an enumerator if no block is given.
def each_value #:yield: +value+
@@ -182,32 +442,45 @@ module Net::HTTPHeader
end
end
- # Removes a header field, specified by case-insensitive key.
+ # Removes the header for the given case-insensitive +key+
+ # (see {Fields}[rdoc-ref:Net::HTTPHeader@Fields]);
+ # returns the deleted value, or +nil+ if no such field exists:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req.delete('Accept') # => ["*/*"]
+ # req.delete('Nosuch') # => nil
+ #
def delete(key)
@header.delete(key.downcase.to_s)
end
- # true if +key+ header exists.
+ # Returns +true+ if the field for the case-insensitive +key+ exists, +false+ otherwise:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req.key?('Accept') # => true
+ # req.key?('Nosuch') # => false
+ #
def key?(key)
@header.key?(key.downcase.to_s)
end
- # Returns a Hash consisting of header names and array of values.
- # e.g.
- # {"cache-control" => ["private"],
- # "content-type" => ["text/html"],
- # "date" => ["Wed, 22 Jun 2005 22:11:50 GMT"]}
+ # Returns a hash of the key/value pairs:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req.to_hash
+ # # =>
+ # {"accept-encoding"=>["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"],
+ # "accept"=>["*/*"],
+ # "user-agent"=>["Ruby"],
+ # "host"=>["jsonplaceholder.typicode.com"]}
+ #
def to_hash
@header.dup
end
- # As for #each_header, except the keys are provided in capitalized form.
+ # Like #each_header, but the keys are returned in capitalized form.
#
- # Note that header names are capitalized systematically;
- # capitalization may not match that used by the remote HTTP
- # server in its response.
- #
- # Returns an enumerator if no block is given.
+ # Net::HTTPHeader#canonical_each is an alias for Net::HTTPHeader#each_capitalized.
def each_capitalized
block_given? or return enum_for(__method__) { @header.size }
@header.each do |k,v|
@@ -222,8 +495,17 @@ module Net::HTTPHeader
end
private :capitalize
- # Returns an Array of Range objects which represent the Range:
- # HTTP header field, or +nil+ if there is no such header.
+ # Returns an array of Range objects that represent
+ # the value of field <tt>'Range'</tt>,
+ # or +nil+ if there is no such field;
+ # see {Range request header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#range-request-header]:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req['Range'] = 'bytes=0-99,200-299,400-499'
+ # req.range # => [0..99, 200..299, 400..499]
+ # req.delete('Range')
+ # req.range # # => nil
+ #
def range
return nil unless @header['range']
@@ -266,14 +548,31 @@ module Net::HTTPHeader
result
end
- # Sets the HTTP Range: header.
- # Accepts either a Range object as a single argument,
- # or a beginning index and a length from that index.
- # Example:
+ # call-seq:
+ # set_range(length) -> length
+ # set_range(offset, length) -> range
+ # set_range(begin..length) -> range
+ #
+ # Sets the value for field <tt>'Range'</tt>;
+ # see {Range request header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#range-request-header]:
+ #
+ # With argument +length+:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req.set_range(100) # => 100
+ # req['Range'] # => "bytes=0-99"
#
- # req.range = (0..1023)
- # req.set_range 0, 1023
+ # With arguments +offset+ and +length+:
#
+ # req.set_range(100, 100) # => 100...200
+ # req['Range'] # => "bytes=100-199"
+ #
+ # With argument +range+:
+ #
+ # req.set_range(100..199) # => 100..199
+ # req['Range'] # => "bytes=100-199"
+ #
+ # Net::HTTPHeader#range= is an alias for Net::HTTPHeader#set_range.
def set_range(r, e = nil)
unless r
@header.delete 'range'
@@ -305,8 +604,15 @@ module Net::HTTPHeader
alias range= set_range
- # Returns an Integer object which represents the HTTP Content-Length:
- # header field, or +nil+ if that field was not provided.
+ # Returns the value of field <tt>'Content-Length'</tt> as an integer,
+ # or +nil+ if there is no such field;
+ # see {Content-Length request header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-length-request-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/nosuch/1')
+ # res.content_length # => 2
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res.content_length # => nil
+ #
def content_length
return nil unless key?('Content-Length')
len = self['Content-Length'].slice(/\d+/) or
@@ -314,6 +620,20 @@ module Net::HTTPHeader
len.to_i
end
+ # Sets the value of field <tt>'Content-Length'</tt> to the given numeric;
+ # see {Content-Length response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-length-response-header]:
+ #
+ # _uri = uri.dup
+ # hostname = _uri.hostname # => "jsonplaceholder.typicode.com"
+ # _uri.path = '/posts' # => "/posts"
+ # req = Net::HTTP::Post.new(_uri) # => #<Net::HTTP::Post POST>
+ # req.body = '{"title": "foo","body": "bar","userId": 1}'
+ # req.content_length = req.body.size # => 42
+ # req.content_type = 'application/json'
+ # res = Net::HTTP.start(hostname) do |http|
+ # http.request(req)
+ # end # => #<Net::HTTPCreated 201 Created readbody=true>
+ #
def content_length=(len)
unless len
@header.delete 'content-length'
@@ -322,53 +642,99 @@ module Net::HTTPHeader
@header['content-length'] = [len.to_i.to_s]
end
- # Returns "true" if the "transfer-encoding" header is present and
- # set to "chunked". This is an HTTP/1.1 feature, allowing
- # the content to be sent in "chunks" without at the outset
- # stating the entire content length.
+ # Returns +true+ if field <tt>'Transfer-Encoding'</tt>
+ # exists and has value <tt>'chunked'</tt>,
+ # +false+ otherwise;
+ # see {Transfer-Encoding response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#transfer-encoding-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['Transfer-Encoding'] # => "chunked"
+ # res.chunked? # => true
+ #
def chunked?
return false unless @header['transfer-encoding']
field = self['Transfer-Encoding']
(/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false
end
- # Returns a Range object which represents the value of the Content-Range:
- # header field.
- # For a partial entity body, this indicates where this fragment
- # fits inside the full entity body, as range of byte offsets.
+ # Returns a Range object representing the value of field
+ # <tt>'Content-Range'</tt>, or +nil+ if no such field exists;
+ # see {Content-Range response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-range-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['Content-Range'] # => nil
+ # res['Content-Range'] = 'bytes 0-499/1000'
+ # res['Content-Range'] # => "bytes 0-499/1000"
+ # res.content_range # => 0..499
+ #
def content_range
return nil unless @header['content-range']
- m = %r<bytes\s+(\d+)-(\d+)/(\d+|\*)>i.match(self['Content-Range']) or
+ m = %r<\A\s*(\w+)\s+(\d+)-(\d+)/(\d+|\*)>.match(self['Content-Range']) or
raise Net::HTTPHeaderSyntaxError, 'wrong Content-Range format'
- m[1].to_i .. m[2].to_i
+ return unless m[1] == 'bytes'
+ m[2].to_i .. m[3].to_i
end
- # The length of the range represented in Content-Range: header.
+ # Returns the integer representing length of the value of field
+ # <tt>'Content-Range'</tt>, or +nil+ if no such field exists;
+ # see {Content-Range response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-range-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['Content-Range'] # => nil
+ # res['Content-Range'] = 'bytes 0-499/1000'
+ # res.range_length # => 500
+ #
def range_length
r = content_range() or return nil
r.end - r.begin + 1
end
- # Returns a content type string such as "text/html".
- # This method returns nil if Content-Type: header field does not exist.
+ # Returns the {media type}[https://en.wikipedia.org/wiki/Media_type]
+ # from the value of field <tt>'Content-Type'</tt>,
+ # or +nil+ if no such field exists;
+ # see {Content-Type response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-type-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['content-type'] # => "application/json; charset=utf-8"
+ # res.content_type # => "application/json"
+ #
def content_type
- return nil unless main_type()
- if sub_type()
- then "#{main_type()}/#{sub_type()}"
- else main_type()
+ main = main_type()
+ return nil unless main
+
+ sub = sub_type()
+ if sub
+ "#{main}/#{sub}"
+ else
+ main
end
end
- # Returns a content type string such as "text".
- # This method returns nil if Content-Type: header field does not exist.
+ # Returns the leading ('type') part of the
+ # {media type}[https://en.wikipedia.org/wiki/Media_type]
+ # from the value of field <tt>'Content-Type'</tt>,
+ # or +nil+ if no such field exists;
+ # see {Content-Type response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-type-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['content-type'] # => "application/json; charset=utf-8"
+ # res.main_type # => "application"
+ #
def main_type
return nil unless @header['content-type']
self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip
end
- # Returns a content type string such as "html".
- # This method returns nil if Content-Type: header field does not exist
- # or sub-type is not given (e.g. "Content-Type: text").
+ # Returns the trailing ('subtype') part of the
+ # {media type}[https://en.wikipedia.org/wiki/Media_type]
+ # from the value of field <tt>'Content-Type'</tt>,
+ # or +nil+ if no such field exists;
+ # see {Content-Type response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-type-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['content-type'] # => "application/json; charset=utf-8"
+ # res.sub_type # => "json"
+ #
def sub_type
return nil unless @header['content-type']
_, sub = *self['Content-Type'].split(';').first.to_s.split('/')
@@ -376,9 +742,14 @@ module Net::HTTPHeader
sub.strip
end
- # Any parameters specified for the content type, returned as a Hash.
- # For example, a header of Content-Type: text/html; charset=EUC-JP
- # would result in type_params returning {'charset' => 'EUC-JP'}
+ # Returns the trailing ('parameters') part of the value of field <tt>'Content-Type'</tt>,
+ # or +nil+ if no such field exists;
+ # see {Content-Type response header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-type-response-header]:
+ #
+ # res = Net::HTTP.get_response(hostname, '/todos/1')
+ # res['content-type'] # => "application/json; charset=utf-8"
+ # res.type_params # => {"charset"=>"utf-8"}
+ #
def type_params
result = {}
list = self['Content-Type'].to_s.split(';')
@@ -390,29 +761,54 @@ module Net::HTTPHeader
result
end
- # Sets the content type in an HTTP header.
- # The +type+ should be a full HTTP content type, e.g. "text/html".
- # The +params+ are an optional Hash of parameters to add after the
- # content type, e.g. {'charset' => 'iso-8859-1'}
+ # Sets the value of field <tt>'Content-Type'</tt>;
+ # returns the new value;
+ # see {Content-Type request header}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#content-type-request-header]:
+ #
+ # req = Net::HTTP::Get.new(uri)
+ # req.set_content_type('application/json') # => ["application/json"]
+ #
+ # Net::HTTPHeader#content_type= is an alias for Net::HTTPHeader#set_content_type.
def set_content_type(type, params = {})
@header['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')]
end
alias content_type= set_content_type
- # Set header fields and a body from HTML form data.
- # +params+ should be an Array of Arrays or
- # a Hash containing HTML form data.
- # Optional argument +sep+ means data record separator.
+ # Sets the request body to a URL-encoded string derived from argument +params+,
+ # and sets request header field <tt>'Content-Type'</tt>
+ # to <tt>'application/x-www-form-urlencoded'</tt>.
+ #
+ # The resulting request is suitable for HTTP request +POST+ or +PUT+.
+ #
+ # Argument +params+ must be suitable for use as argument +enum+ to
+ # {URI.encode_www_form}[rdoc-ref:URI.encode_www_form].
+ #
+ # With only argument +params+ given,
+ # sets the body to a URL-encoded string with the default separator <tt>'&'</tt>:
+ #
+ # req = Net::HTTP::Post.new('example.com')
+ #
+ # req.set_form_data(q: 'ruby', lang: 'en')
+ # req.body # => "q=ruby&lang=en"
+ # req['Content-Type'] # => "application/x-www-form-urlencoded"
#
- # Values are URL encoded as necessary and the content-type is set to
- # application/x-www-form-urlencoded
+ # req.set_form_data([['q', 'ruby'], ['lang', 'en']])
+ # req.body # => "q=ruby&lang=en"
#
- # Example:
- # http.form_data = {"q" => "ruby", "lang" => "en"}
- # http.form_data = {"q" => ["ruby", "perl"], "lang" => "en"}
- # http.set_form_data({"q" => "ruby", "lang" => "en"}, ';')
+ # req.set_form_data(q: ['ruby', 'perl'], lang: 'en')
+ # req.body # => "q=ruby&q=perl&lang=en"
#
+ # req.set_form_data([['q', 'ruby'], ['q', 'perl'], ['lang', 'en']])
+ # req.body # => "q=ruby&q=perl&lang=en"
+ #
+ # With string argument +sep+ also given,
+ # uses that string as the separator:
+ #
+ # req.set_form_data({q: 'ruby', lang: 'en'}, '|')
+ # req.body # => "q=ruby|lang=en"
+ #
+ # Net::HTTPHeader#form_data= is an alias for Net::HTTPHeader#set_form_data.
def set_form_data(params, sep = '&')
query = URI.encode_www_form(params)
query.gsub!(/&/, sep) if sep != '&'
@@ -422,53 +818,108 @@ module Net::HTTPHeader
alias form_data= set_form_data
- # Set an HTML form data set.
- # +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.
- #
- # 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+ hash has a :filename key,
- # the item is treated as a file field.
- #
- # If Transfer-Encoding is set as chunked, this sends the request using
- # chunked encoding. Because chunked encoding is HTTP/1.1 feature,
- # you should confirm that the server supports HTTP/1.1 before using
- # chunked encoding.
- #
- # Example:
- # 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
+ # Stores form data to be used in a +POST+ or +PUT+ request.
+ #
+ # The form data given in +params+ consists of zero or more fields;
+ # each field is:
+ #
+ # - A scalar value.
+ # - A name/value pair.
+ # - An IO stream opened for reading.
+ #
+ # Argument +params+ should be an
+ # {Enumerable}[rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes]
+ # (method <tt>params.map</tt> will be called),
+ # and is often an array or hash.
+ #
+ # First, we set up a request:
+ #
+ # _uri = uri.dup
+ # _uri.path ='/posts'
+ # req = Net::HTTP::Post.new(_uri)
+ #
+ # <b>Argument +params+ As an Array</b>
+ #
+ # When +params+ is an array,
+ # each of its elements is a subarray that defines a field;
+ # the subarray may contain:
+ #
+ # - One string:
+ #
+ # req.set_form([['foo'], ['bar'], ['baz']])
+ #
+ # - Two strings:
+ #
+ # req.set_form([%w[foo 0], %w[bar 1], %w[baz 2]])
+ #
+ # - When argument +enctype+ (see below) is given as
+ # <tt>'multipart/form-data'</tt>:
+ #
+ # - A string name and an IO stream opened for reading:
+ #
+ # require 'stringio'
+ # req.set_form([['file', StringIO.new('Ruby is cool.')]])
+ #
+ # - A string name, an IO stream opened for reading,
+ # and an options hash, which may contain these entries:
+ #
+ # - +:filename+: The name of the file to use.
+ # - +:content_type+: The content type of the uploaded file.
+ #
+ # Example:
+ #
+ # req.set_form([['file', file, {filename: "other-filename.foo"}]]
+ #
+ # The various forms may be mixed:
+ #
+ # req.set_form(['foo', %w[bar 1], ['file', file]])
+ #
+ # <b>Argument +params+ As a Hash</b>
+ #
+ # When +params+ is a hash,
+ # each of its entries is a name/value pair that defines a field:
+ #
+ # - The name is a string.
+ # - The value may be:
+ #
+ # - +nil+.
+ # - Another string.
+ # - An IO stream opened for reading
+ # (only when argument +enctype+ -- see below -- is given as
+ # <tt>'multipart/form-data'</tt>).
+ #
+ # Examples:
+ #
+ # # Nil-valued fields.
+ # req.set_form({'foo' => nil, 'bar' => nil, 'baz' => nil})
+ #
+ # # String-valued fields.
+ # req.set_form({'foo' => 0, 'bar' => 1, 'baz' => 2})
+ #
+ # # IO-valued field.
+ # require 'stringio'
+ # req.set_form({'file' => StringIO.new('Ruby is cool.')})
+ #
+ # # Mixture of fields.
+ # req.set_form({'foo' => nil, 'bar' => 1, 'file' => file})
+ #
+ # Optional argument +enctype+ specifies the value to be given
+ # to field <tt>'Content-Type'</tt>, and must be one of:
+ #
+ # - <tt>'application/x-www-form-urlencoded'</tt> (the default).
+ # - <tt>'multipart/form-data'</tt>;
+ # see {RFC 7578}[https://www.rfc-editor.org/rfc/rfc7578].
+ #
+ # Optional argument +formopt+ is a hash of options
+ # (applicable only when argument +enctype+
+ # is <tt>'multipart/form-data'</tt>)
+ # that may include the following entries:
+ #
+ # - +:boundary+: The value is the boundary string for the multipart message.
+ # If not given, the boundary is a random string.
+ # See {Boundary}[https://www.rfc-editor.org/rfc/rfc7578#section-4.1].
+ # - +:charset+: Value is the character set for the form submission.
+ # Field names and values of non-file fields should be encoded with this charset.
#
def set_form(params, enctype='application/x-www-form-urlencoded', formopt={})
@body_data = params
@@ -484,12 +935,24 @@ module Net::HTTPHeader
end
end
- # Set the Authorization: header for "Basic" authorization.
+ # Sets header <tt>'Authorization'</tt> using the given
+ # +account+ and +password+ strings:
+ #
+ # req.basic_auth('my_account', 'my_password')
+ # req['Authorization']
+ # # => "Basic bXlfYWNjb3VudDpteV9wYXNzd29yZA=="
+ #
def basic_auth(account, password)
@header['authorization'] = [basic_encode(account, password)]
end
- # Set Proxy-Authorization: header for "Basic" authorization.
+ # Sets header <tt>'Proxy-Authorization'</tt> using the given
+ # +account+ and +password+ strings:
+ #
+ # req.proxy_basic_auth('my_account', 'my_password')
+ # req['Proxy-Authorization']
+ # # => "Basic bXlfYWNjb3VudDpteV9wYXNzd29yZA=="
+ #
def proxy_basic_auth(account, password)
@header['proxy-authorization'] = [basic_encode(account, password)]
end
@@ -499,6 +962,7 @@ module Net::HTTPHeader
end
private :basic_encode
+# Returns whether the HTTP session is to be closed.
def connection_close?
token = /(?:\A|,)\s*close\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
@@ -506,6 +970,7 @@ module Net::HTTPHeader
false
end
+# Returns whether the HTTP session is to be kept alive.
def connection_keep_alive?
token = /(?:\A|,)\s*keep-alive\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
diff --git a/lib/net/http/net-http.gemspec b/lib/net/http/net-http.gemspec
index f5ef4045e8..0021136793 100644
--- a/lib/net/http/net-http.gemspec
+++ b/lib/net/http/net-http.gemspec
@@ -2,9 +2,14 @@
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
+ file = File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")
+ begin
+ break File.foreach(file, mode: "rb") do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end
+ rescue SystemCallError
+ next
+ end
end
Gem::Specification.new do |spec|
@@ -25,12 +30,10 @@ Gem::Specification.new do |spec|
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{\A(?:(?:test|spec|features)/|\.git)}) }
end
spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
- spec.add_dependency "net-protocol"
spec.add_dependency "uri"
end
diff --git a/lib/net/http/proxy_delta.rb b/lib/net/http/proxy_delta.rb
index a2f770ebdb..e7d30def64 100644
--- a/lib/net/http/proxy_delta.rb
+++ b/lib/net/http/proxy_delta.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
module Net::HTTP::ProxyDelta #:nodoc: internal use only
private
diff --git a/lib/net/http/request.rb b/lib/net/http/request.rb
index 1e86f3e4b4..4a138572e9 100644
--- a/lib/net/http/request.rb
+++ b/lib/net/http/request.rb
@@ -1,8 +1,76 @@
-# frozen_string_literal: false
-# HTTP request class.
-# This class wraps together the request header and the request path.
-# You cannot use this class directly. Instead, you should use one of its
-# subclasses: Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Head.
+# frozen_string_literal: true
+
+# This class is the base class for \Net::HTTP request classes.
+# The class should not be used directly;
+# instead you should use its subclasses, listed below.
+#
+# == Creating a Request
+#
+# An request object may be created with either a URI or a string hostname:
+#
+# require 'net/http'
+# uri = URI('https://jsonplaceholder.typicode.com/')
+# req = Net::HTTP::Get.new(uri) # => #<Net::HTTP::Get GET>
+# req = Net::HTTP::Get.new(uri.hostname) # => #<Net::HTTP::Get GET>
+#
+# And with any of the subclasses:
+#
+# req = Net::HTTP::Head.new(uri) # => #<Net::HTTP::Head HEAD>
+# req = Net::HTTP::Post.new(uri) # => #<Net::HTTP::Post POST>
+# req = Net::HTTP::Put.new(uri) # => #<Net::HTTP::Put PUT>
+# # ...
+#
+# The new instance is suitable for use as the argument to Net::HTTP#request.
+#
+# == Request Headers
+#
+# A new request object has these header fields by default:
+#
+# req.to_hash
+# # =>
+# {"accept-encoding"=>["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"],
+# "accept"=>["*/*"],
+# "user-agent"=>["Ruby"],
+# "host"=>["jsonplaceholder.typicode.com"]}
+#
+# See:
+#
+# - {Request header Accept-Encoding}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Accept-Encoding]
+# and {Compression and Decompression}[rdoc-ref:Net::HTTP@Compression+and+Decompression].
+# - {Request header Accept}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#accept-request-header].
+# - {Request header User-Agent}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#user-agent-request-header].
+# - {Request header Host}[https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#host-request-header].
+#
+# You can add headers or override default headers:
+#
+# # res = Net::HTTP::Get.new(uri, {'foo' => '0', 'bar' => '1'})
+#
+# This class (and therefore its subclasses) also includes (indirectly)
+# module Net::HTTPHeader, which gives access to its
+# {methods for setting headers}[rdoc-ref:Net::HTTPHeader@Setters].
+#
+# == Request Subclasses
+#
+# Subclasses for HTTP requests:
+#
+# - Net::HTTP::Get
+# - Net::HTTP::Head
+# - Net::HTTP::Post
+# - Net::HTTP::Put
+# - Net::HTTP::Delete
+# - Net::HTTP::Options
+# - Net::HTTP::Trace
+# - Net::HTTP::Patch
+#
+# Subclasses for WebDAV requests:
+#
+# - Net::HTTP::Propfind
+# - Net::HTTP::Proppatch
+# - Net::HTTP::Mkcol
+# - Net::HTTP::Copy
+# - Net::HTTP::Move
+# - Net::HTTP::Lock
+# - Net::HTTP::Unlock
#
class Net::HTTPRequest < Net::HTTPGenericRequest
# Creates an HTTP request object for +path+.
@@ -18,4 +86,3 @@ class Net::HTTPRequest < Net::HTTPGenericRequest
path, initheader
end
end
-
diff --git a/lib/net/http/requests.rb b/lib/net/http/requests.rb
index d4c80a3812..5724164205 100644
--- a/lib/net/http/requests.rb
+++ b/lib/net/http/requests.rb
@@ -1,67 +1,257 @@
-# frozen_string_literal: false
-#
+# frozen_string_literal: true
+
# HTTP/1.1 methods --- RFC2616
-#
-# See Net::HTTPGenericRequest for attributes and methods.
-# See Net::HTTP for usage examples.
+# \Class for representing
+# {HTTP method GET}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#GET_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Get.new(uri) # => #<Net::HTTP::Get GET>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: optional.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: yes.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: yes.
+#
+# Related:
+#
+# - Net::HTTP.get: sends +GET+ request, returns response body.
+# - Net::HTTP#get: sends +GET+ request, returns response object.
+#
class Net::HTTP::Get < Net::HTTPRequest
METHOD = 'GET'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
-# See Net::HTTP for usage examples.
+# \Class for representing
+# {HTTP method HEAD}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#HEAD_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Head.new(uri) # => #<Net::HTTP::Head HEAD>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: optional.
+# - Response body: no.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: yes.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: yes.
+#
+# Related:
+#
+# - Net::HTTP#head: sends +HEAD+ request, returns response object.
+#
class Net::HTTP::Head < Net::HTTPRequest
METHOD = 'HEAD'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = false
end
-# See Net::HTTPGenericRequest for attributes and methods.
-# See Net::HTTP for usage examples.
+# \Class for representing
+# {HTTP method POST}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#POST_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# uri.path = '/posts'
+# req = Net::HTTP::Post.new(uri) # => #<Net::HTTP::Post POST>
+# req.body = '{"title": "foo","body": "bar","userId": 1}'
+# req.content_type = 'application/json'
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: yes.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: no.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: no.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: yes.
+#
+# Related:
+#
+# - Net::HTTP.post: sends +POST+ request, returns response object.
+# - Net::HTTP#post: sends +POST+ request, returns response object.
+#
class Net::HTTP::Post < Net::HTTPRequest
METHOD = 'POST'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
-# See Net::HTTP for usage examples.
+# \Class for representing
+# {HTTP method PUT}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#PUT_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# uri.path = '/posts'
+# req = Net::HTTP::Put.new(uri) # => #<Net::HTTP::Put PUT>
+# req.body = '{"title": "foo","body": "bar","userId": 1}'
+# req.content_type = 'application/json'
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: yes.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: no.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
+#
class Net::HTTP::Put < Net::HTTPRequest
METHOD = 'PUT'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
-# See Net::HTTP for usage examples.
+# \Class for representing
+# {HTTP method DELETE}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#DELETE_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# uri.path = '/posts/1'
+# req = Net::HTTP::Delete.new(uri) # => #<Net::HTTP::Delete DELETE>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: optional.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: no.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
+#
+# Related:
+#
+# - Net::HTTP#delete: sends +DELETE+ request, returns response object.
+#
class Net::HTTP::Delete < Net::HTTPRequest
METHOD = 'DELETE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {HTTP method OPTIONS}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#OPTIONS_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Options.new(uri) # => #<Net::HTTP::Options OPTIONS>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: optional.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: yes.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
+#
+# Related:
+#
+# - Net::HTTP#options: sends +OPTIONS+ request, returns response object.
+#
class Net::HTTP::Options < Net::HTTPRequest
METHOD = 'OPTIONS'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {HTTP method TRACE}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#TRACE_method]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Trace.new(uri) # => #<Net::HTTP::Trace TRACE>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: no.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: yes.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
+#
+# Related:
+#
+# - Net::HTTP#trace: sends +TRACE+ request, returns response object.
+#
class Net::HTTP::Trace < Net::HTTPRequest
METHOD = 'TRACE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
end
+# \Class for representing
+# {HTTP method PATCH}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#PATCH_method]:
#
-# PATCH method --- RFC5789
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# uri.path = '/posts'
+# req = Net::HTTP::Patch.new(uri) # => #<Net::HTTP::Patch PATCH>
+# req.body = '{"title": "foo","body": "bar","userId": 1}'
+# req.content_type = 'application/json'
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Properties:
+#
+# - Request body: yes.
+# - Response body: yes.
+# - {Safe}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods]: no.
+# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: no.
+# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
+#
+# Related:
+#
+# - Net::HTTP#patch: sends +PATCH+ request, returns response object.
#
-
-# See Net::HTTPGenericRequest for attributes and methods.
class Net::HTTP::Patch < Net::HTTPRequest
METHOD = 'PATCH'
REQUEST_HAS_BODY = true
@@ -72,49 +262,161 @@ end
# WebDAV methods --- RFC2518
#
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method PROPFIND}[http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Propfind.new(uri) # => #<Net::HTTP::Propfind PROPFIND>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#propfind: sends +PROPFIND+ request, returns response object.
+#
class Net::HTTP::Propfind < Net::HTTPRequest
METHOD = 'PROPFIND'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method PROPPATCH}[http://www.webdav.org/specs/rfc4918.html#METHOD_PROPPATCH]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Proppatch.new(uri) # => #<Net::HTTP::Proppatch PROPPATCH>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#proppatch: sends +PROPPATCH+ request, returns response object.
+#
class Net::HTTP::Proppatch < Net::HTTPRequest
METHOD = 'PROPPATCH'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method MKCOL}[http://www.webdav.org/specs/rfc4918.html#METHOD_MKCOL]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Mkcol.new(uri) # => #<Net::HTTP::Mkcol MKCOL>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#mkcol: sends +MKCOL+ request, returns response object.
+#
class Net::HTTP::Mkcol < Net::HTTPRequest
METHOD = 'MKCOL'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method COPY}[http://www.webdav.org/specs/rfc4918.html#METHOD_COPY]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Copy.new(uri) # => #<Net::HTTP::Copy COPY>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#copy: sends +COPY+ request, returns response object.
+#
class Net::HTTP::Copy < Net::HTTPRequest
METHOD = 'COPY'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method MOVE}[http://www.webdav.org/specs/rfc4918.html#METHOD_MOVE]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Move.new(uri) # => #<Net::HTTP::Move MOVE>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#move: sends +MOVE+ request, returns response object.
+#
class Net::HTTP::Move < Net::HTTPRequest
METHOD = 'MOVE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method LOCK}[http://www.webdav.org/specs/rfc4918.html#METHOD_LOCK]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Lock.new(uri) # => #<Net::HTTP::Lock LOCK>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#lock: sends +LOCK+ request, returns response object.
+#
class Net::HTTP::Lock < Net::HTTPRequest
METHOD = 'LOCK'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-# See Net::HTTPGenericRequest for attributes and methods.
+# \Class for representing
+# {WebDAV method UNLOCK}[http://www.webdav.org/specs/rfc4918.html#METHOD_UNLOCK]:
+#
+# require 'net/http'
+# uri = URI('http://example.com')
+# hostname = uri.hostname # => "example.com"
+# req = Net::HTTP::Unlock.new(uri) # => #<Net::HTTP::Unlock UNLOCK>
+# res = Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end
+#
+# See {Request Headers}[rdoc-ref:Net::HTTPRequest@Request+Headers].
+#
+# Related:
+#
+# - Net::HTTP#unlock: sends +UNLOCK+ request, returns response object.
+#
class Net::HTTP::Unlock < Net::HTTPRequest
METHOD = 'UNLOCK'
REQUEST_HAS_BODY = true
diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb
index 08eaeb2cac..40de963868 100644
--- a/lib/net/http/response.rb
+++ b/lib/net/http/response.rb
@@ -1,20 +1,136 @@
-# frozen_string_literal: false
-# HTTP response class.
+# frozen_string_literal: true
+
+# This class is the base class for \Net::HTTP response classes.
+#
+# == About the Examples
+#
+# :include: doc/net-http/examples.rdoc
+#
+# == Returned Responses
+#
+# \Method Net::HTTP.get_response returns
+# an instance of one of the subclasses of \Net::HTTPResponse:
+#
+# Net::HTTP.get_response(uri)
+# # => #<Net::HTTPOK 200 OK readbody=true>
+# Net::HTTP.get_response(hostname, '/nosuch')
+# # => #<Net::HTTPNotFound 404 Not Found readbody=true>
+#
+# As does method Net::HTTP#request:
+#
+# req = Net::HTTP::Get.new(uri)
+# Net::HTTP.start(hostname) do |http|
+# http.request(req)
+# end # => #<Net::HTTPOK 200 OK readbody=true>
+#
+# \Class \Net::HTTPResponse includes module Net::HTTPHeader,
+# which provides access to response header values via (among others):
+#
+# - \Hash-like method <tt>[]</tt>.
+# - Specific reader methods, such as +content_type+.
+#
+# Examples:
+#
+# res = Net::HTTP.get_response(uri) # => #<Net::HTTPOK 200 OK readbody=true>
+# res['Content-Type'] # => "text/html; charset=UTF-8"
+# res.content_type # => "text/html"
+#
+# == Response Subclasses
+#
+# \Class \Net::HTTPResponse has a subclass for each
+# {HTTP status code}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes].
+# You can look up the response class for a given code:
+#
+# Net::HTTPResponse::CODE_TO_OBJ['200'] # => Net::HTTPOK
+# Net::HTTPResponse::CODE_TO_OBJ['400'] # => Net::HTTPBadRequest
+# Net::HTTPResponse::CODE_TO_OBJ['404'] # => Net::HTTPNotFound
+#
+# And you can retrieve the status code for a response object:
+#
+# Net::HTTP.get_response(uri).code # => "200"
+# Net::HTTP.get_response(hostname, '/nosuch').code # => "404"
+#
+# The response subclasses (indentation shows class hierarchy):
+#
+# - Net::HTTPUnknownResponse (for unhandled \HTTP extensions).
#
-# This class wraps together the response header and the response body (the
-# entity requested).
+# - Net::HTTPInformation:
#
-# It mixes in the HTTPHeader module, which provides access to response
-# header values both via hash-like methods and via individual readers.
+# - Net::HTTPContinue (100)
+# - Net::HTTPSwitchProtocol (101)
+# - Net::HTTPProcessing (102)
+# - Net::HTTPEarlyHints (103)
#
-# Note that each possible HTTP response code defines its own
-# HTTPResponse subclass. All classes are defined under the Net module.
-# Indentation indicates inheritance. For a list of the classes see Net::HTTP.
+# - Net::HTTPSuccess:
#
-# Correspondence <code>HTTP code => class</code> is stored in CODE_TO_OBJ
-# constant:
+# - Net::HTTPOK (200)
+# - Net::HTTPCreated (201)
+# - Net::HTTPAccepted (202)
+# - Net::HTTPNonAuthoritativeInformation (203)
+# - Net::HTTPNoContent (204)
+# - Net::HTTPResetContent (205)
+# - Net::HTTPPartialContent (206)
+# - Net::HTTPMultiStatus (207)
+# - Net::HTTPAlreadyReported (208)
+# - Net::HTTPIMUsed (226)
#
-# Net::HTTPResponse::CODE_TO_OBJ['404'] #=> Net::HTTPNotFound
+# - Net::HTTPRedirection:
+#
+# - Net::HTTPMultipleChoices (300)
+# - Net::HTTPMovedPermanently (301)
+# - Net::HTTPFound (302)
+# - Net::HTTPSeeOther (303)
+# - Net::HTTPNotModified (304)
+# - Net::HTTPUseProxy (305)
+# - Net::HTTPTemporaryRedirect (307)
+# - Net::HTTPPermanentRedirect (308)
+#
+# - Net::HTTPClientError:
+#
+# - Net::HTTPBadRequest (400)
+# - Net::HTTPUnauthorized (401)
+# - Net::HTTPPaymentRequired (402)
+# - Net::HTTPForbidden (403)
+# - Net::HTTPNotFound (404)
+# - Net::HTTPMethodNotAllowed (405)
+# - Net::HTTPNotAcceptable (406)
+# - Net::HTTPProxyAuthenticationRequired (407)
+# - Net::HTTPRequestTimeOut (408)
+# - Net::HTTPConflict (409)
+# - Net::HTTPGone (410)
+# - Net::HTTPLengthRequired (411)
+# - Net::HTTPPreconditionFailed (412)
+# - Net::HTTPRequestEntityTooLarge (413)
+# - Net::HTTPRequestURITooLong (414)
+# - Net::HTTPUnsupportedMediaType (415)
+# - Net::HTTPRequestedRangeNotSatisfiable (416)
+# - Net::HTTPExpectationFailed (417)
+# - Net::HTTPMisdirectedRequest (421)
+# - Net::HTTPUnprocessableEntity (422)
+# - Net::HTTPLocked (423)
+# - Net::HTTPFailedDependency (424)
+# - Net::HTTPUpgradeRequired (426)
+# - Net::HTTPPreconditionRequired (428)
+# - Net::HTTPTooManyRequests (429)
+# - Net::HTTPRequestHeaderFieldsTooLarge (431)
+# - Net::HTTPUnavailableForLegalReasons (451)
+#
+# - Net::HTTPServerError:
+#
+# - Net::HTTPInternalServerError (500)
+# - Net::HTTPNotImplemented (501)
+# - Net::HTTPBadGateway (502)
+# - Net::HTTPServiceUnavailable (503)
+# - Net::HTTPGatewayTimeOut (504)
+# - Net::HTTPVersionNotSupported (505)
+# - Net::HTTPVariantAlsoNegotiates (506)
+# - Net::HTTPInsufficientStorage (507)
+# - Net::HTTPLoopDetected (508)
+# - Net::HTTPNotExtended (510)
+# - Net::HTTPNetworkAuthenticationRequired (511)
+#
+# There is also the Net::HTTPBadResponse exception which is raised when
+# there is a protocol error.
#
class Net::HTTPResponse
class << self
@@ -84,6 +200,8 @@ class Net::HTTPResponse
@read = false
@uri = nil
@decode_content = false
+ @body_encoding = false
+ @ignore_eof = true
end
# The HTTP version supported by the server.
@@ -106,6 +224,41 @@ class Net::HTTPResponse
# Accept-Encoding header from the user.
attr_accessor :decode_content
+ # Returns the value set by body_encoding=, or +false+ if none;
+ # see #body_encoding=.
+ attr_reader :body_encoding
+
+ # Sets the encoding that should be used when reading the body:
+ #
+ # - If the given value is an Encoding object, that encoding will be used.
+ # - Otherwise if the value is a string, the value of
+ # {Encoding#find(value)}[rdoc-ref:Encoding.find]
+ # will be used.
+ # - Otherwise an encoding will be deduced from the body itself.
+ #
+ # Examples:
+ #
+ # http = Net::HTTP.new(hostname)
+ # req = Net::HTTP::Get.new('/')
+ #
+ # http.request(req) do |res|
+ # p res.body.encoding # => #<Encoding:ASCII-8BIT>
+ # end
+ #
+ # http.request(req) do |res|
+ # res.body_encoding = "UTF-8"
+ # p res.body.encoding # => #<Encoding:UTF-8>
+ # end
+ #
+ def body_encoding=(value)
+ value = Encoding.find(value) if value.is_a?(String)
+ @body_encoding = value
+ end
+
+ # Whether to ignore EOF when reading bodies with a specified Content-Length
+ # header.
+ attr_accessor :ignore_eof
+
def inspect
"#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
end
@@ -120,7 +273,7 @@ class Net::HTTPResponse
def error! #:nodoc:
message = @code
- message += ' ' + @message.dump if @message
+ message = "#{message} #{@message.dump}" if @message
raise error_type().new(message, self)
end
@@ -213,30 +366,42 @@ class Net::HTTPResponse
@body = nil
end
@read = true
+ return if @body.nil?
+
+ case enc = @body_encoding
+ when Encoding, false, nil
+ # Encoding: force given encoding
+ # false/nil: do not force encoding
+ else
+ # other value: detect encoding from body
+ enc = detect_encoding(@body)
+ end
+
+ @body.force_encoding(enc) if enc
@body
end
- # Returns the full entity body.
+ # Returns the string response body;
+ # note that repeated calls for the unmodified body return a cached string:
#
- # Calling this method a second or subsequent time will return the
- # string already read.
+ # path = '/todos/1'
+ # Net::HTTP.start(hostname) do |http|
+ # res = http.get(path)
+ # p res.body
+ # p http.head(path).body # No body.
+ # end
#
- # http.request_get('/index.html') {|res|
- # puts res.body
- # }
+ # Output:
#
- # http.request_get('/index.html') {|res|
- # p res.body.object_id # 538149362
- # p res.body.object_id # 538149362
- # }
+ # "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"delectus aut autem\",\n \"completed\": false\n}"
+ # nil
#
def body
read_body()
end
- # Because it may be necessary to modify the body, Eg, decompression
- # this method facilitates that.
+ # Sets the body of the response to the given value.
def body=(value)
@body = value
end
@@ -245,6 +410,141 @@ class Net::HTTPResponse
private
+ # :nodoc:
+ def detect_encoding(str, encoding=nil)
+ if encoding
+ elsif encoding = type_params['charset']
+ elsif encoding = check_bom(str)
+ else
+ encoding = case content_type&.downcase
+ when %r{text/x(?:ht)?ml|application/(?:[^+]+\+)?xml}
+ /\A<xml[ \t\r\n]+
+ version[ \t\r\n]*=[ \t\r\n]*(?:"[0-9.]+"|'[0-9.]*')[ \t\r\n]+
+ encoding[ \t\r\n]*=[ \t\r\n]*
+ (?:"([A-Za-z][\-A-Za-z0-9._]*)"|'([A-Za-z][\-A-Za-z0-9._]*)')/x =~ str
+ encoding = $1 || $2 || Encoding::UTF_8
+ when %r{text/html.*}
+ sniff_encoding(str)
+ end
+ end
+ return encoding
+ end
+
+ # :nodoc:
+ def sniff_encoding(str, encoding=nil)
+ # the encoding sniffing algorithm
+ # http://www.w3.org/TR/html5/parsing.html#determining-the-character-encoding
+ if enc = scanning_meta(str)
+ enc
+ # 6. last visited page or something
+ # 7. frequency
+ elsif str.ascii_only?
+ Encoding::US_ASCII
+ elsif str.dup.force_encoding(Encoding::UTF_8).valid_encoding?
+ Encoding::UTF_8
+ end
+ # 8. implementation-defined or user-specified
+ end
+
+ # :nodoc:
+ def check_bom(str)
+ case str.byteslice(0, 2)
+ when "\xFE\xFF"
+ return Encoding::UTF_16BE
+ when "\xFF\xFE"
+ return Encoding::UTF_16LE
+ end
+ if "\xEF\xBB\xBF" == str.byteslice(0, 3)
+ return Encoding::UTF_8
+ end
+ nil
+ end
+
+ # :nodoc:
+ def scanning_meta(str)
+ require 'strscan'
+ ss = StringScanner.new(str)
+ if ss.scan_until(/<meta[\t\n\f\r ]*/)
+ attrs = {} # attribute_list
+ got_pragma = false
+ need_pragma = nil
+ charset = nil
+
+ # step: Attributes
+ while attr = get_attribute(ss)
+ name, value = *attr
+ next if attrs[name]
+ attrs[name] = true
+ case name
+ when 'http-equiv'
+ got_pragma = true if value == 'content-type'
+ when 'content'
+ encoding = extracting_encodings_from_meta_elements(value)
+ unless charset
+ charset = encoding
+ end
+ need_pragma = true
+ when 'charset'
+ need_pragma = false
+ charset = value
+ end
+ end
+
+ # step: Processing
+ return if need_pragma.nil?
+ return if need_pragma && !got_pragma
+
+ charset = Encoding.find(charset) rescue nil
+ return unless charset
+ charset = Encoding::UTF_8 if charset == Encoding::UTF_16
+ return charset # tentative
+ end
+ nil
+ end
+
+ def get_attribute(ss)
+ ss.scan(/[\t\n\f\r \/]*/)
+ if ss.peek(1) == '>'
+ ss.getch
+ return nil
+ end
+ name = ss.scan(/[^=\t\n\f\r \/>]*/)
+ name.downcase!
+ raise if name.empty?
+ ss.skip(/[\t\n\f\r ]*/)
+ if ss.getch != '='
+ value = ''
+ return [name, value]
+ end
+ ss.skip(/[\t\n\f\r ]*/)
+ case ss.peek(1)
+ when '"'
+ ss.getch
+ value = ss.scan(/[^"]+/)
+ value.downcase!
+ ss.getch
+ when "'"
+ ss.getch
+ value = ss.scan(/[^']+/)
+ value.downcase!
+ ss.getch
+ when '>'
+ value = ''
+ else
+ value = ss.scan(/[^\t\n\f\r >]+/)
+ value.downcase!
+ end
+ [name, value]
+ end
+
+ def extracting_encodings_from_meta_elements(value)
+ # http://dev.w3.org/html5/spec/fetching-resources.html#algorithm-for-extracting-an-encoding-from-a-meta-element
+ if /charset[\t\n\f\r ]*=(?:"([^"]*)"|'([^']*)'|["']|\z|([^\t\n\f\r ;]+))/i =~ value
+ return $1 || $2 || $3
+ end
+ return nil
+ end
+
##
# Checks for a supported Content-Encoding header and yields an Inflate
# wrapper for this response's socket when zlib is present. If the
@@ -272,6 +572,9 @@ class Net::HTTPResponse
ensure
begin
inflate_body_io.finish
+ if self['content-length']
+ self['content-length'] = inflate_body_io.bytes_inflated.to_s
+ end
rescue => err
# Ignore #finish's error if there is an exception from yield
raise err if success
@@ -297,7 +600,7 @@ class Net::HTTPResponse
clen = content_length()
if clen
- @socket.read clen, dest, true # ignore EOF
+ @socket.read clen, dest, @ignore_eof
return
end
clen = range_length()
@@ -337,7 +640,7 @@ class Net::HTTPResponse
end
def stream_check
- raise IOError, 'attempt to read body out of block' if @socket.closed?
+ raise IOError, 'attempt to read body out of block' if @socket.nil? || @socket.closed?
end
def procdest(dest, block)
@@ -346,7 +649,7 @@ class Net::HTTPResponse
if block
Net::ReadAdapter.new(block)
else
- dest || ''
+ dest || +''
end
end
@@ -374,6 +677,14 @@ class Net::HTTPResponse
end
##
+ # The number of bytes inflated, used to update the Content-Length of
+ # the response.
+
+ def bytes_inflated
+ @inflate.total_out
+ end
+
+ ##
# Returns a Net::ReadAdapter that inflates each read chunk into +dest+.
#
# This allows a large response body to be inflated without storing the
diff --git a/lib/net/http/responses.rb b/lib/net/http/responses.rb
index 50352032df..6f6fb8d055 100644
--- a/lib/net/http/responses.rb
+++ b/lib/net/http/responses.rb
@@ -1,231 +1,1100 @@
# frozen_string_literal: true
-# :stopdoc:
+#--
# https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
-class Net::HTTPUnknownResponse < Net::HTTPResponse
- HAS_BODY = true
- EXCEPTION_TYPE = Net::HTTPError
-end
-class Net::HTTPInformation < Net::HTTPResponse # 1xx
- HAS_BODY = false
- EXCEPTION_TYPE = Net::HTTPError
-end
-class Net::HTTPSuccess < Net::HTTPResponse # 2xx
- HAS_BODY = true
- EXCEPTION_TYPE = Net::HTTPError
-end
-class Net::HTTPRedirection < Net::HTTPResponse # 3xx
- HAS_BODY = true
- EXCEPTION_TYPE = Net::HTTPRetriableError
-end
-class Net::HTTPClientError < Net::HTTPResponse # 4xx
- HAS_BODY = true
- EXCEPTION_TYPE = Net::HTTPClientException # for backward compatibility
-end
-class Net::HTTPServerError < Net::HTTPResponse # 5xx
- HAS_BODY = true
- EXCEPTION_TYPE = Net::HTTPFatalError # for backward compatibility
-end
-class Net::HTTPContinue < Net::HTTPInformation # 100
- HAS_BODY = false
-end
-class Net::HTTPSwitchProtocol < Net::HTTPInformation # 101
- HAS_BODY = false
-end
-class Net::HTTPProcessing < Net::HTTPInformation # 102
- HAS_BODY = false
-end
-class Net::HTTPEarlyHints < Net::HTTPInformation # 103 - RFC 8297
- HAS_BODY = false
-end
+module Net
-class Net::HTTPOK < Net::HTTPSuccess # 200
- HAS_BODY = true
-end
-class Net::HTTPCreated < Net::HTTPSuccess # 201
- HAS_BODY = true
-end
-class Net::HTTPAccepted < Net::HTTPSuccess # 202
- HAS_BODY = true
-end
-class Net::HTTPNonAuthoritativeInformation < Net::HTTPSuccess # 203
- HAS_BODY = true
-end
-class Net::HTTPNoContent < Net::HTTPSuccess # 204
- HAS_BODY = false
-end
-class Net::HTTPResetContent < Net::HTTPSuccess # 205
- HAS_BODY = false
-end
-class Net::HTTPPartialContent < Net::HTTPSuccess # 206
- HAS_BODY = true
-end
-class Net::HTTPMultiStatus < Net::HTTPSuccess # 207 - RFC 4918
- HAS_BODY = true
-end
-class Net::HTTPAlreadyReported < Net::HTTPSuccess # 208 - RFC 5842
- HAS_BODY = true
-end
-class Net::HTTPIMUsed < Net::HTTPSuccess # 226 - RFC 3229
- HAS_BODY = true
-end
+ class HTTPUnknownResponse < HTTPResponse
+ HAS_BODY = true
+ EXCEPTION_TYPE = HTTPError #
+ end
-class Net::HTTPMultipleChoices < Net::HTTPRedirection # 300
- HAS_BODY = true
-end
-Net::HTTPMultipleChoice = Net::HTTPMultipleChoices
-class Net::HTTPMovedPermanently < Net::HTTPRedirection # 301
- HAS_BODY = true
-end
-class Net::HTTPFound < Net::HTTPRedirection # 302
- HAS_BODY = true
-end
-Net::HTTPMovedTemporarily = Net::HTTPFound
-class Net::HTTPSeeOther < Net::HTTPRedirection # 303
- HAS_BODY = true
-end
-class Net::HTTPNotModified < Net::HTTPRedirection # 304
- HAS_BODY = false
-end
-class Net::HTTPUseProxy < Net::HTTPRedirection # 305
- HAS_BODY = false
-end
-# 306 Switch Proxy - no longer unused
-class Net::HTTPTemporaryRedirect < Net::HTTPRedirection # 307
- HAS_BODY = true
-end
-class Net::HTTPPermanentRedirect < Net::HTTPRedirection # 308
- HAS_BODY = true
-end
+ # Parent class for informational (1xx) HTTP response classes.
+ #
+ # An informational response indicates that the request was received and understood.
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#status.1xx].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#1xx_informational_response].
+ #
+ class HTTPInformation < HTTPResponse
+ HAS_BODY = false
+ EXCEPTION_TYPE = HTTPError #
+ end
-class Net::HTTPBadRequest < Net::HTTPClientError # 400
- HAS_BODY = true
-end
-class Net::HTTPUnauthorized < Net::HTTPClientError # 401
- HAS_BODY = true
-end
-class Net::HTTPPaymentRequired < Net::HTTPClientError # 402
- HAS_BODY = true
-end
-class Net::HTTPForbidden < Net::HTTPClientError # 403
- HAS_BODY = true
-end
-class Net::HTTPNotFound < Net::HTTPClientError # 404
- HAS_BODY = true
-end
-class Net::HTTPMethodNotAllowed < Net::HTTPClientError # 405
- HAS_BODY = true
-end
-class Net::HTTPNotAcceptable < Net::HTTPClientError # 406
- HAS_BODY = true
-end
-class Net::HTTPProxyAuthenticationRequired < Net::HTTPClientError # 407
- HAS_BODY = true
-end
-class Net::HTTPRequestTimeout < Net::HTTPClientError # 408
- HAS_BODY = true
-end
-Net::HTTPRequestTimeOut = Net::HTTPRequestTimeout
-class Net::HTTPConflict < Net::HTTPClientError # 409
- HAS_BODY = true
-end
-class Net::HTTPGone < Net::HTTPClientError # 410
- HAS_BODY = true
-end
-class Net::HTTPLengthRequired < Net::HTTPClientError # 411
- HAS_BODY = true
-end
-class Net::HTTPPreconditionFailed < Net::HTTPClientError # 412
- HAS_BODY = true
-end
-class Net::HTTPPayloadTooLarge < Net::HTTPClientError # 413
- HAS_BODY = true
-end
-Net::HTTPRequestEntityTooLarge = Net::HTTPPayloadTooLarge
-class Net::HTTPURITooLong < Net::HTTPClientError # 414
- HAS_BODY = true
-end
-Net::HTTPRequestURITooLong = Net::HTTPURITooLong
-Net::HTTPRequestURITooLarge = Net::HTTPRequestURITooLong
-class Net::HTTPUnsupportedMediaType < Net::HTTPClientError # 415
- HAS_BODY = true
-end
-class Net::HTTPRangeNotSatisfiable < Net::HTTPClientError # 416
- HAS_BODY = true
-end
-Net::HTTPRequestedRangeNotSatisfiable = Net::HTTPRangeNotSatisfiable
-class Net::HTTPExpectationFailed < Net::HTTPClientError # 417
- HAS_BODY = true
-end
-# 418 I'm a teapot - RFC 2324; a joke RFC
-# 420 Enhance Your Calm - Twitter
-class Net::HTTPMisdirectedRequest < Net::HTTPClientError # 421 - RFC 7540
- HAS_BODY = true
-end
-class Net::HTTPUnprocessableEntity < Net::HTTPClientError # 422 - RFC 4918
- HAS_BODY = true
-end
-class Net::HTTPLocked < Net::HTTPClientError # 423 - RFC 4918
- HAS_BODY = true
-end
-class Net::HTTPFailedDependency < Net::HTTPClientError # 424 - RFC 4918
- HAS_BODY = true
-end
-# 425 Unordered Collection - existed only in draft
-class Net::HTTPUpgradeRequired < Net::HTTPClientError # 426 - RFC 2817
- HAS_BODY = true
-end
-class Net::HTTPPreconditionRequired < Net::HTTPClientError # 428 - RFC 6585
- HAS_BODY = true
-end
-class Net::HTTPTooManyRequests < Net::HTTPClientError # 429 - RFC 6585
- HAS_BODY = true
-end
-class Net::HTTPRequestHeaderFieldsTooLarge < Net::HTTPClientError # 431 - RFC 6585
- HAS_BODY = true
-end
-class Net::HTTPUnavailableForLegalReasons < Net::HTTPClientError # 451 - RFC 7725
- HAS_BODY = true
-end
-# 444 No Response - Nginx
-# 449 Retry With - Microsoft
-# 450 Blocked by Windows Parental Controls - Microsoft
-# 499 Client Closed Request - Nginx
+ # Parent class for success (2xx) HTTP response classes.
+ #
+ # A success response indicates the action requested by the client
+ # was received, understood, and accepted.
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#status.2xx].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_success].
+ #
+ class HTTPSuccess < HTTPResponse
+ HAS_BODY = true
+ EXCEPTION_TYPE = HTTPError #
+ end
+
+ # Parent class for redirection (3xx) HTTP response classes.
+ #
+ # A redirection response indicates the client must take additional action
+ # to complete the request.
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#status.3xx].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_redirection].
+ #
+ class HTTPRedirection < HTTPResponse
+ HAS_BODY = true
+ EXCEPTION_TYPE = HTTPRetriableError #
+ end
+
+ # Parent class for client error (4xx) HTTP response classes.
+ #
+ # A client error response indicates that the client may have caused an error.
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#status.4xx].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_client_errors].
+ #
+ class HTTPClientError < HTTPResponse
+ HAS_BODY = true
+ EXCEPTION_TYPE = HTTPClientException #
+ end
+
+ # Parent class for server error (5xx) HTTP response classes.
+ #
+ # A server error response indicates that the server failed to fulfill a request.
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#status.5xx].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_server_errors].
+ #
+ class HTTPServerError < HTTPResponse
+ HAS_BODY = true
+ EXCEPTION_TYPE = HTTPFatalError #
+ end
+
+ # Response class for +Continue+ responses (status code 100).
+ #
+ # A +Continue+ response indicates that the server has received the request headers.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/100].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-100-continue].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#100].
+ #
+ class HTTPContinue < HTTPInformation
+ HAS_BODY = false
+ end
+
+ # Response class for <tt>Switching Protocol</tt> responses (status code 101).
+ #
+ # The <tt>Switching Protocol<tt> response indicates that the server has received
+ # a request to switch protocols, and has agreed to do so.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/101].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-101-switching-protocols].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#101].
+ #
+ class HTTPSwitchProtocol < HTTPInformation
+ HAS_BODY = false
+ end
+
+ # Response class for +Processing+ responses (status code 102).
+ #
+ # The +Processing+ response indicates that the server has received
+ # and is processing the request, but no response is available yet.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 2518}[https://www.rfc-editor.org/rfc/rfc2518#section-10.1].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#102].
+ #
+ class HTTPProcessing < HTTPInformation
+ HAS_BODY = false
+ end
+
+ # Response class for <tt>Early Hints</tt> responses (status code 103).
+ #
+ # The <tt>Early Hints</tt> indicates that the server has received
+ # and is processing the request, and contains certain headers;
+ # the final response is not available yet.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103].
+ # - {RFC 8297}[https://www.rfc-editor.org/rfc/rfc8297.html#section-2].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#103].
+ #
+ class HTTPEarlyHints < HTTPInformation
+ HAS_BODY = false
+ end
+
+ # Response class for +OK+ responses (status code 200).
+ #
+ # The +OK+ response indicates that the server has received
+ # a request and has responded successfully.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-200-ok].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#200].
+ #
+ class HTTPOK < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for +Created+ responses (status code 201).
+ #
+ # The +Created+ response indicates that the server has received
+ # and has fulfilled a request to create a new resource.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-201-created].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#201].
+ #
+ class HTTPCreated < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for +Accepted+ responses (status code 202).
+ #
+ # The +Accepted+ response indicates that the server has received
+ # and is processing a request, but the processing has not yet been completed.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-202-accepted].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#202].
+ #
+ class HTTPAccepted < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Non-Authoritative Information</tt> responses (status code 203).
+ #
+ # The <tt>Non-Authoritative Information</tt> response indicates that the server
+ # is a transforming proxy (such as a Web accelerator)
+ # that received a 200 OK response from its origin,
+ # and is returning a modified version of the origin's response.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/203].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-203-non-authoritative-infor].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#203].
+ #
+ class HTTPNonAuthoritativeInformation < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>No Content</tt> responses (status code 204).
+ #
+ # The <tt>No Content</tt> response indicates that the server
+ # successfully processed the request, and is not returning any content.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-204-no-content].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#204].
+ #
+ class HTTPNoContent < HTTPSuccess
+ HAS_BODY = false
+ end
+
+ # Response class for <tt>Reset Content</tt> responses (status code 205).
+ #
+ # The <tt>Reset Content</tt> response indicates that the server
+ # successfully processed the request,
+ # asks that the client reset its document view, and is not returning any content.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/205].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-205-reset-content].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#205].
+ #
+ class HTTPResetContent < HTTPSuccess
+ HAS_BODY = false
+ end
+
+ # Response class for <tt>Partial Content</tt> responses (status code 206).
+ #
+ # The <tt>Partial Content</tt> response indicates that the server is delivering
+ # only part of the resource (byte serving)
+ # due to a Range header in the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-206-partial-content].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#206].
+ #
+ class HTTPPartialContent < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Multi-Status (WebDAV)</tt> responses (status code 207).
+ #
+ # The <tt>Multi-Status (WebDAV)</tt> response indicates that the server
+ # has received the request,
+ # and that the message body can contain a number of separate response codes.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 4818}[https://www.rfc-editor.org/rfc/rfc4918#section-11.1].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#207].
+ #
+ class HTTPMultiStatus < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Already Reported (WebDAV)</tt> responses (status code 208).
+ #
+ # The <tt>Already Reported (WebDAV)</tt> response indicates that the server
+ # has received the request,
+ # and that the members of a DAV binding have already been enumerated
+ # in a preceding part of the (multi-status) response,
+ # and are not being included again.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 5842}[https://www.rfc-editor.org/rfc/rfc5842.html#section-7.1].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#208].
+ #
+ class HTTPAlreadyReported < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>IM Used</tt> responses (status code 226).
+ #
+ # The <tt>IM Used</tt> response indicates that the server has fulfilled a request
+ # for the resource, and the response is a representation of the result
+ # of one or more instance-manipulations applied to the current instance.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 3229}[https://www.rfc-editor.org/rfc/rfc3229.html#section-10.4.1].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#226].
+ #
+ class HTTPIMUsed < HTTPSuccess
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Multiple Choices</tt> responses (status code 300).
+ #
+ # The <tt>Multiple Choices</tt> response indicates that the server
+ # offers multiple options for the resource from which the client may choose.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/300].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-300-multiple-choices].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300].
+ #
+ class HTTPMultipleChoices < HTTPRedirection
+ HAS_BODY = true
+ end
+ HTTPMultipleChoice = HTTPMultipleChoices
+
+ # Response class for <tt>Moved Permanently</tt> responses (status code 301).
+ #
+ # The <tt>Moved Permanently</tt> response indicates that links or records
+ # returning this response should be updated to use the given URL.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-301-moved-permanently].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#301].
+ #
+ class HTTPMovedPermanently < HTTPRedirection
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Found</tt> responses (status code 302).
+ #
+ # The <tt>Found</tt> response indicates that the client
+ # should look at (browse to) another URL.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-302-found].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#302].
+ #
+ class HTTPFound < HTTPRedirection
+ HAS_BODY = true
+ end
+ HTTPMovedTemporarily = HTTPFound
+
+ # Response class for <tt>See Other</tt> responses (status code 303).
+ #
+ # The response to the request can be found under another URI using the GET method.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-303-see-other].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#303].
+ #
+ class HTTPSeeOther < HTTPRedirection
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Not Modified</tt> responses (status code 304).
+ #
+ # Indicates that the resource has not been modified since the version
+ # specified by the request headers.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-304-not-modified].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#304].
+ #
+ class HTTPNotModified < HTTPRedirection
+ HAS_BODY = false
+ end
+
+ # Response class for <tt>Use Proxy</tt> responses (status code 305).
+ #
+ # The requested resource is available only through a proxy,
+ # whose address is provided in the response.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-305-use-proxy].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#305].
+ #
+ class HTTPUseProxy < HTTPRedirection
+ HAS_BODY = false
+ end
+
+ # Response class for <tt>Temporary Redirect</tt> responses (status code 307).
+ #
+ # The request should be repeated with another URI;
+ # however, future requests should still use the original URI.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-307-temporary-redirect].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#307].
+ #
+ class HTTPTemporaryRedirect < HTTPRedirection
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Permanent Redirect</tt> responses (status code 308).
+ #
+ # This and all future requests should be directed to the given URI.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-308-permanent-redirect].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#308].
+ #
+ class HTTPPermanentRedirect < HTTPRedirection
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Bad Request</tt> responses (status code 400).
+ #
+ # The server cannot or will not process the request due to an apparent client error.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#400].
+ #
+ class HTTPBadRequest < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Unauthorized</tt> responses (status code 401).
+ #
+ # Authentication is required, but either was not provided or failed.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-401-unauthorized].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#401].
+ #
+ class HTTPUnauthorized < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Payment Required</tt> responses (status code 402).
+ #
+ # Reserved for future use.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-402-payment-required].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#402].
+ #
+ class HTTPPaymentRequired < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Forbidden</tt> responses (status code 403).
+ #
+ # The request contained valid data and was understood by the server,
+ # but the server is refusing action.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-403-forbidden].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#403].
+ #
+ class HTTPForbidden < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Not Found</tt> responses (status code 404).
+ #
+ # The requested resource could not be found but may be available in the future.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-404-not-found].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#404].
+ #
+ class HTTPNotFound < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Method Not Allowed</tt> responses (status code 405).
+ #
+ # The request method is not supported for the requested resource.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-405-method-not-allowed].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#405].
+ #
+ class HTTPMethodNotAllowed < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Not Acceptable</tt> responses (status code 406).
+ #
+ # The requested resource is capable of generating only content
+ # that not acceptable according to the Accept headers sent in the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-406-not-acceptable].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#406].
+ #
+ class HTTPNotAcceptable < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Proxy Authentication Required</tt> responses (status code 407).
+ #
+ # The client must first authenticate itself with the proxy.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/407].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-407-proxy-authentication-re].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#407].
+ #
+ class HTTPProxyAuthenticationRequired < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Request Timeout</tt> responses (status code 408).
+ #
+ # The server timed out waiting for the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-408-request-timeout].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#408].
+ #
+ class HTTPRequestTimeout < HTTPClientError
+ HAS_BODY = true
+ end
+ HTTPRequestTimeOut = HTTPRequestTimeout
+
+ # Response class for <tt>Conflict</tt> responses (status code 409).
+ #
+ # The request could not be processed because of conflict in the current state of the resource.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-409-conflict].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#409].
+ #
+ class HTTPConflict < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Gone</tt> responses (status code 410).
+ #
+ # The resource requested was previously in use but is no longer available
+ # and will not be available again.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/410].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-410-gone].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#410].
+ #
+ class HTTPGone < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Length Required</tt> responses (status code 411).
+ #
+ # The request did not specify the length of its content,
+ # which is required by the requested resource.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/411].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-411-length-required].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#411].
+ #
+ class HTTPLengthRequired < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Precondition Failed</tt> responses (status code 412).
+ #
+ # The server does not meet one of the preconditions
+ # specified in the request headers.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/412].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-412-precondition-failed].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#412].
+ #
+ class HTTPPreconditionFailed < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Payload Too Large</tt> responses (status code 413).
+ #
+ # The request is larger than the server is willing or able to process.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-413-content-too-large].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#413].
+ #
+ class HTTPPayloadTooLarge < HTTPClientError
+ HAS_BODY = true
+ end
+ HTTPRequestEntityTooLarge = HTTPPayloadTooLarge
+
+ # Response class for <tt>URI Too Long</tt> responses (status code 414).
+ #
+ # The URI provided was too long for the server to process.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/414].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-414-uri-too-long].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#414].
+ #
+ class HTTPURITooLong < HTTPClientError
+ HAS_BODY = true
+ end
+ HTTPRequestURITooLong = HTTPURITooLong
+ HTTPRequestURITooLarge = HTTPRequestURITooLong
+
+ # Response class for <tt>Unsupported Media Type</tt> responses (status code 415).
+ #
+ # The request entity has a media type which the server or resource does not support.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/415].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-415-unsupported-media-type].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#415].
+ #
+ class HTTPUnsupportedMediaType < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Range Not Satisfiable</tt> responses (status code 416).
+ #
+ # The request entity has a media type which the server or resource does not support.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/416].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-416-range-not-satisfiable].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#416].
+ #
+ class HTTPRangeNotSatisfiable < HTTPClientError
+ HAS_BODY = true
+ end
+ HTTPRequestedRangeNotSatisfiable = HTTPRangeNotSatisfiable
+
+ # Response class for <tt>Expectation Failed</tt> responses (status code 417).
+ #
+ # The server cannot meet the requirements of the Expect request-header field.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/417].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-417-expectation-failed].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#417].
+ #
+ class HTTPExpectationFailed < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # 418 I'm a teapot - RFC 2324; a joke RFC
+ # See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#418.
+
+ # 420 Enhance Your Calm - Twitter
+
+ # Response class for <tt>Misdirected Request</tt> responses (status code 421).
+ #
+ # The request was directed at a server that is not able to produce a response.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-421-misdirected-request].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#421].
+ #
+ class HTTPMisdirectedRequest < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Unprocessable Entity</tt> responses (status code 422).
+ #
+ # The request was well-formed but had semantic errors.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-422-unprocessable-content].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#422].
+ #
+ class HTTPUnprocessableEntity < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Locked (WebDAV)</tt> responses (status code 423).
+ #
+ # The requested resource is locked.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 4918}[https://www.rfc-editor.org/rfc/rfc4918#section-11.3].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#423].
+ #
+ class HTTPLocked < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Failed Dependency (WebDAV)</tt> responses (status code 424).
+ #
+ # The request failed because it depended on another request and that request failed.
+ # See {424 Failed Dependency (WebDAV)}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#424].
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {RFC 4918}[https://www.rfc-editor.org/rfc/rfc4918#section-11.4].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#424].
+ #
+ class HTTPFailedDependency < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # 425 Too Early
+ # https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#425.
+
+ # Response class for <tt>Upgrade Required</tt> responses (status code 426).
+ #
+ # The client should switch to the protocol given in the Upgrade header field.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/426].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-426-upgrade-required].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#426].
+ #
+ class HTTPUpgradeRequired < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Precondition Required</tt> responses (status code 428).
+ #
+ # The origin server requires the request to be conditional.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/428].
+ # - {RFC 6585}[https://www.rfc-editor.org/rfc/rfc6585#section-3].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#428].
+ #
+ class HTTPPreconditionRequired < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Too Many Requests</tt> responses (status code 429).
+ #
+ # The user has sent too many requests in a given amount of time.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429].
+ # - {RFC 6585}[https://www.rfc-editor.org/rfc/rfc6585#section-4].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#429].
+ #
+ class HTTPTooManyRequests < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Request Header Fields Too Large</tt> responses (status code 431).
+ #
+ # An individual header field is too large,
+ # or all the header fields collectively, are too large.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/431].
+ # - {RFC 6585}[https://www.rfc-editor.org/rfc/rfc6585#section-5].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#431].
+ #
+ class HTTPRequestHeaderFieldsTooLarge < HTTPClientError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Unavailable For Legal Reasons</tt> responses (status code 451).
+ #
+ # A server operator has received a legal demand to deny access to a resource or to a set of resources
+ # that includes the requested resource.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/451].
+ # - {RFC 7725}[https://www.rfc-editor.org/rfc/rfc7725.html#section-3].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#451].
+ #
+ class HTTPUnavailableForLegalReasons < HTTPClientError
+ HAS_BODY = true
+ end
+ # 444 No Response - Nginx
+ # 449 Retry With - Microsoft
+ # 450 Blocked by Windows Parental Controls - Microsoft
+ # 499 Client Closed Request - Nginx
+
+ # Response class for <tt>Internal Server Error</tt> responses (status code 500).
+ #
+ # An unexpected condition was encountered and no more specific message is suitable.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-500-internal-server-error].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#500].
+ #
+ class HTTPInternalServerError < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Not Implemented</tt> responses (status code 501).
+ #
+ # The server either does not recognize the request method,
+ # or it lacks the ability to fulfil the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/501].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-501-not-implemented].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#501].
+ #
+ class HTTPNotImplemented < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Bad Gateway</tt> responses (status code 502).
+ #
+ # The server was acting as a gateway or proxy
+ # and received an invalid response from the upstream server.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-502-bad-gateway].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#502].
+ #
+ class HTTPBadGateway < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Service Unavailable</tt> responses (status code 503).
+ #
+ # The server cannot handle the request
+ # (because it is overloaded or down for maintenance).
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-503-service-unavailable].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#503].
+ #
+ class HTTPServiceUnavailable < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Gateway Timeout</tt> responses (status code 504).
+ #
+ # The server was acting as a gateway or proxy
+ # and did not receive a timely response from the upstream server.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-504-gateway-timeout].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#504].
+ #
+ class HTTPGatewayTimeout < HTTPServerError
+ HAS_BODY = true
+ end
+ HTTPGatewayTimeOut = HTTPGatewayTimeout
+
+ # Response class for <tt>HTTP Version Not Supported</tt> responses (status code 505).
+ #
+ # The server does not support the HTTP version used in the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/505].
+ # - {RFC 9110}[https://www.rfc-editor.org/rfc/rfc9110.html#name-505-http-version-not-suppor].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#505].
+ #
+ class HTTPVersionNotSupported < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Variant Also Negotiates</tt> responses (status code 506).
+ #
+ # Transparent content negotiation for the request results in a circular reference.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/506].
+ # - {RFC 2295}[https://www.rfc-editor.org/rfc/rfc2295#section-8.1].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#506].
+ #
+ class HTTPVariantAlsoNegotiates < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Insufficient Storage (WebDAV)</tt> responses (status code 507).
+ #
+ # The server is unable to store the representation needed to complete the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/507].
+ # - {RFC 4918}[https://www.rfc-editor.org/rfc/rfc4918#section-11.5].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#507].
+ #
+ class HTTPInsufficientStorage < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Loop Detected (WebDAV)</tt> responses (status code 508).
+ #
+ # The server detected an infinite loop while processing the request.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/508].
+ # - {RFC 5942}[https://www.rfc-editor.org/rfc/rfc5842.html#section-7.2].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#508].
+ #
+ class HTTPLoopDetected < HTTPServerError
+ HAS_BODY = true
+ end
+ # 509 Bandwidth Limit Exceeded - Apache bw/limited extension
+
+ # Response class for <tt>Not Extended</tt> responses (status code 510).
+ #
+ # Further extensions to the request are required for the server to fulfill it.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/510].
+ # - {RFC 2774}[https://www.rfc-editor.org/rfc/rfc2774.html#section-7].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#510].
+ #
+ class HTTPNotExtended < HTTPServerError
+ HAS_BODY = true
+ end
+
+ # Response class for <tt>Network Authentication Required</tt> responses (status code 511).
+ #
+ # The client needs to authenticate to gain network access.
+ #
+ # :include: doc/net-http/included_getters.rdoc
+ #
+ # References:
+ #
+ # - {Mozilla}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/511].
+ # - {RFC 6585}[https://www.rfc-editor.org/rfc/rfc6585#section-6].
+ # - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#511].
+ #
+ class HTTPNetworkAuthenticationRequired < HTTPServerError
+ HAS_BODY = true
+ end
-class Net::HTTPInternalServerError < Net::HTTPServerError # 500
- HAS_BODY = true
-end
-class Net::HTTPNotImplemented < Net::HTTPServerError # 501
- HAS_BODY = true
-end
-class Net::HTTPBadGateway < Net::HTTPServerError # 502
- HAS_BODY = true
-end
-class Net::HTTPServiceUnavailable < Net::HTTPServerError # 503
- HAS_BODY = true
-end
-class Net::HTTPGatewayTimeout < Net::HTTPServerError # 504
- HAS_BODY = true
-end
-Net::HTTPGatewayTimeOut = Net::HTTPGatewayTimeout
-class Net::HTTPVersionNotSupported < Net::HTTPServerError # 505
- HAS_BODY = true
-end
-class Net::HTTPVariantAlsoNegotiates < Net::HTTPServerError # 506
- HAS_BODY = true
-end
-class Net::HTTPInsufficientStorage < Net::HTTPServerError # 507 - RFC 4918
- HAS_BODY = true
-end
-class Net::HTTPLoopDetected < Net::HTTPServerError # 508 - RFC 5842
- HAS_BODY = true
-end
-# 509 Bandwidth Limit Exceeded - Apache bw/limited extension
-class Net::HTTPNotExtended < Net::HTTPServerError # 510 - RFC 2774
- HAS_BODY = true
-end
-class Net::HTTPNetworkAuthenticationRequired < Net::HTTPServerError # 511 - RFC 6585
- HAS_BODY = true
end
class Net::HTTPResponse
@@ -303,5 +1172,3 @@ class Net::HTTPResponse
'511' => Net::HTTPNetworkAuthenticationRequired,
}
end
-
-# :startdoc:
diff --git a/lib/net/http/status.rb b/lib/net/http/status.rb
index 8db3f7d9e3..e70b47d9fb 100644
--- a/lib/net/http/status.rb
+++ b/lib/net/http/status.rb
@@ -4,7 +4,7 @@ require_relative '../http'
if $0 == __FILE__
require 'open-uri'
- IO.foreach(__FILE__) do |line|
+ File.foreach(__FILE__) do |line|
puts line
break if line.start_with?('end')
end
@@ -16,7 +16,7 @@ if $0 == __FILE__
next if ['(Unused)', 'Unassigned', 'Description'].include?(mes)
puts " #{code} => '#{mes}',"
end
- puts "}"
+ puts "} # :nodoc:"
end
Net::HTTP::STATUS_CODES = {
@@ -55,15 +55,16 @@ Net::HTTP::STATUS_CODES = {
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
- 413 => 'Payload Too Large',
+ 413 => 'Content Too Large',
414 => 'URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Range Not Satisfiable',
417 => 'Expectation Failed',
421 => 'Misdirected Request',
- 422 => 'Unprocessable Entity',
+ 422 => 'Unprocessable Content',
423 => 'Locked',
424 => 'Failed Dependency',
+ 425 => 'Too Early',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
@@ -78,6 +79,6 @@ Net::HTTP::STATUS_CODES = {
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
508 => 'Loop Detected',
- 510 => 'Not Extended',
+ 510 => 'Not Extended (OBSOLETED)',
511 => 'Network Authentication Required',
-}
+} # :nodoc:
diff --git a/lib/net/https.rb b/lib/net/https.rb
index d46721c82a..0f23e1fb13 100644
--- a/lib/net/https.rb
+++ b/lib/net/https.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
=begin
= net/https -- SSL/TLS enhancement for Net::HTTP.
diff --git a/lib/net/net-protocol.gemspec b/lib/net/net-protocol.gemspec
index 767a7d48e2..c03621cb0d 100644
--- a/lib/net/net-protocol.gemspec
+++ b/lib/net/net-protocol.gemspec
@@ -13,10 +13,10 @@ Gem::Specification.new do |spec|
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.summary = %q{The abstract interface for net-* client.}
+ spec.description = %q{The abstract interface for net-* client.}
spec.homepage = "https://github.com/ruby/net-protocol"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
@@ -27,10 +27,7 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "timeout"
- spec.add_dependency "io-wait"
end
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb
index 0afac2a02a..ea0752a971 100644
--- a/lib/net/protocol.rb
+++ b/lib/net/protocol.rb
@@ -26,7 +26,7 @@ require 'io/wait'
module Net # :nodoc:
class Protocol #:nodoc: internal use only
- VERSION = "0.1.1"
+ VERSION = "0.2.1"
private
def Protocol.protocol_param(name, val)
@@ -120,6 +120,8 @@ module Net # :nodoc:
@continue_timeout = continue_timeout
@debug_output = debug_output
@rbuf = ''.b
+ @rbuf_empty = true
+ @rbuf_offset = 0
end
attr_reader :io
@@ -154,14 +156,15 @@ module Net # :nodoc:
LOG "reading #{len} bytes..."
read_bytes = 0
begin
- while read_bytes + @rbuf.size < len
- s = rbuf_consume(@rbuf.size)
- read_bytes += s.size
- dest << s
+ while read_bytes + rbuf_size < len
+ if s = rbuf_consume_all
+ read_bytes += s.bytesize
+ dest << s
+ end
rbuf_fill
end
s = rbuf_consume(len - read_bytes)
- read_bytes += s.size
+ read_bytes += s.bytesize
dest << s
rescue EOFError
raise unless ignore_eof
@@ -175,9 +178,10 @@ module Net # :nodoc:
read_bytes = 0
begin
while true
- s = rbuf_consume(@rbuf.size)
- read_bytes += s.size
- dest << s
+ if s = rbuf_consume_all
+ read_bytes += s.bytesize
+ dest << s
+ end
rbuf_fill
end
rescue EOFError
@@ -188,14 +192,16 @@ module Net # :nodoc:
end
def readuntil(terminator, ignore_eof = false)
+ offset = @rbuf_offset
begin
- until idx = @rbuf.index(terminator)
+ until idx = @rbuf.index(terminator, offset)
+ offset = @rbuf.bytesize
rbuf_fill
end
- return rbuf_consume(idx + terminator.size)
+ return rbuf_consume(idx + terminator.bytesize - @rbuf_offset)
rescue EOFError
raise unless ignore_eof
- return rbuf_consume(@rbuf.size)
+ return rbuf_consume
end
end
@@ -208,12 +214,16 @@ module Net # :nodoc:
BUFSIZE = 1024 * 16
def rbuf_fill
- tmp = @rbuf.empty? ? @rbuf : nil
+ tmp = @rbuf_empty ? @rbuf : nil
case rv = @io.read_nonblock(BUFSIZE, tmp, exception: false)
when String
- return if rv.equal?(tmp)
- @rbuf << rv
- rv.clear
+ @rbuf_empty = false
+ if rv.equal?(tmp)
+ @rbuf_offset = 0
+ else
+ @rbuf << rv
+ rv.clear
+ end
return
when :wait_readable
(io = @io.to_io).wait_readable(@read_timeout) or raise Net::ReadTimeout.new(io)
@@ -228,13 +238,40 @@ module Net # :nodoc:
end while true
end
- def rbuf_consume(len)
- if len == @rbuf.size
+ def rbuf_flush
+ if @rbuf_empty
+ @rbuf.clear
+ @rbuf_offset = 0
+ end
+ nil
+ end
+
+ def rbuf_size
+ @rbuf.bytesize - @rbuf_offset
+ end
+
+ def rbuf_consume_all
+ rbuf_consume if rbuf_size > 0
+ end
+
+ def rbuf_consume(len = nil)
+ if @rbuf_offset == 0 && (len.nil? || len == @rbuf.bytesize)
s = @rbuf
@rbuf = ''.b
+ @rbuf_offset = 0
+ @rbuf_empty = true
+ elsif len.nil?
+ s = @rbuf.byteslice(@rbuf_offset..-1)
+ @rbuf = ''.b
+ @rbuf_offset = 0
+ @rbuf_empty = true
else
- s = @rbuf.slice!(0, len)
+ s = @rbuf.byteslice(@rbuf_offset, len)
+ @rbuf_offset += len
+ @rbuf_empty = @rbuf_offset == @rbuf.bytesize
+ rbuf_flush
end
+
@debug_output << %Q[-> #{s.dump}\n] if @debug_output
s
end
diff --git a/lib/open-uri.gemspec b/lib/open-uri.gemspec
index 853049f7ec..cad63e4d80 100644
--- a/lib/open-uri.gemspec
+++ b/lib/open-uri.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "open-uri"
- spec.version = "0.1.0"
+ spec.version = "0.3.0"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
@@ -14,10 +14,9 @@ Gem::Specification.new do |spec|
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)/}) }
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A((bin|test|spec|features)/|\.git|[Rr]ake|Gemfile)|\.gemspec\z}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.executables = []
spec.require_paths = ["lib"]
spec.add_dependency "uri"
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index e33e57a7f6..93e8cfcdb7 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -9,7 +9,7 @@ module URI
# If the first argument responds to the 'open' method, 'open' is called on
# it with the rest of the arguments.
#
- # If the first argument is a string that begins with <code>(protocol)://<code>, it is parsed by
+ # If the first argument is a string that begins with <code>(protocol)://</code>, it is parsed by
# URI.parse. If the parsed object responds to the 'open' method,
# 'open' is called on it with the rest of the arguments.
#
@@ -99,6 +99,8 @@ module OpenURI
:open_timeout => true,
:ssl_ca_cert => nil,
:ssl_verify_mode => nil,
+ :ssl_min_version => nil,
+ :ssl_max_version => nil,
:ftp_active_mode => false,
:redirect => true,
:encoding => nil,
@@ -298,6 +300,8 @@ module OpenURI
require 'net/https'
http.use_ssl = true
http.verify_mode = options[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER
+ http.min_version = options[:ssl_min_version]
+ http.max_version = options[:ssl_max_version]
store = OpenSSL::X509::Store.new
if options[:ssl_ca_cert]
Array(options[:ssl_ca_cert]).each do |cert|
@@ -353,7 +357,8 @@ module OpenURI
when Net::HTTPMovedPermanently, # 301
Net::HTTPFound, # 302
Net::HTTPSeeOther, # 303
- Net::HTTPTemporaryRedirect # 307
+ Net::HTTPTemporaryRedirect, # 307
+ Net::HTTPPermanentRedirect # 308
begin
loc_uri = URI.parse(resp['location'])
rescue URI::InvalidURIError
@@ -410,6 +415,13 @@ module OpenURI
end
end
+ # :stopdoc:
+ RE_LWS = /[\r\n\t ]+/n
+ RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
+ RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
+ RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
+ # :startdoc:
+
# Mixin for holding meta-information.
module Meta
def Meta.init(obj, src=nil) # :nodoc:
@@ -487,13 +499,6 @@ module OpenURI
end
end
- # :stopdoc:
- RE_LWS = /[\r\n\t ]+/n
- RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
- RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
- RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
- # :startdoc:
-
def content_type_parse # :nodoc:
vs = @metas['content-type']
# The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.
@@ -698,6 +703,20 @@ module OpenURI
#
# :ssl_verify_mode is used to specify openssl verify mode.
#
+ # [:ssl_min_version]
+ # Synopsis:
+ # :ssl_min_version=>:TLS1_2
+ #
+ # :ssl_min_version option specifies the minimum allowed SSL/TLS protocol
+ # version. See also OpenSSL::SSL::SSLContext#min_version=.
+ #
+ # [:ssl_max_version]
+ # Synopsis:
+ # :ssl_max_version=>:TLS1_2
+ #
+ # :ssl_max_version option specifies the maximum allowed SSL/TLS protocol
+ # version. See also OpenSSL::SSL::SSLContext#max_version=.
+ #
# [:ftp_active_mode]
# Synopsis:
# :ftp_active_mode=>bool
diff --git a/lib/open3.rb b/lib/open3.rb
index c574696bb1..9652b27194 100644
--- a/lib/open3.rb
+++ b/lib/open3.rb
@@ -29,8 +29,9 @@
# - Open3.pipeline : run a pipeline and wait for its completion
#
+require 'open3/version'
+
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.
@@ -758,3 +759,6 @@ module Open3
end
end
+
+# JRuby uses different popen logic on Windows, require it here to reuse wrapper methods above.
+require 'open3/jruby_windows' if RUBY_ENGINE == 'jruby' && JRuby::Util::ON_WINDOWS
diff --git a/lib/open3.gemspec b/lib/open3/open3.gemspec
index ad9485adc7..a33fca7444 100644
--- a/lib/open3.gemspec
+++ b/lib/open3/open3.gemspec
@@ -1,8 +1,8 @@
# 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|
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}/version.rb")) do |line|
/^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
end rescue nil
end
diff --git a/lib/open3/version.rb b/lib/open3/version.rb
new file mode 100644
index 0000000000..b6b6ee2c9c
--- /dev/null
+++ b/lib/open3/version.rb
@@ -0,0 +1,3 @@
+module Open3
+ VERSION = "0.1.2"
+end
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 060b13428a..53a4387bd8 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -50,7 +50,7 @@
#
# === New to \OptionParser?
#
-# See the {Tutorial}[./doc/optparse/tutorial_rdoc.html].
+# See the {Tutorial}[optparse/tutorial.rdoc].
#
# === Introduction
#
@@ -420,12 +420,12 @@
# === Further documentation
#
# The above examples, along with the accompanying
-# {Tutorial}[./doc/optparse/tutorial_rdoc.html],
+# {Tutorial}[optparse/tutorial.rdoc],
# should be enough to learn how to use this class.
# If you have any questions, file a ticket at http://bugs.ruby-lang.org.
#
class OptionParser
- OptionParser::Version = "0.1.1"
+ OptionParser::Version = "0.3.1"
# :stopdoc:
NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
@@ -674,6 +674,29 @@ class OptionParser
end
end
+ def pretty_print_contents(q) # :nodoc:
+ if @block
+ q.text ":" + @block.source_location.join(":") + ":"
+ first = false
+ else
+ first = true
+ end
+ [@short, @long].each do |list|
+ list.each do |opt|
+ if first
+ q.text ":"
+ first = false
+ end
+ q.breakable
+ q.text opt
+ end
+ end
+ end
+
+ def pretty_print(q) # :nodoc:
+ q.object_group(self) {pretty_print_contents(q)}
+ end
+
#
# Switch that takes no arguments.
#
@@ -693,6 +716,10 @@ class OptionParser
def self.pattern
Object
end
+
+ def pretty_head # :nodoc:
+ "NoArgument"
+ end
end
#
@@ -710,6 +737,10 @@ class OptionParser
end
conv_arg(*parse_arg(arg, &method(:raise)))
end
+
+ def pretty_head # :nodoc:
+ "Required"
+ end
end
#
@@ -727,18 +758,22 @@ class OptionParser
conv_arg(arg)
end
end
+
+ def pretty_head # :nodoc:
+ "Optional"
+ end
end
#
- # Switch that takes an argument, which does not begin with '-'.
+ # Switch that takes an argument, which does not begin with '-' or is '-'.
#
class PlacedArgument < self
#
- # Returns nil if argument is not present or begins with '-'.
+ # Returns nil if argument is not present or begins with '-' and is not '-'.
#
def parse(arg, argv, &error)
- if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
+ if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0]))
return nil, block, nil
end
opt = (val = parse_arg(val, &error))[1]
@@ -750,6 +785,10 @@ class OptionParser
end
val
end
+
+ def pretty_head # :nodoc:
+ "Placed"
+ end
end
end
@@ -781,6 +820,17 @@ class OptionParser
@list = []
end
+ def pretty_print(q) # :nodoc:
+ q.group(1, "(", ")") do
+ @list.each do |sw|
+ next unless Switch === sw
+ q.group(1, "(" + sw.pretty_head, ")") do
+ sw.pretty_print_contents(q)
+ end
+ end
+ end
+ end
+
#
# See OptionParser.accept.
#
@@ -1098,6 +1148,7 @@ XXX
@summary_indent = indent
@default_argv = ARGV
@require_exact = false
+ @raise_unknown = true
add_officious
yield self if block_given?
end
@@ -1175,6 +1226,9 @@ XXX
# abbreviated long option as short option).
attr_accessor :require_exact
+ # Whether to raise at unknown option.
+ attr_accessor :raise_unknown
+
#
# Heading banner preceding summary.
#
@@ -1293,6 +1347,29 @@ XXX
def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end
alias to_s help
+ def pretty_print(q) # :nodoc:
+ q.object_group(self) do
+ first = true
+ if @stack.size > 2
+ @stack.each_with_index do |s, i|
+ next if i < 2
+ next if s.list.empty?
+ if first
+ first = false
+ q.text ":"
+ end
+ q.breakable
+ s.pretty_print(q)
+ end
+ end
+ end
+ end
+
+ def inspect # :nodoc:
+ require 'pp'
+ pretty_print_inspect
+ end
+
#
# Returns option summary list.
#
@@ -1429,7 +1506,7 @@ XXX
style = notwice(default_style.guess(arg = o), style, 'style')
default_pattern, conv = search(:atype, Object) unless default_pattern
else
- desc.push(o)
+ desc.push(o) if o && !o.empty?
end
end
@@ -1566,9 +1643,11 @@ XXX
begin
sw, = complete(:long, opt, true)
if require_exact && !sw.long.include?(arg)
+ throw :terminate, arg unless raise_unknown
raise InvalidOption, arg
end
rescue ParseError
+ throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
end
begin
@@ -1600,6 +1679,7 @@ XXX
end
end
rescue ParseError
+ throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
end
begin
@@ -1830,10 +1910,13 @@ XXX
# directory ~/.options, then the basename with '.options' suffix
# under XDG and Haiku standard places.
#
- def load(filename = nil)
+ # The optional +into+ keyword argument works exactly like that accepted in
+ # method #parse.
+ #
+ def load(filename = nil, into: nil)
unless filename
basename = File.basename($0, '.*')
- return true if load(File.expand_path(basename, '~/.options')) rescue nil
+ return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil
basename << ".options"
return [
# XDG
@@ -1845,11 +1928,11 @@ XXX
'~/config/settings',
].any? {|dir|
next if !dir or dir.empty?
- load(File.expand_path(basename, dir)) rescue nil
+ load(File.expand_path(basename, dir), into: into) rescue nil
}
end
begin
- parse(*IO.readlines(filename).each {|s| s.chomp!})
+ parse(*File.readlines(filename, chomp: true), into: into)
true
rescue Errno::ENOENT, Errno::ENOTDIR
false
@@ -2001,10 +2084,23 @@ XXX
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?
+ case o = o.delete("imx")
+ when ""
+ when "u"
+ s = s.encode(Encoding::UTF_8)
+ when "e"
+ s = s.encode(Encoding::EUC_JP)
+ when "s"
+ s = s.encode(Encoding::SJIS)
+ when "n"
+ f |= Regexp::NOENCODING
+ else
+ raise OptionParser::InvalidArgument, "unknown regexp option - #{o}"
+ end
+ else
+ s ||= all
end
- Regexp.new(s || all, f, k)
+ Regexp.new(s, f)
end
#
diff --git a/lib/optparse/ac.rb b/lib/optparse/ac.rb
index 9d520101aa..0953725e46 100644
--- a/lib/optparse/ac.rb
+++ b/lib/optparse/ac.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: false
-require 'optparse'
+require_relative '../optparse'
class OptionParser::AC < OptionParser
private
diff --git a/lib/optparse/date.rb b/lib/optparse/date.rb
index d6649c83f1..7bbf12b77f 100644
--- a/lib/optparse/date.rb
+++ b/lib/optparse/date.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: false
-require 'optparse'
+require_relative '../optparse'
require 'date'
OptionParser.accept(DateTime) do |s,|
diff --git a/lib/optparse/kwargs.rb b/lib/optparse/kwargs.rb
index ccf20c65e9..992aca467e 100644
--- a/lib/optparse/kwargs.rb
+++ b/lib/optparse/kwargs.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'optparse'
+require_relative '../optparse'
class OptionParser
# :call-seq:
diff --git a/lib/optparse/optparse.gemspec b/lib/optparse/optparse.gemspec
index ae6596678c..a4287ddeee 100644
--- a/lib/optparse/optparse.gemspec
+++ b/lib/optparse/optparse.gemspec
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
spec.metadata["source_code_uri"] = spec.homepage
spec.files = Dir["{doc,lib,misc}/**/*"] + %w[README.md ChangeLog COPYING]
+ spec.rdoc_options = ["--main=README.md", "--op=rdoc", "--page-dir=doc"]
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
diff --git a/lib/optparse/shellwords.rb b/lib/optparse/shellwords.rb
index bf31701b96..4feb1993d9 100644
--- a/lib/optparse/shellwords.rb
+++ b/lib/optparse/shellwords.rb
@@ -2,6 +2,6 @@
# -*- ruby -*-
require 'shellwords'
-require 'optparse'
+require_relative '../optparse'
OptionParser.accept(Shellwords) {|s,| Shellwords.shellwords(s)}
diff --git a/lib/optparse/time.rb b/lib/optparse/time.rb
index ffc6ff000d..0ce651f6f6 100644
--- a/lib/optparse/time.rb
+++ b/lib/optparse/time.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: false
-require 'optparse'
+require_relative '../optparse'
require 'time'
OptionParser.accept(Time) do |s,|
diff --git a/lib/optparse/uri.rb b/lib/optparse/uri.rb
index 51550cf91b..31d10593b1 100644
--- a/lib/optparse/uri.rb
+++ b/lib/optparse/uri.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
# -*- ruby -*-
-require 'optparse'
+require_relative '../optparse'
require 'uri'
OptionParser.accept(URI) {|s,| URI.parse(s) if s}
diff --git a/lib/ostruct.rb b/lib/ostruct.rb
index 1203d10e47..a08561d6c9 100644
--- a/lib/ostruct.rb
+++ b/lib/ostruct.rb
@@ -93,21 +93,21 @@
# 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 `!`:
+# To help remedy clashes, OpenStruct uses only protected/private methods ending with <code>!</code>
+# and defines aliases for builtin public methods by adding a <code>!</code>:
#
# o = OpenStruct.new(make: 'Bentley', class: :luxury)
# o.class # => :luxury
# o.class! # => OpenStruct
#
-# It is recommended (but not enforced) to not use fields ending in `!`;
+# It is recommended (but not enforced) to not use fields ending in <code>!</code>;
# Note that a subclass' methods may not be overwritten, nor can OpenStruct's own methods
-# ending with `!`.
+# ending with <code>!</code>.
#
# For all these reasons, consider not using OpenStruct at all.
#
class OpenStruct
- VERSION = "0.4.0"
+ VERSION = "0.5.5"
#
# Creates a new OpenStruct object. By default, the resulting OpenStruct
@@ -197,7 +197,7 @@ class OpenStruct
# data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]]
#
def each_pair
- return to_enum(__method__) { @table.size } unless block_given!
+ return to_enum(__method__) { @table.size } unless defined?(yield)
@table.each_pair{|p| yield p}
self
end
@@ -221,8 +221,17 @@ class OpenStruct
#
def new_ostruct_member!(name) # :nodoc:
unless @table.key?(name) || is_method_protected!(name)
- define_singleton_method!(name) { @table[name] }
- define_singleton_method!("#{name}=") {|x| @table[name] = x}
+ if defined?(::Ractor)
+ getter_proc = nil.instance_eval{ Proc.new { @table[name] } }
+ setter_proc = nil.instance_eval{ Proc.new {|x| @table[name] = x} }
+ ::Ractor.make_shareable(getter_proc)
+ ::Ractor.make_shareable(setter_proc)
+ else
+ getter_proc = Proc.new { @table[name] }
+ setter_proc = Proc.new {|x| @table[name] = x}
+ end
+ define_singleton_method!(name, &getter_proc)
+ define_singleton_method!("#{name}=", &setter_proc)
end
end
private :new_ostruct_member!
@@ -237,7 +246,7 @@ class OpenStruct
if owner.class == ::Class
owner < ::OpenStruct
else
- self.class.ancestors.any? do |mod|
+ self.class!.ancestors.any? do |mod|
return false if mod == ::OpenStruct
mod == owner
end
@@ -273,7 +282,7 @@ class OpenStruct
# :call-seq:
# ostruct[name] -> object
#
- # Returns the value of an attribute, or `nil` if there is no such 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)
@@ -308,7 +317,7 @@ class OpenStruct
# 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].
+ # See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
#
# Examples:
# require "ostruct"
@@ -347,14 +356,14 @@ class OpenStruct
#
# person.delete_field('number') { 8675_309 } # => 8675309
#
- def delete_field(name)
+ def delete_field(name, &block)
sym = name.to_sym
begin
singleton_class.remove_method(sym, "#{sym}=")
rescue NameError
end
@table.delete(sym) do
- return yield if block_given!
+ return yield if block
raise! NameError.new("no field `#{sym}' in #{self}", sym)
end
end
@@ -446,13 +455,23 @@ class OpenStruct
update_to_values!(h)
end
- # Make all public methods (builtin or our own) accessible with `!`:
- instance_methods.each do |method|
+ # Make all public methods (builtin or our own) accessible with <code>!</code>:
+ give_access = instance_methods
+ # See https://github.com/ruby/ostruct/issues/30
+ give_access -= %i[instance_exec instance_eval eval] if RUBY_ENGINE == 'jruby'
+ give_access.each do |method|
+ next if method.match(/\W$/)
+
new_name = "#{method}!"
alias_method new_name, method
end
# Other builtin private methods we use:
alias_method :raise!, :raise
- alias_method :block_given!, :block_given?
- private :raise!, :block_given!
+ private :raise!
+
+ # See https://github.com/ruby/ostruct/issues/40
+ if RUBY_ENGINE != 'jruby'
+ alias_method :block_given!, :block_given?
+ private :block_given!
+ end
end
diff --git a/lib/ostruct/ostruct.gemspec b/lib/ostruct/ostruct.gemspec
index f69a858aa2..31ecc312c3 100644
--- a/lib/ostruct/ostruct.gemspec
+++ b/lib/ostruct/ostruct.gemspec
@@ -20,8 +20,6 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.5.0"
spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "ostruct.gemspec"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler"
diff --git a/lib/pp.gemspec b/lib/pp.gemspec
index 4d2400c31c..3f08f400c4 100644
--- a/lib/pp.gemspec
+++ b/lib/pp.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "pp"
- spec.version = "0.2.0"
+ spec.version = "0.4.0"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/pp.rb b/lib/pp.rb
index 72480e5304..81551aa116 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -61,14 +61,34 @@ require 'prettyprint'
# Tanaka Akira <akr@fsij.org>
class PP < PrettyPrint
+ # Returns the usable width for +out+.
+ # As the width of +out+:
+ # 1. If +out+ is assigned to a tty device, its width is used.
+ # 2. Otherwise, or it could not get the value, the +COLUMN+
+ # environment variable is assumed to be set to the width.
+ # 3. If +COLUMN+ is not set to a non-zero number, 80 is assumed.
+ #
+ # And finally, returns the above width value - 1.
+ # * This -1 is for Windows command prompt, which moves the cursor to
+ # the next line if it reaches the last column.
+ def PP.width_for(out)
+ begin
+ require 'io/console'
+ _, width = out.winsize
+ rescue LoadError, NoMethodError, SystemCallError
+ end
+ (width || ENV['COLUMNS']&.to_i&.nonzero? || 80) - 1
+ end
+
# Outputs +obj+ to +out+ in pretty printed format of
# +width+ columns in width.
#
# If +out+ is omitted, <code>$></code> is assumed.
- # If +width+ is omitted, 79 is assumed.
+ # If +width+ is omitted, the width of +out+ is assumed (see
+ # width_for).
#
# PP.pp returns +out+.
- def PP.pp(obj, out=$>, width=79)
+ def PP.pp(obj, out=$>, width=width_for(out))
q = PP.new(out, width)
q.guard_inspect_key {q.pp obj}
q.flush
@@ -396,6 +416,26 @@ class Struct # :nodoc:
end
end
+class Data # :nodoc:
+ def pretty_print(q) # :nodoc:
+ q.group(1, sprintf("#<data %s", PP.mcall(self, Kernel, :class).name), '>') {
+ q.seplist(PP.mcall(self, Data, :members), lambda { q.text "," }) {|member|
+ q.breakable
+ q.text member.to_s
+ q.text '='
+ q.group(1) {
+ q.breakable ''
+ q.pp public_send(member)
+ }
+ }
+ }
+ end
+
+ def pretty_print_cycle(q) # :nodoc:
+ q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
+ end
+end if "3.2" <= RUBY_VERSION
+
class Range # :nodoc:
def pretty_print(q) # :nodoc:
q.pp self.begin
@@ -424,7 +464,7 @@ end
class File < IO # :nodoc:
class Stat # :nodoc:
def pretty_print(q) # :nodoc:
- require 'etc.so'
+ require 'etc'
q.object_group(self) {
q.breakable
q.text sprintf("dev=0x%x", self.dev); q.comma_breakable
@@ -530,37 +570,39 @@ class MatchData # :nodoc:
end
end
-class RubyVM::AbstractSyntaxTree::Node
- def pretty_print_children(q, names = [])
- children.zip(names) do |c, n|
- if n
- q.breakable
- q.text "#{n}:"
- end
- q.group(2) do
- q.breakable
- q.pp c
+if defined?(RubyVM::AbstractSyntaxTree)
+ class RubyVM::AbstractSyntaxTree::Node
+ def pretty_print_children(q, names = [])
+ children.zip(names) do |c, n|
+ if n
+ q.breakable
+ q.text "#{n}:"
+ end
+ q.group(2) do
+ q.breakable
+ q.pp c
+ end
end
end
- end
- def pretty_print(q)
- q.group(1, "(#{type}@#{first_lineno}:#{first_column}-#{last_lineno}:#{last_column}", ")") {
- case type
- when :SCOPE
- pretty_print_children(q, %w"tbl args body")
- when :ARGS
- pretty_print_children(q, %w[pre_num pre_init opt first_post post_num post_init rest kw kwrest block])
- when :DEFN
- pretty_print_children(q, %w[mid body])
- when :ARYPTN
- pretty_print_children(q, %w[const pre rest post])
- when :HSHPTN
- pretty_print_children(q, %w[const kw kwrest])
- else
- pretty_print_children(q)
- end
- }
+ def pretty_print(q)
+ q.group(1, "(#{type}@#{first_lineno}:#{first_column}-#{last_lineno}:#{last_column}", ")") {
+ case type
+ when :SCOPE
+ pretty_print_children(q, %w"tbl args body")
+ when :ARGS
+ pretty_print_children(q, %w[pre_num pre_init opt first_post post_num post_init rest kw kwrest block])
+ when :DEFN
+ pretty_print_children(q, %w[mid body])
+ when :ARYPTN
+ pretty_print_children(q, %w[const pre rest post])
+ when :HSHPTN
+ pretty_print_children(q, %w[const kw kwrest])
+ else
+ pretty_print_children(q)
+ end
+ }
+ end
end
end
diff --git a/lib/prettyprint.gemspec b/lib/prettyprint.gemspec
index 169267fb16..eae2227d60 100644
--- a/lib/prettyprint.gemspec
+++ b/lib/prettyprint.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "prettyprint"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/pstore.rb b/lib/pstore.rb
index a46bcb84bc..72deaa1017 100644
--- a/lib/pstore.rb
+++ b/lib/pstore.rb
@@ -10,89 +10,323 @@
require "digest"
-#
-# PStore implements a file based persistence mechanism based on a Hash. User
-# code can store hierarchies of Ruby objects (values) into the data store file
-# by name (keys). An object hierarchy may be just a single object. User code
-# may later read values back from the data store or even update data, as needed.
+# \PStore implements a file based persistence mechanism based on a Hash.
+# User code can store hierarchies of Ruby objects (values)
+# into the data store by name (keys).
+# An object hierarchy may be just a single object.
+# User code may later read values back from the data store
+# or even update data, as needed.
#
# The transactional behavior ensures that any changes succeed or fail together.
-# This can be used to ensure that the data store is not left in a transitory
-# state, where some values were updated but others were not.
+# This can be used to ensure that the data store is not left in a transitory state,
+# where some values were updated but others were not.
+#
+# Behind the scenes, Ruby objects are stored to the data store file with Marshal.
+# That carries the usual limitations. Proc objects cannot be marshalled,
+# for example.
+#
+# There are three important concepts here (details at the links):
+#
+# - {Store}[rdoc-ref:PStore@The+Store]: a store is an instance of \PStore.
+# - {Entries}[rdoc-ref:PStore@Entries]: the store is hash-like;
+# each entry is the key for a stored object.
+# - {Transactions}[rdoc-ref:PStore@Transactions]: each transaction is a collection
+# of prospective changes to the store;
+# a transaction is defined in the block given with a call
+# to PStore#transaction.
+#
+# == About the Examples
+#
+# Examples on this page need a store that has known properties.
+# They can get a new (and populated) store by calling thus:
+#
+# example_store do |store|
+# # Example code using store goes here.
+# end
+#
+# All we really need to know about +example_store+
+# is that it yields a fresh store with a known population of entries;
+# its implementation:
+#
+# require 'pstore'
+# require 'tempfile'
+# # Yield a pristine store for use in examples.
+# def example_store
+# # Create the store in a temporary file.
+# Tempfile.create do |file|
+# store = PStore.new(file)
+# # Populate the store.
+# store.transaction do
+# store[:foo] = 0
+# store[:bar] = 1
+# store[:baz] = 2
+# end
+# yield store
+# end
+# end
+#
+# == The Store
+#
+# The contents of the store are maintained in a file whose path is specified
+# when the store is created (see PStore.new).
+# The objects are stored and retrieved using
+# module Marshal, which means that certain objects cannot be added to the store;
+# see {Marshal::dump}[rdoc-ref:Marshal.dump].
+#
+# == Entries
+#
+# A store may have any number of entries.
+# Each entry has a key and a value, just as in a hash:
+#
+# - Key: as in a hash, the key can be (almost) any object;
+# see {Hash Keys}[rdoc-ref:Hash@Hash+Keys].
+# You may find it convenient to keep it simple by using only
+# symbols or strings as keys.
+# - Value: the value may be any object that can be marshalled by \Marshal
+# (see {Marshal::dump}[rdoc-ref:Marshal.dump])
+# and in fact may be a collection
+# (e.g., an array, a hash, a set, a range, etc).
+# That collection may in turn contain nested objects,
+# including collections, to any depth;
+# those objects must also be \Marshal-able.
+# See {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
+#
+# == Transactions
+#
+# === The Transaction Block
+#
+# The block given with a call to method #transaction#
+# contains a _transaction_,
+# which consists of calls to \PStore methods that
+# read from or write to the store
+# (that is, all \PStore methods except #transaction itself,
+# #path, and Pstore.new):
+#
+# example_store do |store|
+# store.transaction do
+# store.keys # => [:foo, :bar, :baz]
+# store[:bat] = 3
+# store.keys # => [:foo, :bar, :baz, :bat]
+# end
+# end
+#
+# Execution of the transaction is deferred until the block exits,
+# and is executed _atomically_ (all-or-nothing):
+# either all transaction calls are executed, or none are.
+# This maintains the integrity of the store.
+#
+# Other code in the block (including even calls to #path and PStore.new)
+# is executed immediately, not deferred.
+#
+# The transaction block:
+#
+# - May not contain a nested call to #transaction.
+# - Is the only context where methods that read from or write to
+# the store are allowed.
+#
+# As seen above, changes in a transaction are made automatically
+# when the block exits.
+# The block may be exited early by calling method #commit or #abort.
+#
+# - Method #commit triggers the update to the store and exits the block:
+#
+# example_store do |store|
+# store.transaction do
+# store.keys # => [:foo, :bar, :baz]
+# store[:bat] = 3
+# store.commit
+# fail 'Cannot get here'
+# end
+# store.transaction do
+# # Update was completed.
+# store.keys # => [:foo, :bar, :baz, :bat]
+# end
+# end
+#
+# - Method #abort discards the update to the store and exits the block:
+#
+# example_store do |store|
+# store.transaction do
+# store.keys # => [:foo, :bar, :baz]
+# store[:bat] = 3
+# store.abort
+# fail 'Cannot get here'
+# end
+# store.transaction do
+# # Update was not completed.
+# store.keys # => [:foo, :bar, :baz]
+# end
+# end
+#
+# === Read-Only Transactions
+#
+# By default, a transaction allows both reading from and writing to
+# the store:
+#
+# store.transaction do
+# # Read-write transaction.
+# # Any code except a call to #transaction is allowed here.
+# end
+#
+# If argument +read_only+ is passed as +true+,
+# only reading is allowed:
+#
+# store.transaction(true) do
+# # Read-only transaction:
+# # Calls to #transaction, #[]=, and #delete are not allowed here.
+# end
+#
+# == Hierarchical Values
+#
+# The value for an entry may be a simple object (as seen above).
+# It may also be a hierarchy of objects nested to any depth:
+#
+# deep_store = PStore.new('deep.store')
+# deep_store.transaction do
+# array_of_hashes = [{}, {}, {}]
+# deep_store[:array_of_hashes] = array_of_hashes
+# deep_store[:array_of_hashes] # => [{}, {}, {}]
+# hash_of_arrays = {foo: [], bar: [], baz: []}
+# deep_store[:hash_of_arrays] = hash_of_arrays
+# deep_store[:hash_of_arrays] # => {:foo=>[], :bar=>[], :baz=>[]}
+# deep_store[:hash_of_arrays][:foo].push(:bat)
+# deep_store[:hash_of_arrays] # => {:foo=>[:bat], :bar=>[], :baz=>[]}
+# end
+#
+# And recall that you can use
+# {dig methods}[rdoc-ref:dig_methods.rdoc]
+# in a returned hierarchy of objects.
+#
+# == Working with the Store
+#
+# === Creating a Store
+#
+# Use method PStore.new to create a store.
+# The new store creates or opens its containing file:
+#
+# store = PStore.new('t.store')
+#
+# === Modifying the Store
+#
+# Use method #[]= to update or create an entry:
+#
+# example_store do |store|
+# store.transaction do
+# store[:foo] = 1 # Update.
+# store[:bam] = 1 # Create.
+# end
+# end
+#
+# Use method #delete to remove an entry:
+#
+# example_store do |store|
+# store.transaction do
+# store.delete(:foo)
+# store[:foo] # => nil
+# end
+# end
+#
+# === Retrieving Values
+#
+# Use method #fetch (allows default) or #[] (defaults to +nil+)
+# to retrieve an entry:
+#
+# example_store do |store|
+# store.transaction do
+# store[:foo] # => 0
+# store[:nope] # => nil
+# store.fetch(:baz) # => 2
+# store.fetch(:nope, nil) # => nil
+# store.fetch(:nope) # Raises exception.
+# end
+# end
+#
+# === Querying the Store
+#
+# Use method #key? to determine whether a given key exists:
#
-# Behind the scenes, Ruby objects are stored to the data store file with
-# Marshal. That carries the usual limitations. Proc objects cannot be
-# marshalled, for example.
+# example_store do |store|
+# store.transaction do
+# store.key?(:foo) # => true
+# end
+# end
#
-# == Usage example:
+# Use method #keys to retrieve keys:
+#
+# example_store do |store|
+# store.transaction do
+# store.keys # => [:foo, :bar, :baz]
+# end
+# end
+#
+# Use method #path to retrieve the path to the store's underlying file;
+# this method may be called from outside a transaction block:
+#
+# store = PStore.new('t.store')
+# store.path # => "t.store"
+#
+# == Transaction Safety
+#
+# For transaction safety, see:
+#
+# - Optional argument +thread_safe+ at method PStore.new.
+# - Attribute #ultra_safe.
+#
+# Needless to say, if you're storing valuable data with \PStore, then you should
+# backup the \PStore file from time to time.
+#
+# == An Example Store
#
# require "pstore"
#
-# # a mock wiki object...
+# # A mock wiki object.
# class WikiPage
-# def initialize( page_name, author, contents )
+#
+# attr_reader :page_name
+#
+# def initialize(page_name, author, contents)
# @page_name = page_name
# @revisions = Array.new
-#
# add_revision(author, contents)
# end
#
-# attr_reader :page_name
-#
-# def add_revision( author, contents )
-# @revisions << { :created => Time.now,
-# :author => author,
-# :contents => contents }
+# def add_revision(author, contents)
+# @revisions << {created: Time.now,
+# author: author,
+# contents: contents}
# end
#
# def wiki_page_references
# [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
# end
#
-# # ...
# end
#
-# # create a new page...
-# home_page = WikiPage.new( "HomePage", "James Edward Gray II",
-# "A page about the JoysOfDocumentation..." )
+# # Create a new wiki page.
+# home_page = WikiPage.new("HomePage", "James Edward Gray II",
+# "A page about the JoysOfDocumentation..." )
#
-# # then we want to update page data and the index together, or not at all...
# wiki = PStore.new("wiki_pages.pstore")
-# wiki.transaction do # begin transaction; do all of this or none of it
-# # store page...
+# # Update page data and the index together, or not at all.
+# wiki.transaction do
+# # Store page.
# wiki[home_page.page_name] = home_page
-# # ensure that an index has been created...
+# # Create page index.
# wiki[:wiki_index] ||= Array.new
-# # update wiki index...
+# # Update wiki index.
# wiki[:wiki_index].push(*home_page.wiki_page_references)
-# end # commit changes to wiki data store file
-#
-# ### Some time later... ###
+# end
#
-# # read wiki data...
-# wiki.transaction(true) do # begin read-only transaction, no changes allowed
-# wiki.roots.each do |data_root_name|
-# p data_root_name
-# p wiki[data_root_name]
+# # Read wiki data, setting argument read_only to true.
+# wiki.transaction(true) do
+# wiki.keys.each do |key|
+# puts key
+# puts wiki[key]
# end
# end
#
-# == Transaction modes
-#
-# By default, file integrity is only ensured as long as the operating system
-# (and the underlying hardware) doesn't raise any unexpected I/O errors. If an
-# I/O error occurs while PStore is writing to its file, then the file will
-# become corrupted.
-#
-# You can prevent this by setting <em>pstore.ultra_safe = true</em>.
-# However, this results in a minor performance loss, and only works on platforms
-# that support atomic file renames. Please consult the documentation for
-# +ultra_safe+ for details.
-#
-# 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"
+ VERSION = "0.1.2"
RDWR_ACCESS = {mode: IO::RDWR | IO::CREAT | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
RD_ACCESS = {mode: IO::RDONLY | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
@@ -102,21 +336,38 @@ class PStore
class Error < StandardError
end
- # Whether PStore should do its best to prevent file corruptions, even when under
- # unlikely-to-occur error conditions such as out-of-space conditions and other
- # unusual OS filesystem errors. Setting this flag comes at the price in the form
- # of a performance loss.
+ # Whether \PStore should do its best to prevent file corruptions,
+ # even when an unlikely error (such as memory-error or filesystem error) occurs:
+ #
+ # - +true+: changes are posted by creating a temporary file,
+ # writing the updated data to it, then renaming the file to the given #path.
+ # File integrity is maintained.
+ # Note: has effect only if the filesystem has atomic file rename
+ # (as do POSIX platforms Linux, MacOS, FreeBSD and others).
+ #
+ # - +false+ (the default): changes are posted by rewinding the open file
+ # and writing the updated data.
+ # File integrity is maintained if the filesystem raises
+ # no unexpected I/O error;
+ # if such an error occurs during a write to the store,
+ # the file may become corrupted.
#
- # This flag only has effect on platforms on which file renames are atomic (e.g.
- # all POSIX platforms: Linux, MacOS X, FreeBSD, etc). The default value is false.
attr_accessor :ultra_safe
+ # Returns a new \PStore object.
#
- # To construct a PStore object, pass in the _file_ path where you would like
- # the data to be stored.
+ # Argument +file+ is the path to the file in which objects are to be stored;
+ # if the file exists, it should be one that was written by \PStore.
#
- # PStore objects are always reentrant. But if _thread_safe_ is set to true,
- # then it will become thread-safe at the cost of a minor performance hit.
+ # path = 't.store'
+ # store = PStore.new(path)
+ #
+ # A \PStore object is
+ # {reentrant}[https://en.wikipedia.org/wiki/Reentrancy_(computing)].
+ # If argument +thread_safe+ is given as +true+,
+ # the object is also thread-safe (at the cost of a small performance penalty):
+ #
+ # store = PStore.new(path, true)
#
def initialize(file, thread_safe = false)
dir = File::dirname(file)
@@ -147,169 +398,160 @@ class PStore
end
private :in_transaction, :in_transaction_wr
+ # Returns the value for the given +key+ if the key exists.
+ # +nil+ otherwise;
+ # if not +nil+, the returned value is an object or a hierarchy of objects:
+ #
+ # example_store do |store|
+ # store.transaction do
+ # store[:foo] # => 0
+ # store[:nope] # => nil
+ # end
+ # end
#
- # Retrieves a value from the PStore file data, by _name_. The hierarchy of
- # Ruby objects stored under that root _name_ will be returned.
+ # Returns +nil+ if there is no such key.
#
- # *WARNING*: This method is only valid in a PStore#transaction. It will
- # raise PStore::Error if called at any other time.
+ # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
#
- def [](name)
+ # Raises an exception if called outside a transaction block.
+ def [](key)
in_transaction
- @table[name]
+ @table[key]
end
+
+ # Like #[], except that it accepts a default value for the store.
+ # If the +key+ does not exist:
#
- # This method is just like PStore#[], save that you may also provide a
- # _default_ value for the object. In the event the specified _name_ is not
- # found in the data store, your _default_ will be returned instead. If you do
- # not specify a default, PStore::Error will be raised if the object is not
- # found.
+ # - Raises an exception if +default+ is +PStore::Error+.
+ # - Returns the value of +default+ otherwise:
#
- # *WARNING*: This method is only valid in a PStore#transaction. It will
- # raise PStore::Error if called at any other time.
+ # example_store do |store|
+ # store.transaction do
+ # store.fetch(:nope, nil) # => nil
+ # store.fetch(:nope) # Raises an exception.
+ # end
+ # end
#
- def fetch(name, default=PStore::Error)
+ # Raises an exception if called outside a transaction block.
+ def fetch(key, default=PStore::Error)
in_transaction
- unless @table.key? name
+ unless @table.key? key
if default == PStore::Error
- raise PStore::Error, format("undefined root name `%s'", name)
+ raise PStore::Error, format("undefined key `%s'", key)
else
return default
end
end
- @table[name]
+ @table[key]
end
+
+ # Creates or replaces the value for the given +key+:
#
- # Stores an individual Ruby object or a hierarchy of Ruby objects in the data
- # store file under the root _name_. Assigning to a _name_ already in the data
- # store clobbers the old data.
- #
- # == Example:
- #
- # require "pstore"
- #
- # store = PStore.new("data_file.pstore")
- # store.transaction do # begin transaction
- # # load some data into the store...
- # store[:single_object] = "My data..."
- # store[:obj_hierarchy] = { "Kev Jackson" => ["rational.rb", "pstore.rb"],
- # "James Gray" => ["erb.rb", "pstore.rb"] }
- # end # commit changes to data store file
+ # example_store do |store|
+ # temp.transaction do
+ # temp[:bat] = 3
+ # end
+ # end
#
- # *WARNING*: This method is only valid in a PStore#transaction and it cannot
- # be read-only. It will raise PStore::Error if called at any other time.
+ # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
#
- def []=(name, value)
+ # Raises an exception if called outside a transaction block.
+ def []=(key, value)
in_transaction_wr
- @table[name] = value
+ @table[key] = value
end
+
+ # Removes and returns the value at +key+ if it exists:
#
- # Removes an object hierarchy from the data store, by _name_.
+ # example_store do |store|
+ # store.transaction do
+ # store[:bat] = 3
+ # store.delete(:bat)
+ # end
+ # end
#
- # *WARNING*: This method is only valid in a PStore#transaction and it cannot
- # be read-only. It will raise PStore::Error if called at any other time.
+ # Returns +nil+ if there is no such key.
#
- def delete(name)
+ # Raises an exception if called outside a transaction block.
+ def delete(key)
in_transaction_wr
- @table.delete name
+ @table.delete key
end
+ # Returns an array of the existing keys:
#
- # Returns the names of all object hierarchies currently in the store.
+ # example_store do |store|
+ # store.transaction do
+ # store.keys # => [:foo, :bar, :baz]
+ # end
+ # end
#
- # *WARNING*: This method is only valid in a PStore#transaction. It will
- # raise PStore::Error if called at any other time.
+ # Raises an exception if called outside a transaction block.
#
- def roots
+ # PStore#roots is an alias for PStore#keys.
+ def keys
in_transaction
@table.keys
end
+ alias roots keys
+
+ # Returns +true+ if +key+ exists, +false+ otherwise:
#
- # Returns true if the supplied _name_ is currently in the data store.
+ # example_store do |store|
+ # store.transaction do
+ # store.key?(:foo) # => true
+ # end
+ # end
#
- # *WARNING*: This method is only valid in a PStore#transaction. It will
- # raise PStore::Error if called at any other time.
+ # Raises an exception if called outside a transaction block.
#
- def root?(name)
+ # PStore#root? is an alias for PStore#key?.
+ def key?(key)
in_transaction
- @table.key? name
+ @table.key? key
end
- # Returns the path to the data store file.
+ alias root? key?
+
+ # Returns the string file path used to create the store:
+ #
+ # store.path # => "flat.store"
+ #
def path
@filename
end
+ # Exits the current transaction block, committing any changes
+ # specified in the transaction block.
+ # See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting].
#
- # Ends the current PStore#transaction, committing any changes to the data
- # store immediately.
- #
- # == Example:
- #
- # require "pstore"
- #
- # store = PStore.new("data_file.pstore")
- # store.transaction do # begin transaction
- # # load some data into the store...
- # store[:one] = 1
- # store[:two] = 2
- #
- # store.commit # end transaction here, committing changes
- #
- # store[:three] = 3 # this change is never reached
- # end
- #
- # *WARNING*: This method is only valid in a PStore#transaction. It will
- # raise PStore::Error if called at any other time.
- #
+ # Raises an exception if called outside a transaction block.
def commit
in_transaction
@abort = false
throw :pstore_abort_transaction
end
+
+ # Exits the current transaction block, discarding any changes
+ # specified in the transaction block.
+ # See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting].
#
- # Ends the current PStore#transaction, discarding any changes to the data
- # store.
- #
- # == Example:
- #
- # require "pstore"
- #
- # store = PStore.new("data_file.pstore")
- # store.transaction do # begin transaction
- # store[:one] = 1 # this change is not applied, see below...
- # store[:two] = 2 # this change is not applied, see below...
- #
- # store.abort # end transaction here, discard all changes
- #
- # store[:three] = 3 # this change is never reached
- # end
- #
- # *WARNING*: This method is only valid in a PStore#transaction. It will
- # raise PStore::Error if called at any other time.
- #
+ # Raises an exception if called outside a transaction block.
def abort
in_transaction
@abort = true
throw :pstore_abort_transaction
end
+ # Opens a transaction block for the store.
+ # See {Transactions}[rdoc-ref:PStore@Transactions].
#
- # Opens a new transaction for the data store. Code executed inside a block
- # passed to this method may read and write data to and from the data store
- # file.
- #
- # At the end of the block, changes are committed to the data store
- # automatically. You may exit the transaction early with a call to either
- # PStore#commit or PStore#abort. See those methods for details about how
- # changes are handled. Raising an uncaught Exception in the block is
- # equivalent to calling PStore#abort.
- #
- # If _read_only_ is set to +true+, you will only be allowed to read from the
- # data store during the transaction and any attempts to change the data will
- # raise a PStore::Error.
+ # With argument +read_only+ as +false+, the block may both read from
+ # and write to the store.
#
- # Note that PStore does not support nested transactions.
+ # With argument +read_only+ as +true+, the block may not include calls
+ # to #transaction, #[]=, or #delete.
#
+ # Raises an exception if called within a transaction block.
def transaction(read_only = false) # :yields: pstore
value = nil
if !@thread_safe
diff --git a/lib/racc/grammar.rb b/lib/racc/grammar.rb
index 3444dfcce3..01c4c3df69 100644
--- a/lib/racc/grammar.rb
+++ b/lib/racc/grammar.rb
@@ -335,14 +335,14 @@ module Racc
if action
idbase = "#{type}@#{id}-#{@seqs[type] += 1}"
target = _wrap(idbase, "#{idbase}-core", action)
- _regist("#{idbase}-core", &block)
+ _register("#{idbase}-core", &block)
else
- target = _regist("#{type}@#{id}", &block)
+ target = _register("#{type}@#{id}", &block)
end
@grammar.intern(target)
end
- def _regist(target_name)
+ def _register(target_name)
target = target_name.intern
unless _added?(@grammar.intern(target))
yield(target).each_rule do |rule|
diff --git a/lib/racc/grammarfileparser.rb b/lib/racc/grammarfileparser.rb
index 419495113b..c7d1207f0b 100644
--- a/lib/racc/grammarfileparser.rb
+++ b/lib/racc/grammarfileparser.rb
@@ -260,9 +260,9 @@ module Racc
_, *blocks = *@scanner.epilogue.split(/^----/)
blocks.each do |block|
header, *body = block.lines.to_a
- label0, pathes = *header.sub(/\A-+/, '').split('=', 2)
+ label0, paths = *header.sub(/\A-+/, '').split('=', 2)
label = canonical_label(label0)
- (pathes ? pathes.strip.split(' ') : []).each do |path|
+ (paths ? paths.strip.split(' ') : []).each do |path|
add_user_code label, SourceText.new(File.read(path), path, 1)
end
add_user_code label, SourceText.new(body.join(''), @filename, line + 1)
diff --git a/lib/racc/info.rb b/lib/racc/info.rb
index f599b13cbb..37bff7edba 100644
--- a/lib/racc/info.rb
+++ b/lib/racc/info.rb
@@ -11,7 +11,7 @@
#++
module Racc
- VERSION = '1.5.2'
+ VERSION = '1.6.2'
Version = VERSION
Copyright = 'Copyright (c) 1999-2006 Minero Aoki'
end
diff --git a/lib/racc/parser-text.rb b/lib/racc/parser-text.rb
index 4188fa853d..0579f4ce9b 100644
--- a/lib/racc/parser-text.rb
+++ b/lib/racc/parser-text.rb
@@ -22,7 +22,7 @@ module Racc
class ParseError < StandardError; end
end
unless defined?(::ParseError)
- ParseError = Racc::ParseError
+ ParseError = Racc::ParseError # :nodoc:
end
# Racc is a LALR(1) parser generator.
diff --git a/lib/racc/parser.rb b/lib/racc/parser.rb
index 4237fb572c..078bfef3e9 100644
--- a/lib/racc/parser.rb
+++ b/lib/racc/parser.rb
@@ -20,7 +20,7 @@ module Racc
class ParseError < StandardError; end
end
unless defined?(::ParseError)
- ParseError = Racc::ParseError
+ ParseError = Racc::ParseError # :nodoc:
end
# Racc is a LALR(1) parser generator.
diff --git a/lib/racc/racc.gemspec b/lib/racc/racc.gemspec
index 20f38925a5..1095c8f47e 100644
--- a/lib/racc/racc.gemspec
+++ b/lib/racc/racc.gemspec
@@ -20,7 +20,7 @@ Racc is a LALR(1) parser generator.
DESC
s.authors = ["Minero Aoki", "Aaron Patterson"]
s.email = [nil, "aaron@tenderlovemaking.com"]
- s.homepage = "http://i.loveruby.net/en/projects/racc/"
+ s.homepage = "https://github.com/ruby/racc"
s.licenses = ["Ruby", "BSD-2-Clause"]
s.executables = ["racc"]
s.files = [
diff --git a/lib/racc/statetransitiontable.rb b/lib/racc/statetransitiontable.rb
index 4d54287258..d75fa1657a 100644
--- a/lib/racc/statetransitiontable.rb
+++ b/lib/racc/statetransitiontable.rb
@@ -216,7 +216,7 @@ module Racc
end
i = ii
end
- Regexp.compile(map, 'n')
+ Regexp.compile(map, Regexp::NOENCODING)
end
def set_table(entries, dummy, tbl, chk, ptr)
diff --git a/lib/random/formatter.rb b/lib/random/formatter.rb
new file mode 100644
index 0000000000..4dea61c16c
--- /dev/null
+++ b/lib/random/formatter.rb
@@ -0,0 +1,245 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: true
+
+# == \Random number formatter.
+#
+# Formats generated random numbers in many manners. When <tt>'random/formatter'</tt>
+# is required, several methods are added to empty core module <tt>Random::Formatter</tt>,
+# making them available as Random's instance and module methods.
+#
+# Standard library SecureRandom is also extended with the module, and the methods
+# described below are available as a module methods in it.
+#
+# === Examples
+#
+# Generate random hexadecimal strings:
+#
+# require 'random/formatter'
+#
+# prng = Random.new
+# prng.hex(10) #=> "52750b30ffbc7de3b362"
+# prng.hex(10) #=> "92b15d6c8dc4beb5f559"
+# prng.hex(13) #=> "39b290146bea6ce975c37cfc23"
+# # or just
+# Random.hex #=> "1aed0c631e41be7f77365415541052ee"
+#
+# Generate random base64 strings:
+#
+# prng.base64(10) #=> "EcmTPZwWRAozdA=="
+# prng.base64(10) #=> "KO1nIU+p9DKxGg=="
+# prng.base64(12) #=> "7kJSM/MzBJI+75j8"
+# Random.base64(4) #=> "bsQ3fQ=="
+#
+# Generate random binary strings:
+#
+# prng.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
+# prng.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
+# Random.random_bytes(6) #=> "\xA1\xE6Lr\xC43"
+#
+# Generate alphanumeric strings:
+#
+# prng.alphanumeric(10) #=> "S8baxMJnPl"
+# prng.alphanumeric(10) #=> "aOxAg8BAJe"
+# Random.alphanumeric #=> "TmP9OsJHJLtaZYhP"
+#
+# Generate UUIDs:
+#
+# prng.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
+# prng.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
+# Random.uuid #=> "f14e0271-de96-45cc-8911-8910292a42cd"
+#
+# All methods are available in the standard library SecureRandom, too:
+#
+# SecureRandom.hex #=> "05b45376a30c67238eb93b16499e50cf"
+
+module Random::Formatter
+
+ # Generate a random binary string.
+ #
+ # The argument _n_ specifies the length of the result string.
+ #
+ # If _n_ is not specified or is nil, 16 is assumed.
+ # It may be larger in future.
+ #
+ # The result may contain any byte: "\x00" - "\xff".
+ #
+ # require 'random/formatter'
+ #
+ # Random.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
+ # # or
+ # prng = Random.new
+ # prng.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
+ def random_bytes(n=nil)
+ n = n ? n.to_int : 16
+ gen_random(n)
+ end
+
+ # Generate a random hexadecimal string.
+ #
+ # The argument _n_ specifies the length, in bytes, of the random number to be generated.
+ # The length of the resulting hexadecimal string is twice of _n_.
+ #
+ # If _n_ is not specified or is nil, 16 is assumed.
+ # It may be larger in the future.
+ #
+ # The result may contain 0-9 and a-f.
+ #
+ # require 'random/formatter'
+ #
+ # Random.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"
+ # # or
+ # prng = Random.new
+ # prng.hex #=> "91dc3bfb4de5b11d029d376634589b61"
+ def hex(n=nil)
+ random_bytes(n).unpack1("H*")
+ end
+
+ # Generate a random base64 string.
+ #
+ # The argument _n_ specifies the length, in bytes, of the random number
+ # to be generated. The length of the result string is about 4/3 of _n_.
+ #
+ # If _n_ is not specified or is nil, 16 is assumed.
+ # It may be larger in the future.
+ #
+ # The result may contain A-Z, a-z, 0-9, "+", "/" and "=".
+ #
+ # require 'random/formatter'
+ #
+ # Random.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A=="
+ # # or
+ # prng = Random.new
+ # prng.base64 #=> "6BbW0pxO0YENxn38HMUbcQ=="
+ #
+ # See RFC 3548 for the definition of base64.
+ def base64(n=nil)
+ [random_bytes(n)].pack("m0")
+ end
+
+ # Generate a random URL-safe base64 string.
+ #
+ # The argument _n_ specifies the length, in bytes, of the random number
+ # to be generated. The length of the result string is about 4/3 of _n_.
+ #
+ # If _n_ is not specified or is nil, 16 is assumed.
+ # It may be larger in the future.
+ #
+ # The boolean argument _padding_ specifies the padding.
+ # If it is false or nil, padding is not generated.
+ # Otherwise padding is generated.
+ # By default, padding is not generated because "=" may be used as a URL delimiter.
+ #
+ # The result may contain A-Z, a-z, 0-9, "-" and "_".
+ # "=" is also used if _padding_ is true.
+ #
+ # require 'random/formatter'
+ #
+ # Random.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg"
+ # # or
+ # prng = Random.new
+ # prng.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
+ #
+ # prng.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
+ # prng.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg=="
+ #
+ # See RFC 3548 for the definition of URL-safe base64.
+ def urlsafe_base64(n=nil, padding=false)
+ s = [random_bytes(n)].pack("m0")
+ s.tr!("+/", "-_")
+ s.delete!("=") unless padding
+ s
+ end
+
+ # Generate a random v4 UUID (Universally Unique IDentifier).
+ #
+ # require 'random/formatter'
+ #
+ # Random.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
+ # Random.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
+ # # or
+ # prng = Random.new
+ # prng.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b"
+ #
+ # The version 4 UUID is purely random (except the version).
+ # It doesn't contain meaningful information such as MAC addresses, timestamps, etc.
+ #
+ # The result contains 122 random bits (15.25 random bytes).
+ #
+ # See RFC4122[https://datatracker.ietf.org/doc/html/rfc4122] for details of UUID.
+ #
+ def uuid
+ ary = random_bytes(16).unpack("NnnnnN")
+ ary[2] = (ary[2] & 0x0fff) | 0x4000
+ ary[3] = (ary[3] & 0x3fff) | 0x8000
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
+ end
+
+ private def gen_random(n)
+ self.bytes(n)
+ end
+
+ # Generate a string that randomly draws from a
+ # source array of characters.
+ #
+ # The argument _source_ specifies the array of characters from which
+ # to generate the string.
+ # The argument _n_ specifies the length, in characters, of the string to be
+ # generated.
+ #
+ # The result may contain whatever characters are in the source array.
+ #
+ # require 'random/formatter'
+ #
+ # prng.choose([*'l'..'r'], 16) #=> "lmrqpoonmmlqlron"
+ # prng.choose([*'0'..'9'], 5) #=> "27309"
+ private def choose(source, n)
+ size = source.size
+ m = 1
+ limit = size
+ while limit * size <= 0x100000000
+ limit *= size
+ m += 1
+ end
+ result = ''.dup
+ while m <= n
+ rs = random_number(limit)
+ is = rs.digits(size)
+ (m-is.length).times { is << 0 }
+ result << source.values_at(*is).join('')
+ n -= m
+ end
+ if 0 < n
+ rs = random_number(limit)
+ is = rs.digits(size)
+ if is.length < n
+ (n-is.length).times { is << 0 }
+ else
+ is.pop while n < is.length
+ end
+ result.concat source.values_at(*is).join('')
+ end
+ result
+ end
+
+ ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9']
+ # Generate a random alphanumeric string.
+ #
+ # The argument _n_ specifies the length, in characters, of the alphanumeric
+ # string to be generated.
+ #
+ # If _n_ is not specified or is nil, 16 is assumed.
+ # It may be larger in the future.
+ #
+ # The result may contain A-Z, a-z and 0-9.
+ #
+ # require 'random/formatter'
+ #
+ # Random.alphanumeric #=> "2BuBuLf3WfSKyQbR"
+ # # or
+ # prng = Random.new
+ # prng.alphanumeric(10) #=> "i6K93NdqiH"
+ def alphanumeric(n=nil)
+ n = 16 if n.nil?
+ choose(ALPHANUMERIC, n)
+ end
+end
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
index 2d3f8c1122..b62c22576d 100644
--- a/lib/rdoc.rb
+++ b/lib/rdoc.rb
@@ -62,7 +62,7 @@ module RDoc
class Error < RuntimeError; end
- require 'rdoc/version'
+ require_relative 'rdoc/version'
##
# Method visibilities
@@ -141,61 +141,61 @@ module RDoc
end
end
- autoload :RDoc, 'rdoc/rdoc'
+ autoload :RDoc, "#{__dir__}/rdoc/rdoc"
- autoload :CrossReference, 'rdoc/cross_reference'
- autoload :ERBIO, 'rdoc/erbio'
- autoload :ERBPartial, 'rdoc/erb_partial'
- autoload :Encoding, 'rdoc/encoding'
- autoload :Generator, 'rdoc/generator'
- autoload :Options, 'rdoc/options'
- autoload :Parser, 'rdoc/parser'
- autoload :Servlet, 'rdoc/servlet'
- autoload :RI, 'rdoc/ri'
- autoload :Stats, 'rdoc/stats'
- autoload :Store, 'rdoc/store'
- autoload :Task, 'rdoc/task'
- autoload :Text, 'rdoc/text'
+ autoload :CrossReference, "#{__dir__}/rdoc/cross_reference"
+ autoload :ERBIO, "#{__dir__}/rdoc/erbio"
+ autoload :ERBPartial, "#{__dir__}/rdoc/erb_partial"
+ autoload :Encoding, "#{__dir__}/rdoc/encoding"
+ autoload :Generator, "#{__dir__}/rdoc/generator"
+ autoload :Options, "#{__dir__}/rdoc/options"
+ autoload :Parser, "#{__dir__}/rdoc/parser"
+ autoload :Servlet, "#{__dir__}/rdoc/servlet"
+ autoload :RI, "#{__dir__}/rdoc/ri"
+ autoload :Stats, "#{__dir__}/rdoc/stats"
+ autoload :Store, "#{__dir__}/rdoc/store"
+ autoload :Task, "#{__dir__}/rdoc/task"
+ autoload :Text, "#{__dir__}/rdoc/text"
- autoload :Markdown, 'rdoc/markdown'
- autoload :Markup, 'rdoc/markup'
- autoload :RD, 'rdoc/rd'
- autoload :TomDoc, 'rdoc/tom_doc'
+ autoload :Markdown, "#{__dir__}/rdoc/markdown"
+ autoload :Markup, "#{__dir__}/rdoc/markup"
+ autoload :RD, "#{__dir__}/rdoc/rd"
+ autoload :TomDoc, "#{__dir__}/rdoc/tom_doc"
- autoload :KNOWN_CLASSES, 'rdoc/known_classes'
+ autoload :KNOWN_CLASSES, "#{__dir__}/rdoc/known_classes"
- autoload :TokenStream, 'rdoc/token_stream'
+ autoload :TokenStream, "#{__dir__}/rdoc/token_stream"
- autoload :Comment, 'rdoc/comment'
+ autoload :Comment, "#{__dir__}/rdoc/comment"
- require 'rdoc/i18n'
+ require_relative 'rdoc/i18n'
# code objects
#
# We represent the various high-level code constructs that appear in Ruby
# programs: classes, modules, methods, and so on.
- autoload :CodeObject, 'rdoc/code_object'
-
- autoload :Context, 'rdoc/context'
- autoload :TopLevel, 'rdoc/top_level'
-
- autoload :AnonClass, 'rdoc/anon_class'
- autoload :ClassModule, 'rdoc/class_module'
- autoload :NormalClass, 'rdoc/normal_class'
- autoload :NormalModule, 'rdoc/normal_module'
- autoload :SingleClass, 'rdoc/single_class'
-
- autoload :Alias, 'rdoc/alias'
- autoload :AnyMethod, 'rdoc/any_method'
- autoload :MethodAttr, 'rdoc/method_attr'
- autoload :GhostMethod, 'rdoc/ghost_method'
- autoload :MetaMethod, 'rdoc/meta_method'
- autoload :Attr, 'rdoc/attr'
-
- autoload :Constant, 'rdoc/constant'
- autoload :Mixin, 'rdoc/mixin'
- autoload :Include, 'rdoc/include'
- autoload :Extend, 'rdoc/extend'
- autoload :Require, 'rdoc/require'
+ autoload :CodeObject, "#{__dir__}/rdoc/code_object"
+
+ autoload :Context, "#{__dir__}/rdoc/context"
+ autoload :TopLevel, "#{__dir__}/rdoc/top_level"
+
+ autoload :AnonClass, "#{__dir__}/rdoc/anon_class"
+ autoload :ClassModule, "#{__dir__}/rdoc/class_module"
+ autoload :NormalClass, "#{__dir__}/rdoc/normal_class"
+ autoload :NormalModule, "#{__dir__}/rdoc/normal_module"
+ autoload :SingleClass, "#{__dir__}/rdoc/single_class"
+
+ autoload :Alias, "#{__dir__}/rdoc/alias"
+ autoload :AnyMethod, "#{__dir__}/rdoc/any_method"
+ autoload :MethodAttr, "#{__dir__}/rdoc/method_attr"
+ autoload :GhostMethod, "#{__dir__}/rdoc/ghost_method"
+ autoload :MetaMethod, "#{__dir__}/rdoc/meta_method"
+ autoload :Attr, "#{__dir__}/rdoc/attr"
+
+ autoload :Constant, "#{__dir__}/rdoc/constant"
+ autoload :Mixin, "#{__dir__}/rdoc/mixin"
+ autoload :Include, "#{__dir__}/rdoc/include"
+ autoload :Extend, "#{__dir__}/rdoc/extend"
+ autoload :Require, "#{__dir__}/rdoc/require"
end
diff --git a/lib/rdoc/Gemfile b/lib/rdoc/Gemfile
deleted file mode 100644
index f853aa9fe7..0000000000
--- a/lib/rdoc/Gemfile
+++ /dev/null
@@ -1,13 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec
-
-group :development do
- gem 'rake'
- gem 'racc', '> 1.4.10'
- gem 'kpeg', github: 'evanphx/kpeg'
- gem 'test-unit'
- gem 'minitest' # for test_rdoc_rubygems_hook.rb
- gem 'rubocop'
- gem 'gettext'
-end
diff --git a/lib/rdoc/Rakefile b/lib/rdoc/Rakefile
deleted file mode 100644
index 278972e3ed..0000000000
--- a/lib/rdoc/Rakefile
+++ /dev/null
@@ -1,107 +0,0 @@
-$:.unshift File.expand_path 'lib'
-require 'rdoc/task'
-require 'bundler/gem_tasks'
-require 'rake/testtask'
-
-task :docs => :generate
-task :test => [:normal_test, :rubygems_test]
-
-PARSER_FILES = %w[
- lib/rdoc/rd/block_parser.ry
- lib/rdoc/rd/inline_parser.ry
- lib/rdoc/markdown.kpeg
- lib/rdoc/markdown/literals.kpeg
-]
-
-$rdoc_rakefile = true
-
-task :default => :test
-
-RDoc::Task.new do |doc|
- doc.main = 'README.rdoc'
- doc.title = "rdoc #{RDoc::VERSION} Documentation"
- doc.rdoc_dir = 'html'
- doc.rdoc_files = FileList.new %w[lib/**/*.rb *.rdoc] - PARSER_FILES
-end
-
-task ghpages: :rdoc do
- `git checkout gh-pages`
- require "fileutils"
- FileUtils.rm_rf "/tmp/html"
- FileUtils.mv "html", "/tmp"
- FileUtils.rm_rf "*"
- FileUtils.cp_r Dir.glob("/tmp/html/*"), "."
-end
-
-Rake::TestTask.new(:normal_test) do |t|
- t.libs << "test/rdoc"
- t.verbose = true
- t.deps = :generate
- t.test_files = FileList["test/**/test_*.rb"].exclude("test/rdoc/test_rdoc_rubygems_hook.rb")
-end
-
-Rake::TestTask.new(:rubygems_test) do |t|
- t.libs << "test/rdoc"
- t.verbose = true
- t.deps = :generate
- t.pattern = "test/rdoc/test_rdoc_rubygems_hook.rb"
-end
-
-path = "pkg/#{Bundler::GemHelper.gemspec.full_name}"
-
-package_parser_files = PARSER_FILES.map do |parser_file|
- name = File.basename(parser_file, File.extname(parser_file))
- _path = File.dirname(parser_file)
- package_parser_file = "#{path}/#{name}.rb"
- parsed_file = "#{_path}/#{name}.rb"
-
- file package_parser_file => parsed_file # ensure copy runs before racc
-
- package_parser_file
-end
-
-parsed_files = PARSER_FILES.map do |parser_file|
- ext = File.extname(parser_file)
- parsed_file = "#{parser_file.chomp(ext)}.rb"
-
- file parsed_file => parser_file do |t|
- puts "Generating #{parsed_file}..."
- case ext
- when '.ry' # need racc
- racc = Gem.bin_path 'racc', 'racc'
- rb_file = parser_file.gsub(/\.ry\z/, ".rb")
- ruby "#{racc} -l -o #{rb_file} #{parser_file}"
- open(rb_file, 'r+') do |f|
- newtext = "# frozen_string_literal: true\n#{f.read}"
- f.rewind
- f.write newtext
- end
- when '.kpeg' # need kpeg
- kpeg = Gem.bin_path 'kpeg', 'kpeg'
- rb_file = parser_file.gsub(/\.kpeg\z/, ".rb")
- ruby "#{kpeg} -fsv -o #{rb_file} #{parser_file}"
- end
- end
-
- parsed_file
-end
-
-task "#{path}.gem" => package_parser_files
-desc "Generate all files used racc and kpeg"
-task :generate => parsed_files
-
-task :clean do
- parsed_files.each do |path|
- File.delete(path) if File.exist?(path)
- end
-end
-
-begin
- require 'rubocop/rake_task'
-rescue LoadError
-else
- RuboCop::RakeTask.new(:rubocop) do |t|
- t.options = [*parsed_files]
- end
- task :build => [:generate, "rubocop:auto_correct"]
-end
diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
index 562e68461c..051f946a10 100644
--- a/lib/rdoc/any_method.rb
+++ b/lib/rdoc/any_method.rb
@@ -26,6 +26,9 @@ class RDoc::AnyMethod < RDoc::MethodAttr
attr_accessor :c_function
+ # The section title of the method (if defined in a C file via +:category:+)
+ attr_accessor :section_title
+
# Parameters for this method
attr_accessor :params
@@ -347,15 +350,15 @@ class RDoc::AnyMethod < RDoc::MethodAttr
ignore << is_alias_for.name
ignore.concat is_alias_for.aliases.map(&:name)
end
- ignore.map! { |n| n =~ /\A\[/ ? n[0, 1] : n}
+ ignore.map! { |n| n =~ /\A\[/ ? /\[.*\]/ : n}
ignore.delete(method_name)
ignore = Regexp.union(ignore)
matching = entries.reject do |entry|
- entry =~ /^\w*\.?#{ignore}/ or
+ entry =~ /^\w*\.?#{ignore}[$\(\s]/ or
entry =~ /\s#{ignore}\s/
end
- matching.join "\n"
+ matching.empty? ? nil : matching.join("\n")
end
end
diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb
index 434a25ac7f..d5f2f920ad 100644
--- a/lib/rdoc/code_objects.rb
+++ b/lib/rdoc/code_objects.rb
@@ -2,5 +2,4 @@
# This file was used to load all the RDoc::CodeObject subclasses at once. Now
# autoload handles this.
-require 'rdoc'
-
+require_relative '../rdoc'
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
index b3caa53aa1..c6edfb473c 100644
--- a/lib/rdoc/context.rb
+++ b/lib/rdoc/context.rb
@@ -1,6 +1,4 @@
# frozen_string_literal: true
-require 'cgi'
-
##
# A Context is something that can hold modules, classes, methods, attributes,
# aliases, requires, and includes. Classes, modules, and files are all
@@ -1261,6 +1259,6 @@ class RDoc::Context < RDoc::CodeObject
klass
end
- autoload :Section, 'rdoc/context/section'
+ autoload :Section, "#{__dir__}/context/section"
end
diff --git a/lib/rdoc/context/section.rb b/lib/rdoc/context/section.rb
index 5fef4a9ffc..c316efe99f 100644
--- a/lib/rdoc/context/section.rb
+++ b/lib/rdoc/context/section.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
+require 'cgi/util'
+
##
# A section of documentation like:
#
diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb
index 99a64cd99a..319bbc02ac 100644
--- a/lib/rdoc/cross_reference.rb
+++ b/lib/rdoc/cross_reference.rb
@@ -1,4 +1,7 @@
# frozen_string_literal: true
+
+require_relative 'markup/attribute_manager' # for PROTECT_ATTR
+
##
# RDoc::CrossReference is a reusable way to create cross references for names.
@@ -15,11 +18,24 @@ class RDoc::CrossReference
CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
##
+ # Regular expression to match a single method argument.
+
+ METHOD_ARG_REGEXP_STR = '[\w.+*/=<>-]+'
+
+ ##
+ # Regular expression to match method arguments.
+
+ METHOD_ARGS_REGEXP_STR = /(?:\((?:#{METHOD_ARG_REGEXP_STR}(?:,\s*#{METHOD_ARG_REGEXP_STR})*)?\))?/.source
+
+ ##
# Regular expression to match method references.
#
# See CLASS_REGEXP_STR
- METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>|\+@|-@|-|\+|\*)(?:\([\w.+*/=<>-]*\))?'
+ METHOD_REGEXP_STR = /(
+ (?!\d)[\w#{RDoc::Markup::AttributeManager::PROTECT_ATTR}]+[!?=]?|
+ %|=(?:==?|~)|![=~]|\[\]=?|<(?:<|=>?)?|>[>=]?|[-+!]@?|\*\*?|[\/%\`|&^~]
+ )#{METHOD_ARGS_REGEXP_STR}/.source.delete("\n ").freeze
##
# Regular expressions matching text that should potentially have
@@ -34,12 +50,6 @@ class RDoc::CrossReference
# A::B::C.meth
#{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
- # Stand-alone method (preceded by a #)
- | \\?\##{METHOD_REGEXP_STR}
-
- # Stand-alone method (preceded by ::)
- | ::#{METHOD_REGEXP_STR}
-
# A::B::C
# The stuff after CLASS_REGEXP_STR is a
# nasty hack. CLASS_REGEXP_STR unfortunately matches
@@ -56,6 +66,12 @@ class RDoc::CrossReference
# marker.
| #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
+ # Stand-alone method (preceded by a #)
+ | \\?\##{METHOD_REGEXP_STR}
+
+ # Stand-alone method (preceded by ::)
+ | ::#{METHOD_REGEXP_STR}
+
# Things that look like filenames
# The key thing is that there must be at least
# one special character (period, slash, or
@@ -82,12 +98,12 @@ class RDoc::CrossReference
# A::B::C.meth
#{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
- # Stand-alone method
- | \\?#{METHOD_REGEXP_STR}
-
# A::B::C
| #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
+ # Stand-alone method
+ | \\?#{METHOD_REGEXP_STR}
+
# Things that look like filenames
| (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+
@@ -115,15 +131,8 @@ class RDoc::CrossReference
@seen = {}
end
- ##
- # Returns a reference to +name+.
- #
- # If the reference is found and +name+ is not documented +text+ will be
- # returned. If +name+ is escaped +name+ is returned. If +name+ is not
- # found +text+ is returned.
-
- def resolve name, text
- return @seen[name] if @seen.include? name
+ def resolve_method name
+ ref = nil
if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
type = $2
@@ -165,12 +174,27 @@ class RDoc::CrossReference
end
end
+ ref
+ end
+
+ ##
+ # Returns a reference to +name+.
+ #
+ # If the reference is found and +name+ is not documented +text+ will be
+ # returned. If +name+ is escaped +name+ is returned. If +name+ is not
+ # found +text+ is returned.
+
+ def resolve name, text
+ return @seen[name] if @seen.include? name
+
ref = case name
when /^\\(#{CLASS_REGEXP_STR})$/o then
@context.find_symbol $1
else
@context.find_symbol name
- end unless ref
+ end
+
+ ref = resolve_method name unless ref
# Try a page name
ref = @store.page name if not ref and name =~ /^[\w.]+$/
diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb
index 340dcbf7ae..a769cf8ac0 100644
--- a/lib/rdoc/generator.rb
+++ b/lib/rdoc/generator.rb
@@ -41,11 +41,11 @@
module RDoc::Generator
- autoload :Markup, 'rdoc/generator/markup'
+ autoload :Markup, "#{__dir__}/generator/markup"
- autoload :Darkfish, 'rdoc/generator/darkfish'
- autoload :JsonIndex, 'rdoc/generator/json_index'
- autoload :RI, 'rdoc/generator/ri'
- autoload :POT, 'rdoc/generator/pot'
+ autoload :Darkfish, "#{__dir__}/generator/darkfish"
+ autoload :JsonIndex, "#{__dir__}/generator/json_index"
+ autoload :RI, "#{__dir__}/generator/ri"
+ autoload :POT, "#{__dir__}/generator/pot"
end
diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb
index b46861d009..60e0265e8c 100644
--- a/lib/rdoc/generator/darkfish.rb
+++ b/lib/rdoc/generator/darkfish.rb
@@ -220,8 +220,8 @@ class RDoc::Generator::Darkfish
install_rdoc_static_file @template_dir + item, "./#{item}", options
end
- @options.template_stylesheets.each do |stylesheet|
- FileUtils.cp stylesheet, '.', options
+ unless @options.template_stylesheets.empty?
+ FileUtils.cp @options.template_stylesheets, '.', **options
end
Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path|
diff --git a/lib/rdoc/generator/markup.rb b/lib/rdoc/generator/markup.rb
index 41e132450d..b54265717c 100644
--- a/lib/rdoc/generator/markup.rb
+++ b/lib/rdoc/generator/markup.rb
@@ -109,7 +109,7 @@ class RDoc::MethodAttr
lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment
lines.each do |line|
if line =~ /^ *(?=\S)/
- n = $&.length
+ n = $~.end(0)
indent = n if n < indent
break if n == 0
end
diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml
index e61fce1b9a..d5aed3e9ef 100644
--- a/lib/rdoc/generator/template/darkfish/_head.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_head.rhtml
@@ -3,20 +3,18 @@
<title><%= h @title %></title>
<script type="text/javascript">
- var rdoc_rel_prefix = "<%= asset_rel_prefix %>/";
- var index_rel_prefix = "<%= rel_prefix %>/";
+ var rdoc_rel_prefix = "<%= h asset_rel_prefix %>/";
+ var index_rel_prefix = "<%= h rel_prefix %>/";
</script>
-<script src="<%= asset_rel_prefix %>/js/navigation.js" defer></script>
-<script src="<%= asset_rel_prefix %>/js/search.js" defer></script>
-<script src="<%= asset_rel_prefix %>/js/search_index.js" defer></script>
-<script src="<%= asset_rel_prefix %>/js/searcher.js" defer></script>
-<script src="<%= asset_rel_prefix %>/js/darkfish.js" defer></script>
+<script src="<%= h asset_rel_prefix %>/js/navigation.js" defer></script>
+<script src="<%= h asset_rel_prefix %>/js/search.js" defer></script>
+<script src="<%= h asset_rel_prefix %>/js/search_index.js" defer></script>
+<script src="<%= h asset_rel_prefix %>/js/searcher.js" defer></script>
+<script src="<%= h asset_rel_prefix %>/js/darkfish.js" defer></script>
-<link href="<%= 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| -%>
-<link href="<%= asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet">
-<%- end -%>
+<link href="<%= h asset_rel_prefix %>/css/fonts.css" rel="stylesheet">
+<link href="<%= h asset_rel_prefix %>/css/rdoc.css" rel="stylesheet">
+<%- @options.template_stylesheets.each do |stylesheet| -%>
+<link href="<%= h asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet">
<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
index 530f25c762..d3d8da4017 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
@@ -1,9 +1,33 @@
<div id="classindex-section" class="nav-section">
<h3>Class and Module Index</h3>
+ <%-
+ all_classes = @classes.group_by do |klass|
+ klass.full_name[/\A[^:]++(?:::[^:]++(?=::))*+(?=::[^:]*+\z)/]
+ end.delete_if do |_, klasses|
+ !klasses.any?(&:display?)
+ end
+ link = proc do |index_klass, display = index_klass.display?|
+ if display
+ -%><code><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.name %></a></code><%-
+ else
+ -%><code><%= index_klass.name %></code><%-
+ end
+ end
+ if top = all_classes[nil]
+ solo = top.one? {|klass| klass.display?}
+ traverse = proc do |klasses| -%>
<ul class="link-list">
- <%- @modsort.each do |index_klass| -%>
- <li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a>
+ <%- klasses.each do |index_klass| -%>
+ <%- if children = all_classes[index_klass.full_name] -%>
+ <li><details<% if solo; solo = false %> open<% end %>><summary><% link.call(index_klass) %></summary>
+ <%- traverse.call(children) -%>
+ </ul></details>
+ <%- elsif index_klass.display? -%>
+ <li><% link.call(index_klass, true) %>
+ <%- end -%>
+ <%- end -%>
+ <%- end -%>
+ <%- traverse.call(top) -%>
<%- end -%>
- </ul>
</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
index 8ec83abda2..3f68f0c0dc 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
@@ -1,11 +1,31 @@
<%- simple_files = @files.select { |f| f.text? } %>
+<%- if defined?(current) -%>
+ <%- dir = current.full_name[%r{\A[^/]+(?=/)}] || current.page_name -%>
+<%- end -%>
<%- unless simple_files.empty? then -%>
<div id="fileindex-section" class="nav-section">
<h3>Pages</h3>
<ul class="link-list">
- <%- simple_files.each do |f| -%>
- <li><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.page_name %></a>
+ <%- simple_files.group_by do |f| -%>
+ <%- f.full_name[%r{\A[^/]+(?=/)}] || f.page_name -%>
+ <%- end.each do |n, files| -%>
+ <%- f = files.shift -%>
+ <%- if files.empty? -%>
+ <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a>
+ <%- next -%>
+ <%- end -%>
+ <li><details<% if dir == n %> open<% end %>><summary><%
+ if n == f.page_name
+ %><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h n %></a><%
+ else
+ %><%= h n %><% files.unshift(f)
+ end %></summary>
+ <ul class="link-list">
+ <%- files.each do |f| -%>
+ <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a>
+ <%- end -%>
+ </ul></details>
<%- end -%>
</ul>
</div>
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 bf70819f64..b1e047b5f7 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
@@ -3,16 +3,37 @@
else
current.comment
end
- table = current.parse(comment).table_of_contents
+ table = current.parse(comment).table_of_contents.dup
if table.length > 1 then %>
<div class="nav-section">
<h3>Table of Contents</h3>
+ <%- display_link = proc do |heading| -%>
+ <a href="#<%= heading.label current %>"><%= heading.plain_html %></a>
+ <%- end -%>
+
+ <%- list_siblings = proc do -%>
+ <%- level = table.first&.level -%>
+ <%- while table.first && table.first.level >= level -%>
+ <%- heading = table.shift -%>
+ <%- if table.first.nil? || table.first.level <= heading.level -%>
+ <li><% display_link.call heading -%>
+ <%- else -%>
+ <li>
+ <details open>
+ <summary><%- display_link.call heading -%></summary>
+ <ul class="link-list" role="directory">
+ <% list_siblings.call %>
+ </ul>
+ </details>
+ </li>
+ <%- end -%>
+ <%- end -%>
+ <%- end -%>
+
<ul class="link-list" role="directory">
-<%- table.each do |heading| -%>
- <li><a href="#<%= heading.label current %>"><%= heading.plain_html %></a>
-<%- end -%>
+ <% list_siblings.call %>
</ul>
</div>
<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml
index 5d7b6a1b80..97d175dddc 100644
--- a/lib/rdoc/generator/template/darkfish/class.rhtml
+++ b/lib/rdoc/generator/template/darkfish/class.rhtml
@@ -98,28 +98,30 @@
<%- methods.each do |method| -%>
<div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
- <%- if (call_seq = method.call_seq) then -%>
- <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%>
- <div class="method-heading">
- <span class="method-callseq">
- <%= h(call_seq.strip.
- gsub( /^\w+\./m, '')).
- gsub(/(.*)[-=]&gt;/, '\1&rarr;') %>
- </span>
- <%- if i == 0 and method.token_stream then -%>
- <span class="method-click-advice">click to toggle source</span>
- <%- end -%>
- </div>
- <%- end -%>
- <%- else -%>
- <div class="method-heading">
- <span class="method-name"><%= h method.name %></span><span
- class="method-args"><%= h method.param_seq %></span>
- <%- if method.token_stream then -%>
- <span class="method-click-advice">click to toggle source</span>
+ <div class="method-header">
+ <%- if (call_seq = method.call_seq) then -%>
+ <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%>
+ <div class="method-heading">
+ <span class="method-callseq">
+ <%= h(call_seq.strip.
+ gsub( /^\w+\./m, '')).
+ gsub(/(.*)[-=]&gt;/, '\1&rarr;') %>
+ </span>
+ <%- if i == 0 and method.token_stream then -%>
+ <span class="method-click-advice">click to toggle source</span>
+ <%- end -%>
+ </div>
+ <%- end -%>
+ <%- else -%>
+ <div class="method-heading">
+ <span class="method-name"><%= h method.name %></span><span
+ class="method-args"><%= h method.param_seq %></span>
+ <%- if method.token_stream then -%>
+ <span class="method-click-advice">click to toggle source</span>
+ <%- end -%>
+ </div>
<%- end -%>
</div>
- <%- end -%>
<div class="method-description">
<%- if method.comment then -%>
diff --git a/lib/rdoc/generator/template/darkfish/css/rdoc.css b/lib/rdoc/generator/template/darkfish/css/rdoc.css
index ebe2e93af6..1be815f503 100644
--- a/lib/rdoc/generator/template/darkfish/css/rdoc.css
+++ b/lib/rdoc/generator/template/darkfish/css/rdoc.css
@@ -186,6 +186,10 @@ nav {
font-family: Helvetica, sans-serif;
font-size: 14px;
border-right: 1px solid #ccc;
+ position: sticky;
+ top: 0;
+ overflow: auto;
+ height: calc(100vh - 100px); /* reduce the footer height */
}
main {
@@ -305,6 +309,25 @@ dl.note-list dt {
background: url(../images/arrow_up.png) no-repeat right center;
}
+.nav-section details summary {
+ display: block;
+}
+
+.nav-section details summary::-webkit-details-marker {
+ display: none;
+}
+
+.nav-section details summary:before {
+ content: "";
+}
+
+.nav-section details summary:after {
+ content: " \25B6"; /* BLACK RIGHT-POINTING TRIANGLE */
+}
+.nav-section details[open] > summary:after {
+ content: " \25BD"; /* WHITE DOWN-POINTING TRIANGLE */
+}
+
/* @end */
/* @group Documentation Section */
@@ -482,7 +505,7 @@ main header h3 {
main .method-source-code {
max-height: 0;
- overflow: hidden;
+ overflow: auto;
transition-duration: 200ms;
transition-delay: 0ms;
transition-property: all;
diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
index 61e3090c1c..dd00982d49 100644
--- a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
+++ b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
index 85686d967d..1decfb95af 100644
--- a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
+++ b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/index.rhtml b/lib/rdoc/generator/template/darkfish/index.rhtml
index 13fa3dcc7f..423e225b68 100644
--- a/lib/rdoc/generator/template/darkfish/index.rhtml
+++ b/lib/rdoc/generator/template/darkfish/index.rhtml
@@ -17,6 +17,6 @@
main_page = @files.find { |f| f.full_name == @options.main_page } then %>
<%= main_page.description %>
<%- else -%>
-<p>This is the API documentation for <%= @title %>.
+<p>This is the API documentation for <%= h @title %>.
<%- end -%>
</main>
diff --git a/lib/rdoc/generator/template/darkfish/js/darkfish.js b/lib/rdoc/generator/template/darkfish/js/darkfish.js
index 111bbf8eb9..d0c9467751 100644
--- a/lib/rdoc/generator/template/darkfish/js/darkfish.js
+++ b/lib/rdoc/generator/template/darkfish/js/darkfish.js
@@ -54,7 +54,7 @@ function hookSearch() {
var html = '';
// TODO add relative path to <script> per-page
- html += '<p class="search-match"><a href="' + index_rel_prefix + result.path + '">' + this.hlt(result.title);
+ html += '<p class="search-match"><a href="' + index_rel_prefix + this.escapeHTML(result.path) + '">' + this.hlt(result.title);
if (result.params)
html += '<span class="params">' + result.params + '</span>';
html += '</a>';
diff --git a/lib/rdoc/generator/template/darkfish/js/search.js b/lib/rdoc/generator/template/darkfish/js/search.js
index b558ca5b4f..58e52afecf 100644
--- a/lib/rdoc/generator/template/darkfish/js/search.js
+++ b/lib/rdoc/generator/template/darkfish/js/search.js
@@ -101,7 +101,7 @@ Search.prototype = Object.assign({}, Navigation, new function() {
}
this.escapeHTML = function(html) {
- return html.replace(/[&<>]/g, function(c) {
+ return html.replace(/[&<>"`']/g, function(c) {
return '&#' + c.charCodeAt(0) + ';';
});
}
diff --git a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
index 303d7016cc..941ff9d630 100644
--- a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
+++ b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
@@ -8,14 +8,14 @@
<ul>
<%- simple_files.sort.each do |file| -%>
<li class="file">
- <a href="<%= file.path %>"><%= h file.page_name %></a>
+ <a href="<%= h file.path %>"><%= h file.page_name %></a>
<%
# HACK table_of_contents should not exist on Document
table = file.parse(file.comment).table_of_contents
unless table.empty? then %>
<ul>
<%- table.each do |heading| -%>
- <li><a href="<%= file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a>
+ <li><a href="<%= h file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a>
<%- end -%>
</ul>
<%- end -%>
diff --git a/lib/rdoc/i18n.rb b/lib/rdoc/i18n.rb
index a32fd848a0..f209a9a6f6 100644
--- a/lib/rdoc/i18n.rb
+++ b/lib/rdoc/i18n.rb
@@ -4,7 +4,7 @@
module RDoc::I18n
- autoload :Locale, 'rdoc/i18n/locale'
+ autoload :Locale, "#{__dir__}/i18n/locale"
require_relative 'i18n/text'
end
diff --git a/lib/rdoc/known_classes.rb b/lib/rdoc/known_classes.rb
index 4d7f4aa995..3e8752bbde 100644
--- a/lib/rdoc/known_classes.rb
+++ b/lib/rdoc/known_classes.rb
@@ -25,6 +25,7 @@ module RDoc
"rb_cObject" => "Object",
"rb_cProc" => "Proc",
"rb_cRange" => "Range",
+ "rb_cRefinement" => "Refinement",
"rb_cRegexp" => "Regexp",
"rb_cRubyVM" => "RubyVM",
"rb_cSocket" => "Socket",
@@ -35,7 +36,7 @@ module RDoc
"rb_cTime" => "Time",
"rb_cTrueClass" => "TrueClass",
- "rb_eArgError" => "ArgError",
+ "rb_eArgError" => "ArgumentError",
"rb_eEOFError" => "EOFError",
"rb_eException" => "Exception",
"rb_eFatal" => "fatal",
@@ -45,8 +46,8 @@ module RDoc
"rb_eInterrupt" => "Interrupt",
"rb_eLoadError" => "LoadError",
"rb_eNameError" => "NameError",
- "rb_eNoMemError" => "NoMemError",
- "rb_eNotImpError" => "NotImpError",
+ "rb_eNoMemError" => "NoMemoryError",
+ "rb_eNotImpError" => "NotImplementedError",
"rb_eRangeError" => "RangeError",
"rb_eRuntimeError" => "RuntimeError",
"rb_eScriptError" => "ScriptError",
@@ -57,7 +58,7 @@ module RDoc
"rb_eSystemCallError" => "SystemCallError",
"rb_eSystemExit" => "SystemExit",
"rb_eTypeError" => "TypeError",
- "rb_eZeroDivError" => "ZeroDivError",
+ "rb_eZeroDivError" => "ZeroDivisionError",
"rb_mComparable" => "Comparable",
"rb_mEnumerable" => "Enumerable",
diff --git a/lib/rdoc/markdown.rb b/lib/rdoc/markdown.rb
index 3442f76b1b..a0709b6352 100644
--- a/lib/rdoc/markdown.rb
+++ b/lib/rdoc/markdown.rb
@@ -199,6 +199,7 @@ class RDoc::Markdown
@result = nil
@failed_rule = nil
@failing_rule_offset = -1
+ @line_offsets = nil
setup_foreign_grammar
end
@@ -208,30 +209,75 @@ class RDoc::Markdown
attr_accessor :result, :pos
def current_column(target=pos)
- if c = string.rindex("\n", target-1)
- return target - c - 1
+ if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1)
+ return target - c
+ elsif c = string.rindex("\n", target)
+ return target - c
end
target + 1
end
- def current_line(target=pos)
- cur_offset = 0
- cur_line = 0
+ def position_line_offsets
+ unless @position_line_offsets
+ @position_line_offsets = []
+ total = 0
+ string.each_line do |line|
+ total += line.size
+ @position_line_offsets << total
+ end
+ end
+ @position_line_offsets
+ end
+
+ if [].respond_to? :bsearch_index
+ def current_line(target=pos)
+ if line = position_line_offsets.bsearch_index {|x| x > target }
+ return line + 1
+ end
+ raise "Target position #{target} is outside of string"
+ end
+ else
+ def current_line(target=pos)
+ if line = position_line_offsets.index {|x| x > target }
+ return line + 1
+ end
- string.each_line do |line|
- cur_line += 1
- cur_offset += line.size
- return cur_line if cur_offset >= target
+ raise "Target position #{target} is outside of string"
end
+ end
- -1
+ def current_character(target=pos)
+ if target < 0 || target >= string.size
+ raise "Target position #{target} is outside of string"
+ end
+ string[target, 1]
+ end
+
+ KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char)
+
+ def current_pos_info(target=pos)
+ l = current_line target
+ c = current_column target
+ ln = get_line(l-1)
+ chr = string[target,1]
+ KpegPosInfo.new(target, l, c, ln, chr)
end
def lines
- lines = []
- string.each_line { |l| lines << l }
- lines
+ string.lines
+ end
+
+ def get_line(no)
+ loff = position_line_offsets
+ if no < 0
+ raise "Line No is out of range: #{no} < 0"
+ elsif no >= loff.size
+ raise "Line No is out of range: #{no} >= #{loff.size}"
+ end
+ lend = loff[no]-1
+ lstart = no > 0 ? loff[no-1] : 0
+ string[lstart..lend]
end
@@ -245,6 +291,7 @@ class RDoc::Markdown
@string = string
@string_size = string ? string.size : 0
@pos = pos
+ @position_line_offsets = nil
end
def show_pos
@@ -269,30 +316,22 @@ class RDoc::Markdown
end
def failure_caret
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
-
- line = lines[l-1]
- "#{line}\n#{' ' * (c - 1)}^"
+ p = current_pos_info @failing_rule_offset
+ "#{p.line.chomp}\n#{' ' * (p.col - 1)}^"
end
def failure_character
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
- lines[l-1][c-1, 1]
+ current_character @failing_rule_offset
end
def failure_oneline
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
-
- char = lines[l-1][c-1, 1]
+ p = current_pos_info @failing_rule_offset
if @failed_rule.kind_of? Symbol
info = self.class::Rules[@failed_rule]
- "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
+ "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'"
else
- "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
+ "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'"
end
end
@@ -305,10 +344,9 @@ class RDoc::Markdown
def show_error(io=STDOUT)
error_pos = @failing_rule_offset
- line_no = current_line(error_pos)
- col_no = current_column(error_pos)
+ p = current_pos_info(error_pos)
- io.puts "On line #{line_no}, column #{col_no}:"
+ io.puts "On line #{p.lno}, column #{p.col}:"
if @failed_rule.kind_of? Symbol
info = self.class::Rules[@failed_rule]
@@ -317,10 +355,9 @@ class RDoc::Markdown
io.puts "Failed to match rule '#{@failed_rule}'"
end
- io.puts "Got: #{string[error_pos,1].inspect}"
- line = lines[line_no-1]
- io.puts "=> #{line}"
- io.print(" " * (col_no + 3))
+ io.puts "Got: #{p.char.inspect}"
+ io.puts "=> #{p.line}"
+ io.print(" " * (p.col + 2))
io.puts "^"
end
@@ -429,6 +466,7 @@ class RDoc::Markdown
end
def apply_with_args(rule, *args)
+ @result = nil
memo_key = [rule, args]
if m = @memoizations[memo_key][@pos]
@pos = m.pos
@@ -462,6 +500,7 @@ class RDoc::Markdown
end
def apply(rule)
+ @result = nil
if m = @memoizations[rule][@pos]
@pos = m.pos
if !m.set
@@ -533,11 +572,11 @@ class RDoc::Markdown
- require 'rdoc'
- require 'rdoc/markup/to_joined_paragraph'
- require 'rdoc/markdown/entities'
+ require_relative '../rdoc'
+ require_relative 'markup/to_joined_paragraph'
+ require_relative 'markdown/entities'
- require 'rdoc/markdown/literals'
+ require_relative 'markdown/literals'
##
# Supported extensions
@@ -795,7 +834,7 @@ class RDoc::Markdown
@note_order.each_with_index do |ref, index|
label = index + 1
- note = @footnotes[ref]
+ note = @footnotes[ref] or raise ParseError, "footnote [^#{ref}] not found"
link = "{^#{label}}[rdoc-label:footmark-#{label}:foottext-#{label}] "
note.parts.unshift link
@@ -14918,7 +14957,7 @@ class RDoc::Markdown
return _tmp
end
- # RawLine = (< (!"\r" !"\n" .)* @Newline > | < .+ > @Eof) { text }
+ # RawLine = (< /[^\r\n]*/ @Newline > | < .+ > @Eof) { text }
def _RawLine
_save = self.pos
@@ -14930,36 +14969,7 @@ class RDoc::Markdown
_save2 = self.pos
while true # sequence
- while true
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = match_string("\r")
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _save6 = self.pos
- _tmp = match_string("\n")
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
+ _tmp = scan(/\G(?-mix:[^\r\n]*)/)
unless _tmp
self.pos = _save2
break
@@ -14977,10 +14987,10 @@ class RDoc::Markdown
break if _tmp
self.pos = _save1
- _save7 = self.pos
+ _save3 = self.pos
while true # sequence
_text_start = self.pos
- _save8 = self.pos
+ _save4 = self.pos
_tmp = get_byte
if _tmp
while true
@@ -14989,18 +14999,18 @@ class RDoc::Markdown
end
_tmp = true
else
- self.pos = _save8
+ self.pos = _save4
end
if _tmp
text = get_text(_text_start)
end
unless _tmp
- self.pos = _save7
+ self.pos = _save3
break
end
_tmp = _Eof()
unless _tmp
- self.pos = _save7
+ self.pos = _save3
end
break
end # end sequence
@@ -15546,7 +15556,7 @@ class RDoc::Markdown
return _tmp
end
- # RawNoteBlock = @StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }
+ # RawNoteBlock = @StartList:a (!@BlankLine !RawNoteReference OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }
def _RawNoteBlock
_save = self.pos
@@ -15569,6 +15579,14 @@ class RDoc::Markdown
self.pos = _save2
break
end
+ _save4 = self.pos
+ _tmp = apply(:_RawNoteReference)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save2
+ break
+ end
_tmp = apply(:_OptionallyIndentedLine)
l = @result
unless _tmp
@@ -15586,26 +15604,34 @@ class RDoc::Markdown
if _tmp
while true
- _save4 = self.pos
+ _save5 = self.pos
while true # sequence
- _save5 = self.pos
+ _save6 = self.pos
_tmp = _BlankLine()
_tmp = _tmp ? nil : true
- self.pos = _save5
+ self.pos = _save6
unless _tmp
- self.pos = _save4
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = apply(:_RawNoteReference)
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
break
end
_tmp = apply(:_OptionallyIndentedLine)
l = @result
unless _tmp
- self.pos = _save4
+ self.pos = _save5
break
end
@result = begin; a << l ; end
_tmp = true
unless _tmp
- self.pos = _save4
+ self.pos = _save5
end
break
end # end sequence
@@ -15907,7 +15933,7 @@ class RDoc::Markdown
return _tmp
end
- # Table = &{ github? } TableRow:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }
+ # Table = &{ github? } TableHead:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }
def _Table
_save = self.pos
@@ -15919,7 +15945,7 @@ class RDoc::Markdown
self.pos = _save
break
end
- _tmp = apply(:_TableRow)
+ _tmp = apply(:_TableHead)
header = @result
unless _tmp
self.pos = _save
@@ -15963,18 +15989,18 @@ class RDoc::Markdown
return _tmp
end
- # TableRow = TableItem+:row "|" @Newline { row }
- def _TableRow
+ # TableHead = TableItem2+:items "|"? @Newline { items }
+ def _TableHead
_save = self.pos
while true # sequence
_save1 = self.pos
_ary = []
- _tmp = apply(:_TableItem)
+ _tmp = apply(:_TableItem2)
if _tmp
_ary << @result
while true
- _tmp = apply(:_TableItem)
+ _tmp = apply(:_TableItem2)
_ary << @result if _tmp
break unless _tmp
end
@@ -15983,13 +16009,18 @@ class RDoc::Markdown
else
self.pos = _save1
end
- row = @result
+ items = @result
unless _tmp
self.pos = _save
break
end
+ _save2 = self.pos
_tmp = match_string("|")
unless _tmp
+ _tmp = true
+ self.pos = _save2
+ end
+ unless _tmp
self.pos = _save
break
end
@@ -15998,7 +16029,7 @@ class RDoc::Markdown
self.pos = _save
break
end
- @result = begin; row ; end
+ @result = begin; items ; end
_tmp = true
unless _tmp
self.pos = _save
@@ -16006,90 +16037,92 @@ class RDoc::Markdown
break
end # end sequence
- set_failed_rule :_TableRow unless _tmp
+ set_failed_rule :_TableHead unless _tmp
return _tmp
end
- # TableItem = "|" < (!"|" !@Newline .)+ > { text.strip }
- def _TableItem
+ # TableRow = ((TableItem:item1 TableItem2*:items { [item1, *items] }):row | TableItem2+:row) "|"? @Newline { row }
+ def _TableRow
_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("|")
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_TableItem)
+ item1 = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _ary = []
+ while true
+ _tmp = apply(:_TableItem2)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ items = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; [item1, *items] ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
break
- end
+ end # end sequence
+
+ row = @result
+ break if _tmp
+ self.pos = _save1
_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
+ _ary = []
+ _tmp = apply(:_TableItem2)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_TableItem2)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save4
end
+ row = @result
+ break if _tmp
+ self.pos = _save1
break
- end # end 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
+ end # end choice
- break unless _tmp
- end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save5 = self.pos
+ _tmp = match_string("|")
+ unless _tmp
_tmp = true
- else
- self.pos = _save1
+ self.pos = _save5
end
- if _tmp
- text = get_text(_text_start)
+ unless _tmp
+ self.pos = _save
+ break
end
+ _tmp = _Newline()
unless _tmp
self.pos = _save
break
end
- @result = begin; text.strip ; end
+ @result = begin; row ; end
_tmp = true
unless _tmp
self.pos = _save
@@ -16097,46 +16130,46 @@ class RDoc::Markdown
break
end # end sequence
- set_failed_rule :_TableItem unless _tmp
+ set_failed_rule :_TableRow unless _tmp
return _tmp
end
- # TableLine = TableColumn+:line "|" @Newline { line }
- def _TableLine
+ # TableItem2 = "|" TableItem
+ def _TableItem2
_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
+ _tmp = match_string("|")
unless _tmp
self.pos = _save
break
end
- _tmp = match_string("|")
+ _tmp = apply(:_TableItem)
unless _tmp
self.pos = _save
- break
end
- _tmp = _Newline()
+ break
+ end # end sequence
+
+ set_failed_rule :_TableItem2 unless _tmp
+ return _tmp
+ end
+
+ # TableItem = < /(?:\\.|[^|\n])+/ > { text.strip.gsub(/\\(.)/, '\1') }
+ def _TableItem
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _tmp = scan(/\G(?-mix:(?:\\.|[^|\n])+)/)
+ if _tmp
+ text = get_text(_text_start)
+ end
unless _tmp
self.pos = _save
break
end
- @result = begin; line ; end
+ @result = begin; text.strip.gsub(/\\(.)/, '\1') ; end
_tmp = true
unless _tmp
self.pos = _save
@@ -16144,80 +16177,136 @@ class RDoc::Markdown
break
end # end sequence
- set_failed_rule :_TableLine unless _tmp
+ set_failed_rule :_TableItem unless _tmp
return _tmp
end
- # TableColumn = "|" < ("-"+ ":"? | ":" "-"*) > { text.start_with?(":") ? :left : text.end_with?(":") ? :right : nil }
- def _TableColumn
+ # TableLine = ((TableAlign:align1 TableAlign2*:aligns {[align1, *aligns] }):line | TableAlign2+:line) "|"? @Newline { line }
+ def _TableLine
_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
+ _tmp = apply(:_TableAlign)
+ align1 = @result
unless _tmp
self.pos = _save2
break
end
- _save4 = self.pos
- _tmp = match_string(":")
+ _ary = []
+ while true
+ _tmp = apply(:_TableAlign2)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ aligns = @result
unless _tmp
- _tmp = true
- self.pos = _save4
+ self.pos = _save2
+ break
end
+ @result = begin; [align1, *aligns] ; end
+ _tmp = true
unless _tmp
self.pos = _save2
end
break
end # end sequence
+ line = @result
break if _tmp
self.pos = _save1
-
- _save5 = self.pos
- while true # sequence
- _tmp = match_string(":")
- unless _tmp
- self.pos = _save5
- break
- end
+ _save4 = self.pos
+ _ary = []
+ _tmp = apply(:_TableAlign2)
+ if _tmp
+ _ary << @result
while true
- _tmp = match_string("-")
+ _tmp = apply(:_TableAlign2)
+ _ary << @result if _tmp
break unless _tmp
end
_tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
+ @result = _ary
+ else
+ self.pos = _save4
+ end
+ line = @result
break if _tmp
self.pos = _save1
break
end # end choice
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save5 = self.pos
+ _tmp = match_string("|")
+ unless _tmp
+ _tmp = true
+ self.pos = _save5
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = _Newline()
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; line ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TableLine unless _tmp
+ return _tmp
+ end
+
+ # TableAlign2 = "|" @Sp TableAlign
+ def _TableAlign2
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("|")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = _Sp()
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_TableAlign)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TableAlign2 unless _tmp
+ return _tmp
+ end
+
+ # TableAlign = < /:?-+:?/ > @Sp { text.start_with?(":") ? (text.end_with?(":") ? :center : :left) : (text.end_with?(":") ? :right : nil) }
+ def _TableAlign
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _tmp = scan(/\G(?-mix::?-+:?)/)
if _tmp
text = get_text(_text_start)
end
@@ -16225,8 +16314,15 @@ class RDoc::Markdown
self.pos = _save
break
end
- @result = begin; text.start_with?(":") ? :left :
- text.end_with?(":") ? :right : nil
+ _tmp = _Sp()
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin;
+ text.start_with?(":") ?
+ (text.end_with?(":") ? :center : :left) :
+ (text.end_with?(":") ? :right : nil)
; end
_tmp = true
unless _tmp
@@ -16235,7 +16331,7 @@ class RDoc::Markdown
break
end # end sequence
- set_failed_rule :_TableColumn unless _tmp
+ set_failed_rule :_TableAlign unless _tmp
return _tmp
end
@@ -16661,7 +16757,7 @@ class RDoc::Markdown
Rules[:_OptionallyIndentedLine] = rule_info("OptionallyIndentedLine", "Indent? Line")
Rules[:_StartList] = rule_info("StartList", "&. { [] }")
Rules[:_Line] = rule_info("Line", "@RawLine:a { a }")
- Rules[:_RawLine] = rule_info("RawLine", "(< (!\"\\r\" !\"\\n\" .)* @Newline > | < .+ > @Eof) { text }")
+ Rules[:_RawLine] = rule_info("RawLine", "(< /[^\\r\\n]*/ @Newline > | < .+ > @Eof) { text }")
Rules[:_SkipBlock] = rule_info("SkipBlock", "(HtmlBlock | (!\"\#\" !SetextBottom1 !SetextBottom2 !@BlankLine @RawLine)+ @BlankLine* | @BlankLine+ | @RawLine)")
Rules[:_ExtendedSpecialChar] = rule_info("ExtendedSpecialChar", "&{ notes? } \"^\"")
Rules[:_NoteReference] = rule_info("NoteReference", "&{ notes? } RawNoteReference:ref { note_for ref }")
@@ -16669,13 +16765,16 @@ class RDoc::Markdown
Rules[:_Note] = rule_info("Note", "&{ notes? } @NonindentSpace RawNoteReference:ref \":\" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }")
Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" @StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }")
Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*")
- Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }")
+ Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine !RawNoteReference OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }")
Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (@Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format.instance_of?(String) verbatim }")
- Rules[:_Table] = rule_info("Table", "&{ github? } 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[:_Table] = rule_info("Table", "&{ github? } TableHead:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }")
+ Rules[:_TableHead] = rule_info("TableHead", "TableItem2+:items \"|\"? @Newline { items }")
+ Rules[:_TableRow] = rule_info("TableRow", "((TableItem:item1 TableItem2*:items { [item1, *items] }):row | TableItem2+:row) \"|\"? @Newline { row }")
+ Rules[:_TableItem2] = rule_info("TableItem2", "\"|\" TableItem")
+ Rules[:_TableItem] = rule_info("TableItem", "< /(?:\\\\.|[^|\\n])+/ > { text.strip.gsub(/\\\\(.)/, '\\1') }")
+ Rules[:_TableLine] = rule_info("TableLine", "((TableAlign:align1 TableAlign2*:aligns {[align1, *aligns] }):line | TableAlign2+:line) \"|\"? @Newline { line }")
+ Rules[:_TableAlign2] = rule_info("TableAlign2", "\"|\" @Sp TableAlign")
+ Rules[:_TableAlign] = rule_info("TableAlign", "< /:?-+:?/ > @Sp { text.start_with?(\":\") ? (text.end_with?(\":\") ? :center : :left) : (text.end_with?(\":\") ? :right : nil) }")
Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }")
Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }")
Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label @Sp @Newline { label }")
diff --git a/lib/rdoc/markdown/literals.rb b/lib/rdoc/markdown/literals.rb
index 943c2d268a..37659b7ae0 100644
--- a/lib/rdoc/markdown/literals.rb
+++ b/lib/rdoc/markdown/literals.rb
@@ -29,6 +29,7 @@ class RDoc::Markdown::Literals
@result = nil
@failed_rule = nil
@failing_rule_offset = -1
+ @line_offsets = nil
setup_foreign_grammar
end
@@ -38,30 +39,75 @@ class RDoc::Markdown::Literals
attr_accessor :result, :pos
def current_column(target=pos)
- if c = string.rindex("\n", target-1)
- return target - c - 1
+ if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1)
+ return target - c
+ elsif c = string.rindex("\n", target)
+ return target - c
end
target + 1
end
- def current_line(target=pos)
- cur_offset = 0
- cur_line = 0
+ def position_line_offsets
+ unless @position_line_offsets
+ @position_line_offsets = []
+ total = 0
+ string.each_line do |line|
+ total += line.size
+ @position_line_offsets << total
+ end
+ end
+ @position_line_offsets
+ end
- string.each_line do |line|
- cur_line += 1
- cur_offset += line.size
- return cur_line if cur_offset >= target
+ if [].respond_to? :bsearch_index
+ def current_line(target=pos)
+ if line = position_line_offsets.bsearch_index {|x| x > target }
+ return line + 1
+ end
+ raise "Target position #{target} is outside of string"
end
+ else
+ def current_line(target=pos)
+ if line = position_line_offsets.index {|x| x > target }
+ return line + 1
+ end
+
+ raise "Target position #{target} is outside of string"
+ end
+ end
+
+ def current_character(target=pos)
+ if target < 0 || target >= string.size
+ raise "Target position #{target} is outside of string"
+ end
+ string[target, 1]
+ end
+
+ KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char)
- -1
+ def current_pos_info(target=pos)
+ l = current_line target
+ c = current_column target
+ ln = get_line(l-1)
+ chr = string[target,1]
+ KpegPosInfo.new(target, l, c, ln, chr)
end
def lines
- lines = []
- string.each_line { |l| lines << l }
- lines
+ string.lines
+ end
+
+ def get_line(no)
+ loff = position_line_offsets
+ if no < 0
+ raise "Line No is out of range: #{no} < 0"
+ elsif no >= loff.size
+ raise "Line No is out of range: #{no} >= #{loff.size}"
+ end
+ lend = loff[no]-1
+ lstart = no > 0 ? loff[no-1] : 0
+ string[lstart..lend]
end
@@ -75,6 +121,7 @@ class RDoc::Markdown::Literals
@string = string
@string_size = string ? string.size : 0
@pos = pos
+ @position_line_offsets = nil
end
def show_pos
@@ -99,30 +146,22 @@ class RDoc::Markdown::Literals
end
def failure_caret
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
-
- line = lines[l-1]
- "#{line}\n#{' ' * (c - 1)}^"
+ p = current_pos_info @failing_rule_offset
+ "#{p.line.chomp}\n#{' ' * (p.col - 1)}^"
end
def failure_character
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
- lines[l-1][c-1, 1]
+ current_character @failing_rule_offset
end
def failure_oneline
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
-
- char = lines[l-1][c-1, 1]
+ p = current_pos_info @failing_rule_offset
if @failed_rule.kind_of? Symbol
info = self.class::Rules[@failed_rule]
- "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
+ "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'"
else
- "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
+ "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'"
end
end
@@ -135,10 +174,9 @@ class RDoc::Markdown::Literals
def show_error(io=STDOUT)
error_pos = @failing_rule_offset
- line_no = current_line(error_pos)
- col_no = current_column(error_pos)
+ p = current_pos_info(error_pos)
- io.puts "On line #{line_no}, column #{col_no}:"
+ io.puts "On line #{p.lno}, column #{p.col}:"
if @failed_rule.kind_of? Symbol
info = self.class::Rules[@failed_rule]
@@ -147,10 +185,9 @@ class RDoc::Markdown::Literals
io.puts "Failed to match rule '#{@failed_rule}'"
end
- io.puts "Got: #{string[error_pos,1].inspect}"
- line = lines[line_no-1]
- io.puts "=> #{line}"
- io.print(" " * (col_no + 3))
+ io.puts "Got: #{p.char.inspect}"
+ io.puts "=> #{p.line}"
+ io.print(" " * (p.col + 2))
io.puts "^"
end
@@ -259,6 +296,7 @@ class RDoc::Markdown::Literals
end
def apply_with_args(rule, *args)
+ @result = nil
memo_key = [rule, args]
if m = @memoizations[memo_key][@pos]
@pos = m.pos
@@ -292,6 +330,7 @@ class RDoc::Markdown::Literals
end
def apply(rule)
+ @result = nil
if m = @memoizations[rule][@pos]
@pos = m.pos
if !m.set
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
index 92aed757cf..6e93030965 100644
--- a/lib/rdoc/markup.rb
+++ b/lib/rdoc/markup.rb
@@ -97,638 +97,7 @@
#
# = \RDoc Markup Reference
#
-# == Block Markup
-#
-# === Paragraphs and Verbatim
-#
-# The markup engine looks for a document's natural left margin. This is
-# used as the initial margin for the document.
-#
-# Consecutive lines starting at this margin are considered to be a
-# paragraph. Empty lines separate paragraphs.
-#
-# Any line that starts to the right of the current margin is treated
-# as verbatim text. This is useful for code listings:
-#
-# 3.times { puts "Ruby" }
-#
-# In verbatim text, two or more blank lines are collapsed into one,
-# and trailing blank lines are removed:
-#
-# This is the first line
-#
-#
-# This is the second non-blank line,
-# after 2 blank lines in the source markup.
-#
-#
-# There were two trailing blank lines right above this paragraph, that
-# have been removed. In addition, the verbatim text has been shifted
-# left, so the amount of indentation of verbatim text is unimportant.
-#
-# For HTML output RDoc makes a small effort to determine if a verbatim section
-# contains Ruby source code. If so, the verbatim block will be marked up as
-# HTML. Triggers include "def", "class", "module", "require", the "hash
-# rocket"# (=>) or a block call with a parameter.
-#
-# === Headers
-#
-# A line starting with an equal sign (=) is treated as a
-# heading. Level one headings have one equals sign, level two headings
-# have two, and so on until level six, which is the maximum
-# (seven hyphens or more result in a level six heading).
-#
-# For example, the above header was obtained with:
-#
-# === Headers
-#
-# In HTML output headers have an id matching their name. The above example's
-# HTML is:
-#
-# <h3 id="label-Headers">Headers</h3>
-#
-# If a heading is inside a method body the id will be prefixed with the
-# method's id. If the above header where in the documentation for a method
-# such as:
-#
-# ##
-# # This method does fun things
-# #
-# # = Example
-# #
-# # Example of fun things goes here ...
-#
-# def do_fun_things
-# end
-#
-# The header's id would be:
-#
-# <h1 id="method-i-do_fun_things-label-Example">Example</h1>
-#
-# The label can be linked-to using <tt>SomeClass@Headers</tt>. See
-# {Links}[RDoc::Markup@Links] for further details.
-#
-# === Rules
-#
-# A line starting with three or more hyphens (at the current indent)
-# generates a horizontal rule.
-#
-# ---
-#
-# produces:
-#
-# ---
-#
-# === Simple Lists
-#
-# If a paragraph starts with a "*", "-", "<digit>." or "<letter>.",
-# then it is taken to be the start of a list. The margin is increased to be
-# the first non-space following the list start flag. Subsequent lines
-# should be indented to this new margin until the list ends. For example:
-#
-# * this is a list with three paragraphs in
-# the first item. This is the first paragraph.
-#
-# And this is the second paragraph.
-#
-# 1. This is an indented, numbered list.
-# 2. This is the second item in that list
-#
-# This is the third conventional paragraph in the
-# first list item.
-#
-# * This is the second item in the original list
-#
-# produces:
-#
-# * this is a list with three paragraphs in
-# the first item. This is the first paragraph.
-#
-# And this is the second paragraph.
-#
-# 1. This is an indented, numbered list.
-# 2. This is the second item in that list
-#
-# This is the third conventional paragraph in the
-# first list item.
-#
-# * This is the second item in the original list
-#
-# === Labeled Lists
-#
-# You can also construct labeled lists, sometimes called description
-# or definition lists. Do this by putting the label in square brackets
-# and indenting the list body:
-#
-# [cat] a small furry mammal
-# that seems to sleep a lot
-#
-# [ant] a little insect that is known
-# to enjoy picnics
-#
-# produces:
-#
-# [cat] a small furry mammal
-# that seems to sleep a lot
-#
-# [ant] a little insect that is known
-# to enjoy picnics
-#
-# If you want the list bodies to line up to the left of the labels,
-# use two colons:
-#
-# cat:: a small furry mammal
-# that seems to sleep a lot
-#
-# ant:: a little insect that is known
-# to enjoy picnics
-#
-# produces:
-#
-# cat:: a small furry mammal
-# that seems to sleep a lot
-#
-# ant:: a little insect that is known
-# to enjoy picnics
-#
-# Notice that blank lines right after the label are ignored in labeled lists:
-#
-# [one]
-#
-# definition 1
-#
-# [two]
-#
-# definition 2
-#
-# produces the same output as
-#
-# [one] definition 1
-# [two] definition 2
-#
-#
-# === Lists and Verbatim
-#
-# If you want to introduce a verbatim section right after a list, it has to be
-# less indented than the list item bodies, but more indented than the list
-# label, letter, digit or bullet. For instance:
-#
-# * point 1
-#
-# * point 2, first paragraph
-#
-# point 2, second paragraph
-# verbatim text inside point 2
-# point 2, third paragraph
-# verbatim text outside of the list (the list is therefore closed)
-# regular paragraph after the list
-#
-# produces:
-#
-# * point 1
-#
-# * point 2, first paragraph
-#
-# point 2, second paragraph
-# verbatim text inside point 2
-# point 2, third paragraph
-# verbatim text outside of the list (the list is therefore closed)
-# regular paragraph after the list
-#
-# == Text Markup
-#
-# === Bold, Italic, Typewriter Text
-#
-# You can use markup within text (except verbatim) to change the
-# appearance of parts of that text. Out of the box, RDoc::Markup
-# supports word-based and general markup.
-#
-# Word-based markup uses flag characters around individual words:
-#
-# <tt>\*_word_\*</tt>:: displays _word_ in a *bold* font
-# <tt>\__word_\_</tt>:: displays _word_ in an _emphasized_ font
-# <tt>\+_word_\+</tt>:: displays _word_ in a +code+ font
-#
-# General markup affects text between a start delimiter and an end
-# delimiter. Not surprisingly, these delimiters look like HTML markup.
-#
-# <tt>\<b>_text_</b></tt>:: displays _text_ in a *bold* font
-# <tt>\<em>_text_</em></tt>:: displays _text_ in an _emphasized_ font
-# (alternate tag: <tt>\<i></tt>)
-# <tt>\<tt>_text_\</tt></tt>:: displays _text_ in a +code+ font
-# (alternate tag: <tt>\<code></tt>)
-#
-# Unlike conventional Wiki markup, general markup can cross line
-# boundaries. You can turn off the interpretation of markup by
-# preceding the first character with a backslash (see <i>Escaping
-# Text Markup</i>, below).
-#
-# === Links
-#
-# Links to starting with +http:+, +https:+, +mailto:+, +ftp:+ or +www.+
-# are recognized. An HTTP url that references an external image is converted
-# into an inline image element.
-#
-# Classes and methods will be automatically linked to their definition. For
-# example, <tt>RDoc::Markup</tt> will link to this documentation. By default
-# methods will only be automatically linked if they contain an <tt>_</tt> (all
-# methods can be automatically linked through the <tt>--hyperlink-all</tt>
-# command line option).
-#
-# Single-word methods can be linked by using the <tt>#</tt> character for
-# instance methods or <tt>::</tt> for class methods. For example,
-# <tt>#convert</tt> links to #convert. A class or method may be combined like
-# <tt>RDoc::Markup#convert</tt>.
-#
-# A heading inside the documentation can be linked by following the class
-# or method by an <tt>@</tt> then the heading name.
-# <tt>RDoc::Markup@Links</tt> will link to this section like this:
-# RDoc::Markup@Links. Spaces in headings with multiple words must be escaped
-# with <tt>+</tt> like <tt>RDoc::Markup@Escaping+Text+Markup</tt>.
-# Punctuation and other special characters must be escaped like CGI.escape.
-#
-# The <tt>@</tt> can also be used to link to sections. If a section and a
-# heading share the same name the section is preferred for the link.
-#
-# Links can also be of the form <tt>label[url]</tt>, in which case +label+ is
-# used in the displayed text, and +url+ is used as the target. If +label+
-# contains multiple words, put it in braces: <tt>{multi word label}[url]</tt>.
-# The +url+ may be an +http:+-type link or a cross-reference to a class,
-# module or method with a label.
-#
-# Links with the <code>rdoc-image:</code> scheme will create an image tag for
-# HTML output. Only fully-qualified URLs are supported.
-#
-# Links with the <tt>rdoc-ref:</tt> scheme will link to the referenced class,
-# module, method, file, etc. If the referenced item is does not exist
-# no link will be generated and <tt>rdoc-ref:</tt> will be removed from the
-# resulting text.
-#
-# Links starting with <tt>rdoc-label:label_name</tt> will link to the
-# +label_name+. You can create a label for the current link (for
-# bidirectional links) by supplying a name for the current link like
-# <tt>rdoc-label:label-other:label-mine</tt>.
-#
-# Links starting with +link:+ refer to local files whose path is relative to
-# the <tt>--op</tt> directory. Use <tt>rdoc-ref:</tt> instead of
-# <tt>link:</tt> to link to files generated by RDoc as the link target may
-# be different across RDoc generators.
-#
-# Example links:
-#
-# https://github.com/ruby/rdoc
-# mailto:user@example.com
-# {RDoc Documentation}[http://rdoc.rubyforge.org]
-# {RDoc Markup}[rdoc-ref:RDoc::Markup]
-#
-# === Escaping Text Markup
-#
-# Text markup can be escaped with a backslash, as in \<tt>, which was obtained
-# with <tt>\\<tt></tt>. Except in verbatim sections and between \<tt> tags,
-# to produce a backslash you have to double it unless it is followed by a
-# space, tab or newline. Otherwise, the HTML formatter will discard it, as it
-# is used to escape potential links:
-#
-# * The \ must be doubled if not followed by white space: \\.
-# * But not in \<tt> tags: in a Regexp, <tt>\S</tt> matches non-space.
-# * This is a link to {ruby-lang}[www.ruby-lang.org].
-# * This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org].
-# * This will not be linked to \RDoc::RDoc#document
-#
-# generates:
-#
-# * The \ must be doubled if not followed by white space: \\.
-# * But not in \<tt> tags: in a Regexp, <tt>\S</tt> matches non-space.
-# * This is a link to {ruby-lang}[www.ruby-lang.org]
-# * This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org]
-# * This will not be linked to \RDoc::RDoc#document
-#
-# Inside \<tt> tags, more precisely, leading backslashes are removed only if
-# followed by a markup character (<tt><*_+</tt>), a backslash, or a known link
-# reference (a known class or method). So in the example above, the backslash
-# of <tt>\S</tt> would be removed if there was a class or module named +S+ in
-# the current context.
-#
-# This behavior is inherited from RDoc version 1, and has been kept for
-# compatibility with existing RDoc documentation.
-#
-# === Conversion of characters
-#
-# HTML will convert two/three dashes to an em-dash. Other common characters are
-# converted as well:
-#
-# em-dash:: -- or ---
-# ellipsis:: ...
-#
-# single quotes:: 'text' or `text'
-# double quotes:: "text" or ``text''
-#
-# copyright:: (c)
-# registered trademark:: (r)
-#
-# produces:
-#
-# em-dash:: -- or ---
-# ellipsis:: ...
-#
-# single quotes:: 'text' or `text'
-# double quotes:: "text" or ``text''
-#
-# copyright:: (c)
-# registered trademark:: (r)
-#
-#
-# == Documenting Source Code
-#
-# Comment blocks can be written fairly naturally, either using <tt>#</tt> on
-# successive lines of the comment, or by including the comment in
-# a <tt>=begin</tt>/<tt>=end</tt> block. If you use the latter form,
-# the <tt>=begin</tt> line _must_ be flagged with an +rdoc+ tag:
-#
-# =begin rdoc
-# Documentation to be processed by RDoc.
-#
-# ...
-# =end
-#
-# RDoc stops processing comments if it finds a comment line starting
-# with <tt>--</tt> right after the <tt>#</tt> character (otherwise,
-# it will be treated as a rule if it has three dashes or more).
-# This can be used to separate external from internal comments,
-# or to stop a comment being associated with a method, class, or module.
-# Commenting can be turned back on with a line that starts with <tt>++</tt>.
-#
-# ##
-# # Extract the age and calculate the date-of-birth.
-# #--
-# # FIXME: fails if the birthday falls on February 29th
-# #++
-# # The DOB is returned as a Time object.
-#
-# def get_dob(person)
-# # ...
-# end
-#
-# Names of classes, files, and any method names containing an underscore or
-# preceded by a hash character are automatically linked from comment text to
-# their description. This linking works inside the current class or module,
-# and with ancestor methods (in included modules or in the superclass).
-#
-# Method parameter lists are extracted and displayed with the method
-# description. If a method calls +yield+, then the parameters passed to yield
-# will also be displayed:
-#
-# def fred
-# ...
-# yield line, address
-#
-# This will get documented as:
-#
-# fred() { |line, address| ... }
-#
-# You can override this using a comment containing ':yields: ...' immediately
-# after the method definition
-#
-# def fred # :yields: index, position
-# # ...
-#
-# yield line, address
-#
-# which will get documented as
-#
-# fred() { |index, position| ... }
-#
-# +:yields:+ is an example of a documentation directive. These appear
-# immediately after the start of the document element they are modifying.
-#
-# RDoc automatically cross-references words with underscores or camel-case.
-# To suppress cross-references, prefix the word with a \ character. To
-# include special characters like "<tt>\n</tt>", you'll need to use
-# two \ characters in normal text, but only one in \<tt> text:
-#
-# "\\n" or "<tt>\n</tt>"
-#
-# produces:
-#
-# "\\n" or "<tt>\n</tt>"
-#
-# == Directives
-#
-# Directives are keywords surrounded by ":" characters.
-#
-# === Controlling what is documented
-#
-# [+:nodoc:+ / <tt>:nodoc: all</tt>]
-# This directive prevents documentation for the element from
-# being generated. For classes and modules, methods, aliases,
-# constants, and attributes directly within the affected class or
-# module also will be omitted. By default, though, modules and
-# classes within that class or module _will_ be documented. This is
-# turned off by adding the +all+ modifier.
-#
-# module MyModule # :nodoc:
-# class Input
-# end
-# end
-#
-# module OtherModule # :nodoc: all
-# class Output
-# end
-# end
-#
-# In the above code, only class <tt>MyModule::Input</tt> will be documented.
-#
-# The +:nodoc:+ directive, like +:enddoc:+, +:stopdoc:+ and +:startdoc:+
-# presented below, is local to the current file: if you do not want to
-# document a module that appears in several files, specify +:nodoc:+ on each
-# appearance, at least once per file.
-#
-# [+:stopdoc:+ / +:startdoc:+]
-# Stop and start adding new documentation elements to the current container.
-# For example, if a class has a number of constants that you don't want to
-# document, put a +:stopdoc:+ before the first, and a +:startdoc:+ after the
-# last. If you don't specify a +:startdoc:+ by the end of the container,
-# disables documentation for the rest of the current file.
-#
-# [+:doc:+]
-# Forces a method or attribute to be documented even if it wouldn't be
-# otherwise. Useful if, for example, you want to include documentation of a
-# particular private method.
-#
-# [+:enddoc:+]
-# Document nothing further at the current level: directives +:startdoc:+ and
-# +:doc:+ that appear after this will not be honored for the current container
-# (file, class or module), in the current file.
-#
-# [+:notnew:+ / +:not_new:+ / +:not-new:+ ]
-# Only applicable to the +initialize+ instance method. Normally RDoc
-# assumes that the documentation and parameters for +initialize+ are
-# actually for the +new+ method, and so fakes out a +new+ for the class.
-# The +:notnew:+ directive stops this. Remember that +initialize+ is private,
-# so you won't see the documentation unless you use the +-a+ command line
-# option.
-#
-# === Method arguments
-#
-# [+:arg:+ or +:args:+ _parameters_]
-# Overrides the default argument handling with exactly these parameters.
-#
-# ##
-# # :args: a, b
-#
-# def some_method(*a)
-# end
-#
-# [+:yield:+ or +:yields:+ _parameters_]
-# Overrides the default yield discovery with these parameters.
-#
-# ##
-# # :yields: key, value
-#
-# def each_thing &block
-# @things.each(&block)
-# end
-#
-# [+:call-seq:+]
-# Lines up to the next blank line or lines with a common prefix in the
-# comment are treated as the method's calling sequence, overriding the
-# default parsing of method parameters and yield arguments.
-#
-# Multiple lines may be used.
-#
-# # :call-seq:
-# # ARGF.readlines(sep=$/) -> array
-# # ARGF.readlines(limit) -> array
-# # ARGF.readlines(sep, limit) -> array
-# #
-# # ARGF.to_a(sep=$/) -> array
-# # ARGF.to_a(limit) -> array
-# # ARGF.to_a(sep, limit) -> array
-# #
-# # The remaining lines are documentation ...
-#
-# === Sections
-#
-# Sections allow you to group methods in a class into sensible containers. If
-# you use the sections 'Public', 'Internal' and 'Deprecated' (the three
-# allowed method statuses from TomDoc) the sections will be displayed in that
-# order placing the most useful methods at the top. Otherwise, sections will
-# be displayed in alphabetical order.
-#
-# [+:category:+ _section_]
-# Adds this item to the named +section+ overriding the current section. Use
-# this to group methods by section in RDoc output while maintaining a
-# sensible ordering (like alphabetical).
-#
-# # :category: Utility Methods
-# #
-# # CGI escapes +text+
-#
-# def convert_string text
-# CGI.escapeHTML text
-# end
-#
-# An empty category will place the item in the default category:
-#
-# # :category:
-# #
-# # This method is in the default category
-#
-# def some_method
-# # ...
-# end
-#
-# Unlike the :section: directive, :category: is not sticky. The category
-# only applies to the item immediately following the comment.
-#
-# Use the :section: directive to provide introductory text for a section of
-# documentation.
-#
-# [+:section:+ _title_]
-# Provides section introductory text in RDoc output. The title following
-# +:section:+ is used as the section name and the remainder of the comment
-# containing the section is used as introductory text. A section's comment
-# block must be separated from following comment blocks. Use an empty title
-# to switch to the default section.
-#
-# The :section: directive is sticky, so subsequent methods, aliases,
-# attributes, and classes will be contained in this section until the
-# section is changed. The :category: directive will override the :section:
-# directive.
-#
-# A :section: comment block may have one or more lines before the :section:
-# directive. These will be removed, and any identical lines at the end of
-# the block are also removed. This allows you to add visual cues to the
-# section.
-#
-# Example:
-#
-# # ----------------------------------------
-# # :section: My Section
-# # This is the section that I wrote.
-# # See it glisten in the noon-day sun.
-# # ----------------------------------------
-#
-# ##
-# # Comment for some_method
-#
-# def some_method
-# # ...
-# end
-#
-# === Other directives
-#
-# [+:markup:+ _type_]
-# Overrides the default markup type for this comment with the specified
-# markup type. For Ruby files, if the first comment contains this directive
-# it is applied automatically to all comments in the file.
-#
-# Unless you are converting between markup formats you should use a
-# <code>.rdoc_options</code> file to specify the default documentation
-# format for your entire project. See RDoc::Options@Saved+Options for
-# instructions.
-#
-# At the top of a file the +:markup:+ directive applies to the entire file:
-#
-# # coding: UTF-8
-# # :markup: TomDoc
-#
-# # TomDoc comment here ...
-#
-# class MyClass
-# # ...
-#
-# For just one comment:
-#
-# # ...
-# end
-#
-# # :markup: RDoc
-# #
-# # This is a comment in RDoc markup format ...
-#
-# def some_method
-# # ...
-#
-# See Markup@CONTRIBUTING for instructions on adding a new markup format.
-#
-# [+:include:+ _filename_]
-# Include the contents of the named file at this point. This directive
-# must appear alone on one line, possibly preceded by spaces. In this
-# position, it can be escaped with a \ in front of the first colon.
-#
-# The file will be searched for in the directories listed by the +--include+
-# option, or in the current directory by default. The contents of the file
-# will be shifted to have the same indentation as the ':' at the start of
-# the +:include:+ directive.
-#
-# [+:title:+ _text_]
-# Sets the title for the document. Equivalent to the <tt>--title</tt>
-# command line parameter. (The command line parameter overrides any :title:
-# directive in the source).
-#
-# [+:main:+ _name_]
-# Equivalent to the <tt>--main</tt> command line parameter.
+# See RDoc::MarkupReference.
#
#--
# Original Author:: Dave Thomas, dave@pragmaticprogrammer.com
@@ -822,46 +191,45 @@ https://github.com/ruby/rdoc/issues
document.accept formatter
end
- autoload :Parser, 'rdoc/markup/parser'
- autoload :PreProcess, 'rdoc/markup/pre_process'
+ autoload :Parser, "#{__dir__}/markup/parser"
+ autoload :PreProcess, "#{__dir__}/markup/pre_process"
# Inline markup classes
- autoload :AttrChanger, 'rdoc/markup/attr_changer'
- autoload :AttrSpan, 'rdoc/markup/attr_span'
- autoload :Attributes, 'rdoc/markup/attributes'
- autoload :AttributeManager, 'rdoc/markup/attribute_manager'
- autoload :RegexpHandling, 'rdoc/markup/regexp_handling'
+ autoload :AttrChanger, "#{__dir__}/markup/attr_changer"
+ autoload :AttrSpan, "#{__dir__}/markup/attr_span"
+ autoload :Attributes, "#{__dir__}/markup/attributes"
+ autoload :AttributeManager, "#{__dir__}/markup/attribute_manager"
+ autoload :RegexpHandling, "#{__dir__}/markup/regexp_handling"
# RDoc::Markup AST
- autoload :BlankLine, 'rdoc/markup/blank_line'
- autoload :BlockQuote, 'rdoc/markup/block_quote'
- autoload :Document, 'rdoc/markup/document'
- autoload :HardBreak, 'rdoc/markup/hard_break'
- autoload :Heading, 'rdoc/markup/heading'
- autoload :Include, 'rdoc/markup/include'
- autoload :IndentedParagraph, 'rdoc/markup/indented_paragraph'
- 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'
+ autoload :BlankLine, "#{__dir__}/markup/blank_line"
+ autoload :BlockQuote, "#{__dir__}/markup/block_quote"
+ autoload :Document, "#{__dir__}/markup/document"
+ autoload :HardBreak, "#{__dir__}/markup/hard_break"
+ autoload :Heading, "#{__dir__}/markup/heading"
+ autoload :Include, "#{__dir__}/markup/include"
+ autoload :IndentedParagraph, "#{__dir__}/markup/indented_paragraph"
+ autoload :List, "#{__dir__}/markup/list"
+ autoload :ListItem, "#{__dir__}/markup/list_item"
+ autoload :Paragraph, "#{__dir__}/markup/paragraph"
+ autoload :Table, "#{__dir__}/markup/table"
+ autoload :Raw, "#{__dir__}/markup/raw"
+ autoload :Rule, "#{__dir__}/markup/rule"
+ autoload :Verbatim, "#{__dir__}/markup/verbatim"
# Formatters
- autoload :Formatter, 'rdoc/markup/formatter'
-
- autoload :ToAnsi, 'rdoc/markup/to_ansi'
- autoload :ToBs, 'rdoc/markup/to_bs'
- autoload :ToHtml, 'rdoc/markup/to_html'
- autoload :ToHtmlCrossref, 'rdoc/markup/to_html_crossref'
- autoload :ToHtmlSnippet, 'rdoc/markup/to_html_snippet'
- autoload :ToLabel, 'rdoc/markup/to_label'
- autoload :ToMarkdown, 'rdoc/markup/to_markdown'
- autoload :ToRdoc, 'rdoc/markup/to_rdoc'
- autoload :ToTableOfContents, 'rdoc/markup/to_table_of_contents'
- autoload :ToTest, 'rdoc/markup/to_test'
- autoload :ToTtOnly, 'rdoc/markup/to_tt_only'
+ autoload :Formatter, "#{__dir__}/markup/formatter"
+
+ autoload :ToAnsi, "#{__dir__}/markup/to_ansi"
+ autoload :ToBs, "#{__dir__}/markup/to_bs"
+ autoload :ToHtml, "#{__dir__}/markup/to_html"
+ autoload :ToHtmlCrossref, "#{__dir__}/markup/to_html_crossref"
+ autoload :ToHtmlSnippet, "#{__dir__}/markup/to_html_snippet"
+ autoload :ToLabel, "#{__dir__}/markup/to_label"
+ autoload :ToMarkdown, "#{__dir__}/markup/to_markdown"
+ autoload :ToRdoc, "#{__dir__}/markup/to_rdoc"
+ autoload :ToTableOfContents, "#{__dir__}/markup/to_table_of_contents"
+ autoload :ToTest, "#{__dir__}/markup/to_test"
+ autoload :ToTtOnly, "#{__dir__}/markup/to_tt_only"
end
-
diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb
index 50764510f3..601e6bc189 100644
--- a/lib/rdoc/markup/attribute_manager.rb
+++ b/lib/rdoc/markup/attribute_manager.rb
@@ -2,6 +2,17 @@
##
# Manages changes of attributes in a block of text
+unless MatchData.method_defined?(:match_length)
+ using Module.new {
+ refine(MatchData) {
+ def match_length(nth)
+ b, e = offset(nth)
+ e - b if b
+ end
+ }
+ }
+end
+
class RDoc::Markup::AttributeManager
##
@@ -147,27 +158,23 @@ class RDoc::Markup::AttributeManager
def convert_attrs_matching_word_pairs(str, attrs, exclusive)
# first do matching ones
tags = @matching_word_pairs.select { |start, bitmap|
- if exclusive && exclusive?(bitmap)
- true
- elsif !exclusive && !exclusive?(bitmap)
- true
- else
- false
- end
+ exclusive == exclusive?(bitmap)
}.keys
return if tags.empty?
- all_tags = @matching_word_pairs.keys
+ tags = "[#{tags.join("")}](?!#{PROTECT_ATTR})"
+ all_tags = "[#{@matching_word_pairs.keys.join("")}](?!#{PROTECT_ATTR})"
- re = /(^|\W|[#{all_tags.join("")}])([#{tags.join("")}])(\2*[#\\]?[\w:.\/\[\]-]+?\S?)\2(?!\2)([#{all_tags.join("")}]|\W|$)/
+ re = /(?:^|\W|#{all_tags})\K(#{tags})(\1*[#\\]?[\w:#{PROTECT_ATTR}.\/\[\]-]+?\S?)\1(?!\1)(?=#{all_tags}|\W|$)/
1 while str.gsub!(re) { |orig|
- attr = @matching_word_pairs[$2]
- 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
+ a, w = (m = $~).values_at(1, 2)
+ attr = @matching_word_pairs[a]
+ if attrs.set_attrs(m.begin(2), w.length, attr)
+ a = NULL * a.length
else
- $1 + NON_PRINTING_START + $2 + NON_PRINTING_END + $3 + NON_PRINTING_START + $2 + NON_PRINTING_END + $4
+ a = NON_PRINTING_START + a + NON_PRINTING_END
end
+ a + w + a
}
str.delete!(NON_PRINTING_START + NON_PRINTING_END)
end
@@ -176,15 +183,12 @@ class RDoc::Markup::AttributeManager
# then non-matching
unless @word_pair_map.empty? then
@word_pair_map.each do |regexp, attr|
- if !exclusive
- next if exclusive?(attr)
- else
- next if !exclusive?(attr)
- end
+ next unless exclusive == exclusive?(attr)
1 while str.gsub!(regexp) { |orig|
- updated = attrs.set_attrs($`.length + $1.length, $2.length, attr)
+ w = (m = ($~))[2]
+ updated = attrs.set_attrs(m.begin(2), w.length, attr)
if updated
- NULL * $1.length + $2 + NULL * $3.length
+ NULL * m.match_length(1) + w + NULL * m.match_length(3)
else
orig
end
@@ -198,20 +202,14 @@ class RDoc::Markup::AttributeManager
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
+ exclusive == exclusive?(bitmap)
}.keys.join '|'
1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { |orig|
attr = @html_tags[$1.downcase]
- html_length = $1.length + 2
+ html_length = $~.match_length(1) + 2 # "<>".length
seq = NULL * html_length
- attrs.set_attrs($`.length + html_length, $2.length, attr)
+ attrs.set_attrs($~.begin(2), $~.match_length(2), attr)
seq + $2 + seq + NULL
}
end
@@ -221,11 +219,7 @@ class RDoc::Markup::AttributeManager
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
+ next unless exclusive == exclusive?(attribute)
str.scan(regexp) do
capture = $~.size == 1 ? 0 : 1
diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb
index 1b54a519d1..0029df7e65 100644
--- a/lib/rdoc/markup/parser.rb
+++ b/lib/rdoc/markup/parser.rb
@@ -287,6 +287,12 @@ class RDoc::Markup::Parser
line << ' ' * indent
when :BREAK, :TEXT then
line << data
+ when :BLOCKQUOTE then
+ line << '>>>'
+ peek_type, _, peek_column = peek_token
+ if peek_type != :NEWLINE and peek_column
+ line << ' ' * (peek_column - column - 3)
+ end
else # *LIST_TOKENS
list_marker = case type
when :BULLET then data
@@ -372,11 +378,8 @@ class RDoc::Markup::Parser
unget
parse_text parent, indent
when :BLOCKQUOTE then
- type, _, column = get
- if type == :NEWLINE
- type, _, column = get
- end
- unget if type
+ nil while (type, = get; type) and type != :NEWLINE
+ _, _, column, = peek_token
bq = RDoc::Markup::BlockQuote.new
p :blockquote_start => [data, column] if @debug
parse bq, column
@@ -544,7 +547,10 @@ class RDoc::Markup::Parser
[:NOTE, @s[1], *pos]
# >>> followed by end of line => :BLOCKQUOTE
when @s.scan(/>>> *(\w+)?$/) then
- [:BLOCKQUOTE, @s[1], *pos]
+ if word = @s[1]
+ @s.unscan(word)
+ end
+ [:BLOCKQUOTE, word, *pos]
# anything else: :TEXT
else
@s.scan(/(.*?)( )?\r?$/)
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
index 3080ae3578..88078c9cef 100644
--- a/lib/rdoc/markup/pre_process.rb
+++ b/lib/rdoc/markup/pre_process.rb
@@ -163,6 +163,8 @@ class RDoc::Markup::PreProcess
if RDoc::Context === code_object then
section = code_object.add_section param
code_object.temporary_section = section
+ elsif RDoc::AnyMethod === code_object then
+ code_object.section_title = param
end
blankline # ignore category if we're not on an RDoc::Context
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
index d3bb8af835..bf323074de 100644
--- a/lib/rdoc/markup/to_html.rb
+++ b/lib/rdoc/markup/to_html.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'cgi'
+require 'cgi/util'
##
# Outputs RDoc markup as HTML.
@@ -61,12 +61,14 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
#
# These methods are used by regexp handling markup added by RDoc::Markup#add_regexp_handling.
+ URL_CHARACTERS_REGEXP_STR = /[A-Za-z0-9\-._~:\/\?#\[\]@!$&'\(\)*+,;%=]/.source
+
##
# Adds regexp handlings.
def init_regexp_handlings
# external links
- @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/,
+ @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)#{URL_CHARACTERS_REGEXP_STR}+\w/,
:HYPERLINK)
init_link_notation_regexp_handlings
end
@@ -82,7 +84,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
def handle_RDOCLINK url # :nodoc:
case url
when /^rdoc-ref:/
- $'
+ CGI.escapeHTML($')
when /^rdoc-label:/
text = $'
@@ -93,13 +95,11 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
else text
end
- gen_url url, text
+ gen_url CGI.escapeHTML(url), CGI.escapeHTML(text)
when /^rdoc-image:/
- "<img src=\"#{$'}\">"
- else
- url =~ /\Ardoc-[a-z]+:/
-
- $'
+ %[<img src=\"#{CGI.escapeHTML($')}\">]
+ when /\Ardoc-[a-z]+:/
+ CGI.escapeHTML($')
end
end
@@ -123,7 +123,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# Reference to a local file relative to the output directory.
def handle_regexp_HYPERLINK(target)
- url = target.text
+ url = CGI.escapeHTML(target.text)
gen_url url, url
end
@@ -152,9 +152,13 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
text =~ /^\{(.*)\}\[(.*?)\]$/ or text =~ /^(\S+)\[(.*?)\]$/
label = $1
- url = $2
+ url = CGI.escapeHTML($2)
- label = handle_RDOCLINK label if /^rdoc-image:/ =~ label
+ if /^rdoc-image:/ =~ label
+ label = handle_RDOCLINK(label)
+ else
+ label = CGI.escapeHTML(label)
+ end
gen_url url, label
end
@@ -322,7 +326,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
header.zip(aligns) do |text, align|
@res << '<th'
@res << ' align="' << align << '"' if align
- @res << '>' << CGI.escapeHTML(text) << "</th>\n"
+ @res << '>' << to_html(text) << "</th>\n"
end
@res << "</tr>\n</thead>\n<tbody>\n"
body.each do |row|
@@ -330,7 +334,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
row.zip(aligns) do |text, align|
@res << '<td'
@res << ' align="' << align << '"' if align
- @res << '>' << CGI.escapeHTML(text) << "</td>\n"
+ @res << '>' << to_html(text) << "</td>\n"
end
@res << "</tr>\n"
end
diff --git a/lib/rdoc/markup/to_label.rb b/lib/rdoc/markup/to_label.rb
index 3d95ccc2e2..aa1dbcf2a1 100644
--- a/lib/rdoc/markup/to_label.rb
+++ b/lib/rdoc/markup/to_label.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'cgi'
+require 'cgi/util'
##
# Creates HTML-safe labels suitable for use in id attributes. Tidylinks are
diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb
index 3cdf4fd08b..2a9b05625c 100644
--- a/lib/rdoc/markup/to_rdoc.rb
+++ b/lib/rdoc/markup/to_rdoc.rb
@@ -330,31 +330,14 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
text_len = 20 if text_len < 20
- re = /^(.{0,#{text_len}})[ \n]/
next_prefix = ' ' * @indent
prefix = @prefix || next_prefix
@prefix = nil
- @res << prefix
-
- while text.length > text_len
- if text =~ re then
- @res << $1
- text.slice!(0, $&.length)
- else
- @res << text.slice!(0, text_len)
- end
-
- @res << "\n" << next_prefix
- end
-
- if text.empty? then
- @res.pop
- @res.pop
- else
- @res << text
- @res << "\n"
+ text.scan(/\G(?:([^ \n]{#{text_len}})(?=[^ \n])|(.{1,#{text_len}})(?:[ \n]|\z))/) do
+ @res << prefix << ($1 || $2) << "\n"
+ prefix = next_prefix
end
end
diff --git a/lib/rdoc/method_attr.rb b/lib/rdoc/method_attr.rb
index 3cef78c4a5..aae3c47e85 100644
--- a/lib/rdoc/method_attr.rb
+++ b/lib/rdoc/method_attr.rb
@@ -289,7 +289,7 @@ class RDoc::MethodAttr < RDoc::CodeObject
# HTML id-friendly method/attribute name
def html_name
- require 'cgi'
+ require 'cgi/util'
CGI.escape(@name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '')
end
diff --git a/lib/rdoc/normal_class.rb b/lib/rdoc/normal_class.rb
index 6729b18448..68dfa7d4a3 100644
--- a/lib/rdoc/normal_class.rb
+++ b/lib/rdoc/normal_class.rb
@@ -56,7 +56,7 @@ class RDoc::NormalClass < RDoc::ClassModule
def pretty_print q # :nodoc:
superclass = @superclass ? " < #{@superclass}" : nil
- q.group 2, "[class #{full_name}#{superclass} ", "]" do
+ q.group 2, "[class #{full_name}#{superclass}", "]" do
q.breakable
q.text "includes:"
q.breakable
diff --git a/lib/rdoc/normal_module.rb b/lib/rdoc/normal_module.rb
index 8f364be41c..edf29f8f1c 100644
--- a/lib/rdoc/normal_module.rb
+++ b/lib/rdoc/normal_module.rb
@@ -30,7 +30,7 @@ class RDoc::NormalModule < RDoc::ClassModule
end
def pretty_print q # :nodoc:
- q.group 2, "[module #{full_name}: ", "]" do
+ q.group 2, "[module #{full_name}:", "]" do
q.breakable
q.text "includes:"
q.breakable
diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb
index 13b7ba5c6c..eed0f6b39b 100644
--- a/lib/rdoc/options.rb
+++ b/lib/rdoc/options.rb
@@ -106,6 +106,7 @@ class RDoc::Options
generator_options
generators
op_dir
+ page_dir
option_parser
pipe
rdoc_include
@@ -338,6 +339,10 @@ class RDoc::Options
attr_reader :visibility
+ ##
+ # Indicates if files of test suites should be skipped
+ attr_accessor :skip_tests
+
def initialize loaded_options = nil # :nodoc:
init_ivars
override loaded_options if loaded_options
@@ -385,6 +390,7 @@ class RDoc::Options
@write_options = false
@encoding = Encoding::UTF_8
@charset = @encoding.name
+ @skip_tests = true
end
def init_with map # :nodoc:
@@ -434,6 +440,7 @@ class RDoc::Options
@main_page = map['main_page'] if map.has_key?('main_page')
@markup = map['markup'] if map.has_key?('markup')
@op_dir = map['op_dir'] if map.has_key?('op_dir')
+ @page_dir = map['page_dir'] if map.has_key?('page_dir')
@show_hash = map['show_hash'] if map.has_key?('show_hash')
@tab_width = map['tab_width'] if map.has_key?('tab_width')
@template_dir = map['template_dir'] if map.has_key?('template_dir')
@@ -513,19 +520,22 @@ class RDoc::Options
##
# For dumping YAML
- def encode_with coder # :nodoc:
+ def to_yaml(*options) # :nodoc:
encoding = @encoding ? @encoding.name : nil
- coder.add 'encoding', encoding
- coder.add 'static_path', sanitize_path(@static_path)
- coder.add 'rdoc_include', sanitize_path(@rdoc_include)
+ yaml = {}
+ yaml['encoding'] = encoding
+ yaml['static_path'] = sanitize_path(@static_path)
+ yaml['rdoc_include'] = sanitize_path(@rdoc_include)
+ yaml['page_dir'] = (sanitize_path([@page_dir]).first if @page_dir)
ivars = instance_variables.map { |ivar| ivar.to_s[1..-1] }
ivars -= SPECIAL
ivars.sort.each do |ivar|
- coder.add ivar, instance_variable_get("@#{ivar}")
+ yaml[ivar] = instance_variable_get("@#{ivar}")
end
+ yaml.to_yaml
end
##
@@ -548,6 +558,11 @@ class RDoc::Options
# #template.
def finish
+ if @write_options then
+ write_options
+ exit
+ end
+
@op_dir ||= 'doc'
@rdoc_include << "." if @rdoc_include.empty?
@@ -585,14 +600,14 @@ class RDoc::Options
def finish_page_dir
return unless @page_dir
- @files << @page_dir.to_s
+ @files << @page_dir
- page_dir = nil
+ page_dir = Pathname(@page_dir)
begin
- page_dir = @page_dir.expand_path.relative_path_from @root
+ page_dir = page_dir.expand_path.relative_path_from @root
rescue ArgumentError
# On Windows, sometimes crosses different drive letters.
- page_dir = @page_dir.expand_path
+ page_dir = page_dir.expand_path
end
@page_dir = page_dir
@@ -768,6 +783,13 @@ Usage: #{opt.program_name} [options] [names...]
opt.separator nil
+ opt.on("--no-skipping-tests", nil,
+ "Don't skip generating documentation for test and spec files") do |value|
+ @skip_tests = false
+ end
+
+ opt.separator nil
+
opt.on("--extension=NEW=OLD", "-E",
"Treat files ending with .new as if they",
"ended with .old. Using '-E cgi=rb' will",
@@ -847,7 +869,7 @@ Usage: #{opt.program_name} [options] [names...]
"such files at your project root.",
"NOTE: Do not use the same file name in",
"the page dir and the root of your project") do |page_dir|
- @page_dir = Pathname(page_dir)
+ @page_dir = page_dir
end
opt.separator nil
@@ -971,7 +993,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.on("--template-stylesheets=FILES", PathArray,
"Set (or add to) the list of files to",
"include with the html template.") do |value|
- @template_stylesheets << value
+ @template_stylesheets.concat value
end
opt.separator nil
@@ -1159,13 +1181,6 @@ Usage: #{opt.program_name} [options] [names...]
@files = argv.dup
- finish
-
- if @write_options then
- write_options
- exit
- end
-
self
end
@@ -1278,8 +1293,37 @@ Usage: #{opt.program_name} [options] [names...]
File.open '.rdoc_options', 'w' do |io|
io.set_encoding Encoding::UTF_8
- YAML.dump self, io
+ io.print to_yaml
end
end
+ ##
+ # Loads options from .rdoc_options if the file exists, otherwise creates a
+ # new RDoc::Options instance.
+
+ def self.load_options
+ options_file = File.expand_path '.rdoc_options'
+ return RDoc::Options.new unless File.exist? options_file
+
+ RDoc.load_yaml
+
+ begin
+ options = YAML.safe_load File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol]
+ rescue Psych::SyntaxError
+ raise RDoc::Error, "#{options_file} is not a valid rdoc options file"
+ end
+
+ return RDoc::Options.new unless options # Allow empty file.
+
+ raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
+ RDoc::Options === options or Hash === options
+
+ if Hash === options
+ # Override the default values with the contents of YAML file.
+ options = RDoc::Options.new options
+ end
+
+ options
+ end
+
end
diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
index 425bc48632..3bb6f5d1f2 100644
--- a/lib/rdoc/parser.rb
+++ b/lib/rdoc/parser.rb
@@ -263,9 +263,26 @@ class RDoc::Parser
@preprocess.options = @options
end
- autoload :RubyTools, 'rdoc/parser/ruby_tools'
- autoload :Text, 'rdoc/parser/text'
+ autoload :RubyTools, "#{__dir__}/parser/ruby_tools"
+ autoload :Text, "#{__dir__}/parser/text"
+ ##
+ # Normalizes tabs in +body+
+
+ def handle_tab_width(body)
+ if /\t/ =~ body
+ tab_width = @options.tab_width
+ body.split(/\n/).map do |line|
+ 1 while line.gsub!(/\t+/) do
+ b, e = $~.offset(0)
+ ' ' * (tab_width * (e-b) - b % tab_width)
+ end
+ line
+ end.join "\n"
+ else
+ body
+ end
+ end
end
# simple must come first in order to show up last in the parsers list
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 9d8db6cdee..5695bf1acb 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -122,6 +122,11 @@ class RDoc::Parser::C < RDoc::Parser
include RDoc::Text
+ # :stopdoc:
+ BOOL_ARG_PATTERN = /\s*+\b([01]|Q?(?:true|false)|TRUE|FALSE)\b\s*/
+ TRUE_VALUES = ['1', 'TRUE', 'true', 'Qtrue'].freeze
+ # :startdoc:
+
##
# Maps C variable names to names of Ruby classes or modules
@@ -173,6 +178,8 @@ class RDoc::Parser::C < RDoc::Parser
@classes = load_variable_map :c_class_variables
@singleton_classes = load_variable_map :c_singleton_class_variables
+ @markup = @options.markup
+
# class_variable => { function => [method, ...] }
@methods = Hash.new { |h, f| h[f] = Hash.new { |i, m| i[m] = [] } }
@@ -257,18 +264,18 @@ class RDoc::Parser::C < RDoc::Parser
@content.scan(/rb_attr\s*\(
\s*(\w+),
\s*([\w"()]+),
- \s*([01]),
- \s*([01]),
- \s*\w+\);/xm) do |var_name, attr_name, read, write|
+ #{BOOL_ARG_PATTERN},
+ #{BOOL_ARG_PATTERN},
+ \s*\w+\);/xmo) do |var_name, attr_name, read, write|
handle_attr var_name, attr_name, read, write
end
@content.scan(%r%rb_define_attr\(
\s*([\w\.]+),
\s*"([^"]+)",
- \s*(\d+),
- \s*(\d+)\s*\);
- %xm) do |var_name, attr_name, read, write|
+ #{BOOL_ARG_PATTERN},
+ #{BOOL_ARG_PATTERN}\);
+ %xmo) do |var_name, attr_name, read, write|
handle_attr var_name, attr_name, read, write
end
end
@@ -293,94 +300,92 @@ class RDoc::Parser::C < RDoc::Parser
@content.scan(
%r(
+ (?<open>\s*\(\s*) {0}
+ (?<close>\s*\)\s*) {0}
+ (?<name>\s*"(?<class_name>\w+)") {0}
+ (?<parent>\s*(?:
+ (?<parent_name>[\w\*\s\(\)\.\->]+) |
+ rb_path2class\s*\(\s*"(?<path>[\w:]+)"\s*\)
+ )) {0}
+ (?<under>\w+) {0}
+
(?<var_name>[\w\.]+)\s* =
\s*rb_(?:
define_(?:
- class(?: # rb_define_class(class_name_1, parent_name_1)
- \s*\(
- \s*"(?<class_name_1>\w+)",
- \s*(?<parent_name_1>\w+)\s*
- \)
- |
- _under\s*\( # rb_define_class_under(class_under, class_name2, parent_name2...)
- \s* (?<class_under>\w+),
- \s* "(?<class_name_2>\w+)",
- \s*
- (?:
- (?<parent_name_2>[\w\*\s\(\)\.\->]+) |
- rb_path2class\("(?<path>[\w:]+)"\)
- )
+ class(?: # rb_define_class(name, parent_name)
+ \(\s*
+ \g<name>,
+ \g<parent>
\s*\)
+ |
+ _under\g<open> # rb_define_class_under(under, name, parent_name...)
+ \g<under>,
+ \g<name>,
+ \g<parent>
+ \g<close>
)
|
- module(?: # rb_define_module(module_name_1)
- \s*\(
- \s*"(?<module_name_1>\w+)"\s*
- \)
+ (?<module>)
+ module(?: # rb_define_module(name)
+ \g<open>
+ \g<name>
+ \g<close>
|
- _under\s*\( # rb_define_module_under(module_under, module_name_2)
- \s*(?<module_under>\w+),
- \s*"(?<module_name_2>\w+)"
- \s*\)
+ _under\g<open> # rb_define_module_under(under, name)
+ \g<under>,
+ \g<name>
+ \g<close>
)
)
|
- struct_define_without_accessor\s*\( # rb_struct_define_without_accessor(class_name_3, parent_name_3, ...)
- \s*"(?<class_name_3>\w+)",
- \s*(?<parent_name_3>\w+),
- \s*\w+, # Allocation function
- (?:\s*"\w+",)* # Attributes
- \s*NULL
- \)
+ (?<attributes>(?:\s*"\w+",)*\s*NULL\s*) {0}
+ struct_define(?:
+ \g<open> # rb_struct_define(name, ...)
+ \g<name>,
+ |
+ _under\g<open> # rb_struct_define_under(under, name, ...)
+ \g<under>,
+ \g<name>,
+ |
+ _without_accessor(?:
+ \g<open> # rb_struct_define_without_accessor(name, parent_name, ...)
+ |
+ _under\g<open> # rb_struct_define_without_accessor_under(under, name, parent_name, ...)
+ \g<under>,
+ )
+ \g<name>,
+ \g<parent>,
+ \s*\w+, # Allocation function
+ )
+ \g<attributes>
+ \g<close>
|
- singleton_class\s*\( # rb_singleton_class(target_class_name)
- \s*(?<target_class_name>\w+)
- \)
+ singleton_class\g<open> # rb_singleton_class(target_class_name)
+ (?<target_class_name>\w+)
+ \g<close>
)
)mx
) do
- class_name = $~[:class_name_1]
- type = :class
- if class_name
- # rb_define_class(class_name_1, parent_name_1)
- parent_name = $~[:parent_name_1]
- #under = nil
- else
- class_name = $~[:class_name_2]
- if class_name
- # rb_define_class_under(class_under, class_name2, parent_name2...)
- parent_name = $~[:parent_name_2] || $~[:path]
- under = $~[:class_under]
- else
- class_name = $~[:class_name_3]
- if class_name
- # rb_struct_define_without_accessor(class_name_3, parent_name_3, ...)
- parent_name = $~[:parent_name_3]
- #under = nil
- else
- type = :module
- class_name = $~[:module_name_1]
- #parent_name = nil
- if class_name
- # rb_define_module(module_name_1)
- #under = nil
- else
- class_name = $~[:module_name_2]
- if class_name
- # rb_define_module_under(module_under, module_name_1)
- under = $~[:module_under]
- else
- # rb_singleton_class(target_class_name)
- target_class_name = $~[:target_class_name]
- handle_singleton $~[:var_name], target_class_name
- next
- end
- end
- end
- end
+ if target_class_name = $~[:target_class_name]
+ # rb_singleton_class(target_class_name)
+ handle_singleton $~[:var_name], target_class_name
+ next
end
- handle_class_module($~[:var_name], type, class_name, parent_name, under)
+ var_name = $~[:var_name]
+ type = $~[:module] ? :module : :class
+ class_name = $~[:class_name]
+ parent_name = $~[:parent_name] || $~[:path]
+ under = $~[:under]
+ attributes = $~[:attributes]
+
+ handle_class_module(var_name, type, class_name, parent_name, under)
+ if attributes and !parent_name # rb_struct_define *not* without_accessor
+ true_flag = 'Qtrue'
+ attributes.scan(/"\K\w+(?=")/) do |attr_name|
+ handle_attr var_name, attr_name, true_flag, true_flag
+ end
+ end
end
end
@@ -439,7 +444,7 @@ class RDoc::Parser::C < RDoc::Parser
next unless cls = @classes[c]
m = @known_classes[m] || m
- comment = RDoc::Comment.new '', @top_level, :c
+ comment = new_comment '', @top_level, :c
incl = cls.add_include RDoc::Include.new(m, comment)
incl.record_location @top_level
end
@@ -521,7 +526,7 @@ class RDoc::Parser::C < RDoc::Parser
\s*"#{Regexp.escape new_name}"\s*,
\s*"#{Regexp.escape old_name}"\s*\);%xm
- RDoc::Comment.new($1 || '', @top_level, :c)
+ new_comment($1 || '', @top_level, :c)
end
##
@@ -560,7 +565,7 @@ class RDoc::Parser::C < RDoc::Parser
''
end
- RDoc::Comment.new comment, @top_level, :c
+ new_comment comment, @top_level, :c
end
##
@@ -600,7 +605,7 @@ class RDoc::Parser::C < RDoc::Parser
case type
when :func_def
- comment = RDoc::Comment.new args[0], @top_level, :c
+ comment = new_comment args[0], @top_level, :c
body = args[1]
offset, = args[2]
@@ -630,7 +635,7 @@ class RDoc::Parser::C < RDoc::Parser
body
when :macro_def
- comment = RDoc::Comment.new args[0], @top_level, :c
+ comment = new_comment args[0], @top_level, :c
body = args[1]
offset, = args[2]
@@ -675,13 +680,14 @@ class RDoc::Parser::C < RDoc::Parser
##
# Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+
- def find_class(raw_name, name)
+ def find_class(raw_name, name, base_name = nil)
unless @classes[raw_name]
if raw_name =~ /^rb_m/
container = @top_level.add_module RDoc::NormalModule, name
else
container = @top_level.add_class RDoc::NormalClass, name
end
+ container.name = base_name if base_name
container.record_location @top_level
@classes[raw_name] = container
@@ -722,7 +728,7 @@ class RDoc::Parser::C < RDoc::Parser
((?>/\*.*?\*/\s+))
(static\s+)?
void\s+
- Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xmi then
+ Init(?:VM)?_(?i:#{class_name})\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xm then
comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '')
elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*?
(?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then
@@ -737,7 +743,7 @@ class RDoc::Parser::C < RDoc::Parser
comment = ''
end
- comment = RDoc::Comment.new comment, @top_level, :c
+ comment = new_comment comment, @top_level, :c
comment.normalize
look_for_directives_in class_mod, comment
@@ -782,7 +788,7 @@ class RDoc::Parser::C < RDoc::Parser
table[const_name] ||
''
- RDoc::Comment.new comment, @top_level, :c
+ new_comment comment, @top_level, :c
end
##
@@ -813,7 +819,7 @@ class RDoc::Parser::C < RDoc::Parser
return unless comment
- RDoc::Comment.new comment, @top_level, :c
+ new_comment comment, @top_level, :c
end
##
@@ -822,8 +828,8 @@ class RDoc::Parser::C < RDoc::Parser
def handle_attr(var_name, attr_name, read, write)
rw = ''
- rw += 'R' if '1' == read
- rw += 'W' if '1' == write
+ rw += 'R' if TRUE_VALUES.include?(read)
+ rw += 'W' if TRUE_VALUES.include?(write)
class_name = @known_classes[var_name]
@@ -919,7 +925,7 @@ class RDoc::Parser::C < RDoc::Parser
return unless class_name
- class_obj = find_class var_name, class_name
+ class_obj = find_class var_name, class_name, class_name[/::\K[^:]+\z/]
unless class_obj then
@options.warn 'Enclosing class or module %p is not known' % [const_name]
@@ -947,7 +953,7 @@ class RDoc::Parser::C < RDoc::Parser
new_comment = "#{$1}#{new_comment.lstrip}"
- new_comment = RDoc::Comment.new new_comment, @top_level, :c
+ new_comment = self.new_comment(new_comment, @top_level, :c)
con = RDoc::Constant.new const_name, new_definition, new_comment
else
@@ -1023,12 +1029,18 @@ class RDoc::Parser::C < RDoc::Parser
elsif p_count == -1 then # argc, argv
rb_scan_args body
else
- "(#{(1..p_count).map { |i| "p#{i}" }.join ', '})"
+ args = (1..p_count).map { |i| "p#{i}" }
+ "(#{args.join ', '})"
end
meth_obj.record_location @top_level
+
+ if meth_obj.section_title
+ class_obj.temporary_section = class_obj.add_section(meth_obj.section_title)
+ end
class_obj.add_method meth_obj
+
@stats.add_method meth_obj
meth_obj.visibility = :private if 'private_method' == type
end
@@ -1046,23 +1058,6 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # Normalizes tabs in +body+
-
- def handle_tab_width(body)
- if /\t/ =~ body
- tab_width = @options.tab_width
- body.split(/\n/).map do |line|
- 1 while line.gsub!(/\t+/) do
- ' ' * (tab_width * $&.length - $`.length % tab_width)
- end && $~
- line
- end.join "\n"
- else
- body
- end
- end
-
- ##
# Loads the variable map with the given +name+ from the RDoc::Store, if
# present.
@@ -1222,4 +1217,9 @@ class RDoc::Parser::C < RDoc::Parser
@top_level
end
+ def new_comment text = nil, location = nil, language = nil
+ RDoc::Comment.new(text, location, language).tap do |comment|
+ comment.format = @markup
+ end
+ end
end
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index e546fe2141..b74ead65ab 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -164,15 +164,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
def initialize(top_level, file_name, content, options, stats)
super
- if /\t/ =~ content then
- tab_width = @options.tab_width
- content = content.split(/\n/).map do |line|
- 1 while line.gsub!(/\t+/) {
- ' ' * (tab_width*$&.length - $`.length % tab_width)
- } && $~
- line
- end.join("\n")
- end
+ content = handle_tab_width(content)
@size = 0
@token_listeners = nil
@@ -400,6 +392,29 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
##
+ # Skip opening parentheses and yield the block.
+ # Skip closing parentheses too when exists.
+
+ def skip_parentheses(&block)
+ left_tk = peek_tk
+
+ if :on_lparen == left_tk[:kind]
+ get_tk
+
+ ret = skip_parentheses(&block)
+
+ right_tk = peek_tk
+ if :on_rparen == right_tk[:kind]
+ get_tk
+ end
+
+ ret
+ else
+ yield
+ end
+ end
+
+ ##
# Return a superclass, which can be either a constant of an expression
def get_class_specification
@@ -833,7 +848,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
cls = parse_class_regular container, declaration_context, single,
name_t, given_name, comment
elsif name_t[:kind] == :on_op && name_t[:text] == '<<'
- case name = get_class_specification
+ case name = skip_parentheses { get_class_specification }
when 'self', container.name
read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
parse_statements container, SINGLE
diff --git a/lib/rdoc/rd.rb b/lib/rdoc/rd.rb
index 0d3d3cea85..8c2366a3ca 100644
--- a/lib/rdoc/rd.rb
+++ b/lib/rdoc/rd.rb
@@ -92,9 +92,8 @@ class RDoc::RD
document
end
- autoload :BlockParser, 'rdoc/rd/block_parser'
- autoload :InlineParser, 'rdoc/rd/inline_parser'
- autoload :Inline, 'rdoc/rd/inline'
+ autoload :BlockParser, "#{__dir__}/rd/block_parser"
+ autoload :InlineParser, "#{__dir__}/rd/inline_parser"
+ autoload :Inline, "#{__dir__}/rd/inline"
end
-
diff --git a/lib/rdoc/rd/block_parser.rb b/lib/rdoc/rd/block_parser.rb
index 462ba869a2..6f70622c0b 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.5.2
+# This file is automatically generated by Racc 1.6.0
# from Racc grammar file "".
#
@@ -18,8 +18,6 @@ class BlockParser < Racc::Parser
# :stopdoc:
-TMPFILE = ["rdtmp", $$, 0]
-
MARK_TO_LEVEL = {
'=' => 1,
'==' => 2,
@@ -129,15 +127,19 @@ def next_token # :nodoc:
# non-RD part begin
when /^=begin\s+(\w+)/
part = $1
+=begin # not imported to RDoc
if @in_part # if in non-RD part
@part_content.push(line)
else
@in_part = part if @tree.filter[part] # if filter exists
# p "BEGIN_PART: #{@in_part}" # DEBUG
end
+=end
+ @in_part = part
# non-RD part end
- when /^=end/
+ when /^=end(?:$|[\s\0\C-d\C-z])/
if @in_part # if in non-RD part
+=begin # not imported to RDoc
# p "END_PART: #{@in_part}" # DEBUG
# make Part-in object
part = RDoc::RD::Part.new(@part_content.join(""), @tree, "r")
@@ -148,20 +150,22 @@ def next_token # :nodoc:
if @tree.filter[@in_part].mode == :rd # if output is RD formatted
subtree = parse_subtree(part_out.to_a)
else # if output is target formatted
- basename = TMPFILE.join('.')
- TMPFILE[-1] += 1
- tmpfile = open(@tree.tmp_dir + "/" + basename + ".#{@in_part}", "w")
- tmpfile.print(part_out)
- tmpfile.close
+ basename = Tempfile.create(["rdtmp", ".#{@in_part}"], @tree.tmp_dir) do |tmpfile|
+ tmpfile.print(part_out)
+ File.basename(tmpfile.path)
+ end
subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"])
end
@in_part = nil
return [:SUBTREE, subtree]
+=end
end
else
+=begin # not imported to RDoc
if @in_part # if in non-RD part
@part_content.push(line)
end
+=end
end
end
diff --git a/lib/rdoc/rd/inline_parser.rb b/lib/rdoc/rd/inline_parser.rb
index 8f4c2c31ef..c1da35a109 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.5.2
+# This file is automatically generated by Racc 1.6.0
# from Racc grammar file "".
#
diff --git a/lib/rdoc/rdoc.gemspec b/lib/rdoc/rdoc.gemspec
index 525a15fcde..3c96f7deb1 100644
--- a/lib/rdoc/rdoc.gemspec
+++ b/lib/rdoc/rdoc.gemspec
@@ -38,16 +38,12 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
"CVE-2013-0256.rdoc",
"ExampleMarkdown.md",
"ExampleRDoc.rdoc",
- "Gemfile",
"History.rdoc",
"LEGAL.rdoc",
"LICENSE.rdoc",
"README.rdoc",
"RI.rdoc",
- "Rakefile",
"TODO.rdoc",
- "bin/console",
- "bin/setup",
"exe/rdoc",
"exe/ri",
"lib/rdoc.rb",
@@ -223,24 +219,12 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
"lib/rdoc/top_level.rb",
"lib/rdoc/version.rb",
"man/ri.1",
- "rdoc.gemspec",
]
# files from .gitignore
s.files << "lib/rdoc/rd/block_parser.rb" << "lib/rdoc/rd/inline_parser.rb" << "lib/rdoc/markdown.rb" << "lib/rdoc/markdown/literals.rb"
s.rdoc_options = ["--main", "README.rdoc"]
- s.extra_rdoc_files += %w[
- CVE-2013-0256.rdoc
- CONTRIBUTING.rdoc
- ExampleMarkdown.md
- ExampleRDoc.rdoc
- History.rdoc
- LEGAL.rdoc
- LICENSE.rdoc
- README.rdoc
- RI.rdoc
- TODO.rdoc
- ]
+ s.extra_rdoc_files += s.files.grep(%r[\A[^\/]+\.(?:rdoc|md)\z])
s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
s.required_rubygems_version = Gem::Requirement.new(">= 2.2")
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index 3a3defacb6..2d8a9dea8c 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rdoc'
+require_relative '../rdoc'
require 'find'
require 'fileutils'
@@ -14,7 +14,7 @@ require 'time'
# is:
#
# rdoc = RDoc::RDoc.new
-# options = rdoc.load_options # returns an RDoc::Options instance
+# options = RDoc::Options.load_options # returns an RDoc::Options instance
# # set extra options
# rdoc.document options
#
@@ -36,6 +36,17 @@ class RDoc::RDoc
GENERATORS = {}
##
+ # List of directory names always skipped
+
+ UNCONDITIONALLY_SKIPPED_DIRECTORIES = %w[CVS .svn .git].freeze
+
+ ##
+ # List of directory names skipped if test suites should be skipped
+
+ TEST_SUITE_DIRECTORY_NAMES = %w[spec test].freeze
+
+
+ ##
# Generator instance used for creating output
attr_accessor :generator
@@ -152,35 +163,6 @@ class RDoc::RDoc
end
##
- # Loads options from .rdoc_options if the file exists, otherwise creates a
- # new RDoc::Options instance.
-
- def load_options
- options_file = File.expand_path '.rdoc_options'
- return RDoc::Options.new unless File.exist? options_file
-
- RDoc.load_yaml
-
- begin
- options = YAML.safe_load File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol]
- rescue Psych::SyntaxError
- raise RDoc::Error, "#{options_file} is not a valid rdoc options file"
- end
-
- return RDoc::Options.new unless options # Allow empty file.
-
- raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
- RDoc::Options === options or Hash === options
-
- if Hash === options
- # Override the default values with the contents of YAML file.
- options = RDoc::Options.new options
- end
-
- options
- end
-
- ##
# Create an output dir if it doesn't exist. If it does exist, but doesn't
# contain the flag file <tt>created.rid</tt> then we refuse to use it, as
# we may clobber some manually generated documentation
@@ -309,7 +291,10 @@ option)
file_list[rel_file_name] = mtime
end
when "directory" then
- next if rel_file_name == "CVS" || rel_file_name == ".svn"
+ next if UNCONDITIONALLY_SKIPPED_DIRECTORIES.include?(rel_file_name)
+
+ basename = File.basename(rel_file_name)
+ next if options.skip_tests && TEST_SUITE_DIRECTORY_NAMES.include?(basename)
created_rid = File.join rel_file_name, "created.rid"
next if File.file? created_rid
@@ -469,11 +454,11 @@ The internal error was:
if RDoc::Options === options then
@options = options
- @options.finish
else
- @options = load_options
+ @options = RDoc::Options.load_options
@options.parse options
end
+ @options.finish
if @options.pipe then
handle_pipe
diff --git a/lib/rdoc/ri.rb b/lib/rdoc/ri.rb
index c798c1fc49..0af05f729f 100644
--- a/lib/rdoc/ri.rb
+++ b/lib/rdoc/ri.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rdoc'
+require_relative '../rdoc'
##
# Namespace for the ri command line tool's implementation.
@@ -13,9 +13,8 @@ module RDoc::RI
class Error < RDoc::Error; end
- autoload :Driver, 'rdoc/ri/driver'
- autoload :Paths, 'rdoc/ri/paths'
- autoload :Store, 'rdoc/ri/store'
+ autoload :Driver, "#{__dir__}/ri/driver"
+ autoload :Paths, "#{__dir__}/ri/paths"
+ autoload :Store, "#{__dir__}/ri/store"
end
-
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index 7549a39203..819cff8aa3 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -1,23 +1,10 @@
# frozen_string_literal: true
-require 'abbrev'
require 'optparse'
-begin
- require 'readline'
-rescue LoadError
-end
-
-begin
- require 'win32console'
-rescue LoadError
-end
-
-require 'rdoc'
-
-##
-# For RubyGems backwards compatibility
+require_relative '../../rdoc'
-require_relative 'formatter'
+require_relative 'formatter' # For RubyGems backwards compatibility
+# TODO: Fix weird documentation with `require_relative`
##
# The RI driver implements the command-line ri tool.
@@ -433,9 +420,6 @@ or the PAGER environment variable.
@use_stdout = options[:use_stdout]
@show_all = options[:show_all]
@width = options[:width]
-
- # pager process for jruby
- @jruby_pager_process = nil
end
##
@@ -1052,36 +1036,6 @@ or the PAGER environment variable.
end
##
- # Finds the given +pager+ for jruby. Returns an IO if +pager+ was found.
- #
- # Returns false if +pager+ does not exist.
- #
- # Returns nil if the jruby JVM doesn't support ProcessBuilder redirection
- # (1.6 and older).
-
- def find_pager_jruby pager
- require 'java'
- require 'shellwords'
-
- return nil unless java.lang.ProcessBuilder.constants.include? :Redirect
-
- pager = Shellwords.split pager
-
- pb = java.lang.ProcessBuilder.new(*pager)
- pb = pb.redirect_output java.lang.ProcessBuilder::Redirect::INHERIT
-
- @jruby_pager_process = pb.start
-
- input = @jruby_pager_process.output_stream
-
- io = input.to_io
- io.sync = true
- io
- rescue java.io.IOException
- false
- end
-
- ##
# Finds a store that matches +name+ which can be the name of a gem, "ruby",
# "home" or "site".
#
@@ -1120,6 +1074,10 @@ or the PAGER environment variable.
def interactive
puts "\nEnter the method name you want to look up."
+ begin
+ require 'readline'
+ rescue LoadError
+ end
if defined? Readline then
Readline.completion_proc = method :complete
puts "You can use tab to autocomplete."
@@ -1149,17 +1107,6 @@ or the PAGER environment variable.
end
##
- # Is +file+ in ENV['PATH']?
-
- def in_path? file
- return true if file =~ %r%\A/% and File.exist? file
-
- ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path|
- File.exist? File.join(path, file)
- end
- end
-
- ##
# Lists classes known to ri starting with +names+. If +names+ is empty all
# known classes are shown.
@@ -1353,7 +1300,6 @@ or the PAGER environment variable.
yield pager
ensure
pager.close
- @jruby_pager_process.wait_for if @jruby_pager_process
end
else
yield $stdout
@@ -1521,27 +1467,14 @@ or the PAGER environment variable.
def setup_pager
return if @use_stdout
- jruby = RUBY_ENGINE == 'jruby'
-
pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more']
+ require 'shellwords'
pagers.compact.uniq.each do |pager|
- next unless pager
-
- pager_cmd = pager.split(' ').first
-
- next unless in_path? pager_cmd
-
- if jruby then
- case io = find_pager_jruby(pager)
- when nil then break
- when false then next
- else io
- end
- else
- io = IO.popen(pager, 'w') rescue next
- end
+ pager = Shellwords.split(pager)
+ next if pager.empty?
+ io = IO.popen(pager, 'w') rescue next
next if $? and $?.pid == io.pid and $?.exited? # pager didn't work
@paging = true
diff --git a/lib/rdoc/rubygems_hook.rb b/lib/rdoc/rubygems_hook.rb
index 3781ff9858..3160072e53 100644
--- a/lib/rdoc/rubygems_hook.rb
+++ b/lib/rdoc/rubygems_hook.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'rubygems/user_interaction'
require 'fileutils'
-require 'rdoc'
+require_relative '../rdoc'
##
# Gem::RDoc provides methods to generate RDoc and ri data for installed gems
diff --git a/lib/rdoc/servlet.rb b/lib/rdoc/servlet.rb
index 0ab1eaf19d..d05368766a 100644
--- a/lib/rdoc/servlet.rb
+++ b/lib/rdoc/servlet.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rdoc'
+require_relative '../rdoc'
require 'erb'
require 'time'
require 'json'
diff --git a/lib/rdoc/single_class.rb b/lib/rdoc/single_class.rb
index 6a7b67deb3..860f06a6e5 100644
--- a/lib/rdoc/single_class.rb
+++ b/lib/rdoc/single_class.rb
@@ -22,5 +22,10 @@ class RDoc::SingleClass < RDoc::ClassModule
"class << #{full_name}"
end
+ def pretty_print q # :nodoc:
+ q.group 2, "[class << #{full_name}", "]" do
+ next
+ end
+ end
end
diff --git a/lib/rdoc/stats.rb b/lib/rdoc/stats.rb
index bd6c0ef23a..4817c9c729 100644
--- a/lib/rdoc/stats.rb
+++ b/lib/rdoc/stats.rb
@@ -454,9 +454,8 @@ class RDoc::Stats
[params.length, undoc]
end
- autoload :Quiet, 'rdoc/stats/quiet'
- autoload :Normal, 'rdoc/stats/normal'
- autoload :Verbose, 'rdoc/stats/verbose'
+ autoload :Quiet, "#{__dir__}/stats/quiet"
+ autoload :Normal, "#{__dir__}/stats/normal"
+ autoload :Verbose, "#{__dir__}/stats/verbose"
end
-
diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
index 5ba671ca1b..c793e49ed8 100644
--- a/lib/rdoc/store.rb
+++ b/lib/rdoc/store.rb
@@ -556,9 +556,7 @@ class RDoc::Store
def load_cache
#orig_enc = @encoding
- File.open cache_path, 'rb' do |io|
- @cache = Marshal.load io.read
- end
+ @cache = marshal_load(cache_path)
load_enc = @cache[:encoding]
@@ -615,9 +613,7 @@ class RDoc::Store
def load_class_data klass_name
file = class_file klass_name
- File.open file, 'rb' do |io|
- Marshal.load io.read
- end
+ marshal_load(file)
rescue Errno::ENOENT => e
error = MissingFileError.new(self, file, klass_name)
error.set_backtrace e.backtrace
@@ -630,14 +626,10 @@ class RDoc::Store
def load_method klass_name, method_name
file = method_file klass_name, method_name
- File.open file, 'rb' do |io|
- obj = Marshal.load io.read
- obj.store = self
- obj.parent =
- find_class_or_module(klass_name) || load_class(klass_name) unless
- obj.parent
- obj
- end
+ obj = marshal_load(file)
+ obj.store = self
+ obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name)
+ obj
rescue Errno::ENOENT => e
error = MissingFileError.new(self, file, klass_name + method_name)
error.set_backtrace e.backtrace
@@ -650,11 +642,9 @@ class RDoc::Store
def load_page page_name
file = page_file page_name
- File.open file, 'rb' do |io|
- obj = Marshal.load io.read
- obj.store = self
- obj
- end
+ obj = marshal_load(file)
+ obj.store = self
+ obj
rescue Errno::ENOENT => e
error = MissingFileError.new(self, file, page_name)
error.set_backtrace e.backtrace
@@ -976,4 +966,21 @@ class RDoc::Store
@unique_modules
end
+ private
+ def marshal_load(file)
+ File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)}
+ end
+
+ MarshalFilter = proc do |obj|
+ case obj
+ when true, false, nil, Array, Class, Encoding, Hash, Integer, String, Symbol, RDoc::Text
+ else
+ unless obj.class.name.start_with?("RDoc::")
+ raise TypeError, "not permitted class: #{obj.class.name}"
+ end
+ end
+ obj
+ end
+ private_constant :MarshalFilter
+
end
diff --git a/lib/rdoc/task.rb b/lib/rdoc/task.rb
index 0bedaa50b0..8ea2d0588c 100644
--- a/lib/rdoc/task.rb
+++ b/lib/rdoc/task.rb
@@ -32,7 +32,7 @@ begin
rescue Gem::LoadError
end unless defined?(Rake)
-require 'rdoc'
+require_relative '../rdoc'
require 'rake'
require 'rake/tasklib'
@@ -71,7 +71,7 @@ require 'rake/tasklib'
# require 'rdoc/task'
#
# RDoc::Task.new :rdoc_dev do |rdoc|
-# rdoc.main = "README.doc"
+# rdoc.main = "README.rdoc"
# rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb")
# rdoc.options << "--all"
# end
@@ -323,7 +323,7 @@ module Rake
##
# For backwards compatibility
- RDocTask = RDoc::Task
+ RDocTask = RDoc::Task # :nodoc:
end
# :startdoc:
diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb
index c3218fdb2f..0bc4aba428 100644
--- a/lib/rdoc/text.rb
+++ b/lib/rdoc/text.rb
@@ -218,10 +218,10 @@ module RDoc::Text
when s.scan(/\.\.\.(\.?)/) then
html << s[1] << encoded[:ellipsis]
after_word = nil
- when s.scan(/\(c\)/) then
+ when s.scan(/\(c\)/i) then
html << encoded[:copyright]
after_word = nil
- when s.scan(/\(r\)/) then
+ when s.scan(/\(r\)/i) then
html << encoded[:trademark]
after_word = nil
when s.scan(/---/) then
@@ -237,10 +237,18 @@ module RDoc::Text
when s.scan(/``/) then # backtick double quote
html << encoded[:open_dquote]
after_word = nil
- when s.scan(/''/) then # tick double quote
+ when s.scan(/(?:&#39;|'){2}/) then # tick double quote
html << encoded[:close_dquote]
after_word = nil
- when s.scan(/'/) then # single quote
+ when s.scan(/`/) then # backtick
+ if insquotes or after_word
+ html << '`'
+ after_word = false
+ else
+ html << encoded[:open_squote]
+ insquotes = true
+ end
+ when s.scan(/&#39;|'/) then # single quote
if insquotes
html << encoded[:close_squote]
insquotes = false
diff --git a/lib/rdoc/version.rb b/lib/rdoc/version.rb
index a3ef62d6be..31c1aa0276 100644
--- a/lib/rdoc/version.rb
+++ b/lib/rdoc/version.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module RDoc
##
# RDoc version you are using
- VERSION = '6.3.2'
+ VERSION = '6.5.1.1'
end
diff --git a/lib/readline.gemspec b/lib/readline.gemspec
index 69d76954fa..3a18f9edb6 100644
--- a/lib/readline.gemspec
+++ b/lib/readline.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = 'readline'
- spec.version = '0.0.2'
+ spec.version = '0.0.3'
spec.authors = ['aycabta']
spec.email = ['aycabta@gmail.com']
diff --git a/lib/readline.rb b/lib/readline.rb
index 6cc923cb2f..29cdf3a14f 100644
--- a/lib/readline.rb
+++ b/lib/readline.rb
@@ -2,5 +2,6 @@ begin
require 'readline.so'
rescue LoadError
require 'reline' unless defined? Reline
+ Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
Readline = Reline
end
diff --git a/lib/reline.rb b/lib/reline.rb
index d68627dca5..7800a281ce 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -16,8 +16,35 @@ module Reline
class ConfigEncodingConversionError < StandardError; end
- Key = Struct.new('Key', :char, :combined_char, :with_meta)
+ Key = Struct.new('Key', :char, :combined_char, :with_meta) do
+ def match?(other)
+ case other
+ when Reline::Key
+ (other.char.nil? or char.nil? or char == other.char) and
+ (other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
+ (other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
+ when Integer, Symbol
+ (combined_char and combined_char == other) or
+ (combined_char.nil? and char and char == other)
+ else
+ false
+ end
+ end
+ alias_method :==, :match?
+ end
CursorPos = Struct.new(:x, :y)
+ DialogRenderInfo = Struct.new(
+ :pos,
+ :contents,
+ :bg_color,
+ :pointer_bg_color,
+ :fg_color,
+ :pointer_fg_color,
+ :width,
+ :height,
+ :scrollbar,
+ keyword_init: true
+ )
class Core
ATTR_READER_NAMES = %i(
@@ -42,8 +69,14 @@ module Reline
attr_accessor :last_incremental_search
attr_reader :output
+ extend Forwardable
+ def_delegators :config,
+ :autocompletion,
+ :autocompletion=
+
def initialize
self.output = STDOUT
+ @dialog_proc_list = {}
yield self
@completion_quote_character = nil
@bracketed_paste_finished = false
@@ -130,6 +163,17 @@ module Reline
@dig_perfect_match_proc = p
end
+ DialogProc = Struct.new(:dialog_proc, :context)
+ def add_dialog_proc(name_sym, p, context = nil)
+ raise ArgumentError unless p.respond_to?(:call) or p.nil?
+ raise ArgumentError unless name_sym.instance_of?(Symbol)
+ @dialog_proc_list[name_sym] = DialogProc.new(p, context)
+ end
+
+ def dialog_proc(name_sym)
+ @dialog_proc_list[name_sym]
+ end
+
def input=(val)
raise TypeError unless val.respond_to?(:getc) or val.nil?
if val.respond_to?(:getc)
@@ -171,6 +215,55 @@ module Reline
Reline::IOGate.get_screen_size
end
+ Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
+ # autocomplete
+ return nil unless config.autocompletion
+ if just_cursor_moving and completion_journey_data.nil?
+ # Auto complete starts only when edited
+ return nil
+ end
+ pre, target, post = retrieve_completion_block(true)
+ if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
+ return nil
+ end
+ if completion_journey_data and completion_journey_data.list
+ result = completion_journey_data.list.dup
+ result.shift
+ pointer = completion_journey_data.pointer - 1
+ else
+ result = call_completion_proc_with_checking_args(pre, target, post)
+ pointer = nil
+ end
+ if result and result.size == 1 and result[0] == target and pointer != 0
+ result = nil
+ end
+ target_width = Reline::Unicode.calculate_width(target)
+ x = cursor_pos.x - target_width
+ if x < 0
+ x = screen_width + x
+ y = -1
+ else
+ y = 0
+ end
+ cursor_pos_to_render = Reline::CursorPos.new(x, y)
+ if context and context.is_a?(Array)
+ context.clear
+ context.push(cursor_pos_to_render, result, pointer, dialog)
+ end
+ dialog.pointer = pointer
+ DialogRenderInfo.new(
+ pos: cursor_pos_to_render,
+ contents: result,
+ scrollbar: true,
+ height: 15,
+ bg_color: 46,
+ pointer_bg_color: 45,
+ fg_color: 37,
+ pointer_fg_color: 37
+ )
+ }
+ Reline::DEFAULT_DIALOG_CONTEXT = Array.new
+
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
unless confirm_multiline_termination
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
@@ -230,6 +323,9 @@ module Reline
line_editor.auto_indent_proc = auto_indent_proc
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
line_editor.pre_input_hook = pre_input_hook
+ @dialog_proc_list.each_pair do |name_sym, d|
+ line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
+ end
unless config.test_mode
config.read
@@ -240,6 +336,7 @@ module Reline
line_editor.rerender
begin
+ line_editor.set_signal_handlers
prev_pasting_state = false
loop do
prev_pasting_state = Reline::IOGate.in_pasting?
@@ -268,6 +365,11 @@ module Reline
line_editor.finalize
Reline::IOGate.deprep(otio)
raise e
+ rescue Exception
+ # Including Interrupt
+ line_editor.finalize
+ Reline::IOGate.deprep(otio)
+ raise
end
line_editor.finalize
@@ -303,25 +405,9 @@ module Reline
break
when :matching
if buffer.size == 1
- begin
- succ_c = nil
- Timeout.timeout(keyseq_timeout / 1000.0) {
- succ_c = Reline::IOGate.getc
- }
- rescue Timeout::Error # cancel matching only when first byte
- block.([Reline::Key.new(c, c, false)])
- break
- else
- if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
- if c == "\e".ord
- block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
- else
- block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
- end
- break
- else
- Reline::IOGate.ungetc(succ_c)
- end
+ case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
+ when :break then break
+ when :next then next
end
end
when :unmatched
@@ -338,6 +424,38 @@ module Reline
end
end
+ private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
+ begin
+ succ_c = nil
+ Timeout.timeout(keyseq_timeout / 1000.0) {
+ succ_c = Reline::IOGate.getc
+ }
+ rescue Timeout::Error # cancel matching only when first byte
+ block.([Reline::Key.new(c, c, false)])
+ return :break
+ else
+ case key_stroke.match_status(buffer.dup.push(succ_c))
+ when :unmatched
+ if c == "\e".ord
+ block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
+ else
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
+ end
+ return :break
+ when :matching
+ Reline::IOGate.ungetc(succ_c)
+ return :next
+ when :matched
+ buffer << succ_c
+ expanded = key_stroke.expand(buffer).map{ |expanded_c|
+ Reline::Key.new(expanded_c, expanded_c, false)
+ }
+ block.(expanded)
+ return :break
+ end
+ end
+ end
+
private def read_escaped_key(keyseq_timeout, c, block)
begin
escaped_c = nil
@@ -365,8 +483,8 @@ module Reline
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
+ @ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or !STDOUT.tty?
+ return if defined? @ambiguous_width
Reline::IOGate.move_cursor_column(0)
begin
output.write "\u{25bd}"
@@ -389,7 +507,7 @@ module Reline
#--------------------------------------------------------
(Core::ATTR_READER_NAMES).each { |name|
- def_single_delegators :core, "#{name}", "#{name}="
+ def_single_delegators :core, :"#{name}", :"#{name}="
}
def_single_delegators :core, :input=, :output=
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
@@ -424,6 +542,9 @@ module Reline
def_single_delegators :core, :ambiguous_width
def_single_delegators :core, :last_incremental_search
def_single_delegators :core, :last_incremental_search=
+ def_single_delegators :core, :add_dialog_proc
+ def_single_delegators :core, :dialog_proc
+ def_single_delegators :core, :autocompletion, :autocompletion=
def_single_delegators :core, :readmultiline
def_instance_delegators self, :readmultiline
@@ -445,6 +566,7 @@ module Reline
core.completer_quote_characters = '"\''
core.filename_quote_characters = ""
core.special_prefixes = ""
+ core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT)
}
end
@@ -458,24 +580,21 @@ module Reline
end
require 'reline/general_io'
-if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
- require 'reline/windows'
- if Reline::Windows.msys_tty?
- Reline::IOGate = if ENV['TERM'] == 'dumb'
- Reline::GeneralIO
- else
- require 'reline/ansi'
- Reline::ANSI
- end
+io = Reline::GeneralIO
+unless ENV['TERM'] == 'dumb'
+ case RbConfig::CONFIG['host_os']
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
+ require 'reline/windows'
+ tty = (io = Reline::Windows).msys_tty?
else
- Reline::IOGate = Reline::Windows
+ tty = $stdout.tty?
end
+end
+Reline::IOGate = if tty
+ require 'reline/ansi'
+ Reline::ANSI
else
- Reline::IOGate = if $stdout.isatty
- require 'reline/ansi'
- Reline::ANSI
- else
- Reline::GeneralIO
- end
+ io
end
+
Reline::HISTORY = Reline::History.new(Reline.core.config)
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
index 09bd95662a..c40085e50d 100644
--- a/lib/reline/ansi.rb
+++ b/lib/reline/ansi.rb
@@ -4,6 +4,19 @@ require 'timeout'
require_relative 'terminfo'
class Reline::ANSI
+ CAPNAME_KEY_BINDINGS = {
+ 'khome' => :ed_move_to_beg,
+ 'kend' => :ed_move_to_end,
+ 'kcuu1' => :ed_prev_history,
+ 'kcud1' => :ed_next_history,
+ 'kcuf1' => :ed_next_char,
+ 'kcub1' => :ed_prev_char,
+ 'cuu' => :ed_prev_history,
+ 'cud' => :ed_next_history,
+ 'cuf' => :ed_next_char,
+ 'cub' => :ed_prev_char,
+ }
+
if Reline::Terminfo.enabled?
Reline::Terminfo.setupterm(0, 2)
end
@@ -34,6 +47,12 @@ class Reline::ANSI
config.add_default_key_binding_by_keymap(:vi_command, key, func)
end
{
+ [27, 91, 90] => :completion_journey_up, # S-Tab
+ }.each_pair do |key, func|
+ config.add_default_key_binding_by_keymap(:emacs, key, func)
+ config.add_default_key_binding_by_keymap(:vi_insert, key, func)
+ end
+ {
# default bindings
[27, 32] => :em_set_mark, # M-<space>
[24, 24] => :em_exchange_mark, # C-x C-x
@@ -43,20 +62,23 @@ class Reline::ANSI
end
def self.set_default_key_bindings_terminfo(config)
- {
- Reline::Terminfo.tigetstr('khome').bytes => :ed_move_to_beg,
- Reline::Terminfo.tigetstr('kend').bytes => :ed_move_to_end,
- Reline::Terminfo.tigetstr('kcuu1').bytes => :ed_prev_history,
- Reline::Terminfo.tigetstr('kcud1').bytes => :ed_next_history,
- Reline::Terminfo.tigetstr('kcuf1').bytes => :ed_next_char,
- Reline::Terminfo.tigetstr('kcub1').bytes => :ed_prev_char,
- # Escape sequences that omit the move distance and are set to defaults
- # value 1 may be sometimes sent by pressing the arrow-key.
- Reline::Terminfo.tigetstr('cuu').sub(/%p1%d/, '').bytes => :ed_prev_history,
- Reline::Terminfo.tigetstr('cud').sub(/%p1%d/, '').bytes => :ed_next_history,
- Reline::Terminfo.tigetstr('cuf').sub(/%p1%d/, '').bytes => :ed_next_char,
- Reline::Terminfo.tigetstr('cub').sub(/%p1%d/, '').bytes => :ed_prev_char,
- }.each_pair do |key, func|
+ key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
+ begin
+ key_code = Reline::Terminfo.tigetstr(capname)
+ case capname
+ # Escape sequences that omit the move distance and are set to defaults
+ # value 1 may be sometimes sent by pressing the arrow-key.
+ when 'cuu', 'cud', 'cuf', 'cub'
+ [ key_code.sub(/%p1%d/, '').bytes, key_binding ]
+ else
+ [ key_code.bytes, key_binding ]
+ end
+ rescue Reline::Terminfo::TerminfoError
+ # capname is undefined
+ end
+ end.compact.to_h
+
+ key_bindings.each_pair do |key, func|
config.add_default_key_binding_by_keymap(:emacs, key, func)
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
config.add_default_key_binding_by_keymap(:vi_command, key, func)
@@ -125,10 +147,10 @@ class Reline::ANSI
unless @@buf.empty?
return @@buf.shift
end
- until c = @@input.raw(intr: true, &:getbyte)
- sleep 0.1
+ until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
+ Reline.core.line_editor.resize
end
- (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
+ (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
rescue Errno::EIO
# Maybe the I/O has been closed.
nil
@@ -260,7 +282,7 @@ class Reline::ANSI
def self.move_cursor_up(x)
if x > 0
- @@output.write "\e[#{x}A" if x > 0
+ @@output.write "\e[#{x}A"
elsif x < 0
move_cursor_down(-x)
end
@@ -268,12 +290,36 @@ class Reline::ANSI
def self.move_cursor_down(x)
if x > 0
- @@output.write "\e[#{x}B" if x > 0
+ @@output.write "\e[#{x}B"
elsif x < 0
move_cursor_up(-x)
end
end
+ def self.hide_cursor
+ if Reline::Terminfo.enabled?
+ begin
+ @@output.write Reline::Terminfo.tigetstr('civis')
+ rescue Reline::Terminfo::TerminfoError
+ # civis is undefined
+ end
+ else
+ # ignored
+ end
+ end
+
+ def self.show_cursor
+ if Reline::Terminfo.enabled?
+ begin
+ @@output.write Reline::Terminfo.tigetstr('cnorm')
+ rescue Reline::Terminfo::TerminfoError
+ # cnorm is undefined
+ end
+ else
+ # ignored
+ end
+ end
+
def self.erase_after_cursor
@@output.write "\e[K"
end
@@ -299,8 +345,6 @@ class Reline::ANSI
end
def self.deprep(otio)
- int_handle = Signal.trap('INT', 'IGNORE')
- Signal.trap('INT', int_handle)
Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
end
end
diff --git a/lib/reline/config.rb b/lib/reline/config.rb
index c2b50a95a2..5ba269258f 100644
--- a/lib/reline/config.rb
+++ b/lib/reline/config.rb
@@ -45,15 +45,19 @@ class Reline::Config
attr_accessor v
end
+ attr_accessor :autocompletion
+
def initialize
@additional_key_bindings = {} # from inputrc
@additional_key_bindings[:emacs] = {}
@additional_key_bindings[:vi_insert] = {}
@additional_key_bindings[:vi_command] = {}
+ @oneshot_key_bindings = {}
@skip_section = nil
@if_stack = nil
@editing_mode_label = :emacs
@keymap_label = :emacs
+ @keymap_prefix = []
@key_actors = {}
@key_actors[:emacs] = Reline::KeyActor::Emacs.new
@key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
@@ -65,6 +69,8 @@ class Reline::Config
@history_size = -1 # unlimited
@keyseq_timeout = 500
@test_mode = false
+ @autocompletion = false
+ @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
end
def reset
@@ -74,6 +80,7 @@ class Reline::Config
@additional_key_bindings.keys.each do |key|
@additional_key_bindings[key].clear
end
+ @oneshot_key_bindings.clear
reset_default_key_bindings
end
@@ -119,8 +126,12 @@ class Reline::Config
return home_rc_path
end
+ private def default_inputrc_path
+ @default_inputrc_path ||= inputrc_path
+ end
+
def read(file = nil)
- file ||= inputrc_path
+ file ||= default_inputrc_path
begin
if file.respond_to?(:readlines)
lines = file.readlines
@@ -139,8 +150,19 @@ class Reline::Config
end
def key_bindings
- # override @key_actors[@editing_mode_label].default_key_bindings with @additional_key_bindings[@editing_mode_label]
- @key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label])
+ # The key bindings for each editing mode will be overwritten by the user-defined ones.
+ kb = @key_actors[@editing_mode_label].default_key_bindings.dup
+ kb.merge!(@additional_key_bindings[@editing_mode_label])
+ kb.merge!(@oneshot_key_bindings)
+ kb
+ end
+
+ def add_oneshot_key_binding(keystroke, target)
+ @oneshot_key_bindings[keystroke] = target
+ end
+
+ def reset_oneshot_key_bindings
+ @oneshot_key_bindings.clear
end
def add_default_key_binding_by_keymap(keymap, keystroke, target)
@@ -194,7 +216,7 @@ class Reline::Config
key, func_name = $1, $2
keystroke, func = bind_key(key, func_name)
next unless keystroke
- @additional_key_bindings[@keymap_label][keystroke] = func
+ @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
end
end
unless @if_stack.empty?
@@ -265,18 +287,29 @@ class Reline::Config
when 'emacs'
@editing_mode_label = :emacs
@keymap_label = :emacs
+ @keymap_prefix = []
when 'vi'
@editing_mode_label = :vi_insert
@keymap_label = :vi_insert
+ @keymap_prefix = []
end
when 'keymap'
case value
- when 'emacs', 'emacs-standard', 'emacs-meta', 'emacs-ctlx'
+ when 'emacs', 'emacs-standard'
+ @keymap_label = :emacs
+ @keymap_prefix = []
+ when 'emacs-ctlx'
+ @keymap_label = :emacs
+ @keymap_prefix = [?\C-x.ord]
+ when 'emacs-meta'
@keymap_label = :emacs
+ @keymap_prefix = [?\e.ord]
when 'vi', 'vi-move', 'vi-command'
@keymap_label = :vi_command
+ @keymap_prefix = []
when 'vi-insert'
@keymap_label = :vi_insert
+ @keymap_prefix = []
end
when 'keyseq-timeout'
@keyseq_timeout = value.to_i
@@ -361,4 +394,8 @@ class Reline::Config
end
ret
end
+
+ private def seven_bit_encoding?(encoding)
+ encoding == Encoding::US_ASCII
+ end
end
diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb
index 2f87d718c6..92c76cbba1 100644
--- a/lib/reline/general_io.rb
+++ b/lib/reline/general_io.rb
@@ -1,4 +1,5 @@
require 'timeout'
+require 'io/wait'
class Reline::GeneralIO
def self.reset(encoding: nil)
@@ -24,6 +25,7 @@ class Reline::GeneralIO
end
@@buf = []
+ @@input = STDIN
def self.input=(val)
@@input = val
@@ -35,7 +37,7 @@ class Reline::GeneralIO
end
c = nil
loop do
- result = select([@@input], [], [], 0.1)
+ result = @@input.wait_readable(0.1)
next if result.nil?
c = @@input.read(1)
break
@@ -55,6 +57,12 @@ class Reline::GeneralIO
Reline::CursorPos.new(1, 1)
end
+ def self.hide_cursor
+ end
+
+ def self.show_cursor
+ end
+
def self.move_cursor_column(val)
end
diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb
index cad97a7d04..a561feee57 100644
--- a/lib/reline/key_actor/emacs.rb
+++ b/lib/reline/key_actor/emacs.rb
@@ -43,7 +43,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
# 20 ^T
:ed_transpose_chars,
# 21 ^U
- :em_kill_line,
+ :unix_line_discard,
# 22 ^V
:ed_quoted_insert,
# 23 ^W
diff --git a/lib/reline/key_stroke.rb b/lib/reline/key_stroke.rb
index 017e3db00a..c1c61513a9 100644
--- a/lib/reline/key_stroke.rb
+++ b/lib/reline/key_stroke.rb
@@ -1,38 +1,88 @@
class Reline::KeyStroke
- using Module.new {
- refine Array do
- def start_with?(other)
- other.size <= size && other == self.take(other.size)
+ def initialize(config)
+ @config = config
+ end
+
+ def compress_meta_key(ary)
+ return ary unless @config.convert_meta
+ ary.inject([]) { |result, key|
+ if result.size > 0 and result.last == "\e".ord
+ result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
+ else
+ result << key
end
+ result
+ }
+ end
- def bytes
- self
+ def start_with?(me, other)
+ compressed_me = compress_meta_key(me)
+ compressed_other = compress_meta_key(other)
+ i = 0
+ loop do
+ my_c = compressed_me[i]
+ other_c = compressed_other[i]
+ other_is_last = (i + 1) == compressed_other.size
+ me_is_last = (i + 1) == compressed_me.size
+ if my_c != other_c
+ if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
+ return true
+ else
+ return false
+ end
+ elsif other_is_last
+ return true
+ elsif me_is_last
+ return false
end
+ i += 1
end
- }
+ end
- def initialize(config)
- @config = config
+ def equal?(me, other)
+ case me
+ when Array
+ compressed_me = compress_meta_key(me)
+ compressed_other = compress_meta_key(other)
+ compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
+ when Integer
+ if other.is_a?(Reline::Key)
+ if other.combined_char == "\e".ord
+ false
+ else
+ other.combined_char == me
+ end
+ else
+ me == other
+ end
+ when Reline::Key
+ if other.is_a?(Integer)
+ me.combined_char == other
+ else
+ me == other
+ end
+ end
end
def match_status(input)
key_mapping.keys.select { |lhs|
- lhs.start_with? input
+ start_with?(lhs, input)
}.tap { |it|
- return :matched if it.size == 1 && (it.max_by(&:size)&.size&.== input.size)
- return :matching if it.size == 1 && (it.max_by(&:size)&.size&.!= input.size)
+ return :matched if it.size == 1 && equal?(it[0], input)
+ return :matching if it.size == 1 && !equal?(it[0], input)
return :matched if it.max_by(&:size)&.size&.< input.size
return :matching if it.size > 1
}
key_mapping.keys.select { |lhs|
- input.start_with? lhs
+ start_with?(input, lhs)
}.tap { |it|
return it.size > 0 ? :matched : :unmatched
}
end
def expand(input)
- lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).reverse.first
+ input = compress_meta_key(input)
+ lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
return input unless lhs
rhs = key_mapping[lhs]
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 97f12116b9..8153aaba05 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -5,6 +5,7 @@ require 'tempfile'
class Reline::LineEditor
# TODO: undo
+ # TODO: Use "private alias_method" idiom after drop Ruby 2.5.
attr_reader :line
attr_reader :byte_pointer
attr_accessor :confirm_multiline_termination_proc
@@ -92,7 +93,7 @@ class Reline::LineEditor
mode_string
end
- private def check_multiline_prompt(buffer, prompt)
+ private def check_multiline_prompt(buffer)
if @vi_arg
prompt = "(arg: #{@vi_arg}) "
@rerender_all = true
@@ -120,7 +121,7 @@ class Reline::LineEditor
if use_cached_prompt_list
prompt_list = @cached_prompt_list
else
- prompt_list = @cached_prompt_list = @prompt_proc.(buffer)
+ prompt_list = @cached_prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") }
@prompt_cache_time = Time.now.to_f
end
prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
@@ -150,7 +151,75 @@ class Reline::LineEditor
@screen_size = Reline::IOGate.get_screen_size
@screen_height = @screen_size.first
reset_variables(prompt, encoding: encoding)
- @old_trap = Signal.trap(:INT) {
+ Reline::IOGate.set_winch_handler do
+ @resized = true
+ end
+ if ENV.key?('RELINE_ALT_SCROLLBAR')
+ @full_block = '::'
+ @upper_half_block = "''"
+ @lower_half_block = '..'
+ @block_elem_width = 2
+ elsif Reline::IOGate.win?
+ @full_block = '█'
+ @upper_half_block = '▀'
+ @lower_half_block = '▄'
+ @block_elem_width = 1
+ elsif @encoding == Encoding::UTF_8
+ @full_block = '█'
+ @upper_half_block = '▀'
+ @lower_half_block = '▄'
+ @block_elem_width = Reline::Unicode.calculate_width('█')
+ else
+ @full_block = '::'
+ @upper_half_block = "''"
+ @lower_half_block = '..'
+ @block_elem_width = 2
+ end
+ end
+
+ def resize
+ return unless @resized
+ @resized = false
+ @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
+ old_screen_size = @screen_size
+ @screen_size = Reline::IOGate.get_screen_size
+ @screen_height = @screen_size.first
+ if old_screen_size.last < @screen_size.last # columns increase
+ @rerender_all = true
+ rerender
+ else
+ back = 0
+ new_buffer = whole_lines
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer)
+ new_buffer.each_with_index do |line, index|
+ prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
+ width = prompt_width + calculate_width(line)
+ height = calculate_height_by_width(width)
+ back += height
+ end
+ @highest_in_all = back
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ @first_line_started_from =
+ if @line_index.zero?
+ 0
+ else
+ calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
+ end
+ if @prompt_proc
+ prompt = prompt_list[@line_index]
+ prompt_width = calculate_width(prompt, true)
+ end
+ calculate_nearest_cursor
+ @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ @rerender_all = true
+ end
+ end
+
+ def set_signal_handlers
+ @old_trap = Signal.trap('INT') {
+ clear_dialog
if @scroll_partial_screen
move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
else
@@ -166,50 +235,24 @@ class Reline::LineEditor
when 'EXIT'
exit
else
- @old_trap.call
+ @old_trap.call if @old_trap.respond_to?(:call)
end
}
- Reline::IOGate.set_winch_handler do
- @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
- old_screen_size = @screen_size
- @screen_size = Reline::IOGate.get_screen_size
- @screen_height = @screen_size.first
- if old_screen_size.last < @screen_size.last # columns increase
- @rerender_all = true
- rerender
- else
- back = 0
- new_buffer = whole_lines
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
- new_buffer.each_with_index do |line, index|
- prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
- width = prompt_width + calculate_width(line)
- height = calculate_height_by_width(width)
- back += height
- end
- @highest_in_all = back
- @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
- @first_line_started_from =
- if @line_index.zero?
- 0
- else
- calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
- end
- if @prompt_proc
- prompt = prompt_list[@line_index]
- prompt_width = calculate_width(prompt, true)
- end
- calculate_nearest_cursor
- @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
- Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
- @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
- @rerender_all = true
- end
+ begin
+ @old_tstp_trap = Signal.trap('TSTP') {
+ Reline::IOGate.ungetc("\C-z".ord)
+ @old_tstp_trap.call if @old_tstp_trap.respond_to?(:call)
+ }
+ rescue ArgumentError
end
end
def finalize
- Signal.trap('SIGINT', @old_trap)
+ Signal.trap('INT', @old_trap)
+ begin
+ Signal.trap('TSTP', @old_tstp_trap)
+ rescue ArgumentError
+ end
end
def eof?
@@ -217,7 +260,7 @@ class Reline::LineEditor
end
def reset_variables(prompt = '', encoding:)
- @prompt = prompt
+ @prompt = prompt.gsub("\n", "\\n")
@mark_pointer = nil
@encoding = encoding
@is_multiline = false
@@ -249,6 +292,9 @@ class Reline::LineEditor
@drop_terminate_spaces = false
@in_pasting = false
@auto_indent_proc = nil
+ @dialogs = []
+ @last_key = nil
+ @resized = false
reset_line
end
@@ -392,7 +438,7 @@ class Reline::LineEditor
show_menu
@menu_info = nil
end
- prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
+ prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
if @cleared
clear_screen_buffer(prompt, prompt_list, prompt_width)
@cleared = false
@@ -403,7 +449,7 @@ class Reline::LineEditor
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)
+ prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
if @previous_line_index
new_lines = whole_lines(index: @previous_line_index, line: @line)
else
@@ -414,19 +460,23 @@ class Reline::LineEditor
Reline::IOGate.erase_after_cursor
end
@output.flush
+ clear_dialog
return
end
new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
rendered = false
if @add_newline_to_end_of_buffer
+ clear_dialog_with_content
rerender_added_newline(prompt, prompt_width)
@add_newline_to_end_of_buffer = false
else
if @just_cursor_moving and not @rerender_all
+ clear_dialog_with_content
rendered = just_move_cursor
@just_cursor_moving = false
return
elsif @previous_line_index or new_highest_in_this != @highest_in_this
+ clear_dialog_with_content
rerender_changed_current_line
@previous_line_index = nil
rendered = true
@@ -446,18 +496,20 @@ class Reline::LineEditor
new_lines = whole_lines
end
line = modify_lines(new_lines)[@line_index]
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
+ clear_dialog
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
render_partial(prompt, prompt_width, line, @first_line_started_from)
move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1)
scroll_down(1)
Reline::IOGate.move_cursor_column(0)
Reline::IOGate.erase_after_cursor
- elsif not rendered
- unless @in_pasting
+ else
+ if not rendered and not @in_pasting
line = modify_lines(whole_lines)[@line_index]
- prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
+ prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
render_partial(prompt, prompt_width, line, @first_line_started_from)
end
+ render_dialog((prompt_width + @cursor) % @screen_size.last)
end
@buffer_of_lines[@line_index] = @line
@rest_height = 0 if @scroll_partial_screen
@@ -472,6 +524,413 @@ class Reline::LineEditor
end
end
+ class DialogProcScope
+ def initialize(line_editor, config, proc_to_exec, context)
+ @line_editor = line_editor
+ @config = config
+ @proc_to_exec = proc_to_exec
+ @context = context
+ @cursor_pos = Reline::CursorPos.new
+ end
+
+ def context
+ @context
+ end
+
+ def retrieve_completion_block(set_completion_quote_character = false)
+ @line_editor.retrieve_completion_block(set_completion_quote_character)
+ end
+
+ def call_completion_proc_with_checking_args(pre, target, post)
+ @line_editor.call_completion_proc_with_checking_args(pre, target, post)
+ end
+
+ def set_dialog(dialog)
+ @dialog = dialog
+ end
+
+ def dialog
+ @dialog
+ end
+
+ def set_cursor_pos(col, row)
+ @cursor_pos.x = col
+ @cursor_pos.y = row
+ end
+
+ def set_key(key)
+ @key = key
+ end
+
+ def key
+ @key
+ end
+
+ def cursor_pos
+ @cursor_pos
+ end
+
+ def just_cursor_moving
+ @line_editor.instance_variable_get(:@just_cursor_moving)
+ end
+
+ def screen_width
+ @line_editor.instance_variable_get(:@screen_size).last
+ end
+
+ def completion_journey_data
+ @line_editor.instance_variable_get(:@completion_journey_data)
+ end
+
+ def config
+ @config
+ end
+
+ def call
+ instance_exec(&@proc_to_exec)
+ end
+ end
+
+ class Dialog
+ attr_reader :name, :contents, :width
+ attr_accessor :scroll_top, :scrollbar_pos, :pointer, :column, :vertical_offset, :lines_backup, :trap_key
+
+ def initialize(name, config, proc_scope)
+ @name = name
+ @config = config
+ @proc_scope = proc_scope
+ @width = nil
+ @scroll_top = 0
+ @trap_key = nil
+ end
+
+ def set_cursor_pos(col, row)
+ @proc_scope.set_cursor_pos(col, row)
+ end
+
+ def width=(v)
+ @width = v
+ end
+
+ def contents=(contents)
+ @contents = contents
+ if contents and @width.nil?
+ @width = contents.map{ |line| Reline::Unicode.calculate_width(line, true) }.max
+ end
+ end
+
+ def call(key)
+ @proc_scope.set_dialog(self)
+ @proc_scope.set_key(key)
+ dialog_render_info = @proc_scope.call
+ if @trap_key
+ if @trap_key.any?{ |i| i.is_a?(Array) } # multiple trap
+ @trap_key.each do |t|
+ @config.add_oneshot_key_binding(t, @name)
+ end
+ elsif @trap_key.is_a?(Array)
+ @config.add_oneshot_key_binding(@trap_key, @name)
+ elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
+ @config.add_oneshot_key_binding([@trap_key], @name)
+ end
+ end
+ dialog_render_info
+ end
+ end
+
+ def add_dialog_proc(name, p, context = nil)
+ dialog = Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context))
+ if index = @dialogs.find_index { |d| d.name == name }
+ @dialogs[index] = dialog
+ else
+ @dialogs << dialog
+ end
+ end
+
+ DIALOG_DEFAULT_HEIGHT = 20
+ private def render_dialog(cursor_column)
+ @dialogs.each do |dialog|
+ render_each_dialog(dialog, cursor_column)
+ end
+ end
+
+ private def padding_space_with_escape_sequences(str, width)
+ padding_width = width - calculate_width(str, true)
+ # padding_width should be only positive value. But macOS and Alacritty returns negative value.
+ padding_width = 0 if padding_width < 0
+ str + (' ' * padding_width)
+ end
+
+ private def render_each_dialog(dialog, cursor_column)
+ if @in_pasting
+ clear_each_dialog(dialog)
+ dialog.contents = nil
+ dialog.trap_key = nil
+ return
+ end
+ dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
+ dialog_render_info = dialog.call(@last_key)
+ if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
+ dialog.lines_backup = {
+ lines: modify_lines(whole_lines),
+ line_index: @line_index,
+ first_line_started_from: @first_line_started_from,
+ started_from: @started_from,
+ byte_pointer: @byte_pointer
+ }
+ clear_each_dialog(dialog)
+ dialog.contents = nil
+ dialog.trap_key = nil
+ return
+ end
+ old_dialog = dialog.clone
+ dialog.contents = dialog_render_info.contents
+ pointer = dialog.pointer
+ if dialog_render_info.width
+ dialog.width = dialog_render_info.width
+ else
+ dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
+ end
+ height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
+ height = dialog.contents.size if dialog.contents.size < height
+ if dialog.contents.size > height
+ if dialog.pointer
+ if dialog.pointer < 0
+ dialog.scroll_top = 0
+ elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
+ dialog.scroll_top = dialog.pointer - (height - 1)
+ elsif (dialog.pointer - dialog.scroll_top) < 0
+ dialog.scroll_top = dialog.pointer
+ end
+ pointer = dialog.pointer - dialog.scroll_top
+ end
+ dialog.contents = dialog.contents[dialog.scroll_top, height]
+ end
+ if dialog.contents and dialog.scroll_top >= dialog.contents.size
+ dialog.scroll_top = dialog.contents.size - height
+ end
+ if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
+ bar_max_height = height * 2
+ moving_distance = (dialog_render_info.contents.size - height) * 2
+ position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
+ bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
+ dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
+ else
+ dialog.scrollbar_pos = nil
+ end
+ upper_space = @first_line_started_from - @started_from
+ dialog.column = dialog_render_info.pos.x
+ dialog.width += @block_elem_width if dialog.scrollbar_pos
+ diff = (dialog.column + dialog.width) - (@screen_size.last)
+ if diff > 0
+ dialog.column -= diff
+ end
+ if (@rest_height - dialog_render_info.pos.y) >= height
+ dialog.vertical_offset = dialog_render_info.pos.y + 1
+ elsif upper_space >= height
+ dialog.vertical_offset = dialog_render_info.pos.y - height
+ else
+ if (@rest_height - dialog_render_info.pos.y) < height
+ scroll_down(height + dialog_render_info.pos.y)
+ move_cursor_up(height + dialog_render_info.pos.y)
+ end
+ dialog.vertical_offset = dialog_render_info.pos.y + 1
+ end
+ Reline::IOGate.hide_cursor
+ if dialog.column < 0
+ dialog.column = 0
+ dialog.width = @screen_size.last
+ end
+ reset_dialog(dialog, old_dialog)
+ move_cursor_down(dialog.vertical_offset)
+ Reline::IOGate.move_cursor_column(dialog.column)
+ dialog.contents.each_with_index do |item, i|
+ if i == pointer
+ fg_color = dialog_render_info.pointer_fg_color
+ bg_color = dialog_render_info.pointer_bg_color
+ else
+ fg_color = dialog_render_info.fg_color
+ bg_color = dialog_render_info.bg_color
+ end
+ str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
+ str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
+ @output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
+ if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
+ @output.write "\e[37m"
+ if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
+ @output.write @full_block
+ elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
+ @output.write @upper_half_block
+ elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
+ @output.write @lower_half_block
+ else
+ @output.write ' ' * @block_elem_width
+ end
+ end
+ @output.write "\e[0m"
+ Reline::IOGate.move_cursor_column(dialog.column)
+ move_cursor_down(1) if i < (dialog.contents.size - 1)
+ end
+ Reline::IOGate.move_cursor_column(cursor_column)
+ move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
+ Reline::IOGate.show_cursor
+ dialog.lines_backup = {
+ lines: modify_lines(whole_lines),
+ line_index: @line_index,
+ first_line_started_from: @first_line_started_from,
+ started_from: @started_from,
+ byte_pointer: @byte_pointer
+ }
+ end
+
+ private def reset_dialog(dialog, old_dialog)
+ return if dialog.lines_backup.nil? or old_dialog.contents.nil?
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
+ visual_lines = []
+ visual_start = nil
+ dialog.lines_backup[:lines].each_with_index { |l, i|
+ pr = prompt_list ? prompt_list[i] : prompt
+ vl, _ = split_by_width(pr + l, @screen_size.last)
+ vl.compact!
+ if i == dialog.lines_backup[:line_index]
+ visual_start = visual_lines.size + dialog.lines_backup[:started_from]
+ end
+ visual_lines.concat(vl)
+ }
+ old_y = dialog.lines_backup[:first_line_started_from] + dialog.lines_backup[:started_from]
+ y = @first_line_started_from + @started_from
+ y_diff = y - old_y
+ if (old_y + old_dialog.vertical_offset) < (y + dialog.vertical_offset)
+ # rerender top
+ move_cursor_down(old_dialog.vertical_offset - y_diff)
+ start = visual_start + old_dialog.vertical_offset
+ line_num = dialog.vertical_offset - old_dialog.vertical_offset
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column)
+ if visual_lines[start + i].nil?
+ s = ' ' * old_dialog.width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
+ s = padding_space_with_escape_sequences(s, old_dialog.width)
+ end
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
+ end
+ if (old_y + old_dialog.vertical_offset + old_dialog.contents.size) > (y + dialog.vertical_offset + dialog.contents.size)
+ # rerender bottom
+ move_cursor_down(dialog.vertical_offset + dialog.contents.size - y_diff)
+ start = visual_start + dialog.vertical_offset + dialog.contents.size
+ line_num = (old_dialog.vertical_offset + old_dialog.contents.size) - (dialog.vertical_offset + dialog.contents.size)
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column)
+ if visual_lines[start + i].nil?
+ s = ' ' * old_dialog.width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
+ s = padding_space_with_escape_sequences(s, old_dialog.width)
+ end
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
+ end
+ if old_dialog.column < dialog.column
+ # rerender left
+ move_cursor_down(old_dialog.vertical_offset - y_diff)
+ width = dialog.column - old_dialog.column
+ start = visual_start + old_dialog.vertical_offset
+ line_num = old_dialog.contents.size
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column)
+ if visual_lines[start + i].nil?
+ s = ' ' * width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
+ s = padding_space_with_escape_sequences(s, dialog.width)
+ end
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
+ end
+ if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width)
+ # rerender right
+ move_cursor_down(old_dialog.vertical_offset + y_diff)
+ width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width)
+ start = visual_start + old_dialog.vertical_offset
+ line_num = old_dialog.contents.size
+ line_num.times do |i|
+ Reline::IOGate.move_cursor_column(old_dialog.column + dialog.width)
+ if visual_lines[start + i].nil?
+ s = ' ' * width
+ else
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width)
+ rerender_width = old_dialog.width - dialog.width
+ s = padding_space_with_escape_sequences(s, rerender_width)
+ end
+ Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
+ @output.write "\e[0m#{s}\e[0m"
+ move_cursor_down(1) if i < (line_num - 1)
+ end
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
+ end
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ end
+
+ private def clear_dialog
+ @dialogs.each do |dialog|
+ clear_each_dialog(dialog)
+ end
+ end
+
+ private def clear_dialog_with_content
+ @dialogs.each do |dialog|
+ clear_each_dialog(dialog)
+ dialog.contents = nil
+ dialog.trap_key = nil
+ end
+ end
+
+ private def clear_each_dialog(dialog)
+ dialog.trap_key = nil
+ return unless dialog.contents
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
+ visual_lines = []
+ visual_lines_under_dialog = []
+ visual_start = nil
+ dialog.lines_backup[:lines].each_with_index { |l, i|
+ pr = prompt_list ? prompt_list[i] : prompt
+ vl, _ = split_by_width(pr + l, @screen_size.last)
+ vl.compact!
+ if i == dialog.lines_backup[:line_index]
+ visual_start = visual_lines.size + dialog.lines_backup[:started_from] + dialog.vertical_offset
+ end
+ visual_lines.concat(vl)
+ }
+ visual_lines_under_dialog = visual_lines[visual_start, dialog.contents.size]
+ visual_lines_under_dialog = [] if visual_lines_under_dialog.nil?
+ Reline::IOGate.hide_cursor
+ move_cursor_down(dialog.vertical_offset)
+ dialog_vertical_size = dialog.contents.size
+ dialog_vertical_size.times do |i|
+ if i < visual_lines_under_dialog.size
+ Reline::IOGate.move_cursor_column(dialog.column)
+ str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
+ str = padding_space_with_escape_sequences(str, dialog.width)
+ @output.write "\e[0m#{str}\e[0m"
+ else
+ Reline::IOGate.move_cursor_column(dialog.column)
+ @output.write "\e[0m#{' ' * dialog.width}\e[0m"
+ end
+ move_cursor_down(1) if i < (dialog_vertical_size - 1)
+ end
+ move_cursor_up(dialog_vertical_size - 1 + dialog.vertical_offset)
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ Reline::IOGate.show_cursor
+ end
+
private def calculate_scroll_partial_screen(highest_in_all, cursor_y)
if @screen_height < highest_in_all
old_scroll_partial_screen = @scroll_partial_screen
@@ -522,7 +981,7 @@ class Reline::LineEditor
end
def just_move_cursor
- prompt, prompt_width, prompt_list = check_multiline_prompt(@buffer_of_lines, prompt)
+ prompt, prompt_width, prompt_list = check_multiline_prompt(@buffer_of_lines)
move_cursor_up(@started_from)
new_first_line_started_from =
if @line_index.zero?
@@ -559,7 +1018,7 @@ class Reline::LineEditor
else
new_lines = whole_lines
end
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
all_height = calculate_height_by_lines(new_lines, prompt_list || prompt)
diff = all_height - @highest_in_all
move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1)
@@ -606,7 +1065,7 @@ class Reline::LineEditor
Reline::IOGate.move_cursor_column(0)
back = 0
new_buffer = whole_lines
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer)
new_buffer.each_with_index do |line, index|
prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
width = prompt_width + calculate_width(line)
@@ -813,7 +1272,7 @@ class Reline::LineEditor
height = render_partial(prompt, prompt_width, line, back, with_control: false)
end
if index < (@buffer_of_lines.size - 1)
- move_cursor_down(height)
+ move_cursor_down(1)
back += height
end
end
@@ -932,6 +1391,16 @@ class Reline::LineEditor
@completion_journey_data = CompletionJourneyData.new(
preposing, postposing,
[target] + list.select{ |item| item.start_with?(target) }, 0)
+ if @completion_journey_data.list.size == 1
+ @completion_journey_data.pointer = 0
+ else
+ case direction
+ when :up
+ @completion_journey_data.pointer = @completion_journey_data.list.size - 1
+ when :down
+ @completion_journey_data.pointer = 1
+ end
+ end
@completion_state = CompletionState::JOURNEY
else
case direction
@@ -946,20 +1415,22 @@ class Reline::LineEditor
@completion_journey_data.pointer = 0
end
end
- completed = @completion_journey_data.list[@completion_journey_data.pointer]
- @line = @completion_journey_data.preposing + completed + @completion_journey_data.postposing
- line_to_pointer = @completion_journey_data.preposing + completed
- @cursor_max = calculate_width(@line)
- @cursor = calculate_width(line_to_pointer)
- @byte_pointer = line_to_pointer.bytesize
end
+ completed = @completion_journey_data.list[@completion_journey_data.pointer]
+ new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index]
+ @line = new_line.nil? ? String.new(encoding: @encoding) : new_line
+ line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last
+ line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil?
+ @cursor_max = calculate_width(@line)
+ @cursor = calculate_width(line_to_pointer)
+ @byte_pointer = line_to_pointer.bytesize
end
private def run_for_operators(key, method_symbol, &block)
if @waiting_operator_proc
if VI_MOTIONS.include?(method_symbol)
old_cursor, old_byte_pointer = @cursor, @byte_pointer
- @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg > 1
+ @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
@@ -984,7 +1455,10 @@ class Reline::LineEditor
end
@waiting_operator_proc = nil
@waiting_operator_vi_arg = nil
- @vi_arg = nil
+ if @vi_arg
+ @rerender_all = true
+ @vi_arg = nil
+ end
else
block.(false)
end
@@ -1035,7 +1509,10 @@ class Reline::LineEditor
wrap_method_call(method_symbol, method_obj, key) if method_obj
end
@kill_ring.process
- @vi_arg = nil
+ if @vi_arg
+ @rerender_al = true
+ @vi_arg = nil
+ end
elsif @vi_arg
if key.chr =~ /[0-9]/
ed_argument_digit(key)
@@ -1052,7 +1529,10 @@ class Reline::LineEditor
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
end
@kill_ring.process
- @vi_arg = nil
+ if @vi_arg
+ @rerender_all = true
+ @vi_arg = nil
+ end
end
elsif @waiting_proc
@waiting_proc.(key)
@@ -1110,6 +1590,13 @@ class Reline::LineEditor
end
def input_key(key)
+ @last_key = key
+ @config.reset_oneshot_key_bindings
+ @dialogs.each do |dialog|
+ if key.char.instance_of?(Symbol) and key.char == dialog.name
+ return
+ end
+ end
@just_cursor_moving = nil
if key.char.nil?
if @first_char
@@ -1127,7 +1614,20 @@ class Reline::LineEditor
if result.is_a?(Array)
completion_occurs = true
process_insert
- complete(result)
+ if @config.autocompletion
+ move_completed_list(result, :down)
+ else
+ complete(result)
+ end
+ end
+ end
+ elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up
+ if not @config.disable_completion and @config.autocompletion
+ result = call_completion_proc
+ if result.is_a?(Array)
+ completion_occurs = true
+ process_insert
+ move_completed_list(result, :up)
end
end
elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
@@ -1146,6 +1646,7 @@ class Reline::LineEditor
end
unless completion_occurs
@completion_state = CompletionState::NORMAL
+ @completion_journey_data = nil
end
if not @in_pasting and @just_cursor_moving.nil?
if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line
@@ -1165,7 +1666,13 @@ class Reline::LineEditor
def call_completion_proc
result = retrieve_completion_block(true)
- preposing, target, postposing = result
+ pre, target, post = result
+ result = call_completion_proc_with_checking_args(pre, target, post)
+ Reline.core.instance_variable_set(:@completion_quote_character, nil)
+ result
+ end
+
+ def call_completion_proc_with_checking_args(pre, target, post)
if @completion_proc and target
argnum = @completion_proc.parameters.inject(0) { |result, item|
case item.first
@@ -1179,12 +1686,11 @@ class Reline::LineEditor
when 1
result = @completion_proc.(target)
when 2
- result = @completion_proc.(target, preposing)
+ result = @completion_proc.(target, pre)
when 3..Float::INFINITY
- result = @completion_proc.(target, preposing, postposing)
+ result = @completion_proc.(target, pre, post)
end
end
- Reline.core.instance_variable_set(:@completion_quote_character, nil)
result
end
@@ -1465,6 +1971,8 @@ class Reline::LineEditor
end
end
+ # Editline:: +ed-unassigned+ This editor command always results in an error.
+ # GNU Readline:: There is no corresponding macro.
private def ed_unassigned(key) end # do nothing
private def process_insert(force: false)
@@ -1482,6 +1990,19 @@ class Reline::LineEditor
@continuous_insertion_buffer.clear
end
+ # Editline:: +ed-insert+ (vi input: almost all; emacs: printable characters)
+ # In insert mode, insert the input character left of the cursor
+ # position. In replace mode, overwrite the character at the
+ # cursor and move the cursor to the right by one character
+ # position. Accept an argument to do this repeatedly. It is an
+ # error if the input character is the NUL character (+Ctrl-@+).
+ # Failure to enlarge the edit buffer also results in an error.
+ # Editline:: +ed-digit+ (emacs: 0 to 9) If in argument input mode, append
+ # the input digit to the argument being read. Otherwise, call
+ # +ed-insert+. It is an error if the input character is not a
+ # digit or if the existing argument is already greater than a
+ # million.
+ # GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
private def ed_insert(key)
str = nil
width = nil
@@ -1518,8 +2039,16 @@ class Reline::LineEditor
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
+ combined_char = last_mbchar + str
+ if last_byte_size != 0 and combined_char.grapheme_clusters.size == 1
+ # combined char
+ last_mbchar_width = Reline::Unicode.get_mbchar_width(last_mbchar)
+ combined_char_width = Reline::Unicode.get_mbchar_width(combined_char)
+ if combined_char_width > last_mbchar_width
+ width = combined_char_width - last_mbchar_width
+ else
+ width = 0
+ end
end
@cursor += width
@cursor_max += width
@@ -1532,6 +2061,8 @@ class Reline::LineEditor
arg.times do
if key == "\C-j".ord or key == "\C-m".ord
key_newline(key)
+ elsif key == 0
+ # Ignore NUL.
else
ed_insert(key)
end
@@ -1702,6 +2233,8 @@ class Reline::LineEditor
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
@line_index = @buffer_of_lines.size - 1
@line = @buffer_of_lines.last
+ @byte_pointer = @line.bytesize
+ @cursor = @cursor_max = calculate_width(@line)
@rerender_all = true
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
else
@@ -1966,6 +2499,7 @@ class Reline::LineEditor
arg -= 1
ed_prev_history(key, arg: arg) if arg > 0
end
+ alias_method :previous_history, :ed_prev_history
private def ed_next_history(key, arg: 1)
if @is_multiline and @line_index < (@buffer_of_lines.size - 1)
@@ -2013,6 +2547,7 @@ class Reline::LineEditor
arg -= 1
ed_next_history(key, arg: arg) if arg > 0
end
+ alias_method :next_history, :ed_next_history
private def ed_newline(key)
process_insert(force: true)
@@ -2047,7 +2582,7 @@ class Reline::LineEditor
end
end
- private def em_delete_prev_char(key)
+ private def em_delete_prev_char(key, arg: 1)
if @is_multiline and @cursor == 0 and @line_index > 0
@buffer_of_lines[@line_index] = @line
@cursor = calculate_width(@buffer_of_lines[@line_index - 1])
@@ -2065,9 +2600,16 @@ class Reline::LineEditor
@cursor -= width
@cursor_max -= width
end
+ arg -= 1
+ em_delete_prev_char(key, arg: arg) if arg > 0
end
alias_method :backward_delete_char, :em_delete_prev_char
+ # Editline:: +ed-kill-line+ (vi command: +D+, +Ctrl-K+; emacs: +Ctrl-K+,
+ # +Ctrl-U+) + Kill from the cursor to the end of the line.
+ # GNU Readline:: +kill-line+ (+C-k+) Kill the text from point to the end of
+ # the line. With a negative numeric argument, kill backward
+ # from the cursor to the beginning of the current line.
private def ed_kill_line(key)
if @line.bytesize > @byte_pointer
@line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer)
@@ -2084,8 +2626,14 @@ class Reline::LineEditor
@rest_height += 1
end
end
+ alias_method :kill_line, :ed_kill_line
- private def em_kill_line(key)
+ # Editline:: +vi-kill-line-prev+ (vi: +Ctrl-U+) Delete the string from the
+ # beginning of the edit buffer to the cursor and save it to the
+ # cut buffer.
+ # GNU Readline:: +unix-line-discard+ (+C-u+) Kill backward from the cursor
+ # to the beginning of the current line.
+ private def vi_kill_line_prev(key)
if @byte_pointer > 0
@line, deleted = byteslice!(@line, 0, @byte_pointer)
@byte_pointer = 0
@@ -2094,7 +2642,22 @@ class Reline::LineEditor
@cursor = 0
end
end
- alias_method :kill_line, :em_kill_line
+ alias_method :unix_line_discard, :vi_kill_line_prev
+
+ # Editline:: +em-kill-line+ (not bound) Delete the entire contents of the
+ # edit buffer and save it to the cut buffer. +vi-kill-line-prev+
+ # GNU Readline:: +kill-whole-line+ (not bound) Kill all characters on the
+ # current line, no matter where point is.
+ private def em_kill_line(key)
+ if @line.size > 0
+ @kill_ring.append(@line.dup, true)
+ @line.clear
+ @byte_pointer = 0
+ @cursor_max = 0
+ @cursor = 0
+ end
+ end
+ alias_method :kill_whole_line, :em_kill_line
private def em_delete(key)
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
@@ -2599,7 +3162,14 @@ class Reline::LineEditor
private def ed_argument_digit(key)
if @vi_arg.nil?
- unless key.chr.to_i.zero?
+ if key.chr.to_i.zero?
+ if key.anybits?(0b10000000)
+ unescaped_key = key ^ 0b10000000
+ unless unescaped_key.chr.to_i.zero?
+ @vi_arg = unescaped_key.chr.to_i
+ end
+ end
+ else
@vi_arg = key.chr.to_i
end
else
diff --git a/lib/reline/reline.gemspec b/lib/reline/reline.gemspec
index 400301fc70..7bf1f8758b 100644
--- a/lib/reline/reline.gemspec
+++ b/lib/reline/reline.gemspec
@@ -1,7 +1,9 @@
-lib = File.expand_path('../lib', __FILE__)
-$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
-require 'reline/version'
+begin
+ require_relative 'lib/reline/version'
+rescue LoadError
+ require_relative 'version'
+end
Gem::Specification.new do |spec|
spec.name = 'reline'
@@ -17,7 +19,7 @@ Gem::Specification.new do |spec|
spec.files = Dir['BSDL', 'COPYING', 'README.md', 'license_of_rb-readline', 'lib/**/*']
spec.require_paths = ['lib']
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5')
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.6')
spec.add_dependency 'io-console', '~> 0.5'
end
diff --git a/lib/reline/terminfo.rb b/lib/reline/terminfo.rb
index d78f3d7b17..f53642b919 100644
--- a/lib/reline/terminfo.rb
+++ b/lib/reline/terminfo.rb
@@ -1,5 +1,13 @@
-require 'fiddle'
-require 'fiddle/import'
+begin
+ require 'fiddle'
+ require 'fiddle/import'
+rescue LoadError
+ module Reline::Terminfo
+ def self.curses_dl
+ false
+ end
+ end
+end
module Reline::Terminfo
extend Fiddle::Importer
@@ -27,7 +35,7 @@ module Reline::Terminfo
# Gem module isn't defined in test-all of the Ruby repository, and
# Fiddle in Ruby 3.0.0 or later supports Fiddle::TYPE_VARIADIC.
fiddle_supports_variadic = true
- elsif Fiddle.const_defined?(:VERSION) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
+ elsif Fiddle.const_defined?(:VERSION,false) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
# Fiddle::TYPE_VARIADIC is supported from Fiddle 1.0.1.
fiddle_supports_variadic = true
else
@@ -50,7 +58,7 @@ module Reline::Terminfo
@curses_dl = nil if @curses_dl == false
@curses_dl
end
-end
+end if not Reline.const_defined?(:Terminfo) or not Reline::Terminfo.respond_to?(:curses_dl)
module Reline::Terminfo
dlload curses_dl
@@ -66,12 +74,27 @@ module Reline::Terminfo
#extern 'char *tparm(const char *str, ...)'
@tiparm = Fiddle::Function.new(curses_dl['tparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
end
- # TODO: add int tigetflag(char *capname) and int tigetnum(char *capname)
+ begin
+ #extern 'int tigetflag(char *str)'
+ @tigetflag = Fiddle::Function.new(curses_dl['tigetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
+ rescue Fiddle::DLError
+ # OpenBSD lacks tigetflag
+ #extern 'int tgetflag(char *str)'
+ @tigetflag = Fiddle::Function.new(curses_dl['tgetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
+ end
+ begin
+ #extern 'int tigetnum(char *str)'
+ @tigetnum = Fiddle::Function.new(curses_dl['tigetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
+ rescue Fiddle::DLError
+ # OpenBSD lacks tigetnum
+ #extern 'int tgetnum(char *str)'
+ @tigetnum = Fiddle::Function.new(curses_dl['tgetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
+ end
def self.setupterm(term, fildes)
- errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
+ errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
ret = @setupterm.(term, fildes, errret_int)
- errret = errret_int.unpack('i')[0]
+ errret = errret_int[0, Fiddle::SIZEOF_INT].unpack1('i')
case ret
when 0 # OK
0
@@ -98,6 +121,7 @@ module Reline::Terminfo
end
def self.tigetstr(capname)
+ raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
capability = @tigetstr.(capname)
case capability.to_i
when 0, -1
@@ -114,6 +138,30 @@ module Reline::Terminfo
@tiparm.(str, *new_args).to_s
end
+ def self.tigetflag(capname)
+ raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
+ flag = @tigetflag.(capname).to_i
+ case flag
+ when -1
+ raise TerminfoError, "not boolean capability: #{capname}"
+ when 0
+ raise TerminfoError, "can't find capability: #{capname}"
+ end
+ flag
+ end
+
+ def self.tigetnum(capname)
+ raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
+ num = @tigetnum.(capname).to_i
+ case num
+ when -2
+ raise TerminfoError, "not numeric capability: #{capname}"
+ when -1
+ raise TerminfoError, "can't find capability: #{capname}"
+ end
+ num
+ end
+
def self.enabled?
true
end
diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb
index 7dbe8a12a5..6000c9f82a 100644
--- a/lib/reline/unicode.rb
+++ b/lib/reline/unicode.rb
@@ -79,6 +79,8 @@ class Reline::Unicode
require 'reline/unicode/east_asian_width'
+ HalfwidthDakutenHandakuten = /[\u{FF9E}\u{FF9F}]/
+
MBCharWidthRE = /
(?<width_2_1>
[#{ EscapedChars.map {|c| "\\x%02x" % c.ord }.join }] (?# ^ + char, such as ^M, ^H, ^[, ...)
@@ -93,6 +95,12 @@ class Reline::Unicode
#{ EastAsianWidth::TYPE_H }
| #{ EastAsianWidth::TYPE_NA }
| #{ EastAsianWidth::TYPE_N }
+ )(?!#{ HalfwidthDakutenHandakuten })
+ | (?<width_2_3>
+ (?: #{ EastAsianWidth::TYPE_H }
+ | #{ EastAsianWidth::TYPE_NA }
+ | #{ EastAsianWidth::TYPE_N })
+ #{ HalfwidthDakutenHandakuten }
)
| (?<ambiguous_width>
#{EastAsianWidth::TYPE_A}
@@ -101,15 +109,15 @@ class Reline::Unicode
def self.get_mbchar_width(mbchar)
ord = mbchar.ord
- if (0x00 <= ord and ord <= 0x1F)
+ if (0x00 <= ord and ord <= 0x1F) # in EscapedPairs
return 2
- elsif (0x20 <= ord and ord <= 0x7E)
+ elsif (0x20 <= ord and ord <= 0x7E) # printable ASCII chars
return 1
end
m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE)
case
when m.nil? then 1 # TODO should be U+FFFD � REPLACEMENT CHARACTER
- when m[:width_2_1], m[:width_2_2] then 2
+ when m[:width_2_1], m[:width_2_2], m[:width_2_3] then 2
when m[:width_3] then 3
when m[:width_0] then 0
when m[:width_1] then 1
@@ -185,6 +193,37 @@ class Reline::Unicode
[lines, height]
end
+ # Take a chunk of a String cut by width with escape sequences.
+ def self.take_range(str, start_col, max_width, encoding = str.encoding)
+ chunk = String.new(encoding: encoding)
+ total_width = 0
+ rest = str.encode(Encoding::UTF_8)
+ in_zero_width = false
+ rest.scan(WIDTH_SCANNER) do |gc|
+ case
+ when gc[NON_PRINTING_START_INDEX]
+ in_zero_width = true
+ when gc[NON_PRINTING_END_INDEX]
+ in_zero_width = false
+ when gc[CSI_REGEXP_INDEX]
+ chunk << gc[CSI_REGEXP_INDEX]
+ when gc[OSC_REGEXP_INDEX]
+ chunk << gc[OSC_REGEXP_INDEX]
+ when gc[GRAPHEME_CLUSTER_INDEX]
+ gc = gc[GRAPHEME_CLUSTER_INDEX]
+ if in_zero_width
+ chunk << gc
+ else
+ mbchar_width = get_mbchar_width(gc)
+ total_width += mbchar_width
+ break if (start_col + max_width) < total_width
+ chunk << gc if start_col < total_width
+ end
+ end
+ end
+ chunk
+ end
+
def self.get_next_mbchar_size(line, byte_pointer)
grapheme = line.byteslice(byte_pointer..-1).grapheme_clusters.first
grapheme ? grapheme.bytesize : 0
diff --git a/lib/reline/version.rb b/lib/reline/version.rb
index d4aac2e3cb..67a3d694bd 100644
--- a/lib/reline/version.rb
+++ b/lib/reline/version.rb
@@ -1,3 +1,3 @@
module Reline
- VERSION = '0.2.7'
+ VERSION = '0.3.2'
end
diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb
index 5b4cb05b99..b952329911 100644
--- a/lib/reline/windows.rb
+++ b/lib/reline/windows.rb
@@ -42,6 +42,14 @@ class Reline::Windows
}.each_pair do |key, func|
config.add_default_key_binding_by_keymap(:emacs, key, func)
end
+
+ # Emulate ANSI key sequence.
+ {
+ [27, 91, 90] => :completion_journey_up, # S-Tab
+ }.each_pair do |key, func|
+ config.add_default_key_binding_by_keymap(:emacs, key, func)
+ config.add_default_key_binding_by_keymap(:vi_insert, key, func)
+ end
end
if defined? JRUBY_VERSION
@@ -87,7 +95,7 @@ class Reline::Windows
end
VK_RETURN = 0x0D
- VK_MENU = 0x12
+ VK_MENU = 0x12 # ALT key
VK_LMENU = 0xA4
VK_CONTROL = 0x11
VK_SHIFT = 0x10
@@ -106,6 +114,7 @@ class Reline::Windows
SCROLLLOCK_ON = 0x0040
SHIFT_PRESSED = 0x0010
+ VK_TAB = 0x09
VK_END = 0x23
VK_HOME = 0x24
VK_LEFT = 0x25
@@ -133,9 +142,11 @@ class Reline::Windows
@@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
@@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
@@FillConsoleOutputAttribute = Win32API.new('kernel32', 'FillConsoleOutputAttribute', ['L', 'L', 'L', 'L', 'P'], 'L')
+ @@SetConsoleCursorInfo = Win32API.new('kernel32', 'SetConsoleCursorInfo', ['L', 'P'], 'L')
@@GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L')
@@SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L')
+ @@WaitForSingleObject = Win32API.new('kernel32', 'WaitForSingleObject', ['L', 'L'], 'L')
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
private_class_method def self.getconsolemode
@@ -157,7 +168,9 @@ class Reline::Windows
@@input_buf = []
@@output_buf = []
- def self.msys_tty?(io=@@hConsoleInputHandle)
+ @@output = STDOUT
+
+ def self.msys_tty?(io = @@hConsoleInputHandle)
# check if fd is a pipe
if @@GetFileType.call(io) != FILE_TYPE_PIPE
return false
@@ -173,7 +186,7 @@ class Reline::Windows
# DWORD FileNameLength;
# WCHAR FileName[1];
# } FILE_NAME_INFO
- len = p_buffer[0, 4].unpack("L")[0]
+ len = p_buffer[0, 4].unpack1("L")
name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
# Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
@@ -197,10 +210,34 @@ class Reline::Windows
[ { control_keys: [], virtual_key_code: VK_DELETE }, [0, 83] ],
[ { control_keys: [], virtual_key_code: VK_HOME }, [0, 71] ],
[ { control_keys: [], virtual_key_code: VK_END }, [0, 79] ],
+
+ # Emulate ANSI key sequence.
+ [ { control_keys: :SHIFT, virtual_key_code: VK_TAB }, [27, 91, 90] ],
]
+ @@hsg = nil
+
def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
+ # high-surrogate
+ if 0xD800 <= char_code and char_code <= 0xDBFF
+ @@hsg = char_code
+ return
+ end
+ # low-surrogate
+ if 0xDC00 <= char_code and char_code <= 0xDFFF
+ if @@hsg
+ char_code = 0x10000 + (@@hsg - 0xD800) * 0x400 + char_code - 0xDC00
+ @@hsg = nil
+ else
+ # no high-surrogate. ignored.
+ return
+ end
+ else
+ # ignore high-surrogate without low-surrogate if there
+ @@hsg = nil
+ end
+
key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state)
match = KEY_MAP.find { |args,| key.matches?(**args) }
@@ -212,30 +249,42 @@ class Reline::Windows
# no char, only control keys
return if key.char_code == 0 and key.control_keys.any?
+ @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
+
@@output_buf.concat(key.char.bytes)
end
def self.check_input_event
num_of_events = 0.chr * 8
- while @@output_buf.empty? #or true
- next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack('L').first == 0
- input_record = 0.chr * 18
+ while @@output_buf.empty?
+ Reline.core.line_editor.resize
+ if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
+ # prevent for background consolemode change
+ @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
+ next
+ end
+ next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
+ input_records = 0.chr * 20 * 80
read_event = 0.chr * 4
- if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
- event = input_record[0, 2].unpack('s*').first
- case event
- when WINDOW_BUFFER_SIZE_EVENT
- @@winch_handler.()
- when KEY_EVENT
- key_down = input_record[4, 4].unpack('l*').first
- repeat_count = input_record[8, 2].unpack('s*').first
- virtual_key_code = input_record[10, 2].unpack('s*').first
- virtual_scan_code = input_record[12, 2].unpack('s*').first
- char_code = input_record[14, 2].unpack('S*').first
- control_key_state = input_record[16, 2].unpack('S*').first
- is_key_down = key_down.zero? ? false : true
- if is_key_down
- process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
+ if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_records, 80, read_event) != 0
+ read_events = read_event.unpack1('L')
+ 0.upto(read_events) do |idx|
+ input_record = input_records[idx * 20, 20]
+ event = input_record[0, 2].unpack1('s*')
+ case event
+ when WINDOW_BUFFER_SIZE_EVENT
+ @@winch_handler.()
+ when KEY_EVENT
+ key_down = input_record[4, 4].unpack1('l*')
+ repeat_count = input_record[8, 2].unpack1('s*')
+ virtual_key_code = input_record[10, 2].unpack1('s*')
+ virtual_scan_code = input_record[12, 2].unpack1('s*')
+ char_code = input_record[14, 2].unpack1('S*')
+ control_key_state = input_record[16, 2].unpack1('S*')
+ is_key_down = key_down.zero? ? false : true
+ if is_key_down
+ process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
+ end
end
end
end
@@ -256,7 +305,7 @@ class Reline::Windows
end
def self.empty_buffer?
- if not @@input_buf.empty?
+ if not @@output_buf.empty?
false
elsif @@kbhit.call == 0
true
@@ -265,17 +314,37 @@ class Reline::Windows
end
end
- def self.get_screen_size
+ def self.get_console_screen_buffer_info
+ # CONSOLE_SCREEN_BUFFER_INFO
+ # [ 0,2] dwSize.X
+ # [ 2,2] dwSize.Y
+ # [ 4,2] dwCursorPositions.X
+ # [ 6,2] dwCursorPositions.Y
+ # [ 8,2] wAttributes
+ # [10,2] srWindow.Left
+ # [12,2] srWindow.Top
+ # [14,2] srWindow.Right
+ # [16,2] srWindow.Bottom
+ # [18,2] dwMaximumWindowSize.X
+ # [20,2] dwMaximumWindowSize.Y
csbi = 0.chr * 22
- @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
+ return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
+ csbi
+ end
+
+ def self.get_screen_size
+ unless csbi = get_console_screen_buffer_info
+ return [1, 1]
+ end
csbi[0, 4].unpack('SS').reverse
end
def self.cursor_pos
- csbi = 0.chr * 22
- @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
- x = csbi[4, 2].unpack('s*').first
- y = csbi[6, 2].unpack('s*').first
+ unless csbi = get_console_screen_buffer_info
+ return Reline::CursorPos.new(0, 0)
+ end
+ x = csbi[4, 2].unpack1('s')
+ y = csbi[6, 2].unpack1('s')
Reline::CursorPos.new(x, y)
end
@@ -295,6 +364,7 @@ class Reline::Windows
def self.move_cursor_down(val)
if val > 0
+ return unless csbi = get_console_screen_buffer_info
screen_height = get_screen_size.first
y = cursor_pos.y + val
y = screen_height - 1 if y > (screen_height - 1)
@@ -305,42 +375,74 @@ class Reline::Windows
end
def self.erase_after_cursor
- csbi = 0.chr * 24
- @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
- cursor = csbi[4, 4].unpack('L').first
+ return unless csbi = get_console_screen_buffer_info
+ attributes = csbi[8, 2].unpack1('S')
+ cursor = csbi[4, 4].unpack1('L')
written = 0.chr * 4
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
- @@FillConsoleOutputAttribute.call(@@hConsoleHandle, 0, get_screen_size.last - cursor_pos.x, cursor, written)
+ @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, get_screen_size.last - cursor_pos.x, cursor, written)
end
def self.scroll_down(val)
- return if val.zero?
- 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')
- @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
+ return if val < 0
+ return unless csbi = get_console_screen_buffer_info
+ buffer_width, buffer_lines, x, y, attributes, window_left, window_top, window_bottom = csbi.unpack('ssssSssx2s')
+ screen_height = window_bottom - window_top + 1
+ val = screen_height if val > screen_height
+
+ if @@legacy_console || window_left != 0
+ # unless ENABLE_VIRTUAL_TERMINAL,
+ # if srWindow.Left != 0 then it's conhost.exe hosted console
+ # and puts "\n" causes horizontal scroll. its glitch.
+ # FYI irb write from culumn 1, so this gives no gain.
+ scroll_rectangle = [0, val, buffer_width, buffer_lines - val].pack('s4')
+ destination_origin = 0 # y * 65536 + x
+ fill = [' '.ord, attributes].pack('SS')
+ @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
+ else
+ origin_x = x + 1
+ origin_y = y - window_top + 1
+ @@output.write [
+ (origin_y != screen_height) ? "\e[#{screen_height};H" : nil,
+ "\n" * val,
+ (origin_y != screen_height or !x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil
+ ].join
+ end
end
def self.clear_screen
- csbi = 0.chr * 22
- return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
- buffer_width = csbi[0, 2].unpack('S').first
- attributes = csbi[8, 2].unpack('S').first
- _window_left, window_top, _window_right, window_bottom = *csbi[10,8].unpack('S*')
- fill_length = buffer_width * (window_bottom - window_top + 1)
- screen_topleft = window_top * 65536
- written = 0.chr * 4
- @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, fill_length, screen_topleft, written)
- @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, fill_length, screen_topleft, written)
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, screen_topleft)
+ if @@legacy_console
+ return unless csbi = get_console_screen_buffer_info
+ buffer_width, _buffer_lines, attributes, window_top, window_bottom = csbi.unpack('ss@8S@12sx2s')
+ fill_length = buffer_width * (window_bottom - window_top + 1)
+ screen_topleft = window_top * 65536
+ written = 0.chr * 4
+ @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, fill_length, screen_topleft, written)
+ @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, fill_length, screen_topleft, written)
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, screen_topleft)
+ else
+ @@output.write "\e[2J" "\e[H"
+ end
end
def self.set_screen_size(rows, columns)
raise NotImplementedError
end
+ def self.hide_cursor
+ size = 100
+ visible = 0 # 0 means false
+ cursor_info = [size, visible].pack('Li')
+ @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
+ end
+
+ def self.show_cursor
+ size = 100
+ visible = 1 # 1 means true
+ cursor_info = [size, visible].pack('Li')
+ @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
+ end
+
def self.set_winch_handler(&handler)
@@winch_handler = handler
end
diff --git a/lib/resolv-replace.gemspec b/lib/resolv-replace.gemspec
index 6bc07dbe10..48f7108a8e 100644
--- a/lib/resolv-replace.gemspec
+++ b/lib/resolv-replace.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "resolv-replace"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/resolv.gemspec b/lib/resolv.gemspec
index c6a0609b51..f221010ab6 100644
--- a/lib/resolv.gemspec
+++ b/lib/resolv.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "resolv"
- spec.version = "0.2.1"
+ spec.version = "0.2.3"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/resolv.rb b/lib/resolv.rb
index b69c7045ca..eaea69bfd5 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -1624,6 +1624,7 @@ class Resolv
prev_index = @index
save_index = nil
d = []
+ size = -1
while true
raise DecodeError.new("limit exceeded") if @limit <= @index
case @data.getbyte(@index)
@@ -1644,7 +1645,10 @@ class Resolv
end
@index = idx
else
- d << self.get_label
+ l = self.get_label
+ d << l
+ size += 1 + l.string.bytesize
+ raise DecodeError.new("name label data exceed 255 octets") if size > 255
end
end
end
@@ -2464,7 +2468,7 @@ class Resolv
Regex_8HexLinkLocal = /\A
[Ff][Ee]80
(?::[0-9A-Fa-f]{1,4}){7}
- %[0-9A-Za-z]+
+ %[-0-9A-Za-z._~]+
\z/x
##
@@ -2478,7 +2482,7 @@ class Resolv
|
:((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
)?
- :[0-9A-Fa-f]{1,4}%[0-9A-Za-z.]+
+ :[0-9A-Fa-f]{1,4}%[-0-9A-Za-z._~]+
\z/x
##
diff --git a/lib/rinda/rinda.gemspec b/lib/rinda/rinda.gemspec
index 1cc5a453d8..0c13e3c2df 100644
--- a/lib/rinda/rinda.gemspec
+++ b/lib/rinda/rinda.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "rinda"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Masatoshi SEKI"]
spec.email = ["seki@ruby-lang.org"]
diff --git a/lib/ruby_vm/mjit/c_pointer.rb b/lib/ruby_vm/mjit/c_pointer.rb
new file mode 100644
index 0000000000..a92c2140ae
--- /dev/null
+++ b/lib/ruby_vm/mjit/c_pointer.rb
@@ -0,0 +1,329 @@
+module RubyVM::MJIT # :nodoc: all
+ # Every class under this namespace is a pointer. Even if the type is
+ # immediate, it shouldn't be dereferenced until `*` is called.
+ module CPointer
+ # Note: We'd like to avoid alphabetic method names to avoid a conflict
+ # with member methods. to_i and to_s are considered an exception.
+ class Struct
+ # @param name [String]
+ # @param sizeof [Integer]
+ # @param members [Hash{ Symbol => [RubyVM::MJIT::CType::*, Integer, TrueClass] }]
+ def initialize(addr, sizeof, members)
+ @addr = addr
+ @sizeof = sizeof
+ @members = members
+ end
+
+ # Get a raw address
+ def to_i
+ @addr
+ end
+
+ # Serialized address for generated code
+ def to_s
+ "0x#{@addr.to_s(16)}"
+ end
+
+ # Pointer diff
+ def -(struct)
+ raise ArgumentError if self.class != struct.class
+ (@addr - struct.to_i) / @sizeof
+ end
+
+ # Primitive API that does no automatic dereference
+ # TODO: remove this?
+ # @param member [Symbol]
+ def [](member)
+ type, offset = @members.fetch(member)
+ type.new(@addr + offset / 8)
+ end
+
+ private
+
+ # @param member [Symbol]
+ # @param value [Object]
+ def []=(member, value)
+ type, offset = @members.fetch(member)
+ type[@addr + offset / 8] = value
+ end
+
+ # @param sizeof [Integer]
+ # @param members [Hash{ Symbol => [Integer, RubyVM::MJIT::CType::*] }]
+ def self.define(sizeof, members)
+ Class.new(self) do
+ # Return the size of this type
+ define_singleton_method(:sizeof) { sizeof }
+
+ define_method(:initialize) do |addr = nil|
+ if addr.nil? # TODO: get rid of this feature later
+ addr = Fiddle.malloc(sizeof)
+ end
+ super(addr, sizeof, members)
+ end
+
+ members.each do |member, (type, offset, to_ruby)|
+ # Intelligent API that does automatic dereference
+ define_method(member) do
+ value = self[member]
+ if value.respond_to?(:*)
+ value = value.*
+ end
+ if to_ruby
+ value = C.to_ruby(value)
+ end
+ value
+ end
+
+ define_method("#{member}=") do |value|
+ self[member] = value
+ end
+ end
+ end
+ end
+ end
+
+ # Note: We'd like to avoid alphabetic method names to avoid a conflict
+ # with member methods. to_i is considered an exception.
+ class Union
+ # @param _name [String] To be used when it starts defining a union pointer class
+ # @param sizeof [Integer]
+ # @param members [Hash{ Symbol => RubyVM::MJIT::CType::* }]
+ def initialize(addr, sizeof, members)
+ @addr = addr
+ @sizeof = sizeof
+ @members = members
+ end
+
+ # Get a raw address
+ def to_i
+ @addr
+ end
+
+ # Move addr to access this pointer like an array
+ def +(index)
+ raise ArgumentError unless index.is_a?(Integer)
+ self.class.new(@addr + index * @sizeof)
+ end
+
+ # Pointer diff
+ def -(union)
+ raise ArgumentError if self.class != union.class
+ (@addr - union.instance_variable_get(:@addr)) / @sizeof
+ end
+
+ # @param sizeof [Integer]
+ # @param members [Hash{ Symbol => RubyVM::MJIT::CType::* }]
+ def self.define(sizeof, members)
+ Class.new(self) do
+ # Return the size of this type
+ define_singleton_method(:sizeof) { sizeof }
+
+ define_method(:initialize) do |addr|
+ super(addr, sizeof, members)
+ end
+
+ members.each do |member, type|
+ # Intelligent API that does automatic dereference
+ define_method(member) do
+ value = type.new(@addr)
+ if value.respond_to?(:*)
+ value = value.*
+ end
+ value
+ end
+ end
+ end
+ end
+ end
+
+ class Immediate
+ # @param addr [Integer]
+ # @param size [Integer]
+ # @param pack [String]
+ def initialize(addr, size, pack)
+ @addr = addr
+ @size = size
+ @pack = pack
+ end
+
+ # Get a raw address
+ def to_i
+ @addr
+ end
+
+ # Move addr to addess this pointer like an array
+ def +(index)
+ Immediate.new(@addr + index * @size, @size, @pack)
+ end
+
+ # Dereference
+ def *
+ self[0]
+ end
+
+ # Array access
+ def [](index)
+ return nil if @addr == 0
+ Fiddle::Pointer.new(@addr + index * @size)[0, @size].unpack1(@pack)
+ end
+
+ # Array set
+ def []=(index, value)
+ Fiddle::Pointer.new(@addr + index * @size)[0, @size] = [value].pack(@pack)
+ end
+
+ # Serialized address for generated code. Used for embedding things like body->iseq_encoded.
+ def to_s
+ "0x#{Integer(@addr).to_s(16)}"
+ end
+
+ # @param fiddle_type [Integer] Fiddle::TYPE_*
+ def self.define(fiddle_type)
+ size = Fiddle::PackInfo::SIZE_MAP.fetch(fiddle_type)
+ pack = Fiddle::PackInfo::PACK_MAP.fetch(fiddle_type)
+
+ Class.new(self) do
+ define_method(:initialize) do |addr|
+ super(addr, size, pack)
+ end
+
+ define_singleton_method(:size) do
+ size
+ end
+
+ # Type-level []=: Used by struct fields
+ define_singleton_method(:[]=) do |addr, value|
+ Fiddle::Pointer.new(addr)[0, size] = [value].pack(pack)
+ end
+ end
+ end
+ end
+
+ # -Fiddle::TYPE_CHAR Immediate with special handling of true/false
+ class Bool < Immediate.define(-Fiddle::TYPE_CHAR)
+ # Dereference
+ def *
+ return nil if @addr == 0
+ super != 0
+ end
+
+ def self.[]=(addr, value)
+ super(addr, value ? 1 : 0)
+ end
+ end
+
+ class Pointer
+ attr_reader :type
+
+ # @param addr [Integer]
+ # @param type [Class] RubyVM::MJIT::CType::*
+ def initialize(addr, type)
+ @addr = addr
+ @type = type
+ end
+
+ # Move addr to addess this pointer like an array
+ def +(index)
+ raise ArgumentError unless index.is_a?(Integer)
+ Pointer.new(@addr + index * Fiddle::SIZEOF_VOIDP, @type)
+ end
+
+ # Dereference
+ def *
+ return nil if dest_addr == 0
+ @type.new(dest_addr)
+ end
+
+ # Array access
+ def [](index)
+ (self + index).*
+ end
+
+ # Array set
+ # @param index [Integer]
+ # @param value [Integer, RubyVM::MJIT::CPointer::Struct] an address itself or an object that return an address with to_i
+ def []=(index, value)
+ Fiddle::Pointer.new(@addr + index * Fiddle::SIZEOF_VOIDP)[0, Fiddle::SIZEOF_VOIDP] =
+ [value.to_i].pack(Fiddle::PackInfo::PACK_MAP[Fiddle::TYPE_VOIDP])
+ end
+
+ private
+
+ def dest_addr
+ Fiddle::Pointer.new(@addr)[0, Fiddle::SIZEOF_VOIDP].unpack1(Fiddle::PackInfo::PACK_MAP[Fiddle::TYPE_VOIDP])
+ end
+
+ def self.define(block)
+ Class.new(self) do
+ define_method(:initialize) do |addr|
+ super(addr, block.call)
+ end
+
+ # Type-level []=: Used by struct fields
+ # @param addr [Integer]
+ # @param value [Integer, RubyVM::MJIT::CPointer::Struct] an address itself, or an object that return an address with to_i
+ define_singleton_method(:[]=) do |addr, value|
+ value = value.to_i
+ Fiddle::Pointer.new(addr)[0, Fiddle::SIZEOF_VOIDP] = [value].pack(Fiddle::PackInfo::PACK_MAP[Fiddle::TYPE_VOIDP])
+ end
+ end
+ end
+ end
+
+ class BitField
+ # @param addr [Integer]
+ # @param width [Integer]
+ # @param offset [Integer]
+ def initialize(addr, width, offset)
+ @addr = addr
+ @width = width
+ @offset = offset
+ end
+
+ # Dereference
+ def *
+ byte = Fiddle::Pointer.new(@addr)[0, Fiddle::SIZEOF_CHAR].unpack1('c')
+ if @width == 1
+ bit = (1 & (byte >> @offset))
+ bit == 1
+ elsif @width <= 8 && @offset == 0
+ bitmask = @width.times.sum { |i| 1 << i }
+ byte & bitmask
+ else
+ raise NotImplementedError.new("not-implemented bit field access: width=#{@width} offset=#{@offset}")
+ end
+ end
+
+ # @param width [Integer]
+ # @param offset [Integer]
+ def self.define(width, offset)
+ Class.new(self) do
+ define_method(:initialize) do |addr|
+ super(addr, width, offset)
+ end
+ end
+ end
+ end
+
+ # Give a name to a dynamic CPointer class to see it on inspect
+ def self.with_class_name(prefix, name, cache: false, &block)
+ return block.call if name.empty?
+
+ # Use a cached result only if cache: true
+ class_name = "#{prefix}_#{name}"
+ klass =
+ if cache && self.const_defined?(class_name)
+ self.const_get(class_name)
+ else
+ block.call
+ end
+
+ # Give it a name unless it's already defined
+ unless self.const_defined?(class_name)
+ self.const_set(class_name, klass)
+ end
+
+ klass
+ end
+ end
+end
diff --git a/lib/ruby_vm/mjit/c_type.rb b/lib/ruby_vm/mjit/c_type.rb
new file mode 100644
index 0000000000..9c965ad2fb
--- /dev/null
+++ b/lib/ruby_vm/mjit/c_type.rb
@@ -0,0 +1,91 @@
+require 'fiddle'
+require 'fiddle/pack'
+require_relative 'c_pointer'
+
+module RubyVM::MJIT # :nodoc: all
+ module CType
+ module Struct
+ # @param name [String]
+ # @param members [Hash{ Symbol => [Integer, RubyVM::MJIT::CType::*] }]
+ def self.new(name, sizeof, **members)
+ name = members.keys.join('_') if name.empty?
+ CPointer.with_class_name('Struct', name) do
+ CPointer::Struct.define(sizeof, members)
+ end
+ end
+ end
+
+ module Union
+ # @param name [String]
+ # @param members [Hash{ Symbol => RubyVM::MJIT::CType::* }]
+ def self.new(name, sizeof, **members)
+ name = members.keys.join('_') if name.empty?
+ CPointer.with_class_name('Union', name) do
+ CPointer::Union.define(sizeof, members)
+ end
+ end
+ end
+
+ module Immediate
+ # @param fiddle_type [Integer]
+ def self.new(fiddle_type)
+ name = Fiddle.constants.find do |const|
+ const.start_with?('TYPE_') && Fiddle.const_get(const) == fiddle_type.abs
+ end&.to_s
+ name.delete_prefix!('TYPE_')
+ if fiddle_type.negative?
+ name.prepend('U')
+ end
+ CPointer.with_class_name('Immediate', name, cache: true) do
+ CPointer::Immediate.define(fiddle_type)
+ end
+ end
+
+ # @param type [String]
+ def self.parse(ctype)
+ new(Fiddle::Importer.parse_ctype(ctype))
+ end
+
+ def self.find(size, signed)
+ fiddle_type = TYPE_MAP.fetch(size)
+ fiddle_type = -fiddle_type unless signed
+ new(fiddle_type)
+ end
+
+ TYPE_MAP = Fiddle::PackInfo::SIZE_MAP.map { |type, size| [size, type.abs] }.to_h
+ private_constant :TYPE_MAP
+ end
+
+ module Bool
+ def self.new
+ CPointer::Bool
+ end
+ end
+
+ class Pointer
+ # This takes a block to avoid "stack level too deep" on a cyclic reference
+ # @param block [Proc]
+ def self.new(&block)
+ CPointer.with_class_name('Pointer', block.object_id.to_s) do
+ CPointer::Pointer.define(block)
+ end
+ end
+ end
+
+ module BitField
+ # @param width [Integer]
+ # @param offset [Integer]
+ def self.new(width, offset)
+ CPointer.with_class_name('BitField', "#{offset}_#{width}") do
+ CPointer::BitField.define(width, offset)
+ end
+ end
+ end
+
+ # Types that are referenced but not part of code generation targets
+ Stub = ::Struct.new(:name)
+
+ # Types that it failed to figure out from the header
+ Unknown = Module.new
+ end
+end
diff --git a/lib/ruby_vm/mjit/compiler.rb b/lib/ruby_vm/mjit/compiler.rb
new file mode 100644
index 0000000000..81022cd0a8
--- /dev/null
+++ b/lib/ruby_vm/mjit/compiler.rb
@@ -0,0 +1,952 @@
+# Available variables and macros in JIT-ed function:
+# ec: the first argument of _mjitXXX
+# reg_cfp: the second argument of _mjitXXX
+# 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 `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
+# 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
+# DISPATCH_ORIGINAL_INSN(): expanded in _mjit_compile_insn.erb
+# THROW_EXCEPTION(): specially defined for JIT
+# RESTORE_REGS(): specially defined for `leave`
+class RubyVM::MJIT::Compiler # :nodoc: all
+ C = RubyVM::MJIT.const_get(:C, false)
+ INSNS = RubyVM::MJIT.const_get(:INSNS, false)
+ UNSUPPORTED_INSNS = [
+ :defineclass, # low priority
+ ]
+
+ def initialize = freeze
+
+ # @param iseq [RubyVM::MJIT::CPointer::Struct]
+ # @param funcname [String]
+ # @param id [Integer]
+ # @return [String,NilClass]
+ def compile(iseq, funcname, id)
+ status = C.compile_status.new # not freed for now
+ status.compiled_iseq = iseq.body
+ status.compiled_id = id
+ init_compile_status(status, iseq.body, true) # not freed for now
+ if iseq.body.ci_size > 0 && status.cc_entries_index == -1
+ return nil
+ end
+
+ src = +''
+ if !status.compile_info.disable_send_cache && !status.compile_info.disable_inlining
+ unless precompile_inlinable_iseqs(src, iseq, status)
+ return nil
+ end
+ end
+
+ src << "VALUE\n#{funcname}(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)\n{\n"
+ success = compile_body(src, iseq, status)
+ src << "\n} // end of #{funcname}\n"
+
+ return success ? src : nil
+ rescue Exception => e # should we use rb_rescue in C instead?
+ if C.mjit_opts.warnings || C.mjit_opts.verbose > 0
+ $stderr.puts "MJIT error: #{e.full_message}"
+ end
+ return nil
+ end
+
+ private
+
+ def compile_body(src, iseq, status)
+ status.success = true
+ status.local_stack_p = !iseq.body.catch_except_p
+
+ if status.local_stack_p
+ src << " VALUE stack[#{iseq.body.stack_max}];\n"
+ else
+ src << " VALUE *stack = reg_cfp->sp;\n"
+ end
+
+ unless status.inlined_iseqs.nil? # i.e. compile root
+ src << " static const rb_iseq_t *original_iseq = (const rb_iseq_t *)#{iseq};\n"
+ end
+ src << " static const VALUE *const original_body_iseq = (VALUE *)#{iseq.body.iseq_encoded};\n"
+
+ src << " VALUE cfp_self = reg_cfp->self;\n" # cache self across the method
+ src << "#undef GET_SELF\n"
+ src << "#define GET_SELF() cfp_self\n"
+
+ # Generate merged ivar guards first if needed
+ if !status.compile_info.disable_ivar_cache && using_ivar?(iseq.body)
+ src << " if (UNLIKELY(!RB_TYPE_P(GET_SELF(), T_OBJECT))) {"
+ src << " goto ivar_cancel;\n"
+ src << " }\n"
+ end
+
+ # 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 jit_exec for catch tables.
+ if iseq.body.param.flags.has_opt
+ src << "\n"
+ src << " switch (reg_cfp->pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded) {\n"
+ (0..iseq.body.param.opt_num).each do |i|
+ pc_offset = iseq.body.param.opt_table[i]
+ src << " case #{pc_offset}:\n"
+ src << " goto label_#{pc_offset};\n"
+ end
+ src << " }\n"
+ end
+
+ compile_insns(0, 0, status, iseq.body, src)
+ compile_cancel_handler(src, iseq.body, status)
+ src << "#undef GET_SELF\n"
+ return status.success
+ end
+
+ # Compile one conditional branch. If it has branchXXX insn, this should be
+ # called multiple times for each branch.
+ def compile_insns(stack_size, pos, status, body, src)
+ branch = C.compile_branch.new # not freed for now
+ branch.stack_size = stack_size
+ branch.finish_p = false
+
+ while pos < body.iseq_size && !already_compiled?(status, pos) && !branch.finish_p
+ insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
+ status.stack_size_for_pos[pos] = branch.stack_size
+
+ src << "\nlabel_#{pos}: /* #{insn.name} */\n"
+ pos = compile_insn(insn, pos, status, body.iseq_encoded + (pos+1), body, branch, src)
+ if status.success && branch.stack_size > body.stack_max
+ if mjit_opts.warnings || mjit_opts.verbose > 0
+ $stderr.puts "MJIT warning: JIT stack size (#{branch.stack_size}) exceeded its max size (#{body.stack_max})"
+ end
+ status.success = false
+ end
+ break unless status.success
+ end
+ end
+
+ # Main function of JIT compilation, vm_exec_core counterpart for JIT. Compile one insn to `f`, may modify
+ # b->stack_size and return next position.
+ #
+ # When you add a new instruction to insns.def, it would be nice to have JIT compilation support here but
+ # it's optional. This JIT compiler just ignores ISeq which includes unknown instruction, and ISeq which
+ # does not have it can be compiled as usual.
+ def compile_insn(insn, pos, status, operands, body, b, src)
+ sp_inc = C.mjit_call_attribute_sp_inc(insn.bin, operands)
+ next_pos = pos + insn.len
+
+ result = compile_insn_entry(insn, b.stack_size, sp_inc, status.local_stack_p, pos, next_pos, insn.len,
+ status.inlined_iseqs.nil?, status, operands, body)
+ if result.nil?
+ if C.mjit_opts.warnings || C.mjit_opts.verbose > 0
+ $stderr.puts "MJIT warning: Skipped to compile unsupported instruction: #{insn.name}"
+ end
+ status.success = false
+ else
+ result_src, next_pos, finish_p, compile_insns_p = result
+
+ src << result_src
+ b.stack_size += sp_inc
+
+ if finish_p
+ b.finish_p = true
+ end
+ if compile_insns_p
+ if already_compiled?(status, pos + insn.len)
+ src << "goto label_#{pos + insn.len};\n"
+ else
+ compile_insns(b.stack_size, pos + insn.len, status, body, src)
+ end
+ end
+ end
+
+ # If next_pos is already compiled and this branch is not finished yet,
+ # next instruction won't be compiled in C code next and will need `goto`.
+ if !b.finish_p && next_pos < body.iseq_size && already_compiled?(status, next_pos)
+ src << "goto label_#{next_pos};\n"
+
+ # Verify stack size assumption is the same among multiple branches
+ if status.stack_size_for_pos[next_pos] != b.stack_size
+ if mjit_opts.warnings || mjit_opts.verbose > 0
+ $stderr.puts "MJIT warning: JIT stack assumption is not the same between branches (#{status.stack_size_for_pos[next_pos]} != #{b.stack_size})\n"
+ end
+ status.success = false
+ end
+ end
+
+ return next_pos
+ end
+
+ def compile_insn_entry(insn, stack_size, sp_inc, local_stack_p, pos, next_pos, insn_len, inlined_iseq_p, status, operands, body)
+ finish_p = false
+ compile_insns = false
+
+ # TODO: define this outside this method, or at least cache it
+ opt_send_without_block = INSNS.values.find { |i| i.name == :opt_send_without_block }
+ if opt_send_without_block.nil?
+ raise 'opt_send_without_block not found'
+ end
+ send_compatible_opt_insns = INSNS.values.select do |insn|
+ insn.name.start_with?('opt_') && opt_send_without_block.opes == insn.opes &&
+ insn.expr.lines.any? { |l| l.match(/\A\s+CALL_SIMPLE_METHOD\(\);\s+\z/) }
+ end.map(&:name)
+
+ case insn.name
+ when *UNSUPPORTED_INSNS
+ return nil
+ when :opt_send_without_block, :send
+ if src = compile_send(insn, stack_size, sp_inc, local_stack_p, pos, next_pos, status, operands, body)
+ return src, next_pos, finish_p, compile_insns
+ end
+ when *send_compatible_opt_insns
+ if C.has_cache_for_send(captured_cc_entries(status)[call_data_index(C.CALL_DATA.new(operands[0]), body)], insn.bin) &&
+ src = compile_send(opt_send_without_block, stack_size, sp_inc, local_stack_p, pos, next_pos, status, operands, body)
+ return src, next_pos, finish_p, compile_insns
+ end
+ when :getinstancevariable, :setinstancevariable
+ if src = compile_ivar(insn.name, stack_size, pos, status, operands, body)
+ return src, next_pos, finish_p, compile_insns
+ end
+ when :opt_getconstant_path
+ if src = compile_getconstant_path(stack_size, pos, insn_len, operands, status)
+ return src, next_pos, finish_p, compile_insns
+ end
+ when :invokebuiltin, :opt_invokebuiltin_delegate, :opt_invokebuiltin_delegate_leave
+ if src = compile_invokebuiltin(insn, stack_size, sp_inc, body, operands)
+ if insn.name == :opt_invokebuiltin_delegate_leave
+ src << compile_leave(stack_size, pos, inlined_iseq_p)
+ finish_p = true
+ end
+ return src, next_pos, finish_p, compile_insns
+ end
+ when :leave
+ if stack_size != 1
+ raise "Unexpected JIT stack_size on leave: #{stack_size}"
+ end
+ src = compile_leave(stack_size, pos, inlined_iseq_p)
+ finish_p = true
+ return src, next_pos, finish_p, compile_insns
+ end
+
+ return compile_insn_default(insn, stack_size, sp_inc, local_stack_p, pos, next_pos, insn_len, inlined_iseq_p, operands)
+ end
+
+ # Optimized case of send / opt_send_without_block instructions.
+ def compile_send(insn, stack_size, sp_inc, local_stack_p, pos, next_pos, status, operands, body)
+ # compiler: Use captured cc to avoid race condition
+ cd = C.CALL_DATA.new(operands[0])
+ cd_index = call_data_index(cd, body)
+ captured_cc = captured_cc_entries(status)[cd_index]
+
+ # compiler: Inline send insn where some supported fastpath is used.
+ ci = cd.ci
+ kw_splat = (C.vm_ci_flag(ci) & C.VM_CALL_KW_SPLAT) > 0
+ 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 == C.VM_METHOD_TYPE_CFUNC && !C.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 == C.VM_METHOD_TYPE_ISEQ &&
+ C.fastpath_applied_iseq_p(ci, captured_cc, iseq = def_iseq_ptr(vm_cc_cme(captured_cc).def)) &&
+ (C.vm_ci_flag(ci) & C.VM_CALL_TAILCALL) == 0)
+ )
+ src = +"{\n"
+
+ # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
+ src << " const struct rb_callcache *cc = (struct rb_callcache *)#{captured_cc};\n"
+ src << " const rb_callable_method_entry_t *cc_cme = (rb_callable_method_entry_t *)#{vm_cc_cme(captured_cc)};\n"
+ src << " const VALUE recv = stack[#{stack_size + sp_inc - 1}];\n"
+ # If opt_class_of is true, use RBASIC_CLASS instead of CLASS_OF to reduce code size
+ opt_class_of = !maybe_special_const?(captured_cc.klass)
+ src << " if (UNLIKELY(#{opt_class_of ? 'RB_SPECIAL_CONST_P(recv)' : 'false'} || !vm_cc_valid_p(cc, cc_cme, #{opt_class_of ? 'RBASIC_CLASS' : 'CLASS_OF'}(recv)))) {\n"
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " goto send_cancel;\n"
+ src << " }\n"
+
+ # JIT: move sp and pc if necessary
+ pc_moved_p = compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
+
+ # JIT: If ISeq is inlinable, call the inlined method without pushing a frame.
+ if iseq && status.inlined_iseqs && iseq.body.to_i == status.inlined_iseqs[pos]&.to_i
+ src << " {\n"
+ src << " VALUE orig_self = reg_cfp->self;\n"
+ src << " reg_cfp->self = stack[#{stack_size + sp_inc - 1}];\n"
+ src << " stack[#{stack_size + sp_inc - 1}] = _mjit#{status.compiled_id}_inlined_#{pos}(ec, reg_cfp, orig_self, original_iseq);\n"
+ src << " reg_cfp->self = orig_self;\n"
+ src << " }\n"
+ else
+ # JIT: Forked `vm_sendish` (except method_explorer = vm_search_method_wrap) to inline various things
+ src << " {\n"
+ src << " VALUE val;\n"
+ src << " struct rb_calling_info calling;\n"
+ if insn.name == :send
+ src << " calling.block_handler = vm_caller_setup_arg_block(ec, reg_cfp, (const struct rb_callinfo *)#{ci}, (rb_iseq_t *)0x#{operands[1].to_s(16)}, FALSE);\n"
+ else
+ src << " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n"
+ end
+ src << " calling.kw_splat = #{kw_splat ? 1 : 0};\n"
+ src << " calling.recv = stack[#{stack_size + sp_inc - 1}];\n"
+ src << " calling.argc = #{C.vm_ci_argc(ci)};\n"
+
+ if vm_cc_cme(captured_cc).def.type == C.VM_METHOD_TYPE_CFUNC
+ # TODO: optimize this more
+ src << " calling.ci = (const struct rb_callinfo *)#{ci};\n" # creating local cd here because operand's cd->cc may not be the same as inlined cc.
+ src << " calling.cc = cc;"
+ src << " val = vm_call_cfunc_with_frame(ec, reg_cfp, &calling);\n"
+ else # :iseq
+ # fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE
+ src << " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, cc_cme, 0, #{iseq.body.param.size}, #{iseq.body.local_table_size});\n"
+ if iseq.body.catch_except_p
+ src << " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"
+ src << " val = vm_exec(ec, true);\n"
+ else
+ src << " if ((val = jit_exec(ec)) == Qundef) {\n"
+ src << " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n" # This is vm_call0_body's code after vm_call_iseq_setup
+ src << " val = vm_exec(ec, false);\n"
+ src << " }\n"
+ end
+ end
+ src << " stack[#{stack_size + sp_inc - 1}] = val;\n"
+ src << " }\n"
+
+ # JIT: We should evaluate ISeq modified for TracePoint if it's enabled. Note: This is slow.
+ src << " if (UNLIKELY(!mjit_call_p)) {\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size + sp_inc};\n"
+ if !pc_moved_p
+ src << " reg_cfp->pc = original_body_iseq + #{next_pos};\n"
+ end
+ src << " goto cancel;\n"
+ src << " }\n"
+ end
+
+ src << "}\n"
+ return src
+ else
+ return nil
+ end
+ end
+
+ def compile_ivar(insn_name, stack_size, pos, status, operands, body)
+ iv_cache = C.iseq_inline_storage_entry.new(operands[1]).iv_cache
+ dest_shape_id = iv_cache.value >> C.SHAPE_FLAG_SHIFT
+ source_shape_id = parent_shape_id(dest_shape_id)
+ attr_index = iv_cache.value & ((1 << C.SHAPE_FLAG_SHIFT) - 1)
+
+ src = +''
+ if !status.compile_info.disable_ivar_cache && source_shape_id != C.INVALID_SHAPE_ID
+ # 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`.
+ # compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
+
+ # JIT: prepare vm_getivar/vm_setivar arguments and variables
+ src << "{\n"
+ src << " VALUE obj = GET_SELF();\n" # T_OBJECT guaranteed by compile_body
+ # JIT: cache hit path of vm_getivar/vm_setivar, or cancel JIT (recompile it with exivar)
+ if insn_name == :setinstancevariable
+ src << " const uint32_t index = #{attr_index - 1};\n"
+ src << " const shape_id_t dest_shape_id = (shape_id_t)#{dest_shape_id};\n"
+ src << " if (dest_shape_id == ROBJECT_SHAPE_ID(obj)) {\n"
+ src << " VALUE *ptr = ROBJECT_IVPTR(obj);\n"
+ src << " RB_OBJ_WRITE(obj, &ptr[index], stack[#{stack_size - 1}]);\n"
+ src << " }\n"
+ else
+ src << " const shape_id_t source_shape_id = (shape_id_t)#{dest_shape_id};\n"
+ if attr_index == 0 # cache hit, but uninitialized iv
+ src << " /* Uninitialized instance variable */\n"
+ src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj)) {\n"
+ src << " stack[#{stack_size}] = Qnil;\n"
+ src << " }\n"
+ else
+ src << " const uint32_t index = #{attr_index - 1};\n"
+ src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj)) {\n"
+ src << " stack[#{stack_size}] = ROBJECT_IVPTR(obj)[index];\n"
+ src << " }\n"
+ end
+ end
+ src << " else {\n"
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " goto ivar_cancel;\n"
+ src << " }\n"
+ src << "}\n"
+ return src
+ elsif insn_name == :getinstancevariable && !status.compile_info.disable_exivar_cache && source_shape_id != C.INVALID_SHAPE_ID
+ # 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`.
+ # compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
+
+ # JIT: prepare vm_getivar's arguments and variables
+ src << "{\n"
+ src << " VALUE obj = GET_SELF();\n"
+ src << " const shape_id_t source_shape_id = (shape_id_t)#{dest_shape_id};\n"
+ src << " const uint32_t index = #{attr_index - 1};\n"
+ # JIT: cache hit path of vm_getivar, or cancel JIT (recompile it without any ivar optimization)
+ src << " struct gen_ivtbl *ivtbl;\n"
+ src << " if (LIKELY(FL_TEST_RAW(GET_SELF(), FL_EXIVAR) && source_shape_id == rb_shape_get_shape_id(obj) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl))) {\n"
+ src << " stack[#{stack_size}] = ivtbl->ivptr[index];\n"
+ src << " }\n"
+ src << " else {\n"
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " goto exivar_cancel;\n"
+ src << " }\n"
+ src << "}\n"
+ return src
+ else
+ return nil
+ end
+ end
+
+ def compile_invokebuiltin(insn, stack_size, sp_inc, body, operands)
+ bf = C.RB_BUILTIN.new(operands[0])
+ if bf.compiler > 0
+ index = (insn.name == :invokebuiltin ? -1 : operands[1])
+ src = +"{\n"
+ src << " VALUE val;\n"
+ C.builtin_compiler(src, bf, index, stack_size, body.builtin_inline_p)
+ src << " stack[#{stack_size + sp_inc - 1}] = val;\n"
+ src << "}\n"
+ return src
+ else
+ return nil
+ end
+ end
+
+ def compile_leave(stack_size, pos, inlined_iseq_p)
+ src = +''
+ # Skip vm_pop_frame for inlined call
+ unless inlined_iseq_p
+ # Cancel on interrupts to make leave insn leaf
+ src << " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n"
+ src << " }\n"
+ src << " ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);\n" # vm_pop_frame
+ end
+ src << " return stack[0];\n"
+ end
+
+ def compile_getconstant_path(stack_size, pos, insn_len, operands, status)
+ ice = C.IC.new(operands[0]).entry
+ if !status.compile_info.disable_const_cache && ice
+ # JIT: Inline everything in IC, and cancel the slow path
+ src = +" if (vm_inlined_ic_hit_p(#{ice.flags}, #{ice.value}, (const rb_cref_t *)#{to_addr(ice.ic_cref)}, reg_cfp->ep)) {\n"
+ src << " stack[#{stack_size}] = #{ice.value};\n"
+ src << " }\n"
+ src << " else {\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " goto const_cancel;\n"
+ src << " }\n"
+ return src
+ else
+ return nil
+ end
+ end
+
+ def compile_insn_default(insn, stack_size, sp_inc, local_stack_p, pos, next_pos, insn_len, inlined_iseq_p, operands)
+ src = +''
+ finish_p = false
+ compile_insns = false
+
+ # JIT: Declare stack_size to be used in some macro of _mjit_compile_insn_body.erb
+ src << "{\n"
+ if local_stack_p
+ src << " MAYBE_UNUSED(unsigned int) stack_size = #{stack_size};\n"
+ end
+
+ # JIT: Declare variables for operands, popped values and return values
+ insn.declarations.each do |decl|
+ src << " #{decl};\n"
+ end
+
+ # JIT: Set const expressions for `RubyVM::OperandsUnifications` insn
+ insn.preamble.each do |amble|
+ src << "#{amble.sub(/const \S+\s+/, '')}\n"
+ end
+
+ # JIT: Initialize operands
+ insn.opes.each_with_index do |ope, i|
+ src << " #{ope.fetch(:name)} = (#{ope.fetch(:type)})#{operands[i]};\n"
+ # TODO: resurrect comment_id
+ end
+
+ # JIT: Initialize popped values
+ insn.pops.reverse_each.with_index.reverse_each do |pop, i|
+ src << " #{pop.fetch(:name)} = stack[#{stack_size - (i + 1)}];\n"
+ end
+
+ # JIT: move sp and pc if necessary
+ pc_moved_p = compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
+
+ # JIT: Print insn body in insns.def
+ next_pos = compile_insn_body(src, insn, pos, next_pos, insn_len, local_stack_p, stack_size, sp_inc, operands)
+
+ # JIT: Set return values
+ insn.rets.reverse_each.with_index do |ret, i|
+ # TOPN(n) = ...
+ src << " stack[#{stack_size + sp_inc - (i + 1)}] = #{ret.fetch(:name)};\n"
+ end
+
+ # JIT: We should evaluate ISeq modified for TracePoint if it's enabled. Note: This is slow.
+ # 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?
+ src << " if (UNLIKELY(!mjit_call_p)) {\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size + sp_inc};\n"
+ if !pc_moved_p
+ src << " reg_cfp->pc = original_body_iseq + #{next_pos};\n"
+ end
+ src << " goto cancel;\n"
+ src << " }\n"
+ end
+
+ src << "}\n"
+
+ # compiler: If insn has conditional JUMP, the code should go to the branch not targeted by JUMP next.
+ if insn.expr.match?(/if\s+\([^{}]+\)\s+\{[^{}]+JUMP\([^)]+\);[^{}]+\}/)
+ compile_insns = true
+ end
+
+ # compiler: If insn returns (leave) or does longjmp (throw), the branch should no longer be compiled. TODO: create attr for it?
+ if insn.expr.match?(/\sTHROW_EXCEPTION\([^)]+\);/) || insn.expr.match?(/\bvm_pop_frame\(/)
+ finish_p = true
+ end
+
+ return src, next_pos, finish_p, compile_insns
+ end
+
+ def compile_insn_body(src, insn, pos, next_pos, insn_len, local_stack_p, stack_size, sp_inc, operands)
+ # Print a body of insn, but with macro expansion.
+ expand_simple_macros(insn.expr).each_line do |line|
+ # Expand dynamic macro here
+ # 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
+ src << " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"
+ src << " reg_cfp->pc = original_body_iseq + #{next_pos};\n" # ADD_PC(INSN_ATTR(width));
+ src << " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n"
+ src << " if (UNLIKELY(!mjit_call_p)) {\n"
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ src << " goto cancel;\n"
+ src << " }\n"
+ src << " }\n"
+ else
+ src << to_cstr(line)
+ end
+ when /\A\s+JUMP\((?<dest>[^)]+)\);\s+\z/
+ dest = Regexp.last_match[:dest]
+ if insn.name == :opt_case_dispatch # special case... TODO: use another macro to avoid checking name
+ hash_offsets = C.rb_hash_values(operands[0]).uniq
+ else_offset = cast_offset(operands[1])
+ base_pos = pos + insn_len
+
+ src << " switch (#{dest}) {\n"
+ hash_offsets.each do |offset|
+ src << " case #{offset}:\n"
+ src << " goto label_#{base_pos + offset};\n"
+ end
+ src << " case #{else_offset}:\n"
+ src << " goto label_#{base_pos + else_offset};\n"
+ src << " }\n"
+ else
+ # Before we `goto` next insn, we need to set return values, especially for getinlinecache
+ insn.rets.reverse_each.with_index do |ret, i|
+ # TOPN(n) = ...
+ src << " stack[#{stack_size + sp_inc - (i + 1)}] = #{ret.fetch(:name)};\n"
+ end
+
+ next_pos = pos + insn_len + cast_offset(operands[0]) # workaround: assuming dest == operands[0]. TODO: avoid relying on it
+ src << " goto label_#{next_pos};\n"
+ end
+ when /\A\s+CALL_SIMPLE_METHOD\(\);\s+\z/
+ # For `opt_xxx`'s fallbacks.
+ if local_stack_p
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ end
+ src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
+ src << " goto cancel;\n"
+ when /\A(?<prefix>.+\b)INSN_LABEL\((?<name>[^)]+)\)(?<suffix>.+)\z/m
+ prefix, name, suffix = Regexp.last_match[:prefix], Regexp.last_match[:name], Regexp.last_match[:suffix]
+ src << "#{prefix}INSN_LABEL(#{name}_#{pos})#{suffix}"
+ else
+ if insn.handles_sp?
+ # If insn.handles_sp? is true, cfp->sp might be changed inside insns (like vm_caller_setup_arg_block)
+ # and thus we need to use cfp->sp, even when local_stack_p is TRUE. When insn.handles_sp? is true,
+ # cfp->sp should be available too because _mjit_compile_pc_and_sp.erb sets it.
+ src << to_cstr(line)
+ else
+ # If local_stack_p is TRUE and insn.handles_sp? is false, stack values are only available in local variables
+ # for stack. So we need to replace those macros if local_stack_p is TRUE here.
+ case line
+ when /\bGET_SP\(\)/
+ # reg_cfp->sp
+ src << to_cstr(line.sub(/\bGET_SP\(\)/, local_stack_p ? '(stack + stack_size)' : 'GET_SP()'))
+ when /\bSTACK_ADDR_FROM_TOP\((?<num>[^)]+)\)/
+ # #define STACK_ADDR_FROM_TOP(n) (GET_SP()-(n))
+ num = Regexp.last_match[:num]
+ src << to_cstr(line.sub(/\bSTACK_ADDR_FROM_TOP\(([^)]+)\)/, 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]
+ src << to_cstr(line.sub(/\bTOPN\(([^)]+)\)/, local_stack_p ? "*(stack + (stack_size - (#{num}) - 1))" : "TOPN(#{num})"))
+ else
+ src << to_cstr(line)
+ end
+ end
+ end
+ end
+ return next_pos
+ end
+
+ def compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
+ # 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.
+ pc_moved_p = false
+ unless insn.always_leaf? || insn.leaf_without_check_ints?
+ src << " reg_cfp->pc = original_body_iseq + #{next_pos};\n" # ADD_PC(INSN_ATTR(width));
+ pc_moved_p = true
+ end
+
+ # JIT: move sp to use or preserve stack variables
+ if local_stack_p
+ # sp motion is optimized away for `handles_sp? #=> false` case.
+ # Thus sp should be set properly before `goto cancel`.
+ if insn.handles_sp?
+ # JIT-only behavior (pushing JIT's local variables to VM's stack):
+ push_size = -sp_inc + insn.rets.size - insn.pops.size
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{push_size};\n"
+ push_size.times do |i|
+ src << " *(reg_cfp->sp + #{i - push_size}) = stack[#{stack_size - push_size + i}];\n"
+ end
+ end
+ else
+ if insn.handles_sp?
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size - insn.pops.size};\n" # POPN(INSN_ATTR(popn));
+ else
+ src << " reg_cfp->sp = vm_base_ptr(reg_cfp) + #{stack_size};\n"
+ end
+ end
+ return pc_moved_p
+ end
+
+ # Print the block to cancel inlined method call. It's supporting only `opt_send_without_block` for now.
+ def compile_inlined_cancel_handler(src, body, inline_context)
+ src << "\ncancel:\n"
+ src << " rb_mjit_recompile_inlining(original_iseq);\n"
+
+ # Swap pc/sp set on cancel with original pc/sp.
+ src << " const VALUE *current_pc = reg_cfp->pc;\n"
+ src << " VALUE *current_sp = reg_cfp->sp;\n"
+ src << " reg_cfp->pc = orig_pc;\n"
+ src << " reg_cfp->sp = orig_sp;\n\n"
+
+ # Lazily push the current call frame.
+ src << " struct rb_calling_info calling;\n"
+ src << " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n" # assumes `opt_send_without_block`
+ src << " calling.argc = #{inline_context.orig_argc};\n"
+ src << " calling.recv = reg_cfp->self;\n"
+ src << " reg_cfp->self = orig_self;\n"
+ # fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE
+ src << " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, (const rb_callable_method_entry_t *)#{inline_context.me}, 0, #{inline_context.param_size}, #{inline_context.local_size});\n\n"
+
+ # Start usual cancel from here.
+ src << " reg_cfp = ec->cfp;\n" # work on the new frame
+ src << " reg_cfp->pc = current_pc;\n"
+ src << " reg_cfp->sp = current_sp;\n"
+ (0...body.stack_max).each do |i| # should be always `status->local_stack_p`
+ src << " *(vm_base_ptr(reg_cfp) + #{i}) = stack[#{i}];\n"
+ end
+ # We're not just returning Qundef here so that caller's normal cancel handler can
+ # push back `stack` to `cfp->sp`.
+ src << " return vm_exec(ec, false);\n"
+ end
+
+ # Print the block to cancel JIT execution.
+ def compile_cancel_handler(src, body, status)
+ if status.inlined_iseqs.nil? # the current ISeq is being inlined
+ compile_inlined_cancel_handler(src, body, status.inline_context)
+ return
+ end
+
+ src << "\nsend_cancel:\n"
+ src << " rb_mjit_recompile_send(original_iseq);\n"
+ src << " goto cancel;\n"
+
+ src << "\nivar_cancel:\n"
+ src << " rb_mjit_recompile_ivar(original_iseq);\n"
+ src << " goto cancel;\n"
+
+ src << "\nexivar_cancel:\n"
+ src << " rb_mjit_recompile_exivar(original_iseq);\n"
+ src << " goto cancel;\n"
+
+ src << "\nconst_cancel:\n"
+ src << " rb_mjit_recompile_const(original_iseq);\n"
+ src << " goto cancel;\n"
+
+ src << "\ncancel:\n"
+ if status.local_stack_p
+ (0...body.stack_max).each do |i|
+ src << " *(vm_base_ptr(reg_cfp) + #{i}) = stack[#{i}];\n"
+ end
+ end
+ src << " return Qundef;\n"
+ end
+
+ def precompile_inlinable_child_iseq(src, child_iseq, status, ci, cc, pos)
+ child_status = C.compile_status.new # not freed for now
+ child_status.compiled_iseq = status.compiled_iseq
+ child_status.compiled_id = status.compiled_id
+ init_compile_status(child_status, child_iseq.body, false) # not freed for now
+ child_status.inline_context.orig_argc = C.vm_ci_argc(ci)
+ child_status.inline_context.me = vm_cc_cme(cc).to_i
+ child_status.inline_context.param_size = child_iseq.body.param.size
+ child_status.inline_context.local_size = child_iseq.body.local_table_size
+ if child_iseq.body.ci_size > 0 && child_status.cc_entries_index == -1
+ return false
+ end
+
+ src << "ALWAYS_INLINE(static VALUE _mjit#{status.compiled_id}_inlined_#{pos}(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n"
+ src << "static inline VALUE\n_mjit#{status.compiled_id}_inlined_#{pos}(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n"
+ src << " const VALUE *orig_pc = reg_cfp->pc;\n"
+ src << " VALUE *orig_sp = reg_cfp->sp;\n"
+
+ success = compile_body(src, child_iseq, child_status)
+
+ src << "\n} /* end of _mjit#{status.compiled_id}_inlined_#{pos} */\n\n"
+
+ return success;
+ end
+
+ def precompile_inlinable_iseqs(src, iseq, status)
+ body = iseq.body
+ pos = 0
+ while pos < body.iseq_size
+ insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
+ if insn.name == :opt_send_without_block || insn.name == :opt_size # `compile_inlined_cancel_handler` supports only `opt_send_without_block`
+ cd = C.CALL_DATA.new(body.iseq_encoded[pos + 1])
+ ci = cd.ci
+ cc = captured_cc_entries(status)[call_data_index(cd, body)] # use copy to avoid race condition
+
+ if (child_iseq = rb_mjit_inlinable_iseq(ci, cc)) != nil
+ status.inlined_iseqs[pos] = child_iseq.body
+
+ if C.mjit_opts.verbose >= 1 # print beforehand because ISeq may be GCed during copy job.
+ child_location = child_iseq.body.location
+ $stderr.puts "JIT inline: #{child_location.label}@#{C.rb_iseq_path(child_iseq)}:#{C.rb_iseq_first_lineno(child_iseq)} " \
+ "=> #{iseq.body.location.label}@#{C.rb_iseq_path(iseq)}:#{C.rb_iseq_first_lineno(iseq)}"
+ end
+ if !precompile_inlinable_child_iseq(src, child_iseq, status, ci, cc, pos)
+ return false
+ end
+ end
+ end
+ pos += insn.len
+ end
+ return true
+ end
+
+ def init_compile_status(status, body, compile_root_p)
+ status.stack_size_for_pos = Fiddle.malloc(Fiddle::SIZEOF_INT * body.iseq_size)
+ body.iseq_size.times do |i|
+ status.stack_size_for_pos[i] = C.NOT_COMPILED_STACK_SIZE
+ end
+ if compile_root_p
+ status.inlined_iseqs = Fiddle.malloc(Fiddle::SIZEOF_VOIDP * body.iseq_size)
+ body.iseq_size.times do |i|
+ status.inlined_iseqs[i] = nil
+ end
+ end
+ if body.ci_size > 0
+ status.cc_entries_index = C.mjit_capture_cc_entries(status.compiled_iseq, body)
+ else
+ status.cc_entries_index = -1
+ end
+ if compile_root_p
+ status.compile_info = rb_mjit_iseq_compile_info(body)
+ else
+ status.compile_info = Fiddle.malloc(C.rb_mjit_compile_info.sizeof)
+ status.compile_info.disable_ivar_cache = false
+ status.compile_info.disable_exivar_cache = false
+ status.compile_info.disable_send_cache = false
+ status.compile_info.disable_inlining = false
+ status.compile_info.disable_const_cache = false
+ end
+ end
+
+ def using_ivar?(body)
+ pos = 0
+ while pos < body.iseq_size
+ insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
+ case insn.name
+ when :getinstancevariable, :setinstancevariable
+ return true
+ end
+ pos += insn.len
+ end
+ return false
+ end
+
+ # Expand simple macro that doesn't require dynamic C code.
+ def expand_simple_macros(arg_expr)
+ arg_expr.dup.tap do |expr|
+ # 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]
+ <<-end.gsub(/^ {12}/, '')
+ #if OPT_CALL_THREADED_CODE
+ #{indent}rb_ec_thread_ptr(ec)->retval = val;
+ #{indent}return 0;
+ #else
+ #{indent}return val;
+ #endif
+ end
+ end
+ expr.gsub!(/^(?<indent>\s*)NEXT_INSN\(\);\n/) do
+ indent = Regexp.last_match[:indent]
+ <<-end.gsub(/^ {12}/, '')
+ #{indent}UNREACHABLE_RETURN(Qundef);
+ end
+ end
+ end
+ end
+
+ def to_cstr(expr)
+ expr.gsub(/^(?!#)/, ' ') # indent everything but preprocessor lines
+ end
+
+ # Interpret unsigned long as signed long (VALUE -> OFFSET)
+ def cast_offset(offset)
+ if offset >= 1 << 8 * Fiddle::SIZEOF_VOIDP - 1 # negative
+ offset -= 1 << 8 * Fiddle::SIZEOF_VOIDP
+ end
+ offset
+ end
+
+ def captured_cc_entries(status)
+ status.compiled_iseq.mjit_unit.cc_entries + status.cc_entries_index
+ end
+
+ def call_data_index(cd, body)
+ cd - body.call_data
+ end
+
+ def vm_cc_cme(cc)
+ # TODO: add VM_ASSERT like actual vm_cc_cme
+ cc.cme_
+ end
+
+ def def_iseq_ptr(method_def)
+ C.rb_iseq_check(method_def.body.iseq.iseqptr)
+ end
+
+ def rb_mjit_iseq_compile_info(body)
+ body.mjit_unit.compile_info
+ end
+
+ def ISEQ_IS_SIZE(body)
+ body.ic_size + body.ivc_size + body.ise_size + body.icvarc_size
+ end
+
+ # Return true if an object of the class may be a special const (immediate).
+ # It's "maybe" because Integer and Float are not guaranteed to be an immediate.
+ # If this returns false, rb_class_of could be optimzied to RBASIC_CLASS.
+ def maybe_special_const?(klass)
+ [
+ C.rb_cFalseClass,
+ C.rb_cNilClass,
+ C.rb_cTrueClass,
+ C.rb_cInteger,
+ C.rb_cSymbol,
+ C.rb_cFloat,
+ ].include?(klass)
+ end
+
+ def has_valid_method_type?(cc)
+ vm_cc_cme(cc) != nil
+ end
+
+ def already_compiled?(status, pos)
+ status.stack_size_for_pos[pos] != C.NOT_COMPILED_STACK_SIZE
+ end
+
+ # Return an iseq pointer if cc has inlinable iseq.
+ def rb_mjit_inlinable_iseq(ci, cc)
+ if has_valid_method_type?(cc) &&
+ C.vm_ci_flag(ci) & C.VM_CALL_TAILCALL == 0 && # inlining only non-tailcall path
+ vm_cc_cme(cc).def.type == C.VM_METHOD_TYPE_ISEQ &&
+ C.fastpath_applied_iseq_p(ci, cc, iseq = def_iseq_ptr(vm_cc_cme(cc).def)) &&
+ inlinable_iseq_p(iseq.body) # CC_SET_FASTPATH in vm_callee_setup_arg
+ return iseq
+ end
+ return nil
+ end
+
+ # Return true if the ISeq can be inlined without pushing a new control frame.
+ def inlinable_iseq_p(body)
+ # 1) If catch_except_p, caller frame should be preserved when callee catches an exception.
+ # Then we need to wrap `vm_exec()` but then we can't inline the call inside it.
+ #
+ # 2) If `body->catch_except_p` is false and `handles_sp?` of an insn is false,
+ # sp is not moved as we assume `status->local_stack_p = !body->catch_except_p`.
+ #
+ # 3) If `body->catch_except_p` is false and `always_leaf?` of an insn is true,
+ # pc is not moved.
+ if body.catch_except_p
+ return false
+ end
+
+ pos = 0
+ while pos < body.iseq_size
+ insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
+ # All insns in the ISeq except `leave` (to be overridden in the inlined code)
+ # should meet following strong assumptions:
+ # * Do not require `cfp->sp` motion
+ # * Do not move `cfp->pc`
+ # * Do not read any `cfp->pc`
+ if insn.name == :invokebuiltin || insn.name == :opt_invokebuiltin_delegate || insn.name == :opt_invokebuiltin_delegate_leave
+ # builtin insn's inlinability is handled by `Primitive.attr! 'inline'` per iseq
+ if !body.builtin_inline_p
+ return false;
+ end
+ elsif insn.name != :leave && C.insn_may_depend_on_sp_or_pc(insn.bin, body.iseq_encoded + (pos + 1))
+ return false
+ end
+ # At this moment, `cfp->ep` in an inlined method is not working.
+ case insn.name
+ when :getlocal,
+ :getlocal_WC_0,
+ :getlocal_WC_1,
+ :setlocal,
+ :setlocal_WC_0,
+ :setlocal_WC_1,
+ :getblockparam,
+ :getblockparamproxy,
+ :setblockparam
+ return false
+ end
+ pos += insn.len
+ end
+ return true
+ end
+
+ # CPointer::Struct could be nil on field reference, and this is a helper to
+ # handle that case while using CPointer::Struct#to_s in most cases.
+ # @param struct [RubyVM::MJIT::CPointer::Struct]
+ def to_addr(struct)
+ struct&.to_s || 'NULL'
+ end
+
+ def parent_shape_id(shape_id)
+ return shape_id if shape_id == C.INVALID_SHAPE_ID
+
+ parent_id = C.rb_shape_get_shape_by_id(shape_id).parent_id
+ parent = C.rb_shape_get_shape_by_id(parent_id)
+
+ if parent.type == C.SHAPE_CAPACITY_CHANGE
+ parent.parent_id
+ else
+ parent_id
+ end
+ end
+end
diff --git a/lib/ruby_vm/mjit/hooks.rb b/lib/ruby_vm/mjit/hooks.rb
new file mode 100644
index 0000000000..3fb1004111
--- /dev/null
+++ b/lib/ruby_vm/mjit/hooks.rb
@@ -0,0 +1,32 @@
+module RubyVM::MJIT::Hooks # :nodoc: all
+ C = RubyVM::MJIT.const_get(:C, false)
+
+ def self.on_bop_redefined(_redefined_flag, _bop)
+ C.mjit_cancel_all("BOP is redefined")
+ end
+
+ def self.on_cme_invalidate(_cme)
+ # to be used later
+ end
+
+ def self.on_ractor_spawn
+ C.mjit_cancel_all("Ractor is spawned")
+ end
+
+ def self.on_constant_state_changed(_id)
+ # to be used later
+ end
+
+ def self.on_constant_ic_update(_iseq, _ic, _insn_idx)
+ # to be used later
+ end
+
+ def self.on_tracing_invalidate_all(new_iseq_events)
+ # Stop calling all JIT-ed code. We can't rewrite existing JIT-ed code to trace_ insns for now.
+ # :class events are triggered only in ISEQ_TYPE_CLASS, but mjit_target_iseq_p ignores such iseqs.
+ # Thus we don't need to cancel JIT-ed code for :class events.
+ if new_iseq_events != C.RUBY_EVENT_CLASS
+ C.mjit_cancel_all("TracePoint is enabled")
+ end
+ end
+end
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 60a599e380..af86646a82 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1,22 +1,23 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rbconfig'
+require "rbconfig"
module Gem
- VERSION = "3.3.0.dev".freeze
+ VERSION = "3.4.19"
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
@@ -48,7 +49,7 @@ require 'rubygems/errors'
# 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.
+# which adds a <tt>gem graph</tt> command.
#
# == RubyGems Defaults, Packaging
#
@@ -112,16 +113,12 @@ require 'rubygems/errors'
# -The RubyGems Team
module Gem
- RUBYGEMS_DIR = File.dirname File.expand_path(__FILE__)
+ RUBYGEMS_DIR = __dir__
# Taint support is deprecated in Ruby 2.7.
# This allows switching ".untaint" to ".tap(&Gem::UNTAINT)",
# 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')
+ UNTAINT = RUBY_VERSION < "2.7" ? :untaint.to_sym : proc {}
##
# An Array of Regexps that match windows Ruby platforms.
@@ -163,16 +160,6 @@ module Gem
specifications/default
].freeze
- ##
- # Exception classes used in a Gem.read_binary +rescue+ statement
-
- READ_BINARY_ERRORS = [Errno::EACCES, Errno::EROFS, Errno::ENOSYS, Errno::ENOTSUP].freeze
-
- ##
- # Exception classes used in Gem.write_binary +rescue+ statement
-
- WRITE_BINARY_ERRORS = [Errno::ENOSYS, Errno::ENOTSUP].freeze
-
@@win_platform = nil
@configuration = nil
@@ -195,6 +182,8 @@ module Gem
@default_source_date_epoch = nil
+ @discover_gems_on_require = true
+
##
# Try to activate a gem containing +path+. Returns true if
# activation succeeded or wasn't needed because it was already
@@ -249,9 +238,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?
@@ -275,9 +261,6 @@ module Gem
unless spec = specs.first
msg = "can't find gem #{dep} with executable #{exec_name}"
- if dep.filters_bundler? && bundler_message = Gem::BundlerVersionFinder.missing_version_message
- msg = bundler_message
- end
raise Gem::GemNotFoundException, msg
end
@@ -309,14 +292,14 @@ module Gem
# The mode needed to read a file as straight binary.
def self.binary_mode
- 'rb'
+ "rb"
end
##
# The path where gem executables are to be installed.
def self.bindir(install_dir=Gem.dir)
- return File.join install_dir, 'bin' unless
+ return File.join install_dir, "bin" unless
install_dir.to_s == Gem.default_dir.to_s
Gem.default_bindir
end
@@ -325,7 +308,7 @@ module Gem
# The path were rubygems plugins are to be installed.
def self.plugindir(install_dir=Gem.dir)
- File.join install_dir, 'plugins'
+ File.join install_dir, "plugins"
end
##
@@ -369,7 +352,7 @@ module Gem
# A Zlib::Deflate.deflate wrapper
def self.deflate(data)
- require 'zlib'
+ require "zlib"
Zlib::Deflate.deflate data
end
@@ -391,7 +374,7 @@ module Gem
target = {}
env.each_pair do |k,v|
case k
- when 'GEM_HOME', 'GEM_PATH', 'GEM_SPEC_CACHE'
+ when "GEM_HOME", "GEM_PATH", "GEM_SPEC_CACHE"
case v
when nil, String
target[k] = v
@@ -458,8 +441,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
old_umask = File.umask
File.umask old_umask | 002
- require 'fileutils'
-
options = {}
options[:mode] = mode if mode
@@ -467,6 +448,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
subdirs.each do |name|
subdir = File.join dir, name
next if File.exist? subdir
+
+ require "fileutils"
+
begin
FileUtils.mkdir_p subdir, **options
rescue SystemCallError
@@ -481,7 +465,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# distinction as extensions cannot be shared between the two.
def self.extension_api_version # :nodoc:
- if 'no' == RbConfig::CONFIG['ENABLE_SHARED']
+ if "no" == RbConfig::CONFIG["ENABLE_SHARED"]
"#{ruby_api_version}-static"
else
ruby_api_version
@@ -562,7 +546,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# => [#<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
@@ -591,14 +575,14 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
return i if path.instance_variable_defined?(:@gem_prelude_index)
end
- index = $LOAD_PATH.index RbConfig::CONFIG['sitelibdir']
+ index = $LOAD_PATH.index RbConfig::CONFIG["sitelibdir"]
index || 0
end
##
- # The number of paths in the `$LOAD_PATH` from activated gems. Used to
- # prioritize `-I` and `ENV['RUBYLIB`]` entries during `require`.
+ # The number of paths in the +$LOAD_PATH+ from activated gems. Used to
+ # prioritize +-I+ and +ENV['RUBYLIB']+ entries during +require+.
def self.activated_gem_paths
@activated_gem_paths ||= 0
@@ -622,18 +606,10 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.load_yaml
return if @yaml_loaded
- begin
- # Try requiring the gem version *or* stdlib version of psych.
- require 'psych'
- rescue ::LoadError
- # If we can't load psych, that's fine, go on.
- else
- require 'rubygems/psych_additions'
- require 'rubygems/psych_tree'
- end
+ require "psych"
+ require_relative "rubygems/psych_tree"
- require 'yaml'
- require 'rubygems/safe_yaml'
+ require_relative "rubygems/safe_yaml"
@yaml_loaded = true
end
@@ -764,9 +740,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.prefix
prefix = File.dirname RUBYGEMS_DIR
- if prefix != File.expand_path(RbConfig::CONFIG['sitelibdir']) and
- prefix != File.expand_path(RbConfig::CONFIG['libdir']) and
- 'lib' == File.basename(RUBYGEMS_DIR)
+ if prefix != File.expand_path(RbConfig::CONFIG["sitelibdir"]) &&
+ prefix != File.expand_path(RbConfig::CONFIG["libdir"]) &&
+ "lib" == File.basename(RUBYGEMS_DIR)
prefix
end
end
@@ -782,40 +758,46 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Safely read a file in binary mode on all platforms.
def self.read_binary(path)
- File.open path, 'rb+' do |f|
- f.flock(File::LOCK_EX)
- f.read
+ open_file(path, "rb+") do |io|
+ io.read
end
- rescue *READ_BINARY_ERRORS
- File.open path, 'rb' do |f|
- f.read
- end
- rescue Errno::ENOLCK # NFS
- if Thread.main != Thread.current
- raise
- else
- File.open path, 'rb' do |f|
- f.read
- end
+ rescue Errno::EACCES, Errno::EROFS
+ open_file(path, "rb") do |io|
+ io.read
end
end
##
# Safely write a file in binary mode on all platforms.
def self.write_binary(path, data)
- File.open(path, 'wb') do |io|
- begin
- io.flock(File::LOCK_EX)
- rescue *WRITE_BINARY_ERRORS
- end
+ open_file(path, "wb") do |io|
io.write data
end
+ rescue Errno::ENOSPC
+ # If we ran out of space but the file exists, it's *guaranteed* to be corrupted.
+ File.delete(path) if File.exist?(path)
+ raise
+ end
+
+ ##
+ # Open a file with given flags, and on Windows protect access with flock
+
+ def self.open_file(path, flags, &block)
+ File.open(path, flags) do |io|
+ if !java_platform? && win_platform?
+ begin
+ io.flock(File::LOCK_EX)
+ rescue Errno::ENOSYS, Errno::ENOTSUP
+ end
+ end
+ yield io
+ end
rescue Errno::ENOLCK # NFS
if Thread.main != Thread.current
raise
else
- File.open(path, 'wb') do |io|
- io.write data
+ File.open(path, flags) do |io|
+ yield io
end
end
end
@@ -837,13 +819,13 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Returns a String containing the API compatibility version of Ruby
def self.ruby_api_version
- @ruby_api_version ||= RbConfig::CONFIG['ruby_version'].dup
+ @ruby_api_version ||= RbConfig::CONFIG["ruby_version"].dup
end
def self.env_requirement(gem_name)
@env_requirements_by_name ||= {}
@env_requirements_by_name[gem_name] ||= begin
- req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || '>= 0'.freeze
+ req = ENV["GEM_REQUIREMENT_#{gem_name.upcase}"] || ">= 0"
Gem::Requirement.create(req)
end
end
@@ -857,7 +839,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
fetcher = Gem::SpecFetcher.fetcher
spec_tuples, = fetcher.spec_for_dependency dependency
- spec, = spec_tuples.first
+ spec, = spec_tuples.last
spec
end
@@ -866,16 +848,15 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Returns the latest release version of RubyGems.
def self.latest_rubygems_version
- latest_version_for('rubygems-update') or
- raise "Can't find 'rubygems-update' in any repo. Check `gem source list`."
+ latest_version_for("rubygems-update") ||
+ raise("Can't find 'rubygems-update' in any repo. Check `gem source list`.")
end
##
# Returns the version of the latest release-version of gem +name+
def self.latest_version_for(name)
- spec = latest_spec_for name
- spec and spec.version
+ latest_spec_for(name)&.version
end
##
@@ -885,9 +866,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
return @ruby_version if defined? @ruby_version
version = RUBY_VERSION.dup
- if defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1
- version << ".#{RUBY_PATCHLEVEL}"
- elsif defined?(RUBY_DESCRIPTION)
+ unless defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1
if RUBY_ENGINE == "ruby"
desc = RUBY_DESCRIPTION[/\Aruby #{Regexp.quote(RUBY_VERSION)}([^ ]+) /, 1]
else
@@ -963,11 +942,11 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Suffixes for require-able paths.
def self.suffixes
- @suffixes ||= ['',
- '.rb',
+ @suffixes ||= ["",
+ ".rb",
*%w[DLEXT DLEXT2].map do |key|
val = RbConfig::CONFIG[key]
- next unless val and not val.empty?
+ next unless val && !val.empty?
".#{val}"
end,
].compact.uniq
@@ -993,7 +972,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
@@ -1015,7 +994,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.win_platform?
if @@win_platform.nil?
- ruby_platform = RbConfig::CONFIG['host_os']
+ ruby_platform = RbConfig::CONFIG["host_os"]
@@win_platform = !!WIN_PATTERNS.find {|r| ruby_platform =~ r }
end
@@ -1030,11 +1009,17 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
##
+ # Is this platform Solaris?
+
+ def self.solaris_platform?
+ RUBY_PLATFORM.include?("solaris")
+ end
+
+ ##
# Load +plugins+ as Ruby files
def self.load_plugin_files(plugins) # :nodoc:
plugins.each do |plugin|
-
# Skip older versions of the GemCutter plugin: Its commands are in
# RubyGems proper now.
@@ -1053,7 +1038,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Find rubygems plugin files in the standard location and load them
def self.load_plugins
- load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir)
+ Gem.path.each do |gem_path|
+ load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir(gem_path))
+ end
end
##
@@ -1086,7 +1073,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.use_gemdeps(path = nil)
raise_exception = path
- path ||= ENV['RUBYGEMS_GEMDEPS']
+ path ||= ENV["RUBYGEMS_GEMDEPS"]
return unless path
path = path.dup
@@ -1111,33 +1098,28 @@ 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
##
# If the SOURCE_DATE_EPOCH environment variable is set, returns it's value.
- # Otherwise, returns the time that `Gem.source_date_epoch_string` was
+ # Otherwise, returns the time that +Gem.source_date_epoch_string+ was
# first called in the same format as SOURCE_DATE_EPOCH.
#
# NOTE(@duckinator): The implementation is a tad weird because we want to:
@@ -1183,9 +1165,17 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# 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
##
+ # Whether RubyGems should enhance builtin `require` to automatically
+ # check whether the path required is present in installed gems, and
+ # automatically activate them and add them to `$LOAD_PATH`.
+
+ attr_accessor :discover_gems_on_require
+
+ ##
# Hash of loaded Gem::Specification keyed by name
attr_reader :loaded_specs
@@ -1299,44 +1289,57 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
def default_gem_load_paths
- @default_gem_load_paths ||= $LOAD_PATH[load_path_insert_index..-1]
+ @default_gem_load_paths ||= $LOAD_PATH[load_path_insert_index..-1].map do |lp|
+ expanded = File.expand_path(lp)
+ next expanded unless File.exist?(expanded)
+
+ File.realpath(expanded)
+ end
end
end
##
# Location of Marshal quick gemspecs on remote repositories
- MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze
-
- autoload :BundlerVersionFinder, File.expand_path('rubygems/bundler_version_finder', __dir__)
- autoload :ConfigFile, File.expand_path('rubygems/config_file', __dir__)
- autoload :Dependency, File.expand_path('rubygems/dependency', __dir__)
- autoload :DependencyList, File.expand_path('rubygems/dependency_list', __dir__)
- autoload :Installer, File.expand_path('rubygems/installer', __dir__)
- autoload :Licenses, File.expand_path('rubygems/util/licenses', __dir__)
- autoload :NameTuple, File.expand_path('rubygems/name_tuple', __dir__)
- autoload :PathSupport, File.expand_path('rubygems/path_support', __dir__)
- autoload :Platform, File.expand_path('rubygems/platform', __dir__)
- autoload :RequestSet, File.expand_path('rubygems/request_set', __dir__)
- autoload :Requirement, File.expand_path('rubygems/requirement', __dir__)
- autoload :Resolver, File.expand_path('rubygems/resolver', __dir__)
- autoload :Source, File.expand_path('rubygems/source', __dir__)
- autoload :SourceList, File.expand_path('rubygems/source_list', __dir__)
- autoload :SpecFetcher, File.expand_path('rubygems/spec_fetcher', __dir__)
- autoload :Specification, File.expand_path('rubygems/specification', __dir__)
- autoload :Util, File.expand_path('rubygems/util', __dir__)
- autoload :Version, File.expand_path('rubygems/version', __dir__)
+ MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
+
+ autoload :ConfigFile, File.expand_path("rubygems/config_file", __dir__)
+ autoload :Dependency, File.expand_path("rubygems/dependency", __dir__)
+ autoload :DependencyList, File.expand_path("rubygems/dependency_list", __dir__)
+ autoload :Installer, File.expand_path("rubygems/installer", __dir__)
+ autoload :Licenses, File.expand_path("rubygems/util/licenses", __dir__)
+ autoload :NameTuple, File.expand_path("rubygems/name_tuple", __dir__)
+ autoload :PathSupport, File.expand_path("rubygems/path_support", __dir__)
+ autoload :RequestSet, File.expand_path("rubygems/request_set", __dir__)
+ autoload :Requirement, File.expand_path("rubygems/requirement", __dir__)
+ autoload :Resolver, File.expand_path("rubygems/resolver", __dir__)
+ autoload :Source, File.expand_path("rubygems/source", __dir__)
+ autoload :SourceList, File.expand_path("rubygems/source_list", __dir__)
+ autoload :SpecFetcher, File.expand_path("rubygems/spec_fetcher", __dir__)
+ autoload :SpecificationPolicy, File.expand_path("rubygems/specification_policy", __dir__)
+ autoload :Util, File.expand_path("rubygems/util", __dir__)
+ autoload :Version, File.expand_path("rubygems/version", __dir__)
end
-require 'rubygems/exceptions'
+require_relative "rubygems/exceptions"
+require_relative "rubygems/specification"
# REFACTOR: This should be pulled out into some kind of hacks file.
begin
##
# Defaults the operating system (or packager) wants to provide for RubyGems.
- require 'rubygems/defaults/operating_system'
+ require "rubygems/defaults/operating_system"
rescue LoadError
+ # Ignored
+rescue StandardError => e
+ path = e.backtrace_locations.reverse.find {|l| l.path.end_with?("rubygems/defaults/operating_system.rb") }.path
+ msg = "#{e.message}\n" \
+ "Loading the #{path} file caused an error. " \
+ "This file is owned by your OS, not by rubygems upstream. " \
+ "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \
+ "the problem and ask for help."
+ raise e.class, msg
end
begin
@@ -1351,8 +1354,17 @@ 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"
+
+path = File.join(__dir__, "rubygems/core_ext/kernel_require.rb")
+# When https://bugs.ruby-lang.org/issues/17259 is available, there is no need to override Kernel#warn
+if RUBY_ENGINE == "truffleruby" ||
+ (RUBY_ENGINE == "ruby" && RUBY_VERSION >= "3.0")
+ file = "<internal:#{path}>"
+else
+ require_relative "rubygems/core_ext/kernel_warn"
+ file = path
+end
+eval File.read(path), nil, file
-Gem.use_gemdeps
+require ENV["BUNDLER_SETUP"] if ENV["BUNDLER_SETUP"] && !defined?(Bundler)
diff --git a/lib/rubygems/available_set.rb b/lib/rubygems/available_set.rb
index 499483d9e9..2ab3e137da 100644
--- a/lib/rubygems/available_set.rb
+++ b/lib/rubygems/available_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
class Gem::AvailableSet
include Enumerable
@@ -26,7 +27,7 @@ class Gem::AvailableSet
s = o.set
when Array
s = o.map do |sp,so|
- if !sp.kind_of?(Gem::Specification) or !so.kind_of?(Gem::Source)
+ if !sp.kind_of?(Gem::Specification) || !so.kind_of?(Gem::Source)
raise TypeError, "Array must be in [[spec, source], ...] form"
end
@@ -149,8 +150,8 @@ class Gem::AvailableSet
@set.reject! do |t|
# already locally installed
Gem::Specification.any? do |installed_spec|
- dep.name == installed_spec.name and
- dep.requirement.satisfied_by? installed_spec.version
+ dep.name == installed_spec.name &&
+ dep.requirement.satisfied_by?(installed_spec.version)
end
end
diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb
index 665b87fc0e..5d198114e0 100644
--- a/lib/rubygems/basic_specification.rb
+++ b/lib/rubygems/basic_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# BasicSpecification is an abstract class which implements some common code
# used by both Specification and StubSpecification.
@@ -47,7 +48,7 @@ class Gem::BasicSpecification
# directory.
def gem_build_complete_path # :nodoc:
- File.join extension_dir, 'gem.build_complete'
+ File.join extension_dir, "gem.build_complete"
end
##
@@ -77,7 +78,7 @@ class Gem::BasicSpecification
if Gem::Platform::RUBY == platform || Gem::Platform.local === platform
warn "Ignoring #{full_name} because its extensions are not built. " +
- "Try: gem pristine #{name} --version #{version}"
+ "Try: gem pristine #{name} --version #{version}"
end
return false
@@ -103,7 +104,7 @@ class Gem::BasicSpecification
def extensions_dir
Gem.default_ext_dir_for(base_dir) ||
- File.join(base_dir, 'extensions', Gem::Platform.local.to_s,
+ File.join(base_dir, "extensions", Gem::Platform.local.to_s,
Gem.extension_api_version)
end
@@ -131,7 +132,7 @@ class Gem::BasicSpecification
# default Ruby platform.
def full_name
- if platform == Gem::Platform::RUBY or platform.nil?
+ if platform == Gem::Platform::RUBY || platform.nil?
"#{name}-#{version}".dup.tap(&Gem::UNTAINT)
else
"#{name}-#{version}-#{platform}".dup.tap(&Gem::UNTAINT)
@@ -289,14 +290,14 @@ class Gem::BasicSpecification
def lib_dirs_glob
dirs = if self.raw_require_paths
- if self.raw_require_paths.size > 1
- "{#{self.raw_require_paths.join(',')}}"
- else
- self.raw_require_paths.first
- end
- else
- "lib" # default value for require_paths for bundler/inline
- end
+ if self.raw_require_paths.size > 1
+ "{#{self.raw_require_paths.join(',')}}"
+ else
+ self.raw_require_paths.first
+ end
+ else
+ "lib" # default value for require_paths for bundler/inline
+ end
"#{self.full_gem_path}/#{dirs}".dup.tap(&Gem::UNTAINT)
end
diff --git a/lib/rubygems/bundler_version_finder.rb b/lib/rubygems/bundler_version_finder.rb
index 9ce0a2378e..5b34227d3a 100644
--- a/lib/rubygems/bundler_version_finder.rb
+++ b/lib/rubygems/bundler_version_finder.rb
@@ -2,48 +2,18 @@
module Gem::BundlerVersionFinder
def self.bundler_version
- version, _ = bundler_version_with_reason
+ v = ENV["BUNDLER_VERSION"]
- return unless version
+ v ||= bundle_update_bundler_version
+ return if v == true
- Gem::Version.new(version)
- end
-
- def self.bundler_version_with_reason
- if v = ENV["BUNDLER_VERSION"]
- return [v, "`$BUNDLER_VERSION`"]
- end
- if v = bundle_update_bundler_version
- return if v == true
- return [v, "`bundle update --bundler`"]
- end
- v, lockfile = lockfile_version
- if v
- return [v, "your #{lockfile}"]
- end
- end
+ v ||= lockfile_version
+ return unless v
- def self.missing_version_message
- return unless vr = bundler_version_with_reason
- <<-EOS
-Could not find 'bundler' (#{vr.first}) required by #{vr.last}.
-To update to the latest version installed on your system, run `bundle update --bundler`.
-To install the missing version, run `gem install bundler:#{vr.first}`
- EOS
+ Gem::Version.new(v)
end
- def self.compatible?(spec)
- return true unless spec.name == "bundler".freeze
- return true unless bundler_version = self.bundler_version
-
- spec.version.segments.first == bundler_version.segments.first
- end
-
- def self.filter!(specs)
- return unless bundler_version = self.bundler_version
-
- specs.reject! {|spec| spec.version.segments.first != bundler_version.segments.first }
-
+ def self.prioritize!(specs)
exact_match_index = specs.find_index {|spec| spec.version == bundler_version }
return unless exact_match_index
@@ -51,7 +21,7 @@ To install the missing version, run `gem install bundler:#{vr.first}`
end
def self.bundle_update_bundler_version
- return unless File.basename($0) == "bundle".freeze
+ return unless File.basename($0) == "bundle"
return unless "update".start_with?(ARGV.first || " ")
bundler_version = nil
update_index = nil
@@ -68,18 +38,16 @@ To install the missing version, run `gem install bundler:#{vr.first}`
private_class_method :bundle_update_bundler_version
def self.lockfile_version
- return unless lockfile = lockfile_contents
- lockfile, contents = lockfile
- lockfile ||= "lockfile"
+ return unless contents = lockfile_contents
regexp = /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
return unless contents =~ regexp
- [$1, lockfile]
+ $1
end
private_class_method :lockfile_version
def self.lockfile_contents
gemfile = ENV["BUNDLE_GEMFILE"]
- gemfile = nil if gemfile && gemfile.empty?
+ gemfile = nil if gemfile&.empty?
unless gemfile
begin
@@ -97,13 +65,13 @@ To install the missing version, run `gem install bundler:#{vr.first}`
return unless gemfile
lockfile = case gemfile
- when "gems.rb" then "gems.locked"
- else "#{gemfile}.lock"
- end.dup.tap(&Gem::UNTAINT)
+ when "gems.rb" then "gems.locked"
+ else "#{gemfile}.lock"
+ end.dup.tap(&Gem::UNTAINT)
return unless File.file?(lockfile)
- [lockfile, File.read(lockfile)]
+ File.read(lockfile)
end
private_class_method :lockfile_contents
end
diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb
index 303f54a7d7..07cf4e0e81 100644
--- a/lib/rubygems/command.rb
+++ b/lib/rubygems/command.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'optparse'
-require_relative 'requirement'
-require_relative '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
@@ -19,7 +20,7 @@ require_relative 'user_interaction'
class Gem::Command
include Gem::UserInteraction
- OptionParser.accept Symbol do |value|
+ Gem::OptionParser.accept Symbol do |value|
value.to_sym
end
@@ -76,7 +77,7 @@ class Gem::Command
when Array
@extra_args = value
when String
- @extra_args = value.split(' ')
+ @extra_args = value.split(" ")
end
end
@@ -159,11 +160,11 @@ class Gem::Command
gem = "'#{gem_name}' (#{version})"
msg = String.new "Could not find a valid gem #{gem}"
- if errors and !errors.empty?
+ if errors && !errors.empty?
msg << ", here is why:\n"
errors.each {|x| msg << " #{x.wordy}\n" }
else
- if required_by and gem != required_by
+ if required_by && gem != required_by
msg << " (required by #{required_by}) in any repository"
else
msg << " in any repository"
@@ -186,7 +187,7 @@ class Gem::Command
def get_all_gem_names
args = options[:args]
- if args.nil? or args.empty?
+ if args.nil? || args.empty?
raise Gem::CommandLineError,
"Please specify at least one gem name (e.g. gem build GEMNAME)"
end
@@ -201,11 +202,15 @@ class Gem::Command
# respectively.
def get_all_gem_names_and_versions
get_all_gem_names.map do |name|
- if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name
- [$1, $2]
- else
- [name]
- end
+ extract_gem_name_and_version(name)
+ end
+ end
+
+ def extract_gem_name_and_version(name) # :nodoc:
+ if /\A(.*):(#{Gem::Requirement::PATTERN_RAW})\z/ =~ name
+ [$1, $2]
+ else
+ [name]
end
end
@@ -216,7 +221,7 @@ class Gem::Command
def get_one_gem_name
args = options[:args]
- if args.nil? or args.empty?
+ if args.nil? || args.empty?
raise Gem::CommandLineError,
"Please specify a gem name on the command line (e.g. gem build GEMNAME)"
end
@@ -344,7 +349,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.
@@ -398,10 +403,10 @@ class Gem::Command
version_to_expire = deprecation["rg_version_to_expire"]
deprecate_option_msg = if version_to_expire
- "The \"#{option}\" option has been deprecated and will be removed in Rubygems #{version_to_expire}."
- else
- "The \"#{option}\" option has been deprecated and will be removed in future versions of Rubygems."
- end
+ "The \"#{option}\" option has been deprecated and will be removed in Rubygems #{version_to_expire}."
+ else
+ "The \"#{option}\" option has been deprecated and will be removed in future versions of Rubygems."
+ end
extra_msg = deprecation["extra_msg"]
@@ -540,7 +545,7 @@ class Gem::Command
# command.
def create_option_parser
- @parser = OptionParser.new
+ @parser = Gem::OptionParser.new
add_parser_options
@@ -554,9 +559,9 @@ class Gem::Command
end
def configure_options(header, option_list)
- return if option_list.nil? or option_list.empty?
+ return if option_list.nil? || option_list.empty?
- header = header.to_s.empty? ? '' : "#{header} "
+ header = header.to_s.empty? ? "" : "#{header} "
@parser.separator " #{header}Options:"
option_list.each do |args, handler|
@@ -565,7 +570,7 @@ class Gem::Command
end
end
- @parser.separator ''
+ @parser.separator ""
end
##
@@ -578,22 +583,22 @@ class Gem::Command
# ----------------------------------------------------------------
# Add the options common to all commands.
- add_common_option('-h', '--help',
- 'Get help on this command') do |value, options|
+ add_common_option("-h", "--help",
+ "Get help on this command") do |value, options|
options[:help] = true
end
- add_common_option('-V', '--[no-]verbose',
- 'Set the verbose level of output') do |value, options|
+ add_common_option("-V", "--[no-]verbose",
+ "Set the verbose level of output") do |value, options|
# Set us to "really verbose" so the progress meter works
- if Gem.configuration.verbose and value
+ if Gem.configuration.verbose && value
Gem.configuration.verbose = 1
else
Gem.configuration.verbose = value
end
end
- add_common_option('-q', '--quiet', 'Silence command progress meter') do |value, options|
+ add_common_option("-q", "--quiet", "Silence command progress meter") do |value, options|
Gem.configuration.verbose = false
end
@@ -606,31 +611,35 @@ class Gem::Command
# commands. Both options are actually handled before the other
# options get parsed.
- add_common_option('--config-file FILE',
- 'Use this config file instead of default') do
+ add_common_option("--config-file FILE",
+ "Use this config file instead of default") do
end
- add_common_option('--backtrace',
- 'Show stack backtrace on errors') do
+ add_common_option("--backtrace",
+ "Show stack backtrace on errors") do
end
- add_common_option('--debug',
- 'Turn on Ruby debugging') do
+ add_common_option("--debug",
+ "Turn on Ruby debugging") do
end
- add_common_option('--norc',
- 'Avoid loading any .gemrc file') do
+ add_common_option("--norc",
+ "Avoid loading any .gemrc file") do
end
# :stopdoc:
- HELP = <<-HELP.freeze
+ HELP = <<-HELP
RubyGems is a package manager for Ruby.
Usage:
gem -h/--help
gem -v/--version
- gem command [arguments...] [options...]
+ gem [global options...] command [arguments...] [options...]
+
+ Global options:
+ -C PATH run as if gem was started in <PATH>
+ instead of the current working directory
Examples:
gem install rake
diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb
index 2409550882..b3913d465a 100644
--- a/lib/rubygems/command_manager.rb
+++ b/lib/rubygems/command_manager.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/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
@@ -43,6 +44,7 @@ class Gem::CommandManager
:contents,
:dependency,
:environment,
+ :exec,
:fetch,
:generate_index,
:help,
@@ -73,14 +75,16 @@ class Gem::CommandManager
].freeze
ALIAS_COMMANDS = {
- 'i' => 'install',
+ "i" => "install",
+ "login" => "signin",
+ "logout" => "signout",
}.freeze
##
# Return the authoritative instance of the command manager.
def self.instance
- @command_manager ||= new
+ @instance ||= new
end
##
@@ -95,14 +99,14 @@ class Gem::CommandManager
# Reset the authoritative instance of the command manager.
def self.reset
- @command_manager = nil
+ @instance = nil
end
##
# Register all the subcommands supported by the gem command.
def initialize
- require 'timeout'
+ require "timeout"
@commands = {}
BUILTIN_COMMANDS.each do |name|
@@ -146,7 +150,12 @@ class Gem::CommandManager
def run(args, build_args=nil)
process_args(args, build_args)
rescue StandardError, Timeout::Error => ex
- alert_error clean_text("While executing gem ... (#{ex.class})\n #{ex}")
+ if ex.respond_to?(:detailed_message)
+ msg = ex.detailed_message(highlight: false).sub(/\A(.*?)(?: \(.+?\))/) { $1 }
+ else
+ msg = ex.message
+ end
+ alert_error clean_text("While executing gem ... (#{ex.class})\n #{msg}")
ui.backtrace ex
terminate_interaction(1)
@@ -162,20 +171,26 @@ class Gem::CommandManager
end
case args.first
- when '-h', '--help' then
+ when "-h", "--help" then
say Gem::Command::HELP
terminate_interaction 0
- when '-v', '--version' then
+ when "-v", "--version" then
say Gem::VERSION
terminate_interaction 0
+ when "-C" then
+ args.shift
+ start_point = args.shift
+ if Dir.exist?(start_point)
+ Dir.chdir(start_point) { invoke_command(args, build_args) }
+ else
+ alert_error clean_text("#{start_point} isn't a directory.")
+ terminate_interaction 1
+ end
when /^-/ then
alert_error clean_text("Invalid option: #{args.first}. See 'gem --help'.")
terminate_interaction 1
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
+ invoke_command(args, build_args)
end
end
@@ -230,4 +245,11 @@ class Gem::CommandManager
ui.backtrace e
end
end
+
+ def invoke_command(args, build_args)
+ 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
diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb
index 842ec1855a..68e020d94a 100644
--- a/lib/rubygems/commands/build_command.rb
+++ b/lib/rubygems/commands/build_command.rb
@@ -1,31 +1,35 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/package'
-require 'rubygems/version_option'
+
+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'
+ super "build", "Build a gem from a gemspec"
add_platform_option
- add_option '--force', 'skip validation of the spec' do |value, options|
+ add_option "--force", "skip validation of the spec" do |value, options|
options[:force] = true
end
- add_option '--strict', 'consider warnings as errors when validating the spec' do |value, options|
+ add_option "--strict", "consider warnings as errors when validating the spec" do |value, options|
options[:strict] = true
end
- add_option '-o', '--output FILE', 'output gem with the given filename' do |value, options|
+ add_option "-o", "--output FILE", "output gem with the given filename" do |value, options|
options[:output] = value
end
- add_option '-C PATH', 'Run as if gem build was started in <PATH> instead of the current working directory.' do |value, options|
+ add_option "-C PATH", "Run as if gem build was started in <PATH> instead of the current working directory." do |value, options|
options[:build_path] = value
end
+ deprecate_option "-C",
+ version: "4.0",
+ extra_msg: "-C is a global flag now. Use `gem -C PATH build GEMSPEC_FILE [options]` instead"
end
def arguments # :nodoc:
diff --git a/lib/rubygems/commands/cert_command.rb b/lib/rubygems/commands/cert_command.rb
index 3fc0daea7d..344f31fba9 100644
--- a/lib/rubygems/commands/cert_command.rb
+++ b/lib/rubygems/commands/cert_command.rb
@@ -1,64 +1,70 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/security'
+
+require_relative "../command"
+require_relative "../security"
class Gem::Commands::CertCommand < Gem::Command
def initialize
- super 'cert', 'Manage RubyGems certificates and signing settings',
+ super "cert", "Manage RubyGems certificates and signing settings",
:add => [], :remove => [], :list => [], :build => [], :sign => []
- add_option('-a', '--add CERT',
- 'Add a trusted certificate.') do |cert_file, options|
+ 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]',
- 'List trusted certificates where the',
- 'subject contains FILTER') do |filter, options|
- filter ||= ''
+ add_option("-l", "--list [FILTER]",
+ "List trusted certificates where the",
+ "subject contains FILTER") do |filter, options|
+ filter ||= ""
options[:list] << filter
end
- add_option('-r', '--remove FILTER',
- 'Remove trusted certificates where the',
- 'subject contains FILTER') do |filter, options|
+ add_option("-r", "--remove FILTER",
+ "Remove trusted certificates where the",
+ "subject contains FILTER") do |filter, options|
options[:remove] << filter
end
- add_option('-b', '--build EMAIL_ADDR',
- 'Build private key and self-signed',
- 'certificate for EMAIL_ADDR') do |email_address, options|
+ add_option("-b", "--build EMAIL_ADDR",
+ "Build private key and self-signed",
+ "certificate for EMAIL_ADDR") do |email_address, options|
options[:build] << email_address
end
- add_option('-C', '--certificate CERT',
- 'Signing certificate for --sign') do |cert_file, options|
+ 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',
- 'Key for --sign or --build') do |key_file, options|
+ 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('-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
+ 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 Gem::OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless
File.file? cert_file
options[:sign] << cert_file
end
- add_option('-d', '--days NUMBER_OF_DAYS',
- 'Days before the certificate expires') do |days, options|
+ add_option("-d", "--days NUMBER_OF_DAYS",
+ "Days before the certificate expires") do |days, options|
options[:expiration_length_days] = days.to_i
end
- add_option('-R', '--re-sign',
- 'Re-signs the certificate from -C with the key from -K') do |resign, options|
+ add_option("-R", "--re-sign",
+ "Re-signs the certificate from -C with the key from -K") do |resign, options|
options[:resign] = resign
end
end
@@ -80,23 +86,23 @@ class Gem::Commands::CertCommand < Gem::Command
check_openssl
OpenSSL::X509::Certificate.new File.read certificate_file
rescue Errno::ENOENT
- raise OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
+ raise Gem::OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
rescue OpenSSL::X509::CertificateError
- raise OptionParser::InvalidArgument,
+ 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::RSA.new File.read(key_file), passphrase
- raise OptionParser::InvalidArgument,
+ 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 OptionParser::InvalidArgument, "#{key_file}: does not exist"
- rescue OpenSSL::PKey::RSAError
- raise OptionParser::InvalidArgument, "#{key_file}: invalid RSA key"
+ 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
@@ -147,7 +153,7 @@ class Gem::Commands::CertCommand < Gem::Command
def build_cert(email, key) # :nodoc:
expiration_length_days = options[:expiration_length_days] ||
- Gem.configuration.cert_expiration_length_days
+ Gem.configuration.cert_expiration_length_days
cert = Gem::Security.create_cert_email(
email,
@@ -161,16 +167,17 @@ class Gem::Commands::CertCommand < Gem::Command
def build_key # :nodoc:
return options[:key] if options[:key]
- passphrase = ask_for_password 'Passphrase for your Private Key:'
+ passphrase = ask_for_password "Passphrase for your Private Key:"
say "\n"
- passphrase_confirmation = ask_for_password 'Please repeat the passphrase for your Private Key:'
+ passphrase_confirmation = ask_for_password "Please repeat the passphrase for your Private Key:"
say "\n"
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
@@ -254,14 +261,15 @@ For further reading on signing gems see `ri Gem::Security`.
def load_default_key
key_file = File.join Gem.default_key_path
key = File.read key_file
- passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
- options[:key] = OpenSSL::PKey::RSA.new key, passphrase
+ passphrase = ENV["GEM_PRIVATE_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"
diff --git a/lib/rubygems/commands/check_command.rb b/lib/rubygems/commands/check_command.rb
index 8b8eda53cf..b300b4f87a 100644
--- a/lib/rubygems/commands/check_command.rb
+++ b/lib/rubygems/commands/check_command.rb
@@ -1,44 +1,45 @@
# 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
- super 'check', 'Check a gem repository for added or missing files',
+ super "check", "Check a gem repository for added or missing files",
:alien => true, :doctor => false, :dry_run => false, :gems => true
- add_option('-a', '--[no-]alien',
+ add_option("-a", "--[no-]alien",
'Report "unmanaged" or rogue files in the',
- 'gem repository') do |value, options|
+ "gem repository") do |value, options|
options[:alien] = value
end
- add_option('--[no-]doctor',
- 'Clean up uninstalled gems and broken',
- 'specifications') do |value, options|
+ add_option("--[no-]doctor",
+ "Clean up uninstalled gems and broken",
+ "specifications") do |value, options|
options[:doctor] = value
end
- add_option('--[no-]dry-run',
- 'Do not remove files, only report what',
- 'would be removed') do |value, options|
+ add_option("--[no-]dry-run",
+ "Do not remove files, only report what",
+ "would be removed") do |value, options|
options[:dry_run] = value
end
- add_option('--[no-]gems',
- 'Check installed gems for problems') do |value, options|
+ add_option("--[no-]gems",
+ "Check installed gems for problems") do |value, options|
options[:gems] = value
end
- add_version_option 'check'
+ add_version_option "check"
end
def check_gems
- say 'Checking gems...'
+ say "Checking gems..."
say
gems = get_all_gem_names rescue []
@@ -57,7 +58,7 @@ class Gem::Commands::CheckCommand < Gem::Command
end
def doctor
- say 'Checking for files from uninstalled gems...'
+ say "Checking for files from uninstalled gems..."
say
Gem.path.each do |gem_repo|
@@ -72,11 +73,11 @@ class Gem::Commands::CheckCommand < Gem::Command
end
def arguments # :nodoc:
- 'GEMNAME name of gem to check'
+ "GEMNAME name of gem to check"
end
def defaults_str # :nodoc:
- '--gems --alien'
+ "--gems --alien"
end
def description # :nodoc:
diff --git a/lib/rubygems/commands/cleanup_command.rb b/lib/rubygems/commands/cleanup_command.rb
index 662badce33..ee5e1252b6 100644
--- a/lib/rubygems/commands/cleanup_command.rb
+++ b/lib/rubygems/commands/cleanup_command.rb
@@ -1,35 +1,36 @@
# 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',
+ super "cleanup",
+ "Clean up old versions of installed gems",
:force => false, :install_dir => Gem.dir,
:check_dev => true
- add_option('-n', '-d', '--dry-run',
- 'Do not uninstall gems') do |value, options|
+ 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|
+ add_option(:Deprecated, "--dryrun",
+ "Do not uninstall gems") do |value, options|
options[:dryrun] = true
end
- deprecate_option('--dryrun', extra_msg: 'Use --dry-run instead')
+ deprecate_option("--dryrun", extra_msg: "Use --dry-run instead")
- add_option('-D', '--[no-]check-development',
- 'Check development dependencies while uninstalling',
- '(default: true)') do |value, options|
+ add_option("-D", "--[no-]check-development",
+ "Check development dependencies while uninstalling",
+ "(default: true)") do |value, options|
options[:check_dev] = value
end
- add_option('--[no-]user-install',
- 'Cleanup in user\'s home directory instead',
- 'of GEM_HOME.') do |value, options|
+ add_option("--[no-]user-install",
+ "Cleanup in user's home directory instead",
+ "of GEM_HOME.") do |value, options|
options[:user_install] = value
end
@@ -117,12 +118,12 @@ If no gems are named all gems in GEM_HOME are cleaned.
def get_candidate_gems
@candidate_gems = unless options[:args].empty?
- options[:args].map do |gem_name|
- Gem::Specification.find_all_by_name gem_name
- end.flatten
- else
- Gem::Specification.to_a
- end
+ options[:args].map do |gem_name|
+ Gem::Specification.find_all_by_name gem_name
+ end.flatten
+ else
+ Gem::Specification.to_a
+ end
end
def get_gems_to_cleanup
@@ -149,7 +150,7 @@ If no gems are named all gems in GEM_HOME are cleaned.
@primary_gems = {}
Gem::Specification.each do |spec|
- if @primary_gems[spec.name].nil? or
+ if @primary_gems[spec.name].nil? ||
@primary_gems[spec.name].version < spec.version
@primary_gems[spec.name] = spec
end
diff --git a/lib/rubygems/commands/contents_command.rb b/lib/rubygems/commands/contents_command.rb
index f17aed64db..f378441ca4 100644
--- a/lib/rubygems/commands/contents_command.rb
+++ b/lib/rubygems/commands/contents_command.rb
@@ -1,39 +1,40 @@
# frozen_string_literal: true
-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
- super 'contents', 'Display the contents of the installed gems',
+ super "contents", "Display the contents of the installed gems",
:specdirs => [], :lib_only => false, :prefix => true,
:show_install_dir => false
add_version_option
- add_option('--all',
+ add_option("--all",
"Contents for all gems") do |all, options|
options[:all] = all
end
- add_option('-s', '--spec-dir a,b,c', Array,
+ add_option("-s", "--spec-dir a,b,c", Array,
"Search for gems under specific paths") do |spec_dirs, options|
options[:specdirs] = spec_dirs
end
- add_option('-l', '--[no-]lib-only',
+ add_option("-l", "--[no-]lib-only",
"Only return files in the Gem's lib_dirs") do |lib_only, options|
options[:lib_only] = lib_only
end
- add_option('--[no-]prefix',
+ add_option("--[no-]prefix",
"Don't include installed path prefix") do |prefix, options|
options[:prefix] = prefix
end
- add_option('--[no-]show-install-dir',
- 'Show only the gem install dir') do |show, options|
+ add_option("--[no-]show-install-dir",
+ "Show only the gem install dir") do |show, options|
options[:show_install_dir] = show
end
@@ -77,7 +78,7 @@ prefix or only the files that are requireable.
gem_contents name
end
- terminate_interaction 1 unless found or names.length > 1
+ terminate_interaction 1 unless found || names.length > 1
end
end
@@ -105,11 +106,11 @@ prefix or only the files that are requireable.
case file
when /\A#{spec.bindir}\//
# $' is POSTMATCH
- [RbConfig::CONFIG['bindir'], $']
+ [RbConfig::CONFIG["bindir"], $']
when /\.so\z/
- [RbConfig::CONFIG['archdir'], file]
+ [RbConfig::CONFIG["archdir"], file]
else
- [RbConfig::CONFIG['rubylibdir'], file]
+ [RbConfig::CONFIG["rubylibdir"], file]
end
end
end
diff --git a/lib/rubygems/commands/dependency_command.rb b/lib/rubygems/commands/dependency_command.rb
index e472d8fa8d..cef98e30d3 100644
--- a/lib/rubygems/commands/dependency_command.rb
+++ b/lib/rubygems/commands/dependency_command.rb
@@ -1,28 +1,29 @@
# 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
def initialize
- super 'dependency',
- 'Show the dependencies of an installed gem',
+ super "dependency",
+ "Show the dependencies of an installed gem",
:version => Gem::Requirement.default, :domain => :local
add_version_option
add_platform_option
add_prerelease_option
- add_option('-R', '--[no-]reverse-dependencies',
- 'Include reverse dependencies in the output') do
+ add_option("-R", "--[no-]reverse-dependencies",
+ "Include reverse dependencies in the output") do
|value, options|
options[:reverse_dependencies] = value
end
- add_option('-p', '--pipe',
+ add_option("-p", "--pipe",
"Pipe Format (name --version ver)") do |value, options|
options[:pipe_format] = value
end
@@ -53,41 +54,41 @@ use with other commands.
"#{program_name} REGEXP"
end
- def fetch_remote_specs(dependency) # :nodoc:
+ def fetch_remote_specs(name, requirement, prerelease) # :nodoc:
fetcher = Gem::SpecFetcher.fetcher
- ss, = fetcher.spec_for_dependency dependency
+ specs_type = prerelease ? :complete : :released
+
+ ss = if name.nil?
+ fetcher.detect(specs_type) { true }
+ else
+ fetcher.detect(specs_type) do |name_tuple|
+ name === name_tuple.name && requirement.satisfied_by?(name_tuple.version)
+ end
+ end
- ss.map {|spec, _| spec }
+ ss.map {|tuple, source| source.fetch_spec(tuple) }
end
- def fetch_specs(name_pattern, dependency) # :nodoc:
+ def fetch_specs(name_pattern, requirement, prerelease) # :nodoc:
specs = []
if local?
specs.concat Gem::Specification.stubs.find_all {|spec|
- name_pattern =~ spec.name and
- dependency.requirement.satisfied_by? spec.version
+ name_matches = name_pattern ? name_pattern =~ spec.name : true
+ version_matches = requirement.satisfied_by?(spec.version)
+
+ name_matches && version_matches
}.map(&:to_spec)
end
- specs.concat fetch_remote_specs dependency if remote?
+ specs.concat fetch_remote_specs name_pattern, requirement, prerelease if remote?
ensure_specs specs
specs.uniq.sort
end
- def gem_dependency(pattern, version, prerelease) # :nodoc:
- dependency = Gem::Deprecate.skip_during do
- Gem::Dependency.new pattern, version
- end
-
- dependency.prerelease = prerelease
-
- dependency
- end
-
def display_pipe(specs) # :nodoc:
specs.each do |spec|
unless spec.dependencies.empty?
@@ -119,11 +120,9 @@ use with other commands.
ensure_local_only_reverse_dependencies
pattern = name_pattern options[:args]
+ requirement = Gem::Requirement.new options[:version]
- dependency =
- gem_dependency pattern, options[:version], options[:prerelease]
-
- specs = fetch_specs pattern, dependency
+ specs = fetch_specs pattern, requirement, options[:prerelease]
reverse = reverse_dependencies specs
@@ -135,8 +134,8 @@ use with other commands.
end
def ensure_local_only_reverse_dependencies # :nodoc:
- if options[:reverse_dependencies] and remote? and not local?
- alert_error 'Only reverse dependencies for local gems are supported.'
+ if options[:reverse_dependencies] && remote? && !local?
+ alert_error "Only reverse dependencies for local gems are supported."
terminate_interaction 1
end
end
@@ -144,7 +143,7 @@ use with other commands.
def ensure_specs(specs) # :nodoc:
return unless specs.empty?
- patterns = options[:args].join ','
+ patterns = options[:args].join ","
say "No gems found matching #{patterns} (#{options[:version]})" if
Gem.configuration.verbose
@@ -153,23 +152,15 @@ use with other commands.
def print_dependencies(spec, level = 0) # :nodoc:
response = String.new
- response << ' ' * level + "Gem #{spec.full_name}\n"
+ response << " " * level + "Gem #{spec.full_name}\n"
unless spec.dependencies.empty?
spec.dependencies.sort_by {|dep| dep.name }.each do |dep|
- response << ' ' * level + " #{dep}\n"
+ response << " " * level + " #{dep}\n"
end
end
response
end
- def remote_specs(dependency) # :nodoc:
- fetcher = Gem::SpecFetcher.fetcher
-
- ss, _ = fetcher.spec_for_dependency dependency
-
- ss.map {|s,o| s }
- end
-
def reverse_dependencies(specs) # :nodoc:
reverse = Hash.new {|h, k| h[k] = [] }
@@ -192,7 +183,7 @@ use with other commands.
sp.dependencies.each do |dep|
dep = Gem::Dependency.new(*dep) unless Gem::Dependency === dep
- if spec.name == dep.name and
+ if spec.name == dep.name &&
dep.requirement.satisfied_by?(spec.version)
result << [sp.full_name, dep]
end
@@ -205,9 +196,9 @@ use with other commands.
private
def name_pattern(args)
- args << '' if args.empty?
+ return if args.empty?
- if args.length == 1 and args.first =~ /\A(.*)(i)?\z/m
+ if args.length == 1 && args.first =~ /\A(.*)(i)?\z/m
flags = $2 ? Regexp::IGNORECASE : nil
Regexp.new $1, flags
else
diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb
index 37429fb836..28dbf93c50 100644
--- a/lib/rubygems/commands/environment_command.rb
+++ b/lib/rubygems/commands/environment_command.rb
@@ -1,21 +1,23 @@
# 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'
+ super "environment", "Display information about the RubyGems environment"
end
def arguments # :nodoc:
args = <<-EOF
- gemdir display the path where gems are installed
- gempath display path used to search for gems
+ home display the path where gems are installed. Aliases: gemhome, gemdir, GEM_HOME
+ path display path used to search for gems. Aliases: gempath, GEM_PATH
+ user_gemhome display the path where gems are installed when `--user-install` is given. Aliases: user_gemdir
version display the gem format version
remotesources display the remote gem servers
platform display the supported gem platforms
<omitted> display everything
EOF
- return args.gsub(/^\s+/, '')
+ return args.gsub(/^\s+/, "")
end
def description # :nodoc:
@@ -80,6 +82,8 @@ lib/rubygems/defaults/operating_system.rb
Gem.dir
when /^gempath/, /^path/, /^GEM_PATH/ then
Gem.path.join(File::PATH_SEPARATOR)
+ when /^user_gemdir/, /^user_gemhome/ then
+ Gem.user_dir
when /^remotesources/ then
Gem.sources.to_a.join("\n")
when /^platform/ then
@@ -138,7 +142,7 @@ lib/rubygems/defaults/operating_system.rb
out << " - GEM CONFIGURATION:\n"
Gem.configuration.each do |name, value|
- value = value.gsub(/./, '*') if name == 'gemcutter_key'
+ value = value.gsub(/./, "*") if name == "gemcutter_key"
out << " - #{name.inspect} => #{value.inspect}\n"
end
@@ -149,7 +153,7 @@ lib/rubygems/defaults/operating_system.rb
out << " - SHELL PATH:\n"
- shell_path = ENV['PATH'].split(File::PATH_SEPARATOR)
+ shell_path = ENV["PATH"].split(File::PATH_SEPARATOR)
add_path out, shell_path
out
diff --git a/lib/rubygems/commands/exec_command.rb b/lib/rubygems/commands/exec_command.rb
new file mode 100644
index 0000000000..383c8c5b37
--- /dev/null
+++ b/lib/rubygems/commands/exec_command.rb
@@ -0,0 +1,249 @@
+# frozen_string_literal: true
+
+require_relative "../command"
+require_relative "../dependency_installer"
+require_relative "../gem_runner"
+require_relative "../package"
+require_relative "../version_option"
+
+class Gem::Commands::ExecCommand < Gem::Command
+ include Gem::VersionOption
+
+ def initialize
+ super "exec", "Run a command from a gem", {
+ version: Gem::Requirement.default,
+ }
+
+ add_version_option
+ add_prerelease_option "to be installed"
+
+ add_option "-g", "--gem GEM", "run the executable from the given gem" do |value, options|
+ options[:gem_name] = value
+ end
+
+ add_option(:"Install/Update", "--conservative",
+ "Prefer the most recent installed version, ",
+ "rather than the latest version overall") do |value, options|
+ options[:conservative] = true
+ end
+ end
+
+ def arguments # :nodoc:
+ "COMMAND the executable command to run"
+ end
+
+ def defaults_str # :nodoc:
+ "--version '#{Gem::Requirement.default}'"
+ end
+
+ def description # :nodoc:
+ <<-EOF
+The exec command handles installing (if necessary) and running an executable
+from a gem, regardless of whether that gem is currently installed.
+
+The exec command can be thought of as a shortcut to running `gem install` and
+then the executable from the installed gem.
+
+For example, `gem exec rails new .` will run `rails new .` in the current
+directory, without having to manually run `gem install rails`.
+Additionally, the exec command ensures the most recent version of the gem
+is used (unless run with `--conservative`), and that the gem is not installed
+to the same gem path as user-installed gems.
+ EOF
+ end
+
+ def usage # :nodoc:
+ "#{program_name} [options --] COMMAND [args]"
+ end
+
+ def execute
+ gem_paths = { "GEM_HOME" => Gem.paths.home, "GEM_PATH" => Gem.paths.path.join(File::PATH_SEPARATOR), "GEM_SPEC_CACHE" => Gem.paths.spec_cache_dir }.compact
+
+ check_executable
+
+ print_command
+ if options[:gem_name] == "gem" && options[:executable] == "gem"
+ set_gem_exec_install_paths
+ Gem::GemRunner.new.run options[:args]
+ return
+ elsif options[:conservative]
+ install_if_needed
+ else
+ install
+ activate!
+ end
+
+ load!
+ ensure
+ ENV.update(gem_paths) if gem_paths
+ Gem.clear_paths
+ end
+
+ private
+
+ def handle_options(args)
+ args = add_extra_args(args)
+ check_deprecated_options(args)
+ @options = Marshal.load Marshal.dump @defaults # deep copy
+ parser.order!(args) do |v|
+ # put the non-option back at the front of the list of arguments
+ args.unshift(v)
+
+ # stop parsing once we hit the first non-option,
+ # so you can call `gem exec rails --version` and it prints the rails
+ # version rather than rubygem's
+ break
+ end
+ @options[:args] = args
+
+ options[:executable], gem_version = extract_gem_name_and_version(options[:args].shift)
+ options[:gem_name] ||= options[:executable]
+
+ if gem_version
+ if options[:version].none?
+ options[:version] = Gem::Requirement.new(gem_version)
+ else
+ options[:version].concat [gem_version]
+ end
+ end
+
+ if options[:prerelease] && !options[:version].prerelease?
+ if options[:version].none?
+ options[:version] = Gem::Requirement.default_prerelease
+ else
+ options[:version].concat [Gem::Requirement.default_prerelease]
+ end
+ end
+ end
+
+ def check_executable
+ if options[:executable].nil?
+ raise Gem::CommandLineError,
+ "Please specify an executable to run (e.g. #{program_name} COMMAND)"
+ end
+ end
+
+ def print_command
+ verbose "running #{program_name} with:\n"
+ opts = options.reject {|_, v| v.nil? || Array(v).empty? }
+ max_length = opts.map {|k, _| k.size }.max
+ opts.each do |k, v|
+ next if v.nil?
+ verbose "\t#{k.to_s.rjust(max_length)}: #{v}"
+ end
+ verbose ""
+ end
+
+ def install_if_needed
+ activate!
+ rescue Gem::MissingSpecError
+ verbose "#{Gem::Dependency.new(options[:gem_name], options[:version])} not available locally, installing from remote"
+ install
+ activate!
+ end
+
+ def set_gem_exec_install_paths
+ home = File.join(Gem.dir, "gem_exec")
+
+ ENV["GEM_PATH"] = ([home] + Gem.path).join(File::PATH_SEPARATOR)
+ ENV["GEM_HOME"] = home
+ Gem.clear_paths
+ end
+
+ def install
+ set_gem_exec_install_paths
+
+ gem_name = options[:gem_name]
+ gem_version = options[:version]
+
+ install_options = options.merge(
+ minimal_deps: false,
+ wrappers: true
+ )
+
+ suppress_always_install do
+ dep_installer = Gem::DependencyInstaller.new install_options
+
+ request_set = dep_installer.resolve_dependencies gem_name, gem_version
+
+ verbose "Gems to install:"
+ request_set.sorted_requests.each do |activation_request|
+ verbose "\t#{activation_request.full_name}"
+ end
+
+ request_set.install install_options
+ end
+
+ Gem::Specification.reset
+ rescue Gem::InstallError => e
+ alert_error "Error installing #{gem_name}:\n\t#{e.message}"
+ terminate_interaction 1
+ rescue Gem::GemNotFoundException => e
+ show_lookup_failure e.name, e.version, e.errors, false
+
+ terminate_interaction 2
+ rescue Gem::UnsatisfiableDependencyError => e
+ show_lookup_failure e.name, e.version, e.errors, false,
+ "'#{gem_name}' (#{gem_version})"
+
+ terminate_interaction 2
+ end
+
+ def activate!
+ gem(options[:gem_name], options[:version])
+ Gem.finish_resolve
+
+ verbose "activated #{options[:gem_name]} (#{Gem.loaded_specs[options[:gem_name]].version})"
+ end
+
+ def load!
+ argv = ARGV.clone
+ ARGV.replace options[:args]
+
+ exe = executable = options[:executable]
+
+ contains_executable = Gem.loaded_specs.values.select do |spec|
+ spec.executables.include?(executable)
+ end
+
+ if contains_executable.any? {|s| s.name == executable }
+ contains_executable.select! {|s| s.name == executable }
+ end
+
+ if contains_executable.empty?
+ if (spec = Gem.loaded_specs[executable]) && (exe = spec.executable)
+ contains_executable << spec
+ else
+ alert_error "Failed to load executable `#{executable}`," \
+ " are you sure the gem `#{options[:gem_name]}` contains it?"
+ terminate_interaction 1
+ end
+ end
+
+ if contains_executable.size > 1
+ alert_error "Ambiguous which gem `#{executable}` should come from: " \
+ "the options are #{contains_executable.map(&:name)}, " \
+ "specify one via `-g`"
+ terminate_interaction 1
+ end
+
+ load Gem.activate_bin_path(contains_executable.first.name, exe, ">= 0.a")
+ ensure
+ ARGV.replace argv
+ end
+
+ def suppress_always_install
+ name = :always_install
+ cls = ::Gem::Resolver::InstallerSet
+ method = cls.instance_method(name)
+ cls.remove_method(name)
+ cls.define_method(name) { [] }
+
+ begin
+ yield
+ ensure
+ cls.remove_method(name)
+ cls.define_method(name, method)
+ end
+ end
+end
diff --git a/lib/rubygems/commands/fetch_command.rb b/lib/rubygems/commands/fetch_command.rb
index 6a1b346dd3..950d4fe30e 100644
--- a/lib/rubygems/commands/fetch_command.rb
+++ b/lib/rubygems/commands/fetch_command.rb
@@ -1,14 +1,20 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
+
+require_relative "../command"
+require_relative "../local_remote_options"
+require_relative "../version_option"
class Gem::Commands::FetchCommand < Gem::Command
include Gem::LocalRemoteOptions
include Gem::VersionOption
def initialize
- super 'fetch', 'Download a gem and place it in the current directory'
+ defaults = {
+ :suggest_alternate => true,
+ :version => Gem::Requirement.default,
+ }
+
+ super "fetch", "Download a gem and place it in the current directory", defaults
add_bulk_threshold_option
add_proxy_option
@@ -18,10 +24,14 @@ class Gem::Commands::FetchCommand < Gem::Command
add_version_option
add_platform_option
add_prerelease_option
+
+ add_option "--[no-]suggestions", "Suggest alternates when gems are not found" do |value, options|
+ options[:suggest_alternate] = value
+ end
end
def arguments # :nodoc:
- 'GEMNAME name of gem to download'
+ "GEMNAME name of gem to download"
end
def defaults_str # :nodoc:
@@ -42,15 +52,27 @@ then repackaging it.
"#{program_name} GEMNAME [GEMNAME ...]"
end
+ def check_version # :nodoc:
+ if options[:version] != Gem::Requirement.default &&
+ get_all_gem_names.size > 1
+ alert_error "Can't use --version with multiple gems. You can specify multiple gems with" \
+ " version requirements using `gem fetch 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`"
+ terminate_interaction 1
+ end
+ end
+
def execute
- version = options[:version] || Gem::Requirement.default
+ check_version
+ version = options[:version]
platform = Gem.platforms.last
- gem_names = get_all_gem_names
+ gem_names = get_all_gem_names_and_versions
- gem_names.each do |gem_name|
- dep = Gem::Dependency.new gem_name, version
+ gem_names.each do |gem_name, gem_version|
+ gem_version ||= version
+ dep = Gem::Dependency.new gem_name, gem_version
dep.prerelease = options[:prerelease]
+ suppress_suggestions = !options[:suggest_alternate]
specs_and_sources, errors =
Gem::SpecFetcher.fetcher.spec_for_dependency dep
@@ -60,15 +82,13 @@ then repackaging it.
specs_and_sources = filtered unless filtered.empty?
end
- spec, source = specs_and_sources.max_by {|s,| s.version }
+ spec, source = specs_and_sources.max_by {|s,| s }
if spec.nil?
- show_lookup_failure gem_name, version, errors, options[:domain]
+ show_lookup_failure gem_name, gem_version, errors, suppress_suggestions, options[:domain]
next
end
-
source.download spec
-
say "Downloaded #{spec.full_name}"
end
end
diff --git a/lib/rubygems/commands/generate_index_command.rb b/lib/rubygems/commands/generate_index_command.rb
index 93e25ef5e4..ce580cfaf9 100644
--- a/lib/rubygems/commands/generate_index_command.rb
+++ b/lib/rubygems/commands/generate_index_command.rb
@@ -1,6 +1,7 @@
# 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.
@@ -9,27 +10,27 @@ require 'rubygems/indexer'
class Gem::Commands::GenerateIndexCommand < Gem::Command
def initialize
- super 'generate_index',
- 'Generates the index files for a gem server directory',
- :directory => '.', :build_modern => true
+ super "generate_index",
+ "Generates the index files for a gem server directory",
+ :directory => ".", :build_modern => true
- add_option '-d', '--directory=DIRNAME',
- 'repository base dir containing gems subdir' do |dir, options|
+ add_option "-d", "--directory=DIRNAME",
+ "repository base dir containing gems subdir" do |dir, options|
options[:directory] = File.expand_path dir
end
- add_option '--[no-]modern',
- 'Generate indexes for RubyGems',
- '(always true)' do |value, options|
+ add_option "--[no-]modern",
+ "Generate indexes for RubyGems",
+ "(always true)" do |value, options|
options[:build_modern] = value
end
- deprecate_option('--modern', version: '4.0', extra_msg: 'Modern indexes (specs, latest_specs, and prerelease_specs) are always generated, so this option is not needed.')
- deprecate_option('--no-modern', version: '4.0', extra_msg: 'The `--no-modern` option is currently ignored. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated.')
+ deprecate_option("--modern", version: "4.0", extra_msg: "Modern indexes (specs, latest_specs, and prerelease_specs) are always generated, so this option is not needed.")
+ deprecate_option("--no-modern", version: "4.0", extra_msg: "The `--no-modern` option is currently ignored. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated.")
- add_option '--update',
- 'Update modern indexes with gems added',
- 'since the last update' do |value, options|
+ add_option "--update",
+ "Update modern indexes with gems added",
+ "since the last update" do |value, options|
options[:update] = value
end
end
@@ -68,8 +69,8 @@ Marshal::MINOR_VERSION constants. It is used to ensure compatibility.
# This is always true because it's the only way now.
options[:build_modern] = true
- if not File.exist?(options[:directory]) or
- not File.directory?(options[:directory])
+ if !File.exist?(options[:directory]) ||
+ !File.directory?(options[:directory])
alert_error "unknown directory name #{options[:directory]}."
terminate_interaction 1
else
diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb
index 4e8d7600fb..20b99fa366 100644
--- a/lib/rubygems/commands/help_command.rb
+++ b/lib/rubygems/commands/help_command.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
+
+require_relative "../command"
class Gem::Commands::HelpCommand < Gem::Command
# :stopdoc:
- EXAMPLES = <<-EOF.freeze
+ EXAMPLES = <<-EOF
Some examples of 'gem' usage.
* Install 'rake', either from local directory or remote server:
@@ -52,7 +53,7 @@ Some examples of 'gem' usage.
gem update --system
EOF
- GEM_DEPENDENCIES = <<-EOF.freeze
+ GEM_DEPENDENCIES = <<-EOF
A gem dependencies file allows installation of a consistent set of gems across
multiple environments. The RubyGems implementation is designed to be
compatible with Bundler's Gemfile format. You can see additional
@@ -229,7 +230,7 @@ default. This may be overridden with the :development_group option:
EOF
- PLATFORMS = <<-'EOF'.freeze
+ PLATFORMS = <<-'EOF'
RubyGems platforms are composed of three parts, a CPU, an OS, and a
version. These values are taken from values in rbconfig.rb. You can view
your current platform by running `gem environment`.
@@ -280,7 +281,7 @@ platform.
# :startdoc:
def initialize
- super 'help', "Provide help on the 'gem' command"
+ super "help", "Provide help on the 'gem' command"
@command_manager = Gem::CommandManager.instance
end
@@ -326,7 +327,7 @@ platform.
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)
+ wrap_indent = " " * (margin_width + desc_width)
format = "#{' ' * margin_width}%-#{desc_width}s%s"
@command_manager.command_names.each do |cmd_name|
diff --git a/lib/rubygems/commands/info_command.rb b/lib/rubygems/commands/info_command.rb
index 9ca6ae364f..ced7751ff5 100644
--- a/lib/rubygems/commands/info_command.rb
+++ b/lib/rubygems/commands/info_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
+require_relative "../command"
+require_relative "../query_utils"
class Gem::Commands::InfoCommand < Gem::Command
include Gem::QueryUtils
@@ -13,7 +13,7 @@ class Gem::Commands::InfoCommand < Gem::Command
add_query_options
- remove_option('-d')
+ remove_option("-d")
defaults[:details] = true
defaults[:exact] = true
diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb
index 4d36c69d51..b0bc2908b4 100644
--- a/lib/rubygems/commands/install_command.rb
+++ b/lib/rubygems/commands/install_command.rb
@@ -1,10 +1,12 @@
# 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"
+require_relative "../update_suggestion"
##
# Gem installer command line tool
@@ -17,19 +19,20 @@ class Gem::Commands::InstallCommand < Gem::Command
include Gem::VersionOption
include Gem::LocalRemoteOptions
include Gem::InstallUpdateOptions
+ include Gem::UpdateSuggestion
def initialize
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
:format_executable => false,
- :lock => true,
+ :lock => true,
:suggest_alternate => true,
- :version => Gem::Requirement.default,
- :without_groups => [],
+ :version => Gem::Requirement.default,
+ :without_groups => [],
})
defaults.merge!(install_update_options)
- super 'install', 'Install a gem into the local repository', defaults
+ super "install", "Install a gem into the local repository", defaults
add_install_update_options
add_local_remote_options
@@ -46,8 +49,8 @@ class Gem::Commands::InstallCommand < Gem::Command
def defaults_str # :nodoc:
"--both --version '#{Gem::Requirement.default}' --no-force\n" +
- "--install-dir #{Gem.dir} --lock\n" +
- install_update_defaults_str
+ "--install-dir #{Gem.dir} --lock\n" +
+ install_update_defaults_str
end
def description # :nodoc:
@@ -134,15 +137,15 @@ You can use `i` command instead of `install`.
end
def check_install_dir # :nodoc:
- if options[:install_dir] and options[:user_install]
+ if options[:install_dir] && options[:user_install]
alert_error "Use --install-dir or --user-install but not both"
terminate_interaction 1
end
end
def check_version # :nodoc:
- if options[:version] != Gem::Requirement.default and
- get_all_gem_names.size > 1
+ if options[:version] != Gem::Requirement.default &&
+ get_all_gem_names.size > 1
alert_error "Can't use --version with multiple gems. You can specify multiple gems with" \
" version requirements using `gem install 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`"
terminate_interaction 1
@@ -157,7 +160,7 @@ You can use `i` command instead of `install`.
@installed_specs = []
- ENV.delete 'GEM_PATH' if options[:install_dir].nil?
+ ENV.delete "GEM_PATH" if options[:install_dir].nil?
check_install_dir
check_version
@@ -168,11 +171,13 @@ You can use `i` command instead of `install`.
show_installed
+ say update_suggestion if eglible_for_update?
+
terminate_interaction exit_code
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|
@@ -191,8 +196,8 @@ You can use `i` command instead of `install`.
end
def install_gem(name, version) # :nodoc:
- return if options[:conservative] and
- not Gem::Dependency.new(name, version).matching_specs.empty?
+ return if options[:conservative] &&
+ !Gem::Dependency.new(name, version).matching_specs.empty?
req = Gem::Requirement.create(version)
@@ -247,11 +252,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:
@@ -260,7 +265,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.redact(x.source.uri)}': #{x.error.message}"
alert_warning msg
end
@@ -269,7 +275,7 @@ You can use `i` command instead of `install`.
def show_installed # :nodoc:
return if @installed_specs.empty?
- gems = @installed_specs.length == 1 ? 'gem' : 'gems'
+ 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 5c99d3d73d..522c771f90 100644
--- a/lib/rubygems/commands/list_command.rb
+++ b/lib/rubygems/commands/list_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
+
+require_relative "../command"
+require_relative "../query_utils"
##
# Searches for gems starting with the supplied argument.
@@ -9,8 +10,8 @@ class Gem::Commands::ListCommand < Gem::Command
include Gem::QueryUtils
def initialize
- super 'list', 'Display local gems whose name matches REGEXP',
- :name => //, :domain => :local, :details => false, :versions => true,
+ super "list", "Display local gems whose name matches REGEXP",
+ :domain => :local, :details => false, :versions => true,
:installed => nil, :version => Gem::Requirement.default
add_query_options
diff --git a/lib/rubygems/commands/lock_command.rb b/lib/rubygems/commands/lock_command.rb
index f1dc1ac586..3a9512fe3f 100644
--- a/lib/rubygems/commands/lock_command.rb
+++ b/lib/rubygems/commands/lock_command.rb
@@ -1,13 +1,14 @@
# 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',
+ super "lock", "Generate a lockdown list of gems",
:strict => false
- add_option '-s', '--[no-]strict',
- 'fail if unable to satisfy a dependency' do |strict, options|
+ add_option "-s", "--[no-]strict",
+ "fail if unable to satisfy a dependency" do |strict, options|
options[:strict] = strict
end
end
diff --git a/lib/rubygems/commands/mirror_command.rb b/lib/rubygems/commands/mirror_command.rb
index 86671a93b2..b91a8db12d 100644
--- a/lib/rubygems/commands/mirror_command.rb
+++ b/lib/rubygems/commands/mirror_command.rb
@@ -1,12 +1,13 @@
# 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)')
+ super("mirror", "Mirror all gem files (requires rubygems-mirror)")
begin
- Gem::Specification.find_by_name('rubygems-mirror').activate
+ Gem::Specification.find_by_name("rubygems-mirror").activate
rescue Gem::LoadError
# no-op
end
diff --git a/lib/rubygems/commands/open_command.rb b/lib/rubygems/commands/open_command.rb
index 8012a9a0e1..5a13074a1d 100644
--- a/lib/rubygems/commands/open_command.rb
+++ b/lib/rubygems/commands/open_command.rb
@@ -1,18 +1,19 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
+
+require_relative "../command"
+require_relative "../version_option"
class Gem::Commands::OpenCommand < Gem::Command
include Gem::VersionOption
def initialize
- super 'open', 'Open gem sources in editor'
+ super "open", "Open gem sources in editor"
- add_option('-e', '--editor COMMAND', String,
+ add_option("-e", "--editor COMMAND", String,
"Prepends COMMAND to gem path. Could be used to specify editor.") do |command, options|
options[:editor] = command || get_env_editor
end
- add_option('-v', '--version VERSION', String,
+ add_option("-v", "--version VERSION", String,
"Opens specific gem version") do |version|
options[:version] = version
end
@@ -40,10 +41,10 @@ class Gem::Commands::OpenCommand < Gem::Command
end
def get_env_editor
- ENV['GEM_EDITOR'] ||
- ENV['VISUAL'] ||
- ENV['EDITOR'] ||
- 'vi'
+ ENV["GEM_EDITOR"] ||
+ ENV["VISUAL"] ||
+ ENV["EDITOR"] ||
+ "vi"
end
def execute
diff --git a/lib/rubygems/commands/outdated_command.rb b/lib/rubygems/commands/outdated_command.rb
index 3579bfc3ba..08a9221a26 100644
--- a/lib/rubygems/commands/outdated_command.rb
+++ b/lib/rubygems/commands/outdated_command.rb
@@ -1,15 +1,16 @@
# 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
def initialize
- super 'outdated', 'Display all gems that need updates'
+ super "outdated", "Display all gems that need updates"
add_local_remote_options
add_platform_option
diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb
index dd49027469..b51c9cf888 100644
--- a/lib/rubygems/commands/owner_command.rb
+++ b/lib/rubygems/commands/owner_command.rb
@@ -1,8 +1,9 @@
# 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
@@ -12,7 +13,12 @@ class Gem::Commands::OwnerCommand < Gem::Command
def description # :nodoc:
<<-EOF
The owner command lets you add and remove owners of a gem on a push
-server (the default is https://rubygems.org).
+server (the default is https://rubygems.org). Multiple owners can be
+added or removed at the same time, if the flag is given multiple times.
+
+The supported user identifiers are dependent on the push server.
+For rubygems.org, both e-mail and handle are supported, even though the
+user identifier field is called "email".
The owner of a gem has the permission to push new versions, yank existing
versions or edit the HTML page of the gem. Be careful of who you give push
@@ -29,23 +35,23 @@ permission to.
end
def initialize
- super 'owner', 'Manage gem owners of a gem on the push server'
+ super "owner", "Manage gem owners of a gem on the push server"
add_proxy_option
add_key_option
add_otp_option
defaults.merge! :add => [], :remove => []
- add_option '-a', '--add EMAIL', 'Add an owner' do |value, options|
+ add_option "-a", "--add NEW_OWNER", "Add an owner by user identifier" do |value, options|
options[:add] << value
end
- add_option '-r', '--remove EMAIL', 'Remove an owner' do |value, options|
+ add_option "-r", "--remove OLD_OWNER", "Remove an owner by user identifier" do |value, options|
options[:remove] << value
end
- add_option '-h', '--host HOST',
- 'Use another gemcutter-compatible host',
- ' (e.g. https://rubygems.org)' do |value, options|
+ add_option "-h", "--host HOST",
+ "Use another gemcutter-compatible host",
+ " (e.g. https://rubygems.org)" do |value, options|
options[:host] = value
end
end
@@ -93,8 +99,10 @@ permission to.
action = method == :delete ? "Removing" : "Adding"
with_response response, "#{action} #{owner}"
- rescue
- # ignore
+ rescue Gem::WebauthnVerificationError => e
+ raise e
+ rescue StandardError
+ # ignore early exits to allow for completing the iteration of all owners
end
end
end
@@ -103,7 +111,7 @@ permission to.
def send_owner_request(method, name, owner)
rubygems_api_request method, "api/v1/gems/#{name}/owners", scope: get_owner_scope(method: method) do |request|
- request.set_form_data 'email' => owner
+ request.set_form_data "email" => owner
request.add_field "Authorization", api_key
end
end
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 143105981e..64608a033f 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -1,62 +1,73 @@
# 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
- super 'pristine',
- 'Restores installed gems to pristine condition from files located in the gem cache',
+ super "pristine",
+ "Restores installed gems to pristine condition from files located in the gem cache",
:version => Gem::Requirement.default,
:extensions => true,
:extensions_set => false,
:all => false
- add_option('--all',
- 'Restore all installed gems to pristine',
- 'condition') do |value, options|
+ add_option("--all",
+ "Restore all installed gems to pristine",
+ "condition") do |value, options|
options[:all] = value
end
- add_option('--skip=gem_name',
- 'used on --all, skip if name == gem_name') do |value, options|
+ add_option("--skip=gem_name",
+ "used on --all, skip if name == gem_name") do |value, options|
options[:skip] ||= []
options[:skip] << value
end
- add_option('--[no-]extensions',
- 'Restore gems with extensions',
- 'in addition to regular gems') do |value, options|
+ add_option("--[no-]extensions",
+ "Restore gems with extensions",
+ "in addition to regular gems") do |value, options|
options[:extensions_set] = true
options[:extensions] = value
end
- add_option('--only-executables',
- 'Only restore executables') do |value, options|
+ add_option("--only-missing-extensions",
+ "Only restore gems with missing extensions") do |value, options|
+ options[:only_missing_extensions] = value
+ end
+
+ add_option("--only-executables",
+ "Only restore executables") do |value, options|
options[:only_executables] = value
end
- add_option('--only-plugins',
- 'Only restore plugins') do |value, options|
+ 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|
+ 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('-n', '--bindir DIR',
- 'Directory where executables are',
- 'located') do |value, options|
+ 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|
options[:bin_dir] = File.expand_path(value)
end
- add_version_option('restore to', 'pristine condition')
+ add_version_option("restore to", "pristine condition")
end
def arguments # :nodoc:
@@ -64,7 +75,7 @@ class Gem::Commands::PristineCommand < Gem::Command
end
def defaults_str # :nodoc:
- '--extensions'
+ "--extensions"
end
def description # :nodoc:
@@ -93,22 +104,26 @@ extensions will be restored.
def execute
specs = if options[:all]
- Gem::Specification.map
-
- # `--extensions` must be explicitly given to pristine only gems
- # with extensions.
- elsif options[:extensions_set] and
- options[:extensions] and options[:args].empty?
- Gem::Specification.select do |spec|
- spec.extensions and not spec.extensions.empty?
- end
- else
- get_all_gem_names.sort.map do |gem_name|
- Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse
- end.flatten
- end
-
- specs = specs.select{|spec| RUBY_ENGINE == spec.platform || Gem::Platform.local === spec.platform || spec.platform == Gem::Platform::RUBY }
+ Gem::Specification.map
+
+ # `--extensions` must be explicitly given to pristine only gems
+ # with extensions.
+ elsif options[:extensions_set] &&
+ options[:extensions] && options[:args].empty?
+ Gem::Specification.select do |spec|
+ spec.extensions && !spec.extensions.empty?
+ end
+ elsif options[:only_missing_extensions]
+ Gem::Specification.select do |spec|
+ spec.missing_extensions?
+ end
+ else
+ get_all_gem_names.sort.map do |gem_name|
+ Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse
+ end.flatten
+ end
+
+ specs = specs.select {|spec| RUBY_ENGINE == spec.platform || Gem::Platform.local === spec.platform || spec.platform == Gem::Platform::RUBY }
if specs.to_a.empty?
raise Gem::Exception,
@@ -130,15 +145,15 @@ extensions will be restored.
end
end
- unless spec.extensions.empty? or options[:extensions] or options[:only_executables] or options[:only_plugins]
+ unless spec.extensions.empty? || options[:extensions] || options[:only_executables] || 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] or options[:only_plugins]
- require 'rubygems/remote_fetcher'
+ unless File.exist?(gem) || options[:only_executables] || options[:only_plugins]
+ require_relative "../remote_fetcher"
say "Cached gem for #{spec.full_name} not found, attempting to fetch..."
@@ -158,16 +173,17 @@ extensions will be restored.
if options.include? :env_shebang
options[:env_shebang]
else
- install_defaults = Gem::ConfigFile::PLATFORM_DEFAULTS['install']
- install_defaults.to_s['--env-shebang']
+ install_defaults = Gem::ConfigFile::PLATFORM_DEFAULTS["install"]
+ install_defaults.to_s["--env-shebang"]
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,
@@ -177,7 +193,7 @@ extensions will be restored.
installer = Gem::Installer.for_spec(spec, installer_options)
installer.generate_bin
elsif options[:only_plugins]
- installer = Gem::Installer.for_spec(spec)
+ installer = Gem::Installer.for_spec(spec, installer_options)
installer.generate_plugins
else
installer = Gem::Installer.at(gem, installer_options)
diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb
index 1a9a1932f8..79ca3d59b0 100644
--- a/lib/rubygems/commands/push_command.rb
+++ b/lib/rubygems/commands/push_command.rb
@@ -1,8 +1,9 @@
# 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
@@ -29,7 +30,7 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
end
def initialize
- super 'push', 'Push a gem up to the gem server', :host => self.host
+ super "push", "Push a gem up to the gem server", :host => self.host
@user_defined_host = false
@@ -37,9 +38,9 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
add_key_option
add_otp_option
- add_option('--host HOST',
- 'Push to another gemcutter-compatible host',
- ' (e.g. https://rubygems.org)') do |value, options|
+ add_option("--host HOST",
+ "Push to another gemcutter-compatible host",
+ " (e.g. https://rubygems.org)") do |value, options|
options[:host] = value
@user_defined_host = true
end
@@ -52,14 +53,14 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
default_gem_server, push_host = get_hosts_for(gem_name)
@host = if @user_defined_host
- options[:host]
- elsif default_gem_server
- default_gem_server
- elsif push_host
- push_host
- else
- options[:host]
- end
+ options[:host]
+ elsif default_gem_server
+ default_gem_server
+ elsif push_host
+ push_host
+ else
+ options[:host]
+ end
sign_in @host, scope: get_push_scope
diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb
index 789afd6509..4fa201272e 100644
--- a/lib/rubygems/commands/query_command.rb
+++ b/lib/rubygems/commands/query_command.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
-require 'rubygems/deprecate'
+
+require_relative "../command"
+require_relative "../query_utils"
+require_relative "../deprecate"
class Gem::Commands::QueryCommand < Gem::Command
extend Gem::Deprecate
@@ -17,15 +18,15 @@ class Gem::Commands::QueryCommand < Gem::Command
alert_warning message unless Gem::Deprecate.skip
end
- def initialize(name = 'query',
- summary = 'Query gem information in local or remote repositories')
+ def initialize(name = "query",
+ summary = "Query gem information in local or remote repositories")
super name, summary,
- :name => //, :domain => :local, :details => false, :versions => true,
+ :domain => :local, :details => false, :versions => true,
:installed => nil, :version => Gem::Requirement.default
- add_option('-n', '--name-matches REGEXP',
- 'Name of gem(s) to query on matches the',
- 'provided REGEXP') do |value, options|
+ 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
diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb
index e8c9e84b29..e318a52914 100644
--- a/lib/rubygems/commands/rdoc_command.rb
+++ b/lib/rubygems/commands/rdoc_command.rb
@@ -1,35 +1,36 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/rdoc'
-require 'fileutils'
+
+require_relative "../command"
+require_relative "../version_option"
+require_relative "../rdoc"
+require "fileutils"
class Gem::Commands::RdocCommand < Gem::Command
include Gem::VersionOption
def initialize
- super 'rdoc', 'Generates RDoc for pre-installed gems',
+ super "rdoc", "Generates RDoc for pre-installed gems",
:version => Gem::Requirement.default,
:include_rdoc => false, :include_ri => true, :overwrite => false
- add_option('--all',
- 'Generate RDoc/RI documentation for all',
- 'installed gems') do |value, options|
+ add_option("--all",
+ "Generate RDoc/RI documentation for all",
+ "installed gems") do |value, options|
options[:all] = value
end
- add_option('--[no-]rdoc',
- 'Generate RDoc HTML') do |value, options|
+ add_option("--[no-]rdoc",
+ "Generate RDoc HTML") do |value, options|
options[:include_rdoc] = value
end
- add_option('--[no-]ri',
- 'Generate RI data') do |value, options|
+ add_option("--[no-]ri",
+ "Generate RI data") do |value, options|
options[:include_ri] = value
end
- add_option('--[no-]overwrite',
- 'Overwrite installed documents') do |value, options|
+ add_option("--[no-]overwrite",
+ "Overwrite installed documents") do |value, options|
options[:overwrite] = value
end
@@ -61,15 +62,15 @@ Use --overwrite to force rebuilding of documentation.
def execute
specs = if options[:all]
- Gem::Specification.to_a
- else
- get_all_gem_names.map do |name|
- Gem::Specification.find_by_name name, options[:version]
- end.flatten.uniq
- end
+ Gem::Specification.to_a
+ else
+ get_all_gem_names.map do |name|
+ Gem::Specification.find_by_name name, options[:version]
+ end.flatten.uniq
+ end
if specs.empty?
- alert_error 'No matching gems found'
+ alert_error "No matching gems found"
terminate_interaction 1
end
@@ -79,15 +80,16 @@ Use --overwrite to force rebuilding of documentation.
doc.force = options[:overwrite]
if options[:overwrite]
- FileUtils.rm_rf File.join(spec.doc_dir, 'ri')
- FileUtils.rm_rf File.join(spec.doc_dir, 'rdoc')
+ FileUtils.rm_rf File.join(spec.doc_dir, "ri")
+ FileUtils.rm_rf File.join(spec.doc_dir, "rdoc")
end
begin
doc.generate
rescue Errno::ENOENT => e
- e.message =~ / - /
- alert_error "Unable to document #{spec.full_name}, #{$'} is missing, skipping"
+ match = / - /.match(e.message)
+ alert_error "Unable to document #{spec.full_name}, " \
+ " #{match.post_match} is missing, skipping"
terminate_interaction 1 if specs.length == 1
end
end
diff --git a/lib/rubygems/commands/search_command.rb b/lib/rubygems/commands/search_command.rb
index aeb2119235..c7469e1fa8 100644
--- a/lib/rubygems/commands/search_command.rb
+++ b/lib/rubygems/commands/search_command.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/query_utils'
+
+require_relative "../command"
+require_relative "../query_utils"
class Gem::Commands::SearchCommand < Gem::Command
include Gem::QueryUtils
def initialize
- super 'search', 'Display remote gems whose name matches REGEXP',
- :name => //, :domain => :remote, :details => false, :versions => true,
+ super "search", "Display remote gems whose name matches REGEXP",
+ :domain => :remote, :details => false, :versions => true,
:installed => nil, :version => Gem::Requirement.default
add_query_options
diff --git a/lib/rubygems/commands/server_command.rb b/lib/rubygems/commands/server_command.rb
index 594cf77f66..f1dde4aa02 100644
--- a/lib/rubygems/commands/server_command.rb
+++ b/lib/rubygems/commands/server_command.rb
@@ -1,88 +1,26 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/server'
-require 'rubygems/deprecate'
-class Gem::Commands::ServerCommand < Gem::Command
- extend Gem::Deprecate
- rubygems_deprecate_command
+require_relative "../command"
- def initialize
- super 'server', 'Documentation and gem repository HTTP server',
- :port => 8808, :gemdir => [], :daemon => false
-
- OptionParser.accept :Port do |port|
- if port =~ /\A\d+\z/
- port = Integer port
- raise OptionParser::InvalidArgument, "#{port}: not a port number" if
- port > 65535
-
- port
- else
- begin
- Socket.getservbyname port
- rescue SocketError
- raise OptionParser::InvalidArgument, "#{port}: no such named service"
- end
+unless defined? Gem::Commands::ServerCommand
+ class Gem::Commands::ServerCommand < Gem::Command
+ def initialize
+ super("server", "Starts up a web server that hosts the RDoc (requires rubygems-server)")
+ begin
+ Gem::Specification.find_by_name("rubygems-server").activate
+ rescue Gem::LoadError
+ # no-op
end
end
- add_option '-p', '--port=PORT', :Port,
- 'port to listen on' do |port, options|
- options[:port] = port
- end
-
- add_option '-d', '--dir=GEMDIR',
- 'directories from which to serve gems',
- 'multiple directories may be provided' do |gemdir, options|
- options[:gemdir] << File.expand_path(gemdir)
- end
-
- add_option '--[no-]daemon', 'run as a daemon' do |daemon, options|
- options[:daemon] = daemon
- end
-
- add_option '-b', '--bind=HOST,HOST',
- 'addresses to bind', Array do |address, options|
- options[:addresses] ||= []
- options[:addresses].push(*address)
+ def description # :nodoc:
+ <<-EOF
+The server command has been moved to the rubygems-server gem.
+ EOF
end
- add_option '-l', '--launch[=COMMAND]',
- 'launches a browser window',
- "COMMAND defaults to 'start' on Windows",
- "and 'open' on all other platforms" do |launch, options|
- launch ||= Gem.win_platform? ? 'start' : 'open'
- options[:launch] = launch
+ def execute
+ alert_error "Install the rubygems-server gem for the server command"
end
end
-
- def defaults_str # :nodoc:
- "--port 8808 --dir #{Gem.dir} --no-daemon"
- end
-
- def description # :nodoc:
- <<-EOF
-The server command starts up a web server that hosts the RDoc for your
-installed gems and can operate as a server for installation of gems on other
-machines.
-
-The cache files for installed gems must exist to use the server as a source
-for gem installation.
-
-To install gems from a running server, use `gem install GEMNAME --source
-http://gem_server_host:8808`
-
-You can set up a shortcut to gem server documentation using the URL:
-
- http://localhost:8808/rdoc?q=%s - Firefox
- http://localhost:8808/rdoc?q=* - LaunchBar
-
- EOF
- end
-
- def execute
- options[:gemdir] = Gem.path if options[:gemdir].empty?
- Gem::Server.run options
- end
end
diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 47e215c149..df1732b49e 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
+
+require_relative "../command"
##
# Installs RubyGems itself. This command is ordinarily only available from a
@@ -12,96 +13,94 @@ class Gem::Commands::SetupCommand < Gem::Command
ENV_PATHS = %w[/usr/bin/env /bin/env].freeze
def initialize
- require 'tmpdir'
-
- super 'setup', 'Install RubyGems',
+ super "setup", "Install RubyGems",
:format_executable => false, :document => %w[ri],
:force => true,
- :site_or_vendor => 'sitelibdir',
- :destdir => '', :prefix => '', :previous_version => '',
+ :site_or_vendor => "sitelibdir",
+ :destdir => "", :prefix => "", :previous_version => "",
:regenerate_binstubs => true,
:regenerate_plugins => true
- add_option '--previous-version=VERSION',
- 'Previous version of RubyGems',
- 'Used for changelog processing' do |version, options|
+ add_option "--previous-version=VERSION",
+ "Previous version of RubyGems",
+ "Used for changelog processing" do |version, options|
options[:previous_version] = version
end
- add_option '--prefix=PREFIX',
- 'Prefix path for installing RubyGems',
- 'Will not affect gem repository location' do |prefix, options|
+ add_option "--prefix=PREFIX",
+ "Prefix path for installing RubyGems",
+ "Will not affect gem repository location" do |prefix, options|
options[:prefix] = File.expand_path prefix
end
- add_option '--destdir=DESTDIR',
- 'Root directory to install RubyGems into',
- 'Mainly used for packaging RubyGems' do |destdir, options|
+ add_option "--destdir=DESTDIR",
+ "Root directory to install RubyGems into",
+ "Mainly used for packaging RubyGems" do |destdir, options|
options[:destdir] = File.expand_path destdir
end
- add_option '--[no-]vendor',
- 'Install into vendorlibdir not sitelibdir' do |vendor, options|
- options[:site_or_vendor] = vendor ? 'vendorlibdir' : 'sitelibdir'
+ add_option "--[no-]vendor",
+ "Install into vendorlibdir not sitelibdir" do |vendor, options|
+ options[:site_or_vendor] = vendor ? "vendorlibdir" : "sitelibdir"
end
- add_option '--[no-]format-executable',
- 'Makes `gem` match ruby',
- 'If Ruby is ruby18, gem will be gem18' do |value, options|
+ add_option "--[no-]format-executable",
+ "Makes `gem` match ruby",
+ "If Ruby is ruby18, gem will be gem18" do |value, options|
options[:format_executable] = value
end
- add_option '--[no-]document [TYPES]', Array,
- 'Generate documentation for RubyGems',
- 'List the documentation types you wish to',
- 'generate. For example: rdoc,ri' do |value, options|
+ add_option "--[no-]document [TYPES]", Array,
+ "Generate documentation for RubyGems",
+ "List the documentation types you wish to",
+ "generate. For example: rdoc,ri" do |value, options|
options[:document] = case value
- when nil then %w[rdoc ri]
- when false then []
- else value
- end
+ when nil then %w[rdoc ri]
+ when false then []
+ else value
+ end
end
- add_option '--[no-]rdoc',
- 'Generate RDoc documentation for RubyGems' do |value, options|
+ add_option "--[no-]rdoc",
+ "Generate RDoc documentation for RubyGems" do |value, options|
if value
- options[:document] << 'rdoc'
+ options[:document] << "rdoc"
else
- options[:document].delete 'rdoc'
+ options[:document].delete "rdoc"
end
options[:document].uniq!
end
- add_option '--[no-]ri',
- 'Generate RI documentation for RubyGems' do |value, options|
+ add_option "--[no-]ri",
+ "Generate RI documentation for RubyGems" do |value, options|
if value
- options[:document] << 'ri'
+ options[:document] << "ri"
else
- options[:document].delete 'ri'
+ options[:document].delete "ri"
end
options[:document].uniq!
end
- add_option '--[no-]regenerate-binstubs',
- 'Regenerate gem binstubs' do |value, options|
+ add_option "--[no-]regenerate-binstubs",
+ "Regenerate gem binstubs" do |value, options|
options[:regenerate_binstubs] = value
end
- add_option '--[no-]regenerate-plugins',
- 'Regenerate gem plugins' do |value, options|
+ 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|
+ add_option "-f", "--[no-]force",
+ "Forcefully overwrite binstubs" do |value, options|
options[:force] = value
end
- add_option('-E', '--[no-]env-shebang',
- 'Rewrite executables with a shebang',
- 'of /usr/bin/env') do |value, options|
+ add_option("-E", "--[no-]env-shebang",
+ "Rewrite executables with a shebang",
+ "of /usr/bin/env") do |value, options|
options[:env_shebang] = value
end
@@ -109,7 +108,7 @@ class Gem::Commands::SetupCommand < Gem::Command
end
def check_ruby_version
- required_version = Gem::Requirement.new '>= 2.3.0'
+ required_version = Gem::Requirement.new ">= 2.6.0"
unless required_version.satisfied_by? Gem.ruby_version
alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}"
@@ -149,16 +148,9 @@ 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'
+ require "fileutils"
if Gem.configuration.really_verbose
extend FileUtils::Verbose
else
@@ -166,8 +158,8 @@ By default, this RubyGems will install gem as:
end
extend MakeDirs
- lib_dir, bin_dir = make_destination_dirs install_destdir
- man_dir = generate_default_man_dir install_destdir
+ lib_dir, bin_dir = make_destination_dirs
+ man_dir = generate_default_man_dir
install_lib lib_dir
@@ -189,8 +181,8 @@ By default, this RubyGems will install gem as:
say "RubyGems #{Gem::VERSION} installed"
- regenerate_binstubs if options[:regenerate_binstubs]
- regenerate_plugins if options[:regenerate_plugins]
+ regenerate_binstubs(bin_dir) if options[:regenerate_binstubs]
+ regenerate_plugins(bin_dir) if options[:regenerate_plugins]
uninstall_old_gemcutter
@@ -203,7 +195,7 @@ By default, this RubyGems will install gem as:
end
if options[:previous_version].empty?
- options[:previous_version] = Gem::VERSION.sub(/[0-9]+$/, '0')
+ options[:previous_version] = Gem::VERSION.sub(/[0-9]+$/, "0")
end
options[:previous_version] = Gem::Version.new(options[:previous_version])
@@ -225,7 +217,7 @@ By default, this RubyGems will install gem as:
end
if documentation_success
- if options[:document].include? 'rdoc'
+ if options[:document].include? "rdoc"
say "Rdoc documentation was installed. You may now invoke:"
say " gem server"
say "and then peruse beautifully formatted documentation for your gems"
@@ -236,7 +228,7 @@ By default, this RubyGems will install gem as:
say
end
- if options[:document].include? 'ri'
+ if options[:document].include? "ri"
say "Ruby Interactive (ri) documentation was installed. ri is kind of like man "
say "pages for Ruby libraries. You may access it like this:"
say " ri Classname"
@@ -253,40 +245,39 @@ By default, this RubyGems will install gem as:
def install_executables(bin_dir)
prog_mode = options[:prog_mode] || 0755
- executables = { 'gem' => 'bin' }
+ executables = { "gem" => "exe" }
executables.each do |tool, path|
say "Installing #{tool} executable" if @verbose
Dir.chdir path do
- bin_files = Dir['*']
-
- bin_files -= %w[update_rubygems]
+ bin_file = "gem"
- bin_files.each do |bin_file|
- dest_file = target_bin_path(bin_dir, bin_file)
- bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"
+ require "tmpdir"
- begin
- bin = File.readlines bin_file
- bin[0] = shebang
+ dest_file = target_bin_path(bin_dir, bin_file)
+ bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"
- File.open bin_tmp_file, 'w' do |fp|
- fp.puts bin.join
- end
+ begin
+ bin = File.readlines bin_file
+ bin[0] = shebang
- install bin_tmp_file, dest_file, :mode => prog_mode
- bin_file_names << dest_file
- ensure
- rm bin_tmp_file
+ File.open bin_tmp_file, "w" do |fp|
+ fp.puts bin.join
end
- next unless Gem.win_platform?
+ install bin_tmp_file, dest_file, :mode => prog_mode
+ bin_file_names << dest_file
+ ensure
+ rm bin_tmp_file
+ end
+
+ next unless Gem.win_platform?
- begin
- bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
+ begin
+ bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
- File.open bin_cmd_file, 'w' do |file|
- file.puts <<-TEXT
+ File.open bin_cmd_file, "w" do |file|
+ file.puts <<-TEXT
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
@@ -294,12 +285,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
@@ -307,7 +297,7 @@ By default, this RubyGems will install gem as:
def shebang
if options[:env_shebang]
- ruby_name = RbConfig::CONFIG['ruby_install_name']
+ ruby_name = RbConfig::CONFIG["ruby_install_name"]
@env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
"#!#{@env_path} #{ruby_name}\n"
else
@@ -316,8 +306,8 @@ By default, this RubyGems will install gem as:
end
def install_lib(lib_dir)
- libs = { 'RubyGems' => 'lib' }
- libs['Bundler'] = 'bundler/lib'
+ libs = { "RubyGems" => "lib" }
+ libs["Bundler"] = "bundler/lib"
libs.each do |tool, path|
say "Installing #{tool}" if @verbose
@@ -330,7 +320,7 @@ By default, this RubyGems will install gem as:
end
def install_rdoc
- gem_doc_dir = File.join Gem.dir, 'doc'
+ gem_doc_dir = File.join Gem.dir, "doc"
rubygems_name = "rubygems-#{Gem::VERSION}"
rubygems_doc_dir = File.join gem_doc_dir, rubygems_name
@@ -340,23 +330,23 @@ By default, this RubyGems will install gem as:
# ignore
end
- if File.writable? gem_doc_dir and
- (not File.exist? rubygems_doc_dir or
- File.writable? rubygems_doc_dir)
+ if File.writable?(gem_doc_dir) &&
+ (!File.exist?(rubygems_doc_dir) ||
+ File.writable?(rubygems_doc_dir))
say "Removing old RubyGems RDoc and ri" if @verbose
- Dir[File.join(Gem.dir, 'doc', 'rubygems-[0-9]*')].each do |dir|
+ Dir[File.join(Gem.dir, "doc", "rubygems-[0-9]*")].each do |dir|
rm_rf dir
end
- require 'rubygems/rdoc'
+ require_relative "../rdoc"
- fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION
+ fake_spec = Gem::Specification.new "rubygems", Gem::VERSION
def fake_spec.full_gem_path
- File.expand_path '../../../..', __FILE__
+ File.expand_path "../../..", __dir__
end
- generate_ri = options[:document].include? 'ri'
- generate_rdoc = options[:document].include? 'rdoc'
+ generate_ri = options[:document].include? "ri"
+ generate_rdoc = options[:document].include? "rdoc"
rdoc = Gem::RDoc.new fake_spec, generate_rdoc, generate_ri
rdoc.generate
@@ -371,24 +361,26 @@ 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?
- mkdir_p specs_dir, :mode => 0755
+ current_default_spec = Gem::Specification.default_stubs.find {|s| s.name == "bundler" }
+ specs_dir = if current_default_spec && default_dir == Gem.default_dir
+ Gem::Specification.remove_spec current_default_spec
+ loaded_from = current_default_spec.loaded_from
+ File.delete(loaded_from)
+ File.dirname(loaded_from)
+ else
+ target_specs_dir = File.join(default_dir, "specifications", "default")
+ mkdir_p target_specs_dir, :mode => 0755
+ target_specs_dir
+ end
bundler_spec = Dir.chdir("bundler") { Gem::Specification.load("bundler.gemspec") }
-
- # Remove bundler-*.gemspec in default specification directory.
- Dir.entries(specs_dir).
- select {|gs| gs.start_with?("bundler-") }.
- each {|gs| File.delete(File.join(specs_dir, gs)) }
-
default_spec_path = File.join(specs_dir, "#{bundler_spec.full_name}.gemspec")
Gem.write_binary(default_spec_path, bundler_spec.to_ruby)
bundler_spec = Gem::Specification.load(default_spec_path)
# 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
@@ -401,19 +393,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
@@ -424,11 +423,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
@@ -437,70 +436,49 @@ By default, this RubyGems will install gem as:
return lib_dir, bin_dir
end
- def generate_default_man_dir(install_destdir)
+ def generate_default_man_dir
prefix = options[:prefix]
if prefix.empty?
- man_dir = RbConfig::CONFIG['mandir']
+ man_dir = RbConfig::CONFIG["mandir"]
return unless man_dir
else
- man_dir = File.join prefix, 'man'
- end
-
- unless install_destdir.empty?
- man_dir = File.join install_destdir, man_dir.gsub(/^[a-zA-Z]:/, '')
+ man_dir = File.join prefix, "man"
end
- man_dir
+ prepend_destdir_if_present(man_dir)
end
- def generate_default_dirs(install_destdir)
+ def generate_default_dirs
prefix = options[:prefix]
site_or_vendor = options[:site_or_vendor]
if prefix.empty?
lib_dir = RbConfig::CONFIG[site_or_vendor]
- bin_dir = RbConfig::CONFIG['bindir']
+ bin_dir = RbConfig::CONFIG["bindir"]
else
- # Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets
- # confused about installation location, so switch back to
- # sitelibdir/vendorlibdir.
- if defined?(APPLE_GEM_HOME) and
- # just in case Apple and RubyGems don't get this patched up proper.
- (prefix == RbConfig::CONFIG['libdir'] or
- # this one is important
- prefix == File.join(RbConfig::CONFIG['libdir'], 'ruby'))
- lib_dir = RbConfig::CONFIG[site_or_vendor]
- bin_dir = RbConfig::CONFIG['bindir']
- else
- lib_dir = File.join prefix, 'lib'
- bin_dir = File.join prefix, 'bin'
- end
+ lib_dir = File.join prefix, "lib"
+ bin_dir = File.join prefix, "bin"
end
- unless install_destdir.empty?
- lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '')
- bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '')
- end
-
- [lib_dir, bin_dir]
+ [prepend_destdir_if_present(lib_dir), prepend_destdir_if_present(bin_dir)]
end
def files_in(dir)
Dir.chdir dir do
- Dir.glob(File.join('**', '*'), File::FNM_DOTMATCH).
- select{|f| !File.directory?(f) }
+ Dir.glob(File.join("**", "*"), File::FNM_DOTMATCH).
+ select {|f| !File.directory?(f) }
end
end
def remove_old_bin_files(bin_dir)
old_bin_files = {
- 'gem_mirror' => 'gem mirror',
- 'gem_server' => 'gem server',
- 'gemlock' => 'gem lock',
- 'gemri' => 'ri',
- 'gemwhich' => 'gem which',
- 'index_gem_repository.rb' => 'gem generate_index',
+ "gem_mirror" => "gem mirror",
+ "gem_server" => "gem server",
+ "gemlock" => "gem lock",
+ "gemri" => "ri",
+ "gemwhich" => "gem which",
+ "index_gem_repository.rb" => "gem generate_index",
}
old_bin_files.each do |old_bin_file, new_name|
@@ -509,7 +487,7 @@ By default, this RubyGems will install gem as:
deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead."
- File.open old_bin_path, 'w' do |fp|
+ File.open old_bin_path, "w" do |fp|
fp.write <<-EOF
#!#{Gem.ruby}
@@ -519,15 +497,15 @@ abort "#{deprecation_message}"
next unless Gem.win_platform?
- File.open "#{old_bin_path}.bat", 'w' do |fp|
+ File.open "#{old_bin_path}.bat", "w" do |fp|
fp.puts %(@ECHO.#{deprecation_message})
end
end
end
def remove_old_lib_files(lib_dir)
- lib_dirs = { File.join(lib_dir, 'rubygems') => 'lib/rubygems' }
- lib_dirs[File.join(lib_dir, 'bundler')] = 'bundler/lib/bundler'
+ lib_dirs = { 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 = files_in(new_lib_dir)
@@ -535,11 +513,11 @@ abort "#{deprecation_message}"
to_remove = old_lib_files - lib_files
- gauntlet_rubygems = File.join(lib_dir, 'gauntlet_rubygems.rb')
+ 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'
+ file.start_with? "defaults"
end
remove_file_list(to_remove, old_lib_dir)
@@ -565,7 +543,7 @@ abort "#{deprecation_message}"
end
def show_release_notes
- release_notes = File.join Dir.pwd, 'CHANGELOG.md'
+ release_notes = File.join Dir.pwd, "CHANGELOG.md"
release_notes =
if File.exist? release_notes
@@ -582,7 +560,7 @@ abort "#{deprecation_message}"
history_string = ""
- until versions.length == 0 or
+ until versions.length == 0 ||
versions.shift <= options[:previous_version] do
history_string += version_lines.shift + text.shift
end
@@ -596,19 +574,20 @@ 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')
+ ui = Gem::Uninstaller.new("gemcutter", :all => true, :ignore => true,
+ :version => "< 0.4")
ui.uninstall
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
@@ -617,11 +596,13 @@ abort "#{deprecation_message}"
command.invoke(*args)
end
- def regenerate_plugins
- require "rubygems/commands/pristine_command"
+ 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)
@@ -629,6 +610,25 @@ abort "#{deprecation_message}"
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
@@ -658,10 +658,10 @@ abort "#{deprecation_message}"
def target_bin_path(bin_dir, bin_file)
bin_file_formatted = if options[:format_executable]
- Gem.default_exec_format % bin_file
- else
- bin_file
- end
+ Gem.default_exec_format % bin_file
+ else
+ bin_file
+ end
File.join bin_dir, bin_file_formatted
end
diff --git a/lib/rubygems/commands/signin_command.rb b/lib/rubygems/commands/signin_command.rb
index 2e19c8333c..0f77908c5b 100644
--- a/lib/rubygems/commands/signin_command.rb
+++ b/lib/rubygems/commands/signin_command.rb
@@ -1,15 +1,16 @@
# 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
- super 'signin', 'Sign in to any gemcutter-compatible host. '\
- 'It defaults to https://rubygems.org'
+ super "signin", "Sign in to any gemcutter-compatible host. "\
+ "It defaults to https://rubygems.org"
- add_option('--host HOST', 'Push to another gemcutter-compatible host') do |value, options|
+ add_option("--host HOST", "Push to another gemcutter-compatible host") do |value, options|
options[:host] = value
end
@@ -17,10 +18,10 @@ class Gem::Commands::SigninCommand < Gem::Command
end
def description # :nodoc:
- 'The signin command executes host sign in for a push server (the default is'\
- ' https://rubygems.org). The host can be provided with the host flag or can'\
- ' be inferred from the provided gem. Host resolution matches the resolution'\
- ' strategy for the push command.'
+ "The signin command executes host sign in for a push server (the default is"\
+ " https://rubygems.org). The host can be provided with the host flag or can"\
+ " be inferred from the provided gem. Host resolution matches the resolution"\
+ " strategy for the push command."
end
def usage # :nodoc:
diff --git a/lib/rubygems/commands/signout_command.rb b/lib/rubygems/commands/signout_command.rb
index ebbe746cb4..bdd01e4393 100644
--- a/lib/rubygems/commands/signout_command.rb
+++ b/lib/rubygems/commands/signout_command.rb
@@ -1,14 +1,15 @@
# 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.'
+ super "signout", "Sign out from all the current sessions."
end
def description # :nodoc:
- 'The `signout` command is used to sign out from all current sessions,'\
- ' allowing you to sign in using a different set of credentials.'
+ "The `signout` command is used to sign out from all current sessions,"\
+ " allowing you to sign in using a different set of credentials."
end
def usage # :nodoc:
@@ -19,13 +20,13 @@ class Gem::Commands::SignoutCommand < Gem::Command
credentials_path = Gem.configuration.credentials_path
if !File.exist?(credentials_path)
- alert_error 'You are not currently signed in.'
+ alert_error "You are not currently signed in."
elsif !File.writable?(credentials_path)
alert_error "File '#{Gem.configuration.credentials_path}' is read-only."\
- ' Please make sure it is writable.'
+ " Please make sure it is writable."
else
Gem.configuration.unset_api_key!
- say 'You have successfully signed out from all sessions.'
+ 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 f74fb12e42..85cc68ac09 100644
--- a/lib/rubygems/commands/sources_command.rb
+++ b/lib/rubygems/commands/sources_command.rb
@@ -1,40 +1,41 @@
# 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
- require 'fileutils'
+ require "fileutils"
- super 'sources',
- 'Manage the sources and cache file RubyGems uses to search for gems'
+ super "sources",
+ "Manage the sources and cache file RubyGems uses to search for gems"
- add_option '-a', '--add SOURCE_URI', 'Add source' do |value, options|
+ add_option "-a", "--add SOURCE_URI", "Add source" do |value, options|
options[:add] = value
end
- add_option '-l', '--list', 'List sources' do |value, options|
+ add_option "-l", "--list", "List sources" do |value, options|
options[:list] = value
end
- add_option '-r', '--remove SOURCE_URI', 'Remove source' do |value, options|
+ add_option "-r", "--remove SOURCE_URI", "Remove source" do |value, options|
options[:remove] = value
end
- add_option '-c', '--clear-all',
- 'Remove all sources (clear the cache)' do |value, options|
+ add_option "-c", "--clear-all",
+ "Remove all sources (clear the cache)" do |value, options|
options[:clear_all] = value
end
- add_option '-u', '--update', 'Update source cache' do |value, options|
+ add_option "-u", "--update", "Update source cache" do |value, options|
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|
+ 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
@@ -62,7 +63,7 @@ class Gem::Commands::SourcesCommand < Gem::Command
say "#{source_uri} is not a URI"
terminate_interaction 1
rescue Gem::RemoteFetcher::FetchError => e
- say "Error fetching #{source_uri}:\n\t#{e.message}"
+ say "Error fetching #{Gem::Uri.redact(source.uri)}:\n\t#{e.message}"
terminate_interaction 1
end
end
@@ -82,8 +83,8 @@ Do you want to add this source?
def check_rubygems_https(source_uri) # :nodoc:
uri = URI source_uri
- if uri.scheme and uri.scheme.downcase == 'http' and
- uri.host.downcase == 'rubygems.org'
+ if uri.scheme && uri.scheme.downcase == "http" &&
+ uri.host.downcase == "rubygems.org"
question = <<-QUESTION.chomp
https://rubygems.org is recommended for security over #{uri}
@@ -112,7 +113,7 @@ Do you want to add this insecure source?
end
def defaults_str # :nodoc:
- '--list'
+ "--list"
end
def description # :nodoc:
@@ -138,8 +139,8 @@ do not recognize you should remove them.
RubyGems has been configured to serve gems via the following URLs through
its history:
-* http://gems.rubyforge.org (RubyGems 1.3.6 and earlier)
-* https://rubygems.org/ (RubyGems 1.3.7 through 1.8.25)
+* http://gems.rubyforge.org (RubyGems 1.3.5 and earlier)
+* http://rubygems.org (RubyGems 1.3.6 through 1.8.30, and 2.0.0)
* https://rubygems.org (RubyGems 2.0.1 and newer)
Since all of these sources point to the same set of gems you only need one
@@ -215,9 +216,9 @@ To remove a source use the --remove argument:
def remove_cache_file(desc, path) # :nodoc:
FileUtils.rm_rf path
- if not File.exist?(path)
+ if !File.exist?(path)
say "*** Removed #{desc} source cache ***"
- elsif not File.writable?(path)
+ elsif !File.writable?(path)
say "*** Unable to remove #{desc} source cache (write protected) ***"
else
say "*** Unable to remove #{desc} source cache ***"
diff --git a/lib/rubygems/commands/specification_command.rb b/lib/rubygems/commands/specification_command.rb
index 3fddaaaf30..ed158506e0 100644
--- a/lib/rubygems/commands/specification_command.rb
+++ b/lib/rubygems/commands/specification_command.rb
@@ -1,8 +1,9 @@
# 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
@@ -11,28 +12,28 @@ class Gem::Commands::SpecificationCommand < Gem::Command
def initialize
Gem.load_yaml
- super 'specification', 'Display gem specification (in yaml)',
+ super "specification", "Display gem specification (in yaml)",
:domain => :local, :version => Gem::Requirement.default,
:format => :yaml
- add_version_option('examine')
+ add_version_option("examine")
add_platform_option
add_prerelease_option
- add_option('--all', 'Output specifications for all versions of',
- 'the gem') do |value, options|
+ add_option("--all", "Output specifications for all versions of",
+ "the gem") do |value, options|
options[:all] = true
end
- add_option('--ruby', 'Output ruby format') do |value, options|
+ add_option("--ruby", "Output ruby format") do |value, options|
options[:format] = :ruby
end
- add_option('--yaml', 'Output YAML format') do |value, options|
+ add_option("--yaml", "Output YAML format") do |value, options|
options[:format] = :yaml
end
- add_option('--marshal', 'Output Marshal format') do |value, options|
+ add_option("--marshal", "Output Marshal format") do |value, options|
options[:format] = :marshal
end
@@ -88,7 +89,7 @@ Specific fields in the specification can be extracted in YAML format:
raise Gem::CommandLineError, "Unsupported version type: '#{v}'"
end
- if !req.none? and options[:all]
+ if !req.none? && options[:all]
alert_error "Specify --all or -v, not both"
terminate_interaction 1
end
@@ -102,7 +103,7 @@ Specific fields in the specification can be extracted in YAML format:
field = get_one_optional_argument
raise Gem::CommandLineError, "--ruby and FIELD are mutually exclusive" if
- field and options[:format] == :ruby
+ field && options[:format] == :ruby
if local?
if File.exist? gem
@@ -129,7 +130,7 @@ Specific fields in the specification can be extracted in YAML format:
platform = get_platform_from_requirements(options)
if platform
- specs = specs.select{|s| s.platform.to_s == platform }
+ specs = specs.select {|s| s.platform.to_s == platform }
end
unless options[:all]
@@ -140,10 +141,10 @@ Specific fields in the specification can be extracted in YAML format:
s = s.send field if field
say case options[:format]
- when :ruby then s.to_ruby
- when :marshal then Marshal.dump s
- else s.to_yaml
- end
+ when :ruby then s.to_ruby
+ when :marshal then Marshal.dump s
+ else s.to_yaml
+ end
say "\n"
end
diff --git a/lib/rubygems/commands/stale_command.rb b/lib/rubygems/commands/stale_command.rb
index badc9905c1..a94d77c193 100644
--- a/lib/rubygems/commands/stale_command.rb
+++ b/lib/rubygems/commands/stale_command.rb
@@ -1,9 +1,10 @@
# 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')
+ super("stale", "List gems along with access times")
end
def description # :nodoc:
diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb
index 1540b2f0fb..feba1c5b7c 100644
--- a/lib/rubygems/commands/uninstall_command.rb
+++ b/lib/rubygems/commands/uninstall_command.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/uninstaller'
-require 'fileutils'
+
+require_relative "../command"
+require_relative "../version_option"
+require_relative "../uninstaller"
+require "fileutils"
##
# Gem uninstaller command line tool
@@ -13,78 +14,78 @@ class Gem::Commands::UninstallCommand < Gem::Command
include Gem::VersionOption
def initialize
- super 'uninstall', 'Uninstall gems from the local repository',
+ super "uninstall", "Uninstall gems from the local repository",
:version => Gem::Requirement.default, :user_install => true,
:check_dev => false, :vendor => false
- add_option('-a', '--[no-]all',
- 'Uninstall all matching versions'
+ add_option("-a", "--[no-]all",
+ "Uninstall all matching versions"
) do |value, options|
options[:all] = value
end
- add_option('-I', '--[no-]ignore-dependencies',
- 'Ignore dependency requirements while',
- 'uninstalling') do |value, options|
+ add_option("-I", "--[no-]ignore-dependencies",
+ "Ignore dependency requirements while",
+ "uninstalling") do |value, options|
options[:ignore] = value
end
- add_option('-D', '--[no-]check-development',
- 'Check development dependencies while uninstalling',
- '(default: false)') do |value, options|
+ add_option("-D", "--[no-]check-development",
+ "Check development dependencies while uninstalling",
+ "(default: false)") do |value, options|
options[:check_dev] = value
end
- add_option('-x', '--[no-]executables',
- 'Uninstall applicable executables without',
- 'confirmation') do |value, options|
+ add_option("-x", "--[no-]executables",
+ "Uninstall applicable executables without",
+ "confirmation") do |value, options|
options[:executables] = value
end
- add_option('-i', '--install-dir DIR',
- 'Directory to uninstall gem from') do |value, options|
+ add_option("-i", "--install-dir DIR",
+ "Directory to uninstall gem from") do |value, options|
options[:install_dir] = File.expand_path(value)
end
- add_option('-n', '--bindir DIR',
- 'Directory to remove executables from') do |value, options|
+ add_option("-n", "--bindir DIR",
+ "Directory to remove executables from") do |value, options|
options[:bin_dir] = File.expand_path(value)
end
- add_option('--[no-]user-install',
- 'Uninstall from user\'s home directory',
- 'in addition to GEM_HOME.') do |value, options|
+ add_option("--[no-]user-install",
+ "Uninstall from user's home directory",
+ "in addition to GEM_HOME.") do |value, options|
options[:user_install] = value
end
- add_option('--[no-]format-executable',
- 'Assume executable names match Ruby\'s prefix and suffix.') do |value, options|
+ add_option("--[no-]format-executable",
+ "Assume executable names match Ruby's prefix and suffix.") do |value, options|
options[:format_executable] = value
end
- add_option('--[no-]force',
- 'Uninstall all versions of the named gems',
- 'ignoring dependencies') do |value, options|
+ add_option("--[no-]force",
+ "Uninstall all versions of the named gems",
+ "ignoring dependencies") do |value, options|
options[:force] = value
end
- add_option('--[no-]abort-on-dependent',
- 'Prevent uninstalling gems that are',
- 'depended on by other gems.') do |value, options|
+ add_option("--[no-]abort-on-dependent",
+ "Prevent uninstalling gems that are",
+ "depended on by other gems.") do |value, options|
options[:abort_on_dependent] = value
end
add_version_option
add_platform_option
- add_option('--vendor',
- 'Uninstall gem from the vendor directory.',
- 'Only for use by gem repackagers.') do |value, options|
+ add_option("--vendor",
+ "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'
+ alert_warning "Use your OS package manager to uninstall vendor gems"
options[:vendor] = true
options[:install_dir] = Gem.vendor_dir
end
@@ -96,7 +97,7 @@ class Gem::Commands::UninstallCommand < Gem::Command
def defaults_str # :nodoc:
"--version '#{Gem::Requirement.default}' --no-force " +
- "--user-install"
+ "--user-install"
end
def description # :nodoc:
@@ -114,8 +115,8 @@ that is a dependency of an existing gem. You can use the
end
def check_version # :nodoc:
- if options[:version] != Gem::Requirement.default and
- get_all_gem_names.size > 1
+ if options[:version] != Gem::Requirement.default &&
+ get_all_gem_names.size > 1
alert_error "Can't use --version with multiple gems. You can specify multiple gems with" \
" version requirements using `gem uninstall 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`"
terminate_interaction 1
@@ -125,7 +126,10 @@ that is a dependency of an existing gem. You can use the
def execute
check_version
- if options[:all] and not options[:args].empty?
+ # Consider only gem specifications installed at `--install-dir`
+ Gem::Specification.dirs = options[:install_dir] if options[:install_dir]
+
+ if options[:all] && !options[:args].empty?
uninstall_specific
elsif options[:all]
uninstall_all
diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb
index 8d90d08eb4..1bff53429b 100644
--- a/lib/rubygems/commands/unpack_command.rb
+++ b/lib/rubygems/commands/unpack_command.rb
@@ -1,9 +1,10 @@
# 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
@@ -17,18 +18,18 @@ class Gem::Commands::UnpackCommand < Gem::Command
include Gem::SecurityOption
def initialize
- require 'fileutils'
+ require "fileutils"
- super 'unpack', 'Unpack an installed gem to the current directory',
+ super "unpack", "Unpack an installed gem to the current directory",
:version => Gem::Requirement.default,
- :target => Dir.pwd
+ :target => Dir.pwd
- add_option('--target=DIR',
- 'target directory for unpacking') do |value, options|
+ add_option("--target=DIR",
+ "target directory for unpacking") do |value, options|
options[:target] = value
end
- add_option('--spec', 'unpack the gem specification') do |value, options|
+ add_option("--spec", "unpack the gem specification") do |value, options|
options[:spec] = true
end
@@ -103,11 +104,11 @@ command help for an example.
end
end
- File.open destination, 'w' do |io|
+ File.open destination, "w" do |io|
io.write metadata
end
else
- basename = File.basename path, '.gem'
+ basename = File.basename path, ".gem"
target_dir = File.expand_path basename, options[:target]
package = Gem::Package.new path, security_policy
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index 91d93e398c..6f084d1c38 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -1,13 +1,14 @@
# 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
@@ -25,18 +26,18 @@ class Gem::Commands::UpdateCommand < Gem::Command
options.merge!(install_update_options)
- super 'update', 'Update installed gems to the latest version', options
+ super "update", "Update installed gems to the latest version", options
add_install_update_options
- OptionParser.accept Gem::Version do |value|
+ Gem::OptionParser.accept Gem::Version do |value|
Gem::Version.new value
value
end
- add_option('--system [VERSION]', Gem::Version,
- 'Update the RubyGems system software') do |value, options|
+ add_option("--system [VERSION]", Gem::Version,
+ "Update the RubyGems system software") do |value, options|
value = true unless value
options[:system] = value
@@ -56,7 +57,7 @@ class Gem::Commands::UpdateCommand < Gem::Command
def defaults_str # :nodoc:
"--no-force --install-dir #{Gem.dir}\n" +
- install_update_defaults_str
+ install_update_defaults_str
end
def description # :nodoc:
@@ -118,15 +119,19 @@ command to remove old versions.
updated = update_gems gems_to_update
+ installed_names = highest_installed_gems.keys
updated_names = updated.map {|spec| spec.name }
not_updated_names = options[:args].uniq - updated_names
+ not_installed_names = not_updated_names - installed_names
+ up_to_date_names = not_updated_names - not_installed_names
if updated.empty?
say "Nothing to update"
else
say "Gems updated: #{updated_names.join(' ')}"
- say "Gems already up-to-date: #{not_updated_names.join(' ')}" unless not_updated_names.empty?
end
+ say "Gems already up-to-date: #{up_to_date_names.join(' ')}" unless up_to_date_names.empty?
+ say "Gems not currently installed: #{not_installed_names.join(' ')}" unless not_installed_names.empty?
end
def fetch_remote_gems(spec) # :nodoc:
@@ -151,7 +156,7 @@ command to remove old versions.
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
+ if hig[spec.name].nil? || hig[spec.name].version < spec.version
hig[spec.name] = spec
end
end
@@ -162,27 +167,23 @@ command to remove old versions.
def highest_remote_name_tuple(spec) # :nodoc:
spec_tuples = fetch_remote_gems spec
- matching_gems = spec_tuples.select do |g,_|
- g.name == spec.name and g.match_platform?
- end
-
- highest_remote_gem = matching_gems.max
-
- highest_remote_gem ||= [Gem::NameTuple.null]
+ highest_remote_gem = spec_tuples.max
+ return unless highest_remote_gem
highest_remote_gem.first
end
- def install_rubygems(version) # :nodoc:
+ def install_rubygems(spec) # :nodoc:
args = update_rubygems_arguments
+ version = spec.version
- update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"
+ update_dir = File.join spec.base_dir, "gems", "rubygems-update-#{version}"
Dir.chdir update_dir do
say "Installing RubyGems #{version}" unless options[:silent]
installed = preparing_gem_layout_for(version) do
- system Gem.ruby, '--disable-gems', 'setup.rb', *args
+ system Gem.ruby, "--disable-gems", "setup.rb", *args
end
say "RubyGems system software updated" if installed unless options[:silent]
@@ -213,30 +214,22 @@ command to remove old versions.
version = options[:system]
update_latest = version == true
- if update_latest
- version = Gem::Version.new Gem::VERSION
- requirement = Gem::Requirement.new ">= #{Gem::VERSION}"
- else
+ unless update_latest
version = Gem::Version.new version
requirement = Gem::Requirement.new version
+
+ return version, requirement
end
+ version = Gem::Version.new Gem::VERSION
+ requirement = Gem::Requirement.new ">= #{Gem::VERSION}"
+
rubygems_update = Gem::Specification.new
- rubygems_update.name = 'rubygems-update'
+ rubygems_update.name = "rubygems-update"
rubygems_update.version = version
- hig = {
- 'rubygems-update' => rubygems_update,
- }
-
- gems_to_update = which_to_update hig, options[:args], :system
- up_ver = gems_to_update.first.version
-
- target = if update_latest
- up_ver
- else
- version
- end
+ highest_remote_tup = highest_remote_name_tuple(rubygems_update)
+ target = highest_remote_tup ? highest_remote_tup.version : version
return target, requirement
end
@@ -286,40 +279,36 @@ command to remove old versions.
check_oldest_rubygems version
- update_gem 'rubygems-update', version
-
- installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement
- version = installed_gems.first.version
+ installed_gems = Gem::Specification.find_all_by_name "rubygems-update", requirement
+ installed_gems = update_gem("rubygems-update", version) if installed_gems.empty? || installed_gems.first.version != version
+ return if installed_gems.empty?
- install_rubygems version
+ install_rubygems installed_gems.first
end
def update_rubygems_arguments # :nodoc:
args = []
- args << '--silent' if options[:silent]
- args << '--prefix' << Gem.prefix if Gem.prefix
- args << '--no-document' unless options[:document].include?('rdoc') || options[:document].include?('ri')
- args << '--no-format-executable' if options[:no_format_executable]
- args << '--previous-version' << Gem::VERSION if
- options[:system] == true or
- Gem::Version.new(options[:system]) >= Gem::Version.new(2)
+ 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]
+ args << "--previous-version" << Gem::VERSION if
+ options[:system] == true ||
+ Gem::Version.new(options[:system]) >= Gem::Version.new(2)
args
end
- def which_to_update(highest_installed_gems, gem_names, system = false)
+ def which_to_update(highest_installed_gems, gem_names)
result = []
highest_installed_gems.each do |l_name, l_spec|
- next if not gem_names.empty? and
+ next if !gem_names.empty? &&
gem_names.none? {|name| name == l_spec.name }
highest_remote_tup = highest_remote_name_tuple l_spec
- highest_remote_ver = highest_remote_tup.version
- highest_installed_ver = l_spec.version
+ next unless highest_remote_tup
- if system or (highest_installed_ver < highest_remote_ver)
- result << Gem::NameTuple.new(l_spec.name, [highest_installed_ver, highest_remote_ver].max, highest_remote_tup.platform)
- end
+ result << highest_remote_tup
end
result
@@ -335,18 +324,14 @@ command to remove old versions.
#
def oldest_supported_version
@oldest_supported_version ||=
- if Gem.ruby_version > Gem::Version.new("3.0.a")
+ if Gem.ruby_version > Gem::Version.new("3.1.a")
+ Gem::Version.new("3.3.3")
+ elsif Gem.ruby_version > Gem::Version.new("3.0.a")
Gem::Version.new("3.2.3")
elsif Gem.ruby_version > Gem::Version.new("2.7.a")
Gem::Version.new("3.1.2")
- elsif Gem.ruby_version > Gem::Version.new("2.6.a")
- Gem::Version.new("3.0.1")
- elsif Gem.ruby_version > Gem::Version.new("2.5.a")
- Gem::Version.new("2.7.3")
- elsif Gem.ruby_version > Gem::Version.new("2.4.a")
- Gem::Version.new("2.6.8")
else
- Gem::Version.new("2.5.2")
+ Gem::Version.new("3.0.1")
end
end
end
diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb
index d42ab18395..ec464d9672 100644
--- a/lib/rubygems/commands/which_command.rb
+++ b/lib/rubygems/commands/which_command.rb
@@ -1,17 +1,18 @@
# 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',
+ super "which", "Find the location of a library file you can require",
:search_gems_first => false, :show_all => false
- add_option '-a', '--[no-]all', 'show all matching files' do |show_all, options|
+ add_option "-a", "--[no-]all", "show all matching files" do |show_all, options|
options[:show_all] = show_all
end
- add_option '-g', '--[no-]gems-first',
- 'search gems before non-gems' do |gems_first, options|
+ add_option "-g", "--[no-]gems-first",
+ "search gems before non-gems" do |gems_first, options|
options[:search_gems_first] = gems_first
end
end
@@ -39,7 +40,7 @@ requiring to see why it does not behave as you expect.
found = true
options[:args].each do |arg|
- arg = arg.sub(/#{Regexp.union(*Gem.suffixes)}$/, '')
+ arg = arg.sub(/#{Regexp.union(*Gem.suffixes)}$/, "")
dirs = $LOAD_PATH
spec = Gem::Specification.find_by_path arg
@@ -71,7 +72,7 @@ requiring to see why it does not behave as you expect.
dirs.each do |dir|
Gem.suffixes.each do |ext|
full_path = File.join dir, "#{package_name}#{ext}"
- if File.exist? full_path and not File.directory? full_path
+ if File.exist?(full_path) && !File.directory?(full_path)
result << full_path
return result unless options[:show_all]
end
diff --git a/lib/rubygems/commands/yank_command.rb b/lib/rubygems/commands/yank_command.rb
index a7930253d6..d344a020c3 100644
--- a/lib/rubygems/commands/yank_command.rb
+++ b/lib/rubygems/commands/yank_command.rb
@@ -1,8 +1,9 @@
# 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
@@ -28,15 +29,15 @@ data you will need to change them immediately and yank your gem.
end
def initialize
- super 'yank', 'Remove a pushed gem from the index'
+ super "yank", "Remove a pushed gem from the index"
add_version_option("remove")
add_platform_option("remove")
add_otp_option
- add_option('--host HOST',
- 'Yank from another gemcutter-compatible host',
- ' (e.g. https://rubygems.org)') do |value, options|
+ add_option("--host HOST",
+ "Yank from another gemcutter-compatible host",
+ " (e.g. https://rubygems.org)") do |value, options|
options[:host] = value
end
@@ -76,10 +77,10 @@ data you will need to change them immediately and yank your gem.
request.add_field("Authorization", api_key)
data = {
- 'gem_name' => name,
- 'version' => version,
+ "gem_name" => name,
+ "version" => version,
}
- data['platform'] = platform if platform
+ data["platform"] = platform if platform
request.set_form_data data
end
diff --git a/lib/rubygems/compatibility.rb b/lib/rubygems/compatibility.rb
index f1d452ea04..b4c1ef16fa 100644
--- a/lib/rubygems/compatibility.rb
+++ b/lib/rubygems/compatibility.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-# :stopdoc:
#--
# This file contains all sorts of little compatibility hacks that we've
@@ -8,10 +7,13 @@
#
# Ruby 1.9.x has introduced some things that are awkward, and we need to
# support them, so we define some constants to use later.
+#
+# TODO remove at RubyGems 4
#++
-# TODO remove at RubyGems 4
module Gem
+ # :stopdoc:
+
RubyGemsVersion = VERSION
deprecate_constant(:RubyGemsVersion)
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index 02bb2be122..68c653269e 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/user_interaction'
-require 'rbconfig'
+require_relative "user_interaction"
+require "rbconfig"
##
# Gem::ConfigFile RubyGems options and gem command options from gemrc.
@@ -39,7 +40,7 @@ require 'rbconfig'
class Gem::ConfigFile
include Gem::UserInteraction
- DEFAULT_BACKTRACE = false
+ DEFAULT_BACKTRACE = true
DEFAULT_BULK_THRESHOLD = 1000
DEFAULT_VERBOSITY = true
DEFAULT_UPDATE_SOURCES = true
@@ -71,7 +72,7 @@ class Gem::ConfigFile
# :startdoc:
- SYSTEM_WIDE_CONFIG_FILE = File.join SYSTEM_CONFIG_PATH, 'gemrc'
+ SYSTEM_WIDE_CONFIG_FILE = File.join SYSTEM_CONFIG_PATH, "gemrc"
##
# List of arguments supplied to the config file object.
@@ -182,20 +183,20 @@ 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
+ @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)
system_config = load_file SYSTEM_WIDE_CONFIG_FILE
user_config = load_file config_file_name.dup.tap(&Gem::UNTAINT)
- environment_config = (ENV['GEMRC'] || '')
+ environment_config = (ENV["GEMRC"] || "")
.split(File::PATH_SEPARATOR).inject({}) do |result, file|
result.merge load_file file
end
@hash = operating_system_config.merge platform_config
- unless args.index '--norc'
+ unless args.index "--norc"
@hash = @hash.merge system_config
@hash = @hash.merge user_config
@hash = @hash.merge environment_config
@@ -269,7 +270,7 @@ if you believe they were disclosed to a third party.
# Location of RubyGems.org credentials
def credentials_path
- credentials = File.join Gem.user_home, '.gem', 'credentials'
+ credentials = File.join Gem.user_home, ".gem", "credentials"
if File.exist? credentials
credentials
else
@@ -281,10 +282,10 @@ if you believe they were disclosed to a third party.
check_credentials_permissions
@api_keys = if File.exist? credentials_path
- load_file(credentials_path)
- else
- @hash
- end
+ load_file(credentials_path)
+ else
+ @hash
+ end
if @api_keys.key? :rubygems_api_key
@rubygems_api_key = @api_keys[:rubygems_api_key]
@@ -320,13 +321,13 @@ if you believe they were disclosed to a third party.
config = load_file(credentials_path).merge(host => api_key)
dirname = File.dirname credentials_path
- require 'fileutils'
+ require "fileutils"
FileUtils.mkdir_p(dirname)
Gem.load_yaml
permissions = 0600 & (~File.umask)
- File.open(credentials_path, 'w', permissions) do |f|
+ File.open(credentials_path, "w", permissions) do |f|
f.write config.to_yaml
end
@@ -368,7 +369,21 @@ if you believe they were disclosed to a third party.
# True if the backtrace option has been specified, or debug is on.
def backtrace
- @backtrace or $DEBUG
+ @backtrace || $DEBUG
+ end
+
+ # Check state file is writable. Creates empty file if not present to ensure we can write to it.
+ def state_file_writable?
+ if File.exist?(state_file_name)
+ File.writable?(state_file_name)
+ else
+ require "fileutils"
+ FileUtils.mkdir_p File.dirname(state_file_name)
+ File.open(state_file_name, "w") {}
+ true
+ end
+ rescue Errno::EACCES
+ false
end
# The name of the configuration file.
@@ -376,6 +391,25 @@ if you believe they were disclosed to a third party.
@config_file_name || Gem.config_file
end
+ # The name of the state file.
+ def state_file_name
+ Gem.state_file
+ end
+
+ # Reads time of last update check from state file
+ def last_update_check
+ if File.readable?(state_file_name)
+ File.read(state_file_name).to_i
+ else
+ 0
+ end
+ end
+
+ # Writes time of last update check to state file
+ def last_update_check=(timestamp)
+ File.write(state_file_name, timestamp.to_s) if state_file_writable?
+ end
+
# Delegates to @hash
def each(&block)
hash = @hash.dup
@@ -389,7 +423,7 @@ if you believe they were disclosed to a third party.
yield :backtrace, @backtrace
yield :bulk_threshold, @bulk_threshold
- yield 'config_file_name', @config_file_name if @config_file_name
+ yield "config_file_name", @config_file_name if @config_file_name
hash.each(&block)
end
@@ -405,7 +439,7 @@ if you believe they were disclosed to a third party.
when /^--debug$/ then
$DEBUG = true
- warn 'NOTE: Debugging mode prints all exceptions even when rescued'
+ warn "NOTE: Debugging mode prints all exceptions even when rescued"
else
@args << arg
end
@@ -444,7 +478,7 @@ if you believe they were disclosed to a third party.
@hash[:ssl_client_cert] if @hash.key? :ssl_client_cert
keys = yaml_hash.keys.map {|key| key.to_s }
- keys << 'debug'
+ keys << "debug"
re = Regexp.union(*keys)
@hash.each do |key, value|
@@ -458,10 +492,10 @@ if you believe they were disclosed to a third party.
# Writes out this config file, replacing its source.
def write
- require 'fileutils'
+ require "fileutils"
FileUtils.mkdir_p File.dirname(config_file_name)
- File.open config_file_name, 'w' do |io|
+ File.open config_file_name, "w" do |io|
io.write to_yaml
end
end
@@ -477,11 +511,11 @@ if you believe they were disclosed to a third party.
end
def ==(other) # :nodoc:
- self.class === other and
- @backtrace == other.backtrace and
- @bulk_threshold == other.bulk_threshold and
- @verbose == other.verbose and
- @update_sources == other.update_sources and
+ self.class === other &&
+ @backtrace == other.backtrace &&
+ @bulk_threshold == other.bulk_threshold &&
+ @verbose == other.verbose &&
+ @update_sources == other.update_sources &&
@hash == other.hash
end
diff --git a/lib/rubygems/core_ext/kernel_gem.rb b/lib/rubygems/core_ext/kernel_gem.rb
index e722225739..b2f97b9ed9 100644
--- a/lib/rubygems/core_ext/kernel_gem.rb
+++ b/lib/rubygems/core_ext/kernel_gem.rb
@@ -1,9 +1,4 @@
# frozen_string_literal: true
-##
-# RubyGems adds the #gem method to allow activation of specific gem versions
-# and overrides the #require method on Kernel to make gems appear as if they
-# live on the <code>$LOAD_PATH</code>. See the documentation of these methods
-# for further detail.
module Kernel
@@ -39,7 +34,7 @@ module Kernel
# GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
def gem(gem_name, *requirements) # :doc:
- skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
+ skip_list = (ENV["GEM_SKIP"] || "").split(/:/)
raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
if gem_name.kind_of? Gem::Dependency
diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb
index 4b867c55e9..0869c8746f 100644
--- a/lib/rubygems/core_ext/kernel_require.rb
+++ b/lib/rubygems/core_ext/kernel_require.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'monitor'
+require "monitor"
module Kernel
@@ -13,12 +14,12 @@ module Kernel
# Make sure we have a reference to Ruby's original Kernel#require
unless defined?(gem_original_require)
+ # :stopdoc:
alias gem_original_require require
private :gem_original_require
+ # :startdoc:
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.
@@ -33,142 +34,135 @@ module Kernel
# The normal <tt>require</tt> functionality of returning false if
# that file has already been loaded is preserved.
- def require(path)
- if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
- monitor_owned = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?
- end
- RUBYGEMS_ACTIVATION_MONITOR.enter
-
- path = path.to_path if path.respond_to? :to_path
-
- if spec = Gem.find_unresolved_default_spec(path)
- # Ensure -I beats a default gem
- resolved_path = begin
- rp = nil
- load_path_check_index = Gem.load_path_insert_index - Gem.activated_gem_paths
- Gem.suffixes.each do |s|
- $LOAD_PATH[0...load_path_check_index].each do |lp|
- safe_lp = lp.dup.tap(&Gem::UNTAINT)
- begin
- if File.symlink? safe_lp # for backward compatibility
- next
+ def require(path) # :doc:
+ return gem_original_require(path) unless Gem.discover_gems_on_require
+
+ begin
+ RUBYGEMS_ACTIVATION_MONITOR.enter
+
+ path = path.to_path if path.respond_to? :to_path
+
+ if spec = Gem.find_unresolved_default_spec(path)
+ # Ensure -I beats a default gem
+ resolved_path = begin
+ rp = nil
+ load_path_check_index = Gem.load_path_insert_index - Gem.activated_gem_paths
+ Gem.suffixes.each do |s|
+ $LOAD_PATH[0...load_path_check_index].each do |lp|
+ safe_lp = lp.dup.tap(&Gem::UNTAINT)
+ begin
+ if File.symlink? safe_lp # for backward compatibility
+ next
+ end
+ rescue SecurityError
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise
end
- rescue SecurityError
- RUBYGEMS_ACTIVATION_MONITOR.exit
- raise
- end
- full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}"))
- if File.file?(full_path)
- rp = full_path
- break
+ full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}"))
+ if File.file?(full_path)
+ rp = full_path
+ break
+ end
end
+ break if rp
end
- break if rp
+ rp
end
- rp
- end
-
- begin
- Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease)
- rescue Exception
- RUBYGEMS_ACTIVATION_MONITOR.exit
- raise
- end unless resolved_path
- end
-
- # If there are no unresolved deps, then we can use just try
- # normal require handle loading a gem from the rescue below.
-
- if Gem::Specification.unresolved_deps.empty?
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(path)
- end
-
- # If +path+ is for a gem that has already been loaded, don't
- # bother trying to find it in an unresolved gem, just go straight
- # to normal require.
- #--
- # TODO request access to the C implementation of this to speed up RubyGems
-
- if Gem::Specification.find_active_stub_by_path(path)
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(path)
- end
- # Attempt to find +path+ in any unresolved gems...
-
- found_specs = Gem::Specification.find_in_unresolved path
-
- # If there are no directly unresolved gems, then try and find +path+
- # in any gems that are available via the currently unresolved gems.
- # For example, given:
- #
- # a => b => c => d
- #
- # If a and b are currently active with c being unresolved and d.rb is
- # requested, then find_in_unresolved_tree will find d.rb in d because
- # it's a dependency of c.
- #
- if found_specs.empty?
- found_specs = Gem::Specification.find_in_unresolved_tree path
-
- found_specs.each do |found_spec|
- found_spec.activate
+ begin
+ Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease)
+ rescue Exception
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise
+ end unless resolved_path
end
- # We found +path+ directly in an unresolved gem. Now we figure out, of
- # the possible found specs, which one we should activate.
- else
-
- # Check that all the found specs are just different
- # versions of the same gem
- names = found_specs.map(&:name).uniq
+ # If there are no unresolved deps, then we can use just try
+ # normal require handle loading a gem from the rescue below.
- if names.size > 1
+ if Gem::Specification.unresolved_deps.empty?
RUBYGEMS_ACTIVATION_MONITOR.exit
- raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
+ return gem_original_require(path)
end
- # Ok, now find a gem that has no conflicts, starting
- # at the highest version.
- valid = found_specs.find {|s| !s.has_conflicts? }
+ # If +path+ is for a gem that has already been loaded, don't
+ # bother trying to find it in an unresolved gem, just go straight
+ # to normal require.
+ #--
+ # TODO request access to the C implementation of this to speed up RubyGems
- unless valid
- le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
- le.name = names.first
+ if Gem::Specification.find_active_stub_by_path(path)
RUBYGEMS_ACTIVATION_MONITOR.exit
- raise le
+ return gem_original_require(path)
end
- valid.activate
- end
+ # Attempt to find +path+ in any unresolved gems...
+
+ found_specs = Gem::Specification.find_in_unresolved path
+
+ # If there are no directly unresolved gems, then try and find +path+
+ # in any gems that are available via the currently unresolved gems.
+ # For example, given:
+ #
+ # a => b => c => d
+ #
+ # If a and b are currently active with c being unresolved and d.rb is
+ # requested, then find_in_unresolved_tree will find d.rb in d because
+ # it's a dependency of c.
+ #
+ if found_specs.empty?
+ found_specs = Gem::Specification.find_in_unresolved_tree path
+
+ found_specs.each do |found_spec|
+ found_spec.activate
+ end
- RUBYGEMS_ACTIVATION_MONITOR.exit
- return gem_original_require(path)
- rescue LoadError => load_error
- RUBYGEMS_ACTIVATION_MONITOR.enter
+ # We found +path+ directly in an unresolved gem. Now we figure out, of
+ # the possible found specs, which one we should activate.
+ else
- begin
- if load_error.path == path and Gem.try_activate(path)
- require_again = true
+ # Check that all the found specs are just different
+ # versions of the same gem
+ names = found_specs.map(&:name).uniq
+
+ if names.size > 1
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
+ end
+
+ # Ok, now find a gem that has no conflicts, starting
+ # at the highest version.
+ valid = found_specs.find {|s| !s.has_conflicts? }
+
+ unless valid
+ le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
+ le.name = names.first
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ raise le
+ end
+
+ valid.activate
end
- ensure
- RUBYGEMS_ACTIVATION_MONITOR.exit
- end
- return gem_original_require(path) if require_again
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ return gem_original_require(path)
+ rescue LoadError => load_error
+ if load_error.path == path
+ RUBYGEMS_ACTIVATION_MONITOR.enter
+
+ begin
+ require_again = Gem.try_activate(path)
+ ensure
+ RUBYGEMS_ACTIVATION_MONITOR.exit
+ end
- raise load_error
- ensure
- if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
- if monitor_owned != (ow = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?)
- STDERR.puts [$$, Thread.current, $!, $!.backtrace].inspect if $!
- raise "CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before #{monitor_owned} -> after #{ow}"
+ return gem_original_require(path) if require_again
end
+
+ raise load_error
end
end
-RUBY
private :require
diff --git a/lib/rubygems/core_ext/kernel_warn.rb b/lib/rubygems/core_ext/kernel_warn.rb
index 3373cfdd3b..1f4c77f04b 100644
--- a/lib/rubygems/core_ext/kernel_warn.rb
+++ b/lib/rubygems/core_ext/kernel_warn.rb
@@ -1,54 +1,50 @@
# frozen_string_literal: true
-# `uplevel` keyword argument of Kernel#warn is available since ruby 2.5.
-if RUBY_VERSION >= "2.5" && !Gem::KERNEL_WARN_IGNORES_INTERNAL_ENTRIES
+module Kernel
+ rubygems_path = "#{__dir__}/" # Frames to be skipped start with this path.
- module Kernel
- rubygems_path = "#{__dir__}/" # Frames to be skipped start with this path.
+ original_warn = instance_method(:warn)
- original_warn = instance_method(:warn)
+ remove_method :warn
+ class << self
remove_method :warn
+ end
- class << self
- remove_method :warn
+ module_function define_method(:warn) {|*messages, **kw|
+ unless uplevel = kw[:uplevel]
+ if Gem.java_platform? && RUBY_VERSION < "3.1"
+ return original_warn.bind(self).call(*messages)
+ else
+ return original_warn.bind(self).call(*messages, **kw)
+ end
end
- module_function define_method(:warn) {|*messages, **kw|
- unless uplevel = kw[:uplevel]
- if Gem.java_platform?
- return original_warn.bind(self).call(*messages)
- else
- return original_warn.bind(self).call(*messages, **kw)
+ # Ensure `uplevel` fits a `long`
+ uplevel, = [uplevel].pack("l!").unpack("l!")
+
+ if uplevel >= 0
+ start = 0
+ while uplevel >= 0
+ loc, = caller_locations(start, 1)
+ unless loc
+ # No more backtrace
+ start += uplevel
+ break
end
- end
- # Ensure `uplevel` fits a `long`
- uplevel, = [uplevel].pack("l!").unpack("l!")
-
- if uplevel >= 0
- start = 0
- while uplevel >= 0
- loc, = caller_locations(start, 1)
- unless loc
- # No more backtrace
- start += uplevel
- break
- end
+ start += 1
- start += 1
-
- if path = loc.path
- unless path.start_with?(rubygems_path) or path.start_with?('<internal:')
- # Non-rubygems frames
- uplevel -= 1
- end
+ if path = loc.path
+ unless path.start_with?(rubygems_path) || path.start_with?("<internal:")
+ # Non-rubygems frames
+ uplevel -= 1
end
end
- kw[:uplevel] = start
end
+ kw[:uplevel] = start
+ end
- original_warn.bind(self).call(*messages, **kw)
- }
- end
+ original_warn.bind(self).call(*messages, **kw)
+ }
end
diff --git a/lib/rubygems/core_ext/tcpsocket_init.rb b/lib/rubygems/core_ext/tcpsocket_init.rb
index 2a79b63bd6..451ffa50b2 100644
--- a/lib/rubygems/core_ext/tcpsocket_init.rb
+++ b/lib/rubygems/core_ext/tcpsocket_init.rb
@@ -1,4 +1,6 @@
-require 'socket'
+# frozen_string_literal: true
+
+require "socket"
module CoreExtensions
module TCPSocketExt
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index e95bc06792..2b1baa333d 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
+
module Gem
- DEFAULT_HOST = "https://rubygems.org".freeze
+ DEFAULT_HOST = "https://rubygems.org"
@post_install_hooks ||= []
@done_installing_hooks ||= []
@@ -20,10 +21,10 @@ module Gem
# specified in the environment
def self.default_spec_cache_dir
- 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'
+ default_spec_cache_dir = File.join Gem.data_home, "gem", "specs"
end
default_spec_cache_dir
@@ -34,21 +35,7 @@ module Gem
# specified in the environment
def self.default_dir
- path = if defined? RUBY_FRAMEWORK_VERSION
- [
- File.dirname(RbConfig::CONFIG['sitedir']),
- 'Gems',
- RbConfig::CONFIG['ruby_version'],
- ]
- else
- [
- RbConfig::CONFIG['rubylibprefix'],
- 'gems',
- RbConfig::CONFIG['ruby_version'],
- ]
- end
-
- @default_dir ||= File.join(*path)
+ @default_dir ||= File.join(RbConfig::CONFIG["rubylibprefix"], "gems", RbConfig::CONFIG["ruby_version"])
end
##
@@ -73,7 +60,7 @@ 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
##
@@ -95,7 +82,7 @@ module Gem
Dir.home.dup
rescue
if Gem.win_platform?
- File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/')
+ File.expand_path File.join(ENV["HOMEDRIVE"] || ENV["SystemDrive"], "/")
else
File.expand_path "/"
end
@@ -117,7 +104,7 @@ module Gem
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?
+ parts << RbConfig::CONFIG["ruby_version"] unless RbConfig::CONFIG["ruby_version"].empty?
File.join parts
end
@@ -125,14 +112,14 @@ module Gem
# 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'))
+ @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'
+ gemrc = File.join Gem.user_home, ".gemrc"
if File.exist? gemrc
gemrc
else
@@ -148,17 +135,31 @@ module Gem
end
##
+ # The path to standard location of the user's state file.
+
+ def self.state_file
+ @state_file ||= File.join(Gem.state_home, "gem", "last_update_check").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'))
+ @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'))
+ @data_home ||= (ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share"))
+ end
+
+ ##
+ # The path to standard location of the user's state directory.
+
+ def self.state_home
+ @state_home ||= (ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state"))
end
##
@@ -175,7 +176,7 @@ module Gem
path = []
path << user_dir if user_home && File.exist?(user_home)
path << default_dir
- path << vendor_dir if vendor_dir and File.directory? vendor_dir
+ path << vendor_dir if vendor_dir && File.directory?(vendor_dir)
path
end
@@ -183,9 +184,9 @@ module Gem
# Deduce Ruby's --program-prefix and --program-suffix from its install name
def self.default_exec_format
- exec_format = RbConfig::CONFIG['ruby_install_name'].sub('ruby', '%s') rescue '%s'
+ exec_format = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "%s") rescue "%s"
- unless exec_format =~ /%s/
+ unless exec_format.include?("%s")
raise Gem::Exception,
"[BUG] invalid exec_format #{exec_format.inspect}, no %s"
end
@@ -197,11 +198,7 @@ module Gem
# The default directory for binaries
def self.default_bindir
- if defined? RUBY_FRAMEWORK_VERSION # mac framework support
- '/usr/local/bin'
- else # generic install
- RbConfig::CONFIG['bindir']
- end
+ RbConfig::CONFIG["bindir"]
end
def self.ruby_engine
@@ -245,14 +242,14 @@ module Gem
# Directory where vendor gems are installed.
def self.vendor_dir # :nodoc:
- if vendor_dir = ENV['GEM_VENDOR']
+ if vendor_dir = ENV["GEM_VENDOR"]
return vendor_dir.dup
end
- return nil unless RbConfig::CONFIG.key? 'vendordir'
+ return nil unless RbConfig::CONFIG.key? "vendordir"
- File.join RbConfig::CONFIG['vendordir'], 'gems',
- RbConfig::CONFIG['ruby_version']
+ File.join RbConfig::CONFIG["vendordir"], "gems",
+ RbConfig::CONFIG["ruby_version"]
end
##
diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb
index 3721204ab2..d9e0c07b0f 100644
--- a/lib/rubygems/dependency.rb
+++ b/lib/rubygems/dependency.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The Dependency class holds a Gem name and a Gem::Requirement.
@@ -97,14 +98,14 @@ class Gem::Dependency
end
def pretty_print(q) # :nodoc:
- q.group 1, 'Gem::Dependency.new(', ')' do
+ q.group 1, "Gem::Dependency.new(", ")" do
q.pp name
- q.text ','
+ q.text ","
q.breakable
q.pp requirement
- q.text ','
+ q.text ","
q.breakable
q.pp type
@@ -115,7 +116,7 @@ class Gem::Dependency
# What does this dependency require?
def requirement
- return @requirement if defined?(@requirement) and @requirement
+ return @requirement if defined?(@requirement) && @requirement
# @version_requirements and @version_requirement are legacy ivar
# names, and supported here because older gems need to keep
@@ -197,7 +198,7 @@ class Gem::Dependency
reqs = other.requirement.requirements
return false unless reqs.length == 1
- return false unless reqs.first.first == '='
+ return false unless reqs.first.first == "="
version = reqs.first.last
@@ -230,10 +231,10 @@ class Gem::Dependency
version = Gem::Version.new version
- return true if requirement.none? and not version.prerelease?
- return false if version.prerelease? and
- not allow_prerelease and
- not prerelease?
+ return true if requirement.none? && !version.prerelease?
+ return false if version.prerelease? &&
+ !allow_prerelease &&
+ !prerelease?
requirement.satisfied_by? version
end
@@ -277,7 +278,10 @@ class Gem::Dependency
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
end.map(&:to_spec)
- Gem::BundlerVersionFinder.filter!(matches) if filters_bundler?
+ if prioritizes_bundler?
+ require_relative "bundler_version_finder"
+ Gem::BundlerVersionFinder.prioritize!(matches)
+ end
if platform_only
matches.reject! do |spec|
@@ -295,8 +299,8 @@ class Gem::Dependency
@requirement.specific?
end
- def filters_bundler?
- name == "bundler".freeze && !specific?
+ def prioritizes_bundler?
+ name == "bundler" && !specific?
end
def to_specs
@@ -325,11 +329,11 @@ class Gem::Dependency
active = matches.find {|spec| spec.activated? }
return active if active
- return matches.first if prerelease?
-
- # Move prereleases to the end of the list for >= 0 requirements
- pre, matches = matches.partition {|spec| spec.version.prerelease? }
- matches += pre if requirement == Gem::Requirement.default
+ unless prerelease?
+ # Move prereleases to the end of the list for >= 0 requirements
+ pre, matches = matches.partition {|spec| spec.version.prerelease? }
+ matches += pre if requirement == Gem::Requirement.default
+ end
matches.first
end
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index 400a5de5cf..a8d73e521b 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -1,12 +1,13 @@
# 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/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.
@@ -16,16 +17,16 @@ class Gem::DependencyInstaller
extend Gem::Deprecate
DEFAULT_OPTIONS = { # :nodoc:
- :env_shebang => false,
- :document => %w[ri],
- :domain => :both, # HACK dup
- :force => false,
- :format_executable => false, # HACK dup
+ :env_shebang => false,
+ :document => %w[ri],
+ :domain => :both, # HACK dup
+ :force => false,
+ :format_executable => false, # HACK dup
:ignore_dependencies => false,
- :prerelease => false,
- :security_policy => nil, # HACK NoSecurity requires OpenSSL. AlmostNo? Low?
- :wrappers => true,
- :build_args => nil,
+ :prerelease => false,
+ :security_policy => nil, # HACK NoSecurity requires OpenSSL. AlmostNo? Low?
+ :wrappers => true,
+ :build_args => nil,
:build_docs_in_background => false,
:install_as_default => false,
}.freeze
@@ -109,7 +110,7 @@ class Gem::DependencyInstaller
# gems should be considered.
def consider_local?
- @domain == :both or @domain == :local
+ @domain == :both || @domain == :local
end
##
@@ -117,7 +118,7 @@ class Gem::DependencyInstaller
# gems should be considered.
def consider_remote?
- @domain == :both or @domain == :remote
+ @domain == :both || @domain == :remote
end
##
@@ -197,7 +198,7 @@ class Gem::DependencyInstaller
def in_background(what) # :nodoc:
fork_happened = false
- if @build_docs_in_background and Process.respond_to?(:fork)
+ if @build_docs_in_background && Process.respond_to?(:fork)
begin
Process.fork do
yield
@@ -230,22 +231,22 @@ class Gem::DependencyInstaller
@installed_gems = []
options = {
- :bin_dir => @bin_dir,
- :build_args => @build_args,
- :document => @document,
- :env_shebang => @env_shebang,
- :force => @force,
- :format_executable => @format_executable,
+ :bin_dir => @bin_dir,
+ :build_args => @build_args,
+ :document => @document,
+ :env_shebang => @env_shebang,
+ :force => @force,
+ :format_executable => @format_executable,
:ignore_dependencies => @ignore_dependencies,
- :prerelease => @prerelease,
- :security_policy => @security_policy,
- :user_install => @user_install,
- :wrappers => @wrappers,
- :build_root => @build_root,
- :install_as_default => @install_as_default,
- :dir_mode => @dir_mode,
- :data_mode => @data_mode,
- :prog_mode => @prog_mode,
+ :prerelease => @prerelease,
+ :security_policy => @security_policy,
+ :user_install => @user_install,
+ :wrappers => @wrappers,
+ :build_root => @build_root,
+ :install_as_default => @install_as_default,
+ :dir_mode => @dir_mode,
+ :data_mode => @data_mode,
+ :prog_mode => @prog_mode,
}
options[:install_dir] = @install_dir if @only_install_dir
@@ -268,7 +269,7 @@ class Gem::DependencyInstaller
end
def install_development_deps # :nodoc:
- if @development and @dev_shallow
+ if @development && @dev_shallow
:shallow
elsif @development
:all
@@ -289,7 +290,7 @@ class Gem::DependencyInstaller
installer_set.force = @force
if consider_local?
- if dep_or_name =~ /\.gem$/ and File.file? dep_or_name
+ if dep_or_name =~ /\.gem$/ && File.file?(dep_or_name)
src = Gem::Source::SpecificFile.new dep_or_name
installer_set.add_local dep_or_name, src.spec, src
version = src.spec.version if version == Gem::Requirement.default
diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb
index bcf436cd03..5820298bb9 100644
--- a/lib/rubygems/dependency_list.rb
+++ b/lib/rubygems/dependency_list.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# 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
@@ -20,7 +21,7 @@ class Gem::DependencyList
attr_reader :specs
include Enumerable
- include TSort
+ include Gem::TSort
##
# Allows enabling/disabling use of development dependencies
@@ -119,11 +120,11 @@ class Gem::DependencyList
each do |spec|
spec.runtime_dependencies.each do |dep|
inst = Gem::Specification.any? do |installed_spec|
- dep.name == installed_spec.name and
- dep.requirement.satisfied_by? installed_spec.version
+ dep.name == installed_spec.name &&
+ dep.requirement.satisfied_by?(installed_spec.version)
end
- unless inst or @specs.find {|s| s.satisfies_requirement? dep }
+ unless inst || @specs.find {|s| s.satisfies_requirement? dep }
unsatisfied[spec.name] << dep
return unsatisfied if quick
end
@@ -175,7 +176,7 @@ class Gem::DependencyList
def remove_specs_unsatisfied_by(dependencies)
specs.reject! do |spec|
dep = dependencies[spec.name]
- dep and not dep.requirement.satisfied_by? spec.version
+ dep && !dep.requirement.satisfied_by?(spec.version)
end
end
diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb
index 5fe0afb6b0..9fff306949 100644
--- a/lib/rubygems/deprecate.rb
+++ b/lib/rubygems/deprecate.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Provides 3 methods for declaring when something is going away.
#
@@ -143,7 +144,7 @@ module Gem::Deprecate
end
# Deprecation method to deprecate Rubygems commands
- def rubygems_deprecate_command
+ def rubygems_deprecate_command(version = Gem::Deprecate.next_rubygems_major_version)
class_eval do
define_method "deprecated?" do
true
@@ -151,7 +152,7 @@ module Gem::Deprecate
define_method "deprecation_warning" do
msg = [ "#{self.command} command is deprecated",
- ". It will be removed in Rubygems #{Gem::Deprecate.next_rubygems_major_version}.\n",
+ ". It will be removed in Rubygems #{version}.\n",
]
alert_warning "#{msg.join}" unless Gem::Deprecate.skip
diff --git a/lib/rubygems/doctor.rb b/lib/rubygems/doctor.rb
index ef31aeddd0..1d3889af77 100644
--- a/lib/rubygems/doctor.rb
+++ b/lib/rubygems/doctor.rb
@@ -1,6 +1,7 @@
# 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
@@ -19,18 +20,18 @@ class Gem::Doctor
# subdirectory.
REPOSITORY_EXTENSION_MAP = [ # :nodoc:
- ['specifications', '.gemspec'],
- ['build_info', '.info'],
- ['cache', '.gem'],
- ['doc', ''],
- ['extensions', ''],
- ['gems', ''],
- ['plugins', ''],
+ ["specifications", ".gemspec"],
+ ["build_info", ".info"],
+ ["cache", ".gem"],
+ ["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?
@@ -59,7 +60,7 @@ class Gem::Doctor
# Are we doctoring a gem repository?
def gem_repository?
- not installed_specs.empty?
+ !installed_specs.empty?
end
##
@@ -74,8 +75,8 @@ class Gem::Doctor
Gem.use_paths @gem_repository.to_s
unless gem_repository?
- say 'This directory does not appear to be a RubyGems repository, ' +
- 'skipping'
+ say "This directory does not appear to be a RubyGems repository, " +
+ "skipping"
say
return
end
@@ -111,17 +112,17 @@ class Gem::Doctor
basename = File.basename(child, extension)
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
+ next if "specifications" == sub_directory && "default" == basename
+ next if "plugins" == sub_directory && Gem.plugin_suffix_regexp =~ (basename)
- type = File.directory?(child) ? 'directory' : 'file'
+ type = File.directory?(child) ? "directory" : "file"
action = if @dry_run
- 'Extra'
- else
- FileUtils.rm_r(child)
- 'Removed'
- end
+ "Extra"
+ else
+ FileUtils.rm_r(child)
+ "Removed"
+ end
say "#{action} #{type} #{sub_directory}/#{File.basename(child)}"
end
diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb
index abee20651e..b36fabffc2 100644
--- a/lib/rubygems/errors.rb
+++ b/lib/rubygems/errors.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# This file contains all the various exceptions and other errors that are used
# inside of RubyGems.
@@ -59,9 +60,6 @@ module Gem
private
def build_message
- if name == "bundler" && message = Gem::BundlerVersionFinder.missing_version_message
- return message
- end
names = specs.map(&:full_name)
"Could not find '#{name}' (#{requirement}) - did find: [#{names.join ','}]\n"
end
@@ -139,8 +137,8 @@ module Gem
"Found %s (%s), but was for platform%s %s" %
[@name,
@version,
- @platforms.size == 1 ? '' : 's',
- @platforms.join(' ,')]
+ @platforms.size == 1 ? "" : "s",
+ @platforms.join(" ,")]
end
end
@@ -171,8 +169,7 @@ 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.redact(@source.uri)} - #{@error.message}"
end
##
diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb
index 185efdb6ab..b92396f0ef 100644
--- a/lib/rubygems/exceptions.rb
+++ b/lib/rubygems/exceptions.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/deprecate'
-require 'rubygems/unknown_command_spell_checker'
+require_relative "deprecate"
+require_relative "unknown_command_spell_checker"
##
# Base exception class for RubyGems. All exception raised by RubyGems are a
@@ -24,10 +24,14 @@ class Gem::UnknownCommandError < Gem::Exception
return if defined?(@attached)
if defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable)
- DidYouMean::SPELL_CHECKERS['Gem::UnknownCommandError'] =
- Gem::UnknownCommandSpellChecker
+ if DidYouMean.respond_to?(:correct_error)
+ DidYouMean.correct_error(Gem::UnknownCommandError, Gem::UnknownCommandSpellChecker)
+ else
+ DidYouMean::SPELL_CHECKERS["Gem::UnknownCommandError"] =
+ Gem::UnknownCommandSpellChecker
- prepend DidYouMean::Correctable
+ prepend DidYouMean::Correctable
+ end
end
@attached = true
@@ -150,7 +154,7 @@ class Gem::ImpossibleDependenciesError < Gem::Exception
def build_message # :nodoc:
requester = @request.requester
- requester = requester ? requester.spec.full_name : 'The user'
+ requester = requester ? requester.spec.full_name : "The user"
dependency = @request.dependency
message = "#{requester} requires #{dependency} but it conflicted:\n".dup
@@ -210,6 +214,16 @@ class Gem::RubyVersionMismatch < Gem::Exception; end
class Gem::VerificationError < Gem::Exception; end
##
+# Raised by Gem::WebauthnListener when an error occurs during security
+# device verification.
+
+class Gem::WebauthnVerificationError < Gem::Exception
+ def initialize(message)
+ super "Security device verification failed: #{message}"
+ end
+end
+
+##
# Raised to indicate that a system exit should occur with the specified
# exit_code
@@ -217,14 +231,12 @@ class Gem::SystemExitException < SystemExit
##
# The exit code for the process
- attr_accessor :exit_code
+ alias exit_code status
##
# Creates a new SystemExitException with the given +exit_code+
def initialize(exit_code)
- @exit_code = exit_code
-
super exit_code, "Exiting RubyGems with exit_code #{exit_code}"
end
end
@@ -250,7 +262,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError
# Gem::Resolver::DependencyRequest +dep+
def initialize(dep, platform_mismatch=nil)
- if platform_mismatch and !platform_mismatch.empty?
+ if platform_mismatch && !platform_mismatch.empty?
plats = platform_mismatch.map {|x| x.platform.to_s }.sort.uniq
super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(', ')}"
else
@@ -284,3 +296,4 @@ 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 bdd5bd9d82..b5ca126a08 100644
--- a/lib/rubygems/ext.rb
+++ b/lib/rubygems/ext.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -10,9 +11,10 @@
module Gem::Ext; end
-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'
+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"
+require_relative "ext/cargo_builder"
diff --git a/lib/rubygems/ext/build_error.rb b/lib/rubygems/ext/build_error.rb
index 8ef57ed91a..0329c1eec3 100644
--- a/lib/rubygems/ext/build_error.rb
+++ b/lib/rubygems/ext/build_error.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
+
##
# Raised when there is an error while building extensions.
-require_relative '../exceptions'
+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 7934309901..4960ddd7b1 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require_relative '../user_interaction'
+require_relative "../user_interaction"
+require_relative "../shellwords"
class Gem::Ext::Builder
include Gem::UserInteraction
@@ -17,54 +19,77 @@ class Gem::Ext::Builder
$1.downcase
end
- def self.make(dest_path, results, make_dir = Dir.pwd)
- unless File.exist? File.join(make_dir, 'Makefile')
- raise Gem::InstallError, 'Makefile not found'
+ def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"])
+ 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'
+ RbConfig::CONFIG["configure_args"] =~ /with-make-prog\=(\w+)/
+ make_program_name = ENV["MAKE"] || ENV["make"] || $1
+ unless make_program_name
+ make_program_name = (RUBY_PLATFORM.include?("mswin")) ? "nmake" : "make"
end
- make_program = Shellwords.split(make_program)
+ make_program = Shellwords.split(make_program_name)
+
+ # The installation of the bundled gems is failed when DESTDIR is empty in mswin platform.
+ destdir = (/\bnmake/i !~ make_program_name || ENV["DESTDIR"] && ENV["DESTDIR"] != "") ? "DESTDIR=%s" % ENV["DESTDIR"] : ""
- destdir = 'DESTDIR=%s' % ENV['DESTDIR']
+ env = [destdir]
+
+ if sitedir
+ env << "sitearchdir=%s" % sitedir
+ env << "sitelibdir=%s" % sitedir
+ end
- ['clean', '', 'install'].each do |target|
+ targets.each do |target|
# Pass DESTDIR via command line to override what's in MAKEFLAGS
cmd = [
*make_program,
- destdir,
+ *env,
target,
].reject(&:empty?)
begin
run(cmd, results, "make #{target}".rstrip, make_dir)
rescue Gem::InstallError
- raise unless target == 'clean' # ignore clean failure
+ raise unless target == "clean" # ignore clean failure
end
end
end
- def self.run(command, results, command_name = nil, dir = Dir.pwd)
+ def self.ruby
+ # Gem.ruby is quoted if it contains whitespace
+ cmd = Shellwords.split(Gem.ruby)
+
+ # This load_path is only needed when running rubygems test without a proper installation.
+ # Prepending it in a normal installation will cause problem with order of $LOAD_PATH.
+ # Therefore only add load_path if it is not present in the default $LOAD_PATH.
+ load_path = File.expand_path("../..", __dir__)
+ case load_path
+ when RbConfig::CONFIG["sitelibdir"], RbConfig::CONFIG["vendorlibdir"], RbConfig::CONFIG["rubylibdir"]
+ cmd
+ else
+ cmd << "-I#{load_path}"
+ end
+ end
+
+ def self.run(command, results, command_name = nil, dir = Dir.pwd, env = {})
verbose = Gem.configuration.really_verbose
begin
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
+ rubygems_gemdeps, ENV["RUBYGEMS_GEMDEPS"] = ENV["RUBYGEMS_GEMDEPS"], nil
if verbose
puts("current directory: #{dir}")
p(command)
end
results << "current directory: #{dir}"
- require "shellwords"
- results << command.shelljoin
+ results << Shellwords.join(command)
require "open3"
# Set $SOURCE_DATE_EPOCH for the subprocess.
- env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string}
+ build_env = { "SOURCE_DATE_EPOCH" => Gem.source_date_epoch_string }.merge(env)
output, status = begin
- Open3.capture2e(env, *command, :chdir => dir)
+ Open3.capture2e(build_env, *command, :chdir => dir)
rescue => error
raise Gem::InstallError, "#{command_name || class_name} failed#{error.message}"
end
@@ -74,7 +99,7 @@ class Gem::Ext::Builder
results << output
end
ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps
end
unless status.success?
@@ -122,6 +147,8 @@ class Gem::Ext::Builder
Gem::Ext::RakeBuilder
when /CMakeLists.txt/ then
Gem::Ext::CmakeBuilder
+ when /Cargo.toml/ then
+ Gem::Ext::CargoBuilder.new
else
build_error("No builder for extension '#{extension}'")
end
@@ -201,11 +228,11 @@ EOF
# Writes +output+ to gem_make.out in the extension install directory.
def write_gem_make_out(output) # :nodoc:
- destination = File.join @spec.extension_dir, 'gem_make.out'
+ destination = File.join @spec.extension_dir, "gem_make.out"
FileUtils.mkdir_p @spec.extension_dir
- File.open destination, 'wb' do |io|
+ File.open destination, "wb" do |io|
io.puts output
end
diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb
new file mode 100644
index 0000000000..ce3b296f79
--- /dev/null
+++ b/lib/rubygems/ext/cargo_builder.rb
@@ -0,0 +1,360 @@
+# frozen_string_literal: true
+
+require_relative "../shellwords"
+
+# This class is used by rubygems to build Rust extensions. It is a thin-wrapper
+# over the `cargo rustc` command which takes care of building Rust code in a way
+# that Ruby can use.
+class Gem::Ext::CargoBuilder < Gem::Ext::Builder
+ attr_accessor :spec, :runner, :profile
+
+ def initialize
+ require_relative "../command"
+ require_relative "cargo_builder/link_flag_converter"
+
+ @runner = self.class.method(:run)
+ @profile = :release
+ end
+
+ def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
+ require "tempfile"
+ require "fileutils"
+
+ # Where's the Cargo.toml of the crate we're building
+ cargo_toml = File.join(cargo_dir, "Cargo.toml")
+ # What's the crate's name
+ crate_name = cargo_crate_name(cargo_dir, cargo_toml, results)
+
+ begin
+ # Create a tmp dir to do the build in
+ tmp_dest = Dir.mktmpdir(".gem.", cargo_dir)
+
+ # Run the build
+ cmd = cargo_command(cargo_toml, tmp_dest, args, crate_name)
+ runner.call(cmd, results, "cargo", cargo_dir, build_env)
+
+ # Where do we expect Cargo to write the compiled library
+ dylib_path = cargo_dylib_path(tmp_dest, crate_name)
+
+ # Helpful error if we didn't find the compiled library
+ raise DylibNotFoundError, tmp_dest unless File.exist?(dylib_path)
+
+ # Cargo and Ruby differ on how the library should be named, rename from
+ # what Cargo outputs to what Ruby expects
+ dlext_name = "#{crate_name}.#{makefile_config("DLEXT")}"
+ dlext_path = File.join(File.dirname(dylib_path), dlext_name)
+ FileUtils.cp(dylib_path, dlext_path)
+
+ nesting = extension_nesting(extension)
+
+ # TODO: remove in RubyGems 4
+ if Gem.install_extension_in_lib && lib_dir
+ nested_lib_dir = File.join(lib_dir, nesting)
+ FileUtils.mkdir_p nested_lib_dir
+ FileUtils.cp_r dlext_path, nested_lib_dir, remove_destination: true
+ end
+
+ # move to final destination
+ nested_dest_path = File.join(dest_path, nesting)
+ FileUtils.mkdir_p nested_dest_path
+ FileUtils.cp_r dlext_path, nested_dest_path, remove_destination: true
+ ensure
+ # clean up intermediary build artifacts
+ FileUtils.rm_rf tmp_dest if tmp_dest
+ end
+
+ results
+ end
+
+ def build_env
+ build_env = rb_config_env
+ build_env["RUBY_STATIC"] = "true" if ruby_static? && ENV.key?("RUBY_STATIC")
+ cfg = "--cfg=rb_sys_gem --cfg=rubygems --cfg=rubygems_#{Gem::VERSION.tr(".", "_")}"
+ build_env["RUSTFLAGS"] = [ENV["RUSTFLAGS"], cfg].compact.join(" ")
+ build_env
+ end
+
+ def cargo_command(cargo_toml, dest_path, args = [], crate_name = nil)
+ cmd = []
+ cmd += [cargo, "rustc"]
+ cmd += ["--crate-type", "cdylib"]
+ cmd += ["--target", ENV["CARGO_BUILD_TARGET"]] if ENV["CARGO_BUILD_TARGET"]
+ cmd += ["--target-dir", dest_path]
+ cmd += ["--manifest-path", cargo_toml]
+ cmd += ["--lib"]
+ cmd += ["--profile", profile.to_s]
+ cmd += ["--locked"]
+ cmd += Gem::Command.build_args
+ cmd += args
+ cmd += ["--"]
+ cmd += [*cargo_rustc_args(dest_path, crate_name)]
+ cmd
+ end
+
+ private
+
+ def cargo
+ ENV.fetch("CARGO", "cargo")
+ end
+
+ # returns the directory nesting of the extension, ignoring the first part, so
+ # "ext/foo/bar/Cargo.toml" becomes "foo/bar"
+ def extension_nesting(extension)
+ parts = extension.to_s.split(Regexp.union([File::SEPARATOR, File::ALT_SEPARATOR].compact))
+
+ parts = parts.each_with_object([]) do |segment, final|
+ next if segment == "."
+ if segment == ".."
+ raise Gem::InstallError, "extension outside of gem root" if final.empty?
+ next final.pop
+ end
+ final << segment
+ end
+
+ File.join(parts[1...-1])
+ end
+
+ def rb_config_env
+ result = {}
+ RbConfig::CONFIG.each {|k, v| result["RBCONFIG_#{k}"] = v }
+ result
+ end
+
+ def cargo_rustc_args(dest_dir, crate_name)
+ [
+ *linker_args,
+ *mkmf_libpath,
+ *rustc_dynamic_linker_flags(dest_dir, crate_name),
+ *rustc_lib_flags(dest_dir),
+ *platform_specific_rustc_args(dest_dir),
+ ]
+ end
+
+ def platform_specific_rustc_args(dest_dir, flags = [])
+ if mingw_target?
+ # On mingw platforms, mkmf adds libruby to the linker flags
+ flags += libruby_args(dest_dir)
+
+ # Make sure ALSR is used on mingw
+ # see https://github.com/rust-lang/rust/pull/75406/files
+ flags += ["-C", "link-arg=-Wl,--dynamicbase"]
+ flags += ["-C", "link-arg=-Wl,--disable-auto-image-base"]
+
+ # If the gem is installed on a host with build tools installed, but is
+ # run on one that isn't the missing libraries will cause the extension
+ # to fail on start.
+ flags += ["-C", "link-arg=-static-libgcc"]
+ elsif darwin_target?
+ # Ventura does not always have this flag enabled
+ flags += ["-C", "link-arg=-Wl,-undefined,dynamic_lookup"]
+ end
+
+ flags
+ end
+
+ # We want to use the same linker that Ruby uses, so that the linker flags from
+ # mkmf work properly.
+ def linker_args
+ cc_flag = Shellwords.split(makefile_config("CC"))
+ linker = cc_flag.shift
+ link_args = cc_flag.flat_map {|a| ["-C", "link-arg=#{a}"] }
+
+ return mswin_link_args if linker == "cl"
+
+ ["-C", "linker=#{linker}", *link_args]
+ end
+
+ def mswin_link_args
+ args = []
+ args += ["-l", makefile_config("LIBRUBYARG_SHARED").chomp(".lib")]
+ args += split_flags("LIBS").flat_map {|lib| ["-l", lib.chomp(".lib")] }
+ args += split_flags("LOCAL_LIBS").flat_map {|lib| ["-l", lib.chomp(".lib")] }
+ args
+ end
+
+ def libruby_args(dest_dir)
+ libs = makefile_config(ruby_static? ? "LIBRUBYARG_STATIC" : "LIBRUBYARG_SHARED")
+ raw_libs = Shellwords.split(libs)
+ raw_libs.flat_map {|l| ldflag_to_link_modifier(l) }
+ end
+
+ def ruby_static?
+ return true if %w[1 true].include?(ENV["RUBY_STATIC"])
+
+ makefile_config("ENABLE_SHARED") == "no"
+ end
+
+ def cargo_dylib_path(dest_path, crate_name)
+ prefix = so_ext == "dll" ? "" : "lib"
+ path_parts = [dest_path]
+ path_parts << ENV["CARGO_BUILD_TARGET"] if ENV["CARGO_BUILD_TARGET"]
+ path_parts += ["release", "#{prefix}#{crate_name}.#{so_ext}"]
+ File.join(*path_parts)
+ end
+
+ def cargo_crate_name(cargo_dir, manifest_path, results)
+ require "open3"
+ Gem.load_yaml
+
+ output, status =
+ begin
+ Open3.capture2e(cargo, "metadata", "--no-deps", "--format-version", "1", :chdir => cargo_dir)
+ rescue => error
+ raise Gem::InstallError, "cargo metadata failed #{error.message}"
+ end
+
+ unless status.success?
+ if Gem.configuration.really_verbose
+ puts output
+ else
+ results << output
+ end
+
+ exit_reason =
+ if status.exited?
+ ", exit code #{status.exitstatus}"
+ elsif status.signaled?
+ ", uncaught signal #{status.termsig}"
+ end
+
+ raise Gem::InstallError, "cargo metadata failed#{exit_reason}"
+ end
+
+ # cargo metadata output is specified as json, but with the
+ # --format-version 1 option the output is compatible with YAML, so we can
+ # avoid the json dependency
+ metadata = Gem::SafeYAML.safe_load(output)
+ package = metadata["packages"].find {|pkg| normalize_path(pkg["manifest_path"]) == manifest_path }
+ unless package
+ found = metadata["packages"].map {|md| "#{md["name"]} at #{md["manifest_path"]}" }
+ raise Gem::InstallError, <<-EOF
+failed to determine cargo package name
+
+looking for: #{manifest_path}
+
+found:
+#{found.join("\n")}
+EOF
+ end
+ package["name"].tr("-", "_")
+ end
+
+ def normalize_path(path)
+ return path unless File::ALT_SEPARATOR
+
+ path.tr(File::ALT_SEPARATOR, File::SEPARATOR)
+ end
+
+ def rustc_dynamic_linker_flags(dest_dir, crate_name)
+ split_flags("DLDFLAGS")
+ .map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir, crate_name) }
+ .compact
+ .flat_map {|arg| ldflag_to_link_modifier(arg) }
+ end
+
+ def rustc_lib_flags(dest_dir)
+ split_flags("LIBS").flat_map {|arg| ldflag_to_link_modifier(arg) }
+ end
+
+ def split_flags(var)
+ Shellwords.split(RbConfig::CONFIG.fetch(var, ""))
+ end
+
+ def ldflag_to_link_modifier(arg)
+ LinkFlagConverter.convert(arg)
+ end
+
+ def msvc_target?
+ makefile_config("target_os").include?("msvc")
+ end
+
+ def darwin_target?
+ makefile_config("target_os").include?("darwin")
+ end
+
+ def mingw_target?
+ makefile_config("target_os").include?("mingw")
+ end
+
+ def win_target?
+ target_platform = RbConfig::CONFIG["target_os"]
+ !!Gem::WIN_PATTERNS.find {|r| target_platform =~ r }
+ end
+
+ # Interpolate substitution vars in the arg (i.e. $(DEFFILE))
+ def maybe_resolve_ldflag_variable(input_arg, dest_dir, crate_name)
+ var_matches = input_arg.match(/\$\((\w+)\)/)
+
+ return input_arg unless var_matches
+
+ var_name = var_matches[1]
+
+ return input_arg if var_name.nil? || var_name.chomp.empty?
+
+ case var_name
+ # On windows, it is assumed that mkmf has setup an exports file for the
+ # extension, so we have to to create one ourselves.
+ when "DEFFILE"
+ write_deffile(dest_dir, crate_name)
+ else
+ RbConfig::CONFIG[var_name]
+ end
+ end
+
+ def write_deffile(dest_dir, crate_name)
+ deffile_path = File.join(dest_dir, "#{crate_name}-#{RbConfig::CONFIG["arch"]}.def")
+ export_prefix = makefile_config("EXPORT_PREFIX") || ""
+
+ File.open(deffile_path, "w") do |f|
+ f.puts "EXPORTS"
+ f.puts "#{export_prefix.strip}Init_#{crate_name}"
+ end
+
+ deffile_path
+ end
+
+ # We have to basically reimplement RbConfig::CONFIG['SOEXT'] here to support
+ # Ruby < 2.5
+ #
+ # @see https://github.com/ruby/ruby/blob/c87c027f18c005460746a74c07cd80ee355b16e4/configure.ac#L3185
+ def so_ext
+ return RbConfig::CONFIG["SOEXT"] if RbConfig::CONFIG.key?("SOEXT")
+
+ if win_target?
+ "dll"
+ elsif darwin_target?
+ "dylib"
+ else
+ "so"
+ end
+ end
+
+ # Corresponds to $(LIBPATH) in mkmf
+ def mkmf_libpath
+ ["-L", "native=#{makefile_config("libdir")}"]
+ end
+
+ def makefile_config(var_name)
+ val = RbConfig::MAKEFILE_CONFIG[var_name]
+
+ return unless val
+
+ RbConfig.expand(val.dup)
+ end
+
+ # Error raised when no cdylib artifact was created
+ class DylibNotFoundError < StandardError
+ def initialize(dir)
+ files = Dir.glob(File.join(dir, "**", "*")).map {|f| "- #{f}" }.join "\n"
+
+ super <<~MSG
+ Dynamic library not found for Rust extension (in #{dir})
+
+ Make sure you set "crate-type" in Cargo.toml to "cdylib"
+
+ Found files:
+ #{files}
+ MSG
+ end
+ end
+end
diff --git a/lib/rubygems/ext/cargo_builder/link_flag_converter.rb b/lib/rubygems/ext/cargo_builder/link_flag_converter.rb
new file mode 100644
index 0000000000..e4d196cb10
--- /dev/null
+++ b/lib/rubygems/ext/cargo_builder/link_flag_converter.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class Gem::Ext::CargoBuilder < Gem::Ext::Builder
+ # Converts Ruby link flags into something cargo understands
+ class LinkFlagConverter
+ FILTERED_PATTERNS = [
+ /compress-debug-sections/, # Not supported by all linkers, and not required for Rust
+ ].freeze
+
+ def self.convert(arg)
+ return [] if FILTERED_PATTERNS.any? {|p| p.match?(arg) }
+
+ case arg.chomp
+ when /^-L\s*(.+)$/
+ ["-L", "native=#{$1}"]
+ when /^--library=(\w+\S+)$/, /^-l\s*(\w+\S+)$/
+ ["-l", $1]
+ when /^-l\s*([^:\s])+/ # -lfoo, but not -l:libfoo.a
+ ["-l", $1]
+ when /^-F\s*(.*)$/
+ ["-l", "framework=#{$1}"]
+ else
+ ["-C", "link-args=#{arg}"]
+ end
+ end
+ end
+end
diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb
index 269e876cfa..b162664784 100644
--- a/lib/rubygems/ext/cmake_builder.rb
+++ b/lib/rubygems/ext/cmake_builder.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require_relative '../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'))
+ unless File.exist?(File.join(cmake_dir, "Makefile"))
+ require_relative "../command"
cmd = ["cmake", ".", "-DCMAKE_INSTALL_PREFIX=#{dest_path}", *Gem::Command.build_args]
run cmd, results, class_name, cmake_dir
diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb
index eb2f9fce61..6b8590ba2e 100644
--- a/lib/rubygems/ext/configure_builder.rb
+++ b/lib/rubygems/ext/configure_builder.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -7,7 +8,7 @@
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'))
+ unless File.exist?(File.join(configure_dir, "Makefile"))
cmd = ["sh", "./configure", "--prefix=#{dest_path}", *args]
run cmd, results, class_name, configure_dir
diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb
index 3ca3463615..9c22329fe3 100644
--- a/lib/rubygems/ext/ext_conf_builder.rb
+++ b/lib/rubygems/ext/ext_conf_builder.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -7,81 +8,57 @@
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'
+ require "fileutils"
+ require "tempfile"
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
- # paths cause all C extension builds to fail.
- #
- # As such, we convert to a relative path unless we are using Ruby 1.9.x on
- # Windows. This means that when using Ruby 1.9.x on Windows, paths with
- # spaces do not work.
+ # if the paths contain spaces.
#
- # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940
+ # As such, we convert to a relative path.
tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir)
- Tempfile.open %w[siteconf .rb], extension_dir do |siteconf|
- siteconf.puts "require 'rbconfig'"
- 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"
- end
+ destdir = ENV["DESTDIR"]
- siteconf.close
-
- 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, extension_dir) << File.basename(extension)
- cmd.push(*args)
-
- begin
- 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
- end
+ begin
+ cmd = ruby << File.basename(extension)
+ cmd.push(*args)
+
+ 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
- siteconf.unlink
+ FileUtils.mv mkmf_log, dest_path
end
+ end
- ENV["DESTDIR"] = nil
+ ENV["DESTDIR"] = nil
- make dest_path, results, extension_dir
+ make dest_path, results, extension_dir, tmp_dest_relative
- if tmp_dest_relative
- full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
+ full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
- # TODO remove in RubyGems 3
- if Gem.install_extension_in_lib and lib_dir
- FileUtils.mkdir_p lib_dir
- 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
+ # TODO remove in RubyGems 4
+ if Gem.install_extension_in_lib && lib_dir
+ FileUtils.mkdir_p lib_dir
+ 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
- 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
- end
- ensure
- ENV["DESTDIR"] = destdir
- siteconf.close!
+ FileUtils::Entry_.new(full_tmp_dest).traverse do |ent|
+ destent = ent.class.new(dest_path, ent.rel)
+ destent.exist? || FileUtils.mv(ent.path, destent.path)
end
+
+ make dest_path, results, extension_dir, tmp_dest_relative, ["clean"]
+ ensure
+ ENV["DESTDIR"] = destdir
end
results
@@ -92,7 +69,7 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
private
def self.get_relative_path(path, base)
- path[0..base.length - 1] = '.' if path.start_with?(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 fed98e741c..8f39a63e11 100644
--- a/lib/rubygems/ext/rake_builder.rb
+++ b/lib/rubygems/ext/rake_builder.rb
@@ -1,4 +1,7 @@
# frozen_string_literal: true
+
+require_relative "../shellwords"
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -11,16 +14,15 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder
run([Gem.ruby, File.basename(extension), *args], results, class_name, extension_dir)
end
- rake = ENV['rake']
+ rake = ENV["rake"]
if rake
- require "shellwords"
- rake = rake.shellsplit
+ rake = Shellwords.split(rake)
else
begin
- rake = [Gem.ruby, "-I#{File.expand_path("../..", __dir__)}", "-rrubygems", Gem.bin_path('rake', 'rake')]
+ rake = ruby << "-rrubygems" << Gem.bin_path("rake", "rake")
rescue Gem::Exception
- rake = [Gem.default_exec_format % 'rake']
+ rake = [Gem.default_exec_format % "rake"]
end
end
diff --git a/lib/rubygems/gem_runner.rb b/lib/rubygems/gem_runner.rb
index a36674503e..d238a5863b 100644
--- a/lib/rubygems/gem_runner.rb
+++ b/lib/rubygems/gem_runner.rb
@@ -1,18 +1,14 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/command_manager'
-require 'rubygems/deprecate'
-
-##
-# Load additional plugins from $LOAD_PATH
-
-Gem.load_env_plugins rescue nil
+require_relative "../rubygems"
+require_relative "command_manager"
+require_relative "deprecate"
##
# Run an instance of the gem program.
@@ -37,16 +33,19 @@ class Gem::GemRunner
do_configuration args
+ Gem.load_env_plugins rescue nil
+ Gem.load_plugins
+
cmd = @command_manager_class.instance
cmd.command_names.each do |command_name|
config_args = Gem.configuration[command_name]
config_args = case config_args
- when String
- config_args.split ' '
- else
- Array(config_args)
- end
+ when String
+ config_args.split " "
+ else
+ Array(config_args)
+ end
Gem::Command.add_specific_extra_args command_name, config_args
end
@@ -58,7 +57,7 @@ class Gem::GemRunner
# other arguments in the list.
def extract_build_args(args) # :nodoc:
- return [] unless offset = args.index('--')
+ return [] unless offset = args.index("--")
build_args = args.slice!(offset...args.length)
@@ -75,5 +74,3 @@ class Gem::GemRunner
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 f465881041..92739617f6 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/remote_fetcher'
-require 'rubygems/text'
+
+require_relative "remote_fetcher"
+require_relative "text"
+require_relative "gemcutter_utilities/webauthn_listener"
+require_relative "gemcutter_utilities/webauthn_poller"
##
# Utility methods for using the RubyGems API.
@@ -19,8 +22,8 @@ module Gem::GemcutterUtilities
# Add the --key option
def add_key_option
- add_option('-k', '--key KEYNAME', Symbol,
- 'Use the given API key',
+ add_option("-k", "--key KEYNAME", Symbol,
+ "Use the given API key",
"from #{Gem.configuration.credentials_path}") do |value,options|
options[:key] = value
end
@@ -30,9 +33,9 @@ module Gem::GemcutterUtilities
# Add the --otp option
def add_otp_option
- add_option('--otp CODE',
- 'Digit code for multifactor authentication',
- 'You can also use the environment variable GEM_HOST_OTP_CODE') do |value, options|
+ add_option("--otp CODE",
+ "Digit code for multifactor authentication",
+ "You can also use the environment variable GEM_HOST_OTP_CODE") do |value, options|
options[:otp] = value
end
end
@@ -69,9 +72,8 @@ module Gem::GemcutterUtilities
@host ||=
begin
- env_rubygems_host = ENV['RUBYGEMS_HOST']
- env_rubygems_host = nil if
- env_rubygems_host and env_rubygems_host.empty?
+ env_rubygems_host = ENV["RUBYGEMS_HOST"]
+ env_rubygems_host = nil if env_rubygems_host&.empty?
env_rubygems_host || configured_host
end
@@ -82,8 +84,8 @@ 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, scope: nil, &block)
- require 'net/http'
+ def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scope: nil, credentials: {}, &block)
+ require "net/http"
self.host = host if host
unless self.host
@@ -105,7 +107,7 @@ module Gem::GemcutterUtilities
response = request_with_otp(method, uri, &block)
if mfa_unauthorized?(response)
- ask_otp
+ fetch_otp(credentials)
response = request_with_otp(method, uri, &block)
end
@@ -118,7 +120,7 @@ module Gem::GemcutterUtilities
end
def mfa_unauthorized?(response)
- response.kind_of?(Net::HTTPUnauthorized) && response.body.start_with?('You have enabled multifactor authentication')
+ response.kind_of?(Net::HTTPUnauthorized) && response.body.start_with?("You have enabled multifactor authentication")
end
def update_scope(scope)
@@ -135,7 +137,7 @@ module Gem::GemcutterUtilities
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))
+ request.body = URI.encode_www_form({ :api_key => api_key }.merge(update_scope_params))
end
with_response response do |resp|
@@ -163,12 +165,19 @@ module Gem::GemcutterUtilities
key_name = get_key_name(scope)
scope_params = get_scope_params(scope)
+ profile = get_user_profile(email, password)
+ mfa_params = get_mfa_params(profile)
+ all_params = scope_params.merge(mfa_params)
+ warning = profile["warning"]
+ credentials = { email: email, password: password }
+
+ say "#{warning}\n" if warning
response = rubygems_api_request(:post, "api/v1/api_key",
- sign_in_host, scope: scope) do |request|
+ sign_in_host, credentials: credentials, scope: scope) do |request|
request.basic_auth email, password
request["OTP"] = otp if otp
- request.body = URI.encode_www_form({ name: key_name }.merge(scope_params))
+ request.body = URI.encode_www_form({ name: key_name }.merge(all_params))
end
with_response response do |resp|
@@ -195,7 +204,8 @@ module Gem::GemcutterUtilities
# block was given or shows the response body to the user.
#
# If the response was not successful, shows an error to the user including
- # the +error_prefix+ and the response body.
+ # the +error_prefix+ and the response body. If the response was a permanent redirect,
+ # shows an error to the user including the redirect location.
def with_response(response, error_prefix = nil)
case response
@@ -205,6 +215,12 @@ module Gem::GemcutterUtilities
else
say clean_text(response.body)
end
+ when Net::HTTPPermanentRedirect, Net::HTTPRedirection then
+ message = "The request has redirected permanently to #{response['location']}. Please check your defined push host URL."
+ message = "#{error_prefix}: #{message}" if error_prefix
+
+ say clean_text(message)
+ terminate_interaction(ERROR_CODE)
else
message = response.body
message = "#{error_prefix}: #{message}" if error_prefix
@@ -219,7 +235,7 @@ module Gem::GemcutterUtilities
# +response+ text and no otp provided by options.
def set_api_key(host, key)
- if host == Gem::DEFAULT_HOST
+ if default_host?
Gem.configuration.rubygems_api_key = key
else
Gem.configuration.set_api_key host, key
@@ -237,14 +253,57 @@ module Gem::GemcutterUtilities
end
end
- def ask_otp
- say 'You have enabled multi-factor authentication. Please enter OTP code.'
- options[:otp] = ask 'Code: '
+ def fetch_otp(credentials)
+ options[:otp] = if webauthn_url = webauthn_verification_url(credentials)
+ server = TCPServer.new 0
+ port = server.addr[1].to_s
+
+ url_with_port = "#{webauthn_url}?port=#{port}"
+ say "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin command with the `--otp [your_code]` option."
+
+ threads = [WebauthnListener.listener_thread(host, server), WebauthnPoller.poll_thread(options, host, webauthn_url, credentials)]
+ otp_thread = wait_for_otp_thread(*threads)
+
+ threads.each(&:join)
+
+ if error = otp_thread[:error]
+ alert_error error.message
+ terminate_interaction(1)
+ end
+
+ say "You are verified with a security device. You may close the browser window."
+ otp_thread[:otp]
+ else
+ say "You have enabled multi-factor authentication. Please enter OTP code."
+ ask "Code: "
+ end
+ end
+
+ def wait_for_otp_thread(*threads)
+ loop do
+ threads.each do |otp_thread|
+ return otp_thread unless otp_thread.alive?
+ end
+ sleep 0.1
+ end
+ ensure
+ threads.each(&:exit)
+ end
+
+ def webauthn_verification_url(credentials)
+ response = rubygems_api_request(:post, "api/v1/webauthn_verification") do |request|
+ if credentials.empty?
+ request.add_field "Authorization", api_key
+ else
+ request.basic_auth credentials[:email], credentials[:password]
+ end
+ end
+ response.is_a?(Net::HTTPSuccess) ? response.body : nil
end
def pretty_host(host)
- if Gem::DEFAULT_HOST == host
- 'RubyGems.org'
+ if default_host?
+ "RubyGems.org"
else
host
end
@@ -258,8 +317,8 @@ module Gem::GemcutterUtilities
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)?$/
+ selected = ask_yes_no("#{scope}", false)
+ scope_params[scope] = true if selected
end
say "\n"
end
@@ -267,6 +326,32 @@ module Gem::GemcutterUtilities
scope_params
end
+ def default_host?
+ self.host == Gem::DEFAULT_HOST
+ end
+
+ def get_user_profile(email, password)
+ return {} unless default_host?
+
+ response = rubygems_api_request(:get, "api/v1/profile/me.yaml") do |request|
+ request.basic_auth email, password
+ end
+
+ with_response response do |resp|
+ Gem::SafeYAML.load clean_text(resp.body)
+ end
+ end
+
+ def get_mfa_params(profile)
+ mfa_level = profile["mfa"]
+ params = {}
+ if mfa_level == "ui_only" || mfa_level == "ui_and_gem_signin"
+ selected = ask_yes_no("Would you like to enable MFA for this key? (strongly recommended)")
+ params["mfa"] = true if selected
+ end
+ params
+ end
+
def get_key_name(scope)
hostname = Socket.gethostname || "unknown-host"
user = ENV["USER"] || ENV["USERNAME"] || "unknown-user"
diff --git a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb
new file mode 100644
index 0000000000..bea9d9e397
--- /dev/null
+++ b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require_relative "webauthn_listener/response"
+
+##
+# The WebauthnListener class retrieves an OTP after a user successfully WebAuthns with the Gem host.
+# An instance opens a socket using the TCPServer instance given and listens for a request from the Gem host.
+# The request should be a GET request to the root path and contains the OTP code in the form
+# of a query parameter `code`. The listener will return the code which will be used as the OTP for
+# API requests.
+#
+# Types of responses sent by the listener after receiving a request:
+# - 200 OK: OTP code was successfully retrieved
+# - 204 No Content: If the request was an OPTIONS request
+# - 400 Bad Request: If the request did not contain a query parameter `code`
+# - 404 Not Found: The request was not to the root path
+# - 405 Method Not Allowed: OTP code was not retrieved because the request was not a GET/OPTIONS request
+#
+# Example usage:
+#
+# thread = Gem::WebauthnListener.listener_thread("https://rubygems.example", server)
+# thread.join
+# otp = thread[:otp]
+# error = thread[:error]
+#
+
+module Gem::GemcutterUtilities
+ class WebauthnListener
+ attr_reader :host
+
+ def initialize(host)
+ @host = host
+ end
+
+ def self.listener_thread(host, server)
+ Thread.new do
+ thread = Thread.current
+ thread.abort_on_exception = true
+ thread.report_on_exception = false
+ thread[:otp] = new(host).wait_for_otp_code(server)
+ rescue Gem::WebauthnVerificationError => e
+ thread[:error] = e
+ ensure
+ server.close
+ end
+ end
+
+ def wait_for_otp_code(server)
+ loop do
+ socket = server.accept
+ request_line = socket.gets
+
+ method, req_uri, _protocol = request_line.split(" ")
+ req_uri = URI.parse(req_uri)
+
+ responder = SocketResponder.new(socket)
+
+ unless root_path?(req_uri)
+ responder.send(NotFoundResponse.for(host))
+ raise Gem::WebauthnVerificationError, "Page at #{req_uri.path} not found."
+ end
+
+ case method.upcase
+ when "OPTIONS"
+ responder.send(NoContentResponse.for(host))
+ next # will be GET
+ when "GET"
+ if otp = parse_otp_from_uri(req_uri)
+ responder.send(OkResponse.for(host))
+ return otp
+ end
+ responder.send(BadRequestResponse.for(host))
+ raise Gem::WebauthnVerificationError, "Did not receive OTP from #{host}."
+ else
+ responder.send(MethodNotAllowedResponse.for(host))
+ raise Gem::WebauthnVerificationError, "Invalid HTTP method #{method.upcase} received."
+ end
+ end
+ end
+
+ private
+
+ def root_path?(uri)
+ uri.path == "/"
+ end
+
+ def parse_otp_from_uri(uri)
+ require "cgi"
+
+ return if uri.query.nil?
+ CGI.parse(uri.query).dig("code", 0)
+ end
+
+ class SocketResponder
+ def initialize(socket)
+ @socket = socket
+ end
+
+ def send(response)
+ @socket.print response.to_s
+ @socket.close
+ end
+ end
+ end
+end
diff --git a/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb b/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb
new file mode 100644
index 0000000000..7709a8fef3
--- /dev/null
+++ b/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb
@@ -0,0 +1,163 @@
+# frozen_string_literal: true
+
+##
+# The WebauthnListener Response class is used by the WebauthnListener to create
+# responses to be sent to the Gem host. It creates a Net::HTTPResponse instance
+# when initialized and can be converted to the appropriate format to be sent by a socket using `to_s`.
+# Net::HTTPResponse instances cannot be directly sent over a socket.
+#
+# Types of response classes:
+# - OkResponse
+# - NoContentResponse
+# - BadRequestResponse
+# - NotFoundResponse
+# - MethodNotAllowedResponse
+#
+# Example usage:
+#
+# server = TCPServer.new(0)
+# socket = server.accept
+#
+# response = OkResponse.for("https://rubygems.example")
+# socket.print response.to_s
+# socket.close
+#
+
+module Gem::GemcutterUtilities
+ class WebauthnListener
+ class Response
+ attr_reader :http_response
+
+ def self.for(host)
+ new(host)
+ end
+
+ def initialize(host)
+ @host = host
+
+ build_http_response
+ end
+
+ def to_s
+ status_line = "HTTP/#{@http_response.http_version} #{@http_response.code} #{@http_response.message}\r\n"
+ headers = @http_response.to_hash.map {|header, value| "#{header}: #{value.join(", ")}\r\n" }.join + "\r\n"
+ body = @http_response.body ? "#{@http_response.body}\n" : ""
+
+ status_line + headers + body
+ end
+
+ private
+
+ # Must be implemented in subclasses
+ def code
+ raise NotImplementedError
+ end
+
+ def reason_phrase
+ raise NotImplementedError
+ end
+
+ def body; end
+
+ def build_http_response
+ response_class = Net::HTTPResponse::CODE_TO_OBJ[code.to_s]
+ @http_response = response_class.new("1.1", code, reason_phrase)
+ @http_response.instance_variable_set(:@read, true)
+
+ add_connection_header
+ add_access_control_headers
+ add_body
+ end
+
+ def add_connection_header
+ @http_response["connection"] = "close"
+ end
+
+ def add_access_control_headers
+ @http_response["access-control-allow-origin"] = @host
+ @http_response["access-control-allow-methods"] = "POST"
+ @http_response["access-control-allow-headers"] = %w[Content-Type Authorization x-csrf-token]
+ end
+
+ def add_body
+ return unless body
+ @http_response["content-type"] = "text/plain; charset=utf-8"
+ @http_response["content-length"] = body.bytesize
+ @http_response.instance_variable_set(:@body, body)
+ end
+ end
+
+ class OkResponse < Response
+ private
+
+ def code
+ 200
+ end
+
+ def reason_phrase
+ "OK"
+ end
+
+ def body
+ "success"
+ end
+ end
+
+ class NoContentResponse < Response
+ private
+
+ def code
+ 204
+ end
+
+ def reason_phrase
+ "No Content"
+ end
+ end
+
+ class BadRequestResponse < Response
+ private
+
+ def code
+ 400
+ end
+
+ def reason_phrase
+ "Bad Request"
+ end
+
+ def body
+ "missing code parameter"
+ end
+ end
+
+ class NotFoundResponse < Response
+ private
+
+ def code
+ 404
+ end
+
+ def reason_phrase
+ "Not Found"
+ end
+ end
+
+ class MethodNotAllowedResponse < Response
+ private
+
+ def code
+ 405
+ end
+
+ def reason_phrase
+ "Method Not Allowed"
+ end
+
+ def add_access_control_headers
+ super
+ @http_response["allow"] = %w[GET OPTIONS]
+ end
+ end
+ end
+end
diff --git a/lib/rubygems/gemcutter_utilities/webauthn_poller.rb b/lib/rubygems/gemcutter_utilities/webauthn_poller.rb
new file mode 100644
index 0000000000..e7068605a4
--- /dev/null
+++ b/lib/rubygems/gemcutter_utilities/webauthn_poller.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+##
+# The WebauthnPoller class retrieves an OTP after a user successfully WebAuthns. An instance
+# polls the Gem host for the OTP code. The polling request (api/v1/webauthn_verification/<webauthn_token>/status.json)
+# is sent to the Gem host every 5 seconds and will timeout after 5 minutes. If the status field in the json response
+# is "success", the code field will contain the OTP code.
+#
+# Example usage:
+#
+# thread = Gem::WebauthnPoller.poll_thread(
+# {},
+# "RubyGems.org",
+# "https://rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY",
+# { email: "email@example.com", password: "password" }
+# )
+# thread.join
+# otp = thread[:otp]
+# error = thread[:error]
+#
+
+module Gem::GemcutterUtilities
+ class WebauthnPoller
+ include Gem::GemcutterUtilities
+ TIMEOUT_IN_SECONDS = 300
+
+ attr_reader :options, :host
+
+ def initialize(options, host)
+ @options = options
+ @host = host
+ end
+
+ def self.poll_thread(options, host, webauthn_url, credentials)
+ Thread.new do
+ thread = Thread.current
+ thread.abort_on_exception = true
+ thread.report_on_exception = false
+ thread[:otp] = new(options, host).poll_for_otp(webauthn_url, credentials)
+ rescue Gem::WebauthnVerificationError, Timeout::Error => e
+ thread[:error] = e
+ end
+ end
+
+ def poll_for_otp(webauthn_url, credentials)
+ Timeout.timeout(TIMEOUT_IN_SECONDS) do
+ loop do
+ response = webauthn_verification_poll_response(webauthn_url, credentials)
+ raise Gem::WebauthnVerificationError, response.message unless response.is_a?(Net::HTTPSuccess)
+
+ require "json"
+ parsed_response = JSON.parse(response.body)
+ case parsed_response["status"]
+ when "pending"
+ sleep 5
+ when "success"
+ return parsed_response["code"]
+ else
+ raise Gem::WebauthnVerificationError, parsed_response.fetch("message", "Invalid response from server")
+ end
+ end
+ end
+ end
+
+ private
+
+ def webauthn_verification_poll_response(webauthn_url, credentials)
+ webauthn_token = %r{(?<=\/)[^\/]+(?=$)}.match(webauthn_url)[0]
+ rubygems_api_request(:get, "api/v1/webauthn_verification/#{webauthn_token}/status.json") do |request|
+ if credentials.empty?
+ request.add_field "Authorization", api_key
+ else
+ request.basic_auth credentials[:email], credentials[:password]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/rubygems/indexer.rb b/lib/rubygems/indexer.rb
index e595459c87..0935fe8486 100644
--- a/lib/rubygems/indexer.rb
+++ b/lib/rubygems/indexer.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/package'
-require 'tmpdir'
+
+require_relative "../rubygems"
+require_relative "package"
+require "tmpdir"
##
# Top level class for building the gem repository index.
@@ -43,28 +44,28 @@ class Gem::Indexer
# Create an indexer that will index the gems in +directory+.
def initialize(directory, options = {})
- require 'fileutils'
- require 'tmpdir'
- require 'zlib'
+ require "fileutils"
+ require "tmpdir"
+ require "zlib"
options = { :build_modern => true }.merge options
@build_modern = options[:build_modern]
@dest_directory = directory
- @directory = Dir.mktmpdir 'gem_generate_index'
+ @directory = Dir.mktmpdir "gem_generate_index"
marshal_name = "Marshal.#{Gem.marshal_version}"
- @master_index = File.join @directory, 'yaml'
+ @master_index = File.join @directory, "yaml"
@marshal_index = File.join @directory, marshal_name
- @quick_dir = File.join @directory, 'quick'
+ @quick_dir = File.join @directory, "quick"
@quick_marshal_dir = File.join @quick_dir, marshal_name
@quick_marshal_dir_base = File.join "quick", marshal_name # FIX: UGH
- @quick_index = File.join @quick_dir, 'index'
- @latest_index = File.join @quick_dir, 'latest_index'
+ @quick_index = File.join @quick_dir, "index"
+ @latest_index = File.join @quick_dir, "latest_index"
@specs_index = File.join @directory, "specs.#{Gem.marshal_version}"
@latest_specs_index =
@@ -104,7 +105,7 @@ class Gem::Indexer
files = []
- Gem.time 'Generated Marshal quick index gemspecs' do
+ Gem.time "Generated Marshal quick index gemspecs" do
specs.each do |spec|
next if spec.default_gem?
spec_file_name = "#{spec.original_name}.gemspec.rz"
@@ -112,7 +113,7 @@ class Gem::Indexer
marshal_zipped = Gem.deflate Marshal.dump(spec)
- File.open marshal_name, 'wb' do |io|
+ File.open marshal_name, "wb" do |io|
io.write marshal_zipped
end
@@ -136,7 +137,7 @@ class Gem::Indexer
say "Generating #{name} index"
Gem.time "Generated #{name} index" do
- File.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.
@@ -149,7 +150,7 @@ class Gem::Indexer
next
end
- platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
+ platform = Gem::Platform::RUBY if platform.nil? || platform.empty?
[spec.name, spec.version, platform]
end
@@ -169,10 +170,10 @@ class Gem::Indexer
latest_specs =
Gem::Specification._latest_specs specs
- build_modern_index(released.sort, @specs_index, 'specs')
- build_modern_index(latest_specs.sort, @latest_specs_index, 'latest specs')
+ build_modern_index(released.sort, @specs_index, "specs")
+ build_modern_index(latest_specs.sort, @latest_specs_index, "latest specs")
build_modern_index(prerelease.sort, @prerelease_specs_index,
- 'prerelease specs')
+ "prerelease specs")
@files += [@specs_index,
"#{@specs_index}.gz",
@@ -217,7 +218,7 @@ class Gem::Indexer
def compress_indices
say "Compressing indices"
- Gem.time 'Compressed indices' do
+ Gem.time "Compressed indices" do
if @build_modern
gzip @specs_index
gzip @latest_specs_index
@@ -252,7 +253,7 @@ class Gem::Indexer
zipped = Gem.deflate data
- File.open "#{filename}.#{extension}", 'wb' do |io|
+ File.open "#{filename}.#{extension}", "wb" do |io|
io.write zipped
end
end
@@ -296,7 +297,7 @@ class Gem::Indexer
files = @files
files.delete @quick_marshal_dir if files.include? @quick_dir
- if files.include? @quick_marshal_dir and not files.include? @quick_dir
+ if files.include?(@quick_marshal_dir) && !files.include?(@quick_dir)
files.delete @quick_marshal_dir
dst_name = File.join(@dest_directory, @quick_marshal_dir_base)
@@ -308,7 +309,7 @@ class Gem::Indexer
end
files = files.map do |path|
- path.sub(/^#{Regexp.escape @directory}\/?/, '') # HACK?
+ path.sub(/^#{Regexp.escape @directory}\/?/, "") # HACK?
end
files.each do |file|
@@ -358,7 +359,7 @@ class Gem::Indexer
end
if updated_gems.empty?
- say 'No new gems'
+ say "No new gems"
terminate_interaction 0
end
@@ -367,7 +368,7 @@ class Gem::Indexer
files = build_marshal_gemspecs specs
- Gem.time 'Updated indexes' do
+ Gem.time "Updated indexes" do
update_specs_index released, @dest_specs_index, @specs_index
update_specs_index released, @dest_latest_specs_index, @latest_specs_index
update_specs_index(prerelease,
@@ -389,7 +390,7 @@ class Gem::Indexer
files << "#{@prerelease_specs_index}.gz"
files = files.map do |path|
- path.sub(/^#{Regexp.escape @directory}\/?/, '') # HACK?
+ path.sub(/^#{Regexp.escape @directory}\/?/, "") # HACK?
end
files.each do |file|
@@ -397,10 +398,12 @@ class Gem::Indexer
dst_name = File.join @dest_directory, file # REFACTOR: duped above
FileUtils.mv src_name, dst_name, :verbose => verbose,
- :force => true
+ :force => true
File.utime newest_mtime, newest_mtime, dst_name
end
+ ensure
+ FileUtils.rm_rf @directory
end
##
@@ -412,13 +415,13 @@ class Gem::Indexer
index.each do |spec|
platform = spec.original_platform
- platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
+ platform = Gem::Platform::RUBY if platform.nil? || platform.empty?
specs_index << [spec.name, spec.version, platform]
end
specs_index = compact_specs specs_index.uniq.sort
- File.open dest, 'wb' do |io|
+ File.open dest, "wb" do |io|
Marshal.dump specs_index, io
end
end
diff --git a/lib/rubygems/install_default_message.rb b/lib/rubygems/install_default_message.rb
index f68fd2fd04..0640eaaf08 100644
--- a/lib/rubygems/install_default_message.rb
+++ b/lib/rubygems/install_default_message.rb
@@ -1,6 +1,7 @@
# 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..a24e26b918 100644
--- a/lib/rubygems/install_message.rb
+++ b/lib/rubygems/install_message.rb
@@ -1,6 +1,7 @@
# 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 54a3950b64..e125b3b9b3 100644
--- a/lib/rubygems/install_update_options.rb
+++ b/lib/rubygems/install_update_options.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/security_option'
+require_relative "../rubygems"
+require_relative "security_option"
##
# Mixin methods for install and update options for Gem::Commands
@@ -18,86 +19,86 @@ module Gem::InstallUpdateOptions
# Add the install/update options to the option parser.
def add_install_update_options
- add_option(:"Install/Update", '-i', '--install-dir DIR',
- 'Gem repository directory to get installed',
- 'gems') do |value, options|
+ add_option(:"Install/Update", "-i", "--install-dir DIR",
+ "Gem repository directory to get installed",
+ "gems") do |value, options|
options[:install_dir] = File.expand_path(value)
end
- add_option(:"Install/Update", '-n', '--bindir DIR',
- 'Directory where executables will be',
- 'placed when the gem is installed') do |value, options|
+ add_option(:"Install/Update", "-n", "--bindir DIR",
+ "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,
- 'Generate documentation for installed gems',
- 'List the documentation types you wish to',
- 'generate. For example: rdoc,ri') do |value, options|
+ add_option(:"Install/Update", "--document [TYPES]", Array,
+ "Generate documentation for installed gems",
+ "List the documentation types you wish to",
+ "generate. For example: rdoc,ri") do |value, options|
options[:document] = case value
- when nil then %w[ri]
- when false then []
- else value
- end
+ when nil then %w[ri]
+ when false then []
+ else value
+ end
end
- add_option(:"Install/Update", '--build-root DIR',
- 'Temporary installation root. Useful for building',
- 'packages. Do not use this when installing remote gems.') do |value, options|
+ add_option(:"Install/Update", "--build-root DIR",
+ "Temporary installation root. Useful for building",
+ "packages. Do not use this when installing remote gems.") do |value, options|
options[:build_root] = File.expand_path(value)
end
- add_option(:"Install/Update", '--vendor',
- 'Install gem into the vendor directory.',
- 'Only for use by gem repackagers.') do |value, options|
+ add_option(:"Install/Update", "--vendor",
+ "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
options[:install_dir] = Gem.vendor_dir
end
- add_option(:"Install/Update", '-N', '--no-document',
- 'Disable documentation generation') do |value, options|
+ add_option(:"Install/Update", "-N", "--no-document",
+ "Disable documentation generation") do |value, options|
options[:document] = []
end
- add_option(:"Install/Update", '-E', '--[no-]env-shebang',
+ add_option(:"Install/Update", "-E", "--[no-]env-shebang",
"Rewrite the shebang line on installed",
"scripts to use /usr/bin/env") do |value, options|
options[:env_shebang] = value
end
- add_option(:"Install/Update", '-f', '--[no-]force',
- 'Force gem to install, bypassing dependency',
- 'checks') do |value, options|
+ add_option(:"Install/Update", "-f", "--[no-]force",
+ "Force gem to install, bypassing dependency",
+ "checks") do |value, options|
options[:force] = value
end
- add_option(:"Install/Update", '-w', '--[no-]wrappers',
- 'Use bin wrappers for executables',
- 'Not available on dosish platforms') do |value, options|
+ add_option(:"Install/Update", "-w", "--[no-]wrappers",
+ "Use bin wrappers for executables",
+ "Not available on dosish platforms") do |value, options|
options[:wrappers] = value
end
add_security_option
- add_option(:"Install/Update", '--ignore-dependencies',
- 'Do not install any required dependent gems') do |value, options|
+ add_option(:"Install/Update", "--ignore-dependencies",
+ "Do not install any required dependent gems") do |value, options|
options[:ignore_dependencies] = value
end
- 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|
+ 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|
options[:format_executable] = value
end
- add_option(:"Install/Update", '--[no-]user-install',
- 'Install in user\'s home directory instead',
- 'of GEM_HOME.') do |value, options|
+ add_option(:"Install/Update", "--[no-]user-install",
+ "Install in user's home directory instead",
+ "of GEM_HOME.") do |value, options|
options[:user_install] = value
end
@@ -133,9 +134,9 @@ module Gem::InstallUpdateOptions
options[:post_install_message] = value
end
- add_option(:"Install/Update", '-g', '--file [FILE]',
- 'Read from a gem dependencies API file and',
- 'install the listed gems') do |v,o|
+ add_option(:"Install/Update", "-g", "--file [FILE]",
+ "Read from a gem dependencies API file and",
+ "install the listed gems") do |v,o|
v = Gem::GEM_DEP_FILES.find do |file|
File.exist? file
end unless v
@@ -143,39 +144,39 @@ 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
options[:gemdeps] = v
end
- add_option(:"Install/Update", '--without GROUPS', Array,
- 'Omit the named groups (comma separated)',
- 'when installing from a gem dependencies',
- 'file') do |v,o|
+ add_option(:"Install/Update", "--without GROUPS", Array,
+ "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 }
end
- add_option(:"Install/Update", '--default',
- 'Add the gem\'s full specification to',
- 'specifications/default and extract only its bin') do |v,o|
+ add_option(:"Install/Update", "--default",
+ "Add the gem's full specification to",
+ "specifications/default and extract only its bin") do |v,o|
options[:install_as_default] = v
end
- add_option(:"Install/Update", '--explain',
- 'Rather than install the gems, indicate which would',
- 'be installed') do |v,o|
+ add_option(:"Install/Update", "--explain",
+ "Rather than install the gems, indicate which would",
+ "be installed") do |v,o|
options[:explain] = v
end
- add_option(:"Install/Update", '--[no-]lock',
- 'Create a lock file (when used with -g/--file)') do |v,o|
+ add_option(:"Install/Update", "--[no-]lock",
+ "Create a lock file (when used with -g/--file)") do |v,o|
options[:lock] = v
end
- add_option(:"Install/Update", '--[no-]suggestions',
- 'Suggest alternates when gems are not found') do |v,o|
+ add_option(:"Install/Update", "--[no-]suggestions",
+ "Suggest alternates when gems are not found") do |v,o|
options[:suggest_alternate] = v
end
end
@@ -193,7 +194,7 @@ module Gem::InstallUpdateOptions
# Default description for the gem install and update commands.
def install_update_defaults_str
- '--document=ri'
+ "--document=ri"
end
end
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 7cc9bc6a0b..1b152aaf1f 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/command'
-require 'rubygems/installer_uninstaller_utils'
-require 'rubygems/exceptions'
-require 'rubygems/deprecate'
-require 'rubygems/package'
-require 'rubygems/ext'
-require 'rubygems/user_interaction'
+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.
@@ -68,19 +68,28 @@ class Gem::Installer
@path_warning = false
- @install_lock = Thread::Mutex.new
-
class << self
- ##
- # True if we've warned about PATH not including Gem.bindir
+ #
+ # 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.
- attr_accessor :path_warning
+ def inherited(klass)
+ if klass.name == "Bundler::RubyGemsGemInstaller"
+ require "rubygems/command"
+ end
+
+ 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.
@@ -117,14 +126,14 @@ class Gem::Installer
@spec = spec
end
- def extract_files(destination_dir, pattern = '*')
+ def extract_files(destination_dir, pattern = "*")
FileUtils.mkdir_p destination_dir
spec.files.each do |file|
file = File.join destination_dir, file
next if File.exist? file
FileUtils.mkdir_p File.dirname(file)
- File.open file, 'w' do |fp|
+ File.open file, "w" do |fp|
fp.puts "# #{file}"
end
end
@@ -169,7 +178,7 @@ class Gem::Installer
# :post_install_message:: Print gem post install message if true
def initialize(package, options={})
- require 'fileutils'
+ require "fileutils"
@options = options
@package = package
@@ -193,8 +202,8 @@ class Gem::Installer
#
# If +@force+ is set +filename+ is overwritten.
#
- # If +filename+ exists and is a RubyGems wrapper for different gem the user
- # is consulted.
+ # If +filename+ exists and it is a RubyGems wrapper for a different gem, then
+ # the user is consulted.
#
# If +filename+ exists and +@bin_dir+ is Gem.default_bindir (/usr/local) the
# user is consulted.
@@ -211,13 +220,23 @@ class Gem::Installer
ruby_executable = false
existing = nil
- File.open generated_bin, 'rb' do |io|
- next unless io.gets =~ /^#!/ # shebang
+ File.open generated_bin, "rb" do |io|
+ line = io.gets
+ shebang = /^#!.*ruby/
+
+ if load_relative_enabled?
+ until line.nil? || line =~ shebang do
+ line = io.gets
+ end
+ end
+
+ next unless line =~ shebang
+
io.gets # blankline
# TODO detect a specially formatted comment instead of trying
- # to run a regexp against Ruby code.
- next unless io.gets =~ /This file was generated by RubyGems/
+ # to find a string inside Ruby code.
+ next unless io.gets.to_s.include?("This file was generated by RubyGems")
ruby_executable = true
existing = io.read.slice(%r{
@@ -233,12 +252,12 @@ class Gem::Installer
return if spec.name == existing
# somebody has written to RubyGems' directory, overwrite, too bad
- return if Gem.default_bindir != @bin_dir and not ruby_executable
+ return if Gem.default_bindir != @bin_dir && !ruby_executable
question = "#{spec.name}'s executable \"#{filename}\" conflicts with ".dup
if ruby_executable
- question << (existing || 'an unknown executable')
+ question << (existing || "an unknown executable")
return if ask_yes_no "#{question}\nOverwrite the executable?", false
@@ -267,8 +286,6 @@ class Gem::Installer
def spec
@package.spec
- rescue Gem::Package::Error => e
- raise Gem::InstallError, "invalid gem: #{e.message}"
end
##
@@ -285,8 +302,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
@@ -326,7 +341,9 @@ 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.add_spec(spec)
+
+ load_plugin
run_post_install_hooks
@@ -374,7 +391,7 @@ class Gem::Installer
# we'll be installing into.
def installed_specs
- @specs ||= begin
+ @installed_specs ||= begin
specs = []
Gem::Util.glob_files_in_dir("*.gemspec", File.join(gem_home, "specifications")).each do |path|
@@ -404,10 +421,10 @@ class Gem::Installer
# True if the gems in the system satisfy +dependency+.
def installation_satisfies_dependency?(dependency)
- return true if @options[:development] and dependency.type == :development
+ return true if @options[:development] && dependency.type == :development
return true if installed_specs.detect {|s| dependency.matches_spec? s }
return false if @only_install_dir
- not dependency.matching_specs.empty?
+ !dependency.matching_specs.empty?
end
##
@@ -440,13 +457,9 @@ class Gem::Installer
# specifications directory.
def write_spec
- File.open spec_file, 'w' do |file|
- spec.installed_by_version = Gem.rubygems_version
+ spec.installed_by_version = Gem.rubygems_version
- file.puts spec.to_ruby_for_cache
-
- file.fsync rescue nil # for filesystems without fsync(2)
- end
+ Gem.write_binary(spec_file, spec.to_ruby_for_cache)
end
##
@@ -454,9 +467,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
##
@@ -466,7 +477,7 @@ class Gem::Installer
if Gem.win_platform?
script_name = formatted_program_filename(filename) + ".bat"
script_path = File.join bindir, File.basename(script_name)
- File.open script_path, 'w' do |file|
+ File.open script_path, "w" do |file|
file.puts windows_stub_script(bindir, filename)
end
@@ -475,28 +486,20 @@ class Gem::Installer
end
def generate_bin # :nodoc:
- return if spec.executables.nil? or spec.executables.empty?
+ return if spec.executables.nil? || spec.executables.empty?
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
- 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
+ next unless File.exist? bin_path
mode = File.stat(bin_path).mode
dir_mode = options[:prog_mode] || (mode | 0111)
unless dir_mode == mode
- require 'fileutils'
+ require "fileutils"
FileUtils.chmod dir_mode, bin_path
end
@@ -511,7 +514,7 @@ class Gem::Installer
end
def generate_plugins # :nodoc:
- latest = Gem::Installer.install_lock.synchronize { Gem::Specification.latest_spec_for(spec.name) }
+ latest = Gem::Specification.latest_spec_for(spec.name)
return if latest && latest.version > spec.version
ensure_writable_dir @plugins_dir
@@ -533,10 +536,10 @@ class Gem::Installer
def generate_bin_script(filename, bindir)
bin_script_path = File.join bindir, formatted_program_filename(filename)
- require 'fileutils'
+ require "fileutils"
FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
- File.open bin_script_path, 'wb', 0755 do |file|
+ File.open bin_script_path, "wb", 0755 do |file|
file.print app_script_text(filename)
file.chmod(options[:prog_mode] || 0755)
end
@@ -557,7 +560,7 @@ class Gem::Installer
if File.exist? dst
if File.symlink? dst
link = File.readlink(dst).split File::SEPARATOR
- cur_version = Gem::Version.create(link[-3].sub(/^.*-/, ''))
+ cur_version = Gem::Version.create(link[-3].sub(/^.*-/, ""))
return if spec.version < cur_version
end
File.unlink dst
@@ -585,7 +588,6 @@ 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 } || ""
@@ -598,7 +600,7 @@ class Gem::Installer
if which = Gem.configuration[:custom_shebang]
# replace bin_file_name with "ruby" to avoid endless loops
- which = which.gsub(/ #{bin_file_name}$/," #{RbConfig::CONFIG['ruby_install_name']}")
+ which = which.gsub(/ #{bin_file_name}$/," #{ruby_install_name}")
which = which.gsub(/\$(\w+)/) do
case $1
@@ -614,14 +616,12 @@ class Gem::Installer
end
"#!#{which}"
- elsif not ruby_name
- "#!#{Gem.ruby}#{opts}"
- elsif opts
- "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
- else
+ elsif @env_shebang
# Create a plain shebang line.
@env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
- "#!#{@env_path} #{ruby_name}"
+ "#!#{@env_path} #{ruby_install_name}"
+ else
+ "#{bash_prolog_script}#!#{Gem.ruby}#{opts}"
end
end
@@ -652,9 +652,9 @@ class Gem::Installer
def process_options # :nodoc:
@options = {
- :bin_dir => nil,
- :env_shebang => false,
- :force => false,
+ :bin_dir => nil,
+ :env_shebang => false,
+ :force => false,
:only_install_dir => false,
:post_install_message => true,
}.merge options
@@ -676,12 +676,12 @@ 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?
- @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]:/, ''))
+ @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
@@ -692,7 +692,7 @@ class Gem::Installer
user_bin_dir = @bin_dir || Gem.bindir(gem_home)
user_bin_dir = user_bin_dir.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
- path = ENV['PATH']
+ path = ENV["PATH"]
path = path.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
if Gem.win_platform?
@@ -703,7 +703,7 @@ class Gem::Installer
path = path.split(File::PATH_SEPARATOR)
unless path.include? user_bin_dir
- unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV['HOME'], '~'))
+ unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV["HOME"], "~"))
alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
self.class.path_warning = true
end
@@ -720,11 +720,11 @@ class Gem::Installer
raise Gem::InstallError, "#{spec} has an invalid name"
end
- if spec.raw_require_paths.any?{|path| path =~ /\R/ }
+ if spec.raw_require_paths.any? {|path| path =~ /\R/ }
raise Gem::InstallError, "#{spec} has an invalid require_paths"
end
- if spec.extensions.any?{|ext| ext =~ /\R/ }
+ if spec.extensions.any? {|ext| ext =~ /\R/ }
raise Gem::InstallError, "#{spec} has an invalid extensions"
end
@@ -761,14 +761,14 @@ class Gem::Installer
#
require 'rubygems'
-
+#{gemdeps_load(spec.name)}
version = "#{Gem::Requirement.default_prerelease}"
str = ARGV.first
if str
str = str.b[/\\A_(.*)_\\z/, 1]
if str and Gem::Version.correct?(str)
- version = str
+ #{explicit_version_requirement(spec.name)}
ARGV.shift
end
end
@@ -782,11 +782,29 @@ end
TEXT
end
+ def gemdeps_load(name)
+ return "" if name == "bundler"
+
+ <<-TEXT
+
+Gem.use_gemdeps
+TEXT
+ end
+
+ def explicit_version_requirement(name)
+ code = "version = str"
+ return code unless name == "bundler"
+
+ code += <<-TEXT
+
+ ENV['BUNDLER_VERSION'] = str
+TEXT
+ end
+
##
# return the stub script text used to launch the true Ruby script
def windows_stub_script(bindir, bin_file_name)
- rb_config = RbConfig::CONFIG
rb_topdir = RbConfig::TOPDIR || File.dirname(rb_config["bindir"])
# get ruby executable file name from RbConfig
@@ -801,7 +819,7 @@ TEXT
TEXT
elsif bindir.downcase.start_with? rb_topdir.downcase
# stub within ruby folder, but not standard bin. Portable
- require 'pathname'
+ require "pathname"
from = Pathname.new bindir
to = Pathname.new "#{rb_topdir}/bin"
rel = to.relative_path_from from
@@ -823,7 +841,7 @@ TEXT
# configure scripts and rakefiles or mkrf_conf files.
def build_extensions
- builder = Gem::Ext::Builder.new spec, @build_args
+ builder = Gem::Ext::Builder.new spec, build_args
builder.build_extensions
end
@@ -910,17 +928,17 @@ 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'
+ build_info_dir = File.join gem_home, "build_info"
dir_mode = options[:dir_mode]
FileUtils.mkdir_p build_info_dir, :mode => dir_mode && 0755
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|
+ File.open build_info_file, "w" do |io|
+ build_args.each do |arg|
io.puts arg
end
end
@@ -932,7 +950,7 @@ TEXT
# Writes the .gem file to the cache directory
def write_cache_file
- cache_file = File.join gem_home, 'cache', spec.file_name
+ cache_file = File.join gem_home, "cache", spec.file_name
@package.copy_to cache_file
end
@@ -945,4 +963,59 @@ TEXT
raise Gem::FilePermissionError.new(dir) unless File.writable? dir
end
+
+ private
+
+ def build_args
+ @build_args ||= begin
+ require_relative "command"
+ Gem::Command.build_args
+ end
+ end
+
+ def rb_config
+ RbConfig::CONFIG
+ end
+
+ def ruby_install_name
+ rb_config["ruby_install_name"]
+ end
+
+ def load_relative_enabled?
+ rb_config["LIBRUBY_RELATIVE"] == "yes"
+ end
+
+ def bash_prolog_script
+ if load_relative_enabled?
+ script = +<<~EOS
+ bindir="${0%/*}"
+ EOS
+
+ script << %Q(exec "$bindir/#{ruby_install_name}" "-x" "$0" "$@"\n)
+
+ <<~EOS
+ #!/bin/sh
+ # -*- ruby -*-
+ _=_\\
+ =begin
+ #{script.chomp}
+ =end
+ EOS
+ else
+ ""
+ end
+ end
+
+ def load_plugin
+ specs = Gem::Specification.find_all_by_name(spec.name)
+ # If old version already exists, this plugin isn't loaded
+ # immediately. It's for avoiding a case that multiple versions
+ # are loaded at the same time.
+ return unless specs.size == 1
+
+ plugin_files = spec.plugins.map do |plugin|
+ File.join(@plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}")
+ end
+ Gem.load_plugin_files(plugin_files)
+ end
end
diff --git a/lib/rubygems/installer_uninstaller_utils.rb b/lib/rubygems/installer_uninstaller_utils.rb
index 2c8b7c635e..d97b4e29b1 100644
--- a/lib/rubygems/installer_uninstaller_utils.rb
+++ b/lib/rubygems/installer_uninstaller_utils.rb
@@ -9,12 +9,12 @@ module Gem::InstallerUninstallerUtils
plugins = spec.plugins
return if plugins.empty?
- require 'pathname'
+ 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.open plugin_script_path, "wb" do |file|
file.puts "require_relative '#{Pathname.new(plugin).relative_path_from(Pathname.new(plugins_dir))}'"
end
diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb
index 2d0509eb03..3d970ef225 100644
--- a/lib/rubygems/local_remote_options.rb
+++ b/lib/rubygems/local_remote_options.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'uri'
-require 'rubygems'
+require "uri"
+require_relative "../rubygems"
##
# Mixin methods for local and remote Gem::Command options.
@@ -14,19 +15,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
@@ -38,18 +39,18 @@ module Gem::LocalRemoteOptions
# Add local/remote options to the command line parser.
def add_local_remote_options
- add_option(:"Local/Remote", '-l', '--local',
- 'Restrict operations to the LOCAL domain') do |value, options|
+ add_option(:"Local/Remote", "-l", "--local",
+ "Restrict operations to the LOCAL domain") do |value, options|
options[:domain] = :local
end
- add_option(:"Local/Remote", '-r', '--remote',
- 'Restrict operations to the REMOTE domain') do |value, options|
+ add_option(:"Local/Remote", "-r", "--remote",
+ "Restrict operations to the REMOTE domain") do |value, options|
options[:domain] = :remote
end
- add_option(:"Local/Remote", '-b', '--both',
- 'Allow LOCAL and REMOTE operations') do |value, options|
+ add_option(:"Local/Remote", "-b", "--both",
+ "Allow LOCAL and REMOTE operations") do |value, options|
options[:domain] = :both
end
@@ -64,7 +65,7 @@ module Gem::LocalRemoteOptions
# Add the --bulk-threshold option
def add_bulk_threshold_option
- add_option(:"Local/Remote", '-B', '--bulk-threshold COUNT',
+ add_option(:"Local/Remote", "-B", "--bulk-threshold COUNT",
"Threshold for switching to bulk",
"synchronization (default #{Gem.configuration.bulk_threshold})") do
|value, options|
@@ -76,9 +77,8 @@ module Gem::LocalRemoteOptions
# Add the --clear-sources option
def add_clear_sources_option
- add_option(:"Local/Remote", '--clear-sources',
- 'Clear the gem sources') do |value, options|
-
+ add_option(:"Local/Remote", "--clear-sources",
+ "Clear the gem sources") do |value, options|
Gem.sources = nil
options[:sources_cleared] = true
end
@@ -90,8 +90,8 @@ module Gem::LocalRemoteOptions
def add_proxy_option
accept_uri_http
- add_option(:"Local/Remote", '-p', '--[no-]http-proxy [URL]', URI::HTTP,
- 'Use HTTP proxy for remote operations') do |value, options|
+ add_option(:"Local/Remote", "-p", "--[no-]http-proxy [URL]", URI::HTTP,
+ "Use HTTP proxy for remote operations") do |value, options|
options[:http_proxy] = (value == false) ? :no_proxy : value
Gem.configuration[:http_proxy] = options[:http_proxy]
end
@@ -103,10 +103,9 @@ module Gem::LocalRemoteOptions
def add_source_option
accept_uri_http
- add_option(:"Local/Remote", '-s', '--source URL', URI::HTTP,
- 'Append URL to list of remote gem sources') do |source, options|
-
- source << '/' if source !~ /\/\z/
+ add_option(:"Local/Remote", "-s", "--source URL", URI::HTTP,
+ "Append URL to list of remote gem sources") do |source, options|
+ source << "/" if source !~ /\/\z/
if options.delete :sources_cleared
Gem.sources = [source]
@@ -120,8 +119,8 @@ module Gem::LocalRemoteOptions
# Add the --update-sources option
def add_update_sources_option
- add_option(:Deprecated, '-u', '--[no-]update-sources',
- 'Update local source cache') do |value, options|
+ add_option(:Deprecated, "-u", "--[no-]update-sources",
+ "Update local source cache") do |value, options|
Gem.configuration.update_sources = value
end
end
diff --git a/lib/rubygems/mock_gem_ui.rb b/lib/rubygems/mock_gem_ui.rb
index ec244fb7c6..2dfdc6d523 100644
--- a/lib/rubygems/mock_gem_ui.rb
+++ b/lib/rubygems/mock_gem_ui.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/user_interaction'
+
+require_relative "user_interaction"
##
# This Gem::StreamUI subclass records input and output to StringIO for
@@ -40,7 +41,7 @@ class Gem::MockGemUi < Gem::StreamUI
end
def initialize(input = "")
- require 'stringio'
+ require "stringio"
ins = StringIO.new input
outs = StringIO.new
errs = StringIO.new
diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb
index 3d0afa3094..c26d0765e6 100644
--- a/lib/rubygems/name_tuple.rb
+++ b/lib/rubygems/name_tuple.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
#
# Represents a gem of name +name+ at +version+ of +platform+. These
@@ -10,7 +11,7 @@ class Gem::NameTuple
@version = version
unless platform.kind_of? Gem::Platform
- platform = "ruby" if !platform or platform.empty?
+ platform = "ruby" if !platform || platform.empty?
end
@platform = platform
@@ -48,7 +49,7 @@ class Gem::NameTuple
def full_name
case @platform
- when nil, 'ruby', ''
+ when nil, "ruby", ""
"#{@name}-#{@version}"
else
"#{@name}-#{@version}-#{@platform}"
@@ -89,9 +90,8 @@ class Gem::NameTuple
alias to_s inspect # :nodoc:
def <=>(other)
- [@name, @version, @platform == Gem::Platform::RUBY ? -1 : 1] <=>
- [other.name, other.version,
- other.platform == Gem::Platform::RUBY ? -1 : 1]
+ [@name, @version, Gem::Platform.sort_priority(@platform)] <=>
+ [other.name, other.version, Gem::Platform.sort_priority(other.platform)]
end
include Comparable
@@ -103,8 +103,8 @@ class Gem::NameTuple
def ==(other)
case other
when self.class
- @name == other.name and
- @version == other.version and
+ @name == other.name &&
+ @version == other.version &&
@platform == other.platform
when Array
to_a == other
diff --git a/lib/rubygems/optparse.rb b/lib/rubygems/optparse.rb
new file mode 100644
index 0000000000..6ed718423c
--- /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/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..1e50bda769
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse.rb
@@ -0,0 +1,2308 @@
+# 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}[optparse/tutorial.rdoc].
+#
+# === 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}[optparse/tutorial.rdoc],
+# should be enough to learn how to use this class.
+# If you have any questions, file a ticket at http://bugs.ruby-lang.org.
+#
+class Gem::OptionParser
+ Gem::OptionParser::Version = "0.3.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
+
+ def pretty_print_contents(q) # :nodoc:
+ if @block
+ q.text ":" + @block.source_location.join(":") + ":"
+ first = false
+ else
+ first = true
+ end
+ [@short, @long].each do |list|
+ list.each do |opt|
+ if first
+ q.text ":"
+ first = false
+ end
+ q.breakable
+ q.text opt
+ end
+ end
+ end
+
+ def pretty_print(q) # :nodoc:
+ q.object_group(self) {pretty_print_contents(q)}
+ 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
+
+ def pretty_head # :nodoc:
+ "NoArgument"
+ 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
+
+ def pretty_head # :nodoc:
+ "Required"
+ 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
+
+ def pretty_head # :nodoc:
+ "Optional"
+ end
+ end
+
+ #
+ # Switch that takes an argument, which does not begin with '-' or is '-'.
+ #
+ class PlacedArgument < self
+
+ #
+ # Returns nil if argument is not present or begins with '-' and is not '-'.
+ #
+ 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
+
+ def pretty_head # :nodoc:
+ "Placed"
+ 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
+
+ def pretty_print(q) # :nodoc:
+ q.group(1, "(", ")") do
+ @list.each do |sw|
+ next unless Switch === sw
+ q.group(1, "(" + sw.pretty_head, ")") do
+ sw.pretty_print_contents(q)
+ end
+ end
+ end
+ 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
+ @raise_unknown = true
+ 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
+
+ # Whether to raise at unknown option.
+ attr_accessor :raise_unknown
+
+ #
+ # 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
+
+ def pretty_print(q) # :nodoc:
+ q.object_group(self) do
+ first = true
+ if @stack.size > 2
+ @stack.each_with_index do |s, i|
+ next if i < 2
+ next if s.list.empty?
+ if first
+ first = false
+ q.text ":"
+ end
+ q.breakable
+ s.pretty_print(q)
+ end
+ end
+ end
+ end
+
+ def inspect # :nodoc:
+ require 'pp'
+ pretty_print_inspect
+ end
+
+ #
+ # 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) if o && !o.empty?
+ 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)
+ throw :terminate, arg unless raise_unknown
+ raise InvalidOption, arg
+ end
+ rescue ParseError
+ throw :terminate, arg unless raise_unknown
+ 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
+ throw :terminate, arg unless raise_unknown
+ 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)
+ DidYouMean.formatter.message_for(all_candidates & checker.correct(opt))
+ 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.
+ #
+ # The optional +into+ keyword argument works exactly like that accepted in
+ # method #parse.
+ #
+ def load(filename = nil, into: nil)
+ unless filename
+ basename = File.basename($0, '.*')
+ return true if load(File.expand_path(basename, '~/.options'), into: into) 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), into: into) rescue nil
+ }
+ end
+ begin
+ parse(*File.readlines(filename, chomp: true), into: into)
+ 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..e84d01bf91
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/ac.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: false
+require_relative '../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..d9a9f4f48a
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/date.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: false
+require_relative '../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..6987a5ed62
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/kwargs.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require_relative '../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..d47ad60255
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/shellwords.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: false
+# -*- ruby -*-
+
+require 'shellwords'
+require_relative '../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..c59e1e4ced
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/time.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: false
+require_relative '../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..664d7f2af4
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/uri.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: false
+# -*- ruby -*-
+
+require_relative '../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 a4ae3e9ea5..f28d521bdf 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -1,9 +1,15 @@
# frozen_string_literal: true
+
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
# See LICENSE.txt for additional licensing information.
#++
-#
+
+require_relative "../rubygems"
+require_relative "security"
+require_relative "user_interaction"
+
+##
# Example using a Gem::Package
#
# Builds a .gem file given a Gem::Specification. A .gem file is a tarball
@@ -41,10 +47,6 @@
# #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"
-require 'rubygems/security'
-require 'rubygems/user_interaction'
-
class Gem::Package
include Gem::UserInteraction
@@ -67,7 +69,14 @@ class Gem::Package
class PathError < Error
def initialize(destination, destination_dir)
super "installing into parent path %s of %s is not allowed" %
- [destination, destination_dir]
+ [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
@@ -139,18 +148,18 @@ class Gem::Package
def self.new(gem, security_policy = nil)
gem = if gem.is_a?(Gem::Package::Source)
- gem
- elsif gem.respond_to? :read
- Gem::Package::IOSource.new gem
- else
- Gem::Package::FileSource.new gem
- end
+ gem
+ elsif gem.respond_to? :read
+ Gem::Package::IOSource.new gem
+ else
+ Gem::Package::FileSource.new gem
+ end
return super unless Gem::Package == self
return super unless gem.present?
return super unless gem.start
- return super unless gem.start.include? 'MD5SUM ='
+ return super unless gem.start.include? "MD5SUM ="
Gem::Package::Old.new gem
end
@@ -170,9 +179,9 @@ class Gem::Package
tar = Gem::Package::TarReader.new io
tar.each_entry do |entry|
case entry.full_name
- when 'metadata' then
+ when "metadata" then
metadata = entry.read
- when 'metadata.gz' then
+ when "metadata.gz" then
metadata = Gem::Util.gunzip entry.read
end
end
@@ -185,7 +194,7 @@ class Gem::Package
# Creates a new package that will read or write to the file +gem+.
def initialize(gem, security_policy) # :notnew:
- require 'zlib'
+ require "zlib"
@gem = gem
@@ -221,9 +230,9 @@ class Gem::Package
end
end
- tar.add_file_signed 'checksums.yaml.gz', 0444, @signer do |io|
+ tar.add_file_signed "checksums.yaml.gz", 0444, @signer do |io|
gzip_to io do |gz_io|
- YAML.dump checksums_by_algorithm, gz_io
+ Psych.dump checksums_by_algorithm, gz_io
end
end
end
@@ -233,7 +242,7 @@ class Gem::Package
# and adds this file to the +tar+.
def add_contents(tar) # :nodoc:
- digests = tar.add_file_signed 'data.tar.gz', 0444, @signer do |io|
+ digests = tar.add_file_signed "data.tar.gz", 0444, @signer do |io|
gzip_to io do |gz_io|
Gem::Package::TarWriter.new gz_io do |data_tar|
add_files data_tar
@@ -241,7 +250,7 @@ class Gem::Package
end
end
- @checksums['data.tar.gz'] = digests
+ @checksums["data.tar.gz"] = digests
end
##
@@ -258,7 +267,7 @@ class Gem::Package
next unless stat.file?
tar.add_file_simple file, stat.mode, stat.size do |dst_io|
- File.open file, 'rb' do |src_io|
+ File.open file, "rb" do |src_io|
dst_io.write src_io.read 16384 until src_io.eof?
end
end
@@ -269,13 +278,13 @@ class Gem::Package
# Adds the package's Gem::Specification to the +tar+ file
def add_metadata(tar) # :nodoc:
- digests = tar.add_file_signed 'metadata.gz', 0444, @signer do |io|
+ digests = tar.add_file_signed "metadata.gz", 0444, @signer do |io|
gzip_to io do |gz_io|
gz_io.write @spec.to_yaml
end
end
- @checksums['metadata.gz'] = digests
+ @checksums["metadata.gz"] = digests
end
##
@@ -327,7 +336,7 @@ EOM
gem_tar = Gem::Package::TarReader.new io
gem_tar.each do |entry|
- next unless entry.full_name == 'data.tar.gz'
+ next unless entry.full_name == "data.tar.gz"
open_tar_gz entry do |pkg_tar|
pkg_tar.each do |contents_entry|
@@ -346,10 +355,10 @@ EOM
def digest(entry) # :nodoc:
algorithms = if @checksums
- @checksums.keys
- else
- [Gem::Security::DIGEST_NAME].compact
- end
+ @checksums.keys
+ else
+ [Gem::Security::DIGEST_NAME].compact
+ end
algorithms.each do |algorithm|
digester = Gem::Security.create_digest(algorithm)
@@ -379,7 +388,7 @@ EOM
reader = Gem::Package::TarReader.new io
reader.each do |entry|
- next unless entry.full_name == 'data.tar.gz'
+ next unless entry.full_name == "data.tar.gz"
extract_tar_gz entry, destination_dir, pattern
@@ -400,12 +409,25 @@ EOM
# extracted.
def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
- directories = [] if dir_mode
+ directories = []
+ symlinks = []
+
open_tar_gz io do |tar|
tar.each do |entry|
- next unless File.fnmatch pattern, entry.full_name, File::FNM_DOTMATCH
+ full_name = entry.full_name
+ next unless File.fnmatch pattern, full_name, File::FNM_DOTMATCH
+
+ destination = install_location 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))
- destination = install_location entry.full_name, destination_dir
+ raise Gem::Package::SymlinkError.new(full_name, real_destination, destination_dir) unless
+ normalize_path(real_destination).start_with? normalize_path(destination_dir + "/")
+
+ symlinks << [full_name, link_target, destination, real_destination]
+ end
FileUtils.rm_rf destination
@@ -417,29 +439,41 @@ 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
+ if entry.file?
+ File.open(destination, "wb") {|out| out.write entry.read }
FileUtils.chmod file_mode(entry.header.mode), destination
- end if entry.file?
-
- File.symlink(entry.header.linkname, destination) if entry.symlink?
+ end
verbose destination
end
end
- if directories
- directories.uniq!
+ symlinks.each do |name, target, destination, real_destination|
+ if File.exist?(real_destination)
+ File.symlink(target, destination)
+ else
+ alert_warning "#{@spec.full_name} ships with a dangling symlink named #{name} pointing to missing #{target} file. Ignoring"
+ end
+ end
+
+ if dir_mode
File.chmod(dir_mode, *directories)
end
end
def file_mode(mode) # :nodoc:
- ((mode & 0111).zero? ? data_mode : prog_mode) || mode
+ ((mode & 0111).zero? ? data_mode : prog_mode) ||
+ # If we're not using one of the default modes, then we're going to fall
+ # back to the mode from the tarball. In this case we need to mask it down
+ # to fit into 2^16 bits (the maximum value for a mode in CRuby since it
+ # gets put into an unsigned short).
+ (mode & ((1 << 16) - 1))
end
##
@@ -464,23 +498,13 @@ EOM
def install_location(filename, destination_dir) # :nodoc:
raise Gem::Package::PathError.new(filename, destination_dir) if
- filename.start_with? '/'
+ 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
@@ -494,30 +518,14 @@ 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+
def load_spec(entry) # :nodoc:
case entry.full_name
- when 'metadata' then
+ when "metadata" then
@spec = Gem::Specification.from_yaml entry.read
- when 'metadata.gz' then
+ when "metadata.gz" then
Zlib::GzipReader.wrap(entry, external_encoding: Encoding::UTF_8) do |gzio|
@spec = Gem::Specification.from_yaml gzio.read
end
@@ -541,7 +549,7 @@ EOM
def read_checksums(gem)
Gem.load_yaml
- @checksums = gem.seek 'checksums.yaml.gz' do |entry|
+ @checksums = gem.seek "checksums.yaml.gz" do |entry|
Zlib::GzipReader.wrap entry do |gz_io|
Gem::SafeYAML.safe_load gz_io.read
end
@@ -553,7 +561,7 @@ EOM
# certificate and key are not present only checksum generation is set up.
def setup_signer(signer_options: {})
- passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
+ passphrase = ENV["GEM_PRIVATE_KEY_PASSPHRASE"]
if @spec.signing_key
@signer =
Gem::Security::Signer.new(
@@ -609,8 +617,7 @@ EOM
verify_checksums @digests, @checksums
- @security_policy.verify_signatures @spec, @digests, @signatures if
- @security_policy
+ @security_policy&.verify_signatures @spec, @digests, @signatures
true
rescue Gem::Security::Exception
@@ -660,7 +667,7 @@ EOM
case file_name
when "metadata", "metadata.gz" then
load_spec entry
- when 'data.tar.gz' then
+ when "data.tar.gz" then
verify_gz entry
end
rescue
@@ -677,15 +684,15 @@ EOM
end
unless @spec
- raise Gem::Package::FormatError.new 'package metadata is missing', @gem
+ raise Gem::Package::FormatError.new "package metadata is missing", @gem
end
- unless @files.include? 'data.tar.gz'
+ unless @files.include? "data.tar.gz"
raise Gem::Package::FormatError.new \
- 'package content (data.tar.gz) is missing', @gem
+ "package content (data.tar.gz) is missing", @gem
end
- if duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first) and duplicates.any?
+ if (duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first)) && duplicates.any?
raise Gem::Security::Exception, "duplicate files in the package: (#{duplicates.map(&:inspect).join(', ')})"
end
end
@@ -702,12 +709,12 @@ EOM
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 4736f76d93..1572cb9f2c 100644
--- a/lib/rubygems/package/digest_io.rb
+++ b/lib/rubygems/package/digest_io.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# IO wrapper that creates digests of contents written to the IO it wraps.
diff --git a/lib/rubygems/package/file_source.rb b/lib/rubygems/package/file_source.rb
index 114a950c77..d9717e0f2a 100644
--- a/lib/rubygems/package/file_source.rb
+++ b/lib/rubygems/package/file_source.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The primary source of gems is a file on disk, including all usages
# internal to rubygems.
@@ -22,10 +23,10 @@ class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all
end
def with_write_io(&block)
- File.open path, 'wb', &block
+ File.open path, "wb", &block
end
def with_read_io(&block)
- File.open path, 'rb', &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 03d7714524..227835dfce 100644
--- a/lib/rubygems/package/io_source.rb
+++ b/lib/rubygems/package/io_source.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Supports reading and writing gems from/to a generic IO object. This is
# useful for other applications built on top of rubygems, such as
diff --git a/lib/rubygems/package/old.rb b/lib/rubygems/package/old.rb
index 25317ef23f..bf0ed61b0a 100644
--- a/lib/rubygems/package/old.rb
+++ b/lib/rubygems/package/old.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -19,8 +20,8 @@ class Gem::Package::Old < Gem::Package
# cannot be written.
def initialize(gem, security_policy)
- require 'fileutils'
- require 'zlib'
+ require "fileutils"
+ require "zlib"
Gem.load_yaml
@contents = nil
@@ -41,7 +42,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
@@ -59,7 +60,7 @@ class Gem::Package::Old < Gem::Package
raise Gem::Exception, errstr unless header
header.each do |entry|
- full_name = entry['path']
+ full_name = entry["path"]
destination = install_location full_name, destination_dir
@@ -73,13 +74,13 @@ class Gem::Package::Old < Gem::Package
file_data = Zlib::Inflate.inflate file_data
raise Gem::Package::FormatError, "#{full_name} in #{@gem} is corrupt" if
- file_data.length != entry['size'].to_i
+ file_data.length != entry["size"].to_i
FileUtils.rm_rf destination
FileUtils.mkdir_p File.dirname(destination), :mode => dir_mode && 0755
- File.open destination, 'wb', file_mode(entry['mode']) do |out|
+ File.open destination, "wb", file_mode(entry["mode"]) do |out|
out.write file_data
end
@@ -119,7 +120,7 @@ class Gem::Package::Old < Gem::Package
loop do
line = io.gets
- return if line.chomp == '__END__'
+ return if line.chomp == "__END__"
break unless line
end
@@ -145,7 +146,7 @@ class Gem::Package::Old < Gem::Package
begin
@spec = Gem::Specification.from_yaml yaml
- rescue YAML::SyntaxError
+ rescue Psych::SyntaxError
raise Gem::Exception, "Failed to parse gem specification out of gem file"
end
rescue ArgumentError
@@ -160,7 +161,7 @@ class Gem::Package::Old < Gem::Package
return true unless @security_policy
raise Gem::Security::Exception,
- 'old format gems do not contain signatures and cannot be verified' if
+ "old format gems do not contain signatures and cannot be verified" if
@security_policy.verify_data
true
diff --git a/lib/rubygems/package/source.rb b/lib/rubygems/package/source.rb
index 69701e55e9..8c44f8c305 100644
--- a/lib/rubygems/package/source.rb
+++ b/lib/rubygems/package/source.rb
@@ -1,3 +1,4 @@
# frozen_string_literal: true
+
class Gem::Package::Source # :nodoc:
end
diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb
index ce9b49e3eb..99bd755f90 100644
--- a/lib/rubygems/package/tar_header.rb
+++ b/lib/rubygems/package/tar_header.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
# See LICENSE.txt for additional licensing information.
@@ -53,42 +54,42 @@ class Gem::Package::TarHeader
##
# Pack format for a tar header
- PACK_FORMAT = 'a100' + # name
- 'a8' + # mode
- 'a8' + # uid
- 'a8' + # gid
- 'a12' + # size
- 'a12' + # mtime
- 'a7a' + # chksum
- 'a' + # typeflag
- 'a100' + # linkname
- 'a6' + # magic
- 'a2' + # version
- 'a32' + # uname
- 'a32' + # gname
- 'a8' + # devmajor
- 'a8' + # devminor
- 'a155' # prefix
+ PACK_FORMAT = "a100" + # name
+ "a8" + # mode
+ "a8" + # uid
+ "a8" + # gid
+ "a12" + # size
+ "a12" + # mtime
+ "a7a" + # chksum
+ "a" + # typeflag
+ "a100" + # linkname
+ "a6" + # magic
+ "a2" + # version
+ "a32" + # uname
+ "a32" + # gname
+ "a8" + # devmajor
+ "a8" + # devminor
+ "a155" # prefix
##
# Unpack format for a tar header
- UNPACK_FORMAT = 'A100' + # name
- 'A8' + # mode
- 'A8' + # uid
- 'A8' + # gid
- 'A12' + # size
- 'A12' + # mtime
- 'A8' + # checksum
- 'A' + # typeflag
- 'A100' + # linkname
- 'A6' + # magic
- 'A2' + # version
- 'A32' + # uname
- 'A32' + # gname
- 'A8' + # devmajor
- 'A8' + # devminor
- 'A155' # prefix
+ UNPACK_FORMAT = "A100" + # name
+ "A8" + # mode
+ "A8" + # uid
+ "A8" + # gid
+ "A12" + # size
+ "A12" + # mtime
+ "A8" + # checksum
+ "A" + # typeflag
+ "A100" + # linkname
+ "A6" + # magic
+ "A2" + # version
+ "A32" + # uname
+ "A32" + # gname
+ "A8" + # devmajor
+ "A8" + # devminor
+ "A155" # prefix
attr_reader(*FIELDS)
@@ -103,22 +104,22 @@ class Gem::Package::TarHeader
fields = header.unpack UNPACK_FORMAT
- new :name => fields.shift,
- :mode => strict_oct(fields.shift),
- :uid => oct_or_256based(fields.shift),
- :gid => oct_or_256based(fields.shift),
- :size => strict_oct(fields.shift),
- :mtime => strict_oct(fields.shift),
+ new :name => fields.shift,
+ :mode => strict_oct(fields.shift),
+ :uid => oct_or_256based(fields.shift),
+ :gid => oct_or_256based(fields.shift),
+ :size => strict_oct(fields.shift),
+ :mtime => strict_oct(fields.shift),
:checksum => strict_oct(fields.shift),
:typeflag => fields.shift,
:linkname => fields.shift,
- :magic => fields.shift,
- :version => strict_oct(fields.shift),
- :uname => fields.shift,
- :gname => fields.shift,
+ :magic => fields.shift,
+ :version => strict_oct(fields.shift),
+ :uname => fields.shift,
+ :gname => fields.shift,
:devmajor => strict_oct(fields.shift),
:devminor => strict_oct(fields.shift),
- :prefix => fields.shift,
+ :prefix => fields.shift,
:empty => empty
end
@@ -134,7 +135,7 @@ class Gem::Package::TarHeader
# \ff flags a negative 256-based number
# In case we have a match, parse it as a signed binary value
# in big-endian order, except that the high-order bit is ignored.
- return str.unpack('N2').last if str =~ /\A[\x80\xff]/n
+ return str.unpack("N2").last if str =~ /\A[\x80\xff]/n
strict_oct(str)
end
@@ -173,23 +174,23 @@ class Gem::Package::TarHeader
end
def ==(other) # :nodoc:
- self.class === other and
- @checksum == other.checksum and
- @devmajor == other.devmajor and
- @devminor == other.devminor and
- @gid == other.gid and
- @gname == other.gname and
- @linkname == other.linkname and
- @magic == other.magic and
- @mode == other.mode and
- @mtime == other.mtime and
- @name == other.name and
- @prefix == other.prefix and
- @size == other.size and
- @typeflag == other.typeflag and
- @uid == other.uid and
- @uname == other.uname and
- @version == other.version
+ self.class === other &&
+ @checksum == other.checksum &&
+ @devmajor == other.devmajor &&
+ @devminor == other.devminor &&
+ @gid == other.gid &&
+ @gname == other.gname &&
+ @linkname == other.linkname &&
+ @magic == other.magic &&
+ @mode == other.mode &&
+ @mtime == other.mtime &&
+ @name == other.name &&
+ @prefix == other.prefix &&
+ @size == other.size &&
+ @typeflag == other.typeflag &&
+ @uid == other.uid &&
+ @uname == other.uname &&
+ @version == other.version
end
def to_s # :nodoc:
@@ -208,7 +209,7 @@ class Gem::Package::TarHeader
private
def calculate_checksum(header)
- header.unpack("C*").inject {|a, b| a + b }
+ header.sum(0)
end
def header(checksum = @checksum)
diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb
index e7c5620533..a8dd39c572 100644
--- a/lib/rubygems/package/tar_reader.rb
+++ b/lib/rubygems/package/tar_reader.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
# See LICENSE.txt for additional licensing information.
@@ -53,39 +54,11 @@ class Gem::Package::TarReader
def each
return enum_for __method__ unless block_given?
- use_seek = @io.respond_to?(:seek)
-
until @io.eof? do
header = Gem::Package::TarHeader.from @io
return if header.empty?
-
entry = Gem::Package::TarReader::Entry.new header, @io
- size = entry.header.size
-
yield entry
-
- skip = (512 - (size % 512)) % 512
- pending = size - entry.bytes_read
-
- if use_seek
- begin
- # avoid reading if the @io supports seeking
- @io.seek pending, IO::SEEK_CUR
- pending = 0
- rescue Errno::EINVAL
- end
- end
-
- # if seeking isn't supported or failed
- while pending > 0 do
- bytes_read = @io.read([pending, 4096].min).size
- raise UnexpectedEOF if @io.eof?
- pending -= bytes_read
- end
-
- @io.read skip # discard trailing zeros
-
- # make sure nobody can use #read, #getc or #rewind anymore
entry.close
end
end
@@ -121,4 +94,4 @@ class Gem::Package::TarReader
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 5865599d3a..e770079f41 100644
--- a/lib/rubygems/package/tar_reader/entry.rb
+++ b/lib/rubygems/package/tar_reader/entry.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#++
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
# See LICENSE.txt for additional licensing information.
@@ -9,6 +10,20 @@
class Gem::Package::TarReader::Entry
##
+ # Creates a new tar entry for +header+ that will be read from +io+
+ # If a block is given, the entry is yielded and then closed.
+
+ def self.open(header, io, &block)
+ entry = new header, io
+ return entry unless block_given?
+ begin
+ yield entry
+ ensure
+ entry.close
+ end
+ end
+
+ ##
# Header for this tar entry
attr_reader :header
@@ -21,6 +36,7 @@ class Gem::Package::TarReader::Entry
@header = header
@io = io
@orig_pos = @io.pos
+ @end_pos = @orig_pos + @header.size
@read = 0
end
@@ -39,7 +55,14 @@ class Gem::Package::TarReader::Entry
# Closes the tar entry
def close
+ return if closed?
+ # Seek to the end of the entry if it wasn't fully read
+ seek(0, IO::SEEK_END)
+ # discard trailing zeros
+ skip = (512 - (@header.size % 512)) % 512
+ @io.read(skip)
@closed = true
+ nil
end
##
@@ -68,9 +91,9 @@ class Gem::Package::TarReader::Entry
@header.name
end
rescue ArgumentError => e
- raise unless e.message == 'string contains null byte'
+ raise unless e.message == "string contains null byte"
raise Gem::Package::TarInvalidError,
- 'tar is corrupt, name contains null byte'
+ "tar is corrupt, name contains null byte"
end
##
@@ -117,6 +140,14 @@ class Gem::Package::TarReader::Entry
bytes_read
end
+ ##
+ # Seek to the position in the tar entry
+
+ def pos=(new_pos)
+ seek(new_pos, IO::SEEK_SET)
+ new_pos
+ end
+
def size
@header.size
end
@@ -130,9 +161,10 @@ class Gem::Package::TarReader::Entry
def read(len = nil)
check_closed
- return nil if @read >= @header.size
-
len ||= @header.size - @read
+
+ return nil if len > 0 && @read >= @header.size
+
max_read = [len, @header.size - @read].min
ret = @io.read max_read
@@ -144,9 +176,10 @@ class Gem::Package::TarReader::Entry
def readpartial(maxlen = nil, outbuf = "".b)
check_closed
- raise EOFError if @read >= @header.size
-
maxlen ||= @header.size - @read
+
+ raise EOFError if maxlen > 0 && @read >= @header.size
+
max_read = [maxlen, @header.size - @read].min
@io.readpartial(max_read, outbuf)
@@ -156,12 +189,61 @@ class Gem::Package::TarReader::Entry
end
##
+ # Seeks to +offset+ bytes into the tar file entry
+ # +whence+ can be IO::SEEK_SET, IO::SEEK_CUR, or IO::SEEK_END
+
+ def seek(offset, whence = IO::SEEK_SET)
+ check_closed
+
+ new_pos =
+ case whence
+ when IO::SEEK_SET then @orig_pos + offset
+ when IO::SEEK_CUR then @io.pos + offset
+ when IO::SEEK_END then @end_pos + offset
+ else
+ raise ArgumentError, "invalid whence"
+ end
+
+ if new_pos < @orig_pos
+ new_pos = @orig_pos
+ elsif new_pos > @end_pos
+ new_pos = @end_pos
+ end
+
+ pending = new_pos - @io.pos
+
+ if @io.respond_to?(:seek)
+ begin
+ # avoid reading if the @io supports seeking
+ @io.seek new_pos, IO::SEEK_SET
+ pending = 0
+ rescue Errno::EINVAL
+ end
+ end
+
+ # if seeking isn't supported or failed
+ # negative seek requires that we rewind and read
+ if pending < 0
+ @io.rewind
+ pending = new_pos
+ end
+
+ while pending > 0 do
+ size_read = @io.read([pending, 4096].min).size
+ raise UnexpectedEOF if @io.eof?
+ pending -= size_read
+ end
+
+ @read = @io.pos - @orig_pos
+
+ 0
+ end
+
+ ##
# Rewinds to the beginning of the tar file entry
def rewind
check_closed
-
- @io.pos = @orig_pos
- @read = 0
+ seek(0, IO::SEEK_SET)
end
end
diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb
index 877cc167c9..32a13e9162 100644
--- a/lib/rubygems/package/tar_writer.rb
+++ b/lib/rubygems/package/tar_writer.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
# See LICENSE.txt for additional licensing information.
@@ -166,7 +167,7 @@ class Gem::Package::TarWriter
def add_file_signed(name, mode, signer)
digest_algorithms = [
signer.digest_algorithm,
- Gem::Security.create_digest('SHA512'),
+ Gem::Security.create_digest("SHA512"),
].compact.uniq
digests = add_file_digest name, mode, digest_algorithms do |io|
@@ -304,17 +305,17 @@ class Gem::Package::TarWriter
raise Gem::Package::TooLongFileName.new("File \"#{name}\" has a too long path (should be 256 or less)")
end
- prefix = ''
+ prefix = ""
if name.bytesize > 100
- parts = name.split('/', -1) # parts are never empty here
+ parts = name.split("/", -1) # parts are never empty here
name = parts.pop # initially empty for names with a trailing slash ("foo/.../bar/")
- prefix = parts.join('/') # if empty, then it's impossible to split (parts is empty too)
+ prefix = parts.join("/") # if empty, then it's impossible to split (parts is empty too)
while !parts.empty? && (prefix.bytesize > 155 || name.empty?)
- name = parts.pop + '/' + name
- prefix = parts.join('/')
+ name = parts.pop + "/" + name
+ prefix = parts.join("/")
end
- if name.bytesize > 100 or prefix.empty?
+ if name.bytesize > 100 || prefix.empty?
raise Gem::Package::TooLongFileName.new("File \"#{prefix}/#{name}\" has a too long name (should be 100 or less)")
end
diff --git a/lib/rubygems/package_task.rb b/lib/rubygems/package_task.rb
index d5a2885a64..a67d8cb916 100644
--- a/lib/rubygems/package_task.rb
+++ b/lib/rubygems/package_task.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
# Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel
#
# Permission is hereby granted, free of charge, to any person obtaining
@@ -20,9 +21,9 @@
# 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'
-require 'rake/packagetask'
+require_relative "../rubygems"
+require_relative "package"
+require "rake/packagetask"
##
# Create a package based upon a Gem::Specification. Gem packages, as well as
@@ -113,7 +114,7 @@ class Gem::PackageTask < Rake::PackageTask
Gem::Package.build gem_spec
verbose trace do
- mv gem_file, '..'
+ mv gem_file, ".."
end
end
end
diff --git a/lib/rubygems/path_support.rb b/lib/rubygems/path_support.rb
index 8103caf324..d9df543ad9 100644
--- a/lib/rubygems/path_support.rb
+++ b/lib/rubygems/path_support.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
#
# Gem::PathSupport facilitates the GEM_HOME and GEM_PATH environment settings
@@ -72,12 +73,7 @@ class Gem::PathSupport
# Return the default Gem path
def default_path
- gem_path = Gem.default_path + [@home]
-
- if defined?(APPLE_GEM_HOME)
- gem_path << APPLE_GEM_HOME
- end
- gem_path
+ Gem.default_path + [@home]
end
def expand(path)
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index fd1c0a62ac..b721629b78 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require "rubygems/deprecate"
+
+require_relative "deprecate"
##
# Available list of platforms for targeting Gem installations.
@@ -12,7 +13,7 @@ class Gem::Platform
attr_accessor :cpu, :os, :version
def self.local
- arch = RbConfig::CONFIG['arch']
+ arch = RbConfig::CONFIG["arch"]
arch = "#{arch}_60" if arch =~ /mswin(?:32|64)$/
@local ||= new(arch)
end
@@ -22,10 +23,11 @@ class Gem::Platform
end
def self.match_platforms?(platform, platforms)
+ platform = Gem::Platform.new(platform) unless platform.is_a?(Gem::Platform)
platforms.any? do |local_platform|
- platform.nil? or
- local_platform == platform or
- (local_platform != Gem::Platform::RUBY and local_platform =~ platform)
+ platform.nil? ||
+ local_platform == platform ||
+ (local_platform != Gem::Platform::RUBY && platform =~ local_platform)
end
end
private_class_method :match_platforms?
@@ -40,6 +42,10 @@ class Gem::Platform
match_platforms?(platform, Gem.platforms)
end
+ def self.sort_priority(platform)
+ platform == Gem::Platform::RUBY ? -1 : 1
+ end
+
def self.installable?(spec)
if spec.respond_to? :installable_platform?
spec.installable_platform?
@@ -52,7 +58,7 @@ class Gem::Platform
case arch
when Gem::Platform::CURRENT then
Gem::Platform.local
- when Gem::Platform::RUBY, nil, '' then
+ when Gem::Platform::RUBY, nil, "" then
Gem::Platform::RUBY
else
super
@@ -64,9 +70,9 @@ class Gem::Platform
when Array then
@cpu, @os, @version = arch
when String then
- arch = arch.split '-'
+ arch = arch.split "-"
- if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu
+ if arch.length > 2 && arch.last !~ /\d+(\.\d+)?$/ # reassemble x86-linux-{libc}
extra = arch.pop
arch.last << "-#{extra}"
end
@@ -74,11 +80,11 @@ class Gem::Platform
cpu = arch.shift
@cpu = case cpu
- when /i\d86/ then 'x86'
- else cpu
- end
+ when /i\d86/ then "x86"
+ else cpu
+ end
- if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ # for command-line
+ if arch.length == 2 && arch.last =~ /^\d+(\.\d+)?$/ # for command-line
@os, @version = arch
return
end
@@ -87,31 +93,30 @@ class Gem::Platform
@cpu, os = nil, cpu if os.nil? # legacy jruby
@os, @version = case os
- when /aix(\d+)?/ then [ 'aix', $1 ]
- when /cygwin/ then [ 'cygwin', nil ]
- when /darwin(\d+)?/ then [ 'darwin', $1 ]
- when /^macruby$/ then [ 'macruby', nil ]
- when /freebsd(\d+)?/ then [ 'freebsd', $1 ]
- when /hpux(\d+)?/ then [ 'hpux', $1 ]
- when /^java$/, /^jruby$/ then [ 'java', nil ]
- when /^java([\d.]*)/ then [ 'java', $1 ]
- when /^dalvik(\d+)?$/ then [ 'dalvik', $1 ]
- when /^dotnet$/ then [ 'dotnet', nil ]
- when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ]
- when /linux-?((?!gnu)\w+)?/ then [ 'linux', $1 ]
- when /mingw32/ then [ 'mingw32', nil ]
- when /(mswin\d+)(\_(\d+))?/ then
- os, version = $1, $3
- @cpu = 'x86' if @cpu.nil? and os =~ /32$/
- [os, version]
- when /netbsdelf/ then [ 'netbsdelf', nil ]
- when /openbsd(\d+\.\d+)?/ then [ 'openbsd', $1 ]
- when /bitrig(\d+\.\d+)?/ then [ 'bitrig', $1 ]
- when /solaris(\d+\.\d+)?/ then [ 'solaris', $1 ]
- # test
- when /^(\w+_platform)(\d+)?/ then [ $1, $2 ]
- else [ 'unknown', nil ]
- end
+ when /aix(\d+)?/ then [ "aix", $1 ]
+ when /cygwin/ then [ "cygwin", nil ]
+ when /darwin(\d+)?/ then [ "darwin", $1 ]
+ when /^macruby$/ then [ "macruby", nil ]
+ when /freebsd(\d+)?/ then [ "freebsd", $1 ]
+ when /^java$/, /^jruby$/ then [ "java", nil ]
+ when /^java([\d.]*)/ then [ "java", $1 ]
+ when /^dalvik(\d+)?$/ then [ "dalvik", $1 ]
+ when /^dotnet$/ then [ "dotnet", nil ]
+ when /^dotnet([\d.]*)/ then [ "dotnet", $1 ]
+ when /linux-?(\w+)?/ then [ "linux", $1 ]
+ when /mingw32/ then [ "mingw32", nil ]
+ when /mingw-?(\w+)?/ then [ "mingw", $1 ]
+ when /(mswin\d+)(\_(\d+))?/ then
+ os, version = $1, $3
+ @cpu = "x86" if @cpu.nil? && os =~ /32$/
+ [os, version]
+ when /netbsdelf/ then [ "netbsdelf", nil ]
+ when /openbsd(\d+\.\d+)?/ then [ "openbsd", $1 ]
+ when /solaris(\d+\.\d+)?/ then [ "solaris", $1 ]
+ # test
+ when /^(\w+_platform)(\d+)?/ then [ $1, $2 ]
+ else [ "unknown", nil ]
+ end
when Gem::Platform then
@cpu = arch.cpu
@os = arch.os
@@ -126,7 +131,7 @@ class Gem::Platform
end
def to_s
- to_a.compact.join '-'
+ to_a.compact.join "-"
end
##
@@ -134,7 +139,7 @@ class Gem::Platform
# the same CPU, OS and version.
def ==(other)
- self.class === other and to_a == other.to_a
+ self.class === other && to_a == other.to_a
end
alias :eql? :==
@@ -146,23 +151,53 @@ class Gem::Platform
##
# Does +other+ match this platform? Two platforms match if they have the
# same CPU, or either has a CPU of 'universal', they have the same OS, and
- # they have the same version, or either has no version.
+ # they have the same version, or either one has no version
#
# Additionally, the platform will match if the local CPU is 'arm' and the
# other CPU starts with "arm" (for generic ARM family support).
+ #
+ # Of note, this method is not commutative. Indeed the OS 'linux' has a
+ # special case: the version is the libc name, yet while "no version" stands
+ # as a wildcard for a binary gem platform (as for other OSes), for the
+ # runtime platform "no version" stands for 'gnu'. To be able to distinguish
+ # these, the method receiver is the gem platform, while the argument is
+ # the runtime platform.
+ #
+ #--
+ # NOTE: Until it can be removed, changes to this method must also be reflected in `bundler/lib/bundler/rubygems_ext.rb`
def ===(other)
return nil unless Gem::Platform === other
+ # universal-mingw32 matches x64-mingw-ucrt
+ return true if (@cpu == "universal" || other.cpu == "universal") &&
+ @os.start_with?("mingw") && other.os.start_with?("mingw")
+
# cpu
- ([nil,'universal'].include?(@cpu) or [nil, 'universal'].include?(other.cpu) or @cpu == other.cpu or
- (@cpu == 'arm' and other.cpu.start_with?("arm"))) and
+ ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
+ (@cpu == "arm" && other.cpu.start_with?("arm"))) &&
+
+ # os
+ @os == other.os &&
+
+ # version
+ (
+ (@os != "linux" && (@version.nil? || other.version.nil?)) ||
+ (@os == "linux" && (normalized_linux_version == other.normalized_linux_version || ["musl#{@version}", "musleabi#{@version}", "musleabihf#{@version}"].include?(other.version))) ||
+ @version == other.version
+ )
+ end
- # os
- @os == other.os and
+ #--
+ # NOTE: Until it can be removed, changes to this method must also be reflected in `bundler/lib/bundler/rubygems_ext.rb`
- # version
- (@version.nil? or other.version.nil? or @version == other.version)
+ def normalized_linux_version
+ return nil unless @version
+
+ without_gnu_nor_abi_modifiers = @version.sub(/\Agnu/, "").sub(/eabi(hf)?\Z/, "")
+ return nil if without_gnu_nor_abi_modifiers.empty?
+
+ without_gnu_nor_abi_modifiers
end
##
@@ -175,19 +210,19 @@ class Gem::Platform
when String then
# This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007
other = case other
- when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ]
- when /^i\d86-linux/ then ['x86', 'linux', nil ]
- when 'java', 'jruby' then [nil, 'java', nil ]
- when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ]
- when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ]
- when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ]
- when /mswin64(\_(\d+))?/ then ['x64', 'mswin64', $2 ]
- when 'powerpc-darwin' then ['powerpc', 'darwin', nil ]
- when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ]
- when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ]
- when /universal-darwin(\d)/ then ['universal', 'darwin', $1 ]
- else other
- end
+ when /^i686-darwin(\d)/ then ["x86", "darwin", $1 ]
+ when /^i\d86-linux/ then ["x86", "linux", nil ]
+ when "java", "jruby" then [nil, "java", nil ]
+ when /^dalvik(\d+)?$/ then [nil, "dalvik", $1 ]
+ when /dotnet(\-(\d+\.\d+))?/ then ["universal","dotnet", $2 ]
+ when /mswin32(\_(\d+))?/ then ["x86", "mswin32", $2 ]
+ when /mswin64(\_(\d+))?/ then ["x64", "mswin64", $2 ]
+ when "powerpc-darwin" then ["powerpc", "darwin", nil ]
+ when /powerpc-darwin(\d)/ then ["powerpc", "darwin", $1 ]
+ when /sparc-solaris2.8/ then ["sparc", "solaris", "2.8" ]
+ when /universal-darwin(\d)/ then ["universal", "darwin", $1 ]
+ else other
+ end
other = Gem::Platform.new other
else
@@ -201,11 +236,11 @@ class Gem::Platform
# A pure-Ruby gem that may use Gem::Specification#extensions to build
# binary files.
- RUBY = 'ruby'.freeze
+ RUBY = "ruby"
##
# A platform-specific gem that is built for the packaging Ruby's platform.
# This will be replaced with Gem::Platform::local.
- CURRENT = 'current'.freeze
+ CURRENT = "current"
end
diff --git a/lib/rubygems/psych_additions.rb b/lib/rubygems/psych_additions.rb
deleted file mode 100644
index 1ddd74421c..0000000000
--- a/lib/rubygems/psych_additions.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-# This exists just to satisfy bugs in marshal'd gemspecs that
-# contain a reference to YAML::PrivateType. We prune these out
-# in Specification._load, but if we don't have the constant, Marshal
-# blows up.
-
-module Psych # :nodoc:
- class PrivateType # :nodoc:
- end
-end
diff --git a/lib/rubygems/psych_tree.rb b/lib/rubygems/psych_tree.rb
index 6f399a289e..2d478c94d9 100644
--- a/lib/rubygems/psych_tree.rb
+++ b/lib/rubygems/psych_tree.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem
if defined? ::Psych::Visitors
class NoAliasYAMLTree < Psych::Visitors::YAMLTree
@@ -7,7 +8,7 @@ module Gem
end unless respond_to? :create
def visit_String(str)
- return super unless str == '=' # or whatever you want
+ return super unless str == "=" # or whatever you want
quote = Psych::Nodes::Scalar::SINGLE_QUOTED
@emitter.scalar str, nil, nil, false, true, quote
diff --git a/lib/rubygems/query_utils.rb b/lib/rubygems/query_utils.rb
index ea0f260ab4..c72955f83b 100644
--- a/lib/rubygems/query_utils.rb
+++ b/lib/rubygems/query_utils.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
-require 'rubygems/text'
+require_relative "local_remote_options"
+require_relative "spec_fetcher"
+require_relative "version_option"
+require_relative "text"
module Gem::QueryUtils
@@ -12,41 +12,41 @@ module Gem::QueryUtils
include Gem::VersionOption
def add_query_options
- add_option('-i', '--[no-]installed',
- 'Check for installed gem') do |value, 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|
+ 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|
+ 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|
+ 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|
+ 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|
+ 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|
+ add_option("--[no-]prerelease",
+ "Display prerelease versions") do |value, options|
options[:prerelease] = value
end
@@ -54,14 +54,14 @@ module Gem::QueryUtils
end
def defaults_str # :nodoc:
- "--local --name-matches // --no-details --versions --no-installed"
+ "--local --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 }
+ gem_names = if args.empty?
+ [options[:name]]
+ else
+ options[:exact] ? args.map {|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map {|arg| /#{arg}/i }
end
terminate_interaction(check_installed_gems(gem_names)) if check_installed_gems?
@@ -96,7 +96,7 @@ module Gem::QueryUtils
end
def gem_name?
- !options[:name].source.empty?
+ !options[:name].nil?
end
def prerelease
@@ -112,7 +112,7 @@ module Gem::QueryUtils
end
def display_header(type)
- if (ui.outs.tty? and Gem.configuration.verbose) or both?
+ if (ui.outs.tty? && Gem.configuration.verbose) || both?
say
say "*** #{type} GEMS ***"
say
@@ -129,12 +129,10 @@ module Gem::QueryUtils
display_header("LOCAL")
specs = Gem::Specification.find_all do |s|
- s.name =~ name and req =~ s.version
- end
+ name_matches = name ? s.name =~ name : true
+ version_matches = show_prereleases? || !s.version.prerelease?
- dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req }
- specs.select! do |s|
- dep.match?(s.name, s.version, show_prereleases?)
+ name_matches && version_matches
end
spec_tuples = specs.map do |spec|
@@ -149,19 +147,19 @@ module Gem::QueryUtils
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
+ spec_tuples = if name.nil?
+ fetcher.detect(specs_type) { true }
+ else
+ fetcher.detect(specs_type) do |name_tuple|
+ name === name_tuple.name && options[:version].satisfied_by?(name_tuple.version)
+ end
+ end
output_query_results(spec_tuples)
end
def specs_type
- if options[:all]
+ if options[:all] || options[:version].specific?
if options[:prerelease]
:complete
else
@@ -178,7 +176,7 @@ module Gem::QueryUtils
# 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 }
+ Gem::Specification.any? {|s| s.name =~ name && req =~ s.version }
end
def output_query_results(spec_tuples)
@@ -244,7 +242,7 @@ module Gem::QueryUtils
return unless options[:versions]
list =
- if platforms.empty? or options[:details]
+ if platforms.empty? || options[:details]
name_tuples.map {|n| n.version }.uniq
else
platforms.sort.reverse.map do |version, pls|
@@ -259,7 +257,7 @@ module Gem::QueryUtils
if pls != [Gem::Platform::RUBY]
platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact
- out = platform_list.unshift(out).join(' ')
+ out = platform_list.unshift(out).join(" ")
end
out
@@ -286,21 +284,21 @@ module Gem::QueryUtils
def spec_authors(entry, spec)
authors = "Author#{spec.authors.length > 1 ? 's' : ''}: ".dup
- authors << spec.authors.join(', ')
+ 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?
+ return if spec.homepage.nil? || 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?
+ return if spec.license.nil? || spec.license.empty?
licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: ".dup
- licenses << spec.licenses.join(', ')
+ licenses << spec.licenses.join(", ")
entry << "\n" << format_text(licenses, 68, 4)
end
@@ -308,15 +306,15 @@ module Gem::QueryUtils
return unless spec.loaded_from
if specs.length == 1
- default = spec.default_gem? ? ' (default)' : nil
+ default = spec.default_gem? ? " (default)" : nil
entry << "\n" << " Installed at#{default}: #{spec.base_dir}"
else
- label = 'Installed at'
+ label = "Installed at"
specs.each do |s|
version = s.version.to_s
- version << ', default' if s.default_gem?
+ version << ", default" if s.default_gem?
entry << "\n" << " #{label} (#{version}): #{s.base_dir}"
- label = ' ' * label.length
+ label = " " * label.length
end
end
end
@@ -329,7 +327,7 @@ module Gem::QueryUtils
return unless non_ruby
if platforms.length == 1
- title = platforms.values.length == 1 ? 'Platform' : 'Platforms'
+ title = platforms.values.length == 1 ? "Platform" : "Platforms"
entry << " #{title}: #{platforms.values.sort.join(', ')}\n"
else
entry << " Platforms:\n"
@@ -338,7 +336,7 @@ module Gem::QueryUtils
sorted_platforms.each do |version, pls|
label = " #{version}: "
- data = format_text pls.sort.join(', '), 68, label.length
+ data = format_text pls.sort.join(", "), 68, label.length
data[0, label.length] = label
entry << data << "\n"
end
diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb
index c40bb7d9f1..907dcd9431 100644
--- a/lib/rubygems/rdoc.rb
+++ b/lib/rubygems/rdoc.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
-require 'rubygems'
+
+require_relative "../rubygems"
begin
- require 'rdoc/rubygems_hook'
+ require "rdoc/rubygems_hook"
module Gem
RDoc = ::RDoc::RubygemsHook
end
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 45dca1195e..1c8a441d0c 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -1,11 +1,12 @@
# 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_parser'
-require 'rubygems/user_interaction'
+
+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
@@ -25,15 +26,12 @@ class Gem::RemoteFetcher
attr_accessor :uri, :original_uri
def initialize(message, uri)
- super message
-
- uri = Gem::UriParser.parse_uri(uri)
-
- @original_uri = uri.dup
+ uri = Gem::Uri.new(uri)
- uri.password = 'REDACTED' if uri.respond_to?(:password) && uri.password
+ super uri.redact_credentials_from(message)
- @uri = uri.to_s
+ @original_uri = uri.to_s
+ @uri = uri.redacted.to_s
end
def to_s # :nodoc:
@@ -75,10 +73,10 @@ class Gem::RemoteFetcher
# fetching the gem.
def initialize(proxy=nil, dns=nil, headers={})
- require 'rubygems/core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
- require 'net/http'
- require 'stringio'
- require 'uri'
+ require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled
+ require "net/http"
+ require "stringio"
+ require "uri"
Socket.do_not_reverse_lookup = true
@@ -117,7 +115,7 @@ class Gem::RemoteFetcher
cache_dir =
if Dir.pwd == install_dir # see fetch_command
install_dir
- elsif File.writable?(install_cache_dir) || (File.writable?(install_dir) && (not File.exist?(install_cache_dir)))
+ elsif File.writable?(install_cache_dir) || (File.writable?(install_dir) && (!File.exist?(install_cache_dir)))
install_cache_dir
else
File.join Gem.user_dir, "cache"
@@ -129,7 +127,7 @@ class Gem::RemoteFetcher
require "fileutils"
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
- source_uri = Gem::UriParser.parse_uri(source_uri)
+ source_uri = Gem::Uri.new(source_uri)
scheme = source_uri.scheme
@@ -139,7 +137,7 @@ class Gem::RemoteFetcher
# REFACTOR: split this up and dispatch on scheme (eg download_http)
# REFACTOR: be sure to clean up fake fetcher when you do this... cleaner
case scheme
- when 'http', 'https', 's3' then
+ when "http", "https", "s3" then
unless File.exist? local_gem_path
begin
verbose "Downloading gem #{gem_file_name}"
@@ -159,12 +157,12 @@ class Gem::RemoteFetcher
self.cache_update_path remote_gem_path, local_gem_path
end
end
- when 'file' then
+ when "file" then
begin
path = source_uri.path
- path = File.dirname(path) if File.extname(path) == '.gem'
+ path = File.dirname(path) if File.extname(path) == ".gem"
- remote_gem_path = Gem::Util.correct_for_windows_path(File.join(path, 'gems', gem_file_name))
+ remote_gem_path = Gem::Util.correct_for_windows_path(File.join(path, "gems", gem_file_name))
FileUtils.cp(remote_gem_path, local_gem_path)
rescue Errno::EACCES
@@ -174,11 +172,11 @@ class Gem::RemoteFetcher
verbose "Using local gem #{local_gem_path}"
when nil then # TODO test for local overriding cache
source_path = if Gem.win_platform? && source_uri.scheme &&
- !source_uri.path.include?(':')
- "#{source_uri.scheme}:#{source_uri.path}"
- else
- source_uri.path
- end
+ !source_uri.path.include?(":")
+ "#{source_uri.scheme}:#{source_uri.path}"
+ else
+ source_uri.path
+ end
source_path = Gem::UriFormatter.new(source_path).unescape
@@ -219,12 +217,12 @@ class Gem::RemoteFetcher
head ? response : response.body
when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
Net::HTTPTemporaryRedirect then
- raise FetchError.new('too many redirects', uri) if depth > 10
+ raise FetchError.new("too many redirects", uri) if depth > 10
- unless location = response['Location']
+ unless location = response["Location"]
raise FetchError.new("redirecting but no redirect location was given", uri)
end
- location = Gem::UriParser.parse_uri location
+ location = Gem::Uri.new location
if https?(uri) && !https?(location)
raise FetchError.new("redirecting to non-https resource: #{location}", uri)
@@ -242,7 +240,7 @@ class Gem::RemoteFetcher
# Downloads +uri+ and returns it as a String.
def fetch_path(uri, mtime = nil, head = false)
- uri = Gem::UriParser.parse_uri uri
+ uri = Gem::Uri.new uri
unless uri.scheme
raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
@@ -250,7 +248,7 @@ class Gem::RemoteFetcher
data = send "fetch_#{uri.scheme}", uri, mtime, head
- if data and !head and uri.to_s.end_with?(".gz")
+ if data && !head && uri.to_s.end_with?(".gz")
begin
data = Gem::Util.gunzip data
rescue Zlib::GzipFile::Error
@@ -291,7 +289,7 @@ class Gem::RemoteFetcher
return Gem.read_binary(path)
end
- if update and path
+ if update && path
Gem.write_binary(path, data)
end
@@ -315,7 +313,7 @@ class Gem::RemoteFetcher
end
def https?(uri)
- uri.scheme.downcase == 'https'
+ uri.scheme.downcase == "https"
end
def close_all
diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb
index 5bda0b2e5e..8ea39d9358 100644
--- a/lib/rubygems/request.rb
+++ b/lib/rubygems/request.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'net/http'
-require 'rubygems/user_interaction'
+
+require "net/http"
+require_relative "user_interaction"
class Gem::Request
extend Gem::UserInteraction
@@ -39,12 +40,12 @@ class Gem::Request
def cert_files; @connection_pool.cert_files; end
def self.get_cert_files
- pattern = File.expand_path("./ssl_certs/*/*.pem", File.dirname(__FILE__))
+ pattern = File.expand_path("./ssl_certs/*/*.pem", __dir__)
Dir.glob(pattern)
end
def self.configure_connection_for_https(connection, cert_files)
- raise Gem::Exception.new('OpenSSL is not available. Install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources') unless Gem::HAVE_OPENSSL
+ 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 =
@@ -96,8 +97,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"
@@ -138,13 +141,13 @@ class Gem::Request
Gem::UriFormatter.new(@uri.password).unescape
end
- request.add_field 'User-Agent', @user_agent
- request.add_field 'Connection', 'keep-alive'
- request.add_field 'Keep-Alive', '30'
+ request.add_field "User-Agent", @user_agent
+ request.add_field "Connection", "keep-alive"
+ request.add_field "Keep-Alive", "30"
if @last_modified
- require 'time'
- request.add_field 'If-Modified-Since', @last_modified.httpdate
+ require "time"
+ request.add_field "If-Modified-Since", @last_modified.httpdate
end
yield request if block_given?
@@ -156,7 +159,7 @@ class Gem::Request
# Returns a proxy URI for the given +scheme+ if one is set in the
# environment variables.
- def self.get_proxy_from_env(scheme = 'http')
+ def self.get_proxy_from_env(scheme = "http")
_scheme = scheme.downcase
_SCHEME = scheme.upcase
env_proxy = ENV["#{_scheme}_proxy"] || ENV["#{_SCHEME}_PROXY"]
@@ -164,14 +167,14 @@ class Gem::Request
no_env_proxy = env_proxy.nil? || env_proxy.empty?
if no_env_proxy
- return (_scheme == 'https' || _scheme == 'http') ?
- :no_proxy : get_proxy_from_env('http')
+ return (_scheme == "https" || _scheme == "http") ?
+ :no_proxy : get_proxy_from_env("http")
end
require "uri"
uri = URI(Gem::UriFormatter.new(env_proxy).normalize)
- if uri and uri.user.nil? and uri.password.nil?
+ if uri && uri.user.nil? && uri.password.nil?
user = ENV["#{_scheme}_proxy_user"] || ENV["#{_SCHEME}_PROXY_USER"]
password = ENV["#{_scheme}_proxy_pass"] || ENV["#{_SCHEME}_PROXY_PASS"]
@@ -191,7 +194,7 @@ class Gem::Request
begin
@requests[connection.object_id] += 1
- verbose "#{request.method} #{@uri}"
+ verbose "#{request.method} #{Gem::Uri.redact(@uri)}"
file_name = File.basename(@uri.path)
# perform download progress reporter only for gems
@@ -227,14 +230,14 @@ class Gem::Request
reset connection
- raise Gem::RemoteFetcher::FetchError.new('too many bad responses', @uri) if bad_response
+ raise Gem::RemoteFetcher::FetchError.new("too many bad responses", @uri) if bad_response
bad_response = true
retry
rescue Net::HTTPFatalError
verbose "fatal error"
- raise Gem::RemoteFetcher::FetchError.new('fatal error', @uri)
+ raise Gem::RemoteFetcher::FetchError.new("fatal error", @uri)
# HACK work around EOFError bug in Net::HTTP
# NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
# to install gems.
@@ -244,7 +247,7 @@ class Gem::Request
requests = @requests[connection.object_id]
verbose "connection reset after #{requests} requests, retrying"
- raise Gem::RemoteFetcher::FetchError.new('too many connection resets', @uri) if retried
+ raise Gem::RemoteFetcher::FetchError.new("too many connection resets", @uri) if retried
reset connection
@@ -271,7 +274,7 @@ class Gem::Request
ua = "RubyGems/#{Gem::VERSION} #{Gem::Platform.local}".dup
ruby_version = RUBY_VERSION
- ruby_version += 'dev' if RUBY_PATCHLEVEL == -1
+ ruby_version += "dev" if RUBY_PATCHLEVEL == -1
ua << " Ruby/#{ruby_version} (#{RUBY_RELEASE_DATE}"
if RUBY_PATCHLEVEL >= 0
@@ -281,12 +284,12 @@ class Gem::Request
end
ua << ")"
- ua << " #{RUBY_ENGINE}" if RUBY_ENGINE != 'ruby'
+ ua << " #{RUBY_ENGINE}" if RUBY_ENGINE != "ruby"
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 a4c2929b38..44280489fb 100644
--- a/lib/rubygems/request/connection_pools.rb
+++ b/lib/rubygems/request/connection_pools.rb
@@ -37,15 +37,15 @@ class Gem::Request::ConnectionPools # :nodoc:
# Returns list of no_proxy entries (if any) from the environment
def get_no_proxy_from_env
- env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
+ env_no_proxy = ENV["no_proxy"] || ENV["NO_PROXY"]
- return [] if env_no_proxy.nil? or env_no_proxy.empty?
+ return [] if env_no_proxy.nil? || env_no_proxy.empty?
env_no_proxy.split(/\s*,\s*/)
end
def https?(uri)
- uri.scheme.downcase == 'https'
+ uri.scheme.downcase == "https"
end
def no_proxy?(host, env_no_proxy)
@@ -78,7 +78,7 @@ class Gem::Request::ConnectionPools # :nodoc:
no_proxy = get_no_proxy_from_env
- if proxy_uri and not no_proxy?(hostname, no_proxy)
+ if proxy_uri && !no_proxy?(hostname, no_proxy)
proxy_hostname = proxy_uri.respond_to?(:hostname) ? proxy_uri.hostname : proxy_uri.host
net_http_args + [
proxy_hostname,
diff --git a/lib/rubygems/request/http_pool.rb b/lib/rubygems/request/http_pool.rb
index f028516db8..52543de41f 100644
--- a/lib/rubygems/request/http_pool.rb
+++ b/lib/rubygems/request/http_pool.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A connection "pool" that only manages one connection for now. Provides
# thread safe `checkout` and `checkin` methods. The pool consists of one
@@ -26,7 +27,7 @@ class Gem::Request::HTTPPool # :nodoc:
def close_all
until @queue.empty?
- if connection = @queue.pop(true) and connection.started?
+ if (connection = @queue.pop(true)) && connection.started?
connection.finish
end
end
diff --git a/lib/rubygems/request/https_pool.rb b/lib/rubygems/request/https_pool.rb
index 50f42d9e0d..cb1d4b59b6 100644
--- a/lib/rubygems/request/https_pool.rb
+++ b/lib/rubygems/request/https_pool.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
class Gem::Request::HTTPSPool < Gem::Request::HTTPPool # :nodoc:
private
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb
index 36ec87e1f7..b6e0995726 100644
--- a/lib/rubygems/request_set.rb
+++ b/lib/rubygems/request_set.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'tsort'
+
+require_relative "tsort"
##
# A RequestSet groups a request to activate a set of dependencies.
@@ -15,7 +16,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
@@ -107,7 +108,7 @@ class Gem::RequestSet
@requests = []
@sets = []
@soft_missing = false
- @sorted = nil
+ @sorted_requests = nil
@specs = nil
@vendor_set = nil
@source_set = nil
@@ -254,7 +255,7 @@ class Gem::RequestSet
end
def install_into(dir, force = true, options = {})
- gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir
+ gem_home, ENV["GEM_HOME"] = ENV["GEM_HOME"], dir
existing = force ? [] : specs_in(dir)
existing.delete_if {|s| @always_install.include? s }
@@ -287,7 +288,7 @@ class Gem::RequestSet
installed
ensure
- ENV['GEM_HOME'] = gem_home
+ ENV["GEM_HOME"] = gem_home
end
##
@@ -303,7 +304,7 @@ class Gem::RequestSet
end
end
- require "rubygems/dependency_installer"
+ require_relative "dependency_installer"
inst = Gem::DependencyInstaller.new options
inst.installed_gems.replace specs
@@ -337,32 +338,32 @@ class Gem::RequestSet
end
def pretty_print(q) # :nodoc:
- q.group 2, '[RequestSet:', ']' do
+ q.group 2, "[RequestSet:", "]" do
q.breakable
if @remote
- q.text 'remote'
+ q.text "remote"
q.breakable
end
if @prerelease
- q.text 'prerelease'
+ q.text "prerelease"
q.breakable
end
if @development_shallow
- q.text 'shallow development'
+ q.text "shallow development"
q.breakable
elsif @development
- q.text 'development'
+ q.text "development"
q.breakable
end
if @soft_missing
- q.text 'soft missing'
+ q.text "soft missing"
end
- q.group 2, '[dependencies:', ']' do
+ q.group 2, "[dependencies:", "]" do
q.breakable
@dependencies.map do |dep|
q.text dep.to_s
@@ -371,7 +372,7 @@ class Gem::RequestSet
end
q.breakable
- q.text 'sets:'
+ q.text "sets:"
q.breakable
q.pp @sets.map {|set| set.class }
@@ -424,7 +425,7 @@ class Gem::RequestSet
end
def sorted_requests
- @sorted ||= strongly_connected_components.flatten
+ @sorted_requests ||= strongly_connected_components.flatten
end
def specs
@@ -443,14 +444,14 @@ class Gem::RequestSet
def tsort_each_child(node) # :nodoc:
node.spec.dependencies.each do |dep|
- next if dep.type == :development and not @development
+ next if dep.type == :development && !@development
match = @requests.find do |r|
- dep.match? r.spec.name, r.spec.version, @prerelease
+ dep.match? r.spec.name, r.spec.version, r.spec.is_a?(Gem::Resolver::InstalledSpecification) || @prerelease
end
unless match
- next if dep.type == :development and @development_shallow
+ next if dep.type == :development && @development_shallow
next if @soft_missing
raise Gem::DependencyError,
"Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})"
@@ -461,6 +462,6 @@ class Gem::RequestSet
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 7188b07346..2fd0da340a 100644
--- a/lib/rubygems/request_set/gem_dependency_api.rb
+++ b/lib/rubygems/request_set/gem_dependency_api.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A semi-compatible DSL for the Bundler Gemfile and Isolate gem dependencies
# files.
@@ -32,134 +33,134 @@
class Gem::RequestSet::GemDependencyAPI
ENGINE_MAP = { # :nodoc:
- :jruby => %w[jruby],
- :jruby_18 => %w[jruby],
- :jruby_19 => %w[jruby],
- :maglev => %w[maglev],
- :mri => %w[ruby],
- :mri_18 => %w[ruby],
- :mri_19 => %w[ruby],
- :mri_20 => %w[ruby],
- :mri_21 => %w[ruby],
- :rbx => %w[rbx],
- :truffleruby => %w[truffleruby],
- :ruby => %w[ruby rbx maglev truffleruby],
- :ruby_18 => %w[ruby rbx maglev truffleruby],
- :ruby_19 => %w[ruby rbx maglev truffleruby],
- :ruby_20 => %w[ruby rbx maglev truffleruby],
- :ruby_21 => %w[ruby rbx maglev truffleruby],
+ :jruby => %w[jruby],
+ :jruby_18 => %w[jruby],
+ :jruby_19 => %w[jruby],
+ :maglev => %w[maglev],
+ :mri => %w[ruby],
+ :mri_18 => %w[ruby],
+ :mri_19 => %w[ruby],
+ :mri_20 => %w[ruby],
+ :mri_21 => %w[ruby],
+ :rbx => %w[rbx],
+ :truffleruby => %w[truffleruby],
+ :ruby => %w[ruby rbx maglev truffleruby],
+ :ruby_18 => %w[ruby rbx maglev truffleruby],
+ :ruby_19 => %w[ruby rbx maglev truffleruby],
+ :ruby_20 => %w[ruby rbx maglev truffleruby],
+ :ruby_21 => %w[ruby rbx maglev truffleruby],
}.freeze
- mswin = Gem::Platform.new 'x86-mswin32'
- mswin64 = Gem::Platform.new 'x64-mswin64'
- x86_mingw = Gem::Platform.new 'x86-mingw32'
- x64_mingw = Gem::Platform.new 'x64-mingw32'
+ mswin = Gem::Platform.new "x86-mswin32"
+ mswin64 = Gem::Platform.new "x64-mswin64"
+ x86_mingw = Gem::Platform.new "x86-mingw32"
+ x64_mingw = Gem::Platform.new "x64-mingw32"
PLATFORM_MAP = { # :nodoc:
- :jruby => Gem::Platform::RUBY,
- :jruby_18 => Gem::Platform::RUBY,
- :jruby_19 => Gem::Platform::RUBY,
- :maglev => Gem::Platform::RUBY,
- :mingw => x86_mingw,
- :mingw_18 => x86_mingw,
- :mingw_19 => x86_mingw,
- :mingw_20 => x86_mingw,
- :mingw_21 => x86_mingw,
- :mri => Gem::Platform::RUBY,
- :mri_18 => Gem::Platform::RUBY,
- :mri_19 => Gem::Platform::RUBY,
- :mri_20 => Gem::Platform::RUBY,
- :mri_21 => Gem::Platform::RUBY,
- :mswin => mswin,
- :mswin_18 => mswin,
- :mswin_19 => mswin,
- :mswin_20 => mswin,
- :mswin_21 => mswin,
- :mswin64 => mswin64,
- :mswin64_19 => mswin64,
- :mswin64_20 => mswin64,
- :mswin64_21 => mswin64,
- :rbx => Gem::Platform::RUBY,
- :ruby => Gem::Platform::RUBY,
- :ruby_18 => Gem::Platform::RUBY,
- :ruby_19 => Gem::Platform::RUBY,
- :ruby_20 => Gem::Platform::RUBY,
- :ruby_21 => Gem::Platform::RUBY,
- :truffleruby => Gem::Platform::RUBY,
- :x64_mingw => x64_mingw,
+ :jruby => Gem::Platform::RUBY,
+ :jruby_18 => Gem::Platform::RUBY,
+ :jruby_19 => Gem::Platform::RUBY,
+ :maglev => Gem::Platform::RUBY,
+ :mingw => x86_mingw,
+ :mingw_18 => x86_mingw,
+ :mingw_19 => x86_mingw,
+ :mingw_20 => x86_mingw,
+ :mingw_21 => x86_mingw,
+ :mri => Gem::Platform::RUBY,
+ :mri_18 => Gem::Platform::RUBY,
+ :mri_19 => Gem::Platform::RUBY,
+ :mri_20 => Gem::Platform::RUBY,
+ :mri_21 => Gem::Platform::RUBY,
+ :mswin => mswin,
+ :mswin_18 => mswin,
+ :mswin_19 => mswin,
+ :mswin_20 => mswin,
+ :mswin_21 => mswin,
+ :mswin64 => mswin64,
+ :mswin64_19 => mswin64,
+ :mswin64_20 => mswin64,
+ :mswin64_21 => mswin64,
+ :rbx => Gem::Platform::RUBY,
+ :ruby => Gem::Platform::RUBY,
+ :ruby_18 => Gem::Platform::RUBY,
+ :ruby_19 => Gem::Platform::RUBY,
+ :ruby_20 => Gem::Platform::RUBY,
+ :ruby_21 => Gem::Platform::RUBY,
+ :truffleruby => Gem::Platform::RUBY,
+ :x64_mingw => x64_mingw,
:x64_mingw_20 => x64_mingw,
:x64_mingw_21 => x64_mingw,
}.freeze
- gt_eq_0 = Gem::Requirement.new '>= 0'
- tilde_gt_1_8_0 = Gem::Requirement.new '~> 1.8.0'
- tilde_gt_1_9_0 = Gem::Requirement.new '~> 1.9.0'
- tilde_gt_2_0_0 = Gem::Requirement.new '~> 2.0.0'
- tilde_gt_2_1_0 = Gem::Requirement.new '~> 2.1.0'
+ gt_eq_0 = Gem::Requirement.new ">= 0"
+ tilde_gt_1_8_0 = Gem::Requirement.new "~> 1.8.0"
+ tilde_gt_1_9_0 = Gem::Requirement.new "~> 1.9.0"
+ tilde_gt_2_0_0 = Gem::Requirement.new "~> 2.0.0"
+ tilde_gt_2_1_0 = Gem::Requirement.new "~> 2.1.0"
VERSION_MAP = { # :nodoc:
- :jruby => gt_eq_0,
- :jruby_18 => tilde_gt_1_8_0,
- :jruby_19 => tilde_gt_1_9_0,
- :maglev => gt_eq_0,
- :mingw => gt_eq_0,
- :mingw_18 => tilde_gt_1_8_0,
- :mingw_19 => tilde_gt_1_9_0,
- :mingw_20 => tilde_gt_2_0_0,
- :mingw_21 => tilde_gt_2_1_0,
- :mri => gt_eq_0,
- :mri_18 => tilde_gt_1_8_0,
- :mri_19 => tilde_gt_1_9_0,
- :mri_20 => tilde_gt_2_0_0,
- :mri_21 => tilde_gt_2_1_0,
- :mswin => gt_eq_0,
- :mswin_18 => tilde_gt_1_8_0,
- :mswin_19 => tilde_gt_1_9_0,
- :mswin_20 => tilde_gt_2_0_0,
- :mswin_21 => tilde_gt_2_1_0,
- :mswin64 => gt_eq_0,
- :mswin64_19 => tilde_gt_1_9_0,
- :mswin64_20 => tilde_gt_2_0_0,
- :mswin64_21 => tilde_gt_2_1_0,
- :rbx => gt_eq_0,
- :ruby => gt_eq_0,
- :ruby_18 => tilde_gt_1_8_0,
- :ruby_19 => tilde_gt_1_9_0,
- :ruby_20 => tilde_gt_2_0_0,
- :ruby_21 => tilde_gt_2_1_0,
- :truffleruby => gt_eq_0,
- :x64_mingw => gt_eq_0,
+ :jruby => gt_eq_0,
+ :jruby_18 => tilde_gt_1_8_0,
+ :jruby_19 => tilde_gt_1_9_0,
+ :maglev => gt_eq_0,
+ :mingw => gt_eq_0,
+ :mingw_18 => tilde_gt_1_8_0,
+ :mingw_19 => tilde_gt_1_9_0,
+ :mingw_20 => tilde_gt_2_0_0,
+ :mingw_21 => tilde_gt_2_1_0,
+ :mri => gt_eq_0,
+ :mri_18 => tilde_gt_1_8_0,
+ :mri_19 => tilde_gt_1_9_0,
+ :mri_20 => tilde_gt_2_0_0,
+ :mri_21 => tilde_gt_2_1_0,
+ :mswin => gt_eq_0,
+ :mswin_18 => tilde_gt_1_8_0,
+ :mswin_19 => tilde_gt_1_9_0,
+ :mswin_20 => tilde_gt_2_0_0,
+ :mswin_21 => tilde_gt_2_1_0,
+ :mswin64 => gt_eq_0,
+ :mswin64_19 => tilde_gt_1_9_0,
+ :mswin64_20 => tilde_gt_2_0_0,
+ :mswin64_21 => tilde_gt_2_1_0,
+ :rbx => gt_eq_0,
+ :ruby => gt_eq_0,
+ :ruby_18 => tilde_gt_1_8_0,
+ :ruby_19 => tilde_gt_1_9_0,
+ :ruby_20 => tilde_gt_2_0_0,
+ :ruby_21 => tilde_gt_2_1_0,
+ :truffleruby => gt_eq_0,
+ :x64_mingw => gt_eq_0,
:x64_mingw_20 => tilde_gt_2_0_0,
:x64_mingw_21 => tilde_gt_2_1_0,
}.freeze
WINDOWS = { # :nodoc:
- :mingw => :only,
- :mingw_18 => :only,
- :mingw_19 => :only,
- :mingw_20 => :only,
- :mingw_21 => :only,
- :mri => :never,
- :mri_18 => :never,
- :mri_19 => :never,
- :mri_20 => :never,
- :mri_21 => :never,
- :mswin => :only,
- :mswin_18 => :only,
- :mswin_19 => :only,
- :mswin_20 => :only,
- :mswin_21 => :only,
- :mswin64 => :only,
- :mswin64_19 => :only,
- :mswin64_20 => :only,
- :mswin64_21 => :only,
- :rbx => :never,
- :ruby => :never,
- :ruby_18 => :never,
- :ruby_19 => :never,
- :ruby_20 => :never,
- :ruby_21 => :never,
- :x64_mingw => :only,
+ :mingw => :only,
+ :mingw_18 => :only,
+ :mingw_19 => :only,
+ :mingw_20 => :only,
+ :mingw_21 => :only,
+ :mri => :never,
+ :mri_18 => :never,
+ :mri_19 => :never,
+ :mri_20 => :never,
+ :mri_21 => :never,
+ :mswin => :only,
+ :mswin_18 => :only,
+ :mswin_19 => :only,
+ :mswin_20 => :only,
+ :mswin_21 => :only,
+ :mswin64 => :only,
+ :mswin64_19 => :only,
+ :mswin64_20 => :only,
+ :mswin64_21 => :only,
+ :rbx => :never,
+ :ruby => :never,
+ :ruby_18 => :never,
+ :ruby_19 => :never,
+ :ruby_20 => :never,
+ :ruby_21 => :never,
+ :x64_mingw => :only,
:x64_mingw_20 => :only,
:x64_mingw_21 => :only,
}.freeze
@@ -214,7 +215,7 @@ class Gem::RequestSet::GemDependencyAPI
git_source :github do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include? "/"
- "git://github.com/#{repo_name}.git"
+ "https://github.com/#{repo_name}.git"
end
git_source :bitbucket do |repo_name|
@@ -371,7 +372,7 @@ class Gem::RequestSet::GemDependencyAPI
duplicate = @dependencies.include? name
@dependencies[name] =
- if requirements.empty? and not source_set
+ if requirements.empty? && !source_set
Gem::Requirement.default
elsif source_set
Gem::Requirement.source_set
@@ -435,7 +436,6 @@ Gem dependencies file #{@path} requires #{name} more than once.
reference ||= ref
reference ||= branch
reference ||= tag
- reference ||= 'master'
if ref && branch
warn <<-WARNING
@@ -637,8 +637,8 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
# :development. Only one group may be specified.
def gemspec(options = {})
- name = options.delete(:name) || '{,*}'
- path = options.delete(:path) || '.'
+ name = options.delete(:name) || "{,*}"
+ path = options.delete(:path) || "."
development_group = options.delete(:development_group) || :development
spec = find_gemspec name, path
@@ -697,11 +697,11 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
def pin_gem_source(name, type = :default, source = nil)
source_description =
case type
- when :default then '(default)'
+ when :default then "(default)"
when :path then "path: #{source}"
when :git then "git: #{source}"
when :source then "source: #{source}"
- else '(unknown)'
+ else "(unknown)"
end
raise ArgumentError,
@@ -788,8 +788,8 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
engine_version = options[:engine_version]
raise ArgumentError,
- 'You must specify engine_version along with the Ruby engine' if
- engine and not engine_version
+ "You must specify engine_version along with the Ruby engine" if
+ engine && !engine_version
return true if @installing
@@ -800,7 +800,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
raise Gem::RubyVersionMismatch, message
end
- if engine and engine != Gem.ruby_engine
+ if engine && engine != Gem.ruby_engine
message = "Your Ruby engine is #{Gem.ruby_engine}, " +
"but your #{gem_deps_file} requires #{engine}"
diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb
index 8f8f142fff..9523fa7786 100644
--- a/lib/rubygems/request_set/lockfile.rb
+++ b/lib/rubygems/request_set/lockfile.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Parses a gem.deps.rb.lock file and constructs a LockSet containing the
# dependencies found inside. If the lock file is missing no LockSet is
@@ -56,10 +57,10 @@ class Gem::RequestSet::Lockfile
deps[name] = if [Gem::Resolver::VendorSpecification,
Gem::Resolver::GitSpecification].include? spec.class
- Gem::Requirement.source_set
- else
- requirement
- end
+ Gem::Requirement.source_set
+ else
+ requirement
+ end
end
deps
@@ -76,7 +77,7 @@ class Gem::RequestSet::Lockfile
@gem_deps_file = File.expand_path(gem_deps_file)
@gem_deps_dir = File.dirname(@gem_deps_file)
- if RUBY_VERSION < '2.7'
+ if RUBY_VERSION < "2.7"
@gem_deps_file.untaint unless gem_deps_file.tainted?
end
@@ -106,7 +107,7 @@ class Gem::RequestSet::Lockfile
out << " specs:"
requests.sort_by {|request| request.name }.each do |request|
- next if request.spec.name == 'bundler'
+ next if request.spec.name == "bundler"
platform = "-#{request.spec.platform}" unless
Gem::Platform::RUBY == request.spec.platform
@@ -156,7 +157,7 @@ class Gem::RequestSet::Lockfile
if dest.index(base) == 0
offset = dest[base.size + 1..-1]
- return '.' unless offset
+ return "." unless offset
offset
else
@@ -224,7 +225,7 @@ class Gem::RequestSet::Lockfile
def write
content = to_s
- File.open "#{@gem_deps_file}.lock", 'w' do |io|
+ File.open "#{@gem_deps_file}.lock", "w" do |io|
io.write content
end
end
@@ -236,4 +237,4 @@ class Gem::RequestSet::Lockfile
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 8c12b435af..1daec1fabd 100644
--- a/lib/rubygems/request_set/lockfile/parser.rb
+++ b/lib/rubygems/request_set/lockfile/parser.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
class Gem::RequestSet::Lockfile::Parser
###
# Parses lockfiles
@@ -19,18 +20,18 @@ class Gem::RequestSet::Lockfile::Parser
@tokens.skip :newline
case token.value
- when 'DEPENDENCIES' then
+ when "DEPENDENCIES" then
parse_DEPENDENCIES
- when 'GIT' then
+ when "GIT" then
parse_GIT
- when 'GEM' then
+ when "GEM" then
parse_GEM
- when 'PATH' then
+ when "PATH" then
parse_PATH
- when 'PLATFORMS' then
+ when "PLATFORMS" then
parse_PLATFORMS
else
- token = get until @tokens.empty? or peek.first == :section
+ token = get until @tokens.empty? || peek.first == :section
end
else
raise "BUG: unhandled token #{token.type} (#{token.value.inspect}) at line #{token.line} column #{token.column}"
@@ -44,7 +45,7 @@ class Gem::RequestSet::Lockfile::Parser
def get(expected_types = nil, expected_value = nil) # :nodoc:
token = @tokens.shift
- if expected_types and not Array(expected_types).include? token.type
+ if expected_types && !Array(expected_types).include?(token.type)
unget token
message = "unexpected token [#{token.type.inspect}, #{token.value.inspect}], " +
@@ -53,7 +54,7 @@ class Gem::RequestSet::Lockfile::Parser
raise Gem::RequestSet::Lockfile::ParseError.new message, token.column, token.line, @filename
end
- if expected_value and expected_value != token.value
+ if expected_value && expected_value != token.value
unget token
message = "unexpected token [#{token.type.inspect}, #{token.value.inspect}], " +
@@ -67,7 +68,7 @@ class Gem::RequestSet::Lockfile::Parser
end
def parse_DEPENDENCIES # :nodoc:
- while not @tokens.empty? and :text == peek.type do
+ while !@tokens.empty? && :text == peek.type do
token = get :text
requirements = []
@@ -110,8 +111,8 @@ class Gem::RequestSet::Lockfile::Parser
def parse_GEM # :nodoc:
sources = []
- while [:entry, 'remote'] == peek.first(2) do
- get :entry, 'remote'
+ while [:entry, "remote"] == peek.first(2) do
+ get :entry, "remote"
data = get(:text).value
skip :newline
@@ -120,14 +121,14 @@ class Gem::RequestSet::Lockfile::Parser
sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty?
- get :entry, 'specs'
+ get :entry, "specs"
skip :newline
set = Gem::Resolver::LockSet.new sources
last_specs = nil
- while not @tokens.empty? and :text == peek.type do
+ while !@tokens.empty? && :text == peek.type do
token = get :text
name = token.value
column = token.column
@@ -144,8 +145,8 @@ class Gem::RequestSet::Lockfile::Parser
type = token.type
data = token.value
- if type == :text and column == 4
- version, platform = data.split '-', 2
+ if type == :text && column == 4
+ version, platform = data.split "-", 2
platform =
platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
@@ -171,26 +172,26 @@ class Gem::RequestSet::Lockfile::Parser
end
def parse_GIT # :nodoc:
- get :entry, 'remote'
+ get :entry, "remote"
repository = get(:text).value
skip :newline
- get :entry, 'revision'
+ get :entry, "revision"
revision = get(:text).value
skip :newline
type = peek.type
value = peek.value
- if type == :entry and %w[branch ref tag].include? value
+ if type == :entry && %w[branch ref tag].include?(value)
get
get :text
skip :newline
end
- get :entry, 'specs'
+ get :entry, "specs"
skip :newline
@@ -199,7 +200,7 @@ class Gem::RequestSet::Lockfile::Parser
last_spec = nil
- while not @tokens.empty? and :text == peek.type do
+ while !@tokens.empty? && :text == peek.type do
token = get :text
name = token.value
column = token.column
@@ -214,7 +215,7 @@ class Gem::RequestSet::Lockfile::Parser
type = token.type
data = token.value
- if type == :text and column == 4
+ if type == :text && column == 4
last_spec = set.add_git_spec name, data, repository, revision, true
else
dependency = parse_dependency name, data
@@ -234,19 +235,19 @@ class Gem::RequestSet::Lockfile::Parser
end
def parse_PATH # :nodoc:
- get :entry, 'remote'
+ get :entry, "remote"
directory = get(:text).value
skip :newline
- get :entry, 'specs'
+ get :entry, "specs"
skip :newline
set = Gem::Resolver::VendorSet.new
last_spec = nil
- while not @tokens.empty? and :text == peek.first do
+ while !@tokens.empty? && :text == peek.first do
token = get :text
name = token.value
column = token.column
@@ -261,7 +262,7 @@ class Gem::RequestSet::Lockfile::Parser
type = token.type
data = token.value
- if type == :text and column == 4
+ if type == :text && column == 4
last_spec = set.add_vendor_gem name, directory
else
dependency = parse_dependency name, data
@@ -281,7 +282,7 @@ class Gem::RequestSet::Lockfile::Parser
end
def parse_PLATFORMS # :nodoc:
- while not @tokens.empty? and :text == peek.first do
+ while !@tokens.empty? && :text == peek.first do
name = get(:text).value
@platforms << name
@@ -331,7 +332,7 @@ class Gem::RequestSet::Lockfile::Parser
set.find_all(requirement)
end.compact.first
- specification && specification.version
+ specification&.version
end
##
diff --git a/lib/rubygems/request_set/lockfile/tokenizer.rb b/lib/rubygems/request_set/lockfile/tokenizer.rb
index 6918e8e1a5..e91a11ca93 100644
--- a/lib/rubygems/request_set/lockfile/tokenizer.rb
+++ b/lib/rubygems/request_set/lockfile/tokenizer.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/request_set/lockfile/parser'
+
+#) frozen_string_literal: true
+require_relative "parser"
class Gem::RequestSet::Lockfile::Tokenizer
Token = Struct.new :type, :value, :column, :line
@@ -26,7 +28,7 @@ class Gem::RequestSet::Lockfile::Tokenizer
end
def skip(type)
- @tokens.shift while not @tokens.empty? and peek.type == type
+ @tokens.shift while !@tokens.empty? && peek.type == type
end
##
@@ -57,7 +59,7 @@ class Gem::RequestSet::Lockfile::Tokenizer
private
def tokenize(input)
- require 'strscan'
+ require "strscan"
s = StringScanner.new input
until s.eos? do
diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb
index 16de45ad91..eed12c4914 100644
--- a/lib/rubygems/requirement.rb
+++ b/lib/rubygems/requirement.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require "rubygems/deprecate"
+
+require_relative "version"
##
# A Requirement is a set of one or more version restrictions. It supports a
@@ -10,19 +11,19 @@ require "rubygems/deprecate"
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 "|"
- PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc:
+ PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*" # :nodoc:
##
# A regular expression that matches a requirement
@@ -61,7 +62,7 @@ class Gem::Requirement
input
when Gem::Version, Array then
new input
- when '!' then
+ when "!" then
source_set
else
if input.respond_to? :to_str
@@ -73,11 +74,11 @@ class Gem::Requirement
end
def self.default
- new '>= 0'
+ new ">= 0"
end
def self.default_prerelease
- new '>= 0.a'
+ new ">= 0.a"
end
###
@@ -218,7 +219,7 @@ class Gem::Requirement
end
def encode_with(coder) # :nodoc:
- coder.add 'requirements', @requirements
+ coder.add "requirements", @requirements
end
##
@@ -230,7 +231,7 @@ class Gem::Requirement
end
def pretty_print(q) # :nodoc:
- q.group 1, 'Gem::Requirement.new(', ')' do
+ q.group 1, "Gem::Requirement.new(", ")" do
q.pp as_list
end
end
@@ -253,7 +254,7 @@ class Gem::Requirement
def specific?
return true if @requirements.length > 1 # GIGO, > 1, > 2 is silly
- not %w[> >=].include? @requirements.first.first # grab the operator
+ !%w[> >=].include? @requirements.first.first # grab the operator
end
def to_s # :nodoc:
diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb
index 71c35ea3d3..a912729b37 100644
--- a/lib/rubygems/resolver.rb
+++ b/lib/rubygems/resolver.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/dependency'
-require 'rubygems/exceptions'
-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
@@ -10,14 +11,14 @@ 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
# enabled for the resolver. This will display information about the state
# of the resolver while a set of dependencies is being resolved.
- DEBUG_RESOLVER = !ENV['DEBUG_RESOLVER'].nil?
+ DEBUG_RESOLVER = !ENV["DEBUG_RESOLVER"].nil?
##
# Set to true if all development dependencies should be considered.
@@ -74,7 +75,7 @@ class Gem::Resolver
case sets.length
when 0 then
- raise ArgumentError, 'one set in the composition must be non-nil'
+ raise ArgumentError, "one set in the composition must be non-nil"
when 1 then
sets.first
else
@@ -124,7 +125,7 @@ class Gem::Resolver
data = yield
$stderr.printf "%10s (%d entries)\n", stage.to_s.upcase, data.size
unless data.empty?
- require 'pp'
+ require "pp"
PP.pp data, $stderr
end
end
@@ -153,10 +154,10 @@ class Gem::Resolver
s.fetch_development_dependencies if @development
s.dependencies.reverse_each do |d|
- next if d.type == :development and not @development
- next if d.type == :development and @development_shallow and
+ next if d.type == :development && !@development
+ next if d.type == :development && @development_shallow &&
act.development?
- next if d.type == :development and @development_shallow and
+ next if d.type == :development && @development_shallow &&
act.parent
reqs << Gem::Resolver::DependencyRequest.new(d, act)
@@ -173,7 +174,7 @@ class Gem::Resolver
include Molinillo::UI
def output
- @output ||= debug? ? $stdout : File.open(IO::NULL, 'w')
+ @output ||= debug? ? $stdout : File.open(IO::NULL, "w")
end
def debug?
@@ -192,7 +193,7 @@ class Gem::Resolver
conflict = e.conflicts.values.first
raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement)
ensure
- @output.close if defined?(@output) and !debug?
+ @output.close if defined?(@output) && !debug?
end
##
@@ -246,7 +247,7 @@ class Gem::Resolver
sources.each do |source|
groups[source].
- sort_by {|spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }.
+ sort_by {|spec| [spec.version, spec.platform =~ Gem::Platform.local ? 1 : 0] }.
map {|spec| ActivationRequest.new spec, dependency }.
each {|activation_request| activation_requests << activation_request }
end
@@ -318,30 +319,30 @@ class Gem::Resolver
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 ae35681db9..d59859c102 100644
--- a/lib/rubygems/resolver/activation_request.rb
+++ b/lib/rubygems/resolver/activation_request.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Specifies a Specification object that should be activated. Also contains a
# dependency that was used to introduce this activation.
@@ -93,7 +94,7 @@ class Gem::Resolver::ActivationRequest
end
def inspect # :nodoc:
- '#<%s for %p from %s>' % [
+ "#<%s for %p from %s>" % [
self.class, @spec, @request
]
end
@@ -130,12 +131,12 @@ class Gem::Resolver::ActivationRequest
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Activation request', ']' do
+ q.group 2, "[Activation request", "]" do
q.breakable
q.pp @spec
q.breakable
- q.text ' for '
+ q.text " for "
q.pp @request
end
end
diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb
index 21c9b8920c..9b57b03192 100644
--- a/lib/rubygems/resolver/api_set.rb
+++ b/lib/rubygems/resolver/api_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The global rubygems pool, available via the rubygems.org API.
# Returns instances of APISpecification.
@@ -26,13 +27,13 @@ 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://index.rubygems.org/info/')
+ def initialize(dep_uri = "https://index.rubygems.org/info/")
super()
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] = [] }
@source = Gem::Source.new @uri
@@ -83,12 +84,12 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
end
def pretty_print(q) # :nodoc:
- q.group 2, '[APISet', ']' do
+ q.group 2, "[APISet", "]" do
q.breakable
q.text "URI: #{@dep_uri}"
q.breakable
- q.text 'gem names:'
+ q.text "gem names:"
q.pp @data.keys
end
end
diff --git a/lib/rubygems/resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb
index b5aa0b71d4..f26f82757e 100644
--- a/lib/rubygems/resolver/api_specification.rb
+++ b/lib/rubygems/resolver/api_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Represents a specification retrieved via the rubygems.org API.
#
@@ -40,10 +41,10 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
end
def ==(other) # :nodoc:
- self.class === other and
- @set == other.set and
- @name == other.name and
- @version == other.version and
+ self.class === other &&
+ @set == other.set &&
+ @name == other.name &&
+ @version == other.version &&
@platform == other.platform
end
@@ -62,7 +63,7 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
end
def pretty_print(q) # :nodoc:
- q.group 2, '[APISpecification', ']' do
+ q.group 2, "[APISpecification", "]" do
q.breakable
q.text "name: #{name}"
@@ -73,7 +74,7 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
q.text "platform: #{platform}"
q.breakable
- q.text 'dependencies:'
+ q.text "dependencies:"
q.breakable
q.pp @dependencies
diff --git a/lib/rubygems/resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb
index 300ea8015c..d75fa7c00a 100644
--- a/lib/rubygems/resolver/best_set.rb
+++ b/lib/rubygems/resolver/best_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The BestSet chooses the best available method to query a remote index.
#
@@ -25,7 +26,7 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
end
def find_all(req) # :nodoc:
- pick_sets if @remote and @sets.empty?
+ pick_sets if @remote && @sets.empty?
super
rescue Gem::RemoteFetcher::FetchError => e
@@ -35,15 +36,15 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
end
def prefetch(reqs) # :nodoc:
- pick_sets if @remote and @sets.empty?
+ pick_sets if @remote && @sets.empty?
super
end
def pretty_print(q) # :nodoc:
- q.group 2, '[BestSet', ']' do
+ q.group 2, "[BestSet", "]" do
q.breakable
- q.text 'sets:'
+ q.text "sets:"
q.breakable
q.pp @sets
@@ -63,7 +64,7 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
uri = uri + "."
raise error unless api_set = @sets.find do |set|
- Gem::Resolver::APISet === set and set.dep_uri == uri
+ Gem::Resolver::APISet === set && set.dep_uri == uri
end
index_set = Gem::Resolver::IndexSet.new api_set.source
diff --git a/lib/rubygems/resolver/composed_set.rb b/lib/rubygems/resolver/composed_set.rb
index 226da1e1e0..0991f0713e 100644
--- a/lib/rubygems/resolver/composed_set.rb
+++ b/lib/rubygems/resolver/composed_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A ComposedSet allows multiple sets to be queried like a single set.
#
diff --git a/lib/rubygems/resolver/conflict.rb b/lib/rubygems/resolver/conflict.rb
index 4c4588d7e8..dca41da51f 100644
--- a/lib/rubygems/resolver/conflict.rb
+++ b/lib/rubygems/resolver/conflict.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Used internally to indicate that a dependency conflicted
# with a spec that would be activated.
@@ -27,9 +28,9 @@ class Gem::Resolver::Conflict
end
def ==(other) # :nodoc:
- self.class === other and
- @dependency == other.dependency and
- @activated == other.activated and
+ self.class === other &&
+ @dependency == other.dependency &&
+ @activated == other.activated &&
@failed_dep == other.failed_dep
end
@@ -65,7 +66,7 @@ class Gem::Resolver::Conflict
matching = matching % [
dependency,
- alternates.join(', '),
+ alternates.join(", "),
]
end
@@ -97,21 +98,21 @@ class Gem::Resolver::Conflict
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Dependency conflict: ', ']' do
+ q.group 2, "[Dependency conflict: ", "]" do
q.breakable
- q.text 'activated '
+ q.text "activated "
q.pp @activated
q.breakable
- q.text ' dependency '
+ q.text " dependency "
q.pp @dependency
q.breakable
if @dependency == @failed_dep
- q.text ' failed'
+ q.text " failed"
else
- q.text ' failed dependency '
+ q.text " failed dependency "
q.pp @failed_dep
end
end
@@ -139,7 +140,7 @@ class Gem::Resolver::Conflict
end
end
- path = ['user request (gem command or Gemfile)'] if path.empty?
+ path = ["user request (gem command or Gemfile)"] if path.empty?
path
end
diff --git a/lib/rubygems/resolver/current_set.rb b/lib/rubygems/resolver/current_set.rb
index c3aa3a2c37..370e445089 100644
--- a/lib/rubygems/resolver/current_set.rb
+++ b/lib/rubygems/resolver/current_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A set which represents the installed gems. Respects
# all the normal settings that control where to look
diff --git a/lib/rubygems/resolver/dependency_request.rb b/lib/rubygems/resolver/dependency_request.rb
index 356aadb3b2..60b338277f 100644
--- a/lib/rubygems/resolver/dependency_request.rb
+++ b/lib/rubygems/resolver/dependency_request.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Used Internally. Wraps a Dependency object to also track which spec
# contained the Dependency.
@@ -95,12 +96,12 @@ class Gem::Resolver::DependencyRequest
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Dependency request ', ']' do
+ q.group 2, "[Dependency request ", "]" do
q.breakable
q.text @dependency.to_s
q.breakable
- q.text ' requested by '
+ q.text " requested by "
q.pp @requester
end
end
diff --git a/lib/rubygems/resolver/git_set.rb b/lib/rubygems/resolver/git_set.rb
index eac51f15ad..89342ff80d 100644
--- a/lib/rubygems/resolver/git_set.rb
+++ b/lib/rubygems/resolver/git_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A GitSet represents gems that are sourced from git repositories.
#
@@ -35,7 +36,7 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
def initialize # :nodoc:
super()
- @git = ENV['git'] || 'git'
+ @git = ENV["git"] || "git"
@need_submodules = {}
@repositories = {}
@root_dir = Gem.dir
@@ -104,7 +105,7 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
end
def pretty_print(q) # :nodoc:
- q.group 2, '[GitSet', ']' do
+ q.group 2, "[GitSet", "]" do
next if @repositories.empty?
q.breakable
diff --git a/lib/rubygems/resolver/git_specification.rb b/lib/rubygems/resolver/git_specification.rb
index 555dcffc22..e587c17d2a 100644
--- a/lib/rubygems/resolver/git_specification.rb
+++ b/lib/rubygems/resolver/git_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A GitSpecification represents a gem that is sourced from a git repository
# and is being loaded through a gem dependencies file through the +git:+
@@ -6,9 +7,9 @@
class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
def ==(other) # :nodoc:
- self.class === other and
- @set == other.set and
- @spec == other.spec and
+ self.class === other &&
+ @set == other.set &&
+ @spec == other.spec &&
@source == other.source
end
@@ -21,7 +22,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
@@ -35,7 +36,7 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
end
def pretty_print(q) # :nodoc:
- q.group 2, '[GitSpecification', ']' do
+ q.group 2, "[GitSpecification", "]" do
q.breakable
q.text "name: #{name}"
@@ -43,7 +44,7 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
q.text "version: #{version}"
q.breakable
- q.text 'dependencies:'
+ q.text "dependencies:"
q.breakable
q.pp dependencies
diff --git a/lib/rubygems/resolver/index_set.rb b/lib/rubygems/resolver/index_set.rb
index 9390e34255..5e8632c7d8 100644
--- a/lib/rubygems/resolver/index_set.rb
+++ b/lib/rubygems/resolver/index_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The global rubygems pool represented via the traditional
# source index.
@@ -53,14 +54,14 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set
end
def pretty_print(q) # :nodoc:
- q.group 2, '[IndexSet', ']' do
+ q.group 2, "[IndexSet", "]" do
q.breakable
- q.text 'sources:'
+ q.text "sources:"
q.breakable
q.pp @f.sources
q.breakable
- q.text 'specs:'
+ q.text "specs:"
q.breakable
diff --git a/lib/rubygems/resolver/index_specification.rb b/lib/rubygems/resolver/index_specification.rb
index 9ea76f40ba..6fac8c1487 100644
--- a/lib/rubygems/resolver/index_specification.rb
+++ b/lib/rubygems/resolver/index_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Represents a possible Specification object returned from IndexSet. Used to
# delay needed to download full Specification objects when only the +name+
@@ -21,7 +22,8 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
@name = name
@version = version
@source = source
- @platform = platform.to_s
+ @platform = Gem::Platform.new(platform.to_s)
+ @original_platform = platform.to_s
@spec = nil
end
@@ -66,11 +68,11 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
end
def inspect # :nodoc:
- '#<%s %s source %s>' % [self.class, full_name, @source]
+ "#<%s %s source %s>" % [self.class, full_name, @source]
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Index specification', ']' do
+ q.group 2, "[Index specification", "]" do
q.breakable
q.text full_name
@@ -80,7 +82,7 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
end
q.breakable
- q.text 'source '
+ q.text "source "
q.pp @source
end
end
@@ -91,7 +93,7 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
def spec # :nodoc:
@spec ||=
begin
- tuple = Gem::NameTuple.new @name, @version, @platform
+ tuple = Gem::NameTuple.new @name, @version, @original_platform
@source.fetch_spec tuple
end
diff --git a/lib/rubygems/resolver/installed_specification.rb b/lib/rubygems/resolver/installed_specification.rb
index 167ba1439e..b80f882c77 100644
--- a/lib/rubygems/resolver/installed_specification.rb
+++ b/lib/rubygems/resolver/installed_specification.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
##
# An InstalledSpecification represents a gem that is already installed
# locally.
class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
def ==(other) # :nodoc:
- self.class === other and
- @set == other.set and
+ self.class === other &&
+ @set == other.set &&
@spec == other.spec
end
@@ -30,7 +31,7 @@ class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
end
def pretty_print(q) # :nodoc:
- q.group 2, '[InstalledSpecification', ']' do
+ q.group 2, "[InstalledSpecification", "]" do
q.breakable
q.text "name: #{name}"
@@ -41,7 +42,7 @@ class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
q.text "platform: #{platform}"
q.breakable
- q.text 'dependencies:'
+ q.text "dependencies:"
q.breakable
q.pp spec.dependencies
end
diff --git a/lib/rubygems/resolver/installer_set.rb b/lib/rubygems/resolver/installer_set.rb
index 60181315b0..521d241fd5 100644
--- a/lib/rubygems/resolver/installer_set.rb
+++ b/lib/rubygems/resolver/installer_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A set of gems for installation sourced from remote sources and local .gem
# files
@@ -61,38 +62,37 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
found = find_all request
found.delete_if do |s|
- s.version.prerelease? and not s.local?
+ s.version.prerelease? && !s.local?
end unless dependency.prerelease?
found = found.select do |s|
- Gem::Source::SpecificFile === s.source or
- Gem::Platform::RUBY == s.platform or
- Gem::Platform.local === s.platform
+ Gem::Source::SpecificFile === s.source ||
+ Gem::Platform.match_spec?(s)
end
found = found.sort_by do |s|
- [s.version, s.platform == Gem::Platform::RUBY ? -1 : 1]
+ [s.version, Gem::Platform.sort_priority(s.platform)]
end
newest = found.last
+ unless newest
+ exc = Gem::UnsatisfiableDependencyError.new request
+ exc.errors = errors
+
+ raise exc
+ end
+
unless @force
- found_matching_metadata = found.select do |spec|
+ found_matching_metadata = found.reverse.find do |spec|
metadata_satisfied?(spec)
end
- if found_matching_metadata.empty?
- 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
+ if found_matching_metadata.nil?
+ ensure_required_ruby_version_met(newest.spec)
+ ensure_required_rubygems_version_met(newest.spec)
else
- newest = found_matching_metadata.last
+ newest = found_matching_metadata
end
end
@@ -111,14 +111,14 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
# Should local gems should be considered?
def consider_local? # :nodoc:
- @domain == :both or @domain == :local
+ @domain == :both || @domain == :local
end
##
# Should remote gems should be considered?
def consider_remote? # :nodoc:
- @domain == :both or @domain == :remote
+ @domain == :both || @domain == :remote
end
##
@@ -137,8 +137,8 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
dep = req.dependency
- return res if @ignore_dependencies and
- @always_install.none? {|spec| dep.match? spec }
+ return res if @ignore_dependencies &&
+ @always_install.none? {|spec| dep.match? spec }
name = dep.name
@@ -148,6 +148,8 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
res << Gem::Resolver::InstalledSpecification.new(self, gemspec)
end unless @ignore_installed
+ matching_local = []
+
if consider_local?
matching_local = @local.values.select do |spec, _|
req.match? spec
@@ -168,11 +170,7 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
end
end
- res.delete_if do |spec|
- spec.version.prerelease? and not dep.prerelease?
- end
-
- res.concat @remote_set.find_all req if consider_remote?
+ res.concat @remote_set.find_all req if consider_remote? && matching_local.empty?
res
end
@@ -190,7 +188,7 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
def inspect # :nodoc:
always_install = @always_install.map {|s| s.full_name }
- '#<%s domain: %s specs: %p always install: %p>' % [
+ "#<%s domain: %s specs: %p always install: %p>" % [
self.class, @domain, @specs.keys, always_install
]
end
@@ -219,16 +217,16 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
end
def pretty_print(q) # :nodoc:
- q.group 2, '[InstallerSet', ']' do
+ q.group 2, "[InstallerSet", "]" do
q.breakable
q.text "domain: #{@domain}"
q.breakable
- q.text 'specs: '
+ q.text "specs: "
q.pp @specs.keys
q.breakable
- q.text 'always install: '
+ q.text "always install: "
q.pp @always_install
end
end
diff --git a/lib/rubygems/resolver/local_specification.rb b/lib/rubygems/resolver/local_specification.rb
index 9c69c4ab74..50bf276345 100644
--- a/lib/rubygems/resolver/local_specification.rb
+++ b/lib/rubygems/resolver/local_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A LocalSpecification comes from a .gem file on the local filesystem.
@@ -17,7 +18,7 @@ class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification
end
def pretty_print(q) # :nodoc:
- q.group 2, '[LocalSpecification', ']' do
+ q.group 2, "[LocalSpecification", "]" do
q.breakable
q.text "name: #{name}"
@@ -28,7 +29,7 @@ class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification
q.text "platform: #{platform}"
q.breakable
- q.text 'dependencies:'
+ q.text "dependencies:"
q.breakable
q.pp dependencies
diff --git a/lib/rubygems/resolver/lock_set.rb b/lib/rubygems/resolver/lock_set.rb
index eabf217aba..8eec041bdc 100644
--- a/lib/rubygems/resolver/lock_set.rb
+++ b/lib/rubygems/resolver/lock_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A set of gems from a gem dependencies lockfile.
@@ -54,7 +55,7 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
dep = Gem::Dependency.new name, version
found = @specs.find do |spec|
- dep.matches_spec? spec and spec.platform == platform
+ dep.matches_spec?(spec) && spec.platform == platform
end
tuple = Gem::NameTuple.new found.name, found.version, found.platform
@@ -63,15 +64,15 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
end
def pretty_print(q) # :nodoc:
- q.group 2, '[LockSet', ']' do
+ q.group 2, "[LockSet", "]" do
q.breakable
- q.text 'source:'
+ q.text "source:"
q.breakable
q.pp @source
q.breakable
- q.text 'specs:'
+ q.text "specs:"
q.breakable
q.pp @specs.map {|spec| spec.full_name }
diff --git a/lib/rubygems/resolver/lock_specification.rb b/lib/rubygems/resolver/lock_specification.rb
index cdb8e4e425..06f912dd85 100644
--- a/lib/rubygems/resolver/lock_specification.rb
+++ b/lib/rubygems/resolver/lock_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The LockSpecification comes from a lockfile (Gem::RequestSet::Lockfile).
#
@@ -29,7 +30,7 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
def install(options = {})
destination = options[:install_dir] || Gem.dir
- if File.exist? File.join(destination, 'specifications', spec.spec_name)
+ if File.exist? File.join(destination, "specifications", spec.spec_name)
yield nil
return
end
@@ -45,7 +46,7 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
end
def pretty_print(q) # :nodoc:
- q.group 2, '[LockSpecification', ']' do
+ q.group 2, "[LockSpecification", "]" do
q.breakable
q.text "name: #{@name}"
@@ -59,7 +60,7 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
unless @dependencies.empty?
q.breakable
- q.text 'dependencies:'
+ q.text "dependencies:"
q.breakable
q.pp @dependencies
end
@@ -71,7 +72,7 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
def spec
@spec ||= Gem::Specification.find do |spec|
- spec.name == @name and spec.version == @version
+ spec.name == @name && spec.version == @version
end
@spec ||= Gem::Specification.new do |s|
diff --git a/lib/rubygems/resolver/molinillo.rb b/lib/rubygems/resolver/molinillo.rb
index 2357f41bee..d703505410 100644
--- a/lib/rubygems/resolver/molinillo.rb
+++ b/lib/rubygems/resolver/molinillo.rb
@@ -1,2 +1,3 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo'
+
+require_relative "molinillo/lib/molinillo"
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
index 16430a79f5..731a9e3e90 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'tsort'
+require_relative '../../../../tsort'
require_relative 'dependency_graph/log'
require_relative 'dependency_graph/vertex'
@@ -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
@@ -32,7 +32,7 @@ module Gem::Resolver::Molinillo
# all belong to the same graph.
# @return [Array<Vertex>] The sorted vertices.
def self.tsort(vertices)
- TSort.tsort(
+ Gem::TSort.tsort(
lambda { |b| vertices.each(&b) },
lambda { |v, &b| (v.successors & vertices).each(&b) }
)
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
index ada03a901c..4289902828 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
@@ -107,36 +107,42 @@ module Gem::Resolver::Molinillo
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)
+ full_message_for_conflict = opts.delete(:full_message_for_conflict) do
+ proc do |name, conflict|
+ o = "\n".dup << 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 << %( depends on)
+ t << %(\n)
+ depth += 1
end
- t << %(\n)
- depth += 1
- end
- t
- end.join("\n")
+ t
+ end.join("\n")
- additional_message_for_conflict.call(o, name, conflict)
+ additional_message_for_conflict.call(o, name, conflict)
- o
+ o
+ end
+ end
+
+ conflicts.sort.reduce(''.dup) do |o, (name, conflict)|
+ o << full_message_for_conflict.call(name, conflict)
end.strip
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 6b5ada7ade..86c249c404 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
@@ -2,5 +2,5 @@
module Gem::Resolver::Molinillo
# The version of Gem::Resolver::Molinillo.
- VERSION = '0.7.0'.freeze
+ VERSION = '0.8.0'.freeze
end
diff --git a/lib/rubygems/resolver/requirement_list.rb b/lib/rubygems/resolver/requirement_list.rb
index 5b51493c9a..6f86f0f412 100644
--- a/lib/rubygems/resolver/requirement_list.rb
+++ b/lib/rubygems/resolver/requirement_list.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The RequirementList is used to hold the requirements being considered
# while resolving a set of gems.
diff --git a/lib/rubygems/resolver/set.rb b/lib/rubygems/resolver/set.rb
index 8046e18ea1..243fee5fd5 100644
--- a/lib/rubygems/resolver/set.rb
+++ b/lib/rubygems/resolver/set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Resolver sets are used to look up specifications (and their
# dependencies) used in resolution. This set is abstract.
@@ -20,7 +21,6 @@ class Gem::Resolver::Set
attr_accessor :prerelease
def initialize # :nodoc:
- require 'uri'
@prerelease = false
@remote = true
@errors = []
diff --git a/lib/rubygems/resolver/source_set.rb b/lib/rubygems/resolver/source_set.rb
index bf8c23184e..296cf41078 100644
--- a/lib/rubygems/resolver/source_set.rb
+++ b/lib/rubygems/resolver/source_set.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
##
# The SourceSet chooses the best available method to query a remote index.
#
diff --git a/lib/rubygems/resolver/spec_specification.rb b/lib/rubygems/resolver/spec_specification.rb
index 7b665fe876..79a34d8063 100644
--- a/lib/rubygems/resolver/spec_specification.rb
+++ b/lib/rubygems/resolver/spec_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The Resolver::SpecSpecification contains common functionality for
# Resolver specifications that are backed by a Gem::Specification.
diff --git a/lib/rubygems/resolver/specification.rb b/lib/rubygems/resolver/specification.rb
index 8c6fc9afcf..d2098ef0e2 100644
--- a/lib/rubygems/resolver/specification.rb
+++ b/lib/rubygems/resolver/specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A Resolver::Specification contains a subset of the information
# contained in a Gem::Specification. Only the information necessary for
@@ -93,7 +94,7 @@ class Gem::Resolver::Specification
# specification.
def install(options = {})
- require 'rubygems/installer'
+ require_relative "../installer"
gem = download options
diff --git a/lib/rubygems/resolver/stats.rb b/lib/rubygems/resolver/stats.rb
index 64b458f504..9920976b2a 100644
--- a/lib/rubygems/resolver/stats.rb
+++ b/lib/rubygems/resolver/stats.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
class Gem::Resolver::Stats
def initialize
@max_depth = 0
@@ -32,7 +33,7 @@ class Gem::Resolver::Stats
@iterations += 1
end
- PATTERN = "%20s: %d\n".freeze
+ PATTERN = "%20s: %d\n"
def display
$stdout.puts "=== Resolver Statistics ==="
diff --git a/lib/rubygems/resolver/vendor_set.rb b/lib/rubygems/resolver/vendor_set.rb
index 48c640d8c9..293a1e3331 100644
--- a/lib/rubygems/resolver/vendor_set.rb
+++ b/lib/rubygems/resolver/vendor_set.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A VendorSet represents gems that have been unpacked into a specific
# directory that contains a gemspec.
@@ -69,7 +70,7 @@ class Gem::Resolver::VendorSet < Gem::Resolver::Set
end
def pretty_print(q) # :nodoc:
- q.group 2, '[VendorSet', ']' do
+ q.group 2, "[VendorSet", "]" do
next if @directories.empty?
q.breakable
diff --git a/lib/rubygems/resolver/vendor_specification.rb b/lib/rubygems/resolver/vendor_specification.rb
index 8dfe5940f2..ac78f54558 100644
--- a/lib/rubygems/resolver/vendor_specification.rb
+++ b/lib/rubygems/resolver/vendor_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A VendorSpecification represents a gem that has been unpacked into a project
# and is being loaded through a gem dependencies file through the +path:+
@@ -6,9 +7,9 @@
class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification
def ==(other) # :nodoc:
- self.class === other and
- @set == other.set and
- @spec == other.spec and
+ self.class === other &&
+ @set == other.set &&
+ @spec == other.spec &&
@source == other.source
end
diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb
index bba9afc9ff..5161e43ebb 100644
--- a/lib/rubygems/s3_uri_signer.rb
+++ b/lib/rubygems/s3_uri_signer.rb
@@ -1,5 +1,6 @@
-require 'digest'
-require 'rubygems/openssl'
+# frozen_string_literal: true
+
+require_relative "openssl"
##
# S3URISigner implements AWS SigV4 for S3 Source to avoid a dependency on the aws-sdk-* gems
@@ -87,7 +88,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
@@ -139,14 +140,14 @@ class Gem::S3URISigner
end
def ec2_metadata_credentials_json
- require 'net/http'
- require 'rubygems/request'
- require 'rubygems/request/connection_pools'
- require 'json'
+ require "net/http"
+ require_relative "request"
+ require_relative "request/connection_pools"
+ require "json"
iam_info = ec2_metadata_request(EC2_IAM_INFO)
# Expected format: arn:aws:iam::<id>:instance-profile/<role_name>
- role_name = iam_info['InstanceProfileArn'].split('/').last
+ role_name = iam_info["InstanceProfileArn"].split("/").last
ec2_metadata_request(EC2_IAM_SECURITY_CREDENTIALS + role_name)
end
@@ -171,6 +172,6 @@ class Gem::S3URISigner
end
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
+ EC2_IAM_INFO = "http://169.254.169.254/latest/meta-data/iam/info"
+ EC2_IAM_SECURITY_CREDENTIALS = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
end
diff --git a/lib/rubygems/safe_yaml.rb b/lib/rubygems/safe_yaml.rb
index e905052e1c..74ad25ca15 100644
--- a/lib/rubygems/safe_yaml.rb
+++ b/lib/rubygems/safe_yaml.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gem
###
@@ -24,33 +26,33 @@ module Gem
runtime
].freeze
- if ::YAML.respond_to? :safe_load
+ if ::Psych.respond_to? :safe_load
def self.safe_load(input)
- if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
- ::YAML.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true)
+ if Gem::Version.new(Psych::VERSION) >= Gem::Version.new("3.1.0.pre1")
+ ::Psych.safe_load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, aliases: true)
else
- ::YAML.safe_load(input, PERMITTED_CLASSES, PERMITTED_SYMBOLS, true)
+ ::Psych.safe_load(input, PERMITTED_CLASSES, PERMITTED_SYMBOLS, true)
end
end
def self.load(input)
- if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
- ::YAML.safe_load(input, permitted_classes: [::Symbol])
+ if Gem::Version.new(Psych::VERSION) >= Gem::Version.new("3.1.0.pre1")
+ ::Psych.safe_load(input, permitted_classes: [::Symbol])
else
- ::YAML.safe_load(input, [::Symbol])
+ ::Psych.safe_load(input, [::Symbol])
end
end
else
unless Gem::Deprecate.skip
- warn "YAML safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)."
+ warn "Psych safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0)."
end
def self.safe_load(input, *args)
- ::YAML.load input
+ ::Psych.load input
end
def self.load(input)
- ::YAML.load input
+ ::Psych.load input
end
end
end
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
index c80639af6d..73ee1e4bb9 100644
--- a/lib/rubygems/security.rb
+++ b/lib/rubygems/security.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/exceptions'
-require_relative 'openssl'
+require_relative "exceptions"
+require_relative "openssl"
##
# = Signing gems
@@ -152,6 +153,7 @@ require_relative 'openssl'
# 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
@@ -260,7 +262,7 @@ require_relative 'openssl'
# 2. Grab the public key from the gemspec
#
# gem spec some_signed_gem-1.0.gem cert_chain | \
-# ruby -ryaml -e 'puts YAML.load($stdin)' > public_key.crt
+# ruby -rpsych -e 'puts Psych.load($stdin)' > public_key.crt
#
# 3. Generate a SHA1 hash of the data.tar.gz
#
@@ -317,7 +319,6 @@ require_relative 'openssl'
# * 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
#
@@ -334,26 +335,28 @@ module Gem::Security
##
# Used internally to select the signing digest from all computed digests
- DIGEST_NAME = 'SHA256' # :nodoc:
+ DIGEST_NAME = "SHA256" # :nodoc:
##
- # Algorithm for creating the key pair used to sign gems
+ # Length of keys created by RSA and DSA keys
- KEY_ALGORITHM =
- if defined?(OpenSSL::PKey::RSA)
- OpenSSL::PKey::RSA
- end
+ RSA_DSA_KEY_LENGTH = 3072
+
+ ##
+ # Default algorithm to use when building a key pair
+
+ 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.
# Must be in the list returned by OpenSSL::Cipher.ciphers
- KEY_CIPHER = OpenSSL::Cipher.new('AES-256-CBC') if defined?(OpenSSL::Cipher)
+ KEY_CIPHER = OpenSSL::Cipher.new("AES-256-CBC") if defined?(OpenSSL::Cipher)
##
# One day in seconds
@@ -374,10 +377,10 @@ module Gem::Security
# * The certificate contains a subject key identifier
EXTENSIONS = {
- 'basicConstraints' => 'CA:FALSE',
- 'keyUsage' =>
- 'keyEncipherment,dataEncipherment,digitalSignature',
- 'subjectKeyIdentifier' => 'hash',
+ "basicConstraints" => "CA:FALSE",
+ "keyUsage" =>
+ "keyEncipherment,dataEncipherment,digitalSignature",
+ "subjectKeyIdentifier" => "hash",
}.freeze
def self.alt_name_or_x509_entry(certificate, x509_entry)
@@ -400,7 +403,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
@@ -419,6 +422,19 @@ module Gem::Security
end
##
+ # Gets the right public key from a PKey instance
+
+ def self.get_public_key(key)
+ # Ruby 3.0 (Ruby/OpenSSL 2.2) or later
+ return OpenSSL::PKey.read(key.public_to_der) if key.respond_to?(:public_to_der)
+ return key.public_key unless key.is_a?(OpenSSL::PKey::EC)
+
+ ec_key = OpenSSL::PKey::EC.new(key.group.curve_name)
+ ec_key.public_key = key.public_key
+ ec_key
+ end
+
+ ##
# 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+.
@@ -451,7 +467,7 @@ module Gem::Security
OpenSSL::Digest.new(algorithm)
end
else
- require 'digest'
+ require "digest"
def self.create_digest(algorithm = DIGEST_NAME)
Digest.const_get(algorithm).new
@@ -459,26 +475,39 @@ module Gem::Security
end
##
- # Creates a new key pair of the specified +length+ and +algorithm+. The
- # default is a 3072 bit RSA key.
-
- 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"
+ OpenSSL::PKey::EC.generate(EC_NAME)
+ else
+ raise Gem::Security::Exception,
+ "#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported."
+ end
+ end
end
##
# Turns +email_address+ into an OpenSSL::X509::Name
def self.email_to_name(email_address)
- email_address = email_address.gsub(/[^\w@.-]+/i, '_')
-
- cn, dcs = email_address.split '@'
+ email_address = email_address.gsub(/[^\w@.-]+/i, "_")
- dcs = dcs.split '.'
+ cn, dcs = email_address.split "@"
- name = "CN=#{cn}/#{dcs.map {|dc| "DC=#{dc}" }.join '/'}"
+ dcs = dcs.split "."
- OpenSSL::X509::Name.parse name
+ OpenSSL::X509::Name.new([
+ ["CN", cn],
+ *dcs.map {|dc| ["DC", dc] },
+ ])
end
##
@@ -492,7 +521,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.check_private_key(private_key)
unless expired_certificate.subject.to_s ==
expired_certificate.issuer.to_s
@@ -530,17 +559,17 @@ module Gem::Security
signee_key = certificate.public_key
alt_name = certificate.extensions.find do |extension|
- extension.oid == 'subjectAltName'
+ extension.oid == "subjectAltName"
end
- extensions = extensions.merge 'subjectAltName' => alt_name.value if
+ extensions = extensions.merge "subjectAltName" => alt_name.value if
alt_name
issuer_alt_name = signing_cert.extensions.find do |extension|
- extension.oid == 'subjectAltName'
+ extension.oid == "subjectAltName"
end
- extensions = extensions.merge 'issuerAltName' => issuer_alt_name.value if
+ extensions = extensions.merge "issuerAltName" => issuer_alt_name.value if
issuer_alt_name
signed = create_cert signee_subject, signee_key, age, extensions, serial
@@ -556,7 +585,7 @@ module Gem::Security
def self.trust_dir
return @trust_dir if @trust_dir
- dir = File.join Gem.user_home, '.gem', 'trust'
+ dir = File.join Gem.user_home, ".gem", "trust"
@trust_dir ||= Gem::Security::TrustDir.new dir
end
@@ -576,8 +605,8 @@ module Gem::Security
def self.write(pemmable, path, permissions = 0600, passphrase = nil, cipher = KEY_CIPHER)
path = File.expand_path path
- File.open path, 'wb', permissions do |io|
- if passphrase and cipher
+ File.open path, "wb", permissions do |io|
+ if passphrase && cipher
io.write pemmable.to_pem cipher, passphrase
else
io.write pemmable.to_pem
@@ -592,9 +621,9 @@ module Gem::Security
end
if Gem::HAVE_OPENSSL
- require 'rubygems/security/policy'
- require 'rubygems/security/policies'
- require 'rubygems/security/trust_dir'
+ 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/policies.rb b/lib/rubygems/security/policies.rb
index 8f6ad99316..bdfe9ed43f 100644
--- a/lib/rubygems/security/policies.rb
+++ b/lib/rubygems/security/policies.rb
@@ -1,17 +1,18 @@
# frozen_string_literal: true
+
module Gem::Security
##
# No security policy: all package signature checks are disabled.
NoSecurity = Policy.new(
- 'No Security',
- :verify_data => false,
- :verify_signer => false,
- :verify_chain => false,
- :verify_root => false,
- :only_trusted => false,
- :only_signed => false
+ "No Security",
+ :verify_data => false,
+ :verify_signer => false,
+ :verify_chain => false,
+ :verify_root => false,
+ :only_trusted => false,
+ :only_signed => false
)
##
@@ -23,13 +24,13 @@ module Gem::Security
# easily spoofed, and is not recommended.
AlmostNoSecurity = Policy.new(
- 'Almost No Security',
- :verify_data => true,
- :verify_signer => false,
- :verify_chain => false,
- :verify_root => false,
- :only_trusted => false,
- :only_signed => false
+ "Almost No Security",
+ :verify_data => true,
+ :verify_signer => false,
+ :verify_chain => false,
+ :verify_root => false,
+ :only_trusted => false,
+ :only_signed => false
)
##
@@ -40,13 +41,13 @@ module Gem::Security
# is not recommended.
LowSecurity = Policy.new(
- 'Low Security',
- :verify_data => true,
- :verify_signer => true,
- :verify_chain => false,
- :verify_root => false,
- :only_trusted => false,
- :only_signed => false
+ "Low Security",
+ :verify_data => true,
+ :verify_signer => true,
+ :verify_chain => false,
+ :verify_root => false,
+ :only_trusted => false,
+ :only_signed => false
)
##
@@ -59,13 +60,13 @@ module Gem::Security
# gem off as unsigned.
MediumSecurity = Policy.new(
- 'Medium Security',
- :verify_data => true,
- :verify_signer => true,
- :verify_chain => true,
- :verify_root => true,
- :only_trusted => true,
- :only_signed => false
+ "Medium Security",
+ :verify_data => true,
+ :verify_signer => true,
+ :verify_chain => true,
+ :verify_root => true,
+ :only_trusted => true,
+ :only_signed => false
)
##
@@ -78,37 +79,37 @@ module Gem::Security
# a reasonable guarantee that the contents of the gem have not been altered.
HighSecurity = Policy.new(
- 'High Security',
- :verify_data => true,
- :verify_signer => true,
- :verify_chain => true,
- :verify_root => true,
- :only_trusted => true,
- :only_signed => true
+ "High Security",
+ :verify_data => true,
+ :verify_signer => true,
+ :verify_chain => true,
+ :verify_root => true,
+ :only_trusted => true,
+ :only_signed => true
)
##
# Policy used to verify a certificate and key when signing a gem
SigningPolicy = Policy.new(
- 'Signing Policy',
- :verify_data => false,
- :verify_signer => true,
- :verify_chain => true,
- :verify_root => true,
- :only_trusted => false,
- :only_signed => false
+ "Signing Policy",
+ :verify_data => false,
+ :verify_signer => true,
+ :verify_chain => true,
+ :verify_root => true,
+ :only_trusted => false,
+ :only_signed => false
)
##
# Hash of configured security policies
Policies = {
- 'NoSecurity' => NoSecurity,
- 'AlmostNoSecurity' => AlmostNoSecurity,
- 'LowSecurity' => LowSecurity,
- 'MediumSecurity' => MediumSecurity,
- 'HighSecurity' => HighSecurity,
+ "NoSecurity" => NoSecurity,
+ "AlmostNoSecurity" => AlmostNoSecurity,
+ "LowSecurity" => LowSecurity,
+ "MediumSecurity" => MediumSecurity,
+ "HighSecurity" => HighSecurity,
# SigningPolicy is not intended for use by `gem -P` so do not list it
}.freeze
diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
index 7629d64796..9b9eac46bf 100644
--- a/lib/rubygems/security/policy.rb
+++ b/lib/rubygems/security/policy.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/user_interaction'
+
+require_relative "../user_interaction"
##
# A Gem::Security::Policy object encapsulates the settings for verifying
@@ -53,8 +54,8 @@ class Gem::Security::Policy
# and is valid for the given +time+.
def check_chain(chain, time)
- raise Gem::Security::Exception, 'missing signing chain' unless chain
- raise Gem::Security::Exception, 'empty signing chain' if chain.empty?
+ raise Gem::Security::Exception, "missing signing chain" unless chain
+ raise Gem::Security::Exception, "empty signing chain" if chain.empty?
begin
chain.each_cons 2 do |issuer, cert|
@@ -83,21 +84,21 @@ class Gem::Security::Policy
# If the +issuer+ is +nil+ no verification is performed.
def check_cert(signer, issuer, time)
- raise Gem::Security::Exception, 'missing signing certificate' unless
+ raise Gem::Security::Exception, "missing signing certificate" unless
signer
message = "certificate #{signer.subject}"
- if not_before = signer.not_before and not_before > time
+ if (not_before = signer.not_before) && not_before > time
raise Gem::Security::Exception,
"#{message} not valid before #{not_before}"
end
- if not_after = signer.not_after and not_after < time
+ if (not_after = signer.not_after) && not_after < time
raise Gem::Security::Exception, "#{message} not valid after #{not_after}"
end
- if issuer and not signer.verify issuer.public_key
+ if issuer && !signer.verify(issuer.public_key)
raise Gem::Security::Exception,
"#{message} was not issued by #{issuer.subject}"
end
@@ -109,15 +110,15 @@ class Gem::Security::Policy
# Ensures the public key of +key+ matches the public key in +signer+
def check_key(signer, key)
- unless signer and key
+ unless signer && key
return true unless @only_signed
- raise Gem::Security::Exception, 'missing key or signature'
+ raise Gem::Security::Exception, "missing key or signature"
end
raise Gem::Security::Exception,
"certificate #{signer.subject} does not match the signing key" unless
- signer.public_key.to_pem == key.public_key.to_pem
+ signer.check_private_key(key)
true
end
@@ -127,11 +128,11 @@ class Gem::Security::Policy
# +time+.
def check_root(chain, time)
- raise Gem::Security::Exception, 'missing signing chain' unless chain
+ raise Gem::Security::Exception, "missing signing chain" unless chain
root = chain.first
- raise Gem::Security::Exception, 'missing root certificate' unless root
+ raise Gem::Security::Exception, "missing root certificate" unless root
raise Gem::Security::Exception,
"root certificate #{root.subject} is not self-signed " +
@@ -146,11 +147,11 @@ class Gem::Security::Policy
# the digests of the two certificates match according to +digester+
def check_trust(chain, digester, trust_dir)
- raise Gem::Security::Exception, 'missing signing chain' unless chain
+ raise Gem::Security::Exception, "missing signing chain" unless chain
root = chain.first
- raise Gem::Security::Exception, 'missing root certificate' unless root
+ raise Gem::Security::Exception, "missing root certificate" unless root
path = Gem::Security.trust_dir.cert_path root
@@ -164,9 +165,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,
@@ -182,7 +183,7 @@ class Gem::Security::Policy
def subject(certificate) # :nodoc:
certificate.extensions.each do |extension|
- next unless extension.oid == 'subjectAltName'
+ next unless extension.oid == "subjectAltName"
return extension.value
end
@@ -206,7 +207,7 @@ class Gem::Security::Policy
# If +key+ is given it is used to validate the signing certificate.
def verify(chain, key = nil, digests = {}, signatures = {},
- full_name = '(unknown)')
+ full_name = "(unknown)")
if signatures.empty?
if @only_signed
raise Gem::Security::Exception,
@@ -230,8 +231,8 @@ class Gem::Security::Policy
end
if @verify_data
- raise Gem::Security::Exception, 'no digests provided (probable bug)' if
- signer_digests.nil? or signer_digests.empty?
+ raise Gem::Security::Exception, "no digests provided (probable bug)" if
+ signer_digests.nil? || signer_digests.empty?
else
signer_digests = {}
end
@@ -248,7 +249,7 @@ class Gem::Security::Policy
if @only_trusted
check_trust chain, digester, trust_dir
- elsif signatures.empty? and digests.empty?
+ elsif signatures.empty? && digests.empty?
# trust is irrelevant if there's no signatures to verify
else
alert_warning "#{subject signer} is not trusted for #{full_name}"
diff --git a/lib/rubygems/security/signer.rb b/lib/rubygems/security/signer.rb
index 6c85ab08d2..d76af03eb8 100644
--- a/lib/rubygems/security/signer.rb
+++ b/lib/rubygems/security/signer.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
+
##
# Basic OpenSSL-based package signing class.
-require "rubygems/user_interaction"
+require_relative "../user_interaction"
class Gem::Security::Signer
include Gem::UserInteraction
@@ -42,7 +43,7 @@ class Gem::Security::Signer
def self.re_sign_cert(expired_cert, expired_cert_path, private_key)
return unless expired_cert.not_after < Time.now
- expiry = expired_cert.not_after.strftime('%Y%m%d%H%M%S')
+ expiry = expired_cert.not_after.strftime("%Y%m%d%H%M%S")
expired_cert_file = "#{File.basename(expired_cert_path)}.expired.#{expiry}"
new_expired_cert_path = File.join(Gem.user_home, ".gem", expired_cert_file)
@@ -83,8 +84,8 @@ class Gem::Security::Signer
@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
@@ -105,7 +106,7 @@ 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 # rubocop:disable Performance/StartWith
@@ -139,9 +140,9 @@ class Gem::Security::Signer
def sign(data)
return unless @key
- raise Gem::Security::Exception, 'no certs provided' if @cert_chain.empty?
+ raise Gem::Security::Exception, "no certs provided" if @cert_chain.empty?
- if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now
+ if @cert_chain.length == 1 && @cert_chain.last.not_after < Time.now
alert("Your certificate has expired, trying to re-sign it...")
re_sign_key(
@@ -177,13 +178,12 @@ 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
if disk_key.to_pem == @key.to_pem && disk_cert == old_cert.to_pem
- expiry = old_cert.not_after.strftime('%Y%m%d%H%M%S')
+ expiry = old_cert.not_after.strftime("%Y%m%d%H%M%S")
old_cert_file = "gem-public_cert.pem.expired.#{expiry}"
old_cert_path = File.join(Gem.user_home, ".gem", old_cert_file)
diff --git a/lib/rubygems/security/trust_dir.rb b/lib/rubygems/security/trust_dir.rb
index 456947274c..4de33068f9 100644
--- a/lib/rubygems/security/trust_dir.rb
+++ b/lib/rubygems/security/trust_dir.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The TrustDir manages the trusted certificates for gem signature
# verification.
@@ -8,7 +9,7 @@ class Gem::Security::TrustDir
# Default permissions for the trust directory and its contents
DEFAULT_PERMISSIONS = {
- :trust_dir => 0700,
+ :trust_dir => 0700,
:trusted_cert => 0600,
}.freeze
@@ -41,7 +42,7 @@ class Gem::Security::TrustDir
def each_certificate
return enum_for __method__ unless block_given?
- glob = File.join @dir, '*.pem'
+ glob = File.join @dir, "*.pem"
Dir[glob].each do |certificate_file|
begin
@@ -92,7 +93,7 @@ class Gem::Security::TrustDir
destination = cert_path certificate
- File.open destination, 'wb', 0600 do |io|
+ File.open destination, "wb", 0600 do |io|
io.write certificate.to_pem
io.chmod(@permissions[:trusted_cert])
end
@@ -104,7 +105,7 @@ class Gem::Security::TrustDir
# permissions.
def verify
- require 'fileutils'
+ require "fileutils"
if File.exist? @dir
raise Gem::Security::Exception,
"trust directory #{@dir} is not a directory" unless
diff --git a/lib/rubygems/security_option.rb b/lib/rubygems/security_option.rb
index 3403aaaf05..f288ebd047 100644
--- a/lib/rubygems/security_option.rb
+++ b/lib/rubygems/security_option.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
+require_relative "../rubygems"
# forward-declare
@@ -19,23 +20,23 @@ 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
- add_option(:"Install/Update", '-P', '--trust-policy POLICY',
+ add_option(:"Install/Update", "-P", "--trust-policy POLICY",
Gem::Security::Policy,
- 'Specify gem trust policy') do |value, options|
+ "Specify gem trust policy") do |value, options|
options[:security_policy] = value
end
end
diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb
deleted file mode 100644
index 2c2805f31c..0000000000
--- a/lib/rubygems/server.rb
+++ /dev/null
@@ -1,882 +0,0 @@
-# frozen_string_literal: true
-require 'zlib'
-require 'erb'
-require 'uri'
-
-require 'rubygems'
-require 'rubygems/rdoc'
-
-##
-# Gem::Server and allows users to serve gems for consumption by
-# `gem --remote-install`.
-#
-# gem_server starts an HTTP server on the given port and serves the following:
-# * "/" - Browsing of gem spec files for installed gems
-# * "/specs.#{Gem.marshal_version}.gz" - specs name/version/platform index
-# * "/latest_specs.#{Gem.marshal_version}.gz" - latest specs
-# name/version/platform index
-# * "/quick/" - Individual gemspecs
-# * "/gems" - Direct access to download the installable gems
-# * "/rdoc?q=" - Search for installed rdoc documentation
-#
-# == Usage
-#
-# gem_server = Gem::Server.new Gem.dir, 8089, false
-# gem_server.run
-#
-#--
-# TODO Refactor into a real WEBrick servlet to remove code duplication.
-
-class Gem::Server
- attr_reader :spec_dirs
-
- include ERB::Util
- include Gem::UserInteraction
-
- SEARCH = <<-ERB.freeze
- <form class="headerSearch" name="headerSearchForm" method="get" action="/rdoc">
- <div id="search" style="float:right">
- <label for="q">Filter/Search</label>
- <input id="q" type="text" style="width:10em" name="q">
- <button type="submit" style="display:none"></button>
- </div>
- </form>
- ERB
-
- DOC_TEMPLATE = <<-'ERB'.freeze
- <?xml version="1.0" encoding="iso-8859-1"?>
- <!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" xml:lang="en" lang="en">
- <head>
- <title>RubyGems Documentation Index</title>
- <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
- </head>
- <body>
- <div id="fileHeader">
-<%= SEARCH %>
- <h1>RubyGems Documentation Index</h1>
- </div>
- <!-- banner header -->
-
- <div id="bodyContent">
- <div id="contextContent">
- <div id="description">
- <h1>Summary</h1>
- <p>There are <%=values["gem_count"]%> gems installed:</p>
- <p>
- <%= values["specs"].map { |v| "<a href=\"##{u v["name"]}\">#{h v["name"]}</a>" }.join ', ' %>.
- <h1>Gems</h1>
-
- <dl>
- <% values["specs"].each do |spec| %>
- <dt>
- <% if spec["first_name_entry"] then %>
- <a name="<%=h spec["name"]%>"></a>
- <% end %>
-
- <b><%=h spec["name"]%> <%=h spec["version"]%></b>
-
- <% if spec["ri_installed"] || spec["rdoc_installed"] then %>
- <a href="<%=spec["doc_path"]%>">[rdoc]</a>
- <% else %>
- <span title="rdoc not installed">[rdoc]</span>
- <% end %>
-
- <% if spec["homepage"] then %>
- <a href="<%=uri_encode spec["homepage"]%>" title="<%=h spec["homepage"]%>">[www]</a>
- <% else %>
- <span title="no homepage available">[www]</span>
- <% end %>
-
- <% if spec["has_deps"] then %>
- - depends on
- <%= spec["dependencies"].map { |v| "<a href=\"##{u v["name"]}\">#{h v["name"]}</a>" }.join ', ' %>.
- <% end %>
- </dt>
- <dd>
- <%=spec["summary"]%>
- <% if spec["executables"] then %>
- <br/>
-
- <% if spec["only_one_executable"] then %>
- Executable is
- <% else %>
- Executables are
- <%end%>
-
- <%= spec["executables"].map { |v| "<span class=\"context-item-name\">#{h v["executable"]}</span>"}.join ', ' %>.
-
- <%end%>
- <br/>
- <br/>
- </dd>
- <% end %>
- </dl>
-
- </div>
- </div>
- </div>
- <div id="validator-badges">
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
- </div>
- </body>
- </html>
- ERB
-
- # CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
- RDOC_CSS = <<-CSS.freeze
-body {
- font-family: Verdana,Arial,Helvetica,sans-serif;
- font-size: 90%;
- margin: 0;
- margin-left: 40px;
- padding: 0;
- background: white;
-}
-
-h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
-h1 { font-size: 150%; }
-h2,h3,h4 { margin-top: 1em; }
-
-a { background: #eef; color: #039; text-decoration: none; }
-a:hover { background: #039; color: #eef; }
-
-/* Override the base stylesheets Anchor inside a table cell */
-td > a {
- background: transparent;
- color: #039;
- text-decoration: none;
-}
-
-/* and inside a section title */
-.section-title > a {
- background: transparent;
- color: #eee;
- text-decoration: none;
-}
-
-/* === Structural elements =================================== */
-
-div#index {
- margin: 0;
- margin-left: -40px;
- padding: 0;
- font-size: 90%;
-}
-
-
-div#index a {
- margin-left: 0.7em;
-}
-
-div#index .section-bar {
- margin-left: 0px;
- padding-left: 0.7em;
- background: #ccc;
- font-size: small;
-}
-
-
-div#classHeader, div#fileHeader {
- width: auto;
- color: white;
- padding: 0.5em 1.5em 0.5em 1.5em;
- margin: 0;
- margin-left: -40px;
- border-bottom: 3px solid #006;
-}
-
-div#classHeader a, div#fileHeader a {
- background: inherit;
- color: white;
-}
-
-div#classHeader td, div#fileHeader td {
- background: inherit;
- color: white;
-}
-
-
-div#fileHeader {
- background: #057;
-}
-
-div#classHeader {
- background: #048;
-}
-
-
-.class-name-in-header {
- font-size: 180%;
- font-weight: bold;
-}
-
-
-div#bodyContent {
- padding: 0 1.5em 0 1.5em;
-}
-
-div#description {
- padding: 0.5em 1.5em;
- background: #efefef;
- border: 1px dotted #999;
-}
-
-div#description h1,h2,h3,h4,h5,h6 {
- color: #125;;
- background: transparent;
-}
-
-div#validator-badges {
- text-align: center;
-}
-div#validator-badges img { border: 0; }
-
-div#copyright {
- color: #333;
- background: #efefef;
- font: 0.75em sans-serif;
- margin-top: 5em;
- margin-bottom: 0;
- padding: 0.5em 2em;
-}
-
-
-/* === Classes =================================== */
-
-table.header-table {
- color: white;
- font-size: small;
-}
-
-.type-note {
- font-size: small;
- color: #DEDEDE;
-}
-
-.xxsection-bar {
- background: #eee;
- color: #333;
- padding: 3px;
-}
-
-.section-bar {
- color: #333;
- border-bottom: 1px solid #999;
- margin-left: -20px;
-}
-
-
-.section-title {
- background: #79a;
- color: #eee;
- padding: 3px;
- margin-top: 2em;
- margin-left: -30px;
- border: 1px solid #999;
-}
-
-.top-aligned-row { vertical-align: top }
-.bottom-aligned-row { vertical-align: bottom }
-
-/* --- Context section classes ----------------------- */
-
-.context-row { }
-.context-item-name { font-family: monospace; font-weight: bold; color: black; }
-.context-item-value { font-size: small; color: #448; }
-.context-item-desc { color: #333; padding-left: 2em; }
-
-/* --- Method classes -------------------------- */
-.method-detail {
- background: #efefef;
- padding: 0;
- margin-top: 0.5em;
- margin-bottom: 1em;
- border: 1px dotted #ccc;
-}
-.method-heading {
- color: black;
- background: #ccc;
- border-bottom: 1px solid #666;
- padding: 0.2em 0.5em 0 0.5em;
-}
-.method-signature { color: black; background: inherit; }
-.method-name { font-weight: bold; }
-.method-args { font-style: italic; }
-.method-description { padding: 0 0.5em 0 0.5em; }
-
-/* --- Source code sections -------------------- */
-
-a.source-toggle { font-size: 90%; }
-div.method-source-code {
- background: #262626;
- color: #ffdead;
- margin: 1em;
- padding: 0.5em;
- border: 1px dashed #999;
- overflow: hidden;
-}
-
-div.method-source-code pre { color: #ffdead; overflow: hidden; }
-
-/* --- Ruby keyword styles --------------------- */
-
-.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
-
-.ruby-constant { color: #7fffd4; background: transparent; }
-.ruby-keyword { color: #00ffff; background: transparent; }
-.ruby-ivar { color: #eedd82; background: transparent; }
-.ruby-operator { color: #00ffee; background: transparent; }
-.ruby-identifier { color: #ffdead; background: transparent; }
-.ruby-node { color: #ffa07a; background: transparent; }
-.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
-.ruby-regexp { color: #ffa07a; background: transparent; }
-.ruby-value { color: #7fffd4; background: transparent; }
- CSS
-
- RDOC_NO_DOCUMENTATION = <<-'ERB'.freeze
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!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" xml:lang="en" lang="en">
- <head>
- <title>Found documentation</title>
- <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
- </head>
- <body>
- <div id="fileHeader">
-<%= SEARCH %>
- <h1>No documentation found</h1>
- </div>
-
- <div id="bodyContent">
- <div id="contextContent">
- <div id="description">
- <p>No gems matched <%= h query.inspect %></p>
-
- <p>
- Back to <a href="/">complete gem index</a>
- </p>
-
- </div>
- </div>
- </div>
- <div id="validator-badges">
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
- </div>
- </body>
-</html>
- ERB
-
- RDOC_SEARCH_TEMPLATE = <<-'ERB'.freeze
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!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" xml:lang="en" lang="en">
- <head>
- <title>Found documentation</title>
- <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
- </head>
- <body>
- <div id="fileHeader">
-<%= SEARCH %>
- <h1>Found documentation</h1>
- </div>
- <!-- banner header -->
-
- <div id="bodyContent">
- <div id="contextContent">
- <div id="description">
- <h1>Summary</h1>
- <p><%=doc_items.length%> documentation topics found.</p>
- <h1>Topics</h1>
-
- <dl>
- <% doc_items.each do |doc_item| %>
- <dt>
- <b><%=doc_item[:name]%></b>
- <a href="<%=u doc_item[:url]%>">[rdoc]</a>
- </dt>
- <dd>
- <%=h doc_item[:summary]%>
- <br/>
- <br/>
- </dd>
- <% end %>
- </dl>
-
- <p>
- Back to <a href="/">complete gem index</a>
- </p>
-
- </div>
- </div>
- </div>
- <div id="validator-badges">
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
- </div>
- </body>
-</html>
- ERB
-
- def self.run(options)
- new(options[:gemdir], options[:port], options[:daemon],
- options[:launch], options[:addresses]).run
- end
-
- def initialize(gem_dirs, port, daemon, launch = nil, addresses = nil)
- 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
-
- @gem_dirs = Array gem_dirs
- @port = port
- @daemon = daemon
- @launch = launch
- @addresses = addresses
-
- logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
- @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
-
- @spec_dirs = @gem_dirs.map {|gem_dir| File.join gem_dir, 'specifications' }
- @spec_dirs.reject! {|spec_dir| !File.directory? spec_dir }
-
- reset_gems
-
- @have_rdoc_4_plus = nil
- end
-
- def add_date(res)
- res['date'] = @spec_dirs.map do |spec_dir|
- File.stat(spec_dir).mtime
- end.max
- end
-
- def uri_encode(str)
- str.gsub(URI::UNSAFE) do |match|
- match.each_byte.map {|c| sprintf('%%%02X', c.ord) }.join
- end
- end
-
- def doc_root(gem_name)
- if have_rdoc_4_plus?
- "/doc_root/#{u gem_name}/"
- else
- "/doc_root/#{u gem_name}/rdoc/index.html"
- end
- end
-
- def have_rdoc_4_plus?
- @have_rdoc_4_plus ||=
- Gem::Requirement.new('>= 4.0.0.preview2').satisfied_by? Gem::RDoc.rdoc_version
- end
-
- def latest_specs(req, res)
- reset_gems
-
- res['content-type'] = 'application/x-gzip'
-
- add_date res
-
- latest_specs = Gem::Specification.latest_specs
-
- specs = latest_specs.sort.map do |spec|
- platform = spec.original_platform || Gem::Platform::RUBY
- [spec.name, spec.version, platform]
- end
-
- specs = Marshal.dump specs
-
- if req.path =~ /\.gz$/
- specs = Gem::Util.gzip specs
- res['content-type'] = 'application/x-gzip'
- else
- res['content-type'] = 'application/octet-stream'
- end
-
- if req.request_method == 'HEAD'
- res['content-length'] = specs.length
- else
- res.body << specs
- end
- end
-
- ##
- # Creates server sockets based on the addresses option. If no addresses
- # were given a server socket for all interfaces is created.
-
- def listen(addresses = @addresses)
- addresses = [nil] unless addresses
-
- listeners = 0
-
- addresses.each do |address|
- begin
- @server.listen address, @port
- @server.listeners[listeners..-1].each do |listener|
- host, port = listener.addr.values_at 2, 1
- host = "[#{host}]" if host =~ /:/ # we don't reverse lookup
- say "Server started at http://#{host}:#{port}"
- end
-
- listeners = @server.listeners.length
- rescue SystemCallError
- next
- end
- end
-
- if @server.listeners.empty?
- say "Unable to start a server."
- say "Check for running servers or your --bind and --port arguments"
- terminate_interaction 1
- end
- end
-
- def prerelease_specs(req, res)
- reset_gems
-
- res['content-type'] = 'application/x-gzip'
-
- add_date res
-
- specs = Gem::Specification.select do |spec|
- spec.version.prerelease?
- end.sort.map do |spec|
- platform = spec.original_platform || Gem::Platform::RUBY
- [spec.name, spec.version, platform]
- end
-
- specs = Marshal.dump specs
-
- if req.path =~ /\.gz$/
- specs = Gem::Util.gzip specs
- res['content-type'] = 'application/x-gzip'
- else
- res['content-type'] = 'application/octet-stream'
- end
-
- if req.request_method == 'HEAD'
- res['content-length'] = specs.length
- else
- res.body << specs
- end
- end
-
- def quick(req, res)
- reset_gems
-
- res['content-type'] = 'text/plain'
- add_date res
-
- case req.request_uri.path
- when %r{^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)\.gemspec\.rz$} then
- marshal_format, full_name = $1, $2
- specs = Gem::Specification.find_all_by_full_name(full_name)
-
- selector = full_name.inspect
-
- if specs.empty?
- res.status = 404
- res.body = "No gems found matching #{selector}"
- elsif specs.length > 1
- res.status = 500
- res.body = "Multiple gems found matching #{selector}"
- elsif marshal_format
- res['content-type'] = 'application/x-deflate'
- res.body << Gem.deflate(Marshal.dump(specs.first))
- end
- else
- raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found."
- end
- end
-
- def root(req, res)
- reset_gems
-
- add_date res
-
- raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." unless
- req.path == '/'
-
- specs = []
- total_file_count = 0
-
- Gem::Specification.each do |spec|
- total_file_count += spec.files.size
- deps = spec.dependencies.map do |dep|
- {
- "name" => dep.name,
- "type" => dep.type,
- "version" => dep.requirement.to_s,
- }
- end
-
- deps = deps.sort_by {|dep| [dep["name"].downcase, dep["version"]] }
- deps.last["is_last"] = true unless deps.empty?
-
- # executables
- executables = spec.executables.sort.collect {|exec| {"executable" => exec} }
- executables = nil if executables.empty?
- executables.last["is_last"] = true if executables
-
- # Pre-process spec homepage for safety reasons
- begin
- homepage_uri = URI.parse(spec.homepage)
- if [URI::HTTP, URI::HTTPS].member? homepage_uri.class
- homepage_uri = spec.homepage
- else
- homepage_uri = "."
- end
- rescue URI::InvalidURIError
- homepage_uri = "."
- end
-
- specs << {
- "authors" => spec.authors.sort.join(", "),
- "date" => spec.date.to_s,
- "dependencies" => deps,
- "doc_path" => doc_root(spec.full_name),
- "executables" => executables,
- "only_one_executable" => (executables && executables.size == 1),
- "full_name" => spec.full_name,
- "has_deps" => !deps.empty?,
- "homepage" => homepage_uri,
- "name" => spec.name,
- "rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?,
- "ri_installed" => Gem::RDoc.new(spec).ri_installed?,
- "summary" => spec.summary,
- "version" => spec.version.to_s,
- }
- end
-
- specs << {
- "authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others",
- "dependencies" => [],
- "doc_path" => doc_root("rubygems-#{Gem::VERSION}"),
- "executables" => [{"executable" => 'gem', "is_last" => true}],
- "only_one_executable" => true,
- "full_name" => "rubygems-#{Gem::VERSION}",
- "has_deps" => false,
- "homepage" => "https://guides.rubygems.org/",
- "name" => 'rubygems',
- "ri_installed" => true,
- "summary" => "RubyGems itself",
- "version" => Gem::VERSION,
- }
-
- specs = specs.sort_by {|spec| [spec["name"].downcase, spec["version"]] }
- specs.last["is_last"] = true
-
- # tag all specs with first_name_entry
- last_spec = nil
- specs.each do |spec|
- is_first = last_spec.nil? || (last_spec["name"].downcase != spec["name"].downcase)
- spec["first_name_entry"] = is_first
- last_spec = spec
- end
-
- # create page from template
- template = ERB.new(DOC_TEMPLATE)
- res['content-type'] = 'text/html'
-
- values = { "gem_count" => specs.size.to_s, "specs" => specs,
- "total_file_count" => total_file_count.to_s }
-
- # suppress 1.9.3dev warning about unused variable
- values = values
-
- result = template.result binding
- res.body = result
- end
-
- ##
- # Can be used for quick navigation to the rdoc documentation. You can then
- # define a search shortcut for your browser. E.g. in Firefox connect
- # 'shortcut:rdoc' to http://localhost:8808/rdoc?q=%s template. Then you can
- # directly open the ActionPack documentation by typing 'rdoc actionp'. If
- # there are multiple hits for the search term, they are presented as a list
- # with links.
- #
- # Search algorithm aims for an intuitive search:
- # 1. first try to find the gems and documentation folders which name
- # starts with the search term
- # 2. search for entries, that *contain* the search term
- # 3. show all the gems
- #
- # If there is only one search hit, user is immediately redirected to the
- # documentation for the particular gem, otherwise a list with results is
- # shown.
- #
- # === Additional trick - install documentation for Ruby core
- #
- # Note: please adjust paths accordingly use for example 'locate yaml.rb' and
- # 'gem environment' to identify directories, that are specific for your
- # local installation
- #
- # 1. install Ruby sources
- # cd /usr/src
- # sudo apt-get source ruby
- #
- # 2. generate documentation
- # rdoc -o /usr/lib/ruby/gems/1.8/doc/core/rdoc \
- # /usr/lib/ruby/1.8 ruby1.8-1.8.7.72
- #
- # By typing 'rdoc core' you can now access the core documentation
-
- def rdoc(req, res)
- query = req.query['q']
- show_rdoc_for_pattern("#{query}*", res) && return
- show_rdoc_for_pattern("*#{query}*", res) && return
-
- template = ERB.new RDOC_NO_DOCUMENTATION
-
- res['content-type'] = 'text/html'
- res.body = template.result binding
- end
-
- ##
- # Updates the server to use the latest installed gems.
-
- def reset_gems # :nodoc:
- Gem::Specification.dirs = @gem_dirs
- end
-
- ##
- # Returns true and prepares http response, if rdoc for the requested gem
- # name pattern was found.
- #
- # The search is based on the file system content, not on the gems metadata.
- # This allows additional documentation folders like 'core' for the Ruby core
- # documentation - just put it underneath the main doc folder.
-
- def show_rdoc_for_pattern(pattern, res)
- found_gems = Dir.glob("{#{@gem_dirs.join ','}}/doc/#{pattern}").select do |path|
- File.exist? File.join(path, 'rdoc/index.html')
- end
- case found_gems.length
- when 0
- return false
- when 1
- new_path = File.basename(found_gems[0])
- res.status = 302
- res['Location'] = doc_root new_path
- return true
- else
- doc_items = []
- found_gems.each do |file_name|
- base_name = File.basename(file_name)
- doc_items << {
- :name => base_name,
- :url => doc_root(new_path),
- :summary => '',
- }
- end
-
- template = ERB.new(RDOC_SEARCH_TEMPLATE)
- res['content-type'] = 'text/html'
- result = template.result binding
- res.body = result
- return true
- end
- end
-
- def run
- listen
-
- WEBrick::Daemon.start if @daemon
-
- @server.mount_proc "/specs.#{Gem.marshal_version}", method(:specs)
- @server.mount_proc "/specs.#{Gem.marshal_version}.gz", method(:specs)
-
- @server.mount_proc "/latest_specs.#{Gem.marshal_version}",
- method(:latest_specs)
- @server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz",
- method(:latest_specs)
-
- @server.mount_proc "/prerelease_specs.#{Gem.marshal_version}",
- method(:prerelease_specs)
- @server.mount_proc "/prerelease_specs.#{Gem.marshal_version}.gz",
- method(:prerelease_specs)
-
- @server.mount_proc "/quick/", method(:quick)
-
- @server.mount_proc("/gem-server-rdoc-style.css") do |req, res|
- res['content-type'] = 'text/css'
- add_date res
- res.body << RDOC_CSS
- end
-
- @server.mount_proc "/", method(:root)
-
- @server.mount_proc "/rdoc", method(:rdoc)
-
- file_handlers = {
- '/gems' => '/cache/',
- }
-
- if have_rdoc_4_plus?
- @server.mount '/doc_root', RDoc::Servlet, '/doc_root'
- else
- file_handlers['/doc_root'] = '/doc/'
- end
-
- @gem_dirs.each do |gem_dir|
- file_handlers.each do |mount_point, mount_dir|
- @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
- File.join(gem_dir, mount_dir), true)
- end
- end
-
- trap("INT") { @server.shutdown; exit! }
- trap("TERM") { @server.shutdown; exit! }
-
- launch if @launch
-
- @server.start
- end
-
- def specs(req, res)
- reset_gems
-
- add_date res
-
- specs = Gem::Specification.sort_by(&:sort_obj).map do |spec|
- platform = spec.original_platform || Gem::Platform::RUBY
- [spec.name, spec.version, platform]
- end
-
- specs = Marshal.dump specs
-
- if req.path =~ /\.gz$/
- specs = Gem::Util.gzip specs
- res['content-type'] = 'application/x-gzip'
- else
- res['content-type'] = 'application/octet-stream'
- end
-
- if req.request_method == 'HEAD'
- res['content-length'] = specs.length
- else
- res.body << specs
- end
- end
-
- def launch
- listeners = @server.listeners.map{|l| l.addr[2] }
-
- # TODO: 0.0.0.0 == any, not localhost.
- host = listeners.any?{|l| l == '0.0.0.0' } ? 'localhost' : listeners.first
-
- say "Launching browser to http://#{host}:#{@port}"
-
- system("#{@launch} http://#{host}:#{@port}")
- end
-end
diff --git a/lib/rubygems/shellwords.rb b/lib/rubygems/shellwords.rb
new file mode 100644
index 0000000000..741dccb363
--- /dev/null
+++ b/lib/rubygems/shellwords.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+autoload :Shellwords, "shellwords"
diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb
index 37e03cdfae..aa0cbc1641 100644
--- a/lib/rubygems/source.rb
+++ b/lib/rubygems/source.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require "rubygems/text"
+require_relative "text"
##
# A Source knows how to list and fetch gems from a RubyGems marshal index.
#
@@ -12,9 +12,9 @@ class Gem::Source
include Gem::Text
FILES = { # :nodoc:
- :released => 'specs',
- :latest => 'latest_specs',
- :prerelease => 'prerelease_specs',
+ :released => "specs",
+ :latest => "latest_specs",
+ :prerelease => "prerelease_specs",
}.freeze
##
@@ -26,15 +26,8 @@ class Gem::Source
# Creates a new Source which will use the index located at +uri+.
def initialize(uri)
- begin
- unless uri.kind_of? URI
- uri = URI.parse(uri.to_s)
- end
- rescue URI::InvalidURIError
- raise if Gem::Source == self.class
- end
-
- @uri = uri
+ require_relative "uri"
+ @uri = Gem::Uri.parse!(uri)
@update_cache = nil
end
@@ -69,7 +62,7 @@ class Gem::Source
end
def ==(other) # :nodoc:
- self.class === other and @uri == other.uri
+ self.class === other && @uri == other.uri
end
alias_method :eql?, :== # :nodoc:
@@ -78,15 +71,15 @@ class Gem::Source
# Returns a Set that can fetch specifications from this source.
def dependency_resolver_set # :nodoc:
- return Gem::Resolver::IndexSet.new self if 'file' == uri.scheme
+ return Gem::Resolver::IndexSet.new self if "file" == uri.scheme
fetch_uri = if uri.host == "rubygems.org"
- index_uri = uri.dup
- index_uri.host = "index.rubygems.org"
- index_uri
- else
- uri
- end
+ index_uri = uri.dup
+ index_uri.host = "index.rubygems.org"
+ index_uri
+ else
+ uri
+ end
bundler_api_uri = enforce_trailing_slash(fetch_uri)
@@ -148,7 +141,7 @@ class Gem::Source
return spec if spec
end
- source_uri.path << '.rz'
+ source_uri.path << ".rz"
spec = fetcher.fetch_path source_uri
spec = Gem::Util.inflate spec
@@ -157,7 +150,7 @@ class Gem::Source
require "fileutils"
FileUtils.mkdir_p cache_dir
- File.open local_spec, 'wb' do |io|
+ File.open local_spec, "wb" do |io|
io.write spec
end
end
@@ -216,13 +209,13 @@ class Gem::Source
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Remote:', ']' do
+ q.group 2, "[Remote:", "]" do
q.breakable
q.text @uri.to_s
if api = uri
q.breakable
- q.text 'API URI: '
+ q.text "API URI: "
q.text api.to_s
end
end
@@ -236,13 +229,13 @@ class Gem::Source
private
def enforce_trailing_slash(uri)
- uri.merge(uri.path.gsub(/\/+$/, '') + '/')
+ 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 9876adc24e..7ac685f978 100644
--- a/lib/rubygems/source/git.rb
+++ b/lib/rubygems/source/git.rb
@@ -49,16 +49,16 @@ class Gem::Source::Git < Gem::Source
# will be checked out when the gem is installed.
def initialize(name, repository, reference, submodules = false)
- super repository
-
+ require_relative "../uri"
+ @uri = Gem::Uri.parse(repository)
@name = name
@repository = repository
- @reference = reference
+ @reference = reference || "HEAD"
@need_submodules = submodules
@remote = true
@root_dir = Gem.dir
- @git = ENV['git'] || 'git'
+ @git = ENV["git"] || "git"
end
def <=>(other)
@@ -76,10 +76,10 @@ class Gem::Source::Git < Gem::Source
end
def ==(other) # :nodoc:
- super and
- @name == other.name and
- @repository == other.repository and
- @reference == other.reference and
+ super &&
+ @name == other.name &&
+ @repository == other.repository &&
+ @reference == other.reference &&
@need_submodules == other.need_submodules
end
@@ -92,17 +92,18 @@ class Gem::Source::Git < Gem::Source
return false unless File.exist? repo_cache_dir
unless File.exist? install_dir
- system @git, 'clone', '--quiet', '--no-checkout',
+ system @git, "clone", "--quiet", "--no-checkout",
repo_cache_dir, install_dir
end
Dir.chdir install_dir do
- system @git, 'fetch', '--quiet', '--force', '--tags', install_dir
+ system @git, "fetch", "--quiet", "--force", "--tags", install_dir
- success = system @git, 'reset', '--quiet', '--hard', rev_parse
+ success = system @git, "reset", "--quiet", "--hard", rev_parse
if @need_submodules
- _, status = Open3.capture2e(@git, 'submodule', 'update', '--quiet', '--init', '--recursive')
+ require "open3"
+ _, status = Open3.capture2e(@git, "submodule", "update", "--quiet", "--init", "--recursive")
success &&= status.success?
end
@@ -119,11 +120,11 @@ class Gem::Source::Git < Gem::Source
if File.exist? repo_cache_dir
Dir.chdir repo_cache_dir do
- system @git, 'fetch', '--quiet', '--force', '--tags',
- @repository, 'refs/heads/*:refs/heads/*'
+ system @git, "fetch", "--quiet", "--force", "--tags",
+ @repository, "refs/heads/*:refs/heads/*"
end
else
- system @git, 'clone', '--quiet', '--bare', '--no-hardlinks',
+ system @git, "clone", "--quiet", "--bare", "--no-hardlinks",
@repository, repo_cache_dir
end
end
@@ -132,7 +133,7 @@ class Gem::Source::Git < Gem::Source
# Directory where git gems get unpacked and so-forth.
def base_dir # :nodoc:
- File.join @root_dir, 'bundler'
+ File.join @root_dir, "bundler"
end
##
@@ -154,11 +155,11 @@ class Gem::Source::Git < Gem::Source
def install_dir # :nodoc:
return unless File.exist? repo_cache_dir
- File.join base_dir, 'gems', "#{@name}-#{dir_shortref}"
+ File.join base_dir, "gems", "#{@name}-#{dir_shortref}"
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Git: ', ']' do
+ q.group 2, "[Git: ", "]" do
q.breakable
q.text @repository
@@ -171,7 +172,7 @@ class Gem::Source::Git < Gem::Source
# The directory where the git gem's repository will be cached.
def repo_cache_dir # :nodoc:
- File.join @root_dir, 'cache', 'bundler', 'git', "#{@name}-#{uri_hash}"
+ File.join @root_dir, "cache", "bundler", "git", "#{@name}-#{uri_hash}"
end
##
@@ -181,7 +182,7 @@ class Gem::Source::Git < Gem::Source
hash = nil
Dir.chdir repo_cache_dir do
- hash = Gem::Util.popen(@git, 'rev-parse', @reference).strip
+ hash = Gem::Util.popen(@git, "rev-parse", @reference).strip
end
raise Gem::Exception,
@@ -200,7 +201,7 @@ class Gem::Source::Git < Gem::Source
return [] unless install_dir
Dir.chdir install_dir do
- Dir['{,*,*/*}.gemspec'].map do |spec_file|
+ Dir["{,*,*/*}.gemspec"].map do |spec_file|
directory = File.dirname spec_file
file = File.basename spec_file
@@ -210,7 +211,7 @@ class Gem::Source::Git < Gem::Source
spec.base_dir = base_dir
spec.extension_dir =
- File.join base_dir, 'extensions', Gem::Platform.local.to_s,
+ File.join base_dir, "extensions", Gem::Platform.local.to_s,
Gem.extension_api_version, "#{name}-#{dir_shortref}"
spec.full_gem_path = File.dirname spec.loaded_from if spec
@@ -225,16 +226,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{/$},''
+ 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 7e1dd7af5a..f5d3f06d6a 100644
--- a/lib/rubygems/source/installed.rb
+++ b/lib/rubygems/source/installed.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Represents an installed gem. This is used for dependency resolution.
@@ -33,6 +34,6 @@ class Gem::Source::Installed < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.text '[Installed]'
+ q.text "[Installed]"
end
end
diff --git a/lib/rubygems/source/local.rb b/lib/rubygems/source/local.rb
index 078b06203f..5068b0b906 100644
--- a/lib/rubygems/source/local.rb
+++ b/lib/rubygems/source/local.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# The local source finds gems in the current directory for fulfilling
# dependencies.
@@ -29,7 +30,7 @@ class Gem::Source::Local < Gem::Source
end
def inspect # :nodoc:
- keys = @specs ? @specs.keys.sort : 'NOT LOADED'
+ keys = @specs ? @specs.keys.sort : "NOT LOADED"
"#<%s specs: %p>" % [self.class, keys]
end
@@ -121,7 +122,7 @@ class Gem::Source::Local < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.group 2, '[Local gems:', ']' do
+ q.group 2, "[Local gems:", "]" do
q.breakable
q.seplist @specs.keys do |v|
q.text v.full_name
diff --git a/lib/rubygems/source/lock.rb b/lib/rubygems/source/lock.rb
index 49f097467b..f9388bbd61 100644
--- a/lib/rubygems/source/lock.rb
+++ b/lib/rubygems/source/lock.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A Lock source wraps an installed gem's source and sorts before other sources
# during dependency resolution. This allows RubyGems to prefer gems from
diff --git a/lib/rubygems/source/specific_file.rb b/lib/rubygems/source/specific_file.rb
index 24db1440dd..61965c2644 100644
--- a/lib/rubygems/source/specific_file.rb
+++ b/lib/rubygems/source/specific_file.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# A source representing a single .gem file. This is used for installation of
# local gems.
@@ -42,7 +43,7 @@ class Gem::Source::SpecificFile < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.group 2, '[SpecificFile:', ']' do
+ q.group 2, "[SpecificFile:", "]" do
q.breakable
q.text @path
end
diff --git a/lib/rubygems/source/vendor.rb b/lib/rubygems/source/vendor.rb
index 543acf1388..12161b8cf5 100644
--- a/lib/rubygems/source/vendor.rb
+++ b/lib/rubygems/source/vendor.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# This represents a vendored source that is similar to an installed gem.
diff --git a/lib/rubygems/source_list.rb b/lib/rubygems/source_list.rb
index 13b25b63dc..7abe796409 100644
--- a/lib/rubygems/source_list.rb
+++ b/lib/rubygems/source_list.rb
@@ -48,16 +48,12 @@ class Gem::SourceList
# String.
def <<(obj)
- require "uri"
-
src = case obj
- when URI
- Gem::Source.new(obj)
- when Gem::Source
- obj
- else
- Gem::Source.new(URI.parse(obj))
- end
+ when Gem::Source
+ obj
+ else
+ Gem::Source.new(obj)
+ end
@sources << src unless @sources.include?(src)
src
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index b2bcadc49c..a5a4fa0c0f 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -1,9 +1,10 @@
# 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.
@@ -91,14 +92,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_gem?(tup.platform, tup.name)
+ if matching_platform && !Gem::Platform.match_gem?(tup.platform, tup.name)
pm = (
rejected_specs[dependency] ||= \
Gem::PlatformMismatch.new(tup.name, tup.version))
@@ -121,7 +122,7 @@ class Gem::SpecFetcher
end
end
- tuples = tuples.sort_by {|x| x[0] }
+ tuples = tuples.sort_by {|x| x[0].version }
return [tuples, errors]
end
@@ -171,19 +172,19 @@ class Gem::SpecFetcher
# alternative gem names.
def suggest_gems_from_name(gem_name, type = :latest, num_results = 5)
- gem_name = gem_name.downcase.tr('_-', '')
+ 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?
- [n.name, 0] if n.name.downcase.tr('_-', '').include?(gem_name)
+ [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('_-', '')
+ distance = levenshtein_distance gem_name, n.name.downcase.tr("_-", "")
next if distance >= max
return [n.name] if distance == 0
[n.name, distance]
@@ -191,10 +192,10 @@ class Gem::SpecFetcher
end
matches = if matches.empty? && type != :prerelease
- suggest_gems_from_name gem_name, :prerelease
- else
- matches.uniq.sort_by {|name, dist| dist }
- end
+ suggest_gems_from_name gem_name, :prerelease
+ else
+ matches.uniq.sort_by {|name, dist| dist }
+ end
matches.map {|name, dist| name }.uniq.first(num_results)
end
@@ -216,27 +217,27 @@ class Gem::SpecFetcher
@sources.each_source do |source|
begin
names = case type
- when :latest
- tuples_for source, :latest
- when :released
- tuples_for source, :released
- when :complete
- names =
- tuples_for(source, :prerelease, true) +
- tuples_for(source, :released)
-
- names.sort
- when :abs_latest
- names =
- tuples_for(source, :prerelease, true) +
- tuples_for(source, :latest)
-
- names.sort
- when :prerelease
- tuples_for(source, :prerelease)
- else
- raise Gem::Exception, "Unknown type - :#{type}"
- end
+ when :latest
+ tuples_for source, :latest
+ when :released
+ tuples_for source, :released
+ when :complete
+ names =
+ tuples_for(source, :prerelease, true) +
+ tuples_for(source, :released)
+
+ names.sort
+ when :abs_latest
+ names =
+ tuples_for(source, :prerelease, true) +
+ tuples_for(source, :latest)
+
+ names.sort
+ when :prerelease
+ tuples_for(source, :prerelease)
+ else
+ raise Gem::Exception, "Unknown type - :#{type}"
+ end
rescue Gem::RemoteFetcher::FetchError => e
errors << Gem::SourceFetchProblem.new(source, e)
else
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index ff345bf7a3..7611e1ba1f 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -1,16 +1,17 @@
# frozen_string_literal: true
-# -*- coding: utf-8 -*-
+
+#
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/deprecate'
-require 'rubygems/basic_specification'
-require 'rubygems/stub_specification'
-require 'rubygems/specification_policy'
-require 'rubygems/util/list'
+require_relative "deprecate"
+require_relative "basic_specification"
+require_relative "stub_specification"
+require_relative "platform"
+require_relative "util/list"
##
# The Specification class contains the information for a gem. Typically
@@ -74,40 +75,36 @@ class Gem::Specification < Gem::BasicSpecification
# key should be equal to the CURRENT_SPECIFICATION_VERSION.
SPECIFICATION_VERSION_HISTORY = { # :nodoc:
- -1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'],
- 1 => [
+ -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]"',
],
2 => [
'Added "required_rubygems_version"',
- 'Now forward-compatible with future versions',
+ "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:
-1 => 16,
- 1 => 16,
- 2 => 16,
- 3 => 17,
- 4 => 18,
+ 1 => 16,
+ 2 => 16,
+ 3 => 17,
+ 4 => 18,
}.freeze
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 = Thread::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:
@@ -128,52 +125,52 @@ class Gem::Specification < Gem::BasicSpecification
# Map of attribute names to default values.
@@default_value = {
- :authors => [],
- :autorequire => nil,
- :bindir => 'bin',
- :cert_chain => [],
- :date => nil,
- :dependencies => [],
- :description => nil,
- :email => nil,
- :executables => [],
- :extensions => [],
- :extra_rdoc_files => [],
- :files => [],
- :homepage => nil,
- :licenses => [],
- :metadata => {},
- :name => nil,
- :platform => Gem::Platform::RUBY,
- :post_install_message => nil,
- :rdoc_options => [],
- :require_paths => ['lib'],
- :required_ruby_version => Gem::Requirement.default,
+ :authors => [],
+ :autorequire => nil,
+ :bindir => "bin",
+ :cert_chain => [],
+ :date => nil,
+ :dependencies => [],
+ :description => nil,
+ :email => nil,
+ :executables => [],
+ :extensions => [],
+ :extra_rdoc_files => [],
+ :files => [],
+ :homepage => nil,
+ :licenses => [],
+ :metadata => {},
+ :name => nil,
+ :platform => Gem::Platform::RUBY,
+ :post_install_message => nil,
+ :rdoc_options => [],
+ :require_paths => ["lib"],
+ :required_ruby_version => Gem::Requirement.default,
:required_rubygems_version => Gem::Requirement.default,
- :requirements => [],
- :rubygems_version => Gem::VERSION,
- :signing_key => nil,
- :specification_version => CURRENT_SPECIFICATION_VERSION,
- :summary => nil,
- :test_files => [],
- :version => nil,
+ :requirements => [],
+ :rubygems_version => Gem::VERSION,
+ :signing_key => nil,
+ :specification_version => CURRENT_SPECIFICATION_VERSION,
+ :summary => nil,
+ :test_files => [],
+ :version => nil,
}.freeze
# rubocop:disable Style/MutableConstant
- INITIALIZE_CODE_FOR_DEFAULTS = { } # :nodoc:
+ INITIALIZE_CODE_FOR_DEFAULTS = {} # :nodoc:
# rubocop:enable Style/MutableConstant
@@default_value.each do |k,v|
INITIALIZE_CODE_FOR_DEFAULTS[k] = case v
- when [], {}, true, false, nil, Numeric, Symbol
- v.inspect
- when String
- v.dump
- when Numeric
- "default_value(:#{k})"
- else
- "default_value(:#{k}).dup"
- end
+ when [], {}, true, false, nil, Numeric, Symbol
+ v.inspect
+ when String
+ v.dump
+ when Numeric
+ "default_value(:#{k})"
+ else
+ "default_value(:#{k}).dup"
+ end
end
@@attributes = @@default_value.keys.sort_by {|s| s.to_s }
@@ -182,13 +179,19 @@ class Gem::Specification < Gem::BasicSpecification
@@default_value[k].nil?
end
- @@stubs = nil
- @@stubs_by_name = {}
+ def self.clear_specs # :nodoc:
+ @@all = nil
+ @@stubs = nil
+ @@stubs_by_name = {}
+ @@spec_with_requirable_file = {}
+ @@active_stub_with_requirable_file = {}
+ end
+ private_class_method :clear_specs
+
+ clear_specs
# Sentinel object to represent "not found" stubs
NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
- @@spec_with_requirable_file = {}
- @@active_stub_with_requirable_file = {}
# Tracking removed method calls to warn users during build time.
REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc:
@@ -222,7 +225,7 @@ class Gem::Specification < Gem::BasicSpecification
attr_reader :version
##
- # A short summary of this gem's description. Displayed in `gem list -d`.
+ # A short summary of this gem's description. Displayed in <tt>gem list -d</tt>.
#
# The #description should be more detailed than the summary.
#
@@ -268,7 +271,7 @@ class Gem::Specification < Gem::BasicSpecification
# A list of authors for this gem.
#
# Alternatively, a single author can be specified by assigning a string to
- # `spec.author`
+ # +spec.author+
#
# Usage:
#
@@ -282,6 +285,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
@@ -324,17 +336,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)
- # http://opensource.org/licenses/alphabetical approved.
+ # Ideally, you should pick one that is OSI (Open Source Initiative)
+ # https://opensource.org/licenses/ 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=
@@ -458,7 +474,7 @@ class Gem::Specification < Gem::BasicSpecification
# spec.platform = Gem::Platform.local
def platform=(platform)
- if @original_platform.nil? or
+ if @original_platform.nil? ||
@original_platform == Gem::Platform::RUBY
@original_platform = platform
end
@@ -474,12 +490,12 @@ class Gem::Specification < Gem::BasicSpecification
# legacy constants
when nil, Gem::Platform::RUBY then
@new_platform = Gem::Platform::RUBY
- when 'mswin32' then # was Gem::Platform::WIN32
- @new_platform = Gem::Platform.new 'x86-mswin32'
- when 'i586-linux' then # was Gem::Platform::LINUX_586
- @new_platform = Gem::Platform.new 'x86-linux'
- when 'powerpc-darwin' then # was Gem::Platform::DARWIN
- @new_platform = Gem::Platform.new 'ppc-darwin'
+ when "mswin32" then # was Gem::Platform::WIN32
+ @new_platform = Gem::Platform.new "x86-mswin32"
+ when "i586-linux" then # was Gem::Platform::LINUX_586
+ @new_platform = Gem::Platform.new "x86-linux"
+ when "powerpc-darwin" then # was Gem::Platform::DARWIN
+ @new_platform = Gem::Platform.new "ppc-darwin"
else
@new_platform = Gem::Platform.new platform
end
@@ -513,11 +529,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
@@ -646,6 +657,8 @@ class Gem::Specification < Gem::BasicSpecification
@rdoc_options ||= []
end
+ LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")
+
##
# The version of Ruby required by this gem. The ruby version can be
# specified to the patch-level:
@@ -672,6 +685,14 @@ class Gem::Specification < Gem::BasicSpecification
def required_ruby_version=(req)
@required_ruby_version = Gem::Requirement.create req
+
+ @required_ruby_version.requirements.map! do |op, v|
+ if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
+ [op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
+ else
+ [op, v]
+ end
+ end
end
##
@@ -744,23 +765,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 ||= 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|
@@ -855,7 +868,7 @@ class Gem::Specification < Gem::BasicSpecification
next names if names.nonzero?
versions = b.version <=> a.version
next versions if versions.nonzero?
- b.platform == Gem::Platform::RUBY ? -1 : 1
+ Gem::Platform.sort_priority(b.platform)
end
end
@@ -871,6 +884,30 @@ class Gem::Specification < Gem::BasicSpecification
end
##
+ # Adds +spec+ to the known specifications, keeping the collection
+ # properly sorted.
+
+ def self.add_spec(spec)
+ return if _all.include? spec
+
+ _all << spec
+ stubs << spec
+ (@@stubs_by_name[spec.name] ||= []) << spec
+
+ _resort!(@@stubs_by_name[spec.name])
+ _resort!(stubs)
+ end
+
+ ##
+ # Removes +spec+ from the known specs.
+
+ def self.remove_spec(spec)
+ _all.delete spec.to_spec
+ stubs.delete spec
+ (@@stubs_by_name[spec.name] || []).delete spec
+ end
+
+ ##
# Returns all specifications. This method is discouraged from use.
# You probably want to use one of the Enumerable methods instead.
@@ -986,12 +1023,17 @@ class Gem::Specification < Gem::BasicSpecification
end
##
+ # Find the best specification matching a +full_name+.
+ def self.find_by_full_name(full_name)
+ stubs.find {|s| s.full_name == full_name }&.to_spec
+ end
+
+ ##
# Return the best specification that contains the file matching +path+.
def self.find_by_path(path)
path = path.dup.freeze
spec = @@spec_with_requirable_file[path] ||= (stubs.find do |s|
- next unless Gem::BundlerVersionFinder.compatible?(s)
s.contains_requirable_file? path
end || NOT_FOUND)
spec.to_spec
@@ -1004,15 +1046,14 @@ class Gem::Specification < Gem::BasicSpecification
def self.find_inactive_by_path(path)
stub = stubs.find do |s|
next if s.activated?
- next unless Gem::BundlerVersionFinder.compatible?(s)
s.contains_requirable_file? path
end
- stub && stub.to_spec
+ stub&.to_spec
end
def self.find_active_stub_by_path(path)
stub = @@active_stub_with_requirable_file[path] ||= (stubs.find do |s|
- s.activated? and s.contains_requirable_file? path
+ s.activated? && s.contains_requirable_file?(path)
end || NOT_FOUND)
stub.this
end
@@ -1071,6 +1112,7 @@ class Gem::Specification < Gem::BasicSpecification
spec.specification_version ||= NONEXISTENT_SPECIFICATION_VERSION
spec.reset_nil_attributes_to_default
+ spec.flatten_require_paths
spec
end
@@ -1080,7 +1122,7 @@ class Gem::Specification < Gem::BasicSpecification
# +prerelease+ is true.
def self.latest_specs(prerelease = false)
- _latest_specs Gem::Specification._all, prerelease
+ _latest_specs Gem::Specification.stubs, prerelease
end
##
@@ -1099,7 +1141,7 @@ class Gem::Specification < Gem::BasicSpecification
result[spec.name] = spec
end
- result.map(&:last).flatten.sort_by{|tup| tup.name }
+ result.map(&:last).flatten.sort_by {|tup| tup.name }
end
##
@@ -1108,13 +1150,13 @@ 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)
return unless File.file?(file)
- code = File.read file, :mode => 'r:UTF-8:-'
+ code = Gem.open_file(file, "r:UTF-8:-", &:read)
code.tap(&Gem::UNTAINT)
@@ -1123,12 +1165,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
@@ -1199,7 +1241,7 @@ class Gem::Specification < Gem::BasicSpecification
latest_remote = remotes.sort.last
yield [local_spec, latest_remote] if
- latest_remote and local_spec.version < latest_remote
+ latest_remote && local_spec.version < latest_remote
end
nil
@@ -1226,16 +1268,11 @@ 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
+ clear_specs
+ clear_load_cache
unresolved = unresolved_deps
unless unresolved.empty?
- w = "W" + "ARN"
- warn "#{w}: Unresolved or ambiguous specs during Gem::Specification.reset:"
+ warn "WARN: Unresolved or ambiguous specs during Gem::Specification.reset:"
unresolved.values.each do |dep|
warn " #{dep}"
@@ -1245,7 +1282,7 @@ class Gem::Specification < Gem::BasicSpecification
versions.each {|s| warn " - #{s.version}" }
end
end
- warn "#{w}: Clearing out unresolved specs. Try 'gem cleanup <gem>'"
+ warn "WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'"
warn "Please report a bug if this causes problems."
unresolved.clear
end
@@ -1263,7 +1300,37 @@ class Gem::Specification < Gem::BasicSpecification
def self._load(str)
Gem.load_yaml
- array = Marshal.load str
+ yaml_set = false
+
+ array = begin
+ Marshal.load str
+ rescue ArgumentError => e
+ #
+ # Some very old marshaled specs included references to `YAML::PrivateType`
+ # and `YAML::Syck::DefaultKey` constants due to bugs in the old emitter
+ # that generated them. Workaround the issue by defining the necessary
+ # constants and retrying.
+ #
+ message = e.message
+ raise unless message.include?("YAML::")
+
+ unless Object.const_defined?(:YAML)
+ Object.const_set "YAML", Psych
+ yaml_set = true
+ end
+
+ if message.include?("YAML::Syck::")
+ YAML.const_set "Syck", YAML unless YAML.const_defined?(:Syck)
+
+ YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey")
+ elsif message.include?("YAML::PrivateType")
+ YAML.const_set "PrivateType", Class.new
+ end
+
+ retry
+ ensure
+ Object.__send__(:remove_const, "YAML") if yaml_set
+ end
spec = Gem::Specification.new
spec.instance_variable_set :@specification_version, array[1]
@@ -1271,22 +1338,17 @@ class Gem::Specification < Gem::BasicSpecification
current_version = CURRENT_SPECIFICATION_VERSION
field_count = if spec.specification_version > current_version
- spec.instance_variable_set :@specification_version,
- current_version
- MARSHAL_FIELDS[current_version]
- else
- MARSHAL_FIELDS[spec.specification_version]
- end
+ spec.instance_variable_set :@specification_version,
+ current_version
+ MARSHAL_FIELDS[current_version]
+ else
+ MARSHAL_FIELDS[spec.specification_version]
+ end
if array.size < field_count
raise TypeError, "invalid Gem::Specification format #{array.inspect}"
end
- # Cleanup any YAML::PrivateType. They only show up for an old bug
- # where nil => null, so just convert them to nil based on the type.
-
- array.map! {|e| e.kind_of?(YAML::PrivateType) ? nil : e }
-
spec.instance_variable_set :@rubygems_version, array[0]
# spec version
spec.instance_variable_set :@name, array[2]
@@ -1342,7 +1404,7 @@ class Gem::Specification < Gem::BasicSpecification
@required_rubygems_version,
@original_platform,
@dependencies,
- '', # rubyforge_project
+ "", # rubyforge_project
@email,
@authors,
@description,
@@ -1476,10 +1538,10 @@ class Gem::Specification < Gem::BasicSpecification
def add_dependency_with_type(dependency, type, requirements)
requirements = if requirements.empty?
- Gem::Requirement.default
- else
- requirements.flatten
- end
+ Gem::Requirement.default
+ else
+ requirements.flatten
+ end
unless dependency.respond_to?(:name) &&
dependency.respond_to?(:requirement)
@@ -1508,7 +1570,7 @@ class Gem::Specification < Gem::BasicSpecification
# Singular reader for #authors. Returns the first author in the list
def author
- val = authors and val.first
+ (val = authors) && val.first
end
##
@@ -1556,11 +1618,13 @@ 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 default_gem?
+ # we need to fresh build when same name and version of default gems
+ return if self.class.find_by_full_name(full_name)&.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'))
+ return if !File.exist?(File.join(base_dir, "extensions"))
begin
# We need to require things in $LOAD_PATH without looking for the
@@ -1568,9 +1632,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
@@ -1578,7 +1642,7 @@ class Gem::Specification < Gem::BasicSpecification
builder.build_extensions
end
ensure
- ui.close if ui
+ ui&.close
Gem::Specification.unresolved_deps.replace unresolved_deps
end
end
@@ -1620,7 +1684,7 @@ class Gem::Specification < Gem::BasicSpecification
conflicts = {}
self.runtime_dependencies.each do |dep|
spec = Gem.loaded_specs[dep.name]
- if spec and not spec.satisfies_requirement? dep
+ if spec && !spec.satisfies_requirement?(dep)
(conflicts[spec] ||= []) << dep
end
end
@@ -1647,7 +1711,7 @@ class Gem::Specification < Gem::BasicSpecification
self.dependencies.any? do |dep|
if dep.runtime?
spec = Gem.loaded_specs[dep.name]
- spec and not spec.satisfies_requirement? dep
+ spec && !spec.satisfies_requirement?(dep)
else
false
end
@@ -1668,7 +1732,7 @@ class Gem::Specification < Gem::BasicSpecification
DateLike = Object.new # :nodoc:
def DateLike.===(obj) # :nodoc:
- defined?(::Date) and Date === obj
+ defined?(::Date) && Date === obj
end
DateTimeFormat = # :nodoc:
@@ -1687,18 +1751,18 @@ class Gem::Specification < Gem::BasicSpecification
# This is the cleanest, most-readable, faster-than-using-Date
# way to do it.
@date = case date
- when String then
- if DateTimeFormat =~ date
- Time.utc($1.to_i, $2.to_i, $3.to_i)
- else
- raise(Gem::InvalidSpecificationException,
- "invalid date format in specification: #{date.inspect}")
- end
- when Time, DateLike then
- Time.utc(date.year, date.month, date.day)
- else
- TODAY
- end
+ when String then
+ if DateTimeFormat =~ date
+ Time.utc($1.to_i, $2.to_i, $3.to_i)
+ else
+ raise(Gem::InvalidSpecificationException,
+ "invalid date format in specification: #{date.inspect}")
+ end
+ when Time, DateLike then
+ Time.utc(date.year, date.month, date.day)
+ else
+ TODAY
+ end
end
##
@@ -1708,9 +1772,9 @@ class Gem::Specification < Gem::BasicSpecification
# executable now. See Gem.bin_path.
def default_executable # :nodoc:
- if defined?(@default_executable) and @default_executable
+ if defined?(@default_executable) && @default_executable
result = @default_executable
- elsif @executables and @executables.size == 1
+ elsif @executables && @executables.size == 1
result = Array(@executables).first
else
result = nil
@@ -1789,7 +1853,7 @@ class Gem::Specification < Gem::BasicSpecification
# spec.doc_dir 'ri' # => "/path/to/gem_repo/doc/a-1/ri"
def doc_dir(type = nil)
- @doc_dir ||= File.join base_dir, 'doc', full_name
+ @doc_dir ||= File.join base_dir, "doc", full_name
if type
File.join @doc_dir, type
@@ -1801,17 +1865,17 @@ class Gem::Specification < Gem::BasicSpecification
def encode_with(coder) # :nodoc:
mark_version
- coder.add 'name', @name
- coder.add 'version', @version
+ coder.add "name", @name
+ coder.add "version", @version
platform = case @original_platform
- when nil, '' then
- 'ruby'
- when String then
- @original_platform
- else
- @original_platform.to_s
- end
- coder.add 'platform', platform
+ when nil, "" then
+ "ruby"
+ when String then
+ @original_platform
+ else
+ @original_platform.to_s
+ end
+ coder.add "platform", platform
attributes = @@attributes.map(&:to_s) - %w[name version platform]
attributes.each do |name|
@@ -1827,7 +1891,7 @@ class Gem::Specification < Gem::BasicSpecification
# Singular accessor for #executables
def executable
- val = executables and val.first
+ (val = executables) && val.first
end
##
@@ -1939,7 +2003,7 @@ class Gem::Specification < Gem::BasicSpecification
# True if this gem has files in test_files
def has_unit_tests? # :nodoc:
- not test_files.empty?
+ !test_files.empty?
end
# :stopdoc:
@@ -1992,7 +2056,7 @@ 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
+ if (platform = Gem.platforms.last) && platform != Gem::Platform::RUBY && platform != Gem::Platform.local
self.platform = platform
end
@@ -2027,10 +2091,10 @@ class Gem::Specification < Gem::BasicSpecification
def base_dir
return Gem.dir unless loaded_from
@base_dir ||= if default_gem?
- File.dirname File.dirname File.dirname loaded_from
- else
- File.dirname File.dirname loaded_from
- end
+ File.dirname File.dirname File.dirname loaded_from
+ else
+ File.dirname File.dirname loaded_from
+ end
end
##
@@ -2107,8 +2171,8 @@ class Gem::Specification < Gem::BasicSpecification
return
end
- if @specification_version > CURRENT_SPECIFICATION_VERSION and
- sym.to_s.end_with?("=")
+ if @specification_version > CURRENT_SPECIFICATION_VERSION &&
+ sym.to_s.end_with?("=")
warn "ignoring #{sym} loading #{full_name}" if $DEBUG
else
super
@@ -2120,8 +2184,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 default_gem?
return false if File.exist? gem_build_complete_path
true
@@ -2134,7 +2198,7 @@ class Gem::Specification < Gem::BasicSpecification
# file list.
def normalize
- if defined?(@extra_rdoc_files) and @extra_rdoc_files
+ if defined?(@extra_rdoc_files) && @extra_rdoc_files
@extra_rdoc_files.uniq!
@files ||= []
@files.concat(@extra_rdoc_files)
@@ -2159,7 +2223,7 @@ class Gem::Specification < Gem::BasicSpecification
# platform. For use with legacy gems.
def original_name # :nodoc:
- if platform == Gem::Platform::RUBY or platform.nil?
+ if platform == Gem::Platform::RUBY || platform.nil?
"#{@name}-#{@version}"
else
"#{@name}-#{@version}-#{@original_platform}"
@@ -2177,11 +2241,11 @@ class Gem::Specification < Gem::BasicSpecification
# The platform this gem runs on. See Gem::Platform for details.
def platform
- @new_platform ||= Gem::Platform::RUBY
+ @new_platform ||= Gem::Platform::RUBY # rubocop:disable Naming/MemoizedInstanceVariableName
end
def pretty_print(q) # :nodoc:
- q.group 2, 'Gem::Specification.new do |s|', 'end' do
+ q.group 2, "Gem::Specification.new do |s|", "end" do
q.breakable
attributes = @@attributes - [:name, :version]
@@ -2192,8 +2256,8 @@ 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
- if current_value != default_value(attr_name) or
- self.class.required_attribute? attr_name
+ if current_value != default_value(attr_name) ||
+ self.class.required_attribute?(attr_name)
q.text "s.#{attr_name} = "
@@ -2251,7 +2315,7 @@ class Gem::Specification < Gem::BasicSpecification
# Singular accessor for #require_paths
def require_path
- val = require_paths and val.first
+ (val = require_paths) && val.first
end
##
@@ -2276,7 +2340,7 @@ class Gem::Specification < Gem::BasicSpecification
# Returns the full path to this spec's ri directory.
def ri_dir
- @ri_dir ||= File.join base_dir, 'ri', full_name
+ @ri_dir ||= File.join base_dir, "ri", full_name
end
##
@@ -2286,13 +2350,13 @@ 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.join(', ')} }"
when Gem::Version then obj.to_s.dump
- when DateLike then obj.strftime('%Y-%m-%d').dump
- when Time then obj.strftime('%Y-%m-%d').dump
+ when DateLike then obj.strftime("%Y-%m-%d").dump
+ when Time then obj.strftime("%Y-%m-%d").dump
when Numeric then obj.inspect
when true, false, nil then obj.inspect
when Gem::Platform then "Gem::Platform.new(#{obj.to_a.inspect})"
@@ -2326,14 +2390,14 @@ class Gem::Specification < Gem::BasicSpecification
def satisfies_requirement?(dependency)
return @name == dependency.name &&
- dependency.requirement.satisfied_by?(@version)
+ dependency.requirement.satisfied_by?(@version)
end
##
# Returns an object you can use to sort specifications in #sort_by.
def sort_obj
- [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
+ [@name, @version, Gem::Platform.sort_priority(@new_platform)]
end
##
@@ -2380,7 +2444,7 @@ class Gem::Specification < Gem::BasicSpecification
# Singular accessor for #test_files
def test_file # :nodoc:
- val = test_files and val.first
+ (val = test_files) && val.first
end
##
@@ -2402,7 +2466,7 @@ class Gem::Specification < Gem::BasicSpecification
@test_files = [@test_suite_file].flatten
@test_suite_file = nil
end
- if defined?(@test_files) and @test_files
+ if defined?(@test_files) && @test_files
@test_files
else
@test_files = []
@@ -2426,13 +2490,13 @@ class Gem::Specification < Gem::BasicSpecification
result << " s.name = #{ruby_code name}"
result << " s.version = #{ruby_code version}"
- unless platform.nil? or platform == Gem::Platform::RUBY
+ unless platform.nil? || platform == Gem::Platform::RUBY
result << " s.platform = #{ruby_code original_platform}"
end
result << ""
result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version="
- if metadata and !metadata.empty?
+ if metadata && !metadata.empty?
result << " s.metadata = #{ruby_code metadata} if s.respond_to? :metadata="
end
result << " s.require_paths = #{ruby_code raw_require_paths}"
@@ -2470,25 +2534,14 @@ class Gem::Specification < Gem::BasicSpecification
unless dependencies.empty?
result << nil
- result << " if s.respond_to? :specification_version then"
- result << " s.specification_version = #{specification_version}"
- result << " end"
+ result << " s.specification_version = #{specification_version}"
result << nil
- result << " if s.respond_to? :add_runtime_dependency then"
-
dependencies.each do |dep|
req = dep.requirements_list.inspect
dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
- result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>.freeze, #{req})"
- end
-
- result << " else"
- dependencies.each do |dep|
- version_reqs_param = dep.requirements_list.inspect
- result << " s.add_dependency(%q<#{dep.name}>.freeze, #{version_reqs_param})"
+ result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>.freeze, #{req})"
end
- result << " end"
end
result << "end"
@@ -2525,14 +2578,14 @@ 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
builder << self
ast = builder.tree
- require 'stringio'
+ require "stringio"
io = StringIO.new
io.set_encoding Encoding::UTF_8
@@ -2616,10 +2669,12 @@ class Gem::Specification < Gem::BasicSpecification
def version=(version)
@version = Gem::Version.create(version)
+ return if @version.nil?
+
# skip to set required_ruby_version when pre-released rubygems.
# It caused to raise CircularDependencyError
if @version.prerelease? && (@name.nil? || @name.strip != "rubygems")
- self.required_rubygems_version = '> 1.3.1'
+ self.required_rubygems_version = "> 1.3.1"
end
invalidate_memoized_attributes
@@ -2657,14 +2712,23 @@ class Gem::Specification < Gem::BasicSpecification
default = self.default_value attribute
value = case default
- when Time, Numeric, Symbol, true, false, nil then default
- else default.dup
- end
+ when Time, Numeric, Symbol, true, false, nil then default
+ else default.dup
+ end
instance_variable_set "@#{attribute}", value
end
@installed_by_version ||= nil
+
+ nil
+ end
+
+ def flatten_require_paths # :nodoc:
+ return unless raw_require_paths.first.is_a?(Array)
+
+ warn "#{name} #{version} includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this"
+ raw_require_paths.flatten!
end
def raw_require_paths # :nodoc:
diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb
index 86277a2058..cee7eb3fdc 100644
--- a/lib/rubygems/specification_policy.rb
+++ b/lib/rubygems/specification_policy.rb
@@ -1,4 +1,6 @@
-require 'rubygems/user_interaction'
+# frozen_string_literal: true
+
+require_relative "user_interaction"
class Gem::SpecificationPolicy
include Gem::UserInteraction
@@ -120,7 +122,7 @@ class Gem::SpecificationPolicy
metadata = @specification.metadata
unless Hash === metadata
- error 'metadata must be a hash'
+ error "metadata must be a hash"
end
metadata.each do |key, value|
@@ -154,7 +156,7 @@ class Gem::SpecificationPolicy
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 = []
@specification.dependencies.each do |dep|
@@ -173,6 +175,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
end
##
+ # Checks that the gem does not depend on itself.
# Checks that dependencies use requirements as we recommend. Warnings are
# issued when dependencies are open-ended or overly strict for semantic
# versioning.
@@ -180,6 +183,10 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
def validate_dependencies # :nodoc:
warning_messages = []
@specification.dependencies.each do |dep|
+ if dep.name == @specification.name # warn on self reference
+ warning_messages << "Self referencing dependency is unnecessary and strongly discouraged."
+ end
+
prerelease_dep = dep.requirements_list.any? do |req|
Gem::Requirement.new(req).prerelease?
end
@@ -188,7 +195,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
prerelease_dep && !@specification.version.prerelease?
open_ended = dep.requirement.requirements.all? do |op, version|
- not version.prerelease? and (op == '>' or op == '>=')
+ !version.prerelease? && (op == ">" || op == ">=")
end
if open_ended
@@ -198,18 +205,18 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
base = segments.first 2
- recommendation = if (op == '>' || op == '>=') && segments == [0]
- " use a bounded requirement, such as '~> x.y'"
- else
- bugfix = if op == '>'
- ", '> #{dep_version}'"
- elsif op == '>=' and base != segments
- ", '>= #{dep_version}'"
- end
-
- " if #{dep.name} is semantically versioned, use:\n" \
- " add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}"
- end
+ recommendation = if (op == ">" || op == ">=") && segments == [0]
+ " use a bounded requirement, such as '~> x.y'"
+ else
+ bugfix = if op == ">"
+ ", '> #{dep_version}'"
+ elsif op == ">=" && base != segments
+ ", '>= #{dep_version}'"
+ end
+
+ " if #{dep.name} is semantically versioned, use:\n" \
+ " add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}"
+ end
warning_messages << ["open-ended dependency on #{dep} is not recommended", recommendation].join("\n") + "\n"
end
@@ -286,7 +293,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
def validate_require_paths
return unless @specification.raw_require_paths.empty?
- error 'specification must have at least one require_path'
+ error "specification must have at least one require_path"
end
def validate_non_files
@@ -310,7 +317,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
def validate_specification_version
return if @specification.specification_version.is_a?(Integer)
- error 'specification_version must be an Integer (did you mean version?)'
+ error "specification_version must be an Integer (did you mean version?)"
end
def validate_platform
@@ -332,13 +339,13 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
def validate_array_attribute(field)
val = @specification.send(field)
klass = case field
- when :dependencies then
- Gem::Dependency
- else
- String
- end
+ when :dependencies then
+ Gem::Dependency
+ else
+ String
+ end
- unless Array === val and val.all? {|x| x.kind_of?(klass) }
+ unless Array === val && val.all? {|x| x.kind_of?(klass) }
error "#{field} must be an Array of #{klass}"
end
end
@@ -380,8 +387,8 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
WARNING
end
- LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
- LAZY_PATTERN = /FI XME|TO DO/x.freeze
+ LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, "")
+ LAZY_PATTERN = /\AFI XME|\ATO DO/x.freeze
HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze
def validate_lazy_metadata
@@ -404,8 +411,8 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
homepage = @specification.homepage
# Make sure a homepage is valid HTTP/HTTPS URI
- if homepage and not homepage.empty?
- require 'uri'
+ if homepage && !homepage.empty?
+ require "uri"
begin
homepage_uri = URI.parse(homepage)
unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class
@@ -445,7 +452,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
def validate_shebang_line_in(executable)
executable_path = File.join(@specification.bindir, executable)
- return if File.read(executable_path, 2) == '#!'
+ return if File.read(executable_path, 2) == "#!"
warning "#{executable_path} is missing #! line"
end
@@ -457,11 +464,25 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
end
def validate_extensions # :nodoc:
- require_relative 'ext'
+ require_relative "ext"
builder = Gem::Ext::Builder.new(@specification)
+ validate_rake_extensions(builder)
+ validate_rust_extensions(builder)
+ end
+
+ def validate_rust_extensions(builder) # :nodoc:
+ rust_extension = @specification.extensions.any? {|s| builder.builder_for(s).is_a? Gem::Ext::CargoBuilder }
+ missing_cargo_lock = !@specification.files.any? {|f| f.end_with?("Cargo.lock") }
+
+ error <<-ERROR if rust_extension && missing_cargo_lock
+You have specified rust based extension, but Cargo.lock is not part of the gem files. Please run `cargo generate-lockfile` or any other command to generate Cargo.lock and ensure it is added to your gem files section in gemspec.
+ ERROR
+ end
+
+ def validate_rake_extensions(builder) # :nodoc:
rake_extension = @specification.extensions.any? {|s| builder.builder_for(s) == Gem::Ext::RakeBuilder }
- rake_dependency = @specification.dependencies.any? {|d| d.name == 'rake' }
+ 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.
diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb
index 4246f9de86..d64d611f48 100644
--- a/lib/rubygems/stub_specification.rb
+++ b/lib/rubygems/stub_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
##
# Gem::StubSpecification reads the stub: line from the gemspec. This prevents
# us having to eval the entire gemspec in order to find out certain
@@ -6,10 +7,10 @@
class Gem::StubSpecification < Gem::BasicSpecification
# :nodoc:
- PREFIX = "# stub: ".freeze
+ PREFIX = "# stub: "
# :nodoc:
- OPEN_MODE = 'r:UTF-8:-'.freeze
+ OPEN_MODE = "r:UTF-8:-"
class StubLine # :nodoc: all
attr_reader :name, :version, :platform, :require_paths, :extensions,
@@ -19,9 +20,9 @@ class Gem::StubSpecification < Gem::BasicSpecification
# These are common require paths.
REQUIRE_PATHS = { # :nodoc:
- 'lib' => 'lib'.freeze,
- 'test' => 'test'.freeze,
- 'ext' => 'ext'.freeze,
+ "lib" => "lib",
+ "test" => "test",
+ "ext" => "ext",
}.freeze
# These are common require path lists. This hash is used to optimize
@@ -29,28 +30,28 @@ 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)
- parts = data[PREFIX.length..-1].split(" ".freeze, 4)
+ parts = data[PREFIX.length..-1].split(" ", 4)
@name = parts[0].freeze
@version = if Gem::Version.correct?(parts[1])
- Gem::Version.new(parts[1])
- else
- Gem::Version.new(0)
- end
+ Gem::Version.new(parts[1])
+ else
+ Gem::Version.new(0)
+ end
@platform = Gem::Platform.new parts[2]
@extensions = extensions
@full_name = if platform == Gem::Platform::RUBY
- "#{name}-#{version}"
- else
- "#{name}-#{version}-#{platform}"
- end
+ "#{name}-#{version}"
+ else
+ "#{name}-#{version}-#{platform}"
+ end
path_list = parts.last
- @require_paths = REQUIRE_PATH_LIST[path_list] || path_list.split("\0".freeze).map! do |x|
+ @require_paths = REQUIRE_PATH_LIST[path_list] || path_list.split("\0").map! do |x|
REQUIRE_PATHS[x] || x
end
end
@@ -110,16 +111,16 @@ class Gem::StubSpecification < Gem::BasicSpecification
begin
saved_lineno = $.
- File.open loaded_from, OPEN_MODE do |file|
+ Gem.open_file loaded_from, OPEN_MODE do |file|
begin
file.readline # discard encoding line
stubline = file.readline.chomp
if stubline.start_with?(PREFIX)
extensions = if /\A#{PREFIX}/ =~ file.readline.chomp
- $'.split "\0"
- else
- StubLine::NO_EXTENSIONS
- end
+ $'.split "\0"
+ else
+ StubLine::NO_EXTENSIONS
+ end
@data = StubLine.new stubline, extensions
end
@@ -183,17 +184,15 @@ class Gem::StubSpecification < Gem::BasicSpecification
##
# The full Gem::Specification for this gem, loaded from evalling its gemspec
- def to_spec
+ def spec
@spec ||= if @data
- loaded = Gem.loaded_specs[name]
- loaded if loaded && loaded.version == version
- end
+ loaded = Gem.loaded_specs[name]
+ loaded if loaded && loaded.version == version
+ end
@spec ||= Gem::Specification.load(loaded_from)
- @spec.ignored = @ignored if @spec
-
- @spec
end
+ alias_method :to_spec, :spec
##
# Is this StubSpecification valid? i.e. have we found a stub line, OR does
diff --git a/lib/rubygems/text.rb b/lib/rubygems/text.rb
index acf25a0bcd..be811525f2 100644
--- a/lib/rubygems/text.rb
+++ b/lib/rubygems/text.rb
@@ -9,7 +9,7 @@ module Gem::Text
# Remove any non-printable characters and make the text suitable for
# printing.
def clean_text(text)
- text.gsub(/[\000-\b\v-\f\016-\037\177]/, ".".freeze)
+ text.gsub(/[\000-\b\v-\f\016-\037\177]/, ".")
end
def truncate_text(text, description, max_length = 100_000)
@@ -51,7 +51,7 @@ module Gem::Text
# Returns a value representing the "cost" of transforming str1 into str2
# Vendored version of DidYouMean::Levenshtein.distance from the ruby/did_you_mean gem @ 1.4.0
- # https://git.io/JJgZI
+ # https://github.com/ruby/did_you_mean/blob/2ddf39b874808685965dbc47d344cf6c7651807c/lib/did_you_mean/levenshtein.rb#L7-L37
def levenshtein_distance(str1, str2)
n = str1.length
m = str2.length
diff --git a/lib/rubygems/tsort.rb b/lib/rubygems/tsort.rb
new file mode 100644
index 0000000000..60ebe22e81
--- /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/lib/tsort.rb b/lib/rubygems/tsort/lib/tsort.rb
new file mode 100644
index 0000000000..f825f14257
--- /dev/null
+++ b/lib/rubygems/tsort/lib/tsort.rb
@@ -0,0 +1,452 @@
+# 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::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 self.tsort(each_node, each_child)
+ tsort_each(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #tsort method.
+ # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
+ # modification of _obj_ during the iteration may lead to unexpected results.
+ #
+ # #tsort_each returns +nil+.
+ # If there is a cycle, 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 self.tsort_each(each_node, each_child) # :yields: node
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ each_strongly_connected_component(each_node, each_child) {|component|
+ if component.size == 1
+ yield component.first
+ else
+ raise Cyclic.new("topological sort failed: #{component.inspect}")
+ end
+ }
+ end
+
+ # Returns strongly connected components as an array of arrays of nodes.
+ # The array is sorted from children to parents.
+ # Each elements of the array represents a strongly connected component.
+ #
+ # class G
+ # include 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 self.strongly_connected_components(each_node, each_child)
+ each_strongly_connected_component(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #strongly_connected_components method.
+ # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
+ # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
+ # modification of _obj_ during the iteration may lead to unexpected results.
+ #
+ # #each_strongly_connected_component returns +nil+.
+ #
+ # class G
+ # include 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 self.each_strongly_connected_component(each_node, each_child) # :yields: nodes
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ id_map = {}
+ stack = []
+ each_node.call {|node|
+ unless id_map.include? node
+ each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
+ yield c
+ }
+ end
+ }
+ nil
+ end
+
+ # Iterates over strongly connected component in the subgraph reachable from
+ # _node_.
+ #
+ # Return value is unspecified.
+ #
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
+ #
+ # class G
+ # include 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 self.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
+ return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
+
+ minimum_id = node_id = id_map[node] = id_map.size
+ stack_length = stack.length
+ stack << node
+
+ each_child.call(node) {|child|
+ if id_map.include? child
+ child_id = id_map[child]
+ minimum_id = child_id if child_id && child_id < minimum_id
+ else
+ sub_minimum_id =
+ each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
+ yield c
+ }
+ minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
+ end
+ }
+
+ if node_id == minimum_id
+ component = stack.slice!(stack_length .. -1)
+ component.each {|n| id_map[n] = nil}
+ yield component
+ end
+
+ minimum_id
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_node is used to iterate for all nodes over a graph.
+ #
+ def tsort_each_node # :yields: node
+ raise NotImplementedError.new
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_child is used to iterate for child nodes of _node_.
+ #
+ def tsort_each_child(node) # :yields: child
+ raise NotImplementedError.new
+ end
+end
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 87a5ef770f..f678f960f0 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -1,16 +1,17 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'fileutils'
-require 'rubygems'
-require 'rubygems/installer_uninstaller_utils'
-require 'rubygems/dependency_list'
-require 'rubygems/rdoc'
-require 'rubygems/user_interaction'
+require "fileutils"
+require_relative "../rubygems"
+require_relative "installer_uninstaller_utils"
+require_relative "dependency_list"
+require_relative "rdoc"
+require_relative "user_interaction"
##
# An Uninstaller.
@@ -105,8 +106,8 @@ class Gem::Uninstaller
@default_specs_matching_uninstall_params = default_specs
list, other_repo_specs = list.partition do |spec|
- @gem_home == spec.base_dir or
- (@user_install and spec.base_dir == Gem.user_dir)
+ @gem_home == spec.base_dir ||
+ (@user_install && spec.base_dir == Gem.user_dir)
end
list.sort!
@@ -200,13 +201,13 @@ class Gem::Uninstaller
executables = executables.map {|exec| formatted_program_filename exec }
remove = if @force_executables.nil?
- ask_yes_no("Remove executables:\n" +
- "\t#{executables.join ', '}\n\n" +
- "in addition to the gem?",
- true)
- else
- @force_executables
- end
+ ask_yes_no("Remove executables:\n" +
+ "\t#{executables.join ', '}\n\n" +
+ "in addition to the gem?",
+ true)
+ else
+ @force_executables
+ end
if remove
bin_dir = @bin_dir || Gem.bindir(spec.base_dir)
@@ -239,8 +240,8 @@ class Gem::Uninstaller
# spec:: the spec of the gem to be uninstalled
def remove(spec)
- unless path_ok?(@gem_home, spec) or
- (@user_install and path_ok?(Gem.user_dir, spec))
+ unless path_ok?(@gem_home, spec) ||
+ (@user_install && path_ok?(Gem.user_dir, spec))
e = Gem::GemNotInHomeException.new \
"Gem '#{spec.full_name}' is not installed in directory #{@gem_home}"
e.spec = spec
@@ -302,8 +303,8 @@ class Gem::Uninstaller
# Is +spec+ in +gem_dir+?
def path_ok?(gem_dir, spec)
- full_path = File.join gem_dir, 'gems', spec.full_name
- original_path = File.join gem_dir, 'gems', spec.original_name
+ full_path = File.join gem_dir, "gems", spec.full_name
+ original_path = File.join gem_dir, "gems", spec.original_name
full_path == spec.full_gem_path || original_path == spec.full_gem_path
end
@@ -332,10 +333,10 @@ class Gem::Uninstaller
# Asks if it is OK to remove +spec+. Returns true if it is OK.
def ask_if_ok(spec) # :nodoc:
- msg = ['']
- msg << 'You have requested to uninstall the gem:'
+ msg = [""]
+ msg << "You have requested to uninstall the gem:"
msg << "\t#{spec.full_name}"
- msg << ''
+ msg << ""
siblings = Gem::Specification.select do |s|
s.name == spec.name && s.full_name != spec.full_name
@@ -347,8 +348,8 @@ class Gem::Uninstaller
end
end
- msg << 'If you remove this gem, these dependencies will not be met.'
- msg << 'Continue with Uninstall?'
+ msg << "If you remove this gem, these dependencies will not be met."
+ msg << "Continue with Uninstall?"
return ask_yes_no(msg.join("\n"), false)
end
@@ -360,7 +361,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
diff --git a/lib/rubygems/update_suggestion.rb b/lib/rubygems/update_suggestion.rb
new file mode 100644
index 0000000000..c2e81b2374
--- /dev/null
+++ b/lib/rubygems/update_suggestion.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+##
+# Mixin methods for Gem::Command to promote available RubyGems update
+
+module Gem::UpdateSuggestion
+ # list taken from https://github.com/watson/ci-info/blob/7a3c30d/index.js#L56-L66
+ CI_ENV_VARS = [
+ "CI", # Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari
+ "CONTINUOUS_INTEGRATION", # Travis CI, Cirrus CI
+ "BUILD_NUMBER", # Jenkins, TeamCity
+ "CI_APP_ID", "CI_BUILD_ID", "CI_BUILD_NUMBER", # Applfow
+ "RUN_ID" # TaskCluster, dsari
+ ].freeze
+
+ ONE_WEEK = 7 * 24 * 60 * 60
+
+ ##
+ # Message to promote available RubyGems update with related gem update command.
+
+ def update_suggestion
+ <<-MESSAGE
+
+A new release of RubyGems is available: #{Gem.rubygems_version} → #{Gem.latest_rubygems_version}!
+Run `gem update --system #{Gem.latest_rubygems_version}` to update your installation.
+
+ MESSAGE
+ end
+
+ ##
+ # Determines if current environment is eglible for update suggestion.
+
+ def eglible_for_update?
+ # explicit opt-out
+ return false if Gem.configuration[:prevent_update_suggestion]
+ return false if ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"]
+
+ # focus only on human usage of final RubyGems releases
+ return false unless Gem.ui.tty?
+ return false if Gem.rubygems_version.prerelease?
+ return false if Gem.disable_system_update_message
+ return false if ci?
+
+ # check makes sense only when we can store timestamp of last try
+ # otherwise we will not be able to prevent "annoying" update message
+ # on each command call
+ return unless Gem.configuration.state_file_writable?
+
+ # load time of last check, ensure the difference is enough to repeat the suggestion
+ check_time = Time.now.to_i
+ last_update_check = Gem.configuration.last_update_check
+ return false if (check_time - last_update_check) < ONE_WEEK
+
+ # compare current and latest version, this is the part where
+ # latest rubygems spec is fetched from remote
+ (Gem.rubygems_version < Gem.latest_rubygems_version).tap do |eglible|
+ # store the time of last successful check into state file
+ Gem.configuration.last_update_check = check_time
+
+ return eglible
+ end
+ rescue # don't block install command on any problem
+ false
+ end
+
+ def ci?
+ CI_ENV_VARS.any? {|var| ENV.include?(var) }
+ end
+end
diff --git a/lib/rubygems/uri.rb b/lib/rubygems/uri.rb
new file mode 100644
index 0000000000..4b5d035aa0
--- /dev/null
+++ b/lib/rubygems/uri.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+##
+# The Uri handles rubygems source URIs.
+#
+
+class Gem::Uri
+ ##
+ # Parses and redacts uri
+
+ def self.redact(uri)
+ new(uri).redacted
+ end
+
+ ##
+ # Parses uri, raising if it's invalid
+
+ def self.parse!(uri)
+ require "uri"
+
+ raise URI::InvalidURIError unless uri
+
+ return uri unless uri.is_a?(String)
+
+ # 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 uri, returning the original uri if it's invalid
+
+ def self.parse(uri)
+ parse!(uri)
+ rescue URI::InvalidURIError
+ uri
+ end
+
+ 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.include?(to_s)
+
+ 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
+
+ def parse!(uri)
+ self.class.parse!(uri)
+ end
+
+ def parse(uri)
+ self.class.parse(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 3bda896875..3f1d02d774 100644
--- a/lib/rubygems/uri_formatter.rb
+++ b/lib/rubygems/uri_formatter.rb
@@ -17,7 +17,7 @@ class Gem::UriFormatter
# Creates a new URI formatter for +uri+.
def initialize(uri)
- require 'cgi'
+ require "cgi"
@uri = uri
end
diff --git a/lib/rubygems/uri_parser.rb b/lib/rubygems/uri_parser.rb
deleted file mode 100644
index f51d77a4af..0000000000
--- a/lib/rubygems/uri_parser.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-##
-# The UriParser handles parsing URIs.
-#
-
-class Gem::UriParser
- def self.parse_uri(source_uri)
- return source_uri unless source_uri.is_a?(String)
-
- new.parse(source_uri)
- end
-
- ##
- # 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)
- parse!(uri)
- rescue URI::InvalidURIError
- uri
- end
-end
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 6376ea7cf8..451dba070f 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/deprecate'
-require 'rubygems/text'
+require_relative "deprecate"
+require_relative "text"
##
# Module that defines the default UserInteraction. Any class including this
@@ -148,7 +149,7 @@ module Gem::UserInteraction
##
# Displays the given +statement+ on the standard output (or equivalent).
- def say(statement = '')
+ def say(statement = "")
ui.say statement
end
@@ -239,6 +240,7 @@ class Gem::StreamUI
return nil, nil unless result
result = result.strip.to_i - 1
+ return nil, nil unless (0...list.size) === result
return list[result], result
end
@@ -258,23 +260,23 @@ class Gem::StreamUI
end
default_answer = case default
- when nil
- 'yn'
- when true
- 'Yn'
- else
- 'yN'
- end
+ when nil
+ "yn"
+ when true
+ "Yn"
+ else
+ "yN"
+ end
result = nil
while result.nil? do
result = case ask "#{question} [#{default_answer}]"
- when /^y/i then true
- when /^n/i then false
- when /^$/ then default
- else nil
- end
+ when /^y/i then true
+ when /^n/i then false
+ when /^$/ then default
+ else nil
+ end
end
return result
@@ -284,13 +286,13 @@ class Gem::StreamUI
# Ask a question. Returns an answer if connected to a tty, nil otherwise.
def ask(question)
- return nil if not tty?
+ return nil if !tty?
@outs.print(question + " ")
@outs.flush
result = @ins.gets
- result.chomp! if result
+ result&.chomp!
result
end
@@ -298,21 +300,21 @@ class Gem::StreamUI
# Ask for a password. Does not echo response to terminal.
def ask_for_password(question)
- return nil if not tty?
+ return nil if !tty?
@outs.print(question, " ")
@outs.flush
password = _gets_noecho
@outs.puts
- password.chomp! if password
+ password&.chomp!
password
end
def require_io_console
@require_io_console ||= begin
begin
- require 'io/console'
+ require "io/console"
rescue LoadError
end
true
@@ -472,7 +474,7 @@ class Gem::StreamUI
# and the +terminal_message+ when it is complete.
def initialize(out_stream, size, initial_message,
- terminal_message = 'complete')
+ terminal_message = "complete")
@out = out_stream
@total = size
@count = 0
@@ -616,18 +618,11 @@ class Gem::SilentUI < Gem::StreamUI
# The SilentUI has no arguments as it does not use any stream.
def initialize
- reader, writer = nil, nil
-
- reader = File.open(IO::NULL, 'r')
- writer = File.open(IO::NULL, 'w')
-
- super reader, writer, writer, false
+ io = NullIO.new
+ super io, io, io, false
end
def close
- super
- @ins.close
- @outs.close
end
def download_reporter(*args) # :nodoc:
@@ -637,4 +632,25 @@ class Gem::SilentUI < Gem::StreamUI
def progress_reporter(*args) # :nodoc:
SilentProgressReporter.new(@outs, *args)
end
+
+ ##
+ # An absolutely silent IO.
+
+ class NullIO
+ def puts(*args)
+ end
+
+ def print(*args)
+ end
+
+ def flush
+ end
+
+ def gets(*args)
+ end
+
+ def tty?
+ false
+ end
+ end
end
diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb
index 2a55305172..bd6ea92cc9 100644
--- a/lib/rubygems/util.rb
+++ b/lib/rubygems/util.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/deprecate'
+
+require_relative "deprecate"
##
# This module contains various utility methods as module methods.
@@ -10,9 +11,9 @@ module Gem::Util
# Zlib::GzipReader wrapper that unzips +data+.
def self.gunzip(data)
- require 'zlib'
- require 'stringio'
- data = StringIO.new(data, 'r')
+ require "zlib"
+ require "stringio"
+ data = StringIO.new(data, "r")
gzip_reader = begin
Zlib::GzipReader.new(data)
@@ -29,9 +30,9 @@ module Gem::Util
# Zlib::GzipWriter wrapper that zips +data+.
def self.gzip(data)
- require 'zlib'
- require 'stringio'
- zipped = StringIO.new(String.new, 'w')
+ require "zlib"
+ require "stringio"
+ zipped = StringIO.new(String.new, "w")
zipped.set_encoding Encoding::BINARY
Zlib::GzipWriter.wrap zipped do |io|
@@ -45,7 +46,7 @@ module Gem::Util
# A Zlib::Inflate#inflate wrapper
def self.inflate(data)
- require 'zlib'
+ require "zlib"
Zlib::Inflate.inflate data
end
@@ -60,7 +61,7 @@ module Gem::Util
# Invokes system, but silences all output.
def self.silent_system(*command)
- opt = {:out => IO::NULL, :err => [:child, :out]}
+ opt = { :out => IO::NULL, :err => [:child, :out] }
if Hash === command.last
opt.update(command.last)
cmds = command[0...-1]
@@ -86,7 +87,7 @@ module Gem::Util
loop do
Dir.chdir here, &block rescue Errno::EACCES
- new_here = File.expand_path('..', here)
+ new_here = File.expand_path("..", here)
return if new_here == here # toplevel
here = new_here
end
@@ -97,11 +98,7 @@ module Gem::Util
# returning absolute paths to the matching files.
def self.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.expand_path(glob, base_path))
- end
+ Dir.glob(glob, base: base_path).map! {|f| File.expand_path(f, base_path) }
end
##
@@ -109,7 +106,7 @@ module Gem::Util
# comes with a leading slash.
def self.correct_for_windows_path(path)
- if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':'
+ if path[0].chr == "/" && path[1].chr =~ /[a-z]/i && path[2].chr == ":"
path[1..-1]
else
path
diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb
index 98cbd8929b..1d5efde576 100644
--- a/lib/rubygems/util/licenses.rb
+++ b/lib/rubygems/util/licenses.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
-require 'rubygems/text'
+
+require_relative "../text"
class Gem::Licenses
extend Gem::Text
- NONSTANDARD = 'Nonstandard'.freeze
+ NONSTANDARD = "Nonstandard"
+ LICENSE_REF = "LicenseRef-.+"
# Software Package Data Exchange (SPDX) standard open-source software
# license identifiers
@@ -523,6 +525,7 @@ class Gem::Licenses
\+?
(?:\s WITH \s #{Regexp.union(EXCEPTION_IDENTIFIERS)})?
| #{NONSTANDARD}
+ | #{LICENSE_REF}
)
\Z
}ox.freeze
diff --git a/lib/rubygems/util/list.rb b/lib/rubygems/util/list.rb
index 33c40af4bb..acb6c73ddb 100644
--- a/lib/rubygems/util/list.rb
+++ b/lib/rubygems/util/list.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem
class List
include Enumerable
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 30cdd93b5c..63493638b6 100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems/package'
-require 'rubygems/installer'
+require_relative "package"
+require_relative "installer"
##
# Validator performs various gem file and gem database validation
@@ -15,7 +16,7 @@ class Gem::Validator
include Gem::UserInteraction
def initialize # :nodoc:
- require 'find'
+ require "find"
end
private
@@ -26,7 +27,7 @@ class Gem::Validator
Find.find gem_directory do |file_name|
fn = file_name[gem_directory.size..file_name.size - 1].sub(/^\//, "")
installed_files << fn unless
- fn =~ /CVS/ || fn.empty? || File.directory?(file_name)
+ fn.empty? || fn.include?("CVS") || File.directory?(file_name)
end
installed_files
@@ -110,11 +111,11 @@ class Gem::Validator
begin
next unless data # HACK `gem check -a mkrf`
- source = File.join gem_directory, entry['path']
+ source = File.join gem_directory, entry["path"]
File.open source, Gem.binary_mode do |f|
unless f.read == data
- errors[gem_name][entry['path']] = "Modified from original"
+ errors[gem_name][entry["path"]] = "Modified from original"
end
end
end
diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb
index 20bbff4fdd..c319e1f820 100644
--- a/lib/rubygems/version.rb
+++ b/lib/rubygems/version.rb
@@ -1,4 +1,7 @@
# frozen_string_literal: true
+
+require_relative "deprecate"
+
##
# The Version class processes string versions into comparable
# values. A version string should normally be a series of numbers
@@ -150,11 +153,9 @@
# a zero to give a sensible result.
class Gem::Version
- autoload :Requirement, File.expand_path('requirement', __dir__)
-
include Comparable
- VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?'.freeze # :nodoc:
+ VERSION_PATTERN = '[0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' # :nodoc:
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/.freeze # :nodoc:
##
@@ -170,9 +171,7 @@ class Gem::Version
# True if the +version+ string matches RubyGems' requirements.
def self.correct?(version)
- unless Gem::Deprecate.skip
- warn "nil versions are discouraged and will be deprecated in Rubygems 4" if version.nil?
- end
+ nil_versions_are_discouraged! if version.nil?
!!(version.to_s =~ ANCHORED_VERSION_PATTERN)
end
@@ -189,6 +188,8 @@ class Gem::Version
if self === input # check yourself before you wreck yourself
input
elsif input.nil?
+ nil_versions_are_discouraged!
+
nil
else
new input
@@ -205,6 +206,14 @@ class Gem::Version
@@all[version] ||= super
end
+ def self.nil_versions_are_discouraged!
+ unless Gem::Deprecate.skip
+ warn "nil versions are discouraged and will be deprecated in Rubygems 4"
+ end
+ end
+
+ private_class_method :nil_versions_are_discouraged!
+
##
# Constructs a Version from the +version+ string. A version string is a
# series of digits or ASCII letters separated by dots.
@@ -243,7 +252,7 @@ class Gem::Version
# same precision. Version "1.0" is not the same as version "1".
def eql?(other)
- self.class === other and @version == other._version
+ self.class === other && @version == other._version
end
def hash # :nodoc:
@@ -263,7 +272,7 @@ class Gem::Version
# string for backwards (RubyGems 1.3.5 and earlier) compatibility.
def marshal_dump
- [version]
+ [@version]
end
##
@@ -275,7 +284,7 @@ class Gem::Version
end
def yaml_initialize(tag, map) # :nodoc:
- @version = map['version']
+ @version = map["version"]
@segments = nil
@hash = nil
end
@@ -285,7 +294,7 @@ class Gem::Version
end
def encode_with(coder) # :nodoc:
- coder.add 'version', @version
+ coder.add "version", @version
end
##
@@ -308,12 +317,12 @@ class Gem::Version
def release
@@release[self] ||= if prerelease?
- segments = self.segments
- segments.pop while segments.any? {|s| String === s }
- self.class.new segments.join('.')
- else
- self
- end
+ segments = self.segments
+ segments.pop while segments.any? {|s| String === s }
+ self.class.new segments.join(".")
+ else
+ self
+ end
end
def segments # :nodoc:
@@ -339,9 +348,11 @@ class Gem::Version
# Compares this version with +other+ returning -1, 0, or 1 if the
# other version is larger, the same, or smaller than this
# one. Attempts to compare to something that's not a
- # <tt>Gem::Version</tt> return +nil+.
+ # <tt>Gem::Version</tt> or a valid version String return +nil+.
def <=>(other)
+ return self <=> self.class.new(other) if (String === other) && self.class.correct?(other)
+
return unless Gem::Version === other
return 0 if @version == other._version || canonical_segments == other.canonical_segments
diff --git a/lib/rubygems/version_option.rb b/lib/rubygems/version_option.rb
index be71ef409b..d83a69cf0d 100644
--- a/lib/rubygems/version_option.rb
+++ b/lib/rubygems/version_option.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
+require_relative "../rubygems"
##
# Mixin methods for --version and --platform Gem::Command options.
@@ -16,7 +17,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
@@ -24,7 +25,7 @@ module Gem::VersionOption
end
end
- add_option('--platform PLATFORM', Gem::Platform,
+ add_option("--platform PLATFORM", Gem::Platform,
"Specify the platform of gem to #{task}", *wrap) do
|value, options|
unless options[:added_platform]
@@ -51,11 +52,11 @@ 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
- add_option('-v', '--version VERSION', Gem::Requirement,
+ add_option("-v", "--version VERSION", Gem::Requirement,
"Specify version of gem to #{task}", *wrap) do
|value, options|
# Allow handling for multiple --version operators
diff --git a/lib/securerandom.gemspec b/lib/securerandom.gemspec
index 358dc58056..e095244ce9 100644
--- a/lib/securerandom.gemspec
+++ b/lib/securerandom.gemspec
@@ -1,13 +1,13 @@
Gem::Specification.new do |spec|
spec.name = "securerandom"
- spec.version = "0.1.0"
+ spec.version = "0.2.2"
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.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
diff --git a/lib/securerandom.rb b/lib/securerandom.rb
index 241fde98ce..07ae048634 100644
--- a/lib/securerandom.rb
+++ b/lib/securerandom.rb
@@ -1,6 +1,8 @@
# -*- coding: us-ascii -*-
# frozen_string_literal: true
+require 'random/formatter'
+
# == Secure random number generator interface.
#
# This library is an interface to secure random number generators which are
@@ -31,39 +33,10 @@
# * uuid
#
# These methods are usable as class methods of SecureRandom such as
-# `SecureRandom.hex`.
-#
-# === Examples
-#
-# Generate random hexadecimal strings:
-#
-# require 'securerandom'
-#
-# SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
-# SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559"
-# SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23"
-#
-# Generate random base64 strings:
-#
-# SecureRandom.base64(10) #=> "EcmTPZwWRAozdA=="
-# SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg=="
-# SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8"
-#
-# Generate random binary strings:
-#
-# SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
-# SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
-#
-# Generate alphanumeric strings:
-#
-# SecureRandom.alphanumeric(10) #=> "S8baxMJnPl"
-# SecureRandom.alphanumeric(10) #=> "aOxAg8BAJe"
-#
-# Generate UUIDs:
-#
-# SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
-# SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
+# +SecureRandom.hex+.
#
+# If a secure random number generator is not available,
+# +NotImplementedError+ is raised.
module SecureRandom
class << self
@@ -99,8 +72,11 @@ module SecureRandom
ret
end
- ret = Random.urandom(1)
- if ret.nil?
+ begin
+ # Check if Random.urandom is available
+ Random.urandom(1)
+ alias gen_random gen_random_urandom
+ rescue RuntimeError
begin
require 'openssl'
rescue NoMethodError
@@ -108,210 +84,10 @@ module SecureRandom
else
alias gen_random gen_random_openssl
end
- else
- alias gen_random gen_random_urandom
end
public :gen_random
end
end
-module Random::Formatter
-
- # SecureRandom.random_bytes generates a random binary string.
- #
- # The argument _n_ specifies the length of the result string.
- #
- # If _n_ is not specified or is nil, 16 is assumed.
- # It may be larger in future.
- #
- # The result may contain any byte: "\x00" - "\xff".
- #
- # require 'securerandom'
- #
- # SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
- # SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
- #
- # If a secure random number generator is not available,
- # +NotImplementedError+ is raised.
- def random_bytes(n=nil)
- n = n ? n.to_int : 16
- gen_random(n)
- end
-
- # SecureRandom.hex generates a random hexadecimal string.
- #
- # The argument _n_ specifies the length, in bytes, of the random number to be generated.
- # The length of the resulting hexadecimal string is twice of _n_.
- #
- # If _n_ is not specified or is nil, 16 is assumed.
- # It may be larger in the future.
- #
- # The result may contain 0-9 and a-f.
- #
- # require 'securerandom'
- #
- # SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"
- # SecureRandom.hex #=> "91dc3bfb4de5b11d029d376634589b61"
- #
- # If a secure random number generator is not available,
- # +NotImplementedError+ is raised.
- def hex(n=nil)
- random_bytes(n).unpack("H*")[0]
- end
-
- # SecureRandom.base64 generates a random base64 string.
- #
- # The argument _n_ specifies the length, in bytes, of the random number
- # to be generated. The length of the result string is about 4/3 of _n_.
- #
- # If _n_ is not specified or is nil, 16 is assumed.
- # It may be larger in the future.
- #
- # The result may contain A-Z, a-z, 0-9, "+", "/" and "=".
- #
- # require 'securerandom'
- #
- # SecureRandom.base64 #=> "/2BuBuLf3+WfSKyQbRcc/A=="
- # SecureRandom.base64 #=> "6BbW0pxO0YENxn38HMUbcQ=="
- #
- # If a secure random number generator is not available,
- # +NotImplementedError+ is raised.
- #
- # See RFC 3548 for the definition of base64.
- def base64(n=nil)
- [random_bytes(n)].pack("m0")
- end
-
- # SecureRandom.urlsafe_base64 generates a random URL-safe base64 string.
- #
- # The argument _n_ specifies the length, in bytes, of the random number
- # to be generated. The length of the result string is about 4/3 of _n_.
- #
- # If _n_ is not specified or is nil, 16 is assumed.
- # It may be larger in the future.
- #
- # The boolean argument _padding_ specifies the padding.
- # If it is false or nil, padding is not generated.
- # Otherwise padding is generated.
- # By default, padding is not generated because "=" may be used as a URL delimiter.
- #
- # The result may contain A-Z, a-z, 0-9, "-" and "_".
- # "=" is also used if _padding_ is true.
- #
- # require 'securerandom'
- #
- # SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg"
- # SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
- #
- # SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
- # SecureRandom.urlsafe_base64(nil, true) #=> "-M8rLhr7JEpJlqFGUMmOxg=="
- #
- # If a secure random number generator is not available,
- # +NotImplementedError+ is raised.
- #
- # See RFC 3548 for the definition of URL-safe base64.
- def urlsafe_base64(n=nil, padding=false)
- s = [random_bytes(n)].pack("m0")
- s.tr!("+/", "-_")
- s.delete!("=") unless padding
- s
- end
-
- # SecureRandom.uuid generates a random v4 UUID (Universally Unique IDentifier).
- #
- # require 'securerandom'
- #
- # SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"
- # SecureRandom.uuid #=> "bad85eb9-0713-4da7-8d36-07a8e4b00eab"
- # SecureRandom.uuid #=> "62936e70-1815-439b-bf89-8492855a7e6b"
- #
- # The version 4 UUID is purely random (except the version).
- # It doesn't contain meaningful information such as MAC addresses, timestamps, etc.
- #
- # The result contains 122 random bits (15.25 random bytes).
- #
- # See RFC 4122 for details of UUID.
- #
- def uuid
- ary = random_bytes(16).unpack("NnnnnN")
- ary[2] = (ary[2] & 0x0fff) | 0x4000
- ary[3] = (ary[3] & 0x3fff) | 0x8000
- "%08x-%04x-%04x-%04x-%04x%08x" % ary
- end
-
- private def gen_random(n)
- self.bytes(n)
- end
-
- # SecureRandom.choose generates a string that randomly draws from a
- # source array of characters.
- #
- # The argument _source_ specifies the array of characters from which
- # to generate the string.
- # The argument _n_ specifies the length, in characters, of the string to be
- # generated.
- #
- # The result may contain whatever characters are in the source array.
- #
- # require 'securerandom'
- #
- # SecureRandom.choose([*'l'..'r'], 16) #=> "lmrqpoonmmlqlron"
- # SecureRandom.choose([*'0'..'9'], 5) #=> "27309"
- #
- # If a secure random number generator is not available,
- # +NotImplementedError+ is raised.
- private def choose(source, n)
- size = source.size
- m = 1
- limit = size
- while limit * size <= 0x100000000
- limit *= size
- m += 1
- end
- result = ''.dup
- while m <= n
- rs = random_number(limit)
- is = rs.digits(size)
- (m-is.length).times { is << 0 }
- result << source.values_at(*is).join('')
- n -= m
- end
- if 0 < n
- rs = random_number(limit)
- is = rs.digits(size)
- if is.length < n
- (n-is.length).times { is << 0 }
- else
- is.pop while n < is.length
- end
- result.concat source.values_at(*is).join('')
- end
- result
- end
-
- ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9']
- # SecureRandom.alphanumeric generates a random alphanumeric string.
- #
- # The argument _n_ specifies the length, in characters, of the alphanumeric
- # string to be generated.
- #
- # If _n_ is not specified or is nil, 16 is assumed.
- # It may be larger in the future.
- #
- # The result may contain A-Z, a-z and 0-9.
- #
- # require 'securerandom'
- #
- # SecureRandom.alphanumeric #=> "2BuBuLf3WfSKyQbR"
- # SecureRandom.alphanumeric(10) #=> "i6K93NdqiH"
- #
- # If a secure random number generator is not available,
- # +NotImplementedError+ is raised.
- def alphanumeric(n=nil)
- n = 16 if n.nil?
- choose(ALPHANUMERIC, n)
- end
-end
-
SecureRandom.extend(Random::Formatter)
diff --git a/lib/set.rb b/lib/set.rb
index 50399309e3..df1e68d081 100644
--- a/lib/set.rb
+++ b/lib/set.rb
@@ -66,8 +66,8 @@
#
# First, what's elsewhere. \Class \Set:
#
-# - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-Object-label-What-27s+Here].
-# - Includes {module Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-What-27s+Here],
+# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+# - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
# which provides dozens of additional methods.
#
# In particular, class \Set does not have many methods of its own
@@ -88,134 +88,134 @@
#
# ### Methods for Creating a \Set
#
-# - ::[] -
+# - ::[]:
# Returns a new set containing the given objects.
-# - ::new -
+# - ::new:
# Returns a new set containing either the given objects
# (if no block given) or the return values from the called block
# (if a block given).
#
# ### Methods for \Set Operations
#
-# - [|](#method-i-7C) (aliased as #union and #+) -
+# - [|](#method-i-7C) (aliased as #union and #+):
# Returns a new set containing all elements from +self+
# and all elements from a given enumerable (no duplicates).
-# - [&](#method-i-26) (aliased as #intersection) -
+# - [&](#method-i-26) (aliased as #intersection):
# Returns a new set containing all elements common to +self+
# and a given enumerable.
-# - [-](#method-i-2D) (aliased as #difference) -
+# - [-](#method-i-2D) (aliased as #difference):
# Returns a copy of +self+ with all elements
# in a given enumerable removed.
-# - [\^](#method-i-5E) -
+# - [\^](#method-i-5E):
# Returns a new set containing all elements from +self+
# and a given enumerable except those common to both.
#
# ### Methods for Comparing
#
-# - [<=>](#method-i-3C-3D-3E) -
+# - [<=>](#method-i-3C-3D-3E):
# Returns -1, 0, or 1 as +self+ is less than, equal to,
# or greater than a given object.
-# - [==](#method-i-3D-3D) -
+# - [==](#method-i-3D-3D):
# Returns whether +self+ and a given enumerable are equal,
# as determined by Object#eql?.
-# - \#compare_by_identity? -
+# - \#compare_by_identity?:
# Returns whether the set considers only identity
# when comparing elements.
#
# ### Methods for Querying
#
-# - \#length (aliased as #size) -
+# - \#length (aliased as #size):
# Returns the count of elements.
-# - \#empty? -
+# - \#empty?:
# Returns whether the set has no elements.
-# - \#include? (aliased as #member? and #===) -
+# - \#include? (aliased as #member? and #===):
# Returns whether a given object is an element in the set.
-# - \#subset? (aliased as [<=](#method-i-3C-3D)) -
+# - \#subset? (aliased as [<=](#method-i-3C-3D)):
# Returns whether a given object is a subset of the set.
-# - \#proper_subset? (aliased as [<](#method-i-3C)) -
+# - \#proper_subset? (aliased as [<](#method-i-3C)):
# Returns whether a given enumerable is a proper subset of the set.
-# - \#superset? (aliased as [<=](#method-i-3E-3D])) -
+# - \#superset? (aliased as [>=](#method-i-3E-3D])):
# Returns whether a given enumerable is a superset of the set.
-# - \#proper_superset? (aliased as [>](#method-i-3E)) -
+# - \#proper_superset? (aliased as [>](#method-i-3E)):
# Returns whether a given enumerable is a proper superset of the set.
-# - \#disjoint? -
+# - \#disjoint?:
# Returns +true+ if the set and a given enumerable
# have no common elements, +false+ otherwise.
-# - \#intersect? -
-# Returns +true+ if the set and a given enumerable -
+# - \#intersect?:
+# Returns +true+ if the set and a given enumerable:
# have any common elements, +false+ otherwise.
-# - \#compare_by_identity? -
+# - \#compare_by_identity?:
# Returns whether the set considers only identity
# when comparing elements.
#
# ### Methods for Assigning
#
-# - \#add (aliased as #<<) -
+# - \#add (aliased as #<<):
# Adds a given object to the set; returns +self+.
-# - \#add? -
+# - \#add?:
# If the given object is not an element in the set,
# adds it and returns +self+; otherwise, returns +nil+.
-# - \#merge -
+# - \#merge:
# Adds each given object to the set; returns +self+.
-# - \#replace -
+# - \#replace:
# Replaces the contents of the set with the contents
# of a given enumerable.
#
# ### Methods for Deleting
#
-# - \#clear -
+# - \#clear:
# Removes all elements in the set; returns +self+.
-# - \#delete -
+# - \#delete:
# Removes a given object from the set; returns +self+.
-# - \#delete? -
+# - \#delete?:
# If the given object is an element in the set,
# removes it and returns +self+; otherwise, returns +nil+.
-# - \#subtract -
+# - \#subtract:
# Removes each given object from the set; returns +self+.
# - \#delete_if - Removes elements specified by a given block.
-# - \#select! (aliased as #filter!) -
+# - \#select! (aliased as #filter!):
# Removes elements not specified by a given block.
-# - \#keep_if -
+# - \#keep_if:
# Removes elements not specified by a given block.
# - \#reject!
# Removes elements specified by a given block.
#
# ### Methods for Converting
#
-# - \#classify -
+# - \#classify:
# Returns a hash that classifies the elements,
# as determined by the given block.
-# - \#collect! (aliased as #map!) -
+# - \#collect! (aliased as #map!):
# Replaces each element with a block return-value.
-# - \#divide -
+# - \#divide:
# Returns a hash that classifies the elements,
# as determined by the given block;
# differs from #classify in that the block may accept
# either one or two arguments.
-# - \#flatten -
+# - \#flatten:
# Returns a new set that is a recursive flattening of +self+.
-# \#flatten! -
+# \#flatten!:
# Replaces each nested set in +self+ with the elements from that set.
-# - \#inspect (aliased as #to_s) -
+# - \#inspect (aliased as #to_s):
# Returns a string displaying the elements.
-# - \#join -
+# - \#join:
# Returns a string containing all elements, converted to strings
# as needed, and joined by the given record separator.
-# - \#to_a -
+# - \#to_a:
# Returns an array containing all set elements.
-# - \#to_set -
+# - \#to_set:
# Returns +self+ if given no arguments and no block;
# with a block given, returns a new set consisting of block
# return values.
#
# ### Methods for Iterating
#
-# - \#each -
+# - \#each:
# Calls the block with each successive element; returns +self+.
#
# ### Other Methods
#
-# - \#reset -
+# - \#reset:
# Resets the internal state; useful if an object
# has been modified while an element in the set.
#
@@ -834,13 +834,14 @@ class Set
alias to_s inspect
def pretty_print(pp) # :nodoc:
- pp.text sprintf('#<%s: {', self.class.name)
- pp.nest(1) {
- pp.seplist(self) { |o|
- pp.pp o
+ pp.group(1, sprintf('#<%s:', self.class.name), '>') {
+ pp.breakable
+ pp.group(1, '{', '}') {
+ pp.seplist(self) { |o|
+ pp.pp o
+ }
}
}
- pp.text "}>"
end
def pretty_print_cycle(pp) # :nodoc:
@@ -853,7 +854,7 @@ module Enumerable
# Needs to `require "set"` to use this method.
def to_set(klass = Set, *args, &block)
klass.new(self, *args, &block)
- end
+ end unless method_defined?(:to_set)
end
autoload :SortedSet, "#{__dir__}/set/sorted_set"
diff --git a/lib/set/set.gemspec b/lib/set/set.gemspec
index d14febaad4..0def52e859 100644
--- a/lib/set/set.gemspec
+++ b/lib/set/set.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "set"
- spec.version = "1.0.1"
+ spec.version = "1.0.3"
spec.authors = ["Akinori MUSHA"]
spec.email = ["knu@idaemons.org"]
diff --git a/lib/syntax_suggest.rb b/lib/syntax_suggest.rb
new file mode 100644
index 0000000000..1a45dfa676
--- /dev/null
+++ b/lib/syntax_suggest.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require_relative "syntax_suggest/core_ext"
diff --git a/lib/syntax_suggest/api.rb b/lib/syntax_suggest/api.rb
new file mode 100644
index 0000000000..74e53c2563
--- /dev/null
+++ b/lib/syntax_suggest/api.rb
@@ -0,0 +1,201 @@
+# frozen_string_literal: true
+
+require_relative "version"
+
+require "tmpdir"
+require "stringio"
+require "pathname"
+require "ripper"
+require "timeout"
+
+module SyntaxSuggest
+ # Used to indicate a default value that cannot
+ # be confused with another input.
+ DEFAULT_VALUE = Object.new.freeze
+
+ class Error < StandardError; end
+ TIMEOUT_DEFAULT = ENV.fetch("SYNTAX_SUGGEST_TIMEOUT", 1).to_i
+
+ # SyntaxSuggest.handle_error [Public]
+ #
+ # Takes a `SyntaxError` exception, uses the
+ # error message to locate the file. Then the file
+ # will be analyzed to find the location of the syntax
+ # error and emit that location to stderr.
+ #
+ # Example:
+ #
+ # begin
+ # require 'bad_file'
+ # rescue => e
+ # SyntaxSuggest.handle_error(e)
+ # end
+ #
+ # By default it will re-raise the exception unless
+ # `re_raise: false`. The message output location
+ # can be configured using the `io: $stderr` input.
+ #
+ # If a valid filename cannot be determined, the original
+ # exception will be re-raised (even with
+ # `re_raise: false`).
+ def self.handle_error(e, re_raise: true, io: $stderr)
+ unless e.is_a?(SyntaxError)
+ io.puts("SyntaxSuggest: Must pass a SyntaxError, got: #{e.class}")
+ raise e
+ end
+
+ file = PathnameFromMessage.new(e.message, io: io).call.name
+ raise e unless file
+
+ io.sync = true
+
+ call(
+ io: io,
+ source: file.read,
+ filename: file
+ )
+
+ raise e if re_raise
+ end
+
+ # SyntaxSuggest.call [Private]
+ #
+ # Main private interface
+ def self.call(source:, filename: DEFAULT_VALUE, terminal: DEFAULT_VALUE, record_dir: DEFAULT_VALUE, timeout: TIMEOUT_DEFAULT, io: $stderr)
+ search = nil
+ filename = nil if filename == DEFAULT_VALUE
+ Timeout.timeout(timeout) do
+ record_dir ||= ENV["DEBUG"] ? "tmp" : nil
+ search = CodeSearch.new(source, record_dir: record_dir).call
+ end
+
+ blocks = search.invalid_blocks
+ DisplayInvalidBlocks.new(
+ io: io,
+ blocks: blocks,
+ filename: filename,
+ terminal: terminal,
+ code_lines: search.code_lines
+ ).call
+ rescue Timeout::Error => e
+ io.puts "Search timed out SYNTAX_SUGGEST_TIMEOUT=#{timeout}, run with SYNTAX_SUGGEST_DEBUG=1 for more info"
+ io.puts e.backtrace.first(3).join($/)
+ end
+
+ # SyntaxSuggest.record_dir [Private]
+ #
+ # Used to generate a unique directory to record
+ # search steps for debugging
+ def self.record_dir(dir)
+ time = Time.now.strftime("%Y-%m-%d-%H-%M-%s-%N")
+ dir = Pathname(dir)
+ dir.join(time).tap { |path|
+ path.mkpath
+ alias_dir = dir.join("last")
+ FileUtils.rm_rf(alias_dir) if alias_dir.exist?
+ FileUtils.ln_sf(time, alias_dir)
+ }
+ end
+
+ # SyntaxSuggest.valid_without? [Private]
+ #
+ # This will tell you if the `code_lines` would be valid
+ # if you removed the `without_lines`. In short it's a
+ # way to detect if we've found the lines with syntax errors
+ # in our document yet.
+ #
+ # code_lines = [
+ # CodeLine.new(line: "def foo\n", index: 0)
+ # CodeLine.new(line: " def bar\n", index: 1)
+ # CodeLine.new(line: "end\n", index: 2)
+ # ]
+ #
+ # SyntaxSuggest.valid_without?(
+ # without_lines: code_lines[1],
+ # code_lines: code_lines
+ # ) # => true
+ #
+ # SyntaxSuggest.valid?(code_lines) # => false
+ def self.valid_without?(without_lines:, code_lines:)
+ lines = code_lines - Array(without_lines).flatten
+
+ if lines.empty?
+ true
+ else
+ valid?(lines)
+ end
+ end
+
+ # SyntaxSuggest.invalid? [Private]
+ #
+ # Opposite of `SyntaxSuggest.valid?`
+ def self.invalid?(source)
+ source = source.join if source.is_a?(Array)
+ source = source.to_s
+
+ Ripper.new(source).tap(&:parse).error?
+ end
+
+ # SyntaxSuggest.valid? [Private]
+ #
+ # Returns truthy if a given input source is valid syntax
+ #
+ # SyntaxSuggest.valid?(<<~EOM) # => true
+ # def foo
+ # end
+ # EOM
+ #
+ # SyntaxSuggest.valid?(<<~EOM) # => false
+ # def foo
+ # def bar # Syntax error here
+ # end
+ # EOM
+ #
+ # You can also pass in an array of lines and they'll be
+ # joined before evaluating
+ #
+ # SyntaxSuggest.valid?(
+ # [
+ # "def foo\n",
+ # "end\n"
+ # ]
+ # ) # => true
+ #
+ # SyntaxSuggest.valid?(
+ # [
+ # "def foo\n",
+ # " def bar\n", # Syntax error here
+ # "end\n"
+ # ]
+ # ) # => false
+ #
+ # As an FYI the CodeLine class instances respond to `to_s`
+ # so passing a CodeLine in as an object or as an array
+ # will convert it to it's code representation.
+ def self.valid?(source)
+ !invalid?(source)
+ end
+end
+
+# Integration
+require_relative "cli"
+
+# Core logic
+require_relative "code_search"
+require_relative "code_frontier"
+require_relative "explain_syntax"
+require_relative "clean_document"
+
+# Helpers
+require_relative "lex_all"
+require_relative "code_line"
+require_relative "code_block"
+require_relative "block_expand"
+require_relative "ripper_errors"
+require_relative "priority_queue"
+require_relative "unvisited_lines"
+require_relative "around_block_scan"
+require_relative "priority_engulf_queue"
+require_relative "pathname_from_message"
+require_relative "display_invalid_blocks"
+require_relative "parse_blocks_from_indent_line"
diff --git a/lib/syntax_suggest/around_block_scan.rb b/lib/syntax_suggest/around_block_scan.rb
new file mode 100644
index 0000000000..ce00431b3a
--- /dev/null
+++ b/lib/syntax_suggest/around_block_scan.rb
@@ -0,0 +1,232 @@
+# frozen_string_literal: true
+
+require_relative "scan_history"
+
+module SyntaxSuggest
+ # This class is useful for exploring contents before and after
+ # a block
+ #
+ # It searches above and below the passed in block to match for
+ # whatever criteria you give it:
+ #
+ # Example:
+ #
+ # def dog # 1
+ # puts "bark" # 2
+ # puts "bark" # 3
+ # end # 4
+ #
+ # scan = AroundBlockScan.new(
+ # code_lines: code_lines
+ # block: CodeBlock.new(lines: code_lines[1])
+ # )
+ #
+ # scan.scan_while { true }
+ #
+ # puts scan.before_index # => 0
+ # puts scan.after_index # => 3
+ #
+ class AroundBlockScan
+ def initialize(code_lines:, block:)
+ @code_lines = code_lines
+ @orig_indent = block.current_indent
+
+ @stop_after_kw = false
+ @force_add_empty = false
+ @force_add_hidden = false
+ @target_indent = nil
+
+ @scanner = ScanHistory.new(code_lines: code_lines, block: block)
+ end
+
+ # When using this flag, `scan_while` will
+ # bypass the block it's given and always add a
+ # line that responds truthy to `CodeLine#hidden?`
+ #
+ # Lines are hidden when they've been evaluated by
+ # the parser as part of a block and found to contain
+ # valid code.
+ def force_add_hidden
+ @force_add_hidden = true
+ self
+ end
+
+ # When using this flag, `scan_while` will
+ # bypass the block it's given and always add a
+ # line that responds truthy to `CodeLine#empty?`
+ #
+ # Empty lines contain no code, only whitespace such
+ # as leading spaces a newline.
+ def force_add_empty
+ @force_add_empty = true
+ self
+ end
+
+ # Tells `scan_while` to look for mismatched keyword/end-s
+ #
+ # When scanning up, if we see more keywords then end-s it will
+ # stop. This might happen when scanning outside of a method body.
+ # the first scan line up would be a keyword and this setting would
+ # trigger a stop.
+ #
+ # When scanning down, stop if there are more end-s than keywords.
+ def stop_after_kw
+ @stop_after_kw = true
+ self
+ end
+
+ # Main work method
+ #
+ # The scan_while method takes a block that yields lines above and
+ # below the block. If the yield returns true, the @before_index
+ # or @after_index are modified to include the matched line.
+ #
+ # In addition to yielding individual lines, the internals of this
+ # object give a mini DSL to handle common situations such as
+ # stopping if we've found a keyword/end mis-match in one direction
+ # or the other.
+ def scan_while
+ stop_next_up = false
+ stop_next_down = false
+
+ @scanner.scan(
+ up: ->(line, kw_count, end_count) {
+ next false if stop_next_up
+ next true if @force_add_hidden && line.hidden?
+ next true if @force_add_empty && line.empty?
+
+ if @stop_after_kw && kw_count > end_count
+ stop_next_up = true
+ end
+
+ yield line
+ },
+ down: ->(line, kw_count, end_count) {
+ next false if stop_next_down
+ next true if @force_add_hidden && line.hidden?
+ next true if @force_add_empty && line.empty?
+
+ if @stop_after_kw && end_count > kw_count
+ stop_next_down = true
+ end
+
+ yield line
+ }
+ )
+
+ self
+ end
+
+ # Scanning is intentionally conservative because
+ # we have no way of rolling back an agressive block (at this time)
+ #
+ # If a block was stopped for some trivial reason, (like an empty line)
+ # but the next line would have caused it to be balanced then we
+ # can check that condition and grab just one more line either up or
+ # down.
+ #
+ # For example, below if we're scanning up, line 2 might cause
+ # the scanning to stop. This is because empty lines might
+ # denote logical breaks where the user intended to chunk code
+ # which is a good place to stop and check validity. Unfortunately
+ # it also means we might have a "dangling" keyword or end.
+ #
+ # 1 def bark
+ # 2
+ # 3 end
+ #
+ # If lines 2 and 3 are in the block, then when this method is
+ # run it would see it is unbalanced, but that acquiring line 1
+ # would make it balanced, so that's what it does.
+ def lookahead_balance_one_line
+ kw_count = 0
+ end_count = 0
+ lines.each do |line|
+ kw_count += 1 if line.is_kw?
+ end_count += 1 if line.is_end?
+ end
+
+ return self if kw_count == end_count # nothing to balance
+
+ @scanner.commit_if_changed # Rollback point if we don't find anything to optimize
+
+ # Try to eat up empty lines
+ @scanner.scan(
+ up: ->(line, _, _) { line.hidden? || line.empty? },
+ down: ->(line, _, _) { line.hidden? || line.empty? }
+ )
+
+ # More ends than keywords, check if we can balance expanding up
+ next_up = @scanner.next_up
+ next_down = @scanner.next_down
+ case end_count - kw_count
+ when 1
+ if next_up&.is_kw? && next_up.indent >= @target_indent
+ @scanner.scan(
+ up: ->(line, _, _) { line == next_up },
+ down: ->(line, _, _) { false }
+ )
+ @scanner.commit_if_changed
+ end
+ when -1
+ if next_down&.is_end? && next_down.indent >= @target_indent
+ @scanner.scan(
+ up: ->(line, _, _) { false },
+ down: ->(line, _, _) { line == next_down }
+ )
+ @scanner.commit_if_changed
+ end
+ end
+ # Rollback any uncommitted changes
+ @scanner.stash_changes
+
+ self
+ end
+
+ # Finds code lines at the same or greater indentation and adds them
+ # to the block
+ def scan_neighbors_not_empty
+ @target_indent = @orig_indent
+ scan_while { |line| line.not_empty? && line.indent >= @target_indent }
+ end
+
+ # Scan blocks based on indentation of next line above/below block
+ #
+ # Determines indentaion of the next line above/below the current block.
+ #
+ # Normally this is called when a block has expanded to capture all "neighbors"
+ # at the same (or greater) indentation and needs to expand out. For example
+ # the `def/end` lines surrounding a method.
+ def scan_adjacent_indent
+ before_after_indent = []
+
+ before_after_indent << (@scanner.next_up&.indent || 0)
+ before_after_indent << (@scanner.next_down&.indent || 0)
+
+ @target_indent = before_after_indent.min
+ scan_while { |line| line.not_empty? && line.indent >= @target_indent }
+
+ self
+ end
+
+ # Return the currently matched lines as a `CodeBlock`
+ #
+ # When a `CodeBlock` is created it will gather metadata about
+ # itself, so this is not a free conversion. Avoid allocating
+ # more CodeBlock's than needed
+ def code_block
+ CodeBlock.new(lines: lines)
+ end
+
+ # Returns the lines matched by the current scan as an
+ # array of CodeLines
+ def lines
+ @scanner.lines
+ end
+
+ # Managable rspec errors
+ def inspect
+ "#<#{self.class}:0x0000123843lol >"
+ end
+ end
+end
diff --git a/lib/syntax_suggest/block_expand.rb b/lib/syntax_suggest/block_expand.rb
new file mode 100644
index 0000000000..e9b486c720
--- /dev/null
+++ b/lib/syntax_suggest/block_expand.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # This class is responsible for taking a code block that exists
+ # at a far indentaion and then iteratively increasing the block
+ # so that it captures everything within the same indentation block.
+ #
+ # def dog
+ # puts "bow"
+ # puts "wow"
+ # end
+ #
+ # block = BlockExpand.new(code_lines: code_lines)
+ # .call(CodeBlock.new(lines: code_lines[1]))
+ #
+ # puts block.to_s
+ # # => puts "bow"
+ # puts "wow"
+ #
+ #
+ # Once a code block has captured everything at a given indentation level
+ # then it will expand to capture surrounding indentation.
+ #
+ # block = BlockExpand.new(code_lines: code_lines)
+ # .call(block)
+ #
+ # block.to_s
+ # # => def dog
+ # puts "bow"
+ # puts "wow"
+ # end
+ #
+ class BlockExpand
+ def initialize(code_lines:)
+ @code_lines = code_lines
+ end
+
+ # Main interface. Expand current indentation, before
+ # expanding to a lower indentation
+ def call(block)
+ if (next_block = expand_neighbors(block))
+ next_block
+ else
+ expand_indent(block)
+ end
+ end
+
+ # Expands code to the next lowest indentation
+ #
+ # For example:
+ #
+ # 1 def dog
+ # 2 print "dog"
+ # 3 end
+ #
+ # If a block starts on line 2 then it has captured all it's "neighbors" (code at
+ # the same indentation or higher). To continue expanding, this block must capture
+ # lines one and three which are at a different indentation level.
+ #
+ # This method allows fully expanded blocks to decrease their indentation level (so
+ # they can expand to capture more code up and down). It does this conservatively
+ # as there's no undo (currently).
+ def expand_indent(block)
+ now = AroundBlockScan.new(code_lines: @code_lines, block: block)
+ .force_add_hidden
+ .stop_after_kw
+ .scan_adjacent_indent
+
+ now.lookahead_balance_one_line
+
+ now.code_block
+ end
+
+ # A neighbor is code that is at or above the current indent line.
+ #
+ # First we build a block with all neighbors. If we can't go further
+ # then we decrease the indentation threshold and expand via indentation
+ # i.e. `expand_indent`
+ #
+ # Handles two general cases.
+ #
+ # ## Case #1: Check code inside of methods/classes/etc.
+ #
+ # It's important to note, that not everything in a given indentation level can be parsed
+ # as valid code even if it's part of valid code. For example:
+ #
+ # 1 hash = {
+ # 2 name: "richard",
+ # 3 dog: "cinco",
+ # 4 }
+ #
+ # In this case lines 2 and 3 will be neighbors, but they're invalid until `expand_indent`
+ # is called on them.
+ #
+ # When we are adding code within a method or class (at the same indentation level),
+ # use the empty lines to denote the programmer intended logical chunks.
+ # Stop and check each one. For example:
+ #
+ # 1 def dog
+ # 2 print "dog"
+ # 3
+ # 4 hash = {
+ # 5 end
+ #
+ # If we did not stop parsing at empty newlines then the block might mistakenly grab all
+ # the contents (lines 2, 3, and 4) and report them as being problems, instead of only
+ # line 4.
+ #
+ # ## Case #2: Expand/grab other logical blocks
+ #
+ # Once the search algorithm has converted all lines into blocks at a given indentation
+ # it will then `expand_indent`. Once the blocks that generates are expanded as neighbors
+ # we then begin seeing neighbors being other logical blocks i.e. a block's neighbors
+ # may be another method or class (something with keywords/ends).
+ #
+ # For example:
+ #
+ # 1 def bark
+ # 2
+ # 3 end
+ # 4
+ # 5 def sit
+ # 6 end
+ #
+ # In this case if lines 4, 5, and 6 are in a block when it tries to expand neighbors
+ # it will expand up. If it stops after line 2 or 3 it may cause problems since there's a
+ # valid kw/end pair, but the block will be checked without it.
+ #
+ # We try to resolve this edge case with `lookahead_balance_one_line` below.
+ def expand_neighbors(block)
+ now = AroundBlockScan.new(code_lines: @code_lines, block: block)
+
+ # Initial scan
+ now
+ .force_add_hidden
+ .stop_after_kw
+ .scan_neighbors_not_empty
+
+ # Slurp up empties
+ now
+ .scan_while { |line| line.empty? }
+
+ # If next line is kw and it will balance us, take it
+ expanded_lines = now
+ .lookahead_balance_one_line
+ .lines
+
+ # Don't allocate a block if it won't be used
+ #
+ # If nothing was taken, return nil to indicate that status
+ # used in `def call` to determine if
+ # we need to expand up/out (`expand_indent`)
+ if block.lines == expanded_lines
+ nil
+ else
+ CodeBlock.new(lines: expanded_lines)
+ end
+ end
+
+ # Managable rspec errors
+ def inspect
+ "#<SyntaxSuggest::CodeBlock:0x0000123843lol >"
+ end
+ end
+end
diff --git a/lib/syntax_suggest/capture/before_after_keyword_ends.rb b/lib/syntax_suggest/capture/before_after_keyword_ends.rb
new file mode 100644
index 0000000000..f53c57a4d1
--- /dev/null
+++ b/lib/syntax_suggest/capture/before_after_keyword_ends.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ module Capture
+ # Shows surrounding kw/end pairs
+ #
+ # The purpose of showing these extra pairs is due to cases
+ # of ambiguity when only one visible line is matched.
+ #
+ # For example:
+ #
+ # 1 class Dog
+ # 2 def bark
+ # 4 def eat
+ # 5 end
+ # 6 end
+ #
+ # In this case either line 2 could be missing an `end` or
+ # line 4 was an extra line added by mistake (it happens).
+ #
+ # When we detect the above problem it shows the issue
+ # as only being on line 2
+ #
+ # 2 def bark
+ #
+ # Showing "neighbor" keyword pairs gives extra context:
+ #
+ # 2 def bark
+ # 4 def eat
+ # 5 end
+ #
+ #
+ # Example:
+ #
+ # lines = BeforeAfterKeywordEnds.new(
+ # block: block,
+ # code_lines: code_lines
+ # ).call()
+ #
+ class BeforeAfterKeywordEnds
+ def initialize(code_lines:, block:)
+ @scanner = ScanHistory.new(code_lines: code_lines, block: block)
+ @original_indent = block.current_indent
+ end
+
+ def call
+ lines = []
+
+ @scanner.scan(
+ up: ->(line, kw_count, end_count) {
+ next true if line.empty?
+ break if line.indent < @original_indent
+ next true if line.indent != @original_indent
+
+ # If we're going up and have one complete kw/end pair, stop
+ if kw_count != 0 && kw_count == end_count
+ lines << line
+ break
+ end
+
+ lines << line if line.is_kw? || line.is_end?
+ true
+ },
+ down: ->(line, kw_count, end_count) {
+ next true if line.empty?
+ break if line.indent < @original_indent
+ next true if line.indent != @original_indent
+
+ # if we're going down and have one complete kw/end pair,stop
+ if kw_count != 0 && kw_count == end_count
+ lines << line
+ break
+ end
+
+ lines << line if line.is_kw? || line.is_end?
+ true
+ }
+ )
+ @scanner.stash_changes
+
+ lines
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/capture/falling_indent_lines.rb b/lib/syntax_suggest/capture/falling_indent_lines.rb
new file mode 100644
index 0000000000..1e046b2ba5
--- /dev/null
+++ b/lib/syntax_suggest/capture/falling_indent_lines.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ module Capture
+ # Shows the context around code provided by "falling" indentation
+ #
+ # If this is the original code lines:
+ #
+ # class OH
+ # def hello
+ # it "foo" do
+ # end
+ # end
+ #
+ # And this is the line that is captured
+ #
+ # it "foo" do
+ #
+ # It will yield its surrounding context:
+ #
+ # class OH
+ # def hello
+ # end
+ # end
+ #
+ # Example:
+ #
+ # FallingIndentLines.new(
+ # block: block,
+ # code_lines: @code_lines
+ # ).call do |line|
+ # @lines_to_output << line
+ # end
+ #
+ class FallingIndentLines
+ def initialize(code_lines:, block:)
+ @lines = nil
+ @scanner = ScanHistory.new(code_lines: code_lines, block: block)
+ @original_indent = block.current_indent
+ end
+
+ def call(&yieldable)
+ last_indent_up = @original_indent
+ last_indent_down = @original_indent
+
+ @scanner.commit_if_changed
+ @scanner.scan(
+ up: ->(line, _, _) {
+ next true if line.empty?
+
+ if line.indent < last_indent_up
+ yieldable.call(line)
+ last_indent_up = line.indent
+ end
+ true
+ },
+ down: ->(line, _, _) {
+ next true if line.empty?
+
+ if line.indent < last_indent_down
+ yieldable.call(line)
+ last_indent_down = line.indent
+ end
+ true
+ }
+ )
+ @scanner.stash_changes
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/capture_code_context.rb b/lib/syntax_suggest/capture_code_context.rb
new file mode 100644
index 0000000000..6dc7047176
--- /dev/null
+++ b/lib/syntax_suggest/capture_code_context.rb
@@ -0,0 +1,245 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ module Capture
+ end
+end
+
+require_relative "capture/falling_indent_lines"
+require_relative "capture/before_after_keyword_ends"
+
+module SyntaxSuggest
+ # Turns a "invalid block(s)" into useful context
+ #
+ # There are three main phases in the algorithm:
+ #
+ # 1. Sanitize/format input source
+ # 2. Search for invalid blocks
+ # 3. Format invalid blocks into something meaninful
+ #
+ # This class handles the third part.
+ #
+ # The algorithm is very good at capturing all of a syntax
+ # error in a single block in number 2, however the results
+ # can contain ambiguities. Humans are good at pattern matching
+ # and filtering and can mentally remove extraneous data, but
+ # they can't add extra data that's not present.
+ #
+ # In the case of known ambiguious cases, this class adds context
+ # back to the ambiguitiy so the programmer has full information.
+ #
+ # Beyond handling these ambiguities, it also captures surrounding
+ # code context information:
+ #
+ # puts block.to_s # => "def bark"
+ #
+ # context = CaptureCodeContext.new(
+ # blocks: block,
+ # code_lines: code_lines
+ # )
+ #
+ # lines = context.call.map(&:original)
+ # puts lines.join
+ # # =>
+ # class Dog
+ # def bark
+ # end
+ #
+ class CaptureCodeContext
+ attr_reader :code_lines
+
+ def initialize(blocks:, code_lines:)
+ @blocks = Array(blocks)
+ @code_lines = code_lines
+ @visible_lines = @blocks.map(&:visible_lines).flatten
+ @lines_to_output = @visible_lines.dup
+ end
+
+ def call
+ @blocks.each do |block|
+ capture_first_kw_end_same_indent(block)
+ capture_last_end_same_indent(block)
+ capture_before_after_kws(block)
+ capture_falling_indent(block)
+ end
+
+ sorted_lines
+ end
+
+ def sorted_lines
+ @lines_to_output.select!(&:not_empty?)
+ @lines_to_output.uniq!
+ @lines_to_output.sort!
+
+ @lines_to_output
+ end
+
+ # Shows the context around code provided by "falling" indentation
+ #
+ # Converts:
+ #
+ # it "foo" do
+ #
+ # into:
+ #
+ # class OH
+ # def hello
+ # it "foo" do
+ # end
+ # end
+ #
+ def capture_falling_indent(block)
+ Capture::FallingIndentLines.new(
+ block: block,
+ code_lines: @code_lines
+ ).call do |line|
+ @lines_to_output << line
+ end
+ end
+
+ # Shows surrounding kw/end pairs
+ #
+ # The purpose of showing these extra pairs is due to cases
+ # of ambiguity when only one visible line is matched.
+ #
+ # For example:
+ #
+ # 1 class Dog
+ # 2 def bark
+ # 4 def eat
+ # 5 end
+ # 6 end
+ #
+ # In this case either line 2 could be missing an `end` or
+ # line 4 was an extra line added by mistake (it happens).
+ #
+ # When we detect the above problem it shows the issue
+ # as only being on line 2
+ #
+ # 2 def bark
+ #
+ # Showing "neighbor" keyword pairs gives extra context:
+ #
+ # 2 def bark
+ # 4 def eat
+ # 5 end
+ #
+ def capture_before_after_kws(block)
+ return unless block.visible_lines.count == 1
+
+ around_lines = Capture::BeforeAfterKeywordEnds.new(
+ code_lines: @code_lines,
+ block: block
+ ).call
+
+ around_lines -= block.lines
+
+ @lines_to_output.concat(around_lines)
+ end
+
+ # When there is an invalid block with a keyword
+ # missing an end right before another end,
+ # it is unclear where which keyword is missing the
+ # end
+ #
+ # Take this example:
+ #
+ # class Dog # 1
+ # def bark # 2
+ # puts "woof" # 3
+ # end # 4
+ #
+ # However due to https://github.com/ruby/syntax_suggest/issues/32
+ # the problem line will be identified as:
+ #
+ # > class Dog # 1
+ #
+ # Because lines 2, 3, and 4 are technically valid code and are expanded
+ # first, deemed valid, and hidden. We need to un-hide the matching end
+ # line 4. Also work backwards and if there's a mis-matched keyword, show it
+ # too
+ def capture_last_end_same_indent(block)
+ return if block.visible_lines.length != 1
+ return unless block.visible_lines.first.is_kw?
+
+ visible_line = block.visible_lines.first
+ lines = @code_lines[visible_line.index..block.lines.last.index]
+
+ # Find first end with same indent
+ # (this would return line 4)
+ #
+ # end # 4
+ matching_end = lines.detect { |line| line.indent == block.current_indent && line.is_end? }
+ return unless matching_end
+
+ @lines_to_output << matching_end
+
+ # Work backwards from the end to
+ # see if there are mis-matched
+ # keyword/end pairs
+ #
+ # Return the first mis-matched keyword
+ # this would find line 2
+ #
+ # def bark # 2
+ # puts "woof" # 3
+ # end # 4
+ end_count = 0
+ kw_count = 0
+ kw_line = @code_lines[visible_line.index..matching_end.index].reverse.detect do |line|
+ end_count += 1 if line.is_end?
+ kw_count += 1 if line.is_kw?
+
+ !kw_count.zero? && kw_count >= end_count
+ end
+ return unless kw_line
+ @lines_to_output << kw_line
+ end
+
+ # The logical inverse of `capture_last_end_same_indent`
+ #
+ # When there is an invalid block with an `end`
+ # missing a keyword right after another `end`,
+ # it is unclear where which end is missing the
+ # keyword.
+ #
+ # Take this example:
+ #
+ # class Dog # 1
+ # puts "woof" # 2
+ # end # 3
+ # end # 4
+ #
+ # the problem line will be identified as:
+ #
+ # > end # 4
+ #
+ # This happens because lines 1, 2, and 3 are technically valid code and are expanded
+ # first, deemed valid, and hidden. We need to un-hide the matching keyword on
+ # line 1. Also work backwards and if there's a mis-matched end, show it
+ # too
+ def capture_first_kw_end_same_indent(block)
+ return if block.visible_lines.length != 1
+ return unless block.visible_lines.first.is_end?
+
+ visible_line = block.visible_lines.first
+ lines = @code_lines[block.lines.first.index..visible_line.index]
+ matching_kw = lines.reverse.detect { |line| line.indent == block.current_indent && line.is_kw? }
+ return unless matching_kw
+
+ @lines_to_output << matching_kw
+
+ kw_count = 0
+ end_count = 0
+ orphan_end = @code_lines[matching_kw.index..visible_line.index].detect do |line|
+ kw_count += 1 if line.is_kw?
+ end_count += 1 if line.is_end?
+
+ end_count >= kw_count
+ end
+
+ return unless orphan_end
+ @lines_to_output << orphan_end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/clean_document.rb b/lib/syntax_suggest/clean_document.rb
new file mode 100644
index 0000000000..2c26061bfc
--- /dev/null
+++ b/lib/syntax_suggest/clean_document.rb
@@ -0,0 +1,306 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Parses and sanitizes source into a lexically aware document
+ #
+ # Internally the document is represented by an array with each
+ # index containing a CodeLine correlating to a line from the source code.
+ #
+ # There are three main phases in the algorithm:
+ #
+ # 1. Sanitize/format input source
+ # 2. Search for invalid blocks
+ # 3. Format invalid blocks into something meaninful
+ #
+ # This class handles the first part.
+ #
+ # The reason this class exists is to format input source
+ # for better/easier/cleaner exploration.
+ #
+ # The CodeSearch class operates at the line level so
+ # we must be careful to not introduce lines that look
+ # valid by themselves, but when removed will trigger syntax errors
+ # or strange behavior.
+ #
+ # ## Join Trailing slashes
+ #
+ # Code with a trailing slash is logically treated as a single line:
+ #
+ # 1 it "code can be split" \
+ # 2 "across multiple lines" do
+ #
+ # In this case removing line 2 would add a syntax error. We get around
+ # this by internally joining the two lines into a single "line" object
+ #
+ # ## Logically Consecutive lines
+ #
+ # Code that can be broken over multiple
+ # lines such as method calls are on different lines:
+ #
+ # 1 User.
+ # 2 where(name: "schneems").
+ # 3 first
+ #
+ # Removing line 2 can introduce a syntax error. To fix this, all lines
+ # are joined into one.
+ #
+ # ## Heredocs
+ #
+ # A heredoc is an way of defining a multi-line string. They can cause many
+ # problems. If left as a single line, Ripper would try to parse the contents
+ # as ruby code rather than as a string. Even without this problem, we still
+ # hit an issue with indentation
+ #
+ # 1 foo = <<~HEREDOC
+ # 2 "Be yourself; everyone else is already taken.""
+ # 3 ― Oscar Wilde
+ # 4 puts "I look like ruby code" # but i'm still a heredoc
+ # 5 HEREDOC
+ #
+ # If we didn't join these lines then our algorithm would think that line 4
+ # is separate from the rest, has a higher indentation, then look at it first
+ # and remove it.
+ #
+ # If the code evaluates line 5 by itself it will think line 5 is a constant,
+ # remove it, and introduce a syntax errror.
+ #
+ # All of these problems are fixed by joining the whole heredoc into a single
+ # line.
+ #
+ # ## Comments and whitespace
+ #
+ # Comments can throw off the way the lexer tells us that the line
+ # logically belongs with the next line. This is valid ruby but
+ # results in a different lex output than before:
+ #
+ # 1 User.
+ # 2 where(name: "schneems").
+ # 3 # Comment here
+ # 4 first
+ #
+ # To handle this we can replace comment lines with empty lines
+ # and then re-lex the source. This removal and re-lexing preserves
+ # line index and document size, but generates an easier to work with
+ # document.
+ #
+ class CleanDocument
+ def initialize(source:)
+ lines = clean_sweep(source: source)
+ @document = CodeLine.from_source(lines.join, lines: lines)
+ end
+
+ # Call all of the document "cleaners"
+ # and return self
+ def call
+ join_trailing_slash!
+ join_consecutive!
+ join_heredoc!
+
+ self
+ end
+
+ # Return an array of CodeLines in the
+ # document
+ def lines
+ @document
+ end
+
+ # Renders the document back to a string
+ def to_s
+ @document.join
+ end
+
+ # Remove comments
+ #
+ # replace with empty newlines
+ #
+ # source = <<~'EOM'
+ # # Comment 1
+ # puts "hello"
+ # # Comment 2
+ # puts "world"
+ # EOM
+ #
+ # lines = CleanDocument.new(source: source).lines
+ # expect(lines[0].to_s).to eq("\n")
+ # expect(lines[1].to_s).to eq("puts "hello")
+ # expect(lines[2].to_s).to eq("\n")
+ # expect(lines[3].to_s).to eq("puts "world")
+ #
+ # Important: This must be done before lexing.
+ #
+ # After this change is made, we lex the document because
+ # removing comments can change how the doc is parsed.
+ #
+ # For example:
+ #
+ # values = LexAll.new(source: <<~EOM))
+ # User.
+ # # comment
+ # where(name: 'schneems')
+ # EOM
+ # expect(
+ # values.count {|v| v.type == :on_ignored_nl}
+ # ).to eq(1)
+ #
+ # After the comment is removed:
+ #
+ # values = LexAll.new(source: <<~EOM))
+ # User.
+ #
+ # where(name: 'schneems')
+ # EOM
+ # expect(
+ # values.count {|v| v.type == :on_ignored_nl}
+ # ).to eq(2)
+ #
+ def clean_sweep(source:)
+ # Match comments, but not HEREDOC strings with #{variable} interpolation
+ # https://rubular.com/r/HPwtW9OYxKUHXQ
+ source.lines.map do |line|
+ if line.match?(/^\s*#([^{].*|)$/)
+ $/
+ else
+ line
+ end
+ end
+ end
+
+ # Smushes all heredoc lines into one line
+ #
+ # source = <<~'EOM'
+ # foo = <<~HEREDOC
+ # lol
+ # hehehe
+ # HEREDOC
+ # EOM
+ #
+ # lines = CleanDocument.new(source: source).join_heredoc!.lines
+ # expect(lines[0].to_s).to eq(source)
+ # expect(lines[1].to_s).to eq("")
+ def join_heredoc!
+ start_index_stack = []
+ heredoc_beg_end_index = []
+ lines.each do |line|
+ line.lex.each do |lex_value|
+ case lex_value.type
+ when :on_heredoc_beg
+ start_index_stack << line.index
+ when :on_heredoc_end
+ start_index = start_index_stack.pop
+ end_index = line.index
+ heredoc_beg_end_index << [start_index, end_index]
+ end
+ end
+ end
+
+ heredoc_groups = heredoc_beg_end_index.map { |start_index, end_index| @document[start_index..end_index] }
+
+ join_groups(heredoc_groups)
+ self
+ end
+
+ # Smushes logically "consecutive" lines
+ #
+ # source = <<~'EOM'
+ # User.
+ # where(name: 'schneems').
+ # first
+ # EOM
+ #
+ # lines = CleanDocument.new(source: source).join_consecutive!.lines
+ # expect(lines[0].to_s).to eq(source)
+ # expect(lines[1].to_s).to eq("")
+ #
+ # The one known case this doesn't handle is:
+ #
+ # Ripper.lex <<~EOM
+ # a &&
+ # b ||
+ # c
+ # EOM
+ #
+ # For some reason this introduces `on_ignore_newline` but with BEG type
+ #
+ def join_consecutive!
+ consecutive_groups = @document.select(&:ignore_newline_not_beg?).map do |code_line|
+ take_while_including(code_line.index..-1) do |line|
+ line.ignore_newline_not_beg?
+ end
+ end
+
+ join_groups(consecutive_groups)
+ self
+ end
+
+ # Join lines with a trailing slash
+ #
+ # source = <<~'EOM'
+ # it "code can be split" \
+ # "across multiple lines" do
+ # EOM
+ #
+ # lines = CleanDocument.new(source: source).join_consecutive!.lines
+ # expect(lines[0].to_s).to eq(source)
+ # expect(lines[1].to_s).to eq("")
+ def join_trailing_slash!
+ trailing_groups = @document.select(&:trailing_slash?).map do |code_line|
+ take_while_including(code_line.index..-1) { |x| x.trailing_slash? }
+ end
+ join_groups(trailing_groups)
+ self
+ end
+
+ # Helper method for joining "groups" of lines
+ #
+ # Input is expected to be type Array<Array<CodeLine>>
+ #
+ # The outer array holds the various "groups" while the
+ # inner array holds code lines.
+ #
+ # All code lines are "joined" into the first line in
+ # their group.
+ #
+ # To preserve document size, empty lines are placed
+ # in the place of the lines that were "joined"
+ def join_groups(groups)
+ groups.each do |lines|
+ line = lines.first
+
+ # Handle the case of multiple groups in a a row
+ # if one is already replaced, move on
+ next if @document[line.index].empty?
+
+ # Join group into the first line
+ @document[line.index] = CodeLine.new(
+ lex: lines.map(&:lex).flatten,
+ line: lines.join,
+ index: line.index
+ )
+
+ # Hide the rest of the lines
+ lines[1..-1].each do |line|
+ # The above lines already have newlines in them, if add more
+ # then there will be double newline, use an empty line instead
+ @document[line.index] = CodeLine.new(line: "", index: line.index, lex: [])
+ end
+ end
+ self
+ end
+
+ # Helper method for grabbing elements from document
+ #
+ # Like `take_while` except when it stops
+ # iterating, it also returns the line
+ # that caused it to stop
+ def take_while_including(range = 0..-1)
+ take_next_and_stop = false
+ @document[range].take_while do |line|
+ next if take_next_and_stop
+
+ take_next_and_stop = !(yield line)
+ true
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/cli.rb b/lib/syntax_suggest/cli.rb
new file mode 100644
index 0000000000..967f77bf70
--- /dev/null
+++ b/lib/syntax_suggest/cli.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+require "pathname"
+require "optparse"
+
+module SyntaxSuggest
+ # All the logic of the exe/syntax_suggest CLI in one handy spot
+ #
+ # Cli.new(argv: ["--help"]).call
+ # Cli.new(argv: ["<path/to/file>.rb"]).call
+ # Cli.new(argv: ["<path/to/file>.rb", "--record=tmp"]).call
+ # Cli.new(argv: ["<path/to/file>.rb", "--terminal"]).call
+ #
+ class Cli
+ attr_accessor :options
+
+ # ARGV is Everything passed to the executable, does not include executable name
+ #
+ # All other intputs are dependency injection for testing
+ def initialize(argv:, exit_obj: Kernel, io: $stdout, env: ENV)
+ @options = {}
+ @parser = nil
+ options[:record_dir] = env["SYNTAX_SUGGEST_RECORD_DIR"]
+ options[:record_dir] = "tmp" if env["DEBUG"]
+ options[:terminal] = SyntaxSuggest::DEFAULT_VALUE
+
+ @io = io
+ @argv = argv
+ @exit_obj = exit_obj
+ end
+
+ def call
+ if @argv.empty?
+ # Display help if raw command
+ parser.parse! %w[--help]
+ return
+ else
+ # Mutates @argv
+ parse
+ return if options[:exit]
+ end
+
+ file_name = @argv.first
+ if file_name.nil?
+ @io.puts "No file given"
+ @exit_obj.exit(1)
+ return
+ end
+
+ file = Pathname(file_name)
+ if !file.exist?
+ @io.puts "file not found: #{file.expand_path} "
+ @exit_obj.exit(1)
+ return
+ end
+
+ @io.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
+
+ display = SyntaxSuggest.call(
+ io: @io,
+ source: file.read,
+ filename: file.expand_path,
+ terminal: options.fetch(:terminal, SyntaxSuggest::DEFAULT_VALUE),
+ record_dir: options[:record_dir]
+ )
+
+ if display.document_ok?
+ @io.puts "Syntax OK"
+ @exit_obj.exit(0)
+ else
+ @exit_obj.exit(1)
+ end
+ end
+
+ def parse
+ parser.parse!(@argv)
+
+ self
+ end
+
+ def parser
+ @parser ||= OptionParser.new do |opts|
+ opts.banner = <<~EOM
+ Usage: syntax_suggest <file> [options]
+
+ Parses a ruby source file and searches for syntax error(s) such as
+ unexpected `end', expecting end-of-input.
+
+ Example:
+
+ $ syntax_suggest dog.rb
+
+ # ...
+
+ > 10 defdog
+ > 15 end
+
+ ENV options:
+
+ SYNTAX_SUGGEST_RECORD_DIR=<dir>
+
+ Records the steps used to search for a syntax error
+ to the given directory
+
+ Options:
+ EOM
+
+ opts.version = SyntaxSuggest::VERSION
+
+ opts.on("--help", "Help - displays this message") do |v|
+ @io.puts opts
+ options[:exit] = true
+ @exit_obj.exit
+ end
+
+ opts.on("--record <dir>", "Records the steps used to search for a syntax error to the given directory") do |v|
+ options[:record_dir] = v
+ end
+
+ opts.on("--terminal", "Enable terminal highlighting") do |v|
+ options[:terminal] = true
+ end
+
+ opts.on("--no-terminal", "Disable terminal highlighting") do |v|
+ options[:terminal] = false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/code_block.rb b/lib/syntax_suggest/code_block.rb
new file mode 100644
index 0000000000..61e7986da4
--- /dev/null
+++ b/lib/syntax_suggest/code_block.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Multiple lines form a singular CodeBlock
+ #
+ # Source code is made of multiple CodeBlocks.
+ #
+ # Example:
+ #
+ # code_block.to_s # =>
+ # # def foo
+ # # puts "foo"
+ # # end
+ #
+ # code_block.valid? # => true
+ # code_block.in_valid? # => false
+ #
+ #
+ class CodeBlock
+ UNSET = Object.new.freeze
+ attr_reader :lines, :starts_at, :ends_at
+
+ def initialize(lines: [])
+ @lines = Array(lines)
+ @valid = UNSET
+ @deleted = false
+ @starts_at = @lines.first.number
+ @ends_at = @lines.last.number
+ end
+
+ def delete
+ @deleted = true
+ end
+
+ def deleted?
+ @deleted
+ end
+
+ def visible_lines
+ @lines.select(&:visible?).select(&:not_empty?)
+ end
+
+ def mark_invisible
+ @lines.map(&:mark_invisible)
+ end
+
+ def is_end?
+ to_s.strip == "end"
+ end
+
+ def hidden?
+ @lines.all?(&:hidden?)
+ end
+
+ # This is used for frontier ordering, we are searching from
+ # the largest indentation to the smallest. This allows us to
+ # populate an array with multiple code blocks then call `sort!`
+ # on it without having to specify the sorting criteria
+ def <=>(other)
+ out = current_indent <=> other.current_indent
+ return out if out != 0
+
+ # Stable sort
+ starts_at <=> other.starts_at
+ end
+
+ def current_indent
+ @current_indent ||= lines.select(&:not_empty?).map(&:indent).min || 0
+ end
+
+ def invalid?
+ !valid?
+ end
+
+ def valid?
+ if @valid == UNSET
+ # Performance optimization
+ #
+ # If all the lines were previously hidden
+ # and we expand to capture additional empty
+ # lines then the result cannot be invalid
+ #
+ # That means there's no reason to re-check all
+ # lines with ripper (which is expensive).
+ # Benchmark in commit message
+ @valid = if lines.all? { |l| l.hidden? || l.empty? }
+ true
+ else
+ SyntaxSuggest.valid?(lines.map(&:original).join)
+ end
+ else
+ @valid
+ end
+ end
+
+ def to_s
+ @lines.join
+ end
+ end
+end
diff --git a/lib/syntax_suggest/code_frontier.rb b/lib/syntax_suggest/code_frontier.rb
new file mode 100644
index 0000000000..8e93b32514
--- /dev/null
+++ b/lib/syntax_suggest/code_frontier.rb
@@ -0,0 +1,178 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # The main function of the frontier is to hold the edges of our search and to
+ # evaluate when we can stop searching.
+
+ # There are three main phases in the algorithm:
+ #
+ # 1. Sanitize/format input source
+ # 2. Search for invalid blocks
+ # 3. Format invalid blocks into something meaninful
+ #
+ # The Code frontier is a critical part of the second step
+ #
+ # ## Knowing where we've been
+ #
+ # Once a code block is generated it is added onto the frontier. Then it will be
+ # sorted by indentation and frontier can be filtered. Large blocks that fully enclose a
+ # smaller block will cause the smaller block to be evicted.
+ #
+ # CodeFrontier#<<(block) # Adds block to frontier
+ # CodeFrontier#pop # Removes block from frontier
+ #
+ # ## Knowing where we can go
+ #
+ # Internally the frontier keeps track of "unvisited" lines which are exposed via `next_indent_line`
+ # when called, this method returns, a line of code with the highest indentation.
+ #
+ # The returned line of code can be used to build a CodeBlock and then that code block
+ # is added back to the frontier. Then, the lines are removed from the
+ # "unvisited" so we don't double-create the same block.
+ #
+ # CodeFrontier#next_indent_line # Shows next line
+ # CodeFrontier#register_indent_block(block) # Removes lines from unvisited
+ #
+ # ## Knowing when to stop
+ #
+ # The frontier knows how to check the entire document for a syntax error. When blocks
+ # are added onto the frontier, they're removed from the document. When all code containing
+ # syntax errors has been added to the frontier, the document will be parsable without a
+ # syntax error and the search can stop.
+ #
+ # CodeFrontier#holds_all_syntax_errors? # Returns true when frontier holds all syntax errors
+ #
+ # ## Filtering false positives
+ #
+ # Once the search is completed, the frontier may have multiple blocks that do not contain
+ # the syntax error. To limit the result to the smallest subset of "invalid blocks" call:
+ #
+ # CodeFrontier#detect_invalid_blocks
+ #
+ class CodeFrontier
+ def initialize(code_lines:, unvisited: UnvisitedLines.new(code_lines: code_lines))
+ @code_lines = code_lines
+ @unvisited = unvisited
+ @queue = PriorityEngulfQueue.new
+
+ @check_next = true
+ end
+
+ def count
+ @queue.length
+ end
+
+ # Performance optimization
+ #
+ # Parsing with ripper is expensive
+ # If we know we don't have any blocks with invalid
+ # syntax, then we know we cannot have found
+ # the incorrect syntax yet.
+ #
+ # When an invalid block is added onto the frontier
+ # check document state
+ private def can_skip_check?
+ check_next = @check_next
+ @check_next = false
+
+ if check_next
+ false
+ else
+ true
+ end
+ end
+
+ # Returns true if the document is valid with all lines
+ # removed. By default it checks all blocks in present in
+ # the frontier array, but can be used for arbitrary arrays
+ # of codeblocks as well
+ def holds_all_syntax_errors?(block_array = @queue, can_cache: true)
+ return false if can_cache && can_skip_check?
+
+ without_lines = block_array.to_a.flat_map do |block|
+ block.lines
+ end
+
+ SyntaxSuggest.valid_without?(
+ without_lines: without_lines,
+ code_lines: @code_lines
+ )
+ end
+
+ # Returns a code block with the largest indentation possible
+ def pop
+ @queue.pop
+ end
+
+ def next_indent_line
+ @unvisited.peek
+ end
+
+ def expand?
+ return false if @queue.empty?
+ return true if @unvisited.empty?
+
+ frontier_indent = @queue.peek.current_indent
+ unvisited_indent = next_indent_line.indent
+
+ if ENV["SYNTAX_SUGGEST_DEBUG"]
+ puts "```"
+ puts @queue.peek.to_s
+ puts "```"
+ puts " @frontier indent: #{frontier_indent}"
+ puts " @unvisited indent: #{unvisited_indent}"
+ end
+
+ # Expand all blocks before moving to unvisited lines
+ frontier_indent >= unvisited_indent
+ end
+
+ # Keeps track of what lines have been added to blocks and which are not yet
+ # visited.
+ def register_indent_block(block)
+ @unvisited.visit_block(block)
+ self
+ end
+
+ # When one element fully encapsulates another we remove the smaller
+ # block from the frontier. This prevents double expansions and all-around
+ # weird behavior. However this guarantee is quite expensive to maintain
+ def register_engulf_block(block)
+ end
+
+ # Add a block to the frontier
+ #
+ # This method ensures the frontier always remains sorted (in indentation order)
+ # and that each code block's lines are removed from the indentation hash so we
+ # don't re-evaluate the same line multiple times.
+ def <<(block)
+ @unvisited.visit_block(block)
+
+ @queue.push(block)
+
+ @check_next = true if block.invalid?
+
+ self
+ end
+
+ # Example:
+ #
+ # combination([:a, :b, :c, :d])
+ # # => [[:a], [:b], [:c], [:d], [:a, :b], [:a, :c], [:a, :d], [:b, :c], [:b, :d], [:c, :d], [:a, :b, :c], [:a, :b, :d], [:a, :c, :d], [:b, :c, :d], [:a, :b, :c, :d]]
+ def self.combination(array)
+ guesses = []
+ 1.upto(array.length).each do |size|
+ guesses.concat(array.combination(size).to_a)
+ end
+ guesses
+ end
+
+ # Given that we know our syntax error exists somewhere in our frontier, we want to find
+ # the smallest possible set of blocks that contain all the syntax errors
+ def detect_invalid_blocks
+ self.class.combination(@queue.to_a.select(&:invalid?)).detect do |block_array|
+ holds_all_syntax_errors?(block_array, can_cache: false)
+ end || []
+ end
+ end
+end
diff --git a/lib/syntax_suggest/code_line.rb b/lib/syntax_suggest/code_line.rb
new file mode 100644
index 0000000000..a20f34afa4
--- /dev/null
+++ b/lib/syntax_suggest/code_line.rb
@@ -0,0 +1,237 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Represents a single line of code of a given source file
+ #
+ # This object contains metadata about the line such as
+ # amount of indentation, if it is empty or not, and
+ # lexical data, such as if it has an `end` or a keyword
+ # in it.
+ #
+ # Visibility of lines can be toggled off. Marking a line as invisible
+ # indicates that it should not be used for syntax checks.
+ # It's functionally the same as commenting it out.
+ #
+ # Example:
+ #
+ # line = CodeLine.from_source("def foo\n").first
+ # line.number => 1
+ # line.empty? # => false
+ # line.visible? # => true
+ # line.mark_invisible
+ # line.visible? # => false
+ #
+ class CodeLine
+ TRAILING_SLASH = ("\\" + $/).freeze
+
+ # Returns an array of CodeLine objects
+ # from the source string
+ def self.from_source(source, lines: nil)
+ lines ||= source.lines
+ lex_array_for_line = LexAll.new(source: source, source_lines: lines).each_with_object(Hash.new { |h, k| h[k] = [] }) { |lex, hash| hash[lex.line] << lex }
+ lines.map.with_index do |line, index|
+ CodeLine.new(
+ line: line,
+ index: index,
+ lex: lex_array_for_line[index + 1]
+ )
+ end
+ end
+
+ attr_reader :line, :index, :lex, :line_number, :indent
+ def initialize(line:, index:, lex:)
+ @lex = lex
+ @line = line
+ @index = index
+ @original = line
+ @line_number = @index + 1
+ strip_line = line.dup
+ strip_line.lstrip!
+
+ @indent = if (@empty = strip_line.empty?)
+ line.length - 1 # Newline removed from strip_line is not "whitespace"
+ else
+ line.length - strip_line.length
+ end
+
+ set_kw_end
+ end
+
+ # Used for stable sort via indentation level
+ #
+ # Ruby's sort is not "stable" meaning that when
+ # multiple elements have the same value, they are
+ # not guaranteed to return in the same order they
+ # were put in.
+ #
+ # So when multiple code lines have the same indentation
+ # level, they're sorted by their index value which is unique
+ # and consistent.
+ #
+ # This is mostly needed for consistency of the test suite
+ def indent_index
+ @indent_index ||= [indent, index]
+ end
+ alias_method :number, :line_number
+
+ # Returns true if the code line is determined
+ # to contain a keyword that matches with an `end`
+ #
+ # For example: `def`, `do`, `begin`, `ensure`, etc.
+ def is_kw?
+ @is_kw
+ end
+
+ # Returns true if the code line is determined
+ # to contain an `end` keyword
+ def is_end?
+ @is_end
+ end
+
+ # Used to hide lines
+ #
+ # The search alorithm will group lines into blocks
+ # then if those blocks are determined to represent
+ # valid code they will be hidden
+ def mark_invisible
+ @line = ""
+ end
+
+ # Means the line was marked as "invisible"
+ # Confusingly, "empty" lines are visible...they
+ # just don't contain any source code other than a newline ("\n").
+ def visible?
+ !line.empty?
+ end
+
+ # Opposite or `visible?` (note: different than `empty?`)
+ def hidden?
+ !visible?
+ end
+
+ # An `empty?` line is one that was originally left
+ # empty in the source code, while a "hidden" line
+ # is one that we've since marked as "invisible"
+ def empty?
+ @empty
+ end
+
+ # Opposite of `empty?` (note: different than `visible?`)
+ def not_empty?
+ !empty?
+ end
+
+ # Renders the given line
+ #
+ # Also allows us to represent source code as
+ # an array of code lines.
+ #
+ # When we have an array of code line elements
+ # calling `join` on the array will call `to_s`
+ # on each element, which essentially converts
+ # it back into it's original source string.
+ def to_s
+ line
+ end
+
+ # When the code line is marked invisible
+ # we retain the original value of it's line
+ # this is useful for debugging and for
+ # showing extra context
+ #
+ # DisplayCodeWithLineNumbers will render
+ # all lines given to it, not just visible
+ # lines, it uses the original method to
+ # obtain them.
+ attr_reader :original
+
+ # Comparison operator, needed for equality
+ # and sorting
+ def <=>(other)
+ index <=> other.index
+ end
+
+ # [Not stable API]
+ #
+ # Lines that have a `on_ignored_nl` type token and NOT
+ # a `BEG` type seem to be a good proxy for the ability
+ # to join multiple lines into one.
+ #
+ # This predicate method is used to determine when those
+ # two criteria have been met.
+ #
+ # The one known case this doesn't handle is:
+ #
+ # Ripper.lex <<~EOM
+ # a &&
+ # b ||
+ # c
+ # EOM
+ #
+ # For some reason this introduces `on_ignore_newline` but with BEG type
+ def ignore_newline_not_beg?
+ @ignore_newline_not_beg
+ end
+
+ # Determines if the given line has a trailing slash
+ #
+ # lines = CodeLine.from_source(<<~EOM)
+ # it "foo" \
+ # EOM
+ # expect(lines.first.trailing_slash?).to eq(true)
+ #
+ def trailing_slash?
+ last = @lex.last
+ return false unless last
+ return false unless last.type == :on_sp
+
+ last.token == TRAILING_SLASH
+ end
+
+ # Endless method detection
+ #
+ # From https://github.com/ruby/irb/commit/826ae909c9c93a2ddca6f9cfcd9c94dbf53d44ab
+ # Detecting a "oneliner" seems to need a state machine.
+ # This can be done by looking mostly at the "state" (last value):
+ #
+ # ENDFN -> BEG (token = '=' ) -> END
+ #
+ private def set_kw_end
+ oneliner_count = 0
+ in_oneliner_def = nil
+
+ kw_count = 0
+ end_count = 0
+
+ @ignore_newline_not_beg = false
+ @lex.each do |lex|
+ kw_count += 1 if lex.is_kw?
+ end_count += 1 if lex.is_end?
+
+ if lex.type == :on_ignored_nl
+ @ignore_newline_not_beg = !lex.expr_beg?
+ end
+
+ if in_oneliner_def.nil?
+ in_oneliner_def = :ENDFN if lex.state.allbits?(Ripper::EXPR_ENDFN)
+ elsif lex.state.allbits?(Ripper::EXPR_ENDFN)
+ # Continue
+ elsif lex.state.allbits?(Ripper::EXPR_BEG)
+ in_oneliner_def = :BODY if lex.token == "="
+ elsif lex.state.allbits?(Ripper::EXPR_END)
+ # We found an endless method, count it
+ oneliner_count += 1 if in_oneliner_def == :BODY
+
+ in_oneliner_def = nil
+ else
+ in_oneliner_def = nil
+ end
+ end
+
+ kw_count -= oneliner_count
+
+ @is_kw = (kw_count - end_count) > 0
+ @is_end = (end_count - kw_count) > 0
+ end
+ end
+end
diff --git a/lib/syntax_suggest/code_search.rb b/lib/syntax_suggest/code_search.rb
new file mode 100644
index 0000000000..2a86dfea90
--- /dev/null
+++ b/lib/syntax_suggest/code_search.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Searches code for a syntax error
+ #
+ # There are three main phases in the algorithm:
+ #
+ # 1. Sanitize/format input source
+ # 2. Search for invalid blocks
+ # 3. Format invalid blocks into something meaninful
+ #
+ # This class handles the part.
+ #
+ # The bulk of the heavy lifting is done in:
+ #
+ # - CodeFrontier (Holds information for generating blocks and determining if we can stop searching)
+ # - ParseBlocksFromLine (Creates blocks into the frontier)
+ # - BlockExpand (Expands existing blocks to search more code)
+ #
+ # ## Syntax error detection
+ #
+ # When the frontier holds the syntax error, we can stop searching
+ #
+ # search = CodeSearch.new(<<~EOM)
+ # def dog
+ # def lol
+ # end
+ # EOM
+ #
+ # search.call
+ #
+ # search.invalid_blocks.map(&:to_s) # =>
+ # # => ["def lol\n"]
+ #
+ class CodeSearch
+ private
+
+ attr_reader :frontier
+
+ public
+
+ attr_reader :invalid_blocks, :record_dir, :code_lines
+
+ def initialize(source, record_dir: DEFAULT_VALUE)
+ record_dir = if record_dir == DEFAULT_VALUE
+ ENV["SYNTAX_SUGGEST_RECORD_DIR"] || ENV["SYNTAX_SUGGEST_DEBUG"] ? "tmp" : nil
+ else
+ record_dir
+ end
+
+ if record_dir
+ @record_dir = SyntaxSuggest.record_dir(record_dir)
+ @write_count = 0
+ end
+
+ @tick = 0
+ @source = source
+ @name_tick = Hash.new { |hash, k| hash[k] = 0 }
+ @invalid_blocks = []
+
+ @code_lines = CleanDocument.new(source: source).call.lines
+
+ @frontier = CodeFrontier.new(code_lines: @code_lines)
+ @block_expand = BlockExpand.new(code_lines: @code_lines)
+ @parse_blocks_from_indent_line = ParseBlocksFromIndentLine.new(code_lines: @code_lines)
+ end
+
+ # Used for debugging
+ def record(block:, name: "record")
+ return unless @record_dir
+ @name_tick[name] += 1
+ filename = "#{@write_count += 1}-#{name}-#{@name_tick[name]}-(#{block.starts_at}__#{block.ends_at}).txt"
+ if ENV["SYNTAX_SUGGEST_DEBUG"]
+ puts "\n\n==== #{filename} ===="
+ puts "\n```#{block.starts_at}..#{block.ends_at}"
+ puts block.to_s
+ puts "```"
+ puts " block indent: #{block.current_indent}"
+ end
+ @record_dir.join(filename).open(mode: "a") do |f|
+ document = DisplayCodeWithLineNumbers.new(
+ lines: @code_lines.select(&:visible?),
+ terminal: false,
+ highlight_lines: block.lines
+ ).call
+
+ f.write(" Block lines: #{block.starts_at..block.ends_at} (#{name}) \n\n#{document}")
+ end
+ end
+
+ def push(block, name:)
+ record(block: block, name: name)
+
+ block.mark_invisible if block.valid?
+ frontier << block
+ end
+
+ # Parses the most indented lines into blocks that are marked
+ # and added to the frontier
+ def create_blocks_from_untracked_lines
+ max_indent = frontier.next_indent_line&.indent
+
+ while (line = frontier.next_indent_line) && (line.indent == max_indent)
+ @parse_blocks_from_indent_line.each_neighbor_block(frontier.next_indent_line) do |block|
+ push(block, name: "add")
+ end
+ end
+ end
+
+ # Given an already existing block in the frontier, expand it to see
+ # if it contains our invalid syntax
+ def expand_existing
+ block = frontier.pop
+ return unless block
+
+ record(block: block, name: "before-expand")
+
+ block = @block_expand.call(block)
+ push(block, name: "expand")
+ end
+
+ # Main search loop
+ def call
+ until frontier.holds_all_syntax_errors?
+ @tick += 1
+
+ if frontier.expand?
+ expand_existing
+ else
+ create_blocks_from_untracked_lines
+ end
+ end
+
+ @invalid_blocks.concat(frontier.detect_invalid_blocks)
+ @invalid_blocks.sort_by! { |block| block.starts_at }
+ self
+ end
+ end
+end
diff --git a/lib/syntax_suggest/core_ext.rb b/lib/syntax_suggest/core_ext.rb
new file mode 100644
index 0000000000..e0fd62b81c
--- /dev/null
+++ b/lib/syntax_suggest/core_ext.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+# Ruby 3.2+ has a cleaner way to hook into Ruby that doesn't use `require`
+if SyntaxError.method_defined?(:detailed_message)
+ module SyntaxSuggest
+ # Mini String IO [Private]
+ #
+ # Acts like a StringIO with reduced API, but without having to require that
+ # class.
+ class MiniStringIO
+ def initialize(isatty: $stderr.isatty)
+ @string = +""
+ @isatty = isatty
+ end
+
+ attr_reader :isatty
+ def puts(value = $/, **)
+ @string << value
+ end
+
+ attr_reader :string
+ end
+
+ # SyntaxSuggest.record_dir [Private]
+ #
+ # Used to monkeypatch SyntaxError via Module.prepend
+ def self.module_for_detailed_message
+ Module.new {
+ def detailed_message(highlight: true, syntax_suggest: true, **kwargs)
+ return super unless syntax_suggest
+
+ require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
+
+ message = super
+
+ if path
+ file = Pathname.new(path)
+ io = SyntaxSuggest::MiniStringIO.new
+
+ SyntaxSuggest.call(
+ io: io,
+ source: file.read,
+ filename: file,
+ terminal: highlight
+ )
+ annotation = io.string
+
+ annotation += "\n" unless annotation.end_with?("\n")
+
+ annotation + message
+ else
+ message
+ end
+ rescue => e
+ if ENV["SYNTAX_SUGGEST_DEBUG"]
+ $stderr.warn(e.message)
+ $stderr.warn(e.backtrace)
+ end
+
+ # Ignore internal errors
+ message
+ end
+ }
+ end
+ end
+
+ SyntaxError.prepend(SyntaxSuggest.module_for_detailed_message)
+else
+ autoload :Pathname, "pathname"
+
+ #--
+ # Monkey patch kernel to ensure that all `require` calls call the same
+ # method
+ #++
+ module Kernel
+ # :stopdoc:
+
+ module_function
+
+ alias_method :syntax_suggest_original_require, :require
+ alias_method :syntax_suggest_original_require_relative, :require_relative
+ alias_method :syntax_suggest_original_load, :load
+
+ def load(file, wrap = false)
+ syntax_suggest_original_load(file)
+ rescue SyntaxError => e
+ require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
+
+ SyntaxSuggest.handle_error(e)
+ end
+
+ def require(file)
+ syntax_suggest_original_require(file)
+ rescue SyntaxError => e
+ require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
+
+ SyntaxSuggest.handle_error(e)
+ end
+
+ def require_relative(file)
+ if Pathname.new(file).absolute?
+ syntax_suggest_original_require file
+ else
+ relative_from = caller_locations(1..1).first
+ relative_from_path = relative_from.absolute_path || relative_from.path
+ syntax_suggest_original_require File.expand_path("../#{file}", relative_from_path)
+ end
+ rescue SyntaxError => e
+ require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
+
+ SyntaxSuggest.handle_error(e)
+ end
+ end
+end
diff --git a/lib/syntax_suggest/display_code_with_line_numbers.rb b/lib/syntax_suggest/display_code_with_line_numbers.rb
new file mode 100644
index 0000000000..a18d62e54b
--- /dev/null
+++ b/lib/syntax_suggest/display_code_with_line_numbers.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Outputs code with highlighted lines
+ #
+ # Whatever is passed to this class will be rendered
+ # even if it is "marked invisible" any filtering of
+ # output should be done before calling this class.
+ #
+ # DisplayCodeWithLineNumbers.new(
+ # lines: lines,
+ # highlight_lines: [lines[2], lines[3]]
+ # ).call
+ # # =>
+ # 1
+ # 2 def cat
+ # > 3 Dir.chdir
+ # > 4 end
+ # 5 end
+ # 6
+ class DisplayCodeWithLineNumbers
+ TERMINAL_HIGHLIGHT = "\e[1;3m" # Bold, italics
+ TERMINAL_END = "\e[0m"
+
+ def initialize(lines:, highlight_lines: [], terminal: false)
+ @lines = Array(lines).sort
+ @terminal = terminal
+ @highlight_line_hash = Array(highlight_lines).each_with_object({}) { |line, h| h[line] = true }
+ @digit_count = @lines.last&.line_number.to_s.length
+ end
+
+ def call
+ @lines.map do |line|
+ format_line(line)
+ end.join
+ end
+
+ private def format_line(code_line)
+ # Handle trailing slash lines
+ code_line.original.lines.map.with_index do |contents, i|
+ format(
+ empty: code_line.empty?,
+ number: (code_line.number + i).to_s,
+ contents: contents,
+ highlight: @highlight_line_hash[code_line]
+ )
+ end.join
+ end
+
+ private def format(contents:, number:, empty:, highlight: false)
+ string = +""
+ string << if highlight
+ "> "
+ else
+ " "
+ end
+
+ string << number.rjust(@digit_count).to_s
+ if empty
+ string << contents
+ else
+ string << " "
+ string << TERMINAL_HIGHLIGHT if @terminal && highlight
+ string << contents
+ string << TERMINAL_END if @terminal
+ end
+ string
+ end
+ end
+end
diff --git a/lib/syntax_suggest/display_invalid_blocks.rb b/lib/syntax_suggest/display_invalid_blocks.rb
new file mode 100644
index 0000000000..32ec0021a3
--- /dev/null
+++ b/lib/syntax_suggest/display_invalid_blocks.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require_relative "capture_code_context"
+require_relative "display_code_with_line_numbers"
+
+module SyntaxSuggest
+ # Used for formatting invalid blocks
+ class DisplayInvalidBlocks
+ attr_reader :filename
+
+ def initialize(code_lines:, blocks:, io: $stderr, filename: nil, terminal: DEFAULT_VALUE)
+ @io = io
+ @blocks = Array(blocks)
+ @filename = filename
+ @code_lines = code_lines
+
+ @terminal = terminal == DEFAULT_VALUE ? io.isatty : terminal
+ end
+
+ def document_ok?
+ @blocks.none? { |b| !b.hidden? }
+ end
+
+ def call
+ if document_ok?
+ return self
+ end
+
+ if filename
+ @io.puts("--> #{filename}")
+ @io.puts
+ end
+ @blocks.each do |block|
+ display_block(block)
+ end
+
+ self
+ end
+
+ private def display_block(block)
+ # Build explanation
+ explain = ExplainSyntax.new(
+ code_lines: block.lines
+ ).call
+
+ # Enhance code output
+ # Also handles several ambiguious cases
+ lines = CaptureCodeContext.new(
+ blocks: block,
+ code_lines: @code_lines
+ ).call
+
+ # Build code output
+ document = DisplayCodeWithLineNumbers.new(
+ lines: lines,
+ terminal: @terminal,
+ highlight_lines: block.lines
+ ).call
+
+ # Output syntax error explanation
+ explain.errors.each do |e|
+ @io.puts e
+ end
+ @io.puts
+
+ # Output code
+ @io.puts(document)
+ end
+
+ private def code_with_context
+ lines = CaptureCodeContext.new(
+ blocks: @blocks,
+ code_lines: @code_lines
+ ).call
+
+ DisplayCodeWithLineNumbers.new(
+ lines: lines,
+ terminal: @terminal,
+ highlight_lines: @invalid_lines
+ ).call
+ end
+ end
+end
diff --git a/lib/syntax_suggest/explain_syntax.rb b/lib/syntax_suggest/explain_syntax.rb
new file mode 100644
index 0000000000..142ed2e269
--- /dev/null
+++ b/lib/syntax_suggest/explain_syntax.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require_relative "left_right_lex_count"
+
+module SyntaxSuggest
+ # Explains syntax errors based on their source
+ #
+ # example:
+ #
+ # source = "def foo; puts 'lol'" # Note missing end
+ # explain ExplainSyntax.new(
+ # code_lines: CodeLine.from_source(source)
+ # ).call
+ # explain.errors.first
+ # # => "Unmatched keyword, missing `end' ?"
+ #
+ # When the error cannot be determined by lexical counting
+ # then ripper is run against the input and the raw ripper
+ # errors returned.
+ #
+ # Example:
+ #
+ # source = "1 * " # Note missing a second number
+ # explain ExplainSyntax.new(
+ # code_lines: CodeLine.from_source(source)
+ # ).call
+ # explain.errors.first
+ # # => "syntax error, unexpected end-of-input"
+ class ExplainSyntax
+ INVERSE = {
+ "{" => "}",
+ "}" => "{",
+ "[" => "]",
+ "]" => "[",
+ "(" => ")",
+ ")" => "(",
+ "|" => "|"
+ }.freeze
+
+ def initialize(code_lines:)
+ @code_lines = code_lines
+ @left_right = LeftRightLexCount.new
+ @missing = nil
+ end
+
+ def call
+ @code_lines.each do |line|
+ line.lex.each do |lex|
+ @left_right.count_lex(lex)
+ end
+ end
+
+ self
+ end
+
+ # Returns an array of missing elements
+ #
+ # For example this:
+ #
+ # ExplainSyntax.new(code_lines: lines).missing
+ # # => ["}"]
+ #
+ # Would indicate that the source is missing
+ # a `}` character in the source code
+ def missing
+ @missing ||= @left_right.missing
+ end
+
+ # Converts a missing string to
+ # an human understandable explanation.
+ #
+ # Example:
+ #
+ # explain.why("}")
+ # # => "Unmatched `{', missing `}' ?"
+ #
+ def why(miss)
+ case miss
+ when "keyword"
+ "Unmatched `end', missing keyword (`do', `def`, `if`, etc.) ?"
+ when "end"
+ "Unmatched keyword, missing `end' ?"
+ else
+ inverse = INVERSE.fetch(miss) {
+ raise "Unknown explain syntax char or key: #{miss.inspect}"
+ }
+ "Unmatched `#{inverse}', missing `#{miss}' ?"
+ end
+ end
+
+ # Returns an array of syntax error messages
+ #
+ # If no missing pairs are found it falls back
+ # on the original ripper error messages
+ def errors
+ if missing.empty?
+ return RipperErrors.new(@code_lines.map(&:original).join).call.errors
+ end
+
+ missing.map { |miss| why(miss) }
+ end
+ end
+end
diff --git a/lib/syntax_suggest/left_right_lex_count.rb b/lib/syntax_suggest/left_right_lex_count.rb
new file mode 100644
index 0000000000..6fcae7482b
--- /dev/null
+++ b/lib/syntax_suggest/left_right_lex_count.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Find mis-matched syntax based on lexical count
+ #
+ # Used for detecting missing pairs of elements
+ # each keyword needs an end, each '{' needs a '}'
+ # etc.
+ #
+ # Example:
+ #
+ # left_right = LeftRightLexCount.new
+ # left_right.count_kw
+ # left_right.missing.first
+ # # => "end"
+ #
+ # left_right = LeftRightLexCount.new
+ # source = "{ a: b, c: d" # Note missing '}'
+ # LexAll.new(source: source).each do |lex|
+ # left_right.count_lex(lex)
+ # end
+ # left_right.missing.first
+ # # => "}"
+ class LeftRightLexCount
+ def initialize
+ @kw_count = 0
+ @end_count = 0
+
+ @count_for_char = {
+ "{" => 0,
+ "}" => 0,
+ "[" => 0,
+ "]" => 0,
+ "(" => 0,
+ ")" => 0,
+ "|" => 0
+ }
+ end
+
+ def count_kw
+ @kw_count += 1
+ end
+
+ def count_end
+ @end_count += 1
+ end
+
+ # Count source code characters
+ #
+ # Example:
+ #
+ # left_right = LeftRightLexCount.new
+ # left_right.count_lex(LexValue.new(1, :on_lbrace, "{", Ripper::EXPR_BEG))
+ # left_right.count_for_char("{")
+ # # => 1
+ # left_right.count_for_char("}")
+ # # => 0
+ def count_lex(lex)
+ case lex.type
+ when :on_tstring_content
+ # ^^^
+ # Means it's a string or a symbol `"{"` rather than being
+ # part of a data structure (like a hash) `{ a: b }`
+ # ignore it.
+ when :on_words_beg, :on_symbos_beg, :on_qwords_beg,
+ :on_qsymbols_beg, :on_regexp_beg, :on_tstring_beg
+ # ^^^
+ # Handle shorthand syntaxes like `%Q{ i am a string }`
+ #
+ # The start token will be the full thing `%Q{` but we
+ # need to count it as if it's a `{`. Any token
+ # can be used
+ char = lex.token[-1]
+ @count_for_char[char] += 1 if @count_for_char.key?(char)
+ when :on_embexpr_beg
+ # ^^^
+ # Embedded string expressions like `"#{foo} <-embed"`
+ # are parsed with chars:
+ #
+ # `#{` as :on_embexpr_beg
+ # `}` as :on_embexpr_end
+ #
+ # We cannot ignore both :on_emb_expr_beg and :on_embexpr_end
+ # because sometimes the lexer thinks something is an embed
+ # string end, when it is not like `lol = }` (no clue why).
+ #
+ # When we see `#{` count it as a `{` or we will
+ # have a mis-match count.
+ #
+ case lex.token
+ when "\#{"
+ @count_for_char["{"] += 1
+ end
+ else
+ @end_count += 1 if lex.is_end?
+ @kw_count += 1 if lex.is_kw?
+ @count_for_char[lex.token] += 1 if @count_for_char.key?(lex.token)
+ end
+ end
+
+ def count_for_char(char)
+ @count_for_char[char]
+ end
+
+ # Returns an array of missing syntax characters
+ # or `"end"` or `"keyword"`
+ #
+ # left_right.missing
+ # # => ["}"]
+ def missing
+ out = missing_pairs
+ out << missing_pipe
+ out << missing_keyword_end
+ out.compact!
+ out
+ end
+
+ PAIRS = {
+ "{" => "}",
+ "[" => "]",
+ "(" => ")"
+ }.freeze
+
+ # Opening characters like `{` need closing characters # like `}`.
+ #
+ # When a mis-match count is detected, suggest the
+ # missing member.
+ #
+ # For example if there are 3 `}` and only two `{`
+ # return `"{"`
+ private def missing_pairs
+ PAIRS.map do |(left, right)|
+ case @count_for_char[left] <=> @count_for_char[right]
+ when 1
+ right
+ when 0
+ nil
+ when -1
+ left
+ end
+ end
+ end
+
+ # Keywords need ends and ends need keywords
+ #
+ # If we have more keywords, there's a missing `end`
+ # if we have more `end`-s, there's a missing keyword
+ private def missing_keyword_end
+ case @kw_count <=> @end_count
+ when 1
+ "end"
+ when 0
+ nil
+ when -1
+ "keyword"
+ end
+ end
+
+ # Pipes come in pairs.
+ # If there's an odd number of pipes then we
+ # are missing one
+ private def missing_pipe
+ if @count_for_char["|"].odd?
+ "|"
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/lex_all.rb b/lib/syntax_suggest/lex_all.rb
new file mode 100644
index 0000000000..132cba9f5d
--- /dev/null
+++ b/lib/syntax_suggest/lex_all.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Ripper.lex is not guaranteed to lex the entire source document
+ #
+ # lex = LexAll.new(source: source)
+ # lex.each do |value|
+ # puts value.line
+ # end
+ class LexAll
+ include Enumerable
+
+ def initialize(source:, source_lines: nil)
+ @lex = Ripper::Lexer.new(source, "-", 1).parse.sort_by(&:pos)
+ lineno = @lex.last.pos.first + 1
+ source_lines ||= source.lines
+ last_lineno = source_lines.length
+
+ until lineno >= last_lineno
+ lines = source_lines[lineno..-1]
+
+ @lex.concat(
+ Ripper::Lexer.new(lines.join, "-", lineno + 1).parse.sort_by(&:pos)
+ )
+ lineno = @lex.last.pos.first + 1
+ end
+
+ last_lex = nil
+ @lex.map! { |elem|
+ last_lex = LexValue.new(elem.pos.first, elem.event, elem.tok, elem.state, last_lex)
+ }
+ end
+
+ def to_a
+ @lex
+ end
+
+ def each
+ return @lex.each unless block_given?
+ @lex.each do |x|
+ yield x
+ end
+ end
+
+ def [](index)
+ @lex[index]
+ end
+
+ def last
+ @lex.last
+ end
+ end
+end
+
+require_relative "lex_value"
diff --git a/lib/syntax_suggest/lex_value.rb b/lib/syntax_suggest/lex_value.rb
new file mode 100644
index 0000000000..008cc105b5
--- /dev/null
+++ b/lib/syntax_suggest/lex_value.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Value object for accessing lex values
+ #
+ # This lex:
+ #
+ # [1, 0], :on_ident, "describe", CMDARG
+ #
+ # Would translate into:
+ #
+ # lex.line # => 1
+ # lex.type # => :on_indent
+ # lex.token # => "describe"
+ class LexValue
+ attr_reader :line, :type, :token, :state
+
+ def initialize(line, type, token, state, last_lex = nil)
+ @line = line
+ @type = type
+ @token = token
+ @state = state
+
+ set_kw_end(last_lex)
+ end
+
+ private def set_kw_end(last_lex)
+ @is_end = false
+ @is_kw = false
+ return if type != :on_kw
+ #
+ return if last_lex && last_lex.fname? # https://github.com/ruby/ruby/commit/776759e300e4659bb7468e2b97c8c2d4359a2953
+
+ case token
+ when "if", "unless", "while", "until"
+ # Only count if/unless when it's not a "trailing" if/unless
+ # https://github.com/ruby/ruby/blob/06b44f819eb7b5ede1ff69cecb25682b56a1d60c/lib/irb/ruby-lex.rb#L374-L375
+ @is_kw = true unless expr_label?
+ when "def", "case", "for", "begin", "class", "module", "do"
+ @is_kw = true
+ when "end"
+ @is_end = true
+ end
+ end
+
+ def fname?
+ state.allbits?(Ripper::EXPR_FNAME)
+ end
+
+ def ignore_newline?
+ type == :on_ignored_nl
+ end
+
+ def is_end?
+ @is_end
+ end
+
+ def is_kw?
+ @is_kw
+ end
+
+ def expr_beg?
+ state.anybits?(Ripper::EXPR_BEG)
+ end
+
+ def expr_label?
+ state.allbits?(Ripper::EXPR_LABEL)
+ end
+ end
+end
diff --git a/lib/syntax_suggest/parse_blocks_from_indent_line.rb b/lib/syntax_suggest/parse_blocks_from_indent_line.rb
new file mode 100644
index 0000000000..241ed6acb4
--- /dev/null
+++ b/lib/syntax_suggest/parse_blocks_from_indent_line.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # This class is responsible for generating initial code blocks
+ # that will then later be expanded.
+ #
+ # The biggest concern when guessing code blocks, is accidentally
+ # grabbing one that contains only an "end". In this example:
+ #
+ # def dog
+ # begonn # mispelled `begin`
+ # puts "bark"
+ # end
+ # end
+ #
+ # The following lines would be matched (from bottom to top):
+ #
+ # 1) end
+ #
+ # 2) puts "bark"
+ # end
+ #
+ # 3) begonn
+ # puts "bark"
+ # end
+ #
+ # At this point it has no where else to expand, and it will yield this inner
+ # code as a block
+ class ParseBlocksFromIndentLine
+ attr_reader :code_lines
+
+ def initialize(code_lines:)
+ @code_lines = code_lines
+ end
+
+ # Builds blocks from bottom up
+ def each_neighbor_block(target_line)
+ scan = AroundBlockScan.new(code_lines: code_lines, block: CodeBlock.new(lines: target_line))
+ .force_add_empty
+ .force_add_hidden
+ .scan_while { |line| line.indent >= target_line.indent }
+
+ neighbors = scan.code_block.lines
+
+ block = CodeBlock.new(lines: neighbors)
+ if neighbors.length <= 2 || block.valid?
+ yield block
+ else
+ until neighbors.empty?
+ lines = [neighbors.pop]
+ while (block = CodeBlock.new(lines: lines)) && block.invalid? && neighbors.any?
+ lines.prepend neighbors.pop
+ end
+
+ yield block if block
+ end
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/pathname_from_message.rb b/lib/syntax_suggest/pathname_from_message.rb
new file mode 100644
index 0000000000..b6fe1617be
--- /dev/null
+++ b/lib/syntax_suggest/pathname_from_message.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Converts a SyntaxError message to a path
+ #
+ # Handles the case where the filename has a colon in it
+ # such as on a windows file system: https://github.com/ruby/syntax_suggest/issues/111
+ #
+ # Example:
+ #
+ # message = "/tmp/scratch:2:in `require_relative': /private/tmp/bad.rb:1: syntax error, unexpected `end' (SyntaxError)"
+ # puts PathnameFromMessage.new(message).call.name
+ # # => "/tmp/scratch.rb"
+ #
+ class PathnameFromMessage
+ EVAL_RE = /^\(eval\):\d+/
+ STREAMING_RE = /^-:\d+/
+ attr_reader :name
+
+ def initialize(message, io: $stderr)
+ @line = message.lines.first
+ @parts = @line.split(":")
+ @guess = []
+ @name = nil
+ @io = io
+ end
+
+ def call
+ if skip_missing_file_name?
+ if ENV["SYNTAX_SUGGEST_DEBUG"]
+ @io.puts "SyntaxSuggest: Could not find filename from #{@line.inspect}"
+ end
+ else
+ until stop?
+ @guess << @parts.shift
+ @name = Pathname(@guess.join(":"))
+ end
+
+ if @parts.empty?
+ @io.puts "SyntaxSuggest: Could not find filename from #{@line.inspect}"
+ @name = nil
+ end
+ end
+
+ self
+ end
+
+ def stop?
+ return true if @parts.empty?
+ return false if @guess.empty?
+
+ @name&.exist?
+ end
+
+ def skip_missing_file_name?
+ @line.match?(EVAL_RE) || @line.match?(STREAMING_RE)
+ end
+ end
+end
diff --git a/lib/syntax_suggest/priority_engulf_queue.rb b/lib/syntax_suggest/priority_engulf_queue.rb
new file mode 100644
index 0000000000..2d1e9b1b63
--- /dev/null
+++ b/lib/syntax_suggest/priority_engulf_queue.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Keeps track of what elements are in the queue in
+ # priority and also ensures that when one element
+ # engulfs/covers/eats another that the larger element
+ # evicts the smaller element
+ class PriorityEngulfQueue
+ def initialize
+ @queue = PriorityQueue.new
+ end
+
+ def to_a
+ @queue.to_a
+ end
+
+ def empty?
+ @queue.empty?
+ end
+
+ def length
+ @queue.length
+ end
+
+ def peek
+ @queue.peek
+ end
+
+ def pop
+ @queue.pop
+ end
+
+ def push(block)
+ prune_engulf(block)
+ @queue << block
+ flush_deleted
+
+ self
+ end
+
+ private def flush_deleted
+ while @queue&.peek&.deleted?
+ @queue.pop
+ end
+ end
+
+ private def prune_engulf(block)
+ # If we're about to pop off the same block, we can skip deleting
+ # things from the frontier this iteration since we'll get it
+ # on the next iteration
+ return if @queue.peek && (block <=> @queue.peek) == 1
+
+ if block.starts_at != block.ends_at # A block of size 1 cannot engulf another
+ @queue.to_a.each { |b|
+ if b.starts_at >= block.starts_at && b.ends_at <= block.ends_at
+ b.delete
+ true
+ end
+ }
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/priority_queue.rb b/lib/syntax_suggest/priority_queue.rb
new file mode 100644
index 0000000000..1abda2a444
--- /dev/null
+++ b/lib/syntax_suggest/priority_queue.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Holds elements in a priority heap on insert
+ #
+ # Instead of constantly calling `sort!`, put
+ # the element where it belongs the first time
+ # around
+ #
+ # Example:
+ #
+ # queue = PriorityQueue.new
+ # queue << 33
+ # queue << 44
+ # queue << 1
+ #
+ # puts queue.peek # => 44
+ #
+ class PriorityQueue
+ attr_reader :elements
+
+ def initialize
+ @elements = []
+ end
+
+ def <<(element)
+ @elements << element
+ bubble_up(last_index, element)
+ end
+
+ def pop
+ exchange(0, last_index)
+ max = @elements.pop
+ bubble_down(0)
+ max
+ end
+
+ def length
+ @elements.length
+ end
+
+ def empty?
+ @elements.empty?
+ end
+
+ def peek
+ @elements.first
+ end
+
+ def to_a
+ @elements
+ end
+
+ # Used for testing, extremely not performant
+ def sorted
+ out = []
+ elements = @elements.dup
+ while (element = pop)
+ out << element
+ end
+ @elements = elements
+ out.reverse
+ end
+
+ private def last_index
+ @elements.size - 1
+ end
+
+ private def bubble_up(index, element)
+ return if index <= 0
+
+ parent_index = (index - 1) / 2
+ parent = @elements[parent_index]
+
+ return if (parent <=> element) >= 0
+
+ exchange(index, parent_index)
+ bubble_up(parent_index, element)
+ end
+
+ private def bubble_down(index)
+ child_index = (index * 2) + 1
+
+ return if child_index > last_index
+
+ not_the_last_element = child_index < last_index
+ left_element = @elements[child_index]
+ right_element = @elements[child_index + 1]
+
+ child_index += 1 if not_the_last_element && (right_element <=> left_element) == 1
+
+ return if (@elements[index] <=> @elements[child_index]) >= 0
+
+ exchange(index, child_index)
+ bubble_down(child_index)
+ end
+
+ def exchange(source, target)
+ a = @elements[source]
+ b = @elements[target]
+ @elements[source] = b
+ @elements[target] = a
+ end
+ end
+end
diff --git a/lib/syntax_suggest/ripper_errors.rb b/lib/syntax_suggest/ripper_errors.rb
new file mode 100644
index 0000000000..48eb206e48
--- /dev/null
+++ b/lib/syntax_suggest/ripper_errors.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Capture parse errors from ripper
+ #
+ # Example:
+ #
+ # puts RipperErrors.new(" def foo").call.errors
+ # # => ["syntax error, unexpected end-of-input, expecting ';' or '\\n'"]
+ class RipperErrors < Ripper
+ attr_reader :errors
+
+ # Comes from ripper, called
+ # on every parse error, msg
+ # is a string
+ def on_parse_error(msg)
+ @errors ||= []
+ @errors << msg
+ end
+
+ alias_method :on_alias_error, :on_parse_error
+ alias_method :on_assign_error, :on_parse_error
+ alias_method :on_class_name_error, :on_parse_error
+ alias_method :on_param_error, :on_parse_error
+ alias_method :compile_error, :on_parse_error
+
+ def call
+ @run_once ||= begin
+ @errors = []
+ parse
+ true
+ end
+ self
+ end
+ end
+end
diff --git a/lib/syntax_suggest/scan_history.rb b/lib/syntax_suggest/scan_history.rb
new file mode 100644
index 0000000000..d15597c440
--- /dev/null
+++ b/lib/syntax_suggest/scan_history.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Scans up/down from the given block
+ #
+ # You can try out a change, stash it, or commit it to save for later
+ #
+ # Example:
+ #
+ # scanner = ScanHistory.new(code_lines: code_lines, block: block)
+ # scanner.scan(
+ # up: ->(_, _, _) { true },
+ # down: ->(_, _, _) { true }
+ # )
+ # scanner.changed? # => true
+ # expect(scanner.lines).to eq(code_lines)
+ #
+ # scanner.stash_changes
+ #
+ # expect(scanner.lines).to_not eq(code_lines)
+ class ScanHistory
+ attr_reader :before_index, :after_index
+
+ def initialize(code_lines:, block:)
+ @code_lines = code_lines
+ @history = [block]
+ refresh_index
+ end
+
+ def commit_if_changed
+ if changed?
+ @history << CodeBlock.new(lines: @code_lines[before_index..after_index])
+ end
+
+ self
+ end
+
+ # Discards any changes that have not been committed
+ def stash_changes
+ refresh_index
+ self
+ end
+
+ # Discard changes that have not been committed and revert the last commit
+ #
+ # Cannot revert the first commit
+ def revert_last_commit
+ if @history.length > 1
+ @history.pop
+ refresh_index
+ end
+
+ self
+ end
+
+ def changed?
+ @before_index != current.lines.first.index ||
+ @after_index != current.lines.last.index
+ end
+
+ # Iterates up and down
+ #
+ # Returns line, kw_count, end_count for each iteration
+ def scan(up:, down:)
+ kw_count = 0
+ end_count = 0
+
+ up_index = before_lines.reverse_each.take_while do |line|
+ kw_count += 1 if line.is_kw?
+ end_count += 1 if line.is_end?
+ up.call(line, kw_count, end_count)
+ end.last&.index
+
+ kw_count = 0
+ end_count = 0
+
+ down_index = after_lines.each.take_while do |line|
+ kw_count += 1 if line.is_kw?
+ end_count += 1 if line.is_end?
+ down.call(line, kw_count, end_count)
+ end.last&.index
+
+ @before_index = if up_index && up_index < @before_index
+ up_index
+ else
+ @before_index
+ end
+
+ @after_index = if down_index && down_index > @after_index
+ down_index
+ else
+ @after_index
+ end
+
+ self
+ end
+
+ def next_up
+ return nil if @before_index <= 0
+
+ @code_lines[@before_index - 1]
+ end
+
+ def next_down
+ return nil if @after_index >= @code_lines.length
+
+ @code_lines[@after_index + 1]
+ end
+
+ def lines
+ @code_lines[@before_index..@after_index]
+ end
+
+ private def before_lines
+ @code_lines[0...@before_index] || []
+ end
+
+ # Returns an array of all the CodeLines that exist after
+ # the currently scanned block
+ private def after_lines
+ @code_lines[@after_index.next..-1] || []
+ end
+
+ private def current
+ @history.last
+ end
+
+ private def refresh_index
+ @before_index = current.lines.first.index
+ @after_index = current.lines.last.index
+ self
+ end
+ end
+end
diff --git a/lib/syntax_suggest/syntax_suggest.gemspec b/lib/syntax_suggest/syntax_suggest.gemspec
new file mode 100644
index 0000000000..0e611c13d0
--- /dev/null
+++ b/lib/syntax_suggest/syntax_suggest.gemspec
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+begin
+ require_relative "lib/syntax_suggest/version"
+rescue LoadError # Fallback to load version file in ruby core repository
+ require_relative "version"
+end
+
+Gem::Specification.new do |spec|
+ spec.name = "syntax_suggest"
+ spec.version = SyntaxSuggest::VERSION
+ spec.authors = ["schneems"]
+ spec.email = ["richard.schneeman+foo@gmail.com"]
+
+ spec.summary = "Find syntax errors in your source in a snap"
+ spec.description = 'When you get an "unexpected end" in your syntax this gem helps you find it'
+ spec.homepage = "https://github.com/ruby/syntax_suggest.git"
+ spec.license = "MIT"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = "https://github.com/ruby/syntax_suggest.git"
+
+ # 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|assets)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = ["syntax_suggest"]
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/syntax_suggest/unvisited_lines.rb b/lib/syntax_suggest/unvisited_lines.rb
new file mode 100644
index 0000000000..32808db634
--- /dev/null
+++ b/lib/syntax_suggest/unvisited_lines.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Tracks which lines various code blocks have expanded to
+ # and which are still unexplored
+ class UnvisitedLines
+ def initialize(code_lines:)
+ @unvisited = code_lines.sort_by(&:indent_index)
+ @visited_lines = {}
+ @visited_lines.compare_by_identity
+ end
+
+ def empty?
+ @unvisited.empty?
+ end
+
+ def peek
+ @unvisited.last
+ end
+
+ def pop
+ @unvisited.pop
+ end
+
+ def visit_block(block)
+ block.lines.each do |line|
+ next if @visited_lines[line]
+ @visited_lines[line] = true
+ end
+
+ while @visited_lines[@unvisited.last]
+ @unvisited.pop
+ end
+ end
+ end
+end
diff --git a/lib/syntax_suggest/version.rb b/lib/syntax_suggest/version.rb
new file mode 100644
index 0000000000..ac8c2f62e5
--- /dev/null
+++ b/lib/syntax_suggest/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ VERSION = "1.1.0"
+end
diff --git a/lib/tempfile.gemspec b/lib/tempfile.gemspec
index 4917b997e7..acb26b68db 100644
--- a/lib/tempfile.gemspec
+++ b/lib/tempfile.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "tempfile"
- spec.version = "0.1.1"
+ spec.version = "0.1.3"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
@@ -18,7 +18,5 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
index 1577e45bec..c3263ed3c6 100644
--- a/lib/tempfile.rb
+++ b/lib/tempfile.rb
@@ -36,9 +36,9 @@ require 'tmpdir'
#
# When a Tempfile object is garbage collected, or when the Ruby interpreter
# exits, its associated temporary file is automatically deleted. This means
-# that's it's unnecessary to explicitly delete a Tempfile after use, though
-# it's good practice to do so: not explicitly deleting unused Tempfiles can
-# potentially leave behind large amounts of tempfiles on the filesystem
+# that it's unnecessary to explicitly delete a Tempfile after use, though
+# it's a good practice to do so: not explicitly deleting unused Tempfiles can
+# potentially leave behind a large number of temp files on the filesystem
# until they're garbage collected. The existence of these temp files can make
# it harder to determine a new Tempfile filename.
#
@@ -87,50 +87,64 @@ require 'tmpdir'
# same Tempfile object from multiple threads then you should protect it with a
# mutex.
class Tempfile < DelegateClass(File)
- # Creates a temporary file with permissions 0600 (= only readable and
- # writable by the owner) and opens it with mode "w+".
+
+ # Creates a file in the underlying file system;
+ # returns a new \Tempfile object based on that file.
+ #
+ # If possible, consider instead using Tempfile.create, which:
+ #
+ # - Avoids the performance cost of delegation,
+ # incurred when Tempfile.new calls its superclass <tt>DelegateClass(File)</tt>.
+ # - Does not rely on a finalizer to close and unlink the file,
+ # which can be unreliable.
+ #
+ # Creates and returns file whose:
+ #
+ # - Class is \Tempfile (not \File, as in Tempfile.create).
+ # - Directory is the system temporary directory (system-dependent).
+ # - Generated filename is unique in that directory.
+ # - Permissions are <tt>0600</tt>;
+ # see {File Permissions}[rdoc-ref:File@File+Permissions].
+ # - Mode is <tt>'w+'</tt> (read/write mode, positioned at the end).
+ #
+ # The underlying file is removed when the \Tempfile object dies
+ # and is reclaimed by the garbage collector.
#
- # 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.
+ # Example:
#
- # 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
- # name will begin with the given string. In the latter form,
- # the temporary file's base name will begin with the array's first
- # element, and end with the second element. For example:
+ # f = Tempfile.new # => #<Tempfile:/tmp/20220505-17839-1s0kt30>
+ # f.class # => Tempfile
+ # f.path # => "/tmp/20220505-17839-1s0kt30"
+ # f.stat.mode.to_s(8) # => "100600"
+ # File.exist?(f.path) # => true
+ # File.unlink(f.path) #
+ # File.exist?(f.path) # => false
#
- # file = Tempfile.new('hello')
- # file.path # => something like: "/tmp/hello2843-8392-92849382--0"
+ # Argument +basename+, if given, may be one of:
#
- # # Use the Array form to enforce an extension in the filename:
- # file = Tempfile.new(['hello', '.jpg'])
- # file.path # => something like: "/tmp/hello2843-8392-92849382--0.jpg"
+ # - A string: the generated filename begins with +basename+:
#
- # The temporary file will be placed in the directory as specified
- # by the +tmpdir+ parameter. By default, this is +Dir.tmpdir+.
+ # Tempfile.new('foo') # => #<Tempfile:/tmp/foo20220505-17839-1whk2f>
#
- # file = Tempfile.new('hello', '/home/aisaka')
- # file.path # => something like: "/home/aisaka/hello2843-8392-92849382--0"
+ # - An array of two strings <tt>[prefix, suffix]</tt>:
+ # the generated filename begins with +prefix+ and ends with +suffix+:
#
- # You can also pass an options hash. Under the hood, Tempfile creates
- # the temporary file using +File.open+. These options will be passed to
- # +File.open+. This is mostly useful for specifying encoding
- # options, e.g.:
+ # Tempfile.new(%w/foo .jpg/) # => #<Tempfile:/tmp/foo20220505-17839-58xtfi.jpg>
#
- # Tempfile.new('hello', '/home/aisaka', encoding: 'ascii-8bit')
+ # With arguments +basename+ and +tmpdir+, the file is created in directory +tmpdir+:
#
- # # You can also omit the 'tmpdir' parameter:
- # Tempfile.new('hello', encoding: 'ascii-8bit')
+ # Tempfile.new('foo', '.') # => #<Tempfile:./foo20220505-17839-xfstr8>
#
- # Note: +mode+ keyword argument, as accepted by Tempfile, can only be
- # numeric, combination of the modes defined in File::Constants.
+ # Keyword arguments +mode+ and +options+ are passed directly to method
+ # {File.open}[rdoc-ref:File.open]:
#
- # === Exceptions
+ # - The value given with +mode+ must be an integer,
+ # and may be expressed as the logical OR of constants defined in
+ # {File::Constants}[rdoc-ref:File::Constants].
+ # - For +options+, see {Open Options}[rdoc-ref:IO@Open+Options].
+ #
+ # Related: Tempfile.create.
#
- # If Tempfile.new cannot find a unique filename within a limited
- # number of tries, then it will raise an exception.
def initialize(basename="", tmpdir=nil, mode: 0, **options)
warn "Tempfile.new doesn't call the given block.", uplevel: 1 if block_given?
@@ -325,26 +339,61 @@ class Tempfile < DelegateClass(File)
end
end
-# 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.
+# Creates a file in the underlying file system;
+# returns a new \File object based on that file.
#
-# If no block is given, this is similar to Tempfile.new except
-# creating File instead of Tempfile. In that case, the created file is
-# not removed automatically. You should use File.unlink to remove it.
+# With no block given and no arguments, creates and returns file whose:
#
-# 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,
-# releasing all resources that the block created.
-# The call returns the value of the block.
+# - Class is {File}[rdoc-ref:File] (not \Tempfile).
+# - Directory is the system temporary directory (system-dependent).
+# - Generated filename is unique in that directory.
+# - Permissions are <tt>0600</tt>;
+# see {File Permissions}[rdoc-ref:File@File+Permissions].
+# - Mode is <tt>'w+'</tt> (read/write mode, positioned at the end).
#
-# In any case, all arguments (+basename+, +tmpdir+, +mode+, and
-# <code>**options</code>) will be treated the same as for Tempfile.new.
+# With no block, the file is not removed automatically,
+# and so should be explicitly removed.
#
-# Tempfile.create('foo', '/home/temp') do |f|
-# # ... do something with f ...
-# end
+# Example:
+#
+# f = Tempfile.create # => #<File:/tmp/20220505-9795-17ky6f6>
+# f.class # => File
+# f.path # => "/tmp/20220505-9795-17ky6f6"
+# f.stat.mode.to_s(8) # => "100600"
+# File.exist?(f.path) # => true
+# File.unlink(f.path)
+# File.exist?(f.path) # => false
+#
+# Argument +basename+, if given, may be one of:
+#
+# - A string: the generated filename begins with +basename+:
+#
+# Tempfile.create('foo') # => #<File:/tmp/foo20220505-9795-1gok8l9>
+#
+# - An array of two strings <tt>[prefix, suffix]</tt>:
+# the generated filename begins with +prefix+ and ends with +suffix+:
+#
+# Tempfile.create(%w/foo .jpg/) # => #<File:/tmp/foo20220505-17839-tnjchh.jpg>
+#
+# With arguments +basename+ and +tmpdir+, the file is created in directory +tmpdir+:
+#
+# Tempfile.create('foo', '.') # => #<File:./foo20220505-9795-1emu6g8>
+#
+# Keyword arguments +mode+ and +options+ are passed directly to method
+# {File.open}[rdoc-ref:File.open]:
+#
+# - The value given with +mode+ must be an integer,
+# and may be expressed as the logical OR of constants defined in
+# {File::Constants}[rdoc-ref:File::Constants].
+# - For +options+, see {Open Options}[rdoc-ref:IO@Open+Options].
+#
+# With a block given, creates the file as above, passes it to the block,
+# and returns the block's value;
+# before the return, the file object is closed and the underlying file is removed:
+#
+# Tempfile.create {|file| file.path } # => "/tmp/20220505-9795-rkists"
+#
+# Related: Tempfile.new.
#
def Tempfile.create(basename="", tmpdir=nil, mode: 0, **options)
tmpfile = nil
diff --git a/lib/time.gemspec b/lib/time.gemspec
index 040b9f34cf..bada91a30b 100644
--- a/lib/time.gemspec
+++ b/lib/time.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "time"
- spec.version = "0.1.0"
+ spec.version = "0.2.2"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/time.rb b/lib/time.rb
index bd20a1a8e9..6a13212a49 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -509,8 +509,8 @@ class Time
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
(\d{2,})\s+
(\d{2})\s*
- :\s*(\d{2})\s*
- (?::\s*(\d{2}))?\s+
+ :\s*(\d{2})
+ (?:\s*:\s*(\d\d))?\s+
([+-]\d{4}|
UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])/ix =~ date
# Since RFC 2822 permit comments, the regexp has no right anchor.
@@ -701,7 +701,7 @@ class Time
#
# If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
#
- # +fractional_digits+ specifies a number of digits to use for fractional
+ # +fraction_digits+ specifies a number of digits to use for fractional
# seconds. Its default value is 0.
#
# require 'time'
diff --git a/lib/timeout.rb b/lib/timeout.rb
index e7b11c0a86..7f40bafa4d 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
# Timeout long-running blocks
#
# == Synopsis
@@ -23,7 +23,7 @@
# Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
module Timeout
- VERSION = "0.1.1"
+ VERSION = "0.3.1"
# Raised by Timeout.timeout when the block times out.
class Error < RuntimeError
@@ -50,9 +50,98 @@ module Timeout
end
# :stopdoc:
- THIS_FILE = /\A#{Regexp.quote(__FILE__)}:/o
- CALLER_OFFSET = ((c = caller[0]) && THIS_FILE =~ c) ? 1 : 0
- private_constant :THIS_FILE, :CALLER_OFFSET
+ CONDVAR = ConditionVariable.new
+ QUEUE = Queue.new
+ QUEUE_MUTEX = Mutex.new
+ TIMEOUT_THREAD_MUTEX = Mutex.new
+ @timeout_thread = nil
+ private_constant :CONDVAR, :QUEUE, :QUEUE_MUTEX, :TIMEOUT_THREAD_MUTEX
+
+ class Request
+ attr_reader :deadline
+
+ def initialize(thread, timeout, exception_class, message)
+ @thread = thread
+ @deadline = GET_TIME.call(Process::CLOCK_MONOTONIC) + timeout
+ @exception_class = exception_class
+ @message = message
+
+ @mutex = Mutex.new
+ @done = false # protected by @mutex
+ end
+
+ def done?
+ @mutex.synchronize do
+ @done
+ end
+ end
+
+ def expired?(now)
+ now >= @deadline
+ end
+
+ def interrupt
+ @mutex.synchronize do
+ unless @done
+ @thread.raise @exception_class, @message
+ @done = true
+ end
+ end
+ end
+
+ def finished
+ @mutex.synchronize do
+ @done = true
+ end
+ end
+ end
+ private_constant :Request
+
+ def self.create_timeout_thread
+ watcher = Thread.new do
+ requests = []
+ while true
+ until QUEUE.empty? and !requests.empty? # wait to have at least one request
+ req = QUEUE.pop
+ requests << req unless req.done?
+ end
+ closest_deadline = requests.min_by(&:deadline).deadline
+
+ now = 0.0
+ QUEUE_MUTEX.synchronize do
+ while (now = GET_TIME.call(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty?
+ CONDVAR.wait(QUEUE_MUTEX, closest_deadline - now)
+ end
+ end
+
+ requests.each do |req|
+ req.interrupt if req.expired?(now)
+ end
+ requests.reject!(&:done?)
+ end
+ end
+ ThreadGroup::Default.add(watcher)
+ watcher.name = "Timeout stdlib thread"
+ watcher.thread_variable_set(:"\0__detached_thread__", true)
+ watcher
+ end
+ private_class_method :create_timeout_thread
+
+ def self.ensure_timeout_thread_created
+ unless @timeout_thread and @timeout_thread.alive?
+ TIMEOUT_THREAD_MUTEX.synchronize do
+ unless @timeout_thread and @timeout_thread.alive?
+ @timeout_thread = create_timeout_thread
+ end
+ end
+ end
+ end
+
+ # We keep a private reference so that time mocking libraries won't break
+ # Timeout.
+ GET_TIME = Process.method(:clock_gettime)
+ private_constant :GET_TIME
+
# :startdoc:
# Perform an operation in a block, raising an error if it takes longer than
@@ -83,51 +172,32 @@ module Timeout
def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+
return yield(sec) if sec == nil or sec.zero?
- message ||= "execution expired".freeze
+ message ||= "execution expired"
if Fiber.respond_to?(:current_scheduler) && (scheduler = Fiber.current_scheduler)&.respond_to?(:timeout_after)
return scheduler.timeout_after(sec, klass || Error, message, &block)
end
- from = "from #{caller_locations(1, 1)[0]}" if $DEBUG
- e = Error
- bl = proc do |exception|
+ Timeout.ensure_timeout_thread_created
+ perform = Proc.new do |exc|
+ request = Request.new(Thread.current, sec, exc, message)
+ QUEUE_MUTEX.synchronize do
+ QUEUE << request
+ CONDVAR.signal
+ end
begin
- x = Thread.current
- y = Thread.start {
- Thread.current.name = from
- begin
- sleep sec
- rescue => e
- x.raise e
- else
- x.raise exception, message
- end
- }
return yield(sec)
ensure
- if y
- y.kill
- y.join # make sure y is dead.
- end
+ request.finished
end
end
+
if klass
- begin
- bl.call(klass)
- rescue klass => e
- message = e.message
- bt = e.backtrace
- end
+ perform.call(klass)
else
- bt = Error.catch(message, &bl)
+ backtrace = Error.catch(&perform)
+ raise Error, message, backtrace
end
- level = -caller(CALLER_OFFSET).size-2
- while THIS_FILE =~ bt[level]
- bt.delete_at(level)
- end
- raise(e, message, bt)
end
-
module_function :timeout
end
diff --git a/lib/timeout/timeout.gemspec b/lib/timeout/timeout.gemspec
index 3dc37f8768..7449ae1980 100644
--- a/lib/timeout/timeout.gemspec
+++ b/lib/timeout/timeout.gemspec
@@ -21,10 +21,10 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ spec.files = Dir.chdir(__dir__) do
+ `git ls-files -z`.split("\x0").reject do |f|
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features|rakelib)/|\.(?:git|travis|circleci)|appveyor|Rakefile)})
+ end
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
diff --git a/lib/tmpdir.gemspec b/lib/tmpdir.gemspec
index 7b76403002..e42662ea3b 100644
--- a/lib/tmpdir.gemspec
+++ b/lib/tmpdir.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "tmpdir"
- spec.version = "0.1.2"
+ spec.version = "0.1.3"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
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.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index bf7db5282a..55920a4a74 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -19,9 +19,10 @@ class Dir
# 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
+ ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', @@systmpdir], ['/tmp']*2, ['.']*2].find do |name, dir|
+ unless dir
+ next if !(dir = ENV[name]) or dir.empty?
+ end
dir = File.expand_path(dir)
stat = File.stat(dir) rescue next
case
@@ -32,12 +33,9 @@ class Dir
when stat.world_writable? && !stat.sticky?
warn "#{name} is world-writable: #{dir}"
else
- tmp = dir
- break
+ break dir
end
- end
- raise ArgumentError, "could not find a temporary directory" unless tmp
- tmp
+ end or raise ArgumentError, "could not find a temporary directory"
end
# Dir.mktmpdir creates a temporary directory.
@@ -69,7 +67,7 @@ class Dir
#
# Dir.mktmpdir {|dir|
# # use the directory...
- # open("#{dir}/foo", "w") { ... }
+ # open("#{dir}/foo", "w") { something using the file }
# }
#
# If a block is not given,
@@ -79,7 +77,7 @@ class Dir
# dir = Dir.mktmpdir
# begin
# # use the directory...
- # open("#{dir}/foo", "w") { ... }
+ # open("#{dir}/foo", "w") { something using the file }
# ensure
# # remove the directory.
# FileUtils.remove_entry dir
@@ -108,6 +106,7 @@ class Dir
end
end
+ # Temporary name generator
module Tmpname # :nodoc:
module_function
@@ -115,16 +114,23 @@ class Dir
Dir.tmpdir
end
+ # Unusable characters as path name
UNUSABLE_CHARS = "^,-.0-9A-Z_a-z~"
- class << (RANDOM = Random.new)
+ # Dedicated random number generator
+ RANDOM = Random.new
+ class << RANDOM # :nodoc:
+ # Maximum random number
MAX = 36**6 # < 0x100000000
+
+ # Returns new random string upto 6 bytes
def next
rand(MAX).to_s(36)
end
end
private_constant :RANDOM
+ # Generates and yields random names to create a temporary name
def create(basename, tmpdir=nil, max_try: nil, **opts)
origdir = tmpdir
tmpdir ||= tmpdir()
diff --git a/lib/tsort.gemspec b/lib/tsort.gemspec
index 4656d0b845..a82393b70b 100644
--- a/lib/tsort.gemspec
+++ b/lib/tsort.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "tsort"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
diff --git a/lib/tsort.rb b/lib/tsort.rb
index 2760b7d57f..00ee609d64 100644
--- a/lib/tsort.rb
+++ b/lib/tsort.rb
@@ -172,8 +172,8 @@ module TSort
# 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
+ def self.tsort(each_node, each_child)
+ tsort_each(each_node, each_child).to_a
end
# The iterator version of the #tsort method.
@@ -220,10 +220,10 @@ module TSort
# # 3
# # 1
#
- def TSort.tsort_each(each_node, each_child) # :yields: node
+ def self.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|
+ each_strongly_connected_component(each_node, each_child) {|component|
if component.size == 1
yield component.first
else
@@ -277,8 +277,8 @@ module TSort
# 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
+ def self.strongly_connected_components(each_node, each_child)
+ each_strongly_connected_component(each_node, each_child).to_a
end
# The iterator version of the #strongly_connected_components method.
@@ -339,14 +339,14 @@ module TSort
# # [2, 3]
# # [1]
#
- def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes
+ def self.each_strongly_connected_component(each_node, each_child) # :yields: nodes
return to_enum(__method__, each_node, each_child) unless block_given?
id_map = {}
stack = []
each_node.call {|node|
unless id_map.include? node
- TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
+ each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
yield c
}
end
@@ -405,7 +405,7 @@ module TSort
# # [2, 3]
# # [1]
#
- def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
+ def self.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
minimum_id = node_id = id_map[node] = id_map.size
@@ -418,7 +418,7 @@ module TSort
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|
+ 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
diff --git a/lib/un.gemspec b/lib/un.gemspec
index 1b89ffa2fb..1a466fdebe 100644
--- a/lib/un.gemspec
+++ b/lib/un.gemspec
@@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "un"
- spec.version = "0.1.0"
+ spec.version = "0.2.1"
spec.authors = ["WATANABE Hirofumi"]
spec.email = ["eban@ruby-lang.org"]
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/un"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
@@ -18,6 +19,6 @@ Gem::Specification.new do |spec|
`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.executables = []
spec.require_paths = ["lib"]
end
diff --git a/lib/un.rb b/lib/un.rb
index 3f59e3ff8b..796b36fbab 100644
--- a/lib/un.rb
+++ b/lib/un.rb
@@ -23,6 +23,7 @@
# ruby -run -e wait_writable -- [OPTION] FILE
# ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
# ruby -run -e httpd -- [OPTION] [DocumentRoot]
+# ruby -run -e colorize -- [FILE]
# ruby -run -e help [COMMAND]
require "fileutils"
@@ -78,13 +79,15 @@ end
#
# -p preserve file attributes if possible
# -r copy recursively
+# -l make hard link instead of copying (implies -r)
# -v verbose
#
def cp
- setup("pr") do |argv, options|
+ setup("prl") do |argv, options|
cmd = "cp"
cmd += "_r" if options.delete :r
+ cmd = "cp_lr" if options.delete :l
options[:preserve] = true if options.delete :p
dest = argv.pop
argv = argv[0] if argv.size == 1
@@ -253,7 +256,7 @@ def wait_writable
wait = (wait = options[:w]) ? Float(wait) : 0.2
argv.each do |file|
begin
- open(file, "r+b")
+ File.open(file, "r+b") {}
rescue Errno::ENOENT
break
rescue Errno::EACCES => e
@@ -346,6 +349,21 @@ def httpd
end
options[:Port] ||= 8080 # HTTP Alternate
options[:DocumentRoot] = argv.shift || '.'
+ s = nil
+ options[:StartCallback] = proc {
+ logger = s.logger
+ logger.info("To access this server, open this URL in a browser:")
+ s.listeners.each do |listener|
+ if options[:SSLEnable]
+ addr = listener.addr
+ addr[3] = "127.0.0.1" if addr[3] == "0.0.0.0"
+ addr[3] = "::1" if addr[3] == "::"
+ logger.info(" https://#{Addrinfo.new(addr).inspect_sockaddr}")
+ else
+ logger.info(" http://#{listener.connect_address.inspect_sockaddr}")
+ end
+ end
+ }
s = WEBrick::HTTPServer.new(options)
shut = proc {s.shutdown}
siglist = %w"TERM QUIT"
@@ -359,6 +377,29 @@ def httpd
end
##
+# Colorize ruby code.
+#
+# ruby -run -e colorize -- [FILE]
+#
+
+def colorize
+ begin
+ require "irb/color"
+ rescue LoadError
+ raise "colorize requires irb 1.1.0 or later"
+ end
+ setup do |argv, |
+ if argv.empty?
+ puts IRB::Color.colorize_code STDIN.read
+ return
+ end
+ argv.each do |file|
+ puts IRB::Color.colorize_code File.read(file)
+ end
+ end
+end
+
+##
# Display help message.
#
# ruby -run -e help [COMMAND]
@@ -381,7 +422,7 @@ module UN # :nodoc:
messages = {}
store = proc {|msg| messages[cmd] = msg}
end
- open(__FILE__) do |me|
+ File.open(__FILE__) do |me|
while me.gets("##\n")
if help = me.gets("\n\n")
if all or argv.include?(cmd = help[/^#\s*ruby\s.*-e\s+(\w+)/, 1])
diff --git a/lib/unicode_normalize/normalize.rb b/lib/unicode_normalize/normalize.rb
index b27cdadaaa..1caf2cc8c8 100644
--- a/lib/unicode_normalize/normalize.rb
+++ b/lib/unicode_normalize/normalize.rb
@@ -20,7 +20,7 @@
require_relative 'tables'
-
+# :stopdoc:
module UnicodeNormalize # :nodoc:
## Constant for max hash capacity to avoid DoS attack
MAX_HASH_LENGTH = 18000 # enough for all test cases, otherwise tests get slow
diff --git a/lib/unicode_normalize/tables.rb b/lib/unicode_normalize/tables.rb
index a7a387d13c..7448fad13f 100644
--- a/lib/unicode_normalize/tables.rb
+++ b/lib/unicode_normalize/tables.rb
@@ -29,7 +29,8 @@ module UnicodeNormalize # :nodoc:
"\u0825-\u0827" \
"\u0829-\u082D" \
"\u0859-\u085B" \
- "\u08D3-\u08E1" \
+ "\u0898-\u089F" \
+ "\u08CA-\u08E1" \
"\u08E3-\u08FF" \
"\u093C" \
"\u094D" \
@@ -50,6 +51,7 @@ module UnicodeNormalize # :nodoc:
"\u0BBE" \
"\u0BCD" \
"\u0BD7" \
+ "\u0C3C" \
"\u0C4D" \
"\u0C55\u0C56" \
"\u0CBC" \
@@ -83,7 +85,7 @@ module UnicodeNormalize # :nodoc:
"\u1039\u103A" \
"\u108D" \
"\u135D-\u135F" \
- "\u1714" \
+ "\u1714\u1715" \
"\u1734" \
"\u17D2" \
"\u17DD" \
@@ -94,7 +96,7 @@ module UnicodeNormalize # :nodoc:
"\u1A75-\u1A7C" \
"\u1A7F" \
"\u1AB0-\u1ABD" \
- "\u1ABF\u1AC0" \
+ "\u1ABF-\u1ACE" \
"\u1B34\u1B35" \
"\u1B44" \
"\u1B6B-\u1B73" \
@@ -108,8 +110,7 @@ module UnicodeNormalize # :nodoc:
"\u1CED" \
"\u1CF4" \
"\u1CF8\u1CF9" \
- "\u1DC0-\u1DF9" \
- "\u1DFB-\u1DFF" \
+ "\u1DC0-\u1DFF" \
"\u20D0-\u20DC" \
"\u20E1" \
"\u20E5-\u20F0" \
@@ -149,8 +150,11 @@ module UnicodeNormalize # :nodoc:
"\u{10AE5}\u{10AE6}" \
"\u{10D24}-\u{10D27}" \
"\u{10EAB}\u{10EAC}" \
+ "\u{10EFD}-\u{10EFF}" \
"\u{10F46}-\u{10F50}" \
+ "\u{10F82}-\u{10F85}" \
"\u{11046}" \
+ "\u{11070}" \
"\u{1107F}" \
"\u{110B9}\u{110BA}" \
"\u{11100}-\u{11102}" \
@@ -191,6 +195,7 @@ module UnicodeNormalize # :nodoc:
"\u{11D42}" \
"\u{11D44}\u{11D45}" \
"\u{11D97}" \
+ "\u{11F41}\u{11F42}" \
"\u{16AF0}-\u{16AF4}" \
"\u{16B30}-\u{16B36}" \
"\u{16FF0}\u{16FF1}" \
@@ -206,8 +211,11 @@ module UnicodeNormalize # :nodoc:
"\u{1E01B}-\u{1E021}" \
"\u{1E023}\u{1E024}" \
"\u{1E026}-\u{1E02A}" \
+ "\u{1E08F}" \
"\u{1E130}-\u{1E136}" \
+ "\u{1E2AE}" \
"\u{1E2EC}-\u{1E2EF}" \
+ "\u{1E4EC}-\u{1E4EF}" \
"\u{1E8D0}-\u{1E8D6}" \
"\u{1E944}-\u{1E94A}" \
"]"
@@ -1402,6 +1410,7 @@ module UnicodeNormalize # :nodoc:
"\u3280-\u33FF" \
"\uA69C\uA69D" \
"\uA770" \
+ "\uA7F2-\uA7F4" \
"\uA7F8\uA7F9" \
"\uAB5C-\uAB5F" \
"\uAB69" \
@@ -1428,6 +1437,9 @@ module UnicodeNormalize # :nodoc:
"\uFFDA-\uFFDC" \
"\uFFE0-\uFFE6" \
"\uFFE8-\uFFEE" \
+ "\u{10781}-\u{10785}" \
+ "\u{10787}-\u{107B0}" \
+ "\u{107B2}-\u{107BA}" \
"\u{1D400}-\u{1D454}" \
"\u{1D456}-\u{1D49C}" \
"\u{1D49E}\u{1D49F}" \
@@ -1449,6 +1461,7 @@ module UnicodeNormalize # :nodoc:
"\u{1D552}-\u{1D6A5}" \
"\u{1D6A8}-\u{1D7CB}" \
"\u{1D7CE}-\u{1D7FF}" \
+ "\u{1E030}-\u{1E06D}" \
"\u{1EE00}-\u{1EE03}" \
"\u{1EE05}-\u{1EE1F}" \
"\u{1EE21}\u{1EE22}" \
@@ -1776,6 +1789,23 @@ module UnicodeNormalize # :nodoc:
"\u0859"=>220,
"\u085A"=>220,
"\u085B"=>220,
+ "\u0898"=>230,
+ "\u0899"=>220,
+ "\u089A"=>220,
+ "\u089B"=>220,
+ "\u089C"=>230,
+ "\u089D"=>230,
+ "\u089E"=>230,
+ "\u089F"=>230,
+ "\u08CA"=>230,
+ "\u08CB"=>230,
+ "\u08CC"=>230,
+ "\u08CD"=>230,
+ "\u08CE"=>230,
+ "\u08CF"=>220,
+ "\u08D0"=>220,
+ "\u08D1"=>220,
+ "\u08D2"=>220,
"\u08D3"=>220,
"\u08D4"=>230,
"\u08D5"=>230,
@@ -1836,6 +1866,7 @@ module UnicodeNormalize # :nodoc:
"\u0B3C"=>7,
"\u0B4D"=>9,
"\u0BCD"=>9,
+ "\u0C3C"=>7,
"\u0C4D"=>9,
"\u0C55"=>84,
"\u0C56"=>91,
@@ -1886,6 +1917,7 @@ module UnicodeNormalize # :nodoc:
"\u135E"=>230,
"\u135F"=>230,
"\u1714"=>9,
+ "\u1715"=>9,
"\u1734"=>9,
"\u17D2"=>9,
"\u17DD"=>230,
@@ -1921,6 +1953,20 @@ module UnicodeNormalize # :nodoc:
"\u1ABD"=>220,
"\u1ABF"=>220,
"\u1AC0"=>220,
+ "\u1AC1"=>230,
+ "\u1AC2"=>230,
+ "\u1AC3"=>220,
+ "\u1AC4"=>220,
+ "\u1AC5"=>230,
+ "\u1AC6"=>230,
+ "\u1AC7"=>230,
+ "\u1AC8"=>230,
+ "\u1AC9"=>230,
+ "\u1ACA"=>220,
+ "\u1ACB"=>230,
+ "\u1ACC"=>230,
+ "\u1ACD"=>230,
+ "\u1ACE"=>230,
"\u1B34"=>7,
"\u1B44"=>9,
"\u1B6B"=>230,
@@ -2023,6 +2069,7 @@ module UnicodeNormalize # :nodoc:
"\u1DF7"=>228,
"\u1DF8"=>228,
"\u1DF9"=>220,
+ "\u1DFA"=>218,
"\u1DFB"=>230,
"\u1DFC"=>233,
"\u1DFD"=>220,
@@ -2189,6 +2236,9 @@ module UnicodeNormalize # :nodoc:
"\u{10D27}"=>230,
"\u{10EAB}"=>230,
"\u{10EAC}"=>230,
+ "\u{10EFD}"=>220,
+ "\u{10EFE}"=>220,
+ "\u{10EFF}"=>220,
"\u{10F46}"=>220,
"\u{10F47}"=>220,
"\u{10F48}"=>230,
@@ -2200,7 +2250,12 @@ module UnicodeNormalize # :nodoc:
"\u{10F4E}"=>220,
"\u{10F4F}"=>220,
"\u{10F50}"=>220,
+ "\u{10F82}"=>230,
+ "\u{10F83}"=>220,
+ "\u{10F84}"=>230,
+ "\u{10F85}"=>220,
"\u{11046}"=>9,
+ "\u{11070}"=>9,
"\u{1107F}"=>9,
"\u{110B9}"=>9,
"\u{110BA}"=>7,
@@ -2256,6 +2311,8 @@ module UnicodeNormalize # :nodoc:
"\u{11D44}"=>9,
"\u{11D45}"=>9,
"\u{11D97}"=>9,
+ "\u{11F41}"=>9,
+ "\u{11F42}"=>9,
"\u{16AF0}"=>1,
"\u{16AF1}"=>1,
"\u{16AF2}"=>1,
@@ -2342,6 +2399,7 @@ module UnicodeNormalize # :nodoc:
"\u{1E028}"=>230,
"\u{1E029}"=>230,
"\u{1E02A}"=>230,
+ "\u{1E08F}"=>230,
"\u{1E130}"=>230,
"\u{1E131}"=>230,
"\u{1E132}"=>230,
@@ -2349,10 +2407,15 @@ module UnicodeNormalize # :nodoc:
"\u{1E134}"=>230,
"\u{1E135}"=>230,
"\u{1E136}"=>230,
+ "\u{1E2AE}"=>230,
"\u{1E2EC}"=>230,
"\u{1E2ED}"=>230,
"\u{1E2EE}"=>230,
"\u{1E2EF}"=>230,
+ "\u{1E4EC}"=>232,
+ "\u{1E4ED}"=>232,
+ "\u{1E4EE}"=>220,
+ "\u{1E4EF}"=>230,
"\u{1E8D0}"=>220,
"\u{1E8D1}"=>220,
"\u{1E8D2}"=>220,
@@ -5776,6 +5839,9 @@ module UnicodeNormalize # :nodoc:
"\uA69C"=>"\u044A",
"\uA69D"=>"\u044C",
"\uA770"=>"\uA76F",
+ "\uA7F2"=>"C",
+ "\uA7F3"=>"F",
+ "\uA7F4"=>"Q",
"\uA7F8"=>"\u0126",
"\uA7F9"=>"\u0153",
"\uAB5C"=>"\uA727",
@@ -6828,6 +6894,62 @@ module UnicodeNormalize # :nodoc:
"\uFFEC"=>"\u2193",
"\uFFED"=>"\u25A0",
"\uFFEE"=>"\u25CB",
+ "\u{10781}"=>"\u02D0",
+ "\u{10782}"=>"\u02D1",
+ "\u{10783}"=>"\u00E6",
+ "\u{10784}"=>"\u0299",
+ "\u{10785}"=>"\u0253",
+ "\u{10787}"=>"\u02A3",
+ "\u{10788}"=>"\uAB66",
+ "\u{10789}"=>"\u02A5",
+ "\u{1078A}"=>"\u02A4",
+ "\u{1078B}"=>"\u0256",
+ "\u{1078C}"=>"\u0257",
+ "\u{1078D}"=>"\u1D91",
+ "\u{1078E}"=>"\u0258",
+ "\u{1078F}"=>"\u025E",
+ "\u{10790}"=>"\u02A9",
+ "\u{10791}"=>"\u0264",
+ "\u{10792}"=>"\u0262",
+ "\u{10793}"=>"\u0260",
+ "\u{10794}"=>"\u029B",
+ "\u{10795}"=>"\u0127",
+ "\u{10796}"=>"\u029C",
+ "\u{10797}"=>"\u0267",
+ "\u{10798}"=>"\u0284",
+ "\u{10799}"=>"\u02AA",
+ "\u{1079A}"=>"\u02AB",
+ "\u{1079B}"=>"\u026C",
+ "\u{1079C}"=>"\u{1DF04}",
+ "\u{1079D}"=>"\uA78E",
+ "\u{1079E}"=>"\u026E",
+ "\u{1079F}"=>"\u{1DF05}",
+ "\u{107A0}"=>"\u028E",
+ "\u{107A1}"=>"\u{1DF06}",
+ "\u{107A2}"=>"\u00F8",
+ "\u{107A3}"=>"\u0276",
+ "\u{107A4}"=>"\u0277",
+ "\u{107A5}"=>"q",
+ "\u{107A6}"=>"\u027A",
+ "\u{107A7}"=>"\u{1DF08}",
+ "\u{107A8}"=>"\u027D",
+ "\u{107A9}"=>"\u027E",
+ "\u{107AA}"=>"\u0280",
+ "\u{107AB}"=>"\u02A8",
+ "\u{107AC}"=>"\u02A6",
+ "\u{107AD}"=>"\uAB67",
+ "\u{107AE}"=>"\u02A7",
+ "\u{107AF}"=>"\u0288",
+ "\u{107B0}"=>"\u2C71",
+ "\u{107B2}"=>"\u028F",
+ "\u{107B3}"=>"\u02A1",
+ "\u{107B4}"=>"\u02A2",
+ "\u{107B5}"=>"\u0298",
+ "\u{107B6}"=>"\u01C0",
+ "\u{107B7}"=>"\u01C1",
+ "\u{107B8}"=>"\u01C2",
+ "\u{107B9}"=>"\u{1DF0A}",
+ "\u{107BA}"=>"\u{1DF1E}",
"\u{1D400}"=>"A",
"\u{1D401}"=>"B",
"\u{1D402}"=>"C",
@@ -7824,6 +7946,68 @@ module UnicodeNormalize # :nodoc:
"\u{1D7FD}"=>"7",
"\u{1D7FE}"=>"8",
"\u{1D7FF}"=>"9",
+ "\u{1E030}"=>"\u0430",
+ "\u{1E031}"=>"\u0431",
+ "\u{1E032}"=>"\u0432",
+ "\u{1E033}"=>"\u0433",
+ "\u{1E034}"=>"\u0434",
+ "\u{1E035}"=>"\u0435",
+ "\u{1E036}"=>"\u0436",
+ "\u{1E037}"=>"\u0437",
+ "\u{1E038}"=>"\u0438",
+ "\u{1E039}"=>"\u043A",
+ "\u{1E03A}"=>"\u043B",
+ "\u{1E03B}"=>"\u043C",
+ "\u{1E03C}"=>"\u043E",
+ "\u{1E03D}"=>"\u043F",
+ "\u{1E03E}"=>"\u0440",
+ "\u{1E03F}"=>"\u0441",
+ "\u{1E040}"=>"\u0442",
+ "\u{1E041}"=>"\u0443",
+ "\u{1E042}"=>"\u0444",
+ "\u{1E043}"=>"\u0445",
+ "\u{1E044}"=>"\u0446",
+ "\u{1E045}"=>"\u0447",
+ "\u{1E046}"=>"\u0448",
+ "\u{1E047}"=>"\u044B",
+ "\u{1E048}"=>"\u044D",
+ "\u{1E049}"=>"\u044E",
+ "\u{1E04A}"=>"\uA689",
+ "\u{1E04B}"=>"\u04D9",
+ "\u{1E04C}"=>"\u0456",
+ "\u{1E04D}"=>"\u0458",
+ "\u{1E04E}"=>"\u04E9",
+ "\u{1E04F}"=>"\u04AF",
+ "\u{1E050}"=>"\u04CF",
+ "\u{1E051}"=>"\u0430",
+ "\u{1E052}"=>"\u0431",
+ "\u{1E053}"=>"\u0432",
+ "\u{1E054}"=>"\u0433",
+ "\u{1E055}"=>"\u0434",
+ "\u{1E056}"=>"\u0435",
+ "\u{1E057}"=>"\u0436",
+ "\u{1E058}"=>"\u0437",
+ "\u{1E059}"=>"\u0438",
+ "\u{1E05A}"=>"\u043A",
+ "\u{1E05B}"=>"\u043B",
+ "\u{1E05C}"=>"\u043E",
+ "\u{1E05D}"=>"\u043F",
+ "\u{1E05E}"=>"\u0441",
+ "\u{1E05F}"=>"\u0443",
+ "\u{1E060}"=>"\u0444",
+ "\u{1E061}"=>"\u0445",
+ "\u{1E062}"=>"\u0446",
+ "\u{1E063}"=>"\u0447",
+ "\u{1E064}"=>"\u0448",
+ "\u{1E065}"=>"\u044A",
+ "\u{1E066}"=>"\u044B",
+ "\u{1E067}"=>"\u0491",
+ "\u{1E068}"=>"\u0456",
+ "\u{1E069}"=>"\u0455",
+ "\u{1E06A}"=>"\u045F",
+ "\u{1E06B}"=>"\u04AB",
+ "\u{1E06C}"=>"\uA651",
+ "\u{1E06D}"=>"\u04B1",
"\u{1EE00}"=>"\u0627",
"\u{1EE01}"=>"\u0628",
"\u{1EE02}"=>"\u062C",
diff --git a/lib/uri.rb b/lib/uri.rb
index 394c156ac5..59a7c4ad28 100644
--- a/lib/uri.rb
+++ b/lib/uri.rb
@@ -101,3 +101,4 @@ require_relative 'uri/ldap'
require_relative 'uri/ldaps'
require_relative 'uri/mailto'
require_relative 'uri/ws'
+require_relative 'uri/wss'
diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index 26b179add2..0c4064a67a 100644
--- a/lib/uri/common.rb
+++ b/lib/uri/common.rb
@@ -13,10 +13,14 @@ require_relative "rfc2396_parser"
require_relative "rfc3986_parser"
module URI
+ include RFC2396_REGEXP
+
REGEXP = RFC2396_REGEXP
Parser = RFC2396_Parser
RFC3986_PARSER = RFC3986_Parser.new
Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
+ RFC2396_PARSER = RFC2396_Parser.new
+ Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
# URI::Parser.new
DEFAULT_PARSER = Parser.new
@@ -62,14 +66,17 @@ module URI
module_function :make_components_hash
end
- include REGEXP
-
module Schemes
end
private_constant :Schemes
+ #
+ # Register the given +klass+ to be instantiated when parsing URLs with the given +scheme+.
+ # Note that currently only schemes which after .upcase are valid constant names
+ # can be registered (no -/+/. allowed).
+ #
def self.register_scheme(scheme, klass)
- Schemes.const_set(scheme, klass)
+ Schemes.const_set(scheme.to_s.upcase, klass)
end
# Returns a Hash of the defined schemes.
@@ -295,6 +302,7 @@ module URI
256.times do |i|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
end
+ TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
@@ -320,6 +328,33 @@ module URI
#
# See URI.decode_www_form_component, URI.encode_www_form.
def self.encode_www_form_component(str, enc=nil)
+ _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
+ end
+
+ # Decodes given +str+ of URL-encoded form data.
+ #
+ # This decodes + to SP.
+ #
+ # See URI.encode_www_form_component, URI.decode_www_form.
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
+ _decode_uri_component(/\+|%\h\h/, str, enc)
+ end
+
+ # Encodes +str+ using URL encoding
+ #
+ # This encodes SP to %20 instead of +.
+ def self.encode_uri_component(str, enc=nil)
+ _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
+ end
+
+ # Decodes given +str+ of URL-encoded data.
+ #
+ # This does not decode + to SP.
+ def self.decode_uri_component(str, enc=Encoding::UTF_8)
+ _decode_uri_component(/%\h\h/, str, enc)
+ end
+
+ def self._encode_uri_component(regexp, table, str, enc)
str = str.to_s.dup
if str.encoding != Encoding::ASCII_8BIT
if enc && enc != Encoding::ASCII_8BIT
@@ -328,19 +363,16 @@ module URI
end
str.force_encoding(Encoding::ASCII_8BIT)
end
- str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
+ str.gsub!(regexp, table)
str.force_encoding(Encoding::US_ASCII)
end
+ private_class_method :_encode_uri_component
- # Decodes given +str+ of URL-encoded form data.
- #
- # This decodes + to SP.
- #
- # See URI.encode_www_form_component, URI.decode_www_form.
- def self.decode_www_form_component(str, enc=Encoding::UTF_8)
+ def self._decode_uri_component(regexp, str, enc)
raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
- str.b.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
+ str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
end
+ private_class_method :_decode_uri_component
# Generates URL-encoded form data from given +enum+.
#
diff --git a/lib/uri/file.rb b/lib/uri/file.rb
index 7671ad6470..4ff0bc097e 100644
--- a/lib/uri/file.rb
+++ b/lib/uri/file.rb
@@ -33,6 +33,9 @@ module URI
# If an Array is used, the components must be passed in the
# order <code>[host, path]</code>.
#
+ # A path from e.g. the File class should be escaped before
+ # being passed.
+ #
# Examples:
#
# require 'uri'
@@ -44,6 +47,9 @@ module URI
# :path => '/ruby/src'})
# uri2.to_s # => "file://host.example.com/ruby/src"
#
+ # uri3 = URI::File.build({:path => URI::escape('/path/my file.txt')})
+ # uri3.to_s # => "file:///path/my%20file.txt"
+ #
def self.build(args)
tmp = Util::make_components_hash(self, args)
super(tmp)
diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb
index cfa0de6b74..f7eed57924 100644
--- a/lib/uri/generic.rb
+++ b/lib/uri/generic.rb
@@ -564,16 +564,26 @@ module URI
end
end
- # Returns the user component.
+ # Returns the user component (without URI decoding).
def user
@user
end
- # Returns the password component.
+ # Returns the password component (without URI decoding).
def password
@password
end
+ # Returns the user component after URI decoding.
+ def decoded_user
+ URI.decode_uri_component(@user) if @user
+ end
+
+ # Returns the password component after URI decoding.
+ def decoded_password
+ URI.decode_uri_component(@password) if @password
+ end
+
#
# Checks the host +v+ component for RFC2396 compliance
# and against the URI::Parser Regexp for :HOST.
@@ -1123,17 +1133,16 @@ module URI
base.fragment=(nil)
# RFC2396, Section 5.2, 4)
- if !authority
- base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
- else
- # RFC2396, Section 5.2, 4)
- base.set_path(rel.path) if rel.path
+ if authority
+ base.set_userinfo(rel.userinfo)
+ base.set_host(rel.host)
+ base.set_port(rel.port || base.default_port)
+ base.set_path(rel.path)
+ elsif base.path && rel.path
+ base.set_path(merge_path(base.path, rel.path))
end
# RFC2396, Section 5.2, 7)
- base.set_userinfo(rel.userinfo) if rel.userinfo
- base.set_host(rel.host) if rel.host
- base.set_port(rel.port) if rel.port
base.query = rel.query if rel.query
base.fragment=(rel.fragment) if rel.fragment
diff --git a/lib/uri/http.rb b/lib/uri/http.rb
index 6e9c963ef1..306daf1965 100644
--- a/lib/uri/http.rb
+++ b/lib/uri/http.rb
@@ -80,6 +80,45 @@ module URI
url = @query ? "#@path?#@query" : @path.dup
url.start_with?(?/.freeze) ? url : ?/ + url
end
+
+ #
+ # == Description
+ #
+ # Returns the authority for an HTTP uri, as defined in
+ # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.
+ #
+ #
+ # Example:
+ #
+ # URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').authority #=> "www.example.com"
+ # URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').authority #=> "www.example.com:8000"
+ # URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').authority #=> "www.example.com"
+ #
+ def authority
+ if port == default_port
+ host
+ else
+ "#{host}:#{port}"
+ end
+ end
+
+ #
+ # == Description
+ #
+ # Returns the origin for an HTTP uri, as defined in
+ # https://datatracker.ietf.org/doc/html/rfc6454.
+ #
+ #
+ # Example:
+ #
+ # URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').origin #=> "http://www.example.com"
+ # URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').origin #=> "http://www.example.com:8000"
+ # URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').origin #=> "http://www.example.com"
+ # URI::HTTPS.build(host: 'www.example.com', path: '/foo/bar').origin #=> "https://www.example.com"
+ #
+ def origin
+ "#{scheme}://#{authority}"
+ end
end
register_scheme 'HTTP', HTTP
diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb
index 87cb99656f..cb8024f301 100644
--- a/lib/uri/mailto.rb
+++ b/lib/uri/mailto.rb
@@ -15,7 +15,7 @@ module URI
# RFC6068, the mailto URL scheme.
#
class MailTo < Generic
- include REGEXP
+ include RFC2396_REGEXP
# A Default port of nil for URI::MailTo.
DEFAULT_PORT = nil
diff --git a/lib/uri/rfc2396_parser.rb b/lib/uri/rfc2396_parser.rb
index 76a8f99fd4..00c66cf042 100644
--- a/lib/uri/rfc2396_parser.rb
+++ b/lib/uri/rfc2396_parser.rb
@@ -497,8 +497,8 @@ module URI
ret = {}
# for URI::split
- ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
- ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
+ ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
+ ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
# for URI::extract
ret[:URI_REF] = Regexp.new(pattern[:URI_REF])
diff --git a/lib/uri/rfc3986_parser.rb b/lib/uri/rfc3986_parser.rb
index 3e07de4805..9b1663dbb6 100644
--- a/lib/uri/rfc3986_parser.rb
+++ b/lib/uri/rfc3986_parser.rb
@@ -2,9 +2,8 @@
module URI
class RFC3986_Parser # :nodoc:
# URI defined in RFC3986
- # this regexp is modified not to host is not empty string
- RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
- RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
+ RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*+):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+))(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
+ RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])++)(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
attr_reader :regexp
def initialize
@@ -101,7 +100,7 @@ module URI
QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
OPAQUE: /\A(?:[^\/].*)?\z/,
- PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/,
+ PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
}
end
diff --git a/lib/uri/version.rb b/lib/uri/version.rb
index 41da51d844..c93c97cf6f 100644
--- a/lib/uri/version.rb
+++ b/lib/uri/version.rb
@@ -1,6 +1,6 @@
module URI
# :stopdoc:
- VERSION_CODE = '001001'.freeze
+ VERSION_CODE = '001204'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/lib/weakref.rb b/lib/weakref.rb
index fbd5d8fa82..2bbadf68f9 100644
--- a/lib/weakref.rb
+++ b/lib/weakref.rb
@@ -17,7 +17,7 @@ require "delegate"
#
class WeakRef < Delegator
- VERSION = "0.1.1"
+ VERSION = "0.1.2"
##
# RefError is raised when a referenced object has been recycled by the
@@ -30,9 +30,6 @@ class WeakRef < Delegator
##
# Creates a weak reference to +orig+
- #
- # Raises an ArgumentError if the given +orig+ is immutable, such as Symbol,
- # Integer, or Float.
def initialize(orig)
case orig
diff --git a/lib/yaml.rb b/lib/yaml.rb
index 17b27e802f..6d5d5ebd4c 100644
--- a/lib/yaml.rb
+++ b/lib/yaml.rb
@@ -3,9 +3,17 @@
begin
require 'psych'
rescue LoadError
- warn "It seems your ruby installation is missing psych (for YAML output).\n" \
- "To eliminate this warning, please install libyaml and reinstall your ruby.\n",
- uplevel: 1
+ case RUBY_ENGINE
+ when 'jruby'
+ warn "The Psych YAML extension failed to load.\n" \
+ "Check your env for conflicting versions of SnakeYAML\n" \
+ "See https://github.com/jruby/jruby/wiki/FAQs#why-does-the-psych-yaml-extension-fail-to-load-in-my-environment",
+ uplevel: 1
+ else
+ warn "It seems your ruby installation is missing psych (for YAML output).\n" \
+ "To eliminate this warning, please install libyaml and reinstall your ruby.\n",
+ uplevel: 1
+ end
raise
end
diff --git a/lib/yaml/yaml.gemspec b/lib/yaml/yaml.gemspec
index cf19b0e0da..80554d8a7a 100644
--- a/lib/yaml/yaml.gemspec
+++ b/lib/yaml/yaml.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "yaml"
- spec.version = "0.1.1"
+ spec.version = "0.2.1"
spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"]
spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"]
diff --git a/libexec/bundle b/libexec/bundle
index 1168e5a361..90c62627f8 100755
--- a/libexec/bundle
+++ b/libexec/bundle
@@ -10,36 +10,24 @@ end
base_path = File.expand_path("../lib", __dir__)
if File.exist?(base_path)
- require_relative "../lib/bundler"
-else
- require "bundler"
+ $LOAD_PATH.unshift(base_path)
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
- err = String.new
- err << "Looks like you have a version of bundler that's older than 0.9.\n"
- err << "Please remove your old versions.\n"
- err << "An easy way to do this is by running `gem cleanup bundler`."
- abort(err)
-end
+require "bundler"
-if File.exist?(base_path)
- require_relative "../lib/bundler/friendly_errors"
-else
- require "bundler/friendly_errors"
+if Gem.rubygems_version < Gem::Version.new("3.2.3") && Gem.ruby_version < Gem::Version.new("2.7.a") && !ENV["BUNDLER_NO_OLD_RUBYGEMS_WARNING"]
+ Bundler.ui.warn \
+ "Your RubyGems version (#{Gem::VERSION}) has a bug that prevents " \
+ "`required_ruby_version` from working for Bundler. Any scripts that use " \
+ "`gem install bundler` will break as soon as Bundler drops support for " \
+ "your Ruby version. Please upgrade RubyGems to avoid future breakage " \
+ "and silence this warning by running `gem update --system 3.2.3`"
end
+require "bundler/friendly_errors"
+
Bundler.with_friendly_errors do
- if File.exist?(base_path)
- require_relative "../lib/bundler/cli"
- else
- require "bundler/cli"
- end
+ require "bundler/cli"
# Allow any command to use --help flag to show help for that command
help_flags = %w[--help -h]
diff --git a/libexec/bundler b/libexec/bundler
index d9131fe834..a6826a8c89 100755
--- a/libexec/bundler
+++ b/libexec/bundler
@@ -1,4 +1,4 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
-load File.expand_path("../bundle", __FILE__)
+load File.expand_path("bundle", __dir__)
diff --git a/libexec/erb b/libexec/erb
index ded76991dc..4381671f25 100755
--- a/libexec/erb
+++ b/libexec/erb
@@ -74,11 +74,6 @@ class ERB
$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 == '-'
@@ -127,12 +122,7 @@ EOU
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 = factory.new(src, trim_mode: trim)
erb.filename = filename
if output
if number
diff --git a/libexec/rdoc b/libexec/rdoc
index aaa23292df..95b6eea277 100755
--- a/libexec/rdoc
+++ b/libexec/rdoc
@@ -41,4 +41,3 @@ rescue Exception => e
exit 1
end
-
diff --git a/libexec/syntax_suggest b/libexec/syntax_suggest
new file mode 100755
index 0000000000..e4a0b0b658
--- /dev/null
+++ b/libexec/syntax_suggest
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+
+require_relative "../lib/syntax_suggest/api"
+
+SyntaxSuggest::Cli.new(
+ argv: ARGV
+).call
diff --git a/load.c b/load.c
index b2363690aa..ecb21faa72 100644
--- a/load.c
+++ b/load.c
@@ -14,6 +14,7 @@
#include "internal/variable.h"
#include "iseq.h"
#include "probes.h"
+#include "darray.h"
#include "ruby/encoding.h"
#include "ruby/util.h"
@@ -21,17 +22,10 @@ static VALUE ruby_dln_librefs;
#define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
-#ifdef DLEXT2
-#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0)
-#else
#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
-#endif
static const char *const loadable_ext[] = {
".rb", DLEXT,
-#ifdef DLEXT2
- DLEXT2,
-#endif
0
};
@@ -53,99 +47,103 @@ enum expand_type {
string objects in $LOAD_PATH are frozen.
*/
static void
-rb_construct_expanded_load_path(enum expand_type type, int *has_relative, int *has_non_cache)
+rb_construct_expanded_load_path(rb_vm_t *vm, enum expand_type type, int *has_relative, int *has_non_cache)
{
- rb_vm_t *vm = GET_VM();
VALUE load_path = vm->load_path;
VALUE expanded_load_path = vm->expanded_load_path;
VALUE ary;
long i;
- ary = rb_ary_tmp_new(RARRAY_LEN(load_path));
+ ary = rb_ary_hidden_new(RARRAY_LEN(load_path));
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
- VALUE path, as_str, expanded_path;
- int is_string, non_cache;
- char *as_cstr;
- as_str = path = RARRAY_AREF(load_path, i);
- is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0;
- non_cache = !is_string ? 1 : 0;
+ VALUE path, as_str, expanded_path;
+ int is_string, non_cache;
+ char *as_cstr;
+ as_str = path = RARRAY_AREF(load_path, i);
+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0;
+ non_cache = !is_string ? 1 : 0;
as_str = rb_get_path_check_to_string(path);
- as_cstr = RSTRING_PTR(as_str);
-
- if (!non_cache) {
- if ((type == EXPAND_RELATIVE &&
- rb_is_absolute_path(as_cstr)) ||
- (type == EXPAND_HOME &&
- (!as_cstr[0] || as_cstr[0] != '~')) ||
- (type == EXPAND_NON_CACHE)) {
- /* Use cached expanded path. */
- rb_ary_push(ary, RARRAY_AREF(expanded_load_path, i));
- continue;
- }
- }
- if (!*has_relative && !rb_is_absolute_path(as_cstr))
- *has_relative = 1;
- if (!*has_non_cache && non_cache)
- *has_non_cache = 1;
- /* Freeze only string object. We expand other objects every time. */
- if (is_string)
- rb_str_freeze(path);
+ as_cstr = RSTRING_PTR(as_str);
+
+ if (!non_cache) {
+ if ((type == EXPAND_RELATIVE &&
+ rb_is_absolute_path(as_cstr)) ||
+ (type == EXPAND_HOME &&
+ (!as_cstr[0] || as_cstr[0] != '~')) ||
+ (type == EXPAND_NON_CACHE)) {
+ /* Use cached expanded path. */
+ rb_ary_push(ary, RARRAY_AREF(expanded_load_path, i));
+ continue;
+ }
+ }
+ if (!*has_relative && !rb_is_absolute_path(as_cstr))
+ *has_relative = 1;
+ if (!*has_non_cache && non_cache)
+ *has_non_cache = 1;
+ /* Freeze only string object. We expand other objects every time. */
+ if (is_string)
+ rb_str_freeze(path);
as_str = rb_get_path_check_convert(as_str);
- expanded_path = rb_check_realpath(Qnil, as_str, NULL);
- if (NIL_P(expanded_path)) expanded_path = as_str;
- rb_ary_push(ary, rb_fstring(expanded_path));
+ expanded_path = rb_check_realpath(Qnil, as_str, NULL);
+ if (NIL_P(expanded_path)) expanded_path = as_str;
+ rb_ary_push(ary, rb_fstring(expanded_path));
}
rb_obj_freeze(ary);
vm->expanded_load_path = ary;
rb_ary_replace(vm->load_path_snapshot, vm->load_path);
}
-VALUE
-rb_get_expanded_load_path(void)
+static VALUE
+get_expanded_load_path(rb_vm_t *vm)
{
- rb_vm_t *vm = GET_VM();
const VALUE non_cache = Qtrue;
if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) {
- /* The load path was modified. Rebuild the expanded load path. */
- int has_relative = 0, has_non_cache = 0;
- rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache);
- if (has_relative) {
- vm->load_path_check_cache = rb_dir_getwd_ospath();
- }
- else if (has_non_cache) {
- /* Non string object. */
- vm->load_path_check_cache = non_cache;
- }
- else {
- vm->load_path_check_cache = 0;
- }
+ /* The load path was modified. Rebuild the expanded load path. */
+ int has_relative = 0, has_non_cache = 0;
+ rb_construct_expanded_load_path(vm, EXPAND_ALL, &has_relative, &has_non_cache);
+ if (has_relative) {
+ vm->load_path_check_cache = rb_dir_getwd_ospath();
+ }
+ else if (has_non_cache) {
+ /* Non string object. */
+ vm->load_path_check_cache = non_cache;
+ }
+ else {
+ vm->load_path_check_cache = 0;
+ }
}
else if (vm->load_path_check_cache == non_cache) {
- int has_relative = 1, has_non_cache = 1;
- /* Expand only non-cacheable objects. */
- rb_construct_expanded_load_path(EXPAND_NON_CACHE,
- &has_relative, &has_non_cache);
+ int has_relative = 1, has_non_cache = 1;
+ /* Expand only non-cacheable objects. */
+ rb_construct_expanded_load_path(vm, EXPAND_NON_CACHE,
+ &has_relative, &has_non_cache);
}
else if (vm->load_path_check_cache) {
- int has_relative = 1, has_non_cache = 1;
- VALUE cwd = rb_dir_getwd_ospath();
- if (!rb_str_equal(vm->load_path_check_cache, cwd)) {
- /* Current working directory or filesystem encoding was changed.
- Expand relative load path and non-cacheable objects again. */
- vm->load_path_check_cache = cwd;
- rb_construct_expanded_load_path(EXPAND_RELATIVE,
- &has_relative, &has_non_cache);
- }
- else {
- /* Expand only tilde (User HOME) and non-cacheable objects. */
- rb_construct_expanded_load_path(EXPAND_HOME,
- &has_relative, &has_non_cache);
- }
+ int has_relative = 1, has_non_cache = 1;
+ VALUE cwd = rb_dir_getwd_ospath();
+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) {
+ /* Current working directory or filesystem encoding was changed.
+ Expand relative load path and non-cacheable objects again. */
+ vm->load_path_check_cache = cwd;
+ rb_construct_expanded_load_path(vm, EXPAND_RELATIVE,
+ &has_relative, &has_non_cache);
+ }
+ else {
+ /* Expand only tilde (User HOME) and non-cacheable objects. */
+ rb_construct_expanded_load_path(vm, EXPAND_HOME,
+ &has_relative, &has_non_cache);
+ }
}
return vm->expanded_load_path;
}
+VALUE
+rb_get_expanded_load_path(void)
+{
+ return get_expanded_load_path(GET_VM());
+}
+
static VALUE
load_path_getter(ID id, VALUE * p)
{
@@ -154,34 +152,45 @@ load_path_getter(ID id, VALUE * p)
}
static VALUE
-get_loaded_features(void)
+get_loaded_features(rb_vm_t *vm)
{
- return GET_VM()->loaded_features;
+ return vm->loaded_features;
+}
+
+static VALUE
+get_loaded_features_realpaths(rb_vm_t *vm)
+{
+ return vm->loaded_features_realpaths;
+}
+
+static VALUE
+get_loaded_features_realpath_map(rb_vm_t *vm)
+{
+ return vm->loaded_features_realpath_map;
}
static VALUE
get_LOADED_FEATURES(ID _x, VALUE *_y)
{
- return get_loaded_features();
+ return get_loaded_features(GET_VM());
}
static void
-reset_loaded_features_snapshot(void)
+reset_loaded_features_snapshot(rb_vm_t *vm)
{
- rb_vm_t *vm = GET_VM();
rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
}
static struct st_table *
-get_loaded_features_index_raw(void)
+get_loaded_features_index_raw(rb_vm_t *vm)
{
- return GET_VM()->loaded_features_index;
+ return vm->loaded_features_index;
}
static st_table *
-get_loading_table(void)
+get_loading_table(rb_vm_t *vm)
{
- return GET_VM()->loading_table;
+ return vm->loading_table;
}
static st_data_t
@@ -199,61 +208,95 @@ is_rbext_path(VALUE feature_path)
return IS_RBEXT(RSTRING_PTR(feature_path) + len - rbext_len);
}
+typedef rb_darray(long) feature_indexes_t;
+
+struct features_index_add_single_args {
+ rb_vm_t *vm;
+ VALUE offset;
+ bool rb;
+};
+
+static int
+features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t raw_args, int existing)
+{
+ struct features_index_add_single_args *args = (struct features_index_add_single_args *)raw_args;
+ rb_vm_t *vm = args->vm;
+ VALUE offset = args->offset;
+ bool rb = args->rb;
+
+ if (existing) {
+ VALUE this_feature_index = *value;
+
+ if (FIXNUM_P(this_feature_index)) {
+ VALUE loaded_features = get_loaded_features(vm);
+ VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(this_feature_index));
+
+ feature_indexes_t feature_indexes;
+ rb_darray_make(&feature_indexes, 2);
+ int top = (rb && !is_rbext_path(this_feature_path)) ? 1 : 0;
+ rb_darray_set(feature_indexes, top^0, FIX2LONG(this_feature_index));
+ rb_darray_set(feature_indexes, top^1, FIX2LONG(offset));
+
+ assert(rb_darray_size(feature_indexes) == 2);
+ // assert feature_indexes does not look like a special const
+ assert(!SPECIAL_CONST_P((VALUE)feature_indexes));
+
+ *value = (st_data_t)feature_indexes;
+ }
+ else {
+ feature_indexes_t feature_indexes = (feature_indexes_t)this_feature_index;
+ long pos = -1;
+
+ if (rb) {
+ VALUE loaded_features = get_loaded_features(vm);
+ for (size_t i = 0; i < rb_darray_size(feature_indexes); ++i) {
+ long idx = rb_darray_get(feature_indexes, i);
+ VALUE this_feature_path = RARRAY_AREF(loaded_features, idx);
+ Check_Type(this_feature_path, T_STRING);
+ if (!is_rbext_path(this_feature_path)) {
+ pos = i;
+ break;
+ }
+ }
+ }
+
+ rb_darray_append(&feature_indexes, FIX2LONG(offset));
+ /* darray may realloc which will change the pointer */
+ *value = (st_data_t)feature_indexes;
+
+ if (pos >= 0) {
+ long *ptr = rb_darray_data_ptr(feature_indexes);
+ long len = rb_darray_size(feature_indexes);
+ MEMMOVE(ptr + pos, ptr + pos + 1, long, len - pos - 1);
+ ptr[pos] = FIX2LONG(offset);
+ }
+ }
+ }
+ else {
+ *value = offset;
+ }
+
+ return ST_CONTINUE;
+}
+
static void
-features_index_add_single(const char* str, size_t len, VALUE offset, bool rb)
+features_index_add_single(rb_vm_t *vm, const char* str, size_t len, VALUE offset, bool rb)
{
struct st_table *features_index;
- VALUE this_feature_index = Qnil;
st_data_t short_feature_key;
- st_data_t data;
Check_Type(offset, T_FIXNUM);
short_feature_key = feature_key(str, len);
- features_index = get_loaded_features_index_raw();
- if (!st_lookup(features_index, short_feature_key, &data) ||
- NIL_P(this_feature_index = (VALUE)data)) {
- st_insert(features_index, short_feature_key, (st_data_t)offset);
- }
- else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
- VALUE loaded_features = get_loaded_features();
- VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(this_feature_index));
- VALUE feature_indexes[2];
- int top = (rb && !is_rbext_path(this_feature_path)) ? 1 : 0;
- feature_indexes[top^0] = this_feature_index;
- feature_indexes[top^1] = offset;
- this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
- RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
- rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
- st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
- }
- else {
- long pos = -1;
-
- Check_Type(this_feature_index, T_ARRAY);
- if (rb) {
- VALUE loaded_features = get_loaded_features();
- for (long i = 0; i < RARRAY_LEN(this_feature_index); ++i) {
- VALUE idx = RARRAY_AREF(this_feature_index, i);
- VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(idx));
- Check_Type(this_feature_path, T_STRING);
- if (!is_rbext_path(this_feature_path)) {
- /* as this_feature_index is a fake VALUE, `push` (which
- * doesn't wb_unprotect like as rb_ary_splice) first,
- * then rotate partially. */
- pos = i;
- break;
- }
- }
- }
- rb_ary_push(this_feature_index, offset);
- if (pos >= 0) {
- VALUE *ptr = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(this_feature_index);
- long len = RARRAY_LEN(this_feature_index);
- MEMMOVE(ptr + pos, ptr + pos + 1, VALUE, len - pos - 1);
- ptr[pos] = offset;
- }
- }
+ features_index = get_loaded_features_index_raw(vm);
+
+ struct features_index_add_single_args args = {
+ .vm = vm,
+ .offset = offset,
+ .rb = rb,
+ };
+
+ st_update(features_index, short_feature_key, features_index_add_single_callback, (st_data_t)&args);
}
/* Add to the loaded-features index all the required entries for
@@ -265,7 +308,7 @@ features_index_add_single(const char* str, size_t len, VALUE offset, bool rb)
relies on for its fast lookup.
*/
static void
-features_index_add(VALUE feature, VALUE offset)
+features_index_add(rb_vm_t *vm, VALUE feature, VALUE offset)
{
const char *feature_str, *feature_end, *ext, *p;
bool rb = false;
@@ -274,10 +317,10 @@ features_index_add(VALUE feature, VALUE offset)
feature_end = feature_str + RSTRING_LEN(feature);
for (ext = feature_end; ext > feature_str; ext--)
- if (*ext == '.' || *ext == '/')
- break;
+ if (*ext == '.' || *ext == '/')
+ break;
if (*ext != '.')
- ext = NULL;
+ ext = NULL;
else
rb = IS_RBEXT(ext);
/* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
@@ -285,20 +328,20 @@ features_index_add(VALUE feature, VALUE offset)
p = ext ? ext : feature_end;
while (1) {
- p--;
- while (p >= feature_str && *p != '/')
- p--;
- if (p < feature_str)
- break;
- /* Now *p == '/'. We reach this point for every '/' in `feature`. */
- features_index_add_single(p + 1, feature_end - p - 1, offset, false);
- if (ext) {
- features_index_add_single(p + 1, ext - p - 1, offset, rb);
- }
+ p--;
+ while (p >= feature_str && *p != '/')
+ p--;
+ if (p < feature_str)
+ break;
+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */
+ features_index_add_single(vm, p + 1, feature_end - p - 1, offset, false);
+ if (ext) {
+ features_index_add_single(vm, p + 1, ext - p - 1, offset, rb);
+ }
}
- features_index_add_single(feature_str, feature_end - feature_str, offset, false);
+ features_index_add_single(vm, feature_str, feature_end - feature_str, offset, false);
if (ext) {
- features_index_add_single(feature_str, ext - feature_str, offset, rb);
+ features_index_add_single(vm, feature_str, ext - feature_str, offset, rb);
}
}
@@ -307,34 +350,52 @@ loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
{
VALUE obj = (VALUE)val;
if (!SPECIAL_CONST_P(obj)) {
- rb_ary_free(obj);
- ruby_sized_xfree((void *)obj, sizeof(struct RArray));
+ rb_darray_free((void *)obj);
}
return ST_DELETE;
}
static st_table *
-get_loaded_features_index(void)
+get_loaded_features_index(rb_vm_t *vm)
{
VALUE features;
int i;
- rb_vm_t *vm = GET_VM();
if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) {
- /* The sharing was broken; something (other than us in rb_provide_feature())
- modified loaded_features. Rebuild the index. */
- st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
- features = vm->loaded_features;
- for (i = 0; i < RARRAY_LEN(features); i++) {
- VALUE entry, as_str;
- as_str = entry = rb_ary_entry(features, i);
- StringValue(as_str);
- as_str = rb_fstring(rb_str_freeze(as_str));
- if (as_str != entry)
- rb_ary_store(features, i, as_str);
- features_index_add(as_str, INT2FIX(i));
- }
- reset_loaded_features_snapshot();
+ /* The sharing was broken; something (other than us in rb_provide_feature())
+ modified loaded_features. Rebuild the index. */
+ st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
+
+ VALUE realpaths = vm->loaded_features_realpaths;
+ VALUE realpath_map = vm->loaded_features_realpath_map;
+ VALUE previous_realpath_map = rb_hash_dup(realpath_map);
+ rb_hash_clear(realpaths);
+ rb_hash_clear(realpath_map);
+ features = vm->loaded_features;
+ for (i = 0; i < RARRAY_LEN(features); i++) {
+ VALUE entry, as_str;
+ as_str = entry = rb_ary_entry(features, i);
+ StringValue(as_str);
+ as_str = rb_fstring(rb_str_freeze(as_str));
+ if (as_str != entry)
+ rb_ary_store(features, i, as_str);
+ features_index_add(vm, as_str, INT2FIX(i));
+ }
+ reset_loaded_features_snapshot(vm);
+
+ features = rb_ary_dup(vm->loaded_features_snapshot);
+ long j = RARRAY_LEN(features);
+ for (i = 0; i < j; i++) {
+ VALUE as_str = rb_ary_entry(features, i);
+ VALUE realpath = rb_hash_aref(previous_realpath_map, as_str);
+ if (NIL_P(realpath)) {
+ realpath = rb_check_realpath(Qnil, as_str, NULL);
+ if (NIL_P(realpath)) realpath = as_str;
+ realpath = rb_fstring(realpath);
+ }
+ rb_hash_aset(realpaths, realpath, Qtrue);
+ rb_hash_aset(realpath_map, as_str, realpath);
+ }
}
return vm->loaded_features_index;
}
@@ -352,7 +413,7 @@ get_loaded_features_index(void)
*/
static VALUE
loaded_feature_path(const char *name, long vlen, const char *feature, long len,
- int type, VALUE load_path)
+ int type, VALUE load_path)
{
long i;
long plen;
@@ -360,36 +421,36 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len,
if (vlen < len+1) return 0;
if (strchr(feature, '.') && !strncmp(name+(vlen-len), feature, len)) {
- plen = vlen - len;
+ plen = vlen - len;
}
else {
- for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e);
- if (*e != '.' ||
- e-name < len ||
- strncmp(e-len, feature, len))
- return 0;
- plen = e - name - len;
+ for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e);
+ if (*e != '.' ||
+ e-name < len ||
+ strncmp(e-len, feature, len))
+ return 0;
+ plen = e - name - len;
}
if (plen > 0 && name[plen-1] != '/') {
- return 0;
+ return 0;
}
if (type == 's' ? !IS_DLEXT(&name[plen+len]) :
- type == 'r' ? !IS_RBEXT(&name[plen+len]) :
- 0) {
- return 0;
+ type == 'r' ? !IS_RBEXT(&name[plen+len]) :
+ 0) {
+ return 0;
}
/* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
(possibly empty) and prefix is some string of length plen. */
if (plen > 0) --plen; /* exclude '.' */
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
- VALUE p = RARRAY_AREF(load_path, i);
- const char *s = StringValuePtr(p);
- long n = RSTRING_LEN(p);
+ VALUE p = RARRAY_AREF(load_path, i);
+ const char *s = StringValuePtr(p);
+ long n = RSTRING_LEN(p);
- if (n != plen) continue;
- if (n && strncmp(name, s, n)) continue;
- return p;
+ if (n != plen) continue;
+ if (n && strncmp(name, s, n)) continue;
+ return p;
}
return 0;
}
@@ -408,14 +469,14 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
const char *s = (const char *)v;
struct loaded_feature_searching *fp = (struct loaded_feature_searching *)f;
VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len,
- fp->type, fp->load_path);
+ fp->type, fp->load_path);
if (!p) return ST_CONTINUE;
fp->result = s;
return ST_STOP;
}
static int
-rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
+rb_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn)
{
VALUE features, this_feature_index = Qnil, v, p, load_path = 0;
const char *f, *e;
@@ -427,17 +488,17 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
if (fn) *fn = 0;
if (ext) {
- elen = strlen(ext);
- len = strlen(feature) - elen;
- type = rb ? 'r' : 's';
+ elen = strlen(ext);
+ len = strlen(feature) - elen;
+ type = rb ? 'r' : 's';
}
else {
- len = strlen(feature);
- elen = 0;
- type = 0;
+ len = strlen(feature);
+ elen = 0;
+ type = 0;
}
- features = get_loaded_features();
- features_index = get_loaded_features_index();
+ features = get_loaded_features(vm);
+ features_index = get_loaded_features_index(vm);
key = feature_key(feature, strlen(feature));
/* We search `features` for an entry such that either
@@ -467,91 +528,90 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
as any distractors, so we may ignore all other entries in `features`.
*/
if (st_lookup(features_index, key, &data) && !NIL_P(this_feature_index = (VALUE)data)) {
- for (i = 0; ; i++) {
- VALUE entry;
- long index;
- if (RB_TYPE_P(this_feature_index, T_ARRAY)) {
- if (i >= RARRAY_LEN(this_feature_index)) break;
- entry = RARRAY_AREF(this_feature_index, i);
- }
- else {
- if (i > 0) break;
- entry = this_feature_index;
- }
- index = FIX2LONG(entry);
-
- v = RARRAY_AREF(features, index);
- f = StringValuePtr(v);
- if ((n = RSTRING_LEN(v)) < len) continue;
- if (strncmp(f, feature, len) != 0) {
- if (expanded) continue;
- if (!load_path) load_path = rb_get_expanded_load_path();
- if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
- continue;
- expanded = 1;
- f += RSTRING_LEN(p) + 1;
- }
- if (!*(e = f + len)) {
- if (ext) continue;
- return 'u';
- }
- if (*e != '.') continue;
- if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
- return 's';
- }
- if ((rb || !ext) && (IS_RBEXT(e))) {
- return 'r';
- }
- }
+ for (size_t i = 0; ; i++) {
+ long index;
+ if (FIXNUM_P(this_feature_index)) {
+ if (i > 0) break;
+ index = FIX2LONG(this_feature_index);
+ }
+ else {
+ feature_indexes_t feature_indexes = (feature_indexes_t)this_feature_index;
+ if (i >= rb_darray_size(feature_indexes)) break;
+ index = rb_darray_get(feature_indexes, i);
+ }
+
+ v = RARRAY_AREF(features, index);
+ f = StringValuePtr(v);
+ if ((n = RSTRING_LEN(v)) < len) continue;
+ if (strncmp(f, feature, len) != 0) {
+ if (expanded) continue;
+ if (!load_path) load_path = get_expanded_load_path(vm);
+ if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
+ continue;
+ expanded = 1;
+ f += RSTRING_LEN(p) + 1;
+ }
+ if (!*(e = f + len)) {
+ if (ext) continue;
+ return 'u';
+ }
+ if (*e != '.') continue;
+ if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
+ return 's';
+ }
+ if ((rb || !ext) && (IS_RBEXT(e))) {
+ return 'r';
+ }
+ }
}
- loading_tbl = get_loading_table();
+ loading_tbl = get_loading_table(vm);
f = 0;
- if (!expanded) {
- struct loaded_feature_searching fs;
- fs.name = feature;
- fs.len = len;
- fs.type = type;
- fs.load_path = load_path ? load_path : rb_get_expanded_load_path();
- fs.result = 0;
- st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
- if ((f = fs.result) != 0) {
- if (fn) *fn = f;
- goto loading;
- }
+ if (!expanded && !rb_is_absolute_path(feature)) {
+ struct loaded_feature_searching fs;
+ fs.name = feature;
+ fs.len = len;
+ fs.type = type;
+ fs.load_path = load_path ? load_path : get_expanded_load_path(vm);
+ fs.result = 0;
+ st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
+ if ((f = fs.result) != 0) {
+ if (fn) *fn = f;
+ goto loading;
+ }
}
if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
- if (fn) *fn = (const char*)data;
+ if (fn) *fn = (const char*)data;
goto loading;
}
else {
- VALUE bufstr;
- char *buf;
- static const char so_ext[][4] = {
- ".so", ".o",
- };
-
- if (ext && *ext) return 0;
- bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
- buf = RSTRING_PTR(bufstr);
- MEMCPY(buf, feature, char, len);
- for (i = 0; (e = loadable_ext[i]) != 0; i++) {
- strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
- if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
- rb_str_resize(bufstr, 0);
- if (fn) *fn = (const char*)data;
- return i ? 's' : 'r';
- }
- }
- for (i = 0; i < numberof(so_ext); i++) {
- strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
- if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
- rb_str_resize(bufstr, 0);
- if (fn) *fn = (const char*)data;
- return 's';
- }
- }
- rb_str_resize(bufstr, 0);
+ VALUE bufstr;
+ char *buf;
+ static const char so_ext[][4] = {
+ ".so", ".o",
+ };
+
+ if (ext && *ext) return 0;
+ bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
+ buf = RSTRING_PTR(bufstr);
+ MEMCPY(buf, feature, char, len);
+ for (i = 0; (e = loadable_ext[i]) != 0; i++) {
+ strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
+ if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
+ rb_str_resize(bufstr, 0);
+ if (fn) *fn = (const char*)data;
+ return i ? 's' : 'r';
+ }
+ }
+ for (i = 0; i < numberof(so_ext); i++) {
+ strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
+ if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
+ rb_str_resize(bufstr, 0);
+ if (fn) *fn = (const char*)data;
+ return 's';
+ }
+ }
+ rb_str_resize(bufstr, 0);
}
return 0;
@@ -566,54 +626,65 @@ rb_provided(const char *feature)
return rb_feature_provided(feature, 0);
}
-int
-rb_feature_provided(const char *feature, const char **loading)
+static int
+feature_provided(rb_vm_t *vm, const char *feature, const char **loading)
{
const char *ext = strrchr(feature, '.');
VALUE fullpath = 0;
if (*feature == '.' &&
- (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
- fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil);
- feature = RSTRING_PTR(fullpath);
+ (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil);
+ feature = RSTRING_PTR(fullpath);
}
if (ext && !strchr(ext, '/')) {
- if (IS_RBEXT(ext)) {
- if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE;
- return FALSE;
- }
- else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
- if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE;
- return FALSE;
- }
+ if (IS_RBEXT(ext)) {
+ if (rb_feature_p(vm, feature, ext, TRUE, FALSE, loading)) return TRUE;
+ return FALSE;
+ }
+ else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
+ if (rb_feature_p(vm, feature, ext, FALSE, FALSE, loading)) return TRUE;
+ return FALSE;
+ }
}
- if (rb_feature_p(feature, 0, TRUE, FALSE, loading))
- return TRUE;
+ if (rb_feature_p(vm, feature, 0, TRUE, FALSE, loading))
+ return TRUE;
RB_GC_GUARD(fullpath);
return FALSE;
}
+int
+rb_feature_provided(const char *feature, const char **loading)
+{
+ return feature_provided(GET_VM(), feature, loading);
+}
+
static void
-rb_provide_feature(VALUE feature)
+rb_provide_feature(rb_vm_t *vm, VALUE feature)
{
VALUE features;
- features = get_loaded_features();
+ features = get_loaded_features(vm);
if (OBJ_FROZEN(features)) {
- rb_raise(rb_eRuntimeError,
- "$LOADED_FEATURES is frozen; cannot append feature");
+ rb_raise(rb_eRuntimeError,
+ "$LOADED_FEATURES is frozen; cannot append feature");
}
rb_str_freeze(feature);
+ get_loaded_features_index(vm);
+ // If loaded_features and loaded_features_snapshot share the same backing
+ // array, pushing into it would cause the whole array to be copied.
+ // To avoid this we first clear loaded_features_snapshot.
+ rb_ary_clear(vm->loaded_features_snapshot);
rb_ary_push(features, rb_fstring(feature));
- features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1));
- reset_loaded_features_snapshot();
+ features_index_add(vm, feature, INT2FIX(RARRAY_LEN(features)-1));
+ reset_loaded_features_snapshot(vm);
}
void
rb_provide(const char *feature)
{
- rb_provide_feature(rb_fstring_cstr(feature));
+ rb_provide_feature(GET_VM(), rb_fstring_cstr(feature));
}
NORETURN(static void load_failed(VALUE));
@@ -624,6 +695,8 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
if (!iseq) {
+ rb_execution_context_t *ec = GET_EC();
+ VALUE v = rb_vm_push_frame_fname(ec, fname);
rb_ast_t *ast;
VALUE parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
@@ -631,13 +704,15 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"),
fname, rb_realpath_internal(Qnil, fname, 1), NULL);
rb_ast_dispose(ast);
+ rb_vm_pop_frame(ec);
+ RB_GC_GUARD(v);
}
rb_exec_event_hook_script_compiled(ec, iseq, Qnil);
rb_iseq_eval(iseq);
}
static inline enum ruby_tag_type
-load_wrapping(rb_execution_context_t *ec, VALUE fname)
+load_wrapping(rb_execution_context_t *ec, VALUE fname, VALUE load_wrapper)
{
enum ruby_tag_type state;
rb_thread_t *th = rb_ec_thread_ptr(ec);
@@ -649,9 +724,9 @@ load_wrapping(rb_execution_context_t *ec, VALUE fname)
ec->errinfo = Qnil; /* ensure */
- /* load in anonymous module as toplevel */
+ /* load in module as toplevel */
th->top_self = rb_obj_clone(rb_vm_top_self());
- th->top_wrapper = rb_module_new();
+ th->top_wrapper = load_wrapper;
rb_extend_object(th->top_self, th->top_wrapper);
EC_PUSH_TAG(ec);
@@ -683,12 +758,15 @@ raise_load_if_failed(rb_execution_context_t *ec, enum ruby_tag_type state)
}
static void
-rb_load_internal(VALUE fname, int wrap)
+rb_load_internal(VALUE fname, VALUE wrap)
{
rb_execution_context_t *ec = GET_EC();
enum ruby_tag_type state = TAG_NONE;
- if (wrap) {
- state = load_wrapping(ec, fname);
+ if (RTEST(wrap)) {
+ if (!RB_TYPE_P(wrap, T_MODULE)) {
+ wrap = rb_module_new();
+ }
+ state = load_wrapping(ec, fname, wrap);
}
else {
load_iseq_eval(ec, fname);
@@ -701,7 +779,7 @@ rb_load(VALUE fname, int wrap)
{
VALUE tmp = rb_find_file(FilePathValue(fname));
if (!tmp) load_failed(fname);
- rb_load_internal(tmp, wrap);
+ rb_load_internal(tmp, RBOOL(wrap));
}
void
@@ -743,9 +821,10 @@ rb_load_protect(VALUE fname, int wrap, int *pstate)
*
* 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.
+ * program's global namespace. If the optional _wrap_ parameter is a
+ * module, the loaded script will be executed under the given module.
+ * In no circumstance will any local variables in the loaded file be
+ * propagated to the loading environment.
*/
static VALUE
@@ -761,11 +840,11 @@ rb_f_load(int argc, VALUE *argv, VALUE _)
path = rb_find_file(fname);
if (!path) {
- if (!rb_file_load_ok(RSTRING_PTR(fname)))
- load_failed(orig_fname);
- path = fname;
+ if (!rb_file_load_ok(RSTRING_PTR(fname)))
+ load_failed(orig_fname);
+ path = fname;
}
- rb_load_internal(path, RTEST(wrap));
+ rb_load_internal(path, wrap);
RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
@@ -773,35 +852,28 @@ rb_f_load(int argc, VALUE *argv, VALUE _)
}
static char *
-load_lock(const char *ftptr)
+load_lock(rb_vm_t *vm, const char *ftptr, bool warn)
{
st_data_t data;
- st_table *loading_tbl = get_loading_table();
+ st_table *loading_tbl = get_loading_table(vm);
if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
- /* partial state */
- ftptr = ruby_strdup(ftptr);
- data = (st_data_t)rb_thread_shield_new();
- st_insert(loading_tbl, (st_data_t)ftptr, data);
- return (char *)ftptr;
- }
- else if (imemo_type_p(data, imemo_memo)) {
- struct MEMO *memo = MEMO_CAST(data);
- void (*init)(void) = memo->u3.func;
- data = (st_data_t)rb_thread_shield_new();
- st_insert(loading_tbl, (st_data_t)ftptr, data);
- (*init)();
- return (char *)"";
+ /* partial state */
+ ftptr = ruby_strdup(ftptr);
+ data = (st_data_t)rb_thread_shield_new();
+ st_insert(loading_tbl, (st_data_t)ftptr, data);
+ return (char *)ftptr;
}
- if (RTEST(ruby_verbose)) {
- VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr);
- rb_backtrace_each(rb_str_append, warning);
- rb_warning("%"PRIsVALUE, warning);
+
+ if (warn && rb_thread_shield_owned((VALUE)data)) {
+ VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr);
+ rb_backtrace_each(rb_str_append, warning);
+ rb_warning("%"PRIsVALUE, warning);
}
switch (rb_thread_shield_wait((VALUE)data)) {
case Qfalse:
case Qnil:
- return 0;
+ return 0;
}
return (char *)ftptr;
}
@@ -812,29 +884,30 @@ release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int exis
VALUE thread_shield = (VALUE)*value;
if (!existing) return ST_STOP;
if (done) {
- rb_thread_shield_destroy(thread_shield);
- /* Delete the entry even if there are waiting threads, because they
- * won't load the file and won't delete the entry. */
+ rb_thread_shield_destroy(thread_shield);
+ /* Delete the entry even if there are waiting threads, because they
+ * won't load the file and won't delete the entry. */
}
else if (rb_thread_shield_release(thread_shield)) {
- /* still in-use */
- return ST_CONTINUE;
+ /* still in-use */
+ return ST_CONTINUE;
}
xfree((char *)*key);
return ST_DELETE;
}
static void
-load_unlock(const char *ftptr, int done)
+load_unlock(rb_vm_t *vm, const char *ftptr, int done)
{
if (ftptr) {
- st_data_t key = (st_data_t)ftptr;
- st_table *loading_tbl = get_loading_table();
+ st_data_t key = (st_data_t)ftptr;
+ st_table *loading_tbl = get_loading_table(vm);
- st_update(loading_tbl, key, release_thread_shield, done);
+ st_update(loading_tbl, key, release_thread_shield, done);
}
}
+static VALUE rb_require_string_internal(VALUE fname);
/*
* call-seq:
@@ -884,25 +957,26 @@ rb_f_require(VALUE obj, VALUE fname)
* call-seq:
* require_relative(string) -> true or false
*
- * Ruby tries to load the library named _string_ relative to the requiring
- * file's path. If the file's path cannot be determined a LoadError is raised.
- * If a file is loaded +true+ is returned and false otherwise.
+ * Ruby tries to load the library named _string_ relative to the directory
+ * containing the requiring file. If the file does not exist a LoadError is
+ * raised. Returns +true+ if the file was loaded and +false+ if the file was
+ * already loaded before.
*/
VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
- rb_loaderror("cannot infer basepath");
+ rb_loaderror("cannot infer basepath");
}
base = rb_file_dirname(base);
- return rb_require_string(rb_file_absolute_path(fname, base));
+ return rb_require_string_internal(rb_file_absolute_path(fname, base));
}
-typedef int (*feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn);
+typedef int (*feature_func)(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn);
static int
-search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
+search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
{
VALUE tmp;
char *ext, *ftptr;
@@ -912,84 +986,93 @@ search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
*path = 0;
ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
if (ext && !strchr(ext, '/')) {
- if (IS_RBEXT(ext)) {
- if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) {
- if (loading) *path = rb_filesystem_str_new_cstr(loading);
- return 'r';
- }
+ if (IS_RBEXT(ext)) {
+ if (rb_feature_p(vm, ftptr, ext, TRUE, FALSE, &loading)) {
+ if (loading) *path = rb_filesystem_str_new_cstr(loading);
+ return 'r';
+ }
if ((tmp = rb_find_file(fname)) != 0) {
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
- *path = tmp;
- return 'r';
- }
- return 0;
- }
- else if (IS_SOEXT(ext)) {
- if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
- if (loading) *path = rb_filesystem_str_new_cstr(loading);
- return 's';
- }
- tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
-#ifdef DLEXT2
- OBJ_FREEZE(tmp);
- if (rb_find_file_ext(&tmp, loadable_ext + 1)) {
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
- *path = tmp;
- return 's';
- }
-#else
- rb_str_cat2(tmp, DLEXT);
- OBJ_FREEZE(tmp);
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
+ if (!rb_feature_p(vm, ftptr, ext, TRUE, TRUE, &loading) || loading)
+ *path = tmp;
+ return 'r';
+ }
+ return 0;
+ }
+ else if (IS_SOEXT(ext)) {
+ if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
+ if (loading) *path = rb_filesystem_str_new_cstr(loading);
+ return 's';
+ }
+ tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
+ rb_str_cat2(tmp, DLEXT);
+ OBJ_FREEZE(tmp);
if ((tmp = rb_find_file(tmp)) != 0) {
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
- *path = tmp;
- return 's';
- }
-#endif
- }
- else if (IS_DLEXT(ext)) {
- if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
- if (loading) *path = rb_filesystem_str_new_cstr(loading);
- return 's';
- }
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
+ if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
+ *path = tmp;
+ return 's';
+ }
+ }
+ else if (IS_DLEXT(ext)) {
+ if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
+ if (loading) *path = rb_filesystem_str_new_cstr(loading);
+ return 's';
+ }
if ((tmp = rb_find_file(fname)) != 0) {
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
- *path = tmp;
- return 's';
- }
- }
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
+ if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
+ *path = tmp;
+ return 's';
+ }
+ }
}
- else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
- if (loading) *path = rb_filesystem_str_new_cstr(loading);
- return 'r';
+ else if ((ft = rb_feature_p(vm, ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
+ if (loading) *path = rb_filesystem_str_new_cstr(loading);
+ return 'r';
}
tmp = fname;
type = rb_find_file_ext(&tmp, ft == 's' ? ruby_ext : loadable_ext);
+
+ // Check if it's a statically linked extension when
+ // not already a feature and not found as a dynamic library.
+ if (!ft && type != 1 && vm->static_ext_inits) {
+ VALUE lookup_name = tmp;
+ // Append ".so" if not already present so for example "etc" can find "etc.so".
+ // We always register statically linked extensions with a ".so" extension.
+ // See encinit.c and extinit.c (generated at build-time).
+ if (!ext) {
+ lookup_name = rb_str_dup(lookup_name);
+ rb_str_cat_cstr(lookup_name, ".so");
+ }
+ ftptr = RSTRING_PTR(lookup_name);
+ if (st_lookup(vm->static_ext_inits, (st_data_t)ftptr, NULL)) {
+ *path = rb_filesystem_str_new_cstr(ftptr);
+ return 's';
+ }
+ }
+
switch (type) {
case 0:
- if (ft)
- goto statically_linked;
- ftptr = RSTRING_PTR(tmp);
- return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
+ if (ft)
+ goto feature_present;
+ ftptr = RSTRING_PTR(tmp);
+ return rb_feature_p(vm, ftptr, 0, FALSE, TRUE, 0);
default:
- if (ft) {
- goto statically_linked;
- }
+ if (ft) {
+ goto feature_present;
+ }
/* fall through */
case 1:
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
- break;
- *path = tmp;
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
+ if (rb_feature_p(vm, ftptr, ext, !--type, TRUE, &loading) && !loading)
+ break;
+ *path = tmp;
}
return type ? 's' : 'r';
- statically_linked:
+ feature_present:
if (loading) *path = rb_filesystem_str_new_cstr(loading);
return ft;
}
@@ -1007,8 +1090,21 @@ load_ext(VALUE path)
return (VALUE)dln_load(RSTRING_PTR(path));
}
+static bool
+run_static_ext_init(rb_vm_t *vm, const char *feature)
+{
+ st_data_t key = (st_data_t)feature;
+ st_data_t init_func;
+
+ if (vm->static_ext_inits && st_delete(vm->static_ext_inits, &key, &init_func)) {
+ ((void (*)(void))init_func)();
+ return true;
+ }
+ return false;
+}
+
static int
-no_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
+no_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn)
{
return 0;
}
@@ -1023,7 +1119,7 @@ rb_resolve_feature_path(VALUE klass, VALUE fname)
fname = rb_get_path(fname);
path = rb_str_encode_ospath(fname);
- found = search_required(path, &path, no_feature_p);
+ found = search_required(GET_VM(), path, &path, no_feature_p);
switch (found) {
case 'r':
@@ -1066,7 +1162,7 @@ rb_ext_ractor_safe(bool flag)
* >1: exception
*/
static int
-require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
+require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool warn)
{
volatile int result = -1;
rb_thread_t *th = rb_ec_thread_ptr(ec);
@@ -1079,10 +1175,12 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
char *volatile ftptr = 0;
VALUE path;
volatile VALUE saved_path;
+ volatile VALUE realpath = 0;
+ VALUE realpaths = get_loaded_features_realpaths(th->vm);
+ VALUE realpath_map = get_loaded_features_realpath_map(th->vm);
volatile bool reset_ext_config = false;
struct rb_ext_config prev_ext_config;
- fname = rb_get_path(fname);
path = rb_str_encode_ospath(fname);
RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname));
saved_path = path;
@@ -1091,38 +1189,45 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
ec->errinfo = Qnil; /* ensure */
th->top_wrapper = 0;
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- long handle;
- int found;
+ long handle;
+ int found;
- RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
- found = search_required(path, &saved_path, rb_feature_p);
- RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname));
+ RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
+ found = search_required(th->vm, path, &saved_path, rb_feature_p);
+ RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname));
path = saved_path;
- if (found) {
- if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
- result = 0;
- }
- else if (!*ftptr) {
- result = TAG_RETURN;
- }
- else {
- switch (found) {
- case 'r':
+ if (found) {
+ if (!path || !(ftptr = load_lock(th->vm, RSTRING_PTR(path), warn))) {
+ result = 0;
+ }
+ else if (!*ftptr) {
+ result = TAG_RETURN;
+ }
+ else if (found == 's' && run_static_ext_init(th->vm, RSTRING_PTR(path))) {
+ result = TAG_RETURN;
+ }
+ else if (RTEST(rb_hash_aref(realpaths,
+ realpath = rb_realpath_internal(Qnil, path, 1)))) {
+ result = 0;
+ }
+ else {
+ switch (found) {
+ case 'r':
load_iseq_eval(ec, path);
- break;
+ break;
- case 's':
+ 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));
- break;
- }
+ 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));
+ break;
+ }
result = TAG_RETURN;
- }
- }
+ }
+ }
}
EC_POP_TAG();
@@ -1132,10 +1237,10 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
if (reset_ext_config) ext_config_pop(th2, &prev_ext_config);
path = saved_path;
- if (ftptr) load_unlock(RSTRING_PTR(path), !state);
+ if (ftptr) load_unlock(th2->vm, RSTRING_PTR(path), !state);
if (state) {
- if (state == TAG_FATAL) {
+ if (state == TAG_FATAL || state == TAG_THROW) {
EC_JUMP_TAG(ec, state);
}
else if (exception) {
@@ -1148,16 +1253,24 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
else if (state == TAG_RETURN) {
return TAG_RAISE;
}
- RB_GC_GUARD(fname);
- /* never TAG_RETURN */
- return state;
+ RB_GC_GUARD(fname);
+ /* never TAG_RETURN */
+ return state;
}
if (!NIL_P(ec->errinfo)) {
if (!exception) return TAG_RAISE;
rb_exc_raise(ec->errinfo);
}
- if (result == TAG_RETURN) rb_provide_feature(path);
+ if (result == TAG_RETURN) {
+ rb_provide_feature(th2->vm, path);
+ VALUE real = realpath;
+ if (real) {
+ real = rb_fstring(real);
+ rb_hash_aset(realpaths, real, Qtrue);
+ rb_hash_aset(realpath_map, path, real);
+ }
+ }
ec->errinfo = saved.errinfo;
RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname));
@@ -1166,10 +1279,17 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
}
int
+rb_require_internal_silent(VALUE fname)
+{
+ rb_execution_context_t *ec = GET_EC();
+ return require_internal(ec, fname, 1, false);
+}
+
+int
rb_require_internal(VALUE fname)
{
rb_execution_context_t *ec = GET_EC();
- return require_internal(ec, fname, 1);
+ return require_internal(ec, fname, 1, RTEST(ruby_verbose));
}
int
@@ -1178,7 +1298,7 @@ ruby_require_internal(const char *fname, unsigned int len)
struct RString fake;
VALUE str = rb_setup_fake_str(&fake, fname, len, 0);
rb_execution_context_t *ec = GET_EC();
- int result = require_internal(ec, str, 0);
+ int result = require_internal(ec, str, 0, RTEST(ruby_verbose));
rb_set_errinfo(Qnil);
return result == TAG_RETURN ? 1 : result ? -1 : 0;
}
@@ -1186,14 +1306,20 @@ ruby_require_internal(const char *fname, unsigned int len)
VALUE
rb_require_string(VALUE fname)
{
+ return rb_require_string_internal(FilePathValue(fname));
+}
+
+static VALUE
+rb_require_string_internal(VALUE fname)
+{
rb_execution_context_t *ec = GET_EC();
- int result = require_internal(ec, fname, 1);
+ int result = require_internal(ec, fname, 1, RTEST(ruby_verbose));
if (result > TAG_RETURN) {
EC_JUMP_TAG(ec, result);
}
if (result < 0) {
- load_failed(fname);
+ load_failed(fname);
}
return RBOOL(result);
@@ -1202,7 +1328,9 @@ rb_require_string(VALUE fname)
VALUE
rb_require(const char *fname)
{
- return rb_require_string(rb_str_new_cstr(fname));
+ struct RString fake;
+ VALUE str = rb_setup_fake_str(&fake, fname, strlen(fname), 0);
+ return rb_require_string_internal(str);
}
static int
@@ -1210,38 +1338,51 @@ register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing
{
const char *name = (char *)*key;
if (existing) {
- /* already registered */
- rb_warn("%s is already registered", name);
+ /* already registered */
+ rb_warn("%s is already registered", name);
}
else {
- *value = (st_data_t)MEMO_NEW(0, 0, init);
- *key = (st_data_t)ruby_strdup(name);
+ *value = (st_data_t)init;
}
return ST_CONTINUE;
}
-RUBY_FUNC_EXPORTED void
+// Private API for statically linked extensions.
+// Used with the ext/Setup file, the --with-setup and
+// --with-static-linked-ext configuration option, etc.
+void
ruby_init_ext(const char *name, void (*init)(void))
{
- st_table *loading_tbl = get_loading_table();
+ st_table *inits_table;
+ rb_vm_t *vm = GET_VM();
- if (rb_provided(name))
- return;
- st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
+ if (feature_provided(vm, name, 0))
+ return;
+
+ inits_table = vm->static_ext_inits;
+ if (!inits_table) {
+ inits_table = st_init_strtable();
+ vm->static_ext_inits = inits_table;
+ }
+ st_update(inits_table, (st_data_t)name, register_init_ext, (st_data_t)init);
}
/*
* call-seq:
- * mod.autoload(module, filename) -> nil
+ * mod.autoload(const, filename) -> nil
*
* Registers _filename_ to be loaded (using Kernel::require)
- * the first time that _module_ (which may be a String or
+ * the first time that _const_ (which may be a String or
* a symbol) is accessed in the namespace of _mod_.
*
* module A
* end
* A.autoload(:B, "b")
* A::B.doit # autoloads "b"
+ *
+ * If _const_ in _mod_ is defined as autoload, the file name to be
+ * loaded is replaced with _filename_. If _const_ is defined but not
+ * as autoload, does nothing.
*/
static VALUE
@@ -1288,20 +1429,24 @@ rb_mod_autoload_p(int argc, VALUE *argv, VALUE mod)
ID id = rb_check_id(&sym);
if (!id) {
- return Qnil;
+ return Qnil;
}
return rb_autoload_at_p(mod, id, recur);
}
/*
* call-seq:
- * autoload(module, filename) -> nil
+ * autoload(const, filename) -> nil
*
* Registers _filename_ to be loaded (using Kernel::require)
- * the first time that _module_ (which may be a String or
+ * the first time that _const_ (which may be a String or
* a symbol) is accessed.
*
* autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
+ *
+ * If _const_ is defined as autoload, the file name to be loaded is
+ * replaced with _filename_. If _const_ is defined but not as
+ * autoload, does nothing.
*/
static VALUE
@@ -1309,7 +1454,7 @@ rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
{
VALUE klass = rb_class_real(rb_vm_cbase());
if (!klass) {
- rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
+ rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
}
return rb_mod_autoload(klass, sym, file);
}
@@ -1331,7 +1476,7 @@ rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
/* use rb_vm_cbase() as same as rb_f_autoload. */
VALUE klass = rb_vm_cbase();
if (NIL_P(klass)) {
- return Qnil;
+ return Qnil;
}
return rb_mod_autoload_p(argc, argv, klass);
}
@@ -1347,16 +1492,20 @@ Init_load(void)
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);
+ vm->expanded_load_path = rb_ary_hidden_new(0);
+ vm->load_path_snapshot = rb_ary_hidden_new(0);
vm->load_path_check_cache = 0;
rb_define_singleton_method(vm->load_path, "resolve_feature_path", rb_resolve_feature_path, 1);
rb_define_virtual_variable("$\"", get_LOADED_FEATURES, 0);
rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES, 0);
vm->loaded_features = rb_ary_new();
- vm->loaded_features_snapshot = rb_ary_tmp_new(0);
+ vm->loaded_features_snapshot = rb_ary_hidden_new(0);
vm->loaded_features_index = st_init_numtable();
+ vm->loaded_features_realpaths = rb_hash_new();
+ rb_obj_hide(vm->loaded_features_realpaths);
+ vm->loaded_features_realpath_map = rb_hash_new();
+ rb_obj_hide(vm->loaded_features_realpath_map);
rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1);
@@ -1366,6 +1515,6 @@ Init_load(void)
rb_define_global_function("autoload", rb_f_autoload, 2);
rb_define_global_function("autoload?", rb_f_autoload_p, -1);
- ruby_dln_librefs = rb_ary_tmp_new(0);
+ ruby_dln_librefs = rb_ary_hidden_new(0);
rb_gc_register_mark_object(ruby_dln_librefs);
}
diff --git a/localeinit.c b/localeinit.c
index bbcbac832e..cea2e309f5 100644
--- a/localeinit.c
+++ b/localeinit.c
@@ -46,11 +46,11 @@ locale_charmap(VALUE (*conv)(const char *))
codeset = nl_langinfo_codeset();
# endif
if (!codeset) {
- UINT codepage = ruby_w32_codepage[0];
- if (!codepage) codepage = GetConsoleCP();
- if (!codepage) codepage = GetACP();
- CP_FORMAT(cp, codepage);
- codeset = cp;
+ UINT codepage = ruby_w32_codepage[0];
+ if (!codepage) codepage = GetConsoleCP();
+ if (!codepage) codepage = GetACP();
+ CP_FORMAT(cp, codepage);
+ codeset = cp;
}
#elif defined HAVE_LANGINFO_H
codeset = nl_langinfo(CODESET);
@@ -128,7 +128,7 @@ Init_enc_set_filesystem_encoding(void)
/* for debugging */
CP_FORMAT(cp, codepage);
idx = rb_enc_find_index(cp);
- if (idx < 0) idx = ENCINDEX_ASCII;
+ if (idx < 0) idx = ENCINDEX_ASCII_8BIT;
#elif defined __CYGWIN__
idx = ENCINDEX_UTF_8;
#else
diff --git a/main.c b/main.c
index d81cfce879..c87355e46e 100644
--- a/main.c
+++ b/main.c
@@ -23,13 +23,32 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
-#if RUBY_DEVEL && !defined RUBY_DEBUG_ENV
+#if defined RUBY_DEVEL && !defined RUBY_DEBUG_ENV
# define RUBY_DEBUG_ENV 1
#endif
#if defined RUBY_DEBUG_ENV && !RUBY_DEBUG_ENV
# undef RUBY_DEBUG_ENV
#endif
+static int
+rb_main(int argc, char **argv)
+{
+ RUBY_INIT_STACK;
+ ruby_init();
+ return ruby_run_node(ruby_options(argc, argv));
+}
+
+#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
+int rb_wasm_rt_start(int (main)(int argc, char **argv), int argc, char **argv);
+#define rb_main(argc, argv) rb_wasm_rt_start(rb_main, argc, argv)
+#endif
+
+#ifdef _WIN32
+#define main(argc, argv) w32_main(argc, argv)
+static int main(int argc, char **argv);
+int wmain(void) {return main(0, NULL);}
+#endif
+
int
main(int argc, char **argv)
{
@@ -41,9 +60,5 @@ main(int argc, char **argv)
#endif
ruby_sysinit(&argc, &argv);
- {
- RUBY_INIT_STACK;
- ruby_init();
- return ruby_run_node(ruby_options(argc, argv));
- }
+ return rb_main(argc, argv);
}
diff --git a/man/irb.1 b/man/irb.1
index f0a720fbd3..c589c99c78 100644
--- a/man/irb.1
+++ b/man/irb.1
@@ -18,6 +18,7 @@
.Op Fl - Ns Oo no Oc Ns singleline
.Op Fl - Ns Oo no Oc Ns echo
.Op Fl - Ns Oo no Oc Ns colorize
+.Op Fl - Ns Oo no Oc Ns autocomplete
.Op Fl - Ns Oo no Oc Ns verbose
.Op Fl -prompt Ar mode
.Op Fl -prompt-mode Ar mode
@@ -104,13 +105,27 @@ Uses singleline editor module.
Doesn't use singleline editor module.
.Pp
.Pp
+.It Fl -extra-doc-dir
+Add an extra doc dir for the doc dialog.
+.Pp
+.Pp
.It Fl -echo
-Show result(default).
+Show result (default).
.Pp
.It Fl -noecho
Don't show result.
.Pp
.Pp
+.It Fl -echo-on-assignment
+Show result on assignment.
+.Pp
+.It Fl -noecho-on-assignment
+Don't show result on assignment.
+.Pp
+.It Fl -truncate-echo-on-assignment
+Show truncated result on assignment (default).
+.Pp
+.Pp
.It Fl -colorize
Use colorization.
.Pp
@@ -118,6 +133,13 @@ Use colorization.
Don't use colorization.
.Pp
.Pp
+.It Fl -autocomplete
+Use autocompletion.
+.Pp
+.It Fl -noautocomplete
+Don't use autocompletion.
+.Pp
+.Pp
.It Fl -verbose
Show details.
.Pp
@@ -151,8 +173,19 @@ The default value is 16.
.El
.Pp
.Sh ENVIRONMENT
-.Bl -tag -compact
+.Bl -tag -compact -width "XDG_CONFIG_HOME"
+.It Ev IRB_LANG
+The locale used for
+.Nm .
+.Pp
.It Ev IRBRC
+The path to the personal initialization file.
+.Pp
+.It Ev XDG_CONFIG_HOME
+.Nm
+respects XDG_CONFIG_HOME. If this is set, load
+.Pa $XDG_CONFIG_HOME/irb/irbrc
+as a personal initialization file.
.Pp
.El
.Pp
@@ -164,7 +197,17 @@ depends on same variables as
.Sh FILES
.Bl -tag -compact
.It Pa ~/.irbrc
-Personal irb initialization.
+Personal irb initialization. If
+.Ev IRBRC
+is set, read
+.Pa $IRBRC
+instead. If
+.Ev IRBRC
+is not set and
+.Ev XDG_CONFIG_HOME
+is set,
+.Pa $XDG_CONFIG_HOME/irb/irbrc
+is loaded.
.Pp
.El
.Pp
diff --git a/man/ruby.1 b/man/ruby.1
index 944844b639..86ad73c2ab 100644
--- a/man/ruby.1
+++ b/man/ruby.1
@@ -423,35 +423,37 @@ Dump some information.
.Pp
Prints the specified target.
.Ar target
-can be one of;
+can be one of:
.Bl -hang -offset indent
.It Sy version
-version description same as
-.Fl -version
+Print version description (same as
+.Fl -version).
.It Sy usage
-brief usage message same as
-.Fl h
+Print a brief usage message (same as
+.Fl h).
.It Sy help
-Show long help message same as
-.Fl -help
+Show long help message (same as
+.Fl -help).
.It Sy syntax
-check of syntax same as
+Check syntax (same as
.Fl c
-.Fl -yydebug
-.It Sy yydebug
-compiler debug mode, same as
-.Fl -yydebug
+.Fl -yydebug).
+.Pp
+.El
.Pp
-Only specify this switch if you are going to debug the Ruby interpreter.
+Or one of the following, which are intended for debugging the interpreter:
+.Bl -hang -offset indent -tag -width "parsetree_with_comment"
+.It Sy yydebug
+Enable compiler debug mode (same as
+.Fl -yydebug).
.It Sy parsetree
+Print a textual representation of the Ruby AST for the program.
.It Sy parsetree_with_comment
-AST nodes tree
-.Pp
-Only specify this switch if you are going to debug the Ruby interpreter.
+Print a textual representation of the Ruby AST for the program, but with each node annoted with the associated Ruby source code.
.It Sy insns
-disassembled instructions
-.Pp
-Only specify this switch if you are going to debug the Ruby interpreter.
+Print a list of disassembled bytecode instructions.
+.It Sy insns_without_opt
+Print the list of disassembled bytecode instructions before various optimizations have been applied.
.El
.Pp
.It Fl -verbose
diff --git a/marshal.c b/marshal.c
index ea43c62b94..4ea4255971 100644
--- a/marshal.c
+++ b/marshal.c
@@ -28,14 +28,19 @@
#include "internal/encoding.h"
#include "internal/error.h"
#include "internal/hash.h"
+#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/struct.h"
+#include "internal/symbol.h"
#include "internal/util.h"
#include "internal/vm.h"
#include "ruby/io.h"
#include "ruby/ruby.h"
#include "ruby/st.h"
#include "ruby/util.h"
+#include "builtin.h"
+#include "shape.h"
+#include "ruby/internal/attr/nonstring.h"
#define BITSPERSHORT (2*CHAR_BIT)
#define SHORTMASK ((1<<BITSPERSHORT)-1)
@@ -52,8 +57,8 @@ shortlen(size_t len, BDIGIT *ds)
num = ds[len-1];
while (num) {
- num = SHORTDN(num);
- offset++;
+ num = SHORTDN(num);
+ offset++;
}
return (len - 1)*SIZEOF_BDIGIT/2 + offset;
}
@@ -122,7 +127,7 @@ typedef struct {
static st_table *compat_allocator_tbl;
static VALUE compat_allocator_tbl_wrapper;
static VALUE rb_marshal_dump_limited(VALUE obj, VALUE port, int limit);
-static VALUE rb_marshal_load_with_proc(VALUE port, VALUE proc);
+static VALUE rb_marshal_load_with_proc(VALUE port, VALUE proc, bool freeze);
static int
mark_marshal_compat_i(st_data_t key, st_data_t value, st_data_t _)
@@ -169,6 +174,7 @@ struct dump_arg {
st_table *data;
st_table *compat_tbl;
st_table *encodings;
+ unsigned long num_entries;
};
struct dump_call_arg {
@@ -182,20 +188,20 @@ check_dump_arg(VALUE ret, struct dump_arg *arg, const char *name)
{
if (!arg->symbols) {
rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s",
- name);
+ name);
}
return ret;
}
static VALUE
check_userdump_arg(VALUE obj, ID sym, int argc, const VALUE *argv,
- struct dump_arg *arg, const char *name)
+ struct dump_arg *arg, const char *name)
{
VALUE ret = rb_funcallv(obj, sym, argc, argv);
VALUE klass = CLASS_OF(obj);
if (CLASS_OF(ret) == klass) {
rb_raise(rb_eRuntimeError, "%"PRIsVALUE"#%s returned same class instance",
- klass, name);
+ klass, name);
}
return check_dump_arg(ret, arg, name);
}
@@ -244,13 +250,13 @@ must_not_be_anonymous(const char *type, VALUE path)
char *n = RSTRING_PTR(path);
if (!rb_enc_asciicompat(rb_enc_get(path))) {
- /* cannot occur? */
- rb_raise(rb_eTypeError, "can't dump non-ascii %s name % "PRIsVALUE,
- type, path);
+ /* cannot occur? */
+ rb_raise(rb_eTypeError, "can't dump non-ascii %s name % "PRIsVALUE,
+ type, path);
}
if (n[0] == '#') {
- rb_raise(rb_eTypeError, "can't dump anonymous %s % "PRIsVALUE,
- type, path);
+ rb_raise(rb_eTypeError, "can't dump anonymous %s % "PRIsVALUE,
+ type, path);
}
return path;
}
@@ -262,7 +268,7 @@ class2path(VALUE klass)
must_not_be_anonymous((RB_TYPE_P(klass, T_CLASS) ? "class" : "module"), path);
if (rb_path_to_class(path) != rb_class_real(klass)) {
- rb_raise(rb_eTypeError, "% "PRIsVALUE" can't be referred to", path);
+ rb_raise(rb_eTypeError, "% "PRIsVALUE" can't be referred to", path);
}
return path;
}
@@ -278,8 +284,8 @@ w_nbyte(const char *s, long n, struct dump_arg *arg)
VALUE buf = arg->str;
rb_str_buf_cat(buf, s, n);
if (arg->dest && RSTRING_LEN(buf) >= BUFSIZ) {
- rb_io_write(arg->dest, buf);
- rb_str_resize(buf, 0);
+ rb_io_write(arg->dest, buf);
+ rb_str_resize(buf, 0);
}
}
@@ -323,7 +329,7 @@ ruby_marshal_write_long(long x, char *buf)
#if SIZEOF_LONG > 4
if (!(RSHIFT(x, 31) == 0 || RSHIFT(x, 31) == -1)) {
- /* big long does not fit in 4 bytes */
+ /* big long does not fit in 4 bytes */
return -1;
}
#endif
@@ -341,16 +347,16 @@ ruby_marshal_write_long(long x, char *buf)
return 1;
}
for (i=1;i<(int)sizeof(long)+1;i++) {
- buf[i] = (char)(x & 0xff);
- x = RSHIFT(x,8);
- if (x == 0) {
- buf[0] = i;
- break;
- }
- if (x == -1) {
- buf[0] = -i;
- break;
- }
+ buf[i] = (char)(x & 0xff);
+ x = RSHIFT(x,8);
+ if (x == 0) {
+ buf[0] = i;
+ break;
+ }
+ if (x == -1) {
+ buf[0] = -i;
+ break;
+ }
}
return i+1;
}
@@ -373,13 +379,13 @@ load_mantissa(double d, const char *buf, long len)
{
if (!len) return d;
if (--len > 0 && !*buf++) { /* binary mantissa mark */
- int e, s = d < 0, dig = 0;
- unsigned long m;
+ int e, s = d < 0, dig = 0;
+ unsigned long m;
- modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
- do {
- m = 0;
- switch (len) {
+ modf(ldexp(frexp(fabs(d), &e), DECIMAL_MANT), &d);
+ do {
+ m = 0;
+ switch (len) {
default: m = *buf++ & 0xff; /* fall through */
#if MANT_BITS > 24
case 3: m = (m << 8) | (*buf++ & 0xff); /* fall through */
@@ -388,14 +394,14 @@ load_mantissa(double d, const char *buf, long len)
case 2: m = (m << 8) | (*buf++ & 0xff); /* fall through */
#endif
#if MANT_BITS > 8
- case 1: m = (m << 8) | (*buf++ & 0xff);
+ case 1: m = (m << 8) | (*buf++ & 0xff);
#endif
- }
- dig -= len < MANT_BITS / 8 ? 8 * (unsigned)len : MANT_BITS;
- d += ldexp((double)m, dig);
- } while ((len -= MANT_BITS / 8) > 0);
- d = ldexp(d, e - DECIMAL_MANT);
- if (s) d = -d;
+ }
+ dig -= len < MANT_BITS / 8 ? 8 * (unsigned)len : MANT_BITS;
+ d += ldexp((double)m, dig);
+ } while ((len -= MANT_BITS / 8) > 0);
+ d = ldexp(d, e - DECIMAL_MANT);
+ if (s) d = -d;
}
return d;
}
@@ -415,49 +421,49 @@ w_float(double d, struct dump_arg *arg)
char buf[FLOAT_DIG + (DECIMAL_MANT + 7) / 8 + 10];
if (isinf(d)) {
- if (d < 0) w_cstr("-inf", arg);
- else w_cstr("inf", arg);
+ if (d < 0) w_cstr("-inf", arg);
+ else w_cstr("inf", arg);
}
else if (isnan(d)) {
- w_cstr("nan", arg);
+ w_cstr("nan", arg);
}
else if (d == 0.0) {
if (signbit(d)) w_cstr("-0", arg);
else w_cstr("0", arg);
}
else {
- int decpt, sign, digs, len = 0;
- char *e, *p = ruby_dtoa(d, 0, 0, &decpt, &sign, &e);
- if (sign) buf[len++] = '-';
- digs = (int)(e - p);
- if (decpt < -3 || decpt > digs) {
- buf[len++] = p[0];
- if (--digs > 0) buf[len++] = '.';
- memcpy(buf + len, p + 1, digs);
- len += digs;
- len += snprintf(buf + len, sizeof(buf) - len, "e%d", decpt - 1);
- }
- else if (decpt > 0) {
- memcpy(buf + len, p, decpt);
- len += decpt;
- if ((digs -= decpt) > 0) {
- buf[len++] = '.';
- memcpy(buf + len, p + decpt, digs);
- len += digs;
- }
- }
- else {
- buf[len++] = '0';
- buf[len++] = '.';
- if (decpt) {
- memset(buf + len, '0', -decpt);
- len -= decpt;
- }
- memcpy(buf + len, p, digs);
- len += digs;
- }
- xfree(p);
- w_bytes(buf, len, arg);
+ int decpt, sign, digs, len = 0;
+ char *e, *p = ruby_dtoa(d, 0, 0, &decpt, &sign, &e);
+ if (sign) buf[len++] = '-';
+ digs = (int)(e - p);
+ if (decpt < -3 || decpt > digs) {
+ buf[len++] = p[0];
+ if (--digs > 0) buf[len++] = '.';
+ memcpy(buf + len, p + 1, digs);
+ len += digs;
+ len += snprintf(buf + len, sizeof(buf) - len, "e%d", decpt - 1);
+ }
+ else if (decpt > 0) {
+ memcpy(buf + len, p, decpt);
+ len += decpt;
+ if ((digs -= decpt) > 0) {
+ buf[len++] = '.';
+ memcpy(buf + len, p + decpt, digs);
+ len += digs;
+ }
+ }
+ else {
+ buf[len++] = '0';
+ buf[len++] = '.';
+ if (decpt) {
+ memset(buf + len, '0', -decpt);
+ len -= decpt;
+ }
+ memcpy(buf + len, p, digs);
+ len += digs;
+ }
+ xfree(p);
+ w_bytes(buf, len, arg);
}
}
@@ -468,33 +474,33 @@ w_symbol(VALUE sym, struct dump_arg *arg)
VALUE encname;
if (st_lookup(arg->symbols, sym, &num)) {
- w_byte(TYPE_SYMLINK, arg);
- w_long((long)num, arg);
+ w_byte(TYPE_SYMLINK, arg);
+ w_long((long)num, arg);
}
else {
- const VALUE orig_sym = sym;
- sym = rb_sym2str(sym);
- if (!sym) {
- rb_raise(rb_eTypeError, "can't dump anonymous ID %"PRIdVALUE, sym);
- }
- encname = encoding_name(sym, arg);
- if (NIL_P(encname) ||
- rb_enc_str_coderange(sym) == ENC_CODERANGE_7BIT) {
- encname = Qnil;
- }
- else {
- w_byte(TYPE_IVAR, arg);
- }
- w_byte(TYPE_SYMBOL, arg);
- w_bytes(RSTRING_PTR(sym), RSTRING_LEN(sym), arg);
- st_add_direct(arg->symbols, orig_sym, arg->symbols->num_entries);
- if (!NIL_P(encname)) {
- struct dump_call_arg c_arg;
- c_arg.limit = 1;
- c_arg.arg = arg;
- w_long(1L, arg);
- w_encoding(encname, &c_arg);
- }
+ const VALUE orig_sym = sym;
+ sym = rb_sym2str(sym);
+ if (!sym) {
+ rb_raise(rb_eTypeError, "can't dump anonymous ID %"PRIdVALUE, sym);
+ }
+ encname = encoding_name(sym, arg);
+ if (NIL_P(encname) ||
+ is_ascii_string(sym)) {
+ encname = Qnil;
+ }
+ else {
+ w_byte(TYPE_IVAR, arg);
+ }
+ w_byte(TYPE_SYMBOL, arg);
+ w_bytes(RSTRING_PTR(sym), RSTRING_LEN(sym), arg);
+ st_add_direct(arg->symbols, orig_sym, arg->symbols->num_entries);
+ if (!NIL_P(encname)) {
+ struct dump_call_arg c_arg;
+ c_arg.limit = 1;
+ c_arg.arg = arg;
+ w_long(1L, arg);
+ w_encoding(encname, &c_arg);
+ }
}
}
@@ -518,18 +524,18 @@ hash_each(VALUE key, VALUE value, VALUE v)
#define SINGLETON_DUMP_UNABLE_P(klass) \
(rb_id_table_size(RCLASS_M_TBL(klass)) > 0 || \
- (RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1))
+ rb_ivar_count(klass) > 1)
static void
w_extended(VALUE klass, struct dump_arg *arg, int check)
{
if (check && FL_TEST(klass, FL_SINGLETON)) {
- VALUE origin = RCLASS_ORIGIN(klass);
- if (SINGLETON_DUMP_UNABLE_P(klass) ||
- (origin != klass && SINGLETON_DUMP_UNABLE_P(origin))) {
- rb_raise(rb_eTypeError, "singleton can't be dumped");
- }
- klass = RCLASS_SUPER(klass);
+ VALUE origin = RCLASS_ORIGIN(klass);
+ if (SINGLETON_DUMP_UNABLE_P(klass) ||
+ (origin != klass && SINGLETON_DUMP_UNABLE_P(origin))) {
+ rb_raise(rb_eTypeError, "singleton can't be dumped");
+ }
+ klass = RCLASS_SUPER(klass);
}
while (BUILTIN_TYPE(klass) == T_ICLASS) {
if (!FL_TEST(klass, RICLASS_IS_ORIGIN) ||
@@ -550,7 +556,7 @@ w_class(char type, VALUE obj, struct dump_arg *arg, int check)
VALUE klass;
if (arg->compat_tbl &&
- st_lookup(arg->compat_tbl, (st_data_t)obj, &real_obj)) {
+ st_lookup(arg->compat_tbl, (st_data_t)obj, &real_obj)) {
obj = (VALUE)real_obj;
}
klass = CLASS_OF(obj);
@@ -568,12 +574,31 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
w_extended(klass, arg, TRUE);
klass = rb_class_real(klass);
if (klass != super) {
- w_byte(TYPE_UCLASS, arg);
- w_unique(class2path(klass), arg);
+ w_byte(TYPE_UCLASS, arg);
+ w_unique(class2path(klass), arg);
}
}
-#define to_be_skipped_id(id) (id == rb_id_encoding() || id == s_encoding_short || id == s_ruby2_keywords_flag || !rb_id2str(id))
+static bool
+rb_hash_ruby2_keywords_p(VALUE obj)
+{
+ return (RHASH(obj)->basic.flags & RHASH_PASS_AS_KEYWORDS) != 0;
+}
+
+static void
+rb_hash_ruby2_keywords(VALUE obj)
+{
+ RHASH(obj)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
+}
+
+static inline bool
+to_be_skipped_id(const ID id)
+{
+ if (id == s_encoding_short) return true;
+ if (id == s_ruby2_keywords_flag) return true;
+ if (id == rb_id_encoding()) return true;
+ return !rb_id2str(id);
+}
struct w_ivar_arg {
struct dump_call_arg *dump;
@@ -599,10 +624,6 @@ w_obj_each(st_data_t key, st_data_t val, st_data_t a)
}
return ST_CONTINUE;
}
- if (!ivarg->num_ivar) {
- rb_raise(rb_eRuntimeError, "instance variable added to %"PRIsVALUE" instance",
- CLASS_OF(arg->obj));
- }
--ivarg->num_ivar;
w_symbol(ID2SYM(id), arg->arg);
w_object(value, arg->arg, arg->limit);
@@ -613,7 +634,9 @@ static int
obj_count_ivars(st_data_t key, st_data_t val, st_data_t a)
{
ID id = (ID)key;
- if (!to_be_skipped_id(id)) ++*(st_index_t *)a;
+ if (!to_be_skipped_id(id) && UNLIKELY(!++*(st_index_t *)a)) {
+ rb_raise(rb_eRuntimeError, "too many instance variables");
+ }
return ST_CONTINUE;
}
@@ -659,7 +682,7 @@ w_encoding(VALUE encname, struct dump_call_arg *arg)
case Qfalse:
case Qtrue:
w_symbol(ID2SYM(s_encoding_short), arg->arg);
- w_object(encname, arg->arg, limit);
+ w_object(encname, arg->arg, limit);
return 1;
case Qnil:
return 0;
@@ -672,37 +695,50 @@ w_encoding(VALUE encname, struct dump_call_arg *arg)
static st_index_t
has_ivars(VALUE obj, VALUE encname, VALUE *ivobj)
{
- st_index_t enc = !NIL_P(encname);
- st_index_t num = 0;
- st_index_t ruby2_keywords_flag = 0;
+ st_index_t num = !NIL_P(encname);
if (SPECIAL_CONST_P(obj)) goto generic;
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- break; /* counted elsewhere */
+ break; /* counted elsewhere */
case T_HASH:
- ruby2_keywords_flag = RHASH(obj)->basic.flags & RHASH_PASS_AS_KEYWORDS ? 1 : 0;
+ if (rb_hash_ruby2_keywords_p(obj)) ++num;
/* fall through */
default:
generic:
- rb_ivar_foreach(obj, obj_count_ivars, (st_data_t)&num);
- if (ruby2_keywords_flag || num) *ivobj = obj;
+ rb_ivar_foreach(obj, obj_count_ivars, (st_data_t)&num);
+ if (num) *ivobj = obj;
}
- return num + enc + ruby2_keywords_flag;
+ return num;
}
static void
w_ivar_each(VALUE obj, st_index_t num, struct dump_call_arg *arg)
{
+ shape_id_t shape_id = rb_shape_get_shape_id(arg->obj);
struct w_ivar_arg ivarg = {arg, num};
if (!num) return;
rb_ivar_foreach(obj, w_obj_each, (st_data_t)&ivarg);
- if (ivarg.num_ivar) {
- rb_raise(rb_eRuntimeError, "instance variable removed from %"PRIsVALUE" instance",
- CLASS_OF(arg->obj));
+
+ if (shape_id != rb_shape_get_shape_id(arg->obj)) {
+ rb_shape_t * expected_shape = rb_shape_get_shape_by_id(shape_id);
+ rb_shape_t * actual_shape = rb_shape_get_shape(arg->obj);
+
+ // If the shape tree got _shorter_ then we probably removed an IV
+ // If the shape tree got longer, then we probably added an IV.
+ // The exception message might not be accurate when someone adds and
+ // removes the same number of IVs, but they will still get an exception
+ if (rb_shape_depth(expected_shape) > rb_shape_depth(actual_shape)) {
+ rb_raise(rb_eRuntimeError, "instance variable removed from %"PRIsVALUE" instance",
+ CLASS_OF(arg->obj));
+ }
+ else {
+ rb_raise(rb_eRuntimeError, "instance variable added to %"PRIsVALUE" instance",
+ CLASS_OF(arg->obj));
+ }
}
}
@@ -711,14 +747,14 @@ w_ivar(st_index_t num, VALUE ivobj, VALUE encname, struct dump_call_arg *arg)
{
w_long(num, arg->arg);
num -= w_encoding(encname, arg);
- if (RB_TYPE_P(ivobj, T_HASH) && (RHASH(ivobj)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
+ if (RB_TYPE_P(ivobj, T_HASH) && rb_hash_ruby2_keywords_p(ivobj)) {
int limit = arg->limit;
if (limit >= 0) ++limit;
w_symbol(ID2SYM(s_ruby2_keywords_flag), arg->arg);
- w_object(Qtrue, arg->arg, limit);
+ w_object(Qtrue, arg->arg, limit);
num--;
}
- if (ivobj != Qundef && num) {
+ if (!UNDEF_P(ivobj) && num) {
w_ivar_each(ivobj, num, arg);
}
}
@@ -733,6 +769,62 @@ w_objivar(VALUE obj, struct dump_call_arg *arg)
w_ivar_each(obj, num, arg);
}
+#if SIZEOF_LONG > 4
+// Optimized dump for fixnum larger than 31-bits
+static void
+w_bigfixnum(VALUE obj, struct dump_arg *arg)
+{
+ RUBY_ASSERT(FIXNUM_P(obj));
+
+ w_byte(TYPE_BIGNUM, arg);
+
+#if SIZEOF_LONG == SIZEOF_VALUE
+ long num, slen_num;
+ num = FIX2LONG(obj);
+#else
+ long long num, slen_num;
+ num = NUM2LL(obj);
+#endif
+
+ char sign = num < 0 ? '-' : '+';
+ w_byte(sign, arg);
+
+ // Guaranteed not to overflow, as FIXNUM is 1-bit less than long
+ if (num < 0) num = -num;
+
+ // calculate the size in shorts
+ int slen = 0;
+ {
+ slen_num = num;
+ while (slen_num) {
+ slen++;
+ slen_num = SHORTDN(slen_num);
+ }
+ }
+
+ RUBY_ASSERT(slen > 0 && slen <= SIZEOF_LONG / 2);
+
+ w_long((long)slen, arg);
+
+ for (int i = 0; i < slen; i++) {
+ w_short(num & SHORTMASK, arg);
+ num = SHORTDN(num);
+ }
+
+ // We aren't adding this object to the link table, but we need to increment
+ // the index.
+ arg->num_entries++;
+
+ RUBY_ASSERT(num == 0);
+}
+#endif
+
+static void
+w_remember(VALUE obj, struct dump_arg *arg)
+{
+ st_add_direct(arg->data, obj, arg->num_entries++);
+}
+
static void
w_object(VALUE obj, struct dump_arg *arg, int limit)
{
@@ -743,97 +835,99 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
VALUE encname = Qnil;
if (limit == 0) {
- rb_raise(rb_eArgError, "exceed depth limit");
+ rb_raise(rb_eArgError, "exceed depth limit");
}
- if (limit > 0) limit--;
- c_arg.limit = limit;
- c_arg.arg = arg;
- c_arg.obj = obj;
-
- if (st_lookup(arg->data, obj, &num)) {
- w_byte(TYPE_LINK, arg);
- w_long((long)num, arg);
- return;
- }
-
- if (obj == Qnil) {
- w_byte(TYPE_NIL, arg);
+ if (NIL_P(obj)) {
+ w_byte(TYPE_NIL, arg);
}
else if (obj == Qtrue) {
- w_byte(TYPE_TRUE, arg);
+ w_byte(TYPE_TRUE, arg);
}
else if (obj == Qfalse) {
- w_byte(TYPE_FALSE, arg);
+ w_byte(TYPE_FALSE, arg);
}
else if (FIXNUM_P(obj)) {
#if SIZEOF_LONG <= 4
- w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2INT(obj), arg);
+ w_byte(TYPE_FIXNUM, arg);
+ w_long(FIX2INT(obj), arg);
#else
- if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) {
- w_byte(TYPE_FIXNUM, arg);
- w_long(FIX2LONG(obj), arg);
- }
- else {
- w_object(rb_int2big(FIX2LONG(obj)), arg, limit);
- }
+ if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) {
+ w_byte(TYPE_FIXNUM, arg);
+ w_long(FIX2LONG(obj), arg);
+ }
+ else {
+ w_bigfixnum(obj, arg);
+ }
#endif
}
else if (SYMBOL_P(obj)) {
- w_symbol(obj, arg);
- }
- else if (FLONUM_P(obj)) {
- st_add_direct(arg->data, obj, arg->data->num_entries);
- w_byte(TYPE_FLOAT, arg);
- w_float(RFLOAT_VALUE(obj), arg);
+ w_symbol(obj, arg);
}
else {
- VALUE v;
-
- if (!RBASIC_CLASS(obj)) {
- rb_raise(rb_eTypeError, "can't dump internal %s",
- rb_builtin_type_name(BUILTIN_TYPE(obj)));
- }
-
- if (rb_obj_respond_to(obj, s_mdump, TRUE)) {
- st_add_direct(arg->data, obj, arg->data->num_entries);
-
- v = dump_funcall(arg, obj, s_mdump, 0, 0);
- w_class(TYPE_USRMARSHAL, obj, arg, FALSE);
- w_object(v, arg, limit);
- return;
- }
- if (rb_obj_respond_to(obj, s_dump, TRUE)) {
- VALUE ivobj2 = Qundef;
- st_index_t hasiv2;
- VALUE encname2;
-
- v = INT2NUM(limit);
- v = dump_funcall(arg, obj, s_dump, 1, &v);
- if (!RB_TYPE_P(v, T_STRING)) {
- rb_raise(rb_eTypeError, "_dump() must return string");
- }
- hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivobj);
- hasiv2 = has_ivars(v, (encname2 = encoding_name(v, arg)), &ivobj2);
- if (hasiv2) {
- hasiv = hasiv2;
- ivobj = ivobj2;
- encname = encname2;
- }
- if (hasiv) w_byte(TYPE_IVAR, arg);
- w_class(TYPE_USERDEF, obj, arg, FALSE);
- w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
- if (hasiv) {
- w_ivar(hasiv, ivobj, encname, &c_arg);
- }
- st_add_direct(arg->data, obj, arg->data->num_entries);
- return;
- }
-
- st_add_direct(arg->data, obj, arg->data->num_entries);
-
- hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivobj);
+ if (st_lookup(arg->data, obj, &num)) {
+ w_byte(TYPE_LINK, arg);
+ w_long((long)num, arg);
+ return;
+ }
+
+ if (limit > 0) limit--;
+ c_arg.limit = limit;
+ c_arg.arg = arg;
+ c_arg.obj = obj;
+
+ if (FLONUM_P(obj)) {
+ w_remember(obj, arg);
+ w_byte(TYPE_FLOAT, arg);
+ w_float(RFLOAT_VALUE(obj), arg);
+ return;
+ }
+
+ VALUE v;
+
+ if (!RBASIC_CLASS(obj)) {
+ rb_raise(rb_eTypeError, "can't dump internal %s",
+ rb_builtin_type_name(BUILTIN_TYPE(obj)));
+ }
+
+ if (rb_obj_respond_to(obj, s_mdump, TRUE)) {
+ w_remember(obj, arg);
+
+ v = dump_funcall(arg, obj, s_mdump, 0, 0);
+ w_class(TYPE_USRMARSHAL, obj, arg, FALSE);
+ w_object(v, arg, limit);
+ return;
+ }
+ if (rb_obj_respond_to(obj, s_dump, TRUE)) {
+ VALUE ivobj2 = Qundef;
+ st_index_t hasiv2;
+ VALUE encname2;
+
+ v = INT2NUM(limit);
+ v = dump_funcall(arg, obj, s_dump, 1, &v);
+ if (!RB_TYPE_P(v, T_STRING)) {
+ rb_raise(rb_eTypeError, "_dump() must return string");
+ }
+ hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivobj);
+ hasiv2 = has_ivars(v, (encname2 = encoding_name(v, arg)), &ivobj2);
+ if (hasiv2) {
+ hasiv = hasiv2;
+ ivobj = ivobj2;
+ encname = encname2;
+ }
+ if (hasiv) w_byte(TYPE_IVAR, arg);
+ w_class(TYPE_USERDEF, obj, arg, FALSE);
+ w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
+ if (hasiv) {
+ w_ivar(hasiv, ivobj, encname, &c_arg);
+ }
+ w_remember(obj, arg);
+ return;
+ }
+
+ w_remember(obj, arg);
+
+ hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivobj);
{
st_data_t compat_data;
rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
@@ -847,79 +941,79 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
arg->compat_tbl = rb_init_identtable();
}
st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
- if (obj != real_obj && ivobj == Qundef) hasiv = 0;
+ if (obj != real_obj && UNDEF_P(ivobj)) hasiv = 0;
}
}
- if (hasiv) w_byte(TYPE_IVAR, arg);
-
- switch (BUILTIN_TYPE(obj)) {
- case T_CLASS:
- if (FL_TEST(obj, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "singleton class can't be dumped");
- }
- w_byte(TYPE_CLASS, arg);
- {
- VALUE path = class2path(obj);
- w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
- RB_GC_GUARD(path);
- }
- break;
-
- case T_MODULE:
- w_byte(TYPE_MODULE, arg);
- {
- VALUE path = class2path(obj);
- w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
- RB_GC_GUARD(path);
- }
- break;
-
- case T_FLOAT:
- w_byte(TYPE_FLOAT, arg);
- w_float(RFLOAT_VALUE(obj), arg);
- break;
-
- case T_BIGNUM:
- w_byte(TYPE_BIGNUM, arg);
- {
- char sign = BIGNUM_SIGN(obj) ? '+' : '-';
- size_t len = BIGNUM_LEN(obj);
- size_t slen;
+ if (hasiv) w_byte(TYPE_IVAR, arg);
+
+ switch (BUILTIN_TYPE(obj)) {
+ case T_CLASS:
+ if (FL_TEST(obj, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "singleton class can't be dumped");
+ }
+ w_byte(TYPE_CLASS, arg);
+ {
+ VALUE path = class2path(obj);
+ w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
+ RB_GC_GUARD(path);
+ }
+ break;
+
+ case T_MODULE:
+ w_byte(TYPE_MODULE, arg);
+ {
+ VALUE path = class2path(obj);
+ w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
+ RB_GC_GUARD(path);
+ }
+ break;
+
+ case T_FLOAT:
+ w_byte(TYPE_FLOAT, arg);
+ w_float(RFLOAT_VALUE(obj), arg);
+ break;
+
+ case T_BIGNUM:
+ w_byte(TYPE_BIGNUM, arg);
+ {
+ char sign = BIGNUM_SIGN(obj) ? '+' : '-';
+ size_t len = BIGNUM_LEN(obj);
+ size_t slen;
size_t j;
- BDIGIT *d = BIGNUM_DIGITS(obj);
+ BDIGIT *d = BIGNUM_DIGITS(obj);
slen = SHORTLEN(len);
if (LONG_MAX < slen) {
rb_raise(rb_eTypeError, "too big Bignum can't be dumped");
}
- w_byte(sign, arg);
- w_long((long)slen, arg);
+ w_byte(sign, arg);
+ w_long((long)slen, arg);
for (j = 0; j < len; j++) {
#if SIZEOF_BDIGIT > SIZEOF_SHORT
- BDIGIT num = *d;
- int i;
+ BDIGIT num = *d;
+ int i;
- for (i=0; i<SIZEOF_BDIGIT; i+=SIZEOF_SHORT) {
- w_short(num & SHORTMASK, arg);
- num = SHORTDN(num);
+ for (i=0; i<SIZEOF_BDIGIT; i+=SIZEOF_SHORT) {
+ w_short(num & SHORTMASK, arg);
+ num = SHORTDN(num);
if (j == len - 1 && num == 0) break;
- }
+ }
#else
- w_short(*d, arg);
+ w_short(*d, arg);
#endif
- d++;
- }
- }
- break;
-
- case T_STRING:
- w_uclass(obj, rb_cString, arg);
- w_byte(TYPE_STRING, arg);
- w_bytes(RSTRING_PTR(obj), RSTRING_LEN(obj), arg);
- break;
-
- case T_REGEXP:
+ d++;
+ }
+ }
+ break;
+
+ case T_STRING:
+ w_uclass(obj, rb_cString, arg);
+ w_byte(TYPE_STRING, arg);
+ w_bytes(RSTRING_PTR(obj), RSTRING_LEN(obj), arg);
+ break;
+
+ case T_REGEXP:
w_uclass(obj, rb_cRegexp, arg);
w_byte(TYPE_REGEXP, arg);
{
@@ -927,87 +1021,91 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
w_bytes(RREGEXP_SRC_PTR(obj), RREGEXP_SRC_LEN(obj), arg);
w_byte((char)opts, arg);
}
- break;
-
- case T_ARRAY:
- w_uclass(obj, rb_cArray, arg);
- w_byte(TYPE_ARRAY, arg);
- {
- long i, len = RARRAY_LEN(obj);
-
- w_long(len, arg);
- for (i=0; i<RARRAY_LEN(obj); i++) {
- w_object(RARRAY_AREF(obj, i), arg, limit);
- if (len != RARRAY_LEN(obj)) {
- rb_raise(rb_eRuntimeError, "array modified during dump");
- }
- }
- }
- break;
-
- case T_HASH:
- w_uclass(obj, rb_cHash, arg);
- if (NIL_P(RHASH_IFNONE(obj))) {
- w_byte(TYPE_HASH, arg);
- }
+ break;
+
+ case T_ARRAY:
+ w_uclass(obj, rb_cArray, arg);
+ w_byte(TYPE_ARRAY, arg);
+ {
+ long i, len = RARRAY_LEN(obj);
+
+ w_long(len, arg);
+ for (i=0; i<RARRAY_LEN(obj); i++) {
+ w_object(RARRAY_AREF(obj, i), arg, limit);
+ if (len != RARRAY_LEN(obj)) {
+ rb_raise(rb_eRuntimeError, "array modified during dump");
+ }
+ }
+ }
+ break;
+
+ case T_HASH:
+ w_uclass(obj, rb_cHash, arg);
+ if (rb_hash_compare_by_id_p(obj)) {
+ w_byte(TYPE_UCLASS, arg);
+ w_symbol(rb_sym_intern_ascii_cstr("Hash"), arg);
+ }
+ if (NIL_P(RHASH_IFNONE(obj))) {
+ w_byte(TYPE_HASH, arg);
+ }
else if (FL_TEST(obj, RHASH_PROC_DEFAULT)) {
- rb_raise(rb_eTypeError, "can't dump hash with default proc");
- }
- else {
- w_byte(TYPE_HASH_DEF, arg);
- }
+ rb_raise(rb_eTypeError, "can't dump hash with default proc");
+ }
+ else {
+ w_byte(TYPE_HASH_DEF, arg);
+ }
w_long(rb_hash_size_num(obj), arg);
- rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg);
- if (!NIL_P(RHASH_IFNONE(obj))) {
- w_object(RHASH_IFNONE(obj), arg, limit);
- }
- break;
-
- case T_STRUCT:
- w_class(TYPE_STRUCT, obj, arg, TRUE);
- {
- long len = RSTRUCT_LEN(obj);
- VALUE mem;
- long i;
-
- w_long(len, arg);
- mem = rb_struct_members(obj);
- for (i=0; i<len; i++) {
- w_symbol(RARRAY_AREF(mem, i), arg);
- w_object(RSTRUCT_GET(obj, i), arg, limit);
- }
- }
- break;
-
- case T_OBJECT:
- w_class(TYPE_OBJECT, obj, arg, TRUE);
- w_objivar(obj, &c_arg);
- break;
-
- case T_DATA:
- {
- VALUE v;
-
- if (!rb_obj_respond_to(obj, s_dump_data, TRUE)) {
- rb_raise(rb_eTypeError,
- "no _dump_data is defined for class %"PRIsVALUE,
- rb_obj_class(obj));
- }
- v = dump_funcall(arg, obj, s_dump_data, 0, 0);
- w_class(TYPE_DATA, obj, arg, TRUE);
- w_object(v, arg, limit);
- }
- break;
-
- default:
- rb_raise(rb_eTypeError, "can't dump %"PRIsVALUE,
- rb_obj_class(obj));
- break;
- }
- RB_GC_GUARD(obj);
+ rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg);
+ if (!NIL_P(RHASH_IFNONE(obj))) {
+ w_object(RHASH_IFNONE(obj), arg, limit);
+ }
+ break;
+
+ case T_STRUCT:
+ w_class(TYPE_STRUCT, obj, arg, TRUE);
+ {
+ long len = RSTRUCT_LEN(obj);
+ VALUE mem;
+ long i;
+
+ w_long(len, arg);
+ mem = rb_struct_members(obj);
+ for (i=0; i<len; i++) {
+ w_symbol(RARRAY_AREF(mem, i), arg);
+ w_object(RSTRUCT_GET(obj, i), arg, limit);
+ }
+ }
+ break;
+
+ case T_OBJECT:
+ w_class(TYPE_OBJECT, obj, arg, TRUE);
+ w_objivar(obj, &c_arg);
+ break;
+
+ case T_DATA:
+ {
+ VALUE v;
+
+ if (!rb_obj_respond_to(obj, s_dump_data, TRUE)) {
+ rb_raise(rb_eTypeError,
+ "no _dump_data is defined for class %"PRIsVALUE,
+ rb_obj_class(obj));
+ }
+ v = dump_funcall(arg, obj, s_dump_data, 0, 0);
+ w_class(TYPE_DATA, obj, arg, TRUE);
+ w_object(v, arg, limit);
+ }
+ break;
+
+ default:
+ rb_raise(rb_eTypeError, "can't dump %"PRIsVALUE,
+ rb_obj_class(obj));
+ break;
+ }
+ RB_GC_GUARD(obj);
}
if (hasiv) {
- w_ivar(hasiv, ivobj, encname, &c_arg);
+ w_ivar(hasiv, ivobj, encname, &c_arg);
}
}
@@ -1019,13 +1117,14 @@ clear_dump_arg(struct dump_arg *arg)
arg->symbols = 0;
st_free_table(arg->data);
arg->data = 0;
+ arg->num_entries = 0;
if (arg->compat_tbl) {
- st_free_table(arg->compat_tbl);
- arg->compat_tbl = 0;
+ st_free_table(arg->compat_tbl);
+ arg->compat_tbl = 0;
}
if (arg->encodings) {
- st_free_table(arg->encodings);
- arg->encodings = 0;
+ st_free_table(arg->encodings);
+ arg->encodings = 0;
}
}
@@ -1079,14 +1178,14 @@ marshal_dump(int argc, VALUE *argv, VALUE _)
port = Qnil;
rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
if (argc == 3) {
- if (!NIL_P(a2)) limit = NUM2INT(a2);
- if (NIL_P(a1)) io_needed();
- port = a1;
+ if (!NIL_P(a2)) limit = NUM2INT(a2);
+ if (NIL_P(a1)) io_needed();
+ port = a1;
}
else if (argc == 2) {
- if (FIXNUM_P(a1)) limit = FIX2INT(a1);
- else if (NIL_P(a1)) io_needed();
- else port = a1;
+ if (FIXNUM_P(a1)) limit = FIX2INT(a1);
+ else if (NIL_P(a1)) io_needed();
+ else port = a1;
}
return rb_marshal_dump_limited(obj, port, limit);
}
@@ -1101,18 +1200,19 @@ rb_marshal_dump_limited(VALUE obj, VALUE port, int limit)
arg->dest = 0;
arg->symbols = st_init_numtable();
arg->data = rb_init_identtable();
+ arg->num_entries = 0;
arg->compat_tbl = 0;
arg->encodings = 0;
arg->str = rb_str_buf_new(0);
if (!NIL_P(port)) {
- if (!rb_respond_to(port, s_write)) {
- io_needed();
- }
- arg->dest = port;
- dump_check_funcall(arg, port, s_binmode, 0, 0);
+ if (!rb_respond_to(port, s_write)) {
+ io_needed();
+ }
+ arg->dest = port;
+ dump_check_funcall(arg, port, s_binmode, 0, 0);
}
else {
- port = arg->str;
+ port = arg->str;
}
w_byte(MARSHAL_MAJOR, arg);
@@ -1120,8 +1220,8 @@ rb_marshal_dump_limited(VALUE obj, VALUE port, int limit)
w_object(obj, arg, limit);
if (arg->dest) {
- rb_io_write(arg->dest, arg->str);
- rb_str_resize(arg->str, 0);
+ rb_io_write(arg->dest, arg->str);
+ rb_str_resize(arg->str, 0);
}
clear_dump_arg(arg);
RB_GC_GUARD(wrapper);
@@ -1137,8 +1237,10 @@ struct load_arg {
long offset;
st_table *symbols;
st_table *data;
+ st_table *partial_objects;
VALUE proc;
st_table *compat_tbl;
+ bool freeze;
};
static VALUE
@@ -1146,7 +1248,7 @@ check_load_arg(VALUE ret, struct load_arg *arg, const char *name)
{
if (!arg->symbols) {
rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s",
- name);
+ name);
}
return ret;
}
@@ -1163,6 +1265,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);
}
@@ -1209,15 +1312,15 @@ static unsigned char
r_byte1_buffered(struct load_arg *arg)
{
if (arg->buflen == 0) {
- long readable = arg->readable < BUFSIZ ? arg->readable : BUFSIZ;
- VALUE str, n = LONG2NUM(readable);
+ long readable = arg->readable < BUFSIZ ? arg->readable : BUFSIZ;
+ VALUE str, n = LONG2NUM(readable);
- str = load_funcall(arg, arg->src, s_read, 1, &n);
- if (NIL_P(str)) too_short();
- StringValue(str);
- memcpy(arg->buf, RSTRING_PTR(str), RSTRING_LEN(str));
- arg->offset = 0;
- arg->buflen = RSTRING_LEN(str);
+ str = load_funcall(arg, arg->src, s_read, 1, &n);
+ if (NIL_P(str)) too_short();
+ StringValue(str);
+ memcpy(arg->buf, RSTRING_PTR(str), RSTRING_LEN(str));
+ arg->offset = 0;
+ arg->buflen = RSTRING_LEN(str);
}
arg->buflen--;
return arg->buf[arg->offset++];
@@ -1229,22 +1332,22 @@ r_byte(struct load_arg *arg)
int c;
if (RB_TYPE_P(arg->src, T_STRING)) {
- if (RSTRING_LEN(arg->src) > arg->offset) {
- c = (unsigned char)RSTRING_PTR(arg->src)[arg->offset++];
- }
- else {
- too_short();
- }
+ if (RSTRING_LEN(arg->src) > arg->offset) {
+ c = (unsigned char)RSTRING_PTR(arg->src)[arg->offset++];
+ }
+ else {
+ too_short();
+ }
}
else {
- if (arg->readable >0 || arg->buflen > 0) {
- c = r_byte1_buffered(arg);
- }
- else {
- VALUE v = load_funcall(arg, arg->src, s_getbyte, 0, 0);
- if (NIL_P(v)) rb_eof_error();
- c = (unsigned char)NUM2CHR(v);
- }
+ if (arg->readable >0 || arg->buflen > 0) {
+ c = r_byte1_buffered(arg);
+ }
+ else {
+ VALUE v = load_funcall(arg, arg->src, s_getbyte, 0, 0);
+ if (NIL_P(v)) rb_eof_error();
+ c = (unsigned char)NUM2CHR(v);
+ }
}
return c;
}
@@ -1255,7 +1358,7 @@ static void
long_toobig(int size)
{
rb_raise(rb_eTypeError, "long too big for this architecture (size "
- STRINGIZE(SIZEOF_LONG)", given %d)", size);
+ STRINGIZE(SIZEOF_LONG)", given %d)", size);
}
static long
@@ -1267,26 +1370,26 @@ r_long(struct load_arg *arg)
if (c == 0) return 0;
if (c > 0) {
- if (4 < c && c < 128) {
- return c - 5;
- }
- if (c > (int)sizeof(long)) long_toobig(c);
- x = 0;
- for (i=0;i<c;i++) {
- x |= (long)r_byte(arg) << (8*i);
- }
+ if (4 < c && c < 128) {
+ return c - 5;
+ }
+ if (c > (int)sizeof(long)) long_toobig(c);
+ x = 0;
+ for (i=0;i<c;i++) {
+ x |= (long)r_byte(arg) << (8*i);
+ }
}
else {
- if (-129 < c && c < -4) {
- return c + 5;
- }
- c = -c;
- if (c > (int)sizeof(long)) long_toobig(c);
- x = -1;
- for (i=0;i<c;i++) {
- x &= ~((long)0xff << (8*i));
- x |= (long)r_byte(arg) << (8*i);
- }
+ if (-129 < c && c < -4) {
+ return c + 5;
+ }
+ c = -c;
+ if (c > (int)sizeof(long)) long_toobig(c);
+ x = -1;
+ for (i=0;i<c;i++) {
+ x &= ~((long)0xff << (8*i));
+ x |= (long)r_byte(arg) << (8*i);
+ }
}
return x;
}
@@ -1323,39 +1426,39 @@ r_bytes1_buffered(long len, struct load_arg *arg)
VALUE str;
if (len <= arg->buflen) {
- str = rb_str_new(arg->buf+arg->offset, len);
- arg->offset += len;
- arg->buflen -= len;
+ str = rb_str_new(arg->buf+arg->offset, len);
+ arg->offset += len;
+ arg->buflen -= len;
}
else {
- long buflen = arg->buflen;
- long readable = arg->readable + 1;
- long tmp_len, read_len, need_len = len - buflen;
- VALUE tmp, n;
+ long buflen = arg->buflen;
+ long readable = arg->readable + 1;
+ long tmp_len, read_len, need_len = len - buflen;
+ VALUE tmp, n;
- readable = readable < BUFSIZ ? readable : BUFSIZ;
- read_len = need_len > readable ? need_len : readable;
- n = LONG2NUM(read_len);
- tmp = load_funcall(arg, arg->src, s_read, 1, &n);
- if (NIL_P(tmp)) too_short();
- StringValue(tmp);
+ readable = readable < BUFSIZ ? readable : BUFSIZ;
+ read_len = need_len > readable ? need_len : readable;
+ n = LONG2NUM(read_len);
+ tmp = load_funcall(arg, arg->src, s_read, 1, &n);
+ if (NIL_P(tmp)) too_short();
+ StringValue(tmp);
- tmp_len = RSTRING_LEN(tmp);
+ tmp_len = RSTRING_LEN(tmp);
- if (tmp_len < need_len) too_short();
+ if (tmp_len < need_len) too_short();
- str = rb_str_new(arg->buf+arg->offset, buflen);
- rb_str_cat(str, RSTRING_PTR(tmp), need_len);
+ str = rb_str_new(arg->buf+arg->offset, buflen);
+ rb_str_cat(str, RSTRING_PTR(tmp), need_len);
- if (tmp_len > need_len) {
- buflen = tmp_len - need_len;
- memcpy(arg->buf, RSTRING_PTR(tmp)+need_len, buflen);
- arg->buflen = buflen;
- }
- else {
- arg->buflen = 0;
- }
- arg->offset = 0;
+ if (tmp_len > need_len) {
+ buflen = tmp_len - need_len;
+ memcpy(arg->buf, RSTRING_PTR(tmp)+need_len, buflen);
+ arg->buflen = buflen;
+ }
+ else {
+ arg->buflen = 0;
+ }
+ arg->offset = 0;
}
return str;
@@ -1370,21 +1473,21 @@ r_bytes0(long len, struct load_arg *arg)
if (len == 0) return rb_str_new(0, 0);
if (RB_TYPE_P(arg->src, T_STRING)) {
- if (RSTRING_LEN(arg->src) - arg->offset >= len) {
- str = rb_str_new(RSTRING_PTR(arg->src)+arg->offset, len);
- arg->offset += len;
- }
- else {
- too_short();
- }
+ if (RSTRING_LEN(arg->src) - arg->offset >= len) {
+ str = rb_str_new(RSTRING_PTR(arg->src)+arg->offset, len);
+ arg->offset += len;
+ }
+ else {
+ too_short();
+ }
}
else {
- if (arg->readable > 0 || arg->buflen > 0) {
- str = r_bytes1_buffered(len, arg);
- }
- else {
- str = r_bytes1(len, arg);
- }
+ if (arg->readable > 0 || arg->buflen > 0) {
+ str = r_bytes1_buffered(len, arg);
+ }
+ else {
+ str = r_bytes1(len, arg);
+ }
}
return str;
}
@@ -1399,37 +1502,40 @@ name_equal(const char *name, size_t nlen, const char *p, long l)
static int
sym2encidx(VALUE sym, VALUE val)
{
- static const char name_encoding[8] = "encoding";
+ RBIMPL_ATTR_NONSTRING() static const char name_encoding[8] = "encoding";
const char *p;
long l;
if (rb_enc_get_index(sym) != ENCINDEX_US_ASCII) return -1;
RSTRING_GETMEM(sym, p, l);
if (l <= 0) return -1;
if (name_equal(name_encoding, sizeof(name_encoding), p, l)) {
- int idx = rb_enc_find_index(StringValueCStr(val));
- return idx;
+ int idx = rb_enc_find_index(StringValueCStr(val));
+ return idx;
}
if (name_equal(name_s_encoding_short, rb_strlen_lit(name_s_encoding_short), p, l)) {
- if (val == Qfalse) return rb_usascii_encindex();
- else if (val == Qtrue) return rb_utf8_encindex();
- /* bogus ignore */
+ if (val == Qfalse) return rb_usascii_encindex();
+ else if (val == Qtrue) return rb_utf8_encindex();
+ /* bogus ignore */
}
return -1;
}
static int
-ruby2_keywords_flag_check(VALUE sym)
+symname_equal(VALUE sym, const char *name, size_t nlen)
{
const char *p;
long l;
+ if (rb_enc_get_index(sym) != ENCINDEX_US_ASCII) return 0;
RSTRING_GETMEM(sym, p, l);
- if (l <= 0) return 0;
- if (name_equal(name_s_ruby2_keywords_flag, rb_strlen_lit(name_s_ruby2_keywords_flag), p, 1)) {
- return 1;
- }
- return 0;
+ return name_equal(name, nlen, p, l);
}
+#define BUILD_ASSERT_POSITIVE(n) \
+ /* make 0 negative to workaround the "zero size array" GCC extension, */ \
+ ((sizeof(char [2*(ssize_t)(n)-1])+1)/2) /* assuming no overflow */
+#define symname_equal_lit(sym, sym_name) \
+ symname_equal(sym, sym_name, BUILD_ASSERT_POSITIVE(rb_strlen_lit(sym_name)))
+
static VALUE
r_symlink(struct load_arg *arg)
{
@@ -1437,7 +1543,7 @@ r_symlink(struct load_arg *arg)
long num = r_long(arg);
if (!st_lookup(arg->symbols, num, &sym)) {
- rb_raise(rb_eArgError, "bad symbol");
+ rb_raise(rb_eArgError, "bad symbol");
}
return (VALUE)sym;
}
@@ -1453,13 +1559,19 @@ r_symreal(struct load_arg *arg, int ivar)
if (rb_enc_str_asciionly_p(s)) rb_enc_associate_index(s, ENCINDEX_US_ASCII);
st_insert(arg->symbols, (st_data_t)n, (st_data_t)s);
if (ivar) {
- long num = r_long(arg);
- while (num-- > 0) {
- sym = r_symbol(arg);
- idx = sym2encidx(sym, r_object(arg));
- }
+ long num = r_long(arg);
+ while (num-- > 0) {
+ sym = r_symbol(arg);
+ idx = sym2encidx(sym, r_object(arg));
+ }
+ }
+ if (idx > 0) {
+ rb_enc_associate_index(s, idx);
+ if (is_broken_string(s)) {
+ rb_raise(rb_eArgError, "invalid byte sequence in %s: %+"PRIsVALUE,
+ rb_enc_name(rb_enc_from_index(idx)), s);
+ }
}
- if (idx > 0) rb_enc_associate_index(s, idx);
return s;
}
@@ -1472,17 +1584,17 @@ r_symbol(struct load_arg *arg)
again:
switch ((type = r_byte(arg))) {
default:
- rb_raise(rb_eArgError, "dump format error for symbol(0x%x)", type);
+ rb_raise(rb_eArgError, "dump format error for symbol(0x%x)", type);
case TYPE_IVAR:
- ivar = 1;
- goto again;
+ ivar = 1;
+ goto again;
case TYPE_SYMBOL:
- return r_symreal(arg, ivar);
+ return r_symreal(arg, ivar);
case TYPE_SYMLINK:
- if (ivar) {
- rb_raise(rb_eArgError, "dump format error (symlink with encoding)");
- }
- return r_symlink(arg);
+ if (ivar) {
+ rb_raise(rb_eArgError, "dump format error (symlink with encoding)");
+ }
+ return r_symlink(arg);
}
}
@@ -1507,6 +1619,7 @@ r_entry0(VALUE v, st_index_t num, struct load_arg *arg)
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;
}
@@ -1531,16 +1644,32 @@ static VALUE
r_post_proc(VALUE v, struct load_arg *arg)
{
if (arg->proc) {
- v = load_funcall(arg, arg->proc, s_call, 1, &v);
+ v = load_funcall(arg, arg->proc, s_call, 1, &v);
}
return v;
}
static VALUE
-r_leave(VALUE v, struct load_arg *arg)
+r_leave(VALUE v, struct load_arg *arg, bool partial)
{
v = r_fixup_compat(v, arg);
- v = r_post_proc(v, arg);
+ if (!partial) {
+ st_data_t data;
+ st_data_t key = (st_data_t)v;
+ st_delete(arg->partial_objects, &key, &data);
+ if (arg->freeze) {
+ if (RB_TYPE_P(v, T_MODULE) || RB_TYPE_P(v, T_CLASS)) {
+ // noop
+ }
+ else if (RB_TYPE_P(v, T_STRING)) {
+ v = rb_str_to_interned_str(v);
+ }
+ else {
+ OBJ_FREEZE(v);
+ }
+ }
+ v = r_post_proc(v, arg);
+ }
return v;
}
@@ -1551,7 +1680,7 @@ copy_ivar_i(st_data_t key, st_data_t val, st_data_t arg)
ID vid = (ID)key;
if (!rb_ivar_defined(obj, vid))
- rb_ivar_set(obj, vid, value);
+ rb_ivar_set(obj, vid, value);
return ST_CONTINUE;
}
@@ -1569,22 +1698,22 @@ r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg)
len = r_long(arg);
if (len > 0) {
- do {
- VALUE sym = r_symbol(arg);
- VALUE val = r_object(arg);
- int idx = sym2encidx(sym, val);
- if (idx >= 0) {
+ do {
+ VALUE sym = r_symbol(arg);
+ VALUE val = r_object(arg);
+ int idx = sym2encidx(sym, val);
+ if (idx >= 0) {
if (rb_enc_capable(obj)) {
rb_enc_associate_index(obj, idx);
}
else {
rb_raise(rb_eArgError, "%"PRIsVALUE" is not enc_capable", obj);
}
- if (has_encoding) *has_encoding = TRUE;
- }
- else if (ruby2_keywords_flag_check(sym)) {
+ if (has_encoding) *has_encoding = TRUE;
+ }
+ else if (symname_equal_lit(sym, name_s_ruby2_keywords_flag)) {
if (RB_TYPE_P(obj, T_HASH)) {
- RHASH(obj)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
+ rb_hash_ruby2_keywords(obj);
}
else {
rb_raise(rb_eArgError, "ruby2_keywords flag is given but %"PRIsVALUE" is not a Hash", obj);
@@ -1592,8 +1721,8 @@ r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg)
}
else {
rb_ivar_set(obj, rb_intern_str(sym), val);
- }
- } while (--len > 0);
+ }
+ } while (--len > 0);
}
}
@@ -1603,7 +1732,7 @@ path2class(VALUE path)
VALUE v = rb_path_to_class(path);
if (!RB_TYPE_P(v, T_CLASS)) {
- rb_raise(rb_eArgError, "%"PRIsVALUE" does not refer to class", path);
+ rb_raise(rb_eArgError, "%"PRIsVALUE" does not refer to class", path);
}
return v;
}
@@ -1614,7 +1743,7 @@ static VALUE
must_be_module(VALUE v, VALUE path)
{
if (!RB_TYPE_P(v, T_MODULE)) {
- rb_raise(rb_eArgError, "%"PRIsVALUE" does not refer to module", path);
+ rb_raise(rb_eArgError, "%"PRIsVALUE" does not refer to module", path);
}
return v;
}
@@ -1630,7 +1759,7 @@ obj_alloc_by_klass(VALUE klass, struct load_arg *arg, VALUE *oldclass)
marshal_compat_t *compat = (marshal_compat_t*)data;
VALUE real_obj = rb_obj_alloc(klass);
VALUE obj = rb_obj_alloc(compat->oldclass);
- if (oldclass) *oldclass = compat->oldclass;
+ if (oldclass) *oldclass = compat->oldclass;
if (!arg->compat_tbl) {
arg->compat_tbl = rb_init_identtable();
@@ -1653,449 +1782,504 @@ append_extmod(VALUE obj, VALUE extmod)
{
long i = RARRAY_LEN(extmod);
while (i > 0) {
- VALUE m = RARRAY_AREF(extmod, --i);
- rb_extend_object(obj, m);
+ VALUE m = RARRAY_AREF(extmod, --i);
+ rb_extend_object(obj, m);
}
return obj;
}
#define prohibit_ivar(type, str) do { \
- if (!ivp || !*ivp) break; \
- rb_raise(rb_eTypeError, \
- "can't override instance variable of "type" `%"PRIsVALUE"'", \
- (str)); \
+ if (!ivp || !*ivp) break; \
+ rb_raise(rb_eTypeError, \
+ "can't override instance variable of "type" `%"PRIsVALUE"'", \
+ (str)); \
} while (0)
+static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type);
+
static VALUE
-r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
+r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
{
- VALUE v = Qnil;
int type = r_byte(arg);
+ return r_object_for(arg, partial, ivp, extmod, type);
+}
+
+static int
+r_move_ivar(st_data_t k, st_data_t v, st_data_t d)
+{
+ ID key = (ID)k;
+ VALUE value = (VALUE)v;
+ VALUE dest = (VALUE)d;
+
+ if (rb_is_instance_id(key)) {
+ rb_ivar_set(dest, key, value);
+ return ST_DELETE;
+ }
+ return ST_CONTINUE;
+}
+
+static VALUE
+r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type)
+{
+ VALUE (*hash_new_with_size)(st_index_t) = rb_hash_new_with_size;
+ VALUE v = Qnil;
long id;
st_data_t link;
switch (type) {
case TYPE_LINK:
- id = r_long(arg);
- if (!st_lookup(arg->data, (st_data_t)id, &link)) {
- rb_raise(rb_eArgError, "dump format error (unlinked)");
- }
- v = (VALUE)link;
- v = r_post_proc(v, arg);
- break;
+ id = r_long(arg);
+ if (!st_lookup(arg->data, (st_data_t)id, &link)) {
+ rb_raise(rb_eArgError, "dump format error (unlinked)");
+ }
+ v = (VALUE)link;
+ 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);
- if (ivar) r_ivar(v, NULL, arg);
- }
- break;
+ int ivar = TRUE;
+ v = r_object0(arg, true, &ivar, extmod);
+ if (ivar) r_ivar(v, NULL, arg);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_EXTENDED:
- {
- VALUE path = r_unique(arg);
- VALUE m = rb_path_to_class(path);
- if (NIL_P(extmod)) extmod = rb_ary_tmp_new(0);
-
- if (RB_TYPE_P(m, T_CLASS)) { /* prepended */
- VALUE c;
-
- v = r_object0(arg, 0, Qnil);
- c = CLASS_OF(v);
- if (c != m || FL_TEST(c, FL_SINGLETON)) {
- rb_raise(rb_eArgError,
- "prepended class %"PRIsVALUE" differs from class %"PRIsVALUE,
- path, rb_class_name(c));
- }
- c = rb_singleton_class(v);
- while (RARRAY_LEN(extmod) > 0) {
- m = rb_ary_pop(extmod);
- rb_prepend_module(c, m);
- }
- }
- else {
- must_be_module(m, path);
- rb_ary_push(extmod, m);
-
- v = r_object0(arg, 0, extmod);
- while (RARRAY_LEN(extmod) > 0) {
- m = rb_ary_pop(extmod);
- rb_extend_object(v, m);
- }
- }
- }
- break;
+ {
+ VALUE path = r_unique(arg);
+ VALUE m = rb_path_to_class(path);
+ if (NIL_P(extmod)) extmod = rb_ary_hidden_new(0);
+
+ if (RB_TYPE_P(m, T_CLASS)) { /* prepended */
+ VALUE c;
+
+ v = r_object0(arg, true, 0, Qnil);
+ c = CLASS_OF(v);
+ if (c != m || FL_TEST(c, FL_SINGLETON)) {
+ rb_raise(rb_eArgError,
+ "prepended class %"PRIsVALUE" differs from class %"PRIsVALUE,
+ path, rb_class_name(c));
+ }
+ c = rb_singleton_class(v);
+ while (RARRAY_LEN(extmod) > 0) {
+ m = rb_ary_pop(extmod);
+ rb_prepend_module(c, m);
+ }
+ }
+ else {
+ must_be_module(m, path);
+ rb_ary_push(extmod, m);
+
+ v = r_object0(arg, true, 0, extmod);
+ while (RARRAY_LEN(extmod) > 0) {
+ m = rb_ary_pop(extmod);
+ rb_extend_object(v, m);
+ }
+ }
+ }
+ break;
case TYPE_UCLASS:
- {
- VALUE c = path2class(r_unique(arg));
-
- if (FL_TEST(c, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "singleton can't be loaded");
- }
- v = r_object0(arg, 0, extmod);
- if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
+ {
+ VALUE c = path2class(r_unique(arg));
+
+ if (FL_TEST(c, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "singleton can't be loaded");
+ }
+ type = r_byte(arg);
+ if ((c == rb_cHash) &&
+ /* Hack for compare_by_identify */
+ (type == TYPE_HASH || type == TYPE_HASH_DEF)) {
+ hash_new_with_size = rb_ident_hash_new_with_size;
+ goto type_hash;
+ }
+ v = r_object_for(arg, partial, 0, extmod, type);
+ if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
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);
+ }
+ if (RB_TYPE_P(v, T_MODULE) || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
+ VALUE tmp = rb_obj_alloc(c);
- if (TYPE(v) != TYPE(tmp)) goto format_error;
- }
- RBASIC_SET_CLASS(v, c);
- }
- break;
+ if (TYPE(v) != TYPE(tmp)) goto format_error;
+ }
+ RBASIC_SET_CLASS(v, c);
+ }
+ break;
format_error:
rb_raise(rb_eArgError, "dump format error (user class)");
case TYPE_NIL:
- v = Qnil;
- v = r_leave(v, arg);
- break;
+ v = Qnil;
+ v = r_leave(v, arg, false);
+ break;
case TYPE_TRUE:
- v = Qtrue;
- v = r_leave(v, arg);
- break;
+ v = Qtrue;
+ v = r_leave(v, arg, false);
+ break;
case TYPE_FALSE:
- v = Qfalse;
- v = r_leave(v, arg);
- break;
+ v = Qfalse;
+ v = r_leave(v, arg, false);
+ break;
case TYPE_FIXNUM:
- {
- long i = r_long(arg);
- v = LONG2FIX(i);
- }
- v = r_leave(v, arg);
- break;
+ {
+ long i = r_long(arg);
+ v = LONG2FIX(i);
+ }
+ v = r_leave(v, arg, false);
+ break;
case TYPE_FLOAT:
- {
- double d;
- VALUE str = r_bytes(arg);
- const char *ptr = RSTRING_PTR(str);
-
- if (strcmp(ptr, "nan") == 0) {
- d = nan("");
- }
- else if (strcmp(ptr, "inf") == 0) {
- d = HUGE_VAL;
- }
- else if (strcmp(ptr, "-inf") == 0) {
- d = -HUGE_VAL;
- }
- else {
- char *e;
- d = strtod(ptr, &e);
- d = load_mantissa(d, e, RSTRING_LEN(str) - (e - ptr));
- }
- v = DBL2NUM(d);
- v = r_entry(v, arg);
- v = r_leave(v, arg);
- }
- break;
+ {
+ double d;
+ VALUE str = r_bytes(arg);
+ const char *ptr = RSTRING_PTR(str);
+
+ if (strcmp(ptr, "nan") == 0) {
+ d = nan("");
+ }
+ else if (strcmp(ptr, "inf") == 0) {
+ d = HUGE_VAL;
+ }
+ else if (strcmp(ptr, "-inf") == 0) {
+ d = -HUGE_VAL;
+ }
+ else {
+ char *e;
+ d = strtod(ptr, &e);
+ d = load_mantissa(d, e, RSTRING_LEN(str) - (e - ptr));
+ }
+ v = DBL2NUM(d);
+ v = r_entry(v, arg);
+ v = r_leave(v, arg, false);
+ }
+ break;
case TYPE_BIGNUM:
- {
- long len;
- VALUE data;
+ {
+ long len;
+ VALUE data;
int sign;
- sign = r_byte(arg);
- len = r_long(arg);
- data = r_bytes0(len * 2, arg);
- v = rb_integer_unpack(RSTRING_PTR(data), len, 2, 0,
- INTEGER_PACK_LITTLE_ENDIAN | (sign == '-' ? INTEGER_PACK_NEGATIVE : 0));
- rb_str_resize(data, 0L);
- v = r_entry(v, arg);
- v = r_leave(v, arg);
- }
- break;
+ sign = r_byte(arg);
+ len = r_long(arg);
+
+ if (SIZEOF_VALUE >= 8 && len <= 4) {
+ // Representable within uintptr, likely FIXNUM
+ VALUE num = 0;
+ for (int i = 0; i < len; i++) {
+ num |= (VALUE)r_byte(arg) << (i * 16);
+ num |= (VALUE)r_byte(arg) << (i * 16 + 8);
+ }
+#if SIZEOF_VALUE == SIZEOF_LONG
+ v = ULONG2NUM(num);
+#else
+ v = ULL2NUM(num);
+#endif
+ if (sign == '-') {
+ v = rb_int_uminus(v);
+ }
+ }
+ else {
+ data = r_bytes0(len * 2, arg);
+ v = rb_integer_unpack(RSTRING_PTR(data), len, 2, 0,
+ INTEGER_PACK_LITTLE_ENDIAN | (sign == '-' ? INTEGER_PACK_NEGATIVE : 0));
+ rb_str_resize(data, 0L);
+ }
+ v = r_entry(v, arg);
+ v = r_leave(v, arg, false);
+ }
+ break;
case TYPE_STRING:
- v = r_entry(r_string(arg), arg);
- v = r_leave(v, arg);
- break;
+ v = r_entry(r_string(arg), arg);
+ v = r_leave(v, arg, partial);
+ break;
case TYPE_REGEXP:
- {
- VALUE str = r_bytes(arg);
- int options = r_byte(arg);
- int has_encoding = FALSE;
- st_index_t idx = r_prepare(arg);
-
- if (ivp) {
- r_ivar(str, &has_encoding, arg);
- *ivp = FALSE;
- }
- if (!has_encoding) {
- /* 1.8 compatibility; remove escapes undefined in 1.8 */
- char *ptr = RSTRING_PTR(str), *dst = ptr, *src = ptr;
- long len = RSTRING_LEN(str);
- long bs = 0;
- for (; len-- > 0; *dst++ = *src++) {
- switch (*src) {
- case '\\': bs++; break;
- case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'o': case 'p': case 'q': case 'u': case 'y':
- case 'E': case 'F': case 'H': case 'I': case 'J': case 'K':
- case 'L': case 'N': case 'O': case 'P': case 'Q': case 'R':
- case 'S': case 'T': case 'U': case 'V': case 'X': case 'Y':
- if (bs & 1) --dst;
+ {
+ VALUE str = r_bytes(arg);
+ int options = r_byte(arg);
+ int has_encoding = FALSE;
+ st_index_t idx = r_prepare(arg);
+
+ if (ivp) {
+ r_ivar(str, &has_encoding, arg);
+ *ivp = FALSE;
+ }
+ if (!has_encoding) {
+ /* 1.8 compatibility; remove escapes undefined in 1.8 */
+ char *ptr = RSTRING_PTR(str), *dst = ptr, *src = ptr;
+ long len = RSTRING_LEN(str);
+ long bs = 0;
+ for (; len-- > 0; *dst++ = *src++) {
+ switch (*src) {
+ case '\\': bs++; break;
+ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+ case 'm': case 'o': case 'p': case 'q': case 'u': case 'y':
+ case 'E': case 'F': case 'H': case 'I': case 'J': case 'K':
+ case 'L': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'X': case 'Y':
+ if (bs & 1) --dst;
/* fall through */
- default: bs = 0; break;
- }
- }
- rb_str_set_len(str, dst - ptr);
- }
- v = r_entry0(rb_reg_new_str(str, options), idx, arg);
- v = r_leave(v, arg);
- }
- break;
+ default: bs = 0; break;
+ }
+ }
+ rb_str_set_len(str, dst - ptr);
+ }
+ VALUE regexp = rb_reg_new_str(str, options);
+ rb_ivar_foreach(str, r_move_ivar, regexp);
+
+ v = r_entry0(regexp, idx, arg);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_ARRAY:
- {
- long len = r_long(arg);
-
- v = rb_ary_new2(len);
- v = r_entry(v, arg);
- arg->readable += len - 1;
- while (len--) {
- rb_ary_push(v, r_object(arg));
- arg->readable--;
- }
- v = r_leave(v, arg);
- arg->readable++;
- }
- break;
+ {
+ long len = r_long(arg);
+
+ v = rb_ary_new2(len);
+ v = r_entry(v, arg);
+ arg->readable += len - 1;
+ while (len--) {
+ rb_ary_push(v, r_object(arg));
+ arg->readable--;
+ }
+ v = r_leave(v, arg, partial);
+ arg->readable++;
+ }
+ break;
case TYPE_HASH:
case TYPE_HASH_DEF:
- {
- long len = r_long(arg);
-
- v = rb_hash_new_with_size(len);
- v = r_entry(v, arg);
- arg->readable += (len - 1) * 2;
- while (len--) {
- VALUE key = r_object(arg);
- VALUE value = r_object(arg);
- rb_hash_aset(v, key, value);
- arg->readable -= 2;
- }
- arg->readable += 2;
- if (type == TYPE_HASH_DEF) {
- RHASH_SET_IFNONE(v, r_object(arg));
- }
- v = r_leave(v, arg);
- }
- break;
+ type_hash:
+ {
+ long len = r_long(arg);
+
+ v = hash_new_with_size(len);
+ v = r_entry(v, arg);
+ arg->readable += (len - 1) * 2;
+ while (len--) {
+ VALUE key = r_object(arg);
+ VALUE value = r_object(arg);
+ rb_hash_aset(v, key, value);
+ arg->readable -= 2;
+ }
+ arg->readable += 2;
+ if (type == TYPE_HASH_DEF) {
+ RHASH_SET_IFNONE(v, r_object(arg));
+ }
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_STRUCT:
- {
- VALUE mem, values;
- long i;
- VALUE slot;
- st_index_t idx = r_prepare(arg);
- VALUE klass = path2class(r_unique(arg));
- long len = r_long(arg);
+ {
+ VALUE mem, values;
+ long i;
+ VALUE slot;
+ st_index_t idx = r_prepare(arg);
+ VALUE klass = path2class(r_unique(arg));
+ long len = r_long(arg);
v = rb_obj_alloc(klass);
- if (!RB_TYPE_P(v, T_STRUCT)) {
- rb_raise(rb_eTypeError, "class %"PRIsVALUE" not a struct", rb_class_name(klass));
- }
- mem = rb_struct_s_members(klass);
+ if (!RB_TYPE_P(v, T_STRUCT)) {
+ rb_raise(rb_eTypeError, "class %"PRIsVALUE" not a struct", rb_class_name(klass));
+ }
+ mem = rb_struct_s_members(klass);
if (RARRAY_LEN(mem) != len) {
rb_raise(rb_eTypeError, "struct %"PRIsVALUE" not compatible (struct size differs)",
rb_class_name(klass));
}
- arg->readable += (len - 1) * 2;
- v = r_entry0(v, idx, arg);
- values = rb_ary_new2(len);
- {
- VALUE keywords = Qfalse;
- if (RTEST(rb_struct_s_keyword_init(klass))) {
- keywords = rb_hash_new();
- rb_ary_push(values, keywords);
- }
-
- for (i=0; i<len; i++) {
- VALUE n = rb_sym2str(RARRAY_AREF(mem, i));
- slot = r_symbol(arg);
-
- if (!rb_str_equal(n, slot)) {
- rb_raise(rb_eTypeError, "struct %"PRIsVALUE" not compatible (:%"PRIsVALUE" for :%"PRIsVALUE")",
- rb_class_name(klass),
- slot, n);
- }
- if (keywords) {
- rb_hash_aset(keywords, RARRAY_AREF(mem, i), r_object(arg));
- }
- else {
- rb_ary_push(values, r_object(arg));
- }
- arg->readable -= 2;
- }
- }
+ arg->readable += (len - 1) * 2;
+ v = r_entry0(v, idx, arg);
+ values = rb_ary_new2(len);
+ {
+ VALUE keywords = Qfalse;
+ if (RTEST(rb_struct_s_keyword_init(klass))) {
+ keywords = rb_hash_new();
+ rb_ary_push(values, keywords);
+ }
+
+ for (i=0; i<len; i++) {
+ VALUE n = rb_sym2str(RARRAY_AREF(mem, i));
+ slot = r_symbol(arg);
+
+ if (!rb_str_equal(n, slot)) {
+ rb_raise(rb_eTypeError, "struct %"PRIsVALUE" not compatible (:%"PRIsVALUE" for :%"PRIsVALUE")",
+ rb_class_name(klass),
+ slot, n);
+ }
+ if (keywords) {
+ rb_hash_aset(keywords, RARRAY_AREF(mem, i), r_object(arg));
+ }
+ else {
+ rb_ary_push(values, r_object(arg));
+ }
+ arg->readable -= 2;
+ }
+ }
rb_struct_initialize(v, values);
- v = r_leave(v, arg);
- arg->readable += 2;
- }
- break;
+ v = r_leave(v, arg, partial);
+ arg->readable += 2;
+ }
+ break;
case TYPE_USERDEF:
{
- VALUE name = r_unique(arg);
- VALUE klass = path2class(name);
- VALUE data;
- st_data_t d;
-
- if (!rb_obj_respond_to(klass, s_load, TRUE)) {
- rb_raise(rb_eTypeError, "class %"PRIsVALUE" needs to have method `_load'",
- name);
- }
- data = r_string(arg);
- if (ivp) {
- r_ivar(data, NULL, arg);
- *ivp = FALSE;
- }
- v = load_funcall(arg, klass, s_load, 1, &data);
- v = r_entry(v, arg);
- if (st_lookup(compat_allocator_tbl, (st_data_t)rb_get_alloc_func(klass), &d)) {
- marshal_compat_t *compat = (marshal_compat_t*)d;
- v = compat->loader(klass, v);
- }
- v = r_post_proc(v, arg);
- }
+ VALUE name = r_unique(arg);
+ VALUE klass = path2class(name);
+ VALUE data;
+ st_data_t d;
+
+ if (!rb_obj_respond_to(klass, s_load, TRUE)) {
+ rb_raise(rb_eTypeError, "class %"PRIsVALUE" needs to have method `_load'",
+ name);
+ }
+ data = r_string(arg);
+ if (ivp) {
+ r_ivar(data, NULL, arg);
+ *ivp = FALSE;
+ }
+ v = load_funcall(arg, klass, s_load, 1, &data);
+ v = r_entry(v, arg);
+ if (st_lookup(compat_allocator_tbl, (st_data_t)rb_get_alloc_func(klass), &d)) {
+ marshal_compat_t *compat = (marshal_compat_t*)d;
+ v = compat->loader(klass, v);
+ }
+ if (!partial) v = r_post_proc(v, arg);
+ }
break;
case TYPE_USRMARSHAL:
{
- VALUE name = r_unique(arg);
- VALUE klass = path2class(name);
- VALUE oldclass = 0;
- VALUE data;
+ VALUE name = r_unique(arg);
+ VALUE klass = path2class(name);
+ VALUE oldclass = 0;
+ VALUE data;
- v = obj_alloc_by_klass(klass, arg, &oldclass);
+ v = obj_alloc_by_klass(klass, arg, &oldclass);
+ if (!NIL_P(extmod)) {
+ /* for the case marshal_load is overridden */
+ append_extmod(v, extmod);
+ }
+ if (!rb_obj_respond_to(v, s_mload, TRUE)) {
+ rb_raise(rb_eTypeError, "instance of %"PRIsVALUE" needs to have method `marshal_load'",
+ name);
+ }
+ v = r_entry(v, arg);
+ data = r_object(arg);
+ load_funcall(arg, v, s_mload, 1, &data);
+ v = r_fixup_compat(v, arg);
+ v = r_copy_ivar(v, data);
+ v = r_post_proc(v, arg);
if (!NIL_P(extmod)) {
- /* for the case marshal_load is overridden */
- append_extmod(v, extmod);
+ if (oldclass) append_extmod(v, extmod);
+ rb_ary_clear(extmod);
}
- if (!rb_obj_respond_to(v, s_mload, TRUE)) {
- rb_raise(rb_eTypeError, "instance of %"PRIsVALUE" needs to have method `marshal_load'",
- name);
- }
- v = r_entry(v, arg);
- data = r_object(arg);
- load_funcall(arg, v, s_mload, 1, &data);
- v = r_fixup_compat(v, arg);
- v = r_copy_ivar(v, data);
- v = r_post_proc(v, arg);
- if (!NIL_P(extmod)) {
- if (oldclass) append_extmod(v, extmod);
- rb_ary_clear(extmod);
- }
- }
+ }
break;
case TYPE_OBJECT:
- {
- st_index_t idx = r_prepare(arg);
+ {
+ st_index_t idx = r_prepare(arg);
v = obj_alloc_by_path(r_unique(arg), arg);
- if (!RB_TYPE_P(v, T_OBJECT)) {
- rb_raise(rb_eArgError, "dump format error");
- }
- v = r_entry0(v, idx, arg);
- r_ivar(v, NULL, arg);
- v = r_leave(v, arg);
- }
- break;
+ if (!RB_TYPE_P(v, T_OBJECT)) {
+ rb_raise(rb_eArgError, "dump format error");
+ }
+ v = r_entry0(v, idx, arg);
+ r_ivar(v, NULL, arg);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_DATA:
- {
- VALUE name = r_unique(arg);
- VALUE klass = path2class(name);
- VALUE oldclass = 0;
- VALUE r;
-
- v = obj_alloc_by_klass(klass, arg, &oldclass);
- if (!RB_TYPE_P(v, T_DATA)) {
- rb_raise(rb_eArgError, "dump format error");
- }
- v = r_entry(v, arg);
- if (!rb_obj_respond_to(v, s_load_data, TRUE)) {
- rb_raise(rb_eTypeError,
- "class %"PRIsVALUE" needs to have instance method `_load_data'",
- name);
- }
- r = r_object0(arg, 0, extmod);
- load_funcall(arg, v, s_load_data, 1, &r);
- v = r_leave(v, arg);
- }
- break;
+ {
+ VALUE name = r_unique(arg);
+ VALUE klass = path2class(name);
+ VALUE oldclass = 0;
+ VALUE r;
+
+ v = obj_alloc_by_klass(klass, arg, &oldclass);
+ if (!RB_TYPE_P(v, T_DATA)) {
+ rb_raise(rb_eArgError, "dump format error");
+ }
+ v = r_entry(v, arg);
+ if (!rb_obj_respond_to(v, s_load_data, TRUE)) {
+ rb_raise(rb_eTypeError,
+ "class %"PRIsVALUE" needs to have instance method `_load_data'",
+ name);
+ }
+ r = r_object0(arg, partial, 0, extmod);
+ load_funcall(arg, v, s_load_data, 1, &r);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_MODULE_OLD:
{
- VALUE str = r_bytes(arg);
+ VALUE str = r_bytes(arg);
- v = rb_path_to_class(str);
- prohibit_ivar("class/module", str);
- v = r_entry(v, arg);
- v = r_leave(v, arg);
- }
- break;
+ v = rb_path_to_class(str);
+ prohibit_ivar("class/module", str);
+ v = r_entry(v, arg);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_CLASS:
{
- VALUE str = r_bytes(arg);
+ VALUE str = r_bytes(arg);
- v = path2class(str);
- prohibit_ivar("class", str);
- v = r_entry(v, arg);
- v = r_leave(v, arg);
- }
- break;
+ v = path2class(str);
+ prohibit_ivar("class", str);
+ v = r_entry(v, arg);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_MODULE:
{
- VALUE str = r_bytes(arg);
+ VALUE str = r_bytes(arg);
- v = path2module(str);
- prohibit_ivar("module", str);
- v = r_entry(v, arg);
- v = r_leave(v, arg);
- }
- break;
+ v = path2module(str);
+ prohibit_ivar("module", str);
+ v = r_entry(v, arg);
+ v = r_leave(v, arg, partial);
+ }
+ break;
case TYPE_SYMBOL:
- if (ivp) {
- v = r_symreal(arg, *ivp);
- *ivp = FALSE;
- }
- else {
- v = r_symreal(arg, 0);
- }
- v = rb_str_intern(v);
- v = r_leave(v, arg);
- break;
+ if (ivp) {
+ v = r_symreal(arg, *ivp);
+ *ivp = FALSE;
+ }
+ else {
+ v = r_symreal(arg, 0);
+ }
+ v = rb_str_intern(v);
+ v = r_leave(v, arg, partial);
+ break;
case TYPE_SYMLINK:
- v = rb_str_intern(r_symlink(arg));
- break;
+ v = rb_str_intern(r_symlink(arg));
+ break;
default:
- rb_raise(rb_eArgError, "dump format error(0x%x)", type);
- break;
+ rb_raise(rb_eArgError, "dump format error(0x%x)", type);
+ break;
}
- if (v == Qundef) {
- rb_raise(rb_eArgError, "dump format error (bad link)");
+ if (UNDEF_P(v)) {
+ rb_raise(rb_eArgError, "dump format error (bad link)");
}
return v;
@@ -2104,15 +2288,15 @@ 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
clear_load_arg(struct load_arg *arg)
{
if (arg->buf) {
- xfree(arg->buf);
- arg->buf = 0;
+ xfree(arg->buf);
+ arg->buf = 0;
}
arg->buflen = 0;
arg->offset = 0;
@@ -2122,39 +2306,16 @@ clear_load_arg(struct load_arg *arg)
arg->symbols = 0;
st_free_table(arg->data);
arg->data = 0;
+ st_free_table(arg->partial_objects);
+ arg->partial_objects = 0;
if (arg->compat_tbl) {
- st_free_table(arg->compat_tbl);
- arg->compat_tbl = 0;
+ st_free_table(arg->compat_tbl);
+ arg->compat_tbl = 0;
}
}
-/*
- * call-seq:
- * load( source [, proc] ) -> obj
- * restore( source [, proc] ) -> obj
- *
- * Returns the result of converting the serialized data in source into a
- * Ruby object (possibly with associated subordinate objects). source
- * may be either an instance of IO or an object that responds to
- * to_str. If proc is specified, each object will be passed to the proc, as the object
- * is being deserialized.
- *
- * Never pass untrusted data (including user supplied input) to this method.
- * Please see the overview for further details.
- */
-static VALUE
-marshal_load(int argc, VALUE *argv, VALUE _)
-{
- VALUE port, proc;
-
- rb_check_arity(argc, 1, 2);
- port = argv[0];
- proc = argc > 1 ? argv[1] : Qnil;
- return rb_marshal_load_with_proc(port, proc);
-}
-
VALUE
-rb_marshal_load_with_proc(VALUE port, VALUE proc)
+rb_marshal_load_with_proc(VALUE port, VALUE proc, bool freeze)
{
int major, minor;
VALUE v;
@@ -2163,40 +2324,42 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc)
v = rb_check_string_type(port);
if (!NIL_P(v)) {
- port = v;
+ port = v;
}
else if (rb_respond_to(port, s_getbyte) && rb_respond_to(port, s_read)) {
- rb_check_funcall(port, s_binmode, 0, 0);
+ rb_check_funcall(port, s_binmode, 0, 0);
}
else {
- io_needed();
+ io_needed();
}
wrapper = TypedData_Make_Struct(0, struct load_arg, &load_arg_data, arg);
arg->src = port;
arg->offset = 0;
arg->symbols = st_init_numtable();
arg->data = rb_init_identtable();
+ arg->partial_objects = rb_init_identtable();
arg->compat_tbl = 0;
arg->proc = 0;
arg->readable = 0;
+ arg->freeze = freeze;
if (NIL_P(v))
- arg->buf = xmalloc(BUFSIZ);
+ arg->buf = xmalloc(BUFSIZ);
else
- arg->buf = 0;
+ arg->buf = 0;
major = r_byte(arg);
minor = r_byte(arg);
if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
- clear_load_arg(arg);
- rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
+ clear_load_arg(arg);
+ rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
\tformat version %d.%d required; %d.%d given",
- MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
+ MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
}
if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
- rb_warn("incompatible marshal file format (can be read)\n\
+ rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
- MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
+ MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
}
if (!NIL_P(proc)) arg->proc = proc;
@@ -2207,6 +2370,14 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc)
return v;
}
+static VALUE
+marshal_load(rb_execution_context_t *ec, VALUE mod, VALUE source, VALUE proc, VALUE freeze)
+{
+ return rb_marshal_load_with_proc(source, proc, RTEST(freeze));
+}
+
+#include "marshal.rbinc"
+
/*
* The marshaling library converts collections of Ruby objects into a
* byte stream, allowing them to be stored outside the currently
@@ -2339,8 +2510,6 @@ Init_marshal(void)
set_id(s_ruby2_keywords_flag);
rb_define_module_function(rb_mMarshal, "dump", marshal_dump, -1);
- rb_define_module_function(rb_mMarshal, "load", marshal_load, -1);
- rb_define_module_function(rb_mMarshal, "restore", marshal_load, -1);
/* major version */
rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
@@ -2356,7 +2525,7 @@ compat_allocator_table(void)
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
compat_allocator_tbl_wrapper =
- Data_Wrap_Struct(0, mark_marshal_compat_t, 0, compat_allocator_tbl);
+ Data_Wrap_Struct(0, mark_marshal_compat_t, 0, compat_allocator_tbl);
rb_gc_register_mark_object(compat_allocator_tbl_wrapper);
return compat_allocator_tbl;
}
@@ -2370,5 +2539,5 @@ rb_marshal_dump(VALUE obj, VALUE port)
VALUE
rb_marshal_load(VALUE port)
{
- return rb_marshal_load_with_proc(port, Qnil);
+ return rb_marshal_load_with_proc(port, Qnil, false);
}
diff --git a/marshal.rb b/marshal.rb
new file mode 100644
index 0000000000..9ff74dd8b2
--- /dev/null
+++ b/marshal.rb
@@ -0,0 +1,40 @@
+module Marshal
+ # call-seq:
+ # load(source, proc = nil, freeze: false) -> obj
+ # restore(source, proc = nil, freeze: false) -> obj
+ #
+ # Returns the result of converting the serialized data in source into a
+ # Ruby object (possibly with associated subordinate objects). source
+ # may be either an instance of IO or an object that responds to
+ # to_str. If proc is specified, each object will be passed to the proc, as the object
+ # is being deserialized.
+ #
+ # Never pass untrusted data (including user supplied input) to this method.
+ # Please see the overview for further details.
+ #
+ # If the <tt>freeze: true</tt> argument is passed, deserialized object would
+ # be deeply frozen. Note that it may lead to more efficient memory usage due to
+ # frozen strings deduplication:
+ #
+ # serialized = Marshal.dump(['value1', 'value2', 'value1', 'value2'])
+ #
+ # deserialized = Marshal.load(serialized)
+ # deserialized.map(&:frozen?)
+ # # => [false, false, false, false]
+ # deserialized.map(&:object_id)
+ # # => [1023900, 1023920, 1023940, 1023960] -- 4 different objects
+ #
+ # deserialized = Marshal.load(serialized, freeze: true)
+ # deserialized.map(&:frozen?)
+ # # => [true, true, true, true]
+ # deserialized.map(&:object_id)
+ # # => [1039360, 1039380, 1039360, 1039380] -- only 2 different objects, object_ids repeating
+ #
+ def self.load(source, proc = nil, freeze: false)
+ Primitive.marshal_load(source, proc, freeze)
+ end
+
+ class << self
+ alias restore load
+ end
+end
diff --git a/math.c b/math.c
index f0237d4fa9..67bf8b7b63 100644
--- a/math.c
+++ b/math.c
@@ -26,13 +26,6 @@
#include "internal/object.h"
#include "internal/vm.h"
-#if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
- !defined(signbit)
- extern int signbit(double);
-#endif
-
-#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM)
-
VALUE rb_mMath;
VALUE rb_eMathDomainError;
@@ -47,31 +40,21 @@ VALUE rb_eMathDomainError;
/*
* call-seq:
- * Math.atan2(y, x) -> Float
- *
- * Computes the arc tangent given +y+ and +x+.
- * Returns a Float in the range -PI..PI. Return value is a angle
- * in radians between the positive x-axis of cartesian plane
- * and the point given by the coordinates (+x+, +y+) on it.
- *
- * Domain: (-INFINITY, INFINITY)
- *
- * Codomain: [-PI, PI]
- *
- * Math.atan2(-0.0, -1.0) #=> -3.141592653589793
- * Math.atan2(-1.0, -1.0) #=> -2.356194490192345
- * Math.atan2(-1.0, 0.0) #=> -1.5707963267948966
- * Math.atan2(-1.0, 1.0) #=> -0.7853981633974483
- * Math.atan2(-0.0, 1.0) #=> -0.0
- * Math.atan2(0.0, 1.0) #=> 0.0
- * Math.atan2(1.0, 1.0) #=> 0.7853981633974483
- * Math.atan2(1.0, 0.0) #=> 1.5707963267948966
- * Math.atan2(1.0, -1.0) #=> 2.356194490192345
- * Math.atan2(0.0, -1.0) #=> 3.141592653589793
- * Math.atan2(INFINITY, INFINITY) #=> 0.7853981633974483
- * Math.atan2(INFINITY, -INFINITY) #=> 2.356194490192345
- * Math.atan2(-INFINITY, INFINITY) #=> -0.7853981633974483
- * Math.atan2(-INFINITY, -INFINITY) #=> -2.356194490192345
+ * Math.atan2(y, x) -> float
+ *
+ * Returns the {arc tangent}[https://en.wikipedia.org/wiki/Atan2] of +y+ and +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
+ *
+ * - Domain of +y+: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Domain of +x+: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-PI, PI]</tt>.
+ *
+ * Examples:
+ *
+ * atan2(-1.0, -1.0) # => -2.356194490192345 # -3*PI/4
+ * atan2(-1.0, 0.0) # => -1.5707963267948966 # -PI/2
+ * atan2(-1.0, 1.0) # => -0.7853981633974483 # -PI/4
+ * atan2(0.0, -1.0) # => 3.141592653589793 # PI
*
*/
@@ -82,23 +65,23 @@ math_atan2(VALUE unused_obj, VALUE y, VALUE x)
dx = Get_Double(x);
dy = Get_Double(y);
if (dx == 0.0 && dy == 0.0) {
- if (!signbit(dx))
- return DBL2NUM(dy);
+ if (!signbit(dx))
+ return DBL2NUM(dy);
if (!signbit(dy))
- return DBL2NUM(M_PI);
- return DBL2NUM(-M_PI);
+ return DBL2NUM(M_PI);
+ return DBL2NUM(-M_PI);
}
#ifndef ATAN2_INF_C99
if (isinf(dx) && isinf(dy)) {
- /* optimization for FLONUM */
- if (dx < 0.0) {
- const double dz = (3.0 * M_PI / 4.0);
- return (dy < 0.0) ? DBL2NUM(-dz) : DBL2NUM(dz);
- }
- else {
- const double dz = (M_PI / 4.0);
- return (dy < 0.0) ? DBL2NUM(-dz) : DBL2NUM(dz);
- }
+ /* optimization for FLONUM */
+ if (dx < 0.0) {
+ const double dz = (3.0 * M_PI / 4.0);
+ return (dy < 0.0) ? DBL2NUM(-dz) : DBL2NUM(dz);
+ }
+ else {
+ const double dz = (M_PI / 4.0);
+ return (dy < 0.0) ? DBL2NUM(-dz) : DBL2NUM(dz);
+ }
}
#endif
return DBL2NUM(atan2(dy, dx));
@@ -107,16 +90,22 @@ math_atan2(VALUE unused_obj, VALUE y, VALUE x)
/*
* call-seq:
- * Math.cos(x) -> Float
+ * Math.cos(x) -> float
*
- * Computes the cosine of +x+ (expressed in radians).
- * Returns a Float in the range -1.0..1.0.
+ * Returns the
+ * {cosine}[https://en.wikipedia.org/wiki/Sine_and_cosine] of +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>(-INFINITY, INFINITY)</tt>.
+ * - Range: <tt>[-1.0, 1.0]</tt>.
*
- * Codomain: [-1, 1]
+ * Examples:
*
- * Math.cos(Math::PI) #=> -1.0
+ * cos(-PI) # => -1.0
+ * cos(-PI/2) # => 6.123031769111886e-17 # 0.0000000000000001
+ * cos(0.0) # => 1.0
+ * cos(PI/2) # => 6.123031769111886e-17 # 0.0000000000000001
+ * cos(PI) # => -1.0
*
*/
@@ -128,16 +117,22 @@ math_cos(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.sin(x) -> Float
+ * Math.sin(x) -> float
*
- * Computes the sine of +x+ (expressed in radians).
- * Returns a Float in the range -1.0..1.0.
+ * Returns the
+ * {sine}[https://en.wikipedia.org/wiki/Sine_and_cosine] of +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>(-INFINITY, INFINITY)</tt>.
+ * - Range: <tt>[-1.0, 1.0]</tt>.
*
- * Codomain: [-1, 1]
+ * Examples:
*
- * Math.sin(Math::PI/2) #=> 1.0
+ * sin(-PI) # => -1.2246063538223773e-16 # -0.0000000000000001
+ * sin(-PI/2) # => -1.0
+ * sin(0.0) # => 0.0
+ * sin(PI/2) # => 1.0
+ * sin(PI) # => 1.2246063538223773e-16 # 0.0000000000000001
*
*/
@@ -150,15 +145,22 @@ math_sin(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.tan(x) -> Float
+ * Math.tan(x) -> float
*
- * Computes the tangent of +x+ (expressed in radians).
+ * Returns the
+ * {tangent}[https://en.wikipedia.org/wiki/Trigonometric_functions] of +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>(-INFINITY, INFINITY)</tt>.
+ * - Range: <tt>(-INFINITY, INFINITY)</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.tan(0) #=> 0.0
+ * tan(-PI) # => 1.2246467991473532e-16 # -0.0000000000000001
+ * tan(-PI/2) # => -1.633123935319537e+16 # -16331239353195370.0
+ * tan(0.0) # => 0.0
+ * tan(PI/2) # => 1.633123935319537e+16 # 16331239353195370.0
+ * tan(PI) # => -1.2246467991473532e-16 # -0.0000000000000001
*
*/
@@ -170,15 +172,18 @@ math_tan(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.acos(x) -> Float
+ * Math.acos(x) -> float
*
- * Computes the arc cosine of +x+. Returns 0..PI.
+ * Returns the {arc cosine}[https://en.wikipedia.org/wiki/Inverse_trigonometric_functions] of +x+.
*
- * Domain: [-1, 1]
+ * - Domain: <tt>[-1, 1]</tt>.
+ * - Range: <tt>[0, PI]</tt>.
*
- * Codomain: [0, PI]
+ * Examples:
*
- * Math.acos(0) == Math::PI/2 #=> true
+ * acos(-1.0) # => 3.141592653589793 # PI
+ * acos(0.0) # => 1.5707963267948966 # PI/2
+ * acos(1.0) # => 0.0
*
*/
@@ -194,15 +199,19 @@ math_acos(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.asin(x) -> Float
+ * Math.asin(x) -> float
+ *
+ * Returns the {arc sine}[https://en.wikipedia.org/wiki/Inverse_trigonometric_functions] of +x+.
*
- * Computes the arc sine of +x+. Returns -PI/2..PI/2.
+ * - Domain: <tt>[-1, -1]</tt>.
+ * - Range: <tt>[-PI/2, PI/2]</tt>.
*
- * Domain: [-1, -1]
+ * Examples:
*
- * Codomain: [-PI/2, PI/2]
+ * asin(-1.0) # => -1.5707963267948966 # -PI/2
+ * asin(0.0) # => 0.0
+ * asin(1.0) # => 1.5707963267948966 # PI/2
*
- * Math.asin(1) == Math::PI/2 #=> true
*/
static VALUE
@@ -219,13 +228,21 @@ math_asin(VALUE unused_obj, VALUE x)
* call-seq:
* Math.atan(x) -> Float
*
- * Computes the arc tangent of +x+. Returns -PI/2..PI/2.
+ * Returns the {arc tangent}[https://en.wikipedia.org/wiki/Inverse_trigonometric_functions] of +x+.
+ *
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-PI/2, PI/2] </tt>.
*
- * Domain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Codomain: (-PI/2, PI/2)
+ * atan(-INFINITY) # => -1.5707963267948966 # -PI2
+ * atan(-PI) # => -1.2626272556789115
+ * atan(-PI/2) # => -1.0038848218538872
+ * atan(0.0) # => 0.0
+ * atan(PI/2) # => 1.0038848218538872
+ * atan(PI) # => 1.2626272556789115
+ * atan(INFINITY) # => 1.5707963267948966 # PI/2
*
- * Math.atan(0) #=> 0.0
*/
static VALUE
@@ -244,15 +261,19 @@ cosh(double x)
/*
* call-seq:
- * Math.cosh(x) -> Float
+ * Math.cosh(x) -> float
*
- * Computes the hyperbolic cosine of +x+ (expressed in radians).
+ * Returns the {hyperbolic cosine}[https://en.wikipedia.org/wiki/Hyperbolic_functions] of +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[1, INFINITY]</tt>.
*
- * Codomain: [1, INFINITY)
+ * Examples:
*
- * Math.cosh(0) #=> 1.0
+ * cosh(-INFINITY) # => Infinity
+ * cosh(0.0) # => 1.0
+ * cosh(INFINITY) # => Infinity
*
*/
@@ -272,15 +293,19 @@ sinh(double x)
/*
* call-seq:
- * Math.sinh(x) -> Float
+ * Math.sinh(x) -> float
*
- * Computes the hyperbolic sine of +x+ (expressed in radians).
+ * Returns the {hyperbolic sine}[https://en.wikipedia.org/wiki/Hyperbolic_functions] of +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.sinh(0) #=> 0.0
+ * sinh(-INFINITY) # => -Infinity
+ * sinh(0.0) # => 0.0
+ * sinh(INFINITY) # => Infinity
*
*/
@@ -307,15 +332,19 @@ tanh(double x)
/*
* call-seq:
- * Math.tanh(x) -> Float
+ * Math.tanh(x) -> float
*
- * Computes the hyperbolic tangent of +x+ (expressed in radians).
+ * Returns the {hyperbolic tangent}[https://en.wikipedia.org/wiki/Hyperbolic_functions] of +x+
+ * in {radians}[https://en.wikipedia.org/wiki/Trigonometric_functions#Radians_versus_degrees].
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-1, 1]</tt>.
*
- * Codomain: (-1, 1)
+ * Examples:
*
- * Math.tanh(0) #=> 0.0
+ * tanh(-INFINITY) # => -1.0
+ * tanh(0.0) # => 0.0
+ * tanh(INFINITY) # => 1.0
*
*/
@@ -327,15 +356,17 @@ math_tanh(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.acosh(x) -> Float
+ * Math.acosh(x) -> float
*
- * Computes the inverse hyperbolic cosine of +x+.
+ * Returns the {inverse hyperbolic cosine}[https://en.wikipedia.org/wiki/Inverse_hyperbolic_functions] of +x+.
*
- * Domain: [1, INFINITY)
+ * - Domain: <tt>[1, INFINITY]</tt>.
+ * - Range: <tt>[0, INFINITY]</tt>.
*
- * Codomain: [0, INFINITY)
+ * Examples:
*
- * Math.acosh(1) #=> 0.0
+ * acosh(1.0) # => 0.0
+ * acosh(INFINITY) # => Infinity
*
*/
@@ -351,15 +382,18 @@ math_acosh(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.asinh(x) -> Float
+ * Math.asinh(x) -> float
*
- * Computes the inverse hyperbolic sine of +x+.
+ * Returns the {inverse hyperbolic sine}[https://en.wikipedia.org/wiki/Inverse_hyperbolic_functions] of +x+.
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.asinh(1) #=> 0.881373587019543
+ * asinh(-INFINITY) # => -Infinity
+ * asinh(0.0) # => 0.0
+ * asinh(INFINITY) # => Infinity
*
*/
@@ -371,15 +405,18 @@ math_asinh(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.atanh(x) -> Float
+ * Math.atanh(x) -> float
*
- * Computes the inverse hyperbolic tangent of +x+.
+ * Returns the {inverse hyperbolic tangent}[https://en.wikipedia.org/wiki/Inverse_hyperbolic_functions] of +x+.
*
- * Domain: (-1, 1)
+ * - Domain: <tt>[-1, 1]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.atanh(1) #=> Infinity
+ * atanh(-1.0) # => -Infinity
+ * atanh(0.0) # => 0.0
+ * atanh(1.0) # => Infinity
*
*/
@@ -398,17 +435,22 @@ math_atanh(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.exp(x) -> Float
+ * Math.exp(x) -> float
*
- * Returns e**x.
+ * Returns +e+ raised to the +x+ power.
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[0, INFINITY]</tt>.
*
- * Codomain: (0, INFINITY)
+ * Examples:
*
- * Math.exp(0) #=> 1.0
- * Math.exp(1) #=> 2.718281828459045
- * Math.exp(1.5) #=> 4.4816890703380645
+ * exp(-INFINITY) # => 0.0
+ * exp(-1.0) # => 0.36787944117144233 # 1.0/E
+ * exp(0.0) # => 1.0
+ * exp(0.5) # => 1.6487212707001282 # sqrt(E)
+ * exp(1.0) # => 2.718281828459045 # E
+ * exp(2.0) # => 7.38905609893065 # E**2
+ * exp(INFINITY) # => Infinity
*
*/
@@ -439,22 +481,27 @@ FUNC_MINIMIZED(static VALUE math_log(int, const VALUE *, VALUE));
/*
* call-seq:
- * Math.log(x) -> Float
- * Math.log(x, base) -> Float
+ * Math.log(x, base = Math::E) -> Float
*
- * Returns the logarithm of +x+.
- * If additional second argument is given, it will be the base
- * of logarithm. Otherwise it is +e+ (for the natural logarithm).
+ * Returns the base +base+ {logarithm}[https://en.wikipedia.org/wiki/Logarithm] of +x+.
*
- * Domain: (0, INFINITY)
+ * - Domain: <tt>[0, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY)]</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.log(0) #=> -Infinity
- * Math.log(1) #=> 0.0
- * Math.log(Math::E) #=> 1.0
- * Math.log(Math::E**3) #=> 3.0
- * Math.log(12, 3) #=> 2.2618595071429146
+ * log(0.0) # => -Infinity
+ * log(1.0) # => 0.0
+ * log(E) # => 1.0
+ * log(INFINITY) # => Infinity
+ *
+ * log(0.0, 2.0) # => -Infinity
+ * log(1.0, 2.0) # => 0.0
+ * log(2.0, 2.0) # => 1.0
+ *
+ * log(0.0, 10.0) # => -Infinity
+ * log(1.0, 10.0) # => 0.0
+ * log(10.0, 10.0) # => 1.0
*
*/
@@ -473,7 +520,7 @@ rb_math_log(int argc, const VALUE *argv)
rb_scan_args(argc, argv, "11", &x, &base);
d = math_log1(x);
if (argc == 2) {
- d /= math_log1(base);
+ d /= math_log1(base);
}
return DBL2NUM(d);
}
@@ -489,7 +536,7 @@ get_double_rshift(VALUE x, size_t *pnumbits)
x = rb_big_rshift(x, SIZET2NUM(numbits));
}
else {
- numbits = 0;
+ numbits = 0;
}
*pnumbits = numbits;
return Get_Double(x);
@@ -522,18 +569,19 @@ extern double log2(double);
/*
* call-seq:
- * Math.log2(x) -> Float
+ * Math.log2(x) -> float
*
- * Returns the base 2 logarithm of +x+.
+ * Returns the base 2 {logarithm}[https://en.wikipedia.org/wiki/Logarithm] of +x+.
*
- * Domain: (0, INFINITY)
+ * - Domain: <tt>[0, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.log2(1) #=> 0.0
- * Math.log2(2) #=> 1.0
- * Math.log2(32768) #=> 15.0
- * Math.log2(65536) #=> 16.0
+ * log2(0.0) # => -Infinity
+ * log2(1.0) # => 0.0
+ * log2(2.0) # => 1.0
+ * log2(INFINITY) # => Infinity
*
*/
@@ -552,17 +600,19 @@ math_log2(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.log10(x) -> Float
+ * Math.log10(x) -> float
*
- * Returns the base 10 logarithm of +x+.
+ * Returns the base 10 {logarithm}[https://en.wikipedia.org/wiki/Logarithm] of +x+.
*
- * Domain: (0, INFINITY)
+ * - Domain: <tt>[0, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
*
- * Codomain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Math.log10(1) #=> 0.0
- * Math.log10(10) #=> 1.0
- * Math.log10(10**100) #=> 100.0
+ * log10(0.0) # => -Infinity
+ * log10(1.0) # => 0.0
+ * log10(10.0) # => 1.0
+ * log10(INFINITY) # => Infinity
*
*/
@@ -583,35 +633,23 @@ static VALUE rb_math_sqrt(VALUE x);
/*
* call-seq:
- * Math.sqrt(x) -> Float
- *
- * Returns the non-negative square root of +x+.
+ * Math.sqrt(x) -> float
*
- * Domain: [0, INFINITY)
+ * Returns the principal (non-negative) {square root}[https://en.wikipedia.org/wiki/Square_root] of +x+.
*
- * Codomain:[0, INFINITY)
+ * - Domain: <tt>[0, INFINITY]</tt>.
+ * - Range: <tt>[0, INFINITY]</tt>.
*
- * 0.upto(10) {|x|
- * p [x, Math.sqrt(x), Math.sqrt(x)**2]
- * }
- * #=> [0, 0.0, 0.0]
- * # [1, 1.0, 1.0]
- * # [2, 1.4142135623731, 2.0]
- * # [3, 1.73205080756888, 3.0]
- * # [4, 2.0, 4.0]
- * # [5, 2.23606797749979, 5.0]
- * # [6, 2.44948974278318, 6.0]
- * # [7, 2.64575131106459, 7.0]
- * # [8, 2.82842712474619, 8.0]
- * # [9, 3.0, 9.0]
- * # [10, 3.16227766016838, 10.0]
+ * Examples:
*
- * Note that the limited precision of floating point arithmetic
- * might lead to surprising results:
+ * sqrt(0.0) # => 0.0
+ * sqrt(0.5) # => 0.7071067811865476
+ * sqrt(1.0) # => 1.0
+ * sqrt(2.0) # => 1.4142135623730951
+ * sqrt(4.0) # => 2.0
+ * sqrt(9.0) # => 3.0
+ * sqrt(INFINITY) # => Infinity
*
- * Math.sqrt(10**46).to_i #=> 99999999999999991611392 (!)
- *
- * See also BigDecimal#sqrt and Integer.sqrt.
*/
static VALUE
@@ -620,20 +658,19 @@ math_sqrt(VALUE unused_obj, VALUE x)
return rb_math_sqrt(x);
}
-#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
inline static VALUE
f_negative_p(VALUE x)
{
if (FIXNUM_P(x))
- return f_boolcast(FIX2LONG(x) < 0);
+ return RBOOL(FIX2LONG(x) < 0);
return rb_funcall(x, '<', 1, INT2FIX(0));
}
inline static VALUE
f_signbit(VALUE x)
{
- if (RB_TYPE_P(x, T_FLOAT)) {
+ if (RB_FLOAT_TYPE_P(x)) {
double f = RFLOAT_VALUE(x);
- return f_boolcast(!isnan(f) && signbit(f));
+ return RBOOL(!isnan(f) && signbit(f));
}
return f_negative_p(x);
}
@@ -644,13 +681,13 @@ rb_math_sqrt(VALUE x)
double d;
if (RB_TYPE_P(x, T_COMPLEX)) {
- VALUE neg = f_signbit(RCOMPLEX(x)->imag);
- double re = Get_Double(RCOMPLEX(x)->real), im;
- d = Get_Double(rb_complex_abs(x));
- im = sqrt((d - re) / 2.0);
- re = sqrt((d + re) / 2.0);
- if (neg) im = -im;
- return rb_complex_new(DBL2NUM(re), DBL2NUM(im));
+ VALUE neg = f_signbit(RCOMPLEX(x)->imag);
+ double re = Get_Double(RCOMPLEX(x)->real), im;
+ d = Get_Double(rb_complex_abs(x));
+ im = sqrt((d - re) / 2.0);
+ re = sqrt((d + re) / 2.0);
+ if (neg) im = -im;
+ return rb_complex_new(DBL2NUM(re), DBL2NUM(im));
}
d = Get_Double(x);
domain_check_min(d, 0.0, "sqrt");
@@ -660,36 +697,26 @@ rb_math_sqrt(VALUE x)
/*
* call-seq:
- * Math.cbrt(x) -> Float
- *
- * Returns the cube root of +x+.
- *
- * Domain: (-INFINITY, INFINITY)
- *
- * Codomain: (-INFINITY, INFINITY)
- *
- * -9.upto(9) {|x|
- * p [x, Math.cbrt(x), Math.cbrt(x)**3]
- * }
- * #=> [-9, -2.0800838230519, -9.0]
- * # [-8, -2.0, -8.0]
- * # [-7, -1.91293118277239, -7.0]
- * # [-6, -1.81712059283214, -6.0]
- * # [-5, -1.7099759466767, -5.0]
- * # [-4, -1.5874010519682, -4.0]
- * # [-3, -1.44224957030741, -3.0]
- * # [-2, -1.25992104989487, -2.0]
- * # [-1, -1.0, -1.0]
- * # [0, 0.0, 0.0]
- * # [1, 1.0, 1.0]
- * # [2, 1.25992104989487, 2.0]
- * # [3, 1.44224957030741, 3.0]
- * # [4, 1.5874010519682, 4.0]
- * # [5, 1.7099759466767, 5.0]
- * # [6, 1.81712059283214, 6.0]
- * # [7, 1.91293118277239, 7.0]
- * # [8, 2.0, 8.0]
- * # [9, 2.0800838230519, 9.0]
+ * Math.cbrt(x) -> float
+ *
+ * Returns the {cube root}[https://en.wikipedia.org/wiki/Cube_root] of +x+.
+ *
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
+ *
+ * Examples:
+ *
+ * cbrt(-INFINITY) # => -Infinity
+ * cbrt(-27.0) # => -3.0
+ * cbrt(-8.0) # => -2.0
+ * cbrt(-2.0) # => -1.2599210498948732
+ * cbrt(1.0) # => 1.0
+ * cbrt(0.0) # => 0.0
+ * cbrt(1.0) # => 1.0
+ cbrt(2.0) # => 1.2599210498948732
+ * cbrt(8.0) # => 2.0
+ * cbrt(27.0) # => 3.0
+ * cbrt(INFINITY) # => Infinity
*
*/
@@ -700,7 +727,7 @@ math_cbrt(VALUE unused_obj, VALUE x)
double r = cbrt(f);
#if defined __GLIBC__
if (isfinite(r) && !(f == 0.0 && r == 0.0)) {
- r = (2.0 * r + (f / r / r)) / 3.0;
+ r = (2.0 * r + (f / r / r)) / 3.0;
}
#endif
return DBL2NUM(r);
@@ -708,13 +735,30 @@ math_cbrt(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.frexp(x) -> [fraction, exponent]
+ * Math.frexp(x) -> [fraction, exponent]
+ *
+ * Returns a 2-element array containing the normalized signed float +fraction+
+ * and integer +exponent+ of +x+ such that:
+ *
+ * x = fraction * 2**exponent
+ *
+ * See {IEEE 754 double-precision binary floating-point format: binary64}[https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64].
+ *
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range <tt>[-INFINITY, INFINITY]</tt>.
+ *
+ * Examples:
+ *
+ * frexp(-INFINITY) # => [-Infinity, -1]
+ * frexp(-2.0) # => [-0.5, 2]
+ * frexp(-1.0) # => [-0.5, 1]
+ * frexp(0.0) # => [0.0, 0]
+ * frexp(1.0) # => [0.5, 1]
+ * frexp(2.0) # => [0.5, 2]
+ * frexp(INFINITY) # => [Infinity, -1]
*
- * Returns a two-element array containing the normalized fraction (a Float)
- * and exponent (an Integer) of +x+.
+ * Related: Math.ldexp (inverse of Math.frexp).
*
- * fraction, exponent = Math.frexp(1234) #=> [0.6025390625, 11]
- * fraction * 2**exponent #=> 1234.0
*/
static VALUE
@@ -729,12 +773,28 @@ math_frexp(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.ldexp(fraction, exponent) -> float
+ * Math.ldexp(fraction, exponent) -> float
*
- * Returns the value of +fraction+*(2**+exponent+).
+ * Returns the value of <tt>fraction * 2**exponent</tt>.
+ *
+ * - Domain of +fraction+: <tt>[0.0, 1.0)</tt>.
+ * - Domain of +exponent+: <tt>[0, 1024]</tt>
+ * (larger values are equivalent to 1024).
+ *
+ * See {IEEE 754 double-precision binary floating-point format: binary64}[https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64].
+ *
+ * Examples:
+ *
+ * ldexp(-INFINITY, -1) # => -Infinity
+ * ldexp(-0.5, 2) # => -2.0
+ * ldexp(-0.5, 1) # => -1.0
+ * ldexp(0.0, 0) # => 0.0
+ * ldexp(-0.5, 1) # => 1.0
+ * ldexp(-0.5, 2) # => 2.0
+ * ldexp(INFINITY, -1) # => Infinity
+ *
+ * Related: Math.frexp (inverse of Math.ldexp).
*
- * fraction, exponent = Math.frexp(1234)
- * Math.ldexp(fraction, exponent) #=> 1234.0
*/
static VALUE
@@ -745,12 +805,27 @@ math_ldexp(VALUE unused_obj, VALUE x, VALUE n)
/*
* call-seq:
- * Math.hypot(x, y) -> Float
+ * Math.hypot(a, b) -> float
+ *
+ * Returns <tt>sqrt(a**2 + b**2)</tt>,
+ * which is the length of the longest side +c+ (the hypotenuse)
+ * of the right triangle whose other sides have lengths +a+ and +b+.
*
- * Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle with
- * sides +x+ and +y+.
+ * - Domain of +a+: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Domain of +ab: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[0, INFINITY]</tt>.
+ *
+ * Examples:
+ *
+ * hypot(0.0, 1.0) # => 1.0
+ * hypot(1.0, 1.0) # => 1.4142135623730951 # sqrt(2.0)
+ * hypot(3.0, 4.0) # => 5.0
+ * hypot(5.0, 12.0) # => 13.0
+ * hypot(1.0, sqrt(3.0)) # => 1.9999999999999998 # Near 2.0
+ *
+ * Note that if either argument is +INFINITY+ or <tt>-INFINITY</tt>,
+ * the result is +Infinity+.
*
- * Math.hypot(3, 4) #=> 5.0
*/
static VALUE
@@ -761,15 +836,20 @@ math_hypot(VALUE unused_obj, VALUE x, VALUE y)
/*
* call-seq:
- * Math.erf(x) -> Float
+ * Math.erf(x) -> float
*
- * Calculates the error function of +x+.
+ * Returns the value of the {Gauss error function}[https://en.wikipedia.org/wiki/Error_function] for +x+.
*
- * Domain: (-INFINITY, INFINITY)
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-1, 1]</tt>.
*
- * Codomain: (-1, 1)
+ * Examples:
*
- * Math.erf(0) #=> 0.0
+ * erf(-INFINITY) # => -1.0
+ * erf(0.0) # => 0.0
+ * erf(INFINITY) # => 1.0
+ *
+ * Related: Math.erfc.
*
*/
@@ -783,13 +863,18 @@ math_erf(VALUE unused_obj, VALUE x)
* call-seq:
* Math.erfc(x) -> Float
*
- * Calculates the complementary error function of x.
+ * Returns the value of the {complementary error function}[https://en.wikipedia.org/wiki/Error_function#Complementary_error_function] for +x+.
+ *
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[0, 2]</tt>.
*
- * Domain: (-INFINITY, INFINITY)
+ * Examples:
*
- * Codomain: (0, 2)
+ * erfc(-INFINITY) # => 2.0
+ * erfc(0.0) # => 1.0
+ * erfc(INFINITY) # => 0.0
*
- * Math.erfc(0) #=> 1.0
+ * Related: Math.erf.
*
*/
@@ -801,41 +886,26 @@ math_erfc(VALUE unused_obj, VALUE x)
/*
* call-seq:
- * Math.gamma(x) -> Float
- *
- * Calculates the gamma function of x.
- *
- * Note that gamma(n) is the same as fact(n-1) for integer n > 0.
- * However gamma(n) returns float and can be an approximation.
- *
- * def fact(n) (1..n).inject(1) {|r,i| r*i } end
- * 1.upto(26) {|i| p [i, Math.gamma(i), fact(i-1)] }
- * #=> [1, 1.0, 1]
- * # [2, 1.0, 1]
- * # [3, 2.0, 2]
- * # [4, 6.0, 6]
- * # [5, 24.0, 24]
- * # [6, 120.0, 120]
- * # [7, 720.0, 720]
- * # [8, 5040.0, 5040]
- * # [9, 40320.0, 40320]
- * # [10, 362880.0, 362880]
- * # [11, 3628800.0, 3628800]
- * # [12, 39916800.0, 39916800]
- * # [13, 479001600.0, 479001600]
- * # [14, 6227020800.0, 6227020800]
- * # [15, 87178291200.0, 87178291200]
- * # [16, 1307674368000.0, 1307674368000]
- * # [17, 20922789888000.0, 20922789888000]
- * # [18, 355687428096000.0, 355687428096000]
- * # [19, 6.402373705728e+15, 6402373705728000]
- * # [20, 1.21645100408832e+17, 121645100408832000]
- * # [21, 2.43290200817664e+18, 2432902008176640000]
- * # [22, 5.109094217170944e+19, 51090942171709440000]
- * # [23, 1.1240007277776077e+21, 1124000727777607680000]
- * # [24, 2.5852016738885062e+22, 25852016738884976640000]
- * # [25, 6.204484017332391e+23, 620448401733239439360000]
- * # [26, 1.5511210043330954e+25, 15511210043330985984000000]
+ * Math.gamma(x) -> float
+ *
+ * Returns the value of the {gamma function}[https://en.wikipedia.org/wiki/Gamma_function] for +x+.
+ *
+ * - Domain: <tt>(-INFINITY, INFINITY]</tt> excluding negative integers.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
+ *
+ * Examples:
+ *
+ * gamma(-2.5) # => -0.9453087204829431
+ * gamma(-1.5) # => 2.3632718012073513
+ * gamma(-0.5) # => -3.5449077018110375
+ * gamma(0.0) # => Infinity
+ * gamma(1.0) # => 1.0
+ * gamma(2.0) # => 1.0
+ * gamma(3.0) # => 2.0
+ * gamma(4.0) # => 6.0
+ * gamma(5.0) # => 24.0
+ *
+ * Related: Math.lgamma.
*
*/
@@ -875,32 +945,56 @@ math_gamma(VALUE unused_obj, VALUE x)
d = Get_Double(x);
/* check for domain error */
if (isinf(d)) {
- if (signbit(d)) domain_error("gamma");
- return DBL2NUM(HUGE_VAL);
+ if (signbit(d)) domain_error("gamma");
+ return DBL2NUM(HUGE_VAL);
}
if (d == 0.0) {
- return signbit(d) ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
+ return signbit(d) ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
}
if (d == floor(d)) {
- domain_check_min(d, 0.0, "gamma");
- if (1.0 <= d && d <= (double)NFACT_TABLE) {
- return DBL2NUM(fact_table[(int)d - 1]);
- }
+ domain_check_min(d, 0.0, "gamma");
+ if (1.0 <= d && d <= (double)NFACT_TABLE) {
+ return DBL2NUM(fact_table[(int)d - 1]);
+ }
}
return DBL2NUM(tgamma(d));
}
/*
* call-seq:
- * Math.lgamma(x) -> [float, -1 or 1]
+ * Math.lgamma(x) -> [float, -1 or 1]
+ *
+ * Returns a 2-element array equivalent to:
+ *
+ * [Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1]
+ *
+ * See {logarithmic gamma function}[https://en.wikipedia.org/wiki/Gamma_function#The_log-gamma_function].
+ *
+ * - Domain: <tt>(-INFINITY, INFINITY]</tt>.
+ * - Range of first element: <tt>(-INFINITY, INFINITY]</tt>.
+ * - Second element is -1 or 1.
+ *
+ * Examples:
+ *
+ * lgamma(-4.0) # => [Infinity, -1]
+ * lgamma(-3.0) # => [Infinity, -1]
+ * lgamma(-2.0) # => [Infinity, -1]
+ * lgamma(-1.0) # => [Infinity, -1]
+ * lgamma(0.0) # => [Infinity, 1]
*
- * Calculates the logarithmic gamma of +x+ and the sign of gamma of +x+.
+ * lgamma(1.0) # => [0.0, 1]
+ * lgamma(2.0) # => [0.0, 1]
+ * lgamma(3.0) # => [0.6931471805599436, 1]
+ * lgamma(4.0) # => [1.7917594692280545, 1]
*
- * Math.lgamma(x) is the same as
- * [Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1]
- * but avoids overflow by Math.gamma(x) for large x.
+ * lgamma(-2.5) # => [-0.05624371649767279, -1]
+ * lgamma(-1.5) # => [0.8600470153764797, 1]
+ * lgamma(-0.5) # => [1.265512123484647, -1]
+ * lgamma(0.5) # => [0.5723649429247004, 1]
+ * lgamma(1.5) # => [-0.12078223763524676, 1]
+ * lgamma(2.5) # => [0.2846828704729205, 1]
*
- * Math.lgamma(0) #=> [Infinity, 1]
+ * Related: Math.gamma.
*
*/
@@ -913,12 +1007,12 @@ math_lgamma(VALUE unused_obj, VALUE x)
d = Get_Double(x);
/* check for domain error */
if (isinf(d)) {
- if (signbit(d)) domain_error("lgamma");
- return rb_assoc_new(DBL2NUM(HUGE_VAL), INT2FIX(1));
+ if (signbit(d)) domain_error("lgamma");
+ return rb_assoc_new(DBL2NUM(HUGE_VAL), INT2FIX(1));
}
if (d == 0.0) {
- VALUE vsign = signbit(d) ? INT2FIX(-1) : INT2FIX(+1);
- return rb_assoc_new(DBL2NUM(HUGE_VAL), vsign);
+ VALUE vsign = signbit(d) ? INT2FIX(-1) : INT2FIX(+1);
+ return rb_assoc_new(DBL2NUM(HUGE_VAL), vsign);
}
v = DBL2NUM(lgamma_r(d, &sign));
return rb_assoc_new(v, INT2FIX(sign));
@@ -970,12 +1064,8 @@ exp1(sqrt)
/*
* Document-class: Math
*
- * The Math module contains module functions for basic
- * trigonometric and transcendental functions. See class
- * Float for a list of constants that
- * define Ruby's floating point accuracy.
+ * :include: doc/math/math.rdoc
*
- * Domains and codomains are given only for real (not complex) numbers.
*/
diff --git a/memory_view.c b/memory_view.c
index 6e422c1476..3fb79202f9 100644
--- a/memory_view.c
+++ b/memory_view.c
@@ -9,8 +9,8 @@
#include "internal.h"
#include "internal/hash.h"
#include "internal/variable.h"
-#include "internal/util.h"
#include "ruby/memory_view.h"
+#include "ruby/util.h"
#include "vm_sync.h"
#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
@@ -61,9 +61,9 @@ exported_object_registry_free(void *ptr)
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,
+ exported_object_registry_mark,
+ exported_object_registry_free,
+ 0,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -108,7 +108,8 @@ 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);
+ if (exported_object_table)
+ st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0);
RB_VM_LOCK_LEAVE();
}
@@ -119,9 +120,9 @@ static ID id_memory_view;
static const rb_data_type_t memory_view_entry_data_type = {
"memory_view/entry",
{
- 0,
- 0,
- 0,
+ 0,
+ 0,
+ 0,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -210,7 +211,7 @@ rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data,
view->shape = NULL;
view->strides = NULL;
view->sub_offsets = NULL;
- *((void **)&view->private) = NULL;
+ view->private_data = NULL;
return true;
}
@@ -783,7 +784,7 @@ 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);
+ klass = rb_class_superclass(klass);
if (klass == rb_cBasicObject || klass == rb_cObject)
return NULL;
@@ -822,6 +823,7 @@ rb_memory_view_get(VALUE obj, rb_memory_view_t* view, int flags)
bool rv = (*entry->get_func)(obj, view, flags);
if (rv) {
+ view->_memory_view_entry = entry;
register_exported_object(view->obj);
}
return rv;
@@ -834,8 +836,7 @@ rb_memory_view_get(VALUE obj, rb_memory_view_t* view, int flags)
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);
+ const rb_memory_view_entry_t *entry = view->_memory_view_entry;
if (entry) {
bool rv = true;
if (entry->release_func) {
diff --git a/method.h b/method.h
index 5b6fe2d800..ec89bf26bb 100644
--- a/method.h
+++ b/method.h
@@ -44,7 +44,7 @@ typedef struct rb_scope_visi_struct {
typedef struct rb_cref_struct {
VALUE flags;
VALUE refinements;
- VALUE klass;
+ VALUE klass_or_self;
struct rb_cref_struct * next;
const rb_scope_visibility_t scope_visi;
} rb_cref_t;
@@ -75,7 +75,6 @@ typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_e
#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)
@@ -102,8 +101,9 @@ static inline void
METHOD_ENTRY_FLAGS_COPY(rb_method_entry_t *dst, const rb_method_entry_t *src)
{
dst->flags =
- (dst->flags & ~(IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2)) |
- (src->flags & (IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2));
+ (dst->flags & ~(IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2
+ |IMEMO_FL_USER3)) |
+ (src->flags & (IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2|IMEMO_FL_USER3));
}
typedef enum {
@@ -132,7 +132,7 @@ typedef struct rb_iseq_struct rb_iseq_t;
#endif
typedef struct rb_method_iseq_struct {
- rb_iseq_t * iseqptr; /*!< iseq pointer, should be separated from iseqval */
+ const rb_iseq_t * iseqptr; /*!< iseq pointer, should be separated from iseqval */
rb_cref_t * cref; /*!< class reference, should be marked */
} rb_method_iseq_t; /* check rb_add_method_iseq() when modify the fields */
@@ -166,13 +166,22 @@ enum method_optimized_type {
OPTIMIZED_METHOD_TYPE_SEND,
OPTIMIZED_METHOD_TYPE_CALL,
OPTIMIZED_METHOD_TYPE_BLOCK_CALL,
+ OPTIMIZED_METHOD_TYPE_STRUCT_AREF,
+ OPTIMIZED_METHOD_TYPE_STRUCT_ASET,
OPTIMIZED_METHOD_TYPE__MAX
};
+typedef struct rb_method_optimized {
+ enum method_optimized_type type;
+ unsigned int index;
+} rb_method_optimized_t;
+
struct rb_method_definition_struct {
BITFIELD(rb_method_type_t, type, VM_METHOD_TYPE_MINIMUM_BITS);
- int alias_count : 28;
- int complemented_count : 28;
+ unsigned int iseq_overload: 1;
+ unsigned int no_redef_warning: 1;
+ unsigned int aliased : 1;
+ int reference_count : 28;
union {
rb_method_iseq_t iseq;
@@ -181,8 +190,7 @@ struct rb_method_definition_struct {
rb_method_alias_t alias;
rb_method_refined_t refined;
rb_method_bmethod_t bmethod;
-
- enum method_optimized_type optimize_type;
+ rb_method_optimized_t optimized;
} body;
ID original_id;
@@ -199,13 +207,14 @@ STATIC_ASSERT(sizeof_method_def, offsetof(rb_method_definition_t, body)==8);
((def)->type == VM_METHOD_TYPE_REFINED && \
UNDEFINED_METHOD_ENTRY_P((def)->body.refined.orig_me))
+void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi);
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi);
void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi);
+void rb_add_method_optimized(VALUE klass, ID mid, enum method_optimized_type, unsigned int index, rb_method_visibility_t visi);
void rb_add_refined_method_entry(VALUE refined_class, ID mid);
-void rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi);
rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_visibility_t noex);
-rb_method_entry_t *rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def);
+rb_method_entry_t *rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, rb_method_definition_t *def);
const rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id);
@@ -218,6 +227,7 @@ const rb_method_entry_t *rb_resolve_me_location(const rb_method_entry_t *, VALUE
RUBY_SYMBOL_EXPORT_END
const rb_callable_method_entry_t *rb_callable_method_entry(VALUE klass, ID id);
+const rb_callable_method_entry_t *rb_callable_method_entry_or_negative(VALUE klass, ID id);
const rb_callable_method_entry_t *rb_callable_method_entry_with_refinements(VALUE klass, ID id, VALUE *defined_class);
const rb_callable_method_entry_t *rb_callable_method_entry_without_refinements(VALUE klass, ID id, VALUE *defined_class);
diff --git a/mini_builtin.c b/mini_builtin.c
index 8c8cf66263..c263d1ee71 100644
--- a/mini_builtin.c
+++ b/mini_builtin.c
@@ -36,7 +36,7 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta
FALSE, /* unsigned int coverage_enabled; */
0, /* int debug_level; */
};
- const rb_iseq_t *iseq = rb_iseq_new_with_opt(&ast->body, name_str, name_str, Qnil, INT2FIX(0), NULL, 0, ISEQ_TYPE_TOP, &optimization);
+ const rb_iseq_t *iseq = rb_iseq_new_with_opt(&ast->body, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization);
GET_VM()->builtin_function_table = NULL;
rb_ast_dispose(ast);
diff --git a/misc/lldb_cruby.py b/misc/lldb_cruby.py
index 3f0479b51f..9ef9d3967b 100755
--- a/misc/lldb_cruby.py
+++ b/misc/lldb_cruby.py
@@ -9,13 +9,16 @@
from __future__ import print_function
import lldb
import os
+import inspect
+import sys
import shlex
+import platform
+import glob
-HEAP_PAGE_ALIGN_LOG = 14
-HEAP_PAGE_ALIGN_MASK = (~(~0 << HEAP_PAGE_ALIGN_LOG))
-HEAP_PAGE_ALIGN = (1 << HEAP_PAGE_ALIGN_LOG)
-HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN
+from lldb_rb.constants import *
+# BEGIN FUNCTION STYLE DECLS
+# This will be refactored to use class style decls in the misc/commands dir
class BackTrace:
VM_FRAME_MAGIC_METHOD = 0x11110001
VM_FRAME_MAGIC_BLOCK = 0x22220001
@@ -75,7 +78,7 @@ class BackTrace:
pathobj = pathobj.Cast(self.tRArray)
if flags & RUBY_FL_USER1:
- len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
+ len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6|RUBY_FL_USER7|RUBY_FL_USER8|RUBY_FL_USER9)) >> (RUBY_FL_USHIFT+3))
ptr = pathobj.GetValueForExpressionPath("->as.ary")
else:
len = pathobj.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned()
@@ -166,6 +169,14 @@ def lldb_init(debugger):
value_types = []
g = globals()
+
+ imemo_types = target.FindFirstType('enum imemo_type')
+ enum_members = imemo_types.GetEnumMembers()
+
+ for i in range(enum_members.GetSize()):
+ member = enum_members.GetTypeEnumMemberAtIndex(i)
+ g[member.GetName()] = member.GetValueAsUnsigned()
+
for enum in target.FindFirstGlobalVariable('ruby_dummy_gdb_enums'):
enum = enum.GetType()
members = enum.GetEnumMembers()
@@ -190,8 +201,8 @@ def string2cstr(rstring):
cptr = int(rstring.GetValueForExpressionPath(".as.heap.ptr").value, 0)
clen = int(rstring.GetValueForExpressionPath(".as.heap.len").value, 0)
else:
- cptr = int(rstring.GetValueForExpressionPath(".as.ary").location, 0)
- clen = (flags & RSTRING_EMBED_LEN_MASK) >> RSTRING_EMBED_LEN_SHIFT
+ cptr = int(rstring.GetValueForExpressionPath(".as.embed.ary").location, 0)
+ clen = int(rstring.GetValueForExpressionPath(".as.embed.len").value, 0)
return cptr, clen
def output_string(debugger, result, rstring):
@@ -285,8 +296,17 @@ def lldb_inspect(debugger, target, result, val):
elif flType == RUBY_T_CLASS or flType == RUBY_T_MODULE or flType == RUBY_T_ICLASS:
result.write('T_%s: %s' % ('CLASS' if flType == RUBY_T_CLASS else 'MODULE' if flType == RUBY_T_MODULE else 'ICLASS', flaginfo))
append_command_output(debugger, "print *(struct RClass*)%0#x" % val.GetValueAsUnsigned(), result)
+ tRClass = target.FindFirstType("struct RClass")
+ if not val.Cast(tRClass).GetChildMemberWithName("ptr").IsValid():
+ append_command_output(debugger, "print *(struct rb_classext_struct*)%0#x" % (val.GetValueAsUnsigned() + tRClass.GetByteSize()), result)
elif flType == RUBY_T_STRING:
result.write('T_STRING: %s' % flaginfo)
+ encidx = ((flags & RUBY_ENCODING_MASK)>>RUBY_ENCODING_SHIFT)
+ encname = target.FindFirstType("enum ruby_preserved_encindex").GetEnumMembers().GetTypeEnumMemberAtIndex(encidx).GetName()
+ if encname is not None:
+ result.write('[%s] ' % encname[14:])
+ else:
+ result.write('[enc=%d] ' % encidx)
tRString = target.FindFirstType("struct RString").GetPointerType()
ptr, len = string2cstr(val.Cast(tRString))
if len == 0:
@@ -304,12 +324,11 @@ def lldb_inspect(debugger, target, result, val):
tRArray = target.FindFirstType("struct RArray").GetPointerType()
val = val.Cast(tRArray)
if flags & RUBY_FL_USER1:
- len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
+ len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6|RUBY_FL_USER7|RUBY_FL_USER8|RUBY_FL_USER9)) >> (RUBY_FL_USHIFT+3))
ptr = val.GetValueForExpressionPath("->as.ary")
else:
len = val.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned()
ptr = val.GetValueForExpressionPath("->as.heap.ptr")
- #print(val.GetValueForExpressionPath("->as.heap"), file=result)
result.write("T_ARRAY: %slen=%d" % (flaginfo, len))
if flags & RUBY_FL_USER1:
result.write(" (embed)")
@@ -330,9 +349,6 @@ def lldb_inspect(debugger, target, result, val):
elif flType == RUBY_T_HASH:
result.write("T_HASH: %s" % flaginfo)
append_command_output(debugger, "p *(struct RHash *) %0#x" % val.GetValueAsUnsigned(), result)
- elif flType == RUBY_T_PAYLOAD:
- result.write("T_PAYLOAD: %s" % flaginfo)
- append_command_output(debugger, "p *(struct RPayload *) %0#x" % val.GetValueAsUnsigned(), result)
elif flType == RUBY_T_BIGNUM:
tRBignum = target.FindFirstType("struct RBignum").GetPointerType()
val = val.Cast(tRBignum)
@@ -402,9 +418,14 @@ def lldb_inspect(debugger, target, result, val):
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_STRUCT:
+ tRTypedData = target.FindFirstType("struct RStruct").GetPointerType()
+ val = val.Cast(tRTypedData)
+ append_command_output(debugger, "p *(struct RStruct *) %0#x" % val.GetValueAsUnsigned(), result)
elif flType == RUBY_T_ZOMBIE:
tRZombie = target.FindFirstType("struct RZombie").GetPointerType()
val = val.Cast(tRZombie)
@@ -449,19 +470,6 @@ def check_bits(page, bitmap_name, bitmap_index, bitmap_bit, 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()
@@ -494,6 +502,8 @@ def dump_node(debugger, command, ctx, result, internal_dict):
output_string(ctx, result, dump)
def rb_backtrace(debugger, command, result, internal_dict):
+ if not ('RUBY_Qfalse' in globals()):
+ lldb_init(debugger)
bt = BackTrace(debugger, command, result, internal_dict)
frame = bt.frame
@@ -536,14 +546,15 @@ class HeapPageIter:
self.target = target
self.start = page.GetChildMemberWithName('start').GetValueAsUnsigned();
self.num_slots = page.GetChildMemberWithName('total_slots').unsigned
+ self.slot_size = page.GetChildMemberWithName('size_pool').GetChildMemberWithName('slot_size').unsigned
self.counter = 0
self.tRBasic = target.FindFirstType("struct RBasic")
self.tRValue = target.FindFirstType("struct RVALUE")
def is_valid(self):
heap_page_header_size = self.target.FindFirstType("struct heap_page_header").GetByteSize()
- rvalue_size = self.tRValue.GetByteSize()
- heap_page_obj_limit = int((HEAP_PAGE_SIZE - heap_page_header_size) / rvalue_size)
+ rvalue_size = self.slot_size
+ heap_page_obj_limit = int((HEAP_PAGE_SIZE - heap_page_header_size) / self.slot_size)
return (heap_page_obj_limit - 1) <= self.num_slots <= heap_page_obj_limit
@@ -552,7 +563,7 @@ class HeapPageIter:
def __next__(self):
if self.counter < self.num_slots:
- obj_addr_i = self.start + (self.counter * self.tRValue.GetByteSize())
+ obj_addr_i = self.start + (self.counter * self.slot_size)
obj_addr = lldb.SBAddress(obj_addr_i, self.target)
slot_info = (self.counter, obj_addr_i, self.target.CreateValueFromAddress("object", obj_addr, self.tRBasic))
self.counter += 1
@@ -591,9 +602,13 @@ def dump_page_internal(page, target, process, thread, frame, result, debugger, h
try:
flidx = "%3d" % freelist.index(obj_addr)
except ValueError:
- flidx = ' '
+ flidx = ' -1'
- result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x)" % (rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags)
+ if flType == RUBY_T_NONE:
+ klass = obj.GetChildMemberWithName('klass').GetValueAsUnsigned()
+ result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x, next: %0#x)" % (rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags, klass)
+ else:
+ result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x)" % (rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags)
if highlight == obj_addr:
result_str = ' '.join([result_str, "<<<<<"])
@@ -697,18 +712,37 @@ def rb_id2str(debugger, command, result, internal_dict):
pos = (num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE
id_str = rb_ary_entry(target, ary, pos, result)
lldb_inspect(debugger, target, result, id_str)
+# END FUNCTION STYLE DECLS
+
+
+load_dir, _ = os.path.split(os.path.realpath(__file__))
+
+for fname in glob.glob(f"{load_dir}/lldb_rb/commands/*_command.py"):
+ _, basename = os.path.split(fname)
+ mname, _ = os.path.splitext(basename)
+
+ exec(f"import lldb_rb.commands.{mname}")
def __lldb_init_module(debugger, internal_dict):
+ # Register all classes that subclass RbBaseCommand
+
+ for memname, mem in inspect.getmembers(sys.modules["lldb_rb.rb_base_command"]):
+ if inspect.isclass(mem):
+ for sclass in mem.__subclasses__():
+ sclass.register_lldb_command(debugger, f"{__name__}.{sclass.__module__}")
+
+
+ ## FUNCTION INITS - These should be removed when converted to class commands
debugger.HandleCommand("command script add -f lldb_cruby.lldb_rp rp")
debugger.HandleCommand("command script add -f lldb_cruby.count_objects rb_count_objects")
debugger.HandleCommand("command script add -f lldb_cruby.stack_dump_raw SDR")
debugger.HandleCommand("command script add -f lldb_cruby.dump_node dump_node")
- debugger.HandleCommand("command script add -f lldb_cruby.heap_page heap_page")
debugger.HandleCommand("command script add -f lldb_cruby.heap_page_body heap_page_body")
debugger.HandleCommand("command script add -f lldb_cruby.rb_backtrace rbbt")
debugger.HandleCommand("command script add -f lldb_cruby.dump_page dump_page")
debugger.HandleCommand("command script add -f lldb_cruby.dump_page_rvalue dump_page_rvalue")
debugger.HandleCommand("command script add -f lldb_cruby.rb_id2str rb_id2str")
- lldb_init(debugger)
+ lldb_rb.rb_base_command.RbBaseCommand.lldb_init(debugger)
+
print("lldb scripts for ruby has been installed.")
diff --git a/misc/lldb_disasm.py b/misc/lldb_disasm.py
index b46d097910..ab759f009a 100644
--- a/misc/lldb_disasm.py
+++ b/misc/lldb_disasm.py
@@ -21,12 +21,13 @@ import lldb
import os
import shlex
-class IseqDissassembler:
+class IseqDisassembler:
TS_VARIABLE = b'.'[0]
TS_CALLDATA = b'C'[0]
TS_CDHASH = b'H'[0]
TS_IC = b'K'[0]
TS_IVC = b'A'[0]
+ TS_ICVARC = b'J'[0]
TS_ID = b'I'[0]
TS_ISE = b'T'[0]
TS_ISEQ = b'S'[0]
@@ -48,6 +49,7 @@ class IseqDissassembler:
TS_ISE: "(iseq_inline_storage_entry *)%0#x",
TS_ID: "ID: %0#x",
TS_IVC: "(struct iseq_inline_iv_cache_entry *)%0#x",
+ TS_ICVARC: "(struct iseq_inline_cvar_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",
@@ -61,6 +63,7 @@ class IseqDissassembler:
self.internal_dict = internal_dict
self.target = debugger.GetSelectedTarget()
+ self.insns_address_table = self.__get_insns_address_table()
self.process = self.target.GetProcess()
self.thread = self.process.GetSelectedThread()
self.frame = self.thread.GetSelectedFrame()
@@ -86,7 +89,7 @@ class IseqDissassembler:
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)
+ addr_of_table = self.insns_address_table.GetStartAddress().GetLoadAddress(target)
my_dict = {}
@@ -142,7 +145,7 @@ class IseqDissassembler:
def insn_len(self, target, offset):
size_of_char = self.tChar.GetByteSize()
- symbol = target.FindSymbols("insn_len.t")[0].GetSymbol()
+ symbol = target.FindSymbols("rb_vm_insn_len_info")[0].GetSymbol()
section = symbol.GetStartAddress().GetSection()
addr_of_table = symbol.GetStartAddress().GetOffset()
@@ -160,7 +163,7 @@ class IseqDissassembler:
size_of_short = tUShort.GetByteSize()
size_of_char = self.tChar.GetByteSize()
- symbol = target.FindSymbols("insn_op_types.y")[0].GetSymbol()
+ symbol = target.FindSymbols("rb_vm_insn_op_offset")[0].GetSymbol()
section = symbol.GetStartAddress().GetSection()
addr_of_table = symbol.GetStartAddress().GetOffset()
@@ -172,7 +175,7 @@ class IseqDissassembler:
if not error.Success():
print("error getting op type offset: ", error)
- symbol = target.FindSymbols("insn_op_types.x")[0].GetSymbol()
+ symbol = target.FindSymbols("rb_vm_insn_op_base")[0].GetSymbol()
section = symbol.GetStartAddress().GetSection()
addr_of_table = symbol.GetStartAddress().GetOffset()
addr_in_name_table = addr_of_table + (offset * size_of_char)
@@ -188,7 +191,7 @@ class IseqDissassembler:
tUShort = target.FindFirstType("unsigned short")
size_of_short = tUShort.GetByteSize()
- symbol = target.FindSymbols("insn_name.y")[0].GetSymbol()
+ symbol = target.FindSymbols("rb_vm_insn_name_offset")[0].GetSymbol()
section = symbol.GetStartAddress().GetSection()
table_offset = symbol.GetStartAddress().GetOffset()
@@ -203,7 +206,7 @@ class IseqDissassembler:
print("error getting insn name table offset: ", error)
def insn_name(self, target, process, result, offset):
- symbol = target.FindSymbols("insn_name.x")[0].GetSymbol()
+ symbol = target.FindSymbols("rb_vm_insn_name_base")[0].GetSymbol()
section = symbol.GetStartAddress().GetSection()
addr_of_table = symbol.GetStartAddress().GetOffset()
@@ -218,8 +221,17 @@ class IseqDissassembler:
else:
print('error getting insn name', error)
+ def __get_insns_address_table(self):
+ module = self.target.FindSymbols("vm_exec_core")[0].GetModule()
+
+ for symbol in module:
+ if "insns_address_table" in symbol.name and symbol.GetType() == lldb.eSymbolTypeData:
+ print(f"found symbol {symbol.name}")
+ return symbol
+
+
def disasm(debugger, command, result, internal_dict):
- disassembler = IseqDissassembler(debugger, command, result, internal_dict)
+ disassembler = IseqDisassembler(debugger, command, result, internal_dict)
frame = disassembler.frame
if frame.IsValid():
@@ -233,7 +245,6 @@ def disasm(debugger, command, result, internal_dict):
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/misc/lldb_rb/commands/command_template.py b/misc/lldb_rb/commands/command_template.py
new file mode 100644
index 0000000000..21014a993e
--- /dev/null
+++ b/misc/lldb_rb/commands/command_template.py
@@ -0,0 +1,30 @@
+# This is a command template for implementing a helper function inside LLDB. To
+# use this file
+# 1. Copy it and rename the copy so it ends with `_command.py`.
+# 2. Rename the class to something descriptive that ends with Command.
+# 3. Change the program variable to be a descriptive command name
+# 4. Ensure you are inheriting from RbBaseCommand or another command that
+# implements the same interface
+
+import lldb
+
+from lldb_rb.constants import *
+from lldb_rb.rb_base_command import RbBaseCommand
+
+# This test command inherits from RbBaseCommand which provides access to Ruby
+# globals and utility helpers
+class TestCommand(RbBaseCommand):
+ # program is the keyword the user will type in lldb to execute this command
+ program = "test"
+
+ # help_string will be displayed in lldb when the user uses the help functions
+ help_string = "This is a test command to show how to implement lldb commands"
+
+ # call is where our command logic will be implemented
+ def call(self, debugger, command, exe_ctx, result):
+ # This method will be called once the LLDB environment has been setup.
+ # You will have access to self.target, self.process, self.frame, and
+ # self.thread
+ #
+ # This is where we should implement our command logic
+ pass
diff --git a/misc/lldb_rb/commands/heap_page_command.py b/misc/lldb_rb/commands/heap_page_command.py
new file mode 100644
index 0000000000..edb74a415b
--- /dev/null
+++ b/misc/lldb_rb/commands/heap_page_command.py
@@ -0,0 +1,26 @@
+import lldb
+
+from lldb_rb.constants import *
+from lldb_rb.rb_base_command import RbBaseCommand
+
+class HeapPageCommand(RbBaseCommand):
+ program = "heap_page"
+ help_string = "prints out 'struct heap_page' for a VALUE pointer in the page"
+
+ def call(self, debugger, command, exe_ctx, result):
+ self.t_heap_page_body = self.target.FindFirstType("struct heap_page_body")
+ self.t_heap_page_ptr = self.target.FindFirstType("struct heap_page").GetPointerType()
+
+ page = self._get_page(self.frame.EvaluateExpression(command))
+ page.Cast(self.t_heap_page_ptr)
+
+ self._append_command_output(debugger, "p (struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result)
+ self._append_command_output(debugger, "p *(struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result)
+
+ def _get_page(self, val):
+ addr = val.GetValueAsUnsigned()
+ page_addr = addr & ~(HEAP_PAGE_ALIGN_MASK)
+ address = lldb.SBAddress(page_addr, self.target)
+ body = self.target.CreateValueFromAddress("page", address, self.t_heap_page_body)
+
+ return body.GetValueForExpressionPath("->header.page")
diff --git a/misc/lldb_rb/commands/rclass_ext_command.py b/misc/lldb_rb/commands/rclass_ext_command.py
new file mode 100644
index 0000000000..8bae911457
--- /dev/null
+++ b/misc/lldb_rb/commands/rclass_ext_command.py
@@ -0,0 +1,14 @@
+from lldb_rb.rb_base_command import RbBaseCommand
+
+class RclassExtCommand(RbBaseCommand):
+ program = "rclass_ext"
+ help_string = "retrieves and prints the rb_classext_struct for the VALUE pointer passed in"
+
+ def call(self, debugger, command, exe_ctx, result):
+ uintptr_t = self.target.FindFirstType("uintptr_t")
+ rclass_t = self.target.FindFirstType("struct RClass")
+ rclass_ext_t = self.target.FindFirstType("rb_classext_t")
+
+ rclass_addr = self.target.EvaluateExpression(command).Cast(uintptr_t)
+ rclass_ext_addr = (rclass_addr.GetValueAsUnsigned() + rclass_t.GetByteSize())
+ debugger.HandleCommand("p *(rb_classext_t *)%0#x" % rclass_ext_addr)
diff --git a/misc/lldb_rb/constants.py b/misc/lldb_rb/constants.py
new file mode 100644
index 0000000000..ec3050a399
--- /dev/null
+++ b/misc/lldb_rb/constants.py
@@ -0,0 +1,4 @@
+HEAP_PAGE_ALIGN_LOG = 16
+HEAP_PAGE_ALIGN_MASK = (~(~0 << HEAP_PAGE_ALIGN_LOG))
+HEAP_PAGE_ALIGN = (1 << HEAP_PAGE_ALIGN_LOG)
+HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN
diff --git a/misc/lldb_rb/rb_base_command.py b/misc/lldb_rb/rb_base_command.py
new file mode 100644
index 0000000000..de90a1617c
--- /dev/null
+++ b/misc/lldb_rb/rb_base_command.py
@@ -0,0 +1,69 @@
+import lldb
+from pydoc import locate
+
+class RbBaseCommand:
+ @classmethod
+ def register_lldb_command(cls, debugger, module_name):
+ # Add any commands contained in this module to LLDB
+ command = f"command script add -c {module_name}.{cls.__name__} {cls.program}"
+ debugger.HandleCommand(command)
+
+ @classmethod
+ def lldb_init(cls, debugger):
+ target = debugger.GetSelectedTarget()
+ global SIZEOF_VALUE
+ SIZEOF_VALUE = target.FindFirstType("VALUE").GetByteSize()
+
+ value_types = []
+ g = globals()
+
+ imemo_types = target.FindFirstType("enum imemo_type")
+
+ #for member in imemo_types.GetEnumMembers():
+ # g[member.GetName()] = member.GetValueAsUnsigned()
+
+ for enum in target.FindFirstGlobalVariable("ruby_dummy_gdb_enums"):
+ enum = enum.GetType()
+ members = enum.GetEnumMembers()
+ for i in range(0, members.GetSize()):
+ member = members.GetTypeEnumMemberAtIndex(i)
+ name = member.GetName()
+ value = member.GetValueAsUnsigned()
+ g[name] = value
+
+ if name.startswith("RUBY_T_"):
+ value_types.append(name)
+ g["value_types"] = value_types
+
+ def __init__(self, debugger, _internal_dict):
+ self.internal_dict = _internal_dict
+
+ def __call__(self, debugger, command, exe_ctx, result):
+ if not ("RUBY_Qfalse" in globals()):
+ RbBaseCommand.lldb_init(debugger)
+
+ self.build_environment(debugger)
+ self.call(debugger, command, exe_ctx, result)
+
+ def call(self, debugger, command, exe_ctx, result):
+ raise NotImplementedError("subclasses must implement call")
+
+ def get_short_help(self):
+ return self.__class__.help_string
+
+ def get_long_help(self):
+ return self.__class__.help_string
+
+ def build_environment(self, debugger):
+ self.target = debugger.GetSelectedTarget()
+ self.process = self.target.GetProcess()
+ self.thread = self.process.GetSelectedThread()
+ self.frame = self.thread.GetSelectedFrame()
+
+ def _append_command_output(self, debugger, command, result):
+ output1 = result.GetOutput()
+ debugger.GetCommandInterpreter().HandleCommand(command, result)
+ output2 = result.GetOutput()
+ result.Clear()
+ result.write(output1)
+ result.write(output2)
diff --git a/misc/lldb_yjit.py b/misc/lldb_yjit.py
new file mode 100644
index 0000000000..cc37b990ea
--- /dev/null
+++ b/misc/lldb_yjit.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+#coding: utf-8
+#
+# Usage: run `command script import -r misc/lldb_yjit.py` on LLDB
+#
+
+from __future__ import print_function
+import lldb
+import os
+import shlex
+
+def list_comments(debugger, command, result, internal_dict):
+ target = debugger.GetSelectedTarget()
+ process = target.GetProcess()
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ # Get the different types we need
+ rb_darray_meta_t = target.FindFirstType("rb_darray_meta_t")
+ codeblock_t = target.FindFirstType("codeblock_t")
+ yjit_comment = target.FindFirstType("yjit_comment")
+
+ # Get the global variables we need
+ comments = target.FindFirstGlobalVariable("yjit_code_comments")
+ cb = target.FindFirstGlobalVariable("cb").Cast(codeblock_t.GetPointerType())
+
+ # Get the address of the memory block we're using
+ mem_addr = cb.GetChildMemberWithName("mem_block").GetValueAsUnsigned()
+
+ # Find the size of the darray comment list
+ meta = comments.Cast(rb_darray_meta_t.GetPointerType())
+ size = meta.GetChildMemberWithName("size").GetValueAsUnsigned()
+
+ # Get the address of the block following the metadata header
+ t_offset = comments.GetValueAsUnsigned() + rb_darray_meta_t.GetByteSize()
+
+ # Loop through each comment and print
+ for t in range(0, size):
+ addr = lldb.SBAddress(t_offset + (t * yjit_comment.GetByteSize()), target)
+ comment = target.CreateValueFromAddress("yjit_comment", addr, yjit_comment)
+ string = comment.GetChildMemberWithName("comment")
+ comment_offset = mem_addr + comment.GetChildMemberWithName("offset").GetValueAsUnsigned()
+ print("%0#x %s" % (comment_offset, string.GetSummary()), file = result)
+
+
+def __lldb_init_module(debugger, internal_dict):
+ debugger.HandleCommand("command script add -f lldb_yjit.list_comments lc")
diff --git a/missing/dtoa.c b/missing/dtoa.c
index a940eabd91..b7a8302875 100644
--- a/missing/dtoa.c
+++ b/missing/dtoa.c
@@ -1552,6 +1552,7 @@ break2:
if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
if (*s == '0') {
while (*++s == '0');
+ if (!*s) goto ret;
s1 = strchr(hexdigit, *s);
}
if (s1 != NULL) {
@@ -1574,7 +1575,7 @@ break2:
for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
adj += aadj * ((s1 - hexdigit) & 15);
if ((aadj /= 16) == 0.0) {
- while (strchr(hexdigit, *++s));
+ while (*++s && strchr(hexdigit, *s));
break;
}
}
diff --git a/missing/erf.c b/missing/erf.c
index d72c4eaf4e..c2c9d5f7e9 100644
--- a/missing/erf.c
+++ b/missing/erf.c
@@ -7,21 +7,6 @@ reference - Haruhiko Okumura: C-gengo niyoru saishin algorithm jiten
#include <stdio.h>
#include <math.h>
-#ifdef _WIN32
-# include <float.h>
-# if !defined __MINGW32__ || defined __NO_ISOCEXT
-# ifndef isnan
-# define isnan(x) _isnan(x)
-# endif
-# ifndef isinf
-# define isinf(x) (!_finite(x) && !_isnan(x))
-# endif
-# ifndef finite
-# define finite(x) _finite(x)
-# endif
-# endif
-#endif
-
static double q_gamma(double, double, double);
/* Incomplete gamma function
diff --git a/missing/finite.c b/missing/finite.c
deleted file mode 100644
index ab7686317b..0000000000
--- a/missing/finite.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* public domain rewrite of finite(3) */
-
-#include "ruby/missing.h"
-
-int
-finite(double n)
-{
- return !isnan(n) && !isinf(n);
-}
diff --git a/missing/flock.c b/missing/flock.c
index c0b3f80601..0b76961762 100644
--- a/missing/flock.c
+++ b/missing/flock.c
@@ -2,6 +2,15 @@
#include "ruby/ruby.h"
#if defined _WIN32
+#elif defined __wasi__
+#include <errno.h>
+
+int
+flock(int fd, int operation)
+{
+ errno = EINVAL;
+ return -1;
+}
#elif defined HAVE_FCNTL && defined HAVE_FCNTL_H
/* These are the flock() constants. Since this systems doesn't have
diff --git a/missing/isinf.c b/missing/isinf.c
deleted file mode 100644
index ba24b7768b..0000000000
--- a/missing/isinf.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* public domain rewrite of isinf(3) */
-
-#ifdef __osf__
-
-#define _IEEE 1
-#include <nan.h>
-
-int
-isinf(double n)
-{
- if (IsNANorINF(n) && IsINF(n)) {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-#else
-
-#include "ruby/internal/config.h"
-
-#if defined(HAVE_FINITE) && defined(HAVE_ISNAN)
-
-#include <math.h>
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-/*
- * isinf may be provided only as a macro.
- * ex. HP-UX, Solaris 10
- * http://www.gnu.org/software/automake/manual/autoconf/Function-Portability.html
- */
-#ifndef isinf
-int
-isinf(double n)
-{
- return (!finite(n) && !isnan(n));
-}
-#endif
-
-#else
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-
-static double zero(void) { return 0.0; }
-static double one (void) { return 1.0; }
-static double inf (void) { return one() / zero(); }
-
-int
-isinf(double n)
-{
- static double pinf = 0.0;
- static double ninf = 0.0;
-
- if (pinf == 0.0) {
- pinf = inf();
- ninf = -pinf;
- }
- return memcmp(&n, &pinf, sizeof n) == 0
- || memcmp(&n, &ninf, sizeof n) == 0;
-}
-#endif
-#endif
diff --git a/missing/isnan.c b/missing/isnan.c
deleted file mode 100644
index ed10bf5cd6..0000000000
--- a/missing/isnan.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* public domain rewrite of isnan(3) */
-
-#include "ruby/missing.h"
-
-/*
- * isnan() may be a macro, a function or both.
- * (The C99 standard defines that isnan() is a macro, though.)
- * http://www.gnu.org/software/automake/manual/autoconf/Function-Portability.html
- *
- * macro only: uClibc
- * both: GNU libc
- *
- * This file is compile if no isnan() function is available.
- * (autoconf AC_REPLACE_FUNCS detects only the function.)
- * The macro is detected by following #ifndef.
- */
-
-#ifndef isnan
-static int double_ne(double n1, double n2);
-
-int
-isnan(double n)
-{
- return double_ne(n, n);
-}
-
-static int
-double_ne(double n1, double n2)
-{
- return n1 != n2;
-}
-#endif
diff --git a/missing/langinfo.c b/missing/langinfo.c
index 9ba06b15f6..0274a378f5 100644
--- a/missing/langinfo.c
+++ b/missing/langinfo.c
@@ -140,7 +140,7 @@ char *nl_langinfo(nl_item item)
#ifdef TEST
#include <stdio.h>
-int main()
+int main(void)
{
printf("%s\n", nl_langinfo(CODESET));
return 0;
diff --git a/missing/signbit.c b/missing/signbit.c
deleted file mode 100644
index 2f7ce8c601..0000000000
--- a/missing/signbit.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <limits.h>
-#include "ruby.h"
-
-int
-signbit(double x)
-{
- enum {double_per_long = sizeof(double) / sizeof(long)};
- enum {long_msb = sizeof(long) * CHAR_BIT - 1};
- union {double d; unsigned long i[double_per_long];} u;
- unsigned long l;
-
- u.d = x;
-#ifdef WORDS_BIGENDIAN
- l = u.i[0];
-#else
- l = u.i[double_per_long - 1];
-#endif
- return (int)(l >> long_msb);
-}
diff --git a/missing/tgamma.c b/missing/tgamma.c
index c8638eab2b..82d614d755 100644
--- a/missing/tgamma.c
+++ b/missing/tgamma.c
@@ -14,21 +14,6 @@ reference - Haruhiko Okumura: C-gengo niyoru saishin algorithm jiten
#include <math.h>
#include <errno.h>
-#ifdef _WIN32
-# include <float.h>
-# if !defined __MINGW32__ || defined __NO_ISOCEXT
-# ifndef isnan
-# define isnan(x) _isnan(x)
-# endif
-# ifndef isinf
-# define isinf(x) (!_finite(x) && !_isnan(x))
-# endif
-# ifndef finite
-# define finite(x) _finite(x)
-# endif
-# endif
-#endif
-
#ifndef HAVE_LGAMMA_R
#include <errno.h>
diff --git a/mjit.c b/mjit.c
index 89f50cbda1..3200ee2621 100644
--- a/mjit.c
+++ b/mjit.c
@@ -1,15 +1,69 @@
/**********************************************************************
- mjit.c - MRI method JIT compiler functions for Ruby's main thread
+ mjit.c - MRI method JIT compiler functions
Copyright (C) 2017 Vladimir Makarov <vmakarov@redhat.com>.
+ Copyright (C) 2017 Takashi Kokubun <k0kubun@ruby-lang.org>.
**********************************************************************/
-// Functions in this file are never executed on MJIT worker thread.
-// So you can safely use Ruby methods and GC in this file.
-
-// To share variables privately, include mjit_worker.c instead of linking.
+/* 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.
+ Generated code performance of the used C compilers has a higher
+ priority over the compilation speed.
+
+ So our major goal is to minimize the ISEQ compilation time when we
+ use widely optimization level (-O2). It is achieved by
+
+ o Using a precompiled version of the header
+ o Keeping all files in `/tmp`. On modern Linux `/tmp` is a file
+ system in memory. So it is pretty fast
+ o Implementing MJIT as a multi-threaded code because we want to
+ compile ISEQs in parallel with iseq execution to speed up Ruby
+ code execution. MJIT has one thread (*worker*) to do
+ parallel compilations:
+ o It prepares a precompiled code of the minimized header.
+ It starts at the MRI execution start
+ o It generates PIC object files of ISEQs
+ o It takes one JIT unit from a priority queue unless it is empty.
+ o It translates the JIT unit ISEQ into C-code using the precompiled
+ header, calls CC and load PIC code when it is ready
+ o Currently MJIT put ISEQ in the queue when ISEQ is called
+ o MJIT can reorder ISEQs in the queue if some ISEQ has been called
+ many times and its compilation did not start yet
+ o MRI reuses the machine code if it already exists for ISEQ
+ o The machine code we generate can stop and switch to the ISEQ
+ interpretation if some condition is not satisfied as the machine
+ code can be speculative or some exception raises
+ o Speculative machine code can be canceled.
+
+ Here is a diagram showing the MJIT organization:
+
+ _______
+ |header |
+ |_______|
+ | MRI building
+ --------------|----------------------------------------
+ | MRI execution
+ |
+ _____________|_____
+ | | |
+ | ___V__ | CC ____________________
+ | | |----------->| precompiled header |
+ | | | | |____________________|
+ | | | | |
+ | | MJIT | | |
+ | | | | |
+ | | | | ____V___ CC __________
+ | |______|----------->| C code |--->| .so file |
+ | | |________| |__________|
+ | | |
+ | | |
+ | MRI machine code |<-----------------------------
+ |___________________| loading
+
+*/
#include "ruby/internal/config.h" // defines USE_MJIT
@@ -19,15 +73,874 @@
#include "id_table.h"
#include "internal.h"
#include "internal/class.h"
+#include "internal/cmdlineopt.h"
#include "internal/cont.h"
#include "internal/file.h"
#include "internal/hash.h"
+#include "internal/process.h"
#include "internal/warnings.h"
#include "vm_sync.h"
+#include "ractor_core.h"
+
+#ifdef __sun
+#define __EXTENSIONS__ 1
+#endif
+
+#include "vm_core.h"
+#include "vm_callinfo.h"
+#include "mjit.h"
+#include "mjit_c.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"
+
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <dlfcn.h>
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#include "dln.h"
+
+#include "ruby/util.h"
+#undef strdup // ruby_strdup may trigger GC
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+#endif
+
+// Atomically set function pointer if possible.
+#define MJIT_ATOMIC_SET(var, val) (void)ATOMIC_PTR_EXCHANGE(var, val)
+
+#define MJIT_TMP_PREFIX "_ruby_mjit_"
+
+extern void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
+extern void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
+extern void rb_native_mutex_initialize(rb_nativethread_lock_t *lock);
+extern void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
+
+// process.c
+extern void mjit_add_waiting_pid(rb_vm_t *vm, rb_pid_t pid);
+
+// A copy of MJIT portion of MRI options since MJIT initialization. We
+// need them as MJIT threads still can work when the most MRI data were
+// freed.
+struct mjit_options mjit_opts;
+
+// true if MJIT is enabled.
+bool mjit_enabled = false;
+// true if JIT-ed code should be called. When `ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS`
+// and `mjit_call_p == false`, any JIT-ed code execution is cancelled as soon as possible.
+bool mjit_call_p = false;
+// A flag to communicate that mjit_call_p should be disabled while it's temporarily false.
+bool mjit_cancel_p = false;
+// There's an ISEQ in unit_queue whose total_calls reached 2 * call_threshold.
+// If this is true, check_unit_queue will start compiling ISEQs in unit_queue.
+static bool mjit_compile_p = false;
+// The actual number of units in active_units
+static int active_units_length = 0;
+// The actual number of units in compact_units
+static int compact_units_length = 0;
+
+// Priority queue of iseqs waiting for JIT compilation.
+// This variable is a pointer to head unit of the queue.
+static struct rb_mjit_unit_list unit_queue = { CCAN_LIST_HEAD_INIT(unit_queue.head) };
+// List of units which are successfully compiled.
+static struct rb_mjit_unit_list active_units = { CCAN_LIST_HEAD_INIT(active_units.head) };
+// List of compacted so files which will be cleaned up by `free_list()` in `mjit_finish()`.
+static struct rb_mjit_unit_list compact_units = { CCAN_LIST_HEAD_INIT(compact_units.head) };
+// List of units before recompilation and just waiting for dlclose().
+static struct rb_mjit_unit_list stale_units = { CCAN_LIST_HEAD_INIT(stale_units.head) };
+// The number of so far processed ISEQs, used to generate unique id.
+static int current_unit_num;
+// A mutex for conitionals and critical sections.
+static rb_nativethread_lock_t mjit_engine_mutex;
+// Set to true to stop worker.
+static bool stop_worker_p;
+// Set to true if worker is stopped.
+static bool worker_stopped = true;
+
+// Path of "/tmp", which is different on Windows or macOS. See: system_default_tmpdir()
+static char *tmp_dir;
+
+// Used C compiler path.
+static const char *cc_path;
+// Used C compiler flags.
+static const char **cc_common_args;
+// Used C compiler flags added by --mjit-debug=...
+static char **cc_added_args;
+// Name of the precompiled header file.
+static char *pch_file;
+// The process id which should delete the pch_file on mjit_finish.
+static rb_pid_t pch_owner_pid;
+// Status of the precompiled header creation. The status is
+// shared by the workers and the pch thread.
+static enum {PCH_NOT_READY, PCH_FAILED, PCH_SUCCESS} pch_status;
+
+// The start timestamp of current compilation
+static double current_cc_ms = 0.0; // TODO: make this part of unit?
+// Currently compiling MJIT unit
+static struct rb_mjit_unit *current_cc_unit = NULL;
+// PID of currently running C compiler process. 0 if nothing is running.
+static pid_t current_cc_pid = 0; // TODO: make this part of unit?
+
+// Name of the header file.
+static char *header_file;
+
+#include "mjit_config.h"
+
+#if defined(__GNUC__) && \
+ (!defined(__clang__) || \
+ (defined(__clang__) && (defined(__FreeBSD__) || defined(__GLIBC__))))
+# define GCC_PIC_FLAGS "-Wfatal-errors", "-fPIC", "-shared", "-w", "-pipe",
+# define MJIT_CFLAGS_PIPE 1
+#else
+# define GCC_PIC_FLAGS /* empty */
+# define MJIT_CFLAGS_PIPE 0
+#endif
+
+// Use `-nodefaultlibs -nostdlib` for GCC where possible, which does not work on cygwin, AIX, and OpenBSD.
+// This seems to improve MJIT performance on GCC.
+#if defined __GNUC__ && !defined __clang__ && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__OpenBSD__)
+# define GCC_NOSTDLIB_FLAGS "-nodefaultlibs", "-nostdlib",
+#else
+# define GCC_NOSTDLIB_FLAGS // empty
+#endif
+
+static const char *const CC_COMMON_ARGS[] = {
+ MJIT_CC_COMMON MJIT_CFLAGS GCC_PIC_FLAGS
+ NULL
+};
+
+static const char *const CC_DEBUG_ARGS[] = {MJIT_DEBUGFLAGS NULL};
+static const char *const CC_OPTIMIZE_ARGS[] = {MJIT_OPTFLAGS NULL};
+
+static const char *const CC_LDSHARED_ARGS[] = {MJIT_LDSHARED MJIT_CFLAGS GCC_PIC_FLAGS NULL};
+static const char *const CC_DLDFLAGS_ARGS[] = {MJIT_DLDFLAGS NULL};
+// `CC_LINKER_ARGS` are linker flags which must be passed to `-c` as well.
+static const char *const CC_LINKER_ARGS[] = {
+#if defined __GNUC__ && !defined __clang__ && !defined(__OpenBSD__)
+ "-nostartfiles",
+#endif
+ GCC_NOSTDLIB_FLAGS NULL
+};
+
+static const char *const CC_LIBS[] = {
+#if defined(__CYGWIN__)
+ MJIT_LIBS // mswin, cygwin
+#endif
+#if defined __GNUC__ && !defined __clang__
+ "-lgcc", // cygwin, and GCC platforms using `-nodefaultlibs -nostdlib`
+#endif
+#if defined __ANDROID__
+ "-lm", // to avoid 'cannot locate symbol "modf" referenced by .../_ruby_mjit_XXX.so"'
+#endif
+ NULL
+};
+
+#define CC_CODEFLAG_ARGS (mjit_opts.debug ? CC_DEBUG_ARGS : CC_OPTIMIZE_ARGS)
+
+// Print the arguments according to FORMAT to stderr only if MJIT
+// verbose option value is more or equal to LEVEL.
+PRINTF_ARGS(static void, 2, 3)
+verbose(int level, const char *format, ...)
+{
+ if (mjit_opts.verbose >= level) {
+ va_list args;
+ size_t len = strlen(format);
+ char *full_format = alloca(sizeof(char) * (len + 2));
+
+ // Creating `format + '\n'` to atomically print format and '\n'.
+ memcpy(full_format, format, len);
+ full_format[len] = '\n';
+ full_format[len+1] = '\0';
+
+ va_start(args, format);
+ vfprintf(stderr, full_format, args);
+ va_end(args);
+ }
+}
+
+PRINTF_ARGS(static void, 1, 2)
+mjit_warning(const char *format, ...)
+{
+ if (mjit_opts.warnings || mjit_opts.verbose) {
+ va_list args;
+
+ fprintf(stderr, "MJIT warning: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+// Add unit node to the tail of doubly linked `list`. It should be not in
+// the list before.
+static void
+add_to_list(struct rb_mjit_unit *unit, struct rb_mjit_unit_list *list)
+{
+ ccan_list_add_tail(&list->head, &unit->unode);
+ list->length++;
+}
+
+static void
+remove_from_list(struct rb_mjit_unit *unit, struct rb_mjit_unit_list *list)
+{
+ ccan_list_del(&unit->unode);
+ list->length--;
+}
+
+static void
+remove_file(const char *filename)
+{
+ if (remove(filename)) {
+ mjit_warning("failed to remove \"%s\": %s", filename, strerror(errno));
+ }
+}
+
+// This is called in the following situations:
+// 1) On dequeue or `unload_units()`, associated ISeq is already GCed.
+// 2) The unit is not called often and unloaded by `unload_units()`.
+// 3) Freeing lists on `mjit_finish()`.
+//
+// `jit_func` value does not matter for 1 and 3 since the unit won't be used anymore.
+// For the situation 2, this sets the ISeq's JIT state to MJIT_FUNC_FAILED
+// to prevent the situation that the same methods are continuously compiled.
+static void
+free_unit(struct rb_mjit_unit *unit)
+{
+ if (unit->iseq) { // ISeq is not GCed
+ ISEQ_BODY(unit->iseq)->jit_func = (jit_func_t)MJIT_FUNC_FAILED;
+ ISEQ_BODY(unit->iseq)->mjit_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());
+ }
+ xfree(unit);
+}
+
+// Start a critical section. Use message `msg` to print debug info at `level`.
+static inline void
+CRITICAL_SECTION_START(int level, const char *msg)
+{
+ verbose(level, "Locking %s", msg);
+ rb_native_mutex_lock(&mjit_engine_mutex);
+ verbose(level, "Locked %s", msg);
+}
+
+// Finish the current critical section. Use message `msg` to print
+// debug info at `level`.
+static inline void
+CRITICAL_SECTION_FINISH(int level, const char *msg)
+{
+ verbose(level, "Unlocked %s", msg);
+ rb_native_mutex_unlock(&mjit_engine_mutex);
+}
+
+static pid_t mjit_pid = 0;
+
+static int
+sprint_uniq_filename(char *str, size_t size, unsigned long id, const char *prefix, const char *suffix)
+{
+ return snprintf(str, size, "%s/%sp%"PRI_PIDT_PREFIX"uu%lu%s", tmp_dir, prefix, mjit_pid, id, suffix);
+}
+
+// Return time in milliseconds as a double.
+#ifdef __APPLE__
+double ruby_real_ms_time(void);
+# define real_ms_time() ruby_real_ms_time()
+#else
+static double
+real_ms_time(void)
+{
+# ifdef HAVE_CLOCK_GETTIME
+ struct timespec tv;
+# ifdef CLOCK_MONOTONIC
+ const clockid_t c = CLOCK_MONOTONIC;
+# else
+ const clockid_t c = CLOCK_REALTIME;
+# endif
+
+ clock_gettime(c, &tv);
+ return tv.tv_nsec / 1000000.0 + tv.tv_sec * 1000.0;
+# else
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return tv.tv_usec / 1000.0 + tv.tv_sec * 1000.0;
+# endif
+}
+#endif
+
+// Return the best unit from list. The best is the first
+// high priority unit or the unit whose iseq has the biggest number
+// of calls so far.
+static struct rb_mjit_unit *
+get_from_list(struct rb_mjit_unit_list *list)
+{
+ // Find iseq with max total_calls
+ struct rb_mjit_unit *unit = NULL, *next, *best = NULL;
+ ccan_list_for_each_safe(&list->head, unit, next, unode) {
+ if (unit->iseq == NULL) { // ISeq is GCed.
+ remove_from_list(unit, list);
+ free_unit(unit);
+ continue;
+ }
+
+ if (best == NULL || ISEQ_BODY(best->iseq)->total_calls < ISEQ_BODY(unit->iseq)->total_calls) {
+ best = unit;
+ }
+ }
+
+ if (best) {
+ remove_from_list(best, list);
+ }
+ return best;
+}
+
+// Return length of NULL-terminated array `args` excluding the NULL marker.
+static size_t
+args_len(char *const *args)
+{
+ size_t i;
+
+ for (i = 0; (args[i]) != NULL;i++)
+ ;
+ return i;
+}
+
+// Concatenate `num` passed NULL-terminated arrays of strings, put the
+// result (with NULL end marker) into the heap, and return the result.
+static char **
+form_args(int num, ...)
+{
+ va_list argp;
+ size_t len, n;
+ int i;
+ char **args, **res, **tmp;
+
+ va_start(argp, num);
+ res = NULL;
+ for (i = len = 0; i < num; i++) {
+ args = va_arg(argp, char **);
+ n = args_len(args);
+ if ((tmp = (char **)realloc(res, sizeof(char *) * (len + n + 1))) == NULL) {
+ free(res);
+ res = NULL;
+ break;
+ }
+ res = tmp;
+ MEMCPY(res + len, args, char *, n + 1);
+ len += n;
+ }
+ va_end(argp);
+ return res;
+}
+
+COMPILER_WARNING_PUSH
+#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`.
+// Return PID of the process.
+static pid_t
+start_process(const char *abspath, char *const *argv)
+{
+ // Not calling non-async-signal-safe functions between vfork
+ // and execv for safety
+ int dev_null = rb_cloexec_open(ruby_null_device, O_WRONLY, 0);
+ if (dev_null < 0) {
+ verbose(1, "MJIT: Failed to open a null device: %s", strerror(errno));
+ return -1;
+ }
+ if (mjit_opts.verbose >= 2) {
+ const char *arg;
+ fprintf(stderr, "Starting process: %s", abspath);
+ for (int i = 0; (arg = argv[i]) != NULL; i++)
+ fprintf(stderr, " %s", arg);
+ fprintf(stderr, "\n");
+ }
+
+ pid_t pid;
+ if ((pid = vfork()) == 0) { /* TODO: reuse some function in process.c */
+ umask(0077);
+ if (mjit_opts.verbose == 0) {
+ // CC can be started in a thread using a file which has been
+ // already removed while MJIT is finishing. Discard the
+ // messages about missing files.
+ dup2(dev_null, STDERR_FILENO);
+ dup2(dev_null, STDOUT_FILENO);
+ }
+ (void)close(dev_null);
+ pid = execv(abspath, argv); // Pid will be negative on an error
+ // Even if we successfully found CC to compile PCH we still can
+ // fail with loading the CC in very rare cases for some reasons.
+ // Stop the forked process in this case.
+ verbose(1, "MJIT: Error in execv: %s", abspath);
+ _exit(1);
+ }
+ (void)close(dev_null);
+ return pid;
+}
+COMPILER_WARNING_POP
+
+// Execute an OS process of executable PATH with arguments ARGV.
+// Return -1 or -2 if failed to execute, otherwise exit code of the process.
+// TODO: Use a similar function in process.c
+static int
+exec_process(const char *path, char *const argv[])
+{
+ int stat, exit_code = -2;
+ pid_t pid = start_process(path, argv);
+ for (;pid > 0;) {
+ pid_t r = waitpid(pid, &stat, 0);
+ if (r == -1) {
+ if (errno == EINTR) continue;
+ fprintf(stderr, "[%"PRI_PIDT_PREFIX"d] waitpid(%lu): %s (SIGCHLD=%d,%u)\n",
+ getpid(), (unsigned long)pid, strerror(errno),
+ RUBY_SIGCHLD, SIGCHLD_LOSSY);
+ break;
+ }
+ else if (r == pid) {
+ if (WIFEXITED(stat)) {
+ exit_code = WEXITSTATUS(stat);
+ break;
+ }
+ else if (WIFSIGNALED(stat)) {
+ exit_code = -1;
+ break;
+ }
+ }
+ }
+ return exit_code;
+}
+
+static void
+remove_so_file(const char *so_file, struct rb_mjit_unit *unit)
+{
+ remove_file(so_file);
+}
+
+// Print _mjitX, but make a human-readable funcname when --mjit-debug is used
+static void
+sprint_funcname(char *funcname, size_t funcname_size, const struct rb_mjit_unit *unit)
+{
+ const rb_iseq_t *iseq = unit->iseq;
+ if (iseq == NULL || (!mjit_opts.debug && !mjit_opts.debug_flags)) {
+ snprintf(funcname, funcname_size, "_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(iseq)->location.label);
+ if (!strcmp(method, "[]")) method = "AREF";
+ if (!strcmp(method, "[]=")) method = "ASET";
+
+ // Print and normalize
+ snprintf(funcname, funcname_size, "_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 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))
+
+// The function producing the pre-compiled header.
+static void
+make_pch(void)
+{
+ const char *rest_args[] = {
+# ifdef __clang__
+ "-Xclang",
+ "-emit-pch",
+ "-c",
+# endif
+ // -nodefaultlibs is a linker flag, but it may affect cc1 behavior on Gentoo, which should NOT be changed on pch:
+ // https://gitweb.gentoo.org/proj/gcc-patches.git/tree/7.3.0/gentoo/13_all_default-ssp-fix.patch
+ GCC_NOSTDLIB_FLAGS
+ "-o", pch_file, header_file,
+ NULL,
+ };
+
+ verbose(2, "Creating precompiled header");
+ char **args = form_args(4, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, rest_args);
+ if (args == NULL) {
+ mjit_warning("making precompiled header failed on forming args");
+ pch_status = PCH_FAILED;
+ return;
+ }
+
+ int exit_code = exec_process(cc_path, args);
+ free(args);
+
+ if (exit_code == 0) {
+ pch_status = PCH_SUCCESS;
+ }
+ else {
+ mjit_warning("Making precompiled header failed on compilation. Stopping MJIT worker...");
+ pch_status = PCH_FAILED;
+ }
+}
+
+static int
+c_compile(const char *c_file, const char *so_file)
+{
+ const char *so_args[] = {
+ "-o", so_file,
+# ifdef __clang__
+ "-include-pch", pch_file,
+# endif
+ c_file, NULL
+ };
+
+# 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
+
+ char **args = form_args(8, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS, cc_added_args,
+ so_args, loader_args, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS);
+ if (args == NULL) return 1;
+
+ int exit_code = exec_process(cc_path, args);
+ if (!mjit_opts.save_temps)
+ remove_file(c_file);
+
+ free(args);
+ return exit_code;
+}
+
+static int
+c_compile_unit(struct rb_mjit_unit *unit)
+{
+ static const char c_ext[] = ".c";
+ static const char so_ext[] = DLEXT;
+ char c_file[MAXPATHLEN], so_file[MAXPATHLEN];
+
+ 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);
+
+ return c_compile(c_file, so_file);
+}
+
+static void compile_prelude(FILE *f);
+
+static bool
+mjit_batch(struct rb_mjit_unit *unit)
+{
+ VM_ASSERT(unit->type == MJIT_UNIT_BATCH);
+ static const char c_ext[] = ".c";
+ static const char so_ext[] = DLEXT;
+ char c_file[MAXPATHLEN], so_file[MAXPATHLEN];
+
+ 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);
+
+ 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;
+ }
+
+ compile_prelude(f);
+
+ bool success = true;
+ struct rb_mjit_unit *child_unit = 0;
+ ccan_list_for_each(&unit->units.head, child_unit, unode) {
+ if (!success) continue;
+ if (child_unit->iseq == NULL) continue; // ISEQ is GCed
+
+ char funcname[MAXPATHLEN];
+ sprint_funcname(funcname, sizeof(funcname), child_unit);
+
+ int iseq_lineno = ISEQ_BODY(child_unit->iseq)->location.first_lineno;
+ const char *sep = "@";
+ const char *iseq_label = RSTRING_PTR(ISEQ_BODY(child_unit->iseq)->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:%d */\n", iseq_label, sep, iseq_path, iseq_lineno);
+ success &= mjit_compile(f, child_unit->iseq, funcname, child_unit->id);
+ }
+
+ fclose(f);
+ return success;
+}
+
+// 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 bool
+mjit_compact(struct rb_mjit_unit *unit)
+{
+ VM_ASSERT(unit->type == MJIT_UNIT_COMPACT);
+ static const char c_ext[] = ".c";
+ static const char so_ext[] = DLEXT;
+ char c_file[MAXPATHLEN], so_file[MAXPATHLEN];
+
+ 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);
+
+ 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;
+ }
+
+ compile_prelude(f);
+
+ bool success = true;
+ compact_units_length = 0;
+ struct rb_mjit_unit *batch_unit = 0, *child_unit = 0;
+ ccan_list_for_each(&active_units.head, batch_unit, unode) {
+ ccan_list_for_each(&batch_unit->units.head, child_unit, unode) {
+ if (!success) continue;
+ if (child_unit->iseq == NULL) continue; // ISEQ is GCed
+
+ char funcname[MAXPATHLEN];
+ sprint_funcname(funcname, sizeof(funcname), child_unit);
+
+ int iseq_lineno = ISEQ_BODY(child_unit->iseq)->location.first_lineno;
+ const char *sep = "@";
+ const char *iseq_label = RSTRING_PTR(ISEQ_BODY(child_unit->iseq)->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:%d */\n", iseq_label, sep, iseq_path, iseq_lineno);
+ success &= mjit_compile(f, child_unit->iseq, funcname, child_unit->id);
+ compact_units_length++;
+ }
+ }
+
+ fclose(f);
+ return success;
+}
+
+static void
+load_batch_funcs_from_so(struct rb_mjit_unit *unit, char *c_file, char *so_file)
+{
+ double end_time = real_ms_time();
+
+ void *handle = dlopen(so_file, RTLD_NOW);
+ if (handle == NULL) {
+ mjit_warning("failure in loading code from batched '%s': %s", so_file, dlerror());
+ xfree(unit);
+ return;
+ }
+ unit->handle = handle;
+
+ // lazily dlclose handle on `mjit_finish()`.
+ add_to_list(unit, &active_units);
+ active_units_length += unit->units.length;
+
+ if (!mjit_opts.save_temps)
+ remove_so_file(so_file, unit);
+
+ struct rb_mjit_unit *child_unit = 0;
+ ccan_list_for_each(&unit->units.head, child_unit, unode) {
+ char funcname[MAXPATHLEN];
+ sprint_funcname(funcname, sizeof(funcname), child_unit);
+
+ void *func;
+ if ((func = dlsym(handle, funcname)) == NULL) {
+ mjit_warning("skipping to load '%s' from '%s': %s", funcname, so_file, dlerror());
+ continue;
+ }
+
+ if (child_unit->iseq) { // Check whether GCed or not
+ // Usage of jit_code might be not in a critical section.
+ const rb_iseq_t *iseq = child_unit->iseq;
+ MJIT_ATOMIC_SET(ISEQ_BODY(iseq)->jit_func, (jit_func_t)func);
+
+ verbose(1, "JIT success: %s@%s:%d",
+ RSTRING_PTR(ISEQ_BODY(iseq)->location.label),
+ RSTRING_PTR(rb_iseq_path(iseq)), ISEQ_BODY(iseq)->location.first_lineno);
+ }
+ else {
+ verbose(1, "JIT skip: A compiled method has been GCed");
+ }
+ }
+ verbose(1, "JIT batch (%.1fms): Batched %d methods %s -> %s", end_time - current_cc_ms, unit->units.length, c_file, so_file);
+}
+
+static void
+load_compact_funcs_from_so(struct rb_mjit_unit *unit, char *c_file, char *so_file)
+{
+ double end_time = real_ms_time();
+
+ void *handle = dlopen(so_file, RTLD_NOW);
+ if (handle == NULL) {
+ mjit_warning("failure in loading code from compacted '%s': %s", so_file, dlerror());
+ xfree(unit);
+ return;
+ }
+ unit->handle = handle;
+
+ // lazily dlclose handle on `mjit_finish()`.
+ add_to_list(unit, &compact_units);
+
+ if (!mjit_opts.save_temps)
+ remove_so_file(so_file, unit);
+
+ struct rb_mjit_unit *batch_unit = 0, *child_unit = 0;
+ ccan_list_for_each(&active_units.head, batch_unit, unode) {
+ ccan_list_for_each(&batch_unit->units.head, child_unit, unode) {
+ if (child_unit->iseq == NULL) continue; // ISEQ is GCed
+
+ char funcname[MAXPATHLEN];
+ sprint_funcname(funcname, sizeof(funcname), child_unit);
+
+ void *func;
+ if ((func = dlsym(handle, funcname)) == NULL) {
+ mjit_warning("skipping to reload '%s' from '%s': %s", funcname, so_file, dlerror());
+ continue;
+ }
+
+ if (child_unit->iseq) { // Check whether GCed or not
+ // Usage of jit_code might be not in a critical section.
+ MJIT_ATOMIC_SET(ISEQ_BODY(child_unit->iseq)->jit_func, (jit_func_t)func);
+ }
+ }
+ }
+ verbose(1, "JIT compaction (%.1fms): Compacted %d methods %s -> %s", end_time - current_cc_ms, active_units_length, c_file, so_file);
+}
+
+#ifndef __clang__
+static const char *
+header_name_end(const char *s)
+{
+ const char *e = s + strlen(s);
+# ifdef __GNUC__ // don't chomp .pch for mswin
+ static const char suffix[] = ".gch";
+
+ // chomp .gch suffix
+ if (e > s+sizeof(suffix)-1 && strcmp(e-sizeof(suffix)+1, suffix) == 0) {
+ e -= sizeof(suffix)-1;
+ }
+# endif
+ return e;
+}
+#endif
+
+// Print platform-specific prerequisites in generated code.
+static void
+compile_prelude(FILE *f)
+{
+#ifndef __clang__ // -include-pch is used for Clang
+ const char *s = pch_file;
+ const char *e = header_name_end(s);
+
+ fprintf(f, "#include \"");
+ // print pch_file except .gch for gcc, but keep .pch for mswin
+ for (; s < e; s++) {
+ switch (*s) {
+ case '\\': case '"':
+ fputc('\\', f);
+ }
+ fputc(*s, f);
+ }
+ fprintf(f, "\"\n");
+#endif
+}
+
+static pid_t
+start_c_compile_unit(struct rb_mjit_unit *unit)
+{
+ extern pid_t rb_mjit_fork();
+ pid_t pid = rb_mjit_fork();
+ if (pid == 0) {
+ int exit_code = c_compile_unit(unit);
+ exit(exit_code);
+ }
+ else {
+ return pid;
+ }
+}
+
+// Capture cc entries of `captured_iseq` and append them to `compiled_iseq->mjit_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->mjit_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)
+{
+ VM_ASSERT(compiled_iseq != NULL);
+ VM_ASSERT(compiled_iseq->mjit_unit != NULL);
+ VM_ASSERT(captured_iseq != NULL);
+
+ struct rb_mjit_unit *unit = compiled_iseq->mjit_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;
+
+ // 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;
+ }
-#include "mjit_worker.c"
+ return cc_entries_index;
+}
-extern int rb_thread_create_mjit_thread(void (*worker_func)(void));
+static void mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info);
// Return an unique file name in /tmp with PREFIX and SUFFIX and
// number ID. Use getpid if ID == 0. The return file name exists
@@ -49,40 +962,6 @@ get_uniq_filename(unsigned long id, const char *prefix, const char *suffix)
return str;
}
-// Wait until workers don't compile any iseq. It is called at the
-// start of GC.
-void
-mjit_gc_start_hook(void)
-{
- if (!mjit_enabled)
- return;
- CRITICAL_SECTION_START(4, "mjit_gc_start_hook");
- while (in_jit) {
- verbose(4, "Waiting wakeup from a worker for GC");
- rb_native_cond_wait(&mjit_client_wakeup, &mjit_engine_mutex);
- verbose(4, "Getting wakeup from a worker for GC");
- }
- in_gc++;
- CRITICAL_SECTION_FINISH(4, "mjit_gc_start_hook");
-}
-
-// Send a signal to workers to continue iseq compilations. It is
-// called at the end of GC.
-void
-mjit_gc_exit_hook(void)
-{
- if (!mjit_enabled)
- return;
- CRITICAL_SECTION_START(4, "mjit_gc_exit_hook");
- in_gc--;
- RUBY_ASSERT_ALWAYS(in_gc >= 0);
- if (!in_gc) {
- verbose(4, "Sending wakeup signal to workers after GC");
- rb_native_cond_broadcast(&mjit_gc_wakeup);
- }
- CRITICAL_SECTION_FINISH(4, "mjit_gc_exit_hook");
-}
-
// Prohibit calling JIT-ed code and let existing JIT-ed frames exit before the next insn.
void
mjit_cancel_all(const char *reason)
@@ -91,6 +970,7 @@ mjit_cancel_all(const char *reason)
return;
mjit_call_p = false;
+ mjit_cancel_p = true;
if (mjit_opts.warnings || mjit_opts.verbose) {
fprintf(stderr, "JIT cancel: Disabled JIT-ed code because %s\n", reason);
}
@@ -104,8 +984,8 @@ mjit_update_references(const rb_iseq_t *iseq)
return;
CRITICAL_SECTION_START(4, "mjit_update_references");
- if (iseq->body->jit_unit) {
- iseq->body->jit_unit->iseq = (rb_iseq_t *)rb_gc_location((VALUE)iseq->body->jit_unit->iseq);
+ if (ISEQ_BODY(iseq)->mjit_unit) {
+ ISEQ_BODY(iseq)->mjit_unit->iseq = (rb_iseq_t *)rb_gc_location((VALUE)ISEQ_BODY(iseq)->mjit_unit->iseq);
// We need to invalidate JIT-ed code for the ISeq because it embeds pointer addresses.
// To efficiently do that, we use the same thing as TracePoint and thus everything is cancelled for now.
// See mjit.h and tool/ruby_vm/views/_mjit_compile_insn.erb for how `mjit_call_p` is used.
@@ -113,10 +993,10 @@ mjit_update_references(const rb_iseq_t *iseq)
}
// Units in stale_units (list of over-speculated and invalidated code) are not referenced from
- // `iseq->body->jit_unit` anymore (because new one replaces that). So we need to check them too.
+ // `ISEQ_BODY(iseq)->mjit_unit` anymore (because new one replaces that). So we need to check them too.
// TODO: we should be able to reduce the number of units checked here.
struct rb_mjit_unit *unit = NULL;
- list_for_each(&stale_units.head, unit, unode) {
+ ccan_list_for_each(&stale_units.head, unit, unode) {
if (unit->iseq == iseq) {
unit->iseq = (rb_iseq_t *)rb_gc_location((VALUE)unit->iseq);
}
@@ -132,24 +1012,20 @@ mjit_free_iseq(const rb_iseq_t *iseq)
if (!mjit_enabled)
return;
- CRITICAL_SECTION_START(4, "mjit_free_iseq");
- 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
+ if (ISEQ_BODY(iseq)->mjit_unit) {
+ // mjit_unit is not freed here because it may be referred by multiple
// lists of units. `get_from_list` and `mjit_finish` do the job.
- iseq->body->jit_unit->iseq = NULL;
+ ISEQ_BODY(iseq)->mjit_unit->iseq = NULL;
}
// Units in stale_units (list of over-speculated and invalidated code) are not referenced from
- // `iseq->body->jit_unit` anymore (because new one replaces that). So we need to check them too.
+ // `ISEQ_BODY(iseq)->mjit_unit` anymore (because new one replaces that). So we need to check them too.
// TODO: we should be able to reduce the number of units checked here.
struct rb_mjit_unit *unit = NULL;
- list_for_each(&stale_units.head, unit, unode) {
+ ccan_list_for_each(&stale_units.head, unit, unode) {
if (unit->iseq == iseq) {
unit->iseq = NULL;
}
}
- CRITICAL_SECTION_FINISH(4, "mjit_free_iseq");
}
// Free unit list. This should be called only when worker is finished
@@ -160,8 +1036,8 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p)
{
struct rb_mjit_unit *unit = 0, *next;
- list_for_each_safe(&list->head, unit, next, unode) {
- list_del(&unit->unode);
+ ccan_list_for_each_safe(&list->head, unit, next, unode) {
+ ccan_list_del(&unit->unode);
if (!close_handle_p) unit->handle = NULL; /* Skip dlclose in free_unit() */
if (list == &stale_units) { // `free_unit(unit)` crashes after GC.compact on `stale_units`
@@ -172,8 +1048,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_temp_files(unit);
- free(unit);
+ xfree(unit);
}
else {
free_unit(unit);
@@ -182,130 +1057,320 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p)
list->length = 0;
}
-// Register a new continuation with execution context `ec`. Return MJIT info about
-// the continuation.
-struct mjit_cont *
-mjit_cont_new(rb_execution_context_t *ec)
+static struct rb_mjit_unit*
+create_unit(enum rb_mjit_unit_type type)
+{
+ struct rb_mjit_unit *unit = ZALLOC_N(struct rb_mjit_unit, 1);
+ unit->id = current_unit_num++;
+ unit->type = type;
+ if (type == MJIT_UNIT_BATCH) {
+ ccan_list_head_init(&unit->units.head);
+ }
+ return unit;
+}
+
+static struct rb_mjit_unit*
+create_iseq_unit(const rb_iseq_t *iseq)
+{
+ struct rb_mjit_unit *unit = create_unit(MJIT_UNIT_ISEQ);
+ unit->iseq = (rb_iseq_t *)iseq;
+ ISEQ_BODY(iseq)->mjit_unit = unit;
+ return unit;
+}
+
+static void mjit_wait(struct rb_mjit_unit *unit);
+
+// Check the unit queue and start mjit_compile if nothing is in progress.
+static void
+check_unit_queue(void)
{
- struct mjit_cont *cont;
+ if (mjit_opts.custom) return; // Custom RubyVM::MJIT.compile is in use
+ if (worker_stopped) return;
+ if (current_cc_pid != 0) return; // still compiling
+
+ // TODO: resurrect unload_units
+ if (active_units_length >= mjit_opts.max_cache_size) return; // wait until unload_units makes a progress
+
+ // No ISEQ in unit_queue has enough calls to trigger JIT
+ if (!mjit_compile_p) return;
+ mjit_compile_p = false;
+
+ // Compile all ISEQs in unit_queue together
+ struct rb_mjit_unit *unit = create_unit(MJIT_UNIT_BATCH);
+ struct rb_mjit_unit *child_unit = NULL;
+ VM_ASSERT(unit_queue.length > 0);
+ while ((child_unit = get_from_list(&unit_queue)) != NULL && (active_units_length + unit->units.length) < mjit_opts.max_cache_size) {
+ add_to_list(child_unit, &unit->units);
+ ISEQ_BODY(child_unit->iseq)->jit_func = (jit_func_t)MJIT_FUNC_COMPILING;
+ }
- // 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;
+ // Run the MJIT compiler synchronously
+ current_cc_ms = real_ms_time();
+ current_cc_unit = unit;
+ bool success = mjit_batch(unit);
+ if (!success) {
+ mjit_notify_waitpid(1);
+ return;
+ }
- CRITICAL_SECTION_START(3, "in mjit_cont_new");
- if (first_cont == NULL) {
- cont->next = cont->prev = NULL;
+ // Run the C compiler asynchronously (unless --mjit-wait)
+ if (mjit_opts.wait) {
+ int exit_code = c_compile_unit(unit);
+ mjit_notify_waitpid(exit_code);
}
else {
- cont->prev = NULL;
- cont->next = first_cont;
- first_cont->prev = cont;
+ current_cc_pid = start_c_compile_unit(unit);
+ if (current_cc_pid == -1) { // JIT failure
+ mjit_notify_waitpid(1);
+ }
}
- first_cont = cont;
- CRITICAL_SECTION_FINISH(3, "in mjit_cont_new");
+}
+
+// Check if it should compact all JIT code and start it as needed
+static void
+check_compaction(void)
+{
+ // Allow only `max_cache_size / 100` times (default: 100) of compaction.
+ // Note: GC of compacted code has not been implemented yet.
+ int max_compact_size = mjit_opts.max_cache_size / 100;
+ if (max_compact_size < 10) max_compact_size = 10;
+
+ // Run JIT compaction only when it's going to add 10%+ units.
+ int throttle_threshold = active_units_length / 10;
+
+ if (compact_units.length < max_compact_size
+ && active_units_length - compact_units_length > throttle_threshold
+ && ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1)
+ || (active_units_length == mjit_opts.max_cache_size))) {
+ struct rb_mjit_unit *unit = create_unit(MJIT_UNIT_COMPACT);
+
+ // Run the MJIT compiler synchronously
+ current_cc_ms = real_ms_time();
+ current_cc_unit = unit;
+ bool success = mjit_compact(unit);
+ if (!success) {
+ mjit_notify_waitpid(1);
+ return;
+ }
- return cont;
+ // Run the C compiler asynchronously (unless --mjit-wait)
+ if (mjit_opts.wait) {
+ int exit_code = c_compile_unit(unit);
+ mjit_notify_waitpid(exit_code);
+ }
+ else {
+ current_cc_pid = start_c_compile_unit(unit);
+ if (current_cc_pid == -1) { // JIT failure
+ mjit_notify_waitpid(1);
+ }
+ }
+ }
}
-// Unregister continuation `cont`.
+// Check the current CC process if any, and start a next C compiler process as needed.
void
-mjit_cont_free(struct mjit_cont *cont)
+mjit_notify_waitpid(int exit_code)
{
- CRITICAL_SECTION_START(3, "in mjit_cont_new");
- if (cont == first_cont) {
- first_cont = cont->next;
- if (first_cont != NULL)
- first_cont->prev = NULL;
+ VM_ASSERT(mjit_opts.wait || current_cc_pid != 0);
+ current_cc_pid = 0;
+
+ // Delete .c file
+ char c_file[MAXPATHLEN];
+ sprint_uniq_filename(c_file, (int)sizeof(c_file), current_cc_unit->id, MJIT_TMP_PREFIX, ".c");
+
+ // Check the result
+ if (exit_code != 0) {
+ verbose(2, "Failed to generate so");
+ // TODO: set MJIT_FUNC_FAILED to unit->units
+ // TODO: free list of unit->units
+ free_unit(current_cc_unit);
+ current_cc_unit = NULL;
+ return;
}
- else {
- cont->prev->next = cont->next;
- if (cont->next != NULL)
- cont->next->prev = cont->prev;
+
+ // Load .so file
+ char so_file[MAXPATHLEN];
+ sprint_uniq_filename(so_file, (int)sizeof(so_file), current_cc_unit->id, MJIT_TMP_PREFIX, DLEXT);
+ switch (current_cc_unit->type) {
+ case MJIT_UNIT_ISEQ:
+ rb_bug("unreachable: current_cc_unit->type must not be MJIT_UNIT_ISEQ");
+ case MJIT_UNIT_BATCH:
+ load_batch_funcs_from_so(current_cc_unit, c_file, so_file);
+ current_cc_unit = NULL;
+
+ // Run compaction if it should
+ if (!stop_worker_p) {
+ check_compaction();
+ }
+ break;
+ case MJIT_UNIT_COMPACT:
+ load_compact_funcs_from_so(current_cc_unit, c_file, so_file);
+ current_cc_unit = NULL;
+ break;
}
- CRITICAL_SECTION_FINISH(3, "in mjit_cont_new");
- free(cont);
+ // Skip further compilation if mjit_finish is trying to stop it
+ if (!stop_worker_p) {
+ // Start the next one as needed
+ check_unit_queue();
+ }
}
-// Finish work with continuation info.
-static void
-finish_conts(void)
+// Return true if given ISeq body should be compiled by MJIT
+static inline int
+mjit_target_iseq_p(const rb_iseq_t *iseq)
{
- struct mjit_cont *cont, *next;
+ struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
+ return (body->type == ISEQ_TYPE_METHOD || body->type == ISEQ_TYPE_BLOCK)
+ && !body->builtin_inline_p
+ && strcmp("<internal:mjit>", RSTRING_PTR(rb_iseq_path(iseq))) != 0;
+}
- for (cont = first_cont; cont != NULL; cont = next) {
- next = cont->next;
- xfree(cont);
- }
+// RubyVM::MJIT
+static VALUE rb_mMJIT = 0;
+// RubyVM::MJIT::C
+static VALUE rb_mMJITC = 0;
+// RubyVM::MJIT::Compiler
+static VALUE rb_cMJITCompiler = 0;
+// RubyVM::MJIT::CPointer::Struct_rb_iseq_t
+static VALUE rb_cMJITIseqPtr = 0;
+// RubyVM::MJIT::CPointer::Struct_IC
+static VALUE rb_cMJITICPtr = 0;
+// RubyVM::MJIT::Compiler
+static VALUE rb_mMJITHooks = 0;
+
+#define WITH_MJIT_DISABLED(stmt) do { \
+ bool original_call_p = mjit_call_p; \
+ mjit_call_p = false; \
+ stmt; \
+ mjit_call_p = original_call_p; \
+ if (mjit_cancel_p) mjit_call_p = false; \
+} while (0);
+
+// Hook MJIT when BOP is redefined.
+MJIT_FUNC_EXPORTED void
+rb_mjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop)
+{
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ WITH_MJIT_DISABLED({
+ rb_funcall(rb_mMJITHooks, rb_intern("on_bop_redefined"), 2, INT2NUM(redefined_flag), INT2NUM((int)bop));
+ });
+}
+
+// Hook MJIT when CME is invalidated.
+MJIT_FUNC_EXPORTED void
+rb_mjit_cme_invalidate(rb_callable_method_entry_t *cme)
+{
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ WITH_MJIT_DISABLED({
+ VALUE cme_klass = rb_funcall(rb_mMJITC, rb_intern("rb_callable_method_entry_struct"), 0);
+ VALUE cme_ptr = rb_funcall(cme_klass, rb_intern("new"), 1, SIZET2NUM((size_t)cme));
+ rb_funcall(rb_mMJITHooks, rb_intern("on_cme_invalidate"), 1, cme_ptr);
+ });
+}
+
+// Hook MJIT when Ractor is spawned.
+void
+rb_mjit_before_ractor_spawn(void)
+{
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ WITH_MJIT_DISABLED({
+ rb_funcall(rb_mMJITHooks, rb_intern("on_ractor_spawn"), 0);
+ });
}
-// Create unit for `iseq`. This function may be called from an MJIT worker.
static void
-create_unit(const rb_iseq_t *iseq)
+mjit_constant_state_changed(void *data)
{
- struct rb_mjit_unit *unit;
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ ID id = (ID)data;
+ WITH_MJIT_DISABLED({
+ rb_funcall(rb_mMJITHooks, rb_intern("on_constant_state_changed"), 1, ID2SYM(id));
+ });
+}
- unit = calloc(1, sizeof(struct rb_mjit_unit));
- if (unit == NULL)
- return;
+// Hook MJIT when constant state is changed.
+MJIT_FUNC_EXPORTED void
+rb_mjit_constant_state_changed(ID id)
+{
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ // Asynchronously hook the Ruby code since this is hooked during a "Ruby critical section".
+ extern int rb_workqueue_register(unsigned flags, rb_postponed_job_func_t func, void *data);
+ rb_workqueue_register(0, mjit_constant_state_changed, (void *)id);
+}
- unit->id = current_unit_num++;
- unit->iseq = (rb_iseq_t *)iseq;
- iseq->body->jit_unit = unit;
+// Hook MJIT when constant IC is updated.
+MJIT_FUNC_EXPORTED void
+rb_mjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx)
+{
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ WITH_MJIT_DISABLED({
+ VALUE iseq_ptr = rb_funcall(rb_cMJITIseqPtr, rb_intern("new"), 1, SIZET2NUM((size_t)iseq));
+ VALUE ic_ptr = rb_funcall(rb_cMJITICPtr, rb_intern("new"), 1, SIZET2NUM((size_t)ic));
+ rb_funcall(rb_mMJITHooks, rb_intern("on_constant_ic_update"), 3, iseq_ptr, ic_ptr, UINT2NUM(insn_idx));
+ });
}
-// Return true if given ISeq body should be compiled by MJIT
-static inline int
-mjit_target_iseq_p(struct rb_iseq_constant_body *body)
+// Hook MJIT when TracePoint is enabled.
+MJIT_FUNC_EXPORTED void
+rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events)
{
- return (body->type == ISEQ_TYPE_METHOD || body->type == ISEQ_TYPE_BLOCK)
- && !body->builtin_inline_p;
+ if (!mjit_enabled || !mjit_call_p || !rb_mMJITHooks) return;
+ WITH_MJIT_DISABLED({
+ rb_funcall(rb_mMJITHooks, rb_intern("on_tracing_invalidate_all"), 1, UINT2NUM(new_iseq_events));
+ });
}
-// If recompile_p is true, the call is initiated by mjit_recompile.
-// This assumes the caller holds CRITICAL_SECTION when recompile_p is true.
+// [experimental] Call custom RubyVM::MJIT.compile if defined
static void
-mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool recompile_p)
+mjit_hook_custom_compile(const rb_iseq_t *iseq)
{
- if (!mjit_enabled || pch_status == PCH_FAILED)
+ WITH_MJIT_DISABLED({
+ VALUE iseq_class = rb_funcall(rb_mMJITC, rb_intern("rb_iseq_t"), 0);
+ VALUE iseq_ptr = rb_funcall(iseq_class, rb_intern("new"), 1, ULONG2NUM((size_t)iseq));
+ VALUE jit_func = rb_funcall(rb_mMJIT, rb_intern("compile"), 1, iseq_ptr);
+ ISEQ_BODY(iseq)->jit_func = (jit_func_t)NUM2ULONG(jit_func);
+ });
+}
+
+static void
+mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info)
+{
+ if (!mjit_enabled) return;
+ if (mjit_opts.custom) { // Hook custom RubyVM::MJIT.compile if defined
+ mjit_hook_custom_compile(iseq);
return;
- if (!mjit_target_iseq_p(iseq->body)) {
- iseq->body->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; // skip mjit_wait
+ }
+ if (pch_status != PCH_SUCCESS || !rb_ractor_main_p()) // TODO: Support non-main Ractors
+ return;
+ if (!mjit_target_iseq_p(iseq)) {
+ ISEQ_BODY(iseq)->jit_func = (jit_func_t)MJIT_FUNC_FAILED; // skip mjit_wait
return;
}
- if (!recompile_p) {
- CRITICAL_SECTION_START(3, "in add_iseq_to_process");
-
- // This prevents multiple Ractors from enqueueing the same ISeq twice.
- if (rb_multi_ractor_p() && (uintptr_t)iseq->body->jit_func != NOT_ADDED_JIT_ISEQ_FUNC) {
- CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process");
- return;
+ // For batching multiple ISEQs, we only enqueue ISEQs when total_calls reaches call_threshold,
+ // and compile all enqueued ISEQs when any ISEQ reaches call_threshold * 2.
+ bool recompile_p = !MJIT_FUNC_STATE_P(ISEQ_BODY(iseq)->jit_func);
+ if (!ISEQ_BODY(iseq)->mjit_unit || recompile_p) { // call_threshold, or recompile
+ // Discard an old unit with recompile_p
+ if (recompile_p) {
+ ISEQ_BODY(iseq)->mjit_unit->iseq = NULL; // Ignore this from compaction
+ ISEQ_BODY(iseq)->jit_func = (jit_func_t)MJIT_FUNC_NOT_COMPILED;
+ active_units_length--;
}
- }
- 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)
- // Failure in creating the unit.
- return;
- if (compile_info != NULL)
- iseq->body->jit_unit->compile_info = *compile_info;
- add_to_list(iseq->body->jit_unit, &unit_queue);
- if (active_units.length >= mjit_opts.max_cache_size) {
- unload_requests++;
+ // Create a new unit and enqueue it
+ struct rb_mjit_unit *unit = create_iseq_unit(iseq);
+ if (recompile_p) {
+ VM_ASSERT(compile_info != NULL);
+ unit->compile_info = *compile_info;
+ }
+ add_to_list(unit, &unit_queue);
+ ISEQ_BODY(iseq)->total_calls = 0; // come here again :)
}
-
- if (!recompile_p) {
- verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process");
- rb_native_cond_broadcast(&mjit_worker_wakeup);
- CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process");
+ else { // call_threshold * 2
+ VM_ASSERT(compile_info == NULL);
+ mjit_compile_p = true; // compile all ISEQs in unit_queue
}
}
@@ -314,93 +1379,65 @@ 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, false);
+ mjit_add_iseq_to_process(iseq, NULL);
+ check_unit_queue();
}
-// For this timeout seconds, --jit-wait will wait for JIT compilation finish.
-#define MJIT_WAIT_TIMEOUT_SECONDS 60
+// For this timeout seconds, mjit_finish will wait for JIT compilation finish.
+#define MJIT_WAIT_TIMEOUT_SECONDS 5
static void
-mjit_wait(struct rb_iseq_constant_body *body)
+mjit_wait(struct rb_mjit_unit *unit)
{
- struct timeval tv;
+ pid_t initial_pid = current_cc_pid;
+ if (initial_pid == 0) {
+ mjit_warning("initial_pid was 0 on mjit_wait");
+ return;
+ }
+ if (pch_status == PCH_FAILED) return;
+
int tries = 0;
- tv.tv_sec = 0;
- tv.tv_usec = 1000;
- while (body->jit_func == (mjit_func_t)NOT_READY_JIT_ISEQ_FUNC) {
+ struct timeval tv = { .tv_sec = 0, .tv_usec = 1000 };
+ while (current_cc_pid == initial_pid) {
tries++;
- if (tries / 1000 > MJIT_WAIT_TIMEOUT_SECONDS || pch_status == PCH_FAILED) {
- CRITICAL_SECTION_START(3, "in rb_mjit_wait_call to set jit_func");
- body->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC; // JIT worker seems dead. Give up.
- CRITICAL_SECTION_FINISH(3, "in rb_mjit_wait_call to set jit_func");
+ if (tries / 1000 > MJIT_WAIT_TIMEOUT_SECONDS) {
+ if (unit->type == MJIT_UNIT_ISEQ) {
+ unit->iseq->body->jit_func = (jit_func_t)MJIT_FUNC_FAILED; // C compiler was too slow. Give up.
+ }
mjit_warning("timed out to wait for JIT finish");
break;
}
- CRITICAL_SECTION_START(3, "in rb_mjit_wait_call for a client wakeup");
- rb_native_cond_broadcast(&mjit_worker_wakeup);
- CRITICAL_SECTION_FINISH(3, "in rb_mjit_wait_call for a client wakeup");
rb_thread_wait_for(tv);
}
}
-// Wait for JIT compilation finish for --jit-wait, and call the function pointer
-// if the compiled result is not NOT_COMPILED_JIT_ISEQ_FUNC.
-VALUE
-rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body)
-{
- if (worker_stopped)
- return Qundef;
-
- mjit_wait(body);
- if ((uintptr_t)body->jit_func <= (uintptr_t)LAST_JIT_ISEQ_FUNC) {
- return Qundef;
- }
- return body->jit_func(ec, ec->cfp);
-}
-
struct rb_mjit_compile_info*
rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body)
{
- assert(body->jit_unit != NULL);
- return &body->jit_unit->compile_info;
+ VM_ASSERT(body->mjit_unit != NULL);
+ return &body->mjit_unit->compile_info;
}
static void
mjit_recompile(const rb_iseq_t *iseq)
{
- if ((uintptr_t)iseq->body->jit_func <= (uintptr_t)LAST_JIT_ISEQ_FUNC)
+ if (MJIT_FUNC_STATE_P(ISEQ_BODY(iseq)->jit_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);
+ verbose(1, "JIT recompile: %s@%s:%d", RSTRING_PTR(ISEQ_BODY(iseq)->location.label),
+ RSTRING_PTR(rb_iseq_path(iseq)), ISEQ_BODY(iseq)->location.first_lineno);
+ VM_ASSERT(ISEQ_BODY(iseq)->mjit_unit != NULL);
- if (UNLIKELY(mjit_opts.wait)) {
- CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq");
- remove_from_list(iseq->body->jit_unit, &active_units);
- add_to_list(iseq->body->jit_unit, &stale_units);
- mjit_add_iseq_to_process(iseq, &iseq->body->jit_unit->compile_info, true);
- CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq");
- mjit_wait(iseq->body);
- }
- else {
- // Lazily move active_units to stale_units to avoid race conditions around active_units with compaction.
- // Also, it's lazily moved to unit_queue as well because otherwise it won't be added to stale_units properly.
- // It's good to avoid a race condition between mjit_add_iseq_to_process and mjit_compile around jit_unit as well.
- CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq");
- iseq->body->jit_unit->stale_p = true;
- iseq->body->jit_func = (mjit_func_t)NOT_READY_JIT_ISEQ_FUNC;
- pending_stale_p = true;
- CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq");
- }
+ mjit_add_iseq_to_process(iseq, &ISEQ_BODY(iseq)->mjit_unit->compile_info);
+ check_unit_queue();
}
// 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;
+ rb_mjit_iseq_compile_info(ISEQ_BODY(iseq))->disable_send_cache = true;
mjit_recompile(iseq);
}
@@ -408,7 +1445,7 @@ rb_mjit_recompile_send(const rb_iseq_t *iseq)
void
rb_mjit_recompile_ivar(const rb_iseq_t *iseq)
{
- rb_mjit_iseq_compile_info(iseq->body)->disable_ivar_cache = true;
+ rb_mjit_iseq_compile_info(ISEQ_BODY(iseq))->disable_ivar_cache = true;
mjit_recompile(iseq);
}
@@ -416,7 +1453,7 @@ rb_mjit_recompile_ivar(const rb_iseq_t *iseq)
void
rb_mjit_recompile_exivar(const rb_iseq_t *iseq)
{
- rb_mjit_iseq_compile_info(iseq->body)->disable_exivar_cache = true;
+ rb_mjit_iseq_compile_info(ISEQ_BODY(iseq))->disable_exivar_cache = true;
mjit_recompile(iseq);
}
@@ -424,7 +1461,7 @@ rb_mjit_recompile_exivar(const rb_iseq_t *iseq)
void
rb_mjit_recompile_inlining(const rb_iseq_t *iseq)
{
- rb_mjit_iseq_compile_info(iseq->body)->disable_inlining = true;
+ rb_mjit_iseq_compile_info(ISEQ_BODY(iseq))->disable_inlining = true;
mjit_recompile(iseq);
}
@@ -432,7 +1469,7 @@ rb_mjit_recompile_inlining(const rb_iseq_t *iseq)
void
rb_mjit_recompile_const(const rb_iseq_t *iseq)
{
- rb_mjit_iseq_compile_info(iseq->body)->disable_const_cache = true;
+ rb_mjit_iseq_compile_info(ISEQ_BODY(iseq))->disable_const_cache = true;
mjit_recompile(iseq);
}
@@ -450,16 +1487,6 @@ init_header_filename(void)
const char *basedir = "";
size_t baselen = 0;
char *p;
-#ifdef _WIN32
- static const char libpathflag[] =
-# ifdef _MSC_VER
- "-LIBPATH:"
-# else
- "-L"
-# endif
- ;
- const size_t libpathflag_len = sizeof(libpathflag) - 1;
-#endif
#ifdef LOAD_RELATIVE
basedir_val = ruby_prefix_path;
@@ -501,7 +1528,6 @@ init_header_filename(void)
}
else
#endif
-#ifndef _MSC_VER
{
// A name of the header file included in any C file generated by MJIT for iseqs.
static const char header_name[] = MJIT_HEADER_INSTALL_DIR "/" MJIT_MIN_HEADER_NAME;
@@ -521,56 +1547,15 @@ init_header_filename(void)
}
pch_file = get_uniq_filename(0, MJIT_TMP_PREFIX "h", ".h.gch");
-#else
- {
- static const char pch_name[] = MJIT_HEADER_INSTALL_DIR "/" MJIT_PRECOMPILED_HEADER_NAME;
- const size_t pch_name_len = sizeof(pch_name) - 1;
-
- pch_file = xmalloc(baselen + pch_name_len + 1);
- p = append_str2(pch_file, basedir, baselen);
- p = append_str2(p, pch_name, pch_name_len + 1);
- if ((fd = rb_cloexec_open(pch_file, O_RDONLY, 0)) < 0) {
- verbose(1, "Cannot access precompiled header file: %s", pch_file);
- xfree(pch_file);
- pch_file = NULL;
- return false;
- }
- (void)close(fd);
- }
-#endif
-
-#ifdef _WIN32
- basedir_val = ruby_archlibdir_path;
- basedir = StringValuePtr(basedir_val);
- baselen = RSTRING_LEN(basedir_val);
- libruby_pathflag = p = xmalloc(libpathflag_len + baselen + 1);
- p = append_str(p, libpathflag);
- p = append_str2(p, basedir, baselen);
- *p = '\0';
-#endif
return true;
}
-#ifdef _WIN32
-UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
-#endif
-
static char *
system_default_tmpdir(void)
{
// c.f. ext/etc/etc.c:etc_systmpdir()
-#ifdef _WIN32
- WCHAR tmppath[_MAX_PATH];
- UINT len = rb_w32_system_tmpdir(tmppath, numberof(tmppath));
- if (len) {
- int blen = WideCharToMultiByte(CP_UTF8, 0, tmppath, len, NULL, 0, NULL, NULL);
- char *tmpdir = xmalloc(blen + 1);
- WideCharToMultiByte(CP_UTF8, 0, tmppath, len, tmpdir, blen, NULL, NULL);
- tmpdir[blen] = '\0';
- return tmpdir;
- }
-#elif defined _CS_DARWIN_USER_TEMP_DIR
+#if defined _CS_DARWIN_USER_TEMP_DIR
char path[MAXPATHLEN];
size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path));
if (len > 0) {
@@ -598,19 +1583,17 @@ check_tmpdir(const char *dir)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
if (!S_ISDIR(st.st_mode)) return FALSE;
-#ifndef _WIN32
-# ifndef S_IWOTH
+#ifndef S_IWOTH
# define S_IWOTH 002
-# endif
+#endif
if (st.st_mode & S_IWOTH) {
-# ifdef S_ISVTX
+#ifdef S_ISVTX
if (!(st.st_mode & S_ISVTX)) return FALSE;
-# else
+#else
return FALSE;
-# endif
+#endif
}
if (access(dir, W_OK)) return FALSE;
-#endif
return TRUE;
}
@@ -631,9 +1614,9 @@ system_tmpdir(void)
// Minimum value for JIT cache size.
#define MIN_CACHE_SIZE 10
// Default permitted number of units with a JIT code kept in memory.
-#define DEFAULT_MAX_CACHE_SIZE 10000
+#define DEFAULT_MAX_CACHE_SIZE 100
// A default threshold used to add iseq to JIT.
-#define DEFAULT_MIN_CALLS_TO_ADD 10000
+#define DEFAULT_CALL_THRESHOLD 10000
// Start MJIT worker. Return TRUE if worker is successfully started.
static bool
@@ -641,17 +1624,6 @@ start_worker(void)
{
stop_worker_p = false;
worker_stopped = false;
-
- if (!rb_thread_create_mjit_thread(mjit_worker)) {
- mjit_enabled = false;
- rb_native_mutex_destroy(&mjit_engine_mutex);
- rb_native_cond_destroy(&mjit_pch_wakeup);
- rb_native_cond_destroy(&mjit_client_wakeup);
- rb_native_cond_destroy(&mjit_worker_wakeup);
- rb_native_cond_destroy(&mjit_gc_wakeup);
- verbose(1, "Failure in MJIT thread initialization\n");
- return false;
- }
return true;
}
@@ -692,30 +1664,108 @@ split_flags(const char *flags)
return ret;
}
+#define opt_match_noarg(s, l, name) \
+ opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --mjit-" name " is ignored"), 1) : 1)
+#define opt_match_arg(s, l, name) \
+ opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--mjit-" name " needs an argument"), 0))
+
+void
+mjit_setup_options(const char *s, struct mjit_options *mjit_opt)
+{
+ const size_t l = strlen(s);
+ if (l == 0) {
+ return;
+ }
+ else if (opt_match_noarg(s, l, "warnings")) {
+ mjit_opt->warnings = true;
+ }
+ else if (opt_match(s, l, "debug")) {
+ if (*s)
+ mjit_opt->debug_flags = strdup(s + 1);
+ else
+ mjit_opt->debug = true;
+ }
+ else if (opt_match_noarg(s, l, "wait")) {
+ mjit_opt->wait = true;
+ }
+ else if (opt_match_noarg(s, l, "save-temps")) {
+ mjit_opt->save_temps = true;
+ }
+ else if (opt_match(s, l, "verbose")) {
+ mjit_opt->verbose = *s ? atoi(s + 1) : 1;
+ }
+ else if (opt_match_arg(s, l, "max-cache")) {
+ mjit_opt->max_cache_size = atoi(s + 1);
+ }
+ else if (opt_match_arg(s, l, "call-threshold")) {
+ mjit_opt->call_threshold = atoi(s + 1);
+ }
+ // --mjit=pause is an undocumented feature for experiments
+ else if (opt_match_noarg(s, l, "pause")) {
+ mjit_opt->pause = true;
+ }
+ else {
+ rb_raise(rb_eRuntimeError,
+ "invalid MJIT option `%s' (--help will show valid MJIT options)", s);
+ }
+}
+
+#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
+const struct ruby_opt_message mjit_option_messages[] = {
+ M("--mjit-warnings", "", "Enable printing JIT warnings"),
+ M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
+ M("--mjit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
+ M("--mjit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
+ M("--mjit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
+ M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: "
+ STRINGIZE(DEFAULT_MAX_CACHE_SIZE) ")"),
+ M("--mjit-call-threshold=num", "", "Number of calls to trigger JIT (for testing, default: "
+ STRINGIZE(DEFAULT_CALL_THRESHOLD) ")"),
+ {0}
+};
+#undef M
+
// Initialize MJIT. Start a thread creating the precompiled header and
// processing ISeqs. The function should be called first for using MJIT.
// If everything is successful, MJIT_INIT_P will be TRUE.
void
mjit_init(const struct mjit_options *opts)
{
+ VM_ASSERT(mjit_enabled);
mjit_opts = *opts;
- mjit_enabled = true;
+
+ // MJIT doesn't support miniruby, but it might reach here by MJIT_FORCE_ENABLE.
+ rb_mMJIT = rb_const_get(rb_cRubyVM, rb_intern("MJIT"));
+ if (!rb_const_defined(rb_mMJIT, rb_intern("Compiler"))) {
+ verbose(1, "Disabling MJIT because RubyVM::MJIT::Compiler is not defined");
+ mjit_enabled = false;
+ return;
+ }
+ rb_mMJITC = rb_const_get(rb_mMJIT, rb_intern("C"));
+ rb_cMJITCompiler = rb_funcall(rb_const_get(rb_mMJIT, rb_intern("Compiler")), rb_intern("new"), 0);
+ rb_cMJITIseqPtr = rb_funcall(rb_mMJITC, rb_intern("rb_iseq_t"), 0);
+ rb_cMJITICPtr = rb_funcall(rb_mMJITC, rb_intern("IC"), 0);
+ rb_funcall(rb_cMJITICPtr, rb_intern("new"), 1, SIZET2NUM(0)); // Trigger no-op constant events before enabling hooks
+ rb_mMJITHooks = rb_const_get(rb_mMJIT, rb_intern("Hooks"));
+
mjit_call_p = true;
+ mjit_pid = getpid();
// Normalize options
- if (mjit_opts.min_calls == 0)
- mjit_opts.min_calls = DEFAULT_MIN_CALLS_TO_ADD;
+ if (mjit_opts.call_threshold == 0)
+ mjit_opts.call_threshold = DEFAULT_CALL_THRESHOLD;
+ if (mjit_opts.call_threshold % 2 == 1) {
+ mjit_opts.call_threshold += 1;
+ mjit_warning("--mjit-call-threshold must be an even number. Using %d instead.", mjit_opts.call_threshold);
+ }
+ mjit_opts.call_threshold /= 2; // Half for enqueue, half for trigger
if (mjit_opts.max_cache_size <= 0)
mjit_opts.max_cache_size = DEFAULT_MAX_CACHE_SIZE;
if (mjit_opts.max_cache_size < MIN_CACHE_SIZE)
mjit_opts.max_cache_size = MIN_CACHE_SIZE;
// Initialize variables for compilation
-#ifdef _MSC_VER
- pch_status = PCH_SUCCESS; // has prebuilt precompiled header
-#else
pch_status = PCH_NOT_READY;
-#endif
cc_path = CC_COMMON_ARGS[0];
verbose(2, "MJIT: CC defaults to %s", cc_path);
cc_common_args = xmalloc(sizeof(CC_COMMON_ARGS));
@@ -723,10 +1773,10 @@ mjit_init(const struct mjit_options *opts)
cc_added_args = split_flags(opts->debug_flags);
xfree(opts->debug_flags);
#if MJIT_CFLAGS_PIPE
- // eliminate a flag incompatible with `-pipe`
+ // Filter out `-save-temps`. It's a C compiler flag used by update-deps and not compatible with `-pipe`.
for (size_t i = 0, j = 0; i < sizeof(CC_COMMON_ARGS) / sizeof(char *); i++) {
if (CC_COMMON_ARGS[i] && strncmp("-save-temps", CC_COMMON_ARGS[i], strlen("-save-temps")) == 0)
- continue; // skip -save-temps flag
+ continue; // Skip `-save-temps`
cc_common_args[j] = CC_COMMON_ARGS[i];
j++;
}
@@ -744,35 +1794,26 @@ mjit_init(const struct mjit_options *opts)
// Initialize mutex
rb_native_mutex_initialize(&mjit_engine_mutex);
- rb_native_cond_initialize(&mjit_pch_wakeup);
- rb_native_cond_initialize(&mjit_client_wakeup);
- rb_native_cond_initialize(&mjit_worker_wakeup);
- rb_native_cond_initialize(&mjit_gc_wakeup);
-
- // 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 worker thread
- start_worker();
+
+ // If --mjit=pause is given, lazily start MJIT when RubyVM::MJIT.resume is called.
+ // You can use it to control MJIT warmup, or to customize the JIT implementation.
+ if (!mjit_opts.pause) {
+ // TODO: Consider running C compiler asynchronously
+ make_pch();
+
+ // Enable MJIT compilation
+ start_worker();
+ }
}
static void
stop_worker(void)
{
- rb_execution_context_t *ec = GET_EC();
-
- while (!worker_stopped) {
- verbose(3, "Sending cancel signal to worker");
- CRITICAL_SECTION_START(3, "in stop_worker");
- stop_worker_p = true; // Setting this inside loop because RUBY_VM_CHECK_INTS may make this false.
- rb_native_cond_broadcast(&mjit_worker_wakeup);
- CRITICAL_SECTION_FINISH(3, "in stop_worker");
- RUBY_VM_CHECK_INTS(ec);
+ stop_worker_p = true;
+ if (current_cc_unit != NULL) {
+ mjit_wait(current_cc_unit);
}
+ worker_stopped = true;
}
// Stop JIT-compiling methods but compiled code is kept available.
@@ -788,15 +1829,8 @@ mjit_pause(bool wait_p)
// Flush all queued units with no option or `wait: true`
if (wait_p) {
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 1000;
-
- while (unit_queue.length > 0 && active_units.length < mjit_opts.max_cache_size) { // inverse of condition that waits for mjit_worker_wakeup
- CRITICAL_SECTION_START(3, "in mjit_pause for a worker wakeup");
- rb_native_cond_broadcast(&mjit_worker_wakeup);
- CRITICAL_SECTION_FINISH(3, "in mjit_pause for a worker wakeup");
- rb_thread_wait_for(tv);
+ while (current_cc_unit != NULL) {
+ mjit_wait(current_cc_unit);
}
}
@@ -815,26 +1849,25 @@ mjit_resume(void)
return Qfalse;
}
+ // Lazily prepare PCH when --mjit=pause is given
+ if (pch_status == PCH_NOT_READY) {
+ if (rb_respond_to(rb_mMJIT, rb_intern("compile"))) {
+ // [experimental] defining RubyVM::MJIT.compile allows you to replace JIT
+ mjit_opts.custom = true;
+ pch_status = PCH_SUCCESS;
+ }
+ else {
+ // Lazy MJIT boot
+ make_pch();
+ }
+ }
+
if (!start_worker()) {
rb_raise(rb_eRuntimeError, "Failed to resume MJIT worker");
}
return Qtrue;
}
-// 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)
-{
- struct rb_mjit_unit *unit = NULL, *next;
-
- // 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) {
-#if defined(_WIN32) // mswin doesn't reach here either. This is for MinGW.
- if (unit->so_file) unit->so_file = NULL;
-#endif
- }
-}
-
// This is called after fork initiated by Ruby's method to launch MJIT worker thread
// for child Ruby process.
//
@@ -856,30 +1889,10 @@ mjit_child_after_fork(void)
if (!mjit_enabled)
return;
- /* Let parent process delete the already-compiled object files.
- This must be done before starting MJIT worker on child process. */
- skip_cleaning_object_files(&active_units);
-
/* MJIT worker thread is not inherited on fork. Start it for this child process. */
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.
@@ -892,39 +1905,16 @@ mjit_finish(bool close_handle_p)
if (!mjit_enabled)
return;
- // Wait for pch finish
- verbose(2, "Stopping worker thread");
- CRITICAL_SECTION_START(3, "in mjit_finish to wakeup from pch");
- // As our threads are detached, we could just cancel them. But it
- // is a bad idea because OS processes (C compiler) started by
- // threads can produce temp files. And even if the temp files are
- // removed, the used C compiler still complaint about their
- // absence. So wait for a clean finish of the threads.
- while (pch_status == PCH_NOT_READY) {
- verbose(3, "Waiting wakeup from make_pch");
- rb_native_cond_wait(&mjit_pch_wakeup, &mjit_engine_mutex);
- }
- CRITICAL_SECTION_FINISH(3, "in mjit_finish to wakeup from pch");
-
// Stop worker
+ verbose(2, "Stopping worker thread");
stop_worker();
rb_native_mutex_destroy(&mjit_engine_mutex);
- rb_native_cond_destroy(&mjit_pch_wakeup);
- rb_native_cond_destroy(&mjit_client_wakeup);
- 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)
+ if (!mjit_opts.save_temps && getpid() == pch_owner_pid && pch_status == PCH_SUCCESS && !mjit_opts.custom)
remove_file(pch_file);
xfree(header_file); header_file = NULL;
-#endif
xfree((void *)cc_common_args); cc_common_args = NULL;
for (char **flag = cc_added_args; *flag != NULL; flag++)
xfree(*flag);
@@ -937,7 +1927,6 @@ mjit_finish(bool close_handle_p)
free_list(&active_units, close_handle_p);
free_list(&compact_units, close_handle_p);
free_list(&stale_units, close_handle_p);
- finish_conts();
mjit_enabled = false;
verbose(1, "Successful MJIT finish");
@@ -945,11 +1934,8 @@ mjit_finish(bool close_handle_p)
// 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().
+// Mark active_units so that we do not GC ISeq which may still be
+// referenced by mjit_recompile() or mjit_compact().
void
mjit_mark(void)
{
@@ -957,38 +1943,16 @@ 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");
- 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);
+ // Mark objects used by the MJIT compiler
+ rb_gc_mark(rb_cMJITCompiler);
+ rb_gc_mark(rb_cMJITIseqPtr);
+ rb_gc_mark(rb_cMJITICPtr);
+ rb_gc_mark(rb_mMJITHooks);
+ // Mark JIT-compiled ISEQs
struct rb_mjit_unit *unit = NULL;
- 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]);
+ ccan_list_for_each(&active_units.head, unit, unode) {
+ rb_gc_mark((VALUE)unit->iseq);
}
RUBY_MARK_LEAVE("mjit");
@@ -999,9 +1963,9 @@ 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++) {
+ if (body->mjit_unit && (cc_entries = body->mjit_unit->cc_entries) != NULL) {
+ // It must be `body->mjit_unit->cc_entries_size` instead of `body->ci_size` to mark children's cc_entries
+ for (unsigned int i = 0; i < body->mjit_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.
@@ -1012,4 +1976,24 @@ mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body)
}
}
+// 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, int id)
+{
+ bool original_call_p = mjit_call_p;
+ mjit_call_p = false; // Avoid impacting JIT metrics by itself
+
+ VALUE iseq_ptr = rb_funcall(rb_cMJITIseqPtr, rb_intern("new"), 1, ULONG2NUM((size_t)iseq));
+ VALUE src = rb_funcall(rb_cMJITCompiler, rb_intern("compile"), 3,
+ iseq_ptr, rb_str_new_cstr(funcname), INT2NUM(id));
+ if (!NIL_P(src)) {
+ fprintf(f, "%s", RSTRING_PTR(src));
+ }
+
+ mjit_call_p = original_call_p;
+ return !NIL_P(src);
+}
+
+#include "mjit.rbinc"
+
#endif // USE_MJIT
diff --git a/mjit.h b/mjit.h
index 813ac0cf21..260cf4af78 100644
--- a/mjit.h
+++ b/mjit.h
@@ -2,9 +2,10 @@
#define RUBY_MJIT_H 1
/**********************************************************************
- mjit.h - Interface to MRI method JIT compiler for Ruby's main thread
+ mjit.h - Interface to MRI method JIT compiler
Copyright (C) 2017 Vladimir Makarov <vmakarov@redhat.com>.
+ Copyright (C) 2017 Takashi Kokubun <k0kubun@ruby-lang.org>.
**********************************************************************/
@@ -14,50 +15,54 @@
# if USE_MJIT
-#include "debug_counter.h"
#include "ruby.h"
+#include "vm_core.h"
// Special address values of a function generated from the
// corresponding iseq by MJIT:
-enum rb_mjit_iseq_func {
- // ISEQ has never been enqueued to unit_queue yet
- NOT_ADDED_JIT_ISEQ_FUNC = 0,
+enum rb_mjit_func_state {
+ // ISEQ has not been compiled yet
+ MJIT_FUNC_NOT_COMPILED = 0,
// ISEQ is already queued for the machine code generation but the
// code is not ready yet for the execution
- NOT_READY_JIT_ISEQ_FUNC = 1,
+ MJIT_FUNC_COMPILING = 1,
// ISEQ included not compilable insn, some internal assertion failed
// or the unit is unloaded
- NOT_COMPILED_JIT_ISEQ_FUNC = 2,
- // End mark
- LAST_JIT_ISEQ_FUNC = 3
+ MJIT_FUNC_FAILED = 2,
};
+// Return true if jit_func is part of enum rb_mjit_func_state
+#define MJIT_FUNC_STATE_P(jit_func) ((uintptr_t)(jit_func) <= (uintptr_t)MJIT_FUNC_FAILED)
// MJIT options which can be defined on the MRI command line.
struct mjit_options {
// Converted from "jit" feature flag to tell the enablement
// information to ruby_show_version().
- char on;
+ bool on;
// Save temporary files after MRI finish. The temporary files
// include the pre-compiled header, C code file generated for ISEQ,
// and the corresponding object file.
- char save_temps;
+ bool save_temps;
// Print MJIT warnings to stderr.
- char warnings;
+ bool warnings;
// Disable compiler optimization and add debug symbols. It can be
// very slow.
- char debug;
+ bool debug;
// Add arbitrary cflags.
char* debug_flags;
- // If not 0, all ISeqs are synchronously compiled. For testing.
- unsigned int wait;
+ // If true, all ISeqs are synchronously compiled. For testing.
+ bool wait;
// Number of calls to trigger JIT compilation. For testing.
- unsigned int min_calls;
+ unsigned int call_threshold;
// Force printing info about MJIT work of level VERBOSE or
// less. 0=silence, 1=medium, 2=verbose.
int verbose;
// Maximal permitted number of iseq JIT codes in a MJIT memory
// cache.
int max_cache_size;
+ // [experimental] Do not start MJIT until MJIT.resume is called.
+ bool pause;
+ // [experimental] Call custom RubyVM::MJIT.compile instead of MJIT.
+ bool custom;
};
// State of optimization switches
@@ -74,14 +79,13 @@ struct rb_mjit_compile_info {
bool disable_const_cache;
};
-typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
+typedef VALUE (*jit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
RUBY_SYMBOL_EXPORT_BEGIN
RUBY_EXTERN struct mjit_options mjit_opts;
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_send(const rb_iseq_t *iseq);
extern void rb_mjit_recompile_ivar(const rb_iseq_t *iseq);
@@ -93,81 +97,18 @@ RUBY_SYMBOL_EXPORT_END
extern void mjit_cancel_all(const char *reason);
extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id);
extern void mjit_init(const struct mjit_options *opts);
-extern void mjit_gc_start_hook(void);
-extern void mjit_gc_exit_hook(void);
extern void mjit_free_iseq(const rb_iseq_t *iseq);
extern void mjit_update_references(const rb_iseq_t *iseq);
extern void mjit_mark(void);
-extern struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec);
-extern void mjit_cont_free(struct mjit_cont *cont);
extern void mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body);
+extern void mjit_notify_waitpid(int exit_code);
-# 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) {
- 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
-mjit_exec(rb_execution_context_t *ec)
-{
- const rb_iseq_t *iseq;
- struct rb_iseq_constant_body *body;
-
- if (!mjit_call_p)
- return Qundef;
- RB_DEBUG_COUNTER_INC(mjit_exec);
-
- iseq = ec->cfp->iseq;
- body = iseq->body;
- body->total_calls++;
-
- 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
- RB_DEBUG_COUNTER_INC(mjit_frame_VM2VM);
-# 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
- RB_DEBUG_COUNTER_INC(mjit_exec_call_func);
- return func(ec, ec->cfp);
-}
+extern void rb_mjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
+extern void rb_mjit_cme_invalidate(rb_callable_method_entry_t *cme);
+extern void rb_mjit_before_ractor_spawn(void);
+extern void rb_mjit_constant_state_changed(ID id);
+extern void rb_mjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx);
+extern void rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);
void mjit_child_after_fork(void);
@@ -183,15 +124,18 @@ void mjit_finish(bool close_handle_p);
# else // USE_MJIT
static inline void mjit_cancel_all(const char *reason){}
-static inline struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec){return NULL;}
-static inline void mjit_cont_free(struct mjit_cont *cont){}
-static inline void mjit_gc_start_hook(void){}
-static inline void mjit_gc_exit_hook(void){}
static inline void mjit_free_iseq(const rb_iseq_t *iseq){}
static inline void mjit_mark(void){}
-static inline VALUE mjit_exec(rb_execution_context_t *ec) { return Qundef; /* unreachable */ }
+static inline VALUE jit_exec(rb_execution_context_t *ec) { return Qundef; /* unreachable */ }
static inline void mjit_child_after_fork(void){}
+static inline void rb_mjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
+static inline void rb_mjit_cme_invalidate(rb_callable_method_entry_t *cme) {}
+static inline void rb_mjit_before_ractor_spawn(void) {}
+static inline void rb_mjit_constant_state_changed(ID id) {}
+static inline void rb_mjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx) {}
+static inline void rb_mjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events) {}
+
#define mjit_enabled false
static inline VALUE mjit_pause(bool wait_p){ return Qnil; } // unreachable
static inline VALUE mjit_resume(void){ return Qnil; } // unreachable
diff --git a/mjit.rb b/mjit.rb
new file mode 100644
index 0000000000..717ab832a4
--- /dev/null
+++ b/mjit.rb
@@ -0,0 +1,37 @@
+module RubyVM::MJIT
+ # Return true if MJIT is enabled.
+ def self.enabled?
+ Primitive.cexpr! 'RBOOL(mjit_enabled)'
+ end
+
+ # Stop generating JITed code.
+ def self.pause(wait: true)
+ Primitive.cexpr! 'mjit_pause(RTEST(wait))'
+ end
+
+ # Start generating JITed code again after pause.
+ def self.resume
+ Primitive.cexpr! 'mjit_resume()'
+ end
+end
+
+if RubyVM::MJIT.enabled?
+ begin
+ require 'fiddle'
+ require 'fiddle/import'
+ rescue LoadError
+ return # miniruby doesn't support MJIT
+ end
+
+ # forward declaration for ruby_vm/mjit/compiler
+ RubyVM::MJIT::C = Object.new # :nodoc:
+
+ require 'ruby_vm/mjit/c_type'
+ require 'ruby_vm/mjit/instruction'
+ require 'ruby_vm/mjit/compiler'
+ require 'ruby_vm/mjit/hooks'
+
+ module RubyVM::MJIT
+ private_constant(*constants)
+ end
+end
diff --git a/mjit_c.c b/mjit_c.c
new file mode 100644
index 0000000000..9ba023e84b
--- /dev/null
+++ b/mjit_c.c
@@ -0,0 +1,43 @@
+/**********************************************************************
+
+ mjit_c.c - C helpers for MJIT
+
+ Copyright (C) 2017 Takashi Kokubun <k0kubun@ruby-lang.org>.
+
+**********************************************************************/
+
+#include "ruby/internal/config.h" // defines USE_MJIT
+
+#if USE_MJIT
+
+#include "mjit.h"
+#include "mjit_c.h"
+#include "internal.h"
+#include "internal/compile.h"
+#include "internal/hash.h"
+#include "yjit.h"
+#include "vm_insnhelper.h"
+
+#include "insns.inc"
+#include "insns_info.inc"
+
+#include "mjit_sp_inc.inc"
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+#define NUM2PTR(x) NUM2ULONG(x)
+#define PTR2NUM(x) ULONG2NUM(x)
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+#define NUM2PTR(x) NUM2ULL(x)
+#define PTR2NUM(x) ULL2NUM(x)
+#endif
+
+// An offsetof implementation that works for unnamed struct and union.
+// Multiplying 8 for compatibility with libclang's offsetof.
+#define OFFSETOF(ptr, member) RB_SIZE2NUM(((char *)&ptr.member - (char*)&ptr) * 8)
+
+#define SIZEOF(type) RB_SIZE2NUM(sizeof(type))
+#define SIGNED_TYPE_P(type) RBOOL((type)(-1) < (type)(1))
+
+#include "mjit_c.rbinc"
+
+#endif // USE_MJIT
diff --git a/mjit_c.h b/mjit_c.h
new file mode 100644
index 0000000000..cc4040c9df
--- /dev/null
+++ b/mjit_c.h
@@ -0,0 +1,97 @@
+// This file is parsed by tool/mjit/generate.rb to generate mjit_c.rb
+#ifndef MJIT_C_H
+#define MJIT_C_H
+
+#include "ruby/internal/config.h"
+#include "vm_core.h"
+#include "vm_callinfo.h"
+#include "builtin.h"
+#include "ccan/list/list.h"
+#include "mjit.h"
+#include "shape.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)
+
+// Linked list of struct rb_mjit_unit.
+struct rb_mjit_unit_list {
+ struct ccan_list_head head;
+ int length; // the list length
+};
+
+enum rb_mjit_unit_type {
+ // Single-ISEQ unit for unit_queue
+ MJIT_UNIT_ISEQ = 0,
+ // Multi-ISEQ unit for mjit_batch
+ MJIT_UNIT_BATCH = 1,
+ // All-ISEQ unit for mjit_compact
+ MJIT_UNIT_COMPACT = 2,
+};
+
+// The unit structure that holds metadata of ISeq for MJIT.
+// TODO: Use different structs for ISEQ and BATCH/COMPACT
+struct rb_mjit_unit {
+ struct ccan_list_node unode;
+ // Unique order number of unit.
+ int id;
+ // Type of this unit
+ enum rb_mjit_unit_type type;
+
+ /* MJIT_UNIT_ISEQ */
+ // ISEQ for a non-batch unit
+ rb_iseq_t *iseq;
+ // Only used by unload_units. Flag to check this unit is currently on stack or not.
+ bool used_code_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;
+ // ISEQ_BODY(iseq)->ci_size + ones of inlined iseqs
+ unsigned int cc_entries_size;
+
+ /* MJIT_UNIT_BATCH, MJIT_UNIT_COMPACT */
+ // Dlopen handle of the loaded object file.
+ void *handle;
+ // Units compacted by this batch
+ struct rb_mjit_unit_list units; // MJIT_UNIT_BATCH only
+};
+
+// Storage to keep data which is consistent in each conditional branch.
+// This is created and used for one `compile_insns` call and its values
+// should be copied for extra `compile_insns` call.
+struct compile_branch {
+ unsigned int stack_size; // this simulates sp (stack pointer) of YARV
+ bool finish_p; // if true, compilation in this branch should stop and let another branch to be compiled
+};
+
+// For propagating information needed for lazily pushing a frame.
+struct inlined_call_context {
+ int orig_argc; // ci->orig_argc
+ 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
+// which is global during one `mjit_compile` call. Ones conditional
+// in each branch should be stored in `compile_branch`.
+struct compile_status {
+ bool success; // has true if compilation has had no issue
+ int *stack_size_for_pos; // stack_size_for_pos[pos] has stack size for the position (otherwise -1)
+ // 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;
+ // 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;
+ // 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;
+};
+
+#endif /* MJIT_C_H */
diff --git a/mjit_c.rb b/mjit_c.rb
new file mode 100644
index 0000000000..966289c5ab
--- /dev/null
+++ b/mjit_c.rb
@@ -0,0 +1,807 @@
+# frozen_string_literal: true
+# Part of this file is generated by tool/mjit/bindgen.rb.
+# Run `make mjit-bindgen` to update code between "MJIT bindgen begin" and "MJIT bindgen end".
+module RubyVM::MJIT # :nodoc: all
+ # This `class << C` section is for calling C functions. For importing variables
+ # or macros as is, please consider using tool/mjit/bindgen.rb instead.
+ class << C
+ def rb_hash_values(cdhash_addr)
+ Primitive.cexpr! 'rb_hash_values((VALUE)NUM2PTR(cdhash_addr))'
+ end
+
+ def builtin_compiler(buf, bf_ptr, index, stack_size, builtin_inline_p)
+ _bf_addr = bf_ptr.to_i
+ # Call "mjit_compile_invokebuiltin_for_#{func}" in mk_builtin_loader.rb
+ Primitive.cstmt! %{
+ RB_BUILTIN bf = (RB_BUILTIN)NUM2PTR(_bf_addr);
+ bf->compiler(buf, NIL_P(index) ? -1 : NUM2LONG(index), NUM2UINT(stack_size), RTEST(builtin_inline_p));
+ return Qnil;
+ }
+ end
+
+ def has_cache_for_send(cc_ptr, insn)
+ _cc_addr = cc_ptr.to_i
+ Primitive.cstmt! %{
+ extern bool rb_vm_opt_cfunc_p(CALL_CACHE cc, int insn);
+ CALL_CACHE cc = (CALL_CACHE)NUM2PTR(_cc_addr);
+ bool has_cache = vm_cc_cme(cc) != NULL &&
+ !(vm_cc_cme(cc)->def->type == VM_METHOD_TYPE_CFUNC && rb_vm_opt_cfunc_p(cc, NUM2INT(insn)));
+ return RBOOL(has_cache);
+ }
+ end
+
+ def rb_shape_get_shape_by_id(shape_id)
+ _shape_id = shape_id.to_i
+ shape_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_shape_get_shape_by_id((shape_id_t)NUM2UINT(_shape_id)))'
+ rb_shape_t.new(shape_addr)
+ end
+
+ def rb_iseq_check(iseq)
+ _iseq_addr = iseq.to_i
+ iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseq_check((rb_iseq_t *)NUM2PTR(_iseq_addr)))'
+ rb_iseq_t.new(iseq_addr)
+ end
+
+ def rb_iseq_path(iseq)
+ _iseq_addr = iseq.to_i
+ Primitive.cexpr! 'rb_iseq_path((rb_iseq_t *)NUM2PTR(_iseq_addr))'
+ end
+
+ def rb_iseq_first_lineno(iseq)
+ _iseq_addr = iseq.to_i
+ Primitive.cexpr! 'rb_iseq_first_lineno((rb_iseq_t *)NUM2PTR(_iseq_addr))'
+ end
+
+ def vm_ci_argc(ci)
+ _ci_addr = ci.to_i
+ Primitive.cexpr! 'UINT2NUM(vm_ci_argc((CALL_INFO)NUM2PTR(_ci_addr)))'
+ end
+
+ def vm_ci_flag(ci)
+ _ci_addr = ci.to_i
+ Primitive.cexpr! 'UINT2NUM(vm_ci_flag((CALL_INFO)NUM2PTR(_ci_addr)))'
+ end
+
+ def rb_splat_or_kwargs_p(ci)
+ _ci_addr = ci.to_i
+ Primitive.cstmt! %{
+ extern bool rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci);
+ return RBOOL(rb_splat_or_kwargs_p((CALL_INFO)NUM2PTR(_ci_addr)));
+ }
+ end
+
+ # Returns true if iseq can use fastpath for setup, otherwise NULL. This becomes true in the same condition
+ # as CC_SET_FASTPATH (in vm_callee_setup_arg) is called from vm_call_iseq_setup.
+ def fastpath_applied_iseq_p(ci_ptr, cc_ptr, iseq_ptr)
+ _ci_addr = ci_ptr.to_i
+ _cc_addr = cc_ptr.to_i
+ _iseq_addr = iseq_ptr.to_i
+ Primitive.cstmt! %q{
+ extern bool rb_simple_iseq_p(const rb_iseq_t *iseq);
+ CALL_INFO ci = (CALL_INFO)NUM2PTR(_ci_addr);
+ CALL_CACHE cc = (CALL_CACHE)NUM2PTR(_cc_addr);
+ const rb_iseq_t *iseq = (rb_iseq_t *)NUM2PTR(_iseq_addr);
+
+ bool result = iseq != NULL
+ && !(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(iseq)->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 RBOOL(result);
+ }
+ end
+
+ def mjit_opts
+ addr = Primitive.cexpr! 'PTR2NUM((VALUE)&mjit_opts)'
+ mjit_options.new(addr)
+ end
+
+ def mjit_call_attribute_sp_inc(insn, operands)
+ _operands_addr = operands.to_i
+ Primitive.cexpr! 'LONG2NUM(mjit_call_attribute_sp_inc(NUM2INT(insn), (VALUE *)NUM2PTR(_operands_addr)))'
+ end
+
+ def mjit_capture_cc_entries(compiled_body, captured_body)
+ _compiled_body_addr = compiled_body.to_i
+ _captured_body_addr = captured_body.to_i
+ Primitive.cstmt! %{
+ extern int mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq);
+ return INT2NUM(mjit_capture_cc_entries((struct rb_iseq_constant_body *)NUM2PTR(_compiled_body_addr), (struct rb_iseq_constant_body *)NUM2PTR(_captured_body_addr)));
+ }
+ end
+
+ def mjit_cancel_all(reason)
+ Primitive.cstmt! %{
+ mjit_cancel_all(RSTRING_PTR(reason));
+ return Qnil;
+ }
+ end
+
+ # Convert encoded VM pointers to insn BINs.
+ def rb_vm_insn_decode(encoded)
+ Primitive.cexpr! 'INT2NUM(rb_vm_insn_decode(NUM2PTR(encoded)))'
+ end
+
+ # Convert insn BINs to encoded VM pointers. This one is not used by the compiler, but useful for debugging.
+ def rb_vm_insn_encode(bin)
+ Primitive.cexpr! 'PTR2NUM((VALUE)rb_vm_get_insns_address_table()[NUM2INT(bin)])'
+ end
+
+ def insn_may_depend_on_sp_or_pc(insn, opes)
+ _opes_addr = opes.to_i
+ Primitive.cexpr! 'RBOOL(insn_may_depend_on_sp_or_pc(NUM2INT(insn), (VALUE *)NUM2PTR(_opes_addr)))'
+ end
+
+ # Convert Integer VALUE to an actual Ruby object
+ def to_ruby(value)
+ Primitive.cexpr! '(VALUE)NUM2PTR(value)'
+ end
+
+ # Convert RubyVM::InstructionSequence to C.rb_iseq_t. Not used by the compiler, but useful for debugging.
+ def rb_iseqw_to_iseq(iseqw)
+ iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseqw_to_iseq(iseqw))'
+ rb_iseq_t.new(iseq_addr)
+ end
+ end
+
+ ### MJIT bindgen begin ###
+
+ def C.USE_LAZY_LOAD
+ Primitive.cexpr! %q{ RBOOL(USE_LAZY_LOAD != 0) }
+ end
+
+ def C.NOT_COMPILED_STACK_SIZE
+ Primitive.cexpr! %q{ INT2NUM(NOT_COMPILED_STACK_SIZE) }
+ end
+
+ def C.VM_CALL_KW_SPLAT
+ Primitive.cexpr! %q{ INT2NUM(VM_CALL_KW_SPLAT) }
+ end
+
+ def C.VM_CALL_KW_SPLAT_bit
+ Primitive.cexpr! %q{ INT2NUM(VM_CALL_KW_SPLAT_bit) }
+ end
+
+ def C.VM_CALL_TAILCALL
+ Primitive.cexpr! %q{ INT2NUM(VM_CALL_TAILCALL) }
+ end
+
+ def C.VM_CALL_TAILCALL_bit
+ Primitive.cexpr! %q{ INT2NUM(VM_CALL_TAILCALL_bit) }
+ end
+
+ def C.VM_METHOD_TYPE_CFUNC
+ Primitive.cexpr! %q{ INT2NUM(VM_METHOD_TYPE_CFUNC) }
+ end
+
+ def C.VM_METHOD_TYPE_ISEQ
+ Primitive.cexpr! %q{ INT2NUM(VM_METHOD_TYPE_ISEQ) }
+ end
+
+ def C.RUBY_EVENT_CLASS
+ Primitive.cexpr! %q{ UINT2NUM(RUBY_EVENT_CLASS) }
+ end
+
+ def C.SHAPE_CAPACITY_CHANGE
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_CAPACITY_CHANGE) }
+ end
+
+ def C.SHAPE_FLAG_SHIFT
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_FLAG_SHIFT) }
+ end
+
+ def C.SHAPE_FROZEN
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_FROZEN) }
+ end
+
+ def C.SHAPE_ID_NUM_BITS
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_ID_NUM_BITS) }
+ end
+
+ def C.SHAPE_INITIAL_CAPACITY
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_INITIAL_CAPACITY) }
+ end
+
+ def C.SHAPE_IVAR
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_IVAR) }
+ end
+
+ def C.SHAPE_ROOT
+ Primitive.cexpr! %q{ UINT2NUM(SHAPE_ROOT) }
+ end
+
+ def C.INVALID_SHAPE_ID
+ Primitive.cexpr! %q{ ULONG2NUM(INVALID_SHAPE_ID) }
+ end
+
+ def C.SHAPE_MASK
+ Primitive.cexpr! %q{ ULONG2NUM(SHAPE_MASK) }
+ end
+
+ def C.rb_cFalseClass
+ Primitive.cexpr! %q{ PTR2NUM(rb_cFalseClass) }
+ end
+
+ def C.rb_cFloat
+ Primitive.cexpr! %q{ PTR2NUM(rb_cFloat) }
+ end
+
+ def C.rb_cInteger
+ Primitive.cexpr! %q{ PTR2NUM(rb_cInteger) }
+ end
+
+ def C.rb_cNilClass
+ Primitive.cexpr! %q{ PTR2NUM(rb_cNilClass) }
+ end
+
+ def C.rb_cSymbol
+ Primitive.cexpr! %q{ PTR2NUM(rb_cSymbol) }
+ end
+
+ def C.rb_cTrueClass
+ Primitive.cexpr! %q{ PTR2NUM(rb_cTrueClass) }
+ end
+
+ def C.CALL_DATA
+ @CALL_DATA ||= self.rb_call_data
+ end
+
+ def C.IC
+ @IC ||= self.iseq_inline_constant_cache
+ end
+
+ def C.IVC
+ @IVC ||= self.iseq_inline_iv_cache_entry
+ end
+
+ def C.RB_BUILTIN
+ @RB_BUILTIN ||= self.rb_builtin_function
+ end
+
+ def C.attr_index_t
+ @attr_index_t ||= CType::Immediate.parse("uint32_t")
+ end
+
+ def C.compile_branch
+ @compile_branch ||= CType::Struct.new(
+ "compile_branch", Primitive.cexpr!("SIZEOF(struct compile_branch)"),
+ stack_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct compile_branch *)NULL)), stack_size)")],
+ finish_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct compile_branch *)NULL)), finish_p)")],
+ )
+ end
+
+ def C.compile_status
+ @compile_status ||= CType::Struct.new(
+ "compile_status", Primitive.cexpr!("SIZEOF(struct compile_status)"),
+ success: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), success)")],
+ stack_size_for_pos: [CType::Pointer.new { CType::Immediate.parse("int") }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), stack_size_for_pos)")],
+ local_stack_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), local_stack_p)")],
+ cc_entries_index: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), cc_entries_index)")],
+ compiled_iseq: [CType::Pointer.new { self.rb_iseq_constant_body }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compiled_iseq)")],
+ compiled_id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compiled_id)")],
+ compile_info: [CType::Pointer.new { self.rb_mjit_compile_info }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compile_info)")],
+ inlined_iseqs: [CType::Pointer.new { CType::Pointer.new { self.rb_iseq_constant_body } }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inlined_iseqs)")],
+ inline_context: [self.inlined_call_context, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inline_context)")],
+ )
+ end
+
+ def C.inlined_call_context
+ @inlined_call_context ||= CType::Struct.new(
+ "inlined_call_context", Primitive.cexpr!("SIZEOF(struct inlined_call_context)"),
+ orig_argc: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct inlined_call_context *)NULL)), orig_argc)")],
+ me: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct inlined_call_context *)NULL)), me)")],
+ param_size: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct inlined_call_context *)NULL)), param_size)")],
+ local_size: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct inlined_call_context *)NULL)), local_size)")],
+ )
+ end
+
+ def C.iseq_inline_constant_cache
+ @iseq_inline_constant_cache ||= CType::Struct.new(
+ "iseq_inline_constant_cache", Primitive.cexpr!("SIZEOF(struct iseq_inline_constant_cache)"),
+ entry: [CType::Pointer.new { self.iseq_inline_constant_cache_entry }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache *)NULL)), entry)")],
+ segments: [CType::Pointer.new { self.ID }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache *)NULL)), segments)")],
+ )
+ end
+
+ def C.iseq_inline_constant_cache_entry
+ @iseq_inline_constant_cache_entry ||= CType::Struct.new(
+ "iseq_inline_constant_cache_entry", Primitive.cexpr!("SIZEOF(struct iseq_inline_constant_cache_entry)"),
+ flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), flags)")],
+ value: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), value)")],
+ _unused1: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), _unused1)")],
+ _unused2: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), _unused2)")],
+ ic_cref: [CType::Pointer.new { self.rb_cref_t }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), ic_cref)")],
+ )
+ end
+
+ def C.iseq_inline_iv_cache_entry
+ @iseq_inline_iv_cache_entry ||= CType::Struct.new(
+ "iseq_inline_iv_cache_entry", Primitive.cexpr!("SIZEOF(struct iseq_inline_iv_cache_entry)"),
+ value: [CType::Immediate.parse("uintptr_t"), Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), value)")],
+ iv_set_name: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), iv_set_name)")],
+ )
+ end
+
+ def C.iseq_inline_storage_entry
+ @iseq_inline_storage_entry ||= CType::Union.new(
+ "iseq_inline_storage_entry", Primitive.cexpr!("SIZEOF(union iseq_inline_storage_entry)"),
+ once: CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((union iseq_inline_storage_entry *)NULL)->once)"),
+ running_thread: [CType::Pointer.new { self.rb_thread_struct }, Primitive.cexpr!("OFFSETOF(((union iseq_inline_storage_entry *)NULL)->once, running_thread)")],
+ value: [self.VALUE, Primitive.cexpr!("OFFSETOF(((union iseq_inline_storage_entry *)NULL)->once, value)")],
+ ),
+ ic_cache: self.iseq_inline_constant_cache,
+ iv_cache: self.iseq_inline_iv_cache_entry,
+ )
+ end
+
+ def C.mjit_options
+ @mjit_options ||= CType::Struct.new(
+ "mjit_options", Primitive.cexpr!("SIZEOF(struct mjit_options)"),
+ on: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), on)")],
+ save_temps: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), save_temps)")],
+ warnings: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), warnings)")],
+ debug: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), debug)")],
+ debug_flags: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), debug_flags)")],
+ wait: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), wait)")],
+ call_threshold: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), call_threshold)")],
+ verbose: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), verbose)")],
+ max_cache_size: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), max_cache_size)")],
+ pause: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), pause)")],
+ custom: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct mjit_options *)NULL)), custom)")],
+ )
+ end
+
+ def C.rb_builtin_function
+ @rb_builtin_function ||= CType::Struct.new(
+ "rb_builtin_function", Primitive.cexpr!("SIZEOF(struct rb_builtin_function)"),
+ func_ptr: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), func_ptr)")],
+ argc: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), argc)")],
+ index: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), index)")],
+ name: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), name)")],
+ compiler: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), compiler)")],
+ )
+ end
+
+ def C.rb_call_data
+ @rb_call_data ||= CType::Struct.new(
+ "rb_call_data", Primitive.cexpr!("SIZEOF(struct rb_call_data)"),
+ ci: [CType::Pointer.new { self.rb_callinfo }, Primitive.cexpr!("OFFSETOF((*((struct rb_call_data *)NULL)), ci)")],
+ cc: [CType::Pointer.new { self.rb_callcache }, Primitive.cexpr!("OFFSETOF((*((struct rb_call_data *)NULL)), cc)")],
+ )
+ end
+
+ def C.rb_callable_method_entry_struct
+ @rb_callable_method_entry_struct ||= CType::Struct.new(
+ "rb_callable_method_entry_struct", Primitive.cexpr!("SIZEOF(struct rb_callable_method_entry_struct)"),
+ flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), flags)")],
+ defined_class: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), defined_class)")],
+ def: [CType::Pointer.new { self.rb_method_definition_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), def)")],
+ called_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), called_id)")],
+ owner: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), owner)")],
+ )
+ end
+
+ def C.rb_callcache
+ @rb_callcache ||= CType::Struct.new(
+ "rb_callcache", Primitive.cexpr!("SIZEOF(struct rb_callcache)"),
+ flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), flags)")],
+ klass: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), klass)")],
+ cme_: [CType::Pointer.new { self.rb_callable_method_entry_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), cme_)")],
+ call_: [self.vm_call_handler, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), call_)")],
+ aux_: [CType::Union.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_callcache *)NULL)->aux_)"),
+ attr: CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_callcache *)NULL)->aux_.attr)"),
+ value: [CType::Immediate.parse("uintptr_t"), Primitive.cexpr!("OFFSETOF(((struct rb_callcache *)NULL)->aux_.attr, value)")],
+ ),
+ method_missing_reason: self.method_missing_reason,
+ v: self.VALUE,
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), aux_)")],
+ )
+ end
+
+ def C.rb_callinfo
+ @rb_callinfo ||= CType::Struct.new(
+ "rb_callinfo", Primitive.cexpr!("SIZEOF(struct rb_callinfo)"),
+ flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), flags)")],
+ kwarg: [CType::Pointer.new { self.rb_callinfo_kwarg }, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), kwarg)")],
+ mid: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), mid)")],
+ flag: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), flag)")],
+ argc: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), argc)")],
+ )
+ end
+
+ def C.rb_control_frame_t
+ @rb_control_frame_t ||= CType::Struct.new(
+ "rb_control_frame_struct", Primitive.cexpr!("SIZEOF(struct rb_control_frame_struct)"),
+ pc: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), pc)")],
+ sp: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), sp)")],
+ iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), iseq)")],
+ self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), self)")],
+ ep: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), ep)")],
+ block_code: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), block_code)")],
+ __bp__: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), __bp__)")],
+ jit_return: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), jit_return)")],
+ )
+ end
+
+ def C.rb_cref_t
+ @rb_cref_t ||= CType::Struct.new(
+ "rb_cref_struct", Primitive.cexpr!("SIZEOF(struct rb_cref_struct)"),
+ flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), flags)")],
+ refinements: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), refinements)")],
+ klass_or_self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), klass_or_self)")],
+ next: [CType::Pointer.new { self.rb_cref_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), next)")],
+ scope_visi: [self.rb_scope_visibility_t, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), scope_visi)")],
+ )
+ end
+
+ def C.rb_execution_context_struct
+ @rb_execution_context_struct ||= CType::Struct.new(
+ "rb_execution_context_struct", Primitive.cexpr!("SIZEOF(struct rb_execution_context_struct)"),
+ vm_stack: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), vm_stack)")],
+ vm_stack_size: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), vm_stack_size)")],
+ cfp: [CType::Pointer.new { self.rb_control_frame_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), cfp)")],
+ tag: [CType::Pointer.new { self.rb_vm_tag }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), tag)")],
+ interrupt_flag: [self.rb_atomic_t, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), interrupt_flag)")],
+ interrupt_mask: [self.rb_atomic_t, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), interrupt_mask)")],
+ fiber_ptr: [CType::Pointer.new { self.rb_fiber_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), fiber_ptr)")],
+ thread_ptr: [CType::Pointer.new { self.rb_thread_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), thread_ptr)")],
+ local_storage: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), local_storage)")],
+ local_storage_recursive_hash: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), local_storage_recursive_hash)")],
+ local_storage_recursive_hash_for_trace: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), local_storage_recursive_hash_for_trace)")],
+ storage: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), storage)")],
+ root_lep: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), root_lep)")],
+ root_svar: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), root_svar)")],
+ ensure_list: [CType::Pointer.new { self.rb_ensure_list_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), ensure_list)")],
+ trace_arg: [CType::Pointer.new { self.rb_trace_arg_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), trace_arg)")],
+ errinfo: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), errinfo)")],
+ passed_block_handler: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), passed_block_handler)")],
+ raised_flag: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), raised_flag)")],
+ private_const_reference: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), private_const_reference)")],
+ machine: [CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_execution_context_struct *)NULL)->machine)"),
+ stack_start: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_start)")],
+ stack_end: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_end)")],
+ stack_maxsize: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_maxsize)")],
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), machine)")],
+ )
+ end
+
+ def C.rb_execution_context_t
+ @rb_execution_context_t ||= self.rb_execution_context_struct
+ end
+
+ def C.rb_iseq_constant_body
+ @rb_iseq_constant_body ||= CType::Struct.new(
+ "rb_iseq_constant_body", Primitive.cexpr!("SIZEOF(struct rb_iseq_constant_body)"),
+ type: [self.rb_iseq_type, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), type)")],
+ iseq_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), iseq_size)")],
+ iseq_encoded: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), iseq_encoded)")],
+ param: [CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->param)"),
+ flags: [CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->param.flags)"),
+ has_lead: [CType::BitField.new(1, 0), 0],
+ has_opt: [CType::BitField.new(1, 1), 1],
+ has_rest: [CType::BitField.new(1, 2), 2],
+ has_post: [CType::BitField.new(1, 3), 3],
+ has_kw: [CType::BitField.new(1, 4), 4],
+ has_kwrest: [CType::BitField.new(1, 5), 5],
+ has_block: [CType::BitField.new(1, 6), 6],
+ ambiguous_param0: [CType::BitField.new(1, 7), 7],
+ accepts_no_kwarg: [CType::BitField.new(1, 0), 8],
+ ruby2_keywords: [CType::BitField.new(1, 1), 9],
+ ), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, flags)")],
+ size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, size)")],
+ lead_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, lead_num)")],
+ opt_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, opt_num)")],
+ rest_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, rest_start)")],
+ post_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, post_start)")],
+ post_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, post_num)")],
+ block_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, block_start)")],
+ opt_table: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, opt_table)")],
+ keyword: [CType::Pointer.new { self.rb_iseq_param_keyword }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, keyword)")],
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), param)")],
+ location: [self.rb_iseq_location_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), location)")],
+ insns_info: [self.iseq_insn_info, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), insns_info)")],
+ local_table: [CType::Pointer.new { self.ID }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), local_table)")],
+ catch_table: [CType::Pointer.new { self.iseq_catch_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), catch_table)")],
+ parent_iseq: [CType::Pointer.new { self.rb_iseq_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), parent_iseq)")],
+ local_iseq: [CType::Pointer.new { self.rb_iseq_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), local_iseq)")],
+ is_entries: [CType::Pointer.new { self.iseq_inline_storage_entry }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), is_entries)")],
+ call_data: [CType::Pointer.new { self.rb_call_data }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), call_data)")],
+ variable: [CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->variable)"),
+ flip_count: [self.rb_snum_t, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, flip_count)")],
+ script_lines: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, script_lines)")],
+ coverage: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, coverage)")],
+ pc2branchindex: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, pc2branchindex)")],
+ original_iseq: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, original_iseq)")],
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), variable)")],
+ local_table_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), local_table_size)")],
+ ic_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ic_size)")],
+ ise_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ise_size)")],
+ ivc_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ivc_size)")],
+ icvarc_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), icvarc_size)")],
+ ci_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ci_size)")],
+ stack_max: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), stack_max)")],
+ catch_except_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), catch_except_p)")],
+ builtin_inline_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), builtin_inline_p)")],
+ mark_bits: [CType::Union.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->mark_bits)"),
+ list: CType::Pointer.new { self.iseq_bits_t },
+ single: self.iseq_bits_t,
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), mark_bits)")],
+ outer_variables: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), outer_variables)")],
+ mandatory_only_iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), mandatory_only_iseq)")],
+ jit_func: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_func)")],
+ total_calls: [CType::Immediate.parse("unsigned long"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), total_calls)")],
+ mjit_unit: [CType::Pointer.new { self.rb_mjit_unit }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), mjit_unit)")],
+ )
+ end
+
+ def C.rb_iseq_location_t
+ @rb_iseq_location_t ||= CType::Struct.new(
+ "rb_iseq_location_struct", Primitive.cexpr!("SIZEOF(struct rb_iseq_location_struct)"),
+ pathobj: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), pathobj)"), true],
+ base_label: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), base_label)"), true],
+ label: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), label)"), true],
+ first_lineno: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), first_lineno)"), true],
+ node_id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), node_id)")],
+ code_location: [self.rb_code_location_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), code_location)")],
+ )
+ end
+
+ def C.rb_iseq_struct
+ @rb_iseq_struct ||= CType::Struct.new(
+ "rb_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_iseq_struct)"),
+ flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), flags)")],
+ wrapper: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), wrapper)")],
+ body: [CType::Pointer.new { self.rb_iseq_constant_body }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), body)")],
+ aux: [CType::Union.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_struct *)NULL)->aux)"),
+ compile_data: CType::Pointer.new { self.iseq_compile_data },
+ loader: CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_struct *)NULL)->aux.loader)"),
+ obj: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.loader, obj)")],
+ index: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.loader, index)")],
+ ),
+ exec: CType::Struct.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_struct *)NULL)->aux.exec)"),
+ local_hooks: [CType::Pointer.new { self.rb_hook_list_struct }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.exec, local_hooks)")],
+ global_trace_events: [self.rb_event_flag_t, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.exec, global_trace_events)")],
+ ),
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), aux)")],
+ )
+ end
+
+ def C.rb_iseq_t
+ @rb_iseq_t ||= self.rb_iseq_struct
+ end
+
+ def C.rb_method_definition_struct
+ @rb_method_definition_struct ||= CType::Struct.new(
+ "rb_method_definition_struct", Primitive.cexpr!("SIZEOF(struct rb_method_definition_struct)"),
+ type: [CType::BitField.new(4, 0), 0],
+ iseq_overload: [CType::BitField.new(1, 4), 4],
+ no_redef_warning: [CType::BitField.new(1, 5), 5],
+ aliased: [CType::BitField.new(1, 6), 6],
+ reference_count: [CType::BitField.new(28, 0), 32],
+ body: [CType::Union.new(
+ "", Primitive.cexpr!("SIZEOF(((struct rb_method_definition_struct *)NULL)->body)"),
+ iseq: self.rb_method_iseq_t,
+ cfunc: self.rb_method_cfunc_t,
+ attr: self.rb_method_attr_t,
+ alias: self.rb_method_alias_t,
+ refined: self.rb_method_refined_t,
+ bmethod: self.rb_method_bmethod_t,
+ optimized: self.rb_method_optimized_t,
+ ), Primitive.cexpr!("OFFSETOF((*((struct rb_method_definition_struct *)NULL)), body)")],
+ original_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_method_definition_struct *)NULL)), original_id)")],
+ method_serial: [CType::Immediate.parse("uintptr_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_method_definition_struct *)NULL)), method_serial)")],
+ )
+ end
+
+ def C.rb_method_iseq_t
+ @rb_method_iseq_t ||= CType::Struct.new(
+ "rb_method_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_method_iseq_struct)"),
+ iseqptr: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_iseq_struct *)NULL)), iseqptr)")],
+ cref: [CType::Pointer.new { self.rb_cref_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_iseq_struct *)NULL)), cref)")],
+ )
+ end
+
+ def C.rb_method_type_t
+ @rb_method_type_t ||= CType::Immediate.parse("int")
+ end
+
+ def C.rb_mjit_compile_info
+ @rb_mjit_compile_info ||= CType::Struct.new(
+ "rb_mjit_compile_info", Primitive.cexpr!("SIZEOF(struct rb_mjit_compile_info)"),
+ disable_ivar_cache: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_compile_info *)NULL)), disable_ivar_cache)")],
+ disable_exivar_cache: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_compile_info *)NULL)), disable_exivar_cache)")],
+ disable_send_cache: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_compile_info *)NULL)), disable_send_cache)")],
+ disable_inlining: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_compile_info *)NULL)), disable_inlining)")],
+ disable_const_cache: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_compile_info *)NULL)), disable_const_cache)")],
+ )
+ end
+
+ def C.rb_mjit_unit
+ @rb_mjit_unit ||= CType::Struct.new(
+ "rb_mjit_unit", Primitive.cexpr!("SIZEOF(struct rb_mjit_unit)"),
+ unode: [self.ccan_list_node, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), unode)")],
+ id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), id)")],
+ type: [self.rb_mjit_unit_type, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), type)")],
+ iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), iseq)")],
+ used_code_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), used_code_p)")],
+ compile_info: [self.rb_mjit_compile_info, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), compile_info)")],
+ cc_entries: [CType::Pointer.new { CType::Pointer.new { self.rb_callcache } }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), cc_entries)")],
+ cc_entries_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), cc_entries_size)")],
+ handle: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), handle)")],
+ units: [self.rb_mjit_unit_list, Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_unit *)NULL)), units)")],
+ )
+ end
+
+ def C.rb_serial_t
+ @rb_serial_t ||= CType::Immediate.parse("unsigned long long")
+ end
+
+ def C.rb_shape
+ @rb_shape ||= CType::Struct.new(
+ "rb_shape", Primitive.cexpr!("SIZEOF(struct rb_shape)"),
+ edges: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), edges)")],
+ edge_name: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), edge_name)")],
+ next_iv_index: [self.attr_index_t, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), next_iv_index)")],
+ capacity: [CType::Immediate.parse("uint32_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), capacity)")],
+ type: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), type)")],
+ size_pool_index: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), size_pool_index)")],
+ parent_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), parent_id)")],
+ )
+ end
+
+ def C.rb_shape_t
+ @rb_shape_t ||= self.rb_shape
+ end
+
+ def C.VALUE
+ @VALUE ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(VALUE)"), Primitive.cexpr!("SIGNED_TYPE_P(VALUE)"))
+ end
+
+ def C.shape_id_t
+ @shape_id_t ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(shape_id_t)"), Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)"))
+ end
+
+ def C._Bool
+ CType::Bool.new
+ end
+
+ def C.ID
+ CType::Stub.new(:ID)
+ end
+
+ def C.rb_thread_struct
+ CType::Stub.new(:rb_thread_struct)
+ end
+
+ def C.vm_call_handler
+ CType::Stub.new(:vm_call_handler)
+ end
+
+ def C.method_missing_reason
+ CType::Stub.new(:method_missing_reason)
+ end
+
+ def C.rb_callinfo_kwarg
+ CType::Stub.new(:rb_callinfo_kwarg)
+ end
+
+ def C.rb_cref_struct
+ CType::Stub.new(:rb_cref_struct)
+ end
+
+ def C.rb_scope_visibility_t
+ CType::Stub.new(:rb_scope_visibility_t)
+ end
+
+ def C.rb_vm_tag
+ CType::Stub.new(:rb_vm_tag)
+ end
+
+ def C.rb_atomic_t
+ CType::Stub.new(:rb_atomic_t)
+ end
+
+ def C.rb_fiber_t
+ CType::Stub.new(:rb_fiber_t)
+ end
+
+ def C.rb_id_table
+ CType::Stub.new(:rb_id_table)
+ end
+
+ def C.rb_ensure_list_t
+ CType::Stub.new(:rb_ensure_list_t)
+ end
+
+ def C.rb_trace_arg_struct
+ CType::Stub.new(:rb_trace_arg_struct)
+ end
+
+ def C.rb_iseq_type
+ CType::Stub.new(:rb_iseq_type)
+ end
+
+ def C.rb_iseq_param_keyword
+ CType::Stub.new(:rb_iseq_param_keyword)
+ end
+
+ def C.iseq_insn_info
+ CType::Stub.new(:iseq_insn_info)
+ end
+
+ def C.iseq_catch_table
+ CType::Stub.new(:iseq_catch_table)
+ end
+
+ def C.rb_snum_t
+ CType::Stub.new(:rb_snum_t)
+ end
+
+ def C.iseq_bits_t
+ CType::Stub.new(:iseq_bits_t)
+ end
+
+ def C.rb_code_location_t
+ CType::Stub.new(:rb_code_location_t)
+ end
+
+ def C.iseq_compile_data
+ CType::Stub.new(:iseq_compile_data)
+ end
+
+ def C.rb_hook_list_struct
+ CType::Stub.new(:rb_hook_list_struct)
+ end
+
+ def C.rb_event_flag_t
+ CType::Stub.new(:rb_event_flag_t)
+ end
+
+ def C.rb_method_cfunc_t
+ CType::Stub.new(:rb_method_cfunc_t)
+ end
+
+ def C.rb_method_attr_t
+ CType::Stub.new(:rb_method_attr_t)
+ end
+
+ def C.rb_method_alias_t
+ CType::Stub.new(:rb_method_alias_t)
+ end
+
+ def C.rb_method_refined_t
+ CType::Stub.new(:rb_method_refined_t)
+ end
+
+ def C.rb_method_bmethod_t
+ CType::Stub.new(:rb_method_bmethod_t)
+ end
+
+ def C.rb_method_optimized_t
+ CType::Stub.new(:rb_method_optimized_t)
+ end
+
+ def C.ccan_list_node
+ CType::Stub.new(:ccan_list_node)
+ end
+
+ def C.rb_mjit_unit_type
+ CType::Stub.new(:rb_mjit_unit_type)
+ end
+
+ def C.rb_mjit_unit_list
+ CType::Stub.new(:rb_mjit_unit_list)
+ end
+
+ ### MJIT bindgen end ###
+end if RubyVM::MJIT.enabled? && RubyVM::MJIT.const_defined?(:C) # not defined for miniruby
diff --git a/mjit_compile.c b/mjit_compile.c
deleted file mode 100644
index d68d440ca3..0000000000
--- a/mjit_compile.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/**********************************************************************
-
- mjit_compile.c - MRI method JIT compiler
-
- Copyright (C) 2017 Takashi Kokubun <takashikkbn@gmail.com>.
-
-**********************************************************************/
-
-// NOTE: All functions in this file are executed on MJIT worker. So don't
-// call Ruby methods (C functions that may call rb_funcall) or trigger
-// GC (using ZALLOC, xmalloc, xfree, etc.) in this file.
-
-#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 "vm_insnhelper.h"
-
-#include "builtin.h"
-#include "insns.inc"
-#include "insns_info.inc"
-
-// 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)
-
-// For propagating information needed for lazily pushing a frame.
-struct inlined_call_context {
- int orig_argc; // ci->orig_argc
- 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
-// which is global during one `mjit_compile` call. Ones conditional
-// in each branch should be stored in `compile_branch`.
-struct compile_status {
- bool success; // has true if compilation has had no issue
- int *stack_size_for_pos; // stack_size_for_pos[pos] has stack size for the position (otherwise -1)
- // 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 ivar cache entries copied from main thread.
- union iseq_inline_storage_entry *is_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;
-};
-
-// Storage to keep data which is consistent in each conditional branch.
-// This is created and used for one `compile_insns` call and its values
-// should be copied for extra `compile_insns` call.
-struct compile_branch {
- unsigned int stack_size; // this simulates sp (stack pointer) of YARV
- bool finish_p; // if true, compilation in this branch should stop and let another branch to be compiled
-};
-
-struct case_dispatch_var {
- FILE *f;
- unsigned int base_pos;
- VALUE last_value;
-};
-
-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)
-{
- 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
-// as CC_SET_FASTPATH (in vm_callee_setup_arg) is called from vm_call_iseq_setup.
-static bool
-fastpath_applied_iseq_p(const CALL_INFO ci, const CALL_CACHE cc, const rb_iseq_t *iseq)
-{
- extern bool rb_simple_iseq_p(const rb_iseq_t *iseq);
- return iseq != NULL
- && !(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)
-{
- struct case_dispatch_var *var = (struct case_dispatch_var *)arg;
- unsigned int offset;
-
- if (var->last_value != value) {
- offset = FIX2INT(value);
- var->last_value = value;
- fprintf(var->f, " case %d:\n", offset);
- fprintf(var->f, " goto label_%d;\n", var->base_pos + offset);
- fprintf(var->f, " break;\n");
- }
- return ST_CONTINUE;
-}
-
-// Calling rb_id2str in MJIT worker causes random SEGV. So this is disabled by default.
-static void
-comment_id(FILE *f, ID id)
-{
-#ifdef MJIT_COMMENT_ID
- VALUE name = rb_id2str(id);
- const char *p, *e;
- char c, prev = '\0';
-
- if (!name) return;
- p = RSTRING_PTR(name);
- e = RSTRING_END(name);
- fputs("/* :\"", f);
- for (; p < e; ++p) {
- switch (c = *p) {
- case '*': case '/': if (prev != (c ^ ('/' ^ '*'))) break;
- case '\\': case '"': fputc('\\', f);
- }
- fputc(c, f);
- prev = c;
- }
- fputs("\" */", f);
-#endif
-}
-
-static void compile_insns(FILE *f, const struct rb_iseq_constant_body *body, unsigned int stack_size,
- unsigned int pos, struct compile_status *status);
-
-// Main function of JIT compilation, vm_exec_core counterpart for JIT. Compile one insn to `f`, may modify
-// b->stack_size and return next position.
-//
-// When you add a new instruction to insns.def, it would be nice to have JIT compilation support here but
-// it's optional. This JIT compiler just ignores ISeq which includes unknown instruction, and ISeq which
-// does not have it can be compiled as usual.
-static unsigned int
-compile_insn(FILE *f, const struct rb_iseq_constant_body *body, const int insn, const VALUE *operands,
- const unsigned int pos, struct compile_status *status, struct compile_branch *b)
-{
- unsigned int next_pos = pos + insn_len(insn);
-
-/*****************/
- #include "mjit_compile.inc"
-/*****************/
-
- // If next_pos is already compiled and this branch is not finished yet,
- // next instruction won't be compiled in C code next and will need `goto`.
- if (!b->finish_p && next_pos < body->iseq_size && ALREADY_COMPILED_P(status, next_pos)) {
- fprintf(f, "goto label_%d;\n", next_pos);
-
- // Verify stack size assumption is the same among multiple branches
- if ((unsigned int)status->stack_size_for_pos[next_pos] != b->stack_size) {
- if (mjit_opts.warnings || mjit_opts.verbose)
- fprintf(stderr, "MJIT warning: JIT stack assumption is not the same between branches (%d != %u)\n",
- status->stack_size_for_pos[next_pos], b->stack_size);
- status->success = false;
- }
- }
-
- return next_pos;
-}
-
-// Compile one conditional branch. If it has branchXXX insn, this should be
-// called multiple times for each branch.
-static void
-compile_insns(FILE *f, const struct rb_iseq_constant_body *body, unsigned int stack_size,
- unsigned int pos, struct compile_status *status)
-{
- struct compile_branch branch;
-
- branch.stack_size = stack_size;
- branch.finish_p = false;
-
- while (pos < body->iseq_size && !ALREADY_COMPILED_P(status, pos) && !branch.finish_p) {
- int insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
- status->stack_size_for_pos[pos] = (int)branch.stack_size;
-
- fprintf(f, "\nlabel_%d: /* %s */\n", pos, insn_name(insn));
- pos = compile_insn(f, body, insn, body->iseq_encoded + (pos+1), pos, status, &branch);
- if (status->success && branch.stack_size > body->stack_max) {
- if (mjit_opts.warnings || mjit_opts.verbose)
- fprintf(stderr, "MJIT warning: JIT stack size (%d) exceeded its max size (%d)\n", branch.stack_size, body->stack_max);
- status->success = false;
- }
- if (!status->success)
- break;
- }
-}
-
-// Print the block to cancel inlined method call. It's supporting only `opt_send_without_block` for now.
-static void
-compile_inlined_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct inlined_call_context *inline_context)
-{
- fprintf(f, "\ncancel:\n");
- fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel);\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, " VALUE *current_sp = reg_cfp->sp;\n");
- fprintf(f, " reg_cfp->pc = orig_pc;\n");
- fprintf(f, " reg_cfp->sp = orig_sp;\n\n");
-
- // Lazily push the current call frame.
- fprintf(f, " struct rb_calling_info calling;\n");
- fprintf(f, " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n"); // assumes `opt_send_without_block`
- fprintf(f, " calling.argc = %d;\n", inline_context->orig_argc);
- fprintf(f, " calling.recv = reg_cfp->self;\n");
- fprintf(f, " reg_cfp->self = orig_self;\n");
- fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, (const rb_callable_method_entry_t *)0x%"PRIxVALUE", 0, %d, %d);\n\n",
- inline_context->me, inline_context->param_size, inline_context->local_size); // fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE
-
- // Start usual cancel from here.
- fprintf(f, " reg_cfp = ec->cfp;\n"); // work on the new frame
- fprintf(f, " reg_cfp->pc = current_pc;\n");
- fprintf(f, " reg_cfp->sp = current_sp;\n");
- for (unsigned int i = 0; i < body->stack_max; i++) { // should be always `status->local_stack_p`
- fprintf(f, " *(vm_base_ptr(reg_cfp) + %d) = stack[%d];\n", i, i);
- }
- // 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, false);\n");
-}
-
-// Print the block to cancel JIT execution.
-static void
-compile_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct compile_status *status)
-{
- if (status->inlined_iseqs == NULL) { // the current ISeq is being inlined
- compile_inlined_cancel_handler(f, body, &status->inline_context);
- return;
- }
-
- fprintf(f, "\nsend_cancel:\n");
- fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_send_inline);\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_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");
- fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel);\n");
- if (status->local_stack_p) {
- for (unsigned int i = 0; i < body->stack_max; i++) {
- fprintf(f, " *(vm_base_ptr(reg_cfp) + %d) = stack[%d];\n", i, i);
- }
- }
- fprintf(f, " return Qundef;\n");
-}
-
-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)
-{
- const struct rb_iseq_constant_body *body = iseq->body;
- status->success = true;
- status->local_stack_p = !body->catch_except_p;
-
- if (status->local_stack_p) {
- fprintf(f, " VALUE stack[%d];\n", body->stack_max);
- }
- else {
- fprintf(f, " VALUE *stack = reg_cfp->sp;\n");
- }
- if (status->inlined_iseqs != NULL) // i.e. compile root
- 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.
- if (body->param.flags.has_opt) {
- int i;
- fprintf(f, "\n");
- fprintf(f, " switch (reg_cfp->pc - reg_cfp->iseq->body->iseq_encoded) {\n");
- for (i = 0; i <= body->param.opt_num; i++) {
- VALUE pc_offset = body->param.opt_table[i];
- fprintf(f, " case %"PRIdVALUE":\n", pc_offset);
- fprintf(f, " goto label_%"PRIdVALUE";\n", pc_offset);
- }
- fprintf(f, " }\n");
- }
-
- compile_insns(f, body, 0, 0, status);
- compile_cancel_handler(f, body, status);
- fprintf(f, "#undef GET_SELF");
- return status->success;
-}
-
-// Return true if the ISeq can be inlined without pushing a new control frame.
-static bool
-inlinable_iseq_p(const struct rb_iseq_constant_body *body)
-{
- // 1) If catch_except_p, caller frame should be preserved when callee catches an exception.
- // Then we need to wrap `vm_exec()` but then we can't inline the call inside it.
- //
- // 2) If `body->catch_except_p` is false and `handles_sp?` of an insn is false,
- // sp is not moved as we assume `status->local_stack_p = !body->catch_except_p`.
- //
- // 3) If `body->catch_except_p` is false and `always_leaf?` of an insn is true,
- // pc is not moved.
- if (body->catch_except_p)
- return false;
-
- unsigned int pos = 0;
- while (pos < body->iseq_size) {
- int insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
- // All insns in the ISeq except `leave` (to be overridden in the inlined code)
- // should meet following strong assumptions:
- // * Do not require `cfp->sp` motion
- // * Do not move `cfp->pc`
- // * Do not read any `cfp->pc`
- if (insn == BIN(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) {
- case BIN(getlocal):
- case BIN(getlocal_WC_0):
- case BIN(getlocal_WC_1):
- case BIN(setlocal):
- case BIN(setlocal_WC_0):
- case BIN(setlocal_WC_1):
- case BIN(getblockparam):
- case BIN(getblockparamproxy):
- case BIN(setblockparam):
- return false;
- }
- pos += insn_len(insn);
- }
- return true;
-}
-
-// Return an iseq pointer if cc has inlinable iseq.
-const rb_iseq_t *
-rb_mjit_inlinable_iseq(const struct rb_callinfo *ci, const struct rb_callcache *cc)
-{
- const rb_iseq_t *iseq;
- if (has_valid_method_type(cc) &&
- !(vm_ci_flag(ci) & VM_CALL_TAILCALL) && // inlining only non-tailcall path
- vm_cc_cme(cc)->def->type == VM_METHOD_TYPE_ISEQ &&
- fastpath_applied_iseq_p(ci, cc, iseq = def_iseq_ptr(vm_cc_cme(cc)->def)) &&
- // CC_SET_FASTPATH in vm_callee_setup_arg
- inlinable_iseq_p(iseq->body)) {
- return iseq;
- }
- return NULL;
-}
-
-static void
-init_ivar_compile_status(const struct rb_iseq_constant_body *body, struct compile_status *status)
-{
- mjit_capture_is_entries(body, status->is_entries);
-
- int num_ivars = 0;
- unsigned int pos = 0;
- status->max_ivar_index = 0;
- status->ivar_serial = 0;
-
- while (pos < body->iseq_size) {
- int insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
- if (insn == BIN(getinstancevariable) || insn == BIN(setinstancevariable)) {
- IVC ic = (IVC)body->iseq_encoded[pos+2];
- IVC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->iv_cache;
- if (ic_copy->entry) { // Only initialized (ic_serial > 0) IVCs are optimized
- num_ivars++;
-
- if (status->max_ivar_index < ic_copy->entry->index) {
- status->max_ivar_index = ic_copy->entry->index;
- }
-
- if (status->ivar_serial == 0) {
- status->ivar_serial = ic_copy->entry->class_serial;
- }
- else if (status->ivar_serial != ic_copy->entry->class_serial) {
- // Multiple classes have used this ISeq. Give up assuming one serial.
- status->merge_ivar_guards_p = false;
- return;
- }
- }
- }
- pos += insn_len(insn);
- }
- status->merge_ivar_guards_p = status->ivar_serial > 0 && num_ivars >= 2;
-}
-
-// This needs to be macro instead of a function because it's using `alloca`.
-#define INIT_COMPILE_STATUS(status, body, compile_root_p) do { \
- status = (struct compile_status){ \
- .stack_size_for_pos = (int *)alloca(sizeof(int) * body->iseq_size), \
- .inlined_iseqs = compile_root_p ? \
- alloca(sizeof(const struct rb_iseq_constant_body *) * body->iseq_size) : NULL, \
- .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)) \
- }; \
- memset(status.stack_size_for_pos, NOT_COMPILED_STACK_SIZE, sizeof(int) * body->iseq_size); \
- if (compile_root_p) \
- memset((void *)status.inlined_iseqs, 0, sizeof(const struct rb_iseq_constant_body *) * body->iseq_size); \
- else \
- memset(status.compile_info, 0, sizeof(struct rb_mjit_compile_info)); \
-} while (0)
-
-// Compile inlinable ISeqs to C code in `f`. It returns true if it succeeds to compile them.
-static bool
-precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status *status)
-{
- const struct rb_iseq_constant_body *body = iseq->body;
- unsigned int pos = 0;
- while (pos < body->iseq_size) {
- int insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
- if (insn == BIN(opt_send_without_block) || insn == BIN(opt_size)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block`
- CALL_DATA cd = (CALL_DATA)body->iseq_encoded[pos + 1];
- 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 ((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(child_iseq->body->location.label),
- 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 = { .compiled_iseq = status->compiled_iseq, .compiled_id = status->compiled_id };
- INIT_COMPILE_STATUS(child_status, child_iseq->body, false);
- child_status.inline_context = (struct inlined_call_context){
- .orig_argc = vm_ci_argc(ci),
- .me = (VALUE)vm_cc_cme(cc),
- .param_size = child_iseq->body->param.size,
- .local_size = child_iseq->body->local_table_size
- };
- if (child_iseq->body->ci_size > 0 && child_status.cc_entries_index == -1) {
- return false;
- }
- init_ivar_compile_status(child_iseq->body, &child_status);
-
- fprintf(f, "ALWAYS_INLINE(static VALUE _mjit%d_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n", status->compiled_id, pos);
- fprintf(f, "static inline VALUE\n_mjit%d_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n", status->compiled_id, pos);
- fprintf(f, " const VALUE *orig_pc = reg_cfp->pc;\n");
- fprintf(f, " VALUE *orig_sp = reg_cfp->sp;\n");
- bool success = mjit_compile_body(f, child_iseq, &child_status);
- fprintf(f, "\n} /* end of _mjit%d_inlined_%d */\n\n", status->compiled_id, pos);
-
- if (!success)
- return false;
- }
- }
- pos += insn_len(insn);
- }
- return true;
-}
-
-// 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, int id)
-{
- struct compile_status status = { .compiled_iseq = iseq->body, .compiled_id = id };
- INIT_COMPILE_STATUS(status, iseq->body, true);
- 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))
- return false;
- }
-
-#ifdef _WIN32
- fprintf(f, "__declspec(dllexport)\n");
-#endif
- fprintf(f, "VALUE\n%s(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)\n{\n", funcname);
- bool success = mjit_compile_body(f, iseq, &status);
- fprintf(f, "\n} // end of %s\n", funcname);
- return success;
-}
-
-#endif // USE_MJIT
diff --git a/mjit_worker.c b/mjit_worker.c
deleted file mode 100644
index c6528a9bda..0000000000
--- a/mjit_worker.c
+++ /dev/null
@@ -1,1515 +0,0 @@
-/**********************************************************************
-
- mjit_worker.c - Worker for MRI method JIT compiler
-
- Copyright (C) 2017 Vladimir Makarov <vmakarov@redhat.com>.
-
-**********************************************************************/
-
-// NOTE: All functions in this file are executed on MJIT worker. So don't
-// 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.
- Generated code performance of the used C compilers has a higher
- priority over the compilation speed.
-
- So our major goal is to minimize the ISEQ compilation time when we
- use widely optimization level (-O2). It is achieved by
-
- o Using a precompiled version of the header
- o Keeping all files in `/tmp`. On modern Linux `/tmp` is a file
- system in memory. So it is pretty fast
- o Implementing MJIT as a multi-threaded code because we want to
- compile ISEQs in parallel with iseq execution to speed up Ruby
- code execution. MJIT has one thread (*worker*) to do
- parallel compilations:
- o It prepares a precompiled code of the minimized header.
- It starts at the MRI execution start
- o It generates PIC object files of ISEQs
- o It takes one JIT unit from a priority queue unless it is empty.
- o It translates the JIT unit ISEQ into C-code using the precompiled
- header, calls CC and load PIC code when it is ready
- o Currently MJIT put ISEQ in the queue when ISEQ is called
- o MJIT can reorder ISEQs in the queue if some ISEQ has been called
- many times and its compilation did not start yet
- o MRI reuses the machine code if it already exists for ISEQ
- o The machine code we generate can stop and switch to the ISEQ
- interpretation if some condition is not satisfied as the machine
- code can be speculative or some exception raises
- o Speculative machine code can be canceled.
-
- Here is a diagram showing the MJIT organization:
-
- _______
- |header |
- |_______|
- | MRI building
- --------------|----------------------------------------
- | MRI execution
- |
- _____________|_____
- | | |
- | ___V__ | CC ____________________
- | | |----------->| precompiled header |
- | | | | |____________________|
- | | | | |
- | | MJIT | | |
- | | | | |
- | | | | ____V___ CC __________
- | |______|----------->| C code |--->| .so file |
- | | |________| |__________|
- | | |
- | | |
- | MRI machine code |<-----------------------------
- |___________________| loading
-
-*/
-
-#ifdef __sun
-#define __EXTENSIONS__ 1
-#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>
-#include <windows.h>
-#else
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <dlfcn.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#include "dln.h"
-
-#include "ruby/util.h"
-#undef strdup // ruby_strdup may trigger GC
-
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
-#ifdef _WIN32
-#define dlopen(name,flag) ((void*)LoadLibrary(name))
-#define dlerror() strerror(rb_w32_map_errno(GetLastError()))
-#define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
-#define dlclose(handle) (!FreeLibrary(handle))
-#define RTLD_NOW -1
-
-#define waitpid(pid,stat_loc,options) (WaitForSingleObject((HANDLE)(pid), INFINITE), GetExitCodeProcess((HANDLE)(pid), (LPDWORD)(stat_loc)), CloseHandle((HANDLE)pid), (pid))
-#define WIFEXITED(S) ((S) != STILL_ACTIVE)
-#define WEXITSTATUS(S) (S)
-#define WIFSIGNALED(S) (0)
-typedef intptr_t pid_t;
-#endif
-
-// Atomically set function pointer if possible.
-#define MJIT_ATOMIC_SET(var, val) (void)ATOMIC_PTR_EXCHANGE(var, val)
-
-#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;
-#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.
- 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.
-struct rb_mjit_unit_list {
- struct list_head head;
- int length; // the list length
-};
-
-extern void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
-extern void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
-extern void rb_native_mutex_initialize(rb_nativethread_lock_t *lock);
-extern void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
-
-extern void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
-extern void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
-extern void rb_native_cond_signal(rb_nativethread_cond_t *cond);
-extern void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
-extern void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
-
-// process.c
-extern rb_pid_t ruby_waitpid_locked(rb_vm_t *, rb_pid_t, int *status, int options, rb_nativethread_cond_t *cond);
-
-// A copy of MJIT portion of MRI options since MJIT initialization. We
-// need them as MJIT threads still can work when the most MRI data were
-// freed.
-struct mjit_options mjit_opts;
-
-// true if MJIT is enabled.
-bool mjit_enabled = false;
-// true if JIT-ed code should be called. When `ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS`
-// and `mjit_call_p == false`, any JIT-ed code execution is cancelled as soon as possible.
-bool mjit_call_p = false;
-
-// Priority queue of iseqs waiting for JIT compilation.
-// This variable is a pointer to head unit of the queue.
-static struct rb_mjit_unit_list unit_queue = { LIST_HEAD_INIT(unit_queue.head) };
-// List of units which are successfully compiled.
-static struct rb_mjit_unit_list active_units = { LIST_HEAD_INIT(active_units.head) };
-// List of compacted so files which will be cleaned up by `free_list()` in `mjit_finish()`.
-static struct rb_mjit_unit_list compact_units = { LIST_HEAD_INIT(compact_units.head) };
-// List of units before recompilation and just waiting for dlclose().
-static struct rb_mjit_unit_list stale_units = { LIST_HEAD_INIT(stale_units.head) };
-// The number of so far processed ISEQs, used to generate unique id.
-static int current_unit_num;
-// A mutex for conitionals and critical sections.
-static rb_nativethread_lock_t mjit_engine_mutex;
-// A thread conditional to wake up `mjit_finish` at the end of PCH thread.
-static rb_nativethread_cond_t mjit_pch_wakeup;
-// A thread conditional to wake up the client if there is a change in
-// executed unit status.
-static rb_nativethread_cond_t mjit_client_wakeup;
-// A thread conditional to wake up a worker if there we have something
-// to add or we need to stop MJIT engine.
-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;
-// Greater than 0 when GC is working.
-static int in_gc = 0;
-// True when JIT is working.
-static bool in_jit = false;
-// True when active_units has at least one stale_p=true unit.
-static bool pending_stale_p = false;
-// The times when unload_units is requested. unload_units is called after some requests.
-static int unload_requests = 0;
-// The total number of unloaded units.
-static int total_unloads = 0;
-// Set to true to stop worker.
-static bool stop_worker_p;
-// Set to true if worker is stopped.
-static bool worker_stopped = true;
-
-// Path of "/tmp", which can be changed to $TMP in MinGW.
-static char *tmp_dir;
-
-// Used C compiler path.
-static const char *cc_path;
-// Used C compiler flags.
-static const char **cc_common_args;
-// Used C compiler flags added by --jit-debug=...
-static char **cc_added_args;
-// Name of the precompiled header file.
-static char *pch_file;
-// The process id which should delete the pch_file on mjit_finish.
-static rb_pid_t pch_owner_pid;
-// Status of the precompiled header creation. The status is
-// shared by the workers and the pch thread.
-static enum {PCH_NOT_READY, PCH_FAILED, PCH_SUCCESS} pch_status;
-
-#ifndef _MSC_VER
-// Name of the header file.
-static char *header_file;
-#endif
-
-#ifdef _WIN32
-// Linker option to enable libruby.
-static char *libruby_pathflag;
-#endif
-
-#include "mjit_config.h"
-
-#if defined(__GNUC__) && \
- (!defined(__clang__) || \
- (defined(__clang__) && (defined(__FreeBSD__) || defined(__GLIBC__))))
-# define GCC_PIC_FLAGS "-Wfatal-errors", "-fPIC", "-shared", "-w", "-pipe",
-# define MJIT_CFLAGS_PIPE 1
-#else
-# define GCC_PIC_FLAGS /* empty */
-# define MJIT_CFLAGS_PIPE 0
-#endif
-
-// Use `-nodefaultlibs -nostdlib` for GCC where possible, which does not work on mingw, cygwin, AIX, and OpenBSD.
-// This seems to improve MJIT performance on GCC.
-#if defined __GNUC__ && !defined __clang__ && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__OpenBSD__)
-# define GCC_NOSTDLIB_FLAGS "-nodefaultlibs", "-nostdlib",
-#else
-# define GCC_NOSTDLIB_FLAGS // empty
-#endif
-
-static const char *const CC_COMMON_ARGS[] = {
- MJIT_CC_COMMON MJIT_CFLAGS GCC_PIC_FLAGS
- NULL
-};
-
-static const char *const CC_DEBUG_ARGS[] = {MJIT_DEBUGFLAGS NULL};
-static const char *const CC_OPTIMIZE_ARGS[] = {MJIT_OPTFLAGS NULL};
-
-static const char *const CC_LDSHARED_ARGS[] = {MJIT_LDSHARED GCC_PIC_FLAGS NULL};
-static const char *const CC_DLDFLAGS_ARGS[] = {MJIT_DLDFLAGS NULL};
-// `CC_LINKER_ARGS` are linker flags which must be passed to `-c` as well.
-static const char *const CC_LINKER_ARGS[] = {
-#if defined __GNUC__ && !defined __clang__ && !defined(__OpenBSD__)
- "-nostartfiles",
-#endif
- GCC_NOSTDLIB_FLAGS NULL
-};
-
-static const char *const CC_LIBS[] = {
-#if defined(_WIN32) || defined(__CYGWIN__)
- MJIT_LIBS // mswin, mingw, cygwin
-#endif
-#if defined __GNUC__ && !defined __clang__
-# if defined(_WIN32)
- "-lmsvcrt", // mingw
-# endif
- "-lgcc", // mingw, cygwin, and GCC platforms using `-nodefaultlibs -nostdlib`
-#endif
-#if defined __ANDROID__
- "-lm", // to avoid 'cannot locate symbol "modf" referenced by .../_ruby_mjit_XXX.so"'
-#endif
- NULL
-};
-
-#define CC_CODEFLAG_ARGS (mjit_opts.debug ? CC_DEBUG_ARGS : CC_OPTIMIZE_ARGS)
-
-// Print the arguments according to FORMAT to stderr only if MJIT
-// verbose option value is more or equal to LEVEL.
-PRINTF_ARGS(static void, 2, 3)
-verbose(int level, const char *format, ...)
-{
- if (mjit_opts.verbose >= level) {
- va_list args;
- size_t len = strlen(format);
- char *full_format = alloca(sizeof(char) * (len + 2));
-
- // Creating `format + '\n'` to atomically print format and '\n'.
- memcpy(full_format, format, len);
- full_format[len] = '\n';
- full_format[len+1] = '\0';
-
- va_start(args, format);
- vfprintf(stderr, full_format, args);
- va_end(args);
- }
-}
-
-PRINTF_ARGS(static void, 1, 2)
-mjit_warning(const char *format, ...)
-{
- if (mjit_opts.warnings || mjit_opts.verbose) {
- va_list args;
-
- fprintf(stderr, "MJIT warning: ");
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- fprintf(stderr, "\n");
- }
-}
-
-// Add unit node to the tail of doubly linked `list`. It should be not in
-// the list before.
-static void
-add_to_list(struct rb_mjit_unit *unit, struct rb_mjit_unit_list *list)
-{
- (void)RB_DEBUG_COUNTER_INC_IF(mjit_length_unit_queue, list == &unit_queue);
- (void)RB_DEBUG_COUNTER_INC_IF(mjit_length_active_units, list == &active_units);
- (void)RB_DEBUG_COUNTER_INC_IF(mjit_length_compact_units, list == &compact_units);
- (void)RB_DEBUG_COUNTER_INC_IF(mjit_length_stale_units, list == &stale_units);
-
- list_add_tail(&list->head, &unit->unode);
- list->length++;
-}
-
-static void
-remove_from_list(struct rb_mjit_unit *unit, struct rb_mjit_unit_list *list)
-{
-#if USE_DEBUG_COUNTER
- rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_unit_queue, -1, list == &unit_queue);
- rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_active_units, -1, list == &active_units);
- rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_compact_units, -1, list == &compact_units);
- rb_debug_counter_add(RB_DEBUG_COUNTER_mjit_length_stale_units, -1, list == &stale_units);
-#endif
-
- list_del(&unit->unode);
- list->length--;
-}
-
-static void
-remove_file(const char *filename)
-{
- if (remove(filename)) {
- mjit_warning("failed to remove \"%s\": %s", filename, strerror(errno));
- }
-}
-
-// Lazily delete .so files.
-static void
-clean_temp_files(struct rb_mjit_unit *unit)
-{
-#if defined(_WIN32)
- if (unit->so_file) {
- char *so_file = unit->so_file;
-
- unit->so_file = NULL;
- // unit->so_file is set only when mjit_opts.save_temps is false.
- remove_file(so_file);
- free(so_file);
- }
-#endif
-}
-
-// This is called in the following situations:
-// 1) On dequeue or `unload_units()`, associated ISeq is already GCed.
-// 2) The unit is not called often and unloaded by `unload_units()`.
-// 3) Freeing lists on `mjit_finish()`.
-//
-// `jit_func` value does not matter for 1 and 3 since the unit won't be used anymore.
-// For the situation 2, this sets the ISeq's JIT state to NOT_COMPILED_JIT_ISEQ_FUNC
-// to prevent the situation that the same methods are continuously compiled.
-static void
-free_unit(struct rb_mjit_unit *unit)
-{
- if (unit->iseq) { // ISeq is not GCed
- 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_temp_files(unit);
- free(unit);
-}
-
-// Start a critical section. Use message `msg` to print debug info at `level`.
-static inline void
-CRITICAL_SECTION_START(int level, const char *msg)
-{
- verbose(level, "Locking %s", msg);
- rb_native_mutex_lock(&mjit_engine_mutex);
- verbose(level, "Locked %s", msg);
-}
-
-// Finish the current critical section. Use message `msg` to print
-// debug info at `level`.
-static inline void
-CRITICAL_SECTION_FINISH(int level, const char *msg)
-{
- verbose(level, "Unlocked %s", msg);
- rb_native_mutex_unlock(&mjit_engine_mutex);
-}
-
-static int
-sprint_uniq_filename(char *str, size_t size, unsigned long id, const char *prefix, const char *suffix)
-{
- return snprintf(str, size, "%s/%sp%"PRI_PIDT_PREFIX"uu%lu%s", tmp_dir, prefix, getpid(), id, suffix);
-}
-
-// Return time in milliseconds as a double.
-#ifdef __APPLE__
-double ruby_real_ms_time(void);
-# define real_ms_time() ruby_real_ms_time()
-#else
-static double
-real_ms_time(void)
-{
-# ifdef HAVE_CLOCK_GETTIME
- struct timespec tv;
-# ifdef CLOCK_MONOTONIC
- const clockid_t c = CLOCK_MONOTONIC;
-# else
- const clockid_t c = CLOCK_REALTIME;
-# endif
-
- clock_gettime(c, &tv);
- return tv.tv_nsec / 1000000.0 + tv.tv_sec * 1000.0;
-# else
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- return tv.tv_usec / 1000.0 + tv.tv_sec * 1000.0;
-# endif
-}
-#endif
-
-// Return the best unit from list. The best is the first
-// high priority unit or the unit whose iseq has the biggest number
-// of calls so far.
-static struct rb_mjit_unit *
-get_from_list(struct rb_mjit_unit_list *list)
-{
- 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);
- free_unit(unit);
- continue;
- }
-
- if (best == NULL || best->iseq->body->total_calls < unit->iseq->body->total_calls) {
- 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);
- }
- return best;
-}
-
-// Return length of NULL-terminated array `args` excluding the NULL marker.
-static size_t
-args_len(char *const *args)
-{
- size_t i;
-
- for (i = 0; (args[i]) != NULL;i++)
- ;
- return i;
-}
-
-// Concatenate `num` passed NULL-terminated arrays of strings, put the
-// result (with NULL end marker) into the heap, and return the result.
-static char **
-form_args(int num, ...)
-{
- va_list argp;
- size_t len, n;
- int i;
- char **args, **res, **tmp;
-
- va_start(argp, num);
- res = NULL;
- for (i = len = 0; i < num; i++) {
- args = va_arg(argp, char **);
- n = args_len(args);
- if ((tmp = (char **)realloc(res, sizeof(char *) * (len + n + 1))) == NULL) {
- free(res);
- res = NULL;
- break;
- }
- res = tmp;
- MEMCPY(res + len, args, char *, n + 1);
- len += n;
- }
- va_end(argp);
- return res;
-}
-
-COMPILER_WARNING_PUSH
-#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`.
-// Return PID of the process.
-static pid_t
-start_process(const char *abspath, char *const *argv)
-{
- // Not calling non-async-signal-safe functions between vfork
- // and execv for safety
- int dev_null = rb_cloexec_open(ruby_null_device, O_WRONLY, 0);
- if (dev_null < 0) {
- verbose(1, "MJIT: Failed to open a null device: %s", strerror(errno));
- return -1;
- }
- if (mjit_opts.verbose >= 2) {
- const char *arg;
- fprintf(stderr, "Starting process: %s", abspath);
- for (int i = 0; (arg = argv[i]) != NULL; i++)
- fprintf(stderr, " %s", arg);
- fprintf(stderr, "\n");
- }
-
- pid_t pid;
-#ifdef _WIN32
- extern HANDLE rb_w32_start_process(const char *abspath, char *const *argv, int out_fd);
- int out_fd = 0;
- if (mjit_opts.verbose <= 1) {
- // Discard cl.exe's outputs like:
- // _ruby_mjit_p12u3.c
- // Creating library C:.../_ruby_mjit_p12u3.lib and object C:.../_ruby_mjit_p12u3.exp
- out_fd = dev_null;
- }
-
- pid = (pid_t)rb_w32_start_process(abspath, argv, out_fd);
- if (pid == 0) {
- verbose(1, "MJIT: Failed to create process: %s", dlerror());
- return -1;
- }
-#else
- if ((pid = vfork()) == 0) { /* TODO: reuse some function in process.c */
- umask(0077);
- if (mjit_opts.verbose == 0) {
- // CC can be started in a thread using a file which has been
- // already removed while MJIT is finishing. Discard the
- // messages about missing files.
- dup2(dev_null, STDERR_FILENO);
- dup2(dev_null, STDOUT_FILENO);
- }
- (void)close(dev_null);
- pid = execv(abspath, argv); // Pid will be negative on an error
- // Even if we successfully found CC to compile PCH we still can
- // fail with loading the CC in very rare cases for some reasons.
- // Stop the forked process in this case.
- verbose(1, "MJIT: Error in execv: %s", abspath);
- _exit(1);
- }
-#endif
- (void)close(dev_null);
- return pid;
-}
-COMPILER_WARNING_POP
-
-// Execute an OS process of executable PATH with arguments ARGV.
-// Return -1 or -2 if failed to execute, otherwise exit code of the process.
-// TODO: Use a similar function in process.c
-static int
-exec_process(const char *path, char *const argv[])
-{
- int stat, exit_code = -2;
- rb_vm_t *vm = WAITPID_USE_SIGCHLD ? GET_VM() : 0;
- rb_nativethread_cond_t cond;
-
- if (vm) {
- rb_native_cond_initialize(&cond);
- rb_native_mutex_lock(&vm->waitpid_lock);
- }
-
- pid_t pid = start_process(path, argv);
- for (;pid > 0;) {
- pid_t r = vm ? ruby_waitpid_locked(vm, pid, &stat, 0, &cond)
- : waitpid(pid, &stat, 0);
- if (r == -1) {
- if (errno == EINTR) continue;
- fprintf(stderr, "[%"PRI_PIDT_PREFIX"d] waitpid(%lu): %s (SIGCHLD=%d,%u)\n",
- getpid(), (unsigned long)pid, strerror(errno),
- RUBY_SIGCHLD, SIGCHLD_LOSSY);
- break;
- }
- else if (r == pid) {
- if (WIFEXITED(stat)) {
- exit_code = WEXITSTATUS(stat);
- break;
- }
- else if (WIFSIGNALED(stat)) {
- exit_code = -1;
- break;
- }
- }
- }
-
- if (vm) {
- rb_native_mutex_unlock(&vm->waitpid_lock);
- rb_native_cond_destroy(&cond);
- }
- return exit_code;
-}
-
-static void
-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_temp_files()`
- if (unit->so_file == NULL)
- mjit_warning("failed to allocate memory to lazily remove '%s': %s", so_file, strerror(errno));
-#else
- remove_file(so_file);
-#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) {
- int insn = rb_vm_insn_decode(iseq->body->iseq_encoded[pos]);
- if (insn == BIN(opt_send_without_block) || insn == BIN(opt_size)) {
- CALL_DATA cd = (CALL_DATA)iseq->body->iseq_encoded[pos + 1];
- extern const rb_iseq_t *rb_mjit_inlinable_iseq(const struct rb_callinfo *ci, const struct rb_callcache *cc);
- const rb_iseq_t *iseq = rb_mjit_inlinable_iseq(cd->ci, cd->cc);
- if (iseq != NULL) {
- compiling_iseqs[i] = iseq;
- i++;
- }
- }
- pos += insn_len(insn);
- }
- return true;
-}
-
-static void
-free_compiling_iseqs(void)
-{
- RBIMPL_WARNING_PUSH();
-#ifdef _MSC_VER
- RBIMPL_WARNING_IGNORED(4090); /* suppress false warning by MSVC */
-#endif
- free(compiling_iseqs);
- RBIMPL_WARNING_POP();
- compiling_iseqs = NULL;
-}
-
-bool
-rb_mjit_compiling_iseq_p(const rb_iseq_t *iseq)
-{
- assert(compiling_iseqs != NULL);
- int i = 0;
- while (compiling_iseqs[i]) {
- if (compiling_iseqs[i] == iseq) return true;
- i++;
- }
- return false;
-}
-
-static const int c_file_access_mode =
-#ifdef O_BINARY
- O_BINARY|
-#endif
- O_WRONLY|O_EXCL|O_CREAT;
-
-#define append_str2(p, str, len) ((char *)memcpy((p), str, (len))+(len))
-#define append_str(p, str) append_str2(p, str, sizeof(str)-1)
-#define append_lit(p, str) append_str2(p, str, rb_strlen_lit(str))
-
-#ifdef _MSC_VER
-// Compile C file to so. It returns true if it succeeds. (mswin)
-static bool
-compile_c_to_so(const char *c_file, const char *so_file)
-{
- const char *files[] = { NULL, NULL, NULL, NULL, NULL, NULL, "-link", libruby_pathflag, NULL };
- char *p;
-
- // files[0] = "-Fe*.dll"
- files[0] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fe") + strlen(so_file) + 1));
- p = append_lit(p, "-Fe");
- p = append_str2(p, so_file, strlen(so_file));
- *p = '\0';
-
- // files[1] = "-Fo*.obj"
- // We don't need .obj file, but it's somehow created to cwd without -Fo and we want to control the output directory.
- files[1] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fo") + strlen(so_file) - rb_strlen_lit(DLEXT) + rb_strlen_lit(".obj") + 1));
- char *obj_file = p = append_lit(p, "-Fo");
- p = append_str2(p, so_file, strlen(so_file) - rb_strlen_lit(DLEXT));
- p = append_lit(p, ".obj");
- *p = '\0';
-
- // files[2] = "-Yu*.pch"
- files[2] = p = alloca(sizeof(char) * (rb_strlen_lit("-Yu") + strlen(pch_file) + 1));
- p = append_lit(p, "-Yu");
- p = append_str2(p, pch_file, strlen(pch_file));
- *p = '\0';
-
- // files[3] = "C:/.../rb_mjit_header-*.obj"
- files[3] = p = alloca(sizeof(char) * (strlen(pch_file) + 1));
- p = append_str2(p, pch_file, strlen(pch_file) - strlen(".pch"));
- p = append_lit(p, ".obj");
- *p = '\0';
-
- // files[4] = "-Tc*.c"
- files[4] = p = alloca(sizeof(char) * (rb_strlen_lit("-Tc") + strlen(c_file) + 1));
- p = append_lit(p, "-Tc");
- p = append_str2(p, c_file, strlen(c_file));
- *p = '\0';
-
- // files[5] = "-Fd*.pdb"
- files[5] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fd") + strlen(pch_file) + 1));
- p = append_lit(p, "-Fd");
- p = append_str2(p, pch_file, strlen(pch_file) - rb_strlen_lit(".pch"));
- p = append_lit(p, ".pdb");
- *p = '\0';
-
- char **args = form_args(5, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS,
- files, CC_LIBS, CC_DLDFLAGS_ARGS);
- if (args == NULL)
- return false;
-
- int exit_code = exec_process(cc_path, args);
- free(args);
-
- if (exit_code == 0) {
- // remove never-used files (.obj, .lib, .exp, .pdb). XXX: Is there any way not to generate this?
- if (!mjit_opts.save_temps) {
- char *before_dot;
- remove_file(obj_file);
-
- before_dot = obj_file + strlen(obj_file) - rb_strlen_lit(".obj");
- append_lit(before_dot, ".lib"); remove_file(obj_file);
- append_lit(before_dot, ".exp"); remove_file(obj_file);
- append_lit(before_dot, ".pdb"); remove_file(obj_file);
- }
- }
- else {
- verbose(2, "compile_c_to_so: compile error: %d", exit_code);
- }
- return exit_code == 0;
-}
-#else // _MSC_VER
-
-// The function producing the pre-compiled header.
-static void
-make_pch(void)
-{
- const char *rest_args[] = {
-# ifdef __clang__
- "-emit-pch",
- "-c",
-# endif
- // -nodefaultlibs is a linker flag, but it may affect cc1 behavior on Gentoo, which should NOT be changed on pch:
- // https://gitweb.gentoo.org/proj/gcc-patches.git/tree/7.3.0/gentoo/13_all_default-ssp-fix.patch
- GCC_NOSTDLIB_FLAGS
- "-o", pch_file, header_file,
- NULL,
- };
-
- verbose(2, "Creating precompiled header");
- char **args = form_args(4, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, rest_args);
- if (args == NULL) {
- mjit_warning("making precompiled header failed on forming args");
- CRITICAL_SECTION_START(3, "in make_pch");
- pch_status = PCH_FAILED;
- CRITICAL_SECTION_FINISH(3, "in make_pch");
- return;
- }
-
- int exit_code = exec_process(cc_path, args);
- free(args);
-
- CRITICAL_SECTION_START(3, "in make_pch");
- if (exit_code == 0) {
- pch_status = PCH_SUCCESS;
- }
- else {
- mjit_warning("Making precompiled header failed on compilation. Stopping MJIT worker...");
- pch_status = PCH_FAILED;
- }
- /* wakeup `mjit_finish` */
- rb_native_cond_broadcast(&mjit_pch_wakeup);
- CRITICAL_SECTION_FINISH(3, "in make_pch");
-}
-
-// 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_so(const char *c_file, const char *so_file)
-{
- 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, 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;
- }
-
- const char *so_args[] = {
- "-o", so_file,
-# ifdef _WIN32
- libruby_pathflag,
-# endif
- 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 USE_JIT_COMPACTION
-static void compile_prelude(FILE *f);
-
-static bool
-compile_compact_jit_code(char* c_file)
-{
- FILE *f;
- int fd = rb_cloexec_open(c_file, c_file_access_mode, 0600);
- if (fd < 0 || (f = fdopen(fd, "w")) == NULL) {
- int e = errno;
- if (fd >= 0) (void)close(fd);
- verbose(1, "Failed to fopen '%s', giving up JIT for it (%s)", c_file, strerror(e));
- return false;
- }
-
- compile_prelude(f);
-
- // wait until mjit_gc_exit_hook is called
- CRITICAL_SECTION_START(3, "before mjit_compile to wait GC finish");
- while (in_gc) {
- verbose(3, "Waiting wakeup from GC");
- rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex);
- }
- // We need to check again here because we could've waited on GC above
- bool iseq_gced = false;
- struct rb_mjit_unit *child_unit = 0, *next;
- list_for_each_safe(&active_units.head, child_unit, next, unode) {
- if (child_unit->iseq == NULL) { // ISeq is GC-ed
- iseq_gced = true;
- verbose(1, "JIT compaction: A method for JIT code u%d is obsoleted. Compaction will be skipped.", child_unit->id);
- remove_from_list(child_unit, &active_units);
- free_unit(child_unit); // unload it without waiting for throttled unload_units to retry compaction quickly
- }
- }
- in_jit = !iseq_gced;
- CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish");
- if (!in_jit) {
- fclose(f);
- if (!mjit_opts.save_temps)
- remove_file(c_file);
- return false;
- }
-
- // This entire loop lock GC so that we do not need to consider a case that
- // ISeq is GC-ed in a middle of re-compilation. It takes 3~4ms with 100 methods
- // on my machine. It's not too bad compared to compilation time of C (7200~8000ms),
- // but it might be larger if we use a larger --jit-max-cache.
- //
- // TODO: Consider using a more granular lock after we implement inlining across
- // compacted functions (not done yet).
- bool success = true;
- list_for_each(&active_units.head, child_unit, unode) {
- CRITICAL_SECTION_START(3, "before set_compiling_iseqs");
- success &= set_compiling_iseqs(child_unit->iseq);
- CRITICAL_SECTION_FINISH(3, "after set_compiling_iseqs");
- if (!success) continue;
-
- char funcname[MAXPATHLEN];
- sprint_funcname(funcname, child_unit);
-
- long iseq_lineno = 0;
- if (FIXNUM_P(child_unit->iseq->body->location.first_lineno))
- // FIX2INT may fallback to rb_num2long(), which is a method call and dangerous in MJIT worker. So using only FIX2LONG.
- iseq_lineno = FIX2LONG(child_unit->iseq->body->location.first_lineno);
- const char *sep = "@";
- const char *iseq_label = RSTRING_PTR(child_unit->iseq->body->location.label);
- const char *iseq_path = RSTRING_PTR(rb_iseq_path(child_unit->iseq));
- if (!iseq_label) iseq_label = sep = "";
- fprintf(f, "\n/* %s%s%s:%ld */\n", iseq_label, sep, iseq_path, iseq_lineno);
- success &= mjit_compile(f, child_unit->iseq, funcname, child_unit->id);
-
- CRITICAL_SECTION_START(3, "before compiling_iseqs free");
- free_compiling_iseqs();
- CRITICAL_SECTION_FINISH(3, "after compiling_iseqs free");
- }
-
- // release blocking mjit_gc_start_hook
- CRITICAL_SECTION_START(3, "after mjit_compile to wakeup client for GC");
- in_jit = false;
- verbose(3, "Sending wakeup signal to client in a mjit-worker for GC");
- rb_native_cond_signal(&mjit_client_wakeup);
- CRITICAL_SECTION_FINISH(3, "in worker to wakeup client for GC");
-
- fclose(f);
- return success;
-}
-
-// 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)
-{
- struct rb_mjit_unit *unit, *cur = 0;
- static const char c_ext[] = ".c";
- static const char so_ext[] = DLEXT;
- 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);
-
- 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);
- }
- double end_time = real_ms_time();
-
- if (success) {
- void *handle = dlopen(so_file, RTLD_NOW);
- if (handle == NULL) {
- mjit_warning("failure in loading code from compacted '%s': %s", so_file, dlerror());
- free(unit);
- return;
- }
- unit->handle = handle;
-
- // lazily dlclose handle (and .so file for win32) on `mjit_finish()`.
- add_to_list(unit, &compact_units);
-
- if (!mjit_opts.save_temps)
- remove_so_file(so_file, unit);
-
- CRITICAL_SECTION_START(3, "in compact_all_jit_code to read list");
- list_for_each(&active_units.head, cur, unode) {
- void *func;
- 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());
- continue;
- }
-
- if (cur->iseq) { // Check whether GCed or not
- // Usage of jit_code might be not in a critical section.
- MJIT_ATOMIC_SET(cur->iseq->body->jit_func, (mjit_func_t)func);
- }
- }
- CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to read list");
- 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 // USE_JIT_COMPACTION
-
-static void *
-load_func_from_so(const char *so_file, const char *funcname, struct rb_mjit_unit *unit)
-{
- void *handle, *func;
-
- handle = dlopen(so_file, RTLD_NOW);
- if (handle == NULL) {
- mjit_warning("failure in loading code from '%s': %s", so_file, dlerror());
- return (void *)NOT_COMPILED_JIT_ISEQ_FUNC;
- }
-
- func = dlsym(handle, funcname);
- unit->handle = handle;
- return func;
-}
-
-#ifndef __clang__
-static const char *
-header_name_end(const char *s)
-{
- const char *e = s + strlen(s);
-# ifdef __GNUC__ // don't chomp .pch for mswin
- static const char suffix[] = ".gch";
-
- // chomp .gch suffix
- if (e > s+sizeof(suffix)-1 && strcmp(e-sizeof(suffix)+1, suffix) == 0) {
- e -= sizeof(suffix)-1;
- }
-# endif
- return e;
-}
-#endif
-
-// Print platform-specific prerequisites in generated code.
-static void
-compile_prelude(FILE *f)
-{
-#ifndef __clang__ // -include-pch is used for Clang
- const char *s = pch_file;
- const char *e = header_name_end(s);
-
- fprintf(f, "#include \"");
- // print pch_file except .gch for gcc, but keep .pch for mswin
- for (; s < e; s++) {
- switch (*s) {
- case '\\': case '"':
- fputc('\\', f);
- }
- fputc(*s, f);
- }
- fprintf(f, "\"\n");
-#endif
-
-#ifdef _WIN32
- fprintf(f, "void _pei386_runtime_relocator(void){}\n");
- fprintf(f, "int __stdcall DllMainCRTStartup(void* hinstDLL, unsigned int fdwReason, void* lpvReserved) { return 1; }\n");
-#endif
-}
-
-// Compile ISeq in UNIT and return function pointer of JIT-ed code.
-// It may return NOT_COMPILED_JIT_ISEQ_FUNC if something went wrong.
-static mjit_func_t
-convert_unit_to_func(struct rb_mjit_unit *unit)
-{
- static const char c_ext[] = ".c";
- static const char so_ext[] = DLEXT;
- char c_file[MAXPATHLEN], so_file[MAXPATHLEN], funcname[MAXPATHLEN];
-
- 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);
-
- 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 (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
- }
-
- // print #include of MJIT header, etc.
- compile_prelude(f);
-
- // 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
- 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);
- return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
- }
-
- // To make MJIT worker thread-safe against GC.compact, copy ISeq values while `in_jit` is true.
- long iseq_lineno = 0;
- if (FIXNUM_P(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(unit->iseq->body->location.first_lineno);
- char *iseq_label = alloca(RSTRING_LEN(unit->iseq->body->location.label) + 1);
- char *iseq_path = alloca(RSTRING_LEN(rb_iseq_path(unit->iseq)) + 1);
- strcpy(iseq_label, RSTRING_PTR(unit->iseq->body->location.label));
- strcpy(iseq_path, RSTRING_PTR(rb_iseq_path(unit->iseq)));
-
- 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, unit->id);
-
- // release blocking mjit_gc_start_hook
- CRITICAL_SECTION_START(3, "after mjit_compile to wakeup client for GC");
- free_compiling_iseqs();
- in_jit = false;
- verbose(3, "Sending wakeup signal to client in a mjit-worker for GC");
- rb_native_cond_signal(&mjit_client_wakeup);
- CRITICAL_SECTION_FINISH(3, "in worker to wakeup client for GC");
-
- fclose(f);
- if (!success) {
- if (!mjit_opts.save_temps)
- remove_file(c_file);
- verbose(1, "JIT failure: %s@%s:%ld -> %s", iseq_label, iseq_path, iseq_lineno, c_file);
- return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
- }
-
- double start_time = real_ms_time();
- success = compile_c_to_so(c_file, so_file);
- 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;
- }
-
- void *func = load_func_from_so(so_file, funcname, unit);
- if (!mjit_opts.save_temps)
- remove_so_file(so_file, unit);
-
- if ((uintptr_t)func > (uintptr_t)LAST_JIT_ISEQ_FUNC) {
- verbose(1, "JIT success (%.1fms): %s@%s:%ld -> %s",
- end_time - start_time, iseq_label, iseq_path, iseq_lineno, c_file);
- }
- return (mjit_func_t)func;
-}
-
-// 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;
-}
-
-// 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;
-
- // 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;
- }
-
- return cc_entries_index;
-}
-
-// 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
- }
-}
-
-// 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;
-
-// 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);
- }
- }
-
- // 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;
- }
- }
- 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;
- }
-
- if (units_num > active_units.length) {
- verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
- total_unloads += units_num - active_units.length;
- }
-}
-
-static void mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool worker_p);
-
-// The function implementing a worker. It is executed in a separate
-// thread by rb_thread_create_mjit_thread. It compiles precompiled header
-// and then compiles requested ISeqs.
-void
-mjit_worker(void)
-{
- // Allow only `max_cache_size / 100` times (default: 100) of compaction.
- // Note: GC of compacted code has not been implemented yet.
- int max_compact_size = mjit_opts.max_cache_size / 100;
- if (max_compact_size < 10) max_compact_size = 10;
-
- // Run unload_units after it's requested `max_cache_size / 10` (default: 10) times.
- // This throttles the call to mitigate locking in unload_units. It also throttles JIT compaction.
- int throttle_threshold = mjit_opts.max_cache_size / 10;
-
-#ifndef _MSC_VER
- if (pch_status == PCH_NOT_READY) {
- make_pch();
- }
-#endif
- if (pch_status == PCH_FAILED) {
- mjit_enabled = false;
- CRITICAL_SECTION_START(3, "in worker to update worker_stopped");
- worker_stopped = true;
- verbose(3, "Sending wakeup signal to client in a mjit-worker");
- rb_native_cond_signal(&mjit_client_wakeup);
- CRITICAL_SECTION_FINISH(3, "in worker to update worker_stopped");
- return; // TODO: do the same thing in the latter half of mjit_finish
- }
-
- // main worker loop
- while (!stop_worker_p) {
- struct rb_mjit_unit *unit;
-
- // 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");
-
- if (unit) {
- // JIT compile
- mjit_func_t func = convert_unit_to_func(unit);
- (void)RB_DEBUG_COUNTER_INC_IF(mjit_compile_failures, func == (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC);
-
- CRITICAL_SECTION_START(3, "in jit func replace");
- while (in_gc) { // Make sure we're not GC-ing when touching ISeq
- verbose(3, "Waiting wakeup from GC");
- rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex);
- }
- if (unit->iseq) { // Check whether GCed or not
- if ((uintptr_t)func > (uintptr_t)LAST_JIT_ISEQ_FUNC) {
- add_to_list(unit, &active_units);
- }
- // Usage of jit_code might be not in a critical section.
- MJIT_ATOMIC_SET(unit->iseq->body->jit_func, func);
- }
- else {
- free_unit(unit);
- }
- CRITICAL_SECTION_FINISH(3, "in jit func replace");
-
-#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
- }
- }
-
- // To keep mutex unlocked when it is destroyed by mjit_finish, don't wrap CRITICAL_SECTION here.
- worker_stopped = true;
-}
diff --git a/node.c b/node.c
index cd1c3f0b0a..a6cb498778 100644
--- a/node.c
+++ b/node.c
@@ -29,10 +29,10 @@
#define A_LIT(lit) AR(rb_dump_literal(lit))
#define A_NODE_HEADER(node, term) \
rb_str_catf(buf, "@ %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))%s"term, \
- ruby_node_name(nd_type(node)), nd_node_id(node), nd_line(node), \
- nd_first_lineno(node), nd_first_column(node), \
- nd_last_lineno(node), nd_last_column(node), \
- (node->flags & NODE_FL_NEWLINE ? "*" : ""))
+ ruby_node_name(nd_type(node)), nd_node_id(node), nd_line(node), \
+ nd_first_lineno(node), nd_first_column(node), \
+ nd_last_lineno(node), nd_last_column(node), \
+ (node->flags & NODE_FL_NEWLINE ? "*" : ""))
#define A_FIELD_HEADER(len, name, term) \
rb_str_catf(buf, "+- %.*s:"term, (len), (name))
#define D_FIELD_HEADER(len, name, term) (A_INDENT, A_FIELD_HEADER(len, name, term))
@@ -45,20 +45,20 @@
#define COMPOUND_FIELD1(name, ann) \
COMPOUND_FIELD(FIELD_NAME_LEN(name, ann), \
- FIELD_NAME_DESC(name, ann))
+ FIELD_NAME_DESC(name, ann))
#define FIELD_NAME_DESC(name, ann) name " (" ann ")"
#define FIELD_NAME_LEN(name, ann) (int)( \
- comment ? \
- rb_strlen_lit(FIELD_NAME_DESC(name, ann)) : \
- rb_strlen_lit(name))
+ comment ? \
+ rb_strlen_lit(FIELD_NAME_DESC(name, ann)) : \
+ rb_strlen_lit(name))
#define SIMPLE_FIELD(len, name) \
FIELD_BLOCK(D_FIELD_HEADER((len), (name), " "), A("\n"))
#define FIELD_BLOCK(init, reset) \
for (init, field_flag = 1; \
- field_flag; /* should be optimized away */ \
- reset, field_flag = 0)
+ field_flag; /* should be optimized away */ \
+ reset, field_flag = 0)
#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)
@@ -74,7 +74,7 @@
#define ANN(ann) \
if (comment) { \
- A_INDENT; A("| # " ann "\n"); \
+ A_INDENT; A("| # " ann "\n"); \
}
#define LAST_NODE (next_indent = " ")
@@ -108,16 +108,16 @@ static void
add_id(VALUE buf, ID id)
{
if (id == 0) {
- A("(null)");
+ A("(null)");
}
else {
- VALUE str = rb_id2str(id);
- if (str) {
- A(":"); AR(str);
- }
- else {
+ VALUE str = rb_id2str(id);
+ if (str) {
+ A(":"); AR(str);
+ }
+ else {
rb_str_catf(buf, "(internal variable: 0x%"PRIsVALUE")", id);
- }
+ }
}
}
@@ -136,9 +136,9 @@ dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
const char *next_indent = default_indent;
F_LONG(nd_alen, "length");
F_NODE(nd_head, "element");
- while (node->nd_next && nd_type(node->nd_next) == NODE_LIST) {
- node = node->nd_next;
- F_NODE(nd_head, "element");
+ while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
+ node = node->nd_next;
+ F_NODE(nd_head, "element");
}
LAST_NODE;
F_NODE(nd_next, "next element");
@@ -153,8 +153,8 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
enum node_type type;
if (!node) {
- D_NULL_NODE;
- return;
+ D_NULL_NODE;
+ return;
}
D_NODE_HEADER(node);
@@ -162,63 +162,63 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
type = nd_type(node);
switch (type) {
case NODE_BLOCK:
- ANN("statement sequence");
- ANN("format: [nd_head]; ...; [nd_next]");
- ANN("example: foo; bar");
- i = 0;
- do {
- A_INDENT;
- rb_str_catf(buf, "+- nd_head (%s%d):\n",
- comment ? "statement #" : "", ++i);
- if (!node->nd_next) LAST_NODE;
- D_INDENT;
- dump_node(buf, indent, comment, node->nd_head);
- D_DEDENT;
- } while (node->nd_next &&
- nd_type(node->nd_next) == NODE_BLOCK &&
- (node = node->nd_next, 1));
- if (node->nd_next) {
- LAST_NODE;
- F_NODE(nd_next, "next block");
- }
- return;
+ ANN("statement sequence");
+ ANN("format: [nd_head]; ...; [nd_next]");
+ ANN("example: foo; bar");
+ i = 0;
+ do {
+ A_INDENT;
+ rb_str_catf(buf, "+- nd_head (%s%d):\n",
+ comment ? "statement #" : "", ++i);
+ if (!node->nd_next) LAST_NODE;
+ D_INDENT;
+ dump_node(buf, indent, comment, node->nd_head);
+ D_DEDENT;
+ } while (node->nd_next &&
+ nd_type_p(node->nd_next, NODE_BLOCK) &&
+ (node = node->nd_next, 1));
+ if (node->nd_next) {
+ LAST_NODE;
+ F_NODE(nd_next, "next block");
+ }
+ return;
case NODE_IF:
- ANN("if statement");
- ANN("format: if [nd_cond] then [nd_body] else [nd_else] end");
- ANN("example: if x == 1 then foo else bar end");
- F_NODE(nd_cond, "condition expr");
- F_NODE(nd_body, "then clause");
- LAST_NODE;
- F_NODE(nd_else, "else clause");
- return;
+ ANN("if statement");
+ ANN("format: if [nd_cond] then [nd_body] else [nd_else] end");
+ ANN("example: if x == 1 then foo else bar end");
+ F_NODE(nd_cond, "condition expr");
+ F_NODE(nd_body, "then clause");
+ LAST_NODE;
+ F_NODE(nd_else, "else clause");
+ return;
case NODE_UNLESS:
- ANN("unless statement");
- ANN("format: unless [nd_cond] then [nd_body] else [nd_else] end");
- ANN("example: unless x == 1 then foo else bar end");
- F_NODE(nd_cond, "condition expr");
- F_NODE(nd_body, "then clause");
- LAST_NODE;
- F_NODE(nd_else, "else clause");
- return;
+ ANN("unless statement");
+ ANN("format: unless [nd_cond] then [nd_body] else [nd_else] end");
+ ANN("example: unless x == 1 then foo else bar end");
+ F_NODE(nd_cond, "condition expr");
+ F_NODE(nd_body, "then clause");
+ LAST_NODE;
+ F_NODE(nd_else, "else clause");
+ return;
case NODE_CASE:
- ANN("case statement");
- ANN("format: case [nd_head]; [nd_body]; end");
- ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
- F_NODE(nd_head, "case expr");
- LAST_NODE;
- F_NODE(nd_body, "when clauses");
- return;
+ ANN("case statement");
+ ANN("format: case [nd_head]; [nd_body]; end");
+ ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
+ F_NODE(nd_head, "case expr");
+ LAST_NODE;
+ F_NODE(nd_body, "when clauses");
+ return;
case NODE_CASE2:
- ANN("case statement with no head");
- ANN("format: case; [nd_body]; end");
- ANN("example: case; when 1; foo; when 2; bar; else baz; end");
- F_NODE(nd_head, "case expr");
- LAST_NODE;
- F_NODE(nd_body, "when clauses");
- return;
+ ANN("case statement with no head");
+ ANN("format: case; [nd_body]; end");
+ ANN("example: case; when 1; foo; when 2; bar; else baz; end");
+ F_NODE(nd_head, "case expr");
+ LAST_NODE;
+ F_NODE(nd_body, "when clauses");
+ return;
case NODE_CASE3:
ANN("case statement (pattern matching)");
ANN("format: case [nd_head]; [nd_body]; end");
@@ -229,14 +229,14 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
return;
case NODE_WHEN:
- ANN("when clause");
- ANN("format: when [nd_head]; [nd_body]; (when or else) [nd_next]");
- ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
- F_NODE(nd_head, "when value");
- F_NODE(nd_body, "when body");
- LAST_NODE;
- F_NODE(nd_next, "next when clause");
- return;
+ ANN("when clause");
+ ANN("format: when [nd_head]; [nd_body]; (when or else) [nd_next]");
+ ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
+ F_NODE(nd_head, "when value");
+ F_NODE(nd_body, "when body");
+ LAST_NODE;
+ F_NODE(nd_next, "next when clause");
+ return;
case NODE_IN:
ANN("in clause");
@@ -249,285 +249,278 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
return;
case NODE_WHILE:
- ANN("while statement");
- ANN("format: while [nd_cond]; [nd_body]; end");
- ANN("example: while x == 1; foo; end");
- goto loop;
+ ANN("while statement");
+ ANN("format: while [nd_cond]; [nd_body]; end");
+ ANN("example: while x == 1; foo; end");
+ goto loop;
case NODE_UNTIL:
- ANN("until statement");
- ANN("format: until [nd_cond]; [nd_body]; end");
- ANN("example: until x == 1; foo; end");
+ ANN("until statement");
+ ANN("format: until [nd_cond]; [nd_body]; end");
+ ANN("example: until x == 1; foo; end");
loop:
- F_CUSTOM1(nd_state, "begin-end-while?") {
- A_INT((int)node->nd_state);
- A((node->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
- }
- F_NODE(nd_cond, "condition");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
+ F_CUSTOM1(nd_state, "begin-end-while?") {
+ A_INT((int)node->nd_state);
+ A((node->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
+ }
+ F_NODE(nd_cond, "condition");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
case NODE_ITER:
- ANN("method call with block");
- ANN("format: [nd_iter] { [nd_body] }");
- ANN("example: 3.times { foo }");
- goto iter;
+ ANN("method call with block");
+ ANN("format: [nd_iter] { [nd_body] }");
+ ANN("example: 3.times { foo }");
+ goto iter;
case NODE_FOR:
- ANN("for statement");
- ANN("format: for * in [nd_iter] do [nd_body] end");
- ANN("example: for i in 1..3 do foo end");
+ ANN("for statement");
+ ANN("format: for * in [nd_iter] do [nd_body] end");
+ ANN("example: for i in 1..3 do foo end");
iter:
- F_NODE(nd_iter, "iteration receiver");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
+ F_NODE(nd_iter, "iteration receiver");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
case NODE_FOR_MASGN:
- ANN("vars of for statement with masgn");
- ANN("format: for [nd_var] in ... do ... end");
- ANN("example: for x, y in 1..3 do foo end");
- LAST_NODE;
- F_NODE(nd_var, "var");
- return;
+ ANN("vars of for statement with masgn");
+ ANN("format: for [nd_var] in ... do ... end");
+ ANN("example: for x, y in 1..3 do foo end");
+ LAST_NODE;
+ F_NODE(nd_var, "var");
+ return;
case NODE_BREAK:
- ANN("break statement");
- ANN("format: break [nd_stts]");
- ANN("example: break 1");
- goto jump;
+ ANN("break statement");
+ ANN("format: break [nd_stts]");
+ ANN("example: break 1");
+ goto jump;
case NODE_NEXT:
- ANN("next statement");
- ANN("format: next [nd_stts]");
- ANN("example: next 1");
- goto jump;
+ ANN("next statement");
+ ANN("format: next [nd_stts]");
+ ANN("example: next 1");
+ goto jump;
case NODE_RETURN:
- ANN("return statement");
- ANN("format: return [nd_stts]");
- ANN("example: return 1");
+ ANN("return statement");
+ ANN("format: return [nd_stts]");
+ ANN("example: return 1");
jump:
- LAST_NODE;
- F_NODE(nd_stts, "value");
- return;
+ LAST_NODE;
+ F_NODE(nd_stts, "value");
+ return;
case NODE_REDO:
- ANN("redo statement");
- ANN("format: redo");
- ANN("example: redo");
- return;
+ ANN("redo statement");
+ ANN("format: redo");
+ ANN("example: redo");
+ return;
case NODE_RETRY:
- ANN("retry statement");
- ANN("format: retry");
- ANN("example: retry");
- return;
+ ANN("retry statement");
+ ANN("format: retry");
+ ANN("example: retry");
+ return;
case NODE_BEGIN:
- ANN("begin statement");
- ANN("format: begin; [nd_body]; end");
- ANN("example: begin; 1; end");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
+ ANN("begin statement");
+ ANN("format: begin; [nd_body]; end");
+ ANN("example: begin; 1; end");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
case NODE_RESCUE:
- ANN("rescue clause");
- ANN("format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end");
- ANN("example: begin; foo; rescue; bar; else; baz; end");
- F_NODE(nd_head, "body");
- F_NODE(nd_resq, "rescue clause list");
- LAST_NODE;
- F_NODE(nd_else, "rescue else clause");
- return;
+ ANN("rescue clause");
+ ANN("format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end");
+ ANN("example: begin; foo; rescue; bar; else; baz; end");
+ F_NODE(nd_head, "body");
+ F_NODE(nd_resq, "rescue clause list");
+ LAST_NODE;
+ F_NODE(nd_else, "rescue else clause");
+ return;
case NODE_RESBODY:
- ANN("rescue clause (cont'd)");
- ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
- ANN("example: begin; foo; rescue; bar; else; baz; end");
- F_NODE(nd_args, "rescue exceptions");
- F_NODE(nd_body, "rescue clause");
- LAST_NODE;
- F_NODE(nd_head, "next rescue clause");
- return;
+ ANN("rescue clause (cont'd)");
+ ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
+ ANN("example: begin; foo; rescue; bar; else; baz; end");
+ F_NODE(nd_args, "rescue exceptions");
+ F_NODE(nd_body, "rescue clause");
+ LAST_NODE;
+ F_NODE(nd_head, "next rescue clause");
+ return;
case NODE_ENSURE:
- ANN("ensure clause");
- ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
- ANN("example: begin; foo; ensure; bar; end");
- F_NODE(nd_head, "body");
- LAST_NODE;
- F_NODE(nd_ensr, "ensure clause");
- return;
+ ANN("ensure clause");
+ ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
+ ANN("example: begin; foo; ensure; bar; end");
+ F_NODE(nd_head, "body");
+ LAST_NODE;
+ F_NODE(nd_ensr, "ensure clause");
+ return;
case NODE_AND:
- ANN("&& operator");
- ANN("format: [nd_1st] && [nd_2nd]");
- ANN("example: foo && bar");
- goto andor;
+ ANN("&& operator");
+ ANN("format: [nd_1st] && [nd_2nd]");
+ ANN("example: foo && bar");
+ goto andor;
case NODE_OR:
- ANN("|| operator");
- ANN("format: [nd_1st] || [nd_2nd]");
- ANN("example: foo || bar");
+ ANN("|| operator");
+ ANN("format: [nd_1st] || [nd_2nd]");
+ ANN("example: foo || bar");
andor:
- while (1) {
- F_NODE(nd_1st, "left expr");
- if (!node->nd_2nd || nd_type(node->nd_2nd) != (int)type)
- break;
- node = node->nd_2nd;
- }
- LAST_NODE;
- F_NODE(nd_2nd, "right expr");
- return;
+ while (1) {
+ F_NODE(nd_1st, "left expr");
+ if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
+ break;
+ node = node->nd_2nd;
+ }
+ LAST_NODE;
+ F_NODE(nd_2nd, "right expr");
+ return;
case NODE_MASGN:
- ANN("multiple assignment");
- ANN("format: [nd_head], [nd_args] = [nd_value]");
- ANN("example: a, b = foo");
- F_NODE(nd_value, "rhsn");
- F_NODE(nd_head, "lhsn");
- if (NODE_NAMED_REST_P(node->nd_args)) {
- LAST_NODE;
- F_NODE(nd_args, "splatn");
- }
- else {
- F_MSG(nd_args, "splatn", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- return;
+ ANN("multiple assignment");
+ ANN("format: [nd_head], [nd_args] = [nd_value]");
+ ANN("example: a, b = foo");
+ F_NODE(nd_value, "rhsn");
+ F_NODE(nd_head, "lhsn");
+ if (NODE_NAMED_REST_P(node->nd_args)) {
+ LAST_NODE;
+ F_NODE(nd_args, "splatn");
+ }
+ else {
+ F_MSG(nd_args, "splatn", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ return;
case NODE_LASGN:
- ANN("local variable assignment");
- ANN("format: [nd_vid](lvar) = [nd_value]");
- ANN("example: x = foo");
- F_ID(nd_vid, "local variable");
- if (NODE_REQUIRED_KEYWORD_P(node)) {
- F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
- }
- else {
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- }
- return;
+ ANN("local variable assignment");
+ ANN("format: [nd_vid](lvar) = [nd_value]");
+ ANN("example: x = foo");
+ F_ID(nd_vid, "local variable");
+ if (NODE_REQUIRED_KEYWORD_P(node)) {
+ F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
+ }
+ else {
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ }
+ return;
case NODE_DASGN:
- ANN("dynamic variable assignment (out of current scope)");
- ANN("format: [nd_vid](dvar) = [nd_value]");
- ANN("example: x = nil; 1.times { x = foo }");
- F_ID(nd_vid, "local variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
- case NODE_DASGN_CURR:
- ANN("dynamic variable assignment (in current scope)");
- ANN("format: [nd_vid](current dvar) = [nd_value]");
- ANN("example: 1.times { x = foo }");
- F_ID(nd_vid, "local variable");
- if (NODE_REQUIRED_KEYWORD_P(node)) {
- F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
- }
- else {
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- }
- return;
+ ANN("dynamic variable assignment");
+ ANN("format: [nd_vid](dvar) = [nd_value]");
+ ANN("example: x = nil; 1.times { x = foo }");
+ ANN("example: 1.times { x = foo }");
+ F_ID(nd_vid, "local variable");
+ if (NODE_REQUIRED_KEYWORD_P(node)) {
+ F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
+ }
+ else {
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ }
+ return;
case NODE_IASGN:
- ANN("instance variable assignment");
- ANN("format: [nd_vid](ivar) = [nd_value]");
- ANN("example: @x = foo");
- F_ID(nd_vid, "instance variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ ANN("instance variable assignment");
+ ANN("format: [nd_vid](ivar) = [nd_value]");
+ ANN("example: @x = foo");
+ F_ID(nd_vid, "instance variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_CVASGN:
- ANN("class variable assignment");
- ANN("format: [nd_vid](cvar) = [nd_value]");
- ANN("example: @@x = foo");
- F_ID(nd_vid, "class variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ ANN("class variable assignment");
+ ANN("format: [nd_vid](cvar) = [nd_value]");
+ ANN("example: @@x = foo");
+ F_ID(nd_vid, "class variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_GASGN:
- ANN("global variable assignment");
- ANN("format: [nd_entry](gvar) = [nd_value]");
- ANN("example: $x = foo");
- F_GENTRY(nd_entry, "global variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ ANN("global variable assignment");
+ ANN("format: [nd_entry](gvar) = [nd_value]");
+ ANN("example: $x = foo");
+ F_GENTRY(nd_entry, "global variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_CDECL:
- ANN("constant declaration");
- ANN("format: [nd_else]::[nd_vid](constant) = [nd_value]");
- ANN("example: X = foo");
- if (node->nd_vid) {
- F_ID(nd_vid, "constant");
- F_MSG(nd_else, "extension", "not used");
- }
- else {
- F_MSG(nd_vid, "constant", "0 (see extension field)");
- F_NODE(nd_else, "extension");
- }
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ ANN("constant declaration");
+ ANN("format: [nd_else]::[nd_vid](constant) = [nd_value]");
+ ANN("example: X = foo");
+ if (node->nd_vid) {
+ F_ID(nd_vid, "constant");
+ F_MSG(nd_else, "extension", "not used");
+ }
+ else {
+ F_MSG(nd_vid, "constant", "0 (see extension field)");
+ F_NODE(nd_else, "extension");
+ }
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_OP_ASGN1:
- ANN("array assignment with operator");
- ANN("format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body]");
- ANN("example: ary[1] += foo");
- F_NODE(nd_recv, "receiver");
- F_ID(nd_mid, "operator");
- F_NODE(nd_args->nd_head, "index");
- LAST_NODE;
- F_NODE(nd_args->nd_body, "rvalue");
- return;
+ ANN("array assignment with operator");
+ ANN("format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body]");
+ ANN("example: ary[1] += foo");
+ F_NODE(nd_recv, "receiver");
+ F_ID(nd_mid, "operator");
+ F_NODE(nd_args->nd_head, "index");
+ LAST_NODE;
+ F_NODE(nd_args->nd_body, "rvalue");
+ return;
case NODE_OP_ASGN2:
- ANN("attr assignment with operator");
- ANN("format: [nd_recv].[attr] [nd_next->nd_mid]= [nd_value]");
- ANN(" where [attr]: [nd_next->nd_vid]");
- ANN("example: struct.field += foo");
- F_NODE(nd_recv, "receiver");
- F_CUSTOM1(nd_next->nd_vid, "attr") {
- if (node->nd_next->nd_aid) A("? ");
- A_ID(node->nd_next->nd_vid);
- }
- F_ID(nd_next->nd_mid, "operator");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ ANN("attr assignment with operator");
+ ANN("format: [nd_recv].[attr] [nd_next->nd_mid]= [nd_value]");
+ ANN(" where [attr]: [nd_next->nd_vid]");
+ ANN("example: struct.field += foo");
+ F_NODE(nd_recv, "receiver");
+ F_CUSTOM1(nd_next->nd_vid, "attr") {
+ if (node->nd_next->nd_aid) A("? ");
+ A_ID(node->nd_next->nd_vid);
+ }
+ F_ID(nd_next->nd_mid, "operator");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_OP_ASGN_AND:
- ANN("assignment with && operator");
- ANN("format: [nd_head] &&= [nd_value]");
- ANN("example: foo &&= bar");
- goto asgn_andor;
+ ANN("assignment with && operator");
+ ANN("format: [nd_head] &&= [nd_value]");
+ ANN("example: foo &&= bar");
+ goto asgn_andor;
case NODE_OP_ASGN_OR:
- ANN("assignment with || operator");
- ANN("format: [nd_head] ||= [nd_value]");
- ANN("example: foo ||= bar");
+ ANN("assignment with || operator");
+ ANN("format: [nd_head] ||= [nd_value]");
+ ANN("example: foo ||= bar");
asgn_andor:
- F_NODE(nd_head, "variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ F_NODE(nd_head, "variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_OP_CDECL:
- ANN("constant declaration with operator");
- ANN("format: [nd_head](constant) [nd_aid]= [nd_value]");
- ANN("example: A::B ||= 1");
- F_NODE(nd_head, "constant");
- F_ID(nd_aid, "operator");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
+ ANN("constant declaration with operator");
+ ANN("format: [nd_head](constant) [nd_aid]= [nd_value]");
+ ANN("example: A::B ||= 1");
+ F_NODE(nd_head, "constant");
+ F_ID(nd_aid, "operator");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
case NODE_CALL:
- ANN("method invocation");
- ANN("format: [nd_recv].[nd_mid]([nd_args])");
- ANN("example: obj.foo(1)");
- F_ID(nd_mid, "method id");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
+ ANN("method invocation");
+ ANN("format: [nd_recv].[nd_mid]([nd_args])");
+ ANN("example: obj.foo(1)");
+ F_ID(nd_mid, "method id");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
case NODE_OPCALL:
ANN("method invocation");
@@ -540,492 +533,490 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
return;
case NODE_FCALL:
- ANN("function call");
- ANN("format: [nd_mid]([nd_args])");
- ANN("example: foo(1)");
- F_ID(nd_mid, "method id");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
+ ANN("function call");
+ ANN("format: [nd_mid]([nd_args])");
+ ANN("example: foo(1)");
+ F_ID(nd_mid, "method id");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
case NODE_VCALL:
- ANN("function call with no argument");
- ANN("format: [nd_mid]");
- ANN("example: foo");
- F_ID(nd_mid, "method id");
- return;
+ ANN("function call with no argument");
+ ANN("format: [nd_mid]");
+ ANN("example: foo");
+ F_ID(nd_mid, "method id");
+ return;
case NODE_QCALL:
- ANN("safe method invocation");
- ANN("format: [nd_recv]&.[nd_mid]([nd_args])");
- ANN("example: obj&.foo(1)");
- F_ID(nd_mid, "method id");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
+ ANN("safe method invocation");
+ ANN("format: [nd_recv]&.[nd_mid]([nd_args])");
+ ANN("example: obj&.foo(1)");
+ F_ID(nd_mid, "method id");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
case NODE_SUPER:
- ANN("super invocation");
- ANN("format: super [nd_args]");
- ANN("example: super 1");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
+ ANN("super invocation");
+ ANN("format: super [nd_args]");
+ ANN("example: super 1");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
case NODE_ZSUPER:
- ANN("super invocation with no argument");
- ANN("format: super");
- ANN("example: super");
- return;
+ ANN("super invocation with no argument");
+ ANN("format: super");
+ ANN("example: super");
+ return;
case NODE_LIST:
- ANN("list constructor");
- ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
- ANN("example: [1, 2, 3]");
- goto ary;
+ ANN("list constructor");
+ ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
+ ANN("example: [1, 2, 3]");
+ goto ary;
case NODE_VALUES:
- ANN("return arguments");
- ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
- ANN("example: return 1, 2, 3");
+ ANN("return arguments");
+ ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
+ ANN("example: return 1, 2, 3");
ary:
- dump_array(buf, indent, comment, node);
- return;
+ dump_array(buf, indent, comment, node);
+ return;
case NODE_ZLIST:
- ANN("empty list constructor");
- ANN("format: []");
- ANN("example: []");
- return;
+ ANN("empty list constructor");
+ ANN("format: []");
+ ANN("example: []");
+ return;
case NODE_HASH:
if (!node->nd_brace) {
- ANN("keyword arguments");
- ANN("format: nd_head");
- ANN("example: a: 1, b: 2");
- }
- else {
- ANN("hash constructor");
- ANN("format: { [nd_head] }");
- ANN("example: { 1 => 2, 3 => 4 }");
- }
+ ANN("keyword arguments");
+ ANN("format: nd_head");
+ ANN("example: a: 1, b: 2");
+ }
+ else {
+ ANN("hash constructor");
+ ANN("format: { [nd_head] }");
+ ANN("example: { 1 => 2, 3 => 4 }");
+ }
F_CUSTOM1(nd_brace, "keyword arguments or hash literal") {
switch (node->nd_brace) {
- case 0: A("0 (keyword argument)"); break;
- case 1: A("1 (hash literal)"); break;
- }
- }
- LAST_NODE;
- F_NODE(nd_head, "contents");
- return;
+ case 0: A("0 (keyword argument)"); break;
+ case 1: A("1 (hash literal)"); break;
+ }
+ }
+ LAST_NODE;
+ F_NODE(nd_head, "contents");
+ return;
case NODE_YIELD:
- ANN("yield invocation");
- ANN("format: yield [nd_head]");
- ANN("example: yield 1");
- LAST_NODE;
- F_NODE(nd_head, "arguments");
- return;
+ ANN("yield invocation");
+ ANN("format: yield [nd_head]");
+ ANN("example: yield 1");
+ LAST_NODE;
+ F_NODE(nd_head, "arguments");
+ return;
case NODE_LVAR:
- ANN("local variable reference");
- ANN("format: [nd_vid](lvar)");
- ANN("example: x");
- F_ID(nd_vid, "local variable");
- return;
+ ANN("local variable reference");
+ ANN("format: [nd_vid](lvar)");
+ ANN("example: x");
+ F_ID(nd_vid, "local variable");
+ return;
case NODE_DVAR:
- ANN("dynamic variable reference");
- ANN("format: [nd_vid](dvar)");
- ANN("example: 1.times { x = 1; x }");
- F_ID(nd_vid, "local variable");
- return;
+ ANN("dynamic variable reference");
+ ANN("format: [nd_vid](dvar)");
+ ANN("example: 1.times { x = 1; x }");
+ F_ID(nd_vid, "local variable");
+ return;
case NODE_IVAR:
- ANN("instance variable reference");
- ANN("format: [nd_vid](ivar)");
- ANN("example: @x");
- F_ID(nd_vid, "instance variable");
- return;
+ ANN("instance variable reference");
+ ANN("format: [nd_vid](ivar)");
+ ANN("example: @x");
+ F_ID(nd_vid, "instance variable");
+ return;
case NODE_CONST:
- ANN("constant reference");
- ANN("format: [nd_vid](constant)");
- ANN("example: X");
- F_ID(nd_vid, "constant");
- return;
+ ANN("constant reference");
+ ANN("format: [nd_vid](constant)");
+ ANN("example: X");
+ F_ID(nd_vid, "constant");
+ return;
case NODE_CVAR:
- ANN("class variable reference");
- ANN("format: [nd_vid](cvar)");
- ANN("example: @@x");
- F_ID(nd_vid, "class variable");
- return;
+ ANN("class variable reference");
+ ANN("format: [nd_vid](cvar)");
+ ANN("example: @@x");
+ F_ID(nd_vid, "class variable");
+ return;
case NODE_GVAR:
- ANN("global variable reference");
- ANN("format: [nd_entry](gvar)");
- ANN("example: $x");
- F_GENTRY(nd_entry, "global variable");
- return;
+ ANN("global variable reference");
+ ANN("format: [nd_entry](gvar)");
+ ANN("example: $x");
+ F_GENTRY(nd_entry, "global variable");
+ return;
case NODE_NTH_REF:
- ANN("nth special variable reference");
- ANN("format: $[nd_nth]");
- ANN("example: $1, $2, ..");
- F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(node->nd_nth); }
- return;
+ ANN("nth special variable reference");
+ ANN("format: $[nd_nth]");
+ ANN("example: $1, $2, ..");
+ F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(node->nd_nth); }
+ return;
case NODE_BACK_REF:
- ANN("back special variable reference");
- ANN("format: $[nd_nth]");
- ANN("example: $&, $`, $', $+");
- F_CUSTOM1(nd_nth, "variable") {
- char name[3];
- name[0] = '$';
- name[1] = (char)node->nd_nth;
- name[2] = '\0';
- A(name);
- }
- return;
+ ANN("back special variable reference");
+ ANN("format: $[nd_nth]");
+ ANN("example: $&, $`, $', $+");
+ F_CUSTOM1(nd_nth, "variable") {
+ char name[3] = "$ ";
+ name[1] = (char)node->nd_nth;
+ A(name);
+ }
+ return;
case NODE_MATCH:
- ANN("match expression (against $_ implicitly)");
+ ANN("match expression (against $_ implicitly)");
ANN("format: [nd_lit] (in condition)");
- ANN("example: if /foo/; foo; end");
- F_LIT(nd_lit, "regexp");
- return;
+ ANN("example: if /foo/; foo; end");
+ F_LIT(nd_lit, "regexp");
+ return;
case NODE_MATCH2:
- ANN("match expression (regexp first)");
+ ANN("match expression (regexp first)");
ANN("format: [nd_recv] =~ [nd_value]");
- ANN("example: /foo/ =~ 'foo'");
- F_NODE(nd_recv, "regexp (receiver)");
- if (!node->nd_args) LAST_NODE;
- F_NODE(nd_value, "string (argument)");
- if (node->nd_args) {
- LAST_NODE;
- F_NODE(nd_args, "named captures");
- }
- return;
+ ANN("example: /foo/ =~ 'foo'");
+ F_NODE(nd_recv, "regexp (receiver)");
+ if (!node->nd_args) LAST_NODE;
+ F_NODE(nd_value, "string (argument)");
+ if (node->nd_args) {
+ LAST_NODE;
+ F_NODE(nd_args, "named captures");
+ }
+ return;
case NODE_MATCH3:
- ANN("match expression (regexp second)");
+ ANN("match expression (regexp second)");
ANN("format: [nd_recv] =~ [nd_value]");
- ANN("example: 'foo' =~ /foo/");
- F_NODE(nd_recv, "string (receiver)");
- LAST_NODE;
- F_NODE(nd_value, "regexp (argument)");
- return;
+ ANN("example: 'foo' =~ /foo/");
+ F_NODE(nd_recv, "string (receiver)");
+ LAST_NODE;
+ F_NODE(nd_value, "regexp (argument)");
+ return;
case NODE_LIT:
- ANN("literal");
- ANN("format: [nd_lit]");
- ANN("example: 1, /foo/");
- goto lit;
+ ANN("literal");
+ ANN("format: [nd_lit]");
+ ANN("example: 1, /foo/");
+ goto lit;
case NODE_STR:
- ANN("string literal");
- ANN("format: [nd_lit]");
- ANN("example: 'foo'");
- goto lit;
+ ANN("string literal");
+ ANN("format: [nd_lit]");
+ ANN("example: 'foo'");
+ goto lit;
case NODE_XSTR:
- ANN("xstring literal");
- ANN("format: [nd_lit]");
- ANN("example: `foo`");
+ ANN("xstring literal");
+ ANN("format: [nd_lit]");
+ ANN("example: `foo`");
lit:
- F_LIT(nd_lit, "literal");
- return;
+ F_LIT(nd_lit, "literal");
+ return;
case NODE_ONCE:
- ANN("once evaluation");
- ANN("format: [nd_body]");
- ANN("example: /foo#{ bar }baz/o");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
+ ANN("once evaluation");
+ ANN("format: [nd_body]");
+ ANN("example: /foo#{ bar }baz/o");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
case NODE_DSTR:
- ANN("string literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: \"foo#{ bar }baz\"");
- goto dlit;
+ ANN("string literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: \"foo#{ bar }baz\"");
+ goto dlit;
case NODE_DXSTR:
- ANN("xstring literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: `foo#{ bar }baz`");
- goto dlit;
+ ANN("xstring literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: `foo#{ bar }baz`");
+ goto dlit;
case NODE_DREGX:
- ANN("regexp literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: /foo#{ bar }baz/");
- goto dlit;
+ ANN("regexp literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: /foo#{ bar }baz/");
+ goto dlit;
case NODE_DSYM:
- ANN("symbol literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: :\"foo#{ bar }baz\"");
+ ANN("symbol literal with interpolation");
+ ANN("format: [nd_lit]");
+ 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");
- return;
+ 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");
+ return;
case NODE_EVSTR:
- ANN("interpolation expression");
- ANN("format: \"..#{ [nd_lit] }..\"");
- ANN("example: \"foo#{ bar }baz\"");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
+ ANN("interpolation expression");
+ ANN("format: \"..#{ [nd_lit] }..\"");
+ ANN("example: \"foo#{ bar }baz\"");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
case NODE_ARGSCAT:
- ANN("splat argument following arguments");
- ANN("format: ..(*[nd_head], [nd_body..])");
- ANN("example: foo(*ary, post_arg1, post_arg2)");
- F_NODE(nd_head, "preceding array");
- LAST_NODE;
- F_NODE(nd_body, "following array");
- return;
+ ANN("splat argument following arguments");
+ ANN("format: ..(*[nd_head], [nd_body..])");
+ ANN("example: foo(*ary, post_arg1, post_arg2)");
+ F_NODE(nd_head, "preceding array");
+ LAST_NODE;
+ F_NODE(nd_body, "following array");
+ return;
case NODE_ARGSPUSH:
- ANN("splat argument following one argument");
- ANN("format: ..(*[nd_head], [nd_body])");
- ANN("example: foo(*ary, post_arg)");
- F_NODE(nd_head, "preceding array");
- LAST_NODE;
- F_NODE(nd_body, "following element");
- return;
+ ANN("splat argument following one argument");
+ ANN("format: ..(*[nd_head], [nd_body])");
+ ANN("example: foo(*ary, post_arg)");
+ F_NODE(nd_head, "preceding array");
+ LAST_NODE;
+ F_NODE(nd_body, "following element");
+ return;
case NODE_SPLAT:
- ANN("splat argument");
- ANN("format: *[nd_head]");
- ANN("example: foo(*ary)");
- LAST_NODE;
- F_NODE(nd_head, "splat'ed array");
- return;
+ ANN("splat argument");
+ ANN("format: *[nd_head]");
+ ANN("example: foo(*ary)");
+ LAST_NODE;
+ F_NODE(nd_head, "splat'ed array");
+ return;
case NODE_BLOCK_PASS:
- ANN("arguments with block argument");
- ANN("format: ..([nd_head], &[nd_body])");
- ANN("example: foo(x, &blk)");
- F_NODE(nd_head, "other arguments");
- LAST_NODE;
- F_NODE(nd_body, "block argument");
- return;
+ ANN("arguments with block argument");
+ ANN("format: ..([nd_head], &[nd_body])");
+ ANN("example: foo(x, &blk)");
+ F_NODE(nd_head, "other arguments");
+ LAST_NODE;
+ F_NODE(nd_body, "block argument");
+ return;
case NODE_DEFN:
- ANN("method definition");
- ANN("format: def [nd_mid] [nd_defn]; end");
- ANN("example: def foo; bar; end");
- F_ID(nd_mid, "method name");
- LAST_NODE;
- F_NODE(nd_defn, "method definition");
- return;
+ ANN("method definition");
+ ANN("format: def [nd_mid] [nd_defn]; end");
+ ANN("example: def foo; bar; end");
+ F_ID(nd_mid, "method name");
+ LAST_NODE;
+ F_NODE(nd_defn, "method definition");
+ return;
case NODE_DEFS:
- ANN("singleton method definition");
- ANN("format: def [nd_recv].[nd_mid] [nd_defn]; end");
- ANN("example: def obj.foo; bar; end");
- F_NODE(nd_recv, "receiver");
- F_ID(nd_mid, "method name");
- LAST_NODE;
- F_NODE(nd_defn, "method definition");
- return;
+ ANN("singleton method definition");
+ ANN("format: def [nd_recv].[nd_mid] [nd_defn]; end");
+ ANN("example: def obj.foo; bar; end");
+ F_NODE(nd_recv, "receiver");
+ F_ID(nd_mid, "method name");
+ LAST_NODE;
+ F_NODE(nd_defn, "method definition");
+ return;
case NODE_ALIAS:
- ANN("method alias statement");
- ANN("format: alias [nd_1st] [nd_2nd]");
- ANN("example: alias bar foo");
- F_NODE(nd_1st, "new name");
- LAST_NODE;
- F_NODE(nd_2nd, "old name");
- return;
+ ANN("method alias statement");
+ ANN("format: alias [nd_1st] [nd_2nd]");
+ ANN("example: alias bar foo");
+ F_NODE(nd_1st, "new name");
+ LAST_NODE;
+ F_NODE(nd_2nd, "old name");
+ return;
case NODE_VALIAS:
- ANN("global variable alias statement");
- ANN("format: alias [nd_alias](gvar) [nd_orig](gvar)");
- ANN("example: alias $y $x");
- F_ID(nd_alias, "new name");
- F_ID(nd_orig, "old name");
- return;
+ ANN("global variable alias statement");
+ ANN("format: alias [nd_alias](gvar) [nd_orig](gvar)");
+ ANN("example: alias $y $x");
+ F_ID(nd_alias, "new name");
+ F_ID(nd_orig, "old name");
+ return;
case NODE_UNDEF:
- ANN("method undef statement");
- ANN("format: undef [nd_undef]");
- ANN("example: undef foo");
- LAST_NODE;
- F_NODE(nd_undef, "old name");
- return;
+ ANN("method undef statement");
+ ANN("format: undef [nd_undef]");
+ ANN("example: undef foo");
+ LAST_NODE;
+ F_NODE(nd_undef, "old name");
+ return;
case NODE_CLASS:
- ANN("class definition");
- ANN("format: class [nd_cpath] < [nd_super]; [nd_body]; end");
- ANN("example: class C2 < C; ..; end");
- F_NODE(nd_cpath, "class path");
- F_NODE(nd_super, "superclass");
- LAST_NODE;
- F_NODE(nd_body, "class definition");
- return;
+ ANN("class definition");
+ ANN("format: class [nd_cpath] < [nd_super]; [nd_body]; end");
+ ANN("example: class C2 < C; ..; end");
+ F_NODE(nd_cpath, "class path");
+ F_NODE(nd_super, "superclass");
+ LAST_NODE;
+ F_NODE(nd_body, "class definition");
+ return;
case NODE_MODULE:
- ANN("module definition");
- ANN("format: module [nd_cpath]; [nd_body]; end");
- ANN("example: module M; ..; end");
- F_NODE(nd_cpath, "module path");
- LAST_NODE;
- F_NODE(nd_body, "module definition");
- return;
+ ANN("module definition");
+ ANN("format: module [nd_cpath]; [nd_body]; end");
+ ANN("example: module M; ..; end");
+ F_NODE(nd_cpath, "module path");
+ LAST_NODE;
+ F_NODE(nd_body, "module definition");
+ return;
case NODE_SCLASS:
- ANN("singleton class definition");
- ANN("format: class << [nd_recv]; [nd_body]; end");
- ANN("example: class << obj; ..; end");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_body, "singleton class definition");
- return;
+ ANN("singleton class definition");
+ ANN("format: class << [nd_recv]; [nd_body]; end");
+ ANN("example: class << obj; ..; end");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_body, "singleton class definition");
+ return;
case NODE_COLON2:
- ANN("scoped constant reference");
- ANN("format: [nd_head]::[nd_mid]");
- ANN("example: M::C");
- F_ID(nd_mid, "constant name");
- LAST_NODE;
- F_NODE(nd_head, "receiver");
- return;
+ ANN("scoped constant reference");
+ ANN("format: [nd_head]::[nd_mid]");
+ ANN("example: M::C");
+ F_ID(nd_mid, "constant name");
+ LAST_NODE;
+ F_NODE(nd_head, "receiver");
+ return;
case NODE_COLON3:
- ANN("top-level constant reference");
- ANN("format: ::[nd_mid]");
- ANN("example: ::Object");
- F_ID(nd_mid, "constant name");
- return;
+ ANN("top-level constant reference");
+ ANN("format: ::[nd_mid]");
+ ANN("example: ::Object");
+ F_ID(nd_mid, "constant name");
+ return;
case NODE_DOT2:
- ANN("range constructor (incl.)");
- ANN("format: [nd_beg]..[nd_end]");
- ANN("example: 1..5");
- goto dot;
+ ANN("range constructor (incl.)");
+ ANN("format: [nd_beg]..[nd_end]");
+ ANN("example: 1..5");
+ goto dot;
case NODE_DOT3:
- ANN("range constructor (excl.)");
- ANN("format: [nd_beg]...[nd_end]");
- ANN("example: 1...5");
- goto dot;
+ ANN("range constructor (excl.)");
+ ANN("format: [nd_beg]...[nd_end]");
+ ANN("example: 1...5");
+ goto dot;
case NODE_FLIP2:
- ANN("flip-flop condition (incl.)");
- ANN("format: [nd_beg]..[nd_end]");
- ANN("example: if (x==1)..(x==5); foo; end");
- goto dot;
+ ANN("flip-flop condition (incl.)");
+ ANN("format: [nd_beg]..[nd_end]");
+ ANN("example: if (x==1)..(x==5); foo; end");
+ goto dot;
case NODE_FLIP3:
- ANN("flip-flop condition (excl.)");
- ANN("format: [nd_beg]...[nd_end]");
- ANN("example: if (x==1)...(x==5); foo; end");
+ ANN("flip-flop condition (excl.)");
+ ANN("format: [nd_beg]...[nd_end]");
+ ANN("example: if (x==1)...(x==5); foo; end");
dot:
- F_NODE(nd_beg, "begin");
- LAST_NODE;
- F_NODE(nd_end, "end");
- return;
+ F_NODE(nd_beg, "begin");
+ LAST_NODE;
+ F_NODE(nd_end, "end");
+ return;
case NODE_SELF:
- ANN("self");
- ANN("format: self");
- ANN("example: self");
- return;
+ ANN("self");
+ ANN("format: self");
+ ANN("example: self");
+ return;
case NODE_NIL:
- ANN("nil");
- ANN("format: nil");
- ANN("example: nil");
- return;
+ ANN("nil");
+ ANN("format: nil");
+ ANN("example: nil");
+ return;
case NODE_TRUE:
- ANN("true");
- ANN("format: true");
- ANN("example: true");
- return;
+ ANN("true");
+ ANN("format: true");
+ ANN("example: true");
+ return;
case NODE_FALSE:
- ANN("false");
- ANN("format: false");
- ANN("example: false");
- return;
+ ANN("false");
+ ANN("format: false");
+ ANN("example: false");
+ return;
case NODE_ERRINFO:
- ANN("virtual reference to $!");
- ANN("format: rescue => id");
- ANN("example: rescue => id");
- return;
+ ANN("virtual reference to $!");
+ ANN("format: rescue => id");
+ ANN("example: rescue => id");
+ return;
case NODE_DEFINED:
- ANN("defined? expression");
- ANN("format: defined?([nd_head])");
- ANN("example: defined?(foo)");
- F_NODE(nd_head, "expr");
- return;
+ ANN("defined? expression");
+ ANN("format: defined?([nd_head])");
+ ANN("example: defined?(foo)");
+ F_NODE(nd_head, "expr");
+ return;
case NODE_POSTEXE:
- ANN("post-execution");
- ANN("format: END { [nd_body] }");
- ANN("example: END { foo }");
- LAST_NODE;
- F_NODE(nd_body, "END clause");
- return;
+ ANN("post-execution");
+ ANN("format: END { [nd_body] }");
+ ANN("example: END { foo }");
+ LAST_NODE;
+ F_NODE(nd_body, "END clause");
+ return;
case NODE_ATTRASGN:
- ANN("attr assignment");
- ANN("format: [nd_recv].[nd_mid] = [nd_args]");
- ANN("example: struct.field = foo");
- F_NODE(nd_recv, "receiver");
- F_ID(nd_mid, "method name");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
+ ANN("attr assignment");
+ ANN("format: [nd_recv].[nd_mid] = [nd_args]");
+ ANN("example: struct.field = foo");
+ F_NODE(nd_recv, "receiver");
+ F_ID(nd_mid, "method name");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
case NODE_LAMBDA:
- ANN("lambda expression");
- ANN("format: -> [nd_body]");
- ANN("example: -> { foo }");
- LAST_NODE;
- F_NODE(nd_body, "lambda clause");
- return;
+ ANN("lambda expression");
+ ANN("format: -> [nd_body]");
+ ANN("example: -> { foo }");
+ LAST_NODE;
+ F_NODE(nd_body, "lambda clause");
+ return;
case NODE_OPT_ARG:
- ANN("optional arguments");
- ANN("format: def method_name([nd_body=some], [nd_next..])");
- ANN("example: def foo(a, b=1, c); end");
- F_NODE(nd_body, "body");
- LAST_NODE;
- F_NODE(nd_next, "next");
- return;
+ ANN("optional arguments");
+ ANN("format: def method_name([nd_body=some], [nd_next..])");
+ ANN("example: def foo(a, b=1, c); end");
+ F_NODE(nd_body, "body");
+ LAST_NODE;
+ F_NODE(nd_next, "next");
+ return;
case NODE_KW_ARG:
- ANN("keyword arguments");
- ANN("format: def method_name([nd_body=some], [nd_next..])");
- ANN("example: def foo(a:1, b:2); end");
- F_NODE(nd_body, "body");
- LAST_NODE;
- F_NODE(nd_next, "next");
- return;
+ ANN("keyword arguments");
+ ANN("format: def method_name([nd_body=some], [nd_next..])");
+ ANN("example: def foo(a:1, b:2); end");
+ F_NODE(nd_body, "body");
+ LAST_NODE;
+ F_NODE(nd_next, "next");
+ return;
case NODE_POSTARG:
- ANN("post arguments");
- ANN("format: *[nd_1st], [nd_2nd..] = ..");
- ANN("example: a, *rest, z = foo");
- if (NODE_NAMED_REST_P(node->nd_1st)) {
- F_NODE(nd_1st, "rest argument");
- }
- else {
- F_MSG(nd_1st, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- LAST_NODE;
- F_NODE(nd_2nd, "post arguments");
- return;
+ ANN("post arguments");
+ ANN("format: *[nd_1st], [nd_2nd..] = ..");
+ ANN("example: a, *rest, z = foo");
+ if (NODE_NAMED_REST_P(node->nd_1st)) {
+ F_NODE(nd_1st, "rest argument");
+ }
+ else {
+ F_MSG(nd_1st, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ LAST_NODE;
+ F_NODE(nd_2nd, "post arguments");
+ return;
case NODE_ARGS:
- ANN("method parameters");
- ANN("format: def method_name(.., [nd_opt=some], *[nd_rest], [nd_pid], .., &[nd_body])");
- ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, &blk); end");
- F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
- F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
- F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments");
- F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
- F_ID(nd_ainfo->first_post_arg, "first post argument");
+ ANN("method parameters");
+ ANN("format: def method_name(.., [nd_ainfo->nd_optargs], *[nd_ainfo->rest_arg], [nd_ainfo->first_post_arg], .., [nd_ainfo->kw_args], **[nd_ainfo->kw_rest_arg], &[nd_ainfo->block_arg])");
+ ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, kw: 1, **kwrest, &blk); end");
+ F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
+ F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
+ F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments");
+ F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
+ F_ID(nd_ainfo->first_post_arg, "first post argument");
F_CUSTOM1(nd_ainfo->rest_arg, "rest argument") {
if (node->nd_ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA) {
A("1 (excessed comma)");
@@ -1034,29 +1025,29 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
A_ID(node->nd_ainfo->rest_arg);
}
}
- F_ID(nd_ainfo->block_arg, "block argument");
- F_NODE(nd_ainfo->opt_args, "optional arguments");
- F_NODE(nd_ainfo->kw_args, "keyword arguments");
- LAST_NODE;
- F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
- return;
+ F_ID(nd_ainfo->block_arg, "block argument");
+ F_NODE(nd_ainfo->opt_args, "optional arguments");
+ F_NODE(nd_ainfo->kw_args, "keyword arguments");
+ LAST_NODE;
+ F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
+ return;
case NODE_SCOPE:
- ANN("new scope");
- ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body");
- F_CUSTOM1(nd_tbl, "local table") {
- ID *tbl = node->nd_tbl;
- int i;
- int size = tbl ? (int)*tbl++ : 0;
- if (size == 0) A("(empty)");
- for (i = 0; i < size; i++) {
- A_ID(tbl[i]); if (i < size - 1) A(",");
- }
- }
- F_NODE(nd_args, "arguments");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
+ ANN("new scope");
+ ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body");
+ F_CUSTOM1(nd_tbl, "local table") {
+ rb_ast_id_table_t *tbl = node->nd_tbl;
+ int i;
+ int size = tbl ? tbl->size : 0;
+ if (size == 0) A("(empty)");
+ for (i = 0; i < size; i++) {
+ A_ID(tbl->ids[i]); if (i < size - 1) A(",");
+ }
+ }
+ F_NODE(nd_args, "arguments");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
case NODE_ARYPTN:
ANN("array pattern");
@@ -1107,10 +1098,13 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
F_NODE(nd_pkwrestarg, "keyword rest argument");
}
return;
+ case NODE_ERROR:
+ ANN("Broken input recovered by Error Tolerant mode");
+ return;
case NODE_ARGS_AUX:
case NODE_LAST:
- break;
+ break;
}
rb_bug("dump_node: unknown node: %s", ruby_node_name(nd_type(node)));
@@ -1120,10 +1114,10 @@ VALUE
rb_parser_dump_tree(const NODE *node, int comment)
{
VALUE buf = rb_str_new_cstr(
- "###########################################################\n"
- "## Do NOT use this node dump for any purpose other than ##\n"
- "## debug and research. Compatibility is not guaranteed. ##\n"
- "###########################################################\n\n"
+ "###########################################################\n"
+ "## Do NOT use this node dump for any purpose other than ##\n"
+ "## debug and research. Compatibility is not guaranteed. ##\n"
+ "###########################################################\n\n"
);
dump_node(buf, rb_str_new_cstr("# "), comment, node);
return buf;
@@ -1147,6 +1141,7 @@ rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
n->nd_loc.beg_pos.column = 0;
n->nd_loc.end_pos.lineno = 0;
n->nd_loc.end_pos.column = 0;
+ n->node_id = -1;
}
typedef struct node_buffer_elem_struct {
@@ -1164,8 +1159,14 @@ typedef struct {
struct node_buffer_struct {
node_buffer_list_t unmarkable;
node_buffer_list_t markable;
- ID *local_tables;
+ struct rb_ast_local_table_link *local_tables;
VALUE mark_hash;
+ // - id (sequence number)
+ // - token_type
+ // - text of token
+ // - location info
+ // Array, whose entry is array
+ VALUE tokens;
};
static void
@@ -1192,6 +1193,7 @@ rb_node_buffer_new(void)
init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size));
nb->local_tables = 0;
nb->mark_hash = Qnil;
+ nb->tokens = Qnil;
return nb;
}
@@ -1201,21 +1203,28 @@ node_buffer_list_free(node_buffer_list_t * nb)
node_buffer_elem_t *nbe = nb->head;
while (nbe != nb->last) {
- void *buf = nbe;
- nbe = nbe->next;
- xfree(buf);
+ void *buf = nbe;
+ nbe = nbe->next;
+ xfree(buf);
}
}
+struct rb_ast_local_table_link {
+ struct rb_ast_local_table_link *next;
+ // struct rb_ast_id_table {
+ int size;
+ ID ids[FLEX_ARY_LEN];
+ // }
+};
+
static void
rb_node_buffer_free(node_buffer_t *nb)
{
node_buffer_list_free(&nb->unmarkable);
node_buffer_list_free(&nb->markable);
- ID * local_table = nb->local_tables;
+ struct rb_ast_local_table_link *local_table = nb->local_tables;
while (local_table) {
- unsigned int size = (unsigned int)*local_table;
- ID * next_table = (ID *)local_table[size + 1];
+ struct rb_ast_local_table_link *next_table = local_table->next;
xfree(local_table);
local_table = next_table;
}
@@ -1226,14 +1235,14 @@ static NODE *
ast_newnode_in_bucket(node_buffer_list_t *nb)
{
if (nb->idx >= nb->len) {
- long n = nb->len * 2;
- node_buffer_elem_t *nbe;
+ long n = nb->len * 2;
+ node_buffer_elem_t *nbe;
nbe = rb_xmalloc_mul_add(n, sizeof(NODE), offsetof(node_buffer_elem_t, buf));
nbe->len = n;
- nb->idx = 0;
- nb->len = n;
- nbe->next = nb->head;
- nb->head = nbe;
+ nb->idx = 0;
+ nb->len = n;
+ nbe->next = nb->head;
+ nb->head = nbe;
}
return &nb->head->buf[nb->idx++];
}
@@ -1279,12 +1288,28 @@ rb_ast_node_type_change(NODE *n, enum node_type type)
}
}
-void
-rb_ast_add_local_table(rb_ast_t *ast, ID *buf)
+rb_ast_id_table_t *
+rb_ast_new_local_table(rb_ast_t *ast, int size)
+{
+ size_t alloc_size = sizeof(struct rb_ast_local_table_link) + size * sizeof(ID);
+ struct rb_ast_local_table_link *link = ruby_xmalloc(alloc_size);
+ link->next = ast->node_buffer->local_tables;
+ ast->node_buffer->local_tables = link;
+ link->size = size;
+
+ return (rb_ast_id_table_t *) &link->size;
+}
+
+rb_ast_id_table_t *
+rb_ast_resize_latest_local_table(rb_ast_t *ast, int size)
{
- unsigned int size = (unsigned int)*buf;
- buf[size + 1] = (ID)ast->node_buffer->local_tables;
- ast->node_buffer->local_tables = buf;
+ struct rb_ast_local_table_link *link = ast->node_buffer->local_tables;
+ size_t alloc_size = sizeof(struct rb_ast_local_table_link) + size * sizeof(ID);
+ link = ruby_xrealloc(link, alloc_size);
+ ast->node_buffer->local_tables = link;
+ link->size = size;
+
+ return (rb_ast_id_table_t *) &link->size;
}
void
@@ -1400,7 +1425,10 @@ rb_ast_update_references(rb_ast_t *ast)
void
rb_ast_mark(rb_ast_t *ast)
{
- if (ast->node_buffer) rb_gc_mark(ast->node_buffer->mark_hash);
+ if (ast->node_buffer) {
+ rb_gc_mark(ast->node_buffer->mark_hash);
+ rb_gc_mark(ast->node_buffer->tokens);
+ }
if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option);
if (ast->node_buffer) {
node_buffer_t *nb = ast->node_buffer;
@@ -1414,8 +1442,8 @@ void
rb_ast_free(rb_ast_t *ast)
{
if (ast->node_buffer) {
- rb_node_buffer_free(ast->node_buffer);
- ast->node_buffer = 0;
+ rb_node_buffer_free(ast->node_buffer);
+ ast->node_buffer = 0;
}
}
@@ -1459,3 +1487,15 @@ rb_ast_add_mark_object(rb_ast_t *ast, VALUE obj)
}
rb_hash_aset(ast->node_buffer->mark_hash, obj, Qtrue);
}
+
+VALUE
+rb_ast_tokens(rb_ast_t *ast)
+{
+ return ast->node_buffer->tokens;
+}
+
+void
+rb_ast_set_tokens(rb_ast_t *ast, VALUE tokens)
+{
+ RB_OBJ_WRITE(ast, &ast->node_buffer->tokens, tokens);
+}
diff --git a/node.h b/node.h
index 8b09e81a8c..befb1328fb 100644
--- a/node.h
+++ b/node.h
@@ -11,6 +11,8 @@
**********************************************************************/
+#include "internal/compilers.h"
+
#if defined(__cplusplus)
extern "C" {
#if 0
@@ -46,7 +48,6 @@ enum node_type {
NODE_MASGN,
NODE_LASGN,
NODE_DASGN,
- NODE_DASGN_CURR,
NODE_GASGN,
NODE_IASGN,
NODE_CDECL,
@@ -124,6 +125,7 @@ enum node_type {
NODE_ARYPTN,
NODE_HSHPTN,
NODE_FNDPTN,
+ NODE_ERROR,
NODE_LAST
};
@@ -146,28 +148,33 @@ code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2)
return loc;
}
+typedef struct rb_ast_id_table {
+ int size;
+ ID ids[FLEX_ARY_LEN];
+} rb_ast_id_table_t;
+
typedef struct RNode {
VALUE flags;
union {
- struct RNode *node;
- ID id;
- VALUE value;
- ID *tbl;
+ struct RNode *node;
+ ID id;
+ VALUE value;
+ rb_ast_id_table_t *tbl;
} u1;
union {
- struct RNode *node;
- ID id;
- long argc;
- VALUE value;
+ struct RNode *node;
+ ID id;
+ long argc;
+ VALUE value;
} u2;
union {
- struct RNode *node;
- ID id;
- long state;
- struct rb_args_info *args;
- struct rb_ary_pattern_info *apinfo;
- struct rb_fnd_pattern_info *fpinfo;
- VALUE value;
+ struct RNode *node;
+ ID id;
+ long state;
+ struct rb_args_info *args;
+ struct rb_ary_pattern_info *apinfo;
+ struct rb_fnd_pattern_info *fpinfo;
+ VALUE value;
} u3;
rb_code_location_t nd_loc;
int node_id;
@@ -231,11 +238,6 @@ typedef struct RNode {
#define nd_entry u3.id
#define nd_vid u1.id
-#define nd_cflag u2.id
-#define nd_cval u3.value
-
-#define nd_oid u1.id
-#define nd_tbl u1.tbl
#define nd_var u1.node
#define nd_iter u3.node
@@ -245,11 +247,6 @@ typedef struct RNode {
#define nd_lit u1.value
-#define nd_rest u1.id
-#define nd_opt u1.node
-#define nd_pid u1.id
-#define nd_plen u2.argc
-
#define nd_recv u1.node
#define nd_mid u2.id
#define nd_args u3.node
@@ -263,12 +260,9 @@ typedef struct RNode {
#define nd_beg u1.node
#define nd_end u2.node
#define nd_state u3.state
-#define nd_rval u2.value
#define nd_nth u2.argc
-#define nd_tag u1.id
-
#define nd_alias u1.id
#define nd_orig u2.id
#define nd_undef u2.node
@@ -283,6 +277,19 @@ typedef struct RNode {
#define nd_fpinfo u3.fpinfo
+// for NODE_SCOPE
+#define nd_tbl u1.tbl
+
+// for NODE_ARGS_AUX
+#define nd_pid u1.id
+#define nd_plen u2.argc
+#define nd_cflag u2.id
+
+// for ripper
+#define nd_cval u3.value
+#define nd_rval u2.value
+#define nd_tag u1.id
+
#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)
@@ -320,7 +327,6 @@ typedef struct RNode {
#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)
#define NEW_IASGN(v,val,loc) NEW_NODE(NODE_IASGN,v,val,0,loc)
#define NEW_CDECL(v,val,path,loc) NEW_NODE(NODE_CDECL,v,val,path,loc)
#define NEW_CVASGN(v,val,loc) NEW_NODE(NODE_CVASGN,v,val,0,loc)
@@ -378,9 +384,9 @@ typedef struct RNode {
#define NEW_FALSE(loc) NEW_NODE(NODE_FALSE,0,0,0,loc)
#define NEW_ERRINFO(loc) NEW_NODE(NODE_ERRINFO,0,0,0,loc)
#define NEW_DEFINED(e,loc) NEW_NODE(NODE_DEFINED,e,0,0,loc)
-#define NEW_PREEXE(b,loc) NEW_SCOPE(b,loc)
#define NEW_POSTEXE(b,loc) NEW_NODE(NODE_POSTEXE,0,b,0,loc)
#define NEW_ATTRASGN(r,m,a,loc) NEW_NODE(NODE_ATTRASGN,r,m,a,loc)
+#define NEW_ERROR(loc) NEW_NODE(NODE_ERROR,0,0,0,loc)
#define NODE_SPECIAL_REQUIRED_KEYWORD ((NODE *)-1)
#define NODE_REQUIRED_KEYWORD_P(node) ((node)->nd_value == NODE_SPECIAL_REQUIRED_KEYWORD)
@@ -411,13 +417,16 @@ typedef struct rb_ast_struct {
rb_ast_t *rb_ast_new(void);
void rb_ast_mark(rb_ast_t*);
void rb_ast_update_references(rb_ast_t*);
-void rb_ast_add_local_table(rb_ast_t*, ID *buf);
void rb_ast_dispose(rb_ast_t*);
void rb_ast_free(rb_ast_t*);
size_t rb_ast_memsize(const rb_ast_t*);
void rb_ast_add_mark_object(rb_ast_t*, VALUE);
+void rb_ast_set_tokens(rb_ast_t*, VALUE);
+VALUE rb_ast_tokens(rb_ast_t *ast);
NODE *rb_ast_newnode(rb_ast_t*, enum node_type type);
void rb_ast_delete_node(rb_ast_t*, NODE *n);
+rb_ast_id_table_t *rb_ast_new_local_table(rb_ast_t*, int);
+rb_ast_id_table_t *rb_ast_resize_latest_local_table(rb_ast_t*, int);
VALUE rb_parser_new(void);
VALUE rb_parser_end_seen_p(VALUE);
@@ -454,6 +463,7 @@ struct rb_args_info {
NODE *opt_args;
unsigned int no_kwarg: 1;
unsigned int ruby2_keywords: 1;
+ unsigned int forwarding: 1;
VALUE imemo;
};
@@ -489,6 +499,11 @@ rb_node_set_type(NODE *n, enum node_type t)
return nd_init_type(n, t);
}
+static inline bool
+nd_type_p(const NODE *n, enum node_type t)
+{
+ return (enum node_type)nd_type(n) == t;
+}
#if defined(__cplusplus)
#if 0
{ /* satisfy cc-mode */
diff --git a/numeric.c b/numeric.c
index a1801f9654..6dd1ff6d2f 100644
--- a/numeric.c
+++ b/numeric.c
@@ -35,6 +35,7 @@
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/rational.h"
+#include "internal/string.h"
#include "internal/util.h"
#include "internal/variable.h"
#include "ruby/encoding.h"
@@ -94,12 +95,12 @@ round(double x)
double f;
if (x > 0.0) {
- f = floor(x);
- x = f + (x - f >= 0.5);
+ f = floor(x);
+ x = f + (x - f >= 0.5);
}
else if (x < 0.0) {
- f = ceil(x);
- x = f - (f - x >= 0.5);
+ f = ceil(x);
+ x = f - (f - x >= 0.5);
}
return x;
}
@@ -113,12 +114,12 @@ round_half_up(double x, double s)
f = round(xs);
if (s == 1.0) return f;
if (x > 0) {
- if ((double)((f + 0.5) / s) <= x) f += 1;
- x = f;
+ if ((double)((f + 0.5) / s) <= x) f += 1;
+ x = f;
}
else {
- if ((double)((f - 0.5) / s) >= x) f -= 1;
- x = f;
+ if ((double)((f - 0.5) / s) >= x) f -= 1;
+ x = f;
}
return x;
}
@@ -130,12 +131,12 @@ round_half_down(double x, double s)
f = round(xs);
if (x > 0) {
- if ((double)((f - 0.5) / s) >= x) f -= 1;
- x = f;
+ if ((double)((f - 0.5) / s) >= x) f -= 1;
+ x = f;
}
else {
- if ((double)((f + 0.5) / s) <= x) f += 1;
- x = f;
+ if ((double)((f + 0.5) / s) <= x) f += 1;
+ x = f;
}
return x;
}
@@ -146,26 +147,26 @@ round_half_even(double x, double s)
double f, d, xs = x * s;
if (x > 0.0) {
- f = floor(xs);
- d = xs - f;
- if (d > 0.5)
- d = 1.0;
- else if (d == 0.5 || ((double)((f + 0.5) / s) <= x))
- d = fmod(f, 2.0);
- else
- d = 0.0;
- x = f + d;
+ f = floor(xs);
+ d = xs - f;
+ if (d > 0.5)
+ d = 1.0;
+ else if (d == 0.5 || ((double)((f + 0.5) / s) <= x))
+ d = fmod(f, 2.0);
+ else
+ d = 0.0;
+ x = f + d;
}
else if (x < 0.0) {
- f = ceil(xs);
- d = f - xs;
- if (d > 0.5)
- d = 1.0;
- else if (d == 0.5 || ((double)((f - 0.5) / s) >= x))
- d = fmod(-f, 2.0);
- else
- d = 0.0;
- x = f - d;
+ f = ceil(xs);
+ d = f - xs;
+ if (d > 0.5)
+ d = 1.0;
+ else if (d == 0.5 || ((double)((f - 0.5) / s) >= x))
+ d = fmod(-f, 2.0);
+ else
+ d = 0.0;
+ x = f - d;
}
return x;
}
@@ -210,36 +211,36 @@ rb_num_get_rounding_option(VALUE opts)
const char *s;
if (!NIL_P(opts)) {
- if (!round_kwds[0]) {
- round_kwds[0] = rb_intern_const("half");
- }
- if (!rb_get_kwargs(opts, round_kwds, 0, 1, &rounding)) goto noopt;
- if (SYMBOL_P(rounding)) {
- str = rb_sym2str(rounding);
- }
- else if (NIL_P(rounding)) {
- goto noopt;
- }
- else if (!RB_TYPE_P(str = rounding, T_STRING)) {
- str = rb_check_string_type(rounding);
- if (NIL_P(str)) goto invalid;
- }
+ if (!round_kwds[0]) {
+ round_kwds[0] = rb_intern_const("half");
+ }
+ if (!rb_get_kwargs(opts, round_kwds, 0, 1, &rounding)) goto noopt;
+ if (SYMBOL_P(rounding)) {
+ str = rb_sym2str(rounding);
+ }
+ else if (NIL_P(rounding)) {
+ goto noopt;
+ }
+ else if (!RB_TYPE_P(str = rounding, T_STRING)) {
+ 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:
- if (rb_memcicmp(s, "up", 2) == 0)
- return RUBY_NUM_ROUND_HALF_UP;
- break;
- case 4:
- if (rb_memcicmp(s, "even", 4) == 0)
- return RUBY_NUM_ROUND_HALF_EVEN;
- if (strncasecmp(s, "down", 4) == 0)
- return RUBY_NUM_ROUND_HALF_DOWN;
- break;
- }
+ s = RSTRING_PTR(str);
+ switch (RSTRING_LEN(str)) {
+ case 2:
+ if (rb_memcicmp(s, "up", 2) == 0)
+ return RUBY_NUM_ROUND_HALF_UP;
+ break;
+ case 4:
+ if (rb_memcicmp(s, "even", 4) == 0)
+ return RUBY_NUM_ROUND_HALF_EVEN;
+ if (strncasecmp(s, "down", 4) == 0)
+ return RUBY_NUM_ROUND_HALF_DOWN;
+ break;
+ }
invalid:
- rb_raise(rb_eArgError, "invalid rounding mode: % "PRIsVALUE, rounding);
+ rb_raise(rb_eArgError, "invalid rounding mode: % "PRIsVALUE, rounding);
}
noopt:
return RUBY_NUM_ROUND_DEFAULT;
@@ -253,25 +254,25 @@ rb_num_to_uint(VALUE val, unsigned int *ret)
#define NUMERR_NEGATIVE 2
#define NUMERR_TOOLARGE 3
if (FIXNUM_P(val)) {
- long v = FIX2LONG(val);
+ long v = FIX2LONG(val);
#if SIZEOF_INT < SIZEOF_LONG
- if (v > (long)UINT_MAX) return NUMERR_TOOLARGE;
+ if (v > (long)UINT_MAX) return NUMERR_TOOLARGE;
#endif
- if (v < 0) return NUMERR_NEGATIVE;
- *ret = (unsigned int)v;
- return 0;
+ if (v < 0) return NUMERR_NEGATIVE;
+ *ret = (unsigned int)v;
+ return 0;
}
- if (RB_TYPE_P(val, T_BIGNUM)) {
- if (BIGNUM_NEGATIVE_P(val)) return NUMERR_NEGATIVE;
+ if (RB_BIGNUM_TYPE_P(val)) {
+ if (BIGNUM_NEGATIVE_P(val)) return NUMERR_NEGATIVE;
#if SIZEOF_INT < SIZEOF_LONG
- /* long is 64bit */
- return NUMERR_TOOLARGE;
+ /* long is 64bit */
+ return NUMERR_TOOLARGE;
#else
- /* long is 32bit */
- if (rb_absint_size(val, NULL) > sizeof(int)) return NUMERR_TOOLARGE;
- *ret = (unsigned int)rb_big2ulong((VALUE)val);
- return 0;
+ /* long is 32bit */
+ if (rb_absint_size(val, NULL) > sizeof(int)) return NUMERR_TOOLARGE;
+ *ret = (unsigned int)rb_big2ulong((VALUE)val);
+ return 0;
#endif
}
return NUMERR_TYPE;
@@ -283,10 +284,10 @@ static inline int
int_pos_p(VALUE num)
{
if (FIXNUM_P(num)) {
- return FIXNUM_POSITIVE_P(num);
+ return FIXNUM_POSITIVE_P(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- return BIGNUM_POSITIVE_P(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ return BIGNUM_POSITIVE_P(num);
}
rb_raise(rb_eTypeError, "not an Integer");
}
@@ -295,10 +296,10 @@ static inline int
int_neg_p(VALUE num)
{
if (FIXNUM_P(num)) {
- return FIXNUM_NEGATIVE_P(num);
+ return FIXNUM_NEGATIVE_P(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- return BIGNUM_NEGATIVE_P(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ return BIGNUM_NEGATIVE_P(num);
}
rb_raise(rb_eTypeError, "not an Integer");
}
@@ -326,19 +327,19 @@ num_funcall_op_0(VALUE x, VALUE arg, int recursive)
{
ID func = (ID)arg;
if (recursive) {
- const char *name = rb_id2name(func);
- if (ISALNUM(name[0])) {
- rb_name_error(func, "%"PRIsVALUE".%"PRIsVALUE,
- x, ID2SYM(func));
- }
- else if (name[0] && name[1] == '@' && !name[2]) {
- rb_name_error(func, "%c%"PRIsVALUE,
- name[0], x);
- }
- else {
- rb_name_error(func, "%"PRIsVALUE"%"PRIsVALUE,
- ID2SYM(func), x);
- }
+ const char *name = rb_id2name(func);
+ if (ISALNUM(name[0])) {
+ rb_name_error(func, "%"PRIsVALUE".%"PRIsVALUE,
+ x, ID2SYM(func));
+ }
+ else if (name[0] && name[1] == '@' && !name[2]) {
+ rb_name_error(func, "%c%"PRIsVALUE,
+ name[0], x);
+ }
+ else {
+ rb_name_error(func, "%"PRIsVALUE"%"PRIsVALUE,
+ ID2SYM(func), x);
+ }
}
return rb_funcallv(x, func, 0, 0);
}
@@ -356,12 +357,12 @@ num_funcall_op_1_recursion(VALUE x, ID func, VALUE y)
{
const char *name = rb_id2name(func);
if (ISALNUM(name[0])) {
- rb_name_error(func, "%"PRIsVALUE".%"PRIsVALUE"(%"PRIsVALUE")",
- x, ID2SYM(func), y);
+ rb_name_error(func, "%"PRIsVALUE".%"PRIsVALUE"(%"PRIsVALUE")",
+ x, ID2SYM(func), y);
}
else {
- rb_name_error(func, "%"PRIsVALUE"%"PRIsVALUE"%"PRIsVALUE,
- x, ID2SYM(func), y);
+ rb_name_error(func, "%"PRIsVALUE"%"PRIsVALUE"%"PRIsVALUE,
+ x, ID2SYM(func), y);
}
}
@@ -371,7 +372,7 @@ num_funcall_op_1(VALUE y, VALUE arg, int recursive)
ID func = (ID)((VALUE *)arg)[0];
VALUE x = ((VALUE *)arg)[1];
if (recursive) {
- num_funcall_op_1_recursion(x, func, y);
+ num_funcall_op_1_recursion(x, func, y);
}
return rb_funcall(x, func, 1, y);
}
@@ -387,26 +388,44 @@ num_funcall1(VALUE x, ID func, VALUE y)
/*
* call-seq:
- * num.coerce(numeric) -> array
+ * coerce(other) -> array
+ *
+ * Returns a 2-element array containing two numeric elements,
+ * formed from the two operands +self+ and +other+,
+ * of a common compatible type.
+ *
+ * Of the Core and Standard Library classes,
+ * Integer, Rational, and Complex use this implementation.
+ *
+ * Examples:
+ *
+ * i = 2 # => 2
+ * i.coerce(3) # => [3, 2]
+ * i.coerce(3.0) # => [3.0, 2.0]
+ * i.coerce(Rational(1, 2)) # => [0.5, 2.0]
+ * i.coerce(Complex(3, 4)) # Raises RangeError.
*
- * If +numeric+ is the same type as +num+, returns an array
- * <code>[numeric, num]</code>. Otherwise, returns an array with both
- * +numeric+ and +num+ represented as Float objects.
+ * r = Rational(5, 2) # => (5/2)
+ * r.coerce(2) # => [(2/1), (5/2)]
+ * r.coerce(2.0) # => [2.0, 2.5]
+ * r.coerce(Rational(2, 3)) # => [(2/3), (5/2)]
+ * r.coerce(Complex(3, 4)) # => [(3+4i), ((5/2)+0i)]
*
- * This coercion mechanism is used by Ruby to handle mixed-type numeric
- * operations: it is intended to find a compatible common type between the two
- * operands of the operator.
+ * c = Complex(2, 3) # => (2+3i)
+ * c.coerce(2) # => [(2+0i), (2+3i)]
+ * c.coerce(2.0) # => [(2.0+0i), (2+3i)]
+ * c.coerce(Rational(1, 2)) # => [((1/2)+0i), (2+3i)]
+ * c.coerce(Complex(3, 4)) # => [(3+4i), (2+3i)]
+ *
+ * Raises an exception if any type conversion fails.
*
- * 1.coerce(2.5) #=> [2.5, 1.0]
- * 1.2.coerce(3) #=> [3.0, 1.2]
- * 1.coerce(2) #=> [2, 1]
*/
static VALUE
num_coerce(VALUE x, VALUE y)
{
if (CLASS_OF(x) == CLASS_OF(y))
- return rb_assoc_new(y, x);
+ return rb_assoc_new(y, x);
x = rb_Float(x);
y = rb_Float(y);
return rb_assoc_new(y, x);
@@ -417,30 +436,30 @@ static void
coerce_failed(VALUE x, VALUE y)
{
if (SPECIAL_CONST_P(y) || SYMBOL_P(y) || RB_FLOAT_TYPE_P(y)) {
- y = rb_inspect(y);
+ y = rb_inspect(y);
}
else {
- y = rb_obj_class(y);
+ y = rb_obj_class(y);
}
rb_raise(rb_eTypeError, "%"PRIsVALUE" can't be coerced into %"PRIsVALUE,
- y, rb_obj_class(x));
+ y, rb_obj_class(x));
}
static int
do_coerce(VALUE *x, VALUE *y, int err)
{
VALUE ary = rb_check_funcall(*y, id_coerce, 1, x);
- if (ary == Qundef) {
- if (err) {
- coerce_failed(*x, *y);
- }
- return FALSE;
+ if (UNDEF_P(ary)) {
+ if (err) {
+ coerce_failed(*x, *y);
+ }
+ return FALSE;
}
if (!err && NIL_P(ary)) {
- return FALSE;
+ return FALSE;
}
if (!RB_TYPE_P(ary, T_ARRAY) || RARRAY_LEN(ary) != 2) {
- rb_raise(rb_eTypeError, "coerce must return [x, y]");
+ rb_raise(rb_eTypeError, "coerce must return [x, y]");
}
*x = RARRAY_AREF(ary, 0);
@@ -459,7 +478,7 @@ VALUE
rb_num_coerce_cmp(VALUE x, VALUE y, ID func)
{
if (do_coerce(&x, &y, FALSE))
- return rb_funcall(x, func, 1, y);
+ return rb_funcall(x, func, 1, y);
return Qnil;
}
@@ -476,8 +495,8 @@ rb_num_coerce_relop(VALUE x, VALUE y, ID func)
VALUE x0 = x, y0 = y;
if (!do_coerce(&x, &y, FALSE)) {
- rb_cmperr(x0, y0);
- UNREACHABLE_RETURN(Qnil);
+ rb_cmperr(x0, y0);
+ UNREACHABLE_RETURN(Qnil);
}
return ensure_cmp(rb_funcall(x, func, 1, y), x0, y0);
}
@@ -499,9 +518,9 @@ num_sadded(VALUE x, VALUE name)
/* ruby_frame = ruby_frame->prev; */ /* pop frame for "singleton_method_added" */
rb_remove_method_id(rb_singleton_class(x), mid);
rb_raise(rb_eTypeError,
- "can't define singleton method \"%"PRIsVALUE"\" for %"PRIsVALUE,
- rb_id2str(mid),
- rb_obj_class(x));
+ "can't define singleton method \"%"PRIsVALUE"\" for %"PRIsVALUE,
+ rb_id2str(mid),
+ rb_obj_class(x));
UNREACHABLE_RETURN(Qnil);
}
@@ -509,9 +528,14 @@ num_sadded(VALUE x, VALUE name)
#if 0
/*
* call-seq:
- * num.clone(freeze: true) -> num
+ * clone(freeze: true) -> self
+ *
+ * Returns +self+.
+ *
+ * Raises an exception if the value for +freeze+ is neither +true+ nor +nil+.
+ *
+ * Related: Numeric#dup.
*
- * Returns the receiver. +freeze+ cannot be +false+.
*/
static VALUE
num_clone(int argc, VALUE *argv, VALUE x)
@@ -525,9 +549,12 @@ num_clone(int argc, VALUE *argv, VALUE x)
#if 0
/*
* call-seq:
- * num.dup -> num
+ * dup -> self
+ *
+ * Returns +self+.
+ *
+ * Related: Numeric#clone.
*
- * Returns the receiver.
*/
static VALUE
num_dup(VALUE x)
@@ -540,9 +567,10 @@ num_dup(VALUE x)
/*
* call-seq:
- * +num -> num
+ * +self -> self
+ *
+ * Returns +self+.
*
- * Unary Plus---Returns the receiver.
*/
static VALUE
@@ -553,13 +581,16 @@ num_uplus(VALUE num)
/*
* call-seq:
- * num.i -> Complex(0, num)
+ * i -> complex
+ *
+ * Returns <tt>Complex(0, self)</tt>:
*
- * Returns the corresponding imaginary number.
- * Not available for complex numbers.
+ * 2.i # => (0+2i)
+ * -2.i # => (0-2i)
+ * 2.0.i # => (0+2.0i)
+ * Rational(1, 2).i # => (0+(1/2)*i)
+ * Complex(3, 4).i # Raises NoMethodError.
*
- * -42.i #=> (0-42i)
- * 2.0.i #=> (0+2.0i)
*/
static VALUE
@@ -570,7 +601,7 @@ num_imaginary(VALUE num)
/*
* call-seq:
- * -num -> numeric
+ * -self -> numeric
*
* Unary Minus---Returns the receiver, negated.
*/
@@ -588,9 +619,15 @@ num_uminus(VALUE num)
/*
* call-seq:
- * num.fdiv(numeric) -> float
+ * fdiv(other) -> float
+ *
+ * Returns the quotient <tt>self/other</tt> as a float,
+ * using method +/+ in the derived class of +self+.
+ * (\Numeric itself does not define method +/+.)
+ *
+ * Of the Core and Standard Library classes,
+ * only BigDecimal uses this implementation.
*
- * Returns float division.
*/
static VALUE
@@ -601,14 +638,15 @@ num_fdiv(VALUE x, VALUE y)
/*
* call-seq:
- * num.div(numeric) -> integer
+ * div(other) -> integer
*
- * Uses +/+ to perform division, then converts the result to an integer.
- * Numeric does not define the +/+ operator; this is left to subclasses.
+ * Returns the quotient <tt>self/other</tt> as an integer (via +floor+),
+ * using method +/+ in the derived class of +self+.
+ * (\Numeric itself does not define method +/+.)
*
- * Equivalent to <code>num.divmod(numeric)[0]</code>.
+ * Of the Core and Standard Library classes,
+ * Only Float and Rational use this implementation.
*
- * See Numeric#divmod.
*/
static VALUE
@@ -620,13 +658,38 @@ num_div(VALUE x, VALUE y)
/*
* call-seq:
- * num.modulo(numeric) -> real
+ * self % other -> real_numeric
*
- * <code>x.modulo(y)</code> means <code>x-y*(x/y).floor</code>.
+ * Returns +self+ modulo +other+ as a real number.
*
- * Equivalent to <code>num.divmod(numeric)[1]</code>.
+ * Of the Core and Standard Library classes,
+ * only Rational uses this implementation.
+ *
+ * For \Rational +r+ and real number +n+, these expressions are equivalent:
+ *
+ * r % n
+ * r-n*(r/n).floor
+ * r.divmod(n)[1]
*
* See Numeric#divmod.
+ *
+ * Examples:
+ *
+ * r = Rational(1, 2) # => (1/2)
+ * r2 = Rational(2, 3) # => (2/3)
+ * r % r2 # => (1/2)
+ * r % 2 # => (1/2)
+ * r % 2.0 # => 0.5
+ *
+ * r = Rational(301,100) # => (301/100)
+ * r2 = Rational(7,5) # => (7/5)
+ * r % r2 # => (21/100)
+ * r % -r2 # => (-119/100)
+ * (-r) % r2 # => (119/100)
+ * (-r) %-r2 # => (-21/100)
+ *
+ * Numeric#modulo is an alias for Numeric#%.
+ *
*/
static VALUE
@@ -634,16 +697,38 @@ num_modulo(VALUE x, VALUE y)
{
VALUE q = num_funcall1(x, id_div, y);
return rb_funcall(x, '-', 1,
- rb_funcall(y, '*', 1, q));
+ rb_funcall(y, '*', 1, q));
}
/*
* call-seq:
- * num.remainder(numeric) -> real
+ * remainder(other) -> real_number
*
- * <code>x.remainder(y)</code> means <code>x-y*(x/y).truncate</code>.
+ * Returns the remainder after dividing +self+ by +other+.
+ *
+ * Of the Core and Standard Library classes,
+ * only Float and Rational use this implementation.
+ *
+ * Examples:
+ *
+ * 11.0.remainder(4) # => 3.0
+ * 11.0.remainder(-4) # => 3.0
+ * -11.0.remainder(4) # => -3.0
+ * -11.0.remainder(-4) # => -3.0
+ *
+ * 12.0.remainder(4) # => 0.0
+ * 12.0.remainder(-4) # => 0.0
+ * -12.0.remainder(4) # => -0.0
+ * -12.0.remainder(-4) # => -0.0
+ *
+ * 13.0.remainder(4.0) # => 1.0
+ * 13.0.remainder(Rational(4, 1)) # => 1.0
+ *
+ * Rational(13, 1).remainder(4) # => (1/1)
+ * Rational(13, 1).remainder(-4) # => (1/1)
+ * Rational(-13, 1).remainder(4) # => (-1/1)
+ * Rational(-13, 1).remainder(-4) # => (-1/1)
*
- * See Numeric#divmod.
*/
static VALUE
@@ -652,61 +737,46 @@ num_remainder(VALUE x, VALUE y)
VALUE z = num_funcall1(x, '%', y);
if ((!rb_equal(z, INT2FIX(0))) &&
- ((rb_num_negative_int_p(x) &&
- rb_num_positive_int_p(y)) ||
- (rb_num_positive_int_p(x) &&
- rb_num_negative_int_p(y)))) {
- if (RB_TYPE_P(y, T_FLOAT)) {
+ ((rb_num_negative_int_p(x) &&
+ rb_num_positive_int_p(y)) ||
+ (rb_num_positive_int_p(x) &&
+ rb_num_negative_int_p(y)))) {
+ if (RB_FLOAT_TYPE_P(y)) {
if (isinf(RFLOAT_VALUE(y))) {
return x;
}
}
- return rb_funcall(z, '-', 1, y);
+ return rb_funcall(z, '-', 1, y);
}
return z;
}
/*
* call-seq:
- * num.divmod(numeric) -> array
- *
- * Returns an array containing the quotient and modulus obtained by dividing
- * +num+ by +numeric+.
- *
- * If <code>q, r = x.divmod(y)</code>, then
- *
- * q = floor(x/y)
- * x = q*y + r
- *
- * The quotient is rounded toward negative infinity, as shown in the
- * following table:
- *
- * a | b | a.divmod(b) | a/b | a.modulo(b) | a.remainder(b)
- * ------+-----+---------------+---------+-------------+---------------
- * 13 | 4 | 3, 1 | 3 | 1 | 1
- * ------+-----+---------------+---------+-------------+---------------
- * 13 | -4 | -4, -3 | -4 | -3 | 1
- * ------+-----+---------------+---------+-------------+---------------
- * -13 | 4 | -4, 3 | -4 | 3 | -1
- * ------+-----+---------------+---------+-------------+---------------
- * -13 | -4 | 3, -1 | 3 | -1 | -1
- * ------+-----+---------------+---------+-------------+---------------
- * 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5
- * ------+-----+---------------+---------+-------------+---------------
- * 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5
- * ------+-----+---------------+---------+-------------+---------------
- * -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5
- * ------+-----+---------------+---------+-------------+---------------
- * -11.5 | -4 | 2, -3.5 | 2.875 | -3.5 | -3.5
- *
- *
- * Examples
- *
- * 11.divmod(3) #=> [3, 2]
- * 11.divmod(-3) #=> [-4, -1]
- * 11.divmod(3.5) #=> [3, 0.5]
- * (-11).divmod(3.5) #=> [-4, 3.0]
- * 11.5.divmod(3.5) #=> [3, 1.0]
+ * divmod(other) -> array
+ *
+ * Returns a 2-element array <tt>[q, r]</tt>, where
+ *
+ * q = (self/other).floor # Quotient
+ * r = self % other # Remainder
+ *
+ * Of the Core and Standard Library classes,
+ * only Rational uses this implementation.
+ *
+ * Examples:
+ *
+ * Rational(11, 1).divmod(4) # => [2, (3/1)]
+ * Rational(11, 1).divmod(-4) # => [-3, (-1/1)]
+ * Rational(-11, 1).divmod(4) # => [-3, (1/1)]
+ * Rational(-11, 1).divmod(-4) # => [2, (-3/1)]
+ *
+ * Rational(12, 1).divmod(4) # => [3, (0/1)]
+ * Rational(12, 1).divmod(-4) # => [-3, (0/1)]
+ * Rational(-12, 1).divmod(4) # => [-3, (0/1)]
+ * Rational(-12, 1).divmod(-4) # => [3, (0/1)]
+ *
+ * Rational(13, 1).divmod(4.0) # => [3, 1.0]
+ * Rational(13, 1).divmod(Rational(4, 11)) # => [35, (3/11)]
*/
static VALUE
@@ -717,32 +787,36 @@ num_divmod(VALUE x, VALUE y)
/*
* call-seq:
- * num.abs -> numeric
- * num.magnitude -> numeric
+ * abs -> numeric
*
- * Returns the absolute value of +num+.
+ * Returns the absolute value of +self+.
*
- * 12.abs #=> 12
- * (-34.56).abs #=> 34.56
- * -34.56.abs #=> 34.56
+ * 12.abs #=> 12
+ * (-34.56).abs #=> 34.56
+ * -34.56.abs #=> 34.56
*
* Numeric#magnitude is an alias for Numeric#abs.
+ *
*/
static VALUE
num_abs(VALUE num)
{
if (rb_num_negative_int_p(num)) {
- return num_funcall0(num, idUMinus);
+ return num_funcall0(num, idUMinus);
}
return num;
}
/*
* call-seq:
- * num.zero? -> true or false
+ * zero? -> true or false
+ *
+ * Returns +true+ if +zero+ has a zero value, +false+ otherwise.
+ *
+ * Of the Core and Standard Library classes,
+ * only Rational and Complex use this implementation.
*
- * Returns +true+ if +num+ has a zero value.
*/
static VALUE
@@ -751,61 +825,66 @@ num_zero_p(VALUE num)
return rb_equal(num, INT2FIX(0));
}
-static VALUE
+static bool
int_zero_p(VALUE num)
{
if (FIXNUM_P(num)) {
- if (FIXNUM_ZERO_P(num)) {
- return Qtrue;
- }
- }
- else {
- assert(RB_TYPE_P(num, T_BIGNUM));
- if (rb_bigzero_p(num)) {
- /* this should not happen usually */
- return Qtrue;
- }
+ return FIXNUM_ZERO_P(num);
}
- return Qfalse;
+ assert(RB_BIGNUM_TYPE_P(num));
+ return rb_bigzero_p(num);
}
VALUE
rb_int_zero_p(VALUE num)
{
- return int_zero_p(num);
+ return RBOOL(int_zero_p(num));
}
/*
* call-seq:
- * num.nonzero? -> self or nil
+ * nonzero? -> self or nil
*
- * Returns +self+ if +num+ is not zero, +nil+ otherwise.
+ * Returns +self+ if +self+ is not a zero value, +nil+ otherwise;
+ * uses method <tt>zero?</tt> for the evaluation.
*
- * This behavior is useful when chaining comparisons:
+ * The returned +self+ allows the method to be chained:
+ *
+ * a = %w[z Bb bB bb BB a aA Aa AA A]
+ * a.sort {|a, b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
+ * # => ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]
+ *
+ * Of the Core and Standard Library classes,
+ * Integer, Float, Rational, and Complex use this implementation.
*
- * a = %w( z Bb bB bb BB a aA Aa AA A )
- * b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
- * b #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb", "z"]
*/
static VALUE
num_nonzero_p(VALUE num)
{
if (RTEST(num_funcall0(num, rb_intern("zero?")))) {
- return Qnil;
+ return Qnil;
}
return num;
}
/*
* call-seq:
- * num.to_int -> integer
+ * to_int -> integer
+ *
+ * Returns +self+ as an integer;
+ * converts using method +to_i+ in the derived class.
*
- * Invokes the child class's +to_i+ method to convert +num+ to an integer.
+ * Of the Core and Standard Library classes,
+ * only Rational and Complex use this implementation.
+ *
+ * Examples:
+ *
+ * Rational(1, 2).to_int # => 0
+ * Rational(2, 1).to_int # => 2
+ * Complex(2, 0).to_int # => 2
+ * Complex(2, 1) # Raises RangeError (non-zero imaginary part)
*
- * 1.0.class #=> Float
- * 1.0.to_int.class #=> Integer
- * 1.0.to_i.class #=> Integer
*/
static VALUE
@@ -816,9 +895,10 @@ num_to_int(VALUE num)
/*
* call-seq:
- * num.positive? -> true or false
+ * positive? -> true or false
+ *
+ * Returns +true+ if +self+ is greater than 0, +false+ otherwise.
*
- * Returns +true+ if +num+ is greater than 0.
*/
static VALUE
@@ -827,21 +907,22 @@ num_positive_p(VALUE num)
const ID mid = '>';
if (FIXNUM_P(num)) {
- if (method_basic_p(rb_cInteger))
- return RBOOL((SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0));
+ if (method_basic_p(rb_cInteger))
+ return RBOOL((SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0));
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- if (method_basic_p(rb_cInteger))
- return RBOOL(BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num));
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ if (method_basic_p(rb_cInteger))
+ return RBOOL(BIGNUM_POSITIVE_P(num) && !rb_bigzero_p(num));
}
return rb_num_compare_with_zero(num, mid);
}
/*
* call-seq:
- * num.negative? -> true or false
+ * negative? -> true or false
+ *
+ * Returns +true+ if +self+ is less than 0, +false+ otherwise.
*
- * Returns +true+ if +num+ is less than 0.
*/
static VALUE
@@ -853,9 +934,9 @@ num_negative_p(VALUE num)
/********************************************************************
*
- * Document-class: Float
+ * Document-class: Float
*
- * Float objects represent inexact real numbers using the native
+ * A \Float object represents a sometimes-inexact real number using the native
* architecture's double-precision floating point representation.
*
* Floating point has a different arithmetic and is an inexact number.
@@ -864,6 +945,69 @@ num_negative_p(VALUE num)
* - 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
* - https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
+ *
+ * You can create a \Float object explicitly with:
+ *
+ * - A {floating-point literal}[rdoc-ref:syntax/literals.rdoc@Float+Literals].
+ *
+ * You can convert certain objects to Floats with:
+ *
+ * - \Method #Float.
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere. \Class \Float:
+ *
+ * - Inherits from {class Numeric}[rdoc-ref:Numeric@What-27s+Here].
+ *
+ * Here, class \Float provides methods for:
+ *
+ * - {Querying}[rdoc-ref:Float@Querying]
+ * - {Comparing}[rdoc-ref:Float@Comparing]
+ * - {Converting}[rdoc-ref:Float@Converting]
+ *
+ * === Querying
+ *
+ * - #finite?: Returns whether +self+ is finite.
+ * - #hash: Returns the integer hash code for +self+.
+ * - #infinite?: Returns whether +self+ is infinite.
+ * - #nan?: Returns whether +self+ is a NaN (not-a-number).
+ *
+ * === Comparing
+ *
+ * - #<: Returns whether +self+ is less than the given value.
+ * - #<=: Returns whether +self+ is less than or equal to the given value.
+ * - #<=>: Returns a number indicating whether +self+ is less than, equal
+ * to, or greater than the given value.
+ * - #== (aliased as #=== and #eql?): Returns whether +self+ is equal to
+ * the given value.
+ * - #>: Returns whether +self+ is greater than the given value.
+ * - #>=: Returns whether +self+ is greater than or equal to the given value.
+ *
+ * === Converting
+ *
+ * - #% (aliased as #modulo): Returns +self+ modulo the given value.
+ * - #*: Returns the product of +self+ and the given value.
+ * - #**: Returns the value of +self+ raised to the power of the given value.
+ * - #+: Returns the sum of +self+ and the given value.
+ * - #-: Returns the difference of +self+ and the given value.
+ * - #/: Returns the quotient of +self+ and the given value.
+ * - #ceil: Returns the smallest number greater than or equal to +self+.
+ * - #coerce: Returns a 2-element array containing the given value converted to a \Float
+ and +self+
+ * - #divmod: Returns a 2-element array containing the quotient and remainder
+ * results of dividing +self+ by the given value.
+ * - #fdiv: Returns the Float result of dividing +self+ by the given value.
+ * - #floor: Returns the greatest number smaller than or equal to +self+.
+ * - #next_float: Returns the next-larger representable \Float.
+ * - #prev_float: Returns the next-smaller representable \Float.
+ * - #quo: Returns the quotient from dividing +self+ by the given value.
+ * - #round: Returns +self+ rounded to the nearest value, to a given precision.
+ * - #to_i (aliased as #to_int): Returns +self+ truncated to an Integer.
+ * - #to_s (aliased as #inspect): Returns a string containing the place-value
+ * representation of +self+ in the given radix.
+ * - #truncate: Returns +self+ truncated to a given precision.
+ *
*/
VALUE
@@ -871,18 +1015,39 @@ rb_float_new_in_heap(double d)
{
NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0));
+#if SIZEOF_DOUBLE <= SIZEOF_VALUE
flt->float_value = d;
+#else
+ union {
+ double d;
+ rb_float_value_type v;
+ } u = {d};
+ flt->float_value = u.v;
+#endif
OBJ_FREEZE((VALUE)flt);
return (VALUE)flt;
}
/*
* call-seq:
- * float.to_s -> string
+ * to_s -> string
+ *
+ * Returns a string containing a representation of +self+;
+ * depending of the value of +self+, the string representation
+ * may contain:
+ *
+ * - A fixed-point number.
+ * - A number in "scientific notation" (containing an exponent).
+ * - 'Infinity'.
+ * - '-Infinity'.
+ * - 'NaN' (indicating not-a-number).
+ *
+ * 3.14.to_s # => "3.14"
+ * (10.1**50).to_s # => "1.644631821843879e+50"
+ * (10.1**500).to_s # => "Infinity"
+ * (-10.1**500).to_s # => "-Infinity"
+ * (0.0/0.0).to_s # => "NaN"
*
- * Returns a string containing a representation of +self+.
- * As well as a fixed or exponential form of the +float+,
- * the call may return +NaN+, +Infinity+, and +-Infinity+.
*/
static VALUE
@@ -890,19 +1055,19 @@ flo_to_s(VALUE flt)
{
enum {decimal_mant = DBL_MANT_DIG-DBL_DIG};
enum {float_dig = DBL_DIG+1};
- char buf[float_dig + (decimal_mant + CHAR_BIT - 1) / CHAR_BIT + 10];
+ char buf[float_dig + roomof(decimal_mant, CHAR_BIT) + 10];
double value = RFLOAT_VALUE(flt);
VALUE s;
char *p, *e;
int sign, decpt, digs;
if (isinf(value)) {
- static const char minf[] = "-Infinity";
- const int pos = (value > 0); /* skip "-" */
- return rb_usascii_str_new(minf+pos, strlen(minf)-pos);
+ static const char minf[] = "-Infinity";
+ const int pos = (value > 0); /* skip "-" */
+ return rb_usascii_str_new(minf+pos, strlen(minf)-pos);
}
else if (isnan(value))
- return rb_usascii_str_new2("NaN");
+ return rb_usascii_str_new2("NaN");
p = ruby_dtoa(value, 0, 0, &decpt, &sign, &e);
s = sign ? rb_usascii_str_new_cstr("-") : rb_usascii_str_new(0, 0);
@@ -910,35 +1075,35 @@ flo_to_s(VALUE flt)
memcpy(buf, p, digs);
xfree(p);
if (decpt > 0) {
- if (decpt < digs) {
- memmove(buf + decpt + 1, buf + decpt, digs - decpt);
- buf[decpt] = '.';
- rb_str_cat(s, buf, digs + 1);
- }
- else if (decpt <= DBL_DIG) {
- long len;
- char *ptr;
- rb_str_cat(s, buf, digs);
- rb_str_resize(s, (len = RSTRING_LEN(s)) + decpt - digs + 2);
- ptr = RSTRING_PTR(s) + len;
- if (decpt > digs) {
- memset(ptr, '0', decpt - digs);
- ptr += decpt - digs;
- }
- memcpy(ptr, ".0", 2);
- }
- else {
- goto exp;
- }
+ if (decpt < digs) {
+ memmove(buf + decpt + 1, buf + decpt, digs - decpt);
+ buf[decpt] = '.';
+ rb_str_cat(s, buf, digs + 1);
+ }
+ else if (decpt <= DBL_DIG) {
+ long len;
+ char *ptr;
+ rb_str_cat(s, buf, digs);
+ rb_str_resize(s, (len = RSTRING_LEN(s)) + decpt - digs + 2);
+ ptr = RSTRING_PTR(s) + len;
+ if (decpt > digs) {
+ memset(ptr, '0', decpt - digs);
+ ptr += decpt - digs;
+ }
+ memcpy(ptr, ".0", 2);
+ }
+ else {
+ goto exp;
+ }
}
else if (decpt > -4) {
- long len;
- char *ptr;
- rb_str_cat(s, "0.", 2);
- rb_str_resize(s, (len = RSTRING_LEN(s)) - decpt + digs);
- ptr = RSTRING_PTR(s);
- memset(ptr += len, '0', -decpt);
- memcpy(ptr -= decpt, buf, digs);
+ long len;
+ char *ptr;
+ rb_str_cat(s, "0.", 2);
+ rb_str_resize(s, (len = RSTRING_LEN(s)) - decpt + digs);
+ ptr = RSTRING_PTR(s);
+ memset(ptr += len, '0', -decpt);
+ memcpy(ptr -= decpt, buf, digs);
}
else {
goto exp;
@@ -961,15 +1126,19 @@ flo_to_s(VALUE flt)
/*
* call-seq:
- * float.coerce(numeric) -> array
+ * coerce(other) -> array
*
- * Returns an array with both +numeric+ and +float+ represented as Float
- * objects.
+ * Returns a 2-element array containing +other+ converted to a \Float
+ * and +self+:
*
- * This is achieved by converting +numeric+ to a Float.
+ * f = 3.14 # => 3.14
+ * f.coerce(2) # => [2.0, 3.14]
+ * f.coerce(2.0) # => [2.0, 3.14]
+ * f.coerce(Rational(1, 2)) # => [0.5, 3.14]
+ * f.coerce(Complex(1, 0)) # => [1.0, 3.14]
+ *
+ * Raises an exception if a type conversion fails.
*
- * 1.2.coerce(3) #=> [3.0, 1.2]
- * 2.5.coerce(1.1) #=> [1.1, 2.5]
*/
static VALUE
@@ -985,74 +1154,94 @@ rb_float_uminus(VALUE flt)
}
/*
- * call-seq:
- * float + other -> float
+ * call-seq:
+ * self + other -> numeric
+ *
+ * Returns a new \Float which is the sum of +self+ and +other+:
+ *
+ * f = 3.14
+ * f + 1 # => 4.140000000000001
+ * f + 1.0 # => 4.140000000000001
+ * f + Rational(1, 1) # => 4.140000000000001
+ * f + Complex(1, 0) # => (4.140000000000001+0i)
*
- * Returns a new Float which is the sum of +float+ and +other+.
*/
VALUE
rb_float_plus(VALUE x, VALUE y)
{
- if (RB_TYPE_P(y, T_FIXNUM)) {
- return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
+ if (FIXNUM_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '+');
+ return rb_num_coerce_bin(x, y, '+');
}
}
/*
- * call-seq:
- * float - other -> float
+ * call-seq:
+ * self - other -> numeric
+ *
+ * Returns a new \Float which is the difference of +self+ and +other+:
+ *
+ * f = 3.14
+ * f - 1 # => 2.14
+ * f - 1.0 # => 2.14
+ * f - Rational(1, 1) # => 2.14
+ * f - Complex(1, 0) # => (2.14+0i)
*
- * Returns a new Float which is the difference of +float+ and +other+.
*/
VALUE
rb_float_minus(VALUE x, VALUE y)
{
- if (RB_TYPE_P(y, T_FIXNUM)) {
- return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
+ if (FIXNUM_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return DBL2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '-');
+ return rb_num_coerce_bin(x, y, '-');
}
}
/*
- * call-seq:
- * float * other -> float
+ * call-seq:
+ * self * other -> numeric
+ *
+ * Returns a new \Float which is the product of +self+ and +other+:
*
- * Returns a new Float which is the product of +float+ and +other+.
+ * f = 3.14
+ * f * 2 # => 6.28
+ * f * 2.0 # => 6.28
+ * f * Rational(1, 2) # => 1.57
+ * f * Complex(2, 0) # => (6.28+0.0i)
*/
VALUE
rb_float_mul(VALUE x, VALUE y)
{
- if (RB_TYPE_P(y, T_FIXNUM)) {
- return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
+ if (FIXNUM_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return DBL2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '*');
+ return rb_num_coerce_bin(x, y, '*');
}
}
@@ -1081,10 +1270,17 @@ rb_flo_div_flo(VALUE x, VALUE y)
}
/*
- * call-seq:
- * float / other -> float
+ * call-seq:
+ * self / other -> numeric
+ *
+ * Returns a new \Float which is the result of dividing +self+ by +other+:
+ *
+ * f = 3.14
+ * f / 2 # => 1.57
+ * f / 2.0 # => 1.57
+ * f / Rational(2, 1) # => 1.57
+ * f / Complex(2, 0) # => (1.57+0.0i)
*
- * Returns a new Float which is the result of dividing +float+ by +other+.
*/
VALUE
@@ -1094,17 +1290,17 @@ rb_float_div(VALUE x, VALUE y)
double den;
double ret;
- if (RB_TYPE_P(y, T_FIXNUM)) {
+ if (FIXNUM_P(y)) {
den = FIX2LONG(y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
+ else if (RB_BIGNUM_TYPE_P(y)) {
den = rb_big2dbl(y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
+ else if (RB_FLOAT_TYPE_P(y)) {
den = RFLOAT_VALUE(y);
}
else {
- return rb_num_coerce_bin(x, y, '/');
+ return rb_num_coerce_bin(x, y, '/');
}
ret = double_div_double(num, den);
@@ -1113,10 +1309,18 @@ rb_float_div(VALUE x, VALUE y)
/*
* call-seq:
- * float.fdiv(numeric) -> float
- * float.quo(numeric) -> float
+ * quo(other) -> numeric
+ *
+ * Returns the quotient from dividing +self+ by +other+:
+ *
+ * f = 3.14
+ * f.quo(2) # => 1.57
+ * f.quo(-2) # => -1.57
+ * f.quo(Rational(2, 1)) # => 1.57
+ * f.quo(Complex(2, 0)) # => (1.57+0.0i)
+ *
+ * Float#fdiv is an alias for Float#quo.
*
- * Returns <code>float / numeric</code>, same as Float#/.
*/
static VALUE
@@ -1131,28 +1335,28 @@ flodivmod(double x, double y, double *divp, double *modp)
double div, mod;
if (isnan(y)) {
- /* y is NaN so all results are NaN */
- if (modp) *modp = y;
- if (divp) *divp = y;
- return;
+ /* y is NaN so all results are NaN */
+ if (modp) *modp = y;
+ if (divp) *divp = y;
+ return;
}
if (y == 0.0) rb_num_zerodiv();
if ((x == 0.0) || (isinf(y) && !isinf(x)))
mod = x;
else {
#ifdef HAVE_FMOD
- mod = fmod(x, y);
+ mod = fmod(x, y);
#else
- double z;
+ double z;
- modf(x/y, &z);
- mod = x - z * y;
+ modf(x/y, &z);
+ mod = x - z * y;
#endif
}
if (isinf(x) && !isinf(y))
- div = x;
+ div = x;
else {
- div = (x - mod) / y;
+ div = (x - mod) / y;
if (modp && divp) div = round(div);
}
if (y*mod < 0) {
@@ -1178,13 +1382,33 @@ ruby_float_mod(double x, double y)
/*
* call-seq:
- * float % other -> float
- * float.modulo(other) -> float
+ * self % other -> float
+ *
+ * Returns +self+ modulo +other+ as a float.
+ *
+ * For float +f+ and real number +r+, these expressions are equivalent:
*
- * Returns the modulo after division of +float+ by +other+.
+ * f % r
+ * f-r*(f/r).floor
+ * f.divmod(r)[1]
+ *
+ * See Numeric#divmod.
+ *
+ * Examples:
+ *
+ * 10.0 % 2 # => 0.0
+ * 10.0 % 3 # => 1.0
+ * 10.0 % 4 # => 2.0
+ *
+ * 10.0 % -2 # => 0.0
+ * 10.0 % -3 # => -2.0
+ * 10.0 % -4 # => -2.0
+ *
+ * 10.0 % 4.0 # => 2.0
+ * 10.0 % Rational(4, 1) # => 2.0
+ *
+ * Float#modulo is an alias for Float#%.
*
- * 6543.21.modulo(137) #=> 104.21000000000004
- * 6543.21.modulo(137.24) #=> 92.92999999999961
*/
static VALUE
@@ -1192,17 +1416,17 @@ flo_mod(VALUE x, VALUE y)
{
double fy;
- if (RB_TYPE_P(y, T_FIXNUM)) {
- fy = (double)FIX2LONG(y);
+ if (FIXNUM_P(y)) {
+ fy = (double)FIX2LONG(y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- fy = rb_big2dbl(y);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ fy = rb_big2dbl(y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- fy = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ fy = RFLOAT_VALUE(y);
}
else {
- return rb_num_coerce_bin(x, y, '%');
+ return rb_num_coerce_bin(x, y, '%');
}
return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(x), fy));
}
@@ -1211,19 +1435,35 @@ static VALUE
dbl2ival(double d)
{
if (FIXABLE(d)) {
- return LONG2FIX((long)d);
+ return LONG2FIX((long)d);
}
return rb_dbl2big(d);
}
/*
* call-seq:
- * float.divmod(numeric) -> array
+ * divmod(other) -> array
*
- * See Numeric#divmod.
+ * Returns a 2-element array <tt>[q, r]</tt>, where
+ *
+ * q = (self/other).floor # Quotient
+ * r = self % other # Remainder
+ *
+ * Examples:
+ *
+ * 11.0.divmod(4) # => [2, 3.0]
+ * 11.0.divmod(-4) # => [-3, -1.0]
+ * -11.0.divmod(4) # => [-3, 1.0]
+ * -11.0.divmod(-4) # => [2, -3.0]
+ *
+ * 12.0.divmod(4) # => [3, 0.0]
+ * 12.0.divmod(-4) # => [-3, 0.0]
+ * -12.0.divmod(4) # => [-3, -0.0]
+ * -12.0.divmod(-4) # => [3, -0.0]
+ *
+ * 13.0.divmod(4.0) # => [3, 1.0]
+ * 13.0.divmod(Rational(4, 1)) # => [3, 1.0]
*
- * 42.0.divmod(6) #=> [7, 0.0]
- * 42.0.divmod(5) #=> [8, 2.0]
*/
static VALUE
@@ -1232,17 +1472,17 @@ flo_divmod(VALUE x, VALUE y)
double fy, div, mod;
volatile VALUE a, b;
- if (RB_TYPE_P(y, T_FIXNUM)) {
- fy = (double)FIX2LONG(y);
+ if (FIXNUM_P(y)) {
+ fy = (double)FIX2LONG(y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- fy = rb_big2dbl(y);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ fy = rb_big2dbl(y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- fy = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ fy = RFLOAT_VALUE(y);
}
else {
- return rb_num_coerce_bin(x, y, id_divmod);
+ return rb_num_coerce_bin(x, y, id_divmod);
}
flodivmod(RFLOAT_VALUE(x), fy, &div, &mod);
a = dbl2ival(div);
@@ -1251,12 +1491,18 @@ flo_divmod(VALUE x, VALUE y)
}
/*
- * call-seq:
- * float ** other -> float
+ * call-seq:
+ * self ** other -> numeric
+ *
+ * Raises +self+ to the power of +other+:
*
- * Raises +float+ to the power of +other+.
+ * f = 3.14
+ * f ** 2 # => 9.8596
+ * f ** -2 # => 0.1014239928597509
+ * f ** 2.1 # => 11.054834900588839
+ * f ** Rational(2, 1) # => 9.8596
+ * f ** Complex(2, 0) # => (9.8596+0i)
*
- * 2.0**3 #=> 8.0
*/
VALUE
@@ -1264,39 +1510,48 @@ rb_float_pow(VALUE x, VALUE y)
{
double dx, dy;
if (y == INT2FIX(2)) {
- dx = RFLOAT_VALUE(x);
+ dx = RFLOAT_VALUE(x);
return DBL2NUM(dx * dx);
}
- else if (RB_TYPE_P(y, T_FIXNUM)) {
- dx = RFLOAT_VALUE(x);
- dy = (double)FIX2LONG(y);
+ else if (FIXNUM_P(y)) {
+ dx = RFLOAT_VALUE(x);
+ dy = (double)FIX2LONG(y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- dx = RFLOAT_VALUE(x);
- dy = rb_big2dbl(y);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ dx = RFLOAT_VALUE(x);
+ dy = rb_big2dbl(y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- dx = RFLOAT_VALUE(x);
- dy = RFLOAT_VALUE(y);
- if (dx < 0 && dy != round(dy))
+ else if (RB_FLOAT_TYPE_P(y)) {
+ dx = RFLOAT_VALUE(x);
+ dy = RFLOAT_VALUE(y);
+ if (dx < 0 && dy != round(dy))
return rb_dbl_complex_new_polar_pi(pow(-dx, dy), dy);
}
else {
- return rb_num_coerce_bin(x, y, idPow);
+ return rb_num_coerce_bin(x, y, idPow);
}
return DBL2NUM(pow(dx, dy));
}
/*
* call-seq:
- * num.eql?(numeric) -> true or false
+ * eql?(other) -> true or false
*
- * Returns +true+ if +num+ and +numeric+ are the same type and have equal
- * values. Contrast this with Numeric#==, which performs type conversions.
+ * Returns +true+ if +self+ and +other+ are the same type and have equal values.
+ *
+ * Of the Core and Standard Library classes,
+ * only Integer, Rational, and Complex use this implementation.
+ *
+ * Examples:
+ *
+ * 1.eql?(1) # => true
+ * 1.eql?(1.0) # => false
+ * 1.eql?(Rational(1, 1)) # => false
+ * 1.eql?(Complex(1, 0)) # => false
+ *
+ * \Method +eql?+ is different from +==+ in that +eql?+ requires matching types,
+ * while +==+ does not.
*
- * 1 == 1.0 #=> true
- * 1.eql?(1.0) #=> false
- * 1.0.eql?(1.0) #=> true
*/
static VALUE
@@ -1304,8 +1559,8 @@ num_eql(VALUE x, VALUE y)
{
if (TYPE(x) != TYPE(y)) return Qfalse;
- if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_eql(x, y);
+ if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_eql(x, y);
}
return rb_equal(x, y);
@@ -1313,9 +1568,12 @@ num_eql(VALUE x, VALUE y)
/*
* call-seq:
- * number <=> other -> 0 or nil
+ * self <=> other -> zero or nil
+ *
+ * Returns zero if +self+ is the same as +other+, +nil+ otherwise.
+ *
+ * No subclass in the Ruby Core or Standard Library uses this implementation.
*
- * Returns zero if +number+ equals +other+, otherwise returns +nil+.
*/
static VALUE
@@ -1336,15 +1594,19 @@ num_equal(VALUE x, VALUE y)
/*
* call-seq:
- * float == obj -> true or false
+ * self == other -> true or false
*
- * Returns +true+ only if +obj+ has the same value as +float+.
- * Contrast this with Float#eql?, which requires +obj+ to be a Float.
+ * Returns +true+ if +other+ has the same value as +self+, +false+ otherwise:
*
- * 1.0 == 1 #=> true
+ * 2.0 == 2 # => true
+ * 2.0 == 2.0 # => true
+ * 2.0 == Rational(2, 1) # => true
+ * 2.0 == Complex(2, 0) # => true
+ *
+ * <tt>Float::NAN == Float::NAN</tt> returns an implementation-dependent value.
+ *
+ * Related: Float#eql? (requires +other+ to be a \Float).
*
- * The result of <code>NaN == NaN</code> is undefined,
- * so an implementation-dependent value is returned.
*/
MJIT_FUNC_EXPORTED VALUE
@@ -1352,23 +1614,23 @@ rb_float_equal(VALUE x, VALUE y)
{
volatile double a, b;
- if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
+ if (RB_INTEGER_TYPE_P(y)) {
return rb_integer_float_eq(y, x);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- b = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ b = RFLOAT_VALUE(y);
#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
+ if (isnan(b)) return Qfalse;
#endif
}
else {
- return num_equal(x, y);
+ return num_equal(x, y);
}
a = RFLOAT_VALUE(x);
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
- return (a == b)?Qtrue:Qfalse;
+ return RBOOL(a == b);
}
#define flo_eq rb_float_equal
@@ -1376,9 +1638,9 @@ static VALUE rb_dbl_hash(double d);
/*
* call-seq:
- * float.hash -> integer
+ * hash -> integer
*
- * Returns a hash code for this float.
+ * Returns the integer hash value for +self+.
*
* See also Object#hash.
*/
@@ -1407,16 +1669,30 @@ rb_dbl_cmp(double a, double b)
/*
* call-seq:
- * float <=> real -> -1, 0, +1, or nil
+ * self <=> other -> -1, 0, +1, or nil
+ *
+ * Returns a value that depends on the numeric relation
+ * between +self+ and +other+:
+ *
+ * - -1, if +self+ is less than +other+.
+ * - 0, if +self+ is equal to +other+.
+ * - 1, if +self+ is greater than +other+.
+ * - +nil+, if the two values are incommensurate.
+ *
+ * Examples:
+ *
+ * 2.0 <=> 2 # => 0
+ 2.0 <=> 2.0 # => 0
+ 2.0 <=> Rational(2, 1) # => 0
+ 2.0 <=> Complex(2, 0) # => 0
+ 2.0 <=> 1.9 # => 1
+ 2.0 <=> 2.1 # => -1
+ 2.0 <=> 'foo' # => nil
*
- * Returns -1, 0, or +1 depending on whether +float+ is
- * less than, equal to, or greater than +real+.
* This is the basis for the tests in the Comparable module.
*
- * The result of <code>NaN <=> NaN</code> is undefined,
- * so an implementation-dependent value is returned.
+ * <tt>Float::NAN <=> Float::NAN</tt> returns an implementation-dependent value.
*
- * +nil+ is returned if the two values are incomparable.
*/
static VALUE
@@ -1427,26 +1703,26 @@ flo_cmp(VALUE x, VALUE y)
a = RFLOAT_VALUE(x);
if (isnan(a)) return Qnil;
- if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
+ if (RB_INTEGER_TYPE_P(y)) {
VALUE rel = rb_integer_float_cmp(y, x);
if (FIXNUM_P(rel))
return LONG2FIX(-FIX2LONG(rel));
return rel;
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- b = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ b = RFLOAT_VALUE(y);
}
else {
- if (isinf(a) && (i = rb_check_funcall(y, rb_intern("infinite?"), 0, 0)) != Qundef) {
- if (RTEST(i)) {
- int j = rb_cmpint(i, x, y);
- j = (a > 0.0) ? (j > 0 ? 0 : +1) : (j < 0 ? 0 : -1);
- return INT2FIX(j);
- }
- if (a > 0.0) return INT2FIX(1);
- return INT2FIX(-1);
- }
- return rb_num_coerce_cmp(x, y, id_cmp);
+ if (isinf(a) && !UNDEF_P(i = rb_check_funcall(y, rb_intern("infinite?"), 0, 0))) {
+ if (RTEST(i)) {
+ int j = rb_cmpint(i, x, y);
+ j = (a > 0.0) ? (j > 0 ? 0 : +1) : (j < 0 ? 0 : -1);
+ return INT2FIX(j);
+ }
+ if (a > 0.0) return INT2FIX(1);
+ return INT2FIX(-1);
+ }
+ return rb_num_coerce_cmp(x, y, id_cmp);
}
return rb_dbl_cmp(a, b);
}
@@ -1458,13 +1734,18 @@ rb_float_cmp(VALUE x, VALUE y)
}
/*
- * call-seq:
- * float > real -> true or false
+ * call-seq:
+ * self > other -> true or false
+ *
+ * Returns +true+ if +self+ is numerically greater than +other+:
+ *
+ * 2.0 > 1 # => true
+ * 2.0 > 1.0 # => true
+ * 2.0 > Rational(1, 2) # => true
+ * 2.0 > 2.0 # => false
*
- * Returns +true+ if +float+ is greater than +real+.
+ * <tt>Float::NAN > Float::NAN</tt> returns an implementation-dependent value.
*
- * The result of <code>NaN > NaN</code> is undefined,
- * so an implementation-dependent value is returned.
*/
VALUE
@@ -1473,35 +1754,41 @@ rb_float_gt(VALUE x, VALUE y)
double a, b;
a = RFLOAT_VALUE(x);
- if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
+ if (RB_INTEGER_TYPE_P(y)) {
VALUE rel = rb_integer_float_cmp(y, x);
if (FIXNUM_P(rel))
return RBOOL(-FIX2LONG(rel) > 0);
return Qfalse;
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- b = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ b = RFLOAT_VALUE(y);
#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
+ if (isnan(b)) return Qfalse;
#endif
}
else {
- return rb_num_coerce_relop(x, y, '>');
+ return rb_num_coerce_relop(x, y, '>');
}
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
- return (a > b)?Qtrue:Qfalse;
+ return RBOOL(a > b);
}
/*
- * call-seq:
- * float >= real -> true or false
+ * call-seq:
+ * self >= other -> true or false
+ *
+ * Returns +true+ if +self+ is numerically greater than or equal to +other+:
+ *
+ * 2.0 >= 1 # => true
+ * 2.0 >= 1.0 # => true
+ * 2.0 >= Rational(1, 2) # => true
+ * 2.0 >= 2.0 # => true
+ * 2.0 >= 2.1 # => false
*
- * Returns +true+ if +float+ is greater than or equal to +real+.
+ * <tt>Float::NAN >= Float::NAN</tt> returns an implementation-dependent value.
*
- * The result of <code>NaN >= NaN</code> is undefined,
- * so an implementation-dependent value is returned.
*/
static VALUE
@@ -1510,35 +1797,40 @@ flo_ge(VALUE x, VALUE y)
double a, b;
a = RFLOAT_VALUE(x);
- if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
+ if (RB_TYPE_P(y, T_FIXNUM) || RB_BIGNUM_TYPE_P(y)) {
VALUE rel = rb_integer_float_cmp(y, x);
if (FIXNUM_P(rel))
return RBOOL(-FIX2LONG(rel) >= 0);
return Qfalse;
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- b = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ b = RFLOAT_VALUE(y);
#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
+ if (isnan(b)) return Qfalse;
#endif
}
else {
- return rb_num_coerce_relop(x, y, idGE);
+ return rb_num_coerce_relop(x, y, idGE);
}
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
- return (a >= b)?Qtrue:Qfalse;
+ return RBOOL(a >= b);
}
/*
- * call-seq:
- * float < real -> true or false
+ * call-seq:
+ * self < other -> true or false
+ *
+ * Returns +true+ if +self+ is numerically less than +other+:
*
- * Returns +true+ if +float+ is less than +real+.
+ * 2.0 < 3 # => true
+ * 2.0 < 3.0 # => true
+ * 2.0 < Rational(3, 1) # => true
+ * 2.0 < 2.0 # => false
+ *
+ * <tt>Float::NAN < Float::NAN</tt> returns an implementation-dependent value.
*
- * The result of <code>NaN < NaN</code> is undefined,
- * so an implementation-dependent value is returned.
*/
static VALUE
@@ -1547,35 +1839,41 @@ flo_lt(VALUE x, VALUE y)
double a, b;
a = RFLOAT_VALUE(x);
- if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
+ if (RB_INTEGER_TYPE_P(y)) {
VALUE rel = rb_integer_float_cmp(y, x);
if (FIXNUM_P(rel))
return RBOOL(-FIX2LONG(rel) < 0);
return Qfalse;
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- b = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ b = RFLOAT_VALUE(y);
#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
+ if (isnan(b)) return Qfalse;
#endif
}
else {
- return rb_num_coerce_relop(x, y, '<');
+ return rb_num_coerce_relop(x, y, '<');
}
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
- return (a < b)?Qtrue:Qfalse;
+ return RBOOL(a < b);
}
/*
- * call-seq:
- * float <= real -> true or false
+ * call-seq:
+ * self <= other -> true or false
*
- * Returns +true+ if +float+ is less than or equal to +real+.
+ * Returns +true+ if +self+ is numerically less than or equal to +other+:
+ *
+ * 2.0 <= 3 # => true
+ * 2.0 <= 3.0 # => true
+ * 2.0 <= Rational(3, 1) # => true
+ * 2.0 <= 2.0 # => true
+ * 2.0 <= 1.0 # => false
+ *
+ * <tt>Float::NAN <= Float::NAN</tt> returns an implementation-dependent value.
*
- * The result of <code>NaN <= NaN</code> is undefined,
- * so an implementation-dependent value is returned.
*/
static VALUE
@@ -1584,51 +1882,55 @@ flo_le(VALUE x, VALUE y)
double a, b;
a = RFLOAT_VALUE(x);
- if (RB_TYPE_P(y, T_FIXNUM) || RB_TYPE_P(y, T_BIGNUM)) {
+ if (RB_INTEGER_TYPE_P(y)) {
VALUE rel = rb_integer_float_cmp(y, x);
if (FIXNUM_P(rel))
return RBOOL(-FIX2LONG(rel) <= 0);
return Qfalse;
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- b = RFLOAT_VALUE(y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ b = RFLOAT_VALUE(y);
#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
+ if (isnan(b)) return Qfalse;
#endif
}
else {
- return rb_num_coerce_relop(x, y, idLE);
+ return rb_num_coerce_relop(x, y, idLE);
}
#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
- return (a <= b)?Qtrue:Qfalse;
+ return RBOOL(a <= b);
}
/*
* call-seq:
- * float.eql?(obj) -> true or false
+ * eql?(other) -> true or false
+ *
+ * Returns +true+ if +other+ is a \Float with the same value as +self+,
+ * +false+ otherwise:
*
- * Returns +true+ only if +obj+ is a Float with the same value as +float+.
- * Contrast this with Float#==, which performs type conversions.
+ * 2.0.eql?(2.0) # => true
+ * 2.0.eql?(1.0) # => false
+ * 2.0.eql?(1) # => false
+ * 2.0.eql?(Rational(2, 1)) # => false
+ * 2.0.eql?(Complex(2, 0)) # => false
*
- * 1.0.eql?(1) #=> false
+ * <tt>Float::NAN.eql?(Float::NAN)</tt> returns an implementation-dependent value.
*
- * The result of <code>NaN.eql?(NaN)</code> is undefined,
- * so an implementation-dependent value is returned.
+ * Related: Float#== (performs type conversions).
*/
MJIT_FUNC_EXPORTED VALUE
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 (RB_FLOAT_TYPE_P(y)) {
+ double a = RFLOAT_VALUE(x);
+ double b = RFLOAT_VALUE(y);
#if MSC_VERSION_BEFORE(1300)
- if (isnan(a) || isnan(b)) return Qfalse;
+ if (isnan(a) || isnan(b)) return Qfalse;
#endif
- if (a == b)
- return Qtrue;
+ return RBOOL(a == b);
}
return Qfalse;
}
@@ -1644,14 +1946,14 @@ rb_float_abs(VALUE flt)
/*
* call-seq:
- * float.nan? -> true or false
+ * nan? -> true or false
*
- * Returns +true+ if +float+ is an invalid IEEE floating point number.
+ * Returns +true+ if +self+ is a NaN, +false+ otherwise.
*
- * a = -1.0 #=> -1.0
- * a.nan? #=> false
- * a = 0.0/0.0 #=> NaN
- * a.nan? #=> true
+ * f = -1.0 #=> -1.0
+ * f.nan? #=> false
+ * f = 0.0/0.0 #=> NaN
+ * f.nan? #=> true
*/
static VALUE
@@ -1664,14 +1966,25 @@ flo_is_nan_p(VALUE num)
/*
* call-seq:
- * float.infinite? -> -1, 1, or nil
+ * infinite? -> -1, 1, or nil
*
- * Returns +nil+, -1, or 1 depending on whether the value is
- * finite, <code>-Infinity</code>, or <code>+Infinity</code>.
+ * Returns:
+ *
+ * - 1, if +self+ is <tt>Infinity</tt>.
+ * - -1 if +self+ is <tt>-Infinity</tt>.
+ * - +nil+, otherwise.
+ *
+ * Examples:
+ *
+ * f = 1.0/0.0 # => Infinity
+ * f.infinite? # => 1
+ * f = -1.0/0.0 # => -Infinity
+ * f.infinite? # => -1
+ * f = 1.0 # => 1.0
+ * f.infinite? # => nil
+ * f = 0.0/0.0 # => NaN
+ * f.infinite? # => nil
*
- * (0.0).infinite? #=> nil
- * (-1.0/0.0).infinite? #=> -1
- * (+1.0/0.0).infinite? #=> 1
*/
VALUE
@@ -1680,7 +1993,7 @@ rb_flo_is_infinite_p(VALUE num)
double value = RFLOAT_VALUE(num);
if (isinf(value)) {
- return INT2FIX( value < 0 ? -1 : 1 );
+ return INT2FIX( value < 0 ? -1 : 1 );
}
return Qnil;
@@ -1688,10 +2001,20 @@ rb_flo_is_infinite_p(VALUE num)
/*
* call-seq:
- * float.finite? -> true or false
+ * finite? -> true or false
+ *
+ * Returns +true+ if +self+ is not +Infinity+, +-Infinity+, or +NaN+,
+ * +false+ otherwise:
+ *
+ * f = 2.0 # => 2.0
+ * f.finite? # => true
+ * f = 1.0/0.0 # => Infinity
+ * f.finite? # => false
+ * f = -1.0/0.0 # => -Infinity
+ * f.finite? # => false
+ * f = 0.0/0.0 # => NaN
+ * f.finite? # => false
*
- * Returns +true+ if +float+ is a valid IEEE floating point number,
- * i.e. it is not infinite and Float#nan? is +false+.
*/
VALUE
@@ -1699,15 +2022,7 @@ rb_flo_is_finite_p(VALUE num)
{
double value = RFLOAT_VALUE(num);
-#ifdef HAVE_ISFINITE
- if (!isfinite(value))
- return Qfalse;
-#else
- if (isinf(value) || isnan(value))
- return Qfalse;
-#endif
-
- return Qtrue;
+ return RBOOL(isfinite(value));
}
static VALUE
@@ -1721,55 +2036,47 @@ flo_nextafter(VALUE flo, double value)
/*
* call-seq:
- * float.next_float -> float
- *
- * Returns the next representable floating point number.
- *
- * Float::MAX.next_float and Float::INFINITY.next_float is Float::INFINITY.
- *
- * Float::NAN.next_float is Float::NAN.
- *
- * For example:
- *
- * 0.01.next_float #=> 0.010000000000000002
- * 1.0.next_float #=> 1.0000000000000002
- * 100.0.next_float #=> 100.00000000000001
- *
- * 0.01.next_float - 0.01 #=> 1.734723475976807e-18
- * 1.0.next_float - 1.0 #=> 2.220446049250313e-16
- * 100.0.next_float - 100.0 #=> 1.4210854715202004e-14
- *
- * f = 0.01; 20.times { printf "%-20a %s\n", f, f.to_s; f = f.next_float }
- * #=> 0x1.47ae147ae147bp-7 0.01
- * # 0x1.47ae147ae147cp-7 0.010000000000000002
- * # 0x1.47ae147ae147dp-7 0.010000000000000004
- * # 0x1.47ae147ae147ep-7 0.010000000000000005
- * # 0x1.47ae147ae147fp-7 0.010000000000000007
- * # 0x1.47ae147ae148p-7 0.010000000000000009
- * # 0x1.47ae147ae1481p-7 0.01000000000000001
- * # 0x1.47ae147ae1482p-7 0.010000000000000012
- * # 0x1.47ae147ae1483p-7 0.010000000000000014
- * # 0x1.47ae147ae1484p-7 0.010000000000000016
- * # 0x1.47ae147ae1485p-7 0.010000000000000018
- * # 0x1.47ae147ae1486p-7 0.01000000000000002
- * # 0x1.47ae147ae1487p-7 0.010000000000000021
- * # 0x1.47ae147ae1488p-7 0.010000000000000023
- * # 0x1.47ae147ae1489p-7 0.010000000000000024
- * # 0x1.47ae147ae148ap-7 0.010000000000000026
- * # 0x1.47ae147ae148bp-7 0.010000000000000028
- * # 0x1.47ae147ae148cp-7 0.01000000000000003
- * # 0x1.47ae147ae148dp-7 0.010000000000000031
- * # 0x1.47ae147ae148ep-7 0.010000000000000033
- *
- * f = 0.0
- * 100.times { f += 0.1 }
- * f #=> 9.99999999999998 # should be 10.0 in the ideal world.
- * 10-f #=> 1.9539925233402755e-14 # the floating point error.
- * 10.0.next_float-10 #=> 1.7763568394002505e-15 # 1 ulp (unit in the last place).
- * (10-f)/(10.0.next_float-10) #=> 11.0 # the error is 11 ulp.
- * (10-f)/(10*Float::EPSILON) #=> 8.8 # approximation of the above.
- * "%a" % 10 #=> "0x1.4p+3"
- * "%a" % f #=> "0x1.3fffffffffff5p+3" # the last hex digit is 5. 16 - 5 = 11 ulp.
+ * next_float -> float
+ *
+ * Returns the next-larger representable \Float.
+ *
+ * These examples show the internally stored values (64-bit hexadecimal)
+ * for each \Float +f+ and for the corresponding <tt>f.next_float</tt>:
+ *
+ * f = 0.0 # 0x0000000000000000
+ * f.next_float # 0x0000000000000001
+ *
+ * f = 0.01 # 0x3f847ae147ae147b
+ * f.next_float # 0x3f847ae147ae147c
+ *
+ * In the remaining examples here, the output is shown in the usual way
+ * (result +to_s+):
+ *
+ * 0.01.next_float # => 0.010000000000000002
+ * 1.0.next_float # => 1.0000000000000002
+ * 100.0.next_float # => 100.00000000000001
+ *
+ * f = 0.01
+ * (0..3).each_with_index {|i| printf "%2d %-20a %s\n", i, f, f.to_s; f = f.next_float }
+ *
+ * Output:
+ *
+ * 0 0x1.47ae147ae147bp-7 0.01
+ * 1 0x1.47ae147ae147cp-7 0.010000000000000002
+ * 2 0x1.47ae147ae147dp-7 0.010000000000000004
+ * 3 0x1.47ae147ae147ep-7 0.010000000000000005
+ *
+ * f = 0.0; 100.times { f += 0.1 }
+ * f # => 9.99999999999998 # should be 10.0 in the ideal world.
+ * 10-f # => 1.9539925233402755e-14 # the floating point error.
+ * 10.0.next_float-10 # => 1.7763568394002505e-15 # 1 ulp (unit in the last place).
+ * (10-f)/(10.0.next_float-10) # => 11.0 # the error is 11 ulp.
+ * (10-f)/(10*Float::EPSILON) # => 8.8 # approximation of the above.
+ * "%a" % 10 # => "0x1.4p+3"
+ * "%a" % f # => "0x1.3fffffffffff5p+3" # the last hex digit is 5. 16 - 5 = 11 ulp.
+ *
+ * Related: Float#prev_float
+ *
*/
static VALUE
flo_next_float(VALUE vx)
@@ -1781,43 +2088,36 @@ flo_next_float(VALUE vx)
* call-seq:
* float.prev_float -> float
*
- * Returns the previous representable floating point number.
- *
- * (-Float::MAX).prev_float and (-Float::INFINITY).prev_float is -Float::INFINITY.
- *
- * Float::NAN.prev_float is Float::NAN.
- *
- * For example:
- *
- * 0.01.prev_float #=> 0.009999999999999998
- * 1.0.prev_float #=> 0.9999999999999999
- * 100.0.prev_float #=> 99.99999999999999
- *
- * 0.01 - 0.01.prev_float #=> 1.734723475976807e-18
- * 1.0 - 1.0.prev_float #=> 1.1102230246251565e-16
- * 100.0 - 100.0.prev_float #=> 1.4210854715202004e-14
- *
- * f = 0.01; 20.times { printf "%-20a %s\n", f, f.to_s; f = f.prev_float }
- * #=> 0x1.47ae147ae147bp-7 0.01
- * # 0x1.47ae147ae147ap-7 0.009999999999999998
- * # 0x1.47ae147ae1479p-7 0.009999999999999997
- * # 0x1.47ae147ae1478p-7 0.009999999999999995
- * # 0x1.47ae147ae1477p-7 0.009999999999999993
- * # 0x1.47ae147ae1476p-7 0.009999999999999992
- * # 0x1.47ae147ae1475p-7 0.00999999999999999
- * # 0x1.47ae147ae1474p-7 0.009999999999999988
- * # 0x1.47ae147ae1473p-7 0.009999999999999986
- * # 0x1.47ae147ae1472p-7 0.009999999999999985
- * # 0x1.47ae147ae1471p-7 0.009999999999999983
- * # 0x1.47ae147ae147p-7 0.009999999999999981
- * # 0x1.47ae147ae146fp-7 0.00999999999999998
- * # 0x1.47ae147ae146ep-7 0.009999999999999978
- * # 0x1.47ae147ae146dp-7 0.009999999999999976
- * # 0x1.47ae147ae146cp-7 0.009999999999999974
- * # 0x1.47ae147ae146bp-7 0.009999999999999972
- * # 0x1.47ae147ae146ap-7 0.00999999999999997
- * # 0x1.47ae147ae1469p-7 0.009999999999999969
- * # 0x1.47ae147ae1468p-7 0.009999999999999967
+ * Returns the next-smaller representable \Float.
+ *
+ * These examples show the internally stored values (64-bit hexadecimal)
+ * for each \Float +f+ and for the corresponding <tt>f.pev_float</tt>:
+ *
+ * f = 5e-324 # 0x0000000000000001
+ * f.prev_float # 0x0000000000000000
+ *
+ * f = 0.01 # 0x3f847ae147ae147b
+ * f.prev_float # 0x3f847ae147ae147a
+ *
+ * In the remaining examples here, the output is shown in the usual way
+ * (result +to_s+):
+ *
+ * 0.01.prev_float # => 0.009999999999999998
+ * 1.0.prev_float # => 0.9999999999999999
+ * 100.0.prev_float # => 99.99999999999999
+ *
+ * f = 0.01
+ * (0..3).each_with_index {|i| printf "%2d %-20a %s\n", i, f, f.to_s; f = f.prev_float }
+ *
+ * Output:
+ *
+ * 0 0x1.47ae147ae147bp-7 0.01
+ * 1 0x1.47ae147ae147ap-7 0.009999999999999998
+ * 2 0x1.47ae147ae1479p-7 0.009999999999999997
+ * 3 0x1.47ae147ae1478p-7 0.009999999999999995
+ *
+ * Related: Float#next_float.
+ *
*/
static VALUE
flo_prev_float(VALUE vx)
@@ -1831,16 +2131,16 @@ rb_float_floor(VALUE num, int ndigits)
double number;
number = RFLOAT_VALUE(num);
if (number == 0.0) {
- return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
+ return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
}
if (ndigits > 0) {
- int binexp;
+ int binexp;
double f, mul, res;
- frexp(number, &binexp);
- if (float_round_overflow(ndigits, binexp)) return num;
- if (number > 0.0 && float_round_underflow(ndigits, binexp))
- return DBL2NUM(0.0);
- f = pow(10, ndigits);
+ frexp(number, &binexp);
+ if (float_round_overflow(ndigits, binexp)) return num;
+ if (number > 0.0 && float_round_underflow(ndigits, binexp))
+ return DBL2NUM(0.0);
+ f = pow(10, ndigits);
mul = floor(number * f);
res = (mul + 1) / f;
if (res > number)
@@ -1848,108 +2148,104 @@ rb_float_floor(VALUE num, int ndigits)
return DBL2NUM(res);
}
else {
- num = dbl2ival(floor(number));
- if (ndigits < 0) num = rb_int_floor(num, ndigits);
- return num;
+ num = dbl2ival(floor(number));
+ if (ndigits < 0) num = rb_int_floor(num, ndigits);
+ return num;
}
}
+static int
+flo_ndigits(int argc, VALUE *argv)
+{
+ if (rb_check_arity(argc, 0, 1)) {
+ return NUM2INT(argv[0]);
+ }
+ return 0;
+}
+
/*
* call-seq:
- * float.floor([ndigits]) -> integer or float
+ * floor(ndigits = 0) -> float or integer
*
- * Returns the largest number less than or equal to +float+ with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns the largest number less than or equal to +self+ with
+ * a precision of +ndigits+ decimal digits.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
- *
- * Returns a floating point number when +ndigits+ is positive,
- * otherwise returns an integer.
- *
- * 1.2.floor #=> 1
- * 2.0.floor #=> 2
- * (-1.2).floor #=> -2
- * (-2.0).floor #=> -2
- *
- * 1.234567.floor(2) #=> 1.23
- * 1.234567.floor(3) #=> 1.234
- * 1.234567.floor(4) #=> 1.2345
- * 1.234567.floor(5) #=> 1.23456
- *
- * 34567.89.floor(-5) #=> 0
- * 34567.89.floor(-4) #=> 30000
- * 34567.89.floor(-3) #=> 34000
- * 34567.89.floor(-2) #=> 34500
- * 34567.89.floor(-1) #=> 34560
- * 34567.89.floor(0) #=> 34567
- * 34567.89.floor(1) #=> 34567.8
- * 34567.89.floor(2) #=> 34567.89
- * 34567.89.floor(3) #=> 34567.89
- *
- * Note that the limited precision of floating point arithmetic
- * might lead to surprising results:
+ * When +ndigits+ is positive, returns a float with +ndigits+
+ * digits after the decimal point (as available):
+ *
+ * f = 12345.6789
+ * f.floor(1) # => 12345.6
+ * f.floor(3) # => 12345.678
+ * f = -12345.6789
+ * f.floor(1) # => -12345.7
+ * f.floor(3) # => -12345.679
+ *
+ * When +ndigits+ is non-positive, returns an integer with at least
+ * <code>ndigits.abs</code> trailing zeros:
+ *
+ * f = 12345.6789
+ * f.floor(0) # => 12345
+ * f.floor(-3) # => 12000
+ * f = -12345.6789
+ * f.floor(0) # => -12346
+ * f.floor(-3) # => -13000
+ *
+ * Note that the limited precision of floating-point arithmetic
+ * may lead to surprising results:
*
* (0.3 / 0.1).floor #=> 2 (!)
+ *
+ * Related: Float#ceil.
+ *
*/
static VALUE
flo_floor(int argc, VALUE *argv, VALUE num)
{
- int ndigits = 0;
- if (rb_check_arity(argc, 0, 1)) {
- ndigits = NUM2INT(argv[0]);
- }
+ int ndigits = flo_ndigits(argc, argv);
return rb_float_floor(num, ndigits);
}
/*
* call-seq:
- * float.ceil([ndigits]) -> integer or float
+ * ceil(ndigits = 0) -> float or integer
*
- * Returns the smallest number greater than or equal to +float+ with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns the smallest number greater than or equal to +self+ with
+ * a precision of +ndigits+ decimal digits.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
- *
- * Returns a floating point number when +ndigits+ is positive,
- * otherwise returns an integer.
- *
- * 1.2.ceil #=> 2
- * 2.0.ceil #=> 2
- * (-1.2).ceil #=> -1
- * (-2.0).ceil #=> -2
- *
- * 1.234567.ceil(2) #=> 1.24
- * 1.234567.ceil(3) #=> 1.235
- * 1.234567.ceil(4) #=> 1.2346
- * 1.234567.ceil(5) #=> 1.23457
- *
- * 34567.89.ceil(-5) #=> 100000
- * 34567.89.ceil(-4) #=> 40000
- * 34567.89.ceil(-3) #=> 35000
- * 34567.89.ceil(-2) #=> 34600
- * 34567.89.ceil(-1) #=> 34570
- * 34567.89.ceil(0) #=> 34568
- * 34567.89.ceil(1) #=> 34567.9
- * 34567.89.ceil(2) #=> 34567.89
- * 34567.89.ceil(3) #=> 34567.89
- *
- * Note that the limited precision of floating point arithmetic
- * might lead to surprising results:
+ * When +ndigits+ is positive, returns a float with +ndigits+
+ * digits after the decimal point (as available):
+ *
+ * f = 12345.6789
+ * f.ceil(1) # => 12345.7
+ * f.ceil(3) # => 12345.679
+ * f = -12345.6789
+ * f.ceil(1) # => -12345.6
+ * f.ceil(3) # => -12345.678
+ *
+ * When +ndigits+ is non-positive, returns an integer with at least
+ * <code>ndigits.abs</code> trailing zeros:
+ *
+ * f = 12345.6789
+ * f.ceil(0) # => 12346
+ * f.ceil(-3) # => 13000
+ * f = -12345.6789
+ * f.ceil(0) # => -12345
+ * f.ceil(-3) # => -12000
+ *
+ * Note that the limited precision of floating-point arithmetic
+ * may lead to surprising results:
*
* (2.1 / 0.7).ceil #=> 4 (!)
+ *
+ * Related: Float#floor.
+ *
*/
static VALUE
flo_ceil(int argc, VALUE *argv, VALUE num)
{
- int ndigits = 0;
-
- if (rb_check_arity(argc, 0, 1)) {
- ndigits = NUM2INT(argv[0]);
- }
+ int ndigits = flo_ndigits(argc, argv);
return rb_float_ceil(num, ndigits);
}
@@ -1960,22 +2256,22 @@ rb_float_ceil(VALUE num, int ndigits)
number = RFLOAT_VALUE(num);
if (number == 0.0) {
- return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
+ return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
}
if (ndigits > 0) {
- int binexp;
- frexp(number, &binexp);
- if (float_round_overflow(ndigits, binexp)) return num;
- if (number < 0.0 && float_round_underflow(ndigits, binexp))
- return DBL2NUM(0.0);
- f = pow(10, ndigits);
- f = ceil(number * f) / f;
- return DBL2NUM(f);
+ int binexp;
+ frexp(number, &binexp);
+ if (float_round_overflow(ndigits, binexp)) return num;
+ if (number < 0.0 && float_round_underflow(ndigits, binexp))
+ return DBL2NUM(0.0);
+ f = pow(10, ndigits);
+ f = ceil(number * f) / f;
+ return DBL2NUM(f);
}
else {
- num = dbl2ival(ceil(number));
- if (ndigits < 0) num = rb_int_ceil(num, ndigits);
- return num;
+ num = dbl2ival(ceil(number));
+ if (ndigits < 0) num = rb_int_ceil(num, ndigits);
+ return num;
}
}
@@ -1986,13 +2282,13 @@ int_round_zero_p(VALUE num, int ndigits)
/* If 10**N / 2 > num, then return 0 */
/* We have log_256(10) > 0.415241 and log_256(1/2) = -0.125, so */
if (FIXNUM_P(num)) {
- bytes = sizeof(long);
+ bytes = sizeof(long);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- bytes = rb_big_size(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ bytes = rb_big_size(num);
}
else {
- bytes = NUM2LONG(rb_funcall(num, idSize, 0));
+ bytes = NUM2LONG(rb_funcall(num, idSize, 0));
}
return (-0.415241 * ndigits - 0.125 > bytes);
}
@@ -2002,7 +2298,7 @@ int_round_half_even(SIGNED_VALUE x, SIGNED_VALUE y)
{
SIGNED_VALUE z = +(x + y / 2) / y;
if ((z * y - x) * 2 == y) {
- z &= ~1;
+ z &= ~1;
}
return z * y;
}
@@ -2046,29 +2342,29 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
VALUE n, f, h, r;
if (int_round_zero_p(num, ndigits)) {
- return INT2FIX(0);
+ return INT2FIX(0);
}
f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
- SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
- int neg = x < 0;
- if (neg) x = -x;
- x = ROUND_CALL(mode, int_round, (x, y));
- if (neg) x = -x;
- return LONG2NUM(x);
+ SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
+ int neg = x < 0;
+ if (neg) x = -x;
+ x = ROUND_CALL(mode, int_round, (x, y));
+ if (neg) x = -x;
+ return LONG2NUM(x);
}
- if (RB_TYPE_P(f, T_FLOAT)) {
- /* then int_pow overflow */
- return INT2FIX(0);
+ if (RB_FLOAT_TYPE_P(f)) {
+ /* then int_pow overflow */
+ return INT2FIX(0);
}
h = rb_int_idiv(f, INT2FIX(2));
r = rb_int_modulo(num, f);
n = rb_int_minus(num, r);
r = rb_int_cmp(r, h);
if (FIXNUM_POSITIVE_P(r) ||
- (FIXNUM_ZERO_P(r) && ROUND_CALL(mode, int_half_p, (num, n, f)))) {
- n = rb_int_plus(n, f);
+ (FIXNUM_ZERO_P(r) && ROUND_CALL(mode, int_half_p, (num, n, f)))) {
+ n = rb_int_plus(n, f);
}
return n;
}
@@ -2076,48 +2372,47 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
static VALUE
rb_int_floor(VALUE num, int ndigits)
{
- VALUE f;
-
- if (int_round_zero_p(num, ndigits))
- return INT2FIX(0);
- f = int_pow(10, -ndigits);
+ VALUE f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
- SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
- int neg = x < 0;
- if (neg) x = -x + y - 1;
- x = x / y * y;
- if (neg) x = -x;
- return LONG2NUM(x);
+ SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
+ int neg = x < 0;
+ if (neg) x = -x + y - 1;
+ x = x / y * y;
+ if (neg) x = -x;
+ return LONG2NUM(x);
}
- if (RB_TYPE_P(f, T_FLOAT)) {
- /* then int_pow overflow */
- return INT2FIX(0);
+ else {
+ bool neg = int_neg_p(num);
+ if (neg) num = rb_int_minus(rb_int_plus(rb_int_uminus(num), f), INT2FIX(1));
+ num = rb_int_mul(rb_int_div(num, f), f);
+ if (neg) num = rb_int_uminus(num);
+ return num;
}
- return rb_int_minus(num, rb_int_modulo(num, f));
}
static VALUE
rb_int_ceil(VALUE num, int ndigits)
{
- VALUE f;
-
- if (int_round_zero_p(num, ndigits))
- return INT2FIX(0);
- f = int_pow(10, -ndigits);
+ VALUE f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
- SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
- int neg = x < 0;
- if (neg) x = -x;
- else x += y - 1;
- x = (x / y) * y;
- if (neg) x = -x;
- return LONG2NUM(x);
+ SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
+ int neg = x < 0;
+ if (neg) x = -x;
+ else x += y - 1;
+ x = (x / y) * y;
+ if (neg) x = -x;
+ return LONG2NUM(x);
}
- if (RB_TYPE_P(f, T_FLOAT)) {
- /* then int_pow overflow */
- return INT2FIX(0);
+ else {
+ bool neg = int_neg_p(num);
+ if (neg)
+ num = rb_int_uminus(num);
+ else
+ num = rb_int_plus(num, rb_int_minus(f, INT2FIX(1)));
+ num = rb_int_mul(rb_int_div(num, f), f);
+ if (neg) num = rb_int_uminus(num);
+ return num;
}
- return rb_int_plus(num, rb_int_minus(f, rb_int_modulo(num, f)));
}
VALUE
@@ -2127,79 +2422,82 @@ rb_int_truncate(VALUE num, int ndigits)
VALUE m;
if (int_round_zero_p(num, ndigits))
- return INT2FIX(0);
+ return INT2FIX(0);
f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
- SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
- int neg = x < 0;
- if (neg) x = -x;
- x = x / y * y;
- if (neg) x = -x;
- return LONG2NUM(x);
+ SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
+ int neg = x < 0;
+ if (neg) x = -x;
+ x = x / y * y;
+ if (neg) x = -x;
+ return LONG2NUM(x);
}
- if (RB_TYPE_P(f, T_FLOAT)) {
- /* then int_pow overflow */
- return INT2FIX(0);
+ if (RB_FLOAT_TYPE_P(f)) {
+ /* then int_pow overflow */
+ return INT2FIX(0);
}
m = rb_int_modulo(num, f);
if (int_neg_p(num)) {
- return rb_int_plus(num, rb_int_minus(f, m));
+ return rb_int_plus(num, rb_int_minus(f, m));
}
else {
- return rb_int_minus(num, m);
+ return rb_int_minus(num, m);
}
}
/*
* call-seq:
- * float.round([ndigits] [, half: mode]) -> integer or float
+ * round(ndigits = 0, half: :up]) -> integer or float
*
- * Returns +float+ rounded to the nearest value with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns +self+ rounded to the nearest value with
+ * a precision of +ndigits+ decimal digits.
+ *
+ * When +ndigits+ is non-negative, returns a float with +ndigits+
+ * after the decimal point (as available):
+ *
+ * f = 12345.6789
+ * f.round(1) # => 12345.7
+ * f.round(3) # => 12345.679
+ * f = -12345.6789
+ * f.round(1) # => -12345.7
+ * f.round(3) # => -12345.679
+ *
+ * When +ndigits+ is negative, returns an integer
+ * with at least <tt>ndigits.abs</tt> trailing zeros:
+ *
+ * f = 12345.6789
+ * f.round(0) # => 12346
+ * f.round(-3) # => 12000
+ * f = -12345.6789
+ * f.round(0) # => -12346
+ * f.round(-3) # => -12000
+ *
+ * If keyword argument +half+ is given,
+ * and +self+ is equidistant from the two candidate values,
+ * the rounding is according to the given +half+ value:
+ *
+ * - +:up+ or +nil+: round away from zero:
+ *
+ * 2.5.round(half: :up) # => 3
+ * 3.5.round(half: :up) # => 4
+ * (-2.5).round(half: :up) # => -3
+ *
+ * - +:down+: round toward zero:
+ *
+ * 2.5.round(half: :down) # => 2
+ * 3.5.round(half: :down) # => 3
+ * (-2.5).round(half: :down) # => -2
+ *
+ * - +:even+: round toward the candidate whose last nonzero digit is even:
+ *
+ * 2.5.round(half: :even) # => 2
+ * 3.5.round(half: :even) # => 4
+ * (-2.5).round(half: :even) # => -2
+ *
+ * Raises and exception if the value for +half+ is invalid.
+ *
+ * Related: Float#truncate.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
- *
- * Returns a floating point number when +ndigits+ is positive,
- * otherwise returns an integer.
- *
- * 1.4.round #=> 1
- * 1.5.round #=> 2
- * 1.6.round #=> 2
- * (-1.5).round #=> -2
- *
- * 1.234567.round(2) #=> 1.23
- * 1.234567.round(3) #=> 1.235
- * 1.234567.round(4) #=> 1.2346
- * 1.234567.round(5) #=> 1.23457
- *
- * 34567.89.round(-5) #=> 0
- * 34567.89.round(-4) #=> 30000
- * 34567.89.round(-3) #=> 35000
- * 34567.89.round(-2) #=> 34600
- * 34567.89.round(-1) #=> 34570
- * 34567.89.round(0) #=> 34568
- * 34567.89.round(1) #=> 34567.9
- * 34567.89.round(2) #=> 34567.89
- * 34567.89.round(3) #=> 34567.89
- *
- * If the optional +half+ keyword argument is given,
- * numbers that are half-way between two possible rounded values
- * will be rounded according to the specified tie-breaking +mode+:
- *
- * * <code>:up</code> or +nil+: round half away from zero (default)
- * * <code>:down</code>: round half toward zero
- * * <code>:even</code>: round half toward the nearest even number
- *
- * 2.5.round(half: :up) #=> 3
- * 2.5.round(half: :down) #=> 2
- * 2.5.round(half: :even) #=> 2
- * 3.5.round(half: :up) #=> 4
- * 3.5.round(half: :down) #=> 3
- * 3.5.round(half: :even) #=> 4
- * (-2.5).round(half: :up) #=> -3
- * (-2.5).round(half: :down) #=> -2
- * (-2.5).round(half: :even) #=> -2
*/
static VALUE
@@ -2211,32 +2509,32 @@ flo_round(int argc, VALUE *argv, VALUE num)
enum ruby_num_rounding_mode mode;
if (rb_scan_args(argc, argv, "01:", &nd, &opt)) {
- ndigits = NUM2INT(nd);
+ ndigits = NUM2INT(nd);
}
mode = rb_num_get_rounding_option(opt);
number = RFLOAT_VALUE(num);
if (number == 0.0) {
- return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
+ return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
}
if (ndigits < 0) {
- return rb_int_round(flo_to_i(num), ndigits, mode);
+ return rb_int_round(flo_to_i(num), ndigits, mode);
}
if (ndigits == 0) {
- x = ROUND_CALL(mode, round, (number, 1.0));
- return dbl2ival(x);
+ x = ROUND_CALL(mode, round, (number, 1.0));
+ return dbl2ival(x);
}
if (isfinite(number)) {
- int binexp;
- frexp(number, &binexp);
- if (float_round_overflow(ndigits, binexp)) return num;
- if (float_round_underflow(ndigits, binexp)) return DBL2NUM(0);
+ int binexp;
+ frexp(number, &binexp);
+ if (float_round_overflow(ndigits, binexp)) return num;
+ if (float_round_underflow(ndigits, binexp)) return DBL2NUM(0);
if (ndigits > 14) {
/* In this case, pow(10, ndigits) may not be accurate. */
return rb_flo_round_by_rational(argc, argv, num);
}
- f = pow(10, ndigits);
- x = ROUND_CALL(mode, round, (number, f));
- return DBL2NUM(x / f);
+ f = pow(10, ndigits);
+ x = ROUND_CALL(mode, round, (number, f));
+ return DBL2NUM(x / f);
}
return num;
}
@@ -2254,17 +2552,17 @@ float_round_overflow(int ndigits, int binexp)
If ndigits + exp <= 0, the result is 0 or "1e#{exp}", so
if ndigits + exp < 0, the result is 0.
We have:
- 2 ** (binexp-1) <= |number| < 2 ** binexp
- 10 ** ((binexp-1)/log_2(10)) <= |number| < 10 ** (binexp/log_2(10))
- If binexp >= 0, and since log_2(10) = 3.322259:
- 10 ** (binexp/4 - 1) < |number| < 10 ** (binexp/3)
- floor(binexp/4) <= exp <= ceil(binexp/3)
- If binexp <= 0, swap the /4 and the /3
- So if ndigits + floor(binexp/(4 or 3)) >= float_dig, the result is number
- If ndigits + ceil(binexp/(3 or 4)) < 0 the result is 0
+ 2 ** (binexp-1) <= |number| < 2 ** binexp
+ 10 ** ((binexp-1)/log_2(10)) <= |number| < 10 ** (binexp/log_2(10))
+ If binexp >= 0, and since log_2(10) = 3.322259:
+ 10 ** (binexp/4 - 1) < |number| < 10 ** (binexp/3)
+ floor(binexp/4) <= exp <= ceil(binexp/3)
+ If binexp <= 0, swap the /4 and the /3
+ So if ndigits + floor(binexp/(4 or 3)) >= float_dig, the result is number
+ If ndigits + ceil(binexp/(3 or 4)) < 0 the result is 0
*/
if (ndigits >= float_dig - (binexp > 0 ? binexp / 4 : binexp / 3 - 1)) {
- return TRUE;
+ return TRUE;
}
return FALSE;
}
@@ -2273,27 +2571,26 @@ static int
float_round_underflow(int ndigits, int binexp)
{
if (ndigits < - (binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
- return TRUE;
+ return TRUE;
}
return FALSE;
}
/*
* call-seq:
- * float.to_i -> integer
- * float.to_int -> integer
+ * to_i -> integer
*
- * Returns the +float+ truncated to an Integer.
+ * Returns +self+ truncated to an Integer.
*
- * 1.2.to_i #=> 1
- * (-1.2).to_i #=> -1
+ * 1.2.to_i # => 1
+ * (-1.2).to_i # => -1
*
- * Note that the limited precision of floating point arithmetic
- * might lead to surprising results:
+ * Note that the limited precision of floating-point arithmetic
+ * may lead to surprising results:
*
- * (0.3 / 0.1).to_i #=> 2 (!)
+ * (0.3 / 0.1).to_i # => 2 (!)
*
- * #to_int is an alias for #to_i.
+ * Float#to_int is an alias for Float#to_i.
*/
static VALUE
@@ -2309,44 +2606,56 @@ flo_to_i(VALUE num)
/*
* call-seq:
- * float.truncate([ndigits]) -> integer or float
+ * truncate(ndigits = 0) -> float or integer
*
- * Returns +float+ truncated (toward zero) to
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns +self+ truncated (toward zero) to
+ * a precision of +ndigits+ decimal digits.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
+ * When +ndigits+ is positive, returns a float with +ndigits+ digits
+ * after the decimal point (as available):
+ *
+ * f = 12345.6789
+ * f.truncate(1) # => 12345.6
+ * f.truncate(3) # => 12345.678
+ * f = -12345.6789
+ * f.truncate(1) # => -12345.6
+ * f.truncate(3) # => -12345.678
*
- * Returns a floating point number when +ndigits+ is positive,
- * otherwise returns an integer.
+ * When +ndigits+ is negative, returns an integer
+ * with at least <tt>ndigits.abs</tt> trailing zeros:
*
- * 2.8.truncate #=> 2
- * (-2.8).truncate #=> -2
- * 1.234567.truncate(2) #=> 1.23
- * 34567.89.truncate(-2) #=> 34500
+ * f = 12345.6789
+ * f.truncate(0) # => 12345
+ * f.truncate(-3) # => 12000
+ * f = -12345.6789
+ * f.truncate(0) # => -12345
+ * f.truncate(-3) # => -12000
*
- * Note that the limited precision of floating point arithmetic
- * might lead to surprising results:
+ * Note that the limited precision of floating-point arithmetic
+ * may lead to surprising results:
*
* (0.3 / 0.1).truncate #=> 2 (!)
+ *
+ * Related: Float#round.
+ *
*/
static VALUE
flo_truncate(int argc, VALUE *argv, VALUE num)
{
if (signbit(RFLOAT_VALUE(num)))
- return flo_ceil(argc, argv, num);
+ return flo_ceil(argc, argv, num);
else
- return flo_floor(argc, argv, num);
+ return flo_floor(argc, argv, num);
}
/*
* call-seq:
- * num.floor([ndigits]) -> integer or float
+ * floor(digits = 0) -> integer or float
*
- * Returns the largest number less than or equal to +num+ with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns the largest number that is less than or equal to +self+ with
+ * a precision of +digits+ decimal digits.
*
- * Numeric implements this by converting its value to a Float and
+ * \Numeric implements this by converting +self+ to a Float and
* invoking Float#floor.
*/
@@ -2358,12 +2667,12 @@ num_floor(int argc, VALUE *argv, VALUE num)
/*
* call-seq:
- * num.ceil([ndigits]) -> integer or float
+ * ceil(digits = 0) -> integer or float
*
- * Returns the smallest number greater than or equal to +num+ with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns the smallest number that is greater than or equal to +self+ with
+ * a precision of +digits+ decimal digits.
*
- * Numeric implements this by converting its value to a Float and
+ * \Numeric implements this by converting +self+ to a Float and
* invoking Float#ceil.
*/
@@ -2375,12 +2684,12 @@ num_ceil(int argc, VALUE *argv, VALUE num)
/*
* call-seq:
- * num.round([ndigits]) -> integer or float
+ * round(digits = 0) -> integer or float
*
- * Returns +num+ rounded to the nearest value with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns +self+ rounded to the nearest value with
+ * a precision of +digits+ decimal digits.
*
- * Numeric implements this by converting its value to a Float and
+ * \Numeric implements this by converting +self+ to a Float and
* invoking Float#round.
*/
@@ -2392,12 +2701,12 @@ num_round(int argc, VALUE* argv, VALUE num)
/*
* call-seq:
- * num.truncate([ndigits]) -> integer or float
+ * truncate(digits = 0) -> integer or float
*
- * Returns +num+ truncated (toward zero) to
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns +self+ truncated (toward zero) to
+ * a precision of +digits+ decimal digits.
*
- * Numeric implements this by converting its value to a Float and
+ * \Numeric implements this by converting +self+ to a Float and
* invoking Float#truncate.
*/
@@ -2411,41 +2720,43 @@ double
ruby_float_step_size(double beg, double end, double unit, int excl)
{
const double epsilon = DBL_EPSILON;
- double n, err;
+ double d, n, err;
if (unit == 0) {
return HUGE_VAL;
}
if (isinf(unit)) {
- return unit > 0 ? beg <= end : beg >= end;
+ return unit > 0 ? beg <= end : beg >= end;
}
n= (end - beg)/unit;
err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon;
if (err>0.5) err=0.5;
if (excl) {
- if (n<=0) return 0;
- if (n<1)
- n = 0;
- else
- n = floor(n - err);
+ if (n<=0) return 0;
+ if (n<1)
+ n = 0;
+ else
+ n = floor(n - err);
+ d = +((n + 1) * unit) + beg;
if (beg < end) {
- if ((n+1)*unit+beg < end)
+ if (d < end)
n++;
}
else if (beg > end) {
- if ((n+1)*unit+beg > end)
+ if (d > end)
n++;
}
}
else {
- if (n<0) return 0;
- n = floor(n + err);
+ if (n<0) return 0;
+ n = floor(n + err);
+ d = +((n + 1) * unit) + beg;
if (beg < end) {
- if ((n+1)*unit+beg <= end)
+ if (d <= end)
n++;
}
else if (beg > end) {
- if ((n+1)*unit+beg >= end)
+ if (d >= end)
n++;
}
}
@@ -2455,30 +2766,30 @@ ruby_float_step_size(double beg, double end, double unit, int excl)
int
ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless)
{
- if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) {
+ if (RB_FLOAT_TYPE_P(from) || RB_FLOAT_TYPE_P(to) || RB_FLOAT_TYPE_P(step)) {
double unit = NUM2DBL(step);
- double beg = NUM2DBL(from);
+ double beg = NUM2DBL(from);
double end = (allow_endless && NIL_P(to)) ? (unit < 0 ? -1 : 1)*HUGE_VAL : NUM2DBL(to);
- double n = ruby_float_step_size(beg, end, unit, excl);
- long i;
-
- if (isinf(unit)) {
- /* if unit is infinity, i*unit+beg is NaN */
- if (n) rb_yield(DBL2NUM(beg));
- }
- else if (unit == 0) {
- VALUE val = DBL2NUM(beg);
- for (;;)
- rb_yield(val);
- }
- else {
- for (i=0; i<n; i++) {
- double d = i*unit+beg;
- if (unit >= 0 ? end < d : d < end) d = end;
- rb_yield(DBL2NUM(d));
- }
- }
- return TRUE;
+ double n = ruby_float_step_size(beg, end, unit, excl);
+ long i;
+
+ if (isinf(unit)) {
+ /* if unit is infinity, i*unit+beg is NaN */
+ if (n) rb_yield(DBL2NUM(beg));
+ }
+ else if (unit == 0) {
+ VALUE val = DBL2NUM(beg);
+ for (;;)
+ rb_yield(val);
+ }
+ else {
+ for (i=0; i<n; i++) {
+ double d = i*unit+beg;
+ if (unit >= 0 ? end < d : d < end) d = end;
+ rb_yield(DBL2NUM(d));
+ }
+ }
+ return TRUE;
}
return FALSE;
}
@@ -2487,45 +2798,45 @@ VALUE
ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
{
if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
- long delta, diff;
-
- diff = FIX2LONG(step);
- if (diff == 0) {
- return DBL2NUM(HUGE_VAL);
- }
- delta = FIX2LONG(to) - FIX2LONG(from);
- if (diff < 0) {
- diff = -diff;
- delta = -delta;
- }
- if (excl) {
- delta--;
- }
- if (delta < 0) {
- return INT2FIX(0);
- }
- return ULONG2NUM(delta / diff + 1UL);
- }
- else if (RB_TYPE_P(from, T_FLOAT) || RB_TYPE_P(to, T_FLOAT) || RB_TYPE_P(step, T_FLOAT)) {
- double n = ruby_float_step_size(NUM2DBL(from), NUM2DBL(to), NUM2DBL(step), excl);
-
- if (isinf(n)) return DBL2NUM(n);
- if (POSFIXABLE(n)) return LONG2FIX((long)n);
- return rb_dbl2big(n);
+ long delta, diff;
+
+ diff = FIX2LONG(step);
+ if (diff == 0) {
+ return DBL2NUM(HUGE_VAL);
+ }
+ delta = FIX2LONG(to) - FIX2LONG(from);
+ if (diff < 0) {
+ diff = -diff;
+ delta = -delta;
+ }
+ if (excl) {
+ delta--;
+ }
+ if (delta < 0) {
+ return INT2FIX(0);
+ }
+ return ULONG2NUM(delta / diff + 1UL);
+ }
+ else if (RB_FLOAT_TYPE_P(from) || RB_FLOAT_TYPE_P(to) || RB_FLOAT_TYPE_P(step)) {
+ double n = ruby_float_step_size(NUM2DBL(from), NUM2DBL(to), NUM2DBL(step), excl);
+
+ if (isinf(n)) return DBL2NUM(n);
+ if (POSFIXABLE(n)) return LONG2FIX((long)n);
+ return rb_dbl2big(n);
}
else {
- VALUE result;
- ID cmp = '>';
- switch (rb_cmpint(rb_num_coerce_cmp(step, INT2FIX(0), id_cmp), step, INT2FIX(0))) {
- case 0: return DBL2NUM(HUGE_VAL);
- case -1: cmp = '<'; break;
- }
- if (RTEST(rb_funcall(from, cmp, 1, to))) return INT2FIX(0);
- result = rb_funcall(rb_funcall(to, '-', 1, from), id_div, 1, step);
- if (!excl || RTEST(rb_funcall(rb_funcall(from, '+', 1, rb_funcall(result, '*', 1, step)), cmp, 1, to))) {
- result = rb_funcall(result, '+', 1, INT2FIX(1));
- }
- return result;
+ VALUE result;
+ ID cmp = '>';
+ switch (rb_cmpint(rb_num_coerce_cmp(step, INT2FIX(0), id_cmp), step, INT2FIX(0))) {
+ case 0: return DBL2NUM(HUGE_VAL);
+ case -1: cmp = '<'; break;
+ }
+ if (RTEST(rb_funcall(from, cmp, 1, to))) return INT2FIX(0);
+ result = rb_funcall(rb_funcall(to, '-', 1, from), id_div, 1, step);
+ if (!excl || RTEST(rb_funcall(rb_funcall(from, '+', 1, rb_funcall(result, '*', 1, step)), cmp, 1, to))) {
+ result = rb_funcall(result, '+', 1, INT2FIX(1));
+ }
+ return result;
}
}
@@ -2537,17 +2848,17 @@ num_step_negative_p(VALUE num)
VALUE r;
if (FIXNUM_P(num)) {
- if (method_basic_p(rb_cInteger))
- return (SIGNED_VALUE)num < 0;
+ if (method_basic_p(rb_cInteger))
+ return (SIGNED_VALUE)num < 0;
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- if (method_basic_p(rb_cInteger))
- return BIGNUM_NEGATIVE_P(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ if (method_basic_p(rb_cInteger))
+ return BIGNUM_NEGATIVE_P(num);
}
r = rb_check_funcall(num, '>', 1, &zero);
- if (r == Qundef) {
- coerce_failed(num, INT2FIX(0));
+ if (UNDEF_P(r)) {
+ coerce_failed(num, INT2FIX(0));
}
return !RTEST(r);
}
@@ -2559,19 +2870,19 @@ num_step_extract_args(int argc, const VALUE *argv, VALUE *to, VALUE *step, VALUE
argc = rb_scan_args(argc, argv, "02:", to, step, &hash);
if (!NIL_P(hash)) {
- ID keys[2];
- VALUE values[2];
- keys[0] = id_to;
- keys[1] = id_by;
- rb_get_kwargs(hash, keys, 0, 2, values);
- if (values[0] != Qundef) {
- if (argc > 0) rb_raise(rb_eArgError, "to is given twice");
- *to = values[0];
- }
- if (values[1] != Qundef) {
- if (argc > 1) rb_raise(rb_eArgError, "step is given twice");
- *by = values[1];
- }
+ ID keys[2];
+ VALUE values[2];
+ keys[0] = id_to;
+ keys[1] = id_by;
+ rb_get_kwargs(hash, keys, 0, 2, values);
+ if (!UNDEF_P(values[0])) {
+ if (argc > 0) rb_raise(rb_eArgError, "to is given twice");
+ *to = values[0];
+ }
+ if (!UNDEF_P(values[1])) {
+ if (argc > 1) rb_raise(rb_eArgError, "step is given twice");
+ *by = values[1];
+ }
}
return argc;
@@ -2581,7 +2892,7 @@ static int
num_step_check_fix_args(int argc, VALUE *to, VALUE *step, VALUE by, int fix_nil, int allow_zero_step)
{
int desc;
- if (by != Qundef) {
+ if (!UNDEF_P(by)) {
*step = by;
}
else {
@@ -2594,7 +2905,7 @@ num_step_check_fix_args(int argc, VALUE *to, VALUE *step, VALUE by, int fix_nil,
rb_raise(rb_eArgError, "step can't be 0");
}
if (NIL_P(*step)) {
- *step = INT2FIX(1);
+ *step = INT2FIX(1);
}
desc = num_step_negative_p(*step);
if (fix_nil && NIL_P(*to)) {
@@ -2625,25 +2936,89 @@ num_step_size(VALUE from, VALUE args, VALUE eobj)
/*
* call-seq:
- * num.step(by: step, to: limit) {|i| block } -> self
- * num.step(by: step, to: limit) -> an_enumerator
- * num.step(by: step, to: limit) -> an_arithmetic_sequence
- * num.step(limit=nil, step=1) {|i| block } -> self
- * num.step(limit=nil, step=1) -> an_enumerator
- * num.step(limit=nil, step=1) -> an_arithmetic_sequence
- *
- * Invokes the given block with the sequence of numbers starting at +num+,
- * incremented by +step+ (defaulted to +1+) on each call.
- *
- * The loop finishes when the value to be passed to the block is greater than
- * +limit+ (if +step+ is positive) or less than +limit+ (if +step+ is
- * negative), where +limit+ is defaulted to infinity.
- *
- * In the recommended keyword argument style, either or both of
- * +step+ and +limit+ (default infinity) can be omitted. In the
- * fixed position argument style, zero as a step
- * (i.e. <code>num.step(limit, 0)</code>) is not allowed for historical
- * compatibility reasons.
+ * step(to = nil, by = 1) {|n| ... } -> self
+ * step(to = nil, by = 1) -> enumerator
+ * step(to = nil, by: 1) {|n| ... } -> self
+ * step(to = nil, by: 1) -> enumerator
+ * step(by: 1, to: ) {|n| ... } -> self
+ * step(by: 1, to: ) -> enumerator
+ * step(by: , to: nil) {|n| ... } -> self
+ * step(by: , to: nil) -> enumerator
+ *
+ * Generates a sequence of numbers; with a block given, traverses the sequence.
+ *
+ * Of the Core and Standard Library classes,
+ * Integer, Float, and Rational use this implementation.
+ *
+ * A quick example:
+ *
+ * squares = []
+ * 1.step(by: 2, to: 10) {|i| squares.push(i*i) }
+ * squares # => [1, 9, 25, 49, 81]
+ *
+ * The generated sequence:
+ *
+ * - Begins with +self+.
+ * - Continues at intervals of +step+ (which may not be zero).
+ * - Ends with the last number that is within or equal to +limit+;
+ * that is, less than or equal to +limit+ if +step+ is positive,
+ * greater than or equal to +limit+ if +step+ is negative.
+ * If +limit+ is not given, the sequence is of infinite length.
+ *
+ * If a block is given, calls the block with each number in the sequence;
+ * returns +self+. If no block is given, returns an Enumerator::ArithmeticSequence.
+ *
+ * <b>Keyword Arguments</b>
+ *
+ * With keyword arguments +by+ and +to+,
+ * their values (or defaults) determine the step and limit:
+ *
+ * # Both keywords given.
+ * squares = []
+ * 4.step(by: 2, to: 10) {|i| squares.push(i*i) } # => 4
+ * squares # => [16, 36, 64, 100]
+ * cubes = []
+ * 3.step(by: -1.5, to: -3) {|i| cubes.push(i*i*i) } # => 3
+ * cubes # => [27.0, 3.375, 0.0, -3.375, -27.0]
+ * squares = []
+ * 1.2.step(by: 0.2, to: 2.0) {|f| squares.push(f*f) }
+ * squares # => [1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]
+ *
+ * squares = []
+ * Rational(6/5).step(by: 0.2, to: 2.0) {|r| squares.push(r*r) }
+ * squares # => [1.0, 1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]
+ *
+ * # Only keyword to given.
+ * squares = []
+ * 4.step(to: 10) {|i| squares.push(i*i) } # => 4
+ * squares # => [16, 25, 36, 49, 64, 81, 100]
+ * # Only by given.
+ *
+ * # Only keyword by given
+ * squares = []
+ * 4.step(by:2) {|i| squares.push(i*i); break if i > 10 }
+ * squares # => [16, 36, 64, 100, 144]
+ *
+ * # No block given.
+ * e = 3.step(by: -1.5, to: -3) # => (3.step(by: -1.5, to: -3))
+ * e.class # => Enumerator::ArithmeticSequence
+ *
+ * <b>Positional Arguments</b>
+ *
+ * With optional positional arguments +limit+ and +step+,
+ * their values (or defaults) determine the step and limit:
+ *
+ * squares = []
+ * 4.step(10, 2) {|i| squares.push(i*i) } # => 4
+ * squares # => [16, 36, 64, 100]
+ * squares = []
+ * 4.step(10) {|i| squares.push(i*i) }
+ * squares # => [16, 25, 36, 49, 64, 81, 100]
+ * squares = []
+ * 4.step {|i| squares.push(i*i); break if i > 10 } # => nil
+ * squares # => [16, 25, 36, 49, 64, 81, 100, 121]
+ *
+ * <b>Implementation Notes</b>
*
* If all the arguments are integers, the loop operates using an integer
* counter.
@@ -2651,32 +3026,8 @@ num_step_size(VALUE from, VALUE args, VALUE eobj)
* If any of the arguments are floating point numbers, all are converted
* to floats, and the loop is executed
* <i>floor(n + n*Float::EPSILON) + 1</i> times,
- * where <i>n = (limit - num)/step</i>.
- *
- * Otherwise, the loop starts at +num+, uses either the
- * less-than (<code><</code>) or greater-than (<code>></code>) operator
- * to compare the counter against +limit+,
- * and increments itself using the <code>+</code> operator.
- *
- * If no block is given, an Enumerator is returned instead.
- * Especially, the enumerator is an Enumerator::ArithmeticSequence
- * if both +limit+ and +step+ are kind of Numeric or <code>nil</code>.
- *
- * For example:
- *
- * p 1.step.take(4)
- * p 10.step(by: -1).take(4)
- * 3.step(to: 5) {|i| print i, " " }
- * 1.step(10, 2) {|i| print i, " " }
- * Math::E.step(to: Math::PI, by: 0.2) {|f| print f, " " }
+ * where <i>n = (limit - self)/step</i>.
*
- * Will produce:
- *
- * [1, 2, 3, 4]
- * [10, 9, 8, 7]
- * 3 4 5
- * 1 3 5 7 9
- * 2.718281828459045 2.9182818284590453 3.118281828459045
*/
static VALUE
@@ -2689,7 +3040,7 @@ num_step(int argc, VALUE *argv, VALUE from)
VALUE by = Qundef;
num_step_extract_args(argc, argv, &to, &step, &by);
- if (by != Qundef) {
+ if (!UNDEF_P(by)) {
step = by;
}
if (NIL_P(step)) {
@@ -2704,53 +3055,53 @@ num_step(int argc, VALUE *argv, VALUE from)
num_step_size, from, to, step, FALSE);
}
- return SIZED_ENUMERATOR(from, 2, ((VALUE [2]){to, step}), num_step_size);
+ return SIZED_ENUMERATOR_KW(from, 2, ((VALUE [2]){to, step}), num_step_size, FALSE);
}
desc = num_step_scan_args(argc, argv, &to, &step, TRUE, FALSE);
if (rb_equal(step, INT2FIX(0))) {
- inf = 1;
+ inf = 1;
}
- else if (RB_TYPE_P(to, T_FLOAT)) {
- double f = RFLOAT_VALUE(to);
- inf = isinf(f) && (signbit(f) ? desc : !desc);
+ else if (RB_FLOAT_TYPE_P(to)) {
+ double f = RFLOAT_VALUE(to);
+ inf = isinf(f) && (signbit(f) ? desc : !desc);
}
else inf = 0;
if (FIXNUM_P(from) && (inf || FIXNUM_P(to)) && FIXNUM_P(step)) {
- long i = FIX2LONG(from);
- long diff = FIX2LONG(step);
-
- if (inf) {
- for (;; i += diff)
- rb_yield(LONG2FIX(i));
- }
- else {
- long end = FIX2LONG(to);
-
- if (desc) {
- for (; i >= end; i += diff)
- rb_yield(LONG2FIX(i));
- }
- else {
- for (; i <= end; i += diff)
- rb_yield(LONG2FIX(i));
- }
- }
+ long i = FIX2LONG(from);
+ long diff = FIX2LONG(step);
+
+ if (inf) {
+ for (;; i += diff)
+ rb_yield(LONG2FIX(i));
+ }
+ else {
+ long end = FIX2LONG(to);
+
+ if (desc) {
+ for (; i >= end; i += diff)
+ rb_yield(LONG2FIX(i));
+ }
+ else {
+ for (; i <= end; i += diff)
+ rb_yield(LONG2FIX(i));
+ }
+ }
}
else if (!ruby_float_step(from, to, step, FALSE, FALSE)) {
- VALUE i = from;
+ VALUE i = from;
- if (inf) {
- for (;; i = rb_funcall(i, '+', 1, step))
- rb_yield(i);
- }
- else {
- ID cmp = desc ? '<' : '>';
+ if (inf) {
+ for (;; i = rb_funcall(i, '+', 1, step))
+ rb_yield(i);
+ }
+ else {
+ ID cmp = desc ? '<' : '>';
- for (; !RTEST(rb_funcall(i, cmp, 1, to)); i = rb_funcall(i, '+', 1, step))
- rb_yield(i);
- }
+ for (; !RTEST(rb_funcall(i, cmp, 1, to)); i = rb_funcall(i, '+', 1, step))
+ rb_yield(i);
+ }
}
return from;
}
@@ -2769,7 +3120,7 @@ out_of_range_float(char (*pbuf)[24], VALUE val)
#define FLOAT_OUT_OF_RANGE(val, type) do { \
char buf[24]; \
rb_raise(rb_eRangeError, "float %s out of range of "type, \
- out_of_range_float(&buf, (val))); \
+ out_of_range_float(&buf, (val))); \
} while (0)
#define LONG_MIN_MINUS_ONE ((double)LONG_MIN-1)
@@ -2785,26 +3136,26 @@ rb_num2long(VALUE val)
{
again:
if (NIL_P(val)) {
- rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
+ rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
}
if (FIXNUM_P(val)) return FIX2LONG(val);
- else if (RB_TYPE_P(val, T_FLOAT)) {
- if (RFLOAT_VALUE(val) < LONG_MAX_PLUS_ONE
- && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
- return (long)RFLOAT_VALUE(val);
- }
- else {
- FLOAT_OUT_OF_RANGE(val, "integer");
- }
+ else if (RB_FLOAT_TYPE_P(val)) {
+ if (RFLOAT_VALUE(val) < LONG_MAX_PLUS_ONE
+ && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
+ return (long)RFLOAT_VALUE(val);
+ }
+ else {
+ FLOAT_OUT_OF_RANGE(val, "integer");
+ }
}
- else if (RB_TYPE_P(val, T_BIGNUM)) {
- return rb_big2long(val);
+ else if (RB_BIGNUM_TYPE_P(val)) {
+ return rb_big2long(val);
}
else {
- val = rb_to_int(val);
- goto again;
+ val = rb_to_int(val);
+ goto again;
}
}
@@ -2822,20 +3173,20 @@ rb_num2ulong_internal(VALUE val, int *wrap_p)
*wrap_p = l < 0;
return (unsigned long)l;
}
- else if (RB_TYPE_P(val, T_FLOAT)) {
- double d = RFLOAT_VALUE(val);
- if (d < ULONG_MAX_PLUS_ONE && LONG_MIN_MINUS_ONE_IS_LESS_THAN(d)) {
- if (wrap_p)
- *wrap_p = d <= -1.0; /* NUM2ULONG(v) uses v.to_int conceptually. */
- if (0 <= d)
- return (unsigned long)d;
- return (unsigned long)(long)d;
- }
- else {
- FLOAT_OUT_OF_RANGE(val, "integer");
- }
- }
- else if (RB_TYPE_P(val, T_BIGNUM)) {
+ else if (RB_FLOAT_TYPE_P(val)) {
+ double d = RFLOAT_VALUE(val);
+ if (d < ULONG_MAX_PLUS_ONE && LONG_MIN_MINUS_ONE_IS_LESS_THAN(d)) {
+ if (wrap_p)
+ *wrap_p = d <= -1.0; /* NUM2ULONG(v) uses v.to_int conceptually. */
+ if (0 <= d)
+ return (unsigned long)d;
+ return (unsigned long)(long)d;
+ }
+ else {
+ FLOAT_OUT_OF_RANGE(val, "integer");
+ }
+ }
+ else if (RB_BIGNUM_TYPE_P(val)) {
{
unsigned long ul = rb_big2ulong(val);
if (wrap_p)
@@ -2859,7 +3210,7 @@ void
rb_out_of_int(SIGNED_VALUE num)
{
rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `int'",
- num, num < 0 ? "small" : "big");
+ num, num < 0 ? "small" : "big");
}
#if SIZEOF_INT < SIZEOF_LONG
@@ -2867,7 +3218,7 @@ static void
check_int(long num)
{
if ((long)(int)num != num) {
- rb_out_of_int(num);
+ rb_out_of_int(num);
}
}
@@ -2875,14 +3226,14 @@ static void
check_uint(unsigned long num, int sign)
{
if (sign) {
- /* minus */
- if (num < (unsigned long)INT_MIN)
- rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned int'", (long)num);
+ /* minus */
+ if (num < (unsigned long)INT_MIN)
+ rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned int'", (long)num);
}
else {
- /* plus */
- if (UINT_MAX < num)
- rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
+ /* plus */
+ if (UINT_MAX < num)
+ rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
}
}
@@ -2920,11 +3271,11 @@ rb_fix2uint(VALUE val)
unsigned long num;
if (!FIXNUM_P(val)) {
- return rb_num2uint(val);
+ return rb_num2uint(val);
}
num = FIX2ULONG(val);
- check_uint(num, rb_num_negative_int_p(val));
+ check_uint(num, FIXNUM_NEGATIVE_P(val));
return num;
}
#else
@@ -2958,14 +3309,14 @@ static void
rb_out_of_short(SIGNED_VALUE num)
{
rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `short'",
- num, num < 0 ? "small" : "big");
+ num, num < 0 ? "small" : "big");
}
static void
check_short(long num)
{
if ((long)(short)num != num) {
- rb_out_of_short(num);
+ rb_out_of_short(num);
}
}
@@ -2973,14 +3324,14 @@ static void
check_ushort(unsigned long num, int sign)
{
if (sign) {
- /* minus */
- if (num < (unsigned long)SHRT_MIN)
- rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned short'", (long)num);
+ /* minus */
+ if (num < (unsigned long)SHRT_MIN)
+ rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned short'", (long)num);
}
else {
- /* plus */
- if (USHRT_MAX < num)
- rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned short'", num);
+ /* plus */
+ if (USHRT_MAX < num)
+ rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned short'", num);
}
}
@@ -3018,11 +3369,11 @@ rb_fix2ushort(VALUE val)
unsigned long num;
if (!FIXNUM_P(val)) {
- return rb_num2ushort(val);
+ return rb_num2ushort(val);
}
num = FIX2ULONG(val);
- check_ushort(num, rb_num_negative_int_p(val));
+ check_ushort(num, FIXNUM_NEGATIVE_P(val));
return num;
}
@@ -3035,7 +3386,7 @@ rb_num2fix(VALUE val)
v = rb_num2long(val);
if (!FIXABLE(v))
- rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
+ rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
return LONG2FIX(v);
}
@@ -3056,28 +3407,28 @@ LONG_LONG
rb_num2ll(VALUE val)
{
if (NIL_P(val)) {
- rb_raise(rb_eTypeError, "no implicit conversion from nil");
+ rb_raise(rb_eTypeError, "no implicit conversion from nil");
}
if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
- else if (RB_TYPE_P(val, T_FLOAT)) {
- double d = RFLOAT_VALUE(val);
- if (d < LLONG_MAX_PLUS_ONE && (LLONG_MIN_MINUS_ONE_IS_LESS_THAN(d))) {
- return (LONG_LONG)d;
- }
- else {
- FLOAT_OUT_OF_RANGE(val, "long long");
- }
+ else if (RB_FLOAT_TYPE_P(val)) {
+ double d = RFLOAT_VALUE(val);
+ if (d < LLONG_MAX_PLUS_ONE && (LLONG_MIN_MINUS_ONE_IS_LESS_THAN(d))) {
+ return (LONG_LONG)d;
+ }
+ else {
+ FLOAT_OUT_OF_RANGE(val, "long long");
+ }
}
- else if (RB_TYPE_P(val, T_BIGNUM)) {
- return rb_big2ll(val);
+ else if (RB_BIGNUM_TYPE_P(val)) {
+ return rb_big2ll(val);
}
else if (RB_TYPE_P(val, T_STRING)) {
- rb_raise(rb_eTypeError, "no implicit conversion from string");
+ rb_raise(rb_eTypeError, "no implicit conversion from string");
}
else if (RB_TYPE_P(val, T_TRUE) || RB_TYPE_P(val, T_FALSE)) {
- rb_raise(rb_eTypeError, "no implicit conversion from boolean");
+ rb_raise(rb_eTypeError, "no implicit conversion from boolean");
}
val = rb_to_int(val);
@@ -3087,31 +3438,31 @@ rb_num2ll(VALUE val)
unsigned LONG_LONG
rb_num2ull(VALUE val)
{
- if (RB_TYPE_P(val, T_NIL)) {
- rb_raise(rb_eTypeError, "no implicit conversion from nil");
+ if (NIL_P(val)) {
+ rb_raise(rb_eTypeError, "no implicit conversion from nil");
}
- else if (RB_TYPE_P(val, T_FIXNUM)) {
- return (LONG_LONG)FIX2LONG(val); /* this is FIX2LONG, intended */
+ else if (FIXNUM_P(val)) {
+ return (LONG_LONG)FIX2LONG(val); /* this is FIX2LONG, intended */
}
- else if (RB_TYPE_P(val, T_FLOAT)) {
- double d = RFLOAT_VALUE(val);
- if (d < ULLONG_MAX_PLUS_ONE && LLONG_MIN_MINUS_ONE_IS_LESS_THAN(d)) {
- if (0 <= d)
- return (unsigned LONG_LONG)d;
- return (unsigned LONG_LONG)(LONG_LONG)d;
- }
- else {
- FLOAT_OUT_OF_RANGE(val, "unsigned long long");
- }
+ else if (RB_FLOAT_TYPE_P(val)) {
+ double d = RFLOAT_VALUE(val);
+ if (d < ULLONG_MAX_PLUS_ONE && LLONG_MIN_MINUS_ONE_IS_LESS_THAN(d)) {
+ if (0 <= d)
+ return (unsigned LONG_LONG)d;
+ return (unsigned LONG_LONG)(LONG_LONG)d;
+ }
+ else {
+ FLOAT_OUT_OF_RANGE(val, "unsigned long long");
+ }
}
- else if (RB_TYPE_P(val, T_BIGNUM)) {
- return rb_big2ull(val);
+ else if (RB_BIGNUM_TYPE_P(val)) {
+ return rb_big2ull(val);
}
else if (RB_TYPE_P(val, T_STRING)) {
- rb_raise(rb_eTypeError, "no implicit conversion from string");
+ rb_raise(rb_eTypeError, "no implicit conversion from string");
}
else if (RB_TYPE_P(val, T_TRUE) || RB_TYPE_P(val, T_FALSE)) {
- rb_raise(rb_eTypeError, "no implicit conversion from boolean");
+ rb_raise(rb_eTypeError, "no implicit conversion from boolean");
}
val = rb_to_int(val);
@@ -3124,8 +3475,93 @@ rb_num2ull(VALUE val)
*
* Document-class: Integer
*
- * Holds Integer values. You cannot add a singleton method to an
- * Integer object, any attempt to do so will raise a TypeError.
+ * An \Integer object represents an integer value.
+ *
+ * You can create an \Integer object explicitly with:
+ *
+ * - An {integer literal}[rdoc-ref:syntax/literals.rdoc@Integer+Literals].
+ *
+ * You can convert certain objects to Integers with:
+ *
+ * - \Method #Integer.
+ *
+ * An attempt to add a singleton method to an instance of this class
+ * causes an exception to be raised.
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere. \Class \Integer:
+ *
+ * - Inherits from {class Numeric}[rdoc-ref:Numeric@What-27s+Here].
+ *
+ * Here, class \Integer provides methods for:
+ *
+ * - {Querying}[rdoc-ref:Integer@Querying]
+ * - {Comparing}[rdoc-ref:Integer@Comparing]
+ * - {Converting}[rdoc-ref:Integer@Converting]
+ * - {Other}[rdoc-ref:Integer@Other]
+ *
+ * === Querying
+ *
+ * - #allbits?: Returns whether all bits in +self+ are set.
+ * - #anybits?: Returns whether any bits in +self+ are set.
+ * - #nobits?: Returns whether no bits in +self+ are set.
+ *
+ * === Comparing
+ *
+ * - #<: Returns whether +self+ is less than the given value.
+ * - #<=: Returns whether +self+ is less than or equal to the given value.
+ * - #<=>: Returns a number indicating whether +self+ is less than, equal
+ * to, or greater than the given value.
+ * - #== (aliased as #===): Returns whether +self+ is equal to the given
+ * value.
+ * - #>: Returns whether +self+ is greater than the given value.
+ * - #>=: Returns whether +self+ is greater than or equal to the given value.
+ *
+ * === Converting
+ *
+ * - ::sqrt: Returns the integer square root of the given value.
+ * - ::try_convert: Returns the given value converted to an \Integer.
+ * - #% (aliased as #modulo): Returns +self+ modulo the given value.
+ * - #&: Returns the bitwise AND of +self+ and the given value.
+ * - #*: Returns the product of +self+ and the given value.
+ * - #**: Returns the value of +self+ raised to the power of the given value.
+ * - #+: Returns the sum of +self+ and the given value.
+ * - #-: Returns the difference of +self+ and the given value.
+ * - #/: Returns the quotient of +self+ and the given value.
+ * - #<<: Returns the value of +self+ after a leftward bit-shift.
+ * - #>>: Returns the value of +self+ after a rightward bit-shift.
+ * - #[]: Returns a slice of bits from +self+.
+ * - #^: Returns the bitwise EXCLUSIVE OR of +self+ and the given value.
+ * - #ceil: Returns the smallest number greater than or equal to +self+.
+ * - #chr: Returns a 1-character string containing the character
+ * represented by the value of +self+.
+ * - #digits: Returns an array of integers representing the base-radix digits
+ * of +self+.
+ * - #div: Returns the integer result of dividing +self+ by the given value.
+ * - #divmod: Returns a 2-element array containing the quotient and remainder
+ * results of dividing +self+ by the given value.
+ * - #fdiv: Returns the Float result of dividing +self+ by the given value.
+ * - #floor: Returns the greatest number smaller than or equal to +self+.
+ * - #pow: Returns the modular exponentiation of +self+.
+ * - #pred: Returns the integer predecessor of +self+.
+ * - #remainder: Returns the remainder after dividing +self+ by the given value.
+ * - #round: Returns +self+ rounded to the nearest value with the given precision.
+ * - #succ (aliased as #next): Returns the integer successor of +self+.
+ * - #to_f: Returns +self+ converted to a Float.
+ * - #to_s (aliased as #inspect): Returns a string containing the place-value
+ * representation of +self+ in the given radix.
+ * - #truncate: Returns +self+ truncated to the given precision.
+ * - #|: Returns the bitwise OR of +self+ and the given value.
+ *
+ * === Other
+ *
+ * - #downto: Calls the given block with each integer value from +self+
+ * down to the given value.
+ * - #times: Calls the given block +self+ times with each integer
+ * in <tt>(0..self-1)</tt>.
+ * - #upto: Calls the given block with each integer value from +self+
+ * up to the given value.
*
*/
@@ -3136,8 +3572,8 @@ rb_int_odd_p(VALUE num)
return RBOOL(num & 2);
}
else {
- assert(RB_TYPE_P(num, T_BIGNUM));
- return rb_big_odd_p(num);
+ assert(RB_BIGNUM_TYPE_P(num));
+ return rb_big_odd_p(num);
}
}
@@ -3148,8 +3584,8 @@ int_even_p(VALUE num)
return RBOOL((num & 2) == 0);
}
else {
- assert(RB_TYPE_P(num, T_BIGNUM));
- return rb_big_even_p(num);
+ assert(RB_BIGNUM_TYPE_P(num));
+ return rb_big_even_p(num);
}
}
@@ -3161,9 +3597,25 @@ rb_int_even_p(VALUE num)
/*
* call-seq:
- * int.allbits?(mask) -> true or false
+ * allbits?(mask) -> true or false
+ *
+ * Returns +true+ if all bits that are set (=1) in +mask+
+ * are also set in +self+; returns +false+ otherwise.
+ *
+ * Example values:
+ *
+ * 0b1010101 self
+ * 0b1010100 mask
+ * 0b1010100 self & mask
+ * true self.allbits?(mask)
+ *
+ * 0b1010100 self
+ * 0b1010101 mask
+ * 0b1010100 self & mask
+ * false self.allbits?(mask)
+ *
+ * Related: Integer#anybits?, Integer#nobits?.
*
- * Returns +true+ if all bits of <code>+int+ & +mask+</code> are 1.
*/
static VALUE
@@ -3175,57 +3627,87 @@ int_allbits_p(VALUE num, VALUE mask)
/*
* call-seq:
- * int.anybits?(mask) -> true or false
+ * anybits?(mask) -> true or false
+ *
+ * Returns +true+ if any bit that is set (=1) in +mask+
+ * is also set in +self+; returns +false+ otherwise.
+ *
+ * Example values:
+ *
+ * 0b10000010 self
+ * 0b11111111 mask
+ * 0b10000010 self & mask
+ * true self.anybits?(mask)
+ *
+ * 0b00000000 self
+ * 0b11111111 mask
+ * 0b00000000 self & mask
+ * false self.anybits?(mask)
+ *
+ * Related: Integer#allbits?, Integer#nobits?.
*
- * Returns +true+ if any bits of <code>+int+ & +mask+</code> are 1.
*/
static VALUE
int_anybits_p(VALUE num, VALUE mask)
{
mask = rb_to_int(mask);
- return int_zero_p(rb_int_and(num, mask)) ? Qfalse : Qtrue;
+ return RBOOL(!int_zero_p(rb_int_and(num, mask)));
}
/*
* call-seq:
- * int.nobits?(mask) -> true or false
+ * nobits?(mask) -> true or false
+ *
+ * Returns +true+ if no bit that is set (=1) in +mask+
+ * is also set in +self+; returns +false+ otherwise.
+ *
+ * Example values:
+ *
+ * 0b11110000 self
+ * 0b00001111 mask
+ * 0b00000000 self & mask
+ * true self.nobits?(mask)
+ *
+ * 0b00000001 self
+ * 0b11111111 mask
+ * 0b00000001 self & mask
+ * false self.nobits?(mask)
+ *
+ * Related: Integer#allbits?, Integer#anybits?.
*
- * Returns +true+ if no bits of <code>+int+ & +mask+</code> are 1.
*/
static VALUE
int_nobits_p(VALUE num, VALUE mask)
{
mask = rb_to_int(mask);
- return int_zero_p(rb_int_and(num, mask));
+ return RBOOL(int_zero_p(rb_int_and(num, mask)));
}
/*
- * Document-method: Integer#succ
- * Document-method: Integer#next
* call-seq:
- * int.next -> integer
- * int.succ -> integer
+ * succ -> next_integer
*
- * Returns the successor of +int+,
- * i.e. the Integer equal to <code>int+1</code>.
+ * Returns the successor integer of +self+ (equivalent to <tt>self + 1</tt>):
*
- * 1.next #=> 2
- * (-1).next #=> 0
- * 1.succ #=> 2
- * (-1).succ #=> 0
+ * 1.succ #=> 2
+ * -1.succ #=> 0
+ *
+ * Integer#next is an alias for Integer#succ.
+ *
+ * Related: Integer#pred (predecessor value).
*/
VALUE
rb_int_succ(VALUE num)
{
if (FIXNUM_P(num)) {
- long i = FIX2LONG(num) + 1;
- return LONG2NUM(i);
+ long i = FIX2LONG(num) + 1;
+ return LONG2NUM(i);
}
- if (RB_TYPE_P(num, T_BIGNUM)) {
- return rb_big_plus(num, INT2FIX(1));
+ if (RB_BIGNUM_TYPE_P(num)) {
+ return rb_big_plus(num, INT2FIX(1));
}
return num_funcall1(num, '+', INT2FIX(1));
}
@@ -3234,43 +3716,32 @@ rb_int_succ(VALUE num)
/*
* call-seq:
- * int.pred -> integer
+ * pred -> next_integer
+ *
+ * Returns the predecessor of +self+ (equivalent to <tt>self - 1</tt>):
*
- * Returns the predecessor of +int+,
- * i.e. the Integer equal to <code>int-1</code>.
+ * 1.pred #=> 0
+ * -1.pred #=> -2
+ *
+ * Related: Integer#succ (successor value).
*
- * 1.pred #=> 0
- * (-1).pred #=> -2
*/
static VALUE
rb_int_pred(VALUE num)
{
if (FIXNUM_P(num)) {
- long i = FIX2LONG(num) - 1;
- return LONG2NUM(i);
+ long i = FIX2LONG(num) - 1;
+ return LONG2NUM(i);
}
- if (RB_TYPE_P(num, T_BIGNUM)) {
- return rb_big_minus(num, INT2FIX(1));
+ if (RB_BIGNUM_TYPE_P(num)) {
+ return rb_big_minus(num, INT2FIX(1));
}
return num_funcall1(num, '-', INT2FIX(1));
}
#define int_pred rb_int_pred
-/*
- * Document-method: Integer#chr
- * call-seq:
- * int.chr([encoding]) -> string
- *
- * Returns a string containing the character represented by the +int+'s value
- * according to +encoding+.
- *
- * 65.chr #=> "A"
- * 230.chr #=> "\xE6"
- * 255.chr(Encoding::UTF_8) #=> "\u00FF"
- */
-
VALUE
rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
{
@@ -3278,21 +3749,40 @@ rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
VALUE str;
switch (n = rb_enc_codelen(code, enc)) {
case ONIGERR_INVALID_CODE_POINT_VALUE:
- rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
- break;
+ rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
+ break;
case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
case 0:
- rb_raise(rb_eRangeError, "%u out of char range", code);
- break;
+ rb_raise(rb_eRangeError, "%u out of char range", code);
+ break;
}
str = rb_enc_str_new(0, n, enc);
rb_enc_mbcput(code, RSTRING_PTR(str), enc);
if (rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_END(str), enc) != n) {
- rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
+ rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
}
return str;
}
+/* call-seq:
+ * chr -> string
+ * chr(encoding) -> string
+ *
+ * Returns a 1-character string containing the character
+ * represented by the value of +self+, according to the given +encoding+.
+ *
+ * 65.chr # => "A"
+ * 0.chr # => "\x00"
+ * 255.chr # => "\xFF"
+ * string = 255.chr(Encoding::UTF_8)
+ * string.encoding # => Encoding::UTF_8
+ *
+ * Raises an exception if +self+ is negative.
+ *
+ * Related: Integer#ord.
+ *
+ */
+
static VALUE
int_chr(int argc, VALUE *argv, VALUE num)
{
@@ -3303,30 +3793,30 @@ int_chr(int argc, VALUE *argv, VALUE num)
if (rb_num_to_uint(num, &i) == 0) {
}
else if (FIXNUM_P(num)) {
- rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(num));
+ rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(num));
}
else {
- rb_raise(rb_eRangeError, "bignum out of char range");
+ rb_raise(rb_eRangeError, "bignum out of char range");
}
switch (argc) {
case 0:
- if (0xff < i) {
- enc = rb_default_internal_encoding();
- if (!enc) {
- rb_raise(rb_eRangeError, "%u out of char range", i);
- }
- goto decode;
- }
- c = (char)i;
- if (i < 0x80) {
- return rb_usascii_str_new(&c, 1);
- }
- else {
- return rb_str_new(&c, 1);
- }
+ if (0xff < i) {
+ enc = rb_default_internal_encoding();
+ if (!enc) {
+ rb_raise(rb_eRangeError, "%u out of char range", i);
+ }
+ goto decode;
+ }
+ c = (char)i;
+ if (i < 0x80) {
+ return rb_usascii_str_new(&c, 1);
+ }
+ else {
+ return rb_str_new(&c, 1);
+ }
case 1:
- break;
+ break;
default:
rb_error_arity(argc, 0, 1);
}
@@ -3350,31 +3840,14 @@ VALUE
rb_int_uminus(VALUE num)
{
if (FIXNUM_P(num)) {
- return fix_uminus(num);
+ return fix_uminus(num);
}
else {
- assert(RB_TYPE_P(num, T_BIGNUM));
- return rb_big_uminus(num);
+ assert(RB_BIGNUM_TYPE_P(num));
+ return rb_big_uminus(num);
}
}
-/*
- * Document-method: Integer#to_s
- * call-seq:
- * int.to_s(base=10) -> string
- *
- * Returns a string containing the place-value representation of +int+
- * with radix +base+ (between 2 and 36).
- *
- * 12345.to_s #=> "12345"
- * 12345.to_s(2) #=> "11000000111001"
- * 12345.to_s(8) #=> "30071"
- * 12345.to_s(10) #=> "12345"
- * 12345.to_s(16) #=> "3039"
- * 12345.to_s(36) #=> "9ix"
- * 78546939656932.to_s(36) #=> "rubyrules"
- */
-
VALUE
rb_fix2str(VALUE x, int base)
{
@@ -3384,13 +3857,13 @@ rb_fix2str(VALUE x, int base)
int neg = 0;
if (base < 2 || 36 < base) {
- rb_raise(rb_eArgError, "invalid radix %d", base);
+ rb_raise(rb_eArgError, "invalid radix %d", base);
}
#if SIZEOF_LONG < SIZEOF_VOIDP
# if SIZEOF_VOIDP == SIZEOF_LONG_LONG
if ((val >= 0 && (x & 0xFFFFFFFF00000000ull)) ||
- (val < 0 && (x & 0xFFFFFFFF00000000ull) != 0xFFFFFFFF00000000ull)) {
- rb_bug("Unnormalized Fixnum value %p", (void *)x);
+ (val < 0 && (x & 0xFFFFFFFF00000000ull) != 0xFFFFFFFF00000000ull)) {
+ rb_bug("Unnormalized Fixnum value %p", (void *)x);
}
# else
/* should do something like above code, but currently ruby does not know */
@@ -3398,34 +3871,67 @@ rb_fix2str(VALUE x, int base)
# endif
#endif
if (val == 0) {
- return rb_usascii_str_new2("0");
+ return rb_usascii_str_new2("0");
}
if (val < 0) {
- u = 1 + (unsigned long)(-(val + 1)); /* u = -val avoiding overflow */
- neg = 1;
+ u = 1 + (unsigned long)(-(val + 1)); /* u = -val avoiding overflow */
+ neg = 1;
}
else {
- u = val;
+ u = val;
}
do {
- *--b = ruby_digitmap[(int)(u % base)];
+ *--b = ruby_digitmap[(int)(u % base)];
} while (u /= base);
if (neg) {
- *--b = '-';
+ *--b = '-';
}
return rb_usascii_str_new(b, e - b);
}
-static VALUE
-int_to_s(int argc, VALUE *argv, VALUE x)
+static VALUE rb_fix_to_s_static[10];
+
+MJIT_FUNC_EXPORTED VALUE
+rb_fix_to_s(VALUE x)
+{
+ long i = FIX2LONG(x);
+ if (i >= 0 && i < 10) {
+ return rb_fix_to_s_static[i];
+ }
+ return rb_fix2str(x, 10);
+}
+
+/*
+ * call-seq:
+ * to_s(base = 10) -> string
+ *
+ * Returns a string containing the place-value representation of +self+
+ * in radix +base+ (in 2..36).
+ *
+ * 12345.to_s # => "12345"
+ * 12345.to_s(2) # => "11000000111001"
+ * 12345.to_s(8) # => "30071"
+ * 12345.to_s(10) # => "12345"
+ * 12345.to_s(16) # => "3039"
+ * 12345.to_s(36) # => "9ix"
+ * 78546939656932.to_s(36) # => "rubyrules"
+ *
+ * Raises an exception if +base+ is out of range.
+ *
+ * Integer#inspect is an alias for Integer#to_s.
+ *
+ */
+
+MJIT_FUNC_EXPORTED VALUE
+rb_int_to_s(int argc, VALUE *argv, VALUE x)
{
int base;
if (rb_check_arity(argc, 0, 1))
- base = NUM2INT(argv[0]);
+ base = NUM2INT(argv[0]);
else
- base = 10;
+ base = 10;
return rb_int2str(x, base);
}
@@ -3433,41 +3939,32 @@ VALUE
rb_int2str(VALUE x, int base)
{
if (FIXNUM_P(x)) {
- return rb_fix2str(x, base);
+ return rb_fix2str(x, base);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big2str(x, base);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big2str(x, base);
}
return rb_any_to_s(x);
}
-/*
- * Document-method: Integer#+
- * call-seq:
- * int + numeric -> numeric_result
- *
- * Performs addition: the class of the resulting object depends on
- * the class of +numeric+.
- */
-
static VALUE
fix_plus(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- return rb_fix_plus_fix(x, y);
+ return rb_fix_plus_fix(x, y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return rb_big_plus(y, x);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return rb_big_plus(y, x);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y));
}
else if (RB_TYPE_P(y, T_COMPLEX)) {
- return rb_complex_plus(y, x);
+ return rb_complex_plus(y, x);
}
else {
- return rb_num_coerce_bin(x, y, '+');
+ return rb_num_coerce_bin(x, y, '+');
}
}
@@ -3477,53 +3974,74 @@ rb_fix_plus(VALUE x, VALUE y)
return fix_plus(x, y);
}
+/*
+ * call-seq:
+ * self + numeric -> numeric_result
+ *
+ * Performs addition:
+ *
+ * 2 + 2 # => 4
+ * -2 + 2 # => 0
+ * -2 + -2 # => -4
+ * 2 + 2.0 # => 4.0
+ * 2 + Rational(2, 1) # => (4/1)
+ * 2 + Complex(2, 0) # => (4+0i)
+ *
+ */
+
VALUE
rb_int_plus(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_plus(x, y);
+ return fix_plus(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_plus(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_plus(x, y);
}
return rb_num_coerce_bin(x, y, '+');
}
-/*
- * Document-method: Integer#-
- * call-seq:
- * int - numeric -> numeric_result
- *
- * Performs subtraction: the class of the resulting object depends on
- * the class of +numeric+.
- */
-
static VALUE
fix_minus(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- return rb_fix_minus_fix(x, y);
+ return rb_fix_minus_fix(x, y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- x = rb_int2big(FIX2LONG(x));
- return rb_big_minus(x, y);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_minus(x, y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y));
}
else {
- return rb_num_coerce_bin(x, y, '-');
+ return rb_num_coerce_bin(x, y, '-');
}
}
+/*
+ * call-seq:
+ * self - numeric -> numeric_result
+ *
+ * Performs subtraction:
+ *
+ * 4 - 2 # => 2
+ * -4 - 2 # => -6
+ * -4 - -2 # => -2
+ * 4 - 2.0 # => 2.0
+ * 4 - Rational(2, 1) # => (2/1)
+ * 4 - Complex(2, 0) # => (2+0i)
+ *
+ */
+
VALUE
rb_int_minus(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_minus(x, y);
+ return fix_minus(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_minus(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_minus(x, y);
}
return rb_num_coerce_bin(x, y, '-');
}
@@ -3533,47 +4051,52 @@ rb_int_minus(VALUE x, VALUE y)
/*tests if N*N would overflow*/
#define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
-/*
- * Document-method: Integer#*
- * call-seq:
- * int * numeric -> numeric_result
- *
- * Performs multiplication: the class of the resulting object depends on
- * the class of +numeric+.
- */
-
static VALUE
fix_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- return rb_fix_mul_fix(x, y);
+ return rb_fix_mul_fix(x, y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- switch (x) {
- case INT2FIX(0): return x;
- case INT2FIX(1): return y;
- }
- return rb_big_mul(y, x);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ switch (x) {
+ case INT2FIX(0): return x;
+ case INT2FIX(1): return y;
+ }
+ return rb_big_mul(y, x);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y));
}
else if (RB_TYPE_P(y, T_COMPLEX)) {
- return rb_complex_mul(y, x);
+ return rb_complex_mul(y, x);
}
else {
- return rb_num_coerce_bin(x, y, '*');
+ return rb_num_coerce_bin(x, y, '*');
}
}
+/*
+ * call-seq:
+ * self * numeric -> numeric_result
+ *
+ * Performs multiplication:
+ *
+ * 4 * 2 # => 8
+ * 4 * -2 # => -8
+ * -4 * 2 # => -8
+ * 4 * 2.0 # => 8.0
+ * 4 * Rational(1, 3) # => (4/3)
+ * 4 * Complex(2, 0) # => (8+0i)
+ */
+
VALUE
rb_int_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_mul(x, y);
+ return fix_mul(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_mul(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_mul(x, y);
}
return rb_num_coerce_bin(x, y, '*');
}
@@ -3584,10 +4107,10 @@ fix_fdiv_double(VALUE x, VALUE y)
if (FIXNUM_P(y)) {
return double_div_double(FIX2LONG(x), FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
+ else if (RB_BIGNUM_TYPE_P(y)) {
return rb_big_fdiv_double(rb_int2big(FIX2LONG(x)), y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
+ else if (RB_FLOAT_TYPE_P(y)) {
return double_div_double(FIX2LONG(x), RFLOAT_VALUE(y));
}
else {
@@ -3599,16 +4122,16 @@ double
rb_int_fdiv_double(VALUE x, VALUE y)
{
if (RB_INTEGER_TYPE_P(y) && !FIXNUM_ZERO_P(y)) {
- VALUE gcd = rb_gcd(x, y);
- if (!FIXNUM_ZERO_P(gcd)) {
- x = rb_int_idiv(x, gcd);
- y = rb_int_idiv(y, gcd);
- }
+ VALUE gcd = rb_gcd(x, y);
+ if (!FIXNUM_ZERO_P(gcd)) {
+ x = rb_int_idiv(x, gcd);
+ y = rb_int_idiv(y, gcd);
+ }
}
if (FIXNUM_P(x)) {
return fix_fdiv_double(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
+ else if (RB_BIGNUM_TYPE_P(x)) {
return rb_big_fdiv_double(x, y);
}
else {
@@ -3617,15 +4140,19 @@ rb_int_fdiv_double(VALUE x, VALUE y)
}
/*
- * Document-method: Integer#fdiv
* call-seq:
- * int.fdiv(numeric) -> float
+ * fdiv(numeric) -> float
+ *
+ * Returns the Float result of dividing +self+ by +numeric+:
+ *
+ * 4.fdiv(2) # => 2.0
+ * 4.fdiv(-2) # => -2.0
+ * -4.fdiv(2) # => -2.0
+ * 4.fdiv(2.0) # => 2.0
+ * 4.fdiv(Rational(3, 4)) # => 5.333333333333333
*
- * Returns the floating point result of dividing +int+ by +numeric+.
+ * Raises an exception if +numeric+ cannot be converted to a Float.
*
- * 654321.fdiv(13731) #=> 47.652829364212366
- * 654321.fdiv(13731.24) #=> 47.65199646936475
- * -654321.fdiv(13731) #=> -47.652829364212366
*/
VALUE
@@ -3637,43 +4164,34 @@ rb_int_fdiv(VALUE x, VALUE y)
return Qnil;
}
-/*
- * Document-method: Integer#/
- * call-seq:
- * int / numeric -> numeric_result
- *
- * Performs division: the class of the resulting object depends on
- * the class of +numeric+.
- */
-
static VALUE
fix_divide(VALUE x, VALUE y, ID op)
{
if (FIXNUM_P(y)) {
- if (FIXNUM_ZERO_P(y)) rb_num_zerodiv();
- return rb_fix_div_fix(x, y);
+ if (FIXNUM_ZERO_P(y)) rb_num_zerodiv();
+ return rb_fix_div_fix(x, y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- x = rb_int2big(FIX2LONG(x));
- return rb_big_div(x, y);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_div(x, y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- if (op == '/') {
+ else if (RB_FLOAT_TYPE_P(y)) {
+ if (op == '/') {
double d = FIX2LONG(x);
return rb_flo_div_flo(DBL2NUM(d), y);
- }
- else {
+ }
+ else {
VALUE v;
- if (RFLOAT_VALUE(y) == 0) rb_num_zerodiv();
+ if (RFLOAT_VALUE(y) == 0) rb_num_zerodiv();
v = fix_divide(x, y, '/');
return flo_floor(0, 0, v);
- }
+ }
}
else {
- if (RB_TYPE_P(y, T_RATIONAL) &&
- op == '/' && FIX2LONG(x) == 1)
- return rb_rational_reciprocal(y);
- return rb_num_coerce_bin(x, y, op);
+ if (RB_TYPE_P(y, T_RATIONAL) &&
+ op == '/' && FIX2LONG(x) == 1)
+ return rb_rational_reciprocal(y);
+ return rb_num_coerce_bin(x, y, op);
}
}
@@ -3683,182 +4201,249 @@ fix_div(VALUE x, VALUE y)
return fix_divide(x, y, '/');
}
+/*
+ * call-seq:
+ * self / numeric -> numeric_result
+ *
+ * Performs division; for integer +numeric+, truncates the result to an integer:
+ *
+ * 4 / 3 # => 1
+ * 4 / -3 # => -2
+ * -4 / 3 # => -2
+ * -4 / -3 # => 1
+ *
+ * For other +numeric+, returns non-integer result:
+ *
+ * 4 / 3.0 # => 1.3333333333333333
+ * 4 / Rational(3, 1) # => (4/3)
+ * 4 / Complex(3, 0) # => ((4/3)+0i)
+ *
+ */
+
VALUE
rb_int_div(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_div(x, y);
+ return fix_div(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_div(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_div(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#div
- * call-seq:
- * int.div(numeric) -> integer
- *
- * Performs integer division: returns the integer result of dividing +int+
- * by +numeric+.
- */
-
static VALUE
fix_idiv(VALUE x, VALUE y)
{
return fix_divide(x, y, id_div);
}
+/*
+ * call-seq:
+ * div(numeric) -> integer
+ *
+ * Performs integer division; returns the integer result of dividing +self+
+ * by +numeric+:
+ *
+ * 4.div(3) # => 1
+ * 4.div(-3) # => -2
+ * -4.div(3) # => -2
+ * -4.div(-3) # => 1
+ * 4.div(3.0) # => 1
+ * 4.div(Rational(3, 1)) # => 1
+ *
+ * Raises an exception if +numeric+ does not have method +div+.
+ *
+ */
+
VALUE
rb_int_idiv(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_idiv(x, y);
+ return fix_idiv(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_idiv(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_idiv(x, y);
}
return num_div(x, y);
}
-/*
- * Document-method: Integer#%
- * Document-method: Integer#modulo
- * call-seq:
- * int % other -> real
- * int.modulo(other) -> real
- *
- * Returns +int+ modulo +other+.
- *
- * See Numeric#divmod for more information.
- */
-
static VALUE
fix_mod(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- if (FIXNUM_ZERO_P(y)) rb_num_zerodiv();
- return rb_fix_mod_fix(x, y);
+ if (FIXNUM_ZERO_P(y)) rb_num_zerodiv();
+ return rb_fix_mod_fix(x, y);
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- x = rb_int2big(FIX2LONG(x));
- return rb_big_modulo(x, y);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_modulo(x, y);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return DBL2NUM(ruby_float_mod((double)FIX2LONG(x), RFLOAT_VALUE(y)));
}
else {
- return rb_num_coerce_bin(x, y, '%');
+ return rb_num_coerce_bin(x, y, '%');
}
}
+/*
+ * call-seq:
+ * self % other -> real_number
+ *
+ * Returns +self+ modulo +other+ as a real number.
+ *
+ * For integer +n+ and real number +r+, these expressions are equivalent:
+ *
+ * n % r
+ * n-r*(n/r).floor
+ * n.divmod(r)[1]
+ *
+ * See Numeric#divmod.
+ *
+ * Examples:
+ *
+ * 10 % 2 # => 0
+ * 10 % 3 # => 1
+ * 10 % 4 # => 2
+ *
+ * 10 % -2 # => 0
+ * 10 % -3 # => -2
+ * 10 % -4 # => -2
+ *
+ * 10 % 3.0 # => 1.0
+ * 10 % Rational(3, 1) # => (1/1)
+ *
+ * Integer#modulo is an alias for Integer#%.
+ *
+ */
VALUE
rb_int_modulo(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_mod(x, y);
+ return fix_mod(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_modulo(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_modulo(x, y);
}
return num_modulo(x, y);
}
/*
* call-seq:
- * int.remainder(numeric) -> real
+ * remainder(other) -> real_number
*
- * Returns the remainder after dividing +int+ by +numeric+.
+ * Returns the remainder after dividing +self+ by +other+.
*
- * <code>x.remainder(y)</code> means <code>x-y*(x/y).truncate</code>.
+ * Examples:
*
- * 5.remainder(3) #=> 2
- * -5.remainder(3) #=> -2
- * 5.remainder(-3) #=> 2
- * -5.remainder(-3) #=> -2
- * 5.remainder(1.5) #=> 0.5
+ * 11.remainder(4) # => 3
+ * 11.remainder(-4) # => 3
+ * -11.remainder(4) # => -3
+ * -11.remainder(-4) # => -3
+ *
+ * 12.remainder(4) # => 0
+ * 12.remainder(-4) # => 0
+ * -12.remainder(4) # => 0
+ * -12.remainder(-4) # => 0
+ *
+ * 13.remainder(4.0) # => 1.0
+ * 13.remainder(Rational(4, 1)) # => (1/1)
*
- * See Numeric#divmod.
*/
static VALUE
int_remainder(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return num_remainder(x, y);
+ return num_remainder(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_remainder(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_remainder(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#divmod
- * call-seq:
- * int.divmod(numeric) -> array
- *
- * See Numeric#divmod.
- */
static VALUE
fix_divmod(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- VALUE div, mod;
- if (FIXNUM_ZERO_P(y)) rb_num_zerodiv();
- rb_fix_divmod_fix(x, y, &div, &mod);
- return rb_assoc_new(div, mod);
- }
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- x = rb_int2big(FIX2LONG(x));
- return rb_big_divmod(x, y);
- }
- else if (RB_TYPE_P(y, T_FLOAT)) {
- {
- double div, mod;
- volatile VALUE a, b;
-
- flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
- a = dbl2ival(div);
- b = DBL2NUM(mod);
- return rb_assoc_new(a, b);
- }
+ VALUE div, mod;
+ if (FIXNUM_ZERO_P(y)) rb_num_zerodiv();
+ rb_fix_divmod_fix(x, y, &div, &mod);
+ return rb_assoc_new(div, mod);
+ }
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_divmod(x, y);
+ }
+ else if (RB_FLOAT_TYPE_P(y)) {
+ {
+ double div, mod;
+ volatile VALUE a, b;
+
+ flodivmod((double)FIX2LONG(x), RFLOAT_VALUE(y), &div, &mod);
+ a = dbl2ival(div);
+ b = DBL2NUM(mod);
+ return rb_assoc_new(a, b);
+ }
}
else {
- return rb_num_coerce_bin(x, y, id_divmod);
+ return rb_num_coerce_bin(x, y, id_divmod);
}
}
+/*
+ * call-seq:
+ * divmod(other) -> array
+ *
+ * Returns a 2-element array <tt>[q, r]</tt>, where
+ *
+ * q = (self/other).floor # Quotient
+ * r = self % other # Remainder
+ *
+ * Examples:
+ *
+ * 11.divmod(4) # => [2, 3]
+ * 11.divmod(-4) # => [-3, -1]
+ * -11.divmod(4) # => [-3, 1]
+ * -11.divmod(-4) # => [2, -3]
+ *
+ * 12.divmod(4) # => [3, 0]
+ * 12.divmod(-4) # => [-3, 0]
+ * -12.divmod(4) # => [-3, 0]
+ * -12.divmod(-4) # => [3, 0]
+ *
+ * 13.divmod(4.0) # => [3, 1.0]
+ * 13.divmod(Rational(4, 1)) # => [3, (1/1)]
+ *
+ */
VALUE
rb_int_divmod(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_divmod(x, y);
+ return fix_divmod(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_divmod(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_divmod(x, y);
}
return Qnil;
}
/*
- * Document-method: Integer#**
* call-seq:
- * int ** numeric -> numeric_result
+ * self ** numeric -> numeric_result
*
- * Raises +int+ to the power of +numeric+, which may be negative or
- * fractional.
- * The result may be an Integer, a Float, a Rational, or a complex number.
+ * Raises +self+ to the power of +numeric+:
*
- * 2 ** 3 #=> 8
- * 2 ** -1 #=> (1/2)
- * 2 ** 0.5 #=> 1.4142135623730951
- * (-1) ** 0.5 #=> (0.0+1.0i)
+ * 2 ** 3 # => 8
+ * 2 ** -3 # => (1/8)
+ * -2 ** 3 # => -8
+ * -2 ** -3 # => (-1/8)
+ * 2 ** 3.3 # => 9.849155306759329
+ * 2 ** Rational(3, 1) # => (8/1)
+ * 2 ** Complex(3, 0) # => (8+0i)
*
- * 123456789 ** 2 #=> 15241578750190521
- * 123456789 ** 1.2 #=> 5126464716.0993185
- * 123456789 ** -2 #=> (1/15241578750190521)
*/
static VALUE
@@ -3871,24 +4456,24 @@ int_pow(long x, unsigned long y)
if (y == 1) return LONG2NUM(x);
if (neg) x = -x;
if (y & 1)
- z = x;
+ z = x;
else
- neg = 0;
+ neg = 0;
y &= ~1;
do {
- while (y % 2 == 0) {
- if (!FIT_SQRT_LONG(x)) {
+ while (y % 2 == 0) {
+ if (!FIT_SQRT_LONG(x)) {
goto bignum;
- }
- x = x * x;
- y >>= 1;
- }
- {
+ }
+ x = x * x;
+ y >>= 1;
+ }
+ {
if (MUL_OVERFLOW_FIXNUM_P(x, z)) {
- goto bignum;
- }
- z = x * z;
- }
+ goto bignum;
+ }
+ z = x * z;
+ }
} while (--y);
if (neg) z = -z;
return LONG2NUM(z);
@@ -3934,48 +4519,63 @@ fix_pow(VALUE x, VALUE y)
long a = FIX2LONG(x);
if (FIXNUM_P(y)) {
- long b = FIX2LONG(y);
+ long b = FIX2LONG(y);
- if (a == 1) return INT2FIX(1);
+ if (a == 1) return INT2FIX(1);
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) return INT2FIX(0);
- return int_pow(a, b);
+ if (b == 0) return INT2FIX(1);
+ if (b == 1) return x;
+ 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);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ if (a == 1) return INT2FIX(1);
if (a == -1) return INT2FIX(int_even_p(y) ? 1 : -1);
if (BIGNUM_NEGATIVE_P(y)) return fix_pow_inverted(x, rb_big_uminus(y));
- if (a == 0) return INT2FIX(0);
- x = rb_int2big(FIX2LONG(x));
- return rb_big_pow(x, y);
- }
- else if (RB_TYPE_P(y, T_FLOAT)) {
- double dy = RFLOAT_VALUE(y);
- if (dy == 0.0) return DBL2NUM(1.0);
- if (a == 0) {
- return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0);
- }
- if (a == 1) return DBL2NUM(1.0);
+ if (a == 0) return INT2FIX(0);
+ x = rb_int2big(FIX2LONG(x));
+ return rb_big_pow(x, y);
+ }
+ else if (RB_FLOAT_TYPE_P(y)) {
+ double dy = RFLOAT_VALUE(y);
+ if (dy == 0.0) return DBL2NUM(1.0);
+ if (a == 0) {
+ return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0);
+ }
+ if (a == 1) return DBL2NUM(1.0);
if (a < 0 && dy != round(dy))
return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy);
return DBL2NUM(pow((double)a, dy));
}
else {
- return rb_num_coerce_bin(x, y, idPow);
+ return rb_num_coerce_bin(x, y, idPow);
}
}
+/*
+ * call-seq:
+ * self ** numeric -> numeric_result
+ *
+ * Raises +self+ to the power of +numeric+:
+ *
+ * 2 ** 3 # => 8
+ * 2 ** -3 # => (1/8)
+ * -2 ** 3 # => -8
+ * -2 ** -3 # => (-1/8)
+ * 2 ** 3.3 # => 9.849155306759329
+ * 2 ** Rational(3, 1) # => (8/1)
+ * 2 ** Complex(3, 0) # => (8+0i)
+ *
+ */
VALUE
rb_int_pow(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_pow(x, y);
+ return fix_pow(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_pow(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_pow(x, y);
}
return Qnil;
}
@@ -3998,250 +4598,293 @@ rb_num_pow(VALUE x, VALUE y)
return Qnil;
}
-/*
- * Document-method: Integer#==
- * Document-method: Integer#===
- * call-seq:
- * int == other -> true or false
- *
- * Returns +true+ if +int+ equals +other+ numerically.
- * Contrast this with Integer#eql?, which requires +other+ to be an Integer.
- *
- * 1 == 2 #=> false
- * 1 == 1.0 #=> true
- */
-
static VALUE
fix_equal(VALUE x, VALUE y)
{
if (x == y) return Qtrue;
if (FIXNUM_P(y)) return Qfalse;
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return rb_big_eq(y, x);
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return rb_big_eq(y, x);
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
+ else if (RB_FLOAT_TYPE_P(y)) {
return rb_integer_float_eq(x, y);
}
else {
- return num_equal(x, y);
+ return num_equal(x, y);
}
}
+/*
+ * call-seq:
+ * self == other -> true or false
+ *
+ * Returns +true+ if +self+ is numerically equal to +other+; +false+ otherwise.
+ *
+ * 1 == 2 #=> false
+ * 1 == 1.0 #=> true
+ *
+ * Related: Integer#eql? (requires +other+ to be an \Integer).
+ *
+ * Integer#=== is an alias for Integer#==.
+ *
+ */
+
VALUE
rb_int_equal(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_equal(x, y);
+ return fix_equal(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_eq(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_eq(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#<=>
- * call-seq:
- * int <=> numeric -> -1, 0, +1, or nil
- *
- * Comparison---Returns -1, 0, or +1 depending on whether +int+ is
- * less than, equal to, or greater than +numeric+.
- *
- * This is the basis for the tests in the Comparable module.
- *
- * +nil+ is returned if the two values are incomparable.
- */
-
static VALUE
fix_cmp(VALUE x, VALUE y)
{
if (x == y) return INT2FIX(0);
if (FIXNUM_P(y)) {
- if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
- return INT2FIX(-1);
- }
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- VALUE cmp = rb_big_cmp(y, x);
- switch (cmp) {
- case INT2FIX(+1): return INT2FIX(-1);
- case INT2FIX(-1): return INT2FIX(+1);
- }
- return cmp;
+ if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
+ return INT2FIX(-1);
+ }
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ VALUE cmp = rb_big_cmp(y, x);
+ switch (cmp) {
+ case INT2FIX(+1): return INT2FIX(-1);
+ case INT2FIX(-1): return INT2FIX(+1);
+ }
+ return cmp;
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- return rb_integer_float_cmp(x, y);
+ else if (RB_FLOAT_TYPE_P(y)) {
+ return rb_integer_float_cmp(x, y);
}
else {
- return rb_num_coerce_cmp(x, y, id_cmp);
+ return rb_num_coerce_cmp(x, y, id_cmp);
}
}
+/*
+ * call-seq:
+ * self <=> other -> -1, 0, +1, or nil
+ *
+ * Returns:
+ *
+ * - -1, if +self+ is less than +other+.
+ * - 0, if +self+ is equal to +other+.
+ * - 1, if +self+ is greater then +other+.
+ * - +nil+, if +self+ and +other+ are incomparable.
+ *
+ * Examples:
+ *
+ * 1 <=> 2 # => -1
+ * 1 <=> 1 # => 0
+ * 1 <=> 0 # => 1
+ * 1 <=> 'foo' # => nil
+ *
+ * 1 <=> 1.0 # => 0
+ * 1 <=> Rational(1, 1) # => 0
+ * 1 <=> Complex(1, 0) # => 0
+ *
+ * This method is the basis for comparisons in module Comparable.
+ *
+ */
+
VALUE
rb_int_cmp(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_cmp(x, y);
+ return fix_cmp(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_cmp(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_cmp(x, y);
}
else {
- rb_raise(rb_eNotImpError, "need to define `<=>' in %s", rb_obj_classname(x));
+ rb_raise(rb_eNotImpError, "need to define `<=>' in %s", rb_obj_classname(x));
}
}
-/*
- * Document-method: Integer#>
- * call-seq:
- * int > real -> true or false
- *
- * Returns +true+ if the value of +int+ is greater than that of +real+.
- */
-
static VALUE
fix_gt(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- if (FIX2LONG(x) > FIX2LONG(y)) return Qtrue;
- return Qfalse;
+ return RBOOL(FIX2LONG(x) > FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return RBOOL(rb_big_cmp(y, x) == INT2FIX(-1));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return RBOOL(rb_big_cmp(y, x) == INT2FIX(-1));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
+ else if (RB_FLOAT_TYPE_P(y)) {
return RBOOL(rb_integer_float_cmp(x, y) == INT2FIX(1));
}
else {
- return rb_num_coerce_relop(x, y, '>');
+ return rb_num_coerce_relop(x, y, '>');
}
}
+/*
+ * call-seq:
+ * self > other -> true or false
+ *
+ * Returns +true+ if the value of +self+ is greater than that of +other+:
+ *
+ * 1 > 0 # => true
+ * 1 > 1 # => false
+ * 1 > 2 # => false
+ * 1 > 0.5 # => true
+ * 1 > Rational(1, 2) # => true
+ *
+ * Raises an exception if the comparison cannot be made.
+ *
+ */
+
VALUE
rb_int_gt(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_gt(x, y);
+ return fix_gt(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_gt(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_gt(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#>=
- * call-seq:
- * int >= real -> true or false
- *
- * Returns +true+ if the value of +int+ is greater than or equal to that of
- * +real+.
- */
-
static VALUE
fix_ge(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- if (FIX2LONG(x) >= FIX2LONG(y)) return Qtrue;
- return Qfalse;
+ return RBOOL(FIX2LONG(x) >= FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return RBOOL(rb_big_cmp(y, x) != INT2FIX(+1));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return RBOOL(rb_big_cmp(y, x) != INT2FIX(+1));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- VALUE rel = rb_integer_float_cmp(x, y);
- return RBOOL(rel == INT2FIX(1) || rel == INT2FIX(0));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ VALUE rel = rb_integer_float_cmp(x, y);
+ return RBOOL(rel == INT2FIX(1) || rel == INT2FIX(0));
}
else {
- return rb_num_coerce_relop(x, y, idGE);
+ return rb_num_coerce_relop(x, y, idGE);
}
}
+/*
+ * call-seq:
+ * self >= real -> true or false
+ *
+ * Returns +true+ if the value of +self+ is greater than or equal to
+ * that of +other+:
+ *
+ * 1 >= 0 # => true
+ * 1 >= 1 # => true
+ * 1 >= 2 # => false
+ * 1 >= 0.5 # => true
+ * 1 >= Rational(1, 2) # => true
+ *
+ * Raises an exception if the comparison cannot be made.
+ *
+ */
+
VALUE
rb_int_ge(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_ge(x, y);
+ return fix_ge(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_ge(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_ge(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#<
- * call-seq:
- * int < real -> true or false
- *
- * Returns +true+ if the value of +int+ is less than that of +real+.
- */
-
static VALUE
fix_lt(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- if (FIX2LONG(x) < FIX2LONG(y)) return Qtrue;
- return Qfalse;
+ return RBOOL(FIX2LONG(x) < FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return RBOOL(rb_big_cmp(y, x) == INT2FIX(+1));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return RBOOL(rb_big_cmp(y, x) == INT2FIX(+1));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
+ else if (RB_FLOAT_TYPE_P(y)) {
return RBOOL(rb_integer_float_cmp(x, y) == INT2FIX(-1));
}
else {
- return rb_num_coerce_relop(x, y, '<');
+ return rb_num_coerce_relop(x, y, '<');
}
}
+/*
+ * call-seq:
+ * self < other -> true or false
+ *
+ * Returns +true+ if the value of +self+ is less than that of +other+:
+ *
+ * 1 < 0 # => false
+ * 1 < 1 # => false
+ * 1 < 2 # => true
+ * 1 < 0.5 # => false
+ * 1 < Rational(1, 2) # => false
+ *
+ * Raises an exception if the comparison cannot be made.
+ *
+ */
+
static VALUE
int_lt(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_lt(x, y);
+ return fix_lt(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_lt(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_lt(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#<=
- * call-seq:
- * int <= real -> true or false
- *
- * Returns +true+ if the value of +int+ is less than or equal to that of
- * +real+.
- */
-
static VALUE
fix_le(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- if (FIX2LONG(x) <= FIX2LONG(y)) return Qtrue;
- return Qfalse;
+ return RBOOL(FIX2LONG(x) <= FIX2LONG(y));
}
- else if (RB_TYPE_P(y, T_BIGNUM)) {
- return RBOOL(rb_big_cmp(y, x) != INT2FIX(-1));
+ else if (RB_BIGNUM_TYPE_P(y)) {
+ return RBOOL(rb_big_cmp(y, x) != INT2FIX(-1));
}
- else if (RB_TYPE_P(y, T_FLOAT)) {
- VALUE rel = rb_integer_float_cmp(x, y);
- return RBOOL(rel == INT2FIX(-1) || rel == INT2FIX(0));
+ else if (RB_FLOAT_TYPE_P(y)) {
+ VALUE rel = rb_integer_float_cmp(x, y);
+ return RBOOL(rel == INT2FIX(-1) || rel == INT2FIX(0));
}
else {
- return rb_num_coerce_relop(x, y, idLE);
+ return rb_num_coerce_relop(x, y, idLE);
}
}
+/*
+ * call-seq:
+ * self <= real -> true or false
+ *
+ * Returns +true+ if the value of +self+ is less than or equal to
+ * that of +other+:
+ *
+ * 1 <= 0 # => false
+ * 1 <= 1 # => true
+ * 1 <= 2 # => true
+ * 1 <= 0.5 # => false
+ * 1 <= Rational(1, 2) # => false
+ *
+ * Raises an exception if the comparison cannot be made.
+ *
+ */
+
static VALUE
int_le(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_le(x, y);
+ return fix_le(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_le(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_le(x, y);
}
return Qnil;
}
@@ -4256,10 +4899,10 @@ VALUE
rb_int_comp(VALUE num)
{
if (FIXNUM_P(num)) {
- return fix_comp(num);
+ return fix_comp(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- return rb_big_comp(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ return rb_big_comp(num);
}
return Qnil;
}
@@ -4270,7 +4913,7 @@ num_funcall_bit_1(VALUE y, VALUE arg, int recursive)
ID func = (ID)((VALUE *)arg)[0];
VALUE x = ((VALUE *)arg)[1];
if (recursive) {
- num_funcall_op_1_recursion(x, func, y);
+ num_funcall_op_1_recursion(x, func, y);
}
return rb_check_funcall(x, func, 1, &y);
}
@@ -4285,139 +4928,152 @@ rb_num_coerce_bit(VALUE x, VALUE y, ID func)
args[2] = y;
do_coerce(&args[1], &args[2], TRUE);
ret = rb_exec_recursive_paired(num_funcall_bit_1,
- args[2], args[1], (VALUE)args);
- if (ret == Qundef) {
- /* show the original object, not coerced object */
- coerce_failed(x, y);
+ args[2], args[1], (VALUE)args);
+ if (UNDEF_P(ret)) {
+ /* show the original object, not coerced object */
+ coerce_failed(x, y);
}
return ret;
}
-/*
- * Document-method: Integer#&
- * call-seq:
- * int & other_int -> integer
- *
- * Bitwise AND.
- */
-
static VALUE
fix_and(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- long val = FIX2LONG(x) & FIX2LONG(y);
- return LONG2NUM(val);
+ long val = FIX2LONG(x) & FIX2LONG(y);
+ return LONG2NUM(val);
}
- if (RB_TYPE_P(y, T_BIGNUM)) {
- return rb_big_and(y, x);
+ if (RB_BIGNUM_TYPE_P(y)) {
+ return rb_big_and(y, x);
}
return rb_num_coerce_bit(x, y, '&');
}
+/*
+ * call-seq:
+ * self & other -> integer
+ *
+ * Bitwise AND; each bit in the result is 1 if both corresponding bits
+ * in +self+ and +other+ are 1, 0 otherwise:
+ *
+ * "%04b" % (0b0101 & 0b0110) # => "0100"
+ *
+ * Raises an exception if +other+ is not an \Integer.
+ *
+ * Related: Integer#| (bitwise OR), Integer#^ (bitwise EXCLUSIVE OR).
+ *
+ */
+
VALUE
rb_int_and(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_and(x, y);
+ return fix_and(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_and(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_and(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#|
- * call-seq:
- * int | other_int -> integer
- *
- * Bitwise OR.
- */
-
static VALUE
fix_or(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- long val = FIX2LONG(x) | FIX2LONG(y);
- return LONG2NUM(val);
+ long val = FIX2LONG(x) | FIX2LONG(y);
+ return LONG2NUM(val);
}
- if (RB_TYPE_P(y, T_BIGNUM)) {
- return rb_big_or(y, x);
+ if (RB_BIGNUM_TYPE_P(y)) {
+ return rb_big_or(y, x);
}
return rb_num_coerce_bit(x, y, '|');
}
+/*
+ * call-seq:
+ * self | other -> integer
+ *
+ * Bitwise OR; each bit in the result is 1 if either corresponding bit
+ * in +self+ or +other+ is 1, 0 otherwise:
+ *
+ * "%04b" % (0b0101 | 0b0110) # => "0111"
+ *
+ * Raises an exception if +other+ is not an \Integer.
+ *
+ * Related: Integer#& (bitwise AND), Integer#^ (bitwise EXCLUSIVE OR).
+ *
+ */
+
static VALUE
int_or(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_or(x, y);
+ return fix_or(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_or(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_or(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#^
- * call-seq:
- * int ^ other_int -> integer
- *
- * Bitwise EXCLUSIVE OR.
- */
-
static VALUE
fix_xor(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- long val = FIX2LONG(x) ^ FIX2LONG(y);
- return LONG2NUM(val);
+ long val = FIX2LONG(x) ^ FIX2LONG(y);
+ return LONG2NUM(val);
}
- if (RB_TYPE_P(y, T_BIGNUM)) {
- return rb_big_xor(y, x);
+ if (RB_BIGNUM_TYPE_P(y)) {
+ return rb_big_xor(y, x);
}
return rb_num_coerce_bit(x, y, '^');
}
+/*
+ * call-seq:
+ * self ^ other -> integer
+ *
+ * Bitwise EXCLUSIVE OR; each bit in the result is 1 if the corresponding bits
+ * in +self+ and +other+ are different, 0 otherwise:
+ *
+ * "%04b" % (0b0101 ^ 0b0110) # => "0011"
+ *
+ * Raises an exception if +other+ is not an \Integer.
+ *
+ * Related: Integer#& (bitwise AND), Integer#| (bitwise OR).
+ *
+ */
+
static VALUE
int_xor(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return fix_xor(x, y);
+ return fix_xor(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_xor(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_xor(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#<<
- * call-seq:
- * int << count -> integer
- *
- * Returns +int+ shifted left +count+ positions, or right if +count+
- * is negative.
- */
-
static VALUE
rb_fix_lshift(VALUE x, VALUE y)
{
long val, width;
val = NUM2LONG(x);
+ if (!val) return (rb_to_int(y), INT2FIX(0));
if (!FIXNUM_P(y))
- return rb_big_lshift(rb_int2big(val), y);
+ return rb_big_lshift(rb_int2big(val), y);
width = FIX2LONG(y);
if (width < 0)
- return fix_rshift(val, (unsigned long)-width);
+ return fix_rshift(val, (unsigned long)-width);
return fix_lshift(val, width);
}
@@ -4425,46 +5081,55 @@ static VALUE
fix_lshift(long val, unsigned long width)
{
if (width > (SIZEOF_LONG*CHAR_BIT-1)
- || ((unsigned long)val)>>(SIZEOF_LONG*CHAR_BIT-1-width) > 0) {
- return rb_big_lshift(rb_int2big(val), ULONG2NUM(width));
+ || ((unsigned long)val)>>(SIZEOF_LONG*CHAR_BIT-1-width) > 0) {
+ return rb_big_lshift(rb_int2big(val), ULONG2NUM(width));
}
val = val << width;
return LONG2NUM(val);
}
+/*
+ * call-seq:
+ * self << count -> integer
+ *
+ * Returns +self+ with bits shifted +count+ positions to the left,
+ * or to the right if +count+ is negative:
+ *
+ * n = 0b11110000
+ * "%08b" % (n << 1) # => "111100000"
+ * "%08b" % (n << 3) # => "11110000000"
+ * "%08b" % (n << -1) # => "01111000"
+ * "%08b" % (n << -3) # => "00011110"
+ *
+ * Related: Integer#>>.
+ *
+ */
+
VALUE
rb_int_lshift(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return rb_fix_lshift(x, y);
+ return rb_fix_lshift(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_lshift(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_lshift(x, y);
}
return Qnil;
}
-/*
- * Document-method: Integer#>>
- * call-seq:
- * int >> count -> integer
- *
- * Returns +int+ shifted right +count+ positions, or left if +count+
- * is negative.
- */
-
static VALUE
rb_fix_rshift(VALUE x, VALUE y)
{
long i, val;
val = FIX2LONG(x);
+ if (!val) return (rb_to_int(y), INT2FIX(0));
if (!FIXNUM_P(y))
- return rb_big_rshift(rb_int2big(val), y);
+ return rb_big_rshift(rb_int2big(val), y);
i = FIX2LONG(y);
if (i == 0) return x;
if (i < 0)
- return fix_lshift(val, (unsigned long)-i);
+ return fix_lshift(val, (unsigned long)-i);
return fix_rshift(val, i);
}
@@ -4472,21 +5137,38 @@ static VALUE
fix_rshift(long val, unsigned long i)
{
if (i >= sizeof(long)*CHAR_BIT-1) {
- if (val < 0) return INT2FIX(-1);
- return INT2FIX(0);
+ if (val < 0) return INT2FIX(-1);
+ return INT2FIX(0);
}
val = RSHIFT(val, i);
return LONG2FIX(val);
}
+/*
+ * call-seq:
+ * self >> count -> integer
+ *
+ * Returns +self+ with bits shifted +count+ positions to the right,
+ * or to the left if +count+ is negative:
+ *
+ * n = 0b11110000
+ * "%08b" % (n >> 1) # => "01111000"
+ * "%08b" % (n >> 3) # => "00011110"
+ * "%08b" % (n >> -1) # => "111100000"
+ * "%08b" % (n >> -3) # => "11110000000"
+ *
+ * Related: Integer#<<.
+ *
+ */
+
static VALUE
rb_int_rshift(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
- return rb_fix_rshift(x, y);
+ return rb_fix_rshift(x, y);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return rb_big_rshift(x, y);
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return rb_big_rshift(x, y);
}
return Qnil;
}
@@ -4499,22 +5181,22 @@ rb_fix_aref(VALUE fix, VALUE idx)
idx = rb_to_int(idx);
if (!FIXNUM_P(idx)) {
- idx = rb_big_norm(idx);
- if (!FIXNUM_P(idx)) {
- if (!BIGNUM_SIGN(idx) || val >= 0)
- return INT2FIX(0);
- return INT2FIX(1);
- }
+ idx = rb_big_norm(idx);
+ if (!FIXNUM_P(idx)) {
+ if (!BIGNUM_SIGN(idx) || val >= 0)
+ return INT2FIX(0);
+ return INT2FIX(1);
+ }
}
i = FIX2LONG(idx);
if (i < 0) return INT2FIX(0);
if (SIZEOF_LONG*CHAR_BIT-1 <= i) {
- if (val < 0) return INT2FIX(1);
- return INT2FIX(0);
+ if (val < 0) return INT2FIX(1);
+ return INT2FIX(0);
}
if (val & (1L<<i))
- return INT2FIX(1);
+ return INT2FIX(1);
return INT2FIX(0);
}
@@ -4553,7 +5235,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(int_zero_p(rb_int_and(num, mask)))) {
+ if (int_zero_p(rb_int_and(num, mask))) {
return INT2FIX(0);
}
else {
@@ -4586,7 +5268,7 @@ one_bit:
if (FIXNUM_P(num)) {
return rb_fix_aref(num, arg);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
+ else if (RB_BIGNUM_TYPE_P(num)) {
return rb_big_aref(num, arg);
}
return Qnil;
@@ -4602,41 +5284,42 @@ int_aref2(VALUE num, VALUE beg, VALUE len)
}
/*
- * Document-method: Integer#[]
* call-seq:
- * int[n] -> 0, 1
- * int[n, m] -> num
- * int[range] -> num
+ * self[offset] -> 0 or 1
+ * self[offset, size] -> integer
+ * self[range] -> integer
*
- * Bit Reference---Returns the <code>n</code>th bit in the
- * binary representation of +int+, where <code>int[0]</code>
- * is the least significant bit.
+ * Returns a slice of bits from +self+.
*
- * a = 0b11001100101010
- * 30.downto(0) {|n| print a[n] }
- * #=> 0000000000000000011001100101010
+ * With argument +offset+, returns the bit at the given offset,
+ * where offset 0 refers to the least significant bit:
*
- * a = 9**15
- * 50.downto(0) {|n| print a[n] }
- * #=> 000101110110100000111000011110010100111100010111001
+ * n = 0b10 # => 2
+ * n[0] # => 0
+ * n[1] # => 1
+ * n[2] # => 0
+ * n[3] # => 0
*
* In principle, <code>n[i]</code> is equivalent to <code>(n >> i) & 1</code>.
- * Thus, any negative index always returns zero:
+ * Thus, negative index always returns zero:
*
- * p 255[-1] #=> 0
+ * 255[-1] # => 0
*
- * Range operations <code>n[i, len]</code> and <code>n[i..j]</code>
- * are naturally extended.
+ * With arguments +offset+ and +size+, returns +size+ bits from +self+,
+ * beginning at +offset+ and including bits of greater significance:
*
- * * <code>n[i, len]</code> equals to <code>(n >> i) & ((1 << len) - 1)</code>.
- * * <code>n[i..j]</code> equals to <code>(n >> i) & ((1 << (j - i + 1)) - 1)</code>.
- * * <code>n[i...j]</code> equals to <code>(n >> i) & ((1 << (j - i)) - 1)</code>.
- * * <code>n[i..]</code> equals to <code>(n >> i)</code>.
- * * <code>n[..j]</code> is zero if <code>n & ((1 << (j + 1)) - 1)</code> is zero. Otherwise, raises an ArgumentError.
- * * <code>n[...j]</code> is zero if <code>n & ((1 << j) - 1)</code> is zero. Otherwise, raises an ArgumentError.
+ * n = 0b111000 # => 56
+ * "%010b" % n[0, 10] # => "0000111000"
+ * "%010b" % n[4, 10] # => "0000000011"
*
- * Note that range operation may exhaust memory.
- * For example, <code>-1[0, 1000000000000]</code> will raise NoMemoryError.
+ * With argument +range+, returns <tt>range.size</tt> bits from +self+,
+ * beginning at <tt>range.begin</tt> and including bits of greater significance:
+ *
+ * n = 0b111000 # => 56
+ * "%010b" % n[0..9] # => "0000111000"
+ * "%010b" % n[4..9] # => "0000000011"
+ *
+ * Raises an exception if the slice cannot be constructed.
*/
static VALUE
@@ -4652,12 +5335,20 @@ int_aref(int const argc, VALUE * const argv, VALUE const num)
}
/*
- * Document-method: Integer#to_f
* call-seq:
- * int.to_f -> float
+ * to_f -> float
+ *
+ * Converts +self+ to a Float:
+ *
+ * 1.to_f # => 1.0
+ * -1.to_f # => -1.0
+ *
+ * If the value of +self+ does not fit in a \Float,
+ * the result is infinity:
+ *
+ * (10**400).to_f # => Infinity
+ * (-10**400).to_f # => -Infinity
*
- * Converts +int+ to a Float. If +int+ doesn't fit in a Float,
- * the result is infinity.
*/
static VALUE
@@ -4666,34 +5357,18 @@ int_to_f(VALUE num)
double val;
if (FIXNUM_P(num)) {
- val = (double)FIX2LONG(num);
+ val = (double)FIX2LONG(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- val = rb_big2dbl(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ val = rb_big2dbl(num);
}
else {
- rb_raise(rb_eNotImpError, "Unknown subclass for to_f: %s", rb_obj_classname(num));
+ rb_raise(rb_eNotImpError, "Unknown subclass for to_f: %s", rb_obj_classname(num));
}
return DBL2NUM(val);
}
-/*
- * Document-method: Integer#abs
- * Document-method: Integer#magnitude
- * call-seq:
- * int.abs -> integer
- * int.magnitude -> integer
- *
- * Returns the absolute value of +int+.
- *
- * (-12345).abs #=> 12345
- * -12345.abs #=> 12345
- * 12345.abs #=> 12345
- *
- * Integer#magnitude is an alias for Integer#abs.
- */
-
static VALUE
fix_abs(VALUE fix)
{
@@ -4708,10 +5383,10 @@ VALUE
rb_int_abs(VALUE num)
{
if (FIXNUM_P(num)) {
- return fix_abs(num);
+ return fix_abs(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- return rb_big_abs(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ return rb_big_abs(num);
}
return Qnil;
}
@@ -4726,10 +5401,10 @@ MJIT_FUNC_EXPORTED VALUE
rb_int_size(VALUE num)
{
if (FIXNUM_P(num)) {
- return fix_size(num);
+ return fix_size(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- return rb_big_size_m(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ return rb_big_size_m(num);
}
return Qnil;
}
@@ -4747,34 +5422,14 @@ VALUE
rb_int_bit_length(VALUE num)
{
if (FIXNUM_P(num)) {
- return rb_fix_bit_length(num);
+ return rb_fix_bit_length(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- return rb_big_bit_length(num);
+ else if (RB_BIGNUM_TYPE_P(num)) {
+ return rb_big_bit_length(num);
}
return Qnil;
}
-/*
- * Document-method: Integer#digits
- * call-seq:
- * int.digits -> array
- * int.digits(base) -> array
- *
- * Returns the digits of +int+'s place-value representation
- * with radix +base+ (default: 10).
- * The digits are returned as an array with the least significant digit
- * as the first array element.
- *
- * +base+ must be greater than or equal to 2.
- *
- * 12345.digits #=> [5, 4, 3, 2, 1]
- * 12345.digits(7) #=> [4, 6, 6, 0, 5]
- * 12345.digits(100) #=> [45, 23, 1]
- *
- * -12345.digits(7) #=> Math::DomainError
- */
-
static VALUE
rb_fix_digits(VALUE fix, long base)
{
@@ -4806,12 +5461,12 @@ rb_int_digits_bigbase(VALUE num, VALUE base)
assert(!rb_num_negative_p(num));
- if (RB_TYPE_P(base, T_BIGNUM))
+ if (RB_BIGNUM_TYPE_P(base))
base = rb_big_norm(base);
if (FIXNUM_P(base) && FIX2LONG(base) < 2)
rb_raise(rb_eArgError, "invalid radix %ld", FIX2LONG(base));
- else if (RB_TYPE_P(base, T_BIGNUM) && BIGNUM_NEGATIVE_P(base))
+ else if (RB_BIGNUM_TYPE_P(base) && BIGNUM_NEGATIVE_P(base))
rb_raise(rb_eArgError, "negative radix");
if (FIXNUM_P(base) && FIXNUM_P(num))
@@ -4851,6 +5506,22 @@ rb_int_digits_bigbase(VALUE num, VALUE base)
return digits;
}
+/*
+ * call-seq:
+ * digits(base = 10) -> array_of_integers
+ *
+ * Returns an array of integers representing the +base+-radix
+ * digits of +self+;
+ * the first element of the array represents the least significant digit:
+ *
+ * 12345.digits # => [5, 4, 3, 2, 1]
+ * 12345.digits(7) # => [4, 6, 6, 0, 5]
+ * 12345.digits(100) # => [45, 23, 1]
+ *
+ * Raises an exception if +self+ is negative or +base+ is less than 2.
+ *
+ */
+
static VALUE
rb_int_digits(int argc, VALUE *argv, VALUE num)
{
@@ -4865,7 +5536,7 @@ rb_int_digits(int argc, VALUE *argv, VALUE num)
if (!RB_INTEGER_TYPE_P(base_value))
rb_raise(rb_eTypeError, "wrong argument type %s (expected Integer)",
rb_obj_classname(argv[0]));
- if (RB_TYPE_P(base_value, T_BIGNUM))
+ if (RB_BIGNUM_TYPE_P(base_value))
return rb_int_digits_bigbase(num, base_value);
base = FIX2LONG(base_value);
@@ -4879,183 +5550,211 @@ rb_int_digits(int argc, VALUE *argv, VALUE num)
if (FIXNUM_P(num))
return rb_fix_digits(num, base);
- else if (RB_TYPE_P(num, T_BIGNUM))
+ else if (RB_BIGNUM_TYPE_P(num))
return rb_int_digits_bigbase(num, LONG2FIX(base));
return Qnil;
}
+static VALUE
+int_upto_size(VALUE from, VALUE args, VALUE eobj)
+{
+ return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(1), FALSE);
+}
+
/*
- * Document-method: Integer#upto
* call-seq:
- * int.upto(limit) {|i| block } -> self
- * int.upto(limit) -> an_enumerator
+ * upto(limit) {|i| ... } -> self
+ * upto(limit) -> enumerator
+ *
+ * Calls the given block with each integer value from +self+ up to +limit+;
+ * returns +self+:
*
- * Iterates the given block, passing in integer values from +int+ up to and
- * including +limit+.
+ * a = []
+ * 5.upto(10) {|i| a << i } # => 5
+ * a # => [5, 6, 7, 8, 9, 10]
+ * a = []
+ * -5.upto(0) {|i| a << i } # => -5
+ * a # => [-5, -4, -3, -2, -1, 0]
+ * 5.upto(4) {|i| fail 'Cannot happen' } # => 5
*
- * If no block is given, an Enumerator is returned instead.
+ * With no block given, returns an Enumerator.
*
- * 5.upto(10) {|i| print i, " " } #=> 5 6 7 8 9 10
*/
static VALUE
-int_upto_size(VALUE from, VALUE args, VALUE eobj)
-{
- return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(1), FALSE);
-}
-
-static VALUE
int_upto(VALUE from, VALUE to)
{
RETURN_SIZED_ENUMERATOR(from, 1, &to, int_upto_size);
if (FIXNUM_P(from) && FIXNUM_P(to)) {
- long i, end;
+ long i, end;
- end = FIX2LONG(to);
- for (i = FIX2LONG(from); i <= end; i++) {
- rb_yield(LONG2FIX(i));
- }
+ end = FIX2LONG(to);
+ for (i = FIX2LONG(from); i <= end; i++) {
+ rb_yield(LONG2FIX(i));
+ }
}
else {
- VALUE i = from, c;
+ VALUE i = from, c;
- while (!(c = rb_funcall(i, '>', 1, to))) {
- rb_yield(i);
- i = rb_funcall(i, '+', 1, INT2FIX(1));
- }
- ensure_cmp(c, i, to);
+ while (!(c = rb_funcall(i, '>', 1, to))) {
+ rb_yield(i);
+ i = rb_funcall(i, '+', 1, INT2FIX(1));
+ }
+ ensure_cmp(c, i, to);
}
return from;
}
+static VALUE
+int_downto_size(VALUE from, VALUE args, VALUE eobj)
+{
+ return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE);
+}
+
/*
- * Document-method: Integer#downto
* call-seq:
- * int.downto(limit) {|i| block } -> self
- * int.downto(limit) -> an_enumerator
+ * downto(limit) {|i| ... } -> self
+ * downto(limit) -> enumerator
+ *
+ * Calls the given block with each integer value from +self+ down to +limit+;
+ * returns +self+:
*
- * Iterates the given block, passing in decreasing values from +int+ down to
- * and including +limit+.
+ * a = []
+ * 10.downto(5) {|i| a << i } # => 10
+ * a # => [10, 9, 8, 7, 6, 5]
+ * a = []
+ * 0.downto(-5) {|i| a << i } # => 0
+ * a # => [0, -1, -2, -3, -4, -5]
+ * 4.downto(5) {|i| fail 'Cannot happen' } # => 4
*
- * If no block is given, an Enumerator is returned instead.
+ * With no block given, returns an Enumerator.
*
- * 5.downto(1) { |n| print n, ".. " }
- * puts "Liftoff!"
- * #=> "5.. 4.. 3.. 2.. 1.. Liftoff!"
*/
static VALUE
-int_downto_size(VALUE from, VALUE args, VALUE eobj)
-{
- return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE);
-}
-
-static VALUE
int_downto(VALUE from, VALUE to)
{
RETURN_SIZED_ENUMERATOR(from, 1, &to, int_downto_size);
if (FIXNUM_P(from) && FIXNUM_P(to)) {
- long i, end;
+ long i, end;
- end = FIX2LONG(to);
- for (i=FIX2LONG(from); i >= end; i--) {
- rb_yield(LONG2FIX(i));
- }
+ end = FIX2LONG(to);
+ for (i=FIX2LONG(from); i >= end; i--) {
+ rb_yield(LONG2FIX(i));
+ }
}
else {
- VALUE i = from, c;
+ VALUE i = from, c;
- while (!(c = rb_funcall(i, '<', 1, to))) {
- rb_yield(i);
- i = rb_funcall(i, '-', 1, INT2FIX(1));
- }
- if (NIL_P(c)) rb_cmperr(i, to);
+ while (!(c = rb_funcall(i, '<', 1, to))) {
+ rb_yield(i);
+ i = rb_funcall(i, '-', 1, INT2FIX(1));
+ }
+ if (NIL_P(c)) rb_cmperr(i, to);
}
return from;
}
-/*
- * Document-method: Integer#times
- * call-seq:
- * int.times {|i| block } -> self
- * int.times -> an_enumerator
- *
- * Iterates the given block +int+ times, passing in values from zero to
- * <code>int - 1</code>.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * 5.times {|i| print i, " " } #=> 0 1 2 3 4
- */
-
static VALUE
int_dotimes_size(VALUE num, VALUE args, VALUE eobj)
{
if (FIXNUM_P(num)) {
- if (NUM2LONG(num) <= 0) return INT2FIX(0);
+ if (NUM2LONG(num) <= 0) return INT2FIX(0);
}
else {
- if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) return INT2FIX(0);
+ if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) return INT2FIX(0);
}
return num;
}
+/*
+ * call-seq:
+ * times {|i| ... } -> self
+ * times -> enumerator
+ *
+ * Calls the given block +self+ times with each integer in <tt>(0..self-1)</tt>:
+ *
+ * a = []
+ * 5.times {|i| a.push(i) } # => 5
+ * a # => [0, 1, 2, 3, 4]
+ *
+ * With no block given, returns an Enumerator.
+ *
+ */
+
static VALUE
int_dotimes(VALUE num)
{
RETURN_SIZED_ENUMERATOR(num, 0, 0, int_dotimes_size);
if (FIXNUM_P(num)) {
- long i, end;
+ long i, end;
- end = FIX2LONG(num);
- for (i=0; i<end; i++) {
- rb_yield_1(LONG2FIX(i));
- }
+ end = FIX2LONG(num);
+ for (i=0; i<end; i++) {
+ rb_yield_1(LONG2FIX(i));
+ }
}
else {
- VALUE i = INT2FIX(0);
+ VALUE i = INT2FIX(0);
- for (;;) {
- if (!RTEST(rb_funcall(i, '<', 1, num))) break;
- rb_yield(i);
- i = rb_funcall(i, '+', 1, INT2FIX(1));
- }
+ for (;;) {
+ if (!RTEST(int_le(i, num))) break;
+ rb_yield(i);
+ i = rb_int_plus(i, INT2FIX(1));
+ }
}
return num;
}
/*
- * Document-method: Integer#round
* call-seq:
- * int.round([ndigits] [, half: mode]) -> integer or float
+ * round(ndigits= 0, half: :up) -> integer
*
- * Returns +int+ rounded to the nearest value with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns +self+ rounded to the nearest value with
+ * a precision of +ndigits+ decimal digits.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
+ * When +ndigits+ is negative, the returned value
+ * has at least <tt>ndigits.abs</tt> trailing zeros:
+ *
+ * 555.round(-1) # => 560
+ * 555.round(-2) # => 600
+ * 555.round(-3) # => 1000
+ * -555.round(-2) # => -600
+ * 555.round(-4) # => 0
*
* Returns +self+ when +ndigits+ is zero or positive.
*
- * 1.round #=> 1
- * 1.round(2) #=> 1
- * 15.round(-1) #=> 20
- * (-15).round(-1) #=> -20
- *
- * The optional +half+ keyword argument is available
- * similar to Float#round.
- *
- * 25.round(-1, half: :up) #=> 30
- * 25.round(-1, half: :down) #=> 20
- * 25.round(-1, half: :even) #=> 20
- * 35.round(-1, half: :up) #=> 40
- * 35.round(-1, half: :down) #=> 30
- * 35.round(-1, half: :even) #=> 40
- * (-25).round(-1, half: :up) #=> -30
- * (-25).round(-1, half: :down) #=> -20
- * (-25).round(-1, half: :even) #=> -20
+ * 555.round # => 555
+ * 555.round(1) # => 555
+ * 555.round(50) # => 555
+ *
+ * If keyword argument +half+ is given,
+ * and +self+ is equidistant from the two candidate values,
+ * the rounding is according to the given +half+ value:
+ *
+ * - +:up+ or +nil+: round away from zero:
+ *
+ * 25.round(-1, half: :up) # => 30
+ * (-25).round(-1, half: :up) # => -30
+ *
+ * - +:down+: round toward zero:
+ *
+ * 25.round(-1, half: :down) # => 20
+ * (-25).round(-1, half: :down) # => -20
+ *
+ *
+ * - +:even+: round toward the candidate whose last nonzero digit is even:
+ *
+ * 25.round(-1, half: :even) # => 20
+ * 15.round(-1, half: :even) # => 20
+ * (-25).round(-1, half: :even) # => -20
+ *
+ * Raises and exception if the value for +half+ is invalid.
+ *
+ * Related: Integer#truncate.
+ *
*/
static VALUE
@@ -5069,28 +5768,33 @@ int_round(int argc, VALUE* argv, VALUE num)
ndigits = NUM2INT(nd);
mode = rb_num_get_rounding_option(opt);
if (ndigits >= 0) {
- return num;
+ return num;
}
return rb_int_round(num, ndigits, mode);
}
/*
- * Document-method: Integer#floor
* call-seq:
- * int.floor([ndigits]) -> integer or float
+ * floor(ndigits = 0) -> integer
*
- * Returns the largest number less than or equal to +int+ with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns the largest number less than or equal to +self+ with
+ * a precision of +ndigits+ decimal digits.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
+ * When +ndigits+ is negative, the returned value
+ * has at least <tt>ndigits.abs</tt> trailing zeros:
+ *
+ * 555.floor(-1) # => 550
+ * 555.floor(-2) # => 500
+ * -555.floor(-2) # => -600
+ * 555.floor(-3) # => 0
*
* Returns +self+ when +ndigits+ is zero or positive.
*
- * 1.floor #=> 1
- * 1.floor(2) #=> 1
- * 18.floor(-1) #=> 10
- * (-18).floor(-1) #=> -20
+ * 555.floor # => 555
+ * 555.floor(50) # => 555
+ *
+ * Related: Integer#ceil.
+ *
*/
static VALUE
@@ -5101,28 +5805,33 @@ int_floor(int argc, VALUE* argv, VALUE num)
if (!rb_check_arity(argc, 0, 1)) return num;
ndigits = NUM2INT(argv[0]);
if (ndigits >= 0) {
- return num;
+ return num;
}
return rb_int_floor(num, ndigits);
}
/*
- * Document-method: Integer#ceil
* call-seq:
- * int.ceil([ndigits]) -> integer or float
+ * ceil(ndigits = 0) -> integer
*
- * Returns the smallest number greater than or equal to +int+ with
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns the smallest number greater than or equal to +self+ with
+ * a precision of +ndigits+ decimal digits.
*
* When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
+ * with at least <code>ndigits.abs</code> trailing zeros:
+ *
+ * 555.ceil(-1) # => 560
+ * 555.ceil(-2) # => 600
+ * -555.ceil(-2) # => -500
+ * 555.ceil(-3) # => 1000
*
* Returns +self+ when +ndigits+ is zero or positive.
*
- * 1.ceil #=> 1
- * 1.ceil(2) #=> 1
- * 18.ceil(-1) #=> 20
- * (-18).ceil(-1) #=> -10
+ * 555.ceil # => 555
+ * 555.ceil(50) # => 555
+ *
+ * Related: Integer#floor.
+ *
*/
static VALUE
@@ -5133,28 +5842,32 @@ int_ceil(int argc, VALUE* argv, VALUE num)
if (!rb_check_arity(argc, 0, 1)) return num;
ndigits = NUM2INT(argv[0]);
if (ndigits >= 0) {
- return num;
+ return num;
}
return rb_int_ceil(num, ndigits);
}
/*
- * Document-method: Integer#truncate
* call-seq:
- * int.truncate([ndigits]) -> integer or float
+ * truncate(ndigits = 0) -> integer
*
- * Returns +int+ truncated (toward zero) to
- * a precision of +ndigits+ decimal digits (default: 0).
+ * Returns +self+ truncated (toward zero) to
+ * a precision of +ndigits+ decimal digits.
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros.
+ * When +ndigits+ is negative, the returned value
+ * has at least <tt>ndigits.abs</tt> trailing zeros:
+ *
+ * 555.truncate(-1) # => 550
+ * 555.truncate(-2) # => 500
+ * -555.truncate(-2) # => -500
*
* Returns +self+ when +ndigits+ is zero or positive.
*
- * 1.truncate #=> 1
- * 1.truncate(2) #=> 1
- * 18.truncate(-1) #=> 10
- * (-18).truncate(-1) #=> -10
+ * 555.truncate # => 555
+ * 555.truncate(50) # => 555
+ *
+ * Related: Integer#round.
+ *
*/
static VALUE
@@ -5165,7 +5878,7 @@ int_truncate(int argc, VALUE* argv, VALUE num)
if (!rb_check_arity(argc, 0, 1)) return num;
ndigits = NUM2INT(argv[0]);
if (ndigits >= 0) {
- return num;
+ return num;
}
return rb_int_truncate(num, ndigits);
}
@@ -5175,12 +5888,12 @@ rettype \
prefix##_isqrt(argtype n) \
{ \
if (!argtype##_IN_DOUBLE_P(n)) { \
- unsigned int b = bit_length(n); \
- argtype t; \
- rettype x = (rettype)(n >> (b/2+1)); \
- x |= ((rettype)1LU << (b-1)/2); \
- while ((t = n/x) < (argtype)x) x = (rettype)((x + t) >> 1); \
- return x; \
+ unsigned int b = bit_length(n); \
+ argtype t; \
+ rettype x = (rettype)(n >> (b/2+1)); \
+ x |= ((rettype)1LU << (b-1)/2); \
+ while ((t = n/x) < (argtype)x) x = (rettype)((x + t) >> 1); \
+ return x; \
} \
return (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
}
@@ -5212,29 +5925,35 @@ DEFINE_INT_SQRT(BDIGIT, rb_bdigit_dbl, BDIGIT_DBL)
rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg)
/*
- * Document-method: Integer::sqrt
* call-seq:
- * Integer.sqrt(n) -> integer
+ * Integer.sqrt(numeric) -> integer
*
* Returns the integer square root of the non-negative integer +n+,
- * i.e. the largest non-negative integer less than or equal to the
- * square root of +n+.
+ * which is the largest non-negative integer less than or equal to the
+ * square root of +numeric+.
*
- * Integer.sqrt(0) #=> 0
- * Integer.sqrt(1) #=> 1
- * Integer.sqrt(24) #=> 4
- * Integer.sqrt(25) #=> 5
- * Integer.sqrt(10**400) #=> 10**200
+ * Integer.sqrt(0) # => 0
+ * Integer.sqrt(1) # => 1
+ * Integer.sqrt(24) # => 4
+ * Integer.sqrt(25) # => 5
+ * Integer.sqrt(10**400) # => 10**200
*
- * Equivalent to <code>Math.sqrt(n).floor</code>, except that
- * the result of the latter code may differ from the true value
+ * If +numeric+ is not an \Integer, it is converted to an \Integer:
+ *
+ * Integer.sqrt(Complex(4, 0)) # => 2
+ * Integer.sqrt(Rational(4, 1)) # => 2
+ * Integer.sqrt(4.0) # => 2
+ * Integer.sqrt(3.14159) # => 1
+ *
+ * This method is equivalent to <tt>Math.sqrt(numeric).floor</tt>,
+ * except that the result of the latter code may differ from the true value
* due to the limited precision of floating point arithmetic.
*
- * Integer.sqrt(10**46) #=> 100000000000000000000000
- * Math.sqrt(10**46).floor #=> 99999999999999991611392 (!)
+ * Integer.sqrt(10**46) # => 100000000000000000000000
+ * Math.sqrt(10**46).floor # => 99999999999999991611392
+ *
+ * Raises an exception if +numeric+ is negative.
*
- * If +n+ is not an Integer, it is converted to an Integer first.
- * If +n+ is negative, a Math::DomainError is raised.
*/
static VALUE
@@ -5243,32 +5962,33 @@ rb_int_s_isqrt(VALUE self, VALUE num)
unsigned long n, sq;
num = rb_to_int(num);
if (FIXNUM_P(num)) {
- if (FIXNUM_NEGATIVE_P(num)) {
- domain_error("isqrt");
- }
- n = FIX2ULONG(num);
- sq = rb_ulong_isqrt(n);
- return LONG2FIX(sq);
+ if (FIXNUM_NEGATIVE_P(num)) {
+ domain_error("isqrt");
+ }
+ n = FIX2ULONG(num);
+ sq = rb_ulong_isqrt(n);
+ return LONG2FIX(sq);
}
else {
- size_t biglen;
- if (RBIGNUM_NEGATIVE_P(num)) {
- domain_error("isqrt");
- }
- biglen = BIGNUM_LEN(num);
- if (biglen == 0) return INT2FIX(0);
+ size_t biglen;
+ if (RBIGNUM_NEGATIVE_P(num)) {
+ domain_error("isqrt");
+ }
+ biglen = BIGNUM_LEN(num);
+ if (biglen == 0) return INT2FIX(0);
#if SIZEOF_BDIGIT <= SIZEOF_LONG
- /* short-circuit */
- if (biglen == 1) {
- n = BIGNUM_DIGITS(num)[0];
- sq = rb_ulong_isqrt(n);
- return ULONG2NUM(sq);
- }
+ /* short-circuit */
+ if (biglen == 1) {
+ n = BIGNUM_DIGITS(num)[0];
+ sq = rb_ulong_isqrt(n);
+ return ULONG2NUM(sq);
+ }
#endif
- return rb_big_isqrt(num);
+ return rb_big_isqrt(num);
}
}
+/* :nodoc: */
static VALUE
int_s_try_convert(VALUE self, VALUE num)
{
@@ -5374,80 +6094,82 @@ int_s_try_convert(VALUE self, VALUE num)
*
* First, what's elsewhere. \Class \Numeric:
*
- * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
- * - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here].
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
*
* Here, class \Numeric provides methods for:
*
- * - {Querying}[#class-Numeric-label-Querying]
- * - {Comparing}[#class-Numeric-label-Comparing]
- * - {Converting}[#class-Numeric-label-Converting]
- * - {Other}[#class-Numeric-label-Other]
+ * - {Querying}[rdoc-ref:Numeric@Querying]
+ * - {Comparing}[rdoc-ref:Numeric@Comparing]
+ * - {Converting}[rdoc-ref:Numeric@Converting]
+ * - {Other}[rdoc-ref:Numeric@Other]
*
* === Querying
*
- * - #finite?:: Returns true unless +self+ is infinite or not a number.
- * - #infinite?:: Returns -1, +nil+ or +1, depending on whether +self+
- * is <tt>-Infinity<tt>, finite, or <tt>+Infinity</tt>.
- * - #integer?:: Returns whether +self+ is an integer.
- * - #negative?:: Returns whether +self+ is negative.
- * - #nonzero?:: Returns whether +self+ is not zero.
- * - #positive?:: Returns whether +self+ is positive.
- * - #real?:: Returns whether +self+ is a real value.
- * - #zero?:: Returns whether +self+ is zero.
+ * - #finite?: Returns true unless +self+ is infinite or not a number.
+ * - #infinite?: Returns -1, +nil+ or +1, depending on whether +self+
+ * is <tt>-Infinity<tt>, finite, or <tt>+Infinity</tt>.
+ * - #integer?: Returns whether +self+ is an integer.
+ * - #negative?: Returns whether +self+ is negative.
+ * - #nonzero?: Returns whether +self+ is not zero.
+ * - #positive?: Returns whether +self+ is positive.
+ * - #real?: Returns whether +self+ is a real value.
+ * - #zero?: Returns whether +self+ is zero.
*
* === Comparing
*
- * - {<=>}[#method-i-3C-3D-3E]:: Returns:
+ * - #<=>: Returns:
+ *
* - -1 if +self+ is less than the given value.
* - 0 if +self+ is equal to the given value.
- * - 1 if +self is greater than the given value.
+ * - 1 if +self+ is greater than the given value.
* - +nil+ if +self+ and the given value are not comparable.
- * - #eql?:: Returns whether +self+ and the given value have the same value and type.
+ *
+ * - #eql?: Returns whether +self+ and the given value have the same value and type.
*
* === Converting
*
- * - #% (aliased as #modulo):: Returns the remainder of +self+ divided by the given value.
- * - #-@:: Returns the value of +self+, negated.
- * - #abs (aliased as #magnitude):: Returns the absolute value of +self+.
- * - #abs2:: Returns the square of +self+.
- * - #angle (aliased as #arg and #phase):: Returns 0 if +self+ is positive,
- * Math::PI otherwise.
- * - #ceil:: Returns the smallest number greater than or equal to +self+,
- * to a given precision.
- * - #coerce:: Returns array <tt>[coerced_self, coerced_other]</tt>
- * for the given other value.
- * - #conj (aliased as #conjugate):: Returns the complex conjugate of +self+.
- * - #denominator:: Returns the denominator (always positive)
- * of the Rational representation of +self+.
- * - #div:: Returns the value of +self+ divided by the given value
- * and converted to an integer.
- * - #divmod:: Returns array <tt>[quotient, modulus]</tt> resulting
- * from dividing +self+ the given divisor.
- * - #fdiv:: Returns the Float result of dividing +self+ by the given divisor.
- * - #floor:: Returns the largest number less than or equal to +self+,
- * to a given precision.
- * - #i:: Returns the Complex object <tt>Complex(0, self)</tt>.
- * the given value.
- * - #imaginary (aliased as #imag):: Returns the imaginary part of the +self+.
- * - #numerator:: Returns the numerator of the Rational representation of +self+;
- * has the same sign as +self+.
- * - #polar:: Returns the array <tt>[self.abs, self.arg]</tt>.
- * - #quo:: Returns the value of +self+ divided by the given value.
- * - #real:: Returns the real part of +self+.
- * - #rect (aliased as #rectangular):: Returns the array <tt>[self, 0]</tt>.
- * - #remainder:: Returns <tt>self-arg*(self/arg).truncate</tt> for the given +arg+.
- * - #round:: Returns the value of +self+ rounded to the nearest value
- * for the given a precision.
- * - #to_c:: Returns the Complex representation of +self+.
- * - #to_int:: Returns the Integer representation of +self+, truncating if necessary.
- * - #truncate:: Returns +self+ truncated (toward zero) to a given precision.
+ * - #% (aliased as #modulo): Returns the remainder of +self+ divided by the given value.
+ * - #-@: Returns the value of +self+, negated.
+ * - #abs (aliased as #magnitude): Returns the absolute value of +self+.
+ * - #abs2: Returns the square of +self+.
+ * - #angle (aliased as #arg and #phase): Returns 0 if +self+ is positive,
+ * Math::PI otherwise.
+ * - #ceil: Returns the smallest number greater than or equal to +self+,
+ * to a given precision.
+ * - #coerce: Returns array <tt>[coerced_self, coerced_other]</tt>
+ * for the given other value.
+ * - #conj (aliased as #conjugate): Returns the complex conjugate of +self+.
+ * - #denominator: Returns the denominator (always positive)
+ * of the Rational representation of +self+.
+ * - #div: Returns the value of +self+ divided by the given value
+ * and converted to an integer.
+ * - #divmod: Returns array <tt>[quotient, modulus]</tt> resulting
+ * from dividing +self+ the given divisor.
+ * - #fdiv: Returns the Float result of dividing +self+ by the given divisor.
+ * - #floor: Returns the largest number less than or equal to +self+,
+ * to a given precision.
+ * - #i: Returns the Complex object <tt>Complex(0, self)</tt>.
+ * the given value.
+ * - #imaginary (aliased as #imag): Returns the imaginary part of the +self+.
+ * - #numerator: Returns the numerator of the Rational representation of +self+;
+ * has the same sign as +self+.
+ * - #polar: Returns the array <tt>[self.abs, self.arg]</tt>.
+ * - #quo: Returns the value of +self+ divided by the given value.
+ * - #real: Returns the real part of +self+.
+ * - #rect (aliased as #rectangular): Returns the array <tt>[self, 0]</tt>.
+ * - #remainder: Returns <tt>self-arg*(self/arg).truncate</tt> for the given +arg+.
+ * - #round: Returns the value of +self+ rounded to the nearest value
+ * for the given a precision.
+ * - #to_c: Returns the Complex representation of +self+.
+ * - #to_int: Returns the Integer representation of +self+, truncating if necessary.
+ * - #truncate: Returns +self+ truncated (toward zero) to a given precision.
*
* === Other
*
- * - #clone:: Returns +self+; does not allow freezing.
- * - #dup (aliased as #+@):: Returns +self+.
- * - #step:: Invokes the given block with the sequence of specified numbers.
+ * - #clone: Returns +self+; does not allow freezing.
+ * - #dup (aliased as #+@): Returns +self+.
+ * - #step: Invokes the given block with the sequence of specified numbers.
*
*/
void
@@ -5503,7 +6225,7 @@ Init_Numeric(void)
rb_define_singleton_method(rb_cInteger, "sqrt", rb_int_s_isqrt, 1);
rb_define_singleton_method(rb_cInteger, "try_convert", int_s_try_convert, 1);
- rb_define_method(rb_cInteger, "to_s", int_to_s, -1);
+ rb_define_method(rb_cInteger, "to_s", rb_int_to_s, -1);
rb_define_alias(rb_cInteger, "inspect", "to_s");
rb_define_method(rb_cInteger, "allbits?", int_allbits_p, 1);
rb_define_method(rb_cInteger, "anybits?", int_anybits_p, 1);
@@ -5553,9 +6275,19 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "digits", rb_int_digits, -1);
- /* An obsolete class, use Integer */
- rb_define_const(rb_cObject, "Fixnum", rb_cInteger);
- rb_deprecate_constant(rb_cObject, "Fixnum");
+ rb_fix_to_s_static[0] = rb_fstring_literal("0");
+ rb_fix_to_s_static[1] = rb_fstring_literal("1");
+ rb_fix_to_s_static[2] = rb_fstring_literal("2");
+ rb_fix_to_s_static[3] = rb_fstring_literal("3");
+ rb_fix_to_s_static[4] = rb_fstring_literal("4");
+ rb_fix_to_s_static[5] = rb_fstring_literal("5");
+ rb_fix_to_s_static[6] = rb_fstring_literal("6");
+ rb_fix_to_s_static[7] = rb_fstring_literal("7");
+ rb_fix_to_s_static[8] = rb_fstring_literal("8");
+ rb_fix_to_s_static[9] = rb_fstring_literal("9");
+ for(int i = 0; i < 10; i++) {
+ rb_gc_register_mark_object(rb_fix_to_s_static[i]);
+ }
rb_cFloat = rb_define_class("Float", rb_cNumeric);
diff --git a/numeric.rb b/numeric.rb
index c892cbe6ef..f026679210 100644
--- a/numeric.rb
+++ b/numeric.rb
@@ -6,7 +6,17 @@ class Numeric
# Returns +true+ if +num+ is a real number (i.e. not Complex).
#
def real?
- return true
+ true
+ end
+
+ #
+ # call-seq:
+ # num.real -> self
+ #
+ # Returns self.
+ #
+ def real
+ self
end
#
@@ -19,7 +29,7 @@ class Numeric
# 1.integer? #=> true
#
def integer?
- return false
+ false
end
#
@@ -29,7 +39,7 @@ class Numeric
# Returns +true+ if +num+ is a finite number, otherwise returns +false+.
#
def finite?
- return true
+ true
end
#
@@ -40,8 +50,34 @@ class Numeric
# finite, <code>-Infinity</code>, or <code>+Infinity</code>.
#
def infinite?
- return nil
+ nil
+ end
+
+ #
+ # call-seq:
+ # num.imag -> 0
+ # num.imaginary -> 0
+ #
+ # Returns zero.
+ #
+ def imaginary
+ 0
end
+
+ alias imag imaginary
+
+ #
+ # call-seq:
+ # num.conj -> self
+ # num.conjugate -> self
+ #
+ # Returns self.
+ #
+ def conjugate
+ self
+ end
+
+ alias conj conjugate
end
class Integer
@@ -70,6 +106,17 @@ class Integer
Primitive.cexpr! 'rb_int_comp(self)'
end
+ # call-seq:
+ # int.abs -> integer
+ # int.magnitude -> integer
+ #
+ # Returns the absolute value of +int+.
+ #
+ # (-12345).abs #=> 12345
+ # -12345.abs #=> 12345
+ # 12345.abs #=> 12345
+ #
+ # Integer#magnitude is an alias for Integer#abs.
def abs
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_int_abs(self)'
@@ -135,13 +182,16 @@ class Integer
#
# Since +int+ is already an Integer, this always returns +true+.
def integer?
- return true
+ true
end
+ alias magnitude abs
+=begin
def magnitude
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_int_abs(self)'
end
+=end
# call-seq:
# int.odd? -> true or false
@@ -164,7 +214,7 @@ class Integer
#
# For example, <code>?a.ord</code> returns 97 both in 1.8 and 1.9.
def ord
- return self
+ self
end
#
@@ -194,7 +244,7 @@ class Integer
#
# #to_int is an alias for #to_i.
def to_i
- return self
+ self
end
# call-seq:
@@ -202,7 +252,7 @@ class Integer
#
# Since +int+ is already an Integer, returns +self+.
def to_int
- return self
+ self
end
# call-seq:
@@ -213,8 +263,67 @@ class Integer
Primitive.attr! 'inline'
Primitive.cexpr! 'rb_int_zero_p(self)'
end
+
+ # call-seq:
+ # ceildiv(other) -> integer
+ #
+ # Returns the result of division +self+ by +other+. The result is rounded up to the nearest integer.
+ #
+ # 3.ceildiv(3) # => 1
+ # 4.ceildiv(3) # => 2
+ #
+ # 4.ceildiv(-3) # => -1
+ # -4.ceildiv(3) # => -1
+ # -4.ceildiv(-3) # => 2
+ #
+ # 3.ceildiv(1.2) # => 3
+ def ceildiv(other)
+ -div(-other)
+ end
+
+ #
+ # call-seq:
+ # int.numerator -> self
+ #
+ # Returns self.
+ #
+ def numerator
+ self
+ end
+
+ #
+ # call-seq:
+ # int.denominator -> 1
+ #
+ # Returns 1.
+ #
+ def denominator
+ 1
+ end
end
+# call-seq:
+# Integer.try_convert(object) -> object, integer, or nil
+#
+# If +object+ is an \Integer object, returns +object+.
+# Integer.try_convert(1) # => 1
+#
+# Otherwise if +object+ responds to <tt>:to_int</tt>,
+# calls <tt>object.to_int</tt> and returns the result.
+# Integer.try_convert(1.25) # => 1
+#
+# Returns +nil+ if +object+ does not respond to <tt>:to_int</tt>
+# Integer.try_convert([]) # => nil
+#
+# Raises an exception unless <tt>object.to_int</tt> returns an \Integer object.
+#
+def Integer.try_convert(num)
+=begin
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_check_integer_type(num)'
+=end
+end if false
+
class Float
#
# call-seq:
@@ -223,7 +332,7 @@ class Float
# Since +float+ is already a Float, returns +self+.
#
def to_f
- return self
+ self
end
#
@@ -268,7 +377,7 @@ class Float
#
def zero?
Primitive.attr! 'inline'
- Primitive.cexpr! 'FLOAT_ZERO_P(self) ? Qtrue : Qfalse'
+ Primitive.cexpr! 'RBOOL(FLOAT_ZERO_P(self))'
end
#
@@ -279,7 +388,7 @@ class Float
#
def positive?
Primitive.attr! 'inline'
- Primitive.cexpr! 'RFLOAT_VALUE(self) > 0.0 ? Qtrue : Qfalse'
+ Primitive.cexpr! 'RBOOL(RFLOAT_VALUE(self) > 0.0)'
end
#
@@ -290,6 +399,7 @@ class Float
#
def negative?
Primitive.attr! 'inline'
- Primitive.cexpr! 'RFLOAT_VALUE(self) < 0.0 ? Qtrue : Qfalse'
+ Primitive.cexpr! 'RBOOL(RFLOAT_VALUE(self) < 0.0)'
end
+
end
diff --git a/object.c b/object.c
index 31633f91db..e1fc72c89f 100644
--- a/object.c
+++ b/object.c
@@ -33,27 +33,30 @@
#include "internal/string.h"
#include "internal/symbol.h"
#include "internal/variable.h"
+#include "variable.h"
#include "probes.h"
#include "ruby/encoding.h"
#include "ruby/st.h"
#include "ruby/util.h"
#include "ruby/assert.h"
#include "builtin.h"
+#include "shape.h"
/*!
- * \defgroup object Core objects and their operations
+ * \addtogroup object
* \{
*/
-VALUE rb_cBasicObject; /*!< BasicObject class */
-VALUE rb_mKernel; /*!< Kernel module */
-VALUE rb_cObject; /*!< Object class */
-VALUE rb_cModule; /*!< Module class */
-VALUE rb_cClass; /*!< Class class */
+VALUE rb_cBasicObject;
+VALUE rb_mKernel;
+VALUE rb_cObject;
+VALUE rb_cModule;
+VALUE rb_cClass;
+VALUE rb_cRefinement;
-VALUE rb_cNilClass; /*!< NilClass class */
-VALUE rb_cTrueClass; /*!< TrueClass class */
-VALUE rb_cFalseClass; /*!< FalseClass class */
+VALUE rb_cNilClass;
+VALUE rb_cTrueClass;
+VALUE rb_cFalseClass;
static VALUE rb_cNilClass_to_s;
static VALUE rb_cTrueClass_to_s;
@@ -77,56 +80,29 @@ static VALUE rb_cFalseClass_to_s;
/*! \endcond */
-/*!
- * Make the object invisible from Ruby code.
- *
- * It is useful to let Ruby's GC manage your internal data structure --
- * The object keeps being managed by GC, but \c ObjectSpace.each_object
- * never yields the object.
- *
- * Note that the object also lose a way to call a method on it.
- *
- * \param[in] obj a Ruby object
- * \sa rb_obj_reveal
- */
VALUE
rb_obj_hide(VALUE obj)
{
if (!SPECIAL_CONST_P(obj)) {
- RBASIC_CLEAR_CLASS(obj);
+ RBASIC_CLEAR_CLASS(obj);
}
return obj;
}
-/*!
- * Make a hidden object visible again.
- *
- * It is the caller's responsibility to pass the right \a klass
- * which \a obj originally used to belong to.
- *
- * \sa rb_obj_hide
- */
VALUE
rb_obj_reveal(VALUE obj, VALUE klass)
{
if (!SPECIAL_CONST_P(obj)) {
- RBASIC_SET_CLASS(obj, klass);
+ RBASIC_SET_CLASS(obj, klass);
}
return obj;
}
-/*!
- * Fills common (\c RBasic) fields in \a obj.
- *
- * \note Prefer rb_newobj_of() to this function.
- * \param[in,out] obj a Ruby object to be set up.
- * \param[in] klass \c obj will belong to this class.
- * \param[in] type one of \c ruby_value_type
- */
VALUE
rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
{
- RBASIC(obj)->flags = type;
+ VALUE ignored_flags = RUBY_FL_PROMOTED | RUBY_FL_SEEN_OBJ_ID;
+ RBASIC(obj)->flags = (type & ~ignored_flags) | (RBASIC(obj)->flags & ignored_flags);
RBASIC_SET_CLASS(obj, klass);
return obj;
}
@@ -143,17 +119,6 @@ rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
/* 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)
{
@@ -161,32 +126,23 @@ rb_equal(VALUE obj1, VALUE obj2)
if (obj1 == obj2) return Qtrue;
result = rb_equal_opt(obj1, obj2);
- if (result == Qundef) {
- result = rb_funcall(obj1, id_eq, 1, obj2);
+ if (UNDEF_P(result)) {
+ result = rb_funcall(obj1, id_eq, 1, obj2);
}
return RBOOL(RTEST(result));
}
-/**
- * Determines if \a obj1 and \a obj2 are equal in terms of
- * \c Object#eql?.
- *
- * \note It actually calls \c #eql? when necessary.
- * So you cannot implement \c #eql? with this function.
- * \retval non-zero if they are eql?
- * \retval zero if they are not eql?.
- */
int
rb_eql(VALUE obj1, VALUE obj2)
{
VALUE result;
- if (obj1 == obj2) return Qtrue;
+ if (obj1 == obj2) return TRUE;
result = rb_eql_opt(obj1, obj2);
- if (result == Qundef) {
- result = rb_funcall(obj1, id_eql, 1, obj2);
+ if (UNDEF_P(result)) {
+ result = rb_funcall(obj1, id_eql, 1, obj2);
}
- return RBOOL(RTEST(result));
+ return RTEST(result);
}
/**
@@ -251,7 +207,7 @@ VALUE rb_obj_hash(VALUE obj);
MJIT_FUNC_EXPORTED VALUE
rb_obj_not(VALUE obj)
{
- return RTEST(obj) ? Qfalse : Qtrue;
+ return RBOOL(!RTEST(obj));
}
/**
@@ -268,23 +224,15 @@ MJIT_FUNC_EXPORTED VALUE
rb_obj_not_equal(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_eq, 1, obj2);
- return RTEST(result) ? Qfalse : Qtrue;
+ return rb_obj_not(result);
}
-/*!
- * Looks up the nearest ancestor of \a cl, skipping singleton classes or
- * module inclusions.
- * It returns the \a cl itself if it is neither a singleton class or a module.
- *
- * \param[in] cl a Class object.
- * \return the ancestor class found, or Qfalse if nothing found.
- */
VALUE
rb_class_real(VALUE cl)
{
while (cl &&
((RBASIC(cl)->flags & FL_SINGLETON) || BUILTIN_TYPE(cl) == T_ICLASS)) {
- cl = RCLASS_SUPER(cl);
+ cl = RCLASS_SUPER(cl);
}
return cl;
}
@@ -322,33 +270,61 @@ rb_obj_singleton_class(VALUE obj)
MJIT_FUNC_EXPORTED void
rb_obj_copy_ivar(VALUE dest, VALUE obj)
{
- VALUE *dst_buf = 0;
- VALUE *src_buf = 0;
- uint32_t len = ROBJECT_EMBED_LEN_MAX;
+ RUBY_ASSERT(!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE));
- if (RBASIC(obj)->flags & ROBJECT_EMBED) {
- src_buf = ROBJECT(obj)->as.ary;
+ RUBY_ASSERT(BUILTIN_TYPE(dest) == BUILTIN_TYPE(obj));
+ rb_shape_t * src_shape = rb_shape_get_shape(obj);
- // embedded -> embedded
- if (RBASIC(dest)->flags & ROBJECT_EMBED) {
- dst_buf = ROBJECT(dest)->as.ary;
- }
- // embedded -> extended
- else {
- dst_buf = ROBJECT(dest)->as.heap.ivptr;
- }
+ if (rb_shape_id(src_shape) == OBJ_TOO_COMPLEX_SHAPE_ID) {
+ st_table *table = st_copy(ROBJECT_IV_HASH(obj));
+
+ rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table);
+ rb_shape_set_too_complex(dest);
+
+ ROBJECT(dest)->as.heap.ivptr = (VALUE *)table;
+
+ return;
}
- // extended -> extended
- else {
- uint32_t src_len = ROBJECT(obj)->as.heap.numiv;
- uint32_t dst_len = ROBJECT(dest)->as.heap.numiv;
- len = src_len < dst_len ? src_len : dst_len;
- dst_buf = ROBJECT(dest)->as.heap.ivptr;
- src_buf = ROBJECT(obj)->as.heap.ivptr;
+ uint32_t src_num_ivs = RBASIC_IV_COUNT(obj);
+ rb_shape_t * shape_to_set_on_dest = src_shape;
+ VALUE * src_buf;
+ VALUE * dest_buf;
+
+ if (!src_num_ivs) {
+ return;
+ }
+
+ // The copy should be mutable, so we don't want the frozen shape
+ if (rb_shape_frozen_shape_p(src_shape)) {
+ shape_to_set_on_dest = rb_shape_get_parent(src_shape);
+ }
+
+ src_buf = ROBJECT_IVPTR(obj);
+ dest_buf = ROBJECT_IVPTR(dest);
+
+ rb_shape_t * initial_shape = rb_shape_get_shape(dest);
+
+ if (initial_shape->size_pool_index != src_shape->size_pool_index) {
+ RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
+
+ shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
}
- MEMCPY(dst_buf, src_buf, VALUE, len);
+ RUBY_ASSERT(src_num_ivs <= shape_to_set_on_dest->capacity);
+ if (initial_shape->capacity < shape_to_set_on_dest->capacity) {
+ rb_ensure_iv_list_size(dest, initial_shape->capacity, shape_to_set_on_dest->capacity);
+ dest_buf = ROBJECT_IVPTR(dest);
+ }
+
+ MEMCPY(dest_buf, src_buf, VALUE, src_num_ivs);
+
+ // Fire write barriers
+ for (uint32_t i = 0; i < src_num_ivs; i++) {
+ RB_OBJ_WRITTEN(dest, Qundef, dest_buf[i]);
+ }
+
+ rb_shape_set_shape(dest, shape_to_set_on_dest);
}
static void
@@ -358,12 +334,14 @@ init_copy(VALUE dest, VALUE obj)
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
+ // Copies the shape id from obj to dest
RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR);
rb_copy_wb_protected_attribute(dest, obj);
rb_copy_generic_ivar(dest, obj);
rb_gc_copy_finalizer(dest, obj);
+
if (RB_TYPE_P(obj, T_OBJECT)) {
- rb_obj_copy_ivar(dest, obj);
+ rb_obj_copy_ivar(dest, obj);
}
}
@@ -380,10 +358,10 @@ special_object_p(VALUE obj)
case T_SYMBOL:
case T_RATIONAL:
case T_COMPLEX:
- /* not a comprehensive list */
- return TRUE;
+ /* not a comprehensive list */
+ return TRUE;
default:
- return FALSE;
+ return FALSE;
}
}
@@ -407,7 +385,7 @@ rb_obj_clone2(rb_execution_context_t *ec, VALUE obj, VALUE freeze)
{
VALUE kwfreeze = obj_freeze_opt(freeze);
if (!special_object_p(obj))
- return mutable_obj_clone(obj, kwfreeze);
+ return mutable_obj_clone(obj, kwfreeze);
return immutable_obj_clone(obj, kwfreeze);
}
@@ -427,12 +405,12 @@ rb_get_freeze_opt(int argc, VALUE *argv)
VALUE kwfreeze = Qnil;
if (!keyword_ids[0]) {
- CONST_ID(keyword_ids[0], "freeze");
+ CONST_ID(keyword_ids[0], "freeze");
}
rb_scan_args(argc, argv, "0:", &opt);
if (!NIL_P(opt)) {
- rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
- if (kwfreeze != Qundef)
+ rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
+ if (!UNDEF_P(kwfreeze))
kwfreeze = obj_freeze_opt(kwfreeze);
}
return kwfreeze;
@@ -442,8 +420,8 @@ static VALUE
immutable_obj_clone(VALUE obj, VALUE kwfreeze)
{
if (kwfreeze == Qfalse)
- rb_raise(rb_eArgError, "can't unfreeze %"PRIsVALUE,
- rb_obj_class(obj));
+ rb_raise(rb_eArgError, "can't unfreeze %"PRIsVALUE,
+ rb_obj_class(obj));
return obj;
}
@@ -458,7 +436,7 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze)
singleton = rb_singleton_class_clone_and_attach(obj, clone);
RBASIC_SET_CLASS(clone, singleton);
if (FL_TEST(singleton, FL_SINGLETON)) {
- rb_singleton_class_attached(singleton, clone);
+ rb_singleton_class_attached(singleton, clone);
}
init_copy(clone, obj);
@@ -466,7 +444,10 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze)
switch (kwfreeze) {
case Qnil:
rb_funcall(clone, id_init_clone, 1, obj);
- RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
+ RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
+ if (RB_OBJ_FROZEN(obj)) {
+ rb_shape_transition_shape_frozen(clone);
+ }
break;
case Qtrue:
{
@@ -482,6 +463,7 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze)
argv[1] = freeze_true_hash;
rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS);
RBASIC(clone)->flags |= FL_FREEZE;
+ rb_shape_transition_shape_frozen(clone);
break;
}
case Qfalse:
@@ -506,12 +488,6 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze)
return clone;
}
-/**
- * :nodoc
- *--
- * Almost same as \c Object#clone
- *++
- */
VALUE
rb_obj_clone(VALUE obj)
{
@@ -519,7 +495,7 @@ rb_obj_clone(VALUE obj)
return mutable_obj_clone(obj, Qnil);
}
-/**
+/*
* call-seq:
* obj.dup -> an_object
*
@@ -557,9 +533,6 @@ rb_obj_clone(VALUE obj)
*
* s3 = s1.dup #=> #<Klass:0x401c1084>
* s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401c1084>
- *--
- * Equivalent to \c Object\#dup in Ruby
- *++
*/
VALUE
rb_obj_dup(VALUE obj)
@@ -567,7 +540,7 @@ rb_obj_dup(VALUE obj)
VALUE dup;
if (special_object_p(obj)) {
- return obj;
+ return obj;
}
dup = rb_obj_alloc(rb_obj_class(obj));
init_copy(dup, obj);
@@ -619,7 +592,7 @@ rb_obj_init_copy(VALUE obj, VALUE orig)
if (obj == orig) return obj;
rb_check_frozen(obj);
if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) {
- rb_raise(rb_eTypeError, "initialize_copy should take same class object");
+ rb_raise(rb_eTypeError, "initialize_copy should take same class object");
}
return obj;
}
@@ -662,7 +635,7 @@ rb_obj_init_clone(int argc, VALUE *argv, VALUE obj)
return obj;
}
-/**
+/*
* call-seq:
* obj.to_s -> string
*
@@ -671,9 +644,6 @@ rb_obj_init_clone(int argc, VALUE *argv, VALUE obj)
* case, the top-level object that is the initial execution context
* of Ruby programs returns ``main''.
*
- *--
- * Default implementation of \c #to_s.
- *++
*/
VALUE
rb_any_to_s(VALUE obj)
@@ -686,18 +656,6 @@ rb_any_to_s(VALUE obj)
return str;
}
-/*!
- * Convenient wrapper of \c Object#inspect.
- * Returns a human-readable string representation of \a obj,
- * similarly to \c Object#inspect.
- *
- * Unlike Ruby-level \c #inspect, it escapes characters to keep the
- * result compatible to the default internal or external encoding.
- * If the default internal or external encoding is ASCII compatible,
- * the encoding of the inspected result must be compatible with it.
- * If the default internal or external encoding is ASCII incompatible,
- * the result must be ASCII only.
- */
VALUE
rb_inspect(VALUE obj)
{
@@ -706,12 +664,12 @@ rb_inspect(VALUE obj)
rb_encoding *enc = rb_default_internal_encoding();
if (enc == NULL) enc = rb_default_external_encoding();
if (!rb_enc_asciicompat(enc)) {
- if (!rb_enc_str_asciionly_p(str))
- return rb_str_escape(str);
- return str;
+ if (!rb_enc_str_asciionly_p(str))
+ return rb_str_escape(str);
+ return str;
}
if (rb_enc_get(str) != enc && !rb_enc_str_asciionly_p(str))
- return rb_str_escape(str);
+ return rb_str_escape(str);
return str;
}
@@ -726,14 +684,14 @@ inspect_i(st_data_t k, st_data_t v, st_data_t a)
if (CLASS_OF(value) == 0) return ST_CONTINUE;
if (!rb_is_instance_id(id)) return ST_CONTINUE;
if (RSTRING_PTR(str)[0] == '-') { /* first element */
- RSTRING_PTR(str)[0] = '#';
- rb_str_cat2(str, " ");
+ RSTRING_PTR(str)[0] = '#';
+ rb_str_cat2(str, " ");
}
else {
- rb_str_cat2(str, ", ");
+ rb_str_cat2(str, ", ");
}
- rb_str_catf(str, "%"PRIsVALUE"=%+"PRIsVALUE,
- rb_id2str(id), value);
+ rb_str_catf(str, "%"PRIsVALUE"=", rb_id2str(id));
+ rb_str_buf_append(str, rb_inspect(value));
return ST_CONTINUE;
}
@@ -742,10 +700,10 @@ static VALUE
inspect_obj(VALUE obj, VALUE str, int recur)
{
if (recur) {
- rb_str_cat2(str, " ...");
+ rb_str_cat2(str, " ...");
}
else {
- rb_ivar_foreach(obj, inspect_i, str);
+ rb_ivar_foreach(obj, inspect_i, str);
}
rb_str_cat2(str, ">");
RSTRING_PTR(str)[0] = '#';
@@ -784,14 +742,14 @@ static VALUE
rb_obj_inspect(VALUE obj)
{
if (rb_ivar_count(obj) > 0) {
- VALUE str;
- VALUE c = rb_class_name(CLASS_OF(obj));
+ VALUE str;
+ VALUE c = rb_class_name(CLASS_OF(obj));
- str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
- return rb_exec_recursive(inspect_obj, obj, str);
+ str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
+ return rb_exec_recursive(inspect_obj, obj, str);
}
else {
- return rb_any_to_s(obj);
+ return rb_any_to_s(obj);
}
}
@@ -802,17 +760,17 @@ class_or_module_required(VALUE c)
case T_MODULE:
case T_CLASS:
case T_ICLASS:
- break;
+ break;
default:
- rb_raise(rb_eTypeError, "class or module required");
+ rb_raise(rb_eTypeError, "class or module required");
}
return c;
}
static VALUE class_search_ancestor(VALUE cl, VALUE c);
-/**
+/*
* call-seq:
* obj.instance_of?(class) -> true or false
*
@@ -827,13 +785,6 @@ static VALUE class_search_ancestor(VALUE cl, VALUE c);
* b.instance_of? A #=> false
* b.instance_of? B #=> true
* b.instance_of? C #=> false
- *--
- * Determines if \a obj is an instance of \a c.
- *
- * Equivalent to \c Object\#is_instance_of in Ruby.
- * \param[in] obj the object to be determined.
- * \param[in] c a Class object
- *++
*/
VALUE
@@ -843,8 +794,28 @@ rb_obj_is_instance_of(VALUE obj, VALUE c)
return RBOOL(rb_obj_class(obj) == c);
}
+// Returns whether c is a proper (c != cl) subclass of cl
+// Both c and cl must be T_CLASS
+static VALUE
+class_search_class_ancestor(VALUE cl, VALUE c)
+{
+ RUBY_ASSERT(RB_TYPE_P(c, T_CLASS));
+ RUBY_ASSERT(RB_TYPE_P(cl, T_CLASS));
-/**
+ size_t c_depth = RCLASS_SUPERCLASS_DEPTH(c);
+ size_t cl_depth = RCLASS_SUPERCLASS_DEPTH(cl);
+ VALUE *classes = RCLASS_SUPERCLASSES(cl);
+
+ // If c's inheritance chain is longer, it cannot be an ancestor
+ // We are checking for a proper subclass so don't check if they are equal
+ if (cl_depth <= c_depth)
+ return Qfalse;
+
+ // Otherwise check that c is in cl's inheritance chain
+ return RBOOL(classes[c_depth] == c);
+}
+
+/*
* call-seq:
* obj.is_a?(class) -> true or false
* obj.kind_of?(class) -> true or false
@@ -870,13 +841,6 @@ rb_obj_is_instance_of(VALUE obj, VALUE c)
* b.kind_of? B #=> true
* b.kind_of? C #=> false
* b.kind_of? M #=> true
- *--
- * Determines if \a obj is a kind of \a c.
- *
- * Equivalent to \c Object\#kind_of? in Ruby.
- * \param[in] obj the object to be determined
- * \param[in] c a Module object.
- *++
*/
VALUE
@@ -884,17 +848,54 @@ rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
- c = class_or_module_required(c);
- return RBOOL(class_search_ancestor(cl, RCLASS_ORIGIN(c)));
+ RUBY_ASSERT(RB_TYPE_P(cl, T_CLASS));
+
+ // Fastest path: If the object's class is an exact match we know `c` is a
+ // class without checking type and can return immediately.
+ if (cl == c) return Qtrue;
+
+ // Note: YJIT needs this function to never allocate and never raise when
+ // `c` is a class or a module.
+
+ if (LIKELY(RB_TYPE_P(c, T_CLASS))) {
+ // Fast path: Both are T_CLASS
+ return class_search_class_ancestor(cl, c);
+ }
+ else if (RB_TYPE_P(c, T_ICLASS)) {
+ // First check if we inherit the includer
+ // If we do we can return true immediately
+ VALUE includer = RCLASS_INCLUDER(c);
+ if (cl == includer) return Qtrue;
+
+ // Usually includer is a T_CLASS here, except when including into an
+ // already included Module.
+ // If it is a class, attempt the fast class-to-class check and return
+ // true if there is a match.
+ if (RB_TYPE_P(includer, T_CLASS) && class_search_class_ancestor(cl, includer))
+ return Qtrue;
+
+ // We don't include the ICLASS directly, so must check if we inherit
+ // the module via another include
+ return RBOOL(class_search_ancestor(cl, RCLASS_ORIGIN(c)));
+ }
+ else if (RB_TYPE_P(c, T_MODULE)) {
+ // Slow path: check each ancestor in the linked list and its method table
+ return RBOOL(class_search_ancestor(cl, RCLASS_ORIGIN(c)));
+ }
+ else {
+ rb_raise(rb_eTypeError, "class or module required");
+ UNREACHABLE_RETURN(Qfalse);
+ }
}
+
static VALUE
class_search_ancestor(VALUE cl, VALUE c)
{
while (cl) {
- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
- return cl;
- cl = RCLASS_SUPER(cl);
+ if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
+ return cl;
+ cl = RCLASS_SUPER(cl);
}
return 0;
}
@@ -1096,6 +1097,28 @@ rb_class_search_ancestor(VALUE cl, VALUE c)
*/
#define rb_obj_singleton_method_undefined rb_obj_dummy1
+/* Document-method: const_added
+ *
+ * call-seq:
+ * const_added(const_name)
+ *
+ * Invoked as a callback whenever a constant is assigned on the receiver
+ *
+ * module Chatty
+ * def self.const_added(const_name)
+ * super
+ * puts "Added #{const_name.inspect}"
+ * end
+ * FOO = 1
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * Added :FOO
+ *
+ */
+#define rb_obj_mod_const_added rb_obj_dummy1
+
/*
* Document-method: extended
*
@@ -1191,103 +1214,7 @@ rb_obj_dummy1(VALUE _x, VALUE _y)
return rb_obj_dummy();
}
-/**
- * call-seq:
- * obj.tainted? -> false
- *
- * Returns false. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-VALUE
-rb_obj_tainted(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "Object#tainted?", NULL);
- return Qfalse;
-}
-
-/**
- * call-seq:
- * obj.taint -> obj
- *
- * Returns object. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-VALUE
-rb_obj_taint(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "Object#taint", NULL);
- return obj;
-}
-
-
-/**
- * call-seq:
- * obj.untaint -> obj
- *
- * Returns object. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-VALUE
-rb_obj_untaint(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "Object#untaint", NULL);
- return obj;
-}
-
-/**
- * call-seq:
- * obj.untrusted? -> false
- *
- * Returns false. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-VALUE
-rb_obj_untrusted(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "Object#untrusted?", NULL);
- return Qfalse;
-}
-
-/**
- * call-seq:
- * obj.untrust -> obj
- *
- * Returns object. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-VALUE
-rb_obj_untrust(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "Object#untrust", NULL);
- return obj;
-}
-
-
-/**
- * call-seq:
- * obj.trust -> obj
- *
- * Returns object. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-VALUE
-rb_obj_trust(VALUE obj)
-{
- rb_warn_deprecated_to_remove_at(3.2, "Object#trust", NULL);
- return obj;
-}
-
-/**
- * Does nothing. This method is deprecated and will be removed in Ruby 3.2.
- */
-
-void
-rb_obj_infect(VALUE victim, VALUE carrier)
-{
- rb_warn_deprecated_to_remove_at(3.2, "rb_obj_infect", NULL);
-}
-
-/**
+/*
* call-seq:
* obj.freeze -> obj
*
@@ -1309,21 +1236,16 @@ rb_obj_infect(VALUE victim, VALUE carrier)
*
* Objects of the following classes are always frozen: Integer,
* Float, Symbol.
- *--
- * Make the object unmodifiable. Equivalent to \c Object\#freeze in Ruby.
- * \param[in,out] obj the object to be frozen
- * \return the frozen object
- *++
*/
VALUE
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
- OBJ_FREEZE(obj);
- if (SPECIAL_CONST_P(obj)) {
- rb_bug("special consts should be frozen.");
- }
+ OBJ_FREEZE(obj);
+ if (SPECIAL_CONST_P(obj)) {
+ rb_bug("special consts should be frozen.");
+ }
}
return obj;
}
@@ -1348,8 +1270,8 @@ rb_obj_frozen_p(VALUE obj)
* Always returns the empty string.
*/
-static VALUE
-nil_to_s(VALUE obj)
+MJIT_FUNC_EXPORTED VALUE
+rb_nil_to_s(VALUE obj)
{
return rb_cNilClass_to_s;
}
@@ -1406,6 +1328,8 @@ nil_inspect(VALUE obj)
* nil =~ other -> nil
*
* Dummy pattern matching -- always returns nil.
+ *
+ * This method makes it possible to `while gets =~ /re/ do`.
*/
static VALUE
@@ -1431,8 +1355,8 @@ nil_match(VALUE obj1, VALUE obj2)
* The string representation of <code>true</code> is "true".
*/
-static VALUE
-true_to_s(VALUE obj)
+MJIT_FUNC_EXPORTED VALUE
+rb_true_to_s(VALUE obj)
{
return rb_cTrueClass_to_s;
}
@@ -1487,7 +1411,7 @@ true_or(VALUE obj, VALUE obj2)
static VALUE
true_xor(VALUE obj, VALUE obj2)
{
- return RTEST(obj2)?Qfalse:Qtrue;
+ return rb_obj_not(obj2);
}
@@ -1508,8 +1432,8 @@ true_xor(VALUE obj, VALUE obj2)
* The string representation of <code>false</code> is "false".
*/
-static VALUE
-false_to_s(VALUE obj)
+MJIT_FUNC_EXPORTED VALUE
+rb_false_to_s(VALUE obj)
{
return rb_cFalseClass_to_s;
}
@@ -1585,27 +1509,6 @@ rb_false(VALUE obj)
return Qfalse;
}
-
-/*
- * call-seq:
- * obj =~ other -> nil
- *
- * This method is deprecated.
- *
- * 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_category_warn(RB_WARN_CATEGORY_DEPRECATED, "deprecated Object#=~ is called on %"PRIsVALUE
- "; it always returns nil", rb_obj_class(obj1));
- }
- return Qnil;
-}
-
/*
* call-seq:
* obj !~ other -> true or false
@@ -1618,7 +1521,7 @@ static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_match, 1, obj2);
- return RTEST(result) ? Qfalse : Qtrue;
+ return rb_obj_not(result);
}
@@ -1644,7 +1547,7 @@ static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
if (rb_equal(obj1, obj2))
- return INT2FIX(0);
+ return INT2FIX(0);
return Qnil;
}
@@ -1685,37 +1588,37 @@ rb_obj_cmp(VALUE obj1, VALUE obj2)
* show information on the thing we're attached to as well.
*/
-static VALUE
+MJIT_FUNC_EXPORTED VALUE
rb_mod_to_s(VALUE klass)
{
ID id_defined_at;
VALUE refined_class, defined_at;
if (FL_TEST(klass, FL_SINGLETON)) {
- VALUE s = rb_usascii_str_new2("#<Class:");
- VALUE v = rb_ivar_get(klass, id__attached__);
-
- if (CLASS_OR_MODULE_P(v)) {
- rb_str_append(s, rb_inspect(v));
- }
- else {
- rb_str_append(s, rb_any_to_s(v));
- }
- rb_str_cat2(s, ">");
-
- return s;
+ VALUE s = rb_usascii_str_new2("#<Class:");
+ VALUE v = rb_ivar_get(klass, id__attached__);
+
+ if (CLASS_OR_MODULE_P(v)) {
+ rb_str_append(s, rb_inspect(v));
+ }
+ else {
+ rb_str_append(s, rb_any_to_s(v));
+ }
+ rb_str_cat2(s, ">");
+
+ return s;
}
refined_class = rb_refinement_module_get_refined_class(klass);
if (!NIL_P(refined_class)) {
- VALUE s = rb_usascii_str_new2("#<refinement:");
-
- rb_str_concat(s, rb_inspect(refined_class));
- rb_str_cat2(s, "@");
- CONST_ID(id_defined_at, "__defined_at__");
- defined_at = rb_attr_get(klass, id_defined_at);
- rb_str_concat(s, rb_inspect(defined_at));
- rb_str_cat2(s, ">");
- return s;
+ VALUE s = rb_usascii_str_new2("#<refinement:");
+
+ rb_str_concat(s, rb_inspect(refined_class));
+ rb_str_cat2(s, "@");
+ CONST_ID(id_defined_at, "__defined_at__");
+ defined_at = rb_attr_get(klass, id_defined_at);
+ rb_str_concat(s, rb_inspect(defined_at));
+ rb_str_cat2(s, ">");
+ return s;
}
return rb_class_name(klass);
}
@@ -1752,7 +1655,7 @@ rb_mod_eqq(VALUE mod, VALUE arg)
return rb_obj_is_kind_of(arg, mod);
}
-/**
+/*
* call-seq:
* mod <= other -> true, false, or nil
*
@@ -1761,32 +1664,47 @@ rb_mod_eqq(VALUE mod, VALUE arg)
* <code>nil</code> if there's no relationship between the two.
* (Think of the relationship in terms of the class definition:
* "class A < B" implies "A < B".)
- *--
- * Determines if \a mod inherits \a arg. Equivalent to \c Module\#<= in Ruby
- *
- * \param[in] mod a Module object
- * \param[in] arg another Module object or an iclass of a module
- * \retval Qtrue if \a mod inherits \a arg, or \a mod equals \a arg
- * \retval Qfalse if \a arg inherits \a mod
- * \retval Qnil if otherwise
- *++
*/
VALUE
rb_class_inherited_p(VALUE mod, VALUE arg)
{
if (mod == arg) return Qtrue;
- if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
- rb_raise(rb_eTypeError, "compared with non class/module");
- }
- if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
- return Qtrue;
+
+ if (RB_TYPE_P(arg, T_CLASS) && RB_TYPE_P(mod, T_CLASS)) {
+ // comparison between classes
+ size_t mod_depth = RCLASS_SUPERCLASS_DEPTH(mod);
+ size_t arg_depth = RCLASS_SUPERCLASS_DEPTH(arg);
+ if (arg_depth < mod_depth) {
+ // check if mod < arg
+ return RCLASS_SUPERCLASSES(mod)[arg_depth] == arg ?
+ Qtrue :
+ Qnil;
+ }
+ else if (arg_depth > mod_depth) {
+ // check if mod > arg
+ return RCLASS_SUPERCLASSES(arg)[mod_depth] == mod ?
+ Qfalse :
+ Qnil;
+ }
+ else {
+ // Depths match, and we know they aren't equal: no relation
+ return Qnil;
+ }
}
- /* not mod < arg; check if mod > arg */
- if (class_search_ancestor(arg, mod)) {
- return Qfalse;
+ else {
+ if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
+ rb_raise(rb_eTypeError, "compared with non class/module");
+ }
+ if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) {
+ return Qtrue;
+ }
+ /* not mod < arg; check if mod > arg */
+ if (class_search_ancestor(arg, mod)) {
+ return Qfalse;
+ }
+ return Qnil;
}
- return Qnil;
}
/*
@@ -1794,7 +1712,9 @@ rb_class_inherited_p(VALUE mod, VALUE arg)
* mod < other -> true, false, or nil
*
* Returns true if <i>mod</i> is a subclass of <i>other</i>. Returns
- * <code>nil</code> if there's no relationship between the two.
+ * <code>false</code> if <i>mod</i> is the same as <i>other</i>
+ * or <i>mod</i> is an ancestor of <i>other</i>.
+ * Returns <code>nil</code> if there's no relationship between the two.
* (Think of the relationship in terms of the class definition:
* "class A < B" implies "A < B".)
*
@@ -1824,7 +1744,7 @@ static VALUE
rb_mod_ge(VALUE mod, VALUE arg)
{
if (!CLASS_OR_MODULE_P(arg)) {
- rb_raise(rb_eTypeError, "compared with non class/module");
+ rb_raise(rb_eTypeError, "compared with non class/module");
}
return rb_class_inherited_p(arg, mod);
@@ -1835,7 +1755,9 @@ rb_mod_ge(VALUE mod, VALUE arg)
* mod > other -> true, false, or nil
*
* Returns true if <i>mod</i> is an ancestor of <i>other</i>. Returns
- * <code>nil</code> if there's no relationship between the two.
+ * <code>false</code> if <i>mod</i> is the same as <i>other</i>
+ * or <i>mod</i> is a descendant of <i>other</i>.
+ * Returns <code>nil</code> if there's no relationship between the two.
* (Think of the relationship in terms of the class definition:
* "class A < B" implies "B > A".)
*
@@ -1867,31 +1789,18 @@ rb_mod_cmp(VALUE mod, VALUE arg)
if (mod == arg) return INT2FIX(0);
if (!CLASS_OR_MODULE_P(arg)) {
- return Qnil;
+ return Qnil;
}
cmp = rb_class_inherited_p(mod, arg);
if (NIL_P(cmp)) return Qnil;
if (cmp) {
- return INT2FIX(-1);
+ return INT2FIX(-1);
}
return INT2FIX(1);
}
-static VALUE
-rb_module_s_alloc(VALUE klass)
-{
- VALUE mod = rb_module_new();
-
- RBASIC_SET_CLASS(mod, klass);
- return mod;
-}
-
-static VALUE
-rb_class_s_alloc(VALUE klass)
-{
- return rb_class_boot(0);
-}
+static VALUE rb_mod_initialize_exec(VALUE module);
/*
* call-seq:
@@ -1922,8 +1831,14 @@ rb_class_s_alloc(VALUE klass)
static VALUE
rb_mod_initialize(VALUE module)
{
+ return rb_mod_initialize_exec(module);
+}
+
+static VALUE
+rb_mod_initialize_exec(VALUE module)
+{
if (rb_block_given_p()) {
- rb_mod_module_exec(1, &module, module);
+ rb_mod_module_exec(1, &module, module);
}
return Qnil;
}
@@ -1976,22 +1891,22 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass)
VALUE super;
if (RCLASS_SUPER(klass) != 0 || klass == rb_cBasicObject) {
- rb_raise(rb_eTypeError, "already initialized class");
+ rb_raise(rb_eTypeError, "already initialized class");
}
if (rb_check_arity(argc, 0, 1) == 0) {
- super = rb_cObject;
+ super = rb_cObject;
}
else {
super = argv[0];
- rb_check_inheritable(super);
- if (super != rb_cBasicObject && !RCLASS_SUPER(super)) {
- rb_raise(rb_eTypeError, "can't inherit uninitialized class");
- }
+ rb_check_inheritable(super);
+ if (super != rb_cBasicObject && !RCLASS_SUPER(super)) {
+ rb_raise(rb_eTypeError, "can't inherit uninitialized class");
+ }
}
RCLASS_SET_SUPER(klass, super);
rb_make_metaclass(klass, RBASIC(super)->klass);
rb_class_inherited(super, klass);
- rb_mod_initialize(klass);
+ rb_mod_initialize_exec(klass);
return klass;
}
@@ -2001,7 +1916,7 @@ void
rb_undefined_alloc(VALUE klass)
{
rb_raise(rb_eTypeError, "allocator undefined for %"PRIsVALUE,
- klass);
+ klass);
}
static rb_alloc_func_t class_get_alloc_func(VALUE klass);
@@ -2053,14 +1968,14 @@ class_get_alloc_func(VALUE klass)
rb_alloc_func_t allocator;
if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
- rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
+ rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
}
if (FL_TEST(klass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "can't create instance of singleton class");
+ rb_raise(rb_eTypeError, "can't create instance of singleton class");
}
allocator = rb_get_alloc_func(klass);
if (!allocator) {
- rb_undefined_alloc(klass);
+ rb_undefined_alloc(klass);
}
return allocator;
}
@@ -2075,25 +1990,11 @@ class_call_alloc_func(rb_alloc_func_t allocator, VALUE klass)
obj = (*allocator)(klass);
if (rb_obj_class(obj) != rb_class_real(klass)) {
- rb_raise(rb_eTypeError, "wrong instance allocation");
+ rb_raise(rb_eTypeError, "wrong instance allocation");
}
return obj;
}
-/**
- * Allocates an instance of \a klass
- *
- * \note It calls the allocator defined by {rb_define_alloc_func}.
- * So you cannot use this function to define an allocator.
- * Use {rb_newobj_of}, {TypedData_Make_Struct} or others, instead.
- * \note Usually prefer rb_class_new_instance to rb_obj_alloc and rb_obj_call_init
- * \param[in] klass a Class object
- * \sa rb_class_new_instance
- * \sa rb_obj_call_init
- * \sa rb_define_alloc_func
- * \sa rb_newobj_of
- * \sa TypedData_Make_Struct
- */
VALUE
rb_obj_alloc(VALUE klass)
{
@@ -2135,28 +2036,10 @@ rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat)
return obj;
}
-/**
- * Allocates and initializes an instance of \a klass.
- *
- * Equivalent to \c Class\#new in Ruby
- *
- * \param[in] argc the number of arguments to \c #initialize
- * \param[in] argv a pointer to an array of arguments to \c #initialize
- * \param[in] klass a Class object
- * \return the new instance of \a klass
- * \sa rb_obj_call_init
- * \sa rb_obj_alloc
- */
VALUE
rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
{
- VALUE obj;
- Check_Type(klass, T_CLASS);
-
- obj = rb_class_alloc(klass);
- rb_obj_call_init_kw(obj, argc, argv, RB_NO_KEYWORDS);
-
- return obj;
+ return rb_class_new_instance_kw(argc, argv, klass, RB_NO_KEYWORDS);
}
/**
@@ -2189,28 +2072,25 @@ rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
VALUE
rb_class_superclass(VALUE klass)
{
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS));
+
VALUE super = RCLASS_SUPER(klass);
if (!super) {
- if (klass == rb_cBasicObject) return Qnil;
- rb_raise(rb_eTypeError, "uninitialized class");
+ if (klass == rb_cBasicObject) return Qnil;
+ rb_raise(rb_eTypeError, "uninitialized class");
}
- while (RB_TYPE_P(super, T_ICLASS)) {
- super = RCLASS_SUPER(super);
+
+ if (!RCLASS_SUPERCLASS_DEPTH(klass)) {
+ return Qnil;
}
- if (!super) {
- return Qnil;
+ else {
+ super = RCLASS_SUPERCLASSES(klass)[RCLASS_SUPERCLASS_DEPTH(klass) - 1];
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS));
+ return super;
}
- return super;
}
-/**
- * Returns the superclass of \a klass
- * The return value might be an iclass of a module, unlike rb_class_superclass.
- *
- * Also it returns Qfalse when \a klass does not have a parent class.
- * \sa rb_class_superclass
- */
VALUE
rb_class_get_superclass(VALUE klass)
{
@@ -2230,15 +2110,15 @@ static const char bad_attr_name[] = "invalid attribute name `%1$s'";
check_setter_id(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message))
static ID
check_setter_id(VALUE obj, VALUE *pname,
- int (*valid_id_p)(ID), int (*valid_name_p)(VALUE),
- const char *message, size_t message_len)
+ int (*valid_id_p)(ID), int (*valid_name_p)(VALUE),
+ const char *message, size_t message_len)
{
ID id = rb_check_id(pname);
VALUE name = *pname;
if (id ? !valid_id_p(id) : !valid_name_p(name)) {
- rb_name_err_raise_str(rb_fstring_new(message, message_len),
- obj, name);
+ rb_name_err_raise_str(rb_fstring_new(message, message_len),
+ obj, name);
}
return id;
}
@@ -2284,9 +2164,9 @@ rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
VALUE names = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- ID id = id_for_attr(klass, argv[i]);
- rb_attr(klass, id, TRUE, FALSE, TRUE);
- rb_ary_push(names, ID2SYM(id));
+ ID id = id_for_attr(klass, argv[i]);
+ rb_attr(klass, id, TRUE, FALSE, TRUE);
+ rb_ary_push(names, ID2SYM(id));
}
return names;
}
@@ -2310,14 +2190,14 @@ VALUE
rb_mod_attr(int argc, VALUE *argv, VALUE klass)
{
if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) {
- 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;
+ 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);
}
@@ -2340,9 +2220,9 @@ rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
VALUE names = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- ID id = id_for_attr(klass, argv[i]);
- rb_attr(klass, id, FALSE, TRUE, TRUE);
- rb_ary_push(names, ID2SYM(rb_id_attrset(id)));
+ 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 names;
}
@@ -2372,11 +2252,11 @@ rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
VALUE names = rb_ary_new2(argc * 2);
for (i=0; i<argc; i++) {
- ID id = id_for_attr(klass, argv[i]);
+ 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)));
+ rb_attr(klass, id, TRUE, TRUE, TRUE);
+ rb_ary_push(names, ID2SYM(id));
+ rb_ary_push(names, ID2SYM(rb_id_attrset(id)));
}
return names;
}
@@ -2434,17 +2314,17 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
recur = (argc == 1) ? Qtrue : argv[1];
if (SYMBOL_P(name)) {
- if (!rb_is_const_sym(name)) goto wrong_name;
- id = rb_check_id(&name);
- if (!id) return rb_const_missing(mod, name);
- return RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
+ if (!rb_is_const_sym(name)) goto wrong_name;
+ id = rb_check_id(&name);
+ if (!id) return rb_const_missing(mod, name);
+ return RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
}
path = StringValuePtr(name);
enc = rb_enc_get(name);
if (!rb_enc_asciicompat(enc)) {
- rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
+ rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
}
pbeg = p = path;
@@ -2455,53 +2335,53 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
}
if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
- mod = rb_cObject;
- p += 2;
- pbeg = p;
+ mod = rb_cObject;
+ p += 2;
+ pbeg = p;
}
while (p < pend) {
- VALUE part;
- long len, beglen;
-
- while (p < pend && *p != ':') p++;
-
- if (pbeg == p) goto wrong_name;
-
- id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
- beglen = pbeg-path;
-
- if (p < pend && p[0] == ':') {
- if (p + 2 >= pend || p[1] != ':') goto wrong_name;
- p += 2;
- pbeg = p;
- }
-
- if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
- QUOTE(name));
- }
-
- if (!id) {
- part = rb_str_subseq(name, beglen, len);
- OBJ_FREEZE(part);
- if (!rb_is_const_name(part)) {
- name = part;
- goto wrong_name;
- }
- else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
- part = rb_str_intern(part);
- mod = rb_const_missing(mod, part);
- continue;
- }
- else {
- rb_mod_const_missing(mod, part);
- }
- }
- if (!rb_is_const_id(id)) {
- name = ID2SYM(id);
- goto wrong_name;
- }
+ VALUE part;
+ long len, beglen;
+
+ while (p < pend && *p != ':') p++;
+
+ if (pbeg == p) goto wrong_name;
+
+ id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
+ beglen = pbeg-path;
+
+ if (p < pend && p[0] == ':') {
+ if (p + 2 >= pend || p[1] != ':') goto wrong_name;
+ p += 2;
+ pbeg = p;
+ }
+
+ if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
+ rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
+ QUOTE(name));
+ }
+
+ if (!id) {
+ part = rb_str_subseq(name, beglen, len);
+ OBJ_FREEZE(part);
+ if (!rb_is_const_name(part)) {
+ name = part;
+ goto wrong_name;
+ }
+ else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
+ part = rb_str_intern(part);
+ mod = rb_const_missing(mod, part);
+ continue;
+ }
+ else {
+ rb_mod_const_missing(mod, part);
+ }
+ }
+ if (!rb_is_const_id(id)) {
+ name = ID2SYM(id);
+ goto wrong_name;
+ }
#if 0
mod = rb_const_get_0(mod, id, beglen > 0 || !RTEST(recur), RTEST(recur), FALSE);
#else
@@ -2607,17 +2487,17 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
recur = (argc == 1) ? Qtrue : argv[1];
if (SYMBOL_P(name)) {
- if (!rb_is_const_sym(name)) goto wrong_name;
- id = rb_check_id(&name);
- if (!id) return Qfalse;
- return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id);
+ if (!rb_is_const_sym(name)) goto wrong_name;
+ id = rb_check_id(&name);
+ if (!id) return Qfalse;
+ return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id);
}
path = StringValuePtr(name);
enc = rb_enc_get(name);
if (!rb_enc_asciicompat(enc)) {
- rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
+ rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
}
pbeg = p = path;
@@ -2628,54 +2508,54 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
}
if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
- mod = rb_cObject;
- p += 2;
- pbeg = p;
+ mod = rb_cObject;
+ p += 2;
+ pbeg = p;
}
while (p < pend) {
- VALUE part;
- long len, beglen;
-
- while (p < pend && *p != ':') p++;
-
- if (pbeg == p) goto wrong_name;
-
- id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
- beglen = pbeg-path;
-
- if (p < pend && p[0] == ':') {
- if (p + 2 >= pend || p[1] != ':') goto wrong_name;
- p += 2;
- pbeg = p;
- }
-
- if (!id) {
- part = rb_str_subseq(name, beglen, len);
- OBJ_FREEZE(part);
- if (!rb_is_const_name(part)) {
- name = part;
- goto wrong_name;
- }
- else {
- return Qfalse;
- }
- }
- if (!rb_is_const_id(id)) {
- name = ID2SYM(id);
- goto wrong_name;
- }
+ VALUE part;
+ long len, beglen;
+
+ while (p < pend && *p != ':') p++;
+
+ if (pbeg == p) goto wrong_name;
+
+ id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
+ beglen = pbeg-path;
+
+ if (p < pend && p[0] == ':') {
+ if (p + 2 >= pend || p[1] != ':') goto wrong_name;
+ p += 2;
+ pbeg = p;
+ }
+
+ if (!id) {
+ part = rb_str_subseq(name, beglen, len);
+ OBJ_FREEZE(part);
+ if (!rb_is_const_name(part)) {
+ name = part;
+ goto wrong_name;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ if (!rb_is_const_id(id)) {
+ name = ID2SYM(id);
+ goto wrong_name;
+ }
#if 0
mod = rb_const_search(mod, id, beglen > 0 || !RTEST(recur), RTEST(recur), FALSE);
- if (mod == Qundef) return Qfalse;
+ if (UNDEF_P(mod)) return Qfalse;
#else
if (!RTEST(recur)) {
- if (!rb_const_defined_at(mod, id))
- return Qfalse;
+ if (!rb_const_defined_at(mod, id))
+ return Qfalse;
if (p == pend) return Qtrue;
- mod = rb_const_get_at(mod, id);
- }
+ mod = rb_const_get_at(mod, id);
+ }
else if (beglen == 0) {
if (!rb_const_defined(mod, id))
return Qfalse;
@@ -2690,10 +2570,10 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
}
#endif
- if (p < pend && !RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
- QUOTE(name));
- }
+ if (p < pend && !RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
+ rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
+ QUOTE(name));
+ }
}
return Qtrue;
@@ -2884,7 +2764,7 @@ rb_obj_ivar_get(VALUE obj, VALUE iv)
ID id = id_for_var(obj, iv, instance);
if (!id) {
- return Qnil;
+ return Qnil;
}
return rb_ivar_get(obj, id);
}
@@ -2913,7 +2793,7 @@ rb_obj_ivar_get(VALUE obj, VALUE iv)
*/
static VALUE
-rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val)
+rb_obj_ivar_set_m(VALUE obj, VALUE iv, VALUE val)
{
ID id = id_for_var(obj, iv, instance);
if (!id) id = rb_intern_str(iv);
@@ -2946,7 +2826,7 @@ rb_obj_ivar_defined(VALUE obj, VALUE iv)
ID id = id_for_var(obj, iv, instance);
if (!id) {
- return Qfalse;
+ return Qfalse;
}
return rb_ivar_defined(obj, id);
}
@@ -2973,8 +2853,8 @@ rb_mod_cvar_get(VALUE obj, VALUE iv)
ID id = id_for_var(obj, iv, class);
if (!id) {
- rb_name_err_raise("uninitialized class variable %1$s in %2$s",
- obj, iv);
+ rb_name_err_raise("uninitialized class variable %1$s in %2$s",
+ obj, iv);
}
return rb_cvar_get(obj, id);
}
@@ -3030,7 +2910,7 @@ rb_mod_cvar_defined(VALUE obj, VALUE iv)
ID id = id_for_var(obj, iv, class);
if (!id) {
- return Qfalse;
+ return Qfalse;
}
return rb_cvar_defined(obj, id);
}
@@ -3070,6 +2950,7 @@ static const struct conv_method_tbl {
M(a),
M(s),
M(i),
+ M(f),
M(r),
#undef M
};
@@ -3081,14 +2962,14 @@ conv_method_index(const char *method)
static const char prefix[] = "to_";
if (strncmp(prefix, method, sizeof(prefix)-1) == 0) {
- const char *const meth = &method[sizeof(prefix)-1];
- int i;
- for (i=0; i < numberof(conv_method_names); i++) {
- if (conv_method_names[i].method[0] == meth[0] &&
- strcmp(conv_method_names[i].method, meth) == 0) {
- return i;
- }
- }
+ const char *const meth = &method[sizeof(prefix)-1];
+ int i;
+ for (i=0; i < numberof(conv_method_names); i++) {
+ if (conv_method_names[i].method[0] == meth[0] &&
+ strcmp(conv_method_names[i].method, meth) == 0) {
+ return i;
+ }
+ }
}
return numberof(conv_method_names);
}
@@ -3097,23 +2978,23 @@ static VALUE
convert_type_with_id(VALUE val, const char *tname, ID method, int raise, int index)
{
VALUE r = rb_check_funcall(val, method, 0, 0);
- if (r == Qundef) {
- if (raise) {
- const char *msg =
- ((index < 0 ? conv_method_index(rb_id2name(method)) : index)
- < IMPLICIT_CONVERSIONS) ?
- "no implicit conversion of" : "can't convert";
- const char *cname = NIL_P(val) ? "nil" :
- val == Qtrue ? "true" :
- val == Qfalse ? "false" :
- NULL;
- if (cname)
- rb_raise(rb_eTypeError, "%s %s into %s", msg, cname, tname);
- rb_raise(rb_eTypeError, "%s %"PRIsVALUE" into %s", msg,
- rb_obj_class(val),
- tname);
- }
- return Qnil;
+ if (UNDEF_P(r)) {
+ if (raise) {
+ const char *msg =
+ ((index < 0 ? conv_method_index(rb_id2name(method)) : index)
+ < IMPLICIT_CONVERSIONS) ?
+ "no implicit conversion of" : "can't convert";
+ const char *cname = NIL_P(val) ? "nil" :
+ val == Qtrue ? "true" :
+ val == Qfalse ? "false" :
+ NULL;
+ if (cname)
+ rb_raise(rb_eTypeError, "%s %s into %s", msg, cname, tname);
+ rb_raise(rb_eTypeError, "%s %"PRIsVALUE" into %s", msg,
+ rb_obj_class(val),
+ tname);
+ }
+ return Qnil;
}
return r;
}
@@ -3123,7 +3004,7 @@ convert_type(VALUE val, const char *tname, const char *method, int raise)
{
int i = conv_method_index(method);
ID m = i < numberof(conv_method_names) ?
- conv_method_names[i].id : rb_intern(method);
+ conv_method_names[i].id : rb_intern(method);
return convert_type_with_id(val, tname, m, raise, i);
}
@@ -3134,23 +3015,10 @@ conversion_mismatch(VALUE val, const char *tname, const char *method, VALUE resu
{
VALUE cname = rb_obj_class(val);
rb_raise(rb_eTypeError,
- "can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")",
- cname, tname, cname, method, rb_obj_class(result));
+ "can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")",
+ cname, tname, cname, method, rb_obj_class(result));
}
-/*!
- * Converts an object into another type.
- * Calls the specified conversion method if necessary.
- *
- * \param[in] val the object to be converted
- * \param[in] type a value of \c ruby_value_type
- * \param[in] tname name of the target type.
- * only used for error messages.
- * \param[in] method name of the method
- * \return an object of the specified type
- * \throw TypeError on failure
- * \sa rb_check_convert_type
- */
VALUE
rb_convert_type(VALUE val, int type, const char *tname, const char *method)
{
@@ -3159,7 +3027,7 @@ rb_convert_type(VALUE val, int type, const char *tname, const char *method)
if (TYPE(val) == type) return val;
v = convert_type(val, tname, method, TRUE);
if (TYPE(v) != type) {
- conversion_mismatch(val, tname, method, v);
+ conversion_mismatch(val, tname, method, v);
}
return v;
}
@@ -3173,25 +3041,11 @@ rb_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
if (TYPE(val) == type) return val;
v = convert_type_with_id(val, tname, method, TRUE, -1);
if (TYPE(v) != type) {
- conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);
+ conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);
}
return v;
}
-/*!
- * Tries to convert an object into another type.
- * Calls the specified conversion method if necessary.
- *
- * \param[in] val the object to be converted
- * \param[in] type a value of \c ruby_value_type
- * \param[in] tname name of the target type.
- * only used for error messages.
- * \param[in] method name of the method
- * \return an object of the specified type, or Qnil if no such conversion method defined.
- * \throw TypeError if the conversion method returns an unexpected type of value.
- * \sa rb_convert_type
- * \sa rb_check_convert_type_with_id
- */
VALUE
rb_check_convert_type(VALUE val, int type, const char *tname, const char *method)
{
@@ -3202,7 +3056,7 @@ rb_check_convert_type(VALUE val, int type, const char *tname, const char *method
v = convert_type(val, tname, method, FALSE);
if (NIL_P(v)) return Qnil;
if (TYPE(v) != type) {
- conversion_mismatch(val, tname, method, v);
+ conversion_mismatch(val, tname, method, v);
}
return v;
}
@@ -3218,7 +3072,7 @@ rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
v = convert_type_with_id(val, tname, method, FALSE, -1);
if (NIL_P(v)) return Qnil;
if (TYPE(v) != type) {
- conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);
+ conversion_mismatch(val, tname, RSTRING_PTR(rb_id2str(method)), v);
}
return v;
}
@@ -3244,16 +3098,6 @@ rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise
#define rb_to_integer(val, method, mid) \
rb_to_integer_with_id_exception(val, method, mid, TRUE)
-/**
- * Tries to convert \a val into \c Integer.
- * It calls the specified conversion method if necessary.
- *
- * \param[in] val a Ruby object
- * \param[in] method a name of a method
- * \return an \c Integer object on success,
- * or \c Qnil if no such conversion method defined.
- * \exception TypeError if the conversion method returns a non-Integer object.
- */
VALUE
rb_check_to_integer(VALUE val, const char *method)
{
@@ -3267,29 +3111,12 @@ rb_check_to_integer(VALUE val, const char *method)
return v;
}
-/**
- * Converts \a val into \c Integer.
- * It calls \a #to_int method if necessary.
- *
- * \param[in] val a Ruby object
- * \return an \c Integer object
- * \exception TypeError on failure
- */
VALUE
rb_to_int(VALUE val)
{
return rb_to_integer(val, "to_int", idTo_int);
}
-/**
- * Tries to convert \a val into Integer.
- * It calls \c #to_int method if necessary.
- *
- * \param[in] val a Ruby object
- * \return an Integer object on success,
- * or \c Qnil if \c #to_int is not defined.
- * \exception TypeError if \c #to_int returns a non-Integer object.
- */
VALUE
rb_check_to_int(VALUE val)
{
@@ -3346,6 +3173,9 @@ rb_convert_to_integer(VALUE val, int base, int raise_exception)
tmp = rb_protect(rb_check_to_int, val, NULL);
if (RB_INTEGER_TYPE_P(tmp)) return tmp;
rb_set_errinfo(Qnil);
+ if (!NIL_P(tmp = rb_check_string_type(val))) {
+ return rb_str_convert_to_inum(tmp, base, TRUE, raise_exception);
+ }
if (!raise_exception) {
VALUE result = rb_protect(rb_check_to_i, val, NULL);
@@ -3356,12 +3186,6 @@ rb_convert_to_integer(VALUE val, int base, int raise_exception)
return rb_to_integer(val, "to_i", idTo_i);
}
-/**
- * Equivalent to \c Kernel\#Integer in Ruby.
- *
- * Converts \a val into \c Integer in a slightly more strict manner
- * than \c #to_i.
- */
VALUE
rb_Integer(VALUE val)
{
@@ -3375,16 +3199,22 @@ rb_check_integer_type(VALUE val)
}
int
-rb_bool_expected(VALUE obj, const char *flagname)
+rb_bool_expected(VALUE obj, const char *flagname, int raise)
{
switch (obj) {
- case Qtrue: case Qfalse:
- break;
- default:
- rb_raise(rb_eArgError, "expected true or false as %s: %+"PRIsVALUE,
- flagname, obj);
+ case Qtrue:
+ return TRUE;
+ case Qfalse:
+ return FALSE;
+ default: {
+ static const char message[] = "expected true or false as %s: %+"PRIsVALUE;
+ if (raise) {
+ rb_raise(rb_eArgError, message, flagname, obj);
+ }
+ rb_warning(message, flagname, obj);
+ return !NIL_P(obj);
+ }
}
- return obj != Qfalse;
}
int
@@ -3393,7 +3223,7 @@ rb_opts_exception_p(VALUE opts, int default_value)
static const ID kwds[1] = {idException};
VALUE exception;
if (rb_get_kwargs(opts, kwds, 0, 1, &exception))
- return rb_bool_expected(exception, "exception");
+ return rb_bool_expected(exception, "exception", TRUE);
return default_value;
}
@@ -3401,35 +3231,89 @@ rb_opts_exception_p(VALUE opts, int default_value)
/*
* call-seq:
- * Integer(arg, base=0, exception: true) -> integer or nil
- *
- * Converts <i>arg</i> to an Integer.
- * Numeric types are converted directly (with floating point numbers
- * being truncated). <i>base</i> (0, or between 2 and 36) is a base for
- * 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 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>.
- *
- * Passing <code>nil</code> raises a TypeError, while passing a String that
- * does not conform with numeric representation raises an ArgumentError.
- * This behavior can be altered by passing <code>exception: false</code>,
- * in this case a not convertible value will return <code>nil</code>.
- *
- * Integer(123.999) #=> 123
- * Integer("0x1a") #=> 26
- * 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"
- *
- * Integer("x", exception: false) #=> nil
+ * Integer(object, base = 0, exception: true) -> integer or nil
+ *
+ * Returns an integer converted from +object+.
+ *
+ * Tries to convert +object+ to an integer
+ * using +to_int+ first and +to_i+ second;
+ * see below for exceptions.
+ *
+ * With a non-zero +base+, +object+ must be a string or convertible
+ * to a string.
+ *
+ * ==== numeric objects
+ *
+ * With integer argument +object+ given, returns +object+:
+ *
+ * Integer(1) # => 1
+ * Integer(-1) # => -1
+ *
+ * With floating-point argument +object+ given,
+ * returns +object+ truncated to an intger:
+ *
+ * Integer(1.9) # => 1 # Rounds toward zero.
+ * Integer(-1.9) # => -1 # Rounds toward zero.
+ *
+ * ==== string objects
+ *
+ * With string argument +object+ and zero +base+ given,
+ * returns +object+ converted to an integer in base 10:
+ *
+ * Integer('100') # => 100
+ * Integer('-100') # => -100
+ *
+ * With +base+ zero, string +object+ may contain leading characters
+ * to specify the actual base (radix indicator):
+ *
+ * Integer('0100') # => 64 # Leading '0' specifies base 8.
+ * Integer('0b100') # => 4 # Leading '0b', specifies base 2.
+ * Integer('0x100') # => 256 # Leading '0x' specifies base 16.
+ *
+ * With a positive +base+ (in range 2..36) given, returns +object+
+ * converted to an integer in the given base:
+ *
+ * Integer('100', 2) # => 4
+ * Integer('100', 8) # => 64
+ * Integer('-100', 16) # => -256
+ *
+ * With a negative +base+ (in range -36..-2) given, returns +object+
+ * converted to an integer in the radix indicator if exists or
+ * +-base+:
+ *
+ * Integer('0x100', -2) # => 256
+ * Integer('100', -2) # => 4
+ * Integer('0b100', -8) # => 4
+ * Integer('100', -8) # => 64
+ * Integer('0o100', -10) # => 64
+ * Integer('100', -10) # => 100
+ *
+ * +base+ -1 is equal the -10 case.
+ *
+ * When converting strings, surrounding whitespace and embedded underscores
+ * are allowed and ignored:
+ *
+ * Integer(' 100 ') # => 100
+ * Integer('-1_0_0', 16) # => -256
+ *
+ * ==== other classes
+ *
+ * Examples with +object+ of various other classes:
+ *
+ * Integer(Rational(9, 10)) # => 0 # Rounds toward zero.
+ * Integer(Complex(2, 0)) # => 2 # Imaginary part must be zero.
+ * Integer(Time.now) # => 1650974042
+ *
+ * ==== keywords
+ *
+ * With optional keyword argument +exception+ given as +true+ (the default):
+ *
+ * - Raises TypeError if +object+ does not respond to +to_int+ or +to_i+.
+ * - Raises TypeError if +object+ is +nil+.
+ * - Raise ArgumentError if +object+ is an invalid string.
+ *
+ * With +exception+ given as +false+, an exception of any kind is suppressed
+ * and +nil+ is returned.
*
*/
@@ -3576,17 +3460,6 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
}
}
-/*!
- * Parses a string representation of a floating point number.
- *
- * \param[in] p a string representation of a floating number
- * \param[in] badcheck raises an exception on parse error if \a badcheck is non-zero.
- * \return the floating point number in the string on success,
- * 0.0 on parse error and \a badcheck is zero.
- * \note it always fails to parse a hexadecimal representation like "0xAB.CDp+1" when
- * \a badcheck is zero, even though it would success if \a badcheck was non-zero.
- * This inconsistency is coming from a historical compatibility reason. [ruby-dev:40822]
- */
double
rb_cstr_to_dbl(const char *p, int badcheck)
{
@@ -3602,43 +3475,33 @@ rb_str_to_dbl_raise(VALUE str, int badcheck, int raise, int *error)
VALUE v = 0;
StringValue(str);
+ rb_must_asciicompat(str);
s = RSTRING_PTR(str);
len = RSTRING_LEN(str);
if (s) {
- if (badcheck && memchr(s, '\0', len)) {
+ if (badcheck && memchr(s, '\0', len)) {
if (raise)
rb_raise(rb_eArgError, "string for Float contains null byte");
else {
if (error) *error = 1;
return 0.0;
}
- }
- if (s[len]) { /* no sentinel somehow */
- char *p = ALLOCV(v, (size_t)len + 1);
- MEMCPY(p, s, char, len);
- p[len] = '\0';
- s = p;
- }
+ }
+ if (s[len]) { /* no sentinel somehow */
+ char *p = ALLOCV(v, (size_t)len + 1);
+ MEMCPY(p, s, char, len);
+ p[len] = '\0';
+ s = p;
+ }
}
ret = rb_cstr_to_dbl_raise(s, badcheck, raise, error);
if (v)
- ALLOCV_END(v);
+ ALLOCV_END(v);
return ret;
}
FUNC_MINIMIZED(double rb_str_to_dbl(VALUE str, int badcheck));
-/*!
- * Parses a string representation of a floating point number.
- *
- * \param[in] str a \c String object representation of a floating number
- * \param[in] badcheck raises an exception on parse error if \a badcheck is non-zero.
- * \return the floating point number in the string on success,
- * 0.0 on parse error and \a badcheck is zero.
- * \note it always fails to parse a hexadecimal representation like "0xAB.CDp+1" when
- * \a badcheck is zero, even though it would success if \a badcheck was non-zero.
- * This inconsistency is coming from a historical compatibility reason. [ruby-dev:40822]
- */
double
rb_str_to_dbl(VALUE str, int badcheck)
{
@@ -3652,7 +3515,7 @@ rb_str_to_dbl(VALUE str, int badcheck)
(FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x))
#define num2dbl_without_to_f(x) \
(FIXNUM_P(x) ? fix2dbl_without_to_f(x) : \
- RB_TYPE_P(x, T_BIGNUM) ? big2dbl_without_to_f(x) : \
+ RB_BIGNUM_TYPE_P(x) ? big2dbl_without_to_f(x) : \
(Check_Type(x, T_FLOAT), RFLOAT_VALUE(x)))
static inline double
rat2dbl_without_to_f(VALUE x)
@@ -3665,11 +3528,11 @@ rat2dbl_without_to_f(VALUE x)
#define special_const_to_float(val, pre, post) \
switch (val) { \
case Qnil: \
- rb_raise_static(rb_eTypeError, pre "nil" post); \
+ rb_raise_static(rb_eTypeError, pre "nil" post); \
case Qtrue: \
- rb_raise_static(rb_eTypeError, pre "true" post); \
+ rb_raise_static(rb_eTypeError, pre "true" post); \
case Qfalse: \
- rb_raise_static(rb_eTypeError, pre "false" post); \
+ rb_raise_static(rb_eTypeError, pre "false" post); \
}
/*! \endcond */
@@ -3690,31 +3553,31 @@ to_float(VALUE *valp, int raise_exception)
{
VALUE val = *valp;
if (SPECIAL_CONST_P(val)) {
- if (FIXNUM_P(val)) {
- *valp = DBL2NUM(fix2dbl_without_to_f(val));
- return T_FLOAT;
- }
- else if (FLONUM_P(val)) {
- return T_FLOAT;
- }
- else if (raise_exception) {
- conversion_to_float(val);
- }
+ if (FIXNUM_P(val)) {
+ *valp = DBL2NUM(fix2dbl_without_to_f(val));
+ return T_FLOAT;
+ }
+ else if (FLONUM_P(val)) {
+ return T_FLOAT;
+ }
+ else if (raise_exception) {
+ conversion_to_float(val);
+ }
}
else {
- int type = BUILTIN_TYPE(val);
- switch (type) {
- case T_FLOAT:
- return T_FLOAT;
- case T_BIGNUM:
- *valp = DBL2NUM(big2dbl_without_to_f(val));
- return T_FLOAT;
- case T_RATIONAL:
- *valp = DBL2NUM(rat2dbl_without_to_f(val));
- return T_FLOAT;
- case T_STRING:
- return T_STRING;
- }
+ int type = BUILTIN_TYPE(val);
+ switch (type) {
+ case T_FLOAT:
+ return T_FLOAT;
+ case T_BIGNUM:
+ *valp = DBL2NUM(big2dbl_without_to_f(val));
+ return T_FLOAT;
+ case T_RATIONAL:
+ *valp = DBL2NUM(rat2dbl_without_to_f(val));
+ return T_FLOAT;
+ case T_STRING:
+ return T_STRING;
+ }
}
return T_NONE;
}
@@ -3730,7 +3593,7 @@ rb_convert_to_float(VALUE val, int raise_exception)
{
switch (to_float(&val, raise_exception)) {
case T_FLOAT:
- return val;
+ return val;
case T_STRING:
if (!raise_exception) {
int e = 0;
@@ -3755,12 +3618,6 @@ rb_convert_to_float(VALUE val, int raise_exception)
FUNC_MINIMIZED(VALUE rb_Float(VALUE val));
-/*!
- * Equivalent to \c Kernel\#Float in Ruby.
- *
- * Converts \a val into \c Float in a slightly more strict manner
- * than \c #to_f.
- */
VALUE
rb_Float(VALUE val)
{
@@ -3768,9 +3625,15 @@ rb_Float(VALUE val)
}
static VALUE
+rb_f_float1(rb_execution_context_t *ec, VALUE obj, VALUE arg)
+{
+ return rb_convert_to_float(arg, TRUE);
+}
+
+static VALUE
rb_f_float(rb_execution_context_t *ec, VALUE obj, VALUE arg, VALUE opts)
{
- int exception = rb_bool_expected(opts, "exception");
+ int exception = rb_bool_expected(opts, "exception", TRUE);
return rb_convert_to_float(arg, exception);
}
@@ -3778,40 +3641,28 @@ static VALUE
numeric_to_float(VALUE val)
{
if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
- rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into Float",
- rb_obj_class(val));
+ rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into Float",
+ rb_obj_class(val));
}
return rb_convert_type_with_id(val, T_FLOAT, "Float", id_to_f);
}
-/*!
- * Converts a \c Numeric object into \c Float.
- * \param[in] val a \c Numeric object
- * \exception TypeError if \a val is not a \c Numeric or other conversion failures.
- */
VALUE
rb_to_float(VALUE val)
{
switch (to_float(&val, TRUE)) {
case T_FLOAT:
- return val;
+ return val;
}
return numeric_to_float(val);
}
-/*!
- * Tries to convert an object into \c Float.
- * It calls \c #to_f if necessary.
- *
- * It returns \c Qnil if the object is not a \c Numeric
- * or \c #to_f is not defined on the object.
- */
VALUE
rb_check_to_float(VALUE val)
{
- if (RB_TYPE_P(val, T_FLOAT)) return val;
+ if (RB_FLOAT_TYPE_P(val)) return val;
if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
- return Qnil;
+ return Qnil;
}
return rb_check_convert_type_with_id(val, T_FLOAT, "Float", id_to_f);
}
@@ -3827,103 +3678,93 @@ double
rb_num_to_dbl(VALUE val)
{
if (SPECIAL_CONST_P(val)) {
- if (FIXNUM_P(val)) {
- if (basic_to_f_p(rb_cInteger))
- return fix2dbl_without_to_f(val);
- }
- else if (FLONUM_P(val)) {
- return rb_float_flonum_value(val);
- }
- else {
- conversion_to_float(val);
- }
+ if (FIXNUM_P(val)) {
+ if (basic_to_f_p(rb_cInteger))
+ return fix2dbl_without_to_f(val);
+ }
+ else if (FLONUM_P(val)) {
+ return rb_float_flonum_value(val);
+ }
+ else {
+ conversion_to_float(val);
+ }
}
else {
- switch (BUILTIN_TYPE(val)) {
- case T_FLOAT:
- return rb_float_noflonum_value(val);
- case T_BIGNUM:
- if (basic_to_f_p(rb_cInteger))
- return big2dbl_without_to_f(val);
- break;
- case T_RATIONAL:
- if (basic_to_f_p(rb_cRational))
- return rat2dbl_without_to_f(val);
- break;
+ switch (BUILTIN_TYPE(val)) {
+ case T_FLOAT:
+ return rb_float_noflonum_value(val);
+ case T_BIGNUM:
+ if (basic_to_f_p(rb_cInteger))
+ return big2dbl_without_to_f(val);
+ break;
+ case T_RATIONAL:
+ if (basic_to_f_p(rb_cRational))
+ return rat2dbl_without_to_f(val);
+ break;
default:
- break;
- }
+ break;
+ }
}
val = numeric_to_float(val);
return RFLOAT_VALUE(val);
}
-/*!
- * Converts a \c Numeric object to \c double.
- * \param[in] val a \c Numeric object
- * \return the converted value
- * \exception TypeError if \a val is not a \c Numeric or
- * it does not support conversion to a floating point number.
- */
double
rb_num2dbl(VALUE val)
{
if (SPECIAL_CONST_P(val)) {
- if (FIXNUM_P(val)) {
- return fix2dbl_without_to_f(val);
- }
- else if (FLONUM_P(val)) {
- return rb_float_flonum_value(val);
- }
- else {
- implicit_conversion_to_float(val);
- }
+ if (FIXNUM_P(val)) {
+ return fix2dbl_without_to_f(val);
+ }
+ else if (FLONUM_P(val)) {
+ return rb_float_flonum_value(val);
+ }
+ else {
+ implicit_conversion_to_float(val);
+ }
}
else {
- switch (BUILTIN_TYPE(val)) {
- case T_FLOAT:
- return rb_float_noflonum_value(val);
- case T_BIGNUM:
- return big2dbl_without_to_f(val);
- case T_RATIONAL:
- return rat2dbl_without_to_f(val);
- case T_STRING:
- rb_raise(rb_eTypeError, "no implicit conversion to float from string");
+ switch (BUILTIN_TYPE(val)) {
+ case T_FLOAT:
+ return rb_float_noflonum_value(val);
+ case T_BIGNUM:
+ return big2dbl_without_to_f(val);
+ case T_RATIONAL:
+ return rat2dbl_without_to_f(val);
+ case T_STRING:
+ rb_raise(rb_eTypeError, "no implicit conversion to float from string");
default:
- break;
- }
+ break;
+ }
}
val = rb_convert_type_with_id(val, T_FLOAT, "Float", id_to_f);
return RFLOAT_VALUE(val);
}
-/*!
- * Equivalent to \c Kernel\#String in Ruby.
- *
- * Converts \a val into \c String by trying \c #to_str at first and
- * then trying \c #to_s.
- */
VALUE
rb_String(VALUE val)
{
VALUE tmp = rb_check_string_type(val);
if (NIL_P(tmp))
- tmp = rb_convert_type_with_id(val, T_STRING, "String", idTo_s);
+ tmp = rb_convert_type_with_id(val, T_STRING, "String", idTo_s);
return tmp;
}
/*
* call-seq:
- * String(arg) -> string
+ * String(object) -> object or new_string
+ *
+ * Returns a string converted from +object+.
*
- * Returns <i>arg</i> as a String.
+ * Tries to convert +object+ to a string
+ * using +to_str+ first and +to_s+ second:
*
- * First tries to call its <code>to_str</code> method, then its <code>to_s</code> method.
+ * String([0, 1, 2]) # => "[0, 1, 2]"
+ * String(0..5) # => "0..5"
+ * String({foo: 0, bar: 1}) # => "{:foo=>0, :bar=>1}"
*
- * String(self) #=> "main"
- * String(self.class) #=> "Object"
- * String(123456) #=> "123456"
+ * Raises +TypeError+ if +object+ cannot be converted to a string.
*/
static VALUE
@@ -3932,41 +3773,38 @@ rb_f_string(VALUE obj, VALUE arg)
return rb_String(arg);
}
-/*!
- * Equivalent to \c Kernel\#Array in Ruby.
- */
VALUE
rb_Array(VALUE val)
{
VALUE tmp = rb_check_array_type(val);
if (NIL_P(tmp)) {
- tmp = rb_check_to_array(val);
- if (NIL_P(tmp)) {
- return rb_ary_new3(1, val);
- }
+ tmp = rb_check_to_array(val);
+ if (NIL_P(tmp)) {
+ return rb_ary_new3(1, val);
+ }
}
return tmp;
}
/*
* call-seq:
- * Array(arg) -> array
+ * Array(object) -> object or new_array
+ *
+ * Returns an array converted from +object+.
*
- * Returns +arg+ as an Array.
+ * Tries to convert +object+ to an array
+ * using +to_ary+ first and +to_a+ second:
*
- * First tries to call <code>to_ary</code> on +arg+, then <code>to_a</code>.
- * If +arg+ does not respond to <code>to_ary</code> or <code>to_a</code>,
- * returns an Array of length 1 containing +arg+.
+ * Array([0, 1, 2]) # => [0, 1, 2]
+ * Array({foo: 0, bar: 1}) # => [[:foo, 0], [:bar, 1]]
+ * Array(0..4) # => [0, 1, 2, 3, 4]
*
- * If <code>to_ary</code> or <code>to_a</code> returns something other than
- * an Array, raises a TypeError.
+ * Returns +object+ in an array, <tt>[object]</tt>,
+ * if +object+ cannot be converted:
+ *
+ * Array(:foo) # => [:foo]
*
- * Array(["a", "b"]) #=> ["a", "b"]
- * Array(1..5) #=> [1, 2, 3, 4, 5]
- * Array(key: :value) #=> [[:key, :value]]
- * Array(nil) #=> []
- * Array(1) #=> [1]
*/
static VALUE
@@ -3986,25 +3824,33 @@ rb_Hash(VALUE val)
if (NIL_P(val)) return rb_hash_new();
tmp = rb_check_hash_type(val);
if (NIL_P(tmp)) {
- if (RB_TYPE_P(val, T_ARRAY) && RARRAY_LEN(val) == 0)
- return rb_hash_new();
- rb_raise(rb_eTypeError, "can't convert %s into Hash", rb_obj_classname(val));
+ if (RB_TYPE_P(val, T_ARRAY) && RARRAY_LEN(val) == 0)
+ return rb_hash_new();
+ rb_raise(rb_eTypeError, "can't convert %s into Hash", rb_obj_classname(val));
}
return tmp;
}
/*
* call-seq:
- * Hash(arg) -> hash
+ * Hash(object) -> object or new_hash
+ *
+ * Returns a hash converted from +object+.
+ *
+ * - If +object+ is:
*
- * Converts <i>arg</i> to a Hash by calling
- * <i>arg</i><code>.to_hash</code>. Returns an empty Hash when
- * <i>arg</i> is <tt>nil</tt> or <tt>[]</tt>.
+ * - A hash, returns +object+.
+ * - An empty array or +nil+, returns an empty hash.
+ *
+ * - Otherwise, if <tt>object.to_hash</tt> returns a hash, returns that hash.
+ * - Otherwise, returns TypeError.
+ *
+ * Examples:
+ *
+ * Hash({foo: 0, bar: 1}) # => {:foo=>0, :bar=>1}
+ * Hash(nil) # => {}
+ * Hash([]) # => {}
*
- * Hash([]) #=> {}
- * Hash(nil) #=> {}
- * Hash(key: :value) #=> {:key => :value}
- * Hash([1, 2, 3]) #=> TypeError
*/
static VALUE
@@ -4026,8 +3872,8 @@ dig_basic_p(VALUE obj, struct dig_method *cache)
{
VALUE klass = RBASIC_CLASS(obj);
if (klass != cache->klass) {
- cache->klass = klass;
- cache->basic = rb_method_basic_definition_p(klass, id_dig);
+ cache->klass = klass;
+ cache->basic = rb_method_basic_definition_p(klass, id_dig);
}
return cache->basic;
}
@@ -4036,8 +3882,8 @@ static void
no_dig_method(int found, VALUE recv, ID mid, int argc, const VALUE *argv, VALUE data)
{
if (!found) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE" does not have #dig method",
- CLASS_OF(data));
+ rb_raise(rb_eTypeError, "%"PRIsVALUE" does not have #dig method",
+ CLASS_OF(data));
}
}
@@ -4048,31 +3894,31 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
struct dig_method hash = {Qnil}, ary = {Qnil}, strt = {Qnil};
for (; argc > 0; ++argv, --argc) {
- if (NIL_P(obj)) return notfound;
- if (!SPECIAL_CONST_P(obj)) {
- switch (BUILTIN_TYPE(obj)) {
- case T_HASH:
- if (dig_basic_p(obj, &hash)) {
- obj = rb_hash_aref(obj, *argv);
- continue;
- }
- break;
- case T_ARRAY:
- if (dig_basic_p(obj, &ary)) {
- obj = rb_ary_at(obj, *argv);
- continue;
- }
- break;
- case T_STRUCT:
- if (dig_basic_p(obj, &strt)) {
- obj = rb_struct_lookup(obj, *argv);
- continue;
- }
- break;
+ if (NIL_P(obj)) return notfound;
+ if (!SPECIAL_CONST_P(obj)) {
+ switch (BUILTIN_TYPE(obj)) {
+ case T_HASH:
+ if (dig_basic_p(obj, &hash)) {
+ obj = rb_hash_aref(obj, *argv);
+ continue;
+ }
+ break;
+ case T_ARRAY:
+ if (dig_basic_p(obj, &ary)) {
+ obj = rb_ary_at(obj, *argv);
+ continue;
+ }
+ break;
+ case T_STRUCT:
+ if (dig_basic_p(obj, &strt)) {
+ obj = rb_struct_lookup(obj, *argv);
+ continue;
+ }
+ break;
default:
break;
- }
- }
+ }
+ }
return rb_check_funcall_with_hook_kw(obj, id_dig, argc, argv,
no_dig_method, obj,
RB_NO_KEYWORDS);
@@ -4082,263 +3928,16 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
/*
* call-seq:
- * format(format_string [, arguments...] ) -> string
- * sprintf(format_string [, arguments...] ) -> string
- *
- * Returns the string resulting from applying <i>format_string</i> to
- * any additional arguments. Within the format string, any characters
- * other than format sequences are copied to the result.
- *
- * The syntax of a format sequence is as follows.
- *
- * %[flags][width][.precision]type
- *
- * A format
- * sequence consists of a percent sign, followed by optional flags,
- * width, and precision indicators, then terminated with a field type
- * character. The field type controls how the corresponding
- * <code>sprintf</code> argument is to be interpreted, while the flags
- * modify that interpretation.
- *
- * The field type characters are:
- *
- * Field | Integer Format
- * ------+--------------------------------------------------------------
- * b | Convert argument as a binary number.
- * | Negative numbers will be displayed as a two's complement
- * | prefixed with `..1'.
- * B | Equivalent to `b', but uses an uppercase 0B for prefix
- * | in the alternative format by #.
- * d | Convert argument as a decimal number.
- * i | Identical to `d'.
- * o | Convert argument as an octal number.
- * | Negative numbers will be displayed as a two's complement
- * | prefixed with `..7'.
- * u | Identical to `d'.
- * x | Convert argument as a hexadecimal number.
- * | Negative numbers will be displayed as a two's complement
- * | prefixed with `..f' (representing an infinite string of
- * | leading 'ff's).
- * X | Equivalent to `x', but uses uppercase letters.
- *
- * Field | Float Format
- * ------+--------------------------------------------------------------
- * e | Convert floating point argument into exponential notation
- * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
- * | The precision specifies the number of digits after the decimal
- * | point (defaulting to six).
- * E | Equivalent to `e', but uses an uppercase E to indicate
- * | the exponent.
- * f | Convert floating point argument as [-]ddd.dddddd,
- * | where the precision specifies the number of digits after
- * | the decimal point.
- * g | Convert a floating point number using exponential form
- * | if the exponent is less than -4 or greater than or
- * | equal to the precision, or in dd.dddd form otherwise.
- * | The precision specifies the number of significant digits.
- * G | Equivalent to `g', but use an uppercase `E' in exponent form.
- * a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
- * | which is consisted from optional sign, "0x", fraction part
- * | as hexadecimal, "p", and exponential part as decimal.
- * A | Equivalent to `a', but use uppercase `X' and `P'.
- *
- * Field | Other Format
- * ------+--------------------------------------------------------------
- * c | Argument is the numeric code for a single character or
- * | a single character string itself.
- * p | The valuing of argument.inspect.
- * s | Argument is a string to be substituted. If the format
- * | sequence contains a precision, at most that many characters
- * | will be copied.
- * % | A percent sign itself will be displayed. No argument taken.
- *
- * The flags modifies the behavior of the formats.
- * The flag characters are:
- *
- * Flag | Applies to | Meaning
- * ---------+---------------+-----------------------------------------
- * space | bBdiouxX | Leave a space at the start of
- * | aAeEfgG | non-negative numbers.
- * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
- * | | a minus sign with absolute value for
- * | | negative values.
- * ---------+---------------+-----------------------------------------
- * (digit)$ | all | Specifies the absolute argument number
- * | | for this field. Absolute and relative
- * | | argument numbers cannot be mixed in a
- * | | sprintf string.
- * ---------+---------------+-----------------------------------------
- * # | bBoxX | Use an alternative format.
- * | aAeEfgG | For the conversions `o', increase the precision
- * | | until the first digit will be `0' if
- * | | it is not formatted as complements.
- * | | For the conversions `x', `X', `b' and `B'
- * | | on non-zero, prefix the result with ``0x'',
- * | | ``0X'', ``0b'' and ``0B'', respectively.
- * | | For `a', `A', `e', `E', `f', `g', and 'G',
- * | | force a decimal point to be added,
- * | | even if no digits follow.
- * | | For `g' and 'G', do not remove trailing zeros.
- * ---------+---------------+-----------------------------------------
- * + | bBdiouxX | Add a leading plus sign to non-negative
- * | aAeEfgG | numbers.
- * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
- * | | a minus sign with absolute value for
- * | | negative values.
- * ---------+---------------+-----------------------------------------
- * - | all | Left-justify the result of this conversion.
- * ---------+---------------+-----------------------------------------
- * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
- * | aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
- * | (numeric fmt) | is used for negative numbers formatted as
- * | | complements.
- * ---------+---------------+-----------------------------------------
- * * | all | Use the next argument as the field width.
- * | | If negative, left-justify the result. If the
- * | | asterisk is followed by a number and a dollar
- * | | sign, use the indicated argument as the width.
- *
- * Examples of flags:
- *
- * # `+' and space flag specifies the sign of non-negative numbers.
- * sprintf("%d", 123) #=> "123"
- * sprintf("%+d", 123) #=> "+123"
- * sprintf("% d", 123) #=> " 123"
- *
- * # `#' flag for `o' increases number of digits to show `0'.
- * # `+' and space flag changes format of negative numbers.
- * sprintf("%o", 123) #=> "173"
- * sprintf("%#o", 123) #=> "0173"
- * sprintf("%+o", -123) #=> "-173"
- * sprintf("%o", -123) #=> "..7605"
- * sprintf("%#o", -123) #=> "..7605"
- *
- * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
- * # `+' and space flag disables complements for negative numbers.
- * sprintf("%x", 123) #=> "7b"
- * sprintf("%#x", 123) #=> "0x7b"
- * sprintf("%+x", -123) #=> "-7b"
- * sprintf("%x", -123) #=> "..f85"
- * sprintf("%#x", -123) #=> "0x..f85"
- * sprintf("%#x", 0) #=> "0"
- *
- * # `#' for `X' uses the prefix `0X'.
- * sprintf("%X", 123) #=> "7B"
- * sprintf("%#X", 123) #=> "0X7B"
- *
- * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
- * # `+' and space flag disables complements for negative numbers.
- * sprintf("%b", 123) #=> "1111011"
- * sprintf("%#b", 123) #=> "0b1111011"
- * sprintf("%+b", -123) #=> "-1111011"
- * sprintf("%b", -123) #=> "..10000101"
- * sprintf("%#b", -123) #=> "0b..10000101"
- * sprintf("%#b", 0) #=> "0"
- *
- * # `#' for `B' uses the prefix `0B'.
- * sprintf("%B", 123) #=> "1111011"
- * sprintf("%#B", 123) #=> "0B1111011"
- *
- * # `#' for `e' forces to show the decimal point.
- * sprintf("%.0e", 1) #=> "1e+00"
- * sprintf("%#.0e", 1) #=> "1.e+00"
- *
- * # `#' for `f' forces to show the decimal point.
- * sprintf("%.0f", 1234) #=> "1234"
- * sprintf("%#.0f", 1234) #=> "1234."
- *
- * # `#' for `g' forces to show the decimal point.
- * # It also disables stripping lowest zeros.
- * sprintf("%g", 123.4) #=> "123.4"
- * sprintf("%#g", 123.4) #=> "123.400"
- * sprintf("%g", 123456) #=> "123456"
- * sprintf("%#g", 123456) #=> "123456."
- *
- * The field width is an optional integer, followed optionally by a
- * period and a precision. The width specifies the minimum number of
- * characters that will be written to the result for this field.
- *
- * Examples of width:
- *
- * # padding is done by spaces, width=20
- * # 0 or radix-1. <------------------>
- * sprintf("%20d", 123) #=> " 123"
- * sprintf("%+20d", 123) #=> " +123"
- * sprintf("%020d", 123) #=> "00000000000000000123"
- * sprintf("%+020d", 123) #=> "+0000000000000000123"
- * sprintf("% 020d", 123) #=> " 0000000000000000123"
- * sprintf("%-20d", 123) #=> "123 "
- * sprintf("%-+20d", 123) #=> "+123 "
- * sprintf("%- 20d", 123) #=> " 123 "
- * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
- *
- * For
- * numeric fields, the precision controls the number of decimal places
- * displayed. For string fields, the precision determines the maximum
- * number of characters to be copied from the string. (Thus, the format
- * sequence <code>%10.10s</code> will always contribute exactly ten
- * characters to the result.)
- *
- * Examples of precisions:
- *
- * # precision for `d', 'o', 'x' and 'b' is
- * # minimum number of digits <------>
- * sprintf("%20.8d", 123) #=> " 00000123"
- * sprintf("%20.8o", 123) #=> " 00000173"
- * sprintf("%20.8x", 123) #=> " 0000007b"
- * sprintf("%20.8b", 123) #=> " 01111011"
- * sprintf("%20.8d", -123) #=> " -00000123"
- * sprintf("%20.8o", -123) #=> " ..777605"
- * sprintf("%20.8x", -123) #=> " ..ffff85"
- * sprintf("%20.8b", -11) #=> " ..110101"
- *
- * # "0x" and "0b" for `#x' and `#b' is not counted for
- * # precision but "0" for `#o' is counted. <------>
- * sprintf("%#20.8d", 123) #=> " 00000123"
- * sprintf("%#20.8o", 123) #=> " 00000173"
- * sprintf("%#20.8x", 123) #=> " 0x0000007b"
- * sprintf("%#20.8b", 123) #=> " 0b01111011"
- * sprintf("%#20.8d", -123) #=> " -00000123"
- * sprintf("%#20.8o", -123) #=> " ..777605"
- * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
- * sprintf("%#20.8b", -11) #=> " 0b..110101"
- *
- * # precision for `e' is number of
- * # digits after the decimal point <------>
- * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
- *
- * # precision for `f' is number of
- * # digits after the decimal point <------>
- * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
- *
- * # precision for `g' is number of
- * # significant digits <------->
- * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
- *
- * # <------->
- * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
- *
- * # precision for `s' is
- * # maximum number of characters <------>
- * sprintf("%20.8s", "string test") #=> " string t"
+ * sprintf(format_string *objects) -> string
*
- * Examples:
+ * Returns the string resulting from formatting +objects+
+ * into +format_string+.
*
- * sprintf("%d %04x", 123, 123) #=> "123 007b"
- * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
- * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
- * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
- * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
- * sprintf("%u", -123) #=> "-123"
+ * For details on +format_string+, see
+ * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
*
- * For more complex formatting, Ruby supports a reference by name.
- * %<name>s style uses format style, but %{name} style doesn't.
+ * Kernel#format is an alias for Kernel#sprintf.
*
- * Examples:
- * sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
- * #=> 1 : 2.000000
- * sprintf("%{foo}f", { :foo => 1 })
- * # => "1f"
*/
static VALUE
@@ -4465,25 +4064,16 @@ f_sprintf(int c, const VALUE *v, VALUE _)
*
* These are the methods defined for \BasicObject:
*
- * - ::new:: Returns a new \BasicObject instance.
- * - {!}[#method-i-21]:: Returns the boolean negation of +self+: +true+ or +false+.
- * - {!=}[#method-i-21-3D]:: Returns whether +self+ and the given object
- * are _not_ equal.
- * - {==}[#method-i-3D-3D]:: Returns whether +self+ and the given object
- * are equivalent.
- * - {__id__}[#method-i-__id__]:: Returns the integer object identifier for +self+.
- * - {__send__}[#method-i-__send__]:: Calls the method identified by the given symbol.
- * - #equal?:: Returns whether +self+ and the given object are the same object.
- * - #instance_eval:: Evaluates the given string or block in the context of +self+.
- * - #instance_exec:: Executes the given block in the context of +self+,
- * passing the given arguments.
- * - #method_missing:: Method called when an undefined method is called on +self+.
- * - #singleton_method_added:: Method called when a singleton method
- * is added to +self+.
- * - #singleton_method_removed:: Method called when a singleton method
- * is added removed from +self+.
- * - #singleton_method_undefined:: Method called when a singleton method
- * is undefined in +self+.
+ * - ::new: Returns a new \BasicObject instance.
+ * - #!: Returns the boolean negation of +self+: +true+ or +false+.
+ * - #!=: Returns whether +self+ and the given object are _not_ equal.
+ * - #==: Returns whether +self+ and the given object are equivalent.
+ * - #__id__: Returns the integer object identifier for +self+.
+ * - #__send__: Calls the method identified by the given symbol.
+ * - #equal?: Returns whether +self+ and the given object are the same object.
+ * - #instance_eval: Evaluates the given string or block in the context of +self+.
+ * - #instance_exec: Executes the given block in the context of +self+,
+ * passing the given arguments.
*
*/
@@ -4509,84 +4099,83 @@ f_sprintf(int c, const VALUE *v, VALUE _)
*
* First, what's elsewhere. \Class \Object:
*
- * - Inherits from {class BasicObject}[BasicObject.html#class-BasicObject-label-What-27s+Here].
- * - Includes {module Kernel}[Kernel.html#module-Kernel-label-What-27s+Here].
+ * - Inherits from {class BasicObject}[rdoc-ref:BasicObject@What-27s+Here].
+ * - Includes {module Kernel}[rdoc-ref:Kernel@What-27s+Here].
*
* Here, class \Object provides methods for:
*
- * - {Querying}[#class-Object-label-Querying]
- * - {Instance Variables}[#class-Object-label-Instance+Variables]
- * - {Other}[#class-Object-label-Other]
+ * - {Querying}[rdoc-ref:Object@Querying]
+ * - {Instance Variables}[rdoc-ref:Object@Instance+Variables]
+ * - {Other}[rdoc-ref:Object@Other]
*
* === Querying
*
- * - {!~}[#method-i-21~]:: Returns +true+ if +self+ does not match the given object,
- * otherwise +false+.
- * - {<=>}[#method-i-3C-3D-3E]:: Returns 0 if +self+ and the given object +object+
- * are the same object, or if
- * <tt>self == object</tt>; otherwise returns +nil+.
- * - #===:: Implements case equality, effectively the same as calling #==.
- * - #eql?:: Implements hash equality, effectively the same as calling #==.
- * - #kind_of? (aliased as #is_a?):: Returns whether given argument is an ancestor
- * of the singleton class of +self+.
- * - #instance_of?:: Returns whether +self+ is an instance of the given class.
- * - #instance_variable_defined?:: Returns whether the given instance variable
- * is defined in +self+.
- * - #method:: Returns the Method object for the given method in +self+.
- * - #methods:: Returns an array of symbol names of public and protected methods
- * in +self+.
- * - #nil?:: Returns +false+. (Only +nil+ responds +true+ to method <tt>nil?</tt>.)
- * - #object_id:: Returns an integer corresponding to +self+ that is unique
- * for the current process
- * - #private_methods:: Returns an array of the symbol names
- * of the private methods in +self+.
- * - #protected_methods:: Returns an array of the symbol names
- * of the protected methods in +self+.
- * - #public_method:: Returns the Method object for the given public method in +self+.
- * - #public_methods:: Returns an array of the symbol names
- * of the public methods in +self+.
- * - #respond_to?:: Returns whether +self+ responds to the given method.
- * - #singleton_class:: Returns the singleton class of +self+.
- * - #singleton_method:: Returns the Method object for the given singleton method
- * in +self+.
- * - #singleton_methods:: Returns an array of the symbol names
- * of the singleton methods in +self+.
- *
- * - #define_singleton_method:: Defines a singleton method in +self+
- * for the given symbol method-name and block or proc.
- * - #extend:: Includes the given modules in the singleton class of +self+.
- * - #public_send:: Calls the given public method in +self+ with the given argument.
- * - #send:: Calls the given method in +self+ with the given argument.
+ * - #!~: Returns +true+ if +self+ does not match the given object,
+ * otherwise +false+.
+ * - #<=>: Returns 0 if +self+ and the given object +object+ are the same
+ * object, or if <tt>self == object</tt>; otherwise returns +nil+.
+ * - #===: Implements case equality, effectively the same as calling #==.
+ * - #eql?: Implements hash equality, effectively the same as calling #==.
+ * - #kind_of? (aliased as #is_a?): Returns whether given argument is an ancestor
+ * of the singleton class of +self+.
+ * - #instance_of?: Returns whether +self+ is an instance of the given class.
+ * - #instance_variable_defined?: Returns whether the given instance variable
+ * is defined in +self+.
+ * - #method: Returns the Method object for the given method in +self+.
+ * - #methods: Returns an array of symbol names of public and protected methods
+ * in +self+.
+ * - #nil?: Returns +false+. (Only +nil+ responds +true+ to method <tt>nil?</tt>.)
+ * - #object_id: Returns an integer corresponding to +self+ that is unique
+ * for the current process
+ * - #private_methods: Returns an array of the symbol names
+ * of the private methods in +self+.
+ * - #protected_methods: Returns an array of the symbol names
+ * of the protected methods in +self+.
+ * - #public_method: Returns the Method object for the given public method in +self+.
+ * - #public_methods: Returns an array of the symbol names
+ * of the public methods in +self+.
+ * - #respond_to?: Returns whether +self+ responds to the given method.
+ * - #singleton_class: Returns the singleton class of +self+.
+ * - #singleton_method: Returns the Method object for the given singleton method
+ * in +self+.
+ * - #singleton_methods: Returns an array of the symbol names
+ * of the singleton methods in +self+.
+ *
+ * - #define_singleton_method: Defines a singleton method in +self+
+ * for the given symbol method-name and block or proc.
+ * - #extend: Includes the given modules in the singleton class of +self+.
+ * - #public_send: Calls the given public method in +self+ with the given argument.
+ * - #send: Calls the given method in +self+ with the given argument.
*
* === Instance Variables
*
- * - #instance_variable_get:: Returns the value of the given instance variable
- * in +self+, or +nil+ if the instance variable is not set.
- * - #instance_variable_set:: Sets the value of the given instance variable in +self+
- * to the given object.
- * - #instance_variables:: Returns an array of the symbol names
- * of the instance variables in +self+.
- * - #remove_instance_variable:: Removes the named instance variable from +self+.
+ * - #instance_variable_get: Returns the value of the given instance variable
+ * in +self+, or +nil+ if the instance variable is not set.
+ * - #instance_variable_set: Sets the value of the given instance variable in +self+
+ * to the given object.
+ * - #instance_variables: Returns an array of the symbol names
+ * of the instance variables in +self+.
+ * - #remove_instance_variable: Removes the named instance variable from +self+.
*
* === Other
*
- * - #clone:: Returns a shallow copy of +self+, including singleton class
- * and frozen state.
- * - #define_singleton_method:: Defines a singleton method in +self+
- * for the given symbol method-name and block or proc.
- * - #display:: Prints +self+ to the given \IO stream or <tt>$stdout</tt>.
- * - #dup:: Returns a shallow unfrozen copy of +self+.
- * - #enum_for (aliased as #to_enum):: Returns an Enumerator for +self+
- * using the using the given method,
- * arguments, and block.
- * - #extend:: Includes the given modules in the singleton class of +self+.
- * - #freeze:: Prevents further modifications to +self+.
- * - #hash:: Returns the integer hash value for +self+.
- * - #inspect:: Returns a human-readable string representation of +self+.
- * - #itself:: Returns +self+.
- * - #public_send:: Calls the given public method in +self+ with the given argument.
- * - #send:: Calls the given method in +self+ with the given argument.
- * - #to_s:: Returns a string representation of +self+.
+ * - #clone: Returns a shallow copy of +self+, including singleton class
+ * and frozen state.
+ * - #define_singleton_method: Defines a singleton method in +self+
+ * for the given symbol method-name and block or proc.
+ * - #display: Prints +self+ to the given \IO stream or <tt>$stdout</tt>.
+ * - #dup: Returns a shallow unfrozen copy of +self+.
+ * - #enum_for (aliased as #to_enum): Returns an Enumerator for +self+
+ * using the using the given method, arguments, and block.
+ * - #extend: Includes the given modules in the singleton class of +self+.
+ * - #freeze: Prevents further modifications to +self+.
+ * - #hash: Returns the integer hash value for +self+.
+ * - #inspect: Returns a human-readable string representation of +self+.
+ * - #itself: Returns +self+.
+ * - #method_missing: Method called when an undefined method is called on +self+.
+ * - #public_send: Calls the given public method in +self+ with the given argument.
+ * - #send: Calls the given method in +self+ with the given argument.
+ * - #to_s: Returns a string representation of +self+.
*
*/
@@ -4622,6 +4211,7 @@ InitVM_Object(void)
rb_cObject = rb_define_class("Object", rb_cBasicObject);
rb_cModule = rb_define_class("Module", rb_cObject);
rb_cClass = rb_define_class("Class", rb_cModule);
+ rb_cRefinement = rb_define_class("Refinement", rb_cModule);
#endif
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_initialize, 0);
@@ -4650,134 +4240,131 @@ InitVM_Object(void)
*
* \Module \Kernel provides methods that are useful for:
*
- * - {Converting}[#module-Kernel-label-Converting]
- * - {Querying}[#module-Kernel-label-Querying]
- * - {Exiting}[#module-Kernel-label-Exiting]
- * - {Exceptions}[#module-Kernel-label-Exceptions]
- * - {IO}[#module-Kernel-label-IO]
- * - {Procs}[#module-Kernel-label-Procs]
- * - {Tracing}[#module-Kernel-label-Tracing]
- * - {Subprocesses}[#module-Kernel-label-Subprocesses]
- * - {Loading}[#module-Kernel-label-Loading]
- * - {Yielding}[#module-Kernel-label-Yielding]
- * - {Random Values}[#module-Kernel-label-Random+Values]
- * - {Other}[#module-Kernel-label-Other]
+ * - {Converting}[rdoc-ref:Kernel@Converting]
+ * - {Querying}[rdoc-ref:Kernel@Querying]
+ * - {Exiting}[rdoc-ref:Kernel@Exiting]
+ * - {Exceptions}[rdoc-ref:Kernel@Exceptions]
+ * - {IO}[rdoc-ref:Kernel@IO]
+ * - {Procs}[rdoc-ref:Kernel@Procs]
+ * - {Tracing}[rdoc-ref:Kernel@Tracing]
+ * - {Subprocesses}[rdoc-ref:Kernel@Subprocesses]
+ * - {Loading}[rdoc-ref:Kernel@Loading]
+ * - {Yielding}[rdoc-ref:Kernel@Yielding]
+ * - {Random Values}[rdoc-ref:Kernel@Random+Values]
+ * - {Other}[rdoc-ref:Kernel@Other]
*
* === Converting
*
- * - {#Array}[#method-i-Array]:: Returns an Array based on the given argument.
- * - {#Complex}[#method-i-Complex]:: Returns a Complex based on the given arguments.
- * - {#Float}[#method-i-Float]:: Returns a Float based on the given arguments.
- * - {#Hash}[#method-i-Hash]:: Returns a Hash based on the given argument.
- * - {#Integer}[#method-i-Integer]:: Returns an Integer based on the given arguments.
- * - {#Rational}[#method-i-Rational]:: Returns a Rational
- * based on the given arguments.
- * - {#String}[#method-i-String]:: Returns a String based on the given argument.
+ * - #Array: Returns an Array based on the given argument.
+ * - #Complex: Returns a Complex based on the given arguments.
+ * - #Float: Returns a Float based on the given arguments.
+ * - #Hash: Returns a Hash based on the given argument.
+ * - #Integer: Returns an Integer based on the given arguments.
+ * - #Rational: Returns a Rational based on the given arguments.
+ * - #String: Returns a String based on the given argument.
*
* === Querying
*
- * - {#__callee__}[#method-i-__callee__]:: Returns the called name
- * of the current method as a symbol.
- * - {#__dir__}[#method-i-__dir__]:: Returns the path to the directory
- * from which the current method is called.
- * - {#__method__}[#method-i-__method__]:: Returns the name
- * of the current method as a symbol.
- * - #autoload?:: Returns the file to be loaded when the given module is referenced.
- * - #binding:: Returns a Binding for the context at the point of call.
- * - #block_given?:: Returns +true+ if a block was passed to the calling method.
- * - #caller:: Returns the current execution stack as an array of strings.
- * - #caller_locations:: Returns the current execution stack as an array
- * of Thread::Backtrace::Location objects.
- * - #class:: Returns the class of +self+.
- * - #frozen?:: Returns whether +self+ is frozen.
- * - #global_variables:: Returns an array of global variables as symbols.
- * - #local_variables:: Returns an array of local variables as symbols.
- * - #test:: Performs specified tests on the given single file or pair of files.
+ * - #__callee__: Returns the called name of the current method as a symbol.
+ * - #__dir__: Returns the path to the directory from which the current
+ * method is called.
+ * - #__method__: Returns the name of the current method as a symbol.
+ * - #autoload?: Returns the file to be loaded when the given module is referenced.
+ * - #binding: Returns a Binding for the context at the point of call.
+ * - #block_given?: Returns +true+ if a block was passed to the calling method.
+ * - #caller: Returns the current execution stack as an array of strings.
+ * - #caller_locations: Returns the current execution stack as an array
+ * of Thread::Backtrace::Location objects.
+ * - #class: Returns the class of +self+.
+ * - #frozen?: Returns whether +self+ is frozen.
+ * - #global_variables: Returns an array of global variables as symbols.
+ * - #local_variables: Returns an array of local variables as symbols.
+ * - #test: Performs specified tests on the given single file or pair of files.
*
* === Exiting
*
- * - #abort:: Exits the current process after printing the given arguments.
- * - #at_exit:: Executes the given block when the process exits.
- * - #exit:: Exits the current process after calling any registered
- * +at_exit+ handlers.
- * - #exit!:: Exits the current process without calling any registered
- * +at_exit+ handlers.
+ * - #abort: Exits the current process after printing the given arguments.
+ * - #at_exit: Executes the given block when the process exits.
+ * - #exit: Exits the current process after calling any registered
+ * +at_exit+ handlers.
+ * - #exit!: Exits the current process without calling any registered
+ * +at_exit+ handlers.
*
* === Exceptions
*
- * - #catch:: Executes the given block, possibly catching a thrown object.
- * - #raise (aliased as #fail):: Raises an exception based on the given arguments.
- * - #throw:: Returns from the active catch block waiting for the given tag.
+ * - #catch: Executes the given block, possibly catching a thrown object.
+ * - #raise (aliased as #fail): Raises an exception based on the given arguments.
+ * - #throw: Returns from the active catch block waiting for the given tag.
*
*
* === \IO
*
- * - #gets:: Returns and assigns to <tt>$_</tt> the next line from the current input.
- * - #open:: Creates an IO object connected to the given stream, file, or subprocess.
- * - #p:: Prints the given objects' inspect output to the standard output.
- * - #pp:: Prints the given objects in pretty form.
- * - #print:: Prints the given objects to standard output without a newline.
- * - #printf:: Prints the string resulting from applying the given format string
- * to any additional arguments.
- * - #putc:: Equivalent to <tt.$stdout.putc(object)</tt> for the given object.
- * - #puts:: Equivalent to <tt>$stdout.puts(*objects)</tt> for the given objects.
- * - #readline:: Similar to #gets, but raises an exception at the end of file.
- * - #readlines:: Returns an array of the remaining lines from the current input.
- * - #select:: Same as IO.select.
+ * - ::pp: Prints the given objects in pretty form.
+ * - #gets: Returns and assigns to <tt>$_</tt> the next line from the current input.
+ * - #open: Creates an IO object connected to the given stream, file, or subprocess.
+ * - #p: Prints the given objects' inspect output to the standard output.
+ * - #print: Prints the given objects to standard output without a newline.
+ * - #printf: Prints the string resulting from applying the given format string
+ * to any additional arguments.
+ * - #putc: Equivalent to <tt.$stdout.putc(object)</tt> for the given object.
+ * - #puts: Equivalent to <tt>$stdout.puts(*objects)</tt> for the given objects.
+ * - #readline: Similar to #gets, but raises an exception at the end of file.
+ * - #readlines: Returns an array of the remaining lines from the current input.
+ * - #select: Same as IO.select.
*
* === Procs
*
- * - #lambda:: Returns a lambda proc for the given block.
- * - #proc:: Returns a new Proc; equivalent to Proc.new.
+ * - #lambda: Returns a lambda proc for the given block.
+ * - #proc: Returns a new Proc; equivalent to Proc.new.
*
* === Tracing
*
- * - #set_trace_func:: Sets the given proc as the handler for tracing,
- * or disables tracing if given +nil+.
- * - #trace_var:: Starts tracing assignments to the given global variable.
- * - #untrace_var:: Disables tracing of assignments to the given global variable.
+ * - #set_trace_func: Sets the given proc as the handler for tracing,
+ * or disables tracing if given +nil+.
+ * - #trace_var: Starts tracing assignments to the given global variable.
+ * - #untrace_var: Disables tracing of assignments to the given global variable.
*
* === Subprocesses
*
- * - #`cmd`:: Returns the standard output of running +cmd+ in a subshell.
- * - #exec:: Replaces current process with a new process.
- * - #fork:: Forks the current process into two processes.
- * - #spawn:: Executes the given command and returns its pid without waiting
- * for completion.
- * - #system:: Executes the given command in a subshell.
+ * - {\`command`}[rdoc-ref:Kernel#`]: Returns the standard output of running
+ * +command+ in a subshell.
+ * - #exec: Replaces current process with a new process.
+ * - #fork: Forks the current process into two processes.
+ * - #spawn: Executes the given command and returns its pid without waiting
+ * for completion.
+ * - #system: Executes the given command in a subshell.
*
* === Loading
*
- * - #autoload:: Registers the given file to be loaded when the given constant
- * is first referenced.
- * - #load:: Loads the given Ruby file.
- * - #require:: Loads the given Ruby file unless it has already been loaded.
- * - #require_relative:: Loads the Ruby file path relative to the calling file,
- * unless it has already been loaded.
+ * - #autoload: Registers the given file to be loaded when the given constant
+ * is first referenced.
+ * - #load: Loads the given Ruby file.
+ * - #require: Loads the given Ruby file unless it has already been loaded.
+ * - #require_relative: Loads the Ruby file path relative to the calling file,
+ * unless it has already been loaded.
*
* === Yielding
*
- * - #tap:: Yields +self+ to the given block; returns +self+.
- * - #then (aliased as #yield_self):: Yields +self+ to the block
- * and returns the result of the block.
+ * - #tap: Yields +self+ to the given block; returns +self+.
+ * - #then (aliased as #yield_self): Yields +self+ to the block
+ * and returns the result of the block.
*
* === \Random Values
*
- * - #rand:: Returns a pseudo-random floating point number
- * strictly between 0.0 and 1.0.
- * - #srand:: Seeds the pseudo-random number generator with the given number.
+ * - #rand: Returns a pseudo-random floating point number
+ * strictly between 0.0 and 1.0.
+ * - #srand: Seeds the pseudo-random number generator with the given number.
*
* === Other
*
- * - #eval:: Evaluates the given string as Ruby code.
- * - #loop:: Repeatedly executes the given block.
- * - #sleep:: Suspends the current thread for the given number of seconds.
- * - #sprintf (aliased as #format):: Returns the string resulting from applying
- * the given format string
- * to any additional arguments.
- * - #syscall:: Runs an operating system call.
- * - #trap:: Specifies the handling of system signals.
- * - #warn:: Issue a warning based on the given messages and options.
+ * - #eval: Evaluates the given string as Ruby code.
+ * - #loop: Repeatedly executes the given block.
+ * - #sleep: Suspends the current thread for the given number of seconds.
+ * - #sprintf (aliased as #format): Returns the string resulting from applying
+ * the given format string to any additional arguments.
+ * - #syscall: Runs an operating system call.
+ * - #trap: Specifies the handling of system signals.
+ * - #warn: Issue a warning based on the given messages and options.
*
*/
rb_mKernel = rb_define_module("Kernel");
@@ -4787,12 +4374,12 @@ InitVM_Object(void)
rb_define_private_method(rb_cModule, "extended", rb_obj_mod_extended, 1);
rb_define_private_method(rb_cModule, "prepended", rb_obj_mod_prepended, 1);
rb_define_private_method(rb_cModule, "method_added", rb_obj_mod_method_added, 1);
+ rb_define_private_method(rb_cModule, "const_added", rb_obj_mod_const_added, 1);
rb_define_private_method(rb_cModule, "method_removed", rb_obj_mod_method_removed, 1);
rb_define_private_method(rb_cModule, "method_undefined", rb_obj_mod_method_undefined, 1);
rb_define_method(rb_mKernel, "nil?", rb_false, 0);
rb_define_method(rb_mKernel, "===", 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 */
@@ -4805,12 +4392,6 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "initialize_dup", 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);
- rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
- rb_define_method(rb_mKernel, "untrust", rb_obj_untrust, 0);
- 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, "to_s", rb_any_to_s, 0);
@@ -4822,10 +4403,10 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "public_methods", rb_obj_public_methods, -1); /* in class.c */
rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0); /* in variable.c */
rb_define_method(rb_mKernel, "instance_variable_get", rb_obj_ivar_get, 1);
- rb_define_method(rb_mKernel, "instance_variable_set", rb_obj_ivar_set, 2);
+ rb_define_method(rb_mKernel, "instance_variable_set", rb_obj_ivar_set_m, 2);
rb_define_method(rb_mKernel, "instance_variable_defined?", rb_obj_ivar_defined, 1);
rb_define_method(rb_mKernel, "remove_instance_variable",
- rb_obj_remove_instance_variable, 1); /* in variable.c */
+ rb_obj_remove_instance_variable, 1); /* in variable.c */
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);
@@ -4843,7 +4424,7 @@ InitVM_Object(void)
rb_cNilClass = rb_define_class("NilClass", rb_cObject);
rb_cNilClass_to_s = rb_fstring_enc_lit("", rb_usascii_encoding());
rb_gc_register_mark_object(rb_cNilClass_to_s);
- rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
+ rb_define_method(rb_cNilClass, "to_s", rb_nil_to_s, 0);
rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
rb_define_method(rb_cNilClass, "to_h", nil_to_h, 0);
rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
@@ -4879,15 +4460,18 @@ InitVM_Object(void)
rb_define_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1);
rb_define_alloc_func(rb_cModule, rb_module_s_alloc);
+ rb_undef_method(rb_singleton_class(rb_cModule), "allocate");
rb_define_method(rb_cModule, "initialize", rb_mod_initialize, 0);
rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, -1);
rb_define_method(rb_cModule, "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 */
+ rb_class_public_instance_methods, -1); /* in class.c */
rb_define_method(rb_cModule, "protected_instance_methods",
- rb_class_protected_instance_methods, -1); /* in class.c */
+ rb_class_protected_instance_methods, -1); /* in class.c */
rb_define_method(rb_cModule, "private_instance_methods",
- rb_class_private_instance_methods, -1); /* in class.c */
+ rb_class_private_instance_methods, -1); /* in class.c */
+ rb_define_method(rb_cModule, "undefined_instance_methods",
+ rb_class_undefined_instance_methods, 0); /* in class.c */
rb_define_method(rb_cModule, "constants", rb_mod_constants, -1); /* in variable.c */
rb_define_method(rb_cModule, "const_get", rb_mod_const_get, -1);
@@ -4895,13 +4479,13 @@ InitVM_Object(void)
rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, -1);
rb_define_method(rb_cModule, "const_source_location", rb_mod_const_source_location, -1);
rb_define_private_method(rb_cModule, "remove_const",
- rb_mod_remove_const, 1); /* in variable.c */
+ rb_mod_remove_const, 1); /* in variable.c */
rb_define_method(rb_cModule, "const_missing",
- rb_mod_const_missing, 1); /* in variable.c */
+ rb_mod_const_missing, 1); /* in variable.c */
rb_define_method(rb_cModule, "class_variables",
- rb_mod_class_variables, -1); /* in variable.c */
+ rb_mod_class_variables, -1); /* in variable.c */
rb_define_method(rb_cModule, "remove_class_variable",
- rb_mod_remove_cvar, 1); /* in variable.c */
+ rb_mod_remove_cvar, 1); /* in variable.c */
rb_define_method(rb_cModule, "class_variable_get", rb_mod_cvar_get, 1);
rb_define_method(rb_cModule, "class_variable_set", rb_mod_cvar_set, 2);
rb_define_method(rb_cModule, "class_variable_defined?", rb_mod_cvar_defined, 1);
@@ -4910,10 +4494,13 @@ InitVM_Object(void)
rb_define_method(rb_cModule, "deprecate_constant", rb_mod_deprecate_constant, -1); /* in variable.c */
rb_define_method(rb_cModule, "singleton_class?", rb_mod_singleton_p, 0);
+ rb_define_method(rb_singleton_class(rb_cClass), "allocate", rb_class_alloc_m, 0);
rb_define_method(rb_cClass, "allocate", rb_class_alloc_m, 0);
rb_define_method(rb_cClass, "new", rb_class_new_instance_pass_kw, -1);
rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
+ rb_define_method(rb_cClass, "subclasses", rb_class_subclasses, 0); /* in class.c */
+ rb_define_method(rb_cClass, "attached_object", rb_class_attached_object, 0); /* in class.c */
rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
rb_undef_method(rb_cClass, "extend_object");
rb_undef_method(rb_cClass, "append_features");
@@ -4922,7 +4509,7 @@ InitVM_Object(void)
rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
rb_cTrueClass_to_s = rb_fstring_enc_lit("true", rb_usascii_encoding());
rb_gc_register_mark_object(rb_cTrueClass_to_s);
- rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
+ rb_define_method(rb_cTrueClass, "to_s", rb_true_to_s, 0);
rb_define_alias(rb_cTrueClass, "inspect", "to_s");
rb_define_method(rb_cTrueClass, "&", true_and, 1);
rb_define_method(rb_cTrueClass, "|", true_or, 1);
@@ -4934,7 +4521,7 @@ InitVM_Object(void)
rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
rb_cFalseClass_to_s = rb_fstring_enc_lit("false", rb_usascii_encoding());
rb_gc_register_mark_object(rb_cFalseClass_to_s);
- rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
+ rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, 0);
rb_define_alias(rb_cFalseClass, "inspect", "to_s");
rb_define_method(rb_cFalseClass, "&", false_and, 1);
rb_define_method(rb_cFalseClass, "|", false_or, 1);
diff --git a/pack.c b/pack.c
index 440346576b..3bdae01362 100644
--- a/pack.c
+++ b/pack.c
@@ -21,8 +21,8 @@
#include "internal/bits.h"
#include "internal/string.h"
#include "internal/symbol.h"
-#include "internal/util.h"
#include "internal/variable.h"
+#include "ruby/util.h"
#include "builtin.h"
@@ -135,7 +135,23 @@ str_associate(VALUE str, VALUE add)
static VALUE
str_associated(VALUE str)
{
- return rb_ivar_lookup(str, id_associated, Qfalse);
+ VALUE associates = rb_ivar_lookup(str, id_associated, Qfalse);
+ if (!associates)
+ rb_raise(rb_eArgError, "no associated pointer");
+ return associates;
+}
+
+static VALUE
+associated_pointer(VALUE associates, const char *t)
+{
+ const VALUE *p = RARRAY_CONST_PTR(associates);
+ const VALUE *pend = p + RARRAY_LEN(associates);
+ for (; p < pend; p++) {
+ VALUE tmp = *p;
+ if (RB_TYPE_P(tmp, T_STRING) && RSTRING_PTR(tmp) == t) return tmp;
+ }
+ rb_raise(rb_eArgError, "non associated pointer");
+ UNREACHABLE_RETURN(Qnil);
}
static void
@@ -151,8 +167,8 @@ unknown_directive(const char *mode, char type, VALUE fmt)
snprintf(unknown, sizeof(unknown), "\\x%.2x", type & 0xff);
}
fmt = rb_str_quote_unprintable(fmt);
- rb_warning("unknown %s directive '%s' in '%"PRIsVALUE"'",
- mode, unknown, fmt);
+ rb_warn("unknown %s directive '%s' in '%"PRIsVALUE"'",
+ mode, unknown, fmt);
}
static float
@@ -192,16 +208,18 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
int integer_size, bigendian_p;
StringValue(fmt);
+ rb_must_asciicompat(fmt);
p = RSTRING_PTR(fmt);
pend = p + RSTRING_LEN(fmt);
if (NIL_P(buffer)) {
- res = rb_str_buf_new(0);
+ res = rb_str_buf_new(0);
}
else {
if (!RB_TYPE_P(buffer, T_STRING))
rb_raise(rb_eTypeError, "buffer must be String, not %s", rb_obj_classname(buffer));
- res = buffer;
+ rb_str_modify(buffer);
+ res = buffer;
}
idx = 0;
@@ -212,327 +230,311 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
#define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW)
while (p < pend) {
- int explicit_endian = 0;
- if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
- rb_raise(rb_eRuntimeError, "format string modified");
- }
- type = *p++; /* get data type */
+ int explicit_endian = 0;
+ if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
+ rb_raise(rb_eRuntimeError, "format string modified");
+ }
+ type = *p++; /* get data type */
#ifdef NATINT_PACK
- natint = 0;
+ natint = 0;
#endif
- if (ISSPACE(type)) continue;
- if (type == '#') {
- while ((p < pend) && (*p != '\n')) {
- p++;
- }
- continue;
- }
+ if (ISSPACE(type)) continue;
+ if (type == '#') {
+ while ((p < pend) && (*p != '\n')) {
+ p++;
+ }
+ continue;
+ }
- {
+ {
modifiers:
- switch (*p) {
- case '_':
- case '!':
- if (strchr(natstr, type)) {
+ switch (*p) {
+ case '_':
+ case '!':
+ if (strchr(natstr, type)) {
#ifdef NATINT_PACK
- natint = 1;
+ natint = 1;
#endif
- p++;
- }
- else {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
- }
- goto modifiers;
-
- case '<':
- case '>':
- if (!strchr(endstr, type)) {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
- }
- if (explicit_endian) {
- rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
- }
- explicit_endian = *p++;
- goto modifiers;
- }
- }
-
- if (*p == '*') { /* set data length */
- len = strchr("@Xxu", type) ? 0
+ p++;
+ }
+ else {
+ rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
+ }
+ goto modifiers;
+
+ case '<':
+ case '>':
+ if (!strchr(endstr, type)) {
+ rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
+ }
+ if (explicit_endian) {
+ rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
+ }
+ explicit_endian = *p++;
+ goto modifiers;
+ }
+ }
+
+ if (*p == '*') { /* set data length */
+ len = strchr("@Xxu", type) ? 0
: strchr("PMm", type) ? 1
: RARRAY_LEN(ary) - idx;
- p++;
- }
- else if (ISDIGIT(*p)) {
- errno = 0;
- len = STRTOUL(p, (char**)&p, 10);
- if (errno) {
- rb_raise(rb_eRangeError, "pack length too big");
- }
- }
- else {
- len = 1;
- }
-
- switch (type) {
- case 'U':
- /* if encoding is US-ASCII, upgrade to UTF-8 */
- if (enc_info == 1) enc_info = 2;
- break;
- case 'm': case 'M': case 'u':
- /* keep US-ASCII (do nothing) */
- break;
- default:
- /* fall back to BINARY */
- enc_info = 0;
- break;
- }
- switch (type) {
- case 'A': case 'a': case 'Z':
- case 'B': case 'b':
- case 'H': case 'h':
- from = NEXTFROM;
- if (NIL_P(from)) {
- ptr = "";
- plen = 0;
- }
- else {
- StringValue(from);
- ptr = RSTRING_PTR(from);
- plen = RSTRING_LEN(from);
- }
-
- if (p[-1] == '*')
- len = plen;
-
- switch (type) {
- case 'a': /* arbitrary binary string (null padded) */
- case 'A': /* arbitrary binary string (ASCII space padded) */
- case 'Z': /* null terminated string */
- if (plen >= len) {
- rb_str_buf_cat(res, ptr, len);
- if (p[-1] == '*' && type == 'Z')
- rb_str_buf_cat(res, nul10, 1);
- }
- else {
- rb_str_buf_cat(res, ptr, plen);
- len -= plen;
- while (len >= 10) {
- rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
- len -= 10;
- }
- rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
- }
- break;
+ p++;
+ }
+ else if (ISDIGIT(*p)) {
+ errno = 0;
+ len = STRTOUL(p, (char**)&p, 10);
+ if (errno) {
+ rb_raise(rb_eRangeError, "pack length too big");
+ }
+ }
+ else {
+ len = 1;
+ }
+
+ switch (type) {
+ case 'U':
+ /* if encoding is US-ASCII, upgrade to UTF-8 */
+ if (enc_info == 1) enc_info = 2;
+ break;
+ case 'm': case 'M': case 'u':
+ /* keep US-ASCII (do nothing) */
+ break;
+ default:
+ /* fall back to BINARY */
+ enc_info = 0;
+ break;
+ }
+ switch (type) {
+ case 'A': case 'a': case 'Z':
+ case 'B': case 'b':
+ case 'H': case 'h':
+ from = NEXTFROM;
+ if (NIL_P(from)) {
+ ptr = "";
+ plen = 0;
+ }
+ else {
+ StringValue(from);
+ ptr = RSTRING_PTR(from);
+ plen = RSTRING_LEN(from);
+ }
+
+ if (p[-1] == '*')
+ len = plen;
+
+ switch (type) {
+ case 'a': /* arbitrary binary string (null padded) */
+ case 'A': /* arbitrary binary string (ASCII space padded) */
+ case 'Z': /* null terminated string */
+ if (plen >= len) {
+ rb_str_buf_cat(res, ptr, len);
+ if (p[-1] == '*' && type == 'Z')
+ rb_str_buf_cat(res, nul10, 1);
+ }
+ else {
+ rb_str_buf_cat(res, ptr, plen);
+ len -= plen;
+ while (len >= 10) {
+ rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
+ len -= 10;
+ }
+ rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
+ }
+ break;
#define castchar(from) (char)((from) & 0xff)
- case 'b': /* bit string (ascending) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len - plen + 1)/2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- if (*ptr & 1)
- byte |= 128;
- if (i & 7)
- byte >>= 1;
- else {
- char c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 7) {
- char c;
- byte >>= 7 - (len & 7);
- c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
-
- case 'B': /* bit string (descending) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len - plen + 1)/2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- byte |= *ptr & 1;
- if (i & 7)
- byte <<= 1;
- else {
- char c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 7) {
- char c;
- byte <<= 7 - (len & 7);
- c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
-
- case 'h': /* hex string (low nibble first) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len + 1) / 2 - (plen + 1) / 2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- if (ISALPHA(*ptr))
- byte |= (((*ptr & 15) + 9) & 15) << 4;
- else
- byte |= (*ptr & 15) << 4;
- if (i & 1)
- byte >>= 4;
- else {
- char c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 1) {
- char c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
-
- case 'H': /* hex string (high nibble first) */
- {
- int byte = 0;
- long i, j = 0;
-
- if (len > plen) {
- j = (len + 1) / 2 - (plen + 1) / 2;
- len = plen;
- }
- for (i=0; i++ < len; ptr++) {
- if (ISALPHA(*ptr))
- byte |= ((*ptr & 15) + 9) & 15;
- else
- byte |= *ptr & 15;
- if (i & 1)
- byte <<= 4;
- else {
- char c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- byte = 0;
- }
- }
- if (len & 1) {
- char c = castchar(byte);
- rb_str_buf_cat(res, &c, 1);
- }
- len = j;
- goto grow;
- }
- break;
- }
- break;
-
- case 'c': /* signed char */
- case 'C': /* unsigned char */
+ case 'b': /* bit string (ascending) */
+ {
+ int byte = 0;
+ long i, j = 0;
+
+ if (len > plen) {
+ j = (len - plen + 1)/2;
+ len = plen;
+ }
+ for (i=0; i++ < len; ptr++) {
+ if (*ptr & 1)
+ byte |= 128;
+ if (i & 7)
+ byte >>= 1;
+ else {
+ char c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ byte = 0;
+ }
+ }
+ if (len & 7) {
+ char c;
+ byte >>= 7 - (len & 7);
+ c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ }
+ len = j;
+ goto grow;
+ }
+ break;
+
+ case 'B': /* bit string (descending) */
+ {
+ int byte = 0;
+ long i, j = 0;
+
+ if (len > plen) {
+ j = (len - plen + 1)/2;
+ len = plen;
+ }
+ for (i=0; i++ < len; ptr++) {
+ byte |= *ptr & 1;
+ if (i & 7)
+ byte <<= 1;
+ else {
+ char c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ byte = 0;
+ }
+ }
+ if (len & 7) {
+ char c;
+ byte <<= 7 - (len & 7);
+ c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ }
+ len = j;
+ goto grow;
+ }
+ break;
+
+ case 'h': /* hex string (low nibble first) */
+ {
+ int byte = 0;
+ long i, j = 0;
+
+ if (len > plen) {
+ j = (len + 1) / 2 - (plen + 1) / 2;
+ len = plen;
+ }
+ for (i=0; i++ < len; ptr++) {
+ if (ISALPHA(*ptr))
+ byte |= (((*ptr & 15) + 9) & 15) << 4;
+ else
+ byte |= (*ptr & 15) << 4;
+ if (i & 1)
+ byte >>= 4;
+ else {
+ char c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ byte = 0;
+ }
+ }
+ if (len & 1) {
+ char c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ }
+ len = j;
+ goto grow;
+ }
+ break;
+
+ case 'H': /* hex string (high nibble first) */
+ {
+ int byte = 0;
+ long i, j = 0;
+
+ if (len > plen) {
+ j = (len + 1) / 2 - (plen + 1) / 2;
+ len = plen;
+ }
+ for (i=0; i++ < len; ptr++) {
+ if (ISALPHA(*ptr))
+ byte |= ((*ptr & 15) + 9) & 15;
+ else
+ byte |= *ptr & 15;
+ if (i & 1)
+ byte <<= 4;
+ else {
+ char c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ byte = 0;
+ }
+ }
+ if (len & 1) {
+ char c = castchar(byte);
+ rb_str_buf_cat(res, &c, 1);
+ }
+ len = j;
+ goto grow;
+ }
+ break;
+ }
+ break;
+
+ case 'c': /* signed char */
+ case 'C': /* unsigned char */
integer_size = 1;
bigendian_p = BIGENDIAN_P(); /* not effective */
goto pack_integer;
- case 's': /* s for int16_t, s! for signed short */
+ case 's': /* s for int16_t, s! for signed short */
+ case 'S': /* S for uint16_t, S! for unsigned short */
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
- case 'S': /* S for uint16_t, S! for unsigned short */
- integer_size = NATINT_LEN(short, 2);
- bigendian_p = BIGENDIAN_P();
- goto pack_integer;
-
- case 'i': /* i and i! for signed int */
+ case 'i': /* i and i! for signed int */
+ case 'I': /* I and I! for unsigned int */
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
- case 'I': /* I and I! for unsigned int */
- integer_size = (int)sizeof(int);
- bigendian_p = BIGENDIAN_P();
- goto pack_integer;
-
- case 'l': /* l for int32_t, l! for signed long */
+ case 'l': /* l for int32_t, l! for signed long */
+ case 'L': /* L for uint32_t, L! for unsigned long */
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
- case 'L': /* L for uint32_t, L! for unsigned long */
- integer_size = NATINT_LEN(long, 4);
+ case 'q': /* q for int64_t, q! for signed long long */
+ case 'Q': /* Q for uint64_t, Q! for unsigned long long */
+ integer_size = NATINT_LEN_Q;
bigendian_p = BIGENDIAN_P();
goto pack_integer;
- case 'q': /* q for int64_t, q! for signed long long */
- integer_size = NATINT_LEN_Q;
+ case 'j': /* j for intptr_t */
+ integer_size = sizeof(intptr_t);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
- case 'Q': /* Q for uint64_t, Q! for unsigned long long */
- integer_size = NATINT_LEN_Q;
+ case 'J': /* J for uintptr_t */
+ integer_size = sizeof(uintptr_t);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
- case 'j': /* j for intptr_t */
- integer_size = sizeof(intptr_t);
- bigendian_p = BIGENDIAN_P();
- goto pack_integer;
-
- case 'J': /* J for uintptr_t */
- integer_size = sizeof(uintptr_t);
- bigendian_p = BIGENDIAN_P();
- goto pack_integer;
-
- case 'n': /* 16 bit (2 bytes) integer (network byte-order) */
+ case 'n': /* 16 bit (2 bytes) integer (network byte-order) */
integer_size = 2;
bigendian_p = 1;
goto pack_integer;
- case 'N': /* 32 bit (4 bytes) integer (network byte-order) */
+ case 'N': /* 32 bit (4 bytes) integer (network byte-order) */
integer_size = 4;
bigendian_p = 1;
goto pack_integer;
- case 'v': /* 16 bit (2 bytes) integer (VAX byte-order) */
+ case 'v': /* 16 bit (2 bytes) integer (VAX byte-order) */
integer_size = 2;
bigendian_p = 0;
goto pack_integer;
- case 'V': /* 32 bit (4 bytes) integer (VAX byte-order) */
+ case 'V': /* 32 bit (4 bytes) integer (VAX byte-order) */
integer_size = 4;
bigendian_p = 0;
goto pack_integer;
pack_integer:
- if (explicit_endian) {
- bigendian_p = explicit_endian == '>';
- }
+ if (explicit_endian) {
+ bigendian_p = explicit_endian == '>';
+ }
if (integer_size > MAX_INTEGER_PACK_SIZE)
rb_bug("unexpected intger size for pack: %d", integer_size);
while (len-- > 0) {
@@ -544,192 +546,192 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
(bigendian_p ? INTEGER_PACK_BIG_ENDIAN : INTEGER_PACK_LITTLE_ENDIAN));
rb_str_buf_cat(res, intbuf, integer_size);
}
- break;
+ break;
- case 'f': /* single precision float in native format */
- case 'F': /* ditto */
- while (len-- > 0) {
- float f;
+ case 'f': /* single precision float in native format */
+ case 'F': /* ditto */
+ while (len-- > 0) {
+ float f;
- from = NEXTFROM;
+ from = NEXTFROM;
f = VALUE_to_float(from);
- rb_str_buf_cat(res, (char*)&f, sizeof(float));
- }
- break;
+ rb_str_buf_cat(res, (char*)&f, sizeof(float));
+ }
+ break;
- case 'e': /* single precision float in VAX byte-order */
- while (len-- > 0) {
- FLOAT_CONVWITH(tmp);
+ case 'e': /* single precision float in VAX byte-order */
+ while (len-- > 0) {
+ FLOAT_CONVWITH(tmp);
- from = NEXTFROM;
+ from = NEXTFROM;
tmp.f = VALUE_to_float(from);
- HTOVF(tmp);
- rb_str_buf_cat(res, tmp.buf, sizeof(float));
- }
- break;
-
- case 'E': /* double precision float in VAX byte-order */
- while (len-- > 0) {
- DOUBLE_CONVWITH(tmp);
- from = NEXTFROM;
- tmp.d = RFLOAT_VALUE(rb_to_float(from));
- HTOVD(tmp);
- rb_str_buf_cat(res, tmp.buf, sizeof(double));
- }
- break;
-
- case 'd': /* double precision float in native format */
- case 'D': /* ditto */
- while (len-- > 0) {
- double d;
-
- from = NEXTFROM;
- d = RFLOAT_VALUE(rb_to_float(from));
- rb_str_buf_cat(res, (char*)&d, sizeof(double));
- }
- break;
-
- case 'g': /* single precision float in network byte-order */
- while (len-- > 0) {
- FLOAT_CONVWITH(tmp);
- from = NEXTFROM;
+ HTOVF(tmp);
+ rb_str_buf_cat(res, tmp.buf, sizeof(float));
+ }
+ break;
+
+ case 'E': /* double precision float in VAX byte-order */
+ while (len-- > 0) {
+ DOUBLE_CONVWITH(tmp);
+ from = NEXTFROM;
+ tmp.d = RFLOAT_VALUE(rb_to_float(from));
+ HTOVD(tmp);
+ rb_str_buf_cat(res, tmp.buf, sizeof(double));
+ }
+ break;
+
+ case 'd': /* double precision float in native format */
+ case 'D': /* ditto */
+ while (len-- > 0) {
+ double d;
+
+ from = NEXTFROM;
+ d = RFLOAT_VALUE(rb_to_float(from));
+ rb_str_buf_cat(res, (char*)&d, sizeof(double));
+ }
+ break;
+
+ case 'g': /* single precision float in network byte-order */
+ while (len-- > 0) {
+ FLOAT_CONVWITH(tmp);
+ from = NEXTFROM;
tmp.f = VALUE_to_float(from);
- HTONF(tmp);
- rb_str_buf_cat(res, tmp.buf, sizeof(float));
- }
- break;
-
- case 'G': /* double precision float in network byte-order */
- while (len-- > 0) {
- DOUBLE_CONVWITH(tmp);
-
- from = NEXTFROM;
- tmp.d = RFLOAT_VALUE(rb_to_float(from));
- HTOND(tmp);
- rb_str_buf_cat(res, tmp.buf, sizeof(double));
- }
- break;
-
- case 'x': /* null byte */
- grow:
- while (len >= 10) {
- rb_str_buf_cat(res, nul10, 10);
- len -= 10;
- }
- rb_str_buf_cat(res, nul10, len);
- break;
-
- case 'X': /* back up byte */
- shrink:
- plen = RSTRING_LEN(res);
- if (plen < len)
- rb_raise(rb_eArgError, "X outside of string");
- rb_str_set_len(res, plen - len);
- break;
-
- case '@': /* null fill to absolute position */
- len -= RSTRING_LEN(res);
- if (len > 0) goto grow;
- len = -len;
- if (len > 0) goto shrink;
- break;
-
- case '%':
- rb_raise(rb_eArgError, "%% is not supported");
- break;
-
- case 'U': /* Unicode character */
- while (len-- > 0) {
- SIGNED_VALUE l;
- char buf[8];
- int le;
-
- from = NEXTFROM;
- from = rb_to_int(from);
- l = NUM2LONG(from);
- if (l < 0) {
- rb_raise(rb_eRangeError, "pack(U): value out of range");
- }
- le = rb_uv_to_utf8(buf, l);
- rb_str_buf_cat(res, (char*)buf, le);
- }
- break;
-
- case 'u': /* uuencoded string */
- case 'm': /* base64 encoded string */
- from = NEXTFROM;
- StringValue(from);
- ptr = RSTRING_PTR(from);
- plen = RSTRING_LEN(from);
-
- if (len == 0 && type == 'm') {
- encodes(res, ptr, plen, type, 0);
- ptr += plen;
- break;
- }
- if (len <= 2)
- len = 45;
- else if (len > 63 && type == 'u')
- len = 63;
- else
- len = len / 3 * 3;
- while (plen > 0) {
- long todo;
-
- if (plen > len)
- todo = len;
- else
- todo = plen;
- encodes(res, ptr, todo, type, 1);
- plen -= todo;
- ptr += todo;
- }
- break;
-
- case 'M': /* quoted-printable encoded string */
- from = rb_obj_as_string(NEXTFROM);
- if (len <= 1)
- len = 72;
- qpencode(res, from, len);
- break;
-
- case 'P': /* pointer to packed byte string */
- from = THISFROM;
- if (!NIL_P(from)) {
- StringValue(from);
- if (RSTRING_LEN(from) < len) {
- rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
- RSTRING_LEN(from), len);
- }
- }
- len = 1;
- /* FALL THROUGH */
- case 'p': /* pointer to string */
- while (len-- > 0) {
- char *t;
- from = NEXTFROM;
- if (NIL_P(from)) {
- t = 0;
- }
- else {
- t = StringValuePtr(from);
- }
- if (!associates) {
- associates = rb_ary_new();
- }
- rb_ary_push(associates, from);
- rb_str_buf_cat(res, (char*)&t, sizeof(char*));
- }
- break;
-
- case 'w': /* BER compressed integer */
- while (len-- > 0) {
- VALUE buf = rb_str_new(0, 0);
+ HTONF(tmp);
+ rb_str_buf_cat(res, tmp.buf, sizeof(float));
+ }
+ break;
+
+ case 'G': /* double precision float in network byte-order */
+ while (len-- > 0) {
+ DOUBLE_CONVWITH(tmp);
+
+ from = NEXTFROM;
+ tmp.d = RFLOAT_VALUE(rb_to_float(from));
+ HTOND(tmp);
+ rb_str_buf_cat(res, tmp.buf, sizeof(double));
+ }
+ break;
+
+ case 'x': /* null byte */
+ grow:
+ while (len >= 10) {
+ rb_str_buf_cat(res, nul10, 10);
+ len -= 10;
+ }
+ rb_str_buf_cat(res, nul10, len);
+ break;
+
+ case 'X': /* back up byte */
+ shrink:
+ plen = RSTRING_LEN(res);
+ if (plen < len)
+ rb_raise(rb_eArgError, "X outside of string");
+ rb_str_set_len(res, plen - len);
+ break;
+
+ case '@': /* null fill to absolute position */
+ len -= RSTRING_LEN(res);
+ if (len > 0) goto grow;
+ len = -len;
+ if (len > 0) goto shrink;
+ break;
+
+ case '%':
+ rb_raise(rb_eArgError, "%% is not supported");
+ break;
+
+ case 'U': /* Unicode character */
+ while (len-- > 0) {
+ SIGNED_VALUE l;
+ char buf[8];
+ int le;
+
+ from = NEXTFROM;
+ from = rb_to_int(from);
+ l = NUM2LONG(from);
+ if (l < 0) {
+ rb_raise(rb_eRangeError, "pack(U): value out of range");
+ }
+ le = rb_uv_to_utf8(buf, l);
+ rb_str_buf_cat(res, (char*)buf, le);
+ }
+ break;
+
+ case 'u': /* uuencoded string */
+ case 'm': /* base64 encoded string */
+ from = NEXTFROM;
+ StringValue(from);
+ ptr = RSTRING_PTR(from);
+ plen = RSTRING_LEN(from);
+
+ if (len == 0 && type == 'm') {
+ encodes(res, ptr, plen, type, 0);
+ ptr += plen;
+ break;
+ }
+ if (len <= 2)
+ len = 45;
+ else if (len > 63 && type == 'u')
+ len = 63;
+ else
+ len = len / 3 * 3;
+ while (plen > 0) {
+ long todo;
+
+ if (plen > len)
+ todo = len;
+ else
+ todo = plen;
+ encodes(res, ptr, todo, type, 1);
+ plen -= todo;
+ ptr += todo;
+ }
+ break;
+
+ case 'M': /* quoted-printable encoded string */
+ from = rb_obj_as_string(NEXTFROM);
+ if (len <= 1)
+ len = 72;
+ qpencode(res, from, len);
+ break;
+
+ case 'P': /* pointer to packed byte string */
+ from = THISFROM;
+ if (!NIL_P(from)) {
+ StringValue(from);
+ if (RSTRING_LEN(from) < len) {
+ rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
+ RSTRING_LEN(from), len);
+ }
+ }
+ len = 1;
+ /* FALL THROUGH */
+ case 'p': /* pointer to string */
+ while (len-- > 0) {
+ char *t;
+ from = NEXTFROM;
+ if (NIL_P(from)) {
+ t = 0;
+ }
+ else {
+ t = StringValuePtr(from);
+ }
+ if (!associates) {
+ associates = rb_ary_new();
+ }
+ rb_ary_push(associates, from);
+ rb_str_buf_cat(res, (char*)&t, sizeof(char*));
+ }
+ break;
+
+ case 'w': /* BER compressed integer */
+ while (len-- > 0) {
+ VALUE buf = rb_str_new(0, 0);
size_t numbytes;
int sign;
char *cp;
- from = NEXTFROM;
+ from = NEXTFROM;
from = rb_to_int(from);
numbytes = rb_absint_numwords(from, 7, NULL);
if (numbytes == 0)
@@ -751,29 +753,29 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
}
rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
- }
- break;
+ }
+ break;
- default: {
+ default: {
unknown_directive("pack", type, fmt);
- break;
- }
- }
+ break;
+ }
+ }
}
if (associates) {
- str_associate(res, associates);
+ str_associate(res, associates);
}
switch (enc_info) {
case 1:
- ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
- break;
+ ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
+ break;
case 2:
- rb_enc_set_index(res, rb_utf8_encindex());
- break;
+ rb_enc_set_index(res, rb_utf8_encindex());
+ break;
default:
- /* do nothing, keep ASCII-8BIT */
- break;
+ /* do nothing, keep ASCII-8BIT */
+ break;
}
return res;
}
@@ -794,11 +796,11 @@ encodes(VALUE str, const char *s0, long len, int type, int tail_lf)
const unsigned char *s = (const unsigned char *)s0;
if (type == 'u') {
- buff[i++] = (char)len + ' ';
- padding = '`';
+ buff[i++] = (char)len + ' ';
+ padding = '`';
}
else {
- padding = '=';
+ padding = '=';
}
while (len >= input_unit) {
while (len >= input_unit && buff_size-i >= encoded_unit) {
@@ -816,16 +818,16 @@ encodes(VALUE str, const char *s0, long len, int type, int tail_lf)
}
if (len == 2) {
- buff[i++] = trans[077 & (*s >> 2)];
- buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
- buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
- buff[i++] = padding;
+ buff[i++] = trans[077 & (*s >> 2)];
+ buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
+ buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
+ buff[i++] = padding;
}
else if (len == 1) {
- buff[i++] = trans[077 & (*s >> 2)];
- buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
- buff[i++] = padding;
- buff[i++] = padding;
+ buff[i++] = trans[077 & (*s >> 2)];
+ buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
+ buff[i++] = padding;
+ buff[i++] = padding;
}
if (tail_lf) buff[i++] = '\n';
rb_str_buf_cat(str, buff, i);
@@ -844,46 +846,46 @@ qpencode(VALUE str, VALUE from, long len)
while (s < send) {
if ((*s > 126) ||
- (*s < 32 && *s != '\n' && *s != '\t') ||
- (*s == '=')) {
- buff[i++] = '=';
- buff[i++] = hex_table[*s >> 4];
- buff[i++] = hex_table[*s & 0x0f];
+ (*s < 32 && *s != '\n' && *s != '\t') ||
+ (*s == '=')) {
+ buff[i++] = '=';
+ buff[i++] = hex_table[*s >> 4];
+ buff[i++] = hex_table[*s & 0x0f];
n += 3;
prev = EOF;
}
- else if (*s == '\n') {
+ else if (*s == '\n') {
if (prev == ' ' || prev == '\t') {
- buff[i++] = '=';
- buff[i++] = *s;
+ buff[i++] = '=';
+ buff[i++] = *s;
}
- buff[i++] = *s;
+ buff[i++] = *s;
n = 0;
prev = *s;
}
- else {
- buff[i++] = *s;
+ else {
+ buff[i++] = *s;
n++;
prev = *s;
}
if (n > len) {
- buff[i++] = '=';
- buff[i++] = '\n';
+ buff[i++] = '=';
+ buff[i++] = '\n';
n = 0;
prev = '\n';
}
- if (i > 1024 - 5) {
- rb_str_buf_cat(str, buff, i);
- i = 0;
- }
- s++;
+ if (i > 1024 - 5) {
+ rb_str_buf_cat(str, buff, i);
+ i = 0;
+ }
+ s++;
}
if (n > 0) {
- buff[i++] = '=';
- buff[i++] = '\n';
+ buff[i++] = '=';
+ buff[i++] = '\n';
}
if (i > 0) {
- rb_str_buf_cat(str, buff, i);
+ rb_str_buf_cat(str, buff, i);
}
}
@@ -901,15 +903,15 @@ hex2num(char c)
tmp_len = 0; \
if (len > (long)((send-s)/(sz))) { \
if (!star) { \
- tmp_len = len-(send-s)/(sz); \
+ tmp_len = len-(send-s)/(sz); \
} \
- len = (send-s)/(sz); \
+ len = (send-s)/(sz); \
} \
} while (0)
#define PACK_ITEM_ADJUST() do { \
if (tmp_len > 0 && mode == UNPACK_ARRAY) \
- rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
+ rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
} while (0)
/* Workaround for Oracle Developer Studio (Oracle Solaris Studio)
@@ -922,18 +924,19 @@ hex2num(char c)
# define AVOID_CC_BUG
#endif
-/* unpack mode */
-#define UNPACK_ARRAY 0
-#define UNPACK_BLOCK 1
-#define UNPACK_1 2
+enum unpack_mode {
+ UNPACK_ARRAY,
+ UNPACK_BLOCK,
+ UNPACK_1
+};
static VALUE
-pack_unpack_internal(VALUE str, VALUE fmt, int mode)
+pack_unpack_internal(VALUE str, VALUE fmt, enum unpack_mode mode, long offset)
{
#define hexdigits ruby_hexdigits
char *s, *send;
char *p, *pend;
- VALUE ary;
+ VALUE ary, associates = Qfalse;
char type;
long len;
AVOID_CC_BUG long tmp_len;
@@ -943,316 +946,326 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode)
#endif
int signed_p, integer_size, bigendian_p;
#define UNPACK_PUSH(item) do {\
- VALUE item_val = (item);\
- if ((mode) == UNPACK_BLOCK) {\
- rb_yield(item_val);\
- }\
- else if ((mode) == UNPACK_ARRAY) {\
- rb_ary_push(ary, item_val);\
- }\
- else /* if ((mode) == UNPACK_1) { */ {\
- return item_val; \
- }\
+ VALUE item_val = (item);\
+ if ((mode) == UNPACK_BLOCK) {\
+ rb_yield(item_val);\
+ }\
+ else if ((mode) == UNPACK_ARRAY) {\
+ rb_ary_push(ary, item_val);\
+ }\
+ else /* if ((mode) == UNPACK_1) { */ {\
+ return item_val; \
+ }\
} while (0)
StringValue(str);
StringValue(fmt);
+ rb_must_asciicompat(fmt);
+
+ if (offset < 0) rb_raise(rb_eArgError, "offset can't be negative");
+ len = RSTRING_LEN(str);
+ if (offset > len) rb_raise(rb_eArgError, "offset outside of string");
+
s = RSTRING_PTR(str);
- send = s + RSTRING_LEN(str);
+ send = s + len;
+ s += offset;
+
p = RSTRING_PTR(fmt);
pend = p + RSTRING_LEN(fmt);
+#define UNPACK_FETCH(var, type) (memcpy((var), s, sizeof(type)), s += sizeof(type))
+
ary = mode == UNPACK_ARRAY ? rb_ary_new() : Qnil;
while (p < pend) {
- int explicit_endian = 0;
- type = *p++;
+ int explicit_endian = 0;
+ type = *p++;
#ifdef NATINT_PACK
- natint = 0;
+ natint = 0;
#endif
- if (ISSPACE(type)) continue;
- if (type == '#') {
- while ((p < pend) && (*p != '\n')) {
- p++;
- }
- continue;
- }
+ if (ISSPACE(type)) continue;
+ if (type == '#') {
+ while ((p < pend) && (*p != '\n')) {
+ p++;
+ }
+ continue;
+ }
- star = 0;
- {
+ star = 0;
+ {
modifiers:
- switch (*p) {
- case '_':
- case '!':
+ switch (*p) {
+ case '_':
+ case '!':
- if (strchr(natstr, type)) {
+ if (strchr(natstr, type)) {
#ifdef NATINT_PACK
- natint = 1;
+ natint = 1;
#endif
- p++;
- }
- else {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
- }
- goto modifiers;
-
- case '<':
- case '>':
- if (!strchr(endstr, type)) {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
- }
- if (explicit_endian) {
- rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
- }
- explicit_endian = *p++;
- goto modifiers;
- }
- }
-
- if (p >= pend)
- len = 1;
- else if (*p == '*') {
- star = 1;
- len = send - s;
- p++;
- }
- else if (ISDIGIT(*p)) {
- errno = 0;
- len = STRTOUL(p, (char**)&p, 10);
- if (len < 0 || errno) {
- rb_raise(rb_eRangeError, "pack length too big");
- }
- }
- else {
- len = (type != '@');
- }
-
- switch (type) {
- case '%':
- rb_raise(rb_eArgError, "%% is not supported");
- break;
-
- case 'A':
- if (len > send - s) len = send - s;
- {
- long end = len;
- char *t = s + len - 1;
-
- while (t >= s) {
- if (*t != ' ' && *t != '\0') break;
- t--; len--;
- }
+ p++;
+ }
+ else {
+ rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
+ }
+ goto modifiers;
+
+ case '<':
+ case '>':
+ if (!strchr(endstr, type)) {
+ rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
+ }
+ if (explicit_endian) {
+ rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
+ }
+ explicit_endian = *p++;
+ goto modifiers;
+ }
+ }
+
+ if (p >= pend)
+ len = 1;
+ else if (*p == '*') {
+ star = 1;
+ len = send - s;
+ p++;
+ }
+ else if (ISDIGIT(*p)) {
+ errno = 0;
+ len = STRTOUL(p, (char**)&p, 10);
+ if (len < 0 || errno) {
+ rb_raise(rb_eRangeError, "pack length too big");
+ }
+ }
+ else {
+ len = (type != '@');
+ }
+
+ switch (type) {
+ case '%':
+ rb_raise(rb_eArgError, "%% is not supported");
+ break;
+
+ case 'A':
+ if (len > send - s) len = send - s;
+ {
+ long end = len;
+ char *t = s + len - 1;
+
+ while (t >= s) {
+ if (*t != ' ' && *t != '\0') break;
+ t--; len--;
+ }
UNPACK_PUSH(rb_str_new(s, len));
- s += end;
- }
- break;
+ s += end;
+ }
+ break;
- case 'Z':
- {
- char *t = s;
+ case 'Z':
+ {
+ char *t = s;
- if (len > send-s) len = send-s;
- while (t < s+len && *t) t++;
+ if (len > send-s) len = send-s;
+ while (t < s+len && *t) t++;
UNPACK_PUSH(rb_str_new(s, t-s));
- if (t < send) t++;
- s = star ? t : s+len;
- }
- break;
+ if (t < send) t++;
+ s = star ? t : s+len;
+ }
+ break;
- case 'a':
- if (len > send - s) len = send - s;
+ case 'a':
+ if (len > send - s) len = send - s;
UNPACK_PUSH(rb_str_new(s, len));
- s += len;
- break;
-
- case 'b':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 8)
- len = (send - s) * 8;
- bits = 0;
- bitstr = rb_usascii_str_new(0, len);
- t = RSTRING_PTR(bitstr);
- for (i=0; i<len; i++) {
- if (i & 7) bits >>= 1;
- else bits = (unsigned char)*s++;
- *t++ = (bits & 1) ? '1' : '0';
- }
- UNPACK_PUSH(bitstr);
- }
- break;
-
- case 'B':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 8)
- len = (send - s) * 8;
- bits = 0;
- bitstr = rb_usascii_str_new(0, len);
- t = RSTRING_PTR(bitstr);
- for (i=0; i<len; i++) {
- if (i & 7) bits <<= 1;
- else bits = (unsigned char)*s++;
- *t++ = (bits & 128) ? '1' : '0';
- }
- UNPACK_PUSH(bitstr);
- }
- break;
-
- case 'h':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 2)
- len = (send - s) * 2;
- bits = 0;
- bitstr = rb_usascii_str_new(0, len);
- t = RSTRING_PTR(bitstr);
- for (i=0; i<len; i++) {
- if (i & 1)
- bits >>= 4;
- else
- bits = (unsigned char)*s++;
- *t++ = hexdigits[bits & 15];
- }
- UNPACK_PUSH(bitstr);
- }
- break;
-
- case 'H':
- {
- VALUE bitstr;
- char *t;
- int bits;
- long i;
-
- if (p[-1] == '*' || len > (send - s) * 2)
- len = (send - s) * 2;
- bits = 0;
- bitstr = rb_usascii_str_new(0, len);
- t = RSTRING_PTR(bitstr);
- for (i=0; i<len; i++) {
- if (i & 1)
- bits <<= 4;
- else
- bits = (unsigned char)*s++;
- *t++ = hexdigits[(bits >> 4) & 15];
- }
- UNPACK_PUSH(bitstr);
- }
- break;
-
- case 'c':
- signed_p = 1;
- integer_size = 1;
- bigendian_p = BIGENDIAN_P(); /* not effective */
- goto unpack_integer;
-
- case 'C':
- signed_p = 0;
- integer_size = 1;
- bigendian_p = BIGENDIAN_P(); /* not effective */
- goto unpack_integer;
-
- case 's':
- signed_p = 1;
- integer_size = NATINT_LEN(short, 2);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'S':
- signed_p = 0;
- integer_size = NATINT_LEN(short, 2);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'i':
- signed_p = 1;
- integer_size = (int)sizeof(int);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'I':
- signed_p = 0;
- integer_size = (int)sizeof(int);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'l':
- signed_p = 1;
- integer_size = NATINT_LEN(long, 4);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'L':
- signed_p = 0;
- integer_size = NATINT_LEN(long, 4);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'q':
- signed_p = 1;
- integer_size = NATINT_LEN_Q;
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'Q':
- signed_p = 0;
- integer_size = NATINT_LEN_Q;
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'j':
- signed_p = 1;
- integer_size = sizeof(intptr_t);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'J':
- signed_p = 0;
- integer_size = sizeof(uintptr_t);
- bigendian_p = BIGENDIAN_P();
- goto unpack_integer;
-
- case 'n':
- signed_p = 0;
- integer_size = 2;
- bigendian_p = 1;
- goto unpack_integer;
-
- case 'N':
- signed_p = 0;
- integer_size = 4;
- bigendian_p = 1;
- goto unpack_integer;
-
- case 'v':
- signed_p = 0;
- integer_size = 2;
- bigendian_p = 0;
- goto unpack_integer;
-
- case 'V':
- signed_p = 0;
- integer_size = 4;
- bigendian_p = 0;
- goto unpack_integer;
-
- unpack_integer:
- if (explicit_endian) {
- bigendian_p = explicit_endian == '>';
- }
+ s += len;
+ break;
+
+ case 'b':
+ {
+ VALUE bitstr;
+ char *t;
+ int bits;
+ long i;
+
+ if (p[-1] == '*' || len > (send - s) * 8)
+ len = (send - s) * 8;
+ bits = 0;
+ bitstr = rb_usascii_str_new(0, len);
+ t = RSTRING_PTR(bitstr);
+ for (i=0; i<len; i++) {
+ if (i & 7) bits >>= 1;
+ else bits = (unsigned char)*s++;
+ *t++ = (bits & 1) ? '1' : '0';
+ }
+ UNPACK_PUSH(bitstr);
+ }
+ break;
+
+ case 'B':
+ {
+ VALUE bitstr;
+ char *t;
+ int bits;
+ long i;
+
+ if (p[-1] == '*' || len > (send - s) * 8)
+ len = (send - s) * 8;
+ bits = 0;
+ bitstr = rb_usascii_str_new(0, len);
+ t = RSTRING_PTR(bitstr);
+ for (i=0; i<len; i++) {
+ if (i & 7) bits <<= 1;
+ else bits = (unsigned char)*s++;
+ *t++ = (bits & 128) ? '1' : '0';
+ }
+ UNPACK_PUSH(bitstr);
+ }
+ break;
+
+ case 'h':
+ {
+ VALUE bitstr;
+ char *t;
+ int bits;
+ long i;
+
+ if (p[-1] == '*' || len > (send - s) * 2)
+ len = (send - s) * 2;
+ bits = 0;
+ bitstr = rb_usascii_str_new(0, len);
+ t = RSTRING_PTR(bitstr);
+ for (i=0; i<len; i++) {
+ if (i & 1)
+ bits >>= 4;
+ else
+ bits = (unsigned char)*s++;
+ *t++ = hexdigits[bits & 15];
+ }
+ UNPACK_PUSH(bitstr);
+ }
+ break;
+
+ case 'H':
+ {
+ VALUE bitstr;
+ char *t;
+ int bits;
+ long i;
+
+ if (p[-1] == '*' || len > (send - s) * 2)
+ len = (send - s) * 2;
+ bits = 0;
+ bitstr = rb_usascii_str_new(0, len);
+ t = RSTRING_PTR(bitstr);
+ for (i=0; i<len; i++) {
+ if (i & 1)
+ bits <<= 4;
+ else
+ bits = (unsigned char)*s++;
+ *t++ = hexdigits[(bits >> 4) & 15];
+ }
+ UNPACK_PUSH(bitstr);
+ }
+ break;
+
+ case 'c':
+ signed_p = 1;
+ integer_size = 1;
+ bigendian_p = BIGENDIAN_P(); /* not effective */
+ goto unpack_integer;
+
+ case 'C':
+ signed_p = 0;
+ integer_size = 1;
+ bigendian_p = BIGENDIAN_P(); /* not effective */
+ goto unpack_integer;
+
+ case 's':
+ signed_p = 1;
+ integer_size = NATINT_LEN(short, 2);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'S':
+ signed_p = 0;
+ integer_size = NATINT_LEN(short, 2);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'i':
+ signed_p = 1;
+ integer_size = (int)sizeof(int);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'I':
+ signed_p = 0;
+ integer_size = (int)sizeof(int);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'l':
+ signed_p = 1;
+ integer_size = NATINT_LEN(long, 4);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'L':
+ signed_p = 0;
+ integer_size = NATINT_LEN(long, 4);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'q':
+ signed_p = 1;
+ integer_size = NATINT_LEN_Q;
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'Q':
+ signed_p = 0;
+ integer_size = NATINT_LEN_Q;
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'j':
+ signed_p = 1;
+ integer_size = sizeof(intptr_t);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'J':
+ signed_p = 0;
+ integer_size = sizeof(uintptr_t);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'n':
+ signed_p = 0;
+ integer_size = 2;
+ bigendian_p = 1;
+ goto unpack_integer;
+
+ case 'N':
+ signed_p = 0;
+ integer_size = 4;
+ bigendian_p = 1;
+ goto unpack_integer;
+
+ case 'v':
+ signed_p = 0;
+ integer_size = 2;
+ bigendian_p = 0;
+ goto unpack_integer;
+
+ case 'V':
+ signed_p = 0;
+ integer_size = 4;
+ bigendian_p = 0;
+ goto unpack_integer;
+
+ unpack_integer:
+ if (explicit_endian) {
+ bigendian_p = explicit_endian == '>';
+ }
PACK_LENGTH_ADJUST_SIZE(integer_size);
while (len-- > 0) {
int flags = bigendian_p ? INTEGER_PACK_BIG_ENDIAN : INTEGER_PACK_LITTLE_ENDIAN;
@@ -1266,355 +1279,311 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode)
PACK_ITEM_ADJUST();
break;
- case 'f':
- case 'F':
- PACK_LENGTH_ADJUST_SIZE(sizeof(float));
- while (len-- > 0) {
- float tmp;
- memcpy(&tmp, s, sizeof(float));
- s += sizeof(float);
- UNPACK_PUSH(DBL2NUM((double)tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'e':
- PACK_LENGTH_ADJUST_SIZE(sizeof(float));
- while (len-- > 0) {
- FLOAT_CONVWITH(tmp);
- memcpy(tmp.buf, s, sizeof(float));
- s += sizeof(float);
- VTOHF(tmp);
- UNPACK_PUSH(DBL2NUM(tmp.f));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'E':
- PACK_LENGTH_ADJUST_SIZE(sizeof(double));
- while (len-- > 0) {
- DOUBLE_CONVWITH(tmp);
- memcpy(tmp.buf, s, sizeof(double));
- s += sizeof(double);
- VTOHD(tmp);
- UNPACK_PUSH(DBL2NUM(tmp.d));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'D':
- case 'd':
- PACK_LENGTH_ADJUST_SIZE(sizeof(double));
- while (len-- > 0) {
- double tmp;
- memcpy(&tmp, s, sizeof(double));
- s += sizeof(double);
- UNPACK_PUSH(DBL2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'g':
- PACK_LENGTH_ADJUST_SIZE(sizeof(float));
- while (len-- > 0) {
- FLOAT_CONVWITH(tmp);
- memcpy(tmp.buf, s, sizeof(float));
- s += sizeof(float);
- NTOHF(tmp);
- UNPACK_PUSH(DBL2NUM(tmp.f));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'G':
- PACK_LENGTH_ADJUST_SIZE(sizeof(double));
- while (len-- > 0) {
- DOUBLE_CONVWITH(tmp);
- memcpy(tmp.buf, s, sizeof(double));
- s += sizeof(double);
- NTOHD(tmp);
- UNPACK_PUSH(DBL2NUM(tmp.d));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'U':
- if (len > send - s) len = send - s;
- while (len > 0 && s < send) {
- long alen = send - s;
- unsigned long l;
-
- l = utf8_to_uv(s, &alen);
- s += alen; len--;
- UNPACK_PUSH(ULONG2NUM(l));
- }
- break;
-
- case 'u':
- {
+ case 'f':
+ case 'F':
+ PACK_LENGTH_ADJUST_SIZE(sizeof(float));
+ while (len-- > 0) {
+ float tmp;
+ UNPACK_FETCH(&tmp, float);
+ UNPACK_PUSH(DBL2NUM((double)tmp));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'e':
+ PACK_LENGTH_ADJUST_SIZE(sizeof(float));
+ while (len-- > 0) {
+ FLOAT_CONVWITH(tmp);
+ UNPACK_FETCH(tmp.buf, float);
+ VTOHF(tmp);
+ UNPACK_PUSH(DBL2NUM(tmp.f));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'E':
+ PACK_LENGTH_ADJUST_SIZE(sizeof(double));
+ while (len-- > 0) {
+ DOUBLE_CONVWITH(tmp);
+ UNPACK_FETCH(tmp.buf, double);
+ VTOHD(tmp);
+ UNPACK_PUSH(DBL2NUM(tmp.d));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'D':
+ case 'd':
+ PACK_LENGTH_ADJUST_SIZE(sizeof(double));
+ while (len-- > 0) {
+ double tmp;
+ UNPACK_FETCH(&tmp, double);
+ UNPACK_PUSH(DBL2NUM(tmp));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'g':
+ PACK_LENGTH_ADJUST_SIZE(sizeof(float));
+ while (len-- > 0) {
+ FLOAT_CONVWITH(tmp);
+ UNPACK_FETCH(tmp.buf, float);
+ NTOHF(tmp);
+ UNPACK_PUSH(DBL2NUM(tmp.f));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'G':
+ PACK_LENGTH_ADJUST_SIZE(sizeof(double));
+ while (len-- > 0) {
+ DOUBLE_CONVWITH(tmp);
+ UNPACK_FETCH(tmp.buf, double);
+ NTOHD(tmp);
+ UNPACK_PUSH(DBL2NUM(tmp.d));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'U':
+ if (len > send - s) len = send - s;
+ while (len > 0 && s < send) {
+ long alen = send - s;
+ unsigned long l;
+
+ l = utf8_to_uv(s, &alen);
+ s += alen; len--;
+ UNPACK_PUSH(ULONG2NUM(l));
+ }
+ break;
+
+ case 'u':
+ {
VALUE buf = rb_str_new(0, (send - s)*3/4);
- char *ptr = RSTRING_PTR(buf);
- long total = 0;
-
- while (s < send && (unsigned char)*s > ' ' && (unsigned char)*s < 'a') {
- long a,b,c,d;
- char hunk[3];
-
- len = ((unsigned char)*s++ - ' ') & 077;
-
- total += len;
- if (total > RSTRING_LEN(buf)) {
- len -= total - RSTRING_LEN(buf);
- total = RSTRING_LEN(buf);
- }
-
- while (len > 0) {
- long mlen = len > 3 ? 3 : len;
-
- if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
- a = ((unsigned char)*s++ - ' ') & 077;
- else
- a = 0;
- if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
- b = ((unsigned char)*s++ - ' ') & 077;
- else
- b = 0;
- if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
- c = ((unsigned char)*s++ - ' ') & 077;
- else
- c = 0;
- if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
- d = ((unsigned char)*s++ - ' ') & 077;
- else
- d = 0;
- hunk[0] = (char)(a << 2 | b >> 4);
- hunk[1] = (char)(b << 4 | c >> 2);
- hunk[2] = (char)(c << 6 | d);
- memcpy(ptr, hunk, mlen);
- ptr += mlen;
- len -= mlen;
- }
- if (s < send && (unsigned char)*s != '\r' && *s != '\n')
- s++; /* possible checksum byte */
- if (s < send && *s == '\r') s++;
- if (s < send && *s == '\n') s++;
- }
-
- rb_str_set_len(buf, total);
- UNPACK_PUSH(buf);
- }
- break;
-
- case 'm':
- {
+ char *ptr = RSTRING_PTR(buf);
+ long total = 0;
+
+ while (s < send && (unsigned char)*s > ' ' && (unsigned char)*s < 'a') {
+ long a,b,c,d;
+ char hunk[3];
+
+ len = ((unsigned char)*s++ - ' ') & 077;
+
+ total += len;
+ if (total > RSTRING_LEN(buf)) {
+ len -= total - RSTRING_LEN(buf);
+ total = RSTRING_LEN(buf);
+ }
+
+ while (len > 0) {
+ long mlen = len > 3 ? 3 : len;
+
+ if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
+ a = ((unsigned char)*s++ - ' ') & 077;
+ else
+ a = 0;
+ if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
+ b = ((unsigned char)*s++ - ' ') & 077;
+ else
+ b = 0;
+ if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
+ c = ((unsigned char)*s++ - ' ') & 077;
+ else
+ c = 0;
+ if (s < send && (unsigned char)*s >= ' ' && (unsigned char)*s < 'a')
+ d = ((unsigned char)*s++ - ' ') & 077;
+ else
+ d = 0;
+ hunk[0] = (char)(a << 2 | b >> 4);
+ hunk[1] = (char)(b << 4 | c >> 2);
+ hunk[2] = (char)(c << 6 | d);
+ memcpy(ptr, hunk, mlen);
+ ptr += mlen;
+ len -= mlen;
+ }
+ if (s < send && (unsigned char)*s != '\r' && *s != '\n')
+ s++; /* possible checksum byte */
+ if (s < send && *s == '\r') s++;
+ if (s < send && *s == '\n') s++;
+ }
+
+ rb_str_set_len(buf, total);
+ UNPACK_PUSH(buf);
+ }
+ break;
+
+ case 'm':
+ {
VALUE buf = rb_str_new(0, (send - s + 3)*3/4); /* +3 is for skipping paddings */
- char *ptr = RSTRING_PTR(buf);
- int a = -1,b = -1,c = 0,d = 0;
- static signed char b64_xtable[256];
-
- if (b64_xtable['/'] <= 0) {
- int i;
-
- for (i = 0; i < 256; i++) {
- b64_xtable[i] = -1;
- }
- for (i = 0; i < 64; i++) {
- b64_xtable[(unsigned char)b64_table[i]] = (char)i;
- }
- }
- if (len == 0) {
- while (s < send) {
- a = b = c = d = -1;
- a = b64_xtable[(unsigned char)*s++];
- if (s >= send || a == -1) rb_raise(rb_eArgError, "invalid base64");
- b = b64_xtable[(unsigned char)*s++];
- if (s >= send || b == -1) rb_raise(rb_eArgError, "invalid base64");
- if (*s == '=') {
- if (s + 2 == send && *(s + 1) == '=') break;
- rb_raise(rb_eArgError, "invalid base64");
- }
- c = b64_xtable[(unsigned char)*s++];
- if (s >= send || c == -1) rb_raise(rb_eArgError, "invalid base64");
- if (s + 1 == send && *s == '=') break;
- d = b64_xtable[(unsigned char)*s++];
- if (d == -1) rb_raise(rb_eArgError, "invalid base64");
- *ptr++ = castchar(a << 2 | b >> 4);
- *ptr++ = castchar(b << 4 | c >> 2);
- *ptr++ = castchar(c << 6 | d);
- }
- if (c == -1) {
- *ptr++ = castchar(a << 2 | b >> 4);
- if (b & 0xf) rb_raise(rb_eArgError, "invalid base64");
- }
- else if (d == -1) {
- *ptr++ = castchar(a << 2 | b >> 4);
- *ptr++ = castchar(b << 4 | c >> 2);
- if (c & 0x3) rb_raise(rb_eArgError, "invalid base64");
- }
- }
- else {
- while (s < send) {
- a = b = c = d = -1;
- while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
- if (s >= send) break;
- s++;
- while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
- if (s >= send) break;
- s++;
- while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
- if (*s == '=' || s >= send) break;
- s++;
- while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
- if (*s == '=' || s >= send) break;
- s++;
- *ptr++ = castchar(a << 2 | b >> 4);
- *ptr++ = castchar(b << 4 | c >> 2);
- *ptr++ = castchar(c << 6 | d);
- a = -1;
- }
- if (a != -1 && b != -1) {
- if (c == -1)
- *ptr++ = castchar(a << 2 | b >> 4);
- else {
- *ptr++ = castchar(a << 2 | b >> 4);
- *ptr++ = castchar(b << 4 | c >> 2);
- }
- }
- }
- rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
- UNPACK_PUSH(buf);
- }
- break;
-
- case 'M':
- {
+ char *ptr = RSTRING_PTR(buf);
+ int a = -1,b = -1,c = 0,d = 0;
+ static signed char b64_xtable[256];
+
+ if (b64_xtable['/'] <= 0) {
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ b64_xtable[i] = -1;
+ }
+ for (i = 0; i < 64; i++) {
+ b64_xtable[(unsigned char)b64_table[i]] = (char)i;
+ }
+ }
+ if (len == 0) {
+ while (s < send) {
+ a = b = c = d = -1;
+ a = b64_xtable[(unsigned char)*s++];
+ if (s >= send || a == -1) rb_raise(rb_eArgError, "invalid base64");
+ b = b64_xtable[(unsigned char)*s++];
+ if (s >= send || b == -1) rb_raise(rb_eArgError, "invalid base64");
+ if (*s == '=') {
+ if (s + 2 == send && *(s + 1) == '=') break;
+ rb_raise(rb_eArgError, "invalid base64");
+ }
+ c = b64_xtable[(unsigned char)*s++];
+ if (s >= send || c == -1) rb_raise(rb_eArgError, "invalid base64");
+ if (s + 1 == send && *s == '=') break;
+ d = b64_xtable[(unsigned char)*s++];
+ if (d == -1) rb_raise(rb_eArgError, "invalid base64");
+ *ptr++ = castchar(a << 2 | b >> 4);
+ *ptr++ = castchar(b << 4 | c >> 2);
+ *ptr++ = castchar(c << 6 | d);
+ }
+ if (c == -1) {
+ *ptr++ = castchar(a << 2 | b >> 4);
+ if (b & 0xf) rb_raise(rb_eArgError, "invalid base64");
+ }
+ else if (d == -1) {
+ *ptr++ = castchar(a << 2 | b >> 4);
+ *ptr++ = castchar(b << 4 | c >> 2);
+ if (c & 0x3) rb_raise(rb_eArgError, "invalid base64");
+ }
+ }
+ else {
+ while (s < send) {
+ a = b = c = d = -1;
+ while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
+ if (s >= send) break;
+ s++;
+ while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
+ if (s >= send) break;
+ s++;
+ while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
+ if (*s == '=' || s >= send) break;
+ s++;
+ while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
+ if (*s == '=' || s >= send) break;
+ s++;
+ *ptr++ = castchar(a << 2 | b >> 4);
+ *ptr++ = castchar(b << 4 | c >> 2);
+ *ptr++ = castchar(c << 6 | d);
+ a = -1;
+ }
+ if (a != -1 && b != -1) {
+ if (c == -1)
+ *ptr++ = castchar(a << 2 | b >> 4);
+ else {
+ *ptr++ = castchar(a << 2 | b >> 4);
+ *ptr++ = castchar(b << 4 | c >> 2);
+ }
+ }
+ }
+ rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
+ UNPACK_PUSH(buf);
+ }
+ break;
+
+ case 'M':
+ {
VALUE buf = rb_str_new(0, send - s);
- char *ptr = RSTRING_PTR(buf), *ss = s;
- int csum = 0;
- int c1, c2;
-
- while (s < send) {
- if (*s == '=') {
- if (++s == send) break;
- if (s+1 < send && *s == '\r' && *(s+1) == '\n')
- s++;
- if (*s != '\n') {
- if ((c1 = hex2num(*s)) == -1) break;
- if (++s == send) break;
- if ((c2 = hex2num(*s)) == -1) break;
- csum |= *ptr++ = castchar(c1 << 4 | c2);
- }
- }
- else {
- csum |= *ptr++ = *s;
- }
- s++;
- ss = s;
- }
- rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
- rb_str_buf_cat(buf, ss, send-ss);
- csum = ISASCII(csum) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
- ENCODING_CODERANGE_SET(buf, rb_ascii8bit_encindex(), csum);
- UNPACK_PUSH(buf);
- }
- break;
-
- case '@':
- if (len > RSTRING_LEN(str))
- rb_raise(rb_eArgError, "@ outside of string");
- s = RSTRING_PTR(str) + len;
- break;
-
- case 'X':
- if (len > s - RSTRING_PTR(str))
- rb_raise(rb_eArgError, "X outside of string");
- s -= len;
- break;
-
- case 'x':
- if (len > send - s)
- rb_raise(rb_eArgError, "x outside of string");
- s += len;
- break;
-
- case 'P':
- if (sizeof(char *) <= (size_t)(send - s)) {
- VALUE tmp = Qnil;
- char *t;
-
- memcpy(&t, s, sizeof(char *));
- s += sizeof(char *);
-
- if (t) {
- VALUE a;
- const VALUE *p, *pend;
-
- if (!(a = str_associated(str))) {
- rb_raise(rb_eArgError, "no associated pointer");
- }
- p = RARRAY_CONST_PTR(a);
- pend = p + RARRAY_LEN(a);
- while (p < pend) {
- if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) {
- if (len < RSTRING_LEN(*p)) {
- tmp = rb_str_new(t, len);
- str_associate(tmp, a);
- }
- else {
- tmp = *p;
- }
- break;
- }
- p++;
- }
- if (p == pend) {
- rb_raise(rb_eArgError, "non associated pointer");
- }
- }
- UNPACK_PUSH(tmp);
- }
- break;
-
- case 'p':
- if (len > (long)((send - s) / sizeof(char *)))
- len = (send - s) / sizeof(char *);
- while (len-- > 0) {
- if ((size_t)(send - s) < sizeof(char *))
- break;
- else {
- VALUE tmp = Qnil;
- char *t;
-
- memcpy(&t, s, sizeof(char *));
- s += sizeof(char *);
-
- if (t) {
- VALUE a;
- const VALUE *p, *pend;
-
- if (!(a = str_associated(str))) {
- rb_raise(rb_eArgError, "no associated pointer");
- }
- p = RARRAY_CONST_PTR(a);
- pend = p + RARRAY_LEN(a);
- while (p < pend) {
- if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) {
- tmp = *p;
- break;
- }
- p++;
- }
- if (p == pend) {
- rb_raise(rb_eArgError, "non associated pointer");
- }
- }
- UNPACK_PUSH(tmp);
- }
- }
- break;
-
- case 'w':
- {
+ char *ptr = RSTRING_PTR(buf), *ss = s;
+ int csum = 0;
+ int c1, c2;
+
+ while (s < send) {
+ if (*s == '=') {
+ if (++s == send) break;
+ if (s+1 < send && *s == '\r' && *(s+1) == '\n')
+ s++;
+ if (*s != '\n') {
+ if ((c1 = hex2num(*s)) == -1) break;
+ if (++s == send) break;
+ if ((c2 = hex2num(*s)) == -1) break;
+ csum |= *ptr++ = castchar(c1 << 4 | c2);
+ }
+ }
+ else {
+ csum |= *ptr++ = *s;
+ }
+ s++;
+ ss = s;
+ }
+ rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
+ rb_str_buf_cat(buf, ss, send-ss);
+ csum = ISASCII(csum) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
+ ENCODING_CODERANGE_SET(buf, rb_ascii8bit_encindex(), csum);
+ UNPACK_PUSH(buf);
+ }
+ break;
+
+ case '@':
+ if (len > RSTRING_LEN(str))
+ rb_raise(rb_eArgError, "@ outside of string");
+ s = RSTRING_PTR(str) + len;
+ break;
+
+ case 'X':
+ if (len > s - RSTRING_PTR(str))
+ rb_raise(rb_eArgError, "X outside of string");
+ s -= len;
+ break;
+
+ case 'x':
+ if (len > send - s)
+ rb_raise(rb_eArgError, "x outside of string");
+ s += len;
+ break;
+
+ case 'P':
+ if (sizeof(char *) <= (size_t)(send - s)) {
+ VALUE tmp = Qnil;
+ char *t;
+
+ UNPACK_FETCH(&t, char *);
+ if (t) {
+ if (!associates) associates = str_associated(str);
+ tmp = associated_pointer(associates, t);
+ if (len < RSTRING_LEN(tmp)) {
+ tmp = rb_str_new(t, len);
+ str_associate(tmp, associates);
+ }
+ }
+ UNPACK_PUSH(tmp);
+ }
+ break;
+
+ case 'p':
+ if (len > (long)((send - s) / sizeof(char *)))
+ len = (send - s) / sizeof(char *);
+ while (len-- > 0) {
+ if ((size_t)(send - s) < sizeof(char *))
+ break;
+ else {
+ VALUE tmp = Qnil;
+ char *t;
+
+ UNPACK_FETCH(&t, char *);
+ if (t) {
+ if (!associates) associates = str_associated(str);
+ tmp = associated_pointer(associates, t);
+ }
+ UNPACK_PUSH(tmp);
+ }
+ }
+ break;
+
+ case 'w':
+ {
char *s0 = s;
while (len > 0 && s < send) {
if (*s & 0x80) {
@@ -1627,72 +1596,72 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode)
s0 = s;
}
}
- }
- break;
+ }
+ break;
- default:
+ default:
unknown_directive("unpack", type, fmt);
- break;
- }
+ break;
+ }
}
return ary;
}
static VALUE
-pack_unpack(rb_execution_context_t *ec, VALUE str, VALUE fmt)
+pack_unpack(rb_execution_context_t *ec, VALUE str, VALUE fmt, VALUE offset)
{
- int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY;
- return pack_unpack_internal(str, fmt, mode);
+ enum unpack_mode mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY;
+ return pack_unpack_internal(str, fmt, mode, RB_NUM2LONG(offset));
}
static VALUE
-pack_unpack1(rb_execution_context_t *ec, VALUE str, VALUE fmt)
+pack_unpack1(rb_execution_context_t *ec, VALUE str, VALUE fmt, VALUE offset)
{
- return pack_unpack_internal(str, fmt, UNPACK_1);
+ return pack_unpack_internal(str, fmt, UNPACK_1, RB_NUM2LONG(offset));
}
int
rb_uv_to_utf8(char buf[6], unsigned long uv)
{
if (uv <= 0x7f) {
- buf[0] = (char)uv;
- return 1;
+ buf[0] = (char)uv;
+ return 1;
}
if (uv <= 0x7ff) {
- buf[0] = castchar(((uv>>6)&0xff)|0xc0);
- buf[1] = castchar((uv&0x3f)|0x80);
- return 2;
+ buf[0] = castchar(((uv>>6)&0xff)|0xc0);
+ buf[1] = castchar((uv&0x3f)|0x80);
+ return 2;
}
if (uv <= 0xffff) {
- buf[0] = castchar(((uv>>12)&0xff)|0xe0);
- buf[1] = castchar(((uv>>6)&0x3f)|0x80);
- buf[2] = castchar((uv&0x3f)|0x80);
- return 3;
+ buf[0] = castchar(((uv>>12)&0xff)|0xe0);
+ buf[1] = castchar(((uv>>6)&0x3f)|0x80);
+ buf[2] = castchar((uv&0x3f)|0x80);
+ return 3;
}
if (uv <= 0x1fffff) {
- buf[0] = castchar(((uv>>18)&0xff)|0xf0);
- buf[1] = castchar(((uv>>12)&0x3f)|0x80);
- buf[2] = castchar(((uv>>6)&0x3f)|0x80);
- buf[3] = castchar((uv&0x3f)|0x80);
- return 4;
+ buf[0] = castchar(((uv>>18)&0xff)|0xf0);
+ buf[1] = castchar(((uv>>12)&0x3f)|0x80);
+ buf[2] = castchar(((uv>>6)&0x3f)|0x80);
+ buf[3] = castchar((uv&0x3f)|0x80);
+ return 4;
}
if (uv <= 0x3ffffff) {
- buf[0] = castchar(((uv>>24)&0xff)|0xf8);
- buf[1] = castchar(((uv>>18)&0x3f)|0x80);
- buf[2] = castchar(((uv>>12)&0x3f)|0x80);
- buf[3] = castchar(((uv>>6)&0x3f)|0x80);
- buf[4] = castchar((uv&0x3f)|0x80);
- return 5;
+ buf[0] = castchar(((uv>>24)&0xff)|0xf8);
+ buf[1] = castchar(((uv>>18)&0x3f)|0x80);
+ buf[2] = castchar(((uv>>12)&0x3f)|0x80);
+ buf[3] = castchar(((uv>>6)&0x3f)|0x80);
+ buf[4] = castchar((uv&0x3f)|0x80);
+ return 5;
}
if (uv <= 0x7fffffff) {
- buf[0] = castchar(((uv>>30)&0xff)|0xfc);
- buf[1] = castchar(((uv>>24)&0x3f)|0x80);
- buf[2] = castchar(((uv>>18)&0x3f)|0x80);
- buf[3] = castchar(((uv>>12)&0x3f)|0x80);
- buf[4] = castchar(((uv>>6)&0x3f)|0x80);
- buf[5] = castchar((uv&0x3f)|0x80);
- return 6;
+ buf[0] = castchar(((uv>>30)&0xff)|0xfc);
+ buf[1] = castchar(((uv>>24)&0x3f)|0x80);
+ buf[2] = castchar(((uv>>18)&0x3f)|0x80);
+ buf[3] = castchar(((uv>>12)&0x3f)|0x80);
+ buf[4] = castchar(((uv>>6)&0x3f)|0x80);
+ buf[5] = castchar((uv&0x3f)|0x80);
+ return 6;
}
rb_raise(rb_eRangeError, "pack(U): value out of range");
@@ -1717,12 +1686,12 @@ utf8_to_uv(const char *p, long *lenp)
long n;
if (!(uv & 0x80)) {
- *lenp = 1;
+ *lenp = 1;
return uv;
}
if (!(uv & 0x40)) {
- *lenp = 1;
- rb_raise(rb_eArgError, "malformed UTF-8 character");
+ *lenp = 1;
+ rb_raise(rb_eArgError, "malformed UTF-8 character");
}
if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
@@ -1731,30 +1700,30 @@ utf8_to_uv(const char *p, long *lenp)
else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
else {
- *lenp = 1;
- rb_raise(rb_eArgError, "malformed UTF-8 character");
+ *lenp = 1;
+ rb_raise(rb_eArgError, "malformed UTF-8 character");
}
if (n > *lenp) {
- rb_raise(rb_eArgError, "malformed UTF-8 character (expected %ld bytes, given %ld bytes)",
- n, *lenp);
+ rb_raise(rb_eArgError, "malformed UTF-8 character (expected %ld bytes, given %ld bytes)",
+ n, *lenp);
}
*lenp = n--;
if (n != 0) {
- while (n--) {
- c = *p++ & 0xff;
- if ((c & 0xc0) != 0x80) {
- *lenp -= n + 1;
- rb_raise(rb_eArgError, "malformed UTF-8 character");
- }
- else {
- c &= 0x3f;
- uv = uv << 6 | c;
- }
- }
+ while (n--) {
+ c = *p++ & 0xff;
+ if ((c & 0xc0) != 0x80) {
+ *lenp -= n + 1;
+ rb_raise(rb_eArgError, "malformed UTF-8 character");
+ }
+ else {
+ c &= 0x3f;
+ uv = uv << 6 | c;
+ }
+ }
}
n = *lenp - 1;
if (uv < utf8_limits[n]) {
- rb_raise(rb_eArgError, "redundant UTF-8 sequence");
+ rb_raise(rb_eArgError, "redundant UTF-8 sequence");
}
return uv;
}
diff --git a/pack.rb b/pack.rb
index 019fa80be4..d505eaee35 100644
--- a/pack.rb
+++ b/pack.rb
@@ -1,135 +1,9 @@
-# for pack.c
-
class Array
# call-seq:
- # arr.pack( aTemplateString ) -> aBinaryString
- # arr.pack( aTemplateString, buffer: aBufferString ) -> aBufferString
- #
- # Packs the contents of <i>arr</i> into a binary sequence according to
- # the directives in <i>aTemplateString</i> (see the table below)
- # Directives ``A,'' ``a,'' and ``Z'' may be followed by a count,
- # which gives the width of the resulting field. The remaining
- # directives also may take a count, indicating the number of array
- # elements to convert. If the count is an asterisk
- # (``<code>*</code>''), all remaining array elements will be
- # converted. Any of the directives ``<code>sSiIlL</code>'' may be
- # followed by an underscore (``<code>_</code>'') or
- # exclamation mark (``<code>!</code>'') to use the underlying
- # platform's native size for the specified type; otherwise, they use a
- # platform-independent size. Spaces are ignored in the template
- # string. See also String#unpack.
- #
- # a = [ "a", "b", "c" ]
- # n = [ 65, 66, 67 ]
- # a.pack("A3A3A3") #=> "a b c "
- # a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000"
- # n.pack("ccc") #=> "ABC"
- #
- # If <i>aBufferString</i> is specified and its capacity is enough,
- # +pack+ uses it as the buffer and returns it.
- # When the offset is specified by the beginning of <i>aTemplateString</i>,
- # the result is filled after the offset.
- # If original contents of <i>aBufferString</i> exists and it's longer than
- # the offset, the rest of <i>offsetOfBuffer</i> are overwritten by the result.
- # If it's shorter, the gap is filled with ``<code>\0</code>''.
- #
- # Note that ``buffer:'' option does not guarantee not to allocate memory
- # in +pack+. If the capacity of <i>aBufferString</i> is not enough,
- # +pack+ allocates memory.
- #
- # Directives for +pack+.
+ # pack(template, buffer: nil) -> string
#
- # Integer | Array |
- # Directive | Element | Meaning
- # ----------------------------------------------------------------------------
- # C | Integer | 8-bit unsigned (unsigned char)
- # S | Integer | 16-bit unsigned, native endian (uint16_t)
- # L | Integer | 32-bit unsigned, native endian (uint32_t)
- # Q | Integer | 64-bit unsigned, native endian (uint64_t)
- # J | Integer | pointer width unsigned, native endian (uintptr_t)
- # | | (J is available since Ruby 2.3.)
- # | |
- # c | Integer | 8-bit signed (signed char)
- # s | Integer | 16-bit signed, native endian (int16_t)
- # l | Integer | 32-bit signed, native endian (int32_t)
- # q | Integer | 64-bit signed, native endian (int64_t)
- # j | Integer | pointer width signed, native endian (intptr_t)
- # | | (j is available since Ruby 2.3.)
- # | |
- # S_ S! | Integer | unsigned short, native endian
- # I I_ I! | Integer | unsigned int, native endian
- # L_ L! | Integer | unsigned long, native endian
- # Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
- # | | if the platform has no long long type.)
- # | | (Q_ and Q! is available since Ruby 2.1.)
- # J! | Integer | uintptr_t, native endian (same with J)
- # | | (J! is available since Ruby 2.3.)
- # | |
- # s_ s! | Integer | signed short, native endian
- # i i_ i! | Integer | signed int, native endian
- # l_ l! | Integer | signed long, native endian
- # q_ q! | Integer | signed long long, native endian (ArgumentError
- # | | if the platform has no long long type.)
- # | | (q_ and q! is available since Ruby 2.1.)
- # j! | Integer | intptr_t, native endian (same with j)
- # | | (j! is available since Ruby 2.3.)
- # | |
- # S> s> S!> s!> | Integer | same as the directives without ">" except
- # L> l> L!> l!> | | big endian
- # I!> i!> | | (available since Ruby 1.9.3)
- # Q> q> Q!> q!> | | "S>" is the same as "n"
- # J> j> J!> j!> | | "L>" is the same as "N"
- # | |
- # S< s< S!< s!< | Integer | same as the directives without "<" except
- # L< l< L!< l!< | | little endian
- # I!< i!< | | (available since Ruby 1.9.3)
- # Q< q< Q!< q!< | | "S<" is the same as "v"
- # J< j< J!< j!< | | "L<" is the same as "V"
- # | |
- # n | Integer | 16-bit unsigned, network (big-endian) byte order
- # N | Integer | 32-bit unsigned, network (big-endian) byte order
- # v | Integer | 16-bit unsigned, VAX (little-endian) byte order
- # V | Integer | 32-bit unsigned, VAX (little-endian) byte order
- # | |
- # U | Integer | UTF-8 character
- # w | Integer | BER-compressed integer
- #
- # Float | Array |
- # Directive | Element | Meaning
- # ---------------------------------------------------------------------------
- # D d | Float | double-precision, native format
- # F f | Float | single-precision, native format
- # E | Float | double-precision, little-endian byte order
- # e | Float | single-precision, little-endian byte order
- # G | Float | double-precision, network (big-endian) byte order
- # g | Float | single-precision, network (big-endian) byte order
- #
- # String | Array |
- # Directive | Element | Meaning
- # ---------------------------------------------------------------------------
- # A | String | arbitrary binary string (space padded, count is width)
- # a | String | arbitrary binary string (null padded, count is width)
- # Z | String | same as ``a'', except that null is added with *
- # B | String | bit string (MSB first)
- # b | String | bit string (LSB first)
- # H | String | hex string (high nibble first)
- # h | String | hex string (low nibble first)
- # u | String | UU-encoded string
- # M | String | quoted printable, MIME encoding (see also RFC2045)
- # | | (text mode but input must use LF and output LF)
- # m | String | base64 encoded string (see RFC 2045)
- # | | (if count is 0, no line feed are added, see RFC 4648)
- # | | (count specifies input bytes between each LF,
- # | | rounded down to nearest multiple of 3)
- # P | String | pointer to a structure (fixed-length string)
- # p | String | pointer to a null-terminated string
- #
- # Misc. | Array |
- # Directive | Element | Meaning
- # ---------------------------------------------------------------------------
- # @ | --- | moves to absolute position
- # X | --- | back up a byte
- # x | --- | null byte
+ # Formats each element in +self+ into a binary string; returns that string.
+ # See {Packed Data}[rdoc-ref:packed_data.rdoc].
def pack(fmt, buffer: nil)
Primitive.pack_pack(fmt, buffer)
end
@@ -137,147 +11,21 @@ end
class String
# call-seq:
- # str.unpack(format) -> anArray
- #
- # Decodes <i>str</i> (which may contain binary data) according to the
- # format string, returning an array of each value extracted. The
- # format string consists of a sequence of single-character directives,
- # summarized in the table at the end of this entry.
- # Each directive may be followed
- # by a number, indicating the number of times to repeat with this
- # directive. An asterisk (``<code>*</code>'') will use up all
- # remaining elements. The directives <code>sSiIlL</code> may each be
- # followed by an underscore (``<code>_</code>'') or
- # exclamation mark (``<code>!</code>'') to use the underlying
- # platform's native size for the specified type; otherwise, it uses a
- # platform-independent consistent size. Spaces are ignored in the
- # format string. See also String#unpack1, Array#pack.
- #
- # "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
- # "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
- # "abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
- # "aa".unpack('b8B8') #=> ["10000110", "01100001"]
- # "aaa".unpack('h2H2c') #=> ["16", "61", 97]
- # "\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
- # "now=20is".unpack('M*') #=> ["now is"]
- # "whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
+ # unpack(template, offset: 0) -> array
#
- # This table summarizes the various formats and the Ruby classes
- # returned by each.
- #
- # Integer | |
- # Directive | Returns | Meaning
- # ------------------------------------------------------------------
- # C | Integer | 8-bit unsigned (unsigned char)
- # S | Integer | 16-bit unsigned, native endian (uint16_t)
- # L | Integer | 32-bit unsigned, native endian (uint32_t)
- # Q | Integer | 64-bit unsigned, native endian (uint64_t)
- # J | Integer | pointer width unsigned, native endian (uintptr_t)
- # | |
- # c | Integer | 8-bit signed (signed char)
- # s | Integer | 16-bit signed, native endian (int16_t)
- # l | Integer | 32-bit signed, native endian (int32_t)
- # q | Integer | 64-bit signed, native endian (int64_t)
- # j | Integer | pointer width signed, native endian (intptr_t)
- # | |
- # S_ S! | Integer | unsigned short, native endian
- # I I_ I! | Integer | unsigned int, native endian
- # L_ L! | Integer | unsigned long, native endian
- # Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
- # | | if the platform has no long long type.)
- # J! | Integer | uintptr_t, native endian (same with J)
- # | |
- # s_ s! | Integer | signed short, native endian
- # i i_ i! | Integer | signed int, native endian
- # l_ l! | Integer | signed long, native endian
- # q_ q! | Integer | signed long long, native endian (ArgumentError
- # | | if the platform has no long long type.)
- # j! | Integer | intptr_t, native endian (same with j)
- # | |
- # S> s> S!> s!> | Integer | same as the directives without ">" except
- # L> l> L!> l!> | | big endian
- # I!> i!> | |
- # Q> q> Q!> q!> | | "S>" is the same as "n"
- # J> j> J!> j!> | | "L>" is the same as "N"
- # | |
- # S< s< S!< s!< | Integer | same as the directives without "<" except
- # L< l< L!< l!< | | little endian
- # I!< i!< | |
- # Q< q< Q!< q!< | | "S<" is the same as "v"
- # J< j< J!< j!< | | "L<" is the same as "V"
- # | |
- # n | Integer | 16-bit unsigned, network (big-endian) byte order
- # N | Integer | 32-bit unsigned, network (big-endian) byte order
- # v | Integer | 16-bit unsigned, VAX (little-endian) byte order
- # V | Integer | 32-bit unsigned, VAX (little-endian) byte order
- # | |
- # U | Integer | UTF-8 character
- # w | Integer | BER-compressed integer (see Array#pack)
- #
- # Float | |
- # Directive | Returns | Meaning
- # -----------------------------------------------------------------
- # D d | Float | double-precision, native format
- # F f | Float | single-precision, native format
- # E | Float | double-precision, little-endian byte order
- # e | Float | single-precision, little-endian byte order
- # G | Float | double-precision, network (big-endian) byte order
- # g | Float | single-precision, network (big-endian) byte order
- #
- # String | |
- # Directive | Returns | Meaning
- # -----------------------------------------------------------------
- # A | String | arbitrary binary string (remove trailing nulls and ASCII spaces)
- # a | String | arbitrary binary string
- # Z | String | null-terminated string
- # B | String | bit string (MSB first)
- # b | String | bit string (LSB first)
- # H | String | hex string (high nibble first)
- # h | String | hex string (low nibble first)
- # u | String | UU-encoded string
- # M | String | quoted-printable, MIME encoding (see RFC2045)
- # m | String | base64 encoded string (RFC 2045) (default)
- # | | base64 encoded string (RFC 4648) if followed by 0
- # P | String | pointer to a structure (fixed-length string)
- # p | String | pointer to a null-terminated string
- #
- # Misc. | |
- # Directive | Returns | Meaning
- # -----------------------------------------------------------------
- # @ | --- | skip to the offset given by the length argument
- # X | --- | skip backward one byte
- # x | --- | skip forward one byte
- #
- # HISTORY
- #
- # * J, J! j, and j! are available since Ruby 2.3.
- # * Q_, Q!, q_, and q! are available since Ruby 2.1.
- # * I!<, i!<, I!>, and i!> are available since Ruby 1.9.3.
- def unpack(fmt)
- Primitive.pack_unpack(fmt)
+ # Extracts data from +self+, forming objects that become the elements of a new array;
+ # returns that array.
+ # See {Packed Data}[rdoc-ref:packed_data.rdoc].
+ def unpack(fmt, offset: 0)
+ Primitive.pack_unpack(fmt, offset)
end
# call-seq:
- # str.unpack1(format) -> obj
- #
- # Decodes <i>str</i> (which may contain binary data) according to the
- # format string, returning the first value extracted.
- # See also String#unpack, Array#pack.
- #
- # Contrast with String#unpack:
- #
- # "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
- # "abc \0\0abc \0\0".unpack1('A6Z6') #=> "abc"
- #
- # In that case data would be lost but often it's the case that the array
- # only holds one value, especially when unpacking binary data. For instance:
- #
- # "\xff\x00\x00\x00".unpack("l") #=> [255]
- # "\xff\x00\x00\x00".unpack1("l") #=> 255
+ # unpack1(template, offset: 0) -> object
#
- # Thus unpack1 is convenient, makes clear the intention and signals
- # the expected return value to those reading the code.
- def unpack1(fmt)
- Primitive.pack_unpack1(fmt)
+ # Like String#unpack, but unpacks and returns only the first extracted object.
+ # See {Packed Data}[rdoc-ref:packed_data.rdoc].
+ def unpack1(fmt, offset: 0)
+ Primitive.pack_unpack1(fmt, offset)
end
end
diff --git a/parse.y b/parse.y
index 4c4cbcf633..1c808bd60e 100644
--- a/parse.y
+++ b/parse.y
@@ -9,6 +9,8 @@
**********************************************************************/
+%require "3.0"
+
%{
#if !YYPURE
@@ -32,6 +34,7 @@ struct lex_context;
#include "internal/compile.h"
#include "internal/compilers.h"
#include "internal/complex.h"
+#include "internal/encoding.h"
#include "internal/error.h"
#include "internal/hash.h"
#include "internal/imemo.h"
@@ -42,7 +45,6 @@ struct lex_context;
#include "internal/re.h"
#include "internal/symbol.h"
#include "internal/thread.h"
-#include "internal/util.h"
#include "internal/variable.h"
#include "node.h"
#include "probes.h"
@@ -65,11 +67,22 @@ enum shareability {
struct lex_context {
unsigned int in_defined: 1;
unsigned int in_kwarg: 1;
+ unsigned int in_argdef: 1;
unsigned int in_def: 1;
unsigned int in_class: 1;
BITFIELD(enum shareability, shareable_constant_value, 2);
};
+#if defined(__GNUC__) && !defined(__clang__)
+// Suppress "parameter passing for argument of type 'struct
+// lex_context' changed" notes. `struct lex_context` is file scope,
+// and has no ABI compatibility issue.
+RBIMPL_WARNING_PUSH()
+RBIMPL_WARNING_IGNORED(-Wpsabi)
+RBIMPL_WARNING_POP()
+// Not sure why effective even after popped.
+#endif
+
#include "parse.h"
#define NO_LEX_CTXT (struct lex_context){0}
@@ -89,7 +102,6 @@ struct lex_context {
#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,\
@@ -107,10 +119,19 @@ struct lex_context {
(Current).end_pos = YYRHSLOC(Rhs, 0).end_pos; \
} \
while (0)
+#define YY_(Msgid) \
+ (((Msgid)[0] == 'm') && (strcmp((Msgid), "memory exhausted") == 0) ? \
+ "nesting too deep" : (Msgid))
#define RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(Current) \
rb_parser_set_location_from_strterm_heredoc(p, &p->lex.strterm->u.heredoc, &(Current))
-#define RUBY_SET_YYLLOC_OF_NONE(Current) \
+#define RUBY_SET_YYLLOC_OF_DELAYED_TOKEN(Current) \
+ rb_parser_set_location_of_delayed_token(p, &(Current))
+#define RUBY_SET_YYLLOC_OF_HEREDOC_END(Current) \
+ rb_parser_set_location_of_heredoc_end(p, &(Current))
+#define RUBY_SET_YYLLOC_OF_DUMMY_END(Current) \
+ rb_parser_set_location_of_dummy_end(p, &(Current))
+#define RUBY_SET_YYLLOC_OF_NONE(Current) \
rb_parser_set_location_of_none(p, &(Current))
#define RUBY_SET_YYLLOC(Current) \
rb_parser_set_location(p, &(Current))
@@ -164,10 +185,8 @@ enum lex_state_e {
#define IS_lex_state_all(ls) IS_lex_state_all_for(p->lex.state, (ls))
# define SET_LEX_STATE(ls) \
- (p->lex.state = \
- (p->debug ? \
- rb_parser_trace_lex_state(p, p->lex.state, (ls), __LINE__) : \
- (enum lex_state_e)(ls)))
+ parser_set_lex_state(p, ls, __LINE__)
+static inline enum lex_state_e parser_set_lex_state(struct parser_params *p, enum lex_state_e ls, int line);
typedef VALUE stack_type;
@@ -222,12 +241,12 @@ enum {
};
#define NUMPARAM_ID_P(id) numparam_id_p(id)
-#define NUMPARAM_ID_TO_IDX(id) (unsigned int)(((id) >> ID_SCOPE_SHIFT) - tNUMPARAM_1 + 1)
-#define NUMPARAM_IDX_TO_ID(idx) TOKEN2LOCALID((tNUMPARAM_1 + (idx) - 1))
+#define NUMPARAM_ID_TO_IDX(id) (unsigned int)(((id) >> ID_SCOPE_SHIFT) - (tNUMPARAM_1 - 1))
+#define NUMPARAM_IDX_TO_ID(idx) TOKEN2LOCALID((tNUMPARAM_1 - 1 + (idx)))
static int
numparam_id_p(ID id)
{
- if (!is_local_id(id)) return 0;
+ if (!is_local_id(id) || id < (tNUMPARAM_1 << ID_SCOPE_SHIFT)) return 0;
unsigned int idx = NUMPARAM_ID_TO_IDX(id);
return idx > 0 && idx <= NUMPARAM_MAX;
}
@@ -260,12 +279,12 @@ struct parser_params {
rb_imemo_tmpbuf_t *heap;
YYSTYPE *lval;
+ YYLTYPE *yylloc;
struct {
rb_strterm_t *strterm;
VALUE (*gets)(struct parser_params*,VALUE);
VALUE input;
- VALUE prevline;
VALUE lastline;
VALUE nextline;
const char *pbeg;
@@ -308,6 +327,14 @@ struct parser_params {
VALUE debug_buffer;
VALUE debug_output;
+ struct {
+ VALUE token;
+ int beg_line;
+ int beg_col;
+ int end_line;
+ int end_col;
+ } delayed;
+
ID cur_arg;
rb_ast_t *ast;
@@ -337,22 +364,24 @@ struct parser_params {
unsigned int do_loop: 1;
unsigned int do_chomp: 1;
unsigned int do_split: 1;
- unsigned int save_script_lines: 1;
+ unsigned int keep_script_lines: 1;
+ unsigned int error_tolerant: 1;
+ unsigned int keep_tokens: 1;
NODE *eval_tree_begin;
NODE *eval_tree;
VALUE error_buffer;
VALUE debug_lines;
const struct rb_iseq_struct *parent_iseq;
+ /* store specific keyword locations to generate dummy end token */
+ VALUE end_expect_token_locations;
+ /* id for terms */
+ int token_id;
+ /* Array for term tokens */
+ VALUE tokens;
#else
/* Ripper only */
- struct {
- VALUE token;
- int line;
- int col;
- } delayed;
-
VALUE value;
VALUE result;
VALUE parsing_thread;
@@ -397,11 +426,225 @@ pop_pktbl(struct parser_params *p, st_table *tbl)
p->pktbl = tbl;
}
+#ifndef RIPPER
+static void flush_debug_buffer(struct parser_params *p, VALUE out, VALUE str);
+
+static void
+debug_end_expect_token_locations(struct parser_params *p, const char *name)
+{
+ if(p->debug) {
+ VALUE mesg = rb_sprintf("%s: ", name);
+ rb_str_catf(mesg, " %"PRIsVALUE"\n", p->end_expect_token_locations);
+ flush_debug_buffer(p, p->debug_output, mesg);
+ }
+}
+
+static void
+push_end_expect_token_locations(struct parser_params *p, const rb_code_position_t *pos)
+{
+ if(NIL_P(p->end_expect_token_locations)) return;
+ rb_ary_push(p->end_expect_token_locations, rb_ary_new_from_args(2, INT2NUM(pos->lineno), INT2NUM(pos->column)));
+ debug_end_expect_token_locations(p, "push_end_expect_token_locations");
+}
+
+static void
+pop_end_expect_token_locations(struct parser_params *p)
+{
+ if(NIL_P(p->end_expect_token_locations)) return;
+ rb_ary_pop(p->end_expect_token_locations);
+ debug_end_expect_token_locations(p, "pop_end_expect_token_locations");
+}
+
+static VALUE
+peek_end_expect_token_locations(struct parser_params *p)
+{
+ if(NIL_P(p->end_expect_token_locations)) return Qnil;
+ return rb_ary_last(0, 0, p->end_expect_token_locations);
+}
+
+static ID
+parser_token2id(enum yytokentype tok)
+{
+ switch ((int) tok) {
+#define TOKEN2ID(tok) case tok: return rb_intern(#tok);
+#define TOKEN2ID2(tok, name) case tok: return rb_intern(name);
+ TOKEN2ID2(' ', "words_sep")
+ TOKEN2ID2('!', "!")
+ TOKEN2ID2('%', "%");
+ TOKEN2ID2('&', "&");
+ TOKEN2ID2('*', "*");
+ TOKEN2ID2('+', "+");
+ TOKEN2ID2('-', "-");
+ TOKEN2ID2('/', "/");
+ TOKEN2ID2('<', "<");
+ TOKEN2ID2('=', "=");
+ TOKEN2ID2('>', ">");
+ TOKEN2ID2('?', "?");
+ TOKEN2ID2('^', "^");
+ TOKEN2ID2('|', "|");
+ TOKEN2ID2('~', "~");
+ TOKEN2ID2(':', ":");
+ TOKEN2ID2(',', ",");
+ TOKEN2ID2('.', ".");
+ TOKEN2ID2(';', ";");
+ TOKEN2ID2('`', "`");
+ TOKEN2ID2('\n', "nl");
+ TOKEN2ID2('{', "{");
+ TOKEN2ID2('}', "}");
+ TOKEN2ID2('[', "[");
+ TOKEN2ID2(']', "]");
+ TOKEN2ID2('(', "(");
+ TOKEN2ID2(')', ")");
+ TOKEN2ID(keyword_class);
+ TOKEN2ID(keyword_module);
+ TOKEN2ID(keyword_def);
+ TOKEN2ID(keyword_undef);
+ TOKEN2ID(keyword_begin);
+ TOKEN2ID(keyword_rescue);
+ TOKEN2ID(keyword_ensure);
+ TOKEN2ID(keyword_end);
+ TOKEN2ID(keyword_if);
+ TOKEN2ID(keyword_unless);
+ TOKEN2ID(keyword_then);
+ TOKEN2ID(keyword_elsif);
+ TOKEN2ID(keyword_else);
+ TOKEN2ID(keyword_case);
+ TOKEN2ID(keyword_when);
+ TOKEN2ID(keyword_while);
+ TOKEN2ID(keyword_until);
+ TOKEN2ID(keyword_for);
+ TOKEN2ID(keyword_break);
+ TOKEN2ID(keyword_next);
+ TOKEN2ID(keyword_redo);
+ TOKEN2ID(keyword_retry);
+ TOKEN2ID(keyword_in);
+ TOKEN2ID(keyword_do);
+ TOKEN2ID(keyword_do_cond);
+ TOKEN2ID(keyword_do_block);
+ TOKEN2ID(keyword_do_LAMBDA);
+ TOKEN2ID(keyword_return);
+ TOKEN2ID(keyword_yield);
+ TOKEN2ID(keyword_super);
+ TOKEN2ID(keyword_self);
+ TOKEN2ID(keyword_nil);
+ TOKEN2ID(keyword_true);
+ TOKEN2ID(keyword_false);
+ TOKEN2ID(keyword_and);
+ TOKEN2ID(keyword_or);
+ TOKEN2ID(keyword_not);
+ TOKEN2ID(modifier_if);
+ TOKEN2ID(modifier_unless);
+ TOKEN2ID(modifier_while);
+ TOKEN2ID(modifier_until);
+ TOKEN2ID(modifier_rescue);
+ TOKEN2ID(keyword_alias);
+ TOKEN2ID(keyword_defined);
+ TOKEN2ID(keyword_BEGIN);
+ TOKEN2ID(keyword_END);
+ TOKEN2ID(keyword__LINE__);
+ TOKEN2ID(keyword__FILE__);
+ TOKEN2ID(keyword__ENCODING__);
+ TOKEN2ID(tIDENTIFIER);
+ TOKEN2ID(tFID);
+ TOKEN2ID(tGVAR);
+ TOKEN2ID(tIVAR);
+ TOKEN2ID(tCONSTANT);
+ TOKEN2ID(tCVAR);
+ TOKEN2ID(tLABEL);
+ TOKEN2ID(tINTEGER);
+ TOKEN2ID(tFLOAT);
+ TOKEN2ID(tRATIONAL);
+ TOKEN2ID(tIMAGINARY);
+ TOKEN2ID(tCHAR);
+ TOKEN2ID(tNTH_REF);
+ TOKEN2ID(tBACK_REF);
+ TOKEN2ID(tSTRING_CONTENT);
+ TOKEN2ID(tREGEXP_END);
+ TOKEN2ID(tDUMNY_END);
+ TOKEN2ID(tSP);
+ TOKEN2ID(tUPLUS);
+ TOKEN2ID(tUMINUS);
+ TOKEN2ID(tPOW);
+ TOKEN2ID(tCMP);
+ TOKEN2ID(tEQ);
+ TOKEN2ID(tEQQ);
+ TOKEN2ID(tNEQ);
+ TOKEN2ID(tGEQ);
+ TOKEN2ID(tLEQ);
+ TOKEN2ID(tANDOP);
+ TOKEN2ID(tOROP);
+ TOKEN2ID(tMATCH);
+ TOKEN2ID(tNMATCH);
+ TOKEN2ID(tDOT2);
+ TOKEN2ID(tDOT3);
+ TOKEN2ID(tBDOT2);
+ TOKEN2ID(tBDOT3);
+ TOKEN2ID(tAREF);
+ TOKEN2ID(tASET);
+ TOKEN2ID(tLSHFT);
+ TOKEN2ID(tRSHFT);
+ TOKEN2ID(tANDDOT);
+ TOKEN2ID(tCOLON2);
+ TOKEN2ID(tCOLON3);
+ TOKEN2ID(tOP_ASGN);
+ TOKEN2ID(tASSOC);
+ TOKEN2ID(tLPAREN);
+ TOKEN2ID(tLPAREN_ARG);
+ TOKEN2ID(tRPAREN);
+ TOKEN2ID(tLBRACK);
+ TOKEN2ID(tLBRACE);
+ TOKEN2ID(tLBRACE_ARG);
+ TOKEN2ID(tSTAR);
+ TOKEN2ID(tDSTAR);
+ TOKEN2ID(tAMPER);
+ TOKEN2ID(tLAMBDA);
+ TOKEN2ID(tSYMBEG);
+ TOKEN2ID(tSTRING_BEG);
+ TOKEN2ID(tXSTRING_BEG);
+ TOKEN2ID(tREGEXP_BEG);
+ TOKEN2ID(tWORDS_BEG);
+ TOKEN2ID(tQWORDS_BEG);
+ TOKEN2ID(tSYMBOLS_BEG);
+ TOKEN2ID(tQSYMBOLS_BEG);
+ TOKEN2ID(tSTRING_END);
+ TOKEN2ID(tSTRING_DEND);
+ TOKEN2ID(tSTRING_DBEG);
+ TOKEN2ID(tSTRING_DVAR);
+ TOKEN2ID(tLAMBEG);
+ TOKEN2ID(tLABEL_END);
+ TOKEN2ID(tIGNORED_NL);
+ TOKEN2ID(tCOMMENT);
+ TOKEN2ID(tEMBDOC_BEG);
+ TOKEN2ID(tEMBDOC);
+ TOKEN2ID(tEMBDOC_END);
+ TOKEN2ID(tHEREDOC_BEG);
+ TOKEN2ID(tHEREDOC_END);
+ TOKEN2ID(k__END__);
+ TOKEN2ID(tLOWEST);
+ TOKEN2ID(tUMINUS_NUM);
+ TOKEN2ID(tLAST_TOKEN);
+#undef TOKEN2ID
+#undef TOKEN2ID2
+ }
+
+ rb_bug("parser_token2id: unknown token %d", tok);
+
+ UNREACHABLE_RETURN(0);
+}
+
+#endif
+
+RBIMPL_ATTR_NONNULL((1, 2, 3))
static int parser_yyerror(struct parser_params*, const YYLTYPE *yylloc, const char*);
-#define yyerror0(msg) parser_yyerror(p, NULL, (msg))
+RBIMPL_ATTR_NONNULL((1, 2))
+static int parser_yyerror0(struct parser_params*, const char*);
+#define yyerror0(msg) parser_yyerror0(p, (msg))
#define yyerror1(loc, msg) parser_yyerror(p, (loc), (msg))
#define yyerror(yylloc, p, msg) parser_yyerror(p, yylloc, msg)
#define token_flush(ptr) ((ptr)->lex.ptok = (ptr)->lex.pcur)
+#define lex_goto_eol(p) ((p)->lex.pcur = (p)->lex.pend)
+#define lex_eol_p(p) ((p)->lex.pcur >= (p)->lex.pend)
+#define lex_eol_n_p(p,n) ((p)->lex.pcur+(n) >= (p)->lex.pend)
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);
@@ -451,6 +694,11 @@ static NODE* node_newnode_with_locals(struct parser_params *, enum node_type, VA
static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE, const rb_code_location_t*);
#define rb_node_newnode(type, a1, a2, a3, loc) node_newnode(p, (type), (a1), (a2), (a3), (loc))
+/* Make a new temporal node, which should not be appeared in the
+ * result AST and does not have node_id and location. */
+static NODE* node_new_temporal(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2);
+#define NODE_NEW_TEMPORAL(t,a0,a1,a2) node_new_temporal(p, (t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
+
static NODE *nd_set_loc(NODE *nd, const YYLTYPE *loc);
static int
@@ -568,7 +816,7 @@ static NODE *symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol)
static NODE *match_op(struct parser_params*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*);
-static ID *local_tbl(struct parser_params*);
+static rb_ast_id_table_t *local_tbl(struct parser_params*);
static VALUE reg_compile(struct parser_params*, VALUE, int);
static void reg_fragment_setenc(struct parser_params*, VALUE, int);
@@ -601,7 +849,7 @@ ripper_new_yylval(struct parser_params *p, ID a, VALUE b, VALUE c)
static inline int
ripper_is_node_yylval(VALUE n)
{
- return RB_TYPE_P(n, T_NODE) && nd_type(RNODE(n)) == NODE_RIPPER;
+ return RB_TYPE_P(n, T_NODE) && nd_type_p(RNODE(n), NODE_RIPPER);
}
#define value_expr(node) ((void)(node))
@@ -648,13 +896,15 @@ VALUE rb_parser_lex_state_name(enum lex_state_e state);
void rb_parser_show_bitstack(struct parser_params *, stack_type, const char *, int);
PRINTF_ARGS(void rb_parser_fatal(struct parser_params *p, const char *fmt, ...), 2, 3);
YYLTYPE *rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_heredoc_t *here, YYLTYPE *yylloc);
+YYLTYPE *rb_parser_set_location_of_delayed_token(struct parser_params *p, YYLTYPE *yylloc);
+YYLTYPE *rb_parser_set_location_of_heredoc_end(struct parser_params *p, YYLTYPE *yylloc);
+YYLTYPE *rb_parser_set_location_of_dummy_end(struct parser_params *p, YYLTYPE *yylloc);
YYLTYPE *rb_parser_set_location_of_none(struct parser_params *p, YYLTYPE *yylloc);
YYLTYPE *rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc);
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
@@ -672,7 +922,6 @@ 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);
@@ -697,12 +946,10 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner);
#endif
#define idFWD_REST '*'
-#ifdef RUBY3_KEYWORDS
#define idFWD_KWREST idPow /* Use simple "**", as tDSTAR is "**arg" */
-#else
-#define idFWD_KWREST 0
-#endif
#define idFWD_BLOCK '&'
+#define idFWD_ALL idDot3
+#define FORWARD_ARGS_WITH_RUBY2_KEYWORDS
#define RE_OPTION_ONCE (1<<16)
#define RE_OPTION_ENCODING_SHIFT 8
@@ -981,10 +1228,13 @@ rescued_expr(struct parser_params *p, NODE *arg, NODE *rescue,
static void
restore_defun(struct parser_params *p, NODE *name)
{
- YYSTYPE c = {.val = name->nd_cval};
+ NODE *save = name->nd_next;
+ YYSTYPE c = {.val = save->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;
+ p->max_numparam = (int)save->nd_nth;
+ numparam_pop(p, save->nd_head);
}
static void
@@ -1000,6 +1250,8 @@ endless_method_name(struct parser_params *p, NODE *defn, const YYLTYPE *loc)
token_info_drop(p, "def", loc->beg_pos);
}
+#define debug_token_line(p, name, line) if (p->debug) rb_parser_printf(p, name ":%d (%d: %ld|%ld|%ld)\n", line, p->ruby_sourceline, p->lex.ptok - p->lex.pbeg, p->lex.pcur - p->lex.ptok, p->lex.pend - p->lex.pcur)
+
#ifndef RIPPER
# define Qnone 0
# define Qnull 0
@@ -1084,6 +1336,43 @@ static int looking_at_eol_p(struct parser_params *p);
%expect 0
%define api.pure
%define parse.error verbose
+%printer {
+#ifndef RIPPER
+ if ($$) {
+ rb_parser_printf(p, "%s", ruby_node_name(nd_type($$)));
+ }
+#else
+#endif
+} <node>
+%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
@@ -1169,6 +1458,7 @@ static int looking_at_eol_p(struct parser_params *p);
%token <node> tBACK_REF "back reference"
%token <node> tSTRING_CONTENT "literal content"
%token <num> tREGEXP_END
+%token <num> tDUMNY_END "dummy end"
%type <node> singleton strings string string1 xstring regexp
%type <node> string_contents xstring_contents regexp_contents string_content
@@ -1261,6 +1551,9 @@ static int looking_at_eol_p(struct parser_params *p);
%token tSTRING_DEND "'}'"
%token tSTRING_DBEG tSTRING_DVAR tLAMBEG tLABEL_END
+%token tIGNORED_NL tCOMMENT tEMBDOC_BEG tEMBDOC tEMBDOC_END
+%token tHEREDOC_BEG tHEREDOC_END k__END__
+
/*
* precedence table
*/
@@ -1302,7 +1595,7 @@ program : {
if ($2 && !compile_for_eval) {
NODE *node = $2;
/* last expression should not be void */
- if (nd_type(node) == NODE_BLOCK) {
+ if (nd_type_p(node, NODE_BLOCK)) {
while (node->nd_next) {
node = node->nd_next;
}
@@ -1345,10 +1638,6 @@ top_stmts : none
/*% %*/
/*% ripper: stmts_add!($1, $3) %*/
}
- | error top_stmt
- {
- $$ = remove_begin($2);
- }
;
top_stmt : stmt
@@ -1418,10 +1707,6 @@ stmts : none
/*% %*/
/*% ripper: stmts_add!($1, $3) %*/
}
- | error stmt
- {
- $$ = remove_begin($2);
- }
;
stmt_or_begin : stmt
@@ -1497,7 +1782,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
| stmt modifier_while expr_value
{
/*%%%*/
- if ($1 && nd_type($1) == NODE_BEGIN) {
+ if ($1 && nd_type_p($1, NODE_BEGIN)) {
$$ = NEW_WHILE(cond(p, $3, &@3), $1->nd_body, 0, &@$);
}
else {
@@ -1509,7 +1794,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
| stmt modifier_until expr_value
{
/*%%%*/
- if ($1 && nd_type($1) == NODE_BEGIN) {
+ if ($1 && nd_type_p($1, NODE_BEGIN)) {
$$ = NEW_UNTIL(cond(p, $3, &@3), $1->nd_body, 0, &@$);
}
else {
@@ -1554,7 +1839,6 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
| lhs '=' lex_ctxt mrhs
{
/*%%%*/
- value_expr($4);
$$ = node_assign(p, $1, $4, $3, &@$);
/*% %*/
/*% ripper: assign!($1, $4) %*/
@@ -1563,7 +1847,6 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
{
/*%%%*/
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!($4, $6)) %*/
@@ -1576,6 +1859,12 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
/*% ripper: massign!($1, $4) %*/
}
| expr
+ | error
+ {
+ /*%%%*/
+ $$ = NEW_ERROR(&@$);
+ /*% %*/
+ }
;
command_asgn : lhs '=' lex_ctxt command_rhs
@@ -1627,7 +1916,7 @@ command_asgn : lhs '=' lex_ctxt command_rhs
/*%%%*/
$$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $6) %*/
+ /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/
}
| defn_head f_opt_paren_args '=' command
{
@@ -1728,14 +2017,18 @@ expr : command_call
value_expr($1);
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
p->command_start = FALSE;
- $<ctxt>$ = p->ctxt;
+ $<ctxt>2 = p->ctxt;
p->ctxt.in_kwarg = 1;
+ $<tbl>$ = push_pvtbl(p);
}
- {$<tbl>$ = push_pvtbl(p);}
- p_expr
- {pop_pvtbl(p, $<tbl>4);}
{
- p->ctxt.in_kwarg = $<ctxt>3.in_kwarg;
+ $<tbl>$ = push_pktbl(p);
+ }
+ p_top_expr_body
+ {
+ pop_pktbl(p, $<tbl>4);
+ pop_pvtbl(p, $<tbl>3);
+ p->ctxt.in_kwarg = $<ctxt>2.in_kwarg;
/*%%%*/
$$ = NEW_CASE3($1, NEW_IN($5, 0, 0, &@5), &@$);
/*% %*/
@@ -1746,14 +2039,18 @@ expr : command_call
value_expr($1);
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
p->command_start = FALSE;
- $<ctxt>$ = p->ctxt;
+ $<ctxt>2 = p->ctxt;
p->ctxt.in_kwarg = 1;
+ $<tbl>$ = push_pvtbl(p);
+ }
+ {
+ $<tbl>$ = push_pktbl(p);
}
- {$<tbl>$ = push_pvtbl(p);}
- p_expr
- {pop_pvtbl(p, $<tbl>4);}
+ p_top_expr_body
{
- p->ctxt.in_kwarg = $<ctxt>3.in_kwarg;
+ pop_pktbl(p, $<tbl>4);
+ pop_pvtbl(p, $<tbl>3);
+ p->ctxt.in_kwarg = $<ctxt>2.in_kwarg;
/*%%%*/
$$ = NEW_CASE3($1, NEW_IN($5, NEW_TRUE(&@5), NEW_FALSE(&@5), &@5), &@$);
/*% %*/
@@ -1762,22 +2059,27 @@ expr : command_call
| 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, &@$);
- /*%%%*/
- /*%
+def_name : fname
+ {
+ ID fname = get_id($1);
+ ID cur_arg = p->cur_arg;
+ YYSTYPE c = {.ctxt = p->ctxt};
+ numparam_name(p, fname);
+ NODE *save =
+ NODE_NEW_TEMPORAL(NODE_SELF,
+ /*head*/numparam_push(p),
+ /*nth*/p->max_numparam,
+ /*cval*/c.val);
+ local_push(p, 0);
+ p->cur_arg = 0;
+ p->ctxt.in_def = 1;
+ $<node>$ = NEW_NODE(NODE_SELF, /*vid*/cur_arg, /*mid*/fname, /*args*/save, &@$);
+ /*%%%*/
+ /*%
$$ = NEW_RIPPER(fname, get_value($1), $$, &NULL_LOC);
%*/
- }
- ;
+ }
+ ;
defn_head : k_def def_name
{
@@ -1788,7 +2090,12 @@ defn_head : k_def def_name
}
;
-defs_head : k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} def_name
+defs_head : k_def singleton dot_or_colon
+ {
+ SET_LEX_STATE(EXPR_FNAME);
+ p->ctxt.in_argdef = 1;
+ }
+ def_name
{
SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
$$ = $5;
@@ -1807,6 +2114,12 @@ expr_value : expr
value_expr($1);
$$ = $1;
}
+ | error
+ {
+ /*%%%*/
+ $$ = NEW_ERROR(&@$);
+ /*% %*/
+ }
;
expr_value_do : {COND_PUSH(1);} expr_value do {COND_POP();}
@@ -1888,14 +2201,14 @@ command : fcall command_args %prec tLOWEST
/*%%%*/
$$ = new_command_qcall(p, ID2VAL(idCOLON2), $1, $3, $4, Qnull, &@3, &@$);
/*% %*/
- /*% ripper: command_call!($1, ID2VAL(idCOLON2), $3, $4) %*/
+ /*% ripper: command_call!($1, $2, $3, $4) %*/
}
| primary_value tCOLON2 operation2 command_args cmd_brace_block
{
/*%%%*/
$$ = new_command_qcall(p, ID2VAL(idCOLON2), $1, $3, $4, $5, &@3, &@$);
/*% %*/
- /*% ripper: method_add_block!(command_call!($1, ID2VAL(idCOLON2), $3, $4), $5) %*/
+ /*% ripper: method_add_block!(command_call!($1, $2, $3, $4), $5) %*/
}
| keyword_super command_args
{
@@ -2175,7 +2488,7 @@ lhs : user_variable
/*%%%*/
$$ = attrset(p, $1, idCOLON2, $3, &@$);
/*% %*/
- /*% ripper: field!($1, ID2VAL(idCOLON2), $3) %*/
+ /*% ripper: field!($1, $2, $3) %*/
}
| primary_value call_op tCONSTANT
{
@@ -2366,7 +2679,7 @@ arg : lhs '=' lex_ctxt arg_rhs
/*%%%*/
$$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $6) %*/
+ /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/
}
| primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt arg_rhs
{
@@ -2626,11 +2939,7 @@ rel_expr : arg relop arg %prec '>'
}
;
-lex_ctxt : tSP
- {
- $$ = p->ctxt;
- }
- | none
+lex_ctxt : none
{
$$ = p->ctxt;
}
@@ -2817,6 +3126,16 @@ block_arg : tAMPER arg_value
/*% %*/
/*% ripper: $2 %*/
}
+ | tAMPER
+ {
+ if (!local_id(p, idFWD_BLOCK)) {
+ compile_error(p, "no anonymous block parameter");
+ }
+ /*%%%*/
+ $$ = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@1), &@$);
+ /*% %*/
+ /*% ripper: Qnil %*/
+ }
;
opt_block_arg : ',' block_arg
@@ -2829,6 +3148,7 @@ opt_block_arg : ',' block_arg
}
;
+/* value */
args : arg_value
{
/*%%%*/
@@ -2843,6 +3163,17 @@ args : arg_value
/*% %*/
/*% ripper: args_add_star!(args_new!, $2) %*/
}
+ | tSTAR
+ {
+ if (!local_id(p, idFWD_REST) ||
+ local_id(p, idFWD_ALL)) {
+ compile_error(p, "no anonymous rest parameter");
+ }
+ /*%%%*/
+ $$ = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@1), &@$);
+ /*% %*/
+ /*% ripper: args_add_star!(args_new!, Qnil) %*/
+ }
| args ',' arg_value
{
/*%%%*/
@@ -2857,12 +3188,25 @@ args : arg_value
/*% %*/
/*% ripper: args_add_star!($1, $4) %*/
}
+ | args ',' tSTAR
+ {
+ if (!local_id(p, idFWD_REST) ||
+ local_id(p, idFWD_ALL)) {
+ compile_error(p, "no anonymous rest parameter");
+ }
+ /*%%%*/
+ $$ = rest_arg_append(p, $1, NEW_LVAR(idFWD_REST, &@3), &@$);
+ /*% %*/
+ /*% ripper: args_add_star!($1, Qnil) %*/
+ }
;
+/* value */
mrhs_arg : mrhs
| arg_value
;
+/* value */
mrhs : args ',' arg_value
{
/*%%%*/
@@ -2928,7 +3272,7 @@ primary : literal
| tLPAREN_ARG stmt {SET_LEX_STATE(EXPR_ENDARG);} rparen
{
/*%%%*/
- if (nd_type($2) == NODE_SELF) $2->nd_state = 0;
+ if (nd_type_p($2, NODE_SELF)) $2->nd_state = 0;
$$ = $2;
/*% %*/
/*% ripper: paren!($2) %*/
@@ -2936,7 +3280,7 @@ primary : literal
| tLPAREN compstmt ')'
{
/*%%%*/
- if (nd_type($2) == NODE_SELF) $2->nd_state = 0;
+ if (nd_type_p($2, NODE_SELF)) $2->nd_state = 0;
$$ = $2;
/*% %*/
/*% ripper: paren!($2) %*/
@@ -3127,14 +3471,12 @@ primary : literal
ID id = internal_id(p);
NODE *m = NEW_ARGS_AUX(0, 0, &NULL_LOC);
NODE *args, *scope, *internal_var = NEW_DVAR(id, &@2);
- ID *tbl = ALLOC_N(ID, 3);
- tbl[0] = 1 /* length of local var table */; tbl[1] = id /* internal id */;
- rb_ast_add_local_table(p->ast, tbl);
+ rb_ast_id_table_t *tbl = rb_ast_new_local_table(p->ast, 1);
+ tbl->ids[0] = id; /* internal id */
switch (nd_type($2)) {
case NODE_LASGN:
- case NODE_DASGN:
- case NODE_DASGN_CURR: /* e.each {|internal_var| a = internal_var; ... } */
+ case NODE_DASGN: /* e.each {|internal_var| a = internal_var; ... } */
$2->nd_value = internal_var;
id = 0;
m->nd_plen = 1;
@@ -3224,28 +3566,38 @@ primary : literal
}
| defn_head
f_arglist
+ {
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
+ }
bodystmt
k_end
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
- $$ = set_defun_body(p, $1, $2, $3, &@$);
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
/*% %*/
- /*% ripper: def!(get_value($1), $2, $3) %*/
+ /*% ripper: def!(get_value($1), $2, $4) %*/
local_pop(p);
}
| defs_head
f_arglist
+ {
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
+ }
bodystmt
k_end
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
- $$ = set_defun_body(p, $1, $2, $3, &@$);
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
/*%
$1 = get_value($1);
%*/
- /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $3) %*/
+ /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/
local_pop(p);
}
| keyword_break
@@ -3288,6 +3640,9 @@ primary_value : primary
k_begin : keyword_begin
{
token_info_push(p, "begin", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
@@ -3297,7 +3652,7 @@ k_if : keyword_if
token_info_push(p, "if", &@$);
if (p->token_info && p->token_info->nonspc &&
p->token_info->next && !strcmp(p->token_info->next->token, "else")) {
- const char *tok = p->lex.ptok;
+ const char *tok = p->lex.ptok - rb_strlen_lit("if");
const char *beg = p->lex.pbeg + p->token_info->next->beg.column;
beg += rb_strlen_lit("else");
while (beg < tok && ISSPACE(*beg)) beg++;
@@ -3305,36 +3660,54 @@ k_if : keyword_if
p->token_info->nonspc = 0;
}
}
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
k_unless : keyword_unless
{
token_info_push(p, "unless", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
k_while : keyword_while
{
token_info_push(p, "while", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
k_until : keyword_until
{
token_info_push(p, "until", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
k_case : keyword_case
{
token_info_push(p, "case", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
k_for : keyword_for
{
token_info_push(p, "for", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
@@ -3342,6 +3715,9 @@ k_class : keyword_class
{
token_info_push(p, "class", &@$);
$<ctxt>$ = p->ctxt;
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
@@ -3349,24 +3725,35 @@ k_module : keyword_module
{
token_info_push(p, "module", &@$);
$<ctxt>$ = p->ctxt;
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
k_def : keyword_def
{
token_info_push(p, "def", &@$);
+ p->ctxt.in_argdef = 1;
}
;
k_do : keyword_do
{
token_info_push(p, "do", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
+
}
;
k_do_block : keyword_do_block
{
token_info_push(p, "do", &@$);
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
}
;
@@ -3413,6 +3800,13 @@ k_elsif : keyword_elsif
k_end : keyword_end
{
token_info_pop(p, "end", &@$);
+ /*%%%*/
+ pop_end_expect_token_locations(p);
+ /*% %*/
+ }
+ | tDUMNY_END
+ {
+ compile_error(p, "syntax error, unexpected end-of-input");
}
;
@@ -3550,6 +3944,8 @@ f_any_kwrest : f_kwrest
| f_no_kwarg {$$ = ID2VAL(idNil);}
;
+f_eq : {p->ctxt.in_argdef = 0;} '=';
+
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, $3, $4, &@3);
@@ -3662,6 +4058,7 @@ block_param_def : '|' opt_bv_decl '|'
{
p->cur_arg = 0;
p->max_numparam = ORDINAL_PARAM;
+ p->ctxt.in_argdef = 0;
/*%%%*/
$$ = 0;
/*% %*/
@@ -3671,6 +4068,7 @@ block_param_def : '|' opt_bv_decl '|'
{
p->cur_arg = 0;
p->max_numparam = ORDINAL_PARAM;
+ p->ctxt.in_argdef = 0;
/*%%%*/
$$ = $2;
/*% %*/
@@ -3681,7 +4079,7 @@ block_param_def : '|' opt_bv_decl '|'
opt_bv_decl : opt_nl
{
- $$ = 0;
+ $$ = 0;
}
| opt_nl ';' bv_decls opt_nl
{
@@ -3751,6 +4149,7 @@ lambda : tLAMBDA
f_larglist : '(' f_args opt_bv_decl ')'
{
+ p->ctxt.in_argdef = 0;
/*%%%*/
$$ = $2;
p->max_numparam = ORDINAL_PARAM;
@@ -3759,6 +4158,7 @@ f_larglist : '(' f_args opt_bv_decl ')'
}
| f_args
{
+ p->ctxt.in_argdef = 0;
/*%%%*/
if (!args_info_empty_p($1->nd_ainfo))
p->max_numparam = ORDINAL_PARAM;
@@ -3772,9 +4172,15 @@ lambda_body : tLAMBEG compstmt '}'
token_info_pop(p, "}", &@3);
$$ = $2;
}
- | keyword_do_LAMBDA bodystmt k_end
+ | keyword_do_LAMBDA
{
- $$ = $2;
+ /*%%%*/
+ push_end_expect_token_locations(p, &@1.beg_pos);
+ /*% %*/
+ }
+ bodystmt k_end
+ {
+ $$ = $3;
}
;
@@ -3791,7 +4197,7 @@ do_block : k_do_block do_body k_end
block_call : command do_block
{
/*%%%*/
- if (nd_type($1) == NODE_YIELD) {
+ if (nd_type_p($1, NODE_YIELD)) {
compile_error(p, "block given to yield");
}
else {
@@ -3848,14 +4254,14 @@ method_call : fcall paren_args
$$ = new_qcall(p, ID2VAL(idCOLON2), $1, $3, $4, &@3, &@$);
nd_set_line($$, @3.end_pos.lineno);
/*% %*/
- /*% ripper: method_add_arg!(call!($1, ID2VAL(idCOLON2), $3), $4) %*/
+ /*% ripper: method_add_arg!(call!($1, $2, $3), $4) %*/
}
| primary_value tCOLON2 operation3
{
/*%%%*/
$$ = new_qcall(p, ID2VAL(idCOLON2), $1, $3, Qnull, &@3, &@$);
/*% %*/
- /*% ripper: call!($1, ID2VAL(idCOLON2), $3) %*/
+ /*% ripper: call!($1, $2, $3) %*/
}
| primary_value call_op paren_args
{
@@ -3871,7 +4277,7 @@ method_call : fcall paren_args
$$ = new_qcall(p, ID2VAL(idCOLON2), $1, ID2VAL(idCall), $3, &@2, &@$);
nd_set_line($$, @2.end_pos.lineno);
/*% %*/
- /*% ripper: method_add_arg!(call!($1, ID2VAL(idCOLON2), ID2VAL(idCall)), $3) %*/
+ /*% ripper: method_add_arg!(call!($1, $2, ID2VAL(idCall)), $3) %*/
}
| keyword_super paren_args
{
@@ -3890,7 +4296,7 @@ method_call : fcall paren_args
| primary_value '[' opt_call_args rbracket
{
/*%%%*/
- if ($1 && nd_type($1) == NODE_SELF)
+ if ($1 && nd_type_p($1, NODE_SELF))
$$ = NEW_FCALL(tAREF, $3, &@$);
else
$$ = NEW_CALL($1, tAREF, $3, &@$);
@@ -4243,21 +4649,13 @@ p_args : p_expr
$$ = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &@$);
%*/
}
- | p_args_head tSTAR tIDENTIFIER
- {
- $$ = new_array_pattern_tail(p, $1, 1, $3, Qnone, &@$);
- }
- | p_args_head tSTAR tIDENTIFIER ',' p_args_post
+ | p_args_head p_rest
{
- $$ = new_array_pattern_tail(p, $1, 1, $3, $5, &@$);
+ $$ = new_array_pattern_tail(p, $1, 1, $2, Qnone, &@$);
}
- | p_args_head tSTAR
+ | p_args_head p_rest ',' p_args_post
{
- $$ = new_array_pattern_tail(p, $1, 1, 0, Qnone, &@$);
- }
- | p_args_head tSTAR ',' p_args_post
- {
- $$ = new_array_pattern_tail(p, $1, 1, 0, $4, &@$);
+ $$ = new_array_pattern_tail(p, $1, 1, $2, $4, &@$);
}
| p_args_tail
;
@@ -4288,9 +4686,6 @@ p_args_tail : p_rest
p_find : p_rest ',' p_args_post ',' p_rest
{
$$ = 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!");
}
;
@@ -4357,7 +4752,7 @@ p_kw : p_kw_label p_expr
{
error_duplicate_pattern_key(p, get_id($1), &@1);
/*%%%*/
- $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@$), &@$), $2);
+ $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@1), &@$), $2);
/*% %*/
/*% ripper: rb_ary_new_from_args(2, get_value($1), get_value($2)) %*/
}
@@ -4380,7 +4775,7 @@ p_kw_label : tLABEL
{
YYLTYPE loc = code_loc_gen(&@1, &@3);
/*%%%*/
- if (!$2 || nd_type($2) == NODE_STR) {
+ if (!$2 || nd_type_p($2, NODE_STR)) {
NODE *node = dsym_node(p, $2, &loc);
$$ = SYM2ID(node->nd_lit);
}
@@ -4507,7 +4902,7 @@ p_var_ref : '^' tIDENTIFIER
{
/*%%%*/
NODE *n = gettable(p, $2, &@$);
- if (!(nd_type(n) == NODE_LVAR || nd_type(n) == NODE_DVAR)) {
+ if (!(nd_type_p(n, NODE_LVAR) || nd_type_p(n, NODE_DVAR))) {
compile_error(p, "%"PRIsVALUE": no such local variable", rb_id2str($2));
}
$$ = n;
@@ -4523,7 +4918,7 @@ p_var_ref : '^' tIDENTIFIER
}
;
-p_expr_ref : '^' tLPAREN expr_value ')'
+p_expr_ref : '^' tLPAREN expr_value rparen
{
/*%%%*/
$$ = NEW_BEGIN($3, &@$);
@@ -4563,7 +4958,16 @@ opt_rescue : k_rescue exc_list exc_var then
$$ = NEW_RESBODY($2,
$3 ? block_append(p, node_assign(p, $3, NEW_ERRINFO(&@3), NO_LEX_CTXT, &@3), $5) : $5,
$6, &@$);
- fixpos($$, $2?$2:$5);
+
+ if ($2) {
+ fixpos($$, $2);
+ }
+ else if ($3) {
+ fixpos($$, $3);
+ }
+ else {
+ fixpos($$, $5);
+ }
/*% %*/
/*% ripper: rescue!(escape_Qundef($2), escape_Qundef($3), escape_Qundef($5), escape_Qundef($6)) %*/
}
@@ -4965,9 +5369,7 @@ ssym : tSYMBEG sym
;
sym : fname
- | tIVAR
- | tGVAR
- | tCVAR
+ | nonlocal_var
;
dsym : tSYMBEG string_contents tSTRING_END
@@ -5003,10 +5405,8 @@ nonlocal_var : tIVAR
;
user_variable : tIDENTIFIER
- | tIVAR
- | tGVAR
| tCONSTANT
- | tCVAR
+ | nonlocal_var
;
keyword_variable: keyword_nil {$$ = KWD2EID(nil, $1);}
@@ -5081,6 +5481,7 @@ superclass : '<'
f_opt_paren_args: f_paren_args
| none
{
+ p->ctxt.in_argdef = 0;
$$ = new_args_tail(p, Qnone, Qnone, Qnone, &@0);
$$ = new_args(p, Qnone, Qnone, Qnone, Qnone, $$, &@0);
}
@@ -5094,26 +5495,7 @@ f_paren_args : '(' f_args rparen
/*% ripper: paren!($2) %*/
SET_LEX_STATE(EXPR_BEG);
p->command_start = TRUE;
- }
- | '(' f_arg ',' args_forward rparen
- {
- add_forwarding_args(p);
- /*%%%*/
- $$ = new_args_forward_def(p, $2, &@$);
- /*% %*/
- /*% ripper: paren!(params!($2, Qnone, $4, Qnone, Qnone, Qnone, Qnone)) %*/
- SET_LEX_STATE(EXPR_BEG);
- p->command_start = TRUE;
- }
- | '(' args_forward rparen
- {
- add_forwarding_args(p);
- /*%%%*/
- $$ = new_args_forward_def(p, 0, &@$);
- /*% %*/
- /*% ripper: paren!(params!(Qnone, Qnone, $2, Qnone, Qnone, Qnone, Qnone)) %*/
- SET_LEX_STATE(EXPR_BEG);
- p->command_start = TRUE;
+ p->ctxt.in_argdef = 0;
}
;
@@ -5121,11 +5503,13 @@ f_arglist : f_paren_args
| {
$<ctxt>$ = p->ctxt;
p->ctxt.in_kwarg = 1;
+ p->ctxt.in_argdef = 1;
SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */
}
f_args term
{
p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
+ p->ctxt.in_argdef = 0;
$$ = $2;
SET_LEX_STATE(EXPR_BEG);
p->command_start = TRUE;
@@ -5148,6 +5532,14 @@ args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, Qnone, Qnone, $1, &@1);
}
+ | args_forward
+ {
+ add_forwarding_args(p);
+ $$ = new_args_tail(p, Qnone, $1, ID2VAL(idFWD_BLOCK), &@1);
+ /*%%%*/
+ ($$->nd_ainfo)->forwarding = 1;
+ /*% %*/
+ }
;
opt_args_tail : ',' args_tail
@@ -5226,7 +5618,11 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
args_forward : tBDOT3
{
/*%%%*/
- $$ = idDot3;
+#ifdef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
+ $$ = 0;
+#else
+ $$ = idFWD_KWREST;
+#endif
/*% %*/
/*% ripper: args_forward! %*/
}
@@ -5337,6 +5733,7 @@ f_label : tLABEL
arg_var(p, formal_argument(p, $1));
p->cur_arg = get_id($1);
p->max_numparam = ORDINAL_PARAM;
+ p->ctxt.in_argdef = 0;
$$ = $1;
}
;
@@ -5344,6 +5741,7 @@ f_label : tLABEL
f_kw : f_label arg_value
{
p->cur_arg = 0;
+ p->ctxt.in_argdef = 1;
/*%%%*/
$$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
/*% %*/
@@ -5352,6 +5750,7 @@ f_kw : f_label arg_value
| f_label
{
p->cur_arg = 0;
+ p->ctxt.in_argdef = 1;
/*%%%*/
$$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
/*% %*/
@@ -5361,6 +5760,7 @@ f_kw : f_label arg_value
f_block_kw : f_label primary_value
{
+ p->ctxt.in_argdef = 1;
/*%%%*/
$$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
/*% %*/
@@ -5368,6 +5768,7 @@ f_block_kw : f_label primary_value
}
| f_label
{
+ p->ctxt.in_argdef = 1;
/*%%%*/
$$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
/*% %*/
@@ -5412,7 +5813,7 @@ kwrest_mark : tPOW
| tDSTAR
;
-f_no_kwarg : kwrest_mark keyword_nil
+f_no_kwarg : p_kwnorest
{
/*%%%*/
/*% %*/
@@ -5430,17 +5831,18 @@ f_kwrest : kwrest_mark tIDENTIFIER
}
| kwrest_mark
{
+ arg_var(p, idFWD_KWREST);
/*%%%*/
- $$ = internal_id(p);
- arg_var(p, $$);
+ $$ = idFWD_KWREST;
/*% %*/
/*% ripper: kwrest_param!(Qnil) %*/
}
;
-f_opt : f_arg_asgn '=' arg_value
+f_opt : f_arg_asgn f_eq arg_value
{
p->cur_arg = 0;
+ p->ctxt.in_argdef = 1;
/*%%%*/
$$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$);
/*% %*/
@@ -5448,9 +5850,10 @@ f_opt : f_arg_asgn '=' arg_value
}
;
-f_block_opt : f_arg_asgn '=' primary_value
+f_block_opt : f_arg_asgn f_eq primary_value
{
p->cur_arg = 0;
+ p->ctxt.in_argdef = 1;
/*%%%*/
$$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$);
/*% %*/
@@ -5504,9 +5907,9 @@ f_rest_arg : restarg_mark tIDENTIFIER
}
| restarg_mark
{
+ arg_var(p, idFWD_REST);
/*%%%*/
- $$ = internal_id(p);
- arg_var(p, $$);
+ $$ = idFWD_REST;
/*% %*/
/*% ripper: rest_param!(Qnil) %*/
}
@@ -5524,6 +5927,14 @@ f_block_arg : blkarg_mark tIDENTIFIER
/*% %*/
/*% ripper: blockarg!($2) %*/
}
+ | blkarg_mark
+ {
+ arg_var(p, idFWD_BLOCK);
+ /*%%%*/
+ $$ = idFWD_BLOCK;
+ /*% %*/
+ /*% ripper: blockarg!(Qnil) %*/
+ }
;
opt_f_block_arg : ',' f_block_arg
@@ -5587,8 +5998,8 @@ assocs : assoc
}
else if (tail) {
if (assocs->nd_head &&
- !tail->nd_head && nd_type(tail->nd_next) == NODE_LIST &&
- nd_type(tail->nd_next->nd_head) == NODE_HASH) {
+ !tail->nd_head && nd_type_p(tail->nd_next, NODE_LIST) &&
+ nd_type_p(tail->nd_next->nd_head, NODE_HASH)) {
/* DSTAR */
tail = tail->nd_next->nd_head->nd_head;
}
@@ -5603,7 +6014,7 @@ assocs : assoc
assoc : arg_value tASSOC arg_value
{
/*%%%*/
- if (nd_type($1) == NODE_STR) {
+ if (nd_type_p($1, NODE_STR)) {
nd_set_type($1, NODE_LIT);
RB_OBJ_WRITE(p->ast, &$1->nd_lit, rb_fstring($1->nd_lit));
}
@@ -5618,6 +6029,15 @@ assoc : arg_value tASSOC arg_value
/*% %*/
/*% ripper: assoc_new!($1, $2) %*/
}
+ | tLABEL
+ {
+ /*%%%*/
+ NODE *val = gettable(p, $1, &@$);
+ if (!val) val = NEW_BEGIN(0, &@$);
+ $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@1), &@$), val);
+ /*% %*/
+ /*% ripper: assoc_new!($1, Qnil) %*/
+ }
| tSTRING_BEG string_contents tLABEL_END arg_value
{
/*%%%*/
@@ -5629,7 +6049,7 @@ assoc : arg_value tASSOC arg_value
| tDSTAR arg_value
{
/*%%%*/
- if (nd_type($2) == NODE_HASH &&
+ if (nd_type_p($2, NODE_HASH) &&
!($2->nd_head && $2->nd_head->nd_alen)) {
static VALUE empty_hash;
if (!empty_hash) {
@@ -5643,6 +6063,18 @@ assoc : arg_value tASSOC arg_value
/*% %*/
/*% ripper: assoc_splat!($2) %*/
}
+ | tDSTAR
+ {
+ if (!local_id(p, idFWD_KWREST) ||
+ local_id(p, idFWD_ALL)) {
+ compile_error(p, "no anonymous keyword rest parameter");
+ }
+ /*%%%*/
+ $$ = list_append(p, NEW_LIST(0, &@$),
+ NEW_LVAR(idFWD_KWREST, &@$));
+ /*% %*/
+ /*% ripper: assoc_splat!(Qnil) %*/
+ }
;
operation : tIDENTIFIER
@@ -5650,9 +6082,7 @@ operation : tIDENTIFIER
| tFID
;
-operation2 : tIDENTIFIER
- | tCONSTANT
- | tFID
+operation2 : operation
| op
;
@@ -5690,13 +6120,16 @@ rbracket : opt_nl ']'
rbrace : opt_nl '}'
;
-trailer : /* none */
- | '\n'
+trailer : opt_nl
| ','
;
term : ';' {yyerrok;token_flush(p);}
- | '\n' {token_flush(p);}
+ | '\n'
+ {
+ @$.end_pos = @$.beg_pos;
+ token_flush(p);
+ }
;
terms : term
@@ -5757,12 +6190,91 @@ ripper_yylval_id(struct parser_params *p, ID x)
#endif
#define set_yylval_noname() set_yylval_id(keyword_nil)
+#define has_delayed_token(p) (!NIL_P(p->delayed.token))
#ifndef RIPPER
#define literal_flush(p, ptr) ((p)->lex.ptok = (ptr))
-#define dispatch_scan_event(p, t) ((void)0)
-#define dispatch_delayed_token(p, t) ((void)0)
-#define has_delayed_token(p) (0)
+#define dispatch_scan_event(p, t) parser_dispatch_scan_event(p, t, __LINE__)
+
+static bool
+parser_has_token(struct parser_params *p)
+{
+ if (p->keep_tokens && (p->lex.pcur < p->lex.ptok)) rb_bug("lex.pcur < lex.ptok. (line: %d) %ld|%ld|%ld", p->ruby_sourceline, p->lex.ptok - p->lex.pbeg, p->lex.pcur - p->lex.ptok, p->lex.pend - p->lex.pcur);
+ return p->lex.pcur > p->lex.ptok;
+}
+
+static VALUE
+code_loc_to_ary(const rb_code_location_t *loc)
+{
+ VALUE ary = rb_ary_new_from_args(4,
+ INT2NUM(loc->beg_pos.lineno), INT2NUM(loc->beg_pos.column),
+ INT2NUM(loc->end_pos.lineno), INT2NUM(loc->end_pos.column));
+ rb_obj_freeze(ary);
+
+ return ary;
+}
+
+static void
+parser_append_tokens(struct parser_params *p, VALUE str, enum yytokentype t, int line)
+{
+ VALUE ary;
+ int token_id;
+
+ ary = rb_ary_new2(4);
+ token_id = p->token_id;
+ rb_ary_push(ary, INT2FIX(token_id));
+ rb_ary_push(ary, ID2SYM(parser_token2id(t)));
+ rb_ary_push(ary, str);
+ rb_ary_push(ary, code_loc_to_ary(p->yylloc));
+ rb_obj_freeze(ary);
+ rb_ary_push(p->tokens, ary);
+ p->token_id++;
+
+ if (p->debug) {
+ rb_parser_printf(p, "Append tokens (line: %d) %"PRIsVALUE"\n", line, ary);
+ }
+}
+
+static void
+parser_dispatch_scan_event(struct parser_params *p, enum yytokentype t, int line)
+{
+ debug_token_line(p, "parser_dispatch_scan_event", line);
+
+ if (!parser_has_token(p)) return;
+
+ RUBY_SET_YYLLOC(*p->yylloc);
+
+ if (p->keep_tokens) {
+ VALUE str = STR_NEW(p->lex.ptok, p->lex.pcur - p->lex.ptok);
+ parser_append_tokens(p, str, t, line);
+ }
+
+ token_flush(p);
+}
+
+#define dispatch_delayed_token(p, t) parser_dispatch_delayed_token(p, t, __LINE__)
+static void
+parser_dispatch_delayed_token(struct parser_params *p, enum yytokentype t, int line)
+{
+ int saved_line = p->ruby_sourceline;
+ const char *saved_tokp = p->lex.ptok;
+
+ debug_token_line(p, "parser_dispatch_delayed_token", line);
+
+ if (!has_delayed_token(p)) return;
+
+ RUBY_SET_YYLLOC_OF_DELAYED_TOKEN(*p->yylloc);
+
+ if (p->keep_tokens) {
+ p->ruby_sourceline = p->delayed.beg_line;
+ p->lex.ptok = p->lex.pbeg + p->delayed.beg_col;
+ parser_append_tokens(p, p->delayed.token, t, line);
+ p->ruby_sourceline = saved_line;
+ p->lex.ptok = saved_tokp;
+ }
+
+ p->delayed.token = Qnil;
+}
#else
#define literal_flush(p, ptr) ((void)(ptr))
@@ -5787,6 +6299,7 @@ ripper_scan_event_val(struct parser_params *p, enum yytokentype t)
{
VALUE str = STR_NEW(p->lex.ptok, p->lex.pcur - p->lex.ptok);
VALUE rval = ripper_dispatch1(p, ripper_token2eventid(t), str);
+ RUBY_SET_YYLLOC(*p->yylloc);
token_flush(p);
return rval;
}
@@ -5805,16 +6318,15 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t)
int saved_line = p->ruby_sourceline;
const char *saved_tokp = p->lex.ptok;
- if (NIL_P(p->delayed.token)) return;
- p->ruby_sourceline = p->delayed.line;
- p->lex.ptok = p->lex.pbeg + p->delayed.col;
+ if (!has_delayed_token(p)) return;
+ p->ruby_sourceline = p->delayed.beg_line;
+ p->lex.ptok = p->lex.pbeg + p->delayed.beg_col;
add_mark_object(p, yylval_rval = ripper_dispatch1(p, ripper_token2eventid(t), p->delayed.token));
p->delayed.token = Qnil;
p->ruby_sourceline = saved_line;
p->lex.ptok = saved_tokp;
}
#define dispatch_delayed_token(p, t) ripper_dispatch_delayed_token(p, t)
-#define has_delayed_token(p) (!NIL_P(p->delayed.token))
#endif /* RIPPER */
static inline int
@@ -5951,22 +6463,29 @@ parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc)
static int
parser_yyerror(struct parser_params *p, const YYLTYPE *yylloc, const char *msg)
{
+#if 0
YYLTYPE current;
if (!yylloc) {
yylloc = RUBY_SET_YYLLOC(current);
}
else if ((p->ruby_sourceline != yylloc->beg_pos.lineno &&
- p->ruby_sourceline != yylloc->end_pos.lineno) ||
- (yylloc->beg_pos.lineno == yylloc->end_pos.lineno &&
- yylloc->beg_pos.column == yylloc->end_pos.column)) {
+ p->ruby_sourceline != yylloc->end_pos.lineno)) {
yylloc = 0;
}
+#endif
compile_error(p, "%s", msg);
parser_show_error_line(p, yylloc);
return 0;
}
+static int
+parser_yyerror0(struct parser_params *p, const char *msg)
+{
+ YYLTYPE current;
+ return parser_yyerror(p, RUBY_SET_YYLLOC(current), msg);
+}
+
static void
ruby_show_error_line(VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str)
{
@@ -6076,16 +6595,14 @@ static int
parser_yyerror(struct parser_params *p, const YYLTYPE *yylloc, const char *msg)
{
const char *pcur = 0, *ptok = 0;
- if (yylloc &&
- p->ruby_sourceline == yylloc->beg_pos.lineno &&
+ if (p->ruby_sourceline == yylloc->beg_pos.lineno &&
p->ruby_sourceline == yylloc->end_pos.lineno) {
pcur = p->lex.pcur;
ptok = p->lex.ptok;
p->lex.ptok = p->lex.pbeg + yylloc->beg_pos.column;
p->lex.pcur = p->lex.pbeg + yylloc->end_pos.column;
}
- dispatch1(parse_error, STR_NEW2(msg));
- ripper_error(p);
+ parser_yyerror0(p, msg);
if (pcur) {
p->lex.ptok = ptok;
p->lex.pcur = pcur;
@@ -6093,6 +6610,14 @@ parser_yyerror(struct parser_params *p, const YYLTYPE *yylloc, const char *msg)
return 0;
}
+static int
+parser_yyerror0(struct parser_params *p, const char *msg)
+{
+ dispatch1(parse_error, STR_NEW2(msg));
+ ripper_error(p);
+ return 0;
+}
+
static inline void
parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc)
{
@@ -6251,7 +6776,8 @@ yycompile0(VALUE arg)
cov = Qtrue;
}
}
- if (p->save_script_lines) {
+
+ if (p->keep_script_lines || ruby_vm_keep_script_lines) {
if (!p->debug_lines) {
p->debug_lines = rb_ary_new();
}
@@ -6271,14 +6797,15 @@ yycompile0(VALUE arg)
p->lex.strterm = 0;
p->lex.pcur = p->lex.pbeg = p->lex.pend = 0;
- p->lex.prevline = p->lex.lastline = p->lex.nextline = 0;
if (n || p->error_p) {
VALUE mesg = p->error_buffer;
if (!mesg) {
mesg = rb_class_new_instance(0, 0, rb_eSyntaxError);
}
- rb_set_errinfo(mesg);
- return FALSE;
+ if (!p->error_tolerant) {
+ rb_set_errinfo(mesg);
+ return FALSE;
+ }
}
tree = p->eval_tree;
if (!tree) {
@@ -6286,6 +6813,7 @@ yycompile0(VALUE arg)
}
else {
VALUE opt = p->compile_option;
+ VALUE tokens = p->tokens;
NODE *prelude;
NODE *body = parser_append_options(p, tree->nd_body);
if (!opt) opt = rb_obj_hide(rb_ident_hash_new());
@@ -6293,6 +6821,10 @@ yycompile0(VALUE arg)
prelude = block_append(p, p->eval_tree_begin, body);
tree->nd_body = prelude;
RB_OBJ_WRITE(p->ast, &p->ast->body.compile_option, opt);
+ if (p->keep_tokens) {
+ rb_obj_freeze(tokens);
+ rb_ast_set_tokens(p->ast, tokens);
+ }
}
p->ast->body.root = tree;
if (!p->ast->body.script_lines) p->ast->body.script_lines = INT2FIX(p->line_count);
@@ -6313,11 +6845,17 @@ yycompile(VALUE vparser, struct parser_params *p, VALUE fname, int line)
}
p->ruby_sourceline = line - 1;
+ p->lvtbl = NULL;
+
p->ast = ast = rb_ast_new();
rb_suppress_tracing(yycompile0, (VALUE)p);
p->ast = 0;
RB_GC_GUARD(vparser); /* prohibit tail call optimization */
+ while (p->lvtbl) {
+ local_pop(p);
+ }
+
return ast;
}
#endif /* !RIPPER */
@@ -6358,12 +6896,7 @@ lex_getline(struct parser_params *p)
VALUE line = (*p->lex.gets)(p, p->lex.input);
if (NIL_P(line)) return line;
must_be_ascii_compatible(line);
-#ifndef RIPPER
- if (p->debug_lines) {
- rb_enc_associate(line, p->enc);
- rb_ary_push(p->debug_lines, line);
- }
-#endif
+ if (RB_OBJ_FROZEN(line)) line = rb_str_dup(line); // needed for RubyVM::AST.of because script_lines in iseq is deep-frozen
p->line_count++;
return line;
}
@@ -6472,9 +7005,9 @@ parser_str_new(const char *ptr, long len, rb_encoding *enc, int func, rb_encodin
str = rb_enc_str_new(ptr, len, enc);
if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
- if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
+ if (is_ascii_string(str)) {
}
- else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
+ else if (rb_is_usascii_enc(enc0) && enc != rb_utf8_encoding()) {
rb_enc_associate(str, rb_ascii8bit_encoding());
}
}
@@ -6482,35 +7015,34 @@ parser_str_new(const char *ptr, long len, rb_encoding *enc, int func, rb_encodin
return str;
}
-#define lex_goto_eol(p) ((p)->lex.pcur = (p)->lex.pend)
-#define lex_eol_p(p) ((p)->lex.pcur >= (p)->lex.pend)
-#define lex_eol_n_p(p,n) ((p)->lex.pcur+(n) >= (p)->lex.pend)
#define peek(p,c) peek_n(p, (c), 0)
#define peek_n(p,c,n) (!lex_eol_n_p(p, n) && (c) == (unsigned char)(p)->lex.pcur[n])
#define peekc(p) peekc_n(p, 0)
#define peekc_n(p,n) (lex_eol_n_p(p, n) ? -1 : (unsigned char)(p)->lex.pcur[n])
-#ifdef RIPPER
static void
-add_delayed_token(struct parser_params *p, const char *tok, const char *end)
+add_delayed_token(struct parser_params *p, const char *tok, const char *end, int line)
{
+#ifndef RIPPER
+ debug_token_line(p, "add_delayed_token", line);
+#endif
+
if (tok < end) {
if (!has_delayed_token(p)) {
p->delayed.token = rb_str_buf_new(end - tok);
rb_enc_associate(p->delayed.token, p->enc);
- p->delayed.line = p->ruby_sourceline;
- p->delayed.col = rb_long2int(tok - p->lex.pbeg);
+ p->delayed.beg_line = p->ruby_sourceline;
+ p->delayed.beg_col = rb_long2int(tok - p->lex.pbeg);
}
rb_str_buf_cat(p->delayed.token, tok, end - tok);
+ p->delayed.end_line = p->ruby_sourceline;
+ p->delayed.end_col = rb_long2int(end - p->lex.pbeg);
p->lex.ptok = end;
}
}
-#else
-#define add_delayed_token(p, tok, end) ((void)(tok), (void)(end))
-#endif
static int
-nextline(struct parser_params *p)
+nextline(struct parser_params *p, int set_encoding)
{
VALUE v = p->lex.nextline;
p->lex.nextline = 0;
@@ -6528,13 +7060,19 @@ nextline(struct parser_params *p)
lex_goto_eol(p);
return -1;
}
+#ifndef RIPPER
+ if (p->debug_lines) {
+ if (set_encoding) rb_enc_associate(v, p->enc);
+ rb_ary_push(p->debug_lines, v);
+ }
+#endif
p->cr_seen = FALSE;
}
else if (NIL_P(v)) {
/* after here-document without terminator */
goto end_of_input;
}
- add_delayed_token(p, p->lex.ptok, p->lex.pend);
+ add_delayed_token(p, p->lex.ptok, p->lex.pend, __LINE__);
if (p->heredoc_end > 0) {
p->ruby_sourceline = p->heredoc_end;
p->heredoc_end = 0;
@@ -6543,7 +7081,6 @@ nextline(struct parser_params *p)
p->lex.pbeg = p->lex.pcur = RSTRING_PTR(v);
p->lex.pend = p->lex.pcur + RSTRING_LEN(v);
token_flush(p);
- p->lex.prevline = p->lex.lastline;
p->lex.lastline = v;
return 0;
}
@@ -6559,12 +7096,12 @@ parser_cr(struct parser_params *p, int c)
}
static inline int
-nextc(struct parser_params *p)
+nextc0(struct parser_params *p, int set_encoding)
{
int c;
if (UNLIKELY((p->lex.pcur == p->lex.pend) || p->eofp || RTEST(p->lex.nextline))) {
- if (nextline(p)) return -1;
+ if (nextline(p, set_encoding)) return -1;
}
c = (unsigned char)*p->lex.pcur++;
if (UNLIKELY(c == '\r')) {
@@ -6573,6 +7110,7 @@ nextc(struct parser_params *p)
return c;
}
+#define nextc(p) nextc0(p, TRUE)
static void
pushback(struct parser_params *p, int c)
@@ -6695,19 +7233,25 @@ tokadd_codepoint(struct parser_params *p, rb_encoding **encp,
{
size_t numlen;
int codepoint = scan_hex(p->lex.pcur, wide ? p->lex.pend - p->lex.pcur : 4, &numlen);
- literal_flush(p, p->lex.pcur);
p->lex.pcur += numlen;
- if (wide ? (numlen == 0 || numlen > 6) : (numlen < 4)) {
- yyerror0("invalid Unicode escape");
- return wide && numlen > 0;
- }
- if (codepoint > 0x10ffff) {
- yyerror0("invalid Unicode codepoint (too large)");
- return wide;
- }
- if ((codepoint & 0xfffff800) == 0xd800) {
- yyerror0("invalid Unicode codepoint");
- return wide;
+ if (p->lex.strterm == NULL ||
+ (p->lex.strterm->flags & STRTERM_HEREDOC) ||
+ (p->lex.strterm->u.literal.u1.func != str_regexp)) {
+ if (wide ? (numlen == 0 || numlen > 6) : (numlen < 4)) {
+ literal_flush(p, p->lex.pcur);
+ yyerror0("invalid Unicode escape");
+ return wide && numlen > 0;
+ }
+ if (codepoint > 0x10ffff) {
+ literal_flush(p, p->lex.pcur);
+ yyerror0("invalid Unicode codepoint (too large)");
+ return wide;
+ }
+ if ((codepoint & 0xfffff800) == 0xd800) {
+ literal_flush(p, p->lex.pcur);
+ yyerror0("invalid Unicode codepoint");
+ return wide;
+ }
}
if (regexp_literal) {
tokcopy(p, (int)numlen);
@@ -6729,6 +7273,18 @@ tokadd_codepoint(struct parser_params *p, rb_encoding **encp,
return TRUE;
}
+static int tokadd_mbchar(struct parser_params *p, int c);
+
+static int
+tokskip_mbchar(struct parser_params *p)
+{
+ int len = parser_precise_mbclen(p, p->lex.pcur-1);
+ if (len > 0) {
+ p->lex.pcur += len - 1;
+ }
+ return len;
+}
+
/* return value is for ?\u3042 */
static void
tokadd_utf8(struct parser_params *p, rb_encoding **encp,
@@ -6746,44 +7302,71 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp,
if (regexp_literal) { tokadd(p, '\\'); tokadd(p, 'u'); }
if (peek(p, open_brace)) { /* handle \u{...} form */
- const char *second = NULL;
- int c, last = nextc(p);
- if (p->lex.pcur >= p->lex.pend) goto unterminated;
- while (ISSPACE(c = *p->lex.pcur) && ++p->lex.pcur < p->lex.pend);
- while (c != close_brace) {
- if (c == term) goto unterminated;
- if (second == multiple_codepoints)
- second = p->lex.pcur;
- if (regexp_literal) tokadd(p, last);
- if (!tokadd_codepoint(p, encp, regexp_literal, TRUE)) {
- break;
- }
- while (ISSPACE(c = *p->lex.pcur)) {
- if (++p->lex.pcur >= p->lex.pend) goto unterminated;
- last = c;
- }
- if (term == -1 && !second)
- second = multiple_codepoints;
- }
+ if (regexp_literal && p->lex.strterm->u.literal.u1.func == str_regexp) {
+ /*
+ * Skip parsing validation code and copy bytes as-is until term or
+ * closing brace, in order to correctly handle extended regexps where
+ * invalid unicode escapes are allowed in comments. The regexp parser
+ * does its own validation and will catch any issues.
+ */
+ tokadd(p, open_brace);
+ while (++p->lex.pcur < p->lex.pend) {
+ int c = peekc(p);
+ if (c == close_brace) {
+ tokadd(p, c);
+ ++p->lex.pcur;
+ break;
+ }
+ else if (c == term) {
+ break;
+ }
+ if (c == '\\' && p->lex.pcur + 1 < p->lex.pend) {
+ tokadd(p, c);
+ c = *++p->lex.pcur;
+ }
+ tokadd_mbchar(p, c);
+ }
+ }
+ else {
+ const char *second = NULL;
+ int c, last = nextc(p);
+ if (p->lex.pcur >= p->lex.pend) goto unterminated;
+ while (ISSPACE(c = *p->lex.pcur) && ++p->lex.pcur < p->lex.pend);
+ while (c != close_brace) {
+ if (c == term) goto unterminated;
+ if (second == multiple_codepoints)
+ second = p->lex.pcur;
+ if (regexp_literal) tokadd(p, last);
+ if (!tokadd_codepoint(p, encp, regexp_literal, TRUE)) {
+ break;
+ }
+ while (ISSPACE(c = *p->lex.pcur)) {
+ if (++p->lex.pcur >= p->lex.pend) goto unterminated;
+ last = c;
+ }
+ if (term == -1 && !second)
+ second = multiple_codepoints;
+ }
- if (c != close_brace) {
- unterminated:
- token_flush(p);
- yyerror0("unterminated Unicode escape");
- return;
- }
- if (second && second != multiple_codepoints) {
- const char *pcur = p->lex.pcur;
- p->lex.pcur = second;
- dispatch_scan_event(p, tSTRING_CONTENT);
- token_flush(p);
- p->lex.pcur = pcur;
- yyerror0(multiple_codepoints);
- token_flush(p);
- }
+ if (c != close_brace) {
+ unterminated:
+ token_flush(p);
+ yyerror0("unterminated Unicode escape");
+ return;
+ }
+ if (second && second != multiple_codepoints) {
+ const char *pcur = p->lex.pcur;
+ p->lex.pcur = second;
+ dispatch_scan_event(p, tSTRING_CONTENT);
+ token_flush(p);
+ p->lex.pcur = pcur;
+ yyerror0(multiple_codepoints);
+ token_flush(p);
+ }
- if (regexp_literal) tokadd(p, close_brace);
- nextc(p);
+ if (regexp_literal) tokadd(p, close_brace);
+ nextc(p);
+ }
}
else { /* handle \uxxxx form */
if (!tokadd_codepoint(p, encp, regexp_literal, FALSE)) {
@@ -6858,7 +7441,11 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp)
}
return read_escape(p, flags|ESCAPE_META, encp) | 0x80;
}
- else if (c == -1 || !ISASCII(c)) goto eof;
+ else if (c == -1) goto eof;
+ else if (!ISASCII(c)) {
+ tokskip_mbchar(p);
+ goto eof;
+ }
else {
int c2 = escaped_control_code(c);
if (c2) {
@@ -6889,7 +7476,11 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp)
}
else if (c == '?')
return 0177;
- else if (c == -1 || !ISASCII(c)) goto eof;
+ else if (c == -1) goto eof;
+ else if (!ISASCII(c)) {
+ tokskip_mbchar(p);
+ goto eof;
+ }
else {
int c2 = escaped_control_code(c);
if (c2) {
@@ -6917,7 +7508,7 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp)
eof:
case -1:
yyerror0("Invalid escape character syntax");
- token_flush(p);
+ dispatch_scan_event(p, tSTRING_CONTENT);
return '\0';
default:
@@ -7086,6 +7677,10 @@ tokadd_string(struct parser_params *p,
{
int c;
bool erred = false;
+#ifdef RIPPER
+ const int heredoc_end = (p->heredoc_end ? p->heredoc_end + 1 : 0);
+ int top_of_line = FALSE;
+#endif
#define mixed_error(enc1, enc2) \
(void)(erred || (parser_mixed_error(p, enc1, enc2), erred = true))
@@ -7096,6 +7691,12 @@ tokadd_string(struct parser_params *p,
if (p->heredoc_indent > 0) {
parser_update_heredoc_indent(p, c);
}
+#ifdef RIPPER
+ if (top_of_line && heredoc_end == p->ruby_sourceline) {
+ pushback(p, c);
+ break;
+ }
+#endif
if (paren && c == paren) {
++*nest;
@@ -7108,14 +7709,13 @@ tokadd_string(struct parser_params *p,
--*nest;
}
else if ((func & STR_FUNC_EXPAND) && c == '#' && p->lex.pcur < p->lex.pend) {
- int c2 = *p->lex.pcur;
+ unsigned char c2 = *p->lex.pcur;
if (c2 == '$' || c2 == '@' || c2 == '{') {
pushback(p, c);
break;
}
}
else if (c == '\\') {
- literal_flush(p, p->lex.pcur - 1);
c = nextc(p);
switch (c) {
case '\n':
@@ -7222,6 +7822,9 @@ tokadd_string(struct parser_params *p,
}
}
tokadd(p, c);
+#ifdef RIPPER
+ top_of_line = (c == '\n');
+#endif
}
terminate:
if (*enc) *encp = *enc;
@@ -7260,7 +7863,21 @@ flush_string_content(struct parser_params *p, rb_encoding *enc)
yylval.val = content;
}
#else
-#define flush_string_content(p, enc) ((void)(enc))
+static void
+flush_string_content(struct parser_params *p, rb_encoding *enc)
+{
+ if (has_delayed_token(p)) {
+ ptrdiff_t len = p->lex.pcur - p->lex.ptok;
+ if (len > 0) {
+ rb_enc_str_buf_cat(p->delayed.token, p->lex.ptok, len, enc);
+ p->delayed.end_line = p->ruby_sourceline;
+ p->delayed.end_col = rb_long2int(p->lex.pcur - p->lex.pbeg);
+ }
+ dispatch_delayed_token(p, tSTRING_CONTENT);
+ p->lex.ptok = p->lex.pcur;
+ }
+ dispatch_scan_event(p, tSTRING_CONTENT);
+}
#endif
RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];
@@ -7342,7 +7959,7 @@ parser_string_term(struct parser_params *p, int func)
}
if ((func & STR_FUNC_LABEL) && IS_LABEL_SUFFIX(0)) {
nextc(p);
- SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
+ SET_LEX_STATE(EXPR_ARG|EXPR_LABELED);
return tLABEL_END;
}
SET_LEX_STATE(EXPR_END);
@@ -7379,14 +7996,14 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote)
if (func & STR_FUNC_QWORDS) {
quote->u1.func |= STR_FUNC_TERM;
pushback(p, c); /* dispatch the term at tSTRING_END */
- add_delayed_token(p, p->lex.ptok, p->lex.pcur);
+ add_delayed_token(p, p->lex.ptok, p->lex.pcur, __LINE__);
return ' ';
}
return parser_string_term(p, func);
}
if (space) {
pushback(p, c);
- add_delayed_token(p, p->lex.ptok, p->lex.pcur);
+ add_delayed_token(p, p->lex.ptok, p->lex.pcur, __LINE__);
return ' ';
}
newtok(p);
@@ -7469,7 +8086,7 @@ heredoc_identifier(struct parser_params *p)
len = 0;
while ((c = nextc(p)) != term) {
if (c == -1 || c == '\r' || c == '\n') {
- yyerror(NULL, p, "unterminated here document identifier");
+ yyerror0("unterminated here document identifier");
return -1;
}
}
@@ -7495,7 +8112,7 @@ heredoc_identifier(struct parser_params *p)
len = p->lex.pcur - (p->lex.pbeg + offset) - quote;
if ((unsigned long)len >= HERETERM_LENGTH_MAX)
- yyerror(NULL, p, "too long here document identifier");
+ yyerror0("too long here document identifier");
dispatch_scan_event(p, tHEREDOC_BEG);
lex_goto_eol(p);
@@ -7576,7 +8193,7 @@ heredoc_dedent(struct parser_params *p, NODE *root)
if (!root) return root;
prev_node = node = str_node = root;
- if (nd_type(root) == NODE_LIST) str_node = root->nd_head;
+ if (nd_type_p(root, NODE_LIST)) str_node = root->nd_head;
while (str_node) {
VALUE lit = str_node->nd_lit;
@@ -7593,7 +8210,7 @@ heredoc_dedent(struct parser_params *p, NODE *root)
NODE *end = node->nd_end;
node = prev_node->nd_next = node->nd_next;
if (!node) {
- if (nd_type(prev_node) == NODE_DSTR)
+ if (nd_type_p(prev_node, NODE_DSTR))
nd_set_type(prev_node, NODE_STR);
break;
}
@@ -7604,7 +8221,7 @@ heredoc_dedent(struct parser_params *p, NODE *root)
str_node = 0;
while ((node = (prev_node = node)->nd_next) != 0) {
next_str:
- if (nd_type(node) != NODE_LIST) break;
+ if (!nd_type_p(node, NODE_LIST)) break;
if ((str_node = node->nd_head) != 0) {
enum node_type type = nd_type(str_node);
if (type == NODE_STR || type == NODE_DSTR) break;
@@ -7746,12 +8363,29 @@ dispatch_heredoc_end(struct parser_params *p)
dispatch_delayed_token(p, tSTRING_CONTENT);
str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok);
ripper_dispatch1(p, ripper_token2eventid(tHEREDOC_END), str);
+ RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*p->yylloc);
lex_goto_eol(p);
token_flush(p);
}
#else
-#define dispatch_heredoc_end(p) ((void)0)
+#define dispatch_heredoc_end(p) parser_dispatch_heredoc_end(p, __LINE__)
+static void
+parser_dispatch_heredoc_end(struct parser_params *p, int line)
+{
+ if (has_delayed_token(p))
+ dispatch_delayed_token(p, tSTRING_CONTENT);
+
+ if (p->keep_tokens) {
+ VALUE str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok);
+ RUBY_SET_YYLLOC_OF_HEREDOC_END(*p->yylloc);
+ parser_append_tokens(p, str, tHEREDOC_END, line);
+ }
+
+ RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*p->yylloc);
+ lex_goto_eol(p);
+ token_flush(p);
+}
#endif
static enum yytokentype
@@ -7781,7 +8415,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
int cr = ENC_CODERANGE_UNKNOWN;
rb_str_coderange_scan_restartable(p->lex.ptok, p->lex.pcur, enc, &cr);
if (cr != ENC_CODERANGE_7BIT &&
- p->enc == rb_usascii_encoding() &&
+ rb_is_usascii_enc(p->enc) &&
enc != rb_utf8_encoding()) {
enc = rb_ascii8bit_encoding();
}
@@ -8109,7 +8743,7 @@ parser_set_compile_option_flag(struct parser_params *p, const char *name, const
if (!p->compile_option)
p->compile_option = rb_obj_hide(rb_ident_hash_new());
rb_hash_aset(p->compile_option, ID2SYM(rb_intern(name)),
- (b ? Qtrue : Qfalse));
+ RBOOL(b));
}
static void
@@ -8359,7 +8993,7 @@ set_file_encoding(struct parser_params *p, const char *str, const char *send)
static void
parser_prepare(struct parser_params *p)
{
- int c = nextc(p);
+ int c = nextc0(p, FALSE);
p->token_info_enabled = !compile_for_eval && RTEST(ruby_verbose);
switch (c) {
case '#':
@@ -8371,6 +9005,11 @@ parser_prepare(struct parser_params *p)
(unsigned char)p->lex.pcur[1] == 0xbf) {
p->enc = rb_utf8_encoding();
p->lex.pcur += 2;
+#ifndef RIPPER
+ if (p->debug_lines) {
+ rb_enc_associate(p->lex.lastline, p->enc);
+ }
+#endif
p->lex.pbeg = p->lex.pcur;
return;
}
@@ -8705,7 +9344,7 @@ parse_qmark(struct parser_params *p, int space_seen)
enc = rb_utf8_encoding();
tokadd_utf8(p, &enc, -1, 0, 0);
}
- else if (!lex_eol_p(p) && !(c = *p->lex.pcur, ISASCII(c))) {
+ else if (!ISASCII(c = peekc(p))) {
nextc(p);
if (tokadd_mbchar(p, c) == -1) return 0;
}
@@ -9056,6 +9695,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
int mb = ENC_CODERANGE_7BIT;
const enum lex_state_e last_state = p->lex.state;
ID ident;
+ int enforce_keyword_end = 0;
do {
if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
@@ -9085,7 +9725,34 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
return tLABEL;
}
}
- if (mb == ENC_CODERANGE_7BIT && !IS_lex_state(EXPR_DOT)) {
+
+#ifndef RIPPER
+ if (!NIL_P(peek_end_expect_token_locations(p))) {
+ VALUE end_loc;
+ int lineno, column;
+ int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
+
+ end_loc = peek_end_expect_token_locations(p);
+ lineno = NUM2INT(rb_ary_entry(end_loc, 0));
+ column = NUM2INT(rb_ary_entry(end_loc, 1));
+
+ if (p->debug) {
+ rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n",
+ p->ruby_sourceline, beg_pos, lineno, column);
+ }
+
+ if ((p->ruby_sourceline > lineno) && (beg_pos <= column)) {
+ const struct kwtable *kw;
+
+ if ((IS_lex_state(EXPR_DOT)) && (kw = rb_reserved_word(tok(p), toklen(p))) && (kw && kw->id[0] == keyword_end)) {
+ if (p->debug) rb_parser_printf(p, "enforce_keyword_end is enabled\n");
+ enforce_keyword_end = 1;
+ }
+ }
+ }
+#endif
+
+ if (mb == ENC_CODERANGE_7BIT && (!IS_lex_state(EXPR_DOT) || enforce_keyword_end)) {
const struct kwtable *kw;
/* See if it is a reserved word. */
@@ -9111,7 +9778,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
return keyword_do_block;
return keyword_do;
}
- if (IS_lex_state_for(state, (EXPR_BEG | EXPR_LABELED)))
+ if (IS_lex_state_for(state, (EXPR_BEG | EXPR_LABELED | EXPR_CLASS)))
return kw->id[0];
else {
if (kw->id[0] != kw->id[1])
@@ -9139,13 +9806,23 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
ident = tokenize_ident(p, last_state);
if (result == tCONSTANT && is_local_id(ident)) result = tIDENTIFIER;
if (!IS_lex_state_for(last_state, EXPR_DOT|EXPR_FNAME) &&
- (result == tIDENTIFIER) && /* not EXPR_FNAME, not attrasgn */
- lvar_defined(p, ident)) {
- SET_LEX_STATE(EXPR_END|EXPR_LABEL);
+ (result == tIDENTIFIER) && /* not EXPR_FNAME, not attrasgn */
+ (lvar_defined(p, ident) || NUMPARAM_ID_P(ident))) {
+ SET_LEX_STATE(EXPR_END|EXPR_LABEL);
}
return result;
}
+static void
+warn_cr(struct parser_params *p)
+{
+ 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");
+ }
+}
+
static enum yytokentype
parser_yylex(struct parser_params *p)
{
@@ -9159,6 +9836,7 @@ parser_yylex(struct parser_params *p)
if (p->lex.strterm) {
if (p->lex.strterm->flags & STRTERM_HEREDOC) {
+ token_flush(p);
return here_document(p, &p->lex.strterm->u.heredoc);
}
else {
@@ -9169,33 +9847,41 @@ parser_yylex(struct parser_params *p)
cmd_state = p->command_start;
p->command_start = FALSE;
p->token_seen = TRUE;
- retry:
- last_state = p->lex.state;
#ifndef RIPPER
token_flush(p);
#endif
+ retry:
+ last_state = p->lex.state;
switch (c = nextc(p)) {
case '\0': /* NUL */
case '\004': /* ^D */
case '\032': /* ^Z */
case -1: /* end of script. */
+ p->eofp = 1;
+#ifndef RIPPER
+ if (!NIL_P(p->end_expect_token_locations) && RARRAY_LEN(p->end_expect_token_locations) > 0) {
+ pop_end_expect_token_locations(p);
+ RUBY_SET_YYLLOC_OF_DUMMY_END(*p->yylloc);
+ return tDUMNY_END;
+ }
+#endif
+ /* Set location for end-of-input because dispatch_scan_event is not called. */
+ RUBY_SET_YYLLOC(*p->yylloc);
return 0;
/* white spaces */
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");
- }
+ warn_cr(p);
/* fall through */
case ' ': case '\t': case '\f':
case '\13': /* '\v' */
space_seen = 1;
-#ifdef RIPPER
while ((c = nextc(p))) {
switch (c) {
- case ' ': case '\t': case '\f': case '\r':
+ case '\r':
+ warn_cr(p);
+ /* fall through */
+ case ' ': case '\t': case '\f':
case '\13': /* '\v' */
break;
default:
@@ -9205,6 +9891,8 @@ parser_yylex(struct parser_params *p)
outofloop:
pushback(p, c);
dispatch_scan_event(p, tSP);
+#ifndef RIPPER
+ token_flush(p);
#endif
goto retry;
@@ -9242,7 +9930,10 @@ parser_yylex(struct parser_params *p)
break;
case '#':
pushback(p, c);
- if (space_seen) dispatch_scan_event(p, tSP);
+ if (space_seen) {
+ dispatch_scan_event(p, tSP);
+ token_flush(p);
+ }
goto retry;
case '&':
case '.': {
@@ -9257,18 +9948,10 @@ parser_yylex(struct parser_params *p)
p->ruby_sourceline--;
p->lex.nextline = p->lex.lastline;
case -1: /* EOF no decrement*/
-#ifndef RIPPER
- if (p->lex.prevline && !p->eofp) p->lex.lastline = p->lex.prevline;
- p->lex.pbeg = RSTRING_PTR(p->lex.lastline);
- p->lex.pend = p->lex.pcur = p->lex.pbeg + RSTRING_LEN(p->lex.lastline);
- pushback(p, 1); /* always pushback */
- p->lex.ptok = p->lex.pcur;
-#else
lex_goto_eol(p);
if (c != -1) {
p->lex.ptok = p->lex.pcur;
}
-#endif
goto normal_newline;
}
}
@@ -9595,6 +10278,10 @@ parser_yylex(struct parser_params *p)
SET_LEX_STATE(EXPR_BEG);
if ((c = nextc(p)) == '.') {
if ((c = nextc(p)) == '.') {
+ if (p->ctxt.in_argdef) {
+ SET_LEX_STATE(EXPR_ENDARG);
+ return tBDOT3;
+ }
if (p->lex.paren_nest == 0 && looking_at_eol_p(p)) {
rb_warn0("... at EOL, should be parenthesized?");
}
@@ -9862,12 +10549,9 @@ yylex(YYSTYPE *lval, YYLTYPE *yylloc, struct parser_params *p)
p->lval = lval;
lval->val = Qundef;
- t = parser_yylex(p);
+ p->yylloc = yylloc;
- if (p->lex.strterm && (p->lex.strterm->flags & STRTERM_HEREDOC))
- RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*yylloc);
- else
- RUBY_SET_YYLLOC(*yylloc);
+ t = parser_yylex(p);
if (has_delayed_token(p))
dispatch_delayed_token(p, t);
@@ -9880,11 +10564,18 @@ yylex(YYSTYPE *lval, YYLTYPE *yylloc, struct parser_params *p)
#define LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
static NODE*
-node_newnode(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2, const rb_code_location_t *loc)
+node_new_temporal(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = rb_ast_newnode(p->ast, type);
rb_node_init(n, type, a0, a1, a2);
+ return n;
+}
+
+static NODE*
+node_newnode(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2, const rb_code_location_t *loc)
+{
+ NODE *n = node_new_temporal(p, type, a0, a1, a2);
nd_set_loc(n, loc);
nd_set_node_id(n, parser_get_node_id(p));
@@ -9985,7 +10676,7 @@ block_append(struct parser_params *p, NODE *head, NODE *tail)
break;
}
- if (nd_type(tail) != NODE_BLOCK) {
+ if (!nd_type_p(tail, NODE_BLOCK)) {
tail = NEW_BLOCK(tail, &tail->nd_loc);
tail->nd_end = tail;
}
@@ -10067,7 +10758,7 @@ 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;
+ if (!head || !nd_type_p(head, NODE_STR)) return Qfalse;
}
const VALUE lit = head->nd_lit;
ASSUME(lit != Qfalse);
@@ -10166,7 +10857,7 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l
static NODE *
evstr2dstr(struct parser_params *p, NODE *node)
{
- if (nd_type(node) == NODE_EVSTR) {
+ if (nd_type_p(node, NODE_EVSTR)) {
node = new_dstr(p, node, &node->nd_loc);
}
return node;
@@ -10241,7 +10932,7 @@ new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *a
return ret;
}
-#define nd_once_body(node) (nd_type(node) == NODE_ONCE ? (node)->nd_body : node)
+#define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? (node)->nd_body : node)
static NODE*
match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_loc, const YYLTYPE *loc)
{
@@ -10420,13 +11111,7 @@ static NODE *
kwd_append(NODE *kwlist, NODE *kw)
{
if (kwlist) {
- NODE *kws = kwlist;
- kws->nd_loc.end_pos = kw->nd_loc.end_pos;
- while (kws->nd_next) {
- kws = kws->nd_next;
- kws->nd_loc.end_pos = kw->nd_loc.end_pos;
- }
- kws->nd_next = kw;
+ opt_arg_append(kwlist, kw);
}
return kwlist;
}
@@ -10562,8 +11247,8 @@ check_literal_when(struct parser_params *p, NODE *arg, const YYLTYPE *loc)
if (!arg || !p->case_labels) return;
lit = rb_node_case_when_optimizable_literal(arg);
- if (lit == Qundef) return;
- if (nd_type(arg) == NODE_STR) {
+ if (UNDEF_P(lit)) return;
+ if (nd_type_p(arg, NODE_STR)) {
RB_OBJ_WRITTEN(p->ast, Qnil, arg->nd_lit = lit);
}
@@ -10622,6 +11307,14 @@ new_regexp(struct parser_params *p, VALUE re, VALUE opt, const YYLTYPE *loc)
}
#endif /* !RIPPER */
+static inline enum lex_state_e
+parser_set_lex_state(struct parser_params *p, enum lex_state_e ls, int line)
+{
+ if (p->debug) {
+ ls = rb_parser_trace_lex_state(p, p->lex.state, ls, line);
+ }
+ return p->lex.state = ls;
+}
#ifndef RIPPER
static const char rb_parser_lex_state_names[][8] = {
@@ -10718,7 +11411,7 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...)
va_start(ap, fmt);
rb_str_vcatf(mesg, fmt, ap);
va_end(ap);
- parser_yyerror(p, NULL, RSTRING_PTR(mesg));
+ yyerror0(RSTRING_PTR(mesg));
RB_GC_GUARD(mesg);
mesg = rb_str_new(0, 0);
@@ -10735,6 +11428,16 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...)
p->debug = TRUE;
}
+static YYLTYPE *
+rb_parser_set_pos(YYLTYPE *yylloc, int sourceline, int beg_pos, int end_pos)
+{
+ yylloc->beg_pos.lineno = sourceline;
+ yylloc->beg_pos.column = beg_pos;
+ yylloc->end_pos.lineno = sourceline;
+ yylloc->end_pos.column = end_pos;
+ return yylloc;
+}
+
YYLTYPE *
rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_heredoc_t *here, YYLTYPE *yylloc)
{
@@ -10743,76 +11446,55 @@ rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_
- (rb_strlen_lit("<<-") - !(here->func & STR_FUNC_INDENT));
int end_pos = (int)here->offset + here->length + here->quote;
- yylloc->beg_pos.lineno = sourceline;
- yylloc->beg_pos.column = beg_pos;
- yylloc->end_pos.lineno = sourceline;
- yylloc->end_pos.column = end_pos;
- return yylloc;
+ return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos);
}
YYLTYPE *
-rb_parser_set_location_of_none(struct parser_params *p, YYLTYPE *yylloc)
+rb_parser_set_location_of_delayed_token(struct parser_params *p, YYLTYPE *yylloc)
{
- yylloc->beg_pos.lineno = p->ruby_sourceline;
- yylloc->beg_pos.column = (int)(p->lex.ptok - p->lex.pbeg);
- yylloc->end_pos.lineno = p->ruby_sourceline;
- yylloc->end_pos.column = (int)(p->lex.ptok - p->lex.pbeg);
+ yylloc->beg_pos.lineno = p->delayed.beg_line;
+ yylloc->beg_pos.column = p->delayed.beg_col;
+ yylloc->end_pos.lineno = p->delayed.end_line;
+ yylloc->end_pos.column = p->delayed.end_col;
+
return yylloc;
}
YYLTYPE *
-rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc)
+rb_parser_set_location_of_heredoc_end(struct parser_params *p, YYLTYPE *yylloc)
{
- yylloc->beg_pos.lineno = p->ruby_sourceline;
- yylloc->beg_pos.column = (int)(p->lex.ptok - p->lex.pbeg);
- yylloc->end_pos.lineno = p->ruby_sourceline;
- yylloc->end_pos.column = (int)(p->lex.pcur - p->lex.pbeg);
+ int sourceline = p->ruby_sourceline;
+ int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
+ int end_pos = (int)(p->lex.pend - p->lex.pbeg);
+ return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos);
+}
+
+YYLTYPE *
+rb_parser_set_location_of_dummy_end(struct parser_params *p, YYLTYPE *yylloc)
+{
+ yylloc->end_pos = yylloc->beg_pos;
+
return yylloc;
}
-#endif /* !RIPPER */
-static void
-parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp)
+YYLTYPE *
+rb_parser_set_location_of_none(struct parser_params *p, YYLTYPE *yylloc)
{
- VALUE v;
+ int sourceline = p->ruby_sourceline;
+ int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
+ int end_pos = (int)(p->lex.ptok - p->lex.pbeg);
+ return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos);
+}
- switch (type) {
- case tIDENTIFIER: case tFID: case tGVAR: case tIVAR:
- case tCONSTANT: case tCVAR: case tLABEL: case tOP_ASGN:
-#ifndef RIPPER
- v = rb_id2str(valp->id);
-#else
- v = valp->node->nd_rval;
-#endif
- rb_parser_printf(p, "%"PRIsVALUE, v);
- break;
- case tINTEGER: case tFLOAT: case tRATIONAL: case tIMAGINARY:
- case tSTRING_CONTENT: case tCHAR:
-#ifndef RIPPER
- v = valp->node->nd_lit;
-#else
- v = valp->val;
-#endif
- rb_parser_printf(p, "%+"PRIsVALUE, v);
- break;
- case tNTH_REF:
-#ifndef RIPPER
- rb_parser_printf(p, "$%ld", valp->node->nd_nth);
-#else
- rb_parser_printf(p, "%"PRIsVALUE, valp->val);
-#endif
- break;
- case tBACK_REF:
-#ifndef RIPPER
- rb_parser_printf(p, "$%c", (int)valp->node->nd_nth);
-#else
- rb_parser_printf(p, "%"PRIsVALUE, valp->val);
-#endif
- break;
- default:
- break;
- }
+YYLTYPE *
+rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc)
+{
+ int sourceline = p->ruby_sourceline;
+ int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
+ int end_pos = (int)(p->lex.pcur - p->lex.pbeg);
+ return rb_parser_set_pos(yylloc, sourceline, beg_pos, end_pos);
}
+#endif /* !RIPPER */
static int
assignable0(struct parser_params *p, ID id, const char **err)
@@ -10849,11 +11531,11 @@ assignable0(struct parser_params *p, ID id, const char **err)
NUMPARAM_ID_TO_IDX(id));
return -1;
}
- if (dvar_curr(p, id)) return NODE_DASGN_CURR;
+ if (dvar_curr(p, id)) return NODE_DASGN;
if (dvar_defined(p, id)) return NODE_DASGN;
if (local_id(p, id)) return NODE_LASGN;
dyna_var(p, id);
- return NODE_DASGN_CURR;
+ return NODE_DASGN;
}
else {
if (!local_id(p, id)) local_var(p, id);
@@ -10880,7 +11562,6 @@ assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc)
const char *err = 0;
int node_type = assignable0(p, id, &err);
switch (node_type) {
- case NODE_DASGN_CURR: return NEW_DASGN_CURR(id, val, loc);
case NODE_DASGN: return NEW_DASGN(id, val, loc);
case NODE_LASGN: return NEW_LASGN(id, val, loc);
case NODE_GASGN: return NEW_GASGN(id, val, loc);
@@ -10916,9 +11597,9 @@ is_private_local_id(ID name)
static int
shadowing_lvar_0(struct parser_params *p, ID name)
{
- if (is_private_local_id(name)) return 1;
if (dyna_in_block(p)) {
if (dvar_curr(p, name)) {
+ if (is_private_local_id(name)) return 1;
yyerror0("duplicated argument name");
}
else if (dvar_defined(p, name) || local_id(p, name)) {
@@ -10931,6 +11612,7 @@ shadowing_lvar_0(struct parser_params *p, ID name)
}
else {
if (local_id(p, name)) {
+ if (is_private_local_id(name)) return 1;
yyerror0("duplicated argument name");
}
}
@@ -10967,7 +11649,7 @@ aryset(struct parser_params *p, NODE *recv, NODE *idx, const YYLTYPE *loc)
static void
block_dup_check(struct parser_params *p, NODE *node1, NODE *node2)
{
- if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
+ if (node2 && node1 && nd_type_p(node1, NODE_BLOCK_PASS)) {
compile_error(p, "both block arg and actual block given");
}
}
@@ -11019,7 +11701,7 @@ arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc
nd_set_type(node1, NODE_ARGSCAT);
return node1;
case NODE_ARGSCAT:
- if (nd_type(node1->nd_body) != NODE_LIST) break;
+ if (!nd_type_p(node1->nd_body, NODE_LIST)) break;
node1->nd_body = list_append(p, node1->nd_body, node2);
node1->nd_loc.end_pos = node1->nd_body->nd_loc.end_pos;
return node1;
@@ -11039,13 +11721,13 @@ arg_concat(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc
node1->nd_head = NEW_LIST(node2, loc);
return node1;
case NODE_ARGSPUSH:
- if (nd_type(node2) != NODE_LIST) break;
+ if (!nd_type_p(node2, NODE_LIST)) break;
node1->nd_body = list_concat(NEW_LIST(node1->nd_body, loc), node2);
nd_set_type(node1, NODE_ARGSCAT);
return node1;
case NODE_ARGSCAT:
- if (nd_type(node2) != NODE_LIST ||
- nd_type(node1->nd_body) != NODE_LIST) break;
+ if (!nd_type_p(node2, NODE_LIST) ||
+ !nd_type_p(node1->nd_body, NODE_LIST)) break;
node1->nd_body = list_concat(node1->nd_body, node2);
return node1;
}
@@ -11066,7 +11748,7 @@ static NODE *
rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTYPE *loc)
{
NODE *n1;
- if ((nd_type(rest_arg) == NODE_LIST) && (n1 = splat_array(args)) != 0) {
+ if ((nd_type_p(rest_arg, NODE_LIST)) && (n1 = splat_array(args)) != 0) {
return list_concat(n1, rest_arg);
}
return arg_concat(p, args, rest_arg, loc);
@@ -11075,8 +11757,8 @@ rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTY
static NODE *
splat_array(NODE* node)
{
- if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
- if (nd_type(node) == NODE_LIST) return node;
+ if (nd_type_p(node, NODE_SPLAT)) node = node->nd_head;
+ if (nd_type_p(node, NODE_LIST)) return node;
return 0;
}
@@ -11092,7 +11774,6 @@ mark_lvar_used(struct parser_params *p, NODE *rhs)
}
break;
case NODE_DASGN:
- case NODE_DASGN_CURR:
if (dvar_defined_ref(p, rhs->nd_vid, &vidp)) {
if (vidp) *vidp |= LVAR_USED;
}
@@ -11111,7 +11792,7 @@ static NODE *
const_decl_path(struct parser_params *p, NODE **dest)
{
NODE *n = *dest;
- if (nd_type(n) != NODE_CALL) {
+ if (!nd_type_p(n, NODE_CALL)) {
const YYLTYPE *loc = &n->nd_loc;
VALUE path;
if (n->nd_vid) {
@@ -11120,14 +11801,14 @@ const_decl_path(struct parser_params *p, NODE **dest)
else {
n = n->nd_else;
path = rb_ary_new();
- for (; n && nd_type(n) == NODE_COLON2; n = n->nd_head) {
+ for (; n && nd_type_p(n, NODE_COLON2); n = n->nd_head) {
rb_ary_push(path, rb_id2str(n->nd_mid));
}
- if (n && nd_type(n) == NODE_CONST) {
+ if (n && nd_type_p(n, NODE_CONST)) {
// Const::Name
rb_ary_push(path, rb_id2str(n->nd_vid));
}
- else if (n && nd_type(n) == NODE_COLON3) {
+ else if (n && nd_type_p(n, NODE_COLON3)) {
// ::Const::Name
rb_ary_push(path, rb_str_new(0, 0));
}
@@ -11247,7 +11928,7 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
}
if (RTEST(lit)) {
VALUE e = shareable_literal_value(elt);
- if (e != Qundef) {
+ if (!UNDEF_P(e)) {
rb_ary_push(lit, e);
}
else {
@@ -11287,7 +11968,7 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
if (RTEST(lit)) {
VALUE k = shareable_literal_value(key);
VALUE v = shareable_literal_value(val);
- if (k != Qundef && v != Qundef) {
+ if (!UNDEF_P(k) && !UNDEF_P(v)) {
rb_hash_aset(lit, k, v);
}
else {
@@ -11367,7 +12048,6 @@ node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ct
case NODE_IASGN:
case NODE_LASGN:
case NODE_DASGN:
- case NODE_DASGN_CURR:
case NODE_MASGN:
case NODE_CVASGN:
lhs->nd_value = rhs;
@@ -11405,7 +12085,7 @@ value_expr_check(struct parser_params *p, NODE *node)
return void_node ? void_node : node;
case NODE_CASE3:
- if (!node->nd_body || nd_type(node->nd_body) != NODE_IN) {
+ if (!node->nd_body || !nd_type_p(node->nd_body, NODE_IN)) {
compile_error(p, "unexpected node");
return NULL;
}
@@ -11447,7 +12127,6 @@ value_expr_check(struct parser_params *p, NODE *node)
case NODE_LASGN:
case NODE_DASGN:
- case NODE_DASGN_CURR:
case NODE_MASGN:
mark_lvar_used(p, node);
return NULL;
@@ -11561,7 +12240,7 @@ void_stmts(struct parser_params *p, NODE *node)
NODE *const n = node;
if (!RTEST(ruby_verbose)) return n;
if (!node) return n;
- if (nd_type(node) != NODE_BLOCK) return n;
+ if (!nd_type_p(node, NODE_BLOCK)) return n;
while (node->nd_next) {
void_expr(p, node->nd_head);
@@ -11574,7 +12253,7 @@ static NODE *
remove_begin(NODE *node)
{
NODE **n = &node, *n1 = node;
- while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) {
+ while (n1 && nd_type_p(n1, NODE_BEGIN) && n1->nd_body) {
*n = n1 = n1->nd_body;
}
return node;
@@ -11584,7 +12263,7 @@ static NODE *
remove_begin_all(NODE *node)
{
NODE **n = &node, *n1 = node;
- while (n1 && nd_type(n1) == NODE_BEGIN) {
+ while (n1 && nd_type_p(n1, NODE_BEGIN)) {
*n = n1 = n1->nd_body;
}
return node;
@@ -11683,7 +12362,6 @@ assign_in_cond(struct parser_params *p, NODE *node)
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
- case NODE_DASGN_CURR:
case NODE_GASGN:
case NODE_IASGN:
break;
@@ -11761,12 +12439,13 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l
case NODE_DOT3:
node->nd_beg = range_op(p, node->nd_beg, loc);
node->nd_end = range_op(p, node->nd_end, loc);
- if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
- else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
+ if (nd_type_p(node, NODE_DOT2)) nd_set_type(node,NODE_FLIP2);
+ else if (nd_type_p(node, NODE_DOT3)) nd_set_type(node, NODE_FLIP3);
break;
case NODE_DSYM:
- SWITCH_BY_COND_TYPE(type, warning, "string ")
+ warn_symbol:
+ SWITCH_BY_COND_TYPE(type, warning, "symbol ")
break;
case NODE_LIT:
@@ -11778,6 +12457,9 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l
node->nd_lit == Qfalse) {
/* booleans are OK, e.g., while true */
}
+ else if (SYMBOL_P(node->nd_lit)) {
+ goto warn_symbol;
+ }
else {
SWITCH_BY_COND_TYPE(type, warning, "")
}
@@ -11831,9 +12513,9 @@ logop(struct parser_params *p, ID id, NODE *left, NODE *right,
enum node_type type = id == idAND || id == idANDOP ? NODE_AND : NODE_OR;
NODE *op;
value_expr(left);
- if (left && (enum node_type)nd_type(left) == type) {
+ if (left && nd_type_p(left, type)) {
NODE *node = left, *second;
- while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
+ while ((second = node->nd_2nd) != 0 && nd_type_p(second, type)) {
node = second;
}
node->nd_2nd = NEW_NODE(type, second, right, 0, loc);
@@ -11849,7 +12531,7 @@ logop(struct parser_params *p, ID id, NODE *left, NODE *right,
static void
no_blockarg(struct parser_params *p, NODE *node)
{
- if (node && nd_type(node) == NODE_BLOCK_PASS) {
+ if (nd_type_p(node, NODE_BLOCK_PASS)) {
compile_error(p, "block argument should not be given");
}
}
@@ -11859,7 +12541,7 @@ ret_args(struct parser_params *p, NODE *node)
{
if (node) {
no_blockarg(p, node);
- if (nd_type(node) == NODE_LIST) {
+ if (nd_type_p(node, NODE_LIST)) {
if (node->nd_next == 0) {
node = node->nd_head;
}
@@ -11906,7 +12588,7 @@ negate_lit(struct parser_params *p, VALUE lit)
RCOMPLEX_SET_IMAG(lit, negate_lit(p, RCOMPLEX(lit)->imag));
break;
case T_FLOAT:
- RFLOAT(lit)->float_value = -RFLOAT_VALUE(lit);
+ lit = DBL2NUM(-RFLOAT_VALUE(lit));
break;
unknown:
default:
@@ -11949,6 +12631,14 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N
int saved_line = p->ruby_sourceline;
struct rb_args_info *args = tail->nd_ainfo;
+ if (args->forwarding) {
+ if (rest_arg) {
+ yyerror1(&tail->nd_loc, "... after rest argument");
+ return tail;
+ }
+ rest_arg = idFWD_REST;
+ }
+
args->pre_args_num = pre_args ? rb_long2int(pre_args->nd_plen) : 0;
args->pre_init = pre_args ? pre_args->nd_next : 0;
@@ -11960,7 +12650,11 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N
args->opt_args = opt_args;
- args->ruby2_keywords = rest_arg == idFWD_REST;
+#ifdef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
+ args->ruby2_keywords = args->forwarding;
+#else
+ args->ruby2_keywords = 0;
+#endif
p->ruby_sourceline = saved_line;
nd_set_loc(tail, loc);
@@ -11995,6 +12689,7 @@ new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block,
struct vtable *vtargs = p->lvtbl->args;
NODE *kwn = kw_args;
+ if (block) block = vtargs->tbl[vtargs->pos-1];
vtable_pop(vtargs, !!block + !!kw_rest_arg);
required_kw_vars = kw_vars = &vtargs->tbl[vtargs->pos];
while (kwn) {
@@ -12230,24 +12925,30 @@ remove_duplicate_keys(struct parser_params *p, NODE *hash)
{
st_table *literal_keys = st_init_table_with_size(&literal_type, hash->nd_alen / 2);
NODE *result = 0;
+ NODE *last_expr = 0;
rb_code_location_t loc = hash->nd_loc;
while (hash && hash->nd_head && hash->nd_next) {
NODE *head = hash->nd_head;
NODE *value = hash->nd_next;
NODE *next = value->nd_next;
- VALUE key = (VALUE)head;
+ st_data_t key = (st_data_t)head;
st_data_t data;
- if (nd_type(head) == NODE_LIT &&
- st_lookup(literal_keys, (key = head->nd_lit), &data)) {
+ value->nd_next = 0;
+ if (nd_type_p(head, NODE_LIT) &&
+ st_delete(literal_keys, (key = (st_data_t)head->nd_lit, &key), &data)) {
+ NODE *dup_value = ((NODE *)data)->nd_next;
rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data),
"key %+"PRIsVALUE" is duplicated and overwritten on line %d",
head->nd_lit, nd_line(head));
- head = ((NODE *)data)->nd_next;
- head->nd_head = block_append(p, head->nd_head, value->nd_head);
- }
- else {
- st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
+ if (dup_value == last_expr) {
+ value->nd_head = block_append(p, dup_value->nd_head, value->nd_head);
+ }
+ else {
+ last_expr->nd_head = block_append(p, dup_value->nd_head, last_expr->nd_head);
+ }
}
+ st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
+ last_expr = nd_type_p(head, NODE_LIT) ? value : head;
hash = next;
}
st_foreach(literal_keys, append_literal_keys, (st_data_t)&result);
@@ -12369,7 +13070,7 @@ new_ary_op_assign(struct parser_params *p, NODE *ary,
NODE *asgn;
args = make_list(args, args_loc);
- if (nd_type(args) == NODE_BLOCK_PASS) {
+ if (nd_type_p(args, NODE_BLOCK_PASS)) {
args = NEW_ARGSCAT(args, rhs, loc);
}
else {
@@ -12513,61 +13214,76 @@ local_push(struct parser_params *p, int toplevel_scope)
}
static void
+vtable_chain_free(struct parser_params *p, struct vtable *table)
+{
+ while (!DVARS_TERMINAL_P(table)) {
+ struct vtable *cur_table = table;
+ table = cur_table->prev;
+ vtable_free(cur_table);
+ }
+}
+
+static void
+local_free(struct parser_params *p, struct local_vars *local)
+{
+ vtable_chain_free(p, local->used);
+
+# if WARN_PAST_SCOPE
+ vtable_chain_free(p, local->past);
+# endif
+
+ vtable_chain_free(p, local->args);
+ vtable_chain_free(p, local->vars);
+
+ ruby_sized_xfree(local, sizeof(struct local_vars));
+}
+
+static void
local_pop(struct parser_params *p)
{
struct local_vars *local = p->lvtbl->prev;
if (p->lvtbl->used) {
- warn_unused_var(p, p->lvtbl);
- vtable_free(p->lvtbl->used);
- }
-# if WARN_PAST_SCOPE
- while (p->lvtbl->past) {
- struct vtable *past = p->lvtbl->past;
- p->lvtbl->past = past->prev;
- vtable_free(past);
+ warn_unused_var(p, p->lvtbl);
}
-# endif
- vtable_free(p->lvtbl->args);
- vtable_free(p->lvtbl->vars);
+
+ local_free(p, p->lvtbl);
+ p->lvtbl = local;
+
CMDARG_POP();
COND_POP();
- ruby_sized_xfree(p->lvtbl, sizeof(*p->lvtbl));
- p->lvtbl = local;
}
#ifndef RIPPER
-static ID*
+static rb_ast_id_table_t *
local_tbl(struct parser_params *p)
{
int cnt_args = vtable_size(p->lvtbl->args);
int cnt_vars = vtable_size(p->lvtbl->vars);
int cnt = cnt_args + cnt_vars;
int i, j;
- ID *buf;
+ rb_ast_id_table_t *tbl;
if (cnt <= 0) return 0;
- buf = ALLOC_N(ID, cnt + 2);
- MEMCPY(buf+1, p->lvtbl->args->tbl, ID, cnt_args);
+ tbl = rb_ast_new_local_table(p->ast, cnt);
+ MEMCPY(tbl->ids, p->lvtbl->args->tbl, ID, cnt_args);
/* remove IDs duplicated to warn shadowing */
- for (i = 0, j = cnt_args+1; i < cnt_vars; ++i) {
+ for (i = 0, j = cnt_args; i < cnt_vars; ++i) {
ID id = p->lvtbl->vars->tbl[i];
if (!vtable_included(p->lvtbl->args, id)) {
- buf[j++] = id;
+ tbl->ids[j++] = id;
}
}
- if (--j < cnt) {
- REALLOC_N(buf, ID, (cnt = j) + 2);
+ if (j < cnt) {
+ tbl = rb_ast_resize_latest_local_table(p->ast, j);
}
- buf[0] = cnt;
- rb_ast_add_local_table(p->ast, buf);
- return buf;
+ return tbl;
}
static NODE*
node_newnode_with_locals(struct parser_params *p, enum node_type type, VALUE a1, VALUE a2, const rb_code_location_t *loc)
{
- ID *a0;
+ rb_ast_id_table_t *a0;
NODE *n;
a0 = local_tbl(p);
@@ -12639,11 +13355,7 @@ local_id(struct parser_params *p, ID id)
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;
+ if (local_id(p, idFWD_ALL)) return TRUE;
compile_error(p, "unexpected ...");
return FALSE;
}
@@ -12652,34 +13364,28 @@ static void
add_forwarding_args(struct parser_params *p)
{
arg_var(p, idFWD_REST);
-#if idFWD_KWREST
+#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
arg_var(p, idFWD_KWREST);
#endif
arg_var(p, idFWD_BLOCK);
+ arg_var(p, idFWD_ALL);
}
#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 *rest = NEW_LVAR(idFWD_REST, loc);
+#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
NODE *kwrest = list_append(p, NEW_LIST(0, loc), NEW_LVAR(idFWD_KWREST, loc));
#endif
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);
+ NODE *args = leading ? rest_arg_append(p, leading, rest, argsloc) : NEW_SPLAT(rest, loc);
+#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
+ args = arg_append(p, args, new_hash(p, kwrest, loc), loc);
#endif
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 *
@@ -12846,21 +13552,21 @@ rb_reg_fragment_setenc(struct parser_params* p, VALUE str, int options)
int opt, idx;
rb_char_to_option_kcode(c, &opt, &idx);
if (idx != ENCODING_GET(str) &&
- rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
+ !is_ascii_string(str)) {
goto error;
}
ENCODING_SET(str, idx);
}
else if (RE_OPTION_ENCODING_NONE(options)) {
if (!ENCODING_IS_ASCII8BIT(str) &&
- rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
+ !is_ascii_string(str)) {
c = 'n';
goto error;
}
rb_enc_associate(str, rb_ascii8bit_encoding());
}
- else if (p->enc == rb_usascii_encoding()) {
- if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
+ else if (rb_is_usascii_enc(p->enc)) {
+ if (!is_ascii_string(str)) {
/* raise in re.c */
rb_enc_associate(str, rb_usascii_encoding());
}
@@ -13018,6 +13724,8 @@ parser_append_options(struct parser_params *p, NODE *node)
}
if (p->do_loop) {
+ NODE *irs = NEW_LIST(NEW_GVAR(rb_intern("$/"), LOC), LOC);
+
if (p->do_split) {
ID ifs = rb_intern("$;");
ID fields = rb_intern("$F");
@@ -13029,12 +13737,12 @@ parser_append_options(struct parser_params *p, NODE *node)
node = block_append(p, split, node);
}
if (p->do_chomp) {
- NODE *chomp = NEW_CALL(NEW_GVAR(idLASTLINE, LOC),
- rb_intern("chomp!"), 0, LOC);
- node = block_append(p, chomp, node);
+ NODE *chomp = NEW_LIT(ID2SYM(rb_intern("chomp")), LOC);
+ chomp = list_append(p, NEW_LIST(chomp, LOC), NEW_TRUE(LOC));
+ irs = list_append(p, irs, NEW_HASH(chomp, LOC));
}
- node = NEW_WHILE(NEW_VCALL(idGets, LOC), node, 1, LOC);
+ node = NEW_WHILE(NEW_FCALL(idGets, irs, LOC), node, 1, LOC);
}
return node;
@@ -13051,10 +13759,7 @@ rb_init_parse(void)
static ID
internal_id(struct parser_params *p)
{
- const ID max_id = RB_ID_SERIAL_MAX & ~0xffff;
- ID id = (ID)vtable_size(p->lvtbl->args) + (ID)vtable_size(p->lvtbl->vars);
- id = max_id - id;
- return ID_STATIC_SYM | ID_INTERNAL | (id << ID_SCOPE_SHIFT);
+ return rb_make_temporary_id(vtable_size(p->lvtbl->args) + vtable_size(p->lvtbl->vars));
}
#endif /* !RIPPER */
@@ -13066,12 +13771,15 @@ parser_initialize(struct parser_params *p)
p->ruby_sourcefile_string = Qnil;
p->lex.lpar_beg = -1; /* make lambda_beginning_p() == FALSE at first */
p->node_id = 0;
-#ifdef RIPPER
p->delayed.token = Qnil;
+#ifdef RIPPER
p->result = Qnil;
p->parsing_thread = Qnil;
#else
p->error_buffer = Qfalse;
+ p->end_expect_token_locations = Qnil;
+ p->token_id = 0;
+ p->tokens = Qnil;
#endif
p->debug_buffer = Qnil;
p->debug_output = rb_ractor_stdout();
@@ -13089,19 +13797,20 @@ parser_mark(void *ptr)
struct parser_params *p = (struct parser_params*)ptr;
rb_gc_mark(p->lex.input);
- rb_gc_mark(p->lex.prevline);
rb_gc_mark(p->lex.lastline);
rb_gc_mark(p->lex.nextline);
rb_gc_mark(p->ruby_sourcefile_string);
rb_gc_mark((VALUE)p->lex.strterm);
rb_gc_mark((VALUE)p->ast);
rb_gc_mark(p->case_labels);
+ rb_gc_mark(p->delayed.token);
#ifndef RIPPER
rb_gc_mark(p->debug_lines);
rb_gc_mark(p->compile_option);
rb_gc_mark(p->error_buffer);
+ rb_gc_mark(p->end_expect_token_locations);
+ rb_gc_mark(p->tokens);
#else
- rb_gc_mark(p->delayed.token);
rb_gc_mark(p->value);
rb_gc_mark(p->result);
rb_gc_mark(p->parsing_thread);
@@ -13122,16 +13831,17 @@ parser_free(void *ptr)
if (p->tokenbuf) {
ruby_sized_xfree(p->tokenbuf, p->toksiz);
}
+
for (local = p->lvtbl; local; local = prev) {
- if (local->vars) xfree(local->vars);
- prev = local->prev;
- xfree(local);
+ prev = local->prev;
+ local_free(p, local);
}
+
{
- token_info *ptinfo;
- while ((ptinfo = p->token_info) != 0) {
- p->token_info = ptinfo->next;
- xfree(ptinfo);
+ token_info *ptinfo;
+ while ((ptinfo = p->token_info) != 0) {
+ p->token_info = ptinfo->next;
+ xfree(ptinfo);
}
}
xfree(ptr);
@@ -13197,13 +13907,34 @@ rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main
}
void
-rb_parser_save_script_lines(VALUE vparser)
+rb_parser_keep_script_lines(VALUE vparser)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- p->save_script_lines = 1;
+ p->keep_script_lines = 1;
}
+
+void
+rb_parser_error_tolerant(VALUE vparser)
+{
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ p->error_tolerant = 1;
+ p->end_expect_token_locations = rb_ary_new();
+}
+
+void
+rb_parser_keep_tokens(VALUE vparser)
+{
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ p->keep_tokens = 1;
+ p->tokens = rb_ary_new();
+}
+
#endif
#ifdef RIPPER
@@ -13232,7 +13963,7 @@ ripper_error_p(VALUE vparser)
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- return p->error_p ? Qtrue : Qfalse;
+ return RBOOL(p->error_p);
}
#endif
@@ -13248,7 +13979,7 @@ rb_parser_end_seen_p(VALUE vparser)
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- return p->ruby__end__seen ? Qtrue : Qfalse;
+ return RBOOL(p->ruby__end__seen);
}
/*
@@ -13279,7 +14010,7 @@ rb_parser_get_yydebug(VALUE self)
struct parser_params *p;
TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- return p->debug ? Qtrue : Qfalse;
+ return RBOOL(p->debug);
}
#endif
@@ -13386,12 +14117,10 @@ rb_parser_free(struct parser_params *p, void *ptr)
while ((n = *prev) != NULL) {
if (n->ptr == ptr) {
*prev = n->next;
- rb_gc_force_recycle((VALUE)n);
break;
}
prev = &n->next;
}
- xfree(ptr);
}
#endif
@@ -13515,8 +14244,8 @@ ripper_validate_object(VALUE self, VALUE x)
{
if (x == Qfalse) return x;
if (x == Qtrue) return x;
- if (x == Qnil) return x;
- if (x == Qundef)
+ if (NIL_P(x)) return x;
+ if (UNDEF_P(x))
rb_raise(rb_eArgError, "Qundef given");
if (FIXNUM_P(x)) return x;
if (SYMBOL_P(x)) return x;
@@ -13530,7 +14259,7 @@ ripper_validate_object(VALUE self, VALUE x)
case T_RATIONAL:
break;
case T_NODE:
- if (nd_type((NODE *)x) != NODE_RIPPER) {
+ if (!nd_type_p((NODE *)x, NODE_RIPPER)) {
rb_raise(rb_eArgError, "NODE given: %p", (void *)x);
}
x = ((NODE *)x)->nd_rval;
@@ -13619,7 +14348,7 @@ ripper_get_id(VALUE v)
NODE *nd;
if (!RB_TYPE_P(v, T_NODE)) return 0;
nd = (NODE *)v;
- if (nd_type(nd) != NODE_RIPPER) return 0;
+ if (!nd_type_p(nd, NODE_RIPPER)) return 0;
return nd->nd_vid;
}
@@ -13627,10 +14356,10 @@ static VALUE
ripper_get_value(VALUE v)
{
NODE *nd;
- if (v == Qundef) return Qnil;
+ if (UNDEF_P(v)) return Qnil;
if (!RB_TYPE_P(v, T_NODE)) return v;
nd = (NODE *)v;
- if (nd_type(nd) != NODE_RIPPER) return Qnil;
+ if (!nd_type_p(nd, NODE_RIPPER)) return Qnil;
return nd->nd_rval;
}
@@ -13888,7 +14617,7 @@ static VALUE
ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
{
StringValue(msg);
- if (obj == Qundef) {
+ if (UNDEF_P(obj)) {
rb_raise(rb_eArgError, "%"PRIsVALUE, msg);
}
return Qnil;
diff --git a/prelude.rb b/prelude.rb
index b1e477a3ea..8fd6e6cb77 100644
--- a/prelude.rb
+++ b/prelude.rb
@@ -20,3 +20,12 @@ module Kernel
private :pp
end
+
+autoload :Set, 'set'
+
+module Enumerable
+ # Makes a set from the enumerable object with given arguments.
+ def to_set(klass = Set, *args, &block)
+ klass.new(self, *args, &block)
+ end
+end
diff --git a/probes_helper.h b/probes_helper.h
index d2d0ebb6e2..0003e96dd8 100644
--- a/probes_helper.h
+++ b/probes_helper.h
@@ -19,13 +19,13 @@ MJIT_SYMBOL_EXPORT_END
#define RUBY_DTRACE_METHOD_HOOK(name, ec, klazz, id) \
do { \
if (UNLIKELY(RUBY_DTRACE_##name##_ENABLED())) { \
- struct ruby_dtrace_method_hook_args args; \
- if (rb_dtrace_setup(ec, klazz, id, &args)) { \
- RUBY_DTRACE_##name(args.classname, \
- args.methodname, \
- args.filename, \
- args.line_no); \
- } \
+ struct ruby_dtrace_method_hook_args args; \
+ if (rb_dtrace_setup(ec, klazz, id, &args)) { \
+ RUBY_DTRACE_##name(args.classname, \
+ args.methodname, \
+ args.filename, \
+ args.line_no); \
+ } \
} \
} while (0)
diff --git a/proc.c b/proc.c
index d4236d0061..bb0ad89851 100644
--- a/proc.c
+++ b/proc.c
@@ -15,12 +15,14 @@
#include "internal/class.h"
#include "internal/error.h"
#include "internal/eval.h"
+#include "internal/hash.h"
#include "internal/object.h"
#include "internal/proc.h"
#include "internal/symbol.h"
#include "method.h"
#include "iseq.h"
#include "vm_core.h"
+#include "yjit.h"
#if !defined(__GNUC__) || __GNUC__ < 5 || defined(__MINGW32__)
# define NO_CLOBBERED(v) (*(volatile VALUE *)&(v))
@@ -36,7 +38,11 @@ const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
struct METHOD {
const VALUE recv;
const VALUE klass;
+ /* needed for #super_method */
const VALUE iclass;
+ /* Different than me->owner only for ZSUPER methods.
+ This is error-prone but unavoidable unless ZSUPER methods are removed. */
+ const VALUE owner;
const rb_method_entry_t * const me;
/* for bound methods, `me' should be rb_callable_method_entry_t * */
};
@@ -80,21 +86,21 @@ block_mark(const struct rb_block *block)
switch (vm_block_type(block)) {
case block_type_iseq:
case block_type_ifunc:
- {
- const struct rb_captured_block *captured = &block->as.captured;
- 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 */) {
+ {
+ const struct rb_captured_block *captured = &block->as.captured;
+ RUBY_MARK_MOVABLE_UNLESS_NULL(captured->self);
+ RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)captured->code.val);
+ if (captured->ep && !UNDEF_P(captured->ep[VM_ENV_DATA_INDEX_ENV]) /* cfunc_proc_t */) {
rb_gc_mark(VM_ENV_ENVVAL(captured->ep));
- }
- }
- break;
+ }
+ }
+ break;
case block_type_symbol:
- RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.symbol);
- break;
+ RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.symbol);
+ break;
case block_type_proc:
- RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.proc);
- break;
+ RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.proc);
+ break;
}
}
@@ -104,18 +110,18 @@ block_compact(struct rb_block *block)
switch (block->type) {
case block_type_iseq:
case block_type_ifunc:
- {
- struct rb_captured_block *captured = &block->as.captured;
+ {
+ struct rb_captured_block *captured = &block->as.captured;
captured->self = rb_gc_location(captured->self);
captured->code.val = rb_gc_location(captured->code.val);
- }
- break;
+ }
+ break;
case block_type_symbol:
block->as.symbol = rb_gc_location(block->as.symbol);
- break;
+ break;
case block_type_proc:
block->as.proc = rb_gc_location(block->as.proc);
- break;
+ break;
}
}
@@ -144,17 +150,17 @@ proc_memsize(const void *ptr)
{
const rb_proc_t *proc = ptr;
if (proc->block.as.captured.ep == ((const cfunc_proc_t *)ptr)->env+1)
- return sizeof(cfunc_proc_t);
+ return sizeof(cfunc_proc_t);
return sizeof(rb_proc_t);
}
static const rb_data_type_t proc_data_type = {
"proc",
{
- proc_mark,
- RUBY_TYPED_DEFAULT_FREE,
- proc_memsize,
- proc_compact,
+ proc_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ proc_memsize,
+ proc_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
@@ -332,10 +338,10 @@ binding_memsize(const void *ptr)
const rb_data_type_t ruby_binding_data_type = {
"binding",
{
- binding_mark,
- binding_free,
- binding_memsize,
- binding_compact,
+ binding_mark,
+ binding_free,
+ binding_memsize,
+ binding_compact,
},
0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -346,6 +352,9 @@ rb_binding_alloc(VALUE klass)
VALUE obj;
rb_binding_t *bind;
obj = TypedData_Make_Struct(klass, rb_binding_t, &ruby_binding_data_type, bind);
+#if YJIT_STATS
+ rb_yjit_collect_binding_alloc();
+#endif
return obj;
}
@@ -433,37 +442,37 @@ 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)) {
+ if (!VM_ENV_FLAGS(env->ep, VM_FRAME_FLAG_CFRAME)) {
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));
-
- for (i=0; i<iseq->body->local_table_size; i++) {
- if (iseq->body->local_table[i] == lid) {
- if (iseq->body->local_iseq == iseq &&
- iseq->body->param.flags.has_block &&
- (unsigned int)iseq->body->param.block_start == i) {
- const VALUE *ep = env->ep;
- if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) {
- RB_OBJ_WRITE(env, &env->env[i], rb_vm_bh_to_procval(GET_EC(), VM_ENV_BLOCK_HANDLER(ep)));
- VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
- }
- }
-
- *envp = env;
- return &env->env[i];
- }
- }
- }
- else {
- *envp = NULL;
- return NULL;
- }
+ unsigned int i;
+
+ VM_ASSERT(rb_obj_is_iseq((VALUE)iseq));
+
+ for (i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) {
+ if (ISEQ_BODY(iseq)->local_table[i] == lid) {
+ if (ISEQ_BODY(iseq)->local_iseq == iseq &&
+ ISEQ_BODY(iseq)->param.flags.has_block &&
+ (unsigned int)ISEQ_BODY(iseq)->param.block_start == i) {
+ const VALUE *ep = env->ep;
+ if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) {
+ RB_OBJ_WRITE(env, &env->env[i], rb_vm_bh_to_procval(GET_EC(), VM_ENV_BLOCK_HANDLER(ep)));
+ VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
+ }
+ }
+
+ *envp = env;
+ return &env->env[i];
+ }
+ }
+ }
+ else {
+ *envp = NULL;
+ return NULL;
+ }
} while ((env = rb_vm_env_prev_env(env)) != NULL);
*envp = NULL;
@@ -482,17 +491,17 @@ check_local_id(VALUE bindval, volatile VALUE *pname)
VALUE name = *pname;
if (lid) {
- if (!rb_is_local_id(lid)) {
- rb_name_err_raise("wrong local variable name `%1$s' for %2$s",
- bindval, ID2SYM(lid));
- }
+ if (!rb_is_local_id(lid)) {
+ rb_name_err_raise("wrong local variable name `%1$s' for %2$s",
+ bindval, ID2SYM(lid));
+ }
}
else {
- if (!rb_is_local_name(name)) {
- rb_name_err_raise("wrong local variable name `%1$s' for %2$s",
- bindval, name);
- }
- return 0;
+ if (!rb_is_local_name(name)) {
+ rb_name_err_raise("wrong local variable name `%1$s' for %2$s",
+ bindval, name);
+ }
+ return 0;
}
return lid;
}
@@ -605,11 +614,15 @@ bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val)
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) {
- /* not found. create new env */
- ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid);
- env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
+ /* not found. create new env */
+ ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid);
+ env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
}
+#if YJIT_STATS
+ rb_yjit_collect_binding_set();
+#endif
+
RB_OBJ_WRITE(env, ptr, val);
return val;
@@ -718,25 +731,25 @@ struct vm_ifunc *
rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc)
{
union {
- struct vm_ifunc_argc argc;
- VALUE packed;
+ struct vm_ifunc_argc argc;
+ VALUE packed;
} arity;
if (min_argc < UNLIMITED_ARGUMENTS ||
#if SIZEOF_INT * 2 > SIZEOF_VALUE
- min_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
+ min_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
#endif
- 0) {
- rb_raise(rb_eRangeError, "minimum argument number out of range: %d",
- min_argc);
+ 0) {
+ rb_raise(rb_eRangeError, "minimum argument number out of range: %d",
+ min_argc);
}
if (max_argc < UNLIMITED_ARGUMENTS ||
#if SIZEOF_INT * 2 > SIZEOF_VALUE
- max_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
+ max_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
#endif
- 0) {
- rb_raise(rb_eRangeError, "maximum argument number out of range: %d",
- max_argc);
+ 0) {
+ rb_raise(rb_eRangeError, "maximum argument number out of range: %d",
+ max_argc);
}
arity.argc.min = min_argc;
arity.argc.max = max_argc;
@@ -775,26 +788,26 @@ proc_new(VALUE klass, int8_t is_lambda, int8_t kernel)
/* block is in cf */
switch (vm_block_handler_type(block_handler)) {
case block_handler_type_proc:
- procval = VM_BH_TO_PROC(block_handler);
+ procval = VM_BH_TO_PROC(block_handler);
- if (RBASIC_CLASS(procval) == klass) {
- return procval;
- }
- else {
- VALUE newprocval = rb_proc_dup(procval);
+ if (RBASIC_CLASS(procval) == klass) {
+ return procval;
+ }
+ else {
+ VALUE newprocval = rb_proc_dup(procval);
RBASIC_SET_CLASS(newprocval, klass);
- return newprocval;
- }
- break;
+ return newprocval;
+ }
+ break;
case block_handler_type_symbol:
- return (klass != rb_cProc) ?
- sym_proc_new(klass, VM_BH_TO_SYMBOL(block_handler)) :
- rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
- break;
+ return (klass != rb_cProc) ?
+ sym_proc_new(klass, VM_BH_TO_SYMBOL(block_handler)) :
+ rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
+ break;
case block_handler_type_ifunc:
- return rb_vm_make_proc_lambda(ec, VM_BH_TO_CAPT_BLOCK(block_handler), klass, is_lambda);
+ return rb_vm_make_proc_lambda(ec, VM_BH_TO_CAPT_BLOCK(block_handler), klass, is_lambda);
case block_handler_type_iseq:
{
const struct rb_captured_block *captured = VM_BH_TO_CAPT_BLOCK(block_handler);
@@ -963,8 +976,8 @@ static inline int
check_argc(long argc)
{
if (argc > INT_MAX || argc < 0) {
- rb_raise(rb_eArgError, "too many arguments (%lu)",
- (unsigned long)argc);
+ rb_raise(rb_eArgError, "too many arguments (%lu)",
+ (unsigned long)argc);
}
return (int)argc;
}
@@ -990,15 +1003,7 @@ rb_proc_call_kw(VALUE self, VALUE args, int kw_splat)
VALUE
rb_proc_call(VALUE self, VALUE args)
{
- VALUE vret;
- rb_proc_t *proc;
- GetProcPtr(self, proc);
- vret = rb_vm_invoke_proc(GET_EC(), proc,
- check_argc(RARRAY_LEN(args)), RARRAY_CONST_PTR(args),
- RB_NO_KEYWORDS, VM_BLOCK_HANDLER_NONE);
- RB_GC_GUARD(self);
- RB_GC_GUARD(args);
- return vret;
+ return rb_proc_call_kw(self, args, RB_NO_KEYWORDS);
}
static VALUE
@@ -1077,11 +1082,11 @@ proc_arity(VALUE self)
static inline int
rb_iseq_min_max_arity(const rb_iseq_t *iseq, int *max)
{
- *max = iseq->body->param.flags.has_rest == FALSE ?
- iseq->body->param.lead_num + iseq->body->param.opt_num + iseq->body->param.post_num +
- (iseq->body->param.flags.has_kw == TRUE || iseq->body->param.flags.has_kwrest == TRUE)
+ *max = ISEQ_BODY(iseq)->param.flags.has_rest == FALSE ?
+ ISEQ_BODY(iseq)->param.lead_num + ISEQ_BODY(iseq)->param.opt_num + ISEQ_BODY(iseq)->param.post_num +
+ (ISEQ_BODY(iseq)->param.flags.has_kw == TRUE || ISEQ_BODY(iseq)->param.flags.has_kwrest == TRUE)
: UNLIMITED_ARGUMENTS;
- return iseq->body->param.lead_num + iseq->body->param.post_num + (iseq->body->param.flags.has_kw && iseq->body->param.keyword->required_num > 0);
+ return ISEQ_BODY(iseq)->param.lead_num + ISEQ_BODY(iseq)->param.post_num + (ISEQ_BODY(iseq)->param.flags.has_kw && ISEQ_BODY(iseq)->param.keyword->required_num > 0);
}
static int
@@ -1090,20 +1095,20 @@ rb_vm_block_min_max_arity(const struct rb_block *block, int *max)
again:
switch (vm_block_type(block)) {
case block_type_iseq:
- return rb_iseq_min_max_arity(rb_iseq_check(block->as.captured.code.iseq), max);
+ return rb_iseq_min_max_arity(rb_iseq_check(block->as.captured.code.iseq), max);
case block_type_proc:
- block = vm_proc_block(block->as.proc);
- goto again;
+ block = vm_proc_block(block->as.proc);
+ goto again;
case block_type_ifunc:
- {
- const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
- if (IS_METHOD_PROC_IFUNC(ifunc)) {
- /* e.g. method(:foo).to_proc.arity */
- return method_min_max_arity((VALUE)ifunc->data, max);
- }
- *max = ifunc->argc.max;
- return ifunc->argc.min;
- }
+ {
+ const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
+ if (IS_METHOD_PROC_IFUNC(ifunc)) {
+ /* e.g. method(:foo).to_proc.arity */
+ return method_min_max_arity((VALUE)ifunc->data, max);
+ }
+ *max = ifunc->argc.max;
+ return ifunc->argc.min;
+ }
case block_type_symbol:
*max = UNLIMITED_ARGUMENTS;
return 1;
@@ -1141,20 +1146,20 @@ block_setup(struct rb_block *block, VALUE block_handler)
{
switch (vm_block_handler_type(block_handler)) {
case block_handler_type_iseq:
- block->type = block_type_iseq;
- block->as.captured = *VM_BH_TO_ISEQ_BLOCK(block_handler);
- break;
+ block->type = block_type_iseq;
+ block->as.captured = *VM_BH_TO_ISEQ_BLOCK(block_handler);
+ break;
case block_handler_type_ifunc:
- block->type = block_type_ifunc;
- block->as.captured = *VM_BH_TO_IFUNC_BLOCK(block_handler);
- break;
+ block->type = block_type_ifunc;
+ block->as.captured = *VM_BH_TO_IFUNC_BLOCK(block_handler);
+ break;
case block_handler_type_symbol:
- block->type = block_type_symbol;
- block->as.symbol = VM_BH_TO_SYMBOL(block_handler);
- break;
+ block->type = block_type_symbol;
+ block->as.symbol = VM_BH_TO_SYMBOL(block_handler);
+ break;
case block_handler_type_proc:
- block->type = block_type_proc;
- block->as.proc = VM_BH_TO_PROC(block_handler);
+ block->type = block_type_proc;
+ block->as.proc = VM_BH_TO_PROC(block_handler);
}
}
@@ -1168,7 +1173,7 @@ rb_block_pair_yield_optimizable(void)
struct rb_block block;
if (block_handler == VM_BLOCK_HANDLER_NONE) {
- rb_raise(rb_eArgError, "no block given");
+ rb_raise(rb_eArgError, "no block given");
}
block_setup(&block, block_handler);
@@ -1179,14 +1184,14 @@ rb_block_pair_yield_optimizable(void)
return 0;
case block_handler_type_proc:
- {
- VALUE procval = block_handler;
- rb_proc_t *proc;
- GetProcPtr(procval, 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;
@@ -1203,26 +1208,21 @@ rb_block_arity(void)
struct rb_block block;
if (block_handler == VM_BLOCK_HANDLER_NONE) {
- rb_raise(rb_eArgError, "no block given");
+ 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 -1;
+ return -1;
case block_handler_type_proc:
- {
- VALUE procval = block_handler;
- rb_proc_t *proc;
- GetProcPtr(procval, proc);
- return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
- }
+ return rb_proc_arity(block_handler);
default:
- return max != UNLIMITED_ARGUMENTS ? min : -min-1;
+ min = rb_vm_block_min_max_arity(&block, &max);
+ return max != UNLIMITED_ARGUMENTS ? min : -min-1;
}
}
@@ -1235,7 +1235,7 @@ rb_block_min_max_arity(int *max)
struct rb_block block;
if (block_handler == VM_BLOCK_HANDLER_NONE) {
- rb_raise(rb_eArgError, "no block given");
+ rb_raise(rb_eArgError, "no block given");
}
block_setup(&block, block_handler);
@@ -1254,23 +1254,23 @@ rb_proc_get_iseq(VALUE self, int *is_proc)
switch (vm_block_type(block)) {
case block_type_iseq:
- return rb_iseq_check(block->as.captured.code.iseq);
+ return rb_iseq_check(block->as.captured.code.iseq);
case block_type_proc:
- return rb_proc_get_iseq(block->as.proc, is_proc);
+ return rb_proc_get_iseq(block->as.proc, is_proc);
case block_type_ifunc:
- {
- const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
- if (IS_METHOD_PROC_IFUNC(ifunc)) {
- /* method(:foo).to_proc */
- if (is_proc) *is_proc = 0;
- return rb_method_iseq((VALUE)ifunc->data);
- }
- else {
- return NULL;
- }
- }
+ {
+ const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
+ if (IS_METHOD_PROC_IFUNC(ifunc)) {
+ /* method(:foo).to_proc */
+ if (is_proc) *is_proc = 0;
+ return rb_method_iseq((VALUE)ifunc->data);
+ }
+ else {
+ return NULL;
+ }
+ }
case block_type_symbol:
- return NULL;
+ return NULL;
}
VM_UNREACHABLE(rb_proc_get_iseq);
@@ -1368,7 +1368,7 @@ iseq_location(const rb_iseq_t *iseq)
if (!iseq) return Qnil;
rb_iseq_check(iseq);
loc[0] = rb_iseq_path(iseq);
- loc[1] = iseq->body->location.first_lineno;
+ loc[1] = RB_INT2NUM(ISEQ_BODY(iseq)->location.first_lineno);
return rb_ary_new4(2, loc);
}
@@ -1403,32 +1403,59 @@ rb_unnamed_parameters(int arity)
a = rb_ary_new3(1, ID2SYM(req));
OBJ_FREEZE(a);
for (; n; --n) {
- rb_ary_push(param, a);
+ rb_ary_push(param, a);
}
if (arity < 0) {
- CONST_ID(rest, "rest");
- rb_ary_store(param, ~arity, rb_ary_new3(1, ID2SYM(rest)));
+ CONST_ID(rest, "rest");
+ rb_ary_store(param, ~arity, rb_ary_new3(1, ID2SYM(rest)));
}
return param;
}
/*
* call-seq:
- * prc.parameters -> array
+ * prc.parameters(lambda: nil) -> array
*
- * Returns the parameter information of this proc.
+ * Returns the parameter information of this proc. If the lambda
+ * keyword is provided and not nil, treats the proc as a lambda if
+ * true and as a non-lambda if false.
*
+ * prc = proc{|x, y=42, *other|}
+ * prc.parameters #=> [[:opt, :x], [:opt, :y], [:rest, :other]]
* prc = lambda{|x, y=42, *other|}
* prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
+ * prc = proc{|x, y=42, *other|}
+ * prc.parameters(lambda: true) #=> [[:req, :x], [:opt, :y], [:rest, :other]]
+ * prc = lambda{|x, y=42, *other|}
+ * prc.parameters(lambda: false) #=> [[:opt, :x], [:opt, :y], [:rest, :other]]
*/
static VALUE
-rb_proc_parameters(VALUE self)
+rb_proc_parameters(int argc, VALUE *argv, VALUE self)
{
- int is_proc;
- const rb_iseq_t *iseq = rb_proc_get_iseq(self, &is_proc);
+ static ID keyword_ids[1];
+ VALUE opt, lambda;
+ VALUE kwargs[1];
+ int is_proc ;
+ const rb_iseq_t *iseq;
+
+ iseq = rb_proc_get_iseq(self, &is_proc);
+
+ if (!keyword_ids[0]) {
+ CONST_ID(keyword_ids[0], "lambda");
+ }
+
+ rb_scan_args(argc, argv, "0:", &opt);
+ if (!NIL_P(opt)) {
+ rb_get_kwargs(opt, keyword_ids, 0, 1, kwargs);
+ lambda = kwargs[0];
+ if (!NIL_P(lambda)) {
+ is_proc = !RTEST(lambda);
+ }
+ }
+
if (!iseq) {
- return rb_unnamed_parameters(rb_proc_arity(self));
+ return rb_unnamed_parameters(rb_proc_arity(self));
}
return rb_iseq_parameters(iseq, is_proc);
}
@@ -1438,11 +1465,42 @@ rb_hash_proc(st_index_t hash, VALUE prc)
{
rb_proc_t *proc;
GetProcPtr(prc, proc);
- hash = rb_hash_uint(hash, (st_index_t)proc->block.as.captured.code.val);
- hash = rb_hash_uint(hash, (st_index_t)proc->block.as.captured.self);
+
+ switch (vm_block_type(&proc->block)) {
+ case block_type_iseq:
+ hash = rb_st_hash_uint(hash, (st_index_t)proc->block.as.captured.code.iseq->body);
+ break;
+ case block_type_ifunc:
+ hash = rb_st_hash_uint(hash, (st_index_t)proc->block.as.captured.code.ifunc->func);
+ break;
+ case block_type_symbol:
+ hash = rb_st_hash_uint(hash, rb_any_hash(proc->block.as.symbol));
+ break;
+ case block_type_proc:
+ hash = rb_st_hash_uint(hash, rb_any_hash(proc->block.as.proc));
+ break;
+ default:
+ rb_bug("rb_hash_proc: unknown block type %d", vm_block_type(&proc->block));
+ }
+
return rb_hash_uint(hash, (st_index_t)proc->block.as.captured.ep);
}
+
+/*
+ * call-seq:
+ * to_proc
+ *
+ * Returns a Proc object which calls the method with name of +self+
+ * on the first parameter and passes the remaining parameters to the method.
+ *
+ * proc = :to_s.to_proc # => #<Proc:0x000001afe0e48680(&:to_s) (lambda)>
+ * proc.call(1000) # => "1000"
+ * proc.call(1000, 16) # => "3e8"
+ * (1..3).collect(&:to_s) # => ["1", "2", "3"]
+ *
+ */
+
MJIT_FUNC_EXPORTED VALUE
rb_sym_to_proc(VALUE sym)
{
@@ -1453,9 +1511,9 @@ rb_sym_to_proc(VALUE sym)
ID id;
if (!sym_proc_cache) {
- sym_proc_cache = rb_ary_tmp_new(SYM_PROC_CACHE_SIZE * 2);
- rb_gc_register_mark_object(sym_proc_cache);
- rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
+ sym_proc_cache = rb_ary_hidden_new(SYM_PROC_CACHE_SIZE * 2);
+ rb_gc_register_mark_object(sym_proc_cache);
+ rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
}
id = SYM2ID(sym);
@@ -1468,7 +1526,7 @@ rb_sym_to_proc(VALUE sym)
proc = sym_proc_new(rb_cProc, ID2SYM(id));
RARRAY_ASET(sym_proc_cache, index, sym);
RARRAY_ASET(sym_proc_cache, index + 1, proc);
- return proc;
+ return proc;
}
}
@@ -1500,22 +1558,22 @@ rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_i
again:
switch (vm_block_type(block)) {
case block_type_proc:
- block = vm_proc_block(block->as.proc);
- goto again;
+ block = vm_proc_block(block->as.proc);
+ goto again;
case block_type_iseq:
- {
- const rb_iseq_t *iseq = rb_iseq_check(block->as.captured.code.iseq);
+ {
+ const rb_iseq_t *iseq = rb_iseq_check(block->as.captured.code.iseq);
rb_str_catf(str, "%p %"PRIsVALUE":%d", (void *)self,
- rb_iseq_path(iseq),
- FIX2INT(iseq->body->location.first_lineno));
- }
- break;
+ rb_iseq_path(iseq),
+ ISEQ_BODY(iseq)->location.first_lineno);
+ }
+ break;
case block_type_symbol:
- rb_str_catf(str, "%p(&%+"PRIsVALUE")", (void *)self, block->as.symbol);
- break;
+ rb_str_catf(str, "%p(&%+"PRIsVALUE")", (void *)self, block->as.symbol);
+ break;
case block_type_ifunc:
- rb_str_catf(str, "%p", (void *)block->as.captured.code.ifunc);
- break;
+ rb_str_catf(str, "%p", (void *)block->as.captured.code.ifunc);
+ break;
}
if (additional_info) rb_str_cat_cstr(str, additional_info);
@@ -1560,6 +1618,7 @@ bm_mark(void *ptr)
rb_gc_mark_movable(data->recv);
rb_gc_mark_movable(data->klass);
rb_gc_mark_movable(data->iclass);
+ rb_gc_mark_movable(data->owner);
rb_gc_mark_movable((VALUE)data->me);
}
@@ -1570,6 +1629,7 @@ bm_compact(void *ptr)
UPDATE_REFERENCE(data->recv);
UPDATE_REFERENCE(data->klass);
UPDATE_REFERENCE(data->iclass);
+ UPDATE_REFERENCE(data->owner);
UPDATE_TYPED_REFERENCE(rb_method_entry_t *, data->me);
}
@@ -1582,10 +1642,10 @@ bm_memsize(const void *ptr)
static const rb_data_type_t method_data_type = {
"method",
{
- bm_mark,
- RUBY_TYPED_DEFAULT_FREE,
- bm_memsize,
- bm_compact,
+ bm_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ bm_memsize,
+ bm_compact,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -1602,9 +1662,9 @@ respond_to_missing_p(VALUE klass, VALUE obj, VALUE sym, int scope)
/* TODO: merge with obj_respond_to() */
ID rmiss = idRespond_to_missing;
- if (obj == Qundef) return 0;
+ if (UNDEF_P(obj)) return 0;
if (rb_method_basic_definition_p(klass, rmiss)) return 0;
- return RTEST(rb_funcall(obj, rmiss, 2, sym, scope ? Qfalse : Qtrue));
+ return RTEST(rb_funcall(obj, rmiss, 2, sym, RBOOL(!scope)));
}
@@ -1618,6 +1678,7 @@ mnew_missing(VALUE klass, VALUE obj, ID id, VALUE mclass)
RB_OBJ_WRITE(method, &data->recv, obj);
RB_OBJ_WRITE(method, &data->klass, klass);
+ RB_OBJ_WRITE(method, &data->owner, klass);
def = ZALLOC(rb_method_definition_t);
def->type = VM_METHOD_TYPE_MISSING;
@@ -1641,46 +1702,55 @@ mnew_missing_by_name(VALUE klass, VALUE obj, VALUE *name, int scope, VALUE mclas
static VALUE
mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
- VALUE obj, ID id, VALUE mclass, int scope, int error)
+ VALUE obj, ID id, VALUE mclass, int scope, int error)
{
struct METHOD *data;
VALUE method;
+ const rb_method_entry_t *original_me = me;
rb_method_visibility_t visi = METHOD_VISI_UNDEF;
again:
if (UNDEFINED_METHOD_ENTRY_P(me)) {
- if (respond_to_missing_p(klass, obj, ID2SYM(id), scope)) {
- return mnew_missing(klass, obj, id, mclass);
- }
- if (!error) return Qnil;
- rb_print_undef(klass, id, METHOD_VISI_UNDEF);
+ if (respond_to_missing_p(klass, obj, ID2SYM(id), scope)) {
+ return mnew_missing(klass, obj, id, mclass);
+ }
+ if (!error) return Qnil;
+ rb_print_undef(klass, id, METHOD_VISI_UNDEF);
}
if (visi == METHOD_VISI_UNDEF) {
- visi = METHOD_ENTRY_VISI(me);
- if (scope && (visi != METHOD_VISI_PUBLIC)) {
- if (!error) return Qnil;
- rb_print_inaccessible(klass, id, visi);
- }
+ visi = METHOD_ENTRY_VISI(me);
+ RUBY_ASSERT(visi != METHOD_VISI_UNDEF); /* !UNDEFINED_METHOD_ENTRY_P(me) */
+ if (scope && (visi != METHOD_VISI_PUBLIC)) {
+ if (!error) return Qnil;
+ rb_print_inaccessible(klass, id, visi);
+ }
}
if (me->def->type == VM_METHOD_TYPE_ZSUPER) {
- if (me->defined_class) {
+ if (me->defined_class) {
VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class));
- id = me->def->original_id;
+ id = me->def->original_id;
me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass);
- }
- else {
+ }
+ else {
VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->owner));
- id = me->def->original_id;
- me = rb_method_entry_without_refinements(klass, id, &iclass);
- }
- goto again;
+ id = me->def->original_id;
+ me = rb_method_entry_without_refinements(klass, id, &iclass);
+ }
+ goto again;
}
method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
- RB_OBJ_WRITE(method, &data->recv, obj);
- RB_OBJ_WRITE(method, &data->klass, klass);
+ if (obj == Qundef) {
+ RB_OBJ_WRITE(method, &data->recv, Qundef);
+ RB_OBJ_WRITE(method, &data->klass, Qundef);
+ }
+ else {
+ RB_OBJ_WRITE(method, &data->recv, obj);
+ RB_OBJ_WRITE(method, &data->klass, klass);
+ }
RB_OBJ_WRITE(method, &data->iclass, iclass);
+ RB_OBJ_WRITE(method, &data->owner, original_me->owner);
RB_OBJ_WRITE(method, &data->me, me);
return method;
@@ -1688,7 +1758,7 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
static VALUE
mnew_from_me(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
- VALUE obj, ID id, VALUE mclass, int scope)
+ VALUE obj, ID id, VALUE mclass, int scope)
{
return mnew_internal(me, klass, iclass, obj, id, mclass, scope, TRUE);
}
@@ -1699,7 +1769,7 @@ mnew_callable(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
const rb_method_entry_t *me;
VALUE iclass = Qnil;
- ASSUME(obj != Qundef);
+ ASSUME(!UNDEF_P(obj));
me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass);
return mnew_from_me(me, klass, iclass, obj, id, mclass, scope);
}
@@ -1766,9 +1836,9 @@ method_eq(VALUE method, VALUE other)
VALUE klass1, klass2;
if (!rb_obj_is_method(other))
- return Qfalse;
+ return Qfalse;
if (CLASS_OF(method) != CLASS_OF(other))
- return Qfalse;
+ return Qfalse;
Check_TypedStruct(method, &method_data_type);
m1 = (struct METHOD *)DATA_PTR(method);
@@ -1778,10 +1848,10 @@ method_eq(VALUE method, VALUE other)
klass2 = method_entry_defined_class(m2->me);
if (!rb_method_entry_eq(m1->me, m2->me) ||
- klass1 != klass2 ||
- m1->klass != m2->klass ||
- m1->recv != m2->recv) {
- return Qfalse;
+ klass1 != klass2 ||
+ m1->klass != m2->klass ||
+ m1->recv != m2->recv) {
+ return Qfalse;
}
return Qtrue;
@@ -1789,6 +1859,22 @@ method_eq(VALUE method, VALUE other)
/*
* call-seq:
+ * meth.eql?(other_meth) -> true or false
+ * meth == other_meth -> true or false
+ *
+ * Two unbound method objects are equal if they refer to the same
+ * method definition.
+ *
+ * Array.instance_method(:each_slice) == Enumerable.instance_method(:each_slice)
+ * #=> true
+ *
+ * Array.instance_method(:sum) == Enumerable.instance_method(:sum)
+ * #=> false, Array redefines the method for efficiency
+ */
+#define unbound_method_eq method_eq
+
+/*
+ * call-seq:
* meth.hash -> integer
*
* Returns a hash value corresponding to the method object.
@@ -1827,10 +1913,11 @@ method_unbind(VALUE obj)
TypedData_Get_Struct(obj, struct METHOD, &method_data_type, orig);
method = TypedData_Make_Struct(rb_cUnboundMethod, struct METHOD,
- &method_data_type, data);
+ &method_data_type, data);
RB_OBJ_WRITE(method, &data->recv, Qundef);
- RB_OBJ_WRITE(method, &data->klass, orig->klass);
+ RB_OBJ_WRITE(method, &data->klass, Qundef);
RB_OBJ_WRITE(method, &data->iclass, orig->iclass);
+ RB_OBJ_WRITE(method, &data->owner, orig->me->owner);
RB_OBJ_WRITE(method, &data->me, rb_method_entry_clone(orig->me));
return method;
@@ -1896,7 +1983,15 @@ method_original_name(VALUE obj)
* call-seq:
* meth.owner -> class_or_module
*
- * Returns the class or module that defines the method.
+ * Returns the class or module on which this method is defined.
+ * In other words,
+ *
+ * meth.owner.instance_methods(false).include?(meth.name) # => true
+ *
+ * holds as long as the method is not removed/undefined/replaced,
+ * (with private_instance_methods instead of instance_methods if the method
+ * is private).
+ *
* See also Method#receiver.
*
* (1..3).method(:map).owner #=> Enumerable
@@ -1907,7 +2002,7 @@ method_owner(VALUE obj)
{
struct METHOD *data;
TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
- return data->me->owner;
+ return data->owner;
}
void
@@ -1918,22 +2013,22 @@ rb_method_name_error(VALUE klass, VALUE str)
VALUE s = Qundef;
if (FL_TEST(c, FL_SINGLETON)) {
- VALUE obj = rb_ivar_get(klass, attached);
+ VALUE obj = rb_ivar_get(klass, attached);
- switch (BUILTIN_TYPE(obj)) {
- case T_MODULE:
- case T_CLASS:
- c = obj;
+ switch (BUILTIN_TYPE(obj)) {
+ case T_MODULE:
+ case T_CLASS:
+ c = obj;
break;
default:
- break;
- }
+ break;
+ }
}
else if (RB_TYPE_P(c, T_MODULE)) {
- s = MSG(" module");
+ s = MSG(" module");
}
- if (s == Qundef) {
- s = MSG(" class");
+ if (UNDEF_P(s)) {
+ s = MSG(" class");
}
rb_name_err_raise_str(s, c, str);
#undef MSG
@@ -1949,7 +2044,7 @@ obj_method(VALUE obj, VALUE vid, int scope)
if (!id) {
VALUE m = mnew_missing_by_name(klass, obj, &vid, scope, mclass);
if (m) return m;
- rb_method_name_error(klass, vid);
+ rb_method_name_error(klass, vid);
}
return mnew_callable(klass, obj, id, mclass, scope);
}
@@ -2110,7 +2205,7 @@ rb_mod_instance_method(VALUE mod, VALUE vid)
{
ID id = rb_check_id(&vid);
if (!id) {
- rb_method_name_error(mod, vid);
+ rb_method_name_error(mod, vid);
}
return mnew_unbound(mod, id, rb_cUnboundMethod, FALSE);
}
@@ -2127,11 +2222,79 @@ rb_mod_public_instance_method(VALUE mod, VALUE vid)
{
ID id = rb_check_id(&vid);
if (!id) {
- rb_method_name_error(mod, vid);
+ rb_method_name_error(mod, vid);
}
return mnew_unbound(mod, id, rb_cUnboundMethod, TRUE);
}
+static VALUE
+rb_mod_define_method_with_visibility(int argc, VALUE *argv, VALUE mod, const struct rb_scope_visi_struct* scope_visi)
+{
+ ID id;
+ VALUE body;
+ VALUE name;
+ int is_method = FALSE;
+
+ rb_check_arity(argc, 1, 2);
+ name = argv[0];
+ id = rb_check_id(&name);
+ if (argc == 1) {
+ body = rb_block_lambda();
+ }
+ else {
+ body = argv[1];
+
+ if (rb_obj_is_method(body)) {
+ is_method = TRUE;
+ }
+ else if (rb_obj_is_proc(body)) {
+ is_method = FALSE;
+ }
+ else {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %s (expected Proc/Method/UnboundMethod)",
+ rb_obj_classname(body));
+ }
+ }
+ if (!id) id = rb_to_id(name);
+
+ if (is_method) {
+ struct METHOD *method = (struct METHOD *)DATA_PTR(body);
+ if (method->me->owner != mod && !RB_TYPE_P(method->me->owner, T_MODULE) &&
+ !RTEST(rb_class_inherited_p(mod, method->me->owner))) {
+ if (FL_TEST(method->me->owner, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError,
+ "can't bind singleton method to a different class");
+ }
+ else {
+ rb_raise(rb_eTypeError,
+ "bind argument must be a subclass of % "PRIsVALUE,
+ method->me->owner);
+ }
+ }
+ rb_method_entry_set(mod, id, method->me, scope_visi->method_visi);
+ if (scope_visi->module_func) {
+ rb_method_entry_set(rb_singleton_class(mod), id, method->me, METHOD_VISI_PUBLIC);
+ }
+ RB_GC_GUARD(body);
+ }
+ else {
+ VALUE procval = rb_proc_dup(body);
+ if (vm_proc_iseq(procval) != NULL) {
+ rb_proc_t *proc;
+ GetProcPtr(procval, proc);
+ proc->is_lambda = TRUE;
+ proc->is_from_method = TRUE;
+ }
+ rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)procval, scope_visi->method_visi);
+ if (scope_visi->module_func) {
+ rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, METHOD_VISI_PUBLIC);
+ }
+ }
+
+ return ID2SYM(id);
+}
+
/*
* call-seq:
* define_method(symbol, method) -> symbol
@@ -2175,76 +2338,15 @@ rb_mod_public_instance_method(VALUE mod, VALUE vid)
static VALUE
rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
{
- ID id;
- VALUE body;
- VALUE name;
const rb_cref_t *cref = rb_vm_cref_in_context(mod, mod);
const rb_scope_visibility_t default_scope_visi = {METHOD_VISI_PUBLIC, FALSE};
const rb_scope_visibility_t *scope_visi = &default_scope_visi;
- int is_method = FALSE;
if (cref) {
- scope_visi = CREF_SCOPE_VISI(cref);
+ scope_visi = CREF_SCOPE_VISI(cref);
}
- rb_check_arity(argc, 1, 2);
- name = argv[0];
- id = rb_check_id(&name);
- if (argc == 1) {
- body = rb_block_lambda();
- }
- else {
- body = argv[1];
-
- if (rb_obj_is_method(body)) {
- is_method = TRUE;
- }
- else if (rb_obj_is_proc(body)) {
- is_method = FALSE;
- }
- else {
- rb_raise(rb_eTypeError,
- "wrong argument type %s (expected Proc/Method/UnboundMethod)",
- rb_obj_classname(body));
- }
- }
- if (!id) id = rb_to_id(name);
-
- if (is_method) {
- struct METHOD *method = (struct METHOD *)DATA_PTR(body);
- if (method->me->owner != mod && !RB_TYPE_P(method->me->owner, T_MODULE) &&
- !RTEST(rb_class_inherited_p(mod, method->me->owner))) {
- if (FL_TEST(method->me->owner, FL_SINGLETON)) {
- rb_raise(rb_eTypeError,
- "can't bind singleton method to a different class");
- }
- else {
- rb_raise(rb_eTypeError,
- "bind argument must be a subclass of % "PRIsVALUE,
- method->me->owner);
- }
- }
- rb_method_entry_set(mod, id, method->me, scope_visi->method_visi);
- if (scope_visi->module_func) {
- rb_method_entry_set(rb_singleton_class(mod), id, method->me, METHOD_VISI_PUBLIC);
- }
- RB_GC_GUARD(body);
- }
- else {
- VALUE procval = rb_proc_dup(body);
- if (vm_proc_iseq(procval) != NULL) {
- rb_proc_t *proc;
- GetProcPtr(procval, proc);
- proc->is_lambda = TRUE;
- proc->is_from_method = TRUE;
- }
- rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)procval, scope_visi->method_visi);
- if (scope_visi->module_func) {
- rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, METHOD_VISI_PUBLIC);
- }
- }
-
- return ID2SYM(id);
+ return rb_mod_define_method_with_visibility(argc, argv, mod, scope_visi);
}
/*
@@ -2252,7 +2354,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
* define_singleton_method(symbol, method) -> symbol
* define_singleton_method(symbol) { block } -> symbol
*
- * Defines a singleton method in the receiver. The _method_
+ * Defines a public singleton method in the receiver. The _method_
* parameter can be a +Proc+, a +Method+ or an +UnboundMethod+ object.
* If a block is specified, it is used as the method body.
* If a block or a method has parameters, they're used as method parameters.
@@ -2282,8 +2384,9 @@ static VALUE
rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
{
VALUE klass = rb_singleton_class(obj);
+ const rb_scope_visibility_t scope_visi = {METHOD_VISI_PUBLIC, FALSE};
- return rb_mod_define_method(argc, argv, klass);
+ return rb_mod_define_method_with_visibility(argc, argv, klass, &scope_visi);
}
/*
@@ -2296,17 +2399,7 @@ rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
static VALUE
top_define_method(int argc, VALUE *argv, VALUE obj)
{
- rb_thread_t *th = GET_THREAD();
- VALUE klass;
-
- klass = th->top_wrapper;
- if (klass) {
- rb_warning("main.define_method in the wrapped load is effective only in wrapper module");
- }
- else {
- klass = rb_cObject;
- }
- return rb_mod_define_method(argc, argv, klass);
+ return rb_mod_define_method(argc, argv, rb_top_main_class("define_method"));
}
/*
@@ -2338,6 +2431,7 @@ method_clone(VALUE self)
RB_OBJ_WRITE(clone, &data->recv, orig->recv);
RB_OBJ_WRITE(clone, &data->klass, orig->klass);
RB_OBJ_WRITE(clone, &data->iclass, orig->iclass);
+ RB_OBJ_WRITE(clone, &data->owner, orig->owner);
RB_OBJ_WRITE(clone, &data->me, rb_method_entry_clone(orig->me));
return clone;
}
@@ -2388,8 +2482,7 @@ method_clone(VALUE self)
static VALUE
rb_method_call_pass_called_kw(int argc, const VALUE *argv, VALUE method)
{
- VALUE procval = rb_block_given_p() ? rb_block_proc() : Qnil;
- return rb_method_call_with_block_kw(argc, argv, method, procval, RB_PASS_CALLED_KEYWORDS);
+ return rb_method_call_kw(argc, argv, method, RB_PASS_CALLED_KEYWORDS);
}
VALUE
@@ -2429,8 +2522,8 @@ rb_method_call_with_block_kw(int argc, const VALUE *argv, VALUE method, VALUE pa
rb_execution_context_t *ec = GET_EC();
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
- if (data->recv == Qundef) {
- rb_raise(rb_eTypeError, "can't call unbound method; bind first");
+ if (UNDEF_P(data->recv)) {
+ rb_raise(rb_eTypeError, "can't call unbound method; bind first");
}
return call_method_data(ec, data, argc, argv, passed_procval, kw_splat);
}
@@ -2497,9 +2590,9 @@ rb_method_call_with_block(int argc, const VALUE *argv, VALUE method, VALUE passe
*/
static void
-convert_umethod_to_method_components(const struct METHOD *data, VALUE recv, VALUE *methclass_out, VALUE *klass_out, VALUE *iclass_out, const rb_method_entry_t **me_out)
+convert_umethod_to_method_components(const struct METHOD *data, VALUE recv, VALUE *methclass_out, VALUE *klass_out, VALUE *iclass_out, const rb_method_entry_t **me_out, const bool clone)
{
- VALUE methclass = data->me->owner;
+ VALUE methclass = data->owner;
VALUE iclass = data->me->defined_class;
VALUE klass = CLASS_OF(recv);
@@ -2507,29 +2600,39 @@ convert_umethod_to_method_components(const struct METHOD *data, VALUE recv, VALU
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)) {
- rb_raise(rb_eTypeError,
- "singleton method called for a different object");
- }
- else {
- rb_raise(rb_eTypeError, "bind argument must be an instance of % "PRIsVALUE,
- methclass);
- }
+ if (!RB_TYPE_P(methclass, T_MODULE) && !RTEST(rb_obj_is_kind_of(recv, methclass))) {
+ if (FL_TEST(methclass, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError,
+ "singleton method called for a different object");
+ }
+ else {
+ rb_raise(rb_eTypeError, "bind argument must be an instance of % "PRIsVALUE,
+ methclass);
+ }
}
- const rb_method_entry_t *me = rb_method_entry_clone(data->me);
+ const rb_method_entry_t *me;
+ if (clone) {
+ me = rb_method_entry_clone(data->me);
+ }
+ else {
+ me = data->me;
+ }
if (RB_TYPE_P(me->owner, T_MODULE)) {
- VALUE ic = rb_class_search_ancestor(klass, me->owner);
- if (ic) {
- klass = ic;
+ if (!clone) {
+ // if we didn't previously clone the method entry, then we need to clone it now
+ // because this branch manipulates it in rb_method_entry_complement_defined_class
+ me = rb_method_entry_clone(me);
+ }
+ VALUE ic = rb_class_search_ancestor(klass, me->owner);
+ if (ic) {
+ klass = ic;
iclass = ic;
- }
- else {
- klass = rb_include_class_new(methclass, klass);
- }
+ }
+ else {
+ klass = rb_include_class_new(methclass, klass);
+ }
me = (const rb_method_entry_t *) rb_method_entry_complement_defined_class(me, me->called_id, klass);
}
@@ -2581,13 +2684,14 @@ umethod_bind(VALUE method, VALUE recv)
const rb_method_entry_t *me;
const struct METHOD *data;
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
- convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me);
+ convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me, true);
struct METHOD *bound;
method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
RB_OBJ_WRITE(method, &bound->recv, recv);
RB_OBJ_WRITE(method, &bound->klass, klass);
RB_OBJ_WRITE(method, &bound->iclass, iclass);
+ RB_OBJ_WRITE(method, &bound->owner, methclass);
RB_OBJ_WRITE(method, &bound->me, me);
return method;
@@ -2623,8 +2727,8 @@ umethod_bind_call(int argc, VALUE *argv, VALUE method)
else {
VALUE methclass, klass, iclass;
const rb_method_entry_t *me;
- convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me);
- struct METHOD bound = { recv, klass, 0, me };
+ convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me, false);
+ struct METHOD bound = { recv, klass, 0, methclass, me };
return call_method_data(ec, &bound, argc, argv, passed_procval, RB_PASS_CALLED_KEYWORDS);
}
@@ -2636,68 +2740,78 @@ umethod_bind_call(int argc, VALUE *argv, VALUE method)
* if there is no maximum.
*/
static int
-rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max)
+method_def_min_max_arity(const rb_method_definition_t *def, int *max)
{
- const rb_method_definition_t *def = me->def;
-
again:
if (!def) return *max = 0;
switch (def->type) {
case VM_METHOD_TYPE_CFUNC:
- if (def->body.cfunc.argc < 0) {
- *max = UNLIMITED_ARGUMENTS;
- return 0;
- }
- return *max = check_argc(def->body.cfunc.argc);
+ if (def->body.cfunc.argc < 0) {
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
+ }
+ return *max = check_argc(def->body.cfunc.argc);
case VM_METHOD_TYPE_ZSUPER:
- *max = UNLIMITED_ARGUMENTS;
- return 0;
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
case VM_METHOD_TYPE_ATTRSET:
- return *max = 1;
+ return *max = 1;
case VM_METHOD_TYPE_IVAR:
- return *max = 0;
+ return *max = 0;
case VM_METHOD_TYPE_ALIAS:
- def = def->body.alias.original_me->def;
- goto again;
+ def = def->body.alias.original_me->def;
+ goto again;
case VM_METHOD_TYPE_BMETHOD:
return rb_proc_min_max_arity(def->body.bmethod.proc, max);
case VM_METHOD_TYPE_ISEQ:
- return rb_iseq_min_max_arity(rb_iseq_check(def->body.iseq.iseqptr), max);
+ return rb_iseq_min_max_arity(rb_iseq_check(def->body.iseq.iseqptr), max);
case VM_METHOD_TYPE_UNDEF:
case VM_METHOD_TYPE_NOTIMPLEMENTED:
- return *max = 0;
+ return *max = 0;
case VM_METHOD_TYPE_MISSING:
- *max = UNLIMITED_ARGUMENTS;
- return 0;
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
case VM_METHOD_TYPE_OPTIMIZED: {
- switch (def->body.optimize_type) {
- case OPTIMIZED_METHOD_TYPE_SEND:
- *max = UNLIMITED_ARGUMENTS;
- return 0;
- case OPTIMIZED_METHOD_TYPE_CALL:
- *max = UNLIMITED_ARGUMENTS;
- return 0;
- case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
- *max = UNLIMITED_ARGUMENTS;
- return 0;
- default:
- break;
- }
- break;
+ switch (def->body.optimized.type) {
+ case OPTIMIZED_METHOD_TYPE_SEND:
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
+ case OPTIMIZED_METHOD_TYPE_CALL:
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
+ case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
+ case OPTIMIZED_METHOD_TYPE_STRUCT_AREF:
+ *max = 0;
+ return 0;
+ case OPTIMIZED_METHOD_TYPE_STRUCT_ASET:
+ *max = 1;
+ return 1;
+ default:
+ break;
+ }
+ break;
}
case VM_METHOD_TYPE_REFINED:
- *max = UNLIMITED_ARGUMENTS;
- return 0;
+ *max = UNLIMITED_ARGUMENTS;
+ return 0;
}
- rb_bug("rb_method_entry_min_max_arity: invalid method entry type (%d)", def->type);
+ rb_bug("method_def_min_max_arity: invalid method entry type (%d)", def->type);
UNREACHABLE_RETURN(Qnil);
}
+static int
+method_def_arity(const rb_method_definition_t *def)
+{
+ int max, min = method_def_min_max_arity(def, &max);
+ return min == max ? min : -min-1;
+}
+
int
rb_method_entry_arity(const rb_method_entry_t *me)
{
- int max, min = rb_method_entry_min_max_arity(me, &max);
- return min == max ? min : -min-1;
+ return method_def_arity(me->def);
}
/*
@@ -2765,10 +2879,10 @@ original_method_entry(VALUE mod, ID id)
const rb_method_entry_t *me;
while ((me = rb_method_entry(mod, id)) != 0) {
- const rb_method_definition_t *def = me->def;
- if (def->type != VM_METHOD_TYPE_ZSUPER) break;
- mod = RCLASS_SUPER(me->owner);
- id = def->original_id;
+ const rb_method_definition_t *def = me->def;
+ if (def->type != VM_METHOD_TYPE_ZSUPER) break;
+ mod = RCLASS_SUPER(me->owner);
+ id = def->original_id;
}
return me;
}
@@ -2779,7 +2893,7 @@ method_min_max_arity(VALUE method, int *max)
const struct METHOD *data;
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
- return rb_method_entry_min_max_arity(data->me, max);
+ return method_def_min_max_arity(data->me->def, max);
}
int
@@ -2825,11 +2939,11 @@ method_def_iseq(const rb_method_definition_t *def)
{
switch (def->type) {
case VM_METHOD_TYPE_ISEQ:
- return rb_iseq_check(def->body.iseq.iseqptr);
+ return rb_iseq_check(def->body.iseq.iseqptr);
case VM_METHOD_TYPE_BMETHOD:
return rb_proc_get_iseq(def->body.bmethod.proc, 0);
case VM_METHOD_TYPE_ALIAS:
- return method_def_iseq(def->body.alias.original_me->def);
+ return method_def_iseq(def->body.alias.original_me->def);
case VM_METHOD_TYPE_CFUNC:
case VM_METHOD_TYPE_ATTRSET:
case VM_METHOD_TYPE_IVAR:
@@ -2839,7 +2953,7 @@ method_def_iseq(const rb_method_definition_t *def)
case VM_METHOD_TYPE_OPTIMIZED:
case VM_METHOD_TYPE_MISSING:
case VM_METHOD_TYPE_REFINED:
- break;
+ break;
}
return NULL;
}
@@ -2858,12 +2972,12 @@ method_cref(VALUE method)
again:
switch (def->type) {
case VM_METHOD_TYPE_ISEQ:
- return def->body.iseq.cref;
+ return def->body.iseq.cref;
case VM_METHOD_TYPE_ALIAS:
- def = def->body.alias.original_me->def;
- goto again;
+ def = def->body.alias.original_me->def;
+ goto again;
default:
- return NULL;
+ return NULL;
}
}
@@ -2871,9 +2985,9 @@ static VALUE
method_def_location(const rb_method_definition_t *def)
{
if (def->type == VM_METHOD_TYPE_ATTRSET || def->type == VM_METHOD_TYPE_IVAR) {
- if (!def->body.attr.location)
- return Qnil;
- return rb_ary_dup(def->body.attr.location);
+ if (!def->body.attr.location)
+ return Qnil;
+ return rb_ary_dup(def->body.attr.location);
}
return iseq_location(method_def_iseq(def));
}
@@ -2899,6 +3013,69 @@ rb_method_location(VALUE method)
return method_def_location(rb_method_def(method));
}
+static const rb_method_definition_t *
+vm_proc_method_def(VALUE procval)
+{
+ const rb_proc_t *proc;
+ const struct rb_block *block;
+ const struct vm_ifunc *ifunc;
+
+ GetProcPtr(procval, proc);
+ block = &proc->block;
+
+ if (vm_block_type(block) == block_type_ifunc &&
+ IS_METHOD_PROC_IFUNC(ifunc = block->as.captured.code.ifunc)) {
+ return rb_method_def((VALUE)ifunc->data);
+ }
+ else {
+ return NULL;
+ }
+}
+
+static VALUE
+method_def_parameters(const rb_method_definition_t *def)
+{
+ const rb_iseq_t *iseq;
+ const rb_method_definition_t *bmethod_def;
+
+ switch (def->type) {
+ case VM_METHOD_TYPE_ISEQ:
+ iseq = method_def_iseq(def);
+ return rb_iseq_parameters(iseq, 0);
+ case VM_METHOD_TYPE_BMETHOD:
+ if ((iseq = method_def_iseq(def)) != NULL) {
+ return rb_iseq_parameters(iseq, 0);
+ }
+ else if ((bmethod_def = vm_proc_method_def(def->body.bmethod.proc)) != NULL) {
+ return method_def_parameters(bmethod_def);
+ }
+ break;
+
+ case VM_METHOD_TYPE_ALIAS:
+ return method_def_parameters(def->body.alias.original_me->def);
+
+ case VM_METHOD_TYPE_OPTIMIZED:
+ if (def->body.optimized.type == OPTIMIZED_METHOD_TYPE_STRUCT_ASET) {
+ VALUE param = rb_ary_new_from_args(2, ID2SYM(rb_intern("req")), ID2SYM(rb_intern("_")));
+ return rb_ary_new_from_args(1, param);
+ }
+ break;
+
+ case VM_METHOD_TYPE_CFUNC:
+ case VM_METHOD_TYPE_ATTRSET:
+ case VM_METHOD_TYPE_IVAR:
+ case VM_METHOD_TYPE_ZSUPER:
+ case VM_METHOD_TYPE_UNDEF:
+ case VM_METHOD_TYPE_NOTIMPLEMENTED:
+ case VM_METHOD_TYPE_MISSING:
+ case VM_METHOD_TYPE_REFINED:
+ break;
+ }
+
+ return rb_unnamed_parameters(method_def_arity(def));
+
+}
+
/*
* call-seq:
* meth.parameters -> array
@@ -2921,11 +3098,7 @@ rb_method_location(VALUE method)
static VALUE
rb_method_parameters(VALUE method)
{
- const rb_iseq_t *iseq = rb_method_iseq(method);
- if (!iseq) {
- return rb_unnamed_parameters(method_arity(method));
- }
- return rb_iseq_parameters(iseq, 0);
+ return method_def_parameters(rb_method_def(method));
}
/*
@@ -2985,33 +3158,37 @@ method_inspect(VALUE method)
}
if (data->me->def->type == VM_METHOD_TYPE_ALIAS) {
- defined_class = data->me->def->body.alias.original_me->owner;
+ defined_class = data->me->def->body.alias.original_me->owner;
}
else {
- defined_class = method_entry_defined_class(data->me);
+ defined_class = method_entry_defined_class(data->me);
}
if (RB_TYPE_P(defined_class, T_ICLASS)) {
- defined_class = RBASIC_CLASS(defined_class);
+ defined_class = RBASIC_CLASS(defined_class);
+ }
+
+ if (data->recv == Qundef) {
+ // UnboundMethod
+ rb_str_buf_append(str, rb_inspect(defined_class));
}
+ else if (FL_TEST(mklass, FL_SINGLETON)) {
+ VALUE v = rb_ivar_get(mklass, attached);
- if (FL_TEST(mklass, FL_SINGLETON)) {
- VALUE v = rb_ivar_get(mklass, attached);
-
- if (data->recv == Qundef) {
- rb_str_buf_append(str, rb_inspect(mklass));
- }
- else if (data->recv == v) {
- rb_str_buf_append(str, rb_inspect(v));
- sharp = ".";
- }
- else {
- rb_str_buf_append(str, rb_inspect(data->recv));
- rb_str_buf_cat2(str, "(");
- rb_str_buf_append(str, rb_inspect(v));
- rb_str_buf_cat2(str, ")");
- sharp = ".";
- }
+ if (UNDEF_P(data->recv)) {
+ rb_str_buf_append(str, rb_inspect(mklass));
+ }
+ else if (data->recv == v) {
+ rb_str_buf_append(str, rb_inspect(v));
+ sharp = ".";
+ }
+ else {
+ rb_str_buf_append(str, rb_inspect(data->recv));
+ rb_str_buf_cat2(str, "(");
+ rb_str_buf_append(str, rb_inspect(v));
+ rb_str_buf_cat2(str, ")");
+ sharp = ".";
+ }
}
else {
mklass = data->klass;
@@ -3023,16 +3200,16 @@ method_inspect(VALUE method)
} 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);
- }
+ rb_str_buf_append(str, rb_inspect(mklass));
+ if (defined_class != mklass) {
+ rb_str_catf(str, "(% "PRIsVALUE")", defined_class);
+ }
}
rb_str_buf_cat2(str, sharp);
rb_str_append(str, rb_id2str(data->me->called_id));
if (data->me->called_id != data->me->def->original_id) {
- rb_str_catf(str, "(%"PRIsVALUE")",
- rb_id2str(data->me->def->original_id));
+ rb_str_catf(str, "(%"PRIsVALUE")",
+ rb_id2str(data->me->def->original_id));
}
if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
rb_str_buf_cat2(str, " (not-implemented)");
@@ -3054,6 +3231,16 @@ method_inspect(VALUE method)
rb_str_buf_cat2(str, "(");
+ if (RARRAY_LEN(params) == 3 &&
+ RARRAY_AREF(RARRAY_AREF(params, 0), 0) == rest &&
+ RARRAY_AREF(RARRAY_AREF(params, 0), 1) == ID2SYM('*') &&
+ RARRAY_AREF(RARRAY_AREF(params, 1), 0) == keyrest &&
+ RARRAY_AREF(RARRAY_AREF(params, 1), 1) == ID2SYM(idPow) &&
+ RARRAY_AREF(RARRAY_AREF(params, 2), 0) == block &&
+ RARRAY_AREF(RARRAY_AREF(params, 2), 1) == ID2SYM('&')) {
+ forwarding = 1;
+ }
+
for (int i = 0; i < RARRAY_LEN(params); i++) {
pair = RARRAY_AREF(params, i);
kind = RARRAY_AREF(pair, 0);
@@ -3089,8 +3276,7 @@ method_inspect(VALUE method)
}
else if (kind == rest) {
if (name == ID2SYM('*')) {
- forwarding = 1;
- rb_str_cat_cstr(str, "...");
+ rb_str_cat_cstr(str, forwarding ? "..." : "*");
}
else {
rb_str_catf(str, "*%"PRIsVALUE, name);
@@ -3103,6 +3289,9 @@ method_inspect(VALUE method)
else if (i > 0) {
rb_str_set_len(str, RSTRING_LEN(str) - 2);
}
+ else {
+ rb_str_cat_cstr(str, "**");
+ }
}
else if (kind == block) {
if (name == ID2SYM('&')) {
@@ -3259,7 +3448,7 @@ env_clone(const rb_env_t *env, const rb_cref_t *cref)
VM_ASSERT(VM_ENV_ESCAPED_P(env->ep));
if (cref == NULL) {
- cref = rb_vm_cref_new_toplevel();
+ cref = rb_vm_cref_new_toplevel();
}
new_body = ALLOC_N(VALUE, env->env_size);
@@ -3302,31 +3491,31 @@ proc_binding(VALUE self)
again:
switch (vm_block_type(block)) {
case block_type_iseq:
- iseq = block->as.captured.code.iseq;
- binding_self = block->as.captured.self;
- env = VM_ENV_ENVVAL_PTR(block->as.captured.ep);
- break;
+ iseq = block->as.captured.code.iseq;
+ binding_self = block->as.captured.self;
+ env = VM_ENV_ENVVAL_PTR(block->as.captured.ep);
+ break;
case block_type_proc:
- GetProcPtr(block->as.proc, proc);
- block = &proc->block;
- goto again;
+ GetProcPtr(block->as.proc, proc);
+ block = &proc->block;
+ goto again;
case block_type_ifunc:
- {
- const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
- if (IS_METHOD_PROC_IFUNC(ifunc)) {
- VALUE method = (VALUE)ifunc->data;
- VALUE name = rb_fstring_lit("<empty_iseq>");
- rb_iseq_t *empty;
- binding_self = method_receiver(method);
- iseq = rb_method_iseq(method);
- env = VM_ENV_ENVVAL_PTR(block->as.captured.ep);
- env = env_clone(env, method_cref(method));
- /* set empty iseq */
- empty = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP);
- RB_OBJ_WRITE(env, &env->iseq, empty);
- break;
- }
- }
+ {
+ const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
+ if (IS_METHOD_PROC_IFUNC(ifunc)) {
+ VALUE method = (VALUE)ifunc->data;
+ VALUE name = rb_fstring_lit("<empty_iseq>");
+ rb_iseq_t *empty;
+ binding_self = method_receiver(method);
+ iseq = rb_method_iseq(method);
+ env = VM_ENV_ENVVAL_PTR(block->as.captured.ep);
+ env = env_clone(env, method_cref(method));
+ /* set empty iseq */
+ empty = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP);
+ RB_OBJ_WRITE(env, &env->iseq, empty);
+ break;
+ }
+ }
/* FALLTHROUGH */
case block_type_symbol:
rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
@@ -3341,14 +3530,14 @@ proc_binding(VALUE self)
RB_OBJ_WRITTEN(bindval, Qundef, VM_ENV_ENVVAL(env->ep));
if (iseq) {
- rb_iseq_check(iseq);
- RB_OBJ_WRITE(bindval, &bind->pathobj, iseq->body->location.pathobj);
- bind->first_lineno = FIX2INT(rb_iseq_first_lineno(iseq));
+ rb_iseq_check(iseq);
+ RB_OBJ_WRITE(bindval, &bind->pathobj, ISEQ_BODY(iseq)->location.pathobj);
+ bind->first_lineno = ISEQ_BODY(iseq)->location.first_lineno;
}
else {
- RB_OBJ_WRITE(bindval, &bind->pathobj,
- rb_iseq_pathobj_new(rb_fstring_lit("(binding)"), Qnil));
- bind->first_lineno = 1;
+ RB_OBJ_WRITE(bindval, &bind->pathobj,
+ rb_iseq_pathobj_new(rb_fstring_lit("(binding)"), Qnil));
+ bind->first_lineno = 1;
}
return bindval;
@@ -3386,10 +3575,10 @@ curry(RB_BLOCK_CALL_FUNC_ARGLIST(_, args))
if (RARRAY_LEN(passed) < FIX2INT(arity)) {
if (!NIL_P(blockarg)) {
- rb_warn("given block not used");
- }
- arity = make_curry_proc(proc, passed, arity);
- return arity;
+ rb_warn("given block not used");
+ }
+ arity = make_curry_proc(proc, passed, arity);
+ return arity;
}
else {
return rb_proc_call_with_block(proc, check_argc(RARRAY_LEN(passed)), RARRAY_CONST_PTR(passed), blockarg);
@@ -3408,6 +3597,10 @@ curry(RB_BLOCK_CALL_FUNC_ARGLIST(_, args))
* proc and returns the result. Otherwise, returns another curried proc that
* takes the rest of arguments.
*
+ * The optional <i>arity</i> argument should be supplied when currying procs with
+ * variable arguments to determine how many arguments are needed before the proc is
+ * called.
+ *
* b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
* p b.curry[1][2][3] #=> 6
* p b.curry[1, 2][3, 4] #=> 6
@@ -3445,13 +3638,13 @@ proc_curry(int argc, const VALUE *argv, VALUE self)
VALUE arity;
if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(arity = argv[0])) {
- arity = INT2FIX(min_arity);
+ arity = INT2FIX(min_arity);
}
else {
- sarity = FIX2INT(arity);
- if (rb_proc_lambda_p(self)) {
- rb_check_arity(sarity, min_arity, max_arity);
- }
+ sarity = FIX2INT(arity);
+ if (rb_proc_lambda_p(self)) {
+ rb_check_arity(sarity, min_arity, max_arity);
+ }
}
return make_curry_proc(self, rb_ary_new(), arity);
@@ -3724,10 +3917,10 @@ proc_ruby2_keywords(VALUE procval)
switch (proc->block.type) {
case block_type_iseq:
- if (proc->block.as.captured.code.iseq->body->param.flags.has_rest &&
- !proc->block.as.captured.code.iseq->body->param.flags.has_kw &&
- !proc->block.as.captured.code.iseq->body->param.flags.has_kwrest) {
- proc->block.as.captured.code.iseq->body->param.flags.ruby2_keywords = 1;
+ if (ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_rest &&
+ !ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_kw &&
+ !ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_kwrest) {
+ ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.ruby2_keywords = 1;
}
else {
rb_warn("Skipping set of ruby2_keywords flag for proc (proc accepts keywords or proc does not accept argument splat)");
@@ -3838,7 +4031,8 @@ proc_ruby2_keywords(VALUE procval)
*
* lambda1 = lambda {|x| x**2 }
*
- * * Use the Lambda literal syntax (also constructs a proc with lambda semantics):
+ * * Use the {Lambda proc literal}[rdoc-ref:syntax/literals.rdoc@Lambda+Proc+Literals] syntax
+ * (also constructs a proc with lambda semantics):
*
* lambda2 = ->(x) { x**2 }
*
@@ -4086,14 +4280,10 @@ Init_Proc(void)
rb_undef_alloc_func(rb_cProc);
rb_define_singleton_method(rb_cProc, "new", rb_proc_s_new, -1);
- rb_add_method(rb_cProc, idCall, VM_METHOD_TYPE_OPTIMIZED,
- (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC);
- rb_add_method(rb_cProc, rb_intern("[]"), VM_METHOD_TYPE_OPTIMIZED,
- (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC);
- rb_add_method(rb_cProc, rb_intern("==="), VM_METHOD_TYPE_OPTIMIZED,
- (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC);
- rb_add_method(rb_cProc, rb_intern("yield"), VM_METHOD_TYPE_OPTIMIZED,
- (void *)OPTIMIZED_METHOD_TYPE_CALL, METHOD_VISI_PUBLIC);
+ rb_add_method_optimized(rb_cProc, idCall, OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC);
+ rb_add_method_optimized(rb_cProc, rb_intern("[]"), OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC);
+ rb_add_method_optimized(rb_cProc, rb_intern("==="), OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC);
+ rb_add_method_optimized(rb_cProc, rb_intern("yield"), OPTIMIZED_METHOD_TYPE_CALL, 0, METHOD_VISI_PUBLIC);
#if 0 /* for RDoc */
rb_define_method(rb_cProc, "call", proc_call, -1);
@@ -4117,7 +4307,7 @@ Init_Proc(void)
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, "parameters", rb_proc_parameters, -1);
rb_define_method(rb_cProc, "ruby2_keywords", proc_ruby2_keywords, 0);
// rb_define_method(rb_cProc, "isolate", rb_proc_isolate, 0); is not accepted.
@@ -4167,8 +4357,8 @@ Init_Proc(void)
rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject);
rb_undef_alloc_func(rb_cUnboundMethod);
rb_undef_method(CLASS_OF(rb_cUnboundMethod), "new");
- rb_define_method(rb_cUnboundMethod, "==", method_eq, 1);
- rb_define_method(rb_cUnboundMethod, "eql?", method_eq, 1);
+ rb_define_method(rb_cUnboundMethod, "==", unbound_method_eq, 1);
+ rb_define_method(rb_cUnboundMethod, "eql?", unbound_method_eq, 1);
rb_define_method(rb_cUnboundMethod, "hash", method_hash, 0);
rb_define_method(rb_cUnboundMethod, "clone", method_clone, 0);
rb_define_method(rb_cUnboundMethod, "arity", method_arity_m, 0);
@@ -4192,7 +4382,7 @@ Init_Proc(void)
rb_define_method(rb_mKernel, "define_singleton_method", rb_obj_define_method, -1);
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
- "define_method", top_define_method, -1);
+ "define_method", top_define_method, -1);
}
/*
diff --git a/process.c b/process.c
index dc2dcf9560..c317a4cc2c 100644
--- a/process.c
+++ b/process.c
@@ -103,6 +103,7 @@ int initgroups(const char *, rb_gid_t);
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/hash.h"
+#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/process.h"
#include "internal/thread.h"
@@ -123,6 +124,12 @@ int initgroups(const char *, rb_gid_t);
#endif
#if defined(HAVE_TIMES) || defined(_WIN32)
+/*********************************************************************
+ *
+ * Document-class: Process::Tms
+ *
+ * Placeholder for rusage
+ */
static VALUE rb_cProcessTms;
#endif
@@ -177,6 +184,9 @@ static void check_uid_switch(void);
static void check_gid_switch(void);
static int exec_async_signal_safe(const struct rb_execarg *, char *, size_t);
+VALUE rb_envtbl(void);
+VALUE rb_env_to_hash(void);
+
#if 1
#define p_uid_from_name p_uid_from_name
#define p_gid_from_name p_gid_from_name
@@ -315,10 +325,26 @@ static ID id_pgroup;
#ifdef _WIN32
static ID id_new_pgroup;
#endif
-static ID id_unsetenv_others, id_chdir, id_umask, id_close_others, id_ENV;
+static ID id_unsetenv_others, id_chdir, id_umask, id_close_others;
static ID id_nanosecond, id_microsecond, id_millisecond, id_second;
static ID id_float_microsecond, id_float_millisecond, id_float_second;
static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME, id_TIME_BASED_CLOCK_REALTIME;
+#ifdef CLOCK_REALTIME
+static ID id_CLOCK_REALTIME;
+# define RUBY_CLOCK_REALTIME ID2SYM(id_CLOCK_REALTIME)
+#endif
+#ifdef CLOCK_MONOTONIC
+static ID id_CLOCK_MONOTONIC;
+# define RUBY_CLOCK_MONOTONIC ID2SYM(id_CLOCK_MONOTONIC)
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+static ID id_CLOCK_PROCESS_CPUTIME_ID;
+# define RUBY_CLOCK_PROCESS_CPUTIME_ID ID2SYM(id_CLOCK_PROCESS_CPUTIME_ID)
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+static ID id_CLOCK_THREAD_CPUTIME_ID;
+# define RUBY_CLOCK_THREAD_CPUTIME_ID ID2SYM(id_CLOCK_THREAD_CPUTIME_ID)
+#endif
#ifdef HAVE_TIMES
static ID id_TIMES_BASED_CLOCK_MONOTONIC;
static ID id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID;
@@ -329,6 +355,7 @@ static ID id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID;
static ID id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID;
#ifdef __APPLE__
static ID id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC;
+# define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
#endif
static ID id_hertz;
@@ -733,31 +760,31 @@ static VALUE
pst_message_status(VALUE str, int status)
{
if (WIFSTOPPED(status)) {
- int stopsig = WSTOPSIG(status);
- const char *signame = ruby_signal_name(stopsig);
- if (signame) {
- rb_str_catf(str, " stopped SIG%s (signal %d)", signame, stopsig);
- }
- else {
- rb_str_catf(str, " stopped signal %d", stopsig);
- }
+ int stopsig = WSTOPSIG(status);
+ const char *signame = ruby_signal_name(stopsig);
+ if (signame) {
+ rb_str_catf(str, " stopped SIG%s (signal %d)", signame, stopsig);
+ }
+ else {
+ rb_str_catf(str, " stopped signal %d", stopsig);
+ }
}
if (WIFSIGNALED(status)) {
- int termsig = WTERMSIG(status);
- const char *signame = ruby_signal_name(termsig);
- if (signame) {
- rb_str_catf(str, " SIG%s (signal %d)", signame, termsig);
- }
- else {
- rb_str_catf(str, " signal %d", termsig);
- }
+ int termsig = WTERMSIG(status);
+ const char *signame = ruby_signal_name(termsig);
+ if (signame) {
+ rb_str_catf(str, " SIG%s (signal %d)", signame, termsig);
+ }
+ else {
+ rb_str_catf(str, " signal %d", termsig);
+ }
}
if (WIFEXITED(status)) {
- rb_str_catf(str, " exit %d", WEXITSTATUS(status));
+ rb_str_catf(str, " exit %d", WEXITSTATUS(status));
}
#ifdef WCOREDUMP
if (WCOREDUMP(status)) {
- rb_str_cat2(str, " (core dumped)");
+ rb_str_cat2(str, " (core dumped)");
}
#endif
return str;
@@ -894,10 +921,7 @@ pst_wifstopped(VALUE st)
{
int status = PST2INT(st);
- if (WIFSTOPPED(status))
- return Qtrue;
- else
- return Qfalse;
+ return RBOOL(WIFSTOPPED(status));
}
@@ -915,7 +939,7 @@ pst_wstopsig(VALUE st)
int status = PST2INT(st);
if (WIFSTOPPED(status))
- return INT2NUM(WSTOPSIG(status));
+ return INT2NUM(WSTOPSIG(status));
return Qnil;
}
@@ -933,10 +957,7 @@ pst_wifsignaled(VALUE st)
{
int status = PST2INT(st);
- if (WIFSIGNALED(status))
- return Qtrue;
- else
- return Qfalse;
+ return RBOOL(WIFSIGNALED(status));
}
@@ -955,7 +976,7 @@ pst_wtermsig(VALUE st)
int status = PST2INT(st);
if (WIFSIGNALED(status))
- return INT2NUM(WTERMSIG(status));
+ return INT2NUM(WTERMSIG(status));
return Qnil;
}
@@ -974,10 +995,7 @@ pst_wifexited(VALUE st)
{
int status = PST2INT(st);
- if (WIFEXITED(status))
- return Qtrue;
- else
- return Qfalse;
+ return RBOOL(WIFEXITED(status));
}
@@ -1005,7 +1023,7 @@ pst_wexitstatus(VALUE st)
int status = PST2INT(st);
if (WIFEXITED(status))
- return INT2NUM(WEXITSTATUS(status));
+ return INT2NUM(WEXITSTATUS(status));
return Qnil;
}
@@ -1024,8 +1042,8 @@ pst_success_p(VALUE st)
int status = PST2INT(st);
if (!WIFEXITED(status))
- return Qnil;
- return WEXITSTATUS(status) == EXIT_SUCCESS ? Qtrue : Qfalse;
+ return Qnil;
+ return RBOOL(WEXITSTATUS(status) == EXIT_SUCCESS);
}
@@ -1043,10 +1061,7 @@ pst_wcoredump(VALUE st)
#ifdef WCOREDUMP
int status = PST2INT(st);
- if (WCOREDUMP(status))
- return Qtrue;
- else
- return Qfalse;
+ return RBOOL(WCOREDUMP(status));
#else
return Qfalse;
#endif
@@ -1067,7 +1082,7 @@ do_waitpid(rb_pid_t pid, int *st, int flags)
#define WAITPID_LOCK_ONLY ((struct waitpid_state *)-1)
struct waitpid_state {
- struct list_node wnode;
+ struct ccan_list_node wnode;
rb_execution_context_t *ec;
rb_nativethread_cond_t *cond;
rb_pid_t ret;
@@ -1082,6 +1097,15 @@ void rb_sigwait_sleep(const rb_thread_t *, int fd, const rb_hrtime_t *);
void rb_sigwait_fd_put(const rb_thread_t *, int fd);
void rb_thread_sleep_interruptible(void);
+#if USE_MJIT
+static struct waitpid_state mjit_waitpid_state;
+
+// variables shared with thread.c
+// TODO: implement the same thing with postponed_job and obviate these variables
+bool mjit_waitpid_finished = false;
+int mjit_waitpid_status = 0;
+#endif
+
static int
waitpid_signal(struct waitpid_state *w)
{
@@ -1089,15 +1113,31 @@ waitpid_signal(struct waitpid_state *w)
rb_threadptr_interrupt(rb_ec_thread_ptr(w->ec));
return TRUE;
}
- else { /* ruby_waitpid_locked */
- if (w->cond) {
- rb_native_cond_signal(w->cond);
- return TRUE;
- }
+#if USE_MJIT
+ else if (w == &mjit_waitpid_state && w->ret) { /* mjit_add_waiting_pid */
+ mjit_waitpid_finished = true;
+ mjit_waitpid_status = w->status;
+ return TRUE;
}
+#endif
return FALSE;
}
+// Used for VM memsize reporting. Returns the size of a list of waitpid_state
+// structs. Defined here because the struct definition lives here as well.
+size_t
+rb_vm_memsize_waiting_list(struct ccan_list_head *waiting_list)
+{
+ struct waitpid_state *waitpid = 0;
+ size_t size = 0;
+
+ ccan_list_for_each(waiting_list, waitpid, wnode) {
+ size += sizeof(struct waitpid_state);
+ }
+
+ return size;
+}
+
/*
* When a thread is done using sigwait_fd and there are other threads
* sleeping on waitpid, we must kick one of the threads out of
@@ -1108,10 +1148,10 @@ sigwait_fd_migrate_sleeper(rb_vm_t *vm)
{
struct waitpid_state *w = 0;
- list_for_each(&vm->waiting_pids, w, wnode) {
+ ccan_list_for_each(&vm->waiting_pids, w, wnode) {
if (waitpid_signal(w)) return;
}
- list_for_each(&vm->waiting_grps, w, wnode) {
+ ccan_list_for_each(&vm->waiting_grps, w, wnode) {
if (waitpid_signal(w)) return;
}
}
@@ -1128,18 +1168,30 @@ rb_sigwait_fd_migrate(rb_vm_t *vm)
extern volatile unsigned int ruby_nocldwait; /* signal.c */
/* called by timer thread or thread which acquired sigwait_fd */
static void
-waitpid_each(struct list_head *head)
+waitpid_each(rb_vm_t *vm, struct ccan_list_head *head)
{
struct waitpid_state *w = 0, *next;
- list_for_each_safe(head, w, next, wnode) {
+ ccan_list_for_each_safe(head, w, next, wnode) {
rb_pid_t ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG);
if (!ret) continue;
if (ret == -1) w->errnum = errno;
+ if (w->pid <= 0) {
+ /* when waiting for a group of processes, make sure a waiter for a
+ * specific pid is given that event in preference */
+ struct waitpid_state *w_inner = 0, *next_inner;
+ ccan_list_for_each_safe(&vm->waiting_pids, w_inner, next_inner, wnode) {
+ if (w_inner->pid == ret) {
+ /* signal this one instead */
+ w = w_inner;
+ }
+ }
+ }
+
w->ret = ret;
- list_del_init(&w->wnode);
+ ccan_list_del_init(&w->wnode);
waitpid_signal(w);
}
}
@@ -1152,12 +1204,10 @@ ruby_waitpid_all(rb_vm_t *vm)
{
#if RUBY_SIGCHLD
rb_native_mutex_lock(&vm->waitpid_lock);
- waitpid_each(&vm->waiting_pids);
- if (list_empty(&vm->waiting_pids)) {
- waitpid_each(&vm->waiting_grps);
- }
+ waitpid_each(vm, &vm->waiting_pids);
+ waitpid_each(vm, &vm->waiting_grps);
/* emulate SA_NOCLDWAIT */
- if (list_empty(&vm->waiting_pids) && list_empty(&vm->waiting_grps)) {
+ if (ccan_list_empty(&vm->waiting_pids) && ccan_list_empty(&vm->waiting_grps)) {
while (ruby_nocldwait && do_waitpid(-1, 0, WNOHANG) > 0)
; /* keep looping */
}
@@ -1175,68 +1225,18 @@ waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options)
w->status = 0;
}
-static const rb_hrtime_t *
-sigwait_sleep_time(void)
-{
- if (SIGCHLD_LOSSY) {
- static const rb_hrtime_t busy_wait = 100 * RB_HRTIME_PER_MSEC;
-
- return &busy_wait;
- }
- return 0;
-}
-
+#if USE_MJIT
/*
* must be called with vm->waitpid_lock held, this is not interruptible
*/
-rb_pid_t
-ruby_waitpid_locked(rb_vm_t *vm, rb_pid_t pid, int *status, int options,
- rb_nativethread_cond_t *cond)
+void
+mjit_add_waiting_pid(rb_vm_t *vm, rb_pid_t pid)
{
- struct waitpid_state w;
-
- assert(!ruby_thread_has_gvl_p() && "must not have GVL");
-
- waitpid_state_init(&w, pid, options);
- 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;
- }
- else {
- int sigwait_fd = -1;
-
- w.ec = 0;
- list_add(w.pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w.wnode);
- do {
- if (sigwait_fd < 0)
- sigwait_fd = rb_sigwait_fd_get(0);
-
- if (sigwait_fd >= 0) {
- w.cond = 0;
- rb_native_mutex_unlock(&vm->waitpid_lock);
- rb_sigwait_sleep(0, sigwait_fd, sigwait_sleep_time());
- rb_native_mutex_lock(&vm->waitpid_lock);
- }
- else {
- w.cond = cond;
- rb_native_cond_wait(w.cond, &vm->waitpid_lock);
- }
- } while (!w.ret);
- list_del(&w.wnode);
-
- /* we're done, maybe other waitpid callers are not: */
- if (sigwait_fd >= 0) {
- rb_sigwait_fd_put(0, sigwait_fd);
- sigwait_fd_migrate_sleeper(vm);
- }
- }
- if (status) {
- *status = w.status;
- }
- if (w.ret == -1) errno = w.errnum;
- return w.ret;
+ waitpid_state_init(&mjit_waitpid_state, pid, 0);
+ mjit_waitpid_state.ec = 0; // switch the behavior of waitpid_signal
+ ccan_list_add(&vm->waiting_pids, &mjit_waitpid_state.wnode);
}
+#endif
static VALUE
waitpid_sleep(VALUE x)
@@ -1256,20 +1256,21 @@ waitpid_cleanup(VALUE x)
struct waitpid_state *w = (struct waitpid_state *)x;
/*
- * XXX w->ret is sometimes set but list_del is still needed, here,
- * Not sure why, so we unconditionally do list_del here:
+ * XXX w->ret is sometimes set but ccan_list_del is still needed, here,
+ * Not sure why, so we unconditionally do ccan_list_del here:
*/
if (TRUE || w->ret == 0) {
rb_vm_t *vm = rb_ec_vm_ptr(w->ec);
rb_native_mutex_lock(&vm->waitpid_lock);
- list_del(&w->wnode);
+ ccan_list_del(&w->wnode);
rb_native_mutex_unlock(&vm->waitpid_lock);
}
return Qfalse;
}
+#if RUBY_SIGCHLD
static void
waitpid_wait(struct waitpid_state *w)
{
@@ -1283,10 +1284,17 @@ waitpid_wait(struct waitpid_state *w)
*/
rb_native_mutex_lock(&vm->waitpid_lock);
- if (w->pid > 0 || list_empty(&vm->waiting_pids)) {
- w->ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG);
+ if (w->options & WNOHANG && w->pid <= 0) {
+ /* In the case of WNOHANG wait for a group, make sure there isn't a zombie child
+ * whose PID we are directly waiting for in another call to waitpid. If there is,
+ * we will reap it via a call to waitpid($pid) with this call to waitpid_each. */
+ waitpid_each(vm, &vm->waiting_pids);
+ /* _now_ it's safe to call do_waitpid, without risk of stealing the wait from
+ * another directed call. */
}
+ w->ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG);
+
if (w->ret) {
if (w->ret == -1) w->errnum = errno;
}
@@ -1299,7 +1307,7 @@ waitpid_wait(struct waitpid_state *w)
if (need_sleep) {
w->cond = 0;
/* order matters, favor specified PIDs rather than -1 or 0 */
- list_add(w->pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w->wnode);
+ ccan_list_add(w->pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w->wnode);
}
rb_native_mutex_unlock(&vm->waitpid_lock);
@@ -1308,6 +1316,7 @@ waitpid_wait(struct waitpid_state *w)
rb_ensure(waitpid_sleep, (VALUE)w, waitpid_cleanup, (VALUE)w);
}
}
+#endif
static void *
waitpid_blocking_no_SIGCHLD(void *x)
@@ -1342,7 +1351,7 @@ rb_process_status_wait(rb_pid_t pid, int flags)
if (!(flags & WNOHANG)) {
VALUE scheduler = rb_fiber_scheduler_current();
VALUE result = rb_fiber_scheduler_process_wait(scheduler, pid, flags);
- if (result != Qundef) return result;
+ if (!UNDEF_P(result)) return result;
}
struct waitpid_state waitpid_state;
@@ -1350,12 +1359,11 @@ rb_process_status_wait(rb_pid_t pid, int flags)
waitpid_state_init(&waitpid_state, pid, flags);
waitpid_state.ec = GET_EC();
- if (WAITPID_USE_SIGCHLD) {
- waitpid_wait(&waitpid_state);
- }
- else {
- waitpid_no_SIGCHLD(&waitpid_state);
- }
+#if WAITPID_USE_SIGCHLD
+ waitpid_wait(&waitpid_state);
+#else
+ waitpid_no_SIGCHLD(&waitpid_state);
+#endif
if (waitpid_state.ret == 0) return Qnil;
@@ -1436,7 +1444,7 @@ 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);
+ struct rb_process_status *data = rb_check_typeddata(status, &rb_process_status_type);
pid = data->pid;
if (st) *st = data->status;
@@ -1601,14 +1609,14 @@ proc_waitall(VALUE _)
rb_last_status_clear();
for (pid = -1;;) {
- pid = rb_waitpid(-1, &status, 0);
- if (pid == -1) {
- int e = errno;
- if (e == ECHILD)
- break;
- rb_syserr_fail(e, 0);
- }
- rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
+ pid = rb_waitpid(-1, &status, 0);
+ if (pid == -1) {
+ int e = errno;
+ if (e == ECHILD)
+ break;
+ rb_syserr_fail(e, 0);
+ }
+ rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
}
return result;
}
@@ -1628,7 +1636,7 @@ detach_process_watcher(void *arg)
int status;
while ((cpid = rb_waitpid(pid, &status, 0)) == 0) {
- /* wait while alive */
+ /* wait while alive */
}
return rb_last_status_get();
}
@@ -1786,7 +1794,6 @@ before_fork_ruby(void)
static void
after_fork_ruby(void)
{
- rb_threadptr_pending_interrupt_clear(GET_THREAD());
after_exec();
}
#endif
@@ -1823,7 +1830,7 @@ proc_exec_cmd(const char *prog, VALUE argv_str, VALUE envp_str)
argv = ARGVSTR2ARGV(argv_str);
if (!prog) {
- return ENOENT;
+ return ENOENT;
}
#ifdef _WIN32
@@ -1849,7 +1856,7 @@ proc_exec_sh(const char *str, VALUE envp_str)
s = str;
while (*s == ' ' || *s == '\t' || *s == '\n')
- s++;
+ s++;
if (!*s) {
return ENOENT;
@@ -1965,19 +1972,19 @@ proc_spawn_cmd_internal(char **argv, char *prog)
rb_pid_t status;
if (!prog)
- prog = argv[0];
+ prog = argv[0];
prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
if (!prog)
- return -1;
+ return -1;
before_exec();
status = spawnv(P_NOWAIT, prog, (const char **)argv);
if (status == -1 && errno == ENOEXEC) {
- *argv = (char *)prog;
- *--argv = (char *)"sh";
- status = spawnv(P_NOWAIT, "/bin/sh", (const char **)argv);
- after_exec();
- if (status == -1) errno = ENOEXEC;
+ *argv = (char *)prog;
+ *--argv = (char *)"sh";
+ status = spawnv(P_NOWAIT, "/bin/sh", (const char **)argv);
+ after_exec();
+ if (status == -1) errno = ENOEXEC;
}
return status;
}
@@ -1990,13 +1997,13 @@ proc_spawn_cmd(char **argv, VALUE prog, struct rb_execarg *eargp)
if (argv[0]) {
#if defined(_WIN32)
- DWORD flags = 0;
- if (eargp->new_pgroup_given && eargp->new_pgroup_flag) {
- flags = CREATE_NEW_PROCESS_GROUP;
- }
- pid = rb_w32_uaspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, argv, flags);
+ DWORD flags = 0;
+ if (eargp->new_pgroup_given && eargp->new_pgroup_flag) {
+ flags = CREATE_NEW_PROCESS_GROUP;
+ }
+ pid = rb_w32_uaspawn_flags(P_NOWAIT, prog ? RSTRING_PTR(prog) : 0, argv, flags);
#else
- pid = proc_spawn_cmd_internal(argv, prog ? RSTRING_PTR(prog) : 0);
+ pid = proc_spawn_cmd_internal(argv, prog ? RSTRING_PTR(prog) : 0);
#endif
}
return pid;
@@ -2166,18 +2173,18 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
if (FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2))
flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
else if (RB_TYPE_P(key, T_ARRAY)) {
- int i;
- for (i = 0; i < RARRAY_LEN(key); i++) {
+ int i;
+ for (i = 0; i < RARRAY_LEN(key); i++) {
VALUE v = RARRAY_AREF(key, i);
- VALUE fd = check_exec_redirect_fd(v, 1);
- if (FIX2INT(fd) != 1 && FIX2INT(fd) != 2) break;
- }
- if (i == RARRAY_LEN(key))
- flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
- else
- flags = INT2NUM(O_RDONLY);
- }
- else
+ VALUE fd = check_exec_redirect_fd(v, 1);
+ if (FIX2INT(fd) != 1 && FIX2INT(fd) != 2) break;
+ }
+ if (i == RARRAY_LEN(key))
+ flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
+ else
+ flags = INT2NUM(O_RDONLY);
+ }
+ else
flags = INT2NUM(O_RDONLY);
perm = INT2FIX(0644);
param = hide_obj(rb_ary_new3(4, hide_obj(EXPORT_DUP(path)),
@@ -2186,9 +2193,9 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
break;
default:
- tmp = val;
- val = rb_io_check_io(tmp);
- if (!NIL_P(val)) goto io;
+ tmp = val;
+ val = rb_io_check_io(tmp);
+ if (!NIL_P(val)) goto io;
rb_raise(rb_eArgError, "wrong exec redirect action");
}
@@ -2203,30 +2210,30 @@ rb_execarg_addopt_rlimit(struct rb_execarg *eargp, int rtype, VALUE val)
VALUE ary = eargp->rlimit_limits;
VALUE tmp, softlim, hardlim;
if (eargp->rlimit_limits == Qfalse)
- ary = eargp->rlimit_limits = hide_obj(rb_ary_new());
+ ary = eargp->rlimit_limits = hide_obj(rb_ary_new());
else
- ary = eargp->rlimit_limits;
+ ary = eargp->rlimit_limits;
tmp = rb_check_array_type(val);
if (!NIL_P(tmp)) {
- if (RARRAY_LEN(tmp) == 1)
- softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
- else if (RARRAY_LEN(tmp) == 2) {
- softlim = rb_to_int(rb_ary_entry(tmp, 0));
- hardlim = rb_to_int(rb_ary_entry(tmp, 1));
- }
- else {
- rb_raise(rb_eArgError, "wrong exec rlimit option");
- }
+ if (RARRAY_LEN(tmp) == 1)
+ softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0));
+ else if (RARRAY_LEN(tmp) == 2) {
+ softlim = rb_to_int(rb_ary_entry(tmp, 0));
+ hardlim = rb_to_int(rb_ary_entry(tmp, 1));
+ }
+ else {
+ rb_raise(rb_eArgError, "wrong exec rlimit option");
+ }
}
else {
- softlim = hardlim = rb_to_int(val);
+ softlim = hardlim = rb_to_int(val);
}
tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim));
rb_ary_push(ary, tmp);
}
#endif
-#define TO_BOOL(val, name) NIL_P(val) ? 0 : rb_bool_expected((val), name)
+#define TO_BOOL(val, name) (NIL_P(val) ? 0 : rb_bool_expected((val), name, TRUE))
int
rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
{
@@ -2290,12 +2297,12 @@ rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
rb_raise(rb_eArgError, "chdir option specified twice");
}
FilePathValue(val);
- val = rb_str_encode_ospath(val);
+ val = rb_str_encode_ospath(val);
eargp->chdir_given = 1;
eargp->chdir_dir = hide_obj(EXPORT_DUP(val));
}
else if (id == id_umask) {
- mode_t cmask = NUM2MODET(val);
+ mode_t cmask = NUM2MODET(val);
if (eargp->umask_given) {
rb_raise(rb_eArgError, "umask option specified twice");
}
@@ -2321,36 +2328,36 @@ rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
key = INT2FIX(2);
goto redirect;
}
- else if (id == id_uid) {
+ else if (id == id_uid) {
#ifdef HAVE_SETUID
- if (eargp->uid_given) {
- rb_raise(rb_eArgError, "uid option specified twice");
- }
- check_uid_switch();
- {
- eargp->uid = OBJ2UID(val);
- eargp->uid_given = 1;
- }
+ if (eargp->uid_given) {
+ rb_raise(rb_eArgError, "uid option specified twice");
+ }
+ check_uid_switch();
+ {
+ eargp->uid = OBJ2UID(val);
+ eargp->uid_given = 1;
+ }
#else
- rb_raise(rb_eNotImpError,
- "uid option is unimplemented on this machine");
+ rb_raise(rb_eNotImpError,
+ "uid option is unimplemented on this machine");
#endif
- }
- else if (id == id_gid) {
+ }
+ else if (id == id_gid) {
#ifdef HAVE_SETGID
- if (eargp->gid_given) {
- rb_raise(rb_eArgError, "gid option specified twice");
- }
- check_gid_switch();
- {
- eargp->gid = OBJ2GID(val);
- eargp->gid_given = 1;
- }
+ if (eargp->gid_given) {
+ rb_raise(rb_eArgError, "gid option specified twice");
+ }
+ check_gid_switch();
+ {
+ eargp->gid = OBJ2GID(val);
+ eargp->gid_given = 1;
+ }
#else
- rb_raise(rb_eNotImpError,
- "gid option is unimplemented on this machine");
+ rb_raise(rb_eNotImpError,
+ "gid option is unimplemented on this machine");
#endif
- }
+ }
else if (id == id_exception) {
if (eargp->exception_given) {
rb_raise(rb_eArgError, "exception option specified twice");
@@ -2359,7 +2366,7 @@ rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
eargp->exception = TO_BOOL(val, "exception");
}
else {
- return ST_STOP;
+ return ST_STOP;
}
break;
@@ -2371,7 +2378,7 @@ redirect:
break;
default:
- return ST_STOP;
+ return ST_STOP;
}
RB_GC_GUARD(execarg_obj);
@@ -2385,10 +2392,10 @@ check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
VALUE val = (VALUE)st_val;
VALUE execarg_obj = (VALUE)arg;
if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
- if (SYMBOL_P(key))
- rb_raise(rb_eArgError, "wrong exec option symbol: % "PRIsVALUE,
- key);
- rb_raise(rb_eArgError, "wrong exec option");
+ if (SYMBOL_P(key))
+ rb_raise(rb_eArgError, "wrong exec option symbol: % "PRIsVALUE,
+ key);
+ rb_raise(rb_eArgError, "wrong exec option");
}
return ST_CONTINUE;
}
@@ -2401,9 +2408,9 @@ check_exec_options_i_extract(st_data_t st_key, st_data_t st_val, st_data_t arg)
VALUE *args = (VALUE *)arg;
VALUE execarg_obj = args[0];
if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) {
- VALUE nonopts = args[1];
- if (NIL_P(nonopts)) args[1] = nonopts = rb_hash_new();
- rb_hash_aset(nonopts, key, val);
+ VALUE nonopts = args[1];
+ if (NIL_P(nonopts)) args[1] = nonopts = rb_hash_new();
+ rb_hash_aset(nonopts, key, val);
}
return ST_CONTINUE;
}
@@ -2531,7 +2538,7 @@ check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
if (!NIL_P(val)) val = EXPORT_STR(val);
if (ENVMATCH(k, PATH_ENV)) {
- *path = val;
+ *path = val;
}
rb_ary_push(env, hide_obj(rb_assoc_new(key, val)));
@@ -2562,19 +2569,19 @@ rb_check_argv(int argc, VALUE *argv)
prog = 0;
tmp = rb_check_array_type(argv[0]);
if (!NIL_P(tmp)) {
- if (RARRAY_LEN(tmp) != 2) {
- rb_raise(rb_eArgError, "wrong first argument");
- }
- prog = RARRAY_AREF(tmp, 0);
- argv[0] = RARRAY_AREF(tmp, 1);
- SafeStringValue(prog);
- StringValueCStr(prog);
- prog = rb_str_new_frozen(prog);
+ if (RARRAY_LEN(tmp) != 2) {
+ rb_raise(rb_eArgError, "wrong first argument");
+ }
+ prog = RARRAY_AREF(tmp, 0);
+ argv[0] = RARRAY_AREF(tmp, 1);
+ SafeStringValue(prog);
+ StringValueCStr(prog);
+ prog = rb_str_new_frozen(prog);
}
for (i = 0; i < argc; i++) {
- SafeStringValue(argv[i]);
- argv[i] = rb_str_new_frozen(argv[i]);
- StringValueCStr(argv[i]);
+ SafeStringValue(argv[i]);
+ argv[i] = rb_str_new_frozen(argv[i]);
+ StringValueCStr(argv[i]);
}
return prog;
}
@@ -2586,7 +2593,7 @@ check_hash(VALUE obj)
switch (RB_BUILTIN_TYPE(obj)) {
case T_STRING:
case T_ARRAY:
- return Qnil;
+ return Qnil;
default:
break;
}
@@ -2666,39 +2673,39 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VAL
#ifndef _WIN32
if (eargp->use_shell) {
- static const char posix_sh_cmds[][9] = {
- "!", /* reserved */
- ".", /* special built-in */
- ":", /* special built-in */
- "break", /* special built-in */
- "case", /* reserved */
- "continue", /* special built-in */
- "do", /* reserved */
- "done", /* reserved */
- "elif", /* reserved */
- "else", /* reserved */
- "esac", /* reserved */
- "eval", /* special built-in */
- "exec", /* special built-in */
- "exit", /* special built-in */
- "export", /* special built-in */
- "fi", /* reserved */
- "for", /* reserved */
- "if", /* reserved */
- "in", /* reserved */
- "readonly", /* special built-in */
- "return", /* special built-in */
- "set", /* special built-in */
- "shift", /* special built-in */
- "then", /* reserved */
- "times", /* special built-in */
- "trap", /* special built-in */
- "unset", /* special built-in */
- "until", /* reserved */
- "while", /* reserved */
- };
- const char *p;
- struct string_part first = {0, 0};
+ static const char posix_sh_cmds[][9] = {
+ "!", /* reserved */
+ ".", /* special built-in */
+ ":", /* special built-in */
+ "break", /* special built-in */
+ "case", /* reserved */
+ "continue", /* special built-in */
+ "do", /* reserved */
+ "done", /* reserved */
+ "elif", /* reserved */
+ "else", /* reserved */
+ "esac", /* reserved */
+ "eval", /* special built-in */
+ "exec", /* special built-in */
+ "exit", /* special built-in */
+ "export", /* special built-in */
+ "fi", /* reserved */
+ "for", /* reserved */
+ "if", /* reserved */
+ "in", /* reserved */
+ "readonly", /* special built-in */
+ "return", /* special built-in */
+ "set", /* special built-in */
+ "shift", /* special built-in */
+ "then", /* reserved */
+ "times", /* special built-in */
+ "trap", /* special built-in */
+ "unset", /* special built-in */
+ "until", /* reserved */
+ "while", /* reserved */
+ };
+ const char *p;
+ struct string_part first = {0, 0};
int has_meta = 0;
/*
* meta characters:
@@ -2725,32 +2732,32 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VAL
* % (used in Parameter Expansion)
*/
for (p = RSTRING_PTR(prog); *p; p++) {
- if (*p == ' ' || *p == '\t') {
- if (first.ptr && !first.len) first.len = p - first.ptr;
- }
- else {
- if (!first.ptr) first.ptr = p;
- }
+ if (*p == ' ' || *p == '\t') {
+ if (first.ptr && !first.len) first.len = p - first.ptr;
+ }
+ else {
+ if (!first.ptr) first.ptr = p;
+ }
if (!has_meta && strchr("*?{}[]<>()~&|\\$;'`\"\n#", *p))
has_meta = 1;
- if (!first.len) {
- if (*p == '=') {
- has_meta = 1;
- }
- else if (*p == '/') {
- first.len = 0x100; /* longer than any posix_sh_cmds */
- }
- }
- if (has_meta)
+ if (!first.len) {
+ if (*p == '=') {
+ has_meta = 1;
+ }
+ else if (*p == '/') {
+ first.len = 0x100; /* longer than any posix_sh_cmds */
+ }
+ }
+ if (has_meta)
break;
}
- if (!has_meta && first.ptr) {
- if (!first.len) first.len = p - first.ptr;
- if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) &&
- bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh))
- has_meta = 1;
- }
- if (!has_meta) {
+ if (!has_meta && first.ptr) {
+ if (!first.len) first.len = p - first.ptr;
+ if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) &&
+ bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh))
+ has_meta = 1;
+ }
+ if (!has_meta) {
/* avoid shell since no shell meta character found. */
eargp->use_shell = 0;
}
@@ -2762,7 +2769,7 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VAL
while (*p == ' ' || *p == '\t')
p++;
if (*p) {
- const char *w = p;
+ const char *w = p;
while (*p && *p != ' ' && *p != '\t')
p++;
rb_str_buf_cat(argv_buf, w, p-w);
@@ -2778,15 +2785,15 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VAL
#endif
if (!eargp->use_shell) {
- const char *abspath;
- const char *path_env = 0;
- if (RTEST(eargp->path_env)) path_env = RSTRING_PTR(eargp->path_env);
- abspath = dln_find_exe_r(RSTRING_PTR(eargp->invoke.cmd.command_name),
- path_env, fbuf, sizeof(fbuf));
- if (abspath)
- eargp->invoke.cmd.command_abspath = rb_str_new_cstr(abspath);
- else
- eargp->invoke.cmd.command_abspath = Qnil;
+ const char *abspath;
+ const char *path_env = 0;
+ if (RTEST(eargp->path_env)) path_env = RSTRING_PTR(eargp->path_env);
+ abspath = dln_find_exe_r(RSTRING_PTR(eargp->invoke.cmd.command_name),
+ path_env, fbuf, sizeof(fbuf));
+ if (abspath)
+ eargp->invoke.cmd.command_abspath = rb_str_new_cstr(abspath);
+ else
+ eargp->invoke.cmd.command_abspath = Qnil;
}
if (!eargp->use_shell && !eargp->invoke.cmd.argv_buf) {
@@ -2795,13 +2802,13 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VAL
argv_buf = rb_str_buf_new(0);
hide_obj(argv_buf);
for (i = 0; i < argc; i++) {
- VALUE arg = argv[i];
- const char *s = StringValueCStr(arg);
+ VALUE arg = argv[i];
+ const char *s = StringValueCStr(arg);
#ifdef DEFAULT_PROCESS_ENCODING
- arg = EXPORT_STR(arg);
- s = RSTRING_PTR(arg);
+ arg = EXPORT_STR(arg);
+ s = RSTRING_PTR(arg);
#endif
- rb_str_buf_cat(argv_buf, s, RSTRING_LEN(arg) + 1); /* include '\0' */
+ rb_str_buf_cat(argv_buf, s, RSTRING_LEN(arg) + 1); /* include '\0' */
}
eargp->invoke.cmd.argv_buf = argv_buf;
}
@@ -2978,25 +2985,24 @@ rb_execarg_parent_start1(VALUE execarg_obj)
envtbl = rb_hash_new();
}
else {
- envtbl = rb_const_get(rb_cObject, id_ENV);
- envtbl = rb_to_hash_type(envtbl);
+ envtbl = rb_env_to_hash();
}
hide_obj(envtbl);
if (envopts != Qfalse) {
- st_table *stenv = RHASH_TBL_RAW(envtbl);
+ st_table *stenv = RHASH_TBL_RAW(envtbl);
long i;
for (i = 0; i < RARRAY_LEN(envopts); i++) {
VALUE pair = RARRAY_AREF(envopts, i);
VALUE key = RARRAY_AREF(pair, 0);
VALUE val = RARRAY_AREF(pair, 1);
if (NIL_P(val)) {
- st_data_t stkey = (st_data_t)key;
- st_delete(stenv, &stkey, NULL);
+ st_data_t stkey = (st_data_t)key;
+ st_delete(stenv, &stkey, NULL);
}
else {
- st_insert(stenv, (st_data_t)key, (st_data_t)val);
- RB_OBJ_WRITTEN(envtbl, Qundef, key);
- RB_OBJ_WRITTEN(envtbl, Qundef, val);
+ st_insert(stenv, (st_data_t)key, (st_data_t)val);
+ RB_OBJ_WRITTEN(envtbl, Qundef, key);
+ RB_OBJ_WRITTEN(envtbl, Qundef, val);
}
}
}
@@ -3081,7 +3087,7 @@ rb_exec_fail(struct rb_execarg *eargp, int err, const char *errmsg)
{
if (!errmsg || !*errmsg) return;
if (strcmp(errmsg, "chdir") == 0) {
- rb_sys_fail_str(eargp->chdir_dir);
+ rb_sys_fail_str(eargp->chdir_dir);
}
rb_sys_fail(errmsg);
}
@@ -3142,7 +3148,7 @@ NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _));
* [<code>exec(cmdname, arg1, ...)</code>]
* command name and one or more arguments (no shell)
* [<code>exec([cmdname, argv0], arg1, ...)</code>]
- * command name, argv[0] and zero or more arguments (no shell)
+ * command name, +argv[0]+ and zero or more arguments (no shell)
*
* In the first form, the string is taken as a command line that is subject to
* shell expansion before being executed.
@@ -3155,9 +3161,10 @@ NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _));
* If the string from the first form (<code>exec("command")</code>) follows
* these simple rules:
*
- * * no meta characters
- * * not starting with shell reserved word or special built-in
- * * Ruby invokes the command directly without shell
+ * * no meta characters,
+ * * not starting with shell reserved word or special built-in,
+ *
+ * Ruby invokes the command directly without shell.
*
* You can force shell invocation by adding ";" to the string (because ";" is
* a meta character).
@@ -3237,10 +3244,10 @@ save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_b
newary = hide_obj(rb_ary_new());
sargp->fd_dup2 = newary;
}
- cloexec = fd_get_cloexec(fd, errmsg, errmsg_buflen);
- redirection = hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd)));
- if (cloexec) rb_ary_push(redirection, Qtrue);
- rb_ary_push(newary, redirection);
+ cloexec = fd_get_cloexec(fd, errmsg, errmsg_buflen);
+ redirection = hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd)));
+ if (cloexec) rb_ary_push(redirection, Qtrue);
+ rb_ary_push(newary, redirection);
newary = sargp->fd_close;
if (newary == Qfalse) {
@@ -3397,10 +3404,10 @@ run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, s
ERRMSG("dup2");
goto fail;
}
- if (pairs[j].cloexec &&
- fd_set_cloexec(pairs[j].newfd, errmsg, errmsg_buflen)) {
- goto fail;
- }
+ if (pairs[j].cloexec &&
+ fd_set_cloexec(pairs[j].newfd, errmsg, errmsg_buflen)) {
+ goto fail;
+ }
rb_update_max_fd(pairs[j].newfd); /* async-signal-safe but don't need to call it in a child process. */
pairs[j].oldfd = -1;
j = pairs[j].older_index;
@@ -3591,7 +3598,7 @@ save_env(struct rb_execarg *sargp)
if (!sargp)
return;
if (sargp->env_modification == Qfalse) {
- VALUE env = rb_const_get(rb_cObject, id_ENV);
+ VALUE env = rb_envtbl();
if (RTEST(env)) {
VALUE ary = hide_obj(rb_ary_new());
rb_block_call(env, idEach, 0, 0, save_env_i,
@@ -3708,18 +3715,18 @@ rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp,
#ifdef HAVE_SETGID
if (eargp->gid_given) {
- if (setgid(eargp->gid) < 0) {
- ERRMSG("setgid");
- return -1;
- }
+ if (setgid(eargp->gid) < 0) {
+ ERRMSG("setgid");
+ return -1;
+ }
}
#endif
#ifdef HAVE_SETUID
if (eargp->uid_given) {
- if (setuid(eargp->uid) < 0) {
- ERRMSG("setuid");
- return -1;
- }
+ if (setuid(eargp->uid) < 0) {
+ ERRMSG("setuid");
+ return -1;
+ }
}
#endif
@@ -3757,17 +3764,17 @@ exec_async_signal_safe(const struct rb_execarg *eargp, char *errmsg, size_t errm
int err;
if (rb_execarg_run_options(eargp, sargp, errmsg, errmsg_buflen) < 0) { /* hopefully async-signal-safe */
- return errno;
+ return errno;
}
if (eargp->use_shell) {
- err = proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */
+ err = proc_exec_sh(RSTRING_PTR(eargp->invoke.sh.shell_script), eargp->envp_str); /* async-signal-safe */
}
else {
- char *abspath = NULL;
- if (!NIL_P(eargp->invoke.cmd.command_abspath))
- abspath = RSTRING_PTR(eargp->invoke.cmd.command_abspath);
- err = proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */
+ char *abspath = NULL;
+ if (!NIL_P(eargp->invoke.cmd.command_abspath))
+ abspath = RSTRING_PTR(eargp->invoke.cmd.command_abspath);
+ err = proc_exec_cmd(abspath, eargp->invoke.cmd.argv_str, eargp->envp_str); /* async-signal-safe */
}
#if !defined(HAVE_WORKING_FORK)
rb_execarg_run_options(sargp, NULL, errmsg, errmsg_buflen);
@@ -3784,16 +3791,12 @@ rb_exec_atfork(void* arg, char *errmsg, size_t errmsg_buflen)
return rb_exec_async_signal_safe(arg, errmsg, errmsg_buflen); /* hopefully async-signal-safe */
}
-#if SIZEOF_INT == SIZEOF_LONG
-#define proc_syswait (VALUE (*)(VALUE))rb_syswait
-#else
static VALUE
proc_syswait(VALUE pid)
{
- rb_syswait((int)pid);
+ rb_syswait((rb_pid_t)pid);
return Qnil;
}
-#endif
static int
move_fds_to_avoid_crash(int *fdp, int n, VALUE fds)
@@ -3849,7 +3852,7 @@ rb_thread_sleep_that_takes_VALUE_as_sole_argument(VALUE n)
}
static int
-handle_fork_error(int err, int *status, int *ep, volatile int *try_gc_p)
+handle_fork_error(int err, struct rb_process_status *status, int *ep, volatile int *try_gc_p)
{
int state = 0;
@@ -3870,24 +3873,24 @@ handle_fork_error(int err, int *status, int *ep, volatile int *try_gc_p)
}
else {
rb_protect(rb_thread_sleep_that_takes_VALUE_as_sole_argument, INT2FIX(1), &state);
- if (status) *status = state;
+ if (status) status->status = state;
if (!state) return 0;
}
break;
}
if (ep) {
- close(ep[0]);
- close(ep[1]);
- errno = err;
+ close(ep[0]);
+ close(ep[1]);
+ errno = err;
}
if (state && !status) rb_jump_tag(state);
return -1;
}
#define prefork() ( \
- rb_io_flush(rb_stdout), \
- rb_io_flush(rb_stderr) \
- )
+ rb_io_flush(rb_stdout), \
+ rb_io_flush(rb_stderr) \
+ )
/*
* Forks child process, and returns the process ID in the parent
@@ -3921,7 +3924,7 @@ write_retry(int fd, const void *buf, size_t len)
ssize_t w;
do {
- w = write(fd, buf, len);
+ w = write(fd, buf, len);
} while (w < 0 && errno == EINTR);
return w;
@@ -3939,7 +3942,7 @@ read_retry(int fd, void *buf, size_t len)
}
do {
- r = read(fd, buf, len);
+ r = read(fd, buf, len);
} while (r < 0 && errno == EINTR);
return r;
@@ -3992,7 +3995,7 @@ getresuid(rb_uid_t *ruid, rb_uid_t *euid, rb_uid_t *suid)
*euid = geteuid();
ret = getuidx(ID_SAVED);
if (ret == (rb_uid_t)-1)
- return -1;
+ return -1;
*suid = ret;
return 0;
}
@@ -4010,7 +4013,7 @@ getresgid(rb_gid_t *rgid, rb_gid_t *egid, rb_gid_t *sgid)
*egid = getegid();
ret = getgidx(ID_SAVED);
if (ret == (rb_gid_t)-1)
- return -1;
+ return -1;
*sgid = ret;
return 0;
}
@@ -4037,7 +4040,7 @@ has_privilege(void)
#if defined HAVE_ISSETUGID
if (issetugid())
- return 1;
+ return 1;
#endif
#ifdef HAVE_GETRESUID
@@ -4088,17 +4091,17 @@ struct child_handler_disabler_state
static void
disable_child_handler_before_fork(struct child_handler_disabler_state *old)
{
+#ifdef HAVE_PTHREAD_SIGMASK
int ret;
sigset_t all;
-#ifdef HAVE_PTHREAD_SIGMASK
ret = sigfillset(&all);
if (ret == -1)
rb_sys_fail("sigfillset");
ret = pthread_sigmask(SIG_SETMASK, &all, &old->sigmask); /* not async-signal-safe */
if (ret != 0) {
- rb_syserr_fail(ret, "pthread_sigmask");
+ rb_syserr_fail(ret, "pthread_sigmask");
}
#else
# pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
@@ -4108,12 +4111,12 @@ disable_child_handler_before_fork(struct child_handler_disabler_state *old)
static void
disable_child_handler_fork_parent(struct child_handler_disabler_state *old)
{
+#ifdef HAVE_PTHREAD_SIGMASK
int ret;
-#ifdef HAVE_PTHREAD_SIGMASK
ret = pthread_sigmask(SIG_SETMASK, &old->sigmask, NULL); /* not async-signal-safe */
if (ret != 0) {
- rb_syserr_fail(ret, "pthread_sigmask");
+ rb_syserr_fail(ret, "pthread_sigmask");
}
#else
# pragma GCC warning "pthread_sigmask on fork is not available. potentially dangerous"
@@ -4128,24 +4131,24 @@ disable_child_handler_fork_child(struct child_handler_disabler_state *old, char
int ret;
for (sig = 1; sig < NSIG; sig++) {
- sig_t handler = signal(sig, SIG_DFL);
-
- if (handler == SIG_ERR && errno == EINVAL) {
- continue; /* Ignore invalid signal number */
- }
- if (handler == SIG_ERR) {
- ERRMSG("signal to obtain old action");
- return -1;
- }
+ sig_t handler = signal(sig, SIG_DFL);
+
+ if (handler == SIG_ERR && errno == EINVAL) {
+ continue; /* Ignore invalid signal number */
+ }
+ if (handler == SIG_ERR) {
+ ERRMSG("signal to obtain old action");
+ return -1;
+ }
#ifdef SIGPIPE
- if (sig == SIGPIPE) {
- continue;
- }
+ if (sig == SIGPIPE) {
+ continue;
+ }
#endif
- /* it will be reset to SIG_DFL at execve time, instead */
- if (handler == SIG_IGN) {
- signal(sig, SIG_IGN);
- }
+ /* it will be reset to SIG_DFL at execve time, instead */
+ if (handler == SIG_IGN) {
+ signal(sig, SIG_IGN);
+ }
}
/* non-Ruby child process, ensure cmake can see SIGCHLD */
@@ -4159,7 +4162,7 @@ disable_child_handler_fork_child(struct child_handler_disabler_state *old, char
}
static rb_pid_t
-retry_fork_async_signal_safe(int *status, int *ep,
+retry_fork_async_signal_safe(struct rb_process_status *status, int *ep,
int (*chfunc)(void*, char *, size_t), void *charg,
char *errmsg, size_t errmsg_buflen,
struct waitpid_state *w)
@@ -4201,26 +4204,50 @@ retry_fork_async_signal_safe(int *status, int *ep,
_exit(127);
#endif
}
- err = errno;
+ err = errno;
waitpid_lock = waitpid_lock_init;
if (waitpid_lock) {
if (pid > 0 && w != WAITPID_LOCK_ONLY) {
w->pid = pid;
- list_add(&GET_VM()->waiting_pids, &w->wnode);
+ ccan_list_add(&GET_VM()->waiting_pids, &w->wnode);
}
rb_native_mutex_unlock(waitpid_lock);
}
- disable_child_handler_fork_parent(&old);
+ disable_child_handler_fork_parent(&old);
if (0 < pid) /* fork succeed, parent process */
return pid;
/* fork failed */
- if (handle_fork_error(err, status, ep, &try_gc))
+ if (handle_fork_error(err, status, ep, &try_gc))
return -1;
}
}
+#if USE_MJIT
+// This is used to create MJIT's child Ruby process
+pid_t
+rb_mjit_fork(void)
+{
+ struct child_handler_disabler_state old;
+ rb_vm_t *vm = GET_VM();
+ prefork();
+ disable_child_handler_before_fork(&old);
+ before_fork_ruby();
+
+ rb_native_mutex_lock(&vm->waitpid_lock);
+ pid_t pid = rb_fork();
+ if (pid > 0) mjit_add_waiting_pid(vm, pid);
+ rb_native_mutex_unlock(&vm->waitpid_lock);
+
+ after_fork_ruby();
+ disable_child_handler_fork_parent(&old);
+ if (pid == 0) rb_thread_atfork();
+
+ return pid;
+}
+#endif
+
static rb_pid_t
-fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg,
+fork_check_err(struct rb_process_status *status, int (*chfunc)(void*, char *, size_t), void *charg,
VALUE fds, char *errmsg, size_t errmsg_buflen,
struct rb_execarg *eargp)
{
@@ -4228,31 +4255,46 @@ fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg,
int err;
int ep[2];
int error_occurred;
- struct waitpid_state *w;
- w = eargp && eargp->waitpid_state ? eargp->waitpid_state : 0;
+ struct waitpid_state *w = eargp && eargp->waitpid_state ? eargp->waitpid_state : 0;
- if (status) *status = 0;
+ if (status) status->status = 0;
if (pipe_nocrash(ep, fds)) return -1;
- pid = retry_fork_async_signal_safe(status, ep, chfunc, charg,
- errmsg, errmsg_buflen, w);
- if (pid < 0)
+
+ pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, errmsg, errmsg_buflen, w);
+
+ if (status) status->pid = pid;
+
+ if (pid < 0) {
+ if (status) status->error = errno;
+
return pid;
+ }
+
close(ep[1]);
+
error_occurred = recv_child_error(ep[0], &err, errmsg, errmsg_buflen);
+
if (error_occurred) {
if (status) {
+ int state = 0;
+ status->error = err;
+
VM_ASSERT((w == 0 || w == WAITPID_LOCK_ONLY) &&
"only used by extensions");
- rb_protect(proc_syswait, (VALUE)pid, status);
+ rb_protect(proc_syswait, (VALUE)pid, &state);
+
+ status->status = state;
}
else if (!w || w == WAITPID_LOCK_ONLY) {
rb_syswait(pid);
}
+
errno = err;
return -1;
}
+
return pid;
}
@@ -4268,43 +4310,122 @@ rb_fork_async_signal_safe(int *status,
int (*chfunc)(void*, char *, size_t), void *charg,
VALUE fds, char *errmsg, size_t errmsg_buflen)
{
- return fork_check_err(status, chfunc, charg, fds, errmsg, errmsg_buflen, 0);
+ struct rb_process_status process_status;
+
+ rb_pid_t result = fork_check_err(&process_status, chfunc, charg, fds, errmsg, errmsg_buflen, 0);
+
+ if (status) {
+ *status = process_status.status;
+ }
+
+ return result;
}
-rb_pid_t
-rb_fork_ruby(int *status)
+static rb_pid_t
+rb_fork_ruby2(struct rb_process_status *status)
{
rb_pid_t pid;
int try_gc = 1, err;
struct child_handler_disabler_state old;
- if (status) *status = 0;
+ if (status) status->status = 0;
while (1) {
- prefork();
+ prefork();
if (mjit_enabled) mjit_pause(false); // Don't leave locked mutex to child. Note: child_handler must be enabled to pause MJIT.
- disable_child_handler_before_fork(&old);
- before_fork_ruby();
- pid = rb_fork();
- err = errno;
+ disable_child_handler_before_fork(&old);
+ before_fork_ruby();
+ pid = rb_fork();
+ err = errno;
+ if (status) {
+ status->pid = pid;
+ status->error = err;
+ }
after_fork_ruby();
- disable_child_handler_fork_parent(&old); /* yes, bad name */
+ disable_child_handler_fork_parent(&old); /* yes, bad name */
+
if (mjit_enabled && pid > 0) mjit_resume(); /* child (pid == 0) is cared by rb_thread_atfork */
- if (pid >= 0) { /* fork succeed */
+
+ if (pid >= 0) { /* fork succeed */
if (pid == 0) rb_thread_atfork();
- return pid;
+ return pid;
+ }
+
+ /* fork failed */
+ if (handle_fork_error(err, status, NULL, &try_gc)) {
+ return -1;
}
- /* fork failed */
- if (handle_fork_error(err, status, NULL, &try_gc))
- return -1;
}
}
+rb_pid_t
+rb_fork_ruby(int *status)
+{
+ struct rb_process_status process_status = {0};
+
+ rb_pid_t pid = rb_fork_ruby2(&process_status);
+
+ if (status) *status = process_status.status;
+
+ return pid;
+}
+
+static rb_pid_t
+proc_fork_pid(void)
+{
+ rb_pid_t pid = rb_fork_ruby(NULL);
+
+ if (pid == -1) {
+ rb_sys_fail("fork(2)");
+ }
+
+ return pid;
+}
+
+rb_pid_t
+rb_call_proc__fork(void)
+{
+ ID id__fork;
+ CONST_ID(id__fork, "_fork");
+ if (rb_method_basic_definition_p(CLASS_OF(rb_mProcess), id__fork)) {
+ return proc_fork_pid();
+ }
+ else {
+ VALUE pid = rb_funcall(rb_mProcess, id__fork, 0);
+ return NUM2PIDT(pid);
+ }
+}
#endif
#if defined(HAVE_WORKING_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD)
/*
* call-seq:
+ * Process._fork -> integer
+ *
+ * An internal API for fork. Do not call this method directly.
+ * Currently, this is called via Kernel#fork, Process.fork, and
+ * IO.popen with <tt>"-"</tt>.
+ *
+ * This method is not for casual code but for application monitoring
+ * libraries. You can add custom code before and after fork events
+ * by overriding this method.
+ *
+ * Note: Process.daemon may be implemented using fork(2) BUT does not go
+ * through this method.
+ * Thus, depending on your reason to hook into this method, you
+ * may also want to hook into that one.
+ * See {this issue}[https://bugs.ruby-lang.org/issues/18911] for a
+ * more detailed discussion of this.
+ */
+VALUE
+rb_proc__fork(VALUE _obj)
+{
+ rb_pid_t pid = proc_fork_pid();
+ return PIDT2NUM(pid);
+}
+
+/*
+ * call-seq:
* Kernel.fork [{ block }] -> integer or nil
* Process.fork [{ block }] -> integer or nil
*
@@ -4333,24 +4454,21 @@ rb_f_fork(VALUE obj)
{
rb_pid_t pid;
- switch (pid = rb_fork_ruby(NULL)) {
- case 0:
- if (rb_block_given_p()) {
- int status;
- rb_protect(rb_yield, Qundef, &status);
- ruby_stop(status);
- }
- return Qnil;
-
- case -1:
- rb_sys_fail("fork(2)");
- return Qnil;
+ pid = rb_call_proc__fork();
- default:
- return PIDT2NUM(pid);
+ if (pid == 0) {
+ if (rb_block_given_p()) {
+ int status;
+ rb_protect(rb_yield, Qundef, &status);
+ ruby_stop(status);
+ }
+ return Qnil;
}
+
+ return PIDT2NUM(pid);
}
#else
+#define rb_proc__fork rb_f_notimplement
#define rb_f_fork rb_f_notimplement
#endif
@@ -4361,18 +4479,18 @@ exit_status_code(VALUE status)
switch (status) {
case Qtrue:
- istatus = EXIT_SUCCESS;
- break;
+ istatus = EXIT_SUCCESS;
+ break;
case Qfalse:
- istatus = EXIT_FAILURE;
- break;
+ istatus = EXIT_FAILURE;
+ break;
default:
- istatus = NUM2INT(status);
+ istatus = NUM2INT(status);
#if EXIT_SUCCESS != 0
- if (istatus == 0)
- istatus = EXIT_SUCCESS;
+ if (istatus == 0)
+ istatus = EXIT_SUCCESS;
#endif
- break;
+ break;
}
return istatus;
}
@@ -4395,10 +4513,10 @@ rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
int istatus;
if (rb_check_arity(argc, 0, 1) == 1) {
- istatus = exit_status_code(argv[0]);
+ istatus = exit_status_code(argv[0]);
}
else {
- istatus = EXIT_FAILURE;
+ istatus = EXIT_FAILURE;
}
_exit(istatus);
@@ -4409,11 +4527,11 @@ void
rb_exit(int status)
{
if (GET_EC()->tag) {
- VALUE args[2];
+ VALUE args[2];
- args[0] = INT2NUM(status);
- args[1] = rb_str_new2("exit");
- rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
+ args[0] = INT2NUM(status);
+ args[1] = rb_str_new2("exit");
+ rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
}
ruby_stop(status);
}
@@ -4488,21 +4606,21 @@ rb_f_abort(int argc, const VALUE *argv)
{
rb_check_arity(argc, 0, 1);
if (argc == 0) {
- rb_execution_context_t *ec = GET_EC();
+ rb_execution_context_t *ec = GET_EC();
VALUE errinfo = rb_ec_get_errinfo(ec);
- if (!NIL_P(errinfo)) {
- rb_ec_error_print(ec, errinfo);
- }
- rb_exit(EXIT_FAILURE);
+ if (!NIL_P(errinfo)) {
+ rb_ec_error_print(ec, errinfo);
+ }
+ rb_exit(EXIT_FAILURE);
}
else {
- VALUE args[2];
+ VALUE args[2];
- args[1] = args[0] = argv[0];
- StringValue(args[0]);
- rb_io_puts(1, args, rb_ractor_stderr());
- args[0] = INT2NUM(EXIT_FAILURE);
- rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
+ args[1] = args[0] = argv[0];
+ StringValue(args[0]);
+ rb_io_puts(1, args, rb_ractor_stderr());
+ args[0] = INT2NUM(EXIT_FAILURE);
+ rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
}
UNREACHABLE_RETURN(Qnil);
@@ -4536,24 +4654,24 @@ rb_syswait(rb_pid_t pid)
rb_waitpid(pid, &status, 0);
}
-#if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV
+#if !defined HAVE_WORKING_FORK && !defined HAVE_SPAWNV && !defined __EMSCRIPTEN__
char *
rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
{
VALUE cmd = *prog;
if (eargp && !eargp->use_shell) {
- VALUE str = eargp->invoke.cmd.argv_str;
- VALUE buf = eargp->invoke.cmd.argv_buf;
- char *p, **argv = ARGVSTR2ARGV(str);
- long i, argc = ARGVSTR2ARGC(str);
- const char *start = RSTRING_PTR(buf);
- cmd = rb_str_new(start, RSTRING_LEN(buf));
- p = RSTRING_PTR(cmd);
- for (i = 1; i < argc; ++i) {
- p[argv[i] - start - 1] = ' ';
- }
- *prog = cmd;
- return p;
+ VALUE str = eargp->invoke.cmd.argv_str;
+ VALUE buf = eargp->invoke.cmd.argv_buf;
+ char *p, **argv = ARGVSTR2ARGV(str);
+ long i, argc = ARGVSTR2ARGC(str);
+ const char *start = RSTRING_PTR(buf);
+ cmd = rb_str_new(start, RSTRING_LEN(buf));
+ p = RSTRING_PTR(cmd);
+ for (i = 1; i < argc; ++i) {
+ p[argv[i] - start - 1] = ' ';
+ }
+ *prog = cmd;
+ return p;
}
return StringValueCStr(*prog);
}
@@ -4572,7 +4690,7 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
#endif
#if defined HAVE_WORKING_FORK && !USE_SPAWNV
- pid = fork_check_err(0, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen, eargp);
+ pid = fork_check_err(eargp->status, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen, eargp);
#else
prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
@@ -4626,7 +4744,7 @@ do_spawn_process(VALUE arg)
struct spawn_args *argp = (struct spawn_args *)arg;
rb_execarg_parent_start1(argp->execarg);
return (VALUE)rb_spawn_process(DATA_PTR(argp->execarg),
- argp->errmsg.ptr, argp->errmsg.buflen);
+ argp->errmsg.ptr, argp->errmsg.buflen);
}
static rb_pid_t
@@ -4647,7 +4765,7 @@ rb_execarg_spawn(VALUE execarg_obj, char *errmsg, size_t errmsg_buflen)
args.errmsg.ptr = errmsg;
args.errmsg.buflen = errmsg_buflen;
return (rb_pid_t)rb_ensure(do_spawn_process, (VALUE)&args,
- execarg_parent_end, execarg_obj);
+ execarg_parent_end, execarg_obj);
}
static rb_pid_t
@@ -4678,6 +4796,9 @@ rb_spawn(int argc, const VALUE *argv)
* Executes _command..._ in a subshell.
* _command..._ is one of following forms.
*
+ * This method has potential security vulnerabilities if called with untrusted input;
+ * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ *
* [<code>commandline</code>]
* command line string which is passed to the standard shell
* [<code>cmdname, arg1, ...</code>]
@@ -4725,58 +4846,63 @@ rb_spawn(int argc, const VALUE *argv)
static VALUE
rb_f_system(int argc, VALUE *argv, VALUE _)
{
- /*
- * n.b. using alloca for now to simplify future Thread::Light code
- * when we need to use malloc for non-native Fiber
- */
- struct waitpid_state *w = alloca(sizeof(struct waitpid_state));
- rb_pid_t pid; /* may be different from waitpid_state.pid on exec failure */
- VALUE execarg_obj;
- struct rb_execarg *eargp;
- int exec_errnum;
+ VALUE execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
+ struct rb_execarg *eargp = rb_execarg_get(execarg_obj);
- execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE);
- eargp = rb_execarg_get(execarg_obj);
- w->ec = GET_EC();
- waitpid_state_init(w, 0, 0);
- eargp->waitpid_state = w;
- pid = rb_execarg_spawn(execarg_obj, 0, 0);
- exec_errnum = pid < 0 ? errno : 0;
+ struct rb_process_status status = {0};
+ eargp->status = &status;
-#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
- if (w->pid > 0) {
- /* `pid' (not w->pid) may be < 0 here if execve failed in child */
- if (WAITPID_USE_SIGCHLD) {
- rb_ensure(waitpid_sleep, (VALUE)w, waitpid_cleanup, (VALUE)w);
+ rb_last_status_clear();
+
+ // This function can set the thread's last status.
+ // May be different from waitpid_state.pid on exec failure.
+ rb_pid_t pid = rb_execarg_spawn(execarg_obj, 0, 0);
+
+ if (pid > 0) {
+ VALUE status = rb_process_status_wait(pid, 0);
+
+ struct rb_process_status *data = rb_check_typeddata(status, &rb_process_status_type);
+
+ // Set the last status:
+ rb_obj_freeze(status);
+ GET_THREAD()->last_status = status;
+
+ if (data->status == EXIT_SUCCESS) {
+ return Qtrue;
}
- else {
- waitpid_no_SIGCHLD(w);
+
+ if (data->error != 0) {
+ if (eargp->exception) {
+ VALUE command = eargp->invoke.sh.shell_script;
+ RB_GC_GUARD(execarg_obj);
+ rb_syserr_fail_str(data->error, command);
+ }
+ else {
+ return Qnil;
+ }
}
- rb_last_status_set(w->status, w->ret);
- }
-#endif
- if (w->pid < 0 /* fork failure */ || pid < 0 /* exec failure */) {
- if (eargp->exception) {
- int err = exec_errnum ? exec_errnum : w->errnum;
+ else if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
+ VALUE str = rb_str_new_cstr("Command failed with");
+ rb_str_cat_cstr(pst_message_status(str, data->status), ": ");
+ rb_str_append(str, command);
RB_GC_GUARD(execarg_obj);
- rb_syserr_fail_str(err, command);
+ rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str));
}
else {
- return Qnil;
+ return Qfalse;
}
+
+ RB_GC_GUARD(status);
}
- if (w->status == EXIT_SUCCESS) return Qtrue;
+
if (eargp->exception) {
VALUE command = eargp->invoke.sh.shell_script;
- VALUE str = rb_str_new_cstr("Command failed with");
- rb_str_cat_cstr(pst_message_status(str, w->status), ": ");
- rb_str_append(str, command);
RB_GC_GUARD(execarg_obj);
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str));
+ rb_syserr_fail_str(errno, command);
}
else {
- return Qfalse;
+ return Qnil;
}
}
@@ -5064,10 +5190,10 @@ rb_f_spawn(int argc, VALUE *argv, VALUE _)
pid = rb_execarg_spawn(execarg_obj, errmsg, sizeof(errmsg));
if (pid == -1) {
- int err = errno;
- rb_exec_fail(eargp, err, errmsg);
- RB_GC_GUARD(execarg_obj);
- rb_syserr_fail_str(err, fail_str);
+ int err = errno;
+ rb_exec_fail(eargp, err, errmsg);
+ RB_GC_GUARD(execarg_obj);
+ rb_syserr_fail_str(err, fail_str);
}
#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
return PIDT2NUM(pid);
@@ -5248,7 +5374,7 @@ proc_getsid(int argc, VALUE *argv, VALUE _)
rb_pid_t pid = 0;
if (rb_check_arity(argc, 0, 1) == 1 && !NIL_P(argv[0]))
- pid = NUM2PIDT(argv[0]);
+ pid = NUM2PIDT(argv[0]);
sid = getsid(pid);
if (sid < 0) rb_sys_fail(0);
@@ -5306,8 +5432,8 @@ ruby_setsid(void)
if ((fd = rb_cloexec_open("/dev/tty", O_RDWR, 0)) >= 0) {
rb_update_max_fd(fd);
- ioctl(fd, TIOCNOTTY, NULL);
- close(fd);
+ ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
}
return pid;
}
@@ -5376,7 +5502,7 @@ proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
iprio = NUM2INT(prio);
if (setpriority(iwhich, iwho, iprio) < 0)
- rb_sys_fail(0);
+ rb_sys_fail(0);
return INT2FIX(0);
}
#else
@@ -5441,6 +5567,9 @@ rlimit_resource_name2int(const char *name, long len, int casetype)
#ifdef RLIMIT_NPROC
RESCHECK(NPROC);
#endif
+#ifdef RLIMIT_NPTS
+ RESCHECK(NPTS);
+#endif
#ifdef RLIMIT_NICE
RESCHECK(NICE);
#endif
@@ -5516,7 +5645,7 @@ rlimit_type_by_sym(VALUE key)
enum {prefix_len = sizeof(prefix)-1};
if (len > prefix_len && strncmp(prefix, rname, prefix_len) == 0) {
- rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len);
+ rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len);
}
RB_GC_GUARD(key);
@@ -5533,9 +5662,9 @@ rlimit_resource_type(VALUE rtype)
switch (TYPE(rtype)) {
case T_SYMBOL:
- v = rb_sym2str(rtype);
- name = RSTRING_PTR(v);
- len = RSTRING_LEN(v);
+ v = rb_sym2str(rtype);
+ name = RSTRING_PTR(v);
+ len = RSTRING_LEN(v);
break;
default:
@@ -5544,7 +5673,7 @@ rlimit_resource_type(VALUE rtype)
rtype = v;
case T_STRING:
name = StringValueCStr(rtype);
- len = RSTRING_LEN(rtype);
+ len = RSTRING_LEN(rtype);
break;
}
/* fall through */
@@ -5571,8 +5700,8 @@ rlimit_resource_value(VALUE rval)
switch (TYPE(rval)) {
case T_SYMBOL:
- v = rb_sym2str(rval);
- name = RSTRING_PTR(v);
+ v = rb_sym2str(rval);
+ name = RSTRING_PTR(v);
break;
default:
@@ -5632,7 +5761,7 @@ proc_getrlimit(VALUE obj, VALUE resource)
struct rlimit rlim;
if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
- rb_sys_fail("getrlimit");
+ rb_sys_fail("getrlimit");
}
return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
}
@@ -5669,6 +5798,7 @@ proc_getrlimit(VALUE obj, VALUE resource)
* [NICE] ceiling on process's nice(2) value (number) (GNU/Linux)
* [NOFILE] file descriptors (number) (SUSv3)
* [NPROC] number of processes for the user (number) (4.4BSD, GNU/Linux)
+ * [NPTS] number of pseudo terminals (number) (FreeBSD)
* [RSS] resident memory size (bytes) (4.2BSD, GNU/Linux)
* [RTPRIO] ceiling on the process's real-time priority (number) (GNU/Linux)
* [RTTIME] CPU time for real-time process (us) (GNU/Linux)
@@ -5708,7 +5838,7 @@ proc_setrlimit(int argc, VALUE *argv, VALUE obj)
rlim.rlim_max = rlimit_resource_value(rlim_max);
if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
- rb_sys_fail("setrlimit");
+ rb_sys_fail("setrlimit");
}
return Qnil;
}
@@ -5721,7 +5851,7 @@ static void
check_uid_switch(void)
{
if (under_uid_switch) {
- rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
+ rb_raise(rb_eRuntimeError, "can't handle UID while evaluating block given to Process::UID.switch method");
}
}
@@ -5730,7 +5860,7 @@ static void
check_gid_switch(void)
{
if (under_gid_switch) {
- rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
+ rb_raise(rb_eRuntimeError, "can't handle GID while evaluating block given to Process::UID.switch method");
}
}
@@ -5989,7 +6119,7 @@ rb_getpwdiruid(void)
static rb_uid_t
obj2uid(VALUE id
# ifdef USE_GETPWNAM_R
- , VALUE *getpw_tmp
+ , VALUE *getpw_tmp
# endif
)
{
@@ -5997,46 +6127,46 @@ obj2uid(VALUE id
VALUE tmp;
if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
- uid = NUM2UIDT(id);
+ uid = NUM2UIDT(id);
}
else {
- const char *usrname = StringValueCStr(id);
- struct passwd *pwptr;
+ const char *usrname = StringValueCStr(id);
+ struct passwd *pwptr;
#ifdef USE_GETPWNAM_R
- struct passwd pwbuf;
- char *getpw_buf;
- long getpw_buf_len;
- int e;
- if (!*getpw_tmp) {
- getpw_buf_len = GETPW_R_SIZE_INIT;
- if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
- *getpw_tmp = rb_str_tmp_new(getpw_buf_len);
- }
- getpw_buf = RSTRING_PTR(*getpw_tmp);
- getpw_buf_len = rb_str_capacity(*getpw_tmp);
- rb_str_set_len(*getpw_tmp, getpw_buf_len);
- errno = 0;
- while ((e = getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) != 0) {
- if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
- rb_str_resize(*getpw_tmp, 0);
- rb_syserr_fail(e, "getpwnam_r");
- }
- rb_str_modify_expand(*getpw_tmp, getpw_buf_len);
- getpw_buf = RSTRING_PTR(*getpw_tmp);
- getpw_buf_len = rb_str_capacity(*getpw_tmp);
- }
+ struct passwd pwbuf;
+ char *getpw_buf;
+ long getpw_buf_len;
+ int e;
+ if (!*getpw_tmp) {
+ getpw_buf_len = GETPW_R_SIZE_INIT;
+ if (getpw_buf_len < 0) getpw_buf_len = GETPW_R_SIZE_DEFAULT;
+ *getpw_tmp = rb_str_tmp_new(getpw_buf_len);
+ }
+ getpw_buf = RSTRING_PTR(*getpw_tmp);
+ getpw_buf_len = rb_str_capacity(*getpw_tmp);
+ rb_str_set_len(*getpw_tmp, getpw_buf_len);
+ errno = 0;
+ while ((e = getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) != 0) {
+ if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
+ rb_str_resize(*getpw_tmp, 0);
+ rb_syserr_fail(e, "getpwnam_r");
+ }
+ rb_str_modify_expand(*getpw_tmp, getpw_buf_len);
+ getpw_buf = RSTRING_PTR(*getpw_tmp);
+ getpw_buf_len = rb_str_capacity(*getpw_tmp);
+ }
#else
- pwptr = getpwnam(usrname);
+ pwptr = getpwnam(usrname);
#endif
- if (!pwptr) {
+ if (!pwptr) {
#ifndef USE_GETPWNAM_R
- endpwent();
+ endpwent();
#endif
rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, id);
- }
- uid = pwptr->pw_uid;
+ }
+ uid = pwptr->pw_uid;
#ifndef USE_GETPWNAM_R
- endpwent();
+ endpwent();
#endif
}
return uid;
@@ -6066,7 +6196,7 @@ p_uid_from_name(VALUE self, VALUE id)
static rb_gid_t
obj2gid(VALUE id
# ifdef USE_GETGRNAM_R
- , VALUE *getgr_tmp
+ , VALUE *getgr_tmp
# endif
)
{
@@ -6074,48 +6204,48 @@ obj2gid(VALUE id
VALUE tmp;
if (FIXNUM_P(id) || NIL_P(tmp = rb_check_string_type(id))) {
- gid = NUM2GIDT(id);
+ gid = NUM2GIDT(id);
}
else {
- const char *grpname = StringValueCStr(id);
- struct group *grptr;
+ const char *grpname = StringValueCStr(id);
+ struct group *grptr;
#ifdef USE_GETGRNAM_R
- struct group grbuf;
- char *getgr_buf;
- long getgr_buf_len;
- int e;
- if (!*getgr_tmp) {
- getgr_buf_len = GETGR_R_SIZE_INIT;
- if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
- *getgr_tmp = rb_str_tmp_new(getgr_buf_len);
- }
- getgr_buf = RSTRING_PTR(*getgr_tmp);
- getgr_buf_len = rb_str_capacity(*getgr_tmp);
- rb_str_set_len(*getgr_tmp, getgr_buf_len);
- errno = 0;
- while ((e = getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) != 0) {
- if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
- rb_str_resize(*getgr_tmp, 0);
- rb_syserr_fail(e, "getgrnam_r");
- }
- rb_str_modify_expand(*getgr_tmp, getgr_buf_len);
- getgr_buf = RSTRING_PTR(*getgr_tmp);
- getgr_buf_len = rb_str_capacity(*getgr_tmp);
- }
+ struct group grbuf;
+ char *getgr_buf;
+ long getgr_buf_len;
+ int e;
+ if (!*getgr_tmp) {
+ getgr_buf_len = GETGR_R_SIZE_INIT;
+ if (getgr_buf_len < 0) getgr_buf_len = GETGR_R_SIZE_DEFAULT;
+ *getgr_tmp = rb_str_tmp_new(getgr_buf_len);
+ }
+ getgr_buf = RSTRING_PTR(*getgr_tmp);
+ getgr_buf_len = rb_str_capacity(*getgr_tmp);
+ rb_str_set_len(*getgr_tmp, getgr_buf_len);
+ errno = 0;
+ while ((e = getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) != 0) {
+ if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
+ rb_str_resize(*getgr_tmp, 0);
+ rb_syserr_fail(e, "getgrnam_r");
+ }
+ rb_str_modify_expand(*getgr_tmp, getgr_buf_len);
+ getgr_buf = RSTRING_PTR(*getgr_tmp);
+ getgr_buf_len = rb_str_capacity(*getgr_tmp);
+ }
#elif defined(HAVE_GETGRNAM)
- grptr = getgrnam(grpname);
+ grptr = getgrnam(grpname);
#else
- grptr = NULL;
+ grptr = NULL;
#endif
- if (!grptr) {
+ if (!grptr) {
#if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
- endgrent();
+ endgrent();
#endif
rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, id);
- }
- gid = grptr->gr_gid;
+ }
+ gid = grptr->gr_gid;
#if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
- endgrent();
+ endgrent();
#endif
}
return gid;
@@ -6310,12 +6440,12 @@ proc_setuid(VALUE obj, VALUE id)
if (setruid(uid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETUID
{
- if (geteuid() == uid) {
- if (setuid(uid) < 0) rb_sys_fail(0);
- }
- else {
- rb_notimplement();
- }
+ if (geteuid() == uid) {
+ if (setuid(uid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_notimplement();
+ }
}
#endif
return id;
@@ -6342,11 +6472,11 @@ int
setreuid(rb_uid_t ruid, rb_uid_t euid)
{
if (ruid != (rb_uid_t)-1 && ruid != getuid()) {
- if (euid == (rb_uid_t)-1) euid = geteuid();
- if (setuid(ruid) < 0) return -1;
+ if (euid == (rb_uid_t)-1) euid = geteuid();
+ if (setuid(ruid) < 0) return -1;
}
if (euid != (rb_uid_t)-1 && euid != geteuid()) {
- if (seteuid(euid) < 0) return -1;
+ if (seteuid(euid) < 0) return -1;
}
return 0;
}
@@ -6376,144 +6506,144 @@ p_uid_change_privilege(VALUE obj, VALUE id)
if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESUID)
- if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
+ if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
#elif defined(HAVE_SETUID)
- if (setuid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
+ if (setuid(uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- if (getuid() == uid) {
- if (SAVED_USER_ID == uid) {
- if (setreuid(-1, uid) < 0) rb_sys_fail(0);
- }
- else {
- if (uid == 0) { /* (r,e,s) == (root, root, x) */
- if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
- if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
- if (setreuid(uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- else {
- if (setreuid(0, -1) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0;
- if (setreuid(uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- }
- }
- else {
- if (setreuid(uid, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
+ if (getuid() == uid) {
+ if (SAVED_USER_ID == uid) {
+ if (setreuid(-1, uid) < 0) rb_sys_fail(0);
+ }
+ else {
+ if (uid == 0) { /* (r,e,s) == (root, root, x) */
+ if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
+ if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
+ if (setreuid(uid, uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
+ else {
+ if (setreuid(0, -1) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = 0;
+ if (setreuid(uid, uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
+ }
+ }
+ else {
+ if (setreuid(uid, uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
- if (getuid() == uid) {
- if (SAVED_USER_ID == uid) {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- }
- else {
- if (uid == 0) {
- if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0;
- if (setruid(0) < 0) rb_sys_fail(0);
- }
- else {
- if (setruid(0) < 0) rb_sys_fail(0);
- SAVED_USER_ID = 0;
- if (seteuid(uid) < 0) rb_sys_fail(0);
- if (setruid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- }
- }
- else {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- if (setruid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
+ if (getuid() == uid) {
+ if (SAVED_USER_ID == uid) {
+ if (seteuid(uid) < 0) rb_sys_fail(0);
+ }
+ else {
+ if (uid == 0) {
+ if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = 0;
+ if (setruid(0) < 0) rb_sys_fail(0);
+ }
+ else {
+ if (setruid(0) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = 0;
+ if (seteuid(uid) < 0) rb_sys_fail(0);
+ if (setruid(uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
+ }
+ }
+ else {
+ if (seteuid(uid) < 0) rb_sys_fail(0);
+ if (setruid(uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
#else
- (void)uid;
- rb_notimplement();
+ (void)uid;
+ rb_notimplement();
#endif
}
else { /* unprivileged user */
#if defined(HAVE_SETRESUID)
- if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
- (geteuid() == uid)? (rb_uid_t)-1: uid,
- (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
+ if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
+ (geteuid() == uid)? (rb_uid_t)-1: uid,
+ (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
- if (SAVED_USER_ID == uid) {
- if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
- (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
- rb_sys_fail(0);
- }
- else if (getuid() != uid) {
- if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
- rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- else if (/* getuid() == uid && */ geteuid() != uid) {
- if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setreuid(uid, -1) < 0) rb_sys_fail(0);
- }
- else { /* getuid() == uid && geteuid() == uid */
- if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
- if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setreuid(uid, -1) < 0) rb_sys_fail(0);
- }
+ if (SAVED_USER_ID == uid) {
+ if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
+ (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
+ rb_sys_fail(0);
+ }
+ else if (getuid() != uid) {
+ if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
+ rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
+ else if (/* getuid() == uid && */ geteuid() != uid) {
+ if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ if (setreuid(uid, -1) < 0) rb_sys_fail(0);
+ }
+ else { /* getuid() == uid && geteuid() == uid */
+ if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
+ if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ if (setreuid(uid, -1) < 0) rb_sys_fail(0);
+ }
#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
- if (SAVED_USER_ID == uid) {
- if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
- if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
- }
- else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
- if (getuid() != uid) {
- if (setruid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- else {
- if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setruid(uid) < 0) rb_sys_fail(0);
- }
- }
- else if (/* geteuid() != uid && */ getuid() == uid) {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- if (setruid(uid) < 0) rb_sys_fail(0);
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (SAVED_USER_ID == uid) {
+ if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
+ if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
+ }
+ else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
+ if (getuid() != uid) {
+ if (setruid(uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
+ else {
+ if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ if (setruid(uid) < 0) rb_sys_fail(0);
+ }
+ }
+ else if (/* geteuid() != uid && */ getuid() == uid) {
+ if (seteuid(uid) < 0) rb_sys_fail(0);
+ if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ if (setruid(uid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#elif defined HAVE_44BSD_SETUID
- if (getuid() == uid) {
- /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
- if (setuid(uid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = uid;
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (getuid() == uid) {
+ /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
+ if (setuid(uid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = uid;
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#elif defined HAVE_SETEUID
- if (getuid() == uid && SAVED_USER_ID == uid) {
- if (seteuid(uid) < 0) rb_sys_fail(0);
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (getuid() == uid && SAVED_USER_ID == uid) {
+ if (seteuid(uid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#elif defined HAVE_SETUID
- if (getuid() == uid && SAVED_USER_ID == uid) {
- if (setuid(uid) < 0) rb_sys_fail(0);
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (getuid() == uid && SAVED_USER_ID == uid) {
+ if (setuid(uid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#else
- rb_notimplement();
+ rb_notimplement();
#endif
}
return id;
@@ -6657,12 +6787,7 @@ p_sys_setresgid(VALUE obj, VALUE rid, VALUE eid, VALUE sid)
static VALUE
p_sys_issetugid(VALUE obj)
{
- if (issetugid()) {
- return Qtrue;
- }
- else {
- return Qfalse;
- }
+ return RBOOL(issetugid());
}
#else
#define p_sys_issetugid rb_f_notimplement
@@ -6712,12 +6837,12 @@ proc_setgid(VALUE obj, VALUE id)
if (setrgid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
{
- if (getegid() == gid) {
- if (setgid(gid) < 0) rb_sys_fail(0);
- }
- else {
- rb_notimplement();
- }
+ if (getegid() == gid) {
+ if (setgid(gid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_notimplement();
+ }
}
#endif
return GIDT2NUM(gid);
@@ -6745,7 +6870,6 @@ proc_setgid(VALUE obj, VALUE id)
* Darwin (Mac OS X) 16
* Sun Solaris 7,8,9,10 16
* Sun Solaris 11 / OpenSolaris 1024
- * HP-UX 20
* Windows 1015
*/
static int _maxgroups = -1;
@@ -6764,9 +6888,9 @@ static int
maxgroups(void)
{
if (_maxgroups < 0) {
- _maxgroups = get_sc_ngroups_max();
- if (_maxgroups < 0)
- _maxgroups = RB_MAX_GROUPS;
+ _maxgroups = get_sc_ngroups_max();
+ if (_maxgroups < 0)
+ _maxgroups = RB_MAX_GROUPS;
}
return _maxgroups;
@@ -6792,6 +6916,7 @@ maxgroups(void)
* - the result is sorted
* - the result includes effective GIDs
* - the result does not include duplicated GIDs
+ * - the result size does not exceed the value of Process.maxgroups
*
* You can make sure to get a sorted unique GID list of
* the current process by this expression:
@@ -6809,17 +6934,17 @@ proc_getgroups(VALUE obj)
ngroups = getgroups(0, NULL);
if (ngroups == -1)
- rb_sys_fail(0);
+ rb_sys_fail(0);
groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
ngroups = getgroups(ngroups, groups);
if (ngroups == -1)
- rb_sys_fail(0);
+ rb_sys_fail(0);
ary = rb_ary_new();
for (i = 0; i < ngroups; i++)
- rb_ary_push(ary, GIDT2NUM(groups[i]));
+ rb_ary_push(ary, GIDT2NUM(groups[i]));
ALLOCV_END(tmp);
@@ -6856,19 +6981,19 @@ proc_setgroups(VALUE obj, VALUE ary)
ngroups = RARRAY_LENINT(ary);
if (ngroups > maxgroups())
- rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
+ rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());
groups = ALLOCV_N(rb_gid_t, tmp, ngroups);
for (i = 0; i < ngroups; i++) {
- VALUE g = RARRAY_AREF(ary, i);
+ VALUE g = RARRAY_AREF(ary, i);
- groups[i] = OBJ2GID1(g);
+ groups[i] = OBJ2GID1(g);
}
FINISH_GETGRNAM;
if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
- rb_sys_fail(0);
+ rb_sys_fail(0);
ALLOCV_END(tmp);
@@ -6886,10 +7011,10 @@ proc_setgroups(VALUE obj, VALUE ary)
*
* Initializes the supplemental group access list by reading the
* system group database and using all groups of which the given user
- * is a member. The group with the specified <em>gid</em> is also
- * added to the list. Returns the resulting Array of the
- * gids of all the groups in the supplementary group access list. Not
- * available on all platforms.
+ * is a member. The group with the specified _gid_ is also added to
+ * the list. Returns the resulting Array of the GIDs of all the
+ * groups in the supplementary group access list. Not available on
+ * all platforms.
*
* Process.groups #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
* Process.initgroups( "mgranger", 30 ) #=> [30, 6, 10, 11]
@@ -6901,7 +7026,7 @@ static VALUE
proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
{
if (initgroups(StringValueCStr(uname), OBJ2GID(base_grp)) != 0) {
- rb_sys_fail(0);
+ rb_sys_fail(0);
}
return proc_getgroups(obj);
}
@@ -6914,7 +7039,7 @@ proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
* call-seq:
* Process.maxgroups -> integer
*
- * Returns the maximum number of gids allowed in the supplemental
+ * Returns the maximum number of GIDs allowed in the supplemental
* group access list.
*
* Process.maxgroups #=> 32
@@ -6934,7 +7059,7 @@ proc_getmaxgroups(VALUE obj)
* call-seq:
* Process.maxgroups= integer -> integer
*
- * Sets the maximum number of gids allowed in the supplemental group
+ * Sets the maximum number of GIDs allowed in the supplemental group
* access list.
*/
@@ -6945,13 +7070,13 @@ proc_setmaxgroups(VALUE obj, VALUE val)
int ngroups_max = get_sc_ngroups_max();
if (ngroups <= 0)
- rb_raise(rb_eArgError, "maxgroups %d should be positive", ngroups);
+ rb_raise(rb_eArgError, "maxgroups %d should be positive", ngroups);
if (ngroups > RB_MAX_GROUPS)
- ngroups = RB_MAX_GROUPS;
+ ngroups = RB_MAX_GROUPS;
if (ngroups_max > 0 && ngroups > ngroups_max)
- ngroups = ngroups_max;
+ ngroups = ngroups_max;
_maxgroups = ngroups;
@@ -7007,30 +7132,25 @@ rb_daemon(int nochdir, int noclose)
#else
int n;
-#define fork_daemon() \
- switch (rb_fork_ruby(NULL)) { \
- case -1: return -1; \
- case 0: break; \
- default: _exit(EXIT_SUCCESS); \
+ switch (rb_fork_ruby(NULL)) {
+ case -1: return -1;
+ case 0: break;
+ default: _exit(EXIT_SUCCESS);
}
- fork_daemon();
-
- if (setsid() < 0) return -1;
-
- /* must not be process-leader */
- fork_daemon();
+ /* ignore EPERM which means already being process-leader */
+ if (setsid() < 0) (void)0;
if (!nochdir)
- err = chdir("/");
+ err = chdir("/");
if (!noclose && (n = rb_cloexec_open("/dev/null", O_RDWR, 0)) != -1) {
rb_update_max_fd(n);
- (void)dup2(n, 0);
- (void)dup2(n, 1);
- (void)dup2(n, 2);
- if (n > 2)
- (void)close (n);
+ (void)dup2(n, 0);
+ (void)dup2(n, 1);
+ (void)dup2(n, 2);
+ if (n > 2)
+ (void)close (n);
}
#endif
return err;
@@ -7056,11 +7176,11 @@ int
setregid(rb_gid_t rgid, rb_gid_t egid)
{
if (rgid != (rb_gid_t)-1 && rgid != getgid()) {
- if (egid == (rb_gid_t)-1) egid = getegid();
- if (setgid(rgid) < 0) return -1;
+ if (egid == (rb_gid_t)-1) egid = getegid();
+ if (setgid(rgid) < 0) return -1;
}
if (egid != (rb_gid_t)-1 && egid != getegid()) {
- if (setegid(egid) < 0) return -1;
+ if (setegid(egid) < 0) return -1;
}
return 0;
}
@@ -7090,145 +7210,145 @@ p_gid_change_privilege(VALUE obj, VALUE id)
if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESGID)
- if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
+ if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
#elif defined HAVE_SETGID
- if (setgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
+ if (setgid(gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- if (getgid() == gid) {
- if (SAVED_GROUP_ID == gid) {
- if (setregid(-1, gid) < 0) rb_sys_fail(0);
- }
- else {
- if (gid == 0) { /* (r,e,s) == (root, y, x) */
- if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
- if (setregid(gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- else { /* (r,e,s) == (z, y, x) */
- if (setregid(0, 0) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0;
- if (setregid(gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- }
- }
- else {
- if (setregid(gid, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
+ if (getgid() == gid) {
+ if (SAVED_GROUP_ID == gid) {
+ if (setregid(-1, gid) < 0) rb_sys_fail(0);
+ }
+ else {
+ if (gid == 0) { /* (r,e,s) == (root, y, x) */
+ if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+ if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
+ if (setregid(gid, gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
+ else { /* (r,e,s) == (z, y, x) */
+ if (setregid(0, 0) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = 0;
+ if (setregid(gid, gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
+ }
+ }
+ else {
+ if (setregid(gid, gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
- if (getgid() == gid) {
- if (SAVED_GROUP_ID == gid) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- }
- else {
- if (gid == 0) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0;
- if (setrgid(0) < 0) rb_sys_fail(0);
- }
- else {
- if (setrgid(0) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = 0;
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- }
- }
- else {
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
+ if (getgid() == gid) {
+ if (SAVED_GROUP_ID == gid) {
+ if (setegid(gid) < 0) rb_sys_fail(0);
+ }
+ else {
+ if (gid == 0) {
+ if (setegid(gid) < 0) rb_sys_fail(0);
+ if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = 0;
+ if (setrgid(0) < 0) rb_sys_fail(0);
+ }
+ else {
+ if (setrgid(0) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = 0;
+ if (setegid(gid) < 0) rb_sys_fail(0);
+ if (setrgid(gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
+ }
+ }
+ else {
+ if (setegid(gid) < 0) rb_sys_fail(0);
+ if (setrgid(gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
#else
- rb_notimplement();
+ rb_notimplement();
#endif
}
else { /* unprivileged user */
#if defined(HAVE_SETRESGID)
- if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
- (getegid() == gid)? (rb_gid_t)-1: gid,
- (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
+ if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
+ (getegid() == gid)? (rb_gid_t)-1: gid,
+ (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
- if (SAVED_GROUP_ID == gid) {
- if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
- (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
- rb_sys_fail(0);
- }
- else if (getgid() != gid) {
- if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
- rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- else if (/* getgid() == gid && */ getegid() != gid) {
- if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setregid(gid, -1) < 0) rb_sys_fail(0);
- }
- else { /* getgid() == gid && getegid() == gid */
- if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setregid(gid, -1) < 0) rb_sys_fail(0);
- }
+ if (SAVED_GROUP_ID == gid) {
+ if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
+ (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
+ rb_sys_fail(0);
+ }
+ else if (getgid() != gid) {
+ if (setregid(gid, (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
+ rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
+ else if (/* getgid() == gid && */ getegid() != gid) {
+ if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ if (setregid(gid, -1) < 0) rb_sys_fail(0);
+ }
+ else { /* getgid() == gid && getegid() == gid */
+ if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+ if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ if (setregid(gid, -1) < 0) rb_sys_fail(0);
+ }
#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
- if (SAVED_GROUP_ID == gid) {
- if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
- if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
- }
- else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
- if (getgid() != gid) {
- if (setrgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- else {
- if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setrgid(gid) < 0) rb_sys_fail(0);
- }
- }
- else if (/* getegid() != gid && */ getgid() == gid) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- if (setrgid(gid) < 0) rb_sys_fail(0);
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (SAVED_GROUP_ID == gid) {
+ if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
+ if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
+ }
+ else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
+ if (getgid() != gid) {
+ if (setrgid(gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
+ else {
+ if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ if (setrgid(gid) < 0) rb_sys_fail(0);
+ }
+ }
+ else if (/* getegid() != gid && */ getgid() == gid) {
+ if (setegid(gid) < 0) rb_sys_fail(0);
+ if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ if (setrgid(gid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#elif defined HAVE_44BSD_SETGID
- if (getgid() == gid) {
- /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
- if (setgid(gid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = gid;
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (getgid() == gid) {
+ /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
+ if (setgid(gid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = gid;
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#elif defined HAVE_SETEGID
- if (getgid() == gid && SAVED_GROUP_ID == gid) {
- if (setegid(gid) < 0) rb_sys_fail(0);
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (getgid() == gid && SAVED_GROUP_ID == gid) {
+ if (setegid(gid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#elif defined HAVE_SETGID
- if (getgid() == gid && SAVED_GROUP_ID == gid) {
- if (setgid(gid) < 0) rb_sys_fail(0);
- }
- else {
- rb_syserr_fail(EPERM, 0);
- }
+ if (getgid() == gid && SAVED_GROUP_ID == gid) {
+ if (setgid(gid) < 0) rb_sys_fail(0);
+ }
+ else {
+ rb_syserr_fail(EPERM, 0);
+ }
#else
- (void)gid;
- rb_notimplement();
+ (void)gid;
+ rb_notimplement();
#endif
}
return id;
@@ -7265,10 +7385,10 @@ proc_seteuid(rb_uid_t uid)
if (seteuid(uid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETUID
if (uid == getuid()) {
- if (setuid(uid) < 0) rb_sys_fail(0);
+ if (setuid(uid) < 0) rb_sys_fail(0);
}
else {
- rb_notimplement();
+ rb_notimplement();
}
#else
rb_notimplement();
@@ -7311,18 +7431,18 @@ rb_seteuid_core(rb_uid_t euid)
#if defined(HAVE_SETRESUID)
if (uid != euid) {
- if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = euid;
+ if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = euid;
}
else {
- if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
+ if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
}
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
if (setreuid(-1, euid) < 0) rb_sys_fail(0);
if (uid != euid) {
- if (setreuid(euid,uid) < 0) rb_sys_fail(0);
- if (setreuid(uid,euid) < 0) rb_sys_fail(0);
- SAVED_USER_ID = euid;
+ if (setreuid(euid,uid) < 0) rb_sys_fail(0);
+ if (setreuid(uid,euid) < 0) rb_sys_fail(0);
+ SAVED_USER_ID = euid;
}
#elif defined HAVE_SETEUID
if (seteuid(euid) < 0) rb_sys_fail(0);
@@ -7408,10 +7528,10 @@ proc_setegid(VALUE obj, VALUE egid)
if (setegid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
if (gid == getgid()) {
- if (setgid(gid) < 0) rb_sys_fail(0);
+ if (setgid(gid) < 0) rb_sys_fail(0);
}
else {
- rb_notimplement();
+ rb_notimplement();
}
#else
rb_notimplement();
@@ -7441,18 +7561,18 @@ rb_setegid_core(rb_gid_t egid)
#if defined(HAVE_SETRESGID)
if (gid != egid) {
- if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = egid;
+ if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = egid;
}
else {
- if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
+ if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
}
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
if (setregid(-1, egid) < 0) rb_sys_fail(0);
if (gid != egid) {
- if (setregid(egid,gid) < 0) rb_sys_fail(0);
- if (setregid(gid,egid) < 0) rb_sys_fail(0);
- SAVED_GROUP_ID = egid;
+ if (setregid(egid,gid) < 0) rb_sys_fail(0);
+ if (setregid(gid,egid) < 0) rb_sys_fail(0);
+ SAVED_GROUP_ID = egid;
}
#elif defined HAVE_SETEGID
if (setegid(egid) < 0) rb_sys_fail(0);
@@ -7668,27 +7788,27 @@ p_uid_switch(VALUE obj)
euid = geteuid();
if (uid != euid) {
- proc_seteuid(uid);
- if (rb_block_given_p()) {
- under_uid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
- }
- else {
- return UIDT2NUM(euid);
- }
+ proc_seteuid(uid);
+ if (rb_block_given_p()) {
+ under_uid_switch = 1;
+ return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
+ }
+ else {
+ return UIDT2NUM(euid);
+ }
}
else if (euid != SAVED_USER_ID) {
- proc_seteuid(SAVED_USER_ID);
- if (rb_block_given_p()) {
- under_uid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
- }
- else {
- return UIDT2NUM(uid);
- }
+ proc_seteuid(SAVED_USER_ID);
+ if (rb_block_given_p()) {
+ under_uid_switch = 1;
+ return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
+ }
+ else {
+ return UIDT2NUM(uid);
+ }
}
else {
- rb_syserr_fail(EPERM, 0);
+ rb_syserr_fail(EPERM, 0);
}
UNREACHABLE_RETURN(Qnil);
@@ -7712,15 +7832,15 @@ p_uid_switch(VALUE obj)
euid = geteuid();
if (uid == euid) {
- rb_syserr_fail(EPERM, 0);
+ rb_syserr_fail(EPERM, 0);
}
p_uid_exchange(obj);
if (rb_block_given_p()) {
- under_uid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
+ under_uid_switch = 1;
+ return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj);
}
else {
- return UIDT2NUM(euid);
+ return UIDT2NUM(euid);
}
}
#endif
@@ -7782,27 +7902,27 @@ p_gid_switch(VALUE obj)
egid = getegid();
if (gid != egid) {
- proc_setegid(obj, GIDT2NUM(gid));
- if (rb_block_given_p()) {
- under_gid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
- }
- else {
- return GIDT2NUM(egid);
- }
+ proc_setegid(obj, GIDT2NUM(gid));
+ if (rb_block_given_p()) {
+ under_gid_switch = 1;
+ return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
+ }
+ else {
+ return GIDT2NUM(egid);
+ }
}
else if (egid != SAVED_GROUP_ID) {
- proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
- if (rb_block_given_p()) {
- under_gid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
- }
- else {
- return GIDT2NUM(gid);
- }
+ proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
+ if (rb_block_given_p()) {
+ under_gid_switch = 1;
+ return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
+ }
+ else {
+ return GIDT2NUM(gid);
+ }
}
else {
- rb_syserr_fail(EPERM, 0);
+ rb_syserr_fail(EPERM, 0);
}
UNREACHABLE_RETURN(Qnil);
@@ -7826,15 +7946,15 @@ p_gid_switch(VALUE obj)
egid = getegid();
if (gid == egid) {
- rb_syserr_fail(EPERM, 0);
+ rb_syserr_fail(EPERM, 0);
}
p_gid_exchange(obj);
if (rb_block_given_p()) {
- under_gid_switch = 1;
- return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
+ under_gid_switch = 1;
+ return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj);
}
else {
- return GIDT2NUM(egid);
+ return GIDT2NUM(egid);
}
}
#endif
@@ -7875,7 +7995,7 @@ rb_proc_times(VALUE obj)
struct rusage usage_s, usage_c;
if (getrusage(RUSAGE_SELF, &usage_s) != 0 || getrusage(RUSAGE_CHILDREN, &usage_c) != 0)
- rb_sys_fail("getrusage");
+ rb_sys_fail("getrusage");
utime = DBL2NUM((double)usage_s.ru_utime.tv_sec + (double)usage_s.ru_utime.tv_usec/1e6);
stime = DBL2NUM((double)usage_s.ru_stime.tv_sec + (double)usage_s.ru_stime.tv_usec/1e6);
cutime = DBL2NUM((double)usage_c.ru_utime.tv_sec + (double)usage_c.ru_utime.tv_usec/1e6);
@@ -8112,6 +8232,13 @@ ruby_real_ms_time(void)
}
#endif
+#if defined(NUM2CLOCKID)
+# define NUMERIC_CLOCKID 1
+#else
+# define NUMERIC_CLOCKID 0
+# define NUM2CLOCKID(x) 0
+#endif
+
/*
* call-seq:
* Process.clock_gettime(clock_id [, unit]) -> number
@@ -8128,8 +8255,8 @@ ruby_real_ms_time(void)
* The supported constants depends on OS and version.
* Ruby provides following types of +clock_id+ if available.
*
- * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12
- * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12
+ * [CLOCK_REALTIME] SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012
+ * [CLOCK_MONOTONIC] SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0, OpenBSD 3.4, macOS 10.12, Windows-2000
* [CLOCK_PROCESS_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3, OpenBSD 5.4, macOS 10.12
* [CLOCK_THREAD_CPUTIME_ID] SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD 5.4, macOS 10.12
* [CLOCK_VIRTUAL] FreeBSD 3.0, OpenBSD 2.1
@@ -8228,7 +8355,7 @@ ruby_real_ms_time(void)
* The underlying function, clock_gettime(), returns a number of nanoseconds.
* Float object (IEEE 754 double) is not enough to represent
* the return value for CLOCK_REALTIME.
- * If the exact nanoseconds value is required, use +:nanoseconds+ as the +unit+.
+ * If the exact nanoseconds value is required, use +:nanosecond+ as the +unit+.
*
* The origin (zero) of the returned value varies.
* For example, system start up time, process start up time, the Epoch, etc.
@@ -8252,8 +8379,39 @@ rb_clock_gettime(int argc, VALUE *argv, VALUE _)
VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
VALUE clk_id = argv[0];
+#ifdef HAVE_CLOCK_GETTIME
+ clockid_t c;
+#endif
if (SYMBOL_P(clk_id)) {
+#ifdef CLOCK_REALTIME
+ if (clk_id == RUBY_CLOCK_REALTIME) {
+ c = CLOCK_REALTIME;
+ goto gettime;
+ }
+#endif
+
+#ifdef CLOCK_MONOTONIC
+ if (clk_id == RUBY_CLOCK_MONOTONIC) {
+ c = CLOCK_MONOTONIC;
+ goto gettime;
+ }
+#endif
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ if (clk_id == RUBY_CLOCK_PROCESS_CPUTIME_ID) {
+ c = CLOCK_PROCESS_CPUTIME_ID;
+ goto gettime;
+ }
+#endif
+
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ if (clk_id == RUBY_CLOCK_THREAD_CPUTIME_ID) {
+ c = CLOCK_THREAD_CPUTIME_ID;
+ goto gettime;
+ }
+#endif
+
/*
* Non-clock_gettime clocks are provided by symbol clk_id.
*/
@@ -8364,9 +8522,8 @@ rb_clock_gettime(int argc, VALUE *argv, VALUE _)
}
#ifdef __APPLE__
-#define RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC ID2SYM(id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
- const mach_timebase_info_data_t *info = get_mach_timebase_info();
+ const mach_timebase_info_data_t *info = get_mach_timebase_info();
uint64_t t = mach_absolute_time();
tt.count = (int32_t)(t % 1000000000);
tt.giga_count = t / 1000000000;
@@ -8377,11 +8534,11 @@ rb_clock_gettime(int argc, VALUE *argv, VALUE _)
}
#endif
}
- else {
+ else if (NUMERIC_CLOCKID) {
#if defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
- clockid_t c;
c = NUM2CLOCKID(clk_id);
+ gettime:
ret = clock_gettime(c, &ts);
if (ret == -1)
rb_sys_fail("clock_gettime");
@@ -8443,16 +8600,49 @@ rb_clock_gettime(int argc, VALUE *argv, VALUE _)
static VALUE
rb_clock_getres(int argc, VALUE *argv, VALUE _)
{
+ int ret;
+
struct timetick tt;
timetick_int_t numerators[2];
timetick_int_t denominators[2];
int num_numerators = 0;
int num_denominators = 0;
+#ifdef HAVE_CLOCK_GETRES
+ clockid_t c;
+#endif
VALUE unit = (rb_check_arity(argc, 1, 2) == 2) ? argv[1] : Qnil;
VALUE clk_id = argv[0];
if (SYMBOL_P(clk_id)) {
+#ifdef CLOCK_REALTIME
+ if (clk_id == RUBY_CLOCK_REALTIME) {
+ c = CLOCK_REALTIME;
+ goto getres;
+ }
+#endif
+
+#ifdef CLOCK_MONOTONIC
+ if (clk_id == RUBY_CLOCK_MONOTONIC) {
+ c = CLOCK_MONOTONIC;
+ goto getres;
+ }
+#endif
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ if (clk_id == RUBY_CLOCK_PROCESS_CPUTIME_ID) {
+ c = CLOCK_PROCESS_CPUTIME_ID;
+ goto getres;
+ }
+#endif
+
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ if (clk_id == RUBY_CLOCK_THREAD_CPUTIME_ID) {
+ c = CLOCK_THREAD_CPUTIME_ID;
+ goto getres;
+ }
+#endif
+
#ifdef RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
if (clk_id == RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME) {
tt.giga_count = 0;
@@ -8509,7 +8699,7 @@ rb_clock_getres(int argc, VALUE *argv, VALUE _)
#ifdef RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
if (clk_id == RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC) {
- const mach_timebase_info_data_t *info = get_mach_timebase_info();
+ const mach_timebase_info_data_t *info = get_mach_timebase_info();
tt.count = 1;
tt.giga_count = 0;
numerators[num_numerators++] = info->numer;
@@ -8519,11 +8709,12 @@ rb_clock_getres(int argc, VALUE *argv, VALUE _)
}
#endif
}
- else {
+ else if (NUMERIC_CLOCKID) {
#if defined(HAVE_CLOCK_GETRES)
struct timespec ts;
- clockid_t c = NUM2CLOCKID(clk_id);
- int ret = clock_getres(c, &ts);
+ c = NUM2CLOCKID(clk_id);
+ getres:
+ ret = clock_getres(c, &ts);
if (ret == -1)
rb_sys_fail("clock_getres");
tt.count = (int32_t)ts.tv_nsec;
@@ -8558,7 +8749,7 @@ get_PROCESS_ID(ID _x, VALUE *_y)
/*
* call-seq:
- * Process.kill(signal, pid, ...) -> integer
+ * Process.kill(signal, pid, *pids) -> integer
*
* Sends the given signal to the specified process id(s) if _pid_ is positive.
* If _pid_ is zero, _signal_ is sent to all processes whose group ID is equal
@@ -8651,6 +8842,7 @@ InitVM_process(void)
rb_define_singleton_method(rb_mProcess, "exit", f_exit, -1);
rb_define_singleton_method(rb_mProcess, "abort", f_abort, -1);
rb_define_singleton_method(rb_mProcess, "last_status", proc_s_last_status, 0);
+ rb_define_singleton_method(rb_mProcess, "_fork", rb_proc__fork, 0);
rb_define_module_function(rb_mProcess, "kill", proc_rb_f_kill, -1);
rb_define_module_function(rb_mProcess, "wait", proc_m_wait, -1);
@@ -8721,20 +8913,20 @@ InitVM_process(void)
{
VALUE inf = RLIM2NUM(RLIM_INFINITY);
#ifdef RLIM_SAVED_MAX
- {
- VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
- /* see Process.setrlimit */
- rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
- }
+ {
+ VALUE v = RLIM_INFINITY == RLIM_SAVED_MAX ? inf : RLIM2NUM(RLIM_SAVED_MAX);
+ /* see Process.setrlimit */
+ rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", v);
+ }
#endif
- /* see Process.setrlimit */
+ /* see Process.setrlimit */
rb_define_const(rb_mProcess, "RLIM_INFINITY", inf);
#ifdef RLIM_SAVED_CUR
- {
- VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
- /* see Process.setrlimit */
- rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
- }
+ {
+ VALUE v = RLIM_INFINITY == RLIM_SAVED_CUR ? inf : RLIM2NUM(RLIM_SAVED_CUR);
+ /* see Process.setrlimit */
+ rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", v);
+ }
#endif
}
#ifdef RLIMIT_AS
@@ -8810,6 +9002,14 @@ InitVM_process(void)
*/
rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
#endif
+#ifdef RLIMIT_NPTS
+ /* The maximum number of pseudo-terminals that can be created for the
+ * real user ID of the calling process.
+ *
+ * see the system getrlimit(2) manual for details.
+ */
+ rb_define_const(rb_mProcess, "RLIMIT_NPTS", INT2FIX(RLIMIT_NPTS));
+#endif
#ifdef RLIMIT_RSS
/* Specifies the limit (in pages) of the process's resident set.
*
@@ -8872,31 +9072,49 @@ InitVM_process(void)
rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
-#ifdef CLOCK_REALTIME
- /* see Process.clock_gettime */
- rb_define_const(rb_mProcess, "CLOCK_REALTIME", CLOCKID2NUM(CLOCK_REALTIME));
+#if defined(RUBY_CLOCK_REALTIME)
#elif defined(RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME)
- /* see Process.clock_gettime */
- rb_define_const(rb_mProcess, "CLOCK_REALTIME", RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME);
+# define RUBY_CLOCK_REALTIME RUBY_GETTIMEOFDAY_BASED_CLOCK_REALTIME
+#elif defined(RUBY_TIME_BASED_CLOCK_REALTIME)
+# define RUBY_CLOCK_REALTIME RUBY_TIME_BASED_CLOCK_REALTIME
#endif
-#ifdef CLOCK_MONOTONIC
+#if defined(CLOCK_REALTIME) && defined(CLOCKID2NUM)
/* see Process.clock_gettime */
- rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", CLOCKID2NUM(CLOCK_MONOTONIC));
+ rb_define_const(rb_mProcess, "CLOCK_REALTIME", CLOCKID2NUM(CLOCK_REALTIME));
+#elif defined(RUBY_CLOCK_REALTIME)
+ rb_define_const(rb_mProcess, "CLOCK_REALTIME", RUBY_CLOCK_REALTIME);
+#endif
+
+#if defined(RUBY_CLOCK_MONOTONIC)
#elif defined(RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC)
- /* see Process.clock_gettime */
- rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC);
+# define RUBY_CLOCK_MONOTONIC RUBY_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC
#endif
-#ifdef CLOCK_PROCESS_CPUTIME_ID
+#if defined(CLOCK_MONOTONIC) && defined(CLOCKID2NUM)
/* see Process.clock_gettime */
- rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
+ rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", CLOCKID2NUM(CLOCK_MONOTONIC));
+#elif defined(RUBY_CLOCK_MONOTONIC)
+ rb_define_const(rb_mProcess, "CLOCK_MONOTONIC", RUBY_CLOCK_MONOTONIC);
+#endif
+
+#if defined(RUBY_CLOCK_PROCESS_CPUTIME_ID)
#elif defined(RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
+# define RUBY_CLOCK_PROCESS_CPUTIME_ID RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID
+#endif
+#if defined(CLOCK_PROCESS_CPUTIME_ID) && defined(CLOCKID2NUM)
/* see Process.clock_gettime */
- rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", RUBY_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID);
+ rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", CLOCKID2NUM(CLOCK_PROCESS_CPUTIME_ID));
+#elif defined(RUBY_CLOCK_PROCESS_CPUTIME_ID)
+ rb_define_const(rb_mProcess, "CLOCK_PROCESS_CPUTIME_ID", RUBY_CLOCK_PROCESS_CPUTIME_ID);
#endif
-#ifdef CLOCK_THREAD_CPUTIME_ID
+
+#if defined(CLOCK_THREAD_CPUTIME_ID) && defined(CLOCKID2NUM)
/* see Process.clock_gettime */
rb_define_const(rb_mProcess, "CLOCK_THREAD_CPUTIME_ID", CLOCKID2NUM(CLOCK_THREAD_CPUTIME_ID));
+#elif defined(RUBY_CLOCK_THREAD_CPUTIME_ID)
+ rb_define_const(rb_mProcess, "CLOCK_THREAD_CPUTIME_ID", RUBY_CLOCK_THREAD_CPUTIME_ID);
#endif
+
+#ifdef CLOCKID2NUM
#ifdef CLOCK_VIRTUAL
/* see Process.clock_gettime */
rb_define_const(rb_mProcess, "CLOCK_VIRTUAL", CLOCKID2NUM(CLOCK_VIRTUAL));
@@ -8977,12 +9195,22 @@ InitVM_process(void)
/* see Process.clock_gettime */
rb_define_const(rb_mProcess, "CLOCK_TAI", CLOCKID2NUM(CLOCK_TAI));
#endif
+#endif
rb_define_module_function(rb_mProcess, "clock_gettime", rb_clock_gettime, -1);
rb_define_module_function(rb_mProcess, "clock_getres", rb_clock_getres, -1);
#if defined(HAVE_TIMES) || defined(_WIN32)
- /* Placeholder for rusage */
rb_cProcessTms = rb_struct_define_under(rb_mProcess, "Tms", "utime", "stime", "cutime", "cstime", NULL);
+#if 0 /* for RDoc */
+ /* user time used in this process */
+ rb_define_attr(rb_cProcessTms, "utime", TRUE, TRUE);
+ /* system time used in this process */
+ rb_define_attr(rb_cProcessTms, "stime", TRUE, TRUE);
+ /* user time used in the child processes */
+ rb_define_attr(rb_cProcessTms, "cutime", TRUE, TRUE);
+ /* system time used in the child processes */
+ rb_define_attr(rb_cProcessTms, "cstime", TRUE, TRUE);
+#endif
#endif
SAVED_USER_ID = geteuid();
@@ -9043,46 +9271,58 @@ InitVM_process(void)
void
Init_process(void)
{
- 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");
+#define define_id(name) id_##name = rb_intern_const(#name)
+ define_id(in);
+ define_id(out);
+ define_id(err);
+ define_id(pid);
+ define_id(uid);
+ define_id(gid);
+ define_id(close);
+ define_id(child);
#ifdef HAVE_SETPGID
- id_pgroup = rb_intern_const("pgroup");
+ define_id(pgroup);
#endif
#ifdef _WIN32
- 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");
+ define_id(new_pgroup);
+#endif
+ define_id(unsetenv_others);
+ define_id(chdir);
+ define_id(umask);
+ define_id(close_others);
+ define_id(nanosecond);
+ define_id(microsecond);
+ define_id(millisecond);
+ define_id(second);
+ define_id(float_microsecond);
+ define_id(float_millisecond);
+ define_id(float_second);
+ define_id(GETTIMEOFDAY_BASED_CLOCK_REALTIME);
+ define_id(TIME_BASED_CLOCK_REALTIME);
+#ifdef CLOCK_REALTIME
+ define_id(CLOCK_REALTIME);
+#endif
+#ifdef CLOCK_MONOTONIC
+ define_id(CLOCK_MONOTONIC);
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ define_id(CLOCK_PROCESS_CPUTIME_ID);
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ define_id(CLOCK_THREAD_CPUTIME_ID);
+#endif
#ifdef HAVE_TIMES
- 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");
+ define_id(TIMES_BASED_CLOCK_MONOTONIC);
+ define_id(TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID);
#endif
#ifdef RUSAGE_SELF
- id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
+ define_id(GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID);
#endif
- id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
+ define_id(CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID);
#ifdef __APPLE__
- id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern_const("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
+ define_id(MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC);
#endif
- id_hertz = rb_intern_const("hertz");
+ define_id(hertz);
InitVM(process);
}
diff --git a/ractor.c b/ractor.c
index 7996d1c275..8fb563fa11 100644
--- a/ractor.c
+++ b/ractor.c
@@ -16,6 +16,8 @@
#include "variable.h"
#include "gc.h"
#include "transient_heap.h"
+#include "yjit.h"
+#include "mjit.h"
VALUE rb_cRactor;
@@ -73,7 +75,9 @@ static void
ractor_lock_self(rb_ractor_t *cr, const char *file, int line)
{
VM_ASSERT(cr == GET_RACTOR());
+#if RACTOR_CHECK_MODE > 0
VM_ASSERT(cr->sync.locked_by != cr->pub.self);
+#endif
ractor_lock(cr, file, line);
}
@@ -93,7 +97,9 @@ static void
ractor_unlock_self(rb_ractor_t *cr, const char *file, int line)
{
VM_ASSERT(cr == GET_RACTOR());
+#if RACTOR_CHECK_MODE > 0
VM_ASSERT(cr->sync.locked_by == cr->pub.self);
+#endif
ractor_unlock(cr, file, line);
}
@@ -201,7 +207,7 @@ ractor_mark(void *ptr)
if (r->threads.cnt > 0) {
rb_thread_t *th = 0;
- list_for_each(&r->threads.set, th, lt_node) {
+ ccan_list_for_each(&r->threads.set, th, lt_node) {
VM_ASSERT(th != NULL);
rb_gc_mark(th->self);
}
@@ -262,7 +268,7 @@ static const rb_data_type_t ractor_data_type = {
"ractor",
{
ractor_mark,
- ractor_free,
+ ractor_free,
ractor_memsize,
NULL, // update
},
@@ -413,7 +419,7 @@ ractor_queue_enq(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_ba
rq->size *= 2;
}
rq->baskets[(rq->start + rq->cnt++) % rq->size] = *basket;
- // fprintf(stderr, "%s %p->cnt:%d\n", __func__, rq, rq->cnt);
+ // fprintf(stderr, "%s %p->cnt:%d\n", RUBY_FUNCTION_NAME_STRING, (void *)rq, rq->cnt);
}
static void
@@ -492,17 +498,17 @@ ractor_try_receive(rb_execution_context_t *ec, rb_ractor_t *r)
}
static bool
-ractor_sleeping_by(const rb_ractor_t *r, enum ractor_wait_status wait_status)
+ractor_sleeping_by(const rb_ractor_t *r, enum rb_ractor_wait_status wait_status)
{
return (r->sync.wait.status & wait_status) && r->sync.wait.wakeup_status == wakeup_none;
}
static bool
-ractor_wakeup(rb_ractor_t *r, enum ractor_wait_status wait_status, enum ractor_wakeup_status wakeup_status)
+ractor_wakeup(rb_ractor_t *r, enum rb_ractor_wait_status wait_status, enum rb_ractor_wakeup_status wakeup_status)
{
ASSERT_ractor_locking(r);
- // fprintf(stderr, "%s r:%p status:%s/%s wakeup_status:%s/%s\n", __func__, r,
+ // fprintf(stderr, "%s r:%p status:%s/%s wakeup_status:%s/%s\n", RUBY_FUNCTION_NAME_STRING, (void *)r,
// wait_status_str(r->sync.wait.status), wait_status_str(wait_status),
// wakeup_status_str(r->sync.wait.wakeup_status), wakeup_status_str(wakeup_status));
@@ -546,7 +552,7 @@ ractor_sleep_interrupt(void *ptr)
#if USE_RUBY_DEBUG_LOG
static const char *
-wait_status_str(enum ractor_wait_status wait_status)
+wait_status_str(enum rb_ractor_wait_status wait_status)
{
switch ((int)wait_status) {
case wait_none: return "none";
@@ -562,7 +568,7 @@ wait_status_str(enum ractor_wait_status wait_status)
}
static const char *
-wakeup_status_str(enum ractor_wakeup_status wakeup_status)
+wakeup_status_str(enum rb_ractor_wakeup_status wakeup_status)
{
switch (wakeup_status) {
case wakeup_none: return "none";
@@ -582,7 +588,7 @@ 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,
+ // fprintf(stderr, "%s r:%p status:%s, wakeup_status:%s\n", RUBY_FUNCTION_NAME_STRING, (void *)cr,
// wait_status_str(cr->sync.wait.status), wakeup_status_str(cr->sync.wait.wakeup_status));
RACTOR_UNLOCK(cr);
@@ -723,7 +729,7 @@ 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) {
+ while (UNDEF_P(v = ractor_try_receive(ec, cr))) {
ractor_receive_wait(ec, cr);
}
@@ -754,7 +760,8 @@ 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)));
+ fprintf(stderr, "%d (start:%d) type:%s %p %s\n", i, rq->start, basket_type_name(b->type),
+ (void *)b, RSTRING_PTR(RARRAY_AREF(b->v, 1)));
if (b->type == basket_type_reserved) bug = true;
}
if (bug) rb_bug("!!");
@@ -869,7 +876,7 @@ ractor_receive_if(rb_execution_context_t *ec, VALUE crv, VALUE b)
}
RACTOR_UNLOCK_SELF(cr);
- if (v != Qundef) {
+ if (!UNDEF_P(v)) {
struct receive_block_data data = {
.cr = cr,
.rq = rq,
@@ -881,9 +888,11 @@ ractor_receive_if(rb_execution_context_t *ec, VALUE crv, VALUE b)
VALUE result = rb_ensure(receive_if_body, (VALUE)&data,
receive_if_ensure, (VALUE)&data);
- if (result != Qundef) return result;
+ if (!UNDEF_P(result)) return result;
index++;
}
+
+ RUBY_VM_CHECK_INTS(ec);
}
}
@@ -901,7 +910,7 @@ ractor_send_basket(rb_execution_context_t *ec, rb_ractor_t *r, struct rb_ractor_
else {
ractor_queue_enq(r, rq, b);
if (ractor_wakeup(r, wait_receiving, wakeup_by_send)) {
- RUBY_DEBUG_LOG("wakeup", 0);
+ RUBY_DEBUG_LOG("wakeup");
}
}
}
@@ -1031,7 +1040,7 @@ ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_b
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;
+ enum rb_ractor_wait_status prev_wait_status = r->sync.wait.status;
r->sync.wait.status = wait_moving;
RACTOR_UNLOCK(r);
@@ -1086,8 +1095,8 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VAL
VALUE ret = Qundef;
int i;
bool interrupted = false;
- enum ractor_wait_status wait_status = 0;
- bool yield_p = (yielded_value != Qundef) ? true : false;
+ enum rb_ractor_wait_status wait_status = 0;
+ bool yield_p = !UNDEF_P(yielded_value) ? true : false;
const int alen = rs_len + (yield_p ? 1 : 0);
struct ractor_select_action {
@@ -1144,7 +1153,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VAL
case ractor_select_action_take:
rv = actions[i].v;
v = ractor_try_take(ec, RACTOR_PTR(rv));
- if (v != Qundef) {
+ if (!UNDEF_P(v)) {
*ret_r = rv;
ret = v;
goto cleanup;
@@ -1152,7 +1161,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VAL
break;
case ractor_select_action_receive:
v = ractor_try_receive(ec, cr);
- if (v != Qundef) {
+ if (!UNDEF_P(v)) {
*ret_r = ID2SYM(rb_intern("receive"));
ret = v;
goto cleanup;
@@ -1260,7 +1269,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VAL
}
// check results
- enum ractor_wakeup_status wakeup_status = cr->sync.wait.wakeup_status;
+ enum rb_ractor_wakeup_status wakeup_status = cr->sync.wait.wakeup_status;
cr->sync.wait.wakeup_status = wakeup_none;
switch (wakeup_status) {
@@ -1316,7 +1325,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VAL
goto restart;
}
- VM_ASSERT(ret != Qundef);
+ VM_ASSERT(!UNDEF_P(ret));
return ret;
}
@@ -1348,7 +1357,7 @@ ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r)
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);
+ RUBY_DEBUG_LOG("cancel receiving");
}
}
else {
@@ -1385,7 +1394,7 @@ ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *r)
// raising yielding Ractor
if (!r->yield_atexit &&
ractor_wakeup(r, wait_yielding, wakeup_by_close)) {
- RUBY_DEBUG_LOG("cancel yielding", 0);
+ RUBY_DEBUG_LOG("cancel yielding");
}
}
RACTOR_UNLOCK(r);
@@ -1410,7 +1419,7 @@ 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);
+ ccan_list_add_tail(&vm->ractor.set, &r->vmlr_node);
vm->ractor.cnt++;
}
@@ -1418,7 +1427,7 @@ static void
cancel_single_ractor_mode(void)
{
// enable multi-ractor mode
- RUBY_DEBUG_LOG("enable multi-ractor mode", 0);
+ RUBY_DEBUG_LOG("enable multi-ractor mode");
VALUE was_disabled = rb_gc_enable();
@@ -1430,12 +1439,6 @@ cancel_single_ractor_mode(void)
}
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
@@ -1479,7 +1482,7 @@ vm_remove_ractor(rb_vm_t *vm, rb_ractor_t *cr)
vm->ractor.cnt, vm->ractor.sync.terminate_waiting);
VM_ASSERT(vm->ractor.cnt > 0);
- list_del(&cr->vmlr_node);
+ ccan_list_del(&cr->vmlr_node);
if (vm->ractor.cnt <= 2 && vm->ractor.sync.terminate_waiting) {
rb_native_cond_signal(&vm->ractor.sync.terminate_cond);
@@ -1510,7 +1513,7 @@ 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");
+ fprintf(stderr, "[FATAL] failed to allocate memory for main ractor\n");
exit(EXIT_FAILURE);
}
MEMZERO(r, rb_ractor_t, 1);
@@ -1541,12 +1544,12 @@ rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th)
}
#endif
-void rb_gvl_init(rb_global_vm_lock_t *gvl);
+void rb_thread_sched_init(struct rb_thread_sched *);
void
rb_ractor_living_threads_init(rb_ractor_t *r)
{
- list_head_init(&r->threads.set);
+ ccan_list_head_init(&r->threads.set);
r->threads.cnt = 0;
r->threads.blocking_cnt = 0;
}
@@ -1560,7 +1563,7 @@ ractor_init(rb_ractor_t *r, VALUE name, VALUE loc)
rb_native_cond_initialize(&r->barrier_wait_cond);
// thread management
- rb_gvl_init(&r->threads.gvl);
+ rb_thread_sched_init(&r->threads.sched);
rb_ractor_living_threads_init(r);
// naming
@@ -1603,6 +1606,8 @@ ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VAL
r->verbose = cr->verbose;
r->debug = cr->debug;
+ rb_yjit_before_ractor_spawn();
+ rb_mjit_before_ractor_spawn();
rb_thread_create_ractor(r, args, block);
RB_GC_GUARD(rv);
@@ -1712,12 +1717,6 @@ rb_obj_is_main_ractor(VALUE 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)
{
@@ -1736,7 +1735,7 @@ rb_ractor_thread_list(rb_ractor_t *r)
ts = ALLOCA_N(VALUE, r->threads.cnt);
ts_cnt = 0;
- list_for_each(&r->threads.set, th, lt_node) {
+ ccan_list_for_each(&r->threads.set, th, lt_node) {
switch (th->status) {
case THREAD_RUNNABLE:
case THREAD_STOPPED:
@@ -1765,7 +1764,7 @@ rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th)
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);
+ ccan_list_add_tail(&r->threads.set, &th->lt_node);
r->threads.cnt++;
}
RACTOR_UNLOCK(r);
@@ -1848,7 +1847,7 @@ rb_ractor_living_threads_remove(rb_ractor_t *cr, rb_thread_t *th)
else {
RACTOR_LOCK(cr);
{
- list_del(&th->lt_node);
+ ccan_list_del(&th->lt_node);
cr->threads.cnt--;
}
RACTOR_UNLOCK(cr);
@@ -1922,7 +1921,7 @@ rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r)
rb_threadptr_interrupt(main_th);
}
else {
- RUBY_DEBUG_LOG("killed (%p)", main_th);
+ RUBY_DEBUG_LOG("killed (%p)", (void *)main_th);
}
}
}
@@ -1935,7 +1934,7 @@ 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) {
+ ccan_list_for_each(&vm->ractor.set, r, vmlr_node) {
if (r != vm->ractor.main_ractor) {
rb_ractor_terminate_interrupt_main_thread(r);
}
@@ -2114,7 +2113,7 @@ rb_ractor_dump(void)
rb_vm_t *vm = GET_VM();
rb_ractor_t *r = 0;
- list_for_each(&vm->ractor.set, r, vmlr_node) {
+ ccan_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_));
}
@@ -2251,6 +2250,19 @@ obj_hash_traverse_i(VALUE key, VALUE val, VALUE ptr)
return ST_CONTINUE;
}
+static int
+obj_hash_iv_traverse_i(st_data_t key, st_data_t val, st_data_t ptr)
+{
+ struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr;
+
+ if (obj_traverse_i((VALUE)val, d->data)) {
+ d->stop = true;
+ return ST_STOP;
+ }
+
+ return ST_CONTINUE;
+}
+
static void
obj_traverse_reachable_i(VALUE obj, void *ptr)
{
@@ -2292,7 +2304,7 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
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;
+ if (!UNDEF_P(val) && obj_traverse_i(val, data)) return 1;
}
}
@@ -2309,12 +2321,22 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
case T_OBJECT:
{
- uint32_t len = ROBJECT_NUMIV(obj);
- VALUE *ptr = ROBJECT_IVPTR(obj);
+ if (rb_shape_obj_too_complex(obj)) {
+ struct obj_traverse_callback_data d = {
+ .stop = false,
+ .data = data,
+ };
+ rb_st_foreach(ROBJECT_IV_HASH(obj), obj_hash_iv_traverse_i, (st_data_t)&d);
+ if (d.stop) return 1;
+ }
+ else {
+ uint32_t len = ROBJECT_IV_COUNT(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;
+ for (uint32_t i=0; i<len; i++) {
+ VALUE val = ptr[i];
+ if (!UNDEF_P(val) && obj_traverse_i(val, data)) return 1;
+ }
}
}
break;
@@ -2368,7 +2390,11 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
.stop = false,
.data = data,
};
- rb_objspace_reachable_objects_from(obj, obj_traverse_reachable_i, &d);
+ 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;
@@ -2522,6 +2548,14 @@ rb_ractor_ensure_shareable(VALUE obj, VALUE name)
return obj;
}
+void
+rb_ractor_ensure_main_ractor(const char *msg)
+{
+ if (!rb_ractor_main_p()) {
+ rb_raise(rb_eRactorIsolationError, "%s", msg);
+ }
+}
+
static enum obj_traverse_iterator_result
shareable_p_enter(VALUE obj)
{
@@ -2647,6 +2681,30 @@ obj_hash_traverse_replace_i(st_data_t *key, st_data_t *val, st_data_t ptr, int e
return ST_CONTINUE;
}
+static int
+obj_iv_hash_traverse_replace_foreach_i(st_data_t _key, st_data_t _val, st_data_t _data, int _x)
+{
+ return ST_REPLACE;
+}
+
+static int
+obj_iv_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(*(VALUE *)val, data)) {
+ d->stop = true;
+ return ST_STOP;
+ }
+ else if (*(VALUE *)val != data->replacement) {
+ VALUE v = *(VALUE *)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)
{
@@ -2670,7 +2728,7 @@ obj_refer_only_shareables_p_i(VALUE obj, void *ptr)
int *pcnt = (int *)ptr;
if (!rb_ractor_shareable_p(obj)) {
- pcnt++;
+ *pcnt++;
}
}
@@ -2678,14 +2736,18 @@ static int
obj_refer_only_shareables_p(VALUE obj)
{
int cnt = 0;
- rb_objspace_reachable_objects_from(obj, obj_refer_only_shareables_p_i, &cnt);
+ 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;
+ st_data_t replacement;
if (RB_SPECIAL_CONST_P(obj)) {
data->replacement = obj;
@@ -2698,14 +2760,14 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
case traverse_stop: return 1; // stop search
}
- replacement = data->replacement;
+ replacement = (st_data_t)data->replacement;
- if (UNLIKELY(st_lookup(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t *)&replacement))) {
- data->replacement = replacement;
+ if (UNLIKELY(st_lookup(obj_traverse_replace_rec(data), (st_data_t)obj, &replacement))) {
+ data->replacement = (VALUE)replacement;
return 0;
}
else {
- st_insert(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t)replacement);
+ st_insert(obj_traverse_replace_rec(data), (st_data_t)obj, replacement);
}
if (!data->move) {
@@ -2722,7 +2784,7 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
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) {
+ if (!UNDEF_P(ivtbl->ivptr[i])) {
CHECK_AND_REPLACE(ivtbl->ivptr[i]);
}
}
@@ -2743,16 +2805,31 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
case T_OBJECT:
{
+ if (rb_shape_obj_too_complex(obj)) {
+ st_table * table = ROBJECT_IV_HASH(obj);
+ struct obj_traverse_replace_callback_data d = {
+ .stop = false,
+ .data = data,
+ .src = obj,
+ };
+ rb_st_foreach_with_replace(
+ table,
+ obj_iv_hash_traverse_replace_foreach_i,
+ obj_iv_hash_traverse_replace_i,
+ (st_data_t)&d);
+ }
+ else {
#if USE_TRANSIENT_HEAP
- if (data->move) rb_obj_transient_heap_evacuate(obj, TRUE);
+ if (data->move) rb_obj_transient_heap_evacuate(obj, TRUE);
#endif
- uint32_t len = ROBJECT_NUMIV(obj);
- VALUE *ptr = ROBJECT_IVPTR(obj);
+ uint32_t len = ROBJECT_IV_COUNT(obj);
+ VALUE *ptr = ROBJECT_IVPTR(obj);
- for (uint32_t i=0; i<len; i++) {
- if (ptr[i] != Qundef) {
- CHECK_AND_REPLACE(ptr[i]);
+ for (uint32_t i=0; i<len; i++) {
+ if (!UNDEF_P(ptr[i])) {
+ CHECK_AND_REPLACE(ptr[i]);
+ }
}
}
}
@@ -2851,7 +2928,7 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
rb_bug("unreachable");
}
- data->replacement = replacement;
+ data->replacement = (VALUE)replacement;
if (data->leave_func(obj, data) == traverse_stop) {
return 1;
@@ -2956,7 +3033,7 @@ static VALUE
ractor_move(VALUE obj)
{
VALUE val = rb_obj_traverse_replace(obj, move_enter, move_leave, true);
- if (val != Qundef) {
+ if (!UNDEF_P(val)) {
return val;
}
else {
@@ -2987,7 +3064,7 @@ static VALUE
ractor_copy(VALUE obj)
{
VALUE val = rb_obj_traverse_replace(obj, copy_enter, copy_leave, false);
- if (val != Qundef) {
+ if (!UNDEF_P(val)) {
return val;
}
else {
@@ -3031,9 +3108,9 @@ ractor_local_storage_mark(rb_ractor_t *r)
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) {
+ st_data_t val, k = (st_data_t)key;
+ if (st_delete(r->local_storage, &k, &val) &&
+ (key = (rb_ractor_local_key_t)k)->type->free) {
(*key->type->free)((void *)val);
}
}
@@ -3119,7 +3196,7 @@ static bool
ractor_local_ref(rb_ractor_local_key_t key, void **pret)
{
if (rb_ractor_main_p()) {
- if ((VALUE)key->main_cache != Qundef) {
+ if (!UNDEF_P((VALUE)key->main_cache)) {
*pret = key->main_cache;
return true;
}
@@ -3158,9 +3235,9 @@ ractor_local_set(rb_ractor_local_key_t key, void *ptr)
VALUE
rb_ractor_local_storage_value(rb_ractor_local_key_t key)
{
- VALUE val;
- if (ractor_local_ref(key, (void **)&val)) {
- return val;
+ void *val;
+ if (ractor_local_ref(key, &val)) {
+ return (VALUE)val;
}
else {
return Qnil;
diff --git a/ractor.rb b/ractor.rb
index de7c9a93a7..1031fe499b 100644
--- a/ractor.rb
+++ b/ractor.rb
@@ -1,4 +1,4 @@
-# Ractor is a Actor-model abstraction for Ruby that provides thread-safe parallel execution.
+# Ractor is an Actor-model abstraction for Ruby that provides thread-safe parallel execution.
#
# Ractor.new can make a new Ractor, and it will run in parallel.
#
@@ -195,7 +195,7 @@
# # 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.
+# {Comments syntax}[rdoc-ref:syntax/comments.rdoc] explanation.
#
# == Ractors vs threads
#
@@ -223,7 +223,7 @@
#
# == Reference
#
-# See {Ractor design doc}[rdoc-ref:doc/ractor.md] for more details.
+# See {Ractor design doc}[rdoc-ref:ractor.md] for more details.
#
class Ractor
#
@@ -262,6 +262,10 @@ class Ractor
def self.new(*args, name: nil, &block)
b = block # TODO: builtin bug
raise ArgumentError, "must be called with a block" unless block
+ if __builtin_cexpr!("RBOOL(ruby_single_main_ractor)")
+ warn("Ractor is experimental, and the behavior may change in future versions of Ruby! " \
+ "Also there are many implementation issues.", uplevel: 0, category: :experimental)
+ end
loc = caller_locations(1, 1).first
loc = "#{loc.path}:#{loc.lineno}"
__builtin_ractor_create(loc, name, args, b)
@@ -699,7 +703,7 @@ class Ractor
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))) }
+ id = __builtin_cexpr! %q{ UINT2NUM(rb_ractor_id(RACTOR_PTR(self))) }
status = __builtin_cexpr! %q{
rb_str_new2(ractor_status_str(RACTOR_PTR(self)->status_))
}
@@ -768,7 +772,7 @@ class Ractor
# 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;
+ RBOOL(rb_ractor_shareable_p(obj));
}
end
diff --git a/ractor_core.h b/ractor_core.h
index 879d8683fe..968c12d291 100644
--- a/ractor_core.h
+++ b/ractor_core.h
@@ -5,7 +5,7 @@
#include "vm_debug.h"
#ifndef RACTOR_CHECK_MODE
-#define RACTOR_CHECK_MODE (0 || VM_CHECK_MODE || RUBY_DEBUG)
+#define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE)
#endif
enum rb_ractor_basket_type {
@@ -40,6 +40,24 @@ struct rb_ractor_waiting_list {
rb_ractor_t **ractors;
};
+enum rb_ractor_wait_status {
+ wait_none = 0x00,
+ wait_receiving = 0x01,
+ wait_taking = 0x02,
+ wait_yielding = 0x04,
+ wait_moving = 0x08,
+};
+
+enum rb_ractor_wakeup_status {
+ wakeup_none,
+ wakeup_by_send,
+ wakeup_by_yield,
+ wakeup_by_take,
+ wakeup_by_close,
+ wakeup_by_interrupt,
+ wakeup_by_retry,
+};
+
struct rb_ractor_sync {
// ractor lock
rb_nativethread_lock_t lock;
@@ -56,29 +74,34 @@ struct rb_ractor_sync {
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;
-
+ enum rb_ractor_wait_status status;
+ enum rb_ractor_wakeup_status wakeup_status;
struct rb_ractor_basket yielded_basket;
struct rb_ractor_basket taken_basket;
} wait;
};
+// 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,
+};
+
struct rb_ractor_struct {
struct rb_ractor_pub pub;
@@ -91,11 +114,11 @@ struct rb_ractor_struct {
// thread management
struct {
- struct list_head set;
+ struct ccan_list_head set;
unsigned int cnt;
unsigned int blocking_cnt;
unsigned int sleeper;
- rb_global_vm_lock_t gvl;
+ struct rb_thread_sched sched;
rb_execution_context_t *running_ec;
rb_thread_t *main;
} threads;
@@ -104,29 +127,9 @@ struct rb_ractor_struct {
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;
+ enum ractor_status status_;
+
+ struct ccan_list_node vmlr_node;
// ractor local data
@@ -165,9 +168,9 @@ void rb_ractor_send_parameters(rb_execution_context_t *ec, rb_ractor_t *g, VALUE
VALUE rb_thread_create_ractor(rb_ractor_t *g, VALUE args, VALUE proc); // defined in thread.c
-rb_global_vm_lock_t *rb_ractor_gvl(rb_ractor_t *);
int rb_ractor_living_thread_num(const rb_ractor_t *);
VALUE rb_ractor_thread_list(rb_ractor_t *r);
+bool rb_ractor_p(VALUE rv);
void rb_ractor_living_threads_init(rb_ractor_t *r);
void rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th);
@@ -237,9 +240,11 @@ rb_ractor_sleeper_thread_num(rb_ractor_t *r)
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);
+ if (cr->threads.running_ec != th->ec) {
+ if (0) {
+ ruby_debug_printf("rb_ractor_thread_switch ec:%p->%p\n",
+ (void *)cr->threads.running_ec, (void *)th->ec);
+ }
}
else {
return;
@@ -254,8 +259,10 @@ rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th)
VM_ASSERT(cr == GET_RACTOR());
}
+#define rb_ractor_set_current_ec(cr, ec) rb_ractor_set_current_ec_(cr, ec, __FILE__, __LINE__)
+
static inline void
-rb_ractor_set_current_ec(rb_ractor_t *cr, rb_execution_context_t *ec)
+rb_ractor_set_current_ec_(rb_ractor_t *cr, rb_execution_context_t *ec, const char *file, int line)
{
#ifdef RB_THREAD_LOCAL_SPECIFIER
#ifdef __APPLE__
@@ -266,15 +273,8 @@ rb_ractor_set_current_ec(rb_ractor_t *cr, rb_execution_context_t *ec)
#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
- }
-
+ RUBY_DEBUG_LOG2(file, line, "ec:%p->%p", (void *)cr->threads.running_ec, (void *)ec);
+ VM_ASSERT(cr->threads.running_ec != ec);
cr->threads.running_ec = ec;
}
@@ -288,13 +288,14 @@ rb_ractor_id(const rb_ractor_t *r)
}
#if RACTOR_CHECK_MODE > 0
+# define RACTOR_BELONGING_ID(obj) (*(uint32_t *)(((uintptr_t)(obj)) + rb_gc_obj_slot_size(obj)))
+
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);
+ RACTOR_BELONGING_ID(obj) = rid;
}
static inline void
@@ -310,7 +311,7 @@ rb_ractor_belonging(VALUE obj)
return 0;
}
else {
- return RBASIC(obj)->flags >> 32;
+ return RACTOR_BELONGING_ID(obj);
}
}
diff --git a/random.c b/random.c
index 01796460dd..4b5b7ab6c4 100644
--- a/random.c
+++ b/random.c
@@ -42,9 +42,10 @@
# include <winsock2.h>
# include <windows.h>
# include <wincrypt.h>
+# include <bcrypt.h>
#endif
-#if defined(__OpenBSD__) || defined(__FreeBSD__)
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
/* to define OpenBSD and FreeBSD for version check */
# include <sys/param.h>
#endif
@@ -143,7 +144,7 @@ static rb_random_mt_t *
rand_mt_start(rb_random_mt_t *r)
{
if (!genrand_initialized(&r->mt)) {
- r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef));
+ r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef));
}
return r;
}
@@ -215,7 +216,7 @@ int_pair_to_real_inclusive(uint32_t a, uint32_t b)
r = (double)(uint64_t)((x * m) >> 64);
#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);
+ (((uint64_t)b + (a >> dig_u)) >> dig_r64);
r = (double)x;
#else
/* shift then add to get rid of overflow */
@@ -251,22 +252,15 @@ random_memsize(const void *ptr)
const rb_data_type_t rb_random_data_type = {
"random",
{
- random_mark,
- random_free,
- random_memsize,
+ random_mark,
+ random_free,
+ random_memsize,
},
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);
-}
+#define random_mt_free RUBY_TYPED_DEFAULT_FREE
static size_t
random_mt_memsize(const void *ptr)
@@ -277,9 +271,9 @@ random_mt_memsize(const void *ptr)
static const rb_data_type_t random_mt_type = {
"random/MT",
{
- random_mt_mark,
- random_mt_free,
- random_mt_memsize,
+ random_mt_mark,
+ random_mt_free,
+ random_mt_memsize,
},
&rb_random_data_type,
(void *)&random_mt_if,
@@ -308,7 +302,7 @@ static rb_random_t *
try_get_rnd(VALUE obj)
{
if (obj == rb_cRandom) {
- return rand_start(default_rand());
+ return rand_start(default_rand());
}
if (!rb_typeddata_is_kind_of(obj, &rb_random_data_type)) return NULL;
if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
@@ -325,7 +319,7 @@ 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 &random_mt_if;
}
return rb_rand_if(obj);
}
@@ -371,20 +365,20 @@ rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed)
int sign;
len = rb_absint_numwords(seed, 32, NULL);
+ 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) {
+ rng->init_int32(rnd, len ? buf[0] : 0);
}
- if (len > 1) {
+ else {
if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */
len--;
+ rng->init(rnd, buf, len);
}
- rng->init(rnd, buf, len);
explicit_bzero(buf, len * sizeof(*buf));
ALLOCV_END(buf0);
return seed;
@@ -409,6 +403,15 @@ random_init(int argc, VALUE *argv, VALUE obj)
rb_raise(rb_eTypeError, "undefined random interface: %s",
RTYPEDDATA_TYPE(obj)->wrap_struct_name);
}
+
+ unsigned int major = rng->version.major;
+ unsigned int minor = rng->version.minor;
+ if (major != RUBY_RANDOM_INTERFACE_VERSION_MAJOR) {
+ rb_raise(rb_eTypeError, "Random interface version "
+ STRINGIZE(RUBY_RANDOM_INTERFACE_VERSION_MAJOR) "."
+ STRINGIZE(RUBY_RANDOM_INTERFACE_VERSION_MINOR) " "
+ "expected: %d.%d", major, minor);
+ }
argc = rb_check_arity(argc, 0, 1);
rb_check_frozen(obj);
if (argc == 0) {
@@ -435,12 +438,12 @@ fill_random_bytes_urandom(void *seed, size_t size)
{
unsigned char *p = (unsigned char *)seed;
while (size) {
- size_t len = size < MAX_SEED_LEN_PER_READ ? size : MAX_SEED_LEN_PER_READ;
- if (getentropy(p, len) != 0) {
+ size_t len = size < MAX_SEED_LEN_PER_READ ? size : MAX_SEED_LEN_PER_READ;
+ if (getentropy(p, len) != 0) {
return -1;
- }
- p += len;
- size -= len;
+ }
+ p += len;
+ size -= len;
}
return 0;
}
@@ -455,12 +458,12 @@ fill_random_bytes_urandom(void *seed, size_t size)
*/
int fd = rb_cloexec_open("/dev/urandom",
# ifdef O_NONBLOCK
- O_NONBLOCK|
+ O_NONBLOCK|
# endif
# ifdef O_NOCTTY
- O_NOCTTY|
+ O_NOCTTY|
# endif
- O_RDONLY, 0);
+ O_RDONLY, 0);
struct stat statbuf;
ssize_t ret = 0;
size_t offset = 0;
@@ -468,14 +471,14 @@ fill_random_bytes_urandom(void *seed, size_t size)
if (fd < 0) return -1;
rb_update_max_fd(fd);
if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
- do {
- ret = read(fd, ((char*)seed) + offset, size - offset);
- if (ret < 0) {
- close(fd);
- return -1;
- }
- offset += (size_t)ret;
- } while (offset < size);
+ do {
+ ret = read(fd, ((char*)seed) + offset, size - offset);
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ }
+ offset += (size_t)ret;
+ } while (offset < size);
}
close(fd);
return 0;
@@ -496,28 +499,35 @@ fill_random_bytes_urandom(void *seed, size_t size)
#if 0
#elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
-# if defined MAC_OS_X_VERSION_10_10 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10
+# if defined(USE_COMMON_RANDOM)
+# elif defined MAC_OS_X_VERSION_10_10 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10
+# define USE_COMMON_RANDOM 1
+# else
+# define USE_COMMON_RANDOM 0
+# endif
+# if USE_COMMON_RANDOM
# include <CommonCrypto/CommonCryptoError.h> /* for old Xcode */
# include <CommonCrypto/CommonRandom.h>
-# define USE_COMMON_RANDOM 1
# else
# include <Security/SecRandom.h>
-# define USE_COMMON_RANDOM 0
# endif
static int
fill_random_bytes_syscall(void *seed, size_t size, int unused)
{
#if USE_COMMON_RANDOM
- int failed = CCRandomGenerateBytes(seed, size) != kCCSuccess;
+ CCRNGStatus status = CCRandomGenerateBytes(seed, size);
+ int failed = status != kCCSuccess;
#else
- int failed = SecRandomCopyBytes(kSecRandomDefault, size, seed) != errSecSuccess;
+ int status = SecRandomCopyBytes(kSecRandomDefault, size, seed);
+ int failed = status != errSecSuccess;
#endif
if (failed) {
# if 0
# if USE_COMMON_RANDOM
/* How to get the error message? */
+ fprintf(stderr, "CCRandomGenerateBytes failed: %d\n", status);
# else
CFStringRef s = SecCopyErrorMessageString(status, NULL);
const char *m = s ? CFStringGetCStringPtr(s, kCFStringEncodingUTF8) : NULL;
@@ -544,63 +554,104 @@ fill_random_bytes_syscall(void *buf, size_t size, int unused)
#endif
}
#elif defined(_WIN32)
+
+#ifndef DWORD_MAX
+# define DWORD_MAX (~(DWORD)0UL)
+#endif
+
+# if defined(CRYPT_VERIFYCONTEXT)
+STATIC_ASSERT(sizeof_HCRYPTPROV, sizeof(HCRYPTPROV) == sizeof(size_t));
+
+/* Although HCRYPTPROV is not a HANDLE, it looks like
+ * INVALID_HANDLE_VALUE is not a valid value */
+static const HCRYPTPROV INVALID_HCRYPTPROV = (HCRYPTPROV)INVALID_HANDLE_VALUE;
+
static void
release_crypt(void *p)
{
- HCRYPTPROV prov = (HCRYPTPROV)ATOMIC_PTR_EXCHANGE(*(HCRYPTPROV *)p, INVALID_HANDLE_VALUE);
- if (prov && prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
- CryptReleaseContext(prov, 0);
+ HCRYPTPROV *ptr = p;
+ HCRYPTPROV prov = (HCRYPTPROV)ATOMIC_SIZE_EXCHANGE(*ptr, INVALID_HCRYPTPROV);
+ if (prov && prov != INVALID_HCRYPTPROV) {
+ CryptReleaseContext(prov, 0);
}
}
static int
-fill_random_bytes_syscall(void *seed, size_t size, int unused)
+fill_random_bytes_crypt(void *seed, size_t size)
{
static HCRYPTPROV perm_prov;
HCRYPTPROV prov = perm_prov, old_prov;
if (!prov) {
- if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
- prov = (HCRYPTPROV)INVALID_HANDLE_VALUE;
- }
- old_prov = (HCRYPTPROV)ATOMIC_PTR_CAS(perm_prov, 0, prov);
- if (LIKELY(!old_prov)) { /* no other threads acquired */
- if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
+ if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ prov = INVALID_HCRYPTPROV;
+ }
+ old_prov = (HCRYPTPROV)ATOMIC_SIZE_CAS(perm_prov, 0, prov);
+ if (LIKELY(!old_prov)) { /* no other threads acquired */
+ if (prov != INVALID_HCRYPTPROV) {
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
- rb_gc_register_mark_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov));
- }
- }
- else { /* another thread acquired */
- if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
- CryptReleaseContext(prov, 0);
- }
- prov = old_prov;
- }
+ rb_gc_register_mark_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov));
+ }
+ }
+ else { /* another thread acquired */
+ if (prov != INVALID_HCRYPTPROV) {
+ CryptReleaseContext(prov, 0);
+ }
+ prov = old_prov;
+ }
+ }
+ if (prov == INVALID_HCRYPTPROV) return -1;
+ while (size > 0) {
+ DWORD n = (size > (size_t)DWORD_MAX) ? DWORD_MAX : (DWORD)size;
+ if (!CryptGenRandom(prov, n, seed)) return -1;
+ seed = (char *)seed + n;
+ size -= n;
+ }
+ return 0;
+}
+# else
+# define fill_random_bytes_crypt(seed, size) -1
+# endif
+
+static int
+fill_random_bytes_bcrypt(void *seed, size_t size)
+{
+ while (size > 0) {
+ ULONG n = (size > (size_t)ULONG_MAX) ? LONG_MAX : (ULONG)size;
+ if (BCryptGenRandom(NULL, seed, n, BCRYPT_USE_SYSTEM_PREFERRED_RNG))
+ return -1;
+ seed = (char *)seed + n;
+ size -= n;
}
- if (prov == (HCRYPTPROV)INVALID_HANDLE_VALUE) return -1;
- CryptGenRandom(prov, size, seed);
return 0;
}
+
+static int
+fill_random_bytes_syscall(void *seed, size_t size, int unused)
+{
+ if (fill_random_bytes_bcrypt(seed, size) == 0) return 0;
+ return fill_random_bytes_crypt(seed, size);
+}
#elif defined HAVE_GETRANDOM
static int
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
{
static rb_atomic_t try_syscall = 1;
if (try_syscall) {
- size_t offset = 0;
- int flags = 0;
- if (!need_secure)
- flags = GRND_NONBLOCK;
- do {
- errno = 0;
+ size_t offset = 0;
+ int flags = 0;
+ if (!need_secure)
+ flags = GRND_NONBLOCK;
+ do {
+ errno = 0;
ssize_t ret = getrandom(((char*)seed) + offset, size - offset, flags);
- if (ret == -1) {
- ATOMIC_SET(try_syscall, 0);
- return -1;
- }
- offset += (size_t)ret;
- } while (offset < size);
- return 0;
+ if (ret == -1) {
+ ATOMIC_SET(try_syscall, 0);
+ return -1;
+ }
+ offset += (size_t)ret;
+ } while (offset < size);
+ return 0;
}
return -1;
}
@@ -713,7 +764,7 @@ random_raw_seed(VALUE self, VALUE size)
VALUE buf = rb_str_new(0, n);
if (n == 0) return buf;
if (fill_random_bytes(RSTRING_PTR(buf), n, TRUE))
- rb_raise(rb_eRuntimeError, "failed to get urandom");
+ rb_raise(rb_eRuntimeError, "failed to get urandom");
return buf;
}
@@ -825,16 +876,16 @@ rand_mt_load(VALUE obj, VALUE dump)
left = RARRAY_AREF(dump, 1);
case 1:
state = RARRAY_AREF(dump, 0);
- break;
+ break;
default:
- rb_raise(rb_eArgError, "wrong dump data");
+ rb_raise(rb_eArgError, "wrong dump data");
}
rb_integer_pack(state, mt->state, numberof(mt->state),
sizeof(*mt->state), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
x = NUM2ULONG(left);
if (x > numberof(mt->state)) {
- rb_raise(rb_eArgError, "wrong value");
+ rb_raise(rb_eArgError, "wrong value");
}
mt->left = (unsigned int)x;
mt->next = mt->state + numberof(mt->state) - x + 1;
@@ -844,15 +895,17 @@ rand_mt_load(VALUE obj, VALUE dump)
}
static void
+rand_mt_init_int32(rb_random_t *rnd, uint32_t data)
+{
+ struct MT *mt = &((rb_random_mt_t *)rnd)->mt;
+ init_genrand(mt, data);
+}
+
+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, buf[0]);
- }
- else {
- init_by_array(mt, buf, (int)len);
- }
+ init_by_array(mt, buf, (int)len);
}
static unsigned int
@@ -901,7 +954,7 @@ rb_f_srand(int argc, VALUE *argv, VALUE obj)
seed = random_seed(obj);
}
else {
- seed = rb_to_int(argv[0]);
+ seed = rb_to_int(argv[0]);
}
old = r->base.seed;
rand_init(&random_mt_if, &r->base, seed);
@@ -1024,9 +1077,9 @@ obj_random_bytes(VALUE obj, void *p, long n)
Check_Type(v, T_STRING);
l = RSTRING_LEN(v);
if (l < n)
- rb_raise(rb_eRangeError, "random data too short %ld", l);
+ rb_raise(rb_eRangeError, "random data too short %ld", l);
else if (l > n)
- rb_raise(rb_eRangeError, "random data too long %ld", l);
+ rb_raise(rb_eRangeError, "random data too long %ld", l);
if (p) memcpy(p, RSTRING_PTR(v), n);
return v;
}
@@ -1042,9 +1095,9 @@ rb_random_int32(VALUE obj)
{
rb_random_t *rnd = try_get_rnd(obj);
if (!rnd) {
- uint32_t x;
- obj_random_bytes(obj, &x, sizeof(x));
- return (unsigned int)x;
+ uint32_t x;
+ obj_random_bytes(obj, &x, sizeof(x));
+ return (unsigned int)x;
}
return random_int32(try_rand_if(obj, rnd), rnd);
}
@@ -1055,10 +1108,10 @@ random_real(VALUE obj, rb_random_t *rnd, int excl)
uint32_t a, b;
if (!rnd) {
- uint32_t x[2] = {0, 0};
- obj_random_bytes(obj, x, sizeof(x));
- a = x[0];
- b = x[1];
+ uint32_t x[2] = {0, 0};
+ obj_random_bytes(obj, x, sizeof(x));
+ a = x[0];
+ b = x[1];
}
else {
const rb_random_interface_t *rng = try_rand_if(obj, rnd);
@@ -1073,10 +1126,10 @@ double
rb_int_pair_to_real(uint32_t a, uint32_t b, int excl)
{
if (excl) {
- return int_pair_to_real_exclusive(a, b);
+ return int_pair_to_real_exclusive(a, b);
}
else {
- return int_pair_to_real_inclusive(a, b);
+ return int_pair_to_real_inclusive(a, b);
}
}
@@ -1085,15 +1138,15 @@ rb_random_real(VALUE obj)
{
rb_random_t *rnd = try_get_rnd(obj);
if (!rnd) {
- VALUE v = rb_funcallv(obj, id_rand, 0, 0);
- double d = NUM2DBL(v);
- if (d < 0.0) {
- rb_raise(rb_eRangeError, "random number too small %g", d);
- }
- else if (d >= 1.0) {
- rb_raise(rb_eRangeError, "random number too big %g", d);
- }
- return d;
+ VALUE v = rb_funcallv(obj, id_rand, 0, 0);
+ double d = NUM2DBL(v);
+ if (d < 0.0) {
+ rb_raise(rb_eRangeError, "random number too small %g", d);
+ }
+ else if (d >= 1.0) {
+ rb_raise(rb_eRangeError, "random number too big %g", d);
+ }
+ return d;
}
return random_real(obj, rnd, TRUE);
}
@@ -1105,7 +1158,7 @@ ulong_to_num_plus_1(unsigned long n)
return ULL2NUM((LONG_LONG)n+1);
#else
if (n >= ULONG_MAX) {
- return rb_big_plus(ULONG2NUM(n), INT2FIX(1));
+ return rb_big_plus(ULONG2NUM(n), INT2FIX(1));
}
return ULONG2NUM(n+1);
#endif
@@ -1116,26 +1169,26 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
{
if (!limit) return 0;
if (!rnd) {
- const int w = sizeof(limit) * CHAR_BIT - nlz_long(limit);
- const int n = w > 32 ? sizeof(unsigned long) : sizeof(uint32_t);
- const unsigned long mask = ~(~0UL << w);
- const unsigned long full =
- (size_t)n >= sizeof(unsigned long) ? ~0UL :
- ~(~0UL << n * CHAR_BIT);
- unsigned long val, bits = 0, rest = 0;
- do {
- if (mask & ~rest) {
- union {uint32_t u32; unsigned long ul;} buf;
- obj_random_bytes(obj, &buf, n);
- rest = full;
- bits = (n == sizeof(uint32_t)) ? buf.u32 : buf.ul;
- }
- val = bits;
- bits >>= w;
- rest >>= w;
- val &= mask;
- } while (limit < val);
- return val;
+ const int w = sizeof(limit) * CHAR_BIT - nlz_long(limit);
+ const int n = w > 32 ? sizeof(unsigned long) : sizeof(uint32_t);
+ const unsigned long mask = ~(~0UL << w);
+ const unsigned long full =
+ (size_t)n >= sizeof(unsigned long) ? ~0UL :
+ ~(~0UL << n * CHAR_BIT);
+ unsigned long val, bits = 0, rest = 0;
+ do {
+ if (mask & ~rest) {
+ union {uint32_t u32; unsigned long ul;} buf;
+ obj_random_bytes(obj, &buf, n);
+ rest = full;
+ bits = (n == sizeof(uint32_t)) ? buf.u32 : buf.ul;
+ }
+ val = bits;
+ bits >>= w;
+ rest >>= w;
+ val &= mask;
+ } while (limit < val);
+ return val;
}
return limited_rand(try_rand_if(obj, rnd), rnd, limit);
}
@@ -1145,16 +1198,16 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit)
{
rb_random_t *rnd = try_get_rnd(obj);
if (!rnd) {
- VALUE lim = ulong_to_num_plus_1(limit);
- VALUE v = rb_to_int(rb_funcallv_public(obj, id_rand, 1, &lim));
- unsigned long r = NUM2ULONG(v);
- if (rb_num_negative_p(v)) {
- rb_raise(rb_eRangeError, "random number too small %ld", r);
- }
- if (r > limit) {
- rb_raise(rb_eRangeError, "random number too big %ld", r);
- }
- return r;
+ VALUE lim = ulong_to_num_plus_1(limit);
+ VALUE v = rb_to_int(rb_funcallv_public(obj, id_rand, 1, &lim));
+ unsigned long r = NUM2ULONG(v);
+ if (rb_num_negative_p(v)) {
+ rb_raise(rb_eRangeError, "random number too small %ld", r);
+ }
+ if (r > limit) {
+ rb_raise(rb_eRangeError, "random number too big %ld", r);
+ }
+ return r;
}
return limited_rand(try_rand_if(obj, rnd), rnd, limit);
}
@@ -1163,27 +1216,27 @@ static VALUE
random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
{
if (!rnd) {
- VALUE v, vtmp;
- size_t i, nlz, len = rb_absint_numwords(vmax, 32, &nlz);
- uint32_t *tmp = ALLOCV_N(uint32_t, vtmp, len * 2);
- uint32_t mask = (uint32_t)~0 >> nlz;
- uint32_t *lim_array = tmp;
- uint32_t *rnd_array = tmp + len;
- int flag = INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER;
- rb_integer_pack(vmax, lim_array, len, sizeof(uint32_t), 0, flag);
+ VALUE v, vtmp;
+ size_t i, nlz, len = rb_absint_numwords(vmax, 32, &nlz);
+ uint32_t *tmp = ALLOCV_N(uint32_t, vtmp, len * 2);
+ uint32_t mask = (uint32_t)~0 >> nlz;
+ uint32_t *lim_array = tmp;
+ uint32_t *rnd_array = tmp + len;
+ int flag = INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER;
+ rb_integer_pack(vmax, lim_array, len, sizeof(uint32_t), 0, flag);
retry:
- obj_random_bytes(obj, rnd_array, len * sizeof(uint32_t));
- rnd_array[0] &= mask;
- for (i = 0; i < len; ++i) {
- if (lim_array[i] < rnd_array[i])
- goto retry;
- if (rnd_array[i] < lim_array[i])
- break;
- }
- v = rb_integer_unpack(rnd_array, len, sizeof(uint32_t), 0, flag);
- ALLOCV_END(vtmp);
- return v;
+ obj_random_bytes(obj, rnd_array, len * sizeof(uint32_t));
+ rnd_array[0] &= mask;
+ for (i = 0; i < len; ++i) {
+ if (lim_array[i] < rnd_array[i])
+ goto retry;
+ if (rnd_array[i] < lim_array[i])
+ break;
+ }
+ v = rb_integer_unpack(rnd_array, len, sizeof(uint32_t), 0, flag);
+ ALLOCV_END(vtmp);
+ return v;
}
return limited_big_rand(try_rand_if(obj, rnd), rnd, vmax);
}
@@ -1223,18 +1276,18 @@ rb_rand_bytes_int32(rb_random_get_int32_func *get_int32,
unsigned int r, i;
for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
r = get_int32(rnd);
- i = SIZEOF_INT32;
- do {
- *ptr++ = (char)r;
- r >>= CHAR_BIT;
+ i = SIZEOF_INT32;
+ do {
+ *ptr++ = (char)r;
+ r >>= CHAR_BIT;
} while (--i);
}
if (n > 0) {
r = get_int32(rnd);
- do {
- *ptr++ = (char)r;
- r >>= CHAR_BIT;
- } while (--n);
+ do {
+ *ptr++ = (char)r;
+ r >>= CHAR_BIT;
+ } while (--n);
}
}
@@ -1243,7 +1296,7 @@ rb_random_bytes(VALUE obj, long n)
{
rb_random_t *rnd = try_get_rnd(obj);
if (!rnd) {
- return obj_random_bytes(obj, NULL, n);
+ return obj_random_bytes(obj, NULL, n);
}
return rand_bytes(try_rand_if(obj, rnd), rnd, n);
}
@@ -1261,6 +1314,21 @@ random_s_bytes(VALUE obj, VALUE len)
return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
}
+/*
+ * call-seq: Random.seed -> integer
+ *
+ * Returns the seed value used to initialize the Ruby system PRNG.
+ * This may be used to initialize another generator with the same
+ * state at a later time, causing it to produce the same sequence of
+ * numbers.
+ *
+ * Random.seed #=> 1234
+ * prng1 = Random.new(Random.seed)
+ * prng1.seed #=> 1234
+ * prng1.rand(100) #=> 47
+ * Random.seed #=> 1234
+ * Random.rand(100) #=> 47
+ */
static VALUE
random_s_seed(VALUE obj)
{
@@ -1288,32 +1356,32 @@ rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
unsigned long r;
if (FIXNUM_P(vmax)) {
- long max = FIX2LONG(vmax);
- if (!max) return Qnil;
- if (max < 0) {
- if (restrictive) return Qnil;
- max = -max;
- }
- r = random_ulong_limited(obj, rnd, (unsigned long)max - 1);
- return ULONG2NUM(r);
+ long max = FIX2LONG(vmax);
+ if (!max) return Qnil;
+ if (max < 0) {
+ if (restrictive) return Qnil;
+ max = -max;
+ }
+ r = random_ulong_limited(obj, rnd, (unsigned long)max - 1);
+ return ULONG2NUM(r);
}
else {
- VALUE ret;
- if (rb_bigzero_p(vmax)) return Qnil;
- if (!BIGNUM_SIGN(vmax)) {
- if (restrictive) return Qnil;
+ VALUE ret;
+ if (rb_bigzero_p(vmax)) return Qnil;
+ if (!BIGNUM_SIGN(vmax)) {
+ if (restrictive) return Qnil;
vmax = rb_big_uminus(vmax);
- }
- vmax = rb_big_minus(vmax, INT2FIX(1));
- if (FIXNUM_P(vmax)) {
- long max = FIX2LONG(vmax);
- if (max == -1) return Qnil;
- r = random_ulong_limited(obj, rnd, max);
- return LONG2NUM(r);
- }
- ret = random_ulong_limited_big(obj, rnd, vmax);
- RB_GC_GUARD(vmax);
- return ret;
+ }
+ vmax = rb_big_minus(vmax, INT2FIX(1));
+ if (FIXNUM_P(vmax)) {
+ long max = FIX2LONG(vmax);
+ if (max == -1) return Qnil;
+ r = random_ulong_limited(obj, rnd, max);
+ return LONG2NUM(r);
+ }
+ ret = random_ulong_limited_big(obj, rnd, vmax);
+ RB_GC_GUARD(vmax);
+ return ret;
}
}
@@ -1336,10 +1404,10 @@ check_random_number(VALUE v, const VALUE *argv)
{
switch (v) {
case Qfalse:
- (void)NUM2LONG(argv[0]);
- break;
+ (void)NUM2LONG(argv[0]);
+ break;
case Qnil:
- invalid_argument(argv[0]);
+ invalid_argument(argv[0]);
}
return v;
}
@@ -1348,8 +1416,8 @@ static inline double
float_value(VALUE v)
{
double x = RFLOAT_VALUE(v);
- if (isinf(x) || isnan(x)) {
- domain_error();
+ if (!isfinite(x)) {
+ domain_error();
}
return x;
}
@@ -1361,71 +1429,71 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
int excl = 0;
if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse)
- return Qfalse;
+ return Qfalse;
if (NIL_P(v)) domain_error();
- if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_int(vmax), !NIL_P(v))) {
- long max;
- vmax = v;
- v = Qnil;
+ if (!RB_FLOAT_TYPE_P(vmax) && (v = rb_check_to_int(vmax), !NIL_P(v))) {
+ long max;
+ vmax = v;
+ v = Qnil;
fixnum:
- if (FIXNUM_P(vmax)) {
- if ((max = FIX2LONG(vmax) - excl) >= 0) {
- unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max);
- v = ULONG2NUM(r);
- }
- }
- else if (BUILTIN_TYPE(vmax) == T_BIGNUM && BIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
- vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
- if (FIXNUM_P(vmax)) {
- excl = 0;
- goto fixnum;
- }
- v = random_ulong_limited_big(obj, rnd, vmax);
- }
+ if (FIXNUM_P(vmax)) {
+ if ((max = FIX2LONG(vmax) - excl) >= 0) {
+ unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max);
+ v = ULONG2NUM(r);
+ }
+ }
+ else if (BUILTIN_TYPE(vmax) == T_BIGNUM && BIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
+ vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
+ if (FIXNUM_P(vmax)) {
+ excl = 0;
+ goto fixnum;
+ }
+ v = random_ulong_limited_big(obj, rnd, vmax);
+ }
}
else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
- int scale = 1;
- double max = RFLOAT_VALUE(v), mid = 0.5, r;
- if (isinf(max)) {
- double min = float_value(rb_to_float(beg)) / 2.0;
- max = float_value(rb_to_float(end)) / 2.0;
- scale = 2;
- mid = max + min;
- max -= min;
- }
- else if (isnan(max)) {
- domain_error();
- }
- v = Qnil;
- if (max > 0.0) {
- r = random_real(obj, rnd, excl);
- if (scale > 1) {
- return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
- }
- v = rb_float_new(r * max);
- }
- else if (max == 0.0 && !excl) {
- v = rb_float_new(0.0);
- }
+ int scale = 1;
+ double max = RFLOAT_VALUE(v), mid = 0.5, r;
+ if (isinf(max)) {
+ double min = float_value(rb_to_float(beg)) / 2.0;
+ max = float_value(rb_to_float(end)) / 2.0;
+ scale = 2;
+ mid = max + min;
+ max -= min;
+ }
+ else if (isnan(max)) {
+ domain_error();
+ }
+ v = Qnil;
+ if (max > 0.0) {
+ r = random_real(obj, rnd, excl);
+ if (scale > 1) {
+ return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
+ }
+ v = rb_float_new(r * max);
+ }
+ else if (max == 0.0 && !excl) {
+ v = rb_float_new(0.0);
+ }
}
if (FIXNUM_P(beg) && FIXNUM_P(v)) {
- long x = FIX2LONG(beg) + FIX2LONG(v);
- return LONG2NUM(x);
+ long x = FIX2LONG(beg) + FIX2LONG(v);
+ return LONG2NUM(x);
}
switch (TYPE(v)) {
case T_NIL:
- break;
+ break;
case T_BIGNUM:
- return rb_big_plus(v, beg);
+ return rb_big_plus(v, beg);
case T_FLOAT: {
- VALUE f = rb_check_to_float(beg);
- if (!NIL_P(f)) {
- return DBL2NUM(RFLOAT_VALUE(v) + RFLOAT_VALUE(f));
- }
+ VALUE f = rb_check_to_float(beg);
+ if (!NIL_P(f)) {
+ return DBL2NUM(RFLOAT_VALUE(v) + RFLOAT_VALUE(f));
+ }
}
default:
- return rb_funcallv(beg, id_plus, 1, &v);
+ return rb_funcallv(beg, id_plus, 1, &v);
}
return v;
@@ -1437,6 +1505,7 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
* call-seq:
* prng.rand -> float
* prng.rand(max) -> number
+ * prng.rand(range) -> number
*
* When +max+ is an Integer, +rand+ returns a random integer greater than
* or equal to zero and less than +max+. Unlike Kernel.rand, when +max+
@@ -1450,8 +1519,8 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
*
* prng.rand(1.5) # => 1.4600282860034115
*
- * When +max+ is a Range, +rand+ returns a random number where
- * range.member?(number) == true.
+ * When +range+ is a Range, +rand+ returns a random number where
+ * <code>range.member?(number) == true</code>.
*
* prng.rand(5..9) # => one of [5, 6, 7, 8, 9]
* prng.rand(5...9) # => one of [5, 6, 7, 8]
@@ -1476,35 +1545,37 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
VALUE vmax, v;
if (rb_check_arity(argc, 0, 1) == 0) {
- return rb_float_new(random_real(obj, rnd, TRUE));
+ return rb_float_new(random_real(obj, rnd, TRUE));
}
vmax = argv[0];
if (NIL_P(vmax)) return Qnil;
- if (!RB_TYPE_P(vmax, T_FLOAT)) {
- v = rb_check_to_int(vmax);
- if (!NIL_P(v)) return rand_int(obj, rnd, v, 1);
+ if (!RB_FLOAT_TYPE_P(vmax)) {
+ v = rb_check_to_int(vmax);
+ if (!NIL_P(v)) return rand_int(obj, rnd, v, 1);
}
v = rb_check_to_float(vmax);
if (!NIL_P(v)) {
- const double max = float_value(v);
- if (max < 0.0) {
- return Qnil;
- }
- else {
- double r = random_real(obj, rnd, TRUE);
- if (max > 0.0) r *= max;
- return rb_float_new(r);
- }
+ const double max = float_value(v);
+ if (max < 0.0) {
+ return Qnil;
+ }
+ else {
+ double r = random_real(obj, rnd, TRUE);
+ if (max > 0.0) r *= max;
+ return rb_float_new(r);
+ }
}
return rand_range(obj, rnd, vmax);
}
/*
* call-seq:
- * prng.random_number -> float
- * prng.random_number(max) -> number
- * prng.rand -> float
- * prng.rand(max) -> number
+ * prng.random_number -> float
+ * prng.random_number(max) -> number
+ * prng.random_number(range) -> number
+ * prng.rand -> float
+ * prng.rand(max) -> number
+ * prng.rand(range) -> number
*
* Generates formatted random number from raw random bytes.
* See Random#rand.
@@ -1572,7 +1643,7 @@ rand_mt_equal(VALUE self, VALUE other)
* rand(100) #=> 12
*
* When +max+ is a Range, +rand+ returns a random number where
- * range.member?(number) == true.
+ * <code>range.member?(number) == true</code>.
*
* Negative or floating point values for +max+ are allowed, but may give
* surprising results.
@@ -1595,12 +1666,12 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
VALUE v = rand_range(obj, rnd, vmax);
- if (v != Qfalse) return v;
- vmax = rb_to_int(vmax);
- if (vmax != INT2FIX(0)) {
+ if (v != Qfalse) return v;
+ vmax = rb_to_int(vmax);
+ if (vmax != INT2FIX(0)) {
v = rand_int(obj, rnd, vmax, 0);
- if (!NIL_P(v)) return v;
- }
+ if (!NIL_P(v)) return v;
+ }
}
return DBL2NUM(random_real(obj, rnd, TRUE));
}
@@ -1609,8 +1680,12 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
* call-seq:
* Random.rand -> float
* Random.rand(max) -> number
+ * Random.rand(range) -> number
+ *
+ * Returns a random number using the Ruby system PRNG.
+ *
+ * See also Random#rand.
*/
-
static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
@@ -1652,7 +1727,7 @@ init_hash_salt(struct MT *mt)
int i;
for (i = 0; i < numberof(hash_salt.u32); ++i)
- hash_salt.u32[i] = genrand_int32(mt);
+ hash_salt.u32[i] = genrand_int32(mt);
}
NO_SANITIZE("unsigned-integer-overflow", extern st_index_t rb_hash_start(st_index_t h));
@@ -1728,6 +1803,9 @@ rb_reset_random_seed(void)
* PRNGs are currently implemented as a modified Mersenne Twister with a period
* of 2**19937-1. As this algorithm is _not_ for cryptographical use, you must
* use SecureRandom for security purpose, instead of this PRNG.
+ *
+ * See also Random::Formatter module that adds convenience methods to generate
+ * various forms of random data.
*/
void
@@ -1762,9 +1840,6 @@ InitVM_Random(void)
rb_define_method(rb_cRandom, "seed", random_get_seed, 0);
#endif
- 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);
@@ -1775,12 +1850,21 @@ InitVM_Random(void)
rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);
{
- /* Format raw random number as Random does */
- VALUE m = rb_define_module_under(rb_cRandom, "Formatter");
- 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);
+ /*
+ * Generate a random number in the given range as Random does
+ *
+ * prng.random_number #=> 0.5816771641321361
+ * prng.random_number(1000) #=> 485
+ * prng.random_number(1..6) #=> 3
+ * prng.rand #=> 0.5816771641321361
+ * prng.rand(1000) #=> 485
+ * prng.rand(1..6) #=> 3
+ */
+ VALUE m = rb_define_module_under(rb_cRandom, "Formatter");
+ rb_include_module(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);
diff --git a/range.c b/range.c
index 7d08a49eee..dbc37c1410 100644
--- a/range.c
+++ b/range.c
@@ -47,11 +47,11 @@ static void
range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
{
if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(beg) && !NIL_P(end)) {
- VALUE v;
+ VALUE v;
- v = rb_funcall(beg, id_cmp, 1, end);
- if (NIL_P(v))
- rb_raise(rb_eArgError, "bad value for range");
+ v = rb_funcall(beg, id_cmp, 1, end);
+ if (NIL_P(v))
+ rb_raise(rb_eArgError, "bad value for range");
}
RANGE_SET_EXCL(range, exclude_end);
@@ -78,17 +78,23 @@ range_modify(VALUE range)
rb_check_frozen(range);
/* Ranges are immutable, so that they should be initialized only once. */
if (RANGE_EXCL(range) != Qnil) {
- rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize));
+ rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize));
}
}
/*
* call-seq:
- * Range.new(begin, end, exclude_end=false) -> rng
+ * Range.new(begin, end, exclude_end = false) -> new_range
+ *
+ * Returns a new range based on the given objects +begin+ and +end+.
+ * Optional argument +exclude_end+ determines whether object +end+
+ * is included as the last object in the range:
+ *
+ * Range.new(2, 5).to_a # => [2, 3, 4, 5]
+ * Range.new(2, 5, true).to_a # => [2, 3, 4]
+ * Range.new('a', 'd').to_a # => ["a", "b", "c", "d"]
+ * Range.new('a', 'd', true).to_a # => ["a", "b", "c"]
*
- * Constructs a range using the given +begin+ and +end+. If the +exclude_end+
- * parameter is omitted or is <code>false</code>, the range will include
- * the end object; otherwise, it will be excluded.
*/
static VALUE
@@ -113,12 +119,14 @@ range_initialize_copy(VALUE range, VALUE orig)
/*
* call-seq:
- * rng.exclude_end? -> true or false
+ * exclude_end? -> true or false
*
- * Returns <code>true</code> if the range excludes its end value.
+ * Returns +true+ if +self+ excludes its end value; +false+ otherwise:
*
- * (1..5).exclude_end? #=> false
- * (1...5).exclude_end? #=> true
+ * Range.new(2, 5).exclude_end? # => false
+ * Range.new(2, 5, true).exclude_end? # => true
+ * (2..5).exclude_end? # => false
+ * (2...5).exclude_end? # => true
*/
static VALUE
@@ -132,9 +140,9 @@ recursive_equal(VALUE range, VALUE obj, int recur)
{
if (recur) return Qtrue; /* Subtle! */
if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
- return Qfalse;
+ return Qfalse;
if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
- return Qfalse;
+ return Qfalse;
return RBOOL(EXCL(range) == EXCL(obj));
}
@@ -142,15 +150,32 @@ recursive_equal(VALUE range, VALUE obj, int recur)
/*
* call-seq:
- * rng == obj -> true or false
+ * self == other -> true or false
+ *
+ * Returns +true+ if and only if:
*
- * Returns <code>true</code> only if +obj+ is a Range, has equivalent
- * begin and end items (by comparing them with <code>==</code>), and has
- * the same #exclude_end? setting as the range.
+ * - +other+ is a range.
+ * - <tt>other.begin == self.begin</tt>.
+ * - <tt>other.end == self.end</tt>.
+ * - <tt>other.exclude_end? == self.exclude_end?</tt>.
*
- * (0..2) == (0..2) #=> true
- * (0..2) == Range.new(0,2) #=> true
- * (0..2) == (0...2) #=> false
+ * Otherwise returns +false+.
+ *
+ * r = (1..5)
+ * r == (1..5) # => true
+ * r = Range.new(1, 5)
+ * r == 'foo' # => false
+ * r == (2..5) # => false
+ * r == (1..4) # => false
+ * r == (1...5) # => false
+ * r == Range.new(1, 5, true) # => false
+ *
+ * Note that even with the same argument, the return values of #== and #eql? can differ:
+ *
+ * (1..2) == (1..2.0) # => true
+ * (1..2).eql? (1..2.0) # => false
+ *
+ * Related: Range#eql?.
*
*/
@@ -158,9 +183,9 @@ static VALUE
range_eq(VALUE range, VALUE obj)
{
if (range == obj)
- return Qtrue;
+ return Qtrue;
if (!rb_obj_is_kind_of(obj, rb_cRange))
- return Qfalse;
+ return Qfalse;
return rb_exec_recursive_paired(recursive_equal, range, obj, obj);
}
@@ -176,7 +201,7 @@ r_less(VALUE a, VALUE b)
VALUE r = rb_funcall(a, id_cmp, 1, b);
if (NIL_P(r))
- return INT_MAX;
+ return INT_MAX;
return rb_cmpint(r, a, b);
}
@@ -185,46 +210,62 @@ recursive_eql(VALUE range, VALUE obj, int recur)
{
if (recur) return Qtrue; /* Subtle! */
if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
- return Qfalse;
+ return Qfalse;
if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
- return Qfalse;
+ return Qfalse;
return RBOOL(EXCL(range) == EXCL(obj));
}
/*
* call-seq:
- * rng.eql?(obj) -> true or false
+ * eql?(other) -> true or false
+ *
+ * Returns +true+ if and only if:
+ *
+ * - +other+ is a range.
+ * - <tt>other.begin eql? self.begin</tt>.
+ * - <tt>other.end eql? self.end</tt>.
+ * - <tt>other.exclude_end? == self.exclude_end?</tt>.
+ *
+ * Otherwise returns +false+.
*
- * Returns <code>true</code> only if +obj+ is a Range, has equivalent
- * begin and end items (by comparing them with <code>eql?</code>),
- * and has the same #exclude_end? setting as the range.
+ * r = (1..5)
+ * r.eql?(1..5) # => true
+ * r = Range.new(1, 5)
+ * r.eql?('foo') # => false
+ * r.eql?(2..5) # => false
+ * r.eql?(1..4) # => false
+ * r.eql?(1...5) # => false
+ * r.eql?(Range.new(1, 5, true)) # => false
*
- * (0..2).eql?(0..2) #=> true
- * (0..2).eql?(Range.new(0,2)) #=> true
- * (0..2).eql?(0...2) #=> false
+ * Note that even with the same argument, the return values of #== and #eql? can differ:
*
+ * (1..2) == (1..2.0) # => true
+ * (1..2).eql? (1..2.0) # => false
+ *
+ * Related: Range#==.
*/
static VALUE
range_eql(VALUE range, VALUE obj)
{
if (range == obj)
- return Qtrue;
+ return Qtrue;
if (!rb_obj_is_kind_of(obj, rb_cRange))
- return Qfalse;
+ return Qfalse;
return rb_exec_recursive_paired(recursive_eql, range, obj, obj);
}
/*
* call-seq:
- * rng.hash -> integer
+ * hash -> integer
*
- * Compute a hash-code for this range. Two ranges with equal
- * begin and end points (using <code>eql?</code>), and the same
- * #exclude_end? value will generate the same hash-code.
+ * Returns the integer hash value for +self+.
+ * Two range objects +r0+ and +r1+ have the same hash value
+ * if and only if <tt>r0.eql?(r1)</tt>.
*
- * See also Object#hash.
+ * Related: Range#eql?, Object#hash.
*/
static VALUE
@@ -253,34 +294,41 @@ range_each_func(VALUE range, int (*func)(VALUE, VALUE), VALUE arg)
VALUE v = b;
if (EXCL(range)) {
- while (r_less(v, e) < 0) {
- if ((*func)(v, arg)) break;
- v = rb_funcallv(v, id_succ, 0, 0);
- }
+ while (r_less(v, e) < 0) {
+ if ((*func)(v, arg)) break;
+ v = rb_funcallv(v, id_succ, 0, 0);
+ }
}
else {
- while ((c = r_less(v, e)) <= 0) {
- if ((*func)(v, arg)) break;
- if (!c) break;
- v = rb_funcallv(v, id_succ, 0, 0);
- }
+ while ((c = r_less(v, e)) <= 0) {
+ if ((*func)(v, arg)) break;
+ if (!c) break;
+ v = rb_funcallv(v, id_succ, 0, 0);
+ }
}
}
-static int
-sym_step_i(VALUE i, VALUE arg)
+static bool
+step_i_iter(VALUE arg)
{
VALUE *iter = (VALUE *)arg;
if (FIXNUM_P(iter[0])) {
- iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
+ iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
}
else {
- iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
+ iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
}
- if (iter[0] == INT2FIX(0)) {
- rb_yield(rb_str_intern(i));
- iter[0] = iter[1];
+ if (iter[0] != INT2FIX(0)) return false;
+ iter[0] = iter[1];
+ return true;
+}
+
+static int
+sym_step_i(VALUE i, VALUE arg)
+{
+ if (step_i_iter(arg)) {
+ rb_yield(rb_str_intern(i));
}
return 0;
}
@@ -288,17 +336,8 @@ sym_step_i(VALUE i, VALUE arg)
static int
step_i(VALUE i, VALUE arg)
{
- VALUE *iter = (VALUE *)arg;
-
- if (FIXNUM_P(iter[0])) {
- iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
- }
- else {
- iter[0] = rb_funcall(iter[0], '-', 1, INT2FIX(1));
- }
- if (iter[0] == INT2FIX(0)) {
- rb_yield(i);
- iter[0] = iter[1];
+ if (step_i_iter(arg)) {
+ rb_yield(i);
}
return 0;
}
@@ -306,7 +345,6 @@ step_i(VALUE i, VALUE arg)
static int
discrete_object_p(VALUE obj)
{
- if (rb_obj_is_kind_of(obj, rb_cTime)) return FALSE; /* until Time#succ removed */
return rb_respond_to(obj, id_succ);
}
@@ -318,7 +356,7 @@ linear_object_p(VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_FLOAT:
case T_BIGNUM:
- return TRUE;
+ return TRUE;
default:
break;
}
@@ -333,14 +371,14 @@ check_step_domain(VALUE step)
VALUE zero = INT2FIX(0);
int cmp;
if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
- step = rb_to_int(step);
+ step = rb_to_int(step);
}
cmp = rb_cmpint(rb_funcallv(step, idCmp, 1, &zero), step, zero);
if (cmp < 0) {
- rb_raise(rb_eArgError, "step can't be negative");
+ rb_raise(rb_eArgError, "step can't be negative");
}
else if (cmp == 0) {
- rb_raise(rb_eArgError, "step can't be 0");
+ rb_raise(rb_eArgError, "step can't be 0");
}
return step;
}
@@ -351,55 +389,52 @@ range_step_size(VALUE range, VALUE args, VALUE eobj)
VALUE b = RANGE_BEG(range), e = RANGE_END(range);
VALUE step = INT2FIX(1);
if (args) {
- step = check_step_domain(RARRAY_AREF(args, 0));
+ step = check_step_domain(RARRAY_AREF(args, 0));
}
if (rb_obj_is_kind_of(b, rb_cNumeric) && rb_obj_is_kind_of(e, rb_cNumeric)) {
- return ruby_num_interval_step_size(b, e, step, EXCL(range));
+ return ruby_num_interval_step_size(b, e, step, EXCL(range));
}
return Qnil;
}
/*
- * Document-method: Range#step
- * Document-method: Range#%
* call-seq:
- * rng.step(n=1) {| obj | block } -> rng
- * rng.step(n=1) -> an_enumerator
- * rng.step(n=1) -> an_arithmetic_sequence
- * rng % n -> an_enumerator
- * rng % n -> an_arithmetic_sequence
- *
- * Iterates over the range, passing each <code>n</code>th element to the block.
- * If begin and end are numeric, +n+ is added for each iteration.
- * Otherwise #step invokes #succ to iterate through range elements.
- *
- * If no block is given, an enumerator is returned instead.
- * Especially, the enumerator is an Enumerator::ArithmeticSequence
- * if begin and end of the range are numeric.
- *
- * range = Xs.new(1)..Xs.new(10)
- * range.step(2) {|x| puts x}
- * puts
- * range.step(3) {|x| puts x}
- *
- * <em>produces:</em>
- *
- * 1 x
- * 3 xxx
- * 5 xxxxx
- * 7 xxxxxxx
- * 9 xxxxxxxxx
- *
- * 1 x
- * 4 xxxx
- * 7 xxxxxxx
- * 10 xxxxxxxxxx
- *
- * See Range for the definition of class Xs.
+ * step(n = 1) {|element| ... } -> self
+ * step(n = 1) -> enumerator
+ *
+ * Iterates over the elements of +self+.
+ *
+ * With a block given and no argument,
+ * calls the block each element of the range; returns +self+:
+ *
+ * a = []
+ * (1..5).step {|element| a.push(element) } # => 1..5
+ * a # => [1, 2, 3, 4, 5]
+ * a = []
+ * ('a'..'e').step {|element| a.push(element) } # => "a".."e"
+ * a # => ["a", "b", "c", "d", "e"]
+ *
+ * With a block given and a positive integer argument +n+ given,
+ * calls the block with element +0+, element +n+, element <tt>2n</tt>, and so on:
+ *
+ * a = []
+ * (1..5).step(2) {|element| a.push(element) } # => 1..5
+ * a # => [1, 3, 5]
+ * a = []
+ * ('a'..'e').step(2) {|element| a.push(element) } # => "a".."e"
+ * a # => ["a", "c", "e"]
+ *
+ * With no block given, returns an enumerator,
+ * which will be of class Enumerator::ArithmeticSequence if +self+ is numeric;
+ * otherwise of class Enumerator:
+ *
+ * e = (1..5).step(2) # => ((1..5).step(2))
+ * e.class # => Enumerator::ArithmeticSequence
+ * ('a'..'e').step # => #<Enumerator: ...>
+ *
+ * Related: Range#%.
*/
-
-
static VALUE
range_step(int argc, VALUE *argv, VALUE range)
{
@@ -428,93 +463,112 @@ range_step(int argc, VALUE *argv, VALUE range)
}
step = check_step_domain(step);
+ VALUE iter[2] = {INT2FIX(1), step};
if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(step)) {
- long i = FIX2LONG(b), unit = FIX2LONG(step);
- do {
- rb_yield(LONG2FIX(i));
- i += unit; /* FIXABLE+FIXABLE never overflow */
- } while (FIXABLE(i));
- b = LONG2NUM(i);
+ long i = FIX2LONG(b), unit = FIX2LONG(step);
+ do {
+ rb_yield(LONG2FIX(i));
+ i += unit; /* FIXABLE+FIXABLE never overflow */
+ } while (FIXABLE(i));
+ b = LONG2NUM(i);
- for (;; b = rb_big_plus(b, step))
- rb_yield(b);
+ for (;; b = rb_big_plus(b, step))
+ rb_yield(b);
}
else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
- long end = FIX2LONG(e);
- long i, unit = FIX2LONG(step);
-
- if (!EXCL(range))
- end += 1;
- i = FIX2LONG(b);
- while (i < end) {
- rb_yield(LONG2NUM(i));
- if (i + unit < i) break;
- i += unit;
- }
+ long end = FIX2LONG(e);
+ long i, unit = FIX2LONG(step);
+
+ if (!EXCL(range))
+ end += 1;
+ i = FIX2LONG(b);
+ while (i < end) {
+ rb_yield(LONG2NUM(i));
+ if (i + unit < i) break;
+ i += unit;
+ }
}
else if (SYMBOL_P(b) && (NIL_P(e) || SYMBOL_P(e))) { /* symbols are special */
- VALUE iter[2];
- iter[0] = INT2FIX(1);
- iter[1] = step;
-
- b = rb_sym2str(b);
- if (NIL_P(e)) {
- rb_str_upto_endless_each(b, sym_step_i, (VALUE)iter);
- }
- else {
- rb_str_upto_each(b, rb_sym2str(e), EXCL(range), sym_step_i, (VALUE)iter);
- }
+ b = rb_sym2str(b);
+ if (NIL_P(e)) {
+ rb_str_upto_endless_each(b, sym_step_i, (VALUE)iter);
+ }
+ else {
+ rb_str_upto_each(b, rb_sym2str(e), EXCL(range), sym_step_i, (VALUE)iter);
+ }
}
else if (ruby_float_step(b, e, step, EXCL(range), TRUE)) {
- /* done */
+ /* done */
}
else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
- !NIL_P(rb_check_to_integer(b, "to_int")) ||
- !NIL_P(rb_check_to_integer(e, "to_int"))) {
- ID op = EXCL(range) ? '<' : idLE;
- VALUE v = b;
- int i = 0;
-
- while (NIL_P(e) || RTEST(rb_funcall(v, op, 1, e))) {
- rb_yield(v);
- i++;
- v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
- }
+ !NIL_P(rb_check_to_integer(b, "to_int")) ||
+ !NIL_P(rb_check_to_integer(e, "to_int"))) {
+ ID op = EXCL(range) ? '<' : idLE;
+ VALUE v = b;
+ int i = 0;
+
+ while (NIL_P(e) || RTEST(rb_funcall(v, op, 1, e))) {
+ rb_yield(v);
+ i++;
+ v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
+ }
}
else {
- tmp = rb_check_string_type(b);
-
- if (!NIL_P(tmp)) {
- VALUE iter[2];
-
- b = tmp;
- iter[0] = INT2FIX(1);
- iter[1] = step;
-
- if (NIL_P(e)) {
- rb_str_upto_endless_each(b, step_i, (VALUE)iter);
- }
- else {
- rb_str_upto_each(b, e, EXCL(range), step_i, (VALUE)iter);
- }
- }
- else {
- VALUE args[2];
-
- if (!discrete_object_p(b)) {
- rb_raise(rb_eTypeError, "can't iterate from %s",
- rb_obj_classname(b));
- }
- args[0] = INT2FIX(1);
- args[1] = step;
- range_each_func(range, step_i, (VALUE)args);
- }
+ tmp = rb_check_string_type(b);
+
+ if (!NIL_P(tmp)) {
+ b = tmp;
+ if (NIL_P(e)) {
+ rb_str_upto_endless_each(b, step_i, (VALUE)iter);
+ }
+ else {
+ rb_str_upto_each(b, e, EXCL(range), step_i, (VALUE)iter);
+ }
+ }
+ else {
+ if (!discrete_object_p(b)) {
+ rb_raise(rb_eTypeError, "can't iterate from %s",
+ rb_obj_classname(b));
+ }
+ if (!NIL_P(e))
+ range_each_func(range, step_i, (VALUE)iter);
+ else
+ for (;; b = rb_funcallv(b, id_succ, 0, 0))
+ step_i(b, (VALUE)iter);
+ }
}
return range;
}
+/*
+ * call-seq:
+ * %(n) {|element| ... } -> self
+ * %(n) -> enumerator
+ *
+ * Iterates over the elements of +self+.
+ *
+ * With a block given, calls the block with selected elements of the range;
+ * returns +self+:
+ *
+ * a = []
+ * (1..5).%(2) {|element| a.push(element) } # => 1..5
+ * a # => [1, 3, 5]
+ * a = []
+ * ('a'..'e').%(2) {|element| a.push(element) } # => "a".."e"
+ * a # => ["a", "c", "e"]
+ *
+ * With no block given, returns an enumerator,
+ * which will be of class Enumerator::ArithmeticSequence if +self+ is numeric;
+ * otherwise of class Enumerator:
+ *
+ * e = (1..5) % 2 # => ((1..5).%(2))
+ * e.class # => Enumerator::ArithmeticSequence
+ * ('a'..'e') % 2 # => #<Enumerator: ...>
+ *
+ * Related: Range#step.
+ */
static VALUE
range_percent_step(VALUE range, VALUE step)
{
@@ -532,12 +586,12 @@ int64_as_double_to_num(int64_t i)
{
union int64_double convert;
if (i < 0) {
- convert.i = -i;
- return DBL2NUM(-convert.d);
+ convert.i = -i;
+ return DBL2NUM(-convert.d);
}
else {
- convert.i = i;
- return DBL2NUM(convert.d);
+ convert.i = i;
+ return DBL2NUM(convert.d);
}
}
@@ -557,7 +611,7 @@ is_integer_p(VALUE v)
VALUE is_int;
CONST_ID(id_integer_p, "integer?");
is_int = rb_check_funcall(v, id_integer_p, 0, 0);
- return RTEST(is_int) && is_int != Qundef;
+ return RTEST(is_int) && !UNDEF_P(is_int);
}
static VALUE
@@ -568,29 +622,29 @@ bsearch_integer_range(VALUE beg, VALUE end, int excl)
#define BSEARCH_CHECK(expr) \
do { \
- VALUE val = (expr); \
- VALUE v = rb_yield(val); \
- if (FIXNUM_P(v)) { \
- if (v == INT2FIX(0)) return val; \
- smaller = (SIGNED_VALUE)v < 0; \
- } \
- else if (v == Qtrue) { \
- satisfied = val; \
- smaller = 1; \
- } \
- else if (v == Qfalse || v == Qnil) { \
- smaller = 0; \
- } \
- else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
- int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
- if (!cmp) return val; \
- smaller = cmp < 0; \
- } \
- else { \
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE \
- " (must be numeric, true, false or nil)", \
- rb_obj_class(v)); \
- } \
+ VALUE val = (expr); \
+ VALUE v = rb_yield(val); \
+ if (FIXNUM_P(v)) { \
+ if (v == INT2FIX(0)) return val; \
+ smaller = (SIGNED_VALUE)v < 0; \
+ } \
+ else if (v == Qtrue) { \
+ satisfied = val; \
+ smaller = 1; \
+ } \
+ else if (!RTEST(v)) { \
+ smaller = 0; \
+ } \
+ else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \
+ int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \
+ if (!cmp) return val; \
+ smaller = cmp < 0; \
+ } \
+ else { \
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE \
+ " (must be numeric, true, false or nil)", \
+ rb_obj_class(v)); \
+ } \
} while (0)
VALUE low = rb_to_int(beg);
@@ -603,72 +657,30 @@ bsearch_integer_range(VALUE beg, VALUE end, int excl)
org_high = high;
while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) {
- mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
- BSEARCH_CHECK(mid);
- if (smaller) {
- high = mid;
- }
- else {
- low = rb_funcall(mid, '+', 1, INT2FIX(1));
- }
+ mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2));
+ BSEARCH_CHECK(mid);
+ if (smaller) {
+ high = mid;
+ }
+ else {
+ low = rb_funcall(mid, '+', 1, INT2FIX(1));
+ }
}
if (rb_equal(low, org_high)) {
- BSEARCH_CHECK(low);
- if (!smaller) return Qnil;
+ BSEARCH_CHECK(low);
+ if (!smaller) return Qnil;
}
return satisfied;
}
/*
* call-seq:
- * rng.bsearch {|obj| block } -> value
- *
- * By using binary search, finds a value in range which meets the given
- * condition in O(log n) where n is the size of the range.
- *
- * You can use this method in two use cases: a find-minimum mode and
- * a find-any mode. In either case, the elements of the range must be
- * monotone (or sorted) with respect to the block.
- *
- * In find-minimum mode (this is a good choice for typical use case),
- * the block must return true or false, and there must be a value x
- * so that:
+ * bsearch {|obj| block } -> value
*
- * - the block returns false for any value which is less than x, and
- * - the block returns true for any value which is greater than or
- * equal to x.
+ * Returns an element from +self+ selected by a binary search.
*
- * If x is within the range, this method returns the value x.
- * Otherwise, it returns nil.
+ * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
*
- * ary = [0, 4, 7, 10, 12]
- * (0...ary.size).bsearch {|i| ary[i] >= 4 } #=> 1
- * (0...ary.size).bsearch {|i| ary[i] >= 6 } #=> 2
- * (0...ary.size).bsearch {|i| ary[i] >= 8 } #=> 3
- * (0...ary.size).bsearch {|i| ary[i] >= 100 } #=> nil
- *
- * (0.0...Float::INFINITY).bsearch {|x| Math.log(x) >= 0 } #=> 1.0
- *
- * In find-any mode (this behaves like libc's bsearch(3)), the block
- * must return a number, and there must be two values x and y (x <= y)
- * so that:
- *
- * - the block returns a positive number for v if v < x,
- * - the block returns zero for v if x <= v < y, and
- * - the block returns a negative number for v if y <= v.
- *
- * This method returns any value which is within the intersection of
- * the given range and x...y (if any). If there is no value that
- * satisfies the condition, it returns nil.
- *
- * ary = [0, 100, 100, 100, 200]
- * (0..4).bsearch {|i| 100 - ary[i] } #=> 1, 2 or 3
- * (0..4).bsearch {|i| 300 - ary[i] } #=> nil
- * (0..4).bsearch {|i| 50 - ary[i] } #=> nil
- *
- * You must not mix the two modes at a time; the block must always
- * return either true/false, or always return a number. It is
- * undefined which value is actually picked up at each iteration.
*/
static VALUE
@@ -693,25 +705,25 @@ range_bsearch(VALUE range)
#define BSEARCH(conv) \
do { \
- RETURN_ENUMERATOR(range, 0, 0); \
- if (EXCL(range)) high--; \
- org_high = high; \
- while (low < high) { \
- mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
- : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
- BSEARCH_CHECK(conv(mid)); \
- if (smaller) { \
- high = mid; \
- } \
- else { \
- low = mid + 1; \
- } \
- } \
- if (low == org_high) { \
- BSEARCH_CHECK(conv(low)); \
- if (!smaller) return Qnil; \
- } \
- return satisfied; \
+ RETURN_ENUMERATOR(range, 0, 0); \
+ if (EXCL(range)) high--; \
+ org_high = high; \
+ while (low < high) { \
+ mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \
+ : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \
+ BSEARCH_CHECK(conv(mid)); \
+ if (smaller) { \
+ high = mid; \
+ } \
+ else { \
+ low = mid + 1; \
+ } \
+ } \
+ if (low == org_high) { \
+ BSEARCH_CHECK(conv(low)); \
+ if (!smaller) return Qnil; \
+ } \
+ return satisfied; \
} while (0)
@@ -719,49 +731,49 @@ range_bsearch(VALUE range)
end = RANGE_END(range);
if (FIXNUM_P(beg) && FIXNUM_P(end)) {
- long low = FIX2LONG(beg);
- long high = FIX2LONG(end);
- long mid, org_high;
- BSEARCH(INT2FIX);
+ long low = FIX2LONG(beg);
+ long high = FIX2LONG(end);
+ long mid, org_high;
+ BSEARCH(INT2FIX);
}
#if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
- else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) {
- int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg)));
- int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end)));
- int64_t mid, org_high;
- BSEARCH(int64_as_double_to_num);
+ else if (RB_FLOAT_TYPE_P(beg) || RB_FLOAT_TYPE_P(end)) {
+ int64_t low = double_as_int64(NIL_P(beg) ? -HUGE_VAL : RFLOAT_VALUE(rb_Float(beg)));
+ int64_t high = double_as_int64(NIL_P(end) ? HUGE_VAL : RFLOAT_VALUE(rb_Float(end)));
+ int64_t mid, org_high;
+ BSEARCH(int64_as_double_to_num);
}
#endif
else if (is_integer_p(beg) && is_integer_p(end)) {
- RETURN_ENUMERATOR(range, 0, 0);
- return bsearch_integer_range(beg, end, EXCL(range));
+ RETURN_ENUMERATOR(range, 0, 0);
+ return bsearch_integer_range(beg, end, EXCL(range));
}
else if (is_integer_p(beg) && NIL_P(end)) {
- VALUE diff = LONG2FIX(1);
- RETURN_ENUMERATOR(range, 0, 0);
- while (1) {
- VALUE mid = rb_funcall(beg, '+', 1, diff);
- BSEARCH_CHECK(mid);
- if (smaller) {
- return bsearch_integer_range(beg, mid, 0);
- }
- diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
- }
+ VALUE diff = LONG2FIX(1);
+ RETURN_ENUMERATOR(range, 0, 0);
+ while (1) {
+ VALUE mid = rb_funcall(beg, '+', 1, diff);
+ BSEARCH_CHECK(mid);
+ if (smaller) {
+ return bsearch_integer_range(beg, mid, 0);
+ }
+ diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
+ }
}
else if (NIL_P(beg) && is_integer_p(end)) {
- VALUE diff = LONG2FIX(-1);
- RETURN_ENUMERATOR(range, 0, 0);
- while (1) {
- VALUE mid = rb_funcall(end, '+', 1, diff);
- BSEARCH_CHECK(mid);
- if (!smaller) {
- return bsearch_integer_range(mid, end, 0);
- }
- diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
- }
+ VALUE diff = LONG2FIX(-1);
+ RETURN_ENUMERATOR(range, 0, 0);
+ while (1) {
+ VALUE mid = rb_funcall(end, '+', 1, diff);
+ BSEARCH_CHECK(mid);
+ if (!smaller) {
+ return bsearch_integer_range(mid, end, 0);
+ }
+ diff = rb_funcall(diff, '*', 1, LONG2FIX(2));
+ }
}
else {
- rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
+ rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg));
}
return range;
}
@@ -781,14 +793,18 @@ sym_each_i(VALUE v, VALUE arg)
/*
* call-seq:
- * rng.size -> num
+ * size -> non_negative_integer or Infinity or nil
*
- * Returns the number of elements in the range. Both the begin and the end of
- * the Range must be Numeric, otherwise nil is returned.
+ * Returns the count of elements in +self+
+ * if both begin and end values are numeric;
+ * otherwise, returns +nil+:
*
- * (10..20).size #=> 11
+ * (1..4).size # => 4
+ * (1...4).size # => 3
+ * (1..).size # => Infinity
* ('a'..'z').size #=> nil
- * (-Float::INFINITY..Float::INFINITY).size #=> Infinity
+ *
+ * Related: Range#count.
*/
static VALUE
@@ -797,14 +813,16 @@ range_size(VALUE range)
VALUE b = RANGE_BEG(range), e = RANGE_END(range);
if (rb_obj_is_kind_of(b, rb_cNumeric)) {
if (rb_obj_is_kind_of(e, rb_cNumeric)) {
- return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
+ return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
}
if (NIL_P(e)) {
return DBL2NUM(HUGE_VAL);
}
}
else if (NIL_P(b)) {
- return DBL2NUM(HUGE_VAL);
+ if (rb_obj_is_kind_of(e, rb_cNumeric)) {
+ return DBL2NUM(HUGE_VAL);
+ }
}
return Qnil;
@@ -812,20 +830,23 @@ range_size(VALUE range)
/*
* call-seq:
- * rng.to_a -> array
- * rng.entries -> array
+ * to_a -> array
+ *
+ * Returns an array containing the elements in +self+, if a finite collection;
+ * raises an exception otherwise.
*
- * Returns an array containing the items in the range.
+ * (1..4).to_a # => [1, 2, 3, 4]
+ * (1...4).to_a # => [1, 2, 3]
+ * ('a'..'d').to_a # => ["a", "b", "c", "d"]
*
- * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
- * (1..).to_a #=> RangeError: cannot convert endless range to an array
+ * Range#entries is an alias for Range#to_a.
*/
static VALUE
range_to_a(VALUE range)
{
if (NIL_P(RANGE_END(range))) {
- rb_raise(rb_eRangeError, "cannot convert endless range to an array");
+ rb_raise(rb_eRangeError, "cannot convert endless range to an array");
}
return rb_call_super(0, 0);
}
@@ -870,23 +891,19 @@ range_each_fixnum_loop(VALUE beg, VALUE end, VALUE range)
/*
* call-seq:
- * rng.each {| i | block } -> rng
- * rng.each -> an_enumerator
+ * each {|element| ... } -> self
+ * each -> an_enumerator
*
- * Iterates over the elements of range, passing each in turn to the
- * block.
+ * With a block given, passes each element of +self+ to the block:
*
- * The +each+ method can only be used if the begin object of the range
- * supports the +succ+ method. A TypeError is raised if the object
- * does not have +succ+ method defined (like Float).
+ * a = []
+ * (1..4).each {|element| a.push(element) } # => 1..4
+ * a # => [1, 2, 3, 4]
*
- * If no block is given, an enumerator is returned instead.
+ * Raises an exception unless <tt>self.first.respond_to?(:succ)</tt>.
*
- * (10..15).each {|n| print n, ' ' }
- * # prints: 10 11 12 13 14 15
+ * With no block given, returns an enumerator.
*
- * (2.5..5).each {|n| print n, ' ' }
- * # raises: TypeError: can't iterate from Float
*/
static VALUE
@@ -907,89 +924,92 @@ range_each(VALUE range)
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 */
- if (!FIXNUM_P(beg)) {
- if (RBIGNUM_NEGATIVE_P(beg)) {
- do {
- rb_yield(beg);
- } while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
+ if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
+ if (!FIXNUM_P(beg)) {
+ if (RBIGNUM_NEGATIVE_P(beg)) {
+ do {
+ rb_yield(beg);
+ } while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
if (NIL_P(end)) range_each_fixnum_endless(beg);
if (FIXNUM_P(end)) return range_each_fixnum_loop(beg, end, range);
- }
- else {
+ }
+ else {
if (NIL_P(end)) range_each_bignum_endless(beg);
- if (FIXNUM_P(end)) return range;
- }
- }
- if (FIXNUM_P(beg)) {
- i = FIX2LONG(beg);
- do {
- rb_yield(LONG2FIX(i));
- } while (POSFIXABLE(++i));
- beg = LONG2NUM(i);
- }
- ASSUME(!FIXNUM_P(beg));
- ASSUME(!SPECIAL_CONST_P(end));
- }
- if (!FIXNUM_P(beg) && RBIGNUM_SIGN(beg) == RBIGNUM_SIGN(end)) {
- if (EXCL(range)) {
- while (rb_big_cmp(beg, end) == INT2FIX(-1)) {
- rb_yield(beg);
- beg = rb_big_plus(beg, INT2FIX(1));
- }
- }
- else {
- VALUE c;
- while ((c = rb_big_cmp(beg, end)) != INT2FIX(1)) {
- rb_yield(beg);
- if (c == INT2FIX(0)) break;
- beg = rb_big_plus(beg, INT2FIX(1));
- }
- }
- }
+ if (FIXNUM_P(end)) return range;
+ }
+ }
+ if (FIXNUM_P(beg)) {
+ i = FIX2LONG(beg);
+ do {
+ rb_yield(LONG2FIX(i));
+ } while (POSFIXABLE(++i));
+ beg = LONG2NUM(i);
+ }
+ ASSUME(!FIXNUM_P(beg));
+ ASSUME(!SPECIAL_CONST_P(end));
+ }
+ if (!FIXNUM_P(beg) && RBIGNUM_SIGN(beg) == RBIGNUM_SIGN(end)) {
+ if (EXCL(range)) {
+ while (rb_big_cmp(beg, end) == INT2FIX(-1)) {
+ rb_yield(beg);
+ beg = rb_big_plus(beg, INT2FIX(1));
+ }
+ }
+ else {
+ VALUE c;
+ while ((c = rb_big_cmp(beg, end)) != INT2FIX(1)) {
+ rb_yield(beg);
+ if (c == INT2FIX(0)) break;
+ beg = rb_big_plus(beg, INT2FIX(1));
+ }
+ }
+ }
}
else if (SYMBOL_P(beg) && (NIL_P(end) || SYMBOL_P(end))) { /* symbols are special */
- beg = rb_sym2str(beg);
- if (NIL_P(end)) {
- rb_str_upto_endless_each(beg, sym_each_i, 0);
- }
- else {
- rb_str_upto_each(beg, rb_sym2str(end), EXCL(range), sym_each_i, 0);
- }
+ beg = rb_sym2str(beg);
+ if (NIL_P(end)) {
+ rb_str_upto_endless_each(beg, sym_each_i, 0);
+ }
+ else {
+ rb_str_upto_each(beg, rb_sym2str(end), EXCL(range), sym_each_i, 0);
+ }
}
else {
- VALUE tmp = rb_check_string_type(beg);
-
- if (!NIL_P(tmp)) {
- if (!NIL_P(end)) {
- rb_str_upto_each(tmp, end, EXCL(range), each_i, 0);
- }
- else {
- rb_str_upto_endless_each(tmp, each_i, 0);
- }
- }
- else {
- if (!discrete_object_p(beg)) {
- rb_raise(rb_eTypeError, "can't iterate from %s",
- rb_obj_classname(beg));
- }
- if (!NIL_P(end))
- range_each_func(range, each_i, 0);
- else
- for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
- rb_yield(beg);
- }
+ VALUE tmp = rb_check_string_type(beg);
+
+ if (!NIL_P(tmp)) {
+ if (!NIL_P(end)) {
+ rb_str_upto_each(tmp, end, EXCL(range), each_i, 0);
+ }
+ else {
+ rb_str_upto_endless_each(tmp, each_i, 0);
+ }
+ }
+ else {
+ if (!discrete_object_p(beg)) {
+ rb_raise(rb_eTypeError, "can't iterate from %s",
+ rb_obj_classname(beg));
+ }
+ if (!NIL_P(end))
+ range_each_func(range, each_i, 0);
+ else
+ for (;; beg = rb_funcallv(beg, id_succ, 0, 0))
+ rb_yield(beg);
+ }
}
return range;
}
/*
* call-seq:
- * rng.begin -> obj
+ * self.begin -> object
*
- * Returns the object that defines the beginning of the range.
+ * Returns the object that defines the beginning of +self+.
*
- * (1..10).begin #=> 1
+ * (1..4).begin # => 1
+ * (..2).begin # => nil
+ *
+ * Related: Range#first, Range#end.
*/
static VALUE
@@ -1001,12 +1021,15 @@ range_begin(VALUE range)
/*
* call-seq:
- * rng.end -> obj
+ * self.end -> object
+ *
+ * Returns the object that defines the end of +self+.
*
- * Returns the object that defines the end of the range.
+ * (1..4).end # => 4
+ * (1...4).end # => 4
+ * (1..).end # => nil
*
- * (1..10).end #=> 10
- * (1...10).end #=> 10
+ * Related: Range#begin, Range#last.
*/
@@ -1024,7 +1047,7 @@ first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
long n = NUM2LONG(ary[0]);
if (n <= 0) {
- rb_iter_break();
+ rb_iter_break();
}
rb_ary_push(ary[1], i);
n--;
@@ -1034,14 +1057,24 @@ first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
/*
* call-seq:
- * rng.first -> obj
- * rng.first(n) -> an_array
+ * first -> object
+ * first(n) -> array
*
- * Returns the first object in the range, or an array of the first +n+
- * elements.
+ * With no argument, returns the first element of +self+, if it exists:
*
- * (10..20).first #=> 10
- * (10..20).first(3) #=> [10, 11, 12]
+ * (1..4).first # => 1
+ * ('a'..'d').first # => "a"
+ *
+ * With non-negative integer argument +n+ given,
+ * returns the first +n+ elements in an array:
+ *
+ * (1..10).first(3) # => [1, 2, 3]
+ * (1..10).first(0) # => []
+ * (1..4).first(50) # => [1, 2, 3, 4]
+ *
+ * Raises an exception if there is no first element:
+ *
+ * (..4).first # Raises RangeError
*/
static VALUE
@@ -1080,10 +1113,6 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range)
x = EXCL(range);
len_1 = rb_int_minus(e, b);
- if (FIXNUM_ZERO_P(len_1) || rb_num_negative_p(len_1)) {
- return rb_ary_new_capa(0);
- }
-
if (x) {
e = rb_int_minus(e, ONE);
len = len_1;
@@ -1092,6 +1121,10 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range)
len = rb_int_plus(len_1, ONE);
}
+ if (FIXNUM_ZERO_P(len) || rb_num_negative_p(len)) {
+ return rb_ary_new_capa(0);
+ }
+
rb_scan_args(argc, argv, "1", &nv);
n = NUM2LONG(nv);
if (n < 0) {
@@ -1117,19 +1150,37 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range)
/*
* call-seq:
- * rng.last -> obj
- * rng.last(n) -> an_array
+ * last -> object
+ * last(n) -> array
+ *
+ * With no argument, returns the last element of +self+, if it exists:
+ *
+ * (1..4).last # => 4
+ * ('a'..'d').last # => "d"
+ *
+ * Note that +last+ with no argument returns the end element of +self+
+ * even if #exclude_end? is +true+:
+ *
+ * (1...4).last # => 4
+ * ('a'...'d').last # => "d"
+ *
+ * With non-negative integer argument +n+ given,
+ * returns the last +n+ elements in an array:
*
- * Returns the last object in the range,
- * or an array of the last +n+ elements.
+ * (1..10).last(3) # => [8, 9, 10]
+ * (1..10).last(0) # => []
+ * (1..4).last(50) # => [1, 2, 3, 4]
*
- * Note that with no arguments +last+ will return the object that defines
- * the end of the range even if #exclude_end? is +true+.
+ * Note that +last+ with argument does not return the end element of +self+
+ * if #exclude_end? it +true+:
+ *
+ * (1...4).last(3) # => [1, 2, 3]
+ * ('a'...'d').last(3) # => ["a", "b", "c"]
+ *
+ * Raises an exception if there is no last element:
+ *
+ * (1..).last # Raises RangeError
*
- * (10..20).last #=> 20
- * (10...20).last #=> 20
- * (10..20).last(3) #=> [18, 19, 20]
- * (10...20).last(3) #=> [17, 18, 19]
*/
static VALUE
@@ -1154,19 +1205,82 @@ range_last(int argc, VALUE *argv, VALUE range)
/*
* call-seq:
- * rng.min -> obj
- * rng.min {| a,b | block } -> obj
- * rng.min(n) -> array
- * rng.min(n) {| a,b | block } -> array
+ * min -> object
+ * min(n) -> array
+ * min {|a, b| ... } -> object
+ * min(n) {|a, b| ... } -> array
+ *
+ * Returns the minimum value in +self+,
+ * using method <tt><=></tt> or a given block for comparison.
+ *
+ * With no argument and no block given,
+ * returns the minimum-valued element of +self+.
+ *
+ * (1..4).min # => 1
+ * ('a'..'d').min # => "a"
+ * (-4..-1).min # => -4
+ *
+ * With non-negative integer argument +n+ given, and no block given,
+ * returns the +n+ minimum-valued elements of +self+ in an array:
+ *
+ * (1..4).min(2) # => [1, 2]
+ * ('a'..'d').min(2) # => ["a", "b"]
+ * (-4..-1).min(2) # => [-4, -3]
+ * (1..4).min(50) # => [1, 2, 3, 4]
+ *
+ * If a block is given, it is called:
+ *
+ * - First, with the first two element of +self+.
+ * - Then, sequentially, with the so-far minimum value and the next element of +self+.
+ *
+ * To illustrate:
+ *
+ * (1..4).min {|a, b| p [a, b]; a <=> b } # => 1
+ *
+ * Output:
+ *
+ * [2, 1]
+ * [3, 1]
+ * [4, 1]
+ *
+ * With no argument and a block given,
+ * returns the return value of the last call to the block:
+ *
+ * (1..4).min {|a, b| -(a <=> b) } # => 4
+ *
+ * With non-negative integer argument +n+ given, and a block given,
+ * returns the return values of the last +n+ calls to the block in an array:
+ *
+ * (1..4).min(2) {|a, b| -(a <=> b) } # => [4, 3]
+ * (1..4).min(50) {|a, b| -(a <=> b) } # => [4, 3, 2, 1]
+ *
+ * Returns an empty array if +n+ is zero:
+ *
+ * (1..4).min(0) # => []
+ * (1..4).min(0) {|a, b| -(a <=> b) } # => []
*
- * Returns the minimum value in the range. Returns +nil+ if the begin
- * value of the range is larger than the end value. Returns +nil+ if
- * the begin value of an exclusive range is equal to the end value.
+ * Returns +nil+ or an empty array if:
*
- * Can be given an optional block to override the default comparison
- * method <code>a <=> b</code>.
+ * - The begin value of the range is larger than the end value:
*
- * (10..20).min #=> 10
+ * (4..1).min # => nil
+ * (4..1).min(2) # => []
+ * (4..1).min {|a, b| -(a <=> b) } # => nil
+ * (4..1).min(2) {|a, b| -(a <=> b) } # => []
+ *
+ * - The begin value of an exclusive range is equal to the end value:
+ *
+ * (1...1).min # => nil
+ * (1...1).min(2) # => []
+ * (1...1).min {|a, b| -(a <=> b) } # => nil
+ * (1...1).min(2) {|a, b| -(a <=> b) } # => []
+ *
+ * Raises an exception if either:
+ *
+ * - +self+ is a beginless range: <tt>(..4)</tt>.
+ * - A block is given and +self+ is an endless range.
+ *
+ * Related: Range#max, Range#minmax.
*/
@@ -1174,65 +1288,108 @@ static VALUE
range_min(int argc, VALUE *argv, VALUE range)
{
if (NIL_P(RANGE_BEG(range))) {
- rb_raise(rb_eRangeError, "cannot get the minimum of beginless range");
+ rb_raise(rb_eRangeError, "cannot get the minimum of beginless range");
}
if (rb_block_given_p()) {
if (NIL_P(RANGE_END(range))) {
rb_raise(rb_eRangeError, "cannot get the minimum of endless range with custom comparison method");
}
- return rb_call_super(argc, argv);
+ return rb_call_super(argc, argv);
}
else if (argc != 0) {
- return range_first(argc, argv, range);
+ return range_first(argc, argv, range);
}
else {
- struct cmp_opt_data cmp_opt = { 0, 0 };
- VALUE b = RANGE_BEG(range);
- VALUE e = RANGE_END(range);
- int c = NIL_P(e) ? -1 : OPTIMIZED_CMP(b, e, cmp_opt);
+ VALUE b = RANGE_BEG(range);
+ VALUE e = RANGE_END(range);
+ int c = NIL_P(e) ? -1 : OPTIMIZED_CMP(b, e);
- if (c > 0 || (c == 0 && EXCL(range)))
- return Qnil;
- return b;
+ if (c > 0 || (c == 0 && EXCL(range)))
+ return Qnil;
+ return b;
}
}
/*
* call-seq:
- * rng.max -> obj
- * rng.max {| a,b | block } -> obj
- * rng.max(n) -> obj
- * rng.max(n) {| a,b | block } -> obj
+ * max -> object
+ * max(n) -> array
+ * max {|a, b| ... } -> object
+ * max(n) {|a, b| ... } -> array
*
- * Returns the maximum value in the range, or an array of maximum
- * values in the range if given an \Integer argument.
+ * Returns the maximum value in +self+,
+ * using method <tt><=></tt> or a given block for comparison.
*
- * For inclusive ranges with an end, the maximum value of the range
- * is the same as the end of the range.
+ * With no argument and no block given,
+ * returns the maximum-valued element of +self+.
*
- * 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.
+ * (1..4).max # => 4
+ * ('a'..'d').max # => "d"
+ * (-4..-1).max # => -1
*
- * 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.
+ * With non-negative integer argument +n+ given, and no block given,
+ * returns the +n+ maximum-valued elements of +self+ in an array:
*
- * 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.
+ * (1..4).max(2) # => [4, 3]
+ * ('a'..'d').max(2) # => ["d", "c"]
+ * (-4..-1).max(2) # => [-1, -2]
+ * (1..4).max(50) # => [4, 3, 2, 1]
+ *
+ * If a block is given, it is called:
+ *
+ * - First, with the first two element of +self+.
+ * - Then, sequentially, with the so-far maximum value and the next element of +self+.
+ *
+ * To illustrate:
+ *
+ * (1..4).max {|a, b| p [a, b]; a <=> b } # => 4
+ *
+ * Output:
+ *
+ * [2, 1]
+ * [3, 2]
+ * [4, 3]
+ *
+ * With no argument and a block given,
+ * returns the return value of the last call to the block:
+ *
+ * (1..4).max {|a, b| -(a <=> b) } # => 1
+ *
+ * With non-negative integer argument +n+ given, and a block given,
+ * returns the return values of the last +n+ calls to the block in an array:
+ *
+ * (1..4).max(2) {|a, b| -(a <=> b) } # => [1, 2]
+ * (1..4).max(50) {|a, b| -(a <=> b) } # => [1, 2, 3, 4]
+ *
+ * Returns an empty array if +n+ is zero:
+ *
+ * (1..4).max(0) # => []
+ * (1..4).max(0) {|a, b| -(a <=> b) } # => []
+ *
+ * Returns +nil+ or an empty array if:
+ *
+ * - The begin value of the range is larger than the end value:
+ *
+ * (4..1).max # => nil
+ * (4..1).max(2) # => []
+ * (4..1).max {|a, b| -(a <=> b) } # => nil
+ * (4..1).max(2) {|a, b| -(a <=> b) } # => []
+ *
+ * - The begin value of an exclusive range is equal to the end value:
+ *
+ * (1...1).max # => nil
+ * (1...1).max(2) # => []
+ * (1...1).max {|a, b| -(a <=> b) } # => nil
+ * (1...1).max(2) {|a, b| -(a <=> b) } # => []
+ *
+ * Raises an exception if either:
+ *
+ * - +self+ is a endless range: <tt>(1..)</tt>.
+ * - A block is given and +self+ is a beginless range.
+ *
+ * Related: Range#min, Range#minmax.
*
- * 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
@@ -1242,7 +1399,7 @@ range_max(int argc, VALUE *argv, VALUE range)
int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric);
if (NIL_P(RANGE_END(range))) {
- rb_raise(rb_eRangeError, "cannot get the maximum of endless range");
+ rb_raise(rb_eRangeError, "cannot get the maximum of endless range");
}
VALUE b = RANGE_BEG(range);
@@ -1254,8 +1411,7 @@ range_max(int argc, VALUE *argv, VALUE range)
return rb_call_super(argc, argv);
}
else {
- struct cmp_opt_data cmp_opt = { 0, 0 };
- int c = NIL_P(b) ? -1 : OPTIMIZED_CMP(b, e, cmp_opt);
+ int c = NIL_P(b) ? -1 : OPTIMIZED_CMP(b, e);
if (c > 0)
return Qnil;
@@ -1278,14 +1434,48 @@ range_max(int argc, VALUE *argv, VALUE range)
/*
* call-seq:
- * rng.minmax -> [obj, obj]
- * rng.minmax {| a,b | block } -> [obj, obj]
+ * minmax -> [object, object]
+ * minmax {|a, b| ... } -> [object, object]
+ *
+ * Returns a 2-element array containing the minimum and maximum value in +self+,
+ * either according to comparison method <tt><=></tt> or a given block.
+ *
+ * With no block given, returns the minimum and maximum values,
+ * using <tt><=></tt> for comparison:
+ *
+ * (1..4).minmax # => [1, 4]
+ * (1...4).minmax # => [1, 3]
+ * ('a'..'d').minmax # => ["a", "d"]
+ * (-4..-1).minmax # => [-4, -1]
+ *
+ * With a block given, the block must return an integer:
+ *
+ * - Negative if +a+ is smaller than +b+.
+ * - Zero if +a+ and +b+ are equal.
+ * - Positive if +a+ is larger than +b+.
+ *
+ * The block is called <tt>self.size</tt> times to compare elements;
+ * returns a 2-element Array containing the minimum and maximum values from +self+,
+ * per the block:
+ *
+ * (1..4).minmax {|a, b| -(a <=> b) } # => [4, 1]
+ *
+ * Returns <tt>[nil, nil]</tt> if:
+ *
+ * - The begin value of the range is larger than the end value:
+ *
+ * (4..1).minmax # => [nil, nil]
+ * (4..1).minmax {|a, b| -(a <=> b) } # => [nil, nil]
+ *
+ * - The begin value of an exclusive range is equal to the end value:
*
- * Returns a two element array which contains the minimum and the
- * maximum value in the range.
+ * (1...1).minmax # => [nil, nil]
+ * (1...1).minmax {|a, b| -(a <=> b) } # => [nil, nil]
+ *
+ * Raises an exception if +self+ is a beginless or an endless range.
+ *
+ * Related: Range#min, Range#max.
*
- * Can be given an optional block to override the default comparison
- * method <code>a <=> b</code>.
*/
static VALUE
@@ -1307,22 +1497,22 @@ rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
int excl;
if (rb_obj_is_kind_of(range, rb_cRange)) {
- b = RANGE_BEG(range);
- e = RANGE_END(range);
- excl = EXCL(range);
+ b = RANGE_BEG(range);
+ e = RANGE_END(range);
+ excl = EXCL(range);
}
else if (RTEST(rb_obj_is_kind_of(range, rb_cArithSeq))) {
return (int)Qfalse;
}
else {
- VALUE x;
- b = rb_check_funcall(range, id_beg, 0, 0);
- if (b == Qundef) return (int)Qfalse;
- e = rb_check_funcall(range, id_end, 0, 0);
- if (e == Qundef) return (int)Qfalse;
- x = rb_check_funcall(range, rb_intern("exclude_end?"), 0, 0);
- if (x == Qundef) return (int)Qfalse;
- excl = RTEST(x);
+ VALUE x;
+ b = rb_check_funcall(range, id_beg, 0, 0);
+ if (UNDEF_P(b)) return (int)Qfalse;
+ e = rb_check_funcall(range, id_end, 0, 0);
+ if (UNDEF_P(e)) return (int)Qfalse;
+ x = rb_check_funcall(range, rb_intern("exclude_end?"), 0, 0);
+ if (UNDEF_P(x)) return (int)Qfalse;
+ excl = RTEST(x);
}
*begp = b;
*endp = e;
@@ -1407,10 +1597,23 @@ rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
/*
* call-seq:
- * rng.to_s -> string
+ * to_s -> string
+ *
+ * Returns a string representation of +self+,
+ * including <tt>begin.to_s</tt> and <tt>end.to_s</tt>:
+ *
+ * (1..4).to_s # => "1..4"
+ * (1...4).to_s # => "1...4"
+ * (1..).to_s # => "1.."
+ * (..4).to_s # => "..4"
+ *
+ * Note that returns from #to_s and #inspect may differ:
+ *
+ * ('a'..'d').to_s # => "a..d"
+ * ('a'..'d').inspect # => "\"a\"..\"d\""
+ *
+ * Related: Range#inspect.
*
- * Convert this range object to a printable form (using #to_s to convert the
- * begin and end objects).
*/
static VALUE
@@ -1433,7 +1636,7 @@ inspect_range(VALUE range, VALUE dummy, int recur)
VALUE str, str2 = Qundef;
if (recur) {
- return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
+ return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
}
if (!NIL_P(RANGE_BEG(range)) || NIL_P(RANGE_END(range))) {
str = rb_str_dup(rb_inspect(RANGE_BEG(range)));
@@ -1445,17 +1648,30 @@ inspect_range(VALUE range, VALUE dummy, int recur)
if (NIL_P(RANGE_BEG(range)) || !NIL_P(RANGE_END(range))) {
str2 = rb_inspect(RANGE_END(range));
}
- if (str2 != Qundef) rb_str_append(str, str2);
+ if (!UNDEF_P(str2)) rb_str_append(str, str2);
return str;
}
/*
* call-seq:
- * rng.inspect -> string
+ * inspect -> string
+ *
+ * Returns a string representation of +self+,
+ * including <tt>begin.inspect</tt> and <tt>end.inspect</tt>:
+ *
+ * (1..4).inspect # => "1..4"
+ * (1...4).inspect # => "1...4"
+ * (1..).inspect # => "1.."
+ * (..4).inspect # => "..4"
+ *
+ * Note that returns from #to_s and #inspect may differ:
+ *
+ * ('a'..'d').to_s # => "a..d"
+ * ('a'..'d').inspect # => "\"a\"..\"d\""
+ *
+ * Related: Range#to_s.
*
- * Convert this range object to a printable form (using #inspect to
- * convert the begin and end objects).
*/
@@ -1465,143 +1681,317 @@ range_inspect(VALUE range)
return rb_exec_recursive(inspect_range, range, 0);
}
-static VALUE range_include_internal(VALUE range, VALUE val, int string_use_cover);
+static VALUE range_include_internal(VALUE range, VALUE val);
+static VALUE range_string_cover_internal(VALUE range, VALUE val);
+VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
/*
* call-seq:
- * rng === obj -> true or false
+ * self === object -> true or false
+ *
+ * Returns +true+ if +object+ is between <tt>self.begin</tt> and <tt>self.end</tt>.
+ * +false+ otherwise:
*
- * Returns <code>true</code> if +obj+ is between begin and end of range,
- * <code>false</code> otherwise (same as #cover?). Conveniently,
- * <code>===</code> is the comparison operator used by <code>case</code>
- * statements.
+ * (1..4) === 2 # => true
+ * (1..4) === 5 # => false
+ * (1..4) === 'a' # => false
+ * (1..4) === 4 # => true
+ * (1...4) === 4 # => false
+ * ('a'..'d') === 'c' # => true
+ * ('a'..'d') === 'e' # => false
+ *
+ * A case statement uses method <tt>===</tt>, and so:
*
* case 79
- * when 1..50 then puts "low"
- * when 51..75 then puts "medium"
- * when 76..100 then puts "high"
- * end
- * # Prints "high"
+ * when (1..50)
+ * "low"
+ * when (51..75)
+ * "medium"
+ * when (76..100)
+ * "high"
+ * end # => "high"
*
* case "2.6.5"
- * when ..."2.4" then puts "EOL"
- * when "2.4"..."2.5" then puts "maintenance"
- * when "2.5"..."2.7" then puts "stable"
- * when "2.7".. then puts "upcoming"
- * end
- * # Prints "stable"
+ * when ..."2.4"
+ * "EOL"
+ * when "2.4"..."2.5"
+ * "maintenance"
+ * when "2.5"..."3.0"
+ * "stable"
+ * when "3.1"..
+ * "upcoming"
+ * end # => "stable"
*
*/
static VALUE
range_eqq(VALUE range, VALUE val)
{
- VALUE ret = range_include_internal(range, val, 1);
- if (ret != Qundef) return ret;
+ VALUE ret = range_string_cover_internal(range, val);
+ if (!UNDEF_P(ret)) return ret;
return r_cover_p(range, RANGE_BEG(range), RANGE_END(range), val);
}
/*
* call-seq:
- * rng.member?(obj) -> true or false
- * rng.include?(obj) -> true or false
+ * include?(object) -> true or false
*
- * Returns <code>true</code> if +obj+ is an element of
- * the range, <code>false</code> otherwise.
+ * Returns +true+ if +object+ is an element of +self+, +false+ otherwise:
*
- * ("a".."z").include?("g") #=> true
- * ("a".."z").include?("A") #=> false
- * ("a".."z").include?("cc") #=> false
+ * (1..4).include?(2) # => true
+ * (1..4).include?(5) # => false
+ * (1..4).include?(4) # => true
+ * (1...4).include?(4) # => false
+ * ('a'..'d').include?('b') # => true
+ * ('a'..'d').include?('e') # => false
+ * ('a'..'d').include?('B') # => false
+ * ('a'..'d').include?('d') # => true
+ * ('a'...'d').include?('d') # => false
*
- * If you need to ensure +obj+ is between +begin+ and +end+, use #cover?
+ * If begin and end are numeric, #include? behaves like #cover?
*
- * ("a".."z").cover?("cc") #=> true
+ * (1..3).include?(1.5) # => true
+ * (1..3).cover?(1.5) # => true
*
- * If begin and end are numeric, #include? behaves like #cover?
+ * But when not numeric, the two methods may differ:
+ *
+ * ('a'..'d').include?('cc') # => false
+ * ('a'..'d').cover?('cc') # => true
+ *
+ * Related: Range#cover?.
*
- * (1..3).include?(1.5) # => true
+ * Range#member? is an alias for Range#include?.
*/
static VALUE
range_include(VALUE range, VALUE val)
{
- VALUE ret = range_include_internal(range, val, 0);
- if (ret != Qundef) return ret;
+ VALUE ret = range_include_internal(range, val);
+ if (!UNDEF_P(ret)) return ret;
return rb_call_super(1, &val);
}
+static inline bool
+range_integer_edge_p(VALUE beg, VALUE end)
+{
+ return (!NIL_P(rb_check_to_integer(beg, "to_int")) ||
+ !NIL_P(rb_check_to_integer(end, "to_int")));
+}
+
+static inline bool
+range_string_edge_p(VALUE beg, VALUE end)
+{
+ return RB_TYPE_P(beg, T_STRING) || RB_TYPE_P(end, T_STRING);
+}
+
+static inline bool
+range_string_range_p(VALUE beg, VALUE end)
+{
+ return RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING);
+}
+
+static inline VALUE
+range_include_fallback(VALUE beg, VALUE end, VALUE val)
+{
+ if (NIL_P(beg) && NIL_P(end)) {
+ if (linear_object_p(val)) return Qtrue;
+ }
+
+ if (NIL_P(beg) || NIL_P(end)) {
+ rb_raise(rb_eTypeError, "cannot determine inclusion in beginless/endless ranges");
+ }
+
+ return Qundef;
+}
+
static VALUE
-range_include_internal(VALUE range, VALUE val, int string_use_cover)
+range_string_cover_internal(VALUE range, VALUE val)
{
VALUE beg = RANGE_BEG(range);
VALUE end = RANGE_END(range);
int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
- linear_object_p(beg) || linear_object_p(end);
+ linear_object_p(beg) || linear_object_p(end);
- if (nv ||
- !NIL_P(rb_check_to_integer(beg, "to_int")) ||
- !NIL_P(rb_check_to_integer(end, "to_int"))) {
- return r_cover_p(range, beg, end, val);
+ if (nv || range_integer_edge_p(beg, end)) {
+ return r_cover_p(range, beg, end, val);
}
- else if (RB_TYPE_P(beg, T_STRING) || RB_TYPE_P(end, T_STRING)) {
- if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) {
- if (string_use_cover) {
- return r_cover_p(range, beg, end, val);
- }
- else {
- VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
- return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range));
+ else if (range_string_edge_p(beg, end)) {
+ if (range_string_range_p(beg, end)) {
+ return r_cover_p(range, beg, end, val);
+ }
+ if (NIL_P(beg)) {
+unbounded_begin:;
+ VALUE r = rb_funcall(val, id_cmp, 1, end);
+ if (NIL_P(r)) return Qfalse;
+ if (RANGE_EXCL(range)) {
+ return RBOOL(rb_cmpint(r, val, end) < 0);
}
+ return RBOOL(rb_cmpint(r, val, end) <= 0);
}
- else if (NIL_P(beg)) {
- VALUE r = rb_funcall(val, id_cmp, 1, end);
- if (NIL_P(r)) return Qfalse;
- if (rb_cmpint(r, val, end) <= 0) return Qtrue;
- return Qfalse;
+ else if (NIL_P(end)) {
+unbounded_end:;
+ VALUE r = rb_funcall(beg, id_cmp, 1, val);
+ if (NIL_P(r)) return Qfalse;
+ return RBOOL(rb_cmpint(r, beg, val) <= 0);
}
- else if (NIL_P(end)) {
- VALUE r = rb_funcall(beg, id_cmp, 1, val);
- if (NIL_P(r)) return Qfalse;
- if (rb_cmpint(r, beg, val) <= 0) return Qtrue;
- return Qfalse;
- }
}
- return Qundef;
+
+ if (!NIL_P(beg) && NIL_P(end)) {
+ goto unbounded_end;
+ }
+ if (NIL_P(beg) && !NIL_P(end)) {
+ goto unbounded_begin;
+ }
+
+ return range_include_fallback(beg, end, val);
+}
+
+static VALUE
+range_include_internal(VALUE range, VALUE val)
+{
+ VALUE beg = RANGE_BEG(range);
+ VALUE end = RANGE_END(range);
+ int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
+ linear_object_p(beg) || linear_object_p(end);
+
+ if (nv || range_integer_edge_p(beg, end)) {
+ return r_cover_p(range, beg, end, val);
+ }
+ else if (range_string_range_p(beg, end)) {
+ return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range));
+ }
+
+ return range_include_fallback(beg, end, val);
}
static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val);
/*
* call-seq:
- * rng.cover?(obj) -> true or false
- * rng.cover?(range) -> true or false
- *
- * Returns <code>true</code> if +obj+ is between the begin and end of
- * the range.
- *
- * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
- * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
- *
- * If called with a Range argument, returns <code>true</code> when the
- * given range is covered by the receiver,
- * by comparing the begin and end values. If the argument can be treated as
- * a sequence, this method treats it that way. In the specific case of
- * <code>(a..b).cover?(c...d)</code> with <code>a <= c && b < d</code>,
- * the end of the sequence must be calculated, which may exhibit poor
- * performance if <code>c</code> is non-numeric.
- * Returns <code>false</code> if the begin value of the
- * range is larger than the end value. Also returns +false+ if one of the
- * internal calls to <code><=></code> returns +nil+ (indicating the objects
- * are not comparable).
- *
- * ("a".."z").cover?("c") #=> true
- * ("a".."z").cover?("5") #=> false
- * ("a".."z").cover?("cc") #=> true
- * ("a".."z").cover?(1) #=> false
- * (1..5).cover?(2..3) #=> true
- * (1..5).cover?(0..6) #=> false
- * (1..5).cover?(1...6) #=> true
+ * cover?(object) -> true or false
+ * cover?(range) -> true or false
+ *
+ * Returns +true+ if the given argument is within +self+, +false+ otherwise.
+ *
+ * With non-range argument +object+, evaluates with <tt><=</tt> and <tt><</tt>.
+ *
+ * For range +self+ with included end value (<tt>#exclude_end? == false</tt>),
+ * evaluates thus:
+ *
+ * self.begin <= object <= self.end
+ *
+ * Examples:
+ *
+ * r = (1..4)
+ * r.cover?(1) # => true
+ * r.cover?(4) # => true
+ * r.cover?(0) # => false
+ * r.cover?(5) # => false
+ * r.cover?('foo') # => false
+
+ * r = ('a'..'d')
+ * r.cover?('a') # => true
+ * r.cover?('d') # => true
+ * r.cover?(' ') # => false
+ * r.cover?('e') # => false
+ * r.cover?(0) # => false
+ *
+ * For range +r+ with excluded end value (<tt>#exclude_end? == true</tt>),
+ * evaluates thus:
+ *
+ * r.begin <= object < r.end
+ *
+ * Examples:
+ *
+ * r = (1...4)
+ * r.cover?(1) # => true
+ * r.cover?(3) # => true
+ * r.cover?(0) # => false
+ * r.cover?(4) # => false
+ * r.cover?('foo') # => false
+
+ * r = ('a'...'d')
+ * r.cover?('a') # => true
+ * r.cover?('c') # => true
+ * r.cover?(' ') # => false
+ * r.cover?('d') # => false
+ * r.cover?(0) # => false
+ *
+ * With range argument +range+, compares the first and last
+ * elements of +self+ and +range+:
+ *
+ * r = (1..4)
+ * r.cover?(1..4) # => true
+ * r.cover?(0..4) # => false
+ * r.cover?(1..5) # => false
+ * r.cover?('a'..'d') # => false
+
+ * r = (1...4)
+ * r.cover?(1..3) # => true
+ * r.cover?(1..4) # => false
+ *
+ * If begin and end are numeric, #cover? behaves like #include?
+ *
+ * (1..3).cover?(1.5) # => true
+ * (1..3).include?(1.5) # => true
+ *
+ * But when not numeric, the two methods may differ:
+ *
+ * ('a'..'d').cover?('cc') # => true
+ * ('a'..'d').include?('cc') # => false
+ *
+ * Returns +false+ if either:
+ *
+ * - The begin value of +self+ is larger than its end value.
+ * - An internal call to <tt><=></tt> returns +nil+;
+ * that is, the operands are not comparable.
+ *
+ * Beginless ranges cover all values of the same type before the end,
+ * excluding the end for exclusive ranges. Beginless ranges cover
+ * ranges that end before the end of the beginless range, or at the
+ * end of the beginless range for inclusive ranges.
+ *
+ * (..2).cover?(1) # => true
+ * (..2).cover?(2) # => true
+ * (..2).cover?(3) # => false
+ * (...2).cover?(2) # => false
+ * (..2).cover?("2") # => false
+ * (..2).cover?(..2) # => true
+ * (..2).cover?(...2) # => true
+ * (..2).cover?(.."2") # => false
+ * (...2).cover?(..2) # => false
+ *
+ * Endless ranges cover all values of the same type after the
+ * beginning. Endless exclusive ranges do not cover endless
+ * inclusive ranges.
+ *
+ * (2..).cover?(1) # => false
+ * (2..).cover?(3) # => true
+ * (2...).cover?(3) # => true
+ * (2..).cover?(2) # => true
+ * (2..).cover?("2") # => false
+ * (2..).cover?(2..) # => true
+ * (2..).cover?(2...) # => true
+ * (2..).cover?("2"..) # => false
+ * (2...).cover?(2..) # => false
+ * (2...).cover?(3...) # => true
+ * (2...).cover?(3..) # => false
+ * (3..).cover?(2..) # => false
+ *
+ * Ranges that are both beginless and endless cover all values and
+ * ranges, and return true for all arguments, with the exception that
+ * beginless and endless exclusive ranges do not cover endless
+ * inclusive ranges.
+ *
+ * (nil...).cover?(Object.new) # => true
+ * (nil...).cover?(nil...) # => true
+ * (nil..).cover?(nil...) # => true
+ * (nil...).cover?(nil..) # => false
+ * (nil...).cover?(1..) # => false
+ *
+ * Related: Range#include?.
+ *
*/
static VALUE
@@ -1638,7 +2028,16 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
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);
+
+ if (!NIL_P(val_end) && !NIL_P(end)) {
+ VALUE r_cmp_end = rb_funcall(end, id_cmp, 1, val_end);
+ if (NIL_P(r_cmp_end)) return FALSE;
+ cmp_end = rb_cmpint(r_cmp_end, end, val_end);
+ }
+ else {
+ cmp_end = r_less(end, val_end);
+ }
+
if (EXCL(range) == EXCL(val)) {
return cmp_end >= 0;
@@ -1651,7 +2050,7 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
}
val_max = rb_rescue2(r_call_max, val, 0, Qnil, rb_eTypeError, (VALUE)0);
- if (val_max == Qnil) return FALSE;
+ if (NIL_P(val_max)) return FALSE;
return r_less(end, val_max) >= 0;
}
@@ -1660,9 +2059,9 @@ static VALUE
r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val)
{
if (NIL_P(beg) || r_less(beg, val) <= 0) {
- int excl = EXCL(range);
- if (NIL_P(end) || r_less(val, end) <= -excl)
- return Qtrue;
+ int excl = EXCL(range);
+ if (NIL_P(end) || r_less(val, end) <= -excl)
+ return Qtrue;
}
return Qfalse;
}
@@ -1692,7 +2091,7 @@ range_loader(VALUE range, VALUE obj)
end = rb_ivar_get(obj, id_end);
excl = rb_ivar_get(obj, id_excl);
if (!NIL_P(excl)) {
- range_init(range, beg, end, RBOOL(RTEST(excl)));
+ range_init(range, beg, end, RBOOL(RTEST(excl)));
}
return range;
}
@@ -1707,13 +2106,34 @@ range_alloc(VALUE klass)
/*
* call-seq:
- * range.count -> int
- * range.count(item) -> int
- * range.count { |obj| block } -> int
+ * count -> integer
+ * count(object) -> integer
+ * count {|element| ... } -> integer
+ *
+ * Returns the count of elements, based on an argument or block criterion, if given.
+ *
+ * With no argument and no block given, returns the number of elements:
+ *
+ * (1..4).count # => 4
+ * (1...4).count # => 3
+ * ('a'..'d').count # => 4
+ * ('a'...'d').count # => 3
+ * (1..).count # => Infinity
+ * (..4).count # => Infinity
+ *
+ * With argument +object+, returns the number of +object+ found in +self+,
+ * which will usually be zero or one:
*
- * Identical to Enumerable#count, except it returns Infinity for endless
- * ranges.
+ * (1..4).count(2) # => 1
+ * (1..4).count(5) # => 0
+ * (1..4).count('a') # => 0
*
+ * With a block given, calls the block with each element;
+ * returns the number of elements for which the block returns a truthy value:
+ *
+ * (1..4).count {|element| element < 3 } # => 2
+ *
+ * Related: Range#size.
*/
static VALUE
range_count(int argc, VALUE *argv, VALUE range)
@@ -1741,96 +2161,227 @@ range_count(int argc, VALUE *argv, VALUE range)
}
}
-/* A Range represents an interval---a set of values with a
- * beginning and an end. Ranges may be constructed using the
- * <em>s</em><code>..</code><em>e</em> and
- * <em>s</em><code>...</code><em>e</em> literals, or with
- * Range::new. Ranges constructed using <code>..</code>
- * run from the beginning to the end inclusively. Those created using
- * <code>...</code> exclude the end value. When used as an iterator,
- * ranges return each value in the sequence.
- *
- * (-1..-5).to_a #=> []
- * (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
- * ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
- * ('a'...'e').to_a #=> ["a", "b", "c", "d"]
- *
- * == Beginless/Endless Ranges
- *
- * A "beginless range" and "endless range" represents a semi-infinite
- * range. Literal notation for a beginless range is:
- *
- * (..1)
- * # or
- * (...1)
- *
- * Literal notation for an endless range is:
- *
- * (1..)
- * # or similarly
- * (1...)
- *
- * Which is equivalent to
- *
- * (1..nil) # or similarly (1...nil)
- * Range.new(1, nil) # or Range.new(1, nil, true)
- *
- * Beginless/endless ranges are useful, for example, for idiomatic
- * slicing of arrays:
- *
- * [1, 2, 3, 4, 5][...2] # => [1, 2]
- * [1, 2, 3, 4, 5][2...] # => [3, 4, 5]
- *
- * Some implementation details:
- *
- * * +begin+ of beginless range and +end+ of endless range are +nil+;
- * * +each+ of beginless range raises an exception;
- * * +each+ of endless range enumerates infinite sequence (may be
- * useful in combination with Enumerable#take_while or similar
- * methods);
- * * <code>(1..)</code> and <code>(1...)</code> are not equal,
- * although technically representing the same sequence.
- *
- * == Custom Objects in Ranges
- *
- * Ranges can be constructed using any objects that can be compared
- * using the <code><=></code> operator.
- * Methods that treat the range as a sequence (#each and methods inherited
- * from Enumerable) expect the begin object to implement a
- * <code>succ</code> method to return the next object in sequence.
- * The #step and #include? methods require the begin
- * object to implement <code>succ</code> or to be numeric.
- *
- * In the <code>Xs</code> class below both <code><=></code> and
- * <code>succ</code> are implemented so <code>Xs</code> can be used
- * to construct ranges. Note that the Comparable module is included
- * so the <code>==</code> method is defined in terms of <code><=></code>.
- *
- * class Xs # represent a string of 'x's
- * include Comparable
- * attr :length
- * def initialize(n)
- * @length = n
- * end
- * def succ
- * Xs.new(@length + 1)
- * end
- * def <=>(other)
- * @length <=> other.length
- * end
- * def to_s
- * sprintf "%2d #{inspect}", @length
- * end
- * def inspect
- * 'x' * @length
- * end
+/* A \Range object represents a collection of values
+ * that are between given begin and end values.
+ *
+ * You can create an \Range object explicitly with:
+ *
+ * - A {range literal}[rdoc-ref:syntax/literals.rdoc@Range+Literals]:
+ *
+ * # Ranges that use '..' to include the given end value.
+ * (1..4).to_a # => [1, 2, 3, 4]
+ * ('a'..'d').to_a # => ["a", "b", "c", "d"]
+ * # Ranges that use '...' to exclude the given end value.
+ * (1...4).to_a # => [1, 2, 3]
+ * ('a'...'d').to_a # => ["a", "b", "c"]
+ *
+ * A range may be created using method Range.new:
+ *
+ * # Ranges that by default include the given end value.
+ * Range.new(1, 4).to_a # => [1, 2, 3, 4]
+ * Range.new('a', 'd').to_a # => ["a", "b", "c", "d"]
+ * # Ranges that use third argument +exclude_end+ to exclude the given end value.
+ * Range.new(1, 4, true).to_a # => [1, 2, 3]
+ * Range.new('a', 'd', true).to_a # => ["a", "b", "c"]
+ *
+ * == Beginless Ranges
+ *
+ * A _beginless_ _range_ has a definite end value, but a +nil+ begin value.
+ * Such a range includes all values up to the end value.
+ *
+ * r = (..4) # => nil..4
+ * r.begin # => nil
+ * r.include?(-50) # => true
+ * r.include?(4) # => true
+ *
+ * r = (...4) # => nil...4
+ * r.include?(4) # => false
+ *
+ * Range.new(nil, 4) # => nil..4
+ * Range.new(nil, 4, true) # => nil...4
+ *
+ * A beginless range may be used to slice an array:
+ *
+ * a = [1, 2, 3, 4]
+ * r = (..2) # => nil...2
+ * a[r] # => [1, 2]
+ *
+ * \Method +each+ for a beginless range raises an exception.
+ *
+ * == Endless Ranges
+ *
+ * An _endless_ _range_ has a definite begin value, but a +nil+ end value.
+ * Such a range includes all values from the begin value.
+ *
+ * r = (1..) # => 1..
+ * r.end # => nil
+ * r.include?(50) # => true
+ *
+ * Range.new(1, nil) # => 1..
+ *
+ * The literal for an endless range may be written with either two dots
+ * or three.
+ * The range has the same elements, either way.
+ * But note that the two are not equal:
+ *
+ * r0 = (1..) # => 1..
+ * r1 = (1...) # => 1...
+ * r0.begin == r1.begin # => true
+ * r0.end == r1.end # => true
+ * r0 == r1 # => false
+ *
+ * An endless range may be used to slice an array:
+ *
+ * a = [1, 2, 3, 4]
+ * r = (2..) # => 2..
+ * a[r] # => [3, 4]
+ *
+ * \Method +each+ for an endless range calls the given block indefinitely:
+ *
+ * a = []
+ * r = (1..)
+ * r.each do |i|
+ * a.push(i) if i.even?
+ * break if i > 10
+ * end
+ * a # => [2, 4, 6, 8, 10]
+ *
+ * A range can be both beginless and endless. For literal beginless, endless
+ * ranges, at least the beginning or end of the range must be given as an
+ * explicit nil value. It is recommended to use an explicit nil beginning and
+ * implicit nil end, since that is what Ruby uses for Range#inspect:
+ *
+ * (nil..) # => (nil..)
+ * (..nil) # => (nil..)
+ * (nil..nil) # => (nil..)
+ *
+ * == Ranges and Other Classes
+ *
+ * An object may be put into a range if its class implements
+ * instance method <tt><=></tt>.
+ * Ruby core classes that do so include Array, Complex, File::Stat,
+ * Float, Integer, Kernel, Module, Numeric, Rational, String, Symbol, and Time.
+ *
+ * Example:
+ *
+ * t0 = Time.now # => 2021-09-19 09:22:48.4854986 -0500
+ * t1 = Time.now # => 2021-09-19 09:22:56.0365079 -0500
+ * t2 = Time.now # => 2021-09-19 09:23:08.5263283 -0500
+ * (t0..t2).include?(t1) # => true
+ * (t0..t1).include?(t2) # => false
+ *
+ * A range can be iterated over only if its elements
+ * implement instance method +succ+.
+ * Ruby core classes that do so include Integer, String, and Symbol
+ * (but not the other classes mentioned above).
+ *
+ * Iterator methods include:
+ *
+ * - In \Range itself: #each, #step, and #%
+ * - Included from module Enumerable: #each_entry, #each_with_index,
+ * #each_with_object, #each_slice, #each_cons, and #reverse_each.
+ *
+ * Example:
+ *
+ * a = []
+ * (1..4).each {|i| a.push(i) }
+ * a # => [1, 2, 3, 4]
+ *
+ * == Ranges and User-Defined Classes
+ *
+ * A user-defined class that is to be used in a range
+ * must implement instance <tt><=></tt>;
+ * see Integer#<=>.
+ * To make iteration available, it must also implement
+ * instance method +succ+; see Integer#succ.
+ *
+ * The class below implements both <tt><=></tt> and +succ+,
+ * and so can be used both to construct ranges and to iterate over them.
+ * Note that the Comparable module is included
+ * so the <tt>==</tt> method is defined in terms of <tt><=></tt>.
+ *
+ * # Represent a string of 'X' characters.
+ * class Xs
+ * include Comparable
+ * attr_accessor :length
+ * def initialize(n)
+ * @length = n
+ * end
+ * def succ
+ * Xs.new(@length + 1)
+ * end
+ * def <=>(other)
+ * @length <=> other.length
+ * end
+ * def to_s
+ * sprintf "%2d #{inspect}", @length
+ * end
+ * def inspect
+ * 'X' * @length
* end
+ * end
+ *
+ * r = Xs.new(3)..Xs.new(6) #=> XXX..XXXXXX
+ * r.to_a #=> [XXX, XXXX, XXXXX, XXXXXX]
+ * r.include?(Xs.new(5)) #=> true
+ * r.include?(Xs.new(7)) #=> false
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere. \Class \Range:
+ *
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
+ * which provides dozens of additional methods.
+ *
+ * Here, class \Range provides methods that are useful for:
+ *
+ * - {Creating a Range}[rdoc-ref:Range@Methods+for+Creating+a+Range]
+ * - {Querying}[rdoc-ref:Range@Methods+for+Querying]
+ * - {Comparing}[rdoc-ref:Range@Methods+for+Comparing]
+ * - {Iterating}[rdoc-ref:Range@Methods+for+Iterating]
+ * - {Converting}[rdoc-ref:Range@Methods+for+Converting]
+ *
+ * === Methods for Creating a \Range
+ *
+ * - ::new: Returns a new range.
+ *
+ * === Methods for Querying
+ *
+ * - #begin: Returns the begin value given for +self+.
+ * - #bsearch: Returns an element from +self+ selected by a binary search.
+ * - #count: Returns a count of elements in +self+.
+ * - #end: Returns the end value given for +self+.
+ * - #exclude_end?: Returns whether the end object is excluded.
+ * - #first: Returns the first elements of +self+.
+ * - #hash: Returns the integer hash code.
+ * - #last: Returns the last elements of +self+.
+ * - #max: Returns the maximum values in +self+.
+ * - #min: Returns the minimum values in +self+.
+ * - #minmax: Returns the minimum and maximum values in +self+.
+ * - #size: Returns the count of elements in +self+.
+ *
+ * === Methods for Comparing
+ *
+ * - #==: Returns whether a given object is equal to +self+ (uses #==).
+ * - #===: Returns whether the given object is between the begin and end values.
+ * - #cover?: Returns whether a given object is within +self+.
+ * - #eql?: Returns whether a given object is equal to +self+ (uses #eql?).
+ * - #include? (aliased as #member?): Returns whether a given object
+ * is an element of +self+.
+ *
+ * === Methods for Iterating
+ *
+ * - #%: Requires argument +n+; calls the block with each +n+-th element of +self+.
+ * - #each: Calls the block with each element of +self+.
+ * - #step: Takes optional argument +n+ (defaults to 1);
+ calls the block with each +n+-th element of +self+.
*
- * An example of using <code>Xs</code> to construct a range:
+ * === Methods for Converting
*
- * r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
- * r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
- * r.member?(Xs.new(5)) #=> true
+ * - #inspect: Returns a string representation of +self+ (uses #inspect).
+ * - #to_a (aliased as #entries): Returns elements of +self+ in an array.
+ * - #to_s: Returns a string representation of +self+ (uses #to_s).
*
*/
diff --git a/rational.c b/rational.c
index 7324f78621..dfe2ad74eb 100644
--- a/rational.c
+++ b/rational.c
@@ -15,8 +15,14 @@
#include <ieeefp.h>
#endif
+#if !defined(USE_GMP)
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
-#define USE_GMP
+# define USE_GMP 1
+#else
+# define USE_GMP 0
+#endif
+#endif
+#if USE_GMP
#include <gmp.h>
#endif
@@ -46,7 +52,6 @@ static ID id_abs, id_integer_p,
#define id_idiv idDiv
#define id_to_i idTo_i
-#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
#define f_inspect rb_inspect
#define f_to_s rb_obj_as_string
@@ -57,9 +62,9 @@ inline static VALUE
f_add(VALUE x, VALUE y)
{
if (FIXNUM_ZERO_P(y))
- return x;
+ return x;
if (FIXNUM_ZERO_P(x))
- return y;
+ return y;
if (RB_INTEGER_TYPE_P(x))
return rb_int_plus(x, y);
return rb_funcall(x, '+', 1, y);
@@ -69,9 +74,9 @@ inline static VALUE
f_div(VALUE x, VALUE y)
{
if (y == ONE)
- return x;
+ return x;
if (RB_INTEGER_TYPE_P(x))
- return rb_int_div(x, y);
+ return rb_int_div(x, y);
return rb_funcall(x, '/', 1, y);
}
@@ -79,7 +84,7 @@ inline static int
f_lt_p(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y))
- return (SIGNED_VALUE)x < (SIGNED_VALUE)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);
@@ -102,13 +107,13 @@ inline static VALUE
f_mul(VALUE x, VALUE y)
{
if (FIXNUM_ZERO_P(y) && RB_INTEGER_TYPE_P(x))
- return ZERO;
+ return ZERO;
if (y == ONE) return x;
if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
- return ZERO;
+ return ZERO;
if (x == ONE) return y;
else if (RB_INTEGER_TYPE_P(x))
- return rb_int_mul(x, y);
+ return rb_int_mul(x, y);
return rb_funcall(x, '*', 1, y);
}
@@ -116,7 +121,7 @@ inline static VALUE
f_sub(VALUE x, VALUE y)
{
if (FIXNUM_P(y) && FIXNUM_ZERO_P(y))
- return x;
+ return x;
return rb_funcall(x, '-', 1, y);
}
@@ -124,12 +129,12 @@ inline static VALUE
f_abs(VALUE x)
{
if (RB_INTEGER_TYPE_P(x))
- return rb_int_abs(x);
+ return rb_int_abs(x);
return rb_funcall(x, id_abs, 0);
}
-inline static VALUE
+inline static int
f_integer_p(VALUE x)
{
return RB_INTEGER_TYPE_P(x);
@@ -139,7 +144,7 @@ inline static VALUE
f_to_i(VALUE x)
{
if (RB_TYPE_P(x, T_STRING))
- return rb_str_to_inum(x, 10, 0);
+ return rb_str_to_inum(x, 10, 0);
return rb_funcall(x, id_to_i, 0);
}
@@ -147,7 +152,7 @@ inline static int
f_eqeq_p(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y))
- return x == y;
+ return x == y;
if (RB_INTEGER_TYPE_P(x))
return RTEST(rb_int_equal(x, y));
return (int)rb_equal(x, y);
@@ -157,7 +162,7 @@ inline static VALUE
f_idiv(VALUE x, VALUE y)
{
if (RB_INTEGER_TYPE_P(x))
- return rb_int_idiv(x, y);
+ return rb_int_idiv(x, y);
return rb_funcall(x, id_idiv, 1, y);
}
@@ -167,12 +172,12 @@ inline static int
f_zero_p(VALUE x)
{
if (RB_INTEGER_TYPE_P(x)) {
- return FIXNUM_ZERO_P(x);
+ return FIXNUM_ZERO_P(x);
}
else if (RB_TYPE_P(x, T_RATIONAL)) {
- VALUE num = RRATIONAL(x)->num;
+ VALUE num = RRATIONAL(x)->num;
- return FIXNUM_ZERO_P(num);
+ return FIXNUM_ZERO_P(num);
}
return (int)rb_equal(x, ZERO);
}
@@ -183,13 +188,13 @@ inline static int
f_one_p(VALUE x)
{
if (RB_INTEGER_TYPE_P(x)) {
- return x == LONG2FIX(1);
+ return x == LONG2FIX(1);
}
else if (RB_TYPE_P(x, T_RATIONAL)) {
- VALUE num = RRATIONAL(x)->num;
- VALUE den = RRATIONAL(x)->den;
+ VALUE num = RRATIONAL(x)->num;
+ VALUE den = RRATIONAL(x)->den;
- return num == LONG2FIX(1) && den == LONG2FIX(1);
+ return num == LONG2FIX(1) && den == LONG2FIX(1);
}
return (int)rb_equal(x, ONE);
}
@@ -198,16 +203,16 @@ inline static int
f_minus_one_p(VALUE x)
{
if (RB_INTEGER_TYPE_P(x)) {
- return x == LONG2FIX(-1);
+ return x == LONG2FIX(-1);
}
- else if (RB_TYPE_P(x, T_BIGNUM)) {
- return Qfalse;
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ return Qfalse;
}
else if (RB_TYPE_P(x, T_RATIONAL)) {
- VALUE num = RRATIONAL(x)->num;
- VALUE den = RRATIONAL(x)->den;
+ VALUE num = RRATIONAL(x)->num;
+ VALUE den = RRATIONAL(x)->den;
- return num == LONG2FIX(-1) && den == LONG2FIX(1);
+ return num == LONG2FIX(-1) && den == LONG2FIX(1);
}
return (int)rb_equal(x, INT2FIX(-1));
}
@@ -248,7 +253,7 @@ k_rational_p(VALUE x)
#define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
#define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
-#ifdef USE_GMP
+#if USE_GMP
VALUE
rb_gcd_gmp(VALUE x, VALUE y)
{
@@ -290,35 +295,35 @@ i_gcd(long x, long y)
int shift;
if (x < 0)
- x = -x;
+ x = -x;
if (y < 0)
- y = -y;
+ y = -y;
if (x == 0)
- return y;
+ return y;
if (y == 0)
- return x;
+ return x;
u = (unsigned long)x;
v = (unsigned long)y;
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
- u >>= 1;
- v >>= 1;
+ u >>= 1;
+ v >>= 1;
}
while ((u & 1) == 0)
- u >>= 1;
+ u >>= 1;
do {
- while ((v & 1) == 0)
- v >>= 1;
-
- if (u > v) {
- t = v;
- v = u;
- u = t;
- }
- v = v - u;
+ while ((v & 1) == 0)
+ v >>= 1;
+
+ if (u > v) {
+ t = v;
+ v = u;
+ u = t;
+ }
+ v = v - u;
} while (v != 0);
return (long)(u << shift);
@@ -330,28 +335,28 @@ f_gcd_normal(VALUE x, VALUE y)
VALUE z;
if (FIXNUM_P(x) && FIXNUM_P(y))
- return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
+ return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
if (INT_NEGATIVE_P(x))
- x = rb_int_uminus(x);
+ x = rb_int_uminus(x);
if (INT_NEGATIVE_P(y))
- y = rb_int_uminus(y);
+ y = rb_int_uminus(y);
if (INT_ZERO_P(x))
- return y;
+ return y;
if (INT_ZERO_P(y))
- return x;
+ return x;
for (;;) {
- if (FIXNUM_P(x)) {
- if (FIXNUM_ZERO_P(x))
- return y;
- if (FIXNUM_P(y))
- return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
- }
- z = x;
- x = rb_int_modulo(y, x);
- y = z;
+ if (FIXNUM_P(x)) {
+ if (FIXNUM_ZERO_P(x))
+ return y;
+ if (FIXNUM_P(y))
+ return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
+ }
+ z = x;
+ x = rb_int_modulo(y, x);
+ y = z;
}
/* NOTREACHED */
}
@@ -365,8 +370,8 @@ rb_gcd_normal(VALUE x, VALUE y)
inline static VALUE
f_gcd(VALUE x, VALUE y)
{
-#ifdef USE_GMP
- if (RB_TYPE_P(x, T_BIGNUM) && RB_TYPE_P(y, T_BIGNUM)) {
+#if USE_GMP
+ if (RB_BIGNUM_TYPE_P(x) && RB_BIGNUM_TYPE_P(y)) {
size_t xn = BIGNUM_LEN(x);
size_t yn = BIGNUM_LEN(y);
if (GMP_GCD_DIGITS <= xn || GMP_GCD_DIGITS <= yn)
@@ -384,8 +389,8 @@ f_gcd(VALUE x, VALUE y)
{
VALUE r = f_gcd_orig(x, y);
if (f_nonzero_p(r)) {
- assert(f_zero_p(f_mod(x, r)));
- assert(f_zero_p(f_mod(y, r)));
+ assert(f_zero_p(f_mod(x, r)));
+ assert(f_zero_p(f_mod(y, r)));
}
return r;
}
@@ -395,7 +400,7 @@ inline static VALUE
f_lcm(VALUE x, VALUE y)
{
if (INT_ZERO_P(x) || INT_ZERO_P(y))
- return ZERO;
+ return ZERO;
return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
}
@@ -433,8 +438,8 @@ inline static void
nurat_int_check(VALUE num)
{
if (!RB_INTEGER_TYPE_P(num)) {
- if (!k_numeric_p(num) || !f_integer_p(num))
- rb_raise(rb_eTypeError, "not an integer");
+ if (!k_numeric_p(num) || !f_integer_p(num))
+ rb_raise(rb_eTypeError, "not an integer");
}
}
@@ -443,7 +448,7 @@ nurat_int_value(VALUE num)
{
nurat_int_check(num);
if (!k_integer_p(num))
- num = f_to_i(num);
+ num = f_to_i(num);
return num;
}
@@ -620,14 +625,14 @@ f_imul(long a, long b)
VALUE r;
if (a == 0 || b == 0)
- return ZERO;
+ return ZERO;
else if (a == 1)
- return LONG2NUM(b);
+ return LONG2NUM(b);
else if (b == 1)
- return LONG2NUM(a);
+ return LONG2NUM(a);
if (MUL_OVERFLOW_LONG_P(a, b))
- r = rb_big_mul(rb_int2big(a), rb_int2big(b));
+ r = rb_big_mul(rb_int2big(a), rb_int2big(b));
else
r = LONG2NUM(a * b);
return r;
@@ -651,46 +656,46 @@ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
VALUE num, den;
if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
- FIXNUM_P(bnum) && FIXNUM_P(bden)) {
- long an = FIX2LONG(anum);
- long ad = FIX2LONG(aden);
- long bn = FIX2LONG(bnum);
- long bd = FIX2LONG(bden);
- long ig = i_gcd(ad, bd);
-
- VALUE g = LONG2NUM(ig);
- VALUE a = f_imul(an, bd / ig);
- VALUE b = f_imul(bn, ad / ig);
- VALUE c;
-
- if (k == '+')
- c = rb_int_plus(a, b);
- else
- c = rb_int_minus(a, b);
-
- b = rb_int_idiv(aden, g);
- g = f_gcd(c, g);
- num = rb_int_idiv(c, g);
- a = rb_int_idiv(bden, g);
- den = rb_int_mul(a, b);
+ FIXNUM_P(bnum) && FIXNUM_P(bden)) {
+ long an = FIX2LONG(anum);
+ long ad = FIX2LONG(aden);
+ long bn = FIX2LONG(bnum);
+ long bd = FIX2LONG(bden);
+ long ig = i_gcd(ad, bd);
+
+ VALUE g = LONG2NUM(ig);
+ VALUE a = f_imul(an, bd / ig);
+ VALUE b = f_imul(bn, ad / ig);
+ VALUE c;
+
+ if (k == '+')
+ c = rb_int_plus(a, b);
+ else
+ c = rb_int_minus(a, b);
+
+ b = rb_int_idiv(aden, g);
+ g = f_gcd(c, g);
+ num = rb_int_idiv(c, g);
+ a = rb_int_idiv(bden, g);
+ den = rb_int_mul(a, b);
}
else if (RB_INTEGER_TYPE_P(anum) && RB_INTEGER_TYPE_P(aden) &&
RB_INTEGER_TYPE_P(bnum) && RB_INTEGER_TYPE_P(bden)) {
- VALUE g = f_gcd(aden, bden);
- VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
- VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
- VALUE c;
-
- if (k == '+')
- c = rb_int_plus(a, b);
- else
- c = rb_int_minus(a, b);
-
- b = rb_int_idiv(aden, g);
- g = f_gcd(c, g);
- num = rb_int_idiv(c, g);
- a = rb_int_idiv(bden, g);
- den = rb_int_mul(a, b);
+ VALUE g = f_gcd(aden, bden);
+ VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
+ VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
+ VALUE c;
+
+ if (k == '+')
+ c = rb_int_plus(a, b);
+ else
+ c = rb_int_minus(a, b);
+
+ b = rb_int_idiv(aden, g);
+ g = f_gcd(c, g);
+ num = rb_int_idiv(c, g);
+ a = rb_int_idiv(bden, g);
+ den = rb_int_mul(a, b);
}
else {
double a = NUM2DBL(anum) / NUM2DBL(aden);
@@ -718,28 +723,28 @@ VALUE
rb_rational_plus(VALUE self, VALUE other)
{
if (RB_INTEGER_TYPE_P(other)) {
- {
- get_dat1(self);
+ {
+ get_dat1(self);
- return f_rational_new_no_reduce2(CLASS_OF(self),
- rb_int_plus(dat->num, rb_int_mul(other, dat->den)),
- dat->den);
- }
+ return f_rational_new_no_reduce2(CLASS_OF(self),
+ rb_int_plus(dat->num, rb_int_mul(other, dat->den)),
+ dat->den);
+ }
}
else if (RB_FLOAT_TYPE_P(other)) {
- return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other));
+ return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other));
}
else if (RB_TYPE_P(other, T_RATIONAL)) {
- {
- get_dat2(self, other);
+ {
+ get_dat2(self, other);
- return f_addsub(self,
- adat->num, adat->den,
- bdat->num, bdat->den, '+');
- }
+ return f_addsub(self,
+ adat->num, adat->den,
+ bdat->num, bdat->den, '+');
+ }
}
else {
- return rb_num_coerce_bin(self, other, '+');
+ return rb_num_coerce_bin(self, other, '+');
}
}
@@ -759,28 +764,28 @@ VALUE
rb_rational_minus(VALUE self, VALUE other)
{
if (RB_INTEGER_TYPE_P(other)) {
- {
- get_dat1(self);
+ {
+ get_dat1(self);
- return f_rational_new_no_reduce2(CLASS_OF(self),
- rb_int_minus(dat->num, rb_int_mul(other, dat->den)),
- dat->den);
- }
+ return f_rational_new_no_reduce2(CLASS_OF(self),
+ rb_int_minus(dat->num, rb_int_mul(other, dat->den)),
+ dat->den);
+ }
}
else if (RB_FLOAT_TYPE_P(other)) {
- return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other));
+ return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other));
}
else if (RB_TYPE_P(other, T_RATIONAL)) {
- {
- get_dat2(self, other);
+ {
+ get_dat2(self, other);
- return f_addsub(self,
- adat->num, adat->den,
- bdat->num, bdat->den, '-');
- }
+ return f_addsub(self,
+ adat->num, adat->den,
+ bdat->num, bdat->den, '-');
+ }
}
else {
- return rb_num_coerce_bin(self, other, '-');
+ return rb_num_coerce_bin(self, other, '-');
}
}
@@ -806,35 +811,35 @@ f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
assert(RB_INTEGER_TYPE_P(bden));
if (k == '/') {
- VALUE t;
+ VALUE t;
- if (INT_NEGATIVE_P(bnum)) {
- anum = rb_int_uminus(anum);
- bnum = rb_int_uminus(bnum);
- }
- t = bnum;
- bnum = bden;
- bden = t;
+ if (INT_NEGATIVE_P(bnum)) {
+ anum = rb_int_uminus(anum);
+ bnum = rb_int_uminus(bnum);
+ }
+ t = bnum;
+ bnum = bden;
+ bden = t;
}
if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
- FIXNUM_P(bnum) && FIXNUM_P(bden)) {
- long an = FIX2LONG(anum);
- long ad = FIX2LONG(aden);
- long bn = FIX2LONG(bnum);
- long bd = FIX2LONG(bden);
- long g1 = i_gcd(an, bd);
- long g2 = i_gcd(ad, bn);
+ FIXNUM_P(bnum) && FIXNUM_P(bden)) {
+ long an = FIX2LONG(anum);
+ long ad = FIX2LONG(aden);
+ long bn = FIX2LONG(bnum);
+ long bd = FIX2LONG(bden);
+ long g1 = i_gcd(an, bd);
+ long g2 = i_gcd(ad, bn);
- num = f_imul(an / g1, bn / g2);
- den = f_imul(ad / g2, bd / g1);
+ num = f_imul(an / g1, bn / g2);
+ den = f_imul(ad / g2, bd / g1);
}
else {
- VALUE g1 = f_gcd(anum, bden);
- VALUE g2 = f_gcd(aden, bnum);
+ VALUE g1 = f_gcd(anum, bden);
+ VALUE g2 = f_gcd(aden, bnum);
- num = rb_int_mul(rb_int_idiv(anum, g1), rb_int_idiv(bnum, g2));
- den = rb_int_mul(rb_int_idiv(aden, g2), rb_int_idiv(bden, g1));
+ num = rb_int_mul(rb_int_idiv(anum, g1), rb_int_idiv(bnum, g2));
+ den = rb_int_mul(rb_int_idiv(aden, g2), rb_int_idiv(bden, g1));
}
return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
}
@@ -855,28 +860,28 @@ VALUE
rb_rational_mul(VALUE self, VALUE other)
{
if (RB_INTEGER_TYPE_P(other)) {
- {
- get_dat1(self);
+ {
+ get_dat1(self);
- return f_muldiv(self,
- dat->num, dat->den,
- other, ONE, '*');
- }
+ return f_muldiv(self,
+ dat->num, dat->den,
+ other, ONE, '*');
+ }
}
else if (RB_FLOAT_TYPE_P(other)) {
- return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other));
+ return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other));
}
else if (RB_TYPE_P(other, T_RATIONAL)) {
- {
- get_dat2(self, other);
+ {
+ get_dat2(self, other);
- return f_muldiv(self,
- adat->num, adat->den,
- bdat->num, bdat->den, '*');
- }
+ return f_muldiv(self,
+ adat->num, adat->den,
+ bdat->num, bdat->den, '*');
+ }
}
else {
- return rb_num_coerce_bin(self, other, '*');
+ return rb_num_coerce_bin(self, other, '*');
}
}
@@ -897,37 +902,37 @@ VALUE
rb_rational_div(VALUE self, VALUE other)
{
if (RB_INTEGER_TYPE_P(other)) {
- if (f_zero_p(other))
+ if (f_zero_p(other))
rb_num_zerodiv();
- {
- get_dat1(self);
+ {
+ get_dat1(self);
- return f_muldiv(self,
- dat->num, dat->den,
- other, ONE, '/');
- }
+ return f_muldiv(self,
+ dat->num, dat->den,
+ other, ONE, '/');
+ }
}
else if (RB_FLOAT_TYPE_P(other)) {
VALUE v = nurat_to_f(self);
return rb_flo_div_flo(v, other);
}
else if (RB_TYPE_P(other, T_RATIONAL)) {
- if (f_zero_p(other))
+ if (f_zero_p(other))
rb_num_zerodiv();
- {
- get_dat2(self, other);
+ {
+ get_dat2(self, other);
- if (f_one_p(self))
- return f_rational_new_no_reduce2(CLASS_OF(self),
- bdat->den, bdat->num);
+ if (f_one_p(self))
+ return f_rational_new_no_reduce2(CLASS_OF(self),
+ bdat->den, bdat->num);
- return f_muldiv(self,
- adat->num, adat->den,
- bdat->num, bdat->den, '/');
- }
+ return f_muldiv(self,
+ adat->num, adat->den,
+ bdat->num, bdat->den, '/');
+ }
}
else {
- return rb_num_coerce_bin(self, other, '/');
+ return rb_num_coerce_bin(self, other, '/');
}
}
@@ -948,12 +953,12 @@ nurat_fdiv(VALUE self, VALUE other)
if (f_zero_p(other))
return rb_rational_div(self, rb_float_new(0.0));
if (FIXNUM_P(other) && other == LONG2FIX(1))
- return nurat_to_f(self);
+ return nurat_to_f(self);
div = rb_rational_div(self, other);
if (RB_TYPE_P(div, T_RATIONAL))
- return nurat_to_f(div);
+ return nurat_to_f(div);
if (RB_FLOAT_TYPE_P(div))
- return div;
+ return div;
return rb_funcall(div, idTo_f, 0);
}
@@ -974,76 +979,76 @@ VALUE
rb_rational_pow(VALUE self, VALUE other)
{
if (k_numeric_p(other) && k_exact_zero_p(other))
- return f_rational_new_bang1(CLASS_OF(self), ONE);
+ return f_rational_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other)) {
- get_dat1(other);
+ get_dat1(other);
- if (f_one_p(dat->den))
- other = dat->num; /* c14n */
+ if (f_one_p(dat->den))
+ other = dat->num; /* c14n */
}
/* Deal with special cases of 0**n and 1**n */
if (k_numeric_p(other) && k_exact_p(other)) {
- get_dat1(self);
- if (f_one_p(dat->den)) {
- if (f_one_p(dat->num)) {
- 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(rb_int_odd_p(other) ? -1 : 1));
- }
- else if (INT_ZERO_P(dat->num)) {
- if (rb_num_negative_p(other)) {
+ get_dat1(self);
+ if (f_one_p(dat->den)) {
+ if (f_one_p(dat->num)) {
+ 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(rb_int_odd_p(other) ? -1 : 1));
+ }
+ else if (INT_ZERO_P(dat->num)) {
+ if (rb_num_negative_p(other)) {
rb_num_zerodiv();
- }
- else {
- return f_rational_new_bang1(CLASS_OF(self), ZERO);
- }
- }
- }
+ }
+ else {
+ return f_rational_new_bang1(CLASS_OF(self), ZERO);
+ }
+ }
+ }
}
/* General case */
if (FIXNUM_P(other)) {
- {
- VALUE num, den;
+ {
+ VALUE num, den;
- get_dat1(self);
+ get_dat1(self);
if (INT_POSITIVE_P(other)) {
- num = rb_int_pow(dat->num, other);
- den = rb_int_pow(dat->den, other);
+ num = rb_int_pow(dat->num, other);
+ den = rb_int_pow(dat->den, other);
}
else if (INT_NEGATIVE_P(other)) {
- num = rb_int_pow(dat->den, rb_int_uminus(other));
- den = rb_int_pow(dat->num, rb_int_uminus(other));
+ num = rb_int_pow(dat->den, rb_int_uminus(other));
+ den = rb_int_pow(dat->num, rb_int_uminus(other));
}
else {
- num = ONE;
- den = ONE;
- }
- if (RB_FLOAT_TYPE_P(num)) { /* infinity due to overflow */
- if (RB_FLOAT_TYPE_P(den))
- return DBL2NUM(nan(""));
- return num;
- }
- if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
- num = ZERO;
- den = ONE;
- }
- return f_rational_new2(CLASS_OF(self), num, den);
- }
- }
- else if (RB_TYPE_P(other, T_BIGNUM)) {
- rb_warn("in a**b, b may be too big");
- return rb_float_pow(nurat_to_f(self), other);
+ num = ONE;
+ den = ONE;
+ }
+ if (RB_FLOAT_TYPE_P(num)) { /* infinity due to overflow */
+ if (RB_FLOAT_TYPE_P(den))
+ return DBL2NUM(nan(""));
+ return num;
+ }
+ if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
+ num = ZERO;
+ den = ONE;
+ }
+ return f_rational_new2(CLASS_OF(self), num, den);
+ }
+ }
+ else if (RB_BIGNUM_TYPE_P(other)) {
+ rb_warn("in a**b, b may be too big");
+ return rb_float_pow(nurat_to_f(self), other);
}
else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
- return rb_float_pow(nurat_to_f(self), other);
+ return rb_float_pow(nurat_to_f(self), other);
}
else {
- return rb_num_coerce_bin(self, other, idPow);
+ return rb_num_coerce_bin(self, other, idPow);
}
}
#define nurat_expt rb_rational_pow
@@ -1071,38 +1076,38 @@ rb_rational_cmp(VALUE self, VALUE other)
switch (TYPE(other)) {
case T_FIXNUM:
case T_BIGNUM:
- {
- get_dat1(self);
+ {
+ 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);
+ if (dat->den == LONG2FIX(1))
+ return rb_int_cmp(dat->num, other); /* c14n */
+ other = f_rational_new_bang1(CLASS_OF(self), other);
/* FALLTHROUGH */
- }
+ }
case T_RATIONAL:
- {
- VALUE num1, num2;
-
- get_dat2(self, other);
-
- if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
- FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
- num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
- num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
- }
- else {
- num1 = rb_int_mul(adat->num, bdat->den);
- num2 = rb_int_mul(bdat->num, adat->den);
- }
- return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
- }
+ {
+ VALUE num1, num2;
+
+ get_dat2(self, other);
+
+ if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
+ FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
+ num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
+ num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
+ }
+ else {
+ num1 = rb_int_mul(adat->num, bdat->den);
+ num2 = rb_int_mul(bdat->num, adat->den);
+ }
+ return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
+ }
case T_FLOAT:
return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
default:
- return rb_num_coerce_cmp(self, other, idCmp);
+ return rb_num_coerce_cmp(self, other, idCmp);
}
}
@@ -1125,37 +1130,37 @@ nurat_eqeq_p(VALUE self, VALUE other)
get_dat1(self);
if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
- if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
- return Qtrue;
-
- if (!FIXNUM_P(dat->den))
- return Qfalse;
- if (FIX2LONG(dat->den) != 1)
- return Qfalse;
- return rb_int_equal(dat->num, other);
- }
+ if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
+ return Qtrue;
+
+ if (!FIXNUM_P(dat->den))
+ return Qfalse;
+ if (FIX2LONG(dat->den) != 1)
+ return Qfalse;
+ return rb_int_equal(dat->num, other);
+ }
else {
const double d = nurat_to_double(self);
- return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
+ return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
}
}
else if (RB_FLOAT_TYPE_P(other)) {
- const double d = nurat_to_double(self);
- return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other))));
+ const double d = nurat_to_double(self);
+ return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other))));
}
else if (RB_TYPE_P(other, T_RATIONAL)) {
- {
- get_dat2(self, other);
+ {
+ get_dat2(self, other);
- if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
- return Qtrue;
+ if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
+ return Qtrue;
- return f_boolcast(rb_int_equal(adat->num, bdat->num) &&
- rb_int_equal(adat->den, bdat->den));
- }
+ return RBOOL(rb_int_equal(adat->num, bdat->num) &&
+ rb_int_equal(adat->den, bdat->den));
+ }
}
else {
- return rb_equal(other, self);
+ return rb_equal(other, self);
}
}
@@ -1164,17 +1169,17 @@ static VALUE
nurat_coerce(VALUE self, VALUE other)
{
if (RB_INTEGER_TYPE_P(other)) {
- return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
+ return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
}
else if (RB_FLOAT_TYPE_P(other)) {
return rb_assoc_new(other, nurat_to_f(self));
}
else if (RB_TYPE_P(other, T_RATIONAL)) {
- return rb_assoc_new(other, self);
+ 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(other, rb_Complex(self, INT2FIX(0)));
+ 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);
@@ -1187,7 +1192,7 @@ nurat_coerce(VALUE self, VALUE other)
}
rb_raise(rb_eTypeError, "%s can't be coerced into %s",
- rb_obj_classname(other), rb_obj_classname(self));
+ rb_obj_classname(other), rb_obj_classname(self));
return Qnil;
}
@@ -1201,7 +1206,7 @@ static VALUE
nurat_positive_p(VALUE self)
{
get_dat1(self);
- return f_boolcast(INT_POSITIVE_P(dat->num));
+ return RBOOL(INT_POSITIVE_P(dat->num));
}
/*
@@ -1214,7 +1219,7 @@ static VALUE
nurat_negative_p(VALUE self)
{
get_dat1(self);
- return f_boolcast(INT_NEGATIVE_P(dat->num));
+ return RBOOL(INT_NEGATIVE_P(dat->num));
}
/*
@@ -1274,7 +1279,7 @@ nurat_truncate(VALUE self)
{
get_dat1(self);
if (INT_NEGATIVE_P(dat->num))
- return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
+ return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
return rb_int_idiv(dat->num, dat->den);
}
@@ -1290,14 +1295,14 @@ nurat_round_half_up(VALUE self)
neg = INT_NEGATIVE_P(num);
if (neg)
- num = rb_int_uminus(num);
+ num = rb_int_uminus(num);
num = rb_int_plus(rb_int_mul(num, TWO), den);
den = rb_int_mul(den, TWO);
num = rb_int_idiv(num, den);
if (neg)
- num = rb_int_uminus(num);
+ num = rb_int_uminus(num);
return num;
}
@@ -1314,7 +1319,7 @@ nurat_round_half_down(VALUE self)
neg = INT_NEGATIVE_P(num);
if (neg)
- num = rb_int_uminus(num);
+ num = rb_int_uminus(num);
num = rb_int_plus(rb_int_mul(num, TWO), den);
num = rb_int_minus(num, ONE);
@@ -1322,7 +1327,7 @@ nurat_round_half_down(VALUE self)
num = rb_int_idiv(num, den);
if (neg)
- num = rb_int_uminus(num);
+ num = rb_int_uminus(num);
return num;
}
@@ -1339,17 +1344,17 @@ nurat_round_half_even(VALUE self)
neg = INT_NEGATIVE_P(num);
if (neg)
- num = rb_int_uminus(num);
+ num = rb_int_uminus(num);
num = rb_int_plus(rb_int_mul(num, TWO), den);
den = rb_int_mul(den, TWO);
qr = rb_int_divmod(num, den);
num = RARRAY_AREF(qr, 0);
if (INT_ZERO_P(RARRAY_AREF(qr, 1)))
- num = rb_int_and(num, LONG2FIX(((int)~1)));
+ num = rb_int_and(num, LONG2FIX(((int)~1)));
if (neg)
- num = rb_int_uminus(num);
+ num = rb_int_uminus(num);
return num;
}
@@ -1360,24 +1365,24 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
VALUE n, b, s;
if (rb_check_arity(argc, 0, 1) == 0)
- return (*func)(self);
+ return (*func)(self);
n = argv[0];
if (!k_integer_p(n))
- rb_raise(rb_eTypeError, "not an integer");
+ rb_raise(rb_eTypeError, "not an integer");
b = f_expt10(n);
s = rb_rational_mul(self, b);
if (k_float_p(s)) {
- if (INT_NEGATIVE_P(n))
- return ZERO;
- return self;
+ if (INT_NEGATIVE_P(n))
+ return ZERO;
+ return self;
}
if (!k_rational_p(s)) {
- s = f_rational_new_bang1(CLASS_OF(self), s);
+ s = f_rational_new_bang1(CLASS_OF(self), s);
}
s = (*func)(s);
@@ -1385,7 +1390,7 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b);
if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
- s = nurat_truncate(s);
+ s = nurat_truncate(s);
return s;
}
@@ -1535,7 +1540,7 @@ nurat_round_n(int argc, VALUE *argv, VALUE self)
VALUE opt;
enum ruby_num_rounding_mode mode = (
argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
- rb_num_get_rounding_option(opt));
+ rb_num_get_rounding_option(opt));
VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
return f_round_common(argc, argv, self, round_func);
}
@@ -1684,19 +1689,19 @@ nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
q1 = ZERO;
while (1) {
- c = f_ceil(a);
- if (f_lt_p(c, b))
- break;
- k = f_sub(c, ONE);
- p2 = f_add(f_mul(k, p1), p0);
- q2 = f_add(f_mul(k, q1), q0);
- t = f_reciprocal(f_sub(b, k));
- b = f_reciprocal(f_sub(a, k));
- a = t;
- p0 = p1;
- q0 = q1;
- p1 = p2;
- q1 = q2;
+ c = f_ceil(a);
+ if (f_lt_p(c, b))
+ break;
+ k = f_sub(c, ONE);
+ p2 = f_add(f_mul(k, p1), p0);
+ q2 = f_add(f_mul(k, q1), q0);
+ t = f_reciprocal(f_sub(b, k));
+ b = f_reciprocal(f_sub(a, k));
+ a = t;
+ p0 = p1;
+ q0 = q1;
+ p1 = p2;
+ q1 = q2;
}
*p = f_add(f_mul(c, p1), p0);
*q = f_add(f_mul(c, q1), q0);
@@ -1724,7 +1729,7 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self)
get_dat1(self);
if (rb_check_arity(argc, 0, 1) == 0)
- return self;
+ return self;
e = f_abs(argv[0]);
@@ -1736,7 +1741,7 @@ nurat_rationalize(int argc, VALUE *argv, VALUE self)
b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);
if (f_eqeq_p(a, b))
- return self;
+ return self;
nurat_rationalize_internal(a, b, &p, &q);
if (rat != self) {
@@ -1869,7 +1874,7 @@ nurat_marshal_load(VALUE self, VALUE a)
Check_Type(a, T_ARRAY);
if (RARRAY_LEN(a) != 2)
- rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
+ rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
num = RARRAY_AREF(a, 0);
den = RARRAY_AREF(a, 1);
@@ -1882,8 +1887,6 @@ nurat_marshal_load(VALUE self, VALUE a)
return self;
}
-/* --- */
-
VALUE
rb_rational_reciprocal(VALUE x)
{
@@ -2058,30 +2061,6 @@ rb_rational_canonicalize(VALUE x)
/*
* call-seq:
- * int.numerator -> self
- *
- * Returns self.
- */
-static VALUE
-integer_numerator(VALUE self)
-{
- return self;
-}
-
-/*
- * call-seq:
- * int.denominator -> 1
- *
- * Returns 1.
- */
-static VALUE
-integer_denominator(VALUE self)
-{
- return INT2FIX(1);
-}
-
-/*
- * call-seq:
* flo.numerator -> integer
*
* Returns the numerator. The result is machine dependent.
@@ -2097,8 +2076,8 @@ rb_float_numerator(VALUE self)
{
double d = RFLOAT_VALUE(self);
VALUE r;
- if (isinf(d) || isnan(d))
- return self;
+ if (!isfinite(d))
+ return self;
r = float_to_r(self);
return nurat_numerator(r);
}
@@ -2117,8 +2096,8 @@ rb_float_denominator(VALUE self)
{
double d = RFLOAT_VALUE(self);
VALUE r;
- if (isinf(d) || isnan(d))
- return INT2FIX(1);
+ if (!isfinite(d))
+ return INT2FIX(1);
r = float_to_r(self);
return nurat_denominator(r);
}
@@ -2226,7 +2205,7 @@ float_to_r(VALUE self)
#else
f = rb_int_mul(f, rb_int_pow(INT2FIX(FLT_RADIX), n));
if (RB_TYPE_P(f, T_RATIONAL))
- return f;
+ return f;
return rb_rational_new1(f);
#endif
}
@@ -2324,8 +2303,8 @@ read_sign(const char **s, const char *const e)
int sign = '?';
if (*s < e && issign(**s)) {
- sign = **s;
- (*s)++;
+ sign = **s;
+ (*s)++;
}
return sign;
}
@@ -2340,11 +2319,11 @@ static VALUE
negate_num(VALUE num)
{
if (FIXNUM_P(num)) {
- return rb_int_uminus(num);
+ return rb_int_uminus(num);
}
else {
- BIGNUM_NEGATE(num);
- return rb_big_norm(num);
+ BIGNUM_NEGATE(num);
+ return rb_big_norm(num);
}
}
@@ -2358,51 +2337,51 @@ read_num(const char **s, const char *const end, VALUE *num, VALUE *nexp)
*nexp = ZERO;
*num = ZERO;
if (*s < end && **s != '.') {
- n = rb_int_parse_cstr(*s, end-*s, &e, NULL,
- 10, RB_INT_PARSE_UNDERSCORE);
- if (NIL_P(n))
- return 0;
- *s = e;
- *num = n;
- ok = 1;
+ n = rb_int_parse_cstr(*s, end-*s, &e, NULL,
+ 10, RB_INT_PARSE_UNDERSCORE);
+ if (NIL_P(n))
+ return 0;
+ *s = e;
+ *num = n;
+ ok = 1;
}
if (*s < end && **s == '.') {
- size_t count = 0;
-
- (*s)++;
- fp = rb_int_parse_cstr(*s, end-*s, &e, &count,
- 10, RB_INT_PARSE_UNDERSCORE);
- if (NIL_P(fp))
- return 1;
- *s = e;
- {
+ size_t count = 0;
+
+ (*s)++;
+ fp = rb_int_parse_cstr(*s, end-*s, &e, &count,
+ 10, RB_INT_PARSE_UNDERSCORE);
+ if (NIL_P(fp))
+ return 1;
+ *s = e;
+ {
VALUE l = f_expt10(*nexp = SIZET2NUM(count));
- n = n == ZERO ? fp : rb_int_plus(rb_int_mul(*num, l), fp);
- *num = n;
- fn = SIZET2NUM(count);
- }
- ok = 1;
+ n = n == ZERO ? fp : rb_int_plus(rb_int_mul(*num, l), fp);
+ *num = n;
+ fn = SIZET2NUM(count);
+ }
+ ok = 1;
}
if (ok && *s + 1 < end && islettere(**s)) {
- (*s)++;
- expsign = read_sign(s, end);
- exp = rb_int_parse_cstr(*s, end-*s, &e, NULL,
- 10, RB_INT_PARSE_UNDERSCORE);
- if (NIL_P(exp))
- return 1;
- *s = e;
- if (exp != ZERO) {
- if (expsign == '-') {
- if (fn != ZERO) exp = rb_int_plus(exp, fn);
- }
- else {
- if (fn != ZERO) exp = rb_int_minus(exp, fn);
+ (*s)++;
+ expsign = read_sign(s, end);
+ exp = rb_int_parse_cstr(*s, end-*s, &e, NULL,
+ 10, RB_INT_PARSE_UNDERSCORE);
+ if (NIL_P(exp))
+ return 1;
+ *s = e;
+ if (exp != ZERO) {
+ if (expsign == '-') {
+ if (fn != ZERO) exp = rb_int_plus(exp, fn);
+ }
+ else {
+ if (fn != ZERO) exp = rb_int_minus(exp, fn);
exp = negate_num(exp);
- }
+ }
*nexp = exp;
- }
+ }
}
return ok;
@@ -2412,7 +2391,7 @@ inline static const char *
skip_ws(const char *s, const char *e)
{
while (s < e && isspace((unsigned char)*s))
- ++s;
+ ++s;
return s;
}
@@ -2426,30 +2405,30 @@ parse_rat(const char *s, const char *const e, int strict, int raise)
sign = read_sign(&s, e);
if (!read_num(&s, e, &num, &nexp)) {
- if (strict) return Qnil;
- return nurat_s_alloc(rb_cRational);
+ if (strict) return Qnil;
+ return nurat_s_alloc(rb_cRational);
}
den = ONE;
if (s < e && *s == '/') {
- s++;
+ s++;
if (!read_num(&s, e, &den, &dexp)) {
- if (strict) return Qnil;
+ if (strict) return Qnil;
den = ONE;
- }
- else if (den == ZERO) {
+ }
+ else if (den == ZERO) {
if (!raise) return Qnil;
- rb_num_zerodiv();
- }
- else if (strict && skip_ws(s, e) != e) {
- return Qnil;
- }
- else {
+ rb_num_zerodiv();
+ }
+ else if (strict && skip_ws(s, e) != e) {
+ return Qnil;
+ }
+ else {
nexp = rb_int_minus(nexp, dexp);
- nurat_reduce(&num, &den);
- }
+ nurat_reduce(&num, &den);
+ }
}
else if (strict && skip_ws(s, e) != e) {
- return Qnil;
+ return Qnil;
}
if (nexp != ZERO) {
@@ -2480,7 +2459,7 @@ parse_rat(const char *s, const char *const e, int strict, int raise)
}
if (sign == '-') {
- num = negate_num(num);
+ num = negate_num(num);
}
return rb_rational_raw(num, den);
@@ -2545,7 +2524,7 @@ string_to_r(VALUE self)
num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
- rb_raise(rb_eFloatDomainError, "Infinity");
+ rb_raise(rb_eFloatDomainError, "Infinity");
return num;
}
@@ -2557,7 +2536,7 @@ rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
num = parse_rat(s, s + strlen(s), strict, TRUE);
if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
- rb_raise(rb_eFloatDomainError, "Infinity");
+ rb_raise(rb_eFloatDomainError, "Infinity");
return num;
}
@@ -2573,7 +2552,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
VALUE a1 = numv, a2 = denv;
int state;
- assert(a1 != Qundef);
+ assert(!UNDEF_P(a1));
if (NIL_P(a1) || NIL_P(a2)) {
if (!raise) return Qnil;
@@ -2624,7 +2603,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
a2 = string_to_r_strict(a2, raise);
if (!raise && NIL_P(a2)) return Qnil;
}
- else if (a2 != Qundef && !rb_respond_to(a2, idTo_r)) {
+ else if (!UNDEF_P(a2) && !rb_respond_to(a2, idTo_r)) {
VALUE tmp = rb_protect(rb_check_to_int, a2, NULL);
rb_set_errinfo(Qnil);
if (!NIL_P(tmp)) {
@@ -2633,11 +2612,11 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
}
if (RB_TYPE_P(a1, T_RATIONAL)) {
- if (a2 == Qundef || (k_exact_one_p(a2)))
+ if (UNDEF_P(a2) || (k_exact_one_p(a2)))
return a1;
}
- if (a2 == Qundef) {
+ if (UNDEF_P(a2)) {
if (!RB_INTEGER_TYPE_P(a1)) {
if (!raise) {
VALUE result = rb_protect(to_rational, a1, NULL);
@@ -2687,7 +2666,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
a1 = nurat_int_value(a1);
- if (a2 == Qundef) {
+ if (UNDEF_P(a2)) {
a2 = ONE;
}
else if (!k_integer_p(a2) && !raise) {
@@ -2718,13 +2697,19 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
* a/b (b>0), where a is the numerator and b is the denominator.
* Integer a equals rational a/1 mathematically.
*
- * In Ruby, you can create rational objects with the Kernel#Rational,
- * to_r, or rationalize methods or by suffixing +r+ to a literal.
- * The return values will be irreducible fractions.
+ * You can create a \Rational object explicitly with:
+ *
+ * - A {rational literal}[rdoc-ref:syntax/literals.rdoc@Rational+Literals].
+ *
+ * You can convert certain objects to Rationals with:
+ *
+ * - \Method #Rational.
+ *
+ * Examples
*
* Rational(1) #=> (1/1)
* Rational(2, 3) #=> (2/3)
- * Rational(4, -6) #=> (-2/3)
+ * Rational(4, -6) #=> (-2/3) # Reduced.
* 3.to_r #=> (3/1)
* 2/3r #=> (2/3)
*
@@ -2815,8 +2800,6 @@ Init_Rational(void)
rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
- /* --- */
-
rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
@@ -2825,9 +2808,6 @@ Init_Rational(void)
rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
rb_define_method(rb_cNumeric, "quo", rb_numeric_quo, 1);
- rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
- rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
-
rb_define_method(rb_cFloat, "numerator", rb_float_numerator, 0);
rb_define_method(rb_cFloat, "denominator", rb_float_denominator, 0);
diff --git a/re.c b/re.c
index 3bd9237683..f357d38c63 100644
--- a/re.c
+++ b/re.c
@@ -14,18 +14,22 @@
#include <ctype.h>
#include "encindex.h"
+#include "hrtime.h"
#include "internal.h"
+#include "internal/encoding.h"
#include "internal/hash.h"
#include "internal/imemo.h"
#include "internal/re.h"
#include "internal/string.h"
+#include "internal/object.h"
+#include "internal/ractor.h"
#include "internal/variable.h"
#include "regint.h"
#include "ruby/encoding.h"
#include "ruby/re.h"
#include "ruby/util.h"
-VALUE rb_eRegexpError;
+VALUE rb_eRegexpError, rb_eRegexpTimeoutError;
typedef char onig_errmsg_buffer[ONIG_MAX_ERROR_MESSAGE_LEN];
#define errcpy(err, msg) strlcpy((err), (msg), ONIG_MAX_ERROR_MESSAGE_LEN)
@@ -91,8 +95,8 @@ rb_memcicmp(const void *x, const void *y, long len)
int tmp;
while (len--) {
- if ((tmp = casetable[(unsigned)*p1++] - casetable[(unsigned)*p2++]))
- return tmp;
+ if ((tmp = casetable[(unsigned)*p1++] - casetable[(unsigned)*p2++]))
+ return tmp;
}
return 0;
}
@@ -104,9 +108,9 @@ rb_memsearch_ss(const unsigned char *xs, long m, const unsigned char *ys, long n
const unsigned char *y;
if ((y = memmem(ys, n, xs, m)) != NULL)
- return y - ys;
+ return y - ys;
else
- return -1;
+ return -1;
}
#else
static inline long
@@ -118,26 +122,26 @@ rb_memsearch_ss(const unsigned char *xs, long m, const unsigned char *ys, long n
VALUE hx, hy, mask = VALUE_MAX >> ((SIZEOF_VALUE - m) * CHAR_BIT);
if (m > SIZEOF_VALUE)
- rb_bug("!!too long pattern string!!");
+ rb_bug("!!too long pattern string!!");
if (!(y = memchr(y, *x, n - m + 1)))
- return -1;
+ return -1;
/* Prepare hash value */
for (hx = *x++, hy = *y++; x < xe; ++x, ++y) {
- hx <<= CHAR_BIT;
- hy <<= CHAR_BIT;
- hx |= *x;
- hy |= *y;
+ hx <<= CHAR_BIT;
+ hy <<= CHAR_BIT;
+ hx |= *x;
+ hy |= *y;
}
/* Searching */
while (hx != hy) {
- if (y == ye)
- return -1;
- hy <<= CHAR_BIT;
- hy |= *y;
- hy &= mask;
- y++;
+ if (y == ye)
+ return -1;
+ hy <<= CHAR_BIT;
+ hy |= *y;
+ hy &= mask;
+ y++;
}
return y - ys - m;
}
@@ -152,13 +156,13 @@ rb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long n
/* Preprocessing */
for (i = 0; i < 256; ++i)
- qstable[i] = m + 1;
+ qstable[i] = m + 1;
for (; x < xe; ++x)
- qstable[*x] = xe - x;
+ qstable[*x] = xe - x;
/* Searching */
for (; y + m <= ys + n; y += *(qstable + y[m])) {
- if (*xs == *y && memcmp(xs, y, m) == 0)
- return y - ys;
+ if (*xs == *y && memcmp(xs, y, m) == 0)
+ return y - ys;
}
return -1;
}
@@ -169,28 +173,28 @@ rb_memsearch_qs_utf8_hash(const unsigned char *x)
register const unsigned int mix = 8353;
register unsigned int h = *x;
if (h < 0xC0) {
- return h + 256;
+ return h + 256;
}
else if (h < 0xE0) {
- h *= mix;
- h += x[1];
+ h *= mix;
+ h += x[1];
}
else if (h < 0xF0) {
- h *= mix;
- h += x[1];
- h *= mix;
- h += x[2];
+ h *= mix;
+ h += x[1];
+ h *= mix;
+ h += x[2];
}
else if (h < 0xF5) {
- h *= mix;
- h += x[1];
- h *= mix;
- h += x[2];
- h *= mix;
- h += x[3];
+ h *= mix;
+ h += x[1];
+ h *= mix;
+ h += x[2];
+ h *= mix;
+ h += x[3];
}
else {
- return h + 256;
+ return h + 256;
}
return (unsigned char)h;
}
@@ -204,43 +208,41 @@ rb_memsearch_qs_utf8(const unsigned char *xs, long m, const unsigned char *ys, l
/* Preprocessing */
for (i = 0; i < 512; ++i) {
- qstable[i] = m + 1;
+ qstable[i] = m + 1;
}
for (; x < xe; ++x) {
- qstable[rb_memsearch_qs_utf8_hash(x)] = xe - x;
+ qstable[rb_memsearch_qs_utf8_hash(x)] = xe - x;
}
/* Searching */
for (; y + m <= ys + n; y += qstable[rb_memsearch_qs_utf8_hash(y+m)]) {
- if (*xs == *y && memcmp(xs, y, m) == 0)
- return y - ys;
+ if (*xs == *y && memcmp(xs, y, m) == 0)
+ return y - ys;
}
return -1;
}
static inline long
-rb_memsearch_wchar(const unsigned char *xs, long m, const unsigned char *ys, long n)
+rb_memsearch_with_char_size(const unsigned char *xs, long m, const unsigned char *ys, long n, int char_size)
{
const unsigned char *x = xs, x0 = *xs, *y = ys;
- enum {char_size = 2};
for (n -= m; n >= 0; n -= char_size, y += char_size) {
- if (x0 == *y && memcmp(x+1, y+1, m-1) == 0)
- return y - ys;
+ if (x0 == *y && memcmp(x+1, y+1, m-1) == 0)
+ return y - ys;
}
return -1;
}
static inline long
-rb_memsearch_qchar(const unsigned char *xs, long m, const unsigned char *ys, long n)
+rb_memsearch_wchar(const unsigned char *xs, long m, const unsigned char *ys, long n)
{
- const unsigned char *x = xs, x0 = *xs, *y = ys;
- enum {char_size = 4};
+ return rb_memsearch_with_char_size(xs, m, ys, n, 2);
+}
- for (n -= m; n >= 0; n -= char_size, y += char_size) {
- if (x0 == *y && memcmp(x+1, y+1, m-1) == 0)
- return y - ys;
- }
- return -1;
+static inline long
+rb_memsearch_qchar(const unsigned char *xs, long m, const unsigned char *ys, long n)
+{
+ return rb_memsearch_with_char_size(xs, m, ys, n, 4);
}
long
@@ -250,32 +252,32 @@ rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)
if (m > n) return -1;
else if (m == n) {
- return memcmp(x0, y0, m) == 0 ? 0 : -1;
+ return memcmp(x0, y0, m) == 0 ? 0 : -1;
}
else if (m < 1) {
- return 0;
+ return 0;
}
else if (m == 1) {
- const unsigned char *ys = memchr(y, *x, n);
+ const unsigned char *ys = memchr(y, *x, n);
- if (ys)
- return ys - y;
- else
- return -1;
+ if (ys)
+ return ys - y;
+ else
+ return -1;
}
else if (LIKELY(rb_enc_mbminlen(enc) == 1)) {
- if (m <= SIZEOF_VALUE) {
- return rb_memsearch_ss(x0, m, y0, n);
- }
- else if (enc == rb_utf8_encoding()){
- return rb_memsearch_qs_utf8(x0, m, y0, n);
- }
+ if (m <= SIZEOF_VALUE) {
+ return rb_memsearch_ss(x0, m, y0, n);
+ }
+ else if (enc == rb_utf8_encoding()){
+ return rb_memsearch_qs_utf8(x0, m, y0, n);
+ }
}
else if (LIKELY(rb_enc_mbminlen(enc) == 2)) {
- return rb_memsearch_wchar(x0, m, y0, n);
+ return rb_memsearch_wchar(x0, m, y0, n);
}
else if (LIKELY(rb_enc_mbminlen(enc) == 4)) {
- return rb_memsearch_qchar(x0, m, y0, n);
+ return rb_memsearch_qchar(x0, m, y0, n);
}
return rb_memsearch_qs(x0, m, y0, n);
}
@@ -297,17 +299,17 @@ char_to_option(int c)
switch (c) {
case 'i':
- val = ONIG_OPTION_IGNORECASE;
- break;
+ val = ONIG_OPTION_IGNORECASE;
+ break;
case 'x':
- val = ONIG_OPTION_EXTEND;
- break;
+ val = ONIG_OPTION_EXTEND;
+ break;
case 'm':
- val = ONIG_OPTION_MULTILINE;
- break;
+ val = ONIG_OPTION_MULTILINE;
+ break;
default:
- val = 0;
- break;
+ val = 0;
+ break;
}
return val;
}
@@ -335,17 +337,17 @@ rb_char_to_option_kcode(int c, int *option, int *kcode)
*kcode = rb_ascii8bit_encindex();
return (*option = ARG_ENCODING_NONE);
case 'e':
- *kcode = ENCINDEX_EUC_JP;
- break;
+ *kcode = ENCINDEX_EUC_JP;
+ break;
case 's':
- *kcode = ENCINDEX_Windows_31J;
- break;
+ *kcode = ENCINDEX_Windows_31J;
+ break;
case 'u':
- *kcode = rb_utf8_encindex();
- break;
+ *kcode = rb_utf8_encindex();
+ break;
default:
- *kcode = -1;
- return (*option = char_to_option(c));
+ *kcode = -1;
+ return (*option = char_to_option(c));
}
*option = ARG_ENCODING_FIXED;
return 1;
@@ -355,13 +357,13 @@ static void
rb_reg_check(VALUE re)
{
if (!RREGEXP_PTR(re) || !RREGEXP_SRC(re) || !RREGEXP_SRC_PTR(re)) {
- rb_raise(rb_eTypeError, "uninitialized Regexp");
+ rb_raise(rb_eTypeError, "uninitialized Regexp");
}
}
static void
rb_reg_expr_str(VALUE str, const char *s, long len,
- rb_encoding *enc, rb_encoding *resenc, int term)
+ rb_encoding *enc, rb_encoding *resenc, int term)
{
const char *p, *pend;
int cr = ENC_CODERANGE_UNKNOWN;
@@ -371,80 +373,80 @@ rb_reg_expr_str(VALUE str, const char *s, long len,
p = s; pend = p + len;
rb_str_coderange_scan_restartable(p, pend, enc, &cr);
if (rb_enc_asciicompat(enc) && ENC_CODERANGE_CLEAN_P(cr)) {
- while (p < pend) {
- c = rb_enc_ascget(p, pend, &clen, enc);
- if (c == -1) {
- if (enc == resenc) {
- p += mbclen(p, pend, enc);
- }
- else {
- need_escape = 1;
- break;
- }
- }
- else if (c != term && rb_enc_isprint(c, enc)) {
- p += clen;
- }
- else {
- need_escape = 1;
- break;
- }
- }
+ while (p < pend) {
+ c = rb_enc_ascget(p, pend, &clen, enc);
+ if (c == -1) {
+ if (enc == resenc) {
+ p += mbclen(p, pend, enc);
+ }
+ else {
+ need_escape = 1;
+ break;
+ }
+ }
+ else if (c != term && rb_enc_isprint(c, enc)) {
+ p += clen;
+ }
+ else {
+ need_escape = 1;
+ break;
+ }
+ }
}
else {
- need_escape = 1;
+ need_escape = 1;
}
if (!need_escape) {
- rb_str_buf_cat(str, s, len);
+ rb_str_buf_cat(str, s, len);
}
else {
- int unicode_p = rb_enc_unicode_p(enc);
- p = s;
- while (p<pend) {
+ int unicode_p = rb_enc_unicode_p(enc);
+ p = s;
+ while (p<pend) {
c = rb_enc_ascget(p, pend, &clen, enc);
- if (c == '\\' && p+clen < pend) {
- int n = clen + mbclen(p+clen, pend, enc);
- rb_str_buf_cat(str, p, n);
- p += n;
- continue;
- }
- else if (c == -1) {
- clen = rb_enc_precise_mbclen(p, pend, enc);
- if (!MBCLEN_CHARFOUND_P(clen)) {
- c = (unsigned char)*p;
- clen = 1;
- goto hex;
- }
- if (resenc) {
- unsigned int c = rb_enc_mbc_to_codepoint(p, pend, enc);
- rb_str_buf_cat_escaped_char(str, c, unicode_p);
- }
- else {
- clen = MBCLEN_CHARFOUND_LEN(clen);
- rb_str_buf_cat(str, p, clen);
- }
- }
- else if (c == term) {
- char c = '\\';
- rb_str_buf_cat(str, &c, 1);
- rb_str_buf_cat(str, p, clen);
- }
- else if (rb_enc_isprint(c, enc)) {
- rb_str_buf_cat(str, p, clen);
- }
- else if (!rb_enc_isspace(c, enc)) {
- char b[8];
-
- hex:
- snprintf(b, sizeof(b), "\\x%02X", c);
- rb_str_buf_cat(str, b, 4);
- }
- else {
- rb_str_buf_cat(str, p, clen);
- }
- p += clen;
- }
+ if (c == '\\' && p+clen < pend) {
+ int n = clen + mbclen(p+clen, pend, enc);
+ rb_str_buf_cat(str, p, n);
+ p += n;
+ continue;
+ }
+ else if (c == -1) {
+ clen = rb_enc_precise_mbclen(p, pend, enc);
+ if (!MBCLEN_CHARFOUND_P(clen)) {
+ c = (unsigned char)*p;
+ clen = 1;
+ goto hex;
+ }
+ if (resenc) {
+ unsigned int c = rb_enc_mbc_to_codepoint(p, pend, enc);
+ rb_str_buf_cat_escaped_char(str, c, unicode_p);
+ }
+ else {
+ clen = MBCLEN_CHARFOUND_LEN(clen);
+ rb_str_buf_cat(str, p, clen);
+ }
+ }
+ else if (c == term) {
+ char c = '\\';
+ rb_str_buf_cat(str, &c, 1);
+ rb_str_buf_cat(str, p, clen);
+ }
+ else if (rb_enc_isprint(c, enc)) {
+ rb_str_buf_cat(str, p, clen);
+ }
+ else if (!rb_enc_isspace(c, enc)) {
+ char b[8];
+
+ hex:
+ snprintf(b, sizeof(b), "\\x%02X", c);
+ rb_str_buf_cat(str, b, 4);
+ }
+ else {
+ rb_str_buf_cat(str, p, clen);
+ }
+ p += clen;
+ }
}
}
@@ -457,20 +459,20 @@ rb_reg_desc(const char *s, long len, VALUE re)
if (resenc == NULL) resenc = rb_default_external_encoding();
if (re && rb_enc_asciicompat(enc)) {
- rb_enc_copy(str, re);
+ rb_enc_copy(str, re);
}
else {
- rb_enc_associate(str, rb_usascii_encoding());
+ rb_enc_associate(str, rb_usascii_encoding());
}
rb_reg_expr_str(str, s, len, enc, resenc, '/');
rb_str_buf_cat2(str, "/");
if (re) {
- char opts[OPTBUF_SIZE];
- rb_reg_check(re);
- if (*option_to_str(opts, RREGEXP_PTR(re)->options))
- rb_str_buf_cat2(str, opts);
- if (RBASIC(re)->flags & REG_ENCODING_NONE)
- rb_str_buf_cat2(str, "n");
+ char opts[OPTBUF_SIZE];
+ rb_reg_check(re);
+ if (*option_to_str(opts, RREGEXP_PTR(re)->options))
+ rb_str_buf_cat2(str, opts);
+ if (RBASIC(re)->flags & REG_ENCODING_NONE)
+ rb_str_buf_cat2(str, "n");
}
return str;
}
@@ -478,15 +480,19 @@ rb_reg_desc(const char *s, long len, VALUE re)
/*
* call-seq:
- * rxp.source -> str
+ * source -> string
+ *
+ * Returns the original string of +self+:
+ *
+ * /ab+c/ix.source # => "ab+c"
*
- * Returns the original string of the pattern.
+ * Regexp escape sequences are retained:
*
- * /ab+c/ix.source #=> "ab+c"
+ * /\x20\+/.source # => "\\x20\\+"
*
- * Note that escape sequences are retained as is.
+ * Lexer escape characters are not retained:
*
- * /\x20\+/.source #=> "\\x20\\+"
+ * /\//.source # => "/"
*
*/
@@ -501,15 +507,14 @@ rb_reg_source(VALUE re)
}
/*
- * call-seq:
- * rxp.inspect -> string
+ * call-seq:
+ * inspect -> string
*
- * Produce a nicely formatted string-version of _rxp_. Perhaps surprisingly,
- * <code>#inspect</code> actually produces the more natural version of
- * the string than <code>#to_s</code>.
+ * Returns a nicely-formatted string representation of +self+:
*
- * /ab+c/ix.inspect #=> "/ab+c/ix"
+ * /ab+c/ix.inspect # => "/ab+c/ix"
*
+ * Related: Regexp#to_s.
*/
static VALUE
@@ -525,22 +530,29 @@ static VALUE rb_reg_str_with_term(VALUE re, int term);
/*
* call-seq:
- * rxp.to_s -> str
- *
- * Returns a string containing the regular expression and its options (using the
- * <code>(?opts:source)</code> notation. This string can be fed back in to
- * Regexp::new to a regular expression with the same semantics as the
- * original. (However, <code>Regexp#==</code> may not return true
- * when comparing the two, as the source of the regular expression
- * itself may differ, as the example shows). Regexp#inspect produces
- * a generally more readable version of <i>rxp</i>.
- *
- * r1 = /ab+c/ix #=> /ab+c/ix
- * s1 = r1.to_s #=> "(?ix-m:ab+c)"
- * r2 = Regexp.new(s1) #=> /(?ix-m:ab+c)/
- * r1 == r2 #=> false
- * r1.source #=> "ab+c"
- * r2.source #=> "(?ix-m:ab+c)"
+ * to_s -> string
+ *
+ * Returns a string showing the options and string of +self+:
+ *
+ * r0 = /ab+c/ix
+ * s0 = r0.to_s # => "(?ix-m:ab+c)"
+ *
+ * The returned string may be used as an argument to Regexp.new,
+ * or as interpolated text for a
+ * {Regexp literal}[rdoc-ref:regexp.rdoc@Regexp+Literal]:
+ *
+ * r1 = Regexp.new(s0) # => /(?ix-m:ab+c)/
+ * r2 = /#{s0}/ # => /(?ix-m:ab+c)/
+ *
+ * Note that +r1+ and +r2+ are not equal to +r0+
+ * because their original strings are different:
+ *
+ * r0 == r1 # => false
+ * r0.source # => "ab+c"
+ * r1.source # => "(?ix-m:ab+c)"
+ *
+ * Related: Regexp#inspect.
+ *
*/
static VALUE
@@ -568,10 +580,10 @@ rb_reg_str_with_term(VALUE re, int term)
len = RREGEXP_SRC_LEN(re);
again:
if (len >= 4 && ptr[0] == '(' && ptr[1] == '?') {
- int err = 1;
- ptr += 2;
- if ((len -= 2) > 0) {
- do {
+ int err = 1;
+ ptr += 2;
+ if ((len -= 2) > 0) {
+ do {
opt = char_to_option((int )*ptr);
if (opt != 0) {
options |= opt;
@@ -579,13 +591,13 @@ rb_reg_str_with_term(VALUE re, int term)
else {
break;
}
- ++ptr;
- } while (--len > 0);
- }
- if (len > 1 && *ptr == '-') {
- ++ptr;
- --len;
- do {
+ ++ptr;
+ } while (--len > 0);
+ }
+ if (len > 1 && *ptr == '-') {
+ ++ptr;
+ --len;
+ do {
opt = char_to_option((int )*ptr);
if (opt != 0) {
options &= ~opt;
@@ -593,65 +605,65 @@ rb_reg_str_with_term(VALUE re, int term)
else {
break;
}
- ++ptr;
- } while (--len > 0);
- }
- if (*ptr == ')') {
- --len;
- ++ptr;
- goto again;
- }
- if (*ptr == ':' && ptr[len-1] == ')') {
- Regexp *rp;
- VALUE verbose = ruby_verbose;
- ruby_verbose = Qfalse;
-
- ++ptr;
- len -= 2;
+ ++ptr;
+ } while (--len > 0);
+ }
+ if (*ptr == ')') {
+ --len;
+ ++ptr;
+ goto again;
+ }
+ if (*ptr == ':' && ptr[len-1] == ')') {
+ Regexp *rp;
+ VALUE verbose = ruby_verbose;
+ ruby_verbose = Qfalse;
+
+ ++ptr;
+ len -= 2;
err = onig_new(&rp, ptr, ptr + len, options,
- enc, OnigDefaultSyntax, NULL);
- onig_free(rp);
- ruby_verbose = verbose;
- }
- if (err) {
- options = RREGEXP_PTR(re)->options;
- ptr = (UChar*)RREGEXP_SRC_PTR(re);
- len = RREGEXP_SRC_LEN(re);
- }
+ enc, OnigDefaultSyntax, NULL);
+ onig_free(rp);
+ ruby_verbose = verbose;
+ }
+ if (err) {
+ options = RREGEXP_PTR(re)->options;
+ ptr = (UChar*)RREGEXP_SRC_PTR(re);
+ len = RREGEXP_SRC_LEN(re);
+ }
}
if (*option_to_str(optbuf, options)) rb_str_buf_cat2(str, optbuf);
if ((options & embeddable) != embeddable) {
- optbuf[0] = '-';
- option_to_str(optbuf + 1, ~options);
- rb_str_buf_cat2(str, optbuf);
+ optbuf[0] = '-';
+ option_to_str(optbuf + 1, ~options);
+ rb_str_buf_cat2(str, optbuf);
}
rb_str_buf_cat2(str, ":");
if (rb_enc_asciicompat(enc)) {
- rb_reg_expr_str(str, (char*)ptr, len, enc, NULL, term);
- rb_str_buf_cat2(str, ")");
+ rb_reg_expr_str(str, (char*)ptr, len, enc, NULL, term);
+ rb_str_buf_cat2(str, ")");
}
else {
- const char *s, *e;
- char *paren;
- ptrdiff_t n;
- rb_str_buf_cat2(str, ")");
- rb_enc_associate(str, rb_usascii_encoding());
- str = rb_str_encode(str, rb_enc_from_encoding(enc), 0, Qnil);
-
- /* backup encoded ")" to paren */
- s = RSTRING_PTR(str);
- e = RSTRING_END(str);
- s = rb_enc_left_char_head(s, e-1, e, enc);
- n = e - s;
- paren = ALLOCA_N(char, n);
- memcpy(paren, s, n);
- rb_str_resize(str, RSTRING_LEN(str) - n);
-
- rb_reg_expr_str(str, (char*)ptr, len, enc, NULL, term);
- rb_str_buf_cat(str, paren, n);
+ const char *s, *e;
+ char *paren;
+ ptrdiff_t n;
+ rb_str_buf_cat2(str, ")");
+ rb_enc_associate(str, rb_usascii_encoding());
+ str = rb_str_encode(str, rb_enc_from_encoding(enc), 0, Qnil);
+
+ /* backup encoded ")" to paren */
+ s = RSTRING_PTR(str);
+ e = RSTRING_END(str);
+ s = rb_enc_left_char_head(s, e-1, e, enc);
+ n = e - s;
+ paren = ALLOCA_N(char, n);
+ memcpy(paren, s, n);
+ rb_str_resize(str, RSTRING_LEN(str) - n);
+
+ rb_reg_expr_str(str, (char*)ptr, len, enc, NULL, term);
+ rb_str_buf_cat(str, paren, n);
}
rb_enc_copy(str, re);
@@ -697,7 +709,7 @@ static VALUE
rb_reg_error_desc(VALUE str, int options, const char *err)
{
return rb_enc_reg_error_desc(RSTRING_PTR(str), RSTRING_LEN(str),
- rb_enc_get(str), options, err);
+ rb_enc_get(str), options, err);
}
NORETURN(static void rb_reg_raise_str(VALUE str, int options, const char *err));
@@ -711,13 +723,15 @@ rb_reg_raise_str(VALUE str, int options, const char *err)
/*
* call-seq:
- * rxp.casefold? -> true or false
+ * casefold?-> true or false
*
- * Returns the value of the case-insensitive flag.
+ * Returns +true+ if the case-insensitivity flag in +self+ is set,
+ * +false+ otherwise:
+ *
+ * /a/.casefold? # => false
+ * /a/i.casefold? # => true
+ * /(?i:a)/.casefold? # => false
*
- * /a/.casefold? #=> false
- * /a/i.casefold? #=> true
- * /(?i:a)/.casefold? #=> false
*/
static VALUE
@@ -730,25 +744,39 @@ rb_reg_casefold_p(VALUE re)
/*
* call-seq:
- * rxp.options -> integer
+ * options -> integer
+ *
+ * Returns an integer whose bits show the options set in +self+.
+ *
+ * The option bits are:
+ *
+ * Regexp::IGNORECASE # => 1
+ * Regexp::EXTENDED # => 2
+ * Regexp::MULTILINE # => 4
+ *
+ * Examples:
+ *
+ * /foo/.options # => 0
+ * /foo/i.options # => 1
+ * /foo/x.options # => 2
+ * /foo/m.options # => 4
+ * /foo/mix.options # => 7
+ *
+ * Note that additional bits may be set in the returned integer;
+ * these are maintained internally internally in +self+,
+ * are ignored if passed to Regexp.new, and may be ignored by the caller:
*
* Returns the set of bits corresponding to the options used when
- * creating this Regexp (see Regexp::new for details. Note that
+ * creating this regexp (see Regexp::new for details). Note that
* additional bits may be set in the returned options: these are used
* internally by the regular expression code. These extra bits are
- * ignored if the options are passed to Regexp::new.
- *
- * Regexp::IGNORECASE #=> 1
- * Regexp::EXTENDED #=> 2
- * Regexp::MULTILINE #=> 4
+ * ignored if the options are passed to Regexp::new:
*
- * /cat/.options #=> 0
- * /cat/ix.options #=> 3
- * Regexp.new('cat', true).options #=> 1
- * /\xa1\xa2/e.options #=> 16
+ * r = /\xa1\xa2/e # => /\xa1\xa2/
+ * r.source # => "\\xa1\\xa2"
+ * r.options # => 16
+ * Regexp.new(r.source, r.options) # => /\xa1\xa2/
*
- * r = /cat/ix
- * Regexp.new(r.source, r.options) #=> /cat/ix
*/
static VALUE
@@ -768,19 +796,16 @@ reg_names_iter(const OnigUChar *name, const OnigUChar *name_end,
}
/*
- * call-seq:
- * rxp.names -> [name1, name2, ...]
- *
- * Returns a list of names of captures as an array of strings.
+ * call-seq:
+ * names -> array_of_names
*
- * /(?<foo>.)(?<bar>.)(?<baz>.)/.names
- * #=> ["foo", "bar", "baz"]
+ * Returns an array of names of captures
+ * (see {Named Captures}[rdoc-ref:Regexp@Named+Captures]):
*
- * /(?<foo>.)(?<foo>.)/.names
- * #=> ["foo"]
+ * /(?<foo>.)(?<bar>.)(?<baz>.)/.names # => ["foo", "bar", "baz"]
+ * /(?<foo>.)(?<foo>.)/.names # => ["foo"]
+ * /(.)(.)/.names # => []
*
- * /(.)(.)/.names
- * #=> []
*/
static VALUE
@@ -810,25 +835,21 @@ reg_named_captures_iter(const OnigUChar *name, const OnigUChar *name_end,
}
/*
- * call-seq:
- * rxp.named_captures -> hash
- *
- * Returns a hash representing information about named captures of <i>rxp</i>.
+ * call-seq:
+ * named_captures -> hash
*
- * A key of the hash is a name of the named captures.
- * A value of the hash is an array which is list of indexes of corresponding
- * named captures.
+ * Returns a hash representing named captures of +self+
+ * (see {Named Captures}[rdoc-ref:Regexp@Named+Captures]):
*
- * /(?<foo>.)(?<bar>.)/.named_captures
- * #=> {"foo"=>[1], "bar"=>[2]}
+ * - Each key is the name of a named capture.
+ * - Each value is an array of integer indexes for that named capture.
*
- * /(?<foo>.)(?<foo>.)/.named_captures
- * #=> {"foo"=>[1, 2]}
+ * Examples:
*
- * If there are no named captures, an empty hash is returned.
+ * /(?<foo>.)(?<bar>.)/.named_captures # => {"foo"=>[1], "bar"=>[2]}
+ * /(?<foo>.)(?<foo>.)/.named_captures # => {"foo"=>[1, 2]}
+ * /(.)(.)/.named_captures # => {}
*
- * /(.)(.)/.named_captures
- * #=> {}
*/
static VALUE
@@ -842,8 +863,8 @@ rb_reg_named_captures(VALUE re)
static int
onig_new_with_source(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
- OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
- OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
+ OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
+ OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
{
int r;
@@ -856,15 +877,15 @@ onig_new_with_source(regex_t** reg, const UChar* pattern, const UChar* pattern_e
r = onig_compile_ruby(*reg, pattern, pattern_end, einfo, sourcefile, sourceline);
if (r) {
err:
- onig_free(*reg);
- *reg = NULL;
+ onig_free(*reg);
+ *reg = NULL;
}
return r;
}
static Regexp*
make_regexp(const char *s, long len, rb_encoding *enc, int flags, onig_errmsg_buffer err,
- const char *sourcefile, int sourceline)
+ const char *sourcefile, int sourceline)
{
Regexp *rp;
int r;
@@ -878,10 +899,10 @@ make_regexp(const char *s, long len, rb_encoding *enc, int flags, onig_errmsg_bu
*/
r = onig_new_with_source(&rp, (UChar*)s, (UChar*)(s + len), flags,
- enc, OnigDefaultSyntax, &einfo, sourcefile, sourceline);
+ enc, OnigDefaultSyntax, &einfo, sourcefile, sourceline);
if (r) {
- onig_error_code_to_str((UChar*)err, r, &einfo);
- return 0;
+ onig_error_code_to_str((UChar*)err, r, &einfo);
+ return 0;
}
return rp;
}
@@ -1046,12 +1067,13 @@ update_char_offset(VALUE match)
}
}
-static void
+static VALUE
match_check(VALUE match)
{
if (!RMATCH(match)->regexp) {
- rb_raise(rb_eTypeError, "uninitialized MatchData");
+ rb_raise(rb_eTypeError, "uninitialized MatchData");
}
+ return match;
}
/* :nodoc: */
@@ -1067,7 +1089,7 @@ match_init_copy(VALUE obj, VALUE orig)
rm = RMATCH(obj)->rmatch;
if (rb_reg_region_copy(&rm->regs, RMATCH_REGS(orig)))
- rb_memerror();
+ rb_memerror();
if (RMATCH(orig)->rmatch->char_offset_num_allocated) {
if (rm->char_offset_num_allocated < rm->regs.num_regs) {
@@ -1076,7 +1098,7 @@ match_init_copy(VALUE obj, VALUE orig)
}
MEMCPY(rm->char_offset, RMATCH(orig)->rmatch->char_offset,
struct rmatch_offset, rm->regs.num_regs);
- RB_GC_GUARD(orig);
+ RB_GC_GUARD(orig);
}
return obj;
@@ -1084,13 +1106,14 @@ match_init_copy(VALUE obj, VALUE orig)
/*
- * call-seq:
- * mtch.regexp -> regexp
+ * call-seq:
+ * regexp -> regexp
*
- * Returns the regexp.
+ * Returns the regexp that produced the match:
+ *
+ * m = /a.*b/.match("abc") # => #<MatchData "ab">
+ * m.regexp # => /a.*b/
*
- * m = /a.*b/.match("abc")
- * m.regexp #=> /a.*b/
*/
static VALUE
@@ -1100,25 +1123,32 @@ match_regexp(VALUE match)
match_check(match);
regexp = RMATCH(match)->regexp;
if (NIL_P(regexp)) {
- VALUE str = rb_reg_nth_match(0, match);
- regexp = rb_reg_regcomp(rb_reg_quote(str));
- RMATCH(match)->regexp = regexp;
+ VALUE str = rb_reg_nth_match(0, match);
+ regexp = rb_reg_regcomp(rb_reg_quote(str));
+ RMATCH(match)->regexp = regexp;
}
return regexp;
}
/*
- * call-seq:
- * mtch.names -> [name1, name2, ...]
+ * call-seq:
+ * names -> array_of_names
+ *
+ * Returns an array of the capture names
+ * (see {Named Captures}[rdoc-ref:Regexp@Named+Captures]):
+ *
+ * m = /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge")
+ * # => #<MatchData "hog" foo:"h" bar:"o" baz:"g">
+ * m.names # => ["foo", "bar", "baz"]
+ *
+ * m = /foo/.match('foo') # => #<MatchData "foo">
+ * m.names # => [] # No named captures.
*
- * Returns a list of names of captures as an array of strings.
- * This is the same as mtch.regexp.names.
+ * Equivalent to:
*
- * /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").names
- * #=> ["foo", "bar", "baz"]
+ * m = /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge")
+ * m.regexp.names # => ["foo", "bar", "baz"]
*
- * m = /(?<x>.)(?<y>.)?/.match("a") #=> #<MatchData "a" x:"a" y:nil>
- * m.names #=> ["x", "y"]
*/
static VALUE
@@ -1126,20 +1156,22 @@ match_names(VALUE match)
{
match_check(match);
if (NIL_P(RMATCH(match)->regexp))
- return rb_ary_new_capa(0);
+ return rb_ary_new_capa(0);
return rb_reg_names(RMATCH(match)->regexp);
}
/*
* call-seq:
- * mtch.length -> integer
- * mtch.size -> integer
+ * size -> integer
*
- * Returns the number of elements in the match array.
+ * Returns size of the match array:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m.size # => 5
+ *
+ * MatchData#length is an alias for MatchData.size.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.length #=> 5
- * m.size #=> 5
*/
static VALUE
@@ -1150,6 +1182,21 @@ match_size(VALUE match)
}
static int name_to_backref_number(struct re_registers *, VALUE, const char*, const char*);
+NORETURN(static void name_to_backref_error(VALUE name));
+
+static void
+name_to_backref_error(VALUE name)
+{
+ rb_raise(rb_eIndexError, "undefined group name reference: % "PRIsVALUE,
+ name);
+}
+
+static void
+backref_number_check(struct re_registers *regs, int i)
+{
+ if (i < 0 || regs->num_regs <= i)
+ rb_raise(rb_eIndexError, "index %d out of matches", i);
+}
static int
match_backref_number(VALUE match, VALUE backref)
@@ -1162,17 +1209,17 @@ match_backref_number(VALUE match, VALUE backref)
match_check(match);
if (SYMBOL_P(backref)) {
- backref = rb_sym2str(backref);
+ backref = rb_sym2str(backref);
}
else if (!RB_TYPE_P(backref, T_STRING)) {
- return NUM2INT(backref);
+ return NUM2INT(backref);
}
name = StringValueCStr(backref);
- num = name_to_backref_number(regs, regexp, name, name + strlen(name));
+ num = name_to_backref_number(regs, regexp, name, name + RSTRING_LEN(backref));
if (num < 1) {
- rb_raise(rb_eIndexError, "undefined group name reference: %s", name);
+ name_to_backref_error(backref);
}
return num;
@@ -1186,108 +1233,200 @@ rb_reg_backref_number(VALUE match, VALUE backref)
/*
* call-seq:
- * mtch.offset(n) -> array
+ * offset(n) -> [start_offset, end_offset]
+ * offset(name) -> [start_offset, end_offset]
+ *
+ * :include: doc/matchdata/offset.rdoc
*
- * Returns a two-element array containing the beginning and ending offsets of
+ */
+
+static VALUE
+match_offset(VALUE match, VALUE n)
+{
+ int i = match_backref_number(match, n);
+ struct re_registers *regs = RMATCH_REGS(match);
+
+ match_check(match);
+ backref_number_check(regs, i);
+
+ if (BEG(i) < 0)
+ return rb_assoc_new(Qnil, Qnil);
+
+ update_char_offset(match);
+ return rb_assoc_new(LONG2NUM(RMATCH(match)->rmatch->char_offset[i].beg),
+ LONG2NUM(RMATCH(match)->rmatch->char_offset[i].end));
+}
+
+/*
+ * call-seq:
+ * mtch.byteoffset(n) -> array
+ *
+ * Returns a two-element array containing the beginning and ending byte-based offsets of
* the <em>n</em>th match.
* <em>n</em> can be a string or symbol to reference a named capture.
*
* m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.offset(0) #=> [1, 7]
- * m.offset(4) #=> [6, 7]
+ * m.byteoffset(0) #=> [1, 7]
+ * m.byteoffset(4) #=> [6, 7]
*
* m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
- * p m.offset(:foo) #=> [0, 1]
- * p m.offset(:bar) #=> [2, 3]
+ * p m.byteoffset(:foo) #=> [0, 1]
+ * p m.byteoffset(:bar) #=> [2, 3]
*
*/
static VALUE
-match_offset(VALUE match, VALUE n)
+match_byteoffset(VALUE match, VALUE n)
{
int i = match_backref_number(match, n);
struct re_registers *regs = RMATCH_REGS(match);
match_check(match);
- if (i < 0 || regs->num_regs <= i)
- rb_raise(rb_eIndexError, "index %d out of matches", i);
+ backref_number_check(regs, i);
if (BEG(i) < 0)
- return rb_assoc_new(Qnil, Qnil);
+ return rb_assoc_new(Qnil, Qnil);
+ return rb_assoc_new(LONG2NUM(BEG(i)), LONG2NUM(END(i)));
+}
+
+
+/*
+ * call-seq:
+ * begin(n) -> integer
+ * begin(name) -> integer
+ *
+ * :include: doc/matchdata/begin.rdoc
+ *
+ */
+
+static VALUE
+match_begin(VALUE match, VALUE n)
+{
+ int i = match_backref_number(match, n);
+ struct re_registers *regs = RMATCH_REGS(match);
+
+ match_check(match);
+ backref_number_check(regs, i);
+
+ if (BEG(i) < 0)
+ return Qnil;
update_char_offset(match);
- return rb_assoc_new(INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg),
- INT2FIX(RMATCH(match)->rmatch->char_offset[i].end));
+ return LONG2NUM(RMATCH(match)->rmatch->char_offset[i].beg);
}
/*
* call-seq:
- * mtch.begin(n) -> integer
+ * end(n) -> integer
+ * end(name) -> integer
*
- * Returns the offset of the start of the <em>n</em>th element of the match
- * array in the string.
- * <em>n</em> can be a string or symbol to reference a named capture.
+ * :include: doc/matchdata/end.rdoc
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.begin(0) #=> 1
- * m.begin(2) #=> 2
- *
- * m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
- * p m.begin(:foo) #=> 0
- * p m.begin(:bar) #=> 2
*/
static VALUE
-match_begin(VALUE match, VALUE n)
+match_end(VALUE match, VALUE n)
{
int i = match_backref_number(match, n);
struct re_registers *regs = RMATCH_REGS(match);
match_check(match);
- if (i < 0 || regs->num_regs <= i)
- rb_raise(rb_eIndexError, "index %d out of matches", i);
+ backref_number_check(regs, i);
if (BEG(i) < 0)
- return Qnil;
+ return Qnil;
update_char_offset(match);
- return INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg);
+ return LONG2NUM(RMATCH(match)->rmatch->char_offset[i].end);
}
+/*
+ * call-seq:
+ * match(n) -> string or nil
+ * match(name) -> string or nil
+ *
+ * Returns the matched substring corresponding to the given argument.
+ *
+ * When non-negative argument +n+ is given,
+ * returns the matched substring for the <tt>n</tt>th match:
+ *
+ * m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8" 5:nil>
+ * m.match(0) # => "HX1138"
+ * m.match(4) # => "8"
+ * m.match(5) # => nil
+ *
+ * When string or symbol argument +name+ is given,
+ * returns the matched substring for the given name:
+ *
+ * m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge")
+ * # => #<MatchData "hoge" foo:"h" bar:"ge">
+ * m.match('foo') # => "h"
+ * m.match(:bar) # => "ge"
+ *
+ */
+
+static VALUE
+match_nth(VALUE match, VALUE n)
+{
+ int i = match_backref_number(match, n);
+ struct re_registers *regs = RMATCH_REGS(match);
+
+ backref_number_check(regs, i);
+
+ long start = BEG(i), end = END(i);
+ if (start < 0)
+ return Qnil;
+
+ return rb_str_subseq(RMATCH(match)->str, start, end - start);
+}
/*
* call-seq:
- * mtch.end(n) -> integer
+ * match_length(n) -> integer or nil
+ * match_length(name) -> integer or nil
*
- * Returns the offset of the character immediately following the end of the
- * <em>n</em>th element of the match array in the string.
- * <em>n</em> can be a string or symbol to reference a named capture.
+ * Returns the length (in characters) of the matched substring
+ * corresponding to the given argument.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.end(0) #=> 7
- * m.end(2) #=> 3
+ * When non-negative argument +n+ is given,
+ * returns the length of the matched substring
+ * for the <tt>n</tt>th match:
+ *
+ * m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8" 5:nil>
+ * m.match_length(0) # => 6
+ * m.match_length(4) # => 1
+ * m.match_length(5) # => nil
+ *
+ * When string or symbol argument +name+ is given,
+ * returns the length of the matched substring
+ * for the named match:
+ *
+ * m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge")
+ * # => #<MatchData "hoge" foo:"h" bar:"ge">
+ * m.match_length('foo') # => 1
+ * m.match_length(:bar) # => 2
*
- * m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
- * p m.end(:foo) #=> 1
- * p m.end(:bar) #=> 3
*/
static VALUE
-match_end(VALUE match, VALUE n)
+match_nth_length(VALUE match, VALUE n)
{
int i = match_backref_number(match, n);
struct re_registers *regs = RMATCH_REGS(match);
match_check(match);
- if (i < 0 || regs->num_regs <= i)
- rb_raise(rb_eIndexError, "index %d out of matches", i);
+ backref_number_check(regs, i);
if (BEG(i) < 0)
- return Qnil;
+ return Qnil;
update_char_offset(match);
- return INT2FIX(RMATCH(match)->rmatch->char_offset[i].end);
+ const struct rmatch_offset *const ofs =
+ &RMATCH(match)->rmatch->char_offset[i];
+ return LONG2NUM(ofs->end - ofs->beg);
}
#define MATCH_BUSY FL_USER2
@@ -1322,11 +1461,11 @@ rb_match_nth_defined(int nth, VALUE match)
regs = RMATCH_REGS(match);
if (!regs) return FALSE;
if (nth >= regs->num_regs) {
- return FALSE;
+ return FALSE;
}
if (nth < 0) {
- nth += regs->num_regs;
- if (nth <= 0) return FALSE;
+ nth += regs->num_regs;
+ if (nth <= 0) return FALSE;
}
return (BEG(nth) != -1);
}
@@ -1350,7 +1489,7 @@ rb_backref_set_string(VALUE string, long pos, long len)
{
VALUE match = rb_backref_get();
if (NIL_P(match) || FL_TEST(match, MATCH_BUSY)) {
- match = match_alloc(rb_cMatch);
+ match = match_alloc(rb_cMatch);
}
match_set_string(match, string, pos, len);
rb_backref_set(match);
@@ -1358,31 +1497,31 @@ rb_backref_set_string(VALUE string, long pos, long len)
/*
* call-seq:
- * rxp.fixed_encoding? -> true or false
- *
- * Returns false if rxp is applicable to
- * a string with any ASCII compatible encoding.
- * Returns true otherwise.
- *
- * r = /a/
- * r.fixed_encoding? #=> false
- * r =~ "\u{6666} a" #=> 2
- * r =~ "\xa1\xa2 a".force_encoding("euc-jp") #=> 2
- * r =~ "abc".force_encoding("euc-jp") #=> 0
- *
- * r = /a/u
- * r.fixed_encoding? #=> true
- * r.encoding #=> #<Encoding:UTF-8>
- * r =~ "\u{6666} a" #=> 2
- * r =~ "\xa1\xa2".force_encoding("euc-jp") #=> Encoding::CompatibilityError
- * r =~ "abc".force_encoding("euc-jp") #=> 0
- *
- * r = /\u{6666}/
- * r.fixed_encoding? #=> true
- * r.encoding #=> #<Encoding:UTF-8>
- * r =~ "\u{6666} a" #=> 0
- * r =~ "\xa1\xa2".force_encoding("euc-jp") #=> Encoding::CompatibilityError
- * r =~ "abc".force_encoding("euc-jp") #=> nil
+ * fixed_encoding? -> true or false
+ *
+ * Returns +false+ if +self+ is applicable to
+ * a string with any ASCII-compatible encoding;
+ * otherwise returns +true+:
+ *
+ * r = /a/ # => /a/
+ * r.fixed_encoding? # => false
+ * r.match?("\u{6666} a") # => true
+ * r.match?("\xa1\xa2 a".force_encoding("euc-jp")) # => true
+ * r.match?("abc".force_encoding("euc-jp")) # => true
+ *
+ * r = /a/u # => /a/
+ * r.fixed_encoding? # => true
+ * r.match?("\u{6666} a") # => true
+ * r.match?("\xa1\xa2".force_encoding("euc-jp")) # Raises exception.
+ * r.match?("abc".force_encoding("euc-jp")) # => true
+ *
+ * r = /\u{6666}/ # => /\u{6666}/
+ * r.fixed_encoding? # => true
+ * r.encoding # => #<Encoding:UTF-8>
+ * r.match?("\u{6666} a") # => true
+ * r.match?("\xa1\xa2".force_encoding("euc-jp")) # Raises exception.
+ * r.match?("abc".force_encoding("euc-jp")) # => false
+ *
*/
static VALUE
@@ -1393,7 +1532,7 @@ rb_reg_fixed_encoding_p(VALUE re)
static VALUE
rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
- rb_encoding **fixed_enc, onig_errmsg_buffer err);
+ rb_encoding **fixed_enc, onig_errmsg_buffer err, int options);
NORETURN(static void reg_enc_error(VALUE re, VALUE str));
@@ -1401,9 +1540,9 @@ static void
reg_enc_error(VALUE re, VALUE str)
{
rb_raise(rb_eEncCompatError,
- "incompatible encoding regexp match (%s regexp with %s string)",
- rb_enc_name(rb_enc_get(re)),
- rb_enc_name(rb_enc_get(str)));
+ "incompatible encoding regexp match (%s regexp with %s string)",
+ rb_enc_name(rb_enc_get(re)),
+ rb_enc_name(rb_enc_get(str)));
}
static inline int
@@ -1411,7 +1550,7 @@ str_coderange(VALUE str)
{
int cr = ENC_CODERANGE(str);
if (cr == ENC_CODERANGE_UNKNOWN) {
- cr = rb_enc_str_coderange(str);
+ cr = rb_enc_str_coderange(str);
}
return cr;
}
@@ -1433,24 +1572,24 @@ rb_reg_prepare_enc(VALUE re, VALUE str, int warn)
if (RREGEXP_PTR(re)->enc == enc) {
}
else if (cr == ENC_CODERANGE_7BIT &&
- RREGEXP_PTR(re)->enc == rb_usascii_encoding()) {
- enc = RREGEXP_PTR(re)->enc;
+ RREGEXP_PTR(re)->enc == rb_usascii_encoding()) {
+ enc = RREGEXP_PTR(re)->enc;
}
else if (!rb_enc_asciicompat(enc)) {
- reg_enc_error(re, str);
+ reg_enc_error(re, str);
}
else if (rb_reg_fixed_encoding_p(re)) {
if ((!rb_enc_asciicompat(RREGEXP_PTR(re)->enc) ||
- cr != ENC_CODERANGE_7BIT)) {
- reg_enc_error(re, str);
- }
- enc = RREGEXP_PTR(re)->enc;
+ cr != ENC_CODERANGE_7BIT)) {
+ reg_enc_error(re, str);
+ }
+ enc = RREGEXP_PTR(re)->enc;
}
else if (warn && (RBASIC(re)->flags & REG_ENCODING_NONE) &&
- enc != rb_ascii8bit_encoding() &&
- cr != ENC_CODERANGE_7BIT) {
- rb_warn("historical binary regexp match /.../n against %s string",
- rb_enc_name(enc));
+ enc != rb_ascii8bit_encoding() &&
+ cr != ENC_CODERANGE_7BIT) {
+ rb_warn("historical binary regexp match /.../n against %s string",
+ rb_enc_name(enc));
}
return enc;
}
@@ -1473,24 +1612,29 @@ rb_reg_prepare_re0(VALUE re, VALUE str, onig_errmsg_buffer err)
pattern = RREGEXP_SRC_PTR(re);
unescaped = rb_reg_preprocess(
- pattern, pattern + RREGEXP_SRC_LEN(re), enc,
- &fixed_enc, err);
+ pattern, pattern + RREGEXP_SRC_LEN(re), enc,
+ &fixed_enc, err, 0);
- if (unescaped == Qnil) {
- rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
+ if (NIL_P(unescaped)) {
+ rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
}
+ // inherit the timeout settings
+ rb_hrtime_t timelimit = reg->timelimit;
+
const char *ptr;
long len;
RSTRING_GETMEM(unescaped, ptr, len);
r = onig_new(&reg, (UChar *)ptr, (UChar *)(ptr + len),
- reg->options, enc,
- OnigDefaultSyntax, &einfo);
+ reg->options, enc,
+ OnigDefaultSyntax, &einfo);
if (r) {
- onig_error_code_to_str((UChar*)err, r, &einfo);
- rb_reg_raise(pattern, RREGEXP_SRC_LEN(re), err, re);
+ onig_error_code_to_str((UChar*)err, r, &einfo);
+ rb_reg_raise(pattern, RREGEXP_SRC_LEN(re), err, re);
}
+ reg->timelimit = timelimit;
+
RB_GC_GUARD(unescaped);
return reg;
}
@@ -1512,30 +1656,30 @@ rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int reverse)
enc = rb_reg_prepare_enc(re, str, 0);
if (reverse) {
- range = -pos;
+ range = -pos;
}
else {
- range = RSTRING_LEN(str) - pos;
+ range = RSTRING_LEN(str) - pos;
}
if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(str)) {
- string = (UChar*)RSTRING_PTR(str);
+ string = (UChar*)RSTRING_PTR(str);
- if (range > 0) {
- p = onigenc_get_right_adjust_char_head(enc, string, string + pos, string + RSTRING_LEN(str));
- }
- else {
- p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos, string + RSTRING_LEN(str));
- }
- return p - string;
+ if (range > 0) {
+ p = onigenc_get_right_adjust_char_head(enc, string, string + pos, string + RSTRING_LEN(str));
+ }
+ else {
+ p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos, string + RSTRING_LEN(str));
+ }
+ return p - string;
}
return pos;
}
/* 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;
@@ -1549,77 +1693,75 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
RSTRING_GETMEM(str, start, len);
range = start;
if (pos > len || pos < 0) {
- rb_backref_set(Qnil);
- return -1;
+ rb_backref_set(Qnil);
+ return -1;
}
reg = rb_reg_prepare_re0(re, str, err);
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 += len;
+ range += len;
}
result = onig_search(reg,
- (UChar*)start,
- ((UChar*)(start + len)),
- ((UChar*)(start + pos)),
- ((UChar*)range),
- regs, ONIG_OPTION_NONE);
+ (UChar*)start,
+ ((UChar*)(start + len)),
+ ((UChar*)(start + pos)),
+ ((UChar*)range),
+ regs, ONIG_OPTION_NONE);
if (!tmpreg) RREGEXP(re)->usecnt--;
if (tmpreg) {
- if (RREGEXP(re)->usecnt) {
- onig_free(reg);
- }
- else {
- onig_free(RREGEXP_PTR(re));
- RREGEXP_PTR(re) = reg;
- }
+ if (RREGEXP(re)->usecnt) {
+ onig_free(reg);
+ }
+ else {
+ onig_free(RREGEXP_PTR(re));
+ RREGEXP_PTR(re) = reg;
+ }
}
if (result < 0) {
- if (regs == &regi)
- onig_region_free(regs, 0);
- if (result == ONIG_MISMATCH) {
- rb_backref_set(Qnil);
- return result;
- }
- else {
- onig_error_code_to_str((UChar*)err, (int)result);
- rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
- }
+ if (regs == &regi)
+ onig_region_free(regs, 0);
+ if (result == ONIG_MISMATCH) {
+ rb_backref_set(Qnil);
+ return result;
+ }
+ else {
+ onig_error_code_to_str((UChar*)err, (int)result);
+ rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
+ }
}
- 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);
+ memcpy(RMATCH_REGS(match), regs, sizeof(struct re_registers));
if (set_backref_str) {
- RMATCH(match)->str = rb_str_new4(str);
+ RMATCH(match)->str = rb_str_new4(str);
+ }
+ else {
+ /* Note that a MatchData object with RMATCH(match)->str == 0 is incomplete!
+ * We need to hide the object from ObjectSpace.each_object.
+ * https://bugs.ruby-lang.org/issues/19159
+ */
+ rb_obj_hide(match);
}
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);
@@ -1641,53 +1783,53 @@ rb_reg_start_with_p(VALUE re, VALUE str)
match = rb_backref_get();
if (!NIL_P(match)) {
- if (FL_TEST(match, MATCH_BUSY)) {
- match = Qnil;
- }
- else {
- regs = RMATCH_REGS(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);
}
const char *ptr;
long len;
RSTRING_GETMEM(str, ptr, len);
result = onig_match(reg,
- (UChar*)(ptr),
- ((UChar*)(ptr + len)),
- (UChar*)(ptr),
- regs, ONIG_OPTION_NONE);
+ (UChar*)(ptr),
+ ((UChar*)(ptr + len)),
+ (UChar*)(ptr),
+ regs, ONIG_OPTION_NONE);
if (!tmpreg) RREGEXP(re)->usecnt--;
if (tmpreg) {
- if (RREGEXP(re)->usecnt) {
- onig_free(reg);
- }
- else {
- onig_free(RREGEXP_PTR(re));
- RREGEXP_PTR(re) = reg;
- }
+ if (RREGEXP(re)->usecnt) {
+ onig_free(reg);
+ }
+ else {
+ onig_free(RREGEXP_PTR(re));
+ RREGEXP_PTR(re) = reg;
+ }
}
if (result < 0) {
- if (regs == &regi)
- onig_region_free(regs, 0);
- if (result == ONIG_MISMATCH) {
- rb_backref_set(Qnil);
- return false;
- }
- else {
- onig_error_code_to_str((UChar*)err, (int)result);
- rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
- }
+ if (regs == &regi)
+ onig_region_free(regs, 0);
+ if (result == ONIG_MISMATCH) {
+ rb_backref_set(Qnil);
+ return false;
+ }
+ else {
+ onig_error_code_to_str((UChar*)err, (int)result);
+ rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
+ }
}
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();
+ 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();
}
RMATCH(match)->str = rb_str_new4(str);
@@ -1706,14 +1848,13 @@ rb_reg_nth_defined(int nth, VALUE match)
match_check(match);
regs = RMATCH_REGS(match);
if (nth >= regs->num_regs) {
- return Qnil;
+ return Qnil;
}
if (nth < 0) {
- nth += regs->num_regs;
- if (nth <= 0) return Qnil;
+ nth += regs->num_regs;
+ if (nth <= 0) return Qnil;
}
- if (BEG(nth) == -1) return Qfalse;
- return Qtrue;
+ return RBOOL(BEG(nth) != -1);
}
VALUE
@@ -1727,11 +1868,11 @@ rb_reg_nth_match(int nth, VALUE match)
match_check(match);
regs = RMATCH_REGS(match);
if (nth >= regs->num_regs) {
- return Qnil;
+ return Qnil;
}
if (nth < 0) {
- nth += regs->num_regs;
- if (nth <= 0) return Qnil;
+ nth += regs->num_regs;
+ if (nth <= 0) return Qnil;
}
start = BEG(nth);
if (start == -1) return Qnil;
@@ -1750,13 +1891,19 @@ rb_reg_last_match(VALUE match)
/*
* call-seq:
- * mtch.pre_match -> str
+ * pre_match -> string
*
- * Returns the portion of the original string before the current match.
- * Equivalent to the special variable <code>$`</code>.
+ * Returns the substring of the target string from its beginning
+ * up to the first match in +self+ (that is, <tt>self[0]</tt>);
+ * equivalent to regexp global variable <tt>$`</tt>:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m[0] # => "HX1138"
+ * m.pre_match # => "T"
+ *
+ * Related: MatchData#post_match.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.pre_match #=> "T"
*/
VALUE
@@ -1776,13 +1923,20 @@ rb_reg_match_pre(VALUE match)
/*
* call-seq:
- * mtch.post_match -> str
+ * post_match -> str
+ *
+ * Returns the substring of the target string from
+ * the end of the first match in +self+ (that is, <tt>self[0]</tt>)
+ * to the end of the string;
+ * equivalent to regexp global variable <tt>$'</tt>:
*
- * Returns the portion of the original string after the current match.
- * Equivalent to the special variable <code>$'</code>.
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m[0] # => "HX1138"
+ * m.post_match # => ": The Movie"\
+ *
+ * Related: MatchData.pre_match.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- * m.post_match #=> ": The Movie"
*/
VALUE
@@ -1814,7 +1968,7 @@ rb_reg_match_last(VALUE match)
if (BEG(0) == -1) return Qnil;
for (i=regs->num_regs-1; BEG(i) == -1 && i > 0; i--)
- ;
+ ;
if (i == 0) return Qnil;
return rb_reg_nth_match(i, match);
}
@@ -1857,13 +2011,13 @@ match_array(VALUE match, int start)
target = RMATCH(match)->str;
for (i=start; i<regs->num_regs; i++) {
- if (regs->beg[i] == -1) {
- rb_ary_push(ary, Qnil);
- }
- else {
- VALUE str = rb_str_subseq(target, regs->beg[i], regs->end[i]-regs->beg[i]);
- rb_ary_push(ary, str);
- }
+ if (regs->beg[i] == -1) {
+ rb_ary_push(ary, Qnil);
+ }
+ else {
+ VALUE str = rb_str_subseq(target, regs->beg[i], regs->end[i]-regs->beg[i]);
+ rb_ary_push(ary, str);
+ }
}
return ary;
}
@@ -1871,24 +2025,16 @@ match_array(VALUE match, int start)
/*
* call-seq:
- * mtch.to_a -> anArray
+ * to_a -> array
*
- * Returns the array of matches.
+ * Returns the array of matches:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m.to_a # => ["HX1138", "H", "X", "113", "8"]
+ *
+ * Related: MatchData#captures.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.to_a #=> ["HX1138", "H", "X", "113", "8"]
- *
- * Because <code>to_a</code> is called when expanding
- * <code>*</code><em>variable</em>, there's a useful assignment
- * shortcut for extracting matched fields. This is slightly slower than
- * accessing the fields directly (as an intermediate array is
- * generated).
- *
- * all,f1,f2,f3 = * /(.)(.)(\d+)(\d)/.match("THX1138.")
- * all #=> "HX1138"
- * f1 #=> "H"
- * f2 #=> "X"
- * f3 #=> "113"
*/
static VALUE
@@ -1900,15 +2046,18 @@ match_to_a(VALUE match)
/*
* call-seq:
- * mtch.captures -> array
+ * captures -> array
*
- * Returns the array of captures; equivalent to <code>mtch.to_a[1..-1]</code>.
+ * Returns the array of captures,
+ * which are all matches except <tt>m[0]</tt>:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m[0] # => "HX1138"
+ * m.captures # => ["H", "X", "113", "8"]
+ *
+ * Related: MatchData.to_a.
*
- * f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
- * f1 #=> "H"
- * f2 #=> "X"
- * f3 #=> "113"
- * f4 #=> "8"
*/
static VALUE
match_captures(VALUE match)
@@ -1921,15 +2070,7 @@ name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name
{
if (NIL_P(regexp)) return -1;
return onig_name_to_backref_number(RREGEXP_PTR(regexp),
- (const unsigned char *)name, (const unsigned char *)name_end, regs);
-}
-
-NORETURN(static void name_to_backref_error(VALUE name));
-static void
-name_to_backref_error(VALUE name)
-{
- rb_raise(rb_eIndexError, "undefined group name reference: % "PRIsVALUE,
- name);
+ (const unsigned char *)name, (const unsigned char *)name_end, regs);
}
#define NAME_TO_NUMBER(regs, re, name, name_ptr, name_end) \
@@ -1943,15 +2084,15 @@ namev_to_backref_number(struct re_registers *regs, VALUE re, VALUE name)
int num;
if (SYMBOL_P(name)) {
- name = rb_sym2str(name);
+ name = rb_sym2str(name);
}
else if (!RB_TYPE_P(name, T_STRING)) {
- return -1;
+ return -1;
}
num = NAME_TO_NUMBER(regs, re, name,
- RSTRING_PTR(name), RSTRING_END(name));
+ RSTRING_PTR(name), RSTRING_END(name));
if (num < 1) {
- name_to_backref_error(name);
+ name_to_backref_error(name);
}
return num;
}
@@ -1965,10 +2106,10 @@ match_ary_subseq(VALUE match, long beg, long len, VALUE result)
if (len == 0) return result;
for (j = beg; j < end; j++) {
- rb_ary_push(result, rb_reg_nth_match((int)j, match));
+ rb_ary_push(result, rb_reg_nth_match((int)j, match));
}
if (beg + len > j) {
- rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
+ rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
}
return result;
}
@@ -1982,41 +2123,41 @@ match_ary_aref(VALUE match, VALUE idx, VALUE result)
/* check if idx is Range */
switch (rb_range_beg_len(idx, &beg, &len, (long)num_regs, !NIL_P(result))) {
case Qfalse:
- if (NIL_P(result)) return rb_reg_nth_match(NUM2INT(idx), match);
- rb_ary_push(result, rb_reg_nth_match(NUM2INT(idx), match));
- return result;
+ if (NIL_P(result)) return rb_reg_nth_match(NUM2INT(idx), match);
+ rb_ary_push(result, rb_reg_nth_match(NUM2INT(idx), match));
+ return result;
case Qnil:
- return Qnil;
+ return Qnil;
default:
- return match_ary_subseq(match, beg, len, result);
+ return match_ary_subseq(match, beg, len, result);
}
}
/*
* call-seq:
- * mtch[i] -> str or nil
- * mtch[start, length] -> array
- * mtch[range] -> array
- * mtch[name] -> str or nil
- *
- * Match Reference -- MatchData acts as an array, and may be accessed
- * using the normal array indexing techniques. <code>mtch[0]</code>
- * is equivalent to the special variable <code>$&</code>, and returns
- * the entire matched string. <code>mtch[1]</code>,
- * <code>mtch[2]</code>, and so on return the values of the matched
- * backreferences (portions of the pattern between parentheses).
+ * matchdata[index] -> string or nil
+ * matchdata[start, length] -> array
+ * matchdata[range] -> array
+ * matchdata[name] -> string or nil
+ *
+ * When arguments +index+, +start and +length+, or +range+ are given,
+ * returns match and captures in the style of Array#[]:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m[0] # => "HX1138"
+ * m[1, 2] # => ["H", "X"]
+ * m[1..3] # => ["H", "X", "113"]
+ * m[-3, 2] # => ["X", "113"]
+ *
+ * When string or symbol argument +name+ is given,
+ * returns the matched substring for the given name:
+ *
+ * m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge")
+ * # => #<MatchData "hoge" foo:"h" bar:"ge">
+ * m['foo'] # => "h"
+ * m[:bar] # => "ge"
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m #=> #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
- * m[0] #=> "HX1138"
- * m[1, 2] #=> ["H", "X"]
- * m[1..3] #=> ["H", "X", "113"]
- * m[-3, 2] #=> ["X", "113"]
- *
- * m = /(?<foo>a+)b/.match("ccaaab")
- * m #=> #<MatchData "aaab" foo:"aaa">
- * m["foo"] #=> "aaa"
- * m[:foo] #=> "aaa"
*/
static VALUE
@@ -2028,56 +2169,64 @@ match_aref(int argc, VALUE *argv, VALUE match)
rb_scan_args(argc, argv, "11", &idx, &length);
if (NIL_P(length)) {
- if (FIXNUM_P(idx)) {
- return rb_reg_nth_match(FIX2INT(idx), match);
- }
- else {
- int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, idx);
- if (num >= 0) {
- return rb_reg_nth_match(num, match);
- }
- else {
- return match_ary_aref(match, idx, Qnil);
- }
- }
+ if (FIXNUM_P(idx)) {
+ return rb_reg_nth_match(FIX2INT(idx), match);
+ }
+ else {
+ int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, idx);
+ if (num >= 0) {
+ return rb_reg_nth_match(num, match);
+ }
+ else {
+ return match_ary_aref(match, idx, Qnil);
+ }
+ }
}
else {
- long beg = NUM2LONG(idx);
- long len = NUM2LONG(length);
- long num_regs = RMATCH_REGS(match)->num_regs;
- if (len < 0) {
- return Qnil;
- }
- if (beg < 0) {
- beg += num_regs;
- if (beg < 0) return Qnil;
- }
- else if (beg > num_regs) {
- return Qnil;
- }
- else if (beg+len > num_regs) {
- len = num_regs - beg;
- }
- return match_ary_subseq(match, beg, len, Qnil);
+ long beg = NUM2LONG(idx);
+ long len = NUM2LONG(length);
+ long num_regs = RMATCH_REGS(match)->num_regs;
+ if (len < 0) {
+ return Qnil;
+ }
+ if (beg < 0) {
+ beg += num_regs;
+ if (beg < 0) return Qnil;
+ }
+ else if (beg > num_regs) {
+ return Qnil;
+ }
+ if (beg+len > num_regs) {
+ len = num_regs - beg;
+ }
+ return match_ary_subseq(match, beg, len, Qnil);
}
}
/*
* call-seq:
+ * values_at(*indexes) -> array
+ *
+ * Returns match and captures at the given +indexes+,
+ * which may include any mixture of:
*
- * mtch.values_at(index, ...) -> array
+ * - Integers.
+ * - Ranges.
+ * - Names (strings and symbols).
*
- * Uses each <i>index</i> to access the matching values, returning an array of
- * the corresponding matches.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
- * m.to_a #=> ["HX1138", "H", "X", "113", "8"]
- * m.values_at(0, 2, -2) #=> ["HX1138", "X", "113"]
- * m.values_at(1..2, -1) #=> ["H", "X", "8"]
+ * Examples:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m.values_at(0, 2, -2) # => ["HX1138", "X", "113"]
+ * m.values_at(1..2, -1) # => ["H", "X", "8"]
+ *
+ * m = /(?<a>\d+) *(?<op>[+\-*\/]) *(?<b>\d+)/.match("1 + 2")
+ * # => #<MatchData "1 + 2" a:"1" op:"+" b:"2">
+ * m.values_at(0, 1..2, :a, :b, :op)
+ * # => ["1 + 2", "1", "+", "1", "2", "+"]
*
- * m = /(?<a>\d+) *(?<op>[+\-*\/]) *(?<b>\d+)/.match("1 + 2")
- * m.to_a #=> ["1 + 2", "1", "+", "2"]
- * m.values_at(:a, :b, :op) #=> ["1", "2", "+"]
*/
static VALUE
@@ -2090,18 +2239,18 @@ match_values_at(int argc, VALUE *argv, VALUE match)
result = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- if (FIXNUM_P(argv[i])) {
- rb_ary_push(result, rb_reg_nth_match(FIX2INT(argv[i]), match));
- }
- else {
- int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, argv[i]);
- if (num >= 0) {
- rb_ary_push(result, rb_reg_nth_match(num, match));
- }
- else {
- match_ary_aref(match, argv[i], result);
- }
- }
+ if (FIXNUM_P(argv[i])) {
+ rb_ary_push(result, rb_reg_nth_match(FIX2INT(argv[i]), match));
+ }
+ else {
+ int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, argv[i]);
+ if (num >= 0) {
+ rb_ary_push(result, rb_reg_nth_match(num, match));
+ }
+ else {
+ match_ary_aref(match, argv[i], result);
+ }
+ }
}
return result;
}
@@ -2109,47 +2258,61 @@ match_values_at(int argc, VALUE *argv, VALUE match)
/*
* call-seq:
- * mtch.to_s -> str
+ * to_s -> string
*
- * Returns the entire matched string.
+ * Returns the matched string:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m.to_s # => "HX1138"
+ *
+ * m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge")
+ * # => #<MatchData "hoge" foo:"h" bar:"ge">
+ * m.to_s # => "hoge"
+ *
+ * Related: MatchData.inspect.
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.to_s #=> "HX1138"
*/
static VALUE
match_to_s(VALUE match)
{
- VALUE str = rb_reg_last_match(match);
+ VALUE str = rb_reg_last_match(match_check(match));
- match_check(match);
if (NIL_P(str)) str = rb_str_new(0,0);
return str;
}
static int
match_named_captures_iter(const OnigUChar *name, const OnigUChar *name_end,
- int back_num, int *back_refs, OnigRegex regex, void *arg) {
+ int back_num, int *back_refs, OnigRegex regex, void *arg)
+{
struct MEMO *memo = MEMO_CAST(arg);
VALUE hash = memo->v1;
VALUE match = memo->v2;
+ long symbolize = memo->u3.state;
VALUE key = rb_enc_str_new((const char *)name, name_end-name, regex->enc);
+
+ if (symbolize > 0) {
+ key = rb_str_intern(key);
+ }
+
VALUE value;
int i;
int found = 0;
for (i = 0; i < back_num; i++) {
- value = rb_reg_nth_match(back_refs[i], match);
- if (RTEST(value)) {
- rb_hash_aset(hash, key, value);
- found = 1;
- }
+ value = rb_reg_nth_match(back_refs[i], match);
+ if (RTEST(value)) {
+ rb_hash_aset(hash, key, value);
+ found = 1;
+ }
}
if (found == 0) {
- rb_hash_aset(hash, key, Qnil);
+ rb_hash_aset(hash, key, Qnil);
}
return 0;
@@ -2157,25 +2320,27 @@ match_named_captures_iter(const OnigUChar *name, const OnigUChar *name_end,
/*
* call-seq:
- * mtch.named_captures -> hash
+ * named_captures -> hash
*
- * Returns a Hash using named capture.
+ * Returns a hash of the named captures;
+ * each key is a capture name; each value is its captured string or +nil+:
*
- * A key of the hash is a name of the named captures.
- * A value of the hash is a string of last successful capture of corresponding
- * group.
+ * m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge")
+ * # => #<MatchData "hoge" foo:"h" bar:"ge">
+ * m.named_captures # => {"foo"=>"h", "bar"=>"ge"}
*
- * m = /(?<a>.)(?<b>.)/.match("01")
- * m.named_captures #=> {"a" => "0", "b" => "1"}
+ * m = /(?<a>.)(?<b>.)/.match("01")
+ * # => #<MatchData "01" a:"0" b:"1">
+ * m.named_captures #=> {"a" => "0", "b" => "1"}
*
- * m = /(?<a>.)(?<b>.)?/.match("0")
- * m.named_captures #=> {"a" => "0", "b" => nil}
+ * m = /(?<a>.)(?<b>.)?/.match("0")
+ * # => #<MatchData "0" a:"0" b:nil>
+ * m.named_captures #=> {"a" => "0", "b" => nil}
*
- * m = /(?<a>.)(?<a>.)/.match("01")
- * m.named_captures #=> {"a" => "1"}
+ * m = /(?<a>.)(?<a>.)/.match("01")
+ * # => #<MatchData "01" a:"0" a:"1">
+ * m.named_captures #=> {"a" => "1"}
*
- * m = /(?<a>x)|(?<a>y)/.match("x")
- * m.named_captures #=> {"a" => "x"}
*/
static VALUE
@@ -2186,7 +2351,7 @@ match_named_captures(VALUE match)
match_check(match);
if (NIL_P(RMATCH(match)->regexp))
- return rb_hash_new();
+ return rb_hash_new();
hash = rb_hash_new();
memo = MEMO_NEW(hash, match, 0);
@@ -2198,12 +2363,84 @@ match_named_captures(VALUE match)
/*
* call-seq:
- * mtch.string -> str
+ * deconstruct_keys(array_of_names) -> hash
*
- * Returns a frozen copy of the string passed in to <code>match</code>.
+ * Returns a hash of the named captures for the given names.
+ *
+ * m = /(?<hours>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2})/.match("18:37:22")
+ * m.deconstruct_keys([:hours, :minutes]) # => {:hours => "18", :minutes => "37"}
+ * m.deconstruct_keys(nil) # => {:hours => "18", :minutes => "37", :seconds => "22"}
+ *
+ * Returns an empty hash of no named captures were defined:
+ *
+ * m = /(\d{2}):(\d{2}):(\d{2})/.match("18:37:22")
+ * m.deconstruct_keys(nil) # => {}
+ *
+ */
+static VALUE
+match_deconstruct_keys(VALUE match, VALUE keys)
+{
+ VALUE h;
+ long i;
+
+ match_check(match);
+
+ if (NIL_P(RMATCH(match)->regexp)) {
+ return rb_hash_new_with_size(0);
+ }
+
+ if (NIL_P(keys)) {
+ h = rb_hash_new_with_size(onig_number_of_names(RREGEXP_PTR(RMATCH(match)->regexp)));
+
+ struct MEMO *memo;
+ memo = MEMO_NEW(h, match, 1);
+
+ onig_foreach_name(RREGEXP_PTR(RMATCH(match)->regexp), match_named_captures_iter, (void*)memo);
+
+ return h;
+ }
+
+ Check_Type(keys, T_ARRAY);
+
+ if (onig_number_of_names(RREGEXP_PTR(RMATCH(match)->regexp)) < RARRAY_LEN(keys)) {
+ return rb_hash_new_with_size(0);
+ }
+
+ h = rb_hash_new_with_size(RARRAY_LEN(keys));
+
+ for (i=0; i<RARRAY_LEN(keys); i++) {
+ VALUE key = RARRAY_AREF(keys, i);
+ VALUE name;
+
+ Check_Type(key, T_SYMBOL);
+
+ name = rb_sym2str(key);
+
+ int num = NAME_TO_NUMBER(RMATCH_REGS(match), RMATCH(match)->regexp, RMATCH(match)->regexp,
+ RSTRING_PTR(name), RSTRING_END(name));
+
+ if (num >= 0) {
+ rb_hash_aset(h, key, rb_reg_nth_match(num, match));
+ }
+ else {
+ return h;
+ }
+ }
+
+ return h;
+}
+
+/*
+ * call-seq:
+ * string -> string
+ *
+ * Returns the target string if it was frozen;
+ * otherwise, returns a frozen copy of the target string:
+ *
+ * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ * # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ * m.string # => "THX1138."
*
- * m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- * m.string #=> "THX1138."
*/
static VALUE
@@ -2234,21 +2471,23 @@ match_inspect_name_iter(const OnigUChar *name, const OnigUChar *name_end,
/*
* call-seq:
- * mtch.inspect -> str
+ * inspect -> string
*
- * Returns a printable version of <i>mtch</i>.
+ * Returns a string representation of +self+:
*
- * puts /.$/.match("foo").inspect
- * #=> #<MatchData "o">
+ * m = /.$/.match("foo")
+ * # => #<MatchData "o">
+ * m.inspect # => "#<MatchData \"o\">"
*
- * puts /(.)(.)(.)/.match("foo").inspect
- * #=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">
+ * m = /(.)(.)(.)/.match("foo")
+ * # => #<MatchData "foo" 1:"f" 2:"o" 3:"o">
+ * m.inspect # => "#<MatchData \"foo\" 1:\"f\" 2:\"o\
*
- * puts /(.)(.)?(.)/.match("fo").inspect
- * #=> #<MatchData "fo" 1:"f" 2:nil 3:"o">
+ * m = /(.)(.)?(.)/.match("fo")
+ * # => #<MatchData "fo" 1:"f" 2:nil 3:"o">
+ * m.inspect # => "#<MatchData \"fo\" 1:\"f\" 2:nil 3:\"o\">"
*
- * puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
- * #=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">
+ * Related: MatchData#to_s.
*
*/
@@ -2268,7 +2507,7 @@ match_inspect(VALUE match)
}
else if (NIL_P(regexp)) {
return rb_sprintf("#<%"PRIsVALUE": %"PRIsVALUE">",
- cname, rb_reg_nth_match(0, match));
+ cname, rb_reg_nth_match(0, match));
}
names = ALLOCA_N(struct backref_name_tag, num_regs);
@@ -2292,7 +2531,7 @@ match_inspect(VALUE match)
rb_str_buf_cat2(str, ":");
}
v = rb_reg_nth_match(i, match);
- if (v == Qnil)
+ if (NIL_P(v))
rb_str_buf_cat2(str, "nil");
else
rb_str_buf_append(str, rb_str_inspect(v));
@@ -2562,13 +2801,18 @@ unescape_unicode_bmp(const char **pp, const char *end,
}
static int
-unescape_nonascii(const char *p, const char *end, rb_encoding *enc,
+unescape_nonascii0(const char **pp, const char *end, rb_encoding *enc,
VALUE buf, rb_encoding **encp, int *has_property,
- onig_errmsg_buffer err)
+ onig_errmsg_buffer err, int options, int recurse)
{
+ const char *p = *pp;
unsigned char c;
char smallbuf[2];
+ int in_char_class = 0;
+ int parens = 1; /* ignored unless recurse is true */
+ int extended_mode = options & ONIG_OPTION_EXTEND;
+begin_scan:
while (p < end) {
int chlen = rb_enc_precise_mbclen(p, end, enc);
if (!MBCLEN_CHARFOUND_P(chlen)) {
@@ -2601,7 +2845,7 @@ unescape_nonascii(const char *p, const char *end, rb_encoding *enc,
goto invalid_multibyte;
}
if ((chlen = MBCLEN_CHARFOUND_LEN(chlen)) > 1) {
- /* include the previous backslash */
+ /* include the previous backslash */
--p;
++chlen;
goto multibyte;
@@ -2627,17 +2871,17 @@ unescape_nonascii(const char *p, const char *end, rb_encoding *enc,
case 'C': /* \C-X, \C-\M-X */
case 'M': /* \M-X, \M-\C-X, \M-\cX */
p = p-2;
- if (enc == rb_usascii_encoding()) {
- const char *pbeg = p;
+ if (rb_is_usascii_enc(enc)) {
+ const char *pbeg = p;
int byte = read_escaped_byte(&p, end, err);
if (byte == -1) return -1;
c = byte;
- rb_str_buf_cat(buf, pbeg, p-pbeg);
- }
- else {
- if (unescape_escaped_nonascii(&p, end, enc, buf, encp, err) != 0)
- return -1;
- }
+ rb_str_buf_cat(buf, pbeg, p-pbeg);
+ }
+ else {
+ if (unescape_escaped_nonascii(&p, end, enc, buf, encp, err) != 0)
+ return -1;
+ }
break;
case 'u':
@@ -2679,18 +2923,166 @@ escape_asis:
}
break;
+ case '#':
+ if (extended_mode && !in_char_class) {
+ /* consume and ignore comment in extended regexp */
+ while ((p < end) && ((c = *p++) != '\n')) {
+ if ((c & 0x80) && !*encp && enc == rb_utf8_encoding()) {
+ *encp = enc;
+ }
+ }
+ break;
+ }
+ rb_str_buf_cat(buf, (char *)&c, 1);
+ break;
+ case '[':
+ in_char_class++;
+ rb_str_buf_cat(buf, (char *)&c, 1);
+ break;
+ case ']':
+ if (in_char_class) {
+ in_char_class--;
+ }
+ rb_str_buf_cat(buf, (char *)&c, 1);
+ break;
+ case ')':
+ rb_str_buf_cat(buf, (char *)&c, 1);
+ if (!in_char_class && recurse) {
+ if (--parens == 0) {
+ *pp = p;
+ return 0;
+ }
+ }
+ break;
+ case '(':
+ if (!in_char_class && p + 1 < end && *p == '?') {
+ if (*(p+1) == '#') {
+ /* (?# is comment inside any regexp, and content inside should be ignored */
+ const char *orig_p = p;
+ int cont = 1;
+
+ while (cont && (p < end)) {
+ switch (c = *p++) {
+ default:
+ if (!(c & 0x80)) break;
+ if (!*encp && enc == rb_utf8_encoding()) {
+ *encp = enc;
+ }
+ --p;
+ /* fallthrough */
+ case '\\':
+ chlen = rb_enc_precise_mbclen(p, end, enc);
+ if (!MBCLEN_CHARFOUND_P(chlen)) {
+ goto invalid_multibyte;
+ }
+ p += MBCLEN_CHARFOUND_LEN(chlen);
+ break;
+ case ')':
+ cont = 0;
+ break;
+ }
+ }
+
+ if (cont) {
+ /* unterminated (?#, rewind so it is syntax error */
+ p = orig_p;
+ c = '(';
+ rb_str_buf_cat(buf, (char *)&c, 1);
+ }
+ break;
+ }
+ else {
+ /* potential change of extended option */
+ int invert = 0;
+ int local_extend = 0;
+ const char *s;
+
+ if (recurse) {
+ parens++;
+ }
+
+ for(s = p+1; s < end; s++) {
+ switch(*s) {
+ case 'x':
+ local_extend = invert ? -1 : 1;
+ break;
+ case '-':
+ invert = 1;
+ break;
+ case ':':
+ case ')':
+ if (local_extend == 0 ||
+ (local_extend == -1 && !extended_mode) ||
+ (local_extend == 1 && extended_mode)) {
+ /* no changes to extended flag */
+ goto fallthrough;
+ }
+
+ if (*s == ':') {
+ /* change extended flag until ')' */
+ int local_options = options;
+ if (local_extend == 1) {
+ local_options |= ONIG_OPTION_EXTEND;
+ }
+ else {
+ local_options &= ~ONIG_OPTION_EXTEND;
+ }
+
+ rb_str_buf_cat(buf, (char *)&c, 1);
+ int ret = unescape_nonascii0(&p, end, enc, buf, encp,
+ has_property, err,
+ local_options, 1);
+ if (ret < 0) return ret;
+ goto begin_scan;
+ }
+ else {
+ /* change extended flag for rest of expression */
+ extended_mode = local_extend == 1;
+ goto fallthrough;
+ }
+ case 'i':
+ case 'm':
+ case 'a':
+ case 'd':
+ case 'u':
+ /* other option flags, ignored during scanning */
+ break;
+ default:
+ /* other character, no extended flag change*/
+ goto fallthrough;
+ }
+ }
+ }
+ }
+ else if (!in_char_class && recurse) {
+ parens++;
+ }
+ /* FALLTHROUGH */
default:
+fallthrough:
rb_str_buf_cat(buf, (char *)&c, 1);
break;
}
}
+ if (recurse) {
+ *pp = p;
+ }
return 0;
}
+static int
+unescape_nonascii(const char *p, const char *end, rb_encoding *enc,
+ VALUE buf, rb_encoding **encp, int *has_property,
+ onig_errmsg_buffer err, int options)
+{
+ return unescape_nonascii0(&p, end, enc, buf, encp, has_property,
+ err, options, 0);
+}
+
static VALUE
rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
- rb_encoding **fixed_enc, onig_errmsg_buffer err)
+ rb_encoding **fixed_enc, onig_errmsg_buffer err, int options)
{
VALUE buf;
int has_property = 0;
@@ -2704,7 +3096,7 @@ rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
rb_enc_associate(buf, enc);
}
- if (unescape_nonascii(p, end, enc, buf, fixed_enc, &has_property, err) != 0)
+ if (unescape_nonascii(p, end, enc, buf, fixed_enc, &has_property, err, options) != 0)
return Qnil;
if (has_property && !*fixed_enc) {
@@ -2732,11 +3124,11 @@ rb_reg_check_preprocess(VALUE str)
end = p + RSTRING_LEN(str);
enc = rb_enc_get(str);
- buf = rb_reg_preprocess(p, end, enc, &fixed_enc, err);
+ buf = rb_reg_preprocess(p, end, enc, &fixed_enc, err, 0);
RB_GC_GUARD(str);
- if (buf == Qnil) {
- return rb_reg_error_desc(str, 0, err);
+ if (NIL_P(buf)) {
+ return rb_reg_error_desc(str, 0, err);
}
return Qnil;
}
@@ -2761,22 +3153,22 @@ rb_reg_preprocess_dregexp(VALUE ary, int options)
char *p, *end;
rb_encoding *src_enc;
- src_enc = rb_enc_get(str);
- if (options & ARG_ENCODING_NONE &&
- src_enc != ascii8bit) {
- if (str_coderange(str) != ENC_CODERANGE_7BIT)
- rb_raise(rb_eRegexpError, "/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
- else
- src_enc = ascii8bit;
- }
+ src_enc = rb_enc_get(str);
+ if (options & ARG_ENCODING_NONE &&
+ src_enc != ascii8bit) {
+ if (str_coderange(str) != ENC_CODERANGE_7BIT)
+ rb_raise(rb_eRegexpError, "/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
+ else
+ src_enc = ascii8bit;
+ }
StringValue(str);
p = RSTRING_PTR(str);
end = p + RSTRING_LEN(str);
- buf = rb_reg_preprocess(p, end, src_enc, &fixed_enc, err);
+ buf = rb_reg_preprocess(p, end, src_enc, &fixed_enc, err, options);
- if (buf == Qnil)
+ if (NIL_P(buf))
rb_raise(rb_eArgError, "%s", err);
if (fixed_enc != 0) {
@@ -2801,8 +3193,8 @@ rb_reg_preprocess_dregexp(VALUE ary, int options)
static int
rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc,
- int options, onig_errmsg_buffer err,
- const char *sourcefile, int sourceline)
+ int options, onig_errmsg_buffer err,
+ const char *sourcefile, int sourceline)
{
struct RRegexp *re = RREGEXP(obj);
VALUE unescaped;
@@ -2811,30 +3203,30 @@ rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc,
rb_check_frozen(obj);
if (FL_TEST(obj, REG_LITERAL))
- rb_raise(rb_eSecurityError, "can't modify literal regexp");
+ rb_raise(rb_eSecurityError, "can't modify literal regexp");
if (re->ptr)
rb_raise(rb_eTypeError, "already initialized regexp");
re->ptr = 0;
if (rb_enc_dummy_p(enc)) {
- errcpy(err, "can't make regexp with dummy encoding");
- return -1;
+ errcpy(err, "can't make regexp with dummy encoding");
+ return -1;
}
- unescaped = rb_reg_preprocess(s, s+len, enc, &fixed_enc, err);
- if (unescaped == Qnil)
+ unescaped = rb_reg_preprocess(s, s+len, enc, &fixed_enc, err, options);
+ if (NIL_P(unescaped))
return -1;
if (fixed_enc) {
- if ((fixed_enc != enc && (options & ARG_ENCODING_FIXED)) ||
+ if ((fixed_enc != enc && (options & ARG_ENCODING_FIXED)) ||
(fixed_enc != a_enc && (options & ARG_ENCODING_NONE))) {
- errcpy(err, "incompatible character encoding");
- return -1;
- }
+ errcpy(err, "incompatible character encoding");
+ return -1;
+ }
if (fixed_enc != a_enc) {
- options |= ARG_ENCODING_FIXED;
- enc = fixed_enc;
- }
+ options |= ARG_ENCODING_FIXED;
+ enc = fixed_enc;
+ }
}
else if (!(options & ARG_ENCODING_FIXED)) {
enc = rb_usascii_encoding();
@@ -2842,15 +3234,15 @@ rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc,
rb_enc_associate((VALUE)re, enc);
if ((options & ARG_ENCODING_FIXED) || fixed_enc) {
- re->basic.flags |= KCODE_FIXED;
+ re->basic.flags |= KCODE_FIXED;
}
if (options & ARG_ENCODING_NONE) {
re->basic.flags |= REG_ENCODING_NONE;
}
re->ptr = make_regexp(RSTRING_PTR(unescaped), RSTRING_LEN(unescaped), enc,
- options & ARG_REG_OPTION_MASK, err,
- sourcefile, sourceline);
+ options & ARG_REG_OPTION_MASK, err,
+ sourcefile, sourceline);
if (!re->ptr) return -1;
RB_GC_GUARD(unescaped);
return 0;
@@ -2861,14 +3253,14 @@ reg_set_source(VALUE reg, VALUE str, rb_encoding *enc)
{
rb_encoding *regenc = rb_enc_get(reg);
if (regenc != enc) {
- str = rb_enc_associate(rb_str_dup(str), enc = regenc);
+ str = rb_enc_associate(rb_str_dup(str), enc = regenc);
}
RB_OBJ_WRITE(reg, &RREGEXP(reg)->src, rb_fstring(str));
}
static int
rb_reg_initialize_str(VALUE obj, VALUE str, int options, onig_errmsg_buffer err,
- const char *sourcefile, int sourceline)
+ const char *sourcefile, int sourceline)
{
int ret;
rb_encoding *str_enc = rb_enc_get(str), *enc = str_enc;
@@ -2883,7 +3275,7 @@ rb_reg_initialize_str(VALUE obj, VALUE str, int options, onig_errmsg_buffer err,
}
}
ret = rb_reg_initialize(obj, RSTRING_PTR(str), RSTRING_LEN(str), enc,
- options, err, sourcefile, sourceline);
+ options, err, sourcefile, sourceline);
if (ret == 0) reg_set_source(obj, str, str_enc);
return ret;
}
@@ -2918,7 +3310,7 @@ rb_reg_init_str(VALUE re, VALUE s, int options)
onig_errmsg_buffer err = "";
if (rb_reg_initialize_str(re, s, options, err, NULL, 0) != 0) {
- rb_reg_raise_str(s, options, err);
+ rb_reg_raise_str(s, options, err);
}
return re;
@@ -2930,8 +3322,8 @@ rb_reg_init_str_enc(VALUE re, VALUE s, rb_encoding *enc, int options)
onig_errmsg_buffer err = "";
if (rb_reg_initialize(re, RSTRING_PTR(s), RSTRING_LEN(s),
- enc, options, err, NULL, 0) != 0) {
- rb_reg_raise_str(s, options, err);
+ enc, options, err, NULL, 0) != 0) {
+ rb_reg_raise_str(s, options, err);
}
reg_set_source(re, s, enc);
@@ -2953,7 +3345,7 @@ rb_enc_reg_new(const char *s, long len, rb_encoding *enc, int options)
onig_errmsg_buffer err = "";
if (rb_reg_initialize(re, s, len, enc, options, err, NULL, 0) != 0) {
- rb_enc_reg_raise(s, len, enc, options, err);
+ rb_enc_reg_raise(s, len, enc, options, err);
}
RB_OBJ_WRITE(re, &RREGEXP(re)->src, rb_fstring(rb_enc_str_new(s, len, enc)));
@@ -2974,8 +3366,8 @@ rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
if (!str) str = rb_str_new(0,0);
if (rb_reg_initialize_str(re, str, options, err, sourcefile, sourceline) != 0) {
- rb_set_errinfo(rb_reg_error_desc(str, options, err));
- return Qnil;
+ rb_set_errinfo(rb_reg_error_desc(str, options, err));
+ return Qnil;
}
FL_SET(re, REG_LITERAL);
rb_obj_freeze(re);
@@ -2988,21 +3380,22 @@ VALUE
rb_reg_regcomp(VALUE str)
{
if (reg_cache && RREGEXP_SRC_LEN(reg_cache) == RSTRING_LEN(str)
- && ENCODING_GET(reg_cache) == ENCODING_GET(str)
- && memcmp(RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
- return reg_cache;
+ && ENCODING_GET(reg_cache) == ENCODING_GET(str)
+ && memcmp(RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
+ return reg_cache;
return reg_cache = rb_reg_new_str(str, 0);
}
static st_index_t reg_hash(VALUE re);
/*
- * call-seq:
- * rxp.hash -> integer
+ * call-seq:
+ * hash -> integer
+ *
+ * Returns the integer hash value for +self+.
*
- * Produce a hash based on the text and options of this regular expression.
+ * Related: Object#hash.
*
- * See also Object#hash.
*/
VALUE
@@ -3026,17 +3419,18 @@ reg_hash(VALUE re)
/*
* call-seq:
- * rxp == other_rxp -> true or false
- * rxp.eql?(other_rxp) -> true or false
+ * regexp == object -> true or false
*
- * Equality---Two regexps are equal if their patterns are identical, they have
- * the same character set code, and their <code>casefold?</code> values are the
- * same.
+ * Returns +true+ if +object+ is another \Regexp whose pattern,
+ * flags, and encoding are the same as +self+, +false+ otherwise:
+ *
+ * /foo/ == Regexp.new('foo') # => true
+ * /foo/ == /foo/i # => false
+ * /foo/ == Regexp.new('food') # => false
+ * /foo/ == Regexp.new("abc".force_encoding("euc-jp")) # => false
+ *
+ * Regexp#eql? is an alias for Regexp#==.
*
- * /abc/ == /abc/x #=> false
- * /abc/ == /abc/i #=> false
- * /abc/ == /abc/u #=> false
- * /abc/u == /abc/n #=> false
*/
VALUE
@@ -3049,20 +3443,18 @@ rb_reg_equal(VALUE re1, VALUE re2)
if (RREGEXP_PTR(re1)->options != RREGEXP_PTR(re2)->options) return Qfalse;
if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return Qfalse;
if (ENCODING_GET(re1) != ENCODING_GET(re2)) return Qfalse;
- if (memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0) {
- return Qtrue;
- }
- return Qfalse;
+ return RBOOL(memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0);
}
/*
- * call-seq:
- * mtch.hash -> integer
+ * call-seq:
+ * hash -> integer
+ *
+ * Returns the integer hash value for +self+,
+ * based on the target string, regexp, match, and captures.
*
- * Produce a hash based on the target string, regexp and matched
- * positions of this matchdata.
+ * See also Object#hash.
*
- * See also Object#hash.
*/
static VALUE
@@ -3083,12 +3475,15 @@ match_hash(VALUE match)
}
/*
- * call-seq:
- * mtch == mtch2 -> true or false
- * mtch.eql?(mtch2) -> true or false
+ * call-seq:
+ * matchdata == object -> true or false
+ *
+ * Returns +true+ if +object+ is another \MatchData object
+ * whose target string, regexp, match, and captures
+ * are the same as +self+, +false+ otherwise.
+ *
+ * MatchData#eql? is an alias for MatchData#==.
*
- * Equality---Two matchdata are equal if their target strings,
- * patterns, and matched positions are identical.
*/
static VALUE
@@ -3113,7 +3508,7 @@ static VALUE
reg_operand(VALUE s, int check)
{
if (SYMBOL_P(s)) {
- return rb_sym2str(s);
+ return rb_sym2str(s);
}
else if (RB_TYPE_P(s, T_STRING)) {
return s;
@@ -3124,80 +3519,88 @@ 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;
if (NIL_P(str)) {
- rb_backref_set(Qnil);
- return -1;
+ rb_backref_set(Qnil);
+ return -1;
}
*strp = str = reg_operand(str, TRUE);
if (pos != 0) {
- if (pos < 0) {
- VALUE l = rb_str_length(str);
- pos += NUM2INT(l);
- if (pos < 0) {
- return pos;
- }
- }
- pos = rb_str_offset(str, pos);
+ if (pos < 0) {
+ VALUE l = rb_str_length(str);
+ pos += NUM2INT(l);
+ if (pos < 0) {
+ return 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);
}
/*
* call-seq:
- * rxp =~ str -> integer or nil
+ * regexp =~ string -> integer or nil
+ *
+ * Returns the integer index (in characters) of the first match
+ * for +self+ and +string+, or +nil+ if none;
+ * also sets the
+ * {rdoc-ref:Regexp Global Variables}[rdoc-ref:Regexp@Regexp+Global+Variables]:
*
- * Match---Matches <i>rxp</i> against <i>str</i>.
+ * /at/ =~ 'input data' # => 7
+ * $~ # => #<MatchData "at">
+ * /ax/ =~ 'input data' # => nil
+ * $~ # => nil
*
- * /at/ =~ "input data" #=> 7
- * /ax/ =~ "input data" #=> nil
+ * Assigns named captures to local variables of the same names
+ * if and only if +self+:
*
- * If <code>=~</code> is used with a regexp literal with named captures,
- * captured strings (or nil) is assigned to local variables named by
- * the capture names.
+ * - Is a regexp literal;
+ * see {Regexp Literals}[rdoc-ref:literals.rdoc@Regexp+Literals].
+ * - Does not contain interpolations;
+ * see {Regexp Interpolation}[rdoc-ref:Regexp@Regexp+Interpolation].
+ * - Is at the left of the expression.
*
- * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ " x = y "
- * p lhs #=> "x"
- * p rhs #=> "y"
+ * Example:
*
- * If it is not matched, nil is assigned for the variables.
+ * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ ' x = y '
+ * p lhs # => "x"
+ * p rhs # => "y"
*
- * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ " x = "
- * p lhs #=> nil
- * p rhs #=> nil
+ * Assigns +nil+ if not matched:
*
- * This assignment is implemented in the Ruby parser.
- * The parser detects 'regexp-literal =~ expression' for the assignment.
- * The regexp must be a literal without interpolation and placed at left hand side.
+ * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ ' x = '
+ * p lhs # => nil
+ * p rhs # => nil
*
- * The assignment does not occur if the regexp is not a literal.
+ * Does not make local variable assignments if +self+ is not a regexp literal:
*
- * re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
- * re =~ " x = y "
- * p lhs # undefined local variable
- * p rhs # undefined local variable
+ * r = /(?<foo>\w+)\s*=\s*(?<foo>\w+)/
+ * r =~ ' x = y '
+ * p foo # Undefined local variable
+ * p bar # Undefined local variable
*
- * A regexp interpolation, <code>#{}</code>, also disables
- * the assignment.
+ * The assignment does not occur if the regexp is not at the left:
*
- * rhs_pat = /(?<rhs>\w+)/
- * /(?<lhs>\w+)\s*=\s*#{rhs_pat}/ =~ "x = y"
- * p lhs # undefined local variable
+ * ' x = y ' =~ /(?<foo>\w+)\s*=\s*(?<foo>\w+)/
+ * p foo, foo # Undefined local variables
*
- * The assignment does not occur if the regexp is placed at the right hand side.
+ * A regexp interpolation, <tt>#{}</tt>, also disables
+ * the assignment:
*
- * " x = y " =~ /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
- * p lhs, rhs # undefined local variable
+ * r = /(?<foo>\w+)/
+ * /(?<foo>\w+)\s*=\s*#{r}/ =~ 'x = y'
+ * p foo # Undefined local variable
*
*/
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);
@@ -3205,23 +3608,22 @@ rb_reg_match(VALUE re, VALUE str)
/*
* call-seq:
- * rxp === str -> true or false
+ * regexp === string -> true or false
*
- * Case Equality---Used in case statements.
+ * Returns +true+ if +self+ finds a match in +string+:
*
- * a = "HELLO"
- * case a
- * when /\A[a-z]*\z/; print "Lower case\n"
- * when /\A[A-Z]*\z/; print "Upper case\n"
- * else; print "Mixed case\n"
- * end
- * #=> "Upper case"
+ * /^[a-z]*$/ === 'HELLO' # => false
+ * /^[A-Z]*$/ === 'HELLO' # => true
*
- * Following a regular expression literal with the #=== operator allows you to
- * compare against a String.
+ * This method is called in case statements:
+ *
+ * s = 'HELLO'
+ * case s
+ * when /\A[a-z]*\z/; print "Lower case\n"
+ * when /\A[A-Z]*\z/; print "Upper case\n"
+ * else print "Mixed case\n"
+ * end # => "Upper case"
*
- * /^[a-z]*$/ === "HELLO" #=> false
- * /^[A-Z]*$/ === "HELLO" #=> true
*/
static VALUE
@@ -3231,26 +3633,23 @@ rb_reg_eqq(VALUE re, VALUE str)
str = reg_operand(str, FALSE);
if (NIL_P(str)) {
- rb_backref_set(Qnil);
- return Qfalse;
+ rb_backref_set(Qnil);
+ return Qfalse;
}
start = rb_reg_search(re, str, 0, 0);
- if (start < 0) {
- return Qfalse;
- }
- return Qtrue;
+ return RBOOL(start >= 0);
}
/*
* call-seq:
- * ~ rxp -> integer or nil
+ * ~ rxp -> integer or nil
*
- * Match---Matches <i>rxp</i> against the contents of <code>$_</code>.
- * Equivalent to <code><i>rxp</i> =~ $_</code>.
+ * Equivalent to <tt><i>rxp</i> =~ $_</tt>:
+ *
+ * $_ = "input data"
+ * ~ /at/ # => 7
*
- * $_ = "input data"
- * ~ /at/ #=> 7
*/
VALUE
@@ -3260,13 +3659,13 @@ rb_reg_match2(VALUE re)
VALUE line = rb_lastline_get();
if (!RB_TYPE_P(line, T_STRING)) {
- rb_backref_set(Qnil);
- return Qnil;
+ rb_backref_set(Qnil);
+ return Qnil;
}
start = rb_reg_search(re, line, 0, 0);
if (start < 0) {
- return Qnil;
+ return Qnil;
}
start = rb_str_sublen(line, start);
return LONG2FIX(start);
@@ -3275,76 +3674,84 @@ rb_reg_match2(VALUE re)
/*
* call-seq:
- * rxp.match(str, pos=0) -> matchdata or nil
- * rxp.match(str, pos=0) {|match| block } -> obj
+ * match(string, offset = 0) -> matchdata or nil
+ * match(string, offset = 0) {|matchdata| ... } -> object
+ *
+ * With no block given, returns the MatchData object
+ * that describes the match, if any, or +nil+ if none;
+ * the search begins at the given character +offset+ in +string+:
+ *
+ * /abra/.match('abracadabra') # => #<MatchData "abra">
+ * /abra/.match('abracadabra', 4) # => #<MatchData "abra">
+ * /abra/.match('abracadabra', 8) # => nil
+ * /abra/.match('abracadabra', 800) # => nil
*
- * Returns a MatchData object describing the match, or
- * <code>nil</code> if there was no match. This is equivalent to
- * retrieving the value of the special variable <code>$~</code>
- * following a normal match. If the second parameter is present, it
- * specifies the position in the string to begin the search.
+ * string = "\u{5d0 5d1 5e8 5d0}cadabra"
+ * /abra/.match(string, 7) #=> #<MatchData "abra">
+ * /abra/.match(string, 8) #=> nil
+ * /abra/.match(string.b, 8) #=> #<MatchData "abra">
*
- * /(.)(.)(.)/.match("abc")[2] #=> "b"
- * /(.)(.)/.match("abc", 1)[2] #=> "c"
+ * With a block given, calls the block if and only if a match is found;
+ * returns the block's value:
*
- * If a block is given, invoke the block with MatchData if match succeed, so
- * that you can write
+ * /abra/.match('abracadabra') {|matchdata| p matchdata }
+ * # => #<MatchData "abra">
+ * /abra/.match('abracadabra', 4) {|matchdata| p matchdata }
+ * # => #<MatchData "abra">
+ * /abra/.match('abracadabra', 8) {|matchdata| p matchdata }
+ * # => nil
+ * /abra/.match('abracadabra', 8) {|marchdata| fail 'Cannot happen' }
+ * # => nil
*
- * /M(.*)/.match("Matz") do |m|
- * puts m[0]
- * puts m[1]
- * end
+ * Output (from the first two blocks above):
*
- * instead of
+ * #<MatchData "abra">
+ * #<MatchData "abra">
*
- * if m = /M(.*)/.match("Matz")
- * puts m[0]
- * puts m[1]
- * end
+ * /(.)(.)(.)/.match("abc")[2] # => "b"
+ * /(.)(.)/.match("abc", 1)[2] # => "c"
*
- * The return value is a value from block execution in this case.
*/
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) {
- pos = NUM2LONG(initpos);
+ pos = NUM2LONG(initpos);
}
else {
- pos = 0;
+ 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;
+ 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);
+ return rb_yield(result);
}
return result;
}
/*
* call-seq:
- * rxp.match?(str) -> true or false
- * rxp.match?(str,pos) -> true or false
+ * match?(string) -> true or false
+ * match?(string, offset = 0) -> true or false
*
- * Returns a <code>true</code> or <code>false</code> indicates whether the
+ * Returns <code>true</code> or <code>false</code> to indicate whether the
* regexp is matched or not without updating $~ and other related variables.
* If the second parameter is present, it specifies the position in the string
* to begin the search.
*
- * /R.../.match?("Ruby") #=> true
- * /R.../.match?("Ruby", 1) #=> false
- * /P.../.match?("Ruby") #=> false
- * $& #=> nil
+ * /R.../.match?("Ruby") # => true
+ * /R.../.match?("Ruby", 1) # => false
+ * /P.../.match?("Ruby") # => false
+ * $& # => nil
*/
static VALUE
@@ -3366,16 +3773,16 @@ rb_reg_match_p(VALUE re, VALUE str, long pos)
if (NIL_P(str)) return Qfalse;
str = SYMBOL_P(str) ? rb_sym2str(str) : StringValue(str);
if (pos) {
- if (pos < 0) {
- pos += NUM2LONG(rb_str_length(str));
- if (pos < 0) return Qfalse;
- }
- if (pos > 0) {
- long len = 1;
- const char *beg = rb_str_subpos(str, pos, &len);
- if (!beg) return Qfalse;
- pos = beg - RSTRING_PTR(str);
- }
+ if (pos < 0) {
+ pos += NUM2LONG(rb_str_length(str));
+ if (pos < 0) return Qfalse;
+ }
+ if (pos > 0) {
+ long len = 1;
+ const char *beg = rb_str_subpos(str, pos, &len);
+ if (!beg) return Qfalse;
+ pos = beg - RSTRING_PTR(str);
+ }
}
reg = rb_reg_prepare_re0(re, str, err);
tmpreg = reg != RREGEXP_PTR(re);
@@ -3383,25 +3790,25 @@ rb_reg_match_p(VALUE re, VALUE str, long pos)
start = ((UChar*)RSTRING_PTR(str));
end = start + RSTRING_LEN(str);
result = onig_search(reg, start, end, start + pos, end,
- NULL, ONIG_OPTION_NONE);
+ NULL, ONIG_OPTION_NONE);
if (!tmpreg) RREGEXP(re)->usecnt--;
if (tmpreg) {
- if (RREGEXP(re)->usecnt) {
- onig_free(reg);
- }
- else {
- onig_free(RREGEXP_PTR(re));
- RREGEXP_PTR(re) = reg;
- }
+ if (RREGEXP(re)->usecnt) {
+ onig_free(reg);
+ }
+ else {
+ onig_free(RREGEXP_PTR(re));
+ RREGEXP_PTR(re) = reg;
+ }
}
if (result < 0) {
- if (result == ONIG_MISMATCH) {
- return Qfalse;
- }
- else {
- onig_error_code_to_str((UChar*)err, (int)result);
- rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
- }
+ if (result == ONIG_MISMATCH) {
+ return Qfalse;
+ }
+ else {
+ onig_error_code_to_str((UChar*)err, (int)result);
+ rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
+ }
}
return Qtrue;
}
@@ -3412,67 +3819,176 @@ rb_reg_match_p(VALUE re, VALUE str, long pos)
* Alias for Regexp.new
*/
+static int
+str_to_option(VALUE str)
+{
+ int flag = 0;
+ const char *ptr;
+ long len;
+ str = rb_check_string_type(str);
+ if (NIL_P(str)) return -1;
+ RSTRING_GETMEM(str, ptr, len);
+ for (long i = 0; i < len; ++i) {
+ int f = char_to_option(ptr[i]);
+ if (!f) {
+ rb_raise(rb_eArgError, "unknown regexp option: %"PRIsVALUE, str);
+ }
+ flag |= f;
+ }
+ return flag;
+}
+
+static void
+set_timeout(rb_hrtime_t *hrt, VALUE timeout)
+{
+ double timeout_d = NIL_P(timeout) ? 0.0 : NUM2DBL(timeout);
+ if (!NIL_P(timeout) && timeout_d <= 0) {
+ rb_raise(rb_eArgError, "invalid timeout: %"PRIsVALUE, timeout);
+ }
+ double2hrtime(hrt, timeout_d);
+}
+
+struct reg_init_args {
+ VALUE str;
+ VALUE timeout;
+ rb_encoding *enc;
+ int flags;
+};
+
+static VALUE reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args);
+static VALUE reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags);
+void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...);
+
/*
* call-seq:
- * Regexp.new(string, [options]) -> regexp
- * Regexp.new(regexp) -> regexp
- * Regexp.compile(string, [options]) -> regexp
- * Regexp.compile(regexp) -> regexp
- *
- * Constructs a new regular expression from +pattern+, which can be either a
- * String or a Regexp (in which case that regexp's options are propagated),
- * and new options may not be specified (a change as of Ruby 1.8).
- *
- * If +options+ is an Integer, it should be one or more of the constants
- * Regexp::EXTENDED, Regexp::IGNORECASE, and Regexp::MULTILINE,
- * <em>or</em>-ed together. Otherwise, if +options+ is not
- * +nil+ or +false+, the regexp will be case insensitive.
- *
- * r1 = Regexp.new('^a-z+:\\s+\w+') #=> /^a-z+:\s+\w+/
- * r2 = Regexp.new('cat', true) #=> /cat/i
- * r3 = Regexp.new(r2) #=> /cat/i
- * r4 = Regexp.new('dog', Regexp::EXTENDED | Regexp::IGNORECASE) #=> /dog/ix
+ * Regexp.new(string, options = 0, timeout: nil) -> regexp
+ * Regexp.new(regexp, timeout: nil) -> regexp
+ *
+ * With argument +string+ given, returns a new regexp with the given string
+ * and options:
+ *
+ * r = Regexp.new('foo') # => /foo/
+ * r.source # => "foo"
+ * r.options # => 0
+ *
+ * Optional argument +options+ is one of the following:
+ *
+ * - A String of options:
+ *
+ * Regexp.new('foo', 'i') # => /foo/i
+ * Regexp.new('foo', 'im') # => /foo/im
+ *
+ * - The logical OR of one or more of the constants
+ * Regexp::EXTENDED, Regexp::IGNORECASE, Regexp::MULTILINE, and
+ * Regexp::NOENCODING:
+ *
+ * Regexp.new('foo', Regexp::IGNORECASE) # => /foo/i
+ * Regexp.new('foo', Regexp::EXTENDED) # => /foo/x
+ * Regexp.new('foo', Regexp::MULTILINE) # => /foo/m
+ * Regexp.new('foo', Regexp::NOENCODING) # => /foo/n
+ * flags = Regexp::IGNORECASE | Regexp::EXTENDED | Regexp::MULTILINE
+ * Regexp.new('foo', flags) # => /foo/mix
+ *
+ * - +nil+ or +false+, which is ignored.
+ *
+ * If optional keyword argument +timeout+ is given,
+ * its float value overrides the timeout interval for the class,
+ * Regexp.timeout.
+ * If +nil+ is passed as +timeout, it uses the timeout interval
+ * for the class, Regexp.timeout.
+ *
+ * With argument +regexp+ given, returns a new regexp. The source,
+ * options, timeout are the same as +regexp+. +options+ and +n_flag+
+ * arguments are ineffective. The timeout can be overridden by
+ * +timeout+ keyword.
+ *
+ * options = Regexp::MULTILINE
+ * r = Regexp.new('foo', options, timeout: 1.1) # => /foo/m
+ * r2 = Regexp.new(r) # => /foo/m
+ * r2.timeout # => 1.1
+ * r3 = Regexp.new(r, timeout: 3.14) # => /foo/m
+ * r3.timeout # => 3.14
+ *
+ * Regexp.compile is an alias for Regexp.new.
+ *
*/
static VALUE
rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
{
+ struct reg_init_args args;
+
+ reg_extract_args(argc, argv, &args);
+ reg_init_args(self, args.str, args.enc, args.flags);
+
+ set_timeout(&RREGEXP_PTR(self)->timelimit, args.timeout);
+
+ return self;
+}
+
+static VALUE
+reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args)
+{
int flags = 0;
- VALUE str;
rb_encoding *enc = 0;
+ VALUE str, src, opts = Qundef, n_flag = Qundef, kwargs;
+ VALUE re = Qnil;
+
+ argc = rb_scan_args(argc, argv, "12:", &src, &opts, &n_flag, &kwargs);
+
+ args->timeout = Qnil;
+ if (!NIL_P(kwargs)) {
+ static ID keywords[1];
+ if (!keywords[0]) {
+ keywords[0] = rb_intern_const("timeout");
+ }
+ rb_get_kwargs(kwargs, keywords, 0, 1, &args->timeout);
+ }
- rb_check_arity(argc, 1, 3);
- if (RB_TYPE_P(argv[0], T_REGEXP)) {
- VALUE re = argv[0];
+ if (argc == 3) {
+ rb_warn_deprecated_to_remove("3.3", "3rd argument to Regexp.new", "2nd argument");
+ }
+
+ if (RB_TYPE_P(src, T_REGEXP)) {
+ re = src;
- if (argc > 1) {
- rb_warn("flags ignored");
- }
- rb_reg_check(re);
- flags = rb_reg_options(re);
- str = RREGEXP_SRC(re);
+ if (!NIL_P(opts)) {
+ rb_warn("flags ignored");
+ }
+ rb_reg_check(re);
+ flags = rb_reg_options(re);
+ str = RREGEXP_SRC(re);
}
else {
- if (argc >= 2) {
- if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]);
- else if (RTEST(argv[1])) flags = ONIG_OPTION_IGNORECASE;
- }
- if (argc == 3 && !NIL_P(argv[2])) {
- char *kcode = StringValuePtr(argv[2]);
- if (kcode[0] == 'n' || kcode[0] == 'N') {
- enc = rb_ascii8bit_encoding();
- flags |= ARG_ENCODING_NONE;
- }
- else {
- rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "encoding option is ignored - %s", kcode);
- }
- }
- str = StringValue(argv[0]);
+ if (!UNDEF_P(opts)) {
+ int f;
+ if (FIXNUM_P(opts)) flags = FIX2INT(opts);
+ else if ((f = str_to_option(opts)) >= 0) flags = f;
+ else if (!NIL_P(opts) && rb_bool_expected(opts, "ignorecase", FALSE))
+ flags = ONIG_OPTION_IGNORECASE;
+ }
+ if (!NIL_OR_UNDEF_P(n_flag)) {
+ char *kcode = StringValuePtr(n_flag);
+ if (kcode[0] == 'n' || kcode[0] == 'N') {
+ enc = rb_ascii8bit_encoding();
+ flags |= ARG_ENCODING_NONE;
+ }
+ }
+ str = StringValue(src);
}
+ args->str = str;
+ args->enc = enc;
+ args->flags = flags;
+ return re;
+}
+
+static VALUE
+reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags)
+{
if (enc && rb_enc_get(str) != enc)
- rb_reg_init_str_enc(self, str, enc, flags);
+ rb_reg_init_str_enc(self, str, enc, flags);
else
- rb_reg_init_str(self, str, flags);
+ rb_reg_init_str(self, str, flags);
return self;
}
@@ -3489,19 +4005,19 @@ rb_reg_quote(VALUE str)
send = s + RSTRING_LEN(str);
while (s < send) {
c = rb_enc_ascget(s, send, &clen, enc);
- if (c == -1) {
+ if (c == -1) {
s += mbclen(s, send, enc);
- continue;
- }
- switch (c) {
- case '[': case ']': case '{': case '}':
- case '(': case ')': case '|': case '-':
- case '*': case '.': case '\\':
- case '?': case '+': case '^': case '$':
- case ' ': case '#':
- case '\t': case '\f': case '\v': case '\n': case '\r':
- goto meta_found;
- }
+ continue;
+ }
+ switch (c) {
+ case '[': case ']': case '{': case '}':
+ case '(': case ')': case '|': case '-':
+ case '*': case '.': case '\\':
+ case '?': case '+': case '^': case '$':
+ case ' ': case '#':
+ case '\t': case '\f': case '\v': case '\n': case '\r':
+ goto meta_found;
+ }
s += clen;
}
tmp = rb_str_new3(str);
@@ -3526,47 +4042,47 @@ rb_reg_quote(VALUE str)
while (s < send) {
c = rb_enc_ascget(s, send, &clen, enc);
- if (c == -1) {
- int n = mbclen(s, send, enc);
+ if (c == -1) {
+ int n = mbclen(s, send, enc);
- while (n--)
- *t++ = *s++;
- continue;
- }
+ while (n--)
+ *t++ = *s++;
+ continue;
+ }
s += clen;
- switch (c) {
- case '[': case ']': case '{': case '}':
- case '(': case ')': case '|': case '-':
- case '*': case '.': case '\\':
- case '?': case '+': case '^': case '$':
- case '#':
+ switch (c) {
+ case '[': case ']': case '{': case '}':
+ case '(': case ')': case '|': case '-':
+ case '*': case '.': case '\\':
+ case '?': case '+': case '^': case '$':
+ case '#':
t += rb_enc_mbcput('\\', t, enc);
- break;
- case ' ':
+ break;
+ case ' ':
t += rb_enc_mbcput('\\', t, enc);
t += rb_enc_mbcput(' ', t, enc);
- continue;
- case '\t':
+ continue;
+ case '\t':
t += rb_enc_mbcput('\\', t, enc);
t += rb_enc_mbcput('t', t, enc);
- continue;
- case '\n':
+ continue;
+ case '\n':
t += rb_enc_mbcput('\\', t, enc);
t += rb_enc_mbcput('n', t, enc);
- continue;
- case '\r':
+ continue;
+ case '\r':
t += rb_enc_mbcput('\\', t, enc);
t += rb_enc_mbcput('r', t, enc);
- continue;
- case '\f':
+ continue;
+ case '\f':
t += rb_enc_mbcput('\\', t, enc);
t += rb_enc_mbcput('f', t, enc);
- continue;
- case '\v':
+ continue;
+ case '\v':
t += rb_enc_mbcput('\\', t, enc);
t += rb_enc_mbcput('v', t, enc);
- continue;
- }
+ continue;
+ }
t += rb_enc_mbcput(c, t, enc);
}
rb_str_resize(tmp, t - RSTRING_PTR(tmp));
@@ -3576,15 +4092,19 @@ rb_reg_quote(VALUE str)
/*
* call-seq:
- * Regexp.escape(str) -> string
- * Regexp.quote(str) -> string
+ * Regexp.escape(string) -> new_string
+ *
+ * Returns a new string that escapes any characters
+ * that have special meaning in a regular expression:
+ *
+ * s = Regexp.escape('\*?{}.') # => "\\\\\\*\\?\\{\\}\\."
*
- * Escapes any characters that would have special meaning in a regular
- * expression. Returns a new escaped string with the same or compatible
- * encoding. For any string,
- * <code>Regexp.new(Regexp.escape(<i>str</i>))=~<i>str</i></code> will be true.
+ * For any string +s+, this call returns a MatchData object:
*
- * Regexp.escape('\*?{}.') #=> \\\*\?\{\}\.
+ * r = Regexp.new(Regexp.escape(s)) # => /\\\\\\\*\\\?\\\{\\\}\\\./
+ * r.match(s) # => #<MatchData "\\\\\\*\\?\\{\\}\\.">
+ *
+ * Regexp.quote is an alias for Regexp.escape.
*
*/
@@ -3614,19 +4134,20 @@ rb_check_regexp_type(VALUE re)
/*
* call-seq:
- * Regexp.try_convert(obj) -> re or nil
+ * Regexp.try_convert(object) -> regexp or nil
+ *
+ * Returns +object+ if it is a regexp:
+ *
+ * Regexp.try_convert(/re/) # => /re/
+ *
+ * Otherwise if +object+ responds to <tt>:to_regexp</tt>,
+ * calls <tt>object.to_regexp</tt> and returns the result.
*
- * Try to convert <i>obj</i> into a Regexp, using to_regexp method.
- * Returns converted regexp or nil if <i>obj</i> cannot be converted
- * for any reason.
+ * Returns +nil+ if +object+ does not respond to <tt>:to_regexp</tt>.
*
- * Regexp.try_convert(/re/) #=> /re/
- * Regexp.try_convert("re") #=> nil
+ * Regexp.try_convert('re') # => nil
*
- * o = Object.new
- * Regexp.try_convert(o) #=> nil
- * def o.to_regexp() /foo/ end
- * Regexp.try_convert(o) #=> /foo/
+ * Raises an exception unless <tt>object.to_regexp</tt> returns a regexp.
*
*/
static VALUE
@@ -3657,23 +4178,23 @@ rb_reg_s_union(VALUE self, VALUE args0)
}
}
else {
- int i;
- VALUE source = rb_str_buf_new(0);
- rb_encoding *result_enc;
+ int i;
+ VALUE source = rb_str_buf_new(0);
+ rb_encoding *result_enc;
int has_asciionly = 0;
rb_encoding *has_ascii_compat_fixed = 0;
rb_encoding *has_ascii_incompat = 0;
- for (i = 0; i < argc; i++) {
- volatile VALUE v;
- VALUE e = rb_ary_entry(args0, i);
+ for (i = 0; i < argc; i++) {
+ volatile VALUE v;
+ VALUE e = rb_ary_entry(args0, i);
- if (0 < i)
- rb_str_buf_cat_ascii(source, "|");
+ if (0 < i)
+ rb_str_buf_cat_ascii(source, "|");
- v = rb_check_regexp_type(e);
- if (!NIL_P(v)) {
+ v = rb_check_regexp_type(e);
+ if (!NIL_P(v)) {
rb_encoding *enc = rb_enc_get(v);
if (!rb_enc_asciicompat(enc)) {
if (!has_ascii_incompat)
@@ -3692,9 +4213,9 @@ rb_reg_s_union(VALUE self, VALUE args0)
else {
has_asciionly = 1;
}
- v = rb_reg_str_with_term(v, -1);
- }
- else {
+ v = rb_reg_str_with_term(v, -1);
+ }
+ else {
rb_encoding *enc;
StringValue(e);
enc = rb_enc_get(e);
@@ -3715,8 +4236,8 @@ rb_reg_s_union(VALUE self, VALUE args0)
rb_raise(rb_eArgError, "incompatible encodings: %s and %s",
rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
}
- v = rb_reg_s_quote(Qnil, e);
- }
+ v = rb_reg_s_quote(Qnil, e);
+ }
if (has_ascii_incompat) {
if (has_asciionly) {
rb_raise(rb_eArgError, "ASCII incompatible encoding: %s",
@@ -3731,8 +4252,8 @@ rb_reg_s_union(VALUE self, VALUE args0)
if (i == 0) {
rb_enc_copy(source, v);
}
- rb_str_append(source, v);
- }
+ rb_str_append(source, v);
+ }
if (has_ascii_incompat) {
result_enc = has_ascii_incompat;
@@ -3751,25 +4272,37 @@ rb_reg_s_union(VALUE self, VALUE args0)
/*
* call-seq:
- * Regexp.union(pat1, pat2, ...) -> new_regexp
- * Regexp.union(pats_ary) -> new_regexp
- *
- * Return a Regexp object that is the union of the given
- * <em>pattern</em>s, i.e., will match any of its parts. The
- * <em>pattern</em>s can be Regexp objects, in which case their
- * options will be preserved, or Strings. If no patterns are given,
- * returns <code>/(?!)/</code>. The behavior is unspecified if any
- * given <em>pattern</em> contains capture.
- *
- * Regexp.union #=> /(?!)/
- * Regexp.union("penzance") #=> /penzance/
- * Regexp.union("a+b*c") #=> /a\+b\*c/
- * Regexp.union("skiing", "sledding") #=> /skiing|sledding/
- * Regexp.union(["skiing", "sledding"]) #=> /skiing|sledding/
- * Regexp.union(/dogs/, /cats/i) #=> /(?-mix:dogs)|(?i-mx:cats)/
- *
- * Note: the arguments for ::union will try to be converted into a regular
- * expression literal via #to_regexp.
+ * Regexp.union(*patterns) -> regexp
+ * Regexp.union(array_of_patterns) -> regexp
+ *
+ * Returns a new regexp that is the union of the given patterns:
+ *
+ * r = Regexp.union(%w[cat dog]) # => /cat|dog/
+ * r.match('cat') # => #<MatchData "cat">
+ * r.match('dog') # => #<MatchData "dog">
+ * r.match('cog') # => nil
+ *
+ * For each pattern that is a string, <tt>Regexp.new(pattern)</tt> is used:
+ *
+ * Regexp.union('penzance') # => /penzance/
+ * Regexp.union('a+b*c') # => /a\+b\*c/
+ * Regexp.union('skiing', 'sledding') # => /skiing|sledding/
+ * Regexp.union(['skiing', 'sledding']) # => /skiing|sledding/
+ *
+ * For each pattern that is a regexp, it is used as is,
+ * including its flags:
+ *
+ * Regexp.union(/foo/i, /bar/m, /baz/x)
+ * # => /(?i-mx:foo)|(?m-ix:bar)|(?x-mi:baz)/
+ * Regexp.union([/foo/i, /bar/m, /baz/x])
+ * # => /(?i-mx:foo)|(?m-ix:bar)|(?x-mi:baz)/
+ *
+ * With no arguments, returns <tt>/(?!)/</tt>:
+ *
+ * Regexp.union # => /(?!)/
+ *
+ * If any regexp pattern contains captures, the behavior is unspecified.
+ *
*/
static VALUE
rb_reg_s_union_m(VALUE self, VALUE args)
@@ -3782,6 +4315,40 @@ rb_reg_s_union_m(VALUE self, VALUE args)
return rb_reg_s_union(self, args);
}
+/*
+ * call-seq:
+ * Regexp.linear_time?(re)
+ * Regexp.linear_time?(string, options = 0)
+ *
+ * Returns +true+ if matching against <tt>re</tt> can be
+ * done in linear time to the input string.
+ *
+ * Regexp.linear_time?(/re/) # => true
+ *
+ * Note that this is a property of the ruby interpreter, not of the argument
+ * regular expression. Identical regexp can or cannot run in linear time
+ * depending on your ruby binary. Neither forward nor backward compatibility
+ * is guaranteed about the return value of this method. Our current algorithm
+ * is (*1) but this is subject to change in the future. Alternative
+ * implementations can also behave differently. They might always return
+ * false for everything.
+ *
+ * (*1): https://doi.org/10.1109/SP40001.2021.00032
+ *
+ */
+static VALUE
+rb_reg_s_linear_time_p(int argc, VALUE *argv, VALUE self)
+{
+ struct reg_init_args args;
+ VALUE re = reg_extract_args(argc, argv, &args);
+
+ if (NIL_P(re)) {
+ re = reg_init_args(rb_reg_alloc(), args.str, args.enc, args.flags);
+ }
+
+ return RBOOL(onig_check_linear_time(RREGEXP_PTR(re)));
+}
+
/* :nodoc: */
static VALUE
rb_reg_init_copy(VALUE copy, VALUE re)
@@ -3809,42 +4376,42 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
while (s < e) {
int c = ASCGET(s, e, &clen);
- char *ss;
+ char *ss;
- if (c == -1) {
- s += mbclen(s, e, str_enc);
- continue;
- }
- ss = s;
+ if (c == -1) {
+ s += mbclen(s, e, str_enc);
+ continue;
+ }
+ ss = s;
s += clen;
- if (c != '\\' || s == e) continue;
+ if (c != '\\' || s == e) continue;
- if (!val) {
- val = rb_str_buf_new(ss-p);
- }
+ if (!val) {
+ val = rb_str_buf_new(ss-p);
+ }
rb_enc_str_buf_cat(val, p, ss-p, str_enc);
c = ASCGET(s, e, &clen);
if (c == -1) {
s += mbclen(s, e, str_enc);
- rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
+ rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
p = s;
- continue;
+ continue;
}
s += clen;
- p = s;
- switch (c) {
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
+ p = s;
+ switch (c) {
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
if (!NIL_P(regexp) && onig_noname_group_capture_is_active(RREGEXP_PTR(regexp))) {
no = c - '0';
}
else {
continue;
}
- break;
+ break;
case 'k':
if (s < e && ASCGET(s, e, &clen) == '<') {
@@ -3857,11 +4424,11 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
name_end += c == -1 ? mbclen(name_end, e, str_enc) : clen;
}
if (name_end < e) {
- VALUE n = rb_str_subseq(str, (long)(name - RSTRING_PTR(str)),
- (long)(name_end - name));
- if ((no = NAME_TO_NUMBER(regs, regexp, n, name, name_end)) < 1) {
- name_to_backref_error(n);
- }
+ VALUE n = rb_str_subseq(str, (long)(name - RSTRING_PTR(str)),
+ (long)(name_end - name));
+ if ((no = NAME_TO_NUMBER(regs, regexp, n, name, name_end)) < 1) {
+ name_to_backref_error(n);
+ }
p = s = name_end + clen;
break;
}
@@ -3874,38 +4441,38 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
continue;
case '0':
- case '&':
- no = 0;
- break;
+ case '&':
+ no = 0;
+ break;
- case '`':
- rb_enc_str_buf_cat(val, RSTRING_PTR(src), BEG(0), src_enc);
- continue;
+ case '`':
+ rb_enc_str_buf_cat(val, RSTRING_PTR(src), BEG(0), src_enc);
+ continue;
- case '\'':
- rb_enc_str_buf_cat(val, RSTRING_PTR(src)+END(0), RSTRING_LEN(src)-END(0), src_enc);
- continue;
+ case '\'':
+ rb_enc_str_buf_cat(val, RSTRING_PTR(src)+END(0), RSTRING_LEN(src)-END(0), src_enc);
+ continue;
- case '+':
- no = regs->num_regs-1;
- while (BEG(no) == -1 && no > 0) no--;
- if (no == 0) continue;
- break;
+ case '+':
+ no = regs->num_regs-1;
+ while (BEG(no) == -1 && no > 0) no--;
+ if (no == 0) continue;
+ break;
- case '\\':
- rb_enc_str_buf_cat(val, s-clen, clen, str_enc);
- continue;
+ case '\\':
+ rb_enc_str_buf_cat(val, s-clen, clen, str_enc);
+ continue;
- default:
- rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
- continue;
- }
+ default:
+ rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
+ continue;
+ }
- if (no >= 0) {
- if (no >= regs->num_regs) continue;
- if (BEG(no) == -1) continue;
- rb_enc_str_buf_cat(val, RSTRING_PTR(src)+BEG(no), END(no)-BEG(no), src_enc);
- }
+ if (no >= 0) {
+ if (no >= regs->num_regs) continue;
+ if (BEG(no) == -1) continue;
+ rb_enc_str_buf_cat(val, RSTRING_PTR(src)+BEG(no), END(no)-BEG(no), src_enc);
+ }
}
if (!val) return str;
@@ -3949,37 +4516,47 @@ static void
match_setter(VALUE val, ID _x, VALUE *_y)
{
if (!NIL_P(val)) {
- Check_Type(val, T_MATCH);
+ Check_Type(val, T_MATCH);
}
rb_backref_set(val);
}
/*
* call-seq:
- * Regexp.last_match -> matchdata
- * Regexp.last_match(n) -> str
- *
- * The first form returns the MatchData object generated by the
- * last successful pattern match. Equivalent to reading the special global
- * variable <code>$~</code> (see Special global variables in Regexp for
- * details).
- *
- * The second form returns the <i>n</i>th field in this MatchData object.
- * _n_ can be a string or symbol to reference a named capture.
- *
- * Note that the last_match is local to the thread and method scope of the
- * method that did the pattern match.
- *
- * /c(.)t/ =~ 'cat' #=> 0
- * Regexp.last_match #=> #<MatchData "cat" 1:"a">
- * Regexp.last_match(0) #=> "cat"
- * Regexp.last_match(1) #=> "a"
- * Regexp.last_match(2) #=> nil
- *
- * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ "var = val"
- * Regexp.last_match #=> #<MatchData "var = val" lhs:"var" rhs:"val">
- * Regexp.last_match(:lhs) #=> "var"
- * Regexp.last_match(:rhs) #=> "val"
+ * Regexp.last_match -> matchdata or nil
+ * Regexp.last_match(n) -> string or nil
+ * Regexp.last_match(name) -> string or nil
+ *
+ * With no argument, returns the value of <tt>$!</tt>,
+ * which is the result of the most recent pattern match
+ * (see {Regexp Global Variables}[rdoc-ref:Regexp@Regexp+Global+Variables]):
+ *
+ * /c(.)t/ =~ 'cat' # => 0
+ * Regexp.last_match # => #<MatchData "cat" 1:"a">
+ * /a/ =~ 'foo' # => nil
+ * Regexp.last_match # => nil
+ *
+ * With non-negative integer argument +n+, returns the _n_th field in the
+ * matchdata, if any, or nil if none:
+ *
+ * /c(.)t/ =~ 'cat' # => 0
+ * Regexp.last_match(0) # => "cat"
+ * Regexp.last_match(1) # => "a"
+ * Regexp.last_match(2) # => nil
+ *
+ * With negative integer argument +n+, counts backwards from the last field:
+ *
+ * Regexp.last_match(-1) # => "a"
+ *
+ * With string or symbol argument +name+,
+ * returns the string value for the named capture, if any:
+ *
+ * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ 'var = val'
+ * Regexp.last_match # => #<MatchData "var = val" lhs:"var"rhs:"val">
+ * Regexp.last_match(:lhs) # => "var"
+ * Regexp.last_match('rhs') # => "val"
+ * Regexp.last_match('foo') # Raises IndexError.
+ *
*/
static VALUE
@@ -3990,7 +4567,7 @@ rb_reg_s_last_match(int argc, VALUE *argv, VALUE _)
int n;
if (NIL_P(match)) return Qnil;
n = match_backref_number(match, argv[0]);
- return rb_reg_nth_match(n, match);
+ return rb_reg_nth_match(n, match);
}
return match_getter();
}
@@ -4001,6 +4578,105 @@ re_warn(const char *s)
rb_warn("%s", s);
}
+// The process-global timeout for regexp matching
+rb_hrtime_t rb_reg_match_time_limit = 0;
+
+// This function is periodically called during regexp matching
+void
+rb_reg_check_timeout(regex_t *reg, void *end_time_)
+{
+ rb_hrtime_t *end_time = (rb_hrtime_t *)end_time_;
+
+ if (*end_time == 0) {
+ // This is the first time to check interrupts;
+ // just measure the current time and determine the end time
+ // if timeout is set.
+ rb_hrtime_t timelimit = reg->timelimit;
+
+ if (!timelimit) {
+ // no per-object timeout.
+ timelimit = rb_reg_match_time_limit;
+ }
+
+ if (timelimit) {
+ *end_time = rb_hrtime_add(timelimit, rb_hrtime_now());
+ }
+ else {
+ // no timeout is set
+ *end_time = RB_HRTIME_MAX;
+ }
+ }
+ else {
+ if (*end_time < rb_hrtime_now()) {
+ // timeout is exceeded
+ rb_raise(rb_eRegexpTimeoutError, "regexp match timeout");
+ }
+ }
+}
+
+/*
+ * call-seq:
+ * Regexp.timeout -> float or nil
+ *
+ * It returns the current default timeout interval for Regexp matching in second.
+ * +nil+ means no default timeout configuration.
+ */
+
+static VALUE
+rb_reg_s_timeout_get(VALUE dummy)
+{
+ double d = hrtime2double(rb_reg_match_time_limit);
+ if (d == 0.0) return Qnil;
+ return DBL2NUM(d);
+}
+
+/*
+ * call-seq:
+ * Regexp.timeout = float or nil
+ *
+ * It sets the default timeout interval for Regexp matching in second.
+ * +nil+ means no default timeout configuration.
+ * This configuration is process-global. If you want to set timeout for
+ * each Regexp, use +timeout+ keyword for <code>Regexp.new</code>.
+ *
+ * Regexp.timeout = 1
+ * /^a*b?a*$/ =~ "a" * 100000 + "x" #=> regexp match timeout (RuntimeError)
+ */
+
+static VALUE
+rb_reg_s_timeout_set(VALUE dummy, VALUE timeout)
+{
+ rb_ractor_ensure_main_ractor("can not access Regexp.timeout from non-main Ractors");
+
+ set_timeout(&rb_reg_match_time_limit, timeout);
+
+ return timeout;
+}
+
+/*
+ * call-seq:
+ * rxp.timeout -> float or nil
+ *
+ * It returns the timeout interval for Regexp matching in second.
+ * +nil+ means no default timeout configuration.
+ *
+ * This configuration is per-object. The global configuration set by
+ * Regexp.timeout= is ignored if per-object configuration is set.
+ *
+ * re = Regexp.new("^a*b?a*$", timeout: 1)
+ * re.timeout #=> 1.0
+ * re =~ "a" * 100000 + "x" #=> regexp match timeout (RuntimeError)
+ */
+
+static VALUE
+rb_reg_timeout_get(VALUE re)
+{
+ rb_reg_check(re);
+ double d = hrtime2double(RREGEXP_PTR(re)->timelimit);
+ if (d == 0.0) return Qnil;
+ return DBL2NUM(d);
+}
+
/*
* Document-class: RegexpError
*
@@ -4016,11 +4692,6 @@ re_warn(const char *s)
/*
* Document-class: Regexp
*
- * A Regexp holds a regular expression, used to match a pattern
- * against strings. Regexps are created using the <code>/.../</code>
- * and <code>%r{...}</code> literals, and by the Regexp::new
- * constructor.
- *
* :include: doc/regexp.rdoc
*/
@@ -4049,12 +4720,13 @@ Init_Regexp(void)
rb_cRegexp = rb_define_class("Regexp", rb_cObject);
rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc);
- rb_define_singleton_method(rb_cRegexp, "compile", rb_class_new_instance, -1);
+ rb_define_singleton_method(rb_cRegexp, "compile", rb_class_new_instance_pass_kw, -1);
rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, 1);
rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, 1);
rb_define_singleton_method(rb_cRegexp, "union", rb_reg_s_union_m, -2);
rb_define_singleton_method(rb_cRegexp, "last_match", rb_reg_s_last_match, -1);
rb_define_singleton_method(rb_cRegexp, "try_convert", rb_reg_s_try_convert, 1);
+ rb_define_singleton_method(rb_cRegexp, "linear_time?", rb_reg_s_linear_time_p, -1);
rb_define_method(rb_cRegexp, "initialize", rb_reg_initialize_m, -1);
rb_define_method(rb_cRegexp, "initialize_copy", rb_reg_init_copy, 1);
@@ -4075,6 +4747,11 @@ Init_Regexp(void)
rb_define_method(rb_cRegexp, "fixed_encoding?", rb_reg_fixed_encoding_p, 0);
rb_define_method(rb_cRegexp, "names", rb_reg_names, 0);
rb_define_method(rb_cRegexp, "named_captures", rb_reg_named_captures, 0);
+ rb_define_method(rb_cRegexp, "timeout", rb_reg_timeout_get, 0);
+
+ rb_eRegexpTimeoutError = rb_define_class_under(rb_cRegexp, "TimeoutError", rb_eRegexpError);
+ rb_define_singleton_method(rb_cRegexp, "timeout", rb_reg_s_timeout_get, 0);
+ rb_define_singleton_method(rb_cRegexp, "timeout=", rb_reg_s_timeout_set, 1);
/* see Regexp.options and Regexp.new */
rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));
@@ -4100,12 +4777,17 @@ Init_Regexp(void)
rb_define_method(rb_cMatch, "size", match_size, 0);
rb_define_method(rb_cMatch, "length", match_size, 0);
rb_define_method(rb_cMatch, "offset", match_offset, 1);
+ rb_define_method(rb_cMatch, "byteoffset", match_byteoffset, 1);
rb_define_method(rb_cMatch, "begin", match_begin, 1);
rb_define_method(rb_cMatch, "end", match_end, 1);
+ rb_define_method(rb_cMatch, "match", match_nth, 1);
+ rb_define_method(rb_cMatch, "match_length", match_nth_length, 1);
rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
rb_define_method(rb_cMatch, "[]", match_aref, -1);
rb_define_method(rb_cMatch, "captures", match_captures, 0);
+ rb_define_alias(rb_cMatch, "deconstruct", "captures");
rb_define_method(rb_cMatch, "named_captures", match_named_captures, 0);
+ rb_define_method(rb_cMatch, "deconstruct_keys", match_deconstruct_keys, 1);
rb_define_method(rb_cMatch, "values_at", match_values_at, -1);
rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
diff --git a/regcomp.c b/regcomp.c
index 44ee0b2e51..be85d85f93 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -142,8 +142,13 @@ bitset_on_num(BitSetRef bs)
static void
onig_reg_resize(regex_t *reg)
{
- resize:
- if (reg->alloc > reg->used) {
+ 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) {
@@ -151,10 +156,7 @@ onig_reg_resize(regex_t *reg)
reg->p = new_ptr;
}
}
- if (reg->chain) {
- reg = reg->chain;
- goto resize;
- }
+ } while ((reg = reg->chain) != 0);
}
extern int
@@ -339,7 +341,7 @@ static int
select_str_opcode(int mb_len, OnigDistance byte_len, int ignore_case)
{
int op;
- OnigDistance str_len = (byte_len + mb_len - 1) / mb_len;
+ OnigDistance str_len = roomof(byte_len, mb_len);
if (ignore_case) {
switch (str_len) {
@@ -5034,7 +5036,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
if (NSTRING_IS_DONT_GET_OPT_INFO(node)) {
int n = onigenc_strlen(env->enc, sn->s, sn->end);
- max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n;
+ max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * (OnigDistance)n;
}
else {
concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
@@ -5973,6 +5975,9 @@ onig_reg_init(regex_t* reg, OnigOptionType option,
(reg)->name_table = (void* )NULL;
(reg)->case_fold_flag = case_fold_flag;
+
+ (reg)->timelimit = 0;
+
return 0;
}
diff --git a/regenc.c b/regenc.c
index 16d62fdf40..eb523e1ae5 100644
--- a/regenc.c
+++ b/regenc.c
@@ -52,6 +52,21 @@ onigenc_set_default_encoding(OnigEncoding enc)
}
extern int
+onigenc_mbclen(const OnigUChar* p,const OnigUChar* e, OnigEncoding enc)
+{
+ int ret = ONIGENC_PRECISE_MBC_ENC_LEN(enc, p, e);
+ if (ONIGENC_MBCLEN_CHARFOUND_P(ret)) {
+ ret = ONIGENC_MBCLEN_CHARFOUND_LEN(ret);
+ if (p + ret > e) ret = (int)(e - p); // just for case
+ return ret;
+ }
+ else if (ONIGENC_MBCLEN_NEEDMORE_P(ret)) {
+ return (int)(e - p);
+ }
+ return p < e ? 1 : 0;
+}
+
+extern int
onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, OnigEncoding enc)
{
int ret = ONIGENC_PRECISE_MBC_ENC_LEN(enc, p, e);
diff --git a/regenc.h b/regenc.h
index 16ed6c39da..4b4d21a715 100644
--- a/regenc.h
+++ b/regenc.h
@@ -40,6 +40,7 @@
# include "ruby/defines.h"
# endif
# endif
+# include "ruby.h"
#else /* RUBY */
# ifndef PACKAGE
/* PACKAGE is defined in config.h */
@@ -90,7 +91,7 @@ typedef struct {
#define ONIG_CHECK_NULL_RETURN(p) if (ONIG_IS_NULL(p)) return NULL
#define ONIG_CHECK_NULL_RETURN_VAL(p,val) if (ONIG_IS_NULL(p)) return (val)
-#define enclen(enc,p,e) ((enc->max_enc_len == enc->min_enc_len) ? enc->min_enc_len : ONIGENC_MBC_ENC_LEN(enc,p,e))
+#define enclen(enc,p,e) ((enc->max_enc_len == enc->min_enc_len) ? (p < e ? enc->min_enc_len : 0) : ONIGENC_MBC_ENC_LEN(enc,p,e))
/* character types bit flag */
#define BIT_CTYPE_NEWLINE (1<< ONIGENC_CTYPE_NEWLINE)
@@ -117,6 +118,11 @@ typedef struct {
typedef struct {
short int len;
+#if defined(__has_attribute)
+# if __has_attribute(nonstring)
+ __attribute__((nonstring))
+# endif
+#endif
const UChar name[6];
int ctype;
} PosixBracketEntryType;
@@ -124,10 +130,9 @@ typedef struct {
#define POSIX_BRACKET_ENTRY_INIT(name, ctype) \
{(short int )(sizeof(name) - 1), name, (ctype)}
-#ifndef numberof
-# define numberof(array) (int )(sizeof(array) / sizeof((array)[0]))
-#endif
-
+#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
+#define roomof(x, y) (((x) + (y) - 1) / (y))
+#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
#define USE_CRNL_AS_LINE_TERMINATOR
#define USE_UNICODE_PROPERTIES
diff --git a/regerror.c b/regerror.c
index efcfefffdf..b18fc2e88b 100644
--- a/regerror.c
+++ b/regerror.c
@@ -312,7 +312,7 @@ onig_error_code_to_str(UChar* s, OnigPosition code, ...)
void
onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
- UChar* pat, UChar* pat_end, const UChar *fmt, va_list args)
+ UChar* pat, UChar* pat_end, const char *fmt, va_list args)
{
size_t need;
int n, len;
@@ -376,7 +376,7 @@ onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
#if 0 /* unused */
void
onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
- UChar* pat, UChar* pat_end, const UChar *fmt, ...)
+ UChar* pat, UChar* pat_end, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
diff --git a/regexec.c b/regexec.c
index 8334b16e96..47fc88c9c2 100644
--- a/regexec.c
+++ b/regexec.c
@@ -231,6 +231,488 @@ onig_get_capture_tree(OnigRegion* region)
}
#endif /* USE_CAPTURE_HISTORY */
+#ifdef USE_CACHE_MATCH_OPT
+
+/* count number of jump-like opcodes for allocation of cache memory. */
+static OnigPosition
+count_num_cache_opcode(regex_t* reg, long* num, long* table_size)
+{
+ UChar* p = reg->p;
+ UChar* pend = p + reg->used;
+ LengthType len;
+ MemNumType mem;
+ MemNumType current_mem = -1;
+ long current_mem_num = 0;
+ OnigEncoding enc = reg->enc;
+
+ *num = 0;
+ *table_size = 0;
+
+ while (p < pend) {
+ switch (*p++) {
+ case OP_FINISH:
+ case OP_END:
+ break;
+
+ case OP_EXACT1: p++; break;
+ case OP_EXACT2: p += 2; break;
+ case OP_EXACT3: p += 3; break;
+ case OP_EXACT4: p += 4; break;
+ case OP_EXACT5: p += 5; break;
+ case OP_EXACTN:
+ GET_LENGTH_INC(len, p); p += len; break;
+ case OP_EXACTMB2N1: p += 2; break;
+ case OP_EXACTMB2N2: p += 4; break;
+ case OP_EXACTMB2N3: p += 6; break;
+ case OP_EXACTMB2N:
+ GET_LENGTH_INC(len, p); p += len * 2; break;
+ case OP_EXACTMB3N:
+ GET_LENGTH_INC(len, p); p += len * 3; break;
+ case OP_EXACTMBN:
+ {
+ int mb_len;
+ GET_LENGTH_INC(mb_len, p);
+ GET_LENGTH_INC(len, p);
+ p += mb_len * len;
+ }
+ break;
+
+ case OP_EXACT1_IC:
+ len = enclen(enc, p, pend); p += len; break;
+ case OP_EXACTN_IC:
+ GET_LENGTH_INC(len, p); p += len; break;
+
+ case OP_CCLASS:
+ case OP_CCLASS_NOT:
+ p += SIZE_BITSET; break;
+ case OP_CCLASS_MB:
+ case OP_CCLASS_MB_NOT:
+ GET_LENGTH_INC(len, p); p += len; break;
+ case OP_CCLASS_MIX:
+ case OP_CCLASS_MIX_NOT:
+ p += SIZE_BITSET;
+ GET_LENGTH_INC(len, p);
+ p += len;
+ break;
+
+ case OP_ANYCHAR:
+ case OP_ANYCHAR_ML:
+ break;
+ case OP_ANYCHAR_STAR:
+ case OP_ANYCHAR_ML_STAR:
+ *num += 1; *table_size += 1; break;
+ case OP_ANYCHAR_STAR_PEEK_NEXT:
+ case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
+ p++; *num += 1; *table_size += 1; break;
+
+ case OP_WORD:
+ case OP_NOT_WORD:
+ case OP_WORD_BOUND:
+ case OP_NOT_WORD_BOUND:
+ case OP_WORD_BEGIN:
+ case OP_WORD_END:
+ break;
+
+ case OP_ASCII_WORD:
+ case OP_NOT_ASCII_WORD:
+ case OP_ASCII_WORD_BOUND:
+ case OP_NOT_ASCII_WORD_BOUND:
+ case OP_ASCII_WORD_BEGIN:
+ case OP_ASCII_WORD_END:
+ break;
+
+ case OP_BEGIN_BUF:
+ case OP_END_BUF:
+ case OP_BEGIN_LINE:
+ case OP_END_LINE:
+ case OP_SEMI_END_BUF:
+ case OP_BEGIN_POSITION:
+ break;
+
+ case OP_BACKREF1:
+ case OP_BACKREF2:
+ case OP_BACKREFN:
+ case OP_BACKREFN_IC:
+ case OP_BACKREF_MULTI:
+ case OP_BACKREF_MULTI_IC:
+ case OP_BACKREF_WITH_LEVEL:
+ goto fail;
+
+ case OP_MEMORY_START:
+ case OP_MEMORY_START_PUSH:
+ case OP_MEMORY_END_PUSH:
+ case OP_MEMORY_END_PUSH_REC:
+ case OP_MEMORY_END:
+ case OP_MEMORY_END_REC:
+ p += SIZE_MEMNUM; break;
+
+ case OP_KEEP:
+ break;
+
+ case OP_FAIL:
+ break;
+ case OP_JUMP:
+ p += SIZE_RELADDR;
+ break;
+ case OP_PUSH:
+ p += SIZE_RELADDR;
+ *num += 1;
+ *table_size += 1;
+ break;
+ case OP_POP:
+ break;
+ case OP_PUSH_OR_JUMP_EXACT1:
+ case OP_PUSH_IF_PEEK_NEXT:
+ p += SIZE_RELADDR + 1; *num += 1; *table_size += 1; break;
+ case OP_REPEAT:
+ case OP_REPEAT_NG:
+ if (current_mem != -1) {
+ // A nested OP_REPEAT is not yet supported.
+ goto fail;
+ }
+ GET_MEMNUM_INC(mem, p);
+ p += SIZE_RELADDR;
+ if (reg->repeat_range[mem].lower == 0) {
+ *num += 1;
+ *table_size += 1;
+ }
+ reg->repeat_range[mem].base_num = *num;
+ current_mem = mem;
+ current_mem_num = *num;
+ break;
+ case OP_REPEAT_INC:
+ case OP_REPEAT_INC_NG:
+ GET_MEMNUM_INC(mem, p);
+ if (mem != current_mem) {
+ // A lone or invalid OP_REPEAT_INC is found.
+ goto fail;
+ }
+ {
+ long inner_num = *num - current_mem_num;
+ OnigRepeatRange *repeat_range = &reg->repeat_range[mem];
+ repeat_range->inner_num = inner_num;
+ *num -= inner_num;
+ *num += inner_num * repeat_range->lower + (inner_num + 1) * (repeat_range->upper == 0x7fffffff ? 1 : repeat_range->upper - repeat_range->lower);
+ if (repeat_range->lower < repeat_range->upper) {
+ *table_size += 1;
+ }
+ current_mem = -1;
+ current_mem_num = 0;
+ }
+ break;
+ case OP_REPEAT_INC_SG:
+ case OP_REPEAT_INC_NG_SG:
+ // TODO: Support nested OP_REPEAT.
+ goto fail;
+ case OP_NULL_CHECK_START:
+ case OP_NULL_CHECK_END:
+ case OP_NULL_CHECK_END_MEMST:
+ case OP_NULL_CHECK_END_MEMST_PUSH:
+ p += SIZE_MEMNUM; break;
+
+ case OP_PUSH_POS:
+ case OP_POP_POS:
+ case OP_PUSH_POS_NOT:
+ case OP_FAIL_POS:
+ case OP_PUSH_STOP_BT:
+ case OP_POP_STOP_BT:
+ case OP_LOOK_BEHIND:
+ case OP_PUSH_LOOK_BEHIND_NOT:
+ case OP_FAIL_LOOK_BEHIND_NOT:
+ case OP_PUSH_ABSENT_POS:
+ case OP_ABSENT_END:
+ case OP_ABSENT:
+ goto fail;
+
+ case OP_CALL:
+ case OP_RETURN:
+ goto fail;
+
+ case OP_CONDITION:
+ goto fail;
+
+ case OP_STATE_CHECK_PUSH:
+ case OP_STATE_CHECK_PUSH_OR_JUMP:
+ case OP_STATE_CHECK:
+ case OP_STATE_CHECK_ANYCHAR_STAR:
+ case OP_STATE_CHECK_ANYCHAR_ML_STAR:
+ goto fail;
+
+ case OP_SET_OPTION_PUSH:
+ case OP_SET_OPTION:
+ p += SIZE_OPTION;
+ break;
+
+ default:
+ goto bytecode_error;
+ }
+ }
+
+ return 0;
+
+fail:
+ *num = NUM_CACHE_OPCODE_FAIL;
+ return 0;
+
+bytecode_error:
+ return ONIGERR_UNDEFINED_BYTECODE;
+}
+
+static OnigPosition
+init_cache_index_table(regex_t* reg, OnigCacheIndex *table)
+{
+ UChar* pbegin;
+ UChar* p = reg->p;
+ UChar* pend = p + reg->used;
+ LengthType len;
+ MemNumType mem;
+ MemNumType current_mem = -1;
+ long num = 0;
+ long current_mem_num = 0;
+ OnigEncoding enc = reg->enc;
+
+ while (p < pend) {
+ pbegin = p;
+ switch (*p++) {
+ case OP_FINISH:
+ case OP_END:
+ break;
+
+ case OP_EXACT1: p++; break;
+ case OP_EXACT2: p += 2; break;
+ case OP_EXACT3: p += 3; break;
+ case OP_EXACT4: p += 4; break;
+ case OP_EXACT5: p += 5; break;
+ case OP_EXACTN:
+ GET_LENGTH_INC(len, p); p += len; break;
+ case OP_EXACTMB2N1: p += 2; break;
+ case OP_EXACTMB2N2: p += 4; break;
+ case OP_EXACTMB2N3: p += 6; break;
+ case OP_EXACTMB2N:
+ GET_LENGTH_INC(len, p); p += len * 2; break;
+ case OP_EXACTMB3N:
+ GET_LENGTH_INC(len, p); p += len * 3; break;
+ case OP_EXACTMBN:
+ {
+ int mb_len;
+ GET_LENGTH_INC(mb_len, p);
+ GET_LENGTH_INC(len, p);
+ p += mb_len * len;
+ }
+ break;
+
+ case OP_EXACT1_IC:
+ len = enclen(enc, p, pend); p += len; break;
+ case OP_EXACTN_IC:
+ GET_LENGTH_INC(len, p); p += len; break;
+
+ case OP_CCLASS:
+ case OP_CCLASS_NOT:
+ p += SIZE_BITSET; break;
+ case OP_CCLASS_MB:
+ case OP_CCLASS_MB_NOT:
+ GET_LENGTH_INC(len, p); p += len; break;
+ case OP_CCLASS_MIX:
+ case OP_CCLASS_MIX_NOT:
+ p += SIZE_BITSET;
+ GET_LENGTH_INC(len, p);
+ p += len;
+ break;
+
+ case OP_ANYCHAR:
+ case OP_ANYCHAR_ML:
+ break;
+ case OP_ANYCHAR_STAR:
+ case OP_ANYCHAR_ML_STAR:
+ table->addr = pbegin;
+ table->num = num - current_mem_num;
+ table->outer_repeat = current_mem;
+ num++;
+ table++;
+ break;
+ case OP_ANYCHAR_STAR_PEEK_NEXT:
+ case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
+ p++;
+ table->addr = pbegin;
+ table->num = num - current_mem_num;
+ table->outer_repeat = current_mem;
+ num++;
+ table++;
+ break;
+
+ case OP_WORD:
+ case OP_NOT_WORD:
+ case OP_WORD_BOUND:
+ case OP_NOT_WORD_BOUND:
+ case OP_WORD_BEGIN:
+ case OP_WORD_END:
+ break;
+
+ case OP_ASCII_WORD:
+ case OP_NOT_ASCII_WORD:
+ case OP_ASCII_WORD_BOUND:
+ case OP_NOT_ASCII_WORD_BOUND:
+ case OP_ASCII_WORD_BEGIN:
+ case OP_ASCII_WORD_END:
+ break;
+
+ case OP_BEGIN_BUF:
+ case OP_END_BUF:
+ case OP_BEGIN_LINE:
+ case OP_END_LINE:
+ case OP_SEMI_END_BUF:
+ case OP_BEGIN_POSITION:
+ break;
+
+ case OP_BACKREF1:
+ case OP_BACKREF2:
+ case OP_BACKREFN:
+ case OP_BACKREFN_IC:
+ case OP_BACKREF_MULTI:
+ case OP_BACKREF_MULTI_IC:
+ case OP_BACKREF_WITH_LEVEL:
+ goto unexpected_bytecode_error;
+
+ case OP_MEMORY_START:
+ case OP_MEMORY_START_PUSH:
+ case OP_MEMORY_END_PUSH:
+ case OP_MEMORY_END_PUSH_REC:
+ case OP_MEMORY_END:
+ case OP_MEMORY_END_REC:
+ p += SIZE_MEMNUM; break;
+
+ case OP_KEEP:
+ break;
+
+ case OP_FAIL:
+ break;
+ case OP_JUMP:
+ p += SIZE_RELADDR;
+ break;
+ case OP_PUSH:
+ p += SIZE_RELADDR;
+ table->addr = pbegin;
+ table->num = num - current_mem_num;
+ table->outer_repeat = current_mem;
+ num++;
+ table++;
+ break;
+ case OP_POP:
+ break;
+ case OP_PUSH_OR_JUMP_EXACT1:
+ case OP_PUSH_IF_PEEK_NEXT:
+ p += SIZE_RELADDR + 1;
+ table->addr = pbegin;
+ table->num = num - current_mem_num;
+ table->outer_repeat = current_mem;
+ num++;
+ table++;
+ break;
+ case OP_REPEAT:
+ case OP_REPEAT_NG:
+ GET_MEMNUM_INC(mem, p);
+ p += SIZE_RELADDR;
+ if (reg->repeat_range[mem].lower == 0) {
+ table->addr = pbegin;
+ table->num = num - current_mem_num;
+ table->outer_repeat = -1;
+ num++;
+ table++;
+ }
+ current_mem = mem;
+ current_mem_num = num;
+ break;
+ case OP_REPEAT_INC:
+ case OP_REPEAT_INC_NG:
+ GET_MEMNUM_INC(mem, p);
+ {
+ long inner_num = num - current_mem_num;
+ OnigRepeatRange *repeat_range = &reg->repeat_range[mem];
+ if (repeat_range->lower < repeat_range->upper) {
+ table->addr = pbegin;
+ table->num = num - current_mem_num;
+ table->outer_repeat = mem;
+ table++;
+ }
+ num -= inner_num;
+ num += inner_num * repeat_range->lower + (inner_num + 1) * (repeat_range->upper == 0x7fffffff ? 1 : repeat_range->upper - repeat_range->lower);
+ current_mem = -1;
+ current_mem_num = 0;
+ }
+ break;
+ case OP_REPEAT_INC_SG:
+ case OP_REPEAT_INC_NG_SG:
+ // TODO: support OP_REPEAT opcodes.
+ goto unexpected_bytecode_error;
+ case OP_NULL_CHECK_START:
+ case OP_NULL_CHECK_END:
+ case OP_NULL_CHECK_END_MEMST:
+ case OP_NULL_CHECK_END_MEMST_PUSH:
+ p += SIZE_MEMNUM; break;
+
+ case OP_PUSH_POS:
+ case OP_POP_POS:
+ case OP_PUSH_POS_NOT:
+ case OP_FAIL_POS:
+ case OP_PUSH_STOP_BT:
+ case OP_POP_STOP_BT:
+ case OP_LOOK_BEHIND:
+ case OP_PUSH_LOOK_BEHIND_NOT:
+ case OP_FAIL_LOOK_BEHIND_NOT:
+ case OP_PUSH_ABSENT_POS:
+ case OP_ABSENT_END:
+ case OP_ABSENT:
+ goto unexpected_bytecode_error;
+
+ case OP_CALL:
+ case OP_RETURN:
+ goto unexpected_bytecode_error;
+
+ case OP_CONDITION:
+ goto unexpected_bytecode_error;
+
+ case OP_STATE_CHECK_PUSH:
+ case OP_STATE_CHECK_PUSH_OR_JUMP:
+ case OP_STATE_CHECK:
+ case OP_STATE_CHECK_ANYCHAR_STAR:
+ case OP_STATE_CHECK_ANYCHAR_ML_STAR:
+ goto unexpected_bytecode_error;
+
+ case OP_SET_OPTION_PUSH:
+ case OP_SET_OPTION:
+ p += SIZE_OPTION;
+ break;
+
+ default:
+ goto bytecode_error;
+ }
+ }
+
+ return 0;
+
+unexpected_bytecode_error:
+ return ONIGERR_UNEXPECTED_BYTECODE;
+
+bytecode_error:
+ return ONIGERR_UNDEFINED_BYTECODE;
+}
+#else /* USE_MATCH_CACHE */
+static OnigPosition
+count_num_cache_opcode(regex_t* reg, long* num, long* table_size)
+{
+ *num = NUM_CACHE_OPCODE_FAIL;
+ return 0;
+}
+#endif
+
+extern int
+onig_check_linear_time(OnigRegexType* reg)
+{
+ long num = 0, table_size = 0;
+ count_num_cache_opcode(reg, &num, &table_size);
+ return num != NUM_CACHE_OPCODE_FAIL;
+}
+
extern void
onig_region_clear(OnigRegion* region)
{
@@ -413,6 +895,24 @@ onig_region_copy(OnigRegion* to, const OnigRegion* from)
#define STK_MASK_TO_VOID_TARGET 0x10ff
#define STK_MASK_MEM_END_OR_MARK 0x8000 /* MEM_END or MEM_END_MARK */
+#ifdef USE_CACHE_MATCH_OPT
+#define MATCH_ARG_INIT_CACHE_MATCH_OPT(msa) do {\
+ (msa).enable_cache_match_opt = 0;\
+ (msa).num_fail = 0;\
+ (msa).num_cache_opcode = NUM_CACHE_OPCODE_UNINIT;\
+ (msa).num_cache_table = 0;\
+ (msa).cache_index_table = (OnigCacheIndex *)0;\
+ (msa).match_cache = (uint8_t *)0;\
+} while(0)
+#define MATCH_ARG_FREE_CACHE_MATCH_OPT(msa) do {\
+ if ((msa).cache_index_table) xfree((msa).cache_index_table);\
+ if ((msa).match_cache) xfree((msa).match_cache);\
+} while(0)
+#else
+#define MATCH_ARG_INIT_CACHE_MATCH_OPT(msa)
+#define MATCH_ARG_FREE_CACHE_MATCH_OPT(msa)
+#endif
+
#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
# define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
(msa).stack_p = (void* )0;\
@@ -421,6 +921,9 @@ onig_region_copy(OnigRegion* to, const OnigRegion* from)
(msa).start = (arg_start);\
(msa).gpos = (arg_gpos);\
(msa).best_len = ONIG_MISMATCH;\
+ (msa).counter = 0;\
+ (msa).end_time = 0;\
+ MATCH_ARG_INIT_CACHE_MATCH_OPT(msa);\
} while(0)
#else
# define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\
@@ -429,6 +932,9 @@ onig_region_copy(OnigRegion* to, const OnigRegion* from)
(msa).region = (arg_region);\
(msa).start = (arg_start);\
(msa).gpos = (arg_gpos);\
+ (msa).counter = 0;\
+ (msa).end_time = 0;\
+ MATCH_ARG_INIT_CACHE_MATCH_OPT(msa);\
} while(0)
#endif
@@ -467,9 +973,13 @@ onig_region_copy(OnigRegion* to, const OnigRegion* from)
if ((msa).state_check_buff_size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) { \
if ((msa).state_check_buff) xfree((msa).state_check_buff);\
}\
+ MATCH_ARG_FREE_CACHE_MATCH_OPT(msa);\
} while(0)
#else /* USE_COMBINATION_EXPLOSION_CHECK */
-# define MATCH_ARG_FREE(msa) if ((msa).stack_p) xfree((msa).stack_p)
+# define MATCH_ARG_FREE(msa) do {\
+ if ((msa).stack_p) xfree((msa).stack_p);\
+ MATCH_ARG_FREE_CACHE_MATCH_OPT(msa);\
+} while (0)
#endif /* USE_COMBINATION_EXPLOSION_CHECK */
@@ -591,6 +1101,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_TYPE(stack_type) do {\
STACK_ENSURE(1);\
stk->type = (stack_type);\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
STACK_INC;\
} while(0)
@@ -660,6 +1171,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
# define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\
STACK_ENSURE(1);\
stk->type = (stack_type);\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.state.pcode = (pat);\
stk->u.state.pstr = (s);\
stk->u.state.pstr_prev = (sprev);\
@@ -669,6 +1181,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
# define STACK_PUSH_ENSURED(stack_type,pat) do {\
stk->type = (stack_type);\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.state.pcode = (pat);\
STACK_INC;\
} while(0)
@@ -682,9 +1195,133 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev,keep) \
STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev,keep)
+#ifdef USE_CACHE_MATCH_OPT
+
+#define DO_CACHE_MATCH_OPT(reg,stk,repeat_stk,enable,p,num_cache_table,num_cache_size,table,pos,match_cache) do {\
+ if (enable) {\
+ long cache_index = find_cache_index_table((reg), (stk), (repeat_stk), (table), (num_cache_table), (p));\
+ if (cache_index >= 0) {\
+ long key = (num_cache_size) * (long)(pos) + cache_index;\
+ long index = key >> 3;\
+ long mask = 1 << (key & 7);\
+ if ((match_cache)[index] & mask) {\
+ goto fail;\
+ }\
+ (match_cache)[index] |= mask;\
+ }\
+ }\
+} while (0)
+
+static long
+find_cache_index_table(regex_t* reg, OnigStackType *stk, OnigStackIndex *repeat_stk, OnigCacheIndex* table, long num_cache_table, UChar* p)
+{
+ long l = 0, r = num_cache_table - 1, m = 0;
+ OnigCacheIndex* item;
+ OnigRepeatRange* range;
+ OnigStackType *stkp;
+ int count = 0;
+ int is_inc = *p == OP_REPEAT_INC || *p == OP_REPEAT_INC_NG;
+
+ while (l <= r) {
+ m = (l + r) / 2;
+ if (table[m].addr == p) break;
+ if (table[m].addr < p) l = m + 1;
+ else r = m - 1;
+ }
+
+ if (!(0 <= m && m < num_cache_table && table[m].addr == p)) {
+ return -1;
+ }
+
+ item = &table[m];
+ if (item->outer_repeat == -1) {
+ return item->num;
+ }
+
+ range = &reg->repeat_range[item->outer_repeat];
+
+ stkp = &stk[repeat_stk[item->outer_repeat]];
+ count = is_inc ? stkp->u.repeat.count - 1 : stkp->u.repeat.count;
+
+ if (count < range->lower) {
+ return range->base_num + range->inner_num * count + item->num;
+ }
+
+ if (range->upper == 0x7fffffff) {
+ return range->base_num + range->inner_num * (range->lower - (is_inc ? 1 : 0)) + (is_inc ? 0 : 1) + item->num;
+ }
+
+ return range->base_num + range->inner_num * (range->lower - 1) + (range->inner_num + 1) * (count - range->lower + 1) + item->num;
+}
+
+static void
+reset_match_cache(regex_t* reg, UChar* pbegin, UChar* pend, long pos, uint8_t* match_cache, OnigCacheIndex *table, long num_cache_size, long num_cache_table)
+{
+ long l = 0, r = num_cache_table - 1, m1 = 0, m2 = 0;
+ int is_inc = *pend == OP_REPEAT_INC || *pend == OP_REPEAT_INC_NG;
+ OnigCacheIndex *item1, *item2;
+ long k1, k2, base;
+
+ while (l <= r) {
+ m1 = (l + r) / 2;
+ if (table[m1].addr == pbegin) break;
+ if (table[m1].addr < pbegin) l = m1 + 1;
+ else r = m1 - 1;
+ }
+
+ l = 0, r = num_cache_table - 1;
+ while (l <= r) {
+ m2 = (l + r) / 2;
+ if (table[m2].addr == pend) break;
+ if (table[m2].addr < pend) l = m2 + 1;
+ else r = m2 - 1;
+ }
+
+ if (table[m1].addr < pbegin && m1 + 1 < num_cache_table) m1++;
+ if (table[m2].addr > pend && m2 - 1 > 0) m2--;
+
+ item1 = &table[m1];
+ item2 = &table[m2];
+
+ if (item1->outer_repeat < 0) k1 = item1->num;
+ else k1 = reg->repeat_range[item1->outer_repeat].base_num + item1->num;
+
+ if (item2->outer_repeat < 0) k2 = item2->num;
+ else {
+ OnigRepeatRange *range = &reg->repeat_range[item2->outer_repeat];
+ if (range->upper == 0x7fffffff) k2 = range->base_num + range->inner_num * range->lower + (is_inc ? 0 : 1) + item2->num;
+ else k2 = range->base_num + range->inner_num * range->lower + (range->inner_num + 1) * (range->upper - range->lower - (is_inc ? 1 : 0)) + item2->num;
+ }
+
+ base = pos * num_cache_size;
+ k1 += base;
+ k2 += base;
+
+ if ((k1 >> 3) == (k2 >> 3)) {
+ match_cache[k1 >> 3] &= (((1 << (8 - (k2 & 7) - 1)) - 1) << ((k2 & 7) + 1)) | ((1 << (k1 & 7)) - 1);
+ } else {
+ long i = k1 >> 3;
+ if (k1 & 7) {
+ match_cache[k1 >> 3] &= (1 << ((k1 & 7) - 1)) - 1;
+ i++;
+ }
+ if (i < (k2 >> 3)) {
+ xmemset(&match_cache[i], 0, (k2 >> 3) - i);
+ if (k2 & 7) {
+ match_cache[k2 >> 3] &= (((1 << (8 - (k2 & 7) - 1)) - 1) << ((k2 & 7) + 1));
+ }
+ }
+ }
+}
+
+#else
+#define DO_CACHE_MATCH_OPT(reg,stk,repeat_stk,enable,p,num_cache_table,num_cache_size,table,pos,match_cache)
+#endif /* USE_CACHE_MATCH_OPT */
+
#define STACK_PUSH_REPEAT(id, pat) do {\
STACK_ENSURE(1);\
stk->type = STK_REPEAT;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.repeat.num = (id);\
stk->u.repeat.pcode = (pat);\
stk->u.repeat.count = 0;\
@@ -694,6 +1331,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_REPEAT_INC(sindex) do {\
STACK_ENSURE(1);\
stk->type = STK_REPEAT_INC;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.repeat_inc.si = (sindex);\
STACK_INC;\
} while(0)
@@ -701,6 +1339,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_MEM_START(mnum, s) do {\
STACK_ENSURE(1);\
stk->type = STK_MEM_START;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.mem.num = (mnum);\
stk->u.mem.pstr = (s);\
stk->u.mem.start = mem_start_stk[mnum];\
@@ -713,6 +1352,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_MEM_END(mnum, s) do {\
STACK_ENSURE(1);\
stk->type = STK_MEM_END;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.mem.num = (mnum);\
stk->u.mem.pstr = (s);\
stk->u.mem.start = mem_start_stk[mnum];\
@@ -724,6 +1364,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_MEM_END_MARK(mnum) do {\
STACK_ENSURE(1);\
stk->type = STK_MEM_END_MARK;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.mem.num = (mnum);\
STACK_INC;\
} while(0)
@@ -765,6 +1406,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_NULL_CHECK_START(cnum, s) do {\
STACK_ENSURE(1);\
stk->type = STK_NULL_CHECK_START;\
+ stk->null_check = (OnigStackIndex)(stk - stk_base);\
stk->u.null_check.num = (cnum);\
stk->u.null_check.pstr = (s);\
STACK_INC;\
@@ -773,6 +1415,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_NULL_CHECK_END(cnum) do {\
STACK_ENSURE(1);\
stk->type = STK_NULL_CHECK_END;\
+ stk->null_check = (OnigStackIndex)(stk - stk_base);\
stk->u.null_check.num = (cnum);\
STACK_INC;\
} while(0)
@@ -780,6 +1423,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_CALL_FRAME(pat) do {\
STACK_ENSURE(1);\
stk->type = STK_CALL_FRAME;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.call_frame.ret_addr = (pat);\
STACK_INC;\
} while(0)
@@ -787,12 +1431,14 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_PUSH_RETURN do {\
STACK_ENSURE(1);\
stk->type = STK_RETURN;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
STACK_INC;\
} while(0)
#define STACK_PUSH_ABSENT_POS(start, end) do {\
STACK_ENSURE(1);\
stk->type = STK_ABSENT_POS;\
+ stk->null_check = stk == stk_base ? 0 : (stk-1)->null_check;\
stk->u.absent_pos.abs_pstr = (start);\
stk->u.absent_pos.end_pstr = (end);\
STACK_INC;\
@@ -956,7 +1602,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
} while(0)
#define STACK_NULL_CHECK(isnull,id,s) do {\
- OnigStackType* k = stk;\
+ OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
while (1) {\
k--;\
STACK_BASE_CHECK(k, "STACK_NULL_CHECK"); \
@@ -971,7 +1617,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_NULL_CHECK_REC(isnull,id,s) do {\
int level = 0;\
- OnigStackType* k = stk;\
+ OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
while (1) {\
k--;\
STACK_BASE_CHECK(k, "STACK_NULL_CHECK_REC"); \
@@ -990,8 +1636,8 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
}\
} while(0)
-#define STACK_NULL_CHECK_MEMST(isnull,id,s,reg) do {\
- OnigStackType* k = stk;\
+#define STACK_NULL_CHECK_MEMST(isnull,ischange,id,s,reg) do {\
+ OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
while (1) {\
k--;\
STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST"); \
@@ -1007,14 +1653,14 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
while (k < stk) {\
if (k->type == STK_MEM_START) {\
if (k->u.mem.end == INVALID_STACK_INDEX) {\
- (isnull) = 0; break;\
+ (isnull) = 0; (ischange) = 1; break;\
}\
if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\
endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\
else\
endp = (UChar* )k->u.mem.end;\
if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\
- (isnull) = 0; break;\
+ (isnull) = 0; (ischange) = 1; break;\
}\
else if (endp != s) {\
(isnull) = -1; /* empty, but position changed */ \
@@ -1031,7 +1677,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#define STACK_NULL_CHECK_MEMST_REC(isnull,id,s,reg) do {\
int level = 0;\
- OnigStackType* k = stk;\
+ OnigStackType* k = STACK_AT((stk-1)->null_check)+1;\
while (1) {\
k--;\
STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST_REC"); \
@@ -1176,14 +1822,29 @@ static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
# define DATA_ENSURE_CHECK1 (s < right_range)
# define DATA_ENSURE_CHECK(n) (s + (n) <= right_range)
# define DATA_ENSURE(n) if (s + (n) > right_range) goto fail
+# define DATA_ENSURE_CONTINUE(n) if (s + (n) > right_range) continue
# define ABSENT_END_POS right_range
#else
# define DATA_ENSURE_CHECK1 (s < end)
# define DATA_ENSURE_CHECK(n) (s + (n) <= end)
# define DATA_ENSURE(n) if (s + (n) > end) goto fail
+# define DATA_ENSURE_CONTINUE(n) if (s + (n) > end) continue
# define ABSENT_END_POS end
#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
+int onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc);
+
+static inline int
+enclen_approx(OnigEncoding enc, const OnigUChar* p, const OnigUChar* e)
+{
+ if (enc->max_enc_len == enc->min_enc_len) {
+ return (p < e ? enc->min_enc_len : 0);
+ }
+ else {
+ return onigenc_mbclen_approximate(p, e, enc);
+ }
+}
+
#ifdef USE_CAPTURE_HISTORY
static int
@@ -1231,7 +1892,8 @@ make_capture_history_tree(OnigCaptureTreeNode* node, OnigStackType** kp,
#endif /* USE_CAPTURE_HISTORY */
#ifdef USE_BACKREF_WITH_LEVEL
-static int mem_is_in_memp(int mem, int num, UChar* memp)
+static int
+mem_is_in_memp(int mem, int num, UChar* memp)
{
int i;
MemNumType m;
@@ -1442,6 +2104,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
OnigCaseFoldType case_fold_flag = reg->case_fold_flag;
UChar *s, *q, *sbegin;
UChar *p = reg->p;
+ UChar *pbegin = p;
UChar *pkeep;
char *alloca_base;
char *xmalloc_base = NULL;
@@ -1463,7 +2126,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
# define CASE(x) L_##x: sbegin = s; OPCODE_EXEC_HOOK;
# define DEFAULT L_DEFAULT:
# define NEXT sprev = sbegin; JUMP
-# define JUMP RB_GNUC_EXTENSION_BLOCK(goto *oplabels[*p++])
+# define JUMP pbegin = p; RB_GNUC_EXTENSION_BLOCK(goto *oplabels[*p++])
RB_GNUC_EXTENSION static const void *oplabels[] = {
&&L_OP_FINISH, /* matching process terminator (no more alternative) */
@@ -1639,6 +2302,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
# define VM_LOOP \
while (1) { \
OPCODE_EXEC_HOOK; \
+ pbegin = p; \
sbegin = s; \
switch (*p++) {
# define VM_LOOP_END } sprev = sbegin; }
@@ -2031,7 +2695,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
int mb_len;
DATA_ENSURE(1);
- mb_len = enclen(encode, s, end);
+ mb_len = enclen_approx(encode, s, end);
DATA_ENSURE(mb_len);
ss = s;
s += mb_len;
@@ -2136,7 +2800,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR) MOP_IN(OP_ANYCHAR);
DATA_ENSURE(1);
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
DATA_ENSURE(n);
if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
s += n;
@@ -2145,7 +2809,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_ML) MOP_IN(OP_ANYCHAR_ML);
DATA_ENSURE(1);
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
DATA_ENSURE(n);
s += n;
MOP_OUT;
@@ -2153,8 +2817,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_STAR) MOP_IN(OP_ANYCHAR_STAR);
while (DATA_ENSURE_CHECK1) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p, s, sprev, pkeep);
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
DATA_ENSURE(n);
if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
sprev = s;
@@ -2165,8 +2830,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_ML_STAR) MOP_IN(OP_ANYCHAR_ML_STAR);
while (DATA_ENSURE_CHECK1) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p, s, sprev, pkeep);
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
if (n > 1) {
DATA_ENSURE(n);
sprev = s;
@@ -2182,10 +2848,17 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_STAR_PEEK_NEXT) MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
while (DATA_ENSURE_CHECK1) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, end - s, msa->match_cache);
if (*p == *s) {
STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
+ } else {
+ /* We need to increment num_fail here, for invoking a cache optimization correctly. */
+ /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR` simply in this case.*/
+#ifdef USE_CACHE_MATCH_OPT
+ msa->num_fail++;
+#endif
}
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
DATA_ENSURE(n);
if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
sprev = s;
@@ -2197,10 +2870,17 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_ML_STAR_PEEK_NEXT)MOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);
while (DATA_ENSURE_CHECK1) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
if (*p == *s) {
STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
+ } else {
+ /* We need to increment num_fail here, for invoking a cache optimization correctly. */
+ /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR_ML` simply in this case.*/
+#ifdef USE_CACHE_MATCH_OPT
+ msa->num_fail++;
+#endif
}
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
if (n > 1) {
DATA_ENSURE(n);
sprev = s;
@@ -2223,7 +2903,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
if (scv) goto fail;
STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
DATA_ENSURE(n);
if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
sprev = s;
@@ -2241,7 +2921,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
if (scv) goto fail;
STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
- n = enclen(encode, s, end);
+ n = enclen_approx(encode, s, end);
if (n > 1) {
DATA_ENSURE(n);
sprev = s;
@@ -2528,8 +3208,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_MEMORY_END_PUSH_REC) MOP_IN(OP_MEMORY_END_PUSH_REC);
GET_MEMNUM_INC(mem, p);
STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */
- STACK_PUSH_MEM_END(mem, s);
mem_start_stk[mem] = GET_STACK_INDEX(stkp);
+ STACK_PUSH_MEM_END(mem, s);
MOP_OUT;
JUMP;
@@ -2583,7 +3263,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
DATA_ENSURE(n);
sprev = s;
STRING_CMP(pstart, s, n);
- while (sprev + (len = enclen(encode, sprev, end)) < s)
+ while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
sprev += len;
MOP_OUT;
@@ -2613,8 +3293,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
n = pend - pstart;
DATA_ENSURE(n);
sprev = s;
- STRING_CMP_IC(case_fold_flag, pstart, &s, (int)n, end);
- while (sprev + (len = enclen(encode, sprev, end)) < s)
+ STRING_CMP_IC(case_fold_flag, pstart, &s, n, end);
+ while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
sprev += len;
MOP_OUT;
@@ -2643,13 +3323,13 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
? STACK_AT(mem_end_stk[mem])->u.mem.pstr
: (UChar* )((void* )mem_end_stk[mem]));
n = pend - pstart;
- DATA_ENSURE(n);
+ DATA_ENSURE_CONTINUE(n);
sprev = s;
swork = s;
STRING_CMP_VALUE(pstart, swork, n, is_fail);
if (is_fail) continue;
s = swork;
- while (sprev + (len = enclen(encode, sprev, end)) < s)
+ while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
sprev += len;
p += (SIZE_MEMNUM * (tlen - i - 1));
@@ -2682,7 +3362,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
? STACK_AT(mem_end_stk[mem])->u.mem.pstr
: (UChar* )((void* )mem_end_stk[mem]));
n = pend - pstart;
- DATA_ENSURE(n);
+ DATA_ENSURE_CONTINUE(n);
sprev = s;
swork = s;
STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
@@ -2784,9 +3464,10 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_NULL_CHECK_END_MEMST) MOP_IN(OP_NULL_CHECK_END_MEMST);
{
int isnull;
+ int ischanged = 0; // set 1 when a loop is empty but memory status is changed.
GET_MEMNUM_INC(mem, p); /* mem: null check id */
- STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
+ STACK_NULL_CHECK_MEMST(isnull, ischanged, mem, s, reg);
if (isnull) {
# ifdef ONIG_DEBUG_MATCH
fprintf(stderr, "NULL_CHECK_END_MEMST: skip id:%d, s:%"PRIuPTR" (%p)\n",
@@ -2795,6 +3476,29 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
if (isnull == -1) goto fail;
goto null_check_found;
}
+# ifdef USE_CACHE_MATCH_OPT
+ if (ischanged && msa->enable_cache_match_opt) {
+ RelAddrType rel;
+ OnigUChar *addr;
+ MemNumType mem;
+ UChar* tmp = p;
+ switch (*tmp++) {
+ case OP_JUMP:
+ case OP_PUSH:
+ GET_RELADDR_INC(rel, tmp);
+ addr = tmp + rel;
+ break;
+ case OP_REPEAT_INC:
+ case OP_REPEAT_INC_NG:
+ GET_MEMNUM_INC(mem, tmp);
+ addr = STACK_AT(repeat_stk[mem])->u.repeat.pcode;
+ break;
+ default:
+ goto unexpected_bytecode_error;
+ }
+ reset_match_cache(reg, addr, pbegin, (long)(s - str), msa->match_cache, msa->cache_index_table, msa->num_cache_opcode, msa->num_cache_table);
+ }
+# endif
}
MOP_OUT;
JUMP;
@@ -2837,6 +3541,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_PUSH) MOP_IN(OP_PUSH);
GET_RELADDR_INC(addr, p);
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
MOP_OUT;
JUMP;
@@ -2877,6 +3582,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_POP) MOP_IN(OP_POP);
STACK_POP_ONE;
+ /* We need to increment num_fail here, for invoking a cache optimization correctly, */
+ /* because Onigmo makes a loop, which is pairwise disjoint to the following set, as atomic. */
+#ifdef USE_CACHE_MATCH_OPT
+ msa->num_fail++;
+#endif
MOP_OUT;
JUMP;
@@ -2885,6 +3595,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_RELADDR_INC(addr, p);
if (*p == *s && DATA_ENSURE_CHECK1) {
p++;
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
MOP_OUT;
JUMP;
@@ -2898,6 +3609,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_RELADDR_INC(addr, p);
if (*p == *s) {
p++;
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
MOP_OUT;
JUMP;
@@ -2916,6 +3628,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
STACK_PUSH_REPEAT(mem, p);
if (reg->repeat_range[mem].lower == 0) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, end - s, msa->match_cache);
STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
}
}
@@ -2932,6 +3645,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
STACK_PUSH_REPEAT(mem, p);
if (reg->repeat_range[mem].lower == 0) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
STACK_PUSH_ALT(p, s, sprev, pkeep);
p += addr;
}
@@ -2950,6 +3664,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
/* end of repeat. Nothing to do. */
}
else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
+ if (*pbegin == OP_REPEAT_INC) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
+ }
STACK_PUSH_ALT(p, s, sprev, pkeep);
p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
}
@@ -2980,6 +3697,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
UChar* pcode = stkp->u.repeat.pcode;
STACK_PUSH_REPEAT_INC(si);
+ if (*pbegin == OP_REPEAT_INC_NG) {
+ DO_CACHE_MATCH_OPT(reg, stk_base, repeat_stk, msa->enable_cache_match_opt, pbegin, msa->num_cache_table, msa->num_cache_opcode, msa->cache_index_table, s - str, msa->match_cache);
+ }
STACK_PUSH_ALT(pcode, s, sprev, pkeep);
}
else {
@@ -3100,6 +3820,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
DATA_ENSURE(0);
p += addr;
}
+ else if (s == end) {
+ /* At the end of the string, just match with it */
+ DATA_ENSURE(0);
+ p += addr;
+ }
else {
STACK_PUSH_ALT(p + addr, s, sprev, pkeep); /* Push possible point. */
n = enclen(encode, s, end);
@@ -3167,6 +3892,49 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
sprev = stk->u.state.pstr_prev;
pkeep = stk->u.state.pkeep;
+#ifdef USE_CACHE_MATCH_OPT
+ if (++msa->num_fail >= (long)(end - str) + 1 && msa->num_cache_opcode == NUM_CACHE_OPCODE_UNINIT) {
+ msa->enable_cache_match_opt = 1;
+ if (msa->num_cache_opcode == NUM_CACHE_OPCODE_UNINIT) {
+ OnigPosition r = count_num_cache_opcode(reg, &msa->num_cache_opcode, &msa->num_cache_table);
+ if (r < 0) goto bytecode_error;
+ }
+ if (msa->num_cache_opcode == NUM_CACHE_OPCODE_FAIL || msa->num_cache_opcode == 0) {
+ msa->enable_cache_match_opt = 0;
+ goto fail_match_cache_opt;
+ }
+ if (msa->cache_index_table == NULL) {
+ OnigCacheIndex *table = (OnigCacheIndex *)xmalloc(msa->num_cache_table * sizeof(OnigCacheIndex));
+ if (table == NULL) {
+ return ONIGERR_MEMORY;
+ }
+ OnigPosition r = init_cache_index_table(reg, table);
+ if (r < 0) {
+ if (r == ONIGERR_UNEXPECTED_BYTECODE) goto unexpected_bytecode_error;
+ else goto bytecode_error;
+ }
+ msa->cache_index_table = table;
+ }
+ size_t len = (end - str) + 1;
+ size_t match_cache_size8 = (size_t)msa->num_cache_opcode * len;
+ /* overflow check */
+ if (match_cache_size8 / len != (size_t)msa->num_cache_opcode) {
+ return ONIGERR_MEMORY;
+ }
+ /* Currently, int is used for the key of match_cache */
+ if (match_cache_size8 >= LONG_MAX_LIMIT) {
+ return ONIGERR_MEMORY;
+ }
+ size_t match_cache_size = (match_cache_size8 >> 3) + (match_cache_size8 & 7 ? 1 : 0);
+ msa->match_cache = (uint8_t*)xmalloc(match_cache_size * sizeof(uint8_t));
+ if (msa->match_cache == NULL) {
+ return ONIGERR_MEMORY;
+ }
+ xmemset(msa->match_cache, 0, match_cache_size * sizeof(uint8_t));
+ }
+ fail_match_cache_opt:
+#endif
+
#ifdef USE_COMBINATION_EXPLOSION_CHECK
if (stk->u.state.state_check != 0) {
stk->type = STK_STATE_CHECK_MARK;
@@ -3175,6 +3943,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
#endif
MOP_OUT;
+ CHECK_INTERRUPT_IN_MATCH_AT;
JUMP;
DEFAULT
@@ -3902,12 +4671,17 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
UChar* range, UChar** low, UChar** high, UChar** low_prev)
{
UChar *p, *pprev = (UChar* )NULL;
+ size_t input_len = end - str;
#ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "forward_search_range: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), s: %"PRIuPTR" (%p), range: %"PRIuPTR" (%p)\n",
(uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )s, s, (uintptr_t )range, range);
#endif
+ if (reg->dmin > input_len) {
+ return 0;
+ }
+
p = s;
if (reg->dmin > 0) {
if (ONIGENC_IS_SINGLEBYTE(reg->enc)) {
@@ -4044,6 +4818,11 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
UChar** low, UChar** high)
{
UChar *p;
+ size_t input_len = end - str;
+
+ if (reg->dmin > input_len) {
+ return 0;
+ }
range += reg->dmin;
p = s;
diff --git a/regint.h b/regint.h
index 0740429688..cee766ad6e 100644
--- a/regint.h
+++ b/regint.h
@@ -41,6 +41,14 @@
/* for byte-code statistical data. */
/* #define ONIG_DEBUG_STATISTICS */
+/* enable matching optimization by using cache. */
+#define USE_CACHE_MATCH_OPT
+
+#ifdef USE_CACHE_MATCH_OPT
+# define NUM_CACHE_OPCODE_FAIL -1
+# define NUM_CACHE_OPCODE_UNINIT -2
+#endif
+
#if defined(ONIG_DEBUG_PARSE_TREE) || defined(ONIG_DEBUG_MATCH) || \
defined(ONIG_DEBUG_SEARCH) || defined(ONIG_DEBUG_COMPILE) || \
defined(ONIG_DEBUG_STATISTICS) || defined(ONIG_DEBUG_MEMLEAK)
@@ -49,10 +57,11 @@
# endif
#endif
+/* __POWERPC__ added to accommodate Darwin case. */
#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(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
defined(__mc68020__)
# define UNALIGNED_WORD_ACCESS 1
# else
@@ -148,7 +157,14 @@
#ifdef RUBY
-# define CHECK_INTERRUPT_IN_MATCH_AT rb_thread_check_ints()
+# define CHECK_INTERRUPT_IN_MATCH_AT do { \
+ msa->counter++; \
+ if (msa->counter >= 128) { \
+ msa->counter = 0; \
+ rb_reg_check_timeout(reg, &msa->end_time); \
+ rb_thread_check_ints(); \
+ } \
+} while(0)
# define onig_st_init_table st_init_table
# define onig_st_init_table_with_size st_init_table_with_size
# define onig_st_init_numtable st_init_numtable
@@ -303,9 +319,13 @@ RUBY_SYMBOL_EXPORT_BEGIN
#define ONIG_LAST_CODE_POINT (~((OnigCodePoint )0))
+#define PLATFORM_GET_INC_ARGUMENTS_ASSERT(val, type) \
+ ((void)sizeof(char[2 * (sizeof(val) == sizeof(type)) - 1]))
+
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
# define PLATFORM_GET_INC(val,p,type) do{\
+ PLATFORM_GET_INC_ARGUMENTS_ASSERT(val, type);\
val = *(type* )p;\
(p) += sizeof(type);\
} while(0)
@@ -313,7 +333,10 @@ RUBY_SYMBOL_EXPORT_BEGIN
#else
# define PLATFORM_GET_INC(val,p,type) do{\
- xmemcpy(&val, (p), sizeof(type));\
+ PLATFORM_GET_INC_ARGUMENTS_ASSERT(val, type);\
+ type platform_get_value;\
+ xmemcpy(&platform_get_value, (p), sizeof(type));\
+ val = platform_get_value;\
(p) += sizeof(type);\
} while(0)
@@ -371,6 +394,7 @@ typedef unsigned int BitStatusType;
#define INT_MAX_LIMIT ((1UL << (SIZEOF_INT * 8 - 1)) - 1)
+#define LONG_MAX_LIMIT ((1UL << (SIZEOF_LONG * 8 - 1)) - 1)
#define DIGITVAL(code) ((code) - '0')
#define ODIGITVAL(code) DIGITVAL(code)
@@ -812,6 +836,7 @@ typedef intptr_t OnigStackIndex;
typedef struct _OnigStackType {
unsigned int type;
+ OnigStackIndex null_check;
union {
struct {
UChar *pcode; /* byte code position */
@@ -855,6 +880,14 @@ typedef struct _OnigStackType {
} u;
} OnigStackType;
+#ifdef USE_CACHE_MATCH_OPT
+typedef struct {
+ UChar *addr;
+ long num;
+ int outer_repeat;
+} OnigCacheIndex;
+#endif
+
typedef struct {
void* stack_p;
size_t stack_n;
@@ -870,6 +903,21 @@ typedef struct {
void* state_check_buff;
int state_check_buff_size;
#endif
+ int counter;
+ /* rb_hrtime_t from hrtime.h */
+#ifdef MY_RUBY_BUILD_MAY_TIME_TRAVEL
+ int128_t end_time;
+#else
+ uint64_t end_time;
+#endif
+#ifdef USE_CACHE_MATCH_OPT
+ long num_fail;
+ int enable_cache_match_opt;
+ long num_cache_opcode;
+ long num_cache_table;
+ OnigCacheIndex* cache_index_table;
+ uint8_t* match_cache;
+#endif
} OnigMatchArg;
@@ -903,9 +951,13 @@ extern void onig_print_statistics(FILE* f);
# endif
#endif
+#ifndef PRINTF_ARGS
+#define PRINTF_ARGS(func, fmt, vargs) func
+#endif
+
extern UChar* onig_error_code_to_format(OnigPosition code);
-extern void onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const UChar *fmt, va_list args);
-extern void onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const UChar *fmt, ...);
+PRINTF_ARGS(extern void onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const char *fmt, va_list args), 6, 0);
+PRINTF_ARGS(extern void onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const char *fmt, ...), 6, 7);
extern int onig_bbuf_init(BBuf* buf, OnigDistance size);
extern int onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigErrorInfo* einfo);
#ifdef RUBY
@@ -931,6 +983,7 @@ extern int onig_st_insert_strend(hash_table_type* table, const UChar* str_key, c
#ifdef RUBY
extern size_t onig_memsize(const regex_t *reg);
extern size_t onig_region_memsize(const struct re_registers *regs);
+void rb_reg_check_timeout(regex_t *reg, void *end_time);
#endif
RUBY_SYMBOL_EXPORT_END
diff --git a/regparse.c b/regparse.c
index 24ff5b9a18..33df0e06c7 100644
--- a/regparse.c
+++ b/regparse.c
@@ -28,8 +28,16 @@
* SUCH DAMAGE.
*/
+// Suppress some false-positive compiler warnings
+#if defined(__GNUC__) && __GNUC__ >= 12
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wrestrict"
+#endif
+
#include "regparse.h"
#include <stdarg.h>
+#include "internal/sanitizers.h"
#define WARN_BUFSIZE 256
@@ -387,6 +395,8 @@ str_end_cmp(st_data_t xp, st_data_t yp)
return 0;
}
+NO_SANITIZE("unsigned-integer-overflow", static st_index_t str_end_hash(st_data_t xp));
+
static st_index_t
str_end_hash(st_data_t xp)
{
@@ -2833,6 +2843,10 @@ fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,
#endif /* USE_NAMED_GROUP */
+#ifdef PRINTF_ARGS
+PRINTF_ARGS(static void onig_syntax_warn(ScanEnv *env, const char *fmt, ...), 2, 3);
+#endif
+
static void
onig_syntax_warn(ScanEnv *env, const char *fmt, ...)
{
@@ -2841,7 +2855,7 @@ onig_syntax_warn(ScanEnv *env, const char *fmt, ...)
va_start(args, fmt);
onig_vsnprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
env->pattern, env->pattern_end,
- (const UChar *)fmt, args);
+ fmt, args);
va_end(args);
#ifdef RUBY
if (env->sourcefile == NULL)
@@ -5963,7 +5977,8 @@ node_extended_grapheme_cluster(Node** np, ScanEnv* env)
R_ERR(add_code_range(&(cc->mbuf), env, 0x000A, 0x000A)); /* CR */
R_ERR(add_code_range(&(cc->mbuf), env, 0x000D, 0x000D)); /* LF */
R_ERR(not_code_range_buf(env->enc, cc->mbuf, &inverted_buf, env));
- cc->mbuf = inverted_buf; /* TODO: check what to do with buffer before inversion */
+ bbuf_free(cc->mbuf);
+ cc->mbuf = inverted_buf;
env->warnings_flag &= dup_not_warned; /* TODO: fix false warning */
}
diff --git a/ruby-runner.c b/ruby-runner.c
index b756c219fa..e1a53d5236 100644
--- a/ruby-runner.c
+++ b/ruby-runner.c
@@ -24,29 +24,29 @@ insert_env_path(const char *envname, const char *paths, size_t size, int prepend
size_t n = 0;
if (env) {
- while ((c = *env) == PATH_SEP) ++env;
- n = strlen(env);
- while (n > 0 && env[n-1] == PATH_SEP) --n;
+ while ((c = *env) == PATH_SEP) ++env;
+ n = strlen(env);
+ while (n > 0 && env[n-1] == PATH_SEP) --n;
}
if (c) {
- char *e = malloc(size+n+1);
- size_t pos = 0;
- if (prepend) {
- memcpy(e, paths, pos = size-1);
- e[pos++] = PATH_SEP;
- }
- memcpy(e+pos, env, n);
- pos += n;
- if (!prepend) {
- e[pos++] = PATH_SEP;
- memcpy(e+pos, paths, size-1);
- pos += size-1;
- }
- e[pos] = '\0';
- env = e;
+ char *e = malloc(size+n+1);
+ size_t pos = 0;
+ if (prepend) {
+ memcpy(e, paths, pos = size-1);
+ e[pos++] = PATH_SEP;
+ }
+ memcpy(e+pos, env, n);
+ pos += n;
+ if (!prepend) {
+ e[pos++] = PATH_SEP;
+ memcpy(e+pos, paths, size-1);
+ pos += size-1;
+ }
+ e[pos] = '\0';
+ env = e;
}
else {
- env = paths;
+ env = paths;
}
setenv(envname, env, 1);
}
@@ -58,12 +58,12 @@ main(int argc, char **argv)
static const char builddir[] = BUILDDIR;
static const char rubypath[] = BUILDDIR"/"STRINGIZE(RUBY_INSTALL_NAME);
static const char rubylib[] =
- ABS_SRCDIR"/lib"
- PATH_SEPARATOR
- EXTOUT_DIR"/common"
- PATH_SEPARATOR
- EXTOUT_DIR"/"ARCH
- ;
+ ABS_SRCDIR"/lib"
+ PATH_SEPARATOR
+ EXTOUT_DIR"/common"
+ PATH_SEPARATOR
+ EXTOUT_DIR"/"ARCH
+ ;
#ifndef LOAD_RELATIVE
static const char mjit_build_dir[] = BUILDDIR"/mjit_build_dir."SOEXT;
struct stat stbuf;
@@ -84,9 +84,9 @@ main(int argc, char **argv)
if (!(p = strrchr(arg0, '/'))) p = arg0; else p++;
if (strlen(p) < namesize - 1) {
- argv[0] = malloc(p - arg0 + namesize);
- memcpy(argv[0], arg0, p - arg0);
- p = argv[0] + (p - arg0);
+ argv[0] = malloc(p - arg0 + namesize);
+ memcpy(argv[0], arg0, p - arg0);
+ p = argv[0] + (p - arg0);
}
memcpy(p, rubyname, namesize);
diff --git a/ruby.c b/ruby.c
index a845a812d9..09c81db86c 100644
--- a/ruby.c
+++ b/ruby.c
@@ -22,11 +22,7 @@
# include <sys/cygwin.h>
#endif
-#ifdef __hpux
-# include <sys/pstat.h>
-#endif
-
-#if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
+#if (defined(LOAD_RELATIVE) || defined(__MACH__)) && defined(HAVE_DLADDR)
# include <dlfcn.h>
#endif
@@ -47,6 +43,8 @@
#include "dln.h"
#include "eval_intern.h"
#include "internal.h"
+#include "internal/cmdlineopt.h"
+#include "internal/cont.h"
#include "internal/error.h"
#include "internal/file.h"
#include "internal/inits.h"
@@ -58,13 +56,16 @@
#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"
+#define singlebit_only_p(x) !((x) & ((x)-1))
+STATIC_ASSERT(Qnil_1bit_from_Qfalse, singlebit_only_p(Qnil^Qfalse));
+STATIC_ASSERT(Qundef_1bit_from_Qnil, singlebit_only_p(Qundef^Qnil));
+
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
@@ -72,7 +73,7 @@
# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#endif
-void Init_ruby_description(void);
+void Init_ruby_description(ruby_cmdline_options_t *opt);
#ifndef HAVE_STDLIB_H
char *getenv();
@@ -98,11 +99,15 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits);
SEP \
X(did_you_mean) \
SEP \
+ X(syntax_suggest) \
+ SEP \
X(rubyopt) \
SEP \
X(frozen_string_literal) \
SEP \
- X(jit) \
+ X(mjit) \
+ SEP \
+ X(yjit) \
/* END OF FEATURES */
#define EACH_DEBUG_FEATURES(X, SEP) \
X(frozen_string_literal) \
@@ -113,11 +118,20 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits);
enum feature_flag_bits {
EACH_FEATURES(DEFINE_FEATURE, COMMA),
feature_debug_flag_first,
+#if defined(MJIT_FORCE_ENABLE) || !USE_YJIT
+ DEFINE_FEATURE(jit) = feature_mjit,
+#else
+ DEFINE_FEATURE(jit) = feature_yjit,
+#endif
+ feature_jit_mask = FEATURE_BIT(mjit) | FEATURE_BIT(yjit),
+
feature_debug_flag_begin = feature_debug_flag_first - 1,
EACH_DEBUG_FEATURES(DEFINE_DEBUG_FEATURE, COMMA),
feature_flag_count
};
+#define MULTI_BITS_P(bits) ((bits) & ((bits) - 1))
+
#define DEBUG_BIT(bit) (1U << feature_debug_##bit)
#define DUMP_BIT(bit) (1U << dump_##bit)
@@ -140,22 +154,21 @@ enum feature_flag_bits {
X(parsetree_with_comment) \
SEP \
X(insns) \
+ SEP \
+ X(insns_without_opt) \
/* END OF DUMPS */
enum dump_flag_bits {
dump_version_v,
+ dump_error_tolerant,
EACH_DUMPS(DEFINE_DUMP, COMMA),
+ dump_error_tolerant_bits = (DUMP_BIT(yydebug) |
+ DUMP_BIT(parsetree) |
+ DUMP_BIT(parsetree_with_comment)),
dump_exit_bits = (DUMP_BIT(yydebug) | DUMP_BIT(syntax) |
- DUMP_BIT(parsetree) | DUMP_BIT(parsetree_with_comment) |
- DUMP_BIT(insns))
+ DUMP_BIT(parsetree) | DUMP_BIT(parsetree_with_comment) |
+ DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))
};
-typedef struct ruby_cmdline_options ruby_cmdline_options_t;
-
-typedef struct {
- unsigned int mask;
- unsigned int set;
-} ruby_features_t;
-
static inline void
rb_feature_set_to(ruby_features_t *feat, unsigned int bit_mask, unsigned int bit_set)
{
@@ -167,35 +180,9 @@ rb_feature_set_to(ruby_features_t *feat, unsigned int bit_mask, unsigned int bit
rb_feature_set_to(&(feat), bit_mask, bit_set)
#define FEATURE_SET(feat, bits) FEATURE_SET_TO(feat, bits, bits)
#define FEATURE_SET_RESTORE(feat, save) FEATURE_SET_TO(feat, (save).mask, (save).set & (save).mask)
-#define FEATURE_SET_P(feat, bits) ((feat).set & (bits))
-
-struct ruby_cmdline_options {
- const char *script;
- VALUE script_name;
- VALUE e_script;
- struct {
- struct {
- VALUE name;
- int index;
- } enc;
- } src, ext, intern;
- VALUE req_list;
- ruby_features_t features;
- ruby_features_t warn;
- unsigned int dump;
-#if USE_MJIT
- struct mjit_options mjit;
-#endif
- int sflag, xflag;
- unsigned int warning: 1;
- unsigned int verbose: 1;
- unsigned int do_loop: 1;
- unsigned int do_print: 1;
- unsigned int do_line: 1;
- unsigned int do_split: 1;
- unsigned int do_search: 1;
- unsigned int setids: 2;
-};
+#define FEATURE_SET_P(feat, bits) ((feat).set & FEATURE_BIT(bits))
+#define FEATURE_USED_P(feat, bits) ((feat).mask & FEATURE_BIT(bits))
+#define FEATURE_SET_BITS(feat) ((feat).set & (feat).mask)
static void init_ids(ruby_cmdline_options_t *);
@@ -203,18 +190,18 @@ static void init_ids(ruby_cmdline_options_t *);
enum {
COMPILATION_FEATURES = (
- 0
- | FEATURE_BIT(frozen_string_literal)
- | FEATURE_BIT(debug_frozen_string_literal)
- ),
+ 0
+ | FEATURE_BIT(frozen_string_literal)
+ | FEATURE_BIT(debug_frozen_string_literal)
+ ),
DEFAULT_FEATURES = (
- (FEATURE_BIT(debug_flag_first)-1)
+ (FEATURE_BIT(debug_flag_first)-1)
#if DISABLE_RUBYGEMS
- & ~FEATURE_BIT(gems)
+ & ~FEATURE_BIT(gems)
#endif
- & ~FEATURE_BIT(frozen_string_literal)
- & ~FEATURE_BIT(jit)
- )
+ & ~FEATURE_BIT(frozen_string_literal)
+ & ~feature_jit_mask
+ )
};
static ruby_cmdline_options_t *
@@ -227,13 +214,16 @@ cmdline_options_init(ruby_cmdline_options_t *opt)
opt->intern.enc.index = -1;
opt->features.set = DEFAULT_FEATURES;
#ifdef MJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DMJIT_FORCE_ENABLE" */
- opt->features.set |= FEATURE_BIT(jit);
+ opt->features.set |= FEATURE_BIT(mjit);
+#elif defined(YJIT_FORCE_ENABLE)
+ opt->features.set |= FEATURE_BIT(yjit);
#endif
+
return opt;
}
static rb_ast_t *load_file(VALUE parser, VALUE fname, VALUE f, int script,
- ruby_cmdline_options_t *opt);
+ ruby_cmdline_options_t *opt);
static VALUE open_load_file(VALUE fname_v, int *xflag);
static void forbid_setid(const char *, const ruby_cmdline_options_t *);
#define forbid_setid(s) forbid_setid((s), opt)
@@ -255,10 +245,10 @@ show_usage_line(const char *str, unsigned int namelen, unsigned int secondlen, i
const char *se = highlight ? esc_reset : esc_none;
const int wrap = help && namelen + secondlen - 1 > w;
printf(" %s%.*s%-*.*s%s%-*s%s\n", sb, namelen-1, str,
- (wrap ? 0 : w - namelen + 1),
- (help ? secondlen-1 : 0), str + namelen, se,
- (wrap ? w + 3 : 0), (wrap ? "\n" : ""),
- str + namelen + secondlen);
+ (wrap ? 0 : w - namelen + 1),
+ (help ? secondlen-1 : 0), str + namelen, se,
+ (wrap ? w + 3 : 0), (wrap ? "\n" : ""),
+ str + namelen + secondlen);
}
static void
@@ -267,80 +257,93 @@ 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? */
- struct message {
- const char *str;
- unsigned short namelen, secondlen;
- };
-#define M(shortopt, longopt, desc) { \
- shortopt " " longopt " " desc, \
- (unsigned short)sizeof(shortopt), \
- (unsigned short)sizeof(longopt), \
-}
- static const struct message usage_msg[] = {
- M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
- M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
- M("-c", "", "check syntax only"),
- M("-Cdirectory", "", "cd to directory before executing your script"),
- M("-d", ", --debug", "set debugging flags (set $DEBUG to true)"),
- M("-e 'command'", "", "one line of script. Several -e's allowed. Omit [programfile]"),
- M("-Eex[:in]", ", --encoding=ex[:in]", "specify the default external and internal character encodings"),
- M("-Fpattern", "", "split() pattern for autosplit (-a)"),
- M("-i[extension]", "", "edit ARGV files in place (make backup if extension supplied)"),
- M("-Idirectory", "", "specify $LOAD_PATH directory (may be used more than once)"),
- M("-l", "", "enable line ending processing"),
- M("-n", "", "assume 'while gets(); ... end' loop around your script"),
- M("-p", "", "assume loop like -n but print line also like sed"),
- M("-rlibrary", "", "require the library before executing your script"),
- M("-s", "", "enable some switch parsing for switches after script name"),
- M("-S", "", "look for the script using PATH environment variable"),
- M("-v", "", "print the version number, then turn on verbose mode"),
- M("-w", "", "turn warnings on for your script"),
- M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"),
- M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"),
- M("--jit", "", "enable JIT with default options (experimental)"),
- M("--jit-[option]","", "enable JIT with an option (experimental)"),
- M("-h", "", "show this message, --help for more info"),
+#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
+
+#if USE_YJIT
+# define PLATFORM_JIT_OPTION "--yjit"
+#else
+# define PLATFORM_JIT_OPTION "--mjit (experimental)"
+#endif
+ static const struct ruby_opt_message usage_msg[] = {
+ M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
+ M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
+ M("-c", "", "check syntax only"),
+ M("-Cdirectory", "", "cd to directory before executing your script"),
+ M("-d", ", --debug", "set debugging flags (set $DEBUG to true)"),
+ M("-e 'command'", "", "one line of script. Several -e's allowed. Omit [programfile]"),
+ M("-Eex[:in]", ", --encoding=ex[:in]", "specify the default external and internal character encodings"),
+ M("-Fpattern", "", "split() pattern for autosplit (-a)"),
+ M("-i[extension]", "", "edit ARGV files in place (make backup if extension supplied)"),
+ M("-Idirectory", "", "specify $LOAD_PATH directory (may be used more than once)"),
+ M("-l", "", "enable line ending processing"),
+ M("-n", "", "assume 'while gets(); ... end' loop around your script"),
+ M("-p", "", "assume loop like -n but print line also like sed"),
+ M("-rlibrary", "", "require the library before executing your script"),
+ M("-s", "", "enable some switch parsing for switches after script name"),
+ M("-S", "", "look for the script using PATH environment variable"),
+ M("-v", "", "print the version number, then turn on verbose mode"),
+ M("-w", "", "turn warnings on for your script"),
+ M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"),
+ M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"),
+ M("--jit", "", "enable JIT for the platform, same as " PLATFORM_JIT_OPTION),
+#if USE_MJIT
+ M("--mjit", "", "enable C compiler-based JIT compiler (experimental)"),
+#endif
+#if USE_YJIT
+ M("--yjit", "", "enable in-process JIT compiler"),
+#endif
+ M("-h", "", "show this message, --help for more info"),
};
- static const struct message help_msg[] = {
- M("--copyright", "", "print the copyright"),
- M("--dump={insns|parsetree|...}[,...]", "",
+ static const struct ruby_opt_message help_msg[] = {
+ M("--copyright", "", "print the copyright"),
+ M("--dump={insns|parsetree|...}[,...]", "",
"dump debug information. see below for available dump list"),
- M("--enable={jit|rubyopt|...}[,...]", ", --disable={jit|rubyopt|...}[,...]",
- "enable or disable features. see below for available features"),
- M("--external-encoding=encoding", ", --internal-encoding=encoding",
- "specify the default external or internal character encoding"),
- M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
- M("--verbose", "", "turn on verbose mode and disable script from stdin"),
- M("--version", "", "print the version number, then exit"),
- M("--help", "", "show this message, -h for short message"),
+ M("--enable={jit|rubyopt|...}[,...]", ", --disable={jit|rubyopt|...}[,...]",
+ "enable or disable features. see below for available features"),
+ M("--external-encoding=encoding", ", --internal-encoding=encoding",
+ "specify the default external or internal character encoding"),
+ M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
+ M("--verbose", "", "turn on verbose mode and disable script from stdin"),
+ M("--version", "", "print the version number, then exit"),
+ M("--help", "", "show this message, -h for short message"),
};
- static const struct message dumps[] = {
- M("insns", "", "instruction sequences"),
- M("yydebug", "", "yydebug of yacc parser generator"),
- M("parsetree", "", "AST"),
- M("parsetree_with_comment", "", "AST with comments"),
+ static const struct ruby_opt_message dumps[] = {
+ M("insns", "", "instruction sequences"),
+ M("insns_without_opt", "", "instruction sequences compiled with no optimization"),
+ M("yydebug(+error-tolerant)", "", "yydebug of yacc parser generator"),
+ M("parsetree(+error-tolerant)","", "AST"),
+ M("parsetree_with_comment(+error-tolerant)", "", "AST with comments"),
};
- static const struct message features[] = {
- M("gems", "", "rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")"),
- M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED")"),
- M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")"),
- M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"),
- M("frozen-string-literal", "", "freeze all string literals (default: disabled)"),
- M("jit", "", "JIT compiler (default: disabled)"),
+ static const struct ruby_opt_message features[] = {
+ M("gems", "", "rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")"),
+ M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED")"),
+ M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")"),
+ M("syntax_suggest", "", "syntax_suggest (default: "DEFAULT_RUBYGEMS_ENABLED")"),
+ M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"),
+ M("frozen-string-literal", "", "freeze all string literals (default: disabled)"),
+#if USE_MJIT
+ M("mjit", "", "C compiler-based JIT compiler (default: disabled)"),
+#endif
+#if USE_YJIT
+ M("yjit", "", "in-process JIT compiler (default: disabled)"),
+#endif
};
- static const struct message warn_categories[] = {
+ static const struct ruby_opt_message warn_categories[] = {
M("deprecated", "", "deprecated features"),
M("experimental", "", "experimental features"),
};
- static const struct message mjit_options[] = {
- M("--jit-warnings", "", "Enable printing JIT warnings"),
- M("--jit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
- M("--jit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
- M("--jit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
- M("--jit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
- M("--jit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"),
- M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
+#if USE_MJIT
+ extern const struct ruby_opt_message mjit_option_messages[];
+#endif
+#if USE_YJIT
+ static const struct ruby_opt_message yjit_options[] = {
+ M("--yjit-stats", "", "Enable collecting YJIT statistics"),
+ M("--yjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: 64)"),
+ M("--yjit-call-threshold=num", "", "Number of calls to trigger JIT (default: 10)"),
+ M("--yjit-max-versions=num", "", "Maximum number of versions per basic block (default: 4)"),
+ M("--yjit-greedy-versioning", "", "Greedy versioning mode (default: disabled)"),
};
+#endif
int i;
const char *sb = highlight ? esc_standout+1 : esc_none;
const char *se = highlight ? esc_reset : esc_none;
@@ -350,26 +353,33 @@ usage(const char *name, int help, int highlight, int columns)
printf("%sUsage:%s %s [switches] [--] [programfile] [arguments]\n", sb, se, name);
for (i = 0; i < num; ++i)
- SHOW(usage_msg[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]);
+ SHOW(help_msg[i]);
printf("%s""Dump List:%s\n", sb, se);
for (i = 0; i < numberof(dumps); ++i)
- SHOW(dumps[i]);
+ SHOW(dumps[i]);
printf("%s""Features:%s\n", sb, se);
for (i = 0; i < numberof(features); ++i)
- SHOW(features[i]);
+ SHOW(features[i]);
printf("%s""Warning categories:%s\n", sb, se);
for (i = 0; i < numberof(warn_categories); ++i)
- SHOW(warn_categories[i]);
- printf("%s""JIT options (experimental):%s\n", sb, se);
- for (i = 0; i < numberof(mjit_options); ++i)
- SHOW(mjit_options[i]);
+ SHOW(warn_categories[i]);
+#if USE_MJIT
+ printf("%s""MJIT options (experimental):%s\n", sb, se);
+ for (i = 0; mjit_option_messages[i].str; ++i)
+ SHOW(mjit_option_messages[i]);
+#endif
+#if USE_YJIT
+ printf("%s""YJIT options:%s\n", sb, se);
+ for (i = 0; i < numberof(yjit_options); ++i)
+ SHOW(yjit_options[i]);
+#endif
}
#define rubylib_path_new rb_str_new
@@ -383,12 +393,12 @@ push_include(const char *path, VALUE (*filter)(VALUE))
p = path;
while (*p) {
- while (*p == sep)
- p++;
- if (!*p) break;
- for (s = p; *s && *s != sep; s = CharNext(s));
- rb_ary_push(load_path, (*filter)(rubylib_path_new(p, s - p)));
- p = s;
+ while (*p == sep)
+ p++;
+ if (!*p) break;
+ for (s = p; *s && *s != sep; s = CharNext(s));
+ rb_ary_push(load_path, (*filter)(rubylib_path_new(p, s - p)));
+ p = s;
}
}
@@ -402,33 +412,33 @@ push_include_cygwin(const char *path, VALUE (*filter)(VALUE))
p = path;
while (*p) {
- unsigned int len;
- while (*p == ';')
- p++;
- if (!*p) break;
- for (s = p; *s && *s != ';'; s = CharNext(s));
- len = s - p;
- if (*s) {
- if (!buf) {
- buf = rb_str_new(p, len);
- p = RSTRING_PTR(buf);
- }
- else {
- rb_str_resize(buf, len);
- p = strncpy(RSTRING_PTR(buf), p, len);
- }
- }
+ unsigned int len;
+ while (*p == ';')
+ p++;
+ if (!*p) break;
+ for (s = p; *s && *s != ';'; s = CharNext(s));
+ len = s - p;
+ if (*s) {
+ if (!buf) {
+ buf = rb_str_new(p, len);
+ p = RSTRING_PTR(buf);
+ }
+ else {
+ rb_str_resize(buf, len);
+ p = strncpy(RSTRING_PTR(buf), p, len);
+ }
+ }
#ifdef HAVE_CYGWIN_CONV_PATH
#define CONV_TO_POSIX_PATH(p, lib) \
- cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
+ cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
#else
# error no cygwin_conv_path
#endif
- if (CONV_TO_POSIX_PATH(p, rubylib) == 0)
- p = rubylib;
- push_include(p, filter);
- if (!*s) break;
- p = s + 1;
+ if (CONV_TO_POSIX_PATH(p, rubylib) == 0)
+ p = rubylib;
+ push_include(p, filter);
+ if (!*s) break;
+ p = s + 1;
}
}
@@ -439,7 +449,7 @@ void
ruby_push_include(const char *path, VALUE (*filter)(VALUE))
{
if (path == 0)
- return;
+ return;
push_include(path, filter);
}
@@ -466,9 +476,9 @@ expand_include_path(VALUE path)
{
char *p = RSTRING_PTR(path);
if (!p)
- return path;
+ return path;
if (*p == '.' && p[1] == '/')
- return path;
+ return path;
return rb_file_expand_path(path, Qnil);
}
@@ -486,7 +496,7 @@ BOOL WINAPI
DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
{
if (reason == DLL_PROCESS_ATTACH)
- libruby = dll;
+ libruby = dll;
return TRUE;
}
@@ -500,14 +510,16 @@ static inline void
translit_char_bin(char *p, int from, int to)
{
while (*p) {
- if ((unsigned char)*p == from)
- *p = to;
- p++;
+ if ((unsigned char)*p == from)
+ *p = to;
+ p++;
}
}
#endif
#ifdef _WIN32
+# undef chdir
+# define chdir rb_w32_uchdir
# define UTF8_PATH 1
#endif
@@ -525,8 +537,8 @@ static VALUE
str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
{
return rb_str_conv_enc_opts(str, from, to,
- ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
- Qnil);
+ ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
+ Qnil);
}
#else
# define str_conv_enc(str, from, to) (str)
@@ -534,45 +546,50 @@ str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
void ruby_init_loadpath(void);
-#if defined(LOAD_RELATIVE)
+#if defined(LOAD_RELATIVE) || defined(__MACH__)
static VALUE
runtime_libruby_path(void)
{
#if defined _WIN32 || defined __CYGWIN__
- DWORD len = RSTRING_EMBED_LEN_MAX, ret;
+ DWORD len, ret;
+#if USE_RVARGC
+ len = 32;
+#else
+ len = RSTRING_EMBED_LEN_MAX;
+#endif
VALUE path;
VALUE wsopath = rb_str_new(0, len*sizeof(WCHAR));
WCHAR *wlibpath;
char *libpath;
while (wlibpath = (WCHAR *)RSTRING_PTR(wsopath),
- ret = GetModuleFileNameW(libruby, wlibpath, len),
- (ret == len))
+ ret = GetModuleFileNameW(libruby, wlibpath, len),
+ (ret == len))
{
- rb_str_modify_expand(wsopath, len*sizeof(WCHAR));
- rb_str_set_len(wsopath, (len += len)*sizeof(WCHAR));
+ rb_str_modify_expand(wsopath, len*sizeof(WCHAR));
+ rb_str_set_len(wsopath, (len += len)*sizeof(WCHAR));
}
if (!ret || ret > len) rb_fatal("failed to get module file name");
#if defined __CYGWIN__
{
- const int win_to_posix = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
- size_t newsize = cygwin_conv_path(win_to_posix, wlibpath, 0, 0);
- if (!newsize) rb_fatal("failed to convert module path to cygwin");
- path = rb_str_new(0, newsize);
- libpath = RSTRING_PTR(path);
- if (cygwin_conv_path(win_to_posix, wlibpath, libpath, newsize)) {
- rb_str_resize(path, 0);
- }
+ const int win_to_posix = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
+ size_t newsize = cygwin_conv_path(win_to_posix, wlibpath, 0, 0);
+ if (!newsize) rb_fatal("failed to convert module path to cygwin");
+ path = rb_str_new(0, newsize);
+ libpath = RSTRING_PTR(path);
+ if (cygwin_conv_path(win_to_posix, wlibpath, libpath, newsize)) {
+ rb_str_resize(path, 0);
+ }
}
#else
{
- DWORD i;
- for (len = ret, i = 0; i < len; ++i) {
- if (wlibpath[i] == L'\\') {
- wlibpath[i] = L'/';
- ret = i+1; /* chop after the last separator */
- }
- }
+ DWORD i;
+ for (len = ret, i = 0; i < len; ++i) {
+ if (wlibpath[i] == L'\\') {
+ wlibpath[i] = L'/';
+ ret = i+1; /* chop after the last separator */
+ }
+ }
}
len = WideCharToMultiByte(CP_UTF8, 0, wlibpath, ret, NULL, 0, NULL, NULL);
path = rb_utf8_str_new(0, len);
@@ -587,17 +604,17 @@ runtime_libruby_path(void)
const void* addr = (void *)(VALUE)expand_include_path;
if (!dladdr((void *)addr, &dli)) {
- return rb_str_new(0, 0);
+ return rb_str_new(0, 0);
}
#ifdef __linux__
else if (origarg.argc > 0 && origarg.argv && dli.dli_fname == origarg.argv[0]) {
- fname = rb_str_new_cstr("/proc/self/exe");
- path = rb_readlink(fname, NULL);
+ fname = rb_str_new_cstr("/proc/self/exe");
+ path = rb_readlink(fname, NULL);
}
#endif
else {
- fname = rb_str_new_cstr(dli.dli_fname);
- path = rb_realpath_internal(Qnil, fname, 1);
+ fname = rb_str_new_cstr(dli.dli_fname);
+ path = rb_realpath_internal(Qnil, fname, 1);
}
rb_str_resize(fname, 0);
return path;
@@ -610,6 +627,10 @@ 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)
@@ -617,6 +638,20 @@ 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__)
+ VALUE selfpath = libruby_path;
+# if defined(LOAD_RELATIVE)
+ selfpath = rb_str_dup(selfpath);
+# endif
+ rb_obj_hide(selfpath);
+ OBJ_FREEZE_RAW(selfpath);
+ rb_gc_register_address(&rb_libruby_selfpath);
+ rb_libruby_selfpath = selfpath;
+# endif
+#endif
+
#if defined LOAD_RELATIVE
#if !defined ENABLE_MULTIARCH
# define RUBY_ARCH_PATH ""
@@ -630,49 +665,49 @@ ruby_init_loadpath(void)
size_t baselen;
const char *p;
- sopath = runtime_libruby_path();
+ sopath = libruby_path;
libpath = RSTRING_PTR(sopath);
p = strrchr(libpath, '/');
if (p) {
- static const char libdir[] = "/"
+ static const char libdir[] = "/"
#ifdef LIBDIR_BASENAME
- LIBDIR_BASENAME
+ LIBDIR_BASENAME
#else
- "lib"
+ "lib"
#endif
- RUBY_ARCH_PATH;
- const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir)
- - rb_strlen_lit(RUBY_ARCH_PATH) - 1;
- static const char bindir[] = "/bin";
- const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1;
+ RUBY_ARCH_PATH;
+ const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir)
+ - rb_strlen_lit(RUBY_ARCH_PATH) - 1;
+ static const char bindir[] = "/bin";
+ const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1;
- const char *p2 = NULL;
+ const char *p2 = NULL;
#ifdef ENABLE_MULTIARCH
multiarch:
#endif
- if (p - libpath >= bindir_len && !STRNCASECMP(p - bindir_len, bindir, bindir_len)) {
- p -= bindir_len;
- archlibdir = rb_str_subseq(sopath, 0, p - libpath);
- rb_str_cat_cstr(archlibdir, libdir);
- OBJ_FREEZE_RAW(archlibdir);
- }
- else if (p - libpath >= libdir_len && !strncmp(p - libdir_len, libdir, libdir_len)) {
- archlibdir = rb_str_subseq(sopath, 0, (p2 ? p2 : p) - libpath);
- OBJ_FREEZE_RAW(archlibdir);
- p -= libdir_len;
- }
+ if (p - libpath >= bindir_len && !STRNCASECMP(p - bindir_len, bindir, bindir_len)) {
+ p -= bindir_len;
+ archlibdir = rb_str_subseq(sopath, 0, p - libpath);
+ rb_str_cat_cstr(archlibdir, libdir);
+ OBJ_FREEZE_RAW(archlibdir);
+ }
+ else if (p - libpath >= libdir_len && !strncmp(p - libdir_len, libdir, libdir_len)) {
+ archlibdir = rb_str_subseq(sopath, 0, (p2 ? p2 : p) - libpath);
+ OBJ_FREEZE_RAW(archlibdir);
+ p -= libdir_len;
+ }
#ifdef ENABLE_MULTIARCH
- else if (p2) {
- p = p2;
- }
- else {
- p2 = p;
- p = rb_enc_path_last_separator(libpath, p, rb_ascii8bit_encoding());
- if (p) goto multiarch;
- p = p2;
- }
+ else if (p2) {
+ p = p2;
+ }
+ else {
+ p2 = p;
+ p = rb_enc_path_last_separator(libpath, p, rb_ascii8bit_encoding());
+ if (p) goto multiarch;
+ p = p2;
+ }
#endif
baselen = p - libpath;
}
@@ -702,11 +737,11 @@ ruby_init_loadpath(void)
id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
while (*paths) {
- size_t len = strlen(paths);
- VALUE path = RUBY_RELATIVE(paths, len);
- rb_ivar_set(path, id_initial_load_path_mark, path);
- rb_ary_push(load_path, path);
- paths += len + 1;
+ size_t len = strlen(paths);
+ VALUE path = RUBY_RELATIVE(paths, len);
+ rb_ivar_set(path, id_initial_load_path_mark, path);
+ rb_ary_push(load_path, path);
+ paths += len + 1;
}
rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path);
@@ -720,7 +755,7 @@ add_modules(VALUE *req_list, const char *mod)
VALUE feature;
if (!list) {
- *req_list = list = rb_ary_tmp_new(0);
+ *req_list = list = rb_ary_hidden_new(0);
}
feature = rb_str_cat_cstr(rb_str_tmp_new(0), mod);
rb_ary_push(list, feature);
@@ -736,11 +771,11 @@ require_libraries(VALUE *req_list)
CONST_ID(require, "require");
while (list && RARRAY_LEN(list) > 0) {
- VALUE feature = rb_ary_shift(list);
- rb_enc_associate(feature, extenc);
- RBASIC_SET_CLASS_RAW(feature, rb_cString);
- OBJ_FREEZE(feature);
- rb_funcallv(self, require, 1, &feature);
+ VALUE feature = rb_ary_shift(list);
+ rb_enc_associate(feature, extenc);
+ RBASIC_SET_CLASS_RAW(feature, rb_cString);
+ OBJ_FREEZE(feature);
+ rb_funcallv(self, require, 1, &feature);
}
*req_list = 0;
}
@@ -755,63 +790,63 @@ static void
process_sflag(int *sflag)
{
if (*sflag > 0) {
- long n;
- const VALUE *args;
- VALUE argv = rb_argv;
-
- n = RARRAY_LEN(argv);
- args = RARRAY_CONST_PTR(argv);
- while (n > 0) {
- VALUE v = *args++;
- char *s = StringValuePtr(v);
- char *p;
- int hyphen = FALSE;
-
- if (s[0] != '-')
- break;
- n--;
- if (s[1] == '-' && s[2] == '\0')
- break;
-
- v = Qtrue;
- /* check if valid name before replacing - with _ */
- for (p = s + 1; *p; p++) {
- if (*p == '=') {
- *p++ = '\0';
- v = rb_str_new2(p);
- break;
- }
- if (*p == '-') {
- hyphen = TRUE;
- }
- else if (*p != '_' && !ISALNUM(*p)) {
- VALUE name_error[2];
- name_error[0] =
- rb_str_new2("invalid name for global variable - ");
- if (!(p = strchr(p, '='))) {
- rb_str_cat2(name_error[0], s);
- }
- else {
- rb_str_cat(name_error[0], s, p - s);
- }
- name_error[1] = args[-1];
- rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
- }
- }
- s[0] = '$';
- if (hyphen) {
- for (p = s + 1; *p; ++p) {
- if (*p == '-')
- *p = '_';
- }
- }
- rb_gv_set(s, v);
- }
- n = RARRAY_LEN(argv) - n;
- while (n--) {
- rb_ary_shift(argv);
- }
- *sflag = -1;
+ long n;
+ const VALUE *args;
+ VALUE argv = rb_argv;
+
+ n = RARRAY_LEN(argv);
+ args = RARRAY_CONST_PTR(argv);
+ while (n > 0) {
+ VALUE v = *args++;
+ char *s = StringValuePtr(v);
+ char *p;
+ int hyphen = FALSE;
+
+ if (s[0] != '-')
+ break;
+ n--;
+ if (s[1] == '-' && s[2] == '\0')
+ break;
+
+ v = Qtrue;
+ /* check if valid name before replacing - with _ */
+ for (p = s + 1; *p; p++) {
+ if (*p == '=') {
+ *p++ = '\0';
+ v = rb_str_new2(p);
+ break;
+ }
+ if (*p == '-') {
+ hyphen = TRUE;
+ }
+ else if (*p != '_' && !ISALNUM(*p)) {
+ VALUE name_error[2];
+ name_error[0] =
+ rb_str_new2("invalid name for global variable - ");
+ if (!(p = strchr(p, '='))) {
+ rb_str_cat2(name_error[0], s);
+ }
+ else {
+ rb_str_cat(name_error[0], s, p - s);
+ }
+ name_error[1] = args[-1];
+ rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
+ }
+ }
+ s[0] = '$';
+ if (hyphen) {
+ for (p = s + 1; *p; ++p) {
+ if (*p == '-')
+ *p = '_';
+ }
+ }
+ rb_gv_set(s, v);
+ }
+ n = RARRAY_LEN(argv) - n;
+ while (n--) {
+ rb_ary_shift(argv);
+ }
+ *sflag = -1;
}
}
@@ -837,12 +872,12 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
ap = 0;
rb_str_cat(argary, (char *)&ap, sizeof(ap));
while (*p) {
- ap = p;
- rb_str_cat(argary, (char *)&ap, sizeof(ap));
- while (*p && !ISSPACE(*p)) ++p;
- if (!*p) break;
- *p++ = '\0';
- while (ISSPACE(*p)) ++p;
+ ap = p;
+ rb_str_cat(argary, (char *)&ap, sizeof(ap));
+ while (*p && !ISSPACE(*p)) ++p;
+ if (!*p) break;
+ *p++ = '\0';
+ while (ISSPACE(*p)) ++p;
}
argc = RSTRING_LEN(argary) / sizeof(ap);
ap = 0;
@@ -851,14 +886,14 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
MEMMOVE(argv, RSTRING_PTR(argary), char *, argc);
while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) {
- argv += i;
- if (**argv != '-') {
- *--*argv = '-';
- }
- if ((*argv)[1]) {
- ++argc;
- --argv;
- }
+ argv += i;
+ if (**argv != '-') {
+ *--*argv = '-';
+ }
+ if ((*argv)[1]) {
+ ++argc;
+ --argv;
+ }
}
ruby_xfree(ptr);
@@ -872,15 +907,17 @@ name_match_p(const char *name, const char *str, size_t len)
{
if (len == 0) return 0;
while (1) {
- while (TOLOWER(*str) == *name) {
- if (!--len || !*++str) return 1;
- ++name;
- }
- if (*str != '-' && *str != '_') return 0;
- while (ISALNUM(*name)) name++;
- if (*name != '-' && *name != '_') return 0;
- ++name;
- ++str;
+ while (TOLOWER(*str) == *name) {
+ if (!--len) return 1;
+ ++name;
+ ++str;
+ }
+ if (*str != '-' && *str != '_') return 0;
+ while (ISALNUM(*name)) name++;
+ if (*name != '-' && *name != '_') return 0;
+ ++name;
+ ++str;
+ if (--len == 0) return 1;
}
}
@@ -889,14 +926,14 @@ name_match_p(const char *name, const char *str, size_t len)
#define UNSET_WHEN(name, bit, str, len) \
if (NAME_MATCH_P((name), (str), (len))) { \
- *(unsigned int *)arg &= ~(bit); \
- return; \
+ *(unsigned int *)arg &= ~(bit); \
+ return; \
}
#define SET_WHEN(name, bit, str, len) \
if (NAME_MATCH_P((name), (str), (len))) { \
- *(unsigned int *)arg |= (bit); \
- return; \
+ *(unsigned int *)arg |= (bit); \
+ return; \
}
#define LITERAL_NAME_ELEMENT(name) #name
@@ -917,28 +954,34 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable)
#define SET_FEATURE(bit) \
if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
EACH_FEATURES(SET_FEATURE, ;);
+ if (NAME_MATCH_P("jit", str, len)) { // This allows you to cancel --jit
+ set |= mask = FEATURE_BIT(jit);
+ goto found;
+ }
if (NAME_MATCH_P("all", str, len)) {
+ // YJIT and MJIT cannot be enabled at the same time. We enable only one for --enable=all.
+ mask &= ~feature_jit_mask | FEATURE_BIT(jit);
goto found;
}
#if AMBIGUOUS_FEATURE_NAMES
if (matched == 1) goto found;
if (matched > 1) {
- VALUE mesg = rb_sprintf("ambiguous feature: `%.*s' (", len, str);
+ VALUE mesg = rb_sprintf("ambiguous feature: `%.*s' (", len, str);
#define ADD_FEATURE_NAME(bit) \
- if (FEATURE_BIT(bit) & set) { \
- rb_str_cat_cstr(mesg, #bit); \
- if (--matched) rb_str_cat_cstr(mesg, ", "); \
- }
- EACH_FEATURES(ADD_FEATURE_NAME, ;);
- rb_str_cat_cstr(mesg, ")");
- rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, mesg));
+ if (FEATURE_BIT(bit) & set) { \
+ rb_str_cat_cstr(mesg, #bit); \
+ if (--matched) rb_str_cat_cstr(mesg, ", "); \
+ }
+ EACH_FEATURES(ADD_FEATURE_NAME, ;);
+ rb_str_cat_cstr(mesg, ")");
+ rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, mesg));
#undef ADD_FEATURE_NAME
}
#else
(void)set;
#endif
rb_warn("unknown argument for --%s: `%.*s'",
- enable ? "enable" : "disable", len, str);
+ enable ? "enable" : "disable", len, str);
rb_warn("features are [%.*s].", (int)strlen(list), list);
return;
@@ -980,11 +1023,49 @@ debug_option(const char *str, int len, void *arg)
rb_warn("debug features are [%.*s].", (int)strlen(list), list);
}
+static int
+memtermspn(const char *str, char term, int len)
+{
+ RUBY_ASSERT(len >= 0);
+ if (len <= 0) return 0;
+ const char *next = memchr(str, term, len);
+ return next ? (int)(next - str) : len;
+}
+
+static const char additional_opt_sep = '+';
+
+static unsigned int
+dump_additional_option(const char *str, int len, unsigned int bits, const char *name)
+{
+ int w;
+ for (; len-- > 0 && *str++ == additional_opt_sep; len -= w, str += w) {
+ w = memtermspn(str, additional_opt_sep, len);
+#define SET_ADDITIONAL(bit) if (NAME_MATCH_P(#bit, str, w)) { \
+ if (bits & DUMP_BIT(bit)) \
+ rb_warn("duplicate option to dump %s: `%.*s'", name, w, str); \
+ bits |= DUMP_BIT(bit); \
+ continue; \
+ }
+ if (dump_error_tolerant_bits & bits) {
+ SET_ADDITIONAL(error_tolerant);
+ }
+ rb_warn("don't know how to dump %s with `%.*s'", name, w, str);
+ }
+ return bits;
+}
+
static void
dump_option(const char *str, int len, void *arg)
{
static const char list[] = EACH_DUMPS(LITERAL_NAME_ELEMENT, ", ");
-#define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
+ int w = memtermspn(str, additional_opt_sep, len);
+
+#define SET_WHEN_DUMP(bit) \
+ if (NAME_MATCH_P(#bit, (str), (w))) { \
+ *(unsigned int *)arg |= \
+ dump_additional_option(str + w, len - w, DUMP_BIT(bit), #bit); \
+ return; \
+ }
EACH_DUMPS(SET_WHEN_DUMP, ;);
rb_warn("don't know how to dump `%.*s',", len, str);
rb_warn("but only [%.*s].", (int)strlen(list), list);
@@ -999,9 +1080,9 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen
ename = rb_str_new(e, elen);
if (*name &&
- rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
- rb_raise(rb_eRuntimeError,
- "%s already set to %"PRIsVALUE, type, *name);
+ rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
+ rb_raise(rb_eRuntimeError,
+ "%s already set to %"PRIsVALUE, type, *name);
}
*name = ename;
}
@@ -1013,50 +1094,28 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen
#define set_source_encoding_once(opt, e, elen) \
set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
-#if USE_MJIT
-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 (opt_match_noarg(s, l, "warnings")) {
- mjit_opt->warnings = 1;
- }
- else if (opt_match(s, l, "debug")) {
- if (*s)
- mjit_opt->debug_flags = strdup(s + 1);
- else
- mjit_opt->debug = 1;
- }
- else if (opt_match_noarg(s, l, "wait")) {
- mjit_opt->wait = 1;
- }
- else if (opt_match_noarg(s, l, "save-temps")) {
- mjit_opt->save_temps = 1;
- }
- else if (opt_match(s, l, "verbose")) {
- mjit_opt->verbose = *s ? atoi(s + 1) : 1;
- }
- else if (opt_match_arg(s, l, "max-cache")) {
- mjit_opt->max_cache_size = atoi(s + 1);
- }
- 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);
+#define yjit_opt_match_noarg(s, l, name) \
+ opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --yjit-" name " is ignored"), 1) : 1)
+#define yjit_opt_match_arg(s, l, name) \
+ opt_match(s, l, name) && (*(s) && *(s+1) ? 1 : (rb_raise(rb_eRuntimeError, "--yjit-" name " needs an argument"), 0))
+
+#if USE_YJIT
+static bool
+setup_yjit_options(const char *s)
+{
+ // The option parsing is done in yjit/src/options.rs
+ bool rb_yjit_parse_option(const char* s);
+ bool success = rb_yjit_parse_option(s);
+
+ if (success) {
+ return true;
}
+
+ rb_raise(
+ rb_eRuntimeError,
+ "invalid YJIT option `%s' (--help will show valid yjit options)",
+ s
+ );
}
#endif
@@ -1068,61 +1127,61 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
int warning = opt->warning;
if (argc <= 0 || !argv)
- return 0;
+ return 0;
for (argc--, argv++; argc > 0; argc--, argv++) {
- const char *const arg = argv[0];
- if (!arg || arg[0] != '-' || !arg[1])
- break;
+ const char *const arg = argv[0];
+ if (!arg || arg[0] != '-' || !arg[1])
+ break;
- s = arg + 1;
+ s = arg + 1;
reswitch:
- switch (*s) {
- case 'a':
- if (envopt) goto noenvopt;
- opt->do_split = TRUE;
- s++;
- goto reswitch;
-
- case 'p':
- if (envopt) goto noenvopt;
- opt->do_print = TRUE;
- /* through */
- case 'n':
- if (envopt) goto noenvopt;
- opt->do_loop = TRUE;
- s++;
- goto reswitch;
-
- case 'd':
- ruby_debug = Qtrue;
- ruby_verbose = Qtrue;
- s++;
- goto reswitch;
-
- case 'y':
- if (envopt) goto noenvopt;
- opt->dump |= DUMP_BIT(yydebug);
- s++;
- goto reswitch;
-
- case 'v':
- if (opt->verbose) {
- s++;
- goto reswitch;
- }
- opt->dump |= DUMP_BIT(version_v);
- opt->verbose = 1;
- case 'w':
- if (!opt->warning) {
- warning = 1;
- ruby_verbose = Qtrue;
- }
- FEATURE_SET(opt->warn, RB_WARN_CATEGORY_ALL_BITS);
- s++;
- goto reswitch;
-
- case 'W':
+ switch (*s) {
+ case 'a':
+ if (envopt) goto noenvopt;
+ opt->do_split = TRUE;
+ s++;
+ goto reswitch;
+
+ case 'p':
+ if (envopt) goto noenvopt;
+ opt->do_print = TRUE;
+ /* through */
+ case 'n':
+ if (envopt) goto noenvopt;
+ opt->do_loop = TRUE;
+ s++;
+ goto reswitch;
+
+ case 'd':
+ ruby_debug = Qtrue;
+ ruby_verbose = Qtrue;
+ s++;
+ goto reswitch;
+
+ case 'y':
+ if (envopt) goto noenvopt;
+ opt->dump |= DUMP_BIT(yydebug);
+ s++;
+ goto reswitch;
+
+ case 'v':
+ if (opt->verbose) {
+ s++;
+ goto reswitch;
+ }
+ opt->dump |= DUMP_BIT(version_v);
+ opt->verbose = 1;
+ case 'w':
+ if (!opt->warning) {
+ warning = 1;
+ ruby_verbose = Qtrue;
+ }
+ FEATURE_SET(opt->warn, RB_WARN_CATEGORY_ALL_BITS);
+ s++;
+ goto reswitch;
+
+ case 'W':
if (s[1] == ':') {
unsigned int bits = 0;
static const char no_prefix[] = "no-";
@@ -1141,353 +1200,371 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
if (bits) FEATURE_SET_TO(opt->warn, bits, enable ? bits : 0);
break;
}
- {
- size_t numlen;
- int v = 2; /* -W as -W2 */
+ {
+ size_t numlen;
+ int v = 2; /* -W as -W2 */
- if (*++s) {
- v = scan_oct(s, 1, &numlen);
- if (numlen == 0)
+ if (*++s) {
+ v = scan_oct(s, 1, &numlen);
+ if (numlen == 0)
v = 2;
- s += numlen;
- }
- if (!opt->warning) {
- switch (v) {
- case 0:
- ruby_verbose = Qnil;
- break;
- case 1:
- ruby_verbose = Qfalse;
- break;
- default:
- ruby_verbose = Qtrue;
- break;
- }
- }
- warning = 1;
- switch (v) {
- case 0:
- FEATURE_SET_TO(opt->warn, RB_WARN_CATEGORY_ALL_BITS, 0);
- break;
- case 1:
- FEATURE_SET_TO(opt->warn, 1U << RB_WARN_CATEGORY_DEPRECATED, 0);
- break;
- default:
- FEATURE_SET(opt->warn, RB_WARN_CATEGORY_ALL_BITS);
- break;
- }
- }
- goto reswitch;
-
- case 'c':
- if (envopt) goto noenvopt;
- opt->dump |= DUMP_BIT(syntax);
- s++;
- goto reswitch;
-
- case 's':
- if (envopt) goto noenvopt;
- forbid_setid("-s");
- if (!opt->sflag) opt->sflag = 1;
- s++;
- goto reswitch;
-
- case 'h':
- if (envopt) goto noenvopt;
- opt->dump |= DUMP_BIT(usage);
- goto switch_end;
-
- case 'l':
- if (envopt) goto noenvopt;
- opt->do_line = TRUE;
- rb_output_rs = rb_rs;
- s++;
- goto reswitch;
-
- case 'S':
- if (envopt) goto noenvopt;
- forbid_setid("-S");
- opt->do_search = TRUE;
- s++;
- goto reswitch;
-
- case 'e':
- if (envopt) goto noenvopt;
- forbid_setid("-e");
- if (!*++s) {
- if (!--argc)
- rb_raise(rb_eRuntimeError, "no code specified for -e");
- s = *++argv;
- }
- if (!opt->e_script) {
- opt->e_script = rb_str_new(0, 0);
- if (opt->script == 0)
- opt->script = "-e";
- }
- rb_str_cat2(opt->e_script, s);
- rb_str_cat2(opt->e_script, "\n");
- break;
-
- case 'r':
- forbid_setid("-r");
- if (*++s) {
- add_modules(&opt->req_list, s);
- }
- else if (argc > 1) {
- add_modules(&opt->req_list, argv[1]);
- argc--, argv++;
- }
- break;
-
- case 'i':
- if (envopt) goto noenvopt;
- forbid_setid("-i");
- ruby_set_inplace_mode(s + 1);
- break;
-
- case 'x':
- if (envopt) goto noenvopt;
- forbid_setid("-x");
- opt->xflag = TRUE;
- s++;
- if (*s && chdir(s) < 0) {
- rb_fatal("Can't chdir to %s", s);
- }
- break;
-
- case 'C':
- case 'X':
- if (envopt) goto noenvopt;
- if (!*++s && (!--argc || !(s = *++argv) || !*s)) {
- rb_fatal("Can't chdir");
- }
- if (chdir(s) < 0) {
- rb_fatal("Can't chdir to %s", s);
- }
- break;
-
- case 'F':
- if (envopt) goto noenvopt;
- if (*++s) {
- rb_fs = rb_reg_new(s, strlen(s), 0);
- }
- break;
-
- case 'E':
- if (!*++s && (!--argc || !(s = *++argv))) {
- rb_raise(rb_eRuntimeError, "missing argument for -E");
- }
- goto encoding;
-
- case 'U':
- set_internal_encoding_once(opt, "UTF-8", 0);
- ++s;
- goto reswitch;
-
- case 'K':
- if (*++s) {
- const char *enc_name = 0;
- switch (*s) {
- case 'E': case 'e':
- enc_name = "EUC-JP";
- break;
- case 'S': case 's':
- enc_name = "Windows-31J";
- break;
- case 'U': case 'u':
- enc_name = "UTF-8";
- break;
- case 'N': case 'n': case 'A': case 'a':
- enc_name = "ASCII-8BIT";
- break;
- }
- if (enc_name) {
- opt->src.enc.name = rb_str_new2(enc_name);
- if (!opt->ext.enc.name)
- opt->ext.enc.name = opt->src.enc.name;
- }
- s++;
- }
- goto reswitch;
-
- case 'I':
- forbid_setid("-I");
- if (*++s)
- ruby_incpush_expand(s);
- else if (argc > 1) {
- ruby_incpush_expand(argv[1]);
- argc--, argv++;
- }
- break;
-
- case '0':
- if (envopt) goto noenvopt;
- {
- size_t numlen;
- int v;
- char c;
-
- v = scan_oct(s, 4, &numlen);
- s += numlen;
- if (v > 0377)
- rb_rs = Qnil;
- else if (v == 0 && numlen >= 2) {
- rb_rs = rb_str_new2("");
- }
- else {
- c = v & 0xff;
- rb_rs = rb_str_new(&c, 1);
- }
- }
- goto reswitch;
-
- case '-':
- if (!s[1] || (s[1] == '\r' && !s[2])) {
- argc--, argv++;
- goto switch_end;
- }
- s++;
+ s += numlen;
+ }
+ if (!opt->warning) {
+ switch (v) {
+ case 0:
+ ruby_verbose = Qnil;
+ break;
+ case 1:
+ ruby_verbose = Qfalse;
+ break;
+ default:
+ ruby_verbose = Qtrue;
+ break;
+ }
+ }
+ warning = 1;
+ switch (v) {
+ case 0:
+ FEATURE_SET_TO(opt->warn, RB_WARN_CATEGORY_ALL_BITS, 0);
+ break;
+ case 1:
+ FEATURE_SET_TO(opt->warn, 1U << RB_WARN_CATEGORY_DEPRECATED, 0);
+ break;
+ default:
+ FEATURE_SET(opt->warn, RB_WARN_CATEGORY_ALL_BITS);
+ break;
+ }
+ }
+ goto reswitch;
+
+ case 'c':
+ if (envopt) goto noenvopt;
+ opt->dump |= DUMP_BIT(syntax);
+ s++;
+ goto reswitch;
+
+ case 's':
+ if (envopt) goto noenvopt;
+ forbid_setid("-s");
+ if (!opt->sflag) opt->sflag = 1;
+ s++;
+ goto reswitch;
+
+ case 'h':
+ if (envopt) goto noenvopt;
+ opt->dump |= DUMP_BIT(usage);
+ goto switch_end;
+
+ case 'l':
+ if (envopt) goto noenvopt;
+ opt->do_line = TRUE;
+ rb_output_rs = rb_rs;
+ s++;
+ goto reswitch;
+
+ case 'S':
+ if (envopt) goto noenvopt;
+ forbid_setid("-S");
+ opt->do_search = TRUE;
+ s++;
+ goto reswitch;
+
+ case 'e':
+ if (envopt) goto noenvopt;
+ forbid_setid("-e");
+ if (!*++s) {
+ if (!--argc)
+ rb_raise(rb_eRuntimeError, "no code specified for -e");
+ s = *++argv;
+ }
+ if (!opt->e_script) {
+ opt->e_script = rb_str_new(0, 0);
+ if (opt->script == 0)
+ opt->script = "-e";
+ }
+ rb_str_cat2(opt->e_script, s);
+ rb_str_cat2(opt->e_script, "\n");
+ break;
+
+ case 'r':
+ forbid_setid("-r");
+ if (*++s) {
+ add_modules(&opt->req_list, s);
+ }
+ else if (argc > 1) {
+ add_modules(&opt->req_list, argv[1]);
+ argc--, argv++;
+ }
+ break;
+
+ case 'i':
+ if (envopt) goto noenvopt;
+ forbid_setid("-i");
+ ruby_set_inplace_mode(s + 1);
+ break;
+
+ case 'x':
+ if (envopt) goto noenvopt;
+ forbid_setid("-x");
+ opt->xflag = TRUE;
+ s++;
+ if (*s && chdir(s) < 0) {
+ rb_fatal("Can't chdir to %s", s);
+ }
+ break;
+
+ case 'C':
+ case 'X':
+ if (envopt) goto noenvopt;
+ if (!*++s && (!--argc || !(s = *++argv) || !*s)) {
+ rb_fatal("Can't chdir");
+ }
+ if (chdir(s) < 0) {
+ rb_fatal("Can't chdir to %s", s);
+ }
+ break;
+
+ case 'F':
+ if (envopt) goto noenvopt;
+ if (*++s) {
+ rb_fs = rb_reg_new(s, strlen(s), 0);
+ }
+ break;
+
+ case 'E':
+ if (!*++s && (!--argc || !(s = *++argv))) {
+ rb_raise(rb_eRuntimeError, "missing argument for -E");
+ }
+ goto encoding;
+
+ case 'U':
+ set_internal_encoding_once(opt, "UTF-8", 0);
+ ++s;
+ goto reswitch;
+
+ case 'K':
+ if (*++s) {
+ const char *enc_name = 0;
+ switch (*s) {
+ case 'E': case 'e':
+ enc_name = "EUC-JP";
+ break;
+ case 'S': case 's':
+ enc_name = "Windows-31J";
+ break;
+ case 'U': case 'u':
+ enc_name = "UTF-8";
+ break;
+ case 'N': case 'n': case 'A': case 'a':
+ enc_name = "ASCII-8BIT";
+ break;
+ }
+ if (enc_name) {
+ opt->src.enc.name = rb_str_new2(enc_name);
+ if (!opt->ext.enc.name)
+ opt->ext.enc.name = opt->src.enc.name;
+ }
+ s++;
+ }
+ goto reswitch;
+
+ case 'I':
+ forbid_setid("-I");
+ if (*++s)
+ ruby_incpush_expand(s);
+ else if (argc > 1) {
+ ruby_incpush_expand(argv[1]);
+ argc--, argv++;
+ }
+ break;
+
+ case '0':
+ if (envopt) goto noenvopt;
+ {
+ size_t numlen;
+ int v;
+ char c;
+
+ v = scan_oct(s, 4, &numlen);
+ s += numlen;
+ if (v > 0377)
+ rb_rs = Qnil;
+ else if (v == 0 && numlen >= 2) {
+ rb_rs = rb_str_new2("");
+ }
+ else {
+ c = v & 0xff;
+ rb_rs = rb_str_new(&c, 1);
+ }
+ }
+ goto reswitch;
+
+ case '-':
+ if (!s[1] || (s[1] == '\r' && !s[2])) {
+ argc--, argv++;
+ goto switch_end;
+ }
+ s++;
# define is_option_end(c, allow_hyphen) \
- (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
+ (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
# define check_envopt(name, allow_envopt) \
- (((allow_envopt) || !envopt) ? (void)0 : \
- rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
+ (((allow_envopt) || !envopt) ? (void)0 : \
+ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
# define need_argument(name, s, needs_arg, next_arg) \
- ((*(s) ? !*++(s) : (next_arg) && (!argc || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \
- rb_raise(rb_eRuntimeError, "missing argument for --" name) \
- : (void)0)
+ ((*(s) ? !*++(s) : (next_arg) && (!argc || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \
+ rb_raise(rb_eRuntimeError, "missing argument for --" name) \
+ : (void)0)
# define is_option_with_arg(name, allow_hyphen, allow_envopt) \
- is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue)
+ is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue)
# define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg) \
- (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \
- (check_envopt(name, (allow_envopt)), s += n, \
- need_argument(name, s, needs_arg, next_arg), 1) : 0)
-
- if (strcmp("copyright", s) == 0) {
- if (envopt) goto noenvopt_long;
- opt->dump |= DUMP_BIT(copyright);
- }
- else if (is_option_with_optarg("debug", Qtrue, Qtrue, Qfalse, Qfalse)) {
- if (s && *s) {
- ruby_each_words(s, debug_option, &opt->features);
- }
- else {
- ruby_debug = Qtrue;
- ruby_verbose = Qtrue;
- }
+ (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) && \
+ (s[n] != '-' || s[n+1]) ? \
+ (check_envopt(name, (allow_envopt)), s += n, \
+ need_argument(name, s, needs_arg, next_arg), 1) : 0)
+
+ if (strcmp("copyright", s) == 0) {
+ if (envopt) goto noenvopt_long;
+ opt->dump |= DUMP_BIT(copyright);
}
- else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
- ruby_each_words(s, enable_option, &opt->features);
- }
- else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
- ruby_each_words(s, disable_option, &opt->features);
- }
- else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
- char *p;
- encoding:
- do {
+ else if (is_option_with_optarg("debug", Qtrue, Qtrue, Qfalse, Qfalse)) {
+ if (s && *s) {
+ ruby_each_words(s, debug_option, &opt->features);
+ }
+ else {
+ ruby_debug = Qtrue;
+ ruby_verbose = Qtrue;
+ }
+ }
+ else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
+ ruby_each_words(s, enable_option, &opt->features);
+ }
+ else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
+ ruby_each_words(s, disable_option, &opt->features);
+ }
+ else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
+ char *p;
+ encoding:
+ do {
# define set_encoding_part(type) \
- if (!(p = strchr(s, ':'))) { \
- set_##type##_encoding_once(opt, s, 0); \
- break; \
- } \
- else if (p > s) { \
- set_##type##_encoding_once(opt, s, p-s); \
- }
- set_encoding_part(external);
- if (!*(s = ++p)) break;
- set_encoding_part(internal);
- if (!*(s = ++p)) break;
+ if (!(p = strchr(s, ':'))) { \
+ set_##type##_encoding_once(opt, s, 0); \
+ break; \
+ } \
+ else if (p > s) { \
+ set_##type##_encoding_once(opt, s, p-s); \
+ }
+ set_encoding_part(external);
+ if (!*(s = ++p)) break;
+ set_encoding_part(internal);
+ if (!*(s = ++p)) break;
#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
- set_encoding_part(source);
- if (!*(s = ++p)) break;
+ set_encoding_part(source);
+ if (!*(s = ++p)) break;
#endif
- rb_raise(rb_eRuntimeError, "extra argument for %s: %s",
- (arg[1] == '-' ? "--encoding" : "-E"), s);
+ rb_raise(rb_eRuntimeError, "extra argument for %s: %s",
+ (arg[1] == '-' ? "--encoding" : "-E"), s);
# undef set_encoding_part
- } while (0);
- }
- else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
- set_internal_encoding_once(opt, s, 0);
- }
- else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
- set_external_encoding_once(opt, s, 0);
- }
+ } while (0);
+ }
+ else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
+ set_internal_encoding_once(opt, s, 0);
+ }
+ else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
+ set_external_encoding_once(opt, s, 0);
+ }
#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
- else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
- set_source_encoding_once(opt, s, 0);
- }
-#endif
- else if (strcmp("version", s) == 0) {
- if (envopt) goto noenvopt_long;
- opt->dump |= DUMP_BIT(version);
- }
- else if (strcmp("verbose", s) == 0) {
- opt->verbose = 1;
- ruby_verbose = Qtrue;
- }
- else if (strncmp("jit", s, 3) == 0) {
-#if USE_MJIT
+ else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
+ set_source_encoding_once(opt, s, 0);
+ }
+#endif
+ else if (strcmp("version", s) == 0) {
+ if (envopt) goto noenvopt_long;
+ opt->dump |= DUMP_BIT(version);
+ }
+ else if (strcmp("verbose", s) == 0) {
+ opt->verbose = 1;
+ ruby_verbose = Qtrue;
+ }
+ else if (strcmp("jit", s) == 0) {
+#if !USE_MJIT
+ rb_warn("Ruby was built without JIT support");
+#else
FEATURE_SET(opt->features, FEATURE_BIT(jit));
- setup_mjit_options(s + 3, &opt->mjit);
+#endif
+ }
+ else if (is_option_with_optarg("mjit", '-', true, false, false)) {
+#if USE_MJIT
+ extern void mjit_setup_options(const char *s, struct mjit_options *mjit_opt);
+ FEATURE_SET(opt->features, FEATURE_BIT(mjit));
+ mjit_setup_options(s, &opt->mjit);
#else
rb_warn("MJIT support is disabled.");
#endif
}
- else if (strcmp("yydebug", s) == 0) {
- if (envopt) goto noenvopt_long;
- opt->dump |= DUMP_BIT(yydebug);
- }
- else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
- ruby_each_words(s, dump_option, &opt->dump);
- }
- else if (strcmp("help", s) == 0) {
- if (envopt) goto noenvopt_long;
- opt->dump |= DUMP_BIT(help);
- goto switch_end;
- }
+ else if (is_option_with_optarg("yjit", '-', true, false, false)) {
+#if USE_YJIT
+ FEATURE_SET(opt->features, FEATURE_BIT(yjit));
+ setup_yjit_options(s);
+#else
+ rb_warn("Ruby was built without YJIT support."
+ " You may need to install rustc to build Ruby with YJIT.");
+#endif
+ }
+ else if (strcmp("yydebug", s) == 0) {
+ if (envopt) goto noenvopt_long;
+ opt->dump |= DUMP_BIT(yydebug);
+ }
+ else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
+ ruby_each_words(s, dump_option, &opt->dump);
+ }
+ else if (strcmp("help", s) == 0) {
+ if (envopt) goto noenvopt_long;
+ 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);
- }
- break;
-
- case '\r':
- if (!s[1])
- break;
-
- default:
- {
+ else {
rb_raise(rb_eRuntimeError,
- "invalid option -%c (-h will show valid options)",
+ "invalid option --%s (-h will show valid options)", s);
+ }
+ break;
+
+ case '\r':
+ if (!s[1])
+ break;
+
+ default:
+ {
+ rb_raise(rb_eRuntimeError,
+ "invalid option -%c (-h will show valid options)",
(int)(unsigned char)*s);
- }
- goto switch_end;
+ }
+ goto switch_end;
- noenvopt:
- /* "EIdvwWrKU" only */
- rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
- break;
+ noenvopt:
+ /* "EIdvwWrKU" only */
+ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
+ break;
- noenvopt_long:
- rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
- break;
+ noenvopt_long:
+ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
+ break;
- case 0:
- break;
+ case 0:
+ break;
# undef is_option_end
# undef check_envopt
# undef need_argument
# undef is_option_with_arg
# undef is_option_with_optarg
- }
+ }
}
switch_end:
@@ -1506,12 +1583,22 @@ ruby_init_prelude(void)
void rb_call_builtin_inits(void);
+// Initialize extra optional exts linked statically.
+// This empty definition will be replaced with the actual strong symbol by linker.
+#if RBIMPL_HAS_ATTRIBUTE(weak)
+__attribute__((weak))
+#endif
+void
+Init_extra_exts(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)) {
+ if (FEATURE_SET_P(opt->features, gems)) {
rb_define_module("Gem");
if (opt->features.set & FEATURE_BIT(error_highlight)) {
rb_define_module("ErrorHighlight");
@@ -1519,14 +1606,39 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
if (opt->features.set & FEATURE_BIT(did_you_mean)) {
rb_define_module("DidYouMean");
}
+ if (opt->features.set & FEATURE_BIT(syntax_suggest)) {
+ rb_define_module("SyntaxSuggest");
+ }
}
rb_warning_category_update(opt->warn.mask, opt->warn.set);
+#if USE_MJIT
+ // rb_call_builtin_inits depends on RubyVM::MJIT.enabled?
+ if (opt->mjit.on)
+ mjit_enabled = true;
+#endif
+
Init_ext(); /* load statically linked extensions before rubygems */
+ Init_extra_exts();
rb_call_builtin_inits();
ruby_init_prelude();
+ // Initialize JITs after prelude because JITing prelude is typically not optimal.
+#if USE_MJIT
+ // Also, mjit_init is safe only after rb_call_builtin_inits() defines RubyVM::MJIT::Compiler.
+ if (opt->mjit.on)
+ mjit_init(&opt->mjit);
+#endif
+#if USE_YJIT
+ if (opt->yjit)
+ rb_yjit_init();
+#endif
+ // rb_threadptr_root_fiber_setup for the initial thread is called before rb_yjit_enabled_p()
+ // or mjit_enabled becomes true, meaning jit_cont_new is skipped for the initial root fiber.
+ // Therefore we need to call this again here to set the initial root fiber's jit_cont.
+ rb_jit_cont_init(); // must be after mjit_enabled = true and rb_yjit_init()
+
ruby_set_script_name(opt->script_name);
require_libraries(&opt->req_list);
}
@@ -1538,10 +1650,10 @@ opt_enc_index(VALUE enc_name)
int i = rb_enc_find_index(s);
if (i < 0) {
- rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
+ rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
}
else if (rb_enc_dummy_p(rb_enc_from_index(i))) {
- rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
+ rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
}
return i;
}
@@ -1573,8 +1685,8 @@ uscore_get(void)
line = rb_lastline_get();
if (!RB_TYPE_P(line, T_STRING)) {
- rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
- NIL_P(line) ? "nil" : rb_obj_classname(line));
+ rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
+ NIL_P(line) ? "nil" : rb_obj_classname(line));
}
return line;
}
@@ -1678,6 +1790,37 @@ tty_enabled(void)
#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);
+}
+
+#if USE_YJIT
+// Check that an environment variable is set to a truthy value
+static bool
+env_var_truthy(const char *name)
+{
+ const char *value = getenv(name);
+
+ if (!value)
+ return false;
+ if (strcmp(value, "1") == 0)
+ return true;
+ if (strcmp(value, "true") == 0)
+ return true;
+ if (strcmp(value, "yes") == 0)
+ return true;
+
+ return false;
+}
+#endif
+
+static VALUE
process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
{
rb_ast_t *ast = 0;
@@ -1693,13 +1836,15 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
char fbuf[MAXPATHLEN];
int i = (int)proc_options(argc, argv, opt, 0);
unsigned int dump = opt->dump & dump_exit_bits;
+ rb_vm_t *vm = GET_VM();
+ const long loaded_before_enc = RARRAY_LEN(vm->loaded_features);
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);
+ const char *const progname =
+ (argc > 0 && argv && argv[0] ? argv[0] :
+ origarg.argc > 0 && origarg.argv && origarg.argv[0] ? origarg.argv[0] :
+ ruby_engine);
int columns = 0;
if ((opt->dump & DUMP_BIT(help)) && tty) {
const char *pager_env = getenv("RUBY_PAGER");
@@ -1750,28 +1895,28 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
#endif
}
}
- usage(progname, (opt->dump & DUMP_BIT(help)), tty, columns);
- return Qtrue;
+ usage(progname, (opt->dump & DUMP_BIT(help)), tty, columns);
+ return Qtrue;
}
argc -= i;
argv += i;
- if ((opt->features.set & FEATURE_BIT(rubyopt)) && (s = getenv("RUBYOPT"))) {
- VALUE src_enc_name = opt->src.enc.name;
- VALUE ext_enc_name = opt->ext.enc.name;
- VALUE int_enc_name = opt->intern.enc.name;
+ if (FEATURE_SET_P(opt->features, rubyopt) && (s = getenv("RUBYOPT"))) {
+ VALUE src_enc_name = opt->src.enc.name;
+ VALUE ext_enc_name = opt->ext.enc.name;
+ VALUE int_enc_name = opt->intern.enc.name;
ruby_features_t feat = opt->features;
ruby_features_t warn = opt->warn;
- opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
- moreswitches(s, opt, 1);
- if (src_enc_name)
- opt->src.enc.name = src_enc_name;
- if (ext_enc_name)
- opt->ext.enc.name = ext_enc_name;
- if (int_enc_name)
- opt->intern.enc.name = int_enc_name;
+ opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
+ moreswitches(s, opt, 1);
+ if (src_enc_name)
+ opt->src.enc.name = src_enc_name;
+ if (ext_enc_name)
+ opt->ext.enc.name = ext_enc_name;
+ if (int_enc_name)
+ opt->intern.enc.name = int_enc_name;
FEATURE_SET_RESTORE(opt->features, feat);
FEATURE_SET_RESTORE(opt->warn, warn);
}
@@ -1782,53 +1927,68 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
*/
rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
+ if (!(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) {
+#if USE_YJIT
+ if (!FEATURE_USED_P(opt->features, yjit) && env_var_truthy("RUBY_YJIT_ENABLE")) {
+ FEATURE_SET(opt->features, FEATURE_BIT(yjit));
+ }
+#endif
+ }
+ if (MULTI_BITS_P(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) {
+ rb_warn("MJIT and YJIT cannot both be enabled at the same time. Exiting");
+ return Qfalse;
+ }
+
#if USE_MJIT
- if (opt->features.set & FEATURE_BIT(jit)) {
- opt->mjit.on = TRUE; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */
+ if (FEATURE_SET_P(opt->features, mjit)) {
+ opt->mjit.on = true; // set opt->mjit.on for Init_ruby_description() and calling mjit_init()
}
#endif
- if (opt->dump & (DUMP_BIT(version) | DUMP_BIT(version_v))) {
-#if USE_MJIT
- mjit_opts.on = opt->mjit.on; /* used by ruby_show_version(). mjit_init() still can't be called here. */
+#if USE_YJIT
+ if (FEATURE_SET_P(opt->features, yjit)) {
+ opt->yjit = true; // set opt->yjit for Init_ruby_description() and calling rb_yjit_init()
+ }
#endif
- ruby_show_version();
- if (opt->dump & DUMP_BIT(version)) return Qtrue;
+ Init_ruby_description(opt);
+ if (opt->dump & (DUMP_BIT(version) | DUMP_BIT(version_v))) {
+ ruby_show_version();
+ if (opt->dump & DUMP_BIT(version)) return Qtrue;
}
if (opt->dump & DUMP_BIT(copyright)) {
- ruby_show_copyright();
- return Qtrue;
+ ruby_show_copyright();
+ return Qtrue;
}
if (!opt->e_script) {
- if (argc <= 0) { /* no more args */
- if (opt->verbose)
- return Qtrue;
- opt->script = "-";
- }
- else {
- opt->script = argv[0];
- if (!opt->script || opt->script[0] == '\0') {
- opt->script = "-";
- }
- else if (opt->do_search) {
- const char *path = getenv("RUBYPATH");
-
- opt->script = 0;
- if (path) {
- opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
- }
- if (!opt->script) {
- opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
- }
- if (!opt->script)
- opt->script = argv[0];
- }
- argc--;
- argv++;
- }
- if (opt->script[0] == '-' && !opt->script[1]) {
- forbid_setid("program input from stdin");
- }
+ if (argc <= 0) { /* no more args */
+ if (opt->verbose)
+ return Qtrue;
+ opt->script = "-";
+ }
+ else {
+ opt->script = argv[0];
+ if (!opt->script || opt->script[0] == '\0') {
+ opt->script = "-";
+ }
+ else if (opt->do_search) {
+ const char *path = getenv("RUBYPATH");
+
+ opt->script = 0;
+ if (path) {
+ opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
+ }
+ if (!opt->script) {
+ opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
+ }
+ if (!opt->script)
+ opt->script = argv[0];
+ }
+ argc--;
+ argv++;
+ }
+ if (opt->script[0] == '-' && !opt->script[1]) {
+ forbid_setid("program input from stdin");
+ }
}
opt->script_name = rb_str_new_cstr(opt->script);
@@ -1843,210 +2003,222 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
ruby_gc_set_params();
ruby_init_loadpath();
-#if USE_MJIT
- if (opt->mjit.on)
- /* Using TMP_RUBY_PREFIX created by ruby_init_loadpath(). */
- mjit_init(&opt->mjit);
-#endif
-
- Init_ruby_description();
Init_enc();
lenc = rb_locale_encoding();
rb_enc_associate(rb_progname, lenc);
rb_obj_freeze(rb_progname);
parser = rb_parser_new();
if (opt->dump & DUMP_BIT(yydebug)) {
- rb_parser_set_yydebug(parser, Qtrue);
+ rb_parser_set_yydebug(parser, Qtrue);
+ }
+ if (opt->dump & DUMP_BIT(error_tolerant)) {
+ rb_parser_error_tolerant(parser);
}
if (opt->ext.enc.name != 0) {
- opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
+ opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
}
if (opt->intern.enc.name != 0) {
- opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
+ opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
}
if (opt->src.enc.name != 0) {
- opt->src.enc.index = opt_enc_index(opt->src.enc.name);
- src_encoding_index = opt->src.enc.index;
+ opt->src.enc.index = opt_enc_index(opt->src.enc.name);
+ src_encoding_index = opt->src.enc.index;
}
if (opt->ext.enc.index >= 0) {
- enc = rb_enc_from_index(opt->ext.enc.index);
+ enc = rb_enc_from_index(opt->ext.enc.index);
}
else {
- enc = IF_UTF8_PATH(uenc, lenc);
+ enc = IF_UTF8_PATH(uenc, lenc);
}
rb_enc_set_default_external(rb_enc_from_encoding(enc));
if (opt->intern.enc.index >= 0) {
- enc = rb_enc_from_index(opt->intern.enc.index);
- rb_enc_set_default_internal(rb_enc_from_encoding(enc));
- opt->intern.enc.index = -1;
+ enc = rb_enc_from_index(opt->intern.enc.index);
+ rb_enc_set_default_internal(rb_enc_from_encoding(enc));
+ opt->intern.enc.index = -1;
#if UTF8_PATH
- ienc = enc;
+ ienc = enc;
#endif
}
script_name = opt->script_name;
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);
- opt->script = RSTRING_PTR(opt->script_name);
+ opt->script_name = str_conv_enc(opt->script_name, uenc, lenc);
+ opt->script = RSTRING_PTR(opt->script_name);
}
#endif
rb_obj_freeze(opt->script_name);
if (IF_UTF8_PATH(uenc != lenc, 1)) {
- long i;
- rb_vm_t *vm = GET_VM();
+ long i;
VALUE load_path = vm->load_path;
- const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
+ const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
int modifiable = FALSE;
rb_get_expanded_load_path();
- for (i = 0; i < RARRAY_LEN(load_path); ++i) {
- VALUE path = RARRAY_AREF(load_path, i);
- int mark = rb_attr_get(path, id_initial_load_path_mark) == path;
+ for (i = 0; i < RARRAY_LEN(load_path); ++i) {
+ VALUE path = RARRAY_AREF(load_path, i);
+ int mark = rb_attr_get(path, id_initial_load_path_mark) == path;
#if UTF8_PATH
- VALUE newpath = rb_str_conv_enc(path, uenc, lenc);
- if (newpath == path) continue;
- path = newpath;
+ VALUE newpath = rb_str_conv_enc(path, uenc, lenc);
+ 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 (mark) rb_ivar_set(path, id_initial_load_path_mark, path);
if (!modifiable) {
rb_ary_modify(load_path);
modifiable = TRUE;
}
- RARRAY_ASET(load_path, i, path);
- }
+ RARRAY_ASET(load_path, i, path);
+ }
if (modifiable) {
rb_ary_replace(vm->load_path_snapshot, load_path);
}
}
+ {
+ 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;
+ if (!modified) {
+ rb_ary_modify(loaded_features);
+ modified = true;
+ }
+ RARRAY_ASET(loaded_features, i, path);
+ }
+ if (modified) {
+ rb_ary_replace(vm->loaded_features_snapshot, loaded_features);
+ }
+ }
if (opt->features.mask & COMPILATION_FEATURES) {
- VALUE option = rb_hash_new();
+ VALUE option = rb_hash_new();
#define SET_COMPILE_OPTION(h, o, name) \
- rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
- (FEATURE_SET_P(o->features, FEATURE_BIT(name)) ? Qtrue : Qfalse));
- SET_COMPILE_OPTION(option, opt, frozen_string_literal);
- SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
- rb_funcallv(rb_cISeq, rb_intern_const("compile_option="), 1, &option);
+ rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
+ RBOOL(FEATURE_SET_P(o->features, name)))
+ SET_COMPILE_OPTION(option, opt, frozen_string_literal);
+ SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
+ rb_funcallv(rb_cISeq, rb_intern_const("compile_option="), 1, &option);
#undef SET_COMPILE_OPTION
}
ruby_set_argv(argc, argv);
process_sflag(&opt->sflag);
- rb_parser_set_context(parser, 0, TRUE);
-
if (opt->e_script) {
- VALUE progname = rb_progname;
- rb_encoding *eenc;
- if (opt->src.enc.index >= 0) {
- eenc = rb_enc_from_index(opt->src.enc.index);
- }
- else {
- eenc = lenc;
+ VALUE progname = rb_progname;
+ rb_encoding *eenc;
+ rb_parser_set_context(parser, 0, TRUE);
+
+ if (opt->src.enc.index >= 0) {
+ eenc = rb_enc_from_index(opt->src.enc.index);
+ }
+ else {
+ eenc = lenc;
#if UTF8_PATH
- if (ienc) eenc = ienc;
+ if (ienc) eenc = ienc;
#endif
- }
+ }
#if UTF8_PATH
- if (eenc != uenc) {
- opt->e_script = str_conv_enc(opt->e_script, uenc, eenc);
- }
+ if (eenc != uenc) {
+ opt->e_script = str_conv_enc(opt->e_script, uenc, eenc);
+ }
#endif
- rb_enc_associate(opt->e_script, eenc);
+ rb_enc_associate(opt->e_script, eenc);
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);
- ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
+ rb_parser_set_options(parser, opt->do_print, opt->do_loop,
+ opt->do_line, opt->do_split);
+ ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
}
else {
- VALUE f;
- f = open_load_file(script_name, &opt->xflag);
- ast = load_file(parser, opt->script_name, f, 1, opt);
+ VALUE f;
+ f = open_load_file(script_name, &opt->xflag);
+ rb_parser_set_context(parser, 0, f == rb_stdin);
+ ast = load_file(parser, opt->script_name, f, 1, opt);
}
ruby_set_script_name(opt->script_name);
if (dump & DUMP_BIT(yydebug)) {
- dump &= ~DUMP_BIT(yydebug);
- if (!dump) return Qtrue;
+ dump &= ~DUMP_BIT(yydebug);
+ if (!dump) return Qtrue;
}
if (opt->ext.enc.index >= 0) {
- enc = rb_enc_from_index(opt->ext.enc.index);
+ enc = rb_enc_from_index(opt->ext.enc.index);
}
else {
- enc = IF_UTF8_PATH(uenc, lenc);
+ enc = IF_UTF8_PATH(uenc, lenc);
}
rb_enc_set_default_external(rb_enc_from_encoding(enc));
if (opt->intern.enc.index >= 0) {
- /* Set in the shebang line */
- enc = rb_enc_from_index(opt->intern.enc.index);
- rb_enc_set_default_internal(rb_enc_from_encoding(enc));
+ /* Set in the shebang line */
+ enc = rb_enc_from_index(opt->intern.enc.index);
+ rb_enc_set_default_internal(rb_enc_from_encoding(enc));
}
else if (!rb_default_internal_encoding())
- /* Freeze default_internal */
- rb_enc_set_default_internal(Qnil);
+ /* Freeze default_internal */
+ rb_enc_set_default_internal(Qnil);
rb_stdio_set_default_encoding();
if (!ast->body.root) {
- rb_ast_dispose(ast);
- return Qfalse;
+ rb_ast_dispose(ast);
+ return Qfalse;
}
process_sflag(&opt->sflag);
opt->xflag = 0;
if (dump & DUMP_BIT(syntax)) {
- printf("Syntax OK\n");
- dump &= ~DUMP_BIT(syntax);
- if (!dump) return Qtrue;
+ printf("Syntax OK\n");
+ dump &= ~DUMP_BIT(syntax);
+ if (!dump) return Qtrue;
}
if (opt->do_loop) {
- rb_define_global_function("sub", rb_f_sub, -1);
- rb_define_global_function("gsub", rb_f_gsub, -1);
- rb_define_global_function("chop", rb_f_chop, 0);
- rb_define_global_function("chomp", rb_f_chomp, -1);
+ rb_define_global_function("sub", rb_f_sub, -1);
+ rb_define_global_function("gsub", rb_f_gsub, -1);
+ rb_define_global_function("chop", rb_f_chop, 0);
+ rb_define_global_function("chomp", rb_f_chomp, -1);
}
if (dump & (DUMP_BIT(parsetree)|DUMP_BIT(parsetree_with_comment))) {
- rb_io_write(rb_stdout, rb_parser_dump_tree(ast->body.root, dump & DUMP_BIT(parsetree_with_comment)));
- rb_io_flush(rb_stdout);
- dump &= ~DUMP_BIT(parsetree)&~DUMP_BIT(parsetree_with_comment);
- if (!dump) {
- rb_ast_dispose(ast);
- return Qtrue;
- }
+ rb_io_write(rb_stdout, rb_parser_dump_tree(ast->body.root, dump & DUMP_BIT(parsetree_with_comment)));
+ rb_io_flush(rb_stdout);
+ dump &= ~DUMP_BIT(parsetree)&~DUMP_BIT(parsetree_with_comment);
+ if (!dump) {
+ rb_ast_dispose(ast);
+ return Qtrue;
+ }
}
{
- VALUE path = Qnil;
- if (!opt->e_script && strcmp(opt->script, "-")) {
- path = rb_realpath_internal(Qnil, script_name, 1);
+ VALUE path = Qnil;
+ if (!opt->e_script && strcmp(opt->script, "-")) {
+ path = rb_realpath_internal(Qnil, script_name, 1);
#if UTF8_PATH
- if (uenc != lenc) {
- path = str_conv_enc(path, uenc, lenc);
- }
+ if (uenc != lenc) {
+ path = str_conv_enc(path, uenc, lenc);
+ }
#endif
- if (!ENCODING_GET(path)) { /* ASCII-8BIT */
- rb_enc_copy(path, opt->script_name);
- }
- }
+ if (!ENCODING_GET(path)) { /* ASCII-8BIT */
+ rb_enc_copy(path, opt->script_name);
+ }
+ }
rb_binding_t *toplevel_binding;
GetBindingPtr(rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")),
toplevel_binding);
const struct rb_block *base_block = toplevel_context(toplevel_binding);
- iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block));
- rb_ast_dispose(ast);
+ iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block), !(dump & DUMP_BIT(insns_without_opt)));
+ rb_ast_dispose(ast);
}
- if (dump & DUMP_BIT(insns)) {
- rb_io_write(rb_stdout, rb_iseq_disasm((const rb_iseq_t *)iseq));
- rb_io_flush(rb_stdout);
- dump &= ~DUMP_BIT(insns);
- if (!dump) return Qtrue;
+ if (dump & (DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))) {
+ rb_io_write(rb_stdout, rb_iseq_disasm((const rb_iseq_t *)iseq));
+ rb_io_flush(rb_stdout);
+ dump &= ~DUMP_BIT(insns);
+ if (!dump) return Qtrue;
}
if (opt->dump & dump_exit_bits) return Qtrue;
@@ -2083,13 +2255,15 @@ static void
warn_cr_in_shebang(const char *str, long len)
{
if (str[len-1] == '\n' && str[len-2] == '\r') {
- rb_warn("shebang line ending with \\r may cause problems");
+ rb_warn("shebang line ending with \\r may cause problems");
}
}
#else
#define warn_cr_in_shebang(str, len) (void)0
#endif
+void rb_reset_argf_lineno(long n);
+
struct load_file_arg {
VALUE parser;
VALUE fname;
@@ -2114,114 +2288,115 @@ load_file_internal(VALUE argp_v)
CONST_ID(set_encoding, "set_encoding");
if (script) {
- VALUE c = 1; /* something not nil */
- VALUE line;
- char *p, *str;
- long len;
- int no_src_enc = !opt->src.enc.name;
- int no_ext_enc = !opt->ext.enc.name;
- int no_int_enc = !opt->intern.enc.name;
-
- enc = rb_ascii8bit_encoding();
- rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
-
- if (opt->xflag) {
- line_start--;
- search_shebang:
- while (!NIL_P(line = rb_io_gets(f))) {
- line_start++;
- RSTRING_GETMEM(line, str, len);
- if (len > 2 && str[0] == '#' && str[1] == '!') {
- if (line_start == 1) warn_cr_in_shebang(str, len);
- if ((p = strstr(str+2, ruby_engine)) != 0) {
- goto start_read;
- }
- }
- }
- rb_loaderror("no Ruby script found in input");
- }
-
- c = rb_io_getbyte(f);
- if (c == INT2FIX('#')) {
- c = rb_io_getbyte(f);
+ VALUE c = 1; /* something not nil */
+ VALUE line;
+ char *p, *str;
+ long len;
+ int no_src_enc = !opt->src.enc.name;
+ int no_ext_enc = !opt->ext.enc.name;
+ int no_int_enc = !opt->intern.enc.name;
+
+ enc = rb_ascii8bit_encoding();
+ rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
+
+ if (opt->xflag) {
+ line_start--;
+ search_shebang:
+ while (!NIL_P(line = rb_io_gets(f))) {
+ line_start++;
+ RSTRING_GETMEM(line, str, len);
+ if (len > 2 && str[0] == '#' && str[1] == '!') {
+ if (line_start == 1) warn_cr_in_shebang(str, len);
+ if ((p = strstr(str+2, ruby_engine)) != 0) {
+ goto start_read;
+ }
+ }
+ }
+ rb_loaderror("no Ruby script found in input");
+ }
+
+ c = rb_io_getbyte(f);
+ if (c == INT2FIX('#')) {
+ c = rb_io_getbyte(f);
if (c == INT2FIX('!') && !NIL_P(line = rb_io_gets(f))) {
- RSTRING_GETMEM(line, str, len);
- warn_cr_in_shebang(str, len);
- if ((p = strstr(str, ruby_engine)) == 0) {
- /* not ruby script, assume -x flag */
- goto search_shebang;
- }
-
- start_read:
- str += len - 1;
- if (*str == '\n') *str-- = '\0';
- if (*str == '\r') *str-- = '\0';
- /* ruby_engine should not contain a space */
- if ((p = strstr(p, " -")) != 0) {
- opt->warning = 0;
- moreswitches(p + 1, opt, 0);
- }
-
- /* push back shebang for pragma may exist in next line */
- rb_io_ungetbyte(f, rb_str_new2("!\n"));
- }
- else if (!NIL_P(c)) {
- rb_io_ungetbyte(f, c);
- }
- rb_io_ungetbyte(f, INT2FIX('#'));
- if (no_src_enc && opt->src.enc.name) {
- opt->src.enc.index = opt_enc_index(opt->src.enc.name);
- src_encoding_index = opt->src.enc.index;
- }
- if (no_ext_enc && opt->ext.enc.name) {
- opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
- }
- if (no_int_enc && opt->intern.enc.name) {
- opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
- }
- }
- else if (!NIL_P(c)) {
- rb_io_ungetbyte(f, c);
- }
+ RSTRING_GETMEM(line, str, len);
+ warn_cr_in_shebang(str, len);
+ if ((p = strstr(str, ruby_engine)) == 0) {
+ /* not ruby script, assume -x flag */
+ goto search_shebang;
+ }
+
+ start_read:
+ str += len - 1;
+ if (*str == '\n') *str-- = '\0';
+ if (*str == '\r') *str-- = '\0';
+ /* ruby_engine should not contain a space */
+ if ((p = strstr(p, " -")) != 0) {
+ opt->warning = 0;
+ moreswitches(p + 1, opt, 0);
+ }
+
+ /* push back shebang for pragma may exist in next line */
+ rb_io_ungetbyte(f, rb_str_new2("!\n"));
+ }
+ else if (!NIL_P(c)) {
+ rb_io_ungetbyte(f, c);
+ }
+ rb_io_ungetbyte(f, INT2FIX('#'));
+ if (no_src_enc && opt->src.enc.name) {
+ opt->src.enc.index = opt_enc_index(opt->src.enc.name);
+ src_encoding_index = opt->src.enc.index;
+ }
+ if (no_ext_enc && opt->ext.enc.name) {
+ opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
+ }
+ if (no_int_enc && opt->intern.enc.name) {
+ opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
+ }
+ }
+ else if (!NIL_P(c)) {
+ rb_io_ungetbyte(f, c);
+ }
if (NIL_P(c)) {
- argp->f = f = Qnil;
- }
+ argp->f = f = Qnil;
+ }
+ rb_reset_argf_lineno(0);
ruby_opt_init(opt);
}
if (opt->src.enc.index >= 0) {
- enc = rb_enc_from_index(opt->src.enc.index);
+ enc = rb_enc_from_index(opt->src.enc.index);
}
else if (f == rb_stdin) {
- enc = rb_locale_encoding();
+ enc = rb_locale_encoding();
}
else {
- enc = rb_utf8_encoding();
+ enc = rb_utf8_encoding();
}
rb_parser_set_options(parser, opt->do_print, opt->do_loop,
- opt->do_line, opt->do_split);
+ opt->do_line, opt->do_split);
if (NIL_P(f)) {
- f = rb_str_new(0, 0);
- rb_enc_associate(f, enc);
- return (VALUE)rb_parser_compile_string_path(parser, orig_fname, f, line_start);
+ f = rb_str_new(0, 0);
+ rb_enc_associate(f, enc);
+ return (VALUE)rb_parser_compile_string_path(parser, orig_fname, f, line_start);
}
rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
ast = rb_parser_compile_file_path(parser, orig_fname, f, line_start);
rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
if (script && rb_parser_end_seen_p(parser)) {
- /*
- * DATA is a File that contains the data section of the executed file.
- * To create a data section use <tt>__END__</tt>:
- *
- * $ cat t.rb
- * puts DATA.gets
- * __END__
- * hello world!
- *
- * $ ruby t.rb
- * hello world!
- */
- rb_define_global_const("DATA", f);
- argp->f = Qnil;
+ /*
+ * DATA is a File that contains the data section of the executed file.
+ * To create a data section use <tt>__END__</tt>:
+ *
+ * $ cat t.rb
+ * puts DATA.gets
+ * __END__
+ * hello world!
+ *
+ * $ ruby t.rb
+ * hello world!
+ */
+ rb_define_global_const("DATA", f);
+ argp->f = Qnil;
}
return (VALUE)ast;
}
@@ -2250,71 +2425,72 @@ static VALUE
open_load_file(VALUE fname_v, int *xflag)
{
const char *fname = (fname_v = rb_str_encode_ospath(fname_v),
- StringValueCStr(fname_v));
+ StringValueCStr(fname_v));
long flen = RSTRING_LEN(fname_v);
VALUE f;
int e;
if (flen == 1 && fname[0] == '-') {
- f = rb_stdin;
+ f = rb_stdin;
}
else {
- int fd;
- /* open(2) may block if fname is point to FIFO and it's empty. Let's
- use O_NONBLOCK. */
-#if defined O_NONBLOCK && HAVE_FCNTL && !(O_NONBLOCK & O_ACCMODE)
- /* TODO: fix conflicting O_NONBLOCK in ruby/win32.h */
-# define MODE_TO_LOAD (O_RDONLY | O_NONBLOCK)
-#elif defined O_NDELAY && HAVE_FCNTL && !(O_NDELAY & O_ACCMODE)
-# define MODE_TO_LOAD (O_RDONLY | O_NDELAY)
-#else
-# define MODE_TO_LOAD (O_RDONLY)
+ int fd;
+ /* open(2) may block if fname is point to FIFO and it's empty. Let's
+ use O_NONBLOCK. */
+ const int MODE_TO_LOAD = O_RDONLY | (
+#if defined O_NONBLOCK && HAVE_FCNTL
+ /* TODO: fix conflicting O_NONBLOCK in ruby/win32.h */
+ !(O_NONBLOCK & O_ACCMODE) ? O_NONBLOCK :
+#endif
+#if defined O_NDELAY && HAVE_FCNTL
+ !(O_NDELAY & O_ACCMODE) ? O_NDELAY :
#endif
- int mode = MODE_TO_LOAD;
+ 0);
+ int mode = MODE_TO_LOAD;
#if defined DOSISH || defined __CYGWIN__
# define isdirsep(x) ((x) == '/' || (x) == '\\')
- {
- static const char exeext[] = ".exe";
- enum {extlen = sizeof(exeext)-1};
- if (flen > extlen && !isdirsep(fname[flen-extlen-1]) &&
- STRNCASECMP(fname+flen-extlen, exeext, extlen) == 0) {
- mode |= O_BINARY;
- *xflag = 1;
- }
- }
-#endif
-
- if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
- e = errno;
- if (!rb_gc_for_fd(e)) {
- rb_load_fail(fname_v, strerror(e));
- }
- if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
- rb_load_fail(fname_v, strerror(errno));
- }
- }
- rb_update_max_fd(fd);
-
- if (MODE_TO_LOAD != O_RDONLY && (e = disable_nonblock(fd)) != 0) {
- (void)close(fd);
- rb_load_fail(fname_v, strerror(e));
- }
-
- e = ruby_is_fd_loadable(fd);
- if (!e) {
- e = errno;
- (void)close(fd);
- rb_load_fail(fname_v, strerror(e));
- }
-
- f = rb_io_fdopen(fd, mode, fname);
- if (e < 0) {
- /*
- We need to wait if FIFO is empty. It's FIFO's semantics.
- rb_thread_wait_fd() release GVL. So, it's safe.
- */
- rb_io_wait(f, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
- }
+ {
+ static const char exeext[] = ".exe";
+ enum {extlen = sizeof(exeext)-1};
+ if (flen > extlen && !isdirsep(fname[flen-extlen-1]) &&
+ STRNCASECMP(fname+flen-extlen, exeext, extlen) == 0) {
+ mode |= O_BINARY;
+ *xflag = 1;
+ }
+ }
+#endif
+
+ if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
+ e = errno;
+ if (!rb_gc_for_fd(e)) {
+ rb_load_fail(fname_v, strerror(e));
+ }
+ if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
+ rb_load_fail(fname_v, strerror(errno));
+ }
+ }
+ rb_update_max_fd(fd);
+
+ if (MODE_TO_LOAD != O_RDONLY && (e = disable_nonblock(fd)) != 0) {
+ (void)close(fd);
+ rb_load_fail(fname_v, strerror(e));
+ }
+
+ e = ruby_is_fd_loadable(fd);
+ if (!e) {
+ e = errno;
+ (void)close(fd);
+ rb_load_fail(fname_v, strerror(e));
+ }
+
+ f = rb_io_fdopen(fd, mode, fname);
+ if (e < 0) {
+ /*
+ We need to wait if FIFO is empty. It's FIFO's semantics.
+ rb_thread_wait_fd() release GVL. So, it's safe.
+ */
+ rb_io_wait(f, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
+ }
}
return f;
}
@@ -2326,7 +2502,7 @@ restore_load_file(VALUE arg)
VALUE f = argp->f;
if (!NIL_P(f) && f != rb_stdin) {
- rb_io_close(f);
+ rb_io_close(f);
}
return Qnil;
}
@@ -2341,7 +2517,7 @@ load_file(VALUE parser, VALUE fname, VALUE f, int script, ruby_cmdline_options_t
arg.opt = opt;
arg.f = f;
return (rb_ast_t *)rb_ensure(load_file_internal, (VALUE)&arg,
- restore_load_file, (VALUE)&arg);
+ restore_load_file, (VALUE)&arg);
}
void *
@@ -2419,7 +2595,7 @@ static void
set_arg0(VALUE val, ID id, VALUE *_)
{
if (origarg.argv == 0)
- rb_raise(rb_eRuntimeError, "$0 not initialized");
+ rb_raise(rb_eRuntimeError, "$0 not initialized");
rb_progname = rb_str_new_frozen(ruby_setproctitle(val));
}
@@ -2436,17 +2612,12 @@ external_str_new_cstr(const char *p)
#endif
}
-/*! Sets the current script name to this value.
- *
- * This is similar to <code>$0 = name</code> in Ruby level but also affects
- * <code>Method#location</code> and others.
- */
void
ruby_script(const char *name)
{
if (name) {
- rb_orig_progname = rb_progname = external_str_new_cstr(name);
- rb_vm_set_progname(rb_progname);
+ rb_orig_progname = rb_progname = external_str_new_cstr(name);
+ rb_vm_set_progname(rb_progname);
}
}
@@ -2502,13 +2673,13 @@ opt_W_getter(ID id, VALUE *dmy)
switch (v) {
case Qnil:
- return INT2FIX(0);
+ return INT2FIX(0);
case Qfalse:
- return INT2FIX(1);
+ return INT2FIX(1);
case Qtrue:
- return INT2FIX(2);
+ return INT2FIX(2);
default:
- return Qnil;
+ return Qnil;
}
}
@@ -2524,7 +2695,6 @@ debug_setter(VALUE val, ID id, VALUE *dmy)
*rb_ruby_debug_ptr() = val;
}
-/*! Defines built-in variables */
void
ruby_prog_init(void)
{
@@ -2565,10 +2735,10 @@ ruby_set_argv(int argc, char **argv)
rb_ary_clear(av);
for (i = 0; i < argc; i++) {
- VALUE arg = external_str_new_cstr(argv[i]);
+ VALUE arg = external_str_new_cstr(argv[i]);
- OBJ_FREEZE(arg);
- rb_ary_push(av, arg);
+ OBJ_FREEZE(arg);
+ rb_ary_push(av, arg);
}
}
@@ -2580,8 +2750,8 @@ ruby_process_options(int argc, char **argv)
const char *script_name = (argc > 0 && argv[0]) ? argv[0] : ruby_engine;
if (!origarg.argv || origarg.argc <= 0) {
- origarg.argc = argc;
- origarg.argv = argv;
+ origarg.argc = argc;
+ origarg.argv = argv;
}
ruby_script(script_name); /* for the time being */
rb_argv0 = rb_str_new4(rb_progname);
@@ -2625,13 +2795,6 @@ fill_standard_fds(void)
}
}
-/*! Initializes the process for libruby.
- *
- * This function assumes this process is ruby(1) and it has just started.
- * Usually programs that embed CRuby interpreter may not call this function,
- * and may do their own initialization.
- * argc and argv cannot be NULL.
- */
void
ruby_sysinit(int *argc, char ***argv)
{
@@ -2639,8 +2802,8 @@ ruby_sysinit(int *argc, char ***argv)
rb_w32_sysinit(argc, argv);
#endif
if (*argc >= 0 && *argv) {
- origarg.argc = *argc;
- origarg.argv = *argv;
+ origarg.argc = *argc;
+ origarg.argv = *argv;
}
fill_standard_fds();
}
diff --git a/ruby_assert.h b/ruby_assert.h
index ddd348c7d3..d8f7ddd35b 100644
--- a/ruby_assert.h
+++ b/ruby_assert.h
@@ -1,7 +1,6 @@
#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
diff --git a/rubystub.c b/rubystub.c
index 1b10cdd4c4..75aeca1869 100644
--- a/rubystub.c
+++ b/rubystub.c
@@ -1,4 +1,5 @@
#include "internal.h"
+#include "internal/missing.h"
#if defined HAVE_DLADDR
#include <dlfcn.h>
#endif
@@ -23,23 +24,23 @@ stub_options(int argc, char **argv)
* use argv[0] as is */
#elif defined __linux__
{
- char selfexe[MAXPATHLEN];
- ssize_t len = readlink("/proc/self/exe", selfexe, sizeof(selfexe));
- if (len < 0) {
- perror("readlink(\"/proc/self/exe\")");
- return NULL;
- }
- selfexe[len] = '\0';
- cmd = selfexe;
+ char selfexe[MAXPATHLEN];
+ ssize_t len = readlink("/proc/self/exe", selfexe, sizeof(selfexe));
+ if (len < 0) {
+ perror("readlink(\"/proc/self/exe\")");
+ return NULL;
+ }
+ selfexe[len] = '\0';
+ cmd = selfexe;
}
#elif defined HAVE_DLADDR
{
- Dl_info dli;
- if (!dladdr(stub_options, &dli)) {
- perror("dladdr");
- return NULL;
- }
- cmd = (char *)dli.dli_fname;
+ Dl_info dli;
+ if (!dladdr(stub_options, &dli)) {
+ perror("dladdr");
+ return NULL;
+ }
+ cmd = (char *)dli.dli_fname;
}
#endif
diff --git a/sample/coverage.rb b/sample/coverage.rb
index 8e8d6167e2..42ba89fd50 100644
--- a/sample/coverage.rb
+++ b/sample/coverage.rb
@@ -49,7 +49,7 @@ at_exit do
end
end
- open(cfile, "w") do |out|
+ File.open(cfile, "w") do |out|
covs.zip(sources, pcovs).each_with_index do |(cov, line, pcov), idx|
cov += pcov || 0 if cov
cov = (cov ? (cov == 0 ? "#####" : cov.to_s) : "-").rjust(9)
diff --git a/sample/drb/README.ja.rdoc b/sample/drb/README.ja.rdoc
index 3ab70f3369..1697b1b704 100644
--- a/sample/drb/README.ja.rdoc
+++ b/sample/drb/README.ja.rdoc
@@ -50,7 +50,7 @@
* drbssl_s.rb
* drbssl_c.rb
-* DRbProtoclの追加例
+* DRbProtocolの追加例
* http0.rb
* http0serv.rb
diff --git a/sample/drb/README.rdoc b/sample/drb/README.rdoc
index 80ae910a8a..e6b457bc5c 100644
--- a/sample/drb/README.rdoc
+++ b/sample/drb/README.rdoc
@@ -1,6 +1,6 @@
= Sample scripts
-* array and iteretor
+* array and iterator
* darray.rb --- server
* darrayc.rb --- client
@@ -47,7 +47,7 @@
* drbssl_s.rb
* drbssl_c.rb
-* add DRbProtocl
+* add DRbProtocol
* http0.rb
* http0serv.rb
diff --git a/sample/exyacc.rb b/sample/exyacc.rb
index 9a9435a0dc..cbcc18d58b 100644
--- a/sample/exyacc.rb
+++ b/sample/exyacc.rb
@@ -8,7 +8,7 @@ ARGF.each(nil) do |source|
grammar = source[sbeg, send-sbeg]
grammar.sub!(/.*\n/, "")
grammar.gsub!(/'\{'/, "'\001'")
- grammar.gsub!(/'\}'/, "'\002'")
+ grammar.gsub!(/["']\}["']/, "'\002'")
grammar.gsub!(%r{\*/}, "\003\003")
grammar.gsub!(%r{/\*[^\003]*\003\003}, '')
while grammar.gsub!(/\{[^{}]*\}/, ''); end
diff --git a/sample/from.rb b/sample/from.rb
index db1299c869..0e5a08de5f 100644
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -62,7 +62,7 @@ def from_main
if File.exist?(file)
atime = File.atime(file)
mtime = File.mtime(file)
- open(file, "r") do |f|
+ File.open(file, "r") do |f|
until f.eof?
header = {}
f.each_line do |line|
diff --git a/sample/getoptlong/abbrev.rb b/sample/getoptlong/abbrev.rb
new file mode 100644
index 0000000000..9b89863626
--- /dev/null
+++ b/sample/getoptlong/abbrev.rb
@@ -0,0 +1,9 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', GetoptLong::NO_ARGUMENT],
+ ['--xyz', GetoptLong::NO_ARGUMENT]
+)
+options.each do |option, argument|
+ p [option, argument]
+end
diff --git a/sample/getoptlong/aliases.rb b/sample/getoptlong/aliases.rb
new file mode 100644
index 0000000000..895254c6ae
--- /dev/null
+++ b/sample/getoptlong/aliases.rb
@@ -0,0 +1,8 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', '-x', '--aaa', '-a', '-p', GetoptLong::NO_ARGUMENT]
+)
+options.each do |option, argument|
+ p [option, argument]
+end
diff --git a/sample/getoptlong/argv.rb b/sample/getoptlong/argv.rb
new file mode 100644
index 0000000000..8efcad22ea
--- /dev/null
+++ b/sample/getoptlong/argv.rb
@@ -0,0 +1,12 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', GetoptLong::REQUIRED_ARGUMENT],
+ ['--yyy', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--zzz', GetoptLong::NO_ARGUMENT]
+)
+puts "Original ARGV: #{ARGV}"
+options.each do |option, argument|
+ p [option, argument]
+end
+puts "Remaining ARGV: #{ARGV}"
diff --git a/sample/getoptlong/each.rb b/sample/getoptlong/each.rb
new file mode 100644
index 0000000000..661e0a968f
--- /dev/null
+++ b/sample/getoptlong/each.rb
@@ -0,0 +1,12 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', '-x', GetoptLong::REQUIRED_ARGUMENT],
+ ['--yyy', '-y', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--zzz', '-z',GetoptLong::NO_ARGUMENT]
+)
+puts "Original ARGV: #{ARGV}"
+options.each do |option, argument|
+ p [option, argument]
+end
+puts "Remaining ARGV: #{ARGV}"
diff --git a/sample/getoptlong/fibonacci.rb b/sample/getoptlong/fibonacci.rb
new file mode 100644
index 0000000000..24a2aab3c3
--- /dev/null
+++ b/sample/getoptlong/fibonacci.rb
@@ -0,0 +1,62 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--number', '-n', GetoptLong::REQUIRED_ARGUMENT],
+ ['--verbose', '-v', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--help', '-h', GetoptLong::NO_ARGUMENT]
+)
+
+def help(status = 0)
+ puts <<~HELP
+ Usage:
+
+ -n n, --number n:
+ Compute Fibonacci number for n.
+ -v [boolean], --verbose [boolean]:
+ Show intermediate results; default is 'false'.
+ -h, --help:
+ Show this help.
+ HELP
+ exit(status)
+end
+
+def print_fibonacci (number)
+ return 0 if number == 0
+ return 1 if number == 1 or number == 2
+ i = 0
+ j = 1
+ (2..number).each do
+ k = i + j
+ i = j
+ j = k
+ puts j if @verbose
+ end
+ puts j unless @verbose
+end
+
+options.each do |option, argument|
+ case option
+ when '--number'
+ @number = argument.to_i
+ when '--verbose'
+ @verbose = if argument.empty?
+ true
+ elsif argument.match(/true/i)
+ true
+ elsif argument.match(/false/i)
+ false
+ else
+ puts '--verbose argument must be true or false'
+ help(255)
+ end
+ when '--help'
+ help
+ end
+end
+
+unless @number
+ puts 'Option --number is required.'
+ help(255)
+end
+
+print_fibonacci(@number)
diff --git a/sample/getoptlong/permute.rb b/sample/getoptlong/permute.rb
new file mode 100644
index 0000000000..8efcad22ea
--- /dev/null
+++ b/sample/getoptlong/permute.rb
@@ -0,0 +1,12 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', GetoptLong::REQUIRED_ARGUMENT],
+ ['--yyy', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--zzz', GetoptLong::NO_ARGUMENT]
+)
+puts "Original ARGV: #{ARGV}"
+options.each do |option, argument|
+ p [option, argument]
+end
+puts "Remaining ARGV: #{ARGV}"
diff --git a/sample/getoptlong/require_order.rb b/sample/getoptlong/require_order.rb
new file mode 100644
index 0000000000..357f667905
--- /dev/null
+++ b/sample/getoptlong/require_order.rb
@@ -0,0 +1,13 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', GetoptLong::REQUIRED_ARGUMENT],
+ ['--yyy', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--zzz', GetoptLong::NO_ARGUMENT]
+)
+options.ordering = GetoptLong::REQUIRE_ORDER
+puts "Original ARGV: #{ARGV}"
+options.each do |option, argument|
+ p [option, argument]
+end
+puts "Remaining ARGV: #{ARGV}"
diff --git a/sample/getoptlong/return_in_order.rb b/sample/getoptlong/return_in_order.rb
new file mode 100644
index 0000000000..91ce1ef996
--- /dev/null
+++ b/sample/getoptlong/return_in_order.rb
@@ -0,0 +1,13 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', GetoptLong::REQUIRED_ARGUMENT],
+ ['--yyy', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--zzz', GetoptLong::NO_ARGUMENT]
+)
+options.ordering = GetoptLong::RETURN_IN_ORDER
+puts "Original ARGV: #{ARGV}"
+options.each do |option, argument|
+ p [option, argument]
+end
+puts "Remaining ARGV: #{ARGV}"
diff --git a/sample/getoptlong/simple.rb b/sample/getoptlong/simple.rb
new file mode 100644
index 0000000000..1af6447632
--- /dev/null
+++ b/sample/getoptlong/simple.rb
@@ -0,0 +1,7 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--number', '-n', GetoptLong::REQUIRED_ARGUMENT],
+ ['--verbose', '-v', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--help', '-h', GetoptLong::NO_ARGUMENT]
+)
diff --git a/sample/getoptlong/types.rb b/sample/getoptlong/types.rb
new file mode 100644
index 0000000000..ac74bfe12e
--- /dev/null
+++ b/sample/getoptlong/types.rb
@@ -0,0 +1,10 @@
+require 'getoptlong'
+
+options = GetoptLong.new(
+ ['--xxx', GetoptLong::REQUIRED_ARGUMENT],
+ ['--yyy', GetoptLong::OPTIONAL_ARGUMENT],
+ ['--zzz', GetoptLong::NO_ARGUMENT]
+)
+options.each do |option, argument|
+ p [option, argument]
+end
diff --git a/sample/mine.rb b/sample/mine.rb
index a841d1a60a..77e0204bf6 100755
--- a/sample/mine.rb
+++ b/sample/mine.rb
@@ -1,6 +1,8 @@
#! /usr/bin/ruby -Ku
# -*- coding: utf-8 -*-
+require 'io/console'
+
class Board
def clr
print "\e[2J"
@@ -143,8 +145,8 @@ class Board
end
bd=Board.new(10,10,10)
-system("stty raw -echo")
-begin
+
+IO.console.raw do
loop do
case STDIN.getc
when ?n # new game
@@ -170,7 +172,5 @@ begin
bd.reset
end
end
-ensure
- system("stty -raw echo")
end
print "\n"
diff --git a/sample/mpart.rb b/sample/mpart.rb
index a88eba0ef6..eeb895d3de 100644
--- a/sample/mpart.rb
+++ b/sample/mpart.rb
@@ -2,11 +2,29 @@
# split into multi part
# usage: mpart.rb [-nnn] file..
+class MPart < File
+ def self.new(basename, extname, part, parts)
+ super(sprintf("%s.%s%02d", basename, extname, part), "w").
+ begin_mpart(basename, part, parts)
+ end
+
+ def begin_mpart(basename, part, parts)
+ printf("%s part%02d/%02d\n", basename, part, parts)
+ write("BEGIN--cut here--cut here\n")
+ self
+ end
+
+ def close
+ write("END--cut here--cut here\n")
+ super
+ end
+end
+
lines = 1000
if (ARGV[0] =~ /^-(\d+)$/ )
- lines = $1.to_i;
- ARGV.shift;
+ lines = $1.to_i
+ ARGV.shift
end
basename = ARGV[0]
@@ -14,31 +32,23 @@ extname = "part"
part = 1
line = 0
+ofp = nil
fline = 0
-for i in ifp = open(basename)
- fline = fline + 1
-end
-ifp.close
+File.foreach(basename) {fline += 1}
parts = fline / lines + 1
-for i in ifp = open(basename)
+File.foreach(basename) do |i|
if line == 0
- ofp = open(sprintf("%s.%s%02d", basename, extname, part), "w")
- printf(ofp, "%s part%02d/%02d\n", basename, part, parts)
- ofp.write("BEGIN--cut here--cut here\n")
+ ofp = MPart.new(basename, extname, part, parts)
end
ofp.write(i)
- line = line + 1
- if line >= lines and !ifp.eof?
- ofp.write("END--cut here--cut here\n")
+ line += 1
+ if line >= lines
ofp.close
- part = part + 1
+ part += 1
line = 0
end
end
-ofp.write("END--cut here--cut here\n")
ofp.close
-
-ifp.close
diff --git a/sample/trick2015/kinaba/entry.rb b/sample/trick2015/kinaba/entry.rb
index aa077dc240..2a75888ef5 100644
--- a/sample/trick2015/kinaba/entry.rb
+++ b/sample/trick2015/kinaba/entry.rb
@@ -54,8 +54,8 @@ while 0x00012345 >= $counter
srand +big && $counter >> 0b1
Enumerable
- Fixnum
- Bignum
+ String
+ Struct
Math
Complex
Comparable
diff --git a/sample/trick2018/02-mame/entry.rb b/sample/trick2018/02-mame/entry.rb
index cc4ef9cbc4..ced791aa3d 100644
--- a/sample/trick2018/02-mame/entry.rb
+++ b/sample/trick2018/02-mame/entry.rb
@@ -1,11 +1,11 @@
'';eval(r=%q(->z{r="'';eval(r=\
-%q(#{r}))[%q`#{z}`]";i=-040;30.
+%q(#{r}))[%q`#{z}`]";i=-040;31.
times{|n|(15+n%2*15-n/2).times{
r<<r[i+=(1.-n&2)*(32-n%2*31)]}}
i=r[524,0]=?\0;eval(r[479..-1])
c['"']}))[%q`GFEDCBA"+"[e\"'"'t
kE*;;\";" TRICK2018 ";tb,;{{r
-2E0$ob[us@*0)[90,336])_#i\n}s#i
+2E0$ob[us@*0)[90,336])#_i\n}s#i
0H}>["t]];};o[1,?\n*8];ex"-}eac
1Hl<1[-1]*2*t=n%2];o[14-n,0)mvk
8M$<4,?\n];15.times{|n|;o[35ie2
diff --git a/sample/trick2022/01-tompng/Gemfile b/sample/trick2022/01-tompng/Gemfile
new file mode 100644
index 0000000000..982b9de67f
--- /dev/null
+++ b/sample/trick2022/01-tompng/Gemfile
@@ -0,0 +1,2 @@
+source 'https://rubygems.org'
+gem 'matrix'
diff --git a/sample/trick2022/01-tompng/Gemfile.lock b/sample/trick2022/01-tompng/Gemfile.lock
new file mode 100644
index 0000000000..8bb3c69025
--- /dev/null
+++ b/sample/trick2022/01-tompng/Gemfile.lock
@@ -0,0 +1,13 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ matrix (0.4.2)
+
+PLATFORMS
+ x86_64-darwin-20
+
+DEPENDENCIES
+ matrix
+
+BUNDLED WITH
+ 2.3.3
diff --git a/sample/trick2022/01-tompng/authors.markdown b/sample/trick2022/01-tompng/authors.markdown
new file mode 100644
index 0000000000..26ebe24da6
--- /dev/null
+++ b/sample/trick2022/01-tompng/authors.markdown
@@ -0,0 +1,3 @@
+* Tomoya Ishida (tompng)
+ * tomoyapenguin@gmail.com
+ * cctld: jp
diff --git a/sample/trick2022/01-tompng/entry.rb b/sample/trick2022/01-tompng/entry.rb
new file mode 100644
index 0000000000..97beacc684
--- /dev/null
+++ b/sample/trick2022/01-tompng/entry.rb
@@ -0,0 +1,40 @@
+ eval((s=%~c=(0..35
+ ).map{s[2*_1+1]}*'';class$Inte
+ ger;def$quXinclude(Math ;spXo(a)=self*
+ a.pow(87X=h=32.chr;g=PI/480;ls=(sp*31X,89)%89;
+ def$abX+'eval((s=%'+(n=? .next)+s*88.chr+[nXs()=[a
+ =self%X+'.split(',sp*25+'?'+88.chr+');(0..36).mapX89,89-
+ a].miX{s[2*_1].split}',sp*31+".join.tr('$',$/)))"]*$/)Xn;end
+ ;reqX.split$/;trap(:INT){puts;exit};q=->t,i{a,y=((t+i*99)Xuire
+ 'matrX%960). ivmod(80);[(a*(7+i)+i*23)%79+(y+a)/(5+i%4)%2,39Xix';1
+ 5.tiX-y/2]};p=->t,u{a=->b,c{(0..5).sum{(u%2-1)*E**(t*(b+c*_1)*gXmes{
+ |i,*X.i+ i*u+=5+sin(u*u))}};x,z=a[5,3]. 5,3].rect;x+=y.Xv|z=
+ *?!Xi a[19,4];z+=w;r=(4+(x.abs+z.i).ab };t=(0..959).fX..?
+ W,?Xind{|t|(0..29).all?{x,y=q[t,_1];(x 2||h=ls[y][x]X[,*
+ ?]..X[/[^!-}]/]}};h=($**h+h).chr;eval( []} ->(x,yX?};a
+ =(0X,a,b){x=x*36+39.5;y=19.5-y*18;b*=1 |i|((yX..1
+ 34)X-b).ceil..y+b).map{|j|((x-i)/a+(y j)/ .times{X.ma
+ p{zXx,z=p[t,_1];l=u```=0;while``````(l<1)``; u+```=0 ;d=x-y;X.in
+dex(Xl+=(d.abs+(z-w``)``.i).ab``s*1.``1 ;x``,z=y``,w;o[v``=``x.r d.imag/Xc[i+
+15*Xd.abs*l*sin(2*``l-t``*g*80``-_1) l*(``1-l)/``6,a``=l*( -l)**2*0.X_1]
+)};X7,a*2]&&o[v,z,``0.0``3,l**`` ``times``{|i``|(8+i).times{|Xw=*
+MatXj|o[sin(i)/2+````` ```sin( `/2.0`````````)*j/200,j*0.0Xrix
+[*(X5-1,0.02,0.1]``}} ``. q[t,``_1];m``[y][x]= };i=-X0..
+44).X1;$><<(['%%','[H .map{|j|(0..79).map{|k|x=(Xmap{
+ |i,X -39.5)/35.8;y=( i+=1;m[j][k]?h:c[i]):ls[j]X*b|
+ v<<X[k];}*''}*$/<<0) 1)%9 te"`")#qv.jSaL{=;q(Q}4fXa.z
+ ip(Xjs(:#tK`Jm))FKO /A9(2'%iorvf7 eEa0uV xv+Q@qUU](L@&Py .1v'X0..
+ ).suXydSEH{-GI|-5(,z G5evpq,[b50 D[ t {on,I?VStS`?G@LoqFCXm{|j
+ ,k|Xj1.QnxKz!mH%o# )b2Seut,]! 48 lBieJGi 5jeNPD#b}H3X-(p
+ =(iXaVz#8*+US,hgF 5#6]y-` 4hy HN hF75WjD!0IxJ$sX+k)
+ .powX+UP"cNUE9- G< tHvV;Ib <-s U T ? vlE xylg=x#X(i+k
+ ,88)XV9u$9lKb9 @C do7+-w >l { v9 { P l ga%]AK<e&'X+1)*
+ (j||(X4ifK/6S+ k} @@*a} 6rS xn"Q[M 8 `|g>$#BrjXb<<p;
+ 0))}XtbDp'Kc t2 Dat9C s C rL+ g,j]Tf B< eMI+zzkWX;b}]
+ .lup.XtVP<ak IM E/+)B jwv uB (Twqed D* dyf_dT7Xsolve
+ (v);13Xn:8 #_ RiSTO, [Fk m O]O#"+ a_ cT_.X5.time
+ s{c[i+X e5 T`FBEC q*f 2 o@{a<eUG aW PX15*_1]
+ =z[a[_1]X z_@`nll 7F1 2 [=^uS0z^ 6X||w.shif
+ t]}};eval(Xfg K#R N bp-E_Xc)~.split(
+ ?X);(0..36).map{s[2*_1].split}
+ .join.tr('$',$/)))
diff --git a/sample/trick2022/01-tompng/remarks.markdown b/sample/trick2022/01-tompng/remarks.markdown
new file mode 100644
index 0000000000..70601908b7
--- /dev/null
+++ b/sample/trick2022/01-tompng/remarks.markdown
@@ -0,0 +1,51 @@
+### Remarks
+
+Just run it with no argument:
+
+ ruby entry.rb
+
+Or run it with one non-ascii half-width character argument:
+
+ ruby entry.rb ⬮
+ ruby entry.rb 𓆡
+
+I confirmed the following implementations/platforms:
+
+* ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
+* ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-darwin20]
+
+### Description
+
+This program is an aquatic quine.
+Some characters in the code are overwritten with `" "`, but this program can restore the missing parts.
+Every frame of this animation is an executable ruby program that let fishes start swimming again from their current position.
+
+### Internals
+
+#### Error Correction
+
+Error correction is performed for each block of length 135.
+It consists of 89 kinds of characters(`[*('!'..'W'), '[', *(']'..'}')]`) and satisfies the following constraint.
+
+```
+matrix(size: 45x135) * block_vector(size: 135) % 89 == zero_vector(size: 45)
+```
+
+To restore the missing characters in the block, we need to solve a linear equation problem in modulo 89.
+This can be achieved by using bundled gem 'matrix' and overwriting some methods.
+
+```ruby
+require 'matrix'
+matrix = Matrix[[3, 1, 4], [1, 5, 9], [2, 6, 5]]
+class Integer
+ def quo(x) = self * x.pow(87, 89) % 89 # Fermat's little theorem. 89 is a prime number.
+ def abs() = [self % 89, 89 - self % 89].min # To avoid division by multiple of 89.
+end
+answer = matrix.lup.solve([1, 2, 3]) #=> Vector[24, 42, 83]
+(matrix * answer).map { _1 % 89 } #=> Vector[1, 2, 3]
+```
+
+#### Resuming Animation
+
+The entire animation of this fish tank is a loop of 960 frames.
+This program uses position of the floating bubbles to detect current frame number from the executed source code.
diff --git a/sample/trick2022/02-tompng/authors.markdown b/sample/trick2022/02-tompng/authors.markdown
new file mode 100644
index 0000000000..26ebe24da6
--- /dev/null
+++ b/sample/trick2022/02-tompng/authors.markdown
@@ -0,0 +1,3 @@
+* Tomoya Ishida (tompng)
+ * tomoyapenguin@gmail.com
+ * cctld: jp
diff --git a/sample/trick2022/02-tompng/entry.rb b/sample/trick2022/02-tompng/entry.rb
new file mode 100644
index 0000000000..2e2e2bcf74
--- /dev/null
+++ b/sample/trick2022/02-tompng/entry.rb
@@ -0,0 +1,32 @@
+ q=->{!sleep _1/1e2};p=(
+ c=0..2).map{[_1/9r ,0,5**_1.i/3,1,0]}
+ require'socket';puts'op' "en http://localhost:#{(
+ w=TCPServer.new$*[0]||0).addr[1]}";Thread.new{q[2];f=[-1
+ ]*s=3;t=Time.now.to_f;p.select!{0<_1[3]=[_1[3]+_1[4]/8.0,1
+ ].min};9.times{h=p.map{[2**(_1*t.i)/_4**0.5/(1+Math.sin(2*t-
+ 9*_1%2)**32/16),_2+_4*( _3-_2)]};r=[s*3/2,84].min;g=->{x,y=
+(s*(1+_1+1i)/2).rect;x<0 ||x>=s-1||y<0||y>=s-1?0:((l=f[y+1])[
+x+1]*(a=x%1)+(1-a)*l[x] )*(b=y%1)+(1-b)*((l=f[y])[x+1]*a+(1-
+a)*l[x])};f=(1..r).map {|y|(1..r).map{|x|z=1.5+1.5i-3.0*(y
+.i+x)/r;[h.sum{g[_1.*z +_2]}*0.9,1].min}};s=r};c=f.flatten
+redo};loop{s=w.accept ; Thread.new{r=s.gets;h='HTTP/1.1 '+
+"200 OK\r\nContent-" 'T' "ype:text/html\r\n\r\n";r['/ ']?s.
+ <<(h+'<style>ifram' 'e{' 'opacity:0;height:0;}input{wid'+
+ 'th:252px;}</styl' 'e>' '<form target="i"><input src="'+
+ "g#{rand}\" type" '="im' 'age"><iframe name="i"></ifra'+
+ 'me></form>'):r ['/g'] ?(h[/:.+l/]=?:'image/gif';s<<
+ h+'GIF8' '7a'+[84,
+ 84,246,0,*(0..383).map {15*_1. /(383r)**(3-_1%
+ 3)*17}].pack('v3c*'); loop{ s<<[67434785,5,
+ 44,84,84,7,c.map{_1* 127} .each_slice(126
+ ).map{[127,128,*_1 ] .pack'c*'}*'',
+ 1,129].pack('V3x' 'v2na*c2x');q[
+ 5];q.[]1while(r ==r=c)}):(x,y,
+ z=r.scan(/\d+/).map{_1.to_f/
+ 126-1};z&&p<<[rand-0.5,(
+ z=x+y.i)*1.5,z/(z.
+ abs+0.9),0,-p[
+ -3][4]=-1]
+ s.<<h);s
+ .close
+ }}
diff --git a/sample/trick2022/02-tompng/remarks.markdown b/sample/trick2022/02-tompng/remarks.markdown
new file mode 100644
index 0000000000..3b2d3fd84b
--- /dev/null
+++ b/sample/trick2022/02-tompng/remarks.markdown
@@ -0,0 +1,32 @@
+### Remarks
+
+1. Run it with `ruby entry.rb 8080`
+
+2. Open "http://localhost:8080"
+
+3. Click on the screen and interact with it
+
+I confirmed the following implementations/platforms:
+
+* Ruby Version
+ * ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-darwin20]
+* Browser
+ * Chrome(macOS, Android)
+ * Firefox(macOS)
+ * Edge(macOS)
+
+### Description
+
+This program is an HTTP server that provides a fractal creature playground.
+You can see the heartbeat of a mysterious fractal creature. Clicking on the screen will change the shape of the creature.
+Surprisingly, this interactive webpage is built without JavaScript.
+
+### Internals
+
+Fractal: Iterated function system
+Rendering from server: Streaming animated GIF
+Sending click event to server: `<input type="image" src="streaming.gif">` with `<form target="invisible_iframe">`
+
+### Limitations
+
+Does not work on Safari and iOS.
diff --git a/sample/trick2022/03-mame/authors.markdown b/sample/trick2022/03-mame/authors.markdown
new file mode 100644
index 0000000000..0e420fdf5d
--- /dev/null
+++ b/sample/trick2022/03-mame/authors.markdown
@@ -0,0 +1,3 @@
+* Yusuke Endoh
+ * mame@ruby-lang.org
+ * cctld: jp
diff --git a/sample/trick2022/03-mame/entry.rb b/sample/trick2022/03-mame/entry.rb
new file mode 100644
index 0000000000..f24595dfa9
--- /dev/null
+++ b/sample/trick2022/03-mame/entry.rb
@@ -0,0 +1,27 @@
+2022;"#
+
+.chars} {puts'TRICK+2022'
+ \ { ;
+#';$><< b
+ ?!
+};#{s=' ' # 0
+! s[0]? ( b=$<.read ;'
+} ub( ,''}
+';a= ''<<32
+b.lines {puts( ?.. *(
+b.size) .gsub(/./) {
+b.sub!( /^#$`\K(\S)
+ /x,a)?$1:a }
+ .rstrip)}):
+ ( [ 12,1,12,11].
+cycle { | i | t = ( s *
+
+10<<
+10)*
+10+ %(\e[A)*
+10
+10. times{t[i*
+ _1 ] = 'TRICK+2022'[
+ _1 ] };$><<t
+ sleep 1})
+ }"
diff --git a/sample/trick2022/03-mame/remarks.markdown b/sample/trick2022/03-mame/remarks.markdown
new file mode 100644
index 0000000000..c38279f016
--- /dev/null
+++ b/sample/trick2022/03-mame/remarks.markdown
@@ -0,0 +1,96 @@
+Execute the program normally.
+
+```
+$ ruby entry.rb
+```
+
+It shakes a string.
+
+... Wait! This is not all.
+
+Next, please apply "leftward gravity" to each letter in the file.
+IOW, if there is a space to the left of a letter, move it to the left.
+Here, you may want to use the following command.
+
+```
+$ sed "s/ //g" entry.rb | tee up.rb
+```
+
+This program applies "upward gravity" to each letter in an input text.
+The following demo will help you understand what this means.
+
+```
+$ cat test.txt
+$ ruby up.rb test.txt
+```
+
+Now, here's where we come in.
+Please apply "upward gravity" to entry.rb.
+
+```
+$ ruby up.rb entry.rb | tee left.rb
+```
+
+I think that you already noticed that.
+This program applies "leftward gravity" to an input text.
+
+```
+$ cat test.txt
+$ ruby left.rb test.txt
+```
+
+`sed` is no longer required to create `up.rb`; just use `left.rb`.
+
+```
+$ ruby left.rb entry.rb > up.rb
+```
+
+We've come to the final stage.
+Please apply `left.rb` to `left.rb`.
+
+```
+$ ruby left.rb left.rb | tee horizontal.rb
+$ ruby horizontal.rb
+```
+
+Of course, it is also possible to apply `up.rb` to `up.rb`.
+
+```
+$ ruby up.rb up.rb | tee vertical.rb
+$ ruby vertical.rb
+```
+
+Can you tell how they work? Enjoy analyzing!
+
+
+
+---
+Code reading tips (spoiler)
+
+Some code fragments are highly reused between the programs.
+For example, note that this program has one code fragment to input a text
+(`b=$>.read`); `up.rb` and `left.rb` share and use this code fragment.
+Also, `horizontal.rb` and `vertical.rb` share the fragment `puts'TRICK+2022'`.
+Sometimes letters in very distant places are reused all over the place.
+
+Can you tell how it detects if it is already aligned or not yet?
+Here is a simplified version of the gimmick to switch behavior when
+left-aligned:
+
+```
+"\ #{puts('not left-aligned yet')}
+ # {puts('left-aligned')}"
+```
+
+And for top-aligned:
+
+```
+"#
+xx{puts('top-aligned')}
+x#{puts('not top-aligned yet')}
+"
+```
+
+It is also necessary to detect "top-left-aligned" and "left-top-aligned".
+I made tons of subtle adjustments and trial-and-error to create the program.
+I no longer know precisely how it works.
diff --git a/sample/trick2022/03-mame/test.txt b/sample/trick2022/03-mame/test.txt
new file mode 100644
index 0000000000..18802153a9
--- /dev/null
+++ b/sample/trick2022/03-mame/test.txt
@@ -0,0 +1,13 @@
+T
+ R
+ I
+ C
+ K
+ |
+ |
+ |
+ |
+ 2
+ 0
+ 2
+ 2
diff --git a/sample/trick2022/README.md b/sample/trick2022/README.md
new file mode 100644
index 0000000000..3b2af6f86b
--- /dev/null
+++ b/sample/trick2022/README.md
@@ -0,0 +1,14 @@
+This directory contains the award-winning entries of
+the 4th Transcendental Ruby Imbroglio Contest for rubyKaigi (TRICK 2022).
+
+THESE ARE BAD EXAMPLES! You must NOT use them as a sample code.
+
+* 01-tompng/entry.rb: "Best fishbowl" -- Tomoya Ishida (tompng)
+* 02-tompng/entry.rb: "Most interactive code" -- Tomoya Ishida (tompng)
+* 03-mame/entry.rb: "Most anti-gravity" -- Yusuke Endoh
+
+These files are licensed under MIT license.
+
+For the contest outline and other winning entries, see:
+
+https://github.com/tric/trick2022
diff --git a/sample/uumerge.rb b/sample/uumerge.rb
index 2576bcb864..1b81582c24 100644
--- a/sample/uumerge.rb
+++ b/sample/uumerge.rb
@@ -15,7 +15,7 @@ while line = gets()
if out_stdout
out = STDOUT
else
- out = open($file, "w") if $file != ""
+ out = File.open($file, "w") if $file != ""
end
out.binmode
break
diff --git a/scheduler.c b/scheduler.c
index ca457b0d14..4be18e1799 100644
--- a/scheduler.c
+++ b/scheduler.c
@@ -11,8 +11,12 @@
#include "vm_core.h"
#include "ruby/fiber/scheduler.h"
#include "ruby/io.h"
+#include "ruby/io/buffer.h"
+
+#include "internal/thread.h"
static ID id_close;
+static ID id_scheduler_close;
static ID id_block;
static ID id_unblock;
@@ -21,16 +25,71 @@ static ID id_timeout_after;
static ID id_kernel_sleep;
static ID id_process_wait;
-static ID id_io_read;
-static ID id_io_write;
+static ID id_io_read, id_io_pread;
+static ID id_io_write, id_io_pwrite;
static ID id_io_wait;
+static ID id_io_select;
+static ID id_io_close;
static ID id_address_resolve;
+static ID id_fiber_schedule;
+
+/*
+ * Document-class: Fiber::Scheduler
+ *
+ * This is not an existing class, but documentation of the interface that Scheduler
+ * object should comply to in order to be used as argument to Fiber.scheduler and handle non-blocking
+ * fibers. See also the "Non-blocking fibers" section in Fiber class docs for explanations
+ * of some concepts.
+ *
+ * Scheduler's behavior and usage are expected to be as follows:
+ *
+ * * When the execution in the non-blocking Fiber reaches some blocking operation (like
+ * sleep, wait for a process, or a non-ready I/O), it calls some of the scheduler's
+ * hook methods, listed below.
+ * * Scheduler somehow registers what the current fiber is waiting on, and yields control
+ * to other fibers with Fiber.yield (so the fiber would be suspended while expecting its
+ * wait to end, and other fibers in the same thread can perform)
+ * * At the end of the current thread execution, the scheduler's method #scheduler_close is called
+ * * The scheduler runs into a wait loop, checking all the blocked fibers (which it has
+ * registered on hook calls) and resuming them when the awaited resource is ready
+ * (e.g. I/O ready or sleep time elapsed).
+ *
+ * This way concurrent execution will be achieved transparently for every
+ * individual Fiber's code.
+ *
+ * Scheduler implementations are provided by gems, like
+ * Async[https://github.com/socketry/async].
+ *
+ * Hook methods are:
+ *
+ * * #io_wait, #io_read, #io_write, #io_pread, #io_pwrite, and #io_select, #io_close
+ * * #process_wait
+ * * #kernel_sleep
+ * * #timeout_after
+ * * #address_resolve
+ * * #block and #unblock
+ * * (the list is expanded as Ruby developers make more methods having non-blocking calls)
+ *
+ * When not specified otherwise, the hook implementations are mandatory: if they are not
+ * implemented, the methods trying to call hook will fail. To provide backward compatibility,
+ * in the future hooks will be optional (if they are not implemented, due to the scheduler
+ * being created for the older Ruby version, the code which needs this hook will not fail,
+ * and will just behave in a blocking fashion).
+ *
+ * It is also strongly recommended that the scheduler implements the #fiber method, which is
+ * delegated to by Fiber.schedule.
+ *
+ * Sample _toy_ implementation of the scheduler can be found in Ruby's code, in
+ * <tt>test/fiber/scheduler.rb</tt>
+ *
+ */
void
Init_Fiber_Scheduler(void)
{
id_close = rb_intern_const("close");
+ id_scheduler_close = rb_intern_const("scheduler_close");
id_block = rb_intern_const("block");
id_unblock = rb_intern_const("unblock");
@@ -40,15 +99,42 @@ Init_Fiber_Scheduler(void)
id_process_wait = rb_intern_const("process_wait");
id_io_read = rb_intern_const("io_read");
+ id_io_pread = rb_intern_const("io_pread");
id_io_write = rb_intern_const("io_write");
+ id_io_pwrite = rb_intern_const("io_pwrite");
+
id_io_wait = rb_intern_const("io_wait");
+ id_io_select = rb_intern_const("io_select");
+ id_io_close = rb_intern_const("io_close");
id_address_resolve = rb_intern_const("address_resolve");
+
+ id_fiber_schedule = rb_intern_const("fiber");
+
+#if 0 /* for RDoc */
+ rb_cFiberScheduler = rb_define_class_under(rb_cFiber, "Scheduler", rb_cObject);
+ rb_define_method(rb_cFiberScheduler, "close", rb_fiber_scheduler_close, 0);
+ rb_define_method(rb_cFiberScheduler, "process_wait", rb_fiber_scheduler_process_wait, 2);
+ rb_define_method(rb_cFiberScheduler, "io_wait", rb_fiber_scheduler_io_wait, 3);
+ rb_define_method(rb_cFiberScheduler, "io_read", rb_fiber_scheduler_io_read, 4);
+ rb_define_method(rb_cFiberScheduler, "io_write", rb_fiber_scheduler_io_write, 4);
+ rb_define_method(rb_cFiberScheduler, "io_pread", rb_fiber_scheduler_io_pread, 5);
+ rb_define_method(rb_cFiberScheduler, "io_pwrite", rb_fiber_scheduler_io_pwrite, 5);
+ rb_define_method(rb_cFiberScheduler, "io_select", rb_fiber_scheduler_io_select, 4);
+ rb_define_method(rb_cFiberScheduler, "kernel_sleep", rb_fiber_scheduler_kernel_sleep, 1);
+ rb_define_method(rb_cFiberScheduler, "address_resolve", rb_fiber_scheduler_address_resolve, 1);
+ rb_define_method(rb_cFiberScheduler, "timeout_after", rb_fiber_scheduler_timeout_after, 3);
+ rb_define_method(rb_cFiberScheduler, "block", rb_fiber_scheduler_block, 2);
+ rb_define_method(rb_cFiberScheduler, "unblock", rb_fiber_scheduler_unblock, 2);
+ rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler, -2);
+#endif
}
VALUE
rb_fiber_scheduler_get(void)
{
+ VM_ASSERT(ruby_thread_has_gvl_p());
+
rb_thread_t *thread = GET_THREAD();
VM_ASSERT(thread);
@@ -75,9 +161,26 @@ verify_interface(VALUE scheduler)
}
}
+static VALUE
+fiber_scheduler_close(VALUE scheduler)
+{
+ return rb_fiber_scheduler_close(scheduler);
+}
+
+static VALUE
+fiber_scheduler_close_ensure(VALUE _thread)
+{
+ rb_thread_t *thread = (rb_thread_t*)_thread;
+ thread->scheduler = Qnil;
+
+ return Qnil;
+}
+
VALUE
rb_fiber_scheduler_set(VALUE scheduler)
{
+ VM_ASSERT(ruby_thread_has_gvl_p());
+
rb_thread_t *thread = GET_THREAD();
VM_ASSERT(thread);
@@ -85,9 +188,13 @@ rb_fiber_scheduler_set(VALUE scheduler)
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.
+ // We invoke Scheduler#close when setting it to something else, to ensure
+ // the previous scheduler runs to completion before changing the scheduler.
+ // That way, we do not need to consider interactions, e.g., of a Fiber from
+ // the previous scheduler with the new scheduler.
if (thread->scheduler != Qnil) {
- rb_fiber_scheduler_close(thread->scheduler);
+ // rb_fiber_scheduler_close(thread->scheduler);
+ rb_ensure(fiber_scheduler_close, thread->scheduler, fiber_scheduler_close_ensure, (VALUE)thread);
}
thread->scheduler = scheduler;
@@ -119,12 +226,34 @@ VALUE rb_fiber_scheduler_current_for_thread(VALUE thread)
return rb_fiber_scheduler_current_for_threadptr(rb_thread_ptr(thread));
}
+/*
+ *
+ * Document-method: Fiber::Scheduler#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.
+ *
+ */
VALUE
rb_fiber_scheduler_close(VALUE scheduler)
{
- if (rb_respond_to(scheduler, id_close)) {
- return rb_funcall(scheduler, id_close, 0);
- }
+ VM_ASSERT(ruby_thread_has_gvl_p());
+
+ VALUE result;
+
+ // The reason for calling `scheduler_close` before calling `close` is for
+ // legacy schedulers which implement `close` and expect the user to call
+ // it. Subsequently, that method would call `Fiber.set_scheduler(nil)`
+ // which should call `scheduler_close`. If it were to call `close`, it
+ // would create an infinite loop.
+
+ result = rb_check_funcall(scheduler, id_scheduler_close, 0, NULL);
+ if (!UNDEF_P(result)) return result;
+
+ result = rb_check_funcall(scheduler, id_close, 0, NULL);
+ if (!UNDEF_P(result)) return result;
return Qnil;
}
@@ -139,6 +268,17 @@ rb_fiber_scheduler_make_timeout(struct timeval *timeout)
return Qnil;
}
+/*
+ * Document-method: Fiber::Scheduler#kernel_sleep
+ * call-seq: kernel_sleep(duration = nil)
+ *
+ * Invoked by Kernel#sleep and Mutex#sleep and is expected to provide
+ * an implementation of sleeping in a non-blocking way. Implementation might
+ * register the current fiber in some list of "which fiber wait until what
+ * moment", call Fiber.yield to pass control, and then in #close resume
+ * the fibers whose wait period has elapsed.
+ *
+ */
VALUE
rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE timeout)
{
@@ -152,6 +292,34 @@ rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv)
}
#if 0
+/*
+ * Document-method: Fiber::Scheduler#timeout_after
+ * call-seq: timeout_after(duration, exception_class, *exception_arguments, &block) -> result of block
+ *
+ * Invoked by Timeout.timeout to execute the given +block+ within the given
+ * +duration+. It can also be invoked directly by the scheduler or user code.
+ *
+ * Attempt to limit the execution time of a given +block+ to the given
+ * +duration+ if possible. When a non-blocking operation causes the +block+'s
+ * execution time to exceed the specified +duration+, that non-blocking
+ * operation should be interrupted by raising the specified +exception_class+
+ * constructed with the given +exception_arguments+.
+ *
+ * General execution timeouts are often considered risky. This implementation
+ * will only interrupt non-blocking operations. This is by design because it's
+ * expected that non-blocking operations can fail for a variety of
+ * unpredictable reasons, so applications should already be robust in handling
+ * these conditions and by implication timeouts.
+ *
+ * However, as a result of this design, if the +block+ does not invoke any
+ * non-blocking operations, it will be impossible to interrupt it. If you
+ * desire to provide predictable points for timeouts, consider adding
+ * +sleep(0)+.
+ *
+ * If the block is executed successfully, its result will be returned.
+ *
+ * The exception will typically be raised using Fiber#raise.
+ */
VALUE
rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message)
{
@@ -169,6 +337,24 @@ rb_fiber_scheduler_timeout_afterv(VALUE scheduler, int argc, VALUE * argv)
}
#endif
+/*
+ * Document-method: Fiber::Scheduler#process_wait
+ * call-seq: process_wait(pid, flags)
+ *
+ * Invoked by Process::Status.wait in order to wait for a specified process.
+ * See that method description for arguments description.
+ *
+ * Suggested minimal implementation:
+ *
+ * Thread.new do
+ * Process::Status.wait(pid, flags)
+ * end.value
+ *
+ * This hook is optional: if it is not present in the current scheduler,
+ * Process::Status.wait will behave as a blocking method.
+ *
+ * Expected to return a Process::Status instance.
+ */
VALUE
rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags)
{
@@ -179,18 +365,74 @@ rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags)
return rb_check_funcall(scheduler, id_process_wait, 2, arguments);
}
+/*
+ * Document-method: Fiber::Scheduler#block
+ * call-seq: block(blocker, timeout = nil)
+ *
+ * Invoked by methods like Thread.join, and by Mutex, to signify that current
+ * Fiber is blocked until further notice (e.g. #unblock) or until +timeout+ has
+ * elapsed.
+ *
+ * +blocker+ is what we are waiting on, informational only (for debugging and
+ * logging). There are no guarantee about its value.
+ *
+ * Expected to return boolean, specifying whether the blocking operation was
+ * successful or not.
+ */
VALUE
rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout)
{
return rb_funcall(scheduler, id_block, 2, blocker, timeout);
}
+/*
+ * Document-method: Fiber::Scheduler#unblock
+ * call-seq: unblock(blocker, fiber)
+ *
+ * Invoked to wake up Fiber previously blocked with #block (for example, Mutex#lock
+ * calls #block and Mutex#unlock calls #unblock). The scheduler should use
+ * 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.
+ *
+ */
VALUE
rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
{
- return rb_funcall(scheduler, id_unblock, 2, blocker, fiber);
+ VM_ASSERT(rb_obj_is_fiber(fiber));
+
+ // `rb_fiber_scheduler_unblock` can be called from points where `errno` is expected to be preserved. Therefore, we should save and restore it. For example `io_binwrite` calls `rb_fiber_scheduler_unblock` and if `errno` is reset to 0 by user code, it will break the error handling in `io_write`.
+ // If we explicitly preserve `errno` in `io_binwrite` and other similar functions (e.g. by returning it), this code is no longer needed. I hope in the future we will be able to remove it.
+ int saved_errno = errno;
+
+ VALUE result = rb_funcall(scheduler, id_unblock, 2, blocker, fiber);
+
+ errno = saved_errno;
+
+ return result;
}
+/*
+ * Document-method: Fiber::Scheduler#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.
+ *
+ */
VALUE
rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
{
@@ -200,36 +442,219 @@ rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeou
VALUE
rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
{
- return rb_fiber_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_READABLE), Qnil);
+ return rb_fiber_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_READABLE), rb_io_timeout(io));
}
VALUE
rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
{
- return rb_fiber_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_WRITABLE), Qnil);
+ return rb_fiber_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_WRITABLE), rb_io_timeout(io));
+}
+
+/*
+ * Document-method: Fiber::Scheduler#io_select
+ * call-seq: io_select(readables, writables, exceptables, timeout)
+ *
+ * Invoked by IO.select to ask whether the specified descriptors are ready for
+ * specified events within the specified +timeout+.
+ *
+ * Expected to return the 3-tuple of Array of IOs that are ready.
+ *
+ */
+VALUE rb_fiber_scheduler_io_select(VALUE scheduler, VALUE readables, VALUE writables, VALUE exceptables, VALUE timeout)
+{
+ VALUE arguments[] = {
+ readables, writables, exceptables, timeout
+ };
+
+ return rb_fiber_scheduler_io_selectv(scheduler, 4, arguments);
}
+VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
+{
+ // I wondered about extracting argv, and checking if there is only a single
+ // IO instance, and instead calling `io_wait`. However, it would require a
+ // decent amount of work and it would be hard to preserve the exact
+ // semantics of IO.select.
+
+ return rb_check_funcall(scheduler, id_io_select, argc, argv);
+}
+
+/*
+ * Document-method: Fiber::Scheduler#io_read
+ * call-seq: io_read(io, buffer, minimum_length) -> read length or -errno
+ *
+ * Invoked by IO#read or IO#Buffer.read to read +length+ bytes from +io+ into a
+ * specified +buffer+ (see IO::Buffer).
+ *
+ * The +minimum_length+ argument is the "minimum length to be read". If the IO
+ * buffer size is 8KiB, but the +length+ is +1024+ (1KiB), up to 8KiB might be
+ * read, but at least 1KiB will be. Generally, the only case where less data
+ * than +length+ will be read is if there is an error reading the data.
+ *
+ * Specifying a +length+ of 0 is valid and means try reading at least once and
+ * return any available data.
+ *
+ * Suggested implementation should try to read from +io+ in a non-blocking
+ * manner and call #io_wait if the +io+ is not ready (which will yield control
+ * to other fibers).
+ *
+ * See IO::Buffer for an interface available to return data.
+ *
+ * Expected to return number of bytes read, or, in case of an error,
+ * <tt>-errno</tt> (negated number corresponding to system's error code).
+ *
+ * The method should be considered _experimental_.
+ */
VALUE
-rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
+rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset)
{
VALUE arguments[] = {
- io, buffer, SIZET2NUM(offset), SIZET2NUM(length)
+ io, buffer, SIZET2NUM(length), SIZET2NUM(offset)
};
return rb_check_funcall(scheduler, id_io_read, 4, arguments);
}
+
+/*
+ * Document-method: Fiber::Scheduler#io_read
+ * call-seq: io_pread(io, buffer, from, length, offset) -> read length or -errno
+ *
+ * Invoked by IO::Buffer#pread. See that method for description of arguments.
+ *
+ */
VALUE
-rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
+rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset)
{
VALUE arguments[] = {
- io, buffer, SIZET2NUM(offset), SIZET2NUM(length)
+ io, buffer, OFFT2NUM(from), SIZET2NUM(length), SIZET2NUM(offset)
+ };
+
+ return rb_check_funcall(scheduler, id_io_pread, 5, arguments);
+}
+
+/*
+ * Document-method: Scheduler#io_write
+ * call-seq: io_write(io, buffer, minimum_length) -> written length or -errno
+ *
+ * Invoked by IO#write or IO::Buffer#write to write +length+ bytes to +io+ from
+ * from a specified +buffer+ (see IO::Buffer).
+ *
+ * The +minimum_length+ argument is the "minimum length to be written". If the
+ * IO buffer size is 8KiB, but the +length+ specified is 1024 (1KiB), at most
+ * 8KiB will be written, but at least 1KiB will be. Generally, the only case
+ * where less data than +minimum_length+ will be written is if there is an
+ * error writing the data.
+ *
+ * Specifying a +length+ of 0 is valid and means try writing at least once, as
+ * much data as possible.
+ *
+ * Suggested implementation should try to write to +io+ in a non-blocking
+ * manner and call #io_wait if the +io+ is not ready (which will yield control
+ * to other fibers).
+ *
+ * See IO::Buffer for an interface available to get data from buffer
+ * efficiently.
+ *
+ * Expected to return number of bytes written, or, in case of an error,
+ * <tt>-errno</tt> (negated number corresponding to system's error code).
+ *
+ * The method should be considered _experimental_.
+ */
+VALUE
+rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset)
+{
+ VALUE arguments[] = {
+ io, buffer, SIZET2NUM(length), SIZET2NUM(offset)
};
- // We should ensure string has capacity to receive data, and then resize it afterwards.
return rb_check_funcall(scheduler, id_io_write, 4, arguments);
}
+/*
+ * Document-method: Fiber::Scheduler#io_pwrite
+ * call-seq: io_pwrite(io, buffer, from, length, offset) -> written length or -errno
+ *
+ * Invoked by IO::Buffer#pwrite. See that method for description of arguments.
+ *
+ */
+VALUE
+rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset)
+{
+ VALUE arguments[] = {
+ io, buffer, OFFT2NUM(from), SIZET2NUM(length), SIZET2NUM(offset)
+ };
+
+ return rb_check_funcall(scheduler, id_io_pwrite, 5, arguments);
+}
+
+VALUE
+rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t size, size_t length)
+{
+ VALUE buffer = rb_io_buffer_new(base, size, RB_IO_BUFFER_LOCKED);
+
+ VALUE result = rb_fiber_scheduler_io_read(scheduler, io, buffer, length, 0);
+
+ rb_io_buffer_unlock(buffer);
+ rb_io_buffer_free(buffer);
+
+ return result;
+}
+
+VALUE
+rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size, size_t length)
+{
+ VALUE buffer = rb_io_buffer_new((void*)base, size, RB_IO_BUFFER_LOCKED|RB_IO_BUFFER_READONLY);
+
+ VALUE result = rb_fiber_scheduler_io_write(scheduler, io, buffer, length, 0);
+
+ rb_io_buffer_unlock(buffer);
+ rb_io_buffer_free(buffer);
+
+ return result;
+}
+
+VALUE
+rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io)
+{
+ VALUE arguments[] = {io};
+
+ return rb_check_funcall(scheduler, id_io_close, 1, arguments);
+}
+
+/*
+ * Document-method: Fiber::Scheduler#address_resolve
+ * call-seq: address_resolve(hostname) -> array_of_strings or nil
+ *
+ * Invoked by any method that performs a non-reverse DNS lookup. The most
+ * notable method is Addrinfo.getaddrinfo, but there are many other.
+ *
+ * The method is expected to return an array of strings corresponding to ip
+ * addresses the +hostname+ is resolved to, or +nil+ if it can not be resolved.
+ *
+ * Fairly exhaustive list of all possible call-sites:
+ *
+ * - Addrinfo.getaddrinfo
+ * - Addrinfo.tcp
+ * - Addrinfo.udp
+ * - Addrinfo.ip
+ * - Addrinfo.new
+ * - Addrinfo.marshal_load
+ * - SOCKSSocket.new
+ * - TCPServer.new
+ * - TCPSocket.new
+ * - IPSocket.getaddress
+ * - TCPSocket.gethostbyname
+ * - UDPSocket#connect
+ * - UDPSocket#bind
+ * - UDPSocket#send
+ * - Socket.getaddrinfo
+ * - Socket.gethostbyname
+ * - Socket.pack_sockaddr_in
+ * - Socket.sockaddr_in
+ * - Socket.unpack_sockaddr_in
+ */
VALUE
rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname)
{
@@ -239,3 +664,24 @@ rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname)
return rb_check_funcall(scheduler, id_address_resolve, 1, arguments);
}
+
+/*
+ * Document-method: Fiber::Scheduler#fiber
+ * call-seq: fiber(&block)
+ *
+ * Implementation of the Fiber.schedule. The method is <em>expected</em> to immediately
+ * run the given block of code in a separate non-blocking fiber, and to return that Fiber.
+ *
+ * Minimal suggested implementation is:
+ *
+ * def fiber(&block)
+ * fiber = Fiber.new(blocking: false, &block)
+ * fiber.resume
+ * fiber
+ * end
+ */
+VALUE
+rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat)
+{
+ return rb_funcall_passing_block_kw(scheduler, id_fiber_schedule, argc, argv, kw_splat);
+}
diff --git a/shape.c b/shape.c
new file mode 100644
index 0000000000..1dc08dcb60
--- /dev/null
+++ b/shape.c
@@ -0,0 +1,825 @@
+#include "vm_core.h"
+#include "vm_sync.h"
+#include "shape.h"
+#include "gc.h"
+#include "symbol.h"
+#include "id_table.h"
+#include "internal/class.h"
+#include "internal/symbol.h"
+#include "internal/variable.h"
+#include "variable.h"
+#include <stdbool.h>
+
+#ifndef SHAPE_DEBUG
+#define SHAPE_DEBUG (VM_CHECK_MODE > 0)
+#endif
+
+static ID id_frozen;
+static ID id_t_object;
+static ID size_pool_edge_names[SIZE_POOL_COUNT];
+
+/*
+ * Shape getters
+ */
+rb_shape_t *
+rb_shape_get_root_shape(void)
+{
+ return GET_VM()->root_shape;
+}
+
+shape_id_t
+rb_shape_id(rb_shape_t * shape)
+{
+ return (shape_id_t)(shape - GET_VM()->shape_list);
+}
+
+bool
+rb_shape_root_shape_p(rb_shape_t* shape)
+{
+ return shape == rb_shape_get_root_shape();
+}
+
+void
+rb_shape_each_shape(each_shape_callback callback, void *data)
+{
+ rb_shape_t *cursor = rb_shape_get_root_shape();
+ rb_shape_t *end = rb_shape_get_shape_by_id(GET_VM()->next_shape_id);
+ while (cursor < end) {
+ callback(cursor, data);
+ cursor += 1;
+ }
+}
+
+rb_shape_t*
+rb_shape_get_shape_by_id(shape_id_t shape_id)
+{
+ RUBY_ASSERT(shape_id != INVALID_SHAPE_ID);
+
+ rb_vm_t *vm = GET_VM();
+ rb_shape_t *shape = &vm->shape_list[shape_id];
+ return shape;
+}
+
+rb_shape_t*
+rb_shape_get_shape_by_id_without_assertion(shape_id_t shape_id)
+{
+ RUBY_ASSERT(shape_id != INVALID_SHAPE_ID);
+
+ rb_vm_t *vm = GET_VM();
+ rb_shape_t *shape = &vm->shape_list[shape_id];
+ return shape;
+}
+
+rb_shape_t *
+rb_shape_get_parent(rb_shape_t * shape)
+{
+ return rb_shape_get_shape_by_id(shape->parent_id);
+}
+
+#if !SHAPE_IN_BASIC_FLAGS
+shape_id_t
+rb_rclass_shape_id(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE));
+ return RCLASS_EXT(obj)->shape_id;
+}
+
+shape_id_t rb_generic_shape_id(VALUE obj);
+#endif
+
+shape_id_t
+rb_shape_get_shape_id(VALUE obj)
+{
+ if (RB_SPECIAL_CONST_P(obj)) {
+ return SPECIAL_CONST_SHAPE_ID;
+ }
+
+#if SHAPE_IN_BASIC_FLAGS
+ return RBASIC_SHAPE_ID(obj);
+#else
+ switch (BUILTIN_TYPE(obj)) {
+ case T_OBJECT:
+ return ROBJECT_SHAPE_ID(obj);
+ break;
+ case T_CLASS:
+ case T_MODULE:
+ return RCLASS_SHAPE_ID(obj);
+ default:
+ return rb_generic_shape_id(obj);
+ }
+#endif
+}
+
+size_t
+rb_shape_depth(rb_shape_t * shape)
+{
+ size_t depth = 1;
+
+ while (shape->parent_id != INVALID_SHAPE_ID) {
+ depth++;
+ shape = rb_shape_get_parent(shape);
+ }
+
+ return depth;
+}
+
+rb_shape_t*
+rb_shape_get_shape(VALUE obj)
+{
+ return rb_shape_get_shape_by_id(rb_shape_get_shape_id(obj));
+}
+
+static rb_shape_t*
+get_next_shape_internal(rb_shape_t * shape, ID id, enum shape_type shape_type, bool * variation_created, bool new_shapes_allowed)
+{
+ rb_shape_t *res = NULL;
+
+ // There should never be outgoing edges from "too complex"
+ RUBY_ASSERT(rb_shape_id(shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
+
+ *variation_created = false;
+
+ if (new_shapes_allowed) {
+ RB_VM_LOCK_ENTER();
+ {
+ bool had_edges = !!shape->edges;
+
+ if (!shape->edges) {
+ shape->edges = rb_id_table_create(0);
+ }
+
+ // Lookup the shape in edges - if there's already an edge and a corresponding shape for it,
+ // we can return that. Otherwise, we'll need to get a new shape
+ VALUE lookup_result;
+ if (rb_id_table_lookup(shape->edges, id, &lookup_result)) {
+ res = (rb_shape_t *)lookup_result;
+ }
+ else {
+ *variation_created = had_edges;
+
+ rb_shape_t * new_shape = rb_shape_alloc(id, shape);
+
+ new_shape->type = (uint8_t)shape_type;
+ new_shape->capacity = shape->capacity;
+
+ switch (shape_type) {
+ case SHAPE_IVAR:
+ new_shape->next_iv_index = shape->next_iv_index + 1;
+ break;
+ case SHAPE_CAPACITY_CHANGE:
+ case SHAPE_FROZEN:
+ case SHAPE_T_OBJECT:
+ new_shape->next_iv_index = shape->next_iv_index;
+ break;
+ case SHAPE_OBJ_TOO_COMPLEX:
+ case SHAPE_INITIAL_CAPACITY:
+ case SHAPE_ROOT:
+ rb_bug("Unreachable");
+ break;
+ }
+
+ rb_id_table_insert(shape->edges, id, (VALUE)new_shape);
+
+ res = new_shape;
+ }
+ }
+ RB_VM_LOCK_LEAVE();
+ }
+ return res;
+}
+
+MJIT_FUNC_EXPORTED int
+rb_shape_frozen_shape_p(rb_shape_t* shape)
+{
+ return SHAPE_FROZEN == (enum shape_type)shape->type;
+}
+
+static void
+move_iv(VALUE obj, ID id, attr_index_t from, attr_index_t to)
+{
+ switch(BUILTIN_TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ RCLASS_IVPTR(obj)[to] = RCLASS_IVPTR(obj)[from];
+ break;
+ case T_OBJECT:
+ RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
+ ROBJECT_IVPTR(obj)[to] = ROBJECT_IVPTR(obj)[from];
+ break;
+ default: {
+ struct gen_ivtbl *ivtbl;
+ rb_gen_ivtbl_get(obj, id, &ivtbl);
+ ivtbl->ivptr[to] = ivtbl->ivptr[from];
+ break;
+ }
+ }
+}
+
+static rb_shape_t *
+remove_shape_recursive(VALUE obj, ID id, rb_shape_t * shape, VALUE * removed)
+{
+ if (shape->parent_id == INVALID_SHAPE_ID) {
+ // We've hit the top of the shape tree and couldn't find the
+ // IV we wanted to remove, so return NULL
+ return NULL;
+ }
+ else {
+ if (shape->type == SHAPE_IVAR && shape->edge_name == id) {
+ // We've hit the edge we wanted to remove, return it's _parent_
+ // as the new parent while we go back down the stack.
+ attr_index_t index = shape->next_iv_index - 1;
+
+ switch(BUILTIN_TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ *removed = RCLASS_IVPTR(obj)[index];
+ break;
+ case T_OBJECT:
+ *removed = ROBJECT_IVPTR(obj)[index];
+ break;
+ default: {
+ struct gen_ivtbl *ivtbl;
+ rb_gen_ivtbl_get(obj, id, &ivtbl);
+ *removed = ivtbl->ivptr[index];
+ break;
+ }
+ }
+ return rb_shape_get_parent(shape);
+ }
+ else {
+ // This isn't the IV we want to remove, keep walking up.
+ rb_shape_t * new_parent = remove_shape_recursive(obj, id, rb_shape_get_parent(shape), removed);
+
+ // We found a new parent. Create a child of the new parent that
+ // has the same attributes as this shape.
+ if (new_parent) {
+ bool dont_care;
+ rb_shape_t * new_child = get_next_shape_internal(new_parent, shape->edge_name, shape->type, &dont_care, true);
+ new_child->capacity = shape->capacity;
+ if (new_child->type == SHAPE_IVAR) {
+ move_iv(obj, id, shape->next_iv_index - 1, new_child->next_iv_index - 1);
+ }
+
+ return new_child;
+ }
+ else {
+ // We went all the way to the top of the shape tree and couldn't
+ // find an IV to remove, so return NULL
+ return NULL;
+ }
+ }
+ }
+}
+
+void
+rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape, VALUE * removed)
+{
+ rb_shape_t * new_shape = remove_shape_recursive(obj, id, shape, removed);
+ if (new_shape) {
+ rb_shape_set_shape(obj, new_shape);
+ }
+}
+
+void
+rb_shape_transition_shape_frozen(VALUE obj)
+{
+ rb_shape_t* shape = rb_shape_get_shape(obj);
+ RUBY_ASSERT(shape);
+ RUBY_ASSERT(RB_OBJ_FROZEN(obj));
+
+ if (rb_shape_frozen_shape_p(shape) || rb_shape_obj_too_complex(obj)) {
+ return;
+ }
+
+ rb_shape_t* next_shape;
+
+ if (shape == rb_shape_get_root_shape()) {
+ rb_shape_set_shape_id(obj, SPECIAL_CONST_SHAPE_ID);
+ return;
+ }
+
+ bool dont_care;
+ next_shape = get_next_shape_internal(shape, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true);
+
+ RUBY_ASSERT(next_shape);
+ rb_shape_set_shape(obj, next_shape);
+}
+
+/*
+ * This function is used for assertions where we don't want to increment
+ * max_iv_count
+ */
+rb_shape_t *
+rb_shape_get_next_iv_shape(rb_shape_t* shape, ID id)
+{
+ RUBY_ASSERT(!is_instance_id(id) || RTEST(rb_sym2str(ID2SYM(id))));
+ bool dont_care;
+ return get_next_shape_internal(shape, id, SHAPE_IVAR, &dont_care, true);
+}
+
+rb_shape_t *
+rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id)
+{
+ RUBY_ASSERT(!is_instance_id(id) || RTEST(rb_sym2str(ID2SYM(id))));
+
+ bool allow_new_shape = true;
+
+ if (BUILTIN_TYPE(obj) == T_OBJECT) {
+ VALUE klass = rb_obj_class(obj);
+ allow_new_shape = RCLASS_EXT(klass)->variation_count < SHAPE_MAX_VARIATIONS;
+ }
+
+ bool variation_created = false;
+ rb_shape_t * new_shape = get_next_shape_internal(shape, id, SHAPE_IVAR, &variation_created, allow_new_shape);
+
+ if (!new_shape) {
+ RUBY_ASSERT(BUILTIN_TYPE(obj) == T_OBJECT);
+ new_shape = rb_shape_get_shape_by_id(OBJ_TOO_COMPLEX_SHAPE_ID);
+ }
+
+ // Check if we should update max_iv_count on the object's class
+ if (BUILTIN_TYPE(obj) == T_OBJECT) {
+ VALUE klass = rb_obj_class(obj);
+ if (new_shape->next_iv_index > RCLASS_EXT(klass)->max_iv_count) {
+ RCLASS_EXT(klass)->max_iv_count = new_shape->next_iv_index;
+ }
+
+ if (variation_created) {
+ RCLASS_EXT(klass)->variation_count++;
+ }
+ }
+
+ return new_shape;
+}
+
+rb_shape_t *
+rb_shape_transition_shape_capa(rb_shape_t* shape, uint32_t new_capacity)
+{
+ ID edge_name = rb_make_temporary_id(new_capacity);
+ bool dont_care;
+ rb_shape_t * new_shape = get_next_shape_internal(shape, edge_name, SHAPE_CAPACITY_CHANGE, &dont_care, true);
+ new_shape->capacity = new_capacity;
+ return new_shape;
+}
+
+bool
+rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t *value)
+{
+ // It doesn't make sense to ask for the index of an IV that's stored
+ // on an object that is "too complex" as it uses a hash for storing IVs
+ RUBY_ASSERT(rb_shape_id(shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
+
+ while (shape->parent_id != INVALID_SHAPE_ID) {
+ if (shape->edge_name == id) {
+ enum shape_type shape_type;
+ shape_type = (enum shape_type)shape->type;
+
+ switch (shape_type) {
+ case SHAPE_IVAR:
+ RUBY_ASSERT(shape->next_iv_index > 0);
+ *value = shape->next_iv_index - 1;
+ return true;
+ case SHAPE_CAPACITY_CHANGE:
+ case SHAPE_ROOT:
+ case SHAPE_INITIAL_CAPACITY:
+ case SHAPE_T_OBJECT:
+ return false;
+ case SHAPE_OBJ_TOO_COMPLEX:
+ case SHAPE_FROZEN:
+ rb_bug("Ivar should not exist on transition\n");
+ }
+ }
+ shape = rb_shape_get_parent(shape);
+ }
+ return false;
+}
+
+static rb_shape_t *
+shape_alloc(void)
+{
+ rb_vm_t *vm = GET_VM();
+ shape_id_t shape_id = vm->next_shape_id;
+ vm->next_shape_id++;
+
+ if (shape_id == MAX_SHAPE_ID) {
+ // TODO: Make an OutOfShapesError ??
+ rb_bug("Out of shapes\n");
+ }
+
+ return &GET_VM()->shape_list[shape_id];
+}
+
+rb_shape_t *
+rb_shape_alloc_with_parent_id(ID edge_name, shape_id_t parent_id)
+{
+ rb_shape_t * shape = shape_alloc();
+
+ shape->edge_name = edge_name;
+ shape->next_iv_index = 0;
+ shape->parent_id = parent_id;
+
+ return shape;
+}
+
+rb_shape_t *
+rb_shape_alloc_with_size_pool_index(ID edge_name, rb_shape_t * parent, uint8_t size_pool_index)
+{
+ rb_shape_t * shape = rb_shape_alloc_with_parent_id(edge_name, rb_shape_id(parent));
+ shape->size_pool_index = size_pool_index;
+ return shape;
+}
+
+
+rb_shape_t *
+rb_shape_alloc(ID edge_name, rb_shape_t * parent)
+{
+ return rb_shape_alloc_with_size_pool_index(edge_name, parent, parent->size_pool_index);
+}
+
+MJIT_FUNC_EXPORTED void
+rb_shape_set_shape(VALUE obj, rb_shape_t* shape)
+{
+ rb_shape_set_shape_id(obj, rb_shape_id(shape));
+}
+
+int32_t
+rb_shape_id_offset(void)
+{
+ return sizeof(uintptr_t) - SHAPE_ID_NUM_BITS / sizeof(uintptr_t);
+}
+
+rb_shape_t *
+rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
+{
+ RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
+ rb_shape_t *next_shape = initial_shape;
+
+ if (dest_shape->type != initial_shape->type) {
+ next_shape = rb_shape_traverse_from_new_root(initial_shape, rb_shape_get_parent(dest_shape));
+ if (!next_shape) {
+ return NULL;
+ }
+ }
+
+ switch ((enum shape_type)dest_shape->type) {
+ case SHAPE_IVAR:
+ case SHAPE_FROZEN:
+ if (!next_shape->edges) {
+ return NULL;
+ }
+
+ VALUE lookup_result;
+ if (rb_id_table_lookup(next_shape->edges, dest_shape->edge_name, &lookup_result)) {
+ next_shape = (rb_shape_t *)lookup_result;
+ }
+ else {
+ return NULL;
+ }
+ break;
+ case SHAPE_ROOT:
+ case SHAPE_CAPACITY_CHANGE:
+ case SHAPE_INITIAL_CAPACITY:
+ case SHAPE_T_OBJECT:
+ break;
+ case SHAPE_OBJ_TOO_COMPLEX:
+ rb_bug("Unreachable\n");
+ break;
+ }
+
+ return next_shape;
+}
+
+rb_shape_t *
+rb_shape_rebuild_shape(rb_shape_t * initial_shape, rb_shape_t * dest_shape)
+{
+ rb_shape_t * midway_shape;
+
+ RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
+
+ if (dest_shape->type != initial_shape->type) {
+ midway_shape = rb_shape_rebuild_shape(initial_shape, rb_shape_get_parent(dest_shape));
+ }
+ else {
+ midway_shape = initial_shape;
+ }
+
+ switch ((enum shape_type)dest_shape->type) {
+ case SHAPE_IVAR:
+ if (midway_shape->capacity <= midway_shape->next_iv_index) {
+ // There isn't enough room to write this IV, so we need to increase the capacity
+ midway_shape = rb_shape_transition_shape_capa(midway_shape, midway_shape->capacity * 2);
+ }
+
+ midway_shape = rb_shape_get_next_iv_shape(midway_shape, dest_shape->edge_name);
+ break;
+ case SHAPE_ROOT:
+ case SHAPE_FROZEN:
+ case SHAPE_CAPACITY_CHANGE:
+ case SHAPE_INITIAL_CAPACITY:
+ case SHAPE_T_OBJECT:
+ break;
+ case SHAPE_OBJ_TOO_COMPLEX:
+ rb_bug("Unreachable\n");
+ break;
+ }
+
+ return midway_shape;
+}
+
+bool
+rb_shape_obj_too_complex(VALUE obj)
+{
+ return rb_shape_get_shape_id(obj) == OBJ_TOO_COMPLEX_SHAPE_ID;
+}
+
+void
+rb_shape_set_too_complex(VALUE obj)
+{
+ RUBY_ASSERT(BUILTIN_TYPE(obj) == T_OBJECT);
+ RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
+ rb_shape_set_shape_id(obj, OBJ_TOO_COMPLEX_SHAPE_ID);
+}
+
+size_t
+rb_shape_edges_count(rb_shape_t *shape)
+{
+ if (shape->edges) {
+ return rb_id_table_size(shape->edges);
+ }
+ return 0;
+}
+
+size_t
+rb_shape_memsize(rb_shape_t *shape)
+{
+ size_t memsize = sizeof(rb_shape_t);
+ if (shape->edges) {
+ memsize += rb_id_table_memsize(shape->edges);
+ }
+ return memsize;
+}
+
+#if SHAPE_DEBUG
+/*
+ * Exposing Shape to Ruby via RubyVM.debug_shape
+ */
+
+/* :nodoc: */
+static VALUE
+rb_shape_too_complex(VALUE self)
+{
+ rb_shape_t * shape;
+ shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
+ if (rb_shape_id(shape) == OBJ_TOO_COMPLEX_SHAPE_ID) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+}
+
+static VALUE
+parse_key(ID key)
+{
+ if (is_instance_id(key)) {
+ return ID2SYM(key);
+ }
+ return LONG2NUM(key);
+}
+
+static VALUE rb_shape_edge_name(rb_shape_t * shape);
+
+static VALUE
+rb_shape_t_to_rb_cShape(rb_shape_t *shape)
+{
+ VALUE rb_cShape = rb_const_get(rb_cRubyVM, rb_intern("Shape"));
+
+ VALUE obj = rb_struct_new(rb_cShape,
+ INT2NUM(rb_shape_id(shape)),
+ INT2NUM(shape->parent_id),
+ rb_shape_edge_name(shape),
+ INT2NUM(shape->next_iv_index),
+ INT2NUM(shape->size_pool_index),
+ INT2NUM(shape->type),
+ INT2NUM(shape->capacity));
+ rb_obj_freeze(obj);
+ return obj;
+}
+
+static enum rb_id_table_iterator_result
+rb_edges_to_hash(ID key, VALUE value, void *ref)
+{
+ rb_hash_aset(*(VALUE *)ref, parse_key(key), rb_shape_t_to_rb_cShape((rb_shape_t*)value));
+ return ID_TABLE_CONTINUE;
+}
+
+/* :nodoc: */
+static VALUE
+rb_shape_edges(VALUE self)
+{
+ rb_shape_t* shape;
+
+ shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
+
+ VALUE hash = rb_hash_new();
+
+ if (shape->edges) {
+ rb_id_table_foreach(shape->edges, rb_edges_to_hash, &hash);
+ }
+
+ return hash;
+}
+
+static VALUE
+rb_shape_edge_name(rb_shape_t * shape)
+{
+ if (shape->edge_name) {
+ if (is_instance_id(shape->edge_name)) {
+ return ID2SYM(shape->edge_name);
+ }
+ return INT2NUM(shape->capacity);
+ }
+ return Qnil;
+}
+
+/* :nodoc: */
+static VALUE
+rb_shape_export_depth(VALUE self)
+{
+ rb_shape_t* shape;
+ shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
+ return SIZET2NUM(rb_shape_depth(shape));
+}
+
+/* :nodoc: */
+static VALUE
+rb_shape_parent(VALUE self)
+{
+ rb_shape_t * shape;
+ shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
+ if (shape->parent_id != INVALID_SHAPE_ID) {
+ return rb_shape_t_to_rb_cShape(rb_shape_get_parent(shape));
+ }
+ else {
+ return Qnil;
+ }
+}
+
+/* :nodoc: */
+static VALUE
+rb_shape_debug_shape(VALUE self, VALUE obj)
+{
+ return rb_shape_t_to_rb_cShape(rb_shape_get_shape(obj));
+}
+
+/* :nodoc: */
+static VALUE
+rb_shape_root_shape(VALUE self)
+{
+ return rb_shape_t_to_rb_cShape(rb_shape_get_root_shape());
+}
+
+VALUE rb_obj_shape(rb_shape_t* shape);
+
+static enum rb_id_table_iterator_result collect_keys_and_values(ID key, VALUE value, void *ref)
+{
+ rb_hash_aset(*(VALUE *)ref, parse_key(key), rb_obj_shape((rb_shape_t*)value));
+ return ID_TABLE_CONTINUE;
+}
+
+static VALUE edges(struct rb_id_table* edges)
+{
+ VALUE hash = rb_hash_new();
+ if (edges)
+ rb_id_table_foreach(edges, collect_keys_and_values, &hash);
+ return hash;
+}
+
+/* :nodoc: */
+VALUE
+rb_obj_shape(rb_shape_t* shape)
+{
+ VALUE rb_shape = rb_hash_new();
+
+ rb_hash_aset(rb_shape, ID2SYM(rb_intern("id")), INT2NUM(rb_shape_id(shape)));
+ rb_hash_aset(rb_shape, ID2SYM(rb_intern("edges")), edges(shape->edges));
+
+ if (shape == rb_shape_get_root_shape()) {
+ rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_id")), INT2NUM(ROOT_SHAPE_ID));
+ }
+ else {
+ rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_id")), INT2NUM(shape->parent_id));
+ }
+
+ rb_hash_aset(rb_shape, ID2SYM(rb_intern("edge_name")), rb_id2str(shape->edge_name));
+ return rb_shape;
+}
+
+/* :nodoc: */
+static VALUE
+shape_transition_tree(VALUE self)
+{
+ return rb_obj_shape(rb_shape_get_root_shape());
+}
+
+/* :nodoc: */
+static VALUE
+rb_shape_find_by_id(VALUE mod, VALUE id)
+{
+ shape_id_t shape_id = NUM2UINT(id);
+ if (shape_id >= GET_VM()->next_shape_id) {
+ rb_raise(rb_eArgError, "Shape ID %d is out of bounds\n", shape_id);
+ }
+ return rb_shape_t_to_rb_cShape(rb_shape_get_shape_by_id(shape_id));
+}
+#endif
+
+void
+Init_default_shapes(void)
+{
+ id_frozen = rb_make_internal_id();
+ id_t_object = rb_make_internal_id();
+
+ // Shapes by size pool
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ size_pool_edge_names[i] = rb_make_internal_id();
+ }
+
+ // Root shape
+ rb_shape_t * root = rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID);
+ root->capacity = (uint32_t)((rb_size_pool_slot_size(0) - offsetof(struct RObject, as.ary)) / sizeof(VALUE));
+ root->type = SHAPE_ROOT;
+ root->size_pool_index = 0;
+ GET_VM()->root_shape = root;
+ RUBY_ASSERT(rb_shape_id(GET_VM()->root_shape) == ROOT_SHAPE_ID);
+
+ // Shapes by size pool
+ for (int i = 1; i < SIZE_POOL_COUNT; i++) {
+ uint32_t capa = (uint32_t)((rb_size_pool_slot_size(i) - offsetof(struct RObject, as.ary)) / sizeof(VALUE));
+ rb_shape_t * new_shape = rb_shape_transition_shape_capa(root, capa);
+ new_shape->type = SHAPE_INITIAL_CAPACITY;
+ new_shape->size_pool_index = i;
+ RUBY_ASSERT(rb_shape_id(new_shape) == (shape_id_t)i);
+ }
+
+ // Make shapes for T_OBJECT
+ for (int i = 0; i < SIZE_POOL_COUNT; i++) {
+ rb_shape_t * shape = rb_shape_get_shape_by_id(i);
+ bool dont_care;
+ rb_shape_t * t_object_shape =
+ get_next_shape_internal(shape, id_t_object, SHAPE_T_OBJECT, &dont_care, true);
+ t_object_shape->edges = rb_id_table_create(0);
+ RUBY_ASSERT(rb_shape_id(t_object_shape) == (shape_id_t)(i + SIZE_POOL_COUNT));
+ }
+
+ bool dont_care;
+ // Special const shape
+#if RUBY_DEBUG
+ rb_shape_t * special_const_shape =
+#endif
+ get_next_shape_internal(root, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true);
+ RUBY_ASSERT(rb_shape_id(special_const_shape) == SPECIAL_CONST_SHAPE_ID);
+ RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_VM()->next_shape_id - 1));
+ RUBY_ASSERT(rb_shape_frozen_shape_p(special_const_shape));
+
+ rb_shape_t * hash_fallback_shape = rb_shape_alloc_with_parent_id(0, ROOT_SHAPE_ID);
+ hash_fallback_shape->type = SHAPE_OBJ_TOO_COMPLEX;
+ hash_fallback_shape->size_pool_index = 0;
+ RUBY_ASSERT(OBJ_TOO_COMPLEX_SHAPE_ID == (GET_VM()->next_shape_id - 1));
+ RUBY_ASSERT(rb_shape_id(hash_fallback_shape) == OBJ_TOO_COMPLEX_SHAPE_ID);
+}
+
+void
+Init_shape(void)
+{
+#if SHAPE_DEBUG
+ VALUE rb_cShape = rb_struct_define_under(rb_cRubyVM, "Shape",
+ "id",
+ "parent_id",
+ "edge_name",
+ "next_iv_index",
+ "size_pool_index",
+ "type",
+ "capacity",
+ NULL);
+
+ rb_define_method(rb_cShape, "parent", rb_shape_parent, 0);
+ rb_define_method(rb_cShape, "edges", rb_shape_edges, 0);
+ rb_define_method(rb_cShape, "depth", rb_shape_export_depth, 0);
+ rb_define_method(rb_cShape, "too_complex?", rb_shape_too_complex, 0);
+ rb_define_const(rb_cShape, "SHAPE_ROOT", INT2NUM(SHAPE_ROOT));
+ rb_define_const(rb_cShape, "SHAPE_IVAR", INT2NUM(SHAPE_IVAR));
+ rb_define_const(rb_cShape, "SHAPE_T_OBJECT", INT2NUM(SHAPE_T_OBJECT));
+ rb_define_const(rb_cShape, "SHAPE_FROZEN", INT2NUM(SHAPE_FROZEN));
+ rb_define_const(rb_cShape, "SHAPE_ID_NUM_BITS", INT2NUM(SHAPE_ID_NUM_BITS));
+ rb_define_const(rb_cShape, "SHAPE_FLAG_SHIFT", INT2NUM(SHAPE_FLAG_SHIFT));
+ rb_define_const(rb_cShape, "SPECIAL_CONST_SHAPE_ID", INT2NUM(SPECIAL_CONST_SHAPE_ID));
+ rb_define_const(rb_cShape, "OBJ_TOO_COMPLEX_SHAPE_ID", INT2NUM(OBJ_TOO_COMPLEX_SHAPE_ID));
+ rb_define_const(rb_cShape, "SHAPE_MAX_VARIATIONS", INT2NUM(SHAPE_MAX_VARIATIONS));
+
+ rb_define_singleton_method(rb_cShape, "transition_tree", shape_transition_tree, 0);
+ rb_define_singleton_method(rb_cShape, "find_by_id", rb_shape_find_by_id, 1);
+ rb_define_singleton_method(rb_cShape, "of", rb_shape_debug_shape, 1);
+ rb_define_singleton_method(rb_cShape, "root_shape", rb_shape_root_shape, 0);
+#endif
+}
diff --git a/shape.h b/shape.h
new file mode 100644
index 0000000000..8f3451d492
--- /dev/null
+++ b/shape.h
@@ -0,0 +1,232 @@
+#ifndef RUBY_SHAPE_H
+#define RUBY_SHAPE_H
+
+#include "internal/gc.h"
+
+#if (SIZEOF_UINT64_T == SIZEOF_VALUE)
+#define SIZEOF_SHAPE_T 4
+#define SHAPE_IN_BASIC_FLAGS 1
+typedef uint32_t attr_index_t;
+#else
+#define SIZEOF_SHAPE_T 2
+#define SHAPE_IN_BASIC_FLAGS 0
+typedef uint16_t attr_index_t;
+#endif
+
+#define MAX_IVARS (attr_index_t)(-1)
+
+#if SIZEOF_SHAPE_T == 4
+typedef uint32_t shape_id_t;
+# define SHAPE_ID_NUM_BITS 32
+#else
+typedef uint16_t shape_id_t;
+# define SHAPE_ID_NUM_BITS 16
+#endif
+
+# define SHAPE_MASK (((uintptr_t)1 << SHAPE_ID_NUM_BITS) - 1)
+# define SHAPE_FLAG_MASK (((VALUE)-1) >> SHAPE_ID_NUM_BITS)
+
+# define SHAPE_FLAG_SHIFT ((SIZEOF_VALUE * 8) - SHAPE_ID_NUM_BITS)
+
+# define SHAPE_BITMAP_SIZE 16384
+
+# define SHAPE_MAX_VARIATIONS 8
+
+# define MAX_SHAPE_ID (SHAPE_MASK - 1)
+# define INVALID_SHAPE_ID SHAPE_MASK
+# define ROOT_SHAPE_ID 0x0
+
+# define SPECIAL_CONST_SHAPE_ID (SIZE_POOL_COUNT * 2)
+# define OBJ_TOO_COMPLEX_SHAPE_ID (SPECIAL_CONST_SHAPE_ID + 1)
+
+struct rb_shape {
+ struct rb_id_table * edges; // id_table from ID (ivar) to next shape
+ ID edge_name; // ID (ivar) for transition from parent to rb_shape
+ attr_index_t next_iv_index;
+ uint32_t capacity; // Total capacity of the object with this shape
+ uint8_t type;
+ uint8_t size_pool_index;
+ shape_id_t parent_id;
+};
+
+typedef struct rb_shape rb_shape_t;
+
+enum shape_type {
+ SHAPE_ROOT,
+ SHAPE_IVAR,
+ SHAPE_FROZEN,
+ SHAPE_CAPACITY_CHANGE,
+ SHAPE_INITIAL_CAPACITY,
+ SHAPE_T_OBJECT,
+ SHAPE_OBJ_TOO_COMPLEX,
+};
+
+#if SHAPE_IN_BASIC_FLAGS
+static inline shape_id_t
+RBASIC_SHAPE_ID(VALUE obj)
+{
+ RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj));
+ return (shape_id_t)(SHAPE_MASK & ((RBASIC(obj)->flags) >> SHAPE_FLAG_SHIFT));
+}
+
+static inline void
+RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
+{
+ // Ractors are occupying the upper 32 bits of flags, but only in debug mode
+ // Object shapes are occupying top bits
+ RBASIC(obj)->flags &= SHAPE_FLAG_MASK;
+ RBASIC(obj)->flags |= ((VALUE)(shape_id) << SHAPE_FLAG_SHIFT);
+}
+
+static inline shape_id_t
+ROBJECT_SHAPE_ID(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ return RBASIC_SHAPE_ID(obj);
+}
+
+static inline void
+ROBJECT_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ RBASIC_SET_SHAPE_ID(obj, shape_id);
+}
+
+static inline shape_id_t
+RCLASS_SHAPE_ID(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE));
+ return RBASIC_SHAPE_ID(obj);
+}
+
+#else
+
+static inline shape_id_t
+ROBJECT_SHAPE_ID(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ return (shape_id_t)(SHAPE_MASK & (RBASIC(obj)->flags >> SHAPE_FLAG_SHIFT));
+}
+
+static inline void
+ROBJECT_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
+{
+ RBASIC(obj)->flags &= SHAPE_FLAG_MASK;
+ RBASIC(obj)->flags |= ((VALUE)(shape_id) << SHAPE_FLAG_SHIFT);
+}
+
+MJIT_SYMBOL_EXPORT_BEGIN
+shape_id_t rb_rclass_shape_id(VALUE obj);
+MJIT_SYMBOL_EXPORT_END
+
+static inline shape_id_t RCLASS_SHAPE_ID(VALUE obj)
+{
+ return rb_rclass_shape_id(obj);
+}
+
+#endif
+
+bool rb_shape_root_shape_p(rb_shape_t* shape);
+rb_shape_t * rb_shape_get_root_shape(void);
+uint8_t rb_shape_id_num_bits(void);
+int32_t rb_shape_id_offset(void);
+
+rb_shape_t* rb_shape_get_shape_by_id_without_assertion(shape_id_t shape_id);
+rb_shape_t * rb_shape_get_parent(rb_shape_t * shape);
+
+MJIT_SYMBOL_EXPORT_BEGIN
+rb_shape_t* rb_shape_get_shape_by_id(shape_id_t shape_id);
+shape_id_t rb_shape_get_shape_id(VALUE obj);
+rb_shape_t * rb_shape_get_next_iv_shape(rb_shape_t * shape, ID id);
+bool rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t * value);
+bool rb_shape_obj_too_complex(VALUE obj);
+MJIT_SYMBOL_EXPORT_END
+
+void rb_shape_set_shape(VALUE obj, rb_shape_t* shape);
+rb_shape_t* rb_shape_get_shape(VALUE obj);
+int rb_shape_frozen_shape_p(rb_shape_t* shape);
+void rb_shape_transition_shape_frozen(VALUE obj);
+void rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape, VALUE * removed);
+rb_shape_t * rb_shape_transition_shape_capa(rb_shape_t * shape, uint32_t new_capacity);
+rb_shape_t* rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id);
+
+rb_shape_t * rb_shape_rebuild_shape(rb_shape_t * initial_shape, rb_shape_t * dest_shape);
+
+static inline uint32_t
+ROBJECT_IV_CAPACITY(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ // Asking for capacity doesn't make sense when the object is using
+ // a hash table for storing instance variables
+ RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) != OBJ_TOO_COMPLEX_SHAPE_ID);
+ return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->capacity;
+}
+
+static inline st_table *
+ROBJECT_IV_HASH(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID);
+ return (st_table *)ROBJECT(obj)->as.heap.ivptr;
+}
+
+static inline void
+ROBJECT_SET_IV_HASH(VALUE obj, const struct rb_id_table *tbl)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID);
+ ROBJECT(obj)->as.heap.ivptr = (VALUE *)tbl;
+}
+
+size_t rb_id_table_size(const struct rb_id_table *tbl);
+
+static inline uint32_t
+ROBJECT_IV_COUNT(VALUE obj)
+{
+ if (ROBJECT_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID) {
+ return (uint32_t)rb_st_table_size(ROBJECT_IV_HASH(obj));
+ }
+ else {
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) != OBJ_TOO_COMPLEX_SHAPE_ID);
+ return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->next_iv_index;
+ }
+}
+
+static inline uint32_t
+RBASIC_IV_COUNT(VALUE obj)
+{
+ return rb_shape_get_shape_by_id(rb_shape_get_shape_id(obj))->next_iv_index;
+}
+
+static inline uint32_t
+RCLASS_IV_COUNT(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+ uint32_t ivc = rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj))->next_iv_index;
+ return ivc;
+}
+
+rb_shape_t * rb_shape_alloc(ID edge_name, rb_shape_t * parent);
+rb_shape_t * rb_shape_alloc_with_size_pool_index(ID edge_name, rb_shape_t * parent, uint8_t size_pool_index);
+rb_shape_t * rb_shape_alloc_with_parent_id(ID edge_name, shape_id_t parent_id);
+
+rb_shape_t *rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *orig_shape);
+
+bool rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id);
+
+VALUE rb_obj_debug_shape(VALUE self, VALUE obj);
+VALUE rb_shape_flags_mask(void);
+void rb_shape_set_too_complex(VALUE obj);
+
+// For ext/objspace
+RUBY_SYMBOL_EXPORT_BEGIN
+typedef void each_shape_callback(rb_shape_t * shape, void *data);
+void rb_shape_each_shape(each_shape_callback callback, void *data);
+size_t rb_shape_memsize(rb_shape_t *shape);
+size_t rb_shape_edges_count(rb_shape_t *shape);
+size_t rb_shape_depth(rb_shape_t *shape);
+shape_id_t rb_shape_id(rb_shape_t * shape);
+RUBY_SYMBOL_EXPORT_END
+
+#endif
diff --git a/signal.c b/signal.c
index 46ac6c26cc..1072cb47f1 100644
--- a/signal.c
+++ b/signal.c
@@ -44,6 +44,7 @@
#include "ruby_atomic.h"
#include "vm_core.h"
#include "ractor_core.h"
+#include "ruby/internal/attr/nonstring.h"
#ifdef NEED_RUBY_ATOMIC_OPS
rb_atomic_t
@@ -56,11 +57,11 @@ ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
rb_atomic_t
ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp,
- rb_atomic_t newval)
+ rb_atomic_t newval)
{
rb_atomic_t old = *ptr;
if (old == cmp) {
- *ptr = newval;
+ *ptr = newval;
}
return old;
}
@@ -214,34 +215,34 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr)
int prefix = 0;
if (RB_SYMBOL_P(vsig)) {
- *sig_ptr = vsig = rb_sym2str(vsig);
+ *sig_ptr = vsig = rb_sym2str(vsig);
}
else if (!RB_TYPE_P(vsig, T_STRING)) {
- VALUE str = rb_check_string_type(vsig);
- if (NIL_P(str)) {
- rb_raise(rb_eArgError, "bad signal type %s",
- rb_obj_classname(vsig));
- }
- *sig_ptr = vsig = str;
+ VALUE str = rb_check_string_type(vsig);
+ if (NIL_P(str)) {
+ rb_raise(rb_eArgError, "bad signal type %s",
+ rb_obj_classname(vsig));
+ }
+ *sig_ptr = vsig = str;
}
rb_must_asciicompat(vsig);
RSTRING_GETMEM(vsig, nm, len);
if (memchr(nm, '\0', len)) {
- rb_raise(rb_eArgError, "signal name with null byte");
+ rb_raise(rb_eArgError, "signal name with null byte");
}
if (len > 0 && nm[0] == '-') {
- if (!negative)
- rb_raise(rb_eArgError, "negative signal name: % "PRIsVALUE, vsig);
- prefix = 1;
+ if (!negative)
+ rb_raise(rb_eArgError, "negative signal name: % "PRIsVALUE, vsig);
+ prefix = 1;
}
else {
- negative = 0;
+ negative = 0;
}
if (len >= prefix + signame_prefix_len) {
if (memcmp(nm + prefix, signame_prefix, signame_prefix_len) == 0)
- prefix += signame_prefix_len;
+ prefix += signame_prefix_len;
}
if (len <= (long)prefix) {
goto unsupported;
@@ -252,10 +253,10 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr)
nm += prefix;
if (nmlen > LONGEST_SIGNAME) goto unsupported;
FOREACH_SIGNAL(sigs, !exit) {
- if (memcmp(sigs->signm, nm, nmlen) == 0 &&
- sigs->signm[nmlen] == '\0') {
- return negative ? -sigs->signo : sigs->signo;
- }
+ if (memcmp(sigs->signm, nm, nmlen) == 0 &&
+ sigs->signm[nmlen] == '\0') {
+ return negative ? -sigs->signo : sigs->signo;
+ }
}
unsupported:
@@ -284,8 +285,8 @@ signo2signm(int no)
const struct signals *sigs;
FOREACH_SIGNAL(sigs, 0) {
- if (sigs->signo == no)
- return sigs->signm;
+ if (sigs->signo == no)
+ return sigs->signm;
}
return 0;
}
@@ -323,10 +324,10 @@ rb_signo2signm(int signo)
{
const char *const signm = signo2signm(signo);
if (signm) {
- return rb_sprintf("SIG%s", signm);
+ return rb_sprintf("SIG%s", signm);
}
else {
- return rb_sprintf("SIG%u", signo);
+ return rb_sprintf("SIG%u", signo);
}
}
@@ -347,29 +348,29 @@ esignal_init(int argc, VALUE *argv, VALUE self)
int signo;
if (argc > 0) {
- sig = rb_check_to_integer(argv[0], "to_int");
- if (!NIL_P(sig)) argnum = 2;
- else sig = argv[0];
+ sig = rb_check_to_integer(argv[0], "to_int");
+ if (!NIL_P(sig)) argnum = 2;
+ else sig = argv[0];
}
rb_check_arity(argc, 1, argnum);
if (argnum == 2) {
- signo = NUM2INT(sig);
- if (signo < 0 || signo > NSIG) {
- rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
- }
- if (argc > 1) {
- sig = argv[1];
- }
- else {
- sig = rb_signo2signm(signo);
- }
+ signo = NUM2INT(sig);
+ if (signo < 0 || signo > NSIG) {
+ rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
+ }
+ if (argc > 1) {
+ sig = argv[1];
+ }
+ else {
+ sig = rb_signo2signm(signo);
+ }
}
else {
- int prefix;
- signo = signm2signo(&sig, FALSE, FALSE, &prefix);
- if (prefix != signame_prefix_len) {
- sig = rb_str_append(rb_str_new_cstr("SIG"), sig);
- }
+ int prefix;
+ signo = signm2signo(&sig, FALSE, FALSE, &prefix);
+ if (prefix != signame_prefix_len) {
+ sig = rb_str_append(rb_str_new_cstr("SIG"), sig);
+ }
}
rb_call_super(1, &sig);
rb_ivar_set(self, id_signo, INT2NUM(signo));
@@ -432,72 +433,72 @@ rb_f_kill(int argc, const VALUE *argv)
rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
if (FIXNUM_P(argv[0])) {
- sig = FIX2INT(argv[0]);
+ sig = FIX2INT(argv[0]);
}
else {
- str = argv[0];
- sig = signm2signo(&str, TRUE, FALSE, NULL);
+ str = argv[0];
+ sig = signm2signo(&str, TRUE, FALSE, NULL);
}
if (argc <= 1) return INT2FIX(0);
if (sig < 0) {
- sig = -sig;
- for (i=1; i<argc; i++) {
- if (killpg(NUM2PIDT(argv[i]), sig) < 0)
- rb_sys_fail(0);
- }
+ sig = -sig;
+ for (i=1; i<argc; i++) {
+ if (killpg(NUM2PIDT(argv[i]), sig) < 0)
+ rb_sys_fail(0);
+ }
}
else {
- const rb_pid_t self = (GET_THREAD() == GET_VM()->ractor.main_thread) ? getpid() : -1;
- int wakeup = 0;
-
- for (i=1; i<argc; i++) {
- rb_pid_t pid = NUM2PIDT(argv[i]);
-
- if ((sig != 0) && (self != -1) && (pid == self)) {
- int t;
- /*
- * When target pid is self, many caller assume signal will be
- * delivered immediately and synchronously.
- */
- switch (sig) {
- case SIGSEGV:
+ const rb_pid_t self = (GET_THREAD() == GET_VM()->ractor.main_thread) ? getpid() : -1;
+ int wakeup = 0;
+
+ for (i=1; i<argc; i++) {
+ rb_pid_t pid = NUM2PIDT(argv[i]);
+
+ if ((sig != 0) && (self != -1) && (pid == self)) {
+ int t;
+ /*
+ * When target pid is self, many caller assume signal will be
+ * delivered immediately and synchronously.
+ */
+ switch (sig) {
+ case SIGSEGV:
#ifdef SIGBUS
- case SIGBUS:
+ case SIGBUS:
#endif
#ifdef SIGKILL
- case SIGKILL:
+ case SIGKILL:
#endif
#ifdef SIGILL
- case SIGILL:
+ case SIGILL:
#endif
#ifdef SIGFPE
- case SIGFPE:
+ case SIGFPE:
#endif
#ifdef SIGSTOP
- case SIGSTOP:
-#endif
- kill(pid, sig);
- break;
- default:
- t = signal_ignored(sig);
- if (t) {
- if (t < 0 && kill(pid, sig))
- rb_sys_fail(0);
- break;
- }
- signal_enque(sig);
- wakeup = 1;
- }
- }
- else if (kill(pid, sig) < 0) {
- rb_sys_fail(0);
- }
- }
- if (wakeup) {
- rb_threadptr_check_signal(GET_VM()->ractor.main_thread);
- }
+ case SIGSTOP:
+#endif
+ kill(pid, sig);
+ break;
+ default:
+ t = signal_ignored(sig);
+ if (t) {
+ if (t < 0 && kill(pid, sig))
+ rb_sys_fail(0);
+ break;
+ }
+ signal_enque(sig);
+ wakeup = 1;
+ }
+ }
+ else if (kill(pid, sig) < 0) {
+ rb_sys_fail(0);
+ }
+ }
+ if (wakeup) {
+ rb_threadptr_check_signal(GET_VM()->ractor.main_thread);
+ }
}
rb_thread_execute_interrupts(rb_thread_current());
@@ -542,10 +543,10 @@ rb_sigaltstack_size(void)
#endif
#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
{
- int pagesize;
- pagesize = (int)sysconf(_SC_PAGE_SIZE);
- if (size < pagesize)
- size = pagesize;
+ int pagesize;
+ pagesize = (int)sysconf(_SC_PAGE_SIZE);
+ if (size < pagesize)
+ size = pagesize;
}
#endif
@@ -557,10 +558,13 @@ 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();
+ rb_sigaltstack_size_value = rb_sigaltstack_size();
}
- return xmalloc(rb_sigaltstack_size_value);
+ altstack = malloc(rb_sigaltstack_size_value);
+ if (!altstack) rb_memerror();
+ return altstack;
}
/* alternate stack for SIGSEGV */
@@ -607,42 +611,42 @@ ruby_signal(int signum, sighandler_t handler)
switch (signum) {
#if RUBY_SIGCHLD
case RUBY_SIGCHLD:
- if (handler == SIG_IGN) {
- ruby_nocldwait = 1;
+ if (handler == SIG_IGN) {
+ ruby_nocldwait = 1;
# ifdef USE_SIGALTSTACK
- if (sigact.sa_flags & SA_SIGINFO) {
- sigact.sa_sigaction = (ruby_sigaction_t*)sighandler;
- }
- else {
- sigact.sa_handler = sighandler;
- }
+ if (sigact.sa_flags & SA_SIGINFO) {
+ sigact.sa_sigaction = (ruby_sigaction_t*)sighandler;
+ }
+ else {
+ sigact.sa_handler = sighandler;
+ }
# else
- sigact.sa_handler = handler;
- sigact.sa_flags = 0;
+ sigact.sa_handler = handler;
+ sigact.sa_flags = 0;
# endif
- }
- else {
- ruby_nocldwait = 0;
- }
- break;
+ }
+ else {
+ ruby_nocldwait = 0;
+ }
+ break;
#endif
#if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK)
case SIGSEGV:
#ifdef SIGBUS
case SIGBUS:
#endif
- sigact.sa_flags |= SA_ONSTACK;
- break;
+ sigact.sa_flags |= SA_ONSTACK;
+ break;
#endif
}
(void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old));
if (sigaction(signum, &sigact, &old) < 0) {
- return SIG_ERR;
+ return SIG_ERR;
}
if (old.sa_flags & SA_SIGINFO)
- handler = (sighandler_t)old.sa_sigaction;
+ handler = (sighandler_t)old.sa_sigaction;
else
- handler = old.sa_handler;
+ handler = old.sa_handler;
ASSUME(handler != SIG_ERR);
return handler;
}
@@ -658,8 +662,8 @@ static inline sighandler_t
ruby_signal(int signum, sighandler_t handler)
{
if (signum == SIGKILL) {
- errno = EINVAL;
- return SIG_ERR;
+ errno = EINVAL;
+ return SIG_ERR;
}
return signal(signum, handler);
}
@@ -772,14 +776,14 @@ rb_get_next_signal(void)
int i, sig = 0;
if (signal_buff.size != 0) {
- for (i=1; i<RUBY_NSIG; i++) {
- if (signal_buff.cnt[i] > 0) {
- ATOMIC_DEC(signal_buff.cnt[i]);
- ATOMIC_DEC(signal_buff.size);
- sig = i;
- break;
- }
- }
+ for (i=1; i<RUBY_NSIG; i++) {
+ if (signal_buff.cnt[i] > 0) {
+ ATOMIC_DEC(signal_buff.cnt[i]);
+ ATOMIC_DEC(signal_buff.size);
+ sig = i;
+ break;
+ }
+ }
}
return sig;
}
@@ -819,7 +823,7 @@ reset_sigmask(int sig)
sigemptyset(&mask);
sigaddset(&mask, sig);
if (ruby_sigunmask(SIG_UNBLOCK, &mask, NULL)) {
- rb_bug_errno(STRINGIZE(ruby_sigunmask)":unblock", errno);
+ rb_bug_errno(STRINGIZE(ruby_sigunmask)":unblock", errno);
}
#endif
}
@@ -876,17 +880,18 @@ check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx)
* the fault page can be the next. */
if (sp_page == fault_page || sp_page == fault_page + 1 ||
(sp_page <= fault_page && fault_page <= bp_page)) {
- rb_execution_context_t *ec = GET_EC();
- int crit = FALSE;
- if ((uintptr_t)ec->tag->buf / pagesize <= fault_page + 1) {
- /* drop the last tag if it is close to the fault,
- * otherwise it can cause stack overflow again at the same
- * place. */
- ec->tag = ec->tag->prev;
- crit = TRUE;
- }
- reset_sigmask(sig);
- rb_ec_stack_overflow(ec, crit);
+ rb_execution_context_t *ec = GET_EC();
+ int crit = FALSE;
+ int uplevel = roomof(pagesize, sizeof(*ec->tag)) / 2; /* XXX: heuristic */
+ while ((uintptr_t)ec->tag->buf / pagesize <= fault_page + 1) {
+ /* drop the last tag if it is close to the fault,
+ * otherwise it can cause stack overflow again at the same
+ * place. */
+ if ((crit = (!ec->tag->prev || !--uplevel)) != FALSE) break;
+ ec->tag = ec->tag->prev;
+ }
+ reset_sigmask(sig);
+ rb_ec_stack_overflow(ec, crit);
}
}
# else
@@ -896,8 +901,8 @@ check_stack_overflow(int sig, const void *addr)
int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
rb_thread_t *th = GET_THREAD();
if (ruby_stack_overflowed_p(th, addr)) {
- reset_sigmask(sig);
- rb_ec_stack_overflow(th->ec, FALSE);
+ reset_sigmask(sig);
+ rb_ec_stack_overflow(th->ec, FALSE);
}
}
# endif
@@ -970,7 +975,7 @@ static void
sigill(int sig SIGINFO_ARG)
{
check_reserved_signal("ILL");
-#if defined __APPLE__
+#if defined __APPLE__ || defined __linux__
CHECK_STACK_OVERFLOW();
#endif
rb_bug_for_fatal_signal(default_sigill_handler, sig, SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS);
@@ -1000,30 +1005,30 @@ check_reserved_signal_(const char *name, size_t name_len)
const char *prev = ATOMIC_PTR_EXCHANGE(received_signal, name);
if (prev) {
- ssize_t RB_UNUSED_VAR(err);
-#define NOZ(name, str) name[sizeof(str)-1] = str
- static const char NOZ(msg1, " received in ");
- static const char NOZ(msg2, " handler\n");
+ ssize_t RB_UNUSED_VAR(err);
+#define NOZ(name, str) RBIMPL_ATTR_NONSTRING() name[sizeof(str)-1] = str
+ static const char NOZ(msg1, " received in ");
+ static const char NOZ(msg2, " handler\n");
#ifdef HAVE_WRITEV
- struct iovec iov[4];
-
- iov[0].iov_base = (void *)name;
- iov[0].iov_len = name_len;
- iov[1].iov_base = (void *)msg1;
- iov[1].iov_len = sizeof(msg1);
- iov[2].iov_base = (void *)prev;
- iov[2].iov_len = strlen(prev);
- iov[3].iov_base = (void *)msg2;
- iov[3].iov_len = sizeof(msg2);
- err = writev(2, iov, 4);
+ struct iovec iov[4];
+
+ iov[0].iov_base = (void *)name;
+ iov[0].iov_len = name_len;
+ iov[1].iov_base = (void *)msg1;
+ iov[1].iov_len = sizeof(msg1);
+ iov[2].iov_base = (void *)prev;
+ iov[2].iov_len = strlen(prev);
+ iov[3].iov_base = (void *)msg2;
+ iov[3].iov_len = sizeof(msg2);
+ err = writev(2, iov, 4);
#else
- err = write(2, name, name_len);
- err = write(2, msg1, sizeof(msg1));
- err = write(2, prev, strlen(prev));
- err = write(2, msg2, sizeof(msg2));
+ err = write(2, name, name_len);
+ err = write(2, msg1, sizeof(msg1));
+ err = write(2, prev, strlen(prev));
+ err = write(2, msg2, sizeof(msg2));
#endif
- ruby_abort();
+ ruby_abort();
}
ruby_disable_gc = 1;
@@ -1051,12 +1056,12 @@ signal_exec(VALUE cmd, int sig)
* 3. rb_signal_exec runs on queued signal
*/
if (IMMEDIATE_P(cmd))
- return FALSE;
+ return FALSE;
ec->interrupt_mask |= TRAP_INTERRUPT_MASK;
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- VALUE signum = INT2NUM(sig);
+ VALUE signum = INT2NUM(sig);
rb_eval_cmd_kw(cmd, rb_ary_new3(1, signum), RB_NO_KEYWORDS);
}
EC_POP_TAG();
@@ -1064,8 +1069,8 @@ signal_exec(VALUE cmd, int sig)
ec->interrupt_mask = old_interrupt_mask;
if (state) {
- /* XXX: should be replaced with rb_threadptr_pending_interrupt_enque() */
- EC_JUMP_TAG(ec, state);
+ /* XXX: should be replaced with rb_threadptr_pending_interrupt_enque() */
+ EC_JUMP_TAG(ec, state);
}
return TRUE;
}
@@ -1076,7 +1081,7 @@ rb_vm_trap_exit(rb_vm_t *vm)
VALUE trap_exit = vm->trap_list.cmd[0];
if (trap_exit) {
- vm->trap_list.cmd[0] = 0;
+ vm->trap_list.cmd[0] = 0;
signal_exec(trap_exit, 0);
}
}
@@ -1099,34 +1104,34 @@ rb_signal_exec(rb_thread_t *th, int sig)
VALUE cmd = vm->trap_list.cmd[sig];
if (cmd == 0) {
- switch (sig) {
- case SIGINT:
- rb_interrupt();
- break;
+ switch (sig) {
+ case SIGINT:
+ rb_interrupt();
+ break;
#ifdef SIGHUP
- case SIGHUP:
+ case SIGHUP:
#endif
#ifdef SIGQUIT
- case SIGQUIT:
+ case SIGQUIT:
#endif
#ifdef SIGTERM
- case SIGTERM:
+ case SIGTERM:
#endif
#ifdef SIGALRM
- case SIGALRM:
+ case SIGALRM:
#endif
#ifdef SIGUSR1
- case SIGUSR1:
+ case SIGUSR1:
#endif
#ifdef SIGUSR2
- case SIGUSR2:
+ case SIGUSR2:
#endif
- rb_threadptr_signal_raise(th, sig);
- break;
- }
+ rb_threadptr_signal_raise(th, sig);
+ break;
+ }
}
- else if (cmd == Qundef) {
- rb_threadptr_signal_exit(th);
+ else if (UNDEF_P(cmd)) {
+ rb_threadptr_signal_exit(th);
}
else {
return signal_exec(cmd, sig);
@@ -1198,21 +1203,21 @@ trap_handler(VALUE *cmd, int sig)
VALUE command;
if (NIL_P(*cmd)) {
- func = SIG_IGN;
+ func = SIG_IGN;
}
else {
- command = rb_check_string_type(*cmd);
- if (NIL_P(command) && SYMBOL_P(*cmd)) {
- command = rb_sym2str(*cmd);
- if (!command) rb_raise(rb_eArgError, "bad handler");
- }
- if (!NIL_P(command)) {
- const char *cptr;
- long len;
+ command = rb_check_string_type(*cmd);
+ if (NIL_P(command) && SYMBOL_P(*cmd)) {
+ command = rb_sym2str(*cmd);
+ if (!command) rb_raise(rb_eArgError, "bad handler");
+ }
+ if (!NIL_P(command)) {
+ const char *cptr;
+ long len;
StringValue(command);
- *cmd = command;
- RSTRING_GETMEM(command, cptr, len);
- switch (len) {
+ *cmd = command;
+ RSTRING_GETMEM(command, cptr, len);
+ switch (len) {
sig_ign:
func = SIG_IGN;
*cmd = Qtrue;
@@ -1221,46 +1226,46 @@ trap_handler(VALUE *cmd, int sig)
func = default_handler(sig);
*cmd = 0;
break;
- case 0:
+ case 0:
goto sig_ign;
- break;
+ break;
case 14:
- if (memcmp(cptr, "SYSTEM_DEFAULT", 14) == 0) {
+ if (memcmp(cptr, "SYSTEM_DEFAULT", 14) == 0) {
if (sig == RUBY_SIGCHLD) {
goto sig_dfl;
}
func = SIG_DFL;
*cmd = 0;
- }
+ }
break;
- case 7:
- if (memcmp(cptr, "SIG_IGN", 7) == 0) {
+ case 7:
+ if (memcmp(cptr, "SIG_IGN", 7) == 0) {
goto sig_ign;
- }
- else if (memcmp(cptr, "SIG_DFL", 7) == 0) {
+ }
+ else if (memcmp(cptr, "SIG_DFL", 7) == 0) {
goto sig_dfl;
- }
- else if (memcmp(cptr, "DEFAULT", 7) == 0) {
+ }
+ else if (memcmp(cptr, "DEFAULT", 7) == 0) {
goto sig_dfl;
- }
- break;
- case 6:
- if (memcmp(cptr, "IGNORE", 6) == 0) {
+ }
+ break;
+ case 6:
+ if (memcmp(cptr, "IGNORE", 6) == 0) {
goto sig_ign;
- }
- break;
- case 4:
- if (memcmp(cptr, "EXIT", 4) == 0) {
- *cmd = Qundef;
- }
- break;
- }
- }
- else {
- rb_proc_t *proc;
- GetProcPtr(*cmd, proc);
- (void)proc;
- }
+ }
+ break;
+ case 4:
+ if (memcmp(cptr, "EXIT", 4) == 0) {
+ *cmd = Qundef;
+ }
+ break;
+ }
+ }
+ else {
+ rb_proc_t *proc;
+ GetProcPtr(*cmd, proc);
+ (void)proc;
+ }
}
return func;
@@ -1272,13 +1277,13 @@ trap_signm(VALUE vsig)
int sig = -1;
if (FIXNUM_P(vsig)) {
- sig = FIX2INT(vsig);
- if (sig < 0 || sig >= NSIG) {
- rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
- }
+ sig = FIX2INT(vsig);
+ if (sig < 0 || sig >= NSIG) {
+ rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
+ }
}
else {
- sig = signm2signo(&vsig, FALSE, TRUE, NULL);
+ sig = signm2signo(&vsig, FALSE, TRUE, NULL);
}
return sig;
}
@@ -1296,26 +1301,26 @@ trap(int sig, sighandler_t func, VALUE command)
* RUBY_VM_CHECK_INTS().
*/
if (sig == 0) {
- oldfunc = SIG_ERR;
+ oldfunc = SIG_ERR;
}
else {
- oldfunc = ruby_signal(sig, func);
- if (oldfunc == SIG_ERR) rb_sys_fail_str(rb_signo2signm(sig));
+ oldfunc = ruby_signal(sig, func);
+ if (oldfunc == SIG_ERR) rb_sys_fail_str(rb_signo2signm(sig));
}
oldcmd = vm->trap_list.cmd[sig];
switch (oldcmd) {
case 0:
case Qtrue:
- if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
+ if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
else if (oldfunc == SIG_DFL) oldcmd = rb_str_new2("SYSTEM_DEFAULT");
- else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
- else oldcmd = Qnil;
- break;
+ else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
+ else oldcmd = Qnil;
+ break;
case Qnil:
- break;
+ break;
case Qundef:
- oldcmd = rb_str_new2("EXIT");
- break;
+ oldcmd = rb_str_new2("EXIT");
+ break;
}
ACCESS_ONCE(VALUE, vm->trap_list.cmd[sig]) = command;
@@ -1329,25 +1334,25 @@ reserved_signal_p(int signo)
/* Synchronous signal can't deliver to main thread */
#ifdef SIGSEGV
if (signo == SIGSEGV)
- return 1;
+ return 1;
#endif
#ifdef SIGBUS
if (signo == SIGBUS)
- return 1;
+ return 1;
#endif
#ifdef SIGILL
if (signo == SIGILL)
- return 1;
+ return 1;
#endif
#ifdef SIGFPE
if (signo == SIGFPE)
- return 1;
+ return 1;
#endif
/* used ubf internal see thread_pthread.c. */
#ifdef SIGVTALRM
if (signo == SIGVTALRM)
- return 1;
+ return 1;
#endif
return 0;
@@ -1403,12 +1408,12 @@ sig_trap(int argc, VALUE *argv, VALUE _)
}
if (argc == 1) {
- cmd = rb_block_proc();
- func = sighandler;
+ cmd = rb_block_proc();
+ func = sighandler;
}
else {
- cmd = argv[1];
- func = trap_handler(&cmd, sig);
+ cmd = argv[1];
+ func = trap_handler(&cmd, sig);
}
if (rb_obj_is_proc(cmd) &&
@@ -1435,16 +1440,16 @@ sig_list(VALUE _)
const struct signals *sigs;
FOREACH_SIGNAL(sigs, 0) {
- rb_hash_aset(h, rb_fstring_cstr(sigs->signm), INT2FIX(sigs->signo));
+ rb_hash_aset(h, rb_fstring_cstr(sigs->signm), INT2FIX(sigs->signo));
}
return h;
}
#define INSTALL_SIGHANDLER(cond, signame, signum) do { \
- static const char failed[] = "failed to install "signame" handler"; \
- if (!(cond)) break; \
- if (reserved_signal_p(signum)) rb_bug(failed); \
- perror(failed); \
+ static const char failed[] = "failed to install "signame" handler"; \
+ if (!(cond)) break; \
+ if (reserved_signal_p(signum)) rb_bug(failed); \
+ perror(failed); \
} while (0)
static int
install_sighandler_core(int signum, sighandler_t handler, sighandler_t *old_handler)
@@ -1496,7 +1501,7 @@ ruby_sig_finalize(void)
oldfunc = ruby_signal(SIGINT, SIG_IGN);
if (oldfunc == sighandler) {
- ruby_signal(SIGINT, SIG_DFL);
+ ruby_signal(SIGINT, SIG_DFL);
}
}
@@ -1580,14 +1585,14 @@ Init_signal(void)
if (!ruby_enable_coredump) {
#ifdef SIGBUS
- force_install_sighandler(SIGBUS, (sighandler_t)sigbus, &default_sigbus_handler);
+ force_install_sighandler(SIGBUS, (sighandler_t)sigbus, &default_sigbus_handler);
#endif
#ifdef SIGILL
- force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler);
+ force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler);
#endif
#ifdef SIGSEGV
- RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack());
- force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
+ RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack());
+ force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
#endif
}
#ifdef SIGPIPE
diff --git a/siphash.c b/siphash.c
index 091376747f..62de622778 100644
--- a/siphash.c
+++ b/siphash.c
@@ -34,10 +34,11 @@
#error "Only strictly little or big endian supported"
#endif
+/* __POWERPC__ added to accommodate Darwin case. */
#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(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
defined(__mc68020__)
# define UNALIGNED_WORD_ACCESS 1
# endif
@@ -96,7 +97,7 @@ u64to8_le(uint8_t *p, uint64_t v)
}
#define ROTL64_TO(v, s) ((s) > 32 ? rotl64_swap(rotl64_to(&(v), (s) - 32)) : \
- (s) == 32 ? rotl64_swap(&(v)) : rotl64_to(&(v), (s)))
+ (s) == 32 ? rotl64_swap(&(v)) : rotl64_to(&(v), (s)))
static inline uint64_t *
rotl64_to(uint64_t *v, unsigned int s)
{
@@ -139,6 +140,9 @@ xor64_to(uint64_t *v, const uint64_t s)
#endif
static const union {
+#if defined(__has_attribute) && __has_attribute(nonstring)
+ __attribute__((nonstring))
+#endif
char bin[32];
uint64_t u64[4];
} sip_init_state_bin = {"uespemos""modnarod""arenegyl""setybdet"};
@@ -188,9 +192,9 @@ int_sip_dump(sip_state *state)
for (v = 0; v < 4; v++) {
#ifdef HAVE_UINT64_T
- printf("v%d: %" PRIx64 "\n", v, state->v[v]);
+ printf("v%d: %" PRIx64 "\n", v, state->v[v]);
#else
- printf("v%d: %" PRIx32 "%.8" PRIx32 "\n", v, state->v[v].hi, state->v[v].lo);
+ printf("v%d: %" PRIx32 "%.8" PRIx32 "\n", v, state->v[v].hi, state->v[v].lo);
#endif
}
}
@@ -215,7 +219,7 @@ int_sip_round(sip_state *state, int n)
int i;
for (i = 0; i < n; i++) {
- SIP_COMPRESS(state->v[0], state->v[1], state->v[2], state->v[3]);
+ SIP_COMPRESS(state->v[0], state->v[1], state->v[2], state->v[3]);
}
}
@@ -249,8 +253,8 @@ int_sip_post_update(sip_state *state, const uint8_t *data, size_t len)
{
uint8_t r = len % sizeof(uint64_t);
if (r) {
- memcpy(state->buf, data + len - r, r);
- state->buflen = r;
+ memcpy(state->buf, data + len - r, r);
+ state->buflen = r;
}
}
@@ -269,16 +273,16 @@ int_sip_update(sip_state *state, const uint8_t *data, size_t len)
#if BYTE_ORDER == LITTLE_ENDIAN
while (data64 != end) {
- int_sip_update_block(state, *data64++);
+ int_sip_update_block(state, *data64++);
}
#elif BYTE_ORDER == BIG_ENDIAN
{
- uint64_t m;
- uint8_t *data8 = data;
- for (; data8 != (uint8_t *) end; data8 += sizeof(uint64_t)) {
- m = U8TO64_LE(data8);
- int_sip_update_block(state, m);
- }
+ uint64_t m;
+ uint8_t *data8 = data;
+ for (; data8 != (uint8_t *) end; data8 += sizeof(uint64_t)) {
+ m = U8TO64_LE(data8);
+ int_sip_update_block(state, m);
+ }
}
#endif
@@ -291,7 +295,7 @@ int_sip_pad_final_block(sip_state *state)
int i;
/* pad with 0's and finalize with msg_len mod 256 */
for (i = state->buflen; i < sizeof(uint64_t); i++) {
- state->buf[i] = 0x00;
+ state->buf[i] = 0x00;
}
state->buf[sizeof(uint64_t) - 1] = state->msglen_byte;
}
@@ -420,14 +424,14 @@ sip_hash13(const uint8_t key[16], const uint8_t *data, size_t len)
{
uint64_t *data64 = (uint64_t *)data;
while (data64 != (uint64_t *) end) {
- m = *data64++;
- SIP_ROUND(m, v0, v1, v2, v3);
+ m = *data64++;
+ SIP_ROUND(m, v0, v1, v2, v3);
}
}
#else
for (; data != end; data += sizeof(uint64_t)) {
- m = U8TO64_LE(data);
- SIP_ROUND(m, v0, v1, v2, v3);
+ m = U8TO64_LE(data);
+ SIP_ROUND(m, v0, v1, v2, v3);
}
#endif
@@ -438,40 +442,40 @@ sip_hash13(const uint8_t key[16], const uint8_t *data, size_t len)
last.hi = len << 24;
last.lo = 0;
#define OR_BYTE(n) do { \
- if (n >= 4) \
- last.hi |= ((uint32_t) end[n]) << ((n) >= 4 ? (n) * 8 - 32 : 0); \
- else \
- last.lo |= ((uint32_t) end[n]) << ((n) >= 4 ? 0 : (n) * 8); \
+ if (n >= 4) \
+ last.hi |= ((uint32_t) end[n]) << ((n) >= 4 ? (n) * 8 - 32 : 0); \
+ else \
+ last.lo |= ((uint32_t) end[n]) << ((n) >= 4 ? 0 : (n) * 8); \
} while (0)
#endif
switch (len % sizeof(uint64_t)) {
- case 7:
- OR_BYTE(6);
- case 6:
- OR_BYTE(5);
- case 5:
- OR_BYTE(4);
- case 4:
+ case 7:
+ OR_BYTE(6);
+ case 6:
+ OR_BYTE(5);
+ case 5:
+ OR_BYTE(4);
+ case 4:
#if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS
#ifdef HAVE_UINT64_T
- last |= (uint64_t) ((uint32_t *) end)[0];
+ last |= (uint64_t) ((uint32_t *) end)[0];
#else
- last.lo |= ((uint32_t *) end)[0];
+ last.lo |= ((uint32_t *) end)[0];
#endif
- break;
+ break;
#else
- OR_BYTE(3);
+ OR_BYTE(3);
#endif
- case 3:
- OR_BYTE(2);
- case 2:
- OR_BYTE(1);
- case 1:
- OR_BYTE(0);
- break;
- case 0:
- break;
+ case 3:
+ OR_BYTE(2);
+ case 2:
+ OR_BYTE(1);
+ case 1:
+ OR_BYTE(0);
+ break;
+ case 0:
+ break;
}
SIP_ROUND(last, v0, v1, v2, v3);
diff --git a/sparc.c b/sparc.c
index 7f3a70fd0e..fe9dd684f4 100644
--- a/sparc.c
+++ b/sparc.c
@@ -7,7 +7,7 @@
window of the process executing the instruction will not be flushed
correctly.
- See http://bugs.ruby-lang.org/issues/5244 for discussion.
+ See https://bugs.ruby-lang.org/issues/5244 for discussion.
*********************************************************************/
void
rb_sparc_flush_register_windows(void)
@@ -15,7 +15,7 @@ rb_sparc_flush_register_windows(void)
/*
* gcc doesn't provide "asm" keyword if -ansi and the various -std options
* are given.
- * http://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html
+ * https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html
*/
#ifndef __GNUC__
#define __asm__ asm
diff --git a/spec/README.md b/spec/README.md
index c67aedbb80..4fcf090759 100644
--- a/spec/README.md
+++ b/spec/README.md
@@ -1,14 +1,23 @@
# spec/bundler
-spec/bundler is rspec examples for bundler library(lib/bundler.rb, lib/bundler/*).
+spec/bundler is rspec examples for bundler library (`lib/bundler.rb`, `lib/bundler/*`).
## Running spec/bundler
To run rspec for bundler:
+
```bash
make test-bundler
```
+or run rspec with parallel execution:
+
+```bash
+make test-bundler-parallel
+```
+
+If you specify `BUNDLER_SPECS=foo/bar_spec.rb` then only `spec/bundler/foo/bar_spec.rb` will be run.
+
# spec/ruby
ruby/spec (https://github.com/ruby/spec/) is
@@ -37,6 +46,7 @@ which change behavior or are removed. This is necessary for other Ruby implement
to still be able to run the specs and contribute new specs.
For example, change:
+
```ruby
describe "Some spec" do
it "some example" do
@@ -44,7 +54,9 @@ describe "Some spec" do
end
end
```
+
to:
+
```ruby
describe "Some spec" do
ruby_version_is ""..."2.7" do
@@ -64,7 +76,8 @@ end
See `spec/ruby/CONTRIBUTING.md` for more documentation about guards.
To verify specs are compatible with older Ruby versions:
-```
+
+```bash
cd spec/ruby
$RUBY_MANAGER use 2.4.9
../mspec/bin/mspec -j
@@ -73,28 +86,33 @@ $RUBY_MANAGER use 2.4.9
## Running ruby/spec
To run all specs:
+
```bash
make test-spec
```
Extra arguments can be added via `MSPECOPT`.
For instance, to show the help:
+
```bash
make test-spec MSPECOPT=-h
```
You can also run the specs in parallel, which is currently experimental.
It takes around 10s instead of 60s on a quad-core laptop.
+
```bash
make test-spec MSPECOPT=-j
```
To run a specific test, add its path to the command:
+
```bash
make test-spec MSPECOPT=spec/ruby/language/for_spec.rb
```
If ruby trunk is your current `ruby` in `$PATH`, you can also run `mspec` directly:
+
```bash
# change ruby to trunk
ruby -v # => trunk
@@ -128,3 +146,15 @@ end
```
For more details, see `spec/ruby/CONTRIBUTING.md`.
+
+# spec/syntax_suggest
+
+## Running spec/syntax_suggest
+
+To run rspec for syntax_suggest:
+
+```bash
+make test-syntax-suggest
+```
+
+If you specify `SYNTAX_SUGGEST_SPECS=foo/bar_spec.rb` then only `spec/syntax_suggest/foo/bar_spec.rb` will be run.
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index d164b5d3c6..54fedc8568 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -4,6 +4,71 @@ require "bundler"
require "tmpdir"
RSpec.describe Bundler do
+ describe "#load_marshal" do
+ it "is a private method and raises an error" do
+ data = Marshal.dump(Bundler)
+ expect { Bundler.load_marshal(data) }.to raise_error(NoMethodError, /private method `load_marshal' called/)
+ end
+
+ it "loads any data" do
+ data = Marshal.dump(Bundler)
+ expect(Bundler.send(:load_marshal, data)).to eq(Bundler)
+ end
+ end
+
+ describe "#safe_load_marshal" do
+ it "fails on unexpected class" do
+ data = Marshal.dump(Bundler)
+ expect { Bundler.safe_load_marshal(data) }.to raise_error(Bundler::MarshalError)
+ end
+
+ it "loads simple structure" do
+ simple_structure = { "name" => [:abc] }
+ data = Marshal.dump(simple_structure)
+ expect(Bundler.safe_load_marshal(data)).to eq(simple_structure)
+ end
+
+ it "loads Gem::Specification" do
+ gem_spec = Gem::Specification.new do |s|
+ s.name = "bundler"
+ s.version = Gem::Version.new("2.4.7")
+ s.installed_by_version = Gem::Version.new("0")
+ s.authors = ["André Arko",
+ "Samuel Giddins",
+ "Colby Swandale",
+ "Hiroshi Shibata",
+ "David Rodríguez",
+ "Grey Baker",
+ "Stephanie Morillo",
+ "Chris Morris",
+ "James Wen",
+ "Tim Moore",
+ "André Medeiros",
+ "Jessica Lynn Suttles",
+ "Terence Lee",
+ "Carl Lerche",
+ "Yehuda Katz"]
+ s.date = Time.utc(2023, 2, 15)
+ s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
+ s.email = ["team@bundler.io"]
+ s.homepage = "https://bundler.io"
+ s.metadata = { "bug_tracker_uri" => "https://github.com/rubygems/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
+ "changelog_uri" => "https://github.com/rubygems/rubygems/blob/master/bundler/CHANGELOG.md",
+ "homepage_uri" => "https://bundler.io/",
+ "source_code_uri" => "https://github.com/rubygems/rubygems/tree/master/bundler" }
+ s.require_paths = ["lib"]
+ s.required_ruby_version = Gem::Requirement.new([">= 2.6.0"])
+ s.required_rubygems_version = Gem::Requirement.new([">= 3.0.1"])
+ s.rubygems_version = "3.4.7"
+ s.specification_version = 4
+ s.summary = "The best way to manage your application's dependencies"
+ s.license = false
+ end
+ data = Marshal.dump(gem_spec)
+ expect(Bundler.safe_load_marshal(data)).to eq(gem_spec)
+ end
+ end
+
describe "#load_gemspec_uncached" do
let(:app_gemspec_path) { tmp("test.gemspec") }
subject { Bundler.load_gemspec_uncached(app_gemspec_path) }
@@ -21,30 +86,6 @@ RSpec.describe Bundler do
it "catches YAML syntax errors" do
expect { subject }.to raise_error(Bundler::GemspecError, /error while loading `test.gemspec`/)
end
-
- context "on Rubies with a settable YAML engine", :if => defined?(YAML::ENGINE) do
- context "with Syck as YAML::Engine" do
- it "raises a GemspecError after YAML load throws ArgumentError" do
- orig_yamler = YAML::ENGINE.yamler
- YAML::ENGINE.yamler = "syck"
-
- expect { subject }.to raise_error(Bundler::GemspecError)
-
- YAML::ENGINE.yamler = orig_yamler
- end
- end
-
- context "with Psych as YAML::Engine" do
- it "raises a GemspecError after YAML load throws Psych::SyntaxError" do
- orig_yamler = YAML::ENGINE.yamler
- YAML::ENGINE.yamler = "psych"
-
- expect { subject }.to raise_error(Bundler::GemspecError)
-
- YAML::ENGINE.yamler = orig_yamler
- end
- end
- end
end
context "with correct YAML file", :if => defined?(Encoding) do
@@ -176,11 +217,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
@@ -193,9 +232,9 @@ RSpec.describe Bundler do
allow(::Bundler::FileUtils).to receive(:remove_entry_secure).and_raise(ArgumentError)
allow(File).to receive(:world_writable?).and_return(true)
message = <<EOF
-It is a security vulnerability to allow your home directory to be world-writable, and bundler can not continue.
+It is a security vulnerability to allow your home directory to be world-writable, and bundler cannot continue.
You should probably consider fixing this issue by running `chmod o-w ~` on *nix.
-Please refer to https://ruby-doc.org/stdlib-2.1.2/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure for details.
+Please refer to https://ruby-doc.org/stdlib-3.1.2/libdoc/fileutils/rdoc/FileUtils.html#method-c-remove_entry_secure for details.
EOF
expect(bundler_ui).to receive(:warn).with(message)
expect { Bundler.send(:rm_rf, bundled_app) }.to raise_error(Bundler::PathError)
@@ -215,22 +254,6 @@ EOF
Bundler.mkdir_p(bundled_app.join("foo", "bar"))
expect(bundled_app.join("foo", "bar")).to exist
end
-
- context "when mkdir_p requires sudo" do
- it "creates a new folder using sudo" do
- expect(Bundler).to receive(:requires_sudo?).and_return(true)
- expect(Bundler).to receive(:sudo).and_return true
- Bundler.mkdir_p(bundled_app.join("foo"))
- end
- end
-
- context "with :no_sudo option" do
- it "forces mkdir_p to not use sudo" do
- expect(Bundler).to receive(:requires_sudo?).and_return(true)
- expect(Bundler).to_not receive(:sudo)
- Bundler.mkdir_p(bundled_app.join("foo"), :no_sudo => true)
- end
- end
end
describe "#user_home" do
@@ -294,118 +317,6 @@ EOF
end
end
- describe "#requires_sudo?" do
- let!(:tmpdir) { Dir.mktmpdir }
- let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
-
- def clear_cached_requires_sudo
- return unless Bundler.instance_variable_defined?(:@requires_sudo_ran)
- Bundler.remove_instance_variable(:@requires_sudo_ran)
- Bundler.remove_instance_variable(:@requires_sudo)
- end
-
- before do
- clear_cached_requires_sudo
- allow(Bundler).to receive(:which).with("sudo").and_return("/usr/bin/sudo")
- allow(Bundler).to receive(:bundle_path).and_return(bundle_path)
- end
-
- after do
- FileUtils.rm_rf(tmpdir)
- clear_cached_requires_sudo
- end
-
- subject { Bundler.requires_sudo? }
-
- context "bundle_path doesn't exist" do
- it { should be false }
-
- context "and parent dir can't be written" do
- before do
- FileUtils.chmod(0o500, tmpdir)
- end
-
- it { should be true }
- end
-
- context "with unwritable files in a parent dir" do
- # 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
- file = File.join(tmpdir, "unrelated_file")
- FileUtils.touch(file)
- FileUtils.chmod(0o400, file)
- end
-
- it { should be false }
- end
- end
-
- context "bundle_path exists" do
- before do
- FileUtils.mkdir_p(bundle_path)
- end
-
- it { should be false }
-
- context "and is unwritable" do
- before do
- FileUtils.chmod(0o500, bundle_path)
- end
-
- it { should be true }
- end
- end
-
- context "path writability" do
- before do
- FileUtils.mkdir_p("tmp/vendor/bundle")
- FileUtils.mkdir_p("tmp/vendor/bin_dir")
- end
- after do
- FileUtils.rm_rf("tmp/vendor/bundle")
- FileUtils.rm_rf("tmp/vendor/bin_dir")
- end
- context "writable paths" do
- it "should return false and display nothing" do
- allow(Bundler).to receive(:bundle_path).and_return(Pathname("tmp/vendor/bundle"))
- expect(Bundler.ui).to_not receive(:warn)
- expect(Bundler.requires_sudo?).to eq(false)
- end
- end
- context "unwritable paths" do
- before do
- FileUtils.touch("tmp/vendor/bundle/unwritable1.txt")
- FileUtils.touch("tmp/vendor/bundle/unwritable2.txt")
- FileUtils.touch("tmp/vendor/bin_dir/unwritable3.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bundle/unwritable1.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bundle/unwritable2.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bin_dir/unwritable3.txt")
- end
- it "should return true and display warn message" do
- allow(Bundler).to receive(:bundle_path).and_return(Pathname("tmp/vendor/bundle"))
- bin_dir = Pathname("tmp/vendor/bin_dir/")
-
- # allow File#writable? to be called with args other than the stubbed on below
- allow(File).to receive(:writable?).and_call_original
-
- # fake make the directory unwritable
- allow(File).to receive(:writable?).with(bin_dir).and_return(false)
- allow(Bundler).to receive(:system_bindir).and_return(Pathname("tmp/vendor/bin_dir/"))
- message = <<-MESSAGE.chomp
-Following files may not be writable, so sudo is needed:
- tmp/vendor/bin_dir/
- tmp/vendor/bundle/unwritable1.txt
- tmp/vendor/bundle/unwritable2.txt
-MESSAGE
- expect(Bundler.ui).to receive(:warn).with(message)
- expect(Bundler.requires_sudo?).to eq(true)
- end
- end
- end
- end
-
context "user cache dir" do
let(:home_path) { Pathname.new(ENV["HOME"]) }
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb
index c9dd101f55..b752cd7e70 100644
--- a/spec/bundler/bundler/cli_spec.rb
+++ b/spec/bundler/bundler/cli_spec.rb
@@ -111,22 +111,6 @@ 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 "source \"#{file_uri_for(gem_repo1)}\""
@@ -145,6 +129,52 @@ RSpec.describe "bundle executable" do
end
end
+ describe "bundle outdated" do
+ let(:run_command) do
+ bundle "install"
+
+ bundle "outdated #{flags}", :raise_on_error => false
+ end
+
+ before do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", '0.9.1'
+ G
+ end
+
+ context "with --groups flag" do
+ let(:flags) { "--groups" }
+
+ it "prints a message when there are outdated gems" do
+ run_command
+
+ expect(out).to include("Gem Current Latest Requested Groups")
+ expect(out).to include("rack 0.9.1 1.0.0 = 0.9.1 default")
+ end
+ end
+
+ context "with --parseable" do
+ let(:flags) { "--parseable" }
+
+ it "prints a message when there are outdated gems" do
+ run_command
+
+ expect(out).to include("rack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
+ end
+ end
+
+ context "with --groups and --parseable" do
+ let(:flags) { "--groups --parseable" }
+
+ it "prints a simplified message when there are outdated gems" do
+ run_command
+
+ expect(out).to include("rack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
+ end
+ end
+ end
+
describe "printing the outdated warning" do
shared_examples_for "no warning" do
it "prints no warning" do
@@ -186,7 +216,7 @@ RSpec.describe "bundle executable" do
bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false
expect(err).to start_with(<<-EOS.strip)
The latest bundler is #{latest_version}, but you are currently running #{bundler_version}.
-To install the latest version, run `gem install bundler`
+To update to the most recent version, run `bundle update --bundler`
EOS
end
@@ -211,7 +241,7 @@ To install the latest version, run `gem install bundler`
bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false
expect(err).to start_with(<<-EOS.strip)
The latest bundler is #{latest_version}, but you are currently running #{bundler_version}.
-To install the latest version, run `gem install bundler --pre`
+To update to the most recent version, run `bundle update --bundler`
EOS
end
end
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index 4acd7dbc63..fe417e3920 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -36,16 +36,6 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
end
end
- context "when bundler doesn't have permissions on Dir.tmpdir" do
- it "Errno::EACCES is raised" do
- allow(Bundler::Dir).to receive(:mktmpdir) { raise Errno::EACCES }
-
- expect do
- updater.update(local_path, remote_path)
- end.to raise_error(Bundler::PermissionError)
- end
- end
-
context "when receiving non UTF-8 data and default internal encoding set to ASCII" do
let(:response) { double(:response, :body => "\x8B".b) }
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb
index bf000c468a..59b958ae42 100644
--- a/spec/bundler/bundler/definition_spec.rb
+++ b/spec/bundler/bundler/definition_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Bundler::Definition do
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:
@@ -82,6 +82,24 @@ RSpec.describe Bundler::Definition do
G
end
+ it "with an explicit update" do
+ build_repo4 do
+ build_gem("ffi", "1.9.23") {|s| s.platform = "java" }
+ build_gem("ffi", "1.9.23")
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "ffi"
+ G
+
+ bundle "lock --add-platform java"
+
+ bundle "update ffi", :env => { "DEBUG" => "1" }
+
+ expect(out).to match(/because bundler is unlocking gems: \(ffi\)/)
+ end
+
it "for a path gem with deps and no changes" do
build_lib "foo", "1.0", :path => lib_path("foo") do |s|
s.add_dependency "rack", "1.0"
@@ -96,7 +114,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:
@@ -129,15 +147,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("java")}
DEPENDENCIES
only_java
@@ -156,7 +173,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:
@@ -176,31 +193,6 @@ RSpec.describe Bundler::Definition do
describe "initialize" do
context "gem version promoter" do
- context "with lockfile" do
- before do
- install_gemfile <<-G
- 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_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
- end
- end
-
- context "without gemfile or lockfile" do
- it "should not attempt to parse empty lockfile contents" do
- definition = Bundler::Definition.new(nil, [], mock_source_list, true)
- expect(definition.gem_version_promoter.locked_specs.to_a).to eq []
- end
- end
-
context "eager unlock" do
let(:source_list) do
Bundler::SourceList.new.tap do |source_list|
diff --git a/spec/bundler/bundler/dep_proxy_spec.rb b/spec/bundler/bundler/dep_proxy_spec.rb
deleted file mode 100644
index 8d02a33725..0000000000
--- a/spec/bundler/bundler/dep_proxy_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe Bundler::DepProxy do
- let(:dep) { Bundler::Dependency.new("rake", ">= 0") }
- subject { described_class.get_proxy(dep, Gem::Platform::RUBY) }
- let(:same) { subject }
- 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 }
- it { expect(subject.eql?(other)).to be true }
- it { expect(subject.eql?(different)).to be false }
- it { expect(subject.eql?(nil)).to be false }
- it { expect(subject.eql?("foobar")).to be false }
- end
-
- 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/dependency_spec.rb b/spec/bundler/bundler/dependency_spec.rb
new file mode 100644
index 0000000000..6e346c36c1
--- /dev/null
+++ b/spec/bundler/bundler/dependency_spec.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Dependency do
+ let(:options) do
+ {}
+ end
+ let(:dependency) do
+ described_class.new(
+ "test_gem",
+ "1.0.0",
+ options
+ )
+ end
+
+ describe "to_lock" do
+ it "returns formatted string" do
+ expect(dependency.to_lock).to eq(" test_gem (= 1.0.0)")
+ end
+
+ it "matches format of Gem::Dependency#to_lock" do
+ gem_dependency = Gem::Dependency.new("test_gem", "1.0.0")
+ expect(dependency.to_lock).to eq(gem_dependency.to_lock)
+ end
+
+ context "when source is passed" do
+ let(:options) do
+ {
+ "source" => Bundler::Source::Git.new({}),
+ }
+ end
+
+ it "returns formatted string with exclamation mark" do
+ expect(dependency.to_lock).to eq(" test_gem (= 1.0.0)!")
+ end
+ end
+ end
+
+ describe "PLATFORM_MAP" do
+ subject { described_class::PLATFORM_MAP }
+
+ # rubocop:disable Naming/VariableNumber
+ let(:platforms) do
+ { :ruby => Gem::Platform::RUBY,
+ :ruby_18 => Gem::Platform::RUBY,
+ :ruby_19 => Gem::Platform::RUBY,
+ :ruby_20 => Gem::Platform::RUBY,
+ :ruby_21 => Gem::Platform::RUBY,
+ :ruby_22 => Gem::Platform::RUBY,
+ :ruby_23 => Gem::Platform::RUBY,
+ :ruby_24 => Gem::Platform::RUBY,
+ :ruby_25 => Gem::Platform::RUBY,
+ :ruby_26 => Gem::Platform::RUBY,
+ :ruby_27 => Gem::Platform::RUBY,
+ :ruby_30 => Gem::Platform::RUBY,
+ :ruby_31 => Gem::Platform::RUBY,
+ :ruby_32 => Gem::Platform::RUBY,
+ :ruby_33 => Gem::Platform::RUBY,
+ :mri => Gem::Platform::RUBY,
+ :mri_18 => Gem::Platform::RUBY,
+ :mri_19 => Gem::Platform::RUBY,
+ :mri_20 => Gem::Platform::RUBY,
+ :mri_21 => Gem::Platform::RUBY,
+ :mri_22 => Gem::Platform::RUBY,
+ :mri_23 => Gem::Platform::RUBY,
+ :mri_24 => Gem::Platform::RUBY,
+ :mri_25 => Gem::Platform::RUBY,
+ :mri_26 => Gem::Platform::RUBY,
+ :mri_27 => Gem::Platform::RUBY,
+ :mri_30 => Gem::Platform::RUBY,
+ :mri_31 => Gem::Platform::RUBY,
+ :mri_32 => Gem::Platform::RUBY,
+ :mri_33 => Gem::Platform::RUBY,
+ :rbx => Gem::Platform::RUBY,
+ :truffleruby => Gem::Platform::RUBY,
+ :jruby => Gem::Platform::JAVA,
+ :jruby_18 => Gem::Platform::JAVA,
+ :jruby_19 => Gem::Platform::JAVA,
+ :windows => Gem::Platform::WINDOWS,
+ :windows_18 => Gem::Platform::WINDOWS,
+ :windows_19 => Gem::Platform::WINDOWS,
+ :windows_20 => Gem::Platform::WINDOWS,
+ :windows_21 => Gem::Platform::WINDOWS,
+ :windows_22 => Gem::Platform::WINDOWS,
+ :windows_23 => Gem::Platform::WINDOWS,
+ :windows_24 => Gem::Platform::WINDOWS,
+ :windows_25 => Gem::Platform::WINDOWS,
+ :windows_26 => Gem::Platform::WINDOWS,
+ :windows_27 => Gem::Platform::WINDOWS,
+ :windows_30 => Gem::Platform::WINDOWS,
+ :windows_31 => Gem::Platform::WINDOWS,
+ :windows_32 => Gem::Platform::WINDOWS,
+ :windows_33 => Gem::Platform::WINDOWS,
+ :mswin => Gem::Platform::MSWIN,
+ :mswin_18 => Gem::Platform::MSWIN,
+ :mswin_19 => Gem::Platform::MSWIN,
+ :mswin_20 => Gem::Platform::MSWIN,
+ :mswin_21 => Gem::Platform::MSWIN,
+ :mswin_22 => Gem::Platform::MSWIN,
+ :mswin_23 => Gem::Platform::MSWIN,
+ :mswin_24 => Gem::Platform::MSWIN,
+ :mswin_25 => Gem::Platform::MSWIN,
+ :mswin_26 => Gem::Platform::MSWIN,
+ :mswin_27 => Gem::Platform::MSWIN,
+ :mswin_30 => Gem::Platform::MSWIN,
+ :mswin_31 => Gem::Platform::MSWIN,
+ :mswin_32 => Gem::Platform::MSWIN,
+ :mswin_33 => Gem::Platform::MSWIN,
+ :mswin64 => Gem::Platform::MSWIN64,
+ :mswin64_19 => Gem::Platform::MSWIN64,
+ :mswin64_20 => Gem::Platform::MSWIN64,
+ :mswin64_21 => Gem::Platform::MSWIN64,
+ :mswin64_22 => Gem::Platform::MSWIN64,
+ :mswin64_23 => Gem::Platform::MSWIN64,
+ :mswin64_24 => Gem::Platform::MSWIN64,
+ :mswin64_25 => Gem::Platform::MSWIN64,
+ :mswin64_26 => Gem::Platform::MSWIN64,
+ :mswin64_27 => Gem::Platform::MSWIN64,
+ :mswin64_30 => Gem::Platform::MSWIN64,
+ :mswin64_31 => Gem::Platform::MSWIN64,
+ :mswin64_32 => Gem::Platform::MSWIN64,
+ :mswin64_33 => Gem::Platform::MSWIN64,
+ :mingw => Gem::Platform::MINGW,
+ :mingw_18 => Gem::Platform::MINGW,
+ :mingw_19 => Gem::Platform::MINGW,
+ :mingw_20 => Gem::Platform::MINGW,
+ :mingw_21 => Gem::Platform::MINGW,
+ :mingw_22 => Gem::Platform::MINGW,
+ :mingw_23 => Gem::Platform::MINGW,
+ :mingw_24 => Gem::Platform::MINGW,
+ :mingw_25 => Gem::Platform::MINGW,
+ :mingw_26 => Gem::Platform::MINGW,
+ :mingw_27 => Gem::Platform::MINGW,
+ :mingw_30 => Gem::Platform::MINGW,
+ :mingw_31 => Gem::Platform::MINGW,
+ :mingw_32 => Gem::Platform::MINGW,
+ :mingw_33 => Gem::Platform::MINGW,
+ :x64_mingw => Gem::Platform::X64_MINGW,
+ :x64_mingw_20 => Gem::Platform::X64_MINGW,
+ :x64_mingw_21 => Gem::Platform::X64_MINGW,
+ :x64_mingw_22 => Gem::Platform::X64_MINGW,
+ :x64_mingw_23 => Gem::Platform::X64_MINGW,
+ :x64_mingw_24 => Gem::Platform::X64_MINGW,
+ :x64_mingw_25 => Gem::Platform::X64_MINGW,
+ :x64_mingw_26 => Gem::Platform::X64_MINGW,
+ :x64_mingw_27 => Gem::Platform::X64_MINGW,
+ :x64_mingw_30 => Gem::Platform::X64_MINGW,
+ :x64_mingw_31 => Gem::Platform::X64_MINGW,
+ :x64_mingw_32 => Gem::Platform::X64_MINGW,
+ :x64_mingw_33 => Gem::Platform::X64_MINGW }
+ end
+ # rubocop:enable Naming/VariableNumber
+
+ it "includes all platforms" do
+ expect(subject).to eq(platforms)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/digest_spec.rb b/spec/bundler/bundler/digest_spec.rb
new file mode 100644
index 0000000000..841cc0259e
--- /dev/null
+++ b/spec/bundler/bundler/digest_spec.rb
@@ -0,0 +1,24 @@
+# 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
+ random_strings = ["foo", "skfjsdlkfjsdf", "3924m", "ldskfj"]
+
+ # https://datatracker.ietf.org/doc/html/rfc3174#section-7.3
+ rfc3174_test_cases = ["abc", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "a", "01234567" * 8]
+
+ (random_strings + rfc3174_test_cases).each do |payload|
+ sha1 = subject.sha1(payload)
+ sha1_stdlib = stdlib.hexdigest(payload)
+ expect(sha1).to be == sha1_stdlib, "#{payload}'s sha1 digest (#{sha1}) did not match stlib's result (#{sha1_stdlib})"
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb
index e6cd43ab59..8b5bf930f2 100644
--- a/spec/bundler/bundler/dsl_spec.rb
+++ b/spec/bundler/bundler/dsl_spec.rb
@@ -25,6 +25,45 @@ RSpec.describe Bundler::Dsl do
expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption)
end
+ 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.ref).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")
@@ -98,12 +137,20 @@ RSpec.describe Bundler::Dsl do
end
describe "#gem" do
- [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :ruby_26, :mri, :mri_18, :mri_19,
- :mri_20, :mri_21, :mri_22, :mri_23, :mri_24, :mri_25, :mri_26, :jruby, :rbx, :truffleruby].each do |platform|
+ # rubocop:disable Naming/VariableNumber
+ [:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :ruby_26, :ruby_27,
+ :ruby_30, :ruby_31, :ruby_32, :ruby_33, :mri, :mri_18, :mri_19, :mri_20, :mri_21, :mri_22, :mri_23, :mri_24,
+ :mri_25, :mri_26, :mri_27, :mri_30, :mri_31, :mri_32, :mri_33, :jruby, :rbx, :truffleruby].each do |platform|
it "allows #{platform} as a valid platform" do
subject.gem("foo", :platform => platform)
end
end
+ # rubocop:enable Naming/VariableNumber
+
+ it "allows platforms matching the running Ruby version" do
+ platform = "ruby_#{RbConfig::CONFIG["MAJOR"]}#{RbConfig::CONFIG["MINOR"]}"
+ subject.gem("foo", :platform => platform)
+ end
it "rejects invalid platforms" do
expect { subject.gem("foo", :platform => :bogus) }.
@@ -250,7 +297,7 @@ RSpec.describe Bundler::Dsl do
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." \
+ "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)
diff --git a/spec/bundler/bundler/endpoint_specification_spec.rb b/spec/bundler/bundler/endpoint_specification_spec.rb
index a9371f6617..7dd6925007 100644
--- a/spec/bundler/bundler/endpoint_specification_spec.rb
+++ b/spec/bundler/bundler/endpoint_specification_spec.rb
@@ -5,9 +5,10 @@ RSpec.describe Bundler::EndpointSpecification do
let(:version) { "1.0.0" }
let(:platform) { Gem::Platform::RUBY }
let(:dependencies) { [] }
+ let(:spec_fetcher) { double(:spec_fetcher) }
let(:metadata) { nil }
- subject(:spec) { described_class.new(name, version, platform, dependencies, metadata) }
+ subject(:spec) { described_class.new(name, version, platform, spec_fetcher, dependencies, metadata) }
describe "#build_dependency" do
let(:name) { "foo" }
@@ -32,22 +33,6 @@ RSpec.describe Bundler::EndpointSpecification do
)
end
end
-
- context "when there is an ill formed requirement" do
- before do
- allow(Gem::Dependency).to receive(:new).with(name, [requirement1, requirement2]) {
- raise ArgumentError.new("Ill-formed requirement [\"#<YAML::Syck::DefaultKey")
- }
- # Eliminate extra line break in rspec output due to `puts` in `#build_dependency`
- allow(subject).to receive(:puts) {}
- end
-
- it "should raise a Bundler::GemspecError with invalid gemspec message" do
- expect { subject.send(:build_dependency, name, [requirement1, requirement2]) }.to raise_error(
- Bundler::GemspecError, /Unfortunately, the gem foo \(1\.0\.0\) has an invalid gemspec/
- )
- end
- end
end
describe "#parse_metadata" do
@@ -63,8 +48,35 @@ RSpec.describe Bundler::EndpointSpecification do
end
end
+ describe "#required_ruby_version" do
+ context "required_ruby_version is already set on endpoint specification" do
+ existing_value = "already set value"
+ let(:required_ruby_version) { existing_value }
+
+ it "should return the current value when already set on endpoint specification" do
+ expect(spec.required_ruby_version). eql?(existing_value)
+ end
+ end
+
+ it "should return the remote spec value when not set on endpoint specification and remote spec has one" do
+ remote_value = "remote_value"
+ remote_spec = double(:remote_spec, :required_ruby_version => remote_value, :required_rubygems_version => nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+
+ expect(spec.required_ruby_version). eql?(remote_value)
+ end
+
+ it "should use the default Gem Requirement value when not set on endpoint specification and not set on remote spec" do
+ remote_spec = double(:remote_spec, :required_ruby_version => nil, :required_rubygems_version => nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+ expect(spec.required_ruby_version). eql?(Gem::Requirement.default)
+ end
+ end
+
it "supports equality comparison" do
- other_spec = described_class.new("bar", version, platform, dependencies, metadata)
+ remote_spec = double(:remote_spec, :required_ruby_version => nil, :required_rubygems_version => nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+ other_spec = described_class.new("bar", version, platform, spec_fetcher, dependencies, metadata)
expect(spec).to eql(spec)
expect(spec).to_not eql(other_spec)
end
diff --git a/spec/bundler/bundler/env_spec.rb b/spec/bundler/bundler/env_spec.rb
index 5d3aeec226..a00489d0e5 100644
--- a/spec/bundler/bundler/env_spec.rb
+++ b/spec/bundler/bundler/env_spec.rb
@@ -4,7 +4,7 @@ require "bundler/settings"
require "openssl"
RSpec.describe Bundler::Env do
- let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil, nil) }
+ let(:git_proxy_stub) { Bundler::Source::Git::GitProxy.new(nil, nil) }
describe "#report" do
it "prints the environment" do
@@ -34,8 +34,6 @@ 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")
@@ -43,8 +41,6 @@ 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)
@@ -127,6 +123,20 @@ RSpec.describe Bundler::Env do
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)
@@ -207,7 +217,7 @@ RSpec.describe Bundler::Env do
context "when the git version is OS specific" do
it "includes OS specific information with the version number" do
- expect(git_proxy_stub).to receive(:git).with("--version").
+ expect(git_proxy_stub).to receive(:git_local).with("--version").
and_return("git version 1.2.3 (Apple Git-BS)")
expect(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub)
diff --git a/spec/bundler/bundler/fetcher/dependency_spec.rb b/spec/bundler/bundler/fetcher/dependency_spec.rb
index 53249116cd..20307f9c99 100644
--- a/spec/bundler/bundler/fetcher/dependency_spec.rb
+++ b/spec/bundler/bundler/fetcher/dependency_spec.rb
@@ -155,9 +155,9 @@ RSpec.describe Bundler::Fetcher::Dependency do
end
end
- shared_examples_for "the error suggests retrying with the full index" do
- it "should log the inability to fetch from API at debug level" do
- expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API\nit's suggested to retry using the full index via `bundle install --full-index`")
+ shared_examples_for "the error is logged" do
+ it "should log the inability to fetch from API at debug level, and mention retrying" do
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API, trying the full index")
subject.specs(gem_names, full_dependency_list, last_spec_list)
end
end
@@ -166,25 +166,21 @@ RSpec.describe Bundler::Fetcher::Dependency do
before { allow(subject).to receive(:dependency_specs) { raise Bundler::HTTPError.new } }
it_behaves_like "the error is properly handled"
- it_behaves_like "the error suggests retrying with the full index"
+ it_behaves_like "the error is logged"
end
context "when a GemspecError occurs" do
before { allow(subject).to receive(:dependency_specs) { raise Bundler::GemspecError.new } }
it_behaves_like "the error is properly handled"
- it_behaves_like "the error suggests retrying with the full index"
+ it_behaves_like "the error is logged"
end
context "when a MarshalError occurs" do
before { allow(subject).to receive(:dependency_specs) { raise Bundler::MarshalError.new } }
it_behaves_like "the error is properly handled"
-
- it "should log the inability to fetch from API and mention retrying" do
- expect(Bundler).to receive_message_chain(:ui, :debug).with("could not fetch from the dependency API, trying the full index")
- subject.specs(gem_names, full_dependency_list, last_spec_list)
- end
+ it_behaves_like "the error is logged"
end
end
@@ -222,7 +218,7 @@ RSpec.describe Bundler::Fetcher::Dependency do
it "should fetch dependencies from RubyGems and unmarshal them" do
expect(gem_names).to receive(:each_slice).with(rubygems_limit).and_call_original
expect(downloader).to receive(:fetch).with(dep_api_uri).and_return(fetch_response)
- expect(Bundler).to receive(:load_marshal).with(fetch_response.body).and_return([unmarshalled_gems])
+ expect(Bundler).to receive(:safe_load_marshal).with(fetch_response.body).and_return([unmarshalled_gems])
expect(subject.unmarshalled_dep_gems(gem_names)).to eq([unmarshalled_gems])
end
end
diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb
index 4d3dff3a89..22aa3a8b0c 100644
--- a/spec/bundler/bundler/fetcher/downloader_spec.rb
+++ b/spec/bundler/bundler/fetcher/downloader_spec.rb
@@ -98,6 +98,16 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
end
+ context "when the request response is a Net::HTTPForbidden" do
+ let(:http_response) { Net::HTTPForbidden.new("1.1", 403, "Forbidden") }
+ let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") }
+
+ it "should raise a Bundler::Fetcher::AuthenticationForbiddenError with the uri host" do
+ expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError,
+ /Access token could not be authenticated for www.uri-to-fetch.com/)
+ end
+ end
+
context "when the request response is a Net::HTTPNotFound" do
let(:http_response) { Net::HTTPNotFound.new("1.1", 404, "Not Found") }
@@ -178,26 +188,6 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
end
- context "when the request response causes a NoMethodError" do
- before { allow(connection).to receive(:request).with(uri, net_http_get) { raise NoMethodError.new(message) } }
-
- context "and the error message is about use_ssl=" do
- let(:message) { "undefined method 'use_ssl='" }
-
- it "should raise a LoadError about openssl" do
- expect { subject.request(uri, options) }.to raise_error(LoadError, "cannot load such file -- openssl")
- end
- end
-
- context "and the error message is not about use_ssl=" 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'")
- end
- end
- end
-
context "when the request response causes a OpenSSL::SSL::SSLError" do
before { allow(connection).to receive(:request).with(uri, net_http_get) { raise OpenSSL::SSL::SSLError.new } }
diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb
index f0db07583c..971b64ce8f 100644
--- a/spec/bundler/bundler/fetcher/index_spec.rb
+++ b/spec/bundler/bundler/fetcher/index_spec.rb
@@ -63,26 +63,9 @@ RSpec.describe Bundler::Fetcher::Index do
context "when a 403 response occurs" do
let(:error_message) { "403" }
- before do
- allow(remote_uri).to receive(:userinfo).and_return(userinfo)
- end
-
- context "and there was userinfo" do
- let(:userinfo) { double(:userinfo) }
-
- it "should raise a Bundler::Fetcher::BadAuthenticationError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
- %r{Bad username or password for http://remote-uri.org})
- end
- end
-
- context "and there was no userinfo" do
- let(:userinfo) { nil }
-
- it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
- %r{Authentication is required for http://remote-uri.org})
- end
+ it "should raise a Bundler::Fetcher::AuthenticationForbiddenError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError,
+ %r{Access token could not be authenticated for http://remote-uri.org})
end
end
diff --git a/spec/bundler/bundler/fetcher_spec.rb b/spec/bundler/bundler/fetcher_spec.rb
index 256d342775..27a63c476d 100644
--- a/spec/bundler/bundler/fetcher_spec.rb
+++ b/spec/bundler/bundler/fetcher_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe Bundler::Fetcher do
context "when Gem.configuration specifies http_proxy " do
let(:proxy) { "http://proxy-example2.com" }
before do
- allow(Bundler.rubygems.configuration).to receive(:[]).with(:http_proxy).and_return(proxy)
+ allow(Gem.configuration).to receive(:[]).with(:http_proxy).and_return(proxy)
end
it "consider Gem.configuration when determine proxy" do
expect(fetcher.http_proxy).to match("http://proxy-example2.com")
@@ -113,7 +113,7 @@ RSpec.describe Bundler::Fetcher do
context "when gem ssl configuration is set" do
before do
- allow(Bundler.rubygems.configuration).to receive_messages(
+ allow(Gem.configuration).to receive_messages(
:http_proxy => nil,
:ssl_client_cert => "cert",
:ssl_ca_cert => "ca"
@@ -159,4 +159,34 @@ RSpec.describe Bundler::Fetcher do
end
end
end
+
+ describe "#fetch_spec" do
+ let(:name) { "name" }
+ let(:version) { "1.3.17" }
+ let(:platform) { "platform" }
+ let(:downloader) { double("downloader") }
+ let(:body) { double(Net::HTTP::Get, :body => downloaded_data) }
+
+ context "when attempting to load a Gem::Specification" do
+ let(:spec) { Gem::Specification.new(name, version) }
+ let(:downloaded_data) { Zlib::Deflate.deflate(Marshal.dump(spec)) }
+
+ it "returns the spec" do
+ expect(Bundler::Fetcher::Downloader).to receive(:new).and_return(downloader)
+ expect(downloader).to receive(:fetch).once.and_return(body)
+ result = fetcher.fetch_spec([name, version, platform])
+ expect(result).to eq(spec)
+ end
+ end
+
+ context "when attempting to load an unexpected class" do
+ let(:downloaded_data) { Zlib::Deflate.deflate(Marshal.dump(3)) }
+
+ it "raises a HTTPError error" do
+ expect(Bundler::Fetcher::Downloader).to receive(:new).and_return(downloader)
+ expect(downloader).to receive(:fetch).once.and_return(body)
+ expect { fetcher.fetch_spec([name, version, platform]) }.to raise_error(Bundler::HTTPError, /Gemspec .* contained invalid data/i)
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/friendly_errors_spec.rb b/spec/bundler/bundler/friendly_errors_spec.rb
index 496191f891..37afe488f3 100644
--- a/spec/bundler/bundler/friendly_errors_spec.rb
+++ b/spec/bundler/bundler/friendly_errors_spec.rb
@@ -104,26 +104,12 @@ RSpec.describe Bundler, "friendly errors" do
expect(Bundler.ui).to receive(:error).with(error.message, :wrap => true)
Bundler::FriendlyErrors.log_error(error)
end
- it_behaves_like "Bundler.ui receive trace", Bundler::BundlerError.new
end
context "Thor::Error" do
it_behaves_like "Bundler.ui receive error", Bundler::Thor::Error.new
end
- context "LoadError" do
- let(:error) { LoadError.new("cannot load such file -- openssl") }
-
- before do
- allow(error).to receive(:backtrace).and_return(["backtrace"])
- end
-
- 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
-
context "Interrupt" do
it "Bundler.ui receive error" do
expect(Bundler.ui).to receive(:error).with("\nQuitting...")
diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb
index 6c3ac3e035..7d955007ab 100644
--- a/spec/bundler/bundler/gem_helper_spec.rb
+++ b/spec/bundler/bundler/gem_helper_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Bundler::GemHelper do
before(:each) do
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false",
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
+ sys_exec("git config --global init.defaultBranch main")
bundle "gem #{app_name}"
prepare_gemspec(app_gemspec_path)
end
@@ -66,6 +67,10 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message message
end
+ def sha512_hexdigest(path)
+ Digest::SHA512.file(path).hexdigest
+ end
+
subject! { Bundler::GemHelper.new(app_path) }
let(:app_version) { "0.1.0" }
let(:app_gem_dir) { app_path.join("pkg") }
@@ -169,12 +174,21 @@ RSpec.describe Bundler::GemHelper do
end
describe "#build_checksum" do
+ it "calculates SHA512 of the content" do
+ FileUtils.mkdir_p(app_gem_dir)
+ File.write(app_gem_path, "")
+ mock_checksum_message app_name, app_version
+ subject.build_checksum(app_gem_path)
+ expect(File.read(app_sha_path).chomp).to eql(Digest::SHA512.hexdigest(""))
+ end
+
context "when build was successful" do
it "creates .sha512 file" do
mock_build_message app_name, app_version
mock_checksum_message app_name, app_version
subject.build_checksum
expect(app_sha_path).to exist
+ expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path))
end
end
context "when building in the current working directory" do
@@ -185,6 +199,7 @@ RSpec.describe Bundler::GemHelper do
Bundler::GemHelper.new.build_checksum
end
expect(app_sha_path).to exist
+ expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path))
end
end
context "when building in a location relative to the current working directory" do
@@ -195,6 +210,7 @@ RSpec.describe Bundler::GemHelper do
Bundler::GemHelper.new(File.basename(app_path)).build_checksum
end
expect(app_sha_path).to exist
+ expect(File.read(app_sha_path).chomp).to eql(sha512_hexdigest(app_gem_path))
end
end
end
@@ -219,7 +235,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
@@ -280,7 +296,7 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message "Tagged v#{app_version}."
mock_confirm_message "Pushed git commits and release tag."
- sys_exec("git push -u origin master", :dir => app_path)
+ sys_exec("git push -u origin main", :dir => app_path)
end
it "calls rubygem_push with proper arguments" do
@@ -321,7 +337,7 @@ RSpec.describe Bundler::GemHelper do
mock_build_message app_name, app_version
mock_confirm_message "Pushed git commits and release tag."
- sys_exec("git push -u origin master", :dir => app_path)
+ sys_exec("git push -u origin main", :dir => app_path)
expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
end
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index 43a3630bbb..8058412f32 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -1,178 +1,162 @@
# frozen_string_literal: true
RSpec.describe Bundler::GemVersionPromoter do
- context "conservative resolver" do
- def versions(result)
- result.flatten.map(&:version).map(&:to_s)
+ let(:gvp) { described_class.new }
+
+ # Rightmost (highest array index) in result is most preferred.
+ # Leftmost (lowest array index) in result is least preferred.
+ # `build_candidates` has all versions of gem in index.
+ # `build_spec` is the version currently in the .lock file.
+ #
+ # In default (not strict) mode, all versions in the index will
+ # be returned, allowing Bundler the best chance to resolve all
+ # dependencies, but sometimes resulting in upgrades that some
+ # would not consider conservative.
+
+ describe "#sort_versions" do
+ def build_candidates(versions)
+ versions.map do |v|
+ Bundler::Resolver::Candidate.new(v)
+ end
end
- def make_instance(*args)
- @gvp = Bundler::GemVersionPromoter.new(*args).tap do |gvp|
- gvp.class.class_eval { public :filter_dep_specs, :sort_dep_specs }
- end
+ def build_package(name, version, locked = [])
+ Bundler::Resolver::Package.new(name, [], :locked_specs => Bundler::SpecSet.new(build_spec(name, version)), :unlock => locked)
end
- def unlocking(options)
- make_instance(Bundler::SpecSet.new([]), ["foo"]).tap do |p|
- p.level = options[:level] if options[:level]
- p.strict = options[:strict] if options[:strict]
- end
+ def sorted_versions(candidates:, current:, name: "foo", locked: [])
+ gvp.sort_versions(
+ build_package(name, current, locked),
+ build_candidates(candidates)
+ ).flatten.map(&:version).map(&:to_s)
end
- def keep_locked(options)
- make_instance(Bundler::SpecSet.new([]), ["bar"]).tap do |p|
- p.level = options[:level] if options[:level]
- p.strict = options[:strict] if options[:strict]
- end
+ it "numerically sorts versions" do
+ versions = sorted_versions(:candidates => %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0], :current => "1.7.8")
+ expect(versions).to eq %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]
end
- def build_spec_groups(name, versions)
- versions.map do |v|
- Bundler::Resolver::SpecGroup.create_for({ Gem::Platform::RUBY => build_spec(name, v) }, [Gem::Platform::RUBY], Gem::Platform::RUBY)
+ context "with no options" do
+ it "defaults to level=:major, strict=false, pre=false" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0]
end
end
- # Rightmost (highest array index) in result is most preferred.
- # Leftmost (lowest array index) in result is least preferred.
- # `build_spec_groups` has all versions of gem in index.
- # `build_spec` is the version currently in the .lock file.
- #
- # In default (not strict) mode, all versions in the index will
- # be returned, allowing Bundler the best chance to resolve all
- # dependencies, but sometimes resulting in upgrades that some
- # would not consider conservative.
- context "filter specs (strict) level patch" do
- it "when keeping build_spec, keep current, next release" do
- keep_locked(:level => :patch)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.9 1.7.8]
- end
+ context "when strict" do
+ before { gvp.strict = true }
- it "when unlocking prefer next release first" do
- unlocking(:level => :patch)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[1.7.8 1.7.9 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.8 1.7.9]
- end
+ context "when level is major" do
+ before { gvp.level = :major }
- it "when unlocking keep current when already at latest release" do
- unlocking(:level => :patch)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]),
- build_spec("foo", "1.7.9").first
- )
- expect(versions(res)).to eq %w[1.7.9]
+ it "keeps downgrades" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0]
+ end
end
- end
- context "filter specs (strict) level minor" do
- it "when unlocking favor next releases, remove minor and major increases" do
- unlocking(:level => :minor)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]),
- build_spec("foo", "0.2.0").first
- )
- expect(versions(res)).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0]
+ context "when level is minor" do
+ before { gvp.level = :minor }
+
+ it "removes downgrades and major upgrades" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.3.0 0.3.1 0.9.0]
+ end
end
- it "when keep locked, keep current, then favor next release, remove minor and major increases" do
- keep_locked(:level => :minor)
- res = @gvp.filter_dep_specs(
- build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]),
- build_spec("foo", "0.2.0").first
- )
- expect(versions(res)).to eq %w[0.3.0 0.3.1 0.9.0 0.2.0]
+ context "when level is patch" do
+ before { gvp.level = :patch }
+
+ it "removes downgrades and major and minor upgrades" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.3.0 0.3.1]
+ end
end
end
- context "sort specs (not strict) level patch" do
- it "when not unlocking, same order but make sure build_spec version is most preferred to stay put" do
- keep_locked(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.5.4 1.6.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 2.0.0 2.0.1]),
- build_spec("foo", "1.7.7").first
- )
- expect(versions(res)).to eq %w[1.5.4 1.6.5 1.7.6 2.0.0 2.0.1 1.8.0 1.8.1 1.7.8 1.7.9 1.7.7]
- end
+ context "when not strict" do
+ before { gvp.strict = false }
- it "when unlocking favor next release, then current over minor increase" do
- unlocking(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9]
+ context "when level is major" do
+ before { gvp.level = :major }
+
+ it "orders by version" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0]
+ end
end
- it "when unlocking do proper integer comparison, not string" do
- unlocking(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.7.7 1.7.8 1.7.9 1.7.15 1.8.0]),
- build_spec("foo", "1.7.8").first
- )
- expect(versions(res)).to eq %w[1.7.7 1.8.0 1.7.8 1.7.9 1.7.15]
+ context "when level is minor" do
+ before { gvp.level = :minor }
+
+ it "favors downgrades, then upgrades by major descending, minor ascending, patch ascending" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.2.0 2.0.1 2.1.0 1.0.0 0.3.0 0.3.1 0.9.0]
+ end
end
- it "leave current when unlocking but already at latest release" do
- unlocking(:level => :patch)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[1.7.9 1.8.0 2.0.0]),
- build_spec("foo", "1.7.9").first
- )
- expect(versions(res)).to eq %w[2.0.0 1.8.0 1.7.9]
+ context "when level is patch" do
+ before { gvp.level = :patch }
+
+ it "favors downgrades, then upgrades by major descending, minor descending, patch ascending" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.1 2.1.0], :current => "0.3.0")
+ expect(versions).to eq %w[0.2.0 2.1.0 2.0.1 1.0.0 0.9.0 0.3.0 0.3.1]
+ end
end
end
- context "sort specs (not strict) level minor" do
- it "when unlocking favor next release, then minor increase over current" do
- unlocking(:level => :minor)
- res = @gvp.sort_dep_specs(
- build_spec_groups("foo", %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.0.0 2.0.1]),
- build_spec("foo", "0.2.0").first
- )
- expect(versions(res)).to eq %w[2.0.0 2.0.1 1.0.0 0.2.0 0.3.0 0.3.1 0.9.0]
+ context "when pre" do
+ before { gvp.pre = true }
+
+ it "sorts regardless of prerelease status" do
+ versions = sorted_versions(:candidates => %w[1.7.7.pre 1.8.0 1.8.1.pre 1.8.1 2.0.0.pre 2.0.0], :current => "1.8.0")
+ expect(versions).to eq %w[1.7.7.pre 1.8.0 1.8.1.pre 1.8.1 2.0.0.pre 2.0.0]
end
end
- context "level error handling" do
- subject { Bundler::GemVersionPromoter.new }
+ context "when not pre" do
+ before { gvp.pre = false }
- it "should raise if not major, minor or patch is passed" do
- expect { subject.level = :minjor }.to raise_error ArgumentError
+ it "deprioritizes prerelease gems" do
+ versions = sorted_versions(:candidates => %w[1.7.7.pre 1.8.0 1.8.1.pre 1.8.1 2.0.0.pre 2.0.0], :current => "1.8.0")
+ expect(versions).to eq %w[1.7.7.pre 1.8.1.pre 2.0.0.pre 1.8.0 1.8.1 2.0.0]
end
+ end
- it "should raise if invalid classes passed" do
- [123, nil].each do |value|
- expect { subject.level = value }.to raise_error ArgumentError
- end
+ context "when locking and not major" do
+ before { gvp.level = :minor }
+
+ it "keeps the current version last" do
+ versions = sorted_versions(:candidates => %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.1.0 2.0.1], :current => "0.3.0", :locked => ["bar"])
+ expect(versions.last).to eq("0.3.0")
end
+ end
+ end
- it "should accept major, minor patch symbols" do
- [:major, :minor, :patch].each do |value|
- subject.level = value
- expect(subject.level).to eq value
- end
+ describe "#level=" do
+ subject { described_class.new }
+
+ it "should raise if not major, minor or patch is passed" do
+ expect { subject.level = :minjor }.to raise_error ArgumentError
+ end
+
+ it "should raise if invalid classes passed" do
+ [123, nil].each do |value|
+ expect { subject.level = value }.to raise_error ArgumentError
end
+ end
- it "should accept major, minor patch strings" do
- %w[major minor patch].each do |value|
- subject.level = value
- expect(subject.level).to eq value.to_sym
- end
+ it "should accept major, minor patch symbols" do
+ [:major, :minor, :patch].each do |value|
+ subject.level = value
+ expect(subject.level).to eq value
end
end
- context "debug output" do
- it "should not kerblooie on its own debug output" do
- gvp = unlocking(:level => :patch)
- 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
+ it "should accept major, minor patch strings" do
+ %w[major minor patch].each do |value|
+ subject.level = value
+ expect(subject.level).to eq value.to_sym
end
end
end
diff --git a/spec/bundler/bundler/installer/gem_installer_spec.rb b/spec/bundler/bundler/installer/gem_installer_spec.rb
index 8f8d1c6d15..e86bdf009a 100644
--- a/spec/bundler/bundler/installer/gem_installer_spec.rb
+++ b/spec/bundler/bundler/installer/gem_installer_spec.rb
@@ -3,7 +3,8 @@
require "bundler/installer/gem_installer"
RSpec.describe Bundler::GemInstaller do
- let(:installer) { instance_double("Installer") }
+ let(:definition) { instance_double("Definition", :locked_gems => nil) }
+ let(:installer) { instance_double("Installer", :definition => definition) }
let(:spec_source) { instance_double("SpecSource") }
let(:spec) { instance_double("Specification", :name => "dummy", :version => "0.0.1", :loaded_from => "dummy", :source => spec_source) }
@@ -11,7 +12,10 @@ RSpec.describe Bundler::GemInstaller do
context "spec_settings is nil" do
it "invokes install method with empty build_args" do
- allow(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => [])
+ allow(spec_source).to receive(:install).with(
+ spec,
+ { :force => false, :ensure_builtin_gems_cached => false, :build_args => [], :previous_spec => nil }
+ )
subject.install_from_spec
end
end
@@ -22,7 +26,10 @@ RSpec.describe Bundler::GemInstaller do
allow(Bundler.settings).to receive(:[]).with(:inline)
allow(Bundler.settings).to receive(:[]).with(:forget_cli_options)
allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy")
- expect(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy"])
+ expect(spec_source).to receive(:install).with(
+ spec,
+ { :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy"], :previous_spec => nil }
+ )
subject.install_from_spec
end
end
@@ -33,7 +40,10 @@ RSpec.describe Bundler::GemInstaller do
allow(Bundler.settings).to receive(:[]).with(:inline)
allow(Bundler.settings).to receive(:[]).with(:forget_cli_options)
allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy --with-another-dummy-config")
- expect(spec_source).to receive(:install).with(spec, :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy", "--with-another-dummy-config"])
+ expect(spec_source).to receive(:install).with(
+ spec,
+ { :force => false, :ensure_builtin_gems_cached => false, :build_args => ["--with-dummy-config=dummy", "--with-another-dummy-config"], :previous_spec => nil }
+ )
subject.install_from_spec
end
end
diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb
index e680633862..c8403a2e38 100644
--- a/spec/bundler/bundler/installer/parallel_installer_spec.rb
+++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb
@@ -11,40 +11,6 @@ RSpec.describe Bundler::ParallelInstaller do
subject { described_class.new(installer, all_specs, size, standalone, force) }
- context "when dependencies that are not on the overall installation list are the only ones not installed" do
- let(:all_specs) do
- [
- build_spec("alpha", "1.0") {|s| s.runtime "a", "1" },
- ].flatten
- end
-
- it "prints a warning" do
- expect(Bundler.ui).to receive(:warn).with(<<-W.strip)
-Your lockfile was created by an old Bundler that left some things out.
-You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile.
-The missing gems are:
-* a depended upon by alpha
- W
- subject.check_for_corrupt_lockfile
- end
-
- context "when size > 1" do
- let(:size) { 500 }
-
- it "prints a warning and sets size to 1" do
- expect(Bundler.ui).to receive(:warn).with(<<-W.strip)
-Your lockfile was created by an old Bundler that left some things out.
-Because of the missing DEPENDENCIES, we can only install gems one at a time, instead of installing 500 at a time.
-You can fix this by adding the missing gems to your Gemfile, running bundle install, and then removing the gems from your Gemfile.
-The missing gems are:
-* a depended upon by alpha
- W
- subject.check_for_corrupt_lockfile
- expect(subject.size).to eq(1)
- end
- end
- end
-
context "when the spec set is not a valid resolution" do
let(:all_specs) do
[
@@ -56,9 +22,9 @@ The missing gems are:
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.
+You can fix this by regenerating your lockfile or 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
+* diff-lcs (< 1.4), dependency of cucumber-4.1.0, unsatisfied by diff-lcs-1.4.4
W
subject.check_for_unmet_dependencies
end
diff --git a/spec/bundler/bundler/plugin/index_spec.rb b/spec/bundler/bundler/plugin/index_spec.rb
index d34b0de342..5a7047459f 100644
--- a/spec/bundler/bundler/plugin/index_spec.rb
+++ b/spec/bundler/bundler/plugin/index_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe Bundler::Plugin::Index do
describe "after conflict" do
let(:commands) { ["foo"] }
let(:sources) { ["bar"] }
- let(:hooks) { ["hoook"] }
+ let(:hooks) { ["thehook"] }
shared_examples "it cleans up" do
it "the path" do
@@ -156,7 +156,7 @@ RSpec.describe Bundler::Plugin::Index do
end
it "the hook" do
- expect(index.hook_plugins("xhoook")).to be_empty
+ expect(index.hook_plugins("xthehook")).to be_empty
end
end
@@ -164,7 +164,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
expect do
path = lib_path("cplugin")
- index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["xbar"], ["xhoook"])
+ index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["xbar"], ["xthehook"])
end.to raise_error(Index::CommandConflict)
end
@@ -175,7 +175,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
expect do
path = lib_path("cplugin")
- index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["xfoo"], ["bar"], ["xhoook"])
+ index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["xfoo"], ["bar"], ["xthehook"])
end.to raise_error(Index::SourceConflict)
end
@@ -186,7 +186,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
expect do
path = lib_path("cplugin")
- index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["bar"], ["xhoook"])
+ index.register_plugin("cplugin", path.to_s, [path.join("lib").to_s], ["foo"], ["bar"], ["xthehook"])
end.to raise_error(Index::CommandConflict)
end
diff --git a/spec/bundler/bundler/plugin/installer_spec.rb b/spec/bundler/bundler/plugin/installer_spec.rb
index e89720f6f7..2c50ee5afc 100644
--- a/spec/bundler/bundler/plugin/installer_spec.rb
+++ b/spec/bundler/bundler/plugin/installer_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Bundler::Plugin::Installer do
it "uses Gem.sources when non of the source is provided" do
sources = double(:sources)
Bundler.settings # initialize it before we have to touch rubygems.ext_lock
- allow(Bundler).to receive_message_chain("rubygems.sources") { sources }
+ allow(Gem).to receive(:sources) { sources }
allow(installer).to receive(:install_rubygems).
with("new-plugin", [">= 0"], sources).once
diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb
index d1a05bbad7..d28479cf31 100644
--- a/spec/bundler/bundler/plugin_spec.rb
+++ b/spec/bundler/bundler/plugin_spec.rb
@@ -65,6 +65,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
@@ -73,6 +75,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
@@ -80,6 +84,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
@@ -96,6 +102,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
@@ -273,12 +280,12 @@ RSpec.describe Bundler::Plugin do
end
Bundler::Plugin::Events.send(:reset)
- Bundler::Plugin::Events.send(:define, :EVENT_1, "event-1")
- Bundler::Plugin::Events.send(:define, :EVENT_2, "event-2")
+ Bundler::Plugin::Events.send(:define, :EVENT1, "event-1")
+ Bundler::Plugin::Events.send(:define, :EVENT2, "event-2")
- allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_1).
+ allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT1).
and_return(["foo-plugin", "", nil])
- allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_2).
+ allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT2).
and_return(["foo-plugin"])
allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path)
allow(index).to receive(:load_paths).with("foo-plugin").and_return([])
@@ -296,33 +303,33 @@ RSpec.describe Bundler::Plugin do
it "executes the hook" do
expect do
- Plugin.hook(Bundler::Plugin::Events::EVENT_1)
+ Plugin.hook(Bundler::Plugin::Events::EVENT1)
end.to output("hook for event 1\n").to_stdout
end
context "single plugin declaring more than one hook" do
let(:code) { <<-RUBY }
- Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) {}
- Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_2) {}
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT1) {}
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT2) {}
puts "loaded"
RUBY
it "evals plugins.rb once" do
expect do
- Plugin.hook(Bundler::Plugin::Events::EVENT_1)
- Plugin.hook(Bundler::Plugin::Events::EVENT_2)
+ Plugin.hook(Bundler::Plugin::Events::EVENT1)
+ Plugin.hook(Bundler::Plugin::Events::EVENT2)
end.to output("loaded\n").to_stdout
end
end
context "a block is passed" do
let(:code) { <<-RUBY }
- Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) { |&blk| blk.call }
+ Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT1) { |&blk| blk.call }
RUBY
it "is passed to the hook" do
expect do
- Plugin.hook(Bundler::Plugin::Events::EVENT_1) { puts "win" }
+ Plugin.hook(Bundler::Plugin::Events::EVENT1) { puts "win" }
end.to output("win\n").to_stdout
end
end
diff --git a/spec/bundler/bundler/psyched_yaml_spec.rb b/spec/bundler/bundler/psyched_yaml_spec.rb
deleted file mode 100644
index d5d68c5cc3..0000000000
--- a/spec/bundler/bundler/psyched_yaml_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/psyched_yaml"
-
-RSpec.describe "Bundler::YamlLibrarySyntaxError" do
- it "is raised on YAML parse errors" do
- expect { YAML.parse "{foo" }.to raise_error(Bundler::YamlLibrarySyntaxError)
- end
-end
diff --git a/spec/bundler/bundler/remote_specification_spec.rb b/spec/bundler/bundler/remote_specification_spec.rb
index 8115e026d8..921a47a2d3 100644
--- a/spec/bundler/bundler/remote_specification_spec.rb
+++ b/spec/bundler/bundler/remote_specification_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Bundler::RemoteSpecification do
let(:platform) { "jruby" }
it "should return the spec name, version, and platform" do
- expect(subject.full_name).to eq("foo-1.0.0-jruby")
+ expect(subject.full_name).to eq("foo-1.0.0-java")
end
end
end
diff --git a/spec/bundler/bundler/resolver/candidate_spec.rb b/spec/bundler/bundler/resolver/candidate_spec.rb
new file mode 100644
index 0000000000..cd52c867c4
--- /dev/null
+++ b/spec/bundler/bundler/resolver/candidate_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Resolver::Candidate do
+ it "compares fine" do
+ version1 = described_class.new("1.12.5", :specs => [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::RUBY }])
+ version2 = described_class.new("1.12.5") # passing no specs creates a platform specific candidate, so sorts higher
+
+ expect(version2 >= version1).to be true
+
+ expect(version1.generic! == version2.generic!).to be true
+ expect(version1.platform_specific! == version2.platform_specific!).to be true
+
+ expect(version1.platform_specific! >= version2.generic!).to be true
+ expect(version2.platform_specific! >= version1.generic!).to be true
+
+ version1 = described_class.new("1.12.5", :specs => [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::RUBY }])
+ version2 = described_class.new("1.12.5", :specs => [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::X64_LINUX }])
+
+ expect(version2 >= version1).to be true
+ end
+end
diff --git a/spec/bundler/bundler/ruby_dsl_spec.rb b/spec/bundler/bundler/ruby_dsl_spec.rb
index bc1ca98457..0ba55e949f 100644
--- a/spec/bundler/bundler/ruby_dsl_spec.rb
+++ b/spec/bundler/bundler/ruby_dsl_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Bundler::RubyDsl do
let(:dsl) { MockDSL.new }
let(:ruby_version) { "2.0.0" }
+ let(:ruby_version_arg) { ruby_version }
let(:version) { "2.0.0" }
let(:engine) { "jruby" }
let(:engine_version) { "9000" }
@@ -23,7 +24,10 @@ RSpec.describe Bundler::RubyDsl do
let(:invoke) do
proc do
- args = Array(ruby_version) + [options]
+ args = []
+ args << Array(ruby_version_arg) if ruby_version_arg
+ args << options
+
dsl.ruby(*args)
end
end
@@ -91,5 +95,26 @@ RSpec.describe Bundler::RubyDsl do
it_behaves_like "it stores the ruby version"
end
end
+
+ context "with a file option" do
+ let(:options) { { :file => "foo" } }
+ let(:version) { "3.2.2" }
+ let(:ruby_version) { "3.2.2" }
+ let(:ruby_version_arg) { nil }
+ let(:engine_version) { version }
+ let(:patchlevel) { nil }
+ let(:engine) { "ruby" }
+ before { allow(Bundler).to receive(:read_file).with("foo").and_return("#{version}\n") }
+
+ it_behaves_like "it stores the ruby version"
+
+ context "and a version" do
+ let(:ruby_version_arg) { "2.0.0" }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::GemfileError, "Cannot specify version when using the file option")
+ end
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/ruby_version_spec.rb b/spec/bundler/bundler/ruby_version_spec.rb
index 8c6c071d7f..39d0571361 100644
--- a/spec/bundler/bundler/ruby_version_spec.rb
+++ b/spec/bundler/bundler/ruby_version_spec.rb
@@ -400,19 +400,19 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
let(:bundler_system_ruby_version) { subject }
around do |example|
- if Bundler::RubyVersion.instance_variable_defined?("@ruby_version")
+ if Bundler::RubyVersion.instance_variable_defined?("@system")
begin
- old_ruby_version = Bundler::RubyVersion.instance_variable_get("@ruby_version")
- Bundler::RubyVersion.remove_instance_variable("@ruby_version")
+ old_ruby_version = Bundler::RubyVersion.instance_variable_get("@system")
+ Bundler::RubyVersion.remove_instance_variable("@system")
example.run
ensure
- Bundler::RubyVersion.instance_variable_set("@ruby_version", old_ruby_version)
+ Bundler::RubyVersion.instance_variable_set("@system", old_ruby_version)
end
else
begin
example.run
ensure
- Bundler::RubyVersion.remove_instance_variable("@ruby_version")
+ Bundler::RubyVersion.remove_instance_variable("@system")
end
end
end
@@ -427,9 +427,8 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
end
describe "#version" do
- it "should return a copy of the value of RUBY_VERSION" do
- expect(subject.versions).to eq([RUBY_VERSION])
- expect(subject.versions.first).to_not be(RUBY_VERSION)
+ it "should return the value of Gem.ruby_version as a string" do
+ expect(subject.versions).to eq([Gem.ruby_version.to_s])
end
end
@@ -446,13 +445,12 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
describe "#engine_version" do
context "engine is ruby" do
before do
- stub_const("RUBY_ENGINE_VERSION", "2.2.4")
+ allow(Gem).to receive(:ruby_version).and_return(Gem::Version.new("2.2.4"))
stub_const("RUBY_ENGINE", "ruby")
end
- it "should return a copy of the value of RUBY_ENGINE_VERSION" do
+ it "should return the value of Gem.ruby_version as a string" do
expect(bundler_system_ruby_version.engine_versions).to eq(["2.2.4"])
- expect(bundler_system_ruby_version.engine_versions.first).to_not be(RUBY_ENGINE_VERSION)
end
end
@@ -498,31 +496,5 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
end
end
end
-
- describe "#to_gem_version_with_patchlevel" do
- shared_examples_for "the patchlevel is omitted" do
- it "does not include a patch level" do
- expect(subject.to_gem_version_with_patchlevel.to_s).to eq(version)
- end
- end
-
- context "with nil patch number" do
- let(:patchlevel) { nil }
-
- it_behaves_like "the patchlevel is omitted"
- end
-
- context "with negative patch number" do
- let(:patchlevel) { -1 }
-
- it_behaves_like "the patchlevel is omitted"
- end
-
- context "with a valid patch number" do
- it "uses the specified patchlevel as patchlevel" do
- expect(subject.to_gem_version_with_patchlevel.to_s).to eq("#{version}.#{patchlevel}")
- end
- end
- end
end
end
diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb
index 11fa2f4e0d..182aa3646a 100644
--- a/spec/bundler/bundler/rubygems_integration_spec.rb
+++ b/spec/bundler/bundler/rubygems_integration_spec.rb
@@ -34,21 +34,12 @@ RSpec.describe Bundler::RubygemsIntegration do
end
end
- describe "#configuration" do
- it "handles Gem::SystemExitException errors" do
- allow(Gem).to receive(:configuration) { raise Gem::SystemExitException.new(1) }
- expect { Bundler.rubygems.configuration }.to raise_error(Gem::SystemExitException)
- end
- end
-
describe "#download_gem" do
let(:bundler_retry) { double(Bundler::Retry) }
- let(:retry) { double("Bundler::Retry") }
- let(:uri) { Bundler::URI.parse("https://foo.bar") }
- let(:path) { Gem.path.first }
+ let(:uri) { Bundler::URI.parse("https://foo.bar") }
+ let(:cache_dir) { "#{Gem.path.first}/cache" }
let(:spec) do
- spec = Bundler::RemoteSpecification.new("Foo", Gem::Version.new("2.5.2"),
- Gem::Platform::RUBY, nil)
+ spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2"))
spec.remote = Bundler::Source::Rubygems::Remote.new(uri.to_s)
spec
end
@@ -56,13 +47,13 @@ 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 +69,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)
@@ -98,5 +89,16 @@ RSpec.describe Bundler::RubygemsIntegration do
expect(result).to eq(%w[specs prerelease_specs])
end
end
+
+ context "when loading an unexpected class" do
+ let(:remote_no_mirror) { double("remote", :uri => uri, :original_uri => nil) }
+ let(:unexpected_specs_response) { Marshal.dump(3) }
+
+ it "raises a MarshalError error" do
+ expect(Bundler.rubygems).to receive(:gem_remote_fetcher).once.and_return(fetcher)
+ expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(unexpected_specs_response)
+ expect { Bundler.rubygems.fetch_all_remote_specs(remote_no_mirror) }.to raise_error(Bundler::MarshalError, /unexpected class/i)
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index 24e3de7ba8..4636993d9f 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Bundler::Settings do
"gem.mit" => "false",
"gem.test" => "minitest",
"thingy" => <<-EOS.tr("\n", " "),
---asdf --fdsa --ty=oh man i hope this doesnt break bundler because
+--asdf --fdsa --ty=oh man i hope this doesn't break bundler because
that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
--very-important-option=DontDeleteRoo
--very-important-option=DontDeleteRoo
diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb
index 68a24be31c..3c6536c4eb 100644
--- a/spec/bundler/bundler/shared_helpers_spec.rb
+++ b/spec/bundler/bundler/shared_helpers_spec.rb
@@ -246,6 +246,15 @@ RSpec.describe Bundler::SharedHelpers do
end
end
+ shared_examples_for "ENV['BUNDLER_SETUP'] gets set correctly" do
+ it "ensures bundler/setup is set in ENV['BUNDLER_SETUP']" do
+ skip "Does not play well with DidYouMean being a bundled gem instead of a default gem in Ruby 2.6" if RUBY_VERSION < "2.7"
+
+ subject.set_bundle_environment
+ expect(ENV["BUNDLER_SETUP"]).to eq("#{source_lib_dir}/bundler/setup")
+ end
+ end
+
shared_examples_for "ENV['RUBYLIB'] gets set correctly" do
let(:ruby_lib_path) { "stubbed_ruby_lib_dir" }
@@ -281,7 +290,7 @@ RSpec.describe Bundler::SharedHelpers do
if Gem.respond_to?(:path_separator)
allow(Gem).to receive(:path_separator).and_return(":")
else
- stub_const("File::PATH_SEPARATOR", ":".freeze)
+ stub_const("File::PATH_SEPARATOR", ":")
end
allow(Bundler).to receive(:bundle_path) { Pathname.new("so:me/dir/bin") }
expect { subject.send(:validate_bundle_path) }.to raise_error(
diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb
index 97f06973cb..c79dd8ff71 100644
--- a/spec/bundler/bundler/source/git/git_proxy_spec.rb
+++ b/spec/bundler/bundler/source/git/git_proxy_spec.rb
@@ -6,26 +6,31 @@ RSpec.describe Bundler::Source::Git::GitProxy do
let(:ref) { "HEAD" }
let(:revision) { nil }
let(:git_source) { nil }
+ let(:clone_result) { double(Process::Status, :success? => true) }
+ let(:base_clone_args) { ["clone", "--bare", "--no-hardlinks", "--quiet", "--no-tags", "--depth", "1", "--single-branch"] }
subject { described_class.new(path, uri, ref, revision, git_source) }
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("clone", "https://u:p@github.com/rubygems/rubygems.git", any_args)
+ allow(subject).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(subject).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
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("clone", "https://u:p@github.com/rubygems/rubygems.git", any_args)
+ allow(subject).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(subject).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
subject.checkout
end
end
it "does not add username and password to mismatched URI" do
Bundler.settings.temporary("https://u:p@github.com/rubygems/rubygems-mismatch.git" => "u:p") do
- expect(subject).to receive(:git_retry).with("clone", uri, any_args)
+ allow(subject).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(subject).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result])
subject.checkout
end
end
@@ -34,7 +39,8 @@ RSpec.describe Bundler::Source::Git::GitProxy do
Bundler.settings.temporary("github.com" => "u:p") do
original = "https://orig:info@github.com/rubygems/rubygems.git"
subject = described_class.new(Pathname("path"), original, "HEAD")
- expect(subject).to receive(:git_retry).with("clone", original, any_args)
+ allow(subject).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(subject).to receive(:capture).with([*base_clone_args, "--", original, path.to_s], nil).and_return(["", "", clone_result])
subject.checkout
end
end
@@ -43,7 +49,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
describe "#version" do
context "with a normal version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(subject).to receive(:git_local).with("--version").
and_return("git version 1.2.3")
end
@@ -58,7 +64,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
context "with a OSX version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(subject).to receive(:git_local).with("--version").
and_return("git version 1.2.3 (Apple Git-BS)")
end
@@ -73,7 +79,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
context "with a msysgit version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(subject).to receive(:git_local).with("--version").
and_return("git version 1.2.3.msysgit.0")
end
@@ -90,7 +96,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
describe "#full_version" do
context "with a normal version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(subject).to receive(:git_local).with("--version").
and_return("git version 1.2.3")
end
@@ -101,7 +107,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
context "with a OSX version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(subject).to receive(:git_local).with("--version").
and_return("git version 1.2.3 (Apple Git-BS)")
end
@@ -112,7 +118,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
context "with a msysgit version number" do
before do
- expect(subject).to receive(:git).with("--version").
+ expect(subject).to receive(:git_local).with("--version").
and_return("git version 1.2.3.msysgit.0")
end
@@ -122,30 +128,23 @@ RSpec.describe Bundler::Source::Git::GitProxy do
end
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_for_display) { "git #{command.shelljoin}" }
-
- it "fails gracefully when resetting to the revision fails" do
- 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 `#{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
+ 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 6668b6e69a..ed6dc3cd29 100644
--- a/spec/bundler/bundler/source/git_spec.rb
+++ b/spec/bundler/bundler/source/git_spec.rb
@@ -24,5 +24,50 @@ RSpec.describe Bundler::Source::Git do
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
end
diff --git a/spec/bundler/bundler/source_spec.rb b/spec/bundler/bundler/source_spec.rb
index af370bb45c..ceb369ecdb 100644
--- a/spec/bundler/bundler/source_spec.rb
+++ b/spec/bundler/bundler/source_spec.rb
@@ -30,17 +30,7 @@ RSpec.describe Bundler::Source do
end
context "when there are locked gems" do
- let(:locked_gems) { double(:locked_gems) }
-
- before { allow(Bundler).to receive(:locked_gems).and_return(locked_gems) }
-
context "that contain the relevant gem spec" do
- before do
- specs = double(:specs)
- allow(locked_gems).to receive(:specs).and_return(specs)
- allow(specs).to receive(:find).and_return(locked_gem)
- end
-
context "without a version" do
let(:locked_gem) { double(:locked_gem, :name => "nokogiri", :version => nil) }
@@ -62,7 +52,7 @@ RSpec.describe Bundler::Source do
end
it "should return a string with the spec name and version and locked spec version" do
- expect(subject.version_message(spec)).to eq("nokogiri >= 1.6\e[32m (was < 1.5)\e[0m")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri >= 1.6\e[32m (was < 1.5)\e[0m")
end
end
@@ -74,7 +64,7 @@ RSpec.describe Bundler::Source do
end
it "should return a string with the spec name and version and locked spec version" do
- expect(subject.version_message(spec)).to eq("nokogiri >= 1.6 (was < 1.5)")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri >= 1.6 (was < 1.5)")
end
end
end
@@ -89,7 +79,7 @@ RSpec.describe Bundler::Source do
end
it "should return a string with the locked spec version in yellow" do
- expect(subject.version_message(spec)).to eq("nokogiri 1.6.1\e[33m (was 1.7.0)\e[0m")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.6.1\e[33m (was 1.7.0)\e[0m")
end
end
@@ -101,7 +91,7 @@ RSpec.describe Bundler::Source do
end
it "should return a string with the locked spec version in yellow" do
- expect(subject.version_message(spec)).to eq("nokogiri 1.6.1 (was 1.7.0)")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.6.1 (was 1.7.0)")
end
end
end
@@ -116,7 +106,7 @@ RSpec.describe Bundler::Source do
end
it "should return a string with the locked spec version in green" do
- expect(subject.version_message(spec)).to eq("nokogiri 1.7.1\e[32m (was 1.7.0)\e[0m")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.7.1\e[32m (was 1.7.0)\e[0m")
end
end
@@ -128,27 +118,11 @@ RSpec.describe Bundler::Source do
end
it "should return a string with the locked spec version in yellow" do
- expect(subject.version_message(spec)).to eq("nokogiri 1.7.1 (was 1.7.0)")
+ expect(subject.version_message(spec, locked_gem)).to eq("nokogiri 1.7.1 (was 1.7.0)")
end
end
end
end
-
- context "that do not contain the relevant gem spec" do
- before do
- specs = double(:specs)
- allow(locked_gems).to receive(:specs).and_return(specs)
- allow(specs).to receive(:find).and_return(nil)
- end
-
- it_behaves_like "the lockfile specs are not relevant"
- end
- end
-
- context "when there are no locked gems" do
- before { allow(Bundler).to receive(:locked_gems).and_return(nil) }
-
- it_behaves_like "the lockfile specs are not relevant"
end
end
diff --git a/spec/bundler/bundler/vendored_persistent_spec.rb b/spec/bundler/bundler/vendored_persistent_spec.rb
deleted file mode 100644
index 3ed899dbcf..0000000000
--- a/spec/bundler/bundler/vendored_persistent_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/vendored_persistent"
-
-RSpec.describe Bundler::PersistentHTTP do
- describe "#warn_old_tls_version_rubygems_connection" do
- let(:uri) { "https://index.rubygems.org" }
- let(:connection) { instance_double(Bundler::Persistent::Net::HTTP::Persistent::Connection) }
- let(:tls_version) { "TLSv1.2" }
- let(:socket) { double("Socket") }
- let(:socket_io) { double("SocketIO") }
-
- before do
- allow(connection).to receive_message_chain(:http, :use_ssl?).and_return(!tls_version.nil?)
- allow(socket).to receive(:io).and_return(socket_io) if socket
- connection.instance_variable_set(:@socket, socket)
-
- if tls_version
- allow(socket_io).to receive(:ssl_version).and_return(tls_version)
- end
- end
-
- shared_examples_for "does not warn" do
- it "does not warn" do
- allow(Bundler.ui).to receive(:warn).never
- subject.warn_old_tls_version_rubygems_connection(Bundler::URI(uri), connection)
- end
- end
-
- shared_examples_for "does warn" do |*expected|
- it "warns" do
- expect(Bundler.ui).to receive(:warn).with(*expected)
- subject.warn_old_tls_version_rubygems_connection(Bundler::URI(uri), connection)
- end
- end
-
- context "an HTTPS uri with TLSv1.2" do
- include_examples "does not warn"
- end
-
- context "without SSL" do
- let(:tls_version) { nil }
-
- include_examples "does not warn"
- end
-
- context "without a socket" do
- let(:socket) { nil }
-
- include_examples "does not warn"
- end
-
- context "with a different TLD" do
- let(:uri) { "https://foo.bar" }
- include_examples "does not warn"
-
- context "and an outdated TLS version" do
- let(:tls_version) { "TLSv1" }
- include_examples "does not warn"
- end
- end
-
- context "with a nonsense TLS version" do
- let(:tls_version) { "BlahBlah2.0Blah" }
- include_examples "does not warn"
- end
-
- context "with an outdated TLS version" do
- let(:tls_version) { "TLSv1" }
- include_examples "does warn",
- "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \
- "Starting in January 2018, RubyGems.org will refuse connection requests from these very old versions of OpenSSL. " \
- "If you will need to continue installing gems after January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.",
- :wrap => true
- end
- end
-end
diff --git a/spec/bundler/bundler/version_ranges_spec.rb b/spec/bundler/bundler/version_ranges_spec.rb
deleted file mode 100644
index bca044b0c0..0000000000
--- a/spec/bundler/bundler/version_ranges_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require "bundler/version_ranges"
-
-RSpec.describe Bundler::VersionRanges do
- describe ".empty?" do
- shared_examples_for "empty?" do |exp, *req|
- it "returns #{exp} for #{req}" do
- r = Gem::Requirement.new(*req)
- ranges = described_class.for(r)
- expect(described_class.empty?(*ranges)).to eq(exp), "expected `#{r}` #{exp ? "" : "not "}to be empty"
- end
- end
-
- include_examples "empty?", false
- include_examples "empty?", false, "!= 1"
- include_examples "empty?", false, "!= 1", "= 2"
- include_examples "empty?", false, "!= 1", "> 1"
- include_examples "empty?", false, "!= 1", ">= 1"
- include_examples "empty?", false, "= 1", ">= 0.1", "<= 1.1"
- include_examples "empty?", false, "= 1", ">= 1", "<= 1"
- include_examples "empty?", false, "= 1", "~> 1"
- include_examples "empty?", false, ">= 0.z", "= 0"
- include_examples "empty?", false, ">= 0"
- include_examples "empty?", false, ">= 1.0.0", "< 2.0.0"
- include_examples "empty?", false, "~> 1"
- include_examples "empty?", false, "~> 2.0", "~> 2.1"
- include_examples "empty?", true, ">= 4.1.0", "< 5.0", "= 5.2.1"
- include_examples "empty?", true, "< 5.0", "< 5.3", "< 6.0", "< 6", "= 5.2.0", "> 2", ">= 3.0", ">= 3.1", ">= 3.2", ">= 4.0.0", ">= 4.1.0", ">= 4.2.0", ">= 4.2", ">= 4"
- include_examples "empty?", true, "!= 1", "< 2", "> 2"
- include_examples "empty?", true, "!= 1", "<= 1", ">= 1"
- include_examples "empty?", true, "< 2", "> 2"
- include_examples "empty?", true, "< 2", "> 2", "= 2"
- include_examples "empty?", true, "= 1", "!= 1"
- include_examples "empty?", true, "= 1", "= 2"
- include_examples "empty?", true, "= 1", "~> 2"
- include_examples "empty?", true, ">= 0", "<= 0.a"
- include_examples "empty?", true, "~> 2.0", "~> 3"
- end
-end
diff --git a/spec/bundler/cache/gems_spec.rb b/spec/bundler/cache/gems_spec.rb
index 72e372fb41..63c00eba01 100644
--- a/spec/bundler/cache/gems_spec.rb
+++ b/spec/bundler/cache/gems_spec.rb
@@ -89,35 +89,45 @@ RSpec.describe "bundle cache" do
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"
- end
-
- build_gem "builtin_gem", "1.0.2", :to_system => true do |s|
- s.summary = "This builtin_gem is bundled with Ruby"
+ build_gem "json", default_json_version
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 %(source "#{file_uri_for(gem_repo1)}"; gem 'builtin_gem', '1.0.2')
- expect(the_bundle).to include_gems("builtin_gem 1.0.2")
+ 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 "caches builtin gems when cache_all_platforms is set" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "json"
+ G
+
+ bundle "config set cache_all_platforms true"
+
+ bundle :cache
+ expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
end
it "doesn't make remote request after caching the gem" do
@@ -139,12 +149,12 @@ RSpec.describe "bundle cache" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem 'builtin_gem', '1.0.2'
+ gem 'json', '#{default_json_version}'
G
bundle :cache, :raise_on_error => false
expect(exitstatus).to_not eq(0)
- expect(err).to include("builtin_gem-1.0.2 is built in to Ruby, and can't be cached")
+ expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
end
end
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index b88993e9b1..890ba88605 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -15,7 +15,7 @@ end
RSpec.describe "bundle cache with git" do
it "copies repository to vendor cache and uses it" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -34,7 +34,7 @@ RSpec.describe "bundle cache with git" 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)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -72,7 +72,7 @@ RSpec.describe "bundle cache with git" do
it "tracks updates" do
git = build_git "foo"
- old_ref = git.ref_for("master", 11)
+ old_ref = git.ref_for("main", 11)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -86,11 +86,10 @@ RSpec.describe "bundle cache with git" do
s.write "lib/foo.rb", "puts :CACHE"
end
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
expect(ref).not_to eq(old_ref)
bundle "update", :all => true
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
@@ -103,7 +102,7 @@ RSpec.describe "bundle cache with git" do
it "tracks updates when specifying the gem" do
git = build_git "foo"
- old_ref = git.ref_for("master", 11)
+ old_ref = git.ref_for("main", 11)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -117,7 +116,7 @@ RSpec.describe "bundle cache with git" do
s.write "lib/foo.rb", "puts :CACHE"
end
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
expect(ref).not_to eq(old_ref)
bundle "update foo"
@@ -132,11 +131,11 @@ RSpec.describe "bundle cache with git" do
it "uses the local repository to generate the cache" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :master
+ gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :main
G
bundle %(config set local.foo #{lib_path("foo-1.0")})
@@ -156,6 +155,9 @@ 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|
@@ -172,7 +174,7 @@ RSpec.describe "bundle cache with git" do
end
G
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
bundle "config set cache_all true"
bundle :cache
@@ -196,7 +198,7 @@ RSpec.describe "bundle cache with git" do
bundle "config set cache_all true"
bundle :cache
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
gemspec = bundled_app("vendor/cache/foo-1.0-#{ref}/foo.gemspec").read
expect(gemspec).to_not match("`echo bob`")
end
@@ -218,4 +220,57 @@ RSpec.describe "bundle cache with git" do
expect(the_bundle).to include_gem "foo 1.0"
end
end
+
+ it "respects the --no-install flag" do
+ git = build_git "foo", &:add_c_extension
+ ref = git.ref_for("main", 11)
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle "config set cache_all true"
+
+ # The algorithm for the cache location for a git checkout is
+ # in Bundle::Source::Git#cache_path
+ cache_path_name = "foo-1.0-#{Digest(:SHA1).hexdigest(lib_path("foo-1.0").to_s)}"
+
+ # Run this test twice. This is because materially different codepaths
+ # will get hit the second time around.
+ # The first time, Bundler::Sources::Git#install_path is set to the system
+ # wide cache directory bundler/gems; the second time, it's set to the
+ # vendor/cache directory. We don't want the native extension to appear in
+ # either of these places, so run the `bundle cache` command twice.
+ 2.times do
+ bundle :cache, "all-platforms" => true, :install => false
+
+ # it did _NOT_ actually install the gem - neither in $GEM_HOME (bundler 2 mode),
+ # nor in .bundle (bundler 3 mode)
+ expect(Pathname.new(File.join(default_bundle_path, "gems/foo-1.0-#{ref}"))).to_not exist
+ # it _did_ cache the gem in vendor/
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
+ # it did _NOT_ build the gems extensions in the vendor/ dir
+ expect(Dir[bundled_app("vendor/cache/foo-1.0-#{ref}/lib/foo_c*")]).to be_empty
+ # it _did_ cache the git checkout
+ expect(default_cache_path("git", cache_path_name)).to exist
+ # And the checkout is a bare checkout
+ expect(default_cache_path("git", cache_path_name, "HEAD")).to exist
+ end
+
+ # Subsequently installing the gem should compile it.
+ # _currently_, the gem gets compiled in vendor/cache, and vendor/cache is added
+ # to the $LOAD_PATH for git extensions, so it all kind of "works". However, in the
+ # future we would like to stop adding vendor/cache to the $LOAD_PATH for git extensions
+ # and instead treat them identically to normal gems (where the gem install location,
+ # not the cache location, is added to $LOAD_PATH).
+ # Verify that the compilation worked and the result is in $LOAD_PATH by simply attempting
+ # to require it; that should make sure this spec does not break if the load path behaviour
+ # is changed.
+ bundle :install, :local => true
+ ruby <<~R, :raise_on_error => false
+ require 'bundler/setup'
+ require 'foo_c'
+ R
+ expect(last_command).to_not be_failure
+ end
end
diff --git a/spec/bundler/commands/add_spec.rb b/spec/bundler/commands/add_spec.rb
index 4c533652ca..5a5b534e8d 100644
--- a/spec/bundler/commands/add_spec.rb
+++ b/spec/bundler/commands/add_spec.rb
@@ -68,6 +68,18 @@ RSpec.describe "bundle add" do
end
end
+ describe "with --require" do
+ it "adds the require param for the gem" do
+ bundle "add 'foo' --require=foo/engine"
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo",(?: .*,) :require => "foo\/engine"})
+ end
+
+ it "converts false to a boolean" do
+ bundle "add 'foo' --require=false"
+ expect(bundled_app_gemfile.read).to match(/gem "foo",(?: .*,) :require => false/)
+ end
+ end
+
describe "with --group" do
it "adds dependency for the specified group" do
bundle "add 'foo' --group='development'"
@@ -91,8 +103,17 @@ RSpec.describe "bundle add" do
end
end
+ describe "with --path" do
+ it "adds dependency with specified path" do
+ bundle "add 'foo' --path='#{lib_path("foo-2.0")}'"
+
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :path => "#{lib_path("foo-2.0")}"/)
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
describe "with --git" do
- it "adds dependency with specified github source" do
+ it "adds dependency with specified git source" do
bundle "add foo --git=#{lib_path("foo-2.0")}"
expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}"/)
@@ -105,7 +126,7 @@ RSpec.describe "bundle add" do
update_git "foo", "2.0", :branch => "test"
end
- it "adds dependency with specified github source and branch" do
+ it "adds dependency with specified git source and branch" do
bundle "add foo --git=#{lib_path("foo-2.0")} --branch=test"
expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}", :branch => "test"/)
@@ -113,6 +134,39 @@ RSpec.describe "bundle add" do
end
end
+ describe "with --git and --ref" do
+ it "adds dependency with specified git source and branch" do
+ bundle "add foo --git=#{lib_path("foo-2.0")} --ref=#{revision_for(lib_path("foo-2.0"))}"
+
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2\.0", :git => "#{lib_path("foo-2.0")}", :ref => "#{revision_for(lib_path("foo-2.0"))}"/)
+ expect(the_bundle).to include_gems "foo 2.0"
+ end
+ end
+
+ describe "with --github" do
+ it "adds dependency with specified github source", :realworld do
+ bundle "add rake --github=ruby/rake"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.0", :github => "ruby\/rake"})
+ end
+ end
+
+ describe "with --github and --branch" do
+ it "adds dependency with specified github source and branch", :realworld do
+ bundle "add rake --github=ruby/rake --branch=master"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.0", :github => "ruby\/rake", :branch => "master"})
+ end
+ end
+
+ describe "with --github and --ref" do
+ it "adds dependency with specified github source and ref", :realworld do
+ bundle "add rake --github=ruby/rake --ref=5c60da8"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.0", :github => "ruby\/rake", :ref => "5c60da8"})
+ end
+ end
+
describe "with --skip-install" do
it "adds gem to Gemfile but is not installed" do
bundle "add foo --skip-install --version=2.0"
diff --git a/spec/bundler/commands/binstubs_spec.rb b/spec/bundler/commands/binstubs_spec.rb
index fb5da98bf3..bfbef58181 100644
--- a/spec/bundler/commands/binstubs_spec.rb
+++ b/spec/bundler/commands/binstubs_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe "bundle binstubs <gem>" do
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
@@ -166,6 +166,21 @@ RSpec.describe "bundle binstubs <gem>" do
end
end
+ context "and the version is newer when given `gems.rb` and `gems.locked`" do
+ before do
+ gemfile bundled_app("gems.rb"), gemfile
+ lockfile bundled_app("gems.locked"), lockfile.gsub(system_bundler_version, "999.999")
+ end
+
+ it "runs the correct version of bundler" do
+ sys_exec "bin/bundle install", :env => { "BUNDLE_GEMFILE" => "gems.rb" }, :raise_on_error => false
+
+ expect(exitstatus).to eq(42)
+ expect(err).to include("Activating bundler (~> 999.999) failed:").
+ and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`")
+ end
+ end
+
context "and the version is older and a different major" do
let(:system_bundler_version) { "55" }
@@ -181,17 +196,43 @@ RSpec.describe "bundle binstubs <gem>" do
end
end
+ context "and the version is older and a different major when given `gems.rb` and `gems.locked`" do
+ let(:system_bundler_version) { "55" }
+
+ before do
+ gemfile bundled_app("gems.rb"), gemfile
+ lockfile bundled_app("gems.locked"), lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 44.0")
+ end
+
+ it "runs the correct version of bundler" do
+ sys_exec "bin/bundle install", :env => { "BUNDLE_GEMFILE" => "gems.rb" }, :raise_on_error => false
+ expect(exitstatus).to eq(42)
+ expect(err).to include("Activating bundler (~> 44.0) failed:").
+ and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 44.0'`")
+ end
+ end
+
context "and the version is older and the same major" do
- let(:system_bundler_version) { "55.1" }
+ let(:system_bundler_version) { "2.999.999" }
before do
- lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 55.0")
+ lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 2.3.0")
end
- it "runs the available version of bundler when the version is older and the same major" do
- sys_exec "bin/bundle install"
+ it "installs and runs the exact version of bundler", :rubygems => ">= 3.3.0.dev", :realworld => true do
+ sys_exec "bin/bundle install --verbose", :artifice => "vcr"
expect(exitstatus).not_to eq(42)
- expect(err).not_to include("Activating bundler (~> 55.0) failed:")
+ expect(out).to include("Bundler 2.999.999 is running, but your lockfile was generated with 2.3.0. Installing Bundler 2.3.0 and restarting using that version.")
+ expect(out).to include("Using bundler 2.3.0")
+ expect(err).not_to include("Activating bundler (~> 2.3.0) failed:")
+ end
+
+ it "runs the available version of bundler", :rubygems => "< 3.3.0.dev" do
+ sys_exec "bin/bundle install --verbose"
+ expect(exitstatus).not_to eq(42)
+ expect(out).not_to include("Bundler 2.999.999 is running, but your lockfile was generated with 2.3.0. Installing Bundler 2.3.0 and restarting using that version.")
+ expect(out).to include("Using bundler 2.999.999")
+ expect(err).not_to include("Activating bundler (~> 2.3.0) failed:")
end
end
@@ -214,9 +255,12 @@ RSpec.describe "bundle binstubs <gem>" do
context "when update --bundler is called" do
before { lockfile.gsub(system_bundler_version, "1.1.1") }
- it "calls through to the latest bundler version" do
+ it "calls through to the latest bundler version", :realworld do
sys_exec "bin/bundle update --bundler", :env => { "DEBUG" => "1" }
- expect(out).to include %(Using bundler #{system_bundler_version}\n)
+ using_bundler_line = /Using bundler ([\w\.]+)\n/.match(out)
+ expect(using_bundler_line).to_not be_nil
+ latest_version = using_bundler_line[1]
+ expect(Gem::Version.new(latest_version)).to be >= Gem::Version.new(system_bundler_version)
end
it "calls through to the explicit bundler version" do
@@ -287,8 +331,6 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "sets correct permissions for binstubs" do
- skip "https://github.com/rubygems/rubygems/issues/3352" if Gem.win_platform?
-
with_umask(0o002) do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -297,7 +339,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
@@ -358,6 +400,7 @@ RSpec.describe "bundle binstubs <gem>" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
+ gem "rails"
G
end
@@ -385,6 +428,26 @@ RSpec.describe "bundle binstubs <gem>" do
expect(bundled_app("bin/rackup.cmd")).to exist
end
end
+
+ context "when the gem is bundler" do
+ it "warns without generating a standalone binstub" do
+ bundle "binstubs bundler --standalone"
+ expect(bundled_app("bin/bundle")).not_to exist
+ expect(bundled_app("bin/bundler")).not_to exist
+ expect(err).to include("Sorry, Bundler can only be run via RubyGems.")
+ end
+ end
+
+ context "when specified --all option" do
+ it "generates standalone binstubs for all gems except bundler" do
+ bundle "binstubs --standalone --all"
+ expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/rails")).to exist
+ expect(bundled_app("bin/bundle")).not_to exist
+ expect(bundled_app("bin/bundler")).not_to exist
+ expect(err).not_to include("Sorry, Bundler can only be run via RubyGems.")
+ end
+ end
end
context "when the bin already exists" do
diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb
index 4f9c1c26c4..a9ed389233 100644
--- a/spec/bundler/commands/cache_spec.rb
+++ b/spec/bundler/commands/cache_spec.rb
@@ -291,7 +291,7 @@ RSpec.describe "bundle cache" do
G
subject
expect(exitstatus).to eq(16)
- expect(err).to include("deployment mode")
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
bundle "env"
@@ -403,14 +403,14 @@ RSpec.describe "bundle install with gem sources" do
simulate_new_machine
- simulate_platform "ruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "platform_specific"
- G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 RUBY")
- end
+ bundle "config set --local force_ruby_platform true"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+ run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
+ expect(out).to eq("1.0.0 RUBY")
end
it "does not update the cache if --no-cache is passed" do
diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb
index c48220f8df..99a858e9e9 100644
--- a/spec/bundler/commands/check_spec.rb
+++ b/spec/bundler/commands/check_spec.rb
@@ -137,6 +137,22 @@ RSpec.describe "bundle check" do
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)
+ end
+
it "ignores missing gems restricted to other platforms" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -156,7 +172,7 @@ RSpec.describe "bundle check" do
rack (1.0.0)
PLATFORMS
- #{local}
+ #{generic_local_platform}
#{not_local}
DEPENDENCIES
@@ -187,7 +203,7 @@ RSpec.describe "bundle check" do
rack (1.0.0)
PLATFORMS
- #{local}
+ #{generic_local_platform}
#{not_local}
DEPENDENCIES
@@ -316,6 +332,42 @@ RSpec.describe "bundle check" do
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
+ #{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
@@ -379,9 +431,72 @@ RSpec.describe "bundle check" do
end
end
+ context "with gemspec directive and scoped sources" do
+ before do
+ build_repo4 do
+ build_gem "awesome_print"
+ end
+
+ build_repo2 do
+ build_gem "dex-dispatch-engine"
+ end
+
+ build_lib("bundle-check-issue", :path => tmp.join("bundle-check-issue")) do |s|
+ s.write "Gemfile", <<-G
+ source "https://localgemserver.test"
+
+ gemspec
+
+ source "https://localgemserver.test/extra" do
+ gem "dex-dispatch-engine"
+ end
+ G
+
+ s.add_dependency "awesome_print"
+ end
+
+ bundle "install", :artifice => "compact_index_extra", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, :dir => tmp.join("bundle-check-issue")
+ end
+
+ it "does not corrupt lockfile when changing version" do
+ version_file = tmp.join("bundle-check-issue/bundle-check-issue.gemspec")
+ File.write(version_file, File.read(version_file).gsub(/s\.version = .+/, "s.version = '9999'"))
+
+ bundle "check --verbose", :dir => tmp.join("bundle-check-issue")
+
+ expect(File.read(tmp.join("bundle-check-issue/Gemfile.lock"))).to eq <<~L
+ PATH
+ remote: .
+ specs:
+ bundle-check-issue (9999)
+ awesome_print
+
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ awesome_print (1.0)
+
+ GEM
+ remote: https://localgemserver.test/extra/
+ specs:
+ dex-dispatch-engine (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ bundle-check-issue!
+ dex-dispatch-engine!
+
+ 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:
@@ -395,7 +510,7 @@ 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
@@ -414,16 +529,16 @@ 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
+ it "does not change the lock and does not warn" do
lockfile lock_with(Bundler::VERSION.succ)
bundle :check
- expect(err).to include("the running version of Bundler (#{Bundler::VERSION}) is older than the version that created the lockfile (#{Bundler::VERSION.succ})")
- lockfile_should_be lock_with(Bundler::VERSION.succ)
+ expect(err).to be_empty
+ expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
end
end
@@ -432,7 +547,7 @@ RSpec.describe "bundle check" do
system_gems "bundler-1.18.0"
lockfile lock_with("1.18.0")
bundle :check
- lockfile_should_be lock_with("1.18.0")
+ 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 4c04853bd3..471cd6c354 100644
--- a/spec/bundler/commands/clean_spec.rb
+++ b/spec/bundler/commands/clean_spec.rb
@@ -208,7 +208,7 @@ RSpec.describe "bundle clean" do
G
FileUtils.mkdir_p(bundled_app("real-path"))
- FileUtils.ln_sf(bundled_app("real-path"), bundled_app("symlink-path"))
+ File.symlink(bundled_app("real-path"), bundled_app("symlink-path"))
bundle "config set path #{bundled_app("symlink-path")}"
bundle "install"
@@ -236,7 +236,7 @@ RSpec.describe "bundle clean" do
bundle "config set path vendor/bundle"
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
@@ -625,22 +625,20 @@ RSpec.describe "bundle clean" do
expect(out).to eq("1.0")
end
- it "when using --force, it doesn't remove default gem binaries" do
- skip "does not work on ruby 3.0 because it changes the path to look for default gems, tsort is a default gem there, and we can't install it either like we do with fiddle because it doesn't yet exist" unless RUBY_VERSION < "3.0.0"
+ it "when using --force, it doesn't remove default gem binaries", :realworld 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?
- build_repo2 do
- # simulate executable for default gem
- build_gem "irb", default_irb_version, :to_system => true, :default => true do |s|
- s.executables = "irb"
- end
+ # 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.0"
+ realworld_system_gems "tsort --version 0.1.0", "pathname --version 0.1.0", "set --version 1.0.1"
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -789,7 +787,7 @@ RSpec.describe "bundle clean" do
should_not_have_gems "foo-1.0"
end
- it "doesn't remove extensions artifacts from bundled git gems after clean", :ruby_repo do
+ it "doesn't remove extensions artifacts from bundled git gems after clean" do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
@@ -812,7 +810,7 @@ RSpec.describe "bundle clean" do
expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist
end
- it "removes extension directories", :ruby_repo do
+ it "removes extension directories" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -848,7 +846,7 @@ RSpec.describe "bundle clean" do
expect(simple_binary_extensions_dir).to exist
end
- it "removes git extension directories", :ruby_repo do
+ it "removes git extension directories" do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
diff --git a/spec/bundler/commands/config_spec.rb b/spec/bundler/commands/config_spec.rb
index 1ef84c8195..ede93f99eb 100644
--- a/spec/bundler/commands/config_spec.rb
+++ b/spec/bundler/commands/config_spec.rb
@@ -43,6 +43,12 @@ RSpec.describe ".bundle/config" do
G
end
+ it "is local by default" do
+ bundle "config set foo bar"
+ expect(bundled_app(".bundle/config")).to exist
+ expect(home(".bundle/config")).not_to exist
+ end
+
it "can be moved with an environment variable" do
ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s
bundle "config set --local path vendor/bundle"
@@ -67,6 +73,12 @@ RSpec.describe ".bundle/config" do
end
describe "location without a gemfile" do
+ it "is global by default" do
+ bundle "config set foo bar"
+ expect(bundled_app(".bundle/config")).not_to exist
+ expect(home(".bundle/config")).to exist
+ end
+
it "works with an absolute path" do
ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s
bundle "config set --local path vendor/bundle"
@@ -76,6 +88,30 @@ RSpec.describe ".bundle/config" do
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
+
describe "global" do
before(:each) do
install_gemfile <<-G
@@ -107,17 +143,15 @@ RSpec.describe ".bundle/config" do
end
it "has lower precedence than env" do
- begin
- ENV["BUNDLE_FOO"] = "env"
+ ENV["BUNDLE_FOO"] = "env"
- bundle "config set --global foo global"
- expect(out).to match(/You have a bundler environment variable for foo set to "env"/)
+ bundle "config set --global foo global"
+ expect(out).to match(/You have a bundler environment variable for foo set to "env"/)
- run "puts Bundler.settings[:foo]"
- expect(out).to eq("env")
- ensure
- ENV.delete("BUNDLE_FOO")
- end
+ run "puts Bundler.settings[:foo]"
+ expect(out).to eq("env")
+ ensure
+ ENV.delete("BUNDLE_FOO")
end
it "can be deleted" do
@@ -185,15 +219,13 @@ RSpec.describe ".bundle/config" do
end
it "has higher precedence than env" do
- begin
- ENV["BUNDLE_FOO"] = "env"
- bundle "config set --local foo local"
-
- run "puts Bundler.settings[:foo]"
- expect(out).to eq("local")
- ensure
- ENV.delete("BUNDLE_FOO")
- end
+ ENV["BUNDLE_FOO"] = "env"
+ bundle "config set --local foo local"
+
+ run "puts Bundler.settings[:foo]"
+ expect(out).to eq("local")
+ ensure
+ ENV.delete("BUNDLE_FOO")
end
it "can be deleted" do
@@ -335,7 +367,7 @@ E
it "doesn't return quotes around values" do
bundle "config set foo '1'"
- run "puts Bundler.settings.send(:global_config_file).read"
+ run "puts Bundler.settings.send(:local_config_file).read"
expect(out).to include('"1"')
run "puts Bundler.settings[:foo]"
expect(out).to eq("1")
@@ -399,21 +431,57 @@ E
end
end
+ describe "commented out settings with urls" do
+ before do
+ bundle "config set #mirror.https://rails-assets.org http://localhost:9292"
+ end
+
+ it "does not make bundler crash and ignores the configuration" do
+ bundle "config list --parseable"
+
+ expect(out).to eq("#mirror.https://rails-assets.org/=http://localhost:9292")
+ expect(err).to be_empty
+
+ ruby(<<~RUBY)
+ require "#{entrypoint}"
+ print Bundler.settings.mirror_for("https://rails-assets.org")
+ RUBY
+ expect(out).to eq("https://rails-assets.org/")
+ expect(err).to be_empty
+
+ bundle "config set mirror.all http://localhost:9293"
+ ruby(<<~RUBY)
+ require "#{entrypoint}"
+ print Bundler.settings.mirror_for("https://rails-assets.org")
+ RUBY
+ expect(out).to eq("http://localhost:9293/")
+ expect(err).to be_empty
+ end
+ end
+
describe "subcommands" do
it "list" do
- bundle "config list"
- expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\""
+ bundle "config list", :env => { "BUNDLE_FOO" => "bar" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nfoo\nSet via BUNDLE_FOO: \"bar\""
- bundle "config list", :parseable => true
- expect(out).to eq "spec_run=true"
+ bundle "config list", :env => { "BUNDLE_FOO" => "bar" }, :parseable => true
+ expect(out).to eq "foo=bar"
end
it "list with credentials" do
bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
- expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\"\n\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\""
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\""
bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
- expect(out).to eq "gems.myserver.com=user:password\nspec_run=true"
+ expect(out).to eq "gems.myserver.com=user:password"
+ end
+
+ it "list with API token credentials" do
+ bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"[REDACTED]:x-oauth-basic\""
+
+ bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
+ expect(out).to eq "gems.myserver.com=api_token:x-oauth-basic"
end
it "get" do
diff --git a/spec/bundler/commands/doctor_spec.rb b/spec/bundler/commands/doctor_spec.rb
index a59ccc540a..1afac00923 100644
--- a/spec/bundler/commands/doctor_spec.rb
+++ b/spec/bundler/commands/doctor_spec.rb
@@ -49,8 +49,8 @@ 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?).with("/usr/lib/libSystem.dylib").and_return(true)
- expect { doctor.run }.not_to(raise_error, @stdout.string)
+ allow(Fiddle).to receive(:dlopen).with("/usr/lib/libSystem.dylib").and_return(true)
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to be_empty
end
@@ -58,7 +58,7 @@ 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?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false)
+ allow(Fiddle).to receive(:dlopen).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_raise(Fiddle::DLError)
expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string
The following gems are missing OS dependencies:
* bundler: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
@@ -79,7 +79,7 @@ RSpec.describe "bundle doctor" do
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 - #{@unwritable_file}"
+ "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
@@ -133,4 +133,14 @@ RSpec.describe "bundle doctor" do
end
end
end
+
+ context "when home contains filenames 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 2c83ec8e11..099cdb39fa 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -2,11 +2,10 @@
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 => default_bundle_path)
- end
it "works with --gemfile flag" do
+ system_gems(system_gems_to_install, :path => default_bundle_path)
+
create_file "CustomGemfile", <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
@@ -17,6 +16,8 @@ RSpec.describe "bundle exec" do
end
it "activates the correct gem" do
+ system_gems(system_gems_to_install, :path => default_bundle_path)
+
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
@@ -27,6 +28,8 @@ RSpec.describe "bundle exec" do
end
it "works and prints no warnings when HOME is not writable" do
+ system_gems(system_gems_to_install, :path => default_bundle_path)
+
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
@@ -209,8 +212,6 @@ RSpec.describe "bundle exec" do
end
context "with default gems" do
- let(:system_gems_to_install) { [] }
-
let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false }
context "when not specified in Gemfile" do
@@ -291,7 +292,7 @@ RSpec.describe "bundle exec" do
end
end
- bundle "config set path.system true"
+ bundle "config set --global path.system true"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -402,6 +403,8 @@ RSpec.describe "bundle exec" do
end
it "raises a helpful error when exec'ing to something outside of the bundle" do
+ system_gems(system_gems_to_install, :path => default_bundle_path)
+
bundle "config set clean false" # want to keep the rackup binstub
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -612,6 +615,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"
@@ -676,6 +709,8 @@ RSpec.describe "bundle exec" do
RUBY
before do
+ system_gems(system_gems_to_install, :path => default_bundle_path)
+
bundled_app(path).open("w") {|f| f << executable }
bundled_app(path).chmod(0o755)
@@ -745,9 +780,7 @@ RSpec.describe "bundle exec" do
end
let(:expected_err) { "" }
let(:exit_code) do
- # signal mask 128 + plus signal 15 -> TERM
- # this is specified by C99
- 128 + 15
+ exit_status_for_signal(Signal.list["TERM"])
end
it "runs" do
@@ -836,9 +869,12 @@ 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 rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally.
-The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m
-\e[33mRun `bundle install` to install missing gems.\e[0m
+Could not find gem 'rack (= 2)' in locally installed gems.
+
+The source contains the following gems matching 'rack':
+ * rack-0.9.1
+ * rack-1.0.0
+Run `bundle install` to install missing gems.
EOS
it "runs" do
@@ -863,9 +899,11 @@ The source contains the following versions of 'rack': 0.9.1, 1.0.0\e[0m
let(:exit_code) { Bundler::GemNotFound.new.status_code }
let(:expected) { "" }
let(:expected_err) { <<-EOS.strip }
-\e[31mCould not find gem 'rack (= 2)' in rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally.
-The source contains the following versions of 'rack': 1.0.0\e[0m
-\e[33mRun `bundle install` to install missing gems.\e[0m
+Could not find gem 'rack (= 2)' in locally installed gems.
+
+The source contains the following gems matching 'rack':
+ * rack-1.0.0
+Run `bundle install` to install missing gems.
EOS
it "runs" do
@@ -878,6 +916,30 @@ The source contains the following versions of 'rack': 1.0.0\e[0m
end
end
+ context "when Bundler.setup fails and Gemfile is not the default" do
+ before do
+ create_file "CustomGemfile", <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack', '2'
+ G
+ ENV["BUNDLER_FORCE_TTY"] = "true"
+ ENV["BUNDLE_GEMFILE"] = "CustomGemfile"
+ ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil
+ end
+
+ let(:exit_code) { Bundler::GemNotFound.new.status_code }
+ let(:expected) { "" }
+
+ it "prints proper suggestion" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to include("Run `bundle install --gemfile CustomGemfile` to install missing gems.")
+ 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 }
diff --git a/spec/bundler/commands/fund_spec.rb b/spec/bundler/commands/fund_spec.rb
index 5a0c5411da..5415b88eeb 100644
--- a/spec/bundler/commands/fund_spec.rb
+++ b/spec/bundler/commands/fund_spec.rb
@@ -5,20 +5,20 @@ RSpec.describe "bundle fund" 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",
+ "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",
+ "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",
+ "funding_uri" => "https://example.com/has_funding/funding",
}
end
diff --git a/spec/bundler/commands/help_spec.rb b/spec/bundler/commands/help_spec.rb
index f72763900e..409c49f9e1 100644
--- a/spec/bundler/commands/help_spec.rb
+++ b/spec/bundler/commands/help_spec.rb
@@ -23,8 +23,8 @@ RSpec.describe "bundle help" do
end
it "still outputs the old help for commands that do not have man pages yet" do
- bundle "help version"
- expect(out).to include("Prints the bundler's version information")
+ bundle "help fund"
+ expect(out).to include("Lists information about gems seeking funding assistance")
end
it "looks for a binary and executes it with --help option if it's named bundler-<task>" do
diff --git a/spec/bundler/commands/info_spec.rb b/spec/bundler/commands/info_spec.rb
index 906349cacf..851f50240f 100644
--- a/spec/bundler/commands/info_spec.rb
+++ b/spec/bundler/commands/info_spec.rb
@@ -6,13 +6,13 @@ RSpec.describe "bundle info" 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",
+ "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",
+ "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
@@ -21,6 +21,7 @@ RSpec.describe "bundle info" do
source "#{file_uri_for(gem_repo2)}"
gem "rails"
gem "has_metadata"
+ gem "thin"
G
end
@@ -50,6 +51,19 @@ 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", :raise_on_error => false
expect(err).to eq("Could not find gem 'missing'.")
@@ -60,7 +74,15 @@ RSpec.describe "bundle info" do
bundle "info rails --path"
- expect(err).to match(/has been deleted/i)
+ 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
@@ -102,6 +124,30 @@ RSpec.describe "bundle info" do
expect(out).to_not include("Homepage:")
end
end
+
+ context "when gem has a reverse dependency on any version" do
+ it "prints the details" do
+ bundle "info rack"
+
+ expect(out).to include("Reverse Dependencies: \n\t\tthin (1.0) depends on rack (>= 0)")
+ end
+ end
+
+ context "when gem has a reverse dependency on a specific version" do
+ it "prints the details" do
+ bundle "info actionpack"
+
+ expect(out).to include("Reverse Dependencies: \n\t\trails (2.3.2) depends on actionpack (= 2.3.2)")
+ end
+ end
+
+ context "when gem has no reverse dependencies" do
+ it "excludes the reverse dependencies field from the output" do
+ bundle "info rails"
+
+ expect(out).not_to include("Reverse Dependencies:")
+ end
+ end
end
context "with a git repo in the Gemfile" do
@@ -117,10 +163,10 @@ RSpec.describe "bundle info" do
expect(the_bundle).to include_gems "foo 1.0"
bundle "info foo"
- expect(out).to include("foo (1.0 #{@git.ref_for("master", 6)}")
+ expect(out).to include("foo (1.0 #{@git.ref_for("main", 6)}")
end
- it "prints out branch names other than master" do
+ it "prints out branch names other than main" do
update_git "foo", :branch => "omg" do |s|
s.write "lib/foo.rb", "FOO = '1.0.omg'"
end
@@ -169,7 +215,7 @@ RSpec.describe "bundle info" do
G
bundle "info rac"
- expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>)?\z/)
+ expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>.*)?\z/)
end
end
diff --git a/spec/bundler/commands/init_spec.rb b/spec/bundler/commands/init_spec.rb
index 683a453c7d..6aa3e9edd1 100644
--- a/spec/bundler/commands/init_spec.rb
+++ b/spec/bundler/commands/init_spec.rb
@@ -7,6 +7,29 @@ RSpec.describe "bundle init" do
expect(bundled_app_gemfile).to be_file
end
+ context "with a template with permission flags not matching current process umask" do
+ let(:template_file) do
+ gemfile = Bundler.preferred_gemfile_name
+ templates_dir.join(gemfile)
+ end
+
+ let(:target_dir) { bundled_app("init_permissions_test") }
+
+ around do |example|
+ old_chmod = File.stat(template_file).mode
+ FileUtils.chmod(old_chmod | 0o111, template_file) # chmod +x
+ example.run
+ FileUtils.chmod(old_chmod, template_file)
+ end
+
+ it "honours the current process umask when generating from a template" do
+ FileUtils.mkdir(target_dir)
+ bundle :init, :dir => target_dir
+ generated_mode = File.stat(File.join(target_dir, "Gemfile")).mode & 0o111
+ expect(generated_mode).to be_zero
+ end
+ end
+
context "when a Gemfile already exists" do
before do
create_file "Gemfile", <<-G
@@ -42,7 +65,7 @@ RSpec.describe "bundle init" do
context "when the dir is not writable by the current user" do
let(:subdir) { "child_dir" }
- it "notifies the user that it can not write to it" do
+ it "notifies the user that it cannot write to it" do
FileUtils.mkdir bundled_app(subdir)
# chmod a-w it
mode = File.stat(bundled_app(subdir)).mode ^ 0o222
@@ -168,4 +191,17 @@ RSpec.describe "bundle init" do
end
end
end
+
+ describe "using the --gemfile" do
+ it "should use the --gemfile value to name the gemfile" do
+ custom_gemfile_name = "NiceGemfileName"
+
+ bundle :init, :gemfile => custom_gemfile_name
+
+ expect(out).to include("Writing new #{custom_gemfile_name}")
+ used_template = File.read("#{source_root}/lib/bundler/templates/Gemfile")
+ generated_gemfile = bundled_app(custom_gemfile_name).read
+ expect(generated_gemfile).to eq(used_template)
+ end
+ end
end
diff --git a/spec/bundler/commands/inject_spec.rb b/spec/bundler/commands/inject_spec.rb
index 2d97bf6ff0..d711fe010d 100644
--- a/spec/bundler/commands/inject_spec.rb
+++ b/spec/bundler/commands/inject_spec.rb
@@ -99,7 +99,7 @@ Usage: "bundle inject GEM VERSION"
it "restores frozen afterwards" do
bundle "inject 'rack-obama' '> 0'"
- config = YAML.load(bundled_app(".bundle/config").read)
+ config = Psych.load(bundled_app(".bundle/config").read)
expect(config["BUNDLE_DEPLOYMENT"] || config["BUNDLE_FROZEN"]).to eq("true")
end
@@ -109,7 +109,7 @@ Usage: "bundle inject GEM VERSION"
gem "rack-obama"
G
bundle "inject 'rack' '> 0'", :raise_on_error => false
- expect(err).to match(/trying to install in deployment mode after changing/)
+ expect(err).to match(/the lockfile can't be updated because frozen mode is set/)
expect(bundled_app_lock.read).not_to match(/rack-obama/)
end
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
index 412000341f..f572bdf176 100644
--- a/spec/bundler/commands/install_spec.rb
+++ b/spec/bundler/commands/install_spec.rb
@@ -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)}"
@@ -270,7 +285,7 @@ RSpec.describe "bundle install with gem sources" do
end
it "installs gems for windows" do
- simulate_platform mswin
+ simulate_platform x86_mswin32
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -278,7 +293,7 @@ RSpec.describe "bundle install with gem sources" do
G
run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 MSWIN")
+ expect(out).to eq("1.0 x86-mswin32")
end
end
@@ -336,7 +351,7 @@ RSpec.describe "bundle install with gem sources" do
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." \
+ "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
@@ -349,7 +364,9 @@ RSpec.describe "bundle install with gem sources" do
end
it "throws a warning if a gem is added twice in Gemfile without version requirements" do
- install_gemfile <<-G, :raise_on_error => false
+ build_repo2
+
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rack"
gem "rack"
@@ -361,7 +378,9 @@ RSpec.describe "bundle install with gem sources" do
end
it "throws a warning if a gem is added twice in Gemfile with same versions" do
- install_gemfile <<-G, :raise_on_error => false
+ build_repo2
+
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rack", "1.0"
gem "rack", "1.0"
@@ -372,6 +391,22 @@ RSpec.describe "bundle install with gem sources" do
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 "throws a warning if a gem is added twice under different platforms and does not crash when using the generated lockfile" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack", :platform => :jruby
+ gem "rack"
+ G
+
+ bundle "install"
+
+ 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 "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"
@@ -484,26 +519,23 @@ RSpec.describe "bundle install with gem sources" do
context "and using an unsupported Ruby version" do
it "prints an error" do
install_gemfile <<-G, :raise_on_error => false
- ::RUBY_VERSION = '2.0.1'
- ruby '~> 2.2'
+ ruby '~> 1.2'
source "#{file_uri_for(gem_repo1)}"
G
- expect(err).to include("Your Ruby version is 2.0.1, but your Gemfile specified ~> 2.2")
+ expect(err).to include("Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified ~> 1.2")
end
end
context "and using a supported Ruby version" do
before do
install_gemfile <<-G
- ::RUBY_VERSION = '2.1.3'
- ::RUBY_PATCHLEVEL = 100
- ruby '~> 2.1.0'
+ ruby '~> #{Gem.ruby_version}'
source "#{file_uri_for(gem_repo1)}"
G
end
it "writes current Ruby version to Gemfile.lock" do
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -514,22 +546,20 @@ RSpec.describe "bundle install with gem sources" do
DEPENDENCIES
RUBY VERSION
- ruby 2.1.3p100
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
L
end
- it "updates Gemfile.lock with updated incompatible ruby version" do
+ it "updates Gemfile.lock with updated yet still compatible ruby version" do
install_gemfile <<-G
- ::RUBY_VERSION = '2.2.3'
- ::RUBY_PATCHLEVEL = 100
- ruby '~> 2.2.0'
+ ruby '~> #{current_ruby_minor}'
source "#{file_uri_for(gem_repo1)}"
G
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -540,7 +570,7 @@ RSpec.describe "bundle install with gem sources" do
DEPENDENCIES
RUBY VERSION
- ruby 2.2.3p100
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
@@ -663,6 +693,103 @@ RSpec.describe "bundle install with gem sources" do
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 bundle extensions path does not have write access", :permissions do
+ let(:extensions_path) { bundled_app("vendor/#{Bundler.ruby_scope}/extensions/#{Gem::Platform.local}/#{Gem.extension_api_version}") }
+
+ before do
+ FileUtils.mkdir_p(extensions_path)
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'simple_binary'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", extensions_path)
+ bundle "config set --local path vendor"
+
+ begin
+ bundle :install, :raise_on_error => false
+ ensure
+ FileUtils.chmod("+x", extensions_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to create `#{extensions_path.join("simple_binary-1.0")}`. " \
+ "It is likely that you need to grant executable permissions for all parent directories and write permissions for `#{extensions_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("Could not delete previous installation of `#{foo_path}`.")
+ expect(err).to include("The underlying error was Errno::EACCES")
+ end
+ end
+
describe "when bundle cache path does not have write access", :permissions do
let(:cache_path) { bundled_app("vendor/#{Bundler.ruby_scope}/cache") }
@@ -697,7 +824,7 @@ RSpec.describe "bundle install with gem sources" do
it "includes the standalone path" do
bundle "binstubs rack", :standalone => true
standalone_line = File.read(bundled_app("bin/rackup")).each_line.find {|line| line.include? "$:.unshift" }.strip
- expect(standalone_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath)
+ expect(standalone_line).to eq %($:.unshift File.expand_path "../bundle", __dir__)
end
end
@@ -755,8 +882,225 @@ RSpec.describe "bundle install with gem sources" do
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."
+ "Add the current platform to the lockfile with\n`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 "#{Gem.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
+
+ context "with only option" do
+ before do
+ bundle "config set only a:b"
+ end
+
+ it "installs only gems of the specified groups" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rails"
+ gem "rack", group: :a
+ gem "rake", group: :b
+ gem "yard", group: :c
+ G
+
+ expect(out).to include("Installing rack")
+ expect(out).to include("Installing rake")
+ expect(out).not_to include("Installing yard")
+ end
+ end
+
+ context "with --prefer-local flag" do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.1"
+ build_gem "foo", "1.0.0"
+ build_gem "bar", "1.0.0"
+ end
+
+ system_gems "foo-1.0.0", :path => default_bundle_path, :gem_repo => gem_repo4
+ end
+
+ it "fetches remote sources only when not available locally" do
+ install_gemfile <<-G, :"prefer-local" => true, :verbose => true
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "foo"
+ gem "bar"
+ G
+
+ expect(out).to include("Using foo 1.0.0").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0")
+ expect(last_command).to be_success
+ end
+ end
+
+ context "with a symlinked configured as bundle path and a gem with symlinks" do
+ before do
+ symlinked_bundled_app = tmp("bundled_app-symlink")
+ File.symlink(bundled_app, symlinked_bundled_app)
+ bundle "config path #{File.join(symlinked_bundled_app, ".vendor")}"
+
+ binman_path = tmp("binman")
+ FileUtils.mkdir_p binman_path
+
+ readme_path = File.join(binman_path, "README.markdown")
+ FileUtils.touch(readme_path)
+
+ man_path = File.join(binman_path, "man", "man0")
+ FileUtils.mkdir_p man_path
+
+ File.symlink("../../README.markdown", File.join(man_path, "README.markdown"))
+
+ build_repo4 do
+ build_gem "binman", :path => gem_repo4("gems"), :lib_path => binman_path, :no_default => true do |s|
+ s.files = ["README.markdown", "man/man0/README.markdown"]
+ end
+ end
+ end
+
+ it "installs fine" do
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "binman"
+ G
+ end
+ end
+
+ context "when a gem has equivalent versions with inconsistent dependencies" do
+ before do
+ build_repo4 do
+ build_gem "autobuild", "1.10.rc2" do |s|
+ s.add_dependency "utilrb", ">= 1.6.0"
+ end
+
+ build_gem "autobuild", "1.10.0.rc2" do |s|
+ s.add_dependency "utilrb", ">= 2.0"
+ end
+ end
+ end
+
+ it "does not crash unexpectedly" do
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "autobuild", "1.10.rc2"
+ G
+
+ bundle "install --jobs 1", :raise_on_error => false
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ expect(err).to include("Could not find compatible versions")
+ end
+ end
end
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index 21eb6e5456..491fa30949 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe "bundle lock" do
it "does not fetch remote specs when using the --local option" do
bundle "lock --update --local", :raise_on_error => false
- expect(err).to match(/installed locally/)
+ expect(err).to match(/locally installed gems/)
end
it "works with --gemfile flag" do
@@ -140,6 +140,62 @@ RSpec.describe "bundle lock" do
expect(read_lockfile).to eq(@lockfile)
end
+ it "does not unlock git sources when only uri shape changes" do
+ build_git("foo")
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ G
+
+ # Change uri format to end with "/" and reinstall
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}/"
+ G
+
+ expect(out).to include("using resolution from the lockfile")
+ expect(out).not_to include("re-resolving dependencies because the list of sources changed")
+ end
+
+ it "updates specific gems using --update using the locked revision of unrelated git gems for resolving" do
+ ref = build_git("foo").ref_for("HEAD")
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rake"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :branch => "deadbeef"
+ G
+
+ lockfile <<~L
+ GIT
+ remote: #{file_uri_for(lib_path("foo-1.0"))}
+ revision: #{ref}
+ branch: deadbeef
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rake (10.0.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+ rake
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update rake --verbose"
+ expect(out).to match(/Writing lockfile to.+lock/)
+ expect(lockfile).to include("rake (13.0.1)")
+ end
+
it "errors when updating a missing specific gems using --update" do
lockfile @lockfile
@@ -157,9 +213,9 @@ RSpec.describe "bundle lock" do
gem "rack_middleware", :group => "test"
G
bundle "config set without test"
- bundle "config set path .bundle"
+ bundle "config set path vendor/bundle"
bundle "lock"
- expect(bundled_app(".bundle")).not_to exist
+ expect(bundled_app("vendor/bundle")).not_to exist
end
# see update_spec for more coverage on same options. logic is shared so it's not necessary
@@ -176,7 +232,10 @@ RSpec.describe "bundle lock" do
build_gem "foo", %w[1.5.1] do |s|
s.add_dependency "bar", "~> 3.0"
end
- build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
+ build_gem "foo", %w[2.0.0.pre] do |s|
+ s.add_dependency "bar"
+ end
+ build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 2.1.2.pre 3.0.0 3.1.0.pre 4.0.0.pre]
build_gem "qux", %w[1.0.0 1.0.1 1.1.0 2.0.0]
end
@@ -210,6 +269,55 @@ RSpec.describe "bundle lock" do
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.5.0 bar-2.1.1 qux-1.1.0].sort)
end
+
+ context "pre" do
+ it "defaults to major" do
+ bundle "lock --update --pre"
+
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
+ end
+
+ it "patch preferred" do
+ bundle "lock --update --patch --pre"
+
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.4.5 bar-2.1.2.pre qux-1.0.1].sort)
+ end
+
+ it "minor preferred" do
+ bundle "lock --update --minor --pre"
+
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.5.1 bar-3.1.0.pre qux-1.1.0].sort)
+ end
+
+ it "major preferred" do
+ bundle "lock --update --major --pre"
+
+ expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
+ end
+ end
+ end
+
+ it "updates the bundler version in the lockfile to the latest bundler version" do
+ build_repo4 do
+ build_gem "bundler", "55"
+ end
+
+ system_gems "bundler-55", :gem_repo => gem_repo4
+
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "https://gems.repo4"
+ G
+ lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, '\11.0.0\2')
+
+ bundle "lock --update --bundler --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(lockfile).to end_with("BUNDLED WITH\n 55\n")
+
+ update_repo4 do
+ build_gem "bundler", "99"
+ end
+
+ bundle "lock --update --bundler --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(lockfile).to end_with("BUNDLED WITH\n 99\n")
end
it "supports adding new platforms" do
@@ -217,7 +325,7 @@ RSpec.describe "bundle lock" do
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)
+ expect(lockfile.platforms).to match_array([java, x86_mingw32, local_platform].uniq)
end
it "supports adding new platforms with force_ruby_platform = true" do
@@ -226,11 +334,11 @@ RSpec.describe "bundle lock" do
remote: #{file_uri_for(gem_repo1)}/
specs:
platform_specific (1.0)
- platform_specific (1.0-x86-linux)
+ platform_specific (1.0-x86-64_linux)
PLATFORMS
ruby
- x86-linux
+ x86_64-linux
DEPENDENCIES
platform_specific
@@ -241,7 +349,7 @@ RSpec.describe "bundle lock" do
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)
+ expect(lockfile.platforms).to contain_exactly(rb, linux, java, x86_mingw32)
end
it "supports adding the `ruby` platform" do
@@ -249,7 +357,7 @@ RSpec.describe "bundle lock" do
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)
+ expect(lockfile.platforms).to match_array(["ruby", local_platform].uniq)
end
it "warns when adding an unknown platform" do
@@ -262,16 +370,71 @@ RSpec.describe "bundle lock" do
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)
+ expect(lockfile.platforms).to match_array([java, x86_mingw32, local_platform].uniq)
bundle "lock --remove-platform java"
lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(local_platforms.unshift(mingw).uniq)
+ expect(lockfile.platforms).to match_array([x86_mingw32, local_platform].uniq)
+ end
+
+ it "also cleans up redundant platform gems when removing platforms" do
+ build_repo4 do
+ build_gem "nokogiri", "1.12.0"
+ build_gem "nokogiri", "1.12.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+ end
+
+ simulate_platform "x86_64-darwin-22" do
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ G
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.12.0)
+ nokogiri (1.12.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "lock --remove-platform ruby"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.12.0-x86_64-darwin)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
it "errors when removing all platforms" do
- bundle "lock --remove-platform #{local_platforms.join(" ")}", :raise_on_error => false
+ bundle "lock --remove-platform #{local_platform}", :raise_on_error => false
expect(err).to include("Removing all platforms from the bundle is not allowed")
end
@@ -280,7 +443,7 @@ RSpec.describe "bundle lock" do
build_repo4 do
build_gem "ffi", "1.9.14"
build_gem "ffi", "1.9.14" do |s|
- s.platform = mingw
+ s.platform = x86_mingw32
end
build_gem "gssapi", "0.1"
@@ -312,9 +475,9 @@ RSpec.describe "bundle lock" do
gem "gssapi"
G
- simulate_platform(mingw) { bundle :lock }
+ simulate_platform(x86_mingw32) { bundle :lock }
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -337,9 +500,10 @@ RSpec.describe "bundle lock" do
#{Bundler::VERSION}
G
- simulate_platform(rb) { bundle :lock }
+ bundle "config set --local force_ruby_platform true"
+ bundle :lock
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -426,7 +590,7 @@ RSpec.describe "bundle lock" do
simulate_platform(Gem::Platform.new("x86_64-darwin")) { bundle "lock" }
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -492,22 +656,25 @@ RSpec.describe "bundle lock" do
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"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
end
build_gem "raygun-apm", "1.0.78" do |s|
s.platform = "universal-darwin"
- s.required_ruby_version = "< #{next_minor}.dev"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
end
build_gem "raygun-apm", "1.0.78" do |s|
s.platform = "x64-mingw32"
- s.required_ruby_version = "< #{next_minor}.dev"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x64-mingw-ucrt"
+ s.required_ruby_version = "< #{next_ruby_minor}.dev"
end
end
@@ -536,6 +703,94 @@ RSpec.describe "bundle lock" do
bundle "lock --add-platform x86_64-linux", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
end
+ it "does not crash on conflicting ruby requirements between platform versions in two different gems" do
+ build_repo4 do
+ build_gem "unf_ext", "0.0.8.2"
+
+ build_gem "unf_ext", "0.0.8.2" do |s|
+ s.required_ruby_version = [">= 2.4", "< #{previous_ruby_minor}"]
+ s.platform = "x64-mingw32"
+ end
+
+ build_gem "unf_ext", "0.0.8.2" do |s|
+ s.required_ruby_version = [">= #{previous_ruby_minor}", "< #{current_ruby_minor}"]
+ s.platform = "x64-mingw-ucrt"
+ end
+
+ build_gem "google-protobuf", "3.21.12"
+
+ build_gem "google-protobuf", "3.21.12" do |s|
+ s.required_ruby_version = [">= 2.5", "< #{previous_ruby_minor}"]
+ s.platform = "x64-mingw32"
+ end
+
+ build_gem "google-protobuf", "3.21.12" do |s|
+ s.required_ruby_version = [">= #{previous_ruby_minor}", "< #{current_ruby_minor}"]
+ s.platform = "x64-mingw-ucrt"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "google-protobuf"
+ gem "unf_ext"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ google-protobuf (3.21.12)
+ unf_ext (0.0.8.2)
+
+ PLATFORMS
+ x64-mingw-ucrt
+ x64-mingw32
+
+ DEPENDENCIES
+ google-protobuf
+ unf_ext
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "DEBUG_RESOLVER" => "1" }
+ end
+
+ it "respects lower bound ruby requirements" do
+ build_repo4 do
+ build_gem "our_private_gem", "0.1.0" do |s|
+ s.required_ruby_version = ">= #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+
+ gem "our_private_gem"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ our_private_gem (0.1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ our_private_gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end
+
context "when an update is available" do
let(:repo) { gem_repo2 }
@@ -559,4 +814,460 @@ RSpec.describe "bundle lock" do
expect(read_lockfile).to eq(@lockfile.sub("foo (1.0)", "foo (2.0)").sub(/foo$/, "foo (= 2.0)"))
end
end
+
+ context "when a system gem has incorrect dependencies, different from the lockfile" do
+ before do
+ build_repo4 do
+ build_gem "debug", "1.6.3" do |s|
+ s.add_dependency "irb", ">= 1.3.6"
+ end
+
+ build_gem "irb", "1.5.0"
+ end
+
+ system_gems "irb-1.5.0", :gem_repo => gem_repo4
+ system_gems "debug-1.6.3", :gem_repo => gem_repo4
+
+ # simulate gemspec with wrong empty dependencies
+ debug_gemspec_path = system_gem_path("specifications/debug-1.6.3.gemspec")
+ debug_gemspec = Gem::Specification.load(debug_gemspec_path.to_s)
+ debug_gemspec.dependencies.clear
+ File.write(debug_gemspec_path, debug_gemspec.to_ruby)
+ end
+
+ it "respects the existing lockfile, even when reresolving" do
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "debug"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ debug (1.6.3)
+ irb (>= 1.3.6)
+ irb (1.5.0)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ debug
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-22" do
+ bundle "lock"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ debug (1.6.3)
+ irb (>= 1.3.6)
+ irb (1.5.0)
+
+ PLATFORMS
+ arm64-darwin-22
+ x86_64-linux
+
+ DEPENDENCIES
+ debug
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "properly shows resolution errors including OR requirements" do
+ build_repo4 do
+ build_gem "activeadmin", "2.13.1" do |s|
+ s.add_dependency "railties", ">= 6.1", "< 7.1"
+ end
+ build_gem "actionpack", "6.1.4"
+ build_gem "actionpack", "7.0.3.1"
+ build_gem "actionpack", "7.0.4"
+ build_gem "railties", "6.1.4" do |s|
+ s.add_dependency "actionpack", "6.1.4"
+ end
+ build_gem "rails", "7.0.3.1" do |s|
+ s.add_dependency "railties", "7.0.3.1"
+ end
+ build_gem "rails", "7.0.4" do |s|
+ s.add_dependency "railties", "7.0.4"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "rails", ">= 7.0.3.1"
+ gem "activeadmin", "2.13.1"
+ G
+
+ bundle "lock", :raise_on_error => false
+
+ expect(err).to eq <<~ERR.strip
+ Could not find compatible versions
+
+ Because rails >= 7.0.4 depends on railties = 7.0.4
+ and rails < 7.0.4 depends on railties = 7.0.3.1,
+ railties = 7.0.3.1 OR = 7.0.4 is required.
+ So, because railties = 7.0.3.1 OR = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally,
+ version solving has failed.
+ ERR
+ end
+
+ it "is able to display some explanation on crazy irresolvable cases" do
+ build_repo4 do
+ build_gem "activeadmin", "2.13.1" do |s|
+ s.add_dependency "ransack", "= 3.1.0"
+ end
+
+ # Activemodel is missing as a dependency in lockfile
+ build_gem "ransack", "3.1.0" do |s|
+ s.add_dependency "activemodel", ">= 6.0.4"
+ s.add_dependency "activesupport", ">= 6.0.4"
+ end
+
+ %w[6.0.4 7.0.2.3 7.0.3.1 7.0.4].each do |version|
+ build_gem "activesupport", version
+
+ # Activemodel is only available on 6.0.4
+ if version == "6.0.4"
+ build_gem "activemodel", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ end
+
+ build_gem "rails", version do |s|
+ # Depednencies of Rails 7.0.2.3 are in reverse order
+ if version == "7.0.2.3"
+ s.add_dependency "activesupport", version
+ s.add_dependency "activemodel", version
+ else
+ s.add_dependency "activemodel", version
+ s.add_dependency "activesupport", version
+ end
+ end
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "rails", ">= 7.0.2.3"
+ gem "activeadmin", "= 2.13.1"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ activeadmin (2.13.1)
+ ransack (= 3.1.0)
+ ransack (3.1.0)
+ activemodel (>= 6.0.4)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activeadmin (= 2.13.1)
+ ransack (= 3.1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock", :raise_on_error => false
+
+ expect(err).to eq <<~ERR.strip
+ Could not find compatible versions
+
+ Because every version of activemodel depends on activesupport = 6.0.4
+ and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
+ every version of activemodel is incompatible with rails >= 7.0.2.3, < 7.0.3.1.
+ And because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
+ rails >= 7.0.2.3, < 7.0.3.1 cannot be used.
+ (1) So, because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
+ and rails >= 7.0.4 depends on activemodel = 7.0.4,
+ rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4.
+
+ Because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
+ and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
+ rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 or activesupport = 7.0.3.1.
+ And because rails >= 7.0.4 depends on activesupport = 7.0.4
+ and every version of activemodel depends on activesupport = 6.0.4,
+ activemodel != 7.0.2.3 is incompatible with rails >= 7.0.2.3.
+ And because rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4 (1),
+ rails >= 7.0.2.3 cannot be used.
+ So, because Gemfile depends on rails >= 7.0.2.3,
+ version solving has failed.
+ ERR
+
+ lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
+
+ bundle "lock", :raise_on_error => false
+
+ expect(err).to eq <<~ERR.strip
+ Could not find compatible versions
+
+ Because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
+ and rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
+ rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 OR = 7.0.3.1.
+ And because every version of activemodel depends on activesupport = 6.0.4,
+ rails >= 7.0.2.3, < 7.0.4 requires activesupport = 6.0.4.
+ Because rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1
+ and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
+ rails >= 7.0.2.3, < 7.0.4 requires activesupport = 7.0.2.3 OR = 7.0.3.1.
+ Thus, rails >= 7.0.2.3, < 7.0.4 cannot be used.
+ And because rails >= 7.0.4 depends on activemodel = 7.0.4,
+ rails >= 7.0.2.3 requires activemodel = 7.0.4.
+ So, because activemodel = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally
+ and Gemfile depends on rails >= 7.0.2.3,
+ version solving has failed.
+ ERR
+ end
+
+ it "does not accidentally resolves to prereleases" do
+ build_repo4 do
+ build_gem "autoproj", "2.0.3" do |s|
+ s.add_dependency "autobuild", ">= 1.10.0.a"
+ s.add_dependency "tty-prompt"
+ end
+
+ build_gem "tty-prompt", "0.6.0"
+ build_gem "tty-prompt", "0.7.0"
+
+ build_gem "autobuild", "1.10.0.b3"
+ build_gem "autobuild", "1.10.1" do |s|
+ s.add_dependency "tty-prompt", "~> 0.6.0"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "autoproj", ">= 2.0.0"
+ G
+
+ bundle "lock"
+ expect(lockfile).to_not include("autobuild (1.10.0.b3)")
+ expect(lockfile).to include("autobuild (1.10.1)")
+ end
+
+ # Newer rails depends on Bundler, while ancient Rails does not. Bundler tries
+ # a first resolution pass that does not consider pre-releases. However, when
+ # using a pre-release Bundler (like the .dev version), that results in that
+ # pre-release being ignored and resolving to a version that does not depend on
+ # Bundler at all. We should avoid that and still consider .dev Bundler.
+ #
+ it "does not ignore prereleases with there's only one candidate" do
+ build_repo4 do
+ build_gem "rails", "7.4.0.2" do |s|
+ s.add_dependency "bundler", ">= 1.15.0"
+ end
+
+ build_gem "rails", "2.3.18"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rails"
+ G
+
+ bundle "lock"
+ expect(lockfile).to_not include("rails (2.3.18)")
+ expect(lockfile).to include("rails (7.4.0.2)")
+ end
+
+ it "deals with platform specific incompatibilities" do
+ build_repo4 do
+ build_gem "activerecord", "6.0.6"
+ build_gem "activerecord-jdbc-adapter", "60.4" do |s|
+ s.platform = "java"
+ s.add_dependency "activerecord", "~> 6.0.0"
+ end
+ build_gem "activerecord-jdbc-adapter", "61.0" do |s|
+ s.platform = "java"
+ s.add_dependency "activerecord", "~> 6.1.0"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "activerecord", "6.0.6"
+ gem "activerecord-jdbc-adapter", "61.0"
+ G
+
+ simulate_platform "universal-java-19" do
+ bundle "lock", :raise_on_error => false
+ end
+
+ expect(err).to include("Could not find compatible versions")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+ end
+
+ context "when re-resolving to include prereleases" do
+ before do
+ build_repo4 do
+ build_gem "tzinfo-data", "1.2022.7"
+ build_gem "rails", "7.1.0.alpha" do |s|
+ s.add_dependency "activesupport"
+ end
+ build_gem "activesupport", "7.1.0.alpha"
+ end
+ end
+
+ it "does not end up including gems scoped to other platforms in the lockfile" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rails"
+ gem "tzinfo-data", platform: :windows
+ G
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "lock"
+ end
+
+ expect(lockfile).not_to include("tzinfo-data (1.2022.7)")
+ end
+ end
+
+ context "when resolving platform specific gems as indirect dependencies on truffleruby", :truffleruby_only do
+ before do
+ build_lib "foo", :path => bundled_app do |s|
+ s.add_dependency "nokogiri"
+ end
+
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gemspec
+ G
+ end
+
+ it "locks ruby specs" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock"
+ end
+
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: .
+ specs:
+ foo (1.0)
+ nokogiri
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.2)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when adding a new gem that requires unlocking other transitive deps" do
+ before do
+ build_repo4 do
+ build_gem "govuk_app_config", "0.1.0"
+
+ build_gem "govuk_app_config", "4.13.0" do |s|
+ s.add_dependency "railties", ">= 5.0"
+ end
+
+ %w[7.0.4.1 7.0.4.3].each do |v|
+ build_gem "railties", v do |s|
+ s.add_dependency "actionpack", v
+ s.add_dependency "activesupport", v
+ end
+
+ build_gem "activesupport", v
+ build_gem "actionpack", v
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "govuk_app_config"
+ gem "activesupport", "7.0.4.3"
+ G
+
+ # Simulate out of sync lockfile because top level dependency on
+ # activesuport has just been added to the Gemfile, and locked to a higher
+ # version
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ actionpack (7.0.4.1)
+ activesupport (7.0.4.1)
+ govuk_app_config (4.13.0)
+ railties (>= 5.0)
+ railties (7.0.4.1)
+ actionpack (= 7.0.4.1)
+ activesupport (= 7.0.4.1)
+
+ PLATFORMS
+ arm64-darwin-22
+
+ DEPENDENCIES
+ govuk_app_config
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "does not downgrade top level dependencies" do
+ simulate_platform "arm64-darwin-22" do
+ bundle "lock"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ actionpack (7.0.4.3)
+ activesupport (7.0.4.3)
+ govuk_app_config (4.13.0)
+ railties (>= 5.0)
+ railties (7.0.4.3)
+ actionpack (= 7.0.4.3)
+ activesupport (= 7.0.4.3)
+
+ PLATFORMS
+ arm64-darwin-22
+
+ DEPENDENCIES
+ activesupport (= 7.0.4.3)
+ govuk_app_config
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
end
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 56fea008ec..ede1ff6b8e 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -28,6 +28,10 @@ RSpec.describe "bundle gem" do
let(:require_path) { "mygem" }
+ let(:minitest_test_file_path) { "test/test_mygem.rb" }
+
+ let(:minitest_test_class_name) { "class TestMygem < Minitest::Test" }
+
before do
sys_exec("git config --global user.name 'Bundler User'")
sys_exec("git config --global user.email user@example.com")
@@ -35,36 +39,32 @@ RSpec.describe "bundle gem" do
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", :readline 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", :readline 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
@@ -310,30 +310,30 @@ RSpec.describe "bundle gem" do
expect(last_command).to be_success
end
- it "has no rubocop offenses when using --ext and --linter=rubocop flag", :readline do
+ it "has no rubocop offenses when using --ext=c 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 "gem #{gem_name} --ext=c --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
+ it "has no rubocop offenses when using --ext=c, --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 "gem #{gem_name} --ext=c --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
+ it "has no rubocop offenses when using --ext=c, --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 "gem #{gem_name} --ext=c --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
+ it "has no rubocop offenses when using --ext=c, --test=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 "gem #{gem_name} --ext=c --test=test-unit --linter=rubocop"
bundle_exec_rubocop
expect(last_command).to be_success
end
@@ -345,10 +345,45 @@ RSpec.describe "bundle gem" do
expect(last_command).to be_success
end
+ it "has no rubocop offenses when using --ext=rust 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?
+ skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
+
+ bundle "gem #{gem_name} --ext=rust --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust, --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?
+ skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
+
+ bundle "gem #{gem_name} --ext=rust --test=minitest --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust, --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?
+ skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
+
+ bundle "gem #{gem_name} --ext=rust --test=rspec --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext=rust, --test=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?
+ skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
+
+ bundle "gem #{gem_name} --ext=rust --test=test-unit --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
shared_examples_for "CI config is absent" do
it "does not create any CI files" do
expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
- expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist
expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
end
@@ -517,6 +552,7 @@ RSpec.describe "bundle gem" do
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
@@ -533,6 +569,12 @@ RSpec.describe "bundle gem" do
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}"
@@ -567,13 +609,13 @@ RSpec.describe "bundle gem" do
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}"
- expect(generated_gemspec.required_ruby_version).to eq(Gem::Requirement.new(Gem.ruby_version < Gem::Version.new("2.4.a") ? ">= 2.3.0" : ">= 2.4.0"))
+ expect(generated_gemspec.required_ruby_version.to_s).to start_with(">=")
end
it "requires the version file" do
@@ -588,6 +630,22 @@ RSpec.describe "bundle gem" do
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(bundled_app(gem_name), gem_name).gemspec
+
+ expect(bundler_gemspec.files).not_to include("#{gem_name}.gemspec")
+ end
+
+ it "does not include the Gemfile file in files" do
+ bundle "gem #{gem_name}"
+
+ bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+
+ expect(bundler_gemspec.files).not_to include("Gemfile")
+ end
+
it "runs rake without problems" do
bundle "gem #{gem_name}"
@@ -691,7 +749,7 @@ RSpec.describe "bundle gem" do
end
it "builds spec skeleton" do
- expect(bundled_app("#{gem_name}/test/test_#{require_path}.rb")).to exist
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist
expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
end
end
@@ -711,7 +769,7 @@ RSpec.describe "bundle gem" do
end
it "builds spec skeleton" do
- expect(bundled_app("#{gem_name}/test/test_#{require_path}.rb")).to exist
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist
expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
end
@@ -720,11 +778,15 @@ RSpec.describe "bundle gem" do
end
it "requires 'test_helper'" do
- expect(bundled_app("#{gem_name}/test/test_#{require_path}.rb").read).to include(%(require "test_helper"))
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(%(require "test_helper"))
+ end
+
+ it "defines valid test class name" do
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(minitest_test_class_name)
end
it "creates a default test which fails" do
- expect(bundled_app("#{gem_name}/test/test_#{require_path}.rb").read).to include("assert false")
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include("assert false")
end
end
@@ -869,12 +931,29 @@ RSpec.describe "bundle gem" 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 travis" do
+ it "generates a GitHub Actions config file" do
+ bundle "gem #{gem_name} --ci=travis", :raise_on_error => false
+ expect(err).to include("Support for Travis CI was removed from gem skeleton generator.")
+
+ expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist
+ end
+ end
+
+ context "--ci set to travis" do
+ it "generates a GitHub Actions config file" do
+ bundle "gem #{gem_name} --ci=travis", :raise_on_error => false
+ expect(err).to include("Support for Travis CI was removed from gem skeleton generator.")
+
+ expect(bundled_app("#{gem_name}/.travis.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"
@@ -899,38 +978,32 @@ RSpec.describe "bundle gem" do
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}"
+ context "gem.ci setting set to travis" do
+ it "errors with friendly message" do
+ bundle "config set gem.ci travis"
+ bundle "gem #{gem_name}", :raise_on_error => false
- expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ expect(err).to include("Support for Travis CI was removed from gem skeleton generator,")
+ expect(err).to include("bundle config unset gem.ci")
+
+ expect(bundled_app("#{gem_name}/.travis.yml")).to_not 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"
+ 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}/.travis.yml")).to exist
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
end
end
@@ -1289,6 +1362,10 @@ RSpec.describe "bundle gem" do
let(:require_relative_path) { "test_gem" }
+ let(:minitest_test_file_path) { "test/test_test_gem.rb" }
+
+ let(:minitest_test_class_name) { "class TestTestGem < Minitest::Test" }
+
let(:flags) { nil }
it "does not nest constants" do
@@ -1299,21 +1376,46 @@ RSpec.describe "bundle gem" do
include_examples "generating a gem"
- context "--ext parameter set" do
- let(:flags) { "--ext" }
+ context "--ext parameter with no value" do
+ context "is deprecated", :bundler => "< 3" do
+ it "prints deprecation when used after gem name" do
+ bundle ["gem", "--ext", gem_name].compact.join(" ")
+ expect(err).to include "[DEPRECATED]"
+ expect(err).to include "`--ext` with no arguments has been deprecated"
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
+ end
+
+ it "prints deprecation when used before gem name" do
+ bundle ["gem", gem_name, "--ext"].compact.join(" ")
+ expect(err).to include "[DEPRECATED]"
+ expect(err).to include "`--ext` with no arguments has been deprecated"
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
+ end
+ end
+ end
+
+ context "--ext parameter set with C" do
+ let(:flags) { "--ext=c" }
before do
bundle ["gem", gem_name, flags].compact.join(" ")
end
+ it "is not deprecated" do
+ expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated."
+ end
+
it "builds ext skeleton" do
expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.h")).to exist
expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
end
- it "includes rake-compiler" do
+ it "includes rake-compiler, but no Rust related changes" do
expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
+
+ expect(bundled_app("#{gem_name}/Gemfile").read).to_not include('gem "rb_sys"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.required_rubygems_version = ">= ')
end
it "depends on compile task for build" do
@@ -1335,6 +1437,64 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
end
+
+ context "--ext parameter set with rust and old RubyGems" do
+ it "fails in friendly way" do
+ if ::Gem::Version.new("3.3.11") <= ::Gem.rubygems_version
+ skip "RubyGems compatible with Rust builder"
+ end
+
+ expect do
+ bundle ["gem", gem_name, "--ext=rust"].compact.join(" ")
+ end.to raise_error(RuntimeError, /too old to build Rust extension/)
+ end
+ end
+
+ context "--ext parameter set with rust" do
+ let(:flags) { "--ext=rust" }
+
+ before do
+ skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
+
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ end
+
+ it "is not deprecated" do
+ expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated."
+ end
+
+ it "builds ext skeleton" do
+ expect(bundled_app("#{gem_name}/Cargo.toml")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/Cargo.toml")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/src/lib.rs")).to exist
+ end
+
+ it "includes rake-compiler, rb_sys gems and required_rubygems_version constraint" do
+ expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
+ expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rb_sys"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.required_rubygems_version = ">= ')
+ end
+
+ it "depends on compile task for build" do
+ rakefile = strip_whitespace <<-RAKEFILE
+ # frozen_string_literal: true
+
+ require "bundler/gem_tasks"
+ require "rb_sys/extensiontask"
+
+ task build: :compile
+
+ RbSys::ExtensionTask.new("#{gem_name}") do |ext|
+ ext.lib_dir = "lib/#{gem_name}"
+ end
+
+ task default: :compile
+ RAKEFILE
+
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
+ end
+ end
end
context "gem naming with dashed", :readline do
@@ -1344,6 +1504,10 @@ RSpec.describe "bundle gem" do
let(:require_relative_path) { "gem" }
+ let(:minitest_test_file_path) { "test/test/test_gem.rb" }
+
+ let(:minitest_test_class_name) { "class Test::TestGem < Minitest::Test" }
+
it "nests constants so they work" do
bundle "gem #{gem_name}"
expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module Test\n module Gem/)
diff --git a/spec/bundler/commands/open_spec.rb b/spec/bundler/commands/open_spec.rb
index 53dc35c2c7..e30ebfea5b 100644
--- a/spec/bundler/commands/open_spec.rb
+++ b/spec/bundler/commands/open_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe "bundle open" do
it "does not blow up if the gem to open does not have a Gemfile" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -58,6 +58,64 @@ RSpec.describe "bundle open" do
expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2")}")
end
+ it "opens subpath of the gem" do
+ bundle "open activerecord --path lib/activerecord", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/activerecord")
+ end
+
+ it "opens subpath file of the gem" do
+ bundle "open activerecord --path lib/version.rb", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/version.rb")
+ end
+
+ it "opens deep subpath of the gem" do
+ bundle "open activerecord --path lib/active_record", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/active_record")
+ end
+
+ it "requires value for --path arg" do
+ bundle "open activerecord --path", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false
+ expect(err).to eq "Cannot specify `--path` option without a value"
+ end
+
+ it "suggests alternatives for similar-sounding gems when using subpath" do
+ bundle "open Rails --path README.md", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false
+ expect(err).to match(/did you mean rails\?/i)
+ end
+
+ it "suggests alternatives for similar-sounding gems when using deep subpath" do
+ bundle "open Rails --path some/path/here", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false
+ expect(err).to match(/did you mean rails\?/i)
+ end
+
+ it "opens subpath of the short worded gem" do
+ bundle "open rec --path CHANGELOG.md", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/CHANGELOG.md")
+ end
+
+ it "opens deep subpath of the short worded gem" do
+ bundle "open rec --path lib/activerecord", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ expect(out).to include("editor #{default_bundle_path("gems", "activerecord-2.3.2")}/lib/activerecord")
+ end
+
+ it "opens subpath of the selected matching gem", :readline do
+ env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ bundle "open active --path CHANGELOG.md", :env => env do |input, _, _|
+ input.puts "2"
+ end
+
+ expect(out).to match(%r{bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}/CHANGELOG\.md\z})
+ end
+
+ it "opens deep subpath of the selected matching gem", :readline do
+ env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
+ bundle "open active --path lib/activerecord/version.rb", :env => env do |input, _, _|
+ input.puts "2"
+ end
+
+ expect(out).to match(%r{bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}/lib/activerecord/version\.rb\z})
+ end
+
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, _, _|
diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb
index 731d67af1b..bbc3cb54ae 100644
--- a/spec/bundler/commands/outdated_spec.rb
+++ b/spec/bundler/commands/outdated_spec.rb
@@ -192,7 +192,7 @@ RSpec.describe "bundle outdated" do
vcr (6.0.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
dotenv
@@ -570,8 +570,7 @@ RSpec.describe "bundle outdated" do
end
end
- filter_strict_option = Bundler.feature_flag.bundler_2_mode? ? :"filter-strict" : :strict
- describe "with --#{filter_strict_option} option" do
+ describe "with --filter-strict option" do
before do
build_repo2 do
build_git "foo", :path => lib_path("foo")
@@ -595,7 +594,23 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.0.5"
end
- bundle :outdated, filter_strict_option => true, :raise_on_error => false
+ bundle :outdated, :"filter-strict" => 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 "only reports gems that have a newer version that matches the specified dependency version requirements, using --strict alias" do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ build_gem "weakling", "0.0.5"
+ end
+
+ bundle :outdated, :strict => true, :raise_on_error => false
expected_output = <<~TABLE.strip
Gem Current Latest Requested Groups
@@ -611,7 +626,7 @@ RSpec.describe "bundle outdated" do
gem "activesupport", platforms: [:ruby_22]
G
- bundle :outdated, filter_strict_option => true
+ bundle :outdated, :"filter-strict" => true
expect(out).to end_with("Bundle up to date!")
end
@@ -622,7 +637,7 @@ RSpec.describe "bundle outdated" do
gem "rack_middleware", "1.0"
G
- bundle :outdated, filter_strict_option => true
+ bundle :outdated, :"filter-strict" => true
expect(out).to end_with("Bundle up to date!")
end
@@ -640,7 +655,7 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.0.5"
end
- bundle :outdated, filter_strict_option => true, "filter-patch" => true, :raise_on_error => false
+ bundle :outdated, :"filter-strict" => true, "filter-patch" => true, :raise_on_error => false
expected_output = <<~TABLE.strip
Gem Current Latest Requested Groups
@@ -662,7 +677,7 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.1.5"
end
- bundle :outdated, filter_strict_option => true, "filter-minor" => true, :raise_on_error => false
+ bundle :outdated, :"filter-strict" => true, "filter-minor" => true, :raise_on_error => false
expected_output = <<~TABLE.strip
Gem Current Latest Requested Groups
@@ -684,7 +699,7 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "1.1.5"
end
- bundle :outdated, filter_strict_option => true, "filter-major" => true, :raise_on_error => false
+ bundle :outdated, :"filter-strict" => true, "filter-major" => true, :raise_on_error => false
expected_output = <<~TABLE.strip
Gem Current Latest Requested Groups
@@ -822,7 +837,7 @@ RSpec.describe "bundle outdated" do
expect(out).to end_with("Bundle up to date!")
end
- it "reports that updates are available if the JRuby platform is used", :jruby do
+ it "reports that updates are available if the JRuby platform is used", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
@@ -1099,116 +1114,125 @@ RSpec.describe "bundle outdated" do
end
context "conservative updates" do
- context "without update-strict" do
- before do
- build_repo4 do
- build_gem "patch", %w[1.0.0 1.0.1]
- build_gem "minor", %w[1.0.0 1.0.1 1.1.0]
- build_gem "major", %w[1.0.0 1.0.1 1.1.0 2.0.0]
- end
+ before do
+ build_repo4 do
+ build_gem "patch", %w[1.0.0 1.0.1]
+ build_gem "minor", %w[1.0.0 1.0.1 1.1.0]
+ build_gem "major", %w[1.0.0 1.0.1 1.1.0 2.0.0]
+ end
- # 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'
- G
+ # 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'
+ 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'
- G
- end
+ # remove all version requirements
+ gemfile <<-G
+ 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"
+ it "shows nothing when patching and filtering to minor" do
+ bundle "outdated --patch --filter-minor"
- expect(out).to end_with("No minor updates to display.")
- end
+ 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", :raise_on_error => false
+ it "shows all gems when patching and filtering to patch" do
+ 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
+ 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 end_with(expected_output)
- end
+ 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", :raise_on_error => false
+ it "shows minor and major when updating to minor and filtering to patch and minor" do
+ bundle "outdated --minor --filter-minor", :raise_on_error => false
- 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
+ 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
+ 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", :raise_on_error => false
+ it "shows minor when updating to major and filtering to minor with parseable" do
+ bundle "outdated --major --filter-minor --parseable", :raise_on_error => false
- expect(out).not_to include("patch (newest")
- expect(out).to include("minor (newest")
- expect(out).not_to include("major (newest")
- end
+ expect(out).not_to include("patch (newest")
+ expect(out).to include("minor (newest")
+ expect(out).not_to include("major (newest")
end
+ end
- context "with update-strict" do
- before do
- build_repo4 do
- build_gem "foo", %w[1.4.3 1.4.4] do |s|
- s.add_dependency "bar", "~> 2.0"
- end
- build_gem "foo", %w[1.4.5 1.5.0] do |s|
- s.add_dependency "bar", "~> 2.1"
- end
- build_gem "foo", %w[1.5.1] do |s|
- s.add_dependency "bar", "~> 3.0"
- end
- build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
- build_gem "qux", %w[1.0.0 1.1.0 2.0.0]
+ context "tricky conservative updates" do
+ before do
+ build_repo4 do
+ build_gem "foo", %w[1.4.3 1.4.4] do |s|
+ s.add_dependency "bar", "~> 2.0"
+ end
+ build_gem "foo", %w[1.4.5 1.5.0] do |s|
+ s.add_dependency "bar", "~> 2.1"
end
+ build_gem "foo", %w[1.5.1] do |s|
+ s.add_dependency "bar", "~> 3.0"
+ end
+ build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
+ build_gem "qux", %w[1.0.0 1.1.0 2.0.0]
+ end
- # establish a lockfile set to 1.4.3
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem 'foo', '1.4.3'
- gem 'bar', '2.0.3'
- gem 'qux', '1.0.0'
- G
+ # establish a lockfile set to 1.4.3
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'foo', '1.4.3'
+ gem 'bar', '2.0.3'
+ gem 'qux', '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 'foo'
- gem 'qux'
- G
- end
+ # remove 1.4.3 requirement and bar altogether
+ # to setup update specs below
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'foo'
+ gem 'qux'
+ G
+ end
- it "shows gems with update-strict updating to patch and filtering to patch" do
- bundle "outdated --patch --update-strict --filter-patch", :raise_on_error => false
+ it "shows gems updating to patch and filtering to patch" do
+ bundle "outdated --patch --filter-patch", :raise_on_error => false, :env => { "DEBUG_RESOLVER" => "1" }
- 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
+ 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
+ expect(out).to end_with(expected_output)
+ end
+
+ it "shows gems updating to patch and filtering to patch, in debug mode" do
+ bundle "outdated --patch --filter-patch", :raise_on_error => false, :env => { "DEBUG" => "1" }
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Path
+ 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
diff --git a/spec/bundler/other/platform_spec.rb b/spec/bundler/commands/platform_spec.rb
index 5693d6bce6..688bf7b6df 100644
--- a/spec/bundler/other/platform_spec.rb
+++ b/spec/bundler/commands/platform_spec.rb
@@ -2,10 +2,6 @@
RSpec.describe "bundle platform" do
context "without flags" do
- let(:bundle_platform_platforms_string) do
- local_platforms.reverse.map {|pl| "* #{pl}" }.join("\n")
- end
-
it "returns all the output" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -17,13 +13,13 @@ RSpec.describe "bundle platform" do
bundle "platform"
expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
+Your platform is: #{Gem::Platform.local}
Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
+* #{local_platform}
Your Gemfile specifies a Ruby version requirement:
-* ruby #{RUBY_VERSION}
+* ruby #{Gem.ruby_version}
Your current platform satisfies the Ruby version requirement.
G
@@ -40,13 +36,13 @@ G
bundle "platform"
expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
+Your platform is: #{Gem::Platform.local}
Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
+* #{local_platform}
Your Gemfile specifies a Ruby version requirement:
-* ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
+* #{Bundler::RubyVersion.system.single_version_string}
Your current platform satisfies the Ruby version requirement.
G
@@ -61,10 +57,10 @@ G
bundle "platform"
expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
+Your platform is: #{Gem::Platform.local}
Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
+* #{local_platform}
Your Gemfile does not specify a Ruby version requirement.
G
@@ -81,15 +77,15 @@ G
bundle "platform"
expect(out).to eq(<<-G.chomp)
-Your platform is: #{RUBY_PLATFORM}
+Your platform is: #{Gem::Platform.local}
Your app has gems that work on these platforms:
-#{bundle_platform_platforms_string}
+* #{local_platform}
Your Gemfile specifies a Ruby version requirement:
* ruby #{not_local_ruby_version}
-Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}
+Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified #{not_local_ruby_version}
G
end
end
@@ -235,7 +231,30 @@ G
L
bundle "platform --ruby"
- expect(out).to eq("ruby 1.0.0p127")
+ expect(out).to eq("ruby 1.0.0")
+ end
+
+ it "handles when there is a lockfile with no requirement" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "platform --ruby"
+ expect(out).to eq("No ruby version specified")
end
it "handles when there is a requirement in the gemfile" do
@@ -259,18 +278,18 @@ G
end
end
- let(:ruby_version_correct) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{local_engine_version}\"" }
- let(:ruby_version_correct_engineless) { "ruby \"#{RUBY_VERSION}\"" }
+ let(:ruby_version_correct) { "ruby \"#{Gem.ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{local_engine_version}\"" }
+ let(:ruby_version_correct_engineless) { "ruby \"#{Gem.ruby_version}\"" }
let(:ruby_version_correct_patchlevel) { "#{ruby_version_correct}, :patchlevel => '#{RUBY_PATCHLEVEL}'" }
let(:ruby_version_incorrect) { "ruby \"#{not_local_ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_ruby_version}\"" }
- let(:engine_incorrect) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{not_local_tag}\", :engine_version => \"#{RUBY_VERSION}\"" }
- let(:engine_version_incorrect) { "ruby \"#{RUBY_VERSION}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_engine_version}\"" }
+ let(:engine_incorrect) { "ruby \"#{Gem.ruby_version}\", :engine => \"#{not_local_tag}\", :engine_version => \"#{Gem.ruby_version}\"" }
+ let(:engine_version_incorrect) { "ruby \"#{Gem.ruby_version}\", :engine => \"#{local_ruby_engine}\", :engine_version => \"#{not_local_engine_version}\"" }
let(:patchlevel_incorrect) { "#{ruby_version_correct}, :patchlevel => '#{not_local_patchlevel}'" }
let(:patchlevel_fixnum) { "#{ruby_version_correct}, :patchlevel => #{RUBY_PATCHLEVEL}1" }
def should_be_ruby_version_incorrect
expect(exitstatus).to eq(18)
- expect(err).to be_include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}")
+ expect(err).to be_include("Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified #{not_local_ruby_version}")
end
def should_be_engine_incorrect
@@ -305,7 +324,7 @@ G
expect(bundled_app_lock).to exist
end
- it "installs fine with any engine", :jruby do
+ it "installs fine with any engine", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -351,7 +370,7 @@ G
should_be_engine_incorrect
end
- it "doesn't install when engine version doesn't match", :jruby do
+ it "doesn't install when engine version doesn't match", :jruby_only do
install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -394,7 +413,7 @@ G
expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/)
end
- it "checks fine with any engine", :jruby do
+ it "checks fine with any engine", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -445,7 +464,7 @@ G
should_be_engine_incorrect
end
- it "fails when engine version doesn't match", :jruby do
+ it "fails when engine version doesn't match", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -511,7 +530,7 @@ G
expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
end
- it "updates fine with any engine", :jruby do
+ it "updates fine with any engine", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
@@ -547,7 +566,7 @@ G
should_be_ruby_version_incorrect
end
- it "fails when ruby engine doesn't match", :jruby do
+ it "fails when ruby engine doesn't match", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
@@ -563,7 +582,7 @@ G
should_be_engine_incorrect
end
- it "fails when ruby engine version doesn't match", :jruby do
+ it "fails when ruby engine version doesn't match", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
@@ -615,7 +634,7 @@ 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", :jruby do
+ it "prints path if ruby version is correct for any engine", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
@@ -651,7 +670,7 @@ G
should_be_engine_incorrect
end
- it "fails if engine version doesn't match", :bundler => "< 3", :jruby => true do
+ it "fails if engine version doesn't match", :bundler => "< 3", :jruby_only => true do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
@@ -699,7 +718,7 @@ 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", :jruby do
+ it "copies the .gem file to vendor/cache when ruby version matches for any engine", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
@@ -735,7 +754,7 @@ G
should_be_engine_incorrect
end
- it "fails if the engine version doesn't match", :jruby do
+ it "fails if the engine version doesn't match", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
@@ -780,7 +799,7 @@ 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", :jruby do
+ it "copies the .gem file to vendor/cache when ruby version matches any engine", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
@@ -816,7 +835,7 @@ G
should_be_engine_incorrect
end
- it "fails if the engine version doesn't match", :jruby do
+ it "fails if the engine version doesn't match", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
@@ -859,7 +878,7 @@ G
expect(out).to include("0.9.1")
end
- it "activates the correct gem when ruby version matches any engine", :jruby do
+ it "activates the correct gem when ruby version matches any engine", :jruby_only do
system_gems "rack-1.0.0", "rack-0.9.1", :path => default_bundle_path
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -896,7 +915,7 @@ G
should_be_engine_incorrect
end
- # it "fails when the engine version doesn't match", :jruby do
+ # it "fails when the engine version doesn't match", :jruby_only do
# gemfile <<-G
# gem "rack", "0.9.1"
#
@@ -947,7 +966,7 @@ G
expect(out).to include("0.9.1")
end
- it "starts IRB with the default group loaded when ruby version matches", :readline, :jruby do
+ it "starts IRB with the default group loaded when ruby version matches", :readline, :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -992,7 +1011,7 @@ G
should_be_engine_incorrect
end
- it "fails when engine version doesn't match", :jruby do
+ it "fails when engine version doesn't match", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -1047,7 +1066,7 @@ G
expect(bundled_app_lock).to exist
end
- it "makes a Gemfile.lock if setup succeeds for any engine", :jruby do
+ it "makes a Gemfile.lock if setup succeeds for any engine", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "yard"
@@ -1096,7 +1115,7 @@ G
should_be_engine_incorrect
end
- it "fails when engine version doesn't match", :jruby do
+ it "fails when engine version doesn't match", :jruby_only do
install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "yard"
@@ -1169,7 +1188,7 @@ G
expect(out).to match(Regexp.new(expected_output))
end
- it "returns list of outdated gems when the ruby version matches for any engine", :jruby do
+ it "returns list of outdated gems when the ruby version matches for any engine", :jruby_only do
bundle :install
update_repo2 do
build_gem "activesupport", "3.0"
@@ -1231,7 +1250,7 @@ G
should_be_engine_incorrect
end
- it "fails when the engine version doesn't match", :jruby do
+ it "fails when the engine version doesn't match", :jruby_only do
update_repo2 do
build_gem "activesupport", "3.0"
update_git "foo", :path => lib_path("foo")
@@ -1249,7 +1268,7 @@ G
should_be_engine_version_incorrect
end
- it "fails when the patchlevel doesn't match", :jruby do
+ it "fails when the patchlevel doesn't match", :jruby_only do
update_repo2 do
build_gem "activesupport", "3.0"
update_git "foo", :path => lib_path("foo")
@@ -1267,7 +1286,7 @@ G
should_be_patchlevel_incorrect
end
- it "fails when the patchlevel is a fixnum", :jruby do
+ it "fails when the patchlevel is a fixnum", :jruby_only do
update_repo2 do
build_gem "activesupport", "3.0"
update_git "foo", :path => lib_path("foo")
diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb
index 72f8020b44..3050b87754 100644
--- a/spec/bundler/commands/post_bundle_message_spec.rb
+++ b/spec/bundler/commands/post_bundle_message_spec.rb
@@ -121,7 +121,6 @@ RSpec.describe "post bundle message" do
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
diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb
index 2f730bd4e2..9e496dc91a 100644
--- a/spec/bundler/commands/pristine_spec.rb
+++ b/spec/bundler/commands/pristine_spec.rb
@@ -2,7 +2,7 @@
require "bundler/vendored_fileutils"
-RSpec.describe "bundle pristine", :ruby_repo do
+RSpec.describe "bundle pristine" do
before :each do
build_lib "baz", :path => bundled_app do |s|
s.version = "1.0.0"
@@ -22,7 +22,7 @@ RSpec.describe "bundle pristine", :ruby_repo do
source "#{file_uri_for(gem_repo2)}"
gem "weakling"
gem "very_simple_binary"
- gem "foo", :git => "#{lib_path("foo")}", :branch => "master"
+ gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
gem "git_with_ext", :git => "#{lib_path("git_with_ext")}"
gem "bar", :path => "#{lib_path("bar")}"
diff --git a/spec/bundler/commands/remove_spec.rb b/spec/bundler/commands/remove_spec.rb
index 170545f80c..d757e0be4b 100644
--- a/spec/bundler/commands/remove_spec.rb
+++ b/spec/bundler/commands/remove_spec.rb
@@ -13,7 +13,37 @@ RSpec.describe "bundle remove" do
end
end
- context "when --install flag is specified" do
+ context "after 'bundle install' is run" do
+ describe "running 'bundle remove GEM_NAME'" do
+ it "removes it from the lockfile" do
+ rack_dep = <<~L
+
+ DEPENDENCIES
+ rack
+
+ L
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "rack"
+ G
+
+ bundle "install"
+
+ expect(lockfile).to include(rack_dep)
+
+ bundle "remove rack"
+
+ expect(gemfile).to eq <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ G
+ expect(lockfile).to_not include(rack_dep)
+ end
+ end
+ end
+
+ context "when --install flag is specified", :bundler => "< 3" do
it "removes gems from .bundle" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -40,27 +70,30 @@ RSpec.describe "bundle remove" do
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: 'https://github.com/rack/rack',
- branch: 'master'
+ git: "#{lib_path("rack-1.0")}",
+ branch: 'main'
gem 'nokogiri'
G
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)}'
gem 'git'
@@ -97,7 +130,7 @@ RSpec.describe "bundle remove" do
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
@@ -116,7 +149,7 @@ RSpec.describe "bundle remove" do
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(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
@@ -138,7 +171,7 @@ RSpec.describe "bundle remove" do
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
@@ -158,7 +191,7 @@ RSpec.describe "bundle remove" do
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
@@ -178,7 +211,7 @@ RSpec.describe "bundle remove" do
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
@@ -204,7 +237,7 @@ RSpec.describe "bundle remove" do
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
@@ -223,7 +256,7 @@ RSpec.describe "bundle remove" do
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
@@ -246,7 +279,7 @@ RSpec.describe "bundle remove" do
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
@@ -269,7 +302,7 @@ RSpec.describe "bundle remove" do
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
@@ -292,7 +325,7 @@ RSpec.describe "bundle remove" do
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
@@ -319,7 +352,7 @@ RSpec.describe "bundle remove" do
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
@@ -343,7 +376,7 @@ RSpec.describe "bundle remove" do
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
@@ -365,7 +398,7 @@ RSpec.describe "bundle remove" do
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"
@@ -397,7 +430,7 @@ RSpec.describe "bundle remove" do
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"
@@ -481,7 +514,7 @@ RSpec.describe "bundle remove" do
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"
@@ -489,7 +522,7 @@ RSpec.describe "bundle remove" do
end
end
- context "when gems can not be removed from other gemfile" do
+ context "when gems cannot be removed from other gemfile" do
it "shows error" do
create_file "Gemfile-other", <<-G
gem "rails"; gem "rack"
@@ -506,7 +539,7 @@ RSpec.describe "bundle remove" do
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"
@@ -531,7 +564,7 @@ RSpec.describe "bundle remove" do
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"
@@ -541,7 +574,7 @@ RSpec.describe "bundle remove" do
end
context "when gem present in gemfiles but could not be removed from one from one of them" do
- it "removes gem which can be removed and shows warning for file from which it can not be removed" do
+ it "removes gem which can be removed and shows warning for file from which it cannot be removed" do
create_file "Gemfile-other", <<-G
gem "rack"
G
@@ -574,7 +607,7 @@ RSpec.describe "bundle remove" do
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
@@ -593,7 +626,7 @@ RSpec.describe "bundle remove" do
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
@@ -630,7 +663,7 @@ RSpec.describe "bundle remove" do
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)}"
# gem "rack" might be used in the future
@@ -649,7 +682,7 @@ RSpec.describe "bundle remove" do
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
@@ -668,7 +701,7 @@ RSpec.describe "bundle remove" do
expect(out).to_not include("puma was removed.")
expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem "puma" # implements interface provided by gem "rack"
G
@@ -688,7 +721,7 @@ RSpec.describe "bundle remove" do
expect(out).to include("puma was removed.")
expect(out).to_not include("rack was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb
index 2adb121616..1c6244be41 100644
--- a/spec/bundler/commands/show_spec.rb
+++ b/spec/bundler/commands/show_spec.rb
@@ -100,10 +100,10 @@ RSpec.describe "bundle show", :bundler => "< 3" do
expect(the_bundle).to include_gems "foo 1.0"
bundle :show
- expect(out).to include("foo (1.0 #{@git.ref_for("master", 6)}")
+ expect(out).to include("foo (1.0 #{@git.ref_for("main", 6)}")
end
- it "prints out branch names other than master" do
+ it "prints out branch names other than main" do
update_git "foo", :branch => "omg" do |s|
s.write "lib/foo.rb", "FOO = '1.0.omg'"
end
@@ -173,7 +173,7 @@ RSpec.describe "bundle show", :bundler => "< 3" do
G
bundle "show rac"
- expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>)?\z/)
+ expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>.*)?\z/)
end
end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index 14fe3e245b..84042709bf 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -284,7 +284,7 @@ RSpec.describe "bundle update" do
countries (~> 3.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
countries
@@ -301,6 +301,128 @@ RSpec.describe "bundle update" do
expect(lockfile).to eq(previous_lockfile)
end
+ it "does not downgrade direct dependencies when run with --conservative" do
+ build_repo4 do
+ build_gem "oauth2", "2.0.6" do |s|
+ s.add_dependency "faraday", ">= 0.17.3", "< 3.0"
+ end
+
+ build_gem "oauth2", "1.4.10" do |s|
+ s.add_dependency "faraday", ">= 0.17.3", "< 3.0"
+ s.add_dependency "multi_json", "~> 1.3"
+ end
+
+ build_gem "faraday", "2.5.2"
+
+ build_gem "multi_json", "1.15.0"
+
+ build_gem "quickbooks-ruby", "1.0.19" do |s|
+ s.add_dependency "oauth2", "~> 1.4"
+ end
+
+ build_gem "quickbooks-ruby", "0.1.9" do |s|
+ s.add_dependency "oauth2"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "oauth2"
+ gem "quickbooks-ruby"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ faraday (2.5.2)
+ multi_json (1.15.0)
+ oauth2 (1.4.10)
+ faraday (>= 0.17.3, < 3.0)
+ multi_json (~> 1.3)
+ quickbooks-ruby (1.0.19)
+ oauth2 (~> 1.4)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ oauth2
+ quickbooks-ruby
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update --conservative --verbose"
+
+ expect(out).not_to include("Installing quickbooks-ruby 0.1.9")
+ expect(out).to include("Installing quickbooks-ruby 1.0.19").and include("Installing oauth2 1.4.10")
+ end
+
+ it "does not downgrade direct dependencies when using gemspec sources" do
+ create_file("rails.gemspec", <<-G)
+ Gem::Specification.new do |gem|
+ gem.name = "rails"
+ gem.version = "7.1.0.alpha"
+ gem.author = "DHH"
+ gem.summary = "Full-stack web application framework."
+ end
+ G
+
+ build_repo4 do
+ build_gem "rake", "12.3.3"
+ build_gem "rake", "13.0.6"
+
+ build_gem "sneakers", "2.11.0" do |s|
+ s.add_dependency "rake"
+ end
+
+ build_gem "sneakers", "2.12.0" do |s|
+ s.add_dependency "rake", "~> 12.3"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gemspec
+
+ gem "rake"
+ gem "sneakers"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: .
+ specs:
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rake (13.0.6)
+ sneakers (2.11.0)
+ rake
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rake
+ sneakers
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update --verbose"
+
+ expect(out).not_to include("Installing sneakers 2.12.0")
+ expect(out).not_to include("Installing rake 12.3.3")
+ expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6")
+ end
+
it "does not downgrade indirect dependencies unnecessarily" do
build_repo4 do
build_gem "a" do |s|
@@ -354,6 +476,67 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems("a 1.0", "b 1.0")
end
+
+ it "should still downgrade if forced by the Gemfile, when transitive dependencies also need downgrade" do
+ build_repo4 do
+ build_gem "activesupport", "6.1.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 2.0"
+ end
+
+ build_gem "activesupport", "6.0.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 1.1"
+ end
+
+ build_gem "tzinfo", "2.0.4"
+ build_gem "tzinfo", "1.2.9"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "activesupport", "~> 6.1.0"
+ G
+
+ expect(the_bundle).to include_gems("activesupport 6.1.4.1", "tzinfo 2.0.4")
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "activesupport", "~> 6.0.0"
+ G
+
+ original_lockfile = lockfile
+
+ expected_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ activesupport (6.0.4.1)
+ tzinfo (~> 1.1)
+ tzinfo (1.2.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport (~> 6.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update activesupport"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+
+ lockfile original_lockfile
+ bundle "update"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+
+ lockfile original_lockfile
+ bundle "lock --update"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+ end
end
describe "with --local option" do
@@ -475,22 +658,28 @@ RSpec.describe "bundle update" do
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)
- expect(err).to match(/freeze \nby running `bundle config unset deployment`./m)
+ expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/)
+ expect(err).to match(/freeze by running `bundle config set frozen false`./)
end
- it "should suggest different command when frozen is set globally", :bundler => "< 3" do
+ it "should fail loudly when frozen is set globally" do
bundle "config set --global frozen 1"
bundle "update", :all => true, :raise_on_error => false
- expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m).
- and match(/freeze \nby running `bundle config unset frozen`./m)
+ expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/).
+ and match(/freeze by running `bundle config set frozen false`./)
end
- it "should suggest different command when frozen is set globally", :bundler => "3" do
+ it "should fail loudly when deployment is set globally" do
bundle "config set --global deployment true"
bundle "update", :all => true, :raise_on_error => false
- expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m).
- and match(/freeze \nby running `bundle config unset deployment`./m)
+ expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/).
+ and match(/freeze by running `bundle config set frozen false`./)
+ end
+
+ it "should not suggest any command to unfreeze bundler if frozen is set through ENV" do
+ bundle "update", :all => true, :raise_on_error => false, :env => { "BUNDLE_FROZEN" => "true" }
+ expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/)
+ expect(err).not_to match(/by running/)
end
end
@@ -583,7 +772,7 @@ RSpec.describe "bundle update" do
end
end
- it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do
+ it "shows the previous version of the gem when updated from rubygems source" do
build_repo2
install_gemfile <<-G
@@ -591,7 +780,7 @@ RSpec.describe "bundle update" do
gem "activesupport"
G
- bundle "update", :all => true
+ bundle "update", :all => true, :verbose => true
expect(out).to include("Using activesupport 2.3.5")
update_repo2 do
@@ -602,32 +791,28 @@ RSpec.describe "bundle update" do
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
+ it "only prints `Using` for versions that have changed" do
+ build_repo4 do
+ build_gem "bar"
+ build_gem "foo"
+ end
- bundle "update", :all => true
- expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "bar"
+ gem "foo"
+ G
- update_repo4 do
- build_gem "foo", "2.0"
- end
+ bundle "update", :all => true
+ expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
- 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/)
+ 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
it "shows error message when Gemfile.lock is not preset and gem is specified" do
@@ -682,7 +867,7 @@ RSpec.describe "bundle update" do
vcr (6.0.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
dotenv
@@ -919,27 +1104,21 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler"
end
RSpec.describe "bundle update --ruby" do
- before do
- install_gemfile <<-G
- ::RUBY_VERSION = '2.1.3'
- ::RUBY_PATCHLEVEL = 100
- ruby '~> 2.1.0'
- source "#{file_uri_for(gem_repo1)}"
- G
- end
-
context "when the Gemfile removes the ruby" do
before do
+ install_gemfile <<-G
+ ruby '~> #{Gem.ruby_version}'
+ source "#{file_uri_for(gem_repo1)}"
+ 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:
@@ -957,17 +1136,20 @@ RSpec.describe "bundle update --ruby" do
context "when the Gemfile specified an updated Ruby version" do
before do
+ install_gemfile <<-G
+ ruby '~> #{Gem.ruby_version}'
+ source "#{file_uri_for(gem_repo1)}"
+ G
+
gemfile <<-G
- ::RUBY_VERSION = '2.1.4'
- ::RUBY_PATCHLEVEL = 222
- ruby '~> 2.1.0'
+ ruby '~> #{current_ruby_minor}'
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:
@@ -978,7 +1160,7 @@ RSpec.describe "bundle update --ruby" do
DEPENDENCIES
RUBY VERSION
- ruby 2.1.4p222
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
@@ -988,9 +1170,12 @@ RSpec.describe "bundle update --ruby" do
context "when a different Ruby is being used than has been versioned" do
before do
+ install_gemfile <<-G
+ ruby '~> #{Gem.ruby_version}'
+ source "#{file_uri_for(gem_repo1)}"
+ G
+
gemfile <<-G
- ::RUBY_VERSION = '2.2.2'
- ::RUBY_PATCHLEVEL = 505
ruby '~> 2.1.0'
source "#{file_uri_for(gem_repo1)}"
G
@@ -998,23 +1183,38 @@ RSpec.describe "bundle update --ruby" do
it "shows a helpful error message" do
bundle "update --ruby", :raise_on_error => false
- expect(err).to include("Your Ruby version is 2.2.2, but your Gemfile specified ~> 2.1.0")
+ expect(err).to include("Your Ruby version is #{Bundler::RubyVersion.system.gem_version}, but your Gemfile specified ~> 2.1.0")
end
end
context "when updating Ruby version and Gemfile `ruby`" do
before do
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+
+ RUBY VERSION
+ ruby 2.1.4p222
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
gemfile <<-G
- ::RUBY_VERSION = '1.8.3'
- ::RUBY_PATCHLEVEL = 55
- ruby '~> 1.8.0'
+ ruby '~> #{Gem.ruby_version}'
source "#{file_uri_for(gem_repo1)}"
G
end
it "updates the Gemfile.lock with the latest version" do
bundle "update --ruby"
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -1025,7 +1225,7 @@ RSpec.describe "bundle update --ruby" do
DEPENDENCIES
RUBY VERSION
- ruby 1.8.3p55
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
@@ -1035,7 +1235,7 @@ RSpec.describe "bundle update --ruby" do
end
RSpec.describe "bundle update --bundler" do
- it "updates the bundler version in the lockfile without re-resolving" do
+ it "updates the bundler version in the lockfile" do
build_repo4 do
build_gem "rack", "1.0"
end
@@ -1044,15 +1244,231 @@ RSpec.describe "bundle update --bundler" do
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, :artifice => "compact_index", :verbose => true
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- bundle :update, :bundler => true, :verbose => true
expect(the_bundle).to include_gem "rack 1.0"
+ end
+
+ it "updates the bundler version in the lockfile without re-resolving if the highest version is already installed" do
+ system_gems "bundler-2.3.9"
+
+ build_repo4 do
+ build_gem "rack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ G
+ lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
+
+ bundle :update, :bundler => true, :artifice => "compact_index", :verbose => true
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ expect(the_bundle).to include_gem "rack 1.0"
+ end
+
+ it "updates the bundler version in the lockfile even if the latest version is not installed", :ruby_repo, :realworld do
+ pristine_system_gems "bundler-2.3.9"
+
+ build_repo4 do
+ build_gem "rack", "1.0"
+ end
+
+ install_gemfile <<-G, :env => { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ G
+ lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
+
+ bundle :update, :bundler => true, :artifice => "vcr", :verbose => true, :env => { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
+
+ # Only updates properly on modern RubyGems.
+
+ if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
+ expect(out).to include("Updating bundler to 2.3.10")
+ expect(out).to include("Using bundler 2.3.10")
+ expect(out).not_to include("Installing Bundler 2.3.9 and restarting using that version.")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 2.3.10
+ L
+
+ expect(the_bundle).to include_gems "bundler 2.3.10"
+ end
+
+ expect(the_bundle).to include_gems "rack 1.0"
+ end
+
+ it "errors if the explicit target version does not exist", :realworld do
+ pristine_system_gems "bundler-2.3.9"
+
+ build_repo4 do
+ build_gem "rack", "1.0"
+ end
+
+ install_gemfile <<-G, :env => { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ G
+ lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
+
+ bundle :update, :bundler => "999.999.999", :artifice => "vcr", :raise_on_error => false
+
+ # Only gives a meaningful error message on modern RubyGems.
+
+ if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
+ expect(last_command).to be_failure
+ expect(err).to include("The `bundle update --bundler` target version (999.999.999) does not exist")
+ end
+ end
+
+ it "allows updating to development versions if already installed locally" do
+ system_gems "bundler-2.3.0.dev"
+
+ build_repo4 do
+ build_gem "rack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ G
+
+ bundle :update, :bundler => "2.3.0.dev", :verbose => "true"
+
+ # Only updates properly on modern RubyGems.
- expect(the_bundle.locked_gems.bundler_version).to eq v(Bundler::VERSION)
+ if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 2.3.0.dev
+ L
+
+ expect(out).to include("Using bundler 2.3.0.dev")
+ end
+ end
+
+ it "does not touch the network if not necessary" do
+ system_gems "bundler-2.3.9"
+
+ build_repo4 do
+ build_gem "rack", "1.0"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ G
+
+ bundle :update, :bundler => "2.3.9", :raise_on_error => false, :verbose => true
+
+ expect(out).not_to include("Fetching gem metadata from https://rubygems.org/")
+
+ # Only updates properly on modern RubyGems.
+
+ if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 2.3.9
+ L
+
+ expect(out).to include("Using bundler 2.3.9")
+ end
+ end
+
+ it "prints an error when trying to update bundler in frozen mode" do
+ system_gems "bundler-2.3.9"
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ 2.1.4
+ L
+
+ bundle "update --bundler=2.3.9", :env => { "BUNDLE_FROZEN" => "true" }, :raise_on_error => false
+ expect(err).to include("An update to the version of bundler itself was requested, but the lockfile can't be updated because frozen mode is set")
end
end
@@ -1070,7 +1486,10 @@ RSpec.describe "bundle update conservative" do
build_gem "foo", %w[1.5.1] do |s|
s.add_dependency "bar", "~> 3.0"
end
- build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 3.0.0]
+ build_gem "foo", %w[2.0.0.pre] do |s|
+ s.add_dependency "bar"
+ end
+ build_gem "bar", %w[2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 2.1.2.pre 3.0.0 3.1.0.pre 4.0.0.pre]
build_gem "qux", %w[1.0.0 1.0.1 1.1.0 2.0.0]
end
@@ -1135,6 +1554,32 @@ RSpec.describe "bundle update conservative" do
expect(the_bundle).to include_gems "foo 1.5.0", "bar 2.1.1", "qux 1.1.0"
end
end
+
+ context "pre" do
+ it "defaults to major" do
+ bundle "update --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 2.0.0.pre", "bar 4.0.0.pre", "qux 1.0.0"
+ end
+
+ it "patch preferred" do
+ bundle "update --patch --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.2.pre", "qux 1.0.0"
+ end
+
+ it "minor preferred" do
+ bundle "update --minor --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 1.5.1", "bar 3.1.0.pre", "qux 1.0.0"
+ end
+
+ it "major preferred" do
+ bundle "update --major --pre foo bar"
+
+ expect(the_bundle).to include_gems "foo 2.0.0.pre", "bar 4.0.0.pre", "qux 1.0.0"
+ end
+ end
end
context "eager unlocking" do
@@ -1176,7 +1621,7 @@ RSpec.describe "bundle update conservative" do
shared_dep (~> 5.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
isolated_owner
@@ -1229,7 +1674,7 @@ RSpec.describe "bundle update conservative" do
shared_dep (~> 5.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
isolated_owner
diff --git a/spec/bundler/commands/viz_spec.rb b/spec/bundler/commands/viz_spec.rb
index 0efb24b504..cf612397ab 100644
--- a/spec/bundler/commands/viz_spec.rb
+++ b/spec/bundler/commands/viz_spec.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
-RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
+RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot"), :realworld => true do
before do
- graphviz_version = RUBY_VERSION >= "2.4" ? "1.2.5" : "1.2.4"
-
- realworld_system_gems "ruby-graphviz --version #{graphviz_version}"
+ realworld_system_gems "ruby-graphviz --version 1.2.5"
end
it "graphs gems from the Gemfile" do
diff --git a/spec/bundler/install/allow_offline_install_spec.rb b/spec/bundler/install/allow_offline_install_spec.rb
index 524363fde5..4c6c77a61e 100644
--- a/spec/bundler/install/allow_offline_install_spec.rb
+++ b/spec/bundler/install/allow_offline_install_spec.rb
@@ -53,7 +53,10 @@ RSpec.describe "bundle install with :allow_offline_install" do
File.open(tmp("broken_path/git"), "w", 0o755) do |f|
f.puts strip_whitespace(<<-RUBY)
#!/usr/bin/env ruby
- if %w(fetch --force --quiet --tags refs/heads/*:refs/heads/*).-(ARGV).empty? || %w(clone --bare --no-hardlinks --quiet).-(ARGV).empty?
+ fetch_args = %w(fetch --force --quiet)
+ clone_args = %w(clone --bare --no-hardlinks --quiet)
+
+ if (fetch_args.-(ARGV).empty? || clone_args.-(ARGV).empty?) && ARGV.any? {|arg| arg.start_with?("file://") }
warn "git remote ops have been disabled"
exit 1
end
diff --git a/spec/bundler/install/binstubs_spec.rb b/spec/bundler/install/binstubs_spec.rb
index 6961171f4f..928ba80b15 100644
--- a/spec/bundler/install/binstubs_spec.rb
+++ b/spec/bundler/install/binstubs_spec.rb
@@ -2,10 +2,8 @@
RSpec.describe "bundle install" do
describe "when system_bindir is set" do
- # On OS X, Gem.bindir defaults to /usr/bin, so system_bindir is useful if
- # you want to avoid sudo installs for system gems with OS X's default ruby
it "overrides Gem.bindir" do
- expect(Pathname.new("/usr/bin")).not_to be_writable unless Process.euid == 0
+ expect(Pathname.new("/usr/bin")).not_to be_writable
gemfile <<-G
def Gem.bindir; "/usr/bin"; end
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb
index 963ce82db8..e7ec3bc7e7 100644
--- a/spec/bundler/install/bundler_spec.rb
+++ b/spec/bundler/install/bundler_spec.rb
@@ -37,12 +37,11 @@ RSpec.describe "bundle install" do
G
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "bundler":
- In Gemfile:
- bundler (= 0.9.1)
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
+ Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.1
+ and Gemfile depends on bundler = 0.9.1,
+ version solving has failed.
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`
@@ -58,12 +57,14 @@ RSpec.describe "bundle install" do
G
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "bundler":
- In Gemfile:
- bundler (~> 0.8)
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
+ Because rails >= 3.0 depends on bundler >= 0.9.0.pre
+ and the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler >= 0.9.0.pre, < 1.A,
+ rails >= 3.0 requires bundler >= 1.A.
+ So, because Gemfile depends on rails = 3.0
+ and Gemfile depends on bundler ~> 0.8,
+ version solving has failed.
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`
@@ -79,12 +80,11 @@ RSpec.describe "bundle install" do
G
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "bundler":
- In Gemfile:
- bundler (= 0.9.2)
+ Could not find compatible versions
- Current Bundler version:
- bundler (#{Bundler::VERSION})
+ Because the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler = 0.9.2
+ and Gemfile depends on bundler = 0.9.2,
+ version solving has failed.
Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.
E
@@ -150,13 +150,14 @@ RSpec.describe "bundle install" do
G
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "activesupport":
- In Gemfile:
- activemerchant was resolved to 1.0, which depends on
- activesupport (>= 2.0.0)
-
- rails_pinned_to_old_activesupport was resolved to 1.0, which depends on
- activesupport (= 1.2.3)
+ Could not find compatible versions
+
+ Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3
+ and every version of activemerchant depends on activesupport >= 2.0.0,
+ every version of rails_pinned_to_old_activesupport is incompatible with activemerchant >= 0.
+ So, because Gemfile depends on activemerchant >= 0
+ and Gemfile depends on rails_pinned_to_old_activesupport >= 0,
+ version solving has failed.
E
expect(err).to include(nice_error)
end
@@ -177,12 +178,13 @@ RSpec.describe "bundle install" do
G
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "activesupport":
- In Gemfile:
- activesupport (= 2.3.5)
+ Could not find compatible versions
- rails_pinned_to_old_activesupport was resolved to 1.0, which depends on
- activesupport (= 1.2.3)
+ Because every version of rails_pinned_to_old_activesupport depends on activesupport = 1.2.3
+ and Gemfile depends on rails_pinned_to_old_activesupport >= 0,
+ activesupport = 1.2.3 is required.
+ So, because Gemfile depends on activesupport = 2.3.5,
+ version solving has failed.
E
expect(err).to include(nice_error)
end
@@ -208,6 +210,33 @@ RSpec.describe "bundle install" do
expect(err).to be_empty
end
+ it "prints the previous version when switching to a previously downloaded gem" do
+ build_repo4 do
+ build_gem "rails", "7.0.3"
+ build_gem "rails", "7.0.4"
+ end
+
+ bundle "config set path.system true"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'rails', "7.0.4"
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'rails', "7.0.3"
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'rails', "7.0.4"
+ G
+
+ expect(out).to include("Using rails 7.0.4 (was 7.0.3)")
+ expect(err).to be_empty
+ end
+
it "can install dependencies with newer bundler version with system gems" do
bundle "config set path.system true"
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index 8f2650a932..2a88ed5b06 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -39,6 +39,39 @@ RSpec.describe "install in deployment or frozen mode" do
bundle :install
expect(the_bundle).to include_gems "rack 1.0"
end
+
+ it "installs gems by default to vendor/bundle" do
+ bundle :lock
+ bundle "install --deployment"
+ expect(out).to include("vendor/bundle")
+ end
+
+ it "installs gems to custom path if specified" do
+ bundle :lock
+ bundle "install --path vendor/bundle2 --deployment"
+ expect(out).to include("vendor/bundle2")
+ end
+
+ it "works with the --frozen flag" do
+ bundle :lock
+ bundle "install --frozen"
+ end
+
+ it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
+ bundle :lock
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ gem "rack-obama"
+ G
+
+ bundle "install --deployment", :raise_on_error => false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have added to the Gemfile")
+ expect(err).to include("* rack-obama")
+ expect(err).not_to include("You have deleted from the Gemfile")
+ expect(err).not_to include("You have changed in the Gemfile")
+ end
end
it "still works if you are not in the app directory and specify --gemfile" do
@@ -141,7 +174,7 @@ RSpec.describe "install in deployment or frozen mode" do
rack (1.0.0)
PLATFORMS
- #{local}
+ #{generic_local_platform}
DEPENDENCIES
rack
@@ -202,29 +235,35 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "install"
end
- it "installs gems by default to vendor/bundle", :bundler => "< 3" do
- bundle "install --deployment"
+ it "installs gems by default to vendor/bundle" do
+ bundle "config set deployment true"
+ bundle "install"
expect(out).to include("vendor/bundle")
end
- it "installs gems to custom path if specified", :bundler => "< 3" do
- bundle "install --path vendor/bundle2 --deployment"
+ it "installs gems to custom path if specified" do
+ bundle "config set path vendor/bundle2"
+ bundle "config set deployment true"
+ bundle "install"
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"
+ it "installs gems to custom path if specified, even when configured through ENV" do
+ bundle "config set deployment true"
+ bundle "install", :env => { "BUNDLE_PATH" => "vendor/bundle2" }
+ expect(out).to include("vendor/bundle2")
end
- it "works with the --frozen flag if you didn't change anything", :bundler => "< 3" do
- bundle "install --frozen"
+ it "works with the `frozen` setting" do
+ bundle "config set frozen true"
+ bundle "install"
end
it "works with BUNDLE_FROZEN if you didn't change anything" do
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
+ it "explodes with the `deployment` setting if you make a change and don't check in the lockfile" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -233,7 +272,7 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
@@ -258,6 +297,55 @@ RSpec.describe "install in deployment or frozen mode" do
expect(out).to eq("WIN")
end
+ it "works if a gem is missing, but it's on a different platform" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ source "#{file_uri_for(gem_repo1)}" do
+ gem "rake", platform: :#{not_local_tag}
+ end
+ G
+
+ bundle :install, :env => { "BUNDLE_FROZEN" => "true" }
+ expect(last_command).to be_success
+ end
+
+ it "shows a good error if a gem is missing from the lockfile" do
+ build_repo4 do
+ build_gem "foo"
+ build_gem "bar"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "bar"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install, :env => { "BUNDLE_FROZEN" => "true" }, :raise_on_error => false, :artifice => "compact_index"
+ expect(err).to include("Your lock file is missing \"bar\", but the lockfile can't be updated because frozen mode is set")
+ end
+
it "explodes if a path gem is missing" do
build_lib "path_gem"
install_gemfile <<-G
@@ -274,7 +362,7 @@ RSpec.describe "install in deployment or frozen mode" do
expect(err).to include("The path `#{lib_path("path_gem-1.0")}` does not exist.")
end
- it "can have --frozen set via an environment variable", :bundler => "< 3" do
+ it "can have --frozen set via an environment variable" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -283,7 +371,7 @@ RSpec.describe "install in deployment or frozen mode" do
ENV["BUNDLE_FROZEN"] = "1"
bundle "install", :raise_on_error => false
- expect(err).to include("deployment mode")
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
@@ -299,20 +387,20 @@ RSpec.describe "install in deployment or frozen mode" do
ENV["BUNDLE_DEPLOYMENT"] = "true"
bundle "install", :raise_on_error => false
- expect(err).to include("deployment mode")
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have changed in the Gemfile")
end
- it "installs gems by default to vendor/bundle when deployment mode 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" do
ENV["BUNDLE_DEPLOYMENT"] = "true"
bundle "install"
expect(out).to include("vendor/bundle")
end
- it "installs gems to custom path when deployment mode is set via an environment variable ", :bundler => "< 3" do
+ it "installs gems to custom path when deployment mode is set via an environment variable " do
ENV["BUNDLE_DEPLOYMENT"] = "true"
ENV["BUNDLE_PATH"] = "vendor/bundle2"
bundle "install"
@@ -329,7 +417,7 @@ RSpec.describe "install in deployment or frozen mode" do
ENV["BUNDLE_FROZEN"] = "false"
ENV["BUNDLE_DEPLOYMENT"] = "false"
bundle "install"
- expect(out).not_to include("deployment mode")
+ expect(out).not_to include("frozen mode")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("* rack-obama")
end
@@ -342,7 +430,7 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
bundle :install, :raise_on_error => false
- expect(err).to include("deployment mode")
+ expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile:\n* activesupport\n\n")
expect(err).to include("You have deleted from the Gemfile:\n* rack")
expect(err).not_to include("You have changed in the Gemfile")
@@ -356,12 +444,12 @@ RSpec.describe "install in deployment or frozen mode" do
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")
- expect(err).not_to include("You have changed in the Gemfile")
+ expect(err).to include("frozen mode")
+ expect(err).not_to include("You have added to the Gemfile")
+ expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `git://hubz.com`")
end
- it "explodes if you unpin a source" do
+ it "explodes if you change a source" do
build_git "rack"
install_gemfile <<-G
@@ -376,13 +464,13 @@ RSpec.describe "install in deployment or frozen mode" do
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")}")
+ expect(err).to include("frozen mode")
+ expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have added to the Gemfile")
- expect(err).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")
@@ -400,8 +488,8 @@ RSpec.describe "install in deployment or frozen mode" do
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")}`")
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack")}` to `no specified source`")
expect(err).not_to include("You have added to the Gemfile")
expect(err).not_to include("You have deleted from the Gemfile")
end
@@ -419,7 +507,7 @@ RSpec.describe "install in deployment or frozen mode" do
run "require 'rack'", :raise_on_error => false
expect(err).to include strip_whitespace(<<-E).strip
-The dependencies in your gemfile changed
+The dependencies in your gemfile changed, but the lockfile can't be updated because frozen mode is set (Bundler::ProductionError)
You have added to the Gemfile:
* rack (= 1.0.0)
@@ -452,7 +540,7 @@ You have deleted from the Gemfile:
simulate_new_machine
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("but the lockfile can't be updated because frozen mode is set")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("You have deleted from the Gemfile")
expect(out).to include("vendor/cache/foo")
diff --git a/spec/bundler/install/gemfile/force_ruby_platform_spec.rb b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
new file mode 100644
index 0000000000..0e9f1f0292
--- /dev/null
+++ b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with force_ruby_platform DSL option", :jruby do
+ context "when no transitive deps" do
+ before do
+ build_repo4 do
+ # Build a gem with platform specific versions
+ build_gem("platform_specific") do |s|
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+
+ # Build the exact same gem with a different name to compare using vs not using the option
+ build_gem("platform_specific_forced") do |s|
+ s.write "lib/platform_specific_forced.rb", "PLATFORM_SPECIFIC_FORCED = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific_forced") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific_forced.rb", "PLATFORM_SPECIFIC_FORCED = '1.0.0 #{Bundler.local_platform}'"
+ end
+ end
+ end
+
+ it "pulls the pure ruby variant of the given gem" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "platform_specific_forced", :force_ruby_platform => true
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 #{Bundler.local_platform}"
+ end
+
+ it "still respects a global `force_ruby_platform` config" do
+ install_gemfile <<-G, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "platform_specific_forced", :force_ruby_platform => true
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ end
+ end
+
+ context "when also a transitive dependency" do
+ before do
+ build_repo4 do
+ build_gem("depends_on_platform_specific") {|s| s.add_runtime_dependency "platform_specific" }
+
+ build_gem("platform_specific") do |s|
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+ end
+ end
+
+ it "still pulls the ruby variant" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "depends_on_platform_specific"
+ gem "platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ end
+ end
+
+ context "with transitive dependencies with platform specific versions" do
+ before do
+ build_repo4 do
+ build_gem("depends_on_platform_specific") do |s|
+ s.add_runtime_dependency "platform_specific"
+ s.write "lib/depends_on_platform_specific.rb", "DEPENDS_ON_PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("depends_on_platform_specific") do |s|
+ s.add_runtime_dependency "platform_specific"
+ s.platform = Bundler.local_platform
+ s.write "lib/depends_on_platform_specific.rb", "DEPENDS_ON_PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ end
+
+ build_gem("platform_specific") do |s|
+ s.platform = Bundler.local_platform
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ end
+ end
+ end
+
+ it "ignores ruby variants for the transitive dependencies" do
+ install_gemfile <<-G, :env => { "DEBUG_RESOLVER" => "true" }
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "depends_on_platform_specific", :force_ruby_platform => true
+ G
+
+ expect(the_bundle).to include_gems "depends_on_platform_specific 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0.0 #{Bundler.local_platform}"
+ end
+ end
+end
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index 6d9cd2daff..73f04f071d 100644
--- a/spec/bundler/install/gemfile/gemspec_spec.rb
+++ b/spec/bundler/install/gemfile/gemspec_spec.rb
@@ -8,6 +8,26 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
+ let(:x64_mingw_archs) do
+ if RUBY_PLATFORM == "x64-mingw-ucrt"
+ if Gem.rubygems_version >= Gem::Version.new("3.2.28")
+ ["x64-mingw-ucrt", "x64-mingw32"]
+ else
+ ["x64-mingw32", "x64-unknown"]
+ end
+ else
+ ["x64-mingw32"]
+ end
+ end
+
+ let(:x64_mingw_gems) do
+ x64_mingw_archs.map {|p| "platform_specific (1.0-#{p})" }.join("\n ")
+ end
+
+ let(:x64_mingw_platforms) do
+ x64_mingw_archs.join("\n ")
+ end
+
it "should install runtime and development dependencies" do
build_lib("foo", :path => tmp.join("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
@@ -130,7 +150,7 @@ RSpec.describe "bundle install from an existing gemspec" do
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/)
+ expect(output).not_to match(/the lockfile can't be updated because frozen mode is set/)
end
it "should match a lockfile without needing to re-resolve" do
@@ -168,7 +188,7 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(out.scan(message).size).to eq(1)
end
- it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby do
+ it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby_only do
build_lib("foo", :path => tmp.join("foo")) do |s|
s.add_dependency "platform_specific"
end
@@ -179,7 +199,7 @@ RSpec.describe "bundle install from an existing gemspec" do
gemspec :path => '#{tmp.join("foo")}'
G
- bundle "update --bundler", :verbose => true
+ bundle "update --bundler", :artifice => "compact_index", :verbose => true
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA"
end
@@ -328,83 +348,65 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with a lockfile and some missing dependencies" do
let(:source_uri) { "http://localgemserver.test" }
- context "previously bundled for Ruby" 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
-
- gemfile <<-G
- source "#{source_uri}"
- gemspec :path => "../foo"
- G
+ before do
+ build_lib("foo", :path => tmp.join("foo")) do |s|
+ s.add_dependency "rack", "=1.0.0"
+ end
- lockfile <<-L
- PATH
- remote: ../foo
- specs:
- foo (1.0)
- rack (= 1.0.0)
+ gemfile <<-G
+ source "#{source_uri}"
+ gemspec :path => "../foo"
+ G
- GEM
- remote: #{source_uri}
- specs:
- rack (1.0.0)
+ lockfile <<-L
+ PATH
+ remote: ../foo
+ specs:
+ foo (1.0)
+ rack (= 1.0.0)
- PLATFORMS
- #{generic_local_platform}
+ GEM
+ remote: #{source_uri}
+ specs:
+ rack (1.0.0)
- DEPENDENCIES
- foo!
+ PLATFORMS
+ #{generic_local_platform}
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
+ DEPENDENCIES
+ foo!
- context "using JRuby with explicit platform", :jruby do
- before do
- create_file(
- tmp.join("foo", "foo-java.gemspec"),
- build_spec("foo", "1.0", "java") do
- dep "rack", "=1.0.0"
- @spec.authors = "authors"
- @spec.summary = "summary"
- end.first.to_ruby
- )
- end
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
- it "should install" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ context "using JRuby with explicit platform", :jruby_only do
+ before do
+ create_file(
+ tmp.join("foo", "foo-java.gemspec"),
+ build_spec("foo", "1.0", "java") do
+ dep "rack", "=1.0.0"
+ @spec.authors = "authors"
+ @spec.summary = "summary"
+ end.first.to_ruby
+ )
end
- context "using JRuby", :jruby do
- it "should install" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
+ it "should install" do
+ results = bundle "install", :artifice => "endpoint"
+ expect(results).to include("Installing rack 1.0.0")
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
+ end
- context "using Windows" do
- it "should install" do
- simulate_windows 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
- end
+ it "should install", :jruby do
+ results = bundle "install", :artifice => "endpoint"
+ expect(results).to include("Installing rack 1.0.0")
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
- context "bundled for ruby and jruby" do
+ context "bundled for multiple platforms" do
let(:platform_specific_type) { :runtime }
let(:dependency) { "platform_specific" }
before do
@@ -429,18 +431,22 @@ RSpec.describe "bundle install from an existing gemspec" do
gemspec
G
- simulate_platform("ruby") { bundle "install" }
+ bundle "config set --local force_ruby_platform true"
+ bundle "install"
+
+ simulate_new_machine
simulate_platform("jruby") { bundle "install" }
+ simulate_platform(x64_mingw32) { bundle "install" }
end
context "on ruby" do
before do
- simulate_platform("ruby")
+ bundle "config set --local force_ruby_platform true"
bundle :install
end
context "as a runtime dependency" do
- it "keeps java dependencies in the lockfile" do
+ it "keeps all platform dependencies in the lockfile" do
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
expect(lockfile).to eq strip_whitespace(<<-L)
PATH
@@ -454,10 +460,12 @@ RSpec.describe "bundle install from an existing gemspec" do
specs:
platform_specific (1.0)
platform_specific (1.0-java)
+ #{x64_mingw_gems}
PLATFORMS
java
ruby
+ #{x64_mingw_platforms}
DEPENDENCIES
foo!
@@ -471,7 +479,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "as a development dependency" do
let(:platform_specific_type) { :development }
- it "keeps java dependencies in the lockfile" do
+ it "keeps all platform dependencies in the lockfile" do
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
expect(lockfile).to eq strip_whitespace(<<-L)
PATH
@@ -484,10 +492,12 @@ RSpec.describe "bundle install from an existing gemspec" do
specs:
platform_specific (1.0)
platform_specific (1.0-java)
+ #{x64_mingw_gems}
PLATFORMS
java
ruby
+ #{x64_mingw_platforms}
DEPENDENCIES
foo!
@@ -503,7 +513,7 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:platform_specific_type) { :development }
let(:dependency) { "indirect_platform_specific" }
- it "keeps java dependencies in the lockfile" do
+ it "keeps all platform dependencies in the lockfile" do
expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY"
expect(lockfile).to eq strip_whitespace(<<-L)
PATH
@@ -518,10 +528,12 @@ RSpec.describe "bundle install from an existing gemspec" do
platform_specific
platform_specific (1.0)
platform_specific (1.0-java)
+ #{x64_mingw_gems}
PLATFORMS
java
ruby
+ #{x64_mingw_platforms}
DEPENDENCIES
foo!
@@ -546,7 +558,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "installs the ruby platform gemspec" do
- simulate_platform "ruby"
+ bundle "config set --local force_ruby_platform true"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -557,7 +569,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "installs the ruby platform gemspec and skips dev deps with `without development` configured" do
- simulate_platform "ruby"
+ bundle "config set --local force_ruby_platform true"
bundle "config set --local without development"
install_gemfile <<-G
@@ -605,7 +617,7 @@ RSpec.describe "bundle install from an existing gemspec" do
PLATFORMS
ruby
- x64-mingw32
+ #{x64_mingw_platforms}
x86-mingw32
DEPENDENCIES
@@ -622,4 +634,64 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(lockfile).to eq initial_lockfile
end
end
+
+ context "with multiple locked platforms" do
+ before do
+ build_lib("activeadmin", :path => tmp.join("activeadmin")) do |s|
+ s.version = "2.9.0"
+ s.add_dependency "railties", ">= 5.2", "< 6.2"
+ end
+
+ build_repo4 do
+ build_gem "railties", "6.1.4"
+
+ build_gem "jruby-openssl", "0.10.7" do |s|
+ s.platform = "java"
+ end
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gemspec :path => "../activeadmin"
+ gem "jruby-openssl", :platform => :jruby
+ G
+
+ bundle "lock --add-platform java"
+ end
+
+ it "does not remove the platform specific specs from the lockfile when re-resolving due to gemspec changes" do
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: ../activeadmin
+ specs:
+ activeadmin (2.9.0)
+ railties (>= 5.2, < 6.2)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ jruby-openssl (0.10.7-java)
+ railties (6.1.4)
+
+ PLATFORMS
+ #{lockfile_platforms("java")}
+
+ DEPENDENCIES
+ activeadmin!
+ jruby-openssl
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemspec = tmp.join("activeadmin/activeadmin.gemspec")
+ File.write(gemspec, File.read(gemspec).sub(">= 5.2", ">= 6.0"))
+
+ previous_lockfile = lockfile
+
+ bundle "install --local"
+
+ expect(lockfile).to eq(previous_lockfile.sub(">= 5.2", ">= 6.0"))
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index 5ea9eee878..910f96f4ab 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "bundle install with git sources" do
- describe "when floating on master" do
+ describe "when floating on main" do
before :each do
build_git "foo" do |s|
s.executables = "foobar"
@@ -30,6 +30,13 @@ 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 "does not write to cache on bundler/setup" do
+ cache_path = default_bundle_path.join("cache")
+ FileUtils.rm_rf(cache_path)
+ ruby "require 'bundler/setup'"
+ expect(cache_path).not_to exist
+ end
+
it "caches the git repo globally and properly uses the cached repo on the next invocation" do
simulate_new_machine
bundle "config set global_gem_cache true"
@@ -51,9 +58,10 @@ RSpec.describe "bundle install with git sources" do
bundle "update foo"
- sha = git.ref_for("master", 11)
- spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec").to_s
- ruby_code = Gem::Specification.load(spec_file).to_ruby
+ sha = git.ref_for("main", 11)
+ spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec")
+ expect(spec_file).to exist
+ ruby_code = Gem::Specification.load(spec_file.to_s).to_ruby
file_code = File.read(spec_file)
expect(file_code).to eq(ruby_code)
end
@@ -89,12 +97,10 @@ RSpec.describe "bundle install with git sources" do
gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}"
G
- expect(err).to include("The source contains the following versions of 'foo': 1.0")
+ expect(err).to include("The source contains the following gems matching 'foo':\n * foo-1.0")
end
- it "complains with version and platform if pinned specs don't exist in the git repo" do
- simulate_platform "java"
-
+ it "complains with version and platform if pinned specs don't exist in the git repo", :jruby_only do
build_git "only_java" do |s|
s.platform = "java"
end
@@ -106,12 +112,10 @@ RSpec.describe "bundle install with git sources" do
end
G
- expect(err).to include("The source contains the following versions of 'only_java': 1.0 java")
+ expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java")
end
- it "complains with multiple versions and platforms if pinned specs don't exist in the git repo" do
- simulate_platform "java"
-
+ it "complains with multiple versions and platforms if pinned specs don't exist in the git repo", :jruby_only do
build_git "only_java", "1.0" do |s|
s.platform = "java"
end
@@ -128,7 +132,7 @@ RSpec.describe "bundle install with git sources" do
end
G
- expect(err).to include("The source contains the following versions of 'only_java': 1.0 java, 1.1 java")
+ expect(err).to include("The source contains the following gems matching 'only_java':\n * only_java-1.0-java\n * only_java-1.1-java")
end
it "still works after moving the application directory" do
@@ -196,6 +200,7 @@ RSpec.describe "bundle install with git sources" do
gem "foo"
end
G
+ expect(err).to be_empty
run <<-RUBY
require 'foo'
@@ -222,17 +227,56 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
+ it "works when an abbreviated revision is added after an initial, potentially shallow clone" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ git "#{lib_path("foo-1.0")}" do
+ gem "foo"
+ end
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ git "#{lib_path("foo-1.0")}", :ref => #{@revision[0..7].inspect} do
+ gem "foo"
+ end
+ G
+ end
+
+ it "works when a tag that does not look like a commit hash is used as the value of :ref" do
+ build_git "foo"
+ @remote = build_git("bar", :bare => true)
+ update_git "foo", :remote => file_uri_for(@remote.path)
+ update_git "foo", :push => "main"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'foo', :git => "#{@remote.path}"
+ G
+
+ # Create a new tag on the remote that needs fetching
+ update_git "foo", :tag => "v1.0.0"
+ update_git "foo", :push => "v1.0.0"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'foo', :git => "#{@remote.path}", :ref => "v1.0.0"
+ G
+
+ expect(err).to be_empty
+ end
+
it "works when the revision is a non-head ref" do
- # want to ensure we don't fallback to master
+ # want to ensure we don't fallback to main
update_git "foo", :path => lib_path("foo-1.0") do |s|
s.write("lib/foo.rb", "raise 'FAIL'")
end
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~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
@@ -259,16 +303,16 @@ RSpec.describe "bundle install with git sources" do
end
G
- # want to ensure we don't fallback to master
+ # want to ensure we don't fallback to main
update_git "foo", :path => lib_path("foo-1.0") do |s|
s.write("lib/foo.rb", "raise 'FAIL'")
end
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~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
@@ -288,7 +332,7 @@ RSpec.describe "bundle install with git sources" do
end
it "does not download random non-head refs" do
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", :dir => lib_path("foo-1.0"))
bundle "config set global_gem_cache true"
@@ -418,16 +462,13 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying local override" do
it "uses the local repository instead of checking a new one out" do
- # We don't generate it because we actually don't need it
- # build_git "rack", "0.8"
-
build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
s.write "lib/rack.rb", "puts :LOCAL"
end
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -448,7 +489,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -468,7 +509,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -484,7 +525,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
lockfile0 = File.read(bundled_app_lock)
@@ -506,7 +547,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
lockfile0 = File.read(bundled_app_lock)
@@ -526,7 +567,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -590,12 +631,12 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
bundle :install, :raise_on_error => false
- expect(err).to match(/is using branch another but Gemfile specifies master/)
+ expect(err).to match(/is using branch another but Gemfile specifies main/)
end
it "explodes on invalid revision on install" do
@@ -607,7 +648,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -624,7 +665,7 @@ RSpec.describe "bundle install with git sources" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -872,6 +913,9 @@ RSpec.describe "bundle install with git sources" do
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"
@@ -885,12 +929,15 @@ RSpec.describe "bundle install with git sources" do
gem "has_submodule"
end
G
- expect(err).to match(/could not find gem 'submodule/i)
+ expect(err).to match(%r{submodule >= 0 could not be found in rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally})
expect(the_bundle).not_to include_gems "has_submodule 1.0"
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"
@@ -909,6 +956,9 @@ RSpec.describe "bundle install with git sources" do
end
it "does not warn when deiniting 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"
@@ -1101,6 +1151,17 @@ RSpec.describe "bundle install with git sources" do
G
expect(err).to include("Revision deadbeef does not exist in the repository")
end
+
+ it "gives a helpful error message when the remote branch no longer exists" do
+ build_git "foo"
+
+ install_gemfile <<-G, :env => { "LANG" => "en" }, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :branch => "deadbeef"
+ G
+
+ expect(err).to include("Revision deadbeef does not exist in the repository")
+ end
end
describe "bundle install with deployment mode configured and git sources" do
@@ -1187,7 +1248,7 @@ RSpec.describe "bundle install with git sources" do
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/foo.rb", "w") do |f|
f.puts "FOO = 'YES'"
@@ -1213,11 +1274,12 @@ RSpec.describe "bundle install with git sources" do
expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
end
- it "does not use old extension after ref changes", :ruby_repo do
+ it "does not use old extension after ref changes" do
git_reader = build_git "foo", :no_default => true do |s|
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-RUBY
require "mkmf"
+ $extout = "$(topdir)/" + RbConfig::CONFIG["EXTOUT"]
create_makefile("foo")
RUBY
s.write "ext/foo.c", "void Init_foo() {}"
@@ -1280,7 +1342,7 @@ In Gemfile:
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
cur_time = Time.now.to_f.to_s
File.open("\#{path}/foo.rb", "w") do |f|
@@ -1321,7 +1383,7 @@ In Gemfile:
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
cur_time = Time.now.to_f.to_s
File.open("\#{path}/foo.rb", "w") do |f|
@@ -1364,7 +1426,7 @@ In Gemfile:
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
cur_time = Time.now.to_f.to_s
File.open("\#{path}/foo.rb", "w") do |f|
@@ -1436,7 +1498,42 @@ In Gemfile:
end
describe "without git installed" do
- it "prints a better error message" do
+ it "prints a better error message when installing" do
+ 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
@@ -1488,7 +1585,7 @@ In Gemfile:
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{lib_path("foo")}", :branch => "master"
+ gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
G
bundle :install
diff --git a/spec/bundler/install/gemfile/groups_spec.rb b/spec/bundler/install/gemfile/groups_spec.rb
index c92b5dcc57..734e012e84 100644
--- a/spec/bundler/install/gemfile/groups_spec.rb
+++ b/spec/bundler/install/gemfile/groups_spec.rb
@@ -91,17 +91,8 @@ RSpec.describe "bundle install with groups" do
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"
+ it "respects global `without` configuration, but does not save it locally" do
+ bundle "config set --global without emo"
bundle :install
expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
bundle "config list"
diff --git a/spec/bundler/install/gemfile/install_if_spec.rb b/spec/bundler/install/gemfile/install_if_spec.rb
index 786e0e9258..3d2d15a698 100644
--- a/spec/bundler/install/gemfile/install_if_spec.rb
+++ b/spec/bundler/install/gemfile/install_if_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "bundle install with install_if conditionals" do
expect(the_bundle).not_to include_gems("thin")
expect(the_bundle).not_to include_gems("foo")
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb
index 566fdcf65a..a5207036c3 100644
--- a/spec/bundler/install/gemfile/path_spec.rb
+++ b/spec/bundler/install/gemfile/path_spec.rb
@@ -92,14 +92,12 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "demo", :path => lib_path("demo")
build_lib "aaa", :path => lib_path("demo/aaa")
- gemfile = <<-G
+ gemfile lib_path("demo/Gemfile"), <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec
gem "aaa", :path => "./aaa"
G
- File.open(lib_path("demo/Gemfile"), "w") {|f| f.puts gemfile }
-
lockfile = <<~L
PATH
remote: .
@@ -127,9 +125,9 @@ RSpec.describe "bundle install with explicit source paths" do
L
bundle :install, :dir => lib_path("demo")
- expect(lib_path("demo/Gemfile.lock")).to have_lockfile(lockfile)
+ 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 have_lockfile(lockfile)
+ expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
end
it "expands paths when comparing locked paths to Gemfile paths" do
@@ -137,7 +135,7 @@ RSpec.describe "bundle install with explicit source paths" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem 'foo', :path => File.expand_path("../foo-1.0", __FILE__)
+ gem 'foo', :path => File.expand_path("foo-1.0", __dir__)
G
bundle "config set --local frozen true"
@@ -183,6 +181,72 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "foo 1.0"
end
+ 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")
@@ -248,18 +312,67 @@ RSpec.describe "bundle install with explicit source paths" do
s.add_dependency "rack", "1.0"
end
- gemfile = <<-G
+ gemfile lib_path("foo/Gemfile"), <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec
G
- File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts gemfile }
-
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 "does not unlock dependencies of path sources" do
+ build_repo4 do
+ build_gem "graphql", "2.0.15"
+ build_gem "graphql", "2.0.16"
+ end
+
+ build_lib "foo", "0.1.0", :path => lib_path("foo") do |s|
+ s.add_dependency "graphql", "~> 2.0"
+ end
+
+ gemfile_path = lib_path("foo/Gemfile")
+
+ gemfile gemfile_path, <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gemspec
+ G
+
+ lockfile_path = lib_path("foo/Gemfile.lock")
+
+ original_lockfile = <<~L
+ PATH
+ remote: .
+ specs:
+ foo (0.1.0)
+ graphql (~> 2.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ graphql (2.0.15)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_path, original_lockfile
+
+ build_lib "foo", "0.1.1", :path => lib_path("foo") do |s|
+ s.add_dependency "graphql", "~> 2.0"
+ end
+
+ bundle "install", :dir => lib_path("foo")
+ expect(lockfile_path).to read_as(original_lockfile.gsub("foo (0.1.0)", "foo (0.1.1)"))
+ end
+
it "supports gemspec syntax with an alternative path" do
build_lib "foo", "1.0", :path => lib_path("foo") do |s|
s.add_dependency "rack", "1.0"
@@ -552,7 +665,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:
@@ -580,7 +693,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:
@@ -614,7 +727,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:
@@ -643,7 +756,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:
@@ -669,6 +782,52 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "rack 0.9.1"
end
+
+ it "does not remove existing ruby platform" do
+ build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ s.add_dependency "rack", "0.9.1"
+ end
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ 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("ruby")}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
end
describe "switching sources" do
@@ -725,13 +884,11 @@ RSpec.describe "bundle install with explicit source paths" do
describe "when there are both a gemspec and remote gems" do
it "doesn't query rubygems for local gemspec name" do
build_lib "private_lib", "2.2", :path => lib_path("private_lib")
- gemfile = <<-G
+ gemfile lib_path("private_lib/Gemfile"), <<-G
source "http://localgemserver.test"
gemspec
gem 'rack'
G
- File.open(lib_path("private_lib/Gemfile"), "w") {|f| f.puts gemfile }
-
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/)
diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index 7cd06b7e08..219ae6c2f4 100644
--- a/spec/bundler/install/gemfile/platform_spec.rb
+++ b/spec/bundler/install/gemfile/platform_spec.rb
@@ -50,7 +50,7 @@ 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
+ it "pulls the pure ruby version on jruby if the java platform is not present in the lockfile and bundler is run in frozen mode", :jruby_only do
lockfile <<-G
GEM
remote: #{file_uri_for(gem_repo1)}
@@ -75,6 +75,81 @@ RSpec.describe "bundle install across platforms" do
expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
end
+ context "on universal Rubies" do
+ before do
+ build_repo4 do
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "ruby"
+ s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 RUBY'"
+ end
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "arm64-darwin"
+ s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 arm64-darwin'"
+ end
+ build_gem "darwin_single_arch" do |s|
+ s.platform = "x86_64-darwin"
+ s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 x86_64-darwin'"
+ end
+ end
+ end
+
+ it "pulls in the correct architecture gem" do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ darwin_single_arch (1.0)
+ darwin_single_arch (1.0-arm64-darwin)
+ darwin_single_arch (1.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ darwin_single_arch
+ G
+
+ simulate_platform "universal-darwin-21"
+ simulate_ruby_platform "universal.x86_64-darwin21" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "darwin_single_arch"
+ G
+
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 x86_64-darwin"
+ end
+ end
+
+ it "pulls in the correct architecture gem on arm64e macOS Ruby" do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ darwin_single_arch (1.0)
+ darwin_single_arch (1.0-arm64-darwin)
+ darwin_single_arch (1.0-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ darwin_single_arch
+ G
+
+ simulate_platform "universal-darwin-21"
+ simulate_ruby_platform "universal.arm64e-darwin21" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "darwin_single_arch"
+ G
+
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 arm64-darwin"
+ end
+ end
+ end
+
it "works with gems that have different dependencies" do
simulate_platform "java"
install_gemfile <<-G
@@ -86,13 +161,13 @@ RSpec.describe "bundle install across platforms" do
expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
simulate_new_machine
-
- simulate_platform "ruby"
+ bundle "config set --local force_ruby_platform true"
bundle "install"
expect(the_bundle).to include_gems "nokogiri 1.4.2"
expect(the_bundle).not_to include_gems "weakling"
+ simulate_new_machine
simulate_platform "java"
bundle "install"
@@ -128,7 +203,7 @@ RSpec.describe "bundle install across platforms" do
gem "pry"
G
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -156,7 +231,7 @@ RSpec.describe "bundle install across platforms" do
bundle "lock --add-platform ruby"
- good_lockfile = strip_whitespace(<<-L)
+ good_lockfile = <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -186,9 +261,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:
@@ -216,29 +291,29 @@ RSpec.describe "bundle install across platforms" do
pry
BUNDLED WITH
- #{Bundler::VERSION}
+ 1.16.1
L
aggregate_failures do
lockfile bad_lockfile
- bundle :install
- lockfile_should_be good_lockfile
+ bundle :install, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle :update, :all => true
- lockfile_should_be good_lockfile
+ bundle :update, :all => true, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle "update ffi"
- lockfile_should_be good_lockfile
+ bundle "update ffi", :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle "update empyrean"
- lockfile_should_be good_lockfile
+ bundle "update empyrean", :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle :lock
- lockfile_should_be good_lockfile
+ bundle :lock, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
end
end
@@ -310,7 +385,7 @@ RSpec.describe "bundle install across platforms" do
expect(the_bundle).to include_gem "platform_specific 1.0 RUBY"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -332,8 +407,6 @@ 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)}"
@@ -358,9 +431,50 @@ 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/ the current platforms inline" do
- skip "platform issues" if Gem.win_platform?
+ 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
+ #{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
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri", :platforms => :#{local_tag}
@@ -379,8 +493,6 @@ 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}
@@ -410,7 +522,7 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "does not attempt to install gems from :rbx when using --local" do
- simulate_platform "ruby"
+ bundle "config set --local force_ruby_platform true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -422,12 +534,10 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "does not attempt to install gems from other rubies when using --local" do
- simulate_platform "ruby"
- other_ruby_version_tag = RUBY_VERSION =~ /^1\.8/ ? :ruby_19 : :ruby_18
-
+ bundle "config set --local force_ruby_platform true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "some_gem", platform: :#{other_ruby_version_tag}
+ gem "some_gem", platform: :ruby_22
G
bundle "install --local"
@@ -435,19 +545,19 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "does not print a warning when a dependency is unused on a platform different from the current one" do
- simulate_platform "ruby"
+ bundle "config set --local force_ruby_platform true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby]
+ gem "rack", :platform => [:windows, :mingw, :mswin, :x64_mingw, :jruby]
G
bundle "install"
expect(err).to be_empty
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -462,11 +572,31 @@ RSpec.describe "bundle install with platform conditionals" do
#{Bundler::VERSION}
L
end
+
+ it "resolves fine when a dependency is unused on a platform different from the current one, but reintroduced transitively" do
+ bundle "config set --local force_ruby_platform true"
+
+ build_repo4 do
+ build_gem "listen", "3.7.1" do |s|
+ s.add_dependency "ffi"
+ end
+
+ build_gem "ffi", "1.15.5"
+ end
+
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "listen"
+ gem "ffi", :platform => :windows
+ G
+ expect(err).to be_empty
+ end
end
RSpec.describe "when a gem has no architecture" do
it "still installs correctly" do
- simulate_platform mswin
+ simulate_platform x86_mswin32
build_repo2 do
# The rcov gem is platform mswin32, but has no arch
diff --git a/spec/bundler/install/gemfile/ruby_spec.rb b/spec/bundler/install/gemfile/ruby_spec.rb
index fd4300c042..39f09031b7 100644
--- a/spec/bundler/install/gemfile/ruby_spec.rb
+++ b/spec/bundler/install/gemfile/ruby_spec.rb
@@ -11,13 +11,13 @@ RSpec.describe "ruby requirement" do
it "allows adding gems" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.ruby_version}"
gem "rack"
G
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.ruby_version}"
gem "rack"
gem "rack-obama"
G
@@ -28,7 +28,7 @@ RSpec.describe "ruby requirement" do
it "allows removing the ruby version requirement" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "~> #{RUBY_VERSION}"
+ ruby "~> #{Gem.ruby_version}"
gem "rack"
G
@@ -46,18 +46,16 @@ RSpec.describe "ruby requirement" do
it "allows changing the ruby version requirement to something compatible" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby ">= 1.0.0"
+ ruby ">= #{current_ruby_minor}"
gem "rack"
G
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
- simulate_ruby_version "5100"
-
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby ">= 1.0.1"
+ ruby ">= #{Gem.ruby_version}"
gem "rack"
G
@@ -72,25 +70,41 @@ 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)
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
- simulate_ruby_version "5100"
+ DEPENDENCIES
+ rack
+
+ RUBY VERSION
+ ruby 2.1.4p422
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby ">= 5000.0"
+ ruby ">= #{current_ruby_minor}"
gem "rack"
G
expect(the_bundle).to include_gems "rack 1.0.0"
- expect(locked_ruby_version.versions).to eq(["5100"])
+ expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
end
it "allows requirements with trailing whitespace" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- ruby "#{RUBY_VERSION}\\n \t\\n"
+ ruby "#{Gem.ruby_version}\\n \t\\n"
gem "rack"
G
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 8c225afb11..dd86187a6b 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "fails", :bundler => "3" do
- bundle :instal, :artifice => "compact_index", :raise_on_error => false
+ 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
@@ -262,7 +262,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
depends_on_rack!
@@ -347,7 +347,6 @@ RSpec.describe "bundle install with gems on multiple sources" do
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.")
- expect(err).to include("The source does not contain any versions of 'private_gem_1'")
end
end
@@ -372,7 +371,15 @@ RSpec.describe "bundle install with gems on multiple sources" do
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.")
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of depends_on_missing depends on missing >= 0
+ and missing >= 0 could not be found in any of the sources,
+ depends_on_missing cannot be used.
+ So, because Gemfile depends on depends_on_missing >= 0,
+ version solving has failed.
+ E
end
end
@@ -426,9 +433,15 @@ RSpec.describe "bundle install with gems on multiple sources" do
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."
- )
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of depends_on_rack depends on rack >= 0
+ and rack >= 0 could not be found in rubygems repository https://gem.repo2/ or installed locally,
+ depends_on_rack cannot be used.
+ So, because Gemfile depends on depends_on_rack >= 0,
+ version solving has failed.
+ E
end
end
@@ -627,7 +640,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
zeitwerk (2.4.2)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
activesupport
@@ -683,7 +696,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
sidekiq (>= 6.1.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
activesupport
@@ -767,7 +780,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
sidekiq (>= 6.1.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
activesupport
@@ -823,7 +836,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
sidekiq (>= 6.1.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
activesupport
@@ -911,7 +924,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
nokogiri (>= 1.2.3)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
handsoap!
@@ -971,7 +984,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
rack!
@@ -1001,7 +1014,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
rack!
@@ -1023,7 +1036,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
rack (0.9.1)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
rack!
@@ -1251,8 +1264,34 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs the higher version in the new repo" do
- expect(the_bundle).to include_gems("rack 1.2")
+ it "conservatively installs the existing locked version" do
+ expect(the_bundle).to include_gems("rack 1.0.0")
+ end
+ end
+
+ context "when Gemfile overrides a gemspec development dependency to change the default source" do
+ before do
+ build_repo4 do
+ build_gem "bar"
+ end
+
+ build_lib("gemspec_test", :path => tmp.join("gemspec_test")) do |s|
+ s.add_development_dependency "bar"
+ end
+
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gemspec :path => "#{tmp.join("gemspec_test")}"
+ G
+ end
+
+ it "does not print warnings" do
+ expect(err).to be_empty
end
end
@@ -1281,7 +1320,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(out).to include("Using example 0.1.0")
end
- it "fails inmmediately with a helpful error when a non retriable network error happens while resolving sources" do
+ it "fails immediately with a helpful error when a rubygems source does not exist and bundler/setup is required" do
gemfile <<-G
source "https://gem.repo1"
@@ -1297,6 +1336,21 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
expect(last_command).to be_failure
+ expect(err).to include("Could not find gem 'example' in locally installed gems.")
+ end
+
+ it "fails immediately 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
@@ -1322,8 +1376,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
expect(err).to eq strip_whitespace(<<-EOS).strip
Warning: The gem 'rack' was found in multiple relevant sources.
- * rubygems repository https://gem.repo1/ or installed locally
- * rubygems repository https://gem.repo4/ or installed locally
+ * 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
@@ -1352,8 +1406,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
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 https://gem.repo1/ or installed locally
- * rubygems repository https://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
@@ -1394,7 +1448,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
mime-types (3.3.1)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
capybara (~> 2.5.0)
@@ -1418,7 +1472,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
mime-types (3.0.0)
PLATFORMS
- #{specific_local_platform}
+ #{local_platform}
DEPENDENCIES
capybara (~> 2.5.0)
@@ -1429,4 +1483,190 @@ RSpec.describe "bundle install with gems on multiple sources" do
L
end
end
+
+ context "when default source includes old gems with nil required_ruby_version" do
+ before do
+ build_repo2 do
+ build_gem "ruport", "1.7.0.3" do |s|
+ s.add_dependency "pdf-writer", "1.1.8"
+ end
+ end
+
+ build_repo gem_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_ruby_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://localgemserver.test"
+
+ gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install", :artifice => "compact_index_extra", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ pdf-writer (1.1.8)
+
+ GEM
+ remote: https://localgemserver.test/extra/
+ specs:
+ ruport (1.7.0.3)
+ pdf-writer (= 1.1.8)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ ruport (= 1.7.0.3)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when default source includes old gems with nil required_rubygems_version" do
+ before do
+ build_repo2 do
+ build_gem "ruport", "1.7.0.3" do |s|
+ s.add_dependency "pdf-writer", "1.1.8"
+ end
+ end
+
+ build_repo gem_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_rubygems_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://localgemserver.test"
+
+ gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install", :artifice => "compact_index_extra", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ pdf-writer (1.1.8)
+
+ GEM
+ remote: https://localgemserver.test/extra/
+ specs:
+ ruport (1.7.0.3)
+ pdf-writer (= 1.1.8)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ ruport (= 1.7.0.3)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when default source uses the old API and includes old gems with nil required_rubygems_version" do
+ before do
+ build_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_rubygems_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://localgemserver.test"
+
+ gem "pdf-writer", "= 1.1.8"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install --verbose", :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ pdf-writer (1.1.8)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ pdf-writer (= 1.1.8)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when mistakenly adding a top level gem already depended on and cached under the wrong source" do
+ before do
+ build_repo4 do
+ build_gem "some_private_gem", "0.1.0" do |s|
+ s.add_dependency "example", "~> 1.0"
+ end
+ end
+
+ build_repo2 do
+ build_gem "example", "1.0.0"
+ end
+
+ install_gemfile <<~G, :artifice => "compact_index"
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "some_private_gem"
+ end
+ G
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "some_private_gem"
+ gem "example" # MISTAKE, example is not available at gem.repo4
+ end
+ G
+ end
+
+ it "shows a proper error message and does not generate a corrupted lockfile" do
+ expect do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end.not_to change { lockfile }
+
+ expect(err).to include("Could not find gem 'example' in rubygems repository https://gem.repo4/")
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 4c24f09368..cab53a663a 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -6,10 +6,8 @@ RSpec.describe "bundle install with specific platforms" do
gem "google-protobuf"
G
- context "when on a darwin machine" do
- before { simulate_platform "x86_64-darwin-15" }
-
- it "locks to the specific darwin platform" do
+ it "locks to the specific darwin platform" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
@@ -19,8 +17,10 @@ RSpec.describe "bundle install with specific platforms" do
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
])
end
+ end
- it "understands that a non-plaform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
system_gems "bundler-2.1.4"
@@ -53,8 +53,10 @@ RSpec.describe "bundle install with specific platforms" do
# make sure the platform that got actually installed with the old bundler is used
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
end
+ end
- it "understands that a non-plaform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
system_gems "bundler-2.1.4"
@@ -87,7 +89,7 @@ RSpec.describe "bundle install with specific platforms" do
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
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -103,8 +105,56 @@ RSpec.describe "bundle install with specific platforms" do
#{Bundler::VERSION}
L
end
+ end
+
+ context "when running on a legacy lockfile locked only to RUBY" do
+ around do |example|
+ build_repo4 do
+ build_gem "nokogiri", "1.3.10"
+ build_gem "nokogiri", "1.3.10" do |s|
+ s.platform = "arm64-darwin"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.3.10)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-22", &example
+ end
- it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ it "still installs the generic RUBY variant if necessary" do
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(out).to include("Installing nokogiri 1.3.10")
+ end
+
+ it "still installs the generic RUBY variant if necessary, even in frozen mode" do
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "BUNDLE_FROZEN" => "true" }
+ expect(out).to include("Installing nokogiri 1.3.10")
+ end
+ end
+
+ it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ simulate_platform "x86_64-darwin-15" do
build_repo2 do
build_gem("libv8", "8.4.255.0")
build_gem("libv8", "8.4.255.0") {|s| s.platform = "universal-darwin" }
@@ -147,8 +197,44 @@ RSpec.describe "bundle install with specific platforms" do
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
+ end
+
+ it "chooses platform specific gems even when resolving upon materialization and the API returns more specific platforms first" do
+ simulate_platform "x86_64-darwin-15" do
+ build_repo4 do
+ build_gem("grpc", "1.50.0")
+ build_gem("grpc", "1.50.0") {|s| s.platform = "universal-darwin" }
+ end
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+ gem "grpc"
+ G
- it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ grpc (1.50.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ grpc
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose", :artifice => "compact_index_precompiled_before", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ expect(out).to include("Installing grpc 1.50.0 (universal-darwin)")
+ end
+ end
+
+ it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
gemfile(google_protobuf)
bundle "cache --all-platforms"
@@ -157,8 +243,10 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
expect(err).to be_empty
end
+ end
- it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
gemfile(google_protobuf)
bundle "config set --local cache_all_platforms true"
@@ -168,44 +256,46 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
expect(err).to be_empty
end
+ end
- it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
- git = build_git "pg_array_parser", "1.0"
+ 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
+ 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)
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("pg_array_parser-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ pg_array_parser (1.0-java)
+ pg_array_parser (1.0)
- GEM
- specs:
+ GEM
+ specs:
- PLATFORMS
- java
- #{lockfile_platforms}
+ PLATFORMS
+ java
+ #{lockfile_platforms}
- DEPENDENCIES
- pg_array_parser!
+ DEPENDENCIES
+ pg_array_parser!
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- bundle "config set --local cache_all true"
- bundle "cache --all-platforms"
+ bundle "config set --local cache_all true"
+ bundle "cache --all-platforms"
- expect(err).to be_empty
- end
+ expect(err).to be_empty
+ end
- it "uses the platform-specific gem with extra dependencies" do
+ it "uses the platform-specific gem with extra dependencies" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem_with_different_dependencies_per_platform
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -218,25 +308,29 @@ RSpec.describe "bundle install with specific platforms" do
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0",
"facter-2.4.6-universal-darwin"])
end
+ 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
+ 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
+ it "adds the foreign platform" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
- bundle "lock --add-platform=#{x64_mingw}"
+ bundle "lock --add-platform=#{x64_mingw32}"
- expect(the_bundle.locked_gems.platforms).to eq([x64_mingw, pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.platforms).to eq([x64_mingw32, 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-universal-darwin
google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
])
end
+ end
- it "falls back on plain ruby when that version doesnt have a platform-specific gem" do
+ it "falls back on plain ruby when that version doesn't have a platform-specific gem" do
+ simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
bundle "lock --add-platform=#{java}"
@@ -250,10 +344,11 @@ RSpec.describe "bundle install with specific platforms" do
end
end
- it "installs sorbet-static, which does not provide a pure ruby variant, just fine on truffleruby", :truffleruby do
+ it "installs sorbet-static, which does not provide a pure ruby variant, just fine", :truffleruby do
+ skip "does not apply to Windows" if Gem.win_platform?
+
build_repo2 do
- build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "x86_64-linux" }
- build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "universal-darwin-20" }
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = Bundler.local_platform }
end
gemfile <<~G
@@ -266,8 +361,7 @@ RSpec.describe "bundle install with specific platforms" do
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
- sorbet-static (0.5.6403-universal-darwin-20)
- sorbet-static (0.5.6403-x86_64-linux)
+ sorbet-static (0.5.6403-#{Bundler.local_platform})
PLATFORMS
ruby
@@ -282,6 +376,556 @@ RSpec.describe "bundle install with specific platforms" do
bundle "install --verbose"
end
+ it "does not resolve if the current platform does not match any of available platform specific variants for a top level dependency" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" }
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" }
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static", "0.5.6433"
+ G
+
+ error_message = <<~ERROR.strip
+ Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
+ * sorbet-static-0.5.6433-universal-darwin-20
+ * sorbet-static-0.5.6433-x86_64-linux
+ ERROR
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock", :raise_on_error => false
+ end
+
+ expect(err).to include(error_message).once
+
+ # Make sure it doesn't print error twice in verbose mode
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock --verbose", :raise_on_error => false
+ end
+
+ expect(err).to include(error_message).once
+ end
+
+ it "does not resolve if the current platform does not match any of available platform specific variants for a transitive dependency" do
+ build_repo4 do
+ build_gem("sorbet", "0.5.6433") {|s| s.add_dependency "sorbet-static", "= 0.5.6433" }
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "x86_64-linux" }
+ build_gem("sorbet-static", "0.5.6433") {|s| s.platform = "universal-darwin-20" }
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet", "0.5.6433"
+ G
+
+ error_message = <<~ERROR.strip
+ Could not find compatible versions
+
+ Because every version of sorbet depends on sorbet-static = 0.5.6433
+ and sorbet-static = 0.5.6433 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally for any resolution platforms (arm64-darwin-21),
+ sorbet cannot be used.
+ So, because Gemfile depends on sorbet = 0.5.6433,
+ version solving has failed.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
+ * sorbet-static-0.5.6433-universal-darwin-20
+ * sorbet-static-0.5.6433-x86_64-linux
+ ERROR
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock", :raise_on_error => false
+ end
+
+ expect(err).to include(error_message).once
+
+ # Make sure it doesn't print error twice in verbose mode
+
+ simulate_platform "arm64-darwin-21" do
+ bundle "lock --verbose", :raise_on_error => false
+ end
+
+ expect(err).to include(error_message).once
+ end
+
+ it "does not generate a lockfile if RUBY platform is forced and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.9889") {|s| s.platform = Gem::Platform.local }
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static", "0.5.9889"
+ G
+
+ bundle "lock", :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
+
+ expect(err).to include <<~ERROR.rstrip
+ Could not find gem 'sorbet-static (= 0.5.9889)' with platform 'ruby' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.9889)':
+ * sorbet-static-0.5.9889-#{Gem::Platform.local}
+ ERROR
+ end
+
+ it "automatically fixes the lockfile if RUBY platform is locked and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet", "= 0.5.10160"
+ s.add_runtime_dependency "sorbet-runtime", "= 0.5.10160"
+ end
+
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-runtime", "0.5.10160")
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static-and-runtime"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if both RUBY platform and a more specific platform are locked, and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem "nokogiri", "1.12.0"
+ build_gem "nokogiri", "1.12.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+
+ build_gem "nokogiri", "1.13.0"
+ build_gem "nokogiri", "1.13.0" do |s|
+ s.platform = "x86_64-darwin"
+ end
+
+ build_gem("sorbet-static", "0.5.10601") do |s|
+ s.platform = "x86_64-darwin"
+ end
+ end
+
+ simulate_platform "x86_64-darwin-22" do
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+ gem "sorbet-static"
+ G
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.12.0)
+ nokogiri (1.12.0-x86_64-darwin)
+ sorbet-static (0.5.10601-x86_64-darwin)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ sorbet
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-darwin-22" do
+ bundle "update --conservative nokogiri"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.13.0-x86_64-darwin)
+ sorbet-static (0.5.10601-x86_64-darwin)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ nokogiri
+ sorbet-static
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile if only RUBY platform is locked and some gem has no RUBY variant available" do
+ build_repo4 do
+ build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet", "= 0.5.10160"
+ s.add_runtime_dependency "sorbet-runtime", "= 0.5.10160"
+ end
+
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_runtime_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-runtime", "0.5.10160")
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static-and-runtime"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-runtime (0.5.10160)
+ sorbet-static (0.5.10160-#{Gem::Platform.local})
+ sorbet-static-and-runtime (0.5.10160)
+ sorbet (= 0.5.10160)
+ sorbet-runtime (= 0.5.10160)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ sorbet-static-and-runtime
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile without removing other variants if it's missing platform gems, but they are installed locally" do
+ simulate_platform "x86_64-darwin-21" do
+ build_repo4 do
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-20"
+ end
+
+ build_gem("sorbet-static", "0.5.10549") do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ # Make sure sorbet-static-0.5.10549-universal-darwin-21 is installed
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "sorbet-static", "= 0.5.10549"
+ G
+
+ # Make sure the lockfile is missing sorbet-static-0.5.10549-universal-darwin-21
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet-static (0.5.10549-universal-darwin-20)
+ sorbet-static (0.5.10549-universal-darwin-21)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.10549)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "does not remove ruby if gems for other platforms, and not present in the lockfile, exist in the Gemfile" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8"
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri"
+
+ gem "tzinfo", "~> 1.2", platform: :#{not_local_tag}
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.13.8)
+ nokogiri (1.13.8-#{Gem::Platform.local})
+
+ PLATFORMS
+ #{lockfile_platforms("ruby")}
+
+ DEPENDENCIES
+ nokogiri
+ tzinfo (~> 1.2)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ bundle "lock --update"
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+
+ it "does not remove ruby when adding a new gem to the Gemfile" do
+ build_repo4 do
+ build_gem "concurrent-ruby", "1.2.2"
+ build_gem "rack", "3.0.7"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "concurrent-ruby"
+ gem "rack"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ concurrent-ruby (1.2.2)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ concurrent-ruby
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ concurrent-ruby (1.2.2)
+ rack (3.0.7)
+
+ PLATFORMS
+ #{formatted_lockfile_platforms(*["ruby", generic_local_platform].uniq)}
+
+ DEPENDENCIES
+ concurrent-ruby
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "can fallback to a source gem when platform gems are incompatible with current ruby version" do
+ setup_multiplatform_gem_with_source_gem
+
+ source = file_uri_for(gem_repo2)
+
+ gemfile <<~G
+ source "#{source}"
+
+ gem "my-precompiled-gem"
+ G
+
+ # simulate lockfile which includes both a precompiled gem with:
+ # - Gem the current platform (with incompatible ruby version)
+ # - A source gem with compatible ruby version
+ lockfile <<-L
+ GEM
+ remote: #{source}/
+ specs:
+ my-precompiled-gem (3.0.0)
+ my-precompiled-gem (3.0.0-#{Bundler.local_platform})
+
+ PLATFORMS
+ ruby
+ #{Bundler.local_platform}
+
+ DEPENDENCIES
+ my-precompiled-gem
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+ end
+
+ it "automatically fixes the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
+ #
+ # Given an existing application using native gems (e.g., nokogiri)
+ # And a lockfile generated with a stable ruby version
+ # When want test the application against ruby-head and `bundle install`
+ # Then bundler should fall back to the generic ruby platform gem
+ #
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.0"
+ build_gem "nokogiri", "1.14.0" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "nokogiri", "1.14.0"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (= 1.14.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ expect(lockfile).to eq(<<~L)
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.14.0)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri (= 1.14.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
private
def setup_multiplatform_gem
@@ -312,4 +956,16 @@ RSpec.describe "bundle install with specific platforms" do
build_gem("CFPropertyList")
end
end
+
+ def setup_multiplatform_gem_with_source_gem
+ build_repo2 do
+ build_gem("my-precompiled-gem", "3.0.0")
+ build_gem("my-precompiled-gem", "3.0.0") do |s|
+ s.platform = Bundler.local_platform
+
+ # purposely unresolvable
+ s.required_ruby_version = ">= 1000.0.0"
+ end
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile_spec.rb b/spec/bundler/install/gemfile_spec.rb
index 0f8f1ecfa8..e643573454 100644
--- a/spec/bundler/install/gemfile_spec.rb
+++ b/spec/bundler/install/gemfile_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe "bundle install" do
end
end
- context "with engine specified in symbol", :jruby do
+ context "with engine specified in symbol", :jruby_only do
it "does not raise any error parsing Gemfile" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index 0cee69f702..65be262748 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -163,6 +163,25 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "shows proper path when permission errors happen", :permissions do
+ gemfile <<-G
+ source "#{source_uri}"
+ gem "rack"
+ G
+
+ versions = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
+ "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions")
+ FileUtils.mkdir_p(File.dirname(versions))
+ FileUtils.touch(versions)
+ FileUtils.chmod("-r", versions)
+
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+
+ expect(err).to include(
+ "There was an error while trying to read from `#{versions}`. It is likely that you need to grant read permissions for that path."
+ )
+ end
+
it "falls back when the user's home directory does not exist or is not writable" do
ENV["HOME"] = tmp("missing_home").to_s
@@ -258,7 +277,7 @@ The checksum of /versions does not match the checksum provided by the server! So
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/net_build_extensions.rb", "w") do |f|
f.puts "NET_BUILD_EXTENSIONS = 'YES'"
@@ -387,7 +406,7 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec if the index of gems is large when doing back deps" do
+ it "does not fetch every spec when doing back deps" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -397,9 +416,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
- 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)
+ install_gemfile <<-G, :artifice => "compact_index_extra_missing", :env => env_for_missing_prerelease_default_gem_activation
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -409,7 +426,7 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "does not fetch every spec if the index of gems is large when doing back deps & everything is the compact index" do
+ it "does not fetch every spec when doing back deps & everything is the compact index" do
build_repo4 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -419,9 +436,7 @@ The checksum of /versions does not match the checksum provided by the server! So
FileUtils.rm_rf Dir[gem_repo4("gems/foo-*.gem")]
end
- 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)
+ install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :env => env_for_missing_prerelease_default_gem_activation
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -500,18 +515,6 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "compact_index"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
it "installs the binstubs", :bundler => "< 3" do
gemfile <<-G
source "#{source_uri}"
@@ -680,6 +683,15 @@ The checksum of /versions does not match the checksum provided by the server! So
bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false
expect(err).to include("Bad username or password")
end
+
+ it "does not fallback to old dependency API if bad authentication is provided" do
+ bundle "config set #{source_hostname} #{user}:wrong"
+
+ bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false, :verbose => true
+ expect(err).to include("Bad username or password")
+ expect(out).to include("HTTP 401 Unauthorized http://user@localgemserver.test/versions")
+ expect(out).not_to include("HTTP 401 Unauthorized http://user@localgemserver.test/api/v1/dependencies")
+ end
end
describe "with no password" do
@@ -761,8 +773,6 @@ The checksum of /versions does not match the checksum provided by the server! So
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'
@@ -922,9 +932,10 @@ The checksum of /versions does not match the checksum provided by the server! So
Gem::Dependency.new("activerecord", "= 2.3.2"),
Gem::Dependency.new("actionmailer", "= 2.3.2"),
Gem::Dependency.new("activeresource", "= 2.3.2")]
- expect(out).to include(<<-E.strip).and include("rails-2.3.2 from rubygems remote at #{source_uri}/ has either corrupted API or lockfile dependencies")
+ expect(out).to include("rails-2.3.2 from rubygems remote at #{source_uri}/ has either corrupted API or lockfile dependencies")
+ expect(err).to include(<<-E.strip)
Bundler::APIResponseMismatchError: Downloading rails-2.3.2 revealed dependencies not in the API or the lockfile (#{deps.map(&:to_s).join(", ")}).
-Either installing with `--full-index` or running `bundle update rails` should fix the problem.
+Running `bundle update rails` should fix the problem.
E
end
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index 9738a75474..a54f1db772 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe "gemcutter's dependency API" do
end
it "falls back when the API errors out" do
- simulate_platform mswin
+ simulate_platform x86_mswin32
build_repo2 do
# The rcov gem is platform mswin32, but has no arch
@@ -359,7 +359,7 @@ RSpec.describe "gemcutter's dependency API" do
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec if the index of gems is large when doing back deps", :bundler => "< 3" do
+ it "does not fetch every spec when doing back deps", :bundler => "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -369,9 +369,7 @@ RSpec.describe "gemcutter's dependency API" do
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- 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)
+ install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => env_for_missing_prerelease_default_gem_activation
source "#{source_uri}"
source "#{source_uri}/extra"
gem "back_deps"
@@ -380,7 +378,7 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "does not fetch every spec if the index of gems is large when doing back deps using blocks" do
+ it "does not fetch every spec when doing back deps using blocks" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -390,9 +388,7 @@ RSpec.describe "gemcutter's dependency API" do
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- 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)
+ install_gemfile <<-G, :artifice => "endpoint_extra_missing", :env => env_for_missing_prerelease_default_gem_activation
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -402,17 +398,6 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "uses the endpoint if all sources support it" do
- gemfile <<-G
- source "#{source_uri}"
-
- gem 'foo'
- G
-
- bundle :install, :artifice => "endpoint_api_missing"
- expect(the_bundle).to include_gems "foo 1.0"
- end
-
it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
@@ -454,6 +439,22 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "back_deps 1.0"
end
+ it "does not fetch all marshaled specs" do
+ build_repo2 do
+ build_gem "foo", "1.0"
+ build_gem "foo", "2.0"
+ end
+
+ install_gemfile <<-G, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :verbose => true
+ source "#{source_uri}"
+
+ gem "foo"
+ G
+
+ expect(out).to include("foo-2.0.gemspec.rz")
+ expect(out).not_to include("foo-1.0.gemspec.rz")
+ end
+
it "does not refetch if the only unmet dependency is bundler" do
build_repo2 do
build_gem "bundler_dep" do |s|
@@ -471,18 +472,6 @@ RSpec.describe "gemcutter's dependency API" do
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "endpoint"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
it "installs the binstubs", :bundler => "< 3" do
gemfile <<-G
source "#{source_uri}"
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index 326ec51214..d5fa55be48 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -156,7 +156,7 @@ RSpec.describe "bundle flex_install" do
end
end
- describe "when Gemfile conflicts with lockfile" do
+ describe "when running bundle install and Gemfile conflicts with lockfile" do
before(:each) do
build_repo2
install_gemfile <<-G
@@ -190,28 +190,64 @@ RSpec.describe "bundle flex_install" do
expect(err).to match(/could not find gem 'rack-obama/i)
end
- it "suggests bundle update when the Gemfile requires different versions than the lock" do
+ it "discards the locked gems when the Gemfile requires different versions than the lock" do
bundle "config set force_ruby_platform true"
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "rack":
- In snapshot (Gemfile.lock):
- rack (= 0.9.1)
+ Could not find compatible versions
- In Gemfile:
- rack-obama (= 2.0) was resolved to 2.0, which depends on
- rack (= 1.2)
-
- rack_middleware was resolved to 1.0, which depends on
- rack (= 0.9.1)
-
- Running `bundle update` will rebuild your snapshot from scratch, using only
- the gems in your Gemfile, which may resolve the conflict.
+ Because rack-obama >= 2.0 depends on rack = 1.2
+ and rack = 1.2 could not be found in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally,
+ rack-obama >= 2.0 cannot be used.
+ So, because Gemfile depends on rack-obama = 2.0,
+ version solving has failed.
E
bundle :install, :retry => 0, :raise_on_error => false
expect(err).to end_with(nice_error)
end
+
+ it "does not include conflicts with a single requirement tree, because that can't possibly be a conflict" do
+ bundle "config set force_ruby_platform true"
+
+ bad_error = <<-E.strip.gsub(/^ {8}/, "")
+ Bundler could not find compatible versions for gem "rack-obama":
+ In Gemfile:
+ rack-obama (= 2.0)
+ E
+
+ bundle "update rack_middleware", :retry => 0, :raise_on_error => false
+ expect(err).not_to end_with(bad_error)
+ end
+ end
+
+ describe "when running bundle update and Gemfile conflicts with lockfile" do
+ before(:each) do
+ build_repo4 do
+ build_gem "jekyll-feed", "0.16.0"
+ build_gem "jekyll-feed", "0.15.1"
+
+ build_gem "github-pages", "226" do |s|
+ s.add_dependency "jekyll-feed", "0.15.1"
+ end
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "jekyll-feed", "~> 0.12"
+ G
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "github-pages", "~> 226"
+ gem "jekyll-feed", "~> 0.12"
+ G
+ end
+
+ it "discards the conflicting lockfile information and resolves properly" do
+ bundle :update, :raise_on_error => false, :all => true
+ expect(err).to be_empty
+ end
end
describe "subtler cases" do
@@ -229,14 +265,27 @@ RSpec.describe "bundle flex_install" do
G
end
- it "does something" do
- expect do
- bundle "install", :raise_on_error => false
- end.not_to change { File.read(bundled_app_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
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack (= 0.9.1)
+ rack-obama
- expect(err).to include("rack = 0.9.1")
- expect(err).to include("locked at 1.0.0")
- expect(err).to include("bundle update rack")
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
it "should work when you update" do
@@ -259,24 +308,24 @@ RSpec.describe "bundle flex_install" do
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
@@ -301,7 +350,7 @@ RSpec.describe "bundle flex_install" do
end
end
- it "prints the correct error message" do
+ it "resolves them" do
# install Rails 3.0.0.rc
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -310,13 +359,12 @@ RSpec.describe "bundle flex_install" do
G
# upgrade Rails to 3.0.0 and then install again
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0.0"
gem "capybara", "0.3.9"
G
-
- expect(err).to include("Gemfile.lock")
+ expect(err).to be_empty
end
end
end
diff --git a/spec/bundler/install/gems/fund_spec.rb b/spec/bundler/install/gems/fund_spec.rb
index f521b0296f..9aadc9ed25 100644
--- a/spec/bundler/install/gems/fund_spec.rb
+++ b/spec/bundler/install/gems/fund_spec.rb
@@ -6,20 +6,20 @@ RSpec.describe "bundle install" 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",
+ "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",
+ "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",
+ "funding_uri" => "https://example.com/has_funding/funding",
}
end
@@ -52,6 +52,33 @@ RSpec.describe "bundle install" do
end
end
+ context "when gems include a fund URI but `ignore_funding_requests` is configured" do
+ before do
+ bundle "config set ignore_funding_requests true"
+ end
+
+ it "does not display 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).not_to include("2 installed gems you directly depend on are looking for funding.")
+ end
+
+ it "does not display 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).not_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
diff --git a/spec/bundler/install/gems/native_extensions_spec.rb b/spec/bundler/install/gems/native_extensions_spec.rb
index d5cafcfc2c..5c18d2cc51 100644
--- a/spec/bundler/install/gems/native_extensions_spec.rb
+++ b/spec/bundler/install/gems/native_extensions_spec.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-RSpec.describe "installing a gem with native extensions", :ruby_repo do
+RSpec.describe "installing a gem with native extensions" do
it "installs" do
build_repo2 do
build_gem "c_extension" do |s|
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-E
require "mkmf"
+ $extout = "$(topdir)/" + RbConfig::CONFIG["EXTOUT"]
name = "c_extension_bundle"
dir_config(name)
raise "OMG" unless with_config("c_extension") == "hello"
@@ -51,6 +52,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-E
require "mkmf"
+ $extout = "$(topdir)/" + RbConfig::CONFIG["EXTOUT"]
name = "c_extension_bundle"
dir_config(name)
raise "OMG" unless with_config("c_extension") == "hello"
@@ -95,6 +97,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-E
require "mkmf"
+ $extout = "$(topdir)/" + RbConfig::CONFIG["EXTOUT"]
name = "c_extension_bundle_#{n}"
dir_config(name)
raise "OMG" unless with_config("c_extension_#{n}") == "#{n}"
@@ -147,6 +150,7 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
s.extensions = ["ext/extconf.rb"]
s.write "ext/extconf.rb", <<-E
require "mkmf"
+ $extout = "$(topdir)/" + RbConfig::CONFIG["EXTOUT"]
name = "c_extension_bundle"
dir_config(name)
raise "OMG" unless with_config("c_extension") == "hello" && with_config("c_extension_bundle-dir") == "hola"
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index 94fac0052c..fb6dda2f88 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "bundle install with install-time dependencies" do
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
f.puts "IMPLICIT_RAKE_DEP = 'YES'"
@@ -20,7 +20,7 @@ RSpec.describe "bundle install with install-time dependencies" do
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
@@ -42,7 +42,7 @@ RSpec.describe "bundle install with install-time dependencies" do
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
- path = File.expand_path("../lib", __FILE__)
+ path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/net_build_extensions.rb", "w") do |f|
f.puts "NET_BUILD_EXTENSIONS = 'YES'"
@@ -101,8 +101,6 @@ RSpec.describe "bundle install with install-time dependencies" do
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"
@@ -110,7 +108,7 @@ RSpec.describe "bundle install with install-time dependencies" do
spec.dependencies.each do |d|
d.instance_variable_set(:@type, :fail)
end
- File.open(path, "w") do |f|
+ File.open(path, "wb") do |f|
f.write Gem.deflate(Marshal.dump(spec))
end
@@ -161,7 +159,7 @@ RSpec.describe "bundle install with install-time dependencies" do
bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
- expect(out).to include("BUNDLER: Starting resolution")
+ expect(out).to include("Resolving dependencies...")
end
end
@@ -175,7 +173,7 @@ RSpec.describe "bundle install with install-time dependencies" do
bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
- expect(out).to include("BUNDLER: Starting resolution")
+ expect(out).to include("Resolving dependencies...")
end
end
@@ -189,16 +187,10 @@ RSpec.describe "bundle install with install-time dependencies" do
bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" }
- activated_groups = if local_platforms.any?
- "net_b (1.0) (ruby), net_b (1.0) (#{local_platforms.join(", ")})"
- else
- "net_b (1.0) (ruby)"
- end
-
expect(out).to include(" net_b").
- and include("BUNDLER: Starting resolution").
- and include("BUNDLER: Finished resolution").
- and include("Attempting to activate [#{activated_groups}]")
+ and include("Resolving dependencies...").
+ and include("Solution found after 1 attempts:").
+ and include("selected net_b 1.0")
end
end
end
@@ -217,15 +209,252 @@ RSpec.describe "bundle install with install-time dependencies" do
end
install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.ruby_version}"
+ source "http://localgemserver.test/"
+ gem 'rack'
+ G
+
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("rack 1.2")
+ end
+
+ it "installs the older version when using servers not implementing the compact index API" do
+ build_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
+ build_gem "rack", "9001.0.0" do |s|
+ s.required_ruby_version = "> 9000"
+ end
+ end
+
+ install_gemfile <<-G, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ ruby "#{Gem.ruby_version}"
source "http://localgemserver.test/"
gem 'rack'
G
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
+ context "when there is a lockfile using the newer incompatible version" do
+ before do
+ build_repo2 do
+ build_gem "parallel_tests", "3.7.0" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+ end
+
+ build_gem "parallel_tests", "3.8.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+ end
+ end
+
+ gemfile <<-G
+ source "http://localgemserver.test/"
+ gem 'parallel_tests'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ parallel_tests (3.8.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically updates lockfile to use the older version" do
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ parallel_tests (3.7.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "gives a meaningful error if we're in frozen mode" do
+ expect do
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s, "BUNDLE_FROZEN" => "true" }, :raise_on_error => false
+ end.not_to change { lockfile }
+
+ expect(err).to include("parallel_tests-3.8.0 requires ruby version >= #{next_ruby_minor}")
+ expect(err).not_to include("That means the author of parallel_tests (3.8.0) has removed it.")
+ end
+ end
+
+ context "with transitive dependencies in a lockfile" do
+ before do
+ build_repo2 do
+ build_gem "rubocop", "1.28.2" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+
+ s.add_dependency "rubocop-ast", ">= 1.17.0", "< 2.0"
+ end
+
+ build_gem "rubocop", "1.35.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+
+ s.add_dependency "rubocop-ast", ">= 1.20.1", "< 2.0"
+ end
+
+ build_gem "rubocop-ast", "1.17.0" do |s|
+ s.required_ruby_version = ">= #{current_ruby_minor}"
+ end
+
+ build_gem "rubocop-ast", "1.21.0" do |s|
+ s.required_ruby_version = ">= #{next_ruby_minor}"
+ end
+ end
+
+ gemfile <<-G
+ source "http://localgemserver.test/"
+ gem 'rubocop'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ rubocop (1.35.0)
+ rubocop-ast (>= 1.20.1, < 2.0)
+ rubocop-ast (1.21.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ parallel_tests
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically updates lockfile to use the older compatible versions" do
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ rubocop (1.28.2)
+ rubocop-ast (>= 1.17.0, < 2.0)
+ rubocop-ast (1.17.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rubocop
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with a Gemfile and lock file that don't resolve under the current platform" do
+ before do
+ build_repo4 do
+ build_gem "sorbet", "0.5.10554" do |s|
+ s.add_dependency "sorbet-static", "0.5.10554"
+ end
+
+ build_gem "sorbet-static", "0.5.10554" do |s|
+ s.platform = "universal-darwin-21"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'sorbet', '= 0.5.10554'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ sorbet (0.5.10554)
+ sorbet-static (= 0.5.10554)
+ sorbet-static (0.5.10554-universal-darwin-21)
+
+ PLATFORMS
+ arm64-darwin-21
+
+ DEPENDENCIES
+ sorbet (= 0.5.10554)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a proper error" do
+ simulate_platform "aarch64-linux" do
+ bundle "install", :raise_on_error => false
+ end
+
+ nice_error = strip_whitespace(<<-E).strip
+ Could not find gem 'sorbet-static (= 0.5.10554)' with platforms 'arm64-darwin-21', 'aarch64-linux' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static (= 0.5.10554)':
+ * sorbet-static-0.5.10554-universal-darwin-21
+ E
+ expect(err).to end_with(nice_error)
+ end
+ end
+
+ it "gives a meaningful error on ruby version mismatches between dependencies" do
+ build_repo4 do
+ build_gem "requires-old-ruby" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ build_lib("foo", :path => bundled_app) do |s|
+ s.required_ruby_version = ">= #{Gem.ruby_version}"
+
+ s.add_dependency "requires-old-ruby"
+ end
+
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo4)}"
+ gemspec
+ G
+
+ expect(err).to end_with <<~E.strip
+ Could not find compatible versions
+
+ Because every version of foo depends on requires-old-ruby >= 0
+ and every version of requires-old-ruby depends on Ruby < #{Gem.ruby_version},
+ every version of foo requires Ruby < #{Gem.ruby_version}.
+ So, because Gemfile depends on foo >= 0
+ and current Ruby version is = #{Gem.ruby_version},
+ version solving has failed.
+ E
+ end
+
it "installs the older version under rate limiting conditions" do
build_repo4 do
build_gem "rack", "9001.0.0" do |s|
@@ -236,13 +465,13 @@ RSpec.describe "bundle install with install-time dependencies" do
end
install_gemfile <<-G, :artifice => "compact_index_rate_limited", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.ruby_version}"
source "http://localgemserver.test/"
gem 'rack'
gem 'foo1'
G
- expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
@@ -252,22 +481,22 @@ RSpec.describe "bundle install with install-time dependencies" do
s.required_ruby_version = "> 9000"
end
build_gem "rack", "1.2" do |s|
- s.platform = mingw
+ s.platform = x86_mingw32
s.required_ruby_version = "> 9000"
end
build_gem "rack", "1.2"
end
- simulate_platform mingw do
+ simulate_platform x86_mingw32 do
install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- ruby "#{RUBY_VERSION}"
+ ruby "#{Gem.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(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("rack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
end
@@ -281,13 +510,31 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- let(:ruby_requirement) { %("#{RUBY_VERSION}") }
- let(:error_message_requirement) { "~> #{RUBY_VERSION}.0" }
+ let(:ruby_requirement) { %("#{Gem.ruby_version}") }
+ let(:error_message_requirement) { "= #{Gem.ruby_version}" }
+
+ it "raises a proper error that mentions the current Ruby version during resolution" do
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :raise_on_error => false
+ source "http://localgemserver.test/"
+ gem 'require_ruby'
+ G
+
+ expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
+
+ nice_error = strip_whitespace(<<-E).strip
+ Could not find compatible versions
+
+ Because every version of require_ruby depends on Ruby > 9000
+ and Gemfile depends on require_ruby >= 0,
+ Ruby > 9000 is required.
+ So, because current Ruby version is #{error_message_requirement},
+ version solving has failed.
+ E
+ expect(err).to end_with(nice_error)
+ end
shared_examples_for "ruby version conflicts" do
it "raises an error during resolution" do
- 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}
@@ -297,14 +544,13 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to_not include("Gem::InstallError: require_ruby requires Ruby version > 9000")
nice_error = strip_whitespace(<<-E).strip
- Bundler found conflicting requirements for the Ruby\0 version:
- In Gemfile:
- Ruby\0 (#{error_message_requirement})
-
- require_ruby was resolved to 1.0, which depends on
- Ruby\0 (> 9000)
+ Could not find compatible versions
- Ruby\0 (> 9000), which is required by gem 'require_ruby', is not available in the local ruby installation
+ Because every version of require_ruby depends on Ruby > 9000
+ and Gemfile depends on require_ruby >= 0,
+ Ruby > 9000 is required.
+ So, because current Ruby version is #{error_message_requirement},
+ version solving has failed.
E
expect(err).to end_with(nice_error)
end
@@ -314,7 +560,6 @@ RSpec.describe "bundle install with install-time dependencies" do
describe "with a < requirement" do
let(:ruby_requirement) { %("< 5000") }
- let(:error_message_requirement) { "< 5000" }
it_behaves_like "ruby version conflicts"
end
@@ -322,7 +567,6 @@ RSpec.describe "bundle install with install-time dependencies" do
describe "with a compound requirement" do
let(:reqs) { ["> 0.1", "< 5000"] }
let(:ruby_requirement) { reqs.map(&:dump).join(", ") }
- let(:error_message_requirement) { Gem::Requirement.new(reqs).to_s }
it_behaves_like "ruby version conflicts"
end
@@ -343,7 +587,14 @@ RSpec.describe "bundle install with install-time dependencies" do
G
expect(err).to_not include("Gem::InstallError: require_rubygems requires RubyGems version > 9000")
- expect(err).to include("require_rubygems-1.0 requires rubygems version > 9000, which is incompatible with the current version, #{Gem::VERSION}")
+ nice_error = strip_whitespace(<<-E).strip
+ Because every version of require_rubygems depends on RubyGems > 9000
+ and Gemfile depends on require_rubygems >= 0,
+ RubyGems > 9000 is required.
+ So, because current RubyGems version is = #{Gem::VERSION},
+ version solving has failed.
+ E
+ expect(err).to end_with(nice_error)
end
end
end
diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb
index b3b9d4d46b..4d08752256 100644
--- a/spec/bundler/install/gems/standalone_spec.rb
+++ b/spec/bundler/install/gems/standalone_spec.rb
@@ -32,6 +32,21 @@ RSpec.shared_examples "bundle install --standalone" do
expect(out).to eq(expected_gems.values.join("\n"))
end
+ it "makes the gems available without bundler nor rubygems" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nrequire \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
+ end
+ sys_exec %(#{Gem.ruby} --disable-gems -w -e #{testrb.shellescape})
+
+ 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")
@@ -108,7 +123,113 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
end
- describe "with gems with native extension", :ruby_repo do
+ 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 "tsort --version 0.1.0"
+
+ necessary_system_gems = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.2.0", "stringio --version 3.0.1"]
+ necessary_system_gems += ["shellwords --version 0.1.0", "base64 --version 0.1.0", "resolv --version 0.2.1"] if Gem.rubygems_version < Gem::Version.new("3.3.a")
+ necessary_system_gems += ["yaml --version 0.1.1"] if Gem.rubygems_version < Gem::Version.new("3.4.a")
+ realworld_system_gems(*necessary_system_gems, :path => scoped_gem_path(bundled_app("bundle")))
+
+ build_gem "foo", "1.0.0", :to_system => true, :default => true do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0", :to_system => true, :default => true
+
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ G
+
+ bundle "lock", :dir => cwd, :artifice => "compact_index"
+ end
+
+ it "works and points to the vendored copies, not to the default copies", :realworld do
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :dir => cwd, :artifice => "compact_index", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+
+ load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
+
+ expect(load_path_lines).to eq [
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/bar-1.0.0/lib")',
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/foo-1.0.0/lib")',
+ ]
+ end
+ end
+
+ describe "with Gemfiles using absolute path sources and resulting bundle moved to a folder hierarchy with different nesting" do
+ 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 Gemfiles using relative path sources and app moved to a different root" do
+ before do
+ FileUtils.mkdir_p bundled_app("app/vendor")
+
+ build_lib "minitest", "1.0.0", :path => bundled_app("app/vendor/minitest")
+
+ gemfile bundled_app("app/Gemfile"), <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "minitest", :path => "vendor/minitest"
+ G
+
+ bundle "install", :standalone => true, :dir => bundled_app("app")
+
+ FileUtils.mv(bundled_app("app"), bundled_app2("app"))
+ end
+
+ it "also works" do
+ ruby <<-RUBY, :dir => bundled_app2("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" do
before do
bundle "config set --local path #{bundled_app("bundle")}"
install_gemfile <<-G, :standalone => true, :dir => cwd
@@ -119,9 +240,13 @@ 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 File.expand_path("#{path}/../#{ruby_engine}/#{ruby_version}/extensions/'
- expect(extension_line).to end_with '/very_simple_binary-1.0")'
+ script_content = File.read(expected_path)
+ expect(script_content).to include("def self.ruby_api_version")
+ expect(script_content).to include("def self.extension_api_version")
+ extension_line = script_content.each_line.find {|line| line.include? "/extensions/" }.strip
+ platform = Gem::Platform.local
+ expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/'
+ expect(extension_line).to end_with platform.to_s + '/#{Gem.extension_api_version}/very_simple_binary-1.0")'
end
end
@@ -130,7 +255,7 @@ RSpec.shared_examples "bundle install --standalone" do
build_git "bar", :gemspec => false do |s|
s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
- lib = File.expand_path('../lib/', __FILE__)
+ lib = File.expand_path('lib/', __dir__)
$:.unshift lib unless $:.include?(lib)
require 'bar/version'
@@ -344,7 +469,7 @@ RSpec.shared_examples "bundle install --standalone" do
it "creates stubs with the correct load path" do
extension_line = File.read(bundled_app("bin/rails")).each_line.find {|line| line.include? "$:.unshift" }.strip
- expect(extension_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath)
+ expect(extension_line).to eq %($:.unshift File.expand_path "../bundle", __dir__)
end
end
end
@@ -360,3 +485,31 @@ RSpec.describe "bundle install --standalone run in a subdirectory" do
include_examples("bundle install --standalone")
end
+
+RSpec.describe "bundle install --standalone --local" do
+ before do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ system_gems "rack-1.0.0", :path => default_bundle_path
+ end
+
+ it "generates script pointing to system gems" do
+ bundle "install --standalone --local --verbose"
+
+ expect(out).to include("Using rack 1.0.0")
+
+ load_error_ruby <<-RUBY, "spec"
+ require "./bundler/setup"
+
+ require "rack"
+ puts RACK
+ require "spec"
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to eq("ZOMG LOAD ERROR")
+ end
+end
diff --git a/spec/bundler/install/gems/sudo_spec.rb b/spec/bundler/install/gems/sudo_spec.rb
deleted file mode 100644
index 3e5d38ea4c..0000000000
--- a/spec/bundler/install/gems/sudo_spec.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "when using sudo", :sudo => true do
- describe "and BUNDLE_PATH is writable" do
- context "but BUNDLE_PATH/build_info is not writable" do
- let(:subdir) do
- system_gem_path("cache")
- end
-
- before do
- bundle "config set path.system true"
- subdir.mkpath
- sudo "chmod u-w #{subdir}"
- end
-
- after do
- sudo "chmod u+w #{subdir}"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- expect(out).to_not match(/an error occurred/i)
- expect(system_gem_path("cache/rack-1.0.0.gem")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
- end
- end
-
- describe "and GEM_HOME is owned by root" do
- before :each do
- bundle "config set path.system true"
- chown_system_gems_to_root
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- gem "thin"
- G
-
- expect(system_gem_path("gems/rack-1.0.0")).to exist
- expect(system_gem_path("gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- 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_repo2)}"
- gem "rake"
- gem "another_implicit_rake_dep"
- G
- bundle "install"
- expect(system_gem_path("gems/another_implicit_rake_dep-1.0")).to exist
- end
-
- it "installs when BUNDLE_PATH is owned by root" do
- bundle_path = tmp("owned_by_root")
- FileUtils.mkdir_p bundle_path
- sudo "chown -R root #{bundle_path}"
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0")).to exist
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs when BUNDLE_PATH does not exist" do
- root_path = tmp("owned_by_root")
- FileUtils.mkdir_p root_path
- sudo "chown -R root #{root_path}"
- bundle_path = root_path.join("does_not_exist")
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0")).to exist
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs extensions/" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "very_simple_binary"
- G
-
- expect(system_gem_path("gems/very_simple_binary-1.0")).to exist
- binary_glob = system_gem_path("extensions/*/*/very_simple_binary-1.0")
- expect(Dir.glob(binary_glob).first).to be
- end
- end
-
- describe "and BUNDLE_PATH is not writable" do
- before do
- bundle "config set --local path .bundle"
- sudo "chmod ugo-w .bundle"
- end
-
- after do
- sudo "chmod ugo+w .bundle"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(local_gem_path("gems/rack-1.0.0")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "cleans up the tmpdirs generated" do
- require "tmpdir"
- Dir.glob("#{Dir.tmpdir}/bundler*").each do |tmpdir|
- FileUtils.remove_entry_secure(tmpdir)
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- tmpdirs = Dir.glob("#{Dir.tmpdir}/bundler*")
-
- expect(tmpdirs).to be_empty
- end
- end
-
- describe "and GEM_HOME is not writable" do
- it "installs" do
- 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'
- G
-
- bundle :install, :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
- expect(gem_home.join("bin/rackup")).to exist
- expect(the_bundle).to include_gems "rack 1.0", :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
-
- sudo "rm -rf #{tmp("sudo_gem_home")}"
- end
- end
-
- describe "and root runs install" do
- let(:warning) { "Don't run Bundler as root." }
-
- before do
- gemfile %(source "#{file_uri_for(gem_repo1)}")
- end
-
- it "warns against that" do
- bundle :install, :sudo => :preserve_env
- expect(err).to include(warning)
- end
-
- context "when ENV['BUNDLE_SILENCE_ROOT_WARNING'] is set" do
- it "skips the warning" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "true" }
- expect(err).to_not include(warning)
- end
- end
-
- context "when silence_root_warning = false" do
- it "warns against that" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" }
- expect(err).to include(warning)
- end
- end
- end
-end
diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb
index 0c4518fe2b..7b58ea9839 100644
--- a/spec/bundler/install/gemspecs_spec.rb
+++ b/spec/bundler/install/gemspecs_spec.rb
@@ -34,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|
@@ -44,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
@@ -92,7 +94,8 @@ RSpec.describe "bundle install" do
end
context "when ruby version is specified in gemspec and gemfile" do
- it "installs when patch level is not specified and the version matches" do
+ it "installs when patch level is not specified and the version matches",
+ :if => RUBY_PATCHLEVEL >= 0 do
build_lib("foo", :path => bundled_app) do |s|
s.required_ruby_version = "~> #{RUBY_VERSION}.0"
end
diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb
index d43aacee7e..882f2a2d42 100644
--- a/spec/bundler/install/git_spec.rb
+++ b/spec/bundler/install/git_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "bundle install" do
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(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
@@ -37,16 +37,16 @@ RSpec.describe "bundle install" do
install_gemfile <<-G, :verbose => true
source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "master~2"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "main~2"
G
- expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev})")
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main~2@#{rev})")
expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true
bundle :update, :all => true, :verbose => true
- expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev2})")
+ expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at main~2@#{rev2})")
expect(the_bundle).to include_gems "foo 2.0", :source => "git@#{lib_path("foo")}"
end
@@ -98,5 +98,77 @@ RSpec.describe "bundle install" do
bundle "info zebra"
expect(out).to include("* zebra (2.0 #{revision_for(lib_path("gems"))[0..6]})")
end
+
+ it "should always sort dependencies in the same order" do
+ # This Gemfile + lockfile had a problem where the first
+ # `bundle install` would change the order, but the second would
+ # change it back.
+
+ # NOTE: both gems MUST have the same path! It has to be two gems in one repo.
+
+ test = build_git "test", "1.0.0", :path => lib_path("test-and-other")
+ other = build_git "other", "1.0.0", :path => lib_path("test-and-other")
+ test_ref = test.ref_for("HEAD")
+ other_ref = other.ref_for("HEAD")
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "test", git: #{test.path.to_s.inspect}
+ gem "other", ref: #{other_ref.inspect}, git: #{other.path.to_s.inspect}
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{test.path}
+ revision: #{test_ref}
+ specs:
+ test (1.0.0)
+
+ GIT
+ remote: #{other.path}
+ revision: #{other_ref}
+ ref: #{other_ref}
+ specs:
+ other (1.0.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ other!
+ test!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ # If GH#6743 is present, the first `bundle install` will change the
+ # lockfile, by flipping the order (`other` would be moved to the top).
+ #
+ # The second `bundle install` would then change the lockfile back
+ # to the original.
+ #
+ # The fix makes it so it may change it once, but it will not change
+ # it a second time.
+ #
+ # So, we run `bundle install` once, and store the value of the
+ # modified lockfile.
+ bundle :install
+ modified_lockfile = lockfile
+
+ # If GH#6743 is present, the second `bundle install` would change the
+ # lockfile back to what it was originally.
+ #
+ # This `expect` makes sure it doesn't change a second time.
+ bundle :install
+ expect(lockfile).to eq(modified_lockfile)
+
+ expect(out).to include("Bundle complete!")
+ end
end
end
diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb
index 9bc243e7cf..be34d8b5bc 100644
--- a/spec/bundler/install/global_cache_spec.rb
+++ b/spec/bundler/install/global_cache_spec.rb
@@ -37,6 +37,18 @@ 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"
@@ -113,7 +125,7 @@ RSpec.describe "global gem caching" do
expect(source2_global_cache("rack-0.9.1.gem")).to exist
bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false
expect(err).to include("Internal Server Error 500")
- expect(err).not_to include("please copy and paste the report template above into a new issue")
+ 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"
@@ -128,7 +140,7 @@ RSpec.describe "global gem caching" do
expect(source2_global_cache("rack-0.9.1.gem")).to exist
bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false
expect(err).to include("Internal Server Error 500")
- expect(err).not_to include("please copy and paste the report template above into a new issue")
+ 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"
@@ -193,7 +205,7 @@ RSpec.describe "global gem caching" do
end
describe "extension caching" do
- it "works", :ruby_repo do
+ it "works" do
skip "gets incorrect ref in path" if Gem.win_platform?
build_git "very_simple_git_binary", &:add_c_extension
@@ -208,9 +220,9 @@ RSpec.describe "global gem caching" do
gem "very_simple_path_binary", :path => "#{lib_path("very_simple_path_binary-1.0")}"
G
- gem_binary_cache = home(".bundle", "cache", "extensions", specific_local_platform.to_s, Bundler.ruby_scope,
+ gem_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
Digest(:MD5).hexdigest("#{gem_repo1}/"), "very_simple_binary-1.0")
- git_binary_cache = home(".bundle", "cache", "extensions", specific_local_platform.to_s, Bundler.ruby_scope,
+ git_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
"very_simple_git_binary-1.0-#{revision}", "very_simple_git_binary-1.0")
cached_extensions = Pathname.glob(home(".bundle", "cache", "extensions", "*", "*", "*", "*", "*")).sort
diff --git a/spec/bundler/install/path_spec.rb b/spec/bundler/install/path_spec.rb
index b0392c4ed2..bd5385b265 100644
--- a/spec/bundler/install/path_spec.rb
+++ b/spec/bundler/install/path_spec.rb
@@ -176,7 +176,7 @@ RSpec.describe "bundle install" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "re-installs gems whose extensions have been deleted", :ruby_repo do
+ it "re-installs gems whose extensions have been deleted" do
build_lib "very_simple_binary", "1.0.0", :to_system => true do |s|
s.write "lib/very_simple_binary.rb", "raise 'FAIL'"
end
diff --git a/spec/bundler/install/process_lock_spec.rb b/spec/bundler/install/process_lock_spec.rb
index dac0d34bc4..1f8c62f26e 100644
--- a/spec/bundler/install/process_lock_spec.rb
+++ b/spec/bundler/install/process_lock_spec.rb
@@ -31,5 +31,27 @@ RSpec.describe "process lock spec" do
expect(processed).to eq true
end
end
+
+ context "when creating a lock raises Errno::EPERM" do
+ before { allow(File).to receive(:open).and_raise(Errno::EPERM) }
+
+ it "skips creating the lock file and yields" do
+ processed = false
+ Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
+
+ expect(processed).to eq true
+ end
+ end
+
+ context "when creating a lock raises Errno::EROFS" do
+ before { allow(File).to receive(:open).and_raise(Errno::EROFS) }
+
+ it "skips creating the lock file and yields" do
+ processed = false
+ Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
+
+ expect(processed).to eq true
+ end
+ end
end
end
diff --git a/spec/bundler/install/yanked_spec.rb b/spec/bundler/install/yanked_spec.rb
index 6d3065a836..dc054b50bb 100644
--- a/spec/bundler/install/yanked_spec.rb
+++ b/spec/bundler/install/yanked_spec.rb
@@ -15,7 +15,7 @@ RSpec.context "when installing a bundle that includes yanked gems" do
foo (10.0.0)
PLATFORMS
- ruby
+ #{lockfile_platforms}
DEPENDENCIES
foo (= 10.0.0)
@@ -30,6 +30,72 @@ RSpec.context "when installing a bundle that includes yanked gems" do
expect(err).to include("Your bundle is locked to foo (10.0.0)")
end
+ context "when a re-resolve is necessary, and a yanked version is considered by the resolver" do
+ before do
+ skip "Materialization on Windows is not yet strict, so the example does not detect the gem has been yanked" if Gem.win_platform?
+
+ build_repo4 do
+ build_gem "foo", "1.0.0", "1.0.1"
+ build_gem "actiontext", "6.1.7" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "actiontext", "6.1.6" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "actiontext", "6.1.7" do |s|
+ s.add_dependency "nokogiri", ">= 1.8"
+ end
+ build_gem "nokogiri", "1.13.8"
+ end
+
+ gemfile <<~G
+ source "#{source_uri}"
+ gem "foo", "1.0.1"
+ gem "actiontext", "6.1.6"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{source_uri}/
+ specs:
+ actiontext (6.1.6)
+ nokogiri (>= 1.8)
+ foo (1.0.0)
+ nokogiri (1.13.8-#{Bundler.local_platform})
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ actiontext (= 6.1.6)
+ foo (= 1.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ context "and the old index is used" do
+ let(:source_uri) { file_uri_for(gem_repo4) }
+
+ it "reports the yanked gem properly" do
+ bundle "install", :raise_on_error => false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
+ end
+
+ context "and the compact index API is used" do
+ let(:source_uri) { "https://gem.repo4" }
+
+ it "reports the yanked gem properly" do
+ bundle "install", :artifice => "compact_index", :raise_on_error => false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
+ end
+ end
+
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"
@@ -43,6 +109,63 @@ RSpec.context "when installing a bundle that includes yanked gems" do
end
end
+RSpec.context "when resolving a bundle that includes yanked gems, but unlocking an unrelated gem" do
+ before(:each) do
+ build_repo4 do
+ build_gem "foo", "10.0.0"
+
+ build_gem "bar", "1.0.0"
+ build_gem "bar", "2.0.0"
+ end
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}
+ specs:
+ foo (9.0.0)
+ bar (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "foo"
+ gem "bar"
+ G
+ end
+
+ it "does not update the yanked gem" do
+ bundle "lock --update bar"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ bar (2.0.0)
+ foo (9.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ bar
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+end
+
RSpec.context "when using gem before installing" do
it "does not suggest the author has yanked the gem" do
gemfile <<-G
@@ -57,16 +180,53 @@ RSpec.context "when using gem before installing" do
rack (0.9.1)
PLATFORMS
- ruby
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack (= 0.9.1)
+ L
+
+ bundle :list, :raise_on_error => false
+
+ expect(err).to include("Could not find rack-0.9.1 in locally installed gems")
+ expect(err).to_not include("Your bundle is locked to rack (0.9.1) from")
+ expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
+ expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
+
+ # Check error message is still correct when multiple platforms are locked
+ lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
+
+ bundle :list, :raise_on_error => false
+ expect(err).to include("Could not find rack-0.9.1 in locally installed gems")
+ 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
+ #{lockfile_platforms}
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 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 include("Could not find rack-0.9.1, rack_middleware-1.0 in locally installed gems")
+ expect(err).to include("Install missing gems with `bundle install`.")
+ expect(err).to_not include("Your bundle is locked to rack (0.9.1) from")
expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
end
diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb
index 56db5d8305..ac3d10223c 100644
--- a/spec/bundler/lock/git_spec.rb
+++ b/spec/bundler/lock/git_spec.rb
@@ -14,6 +14,52 @@ RSpec.describe "bundle lock with git gems" do
expect(the_bundle).to include_gems "foo 1.0.0"
end
+ it "doesn't print errors even if running lock after removing the cache" do
+ FileUtils.rm_rf(Dir[default_cache_path("git/foo-1.0-*")].first)
+
+ bundle "lock --verbose"
+
+ expect(err).to be_empty
+ end
+
+ it "prints a proper error when changing a locked Gemfile to point to a bad branch" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}", :branch => "bad"
+ G
+
+ bundle "lock --update foo", :env => { "LANG" => "en" }, :raise_on_error => false
+
+ expect(err).to include("Revision bad does not exist in the repository")
+ end
+
+ it "prints a proper error when installing a Gemfile with a locked ref that does not exist" do
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{"a" * 40}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install", :raise_on_error => false
+
+ expect(err).to include("Revision #{"a" * 40} does not exist in the repository")
+ end
+
it "locks a git source to the current ref" do
update_git "foo"
bundle :install
@@ -26,6 +72,87 @@ RSpec.describe "bundle lock with git gems" do
expect(out).to eq("WIN")
end
+ it "properly clones a git source locked to an out of date ref" do
+ update_git "foo"
+
+ bundle :install, :env => { "BUNDLE_PATH" => "foo" }
+ expect(err).to be_empty
+ end
+
+ it "properly fetches a git source locked to an unreachable ref" do
+ # Create a commit and make it unreachable
+ git "checkout -b foo ", lib_path("foo-1.0")
+ unreachable_sha = update_git("foo").ref_for("HEAD")
+ git "checkout main ", lib_path("foo-1.0")
+ git "branch -D foo ", lib_path("foo-1.0")
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{unreachable_sha}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(err).to be_empty
+ end
+
+ it "properly fetches a git source locked to an annotated tag" do
+ # Create an annotated tag
+ git("tag -a v1.0 -m 'Annotated v1.0'", lib_path("foo-1.0"))
+ annotated_tag = git("rev-parse v1.0", lib_path("foo-1.0"))
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{annotated_tag}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(err).to be_empty
+ end
+
it "provides correct #full_gem_path" do
run <<-RUBY
puts Bundler.rubygems.find_name('foo').first.full_gem_path
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index 0e2a3a3cd8..ccf23a9e3c 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -1,18 +1,8 @@
# frozen_string_literal: true
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
+ build_repo2
end
it "generates a simple lockfile for a single source, gem" do
@@ -22,7 +12,7 @@ RSpec.describe "the lockfile format" do
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -39,7 +29,7 @@ RSpec.describe "the lockfile format" do
G
end
- it "updates the lockfile's bundler version if current ver. is newer" do
+ it "updates the lockfile's bundler version if current ver. is newer, and version was forced through BUNDLER_VERSION" do
system_gems "bundler-1.8.2"
lockfile <<-L
@@ -64,13 +54,16 @@ RSpec.describe "the lockfile format" do
1.8.2
L
- install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ install_gemfile <<-G, :verbose => true, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with 1.8.2.")
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -87,8 +80,8 @@ RSpec.describe "the lockfile format" do
G
end
- it "does not update the lockfile's bundler version if nothing changed during bundle install" do
- version = "#{Bundler::VERSION.split(".").first}.0.0.a"
+ it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version", :rubygems => ">= 3.3.0.a", :realworld => true do
+ version = "2.3.0"
lockfile <<-L
GEM
@@ -106,13 +99,16 @@ RSpec.describe "the lockfile format" do
#{version}
L
- install_gemfile <<-G
+ install_gemfile <<-G, :verbose => true, :artifice => "vcr"
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.")
+ expect(out).to include("Using bundler #{version}")
+
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -129,7 +125,9 @@ RSpec.describe "the lockfile format" do
G
end
- it "updates the lockfile's bundler version if not present" do
+ it "does not update the lockfile's bundler version if nothing changed during bundle install, and uses the latest version", :rubygems => "< 3.3.0.a" do
+ version = "#{Bundler::VERSION.split(".").first}.0.0.a"
+
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -141,15 +139,21 @@ RSpec.describe "the lockfile format" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ #{version}
L
- install_gemfile <<-G
+ install_gemfile <<-G, :verbose => true
source "#{file_uri_for(gem_repo2)}"
- gem "rack", "> 0"
+ gem "rack"
G
- lockfile_should_be <<-G
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.")
+ expect(out).to include("Using bundler #{Bundler::VERSION}")
+
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -159,17 +163,14 @@ RSpec.describe "the lockfile format" do
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0)
+ rack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{version}
G
end
- it "warns if the current is older than lockfile's bundler version" do
- current_version = Bundler::VERSION
- newer_minor = bump_minor(current_version)
-
+ it "adds the BUNDLED WITH section if not present" do
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -181,25 +182,15 @@ RSpec.describe "the lockfile format" do
DEPENDENCIES
rack
-
- BUNDLED WITH
- #{newer_minor}
L
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ gem "rack", "> 0"
G
- pre_flag = prerelease?(newer_minor) ? " --pre" : ""
- warning_message = "the running version of Bundler (#{current_version}) is older " \
- "than the version that created the lockfile (#{newer_minor}). " \
- "We suggest you to upgrade to the version that created the " \
- "lockfile by running `gem install bundler:#{newer_minor}#{pre_flag}`."
- expect(err).to include warning_message
-
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -209,14 +200,14 @@ RSpec.describe "the lockfile format" do
#{lockfile_platforms}
DEPENDENCIES
- rack
+ rack (> 0)
BUNDLED WITH
- #{newer_minor}
+ #{Bundler::VERSION}
G
end
- it "warns when updating bundler major version" do
+ it "update the bundler major version just fine" do
current_version = Bundler::VERSION
older_major = previous_major(current_version)
@@ -244,12 +235,9 @@ RSpec.describe "the lockfile format" do
gem "rack"
G
- expect(err).to include(
- "Warning: the lockfile is being updated to Bundler " \
- "#{current_version.split(".").first}, after which you will be unable to return to Bundler #{older_major.split(".").first}."
- )
+ expect(err).to be_empty
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -273,7 +261,7 @@ RSpec.describe "the lockfile format" do
gem "rack-obama"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -299,7 +287,7 @@ RSpec.describe "the lockfile format" do
gem "rack-obama", ">= 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -333,7 +321,7 @@ 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:
@@ -366,7 +354,7 @@ RSpec.describe "the lockfile format" do
gem "net-sftp"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -395,10 +383,10 @@ RSpec.describe "the lockfile format" do
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")}
+ revision: #{git.ref_for("main")}
specs:
foo (1.0)
@@ -466,10 +454,10 @@ RSpec.describe "the lockfile format" do
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
+ revision: #{git.ref_for("main")}
specs:
foo (1.0)
@@ -497,7 +485,7 @@ RSpec.describe "the lockfile format" do
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")}
@@ -529,7 +517,7 @@ RSpec.describe "the lockfile format" do
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")}
@@ -552,6 +540,92 @@ RSpec.describe "the lockfile format" do
G
end
+ it "is conservative with dependencies of git gems" do
+ build_repo4 do
+ build_gem "orm_adapter", "0.4.1"
+ build_gem "orm_adapter", "0.5.0"
+ end
+
+ FileUtils.mkdir_p lib_path("ckeditor/lib")
+
+ @remote = build_git("ckeditor_remote", :bare => true)
+
+ build_git "ckeditor", :path => lib_path("ckeditor") do |s|
+ s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.7'"
+ s.version = "4.0.7"
+ s.add_dependency "orm_adapter"
+ end
+
+ update_git "ckeditor", :path => lib_path("ckeditor"), :remote => file_uri_for(@remote.path)
+ update_git "ckeditor", :path => lib_path("ckeditor"), :tag => "v4.0.7"
+ old_git = update_git "ckeditor", :path => lib_path("ckeditor"), :push => "v4.0.7"
+
+ update_git "ckeditor", :path => lib_path("ckeditor"), :gemspec => true do |s|
+ s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.8'"
+ s.version = "4.0.8"
+ s.add_dependency "orm_adapter"
+ end
+ update_git "ckeditor", :path => lib_path("ckeditor"), :tag => "v4.0.8"
+
+ new_git = update_git "ckeditor", :path => lib_path("ckeditor"), :push => "v4.0.8"
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "ckeditor", :git => "#{@remote.path}", :tag => "v4.0.8"
+ G
+
+ lockfile <<~L
+ GIT
+ remote: #{@remote.path}
+ revision: #{old_git.ref_for("v4.0.7")}
+ tag: v4.0.7
+ specs:
+ ckeditor (4.0.7)
+ orm_adapter
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ orm_adapter (0.4.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ckeditor!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ # Bumps the git gem, but keeps its dependency locked
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: #{@remote.path}
+ revision: #{new_git.ref_for("v4.0.8")}
+ tag: v4.0.8
+ specs:
+ ckeditor (4.0.8)
+ orm_adapter
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ orm_adapter (0.4.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ckeditor!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
it "serializes pinned path sources to the lockfile" do
build_lib "foo"
@@ -560,7 +634,7 @@ RSpec.describe "the lockfile format" do
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:
@@ -593,7 +667,7 @@ RSpec.describe "the lockfile format" do
bundle :cache
bundle :install, :local => true
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo-1.0")}
specs:
@@ -626,10 +700,10 @@ RSpec.describe "the lockfile format" do
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")}
+ revision: #{bar.ref_for("main")}
specs:
bar (1.0)
@@ -663,7 +737,7 @@ RSpec.describe "the lockfile format" do
gem "rack", :source => "#{file_uri_for(gem_repo2)}/"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -689,7 +763,7 @@ RSpec.describe "the lockfile format" do
gem "rack-obama"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -722,7 +796,7 @@ RSpec.describe "the lockfile format" do
gem "rails"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -755,12 +829,22 @@ RSpec.describe "the lockfile format" do
end
it "orders dependencies by version" do
+ update_repo2 do
+ # Capistrano did this (at least until version 2.5.10)
+ # RubyGems 2.2 doesn't allow the specifying of a dependency twice
+ # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f
+ build_gem "double_deps", "1.0", :skip_validation => true do |s|
+ s.add_dependency "net-ssh", ">= 1.0.0"
+ s.add_dependency "net-ssh"
+ end
+ end
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}/"
gem 'double_deps'
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -787,7 +871,7 @@ RSpec.describe "the lockfile format" do
gem "rack-obama", ">= 1.0", :require => "rack/obama"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -813,7 +897,7 @@ RSpec.describe "the lockfile format" do
gem "rack-obama", ">= 1.0", :group => :test
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -842,7 +926,7 @@ RSpec.describe "the lockfile format" do
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: foo
specs:
@@ -873,7 +957,7 @@ RSpec.describe "the lockfile format" do
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: ../foo
specs:
@@ -899,12 +983,12 @@ RSpec.describe "the lockfile format" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- path File.expand_path("../foo", __FILE__) do
+ path File.expand_path("foo", __dir__) do
gem "foo"
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: foo
specs:
@@ -933,7 +1017,7 @@ RSpec.describe "the lockfile format" do
gemspec :path => "../foo"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: ../foo
specs:
@@ -977,15 +1061,14 @@ RSpec.describe "the lockfile format" do
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
PLATFORMS
- java
- #{lockfile_platforms}
+ #{lockfile_platforms("java")}
DEPENDENCIES
rack
@@ -1009,7 +1092,7 @@ RSpec.describe "the lockfile format" do
gem "platform_specific"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1038,7 +1121,7 @@ RSpec.describe "the lockfile format" do
gem "activesupport"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1064,7 +1147,7 @@ RSpec.describe "the lockfile format" do
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1088,7 +1171,7 @@ RSpec.describe "the lockfile format" do
gem "rack", "1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1112,7 +1195,7 @@ RSpec.describe "the lockfile format" do
gem "rack", "1.0", :group => :two
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1157,7 +1240,7 @@ RSpec.describe "the lockfile format" do
gem "rack", "> 0.9", "< 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1177,11 +1260,11 @@ RSpec.describe "the lockfile format" do
it "captures the Ruby version in the lockfile" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}/"
- ruby '#{RUBY_VERSION}'
+ ruby '#{Gem.ruby_version}'
gem "rack", "> 0.9", "< 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
@@ -1194,7 +1277,7 @@ RSpec.describe "the lockfile format" do
rack (> 0.9, < 1.0)
RUBY VERSION
- ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
@@ -1221,7 +1304,178 @@ RSpec.describe "the lockfile format" do
G
expect(err).to include("Downloading rack_middleware-1.0 revealed dependencies not in the API or the lockfile (#{Gem::Dependency.new("rack", "= 0.9.1")}).").
- and include("Either installing with `--full-index` or running `bundle update rack_middleware` should fix the problem.")
+ and include("Running `bundle update rack_middleware` should fix the problem.")
+ end
+
+ it "regenerates a lockfile with no specs" do
+ build_repo4 do
+ build_gem "indirect_dependency", "1.2.3" do |s|
+ s.metadata["funding_uri"] = "https://example.com/donate"
+ end
+
+ build_gem "direct_dependency", "4.5.6" do |s|
+ s.add_dependency "indirect_dependency", ">= 0"
+ end
+ end
+
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ direct_dependency
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "direct_dependency"
+ G
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ direct_dependency (4.5.6)
+ indirect_dependency
+ indirect_dependency (1.2.3)
+
+ PLATFORMS
+ #{formatted_lockfile_platforms(*["ruby", generic_local_platform].uniq)}
+
+ DEPENDENCIES
+ direct_dependency
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ shared_examples_for "a lockfile missing dependent specs" do
+ it "auto-heals" do
+ build_repo4 do
+ build_gem "minitest-bisect", "1.6.0" do |s|
+ s.add_dependency "path_expander", "~> 1.1"
+ end
+
+ build_gem "path_expander", "1.1.1"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "minitest-bisect"
+ G
+
+ # Corrupt lockfile (completely missing path_expander)
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ minitest-bisect (1.6.0)
+
+ PLATFORMS
+ #{platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ cache_gems "minitest-bisect-1.6.0", "path_expander-1.1.1", :gem_repo => gem_repo4
+ bundle :install
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ minitest-bisect (1.6.0)
+ path_expander (~> 1.1)
+ path_expander (1.1.1)
+
+ PLATFORMS
+ #{platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with just specific platform" do
+ let(:platforms) { lockfile_platforms }
+
+ it_behaves_like "a lockfile missing dependent specs"
+ end
+
+ context "with both ruby and specific platform" do
+ let(:platforms) { lockfile_platforms("ruby") }
+
+ it_behaves_like "a lockfile missing dependent specs"
+ end
+
+ it "auto-heals when the lockfile is missing specs" do
+ build_repo4 do
+ build_gem "minitest-bisect", "1.6.0" do |s|
+ s.add_dependency "path_expander", "~> 1.1"
+ end
+
+ build_gem "path_expander", "1.1.1"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "minitest-bisect"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ minitest-bisect (1.6.0)
+ path_expander (~> 1.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ expect(out).to include("re-resolving dependencies because your lock file is missing \"minitest-bisect\"")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ minitest-bisect (1.6.0)
+ path_expander (~> 1.1)
+ path_expander (1.1.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ minitest-bisect
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
describe "a line ending" do
diff --git a/spec/bundler/other/ext_spec.rb b/spec/bundler/other/ext_spec.rb
index e13f62a856..9b829a2b36 100644
--- a/spec/bundler/other/ext_spec.rb
+++ b/spec/bundler/other/ext_spec.rb
@@ -44,6 +44,10 @@ RSpec.describe "Bundler::GemHelpers#generic" do
expect(generic(pl("x64-mingw32"))).to eq(pl("x64-mingw32"))
expect(generic(pl("x86_64-mingw32"))).to eq(pl("x64-mingw32"))
end
+
+ it "converts 64-bit mingw UCRT platform variants into x64-mingw-ucrt" do
+ expect(generic(pl("x64-mingw-ucrt"))).to eq(pl("x64-mingw-ucrt"))
+ end
end
RSpec.describe "Gem::SourceIndex#refresh!" do
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index 688efbcec8..7b7ceb4586 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -92,6 +92,18 @@ 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, :raise_on_error => false
@@ -340,7 +352,7 @@ RSpec.describe "major deprecations" do
G
expect(warnings).to include(
- "Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.rb.locked."
+ "Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.locked."
)
expect(the_bundle).not_to include_gem "rack 1.0"
@@ -402,7 +414,7 @@ RSpec.describe "major deprecations" do
it "shows a deprecation", :bundler => "< 3" do
expect(deprecations).to include(
- "Your Gemfile contains multiple primary sources. " \
+ "Your Gemfile contains multiple global sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source."
@@ -413,7 +425,7 @@ RSpec.describe "major deprecations" do
bundle "install"
expect(deprecations).to include(
- "Your Gemfile contains multiple primary sources. " \
+ "Your Gemfile contains multiple global sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source."
@@ -426,7 +438,7 @@ RSpec.describe "major deprecations" do
bundle "install"
expect(deprecations).to include(
- "Your Gemfile contains multiple primary sources. " \
+ "Your Gemfile contains multiple global sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source."
@@ -500,7 +512,7 @@ RSpec.describe "major deprecations" do
it "should print a single deprecation warning" do
expect(warnings).to include(
- "Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.rb.locked."
+ "Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.locked."
)
end
end
@@ -522,90 +534,40 @@ RSpec.describe "major deprecations" do
pending "fails with a helpful error", :bundler => "3"
end
- describe Bundler::Dsl do
+ context "bundle show" do
before do
- @rubygems = double("rubygems")
- allow(Bundler::Source::Rubygems).to receive(:new) { @rubygems }
- end
-
- context "with github gems" do
- it "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.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
- end
-
- context "with bitbucket gems" do
- 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:
-
- git_source(:bitbucket) do |repo_name|
- user_name, repo_name = repo_name.split("/")
- repo_name ||= user_name
- "https://\#{user_name}@bitbucket.org/\#{user_name}/\#{repo_name}.git"
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
end
- EOS
- expect(Bundler.ui).to receive(:warn).with("[DEPRECATED] #{msg}")
- subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
+ context "with --outdated flag" do
+ before do
+ bundle "show --outdated"
end
- end
- context "with gist gems" do
- it "does not warn about removal", :bundler => "< 3" do
- expect(Bundler.ui).not_to receive(:warn)
- subject.gem("not-really-a-gem", :gist => "1234")
+ it "prints a deprecation warning informing about its removal", :bundler => "< 3" do
+ expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement")
end
- 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.ui).to receive(:warn).with("[DEPRECATED] #{msg}")
- subject.gem("not-really-a-gem", :gist => "1234")
- end
+ pending "fails with a helpful message", :bundler => "3"
end
end
- context "bundle show" do
+ context "bundle remove" do
before do
- install_gemfile <<-G
+ gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
end
- context "with --outdated flag" do
- before do
- bundle "show --outdated"
- end
+ context "with --install" do
+ it "shows a deprecation warning", :bundler => "< 3" do
+ bundle "remove rack --install"
- 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")
+ 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"
@@ -625,16 +587,15 @@ The :gist git source is deprecated, and will be removed in the future. Add this
pending "fails with a helpful message", :bundler => "3"
end
- context "bundle viz" do
+ context "bundle viz", :realworld do
before do
- graphviz_version = RUBY_VERSION >= "2.4" ? "1.2.5" : "1.2.4"
- realworld_system_gems "ruby-graphviz --version #{graphviz_version}"
+ realworld_system_gems "ruby-graphviz --version 1.2.5"
create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
bundle "viz"
end
it "prints a deprecation warning", :bundler => "< 3" do
- expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
+ 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"
diff --git a/spec/bundler/plugins/command_spec.rb b/spec/bundler/plugins/command_spec.rb
index 4567a39081..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 the following plugins: `copycat`")
-
- 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 c719e8533e..aec131f2ee 100644
--- a/spec/bundler/plugins/install_spec.rb
+++ b/spec/bundler/plugins/install_spec.rb
@@ -22,6 +22,13 @@ RSpec.describe "bundler plugin install" do
plugin_should_be_installed("foo")
end
+ it "installs from rubygems source in frozen mode" do
+ bundle "plugin install foo --source #{file_uri_for(gem_repo2)}", :env => { "BUNDLE_DEPLOYMENT" => "true" }
+
+ expect(out).to include("Installed plugin foo")
+ plugin_should_be_installed("foo")
+ end
+
it "installs from sources configured as Gem.sources without any flags" do
bundle "plugin install foo", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
@@ -32,7 +39,8 @@ RSpec.describe "bundler plugin install" do
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")
+ # The help message defined in ../../lib/bundler/man/bundle-plugin.1.ronn will be output.
+ expect(out).to include("You can install, uninstall, and list plugin(s)")
end
context "plugin is already installed" do
@@ -69,6 +77,41 @@ 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 "installs when --branch specified" do
+ bundle "plugin install foo --branch main --source #{file_uri_for(gem_repo2)}"
+
+ expect(out).to include("Installed plugin foo")
+ end
+
+ it "installs when --ref specified" do
+ bundle "plugin install foo --ref v1.2.3 --source #{file_uri_for(gem_repo2)}"
+
+ expect(out).to include("Installed plugin foo")
+ end
+
+ it "raises error when both --branch and --ref options are specified" do
+ bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --branch main --ref v1.2.3", :raise_on_error => false
+
+ expect(out).not_to include("Installed plugin foo")
+
+ expect(err).to include("You cannot specify `--branch` and `--ref` at the same time.")
+ end
+
it "works with different load paths" do
build_repo2 do
build_plugin "testing" do |s|
@@ -109,9 +152,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("Failed to install the following plugins: `charlie`. The underlying error was: 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
@@ -128,7 +171,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
diff --git a/spec/bundler/plugins/source/example_spec.rb b/spec/bundler/plugins/source/example_spec.rb
index e2bab9c199..9d153b6063 100644
--- a/spec/bundler/plugins/source/example_spec.rb
+++ b/spec/bundler/plugins/source/example_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe "real source plugins" do
it "writes to lock file" do
bundle "install"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PLUGIN SOURCE
remote: #{lib_path("a-path-gem-1.0")}
type: mpath
@@ -203,7 +203,7 @@ RSpec.describe "real source plugins" do
def initialize(opts)
super
- @ref = options["ref"] || options["branch"] || options["tag"] || "master"
+ @ref = options["ref"] || options["branch"] || options["tag"] || "main"
@unlocked = false
end
@@ -247,7 +247,7 @@ RSpec.describe "real source plugins" do
def options_to_lock
opts = {"revision" => revision}
- opts["ref"] = ref if ref != "master"
+ opts["ref"] = ref if ref != "main"
opts
end
@@ -304,13 +304,7 @@ RSpec.describe "real source plugins" do
@install_path ||= begin
git_scope = "\#{base_name}-\#{shortref_for_path(revision)}"
- path = gem_install_dir.join(git_scope)
-
- if !path.exist? && requires_sudo?
- user_bundle_path.join(ruby_scope).join(git_scope)
- else
- path
- end
+ gem_install_dir.join(git_scope)
end
end
@@ -342,7 +336,7 @@ RSpec.describe "real source plugins" 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
@@ -435,7 +429,7 @@ RSpec.describe "real source plugins" do
describe "bundle cache with gitp" do
it "copies repository to vendor cache and uses it" do
git = build_git "foo"
- ref = git.ref_for("master", 11)
+ ref = git.ref_for("main", 11)
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}" # plugin source
diff --git a/spec/bundler/quality_es_spec.rb b/spec/bundler/quality_es_spec.rb
index 90968e6270..0dbd77e451 100644
--- a/spec/bundler/quality_es_spec.rb
+++ b/spec/bundler/quality_es_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe "La biblioteca si misma" do
included = /ronn/
error_messages = []
man_tracked_files.each do |filename|
- next unless filename =~ included
+ next unless filename&.match?(included)
error_messages << check_for_expendable_words(filename)
error_messages << check_for_specific_pronouns(filename)
end
@@ -52,7 +52,7 @@ RSpec.describe "La biblioteca si misma" do
error_messages = []
exempt = /vendor/
lib_tracked_files.each do |filename|
- next if filename =~ exempt
+ next if filename&.match?(exempt)
error_messages << check_for_expendable_words(filename)
error_messages << check_for_specific_pronouns(filename)
end
diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb
index 08ec8bed5c..a98815158e 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 = /
<<<<<<<|
@@ -31,7 +12,7 @@ RSpec.describe "The library itself" do
failing_lines = []
each_line(filename) do |line, number|
- failing_lines << number + 1 if line =~ merge_conflicts_regex
+ failing_lines << number + 1 if line&.match?(merge_conflicts_regex)
end
return if failing_lines.empty?
@@ -41,7 +22,7 @@ RSpec.describe "The library itself" do
def check_for_tab_characters(filename)
failing_lines = []
each_line(filename) do |line, number|
- failing_lines << number + 1 if line =~ /\t/
+ failing_lines << number + 1 if line.include?("\t")
end
return if failing_lines.empty?
@@ -51,8 +32,8 @@ RSpec.describe "The library itself" do
def check_for_extra_spaces(filename)
failing_lines = []
each_line(filename) do |line, number|
- next if line =~ /^\s+#.*\s+\n$/
- failing_lines << number + 1 if line =~ /\s+\n$/
+ next if /^\s+#.*\s+\n$/.match?(line)
+ failing_lines << number + 1 if /\s+\n$/.match?(line)
end
return if failing_lines.empty?
@@ -64,7 +45,7 @@ RSpec.describe "The library itself" do
failing_lines = []
each_line(filename) do |line, number|
- failing_lines << number + 1 if line =~ /’/
+ failing_lines << number + 1 if /’/.match?(line)
end
return if failing_lines.empty?
@@ -108,7 +89,7 @@ RSpec.describe "The library itself" do
exempt = /\.gitmodules|fixtures|vendor|LICENSE|vcr_cassettes|rbreadline\.diff|index\.txt$/
error_messages = []
tracked_files.each do |filename|
- next if filename =~ exempt
+ next if filename&.match?(exempt)
error_messages << check_for_tab_characters(filename)
error_messages << check_for_extra_spaces(filename)
end
@@ -119,27 +100,17 @@ RSpec.describe "The library itself" do
exempt = /vendor|vcr_cassettes|LICENSE|rbreadline\.diff/
error_messages = []
tracked_files.each do |filename|
- next if filename =~ exempt
+ next if filename&.match?(exempt)
error_messages << check_for_straneous_quotes(filename)
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|index\.txt|\.5|\.1}
- error_messages = []
- tracked_files.each do |filename|
- next if filename =~ exempt
- error_messages << check_for_debugging_mechanisms(filename)
- end
- expect(error_messages.compact).to be_well_formed
- end
-
it "does not include any unresolved merge conflicts" do
error_messages = []
exempt = %r{lock/lockfile_spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser\.rb}
tracked_files.each do |filename|
- next if filename =~ exempt
+ next if filename&.match?(exempt)
error_messages << check_for_git_merge_conflicts(filename)
end
expect(error_messages.compact).to be_well_formed
@@ -149,7 +120,7 @@ RSpec.describe "The library itself" do
included = /ronn/
error_messages = []
man_tracked_files.each do |filename|
- next unless filename =~ included
+ next unless filename&.match?(included)
error_messages << check_for_expendable_words(filename)
error_messages << check_for_specific_pronouns(filename)
end
@@ -160,7 +131,7 @@ RSpec.describe "The library itself" do
error_messages = []
exempt = /vendor|vcr_cassettes|CODE_OF_CONDUCT/
lib_tracked_files.each do |filename|
- next if filename =~ exempt
+ next if filename&.match?(exempt)
error_messages << check_for_expendable_words(filename)
error_messages << check_for_specific_pronouns(filename)
end
@@ -180,7 +151,6 @@ RSpec.describe "The library itself" do
git.allow_insecure
inline
trust-policy
- use_gem_version_promoter_for_major_updates
]
all_settings = Hash.new {|h, k| h[k] = [] }
@@ -227,7 +197,7 @@ RSpec.describe "The library itself" do
gem_list = loaded_gemspec.files
- expect(git_list.sort).to eq(gem_list.sort)
+ expect(git_list).to match_array(gem_list)
end
it "does not contain any warnings" do
@@ -236,7 +206,6 @@ RSpec.describe "The library itself" do
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") }
@@ -259,7 +228,7 @@ RSpec.describe "The library itself" do
exempt = %r{templates/|\.5|\.1|vendor/}
all_bad_requires = []
lib_tracked_files.each do |filename|
- next if filename =~ exempt
+ next if filename&.match?(exempt)
each_line(filename) do |line, number|
line.scan(/^ *require "bundler/).each { all_bad_requires << "#{filename}:#{number.succ}" }
end
diff --git a/spec/bundler/realworld/dependency_api_spec.rb b/spec/bundler/realworld/dependency_api_spec.rb
index 08c6acf190..14f99bd262 100644
--- a/spec/bundler/realworld/dependency_api_spec.rb
+++ b/spec/bundler/realworld/dependency_api_spec.rb
@@ -13,12 +13,12 @@ RSpec.describe "gemcutter's dependency API", :realworld => true do
require_relative "../support/artifice/endpoint_timeout"
@t = Thread.new do
- server = Rack::Server.start(:app => EndpointTimeout,
- :Host => "0.0.0.0",
- :Port => port,
- :server => "webrick",
+ server = Rack::Server.start(:app => EndpointTimeout,
+ :Host => "0.0.0.0",
+ :Port => port,
+ :server => "webrick",
:AccessLog => [],
- :Logger => Spec::SilentLogger.new)
+ :Logger => Spec::SilentLogger.new)
server.start
end
@t.run
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index f031e2f354..2f465b7b25 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -4,14 +4,15 @@ RSpec.describe "real world edgecases", :realworld => true do
def rubygems_version(name, requirement)
ruby <<-RUBY
require "#{spec_dir}/support/artifice/vcr"
- require "#{entrypoint}"
- require "#{entrypoint}/source/rubygems/remote"
- require "#{entrypoint}/fetcher"
+ require "bundler"
+ require "bundler/source/rubygems/remote"
+ require "bundler/fetcher"
rubygem = Bundler.ui.silence do
source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org"))
fetcher = Bundler::Fetcher.new(source)
index = fetcher.specs([#{name.dump}], nil)
- index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last
+ requirement = Gem::Requirement.create(#{requirement.dump})
+ index.search(#{name.dump}).select {|spec| requirement.satisfied_by?(spec.version) }.last
end
if rubygem.nil?
raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \
@@ -64,7 +65,7 @@ RSpec.describe "real world edgecases", :realworld => true do
it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do
# from https://github.com/rubygems/bundler/issues/5031
- system_gems "bundler-2.99.0"
+ pristine_system_gems "bundler-1.99.0"
gemfile <<-G
source "https://rubygems.org"
@@ -154,7 +155,7 @@ RSpec.describe "real world edgecases", :realworld => true do
activemodel (= 4.2.7.1)
activerecord (= 4.2.7.1)
activesupport (= 4.2.7.1)
- bundler (>= 1.3.0, < 3.0)
+ bundler (>= 1.3.0, < 2.0)
railties (= 4.2.7.1)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
@@ -191,30 +192,41 @@ RSpec.describe "real world edgecases", :realworld => true do
rails (~> 4.2.7.1)
L
- bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" }
+ bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "1.99.0" }
expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
end
- it "outputs a helpful error message when gems have invalid gemspecs" do
- install_gemfile <<-G, :standalone => true, :raise_on_error => false
+ it "outputs a helpful error message when gems have invalid gemspecs", :rubygems => "< 3.3.16" do
+ install_gemfile <<-G, :standalone => true, :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" }
source 'https://rubygems.org'
gem "resque-scheduler", "2.2.0"
gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0
+ gem "ruby2_keywords", "0.0.5"
G
expect(err).to include("You have one or more invalid gemspecs that need to be fixed.")
expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec")
end
+ it "outputs a helpful warning when gems have a gemspec with invalid `require_paths`", :rubygems => ">= 3.3.16" do
+ install_gemfile <<-G, :standalone => true, :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("resque-scheduler 2.2.0 includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this").once
+ end
+
it "doesn't hang on big gemfile" do
- skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
+ skip "Only for ruby 2.7" unless RUBY_VERSION.start_with?("2.7")
gemfile <<~G
# frozen_string_literal: true
source "https://rubygems.org"
- ruby "2.7.3"
+ ruby "~> 2.7.7"
gem "rails"
gem "pg", ">= 0.18", "< 2.0"
@@ -309,17 +321,17 @@ RSpec.describe "real world edgecases", :realworld => true do
G
if Bundler.feature_flag.bundler_3_mode?
- # Conflicts on bundler version, so fails earlier
+ # Conflicts on bundler version, so we count attempts differently
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false
- expect(out).to display_total_steps_of(435)
+ expect(out.split("\n").grep(/backtracking to/).count).to eq(16)
else
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
- expect(out).to display_total_steps_of(1025)
+ expect(out).to include("Solution found after 7 attempts")
end
end
it "doesn't hang on tricky gemfile" do
- skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
+ skip "Only for ruby 2.7" unless RUBY_VERSION.start_with?("2.7")
gemfile <<~G
source 'https://rubygems.org'
@@ -337,190 +349,168 @@ RSpec.describe "real world edgecases", :realworld => true do
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
- 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
+ expect(out).to include("Solution found after 6 attempts")
end
it "doesn't hang on nix gemfile" do
- skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/
+ skip "Only for ruby 3.0" unless RUBY_VERSION.start_with?("3.0")
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
+ source "https://rubygems.org"
+
+ gem "addressable"
+ gem "atk"
+ gem "awesome_print"
+ gem "bacon"
+ gem "byebug"
+ gem "cairo"
+ gem "cairo-gobject"
+ gem "camping"
+ gem "charlock_holmes"
+ gem "cld3"
+ gem "cocoapods"
+ gem "cocoapods-acknowledgements"
+ gem "cocoapods-art"
+ gem "cocoapods-bin"
+ gem "cocoapods-browser"
+ gem "cocoapods-bugsnag"
+ gem "cocoapods-check"
+ gem "cocoapods-clean"
+ gem "cocoapods-clean_build_phases_scripts"
+ gem "cocoapods-core"
+ gem "cocoapods-coverage"
+ gem "cocoapods-deintegrate"
+ gem "cocoapods-dependencies"
+ gem "cocoapods-deploy"
+ gem "cocoapods-downloader"
+ gem "cocoapods-expert-difficulty"
+ gem "cocoapods-fix-react-native"
+ gem "cocoapods-generate"
+ gem "cocoapods-git_url_rewriter"
+ gem "cocoapods-keys"
+ gem "cocoapods-no-dev-schemes"
+ gem "cocoapods-open"
+ gem "cocoapods-packager"
+ gem "cocoapods-playgrounds"
+ gem "cocoapods-plugins"
+ gem "cocoapods-prune-localizations"
+ gem "cocoapods-rome"
+ gem "cocoapods-search"
+ gem "cocoapods-sorted-search"
+ gem "cocoapods-static-swift-framework"
+ gem "cocoapods-stats"
+ gem "cocoapods-tdfire-binary"
+ gem "cocoapods-testing"
+ gem "cocoapods-trunk"
+ gem "cocoapods-try"
+ gem "cocoapods-try-release-fix"
+ gem "cocoapods-update-if-you-dare"
+ gem "cocoapods-whitelist"
+ gem "cocoapods-wholemodule"
+ gem "coderay"
+ gem "concurrent-ruby"
+ gem "curb"
+ gem "curses"
+ gem "daemons"
+ gem "dep-selector-libgecode"
+ gem "digest-sha3"
+ gem "domain_name"
+ gem "do_sqlite3"
+ gem "ethon"
+ gem "eventmachine"
+ gem "excon"
+ gem "faraday"
+ gem "ffi"
+ gem "ffi-rzmq-core"
+ gem "fog-dnsimple"
+ gem "gdk_pixbuf2"
+ gem "gio2"
+ gem "gitlab-markup"
+ gem "glib2"
+ gem "gpgme"
+ gem "gtk2"
+ gem "hashie"
+ gem "highline"
+ gem "hike"
+ gem "hitimes"
+ gem "hpricot"
+ gem "httpclient"
+ gem "http-cookie"
+ gem "iconv"
+ gem "idn-ruby"
+ gem "jbuilder"
+ gem "jekyll"
+ gem "jmespath"
+ gem "jwt"
+ gem "libv8"
+ gem "libxml-ruby"
+ gem "magic"
+ gem "markaby"
+ gem "method_source"
+ gem "mini_magick"
+ gem "msgpack"
+ gem "mysql2"
+ gem "ncursesw"
+ gem "netrc"
+ gem "net-scp"
+ gem "net-ssh"
+ gem "nokogiri"
+ gem "opus-ruby"
+ gem "ovirt-engine-sdk"
+ gem "pango"
+ gem "patron"
+ gem "pcaprub"
+ gem "pg"
+ gem "pry"
+ gem "pry-byebug"
+ gem "pry-doc"
+ gem "public_suffix"
+ gem "puma"
+ gem "rails"
+ gem "rainbow"
+ gem "rbnacl"
+ gem "rb-readline"
+ gem "re2"
+ gem "redis"
+ gem "redis-rack"
+ gem "rest-client"
+ gem "rmagick"
+ gem "rpam2"
+ gem "rspec"
+ gem "rubocop"
+ gem "rubocop-performance"
+ gem "ruby-libvirt"
+ gem "ruby-lxc"
+ gem "ruby-progressbar"
+ gem "ruby-terminfo"
+ gem "ruby-vips"
+ gem "rubyzip"
+ gem "rugged"
+ gem "sassc"
+ gem "scrypt"
+ gem "semian"
+ gem "sequel"
+ gem "sequel_pg"
+ gem "simplecov"
+ gem "sinatra"
+ gem "slop"
+ gem "snappy"
+ gem "sqlite3"
+ gem "taglib-ruby"
+ gem "thrift"
+ gem "tilt"
+ gem "tiny_tds"
+ gem "treetop"
+ gem "typhoeus"
+ gem "tzinfo"
+ gem "unf_ext"
+ gem "uuid4r"
+ gem "whois"
+ gem "zookeeper"
G
bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
- 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
-
- 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
+ expect(out).to include("Solution found after 4 attempts")
end
end
diff --git a/spec/bundler/realworld/ffi_spec.rb b/spec/bundler/realworld/ffi_spec.rb
new file mode 100644
index 0000000000..fdefc14091
--- /dev/null
+++ b/spec/bundler/realworld/ffi_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+RSpec.describe "loading dynamically 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/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
index 05bcb877db..8f29bd341f 100644
--- a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
@@ -27,4 +27,4 @@ DEPENDENCIES
warbler (~> 2.0)
BUNDLED WITH
- 2.3.0.dev
+ 2.4.0.dev
diff --git a/spec/bundler/realworld/gemfile_source_header_spec.rb b/spec/bundler/realworld/gemfile_source_header_spec.rb
index ada2fc92ee..60c0055a62 100644
--- a/spec/bundler/realworld/gemfile_source_header_spec.rb
+++ b/spec/bundler/realworld/gemfile_source_header_spec.rb
@@ -40,12 +40,12 @@ RSpec.describe "fetching dependencies with a mirrored source", :realworld => tru
require_relative "../support/artifice/endpoint_mirror_source"
@t = Thread.new do
- Rack::Server.start(:app => EndpointMirrorSource,
- :Host => "0.0.0.0",
- :Port => @port,
- :server => "webrick",
+ Rack::Server.start(:app => EndpointMirrorSource,
+ :Host => "0.0.0.0",
+ :Port => @port,
+ :server => "webrick",
:AccessLog => [],
- :Logger => Spec::SilentLogger.new)
+ :Logger => Spec::SilentLogger.new)
end.run
wait_for_server("127.0.0.1", @port)
diff --git a/spec/bundler/realworld/git_spec.rb b/spec/bundler/realworld/git_spec.rb
new file mode 100644
index 0000000000..3d352626ea
--- /dev/null
+++ b/spec/bundler/realworld/git_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.describe "github source", :realworld => true do
+ it "properly fetches PRs" do
+ install_gemfile <<-G
+ source "https://rubygems.org"
+
+ gem "reline", github: "https://github.com/ruby/reline/pull/488"
+ G
+ end
+end
diff --git a/spec/bundler/realworld/mirror_probe_spec.rb b/spec/bundler/realworld/mirror_probe_spec.rb
index a2b5c89150..f2ce477c10 100644
--- a/spec/bundler/realworld/mirror_probe_spec.rb
+++ b/spec/bundler/realworld/mirror_probe_spec.rb
@@ -74,27 +74,12 @@ RSpec.describe "fetching dependencies with a not available mirror", :realworld =
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}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- 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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- 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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- 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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- end
- it "prints each error and warning on a new line" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, :artifice => nil, :raise_on_error => false
-
- expect(out).to include "Fetching source index from #{mirror}/"
- expect(err).to include <<-EOS.strip
-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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>
-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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>
-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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>
-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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>
- EOS
+ err_lines = err.split("\n")
+ expect(err_lines).to include(%r{\ARetrying fetcher due to error \(2/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <})
+ expect(err_lines).to include(%r{\ARetrying fetcher due to error \(3/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <})
+ expect(err_lines).to include(%r{\ARetrying fetcher due to error \(4/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <})
+ expect(err_lines).to include(%r{\ACould not fetch specs from #{mirror}/ due to underlying error <})
end
end
@@ -112,10 +97,12 @@ Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUS
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}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- 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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- 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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
- 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) for \"#{host}\" port #{@mirror_port}) (#{mirror}/specs.4.8.gz)>")
+
+ err_lines = err.split("\n")
+ expect(err_lines).to include(%r{\ARetrying fetcher due to error \(2/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <})
+ expect(err_lines).to include(%r{\ARetrying fetcher due to error \(3/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <})
+ expect(err_lines).to include(%r{\ARetrying fetcher due to error \(4/4\): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <})
+ expect(err_lines).to include(%r{\ACould not fetch specs from #{mirror}/ due to underlying error <})
end
end
@@ -126,12 +113,12 @@ Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUS
require_relative "../support/artifice/endpoint"
@server_thread = Thread.new do
- Rack::Server.start(:app => Endpoint,
- :Host => host,
- :Port => @server_port,
- :server => "webrick",
+ Rack::Server.start(:app => Endpoint,
+ :Host => host,
+ :Port => @server_port,
+ :server => "webrick",
:AccessLog => [],
- :Logger => Spec::SilentLogger.new)
+ :Logger => Spec::SilentLogger.new)
end.run
wait_for_server(host, @server_port)
diff --git a/spec/bundler/realworld/parallel_spec.rb b/spec/bundler/realworld/parallel_spec.rb
index 97c0e0cab4..a1e4f83909 100644
--- a/spec/bundler/realworld/parallel_spec.rb
+++ b/spec/bundler/realworld/parallel_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe "parallel", :realworld => true do
end
it "works with --standalone" do
- gemfile <<-G, :standalone => true
+ gemfile <<-G
source "https://rubygems.org"
gem "diff-lcs"
G
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
index aced5a1641..aa8a48fcc7 100644
--- a/spec/bundler/realworld/slow_perf_spec.rb
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -11,12 +11,23 @@ RSpec.describe "bundle install with complex dependencies", :realworld => true do
gem "mongoid", ">= 0.10.2"
G
- start_time = Time.now
+ expect { bundle "lock" }.to take_less_than(18) # seconds
+ end
+
+ it "resolves quickly (case 2)" do
+ gemfile <<-G
+ source "https://rubygems.org"
- bundle "lock"
+ gem 'metasploit-erd'
+ gem 'rails-erd'
+ gem 'yard'
- duration = Time.now - start_time
+ gem 'coveralls'
+ gem 'rails'
+ gem 'simplecov'
+ gem 'rspec-rails'
+ G
- expect(duration.to_f).to be < 12 # seconds
+ expect { bundle "lock" }.to take_less_than(30) # seconds
end
end
diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb
index ee62dc3577..f739f8c02b 100644
--- a/spec/bundler/resolver/basic_spec.rb
+++ b/spec/bundler/resolver/basic_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe "Resolving" do
dep "chef_app_error"
expect do
resolve
- end.to raise_error(Bundler::VersionConflict)
+ end.to raise_error(Bundler::SolveFailure)
end
it "raises an exception with the minimal set of conflicting dependencies" do
@@ -118,14 +118,15 @@ RSpec.describe "Resolving" do
dep "c"
expect do
resolve
- end.to raise_error(Bundler::VersionConflict, <<-E.strip)
-Bundler could not find compatible versions for gem "a":
- In Gemfile:
- b was resolved to 1.0, which depends on
- a (>= 2)
-
- c was resolved to 1.0, which depends on
- a (< 1)
+ end.to raise_error(Bundler::SolveFailure, <<~E.strip)
+ Could not find compatible versions
+
+ Because every version of c depends on a < 1
+ and every version of b depends on a >= 2,
+ every version of c is incompatible with b >= 0.
+ So, because Gemfile depends on b >= 0
+ and Gemfile depends on c >= 0,
+ version solving has failed.
E
end
@@ -134,7 +135,7 @@ Bundler could not find compatible versions for gem "a":
dep "circular_app"
expect do
- resolve
+ Bundler::SpecSet.new(resolve).sort
end.to raise_error(Bundler::CyclicDependencyError, /please remove either gem 'bar' or gem 'foo'/i)
end
@@ -174,12 +175,7 @@ Bundler could not find compatible versions for gem "a":
dep "foo"
dep "Ruby\0", "1.8.7"
- deps = []
- @deps.each do |d|
- deps << Bundler::DepProxy.get_proxy(d, "ruby")
- end
-
- should_resolve_and_include %w[foo-1.0.0 bar-1.0.0], [[]]
+ should_resolve_and_include %w[foo-1.0.0 bar-1.0.0]
end
context "conservative" do
@@ -305,4 +301,50 @@ Bundler could not find compatible versions for gem "a":
end
end
end
+
+ it "handles versions that redundantly depend on themselves" do
+ @index = build_index do
+ gem "rack", "3.0.0"
+
+ gem "standalone_migrations", "7.1.0" do
+ dep "rack", "~> 2.0"
+ end
+
+ gem "standalone_migrations", "2.0.4" do
+ dep "standalone_migrations", ">= 0"
+ end
+
+ gem "standalone_migrations", "1.0.13" do
+ dep "rack", ">= 0"
+ end
+ end
+
+ dep "rack", "~> 3.0"
+ dep "standalone_migrations"
+
+ should_resolve_as %w[rack-3.0.0 standalone_migrations-2.0.4]
+ end
+
+ it "ignores versions that incorrectly depend on themselves" do
+ @index = build_index do
+ gem "rack", "3.0.0"
+
+ gem "standalone_migrations", "7.1.0" do
+ dep "rack", "~> 2.0"
+ end
+
+ gem "standalone_migrations", "2.0.4" do
+ dep "standalone_migrations", ">= 2.0.5"
+ end
+
+ gem "standalone_migrations", "1.0.13" do
+ dep "rack", ">= 0"
+ end
+ end
+
+ dep "rack", "~> 3.0"
+ dep "standalone_migrations"
+
+ should_resolve_as %w[rack-3.0.0 standalone_migrations-1.0.13]
+ end
end
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index bc4081f8b5..a710dfcb28 100644
--- a/spec/bundler/resolver/platform_spec.rb
+++ b/spec/bundler/resolver/platform_spec.rb
@@ -82,21 +82,105 @@ RSpec.describe "Resolving platform craziness" do
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"]
+ describe "on a linux platform", :rubygems => ">= 3.1.0.pre.1" do
+ # Ruby's platform is *-linux => platform's libc is glibc, so not musl
+ # Ruby's platform is *-linux-musl => platform's libc is musl, so not glibc
+ # Gem's platform is *-linux => gem is glibc + maybe musl compatible
+ # Gem's platform is *-linux-musl => gem is musl compatible but not glibc
+
+ it "favors the platform version-specific gem on a version-specifying linux platform" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux"
+ gem "foo", "1.0.0", "x86_64-linux-musl"
end
- gem "Ruby\0", "2.5.1"
+ dep "foo"
+ platforms "x86_64-linux-musl"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux-musl]
end
- dep "foo"
- dep "Ruby\0", "2.5.1"
- platforms "x64-mingw32"
- should_resolve_as %w[foo-1.1.0]
+ it "favors the version-less gem over the version-specific gem on a gnu linux platform" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux"
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux]
+ end
+
+ it "ignores the platform version-specific gem on a gnu linux platform" do
+ @index = build_index do
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux"
+
+ should_not_resolve
+ end
+
+ it "falls back to the platform version-less gem on a linux platform with a version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux"
+ end
+ dep "foo"
+ platforms "x86_64-linux-musl"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux]
+ end
+
+ it "falls back to the ruby platform gem on a gnu linux platform when only a version-specifying gem is available" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x86_64-linux-musl"
+ end
+ dep "foo"
+ platforms "x86_64-linux"
+
+ should_resolve_as %w[foo-1.0.0]
+ end
+
+ it "falls back to the platform version-less gem on a version-specifying linux platform and no ruby platform gem is available" do
+ @index = build_index do
+ gem "foo", "1.0.0", "x86_64-linux"
+ end
+ dep "foo"
+ platforms "x86_64-linux-musl"
+
+ should_resolve_as %w[foo-1.0.0-x86_64-linux]
+ end
+ end
+
+ context "when the platform specific gem doesn't match the required_ruby_version" do
+ before 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 "Ruby\0", "2.5.1"
+ platforms "x64-mingw32"
+ end
+
+ it "takes the latest ruby gem" do
+ dep "foo"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the latest ruby gem, even if requirement does not match previous versions with the same ruby requirement" do
+ dep "foo", "1.1.0"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
end
it "takes the latest ruby gem with required_ruby_version if the platform specific gem doesn't match the required_ruby_version" do
@@ -137,39 +221,6 @@ RSpec.describe "Resolving platform craziness" do
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"
@@ -291,7 +342,7 @@ RSpec.describe "Resolving platform craziness" do
describe "with mingw32" do
before :each do
@index = build_index do
- platforms "mingw32 mswin32 x64-mingw32" do |platform|
+ platforms "mingw32 mswin32 x64-mingw32 x64-mingw-ucrt" do |platform|
gem "thin", "1.2.7", platform
end
gem "win32-api", "1.5.1", "universal-mingw32"
@@ -312,7 +363,7 @@ RSpec.describe "Resolving platform craziness" do
should_resolve_as %w[thin-1.2.7-mingw32]
end
- it "finds x64-mingw gems" do
+ it "finds x64-mingw32 gems" do
platforms "x64-mingw32"
dep "thin"
should_resolve_as %w[thin-1.2.7-x64-mingw32]
@@ -329,6 +380,22 @@ RSpec.describe "Resolving platform craziness" do
dep "win32-api"
should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
end
+
+ if Gem.rubygems_version >= Gem::Version.new("3.2.28")
+ it "finds x64-mingw-ucrt gems" do
+ platforms "x64-mingw-ucrt"
+ dep "thin"
+ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
+ end
+ end
+
+ if Gem.rubygems_version >= Gem::Version.new("3.3.18")
+ it "finds universal-mingw gems on x64-mingw-ucrt" do
+ platform "x64-mingw-ucrt"
+ dep "win32-api"
+ should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
+ end
+ end
end
describe "with conflicting cases" do
diff --git a/spec/bundler/runtime/gem_tasks_spec.rb b/spec/bundler/runtime/gem_tasks_spec.rb
index b0ef0cc144..b89fdf2cb1 100644
--- a/spec/bundler/runtime/gem_tasks_spec.rb
+++ b/spec/bundler/runtime/gem_tasks_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
it "includes the relevant tasks" do
- with_gem_path_as(base_system_gems.to_s) do
+ with_gem_path_as(base_system_gem_path.to_s) do
sys_exec "#{rake} -T", :env => { "GEM_HOME" => system_gem_path.to_s }
end
@@ -44,7 +44,7 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
it "defines a working `rake install` task", :ruby_repo do
- with_gem_path_as(base_system_gems.to_s) do
+ with_gem_path_as(base_system_gem_path.to_s) do
sys_exec "#{rake} install", :env => { "GEM_HOME" => system_gem_path.to_s }
end
@@ -98,7 +98,7 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
it "adds 'pkg' to rake/clean's CLOBBER" do
- with_gem_path_as(base_system_gems.to_s) do
+ with_gem_path_as(base_system_gem_path.to_s) do
sys_exec %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect'), :env => { "GEM_HOME" => system_gem_path.to_s }
end
expect(out).to eq '["pkg"]'
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index 4f39c552e8..29ef036828 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -89,19 +89,21 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to include("Installing activesupport")
err_lines = err.split("\n")
- err_lines.reject!{|line| line =~ /\.rb:\d+: warning: / } unless RUBY_VERSION < "2.7"
+ err_lines.reject! {|line| line =~ /\.rb:\d+: warning: / } unless RUBY_VERSION < "2.7"
expect(err_lines).to be_empty
end
it "lets me use my own ui object" do
script <<-RUBY, :artifice => "endpoint"
require '#{entrypoint}'
- class MyBundlerUI < Bundler::UI::Silent
+ class MyBundlerUI < Bundler::UI::Shell
def confirm(msg, newline = nil)
puts "CONFIRMED!"
end
end
- gemfile(true, :ui => MyBundlerUI.new) do
+ my_ui = MyBundlerUI.new
+ my_ui.level = "confirm"
+ gemfile(true, :ui => my_ui) do
source "https://notaserver.com"
gem "activesupport", :require => true
end
@@ -166,6 +168,54 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
+ it "installs subdependencies quietly if necessary when the install option is not set" do
+ build_repo4 do
+ build_gem "rack" do |s|
+ s.add_dependency "rackdep"
+ end
+
+ build_gem "rackdep", "1.0.0"
+ end
+
+ script <<-RUBY
+ gemfile do
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ end
+
+ require "rackdep"
+ puts RACKDEP
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+
+ it "installs subdependencies quietly if necessary when the install option is not set, and multiple sources used" do
+ build_repo4 do
+ build_gem "rack" do |s|
+ s.add_dependency "rackdep"
+ end
+
+ build_gem "rackdep", "1.0.0"
+ end
+
+ script <<-RUBY
+ gemfile do
+ source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo4)}" do
+ gem "rack"
+ end
+ end
+
+ require "rackdep"
+ puts RACKDEP
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+
it "installs quietly from git if necessary when the install option is not set" do
build_git "foo", "1.0.0"
baz_ref = build_git("baz", "2.0.0").ref_for("HEAD")
@@ -205,6 +255,113 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
+ it "doesn't reinstall already installed gems" do
+ system_gems "rack-1.0.0"
+
+ script <<-RUBY
+ require '#{entrypoint}'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "activesupport"
+ gem "rack"
+ end
+ RUBY
+
+ expect(out).to include("Installing activesupport")
+ expect(out).not_to include("Installing rack")
+ expect(err).to be_empty
+ end
+
+ it "installs gems in later gemfile calls" do
+ system_gems "rack-1.0.0"
+
+ script <<-RUBY
+ require '#{entrypoint}'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
+
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "activesupport"
+ end
+ RUBY
+
+ expect(out).to include("Installing activesupport")
+ expect(out).not_to include("Installing rack")
+ expect(err).to be_empty
+ end
+
+ it "doesn't reinstall already installed gems in later gemfile calls" do
+ system_gems "rack-1.0.0"
+
+ script <<-RUBY
+ require '#{entrypoint}'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "activesupport"
+ end
+
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
+ RUBY
+
+ expect(out).to include("Installing activesupport")
+ expect(out).not_to include("Installing rack")
+ expect(err).to be_empty
+ end
+
+ it "installs gems with native extensions in later gemfile calls" do
+ system_gems "rack-1.0.0"
+
+ build_git "foo" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("lib", __dir__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/foo.rb", "w") do |f|
+ f.puts "FOO = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ script <<-RUBY
+ require '#{entrypoint}'
+ ui = Bundler::UI::Shell.new
+ ui.level = "confirm"
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
+
+ gemfile(true, ui: ui) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ end
+
+ require 'foo'
+ puts FOO
+ puts $:.grep(/ext/)
+ RUBY
+
+ expect(out).to include("YES")
+ expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
+ expect(err).to be_empty
+ end
+
it "installs inline gems when a Gemfile.lock is present" do
gemfile <<-G
source "https://notaserver.com"
@@ -239,6 +396,40 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
+ it "does not leak Gemfile.lock versions to the installation output" do
+ gemfile <<-G
+ source "https://notaserver.com"
+ gem "rake"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ rake (11.3.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ rake
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ script <<-RUBY
+ gemfile(true) do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rake", "~> 13.0"
+ end
+ RUBY
+
+ expect(out).to include("Installing rake 13.0")
+ expect(out).not_to include("was 11.3.0")
+ expect(err).to be_empty
+ end
+
it "installs inline gems when frozen is set" do
script <<-RUBY, :env => { "BUNDLE_FROZEN" => "true" }
gemfile do
@@ -309,7 +500,7 @@ RSpec.describe "bundler/inline#gemfile" do
end
it "skips platform warnings" do
- simulate_platform "ruby"
+ bundle "config set --local force_ruby_platform true"
script <<-RUBY
gemfile(true) do
@@ -321,6 +512,20 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
+ it "still installs if the application has `bundle package` no_install config set" do
+ bundle "config set --local no_install true"
+
+ script <<-RUBY
+ gemfile do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
+ RUBY
+
+ expect(last_command).to be_success
+ expect(system_gem_path("gems/rack-1.0.0")).to exist
+ end
+
it "preserves previous BUNDLE_GEMFILE value" do
ENV["BUNDLE_GEMFILE"] = ""
script <<-RUBY
@@ -386,11 +591,11 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
- it "when requiring fileutils after does not show redefinition warnings" do
+ it "when requiring fileutils after does not show redefinition warnings", :realworld 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 "does not work on ruby 3.0 because it changes the path to look for default gems, tsort is a default gem there, and we can't install it either like we do with fiddle because it doesn't yet exist" unless RUBY_VERSION < "3.0.0"
+ skip "pathname does not install cleanly on this ruby" if RUBY_VERSION < "2.7.0"
Dir.mkdir tmp("path_without_gemfile")
@@ -399,10 +604,13 @@ RSpec.describe "bundler/inline#gemfile" do
realworld_system_gems "fileutils --version 1.4.1"
- realworld_system_gems "fiddle" # not sure why, but this is needed on Windows to boot rubygems successfully
+ realworld_system_gems "pathname --version 0.2.0"
realworld_system_gems "timeout uri" # this spec uses net/http which requires these default gems
+ # on prerelease rubies, a required_rubygems_version constraint is added by RubyGems to the resolution, causing Molinillo to load the `set` gem
+ realworld_system_gems "set --version 1.0.3" if Gem.ruby_version.prerelease?
+
script <<-RUBY, :dir => tmp("path_without_gemfile"), :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
require "bundler/inline"
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index d81bccbdf8..a9933f90e9 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" 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.4"
+ s.add_dependency "racc", "~> 1.5.2"
end
build_gem "nokogiri", "1.11.1" do |s|
@@ -80,14 +80,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
mini_portile2 (2.5.0)
nokogiri (1.11.1)
mini_portile2 (~> 2.5.0)
- racc (~> 1.4)
+ racc (~> 1.5.2)
nokogiri (1.11.1-#{Bundler.local_platform})
racc (~> 1.4)
racc (1.5.2)
PLATFORMS
- ruby
- #{Bundler.local_platform}
+ #{lockfile_platforms("ruby")}
DEPENDENCIES
nokogiri (~> 1.11)
@@ -146,7 +145,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
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
+ it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby_only do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri"
@@ -169,7 +168,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
BUNDLED WITH
- 2.1.4
+ #{Bundler::VERSION}
G
bundle "install"
@@ -205,7 +204,7 @@ 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 on jruby", :jruby do
+ it "allows specifying only-ruby-platform on jruby", :jruby_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri"
@@ -233,7 +232,21 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
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
+ it "allows specifying only-ruby-platform even if the lockfile is locked to a specific compatible platform" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "nokogiri"
+ gem "platform_specific"
+ G
+
+ bundle "config set force_ruby_platform true"
+
+ bundle "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_only do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "platform_specific"
@@ -242,6 +255,112 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
end
+ it "doesn't pull platform specific gems on truffleruby (except when whitelisted) even if lockfile was generated with an older version that declared RUBY as platform", :truffleruby_only do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "libv8"
+
+ build_gem "libv8" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "libv8"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ libv8 (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "libv8 1.0 x86_64-linux"
+ end
+ end
+
+ it "doesn't pull platform specific gems on truffleruby, even if lockfile only includes those", :truffleruby_only do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0-x86-darwin-100)
+
+ PLATFORMS
+ x86-darwin-100
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ end
+
+ it "pulls platform specific gems correctly on musl" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = "aarch64-linux"
+ end
+ end
+
+ simulate_platform "aarch64-linux-musl" do
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, :verbose => true
+ source "https://gems.repo4"
+ gem "nokogiri"
+ G
+ end
+
+ expect(out).to include("Fetching nokogiri 1.13.8 (aarch64-linux)")
+ end
+
it "allows specifying only-ruby-platform on windows with dependency platforms" do
simulate_windows do
install_gemfile <<-G
@@ -284,7 +403,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
s.add_dependency "platform_specific"
end
end
- simulate_windows x64_mingw do
+ simulate_windows x64_mingw32 do
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo2)}/
@@ -306,7 +425,40 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
gem "requires_platform_specific"
G
+ expect(out).to include("lockfile does not have all gems needed for the current platform")
expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw32"
end
end
+
+ %w[x86-mswin32 x64-mswin64 x86-mingw32 x64-mingw32 x64-mingw-ucrt].each do |arch|
+ it "allows specifying platform windows on #{arch} arch" do
+ platform = send(arch.tr("-", "_"))
+
+ simulate_windows platform do
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0-#{platform})
+ requires_platform_specific (1.0)
+ platform_specific
+
+ PLATFORMS
+ #{platform}
+
+ DEPENDENCIES
+ requires_platform_specific
+ L
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific", :platforms => [:windows]
+ G
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 #{platform}"
+ end
+ end
+ end
end
diff --git a/spec/bundler/runtime/require_spec.rb b/spec/bundler/runtime/require_spec.rb
index d91b5f8666..e59fa564f6 100644
--- a/spec/bundler/runtime/require_spec.rb
+++ b/spec/bundler/runtime/require_spec.rb
@@ -449,8 +449,6 @@ 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/self_management_spec.rb b/spec/bundler/runtime/self_management_spec.rb
new file mode 100644
index 0000000000..61cfc9b795
--- /dev/null
+++ b/spec/bundler/runtime/self_management_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+RSpec.describe "Self management", :rubygems => ">= 3.3.0.dev", :realworld => true do
+ describe "auto switching" do
+ let(:previous_minor) do
+ "2.3.0"
+ end
+
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rack"
+ G
+ end
+
+ it "installs locked version when using system path and uses it" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle "config set --local path.system true"
+ bundle "install", :artifice => "vcr"
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+
+ # It uninstalls the older system bundler
+ bundle "clean --force"
+ expect(out).to eq("Removing bundler (#{Bundler::VERSION})")
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{previous_minor}")
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ end
+
+ it "installs locked version when using local path and uses it" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle "config set --local path vendor/bundle"
+ bundle "install", :artifice => "vcr"
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist
+
+ # It does not uninstall the locked bundler
+ bundle "clean"
+ expect(out).to be_empty
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{previous_minor}")
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ end
+
+ it "installs locked version when using deployment option and uses it" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle "config set --local deployment true"
+ bundle "install", :artifice => "vcr"
+ expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ expect(vendored_gems("gems/bundler-#{previous_minor}")).to exist
+
+ # It does not uninstall the locked bundler
+ bundle "clean"
+ expect(out).to be_empty
+
+ # App now uses locked version
+ bundle "-v"
+ expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+
+ # Subsequent installs use the locked version without reinstalling
+ bundle "install --verbose"
+ expect(out).to include("Using bundler #{previous_minor}")
+ expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ end
+
+ it "does not try to install a development version" do
+ lockfile_bundled_with("#{previous_minor}.dev")
+
+ bundle "install --verbose"
+ expect(out).not_to match(/restarting using that version/)
+
+ bundle "-v"
+ expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION)
+ end
+
+ it "shows a discrete message if locked bundler does not exist" do
+ missing_minor ="#{Bundler::VERSION[0]}.999.999"
+
+ lockfile_bundled_with(missing_minor)
+
+ bundle "install", :artifice => "vcr"
+ expect(err).to eq("Your lockfile is locked to a version of bundler (#{missing_minor}) that doesn't exist at https://rubygems.org/. Going on using #{Bundler::VERSION}")
+
+ bundle "-v"
+ expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION)
+ end
+
+ private
+
+ def lockfile_bundled_with(version)
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{version}
+ L
+ end
+ end
+end
diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb
index 42bbacea0e..2d39d72937 100644
--- a/spec/bundler/runtime/setup_spec.rb
+++ b/spec/bundler/runtime/setup_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require "tmpdir"
-require "tempfile"
RSpec.describe "Bundler.setup" do
describe "with no arguments" do
@@ -341,19 +340,6 @@ RSpec.describe "Bundler.setup" do
expect(out).to eq("WIN")
end
- it "version_requirement is now deprecated in rubygems 1.4.0+ when gem is missing" do
- run <<-R
- begin
- gem "activesupport"
- puts "FAIL"
- rescue LoadError
- puts "WIN"
- end
- R
-
- expect(err).to be_empty
- end
-
it "replaces #gem but raises when the version is wrong" do
run <<-R
begin
@@ -366,19 +352,6 @@ RSpec.describe "Bundler.setup" do
expect(out).to eq("WIN")
end
-
- it "version_requirement is now deprecated in rubygems 1.4.0+ when the version is wrong" do
- run <<-R
- begin
- gem "rack", "1.0.0"
- puts "FAIL"
- rescue LoadError
- puts "WIN"
- end
- R
-
- expect(err).to be_empty
- end
end
describe "by hiding system gems" do
@@ -397,7 +370,7 @@ RSpec.describe "Bundler.setup" do
context "when the ruby stdlib is a substring of Gem.path" do
it "does not reject the stdlib from $LOAD_PATH" do
- substring = "/" + $LOAD_PATH.find {|p| p =~ /vendor_ruby/ }.split("/")[2]
+ substring = "/" + $LOAD_PATH.find {|p| p.include?("vendor_ruby") }.split("/")[2]
run "puts 'worked!'", :env => { "GEM_PATH" => substring }
expect(out).to eq("worked!")
end
@@ -516,7 +489,7 @@ RSpec.describe "Bundler.setup" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -534,7 +507,7 @@ RSpec.describe "Bundler.setup" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -556,7 +529,7 @@ RSpec.describe "Bundler.setup" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -568,7 +541,7 @@ RSpec.describe "Bundler.setup" do
G
run "require 'rack'", :raise_on_error => false
- expect(err).to match(/is using branch master but Gemfile specifies changed/)
+ expect(err).to match(/is using branch main but Gemfile specifies changed/)
end
it "explodes on refs with different branches on runtime" do
@@ -578,17 +551,17 @@ RSpec.describe "Bundler.setup" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "master", :branch => "master"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "main", :branch => "main"
G
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "master", :branch => "nonexistant"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "main", :branch => "nonexistent"
G
bundle %(config set local.rack #{lib_path("local-rack")})
run "require 'rack'", :raise_on_error => false
- expect(err).to match(/is using branch master but Gemfile specifies nonexistant/)
+ expect(err).to match(/is using branch main but Gemfile specifies nonexistent/)
end
end
@@ -661,6 +634,33 @@ RSpec.describe "Bundler.setup" do
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(out).not_to include("lockfile does not have all gems needed for the current platform")
+ expect(err).to be_empty
+ end
+
+ it "doesn't fail in frozen mode when bundler is a Gemfile dependency" do
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "bundler"
+ G
+
+ bundle "install --verbose", :env => { "BUNDLE_FROZEN" => "true" }
+ expect(err).to be_empty
+ end
+
+ it "doesn't re-resolve when deleting dependencies" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ gem "actionpack"
+ G
+
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ expect(out).to include("Some dependencies were deleted, using a subset of the resolution from the lockfile")
expect(err).to be_empty
end
@@ -745,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#{File::PATH_SEPARATOR}" }
+ 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")}#{File::PATH_SEPARATOR}/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({ "LC_ALL" => "C" }, "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
@@ -801,7 +828,7 @@ end
expect(out).to eq("yay")
end
- it "should clean $LOAD_PATH properly", :ruby_repo do
+ it "should clean $LOAD_PATH properly" do
gem_name = "very_simple_binary"
full_gem_name = gem_name + "-1.0"
ext_dir = File.join(tmp("extensions", full_gem_name))
@@ -834,23 +861,21 @@ end
context "with bundler is located in symlinked GEM_HOME" do
let(:gem_home) { Dir.mktmpdir }
- let(:symlinked_gem_home) { Tempfile.new("gem_home").path }
+ let(:symlinked_gem_home) { tmp("gem_home-symlink").to_s }
let(:full_name) { "bundler-#{Bundler::VERSION}" }
before do
- skip "symlink destination exists" if Gem.win_platform?
-
- FileUtils.ln_sf(gem_home, symlinked_gem_home)
+ File.symlink(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(source_root, File.join(gems_dir, full_name))
+ File.symlink(source_root, File.join(gems_dir, full_name))
gemspec_content = File.binread(gemspec).
sub("Bundler::VERSION", %("#{Bundler::VERSION}")).
- lines.reject {|line| line =~ %r{lib/bundler/version} }.join
+ lines.reject {|line| line.include?("lib/bundler/version") }.join
File.open(File.join(specifications_dir, "#{full_name}.gemspec"), "wb") do |f|
f.write(gemspec_content)
@@ -1108,7 +1133,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:
@@ -1122,7 +1147,7 @@ end
L
if bundler_version
- lock += "\n BUNDLED WITH\n #{bundler_version}\n"
+ lock += "\nBUNDLED WITH\n #{bundler_version}\n"
end
lock
@@ -1141,7 +1166,7 @@ end
it "does not change the lock" do
lockfile lock_with(nil)
ruby "require '#{entrypoint}/setup'"
- lockfile_should_be lock_with(nil)
+ expect(lockfile).to eq lock_with(nil)
end
end
@@ -1151,7 +1176,7 @@ end
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
@@ -1160,7 +1185,7 @@ end
system_gems "bundler-1.10.1"
lockfile lock_with("1.10.1")
ruby "require '#{entrypoint}/setup'"
- lockfile_should_be lock_with("1.10.1")
+ expect(lockfile).to eq lock_with("1.10.1")
end
end
end
@@ -1169,7 +1194,7 @@ end
let(:ruby_version) { nil }
def lock_with(ruby_version = nil)
- lock = <<-L
+ lock = <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -1183,10 +1208,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}
@@ -1228,6 +1253,41 @@ 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 "source \"#{file_uri_for(gem_repo1)}\""
ruby <<-RUBY
@@ -1254,16 +1314,14 @@ end
describe "default gem activation" do
let(:exemptions) do
- 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 = %w[did_you_mean bundler]
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" if Gem.ruby_version >= Gem::Version.new("3.0")
+ exempts << "tsort" unless Gem.rubygems_version >= Gem::Version.new("3.2.31")
+ exempts << "error_highlight" # added in Ruby 3.1 as a default gem
+ exempts << "ruby2_keywords" # added in Ruby 3.1 as a default gem
+ exempts << "syntax_suggest" # added in Ruby 3.2 as a default gem
exempts
end
@@ -1431,5 +1489,69 @@ end
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
+
+ it "does not undo the Kernel.require decorations", :rubygems => ">= 3.4.6" do
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ script = bundled_app("bin/script")
+ create_file(script, <<~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
+
+ require "bundler/setup"
+
+ require "foo"
+ RUBY
+
+ sys_exec "#{Gem.ruby} #{script}", :raise_on_error => false
+ expect(out).to include("requiring foo used the monkeypatch")
end
end
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index 80b0ccff4d..6a7e2891a6 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require "bundler/psyched_yaml"
+require "psych"
require "bundler/vendored_fileutils"
require "bundler/vendored_uri"
require "digest"
@@ -23,7 +23,6 @@ require_relative "support/indexes"
require_relative "support/matchers"
require_relative "support/permissions"
require_relative "support/platforms"
-require_relative "support/sudo"
$debug = false
@@ -40,7 +39,6 @@ RSpec.configure do |config|
config.include Spec::Matchers
config.include Spec::Path
config.include Spec::Platforms
- config.include Spec::Sudo
config.include Spec::Permissions
# Enable flags like --only-failures and --next-failure
@@ -60,6 +58,8 @@ RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
+
+ c.max_formatted_output_length = 1000
end
config.mock_with :rspec do |mocks|
@@ -71,8 +71,12 @@ RSpec.configure do |config|
require_relative "support/rubygems_ext"
Spec::Rubygems.test_setup
- ENV["BUNDLE_SPEC_RUN"] = "true"
+ ENV["BUNDLER_SPEC_RUN"] = "true"
+ ENV["BUNDLER_NO_OLD_RUBYGEMS_WARNING"] = "true"
ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil
+ ENV["BUNDLE_APP_CONFIG"] = nil
+ ENV["BUNDLE_SILENCE_ROOT_WARNING"] = nil
+ ENV["RUBYGEMS_GEMDEPS"] = nil
ENV["XDG_CONFIG_HOME"] = nil
ENV["GEMRC"] = nil
@@ -92,23 +96,21 @@ RSpec.configure do |config|
end
config.around :each do |example|
- 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
+ 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
- ensure
- reset!
end
+ ensure
+ reset!
end
config.after :suite do
diff --git a/spec/bundler/support/api_request_limit_hax.rb b/spec/bundler/support/api_request_limit_hax.rb
deleted file mode 100644
index 37ff0203b3..0000000000
--- a/spec/bundler/support/api_request_limit_hax.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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 1b314e89ef..ebc4d0ae5b 100644
--- a/spec/bundler/support/artifice/compact_index.rb
+++ b/spec/bundler/support/artifice/compact_index.rb
@@ -1,120 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-$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"
- Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
- end
-
- def etag_response
- response_body = yield
- checksum = Digest(:MD5).hexdigest(response_body)
- return if not_modified?(checksum)
- headers "ETag" => quote(checksum)
- headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
- content_type "text/plain"
- requested_range_for(response_body)
- rescue StandardError => e
- puts e
- puts e.backtrace
- raise
- end
-
- def not_modified?(checksum)
- etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
-
- return unless etags.include?(checksum)
- headers "ETag" => quote(checksum)
- status 304
- body ""
- end
-
- def requested_range_for(response_body)
- ranges = Rack::Utils.byte_ranges(env, response_body.bytesize)
-
- if ranges
- status 206
- body ranges.map! {|range| slice_body(response_body, range) }.join
- else
- status 200
- body response_body
- end
- end
-
- def quote(string)
- %("#{string}")
- end
-
- def parse_etags(value)
- value ? value.split(/, ?/).select {|s| s.sub!(/"(.*)"/, '\1') } : []
- end
-
- def slice_body(body, range)
- body.byteslice(range)
- end
-
- def gems(gem_repo = default_gem_repo)
- @gems ||= {}
- @gems[gem_repo] ||= begin
- specs = Bundler::Deprecate.skip_during do
- %w[specs.4.8 prerelease_specs.4.8].map do |filename|
- Marshal.load(File.open(gem_repo.join(filename)).read).map do |name, version, platform|
- load_spec(name, version, platform, gem_repo)
- end
- end.flatten
- end
-
- specs.group_by(&:name).map do |name, versions|
- gem_versions = versions.map do |spec|
- deps = spec.dependencies.select {|d| d.type == :runtime }.map do |d|
- reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
- CompactIndex::Dependency.new(d.name, reqs)
- end
- checksum = begin
- 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.to_s, spec.required_rubygems_version.to_s)
- end
- CompactIndex::Gem.new(name, gem_versions)
- end
- end
- end
- end
-
- get "/names" do
- etag_response do
- CompactIndex.names(gems.map(&:name))
- end
- end
-
- get "/versions" do
- etag_response do
- file = tmp("versions.list")
- FileUtils.rm_f(file)
- file = CompactIndex::VersionsFile.new(file.to_s)
- file.create(gems)
- file.contents
- end
- end
-
- get "/info/:name" do
- etag_response do
- gem = gems.find {|g| g.name == params[:name] }
- CompactIndex.info(gem ? gem.versions : [])
- end
- end
-end
+require_relative "helpers/compact_index"
+require_relative "helpers/artifice"
Artifice.activate_with(CompactIndexAPI)
diff --git a/spec/bundler/support/artifice/compact_index_api_missing.rb b/spec/bundler/support/artifice/compact_index_api_missing.rb
index 6514fde01e..f771f7d1f0 100644
--- a/spec/bundler/support/artifice/compact_index_api_missing.rb
+++ b/spec/bundler/support/artifice/compact_index_api_missing.rb
@@ -1,18 +1,13 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexApiMissing < CompactIndexAPI
get "/fetch/actual/gem/:id" do
- warn params[:id]
- if params[:id] == "rack-1.0.gemspec.rz"
- halt 404
- else
- File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
- end
+ halt 404
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexApiMissing)
diff --git a/spec/bundler/support/artifice/compact_index_basic_authentication.rb b/spec/bundler/support/artifice/compact_index_basic_authentication.rb
index 775f1a3977..b9115cdd86 100644
--- a/spec/bundler/support/artifice/compact_index_basic_authentication.rb
+++ b/spec/bundler/support/artifice/compact_index_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexBasicAuthentication < CompactIndexAPI
before do
@@ -12,4 +10,6 @@ class CompactIndexBasicAuthentication < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexBasicAuthentication)
diff --git a/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb b/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb
index 1abe64236c..a6545b9ee4 100644
--- a/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb
+++ b/spec/bundler/support/artifice/compact_index_checksum_mismatch.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexChecksumMismatch < CompactIndexAPI
get "/versions" do
@@ -13,4 +11,6 @@ class CompactIndexChecksumMismatch < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexChecksumMismatch)
diff --git a/spec/bundler/support/artifice/compact_index_concurrent_download.rb b/spec/bundler/support/artifice/compact_index_concurrent_download.rb
index 14c31f35a4..35548f278c 100644
--- a/spec/bundler/support/artifice/compact_index_concurrent_download.rb
+++ b/spec/bundler/support/artifice/compact_index_concurrent_download.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexConcurrentDownload < CompactIndexAPI
get "/versions" do
@@ -29,4 +27,6 @@ class CompactIndexConcurrentDownload < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexConcurrentDownload)
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 cfe22c7f51..401e8a98d8 100644
--- a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexCredsDiffHost < CompactIndexAPI
helpers do
@@ -36,4 +34,6 @@ class CompactIndexCredsDiffHost < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexCredsDiffHost)
diff --git a/spec/bundler/support/artifice/compact_index_extra.rb b/spec/bundler/support/artifice/compact_index_extra.rb
index cec368276a..cd41b3ecca 100644
--- a/spec/bundler/support/artifice/compact_index_extra.rb
+++ b/spec/bundler/support/artifice/compact_index_extra.rb
@@ -1,37 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
-
-class CompactIndexExtra < CompactIndexAPI
- get "/extra/versions" do
- halt 404
- end
-
- get "/extra/api/v1/dependencies" do
- halt 404
- end
-
- get "/extra/specs.4.8.gz" do
- File.binread("#{gem_repo2}/specs.4.8.gz")
- end
-
- get "/extra/prerelease_specs.4.8.gz" do
- File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
- end
-
- get "/extra/quick/Marshal.4.8/:id" do
- redirect "/extra/fetch/actual/gem/#{params[:id]}"
- end
-
- get "/extra/fetch/actual/gem/:id" do
- File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
- end
-
- get "/extra/gems/:id" do
- File.binread("#{gem_repo2}/gems/#{params[:id]}")
- end
-end
+require_relative "helpers/compact_index_extra"
+require_relative "helpers/artifice"
Artifice.activate_with(CompactIndexExtra)
diff --git a/spec/bundler/support/artifice/compact_index_extra_api.rb b/spec/bundler/support/artifice/compact_index_extra_api.rb
index 5cc13421a8..8b9d304ab4 100644
--- a/spec/bundler/support/artifice/compact_index_extra_api.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_api.rb
@@ -1,52 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
-
-class CompactIndexExtraApi < CompactIndexAPI
- get "/extra/names" do
- etag_response do
- CompactIndex.names(gems(gem_repo4).map(&:name))
- end
- end
-
- get "/extra/versions" do
- etag_response do
- file = tmp("versions.list")
- FileUtils.rm_f(file)
- file = CompactIndex::VersionsFile.new(file.to_s)
- file.create(gems(gem_repo4))
- file.contents
- end
- end
-
- get "/extra/info/:name" do
- etag_response do
- gem = gems(gem_repo4).find {|g| g.name == params[:name] }
- CompactIndex.info(gem ? gem.versions : [])
- end
- end
-
- get "/extra/specs.4.8.gz" do
- File.binread("#{gem_repo4}/specs.4.8.gz")
- end
-
- get "/extra/prerelease_specs.4.8.gz" do
- File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
- end
-
- get "/extra/quick/Marshal.4.8/:id" do
- redirect "/extra/fetch/actual/gem/#{params[:id]}"
- end
-
- get "/extra/fetch/actual/gem/:id" do
- File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
- end
-
- get "/extra/gems/:id" do
- File.binread("#{gem_repo4}/gems/#{params[:id]}")
- end
-end
+require_relative "helpers/compact_index_extra_api"
+require_relative "helpers/artifice"
Artifice.activate_with(CompactIndexExtraApi)
diff --git a/spec/bundler/support/artifice/compact_index_extra_api_missing.rb b/spec/bundler/support/artifice/compact_index_extra_api_missing.rb
index b9d757c266..df6ede584c 100644
--- a/spec/bundler/support/artifice/compact_index_extra_api_missing.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_api_missing.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index_extra_api"
-
-Artifice.deactivate
+require_relative "helpers/compact_index_extra_api"
class CompactIndexExtraAPIMissing < CompactIndexExtraApi
get "/extra/fetch/actual/gem/:id" do
@@ -14,4 +12,6 @@ class CompactIndexExtraAPIMissing < CompactIndexExtraApi
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexExtraAPIMissing)
diff --git a/spec/bundler/support/artifice/compact_index_extra_missing.rb b/spec/bundler/support/artifice/compact_index_extra_missing.rb
index ff1e47a1bb..255c89afdb 100644
--- a/spec/bundler/support/artifice/compact_index_extra_missing.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_missing.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index_extra"
-
-Artifice.deactivate
+require_relative "helpers/compact_index_extra"
class CompactIndexExtraMissing < CompactIndexExtra
get "/extra/fetch/actual/gem/:id" do
@@ -14,4 +12,6 @@ class CompactIndexExtraMissing < CompactIndexExtra
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexExtraMissing)
diff --git a/spec/bundler/support/artifice/compact_index_forbidden.rb b/spec/bundler/support/artifice/compact_index_forbidden.rb
index 3eebe0fbd8..18c30ed9a2 100644
--- a/spec/bundler/support/artifice/compact_index_forbidden.rb
+++ b/spec/bundler/support/artifice/compact_index_forbidden.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexForbidden < CompactIndexAPI
get "/versions" do
@@ -10,4 +8,6 @@ class CompactIndexForbidden < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexForbidden)
diff --git a/spec/bundler/support/artifice/compact_index_host_redirect.rb b/spec/bundler/support/artifice/compact_index_host_redirect.rb
index 304c897d68..9a711186db 100644
--- a/spec/bundler/support/artifice/compact_index_host_redirect.rb
+++ b/spec/bundler/support/artifice/compact_index_host_redirect.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexHostRedirect < CompactIndexAPI
get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
@@ -18,4 +16,6 @@ class CompactIndexHostRedirect < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexHostRedirect)
diff --git a/spec/bundler/support/artifice/compact_index_no_gem.rb b/spec/bundler/support/artifice/compact_index_no_gem.rb
index 0a4be08a46..71f6629688 100644
--- a/spec/bundler/support/artifice/compact_index_no_gem.rb
+++ b/spec/bundler/support/artifice/compact_index_no_gem.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexNoGem < CompactIndexAPI
get "/gems/:id" do
@@ -10,4 +8,6 @@ class CompactIndexNoGem < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexNoGem)
diff --git a/spec/bundler/support/artifice/compact_index_partial_update.rb b/spec/bundler/support/artifice/compact_index_partial_update.rb
index cb1c7b9481..8c73011346 100644
--- a/spec/bundler/support/artifice/compact_index_partial_update.rb
+++ b/spec/bundler/support/artifice/compact_index_partial_update.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexPartialUpdate < CompactIndexAPI
# Stub the server to never return 304s. This simulates the behaviour of
@@ -35,4 +33,6 @@ class CompactIndexPartialUpdate < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexPartialUpdate)
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
index acf76dfbf0..20546ba4c3 100644
--- 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
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
def partial_update_no_etag
@@ -37,4 +35,6 @@ class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexPartialUpdateNoEtagNotIncremental)
diff --git a/spec/bundler/support/artifice/compact_index_precompiled_before.rb b/spec/bundler/support/artifice/compact_index_precompiled_before.rb
new file mode 100644
index 0000000000..b5f72f546a
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_precompiled_before.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexPrecompiledBefore < CompactIndexAPI
+ get "/info/:name" do
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ move_ruby_variant_to_the_end(CompactIndex.info(gem ? gem.versions : []))
+ end
+ end
+
+ private
+
+ def move_ruby_variant_to_the_end(response)
+ lines = response.split("\n")
+ ruby = lines.find {|line| /\A\d+\.\d+\.\d* \|/.match(line) }
+ lines.delete(ruby)
+ lines.push(ruby).join("\n")
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexPrecompiledBefore)
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 bb616125bb..8a7c4b79b0 100644
--- a/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
+++ b/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexRangeNotSatisfiable < CompactIndexAPI
get "/versions" do
@@ -31,4 +29,6 @@ class CompactIndexRangeNotSatisfiable < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexRangeNotSatisfiable)
diff --git a/spec/bundler/support/artifice/compact_index_rate_limited.rb b/spec/bundler/support/artifice/compact_index_rate_limited.rb
index 570105e2a0..4495491635 100644
--- a/spec/bundler/support/artifice/compact_index_rate_limited.rb
+++ b/spec/bundler/support/artifice/compact_index_rate_limited.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexRateLimited < CompactIndexAPI
class RequestCounter
@@ -45,4 +43,6 @@ class CompactIndexRateLimited < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexRateLimited)
diff --git a/spec/bundler/support/artifice/compact_index_redirects.rb b/spec/bundler/support/artifice/compact_index_redirects.rb
index 99adc797bf..f7ba393239 100644
--- a/spec/bundler/support/artifice/compact_index_redirects.rb
+++ b/spec/bundler/support/artifice/compact_index_redirects.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexRedirect < CompactIndexAPI
get "/fetch/actual/gem/:id" do
@@ -18,4 +16,6 @@ class CompactIndexRedirect < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexRedirect)
diff --git a/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb b/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb
index 7d427b5382..96259385e7 100644
--- a/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb
+++ b/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexStrictBasicAuthentication < CompactIndexAPI
before do
@@ -12,9 +10,11 @@ class CompactIndexStrictBasicAuthentication < CompactIndexAPI
# Only accepts password == "password"
unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz"
- halt 403, "Authentication failed"
+ halt 401, "Authentication failed"
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexStrictBasicAuthentication)
diff --git a/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb b/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb
index 036fac70b3..15850599b6 100644
--- a/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb
+++ b/spec/bundler/support/artifice/compact_index_wrong_dependencies.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexWrongDependencies < CompactIndexAPI
get "/info/:name" do
@@ -14,4 +12,6 @@ class CompactIndexWrongDependencies < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexWrongDependencies)
diff --git a/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb b/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb
index 8add32b88f..acc13a56ff 100644
--- a/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb
+++ b/spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "compact_index"
-
-Artifice.deactivate
+require_relative "helpers/compact_index"
class CompactIndexWrongGemChecksum < CompactIndexAPI
get "/info/:name" do
@@ -17,4 +15,6 @@ class CompactIndexWrongGemChecksum < CompactIndexAPI
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(CompactIndexWrongGemChecksum)
diff --git a/spec/bundler/support/artifice/endpoint.rb b/spec/bundler/support/artifice/endpoint.rb
index 4a820e5a3f..15242a7942 100644
--- a/spec/bundler/support/artifice/endpoint.rb
+++ b/spec/bundler/support/artifice/endpoint.rb
@@ -1,115 +1,6 @@
# frozen_string_literal: true
-require_relative "../path"
-
-$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 = Thread::Mutex.new
-
-at_exit do
- if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
- expected = expected.split("\n").sort
- actual = ALL_REQUESTS.sort
-
- unless expected == actual
- raise "Unexpected requests!\nExpected:\n\t#{expected.join("\n\t")}\n\nActual:\n\t#{actual.join("\n\t")}"
- end
- end
-end
-
-class Endpoint < Sinatra::Base
- def self.all_requests
- @all_requests ||= []
- end
-
- set :raise_errors, true
- set :show_exceptions, false
-
- def call!(*)
- super.tap do
- ALL_REQUESTS_MUTEX.synchronize do
- ALL_REQUESTS << @request.url
- end
- end
- end
-
- helpers do
- 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?
-
- 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)
- full_name = "#{name}-#{version}"
- full_name += "-#{platform}" if platform != "ruby"
- Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
- end
- end
-
- get "/quick/Marshal.4.8/:id" do
- redirect "/fetch/actual/gem/#{params[:id]}"
- end
-
- get "/fetch/actual/gem/:id" do
- File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
- end
-
- get "/gems/:id" do
- File.binread("#{default_gem_repo}/gems/#{params[:id]}")
- end
-
- get "/api/v1/dependencies" do
- Marshal.dump(dependencies_for(params[:gems]))
- end
-
- get "/specs.4.8.gz" do
- File.binread("#{default_gem_repo}/specs.4.8.gz")
- end
-
- get "/prerelease_specs.4.8.gz" do
- File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
- end
-end
+require_relative "helpers/endpoint"
+require_relative "helpers/artifice"
Artifice.activate_with(Endpoint)
diff --git a/spec/bundler/support/artifice/endpoint_500.rb b/spec/bundler/support/artifice/endpoint_500.rb
index 0ce8dfeaad..d8ab6b65bc 100644
--- a/spec/bundler/support/artifice/endpoint_500.rb
+++ b/spec/bundler/support/artifice/endpoint_500.rb
@@ -2,17 +2,16 @@
require_relative "../path"
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
-require "artifice"
require "sinatra/base"
-Artifice.deactivate
-
class Endpoint500 < Sinatra::Base
before do
halt 500
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(Endpoint500)
diff --git a/spec/bundler/support/artifice/endpoint_api_forbidden.rb b/spec/bundler/support/artifice/endpoint_api_forbidden.rb
index edc2463424..6bdc5896d6 100644
--- a/spec/bundler/support/artifice/endpoint_api_forbidden.rb
+++ b/spec/bundler/support/artifice/endpoint_api_forbidden.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointApiForbidden < Endpoint
get "/api/v1/dependencies" do
@@ -10,4 +8,6 @@ class EndpointApiForbidden < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointApiForbidden)
diff --git a/spec/bundler/support/artifice/endpoint_api_missing.rb b/spec/bundler/support/artifice/endpoint_api_missing.rb
deleted file mode 100644
index 755c42e836..0000000000
--- a/spec/bundler/support/artifice/endpoint_api_missing.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "endpoint"
-
-Artifice.deactivate
-
-class EndpointApiMissing < Endpoint
- get "/fetch/actual/gem/:id" do
- warn params[:id]
- if params[:id] == "rack-1.0.gemspec.rz"
- halt 404
- else
- File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
- end
- end
-end
-
-Artifice.activate_with(EndpointApiMissing)
diff --git a/spec/bundler/support/artifice/endpoint_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_basic_authentication.rb
index ff3d1493d6..e8e3569e63 100644
--- a/spec/bundler/support/artifice/endpoint_basic_authentication.rb
+++ b/spec/bundler/support/artifice/endpoint_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointBasicAuthentication < Endpoint
before do
@@ -12,4 +10,6 @@ class EndpointBasicAuthentication < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
index 8b8972cedd..ce30de0a68 100644
--- a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointCredsDiffHost < Endpoint
helpers do
@@ -36,4 +34,6 @@ class EndpointCredsDiffHost < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointCredsDiffHost)
diff --git a/spec/bundler/support/artifice/endpoint_extra.rb b/spec/bundler/support/artifice/endpoint_extra.rb
index 942c4352b7..021fd435fe 100644
--- a/spec/bundler/support/artifice/endpoint_extra.rb
+++ b/spec/bundler/support/artifice/endpoint_extra.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointExtra < Endpoint
get "/extra/api/v1/dependencies" do
@@ -30,4 +28,6 @@ class EndpointExtra < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointExtra)
diff --git a/spec/bundler/support/artifice/endpoint_extra_api.rb b/spec/bundler/support/artifice/endpoint_extra_api.rb
index 1cfef7a7fc..a965af6e73 100644
--- a/spec/bundler/support/artifice/endpoint_extra_api.rb
+++ b/spec/bundler/support/artifice/endpoint_extra_api.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointExtraApi < Endpoint
get "/extra/api/v1/dependencies" do
@@ -31,4 +29,6 @@ class EndpointExtraApi < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointExtraApi)
diff --git a/spec/bundler/support/artifice/endpoint_extra_missing.rb b/spec/bundler/support/artifice/endpoint_extra_missing.rb
index 5fd9238207..73e2defb32 100644
--- a/spec/bundler/support/artifice/endpoint_extra_missing.rb
+++ b/spec/bundler/support/artifice/endpoint_extra_missing.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint_extra"
-
-Artifice.deactivate
+require_relative "helpers/endpoint_extra"
class EndpointExtraMissing < EndpointExtra
get "/extra/fetch/actual/gem/:id" do
@@ -14,4 +12,6 @@ class EndpointExtraMissing < EndpointExtra
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointExtraMissing)
diff --git a/spec/bundler/support/artifice/endpoint_fallback.rb b/spec/bundler/support/artifice/endpoint_fallback.rb
index 08edf232e3..742e563f07 100644
--- a/spec/bundler/support/artifice/endpoint_fallback.rb
+++ b/spec/bundler/support/artifice/endpoint_fallback.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointFallback < Endpoint
DEPENDENCY_LIMIT = 60
@@ -16,4 +14,6 @@ class EndpointFallback < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointFallback)
diff --git a/spec/bundler/support/artifice/endpoint_host_redirect.rb b/spec/bundler/support/artifice/endpoint_host_redirect.rb
index 338cbcad00..0efb6cda02 100644
--- a/spec/bundler/support/artifice/endpoint_host_redirect.rb
+++ b/spec/bundler/support/artifice/endpoint_host_redirect.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointHostRedirect < Endpoint
get "/fetch/actual/gem/:id", :host_name => "localgemserver.test" do
@@ -14,4 +12,6 @@ class EndpointHostRedirect < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointHostRedirect)
diff --git a/spec/bundler/support/artifice/endpoint_marshal_fail.rb b/spec/bundler/support/artifice/endpoint_marshal_fail.rb
index 22c13e3e17..74ce321de6 100644
--- a/spec/bundler/support/artifice/endpoint_marshal_fail.rb
+++ b/spec/bundler/support/artifice/endpoint_marshal_fail.rb
@@ -1,13 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint_fallback"
-
-Artifice.deactivate
-
-class EndpointMarshalFail < EndpointFallback
- get "/api/v1/dependencies" do
- "f0283y01hasf"
- end
-end
+require_relative "helpers/endpoint_marshal_fail"
+require_relative "helpers/artifice"
Artifice.activate_with(EndpointMarshalFail)
diff --git a/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
index c341c3993f..ea4cfbe965 100644
--- a/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
+++ b/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint_marshal_fail"
-
-Artifice.deactivate
+require_relative "helpers/endpoint_marshal_fail"
class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
before do
@@ -12,4 +10,6 @@ class EndpointMarshalFailBasicAuthentication < EndpointMarshalFail
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointMarshalFailBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint_mirror_source.rb b/spec/bundler/support/artifice/endpoint_mirror_source.rb
index 788a9027f3..6ea1a77eca 100644
--- a/spec/bundler/support/artifice/endpoint_mirror_source.rb
+++ b/spec/bundler/support/artifice/endpoint_mirror_source.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
+require_relative "helpers/endpoint"
class EndpointMirrorSource < Endpoint
get "/gems/:id" do
@@ -12,4 +12,6 @@ class EndpointMirrorSource < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointMirrorSource)
diff --git a/spec/bundler/support/artifice/endpoint_redirect.rb b/spec/bundler/support/artifice/endpoint_redirect.rb
index ee97fccf64..84f546ba9d 100644
--- a/spec/bundler/support/artifice/endpoint_redirect.rb
+++ b/spec/bundler/support/artifice/endpoint_redirect.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointRedirect < Endpoint
get "/fetch/actual/gem/:id" do
@@ -14,4 +12,6 @@ class EndpointRedirect < Endpoint
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointRedirect)
diff --git a/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb
index 4d4da08770..dff360c5c5 100644
--- a/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb
+++ b/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint"
-
-Artifice.deactivate
+require_relative "helpers/endpoint"
class EndpointStrictBasicAuthentication < Endpoint
before do
@@ -12,9 +10,11 @@ class EndpointStrictBasicAuthentication < Endpoint
# Only accepts password == "password"
unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz"
- halt 403, "Authentication failed"
+ halt 401, "Authentication failed"
end
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointStrictBasicAuthentication)
diff --git a/spec/bundler/support/artifice/endpoint_timeout.rb b/spec/bundler/support/artifice/endpoint_timeout.rb
index c118da1893..86b793e499 100644
--- a/spec/bundler/support/artifice/endpoint_timeout.rb
+++ b/spec/bundler/support/artifice/endpoint_timeout.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-require_relative "endpoint_fallback"
-
-Artifice.deactivate
+require_relative "helpers/endpoint_fallback"
class EndpointTimeout < EndpointFallback
SLEEP_TIMEOUT = 3
@@ -12,4 +10,6 @@ class EndpointTimeout < EndpointFallback
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(EndpointTimeout)
diff --git a/spec/bundler/support/artifice/fail.rb b/spec/bundler/support/artifice/fail.rb
index f69f2eccc6..6286e43fbd 100644
--- a/spec/bundler/support/artifice/fail.rb
+++ b/spec/bundler/support/artifice/fail.rb
@@ -2,10 +2,6 @@
require "net/http"
-# We can't use artifice here because it uses rack
-
-module Artifice; end # for < 2.0, Net::HTTP::Persistent::SSLReuse
-
class Fail < Net::HTTP
# Net::HTTP uses a @newimpl instance variable to decide whether
# to use a legacy implementation. Since we are subclassing
@@ -27,8 +23,7 @@ class Fail < Net::HTTP
end
end
+require_relative "helpers/artifice"
+
# Replace Net::HTTP with our failing subclass
-::Net.class_eval do
- remove_const(:HTTP)
- const_set(:HTTP, ::Fail)
-end
+Artifice.replace_net_http(::Fail)
diff --git a/spec/bundler/support/artifice/helpers/artifice.rb b/spec/bundler/support/artifice/helpers/artifice.rb
new file mode 100644
index 0000000000..b8c78614fb
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/artifice.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+# This module was initially borrowed from https://github.com/wycats/artifice
+module Artifice
+ # Activate Artifice with a particular Rack endpoint.
+ #
+ # Calling this method will replace the Net::HTTP system
+ # with a replacement that routes all requests to the
+ # Rack endpoint.
+ #
+ # @param [#call] endpoint A valid Rack endpoint
+ def self.activate_with(endpoint)
+ require_relative "rack_request"
+
+ Net::HTTP.endpoint = endpoint
+ replace_net_http(Artifice::Net::HTTP)
+ end
+
+ # Deactivate the Artifice replacement.
+ def self.deactivate
+ replace_net_http(::Net::HTTP)
+ end
+
+ def self.replace_net_http(value)
+ ::Net.class_eval do
+ remove_const(:HTTP)
+ const_set(:HTTP, value)
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index.rb b/spec/bundler/support/artifice/helpers/compact_index.rb
new file mode 100644
index 0000000000..4df47a9659
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+require_relative "endpoint"
+
+$LOAD_PATH.unshift Dir[Spec::Path.base_system_gem_path.join("gems/compact_index*/lib")].first.to_s
+require "compact_index"
+
+class CompactIndexAPI < Endpoint
+ helpers do
+ include Spec::Path
+
+ def load_spec(name, version, platform, gem_repo)
+ full_name = "#{name}-#{version}"
+ full_name += "-#{platform}" if platform != "ruby"
+ Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
+ end
+
+ def etag_response
+ response_body = yield
+ checksum = Digest(:MD5).hexdigest(response_body)
+ return if not_modified?(checksum)
+ headers "ETag" => quote(checksum)
+ headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
+ content_type "text/plain"
+ requested_range_for(response_body)
+ rescue StandardError => e
+ puts e
+ puts e.backtrace
+ raise
+ end
+
+ def not_modified?(checksum)
+ etags = parse_etags(request.env["HTTP_IF_NONE_MATCH"])
+
+ return unless etags.include?(checksum)
+ headers "ETag" => quote(checksum)
+ status 304
+ body ""
+ end
+
+ def requested_range_for(response_body)
+ ranges = Rack::Utils.byte_ranges(env, response_body.bytesize)
+
+ if ranges
+ status 206
+ body ranges.map! {|range| slice_body(response_body, range) }.join
+ else
+ status 200
+ body response_body
+ end
+ end
+
+ def quote(string)
+ %("#{string}")
+ end
+
+ def parse_etags(value)
+ value ? value.split(/, ?/).select {|s| s.sub!(/"(.*)"/, '\1') } : []
+ end
+
+ def slice_body(body, range)
+ body.byteslice(range)
+ end
+
+ def gems(gem_repo = default_gem_repo)
+ @gems ||= {}
+ @gems[gem_repo] ||= begin
+ specs = Bundler::Deprecate.skip_during do
+ %w[specs.4.8 prerelease_specs.4.8].map do |filename|
+ Marshal.load(File.open(gem_repo.join(filename)).read).map do |name, version, platform|
+ load_spec(name, version, platform, gem_repo)
+ end
+ end.flatten
+ end
+
+ specs.group_by(&:name).map do |name, versions|
+ gem_versions = versions.map do |spec|
+ deps = spec.dependencies.select {|d| d.type == :runtime }.map do |d|
+ reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
+ CompactIndex::Dependency.new(d.name, reqs)
+ end
+ checksum = begin
+ 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.to_s, spec.required_rubygems_version.to_s)
+ end
+ CompactIndex::Gem.new(name, gem_versions)
+ end
+ end
+ end
+ end
+
+ get "/names" do
+ etag_response do
+ CompactIndex.names(gems.map(&:name))
+ end
+ end
+
+ get "/versions" do
+ etag_response do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems)
+ file.contents
+ end
+ end
+
+ get "/info/:name" do
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ CompactIndex.info(gem ? gem.versions : [])
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index_extra.rb b/spec/bundler/support/artifice/helpers/compact_index_extra.rb
new file mode 100644
index 0000000000..9e742630dd
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index_extra.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require_relative "compact_index"
+
+class CompactIndexExtra < CompactIndexAPI
+ get "/extra/versions" do
+ halt 404
+ end
+
+ get "/extra/api/v1/dependencies" do
+ halt 404
+ end
+
+ get "/extra/specs.4.8.gz" do
+ File.binread("#{gem_repo2}/specs.4.8.gz")
+ end
+
+ get "/extra/prerelease_specs.4.8.gz" do
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
+ end
+
+ get "/extra/quick/Marshal.4.8/:id" do
+ redirect "/extra/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/extra/fetch/actual/gem/:id" do
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/extra/gems/:id" do
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/compact_index_extra_api.rb b/spec/bundler/support/artifice/helpers/compact_index_extra_api.rb
new file mode 100644
index 0000000000..d9a7d83d23
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/compact_index_extra_api.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require_relative "compact_index"
+
+class CompactIndexExtraApi < CompactIndexAPI
+ get "/extra/names" do
+ etag_response do
+ CompactIndex.names(gems(gem_repo4).map(&:name))
+ end
+ end
+
+ get "/extra/versions" do
+ etag_response do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems(gem_repo4))
+ file.contents
+ end
+ end
+
+ get "/extra/info/:name" do
+ etag_response do
+ gem = gems(gem_repo4).find {|g| g.name == params[:name] }
+ CompactIndex.info(gem ? gem.versions : [])
+ end
+ end
+
+ get "/extra/specs.4.8.gz" do
+ File.binread("#{gem_repo4}/specs.4.8.gz")
+ end
+
+ get "/extra/prerelease_specs.4.8.gz" do
+ File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
+ end
+
+ get "/extra/quick/Marshal.4.8/:id" do
+ redirect "/extra/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/extra/fetch/actual/gem/:id" do
+ File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/extra/gems/:id" do
+ File.binread("#{gem_repo4}/gems/#{params[:id]}")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint.rb b/spec/bundler/support/artifice/helpers/endpoint.rb
new file mode 100644
index 0000000000..fc0381dc38
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require_relative "../../path"
+
+$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
+
+require "sinatra/base"
+
+ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
+ALL_REQUESTS_MUTEX = Thread::Mutex.new
+
+at_exit do
+ if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
+ expected = expected.split("\n").sort
+ actual = ALL_REQUESTS.sort
+
+ unless expected == actual
+ raise "Unexpected requests!\nExpected:\n\t#{expected.join("\n\t")}\n\nActual:\n\t#{actual.join("\n\t")}"
+ end
+ end
+end
+
+class Endpoint < Sinatra::Base
+ def self.all_requests
+ @all_requests ||= []
+ end
+
+ set :raise_errors, true
+ set :show_exceptions, false
+
+ def call!(*)
+ super.tap do
+ ALL_REQUESTS_MUTEX.synchronize do
+ ALL_REQUESTS << @request.url
+ end
+ end
+ end
+
+ helpers do
+ 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?
+
+ 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)
+ full_name = "#{name}-#{version}"
+ full_name += "-#{platform}" if platform != "ruby"
+ Marshal.load(Bundler.rubygems.inflate(File.binread(gem_repo.join("quick/Marshal.4.8/#{full_name}.gemspec.rz"))))
+ end
+ end
+
+ get "/quick/Marshal.4.8/:id" do
+ redirect "/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/fetch/actual/gem/:id" do
+ File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/gems/:id" do
+ File.binread("#{default_gem_repo}/gems/#{params[:id]}")
+ end
+
+ get "/api/v1/dependencies" do
+ Marshal.dump(dependencies_for(params[:gems]))
+ end
+
+ get "/specs.4.8.gz" do
+ File.binread("#{default_gem_repo}/specs.4.8.gz")
+ end
+
+ get "/prerelease_specs.4.8.gz" do
+ File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint_extra.rb b/spec/bundler/support/artifice/helpers/endpoint_extra.rb
new file mode 100644
index 0000000000..ad08495b50
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint_extra.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require_relative "endpoint"
+
+class EndpointExtra < Endpoint
+ get "/extra/api/v1/dependencies" do
+ halt 404
+ end
+
+ get "/extra/specs.4.8.gz" do
+ File.binread("#{gem_repo2}/specs.4.8.gz")
+ end
+
+ get "/extra/prerelease_specs.4.8.gz" do
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
+ end
+
+ get "/extra/quick/Marshal.4.8/:id" do
+ redirect "/extra/fetch/actual/gem/#{params[:id]}"
+ end
+
+ get "/extra/fetch/actual/gem/:id" do
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ end
+
+ get "/extra/gems/:id" do
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint_fallback.rb b/spec/bundler/support/artifice/helpers/endpoint_fallback.rb
new file mode 100644
index 0000000000..a232930b67
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint_fallback.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require_relative "endpoint"
+
+class EndpointFallback < Endpoint
+ DEPENDENCY_LIMIT = 60
+
+ get "/api/v1/dependencies" do
+ if params[:gems] && params[:gems].size <= DEPENDENCY_LIMIT
+ Marshal.dump(dependencies_for(params[:gems]))
+ else
+ halt 413, "Too many gems to resolve, please request less than #{DEPENDENCY_LIMIT} gems"
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb b/spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb
new file mode 100644
index 0000000000..c409d39d99
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative "endpoint_fallback"
+
+class EndpointMarshalFail < EndpointFallback
+ get "/api/v1/dependencies" do
+ "f0283y01hasf"
+ end
+end
diff --git a/spec/bundler/support/artifice/helpers/rack_request.rb b/spec/bundler/support/artifice/helpers/rack_request.rb
new file mode 100644
index 0000000000..c4a07812a6
--- /dev/null
+++ b/spec/bundler/support/artifice/helpers/rack_request.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require "rack/test"
+require "net/http"
+
+module Artifice
+ module Net
+ # This is an internal object that can receive Rack requests
+ # to the application using the Rack::Test API
+ class RackRequest
+ include Rack::Test::Methods
+ attr_reader :app
+
+ def initialize(app)
+ @app = app
+ end
+ end
+
+ class HTTP < ::Net::HTTP
+ class << self
+ attr_accessor :endpoint
+ end
+
+ # Net::HTTP uses a @newimpl instance variable to decide whether
+ # to use a legacy implementation. Since we are subclassing
+ # Net::HTTP, we must set it
+ @newimpl = true
+
+ # We don't need to connect, so blank out this method
+ def connect
+ end
+
+ # Replace the Net::HTTP request method with a method
+ # that converts the request into a Rack request and
+ # dispatches it to the Rack endpoint.
+ #
+ # @param [Net::HTTPRequest] req A Net::HTTPRequest
+ # object, or one if its subclasses
+ # @param [optional, String, #read] body This should
+ # be sent as "rack.input". If it's a String, it will
+ # be converted to a StringIO.
+ # @return [Net::HTTPResponse]
+ #
+ # @yield [Net::HTTPResponse] If a block is provided,
+ # this method will yield the Net::HTTPResponse to
+ # it after the body is read.
+ def request(req, body = nil, &block)
+ rack_request = RackRequest.new(self.class.endpoint)
+
+ req.each_header do |header, value|
+ rack_request.header(header, value)
+ end
+
+ scheme = use_ssl? ? "https" : "http"
+ prefix = "#{scheme}://#{addr_port}"
+ body_stream_contents = req.body_stream.read if req.body_stream
+
+ response = rack_request.request("#{prefix}#{req.path}",
+ { :method => req.method, :input => body || req.body || body_stream_contents })
+
+ make_net_http_response(response, &block)
+ end
+
+ private
+
+ # This method takes a Rack response and creates a Net::HTTPResponse
+ # Instead of trying to mock HTTPResponse directly, we just convert
+ # the Rack response into a String that looks like a normal HTTP
+ # response and call Net::HTTPResponse.read_new
+ #
+ # @param [Array(#to_i, Hash, #each)] response a Rack response
+ # @return [Net::HTTPResponse]
+ # @yield [Net::HTTPResponse] If a block is provided, yield the
+ # response to it after the body is read
+ def make_net_http_response(response)
+ status = response.status
+ headers = response.headers
+ body = response.body
+
+ response_string = []
+ response_string << "HTTP/1.1 #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
+
+ headers.each do |header, value|
+ response_string << "#{header}: #{value}"
+ end
+
+ response_string << "" << body
+
+ response_io = ::Net::BufferedIO.new(StringIO.new(response_string.join("\n")))
+ res = ::Net::HTTPResponse.read_new(response_io)
+
+ res.reading_body(response_io, true) do
+ yield res if block_given?
+ end
+
+ res
+ end
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/used_cassettes.txt b/spec/bundler/support/artifice/used_cassettes.txt
new file mode 100644
index 0000000000..a96efc790d
--- /dev/null
+++ b/spec/bundler/support/artifice/used_cassettes.txt
@@ -0,0 +1,20908 @@
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ffi-1.15.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/capybara/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/selenium-webdriver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/xpath/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/culerity/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uglifier/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/matrix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyzip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/childprocess/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libwebsocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-active_record/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/therubyracer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gherkin3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-wire/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/event-bus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-formatter-dots/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-html-formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-gherkin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-cucumber-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-messages/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-create-meta/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-uname/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/database_cleaner-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libv8/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trollop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/c21e/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag_expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cucumber-tag-expressions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-protobuf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/protobuf-cucumber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/curses/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis-namespace/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/resque/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rufus-scheduler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mono_logger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/et-orbi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/vegas/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fugit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/raabro/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.2.3.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-4.5.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mono_logger-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/ruby2_keywords-0.0.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tilt-2.0.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/mustermann-1.1.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/redis-namespace-1.6.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/vegas-0.1.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-protection-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/sinatra-2.1.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/tzinfo-2.0.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-1.24.1.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rufus-scheduler-2.0.24.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/resque-scheduler-2.2.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/climate_control/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cocaine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/paperclip/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/terrapin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_aws/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mocha/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thoughtbot-shoulda/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metaclass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/right_http_connection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gxapi_rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-api-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sass-listen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/addressable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/extlib/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/signet/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpadapter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/liquid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/launchy/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/autoparse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sinatra/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uuidtools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jwt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/retriable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/googleauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hurley/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoist/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/representable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-generator/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sassc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fchange/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-fsevent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-inotify/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rb-kqueue/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_dep/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-io/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/public_suffix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/english/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-protection/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongrel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mustermann/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multipart-post/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_http/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-net_http_persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-em_synchrony/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-httpclient/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-patron/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday-rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/logging/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/os/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hooks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/uber/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/declarative-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/trailblazer-option/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrick/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/google-apis-discovery_v1/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gems/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/cgi_multipart_eof_fix/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/fastthread/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gem_plugin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/escape_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/excon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-http-persistent/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/flexmock/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/little-plugger/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hashie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faraday_middleware/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rash/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/oauth2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/roauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/httpauth/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.10.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongoid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongodb-mongo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/durran-validatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mislav-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mongo_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/leshill-will_paginate/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bson/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/origin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/moped/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby2_keywords/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pry/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/optionable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/connection_pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coderay/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spoon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coveralls/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/metasploit-erd/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/yard/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-graphviz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/choice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/webrat/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/railties/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-mocks/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-core/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-expectations/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-collection_matchers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-support/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov-html/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/docile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/lockfile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/colorize/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/simplecov_json_formatter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rest-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tins/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/term-ansicolor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activeresource/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionwebservice/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionview/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activejob/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actioncable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activestorage/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actiontext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/actionmailbox/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-ssl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rexml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nokogiri/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hpricot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-test/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/abstract/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rdoc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/treetop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-mount/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack-cache/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sprockets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/journey/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-deprecated_sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-dom-testing/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-html-sanitizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activerecord-deprecated_finders/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/arel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/netrc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-cookie/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/http-accept/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sync/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-format/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rails-observers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-serializers-xml/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/erubi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/marcel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_mime/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mimemagic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activemodel-globalid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-rails/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/em-hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faye-websocket/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-driver/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/redis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nio4r/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facets/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/polyglot/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/weakling/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mini_portile2/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pkg-config/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/racc/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multimap/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/loofah/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hike/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tilt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mime-types-data/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/domain_name/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-essentials/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sqlite3/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tlsmail/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hiredis/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/text-hyphen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/eventmachine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timers/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/facter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-extras/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-fsm/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-pool/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/nenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/celluloid-supervision/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rspec-logsplit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/websocket-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ftp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/crass/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake-compiler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hitimes/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/CFPropertyList/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sys-admin/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32console/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-dir/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-api/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/windows-pr/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hocon/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/win32-security/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/dotenv-deployment/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coffee-script-source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/daemons/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/execjs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/time/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/configuration/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/mkrf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-protocol/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unf_ext/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rainbow/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/backports/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/powerpack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-progressbar/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/astrolabe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jaro_winkler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/parallel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubocop-ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/regexp_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/psych/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/test-unit/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/libxml-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi-win32-extensions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/date/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/io-wait/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/timeout/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ast/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/slop/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jar-dependencies/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strscan/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/power_assert/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pattern-match/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/maven-tools/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby-maven-libs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/virtus/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/axiom-types/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/coercible/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equalizer/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/descendants_tracker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/adamantium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ice_nine/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memoizable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bundler/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/bundler-2.3.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/concurrent-ruby-1.1.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.9.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.12.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/activesupport/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/i18n/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/faker/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/builder/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/memcache-client/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tzinfo/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thread_safe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/minitest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/method_source/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/zeitwerk/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/concurrent-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/multi_json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/pastel/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/thor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-pager/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-screen/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-tree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/RubyInline/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/hoe/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ZenTest/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/atomic/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/functional-ruby/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ruby_parser/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/equatable/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-which/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/tty-color/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ref/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/verse/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rubyforge/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/gemcutter/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/sexp_processor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ParseTree/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode_utils/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/unicode-display_width/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/strings-ansi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rake/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-scp/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json_pure/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/SexpProcessor/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/spruz/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/net-ssh/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/jruby-pageant/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rbnacl-libsodium/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/bcrypt_pbkdf/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/needle/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/ffi/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/i18n-0.6.11.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/multi_json-1.15.0.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/activesupport-3.2.22.5.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/faker-1.1.2.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/diff-lcs/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/diff-lcs-1.4.4.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/rack/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/info/json/GET/response
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/request
+spec/support/artifice/vcr_cassettes/realworld/rubygems.org/gems/rack-2.0.9.gem/GET/response
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/request
+spec/support/artifice/vcr_cassettes/realworld/index.rubygems.org/versions/GET/response
diff --git a/spec/bundler/support/artifice/vcr.rb b/spec/bundler/support/artifice/vcr.rb
index 0d51201bef..6a346f1ff9 100644
--- a/spec/bundler/support/artifice/vcr.rb
+++ b/spec/bundler/support/artifice/vcr.rb
@@ -4,6 +4,7 @@ require "net/http"
require_relative "../path"
CASSETTE_PATH = "#{Spec::Path.spec_dir}/support/artifice/vcr_cassettes"
+USED_CASSETTES_PATH = "#{Spec::Path.spec_dir}/support/artifice/used_cassettes.txt"
CASSETTE_NAME = ENV.fetch("BUNDLER_SPEC_VCR_CASSETTE_NAME") { "realworld" }
class BundlerVCRHTTP < Net::HTTP
@@ -22,6 +23,10 @@ class BundlerVCRHTTP < Net::HTTP
@__vcr_request_handler = handler
end
+ File.open(USED_CASSETTES_PATH, "a+") do |f|
+ f.puts request_pair_paths.map {|path| Pathname.new(path).relative_path_from(Spec::Path.source_root).to_s }.join("\n")
+ end
+
if recorded_response?
recorded_response
else
@@ -42,7 +47,7 @@ class BundlerVCRHTTP < Net::HTTP
response.uri = request.uri
response.reading_body(response_io, request.response_body_permitted?) do
- response_block.call(response) if response_block
+ response_block&.call(response)
end
end
end
@@ -69,30 +74,13 @@ class BundlerVCRHTTP < Net::HTTP
end
def file_name_for_key(key)
- key.join("/").gsub(/[\:*?"<>|]/, "-")
+ File.join(*key).gsub(/[\:*?"<>|]/, "-")
end
def request_pair_paths
%w[request response].map do |kind|
- File.join(CASSETTE_PATH, CASSETTE_NAME, file_name_for_key(key + [kind]))
- end
- end
-
- def read_stored_request(path)
- contents = File.binread(path)
- headers = {}
- method = nil
- path = nil
- contents.lines.grep(/^> /).each do |line|
- if line =~ /^> (GET|HEAD|POST|PATCH|PUT|DELETE) (.*)/
- method = $1
- path = $2.strip
- elsif line =~ /^> (.*?): (.*)/
- headers[$1] = $2
- end
+ File.join(CASSETTE_PATH, CASSETTE_NAME, file_name_for_key(key), kind)
end
- body = contents =~ /^([^>].*)/m && $1
- Net::HTTP.const_get(method.capitalize).new(path, headers).tap {|r| r.body = body if body }
end
def request_to_string(request)
@@ -158,8 +146,7 @@ class BundlerVCRHTTP < Net::HTTP
alias_method :request, :request_with_vcr
end
+require_relative "helpers/artifice"
+
# Replace Net::HTTP with our VCR subclass
-::Net.class_eval do
- remove_const(:HTTP)
- const_set(:HTTP, BundlerVCRHTTP)
-end
+Artifice.replace_net_http(BundlerVCRHTTP)
diff --git a/spec/bundler/support/artifice/windows.rb b/spec/bundler/support/artifice/windows.rb
index ddbbd62b96..4d90e0a426 100644
--- a/spec/bundler/support/artifice/windows.rb
+++ b/spec/bundler/support/artifice/windows.rb
@@ -2,13 +2,10 @@
require_relative "../path"
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
-require "artifice"
require "sinatra/base"
-Artifice.deactivate
-
class Windows < Sinatra::Base
set :raise_errors, true
set :show_exceptions, false
@@ -43,4 +40,6 @@ class Windows < Sinatra::Base
end
end
+require_relative "helpers/artifice"
+
Artifice.activate_with(Windows)
diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb
index 25377d2ac2..dfc7139523 100644
--- a/spec/bundler/support/builders.rb
+++ b/spec/bundler/support/builders.rb
@@ -17,24 +17,17 @@ 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"
@@ -89,8 +82,8 @@ module Spec
end
build_gem "platform_specific" do |s|
- s.platform = Bundler.local_platform
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
+ s.platform = Gem::Platform.local
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Gem::Platform.local}'"
end
build_gem "platform_specific" do |s|
@@ -105,15 +98,27 @@ module Spec
build_gem "platform_specific" do |s|
s.platform = "x86-mswin32"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 MSWIN'"
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x86-mswin32'"
+ end
+
+ build_gem "platform_specific" do |s|
+ s.platform = "x64-mswin64"
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x64-mswin64'"
end
build_gem "platform_specific" do |s|
s.platform = "x86-mingw32"
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x86-mingw32'"
end
build_gem "platform_specific" do |s|
s.platform = "x64-mingw32"
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x64-mingw32'"
+ end
+
+ build_gem "platform_specific" do |s|
+ s.platform = "x64-mingw-ucrt"
+ s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x64-mingw-ucrt'"
end
build_gem "platform_specific" do |s|
@@ -203,10 +208,8 @@ module Spec
update_repo(gem_repo4, &blk)
end
- def update_repo2
- update_repo gem_repo2 do
- yield if block_given?
- end
+ def update_repo2(&blk)
+ update_repo(gem_repo2, &blk)
end
def build_security_repo
@@ -254,7 +257,7 @@ module Spec
@_build_path = "#{path}/gems"
@_build_repo = File.basename(path)
yield
- with_gem_path_as Path.base_system_gems do
+ with_gem_path_as Path.base_system_gem_path do
gem_command :generate_index, :dir => path
end
ensure
@@ -281,10 +284,6 @@ module Spec
end
end
- def build_dep(name, requirements = Gem::Requirement.default, type = :runtime)
- Bundler::Dependency.new(name, :version => requirements)
- end
-
def build_lib(name, *args, &blk)
build_with(LibBuilder, name, args, &blk)
end
@@ -439,8 +438,7 @@ module Spec
write "ext/extconf.rb", <<-RUBY
require "mkmf"
-
- # exit 1 unless with_config("simple")
+ $extout = "$(topdir)/" + RbConfig::CONFIG["EXTOUT"]
extension_name = "#{name}_c"
if extra_lib_dir = with_config("ext-lib")
@@ -479,7 +477,7 @@ module Spec
end
@spec.authors = ["no one"]
- @spec.files = @files.keys
+ @spec.files += @files.keys
case options[:gemspec]
when false
@@ -520,7 +518,7 @@ module Spec
class GitBuilder < LibBuilder
def _build(options)
- default_branch = options[:default_branch] || "master"
+ default_branch = options[:default_branch] || "main"
path = options[:path] || _default_path
source = options[:source] || "git@#{path}"
super(options.merge(:path => path, :source => source))
@@ -548,17 +546,8 @@ module Spec
update_gemspec = options[:gemspec] || false
source = options[:source] || "git@#{libpath}"
- @context.git "checkout master", libpath
-
if branch = options[:branch]
- raise "You can't specify `master` as the branch" if branch == "master"
- escaped_branch = Shellwords.shellescape(branch)
-
- if @context.git("branch -l #{escaped_branch}", libpath).empty?
- @context.git("branch #{escaped_branch}", libpath)
- end
-
- @context.git("checkout #{escaped_branch}", libpath)
+ @context.git("checkout -b #{Shellwords.shellescape(branch)}", libpath)
elsif tag = options[:tag]
@context.git("tag #{Shellwords.shellescape(tag)}", libpath)
elsif options[:remote]
@@ -572,8 +561,7 @@ module Spec
_default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'"
end
super(options.merge(:path => libpath, :gemspec => update_gemspec, :source => source))
- @context.git("add *", libpath)
- @context.git("commit -m BUMP", libpath, :raise_on_error => false)
+ @context.git("commit -am BUMP", libpath)
end
end
@@ -594,7 +582,8 @@ module Spec
class GemBuilder < LibBuilder
def _build(opts)
- lib_path = super(opts.merge(:path => @context.tmp(".tmp/#{@spec.full_name}"), :no_default => opts[:no_default]))
+ lib_path = opts[:lib_path] || @context.tmp(".tmp/#{@spec.full_name}")
+ lib_path = super(opts.merge(:path => lib_path, :no_default => opts[:no_default]))
destination = opts[:path] || _default_path
FileUtils.mkdir_p(lib_path.join(destination))
diff --git a/spec/bundler/support/bundle.rb b/spec/bundler/support/bundle.rb
index bb21526d35..5f808531ff 100644
--- a/spec/bundler/support/bundle.rb
+++ b/spec/bundler/support/bundle.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
require "rubygems"
+Gem.instance_variable_set(:@ruby, ENV["RUBY"]) if ENV["RUBY"]
+
require_relative "path"
bundler_gemspec = Spec::Path.loaded_gemspec
bundler_gemspec.instance_variable_set(:@full_gem_path, Spec::Path.source_root)
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
index 0c1f27e470..78545d2e64 100644
--- a/spec/bundler/support/filters.rb
+++ b/spec/bundler/support/filters.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "sudo"
-
class RequirementChecker < Proc
def self.against(present)
provided = Gem::Version.new(present)
@@ -21,19 +19,20 @@ class RequirementChecker < Proc
end
RSpec.configure do |config|
- config.filter_run_excluding :sudo => true
config.filter_run_excluding :realworld => true
- git_version = Bundler::Source::Git::GitProxy.new(nil, nil, nil).version
+ git_version = Bundler::Source::Git::GitProxy.new(nil, nil).version
config.filter_run_excluding :git => RequirementChecker.against(git_version)
config.filter_run_excluding :bundler => RequirementChecker.against(Bundler::VERSION.split(".")[0])
+ config.filter_run_excluding :rubygems => RequirementChecker.against(Gem::VERSION)
config.filter_run_excluding :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 :jruby_only => RUBY_ENGINE != "jruby"
+ config.filter_run_excluding :truffleruby_only => 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 aaf8c74894..c7fe3637cc 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -1,5 +1,10 @@
# frozen_string_literal: true
+if ENV["BUNDLER_SPEC_RUBY_PLATFORM"]
+ Object.send(:remove_const, :RUBY_PLATFORM)
+ RUBY_PLATFORM = ENV["BUNDLER_SPEC_RUBY_PLATFORM"]
+end
+
module Gem
def self.ruby=(ruby)
@ruby = ruby
@@ -9,33 +14,40 @@ module Gem
Gem.ruby = ENV["RUBY"]
end
- @default_dir = ENV["BUNDLER_GEM_DEFAULT_DIR"] if ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ if ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ @default_dir = ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ @default_specifications_dir = nil
+ end
+
+ if ENV["BUNDLER_SPEC_WINDOWS"]
+ @@win_platform = true # rubocop:disable Style/ClassVars
+ end
if ENV["BUNDLER_SPEC_PLATFORM"]
+ previous_platforms = @platforms
+ previous_local = Platform.local
+
class Platform
@local = new(ENV["BUNDLER_SPEC_PLATFORM"])
end
- @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
-
- if ENV["BUNDLER_SPEC_PLATFORM"] == "ruby"
- class << self
- remove_method :finish_resolve
-
- def finish_resolve
- []
- end
- end
- end
+ @platforms = previous_platforms.map {|platform| platform == previous_local ? Platform.local : platform }
end
if ENV["BUNDLER_SPEC_GEM_SOURCES"]
- @sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
+ self.sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
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"
+ if ENV["BUNDLER_IGNORE_DEFAULT_GEM"]
+ module RemoveDefaultBundlerStub
+ def default_stubs(pattern = "*")
+ super.delete_if {|stub| stub.name == "bundler" }
+ end
+ end
+
+ class Specification
+ class << self
+ prepend RemoveDefaultBundlerStub
+ end
end
end
end
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index 13fa36fbc2..7b8c56b6ad 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -78,9 +78,6 @@ module Spec
end
def bundle(cmd, options = {}, &block)
- with_sudo = options.delete(:sudo)
- sudo = with_sudo == :preserve_env ? "sudo -E --preserve-env=RUBYOPT" : "sudo" if with_sudo
-
bundle_bin = options.delete(:bundle_bin)
bundle_bin ||= installed_bindir.join("bundle")
@@ -88,7 +85,6 @@ module Spec
requires = options.delete(:requires) || []
realworld = RSpec.current_example.metadata[:realworld]
- options[:verbose] = true if options[:verbose].nil? && realworld
artifice = options.delete(:artifice) do
if realworld
@@ -120,7 +116,7 @@ module Spec
end
end.join
- ruby_cmd = build_ruby_cmd({ :sudo => sudo, :load_path => load_path, :requires => requires })
+ ruby_cmd = build_ruby_cmd({ :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
@@ -147,8 +143,6 @@ module Spec
end
def build_ruby_cmd(options = {})
- sudo = options.delete(:sudo)
-
libs = options.delete(:load_path)
lib_option = libs ? "-I#{libs.join(File::PATH_SEPARATOR)}" : []
@@ -156,7 +150,7 @@ module Spec
requires << "#{Path.spec_dir}/support/hax.rb"
require_option = requires.map {|r| "-r#{r}" }
- [sudo, Gem.ruby, *lib_option, *require_option].compact.join(" ")
+ [Gem.ruby, *lib_option, *require_option].compact.join(" ")
end
def gembin(cmd, options = {})
@@ -166,7 +160,7 @@ module Spec
def gem_command(command, options = {})
env = options[:env] || {}
- env["RUBYOPT"] = opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"] || ENV["RUBYOPT"])
+ env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"]), ENV["RUBYOPT"])
options[:env] = env
sys_exec("#{Path.gem_bin} #{command}", options)
end
@@ -181,7 +175,7 @@ module Spec
def sys_exec(cmd, options = {})
env = options[:env] || {}
- env["RUBYOPT"] = opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"] || ENV["RUBYOPT"])
+ env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"]), ENV["RUBYOPT"])
dir = options[:dir] || bundled_app
command_execution = CommandExecution.new(cmd.to_s, dir)
@@ -200,7 +194,7 @@ module Spec
command_execution.exitstatus = if status.exited?
status.exitstatus
elsif status.signaled?
- 128 + status.termsig
+ exit_status_for_signal(status.termsig)
end
end
@@ -220,13 +214,13 @@ module Spec
end
def all_commands_output
- return [] if command_executions.empty?
+ return "" if command_executions.empty?
"\n\nCommands:\n#{command_executions.map(&:to_s_verbose).join("\n\n")}"
end
def config(config = nil, path = bundled_app(".bundle/config"))
- return YAML.load_file(path) unless config
+ return Psych.load_file(path) unless config
FileUtils.mkdir_p(File.dirname(path))
File.open(path, "w") do |f|
f.puts config.to_yaml
@@ -238,33 +232,31 @@ module Spec
config(config, home(".bundle/config"))
end
- def create_file(*args)
- path = bundled_app(args.shift)
- path = args.shift if args.first.is_a?(Pathname)
- str = args.shift || ""
+ def create_file(path, contents = "")
+ path = Pathname.new(path).expand_path(bundled_app) unless path.is_a?(Pathname)
path.dirname.mkpath
File.open(path.to_s, "w") do |f|
- f.puts strip_whitespace(str)
+ f.puts strip_whitespace(contents)
end
end
def gemfile(*args)
- contents = args.shift
+ contents = args.pop
if contents.nil?
File.open(bundled_app_gemfile, "r", &:read)
else
- create_file("Gemfile", contents, *args)
+ create_file(args.pop || "Gemfile", contents)
end
end
def lockfile(*args)
- contents = args.shift
+ contents = args.pop
if contents.nil?
File.open(bundled_app_lock, "r", &:read)
else
- create_file("Gemfile.lock", contents, *args)
+ create_file(args.pop || "Gemfile.lock", contents)
end
end
@@ -275,8 +267,8 @@ module Spec
end
def install_gemfile(*args)
+ opts = args.last.is_a?(Hash) ? args.pop : {}
gemfile(*args)
- opts = args.last.is_a?(Hash) ? args.last : {}
bundle :install, opts
end
@@ -298,7 +290,7 @@ module Spec
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}
+ elsif %r{\A(?:[a-zA-Z]:)?/.*\.gem\z}.match?(gem_name)
install_gem(gem_name, default)
else
install_gem("#{gem_repo}/gems/#{gem_name}.gem", default)
@@ -310,7 +302,7 @@ module Spec
def install_gem(path, default = false)
raise "OMG `#{path}` does not exist!" unless File.exist?(path)
- args = "--no-document --ignore-dependencies"
+ args = "--no-document --ignore-dependencies --verbose --local"
args += " --default --install-dir #{system_gem_path}" if default
gem_command "install #{args} '#{path}'"
@@ -348,6 +340,7 @@ module Spec
without_env_side_effects do
ENV["GEM_HOME"] = path.to_s
ENV["GEM_PATH"] = path.to_s
+ ENV["BUNDLER_ORIG_GEM_HOME"] = nil
ENV["BUNDLER_ORIG_GEM_PATH"] = nil
yield
end
@@ -421,14 +414,14 @@ module Spec
end
end
- def cache_gems(*gems)
+ def cache_gems(*gems, gem_repo: gem_repo1)
gems = gems.flatten
FileUtils.rm_rf("#{bundled_app}/vendor/cache")
FileUtils.mkdir_p("#{bundled_app}/vendor/cache")
gems.each do |g|
- path = "#{gem_repo1}/gems/#{g}.gem"
+ path = "#{gem_repo}/gems/#{g}.gem"
raise "OMG `#{path}` does not exist!" unless File.exist?(path)
FileUtils.cp(path, "#{bundled_app}/vendor/cache")
end
@@ -439,6 +432,14 @@ module Spec
pristine_system_gems :bundler
end
+ def simulate_ruby_platform(ruby_platform)
+ old = ENV["BUNDLER_SPEC_RUBY_PLATFORM"]
+ ENV["BUNDLER_SPEC_RUBY_PLATFORM"] = ruby_platform.to_s
+ yield
+ ensure
+ ENV["BUNDLER_SPEC_RUBY_PLATFORM"] = old
+ end
+
def simulate_platform(platform)
old = ENV["BUNDLER_SPEC_PLATFORM"]
ENV["BUNDLER_SPEC_PLATFORM"] = platform.to_s
@@ -447,21 +448,16 @@ module Spec
ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given?
end
- def simulate_ruby_version(version)
- return if version == RUBY_VERSION
- old = ENV["BUNDLER_SPEC_RUBY_VERSION"]
- ENV["BUNDLER_SPEC_RUBY_VERSION"] = version
- yield if block_given?
- ensure
- ENV["BUNDLER_SPEC_RUBY_VERSION"] = old if block_given?
- end
-
- def simulate_windows(platform = mswin)
+ def simulate_windows(platform = x86_mswin32)
+ old = ENV["BUNDLER_SPEC_WINDOWS"]
+ ENV["BUNDLER_SPEC_WINDOWS"] = "true"
simulate_platform platform do
simulate_bundler_version_when_missing_prerelease_default_gem_activation do
yield
end
end
+ ensure
+ ENV["BUNDLER_SPEC_WINDOWS"] = old
end
def simulate_bundler_version_when_missing_prerelease_default_gem_activation
@@ -482,10 +478,28 @@ module Spec
end
end
- # versions providing a bundler version finder but not including
+ def current_ruby_minor
+ Gem.ruby_version.segments.tap {|s| s.delete_at(2) }.join(".")
+ end
+
+ def next_ruby_minor
+ ruby_major_minor.map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".")
+ end
+
+ def previous_ruby_minor
+ return "2.7" if ruby_major_minor == [3, 0]
+
+ ruby_major_minor.map.with_index {|s, i| i == 1 ? s - 1 : s }.join(".")
+ end
+
+ def ruby_major_minor
+ Gem.ruby_version.segments[0..1]
+ end
+
+ # versions 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")
+ Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1")
end
def revision_for(path)
@@ -544,7 +558,7 @@ module Spec
def require_rack
# need to hack, so we can require rack
old_gem_home = ENV["GEM_HOME"]
- ENV["GEM_HOME"] = Spec::Path.base_system_gems.to_s
+ ENV["GEM_HOME"] = Spec::Path.base_system_gem_path.to_s
require "rack"
ENV["GEM_HOME"] = old_gem_home
end
@@ -569,6 +583,11 @@ module Spec
port
end
+ def exit_status_for_signal(signal_number)
+ # For details see: https://en.wikipedia.org/wiki/Exit_status#Shell_and_scripts
+ 128 + signal_number
+ end
+
private
def git_root_dir?
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index bf4300edb2..78372302f1 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -16,20 +16,23 @@ 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 }
+ base = args[0] || Bundler::SpecSet.new([])
+ base.each {|ls| ls.source = default_source }
+ gem_version_promoter = args[1] || Bundler::GemVersionPromoter.new
+ originally_locked = args[2] || Bundler::SpecSet.new([])
+ unlock = args[3] || []
@deps.each do |d|
- source_requirements[d.name] = d.source = default_source
- @platforms.each do |p|
- deps << Bundler::DepProxy.get_proxy(d, p)
- end
+ name = d.name
+ source_requirements[name] = d.source = default_source
end
- 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)
+ packages = Bundler::Resolver::Base.new(source_requirements, @deps, base, @platforms, :locked_specs => originally_locked, :unlock => unlock)
+ Bundler::Resolver.new(packages, gem_version_promoter).start
+ end
+
+ def should_not_resolve
+ expect { resolve }.to raise_error(Bundler::GemNotFound)
end
def should_resolve_as(specs)
@@ -46,13 +49,6 @@ module Spec
end
end
- def should_conflict_on(names)
- got = resolve
- raise "The resolve succeeded with: #{got.map(&:full_name).sort.inspect}"
- rescue Bundler::VersionConflict => e
- expect(Array(names).sort).to eq(e.conflicts.sort)
- end
-
def gem(*args, &blk)
build_spec(*args, &blk).first
end
@@ -66,12 +62,11 @@ module Spec
def should_conservative_resolve_and_include(opts, unlock, specs)
# empty unlock means unlock all
opts = Array(opts)
- search = Bundler::GemVersionPromoter.new(@locked, unlock).tap do |s|
+ search = Bundler::GemVersionPromoter.new.tap do |s|
s.level = opts.first
s.strict = opts.include?(:strict)
- s.prerelease_specified = Hash[@deps.map {|d| [d.name, d.requirement.prerelease?] }]
end
- should_resolve_and_include specs, [@base, search]
+ should_resolve_and_include specs, [@base, search, @locked, unlock]
end
def an_awesome_index
@@ -126,7 +121,7 @@ module Spec
next if version == v("1.4.2.1") && platform != pl("x86-mswin32")
next if version == v("1.4.2") && platform == pl("x86-mswin32")
gem "nokogiri", version, platform do
- dep "weakling", ">= 0.0.3" if platform =~ pl("java")
+ dep "weakling", ">= 0.0.3" if platform =~ pl("java") # rubocop:disable Performance/RegexpMatch
end
end
end
diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index 180ad54c5b..ea7c784683 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -97,6 +97,18 @@ module Spec
end
end
+ RSpec::Matchers.define :take_less_than do |seconds|
+ match do |actual|
+ start_time = Time.now
+
+ actual.call
+
+ (Time.now - start_time).to_f < seconds
+ end
+
+ supports_block_expectations
+ end
+
define_compound_matcher :read_as, [exist] do |file_contents|
diffable
@@ -150,7 +162,7 @@ module Spec
end
if exitstatus == 65
actual_platform = out.split("\n").last
- next "#{name} was expected to be of platform #{platform} but was #{actual_platform}"
+ next "#{name} was expected to be of platform #{platform || "ruby"} but was #{actual_platform || "ruby"}"
end
if exitstatus == 66
actual_source = out.split("\n").last
@@ -178,7 +190,7 @@ module Spec
begin
require '#{name}'
- name_constant = '#{Spec::Builders.constantize(name)}'
+ name_constant = #{Spec::Builders.constantize(name)}
if #{version.nil?} || name_constant == '#{version}'
exit 64
else
@@ -208,10 +220,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)
@@ -225,13 +233,5 @@ module Spec
expect(Bundler::Plugin).not_to be_installed(name)
end
end
-
- def lockfile_should_be(expected)
- expect(bundled_app_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/path.rb b/spec/bundler/support/path.rb
index a98ef7c6cf..8b9c0e1290 100644
--- a/spec/bundler/support/path.rb
+++ b/spec/bundler/support/path.rb
@@ -30,7 +30,7 @@ module Spec
end
def test_gemfile
- @test_gemfile ||= source_root.join("tool/bundler/test_gems.rb")
+ @test_gemfile ||= tool_dir.join("test_gems.rb")
end
def rubocop_gemfile
@@ -42,7 +42,7 @@ module Spec
end
def dev_gemfile
- @dev_gemfile ||= git_root.join("dev_gems.rb")
+ @dev_gemfile ||= tool_dir.join("dev_gems.rb")
end
def bindir
@@ -71,10 +71,6 @@ module Spec
@spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec")
end
- def api_request_limit_hack_file
- spec_dir.join("support/api_request_limit_hax.rb")
- end
-
def man_dir
@man_dir ||= lib_dir.join("bundler/man")
end
@@ -118,6 +114,14 @@ module Spec
end
end
+ def default_cache_path(*path)
+ if Bundler.feature_flag.global_gem_cache?
+ home(".bundle/cache", *path)
+ else
+ default_bundle_path("cache/bundler", *path)
+ end
+ end
+
def bundled_app(*path)
root = tmp.join("bundled_app")
FileUtils.mkdir_p(root)
@@ -146,6 +150,10 @@ module Spec
bundled_app("Gemfile.lock")
end
+ def base_system_gem_path
+ scoped_gem_path(base_system_gems)
+ end
+
def base_system_gems
tmp.join("gems/base")
end
@@ -254,6 +262,10 @@ module Spec
end
end
+ def git_root
+ ruby_core? ? source_root : source_root.parent
+ end
+
private
def git_ls_files(glob)
@@ -274,20 +286,24 @@ module Spec
ruby_core? ? "man/bundle* man/gemfile*" : "lib/bundler/man/bundle*.1 lib/bundler/man/gemfile*.5"
end
- def git_root
- ruby_core? ? source_root : source_root.parent
- end
-
def ruby_core_tarball?
!git_root.join(".git").directory?
end
def rubocop_gemfile_basename
- source_root.join("tool/bundler/#{RUBY_VERSION.start_with?("2.3") ? "rubocop23_gems.rb" : "rubocop_gems.rb"}")
+ tool_dir.join("rubocop_gems.rb")
end
def standard_gemfile_basename
- source_root.join("tool/bundler/#{RUBY_VERSION.start_with?("2.3") ? "standard23_gems.rb" : "standard_gems.rb"}")
+ tool_dir.join("standard_gems.rb")
+ end
+
+ def tool_dir
+ ruby_core? ? source_root.join("tool/bundler") : source_root.join("../tool/bundler")
+ end
+
+ def templates_dir
+ lib_dir.join("bundler", "templates")
end
extend self
diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb
index 0cb7f7cd29..eca1b2e60d 100644
--- a/spec/bundler/support/platforms.rb
+++ b/spec/bundler/support/platforms.rb
@@ -21,31 +21,35 @@ module Spec
end
def linux
- Gem::Platform.new(["x86", "linux", nil])
+ Gem::Platform.new("x86_64-linux")
end
- def mswin
+ def x86_mswin32
Gem::Platform.new(["x86", "mswin32", nil])
end
- def mingw
+ def x64_mswin64
+ Gem::Platform.new(["x64", "mswin64", nil])
+ end
+
+ def x86_mingw32
Gem::Platform.new(["x86", "mingw32", nil])
end
- def x64_mingw
+ def x64_mingw32
Gem::Platform.new(["x64", "mingw32", nil])
end
- def all_platforms
- [rb, java, linux, mswin, mingw, x64_mingw]
+ def x64_mingw_ucrt
+ Gem::Platform.new(["x64", "mingw", "ucrt"])
end
- def local
- generic_local_platform
+ def windows_platforms
+ [x86_mswin32, x64_mswin64, x86_mingw32, x64_mingw32, x64_mingw_ucrt]
end
- def specific_local_platform
- Bundler.local_platform
+ def all_platforms
+ [rb, java, linux, windows_platforms].flatten
end
def not_local
@@ -55,13 +59,15 @@ module Spec
def local_tag
if RUBY_PLATFORM == "java"
:jruby
+ elsif ["x64-mingw32", "x64-mingw-ucrt"].include?(RUBY_PLATFORM)
+ :windows
else
:ruby
end
end
def not_local_tag
- [:ruby, :jruby].find {|tag| tag != local_tag }
+ [:jruby, :windows, :ruby].find {|tag| tag != local_tag }
end
def local_ruby_engine
@@ -69,12 +75,12 @@ module Spec
end
def local_engine_version
- RUBY_ENGINE_VERSION
+ RUBY_ENGINE == "ruby" ? Gem.ruby_version : RUBY_ENGINE_VERSION
end
def not_local_engine_version
case not_local_tag
- when :ruby
+ when :ruby, :windows
not_local_ruby_version
when :jruby
"1.6.1"
@@ -89,12 +95,12 @@ module Spec
9999
end
- def lockfile_platforms
- local_platforms.map(&:to_s).sort.join("\n ")
+ def lockfile_platforms(*extra)
+ formatted_lockfile_platforms(local_platform, *extra)
end
- def local_platforms
- [specific_local_platform]
+ def formatted_lockfile_platforms(*platforms)
+ platforms.map(&:to_s).sort.join("\n ")
end
end
end
diff --git a/spec/bundler/support/rubygems_ext.rb b/spec/bundler/support/rubygems_ext.rb
index 9389543a0f..4553c0606e 100644
--- a/spec/bundler/support/rubygems_ext.rb
+++ b/spec/bundler/support/rubygems_ext.rb
@@ -18,6 +18,12 @@ module Spec
gem_load_and_activate(gem_name, bin_container)
end
+ def gem_load_and_possibly_install(gem_name, bin_container)
+ require_relative "switch_rubygems"
+
+ gem_load_activate_and_possibly_install(gem_name, bin_container)
+ end
+
def gem_require(gem_name)
gem_activate(gem_name)
require gem_name
@@ -59,15 +65,13 @@ module Spec
Gem.clear_paths
ENV["BUNDLE_PATH"] = nil
- ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gems.to_s
+ ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gem_path.to_s
ENV["PATH"] = [Path.system_gem_path.join("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
ENV["PATH"] = [Path.bindir, ENV["PATH"]].join(File::PATH_SEPARATOR) if Path.ruby_core?
end
def install_test_deps
- setup_test_paths
-
- install_gems(test_gemfile)
+ install_gems(test_gemfile, Path.base_system_gems.to_s)
install_gems(rubocop_gemfile, Path.rubocop_gems.to_s)
install_gems(standard_gemfile, Path.standard_gems.to_s)
end
@@ -101,15 +105,29 @@ module Spec
abort "We couldn't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`"
end
+ def gem_load_activate_and_possibly_install(gem_name, bin_container)
+ gem_activate_and_possibly_install(gem_name)
+ load Gem.bin_path(gem_name, bin_container)
+ end
+
+ def gem_activate_and_possibly_install(gem_name)
+ gem_activate(gem_name)
+ rescue Gem::LoadError => e
+ Gem.install(gem_name, e.requirement)
+ retry
+ end
+
def gem_activate(gem_name)
require "bundler"
- gem_requirement = Bundler::LockfileParser.new(File.read(dev_lockfile)).dependencies[gem_name]&.requirement
+ gem_requirement = Bundler::LockfileParser.new(File.read(dev_lockfile)).specs.find {|spec| spec.name == gem_name }.version
gem gem_name, gem_requirement
end
def install_gems(gemfile, path = nil)
old_gemfile = ENV["BUNDLE_GEMFILE"]
+ old_orig_gemfile = ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"]
ENV["BUNDLE_GEMFILE"] = gemfile.to_s
+ ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil
if path
old_path = ENV["BUNDLE_PATH"]
@@ -119,8 +137,8 @@ module Spec
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?
+ puts `#{Gem.ruby} #{File.expand_path("support/bundle.rb", Path.spec_dir)} install --verbose`
+ raise unless $?.success?
ensure
if path
ENV["BUNDLE_PATH"] = old_path
@@ -128,6 +146,7 @@ module Spec
ENV["BUNDLE_PATH__SYSTEM"] = old_path__system
end
+ ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = old_orig_gemfile
ENV["BUNDLE_GEMFILE"] = old_gemfile
end
diff --git a/spec/bundler/support/rubygems_version_manager.rb b/spec/bundler/support/rubygems_version_manager.rb
index c2e5a5f484..5653601ae8 100644
--- a/spec/bundler/support/rubygems_version_manager.rb
+++ b/spec/bundler/support/rubygems_version_manager.rb
@@ -24,12 +24,6 @@ class RubygemsVersionManager
def assert_system_features_not_loaded!
at_exit do
- errors = if $?.nil?
- ""
- else
- all_commands_output
- end
-
rubylibdir = RbConfig::CONFIG["rubylibdir"]
rubygems_path = rubylibdir + "/rubygems"
@@ -43,11 +37,11 @@ class RubygemsVersionManager
(loaded_feature.start_with?(bundler_path) && !bundler_exemptions.any? {|bundler_exemption| loaded_feature.start_with?(bundler_exemption) })
end
- if bad_loaded_features.any?
- errors += "the following features were incorrectly loaded:\n#{bad_loaded_features.join("\n")}"
+ errors = if bad_loaded_features.any?
+ all_commands_output + "the following features were incorrectly loaded:\n#{bad_loaded_features.join("\n")}"
end
- raise errors unless errors.empty?
+ raise errors if errors
end
end
@@ -119,7 +113,7 @@ class RubygemsVersionManager
end
def resolve_target_tag
- return "v#{@source}" if @source.match(/^\d/)
+ return "v#{@source}" if @source.match?(/^\d/)
@source
end
diff --git a/spec/bundler/support/sudo.rb b/spec/bundler/support/sudo.rb
deleted file mode 100644
index 04e9443945..0000000000
--- a/spec/bundler/support/sudo.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Spec
- module Sudo
- def self.present?
- @which_sudo ||= Bundler.which("sudo")
- end
-
- def sudo(cmd)
- raise "sudo not present" unless Sudo.present?
- sys_exec("sudo #{cmd}")
- end
-
- def chown_system_gems_to_root
- sudo "chown -R root #{system_gem_path}"
- end
- end
-end
diff --git a/spec/bundler/update/gems/fund_spec.rb b/spec/bundler/update/gems/fund_spec.rb
index 0dfe63d36d..d80f4018f3 100644
--- a/spec/bundler/update/gems/fund_spec.rb
+++ b/spec/bundler/update/gems/fund_spec.rb
@@ -5,20 +5,20 @@ RSpec.describe "bundle update" 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",
+ "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",
+ "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",
+ "funding_uri" => "https://example.com/has_funding/funding",
}
end
end
diff --git a/spec/bundler/update/git_spec.rb b/spec/bundler/update/git_spec.rb
index 26ad1b45d3..59e3d2f5fb 100644
--- a/spec/bundler/update/git_spec.rb
+++ b/spec/bundler/update/git_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe "bundle update" do
end
G
- update_git "foo", :branch => "omg" do |s|
+ update_git "foo" do |s|
s.write "lib/foo.rb", "FOO = '1.1'"
end
@@ -48,7 +48,7 @@ RSpec.describe "bundle update" do
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
@@ -57,7 +57,7 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems "foo 1.1"
end
- it "floats on master when updating all gems that are pinned to the source even if you have child dependencies" do
+ it "floats on main when updating all gems that are pinned to the source even if you have child dependencies" do
build_git "foo", :path => lib_path("foo")
build_gem "bar", :to_bundle => true do |s|
s.add_dependency "foo"
@@ -103,7 +103,7 @@ RSpec.describe "bundle update" do
build_git "foo"
@remote = build_git("bar", :bare => true)
update_git "foo", :remote => file_uri_for(@remote.path)
- update_git "foo", :push => "master"
+ update_git "foo", :push => "main"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -120,10 +120,14 @@ RSpec.describe "bundle update" do
G
bundle "update", :all => true
+ expect(err).to be_empty
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'"
@@ -211,7 +215,7 @@ RSpec.describe "bundle update" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{file_uri_for(lib_path("rack-0.8"))}", :branch => "master"
+ gem "rack", :git => "#{file_uri_for(lib_path("rack-0.8"))}", :branch => "main"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -230,7 +234,7 @@ RSpec.describe "bundle update" do
update_git "rails", "3.0", :path => lib_path("rails"), :gemspec => true
bundle "update", :all => true
- expect(out).to include("Using rails 3.0 (was 2.3.2) from #{file_uri_for(lib_path("rails"))} (at 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 main@#{revision_for(lib_path("rails"))[0..6]})")
end
end
@@ -293,43 +297,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'"
@@ -337,11 +305,11 @@ RSpec.describe "bundle update" do
s.write "foo.gemspec", spec_lines.join("\n")
end
- ref = @git.ref_for "master"
+ ref = @git.ref_for "main"
bundle "update --source bar"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{@git.path}
revision: #{ref}
diff --git a/spec/default.mspec b/spec/default.mspec
index 8791058f95..0dba98306c 100644
--- a/spec/default.mspec
+++ b/spec/default.mspec
@@ -7,24 +7,24 @@ require "./rbconfig" unless defined?(RbConfig)
load File.dirname(__FILE__) + '/ruby/default.mspec'
OBJDIR = File.expand_path("spec/ruby/optional/capi/ext")
class MSpecScript
+ @testing_ruby = true
+
builddir = Dir.pwd
srcdir = ENV['SRCDIR']
- if !srcdir and File.exist?("#{builddir}/Makefile") then
- File.open("#{builddir}/Makefile", "r:US-ASCII") {|f|
- f.read[/^\s*srcdir\s*=\s*(.+)/i] and srcdir = $1
- }
- end
- srcdir = File.expand_path(srcdir)
+ srcdir ||= File.read("Makefile", encoding: "US-ASCII")[/^\s*srcdir\s*=\s*(.+)/i, 1] rescue nil
config = RbConfig::CONFIG
# The default implementation to run the specs.
set :target, File.join(builddir, "miniruby#{config['exeext']}")
set :prefix, File.expand_path('ruby', File.dirname(__FILE__))
- set :flags, %W[
- -I#{srcdir}/lib
- #{srcdir}/tool/runruby.rb --archdir=#{Dir.pwd} --extout=#{config['EXTOUT']}
- --
- ]
+ if srcdir
+ srcdir = File.expand_path(srcdir)
+ set :flags, %W[
+ -I#{srcdir}/lib
+ #{srcdir}/tool/runruby.rb --archdir=#{builddir} --extout=#{config['EXTOUT']}
+ --
+ ]
+ end
end
module MSpecScript::JobServer
diff --git a/spec/mspec/bin/mspec b/spec/mspec/bin/mspec
index f833257bb0..5bd753c06d 100755
--- a/spec/mspec/bin/mspec
+++ b/spec/mspec/bin/mspec
@@ -4,4 +4,4 @@ $:.unshift File.expand_path('../../lib', __FILE__)
require 'mspec/commands/mspec'
-MSpecMain.main
+MSpecMain.main(false)
diff --git a/spec/mspec/lib/mspec/commands/mkspec.rb b/spec/mspec/lib/mspec/commands/mkspec.rb
index d10cc35d18..a31cb2191c 100755
--- a/spec/mspec/lib/mspec/commands/mkspec.rb
+++ b/spec/mspec/lib/mspec/commands/mkspec.rb
@@ -95,7 +95,9 @@ class MkSpec
def write_spec(file, meth, exists)
if exists
- out = `#{ruby} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e '#{meth}' #{file}`
+ command = "#{RbConfig.ruby} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e '#{meth}' #{file}"
+ puts "$ #{command}" if $DEBUG
+ out = `#{command}`
return if out.include?(meth)
end
@@ -133,18 +135,6 @@ EOS
end
end
- ##
- # Determine and return the path of the ruby executable.
-
- def ruby
- ruby = File.join(RbConfig::CONFIG['bindir'],
- RbConfig::CONFIG['ruby_install_name'])
-
- ruby.gsub! File::SEPARATOR, File::ALT_SEPARATOR if File::ALT_SEPARATOR
-
- return ruby
- end
-
def self.main
ENV['MSPEC_RUNNER'] = '1'
diff --git a/spec/mspec/lib/mspec/commands/mspec.rb b/spec/mspec/lib/mspec/commands/mspec.rb
index 9d82949ff1..9c38cebcda 100755
--- a/spec/mspec/lib/mspec/commands/mspec.rb
+++ b/spec/mspec/lib/mspec/commands/mspec.rb
@@ -25,6 +25,7 @@ class MSpecMain < MSpecScript
config[:command] = argv.shift if ["ci", "run", "tag"].include?(argv[0])
options = MSpecOptions.new "mspec [COMMAND] [options] (FILE|DIRECTORY|GLOB)+", 30, config
+ @options = options
options.doc " The mspec command sets up and invokes the sub-commands"
options.doc " (see below) to enable, for instance, running the specs"
@@ -110,8 +111,9 @@ class MSpecMain < MSpecScript
if config[:multi]
exit multi_exec(argv)
else
- $stderr.puts "$ #{argv.join(' ')}"
- $stderr.flush
+ log = config[:options].include?('--error-output') ? $stdout : $stderr
+ log.puts "$ #{argv.join(' ')}"
+ log.flush
exec(*argv, close_others: false)
end
end
diff --git a/spec/mspec/lib/mspec/expectations/expectations.rb b/spec/mspec/lib/mspec/expectations/expectations.rb
index 8d01dc22ab..09852ab557 100644
--- a/spec/mspec/lib/mspec/expectations/expectations.rb
+++ b/spec/mspec/lib/mspec/expectations/expectations.rb
@@ -32,4 +32,8 @@ class SpecExpectation
result_to_s = MSpec.format(result)
raise SpecExpectationNotMetError, "Expected #{receiver_to_s}#{predicate_to_s}#{args_to_s}\n#{expectation} but was #{result_to_s}"
end
+
+ def self.fail_single_arg_predicate(receiver, predicate, arg, result, expectation)
+ fail_predicate(receiver, predicate, [arg], nil, result, expectation)
+ end
end
diff --git a/spec/mspec/lib/mspec/guards/platform.rb b/spec/mspec/lib/mspec/guards/platform.rb
index 2d5c2de6b6..e87b08a4c1 100644
--- a/spec/mspec/lib/mspec/guards/platform.rb
+++ b/spec/mspec/lib/mspec/guards/platform.rb
@@ -41,6 +41,10 @@ class PlatformGuard < SpecGuard
os?(:windows)
end
+ def self.wasi?
+ os?(:wasi)
+ end
+
def self.wsl?
if defined?(@wsl_p)
@wsl_p
diff --git a/spec/mspec/lib/mspec/guards/superuser.rb b/spec/mspec/lib/mspec/guards/superuser.rb
index e92ea7e862..24daf9b26c 100644
--- a/spec/mspec/lib/mspec/guards/superuser.rb
+++ b/spec/mspec/lib/mspec/guards/superuser.rb
@@ -6,10 +6,20 @@ class SuperUserGuard < SpecGuard
end
end
+class RealSuperUserGuard < SpecGuard
+ def match?
+ Process.uid == 0
+ end
+end
+
def as_superuser(&block)
SuperUserGuard.new.run_if(:as_superuser, &block)
end
+def as_real_superuser(&block)
+ RealSuperUserGuard.new.run_if(:as_real_superuser, &block)
+end
+
def as_user(&block)
SuperUserGuard.new.run_unless(:as_user, &block)
end
diff --git a/spec/mspec/lib/mspec/guards/version.rb b/spec/mspec/lib/mspec/guards/version.rb
index 20f8c06d38..f5ea1988ae 100644
--- a/spec/mspec/lib/mspec/guards/version.rb
+++ b/spec/mspec/lib/mspec/guards/version.rb
@@ -33,6 +33,30 @@ class VersionGuard < SpecGuard
@version >= @requirement
end
end
+
+ @kernel_version = nil
+ def self.kernel_version
+ if @kernel_version
+ @kernel_version
+ else
+ if v = RUBY_PLATFORM[/darwin(\d+)/, 1] # build time version
+ uname = v
+ else
+ begin
+ require 'etc'
+ etc = true
+ rescue LoadError
+ etc = false
+ end
+ if etc and Etc.respond_to?(:uname)
+ uname = Etc.uname.fetch(:release)
+ else
+ uname = `uname -r`.chomp
+ end
+ end
+ @kernel_version = uname
+ end
+ end
end
def version_is(base_version, requirement, &block)
@@ -42,3 +66,7 @@ end
def ruby_version_is(requirement, &block)
VersionGuard.new(VersionGuard::FULL_RUBY_VERSION, requirement).run_if(:ruby_version_is, &block)
end
+
+def kernel_version_is(requirement, &block)
+ VersionGuard.new(VersionGuard.kernel_version, requirement).run_if(:kernel_version_is, &block)
+end
diff --git a/spec/mspec/lib/mspec/helpers/datetime.rb b/spec/mspec/lib/mspec/helpers/datetime.rb
index 3a40cc0902..84ac86b686 100644
--- a/spec/mspec/lib/mspec/helpers/datetime.rb
+++ b/spec/mspec/lib/mspec/helpers/datetime.rb
@@ -25,6 +25,7 @@ def new_datetime(opts = {})
end
def with_timezone(name, offset = nil, daylight_saving_zone = "")
+ skip "WASI doesn't have TZ concept" if PlatformGuard.wasi?
zone = name.dup
if offset
diff --git a/spec/mspec/lib/mspec/helpers/numeric.rb b/spec/mspec/lib/mspec/helpers/numeric.rb
index db1fde64d8..c1ed81a233 100644
--- a/spec/mspec/lib/mspec/helpers/numeric.rb
+++ b/spec/mspec/lib/mspec/helpers/numeric.rb
@@ -9,7 +9,9 @@ def infinity_value
end
def bignum_value(plus = 0)
- 0x8000_0000_0000_0000 + plus
+ # Must be >= fixnum_max + 2, so -bignum_value is < fixnum_min
+ # A fixed value has the advantage to be the same numeric value for all Rubies and is much easier to spec
+ (2**64) + plus
end
def max_long
diff --git a/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/spec/mspec/lib/mspec/helpers/ruby_exe.rb
index c62c19f3aa..7fde001cda 100644
--- a/spec/mspec/lib/mspec/helpers/ruby_exe.rb
+++ b/spec/mspec/lib/mspec/helpers/ruby_exe.rb
@@ -112,6 +112,8 @@ unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE
end
def ruby_exe(code = :not_given, opts = {})
+ skip "WASI doesn't provide subprocess" if PlatformGuard.wasi?
+
if opts[:dir]
raise "ruby_exe(..., dir: dir) is no longer supported, use Dir.chdir"
end
@@ -135,16 +137,27 @@ def ruby_exe(code = :not_given, opts = {})
code = tmpfile
end
- expected_exit_status = opts.fetch(:exit_status, 0)
+ expected_status = opts.fetch(:exit_status, 0)
begin
platform_is_not :opal do
command = ruby_cmd(code, opts)
output = `#{command}`
-
- last_status = Process.last_status
- if last_status.exitstatus != expected_exit_status
- raise "Expected exit status is #{expected_exit_status.inspect} but actual is #{last_status.exitstatus.inspect} for command ruby_exe(#{command.inspect})"
+ status = Process.last_status
+
+ exit_status = if status.exited?
+ status.exitstatus
+ elsif status.signaled?
+ signame = Signal.signame status.termsig
+ raise "No signal name?" unless signame
+ :"SIG#{signame}"
+ else
+ raise SpecExpectationNotMetError, "#{exit_status.inspect} is neither exited? nor signaled?"
+ end
+ if exit_status != expected_status
+ formatted_output = output.lines.map { |line| " #{line}" }.join
+ raise SpecExpectationNotMetError,
+ "Expected exit status is #{expected_status.inspect} but actual is #{exit_status.inspect} for command ruby_exe(#{command.inspect})\nOutput:\n#{formatted_output}"
end
output
diff --git a/spec/mspec/lib/mspec/matchers/base.rb b/spec/mspec/lib/mspec/matchers/base.rb
index 94d3b71e55..d9d7f6fec0 100644
--- a/spec/mspec/lib/mspec/matchers/base.rb
+++ b/spec/mspec/lib/mspec/matchers/base.rb
@@ -16,15 +16,24 @@ class SpecPositiveOperatorMatcher < BasicObject
end
def ==(expected)
- method_missing(:==, expected)
+ result = @actual == expected
+ unless result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :==, expected, result, "to be truthy")
+ end
end
def !=(expected)
- method_missing(:!=, expected)
+ result = @actual != expected
+ unless result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :!=, expected, result, "to be truthy")
+ end
end
def equal?(expected)
- method_missing(:equal?, expected)
+ result = @actual.equal?(expected)
+ unless result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :equal?, expected, result, "to be truthy")
+ end
end
def method_missing(name, *args, &block)
@@ -41,15 +50,24 @@ class SpecNegativeOperatorMatcher < BasicObject
end
def ==(expected)
- method_missing(:==, expected)
+ result = @actual == expected
+ if result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :==, expected, result, "to be falsy")
+ end
end
def !=(expected)
- method_missing(:!=, expected)
+ result = @actual != expected
+ if result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :!=, expected, result, "to be falsy")
+ end
end
def equal?(expected)
- method_missing(:equal?, expected)
+ result = @actual.equal?(expected)
+ if result
+ ::SpecExpectation.fail_single_arg_predicate(@actual, :equal?, expected, result, "to be falsy")
+ end
end
def method_missing(name, *args, &block)
diff --git a/spec/mspec/lib/mspec/matchers/output.rb b/spec/mspec/lib/mspec/matchers/output.rb
index 20721df743..5bb5d55027 100644
--- a/spec/mspec/lib/mspec/matchers/output.rb
+++ b/spec/mspec/lib/mspec/matchers/output.rb
@@ -42,12 +42,12 @@ class OutputMatcher
expected_out = "\n"
actual_out = "\n"
unless @out.nil?
- expected_out += " $stdout: #{@out.inspect}\n"
- actual_out += " $stdout: #{@stdout.inspect}\n"
+ expected_out += " $stdout: #{MSpec.format(@out)}\n"
+ actual_out += " $stdout: #{MSpec.format(@stdout.to_s)}\n"
end
unless @err.nil?
- expected_out += " $stderr: #{@err.inspect}\n"
- actual_out += " $stderr: #{@stderr.inspect}\n"
+ expected_out += " $stderr: #{MSpec.format(@err)}\n"
+ actual_out += " $stderr: #{MSpec.format(@stderr.to_s)}\n"
end
["Expected:#{expected_out}", " got:#{actual_out}"]
end
diff --git a/spec/mspec/lib/mspec/matchers/raise_error.rb b/spec/mspec/lib/mspec/matchers/raise_error.rb
index 0ee8953519..54378bb34c 100644
--- a/spec/mspec/lib/mspec/matchers/raise_error.rb
+++ b/spec/mspec/lib/mspec/matchers/raise_error.rb
@@ -1,4 +1,6 @@
class RaiseErrorMatcher
+ FAILURE_MESSAGE_FOR_EXCEPTION = {}.compare_by_identity
+
attr_writer :block
def initialize(exception, message, &block)
@@ -15,7 +17,7 @@ class RaiseErrorMatcher
def matches?(proc)
@result = proc.call
return false
- rescue Exception => actual
+ rescue Object => actual
@actual = actual
if matching_exception?(actual)
@@ -23,7 +25,7 @@ class RaiseErrorMatcher
@block[actual] if @block
return true
else
- actual.instance_variable_set(:@mspec_raise_error_message, failure_message)
+ FAILURE_MESSAGE_FOR_EXCEPTION[actual] = failure_message
raise actual
end
end
diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
index 596b120d9f..69181b71d3 100644
--- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
+++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
@@ -173,7 +173,8 @@ class LeakChecker
def find_threads
Thread.list.find_all {|t|
- t != Thread.current && t.alive?
+ t != Thread.current && t.alive? &&
+ !(t.thread_variable?(:"\0__detached_thread__") && t.thread_variable_get(:"\0__detached_thread__"))
}
end
diff --git a/spec/mspec/lib/mspec/runner/actions/timeout.rb b/spec/mspec/lib/mspec/runner/actions/timeout.rb
index c85bf49ad3..543b7366d7 100644
--- a/spec/mspec/lib/mspec/runner/actions/timeout.rb
+++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb
@@ -8,6 +8,7 @@ class TimeoutAction
def register
MSpec.register :start, self
MSpec.register :before, self
+ MSpec.register :after, self
MSpec.register :finish, self
end
@@ -35,9 +36,16 @@ class TimeoutAction
if @queue.empty?
elapsed = now - @started
if elapsed > @timeout
- STDERR.puts "\n#{@current_state.description}"
+ if @current_state
+ STDERR.puts "\nExample took longer than the configured timeout of #{@timeout}s:"
+ STDERR.puts "#{@current_state.description}"
+ else
+ STDERR.puts "\nSome code outside an example took longer than the configured timeout of #{@timeout}s"
+ end
STDERR.flush
- abort "Example took longer than the configured timeout of #{@timeout}s"
+
+ show_backtraces
+ exit 2
end
end
end
@@ -53,8 +61,33 @@ class TimeoutAction
end
end
+ def after(state = nil)
+ @queue << -> do
+ @current_state = nil
+ end
+ end
+
def finish
@thread.kill
@thread.join
end
+
+ private def show_backtraces
+ if RUBY_ENGINE == 'truffleruby'
+ STDERR.puts 'Java stacktraces:'
+ Process.kill :SIGQUIT, Process.pid
+ sleep 1
+ end
+
+ STDERR.puts "\nRuby backtraces:"
+ if defined?(Truffle::Debug.show_backtraces)
+ Truffle::Debug.show_backtraces
+ else
+ Thread.list.each do |thread|
+ unless thread == Thread.current
+ STDERR.puts thread.inspect, thread.backtrace, ''
+ end
+ end
+ end
+ end
end
diff --git a/spec/mspec/lib/mspec/runner/context.rb b/spec/mspec/lib/mspec/runner/context.rb
index 62483590bb..bcd83b2465 100644
--- a/spec/mspec/lib/mspec/runner/context.rb
+++ b/spec/mspec/lib/mspec/runner/context.rb
@@ -210,6 +210,7 @@ class ContextState
MSpec.clear_expectations
if example
passed = protect nil, example
+ passed = protect nil, -> { MSpec.actions :passed, state, example } if passed
MSpec.actions :example, state, example
protect nil, EXPECTATION_MISSING if !MSpec.expectation? and passed
end
diff --git a/spec/mspec/lib/mspec/runner/exception.rb b/spec/mspec/lib/mspec/runner/exception.rb
index e07f02f684..23375733e6 100644
--- a/spec/mspec/lib/mspec/runner/exception.rb
+++ b/spec/mspec/lib/mspec/runner/exception.rb
@@ -29,7 +29,7 @@ class ExceptionState
if @failure
message
- elsif raise_error_message = @exception.instance_variable_get(:@mspec_raise_error_message)
+ elsif raise_error_message = RaiseErrorMatcher::FAILURE_MESSAGE_FOR_EXCEPTION[@exception]
raise_error_message.join("\n")
else
"#{@exception.class}: #{message}"
diff --git a/spec/mspec/lib/mspec/runner/formatters/base.rb b/spec/mspec/lib/mspec/runner/formatters/base.rb
index 6c075c4d0a..54a83c9c32 100644
--- a/spec/mspec/lib/mspec/runner/formatters/base.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/base.rb
@@ -1,6 +1,7 @@
require 'mspec/expectations/expectations'
require 'mspec/runner/actions/timer'
require 'mspec/runner/actions/tally'
+require 'mspec/utils/options'
if ENV['CHECK_LEAKS']
require 'mspec/runner/actions/leakchecker'
@@ -18,10 +19,17 @@ class BaseFormatter
@count = 0 # For subclasses
- if out.nil?
+ if out
+ @out = File.open out, "w"
+ else
@out = $stdout
+ end
+
+ err = MSpecOptions.latest && MSpecOptions.latest.config[:error_output]
+ if err
+ @err = (err == 'stderr') ? $stderr : File.open(err, "w")
else
- @out = File.open out, "w"
+ @err = @out
end
end
@@ -105,6 +113,14 @@ class BaseFormatter
# evaluating the examples.
def finish
print "\n"
+
+ if MSpecOptions.latest && MSpecOptions.latest.config[:print_skips]
+ print "\nSkips:\n" unless MSpec.skips.empty?
+ MSpec.skips.each do |skip, block|
+ print "#{skip.message} in #{(block.source_location || ['?']).join(':')}\n"
+ end
+ end
+
count = 0
@exceptions.each do |exc|
count += 1
@@ -115,9 +131,9 @@ class BaseFormatter
def print_exception(exc, count)
outcome = exc.failure? ? "FAILED" : "ERROR"
- print "\n#{count})\n#{exc.description} #{outcome}\n"
- print exc.message, "\n"
- print exc.backtrace, "\n"
+ @err.print "\n#{count})\n#{exc.description} #{outcome}\n"
+ @err.print exc.message, "\n"
+ @err.print exc.backtrace, "\n"
end
# A convenience method to allow printing to different outputs.
diff --git a/spec/mspec/lib/mspec/runner/mspec.rb b/spec/mspec/lib/mspec/runner/mspec.rb
index 8331086196..889e085175 100644
--- a/spec/mspec/lib/mspec/runner/mspec.rb
+++ b/spec/mspec/lib/mspec/runner/mspec.rb
@@ -26,6 +26,7 @@ module MSpec
@unload = nil
@tagged = nil
@current = nil
+ @passed = nil
@example = nil
@modes = []
@shared = {}
@@ -36,9 +37,10 @@ module MSpec
@repeat = 1
@expectation = nil
@expectations = false
+ @skips = []
class << self
- attr_reader :file, :include, :exclude
+ attr_reader :file, :include, :exclude, :skips
attr_writer :repeat, :randomize
attr_accessor :formatter
end
@@ -116,8 +118,9 @@ module MSpec
rescue SystemExit => e
raise e
rescue SkippedSpecError => e
+ @skips << [e, block]
return false
- rescue Exception => exc
+ rescue Object => exc
register_exit 1
actions :exception, ExceptionState.new(current && current.state, location, exc)
return false
@@ -241,6 +244,7 @@ module MSpec
# :before before a single spec is run
# :add while a describe block is adding examples to run later
# :expectation before a 'should', 'should_receive', etc.
+ # :passed after an example block is run and passes, passed the block, run before :example action
# :example after an example block is run, passed the block
# :exception after an exception is rescued
# :after after a single spec is run
diff --git a/spec/mspec/lib/mspec/runner/shared.rb b/spec/mspec/lib/mspec/runner/shared.rb
index 1d68365474..283711c1d7 100644
--- a/spec/mspec/lib/mspec/runner/shared.rb
+++ b/spec/mspec/lib/mspec/runner/shared.rb
@@ -1,10 +1,14 @@
require 'mspec/runner/mspec'
def it_behaves_like(desc, meth, obj = nil)
- send :before, :all do
+ before :all do
@method = meth
@object = obj
end
+ after :all do
+ @method = nil
+ @object = nil
+ end
- send :it_should_behave_like, desc.to_s
+ it_should_behave_like desc.to_s
end
diff --git a/spec/mspec/lib/mspec/utils/name_map.rb b/spec/mspec/lib/mspec/utils/name_map.rb
index a389b9d1de..bf70e651a2 100644
--- a/spec/mspec/lib/mspec/utils/name_map.rb
+++ b/spec/mspec/lib/mspec/utils/name_map.rb
@@ -51,6 +51,10 @@ class NameMap
SpecVersion
]
+ ALWAYS_PRIVATE = %w[
+ initialize initialize_copy initialize_clone initialize_dup respond_to_missing?
+ ].map(&:to_sym)
+
def initialize(filter = false)
@seen = {}
@filter = filter
@@ -86,7 +90,8 @@ class NameMap
hash["#{name}."] = ms.sort unless ms.empty?
ms = m.public_instance_methods(false) +
- m.protected_instance_methods(false)
+ m.protected_instance_methods(false) +
+ (m.private_instance_methods(false) & ALWAYS_PRIVATE)
ms.map! { |x| x.to_s }
hash["#{name}#"] = ms.sort unless ms.empty?
diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb
index bef1dbdd2e..612caf6771 100644
--- a/spec/mspec/lib/mspec/utils/options.rb
+++ b/spec/mspec/lib/mspec/utils/options.rb
@@ -32,6 +32,10 @@ class MSpecOptions
# Raised if an unrecognized option is encountered.
class ParseError < Exception; end
+ class << self
+ attr_accessor :latest
+ end
+
attr_accessor :config, :banner, :width, :options
def initialize(banner = "", width = 30, config = nil)
@@ -46,7 +50,7 @@ class MSpecOptions
@extra << x
}
- yield self if block_given?
+ MSpecOptions.latest = self
end
# Registers an option. Acceptable formats for arguments are:
@@ -311,6 +315,11 @@ class MSpecOptions
"Write formatter output to FILE") do |f|
config[:output] = f
end
+
+ on("--error-output", "FILE",
+ "Write error output of failing specs to FILE, or $stderr if value is 'stderr'.") do |f|
+ config[:error_output] = f
+ end
end
def filters
@@ -414,6 +423,10 @@ class MSpecOptions
end
MSpec.register :load, obj
end
+
+ on("--print-skips", "Print skips") do
+ config[:print_skips] = true
+ end
end
def interrupt
diff --git a/spec/mspec/lib/mspec/utils/script.rb b/spec/mspec/lib/mspec/utils/script.rb
index a77476ee2e..e86beaab86 100644
--- a/spec/mspec/lib/mspec/utils/script.rb
+++ b/spec/mspec/lib/mspec/utils/script.rb
@@ -37,6 +37,17 @@ class MSpecScript
config[key]
end
+ class << self
+ attr_accessor :child_process
+ end
+
+ # True if the current process is the one going to run the specs with `MSpec.process`.
+ # False for e.g. `mspec` which exec's to `mspec-run`.
+ # This is useful in .mspec config files.
+ def self.child_process?
+ MSpecScript.child_process
+ end
+
def initialize
check_version!
@@ -267,10 +278,11 @@ class MSpecScript
# Instantiates an instance and calls the series of methods to
# invoke the script.
- def self.main
+ def self.main(child_process = true)
+ MSpecScript.child_process = child_process
+
script = new
script.load_default
- script.try_load '~/.mspecrc'
script.options
script.signals
script.register
diff --git a/spec/mspec/lib/mspec/utils/warnings.rb b/spec/mspec/lib/mspec/utils/warnings.rb
index c770d609f3..0d3d36fada 100644
--- a/spec/mspec/lib/mspec/utils/warnings.rb
+++ b/spec/mspec/lib/mspec/utils/warnings.rb
@@ -10,7 +10,7 @@ if Object.const_defined?(:Warning) and Warning.respond_to?(:[]=)
end
if Object.const_defined?(:Warning) and Warning.respond_to?(:warn)
- def Warning.warn(message)
+ def Warning.warn(message, category: nil)
# Suppress any warning inside the method to prevent recursion
verbose = $VERBOSE
$VERBOSE = nil
diff --git a/spec/mspec/spec/commands/mkspec_spec.rb b/spec/mspec/spec/commands/mkspec_spec.rb
index 825add7212..32262723de 100644
--- a/spec/mspec/spec/commands/mkspec_spec.rb
+++ b/spec/mspec/spec/commands/mkspec_spec.rb
@@ -194,7 +194,7 @@ RSpec.describe MkSpec, "#write_spec" do
end
it "checks if specs exist for the method if the spec file exists" do
- name = Regexp.escape(@script.ruby)
+ name = Regexp.escape(RbConfig.ruby)
expect(@script).to receive(:`).with(
%r"#{name} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e 'Object#inspect' spec/core/tcejbo/inspect_spec.rb")
@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)
diff --git a/spec/mspec/spec/helpers/numeric_spec.rb b/spec/mspec/spec/helpers/numeric_spec.rb
index e65f3e8610..64495b7276 100644
--- a/spec/mspec/spec/helpers/numeric_spec.rb
+++ b/spec/mspec/spec/helpers/numeric_spec.rb
@@ -4,11 +4,17 @@ require 'mspec/helpers'
RSpec.describe Object, "#bignum_value" do
it "returns a value that is an instance of Bignum on any platform" do
- expect(bignum_value).to eq(0x8000_0000_0000_0000)
+ expect(bignum_value).to be > fixnum_max
end
it "returns the default value incremented by the argument" do
- expect(bignum_value(42)).to eq(0x8000_0000_0000_002a)
+ expect(bignum_value(42)).to eq(bignum_value + 42)
+ end
+end
+
+RSpec.describe Object, "-bignum_value" do
+ it "returns a value that is an instance of Bignum on any platform" do
+ expect(-bignum_value).to be < fixnum_min
end
end
diff --git a/spec/mspec/spec/helpers/ruby_exe_spec.rb b/spec/mspec/spec/helpers/ruby_exe_spec.rb
index 8f14f63a32..61225a2756 100644
--- a/spec/mspec/spec/helpers/ruby_exe_spec.rb
+++ b/spec/mspec/spec/helpers/ruby_exe_spec.rb
@@ -145,9 +145,9 @@ RSpec.describe Object, "#ruby_exe" do
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
@script = RubyExeSpecs.new
- allow(@script).to receive(:`)
+ allow(@script).to receive(:`).and_return('OUTPUT')
- status_successful = double(Process::Status, exitstatus: 0)
+ status_successful = double(Process::Status, exited?: true, exitstatus: 0)
allow(Process).to receive(:last_status).and_return(status_successful)
end
@@ -176,7 +176,7 @@ RSpec.describe Object, "#ruby_exe" do
code = "code"
options = {}
- status_failed = double(Process::Status, exitstatus: 4)
+ status_failed = double(Process::Status, exited?: true, exitstatus: 4)
allow(Process).to receive(:last_status).and_return(status_failed)
expect {
@@ -184,16 +184,16 @@ RSpec.describe Object, "#ruby_exe" do
}.to raise_error(%r{Expected exit status is 0 but actual is 4 for command ruby_exe\(.+\)})
end
- it "shows in the exception message if exitstatus is nil (e.g., signal)" do
+ it "shows in the exception message if a signal killed the process" do
code = "code"
options = {}
- status_failed = double(Process::Status, exitstatus: nil)
+ status_failed = double(Process::Status, exited?: false, signaled?: true, termsig: Signal.list.fetch('TERM'))
allow(Process).to receive(:last_status).and_return(status_failed)
expect {
@script.ruby_exe(code, options)
- }.to raise_error(%r{Expected exit status is 0 but actual is nil for command ruby_exe\(.+\)})
+ }.to raise_error(%r{Expected exit status is 0 but actual is :SIGTERM for command ruby_exe\(.+\)})
end
describe "with :dir option" do
@@ -236,7 +236,7 @@ RSpec.describe Object, "#ruby_exe" do
describe "with :exit_status option" do
before do
- status_failed = double(Process::Status, exitstatus: 4)
+ status_failed = double(Process::Status, exited?: true, exitstatus: 4)
allow(Process).to receive(:last_status).and_return(status_failed)
end
diff --git a/spec/mspec/spec/utils/script_spec.rb b/spec/mspec/spec/utils/script_spec.rb
index d9f6eac9a9..c35bda8b47 100644
--- a/spec/mspec/spec/utils/script_spec.rb
+++ b/spec/mspec/spec/utils/script_spec.rb
@@ -96,11 +96,6 @@ RSpec.describe MSpecScript, ".main" do
MSpecScript.main
end
- it "attempts to load the '~/.mspecrc' script" do
- expect(@script).to receive(:try_load).with('~/.mspecrc')
- MSpecScript.main
- end
-
it "calls the #options method on the script" do
expect(@script).to receive(:options)
MSpecScript.main
diff --git a/spec/mspec/tool/remove_old_guards.rb b/spec/mspec/tool/remove_old_guards.rb
index 718e351e11..67485446bb 100644
--- a/spec/mspec/tool/remove_old_guards.rb
+++ b/spec/mspec/tool/remove_old_guards.rb
@@ -21,20 +21,24 @@ def remove_guards(guard, keep)
puts file
lines = contents.lines.to_a
while first = lines.find_index { |line| line =~ guard }
+ comment = first
+ while comment > 0 and lines[comment-1] =~ /^(\s*)#/
+ comment -= 1
+ end
indent = lines[first][/^(\s*)/, 1].length
last = (first+1...lines.size).find { |i|
space = lines[i][/^(\s*)end$/, 1] and space.length == indent
}
raise file unless last
if keep
- lines[first..last] = lines[first+1..last-1].map { |l| dedent(l) }
+ lines[comment..last] = lines[first+1..last-1].map { |l| dedent(l) }
else
- if first > 0 and lines[first-1] == "\n"
- first -= 1
+ if comment > 0 and lines[comment-1] == "\n"
+ comment -= 1
elsif lines[last+1] == "\n"
last += 1
end
- lines[first..last] = []
+ lines[comment..last] = []
end
end
File.binwrite file, lines.join
diff --git a/spec/mspec/tool/sync/sync-rubyspec.rb b/spec/mspec/tool/sync/sync-rubyspec.rb
index 7f3dc0e611..13f1d8004d 100644
--- a/spec/mspec/tool/sync/sync-rubyspec.rb
+++ b/spec/mspec/tool/sync/sync-rubyspec.rb
@@ -20,7 +20,7 @@ IMPLS = {
MSPEC = ARGV.delete('--mspec')
-CHECK_LAST_MERGE = ENV['CHECK_LAST_MERGE'] != 'false'
+CHECK_LAST_MERGE = !MSPEC && ENV['CHECK_LAST_MERGE'] != 'false'
TEST_MASTER = ENV['TEST_MASTER'] != 'false'
MSPEC_REPO = File.expand_path("../../..", __FILE__)
@@ -57,6 +57,10 @@ class RubyImplementation
File.basename(git_url, ".git")
end
+ def repo_path
+ "#{__dir__}/#{repo_name}"
+ end
+
def repo_org
File.basename(File.dirname(git_url))
end
@@ -152,6 +156,11 @@ def rebase_commits(impl)
raise "#{days_since_last_merge.floor} days since last merge, probably wrong commit"
end
+ puts "Checking if the last merge is consistent with upstream files"
+ rubyspec_commit = `git log -n 1 --format='%s' #{last_merge}`.chomp.split('@', 2)[-1]
+ sh "git", "checkout", last_merge
+ sh "git", "diff", "--exit-code", rubyspec_commit, "--", ":!.github"
+
puts "Rebasing..."
sh "git", "branch", "-D", rebased if branch?(rebased)
sh "git", "checkout", "-b", rebased, impl.name
diff --git a/spec/mspec/tool/tag_from_output.rb b/spec/mspec/tool/tag_from_output.rb
index fba52ec26c..a6e60945cd 100755
--- a/spec/mspec/tool/tag_from_output.rb
+++ b/spec/mspec/tool/tag_from_output.rb
@@ -11,21 +11,40 @@ abort 'Could not find tags directory' unless tags_dir
output = ARGF.readlines
+# Automatically strip datetime of GitHub Actions
+if output.first =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z /
+ output = output.map { |line| line.split(' ', 2).last }
+end
+
NUMBER = /^\d+\)$/
ERROR_OR_FAILED = / (ERROR|FAILED)$/
SPEC_FILE = /^(\/.+_spec\.rb)\:\d+/
-output.slice_before(NUMBER).select { |number, error_line, *rest|
- number =~ NUMBER and error_line =~ ERROR_OR_FAILED
-}.each { |number, error_line, *rest|
+output.slice_before(NUMBER).select { |number, *rest|
+ number =~ NUMBER and rest.any? { |line| line =~ ERROR_OR_FAILED }
+}.each { |number, *rest|
+ error_line = rest.find { |line| line =~ ERROR_OR_FAILED }
description = error_line.match(ERROR_OR_FAILED).pre_match
spec_file = rest.find { |line| line =~ SPEC_FILE }
- unless spec_file
- warn "Could not find file for:\n#{error_line}"
- next
+ if spec_file
+ spec_file = spec_file[SPEC_FILE, 1] or raise
+ else
+ if error_line =~ /^(\w+)[#\.](\w+) /
+ module_method = error_line.split(' ', 2).first
+ file = "#{$1.downcase}/#{$2}_spec.rb"
+ spec_file = ['spec/ruby/core', 'spec/ruby/library', *Dir.glob('spec/ruby/library/*')].find { |dir|
+ path = "#{dir}/#{file}"
+ break path if File.exist?(path)
+ }
+ end
+
+ unless spec_file
+ warn "Could not find file for:\n#{error_line}"
+ next
+ end
end
- spec_file = spec_file[SPEC_FILE, 1]
+
prefix = spec_file.index('spec/ruby/') || spec_file.index('spec/truffle/')
spec_file = spec_file[prefix..-1]
diff --git a/spec/ruby/.mspec.constants b/spec/ruby/.mspec.constants
index 6b70274c52..5dd477eb66 100644
--- a/spec/ruby/.mspec.constants
+++ b/spec/ruby/.mspec.constants
@@ -39,6 +39,8 @@ CodingUS_ASCII
CodingUTF_8
ComparisonTest
ConstantSpecsIncludedModule
+ConstantSpecsTwo
+ConstantSpecsThree
ConstantVisibility
Coverage
CoverageSpecs
@@ -73,6 +75,7 @@ EvalBindingProcA
Exception2MessageMapper
ExceptionForMatrix
Fcntl
+Fiddle
FileStat
FileUtils
Find
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index eab4c3c4a6..82733c4b4d 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -1,11 +1,12 @@
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 2.6
+ TargetRubyVersion: 2.7
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
DisabledByDefault: true
+ NewCops: disable
Layout/TrailingWhitespace:
Enabled: true
@@ -56,12 +57,55 @@ Lint/UnusedMethodArgument:
Lint/UselessAssignment:
Enabled: false
-Lint/UselessComparison:
+Lint/BinaryOperatorWithIdenticalOperands:
Enabled: false
+Lint/EmptyConditionalBody:
+ Enabled: false # buggy
+
Lint/Void:
Enabled: false
+Lint/ConstantDefinitionInBlock:
+ Enabled: false
+
+Lint/RaiseException:
+ Enabled: false
+
+Lint/FloatComparison:
+ Enabled: false
+
+Lint/DeprecatedClassMethods:
+ Enabled: false
+
+Lint/UnreachableLoop:
+ Enabled: false
+
+Lint/MissingSuper:
+ Enabled: false
+
+Lint/UselessMethodDefinition:
+ Enabled: false
+
+Lint/UselessTimes:
+ Enabled: false
+
+Lint/MixedRegexpCaptureTypes:
+ Enabled: false
+
+Lint/DuplicateElsifCondition:
+ Enabled: false
+
+Lint/OutOfRangeRegexpRef:
+ Enabled: false
+
+Lint/InheritException:
+ Enabled: false
+
+Lint/ElseLayout:
+ Exclude:
+ - 'language/if_spec.rb'
+
Lint/EmptyExpression:
Exclude:
- 'language/**/*.rb'
@@ -71,6 +115,10 @@ Lint/EmptyWhen:
- language/case_spec.rb
- optional/capi/spec_helper.rb
+Lint/ErbNewArguments:
+ Exclude:
+ - 'library/erb/new_spec.rb'
+
Lint/FormatParameterMismatch:
Exclude:
- 'core/kernel/shared/sprintf.rb'
@@ -117,6 +165,9 @@ Lint/Debugger:
Lint/Loop:
Enabled: false
+Style/BlockComments:
+ Enabled: true
+
Style/Lambda:
Enabled: true
EnforcedStyle: literal
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index a469213841..ac9cfae2bf 100644
--- a/spec/ruby/.rubocop_todo.yml
+++ b/spec/ruby/.rubocop_todo.yml
@@ -50,17 +50,6 @@ Lint/IneffectiveAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'language/fixtures/private.rb'
-# Offense count: 6
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: runtime_error, standard_error
-Lint/InheritException:
- Exclude:
- - 'core/enumerator/lazy/fixtures/classes.rb'
- - 'core/exception/fixtures/common.rb'
- - 'core/module/fixtures/autoload_ex1.rb'
- - 'shared/kernel/raise.rb'
-
# Offense count: 72
# Cop supports --auto-correct.
Lint/LiteralInInterpolation:
diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md
index 30941677e0..adfc2fb0ca 100644
--- a/spec/ruby/CONTRIBUTING.md
+++ b/spec/ruby/CONTRIBUTING.md
@@ -13,12 +13,14 @@ Spec are grouped in 5 separate top-level groups:
* `optional/capi`: for functions available to the Ruby C-extension API
The exact file for methods is decided by the `#owner` of a method, for instance for `#group_by`:
+
```ruby
> [].method(:group_by)
=> #<Method: Array(Enumerable)#group_by>
> [].method(:group_by).owner
=> Enumerable
```
+
Which should therefore be specified in `core/enumerable/group_by_spec.rb`.
### MkSpec - a tool to generate the spec structure
@@ -173,12 +175,13 @@ end
#### Guard for bug
-In case there is a bug in MRI but the expected behavior is obvious.
+In case there is a bug in MRI and the fix will be backported to previous versions.
+If it is not backported or not likely, use `ruby_version_is` instead.
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.
+The problem is `ruby_bug` would make non-MRI implementations fail this spec while MRI itself does not pass it, so it should only be used if the bug is/will be fixed and backported.
```ruby
-ruby_bug '#13669', ''...'2.7' do
+ruby_bug '#13669', ''...'3.2' do
it "works like this" do
# Specify the expected behavior here, not the bug
end
@@ -220,7 +223,7 @@ If an implementation does not support some feature, simply tag the related specs
### Shared Specs
Often throughout Ruby, identical functionality is used by different methods and modules. In order
-to avoid duplication of specs, we have shared specs that are re-used in other specs. The use is a
+to avoid duplication of specs, we have shared specs that are re-used in other specs. The use is a
bit tricky however, so let's go over it.
Commonly, if a shared spec is only reused within its own module, the shared spec will live within a
@@ -232,7 +235,7 @@ An example of this is the `shared/file/socket.rb` which is used by `core/file/so
`core/filetest/socket_spec.rb`, and `core/file/state/socket_spec.rb` and so it lives in the root `shared/`.
Defining a shared spec involves adding a `shared: true` option to the top-level `describe` block. This
-will signal not to run the specs directly by the runner. Shared specs have access to two instance
+will signal not to run the specs directly by the runner. Shared specs have access to two instance
variables from the implementor spec: `@method` and `@object`, which the implementor spec will pass in.
Here's an example of a snippet of a shared spec and two specs which integrates it:
@@ -257,12 +260,12 @@ end
```
In the example, the first `describe` defines the shared spec `:hash_key_p`, which defines a spec that
-calls the `@method` method with an expectation. In the implementor spec, we use `it_behaves_like` to
-integrate the shared spec. `it_behaves_like` takes 3 parameters: the key of the shared spec, a method,
-and an object. These last two parameters are accessible via `@method` and `@object` in the shared spec.
+calls the `@method` method with an expectation. In the implementor spec, we use `it_behaves_like` to
+integrate the shared spec. `it_behaves_like` takes 3 parameters: the key of the shared spec, a method,
+and an object. These last two parameters are accessible via `@method` and `@object` in the shared spec.
Sometimes, shared specs require more context from the implementor class than a simple object. We can address
-this by passing a lambda as the method, which will have the scope of the implementor. Here's an example of
+this by passing a lambda as the method, which will have the scope of the implementor. Here's an example of
how this is used currently:
```ruby
diff --git a/spec/ruby/README.md b/spec/ruby/README.md
index a12cc3f7d8..018bf0ca3e 100644
--- a/spec/ruby/README.md
+++ b/spec/ruby/README.md
@@ -1,7 +1,6 @@
# The Ruby Spec Suite
[![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.
@@ -18,19 +17,21 @@ Every example code has a textual description, which presents several advantages:
The specs are written with syntax similar to RSpec 2.
They are run with MSpec, the purpose-built framework for running the Ruby Spec Suite.
-For more information, see the [MSpec](http://github.com/ruby/mspec) project.
+For more information, see the [MSpec](https://github.com/ruby/mspec) project.
The specs describe the [language syntax](language/), the [core library](core/), the [standard library](library/), the [C API for extensions](optional/capi) and the [command line flags](command_line/).
The language specs are grouped by keyword while the core and standard library specs are grouped by class and method.
ruby/spec is known to be tested in these implementations for every commit:
-* [MRI](http://rubyci.org/) on 30 platforms and 4 versions
+
+* [MRI](https://rubyci.org/) on 30 platforms and 4 versions
* [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x
* [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby)
* [Opal](https://github.com/opal/opal/tree/master/spec)
+* [Artichoke](https://github.com/artichoke/spec/tree/artichoke-vendor)
-ruby/spec describes the behavior of Ruby 2.6 and more recent Ruby versions.
-More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (2.6.x, 2.7.x, 3.0.x, etc), and those are tested in CI.
+ruby/spec describes the behavior of Ruby 2.7 and more recent Ruby versions.
+More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (2.7.x, 3.0.x, 3.1.x, etc), and those are tested in CI.
### Synchronization with Ruby Implementations
@@ -52,12 +53,14 @@ $ ../mspec/bin/mspec
### Specs for old Ruby versions
For older specs try these commits:
+
* Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures)
* Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed)
* Ruby 2.2.10 - [Suite](https://github.com/ruby/spec/commit/cbaa0e412270c944df0c2532fc500c920dba0e92) using [MSpec](https://github.com/ruby/mspec/commit/d84d7668449e96856c5f6bac8cb1526b6d357ce3)
* Ruby 2.3.8 - [Suite](https://github.com/ruby/spec/commit/dc733114d8ae66a3368ba3a98422c50147a76ba5) using [MSpec](https://github.com/ruby/mspec/commit/4599bc195fb109f2a482a01c32a7d659518369ea)
* Ruby 2.4.10 - [Suite](https://github.com/ruby/spec/commit/bce4f2b81d6c31db67cf4d023a0625ceadde59bd) using [MSpec](https://github.com/ruby/mspec/commit/e7eb8aa4c26495b7b461e687d950b96eb08b3ff2)
* Ruby 2.5.9 - [Suite](https://github.com/ruby/spec/commit/c503335d3d9f6ec6ef24de60a0716c34af69b64f) using [MSpec](https://github.com/ruby/mspec/commit/0091e8a62e954717cd54641f935eaf1403692041)
+* Ruby 2.6.10 - [Suite](https://github.com/ruby/spec/commit/aaf998fb8c92c4e63ad423a2e7ca6e6921818c6e) using [MSpec](https://github.com/ruby/mspec/commit/5e36c684e9e2b92b1187589bba1df22c640a8661)
### Running the specs
@@ -69,7 +72,7 @@ Then move to it:
$ cd spec
-Clone [MSpec](http://github.com/ruby/mspec):
+Clone [MSpec](https://github.com/ruby/mspec):
$ git clone https://github.com/ruby/mspec.git ../mspec
@@ -140,10 +143,9 @@ The file `/etc/services` is required for socket specs (package `netbase` on Debi
### Socket specs from rubysl-socket
-Most specs under `library/socket` were imported from [the rubysl-socket project](https://github.com/rubysl/rubysl-socket).
+Most specs under `library/socket` were imported from the rubysl-socket project (which is no longer on GitHub).
The 3 copyright holders of rubysl-socket, Yorick Peterse, Chuck Remes and
-Brian Shirai, [agreed to relicense those specs](https://github.com/rubysl/rubysl-socket/issues/15)
-under the MIT license in ruby/spec.
+Brian Shirai, agreed to relicense those specs under the MIT license in ruby/spec.
### History and RubySpec
@@ -151,5 +153,5 @@ This project was originally born from [Rubinius](https://github.com/rubinius/rub
The revision history of these specs is available [here](https://github.com/ruby/spec/blob/2b886623/CHANGES.before-2008-05-10).
These specs were later extracted to their own project, RubySpec, with a specific vision and principles.
At the end of 2014, Brian Shirai, the creator of RubySpec, decided to [end RubySpec](http://rubinius.com/2014/12/31/matz-s-ruby-developers-don-t-use-rubyspec/).
-A couple months later, the different repositories were merged and [the project was revived](http://eregon.github.io/rubyspec/2015/07/29/rubyspec-is-reborn.html).
+A couple months later, the different repositories were merged and [the project was revived](https://eregon.github.io/rubyspec/2015/07/29/rubyspec-is-reborn.html).
On 12 January 2016, the name was changed to "The Ruby Spec Suite" for clarity and to let the RubySpec ideology rest in peace.
diff --git a/spec/ruby/command_line/backtrace_limit_spec.rb b/spec/ruby/command_line/backtrace_limit_spec.rb
new file mode 100644
index 0000000000..56afa8efef
--- /dev/null
+++ b/spec/ruby/command_line/backtrace_limit_spec.rb
@@ -0,0 +1,48 @@
+require_relative '../spec_helper'
+
+ruby_version_is "3.0" do
+ describe "The --backtrace-limit command line option" do
+ it "limits top-level backtraces to a given number of entries" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1)
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+top
+/fixtures/backtrace.rb:2:in `a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in `b'
+\tfrom /fixtures/backtrace.rb:10:in `c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "affects Exception#full_message" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "full_message 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+full_message
+/fixtures/backtrace.rb:2:in `a': oops (RuntimeError)
+\tfrom /fixtures/backtrace.rb:6:in `b'
+\tfrom /fixtures/backtrace.rb:10:in `c'
+\t ... 2 levels...
+ MSG
+ end
+
+ it "does not affect Exception#backtrace" do
+ file = fixture(__FILE__ , "backtrace.rb")
+ out = ruby_exe(file, options: "--backtrace-limit=2", args: "backtrace 2>&1")
+ out = out.gsub(__dir__, '')
+
+ out.should == <<-MSG
+backtrace
+/fixtures/backtrace.rb:2:in `a'
+/fixtures/backtrace.rb:6:in `b'
+/fixtures/backtrace.rb:10:in `c'
+/fixtures/backtrace.rb:14:in `d'
+/fixtures/backtrace.rb:29:in `<main>'
+ MSG
+ end
+ 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 1b36a1cc22..4019510d42 100644
--- a/spec/ruby/command_line/dash_upper_w_spec.rb
+++ b/spec/ruby/command_line/dash_upper_w_spec.rb
@@ -19,34 +19,26 @@ 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
+describe "The -W command line option with :deprecated" do
+ it "enables deprecation warnings" do
+ ruby_exe('p Warning[:deprecated]', options: '-W:deprecated').should == "true\n"
end
+end
- describe "The -W command line option with :no-experimental" do
- before do
- ruby_version_is ""..."3.0" do
- @src = 'case [0, 1]; in [a, b]; end'
- end
-
- ruby_version_is "3.0" do
- @src = 'warn "This is experimental warning.", category: :experimental'
- end
- end
+describe "The -W command line option with :no-deprecated" do
+ it "suppresses deprecation warnings" do
+ ruby_exe('p Warning[:deprecated]', options: '-w -W:no-deprecated').should == "false\n"
+ end
+end
- it "suppresses experimental warnings" do
- result = ruby_exe(@src, args: '2>&1')
- result.should =~ /is experimental/
+describe "The -W command line option with :experimental" do
+ it "enables experimental warnings" do
+ ruby_exe('p Warning[:experimental]', options: '-W:experimental').should == "true\n"
+ end
+end
- result = ruby_exe(@src, options: '-W:no-experimental', args: '2>&1')
- result.should == ""
- end
+describe "The -W command line option with :no-experimental" do
+ it "suppresses experimental warnings" do
+ ruby_exe('p Warning[:experimental]', options: '-w -W:no-experimental').should == "false\n"
end
end
diff --git a/spec/ruby/command_line/dash_v_spec.rb b/spec/ruby/command_line/dash_v_spec.rb
index 04d684fdad..a4f4dcd051 100644
--- a/spec/ruby/command_line/dash_v_spec.rb
+++ b/spec/ruby/command_line/dash_v_spec.rb
@@ -7,6 +7,7 @@ describe "The -v command line option" do
describe "when used alone" do
it "prints version and ends" do
ruby_exe(nil, args: '-v').should include(RUBY_DESCRIPTION)
- end
+ end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) ||
+ (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?)
end
end
diff --git a/spec/ruby/command_line/dash_w_spec.rb b/spec/ruby/command_line/dash_w_spec.rb
index 1d93e0347b..f310dca3ed 100644
--- a/spec/ruby/command_line/dash_w_spec.rb
+++ b/spec/ruby/command_line/dash_w_spec.rb
@@ -3,4 +3,8 @@ require_relative 'shared/verbose'
describe "The -w command line option" do
it_behaves_like :command_line_verbose, "-w"
+
+ it "enables both deprecated and experimental warnings" do
+ ruby_exe('p Warning[:deprecated]; p Warning[:experimental]', options: '-w').should == "true\ntrue\n"
+ end
end
diff --git a/spec/ruby/command_line/feature_spec.rb b/spec/ruby/command_line/feature_spec.rb
index 1a9ea925c9..4a24cc6795 100644
--- a/spec/ruby/command_line/feature_spec.rb
+++ b/spec/ruby/command_line/feature_spec.rb
@@ -43,7 +43,9 @@ describe "The --enable and --disable flags" do
ruby_exe("p 'foo'.frozen?", options: "--disable-frozen-string-literal").chomp.should == "false"
end
- platform_is_not :darwin do # frequently hangs for >60s on GitHub Actions macos-latest
+ # frequently hangs for >60s on GitHub Actions macos-latest
+ # MinGW's YJIT support seems broken
+ platform_is_not :darwin, :mingw do
it "can be used with all for enable" do
e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
env = {'RUBYOPT' => '-w'}
diff --git a/spec/ruby/command_line/fixtures/backtrace.rb b/spec/ruby/command_line/fixtures/backtrace.rb
new file mode 100644
index 0000000000..99acae95c8
--- /dev/null
+++ b/spec/ruby/command_line/fixtures/backtrace.rb
@@ -0,0 +1,35 @@
+def a
+ raise 'oops'
+end
+
+def b
+ a
+end
+
+def c
+ b
+end
+
+def d
+ c
+end
+
+arg = ARGV.first
+$stderr.puts arg
+
+case arg
+when 'full_message'
+ begin
+ d
+ rescue => exc
+ puts exc.full_message
+ end
+when 'backtrace'
+ begin
+ d
+ rescue => exc
+ puts exc.backtrace
+ end
+else
+ d
+end
diff --git a/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb b/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb
index 074092c9d9..f5547a5bae 100644
--- a/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb
+++ b/spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb
@@ -1 +1 @@
-p "abc".object_id == "abc".object_id
+p "abc".equal?("abc")
diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb
index a2b817bad8..bbea4d557d 100644
--- a/spec/ruby/command_line/rubyopt_spec.rb
+++ b/spec/ruby/command_line/rubyopt_spec.rb
@@ -59,24 +59,22 @@ 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 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 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
+ 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
it "requires the file for '-r'" do
diff --git a/spec/ruby/core/array/clear_spec.rb b/spec/ruby/core/array/clear_spec.rb
index bddc672d3b..81ba56e01e 100644
--- a/spec/ruby/core/array/clear_spec.rb
+++ b/spec/ruby/core/array/clear_spec.rb
@@ -20,30 +20,10 @@ describe "Array#clear" do
a.size.should == 0
end
- ruby_version_is ''...'2.7' do
- it "keeps tainted status" do
- a = [1]
- a.taint
- a.tainted?.should be_true
- a.clear
- a.tainted?.should be_true
- end
- end
-
it "does not accept any arguments" do
-> { [1].clear(true) }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "keeps untrusted status" do
- a = [1]
- a.untrust
- a.untrusted?.should be_true
- a.clear
- a.untrusted?.should be_true
- end
- end
-
it "raises a FrozenError on a frozen array" do
a = [1]
a.freeze
diff --git a/spec/ruby/core/array/compact_spec.rb b/spec/ruby/core/array/compact_spec.rb
index aa3c1c0446..83b3fa2a89 100644
--- a/spec/ruby/core/array/compact_spec.rb
+++ b/spec/ruby/core/array/compact_spec.rb
@@ -21,20 +21,6 @@ describe "Array#compact" do
it "does not return subclass instance for Array subclasses" do
ArraySpecs::MyArray[1, 2, 3, nil].compact.should be_an_instance_of(Array)
end
-
- ruby_version_is ''...'2.7' do
- it "does not keep tainted status even if all elements are removed" do
- a = [nil, nil]
- a.taint
- a.compact.tainted?.should be_false
- end
-
- it "does not keep untrusted status even if all elements are removed" do
- a = [nil, nil]
- a.untrust
- a.compact.untrusted?.should be_false
- end
- end
end
describe "Array#compact!" do
@@ -59,22 +45,6 @@ describe "Array#compact!" do
[1, 2, false, 3].compact!.should == nil
end
- ruby_version_is ''...'2.7' do
- it "keeps tainted status even if all elements are removed" do
- a = [nil, nil]
- a.taint
- a.compact!
- a.tainted?.should be_true
- end
-
- it "keeps untrusted status even if all elements are removed" do
- a = [nil, nil]
- a.untrust
- a.compact!
- a.untrusted?.should be_true
- end
- end
-
it "raises a FrozenError on a frozen array" do
-> { ArraySpecs.frozen_array.compact! }.should raise_error(FrozenError)
end
diff --git a/spec/ruby/core/array/concat_spec.rb b/spec/ruby/core/array/concat_spec.rb
index da6763bfd6..f3cab9c17c 100644
--- a/spec/ruby/core/array/concat_spec.rb
+++ b/spec/ruby/core/array/concat_spec.rb
@@ -41,64 +41,6 @@ describe "Array#concat" do
-> { ArraySpecs.frozen_array.concat([]) }.should raise_error(FrozenError)
end
- ruby_version_is ''...'2.7' do
- it "keeps tainted status" do
- ary = [1, 2]
- ary.taint
- ary.concat([3])
- ary.tainted?.should be_true
- ary.concat([])
- ary.tainted?.should be_true
- end
-
- it "is not infected by the other" do
- ary = [1,2]
- other = [3]; other.taint
- ary.tainted?.should be_false
- ary.concat(other)
- ary.tainted?.should be_false
- end
-
- it "keeps the tainted status of elements" do
- ary = [ Object.new, Object.new, Object.new ]
- ary.each {|x| x.taint }
-
- ary.concat([ Object.new ])
- ary[0].tainted?.should be_true
- ary[1].tainted?.should be_true
- ary[2].tainted?.should be_true
- ary[3].tainted?.should be_false
- end
-
- it "keeps untrusted status" do
- ary = [1, 2]
- ary.untrust
- ary.concat([3])
- ary.untrusted?.should be_true
- ary.concat([])
- ary.untrusted?.should be_true
- end
-
- it "is not infected untrustedness by the other" do
- ary = [1,2]
- other = [3]; other.untrust
- ary.untrusted?.should be_false
- ary.concat(other)
- ary.untrusted?.should be_false
- end
-
- it "keeps the untrusted status of elements" do
- ary = [ Object.new, Object.new, Object.new ]
- ary.each {|x| x.untrust }
-
- ary.concat([ Object.new ])
- ary[0].untrusted?.should be_true
- ary[1].untrusted?.should be_true
- ary[2].untrusted?.should be_true
- ary[3].untrusted?.should be_false
- end
- end
-
it "appends elements to an Array with enough capacity that has been shifted" do
ary = [1, 2, 3, 4, 5]
2.times { ary.shift }
diff --git a/spec/ruby/core/array/deconstruct_spec.rb b/spec/ruby/core/array/deconstruct_spec.rb
index 2b07152dfc..ad67abe47b 100644
--- a/spec/ruby/core/array/deconstruct_spec.rb
+++ b/spec/ruby/core/array/deconstruct_spec.rb
@@ -1,11 +1,9 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "Array#deconstruct" do
- it "returns self" do
- array = [1]
+describe "Array#deconstruct" do
+ it "returns self" do
+ array = [1]
- array.deconstruct.should equal array
- end
+ array.deconstruct.should equal array
end
end
diff --git a/spec/ruby/core/array/delete_at_spec.rb b/spec/ruby/core/array/delete_at_spec.rb
index fc225a03f1..80ec643702 100644
--- a/spec/ruby/core/array/delete_at_spec.rb
+++ b/spec/ruby/core/array/delete_at_spec.rb
@@ -38,26 +38,4 @@ describe "Array#delete_at" do
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
- it "keeps tainted status" do
- ary = [1, 2]
- ary.taint
- ary.tainted?.should be_true
- ary.delete_at(0)
- ary.tainted?.should be_true
- ary.delete_at(0) # now empty
- ary.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- ary = [1, 2]
- ary.untrust
- ary.untrusted?.should be_true
- ary.delete_at(0)
- ary.untrusted?.should be_true
- ary.delete_at(0) # now empty
- ary.untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/array/delete_if_spec.rb b/spec/ruby/core/array/delete_if_spec.rb
index e1931220f5..1459cc8d04 100644
--- a/spec/ruby/core/array/delete_if_spec.rb
+++ b/spec/ruby/core/array/delete_if_spec.rb
@@ -47,22 +47,6 @@ describe "Array#delete_if" do
-> { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(FrozenError)
end
- ruby_version_is ''...'2.7' do
- it "keeps tainted status" do
- @a.taint
- @a.tainted?.should be_true
- @a.delete_if{ true }
- @a.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- @a.untrust
- @a.untrusted?.should be_true
- @a.delete_if{ true }
- @a.untrusted?.should be_true
- end
- end
-
it_behaves_like :enumeratorized_with_origin_size, :delete_if, [1,2,3]
it_behaves_like :delete_if, :delete_if
end
diff --git a/spec/ruby/core/array/delete_spec.rb b/spec/ruby/core/array/delete_spec.rb
index 5d53c74e47..dddbbe6bd3 100644
--- a/spec/ruby/core/array/delete_spec.rb
+++ b/spec/ruby/core/array/delete_spec.rb
@@ -43,26 +43,4 @@ describe "Array#delete" do
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
- it "keeps tainted status" do
- a = [1, 2]
- a.taint
- a.tainted?.should be_true
- a.delete(2)
- a.tainted?.should be_true
- a.delete(1) # now empty
- a.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- a = [1, 2]
- a.untrust
- a.untrusted?.should be_true
- a.delete(2)
- a.untrusted?.should be_true
- a.delete(1) # now empty
- a.untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/array/each_spec.rb b/spec/ruby/core/array/each_spec.rb
index 256647d61e..cf8e9da6d8 100644
--- a/spec/ruby/core/array/each_spec.rb
+++ b/spec/ruby/core/array/each_spec.rb
@@ -3,9 +3,10 @@ require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative '../enumerable/shared/enumeratorized'
-# Modifying a collection while the contents are being iterated
-# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
+# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
+# CRuby simply reads the array storage and checks the size for every iteration;
+# like `i = 0; while i < size; yield self[i]; end`
describe "Array#each" do
it "yields each element to the block" do
@@ -15,6 +16,34 @@ describe "Array#each" do
a.should == [1, 2, 3]
end
+ it "yields each element to the block even if the array is changed during iteration" do
+ a = [1, 2, 3, 4, 5]
+ iterated = []
+ a.each { |x| iterated << x; a << x+5 if x.even? }
+ iterated.should == [1, 2, 3, 4, 5, 7, 9]
+ end
+
+ it "yields only elements that are still in the array" do
+ a = [0, 1, 2, 3, 4]
+ iterated = []
+ a.each { |x| iterated << x; a.pop if x.even? }
+ iterated.should == [0, 1, 2]
+ end
+
+ it "yields elements based on an internal index" do
+ a = [0, 1, 2, 3, 4]
+ iterated = []
+ a.each { |x| iterated << x; a.shift if x.even? }
+ iterated.should == [0, 2, 4]
+ end
+
+ it "yields the same element multiple times if inserting while iterating" do
+ a = [1, 2]
+ iterated = []
+ a.each { |x| iterated << x; a.unshift(0) if a.size == 2 }
+ iterated.should == [1, 1, 2]
+ end
+
it "yields each element to a block that takes multiple arguments" do
a = [[1, 2], :a, [3, 4]]
b = []
diff --git a/spec/ruby/core/array/element_set_spec.rb b/spec/ruby/core/array/element_set_spec.rb
index 1e192c100f..df5ca9582e 100644
--- a/spec/ruby/core/array/element_set_spec.rb
+++ b/spec/ruby/core/array/element_set_spec.rb
@@ -481,50 +481,48 @@ describe "Array#[]= with [m..]" do
end
end
-ruby_version_is "2.7" do
- describe "Array#[]= with [..n] and [...n]" do
- it "just sets the section defined by range to nil even if the rhs is nil" do
- a = [1, 2, 3, 4, 5]
- a[eval("(..2)")] = nil
- a.should == [nil, 4, 5]
- a[eval("(...2)")] = nil
- a.should == [nil, 5]
- end
+describe "Array#[]= with [..n] and [...n]" do
+ it "just sets the section defined by range to nil even if the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[(..2)] = nil
+ a.should == [nil, 4, 5]
+ a[(...2)] = nil
+ a.should == [nil, 5]
+ end
- it "just sets the section defined by range to nil if n < 0 and the rhs is nil" do
- a = [1, 2, 3, 4, 5]
- a[eval("(..-3)")] = nil
- a.should == [nil, 4, 5]
- a[eval("(...-1)")] = [nil, 5]
- end
+ it "just sets the section defined by range to nil if n < 0 and the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[(..-3)] = nil
+ a.should == [nil, 4, 5]
+ a[(...-1)] = [nil, 5]
+ end
- it "replaces the section defined by range" do
- a = [6, 5, 4, 3, 2, 1]
- a[eval("(...3)")] = 9
- a.should == [9, 3, 2, 1]
- a[eval("(..2)")] = [7, 7, 7, 7, 7]
- a.should == [7, 7, 7, 7, 7, 1]
- end
+ it "replaces the section defined by range" do
+ a = [6, 5, 4, 3, 2, 1]
+ a[(...3)] = 9
+ a.should == [9, 3, 2, 1]
+ a[(..2)] = [7, 7, 7, 7, 7]
+ a.should == [7, 7, 7, 7, 7, 1]
+ end
- it "replaces the section if n < 0" do
- a = [1, 2, 3, 4, 5]
- a[eval("(..-2)")] = [7, 8, 9]
- a.should == [7, 8, 9, 5]
- end
+ it "replaces the section if n < 0" do
+ a = [1, 2, 3, 4, 5]
+ a[(..-2)] = [7, 8, 9]
+ a.should == [7, 8, 9, 5]
+ end
- it "replaces everything if n > the array size" do
- a = [1, 2, 3]
- a[eval("(...7)")] = [4]
- a.should == [4]
- end
+ it "replaces everything if n > the array size" do
+ a = [1, 2, 3]
+ a[(...7)] = [4]
+ a.should == [4]
+ end
- it "inserts at the beginning if n < negative the array size" do
- a = [1, 2, 3]
- a[eval("(..-7)")] = [4]
- a.should == [4, 1, 2, 3]
- a[eval("(...-10)")] = [6]
- a.should == [6, 4, 1, 2, 3]
- end
+ it "inserts at the beginning if n < negative the array size" do
+ a = [1, 2, 3]
+ a[(..-7)] = [4]
+ a.should == [4, 1, 2, 3]
+ a[(...-10)] = [6]
+ a.should == [6, 4, 1, 2, 3]
end
end
diff --git a/spec/ruby/core/array/fill_spec.rb b/spec/ruby/core/array/fill_spec.rb
index bfa8db551b..23728414be 100644
--- a/spec/ruby/core/array/fill_spec.rb
+++ b/spec/ruby/core/array/fill_spec.rb
@@ -205,6 +205,12 @@ describe "Array#fill with (filler, index, length)" do
-> { [].fill('a', obj) }.should raise_error(TypeError)
end
+ it "raises a TypeError when the length is not numeric" do
+ -> { [1, 2, 3].fill("x", 1, "foo") }.should raise_error(TypeError, /no implicit conversion of String into Integer/)
+ -> { [1, 2, 3].fill("x", 1, :"foo") }.should raise_error(TypeError, /no implicit conversion of Symbol into Integer/)
+ -> { [1, 2, 3].fill("x", 1, Object.new) }.should raise_error(TypeError, /no implicit conversion of Object into Integer/)
+ end
+
not_supported_on :opal do
it "raises an ArgumentError or RangeError for too-large sizes" do
error_types = [RangeError, ArgumentError]
@@ -323,10 +329,8 @@ describe "Array#fill with (filler, range)" do
[1, 2, 3, 4].fill(eval("(3...)")) { |x| x + 2 }.should == [1, 2, 3, 5]
end
- ruby_version_is "2.7" do
- it "works with beginless ranges" do
- [1, 2, 3, 4].fill('x', eval("(..2)")).should == ["x", "x", "x", 4]
- [1, 2, 3, 4].fill(eval("(...2)")) { |x| x + 2 }.should == [2, 3, 3, 4]
- end
+ it "works with beginless ranges" do
+ [1, 2, 3, 4].fill('x', (..2)).should == ["x", "x", "x", 4]
+ [1, 2, 3, 4].fill((...2)) { |x| x + 2 }.should == [2, 3, 3, 4]
end
end
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index affb3b49e6..aa5fecd96b 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -40,6 +40,68 @@ module ArraySpecs
a
end
+ # Chi squared critical values for tests with n degrees of freedom at 99% confidence.
+ # Values obtained from NIST Engineering Statistic Handbook at
+ # https://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm
+
+ CHI_SQUARED_CRITICAL_VALUES = [
+ 0,
+ 6.635, 9.210, 11.345, 13.277, 15.086, 16.812, 18.475, 20.090, 21.666, 23.209,
+ 24.725, 26.217, 27.688, 29.141, 30.578, 32.000, 33.409, 34.805, 36.191, 37.566,
+ 38.932, 40.289, 41.638, 42.980, 44.314, 45.642, 46.963, 48.278, 49.588, 50.892,
+ 52.191, 53.486, 54.776, 56.061, 57.342, 58.619, 59.893, 61.162, 62.428, 63.691,
+ 64.950, 66.206, 67.459, 68.710, 69.957, 71.201, 72.443, 73.683, 74.919, 76.154,
+ 77.386, 78.616, 79.843, 81.069, 82.292, 83.513, 84.733, 85.950, 87.166, 88.379,
+ 89.591, 90.802, 92.010, 93.217, 94.422, 95.626, 96.828, 98.028, 99.228, 100.425,
+ 101.621, 102.816, 104.010, 105.202, 106.393, 107.583, 108.771, 109.958, 111.144, 112.329,
+ 113.512, 114.695, 115.876, 117.057, 118.236, 119.414, 120.591, 121.767, 122.942, 124.116,
+ 125.289, 126.462, 127.633, 128.803, 129.973, 131.141, 132.309, 133.476, 134.642, 135.807,
+ ]
+
+ def self.measure_sample_fairness(size, samples, iters)
+ ary = Array.new(size) { |x| x }
+ (samples).times do |i|
+ chi_results = []
+ 3.times do
+ counts = Array.new(size) { 0 }
+ expected = iters / size
+ iters.times do
+ x = ary.sample(samples)[i]
+ counts[x] += 1
+ end
+ chi_squared = 0.0
+ counts.each do |count|
+ chi_squared += (((count - expected) ** 2) * 1.0 / expected)
+ end
+ chi_results << chi_squared
+ break if chi_squared <= CHI_SQUARED_CRITICAL_VALUES[size]
+ end
+
+ chi_results.min.should <= CHI_SQUARED_CRITICAL_VALUES[size]
+ end
+ end
+
+ def self.measure_sample_fairness_large_sample_size(size, samples, iters)
+ ary = Array.new(size) { |x| x }
+ counts = Array.new(size) { 0 }
+ expected = iters * samples / size
+ iters.times do
+ ary.sample(samples).each do |sample|
+ counts[sample] += 1
+ end
+ end
+ chi_squared = 0.0
+ counts.each do |count|
+ chi_squared += (((count - expected) ** 2) * 1.0 / expected)
+ end
+
+ # Chi squared critical values for tests with 4 degrees of freedom
+ # Values obtained from NIST Engineering Statistic Handbook at
+ # https://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm
+
+ chi_squared.should <= CHI_SQUARED_CRITICAL_VALUES[size]
+ end
+
class MyArray < Array
# The #initialize method has a different signature than Array to help
# catch places in the specs that do not assert the #initialize is not
diff --git a/spec/ruby/core/array/flatten_spec.rb b/spec/ruby/core/array/flatten_spec.rb
index 2f9fb8a3ec..1770b5389a 100644
--- a/spec/ruby/core/array/flatten_spec.rb
+++ b/spec/ruby/core/array/flatten_spec.rb
@@ -147,16 +147,6 @@ describe "Array#flatten" do
end
end
- ruby_version_is ''...'2.7' do
- it "returns a tainted array if self is tainted" do
- [].taint.flatten.tainted?.should be_true
- end
-
- it "returns an untrusted array if self is untrusted" do
- [].untrust.flatten.untrusted?.should be_true
- end
- end
-
it "performs respond_to? and method_missing-aware checks when coercing elements to array" do
bo = BasicObject.new
[bo].flatten.should == [bo]
diff --git a/spec/ruby/core/array/intersect_spec.rb b/spec/ruby/core/array/intersect_spec.rb
new file mode 100644
index 0000000000..b8c5b1e69a
--- /dev/null
+++ b/spec/ruby/core/array/intersect_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+
+describe 'Array#intersect?' do
+ ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/15198
+ describe 'when at least one element in two Arrays is the same' do
+ it 'returns true' do
+ [1, 2].intersect?([2, 3]).should == true
+ end
+ end
+
+ describe 'when there are no elements in common between two Arrays' do
+ it 'returns false' do
+ [1, 2].intersect?([3, 4]).should == false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/array/intersection_spec.rb b/spec/ruby/core/array/intersection_spec.rb
index 27d90f1e44..e01a68d389 100644
--- a/spec/ruby/core/array/intersection_spec.rb
+++ b/spec/ruby/core/array/intersection_spec.rb
@@ -6,16 +6,14 @@ describe "Array#&" do
it_behaves_like :array_intersection, :&
end
-ruby_version_is "2.7" do
- describe "Array#intersection" do
- it_behaves_like :array_intersection, :intersection
+describe "Array#intersection" do
+ it_behaves_like :array_intersection, :intersection
- it "accepts multiple arguments" do
- [1, 2, 3, 4].intersection([1, 2, 3], [2, 3, 4]).should == [2, 3]
- end
+ it "accepts multiple arguments" do
+ [1, 2, 3, 4].intersection([1, 2, 3], [2, 3, 4]).should == [2, 3]
+ end
- it "preserves elements order from original array" do
- [1, 2, 3, 4].intersection([3, 2, 1]).should == [1, 2, 3]
- end
+ it "preserves elements order from original array" do
+ [1, 2, 3, 4].intersection([3, 2, 1]).should == [1, 2, 3]
end
end
diff --git a/spec/ruby/core/array/keep_if_spec.rb b/spec/ruby/core/array/keep_if_spec.rb
index bf2bdeaf91..40f7329b7c 100644
--- a/spec/ruby/core/array/keep_if_spec.rb
+++ b/spec/ruby/core/array/keep_if_spec.rb
@@ -1,3 +1,4 @@
+require_relative '../../spec_helper'
require_relative 'shared/keep_if'
describe "Array#keep_if" do
diff --git a/spec/ruby/core/array/multiply_spec.rb b/spec/ruby/core/array/multiply_spec.rb
index 16e407348b..23d5c99f3a 100644
--- a/spec/ruby/core/array/multiply_spec.rb
+++ b/spec/ruby/core/array/multiply_spec.rb
@@ -97,46 +97,6 @@ describe "Array#* with an integer" do
ScratchPad.recorded.should be_nil
end
end
-
- ruby_version_is ''...'2.7' 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).should.tainted?
- end
-
- it "copies the taint status of the original array even if the array is empty" do
- ary = []
- ary.taint
- (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).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).should.untrusted?
- end
-
- it "copies the untrusted status of the original array even if the array is empty" do
- ary = []
- ary.untrust
- (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).should.untrusted?
- (ary * 2).should.untrusted?
- end
- end
end
describe "Array#* with a string" do
diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb
index 7af7a16c68..f4a40502c2 100644
--- a/spec/ruby/core/array/pack/a_spec.rb
+++ b/spec/ruby/core/array/pack/a_spec.rb
@@ -12,6 +12,17 @@ describe "Array#pack with format 'A'" do
it_behaves_like :array_pack_string, 'A'
it_behaves_like :array_pack_taint, 'A'
+ it "calls #to_str to convert an Object to a String" do
+ obj = mock("pack A string")
+ obj.should_receive(:to_str).and_return("``abcdef")
+ [obj].pack("A*").should == "``abcdef"
+ end
+
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('A') }.should raise_error(TypeError)
+ -> { [0].pack('a') }.should raise_error(TypeError)
+ end
+
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("A*").should == "abc"
end
diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb
index 872c1b88d5..ec82b7d1ab 100644
--- a/spec/ruby/core/array/pack/b_spec.rb
+++ b/spec/ruby/core/array/pack/b_spec.rb
@@ -13,11 +13,16 @@ describe "Array#pack with format 'B'" do
it_behaves_like :array_pack_taint, 'B'
it "calls #to_str to convert an Object to a String" do
- obj = mock("pack H string")
+ obj = mock("pack B string")
obj.should_receive(:to_str).and_return("``abcdef")
[obj].pack("B*").should == "\x2a"
end
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('B') }.should raise_error(TypeError)
+ -> { [0].pack('b') }.should raise_error(TypeError)
+ end
+
it "encodes one bit for each character starting with the most significant bit" do
[ [["0"], "\x00"],
[["1"], "\x80"]
diff --git a/spec/ruby/core/array/pack/c_spec.rb b/spec/ruby/core/array/pack/c_spec.rb
index 7200830331..be03551629 100644
--- a/spec/ruby/core/array/pack/c_spec.rb
+++ b/spec/ruby/core/array/pack/c_spec.rb
@@ -45,8 +45,18 @@ describe :array_pack_8bit, shared: true do
[1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05"
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb
index 85a875fc8b..2c1dac8d4a 100644
--- a/spec/ruby/core/array/pack/h_spec.rb
+++ b/spec/ruby/core/array/pack/h_spec.rb
@@ -18,6 +18,11 @@ describe "Array#pack with format 'H'" do
[obj].pack("H").should == "\xa0"
end
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('H') }.should raise_error(TypeError)
+ -> { [0].pack('h') }.should raise_error(TypeError)
+ end
+
it "encodes the first character as the most significant nibble when passed no count modifier" do
["ab"].pack("H").should == "\xa0"
end
diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb
index 2b1a84abca..c6364af12d 100644
--- a/spec/ruby/core/array/pack/m_spec.rb
+++ b/spec/ruby/core/array/pack/m_spec.rb
@@ -80,8 +80,16 @@ describe "Array#pack with format 'M'" do
].should be_computed_by(:pack, "M")
end
- it "encodes a tab followed by a newline with an encoded newline" do
+ it "encodes a tab at the end of a line with an encoded newline" do
+ ["\t"].pack("M").should == "\t=\n"
["\t\n"].pack("M").should == "\t=\n\n"
+ ["abc\t\nxyz"].pack("M").should == "abc\t=\n\nxyz=\n"
+ end
+
+ it "encodes a space at the end of a line with an encoded newline" do
+ [" "].pack("M").should == " =\n"
+ [" \n"].pack("M").should == " =\n\n"
+ ["abc \nxyz"].pack("M").should == "abc =\n\nxyz=\n"
end
it "encodes 127..255 in hex format" do
diff --git a/spec/ruby/core/array/pack/p_spec.rb b/spec/ruby/core/array/pack/p_spec.rb
index d7dff8a4da..b023bf9110 100644
--- a/spec/ruby/core/array/pack/p_spec.rb
+++ b/spec/ruby/core/array/pack/p_spec.rb
@@ -15,18 +15,6 @@ describe "Array#pack with format 'P'" do
["hello"].pack("P").unpack("P5").should == ["hello"]
end
- ruby_version_is ''...'2.7' do
- it "taints the input string" do
- input_string = "hello"
- [input_string].pack("P")
- input_string.tainted?.should be_true
- end
-
- it "does not taint the output string in normal cases" do
- ["hello"].pack("P").tainted?.should be_false
- end
- end
-
it "with nil gives a null pointer" do
[nil].pack("P").unpack("J").should == [0]
end
@@ -44,18 +32,6 @@ describe "Array#pack with format 'p'" do
["hello"].pack("p").unpack("p").should == ["hello"]
end
- ruby_version_is ''...'2.7' do
- it "taints the input string" do
- input_string = "hello"
- [input_string].pack("p")
- input_string.tainted?.should be_true
- end
-
- it "does not taint the output string in normal cases" do
- ["hello"].pack("p").tainted?.should be_false
- end
- end
-
it "with nil gives a null pointer" do
[nil].pack("p").unpack("J").should == [0]
end
diff --git a/spec/ruby/core/array/pack/shared/basic.rb b/spec/ruby/core/array/pack/shared/basic.rb
index 9061273ad6..65fdaa45d8 100644
--- a/spec/ruby/core/array/pack/shared/basic.rb
+++ b/spec/ruby/core/array/pack/shared/basic.rb
@@ -27,17 +27,47 @@ describe :array_pack_basic_non_float, shared: true do
[@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
end
+ it "ignores comments in the format string" do
+ # 2 additional directives ('a') are required for the X directive
+ [@obj, @obj, @obj, @obj].pack("aa #{pack_format} # some comment \n#{pack_format}").should be_an_instance_of(String)
+ end
+
+ ruby_version_is ""..."3.2" do
+ it "warns in verbose mode that a directive is unknown" do
+ # additional directive ('a') is required for the X directive
+ -> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/, verbose: true)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/, verbose: true)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/, verbose: true)
+ end
+ end
+
+ ruby_version_is "3.2"..."3.3" do
+ # https://bugs.ruby-lang.org/issues/19150
+ # NOTE: it's just a plan of the Ruby core team
+ it "warns that a directive is unknown" do
+ # additional directive ('a') is required for the X directive
+ -> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/)
+ end
+ end
+
+ ruby_version_is "3.3" do
+ # https://bugs.ruby-lang.org/issues/19150
+ # NOTE: Added this case just to not forget about the decision in the ticket
+ it "raise ArgumentError when a directive is unknown" do
+ # additional directive ('a') is required for the X directive
+ -> { [@obj, @obj].pack("a R" + pack_format) }.should raise_error(ArgumentError)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should raise_error(ArgumentError)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should raise_error(ArgumentError)
+ end
+ end
+
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
[@obj, @obj].pack(d).should be_an_instance_of(String)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the output string if the format string is tainted" do
- [@obj, @obj].pack("x"+pack_format.taint).tainted?.should be_true
- end
- end
end
describe :array_pack_basic_float, shared: true do
@@ -45,17 +75,15 @@ describe :array_pack_basic_float, shared: true do
[9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
end
+ it "ignores comments in the format string" do
+ [9.3, 4.7].pack(pack_format + "# some comment \n" + pack_format).should be_an_instance_of(String)
+ end
+
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
[1.2, 4.7].pack(d).should be_an_instance_of(String)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the output string if the format string is tainted" do
- [3.2, 2.8].pack("x"+pack_format.taint).tainted?.should be_true
- end
- end
end
describe :array_pack_no_platform, shared: true do
diff --git a/spec/ruby/core/array/pack/shared/float.rb b/spec/ruby/core/array/pack/shared/float.rb
index c6b194007f..9510cffed7 100644
--- a/spec/ruby/core/array/pack/shared/float.rb
+++ b/spec/ruby/core/array/pack/shared/float.rb
@@ -25,8 +25,18 @@ describe :array_pack_float_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -53,6 +63,14 @@ describe :array_pack_float_le, shared: true do
it "encodes a negative Float outside the range of a single precision float" do
[-1e150].pack(pack_format).should == "\x00\x00\x80\xff"
end
+
+ it "encodes a bignum as a float" do
+ [2 ** 65].pack(pack_format).should == [(2 ** 65).to_f].pack(pack_format)
+ end
+
+ it "encodes a rational as a float" do
+ [Rational(3, 4)].pack(pack_format).should == [Rational(3, 4).to_f].pack(pack_format)
+ end
end
describe :array_pack_float_be, shared: true do
@@ -66,6 +84,11 @@ describe :array_pack_float_be, shared: true do
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "A\x00\x00\x00"
+ [bignum_value].pack(pack_format).should == "_\x80\x00\x00"
+ end
+
+ it "converts a Rational to a Float" do
+ [Rational(8)].pack(pack_format).should == "A\x00\x00\x00"
end
it "raises a TypeError if passed a String representation of a floating point number" do
@@ -80,8 +103,18 @@ describe :array_pack_float_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -121,6 +154,11 @@ describe :array_pack_double_le, shared: true do
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@"
+ [bignum_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xF0C"
+ end
+
+ it "converts a Rational to a Float" do
+ [Rational(8)].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00 @"
end
it "raises a TypeError if passed a String representation of a floating point number" do
@@ -135,8 +173,18 @@ describe :array_pack_double_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -194,8 +242,18 @@ describe :array_pack_double_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff"
end
- it "ignores NULL bytes between directives" do
- [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [5.3, 9.2].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/shared/integer.rb b/spec/ruby/core/array/pack/shared/integer.rb
index 6592f85022..d3ce9b5792 100644
--- a/spec/ruby/core/array/pack/shared/integer.rb
+++ b/spec/ruby/core/array/pack/shared/integer.rb
@@ -41,9 +41,19 @@ describe :array_pack_16bit_le, shared: true do
str.should == "\x78\x65\xcd\xab\x21\x43"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x78\x65\xcd\xab"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ str.should == "\x78\x65\xcd\xab"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -93,9 +103,19 @@ describe :array_pack_16bit_be, shared: true do
str.should == "\x65\x78\xab\xcd\x43\x21"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x65\x78\xab\xcd"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ str.should == "\x65\x78\xab\xcd"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -145,9 +165,19 @@ describe :array_pack_32bit_le, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -197,9 +227,19 @@ describe :array_pack_32bit_be, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
- it "ignores NULL bytes between directives" do
- str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
- str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -309,9 +349,19 @@ describe :array_pack_64bit_le, shared: true do
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end
- it "ignores NULL bytes between directives" do
- str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
- str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -369,9 +419,19 @@ describe :array_pack_64bit_be, shared: true do
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end
- it "ignores NULL bytes between directives" do
- str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
- str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/shared/numeric_basic.rb b/spec/ruby/core/array/pack/shared/numeric_basic.rb
index 7c36ba4a32..545e215e64 100644
--- a/spec/ruby/core/array/pack/shared/numeric_basic.rb
+++ b/spec/ruby/core/array/pack/shared/numeric_basic.rb
@@ -37,8 +37,14 @@ describe :array_pack_float, shared: true do
-> { ["a"].pack(pack_format) }.should raise_error(TypeError)
end
- it "raises a TypeError when the object does not respond to #to_f" do
- obj = mock('not an float')
+ it "raises a TypeError when the object is not Numeric" do
+ obj = Object.new
+ -> { [obj].pack(pack_format) }.should raise_error(TypeError, /can't convert Object into Float/)
+ end
+
+ it "raises a TypeError when the Numeric object does not respond to #to_f" do
+ klass = Class.new(Numeric)
+ obj = klass.new
-> { [obj].pack(pack_format) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/array/pack/shared/taint.rb b/spec/ruby/core/array/pack/shared/taint.rb
index 565f04b8b9..2c2b011c34 100644
--- a/spec/ruby/core/array/pack/shared/taint.rb
+++ b/spec/ruby/core/array/pack/shared/taint.rb
@@ -1,35 +1,2 @@
describe :array_pack_taint, shared: true do
- ruby_version_is ''...'2.7' do
- it "returns a tainted string when a pack argument is tainted" do
- ["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
- end
-
- it "does not return a tainted string when the array is tainted" do
- ["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
- end
-
- it "returns a tainted string when the format is tainted" do
- ["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
- end
-
- it "returns a tainted string when an empty format is tainted" do
- ["abcd", 0x20].pack("".taint).tainted?.should be_true
- end
-
- it "returns a untrusted string when the format is untrusted" do
- ["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
- end
-
- it "returns a untrusted string when the empty format is untrusted" do
- ["abcd", 0x20].pack("".untrust).untrusted?.should be_true
- end
-
- it "returns a untrusted string when a pack argument is untrusted" do
- ["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
- end
-
- it "returns a trusted string when the array is untrusted" do
- ["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
- end
- end
end
diff --git a/spec/ruby/core/array/pack/shared/unicode.rb b/spec/ruby/core/array/pack/shared/unicode.rb
index dd0f8b38aa..130c447bb7 100644
--- a/spec/ruby/core/array/pack/shared/unicode.rb
+++ b/spec/ruby/core/array/pack/shared/unicode.rb
@@ -67,8 +67,18 @@ describe :array_pack_unicode, shared: true do
-> { [obj].pack("U") }.should raise_error(TypeError)
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack("U\x00U").should == "\x01\x02"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [1, 2, 3].pack("U\x00U").should == "\x01\x02"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack("U\x00U")
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb
index fe969cbb2d..b20093a647 100644
--- a/spec/ruby/core/array/pack/u_spec.rb
+++ b/spec/ruby/core/array/pack/u_spec.rb
@@ -18,6 +18,16 @@ describe "Array#pack with format 'u'" do
it_behaves_like :array_pack_arguments, 'u'
it_behaves_like :array_pack_taint, 'u'
+ it "calls #to_str to convert an Object to a String" do
+ obj = mock("pack u string")
+ obj.should_receive(:to_str).and_return("``abcdef")
+ [obj].pack("u*").should == "(8&!A8F-D968`\n"
+ end
+
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('u') }.should raise_error(TypeError)
+ end
+
it "encodes an empty string as an empty string" do
[""].pack("u").should == ""
end
diff --git a/spec/ruby/core/array/pack/w_spec.rb b/spec/ruby/core/array/pack/w_spec.rb
index 439fa02198..e241d1519c 100644
--- a/spec/ruby/core/array/pack/w_spec.rb
+++ b/spec/ruby/core/array/pack/w_spec.rb
@@ -24,8 +24,18 @@ describe "Array#pack with format 'w'" do
[obj].pack("w").should == "\x05"
end
- it "ignores NULL bytes between directives" do
- [1, 2, 3].pack("w\x00w").should == "\x01\x02"
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ [1, 2, 3].pack("w\x00w").should == "\x01\x02"
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ [1, 2, 3].pack("w\x00w")
+ }.should raise_error(ArgumentError, /unknown pack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/array/pack/x_spec.rb b/spec/ruby/core/array/pack/x_spec.rb
index a28dd0bf21..86c3ad1aa4 100644
--- a/spec/ruby/core/array/pack/x_spec.rb
+++ b/spec/ruby/core/array/pack/x_spec.rb
@@ -30,6 +30,7 @@ describe "Array#pack with format 'x'" do
it "does not add a NULL byte when passed the '*' modifier" do
[].pack("x*").should == ""
+ [1, 2].pack("Cx*C").should == "\x01\x02"
end
end
diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb
index 82ce7b4a1c..5ad3afd69e 100644
--- a/spec/ruby/core/array/pack/z_spec.rb
+++ b/spec/ruby/core/array/pack/z_spec.rb
@@ -12,6 +12,16 @@ describe "Array#pack with format 'Z'" do
it_behaves_like :array_pack_string, 'Z'
it_behaves_like :array_pack_taint, 'Z'
+ it "calls #to_str to convert an Object to a String" do
+ obj = mock("pack Z string")
+ obj.should_receive(:to_str).and_return("``abcdef")
+ [obj].pack("Z*").should == "``abcdef\x00"
+ end
+
+ it "will not implicitly convert a number to a string" do
+ -> { [0].pack('Z') }.should raise_error(TypeError)
+ end
+
it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do
["abc"].pack("Z*").should == "abc\x00"
end
diff --git a/spec/ruby/core/array/plus_spec.rb b/spec/ruby/core/array/plus_spec.rb
index 45f8438208..3962b05c39 100644
--- a/spec/ruby/core/array/plus_spec.rb
+++ b/spec/ruby/core/array/plus_spec.rb
@@ -40,20 +40,4 @@ describe "Array#+" do
it "does not call to_ary on array subclasses" do
([5, 6] + ArraySpecs::ToAryArray[1, 2]).should == [5, 6, 1, 2]
end
-
- ruby_version_is ''...'2.7' do
- it "does not get infected even if an original array is tainted" do
- ([1, 2] + [3, 4]).tainted?.should be_false
- ([1, 2].taint + [3, 4]).tainted?.should be_false
- ([1, 2] + [3, 4].taint).tainted?.should be_false
- ([1, 2].taint + [3, 4].taint).tainted?.should be_false
- end
-
- it "does not infected even if an original array is untrusted" do
- ([1, 2] + [3, 4]).untrusted?.should be_false
- ([1, 2].untrust + [3, 4]).untrusted?.should be_false
- ([1, 2] + [3, 4].untrust).untrusted?.should be_false
- ([1, 2].untrust + [3, 4].untrust).untrusted?.should be_false
- end
- end
end
diff --git a/spec/ruby/core/array/pop_spec.rb b/spec/ruby/core/array/pop_spec.rb
index 96ef78da32..2a19408660 100644
--- a/spec/ruby/core/array/pop_spec.rb
+++ b/spec/ruby/core/array/pop_spec.rb
@@ -30,16 +30,6 @@ describe "Array#pop" do
array.pop.should == [1, 'two', 3.0, array, array, array, array]
end
- ruby_version_is ''...'2.7' do
- it "keeps taint status" do
- a = [1, 2].taint
- a.pop
- a.tainted?.should be_true
- a.pop
- a.tainted?.should be_true
- end
- end
-
it "raises a FrozenError on a frozen array" do
-> { ArraySpecs.frozen_array.pop }.should raise_error(FrozenError)
end
@@ -48,16 +38,6 @@ describe "Array#pop" do
-> { ArraySpecs.empty_frozen_array.pop }.should raise_error(FrozenError)
end
- ruby_version_is ''...'2.7' do
- it "keeps untrusted status" do
- a = [1, 2].untrust
- a.pop
- a.untrusted?.should be_true
- a.pop
- a.untrusted?.should be_true
- end
- end
-
describe "passed a number n as an argument" do
it "removes and returns an array with the last n elements of the array" do
a = [1, 2, 3, 4, 5, 6]
@@ -136,41 +116,9 @@ describe "Array#pop" do
ArraySpecs::MyArray[1, 2, 3].pop(2).should be_an_instance_of(Array)
end
- ruby_version_is ''...'2.7' do
- it "returns an untainted array even if the array is tainted" do
- ary = [1, 2].taint
- ary.pop(2).tainted?.should be_false
- ary.pop(0).tainted?.should be_false
- end
-
- it "keeps taint status" do
- a = [1, 2].taint
- a.pop(2)
- a.tainted?.should be_true
- a.pop(2)
- a.tainted?.should be_true
- end
-
- it "returns a trusted array even if the array is untrusted" do
- ary = [1, 2].untrust
- ary.pop(2).untrusted?.should be_false
- ary.pop(0).untrusted?.should be_false
- end
- end
-
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
- it "keeps untrusted status" do
- a = [1, 2].untrust
- a.pop(2)
- a.untrusted?.should be_true
- a.pop(2)
- a.untrusted?.should be_true
- end
- end
end
end
diff --git a/spec/ruby/core/array/sample_spec.rb b/spec/ruby/core/array/sample_spec.rb
index 565d7ff7f9..5b3aac9aed 100644
--- a/spec/ruby/core/array/sample_spec.rb
+++ b/spec/ruby/core/array/sample_spec.rb
@@ -3,26 +3,32 @@ require_relative 'fixtures/classes'
describe "Array#sample" do
it "samples evenly" do
- ary = [0, 1, 2, 3]
- 3.times do |i|
- counts = [0, 0, 0, 0]
- 4000.times do
- counts[ary.sample(3)[i]] += 1
- end
- counts.each do |count|
- (800..1200).should include(count)
- end
- end
+ ArraySpecs.measure_sample_fairness(4, 1, 400)
+ ArraySpecs.measure_sample_fairness(4, 2, 400)
+ ArraySpecs.measure_sample_fairness(4, 3, 400)
+ ArraySpecs.measure_sample_fairness(40, 3, 400)
+ ArraySpecs.measure_sample_fairness(40, 4, 400)
+ ArraySpecs.measure_sample_fairness(40, 8, 400)
+ ArraySpecs.measure_sample_fairness(40, 16, 400)
+ ArraySpecs.measure_sample_fairness_large_sample_size(100, 80, 4000)
end
it "returns nil for an empty Array" do
[].sample.should be_nil
end
+ it "returns nil for an empty array when called without n and a Random is given" do
+ [].sample(random: Random.new(42)).should be_nil
+ end
+
it "returns a single value when not passed a count" do
[4].sample.should equal(4)
end
+ it "returns a single value when not passed a count and a Random is given" do
+ [4].sample(random: Random.new(42)).should equal(4)
+ end
+
it "returns an empty Array when passed zero" do
[4].sample(0).should == []
end
diff --git a/spec/ruby/core/array/shared/clone.rb b/spec/ruby/core/array/shared/clone.rb
index 3c17b1f10f..035b45ec99 100644
--- a/spec/ruby/core/array/shared/clone.rb
+++ b/spec/ruby/core/array/shared/clone.rb
@@ -17,28 +17,4 @@ describe :array_clone, shared: true do
b.should == a
b.__id__.should_not == a.__id__
end
-
- ruby_version_is ''...'2.7' do
- it "copies taint status from the original" do
- a = [1, 2, 3, 4]
- b = [1, 2, 3, 4]
- a.taint
- aa = a.send @method
- bb = b.send @method
-
- aa.should.tainted?
- bb.should_not.tainted?
- end
-
- it "copies untrusted status from the original" do
- a = [1, 2, 3, 4]
- b = [1, 2, 3, 4]
- a.untrust
- aa = a.send @method
- bb = b.send @method
-
- 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 d84432734a..8d75f7db9a 100644
--- a/spec/ruby/core/array/shared/collect.rb
+++ b/spec/ruby/core/array/shared/collect.rb
@@ -42,20 +42,6 @@ describe :array_collect, shared: true do
}.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "does not copy tainted status" do
- a = [1, 2, 3]
- a.taint
- a.send(@method){|x| x}.tainted?.should be_false
- end
-
- it "does not copy untrusted status" do
- a = [1, 2, 3]
- a.untrust
- a.send(@method){|x| x}.untrusted?.should be_false
- end
- end
-
before :all do
@object = [1, 2, 3, 4]
end
@@ -96,23 +82,6 @@ describe :array_collect_b, shared: true do
a.should == ["1!", "2!", "3!"]
end
- ruby_version_is ''...'2.7' do
- it "keeps tainted status" do
- a = [1, 2, 3]
- a.taint
- a.tainted?.should be_true
- a.send(@method){|x| x}
- a.tainted?.should be_true
- end
-
- it "keeps untrusted status" do
- a = [1, 2, 3]
- a.untrust
- a.send(@method){|x| x}
- a.untrusted?.should be_true
- end
- end
-
describe "when frozen" do
it "raises a FrozenError" do
-> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(FrozenError)
diff --git a/spec/ruby/core/array/shared/inspect.rb b/spec/ruby/core/array/shared/inspect.rb
index 736f8d946b..a2b43d4959 100644
--- a/spec/ruby/core/array/shared/inspect.rb
+++ b/spec/ruby/core/array/shared/inspect.rb
@@ -64,32 +64,6 @@ describe :array_inspect, shared: true do
ArraySpecs.empty_recursive_array.send(@method).should == "[[...]]"
end
- ruby_version_is ''...'2.7' do
- it "taints the result if the Array is non-empty and tainted" do
- [1, 2].taint.send(@method).tainted?.should be_true
- end
-
- it "does not taint the result if the Array is tainted but empty" do
- [].taint.send(@method).tainted?.should be_false
- end
-
- it "taints the result if an element is tainted" do
- ["str".taint].send(@method).tainted?.should be_true
- end
-
- it "untrusts the result if the Array is untrusted" do
- [1, 2].untrust.send(@method).untrusted?.should be_true
- end
-
- it "does not untrust the result if the Array is untrusted but empty" do
- [].untrust.send(@method).untrusted?.should be_false
- end
-
- it "untrusts the result if an element is untrusted" do
- ["str".untrust].send(@method).untrusted?.should be_true
- end
- end
-
describe "with encoding" do
before :each do
@default_external_encoding = Encoding.default_external
diff --git a/spec/ruby/core/array/shared/join.rb b/spec/ruby/core/array/shared/join.rb
index c443d9a628..507b13e3c8 100644
--- a/spec/ruby/core/array/shared/join.rb
+++ b/spec/ruby/core/array/shared/join.rb
@@ -58,36 +58,6 @@ describe :array_join_with_default_separator, shared: true do
-> { ArraySpecs.empty_recursive_array.send(@method) }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "taints the result if the Array is tainted and non-empty" do
- [1, 2].taint.send(@method).tainted?.should be_true
- end
-
- it "does not taint the result if the Array is tainted but empty" do
- [].taint.send(@method).tainted?.should be_false
- end
-
- it "taints the result if the result of coercing an element is tainted" do
- s = mock("taint")
- s.should_receive(:to_s).and_return("str".taint)
- [s].send(@method).tainted?.should be_true
- end
-
- it "untrusts the result if the Array is untrusted and non-empty" do
- [1, 2].untrust.send(@method).untrusted?.should be_true
- end
-
- it "does not untrust the result if the Array is untrusted but empty" do
- [].untrust.send(@method).untrusted?.should be_false
- end
-
- it "untrusts the result if the result of coercing an element is untrusted" do
- s = mock("untrust")
- s.should_receive(:to_s).and_return("str".untrust)
- [s].send(@method).untrusted?.should be_true
- end
- end
-
it "uses the first encoding when other strings are compatible" do
ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings
ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings
@@ -114,17 +84,16 @@ 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
+ 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
+ it "warns" do
+ -> { [].join }.should complain(/warning: \$, is set to non-nil value/)
+ -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/)
end
end
end
@@ -140,42 +109,4 @@ describe :array_join_with_string_separator, shared: true do
[1, [2, [3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6"
[1, [2, ArraySpecs::MyArray[3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6"
end
-
- ruby_version_is ''...'2.7' do
- describe "with a tainted separator" do
- before :each do
- @sep = ":".taint
- end
-
- it "does not taint the result if the array is empty" do
- [].send(@method, @sep).tainted?.should be_false
- end
-
- it "does not taint the result if the array has only one element" do
- [1].send(@method, @sep).tainted?.should be_false
- end
-
- it "taints the result if the array has two or more elements" do
- [1, 2].send(@method, @sep).tainted?.should be_true
- end
- end
-
- describe "with an untrusted separator" do
- before :each do
- @sep = ":".untrust
- end
-
- it "does not untrust the result if the array is empty" do
- [].send(@method, @sep).untrusted?.should be_false
- end
-
- it "does not untrust the result if the array has only one element" do
- [1].send(@method, @sep).untrusted?.should be_false
- end
-
- it "untrusts the result if the array has two or more elements" do
- [1, 2].send(@method, @sep).untrusted?.should be_true
- end
- end
- end
end
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb
index 19e1a3ee2b..8fb33738b9 100644
--- a/spec/ruby/core/array/shared/slice.rb
+++ b/spec/ruby/core/array/shared/slice.rb
@@ -517,8 +517,9 @@ describe :array_slice, shared: true do
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)
+ array = [1, 2, 3, 4, 5, 6]
+ -> { array.send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
+ -> { array.send(@method, 0..bignum_value) }.should raise_error(RangeError)
end
it "can accept endless ranges" do
@@ -533,26 +534,356 @@ describe :array_slice, shared: true do
a.send(@method, eval("(-9...)")).should == nil
end
- ruby_version_is "2.7" do
- it "can accept beginless ranges" do
- a = [0, 1, 2, 3, 4, 5]
- a.send(@method, eval("(..3)")).should == [0, 1, 2, 3]
- a.send(@method, eval("(...3)")).should == [0, 1, 2]
- a.send(@method, eval("(..-3)")).should == [0, 1, 2, 3]
- a.send(@method, eval("(...-3)")).should == [0, 1, 2]
- a.send(@method, eval("(..0)")).should == [0]
- a.send(@method, eval("(...0)")).should == []
- a.send(@method, eval("(..9)")).should == [0, 1, 2, 3, 4, 5]
- a.send(@method, eval("(...9)")).should == [0, 1, 2, 3, 4, 5]
- a.send(@method, eval("(..-9)")).should == []
- a.send(@method, eval("(...-9)")).should == []
+ ruby_version_is "3.0" do
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ before :each do
+ @array = [0, 1, 2, 3, 4, 5]
+ end
+
+ it "has endless range and positive steps" do
+ @array.send(@method, eval("(0..).step(1)")).should == [0, 1, 2, 3, 4, 5]
+ @array.send(@method, eval("(0..).step(2)")).should == [0, 2, 4]
+ @array.send(@method, eval("(0..).step(10)")).should == [0]
+
+ @array.send(@method, eval("(2..).step(1)")).should == [2, 3, 4, 5]
+ @array.send(@method, eval("(2..).step(2)")).should == [2, 4]
+ @array.send(@method, eval("(2..).step(10)")).should == [2]
+
+ @array.send(@method, eval("(-3..).step(1)")).should == [3, 4, 5]
+ @array.send(@method, eval("(-3..).step(2)")).should == [3, 5]
+ @array.send(@method, eval("(-3..).step(10)")).should == [3]
+ end
+
+ it "has beginless range and positive steps" do
+ # end with zero index
+ @array.send(@method, (..0).step(1)).should == [0]
+ @array.send(@method, (...0).step(1)).should == []
+
+ @array.send(@method, (..0).step(2)).should == [0]
+ @array.send(@method, (...0).step(2)).should == []
+
+ @array.send(@method, (..0).step(10)).should == [0]
+ @array.send(@method, (...0).step(10)).should == []
+
+ # end with positive index
+ @array.send(@method, (..3).step(1)).should == [0, 1, 2, 3]
+ @array.send(@method, (...3).step(1)).should == [0, 1, 2]
+
+ @array.send(@method, (..3).step(2)).should == [0, 2]
+ @array.send(@method, (...3).step(2)).should == [0, 2]
+
+ @array.send(@method, (..3).step(10)).should == [0]
+ @array.send(@method, (...3).step(10)).should == [0]
+
+ # end with negative index
+ @array.send(@method, (..-2).step(1)).should == [0, 1, 2, 3, 4,]
+ @array.send(@method, (...-2).step(1)).should == [0, 1, 2, 3]
+
+ @array.send(@method, (..-2).step(2)).should == [0, 2, 4]
+ @array.send(@method, (...-2).step(2)).should == [0, 2]
+
+ @array.send(@method, (..-2).step(10)).should == [0]
+ @array.send(@method, (...-2).step(10)).should == [0]
+ end
+
+ it "has endless range and negative steps" do
+ @array.send(@method, eval("(0..).step(-1)")).should == [0]
+ @array.send(@method, eval("(0..).step(-2)")).should == [0]
+ @array.send(@method, eval("(0..).step(-10)")).should == [0]
+
+ @array.send(@method, eval("(2..).step(-1)")).should == [2, 1, 0]
+ @array.send(@method, eval("(2..).step(-2)")).should == [2, 0]
+
+ @array.send(@method, eval("(-3..).step(-1)")).should == [3, 2, 1, 0]
+ @array.send(@method, eval("(-3..).step(-2)")).should == [3, 1]
+ end
+
+ it "has closed range and positive steps" do
+ # start and end with 0
+ @array.send(@method, eval("(0..0).step(1)")).should == [0]
+ @array.send(@method, eval("(0...0).step(1)")).should == []
+
+ @array.send(@method, eval("(0..0).step(2)")).should == [0]
+ @array.send(@method, eval("(0...0).step(2)")).should == []
+
+ @array.send(@method, eval("(0..0).step(10)")).should == [0]
+ @array.send(@method, eval("(0...0).step(10)")).should == []
+
+ # start and end with positive index
+ @array.send(@method, eval("(1..3).step(1)")).should == [1, 2, 3]
+ @array.send(@method, eval("(1...3).step(1)")).should == [1, 2]
+
+ @array.send(@method, eval("(1..3).step(2)")).should == [1, 3]
+ @array.send(@method, eval("(1...3).step(2)")).should == [1]
+
+ @array.send(@method, eval("(1..3).step(10)")).should == [1]
+ @array.send(@method, eval("(1...3).step(10)")).should == [1]
+
+ # start with positive index, end with negative index
+ @array.send(@method, eval("(1..-2).step(1)")).should == [1, 2, 3, 4]
+ @array.send(@method, eval("(1...-2).step(1)")).should == [1, 2, 3]
+
+ @array.send(@method, eval("(1..-2).step(2)")).should == [1, 3]
+ @array.send(@method, eval("(1...-2).step(2)")).should == [1, 3]
+
+ @array.send(@method, eval("(1..-2).step(10)")).should == [1]
+ @array.send(@method, eval("(1...-2).step(10)")).should == [1]
+
+ # start with negative index, end with positive index
+ @array.send(@method, eval("(-4..4).step(1)")).should == [2, 3, 4]
+ @array.send(@method, eval("(-4...4).step(1)")).should == [2, 3]
+
+ @array.send(@method, eval("(-4..4).step(2)")).should == [2, 4]
+ @array.send(@method, eval("(-4...4).step(2)")).should == [2]
+
+ @array.send(@method, eval("(-4..4).step(10)")).should == [2]
+ @array.send(@method, eval("(-4...4).step(10)")).should == [2]
+
+ # start with negative index, end with negative index
+ @array.send(@method, eval("(-4..-2).step(1)")).should == [2, 3, 4]
+ @array.send(@method, eval("(-4...-2).step(1)")).should == [2, 3]
+
+ @array.send(@method, eval("(-4..-2).step(2)")).should == [2, 4]
+ @array.send(@method, eval("(-4...-2).step(2)")).should == [2]
+
+ @array.send(@method, eval("(-4..-2).step(10)")).should == [2]
+ @array.send(@method, eval("(-4...-2).step(10)")).should == [2]
+ end
+
+ it "has closed range and negative steps" do
+ # start and end with 0
+ @array.send(@method, eval("(0..0).step(-1)")).should == [0]
+ @array.send(@method, eval("(0...0).step(-1)")).should == []
+
+ @array.send(@method, eval("(0..0).step(-2)")).should == [0]
+ @array.send(@method, eval("(0...0).step(-2)")).should == []
+
+ @array.send(@method, eval("(0..0).step(-10)")).should == [0]
+ @array.send(@method, eval("(0...0).step(-10)")).should == []
+
+ # start and end with positive index
+ @array.send(@method, eval("(1..3).step(-1)")).should == []
+ @array.send(@method, eval("(1...3).step(-1)")).should == []
+
+ @array.send(@method, eval("(1..3).step(-2)")).should == []
+ @array.send(@method, eval("(1...3).step(-2)")).should == []
+
+ @array.send(@method, eval("(1..3).step(-10)")).should == []
+ @array.send(@method, eval("(1...3).step(-10)")).should == []
+
+ # start with positive index, end with negative index
+ @array.send(@method, eval("(1..-2).step(-1)")).should == []
+ @array.send(@method, eval("(1...-2).step(-1)")).should == []
+
+ @array.send(@method, eval("(1..-2).step(-2)")).should == []
+ @array.send(@method, eval("(1...-2).step(-2)")).should == []
+
+ @array.send(@method, eval("(1..-2).step(-10)")).should == []
+ @array.send(@method, eval("(1...-2).step(-10)")).should == []
+
+ # start with negative index, end with positive index
+ @array.send(@method, eval("(-4..4).step(-1)")).should == []
+ @array.send(@method, eval("(-4...4).step(-1)")).should == []
+
+ @array.send(@method, eval("(-4..4).step(-2)")).should == []
+ @array.send(@method, eval("(-4...4).step(-2)")).should == []
+
+ @array.send(@method, eval("(-4..4).step(-10)")).should == []
+ @array.send(@method, eval("(-4...4).step(-10)")).should == []
+
+ # start with negative index, end with negative index
+ @array.send(@method, eval("(-4..-2).step(-1)")).should == []
+ @array.send(@method, eval("(-4...-2).step(-1)")).should == []
+
+ @array.send(@method, eval("(-4..-2).step(-2)")).should == []
+ @array.send(@method, eval("(-4...-2).step(-2)")).should == []
+
+ @array.send(@method, eval("(-4..-2).step(-10)")).should == []
+ @array.send(@method, eval("(-4...-2).step(-10)")).should == []
+ end
+
+ it "has inverted closed range and positive steps" do
+ # start and end with positive index
+ @array.send(@method, eval("(3..1).step(1)")).should == []
+ @array.send(@method, eval("(3...1).step(1)")).should == []
+
+ @array.send(@method, eval("(3..1).step(2)")).should == []
+ @array.send(@method, eval("(3...1).step(2)")).should == []
+
+ @array.send(@method, eval("(3..1).step(10)")).should == []
+ @array.send(@method, eval("(3...1).step(10)")).should == []
+
+ # start with negative index, end with positive index
+ @array.send(@method, eval("(-2..1).step(1)")).should == []
+ @array.send(@method, eval("(-2...1).step(1)")).should == []
+
+ @array.send(@method, eval("(-2..1).step(2)")).should == []
+ @array.send(@method, eval("(-2...1).step(2)")).should == []
+
+ @array.send(@method, eval("(-2..1).step(10)")).should == []
+ @array.send(@method, eval("(-2...1).step(10)")).should == []
+
+ # start with positive index, end with negative index
+ @array.send(@method, eval("(4..-4).step(1)")).should == []
+ @array.send(@method, eval("(4...-4).step(1)")).should == []
+
+ @array.send(@method, eval("(4..-4).step(2)")).should == []
+ @array.send(@method, eval("(4...-4).step(2)")).should == []
+
+ @array.send(@method, eval("(4..-4).step(10)")).should == []
+ @array.send(@method, eval("(4...-4).step(10)")).should == []
+
+ # start with negative index, end with negative index
+ @array.send(@method, eval("(-2..-4).step(1)")).should == []
+ @array.send(@method, eval("(-2...-4).step(1)")).should == []
+
+ @array.send(@method, eval("(-2..-4).step(2)")).should == []
+ @array.send(@method, eval("(-2...-4).step(2)")).should == []
+
+ @array.send(@method, eval("(-2..-4).step(10)")).should == []
+ @array.send(@method, eval("(-2...-4).step(10)")).should == []
+ end
+
+ it "has range with bounds outside of array" do
+ # end is equal to array's length
+ @array.send(@method, (0..6).step(1)).should == [0, 1, 2, 3, 4, 5]
+ -> { @array.send(@method, (0..6).step(2)) }.should raise_error(RangeError)
+
+ # end is greater than length with positive steps
+ @array.send(@method, (1..6).step(2)).should == [1, 3, 5]
+ @array.send(@method, (2..7).step(2)).should == [2, 4]
+ -> { @array.send(@method, (2..8).step(2)) }.should raise_error(RangeError)
+
+ # begin is greater than length with negative steps
+ @array.send(@method, (6..1).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (7..2).step(-2)).should == [5, 3]
+ -> { @array.send(@method, (8..2).step(-2)) }.should raise_error(RangeError)
+ end
+
+ it "has endless range with start outside of array's bounds" do
+ @array.send(@method, eval("(6..).step(1)")).should == []
+ @array.send(@method, eval("(7..).step(1)")).should == nil
+
+ @array.send(@method, eval("(6..).step(2)")).should == []
+ -> { @array.send(@method, eval("(7..).step(2)")) }.should raise_error(RangeError)
+ end
end
+ end
- it "can accept nil...nil ranges" do
- a = [0, 1, 2, 3, 4, 5]
- a.send(@method, eval("(nil...nil)")).should == a
- a.send(@method, eval("(...nil)")).should == a
- a.send(@method, eval("(nil..)")).should == a
+ it "can accept beginless ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a.send(@method, (..3)).should == [0, 1, 2, 3]
+ a.send(@method, (...3)).should == [0, 1, 2]
+ a.send(@method, (..-3)).should == [0, 1, 2, 3]
+ a.send(@method, (...-3)).should == [0, 1, 2]
+ a.send(@method, (..0)).should == [0]
+ a.send(@method, (...0)).should == []
+ a.send(@method, (..9)).should == [0, 1, 2, 3, 4, 5]
+ a.send(@method, (...9)).should == [0, 1, 2, 3, 4, 5]
+ a.send(@method, (..-9)).should == []
+ a.send(@method, (...-9)).should == []
+ end
+
+ ruby_version_is "3.2" do
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ it "with infinite/inverted ranges and negative steps" do
+ @array = [0, 1, 2, 3, 4, 5]
+ @array.send(@method, (2..).step(-1)).should == [2, 1, 0]
+ @array.send(@method, (2..).step(-2)).should == [2, 0]
+ @array.send(@method, (2..).step(-3)).should == [2]
+ @array.send(@method, (2..).step(-4)).should == [2]
+
+ @array.send(@method, (-3..).step(-1)).should == [3, 2, 1, 0]
+ @array.send(@method, (-3..).step(-2)).should == [3, 1]
+ @array.send(@method, (-3..).step(-3)).should == [3, 0]
+ @array.send(@method, (-3..).step(-4)).should == [3]
+ @array.send(@method, (-3..).step(-5)).should == [3]
+
+ @array.send(@method, (..0).step(-1)).should == [5, 4, 3, 2, 1, 0]
+ @array.send(@method, (..0).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (..0).step(-3)).should == [5, 2]
+ @array.send(@method, (..0).step(-4)).should == [5, 1]
+ @array.send(@method, (..0).step(-5)).should == [5, 0]
+ @array.send(@method, (..0).step(-6)).should == [5]
+ @array.send(@method, (..0).step(-7)).should == [5]
+
+ @array.send(@method, (...0).step(-1)).should == [5, 4, 3, 2, 1]
+ @array.send(@method, (...0).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (...0).step(-3)).should == [5, 2]
+ @array.send(@method, (...0).step(-4)).should == [5, 1]
+ @array.send(@method, (...0).step(-5)).should == [5]
+ @array.send(@method, (...0).step(-6)).should == [5]
+
+ @array.send(@method, (...1).step(-1)).should == [5, 4, 3, 2]
+ @array.send(@method, (...1).step(-2)).should == [5, 3]
+ @array.send(@method, (...1).step(-3)).should == [5, 2]
+ @array.send(@method, (...1).step(-4)).should == [5]
+ @array.send(@method, (...1).step(-5)).should == [5]
+
+ @array.send(@method, (..-5).step(-1)).should == [5, 4, 3, 2, 1]
+ @array.send(@method, (..-5).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (..-5).step(-3)).should == [5, 2]
+ @array.send(@method, (..-5).step(-4)).should == [5, 1]
+ @array.send(@method, (..-5).step(-5)).should == [5]
+ @array.send(@method, (..-5).step(-6)).should == [5]
+
+ @array.send(@method, (...-5).step(-1)).should == [5, 4, 3, 2]
+ @array.send(@method, (...-5).step(-2)).should == [5, 3]
+ @array.send(@method, (...-5).step(-3)).should == [5, 2]
+ @array.send(@method, (...-5).step(-4)).should == [5]
+ @array.send(@method, (...-5).step(-5)).should == [5]
+
+ @array.send(@method, (4..1).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (4..1).step(-2)).should == [4, 2]
+ @array.send(@method, (4..1).step(-3)).should == [4, 1]
+ @array.send(@method, (4..1).step(-4)).should == [4]
+ @array.send(@method, (4..1).step(-5)).should == [4]
+
+ @array.send(@method, (4...1).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (4...1).step(-2)).should == [4, 2]
+ @array.send(@method, (4...1).step(-3)).should == [4]
+ @array.send(@method, (4...1).step(-4)).should == [4]
+
+ @array.send(@method, (-2..1).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (-2..1).step(-2)).should == [4, 2]
+ @array.send(@method, (-2..1).step(-3)).should == [4, 1]
+ @array.send(@method, (-2..1).step(-4)).should == [4]
+ @array.send(@method, (-2..1).step(-5)).should == [4]
+
+ @array.send(@method, (-2...1).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (-2...1).step(-2)).should == [4, 2]
+ @array.send(@method, (-2...1).step(-3)).should == [4]
+ @array.send(@method, (-2...1).step(-4)).should == [4]
+
+ @array.send(@method, (4..-5).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (4..-5).step(-2)).should == [4, 2]
+ @array.send(@method, (4..-5).step(-3)).should == [4, 1]
+ @array.send(@method, (4..-5).step(-4)).should == [4]
+ @array.send(@method, (4..-5).step(-5)).should == [4]
+
+ @array.send(@method, (4...-5).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (4...-5).step(-2)).should == [4, 2]
+ @array.send(@method, (4...-5).step(-3)).should == [4]
+ @array.send(@method, (4...-5).step(-4)).should == [4]
+
+ @array.send(@method, (-2..-5).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (-2..-5).step(-2)).should == [4, 2]
+ @array.send(@method, (-2..-5).step(-3)).should == [4, 1]
+ @array.send(@method, (-2..-5).step(-4)).should == [4]
+ @array.send(@method, (-2..-5).step(-5)).should == [4]
+
+ @array.send(@method, (-2...-5).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (-2...-5).step(-2)).should == [4, 2]
+ @array.send(@method, (-2...-5).step(-3)).should == [4]
+ @array.send(@method, (-2...-5).step(-4)).should == [4]
+ end
end
end
+
+ it "can accept nil...nil ranges" do
+ a = [0, 1, 2, 3, 4, 5]
+ a.send(@method, eval("(nil...nil)")).should == a
+ a.send(@method, (...nil)).should == a
+ a.send(@method, eval("(nil..)")).should == a
+ end
end
diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb
index fc82e19e2a..4941e098f6 100644
--- a/spec/ruby/core/array/shared/unshift.rb
+++ b/spec/ruby/core/array/shared/unshift.rb
@@ -22,6 +22,11 @@ describe :array_unshift, shared: true do
a.should == [3, 4]
end
+ it "returns self" do
+ a = [1, 2, 3]
+ a.send(@method, "a").should.equal?(a)
+ end
+
it "quietly ignores unshifting nothing" do
[].send(@method).should == []
end
@@ -43,4 +48,17 @@ describe :array_unshift, shared: true do
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
+
+ # https://github.com/oracle/truffleruby/issues/2772
+ it "doesn't rely on Array#[]= so it can be overridden" do
+ subclass = Class.new(Array) do
+ def []=(*)
+ raise "[]= is called"
+ end
+ end
+
+ array = subclass.new
+ array.send(@method, 1)
+ array.should == [1]
+ end
end
diff --git a/spec/ruby/core/array/shift_spec.rb b/spec/ruby/core/array/shift_spec.rb
index b998e45d28..6b4ef39f77 100644
--- a/spec/ruby/core/array/shift_spec.rb
+++ b/spec/ruby/core/array/shift_spec.rb
@@ -116,21 +116,5 @@ describe "Array#shift" do
it "does not return subclass instances with Array subclass" do
ArraySpecs::MyArray[1, 2, 3].shift(2).should be_an_instance_of(Array)
end
-
- ruby_version_is ''...'2.7' do
- it "returns an untainted array even if the array is tainted" do
- ary = [1, 2].taint
- ary.shift(2).tainted?.should be_false
- ary.shift(0).tainted?.should be_false
- end
-
- it "keeps taint status" do
- a = [1, 2].taint
- a.shift(2)
- a.tainted?.should be_true
- a.shift(2)
- a.tainted?.should be_true
- end
- end
end
end
diff --git a/spec/ruby/core/array/slice_spec.rb b/spec/ruby/core/array/slice_spec.rb
index 8c276f9084..8e1499855a 100644
--- a/spec/ruby/core/array/slice_spec.rb
+++ b/spec/ruby/core/array/slice_spec.rb
@@ -172,16 +172,14 @@ describe "Array#slice!" do
a.should == [1, 2]
end
- ruby_version_is "2.7" do
- it "works with beginless ranges" do
- a = [0,1,2,3,4]
- a.slice!(eval("(..3)")).should == [0, 1, 2, 3]
- a.should == [4]
-
- a = [0,1,2,3,4]
- a.slice!(eval("(...-2)")).should == [0, 1, 2]
- a.should == [3, 4]
- end
+ it "works with beginless ranges" do
+ a = [0,1,2,3,4]
+ a.slice!((..3)).should == [0, 1, 2, 3]
+ a.should == [4]
+
+ a = [0,1,2,3,4]
+ a.slice!((...-2)).should == [0, 1, 2]
+ a.should == [3, 4]
end
describe "with a subclass of Array" do
diff --git a/spec/ruby/core/array/sum_spec.rb b/spec/ruby/core/array/sum_spec.rb
index 39c769d328..8ca8353a67 100644
--- a/spec/ruby/core/array/sum_spec.rb
+++ b/spec/ruby/core/array/sum_spec.rb
@@ -9,6 +9,35 @@ describe "Array#sum" do
[1, 2, 3].sum { |i| i * 10 }.should == 60
end
+ # https://bugs.ruby-lang.org/issues/12217
+ # https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214
+ it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do
+ floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5]
+ naive_sum = floats.reduce { |sum, e| sum + e }
+ naive_sum.should == 50.00000000000001
+ floats.sum.should == 50.0
+ end
+
+ it "handles infinite values and NaN" do
+ [1.0, Float::INFINITY].sum.should == Float::INFINITY
+ [1.0, -Float::INFINITY].sum.should == -Float::INFINITY
+ [1.0, Float::NAN].sum.should.nan?
+
+ [Float::INFINITY, 1.0].sum.should == Float::INFINITY
+ [-Float::INFINITY, 1.0].sum.should == -Float::INFINITY
+ [Float::NAN, 1.0].sum.should.nan?
+
+ [Float::NAN, Float::INFINITY].sum.should.nan?
+ [Float::INFINITY, Float::NAN].sum.should.nan?
+
+ [Float::INFINITY, -Float::INFINITY].sum.should.nan?
+ [-Float::INFINITY, Float::INFINITY].sum.should.nan?
+
+ [Float::INFINITY, Float::INFINITY].sum.should == Float::INFINITY
+ [-Float::INFINITY, -Float::INFINITY].sum.should == -Float::INFINITY
+ [Float::NAN, Float::NAN].sum.should.nan?
+ end
+
it "returns init value if array is empty" do
[].sum(-1).should == -1
end
diff --git a/spec/ruby/core/array/uniq_spec.rb b/spec/ruby/core/array/uniq_spec.rb
index 5911c23e6a..4461cae16b 100644
--- a/spec/ruby/core/array/uniq_spec.rb
+++ b/spec/ruby/core/array/uniq_spec.rb
@@ -39,76 +39,32 @@ describe "Array#uniq" do
[x, y].uniq.should == [x, y]
end
- ruby_version_is '2.7' do
- it "compares elements with matching hash codes with #eql?" do
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- false
- end
-
- obj
- end
-
- a.uniq.should == a
+ it "compares elements with matching hash codes with #eql?" do
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- true
- end
-
- obj
+ def obj.eql?(o)
+ false
end
- a.uniq.size.should == 1
+ obj
end
- end
- ruby_version_is ''...'2.7' do
- it "compares elements with matching hash codes with #eql?" do
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- taint
- o.taint
- false
- end
-
- obj
- end
-
- a.uniq.should == a
- a[0].should.tainted?
- a[1].should.tainted?
+ a.uniq.should == a
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
- def obj.eql?(o)
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- taint
- o.taint
- true
- end
-
- obj
+ def obj.eql?(o)
+ true
end
- a.uniq.size.should == 1
- a[0].should.tainted?
- a[1].should.tainted?
+ obj
end
+
+ a.uniq.size.should == 1
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 f1522e0bfe..e85bbee400 100644
--- a/spec/ruby/core/array/values_at_spec.rb
+++ b/spec/ruby/core/array/values_at_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+# Should be synchronized with core/struct/values_at_spec.rb
describe "Array#values_at" do
it "returns an array of elements at the indexes when passed indexes" do
[1, 2, 3, 4, 5].values_at().should == []
@@ -66,10 +67,8 @@ describe "Array#values_at" do
[1, 2, 3, 4].values_at(eval("(3...)")).should == [4]
end
- ruby_version_is "2.7" do
- it "works when given beginless ranges" do
- [1, 2, 3, 4].values_at(eval("(..2)")).should == [1, 2, 3]
- [1, 2, 3, 4].values_at(eval("(...2)")).should == [1, 2]
- end
+ it "works when given beginless ranges" do
+ [1, 2, 3, 4].values_at((..2)).should == [1, 2, 3]
+ [1, 2, 3, 4].values_at((...2)).should == [1, 2]
end
end
diff --git a/spec/ruby/core/array/zip_spec.rb b/spec/ruby/core/array/zip_spec.rb
index af4013debe..2a0f64cb49 100644
--- a/spec/ruby/core/array/zip_spec.rb
+++ b/spec/ruby/core/array/zip_spec.rb
@@ -62,4 +62,10 @@ describe "Array#zip" do
it "does not return subclass instance on Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should be_an_instance_of(Array)
end
+
+ it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
+ -> { [1, 2, 3].zip(Object.new) }.should raise_error(TypeError, "wrong argument type Object (must respond to :each)")
+ -> { [1, 2, 3].zip(1) }.should raise_error(TypeError, "wrong argument type Integer (must respond to :each)")
+ -> { [1, 2, 3].zip(true) }.should raise_error(TypeError, "wrong argument type TrueClass (must respond to :each)")
+ end
end
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
index b6a146095d..350b08a30e 100644
--- a/spec/ruby/core/basicobject/instance_eval_spec.rb
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -20,12 +20,18 @@ describe "BasicObject#instance_eval" do
a.instance_eval('self').equal?(a).should be_true
end
- it "expects a block with no arguments" do
- -> { "hola".instance_eval }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when no arguments and no block are given" do
+ -> { "hola".instance_eval }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1..3)")
end
- it "takes no arguments with a block" do
- -> { "hola".instance_eval(4, 5) {|a,b| a + b } }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when a block and normal arguments are given" do
+ -> { "hola".instance_eval(4, 5) {|a,b| a + b } }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+
+ it "raises an ArgumentError when more than 3 arguments are given" do
+ -> {
+ "hola".instance_eval("1 + 1", "some file", 0, "bogus")
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "yields the object to the block" do
@@ -185,4 +191,58 @@ end
x.should == :value
end
+
+ it "converts string argument with #to_str method" do
+ source_code = Object.new
+ def source_code.to_str() "1" end
+
+ a = BasicObject.new
+ a.instance_eval(source_code).should == 1
+ end
+
+ it "raises ArgumentError if returned value is not String" do
+ source_code = Object.new
+ def source_code.to_str() :symbol end
+
+ a = BasicObject.new
+ -> { a.instance_eval(source_code) }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+
+ it "converts filename argument with #to_str method" do
+ filename = Object.new
+ def filename.to_str() "file.rb" end
+
+ err = begin
+ Object.new.instance_eval("raise", filename)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[0].should == "file.rb"
+ end
+
+ it "raises ArgumentError if returned value is not String" do
+ filename = Object.new
+ def filename.to_str() :symbol end
+
+ -> { Object.new.instance_eval("raise", filename) }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+
+ it "converts lineno argument with #to_int method" do
+ lineno = Object.new
+ def lineno.to_int() 15 end
+
+ err = begin
+ Object.new.instance_eval("raise", "file.rb", lineno)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[1].should == "15"
+ end
+
+ it "raises ArgumentError if returned value is not Integer" do
+ lineno = Object.new
+ def lineno.to_int() :symbol end
+
+ -> { Object.new.instance_eval("raise", "file.rb", lineno) }.should raise_error(TypeError, /can't convert Object to Integer/)
+ end
end
diff --git a/spec/ruby/core/binding/eval_spec.rb b/spec/ruby/core/binding/eval_spec.rb
index b36bec799e..4bb3da7a6c 100644
--- a/spec/ruby/core/binding/eval_spec.rb
+++ b/spec/ruby/core/binding/eval_spec.rb
@@ -93,16 +93,28 @@ describe "Binding#eval" 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
+ suppress_warning { bind.eval("__FILE__") }.should == obj.get_file_of_binding
+ end
+
+ it "inherits __LINE__ from the enclosing scope" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, line = obj.get_binding_and_line
+ suppress_warning { bind.eval("__LINE__") }.should == line
end
end
ruby_version_is "3.0" do
- it "Uses (eval) as __FILE__ if single argument given" 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
+
+ it "uses 1 as __LINE__" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ suppress_warning { bind.eval("__LINE__") }.should == 1
+ end
end
it "uses the __FILE__ that is passed in" do
diff --git a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
index 7c87a970d7..1960f5721f 100644
--- a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
+++ b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
@@ -34,12 +34,6 @@ 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
@@ -49,15 +43,7 @@ describe "RUBY_RELEASE_DATE" do
end
describe "RUBY_REVISION" do
- ruby_version_is ""..."2.7" do
- it "is an Integer" do
- RUBY_REVISION.should be_kind_of(Integer)
- end
- end
-
- ruby_version_is "2.7" do
- it "is a String" do
- RUBY_REVISION.should be_kind_of(String)
- end
+ it "is a String" do
+ RUBY_REVISION.should be_kind_of(String)
end
end
diff --git a/spec/ruby/core/class/attached_object_spec.rb b/spec/ruby/core/class/attached_object_spec.rb
new file mode 100644
index 0000000000..115d5fa563
--- /dev/null
+++ b/spec/ruby/core/class/attached_object_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../spec_helper'
+
+ruby_version_is '3.2' do
+ describe "Class#attached_object" do
+ it "returns the object that is attached to a singleton class" do
+ a = Class.new
+
+ a_obj = a.new
+ a_obj.singleton_class.attached_object.should == a_obj
+ end
+
+ it "returns the class object that is attached to a class's singleton class" do
+ a = Class.new
+ singleton_class = (class << a; self; end)
+
+ singleton_class.attached_object.should == a
+ end
+
+ it "raises TypeError if the class is not a singleton class" do
+ a = Class.new
+
+ -> { a.attached_object }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError for special singleton classes" do
+ -> { nil.singleton_class.attached_object }.should raise_error(TypeError)
+ -> { true.singleton_class.attached_object }.should raise_error(TypeError)
+ -> { false.singleton_class.attached_object }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/core/class/subclasses_spec.rb b/spec/ruby/core/class/subclasses_spec.rb
new file mode 100644
index 0000000000..a16b934d4f
--- /dev/null
+++ b/spec/ruby/core/class/subclasses_spec.rb
@@ -0,0 +1,60 @@
+require_relative '../../spec_helper'
+require_relative '../module/fixtures/classes'
+
+ruby_version_is '3.1' do
+ describe "Class#subclasses" do
+ it "returns a list of classes directly inheriting from self" do
+ assert_subclasses(ModuleSpecs::Parent, [ModuleSpecs::Child, ModuleSpecs::Child2])
+ end
+
+ it "does not return included modules" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
+
+ assert_subclasses(parent, [child])
+ end
+
+ it "does not return singleton classes" do
+ a = Class.new
+
+ a_obj = a.new
+ def a_obj.force_singleton_class
+ 42
+ end
+
+ a.subclasses.should_not include(a_obj.singleton_class)
+ end
+
+ it "has 1 entry per module or class" do
+ ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq
+ end
+
+ it "works when creating subclasses concurrently" do
+ t = 16
+ n = 1000
+ go = false
+ superclass = Class.new
+
+ threads = t.times.map do
+ Thread.new do
+ Thread.pass until go
+ n.times.map do
+ Class.new(superclass)
+ end
+ end
+ end
+
+ go = true
+ classes = threads.map(&:value)
+
+ superclass.subclasses.size.should == t * n
+ superclass.subclasses.each { |c| c.should be_kind_of(Class) }
+ end
+
+ def assert_subclasses(mod,subclasses)
+ mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect)
+ end
+ end
+end
diff --git a/spec/ruby/core/comparable/clamp_spec.rb b/spec/ruby/core/comparable/clamp_spec.rb
index 393496fc76..796d4a18c1 100644
--- a/spec/ruby/core/comparable/clamp_spec.rb
+++ b/spec/ruby/core/comparable/clamp_spec.rb
@@ -2,14 +2,6 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe 'Comparable#clamp' do
- ruby_version_is ""..."2.7" do
- it 'raises an Argument error unless given 2 parameters' do
- c = ComparableSpecs::Weird.new(0)
- -> { c.clamp(c) }.should raise_error(ArgumentError)
- -> { c.clamp(c, c, c) }.should raise_error(ArgumentError)
- end
- end
-
it 'raises an Argument error unless the 2 parameters are correctly ordered' do
one = ComparableSpecs::WithOnlyCompareDefined.new(1)
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
@@ -48,41 +40,39 @@ describe 'Comparable#clamp' do
c.clamp(one, two).should equal(two)
end
- ruby_version_is "2.7" do
- it 'returns self if within the given range parameters' do
- one = ComparableSpecs::WithOnlyCompareDefined.new(1)
- two = ComparableSpecs::WithOnlyCompareDefined.new(2)
- three = ComparableSpecs::WithOnlyCompareDefined.new(3)
- c = ComparableSpecs::Weird.new(2)
-
- c.clamp(one..two).should equal(c)
- c.clamp(two..two).should equal(c)
- c.clamp(one..three).should equal(c)
- c.clamp(two..three).should equal(c)
- end
-
- it 'returns the minimum value of the range parameters if smaller than it' do
- one = ComparableSpecs::WithOnlyCompareDefined.new(1)
- two = ComparableSpecs::WithOnlyCompareDefined.new(2)
- c = ComparableSpecs::Weird.new(0)
-
- c.clamp(one..two).should equal(one)
- end
-
- it 'returns the maximum value of the range parameters if greater than it' do
- one = ComparableSpecs::WithOnlyCompareDefined.new(1)
- two = ComparableSpecs::WithOnlyCompareDefined.new(2)
- c = ComparableSpecs::Weird.new(3)
-
- c.clamp(one..two).should equal(two)
- end
-
- it 'raises an Argument error if the range parameter is exclusive' do
- one = ComparableSpecs::WithOnlyCompareDefined.new(1)
- two = ComparableSpecs::WithOnlyCompareDefined.new(2)
- c = ComparableSpecs::Weird.new(3)
-
- -> { c.clamp(one...two) }.should raise_error(ArgumentError)
- end
+ it 'returns self if within the given range parameters' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ three = ComparableSpecs::WithOnlyCompareDefined.new(3)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one..two).should equal(c)
+ c.clamp(two..two).should equal(c)
+ c.clamp(one..three).should equal(c)
+ c.clamp(two..three).should equal(c)
+ end
+
+ it 'returns the minimum value of the range parameters if smaller than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(one..two).should equal(one)
+ end
+
+ it 'returns the maximum value of the range parameters if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(3)
+
+ c.clamp(one..two).should equal(two)
+ end
+
+ it 'raises an Argument error if the range parameter is exclusive' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(3)
+
+ -> { c.clamp(one...two) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/complex/comparision_spec.rb b/spec/ruby/core/complex/comparision_spec.rb
deleted file mode 100644
index 2a437afb71..0000000000
--- a/spec/ruby/core/complex/comparision_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/comparison_spec.rb b/spec/ruby/core/complex/comparison_spec.rb
new file mode 100644
index 0000000000..3a3142f234
--- /dev/null
+++ b/spec/ruby/core/complex/comparison_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+describe "Complex#<=>" 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
diff --git a/spec/ruby/core/complex/polar_spec.rb b/spec/ruby/core/complex/polar_spec.rb
index 2a5d8ebd69..3bb3751bc6 100644
--- a/spec/ruby/core/complex/polar_spec.rb
+++ b/spec/ruby/core/complex/polar_spec.rb
@@ -10,6 +10,22 @@ describe "Complex.polar" do
->{ Complex.polar(nil) }.should raise_error(TypeError)
->{ Complex.polar(nil, nil) }.should raise_error(TypeError)
end
+
+ ruby_bug "#19004", ""..."3.2" do
+ it "computes the real values of the real & imaginary parts from the polar form" do
+ a = Complex.polar(1.0+0.0i, Math::PI/2+0.0i)
+ a.real.should be_close(0.0, TOLERANCE)
+ a.imag.should be_close(1.0, TOLERANCE)
+ a.real.real?.should be_true
+ a.imag.real?.should be_true
+
+ b = Complex.polar(1+0.0i)
+ b.real.should be_close(1.0, TOLERANCE)
+ b.imag.should be_close(0.0, TOLERANCE)
+ b.real.real?.should be_true
+ b.imag.real?.should be_true
+ end
+ end
end
describe "Complex#polar" do
diff --git a/spec/ruby/library/conditionvariable/broadcast_spec.rb b/spec/ruby/core/conditionvariable/broadcast_spec.rb
index d88159df23..d88159df23 100644
--- a/spec/ruby/library/conditionvariable/broadcast_spec.rb
+++ b/spec/ruby/core/conditionvariable/broadcast_spec.rb
diff --git a/spec/ruby/library/conditionvariable/marshal_dump_spec.rb b/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
index f951a13e28..f951a13e28 100644
--- a/spec/ruby/library/conditionvariable/marshal_dump_spec.rb
+++ b/spec/ruby/core/conditionvariable/marshal_dump_spec.rb
diff --git a/spec/ruby/library/conditionvariable/signal_spec.rb b/spec/ruby/core/conditionvariable/signal_spec.rb
index 86383073f1..86383073f1 100644
--- a/spec/ruby/library/conditionvariable/signal_spec.rb
+++ b/spec/ruby/core/conditionvariable/signal_spec.rb
diff --git a/spec/ruby/library/conditionvariable/wait_spec.rb b/spec/ruby/core/conditionvariable/wait_spec.rb
index 9a68c2b5a1..9a68c2b5a1 100644
--- a/spec/ruby/library/conditionvariable/wait_spec.rb
+++ b/spec/ruby/core/conditionvariable/wait_spec.rb
diff --git a/spec/ruby/core/data/constants_spec.rb b/spec/ruby/core/data/constants_spec.rb
index 1d469f9237..d9d55b50f9 100644
--- a/spec/ruby/core/data/constants_spec.rb
+++ b/spec/ruby/core/data/constants_spec.rb
@@ -14,10 +14,22 @@ ruby_version_is ''...'3.0' do
end
end
-ruby_version_is '3.0' do
+ruby_version_is '3.0'...'3.2' do
describe "Data" do
it "does not exist anymore" do
Object.should_not have_constant(:Data)
end
end
end
+
+ruby_version_is '3.2' do
+ describe "Data" do
+ it "is a new constant" do
+ Data.superclass.should == Object
+ end
+
+ it "is not deprecated" do
+ -> { Data }.should_not complain
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 986c8f38c0..03698cc246 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -105,14 +105,6 @@ describe "Dir#children" do
dirs.each { |d| d.encoding.should == Encoding::UTF_8 }
end
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", nil)
- dirs = @dir.to_a.sort
- dirs.each { |d| d.encoding.should == Encoding.find("filesystem") }
- end
- end
-
it "returns children encoded with the 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.
diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index f7980991e5..520186e79e 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -15,13 +15,6 @@ describe "Dir.each_child" do
dirs.each {|dir| dir.encoding.should == Encoding::UTF_8}
end
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- dirs = Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")}
- end
- end
-
it "yields all names in an existing directory to the provided block" do
a, b = [], []
diff --git a/spec/ruby/core/dir/entries_spec.rb b/spec/ruby/core/dir/entries_spec.rb
index 9aa58657db..91c30fccae 100644
--- a/spec/ruby/core/dir/entries_spec.rb
+++ b/spec/ruby/core/dir/entries_spec.rb
@@ -40,13 +40,6 @@ describe "Dir.entries" do
dirs.each {|dir| dir.encoding.should == Encoding::UTF_8}
end
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- dirs = Dir.entries("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")}
- end
- end
-
it "returns entries encoded with the filesystem encoding by default" do
# This spec depends on the locale not being US-ASCII because if it is, the
# entries that are not ascii_only? will be BINARY encoded.
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb
index a1ea3db215..087f46b331 100644
--- a/spec/ruby/core/dir/fixtures/common.rb
+++ b/spec/ruby/core/dir/fixtures/common.rb
@@ -81,6 +81,8 @@ module DirSpecs
special/}
special/test{1}/file[1]
+ special/{}/special
+ special/test\ +()[]{}/hello_world.erb
]
platform_is_not :windows do
@@ -91,19 +93,39 @@ module DirSpecs
special/|
special/こんにちは.txt
+ special/\a
]
+ @mock_dir_files << "special/_\u{1f60e}.erb"
end
end
@mock_dir_files
end
+ def self.mock_dir_links
+ unless @mock_dir_links
+ @mock_dir_links = []
+ platform_is_not :windows do
+ @mock_dir_links += [
+ ['special/ln', 'subdir_one']
+ ]
+ end
+ end
+ @mock_dir_links
+ end
+
def self.create_mock_dirs
mock_dir_files.each do |name|
file = File.join mock_dir, name
mkdir_p File.dirname(file)
touch file
end
+ mock_dir_links.each do |link, target|
+ full_link = File.join mock_dir, link
+ full_target = File.join mock_dir, target
+
+ File.symlink full_target, full_link
+ end
end
def self.delete_mock_dirs
diff --git a/spec/ruby/core/dir/foreach_spec.rb b/spec/ruby/core/dir/foreach_spec.rb
index c3ddb27a84..9cf34b1d71 100644
--- a/spec/ruby/core/dir/foreach_spec.rb
+++ b/spec/ruby/core/dir/foreach_spec.rb
@@ -41,13 +41,13 @@ describe "Dir.foreach" do
it "accepts an encoding keyword for the encoding of the entries" do
dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding::UTF_8}
- end
+ dirs.each { |dir| dir.encoding.should == Encoding::UTF_8 }
+
+ dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: Encoding::ISO_8859_1).to_a.sort
+ dirs.each { |dir| dir.encoding.should == Encoding::ISO_8859_1 }
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")}
+ Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: Encoding::ISO_8859_1) do |f|
+ f.encoding.should == Encoding::ISO_8859_1
end
end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 6533c9b65a..06b52b90fb 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -79,7 +79,9 @@ describe "Dir.glob" do
nested/
nested/.dotsubir/
special/
+ special/test\ +()[]{}/
special/test{1}/
+ special/{}/
subdir_one/
subdir_two/
]
@@ -129,7 +131,9 @@ describe "Dir.glob" do
./nested/
./nested/.dotsubir/
./special/
+ ./special/test\ +()[]{}/
./special/test{1}/
+ ./special/{}/
./subdir_one/
./subdir_two/
]
@@ -220,5 +224,30 @@ describe "Dir.glob" do
Dir.rmdir('no_permission')
end
end
+
+ it "will follow symlinks when processing a `*/` pattern." do
+ expected = ['special/ln/nondotfile']
+ Dir.glob('special/*/nondotfile').should == expected
+ end
+
+ it "will not follow symlinks when recursively traversing directories" do
+ expected = %w[
+ deeply/nondotfile
+ nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/nondotfile').sort.should == expected
+ end
+
+ it "will follow symlinks when testing directory after recursive directory in pattern" do
+ expected = %w[
+ deeply/nondotfile
+ special/ln/nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/*/nondotfile').sort.should == expected
+ end
end
end
diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb
index 713ba9db9a..bbe347ba9e 100644
--- a/spec/ruby/core/dir/home_spec.rb
+++ b/spec/ruby/core/dir/home_spec.rb
@@ -19,6 +19,45 @@ describe "Dir.home" do
it "returns a non-frozen string" do
Dir.home.should_not.frozen?
end
+
+ it "returns a string with the filesystem encoding" do
+ Dir.home.encoding.should == Encoding.find("filesystem")
+ end
+
+ platform_is_not :windows do
+ it "works even if HOME is unset" do
+ ENV.delete('HOME')
+ Dir.home.should.start_with?('/')
+ Dir.home.encoding.should == Encoding.find("filesystem")
+ end
+ end
+
+ platform_is :windows do
+ ruby_version_is "3.2" do
+ it "returns the home directory with forward slashs and as UTF-8" do
+ ENV['HOME'] = "C:\\rubyspäc\\home"
+ home = Dir.home
+ home.should == "C:/rubyspäc/home"
+ home.encoding.should == Encoding::UTF_8
+ end
+ end
+
+ it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do
+ old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')]
+
+ Dir.home.should == old_dirs[1].gsub("\\", "/")
+ ENV['HOMEDRIVE'] = "C:"
+ ENV['HOMEPATH'] = "\\rubyspec\\home1"
+ Dir.home.should == "C:/rubyspec/home1"
+ ENV['USERPROFILE'] = "C:\\rubyspec\\home2"
+ # https://bugs.ruby-lang.org/issues/19244
+ # Dir.home.should == "C:/rubyspec/home2"
+ ENV['HOME'] = "C:\\rubyspec\\home3"
+ Dir.home.should == "C:/rubyspec/home3"
+ ensure
+ ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs
+ end
+ end
end
describe "when called with the current user name" do
@@ -28,7 +67,7 @@ describe "Dir.home" do
end
end
- platform_is_not :windows, :solaris, :android do
+ platform_is_not :windows, :solaris, :android, :wasi do
it "returns the named user's home directory, from the user database" do
Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp
end
@@ -37,6 +76,10 @@ describe "Dir.home" do
it "returns a non-frozen string" do
Dir.home(ENV['USER']).should_not.frozen?
end
+
+ it "returns a string with the filesystem encoding" do
+ Dir.home(ENV['USER']).encoding.should == Encoding.find("filesystem")
+ end
end
it "raises an ArgumentError if the named user doesn't exist" do
diff --git a/spec/ruby/core/dir/mkdir_spec.rb b/spec/ruby/core/dir/mkdir_spec.rb
index 0ed28f5a99..076ec19dd9 100644
--- a/spec/ruby/core/dir/mkdir_spec.rb
+++ b/spec/ruby/core/dir/mkdir_spec.rb
@@ -46,7 +46,7 @@ describe "Dir.mkdir" do
end
end
- it "calls #to_path on non-String arguments" do
+ it "calls #to_path on non-String path arguments" do
DirSpecs.clear_dirs
p = mock('path')
p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting'))
@@ -54,6 +54,22 @@ describe "Dir.mkdir" do
DirSpecs.clear_dirs
end
+ it "calls #to_int on non-Integer permissions argument" do
+ DirSpecs.clear_dirs
+ path = DirSpecs.mock_dir('nonexisting')
+ permissions = mock('permissions')
+ permissions.should_receive(:to_int).and_return(0666)
+ Dir.mkdir(path, permissions)
+ DirSpecs.clear_dirs
+ end
+
+ it "raises TypeError if non-Integer permissions argument does not have #to_int method" do
+ path = DirSpecs.mock_dir('nonexisting')
+ permissions = Object.new
+
+ -> { Dir.mkdir(path, permissions) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer')
+ end
+
it "raises a SystemCallError if any of the directories in the path before the last does not exist" do
-> { Dir.mkdir "#{DirSpecs.nonexistent}/subdir" }.should raise_error(SystemCallError)
end
diff --git a/spec/ruby/core/dir/read_spec.rb b/spec/ruby/core/dir/read_spec.rb
index 59de2e81cf..276930c6b7 100644
--- a/spec/ruby/core/dir/read_spec.rb
+++ b/spec/ruby/core/dir/read_spec.rb
@@ -39,5 +39,38 @@ describe "Dir#read" do
entries.sort.should == DirSpecs.expected_paths
end
+ platform_is_not :windows do
+ it "returns all directory entries even when encoding conversion will fail" do
+ dir = Dir.open(File.join(DirSpecs.mock_dir, 'special'))
+ utf8_entries = []
+ begin
+ while entry = dir.read
+ utf8_entries << entry
+ end
+ ensure
+ dir.close
+ end
+ old_internal_encoding = Encoding::default_internal
+ old_external_encoding = Encoding::default_external
+ Encoding.default_internal = Encoding::UTF_8
+ Encoding.default_external = Encoding::SHIFT_JIS
+ shift_jis_entries = []
+ begin
+ Dir.open(File.join(DirSpecs.mock_dir, 'special')) do |d|
+ -> {
+ while entry = d.read
+ shift_jis_entries << entry
+ end
+ }.should_not raise_error
+ end
+ ensure
+ Encoding.default_internal = old_internal_encoding
+ Encoding.default_external = old_external_encoding
+ end
+ shift_jis_entries.size.should == utf8_entries.size
+ shift_jis_entries.filter { |f| f.encoding == Encoding::SHIFT_JIS }.size.should == 1
+ end
+ end
+
it_behaves_like :dir_closed, :read
end
diff --git a/spec/ruby/core/dir/shared/chroot.rb b/spec/ruby/core/dir/shared/chroot.rb
index b14a433670..8c0599fe3f 100644
--- a/spec/ruby/core/dir/shared/chroot.rb
+++ b/spec/ruby/core/dir/shared/chroot.rb
@@ -3,7 +3,7 @@ describe :dir_chroot_as_root, shared: true do
DirSpecs.create_mock_dirs
@real_root = "../" * (File.dirname(__FILE__).count('/') - 1)
- @ref_dir = File.join("/", Dir.new('/').entries.first)
+ @ref_dir = File.join("/", File.basename(Dir["/*"].first))
end
after :all do
@@ -14,10 +14,13 @@ describe :dir_chroot_as_root, shared: true do
DirSpecs.delete_mock_dirs
end
+ # Pending until https://github.com/ruby/ruby/runs/8075149420 is fixed
+ compilations_ci = ENV["GITHUB_WORKFLOW"] == "Compilations"
+
it "can be used to change the process' root directory" do
-> { Dir.send(@method, File.dirname(__FILE__)) }.should_not raise_error
File.should.exist?("/#{File.basename(__FILE__)}")
- end
+ end unless compilations_ci
it "returns 0 if successful" do
Dir.send(@method, '/').should == 0
@@ -31,7 +34,7 @@ describe :dir_chroot_as_root, shared: true do
Dir.send(@method, @real_root)
File.should.exist?(@ref_dir)
File.should_not.exist?("/#{File.basename(__FILE__)}")
- end
+ end unless compilations_ci
it "calls #to_path on non-String argument" do
p = mock('path')
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index ae5c2a114b..33b2828c27 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -23,18 +23,45 @@ describe :dir_glob, shared: true do
Dir.send(@method, obj).should == %w[file_one.ext]
end
- ruby_version_is ""..."2.7" do
- it "splits the string on \\0 if there is only one string given and warns" do
- -> {
- Dir.send(@method, "file_o*\0file_t*").should ==
- %w!file_one.ext file_two.ext!
- }.should complain(/warning: use glob patterns list instead of nul-separated patterns/)
+ it "raises an ArgumentError if the string contains \\0" do
+ -> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error ArgumentError, /nul-separated/
+ end
+
+ ruby_version_is "3.0" do
+ it "result is sorted by default" do
+ result = Dir.send(@method, '*')
+ result.should == result.sort
+ end
+
+ it "result is sorted with sort: true" do
+ result = Dir.send(@method, '*', sort: true)
+ result.should == result.sort
+ end
+
+ it "sort: false returns same files" do
+ result = Dir.send(@method,'*', sort: false)
+ result.sort.should == Dir.send(@method, '*').sort
+ end
+ end
+
+ ruby_version_is "3.0"..."3.1" do
+ it "result is sorted with any non false value of sort:" do
+ result = Dir.send(@method, '*', sort: 0)
+ result.should == result.sort
+
+ result = Dir.send(@method, '*', sort: nil)
+ result.should == result.sort
+
+ result = Dir.send(@method, '*', sort: 'false')
+ result.should == result.sort
end
end
- ruby_version_is "2.7" do
- it "raises an ArgumentError if the string contains \\0" do
- -> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error ArgumentError, /nul-separated/
+ ruby_version_is "3.1" do
+ it "raises an ArgumentError if sort: is not true or false" do
+ -> { Dir.send(@method, '*', sort: 0) }.should raise_error ArgumentError, /expected true or false/
+ -> { Dir.send(@method, '*', sort: nil) }.should raise_error ArgumentError, /expected true or false/
+ -> { Dir.send(@method, '*', sort: 'false') }.should raise_error ArgumentError, /expected true or false/
end
end
@@ -64,6 +91,10 @@ describe :dir_glob, shared: true do
Dir.send(@method, 'special/+').should == ['special/+']
end
+ it "matches directories with special characters when escaped" do
+ Dir.send(@method, 'special/\{}/special').should == ["special/{}/special"]
+ end
+
platform_is_not :windows do
it "matches regexp special *" do
Dir.send(@method, 'special/\*').should == ['special/*']
@@ -76,6 +107,14 @@ describe :dir_glob, shared: true do
it "matches regexp special |" do
Dir.send(@method, 'special/|').should == ['special/|']
end
+
+ it "matches files with backslashes in their name" do
+ Dir.glob('special/\\\\{a,b}').should == ['special/\a']
+ end
+
+ it "matches directory with special characters in their name in complex patterns" do
+ Dir.glob("special/test +()\\[\\]\\{\\}/hello_world{.{en},}{.{html},}{+{phone},}{.{erb},}").should == ['special/test +()[]{}/hello_world.erb']
+ end
end
it "matches regexp special ^" do
@@ -190,7 +229,9 @@ describe :dir_glob, shared: true do
dir/
nested/
special/
+ special/test\ +()[]{}/
special/test{1}/
+ special/{}/
subdir_one/
subdir_two/
]
diff --git a/spec/ruby/core/encoding/compatible_spec.rb b/spec/ruby/core/encoding/compatible_spec.rb
index dc47a6553a..80ecab6155 100644
--- a/spec/ruby/core/encoding/compatible_spec.rb
+++ b/spec/ruby/core/encoding/compatible_spec.rb
@@ -54,7 +54,7 @@ describe "Encoding.compatible? String, String" do
it "returns nil if the second's Encoding is not ASCII compatible" do
a = "abc".force_encoding("UTF-8")
- b = "123".force_encoding("UTF-16LE")
+ b = "1234".force_encoding("UTF-16LE")
Encoding.compatible?(a, b).should be_nil
end
end
diff --git a/spec/ruby/core/encoding/converter/putback_spec.rb b/spec/ruby/core/encoding/converter/putback_spec.rb
index 87495eaf3f..c4e0a5da21 100644
--- a/spec/ruby/core/encoding/converter/putback_spec.rb
+++ b/spec/ruby/core/encoding/converter/putback_spec.rb
@@ -34,14 +34,23 @@ describe "Encoding::Converter#putback" do
@ec.putback.should == ""
end
+ it "returns the problematic bytes for UTF-16LE" do
+ ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
+ src = "\x00\xd8\x61\x00"
+ dst = ""
+ ec.primitive_convert(src, dst).should == :invalid_byte_sequence
+ ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
+ ec.putback.should == "a\x00".force_encoding("utf-16le")
+ ec.putback.should == ""
+ end
+
it "accepts an integer argument corresponding to the number of bytes to be put back" do
ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
src = "\x00\xd8\x61\x00"
dst = ""
ec.primitive_convert(src, dst).should == :invalid_byte_sequence
ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
- ec.putback(1).should == "\x00".force_encoding("utf-16le")
- ec.putback.should == "a".force_encoding("utf-16le")
+ ec.putback(2).should == "a\x00".force_encoding("utf-16le")
ec.putback.should == ""
end
end
diff --git a/spec/ruby/core/encoding/default_external_spec.rb b/spec/ruby/core/encoding/default_external_spec.rb
index e2cb9b02f4..682d49d37c 100644
--- a/spec/ruby/core/encoding/default_external_spec.rb
+++ b/spec/ruby/core/encoding/default_external_spec.rb
@@ -17,6 +17,14 @@ describe "Encoding.default_external" do
Encoding.default_external = Encoding::SHIFT_JIS
Encoding.default_external.should == Encoding::SHIFT_JIS
end
+
+ ruby_version_is "3.0" do
+ platform_is :windows do
+ it 'is UTF-8 by default on Windows' do
+ Encoding.default_external.should == Encoding::UTF_8
+ end
+ end
+ end
end
describe "Encoding.default_external=" do
diff --git a/spec/ruby/core/encoding/list_spec.rb b/spec/ruby/core/encoding/list_spec.rb
index 8efd94ab9c..bd3d5b7bc0 100644
--- a/spec/ruby/core/encoding/list_spec.rb
+++ b/spec/ruby/core/encoding/list_spec.rb
@@ -40,10 +40,8 @@ describe "Encoding.list" 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
+ it 'includes CESU-8 encoding' do
+ Encoding.list.should.include?(Encoding::CESU_8)
end
# TODO: Find example that illustrates this
diff --git a/spec/ruby/core/encoding/replicate_spec.rb b/spec/ruby/core/encoding/replicate_spec.rb
index 45727a5c0d..848415eeb4 100644
--- a/spec/ruby/core/encoding/replicate_spec.rb
+++ b/spec/ruby/core/encoding/replicate_spec.rb
@@ -2,66 +2,74 @@
require_relative '../../spec_helper'
describe "Encoding#replicate" do
- before :all do
- @i = 0
- end
+ ruby_version_is ""..."3.3" do
+ before :all do
+ @i = 0
+ end
- before :each do
- @i += 1
- @prefix = "RS#{@i}"
- end
+ before :each do
+ @i += 1
+ @prefix = "RS#{@i}"
+ end
- it "returns a replica of ASCII" do
- name = @prefix + '-ASCII'
- e = Encoding::ASCII.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
+ it "returns a replica of ASCII" do
+ name = @prefix + '-ASCII'
+ e = suppress_warning { Encoding::ASCII.replicate(name) }
+ e.name.should == name
+ Encoding.find(name).should == e
- "a".force_encoding(e).valid_encoding?.should be_true
- "\x80".force_encoding(e).valid_encoding?.should be_false
- end
+ "a".force_encoding(e).valid_encoding?.should be_true
+ "\x80".force_encoding(e).valid_encoding?.should be_false
+ end
- it "returns a replica of UTF-8" do
- name = @prefix + 'UTF-8'
- e = Encoding::UTF_8.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
+ it "returns a replica of UTF-8" do
+ name = @prefix + 'UTF-8'
+ e = suppress_warning { Encoding::UTF_8.replicate(name) }
+ e.name.should == name
+ Encoding.find(name).should == e
- "a".force_encoding(e).valid_encoding?.should be_true
- "\u3042".force_encoding(e).valid_encoding?.should be_true
- "\x80".force_encoding(e).valid_encoding?.should be_false
- end
+ "a".force_encoding(e).valid_encoding?.should be_true
+ "\u3042".force_encoding(e).valid_encoding?.should be_true
+ "\x80".force_encoding(e).valid_encoding?.should be_false
+ end
- it "returns a replica of UTF-16BE" do
- name = @prefix + 'UTF-16-BE'
- e = Encoding::UTF_16BE.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
+ it "returns a replica of UTF-16BE" do
+ name = @prefix + 'UTF-16-BE'
+ e = suppress_warning { Encoding::UTF_16BE.replicate(name) }
+ e.name.should == name
+ Encoding.find(name).should == e
- "a".force_encoding(e).valid_encoding?.should be_false
- "\x30\x42".force_encoding(e).valid_encoding?.should be_true
- "\x80".force_encoding(e).valid_encoding?.should be_false
- end
+ "a".force_encoding(e).valid_encoding?.should be_false
+ "\x30\x42".force_encoding(e).valid_encoding?.should be_true
+ "\x80".force_encoding(e).valid_encoding?.should be_false
+ end
- it "returns a replica of ISO-2022-JP" do
- name = @prefix + 'ISO-2022-JP'
- e = Encoding::ISO_2022_JP.replicate(name)
- Encoding.find(name).should == e
+ it "returns a replica of ISO-2022-JP" do
+ name = @prefix + 'ISO-2022-JP'
+ e = suppress_warning { Encoding::ISO_2022_JP.replicate(name) }
+ Encoding.find(name).should == e
- e.name.should == name
- e.dummy?.should be_true
- end
+ e.name.should == name
+ e.dummy?.should be_true
+ end
- # NOTE: it's unclear of the value of this (for the complexity cost of it),
- # but it is the current CRuby behavior.
- it "can be associated with a String" do
- name = @prefix + '-US-ASCII'
- e = Encoding::US_ASCII.replicate(name)
- e.name.should == name
- Encoding.find(name).should == e
+ # NOTE: it's unclear of the value of this (for the complexity cost of it),
+ # but it is the current CRuby behavior.
+ it "can be associated with a String" do
+ name = @prefix + '-US-ASCII'
+ e = suppress_warning { Encoding::US_ASCII.replicate(name) }
+ e.name.should == name
+ Encoding.find(name).should == e
+
+ s = "abc".force_encoding(e)
+ s.encoding.should == e
+ s.encoding.name.should == name
+ end
+ end
- s = "abc".force_encoding(e)
- s.encoding.should == e
- s.encoding.name.should == name
+ ruby_version_is "3.3" do
+ it "has been removed" do
+ Encoding::US_ASCII.should_not.respond_to?(:replicate, true)
+ end
end
end
diff --git a/spec/ruby/core/enumerable/all_spec.rb b/spec/ruby/core/enumerable/all_spec.rb
index b782f94a3e..0ded1e8eba 100644
--- a/spec/ruby/core/enumerable/all_spec.rb
+++ b/spec/ruby/core/enumerable/all_spec.rb
@@ -131,7 +131,6 @@ describe "Enumerable#all?" do
pattern.yielded.should == [[0], [1], [2], [-1]]
end
- # may raise an exception in future versions
it "always returns true on empty enumeration" do
@empty.all?(Integer).should == true
[].all?(Integer).should == true
diff --git a/spec/ruby/core/enumerable/any_spec.rb b/spec/ruby/core/enumerable/any_spec.rb
index 636b1fa450..355cd0c290 100644
--- a/spec/ruby/core/enumerable/any_spec.rb
+++ b/spec/ruby/core/enumerable/any_spec.rb
@@ -145,7 +145,6 @@ describe "Enumerable#any?" do
pattern.yielded.should == [[0], [1], [2]]
end
- # may raise an exception in future versions
it "always returns false on empty enumeration" do
@empty.any?(Integer).should == false
[].any?(Integer).should == false
diff --git a/spec/ruby/core/enumerable/compact_spec.rb b/spec/ruby/core/enumerable/compact_spec.rb
new file mode 100644
index 0000000000..86e95dce08
--- /dev/null
+++ b/spec/ruby/core/enumerable/compact_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is '3.1' do
+ describe "Enumerable#compact" do
+ it 'returns array without nil elements' do
+ arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true)
+ arr.compact.should == [1, 2, true]
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerable/each_cons_spec.rb b/spec/ruby/core/enumerable/each_cons_spec.rb
index 7d44f54f74..8fb31fb925 100644
--- a/spec/ruby/core/enumerable/each_cons_spec.rb
+++ b/spec/ruby/core/enumerable/each_cons_spec.rb
@@ -10,7 +10,7 @@ describe "Enumerable#each_cons" do
it "passes element groups to the block" do
acc = []
- @enum.each_cons(3){|g| acc << g}.should be_nil
+ @enum.each_cons(3){|g| acc << g}
acc.should == @in_threes
end
@@ -27,7 +27,7 @@ describe "Enumerable#each_cons" do
it "tries to convert n to an Integer using #to_int" do
acc = []
- @enum.each_cons(3.3){|g| acc << g}.should == nil
+ @enum.each_cons(3.3){|g| acc << g}
acc.should == @in_threes
obj = mock('to_int')
@@ -56,6 +56,12 @@ describe "Enumerable#each_cons" do
multi.each_cons(2).to_a.should == [[[1, 2], [3, 4, 5]], [[3, 4, 5], [6, 7, 8, 9]]]
end
+ ruby_version_is "3.1" do
+ it "returns self when a block is given" do
+ @enum.each_cons(3){}.should == @enum
+ end
+ end
+
describe "when no block is given" do
it "returns an enumerator" do
e = @enum.each_cons(3)
diff --git a/spec/ruby/core/enumerable/each_slice_spec.rb b/spec/ruby/core/enumerable/each_slice_spec.rb
index ab3b79c344..a57a1dba81 100644
--- a/spec/ruby/core/enumerable/each_slice_spec.rb
+++ b/spec/ruby/core/enumerable/each_slice_spec.rb
@@ -10,7 +10,7 @@ describe "Enumerable#each_slice" do
it "passes element groups to the block" do
acc = []
- @enum.each_slice(3){|g| acc << g}.should be_nil
+ @enum.each_slice(3){|g| acc << g}
acc.should == @sliced
end
@@ -27,7 +27,7 @@ describe "Enumerable#each_slice" do
it "tries to convert n to an Integer using #to_int" do
acc = []
- @enum.each_slice(3.3){|g| acc << g}.should == nil
+ @enum.each_slice(3.3){|g| acc << g}
acc.should == @sliced
obj = mock('to_int')
@@ -57,6 +57,12 @@ describe "Enumerable#each_slice" do
e.to_a.should == @sliced
end
+ ruby_version_is "3.1" do
+ it "returns self when a block is given" do
+ @enum.each_slice(3){}.should == @enum
+ end
+ end
+
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
multi.each_slice(2).to_a.should == [[[1, 2], [3, 4, 5]], [[6, 7, 8, 9]]]
diff --git a/spec/ruby/core/enumerable/filter_map_spec.rb b/spec/ruby/core/enumerable/filter_map_spec.rb
index 31acc277b4..aa4894230b 100644
--- a/spec/ruby/core/enumerable/filter_map_spec.rb
+++ b/spec/ruby/core/enumerable/filter_map_spec.rb
@@ -1,26 +1,24 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '2.7' do
- describe 'Enumerable#filter_map' do
- before :each do
- @numerous = EnumerableSpecs::Numerous.new(*(1..8).to_a)
- end
+describe 'Enumerable#filter_map' do
+ before :each do
+ @numerous = EnumerableSpecs::Numerous.new(*(1..8).to_a)
+ end
- it 'returns an empty array if there are no elements' do
- EnumerableSpecs::Empty.new.filter_map { true }.should == []
- end
+ it 'returns an empty array if there are no elements' do
+ EnumerableSpecs::Empty.new.filter_map { true }.should == []
+ end
- it 'returns an array with truthy results of passing each element to block' do
- @numerous.filter_map { |i| i * 2 if i.even? }.should == [4, 8, 12, 16]
- @numerous.filter_map { |i| i * 2 }.should == [2, 4, 6, 8, 10, 12, 14, 16]
- @numerous.filter_map { 0 }.should == [0, 0, 0, 0, 0, 0, 0, 0]
- @numerous.filter_map { false }.should == []
- @numerous.filter_map { nil }.should == []
- end
+ it 'returns an array with truthy results of passing each element to block' do
+ @numerous.filter_map { |i| i * 2 if i.even? }.should == [4, 8, 12, 16]
+ @numerous.filter_map { |i| i * 2 }.should == [2, 4, 6, 8, 10, 12, 14, 16]
+ @numerous.filter_map { 0 }.should == [0, 0, 0, 0, 0, 0, 0, 0]
+ @numerous.filter_map { false }.should == []
+ @numerous.filter_map { nil }.should == []
+ end
- it 'returns an enumerator when no block given' do
- @numerous.filter_map.should be_an_instance_of(Enumerator)
- end
+ it 'returns an enumerator when no block given' do
+ @numerous.filter_map.should be_an_instance_of(Enumerator)
end
end
diff --git a/spec/ruby/core/enumerable/grep_spec.rb b/spec/ruby/core/enumerable/grep_spec.rb
index 4e66bb85ea..b81075291f 100644
--- a/spec/ruby/core/enumerable/grep_spec.rb
+++ b/spec/ruby/core/enumerable/grep_spec.rb
@@ -59,6 +59,24 @@ describe "Enumerable#grep" do
["abc", "def"].grep(/b/).should == ["abc"]
$&.should == "z"
end
+
+ it "does not modify Regexp.last_match without block" do
+ "z" =~ /z/ # Reset last match
+ ["abc", "def"].grep(/b/).should == ["abc"]
+ Regexp.last_match[0].should == "z"
+ end
+
+ it "correctly handles non-string elements" do
+ 'set last match' =~ /set last (.*)/
+ [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/).should == [:a, 'b', :c]
+ $1.should == 'match'
+
+ o = Object.new
+ def o.to_str
+ 'hello'
+ end
+ [o].grep(/ll/).first.should.equal?(o)
+ end
end
describe "with a block" do
diff --git a/spec/ruby/core/enumerable/grep_v_spec.rb b/spec/ruby/core/enumerable/grep_v_spec.rb
index 8cae3ac618..35fde27eb6 100644
--- a/spec/ruby/core/enumerable/grep_v_spec.rb
+++ b/spec/ruby/core/enumerable/grep_v_spec.rb
@@ -39,6 +39,24 @@ describe "Enumerable#grep_v" do
["abc", "def"].grep_v(/e/).should == ["abc"]
$&.should == "z"
end
+
+ it "does not modify Regexp.last_match without block" do
+ "z" =~ /z/ # Reset last match
+ ["abc", "def"].grep_v(/e/).should == ["abc"]
+ Regexp.last_match[0].should == "z"
+ end
+
+ it "correctly handles non-string elements" do
+ 'set last match' =~ /set last (.*)/
+ [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/).should == ['z', 42, nil]
+ $1.should == 'match'
+
+ o = Object.new
+ def o.to_str
+ 'hello'
+ end
+ [o].grep_v(/mm/).first.should.equal?(o)
+ end
end
describe "without block" do
diff --git a/spec/ruby/core/enumerable/group_by_spec.rb b/spec/ruby/core/enumerable/group_by_spec.rb
index 52b5a68d64..4fd1603819 100644
--- a/spec/ruby/core/enumerable/group_by_spec.rb
+++ b/spec/ruby/core/enumerable/group_by_spec.rb
@@ -33,15 +33,5 @@ describe "Enumerable#group_by" do
[3, 4, 5] => [[3, 4, 5]] }
end
- ruby_version_is ''...'2.7' do
- it "returns a tainted hash if self is tainted" do
- EnumerableSpecs::Empty.new.taint.group_by {}.tainted?.should be_true
- end
-
- it "returns an untrusted hash if self is untrusted" do
- EnumerableSpecs::Empty.new.untrust.group_by {}.untrusted?.should be_true
- end
- end
-
it_behaves_like :enumerable_enumeratorized_with_origin_size, :group_by
end
diff --git a/spec/ruby/core/enumerable/none_spec.rb b/spec/ruby/core/enumerable/none_spec.rb
index b898d00063..99bb7f7a4e 100644
--- a/spec/ruby/core/enumerable/none_spec.rb
+++ b/spec/ruby/core/enumerable/none_spec.rb
@@ -100,7 +100,6 @@ describe "Enumerable#none?" do
pattern.yielded.should == [[0], [1], [2], [-1]]
end
- # may raise an exception in future versions
it "always returns true on empty enumeration" do
@empty.none?(Integer).should == true
[].none?(Integer).should == true
diff --git a/spec/ruby/core/enumerable/one_spec.rb b/spec/ruby/core/enumerable/one_spec.rb
index d54dd4a527..47bfd65a0f 100644
--- a/spec/ruby/core/enumerable/one_spec.rb
+++ b/spec/ruby/core/enumerable/one_spec.rb
@@ -91,7 +91,6 @@ describe "Enumerable#one?" do
pattern.yielded.should == [[0], [1], [2], [-1]]
end
- # may raise an exception in future versions
it "always returns false on empty enumeration" do
@empty.one?(Integer).should == false
[].one?(Integer).should == false
diff --git a/spec/ruby/core/enumerable/shared/collect.rb b/spec/ruby/core/enumerable/shared/collect.rb
index 32c1722c75..6df1a616eb 100644
--- a/spec/ruby/core/enumerable/shared/collect.rb
+++ b/spec/ruby/core/enumerable/shared/collect.rb
@@ -89,5 +89,19 @@ describe :enumerable_collect, shared: true do
end.should raise_error(ArgumentError)
end
+ it "calls the each method on sub-classes" do
+ c = Class.new(Hash) do
+ def each
+ ScratchPad << 'in each'
+ super
+ end
+ end
+ h = c.new
+ h[1] = 'a'
+ ScratchPad.record []
+ h.send(@method) { |k,v| v }
+ ScratchPad.recorded.should == ['in each']
+ end
+
it_should_behave_like :enumerable_enumeratorized_with_origin_size
end
diff --git a/spec/ruby/core/enumerable/shared/entries.rb b/spec/ruby/core/enumerable/shared/entries.rb
index 590ce73bcf..e32eb23d2a 100644
--- a/spec/ruby/core/enumerable/shared/entries.rb
+++ b/spec/ruby/core/enumerable/shared/entries.rb
@@ -13,14 +13,4 @@ describe :enumerable_entries, shared: true do
count.send(@method, :hello, "world").should == [1, 2, 3]
count.arguments_passed.should == [:hello, "world"]
end
-
- ruby_version_is ''...'2.7' do
- it "returns a tainted array if self is tainted" do
- EnumerableSpecs::Empty.new.taint.send(@method).tainted?.should be_true
- end
-
- it "returns an untrusted array if self is untrusted" do
- EnumerableSpecs::Empty.new.untrust.send(@method).untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/enumerable/shared/inject.rb b/spec/ruby/core/enumerable/shared/inject.rb
index 12e0665dda..c5907f92d8 100644
--- a/spec/ruby/core/enumerable/shared/inject.rb
+++ b/spec/ruby/core/enumerable/shared/inject.rb
@@ -17,7 +17,8 @@ describe :enumerable_inject, shared: true do
end
it "ignores the block if two arguments" do
- EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-){ raise "we never get here"}.should == 4
+ EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-) { raise "we never get here"}.should == 4
+ [].send(@method, 3, :+) { raise "we never get here"}.should == 3
end
it "can take a symbol argument" do
@@ -66,4 +67,11 @@ describe :enumerable_inject, shared: true do
it "returns nil when fails(legacy rubycon)" do
EnumerableSpecs::EachDefiner.new().send(@method) {|acc,x| 999 }.should == nil
end
+
+ ruby_bug '#18635', ''...'3.2' do
+ it "raises an ArgumentError when no parameters or block is given" do
+ -> { [1,2].send(@method) }.should raise_error(ArgumentError)
+ -> { {one: 1, two: 2}.send(@method) }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/enumerable/sum_spec.rb b/spec/ruby/core/enumerable/sum_spec.rb
index c9d7017b45..fc173e4173 100644
--- a/spec/ruby/core/enumerable/sum_spec.rb
+++ b/spec/ruby/core/enumerable/sum_spec.rb
@@ -22,7 +22,29 @@ describe 'Enumerable#sum' do
@enum.sum.should == 5/3r
end
- it 'takes a block to transform the elements' do
- @enum.sum { |element| element * 2 }.should == 10/3r
+ context 'with a block' do
+ it 'transforms the elements' do
+ @enum.sum { |element| element * 2 }.should == 10/3r
+ end
+
+ it 'does not destructure array elements' do
+ class << @enum
+ def each
+ yield [1,2]
+ yield [3]
+ end
+ end
+
+ @enum.sum(&:last).should == 5
+ end
+ end
+
+ # https://bugs.ruby-lang.org/issues/12217
+ # https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214
+ it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do
+ floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5].to_enum
+ naive_sum = floats.reduce { |sum, e| sum + e }
+ naive_sum.should == 50.00000000000001
+ floats.sum.should == 50.0
end
end
diff --git a/spec/ruby/core/enumerable/tally_spec.rb b/spec/ruby/core/enumerable/tally_spec.rb
index c23ea11697..f09a8f533a 100644
--- a/spec/ruby/core/enumerable/tally_spec.rb
+++ b/spec/ruby/core/enumerable/tally_spec.rb
@@ -1,36 +1,34 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "2.7" do
- describe "Enumerable#tally" do
- before :each do
- ScratchPad.record []
- end
+describe "Enumerable#tally" do
+ before :each do
+ ScratchPad.record []
+ end
- it "returns a hash with counts according to the value" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- enum.tally.should == { 'foo' => 2, 'bar' => 1, 'baz' => 1}
- end
+ it "returns a hash with counts according to the value" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ enum.tally.should == { 'foo' => 2, 'bar' => 1, 'baz' => 1}
+ end
- it "returns a hash without default" do
- hash = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz').tally
- hash.default_proc.should be_nil
- hash.default.should be_nil
- end
+ it "returns a hash without default" do
+ hash = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz').tally
+ hash.default_proc.should be_nil
+ hash.default.should be_nil
+ end
- it "returns an empty hash for empty enumerables" do
- EnumerableSpecs::Empty.new.tally.should == {}
- end
+ it "returns an empty hash for empty enumerables" do
+ EnumerableSpecs::Empty.new.tally.should == {}
+ end
- it "counts values as gathered array when yielded with multiple arguments" do
- EnumerableSpecs::YieldsMixed2.new.tally.should == EnumerableSpecs::YieldsMixed2.gathered_yields.group_by(&:itself).transform_values(&:size)
- end
+ it "counts values as gathered array when yielded with multiple arguments" do
+ EnumerableSpecs::YieldsMixed2.new.tally.should == EnumerableSpecs::YieldsMixed2.gathered_yields.group_by(&:itself).transform_values(&:size)
+ end
- it "does not call given block" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- enum.tally { |v| ScratchPad << v }
- ScratchPad.recorded.should == []
- end
+ it "does not call given block" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ enum.tally { |v| ScratchPad << v }
+ ScratchPad.recorded.should == []
end
end
@@ -51,7 +49,7 @@ ruby_version_is "3.1" do
enum.tally(hash).should equal(hash)
end
- it "raises a FrozenError and does not udpate the given hash when the hash is frozen" do
+ it "raises a FrozenError and does not update the given hash when the hash is frozen" do
enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
hash = { 'foo' => 1 }.freeze
-> { enum.tally(hash) }.should raise_error(FrozenError)
diff --git a/spec/ruby/core/enumerable/uniq_spec.rb b/spec/ruby/core/enumerable/uniq_spec.rb
index e58dd36366..a1ed44796f 100644
--- a/spec/ruby/core/enumerable/uniq_spec.rb
+++ b/spec/ruby/core/enumerable/uniq_spec.rb
@@ -31,76 +31,32 @@ describe 'Enumerable#uniq' do
[x, y].to_enum.uniq.should == [x, y]
end
- ruby_version_is '2.7' do
- it "compares elements with matching hash codes with #eql?" do
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- false
- end
-
- obj
- end
-
- a.uniq.should == a
+ it "compares elements with matching hash codes with #eql?" do
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- true
- end
-
- obj
+ def obj.eql?(o)
+ false
end
- a.to_enum.uniq.size.should == 1
+ obj
end
- end
- ruby_version_is ''...'2.7' do
- it "compares elements with matching hash codes with #eql?" do
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- taint
- o.taint
- false
- end
-
- obj
- end
-
- a.uniq.should == a
- a[0].should.tainted?
- a[1].should.tainted?
+ a.uniq.should == a
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
- def obj.eql?(o)
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- taint
- o.taint
- true
- end
-
- obj
+ def obj.eql?(o)
+ true
end
- a.to_enum.uniq.size.should == 1
- a[0].should.tainted?
- a[1].should.tainted?
+ obj
end
+
+ a.to_enum.uniq.size.should == 1
end
context 'when yielded with multiple arguments' do
diff --git a/spec/ruby/core/enumerable/zip_spec.rb b/spec/ruby/core/enumerable/zip_spec.rb
index 9ec15aa030..ab148f2a6e 100644
--- a/spec/ruby/core/enumerable/zip_spec.rb
+++ b/spec/ruby/core/enumerable/zip_spec.rb
@@ -38,4 +38,9 @@ describe "Enumerable#zip" do
multi.zip(multi).should == [[[1, 2], [1, 2]], [[3, 4, 5], [3, 4, 5]], [[6, 7, 8, 9], [6, 7, 8, 9]]]
end
+ it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
+ -> { EnumerableSpecs::Numerous.new(1,2,3).zip(Object.new) }.should raise_error(TypeError, "wrong argument type Object (must respond to :each)")
+ -> { EnumerableSpecs::Numerous.new(1,2,3).zip(1) }.should raise_error(TypeError, "wrong argument type Integer (must respond to :each)")
+ -> { EnumerableSpecs::Numerous.new(1,2,3).zip(true) }.should raise_error(TypeError, "wrong argument type TrueClass (must respond to :each)")
+ end
end
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb
index bed30c546d..bd243fa0b5 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb
@@ -6,4 +6,11 @@ describe "Enumerator::ArithmeticSequence#begin" do
(1..10).step.begin.should == 1
(1...10).step.begin.should == 1
end
+
+ context "with beginless" do
+ it "returns nil as begin of the sequence" do
+ (..10).step(1).begin.should == nil
+ (...10).step(1).begin.should == nil
+ end
+ end
end
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb
index 29e6e105cf..05429cac3e 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb
@@ -6,4 +6,11 @@ describe "Enumerator::ArithmeticSequence#end" do
(1..10).step.end.should == 10
(1...10).step(17).end.should == 10
end
+
+ context "with endless" do
+ it "returns nil as end of the sequence" do
+ (1..).step(1).end.should == nil
+ (1...).step(1).end.should == nil
+ end
+ end
end
diff --git a/spec/ruby/core/enumerator/lazy/compact_spec.rb b/spec/ruby/core/enumerator/lazy/compact_spec.rb
new file mode 100644
index 0000000000..80b6f9481d
--- /dev/null
+++ b/spec/ruby/core/enumerator/lazy/compact_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is '3.1' do
+ describe "Enumerator::Lazy#compact" do
+ it 'returns array without nil elements' do
+ arr = [1, nil, 3, false, 5].to_enum.lazy.compact
+ arr.should be_an_instance_of(Enumerator::Lazy)
+ arr.force.should == [1, 3, false, 5]
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/lazy/eager_spec.rb b/spec/ruby/core/enumerator/lazy/eager_spec.rb
index 30ba2dfe0e..592da4fd8c 100644
--- a/spec/ruby/core/enumerator/lazy/eager_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/eager_spec.rb
@@ -1,29 +1,27 @@
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
+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
+ enum.class.should == Enumerator::Lazy
+ enum.eager.class.should == Enumerator
+ end
- it "does not enumerate an enumerator" do
- ScratchPad.record []
+ 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
+ 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 == []
+ 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
+ enum.map { |i| i }.should == [1, 2, 3]
+ ScratchPad.recorded.should == [1, 2, 3]
end
end
diff --git a/spec/ruby/core/enumerator/lazy/filter_map_spec.rb b/spec/ruby/core/enumerator/lazy/filter_map_spec.rb
index 3480af0865..99dd59cebe 100644
--- a/spec/ruby/core/enumerator/lazy/filter_map_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/filter_map_spec.rb
@@ -3,14 +3,12 @@
require_relative '../../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "2.7" do
- describe "Enumerator::Lazy#filter_map" do
- it "maps only truthy results" do
- (1..Float::INFINITY).lazy.filter_map { |i| i if i.odd? }.first(4).should == [1, 3, 5, 7]
- end
+describe "Enumerator::Lazy#filter_map" do
+ it "maps only truthy results" do
+ (1..Float::INFINITY).lazy.filter_map { |i| i if i.odd? }.first(4).should == [1, 3, 5, 7]
+ end
- it "does not map false results" do
- (1..Float::INFINITY).lazy.filter_map { |i| i.odd? ? i : false }.first(4).should == [1, 3, 5, 7]
- end
+ it "does not map false results" do
+ (1..Float::INFINITY).lazy.filter_map { |i| i.odd? ? i : false }.first(4).should == [1, 3, 5, 7]
end
end
diff --git a/spec/ruby/core/enumerator/lazy/lazy_spec.rb b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
index cde9b31066..0fb104e25a 100644
--- a/spec/ruby/core/enumerator/lazy/lazy_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
@@ -16,6 +16,10 @@ describe "Enumerator::Lazy" do
]
lazy_methods += [:chunk_while, :uniq]
+ ruby_version_is '3.1' do
+ lazy_methods += [:compact]
+ end
+
Enumerator::Lazy.instance_methods(false).should include(*lazy_methods)
end
end
diff --git a/spec/ruby/core/enumerator/lazy/with_index_spec.rb b/spec/ruby/core/enumerator/lazy/with_index_spec.rb
index 3a59ba4116..a6b5c38777 100644
--- a/spec/ruby/core/enumerator/lazy/with_index_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/with_index_spec.rb
@@ -3,28 +3,34 @@
require_relative '../../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "2.7" do
- describe "Enumerator::Lazy#with_index" do
- it "enumerates with an index" do
- (0..Float::INFINITY).lazy.with_index.map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
- end
+describe "Enumerator::Lazy#with_index" do
+ it "enumerates with an index" do
+ (0..Float::INFINITY).lazy.with_index.map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
+ end
+
+ it "enumerates with an index starting at a given offset" do
+ (0..Float::INFINITY).lazy.with_index(3).map { |i, idx| [i, idx] }.first(3).should == [[0, 3], [1, 4], [2, 5]]
+ end
- it "enumerates with an index starting at a given offset" do
- (0..Float::INFINITY).lazy.with_index(3).map { |i, idx| [i, idx] }.first(3).should == [[0, 3], [1, 4], [2, 5]]
- end
+ it "enumerates with an index starting at 0 when offset is nil" do
+ (0..Float::INFINITY).lazy.with_index(nil).map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
+ end
- it "enumerates with an index starting at 0 when offset is nil" do
- (0..Float::INFINITY).lazy.with_index(nil).map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
- end
+ it "raises TypeError when offset does not convert to Integer" do
+ -> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError)
+ end
- it "raises TypeError when offset does not convert to Integer" do
- -> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError)
- end
+ it "enumerates with a given block" do
+ result = []
+ (0..Float::INFINITY).lazy.with_index { |i, idx| result << [i * 2, idx] }.first(3)
+ result.should == [[0,0],[2,1],[4,2]]
+ end
- it "enumerates with a given block" do
- result = []
- (0..Float::INFINITY).lazy.with_index { |i, idx| result << [i * 2, idx] }.first(3)
- result.should == [[0,0],[2,1],[4,2]]
- end
+ it "resets after a new call to each" do
+ enum = (0..2).lazy.with_index.map { |i, idx| [i, idx] }
+ result = []
+ enum.each { |i, idx| result << [i, idx] }
+ enum.each { |i, idx| result << [i, idx] }
+ result.should == [[0,0], [1,1], [2,2], [0,0], [1,1], [2,2]]
end
end
diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb
index 5cc0b3ff2e..c439469525 100644
--- a/spec/ruby/core/enumerator/new_spec.rb
+++ b/spec/ruby/core/enumerator/new_spec.rb
@@ -77,14 +77,12 @@ describe "Enumerator.new" do
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"]
+ 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
describe 'yielded values' do
diff --git a/spec/ruby/core/enumerator/produce_spec.rb b/spec/ruby/core/enumerator/produce_spec.rb
index f6f1dcd429..c69fb49303 100644
--- a/spec/ruby/core/enumerator/produce_spec.rb
+++ b/spec/ruby/core/enumerator/produce_spec.rb
@@ -1,36 +1,34 @@
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
+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
- enum.to_a.should == [0, 1, 2]
+ it "terminates iteration when block raises StopIteration exception" do
+ enum = Enumerator.produce(0) do | prev|
+ raise StopIteration if prev >= 2
+ prev + 1
end
- context "when initial value skipped" do
- it "uses nil instead" do
- ScratchPad.record []
- enum = Enumerator.produce { |prev| ScratchPad << prev; (prev || 0) + 1 }
+ 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
+ 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 }
+ 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
+ lines.should == ["a\n", "b\n", "c\n", "d"]
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
index 0ed1645853..1d3681ab50 100644
--- a/spec/ruby/core/enumerator/yielder/to_proc_spec.rb
+++ b/spec/ruby/core/enumerator/yielder/to_proc_spec.rb
@@ -1,18 +1,16 @@
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" }
+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
+ callable = y.to_proc
+ callable.class.should == Proc
- result = callable.call(1, 2)
- ScratchPad.recorded.should == [[1, 2]]
+ result = callable.call(1, 2)
+ ScratchPad.recorded.should == [[1, 2]]
- result.should == "foobar"
- end
+ result.should == "foobar"
end
end
diff --git a/spec/ruby/core/env/merge_spec.rb b/spec/ruby/core/env/merge_spec.rb
index b418cd11f4..f10662cf79 100644
--- a/spec/ruby/core/env/merge_spec.rb
+++ b/spec/ruby/core/env/merge_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/update'
-ruby_version_is "2.7" do
- describe "ENV.merge!" do
- it_behaves_like :env_update, :merge!
- end
+describe "ENV.merge!" do
+ it_behaves_like :env_update, :merge!
end
diff --git a/spec/ruby/core/env/shared/update.rb b/spec/ruby/core/env/shared/update.rb
index 129a56544c..7d4799955b 100644
--- a/spec/ruby/core/env/shared/update.rb
+++ b/spec/ruby/core/env/shared/update.rb
@@ -15,6 +15,14 @@ describe :env_update, shared: true do
ENV["bar"].should == "1"
end
+ ruby_version_is "3.2" do
+ it "adds the multiple parameter hashes to ENV, returning ENV" do
+ ENV.send(@method, {"foo" => "multi1"}, {"bar" => "multi2"}).should equal(ENV)
+ ENV["foo"].should == "multi1"
+ ENV["bar"].should == "multi2"
+ end
+ end
+
it "returns ENV when no block given" do
ENV.send(@method, {"foo" => "0", "bar" => "1"}).should equal(ENV)
end
@@ -39,23 +47,21 @@ describe :env_update, shared: true do
ENV["bar"].should == "5"
end
- ruby_version_is "2.7" do
- # BUG: https://bugs.ruby-lang.org/issues/16192
- it "does not evaluate the block when the name is new" do
- ENV.delete("bar")
- ENV.send @method, {"foo" => "0"}
- ENV.send(@method, "bar" => "1") { |key, old, new| fail "Should not get here" }
- ENV["bar"].should == "1"
- end
+ # BUG: https://bugs.ruby-lang.org/issues/16192
+ it "does not evaluate the block when the name is new" do
+ ENV.delete("bar")
+ ENV.send @method, {"foo" => "0"}
+ ENV.send(@method, "bar" => "1") { |key, old, new| fail "Should not get here" }
+ ENV["bar"].should == "1"
+ end
- # BUG: https://bugs.ruby-lang.org/issues/16192
- it "does not use the block's return value as the value when the name is new" do
- ENV.delete("bar")
- ENV.send @method, {"foo" => "0"}
- ENV.send(@method, "bar" => "1") { |key, old, new| "Should not use this value" }
- ENV["foo"].should == "0"
- ENV["bar"].should == "1"
- end
+ # BUG: https://bugs.ruby-lang.org/issues/16192
+ it "does not use the block's return value as the value when the name is new" do
+ ENV.delete("bar")
+ ENV.send @method, {"foo" => "0"}
+ ENV.send(@method, "bar" => "1") { |key, old, new| "Should not use this value" }
+ ENV["foo"].should == "0"
+ ENV["bar"].should == "1"
end
it "returns ENV when block given" do
diff --git a/spec/ruby/core/env/shift_spec.rb b/spec/ruby/core/env/shift_spec.rb
index b6c139dc29..1b92e5d1e4 100644
--- a/spec/ruby/core/env/shift_spec.rb
+++ b/spec/ruby/core/env/shift_spec.rb
@@ -2,36 +2,13 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
describe "ENV.shift" do
- it "returns a pair and deletes it" do
- ENV.should_not.empty?
- orig = ENV.to_hash
- begin
- pair = ENV.shift
- ENV.has_key?(pair.first).should == false
- ensure
- ENV.replace orig
- end
- ENV.has_key?(pair.first).should == true
- end
-
- it "returns nil if ENV.empty?" do
- orig = ENV.to_hash
- begin
- ENV.clear
- ENV.shift.should == nil
- ensure
- ENV.replace orig
- end
- end
-end
-
-describe "ENV.shift" do
before :each do
@orig = ENV.to_hash
@external = Encoding.default_external
@internal = Encoding.default_internal
Encoding.default_external = Encoding::BINARY
+ ENV.replace({"FOO"=>"BAR"})
end
after :each do
@@ -40,6 +17,18 @@ describe "ENV.shift" do
ENV.replace @orig
end
+ it "returns a pair and deletes it" do
+ ENV.should.has_key?("FOO")
+ pair = ENV.shift
+ pair.should == ["FOO", "BAR"]
+ ENV.should_not.has_key?("FOO")
+ end
+
+ it "returns nil if ENV.empty?" do
+ ENV.clear
+ ENV.shift.should == nil
+ end
+
it "uses the locale encoding if Encoding.default_internal is nil" do
Encoding.default_internal = nil
diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb
index 095a926e09..a063e522ea 100644
--- a/spec/ruby/core/exception/errno_spec.rb
+++ b/spec/ruby/core/exception/errno_spec.rb
@@ -56,3 +56,12 @@ describe "Errno::ENOTSUP" do
end
end
end
+
+describe "Errno::ENOENT" do
+ it "lets subclasses inherit the default error message" do
+ c = Class.new(Errno::ENOENT)
+ raise c, "custom message"
+ rescue => e
+ e.message.should == "No such file or directory - custom message"
+ end
+end
diff --git a/spec/ruby/core/exception/frozen_error_spec.rb b/spec/ruby/core/exception/frozen_error_spec.rb
index f27b33295c..2efdc239d8 100644
--- a/spec/ruby/core/exception/frozen_error_spec.rb
+++ b/spec/ruby/core/exception/frozen_error_spec.rb
@@ -1,26 +1,22 @@
require_relative '../../spec_helper'
describe "FrozenError.new" do
- ruby_version_is "2.7" do
- it "should take optional receiver argument" do
- o = Object.new
- FrozenError.new("msg", receiver: o).receiver.should equal(o)
- end
+ it "should take optional receiver argument" do
+ o = Object.new
+ FrozenError.new("msg", receiver: o).receiver.should equal(o)
end
end
describe "FrozenError#receiver" do
- ruby_version_is "2.7" do
- it "should return frozen object that modification was attempted on" do
- o = Object.new.freeze
- begin
- def o.x; end
- rescue => e
- e.should be_kind_of(FrozenError)
- e.receiver.should equal(o)
- else
- raise
- end
+ it "should return frozen object that modification was attempted on" do
+ o = Object.new.freeze
+ begin
+ def o.x; end
+ rescue => e
+ e.should be_kind_of(FrozenError)
+ e.receiver.should equal(o)
+ else
+ raise
end
end
end
diff --git a/spec/ruby/core/exception/full_message_spec.rb b/spec/ruby/core/exception/full_message_spec.rb
index 4cece9ebf9..9757a2f407 100644
--- a/spec/ruby/core/exception/full_message_spec.rb
+++ b/spec/ruby/core/exception/full_message_spec.rb
@@ -15,13 +15,19 @@ describe "Exception#full_message" 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: :top).lines
+ full_message[0].should.end_with? "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n"
- 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)"
+ full_message = e.full_message(highlight: true, order: :bottom).lines
+ full_message[0].should == "\e[1mTraceback\e[m (most recent call last):\n"
+ full_message[-1].should.end_with? "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n"
+
+ full_message = e.full_message(highlight: false, order: :top).lines
+ full_message[0].should.end_with? "Some runtime error (RuntimeError)\n"
+
+ full_message = e.full_message(highlight: false, order: :bottom).lines
+ full_message[0].should == "Traceback (most recent call last):\n"
+ full_message[-1].should.end_with? "Some runtime error (RuntimeError)\n"
end
it "supports :order option and places the error message and the backtrace at the top or the bottom" do
@@ -35,9 +41,9 @@ describe "Exception#full_message" do
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")
+ full_message = e.full_message(highlight: false, order: :top).lines
+ full_message[0].should.start_with?("#{__FILE__}:#{__LINE__-1}:in `")
+ full_message[0].should.end_with?("': 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
@@ -45,12 +51,24 @@ describe "Exception#full_message" do
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[0].should.start_with?("#{__FILE__}:#{line}:in `")
+ full_message[0].should.end_with?(": first line (RuntimeError)\n")
full_message[1].should == "second line\n"
end
end
+ it "highlights the entire message when the message contains multiple lines" do
+ begin
+ line = __LINE__; raise "first line\nsecond line\nthird line"
+ rescue => e
+ full_message = e.full_message(highlight: true, order: :top).lines
+ full_message[0].should.start_with?("#{__FILE__}:#{line}:in `")
+ full_message[0].should.end_with?(": \e[1mfirst line (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n")
+ full_message[1].should == "\e[1msecond line\e[m\n"
+ full_message[2].should == "\e[1mthird line\e[m\n"
+ end
+ end
+
it "contains cause of exception" do
begin
begin
diff --git a/spec/ruby/core/exception/interrupt_spec.rb b/spec/ruby/core/exception/interrupt_spec.rb
index a7501efadc..299b5b81f3 100644
--- a/spec/ruby/core/exception/interrupt_spec.rb
+++ b/spec/ruby/core/exception/interrupt_spec.rb
@@ -48,4 +48,13 @@ describe "Interrupt" do
RUBY
out.should == "Interrupt: #{Signal.list["INT"]}\n"
end
+
+ platform_is_not :windows do
+ it "shows the backtrace and has a signaled exit status" do
+ err = IO.popen([*ruby_exe, '-e', 'Process.kill :INT, Process.pid; sleep'], err: [:child, :out], &:read)
+ $?.termsig.should == Signal.list.fetch('INT')
+ err.should.include? ': Interrupt'
+ err.should.include? "from -e:1:in `<main>'"
+ end
+ end
end
diff --git a/spec/ruby/core/exception/signal_exception_spec.rb b/spec/ruby/core/exception/signal_exception_spec.rb
index 566bcb4672..1a0940743f 100644
--- a/spec/ruby/core/exception/signal_exception_spec.rb
+++ b/spec/ruby/core/exception/signal_exception_spec.rb
@@ -93,7 +93,7 @@ describe "SignalException" do
platform_is_not :windows do
it "runs after at_exit" do
- output = ruby_exe(<<-RUBY, exit_status: nil)
+ output = ruby_exe(<<-RUBY, exit_status: :SIGKILL)
at_exit do
puts "hello"
$stdout.flush
@@ -107,7 +107,7 @@ describe "SignalException" do
end
it "cannot be trapped with Signal.trap" do
- ruby_exe(<<-RUBY, exit_status: nil)
+ ruby_exe(<<-RUBY, exit_status: :SIGPROF)
Signal.trap("PROF") {}
raise(SignalException, "PROF")
RUBY
@@ -116,7 +116,7 @@ describe "SignalException" do
end
it "self-signals for USR1" do
- ruby_exe("raise(SignalException, 'USR1')", exit_status: nil)
+ ruby_exe("raise(SignalException, 'USR1')", exit_status: :SIGUSR1)
$?.termsig.should == Signal.list.fetch('USR1')
end
end
diff --git a/spec/ruby/core/exception/system_exit_spec.rb b/spec/ruby/core/exception/system_exit_spec.rb
index eef9faf271..d899844c4e 100644
--- a/spec/ruby/core/exception/system_exit_spec.rb
+++ b/spec/ruby/core/exception/system_exit_spec.rb
@@ -1,6 +1,48 @@
require_relative '../../spec_helper'
describe "SystemExit" do
+ describe "#initialize" do
+ it "accepts a status and message" do
+ exc = SystemExit.new(42, "message")
+ exc.status.should == 42
+ exc.message.should == "message"
+
+ exc = SystemExit.new(true, "message")
+ exc.status.should == 0
+ exc.message.should == "message"
+
+ exc = SystemExit.new(false, "message")
+ exc.status.should == 1
+ exc.message.should == "message"
+ end
+
+ it "accepts a status only" do
+ exc = SystemExit.new(42)
+ exc.status.should == 42
+ exc.message.should == "SystemExit"
+
+ exc = SystemExit.new(true)
+ exc.status.should == 0
+ exc.message.should == "SystemExit"
+
+ exc = SystemExit.new(false)
+ exc.status.should == 1
+ exc.message.should == "SystemExit"
+ end
+
+ it "accepts a message only" do
+ exc = SystemExit.new("message")
+ exc.status.should == 0
+ exc.message.should == "message"
+ end
+
+ it "accepts no arguments" do
+ exc = SystemExit.new
+ exc.status.should == 0
+ exc.message.should == "SystemExit"
+ end
+ end
+
it "sets the exit status and exits silently when raised" do
code = 'raise SystemExit.new(7)'
result = ruby_exe(code, args: "2>&1", exit_status: 7)
diff --git a/spec/ruby/core/false/case_compare_spec.rb b/spec/ruby/core/false/case_compare_spec.rb
new file mode 100644
index 0000000000..0bd0ab44ae
--- /dev/null
+++ b/spec/ruby/core/false/case_compare_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "FalseClass#===" do
+ it "returns true for false" do
+ (false === false).should == true
+ end
+
+ it "returns false for non-false object" do
+ (false === 0).should == false
+ (false === "").should == false
+ (false === Object).should == false
+ (false === nil).should == false
+ end
+end
diff --git a/spec/ruby/core/false/to_s_spec.rb b/spec/ruby/core/false/to_s_spec.rb
index 4cae278891..62f67f6f55 100644
--- a/spec/ruby/core/false/to_s_spec.rb
+++ b/spec/ruby/core/false/to_s_spec.rb
@@ -5,13 +5,11 @@ describe "FalseClass#to_s" do
false.to_s.should == "false"
end
- ruby_version_is "2.7" do
- it "returns a frozen string" do
- false.to_s.should.frozen?
- end
+ it "returns a frozen string" do
+ false.to_s.should.frozen?
+ end
- it "always returns the same string" do
- false.to_s.should equal(false.to_s)
- end
+ it "always returns the same string" do
+ false.to_s.should equal(false.to_s)
end
end
diff --git a/spec/ruby/core/fiber/blocking_spec.rb b/spec/ruby/core/fiber/blocking_spec.rb
new file mode 100644
index 0000000000..eeee5a71c1
--- /dev/null
+++ b/spec/ruby/core/fiber/blocking_spec.rb
@@ -0,0 +1,79 @@
+require_relative '../../spec_helper'
+require_relative 'shared/blocking'
+
+ruby_version_is "3.0" do
+ require "fiber"
+
+ describe "Fiber.blocking?" do
+ it_behaves_like :non_blocking_fiber, -> { Fiber.blocking? }
+
+ context "when fiber is blocking" do
+ context "root Fiber of the main thread" do
+ it "returns 1 for blocking: true" do
+ fiber = Fiber.new(blocking: true) { Fiber.blocking? }
+ blocking = fiber.resume
+
+ blocking.should == 1
+ end
+ end
+
+ context "root Fiber of a new thread" do
+ it "returns 1 for blocking: true" do
+ thread = Thread.new do
+ fiber = Fiber.new(blocking: true) { Fiber.blocking? }
+ blocking = fiber.resume
+
+ blocking.should == 1
+ end
+
+ thread.join
+ end
+ end
+ end
+ end
+
+ describe "Fiber#blocking?" do
+ it_behaves_like :non_blocking_fiber, -> { Fiber.current.blocking? }
+
+ context "when fiber is blocking" do
+ context "root Fiber of the main thread" do
+ it "returns true for blocking: true" do
+ fiber = Fiber.new(blocking: true) { Fiber.current.blocking? }
+ blocking = fiber.resume
+
+ blocking.should == true
+ end
+ end
+
+ context "root Fiber of a new thread" do
+ it "returns true for blocking: true" do
+ thread = Thread.new do
+ fiber = Fiber.new(blocking: true) { Fiber.current.blocking? }
+ blocking = fiber.resume
+
+ blocking.should == true
+ end
+
+ thread.join
+ end
+ end
+ end
+ end
+end
+
+ruby_version_is "3.2" do
+ describe "Fiber.blocking" do
+ context "when fiber is non-blocking" do
+ it "can become blocking" do
+ fiber = Fiber.new(blocking: false) do
+ Fiber.blocking do |f|
+ f.blocking? ? :blocking : :non_blocking
+ end
+ end
+
+ blocking = fiber.resume
+ blocking.should == :blocking
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
index 2a465c8bfa..09c4c1b524 100644
--- a/spec/ruby/core/fiber/raise_spec.rb
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -2,101 +2,99 @@ 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
+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
- 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 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 "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 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 '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 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 '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 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 '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 '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 "raises a FiberError if invoked from a different Thread" do
- fiber = Fiber.new { Fiber.yield }
- fiber.resume
- Thread.new do
- -> {
- fiber.raise
- }.should raise_error(FiberError, "fiber called across threads")
- end.join
- end
+ it "kills Fiber" do
+ fiber = Fiber.new { Fiber.yield :first; :second }
+ fiber.resume
+ -> { fiber.raise }.should raise_error
+ -> { fiber.resume }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ end
- it "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/)
+ it "returns to calling fiber after raise" do
+ fiber_one = Fiber.new do
+ Fiber.yield :yield_one
+ :unreachable
end
- it "returns to calling fiber after raise" do
- fiber_one = Fiber.new do
- Fiber.yield :yield_one
- :unreachable
- end
-
- fiber_two = Fiber.new do
- results = []
- results << fiber_one.resume
- begin
- fiber_one.raise
- rescue
- results << :rescued
- end
- results
+ fiber_two = Fiber.new do
+ results = []
+ results << fiber_one.resume
+ begin
+ fiber_one.raise
+ rescue
+ results << :rescued
end
-
- fiber_two.resume.should == [:yield_one, :rescued]
+ results
end
- end
+ fiber_two.resume.should == [:yield_one, :rescued]
+ end
end
-ruby_version_is "2.7"..."3.0" do
+
+ruby_version_is ""..."3.0" do
describe "Fiber#raise" do
it "raises a FiberError if invoked on a transferring Fiber" do
require "fiber"
diff --git a/spec/ruby/core/fiber/shared/blocking.rb b/spec/ruby/core/fiber/shared/blocking.rb
new file mode 100644
index 0000000000..21707e1ea7
--- /dev/null
+++ b/spec/ruby/core/fiber/shared/blocking.rb
@@ -0,0 +1,41 @@
+describe :non_blocking_fiber, shared: true do
+ context "root Fiber of the main thread" do
+ it "returns false" do
+ fiber = Fiber.new { @method.call }
+ blocking = fiber.resume
+
+ blocking.should == false
+ end
+
+ it "returns false for blocking: false" do
+ fiber = Fiber.new(blocking: false) { @method.call }
+ blocking = fiber.resume
+
+ blocking.should == false
+ end
+ end
+
+ context "root Fiber of a new thread" do
+ it "returns false" do
+ thread = Thread.new do
+ fiber = Fiber.new { @method.call }
+ blocking = fiber.resume
+
+ blocking.should == false
+ end
+
+ thread.join
+ end
+
+ it "returns false for blocking: false" do
+ thread = Thread.new do
+ fiber = Fiber.new(blocking: false) { @method.call }
+ blocking = fiber.resume
+
+ blocking.should == false
+ end
+
+ thread.join
+ end
+ end
+end
diff --git a/spec/ruby/core/fiber/storage_spec.rb b/spec/ruby/core/fiber/storage_spec.rb
new file mode 100644
index 0000000000..e2bf6da04c
--- /dev/null
+++ b/spec/ruby/core/fiber/storage_spec.rb
@@ -0,0 +1,117 @@
+require_relative '../../spec_helper'
+
+require 'fiber'
+
+describe "Fiber.new(storage:)" do
+ ruby_version_is "3.2" do
+ it "creates a Fiber with the given storage" do
+ storage = {life: 42}
+ fiber = Fiber.new(storage: storage) { Fiber.current.storage }
+ fiber.resume.should == storage
+ end
+
+ it "creates a fiber with lazily initialized storage" do
+ Fiber.new(storage: nil) { Fiber.current.storage }.resume.should == {}
+ end
+
+ it "creates a fiber by inheriting the storage of the parent fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.new { Fiber.current.storage }.resume
+ end
+ fiber.resume.should == {life: 42}
+ end
+
+ it "cannot create a fiber with non-hash storage" do
+ -> { Fiber.new(storage: 42) {} }.should raise_error(TypeError)
+ end
+ end
+end
+
+describe "Fiber#storage=" do
+ ruby_version_is "3.2" do
+ it "can clear the storage of the fiber" do
+ fiber = Fiber.new(storage: {life: 42}) {
+ Fiber.current.storage = nil
+ Fiber.current.storage
+ }
+ fiber.resume.should == {}
+ end
+
+ it "can set the storage of the fiber" do
+ fiber = Fiber.new(storage: {life: 42}) {
+ Fiber.current.storage = {life: 43}
+ Fiber.current.storage
+ }
+ fiber.resume.should == {life: 43}
+ end
+
+ it "can't set the storage of the fiber to non-hash" do
+ -> { Fiber.current.storage = 42 }.should raise_error(TypeError)
+ end
+
+ it "can't set the storage of the fiber to a frozen hash" do
+ -> { Fiber.current.storage = {life: 43}.freeze }.should raise_error(FrozenError)
+ end
+
+ it "can't set the storage of the fiber to a hash with non-symbol keys" do
+ -> { Fiber.current.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError)
+ end
+ end
+end
+
+describe "Fiber.[]" do
+ ruby_version_is "3.2" do
+ it "returns the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42
+ end
+
+ it "returns nil if the key is not present in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should be_nil
+ end
+
+ it "returns nil if the current fiber has no storage" do
+ Fiber.new { Fiber[:life] }.resume.should be_nil
+ end
+ end
+
+ ruby_version_is "3.2.3" do
+ it "can use dynamically defined keys" do
+ key = :"#{self.class.name}#.#{self.object_id}"
+ Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
+ end
+
+ it "can't use invalid keys" do
+ invalid_keys = [Object.new, "Foo", 12]
+ invalid_keys.each do |key|
+ -> { Fiber[key] }.should raise_error(TypeError)
+ end
+ end
+ end
+end
+
+describe "Fiber.[]=" do
+ ruby_version_is "3.2" do
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
+ end
+
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43
+ end
+
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
+ end
+ end
+end
+
+describe "Thread.new" do
+ ruby_version_is "3.2" do
+ it "creates a thread with the storage of the current fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Thread.new { Fiber.current.storage }.value
+ end
+ fiber.resume.should == {life: 42}
+ end
+ end
+end
diff --git a/spec/ruby/core/file/absolute_path_spec.rb b/spec/ruby/core/file/absolute_path_spec.rb
index 9f39923472..e35c80ec3c 100644
--- a/spec/ruby/core/file/absolute_path_spec.rb
+++ b/spec/ruby/core/file/absolute_path_spec.rb
@@ -1,54 +1,52 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "File.absolute_path?" do
- before :each do
- @abs = File.expand_path(__FILE__)
- end
+describe "File.absolute_path?" do
+ before :each do
+ @abs = File.expand_path(__FILE__)
+ end
- it "returns true if it's an absolute pathname" do
- File.absolute_path?(@abs).should be_true
- end
+ it "returns true if it's an absolute pathname" do
+ File.absolute_path?(@abs).should be_true
+ end
- it "returns false if it's a relative path" do
- File.absolute_path?(File.basename(__FILE__)).should be_false
- end
+ it "returns false if it's a relative path" do
+ File.absolute_path?(File.basename(__FILE__)).should be_false
+ end
- it "returns false if it's a tricky relative path" do
- File.absolute_path?("C:foo\\bar").should be_false
- end
+ it "returns false if it's a tricky relative path" do
+ File.absolute_path?("C:foo\\bar").should be_false
+ end
- it "does not expand '~' to a home directory." do
- File.absolute_path?('~').should be_false
- end
+ it "does not expand '~' to a home directory." do
+ File.absolute_path?('~').should be_false
+ end
- it "does not expand '~user' to a home directory." do
- path = File.dirname(@abs)
- Dir.chdir(path) do
- File.absolute_path?('~user').should be_false
- end
+ it "does not expand '~user' to a home directory." do
+ path = File.dirname(@abs)
+ Dir.chdir(path) do
+ File.absolute_path?('~user').should be_false
end
+ end
- it "calls #to_path on its argument" do
- mock = mock_to_path(File.expand_path(__FILE__))
+ it "calls #to_path on its argument" do
+ mock = mock_to_path(File.expand_path(__FILE__))
- File.absolute_path?(mock).should be_true
- end
+ File.absolute_path?(mock).should be_true
+ end
- platform_is_not :windows do
- it "takes into consideration the platform's root" do
- File.absolute_path?("C:\\foo\\bar").should be_false
- File.absolute_path?("C:/foo/bar").should be_false
- File.absolute_path?("/foo/bar\\baz").should be_true
- end
+ platform_is_not :windows do
+ it "takes into consideration the platform's root" do
+ File.absolute_path?("C:\\foo\\bar").should be_false
+ File.absolute_path?("C:/foo/bar").should be_false
+ File.absolute_path?("/foo/bar\\baz").should be_true
end
+ end
- platform_is :windows do
- it "takes into consideration the platform path separator(s)" do
- File.absolute_path?("C:\\foo\\bar").should be_true
- File.absolute_path?("C:/foo/bar").should be_true
- File.absolute_path?("/foo/bar\\baz").should be_false
- end
+ platform_is :windows do
+ it "takes into consideration the platform path separator(s)" do
+ File.absolute_path?("C:\\foo\\bar").should be_true
+ File.absolute_path?("C:/foo/bar").should be_true
+ File.absolute_path?("/foo/bar\\baz").should be_false
end
end
end
diff --git a/spec/ruby/core/file/atime_spec.rb b/spec/ruby/core/file/atime_spec.rb
index cef07ba010..3df258016c 100644
--- a/spec/ruby/core/file/atime_spec.rb
+++ b/spec/ruby/core/file/atime_spec.rb
@@ -15,11 +15,11 @@ describe "File.atime" do
File.atime(@file).should be_kind_of(Time)
end
- platform_is :linux, :windows do
- platform_is_not :"powerpc64le-linux" do # https://bugs.ruby-lang.org/issues/17926
+ platform_is :linux do
+ unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926
## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed.
it "returns the last access time for the named file with microseconds" do
- supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10)
+ supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
expected_time = Time.at(Time.now.to_i + 0.123456)
File.utime expected_time, 0, @file
diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb
index b16eb13c1e..9b7ab272ff 100644
--- a/spec/ruby/core/file/ctime_spec.rb
+++ b/spec/ruby/core/file/ctime_spec.rb
@@ -14,9 +14,9 @@ describe "File.ctime" do
File.ctime(@file).should be_kind_of(Time)
end
- platform_is :linux, :windows do
+ platform_is :linux 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)
+ supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
File.ctime(__FILE__).usec.should > 0
else
diff --git a/spec/ruby/core/file/extname_spec.rb b/spec/ruby/core/file/extname_spec.rb
index e182ed44f2..d20cf813d9 100644
--- a/spec/ruby/core/file/extname_spec.rb
+++ b/spec/ruby/core/file/extname_spec.rb
@@ -33,14 +33,14 @@ describe "File.extname" do
end
describe "for a filename ending with a dot" do
- guard -> { platform_is :windows or ruby_version_is ""..."2.7" } do
+ platform_is :windows do
it "returns ''" do
File.extname(".foo.").should == ""
File.extname("foo.").should == ""
end
end
- guard -> { platform_is_not :windows and ruby_version_is "2.7" } do
+ platform_is_not :windows do
it "returns '.'" do
File.extname(".foo.").should == "."
File.extname("foo.").should == "."
diff --git a/spec/ruby/core/file/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb
index 8d47d3021a..6c43265a2c 100644
--- a/spec/ruby/core/file/mtime_spec.rb
+++ b/spec/ruby/core/file/mtime_spec.rb
@@ -15,15 +15,17 @@ describe "File.mtime" do
File.mtime(@filename).should be_close(@mtime, TIME_TOLERANCE)
end
- 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
- expected_time = Time.at(Time.now.to_i + 0.123456)
- File.utime 0, expected_time, @filename
- File.mtime(@filename).usec.should == expected_time.usec
- else
- File.mtime(__FILE__).usec.should == 0
+ platform_is :linux do
+ unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926
+ it "returns the modification Time of the file with microseconds" do
+ supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
+ if supports_subseconds != 0
+ expected_time = Time.at(Time.now.to_i + 0.123456)
+ File.utime 0, expected_time, @filename
+ File.mtime(@filename).usec.should == expected_time.usec
+ else
+ File.mtime(__FILE__).usec.should == 0
+ end
end
end
end
diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb
index c7dd34d5c6..1729780570 100644
--- a/spec/ruby/core/file/open_spec.rb
+++ b/spec/ruby/core/file/open_spec.rb
@@ -494,6 +494,14 @@ describe "File.open" do
File.open(@file, "w") { |f| f.puts "testing" }
File.size(@file).should > 0
File.open(@file, "rb+") do |f|
+ f.binmode?.should == true
+ f.external_encoding.should == Encoding::ASCII_8BIT
+ f.pos.should == 0
+ f.should_not.eof?
+ end
+ File.open(@file, "r+b") do |f|
+ f.binmode?.should == true
+ f.external_encoding.should == Encoding::ASCII_8BIT
f.pos.should == 0
f.should_not.eof?
end
diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb
index a8488fd30a..94f22144b0 100644
--- a/spec/ruby/core/file/shared/fnmatch.rb
+++ b/spec/ruby/core/file/shared/fnmatch.rb
@@ -75,6 +75,14 @@ describe :file_fnmatch, shared: true do
File.send(@method, 'c*t', 'c/a/b/t').should == true
end
+ it "does not match unterminated range of characters" do
+ File.send(@method, 'abc[de', 'abcd').should == false
+ end
+
+ it "does not match unterminated range of characters as a literal" do
+ File.send(@method, 'abc[de', 'abc[de').should == false
+ end
+
it "matches ranges of characters using bracket expression (e.g. [a-z])" do
File.send(@method, 'ca[a-z]', 'cat').should == true
end
@@ -151,10 +159,10 @@ describe :file_fnmatch, shared: true do
end
it "does not match leading periods in filenames with wildcards by default" do
- File.send(@method, '*', '.profile').should == false
- File.send(@method, '*', 'home/.profile').should == true
- File.send(@method, '*/*', 'home/.profile').should == true
- File.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME).should == false
+ File.should_not.send(@method, '*', '.profile')
+ File.should.send(@method, '*', 'home/.profile')
+ File.should.send(@method, '*/*', 'home/.profile')
+ File.should_not.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME)
end
it "matches patterns with leading periods to dotfiles by default" do
diff --git a/spec/ruby/core/file/shared/path.rb b/spec/ruby/core/file/shared/path.rb
index 0a5abe33f0..ee8109ba05 100644
--- a/spec/ruby/core/file/shared/path.rb
+++ b/spec/ruby/core/file/shared/path.rb
@@ -78,13 +78,15 @@ describe :file_path, shared: true 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)
+ ruby_version_is ""..."3.1" do
+ it "raises IOError if file was opened with File::TMPFILE" do
+ begin
+ File.open(@dir, File::RDWR | File::TMPFILE) do |f|
+ -> { f.send(@method) }.should raise_error(IOError)
+ end
+ rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
+ skip "no support from the filesystem"
end
- rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
- skip "no support from the filesystem"
end
end
end
diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb
index 19cb80d5f8..cf7a0aec20 100644
--- a/spec/ruby/core/file/utime_spec.rb
+++ b/spec/ruby/core/file/utime_spec.rb
@@ -19,18 +19,20 @@ describe "File.utime" do
rm_r @file1, @file2
end
- it "sets the access and modification time of each file" do
- File.utime(@atime, @mtime, @file1, @file2)
- if @time_is_float
- File.atime(@file1).should be_close(@atime, 0.0001)
- File.mtime(@file1).should be_close(@mtime, 0.0001)
- File.atime(@file2).should be_close(@atime, 0.0001)
- File.mtime(@file2).should be_close(@mtime, 0.0001)
- else
- File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
- File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
- File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
- File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ platform_is_not :windows do
+ it "sets the access and modification time of each file" do
+ File.utime(@atime, @mtime, @file1, @file2)
+ if @time_is_float
+ File.atime(@file1).should be_close(@atime, 0.0001)
+ File.mtime(@file1).should be_close(@mtime, 0.0001)
+ File.atime(@file2).should be_close(@atime, 0.0001)
+ File.mtime(@file2).should be_close(@mtime, 0.0001)
+ else
+ File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
+ File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE)
+ File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE)
+ end
end
end
@@ -70,19 +72,32 @@ describe "File.utime" do
end
end
+ it "may set nanosecond precision" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
+ File.utime(t, t, @file1)
+ File.atime(@file1).nsec.should.between?(0, 123500000)
+ File.mtime(@file1).nsec.should.between?(0, 123500000)
+ end
+
+ it "returns the number of filenames in the arguments" do
+ File.utime(@atime.to_f, @mtime.to_f, @file1, @file2).should == 2
+ end
+
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 or 2038-01-19)" do
+ it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do
# https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
# "Therefore, timestamps should not overflow until May 2446."
# 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
+ # Amazon Linux 2023 returns 2486-07-02 in this example
+ # http://rubyci.s3.amazonaws.com/amazon2023/ruby-master/log/20230322T063004Z.fail.html.gz
time = Time.at(1<<44)
File.utime(time, time, @file1)
- [559444, 2446, 2038].should.include? File.atime(@file1).year
- [559444, 2446, 2038].should.include? File.mtime(@file1).year
+ [559444, 2486, 2446, 2038].should.include? File.atime(@file1).year
+ [559444, 2486, 2446, 2038].should.include? File.mtime(@file1).year
end
end
end
diff --git a/spec/ruby/core/float/coerce_spec.rb b/spec/ruby/core/float/coerce_spec.rb
index ea108f3303..baa831dcf6 100644
--- a/spec/ruby/core/float/coerce_spec.rb
+++ b/spec/ruby/core/float/coerce_spec.rb
@@ -9,10 +9,10 @@ describe "Float#coerce" do
1.0.coerce(3.14).should == [3.14, 1.0]
a, b = -0.0.coerce(bignum_value)
- a.should be_close(9223372036854775808.0, TOLERANCE)
+ a.should be_close(18446744073709551616.0, TOLERANCE)
b.should be_close(-0.0, TOLERANCE)
a, b = 1.0.coerce(bignum_value)
- a.should be_close(9223372036854775808.0, TOLERANCE)
+ a.should be_close(18446744073709551616.0, TOLERANCE)
b.should be_close(1.0, TOLERANCE)
end
end
diff --git a/spec/ruby/core/float/comparison_spec.rb b/spec/ruby/core/float/comparison_spec.rb
index e367198903..1373b3a1fb 100644
--- a/spec/ruby/core/float/comparison_spec.rb
+++ b/spec/ruby/core/float/comparison_spec.rb
@@ -7,13 +7,32 @@ describe "Float#<=>" do
((bignum_value*1.1) <=> bignum_value).should == 1
end
- it "returns nil when either argument is NaN" do
- (nan_value <=> 71.2).should be_nil
- (1771.176 <=> nan_value).should be_nil
+ it "returns nil if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value <=> n).should == nil
+ (n <=> nan_value).should == nil
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value <=> n).should == 1
+ (n <=> infinity_value).should == -1
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value <=> n).should == -1
+ (n <=> -infinity_value).should == 1
+ }
end
it "returns nil when the given argument is not a Float" do
(1.0 <=> "1").should be_nil
+ (1.0 <=> "1".freeze).should be_nil
+ (1.0 <=> :one).should be_nil
+ (1.0 <=> true).should be_nil
end
it "compares using #coerce when argument is not a Float" do
@@ -46,21 +65,10 @@ describe "Float#<=>" do
}.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 an Integer" do
+ it "returns the correct result when one side is infinite" do
(infinity_value <=> Float::MAX.to_i*2).should == 1
- end
-
- it "returns -1 when self is negative and other is Infinity" do
(-Float::MAX.to_i*2 <=> infinity_value).should == -1
- end
-
- it "returns -1 when self is -Infinity and other is negative" do
(-infinity_value <=> -Float::MAX.to_i*2).should == -1
- end
-
- it "returns 1 when self is negative and other is -Infinity" do
(-Float::MAX.to_i*2 <=> -infinity_value).should == 1
end
@@ -87,4 +95,19 @@ describe "Float#<=>" do
end
(infinity_value <=> obj).should == 1
end
+
+ it "returns 0 for -0.0 and 0.0" do
+ (-0.0 <=> 0.0).should == 0
+ (0.0 <=> -0.0).should == 0
+ end
+
+ it "returns 0 for -0.0 and 0" do
+ (-0.0 <=> 0).should == 0
+ (0 <=> -0.0).should == 0
+ end
+
+ it "returns 0 for 0.0 and 0" do
+ (0.0 <=> 0).should == 0
+ (0 <=> 0.0).should == 0
+ end
end
diff --git a/spec/ruby/core/float/divide_spec.rb b/spec/ruby/core/float/divide_spec.rb
index d8f71a6b98..72ab7527bd 100644
--- a/spec/ruby/core/float/divide_spec.rb
+++ b/spec/ruby/core/float/divide_spec.rb
@@ -36,4 +36,8 @@ describe "Float#/" do
-> { 13.0 / "10" }.should raise_error(TypeError)
-> { 13.0 / :symbol }.should raise_error(TypeError)
end
+
+ it "divides correctly by Rational numbers" do
+ (1.2345678901234567 / Rational(1, 10000000000000000000)).should == 1.2345678901234567e+19
+ end
end
diff --git a/spec/ruby/core/float/divmod_spec.rb b/spec/ruby/core/float/divmod_spec.rb
index ec55dd3681..dad45a9b89 100644
--- a/spec/ruby/core/float/divmod_spec.rb
+++ b/spec/ruby/core/float/divmod_spec.rb
@@ -10,7 +10,7 @@ describe "Float#divmod" do
values[1].should be_close(2.8284, TOLERANCE)
values = -1.0.divmod(bignum_value)
values[0].should eql(-1)
- values[1].should be_close(9223372036854775808.000, TOLERANCE)
+ values[1].should be_close(18446744073709551616.0, TOLERANCE)
values = -1.0.divmod(1)
values[0].should eql(-1)
values[1].should eql(0.0)
@@ -23,7 +23,7 @@ describe "Float#divmod" do
# Behaviour established as correct in r23953
it "raises a FloatDomainError if other is NaN" do
- -> { 1.divmod(nan_value) }.should raise_error(FloatDomainError)
+ -> { 1.0.divmod(nan_value) }.should raise_error(FloatDomainError)
end
# Behaviour established as correct in r23953
diff --git a/spec/ruby/core/float/gt_spec.rb b/spec/ruby/core/float/gt_spec.rb
index 0d73f1c3df..33078e07ce 100644
--- a/spec/ruby/core/float/gt_spec.rb
+++ b/spec/ruby/core/float/gt_spec.rb
@@ -14,4 +14,25 @@ describe "Float#>" do
-> { 5.0 > "4" }.should raise_error(ArgumentError)
-> { 5.0 > mock('x') }.should raise_error(ArgumentError)
end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value > n).should == false
+ (n > nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value > n).should == true
+ (n > infinity_value).should == false
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value > n).should == false
+ (n > -infinity_value).should == true
+ }
+ end
end
diff --git a/spec/ruby/core/float/gte_spec.rb b/spec/ruby/core/float/gte_spec.rb
index 98ec60b70b..44c0a81b43 100644
--- a/spec/ruby/core/float/gte_spec.rb
+++ b/spec/ruby/core/float/gte_spec.rb
@@ -14,4 +14,25 @@ describe "Float#>=" do
-> { 5.0 >= "4" }.should raise_error(ArgumentError)
-> { 5.0 >= mock('x') }.should raise_error(ArgumentError)
end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value >= n).should == false
+ (n >= nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value >= n).should == true
+ (n >= infinity_value).should == false
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value >= n).should == false
+ (n >= -infinity_value).should == true
+ }
+ end
end
diff --git a/spec/ruby/core/float/lt_spec.rb b/spec/ruby/core/float/lt_spec.rb
index c01b6e0e02..94dcfc42f8 100644
--- a/spec/ruby/core/float/lt_spec.rb
+++ b/spec/ruby/core/float/lt_spec.rb
@@ -14,4 +14,25 @@ describe "Float#<" do
-> { 5.0 < "4" }.should raise_error(ArgumentError)
-> { 5.0 < mock('x') }.should raise_error(ArgumentError)
end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value < n).should == false
+ (n < nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value < n).should == false
+ (n < infinity_value).should == true
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value < n).should == true
+ (n < -infinity_value).should == false
+ }
+ end
end
diff --git a/spec/ruby/core/float/lte_spec.rb b/spec/ruby/core/float/lte_spec.rb
index 66f2ddc2c7..7b5a86ee76 100644
--- a/spec/ruby/core/float/lte_spec.rb
+++ b/spec/ruby/core/float/lte_spec.rb
@@ -15,4 +15,25 @@ describe "Float#<=" do
-> { 5.0 <= "4" }.should raise_error(ArgumentError)
-> { 5.0 <= mock('x') }.should raise_error(ArgumentError)
end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value <= n).should == false
+ (n <= nan_value).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value <= n).should == false
+ (n <= infinity_value).should == true
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (-infinity_value <= n).should == true
+ (n <= -infinity_value).should == false
+ }
+ end
end
diff --git a/spec/ruby/core/float/minus_spec.rb b/spec/ruby/core/float/minus_spec.rb
index 5626cbdac2..a4281a397b 100644
--- a/spec/ruby/core/float/minus_spec.rb
+++ b/spec/ruby/core/float/minus_spec.rb
@@ -6,7 +6,7 @@ describe "Float#-" do
it "returns self minus other" do
(9_237_212.5280 - 5_280).should be_close(9231932.528, TOLERANCE)
- (2_560_496.1691 - bignum_value).should be_close(-9223372036852215808.000, TOLERANCE)
+ (2_560_496.1691 - bignum_value).should be_close(-18446744073706991616.0, TOLERANCE)
(5.5 - 5.5).should be_close(0.0,TOLERANCE)
end
end
diff --git a/spec/ruby/core/float/multiply_spec.rb b/spec/ruby/core/float/multiply_spec.rb
index eca0b52c4f..2adb8796cd 100644
--- a/spec/ruby/core/float/multiply_spec.rb
+++ b/spec/ruby/core/float/multiply_spec.rb
@@ -7,7 +7,7 @@ describe "Float#*" do
it "returns self multiplied by other" do
(4923.98221 * 2).should be_close(9847.96442, TOLERANCE)
(6712.5 * 0.25).should be_close(1678.125, TOLERANCE)
- (256.4096 * bignum_value).should be_close(2364961134621118431232.000, TOLERANCE)
+ (256.4096 * bignum_value).should be_close(4729922269242236862464.0, TOLERANCE)
end
it "raises a TypeError when given a non-Numeric" do
diff --git a/spec/ruby/core/float/plus_spec.rb b/spec/ruby/core/float/plus_spec.rb
index 06b136a06b..e3e19d7f39 100644
--- a/spec/ruby/core/float/plus_spec.rb
+++ b/spec/ruby/core/float/plus_spec.rb
@@ -6,7 +6,7 @@ describe "Float#+" do
it "returns self plus other" do
(491.213 + 2).should be_close(493.213, TOLERANCE)
- (9.99 + bignum_value).should be_close(9223372036854775808.000, TOLERANCE)
+ (9.99 + bignum_value).should be_close(18446744073709551616.0, TOLERANCE)
(1001.99 + 5.219).should be_close(1007.209, TOLERANCE)
end
end
diff --git a/spec/ruby/core/float/round_spec.rb b/spec/ruby/core/float/round_spec.rb
index 4bd2dc460c..e5a8f534e7 100644
--- a/spec/ruby/core/float/round_spec.rb
+++ b/spec/ruby/core/float/round_spec.rb
@@ -103,6 +103,70 @@ describe "Float#round" do
5.55.round(1, half: :up).should eql(5.6)
5.55.round(1, half: :down).should eql(5.5)
5.55.round(1, half: :even).should eql(5.6)
+ -5.55.round(1, half: nil).should eql(-5.6)
+ -5.55.round(1, half: :up).should eql(-5.6)
+ -5.55.round(1, half: :down).should eql(-5.5)
+ -5.55.round(1, half: :even).should eql(-5.6)
+ end
+
+ it "preserves cases where neighbouring floating pointer number increase the decimal places" do
+ 4.8100000000000005.round(5, half: nil).should eql(4.81)
+ 4.8100000000000005.round(5, half: :up).should eql(4.81)
+ 4.8100000000000005.round(5, half: :down).should eql(4.81)
+ 4.8100000000000005.round(5, half: :even).should eql(4.81)
+ -4.8100000000000005.round(5, half: nil).should eql(-4.81)
+ -4.8100000000000005.round(5, half: :up).should eql(-4.81)
+ -4.8100000000000005.round(5, half: :down).should eql(-4.81)
+ -4.8100000000000005.round(5, half: :even).should eql(-4.81)
+ 4.81.round(5, half: nil).should eql(4.81)
+ 4.81.round(5, half: :up).should eql(4.81)
+ 4.81.round(5, half: :down).should eql(4.81)
+ 4.81.round(5, half: :even).should eql(4.81)
+ -4.81.round(5, half: nil).should eql(-4.81)
+ -4.81.round(5, half: :up).should eql(-4.81)
+ -4.81.round(5, half: :down).should eql(-4.81)
+ -4.81.round(5, half: :even).should eql(-4.81)
+ 4.809999999999999.round(5, half: nil).should eql(4.81)
+ 4.809999999999999.round(5, half: :up).should eql(4.81)
+ 4.809999999999999.round(5, half: :down).should eql(4.81)
+ 4.809999999999999.round(5, half: :even).should eql(4.81)
+ -4.809999999999999.round(5, half: nil).should eql(-4.81)
+ -4.809999999999999.round(5, half: :up).should eql(-4.81)
+ -4.809999999999999.round(5, half: :down).should eql(-4.81)
+ -4.809999999999999.round(5, half: :even).should eql(-4.81)
+ end
+
+ ruby_bug "", ""..."3.3" do
+ # These numbers are neighbouring floating point numbers round a
+ # precise value. They test that the rounding modes work correctly
+ # round that value and precision is not lost which might cause
+ # incorrect results.
+ it "does not lose precision during the rounding process" do
+ 767573.1875850001.round(5, half: nil).should eql(767573.18759)
+ 767573.1875850001.round(5, half: :up).should eql(767573.18759)
+ 767573.1875850001.round(5, half: :down).should eql(767573.18759)
+ 767573.1875850001.round(5, half: :even).should eql(767573.18759)
+ -767573.1875850001.round(5, half: nil).should eql(-767573.18759)
+ -767573.1875850001.round(5, half: :up).should eql(-767573.18759)
+ -767573.1875850001.round(5, half: :down).should eql(-767573.18759)
+ -767573.1875850001.round(5, half: :even).should eql(-767573.18759)
+ 767573.187585.round(5, half: nil).should eql(767573.18759)
+ 767573.187585.round(5, half: :up).should eql(767573.18759)
+ 767573.187585.round(5, half: :down).should eql(767573.18758)
+ 767573.187585.round(5, half: :even).should eql(767573.18758)
+ -767573.187585.round(5, half: nil).should eql(-767573.18759)
+ -767573.187585.round(5, half: :up).should eql(-767573.18759)
+ -767573.187585.round(5, half: :down).should eql(-767573.18758)
+ -767573.187585.round(5, half: :even).should eql(-767573.18758)
+ 767573.1875849998.round(5, half: nil).should eql(767573.18758)
+ 767573.1875849998.round(5, half: :up).should eql(767573.18758)
+ 767573.1875849998.round(5, half: :down).should eql(767573.18758)
+ 767573.1875849998.round(5, half: :even).should eql(767573.18758)
+ -767573.1875849998.round(5, half: nil).should eql(-767573.18758)
+ -767573.1875849998.round(5, half: :up).should eql(-767573.18758)
+ -767573.1875849998.round(5, half: :down).should eql(-767573.18758)
+ -767573.1875849998.round(5, half: :even).should eql(-767573.18758)
+ end
end
it "raises FloatDomainError for exceptional values with a half option" do
diff --git a/spec/ruby/core/float/shared/equal.rb b/spec/ruby/core/float/shared/equal.rb
index 668aa069b5..4d524e1cf2 100644
--- a/spec/ruby/core/float/shared/equal.rb
+++ b/spec/ruby/core/float/shared/equal.rb
@@ -14,4 +14,25 @@ describe :float_equal, shared: true do
1.0.send(@method, x).should == false
2.0.send(@method, x).should == true
end
+
+ it "returns false if one side is NaN" do
+ [1.0, 42, bignum_value].each { |n|
+ (nan_value.send(@method, n)).should == false
+ (n.send(@method, nan_value)).should == false
+ }
+ end
+
+ it "handles positive infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ (infinity_value.send(@method, n)).should == false
+ (n.send(@method, infinity_value)).should == false
+ }
+ end
+
+ it "handles negative infinity" do
+ [1.0, 42, bignum_value].each { |n|
+ ((-infinity_value).send(@method, n)).should == false
+ (n.send(@method, -infinity_value)).should == false
+ }
+ end
end
diff --git a/spec/ruby/core/float/shared/to_i.rb b/spec/ruby/core/float/shared/to_i.rb
index 960295f095..33b32ca533 100644
--- a/spec/ruby/core/float/shared/to_i.rb
+++ b/spec/ruby/core/float/shared/to_i.rb
@@ -7,4 +7,8 @@ describe :float_to_i, shared: true do
-9223372036854775808.1.send(@method).should eql(-9223372036854775808)
9223372036854775808.1.send(@method).should eql(9223372036854775808)
end
+
+ it "raises a FloatDomainError for NaN" do
+ -> { nan_value.send(@method) }.should raise_error(FloatDomainError)
+ end
end
diff --git a/spec/ruby/core/gc/auto_compact_spec.rb b/spec/ruby/core/gc/auto_compact_spec.rb
new file mode 100644
index 0000000000..4f9d043171
--- /dev/null
+++ b/spec/ruby/core/gc/auto_compact_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.0" do
+ describe "GC.auto_compact" do
+ it "can set and get a boolean value" do
+ begin
+ GC.auto_compact = GC.auto_compact
+ rescue NotImplementedError # platform does not support autocompact
+ skip
+ end
+
+ original = GC.auto_compact
+ begin
+ GC.auto_compact = !original
+ rescue NotImplementedError # platform does not support autocompact
+ skip
+ end
+
+ begin
+ GC.auto_compact.should == !original
+ ensure
+ GC.auto_compact = original
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/gc/measure_total_time_spec.rb b/spec/ruby/core/gc/measure_total_time_spec.rb
new file mode 100644
index 0000000000..05d4598ebc
--- /dev/null
+++ b/spec/ruby/core/gc/measure_total_time_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "GC.measure_total_time" do
+ before :each do
+ @default = GC.measure_total_time
+ end
+
+ after :each do
+ GC.measure_total_time = @default
+ end
+
+ it "can set and get a boolean value" do
+ original = GC.measure_total_time
+ GC.measure_total_time = !original
+ GC.measure_total_time.should == !original
+ end
+ end
+end
diff --git a/spec/ruby/core/gc/stat_spec.rb b/spec/ruby/core/gc/stat_spec.rb
index eb71fd9691..3b43b28a92 100644
--- a/spec/ruby/core/gc/stat_spec.rb
+++ b/spec/ruby/core/gc/stat_spec.rb
@@ -7,6 +7,16 @@ describe "GC.stat" do
stat.keys.should.include?(:count)
end
+ it "updates the given hash values" do
+ hash = { count: "hello", __other__: "world" }
+ stat = GC.stat(hash)
+
+ stat.should be_kind_of(Hash)
+ stat.should equal hash
+ stat[:count].should be_kind_of(Integer)
+ stat[:__other__].should == "world"
+ end
+
it "the values are all Integer since rb_gc_stat() returns size_t" do
GC.stat.values.each { |value| value.should be_kind_of(Integer) }
end
@@ -41,4 +51,12 @@ describe "GC.stat" do
GC.stat(:total_allocated_objects).should be_kind_of(Integer)
GC.stat[:total_allocated_objects].should be_kind_of(Integer)
end
+
+ it "raises an error if argument is not nil, a symbol, or a hash" do
+ -> { GC.stat(7) }.should raise_error(TypeError, "non-hash or symbol given")
+ end
+
+ it "raises an error if an unknown key is given" do
+ -> { GC.stat(:foo) }.should raise_error(ArgumentError, "unknown key: foo")
+ end
end
diff --git a/spec/ruby/core/gc/total_time_spec.rb b/spec/ruby/core/gc/total_time_spec.rb
new file mode 100644
index 0000000000..fcc8f45a83
--- /dev/null
+++ b/spec/ruby/core/gc/total_time_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "GC.total_time" do
+ it "returns an Integer" do
+ GC.total_time.should be_kind_of(Integer)
+ end
+
+ it "increases as collections are run" do
+ time_before = GC.total_time
+ GC.start
+ GC.total_time.should >= time_before
+ end
+ end
+end
diff --git a/spec/ruby/core/hash/constructor_spec.rb b/spec/ruby/core/hash/constructor_spec.rb
index ad67274802..8fba47958f 100644
--- a/spec/ruby/core/hash/constructor_spec.rb
+++ b/spec/ruby/core/hash/constructor_spec.rb
@@ -42,26 +42,13 @@ describe "Hash.[]" do
Hash[ary].should == { a: :b }
end
- ruby_version_is "" ... "2.7" do
- it "ignores elements that are not arrays" do
- -> {
- Hash[[:a]].should == {}
- }.should complain(/ignoring wrong elements/)
- -> {
- Hash[[:nil]].should == {}
- }.should complain(/ignoring wrong elements/)
- end
- end
-
- ruby_version_is "2.7" do
- it "raises for elements that are not arrays" do
- -> {
- Hash[[:a]].should == {}
- }.should raise_error(ArgumentError)
- -> {
- Hash[[:nil]].should == {}
- }.should raise_error(ArgumentError)
- end
+ it "raises for elements that are not arrays" do
+ -> {
+ Hash[[:a]].should == {}
+ }.should raise_error(ArgumentError)
+ -> {
+ Hash[[:nil]].should == {}
+ }.should raise_error(ArgumentError)
end
it "raises an ArgumentError for arrays of more than 2 elements" do
diff --git a/spec/ruby/core/hash/deconstruct_keys_spec.rb b/spec/ruby/core/hash/deconstruct_keys_spec.rb
index b265732616..bbcd8932e5 100644
--- a/spec/ruby/core/hash/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/hash/deconstruct_keys_spec.rb
@@ -1,25 +1,23 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "Hash#deconstruct_keys" do
- it "returns self" do
- hash = {a: 1, b: 2}
+describe "Hash#deconstruct_keys" do
+ it "returns self" do
+ hash = {a: 1, b: 2}
- hash.deconstruct_keys([:a, :b]).should equal hash
- end
+ 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 "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}
+ 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
+ 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
diff --git a/spec/ruby/core/hash/hash_spec.rb b/spec/ruby/core/hash/hash_spec.rb
index 3649d4d8de..2ccb483120 100644
--- a/spec/ruby/core/hash/hash_spec.rb
+++ b/spec/ruby/core/hash/hash_spec.rb
@@ -41,4 +41,13 @@ describe "Hash#hash" do
h.hash.should == {x: [h]}.hash
# Like above, because h.eql?(x: [h])
end
+
+ ruby_version_is "3.1" do
+ it "allows ommiting values" do
+ a = 1
+ b = 2
+
+ eval('{a:, b:}.should == { a: 1, b: 2 }')
+ end
+ end
end
diff --git a/spec/ruby/core/hash/reject_spec.rb b/spec/ruby/core/hash/reject_spec.rb
index 397000ab67..dd8e817237 100644
--- a/spec/ruby/core/hash/reject_spec.rb
+++ b/spec/ruby/core/hash/reject_spec.rb
@@ -31,13 +31,6 @@ describe "Hash#reject" do
HashSpecs::MyHash[1 => 2, 3 => 4].reject { false }.should be_kind_of(Hash)
HashSpecs::MyHash[1 => 2, 3 => 4].reject { true }.should be_kind_of(Hash)
end
-
- ruby_version_is ''...'2.7' do
- it "does not taint the resulting hash" do
- h = { a: 1 }.taint
- h.reject {false}.should_not.tainted?
- end
- end
end
it "processes entries with the same order as reject!" do
diff --git a/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb b/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
index 005886a482..e9337b9d1c 100644
--- a/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
+++ b/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
@@ -1,47 +1,59 @@
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
+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 "copies instance variables" do
+ h = {a: 1}
+ h.instance_variable_set(:@foo, 42)
+ kw = Hash.ruby2_keywords_hash(h)
+ kw.instance_variable_get(:@foo).should == 42
+ end
+
+ it "copies the hash internals" do
+ h = {a: 1}
+ kw = Hash.ruby2_keywords_hash(h)
+ h[:a] = 2
+ kw[:a].should == 1
+ end
+
+ it "raises TypeError for non-Hash" do
+ -> { Hash.ruby2_keywords_hash(nil) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/hash/shared/eql.rb b/spec/ruby/core/hash/shared/eql.rb
index e294edd764..68db49f76d 100644
--- a/spec/ruby/core/hash/shared/eql.rb
+++ b/spec/ruby/core/hash/shared/eql.rb
@@ -149,80 +149,34 @@ describe :hash_eql_additional, shared: true do
h.send(@method, HashSpecs::MyHash[h]).should be_true
end
- ruby_version_is '2.7' do
- # Why isn't this true of eql? too ?
- it "compares keys with matching hash codes via eql?" do
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- return true if self.equal?(o)
- false
- end
-
- obj
+ # Why isn't this true of eql? too ?
+ it "compares keys with matching hash codes via eql?" do
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
+
+ def obj.eql?(o)
+ return true if self.equal?(o)
+ false
end
- { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_false
-
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- true
- end
-
- obj
- end
-
- { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_true
+ obj
end
- end
- ruby_version_is ''...'2.7' do
- # Why isn't this true of eql? too ?
- it "compares keys with matching hash codes via eql?" do
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
+ { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_false
- # It's undefined whether the impl does a[0].eql?(a[1]) or
- # a[1].eql?(a[0]) so we taint both.
- def obj.eql?(o)
- return true if self.equal?(o)
- taint
- o.taint
- false
- end
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
- obj
+ def obj.eql?(o)
+ true
end
- { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_false
- a[0].tainted?.should be_true
- a[1].tainted?.should be_true
-
- a = Array.new(2) do
- obj = mock('0')
- obj.should_receive(:hash).at_least(1).and_return(0)
-
- def obj.eql?(o)
- # It's undefined whether the impl does a[0].send(@method, a[1]) or
- # a[1].send(@method, a[0]) so we taint both.
- taint
- o.taint
- true
- end
-
- obj
- end
-
- { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_true
- a[0].tainted?.should be_true
- a[1].tainted?.should be_true
+ obj
end
+
+ { a[0] => 1 }.send(@method, { a[1] => 1 }).should be_true
end
it "compares the values in self to values in other hash" do
diff --git a/spec/ruby/core/hash/shared/to_s.rb b/spec/ruby/core/hash/shared/to_s.rb
index b0e3705d01..2db3a96583 100644
--- a/spec/ruby/core/hash/shared/to_s.rb
+++ b/spec/ruby/core/hash/shared/to_s.rb
@@ -2,7 +2,6 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe :hash_to_s, shared: true do
-
it "returns a string representation with same order as each()" do
h = { a: [1, 2], b: -2, d: -6, nil => nil }
@@ -77,22 +76,14 @@ describe :hash_to_s, shared: true do
y.send(@method).should == "{1=>{0=>{...}}}"
end
- ruby_version_is ''...'2.7' do
- it "returns a tainted string if self is tainted and not empty" do
- {}.taint.send(@method).tainted?.should be_false
- { nil => nil }.taint.send(@method).tainted?.should be_true
- end
-
- it "returns an untrusted string if self is untrusted and not empty" do
- {}.untrust.send(@method).untrusted?.should be_false
- { nil => nil }.untrust.send(@method).untrusted?.should be_true
- end
- end
-
it "does not raise if inspected result is not default external encoding" do
utf_16be = mock("utf_16be")
utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
{a: utf_16be}.send(@method).should == '{:a=>"utf_16be \u3042"}'
end
+
+ it "works for keys and values whose #inspect return a frozen String" do
+ { true => false }.to_s.should == "{true=>false}"
+ end
end
diff --git a/spec/ruby/core/hash/shift_spec.rb b/spec/ruby/core/hash/shift_spec.rb
index 9d43e640f5..ea36488a04 100644
--- a/spec/ruby/core/hash/shift_spec.rb
+++ b/spec/ruby/core/hash/shift_spec.rb
@@ -30,23 +30,45 @@ describe "Hash#shift" do
h.should == {}
end
- it "calls #default with nil if the Hash is empty" do
- h = {}
- def h.default(key)
- key.should == nil
- :foo
+ ruby_version_is '3.2' do
+ it "returns nil if the Hash is empty" do
+ h = {}
+ def h.default(key)
+ raise
+ end
+ h.shift.should == nil
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it "calls #default with nil if the Hash is empty" do
+ h = {}
+ def h.default(key)
+ key.should == nil
+ :foo
+ end
+ h.shift.should == :foo
end
- h.shift.should == :foo
end
it "returns nil from an empty hash" do
{}.shift.should == nil
end
- it "returns (computed) default for empty hashes" do
- Hash.new(5).shift.should == 5
- h = Hash.new { |*args| args }
- h.shift.should == [h, nil]
+ ruby_version_is '3.2' do
+ it "returns nil for empty hashes with defaults and default procs" do
+ Hash.new(5).shift.should == nil
+ h = Hash.new { |*args| args }
+ h.shift.should == nil
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it "returns (computed) default for empty hashes" do
+ Hash.new(5).shift.should == 5
+ h = Hash.new { |*args| args }
+ h.shift.should == [h, nil]
+ end
end
it "preserves Hash invariants when removing the last item" do
diff --git a/spec/ruby/core/hash/to_a_spec.rb b/spec/ruby/core/hash/to_a_spec.rb
index 46f871389a..8b7894a2ba 100644
--- a/spec/ruby/core/hash/to_a_spec.rb
+++ b/spec/ruby/core/hash/to_a_spec.rb
@@ -27,13 +27,13 @@ describe "Hash#to_a" do
ent.should == pairs
end
- ruby_version_is ''...'2.7' do
- it "returns a tainted array if self is tainted" do
- {}.taint.to_a.tainted?.should be_true
+ ruby_version_is ''...'3.0' do
+ it "returns a not tainted array if self is tainted" do
+ {}.taint.to_a.tainted?.should be_false
end
- it "returns an untrusted array if self is untrusted" do
- {}.untrust.to_a.untrusted?.should be_true
+ it "returns a trusted array if self is untrusted" do
+ {}.untrust.to_a.untrusted?.should be_false
end
end
end
diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb
index 70a4cdde36..361089ca97 100644
--- a/spec/ruby/core/hash/transform_keys_spec.rb
+++ b/spec/ruby/core/hash/transform_keys_spec.rb
@@ -42,6 +42,20 @@ describe "Hash#transform_keys" do
r.keys.should == [:xfoo]
r.class.should == Hash
end
+
+ ruby_version_is "3.0" do
+ it "allows a hash argument" do
+ @hash.transform_keys({ a: :A, b: :B, c: :C }).should == { A: 1, B: 2, C: 3 }
+ end
+
+ it "allows a partial transformation of keys when using a hash argument" do
+ @hash.transform_keys({ a: :A, c: :C }).should == { A: 1, b: 2, C: 3 }
+ end
+
+ it "allows a combination of hash and block argument" do
+ @hash.transform_keys({ a: :A }, &:to_s).should == { A: 1, 'b' => 2, 'c' => 3 }
+ end
+ end
end
describe "Hash#transform_keys!" do
@@ -59,14 +73,13 @@ describe "Hash#transform_keys!" do
@hash.should == { 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4 }
end
- # https://bugs.ruby-lang.org/issues/14380
it "prevents conflicts between new keys and old ones" do
@hash.transform_keys!(&:succ)
@hash.should == { b: 1, c: 2, d: 3, e: 4 }
end
ruby_version_is ""..."3.0.2" do # https://bugs.ruby-lang.org/issues/17735
- it "returns the processed keys if we broke from the block" do
+ it "returns the processed keys if we break from the block" do
@hash.transform_keys! do |v|
break if v == :c
v.succ
@@ -76,7 +89,7 @@ describe "Hash#transform_keys!" do
end
ruby_version_is "3.0.2" do
- it "returns the processed keys and non evaluated keys if we broke from the block" do
+ it "returns the processed keys and non evaluated keys if we break from the block" do
@hash.transform_keys! do |v|
break if v == :c
v.succ
@@ -98,6 +111,13 @@ describe "Hash#transform_keys!" do
end
end
+ ruby_version_is "3.0" do
+ it "allows a hash argument" do
+ @hash.transform_keys!({ a: :A, b: :B, c: :C, d: :D })
+ @hash.should == { A: 1, B: 2, C: 3, D: 4 }
+ end
+ end
+
describe "on frozen instance" do
before :each do
@hash.freeze
@@ -112,6 +132,12 @@ describe "Hash#transform_keys!" do
@hash.should == @initial_pairs
end
+ ruby_version_is "3.0" do
+ it "raises a FrozenError on hash argument" do
+ ->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should raise_error(FrozenError)
+ end
+ end
+
context "when no block is given" do
it "does not raise an exception" do
@hash.transform_keys!.should be_an_instance_of(Enumerator)
diff --git a/spec/ruby/core/integer/bit_and_spec.rb b/spec/ruby/core/integer/bit_and_spec.rb
index 15a8026855..8de5a14aaa 100644
--- a/spec/ruby/core/integer/bit_and_spec.rb
+++ b/spec/ruby/core/integer/bit_and_spec.rb
@@ -55,24 +55,24 @@ describe "Integer#&" do
@bignum = bignum_value(5)
(@bignum & 3).should == 1
(@bignum & 52).should == 4
- (@bignum & bignum_value(9921)).should == 9223372036854775809
+ (@bignum & bignum_value(9921)).should == 18446744073709551617
((2*bignum_value) & 1).should == 0
- ((2*bignum_value) & (2*bignum_value)).should == 18446744073709551616
+ ((2*bignum_value) & (2*bignum_value)).should == 36893488147419103232
end
it "returns self bitwise AND other when one operand is negative" do
((2*bignum_value) & -1).should == (2*bignum_value)
((4*bignum_value) & -1).should == (4*bignum_value)
- (@bignum & -0xffffffffffffff5).should == 9223372036854775809
+ (@bignum & -0xffffffffffffff5).should == 18446744073709551617
(@bignum & -@bignum).should == 1
- (@bignum & -0x8000000000000000).should == 9223372036854775808
+ (@bignum & -0x8000000000000000).should == 18446744073709551616
end
it "returns self bitwise AND other when both operands are negative" do
- (-@bignum & -0x4000000000000005).should == -13835058055282163717
- (-@bignum & -@bignum).should == -9223372036854775813
- (-@bignum & -0x4000000000000000).should == -13835058055282163712
+ (-@bignum & -0x4000000000000005).should == -23058430092136939525
+ (-@bignum & -@bignum).should == -18446744073709551621
+ (-@bignum & -0x4000000000000000).should == -23058430092136939520
end
it "returns self bitwise AND other when both are negative and a multiple in bitsize of Fixnum::MIN" do
diff --git a/spec/ruby/core/integer/bit_or_spec.rb b/spec/ruby/core/integer/bit_or_spec.rb
index e486eeec10..6f4279c170 100644
--- a/spec/ruby/core/integer/bit_or_spec.rb
+++ b/spec/ruby/core/integer/bit_or_spec.rb
@@ -7,13 +7,34 @@ describe "Integer#|" do
(5 | 4).should == 5
(5 | 6).should == 7
(248 | 4096).should == 4344
- (0xffff | bignum_value + 0xf0f0).should == 0x8000_0000_0000_ffff
+ (0xffff | bignum_value + 0xf0f0).should == 0x1_0000_0000_0000_ffff
+ end
+
+ it "returns self bitwise OR other when one operand is negative" do
+ ((1 << 33) | -1).should == -1
+ (-1 | (1 << 33)).should == -1
+
+ ((-(1<<33)-1) | 5).should == -8589934593
+ (5 | (-(1<<33)-1)).should == -8589934593
+ end
+
+ it "returns self bitwise OR other when both operands are negative" do
+ (-5 | -1).should == -1
+ (-3 | -4).should == -3
+ (-12 | -13).should == -9
+ (-13 | -12).should == -9
end
it "returns self bitwise OR a bignum" do
(-1 | 2**64).should == -1
end
+ it "coerces the rhs and calls #coerce" do
+ obj = mock("fixnum bit and")
+ obj.should_receive(:coerce).with(6).and_return([3, 6])
+ (6 & obj).should == 2
+ end
+
it "raises a TypeError when passed a Float" do
-> { (3 | 3.4) }.should raise_error(TypeError)
end
@@ -32,20 +53,20 @@ describe "Integer#|" do
end
it "returns self bitwise OR other" do
- (@bignum | 2).should == 9223372036854775819
- (@bignum | 9).should == 9223372036854775819
- (@bignum | bignum_value).should == 9223372036854775819
+ (@bignum | 2).should == 18446744073709551627
+ (@bignum | 9).should == 18446744073709551627
+ (@bignum | bignum_value).should == 18446744073709551627
end
it "returns self bitwise OR other when one operand is negative" do
- (@bignum | -0x40000000000000000).should == -64563604257983430645
+ (@bignum | -0x40000000000000000).should == -55340232221128654837
(@bignum | -@bignum).should == -1
(@bignum | -0x8000000000000000).should == -9223372036854775797
end
it "returns self bitwise OR other when both operands are negative" do
(-@bignum | -0x4000000000000005).should == -1
- (-@bignum | -@bignum).should == -9223372036854775819
+ (-@bignum | -@bignum).should == -18446744073709551627
(-@bignum | -0x4000000000000000).should == -11
end
diff --git a/spec/ruby/core/integer/bit_xor_spec.rb b/spec/ruby/core/integer/bit_xor_spec.rb
index ac8826a52f..f1150a20d5 100644
--- a/spec/ruby/core/integer/bit_xor_spec.rb
+++ b/spec/ruby/core/integer/bit_xor_spec.rb
@@ -5,13 +5,34 @@ describe "Integer#^" do
it "returns self bitwise EXCLUSIVE OR other" do
(3 ^ 5).should == 6
(-2 ^ -255).should == 255
- (5 ^ bignum_value + 0xffff_ffff).should == 0x8000_0000_ffff_fffa
+ (5 ^ bignum_value + 0xffff_ffff).should == 0x1_0000_0000_ffff_fffa
+ end
+
+ it "returns self bitwise XOR other when one operand is negative" do
+ ((1 << 33) ^ -1).should == -8589934593
+ (-1 ^ (1 << 33)).should == -8589934593
+
+ ((-(1<<33)-1) ^ 5).should == -8589934598
+ (5 ^ (-(1<<33)-1)).should == -8589934598
+ end
+
+ it "returns self bitwise XOR other when both operands are negative" do
+ (-5 ^ -1).should == 4
+ (-3 ^ -4).should == 1
+ (-12 ^ -13).should == 7
+ (-13 ^ -12).should == 7
end
it "returns self bitwise EXCLUSIVE OR a bignum" do
(-1 ^ 2**64).should == -18446744073709551617
end
+ it "coerces the rhs and calls #coerce" do
+ obj = mock("fixnum bit and")
+ obj.should_receive(:coerce).with(6).and_return([3, 6])
+ (6 ^ obj).should == 5
+ end
+
it "raises a TypeError when passed a Float" do
-> { (3 ^ 3.4) }.should raise_error(TypeError)
end
@@ -30,21 +51,21 @@ describe "Integer#^" do
end
it "returns self bitwise EXCLUSIVE OR other" do
- (@bignum ^ 2).should == 9223372036854775824
+ (@bignum ^ 2).should == 18446744073709551632
(@bignum ^ @bignum).should == 0
- (@bignum ^ 14).should == 9223372036854775836
+ (@bignum ^ 14).should == 18446744073709551644
end
it "returns self bitwise EXCLUSIVE OR other when one operand is negative" do
- (@bignum ^ -0x40000000000000000).should == -64563604257983430638
+ (@bignum ^ -0x40000000000000000).should == -55340232221128654830
(@bignum ^ -@bignum).should == -4
- (@bignum ^ -0x8000000000000000).should == -18446744073709551598
+ (@bignum ^ -0x8000000000000000).should == -27670116110564327406
end
it "returns self bitwise EXCLUSIVE OR other when both operands are negative" do
- (-@bignum ^ -0x40000000000000000).should == 64563604257983430638
+ (-@bignum ^ -0x40000000000000000).should == 55340232221128654830
(-@bignum ^ -@bignum).should == 0
- (-@bignum ^ -0x4000000000000000).should == 13835058055282163694
+ (-@bignum ^ -0x4000000000000000).should == 23058430092136939502
end
it "returns self bitwise EXCLUSIVE OR other when all bits are 1 and other value is negative" do
diff --git a/spec/ruby/core/integer/chr_spec.rb b/spec/ruby/core/integer/chr_spec.rb
index 9f105e4241..8fe20ff812 100644
--- a/spec/ruby/core/integer/chr_spec.rb
+++ b/spec/ruby/core/integer/chr_spec.rb
@@ -11,7 +11,11 @@ describe "Integer#chr without argument" do
it "raises a RangeError is self is less than 0" do
-> { -1.chr }.should raise_error(RangeError)
- -> { -bignum_value.chr }.should raise_error(RangeError)
+ -> { (-bignum_value).chr }.should raise_error(RangeError)
+ end
+
+ it "raises a RangeError if self is too large" do
+ -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
end
describe "when Encoding.default_internal is nil" do
@@ -162,7 +166,7 @@ describe "Integer#chr with an encoding argument" do
# http://redmine.ruby-lang.org/issues/4869
it "raises a RangeError is self is less than 0" do
-> { -1.chr(Encoding::UTF_8) }.should raise_error(RangeError)
- -> { -bignum_value.chr(Encoding::EUC_JP) }.should raise_error(RangeError)
+ -> { (-bignum_value).chr(Encoding::EUC_JP) }.should raise_error(RangeError)
end
it "raises a RangeError if self is too large" do
@@ -219,38 +223,35 @@ describe "Integer#chr with an encoding argument" do
# #5864
it "raises RangeError if self is invalid as a codepoint in the specified encoding" do
- [ [0x80, "US-ASCII"],
- [0x0100, "BINARY"],
- [0x0100, "EUC-JP"],
- [0xA1A0, "EUC-JP"],
- [0xA1, "EUC-JP"],
- [0x80, "SHIFT_JIS"],
- [0xE0, "SHIFT_JIS"],
- [0x0100, "ISO-8859-9"],
- [620, "TIS-620"],
- [0xD800, "UTF-8"],
- [0xDBFF, "UTF-8"],
- [0xDC00, "UTF-8"],
- [0xDFFF, "UTF-8"],
- [0xD800, "UTF-16"],
- [0xDBFF, "UTF-16"],
- [0xDC00, "UTF-16"],
- [0xDFFF, "UTF-16"],
- ].each do |integer, encoding_name|
- -> { integer.chr(encoding_name) }.should raise_error(RangeError)
- end
+ -> { 0x80.chr("US-ASCII") }.should raise_error(RangeError)
+ -> { 0x0100.chr("BINARY") }.should raise_error(RangeError)
+ -> { 0x0100.chr("EUC-JP") }.should raise_error(RangeError)
+ -> { 0xA1A0.chr("EUC-JP") }.should raise_error(RangeError)
+ -> { 0xA1.chr("EUC-JP") }.should raise_error(RangeError)
+ -> { 0x80.chr("SHIFT_JIS") }.should raise_error(RangeError)
+ -> { 0xE0.chr("SHIFT_JIS") }.should raise_error(RangeError)
+ -> { 0x0100.chr("ISO-8859-9") }.should raise_error(RangeError)
+ -> { 620.chr("TIS-620") }.should raise_error(RangeError)
+ # UTF-16 surrogate range
+ -> { 0xD800.chr("UTF-8") }.should raise_error(RangeError)
+ -> { 0xDBFF.chr("UTF-8") }.should raise_error(RangeError)
+ -> { 0xDC00.chr("UTF-8") }.should raise_error(RangeError)
+ -> { 0xDFFF.chr("UTF-8") }.should raise_error(RangeError)
+ # UTF-16 surrogate range
+ -> { 0xD800.chr("UTF-16") }.should raise_error(RangeError)
+ -> { 0xDBFF.chr("UTF-16") }.should raise_error(RangeError)
+ -> { 0xDC00.chr("UTF-16") }.should raise_error(RangeError)
+ -> { 0xDFFF.chr("UTF-16") }.should raise_error(RangeError)
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
+ 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
+ # 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
diff --git a/spec/ruby/core/integer/complement_spec.rb b/spec/ruby/core/integer/complement_spec.rb
index eafa5c263f..baf5e6c457 100644
--- a/spec/ruby/core/integer/complement_spec.rb
+++ b/spec/ruby/core/integer/complement_spec.rb
@@ -12,9 +12,9 @@ describe "Integer#~" do
context "bignum" do
it "returns self with each bit flipped" do
- (~bignum_value(48)).should == -9223372036854775857
- (~(-bignum_value(21))).should == 9223372036854775828
- (~bignum_value(1)).should == -9223372036854775810
+ (~bignum_value(48)).should == -18446744073709551665
+ (~(-bignum_value(21))).should == 18446744073709551636
+ (~bignum_value(1)).should == -18446744073709551618
end
end
end
diff --git a/spec/ruby/core/integer/constants_spec.rb b/spec/ruby/core/integer/constants_spec.rb
index 3b8b01e330..2077ad451e 100644
--- a/spec/ruby/core/integer/constants_spec.rb
+++ b/spec/ruby/core/integer/constants_spec.rb
@@ -1,25 +1,41 @@
require_relative '../../spec_helper'
describe "Fixnum" do
- it "is unified into Integer" do
- suppress_warning do
- Fixnum.should equal(Integer)
+ ruby_version_is ""..."3.2" do
+ it "is unified into Integer" do
+ suppress_warning do
+ Fixnum.should equal(Integer)
+ end
+ end
+
+ it "is deprecated" do
+ -> { Fixnum }.should complain(/constant ::Fixnum is deprecated/)
end
end
- it "is deprecated" do
- -> { Fixnum }.should complain(/constant ::Fixnum is deprecated/)
+ ruby_version_is "3.2" do
+ it "is no longer defined" do
+ Object.should_not.const_defined?(:Fixnum)
+ end
end
end
describe "Bignum" do
- it "is unified into Integer" do
- suppress_warning do
- Bignum.should equal(Integer)
+ ruby_version_is ""..."3.2" do
+ it "is unified into Integer" do
+ suppress_warning do
+ Bignum.should equal(Integer)
+ end
+ end
+
+ it "is deprecated" do
+ -> { Bignum }.should complain(/constant ::Bignum is deprecated/)
end
end
- it "is deprecated" do
- -> { Bignum }.should complain(/constant ::Bignum is deprecated/)
+ ruby_version_is "3.2" do
+ it "is no longer defined" do
+ Object.should_not.const_defined?(:Bignum)
+ end
end
end
diff --git a/spec/ruby/core/integer/div_spec.rb b/spec/ruby/core/integer/div_spec.rb
index bc1c4363d4..344e095179 100644
--- a/spec/ruby/core/integer/div_spec.rb
+++ b/spec/ruby/core/integer/div_spec.rb
@@ -70,8 +70,8 @@ describe "Integer#div" do
end
it "returns self divided by other" do
- @bignum.div(4).should == 2305843009213693974
- @bignum.div(Rational(4, 1)).should == 2305843009213693974
+ @bignum.div(4).should == 4611686018427387926
+ @bignum.div(Rational(4, 1)).should == 4611686018427387926
@bignum.div(bignum_value(2)).should == 1
(-(10**50)).div(-(10**40 + 1)).should == 9999999999
@@ -124,11 +124,11 @@ describe "Integer#div" do
end
it "returns a result of integer division of self by a float argument" do
- @bignum.div(4294967295.5).should eql(2147483648)
+ @bignum.div(4294967295.5).should eql(4294967296)
not_supported_on :opal do
- @bignum.div(4294967295.0).should eql(2147483648)
+ @bignum.div(4294967295.0).should eql(4294967297)
@bignum.div(bignum_value(88).to_f).should eql(1)
- @bignum.div(-bignum_value(88).to_f).should eql(-1)
+ @bignum.div((-bignum_value(88)).to_f).should eql(-1)
end
end
diff --git a/spec/ruby/core/integer/divide_spec.rb b/spec/ruby/core/integer/divide_spec.rb
index 5ac2dc538d..a878c4668c 100644
--- a/spec/ruby/core/integer/divide_spec.rb
+++ b/spec/ruby/core/integer/divide_spec.rb
@@ -47,7 +47,7 @@ describe "Integer#/" do
end
it "returns self divided by other" do
- (@bignum / 4).should == 2305843009213693974
+ (@bignum / 4).should == 4611686018427387926
(@bignum / bignum_value(2)).should == 1
@@ -60,15 +60,15 @@ describe "Integer#/" do
it "returns self divided by Float" do
not_supported_on :opal do
- (bignum_value(88) / 4294967295.0).should be_close(2147483648.5, TOLERANCE)
+ (bignum_value(88) / 4294967295.0).should be_close(4294967297.0, TOLERANCE)
end
- (bignum_value(88) / 4294967295.5).should be_close(2147483648.25, TOLERANCE)
+ (bignum_value(88) / 4294967295.5).should be_close(4294967296.5, TOLERANCE)
end
it "returns result the same class as the argument" do
- (@bignum / 4).should == 2305843009213693974
- (@bignum / 4.0).should be_close(2305843009213693974, TOLERANCE)
- (@bignum / Rational(4, 1)).should == Rational(2305843009213693974, 1)
+ (@bignum / 4).should == 4611686018427387926
+ (@bignum / 4.0).should be_close(4611686018427387926, TOLERANCE)
+ (@bignum / Rational(4, 1)).should == Rational(4611686018427387926, 1)
end
it "does NOT raise ZeroDivisionError if other is zero and is a Float" do
diff --git a/spec/ruby/core/integer/divmod_spec.rb b/spec/ruby/core/integer/divmod_spec.rb
index d88925caad..7a489e9344 100644
--- a/spec/ruby/core/integer/divmod_spec.rb
+++ b/spec/ruby/core/integer/divmod_spec.rb
@@ -46,16 +46,16 @@ describe "Integer#divmod" do
# assert(0 < b ? (0 <= r && r < b) : (b < r && r <= 0))
# So, r is always between 0 and b.
it "returns an Array containing quotient and modulus obtained from dividing self by the given argument" do
- @bignum.divmod(4).should == [2305843009213693965, 3]
- @bignum.divmod(13).should == [709490156681136604, 11]
+ @bignum.divmod(4).should == [4611686018427387917, 3]
+ @bignum.divmod(13).should == [1418980313362273205, 6]
- @bignum.divmod(4.5).should == [2049638230412172288, 3.5]
+ @bignum.divmod(4.5).should == [4099276460824344576, 2.5]
not_supported_on :opal do
- @bignum.divmod(4.0).should == [2305843009213693952, 0.0]
- @bignum.divmod(13.0).should == [709490156681136640, 8.0]
+ @bignum.divmod(4.0).should == [4611686018427387904, 0.0]
+ @bignum.divmod(13.0).should == [1418980313362273280, 3.0]
- @bignum.divmod(2.0).should == [4611686018427387904, 0.0]
+ @bignum.divmod(2.0).should == [9223372036854775808, 0.0]
end
@bignum.divmod(bignum_value).should == [1, 55]
diff --git a/spec/ruby/core/integer/element_reference_spec.rb b/spec/ruby/core/integer/element_reference_spec.rb
index 7197ecdc03..cb7e0dc9b0 100644
--- a/spec/ruby/core/integer/element_reference_spec.rb
+++ b/spec/ruby/core/integer/element_reference_spec.rb
@@ -79,81 +79,79 @@ describe "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
+ 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 "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 "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
+ 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
+ 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
+ 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..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 "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 "moves lower boundary to the most significant bits when negative value passed" do
+ 0b000001[-1, 4].should == 0b10
+ 0b000001[-2, 4].should == 0b100
+ 0b000001[-3, 4].should == 0b1000
+ end
- it "ignores upper boundary smaller than lower boundary" do
- 0b101001101[4..1].should == 0b10100
- 0b101001101[4..2].should == 0b10100
- 0b101001101[-4..-5].should == 0b1010011010000
- end
+ it "ignores upper boundary smaller than lower boundary" do
+ 0b101001101[4..1].should == 0b10100
+ 0b101001101[4..2].should == 0b10100
+ 0b101001101[-4..-5].should == 0b1010011010000
+ end
+
+ it "raises FloatDomainError if any boundary is infinity" do
+ -> { 0x0001[3..Float::INFINITY] }.should raise_error(FloatDomainError, /Infinity/)
+ -> { 0x0001[-Float::INFINITY..3] }.should raise_error(FloatDomainError, /-Infinity/)
+ end
- 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/)
+ 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
- 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
+ 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
diff --git a/spec/ruby/core/integer/fdiv_spec.rb b/spec/ruby/core/integer/fdiv_spec.rb
index 6de170278f..d9ea2fdf8d 100644
--- a/spec/ruby/core/integer/fdiv_spec.rb
+++ b/spec/ruby/core/integer/fdiv_spec.rb
@@ -9,6 +9,57 @@ describe "Integer#fdiv" do
8.fdiv(bignum_value).should be_close(8.673617379884035e-19, TOLERANCE)
end
+ it "performs floating-point division between self bignum and a bignum" do
+ num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009
+ den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ num.fdiv(den).should == 500.0
+ end
+
+ it "rounds to the correct value for bignums" do
+ den = 9 * 10**342
+
+ num = 1 * 10**344
+ num.fdiv(den).should == 11.11111111111111
+
+ num = 1 * 10**343
+ num.fdiv(den).should == 1.1111111111111112
+
+ num = 1 * 10**342
+ num.fdiv(den).should == 0.1111111111111111
+
+ num = 2 * 10**342
+ num.fdiv(den).should == 0.2222222222222222
+
+ num = 3 * 10**342
+ num.fdiv(den).should == 0.3333333333333333
+
+ num = 4 * 10**342
+ num.fdiv(den).should == 0.4444444444444444
+
+ num = 5 * 10**342
+ num.fdiv(den).should == 0.5555555555555556
+
+ num = 6 * 10**342
+ num.fdiv(den).should == 0.6666666666666666
+
+ num = 7 * 10**342
+ num.fdiv(den).should == 0.7777777777777778
+
+ num = 8 * 10**342
+ num.fdiv(den).should == 0.8888888888888888
+
+ num = 9 * 10**342
+ num.fdiv(den).should == 1.0
+
+ num = -5 * 10**342
+ num.fdiv(den).should == -0.5555555555555556
+ end
+
+ it "rounds to the correct float for bignum denominators" do
+ 1.fdiv(10**324).should == 0.0
+ 1.fdiv(10**323).should == 1.0e-323
+ end
+
it "performs floating-point division between self and a Float" do
8.fdiv(9.0).should be_close(0.888888888888889, TOLERANCE)
end
diff --git a/spec/ruby/core/integer/left_shift_spec.rb b/spec/ruby/core/integer/left_shift_spec.rb
index 4efcbef334..135af90421 100644
--- a/spec/ruby/core/integer/left_shift_spec.rb
+++ b/spec/ruby/core/integer/left_shift_spec.rb
@@ -56,13 +56,13 @@ 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 a Bignum == fixnum_max * 2 when fixnum_max << 1 and n > 0" do
result = fixnum_max << 1
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 a Bignum == fixnum_min * 2 when fixnum_min << 1 and n < 0" do
result = fixnum_min << 1
result.should be_an_instance_of(Integer)
result.should == fixnum_min * 2
@@ -96,7 +96,7 @@ describe "Integer#<< (with n << m)" do
context "bignum" do
before :each do
- @bignum = bignum_value * 16
+ @bignum = bignum_value * 8 # 2 ** 67
end
it "returns n shifted left m bits when n > 0, m > 0" do
@@ -127,10 +127,6 @@ describe "Integer#<< (with n << m)" do
(@bignum << -68).should == 0
end
- it "returns 0 when m < 0 and m is a Bignum" do
- (@bignum << -bignum_value).should == 0
- end
-
it "returns a Fixnum == fixnum_max when (fixnum_max * 2) << -1 and n > 0" do
result = (fixnum_max * 2) << -1
result.should be_an_instance_of(Integer)
@@ -165,4 +161,51 @@ describe "Integer#<< (with n << m)" do
-> { @bignum << "4" }.should raise_error(TypeError)
end
end
+
+ context "when m is a bignum or larger than int" do
+ it "returns -1 when m < 0 and n < 0" do
+ (-1 << -bignum_value).should == -1
+ (-1 << -(2**40)).should == -1
+
+ (-bignum_value << -bignum_value).should == -1
+ (-bignum_value << -(2**40)).should == -1
+ end
+
+ it "returns 0 when m < 0 and n >= 0" do
+ (0 << -bignum_value).should == 0
+ (1 << -bignum_value).should == 0
+ (bignum_value << -bignum_value).should == 0
+
+ (0 << -(2**40)).should == 0
+ (1 << -(2**40)).should == 0
+ (bignum_value << -(2**40)).should == 0
+ end
+
+ ruby_bug "#18517", ""..."3.2" do
+ it "returns 0 when m > 0 long and n == 0" do
+ (0 << (2**40)).should == 0
+ end
+ end
+
+ it "returns 0 when m > 0 bignum and n == 0" do
+ (0 << bignum_value).should == 0
+ end
+
+ ruby_bug "#18518", ""..."3.3" do
+ it "raises NoMemoryError when m > 0 and n != 0" do
+ coerce_long = mock("long")
+ coerce_long.stub!(:to_int).and_return(2**40)
+ coerce_bignum = mock("bignum")
+ coerce_bignum.stub!(:to_int).and_return(bignum_value)
+ exps = [2**40, bignum_value, coerce_long, coerce_bignum]
+
+ exps.each { |exp|
+ -> { (1 << exp) }.should raise_error(NoMemoryError)
+ -> { (-1 << exp) }.should raise_error(NoMemoryError)
+ -> { (bignum_value << exp) }.should raise_error(NoMemoryError)
+ -> { (-bignum_value << exp) }.should raise_error(NoMemoryError)
+ }
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/integer/minus_spec.rb b/spec/ruby/core/integer/minus_spec.rb
index ce50c8752f..aadf416a05 100644
--- a/spec/ruby/core/integer/minus_spec.rb
+++ b/spec/ruby/core/integer/minus_spec.rb
@@ -10,7 +10,7 @@ describe "Integer#-" do
(9237212 - 5_280).should == 9231932
(781 - 0.5).should == 780.5
- (2_560_496 - bignum_value).should == -9223372036852215312
+ (2_560_496 - bignum_value).should == -18446744073706991120
end
it "raises a TypeError when given a non-Integer" do
@@ -29,8 +29,8 @@ describe "Integer#-" do
end
it "returns self minus the given Integer" do
- (@bignum - 9).should == 9223372036854776113
- (@bignum - 12.57).should be_close(9223372036854776109.43, TOLERANCE)
+ (@bignum - 9).should == 18446744073709551921
+ (@bignum - 12.57).should be_close(18446744073709551917.43, TOLERANCE)
(@bignum - bignum_value(42)).should == 272
end
diff --git a/spec/ruby/core/integer/multiply_spec.rb b/spec/ruby/core/integer/multiply_spec.rb
index d1e9c2640d..5037d27458 100644
--- a/spec/ruby/core/integer/multiply_spec.rb
+++ b/spec/ruby/core/integer/multiply_spec.rb
@@ -10,7 +10,7 @@ describe "Integer#*" do
(1342177 * 800).should == 1073741600
(65536 * 65536).should == 4294967296
- (256 * bignum_value).should == 2361183241434822606848
+ (256 * bignum_value).should == 4722366482869645213696
(6712 * 0.25).should == 1678.0
end
@@ -32,8 +32,8 @@ describe "Integer#*" do
it "returns self multiplied by the given Integer" do
(@bignum * (1/bignum_value(0xffff).to_f)).should be_close(1.0, TOLERANCE)
(@bignum * (1/bignum_value(0xffff).to_f)).should be_close(1.0, TOLERANCE)
- (@bignum * 10).should == 92233720368547765800
- (@bignum * (@bignum - 40)).should == 85070591730234629737795195287525433200
+ (@bignum * 10).should == 184467440737095523880
+ (@bignum * (@bignum - 40)).should == 340282366920938491207277694290934407024
end
it "raises a TypeError when given a non-Integer" do
diff --git a/spec/ruby/core/integer/plus_spec.rb b/spec/ruby/core/integer/plus_spec.rb
index be626c3305..d01a76ab58 100644
--- a/spec/ruby/core/integer/plus_spec.rb
+++ b/spec/ruby/core/integer/plus_spec.rb
@@ -9,7 +9,7 @@ describe "Integer#+" do
(491 + 2).should == 493
(90210 + 10).should == 90220
- (9 + bignum_value).should == 9223372036854775817
+ (9 + bignum_value).should == 18446744073709551625
(1001 + 5.219).should == 1006.219
end
@@ -29,9 +29,9 @@ describe "Integer#+" do
end
it "returns self plus the given Integer" do
- (@bignum + 4).should == 9223372036854775888
- (@bignum + 4.2).should be_close(9223372036854775888.2, TOLERANCE)
- (@bignum + bignum_value(3)).should == 18446744073709551695
+ (@bignum + 4).should == 18446744073709551696
+ (@bignum + 4.2).should be_close(18446744073709551696.2, TOLERANCE)
+ (@bignum + bignum_value(3)).should == 36893488147419103311
end
it "raises a TypeError when given a non-Integer" do
@@ -40,4 +40,19 @@ describe "Integer#+" do
-> { @bignum + :symbol}.should raise_error(TypeError)
end
end
+
+ it "can be redefined" do
+ code = <<~RUBY
+ class Integer
+ alias_method :old_plus, :+
+ def +(other)
+ self - other
+ end
+ end
+ result = 1 + 2
+ Integer.alias_method :+, :old_plus
+ print result
+ RUBY
+ ruby_exe(code).should == "-1"
+ end
end
diff --git a/spec/ruby/core/integer/remainder_spec.rb b/spec/ruby/core/integer/remainder_spec.rb
index cd10dad6f2..96268b3af5 100644
--- a/spec/ruby/core/integer/remainder_spec.rb
+++ b/spec/ruby/core/integer/remainder_spec.rb
@@ -33,7 +33,7 @@ describe "Integer#remainder" do
it "returns the remainder of dividing self by other" do
a = bignum_value(79)
a.remainder(2).should == 1
- a.remainder(97.345).should be_close(46.5674996147722, TOLERANCE)
+ a.remainder(97.345).should be_close(93.1349992295444, TOLERANCE)
a.remainder(bignum_value).should == 79
end
diff --git a/spec/ruby/core/integer/right_shift_spec.rb b/spec/ruby/core/integer/right_shift_spec.rb
index 6abcd8d714..81405667b2 100644
--- a/spec/ruby/core/integer/right_shift_spec.rb
+++ b/spec/ruby/core/integer/right_shift_spec.rb
@@ -52,17 +52,13 @@ describe "Integer#>> (with n >> m)" do
(-7 >> 64).should == -1
end
- it "returns 0 when m is a bignum" do
- (3 >> bignum_value).should == 0
- end
-
- it "returns an Bignum == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do
+ it "returns a Bignum == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do
result = fixnum_max >> -1
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 a Bignum == fixnum_min * 2 when fixnum_min >> -1 and n < 0" do
result = fixnum_min >> -1
result.should be_an_instance_of(Integer)
result.should == fixnum_min * 2
@@ -96,7 +92,7 @@ describe "Integer#>> (with n >> m)" do
context "bignum" do
before :each do
- @bignum = bignum_value * 16
+ @bignum = bignum_value * 8 # 2 ** 67
end
it "returns n shifted right m bits when n > 0, m > 0" do
@@ -153,10 +149,6 @@ describe "Integer#>> (with n >> m)" do
(@bignum >> 68).should == 0
end
- it "returns 0 when m is a Bignum" do
- (@bignum >> bignum_value).should == 0
- end
-
it "returns a Fixnum == fixnum_max when (fixnum_max * 2) >> 1 and n > 0" do
result = (fixnum_max * 2) >> 1
result.should be_an_instance_of(Integer)
@@ -191,4 +183,51 @@ describe "Integer#>> (with n >> m)" do
-> { @bignum >> "4" }.should raise_error(TypeError)
end
end
+
+ context "when m is a bignum or larger than int" do
+ it "returns -1 when m > 0 and n < 0" do
+ (-1 >> bignum_value).should == -1
+ (-1 >> (2**40)).should == -1
+
+ (-bignum_value >> bignum_value).should == -1
+ (-bignum_value >> (2**40)).should == -1
+ end
+
+ it "returns 0 when m > 0 and n >= 0" do
+ (0 >> bignum_value).should == 0
+ (1 >> bignum_value).should == 0
+ (bignum_value >> bignum_value).should == 0
+
+ (0 >> (2**40)).should == 0
+ (1 >> (2**40)).should == 0
+ (bignum_value >> (2**40)).should == 0
+ end
+
+ ruby_bug "#18517", ""..."3.2" do
+ it "returns 0 when m < 0 long and n == 0" do
+ (0 >> -(2**40)).should == 0
+ end
+ end
+
+ it "returns 0 when m < 0 bignum and n == 0" do
+ (0 >> -bignum_value).should == 0
+ end
+
+ ruby_bug "#18518", ""..."3.3" do
+ it "raises NoMemoryError when m < 0 and n != 0" do
+ coerce_long = mock("long")
+ coerce_long.stub!(:to_int).and_return(-(2**40))
+ coerce_bignum = mock("bignum")
+ coerce_bignum.stub!(:to_int).and_return(-bignum_value)
+ exps = [-(2**40), -bignum_value, coerce_long, coerce_bignum]
+
+ exps.each { |exp|
+ -> { (1 >> exp) }.should raise_error(NoMemoryError)
+ -> { (-1 >> exp) }.should raise_error(NoMemoryError)
+ -> { (bignum_value >> exp) }.should raise_error(NoMemoryError)
+ -> { (-bignum_value >> exp) }.should raise_error(NoMemoryError)
+ }
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/integer/shared/abs.rb b/spec/ruby/core/integer/shared/abs.rb
index 946aa21864..43844c9065 100644
--- a/spec/ruby/core/integer/shared/abs.rb
+++ b/spec/ruby/core/integer/shared/abs.rb
@@ -11,8 +11,8 @@ describe :integer_abs, shared: true do
context "bignum" do
it "returns the absolute bignum value" do
- bignum_value(39).send(@method).should == 9223372036854775847
- (-bignum_value(18)).send(@method).should == 9223372036854775826
+ bignum_value(39).send(@method).should == 18446744073709551655
+ (-bignum_value(18)).send(@method).should == 18446744073709551634
end
end
end
diff --git a/spec/ruby/core/integer/shared/exponent.rb b/spec/ruby/core/integer/shared/exponent.rb
index f949c514c8..15df518b7e 100644
--- a/spec/ruby/core/integer/shared/exponent.rb
+++ b/spec/ruby/core/integer/shared/exponent.rb
@@ -30,11 +30,13 @@ describe :integer_exponent, shared: true do
(-2).send(@method, 30).should eql(1073741824)
(-2).send(@method, 31).should eql(-2147483648)
(-2).send(@method, 32).should eql(4294967296)
+ (-2).send(@method, 33).should eql(-8589934592)
(-2).send(@method, 61).should eql(-2305843009213693952)
(-2).send(@method, 62).should eql(4611686018427387904)
(-2).send(@method, 63).should eql(-9223372036854775808)
(-2).send(@method, 64).should eql(18446744073709551616)
+ (-2).send(@method, 65).should eql(-36893488147419103232)
end
it "can raise 1 to a bignum safely" do
@@ -96,8 +98,8 @@ describe :integer_exponent, shared: true do
end
it "returns self raised to other power" do
- (@bignum.send(@method, 4)).should == 7237005577332262361485077344629993318496048279512298547155833600056910050625
- (@bignum.send(@method, 1.2)).should be_close(57262152889751597425762.57804, TOLERANCE)
+ (@bignum.send(@method, 4)).should == 115792089237316196603666111261383895964500887398800252671052694326794607293761
+ (@bignum.send(@method, 1.3)).should be_close(11109528802438156839288832.0, TOLERANCE)
end
it "raises a TypeError when given a non-Integer" do
@@ -116,8 +118,9 @@ describe :integer_exponent, shared: true do
end
it "returns a complex number when negative and raised to a fractional power" do
- ((-@bignum).send(@method, (1.0/3))) .should be_close(Complex(1048576,1816186.907597341), TOLERANCE)
- ((-@bignum).send(@method, Rational(1,3))).should be_close(Complex(1048576,1816186.907597341), TOLERANCE)
+ (-bignum_value).send(@method, (1.0/2)).should be_close(Complex(0.0, 4294967296.0), TOLERANCE)
+ (-@bignum).send(@method, (1.0/3)) .should be_close(Complex(1321122.9748145656, 2288252.1154253655), TOLERANCE)
+ (-@bignum).send(@method, Rational(1,3)).should be_close(Complex(1321122.9748145656, 2288252.1154253655), TOLERANCE)
end
end
end
diff --git a/spec/ruby/core/integer/shared/modulo.rb b/spec/ruby/core/integer/shared/modulo.rb
index b06d81e17d..f678a10806 100644
--- a/spec/ruby/core/integer/shared/modulo.rb
+++ b/spec/ruby/core/integer/shared/modulo.rb
@@ -48,11 +48,11 @@ describe :integer_modulo, shared: true do
end
it "returns the modulus obtained from dividing self by the given argument" do
- @bignum.send(@method, 5).should == 3
- @bignum.send(@method, -5).should == -2
- @bignum.send(@method, -100).should == -92
- @bignum.send(@method, 2.22).should be_close(0.780180180180252, TOLERANCE)
- @bignum.send(@method, bignum_value(10)).should == 9223372036854775808
+ @bignum.send(@method, 5).should == 1
+ @bignum.send(@method, -5).should == -4
+ @bignum.send(@method, -100).should == -84
+ @bignum.send(@method, 2.22).should be_close(1.5603603603605034, TOLERANCE)
+ @bignum.send(@method, bignum_value(10)).should == 18446744073709551616
end
it "raises a ZeroDivisionError when the given argument is 0" do
diff --git a/spec/ruby/core/integer/to_f_spec.rb b/spec/ruby/core/integer/to_f_spec.rb
index 06092eaa92..9f1df9ada9 100644
--- a/spec/ruby/core/integer/to_f_spec.rb
+++ b/spec/ruby/core/integer/to_f_spec.rb
@@ -11,9 +11,9 @@ describe "Integer#to_f" do
context "bignum" do
it "returns self converted to a Float" do
- bignum_value(0x4000_0aa0_0bb0_0000).to_f.should eql(13_835_069_737_789_292_544.00)
- bignum_value(0x8000_0000_0000_0ccc).to_f.should eql(18_446_744_073_709_555_712.00)
- (-bignum_value(99)).to_f.should eql(-9_223_372_036_854_775_808.00)
+ bignum_value(0x4000_0aa0_0bb0_0000).to_f.should eql(23_058_441_774_644_068_352.0)
+ bignum_value(0x8000_0000_0000_0ccc).to_f.should eql(27_670_116_110_564_330_700.0)
+ (-bignum_value(99)).to_f.should eql(-18_446_744_073_709_551_715.0)
end
it "converts number close to Float::MAX without exceeding MAX or producing NaN" do
diff --git a/spec/ruby/core/integer/to_s_spec.rb b/spec/ruby/core/integer/to_s_spec.rb
index 7988bfde7a..ca08dad95c 100644
--- a/spec/ruby/core/integer/to_s_spec.rb
+++ b/spec/ruby/core/integer/to_s_spec.rb
@@ -68,9 +68,9 @@ describe "Integer#to_s" do
describe "when given no base" do
it "returns self converted to a String using base 10" do
- bignum_value(9).to_s.should == "9223372036854775817"
- bignum_value.to_s.should == "9223372036854775808"
- (-bignum_value(675)).to_s.should == "-9223372036854776483"
+ bignum_value(9).to_s.should == "18446744073709551625"
+ bignum_value.to_s.should == "18446744073709551616"
+ (-bignum_value(675)).to_s.should == "-18446744073709552291"
end
end
diff --git a/spec/ruby/core/integer/uminus_spec.rb b/spec/ruby/core/integer/uminus_spec.rb
index b6b110dec4..7a9cfe89bf 100644
--- a/spec/ruby/core/integer/uminus_spec.rb
+++ b/spec/ruby/core/integer/uminus_spec.rb
@@ -20,11 +20,11 @@ describe "Integer#-@" do
context "bignum" do
it "returns self as a negative value" do
- bignum_value.send(:-@).should == -9223372036854775808
- (-bignum_value).send(:-@).should == 9223372036854775808
+ bignum_value.send(:-@).should == -18446744073709551616
+ (-bignum_value).send(:-@).should == 18446744073709551616
- bignum_value(921).send(:-@).should == -9223372036854776729
- (-bignum_value(921).send(:-@)).should == 9223372036854776729
+ bignum_value(921).send(:-@).should == -18446744073709552537
+ (-bignum_value(921).send(:-@)).should == 18446744073709552537
end
end
end
diff --git a/spec/ruby/core/integer/zero_spec.rb b/spec/ruby/core/integer/zero_spec.rb
new file mode 100644
index 0000000000..2dac50c406
--- /dev/null
+++ b/spec/ruby/core/integer/zero_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+describe "Integer#zero?" do
+ it "returns true if self is 0" do
+ 0.should.zero?
+ 1.should_not.zero?
+ -1.should_not.zero?
+ end
+
+ ruby_version_is "3.0" do
+ it "Integer#zero? overrides Numeric#zero?" do
+ 42.method(:zero?).owner.should == Integer
+ end
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "Integer#zero? uses Numeric#zero?" do
+ 42.method(:zero?).owner.should == Numeric
+ end
+ end
+end
diff --git a/spec/ruby/core/io/advise_spec.rb b/spec/ruby/core/io/advise_spec.rb
index 0a845487e2..651fc52378 100644
--- a/spec/ruby/core/io/advise_spec.rb
+++ b/spec/ruby/core/io/advise_spec.rb
@@ -73,19 +73,9 @@ describe "IO#advise" do
end
end
- platform_is :linux do
+ guard -> { platform_is :linux and kernel_version_is '3.6' } do # [ruby-core:65355] tmpfs is not supported
it "supports the willneed advice type" do
- require 'etc'
- uname = if Etc.respond_to?(:uname)
- Etc.uname[:release]
- else
- `uname -r`.chomp
- end
- if (uname.split('.').map(&:to_i) <=> [3,6]) < 0
- skip "[ruby-core:65355] tmpfs is not supported"
- else
- @io.advise(:willneed).should be_nil
- end
+ @io.advise(:willneed).should be_nil
end
end
diff --git a/spec/ruby/core/io/close_spec.rb b/spec/ruby/core/io/close_spec.rb
index eb560eaf67..3a44cc8b17 100644
--- a/spec/ruby/core/io/close_spec.rb
+++ b/spec/ruby/core/io/close_spec.rb
@@ -44,6 +44,12 @@ describe "IO#close" do
@io.close.should be_nil
end
+ it "does not call the #flush method but flushes the stream internally" do
+ @io.should_not_receive(:flush)
+ @io.close
+ @io.should.closed?
+ end
+
it 'raises an IOError with a clear message' do
matching_exception = nil
diff --git a/spec/ruby/core/io/external_encoding_spec.rb b/spec/ruby/core/io/external_encoding_spec.rb
index c1b727d930..2fcf1c7218 100644
--- a/spec/ruby/core/io/external_encoding_spec.rb
+++ b/spec/ruby/core/io/external_encoding_spec.rb
@@ -94,8 +94,12 @@ describe "IO#external_encoding" do
rm_r @name
end
- it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.external_encoding }.should raise_error(IOError)
+ ruby_version_is '3.1' do
+ it "can be retrieved from a closed stream" do
+ io = IOSpecs.io_fixture("lines.txt", "r")
+ io.close
+ io.external_encoding.should equal(Encoding.default_external)
+ end
end
describe "with 'r' mode" do
diff --git a/spec/ruby/core/io/fixtures/classes.rb b/spec/ruby/core/io/fixtures/classes.rb
index 5d81d5fcd9..204a2a101b 100644
--- a/spec/ruby/core/io/fixtures/classes.rb
+++ b/spec/ruby/core/io/fixtures/classes.rb
@@ -7,6 +7,18 @@ module IOSpecs
class SubIO < IO
end
+ class SubIOWithRedefinedNew < IO
+ def self.new(...)
+ ScratchPad << :redefined_new_called
+ super
+ end
+
+ def initialize(...)
+ ScratchPad << :call_original_initialize
+ super
+ end
+ end
+
def self.collector
Proc.new { |x| ScratchPad << x }
end
@@ -108,6 +120,14 @@ module IOSpecs
"linha ", "cinco.\nHere ", "is ", "line ", "six.\n" ]
end
+ def self.lines_space_separator_without_trailing_spaces
+ [ "Voici", "la", "ligne", "une.\nQui",
+ "\303\250", "la", "linea", "due.\n\n\nAqu\303\255",
+ "est\303\241", "la", "l\303\255nea", "tres.\nHier",
+ "ist", "Zeile", "vier.\n\nEst\303\241", "aqui", "a",
+ "linha", "cinco.\nHere", "is", "line", "six.\n" ]
+ end
+
def self.lines_arbitrary_separator
[ "Voici la ligne une.\nQui \303\250",
" la linea due.\n\n\nAqu\303\255 est\303\241 la l\303\255nea tres.\nHier ist Zeile vier.\n\nEst\303\241 aqui a linha cinco.\nHere is line six.\n" ]
@@ -119,6 +139,12 @@ module IOSpecs
"Est\303\241 aqui a linha cinco.\nHere is line six.\n" ]
end
+ def self.paragraphs_without_trailing_new_line_characters
+ [ "Voici la ligne une.\nQui \303\250 la linea due.",
+ "Aqu\303\255 est\303\241 la l\303\255nea tres.\nHier ist Zeile vier.",
+ "Est\303\241 aqui a linha cinco.\nHere is line six.\n" ]
+ end
+
# Creates an IO instance for an existing fixture file. The
# file should obviously not be deleted.
def self.io_fixture(name, mode = "r:utf-8")
diff --git a/spec/ruby/core/io/flush_spec.rb b/spec/ruby/core/io/flush_spec.rb
index 8de373a0bd..34cf42c425 100644
--- a/spec/ruby/core/io/flush_spec.rb
+++ b/spec/ruby/core/io/flush_spec.rb
@@ -23,7 +23,7 @@ describe "IO#flush" do
# For instance, MJIT creates a worker before @r.close with fork(), @r.close happens,
# and the MJIT worker keeps the pipe open until the worker execve().
# TODO: consider acquiring GVL from MJIT worker.
- guard_not -> { defined?(RubyVM::JIT) && RubyVM::JIT.enabled? } do
+ guard_not -> { defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? } do
it "raises Errno::EPIPE if sync=false and the read end is closed" do
@w.sync = false
@w.write "foo"
diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb
index a3cd180b66..d0c91705af 100644
--- a/spec/ruby/core/io/gets_spec.rb
+++ b/spec/ruby/core/io/gets_spec.rb
@@ -38,14 +38,6 @@ describe "IO#gets" do
IOSpecs.lines.each { |line| line.should == @io.gets }
end
- ruby_version_is ''...'2.7' do
- it "returns tainted strings" do
- while line = @io.gets
- line.should.tainted?
- end
- end
- end
-
it "updates lineno with each invocation" do
while @io.gets
@io.lineno.should == @count += 1
@@ -64,14 +56,6 @@ describe "IO#gets" do
@io.gets(nil).should == IOSpecs.lines.join("")
end
- ruby_version_is ''...'2.7' do
- it "returns tainted strings" do
- while line = @io.gets(nil)
- line.should.tainted?
- end
- end
- end
-
it "updates lineno with each invocation" do
while @io.gets(nil)
@io.lineno.should == @count += 1
@@ -100,14 +84,6 @@ describe "IO#gets" do
@io.gets.should == IOSpecs.lines[4]
end
- ruby_version_is ''...'2.7' do
- it "returns tainted strings" do
- while line = @io.gets("")
- line.should.tainted?
- end
- end
- end
-
it "updates lineno with each invocation" do
while @io.gets("")
@io.lineno.should == @count += 1
@@ -126,14 +102,6 @@ describe "IO#gets" do
@io.gets("la linea").should == "Voici la ligne une.\nQui \303\250 la linea"
end
- ruby_version_is ''...'2.7' do
- it "returns tainted strings" do
- while line = @io.gets("la")
- line.should.tainted?
- end
- end
- end
-
it "updates lineno with each invocation" do
while (@io.gets("la"))
@io.lineno.should == @count += 1
@@ -151,6 +119,16 @@ describe "IO#gets" do
it "returns the first line without a trailing newline character" do
@io.gets(chomp: true).should == IOSpecs.lines_without_newline_characters[0]
end
+
+ ruby_version_is "3.0" do
+ it "raises exception when options passed as Hash" do
+ -> { @io.gets({ chomp: true }) }.should raise_error(TypeError)
+
+ -> {
+ @io.gets("\n", 1, { chomp: true })
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
+ end
+ end
end
end
@@ -232,6 +210,16 @@ describe "IO#gets" do
it "reads all bytes when pass a separator and reading more than all bytes" do
@io.gets("\t", 100).should == "one\n\ntwo\n\nthree\nfour\n"
end
+
+ it "returns empty string when 0 passed as a limit" do
+ @io.gets(0).should == ""
+ @io.gets(nil, 0).should == ""
+ @io.gets("", 0).should == ""
+ end
+
+ it "does not accept limit that doesn't fit in a C off_t" do
+ -> { @io.gets(2**128) }.should raise_error(RangeError)
+ end
end
describe "IO#gets" do
diff --git a/spec/ruby/core/io/internal_encoding_spec.rb b/spec/ruby/core/io/internal_encoding_spec.rb
index 210e969c7b..60afaf2ebd 100644
--- a/spec/ruby/core/io/internal_encoding_spec.rb
+++ b/spec/ruby/core/io/internal_encoding_spec.rb
@@ -113,8 +113,12 @@ describe "IO#internal_encoding" do
Encoding.default_internal = @internal
end
- it "raises an IOError on closed stream" do
- -> { IOSpecs.closed_io.internal_encoding }.should raise_error(IOError)
+ ruby_version_is '3.1' do
+ it "can be retrieved from a closed stream" do
+ io = IOSpecs.io_fixture("lines.txt", "r")
+ io.close
+ io.internal_encoding.should equal(Encoding.default_internal)
+ end
end
describe "with 'r' mode" do
diff --git a/spec/ruby/core/io/lineno_spec.rb b/spec/ruby/core/io/lineno_spec.rb
index 99266ecca1..9a4ad90880 100644
--- a/spec/ruby/core/io/lineno_spec.rb
+++ b/spec/ruby/core/io/lineno_spec.rb
@@ -92,8 +92,13 @@ describe "IO#lineno=" do
@io.lineno.should == 92233
end
- it "raises TypeError on nil argument" do
- -> { @io.lineno = nil }.should raise_error(TypeError)
+ it "raises TypeError if cannot convert argument to Integer implicitly" do
+ -> { @io.lineno = "1" }.should raise_error(TypeError, 'no implicit conversion of String into Integer')
+ -> { @io.lineno = nil }.should raise_error(TypeError, 'no implicit conversion from nil to integer')
+ end
+
+ it "does not accept Integers that don't fit in a C int" do
+ -> { @io.lineno = 2**32 }.should raise_error(RangeError)
end
it "sets the current line number to the given value" do
diff --git a/spec/ruby/core/io/new_spec.rb b/spec/ruby/core/io/new_spec.rb
index 3597098caf..0ef30991fd 100644
--- a/spec/ruby/core/io/new_spec.rb
+++ b/spec/ruby/core/io/new_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/new'
+# NOTE: should be syncronized with library/stringio/initialize_spec.rb
+
describe "IO.new" do
it_behaves_like :io_new, :new
end
diff --git a/spec/ruby/core/io/nonblock_spec.rb b/spec/ruby/core/io/nonblock_spec.rb
new file mode 100644
index 0000000000..e81ac10c58
--- /dev/null
+++ b/spec/ruby/core/io/nonblock_spec.rb
@@ -0,0 +1,70 @@
+require_relative '../../spec_helper'
+
+platform_is_not :windows do
+ describe "IO#nonblock?" do
+ before :all do
+ require 'io/nonblock'
+ end
+
+ it "returns false for a file by default" do
+ File.open(__FILE__) do |f|
+ f.nonblock?.should == false
+ end
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "returns false for pipe by default" do
+ r, w = IO.pipe
+ begin
+ r.nonblock?.should == false
+ w.nonblock?.should == false
+ ensure
+ r.close
+ w.close
+ end
+ end
+
+ it "returns false for socket by default" do
+ require 'socket'
+ TCPServer.open(0) do |socket|
+ socket.nonblock?.should == false
+ end
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "returns true for pipe by default" do
+ r, w = IO.pipe
+ begin
+ r.nonblock?.should == true
+ w.nonblock?.should == true
+ ensure
+ r.close
+ w.close
+ end
+ end
+
+ it "returns true for socket by default" do
+ require 'socket'
+ TCPServer.open(0) do |socket|
+ socket.nonblock?.should == true
+ end
+ end
+ end
+ end
+
+ describe "IO#nonblock=" do
+ before :all do
+ require 'io/nonblock'
+ end
+
+ it "changes the IO to non-blocking mode" do
+ File.open(__FILE__) do |f|
+ f.nonblock = true
+ f.nonblock?.should == true
+ f.nonblock = false
+ f.nonblock?.should == false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/open_spec.rb b/spec/ruby/core/io/open_spec.rb
index 94df5a5ef6..d3a3961df7 100644
--- a/spec/ruby/core/io/open_spec.rb
+++ b/spec/ruby/core/io/open_spec.rb
@@ -63,7 +63,7 @@ describe "IO.open" do
ScratchPad.recorded.should == :called
end
- it "does not propagate a IOError with 'closed stream' message raised by #close" do
+ it "does not propagate an IOError with 'closed stream' message raised by #close" do
IO.open(@fd, "w") do |io|
IOSpecs.io_mock(io, :close) do
super()
@@ -74,7 +74,7 @@ describe "IO.open" do
ScratchPad.recorded.should == :called
end
- it "does not set last error when a IOError with 'closed stream' raised by #close" do
+ it "does not set last error when an IOError with 'closed stream' raised by #close" do
IO.open(@fd, "w") do |io|
IOSpecs.io_mock(io, :close) do
super()
diff --git a/spec/ruby/core/io/path_spec.rb b/spec/ruby/core/io/path_spec.rb
new file mode 100644
index 0000000000..8145c32f39
--- /dev/null
+++ b/spec/ruby/core/io/path_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "IO#path" do
+ ruby_version_is "3.2" do
+ it "returns the path of the file associated with the IO object" do
+ path = tmp("io_path.txt")
+ File.open(path, "w") do |file|
+ IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path
+ end
+ ensure
+ File.unlink(path)
+ end
+ end
+end
diff --git a/spec/ruby/core/io/pipe_spec.rb b/spec/ruby/core/io/pipe_spec.rb
index 2f2cf06f4d..aee0d9003f 100644
--- a/spec/ruby/core/io/pipe_spec.rb
+++ b/spec/ruby/core/io/pipe_spec.rb
@@ -25,6 +25,17 @@ describe "IO.pipe" do
@r.should be_an_instance_of(IOSpecs::SubIO)
@w.should be_an_instance_of(IOSpecs::SubIO)
end
+
+ it "does not use IO.new method to create pipes and allows its overriding" do
+ ScratchPad.record []
+
+ # so redefined .new is not called, but original #initialize is
+ @r, @w = IOSpecs::SubIOWithRedefinedNew.pipe
+ ScratchPad.recorded.should == [:call_original_initialize, :call_original_initialize] # called 2 times - for each pipe (r and w)
+
+ @r.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew)
+ @w.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew)
+ end
end
describe "IO.pipe" do
diff --git a/spec/ruby/core/io/print_spec.rb b/spec/ruby/core/io/print_spec.rb
index 04e971ef6d..085852024c 100644
--- a/spec/ruby/core/io/print_spec.rb
+++ b/spec/ruby/core/io/print_spec.rb
@@ -3,16 +3,27 @@ require_relative 'fixtures/classes'
describe "IO#print" do
before :each do
- @old_separator = $\
- suppress_warning {$\ = '->'}
+ @old_record_separator = $\
+ @old_field_separator = $,
+ suppress_warning {
+ $\ = '->'
+ $, = '^^'
+ }
@name = tmp("io_print")
end
after :each do
- suppress_warning {$\ = @old_separator}
+ suppress_warning {
+ $\ = @old_record_separator
+ $, = @old_field_separator
+ }
rm_r @name
end
+ it "returns nil" do
+ touch(@name) { |f| f.print.should be_nil }
+ end
+
it "writes $_.to_s followed by $\\ (if any) to the stream if no arguments given" do
o = mock('o')
o.should_receive(:to_s).and_return("mockmockmock")
@@ -38,13 +49,15 @@ describe "IO#print" do
IO.read(@name).should == "hello#{$\}"
end
- it "writes each obj.to_s to the stream and appends $\\ (if any) given multiple objects" do
+ it "writes each obj.to_s to the stream separated by $, (if any) and appends $\\ (if any) given multiple objects" do
o, o2 = Object.new, Object.new
def o.to_s(); 'o'; end
def o2.to_s(); 'o2'; end
- touch(@name) { |f| f.print(o, o2) }
- IO.read(@name).should == "#{o.to_s}#{o2.to_s}#{$\}"
+ suppress_warning {
+ touch(@name) { |f| f.print(o, o2) }
+ }
+ IO.read(@name).should == "#{o.to_s}#{$,}#{o2.to_s}#{$\}"
end
it "raises IOError on closed stream" do
diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb
index e50531d336..a62b75274c 100644
--- a/spec/ruby/core/io/read_nonblock_spec.rb
+++ b/spec/ruby/core/io/read_nonblock_spec.rb
@@ -55,6 +55,27 @@ describe "IO#read_nonblock" do
@read.read_nonblock(4).should == "hell"
end
+ it "reads after ungetc with data in the buffer" do
+ @write.write("foobar")
+ @read.set_encoding(
+ 'utf-8', universal_newline: false
+ )
+ c = @read.getc
+ @read.ungetc(c)
+ @read.read_nonblock(3).should == "foo"
+ @read.read_nonblock(3).should == "bar"
+ end
+
+ it "raises an exception after ungetc with data in the buffer and character conversion enabled" do
+ @write.write("foobar")
+ @read.set_encoding(
+ 'utf-8', universal_newline: true
+ )
+ c = @read.getc
+ @read.ungetc(c)
+ -> { @read.read_nonblock(3).should == "foo" }.should raise_error(IOError)
+ end
+
it "returns less data if that is all that is available" do
@write << "hello"
@read.read_nonblock(10).should == "hello"
@@ -70,6 +91,10 @@ describe "IO#read_nonblock" do
@read.read_nonblock(1).should == "1"
end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.read_nonblock(-1) }.should raise_error(ArgumentError)
+ end
+
it "reads into the passed buffer" do
buffer = ""
@write.write("1")
@@ -84,6 +109,21 @@ describe "IO#read_nonblock" do
output.should equal(buffer)
end
+ it "discards the existing buffer content upon successful read" do
+ buffer = "existing content"
+ @write.write("hello world")
+ @write.close
+ @read.read_nonblock(11, buffer)
+ buffer.should == "hello world"
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = "existing content"
+ @write.close
+ -> { @read.read_nonblock(1, buffer) }.should raise_error(EOFError)
+ buffer.should be_empty
+ end
+
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.read_nonblock(5) }.should raise_error(IOError)
end
@@ -96,4 +136,13 @@ describe "IO#read_nonblock" do
-> { @read.read_nonblock(5) }.should raise_error(EOFError)
end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @write.write("abc")
+ @write.close
+ @read.read_nonblock(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index 841e693f37..529afbf0ff 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -104,6 +104,14 @@ describe "IO.read" do
str = IO.read(@fname, encoding: Encoding::ISO_8859_1)
str.encoding.should == Encoding::ISO_8859_1
end
+
+ platform_is :windows do
+ it "reads the file in text mode" do
+ # 0x1A is CTRL+Z and is EOF in Windows text mode.
+ File.binwrite(@fname, "\x1Abbb")
+ IO.read(@fname).should.empty?
+ end
+ end
end
describe "IO.read from a pipe" do
@@ -262,6 +270,13 @@ describe "IO#read" do
@io.read(nil, buf).should equal buf
end
+ it "returns the given buffer when there is nothing to read" do
+ buf = ""
+
+ @io.read
+ @io.read(nil, buf).should equal buf
+ end
+
it "coerces the second argument to string and uses it as a buffer" do
buf = "ABCDE"
obj = mock("buff")
@@ -304,6 +319,9 @@ describe "IO#read" do
-> { IOSpecs.closed_io.read }.should raise_error(IOError)
end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @io.read(-1) }.should raise_error(ArgumentError)
+ end
platform_is_not :windows do
it "raises IOError when stream is closed by another thread" do
@@ -384,13 +402,6 @@ describe "IO#read in binary mode" do
xE2 = [226].pack('C*')
result.should == ("abc" + xE2 + "def").force_encoding(Encoding::BINARY)
end
-
- it "does not transcode file contents when an internal encoding is specified" do
- result = File.open(@name, "r:binary:utf-8") { |f| f.read }.chomp
- result.encoding.should == Encoding::BINARY
- xE2 = [226].pack('C*')
- result.should == ("abc" + xE2 + "def").force_encoding(Encoding::BINARY)
- end
end
describe "IO#read in text mode" do
diff --git a/spec/ruby/core/io/readchar_spec.rb b/spec/ruby/core/io/readchar_spec.rb
index b5f762a846..a66773851a 100644
--- a/spec/ruby/core/io/readchar_spec.rb
+++ b/spec/ruby/core/io/readchar_spec.rb
@@ -1,6 +1,16 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+describe :io_readchar_internal_encoding, shared: true do
+ it "returns a transcoded String" do
+ @io.readchar.should == "あ"
+ end
+
+ it "sets the String encoding to the internal encoding" do
+ @io.readchar.encoding.should equal(Encoding::UTF_8)
+ end
+end
+
describe "IO#readchar" do
before :each do
@io = IOSpecs.io_fixture "lines.txt"
@@ -29,6 +39,62 @@ describe "IO#readchar" do
end
end
+describe "IO#readchar with internal encoding" do
+ after :each do
+ @io.close if @io
+ end
+
+ describe "not specified" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", "r:euc-jp"
+ end
+
+ it "does not transcode the String" do
+ @io.readchar.should == ("あ").encode(Encoding::EUC_JP)
+ end
+
+ it "sets the String encoding to the external encoding" do
+ @io.readchar.encoding.should equal(Encoding::EUC_JP)
+ end
+ end
+
+ describe "specified by open mode" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", "r:euc-jp:utf-8"
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by mode: option" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", mode: "r:euc-jp:utf-8"
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by internal_encoding: option" do
+ before :each do
+ options = { mode: "r",
+ internal_encoding: "utf-8",
+ external_encoding: "euc-jp" }
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", options
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by encoding: option" do
+ before :each do
+ options = { mode: "r", encoding: "euc-jp:utf-8" }
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", options
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+end
+
describe "IO#readchar" do
before :each do
@io = IOSpecs.io_fixture "empty.txt"
diff --git a/spec/ruby/core/io/readline_spec.rb b/spec/ruby/core/io/readline_spec.rb
index 7cb1601816..cf9f0dfc11 100644
--- a/spec/ruby/core/io/readline_spec.rb
+++ b/spec/ruby/core/io/readline_spec.rb
@@ -43,9 +43,44 @@ describe "IO#readline" do
end
end
+ describe "when passed limit" do
+ it "reads limit bytes" do
+ @io.readline(3).should == "Voi"
+ end
+
+ it "returns an empty string when passed 0 as a limit" do
+ @io.readline(0).should == ""
+ end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { @io.readline(2**128) }.should raise_error(RangeError)
+ end
+ end
+
+ describe "when passed separator and limit" do
+ it "reads limit bytes till the separator" do
+ # Voici la ligne une.\
+ @io.readline(" ", 4).should == "Voic"
+ @io.readline(" ", 4).should == "i "
+ @io.readline(" ", 4).should == "la "
+ @io.readline(" ", 4).should == "lign"
+ @io.readline(" ", 4).should == "e "
+ end
+ end
+
describe "when passed chomp" do
it "returns the first line without a trailing newline character" do
@io.readline(chomp: true).should == IOSpecs.lines_without_newline_characters[0]
end
+
+ ruby_version_is "3.0" do
+ it "raises exception when options passed as Hash" do
+ -> { @io.readline({ chomp: true }) }.should raise_error(TypeError)
+
+ -> {
+ @io.readline("\n", 1, { chomp: true })
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
+ end
+ end
end
end
diff --git a/spec/ruby/core/io/readlines_spec.rb b/spec/ruby/core/io/readlines_spec.rb
index 254f2927b5..496003002d 100644
--- a/spec/ruby/core/io/readlines_spec.rb
+++ b/spec/ruby/core/io/readlines_spec.rb
@@ -101,6 +101,32 @@ describe "IO#readlines" do
@io.readlines(obj).should == IOSpecs.lines_r_separator
end
end
+
+ describe "when passed limit" do
+ it "raises ArgumentError when passed 0 as a limit" do
+ -> { @io.readlines(0) }.should raise_error(ArgumentError)
+ end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { @io.readlines(2**128) }.should raise_error(RangeError)
+ end
+ end
+
+ describe "when passed chomp" do
+ it "returns the first line without a trailing newline character" do
+ @io.readlines(chomp: true).should == IOSpecs.lines_without_newline_characters
+ end
+
+ ruby_version_is "3.0" do
+ it "raises exception when options passed as Hash" do
+ -> { @io.readlines({ chomp: true }) }.should raise_error(TypeError)
+
+ -> {
+ @io.readlines("\n", 1, { chomp: true })
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
+ end
+ end
+ end
end
describe "IO#readlines" do
diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb
index 2b33a0d5b1..2901b429c2 100644
--- a/spec/ruby/core/io/readpartial_spec.rb
+++ b/spec/ruby/core/io/readpartial_spec.rb
@@ -59,7 +59,7 @@ describe "IO#readpartial" do
end
it "discards the existing buffer content upon successful read" do
- buffer = "existing"
+ buffer = "existing content"
@wr.write("hello world")
@wr.close
@rd.readpartial(11, buffer)
@@ -93,4 +93,19 @@ describe "IO#readpartial" do
@rd.readpartial(0).should == ""
end
+ ruby_bug "#18421", ""..."3.0.4" do
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = "existing content"
+ @rd.readpartial(0, buffer).should == buffer
+ buffer.should == ""
+ end
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @wr.write("abc")
+ @wr.close
+ @rd.readpartial(10, buffer)
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
end
diff --git a/spec/ruby/core/io/rewind_spec.rb b/spec/ruby/core/io/rewind_spec.rb
index 649041afaf..5579cbd988 100644
--- a/spec/ruby/core/io/rewind_spec.rb
+++ b/spec/ruby/core/io/rewind_spec.rb
@@ -18,6 +18,17 @@ describe "IO#rewind" do
@io.readline.should == "Voici la ligne une.\n"
end
+ it "positions the instance to the beginning of output for write-only IO" do
+ name = tmp("io_rewind_spec")
+ io = File.open(name, "w")
+ io.write("Voici la ligne une.\n")
+ io.rewind
+ io.pos.should == 0
+ ensure
+ io.close
+ rm_r name
+ end
+
it "positions the instance to the beginning of input and clears EOF" do
value = @io.read
@io.rewind
@@ -32,6 +43,10 @@ describe "IO#rewind" do
@io.lineno.should == 0
end
+ it "returns 0" do
+ @io.rewind.should == 0
+ end
+
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.rewind }.should raise_error(IOError)
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
index 7368ec7677..92433d6640 100644
--- a/spec/ruby/core/io/set_encoding_by_bom_spec.rb
+++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
@@ -12,66 +12,251 @@ describe "IO#set_encoding_by_bom" do
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")
+ it "returns nil if not readable" do
+ not_readable_io = new_io(@name, 'wb')
- @io.set_encoding_by_bom.should == Encoding::UTF_8
- @io.external_encoding.should == Encoding::UTF_8
- end
+ not_readable_io.set_encoding_by_bom.should be_nil
+ not_readable_io.external_encoding.should == Encoding::ASCII_8BIT
+ ensure
+ not_readable_io.close
+ end
+
+ it "returns the result encoding if found BOM UTF-8 sequence" do
+ File.binwrite(@name, "\u{FEFF}")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_8
+ @io.external_encoding.should == Encoding::UTF_8
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\u{FEFF}abc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_8
+ @io.external_encoding.should == Encoding::UTF_8
+ @io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_16LE sequence" do
+ File.binwrite(@name, "\xFF\xFE")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\xFF\xFEabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_16BE sequence" do
+ File.binwrite(@name, "\xFE\xFF")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ @io.external_encoding.should == Encoding::UTF_16BE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\xFE\xFFabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ @io.external_encoding.should == Encoding::UTF_16BE
+ @io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_32LE sequence" do
+ File.binwrite(@name, "\xFF\xFE\x00\x00")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ @io.external_encoding.should == Encoding::UTF_32LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\xFF\xFE\x00\x00abc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ @io.external_encoding.should == Encoding::UTF_32LE
+ @io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_32BE sequence" do
+ File.binwrite(@name, "\x00\x00\xFE\xFF")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ @io.external_encoding.should == Encoding::UTF_32BE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.binwrite(@name, "\x00\x00\xFE\xFFabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ @io.external_encoding.should == Encoding::UTF_32BE
+ @io.read.b.should == "abc".b
+ end
+
+ it "returns nil if io is empty" do
+ @io.set_encoding_by_bom.should be_nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns nil if UTF-8 BOM sequence is incomplete" do
+ File.write(@name, "\xEF")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF".b
+ @io.rewind
+
+ File.write(@name, "\xEFa")
- it "returns the result encoding if found BOM UTF_16LE sequence" do
- File.binwrite(@name, "\xFF\xFEabc")
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEFa".b
+ @io.rewind
- @io.set_encoding_by_bom.should == Encoding::UTF_16LE
- @io.external_encoding.should == Encoding::UTF_16LE
- end
+ File.write(@name, "\xEF\xBB")
- it "returns the result encoding if found BOM UTF_16BE sequence" do
- File.binwrite(@name, "\xFE\xFFabc")
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF\xBB".b
+ @io.rewind
- @io.set_encoding_by_bom.should == Encoding::UTF_16BE
- @io.external_encoding.should == Encoding::UTF_16BE
- end
+ File.write(@name, "\xEF\xBBa")
- it "returns the result encoding if found BOM UTF_32LE sequence" do
- File.binwrite(@name, "\xFF\xFE\x00\x00abc")
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF\xBBa".b
+ end
+
+ it "returns nil if UTF-16BE BOM sequence is incomplete" do
+ File.write(@name, "\xFE")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFE".b
+ @io.rewind
+
+ File.write(@name, "\xFEa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFEa".b
+ end
+
+ it "returns nil if UTF-16LE/UTF-32LE BOM sequence is incomplete" do
+ File.write(@name, "\xFF")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFF".b
+ @io.rewind
- @io.set_encoding_by_bom.should == Encoding::UTF_32LE
- @io.external_encoding.should == Encoding::UTF_32LE
- end
+ File.write(@name, "\xFFa")
- it "returns the result encoding if found BOM UTF_32BE sequence" do
- File.binwrite(@name, "\x00\x00\xFE\xFFabc")
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFFa".b
+ end
+
+ it "returns UTF-16LE if UTF-32LE BOM sequence is incomplete" do
+ File.write(@name, "\xFF\xFE")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.write(@name, "\xFF\xFE\x00")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "\x00".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.write(@name, "\xFF\xFE\x00a")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "\x00a".b
+ end
- @io.set_encoding_by_bom.should == Encoding::UTF_32BE
- @io.external_encoding.should == Encoding::UTF_32BE
- end
+ it "returns nil if UTF-32BE BOM sequence is incomplete" do
+ File.write(@name, "\x00")
- it "returns nil if found BOM sequence not provided" do
- File.write(@name, "abc")
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00".b
+ @io.rewind
- @io.set_encoding_by_bom.should == nil
- end
+ File.write(@name, "\x00a")
- it 'returns exception if io not in binary mode' do
- not_binary_io = new_io(@name, 'r')
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00a".b
+ @io.rewind
- -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode')
- ensure
- not_binary_io.close
- end
+ File.write(@name, "\x00\x00")
- it 'returns exception if encoding already set' do
- @io.set_encoding("utf-8")
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00".b
+ @io.rewind
- -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already')
- end
+ File.write(@name, "\x00\x00a")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00a".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00\xFE")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00\xFE".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00\xFEa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00\xFEa".b
+ end
+
+ it "returns nil if found BOM sequence not provided" do
+ File.write(@name, "abc")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read(3).should == "abc".b
+ end
+
+ it 'returns exception if io not in binary mode' do
+ not_binary_io = new_io(@name, 'r')
+
+ -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode')
+ ensure
+ not_binary_io.close
+ end
+
+ it 'returns exception if encoding already set' do
+ @io.set_encoding("utf-8")
+
+ -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already')
+ end
- it 'returns exception if encoding conversion is already set' do
- @io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
+ it 'returns exception if encoding conversion is already set' do
+ @io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
- -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding conversion is set')
- end
+ -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding conversion is set')
end
end
diff --git a/spec/ruby/core/io/set_encoding_spec.rb b/spec/ruby/core/io/set_encoding_spec.rb
index 5aec6a96c3..22d9017635 100644
--- a/spec/ruby/core/io/set_encoding_spec.rb
+++ b/spec/ruby/core/io/set_encoding_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe :io_set_encoding_write, shared: true do
- it "sets the encodings to nil" do
+ it "sets the encodings to nil when they were set previously" do
@io = new_io @name, "#{@object}:ibm437:ibm866"
@io.set_encoding nil, nil
@@ -9,6 +9,19 @@ describe :io_set_encoding_write, shared: true do
@io.internal_encoding.should be_nil
end
+ it "sets the encodings to nil when the IO is built with no explicit encoding" do
+ @io = new_io @name, @object
+
+ # Checking our assumptions first
+ @io.external_encoding.should be_nil
+ @io.internal_encoding.should be_nil
+
+ @io.set_encoding nil, nil
+
+ @io.external_encoding.should be_nil
+ @io.internal_encoding.should be_nil
+ end
+
it "prevents the encodings from changing when Encoding defaults are changed" do
@io = new_io @name, "#{@object}:utf-8:us-ascii"
@io.set_encoding nil, nil
@@ -38,6 +51,7 @@ describe "IO#set_encoding when passed nil, nil" do
@external = Encoding.default_external
@internal = Encoding.default_internal
+ # The defaults
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = nil
@@ -113,6 +127,22 @@ describe "IO#set_encoding when passed nil, nil" do
describe "with 'a+' mode" do
it_behaves_like :io_set_encoding_write, nil, "a+"
end
+
+ describe "with standard IOs" do
+ it "correctly resets them" do
+ STDOUT.external_encoding.should == nil
+ STDOUT.internal_encoding.should == nil
+
+ begin
+ STDOUT.set_encoding(Encoding::US_ASCII, Encoding::ISO_8859_1)
+ ensure
+ STDOUT.set_encoding(nil, nil)
+ end
+
+ STDOUT.external_encoding.should == nil
+ STDOUT.internal_encoding.should == nil
+ end
+ end
end
describe "IO#set_encoding" do
@@ -188,4 +218,21 @@ describe "IO#set_encoding" do
@io.external_encoding.should == Encoding::UTF_8
@io.internal_encoding.should == Encoding::UTF_16BE
end
+
+ it "saves encoding options passed as a hash in the last argument" do
+ File.write(@name, "\xff")
+ io = File.open(@name)
+ io.set_encoding(Encoding::EUC_JP, Encoding::SHIFT_JIS, invalid: :replace, replace: ".")
+ io.read.should == "."
+ ensure
+ io.close
+ end
+
+ it "raises ArgumentError when no arguments are given" do
+ -> { @io.set_encoding() }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError when too many arguments are given" do
+ -> { @io.set_encoding(1, 2, 3) }.should raise_error(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index 91766fbe03..02bbe19c1a 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -77,6 +77,10 @@ describe :io_each, shared: true do
-> { @io.send(@method, 0){} }.should raise_error(ArgumentError)
end
end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { @io.send(@method, 2**128){} }.should raise_error(RangeError)
+ end
end
describe "when passed a String containing one space as a separator" do
@@ -113,6 +117,13 @@ describe :io_each, shared: true do
@io.send(@method, "") { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.paragraphs
end
+
+ it "discards leading newlines" do
+ @io.readline
+ @io.readline
+ @io.send(@method, "") { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs[1..-1]
+ end
end
describe "with both separator and limit" do
@@ -152,6 +163,13 @@ describe :io_each, shared: true do
@io.send(@method, "", 1024) { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.paragraphs
end
+
+ it "discards leading newlines" do
+ @io.readline
+ @io.readline
+ @io.send(@method, "", 1024) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs[1..-1]
+ end
end
end
end
@@ -161,6 +179,72 @@ describe :io_each, shared: true do
@io.send(@method, chomp: true) { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.lines_without_newline_characters
end
+
+ ruby_version_is "3.0" do
+ it "raises exception when options passed as Hash" do
+ -> {
+ @io.send(@method, { chomp: true }) { |s| }
+ }.should raise_error(TypeError)
+
+ -> {
+ @io.send(@method, "\n", 1, { chomp: true }) { |s| }
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)")
+ end
+ end
+ end
+
+ describe "when passed chomp and a separator" do
+ it "yields each line without separator to the passed block" do
+ @io.send(@method, " ", chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.lines_space_separator_without_trailing_spaces
+ end
+ end
+
+ describe "when passed chomp and empty line as a separator" do
+ it "yields each paragraph without trailing new line characters" do
+ @io.send(@method, "", 1024, chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs_without_trailing_new_line_characters
+ end
+ end
+
+ describe "when passed chomp and nil as a separator" do
+ ruby_version_is "3.2" do
+ it "yields self's content" do
+ @io.pos = 100
+ @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"]
+ end
+ end
+
+ ruby_version_is ""..."3.2" do
+ it "yields self's content without trailing new line character" do
+ @io.pos = 100
+ @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six."]
+ end
+ end
+ end
+
+ describe "when passed chomp, nil as a separator, and a limit" do
+ it "yields each line of limit size without truncating trailing new line character" do
+ # 43 - is a size of the 1st paragraph in the file
+ @io.send(@method, nil, 43, chomp: true) { |s| ScratchPad << s }
+
+ ScratchPad.recorded.should == [
+ "Voici la ligne une.\nQui è la linea due.\n\n\n",
+ "Aquí está la línea tres.\n" + "Hier ist Zeile ",
+ "vier.\n\nEstá aqui a linha cinco.\nHere is li",
+ "ne six.\n"
+ ]
+ end
+ end
+
+ describe "when passed too many arguments" do
+ it "raises ArgumentError" do
+ -> {
+ @io.send(@method, "", 1, "excess argument", chomp: true) {}
+ }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/io/shared/new.rb b/spec/ruby/core/io/shared/new.rb
index f2a0970a40..7677aada6e 100644
--- a/spec/ruby/core/io/shared/new.rb
+++ b/spec/ruby/core/io/shared/new.rb
@@ -1,5 +1,7 @@
require_relative '../fixtures/classes'
+# NOTE: should be syncronized with library/stringio/initialize_spec.rb
+
# This group of specs may ONLY contain specs that do successfully create
# an IO instance from the file descriptor returned by #new_fd helper.
describe :io_new, shared: true do
diff --git a/spec/ruby/core/io/shared/pos.rb b/spec/ruby/core/io/shared/pos.rb
index d83a6c6692..3fdd3eb2b3 100644
--- a/spec/ruby/core/io/shared/pos.rb
+++ b/spec/ruby/core/io/shared/pos.rb
@@ -60,7 +60,13 @@ describe :io_set_pos, shared: true do
end
end
- it "does not accept Integers that don't fit in a C long" do
+ it "raises TypeError when cannot convert implicitly argument to Integer" do
+ File.open @fname do |io|
+ -> { io.send @method, Object.new }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
+ end
+ end
+
+ it "does not accept Integers that don't fit in a C off_t" 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 8e4a73bb98..7681e1b5c1 100644
--- a/spec/ruby/core/io/shared/readlines.rb
+++ b/spec/ruby/core/io/shared/readlines.rb
@@ -73,6 +73,23 @@ describe :io_readlines_options_19, shared: true do
result = IO.send(@method, @name, 10, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_limit
end
+
+ it "ignores the object as a limit if it is negative" do
+ result = IO.send(@method, @name, -2, &@object)
+ (result ? result : ScratchPad.recorded).should == IOSpecs.lines
+ end
+
+ it "does not accept Integers that don't fit in a C off_t" do
+ -> { IO.send(@method, @name, 2**128, &@object) }.should raise_error(RangeError)
+ end
+
+ ruby_bug "#18767", ""..."3.3" do
+ describe "when passed limit" do
+ it "raises ArgumentError when passed 0 as a limit" do
+ -> { IO.send(@method, @name, 0, &@object) }.should raise_error(ArgumentError)
+ end
+ end
+ end
end
describe "when the object is a String" do
@@ -87,31 +104,35 @@ describe :io_readlines_options_19, shared: true do
end
end
- describe "when the object is a Hash" do
- it "uses the value as the options hash" do
- result = IO.send(@method, @name, mode: "r", &@object)
- (result ? result : ScratchPad.recorded).should == IOSpecs.lines
+ describe "when the object is an options Hash" do
+ ruby_version_is "3.0" do
+ it "raises TypeError exception" do
+ -> {
+ IO.send(@method, @name, { chomp: true }, &@object)
+ }.should raise_error(TypeError)
+ end
end
end
- end
- describe "when passed name, object, object" 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)
- end.should raise_error(IOError)
- end
+ describe "when the object is neither Integer nor String" do
+ it "raises TypeError exception" do
+ obj = mock("not io readlines limit")
- it "calls #to_hash to convert the second object to a Hash" do
- options = mock("io readlines options Hash")
- options.should_receive(:to_hash).and_return({ mode: "w" })
- -> do
- IO.send(@method, @filename, 10, **options, &@object)
- end.should raise_error(IOError)
+ -> {
+ IO.send(@method, @name, obj, &@object)
+ }.should raise_error(TypeError)
end
end
+ end
+
+ describe "when passed name, keyword arguments" do
+ it "uses the keyword arguments as options" do
+ result = IO.send(@method, @name, mode: "r", &@object)
+ (result ? result : ScratchPad.recorded).should == IOSpecs.lines
+ end
+ end
+ describe "when passed name, object, object" do
describe "when the first object is a String" do
it "uses the second object as a limit if it is an Integer" do
result = IO.send(@method, @name, " ", 10, &@object)
@@ -124,32 +145,18 @@ describe :io_readlines_options_19, shared: true do
result = IO.send(@method, @name, " ", limit, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
-
- it "uses the second object as an options Hash" do
- -> do
- IO.send(@method, @filename, " ", mode: "w", &@object)
- end.should raise_error(IOError)
- end
-
- it "calls #to_hash to convert the second object to a Hash" do
- options = mock("io readlines options Hash")
- options.should_receive(:to_hash).and_return({ mode: "w" })
- -> do
- IO.send(@method, @filename, " ", **options, &@object)
- end.should raise_error(IOError)
- end
end
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(" ")
- result = IO.send(@method, @name, sep, 10, mode: "r", &@object)
+ result = IO.send(@method, @name, sep, 10, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
it "uses the second object as a limit if it is an Integer" do
- result = IO.send(@method, @name, " ", 10, mode: "r", &@object)
+ result = IO.send(@method, @name, " ", 10, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
@@ -159,24 +166,59 @@ describe :io_readlines_options_19, shared: true do
result = IO.send(@method, @name, " ", limit, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
+ end
+
+ describe "when the second object is neither Integer nor String" do
+ it "raises TypeError exception" do
+ obj = mock("not io readlines limit")
+
+ -> {
+ IO.send(@method, @name, " ", obj, &@object)
+ }.should raise_error(TypeError)
+ end
+ end
- it "uses the second object as an options Hash" do
+ describe "when the second object is an options Hash" do
+ ruby_version_is "3.0" do
+ it "raises TypeError exception" do
+ -> {
+ IO.send(@method, @name, "", { chomp: true }, &@object)
+ }.should raise_error(TypeError)
+ end
+ end
+ end
+ end
+
+ describe "when passed name, object, keyword arguments" do
+ describe "when the first object is an Integer" do
+ it "uses the keyword arguments as options" do
+ -> do
+ IO.send(@method, @filename, 10, mode: "w", &@object)
+ end.should raise_error(IOError)
+ end
+ end
+
+ describe "when the first object is a String" do
+ it "uses the keyword arguments as options" do
-> do
IO.send(@method, @filename, " ", mode: "w", &@object)
end.should raise_error(IOError)
end
+ end
+
+ describe "when the first object is not a String or Integer" do
+ it "uses the keyword arguments as options" do
+ sep = mock("io readlines separator")
+ sep.should_receive(:to_str).at_least(1).and_return(" ")
- it "calls #to_hash to convert the second object to a Hash" do
- options = mock("io readlines options Hash")
- options.should_receive(:to_hash).and_return({ mode: "w" })
-> do
- IO.send(@method, @filename, " ", **options, &@object)
+ IO.send(@method, @filename, sep, mode: "w", &@object)
end.should raise_error(IOError)
end
end
end
- describe "when passed name, separator, limit, options" do
+ describe "when passed name, separator, limit, keyword arguments" do
it "calls #to_path to convert the name object" do
name = mock("io name to_path")
name.should_receive(:to_path).and_return(@name)
@@ -198,12 +240,24 @@ describe :io_readlines_options_19, shared: true do
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
- it "calls #to_hash to convert the options object" do
- options = mock("io readlines options Hash")
- options.should_receive(:to_hash).and_return({ mode: "w" })
+ it "uses the keyword arguments as options" do
-> do
- IO.send(@method, @filename, " ", 10, **options, &@object)
+ IO.send(@method, @filename, " ", 10, mode: "w", &@object)
end.should raise_error(IOError)
end
+
+ describe "when passed chomp, nil as a separator, and a limit" do
+ it "yields each line of limit size without truncating trailing new line character" do
+ # 43 - is a size of the 1st paragraph in the file
+ result = IO.send(@method, @name, nil, 43, chomp: true, &@object)
+
+ (result ? result : ScratchPad.recorded).should == [
+ "Voici la ligne une.\nQui è la linea due.\n\n\n",
+ "Aquí está la línea tres.\n" + "Hier ist Zeile ",
+ "vier.\n\nEstá aqui a linha cinco.\nHere is li",
+ "ne six.\n"
+ ]
+ end
+ end
end
end
diff --git a/spec/ruby/core/io/shared/write.rb b/spec/ruby/core/io/shared/write.rb
index 5e53d981c5..9503f94212 100644
--- a/spec/ruby/core/io/shared/write.rb
+++ b/spec/ruby/core/io/shared/write.rb
@@ -69,16 +69,6 @@ describe :io_write, shared: true do
-> { IOSpecs.closed_io.send(@method, "hello") }.should raise_error(IOError)
end
- it "does not modify the passed argument" do
- File.open(@filename, "w") do |f|
- f.set_encoding(Encoding::IBM437)
- # A character whose codepoint differs between UTF-8 and IBM437
- f.write "ƒ".freeze
- end
-
- File.binread(@filename).bytes.should == [159]
- end
-
describe "on a pipe" do
before :each do
@r, @w = IO.pipe
@@ -99,7 +89,7 @@ describe :io_write, shared: true do
# For instance, MJIT creates a worker before @r.close with fork(), @r.close happens,
# and the MJIT worker keeps the pipe open until the worker execve().
# TODO: consider acquiring GVL from MJIT worker.
- guard_not -> { defined?(RubyVM::JIT) && RubyVM::JIT.enabled? } do
+ guard_not -> { defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? } do
it "raises Errno::EPIPE if the read end is closed and does not die from SIGPIPE" do
@r.close
-> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, /Broken pipe/)
diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb
index 8201ad47ca..e7f63cefec 100644
--- a/spec/ruby/core/io/sysread_spec.rb
+++ b/spec/ruby/core/io/sysread_spec.rb
@@ -6,7 +6,7 @@ describe "IO#sysread on a file" do
@file_name = tmp("IO_sysread_file") + $$.to_s
File.open(@file_name, "w") do |f|
# write some stuff
- f.write("012345678901234567890123456789")
+ f.write("012345678901234567890123456789\nabcdef")
end
@file = File.open(@file_name, "r+")
end
@@ -84,6 +84,29 @@ describe "IO#sysread on a file" do
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError)
end
+
+ it "immediately returns an empty string if the length argument is 0" do
+ @file.sysread(0).should == ""
+ end
+
+ it "immediately returns the given buffer if the length argument is 0" do
+ buffer = "existing content"
+ @file.sysread(0, buffer).should == buffer
+ buffer.should == "existing content"
+ end
+
+ it "discards the existing buffer content upon successful read" do
+ buffer = "existing content"
+ @file.sysread(11, buffer)
+ buffer.should == "01234567890"
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = "existing content"
+ @file.seek(0, :END)
+ -> { @file.sysread(1, buffer) }.should raise_error(EOFError)
+ buffer.should be_empty
+ end
end
describe "IO#sysread" do
@@ -100,4 +123,10 @@ describe "IO#sysread" do
@write.syswrite "ab"
@read.sysread(3).should == "ab"
end
+
+ guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do # https://bugs.ruby-lang.org/issues/18880
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.sysread(-1) }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/io/sysseek_spec.rb b/spec/ruby/core/io/sysseek_spec.rb
index e631939bce..002f2a14eb 100644
--- a/spec/ruby/core/io/sysseek_spec.rb
+++ b/spec/ruby/core/io/sysseek_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
require_relative 'shared/pos'
describe "IO#sysseek" do
- it_behaves_like :io_set_pos, :seek
+ it_behaves_like :io_set_pos, :sysseek
end
describe "IO#sysseek" do
diff --git a/spec/ruby/core/io/syswrite_spec.rb b/spec/ruby/core/io/syswrite_spec.rb
index a28cc62174..eeb8d302a7 100644
--- a/spec/ruby/core/io/syswrite_spec.rb
+++ b/spec/ruby/core/io/syswrite_spec.rb
@@ -29,6 +29,16 @@ describe "IO#syswrite on a file" do
end
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.syswrite("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [198, 146]
+ end
+
it "warns if called immediately after a buffered IO#write" do
@file.write("abcde")
-> { @file.syswrite("fghij") }.should complain(/syswrite/)
diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb
index 776707205a..716743a6af 100644
--- a/spec/ruby/core/io/ungetbyte_spec.rb
+++ b/spec/ruby/core/io/ungetbyte_spec.rb
@@ -36,20 +36,10 @@ describe "IO#ungetbyte" do
@io.getbyte.should == 97
end
- ruby_version_is ''...'2.6.1' do
- it "is an RangeError if the integer is not in 8bit" do
- for i in [4095, 0x4f7574206f6620636861722072616e6765] do
- -> { @io.ungetbyte(i) }.should raise_error(RangeError)
- end
- end
- end
-
- ruby_version_is '2.6.1' do
- it "never raises RangeError" do
- for i in [4095, 0x4f7574206f6620636861722072616e67ff] do
- @io.ungetbyte(i).should be_nil
- @io.getbyte.should == 255
- end
+ it "never raises RangeError" do
+ for i in [4095, 0x4f7574206f6620636861722072616e67ff] do
+ @io.ungetbyte(i).should be_nil
+ @io.getbyte.should == 255
end
end
diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb
index a05d80ee9c..41a455c836 100644
--- a/spec/ruby/core/io/ungetc_spec.rb
+++ b/spec/ruby/core/io/ungetc_spec.rb
@@ -103,7 +103,7 @@ describe "IO#ungetc" do
-> { @io.sysread(1) }.should raise_error(IOError)
end
- ruby_version_is "0"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "does not affect the stream and returns nil when passed nil" do
@io.getc.should == ?V
@io.ungetc(nil)
diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb
index a8b9ce0a36..5532556d8a 100644
--- a/spec/ruby/core/io/write_nonblock_spec.rb
+++ b/spec/ruby/core/io/write_nonblock_spec.rb
@@ -31,6 +31,16 @@ platform_is_not :windows do
end
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.write_nonblock("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [198, 146]
+ end
+
it "checks if the file is writable if writing zero bytes" do
-> {
@readonly_file.write_nonblock("")
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index 60e66e998f..bcc0582d9e 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -44,6 +44,16 @@ describe "IO#write on a file" do
@file.write("hellø").should == 6
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.write("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [159]
+ end
+
it "uses the encoding from the given option for non-ascii encoding" do
File.open(@filename, "w", encoding: Encoding::UTF_32LE) do |file|
file.write("hi").should == 8
@@ -168,3 +178,27 @@ platform_is :windows do
end
end
end
+
+ruby_version_is "3.0" do
+ describe "IO#write on STDOUT" do
+ # https://bugs.ruby-lang.org/issues/14413
+ platform_is_not :windows do
+ it "raises SignalException SIGPIPE if the stream is closed instead of Errno::EPIPE like other IOs" do
+ stderr_file = tmp("stderr")
+ begin
+ IO.popen([*ruby_exe, "-e", "loop { puts :ok }"], "r", err: stderr_file) do |io|
+ io.gets.should == "ok\n"
+ io.close
+ end
+ status = $?
+ status.should_not.success?
+ status.should.signaled?
+ Signal.signame(status.termsig).should == 'PIPE'
+ File.read(stderr_file).should.empty?
+ ensure
+ rm_r stderr_file
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/kernel/Complex_spec.rb b/spec/ruby/core/kernel/Complex_spec.rb
index 4f043526b8..cc8177fa02 100644
--- a/spec/ruby/core/kernel/Complex_spec.rb
+++ b/spec/ruby/core/kernel/Complex_spec.rb
@@ -1,4 +1,6 @@
require_relative '../../spec_helper'
+require_relative '../../shared/kernel/complex'
+require_relative 'fixtures/Complex'
describe "Kernel.Complex()" do
describe "when passed [Complex, Complex]" do
@@ -58,7 +60,92 @@ describe "Kernel.Complex()" do
end
end
- describe "when passed a String" do
+ describe "when passed [String]" do
+ it_behaves_like :kernel_complex, :Complex_method, KernelSpecs
+
+ context "invalid argument" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ Complex("79+4i".encode("UTF-16"))
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "raises ArgumentError for unrecognised Strings" do
+ -> {
+ Complex("ruby")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "ruby"')
+ end
+
+ it "raises ArgumentError for trailing garbage" do
+ -> {
+ Complex("79+4iruby")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "79+4iruby"')
+ end
+
+ it "does not understand Float::INFINITY" do
+ -> {
+ Complex("Infinity")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "Infinity"')
+
+ -> {
+ Complex("-Infinity")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "-Infinity"')
+ end
+
+ it "does not understand Float::NAN" do
+ -> {
+ Complex("NaN")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "NaN"')
+ end
+
+ it "does not understand a sequence of _" do
+ -> {
+ Complex("7__9+4__0i")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "7__9+4__0i"')
+ end
+
+ it "does not allow null-byte" do
+ -> {
+ Complex("1-2i\0")
+ }.should raise_error(ArgumentError, "string contains null byte")
+ end
+ end
+
+ context "invalid argument and exception: false passed" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ Complex("79+4i".encode("UTF-16"), exception: false)
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "returns nil for unrecognised Strings" do
+ Complex("ruby", exception: false).should == nil
+ end
+
+ it "returns nil when trailing garbage" do
+ Complex("79+4iruby", exception: false).should == nil
+ end
+
+ it "returns nil for Float::INFINITY" do
+ Complex("Infinity", exception: false).should == nil
+ Complex("-Infinity", exception: false).should == nil
+ end
+
+ it "returns nil for Float::NAN" do
+ Complex("NaN", exception: false).should == nil
+ end
+
+ it "returns nil when there is a sequence of _" do
+ Complex("7__9+4__0i", exception: false).should == nil
+ end
+
+ it "returns nil when String contains null-byte" do
+ Complex("1-2i\0", exception: false).should == nil
+ end
+ end
+ end
+
+ describe "when passes [String, String]" do
it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/core/kernel/caller_locations_spec.rb b/spec/ruby/core/kernel/caller_locations_spec.rb
index 3ec8f0f432..5994b28fa3 100644
--- a/spec/ruby/core/kernel/caller_locations_spec.rb
+++ b/spec/ruby/core/kernel/caller_locations_spec.rb
@@ -34,12 +34,10 @@ describe 'Kernel#caller_locations' do
locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
end
- ruby_version_is "2.7" do
- it "works with beginless ranges" do
- locations1 = caller_locations(0)
- locations2 = caller_locations(eval("(...5)"))
- locations2.map(&:to_s)[eval("(2..)")].should == locations1[eval("(...5)")].map(&:to_s)[eval("(2..)")]
- end
+ it "works with beginless ranges" do
+ locations1 = caller_locations(0)
+ locations2 = caller_locations((...5))
+ locations2.map(&:to_s)[eval("(2..)")].should == locations1[(...5)].map(&:to_s)[eval("(2..)")]
end
it "can be called with a range whose end is negative" do
diff --git a/spec/ruby/core/kernel/caller_spec.rb b/spec/ruby/core/kernel/caller_spec.rb
index dba65ddcb0..f1ff7044b8 100644
--- a/spec/ruby/core/kernel/caller_spec.rb
+++ b/spec/ruby/core/kernel/caller_spec.rb
@@ -50,12 +50,10 @@ describe 'Kernel#caller' do
locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
end
- ruby_version_is "2.7" do
- it "works with beginless ranges" do
- locations1 = KernelSpecs::CallerTest.locations(0)
- locations2 = KernelSpecs::CallerTest.locations(eval("(..5)"))
- locations2.map(&:to_s)[eval("(2..)")].should == locations1[eval("(..5)")].map(&:to_s)[eval("(2..)")]
- end
+ it "works with beginless ranges" do
+ locations1 = KernelSpecs::CallerTest.locations(0)
+ locations2 = KernelSpecs::CallerTest.locations((..5))
+ locations2.map(&:to_s)[eval("(2..)")].should == locations1[(..5)].map(&:to_s)[eval("(2..)")]
end
guard -> { Kernel.instance_method(:tap).source_location } do
diff --git a/spec/ruby/core/kernel/clone_spec.rb b/spec/ruby/core/kernel/clone_spec.rb
index c18af4a490..a87c7544fe 100644
--- a/spec/ruby/core/kernel/clone_spec.rb
+++ b/spec/ruby/core/kernel/clone_spec.rb
@@ -28,27 +28,120 @@ describe "Kernel#clone" do
clone.class.should equal klass
end
- it "copies frozen state from the original" do
- o2 = @obj.clone
- @obj.freeze
- o3 = @obj.clone
+ describe "with no arguments" do
+ it "copies frozen state from the original" do
+ o2 = @obj.clone
+ o2.should_not.frozen?
- o2.should_not.frozen?
- o3.should.frozen?
+ @obj.freeze
+ o3 = @obj.clone
+ o3.should.frozen?
+ end
+
+ it 'copies frozen?' do
+ o = ''.freeze.clone
+ o.frozen?.should be_true
+ end
end
- ruby_version_is '3.0' do
- it 'takes an freeze: true option to frozen copy' do
- @obj.clone(freeze: true).should.frozen?
+ describe "with freeze: nil" do
+ ruby_version_is ""..."3.0" do
+ it "raises ArgumentError" do
+ -> { @obj.clone(freeze: nil) }.should raise_error(ArgumentError, /unexpected value for freeze: NilClass/)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "copies frozen state from the original, like #clone without arguments" do
+ o2 = @obj.clone(freeze: nil)
+ o2.should_not.frozen?
+
+ @obj.freeze
+ o3 = @obj.clone(freeze: nil)
+ o3.should.frozen?
+ end
+
+ it "copies frozen?" do
+ o = "".freeze.clone(freeze: nil)
+ o.frozen?.should be_true
+ end
+ end
+ end
+
+ describe "with freeze: true" do
+ it 'makes a frozen copy if the original is frozen' do
@obj.freeze
@obj.clone(freeze: true).should.frozen?
end
+
+ ruby_version_is ''...'3.0' do
+ it 'does not freeze the copy even if the original is not frozen' do
+ @obj.clone(freeze: true).should_not.frozen?
+ end
+
+ it "calls #initialize_clone with no kwargs" do
+ obj = KernelSpecs::CloneFreeze.new
+ obj.clone(freeze: true)
+ ScratchPad.recorded.should == [obj, {}]
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it 'freezes the copy even if the original was not frozen' do
+ @obj.clone(freeze: true).should.frozen?
+ end
+
+ it "calls #initialize_clone with kwargs freeze: true" do
+ obj = KernelSpecs::CloneFreeze.new
+ obj.clone(freeze: true)
+ ScratchPad.recorded.should == [obj, { freeze: true }]
+ end
+
+ it "calls #initialize_clone with kwargs freeze: true even if #initialize_clone only takes a single argument" do
+ obj = KernelSpecs::Clone.new
+ -> { obj.clone(freeze: true) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
+ end
+ end
end
- it 'takes an freeze: false option to not return frozen copy' do
- @obj.clone(freeze: false).should_not.frozen?
- @obj.freeze
- @obj.clone(freeze: false).should_not.frozen?
+ describe "with freeze: false" do
+ it 'does not freeze the copy if the original is frozen' do
+ @obj.freeze
+ @obj.clone(freeze: false).should_not.frozen?
+ end
+
+ it 'does not freeze the copy if the original is not frozen' do
+ @obj.clone(freeze: false).should_not.frozen?
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "calls #initialize_clone with no kwargs" do
+ obj = KernelSpecs::CloneFreeze.new
+ obj.clone(freeze: false)
+ ScratchPad.recorded.should == [obj, {}]
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "calls #initialize_clone with kwargs freeze: false" do
+ obj = KernelSpecs::CloneFreeze.new
+ obj.clone(freeze: false)
+ ScratchPad.recorded.should == [obj, { freeze: false }]
+ end
+
+ it "calls #initialize_clone with kwargs freeze: false even if #initialize_clone only takes a single argument" do
+ obj = KernelSpecs::Clone.new
+ -> { obj.clone(freeze: false) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
+ end
+ end
+ end
+
+ describe "with freeze: anything else" do
+ it 'raises ArgumentError when passed not true/false/nil' do
+ -> { @obj.clone(freeze: 1) }.should raise_error(ArgumentError, /unexpected value for freeze: Integer/)
+ -> { @obj.clone(freeze: "") }.should raise_error(ArgumentError, /unexpected value for freeze: String/)
+ -> { @obj.clone(freeze: Object.new) }.should raise_error(ArgumentError, /unexpected value for freeze: Object/)
+ end
end
it "copies instance variables" do
@@ -113,16 +206,4 @@ describe "Kernel#clone" do
cloned.bar.should == ['a']
end
-
- it 'copies frozen?' do
- o = ''.freeze.clone
- o.frozen?.should be_true
- end
-
- ruby_version_is ''...'2.7' do
- it 'copies tainted?' do
- o = ''.taint.clone
- o.tainted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/kernel/define_singleton_method_spec.rb b/spec/ruby/core/kernel/define_singleton_method_spec.rb
index dc77c3e6f8..2d8b1bf413 100644
--- a/spec/ruby/core/kernel/define_singleton_method_spec.rb
+++ b/spec/ruby/core/kernel/define_singleton_method_spec.rb
@@ -96,4 +96,19 @@ describe "Kernel#define_singleton_method" do
o.define(:foo) { raise "not used" }
}.should raise_error(ArgumentError)
end
+
+ it "always defines the method with public visibility" do
+ cls = Class.new
+ def cls.define(name, &block)
+ private
+ define_singleton_method(name, &block)
+ end
+
+ -> {
+ suppress_warning do
+ cls.define(:foo) { :ok }
+ end
+ cls.foo.should == :ok
+ }.should_not raise_error(NoMethodError)
+ end
end
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 1e2764a4de..9be0f2dfd3 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -168,6 +168,12 @@ describe "Kernel#eval" do
suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__
suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success'
end
+
+ it 'uses the given binding file and line for __FILE__ and __LINE__' do
+ suppress_warning {
+ eval("[__FILE__, __LINE__]", binding).should == [__FILE__, __LINE__]
+ }
+ end
end
ruby_version_is "3.0" do
@@ -180,6 +186,10 @@ describe "Kernel#eval" do
eval("eval '__FILE__', binding", binding, 'success').should == '(eval)'
eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
end
+
+ it 'uses (eval) for __FILE__ and 1 for __LINE__ with a binding argument' do
+ eval("[__FILE__, __LINE__]", binding).should == ["(eval)", 1]
+ end
end
# Found via Rubinius bug github:#149
diff --git a/spec/ruby/core/kernel/fixtures/Complex.rb b/spec/ruby/core/kernel/fixtures/Complex.rb
new file mode 100644
index 0000000000..bf14d55ad5
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/Complex.rb
@@ -0,0 +1,5 @@
+module KernelSpecs
+ def self.Complex_method(string)
+ Complex(string)
+ end
+end
diff --git a/spec/ruby/core/kernel/fixtures/classes.rb b/spec/ruby/core/kernel/fixtures/classes.rb
index 1bf5715c50..541a4c075e 100644
--- a/spec/ruby/core/kernel/fixtures/classes.rb
+++ b/spec/ruby/core/kernel/fixtures/classes.rb
@@ -281,14 +281,25 @@ module KernelSpecs
@two = two
end
- def initialize_copy(other)
+ def initialize_copy(other, **kw)
ScratchPad.record object_id
end
+
+ # define to support calling #clone with optional :freeze keyword argument
+ def initialize_clone(other, **kw)
+ super(other) # to call #initialize_copy
+ end
end
class Clone
def initialize_clone(other)
- ScratchPad.record other.object_id
+ ScratchPad.record other
+ end
+ end
+
+ class CloneFreeze
+ def initialize_clone(other, **kwargs)
+ ScratchPad.record([other, kwargs])
end
end
diff --git a/spec/ruby/core/kernel/fixtures/warn_core_method.rb b/spec/ruby/core/kernel/fixtures/warn_core_method.rb
index f5dee6b668..fd82562404 100644
--- a/spec/ruby/core/kernel/fixtures/warn_core_method.rb
+++ b/spec/ruby/core/kernel/fixtures/warn_core_method.rb
@@ -1,6 +1,6 @@
raise 'should be run without RubyGems' if defined?(Gem)
-def deprecated(n=1)
+public def deprecated(n=1)
# puts nil, caller(0), nil
warn "use X instead", uplevel: n
end
diff --git a/spec/ruby/core/kernel/initialize_clone_spec.rb b/spec/ruby/core/kernel/initialize_clone_spec.rb
new file mode 100644
index 0000000000..2d889f5aad
--- /dev/null
+++ b/spec/ruby/core/kernel/initialize_clone_spec.rb
@@ -0,0 +1,28 @@
+require_relative '../../spec_helper'
+
+describe "Kernel#initialize_clone" do
+ it "is a private instance method" do
+ Kernel.should have_private_instance_method(:initialize_clone)
+ end
+
+ it "returns the receiver" do
+ a = Object.new
+ b = Object.new
+ a.send(:initialize_clone, b).should == a
+ end
+
+ it "calls #initialize_copy" do
+ a = Object.new
+ b = Object.new
+ a.should_receive(:initialize_copy).with(b)
+ a.send(:initialize_clone, b)
+ end
+
+ ruby_version_is "3.0" do
+ it "accepts a :freeze keyword argument for obj.clone(freeze: value)" do
+ a = Object.new
+ b = Object.new
+ a.send(:initialize_clone, b, freeze: true).should == a
+ end
+ end
+end
diff --git a/spec/ruby/core/kernel/initialize_dup_spec.rb b/spec/ruby/core/kernel/initialize_dup_spec.rb
new file mode 100644
index 0000000000..6dff34b7ad
--- /dev/null
+++ b/spec/ruby/core/kernel/initialize_dup_spec.rb
@@ -0,0 +1,20 @@
+require_relative '../../spec_helper'
+
+describe "Kernel#initialize_dup" do
+ it "is a private instance method" do
+ Kernel.should have_private_instance_method(:initialize_dup)
+ end
+
+ it "returns the receiver" do
+ a = Object.new
+ b = Object.new
+ a.send(:initialize_dup, b).should == a
+ end
+
+ it "calls #initialize_copy" do
+ a = Object.new
+ b = Object.new
+ a.should_receive(:initialize_copy).with(b)
+ a.send(:initialize_dup, b)
+ end
+end
diff --git a/spec/ruby/core/kernel/inspect_spec.rb b/spec/ruby/core/kernel/inspect_spec.rb
index e6fca8bf6f..1f9ce834ab 100644
--- a/spec/ruby/core/kernel/inspect_spec.rb
+++ b/spec/ruby/core/kernel/inspect_spec.rb
@@ -6,16 +6,6 @@ describe "Kernel#inspect" do
Object.new.inspect.should be_an_instance_of(String)
end
- ruby_version_is ''...'2.7' do
- it "returns a tainted string if self is tainted" do
- Object.new.taint.inspect.tainted?.should be_true
- end
-
- it "returns an untrusted string if self is untrusted" do
- Object.new.untrust.inspect.untrusted?.should be_true
- end
- end
-
it "does not call #to_s if it is defined" do
# We must use a bare Object here
obj = Object.new
diff --git a/spec/ruby/core/kernel/instance_variable_get_spec.rb b/spec/ruby/core/kernel/instance_variable_get_spec.rb
index bb6f03d3bf..f1d2a45df8 100644
--- a/spec/ruby/core/kernel/instance_variable_get_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_get_spec.rb
@@ -67,6 +67,12 @@ describe "Kernel#instance_variable_get when passed Symbol" do
it "raises a NameError when the passed Symbol is an invalid instance variable name" do
-> { @obj.instance_variable_get(:"@0") }.should raise_error(NameError)
end
+
+ it "returns nil or raises for frozen objects" do
+ nil.instance_variable_get(:@foo).should == nil
+ -> { nil.instance_variable_get(:foo) }.should raise_error(NameError)
+ :foo.instance_variable_get(:@foo).should == nil
+ end
end
describe "Kernel#instance_variable_get when passed String" do
diff --git a/spec/ruby/core/kernel/instance_variable_set_spec.rb b/spec/ruby/core/kernel/instance_variable_set_spec.rb
index 7fda30f72c..2c25f4366f 100644
--- a/spec/ruby/core/kernel/instance_variable_set_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_set_spec.rb
@@ -89,5 +89,17 @@ describe "Kernel#instance_variable_set" do
it "raises a FrozenError when passed replacement is different from stored object" do
-> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(FrozenError)
end
+
+ it "accepts unicode instance variable names" do
+ o = Object.new
+ o.instance_variable_set(:@💙, 42)
+ o.instance_variable_get(:@💙).should == 42
+ end
+
+ it "raises for frozen objects" do
+ -> { nil.instance_variable_set(:@foo, 42) }.should raise_error(FrozenError)
+ -> { nil.instance_variable_set(:foo, 42) }.should raise_error(NameError)
+ -> { :foo.instance_variable_set(:@foo, 42) }.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 831f0662a2..677d8bb7b2 100644
--- a/spec/ruby/core/kernel/instance_variables_spec.rb
+++ b/spec/ruby/core/kernel/instance_variables_spec.rb
@@ -25,5 +25,16 @@ describe "Kernel#instance_variables" do
a.instance_variable_set("@test", 1)
a.instance_variables.should == [:@test]
end
+
+ it "returns the instances variables in the order declared" do
+ c = Class.new do
+ def initialize
+ @c = 1
+ @a = 2
+ @b = 3
+ end
+ end
+ c.new.instance_variables.should == [:@c, :@a, :@b]
+ end
end
end
diff --git a/spec/ruby/core/kernel/lambda_spec.rb b/spec/ruby/core/kernel/lambda_spec.rb
index 9a960f3589..2aa4d4f2fb 100644
--- a/spec/ruby/core/kernel/lambda_spec.rb
+++ b/spec/ruby/core/kernel/lambda_spec.rb
@@ -135,4 +135,16 @@ describe "Kernel.lambda" do
klass.new.lambda { 42 }.should be_an_instance_of Proc
klass.new.ret.should == 1
end
+
+ ruby_version_is "3.0" do
+ context "when called without a literal block" do
+ it "warns when proc isn't a lambda" do
+ -> { lambda(&proc{}) }.should complain("#{__FILE__}:#{__LINE__}: warning: lambda without a literal block is deprecated; use the proc without lambda instead\n")
+ end
+
+ it "doesn't warn when proc is lambda" do
+ -> { lambda(&lambda{}) }.should_not complain(verbose: true)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb
index fbfc77f959..aa25006163 100644
--- a/spec/ruby/core/kernel/match_spec.rb
+++ b/spec/ruby/core/kernel/match_spec.rb
@@ -1,22 +1,30 @@
require_relative '../../spec_helper'
describe "Kernel#=~" do
- it "returns nil matching any object" do
- o = Object.new
+ ruby_version_is ''...'3.2' do
+ it "returns nil matching any object" do
+ o = Object.new
- suppress_warning do
- (o =~ /Object/).should be_nil
- (o =~ 'Object').should be_nil
- (o =~ Object).should be_nil
- (o =~ Object.new).should be_nil
- (o =~ nil).should be_nil
- (o =~ true).should be_nil
+ suppress_warning do
+ (o =~ /Object/).should be_nil
+ (o =~ 'Object').should be_nil
+ (o =~ Object).should be_nil
+ (o =~ Object.new).should be_nil
+ (o =~ nil).should be_nil
+ (o =~ true).should be_nil
+ end
+ end
+
+ it "is deprecated" do
+ -> do
+ Object.new =~ /regexp/
+ end.should complain(/deprecated Object#=~ is called on Object/, verbose: true)
end
end
- it "is deprecated" do
- -> do
- Object.new =~ /regexp/
- end.should complain(/deprecated Object#=~ is called on Object/, verbose: true)
+ ruby_version_is '3.2' do
+ it "is no longer defined" do
+ Object.new.should_not.respond_to?(:=~)
+ end
end
end
diff --git a/spec/ruby/core/kernel/method_spec.rb b/spec/ruby/core/kernel/method_spec.rb
index 25c6691e10..caf2ec948b 100644
--- a/spec/ruby/core/kernel/method_spec.rb
+++ b/spec/ruby/core/kernel/method_spec.rb
@@ -34,4 +34,28 @@ describe "Kernel#method" do
m.should be_an_instance_of(Method)
m.call(1, 2, 3).should == "Done handled_privately([1, 2, 3])"
end
+
+ it "can call a #method_missing accepting zero or one arguments" do
+ cls = Class.new do
+ def respond_to_missing?(name, *)
+ name == :foo or super
+ end
+ def method_missing
+ :no_args
+ end
+ end
+ m = cls.new.method(:foo)
+ -> { m.call }.should raise_error(ArgumentError)
+
+ cls = Class.new do
+ def respond_to_missing?(name, *)
+ name == :bar or super
+ end
+ def method_missing(m)
+ m
+ end
+ end
+ m = cls.new.method(:bar)
+ m.call.should == :bar
+ end
end
diff --git a/spec/ruby/core/kernel/nil_spec.rb b/spec/ruby/core/kernel/nil_spec.rb
index b63705f7bc..7418245f26 100644
--- a/spec/ruby/core/kernel/nil_spec.rb
+++ b/spec/ruby/core/kernel/nil_spec.rb
@@ -1,6 +1,12 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "Kernel#nil?" do
- it "needs to be reviewed for spec completeness"
+describe 'Kernel#nil?' do
+ it 'returns false' do
+ Object.should_not.nil?
+ Object.new.should_not.nil?
+ ''.should_not.nil?
+ [].should_not.nil?
+ {}.should_not.nil?
+ end
end
diff --git a/spec/ruby/core/kernel/open_spec.rb b/spec/ruby/core/kernel/open_spec.rb
index 8d936d8ca0..fa9299f9d4 100644
--- a/spec/ruby/core/kernel/open_spec.rb
+++ b/spec/ruby/core/kernel/open_spec.rb
@@ -27,7 +27,7 @@ describe "Kernel#open" do
open(@name, "r") { |f| f.gets }.should == @content
end
- platform_is_not :windows do
+ platform_is_not :windows, :wasi do
it "opens an io when path starts with a pipe" do
@io = open("|date")
begin
@@ -148,6 +148,18 @@ describe "Kernel#open" do
ruby_exe(code, args: "2>&1").should == "true\n"
end
end
+
+ ruby_version_is "3.0" do
+ it "is not redefined by open-uri" do
+ code = <<~RUBY
+ before = Kernel.instance_method(:open)
+ require 'open-uri'
+ after = Kernel.instance_method(:open)
+ p before == after
+ RUBY
+ ruby_exe(code, args: "2>&1").should == "true\n"
+ end
+ end
end
describe "Kernel.open" do
diff --git a/spec/ruby/core/kernel/p_spec.rb b/spec/ruby/core/kernel/p_spec.rb
index 1bdd1740ca..eae191aa54 100644
--- a/spec/ruby/core/kernel/p_spec.rb
+++ b/spec/ruby/core/kernel/p_spec.rb
@@ -76,10 +76,8 @@ describe "Kernel#p" do
-> { p(*[]) }.should output("")
end
-=begin Not sure how to spec this, but wanted to note the behavior here
- it "does not flush if receiver is not a TTY or a File" do
- end
-=end
+ # Not sure how to spec this, but wanted to note the behavior here
+ it "does not flush if receiver is not a TTY or a File"
end
describe "Kernel.p" do
diff --git a/spec/ruby/core/kernel/print_spec.rb b/spec/ruby/core/kernel/print_spec.rb
index c8c4453d1e..7e7c9b822d 100644
--- a/spec/ruby/core/kernel/print_spec.rb
+++ b/spec/ruby/core/kernel/print_spec.rb
@@ -5,6 +5,18 @@ describe "Kernel#print" do
it "is a private method" do
Kernel.should have_private_instance_method(:print)
end
+
+ it "delegates to $stdout" do
+ -> { print :arg }.should output("arg")
+ end
+
+ it "prints $_ when no arguments are given" do
+ orig_value = $_
+ $_ = 'foo'
+ -> { print }.should output("foo")
+ ensure
+ $_ = orig_value
+ end
end
describe "Kernel.print" do
diff --git a/spec/ruby/core/kernel/proc_spec.rb b/spec/ruby/core/kernel/proc_spec.rb
index dfe178420b..231c1f0dfb 100644
--- a/spec/ruby/core/kernel/proc_spec.rb
+++ b/spec/ruby/core/kernel/proc_spec.rb
@@ -40,15 +40,7 @@ describe "Kernel#proc" do
proc
end
- ruby_version_is ""..."2.7" do
- it "uses the implicit block from an enclosing method" do
- prc = some_method { "hello" }
-
- prc.call.should == "hello"
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "can be created when called with no block" do
-> {
some_method { "hello" }
diff --git a/spec/ruby/core/kernel/rand_spec.rb b/spec/ruby/core/kernel/rand_spec.rb
index c52faee2c4..355e425792 100644
--- a/spec/ruby/core/kernel/rand_spec.rb
+++ b/spec/ruby/core/kernel/rand_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "Kernel.rand" do
+describe "Kernel#rand" do
it "is a private method" do
Kernel.should have_private_instance_method(:rand)
end
@@ -192,6 +192,6 @@ describe "Kernel.rand" do
end
end
-describe "Kernel#rand" do
+describe "Kernel.rand" do
it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/core/kernel/remove_instance_variable_spec.rb b/spec/ruby/core/kernel/remove_instance_variable_spec.rb
index e90efc8aed..4e5ba5e018 100644
--- a/spec/ruby/core/kernel/remove_instance_variable_spec.rb
+++ b/spec/ruby/core/kernel/remove_instance_variable_spec.rb
@@ -41,6 +41,19 @@ describe "Kernel#remove_instance_variable" do
end.should raise_error(TypeError)
end
+ it "raises a FrozenError if self is frozen" do
+ o = Object.new
+ o.freeze
+ -> { o.remove_instance_variable(:@foo) }.should raise_error(FrozenError)
+ -> { o.remove_instance_variable(:foo) }.should raise_error(NameError)
+ end
+
+ it "raises for frozen objects" do
+ -> { nil.remove_instance_variable(:@foo) }.should raise_error(FrozenError)
+ -> { nil.remove_instance_variable(:foo) }.should raise_error(NameError)
+ -> { :foo.remove_instance_variable(:@foo) }.should raise_error(FrozenError)
+ end
+
describe "when passed a String" do
it_behaves_like :kernel_remove_instance_variable, nil, "@greeting"
end
diff --git a/spec/ruby/core/kernel/require_relative_spec.rb b/spec/ruby/core/kernel/require_relative_spec.rb
index d4146eb3c8..5999855de6 100644
--- a/spec/ruby/core/kernel/require_relative_spec.rb
+++ b/spec/ruby/core/kernel/require_relative_spec.rb
@@ -207,7 +207,7 @@ describe "Kernel#require_relative with a relative path" do
$LOADED_FEATURES.should include(@abs_path)
end
- platform_is_not :windows do
+ platform_is_not :windows, :wasi do
describe "with symlinks" do
before :each do
@symlink_to_code_dir = tmp("codesymlink")
diff --git a/spec/ruby/core/kernel/shared/dup_clone.rb b/spec/ruby/core/kernel/shared/dup_clone.rb
index 84ad49cbde..4fac6006e1 100644
--- a/spec/ruby/core/kernel/shared/dup_clone.rb
+++ b/spec/ruby/core/kernel/shared/dup_clone.rb
@@ -52,18 +52,6 @@ describe :kernel_dup_clone, shared: true do
o2.original.should equal(o)
end
- ruby_version_is ''...'2.7' do
- it "preserves tainted state from the original" do
- o = ObjectSpecDupInitCopy.new
- o2 = o.send(@method)
- o.taint
- o3 = o.send(@method)
-
- o2.should_not.tainted?
- o3.should.tainted?
- end
- end
-
it "does not preserve the object_id" do
o1 = ObjectSpecDupInitCopy.new
old_object_id = o1.object_id
@@ -71,18 +59,6 @@ describe :kernel_dup_clone, shared: true do
o2.object_id.should_not == old_object_id
end
- ruby_version_is ''...'2.7' do
- it "preserves untrusted state from the original" do
- o = ObjectSpecDupInitCopy.new
- o2 = o.send(@method)
- o.untrust
- o3 = o.send(@method)
-
- o2.should_not.untrusted?
- o3.should.untrusted?
- end
- end
-
it "returns nil for NilClass" do
nil.send(@method).should == nil
end
diff --git a/spec/ruby/core/kernel/shared/load.rb b/spec/ruby/core/kernel/shared/load.rb
index 120619abef..5c41c19bf6 100644
--- a/spec/ruby/core/kernel/shared/load.rb
+++ b/spec/ruby/core/kernel/shared/load.rb
@@ -88,12 +88,12 @@ describe :kernel_load, shared: true do
describe "when passed true for 'wrap'" do
it "loads from an existing path" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true).should be_true
end
it "sets the enclosing scope to an anonymous module" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
Object.const_defined?(:LoadSpecWrap).should be_false
@@ -103,14 +103,14 @@ describe :kernel_load, shared: true do
end
it "allows referencing outside namespaces" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
ScratchPad.recorded[0].should equal(String)
end
it "sets self as a copy of the top-level main" do
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
top_level = ScratchPad.recorded[2]
@@ -127,7 +127,7 @@ describe :kernel_load, shared: true do
main_ancestors = main.singleton_class.ancestors[1..-1]
main_ancestors.first.should == mod
- path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true)
top_level = ScratchPad.recorded[2]
@@ -154,6 +154,41 @@ describe :kernel_load, shared: true do
end
end
+ describe "when passed a module for 'wrap'" do
+ ruby_version_is "3.1" do
+ it "sets the enclosing scope to the supplied module" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ Object.const_defined?(:LoadSpecWrap).should be_false
+ mod.const_defined?(:LoadSpecWrap).should be_true
+
+ wrap_module = ScratchPad.recorded[1]
+ wrap_module.should == mod
+ end
+
+ it "makes constants and instance methods in the source file reachable with the supplied module" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ mod::LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT.should == 1
+ obj = Object.new
+ obj.extend(mod)
+ obj.send(:load_wrap_specs_top_level_method).should == :load_wrap_specs_top_level_method
+ end
+
+ it "makes instance methods in the source file private" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ mod.private_instance_methods.include?(:load_wrap_specs_top_level_method).should == true
+ end
+ end
+ end
+
describe "(shell expansion)" do
before :each do
@env_home = ENV["HOME"]
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index 9a2c38be1a..ae814aa317 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -237,6 +237,17 @@ describe :kernel_require, shared: true do
}.should complain(/circular require considered harmful/, verbose: true)
ScratchPad.recorded.should == [:loaded]
end
+
+ ruby_bug "#17340", ''...'3.3' do
+ it "loads a file concurrently" do
+ path = File.expand_path "concurrent_require_fixture.rb", CODE_LOADING_DIR
+ ScratchPad.record(@object)
+ -> {
+ @object.require(path)
+ }.should_not complain(/circular require considered harmful/, verbose: true)
+ ScratchPad.recorded.join
+ end
+ end
end
describe "(non-extensioned path)" do
@@ -251,7 +262,7 @@ describe :kernel_require, shared: true do
ScratchPad.recorded.should == [:loaded]
end
- ruby_bug "#16926", "2.7"..."3.0" do
+ ruby_bug "#16926", ""..."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
@@ -547,9 +558,7 @@ describe :kernel_require, shared: true do
end
provided = %w[complex enumerator rational thread]
- ruby_version_is "2.7" do
- provided << 'ruby2_keywords'
- end
+ provided << 'ruby2_keywords'
it "#{provided.join(', ')} are already required" do
features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
@@ -570,6 +579,25 @@ describe :kernel_require, shared: true do
-> { @object.require("unicode_normalize") }.should raise_error(LoadError)
end
+
+ ruby_version_is "3.0" do
+ it "does not load a file earlier on the $LOAD_PATH when other similar features were already loaded" do
+ Dir.chdir CODE_LOADING_DIR do
+ @object.send(@method, "../code/load_fixture").should be_true
+ end
+ ScratchPad.recorded.should == [:loaded]
+
+ $LOAD_PATH.unshift "#{CODE_LOADING_DIR}/b"
+ # This loads because the above load was not on the $LOAD_PATH
+ @object.send(@method, "load_fixture").should be_true
+ ScratchPad.recorded.should == [:loaded, :loaded]
+
+ $LOAD_PATH.unshift "#{CODE_LOADING_DIR}/c"
+ # This does not load because the above load was on the $LOAD_PATH
+ @object.send(@method, "load_fixture").should be_false
+ ScratchPad.recorded.should == [:loaded, :loaded]
+ end
+ end
end
describe "(shell expansion)" do
diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb
index 6d62a65f7c..2db50bd686 100644
--- a/spec/ruby/core/kernel/shared/sprintf.rb
+++ b/spec/ruby/core/kernel/shared/sprintf.rb
@@ -289,21 +289,80 @@ describe :kernel_sprintf, shared: true do
@method.call("%c", "a").should == "a"
end
- it "raises ArgumentError if argument is a string of several characters" do
+ ruby_version_is ""..."3.2" do
+ it "raises ArgumentError if argument is a string of several characters" do
+ -> {
+ @method.call("%c", "abc")
+ }.should raise_error(ArgumentError, /%c requires a character/)
+ end
+
+ it "raises ArgumentError if argument is an empty string" do
+ -> {
+ @method.call("%c", "")
+ }.should raise_error(ArgumentError, /%c requires a character/)
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "displays only the first character if argument is a string of several characters" do
+ @method.call("%c", "abc").should == "a"
+ end
+
+ it "displays no characters if argument is an empty string" do
+ @method.call("%c", "").should == ""
+ end
+ end
+
+ it "raises TypeError if argument is not String or Integer and cannot be converted to them" do
-> {
- @method.call("%c", "abc")
- }.should raise_error(ArgumentError)
+ @method.call("%c", [])
+ }.should raise_error(TypeError, /no implicit conversion of Array into Integer/)
end
- it "raises ArgumentError if argument is an empty string" do
+ it "raises TypeError if argument is nil" do
-> {
- @method.call("%c", "")
- }.should raise_error(ArgumentError)
+ @method.call("%c", nil)
+ }.should raise_error(TypeError, /no implicit conversion from nil to integer/)
end
- it "supports Unicode characters" do
- @method.call("%c", 1286).should == "Ԇ"
- @method.call("%c", "ش").should == "ش"
+ it "tries to convert argument to String with to_str" do
+ obj = BasicObject.new
+ def obj.to_str
+ "a"
+ end
+
+ @method.call("%c", obj).should == "a"
+ end
+
+ it "tries to convert argument to Integer with to_int" do
+ obj = BasicObject.new
+ def obj.to_int
+ 90
+ end
+
+ @method.call("%c", obj).should == "Z"
+ end
+
+ it "raises TypeError if converting to String with to_str returns non-String" do
+ obj = BasicObject.new
+ def obj.to_str
+ :foo
+ end
+
+ -> {
+ @method.call("%c", obj)
+ }.should raise_error(TypeError, /can't convert BasicObject to String/)
+ end
+
+ it "raises TypeError if converting to Integer with to_int returns non-Integer" do
+ obj = BasicObject.new
+ def obj.to_str
+ :foo
+ end
+
+ -> {
+ @method.call("%c", obj)
+ }.should raise_error(TypeError, /can't convert BasicObject to String/)
end
end
@@ -320,6 +379,10 @@ describe :kernel_sprintf, shared: true do
@method.call("%s", "abc").should == "abc"
end
+ it "substitutes '' for nil" do
+ @method.call("%s", nil).should == ""
+ end
+
it "converts argument to string with to_s" do
obj = mock("string")
obj.should_receive(:to_s).and_return("abc")
@@ -348,6 +411,28 @@ describe :kernel_sprintf, shared: true do
Kernel.format("%-3.3s", "hello").should == "hel"
end
+ it "formats string with width" do
+ @method.call("%6s", "abc").should == " abc"
+ @method.call("%6s", "abcdefg").should == "abcdefg"
+ end
+
+ it "formats string with width and precision" do
+ @method.call("%4.6s", "abc").should == " abc"
+ @method.call("%4.6s", "abcdefg").should == "abcdef"
+ end
+
+ it "formats nil with width" do
+ @method.call("%6s", nil).should == " "
+ end
+
+ it "formats nil with precision" do
+ @method.call("%.6s", nil).should == ""
+ end
+
+ it "formats nil with width and precision" do
+ @method.call("%4.6s", nil).should == " "
+ end
+
it "formats multibyte string with precision" do
Kernel.format("%.2s", "été").should == "ét"
end
@@ -901,4 +986,8 @@ describe :kernel_sprintf, shared: true do
}
end
end
+
+ it "does not raise error when passed more arguments than needed" do
+ sprintf("%s %d %c", "string", 2, "c", []).should == "string 2 c"
+ end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf_encoding.rb b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
index 5ca66b9083..9cedb8b662 100644
--- a/spec/ruby/core/kernel/shared/sprintf_encoding.rb
+++ b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
@@ -1,3 +1,5 @@
+# Keep encoding-related specs in a separate shared example to be able to skip them in IO/File/StringIO specs.
+# It's difficult to check result's encoding in the test after writing to a file/io buffer.
describe :kernel_sprintf_encoding, shared: true do
it "can produce a string with valid encoding" do
string = @method.call("good day %{valid}", valid: "e")
@@ -25,7 +27,7 @@ describe :kernel_sprintf_encoding, shared: true do
result.encoding.should equal(Encoding::UTF_8)
end
- it "raises Encoding::CompatibilityError if both encodings are ASCII compatible and there ano not ASCII characters" do
+ it "raises Encoding::CompatibilityError if both encodings are ASCII compatible and there are not ASCII characters" do
string = "Ä %s".encode('windows-1252')
argument = "Ђ".encode('windows-1251')
@@ -33,4 +35,33 @@ describe :kernel_sprintf_encoding, shared: true do
@method.call(string, argument)
}.should raise_error(Encoding::CompatibilityError)
end
+
+ describe "%c" do
+ it "supports Unicode characters" do
+ result = @method.call("%c", 1286)
+ result.should == "Ԇ"
+ result.bytes.should == [212, 134]
+
+ result = @method.call("%c", "ش")
+ result.should == "ش"
+ result.bytes.should == [216, 180]
+ end
+
+ it "raises error when a codepoint isn't representable in an encoding of a format string" do
+ format = "%c".encode("ASCII")
+
+ -> {
+ @method.call(format, 1286)
+ }.should raise_error(RangeError, /out of char range/)
+ end
+
+ it "uses the encoding of the format string to interpret codepoints" do
+ format = "%c".force_encoding("euc-jp")
+ result = @method.call(format, 9415601)
+
+ result.encoding.should == Encoding::EUC_JP
+ result.should == "é".encode(Encoding::EUC_JP)
+ result.bytes.should == [143, 171, 177]
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/singleton_class_spec.rb b/spec/ruby/core/kernel/singleton_class_spec.rb
index a8bcd916d1..c56fa08cc1 100644
--- a/spec/ruby/core/kernel/singleton_class_spec.rb
+++ b/spec/ruby/core/kernel/singleton_class_spec.rb
@@ -1,3 +1,5 @@
+require_relative '../../spec_helper'
+
describe "Kernel#singleton_class" do
it "returns class extended from an object" do
x = Object.new
diff --git a/spec/ruby/core/kernel/srand_spec.rb b/spec/ruby/core/kernel/srand_spec.rb
index 6774d19284..95bb406f46 100644
--- a/spec/ruby/core/kernel/srand_spec.rb
+++ b/spec/ruby/core/kernel/srand_spec.rb
@@ -1,7 +1,15 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "Kernel.srand" do
+describe "Kernel#srand" do
+ before :each do
+ @seed = srand
+ end
+
+ after :each do
+ srand(@seed)
+ end
+
it "is a private method" do
Kernel.should have_private_instance_method(:srand)
end
@@ -11,8 +19,8 @@ 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/
+ it "returns the system-initialized seed value on the first call" do
+ ruby_exe('print srand(10)', options: '--disable-gems').should =~ /\A\d+\z/
end
it "seeds the RNG correctly and repeatably" do
@@ -60,6 +68,6 @@ describe "Kernel.srand" do
end
end
-describe "Kernel#srand" do
+describe "Kernel.srand" do
it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/core/kernel/taint_spec.rb b/spec/ruby/core/kernel/taint_spec.rb
index 8ba9869af2..9a58bb5f04 100644
--- a/spec/ruby/core/kernel/taint_spec.rb
+++ b/spec/ruby/core/kernel/taint_spec.rb
@@ -2,50 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#taint" do
- ruby_version_is ''...'2.7' do
- it "returns self" do
- o = Object.new
- o.taint.should equal(o)
- end
-
- it "sets the tainted bit" do
- o = Object.new
- o.taint
- o.should.tainted?
- end
-
- it "raises FrozenError on an untainted, frozen object" do
- o = Object.new.freeze
- -> { o.taint }.should raise_error(FrozenError)
- end
-
- it "does not raise an error on a tainted, frozen object" do
- o = Object.new.taint.freeze
- o.taint.should equal(o)
- end
-
- it "has no effect on immediate values" do
- [nil, true, false].each do |v|
- v.taint
- v.should_not.tainted?
- end
- end
-
- it "no raises a RuntimeError on symbols" do
- v = :sym
- -> { v.taint }.should_not raise_error(RuntimeError)
- v.should_not.tainted?
- end
-
- it "no raises error on integer values" do
- [1].each do |v|
- -> { v.taint }.should_not raise_error(RuntimeError)
- v.should_not.tainted?
- end
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "is a no-op" do
o = Object.new
o.taint
diff --git a/spec/ruby/core/kernel/tainted_spec.rb b/spec/ruby/core/kernel/tainted_spec.rb
index 022938bfc1..7511c730c9 100644
--- a/spec/ruby/core/kernel/tainted_spec.rb
+++ b/spec/ruby/core/kernel/tainted_spec.rb
@@ -2,17 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#tainted?" do
- ruby_version_is ''...'2.7' do
- it "returns true if Object is tainted" do
- o = mock('o')
- p = mock('p')
- p.taint
- o.should_not.tainted?
- p.should.tainted?
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "is a no-op" do
o = mock('o')
p = mock('p')
diff --git a/spec/ruby/core/kernel/to_s_spec.rb b/spec/ruby/core/kernel/to_s_spec.rb
index 64b40f46e5..ea4b00151e 100644
--- a/spec/ruby/core/kernel/to_s_spec.rb
+++ b/spec/ruby/core/kernel/to_s_spec.rb
@@ -5,14 +5,4 @@ describe "Kernel#to_s" do
it "returns a String containing the name of self's class" do
Object.new.to_s.should =~ /Object/
end
-
- ruby_version_is ''...'2.7' do
- it "returns a tainted result if self is tainted" do
- Object.new.taint.to_s.tainted?.should be_true
- end
-
- it "returns an untrusted result if self is untrusted" do
- Object.new.untrust.to_s.untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/kernel/trust_spec.rb b/spec/ruby/core/kernel/trust_spec.rb
index 399983f74d..4665036da6 100644
--- a/spec/ruby/core/kernel/trust_spec.rb
+++ b/spec/ruby/core/kernel/trust_spec.rb
@@ -2,30 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#trust" do
- ruby_version_is ''...'2.7' do
- it "returns self" do
- o = Object.new
- o.trust.should equal(o)
- end
-
- it "clears the untrusted bit" do
- o = Object.new.untrust
- o.trust
- o.should_not.untrusted?
- end
-
- it "raises FrozenError on an untrusted, frozen object" do
- o = Object.new.untrust.freeze
- -> { o.trust }.should raise_error(FrozenError)
- end
-
- it "does not raise an error on a trusted, frozen object" do
- o = Object.new.freeze
- o.trust.should equal(o)
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "is a no-op" do
o = Object.new.untrust
o.should_not.untrusted?
diff --git a/spec/ruby/core/kernel/untaint_spec.rb b/spec/ruby/core/kernel/untaint_spec.rb
index 44d87da5d5..42fe8a4239 100644
--- a/spec/ruby/core/kernel/untaint_spec.rb
+++ b/spec/ruby/core/kernel/untaint_spec.rb
@@ -2,30 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untaint" do
- ruby_version_is ''...'2.7' do
- it "returns self" do
- o = Object.new
- o.untaint.should equal(o)
- end
-
- it "clears the tainted bit" do
- o = Object.new.taint
- o.untaint
- o.should_not.tainted?
- end
-
- it "raises FrozenError on a tainted, frozen object" do
- o = Object.new.taint.freeze
- -> { o.untaint }.should raise_error(FrozenError)
- end
-
- it "does not raise an error on an untainted, frozen object" do
- o = Object.new.freeze
- o.untaint.should equal(o)
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "is a no-op" do
o = Object.new.taint
o.should_not.tainted?
diff --git a/spec/ruby/core/kernel/untrust_spec.rb b/spec/ruby/core/kernel/untrust_spec.rb
index aff0fec57b..ba0e073cf0 100644
--- a/spec/ruby/core/kernel/untrust_spec.rb
+++ b/spec/ruby/core/kernel/untrust_spec.rb
@@ -2,30 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untrust" do
- ruby_version_is ''...'2.7' do
- it "returns self" do
- o = Object.new
- o.untrust.should equal(o)
- end
-
- it "sets the untrusted bit" do
- o = Object.new
- o.untrust
- o.should.untrusted?
- end
-
- it "raises FrozenError on a trusted, frozen object" do
- o = Object.new.freeze
- -> { o.untrust }.should raise_error(FrozenError)
- end
-
- it "does not raise an error on an untrusted, frozen object" do
- o = Object.new.untrust.freeze
- o.untrust.should equal(o)
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "is a no-op" do
o = Object.new
o.untrust
diff --git a/spec/ruby/core/kernel/untrusted_spec.rb b/spec/ruby/core/kernel/untrusted_spec.rb
index 5347c90093..517bd4711b 100644
--- a/spec/ruby/core/kernel/untrusted_spec.rb
+++ b/spec/ruby/core/kernel/untrusted_spec.rb
@@ -2,33 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untrusted?" do
- ruby_version_is ''...'2.7' do
- it "returns the untrusted status of an object" do
- o = mock('o')
- o.should_not.untrusted?
- o.untrust
- o.should.untrusted?
- end
-
- it "has no effect on immediate values" do
- a = nil
- b = true
- c = false
- a.untrust
- b.untrust
- c.untrust
- a.should_not.untrusted?
- b.should_not.untrusted?
- c.should_not.untrusted?
- end
-
- it "has effect on immediate values" do
- d = 1
- -> { d.untrust }.should_not raise_error(RuntimeError)
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "is a no-op" do
o = mock('o')
o.should_not.untrusted?
diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb
index 511e741f32..7df6fa72d1 100644
--- a/spec/ruby/core/kernel/warn_spec.rb
+++ b/spec/ruby/core/kernel/warn_spec.rb
@@ -212,6 +212,70 @@ describe "Kernel#warn" do
-> { warn('foo', **h) }.should complain("foo\n")
end
+ ruby_version_is '3.0' do
+ it "calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" do
+ verbose = $VERBOSE
+ $VERBOSE = false
+ class << Warning
+ alias_method :_warn, :warn
+ def warn(message)
+ ScratchPad.record(message)
+ end
+ end
+
+ begin
+ ScratchPad.clear
+ Kernel.warn("Chunky bacon!")
+ ScratchPad.recorded.should == "Chunky bacon!\n"
+
+ Kernel.warn("Deprecated bacon!", category: :deprecated)
+ ScratchPad.recorded.should == "Deprecated bacon!\n"
+ ensure
+ class << Warning
+ remove_method :warn
+ alias_method :warn, :_warn
+ remove_method :_warn
+ end
+ $VERBOSE = verbose
+ end
+ end
+
+ it "calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!")
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+
+ it "calls Warning.warn with given category keyword converted to a symbol" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!", category: 'deprecated')
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "calls Warning.warn with no keyword arguments" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n")
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!")
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+ end
+
it "does not call Warning.warn if self is the Warning module" do
# RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
code = <<-RUBY
diff --git a/spec/ruby/core/main/fixtures/using.rb b/spec/ruby/core/main/fixtures/using.rb
new file mode 100644
index 0000000000..30713ef309
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/using.rb
@@ -0,0 +1 @@
+using Module.new
diff --git a/spec/ruby/core/main/fixtures/using_in_main.rb b/spec/ruby/core/main/fixtures/using_in_main.rb
new file mode 100644
index 0000000000..a4a71c89cc
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/using_in_main.rb
@@ -0,0 +1,5 @@
+MAIN = self
+
+module X
+ MAIN.send(:using, Module.new)
+end
diff --git a/spec/ruby/core/main/fixtures/using_in_method.rb b/spec/ruby/core/main/fixtures/using_in_method.rb
new file mode 100644
index 0000000000..d9ea2e9ef0
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/using_in_method.rb
@@ -0,0 +1,5 @@
+def foo
+ using Module.new
+end
+
+foo
diff --git a/spec/ruby/core/main/private_spec.rb b/spec/ruby/core/main/private_spec.rb
index 78c5d287d4..cac0645b40 100644
--- a/spec/ruby/core/main/private_spec.rb
+++ b/spec/ruby/core/main/private_spec.rb
@@ -32,8 +32,16 @@ describe "main#private" do
end
end
- it "returns Object" do
- eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object)
+ ruby_version_is ''...'3.1' do
+ it "returns Object" do
+ eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object)
+ end
+ end
+
+ ruby_version_is '3.1' do
+ it "returns argument" do
+ eval("private :main_public_method", TOPLEVEL_BINDING).should equal(:main_public_method)
+ end
end
it "raises a NameError when at least one of given method names is undefined" do
diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb
index bfc27a9e80..91f045dbab 100644
--- a/spec/ruby/core/main/public_spec.rb
+++ b/spec/ruby/core/main/public_spec.rb
@@ -32,10 +32,19 @@ describe "main#public" do
end
end
- it "returns Object" do
- eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object)
+ ruby_version_is ''...'3.1' do
+ it "returns Object" do
+ eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object)
+ end
end
+ ruby_version_is '3.1' do
+ it "returns argument" do
+ eval("public :main_private_method", TOPLEVEL_BINDING).should equal(:main_private_method)
+ end
+ end
+
+
it "raises a NameError when given an undefined name" do
-> do
eval "public :main_undefined_method", TOPLEVEL_BINDING
diff --git a/spec/ruby/core/main/ruby2_keywords_spec.rb b/spec/ruby/core/main/ruby2_keywords_spec.rb
index 0999cddeed..27ceae3253 100644
--- a/spec/ruby/core/main/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/main/ruby2_keywords_spec.rb
@@ -1,11 +1,9 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "2.7" do
- describe "main.ruby2_keywords" do
- it "is the same as Object.ruby2_keywords" do
- main = TOPLEVEL_BINDING.receiver
- main.should have_private_method(:ruby2_keywords)
- end
+describe "main.ruby2_keywords" do
+ it "is the same as Object.ruby2_keywords" do
+ main = TOPLEVEL_BINDING.receiver
+ main.should have_private_method(:ruby2_keywords)
end
end
diff --git a/spec/ruby/core/main/using_spec.rb b/spec/ruby/core/main/using_spec.rb
index f9f709f7dc..8a23970c4b 100644
--- a/spec/ruby/core/main/using_spec.rb
+++ b/spec/ruby/core/main/using_spec.rb
@@ -129,4 +129,24 @@ describe "main.using" do
x.call_bar(cls2.new).should == 'bar'
end
+
+ it "raises error when called from method in wrapped script" do
+ -> do
+ load File.expand_path('../fixtures/using_in_method.rb', __FILE__), true
+ end.should raise_error(RuntimeError)
+ end
+
+ it "raises error when called on toplevel from module" do
+ -> do
+ load File.expand_path('../fixtures/using_in_main.rb', __FILE__), true
+ end.should raise_error(RuntimeError)
+ end
+
+ ruby_version_is "3.2" do
+ it "does not raise error when wrapped with module" do
+ -> do
+ load File.expand_path('../fixtures/using.rb', __FILE__), true
+ end.should_not raise_error
+ end
+ end
end
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index a54a4c6735..879ea287ce 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -1,5 +1,6 @@
# -*- encoding: binary -*-
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
require_relative 'fixtures/marshal_data'
describe "Marshal.dump" do
@@ -106,7 +107,7 @@ describe "Marshal.dump" do
end
describe "with an object responding to #_dump" do
- it "dumps the object returned by #marshal_dump" do
+ it "dumps the object returned by #_dump" do
Marshal.dump(UserDefined.new).should == "\004\bu:\020UserDefined\022\004\b[\a:\nstuff;\000"
end
@@ -122,6 +123,34 @@ describe "Marshal.dump" do
m.should_not_receive(:_dump)
Marshal.dump(m)
end
+
+ it "indexes instance variables of a String returned by #_dump at first and then indexes the object itself" do
+ class MarshalSpec::M1::A
+ def _dump(level)
+ s = "<dump>"
+ s.instance_variable_set(:@foo, "bar")
+ s
+ end
+ end
+
+ a = MarshalSpec::M1::A.new
+
+ # 0-based index of the object a = 2, that is encoded as \x07 and printed as "\a" character.
+ # Objects are serialized in the following order: Array, a, "bar".
+ # But they are indexed in different order: Array (index=0), "bar" (index=1), a (index=2)
+ # So the second occurenc of the object a is encoded as an index 2.
+ reference = "@\a"
+ Marshal.dump([a, a]).should == "\x04\b[\aIu:\x17MarshalSpec::M1::A\v<dump>\x06:\t@foo\"\bbar#{reference}"
+ end
+
+ describe "Core library classes with #_dump returning a String with instance variables" do
+ it "indexes instance variables and then a Time object itself" do
+ t = Time.utc(2022)
+ reference = "@\a"
+
+ Marshal.dump([t, t]).should == "\x04\b[\aIu:\tTime\r \x80\x1E\xC0\x00\x00\x00\x00\x06:\tzoneI\"\bUTC\x06:\x06EF#{reference}"
+ end
+ end
end
describe "with a Class" do
@@ -185,6 +214,20 @@ describe "Marshal.dump" do
[Marshal, -2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"],
].should be_computed_by(:dump)
end
+
+ it "increases the object links counter" do
+ obj = Object.new
+ object_1_link = "\x06" # representing of (0-based) index=1 (by adding 5 for small Integers)
+ object_2_link = "\x07" # representing of index=2
+
+ # objects: Array, Object, Object
+ Marshal.dump([obj, obj]).should == "\x04\b[\ao:\vObject\x00@#{object_1_link}"
+
+ # objects: Array, Bignum, Object, Object
+ Marshal.dump([2**64, obj, obj]).should == "\x04\b[\bl+\n\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
+ Marshal.dump([2**48, obj, obj]).should == "\x04\b[\bl+\t\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
+ Marshal.dump([2**32, obj, obj]).should == "\x04\b[\bl+\b\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
+ end
end
describe "with a String" do
@@ -604,30 +647,4 @@ describe "Marshal.dump" do
m = Mutex.new
-> { Marshal.dump(m) }.should raise_error(TypeError)
end
-
- ruby_version_is ''...'2.7' do
- it "returns an untainted string if object is untainted" do
- Marshal.dump(Object.new).tainted?.should be_false
- end
-
- it "returns a tainted string if object is tainted" do
- Marshal.dump(Object.new.taint).tainted?.should be_true
- end
-
- it "returns a tainted string if nested object is tainted" do
- Marshal.dump([[Object.new.taint]]).tainted?.should be_true
- end
-
- it "returns a trusted string if object is trusted" do
- Marshal.dump(Object.new).untrusted?.should be_false
- end
-
- it "returns an untrusted string if object is untrusted" do
- Marshal.dump(Object.new.untrust).untrusted?.should be_true
- end
-
- it "returns an untrusted string if nested object is untrusted" do
- Marshal.dump([[Object.new.untrust]]).untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/marshal/fixtures/classes.rb b/spec/ruby/core/marshal/fixtures/classes.rb
new file mode 100644
index 0000000000..7c81c64927
--- /dev/null
+++ b/spec/ruby/core/marshal/fixtures/classes.rb
@@ -0,0 +1,4 @@
+module MarshalSpec
+ # empty modules
+ module M1 end
+end
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index a79fb51cd7..479c7477ec 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -19,43 +19,157 @@ describe :marshal_load, shared: true do
-> { Marshal.send(@method, kaboom) }.should raise_error(ArgumentError)
end
- describe "when called with a proc" do
- it "returns the value of the proc" do
- Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4]
- end
+ ruby_version_is "3.1" do
+ describe "when called with freeze: true" do
+ it "returns frozen strings" do
+ string = Marshal.send(@method, Marshal.dump("foo"), freeze: true)
+ string.should == "foo"
+ string.should.frozen?
+
+ utf8_string = "foo".encode(Encoding::UTF_8)
+ string = Marshal.send(@method, Marshal.dump(utf8_string), freeze: true)
+ string.should == utf8_string
+ string.should.frozen?
+ end
- it "calls the proc for recursively visited data" do
- a = [1]
- a << a
- ret = []
- Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg; arg })
- ret.first.should == 1
- ret[1].should == [1,a]
- ret[2].should == a
- ret.size.should == 3
+ it "returns frozen arrays" do
+ array = Marshal.send(@method, Marshal.dump([1, 2, 3]), freeze: true)
+ array.should == [1, 2, 3]
+ array.should.frozen?
+ end
+
+ it "returns frozen hashes" do
+ hash = Marshal.send(@method, Marshal.dump({foo: 42}), freeze: true)
+ hash.should == {foo: 42}
+ hash.should.frozen?
+ end
+
+ it "returns frozen regexps" do
+ regexp = Marshal.send(@method, Marshal.dump(/foo/), freeze: true)
+ regexp.should == /foo/
+ regexp.should.frozen?
+ end
+
+ it "returns frozen objects" do
+ source_object = Object.new
+ source_object.instance_variable_set(:@foo, "bar")
+
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ object.should.frozen?
+ object.instance_variable_get(:@foo).should.frozen?
+ end
+
+ it "does not freeze modules" do
+ Marshal.send(@method, Marshal.dump(Kernel), freeze: true)
+ Kernel.should_not.frozen?
+ end
+
+ it "does not freeze classes" do
+ Marshal.send(@method, Marshal.dump(Object), freeze: true)
+ Object.should_not.frozen?
+ end
+
+ describe "when called with a proc" do
+ it "call the proc with frozen objects" do
+ arr = []
+ s = 'hi'
+ s.instance_variable_set(:@foo, 5)
+ st = Struct.new("Brittle", :a).new
+ st.instance_variable_set(:@clue, 'none')
+ st.a = 0.0
+ h = Hash.new('def')
+ h['nine'] = 9
+ a = [:a, :b, :c]
+ a.instance_variable_set(:@two, 2)
+ obj = [s, 10, s, s, st, a]
+ obj.instance_variable_set(:@zoo, 'ant')
+ proc = Proc.new { |o| arr << o; o}
+
+ Marshal.send(
+ @method,
+ "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F",
+ proc,
+ freeze: true,
+ )
+
+ arr.should == [
+ false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st,
+ :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]],
+ ]
+
+ arr.each do |v|
+ v.should.frozen?
+ end
+
+ Struct.send(:remove_const, :Brittle)
+ end
+
+ it "does not freeze the object returned by the proc" do
+ string = Marshal.send(@method, Marshal.dump("foo"), proc { |o| o.upcase }, freeze: true)
+ string.should == "FOO"
+ string.should_not.frozen?
+ end
+ end
end
+ end
- it "loads an Array with proc" do
- arr = []
- s = 'hi'
- s.instance_variable_set(:@foo, 5)
- st = Struct.new("Brittle", :a).new
- st.instance_variable_set(:@clue, 'none')
- st.a = 0.0
- h = Hash.new('def')
- h['nine'] = 9
- a = [:a, :b, :c]
- a.instance_variable_set(:@two, 2)
- obj = [s, 10, s, s, st, a]
- obj.instance_variable_set(:@zoo, 'ant')
- proc = Proc.new { |o| arr << o; o}
+ describe "when called with a proc" do
+ ruby_bug "#18141", ""..."3.1" do
+ it "call the proc with fully initialized strings" do
+ utf8_string = "foo".encode(Encoding::UTF_8)
+ Marshal.send(@method, Marshal.dump(utf8_string), proc { |arg|
+ if arg.is_a?(String)
+ arg.should == utf8_string
+ arg.encoding.should == Encoding::UTF_8
+ end
+ arg
+ })
+ end
- Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc)
+ it "no longer mutate the object after it was passed to the proc" do
+ string = Marshal.load(Marshal.dump("foo"), :freeze.to_proc)
+ string.should.frozen?
+ end
+ end
- arr.should == ["hi", false, 5, 10, "hi", "hi", 0.0, st, "none", false,
- :b, :c, a, 2, ["hi", 10, "hi", "hi", st, [:a, :b, :c]], "ant", false]
+ it "returns the value of the proc" do
+ Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4]
+ end
- Struct.send(:remove_const, :Brittle)
+ 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'
+ s.instance_variable_set(:@foo, 5)
+ st = Struct.new("Brittle", :a).new
+ st.instance_variable_set(:@clue, 'none')
+ st.a = 0.0
+ h = Hash.new('def')
+ h['nine'] = 9
+ a = [:a, :b, :c]
+ a.instance_variable_set(:@two, 2)
+ obj = [s, 10, s, s, st, a]
+ obj.instance_variable_set(:@zoo, 'ant')
+ proc = Proc.new { |o| arr << o.dup; o}
+
+ Marshal.send(@method, "\x04\bI[\vI\"\ahi\a:\x06EF:\t@fooi\ni\x0F@\x06@\x06IS:\x14Struct::Brittle\x06:\x06af\x060\x06:\n@clueI\"\tnone\x06;\x00FI[\b;\b:\x06b:\x06c\x06:\t@twoi\a\x06:\t@zooI\"\bant\x06;\x00F", proc)
+
+ arr.should == [
+ false, 5, "hi", 10, "hi", "hi", 0.0, false, "none", st,
+ :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]],
+ ]
+ Struct.send(:remove_const, :Brittle)
+ end
end
end
@@ -119,28 +233,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[0].should == 'stuff'
+ arr[1].should == o1
+ arr[2].should == 'my data'
+ arr[3].should == ['my data']
+ arr[4].should == o2
+ arr[5].should == [o1, o2, o1, o2]
- arr.should == ['stuff', o1, 'my data', ['my data'], o2, o1, o2, obj]
+ arr.size.should == 6
+ end
end
it "assigns classes to nested subclasses of Array correctly" do
@@ -181,89 +306,6 @@ describe :marshal_load, shared: true do
end
end
- ruby_version_is ''...'2.7' do
- it "returns an untainted object if source is untainted" do
- x = Object.new
- y = Marshal.send(@method, Marshal.dump(x))
- y.tainted?.should be_false
- end
-
- describe "when source is tainted" do
- it "returns a tainted object" do
- x = Object.new
- x.taint
- s = Marshal.dump(x)
- y = Marshal.send(@method, s)
- y.tainted?.should be_true
-
- # note that round-trip via Marshal does not preserve
- # the taintedness at each level of the nested structure
- y = Marshal.send(@method, Marshal.dump([[x]]))
- y.tainted?.should be_true
- y.first.tainted?.should be_true
- y.first.first.tainted?.should be_true
- end
-
- it "does not taint Symbols" do
- x = [:x]
- y = Marshal.send(@method, Marshal.dump(x).taint)
- y.tainted?.should be_true
- y.first.tainted?.should be_false
- end
-
- it "does not taint Fixnums" 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
- x = [bignum_value]
- y = Marshal.send(@method, Marshal.dump(x).taint)
- y.tainted?.should be_true
- y.first.tainted?.should be_false
- end
-
- it "does not taint Floats" do
- x = [1.2]
- y = Marshal.send(@method, Marshal.dump(x).taint)
- y.tainted?.should be_true
- y.first.tainted?.should be_false
- end
- end
-
- it "preserves taintedness of nested structure" do
- x = Object.new
- a = [[x]]
- x.taint
- y = Marshal.send(@method, Marshal.dump(a))
- y.tainted?.should be_true
- y.first.tainted?.should be_true
- y.first.first.tainted?.should be_true
- end
-
- it "returns a trusted object if source is trusted" do
- x = Object.new
- y = Marshal.send(@method, Marshal.dump(x))
- y.untrusted?.should be_false
- end
-
- it "returns an untrusted object if source is untrusted" do
- x = Object.new
- x.untrust
- y = Marshal.send(@method, Marshal.dump(x))
- y.untrusted?.should be_true
-
- # note that round-trip via Marshal does not preserve
- # the untrustedness at each level of the nested structure
- y = Marshal.send(@method, Marshal.dump([[x]]))
- y.untrusted?.should be_true
- y.first.untrusted?.should be_true
- y.first.first.untrusted?.should be_true
- end
- end
-
# Note: Ruby 1.9 should be compatible with older marshal format
MarshalSpec::DATA.each do |description, (object, marshal, attributes)|
it "loads a #{description}" do
@@ -678,6 +720,17 @@ describe :marshal_load, shared: true do
new_obj_metaclass_ancestors[@num_self_class, 3].should ==
[Meths, UserRegexp, Regexp]
end
+
+ ruby_bug "#19439", ""..."3.3" do
+ it "restore the regexp instance variables" do
+ obj = Regexp.new("hello")
+ obj.instance_variable_set(:@regexp_ivar, [42])
+
+ new_obj = Marshal.send(@method, "\x04\bI/\nhello\x00\a:\x06EF:\x11@regexp_ivar[\x06i/")
+ new_obj.instance_variables.should == [:@regexp_ivar]
+ new_obj.instance_variable_get(:@regexp_ivar).should == [42]
+ end
+ end
end
describe "for a Float" do
diff --git a/spec/ruby/core/matchdata/allocate_spec.rb b/spec/ruby/core/matchdata/allocate_spec.rb
index 9f3ada4018..142ce639c2 100644
--- a/spec/ruby/core/matchdata/allocate_spec.rb
+++ b/spec/ruby/core/matchdata/allocate_spec.rb
@@ -1,10 +1,8 @@
require_relative '../../spec_helper'
describe "MatchData.allocate" do
- ruby_version_is "2.7" do
- it "is undefined" do
- # https://bugs.ruby-lang.org/issues/16294
- -> { MatchData.allocate }.should raise_error(NoMethodError)
- end
+ it "is undefined" do
+ # https://bugs.ruby-lang.org/issues/16294
+ -> { MatchData.allocate }.should raise_error(NoMethodError)
end
end
diff --git a/spec/ruby/core/matchdata/captures_spec.rb b/spec/ruby/core/matchdata/captures_spec.rb
index 8c0d2978b7..58d4620709 100644
--- a/spec/ruby/core/matchdata/captures_spec.rb
+++ b/spec/ruby/core/matchdata/captures_spec.rb
@@ -1,7 +1,15 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "MatchData#captures" do
it "returns an array of the match captures" do
/(.)(.)(\d+)(\d)/.match("THX1138.").captures.should == ["H","X","113","8"]
end
+
+ ruby_version_is "3.0" do
+ it "returns instances of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138: The Movie")
+ /(.)(.)(\d+)(\d)/.match(str).captures.each { |c| c.should be_an_instance_of(String) }
+ end
+ end
end
diff --git a/spec/ruby/core/matchdata/element_reference_spec.rb b/spec/ruby/core/matchdata/element_reference_spec.rb
index 26550ac94d..7c0f089bb4 100644
--- a/spec/ruby/core/matchdata/element_reference_spec.rb
+++ b/spec/ruby/core/matchdata/element_reference_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "MatchData#[]" do
it "acts as normal array indexing [index]" do
@@ -15,10 +16,38 @@ describe "MatchData#[]" do
it "supports accessors [start, length]" do
/(.)(.)(\d+)(\d)/.match("THX1138.")[1, 2].should == %w|H X|
/(.)(.)(\d+)(\d)/.match("THX1138.")[-3, 2].should == %w|X 113|
+
+ # negative index is larger than the number of match values
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[-30, 2].should == nil
+
+ # length argument larger than number of match values is capped to match value length
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3, 10].should == %w|113 8|
end
it "supports ranges [start..end]" do
/(.)(.)(\d+)(\d)/.match("THX1138.")[1..3].should == %w|H X 113|
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..10].should == %w|113 8|
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[-30..2].should == nil
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..1].should == []
+ end
+
+ it "supports endless ranges [start..]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..].should == %w|113 8|
+ end
+
+ it "supports beginningless ranges [..end]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[..1].should == %w|HX1138 H|
+ end
+
+ it "supports beginningless endless ranges [nil..nil]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[nil..nil].should == %w|HX1138 H X 113 8|
+ end
+
+ ruby_version_is "3.0" do
+ it "returns instances of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138.")
+ /(.)(.)(\d+)(\d)/.match(str)[0..-1].each { |m| m.should be_an_instance_of(String) }
+ end
end
end
diff --git a/spec/ruby/core/matchdata/fixtures/classes.rb b/spec/ruby/core/matchdata/fixtures/classes.rb
new file mode 100644
index 0000000000..54795636e5
--- /dev/null
+++ b/spec/ruby/core/matchdata/fixtures/classes.rb
@@ -0,0 +1,3 @@
+module MatchDataSpecs
+ class MyString < String; end
+end
diff --git a/spec/ruby/core/matchdata/match_length_spec.rb b/spec/ruby/core/matchdata/match_length_spec.rb
new file mode 100644
index 0000000000..f7785ab1a0
--- /dev/null
+++ b/spec/ruby/core/matchdata/match_length_spec.rb
@@ -0,0 +1,34 @@
+# -*- encoding: utf-8 -*-
+
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "MatchData#match_length" do
+ it "returns the length of the corresponding match when given an Integer" do
+ md = /(.)(.)(\d+)(\d)/.match("THX1138.")
+
+ md.match_length(0).should == 6
+ md.match_length(1).should == 1
+ md.match_length(2).should == 1
+ md.match_length(3).should == 3
+ md.match_length(4).should == 1
+ end
+
+ it "returns nil on non-matching index matches" do
+ md = /\d+(\w)?/.match("THX1138.")
+ md.match_length(1).should == nil
+ end
+
+ it "returns the length of the corresponding named match when given a Symbol" do
+ md = 'haystack'.match(/(?<t>t(?<a>ack))/)
+ md.match_length(:a).should == 3
+ md.match_length(:t).should == 4
+ end
+
+ it "returns nil on non-matching index matches" do
+ md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
+ md.match_length(:t).should == 1
+ md.match_length(:a).should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/match_spec.rb b/spec/ruby/core/matchdata/match_spec.rb
new file mode 100644
index 0000000000..545de6f93f
--- /dev/null
+++ b/spec/ruby/core/matchdata/match_spec.rb
@@ -0,0 +1,34 @@
+# -*- encoding: utf-8 -*-
+
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "MatchData#match" do
+ it "returns the corresponding match when given an Integer" do
+ md = /(.)(.)(\d+)(\d)/.match("THX1138.")
+
+ md.match(0).should == 'HX1138'
+ md.match(1).should == 'H'
+ md.match(2).should == 'X'
+ md.match(3).should == '113'
+ md.match(4).should == '8'
+ end
+
+ it "returns nil on non-matching index matches" do
+ md = /\d+(\w)?/.match("THX1138.")
+ md.match(1).should == nil
+ end
+
+ it "returns the corresponding named match when given a Symbol" do
+ md = 'haystack'.match(/(?<t>t(?<a>ack))/)
+ md.match(:a).should == 'ack'
+ md.match(:t).should == 'tack'
+ end
+
+ it "returns nil on non-matching index matches" do
+ md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
+ md.match(:t).should == 't'
+ md.match(:a).should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/post_match_spec.rb b/spec/ruby/core/matchdata/post_match_spec.rb
index 4ae51f107e..d3aa4c8900 100644
--- a/spec/ruby/core/matchdata/post_match_spec.rb
+++ b/spec/ruby/core/matchdata/post_match_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "MatchData#post_match" do
it "returns the string after the match equiv. special var $'" do
@@ -6,24 +7,6 @@ describe "MatchData#post_match" do
$'.should == ': The Movie'
end
- ruby_version_is ''...'2.7' do
- it "keeps taint status from the source string" do
- str = "THX1138: The Movie"
- str.taint
- res = /(.)(.)(\d+)(\d)/.match(str).post_match
- res.tainted?.should be_true
- $'.tainted?.should be_true
- end
-
- it "keeps untrusted status from the source string" do
- str = "THX1138: The Movie"
- str.untrust
- res = /(.)(.)(\d+)(\d)/.match(str).post_match
- res.untrusted?.should be_true
- $'.untrusted?.should be_true
- end
- end
-
it "sets the encoding to the encoding of the source String" do
str = "abc".force_encoding Encoding::EUC_JP
str.match(/b/).post_match.encoding.should equal(Encoding::EUC_JP)
@@ -33,4 +16,11 @@ describe "MatchData#post_match" do
str = "abc".force_encoding Encoding::ISO_8859_1
str.match(/c/).post_match.encoding.should equal(Encoding::ISO_8859_1)
end
+
+ ruby_version_is "3.0" do
+ it "returns an instance of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138: The Movie")
+ /(.)(.)(\d+)(\d)/.match(str).post_match.should be_an_instance_of(String)
+ end
+ end
end
diff --git a/spec/ruby/core/matchdata/pre_match_spec.rb b/spec/ruby/core/matchdata/pre_match_spec.rb
index 824612c84c..b43be5fb41 100644
--- a/spec/ruby/core/matchdata/pre_match_spec.rb
+++ b/spec/ruby/core/matchdata/pre_match_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "MatchData#pre_match" do
it "returns the string before the match, equiv. special var $`" do
@@ -6,24 +7,6 @@ describe "MatchData#pre_match" do
$`.should == 'T'
end
- ruby_version_is ''...'2.7' do
- it "keeps taint status from the source string" do
- str = "THX1138: The Movie"
- str.taint
- res = /(.)(.)(\d+)(\d)/.match(str).pre_match
- res.tainted?.should be_true
- $`.tainted?.should be_true
- end
-
- it "keeps untrusted status from the source string" do
- str = "THX1138: The Movie"
- str.untrust
- res = /(.)(.)(\d+)(\d)/.match(str).pre_match
- res.untrusted?.should be_true
- $`.untrusted?.should be_true
- end
- end
-
it "sets the encoding to the encoding of the source String" do
str = "abc".force_encoding Encoding::EUC_JP
str.match(/b/).pre_match.encoding.should equal(Encoding::EUC_JP)
@@ -33,4 +16,11 @@ describe "MatchData#pre_match" do
str = "abc".force_encoding Encoding::ISO_8859_1
str.match(/a/).pre_match.encoding.should equal(Encoding::ISO_8859_1)
end
+
+ ruby_version_is "3.0" do
+ it "returns an instance of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138: The Movie")
+ /(.)(.)(\d+)(\d)/.match(str).pre_match.should be_an_instance_of(String)
+ end
+ end
end
diff --git a/spec/ruby/core/matchdata/to_a_spec.rb b/spec/ruby/core/matchdata/to_a_spec.rb
index 6231d096fb..50f5a161a5 100644
--- a/spec/ruby/core/matchdata/to_a_spec.rb
+++ b/spec/ruby/core/matchdata/to_a_spec.rb
@@ -1,7 +1,15 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "MatchData#to_a" do
it "returns an array of matches" do
/(.)(.)(\d+)(\d)/.match("THX1138.").to_a.should == ["HX1138", "H", "X", "113", "8"]
end
+
+ ruby_version_is "3.0" do
+ it "returns instances of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138.")
+ /(.)(.)(\d+)(\d)/.match(str)[0..-1].to_a.each { |m| m.should be_an_instance_of(String) }
+ end
+ end
end
diff --git a/spec/ruby/core/matchdata/to_s_spec.rb b/spec/ruby/core/matchdata/to_s_spec.rb
index 9e213bb342..aab0955ae1 100644
--- a/spec/ruby/core/matchdata/to_s_spec.rb
+++ b/spec/ruby/core/matchdata/to_s_spec.rb
@@ -1,7 +1,15 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "MatchData#to_s" do
it "returns the entire matched string" do
/(.)(.)(\d+)(\d)/.match("THX1138.").to_s.should == "HX1138"
end
+
+ ruby_version_is "3.0" do
+ it "returns an instance of String when given a String subclass" do
+ str = MatchDataSpecs::MyString.new("THX1138.")
+ /(.)(.)(\d+)(\d)/.match(str).to_s.should be_an_instance_of(String)
+ end
+ end
end
diff --git a/spec/ruby/core/matchdata/values_at_spec.rb b/spec/ruby/core/matchdata/values_at_spec.rb
index 8f7fdf557c..4fd0bfc42a 100644
--- a/spec/ruby/core/matchdata/values_at_spec.rb
+++ b/spec/ruby/core/matchdata/values_at_spec.rb
@@ -1,21 +1,76 @@
require_relative '../../spec_helper'
-describe "MatchData#values_at" do
- it "returns an array of the matching value" do
- /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0, 2, -2).should == ["HX1138", "X", "113"]
+describe "Struct#values_at" do
+ # Should be synchronized with core/array/values_at_spec.rb and core/struct/values_at_spec.rb
+ #
+ # /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").to_a # => ["HX1138", "H", "X", "113", "8"]
+
+ context "when passed a list of Integers" do
+ it "returns an array containing each value given by one of integers" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0, 2, -2).should == ["HX1138", "X", "113"]
+ end
+
+ it "returns nil value for any integer that is out of range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(5).should == [nil]
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(-6).should == [nil]
+ end
end
- describe "when passed a Range" do
- it "returns an array of the matching value" do
- /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(2..4, 0..1).should == ["X", "113", "8", "HX1138", "H"]
+ context "when passed an integer Range" do
+ it "returns an array containing each value given by the elements of the range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..2).should == ["HX1138", "H", "X"]
+ end
+
+ it "fills with nil values for range elements larger than the captured values number" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..5).should == ["HX1138", "H", "X", "113", "8", nil]
+ end
+
+ it "raises RangeError if any element of the range is negative and out of range" do
+ -> { /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(-6..3) }.should raise_error(RangeError, "-6..3 out of range")
+ end
+
+ it "supports endless Range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..).should == ["HX1138", "H", "X", "113", "8"]
+ end
+
+ it "supports beginningless Range" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..2).should == ["HX1138", "H", "X"]
+ end
+
+ it "returns an empty Array when Range is empty" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(2..0).should == []
+ end
+ end
+
+ context "when passed names" do
+ it 'slices captures with the given names' do
+ /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at(:c, :a).should == ['2', '0']
+ end
+
+ it 'slices captures with the given String names' do
+ /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at('c', 'a').should == ['2', '0']
end
end
- it 'slices captures with the given names' do
- /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at(:c, :a).should == ['2', '0']
+ it "supports multiple integer Ranges" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(1..2, 2..3).should == ["H", "X", "X", "113"]
end
- it 'takes names and indices' do
+ it "supports mixing integer Ranges and Integers" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(1..2, 4).should == ["H", "X", "8"]
+ end
+
+ it 'supports mixing of names and indices' do
/\A(?<a>.)(?<b>.)\z/.match('01').values_at(0, 1, 2, :a, :b).should == ['01', '0', '1', '0', '1']
end
+
+ it "returns a new empty Array if no arguments given" do
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at().should == []
+ end
+
+ it "fails when passed arguments of unsupported types" do
+ -> {
+ /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(Object.new)
+ }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
+ end
end
diff --git a/spec/ruby/core/math/ldexp_spec.rb b/spec/ruby/core/math/ldexp_spec.rb
index fb7799cf26..6dcf94a663 100644
--- a/spec/ruby/core/math/ldexp_spec.rb
+++ b/spec/ruby/core/math/ldexp_spec.rb
@@ -45,6 +45,12 @@ describe "Math.ldexp" do
it "accepts any second argument that can be coerced with Integer()" do
Math.ldexp(3.23, MathSpecs::Integer.new).should be_close(12.92, TOLERANCE)
end
+
+ it "returns correct value that closes to the max value of double type" do
+ Math.ldexp(0.5122058490966879, 1024).should == 9.207889385574391e+307
+ Math.ldexp(0.9999999999999999, 1024).should == 1.7976931348623157e+308
+ Math.ldexp(0.99999999999999999, 1024).should == Float::INFINITY
+ end
end
describe "Math#ldexp" do
diff --git a/spec/ruby/core/math/log2_spec.rb b/spec/ruby/core/math/log2_spec.rb
index 1594f2d7af..3d4d41d130 100644
--- a/spec/ruby/core/math/log2_spec.rb
+++ b/spec/ruby/core/math/log2_spec.rb
@@ -15,7 +15,7 @@ describe "Math.log2" do
Math.log2((2**301+45677544234809571)).should == 301.0
end
- it "raises an Errno::EDOM if the argument is less than 0" do
+ it "raises Math::DomainError if the argument is less than 0" do
-> { Math.log2(-1e-15) }.should raise_error( Math::DomainError)
end
diff --git a/spec/ruby/core/math/sqrt_spec.rb b/spec/ruby/core/math/sqrt_spec.rb
index 779aea2a0a..918e7c3a17 100644
--- a/spec/ruby/core/math/sqrt_spec.rb
+++ b/spec/ruby/core/math/sqrt_spec.rb
@@ -27,6 +27,10 @@ describe "Math.sqrt" do
it "accepts any argument that can be coerced with Float()" do
Math.sqrt(MathSpecs::Float.new).should be_close(1.0, TOLERANCE)
end
+
+ it "raises a Math::DomainError when given a negative number" do
+ -> { Math.sqrt(-1) }.should raise_error(Math::DomainError)
+ end
end
describe "Math#sqrt" do
diff --git a/spec/ruby/core/method/fixtures/classes.rb b/spec/ruby/core/method/fixtures/classes.rb
index be96f65e25..464a519aea 100644
--- a/spec/ruby/core/method/fixtures/classes.rb
+++ b/spec/ruby/core/method/fixtures/classes.rb
@@ -84,6 +84,12 @@ module MethodSpecs
def two_req_one_opt_with_splat_and_block(a, b, c=nil, *d, &blk); end
def one_req_two_opt_with_splat_and_block(a, b=nil, c=nil, *d, &blk); end
+ def my_public_method; end
+ def my_protected_method; end
+ def my_private_method; end
+ protected :my_protected_method
+ private :my_private_method
+
define_method(:zero_defined_method, Proc.new {||})
define_method(:zero_with_splat_defined_method, Proc.new {|*x|})
define_method(:one_req_defined_method, Proc.new {|x|})
@@ -213,4 +219,28 @@ module MethodSpecs
n * m
end
end
+
+ module InheritedMethods
+ module A
+ private
+ def derp(message)
+ 'A'
+ end
+ end
+
+ module B
+ private
+ def derp
+ 'B' + super('superclass')
+ end
+ end
+
+ class C
+ include A
+ include B
+
+ public :derp
+ alias_method :meow, :derp
+ end
+ end
end
diff --git a/spec/ruby/core/method/owner_spec.rb b/spec/ruby/core/method/owner_spec.rb
index ca5dff7295..05422f1697 100644
--- a/spec/ruby/core/method/owner_spec.rb
+++ b/spec/ruby/core/method/owner_spec.rb
@@ -23,4 +23,10 @@ describe "Method#owner" do
@m.method(:handled_via_method_missing).owner.should == MethodSpecs::Methods
end
end
+
+ ruby_version_is "3.2" do
+ it "returns the class on which public was called for a private method in ancestor" do
+ MethodSpecs::InheritedMethods::C.new.method(:derp).owner.should == MethodSpecs::InheritedMethods::C
+ end
+ end
end
diff --git a/spec/ruby/core/method/parameters_spec.rb b/spec/ruby/core/method/parameters_spec.rb
index 3fdaf9ce6f..e6d51d1b4d 100644
--- a/spec/ruby/core/method/parameters_spec.rb
+++ b/spec/ruby/core/method/parameters_spec.rb
@@ -222,9 +222,18 @@ describe "Method#parameters" do
m.method(:handled_via_method_missing).parameters.should == [[:rest]]
end
- it "adds nameless rest arg for \"star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_splat).parameters.should == [[:rest]]
+ ruby_version_is '3.2' do
+ it "adds * rest arg for \"star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]]
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it "adds nameless rest arg for \"star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_splat).parameters.should == [[:rest]]
+ end
end
it "returns the args and block for a splat and block argument" do
diff --git a/spec/ruby/core/method/private_spec.rb b/spec/ruby/core/method/private_spec.rb
new file mode 100644
index 0000000000..230a4e9e81
--- /dev/null
+++ b/spec/ruby/core/method/private_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "Method#private?" do
+ it "returns false when the method is public" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).private?.should == false
+ end
+
+ it "returns false when the method is protected" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).private?.should == false
+ end
+
+ it "returns true when the method is private" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).private?.should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/method/protected_spec.rb b/spec/ruby/core/method/protected_spec.rb
new file mode 100644
index 0000000000..6ee85f7738
--- /dev/null
+++ b/spec/ruby/core/method/protected_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "Method#protected?" do
+ it "returns false when the method is public" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).protected?.should == false
+ end
+
+ it "returns true when the method is protected" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).protected?.should == true
+ end
+
+ it "returns false when the method is private" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).protected?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/method/public_spec.rb b/spec/ruby/core/method/public_spec.rb
new file mode 100644
index 0000000000..3988468551
--- /dev/null
+++ b/spec/ruby/core/method/public_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "Method#public?" do
+ it "returns true when the method is public" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).public?.should == true
+ end
+
+ it "returns false when the method is protected" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).public?.should == false
+ end
+
+ it "returns false when the method is private" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).public?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/method/shared/to_s.rb b/spec/ruby/core/method/shared/to_s.rb
index 0dcae41b59..6fdeaaf99c 100644
--- a/spec/ruby/core/method/shared/to_s.rb
+++ b/spec/ruby/core/method/shared/to_s.rb
@@ -24,19 +24,17 @@ 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
+ 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
it "returns a String containing the Module the method is defined in" do
@@ -79,11 +77,9 @@ describe :method_to_s, shared: true do
@string.should.start_with? "#<Method: #<MethodSpecs::MySub:0xXXXXXX>.bar"
end
- ruby_version_is '2.7' do
- ruby_bug '#17428', '2.7'...'3.0' do
- it "shows the metaclass and the owner for a Module instance method retrieved from a class" do
- String.method(:include).inspect.should.start_with?("#<Method: #<Class:String>(Module)#include")
- end
+ ruby_bug '#17428', ''...'3.0' do
+ it "shows the metaclass and the owner for a Module instance method retrieved from a class" do
+ String.method(:include).inspect.should.start_with?("#<Method: #<Class:String>(Module)#include")
end
end
end
diff --git a/spec/ruby/core/method/super_method_spec.rb b/spec/ruby/core/method/super_method_spec.rb
index e5d8b87a06..f9a18f3878 100644
--- a/spec/ruby/core/method/super_method_spec.rb
+++ b/spec/ruby/core/method/super_method_spec.rb
@@ -42,4 +42,25 @@ describe "Method#super_method" do
method.super_method.should == nil
end
+
+ # https://github.com/jruby/jruby/issues/7240
+ context "after changing an inherited methods visibility" do
+ it "calls the proper super method" do
+ MethodSpecs::InheritedMethods::C.new.derp.should == 'BA'
+ end
+
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+
+ ruby_version_is "2.7.3" do
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/method/unbind_spec.rb b/spec/ruby/core/method/unbind_spec.rb
index cdd3a808f2..bdedd513ce 100644
--- a/spec/ruby/core/method/unbind_spec.rb
+++ b/spec/ruby/core/method/unbind_spec.rb
@@ -27,8 +27,16 @@ describe "Method#unbind" do
@string.should =~ /MethodSpecs::MyMod/
end
- it "returns a String containing the Module the method is referenced from" do
- @string.should =~ /MethodSpecs::MySub/
+ ruby_version_is ""..."3.2" do
+ it "returns a String containing the Module the method is referenced from" do
+ @string.should =~ /MethodSpecs::MySub/
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "returns a String containing the Module the method is referenced from" do
+ @string.should =~ /MethodSpecs::MyMod/
+ end
end
end
diff --git a/spec/ruby/core/module/allocate_spec.rb b/spec/ruby/core/module/allocate_spec.rb
deleted file mode 100644
index 3b2c4119c3..0000000000
--- a/spec/ruby/core/module/allocate_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Module.allocate" do
- it "returns an instance of Module" do
- mod = Module.allocate
- mod.should be_an_instance_of(Module)
- end
-
- it "returns a fully-formed instance of Module" do
- mod = Module.allocate
- mod.constants.should_not == nil
- mod.methods.should_not == nil
- end
-end
diff --git a/spec/ruby/core/module/append_features_spec.rb b/spec/ruby/core/module/append_features_spec.rb
index d960798eef..1724cde5d6 100644
--- a/spec/ruby/core/module/append_features_spec.rb
+++ b/spec/ruby/core/module/append_features_spec.rb
@@ -47,20 +47,6 @@ describe "Module#append_features" do
end
- ruby_version_is ''...'2.7' do
- it "copies own tainted status to the given module" do
- other = Module.new
- Module.new.taint.send :append_features, other
- other.tainted?.should be_true
- end
-
- it "copies own untrusted status to the given module" do
- other = Module.new
- Module.new.untrust.send :append_features, other
- other.untrusted?.should be_true
- end
- end
-
describe "when other is frozen" do
before :each do
@receiver = Module.new
diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index f17675846b..af04ab26c8 100644
--- a/spec/ruby/core/module/autoload_spec.rb
+++ b/spec/ruby/core/module/autoload_spec.rb
@@ -18,16 +18,14 @@ describe "Module#autoload?" do
ModuleSpecs::Autoload::Child.autoload?(:AnotherAutoload).should == "another_autoload.rb"
end
- ruby_version_is "2.7" do
- it "returns nil if an ancestor defined that autoload but recursion is disabled" do
- ModuleSpecs::Autoload::Parent.autoload :InheritedAutoload, "inherited_autoload.rb"
- ModuleSpecs::Autoload::Child.autoload?(:InheritedAutoload, false).should be_nil
- end
+ it "returns nil if an ancestor defined that autoload but recursion is disabled" do
+ ModuleSpecs::Autoload::Parent.autoload :InheritedAutoload, "inherited_autoload.rb"
+ ModuleSpecs::Autoload::Child.autoload?(:InheritedAutoload, false).should be_nil
+ end
- it "returns the name of the file that will be loaded if recursion is disabled but the autoload is defined on the class itself" do
- ModuleSpecs::Autoload::Child.autoload :ChildAutoload, "child_autoload.rb"
- ModuleSpecs::Autoload::Child.autoload?(:ChildAutoload, false).should == "child_autoload.rb"
- end
+ it "returns the name of the file that will be loaded if recursion is disabled but the autoload is defined on the class itself" do
+ ModuleSpecs::Autoload::Child.autoload :ChildAutoload, "child_autoload.rb"
+ ModuleSpecs::Autoload::Child.autoload?(:ChildAutoload, false).should == "child_autoload.rb"
end
end
@@ -441,21 +439,42 @@ describe "Module#autoload" do
ScratchPad.recorded.should == [:raise, :raise]
end
- it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do
- path = fixture(__FILE__, "autoload_o.rb")
- ScratchPad.record []
- ModuleSpecs::Autoload.autoload :O, path
+ ruby_version_is "3.1" do
+ it "removes the constant from Module#constants if the loaded file does not define it" do
+ path = fixture(__FILE__, "autoload_o.rb")
+ ScratchPad.record []
+ ModuleSpecs::Autoload.autoload :O, path
- ModuleSpecs::Autoload.const_defined?(:O).should == true
- ModuleSpecs::Autoload.should have_constant(:O)
- ModuleSpecs::Autoload.autoload?(:O).should == path
+ ModuleSpecs::Autoload.const_defined?(:O).should == true
+ ModuleSpecs::Autoload.should have_constant(:O)
+ ModuleSpecs::Autoload.autoload?(:O).should == path
- -> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
+ -> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
- ModuleSpecs::Autoload.should have_constant(:O)
- ModuleSpecs::Autoload.const_defined?(:O).should == false
- ModuleSpecs::Autoload.autoload?(:O).should == nil
- -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
+ ModuleSpecs::Autoload.const_defined?(:O).should == false
+ ModuleSpecs::Autoload.should_not have_constant(:O)
+ ModuleSpecs::Autoload.autoload?(:O).should == nil
+ -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
+ end
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do
+ path = fixture(__FILE__, "autoload_o.rb")
+ ScratchPad.record []
+ ModuleSpecs::Autoload.autoload :O, path
+
+ ModuleSpecs::Autoload.const_defined?(:O).should == true
+ ModuleSpecs::Autoload.should have_constant(:O)
+ ModuleSpecs::Autoload.autoload?(:O).should == path
+
+ -> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
+
+ ModuleSpecs::Autoload.const_defined?(:O).should == false
+ ModuleSpecs::Autoload.should have_constant(:O)
+ ModuleSpecs::Autoload.autoload?(:O).should == nil
+ -> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
+ end
end
it "does not try to load the file again if the loaded file did not define the constant" do
@@ -493,9 +512,7 @@ describe "Module#autoload" do
it "does not load the file when accessing the constants table of the module" do
ModuleSpecs::Autoload.autoload :P, @non_existent
ModuleSpecs::Autoload.const_defined?(:P).should be_true
- ruby_bug "[Bug #15780]", ""..."2.7" do
- ModuleSpecs::Autoload.const_defined?("P").should be_true
- end
+ ModuleSpecs::Autoload.const_defined?("P").should be_true
end
it "loads the file when opening a module that is the autoloaded constant" do
@@ -554,31 +571,84 @@ describe "Module#autoload" do
# Basically, the parent autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInParentDefinedInCurrent).should == nil
const_defined?(:DeclaredInParentDefinedInCurrent).should == false
- self.should have_constant(:DeclaredInParentDefinedInCurrent)
-> { DeclaredInParentDefinedInCurrent }.should raise_error(NameError)
ModuleSpecs::Autoload::LexicalScope.send(:remove_const, :DeclaredInParentDefinedInCurrent)
end
end
- it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do
- @remove << :DeclaredInCurrentDefinedInParent
- module ModuleSpecs::Autoload
+ ruby_version_is "3.2" do
+ it "warns once in verbose mode if the constant was defined in a parent scope" do
ScratchPad.record -> {
- DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ ModuleSpecs::DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
}
- class LexicalScope
- autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
- -> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError)
- # Basically, the autoload constant remains in a "undefined" state
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
- const_defined?(:DeclaredInCurrentDefinedInParent).should == false
- self.should have_constant(:DeclaredInCurrentDefinedInParent)
- -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
+ module ModuleSpecs
+ module Autoload
+ autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == fixture(__FILE__, "autoload_callback.rb")
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == true
+
+ -> {
+ DeclaredInCurrentDefinedInParent
+ }.should complain(
+ /Expected .*autoload_callback.rb to define ModuleSpecs::Autoload::DeclaredInCurrentDefinedInParent but it didn't/,
+ verbose: true,
+ )
+
+ -> {
+ DeclaredInCurrentDefinedInParent
+ }.should_not complain(/.*/, verbose: true)
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == false
+ ModuleSpecs.const_defined?(:DeclaredInCurrentDefinedInParent).should == true
+ end
+ end
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "looks up in parent scope after failed autoload" do
+ @remove << :DeclaredInCurrentDefinedInParent
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ }
+
+ class LexicalScope
+ autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ -> { DeclaredInCurrentDefinedInParent }.should_not raise_error(NameError)
+ # Basically, the autoload constant remains in a "undefined" state
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == false
+ -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
+ end
+
+ DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
end
+ end
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do
+ @remove << :DeclaredInCurrentDefinedInParent
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ }
- DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
+ class LexicalScope
+ autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ -> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError)
+ # Basically, the autoload constant remains in a "undefined" state
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == false
+ self.should have_constant(:DeclaredInCurrentDefinedInParent)
+ -> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
+ end
+
+ DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
+ end
end
end
diff --git a/spec/ruby/core/module/class_variables_spec.rb b/spec/ruby/core/module/class_variables_spec.rb
index fd7aa93aa8..e155f1deac 100644
--- a/spec/ruby/core/module/class_variables_spec.rb
+++ b/spec/ruby/core/module/class_variables_spec.rb
@@ -23,4 +23,12 @@ describe "Module#class_variables" do
c.extend ModuleSpecs::MVars
c.class_variables.should_not include(:@@mvar)
end
+
+ it "returns the correct class variables when inherit is given" do
+ ModuleSpecs::SubCVars.class_variables(false).should == [:@@sub]
+ ModuleSpecs::SubCVars.new.singleton_class.class_variables(false).should == []
+
+ ModuleSpecs::SubCVars.class_variables(true).should == [:@@sub, :@@cls, :@@meta]
+ ModuleSpecs::SubCVars.new.singleton_class.class_variables(true).should == [:@@sub, :@@cls, :@@meta]
+ end
end
diff --git a/spec/ruby/core/module/const_added_spec.rb b/spec/ruby/core/module/const_added_spec.rb
new file mode 100644
index 0000000000..31ac6eb105
--- /dev/null
+++ b/spec/ruby/core/module/const_added_spec.rb
@@ -0,0 +1,125 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Module#const_added" do
+ ruby_version_is "3.2" do
+ it "is a private instance method" do
+ Module.should have_private_instance_method(:const_added)
+ end
+
+ it "returns nil in the default implementation" do
+ Module.new do
+ const_added(:TEST).should == nil
+ end
+ end
+
+ it "is called when a new constant is assigned on self" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+ end
+
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 1
+ RUBY
+
+ ScratchPad.recorded.should == [:TEST]
+ end
+
+ it "is called when a new constant is assigned on self through const_set" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+ end
+
+ mod.const_set(:TEST, 1)
+
+ ScratchPad.recorded.should == [:TEST]
+ end
+
+ it "is called when a new module is defined under self" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+ end
+
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ module SubModule
+ end
+
+ module SubModule
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:SubModule]
+ end
+
+ it "is called when a new class is defined under self" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+ end
+
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ class SubClass
+ end
+
+ class SubClass
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:SubClass]
+ end
+
+ it "is called when an autoload is defined" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+ end
+
+ mod.autoload :Autoload, "foo"
+ ScratchPad.recorded.should == [:Autoload]
+ end
+
+ it "is called with a precise caller location with the line of definition" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ location = caller_locations(1, 1)[0]
+ ScratchPad << location.lineno
+ end
+ end
+
+ line = __LINE__
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 1
+
+ module SubModule
+ end
+
+ class SubClass
+ end
+ RUBY
+
+ mod.const_set(:CONST_SET, 1)
+
+ ScratchPad.recorded.should == [line + 2, line + 4, line + 7, line + 11]
+ end
+ end
+end
diff --git a/spec/ruby/core/module/const_defined_spec.rb b/spec/ruby/core/module/const_defined_spec.rb
index 75730395e8..0c15629c08 100644
--- a/spec/ruby/core/module/const_defined_spec.rb
+++ b/spec/ruby/core/module/const_defined_spec.rb
@@ -17,11 +17,16 @@ describe "Module#const_defined?" do
ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4).should be_true
end
- it "returns true if the constant is defined in a mixed-in module of the receiver" do
+ it "returns true if the constant is defined in a mixed-in module of the receiver's parent" do
# CS_CONST10 is defined in a module included by ChildA
ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST10).should be_true
end
+ it "returns true if the constant is defined in a mixed-in module (with prepends) of the receiver" do
+ # CS_CONST11 is defined in the module included by ContainerPrepend
+ ConstantSpecs::ContainerPrepend.const_defined?(:CS_CONST11).should be_true
+ end
+
it "returns true if the constant is defined in Object and the receiver is a module" do
# CS_CONST1 is defined in Object
ConstantSpecs::ModuleA.const_defined?(:CS_CONST1).should be_true
diff --git a/spec/ruby/core/module/const_get_spec.rb b/spec/ruby/core/module/const_get_spec.rb
index 9f9fafe5bb..69f181cf51 100644
--- a/spec/ruby/core/module/const_get_spec.rb
+++ b/spec/ruby/core/module/const_get_spec.rb
@@ -100,6 +100,16 @@ describe "Module#const_get" do
ConstantSpecs.const_get("::CS_CONST1").should == :const1
end
+ it "accepts a toplevel scope qualifier when inherit is false" do
+ ConstantSpecs.const_get("::CS_CONST1", false).should == :const1
+ -> { ConstantSpecs.const_get("CS_CONST1", false) }.should raise_error(NameError)
+ end
+
+ it "returns a constant whose module is defined the the toplevel" do
+ ConstantSpecs.const_get("ConstantSpecsTwo::Foo").should == :cs_two_foo
+ ConstantSpecsThree.const_get("ConstantSpecsTwo::Foo").should == :cs_three_foo
+ end
+
it "accepts a scoped constant name" do
ConstantSpecs.const_get("ClassA::CS_CONST10").should == :const10_10
end
@@ -140,6 +150,10 @@ describe "Module#const_get" do
Object.const_get('CSAutoloadD::InnerModule').name.should == 'CSAutoloadD::InnerModule'
end
+ it "raises a NameError when the nested constant does not exist on the module but exists in Object" do
+ -> { Object.const_get('ConstantSpecs::CS_CONST1') }.should raise_error(NameError)
+ end
+
describe "with statically assigned constants" do
it "searches the immediate class or module first" do
ConstantSpecs::ClassA.const_get(:CS_CONST10).should == :const10_10
diff --git a/spec/ruby/core/module/const_set_spec.rb b/spec/ruby/core/module/const_set_spec.rb
index b537d3f133..ba7810d17b 100644
--- a/spec/ruby/core/module/const_set_spec.rb
+++ b/spec/ruby/core/module/const_set_spec.rb
@@ -101,7 +101,7 @@ describe "Module#const_set" do
mod.const_get(:Foo).should == 1
end
- it "does not warn if the previous value was undefined" do
+ it "does not warn after a failed autoload" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
mod = Module.new
@@ -109,7 +109,6 @@ describe "Module#const_set" do
mod.autoload :Foo, path
-> { mod::Foo }.should raise_error(NameError)
- mod.should have_constant(:Foo)
mod.const_defined?(:Foo).should == false
mod.autoload?(:Foo).should == nil
diff --git a/spec/ruby/core/module/const_source_location_spec.rb b/spec/ruby/core/module/const_source_location_spec.rb
index 9e1f2c1c49..11a2e74756 100644
--- a/spec/ruby/core/module/const_source_location_spec.rb
+++ b/spec/ruby/core/module/const_source_location_spec.rb
@@ -6,215 +6,220 @@ describe "Module#const_source_location" 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]
+ 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::ParentA::CSL_CONST301 = :const301_3
- ConstantSpecs::ParentA.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::ContainerA::ChildA::CSL_CONST301 = :const301_5
- ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
- end
+ ConstantSpecs::ParentA::CSL_CONST301 = :const301_3
+ ConstantSpecs::ParentA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
- 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::ContainerA::ChildA::CSL_CONST301 = :const301_5
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+ end
- -> {
- ConstantSpecs::ClassB::CSL_CONST309 = :const309_2
- }.should complain(/already initialized constant/)
- ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2]
- 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
- 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 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 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 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 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 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 "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 "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 "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 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 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 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]
- 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
+ -> {
+ ConstantSpecs::ClassB::CSL_CONST309 = :const309_2
+ }.should complain(/already initialized constant/)
+ ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2]
end
+ end
- it "return empty path if constant defined in C code" do
- Object.const_source_location(:String).should == []
+ 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 "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]
+ 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 "returns nil if no constant is defined in the search path" do
- ConstantSpecs.const_source_location(:CS_CONSTX).should == nil
+ 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 "raises a NameError if the name does not start with a capital letter" do
- -> { ConstantSpecs.const_source_location "name" }.should raise_error(NameError)
+ 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 "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)
+ 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 "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)
+ 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 "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]
+ 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 "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)
+ it "return empty path if constant defined in C code" do
+ Object.const_source_location(:String).should == []
+ end
- name.should_receive(:to_str).and_return(123)
- -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
- 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 "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 "returns nil if no constant is defined in the search path" do
+ ConstantSpecs.const_source_location(:CS_CONSTX).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 "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 "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 "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 "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 "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 "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 "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 "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 "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)
- it "accepts a toplevel scope qualifier" do
- ConstantSpecs.const_source_location("::CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
- end
+ name.should_receive(:to_str).and_return(123)
+ -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+ 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 "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 "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 "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 "raises a NameError if only '::' is passed" do
- -> { ConstantSpecs.const_source_location("::") }.should raise_error(NameError)
- 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 "raises a NameError if a Symbol has a toplevel scope qualifier" do
- -> { ConstantSpecs.const_source_location(:'::CS_CONST1') }.should raise_error(NameError)
- 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 "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 "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 "does search private constants path" do
- ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
- 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 "returns updated location from const_set" do
+ mod = Module.new
+ const_line = __LINE__ + 1
+ mod.const_set :Foo, 1
+ mod.const_source_location(:Foo).should == [__FILE__, const_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
- context 'autoload' do
- before :all do
- ConstantSpecs.autoload :CSL_CONST1, "#{__dir__}/notexisting.rb"
- @line = __LINE__ - 1
- 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 'returns the autoload location while not resolved' do
- ConstantSpecs.const_source_location('CSL_CONST1').should == [__FILE__, @line]
- 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
+ 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
diff --git a/spec/ruby/core/module/constants_spec.rb b/spec/ruby/core/module/constants_spec.rb
index fe95143872..330da1cc88 100644
--- a/spec/ruby/core/module/constants_spec.rb
+++ b/spec/ruby/core/module/constants_spec.rb
@@ -74,6 +74,12 @@ describe "Module#constants" do
it "returns only public constants" do
ModuleSpecs::PrivConstModule.constants.should == [:PUBLIC_CONSTANT]
end
+
+ it "returns only constants starting with an uppercase letter" do
+ # e.g. fatal, IO::generic_readable and IO::generic_writable should not be returned by Module#constants
+ Object.constants.each { |c| c[0].should == c[0].upcase }
+ IO.constants.each { |c| c[0].should == c[0].upcase }
+ end
end
describe "Module#constants" do
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb
index 0cb2ab140c..ce94436bfd 100644
--- a/spec/ruby/core/module/define_method_spec.rb
+++ b/spec/ruby/core/module/define_method_spec.rb
@@ -219,18 +219,55 @@ describe "Module#define_method" do
o.block_test2.should == o
end
+ it "raises TypeError if name cannot converted to String" do
+ -> {
+ Class.new { define_method(1001, -> {}) }
+ }.should raise_error(TypeError, /is not a symbol nor a string/)
+
+ -> {
+ Class.new { define_method([], -> {}) }
+ }.should raise_error(TypeError, /is not a symbol nor a string/)
+ end
+
+ it "converts non-String name to String with #to_str" do
+ obj = Object.new
+ def obj.to_str() "foo" end
+
+ new_class = Class.new { define_method(obj, -> { :called }) }
+ new_class.new.foo.should == :called
+ end
+
+ it "raises TypeError when #to_str called on non-String name returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> {
+ Class.new { define_method(obj, -> {}) }
+ }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+
it "raises a TypeError when the given method is no Method/Proc" do
-> {
Class.new { define_method(:test, "self") }
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, "wrong argument type String (expected Proc/Method/UnboundMethod)")
-> {
Class.new { define_method(:test, 1234) }
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, "wrong argument type Integer (expected Proc/Method/UnboundMethod)")
-> {
Class.new { define_method(:test, nil) }
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, "wrong argument type NilClass (expected Proc/Method/UnboundMethod)")
+ end
+
+ it "uses provided Method/Proc even if block is specified" do
+ new_class = Class.new do
+ define_method(:test, -> { :method_is_called }) do
+ :block_is_called
+ end
+ end
+
+ new_class.new.test.should == :method_is_called
end
it "raises an ArgumentError when no block is given" do
@@ -350,6 +387,14 @@ describe "Module#define_method" do
object2.other_cool_method.should == "data is foo"
end
+ it "accepts a proc from a Symbol" do
+ symbol_proc = :+.to_proc
+ klass = Class.new do
+ define_method :foo, &symbol_proc
+ end
+ klass.new.foo(1, 2).should == 3
+ end
+
it "maintains the Proc's scope" do
class DefineMethodByProcClass
in_scope = true
@@ -715,3 +760,46 @@ describe "Method#define_method when passed a Proc object" do
end
end
end
+
+describe "Method#define_method when passed a block" do
+ describe "behaves exactly like a lambda" do
+ it "for return" do
+ Class.new do
+ define_method(:foo) do
+ return 42
+ end
+ end.new.foo.should == 42
+ end
+
+ it "for break" do
+ Class.new do
+ define_method(:foo) do
+ break 42
+ end
+ end.new.foo.should == 42
+ end
+
+ it "for next" do
+ Class.new do
+ define_method(:foo) do
+ next 42
+ end
+ end.new.foo.should == 42
+ end
+
+ it "for redo" do
+ Class.new do
+ result = []
+ define_method(:foo) do
+ if result.empty?
+ result << :first
+ redo
+ else
+ result << :second
+ result
+ end
+ end
+ end.new.foo.should == [:first, :second]
+ end
+ end
+end
diff --git a/spec/ruby/core/module/deprecate_constant_spec.rb b/spec/ruby/core/module/deprecate_constant_spec.rb
index 7bcced981b..aabef934c4 100644
--- a/spec/ruby/core/module/deprecate_constant_spec.rb
+++ b/spec/ruby/core/module/deprecate_constant_spec.rb
@@ -9,7 +9,6 @@ describe "Module#deprecate_constant" do
@module::PRIVATE = @value
@module.private_constant :PRIVATE
@module.deprecate_constant :PRIVATE
- @pattern = /deprecated/
end
describe "when accessing the deprecated module" do
@@ -19,7 +18,7 @@ describe "Module#deprecate_constant" do
value = nil
-> {
value = @module::PUBLIC1
- }.should complain(@pattern)
+ }.should complain(/warning: constant .+::PUBLIC1 is deprecated/)
value.should equal(@value)
-> { @module::PRIVATE }.should raise_error(NameError)
@@ -28,16 +27,28 @@ describe "Module#deprecate_constant" do
it "warns with a message" do
@module.deprecate_constant :PUBLIC1
- -> { @module::PUBLIC1 }.should complain(@pattern)
- -> { @module.const_get :PRIVATE }.should complain(@pattern)
+ -> { @module::PUBLIC1 }.should complain(/warning: constant .+::PUBLIC1 is deprecated/)
+ -> { @module.const_get :PRIVATE }.should complain(/warning: constant .+::PRIVATE is deprecated/)
+ end
+
+ it "does not warn if Warning[:deprecated] is false" do
+ @module.deprecate_constant :PUBLIC1
+
+ deprecated = Warning[:deprecated]
+ begin
+ Warning[:deprecated] = false
+ -> { @module::PUBLIC1 }.should_not complain
+ ensure
+ Warning[:deprecated] = deprecated
+ end
end
end
it "accepts multiple symbols and strings as constant names" do
@module.deprecate_constant "PUBLIC1", :PUBLIC2
- -> { @module::PUBLIC1 }.should complain(@pattern)
- -> { @module::PUBLIC2 }.should complain(@pattern)
+ -> { @module::PUBLIC1 }.should complain(/warning: constant .+::PUBLIC1 is deprecated/)
+ -> { @module::PUBLIC2 }.should complain(/warning: constant .+::PUBLIC2 is deprecated/)
end
it "returns self" do
diff --git a/spec/ruby/core/module/extend_object_spec.rb b/spec/ruby/core/module/extend_object_spec.rb
index e66b87efef..1fd1abc0b5 100644
--- a/spec/ruby/core/module/extend_object_spec.rb
+++ b/spec/ruby/core/module/extend_object_spec.rb
@@ -42,20 +42,6 @@ describe "Module#extend_object" do
ScratchPad.recorded.should == :extended
end
- ruby_version_is ''...'2.7' do
- it "does not copy own tainted status to the given object" do
- other = Object.new
- Module.new.taint.send :extend_object, other
- other.tainted?.should be_false
- end
-
- it "does not copy own untrusted status to the given object" do
- other = Object.new
- Module.new.untrust.send :extend_object, other
- other.untrusted?.should be_false
- end
- end
-
describe "when given a frozen object" do
before :each do
@receiver = Module.new
diff --git a/spec/ruby/core/module/fixtures/classes.rb b/spec/ruby/core/module/fixtures/classes.rb
index 40777cdbbd..bc6b940a6c 100644
--- a/spec/ruby/core/module/fixtures/classes.rb
+++ b/spec/ruby/core/module/fixtures/classes.rb
@@ -42,6 +42,14 @@ module ModuleSpecs
class LookupChild < Lookup
end
+ module ModuleWithPrepend
+ prepend LookupMod
+ end
+
+ class WithPrependedModule
+ include ModuleWithPrepend
+ end
+
class Parent
# For private_class_method spec
def self.private_method; end
@@ -352,6 +360,10 @@ module ModuleSpecs
end
end
+ class SubCVars < CVars
+ @@sub = :sub
+ end
+
module MVars
@@mvar = :mvar
end
@@ -376,6 +388,7 @@ module ModuleSpecs
# empty modules
module M1; end
module M2; end
+ module M3; end
module Autoload
def self.use_ex1
diff --git a/spec/ruby/core/module/include_spec.rb b/spec/ruby/core/module/include_spec.rb
index 128b9af2bf..c073bc31ca 100644
--- a/spec/ruby/core/module/include_spec.rb
+++ b/spec/ruby/core/module/include_spec.rb
@@ -104,9 +104,9 @@ describe "Module#include" do
class A; include M; end
class B < A; include M; end
- all = [A,B,M]
+ all = [A, B, M]
- (B.ancestors & all).should == [B, A, M]
+ (B.ancestors.filter { |a| all.include?(a) }).should == [B, A, M]
end
end
@@ -532,6 +532,27 @@ describe "Module#include" do
B.foo.should == 'n'
end
end
+
+ it "overrides a previous super method call" do
+ c1 = Class.new do
+ def foo
+ [:c1]
+ end
+ end
+ c2 = Class.new(c1) do
+ def foo
+ [:c2] + super
+ end
+ end
+ c2.new.foo.should == [:c2, :c1]
+ m = Module.new do
+ def foo
+ [:m1]
+ end
+ end
+ c2.include(m)
+ c2.new.foo.should == [:c2, :m1]
+ end
end
describe "Module#include?" do
diff --git a/spec/ruby/core/module/included_modules_spec.rb b/spec/ruby/core/module/included_modules_spec.rb
index 40e20953f4..ce94ed1285 100644
--- a/spec/ruby/core/module/included_modules_spec.rb
+++ b/spec/ruby/core/module/included_modules_spec.rb
@@ -4,9 +4,11 @@ require_relative 'fixtures/classes'
describe "Module#included_modules" do
it "returns a list of modules included in self" do
ModuleSpecs.included_modules.should == []
+
ModuleSpecs::Child.included_modules.should include(ModuleSpecs::Super, ModuleSpecs::Basic, Kernel)
ModuleSpecs::Parent.included_modules.should include(Kernel)
ModuleSpecs::Basic.included_modules.should == []
ModuleSpecs::Super.included_modules.should include(ModuleSpecs::Basic)
+ ModuleSpecs::WithPrependedModule.included_modules.should include(ModuleSpecs::ModuleWithPrepend)
end
end
diff --git a/spec/ruby/core/module/instance_method_spec.rb b/spec/ruby/core/module/instance_method_spec.rb
index b4d6a0d8c8..8d006e647e 100644
--- a/spec/ruby/core/module/instance_method_spec.rb
+++ b/spec/ruby/core/module/instance_method_spec.rb
@@ -45,20 +45,46 @@ describe "Module#instance_method" do
@parent_um.inspect.should =~ /\bModuleSpecs::InstanceMeth\b/
@child_um.inspect.should =~ /\bfoo\b/
@child_um.inspect.should =~ /\bModuleSpecs::InstanceMeth\b/
- @child_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
+
@mod_um.inspect.should =~ /\bbar\b/
@mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethMod\b/
- @mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
+
+ ruby_version_is ""..."3.2" do
+ @child_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
+ @mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
+ end
end
- it "raises a TypeError if not passed a symbol" do
- -> { Object.instance_method([]) }.should raise_error(TypeError)
- -> { Object.instance_method(0) }.should raise_error(TypeError)
+ it "raises a TypeError if the given name is not a String/Symbol" do
+ -> { Object.instance_method([]) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(0) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(nil) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(mock('x')) }.should raise_error(TypeError, /is not a symbol nor a string/)
end
- it "raises a TypeError if the given name is not a string/symbol" do
- -> { Object.instance_method(nil) }.should raise_error(TypeError)
- -> { Object.instance_method(mock('x')) }.should raise_error(TypeError)
+ it "accepts String name argument" do
+ method = ModuleSpecs::InstanceMeth.instance_method(:foo)
+ method.should be_kind_of(UnboundMethod)
+ end
+
+ it "accepts Symbol name argument" do
+ method = ModuleSpecs::InstanceMeth.instance_method("foo")
+ method.should be_kind_of(UnboundMethod)
+ end
+
+ it "converts non-String name by calling #to_str method" do
+ obj = Object.new
+ def obj.to_str() "foo" end
+
+ method = ModuleSpecs::InstanceMeth.instance_method(obj)
+ method.should be_kind_of(UnboundMethod)
+ end
+
+ it "raises TypeError when passed non-String name and #to_str returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> { ModuleSpecs::InstanceMeth.instance_method(obj) }.should raise_error(TypeError, /can't convert Object to String/)
end
it "raises a NameError if the method has been undefined" do
diff --git a/spec/ruby/core/module/module_function_spec.rb b/spec/ruby/core/module/module_function_spec.rb
index 407237d48f..0602e95ca9 100644
--- a/spec/ruby/core/module/module_function_spec.rb
+++ b/spec/ruby/core/module/module_function_spec.rb
@@ -38,14 +38,23 @@ describe "Module#module_function with specific method names" do
m.respond_to?(:test3).should == false
end
- it "returns the current module" do
- x = nil
- m = Module.new do
- def test() end
- x = module_function :test
+ ruby_version_is ""..."3.1" do
+ it "returns self" do
+ Module.new do
+ def foo; end
+ module_function(:foo).should equal(self)
+ end
end
+ end
- x.should == m
+ ruby_version_is "3.1" do
+ it "returns argument or arguments if given" do
+ Module.new do
+ def foo; end
+ module_function(:foo).should equal(:foo)
+ module_function(:foo, :foo).should == [:foo, :foo]
+ end
+ end
end
it "creates an independent copy of the method, not a redirect" do
@@ -160,13 +169,20 @@ describe "Module#module_function as a toggle (no arguments) in a Module body" do
m.respond_to?(:test2).should == true
end
- it "returns the current module" do
- x = nil
- m = Module.new {
- x = module_function
- }
+ ruby_version_is ""..."3.1" do
+ it "returns self" do
+ Module.new do
+ module_function.should equal(self)
+ end
+ end
+ end
- x.should == m
+ ruby_version_is "3.1" do
+ it "returns nil" do
+ Module.new do
+ module_function.should equal(nil)
+ end
+ end
end
it "stops creating module functions if the body encounters another toggle " \
diff --git a/spec/ruby/core/module/name_spec.rb b/spec/ruby/core/module/name_spec.rb
index ca9106a973..b78bbfcc80 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -118,27 +118,13 @@ describe "Module#name" do
m::N.name.should == "ModuleSpecs::Anonymous::E::N"
end
- ruby_version_is ""..."2.7" do
- it "returns a mutable string" do
- ModuleSpecs.name.frozen?.should be_false
- end
-
- it "returns a mutable string that when mutated does not modify the original module name" do
- ModuleSpecs.name << "foo"
-
- ModuleSpecs.name.should == "ModuleSpecs"
- end
+ it "returns a frozen String" do
+ ModuleSpecs.name.should.frozen?
end
- ruby_version_is "2.7" do
- it "returns a frozen String" do
- ModuleSpecs.name.should.frozen?
- end
-
- it "always returns the same String for a given Module" do
- s1 = ModuleSpecs.name
- s2 = ModuleSpecs.name
- s1.should equal(s2)
- end
+ it "always returns the same String for a given Module" do
+ s1 = ModuleSpecs.name
+ s2 = ModuleSpecs.name
+ s1.should equal(s2)
end
end
diff --git a/spec/ruby/core/module/prepend_features_spec.rb b/spec/ruby/core/module/prepend_features_spec.rb
index 2d1fa713b7..09c15c5c15 100644
--- a/spec/ruby/core/module/prepend_features_spec.rb
+++ b/spec/ruby/core/module/prepend_features_spec.rb
@@ -28,20 +28,6 @@ describe "Module#prepend_features" do
}.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "copies own tainted status to the given module" do
- other = Module.new
- Module.new.taint.send :prepend_features, other
- other.tainted?.should be_true
- end
-
- it "copies own untrusted status to the given module" do
- other = Module.new
- Module.new.untrust.send :prepend_features, other
- other.untrusted?.should be_true
- end
- end
-
it "clears caches of the given module" do
parent = Class.new do
def bar; :bar; end
diff --git a/spec/ruby/core/module/prepend_spec.rb b/spec/ruby/core/module/prepend_spec.rb
index 04cc27d472..976b09b105 100644
--- a/spec/ruby/core/module/prepend_spec.rb
+++ b/spec/ruby/core/module/prepend_spec.rb
@@ -499,7 +499,7 @@ describe "Module#prepend" do
c.dup.new.should be_kind_of(m)
end
- ruby_version_is '0'...'3.0' do
+ ruby_version_is ''...'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) }
@@ -611,6 +611,18 @@ describe "Module#prepend" do
ScratchPad.recorded.should == [[:prepend_features, c], [:prepended, c]]
end
+ it "prepends a module if it is included in a super class" do
+ module ModuleSpecs::M3
+ module M; end
+ class A; include M; end
+ class B < A; prepend M; end
+
+ all = [A, B, M]
+
+ (B.ancestors.filter { |a| all.include?(a) }).should == [M, B, A, M]
+ end
+ end
+
it "detects cyclic prepends" do
-> {
module ModuleSpecs::P
diff --git a/spec/ruby/core/module/private_class_method_spec.rb b/spec/ruby/core/module/private_class_method_spec.rb
index e35b50d986..407779cccc 100644
--- a/spec/ruby/core/module/private_class_method_spec.rb
+++ b/spec/ruby/core/module/private_class_method_spec.rb
@@ -78,4 +78,16 @@ describe "Module#private_class_method" do
end
end.should raise_error(NameError)
end
+
+ ruby_version_is "3.0" do
+ context "when single argument is passed and is an array" do
+ it "sets the visibility of the given methods to private" do
+ c = Class.new do
+ def self.foo() "foo" end
+ private_class_method [:foo]
+ end
+ -> { c.foo }.should raise_error(NoMethodError)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/module/private_spec.rb b/spec/ruby/core/module/private_spec.rb
index e893c24f38..ead806637c 100644
--- a/spec/ruby/core/module/private_spec.rb
+++ b/spec/ruby/core/module/private_spec.rb
@@ -38,11 +38,25 @@ describe "Module#private" do
:module_specs_public_method_on_object_for_kernel_private)
end
- it "returns self" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- private(:foo).should equal(self)
- private.should equal(self)
+ ruby_version_is ""..."3.1" do
+ it "returns self" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ private(:foo).should equal(self)
+ private.should equal(self)
+ end
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "returns argument or arguments if given" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ private(:foo).should equal(:foo)
+ private([:foo, :foo]).should == [:foo, :foo]
+ private(:foo, :foo).should == [:foo, :foo]
+ private.should equal(nil)
+ end
end
end
diff --git a/spec/ruby/core/module/protected_spec.rb b/spec/ruby/core/module/protected_spec.rb
index aa04a42fb8..058d49d751 100644
--- a/spec/ruby/core/module/protected_spec.rb
+++ b/spec/ruby/core/module/protected_spec.rb
@@ -39,11 +39,25 @@ describe "Module#protected" do
:module_specs_public_method_on_object_for_kernel_protected)
end
- it "returns self" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- protected(:foo).should equal(self)
- protected.should equal(self)
+ ruby_version_is ""..."3.1" do
+ it "returns self" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ protected(:foo).should equal(self)
+ protected.should equal(self)
+ end
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "returns argument or arguments if given" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ protected(:foo).should equal(:foo)
+ protected([:foo, :foo]).should == [:foo, :foo]
+ protected(:foo, :foo).should == [:foo, :foo]
+ protected.should equal(nil)
+ end
end
end
diff --git a/spec/ruby/core/module/public_class_method_spec.rb b/spec/ruby/core/module/public_class_method_spec.rb
index c09cc64863..b5d76e7b7a 100644
--- a/spec/ruby/core/module/public_class_method_spec.rb
+++ b/spec/ruby/core/module/public_class_method_spec.rb
@@ -77,4 +77,20 @@ describe "Module#public_class_method" do
end
end.should raise_error(NameError)
end
+
+ ruby_version_is "3.0" do
+ context "when single argument is passed and is an array" do
+ it "makes a class method public" do
+ c = Class.new do
+ class << self
+ private
+ def foo() "foo" end
+ end
+ public_class_method [:foo]
+ end
+
+ c.foo.should == "foo"
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/module/public_spec.rb b/spec/ruby/core/module/public_spec.rb
index e7059f6aa6..e3b183f228 100644
--- a/spec/ruby/core/module/public_spec.rb
+++ b/spec/ruby/core/module/public_spec.rb
@@ -27,12 +27,25 @@ describe "Module#public" do
:module_specs_private_method_on_object_for_kernel_public)
end
- it "returns self" do
- (class << Object.new; self; end).class_eval do
- def foo; end
- private :foo
- public(:foo).should equal(self)
- public.should equal(self)
+ ruby_version_is ""..."3.1" do
+ it "returns self" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ public(:foo).should equal(self)
+ public.should equal(self)
+ end
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "returns argument or arguments if given" do
+ (class << Object.new; self; end).class_eval do
+ def foo; end
+ public(:foo).should equal(:foo)
+ public([:foo, :foo]).should == [:foo, :foo]
+ public(:foo, :foo).should == [:foo, :foo]
+ public.should equal(nil)
+ end
end
end
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index e3b7fde049..841900cf87 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -243,28 +243,30 @@ 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
+ ruby_version_is ""..."3.2" do
+ it "looks in the included modules for builtin methods" do
+ result = ruby_exe(<<-RUBY)
+ a = Module.new do
+ def /(other) quo(other) end
+ end
- refinement = Module.new do
- refine Integer do
- include a
+ refinement = Module.new do
+ refine Integer do
+ include a
+ end
end
- end
- result = nil
- Module.new do
- using refinement
- result = 1 / 2
- end
+ result = nil
+ Module.new do
+ using refinement
+ result = 1 / 2
+ end
- print result.class
- RUBY
+ print result.class
+ RUBY
- result.should == 'Rational'
+ result.should == 'Rational'
+ end
end
it "looks in later included modules of the refined module first" do
@@ -298,63 +300,65 @@ describe "Module#refine" do
result.should == "foo from IncludeMeLater"
end
- it "looks in prepended modules from the refinement first" do
- refined_class = ModuleSpecs.build_refined_class
+ ruby_version_is ""..."3.1" do
+ it "looks in prepended modules from the refinement first" do
+ refined_class = ModuleSpecs.build_refined_class
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
- prepend ModuleSpecs::PrependedModule
+ refinement = Module.new do
+ refine refined_class do
+ include ModuleSpecs::IncludedModule
+ prepend ModuleSpecs::PrependedModule
- def foo; "foo from refinement"; end
+ def foo; "foo from refinement"; end
+ end
end
- end
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
+ end
+
+ result.should == "foo from prepended module"
end
- result.should == "foo from prepended module"
- end
+ it "looks in refinement then" do
+ refined_class = ModuleSpecs.build_refined_class
- it "looks in refinement then" do
- refined_class = ModuleSpecs.build_refined_class
+ refinement = Module.new do
+ refine(refined_class) do
+ include ModuleSpecs::IncludedModule
- refinement = Module.new do
- refine(refined_class) do
- include ModuleSpecs::IncludedModule
+ def foo; "foo from refinement"; end
+ end
+ end
- def foo; "foo from refinement"; end
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
end
- end
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
+ result.should == "foo from refinement"
end
- result.should == "foo from refinement"
- end
+ it "looks in included modules from the refinement then" do
+ refined_class = ModuleSpecs.build_refined_class
- it "looks in included modules from the refinement then" do
- refined_class = ModuleSpecs.build_refined_class
+ refinement = Module.new do
+ refine refined_class do
+ include ModuleSpecs::IncludedModule
+ end
+ end
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
end
- end
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
+ result.should == "foo from included module"
end
-
- result.should == "foo from included module"
end
it "looks in the class then" do
@@ -514,115 +518,55 @@ describe "Module#refine" do
result.should == "hello from refinement"
end
- ruby_version_is "" ... "2.7" do
- it "is not honored by Kernel#method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
+ it "is honored by Kernel#method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
-
- -> {
- Module.new do
- using refinement
- klass.new.method(:foo)
- end
- }.should raise_error(NameError, /undefined method `foo'/)
end
- end
-
- ruby_version_is "2.7" do
- it "is honored by Kernel#method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
- result = nil
- Module.new do
- using refinement
- result = klass.new.method(:foo).class
- end
-
- result.should == Method
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.method(:foo).class
end
- end
- ruby_version_is "" ... "2.7" do
- it "is not honored by Kernel#public_method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
-
- -> {
- Module.new do
- using refinement
- klass.new.public_method(:foo)
- end
- }.should raise_error(NameError, /undefined method `foo'/)
- end
+ result.should == Method
end
- ruby_version_is "2.7" do
- it "is honored by Kernel#public_method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = klass.new.public_method(:foo).class
+ it "is honored by Kernel#public_method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
-
- result.should == Method
end
- end
-
- ruby_version_is "" ... "2.7" do
- it "is not honored by Kernel#instance_method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
- -> {
- Module.new do
- using refinement
- klass.instance_method(:foo)
- end
- }.should raise_error(NameError, /undefined method `foo'/)
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.public_method(:foo).class
end
- end
- ruby_version_is "2.7" do
- it "is honored by Kernel#instance_method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
+ result.should == Method
+ end
- result = nil
- Module.new do
- using refinement
- result = klass.instance_method(:foo).class
+ it "is honored by Kernel#instance_method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
+ end
- result.should == UnboundMethod
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.instance_method(:foo).class
end
+
+ result.should == UnboundMethod
end
it "is honored by Kernel#respond_to?" do
@@ -662,26 +606,28 @@ describe "Module#refine" do
end
context "when super is called in a refinement" do
- it "looks in the included to refinery module" do
- refined_class = ModuleSpecs.build_refined_class
+ ruby_version_is ""..."3.1" do
+ it "looks in the included to refinery module" do
+ refined_class = ModuleSpecs.build_refined_class
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
+ refinement = Module.new do
+ refine refined_class do
+ include ModuleSpecs::IncludedModule
- def foo
- super
+ def foo
+ super
+ end
end
end
- end
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
- end
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
+ end
- result.should == "foo from included module"
+ result.should == "foo from included module"
+ end
end
it "looks in the refined class" do
@@ -704,55 +650,57 @@ describe "Module#refine" do
result.should == "foo"
end
- it "looks in the refined class from included module" do
- refined_class = ModuleSpecs.build_refined_class(for_super: true)
+ ruby_version_is ""..."3.1" do
+ it "looks in the refined class from included module" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
- a = Module.new do
- def foo
- [:A] + super
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
end
- end
- refinement = Module.new do
- refine refined_class do
- include a
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
end
- end
- result = nil
- Module.new do
- using refinement
+ result = nil
+ Module.new do
+ using refinement
- result = refined_class.new.foo
- end
+ result = refined_class.new.foo
+ end
- result.should == [:A, :C]
- 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)
+ 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
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
end
- end
- refinement = Module.new do
- refine refined_class do
- include a
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
end
- end
- result = nil
- Module.new do
- using refinement
+ result = nil
+ Module.new do
+ using refinement
- result = subclass.new.foo
- end
+ result = subclass.new.foo
+ end
- result.should == [:A, :C]
+ result.should == [:A, :C]
+ end
end
# super in a method of a refinement invokes the method in the refined
@@ -816,175 +764,177 @@ describe "Module#refine" do
end
end
- it "does't have access to active refinements for C from included module" do
- refined_class = ModuleSpecs.build_refined_class
+ ruby_version_is ""..."3.1" do
+ it "does't have access to active refinements for C from included module" do
+ refined_class = ModuleSpecs.build_refined_class
- a = Module.new do
- def foo
- super + bar
+ a = Module.new do
+ def foo
+ super + bar
+ end
end
- end
- refinement = Module.new do
- refine refined_class do
- include a
+ refinement = Module.new do
+ refine refined_class do
+ include a
- def bar
- "bar is not seen from A methods"
+ def bar
+ "bar is not seen from A methods"
+ end
end
end
- end
- Module.new do
- using refinement
- -> {
- refined_class.new.foo
- }.should raise_error(NameError) { |e| e.name.should == :bar }
+ Module.new do
+ using refinement
+ -> {
+ refined_class.new.foo
+ }.should raise_error(NameError) { |e| e.name.should == :bar }
+ end
end
- end
- it "does't have access to other active refinements from included module" do
- refined_class = ModuleSpecs.build_refined_class
+ 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"
+ refinement_integer = Module.new do
+ refine Integer do
+ def bar
+ "bar is not seen from A methods"
+ end
end
end
- end
- a = Module.new do
- def foo
- super + 1.bar
+ a = Module.new do
+ def foo
+ super + 1.bar
+ end
end
- end
- refinement = Module.new do
- refine refined_class do
- include a
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
end
- end
- Module.new do
- using refinement
- using refinement_integer
- -> {
- refined_class.new.foo
- }.should raise_error(NameError) { |e| e.name.should == :bar }
+ Module.new do
+ using refinement
+ using refinement_integer
+ -> {
+ refined_class.new.foo
+ }.should raise_error(NameError) { |e| e.name.should == :bar }
+ end
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)
+ # 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
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
end
- end
- b = Module.new do
- def foo
- [:B] + super
+ b = Module.new do
+ def foo
+ [:B] + super
+ end
end
- end
- refinement_a = Module.new do
- refine refined_class do
- include a
+ refinement_a = Module.new do
+ refine refined_class do
+ include a
+ end
end
- end
- refinement_b = Module.new do
- refine refined_class do
- include b
+ refinement_b = Module.new do
+ refine refined_class do
+ include b
+ end
end
- end
- result = nil
- Module.new do
- using refinement_a
- using refinement_b
- result = refined_class.new.foo
+ result = nil
+ Module.new do
+ using refinement_a
+ using refinement_b
+ result = refined_class.new.foo
+ end
+
+ result.should == [:B, :A, :C]
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)
- 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
- a = Module.new do
- def foo
- [:A] + super
+ b = Module.new do
+ def foo
+ [:B] + super
+ end
end
- end
- b = Module.new do
- def foo
- [:B] + super
+ refinement = Module.new do
+ refine refined_class do
+ def foo
+ [:LAST] + super
+ end
+ end
end
- end
- refinement = Module.new do
- refine refined_class do
- def foo
- [:LAST] + super
+ refinement_a_b = Module.new do
+ refine refined_class do
+ include a
+ include b
end
end
- end
- refinement_a_b = Module.new do
- refine refined_class do
- include a
- include b
+ result = nil
+ Module.new do
+ using refinement
+ using refinement_a_b
+ result = refined_class.new.foo
end
- end
- result = nil
- Module.new do
- using refinement
- using refinement_a_b
- result = refined_class.new.foo
+ result.should == [:B, :A, :LAST, :C]
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)
- 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
- refinement_local = Module.new do
- refine refined_class do
def foo
- [:LOCAL] + super
+ [:A] + super
end
end
- end
- a = Module.new do
- using refinement_local
-
- def foo
- [:A] + super
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
end
- end
- refinement = Module.new do
- refine refined_class do
- include a
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
end
- end
- result = nil
- Module.new do
- using refinement
- result = refined_class.new.foo
+ result.should == [:A, :LOCAL, :C]
end
-
- result.should == [:A, :LOCAL, :C]
end
end
diff --git a/spec/ruby/core/module/ruby2_keywords_spec.rb b/spec/ruby/core/module/ruby2_keywords_spec.rb
index 34c45cb1bc..80a99e2624 100644
--- a/spec/ruby/core/module/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/module/ruby2_keywords_spec.rb
@@ -1,112 +1,319 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "2.7" do
- describe "Module#ruby2_keywords" do
- it "marks the final hash argument as keyword hash" do
- obj = Object.new
+describe "Module#ruby2_keywords" do
+ class << self
+ ruby2_keywords def mark(*args)
+ args
+ end
+ end
- obj.singleton_class.class_exec do
- def foo(*a) a.last end
- ruby2_keywords :foo
+ it "marks the final hash argument as keyword hash" do
+ last = mark(1, 2, a: "a").last
+ Hash.ruby2_keywords_hash?(last).should == true
+ end
+
+ it "makes a copy of the hash and only marks the copy as keyword hash" do
+ obj = Object.new
+ obj.singleton_class.class_exec do
+ def regular(*args)
+ args.last
end
+ end
- last = obj.foo(1, 2, a: "a")
- Hash.ruby2_keywords_hash?(last).should == true
+ h = {a: 1}
+ ruby_version_is "3.0" do
+ obj.regular(**h).should.equal?(h)
end
- ruby_version_is "2.7" ... "3.0" do
- it "fixes delegation warnings when calling a method accepting keywords" do
- obj = Object.new
+ last = mark(**h).last
+ Hash.ruby2_keywords_hash?(last).should == true
+ Hash.ruby2_keywords_hash?(h).should == false
- obj.singleton_class.class_exec do
- def foo(*a) bar(*a) end
- def bar(*a, **b) end
- end
+ last2 = mark(**last).last # last is already marked
+ Hash.ruby2_keywords_hash?(last2).should == true
+ Hash.ruby2_keywords_hash?(last).should == true
+ last2.should_not.equal?(last)
+ Hash.ruby2_keywords_hash?(h).should == false
+ end
- -> { obj.foo(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
+ it "makes a copy and unmark the Hash when calling a method taking (arg)" do
+ obj = Object.new
+ obj.singleton_class.class_exec do
+ def single(arg)
+ arg
+ end
+ end
- obj.singleton_class.class_exec do
- ruby2_keywords :foo
- end
+ h = { a: 1 }
+ args = mark(**h)
+ marked = args.last
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ after_usage = obj.single(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+ end
- -> { obj.foo(1, 2, {a: "a"}) }.should_not complain
+ it "makes a copy and unmark the Hash when calling a method taking (**kw)" do
+ obj = Object.new
+ obj.singleton_class.class_exec do
+ def kwargs(**kw)
+ kw
end
end
- it "returns nil" do
- obj = Object.new
+ h = { a: 1 }
+ args = mark(**h)
+ marked = args.last
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ after_usage = obj.kwargs(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+ end
+ ruby_version_is "3.2" do
+ it "makes a copy and unmark the Hash when calling a method taking (*args)" do
+ obj = Object.new
obj.singleton_class.class_exec do
- def foo(*a) end
+ def splat(*args)
+ args.last
+ end
- ruby2_keywords(:foo).should == nil
+ def splat1(arg, *args)
+ args.last
+ end
+
+ def proc_call(*args)
+ -> *a { a.last }.call(*args)
+ end
end
+
+ h = { a: 1 }
+ args = mark(**h)
+ marked = args.last
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ after_usage = obj.splat(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(1, **h)
+ marked = args.last
+ after_usage = obj.splat1(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.proc_call(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.send(:splat, *args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
end
+ end
- it "raises NameError when passed not existing method name" do
+ ruby_version_is ""..."3.2" do
+ # https://bugs.ruby-lang.org/issues/18625
+ it "does NOT copy the Hash when calling a method taking (*args)" do
obj = Object.new
+ obj.singleton_class.class_exec do
+ def splat(*args)
+ args.last
+ end
+
+ def splat1(arg, *args)
+ args.last
+ end
- -> {
- obj.singleton_class.class_exec do
- ruby2_keywords :not_existing
+ def proc_call(*args)
+ -> *a { a.last }.call(*args)
end
- }.should raise_error(NameError, /undefined method `not_existing'/)
+ end
+
+ h = { a: 1 }
+ args = mark(**h)
+ marked = args.last
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ after_usage = obj.splat(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
+ Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(1, **h)
+ marked = args.last
+ after_usage = obj.splat1(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
+ Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.proc_call(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
+ Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.send(:splat, *args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ send_copies = RUBY_ENGINE == "ruby" # inconsistent with Proc#call above for CRuby
+ after_usage.equal?(marked).should == !send_copies
+ Hash.ruby2_keywords_hash?(after_usage).should == !send_copies
+ Hash.ruby2_keywords_hash?(marked).should == true
end
+ end
+
+ it "applies to the underlying method and applies across aliasing" do
+ obj = Object.new
+
+ obj.singleton_class.class_exec do
+ def foo(*a) a.last end
+ alias_method :bar, :foo
+ ruby2_keywords :foo
+
+ def baz(*a) a.last end
+ ruby2_keywords :baz
+ alias_method :bob, :baz
+ end
+
+ last = obj.foo(1, 2, a: "a")
+ Hash.ruby2_keywords_hash?(last).should == true
+
+ last = obj.bar(1, 2, a: "a")
+ Hash.ruby2_keywords_hash?(last).should == true
- it "acceps String as well" do
+ last = obj.baz(1, 2, a: "a")
+ Hash.ruby2_keywords_hash?(last).should == true
+
+ last = obj.bob(1, 2, a: "a")
+ Hash.ruby2_keywords_hash?(last).should == true
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "fixes delegation warnings when calling a method accepting keywords" do
obj = Object.new
obj.singleton_class.class_exec do
- def foo(*a) a.last end
- ruby2_keywords "foo"
+ def foo(*a) bar(*a) end
+ def bar(*a, **b) end
end
- last = obj.foo(1, 2, a: "a")
- Hash.ruby2_keywords_hash?(last).should == true
- end
+ -> { obj.foo(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
- it "raises TypeError when passed not Symbol or String" do
- obj = Object.new
+ obj.singleton_class.class_exec do
+ ruby2_keywords :foo
+ end
- -> {
- obj.singleton_class.class_exec do
- ruby2_keywords Object.new
- end
- }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { obj.foo(1, 2, {a: "a"}) }.should_not complain
end
+ end
- it "prints warning when a method does not accept argument splat" do
- obj = Object.new
- def obj.foo(a, b, c) end
+ it "returns nil" do
+ obj = Object.new
- -> {
- obj.singleton_class.class_exec do
- ruby2_keywords :foo
- end
- }.should complain(/Skipping set of ruby2_keywords flag for/)
+ obj.singleton_class.class_exec do
+ def foo(*a) end
+
+ ruby2_keywords(:foo).should == nil
end
+ end
- it "prints warning when a method accepts keywords" do
- obj = Object.new
- def obj.foo(a:, b:) end
+ it "raises NameError when passed not existing method name" do
+ obj = Object.new
- -> {
- obj.singleton_class.class_exec do
- ruby2_keywords :foo
- end
- }.should complain(/Skipping set of ruby2_keywords flag for/)
- end
+ -> {
+ obj.singleton_class.class_exec do
+ ruby2_keywords :not_existing
+ end
+ }.should raise_error(NameError, /undefined method `not_existing'/)
+ end
- it "prints warning when a method accepts keyword splat" do
- obj = Object.new
- def obj.foo(**a) end
+ it "accepts String as well" do
+ obj = Object.new
- -> {
- obj.singleton_class.class_exec do
- ruby2_keywords :foo
- end
- }.should complain(/Skipping set of ruby2_keywords flag for/)
+ obj.singleton_class.class_exec do
+ def foo(*a) a.last end
+ ruby2_keywords "foo"
end
+
+ last = obj.foo(1, 2, a: "a")
+ Hash.ruby2_keywords_hash?(last).should == true
+ end
+
+ it "raises TypeError when passed not Symbol or String" do
+ obj = Object.new
+
+ -> {
+ obj.singleton_class.class_exec do
+ ruby2_keywords Object.new
+ end
+ }.should raise_error(TypeError, /is not a symbol nor a string/)
+ end
+
+ it "prints warning when a method does not accept argument splat" do
+ obj = Object.new
+ def obj.foo(a, b, c) end
+
+ -> {
+ obj.singleton_class.class_exec do
+ ruby2_keywords :foo
+ end
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
+
+ it "prints warning when a method accepts keywords" do
+ obj = Object.new
+ def obj.foo(a:, b:) end
+
+ -> {
+ obj.singleton_class.class_exec do
+ ruby2_keywords :foo
+ end
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
+
+ it "prints warning when a method accepts keyword splat" do
+ obj = Object.new
+ def obj.foo(**a) end
+
+ -> {
+ obj.singleton_class.class_exec do
+ ruby2_keywords :foo
+ end
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
end
end
diff --git a/spec/ruby/core/module/shared/class_eval.rb b/spec/ruby/core/module/shared/class_eval.rb
index 224078ae54..9ef7b5be44 100644
--- a/spec/ruby/core/module/shared/class_eval.rb
+++ b/spec/ruby/core/module/shared/class_eval.rb
@@ -55,40 +55,49 @@ describe :module_class_eval, shared: true do
it "converts a non-string filename to a string using to_str" do
(file = mock(__FILE__)).should_receive(:to_str).and_return(__FILE__)
ModuleSpecs.send(@method, "1+1", file)
+
+ (file = mock(__FILE__)).should_receive(:to_str).and_return(__FILE__)
+ ModuleSpecs.send(@method, "1+1", file, 15)
end
it "raises a TypeError when the given filename can't be converted to string using to_str" do
(file = mock('123')).should_receive(:to_str).and_return(123)
- -> { ModuleSpecs.send(@method, "1+1", file) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, "1+1", file) }.should raise_error(TypeError, /can't convert MockObject to String/)
end
it "converts non string eval-string to string using to_str" do
(o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
ModuleSpecs.send(@method, o).should == 2
+
+ (o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
+ ModuleSpecs.send(@method, o, "file.rb").should == 2
+
+ (o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
+ ModuleSpecs.send(@method, o, "file.rb", 15).should == 2
end
it "raises a TypeError when the given eval-string can't be converted to string using to_str" do
o = mock('x')
- -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError, "no implicit conversion of MockObject into String")
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError, /can't convert MockObject to String/)
end
it "raises an ArgumentError when no arguments and no block are given" do
- -> { ModuleSpecs.send(@method) }.should raise_error(ArgumentError)
+ -> { ModuleSpecs.send(@method) }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1..3)")
end
it "raises an ArgumentError when more than 3 arguments are given" do
-> {
ModuleSpecs.send(@method, "1 + 1", "some file", 0, "bogus")
- }.should raise_error(ArgumentError)
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "raises an ArgumentError when a block and normal arguments are given" do
-> {
ModuleSpecs.send(@method, "1 + 1") { 1 + 1 }
- }.should raise_error(ArgumentError)
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 1, expected 0)")
end
# This case was found because Rubinius was caching the compiled
diff --git a/spec/ruby/core/nil/match_spec.rb b/spec/ruby/core/nil/match_spec.rb
index 2e2b5d1c1b..bc1c591793 100644
--- a/spec/ruby/core/nil/match_spec.rb
+++ b/spec/ruby/core/nil/match_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "NilClass#=~" do
it "returns nil matching any object" do
- o = Object.new
+ o = nil
suppress_warning do
(o =~ /Object/).should be_nil
diff --git a/spec/ruby/core/nil/to_s_spec.rb b/spec/ruby/core/nil/to_s_spec.rb
index 283d26477a..fa0b929677 100644
--- a/spec/ruby/core/nil/to_s_spec.rb
+++ b/spec/ruby/core/nil/to_s_spec.rb
@@ -5,13 +5,11 @@ describe "NilClass#to_s" do
nil.to_s.should == ""
end
- ruby_version_is "2.7" do
- it "returns a frozen string" do
- nil.to_s.should.frozen?
- end
+ it "returns a frozen string" do
+ nil.to_s.should.frozen?
+ end
- it "always returns the same string" do
- nil.to_s.should equal(nil.to_s)
- end
+ it "always returns the same string" do
+ nil.to_s.should equal(nil.to_s)
end
end
diff --git a/spec/ruby/core/numeric/clone_spec.rb b/spec/ruby/core/numeric/clone_spec.rb
index e3bf0a9e7c..c3b06ca0c9 100644
--- a/spec/ruby/core/numeric/clone_spec.rb
+++ b/spec/ruby/core/numeric/clone_spec.rb
@@ -22,4 +22,11 @@ describe "Numeric#clone" do
it "raises ArgumentError if passed freeze: false" do
-> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/)
end
+
+ ruby_version_is "3.0" do
+ it "does not change frozen status if passed freeze: nil" do
+ value = 1
+ value.clone(freeze: nil).should equal(value)
+ end
+ end
end
diff --git a/spec/ruby/core/numeric/quo_spec.rb b/spec/ruby/core/numeric/quo_spec.rb
index 5c952b11a9..67bacee9b5 100644
--- a/spec/ruby/core/numeric/quo_spec.rb
+++ b/spec/ruby/core/numeric/quo_spec.rb
@@ -20,7 +20,7 @@ describe "Numeric#quo" do
-> { 10.quo(0) }.should raise_error(ZeroDivisionError)
-> { -10.quo(0) }.should raise_error(ZeroDivisionError)
-> { bignum_value.quo(0) }.should raise_error(ZeroDivisionError)
- -> { -bignum_value.quo(0) }.should raise_error(ZeroDivisionError)
+ -> { (-bignum_value).quo(0) }.should raise_error(ZeroDivisionError)
end
it "calls #to_r to convert the object to a Rational" do
@@ -52,4 +52,13 @@ describe "Numeric#quo" do
obj.quo(19).should == 1.quo(20)
end
+
+ it "raises a ZeroDivisionError if the given argument is zero and not a Float" do
+ -> { 1.quo(0) }.should raise_error(ZeroDivisionError)
+ end
+
+ it "returns infinity if the given argument is zero and is a Float" do
+ (1.quo(0.0)).to_s.should == 'Infinity'
+ (-1.quo(0.0)).to_s.should == '-Infinity'
+ end
end
diff --git a/spec/ruby/core/numeric/shared/step.rb b/spec/ruby/core/numeric/shared/step.rb
index a4fe74f9db..8b1a7bf307 100644
--- a/spec/ruby/core/numeric/shared/step.rb
+++ b/spec/ruby/core/numeric/shared/step.rb
@@ -256,7 +256,6 @@ describe :numeric_step, :shared => true do
end
describe "when no block is given" do
- step_enum_class = Enumerator
step_enum_class = Enumerator::ArithmeticSequence
ruby_version_is ""..."3.0" do
diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb
index 03af8b0e4d..095c474fec 100644
--- a/spec/ruby/core/numeric/step_spec.rb
+++ b/spec/ruby/core/numeric/step_spec.rb
@@ -21,7 +21,6 @@ describe "Numeric#step" do
it_behaves_like :numeric_step, :step
describe "when no block is given" do
- step_enum_class = Enumerator
step_enum_class = Enumerator::ArithmeticSequence
ruby_version_is ""..."3.0" do
@@ -61,7 +60,6 @@ describe "Numeric#step" do
end
end
end
-
end
describe 'with keyword arguments' do
diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb
index 281785b0a4..d9db027e0b 100644
--- a/spec/ruby/core/objectspace/define_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb
@@ -169,4 +169,26 @@ describe "ObjectSpace.define_finalizer" do
ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"]
end
+
+ ruby_version_is "3.1" do
+ describe "when $VERBOSE is not nil" do
+ it "warns if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should include("warning: Exception in finalizer", "finalizing")
+ end
+ end
+
+ describe "when $VERBOSE is nil" do
+ it "does not warn even if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
+
+ ruby_exe(code, args: "2>&1", options: "-W0").should == ""
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/objectspace/garbage_collect_spec.rb b/spec/ruby/core/objectspace/garbage_collect_spec.rb
index 1aec3ea072..521eaa8785 100644
--- a/spec/ruby/core/objectspace/garbage_collect_spec.rb
+++ b/spec/ruby/core/objectspace/garbage_collect_spec.rb
@@ -6,8 +6,8 @@ describe "ObjectSpace.garbage_collect" do
-> { ObjectSpace.garbage_collect }.should_not raise_error
end
- it "doesn't accept any arguments" do
- -> { ObjectSpace.garbage_collect(1) }.should raise_error(ArgumentError)
+ it "accepts keyword arguments" do
+ ObjectSpace.garbage_collect(full_mark: true, immediate_sweep: true).should == nil
end
it "ignores the supplied block" do
diff --git a/spec/ruby/core/objectspace/weakmap/element_set_spec.rb b/spec/ruby/core/objectspace/weakmap/element_set_spec.rb
index 2b53650148..8588877158 100644
--- a/spec/ruby/core/objectspace/weakmap/element_set_spec.rb
+++ b/spec/ruby/core/objectspace/weakmap/element_set_spec.rb
@@ -17,45 +17,22 @@ describe "ObjectSpace::WeakMap#[]=" do
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)
+ 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)
+ 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
+ y = Object.new.freeze
+ should_accept(map, x, y)
+ should_accept(map, y, x)
end
end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/include.rb b/spec/ruby/core/objectspace/weakmap/shared/include.rb
index f9c174b6d1..1770eeac8b 100644
--- a/spec/ruby/core/objectspace/weakmap/shared/include.rb
+++ b/spec/ruby/core/objectspace/weakmap/shared/include.rb
@@ -20,15 +20,11 @@ describe :weakmap_include?, shared: true do
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
+ 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
diff --git a/spec/ruby/core/proc/block_pass_spec.rb b/spec/ruby/core/proc/block_pass_spec.rb
index 99255139d4..411c0bf3db 100644
--- a/spec/ruby/core/proc/block_pass_spec.rb
+++ b/spec/ruby/core/proc/block_pass_spec.rb
@@ -19,25 +19,3 @@ describe "Proc as a block pass argument" do
p.should == p2
end
end
-
-ruby_version_is ""..."2.7" do
- describe "Proc as an implicit block pass argument" do
- def revivify
- Proc.new
- end
-
- it "remains the same object if re-vivified by the target method" do
- p = Proc.new {}
- p2 = revivify(&p)
- p.should equal p2
- p.should == p2
- end
-
- it "remains the same object if reconstructed with Proc.new" do
- p = Proc.new {}
- p2 = Proc.new(&p)
- p.should equal p2
- p.should == p2
- end
- end
-end
diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb
index 803a32af7b..94814d11bc 100644
--- a/spec/ruby/core/proc/compose_spec.rb
+++ b/spec/ruby/core/proc/compose_spec.rb
@@ -61,9 +61,17 @@ describe "Proc#<<" do
g = proc { |x| x + x }
lambda_proc = -> x { x }
+ # lambda << proc
(f << g).is_a?(Proc).should == true
(f << g).should_not.lambda?
+
+ # lambda << lambda
+ (f << lambda_proc).is_a?(Proc).should == true
(f << lambda_proc).should.lambda?
+
+ # proc << lambda
+ (g << f).is_a?(Proc).should == true
+ (g << f).should.lambda?
end
end
diff --git a/spec/ruby/core/proc/eql_spec.rb b/spec/ruby/core/proc/eql_spec.rb
index 5f38af72d9..06aee272e5 100644
--- a/spec/ruby/core/proc/eql_spec.rb
+++ b/spec/ruby/core/proc/eql_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/equal'
describe "Proc#eql?" do
- ruby_version_is "0"..."3.0" do
+ ruby_version_is ""..."3.0" do
it_behaves_like :proc_equal_undefined, :eql?
end
diff --git a/spec/ruby/core/proc/equal_value_spec.rb b/spec/ruby/core/proc/equal_value_spec.rb
index 4c336331d7..ee88c0537d 100644
--- a/spec/ruby/core/proc/equal_value_spec.rb
+++ b/spec/ruby/core/proc/equal_value_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/equal'
describe "Proc#==" do
- ruby_version_is "0"..."3.0" do
+ ruby_version_is ""..."3.0" do
it_behaves_like :proc_equal_undefined, :==
end
diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb
index 6d5eb67a4b..cb52e94f44 100644
--- a/spec/ruby/core/proc/new_spec.rb
+++ b/spec/ruby/core/proc/new_spec.rb
@@ -94,20 +94,6 @@ describe "Proc.new with an associated block" do
obj.first.should == :a
obj.second.should == 2
end
-
- ruby_version_is ""..."2.7" do
- it "returns a new Proc instance from the block passed to the containing method" do
- prc = ProcSpecs.new_proc_in_method { "hello" }
- prc.should be_an_instance_of(Proc)
- prc.call.should == "hello"
- end
-
- it "returns a new Proc instance from the block passed to the containing method" do
- prc = ProcSpecs.new_proc_subclass_in_method { "hello" }
- prc.should be_an_instance_of(ProcSpecs::ProcSubclass)
- prc.call.should == "hello"
- end
- end
end
describe "Proc.new with a block argument" do
@@ -180,30 +166,7 @@ describe "Proc.new without a block" do
-> { ProcSpecs.new_proc_subclass_in_method }.should raise_error(ArgumentError)
end
- ruby_version_is ""..."2.7" do
- it "uses the implicit block from an enclosing method" do
- def some_method
- Proc.new
- end
-
- prc = some_method { "hello" }
-
- prc.call.should == "hello"
- end
-
- it "uses the implicit block from an enclosing method when called inside a block" do
- def some_method
- proc do |&block|
- Proc.new
- end.call { "failing" }
- end
- prc = some_method { "hello" }
-
- prc.call.should == "hello"
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."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
diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb
index 5fb5cf418d..3a56b613cd 100644
--- a/spec/ruby/core/proc/parameters_spec.rb
+++ b/spec/ruby/core/proc/parameters_spec.rb
@@ -20,6 +20,21 @@ describe "Proc#parameters" do
proc {|x| }.parameters.first.first.should == :opt
end
+ ruby_version_is "3.2" do
+ it "sets the first element of each sub-Array to :req if argument would be required if a lambda if lambda keyword used" do
+ proc {|x| }.parameters(lambda: true).first.first.should == :req
+ proc {|y,*x| }.parameters(lambda: true).first.first.should == :req
+ end
+
+ it "regards named parameters in procs as required if lambda keyword used" do
+ proc {|x| }.parameters(lambda: true).first.first.should == :req
+ end
+
+ it "regards named parameters in lambda as optional if lambda: false keyword used" do
+ -> x { }.parameters(lambda: false).first.first.should == :opt
+ end
+ end
+
it "regards optional keyword parameters in procs as optional" do
proc {|x: :y| }.parameters.first.first.should == :key
end
@@ -80,8 +95,16 @@ describe "Proc#parameters" do
-> x {}.parameters.should == [[:req, :x]]
end
- it "adds nameless rest arg for \"star\" argument" do
- -> x, * {}.parameters.should == [[:req, :x], [:rest]]
+ ruby_version_is '3.2' do
+ it "adds * rest arg for \"star\" argument" do
+ -> x, * {}.parameters.should == [[:req, :x], [:rest, :*]]
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it "adds nameless rest arg for \"star\" argument" do
+ -> x, * {}.parameters.should == [[:req, :x], [:rest]]
+ end
end
it "does not add locals as block options with a block and splat" do
diff --git a/spec/ruby/core/proc/ruby2_keywords_spec.rb b/spec/ruby/core/proc/ruby2_keywords_spec.rb
index 4f6bc151b6..c6eb03e693 100644
--- a/spec/ruby/core/proc/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/proc/ruby2_keywords_spec.rb
@@ -1,64 +1,78 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "Proc#ruby2_keywords" do
- it "marks the final hash argument as keyword hash" do
- f = -> *a { a.last }
- f.ruby2_keywords
+describe "Proc#ruby2_keywords" do
+ it "marks the final hash argument as keyword hash" do
+ f = -> *a { a.last }
+ f.ruby2_keywords
- last = f.call(1, 2, a: "a")
- Hash.ruby2_keywords_hash?(last).should == true
- end
+ last = f.call(1, 2, a: "a")
+ Hash.ruby2_keywords_hash?(last).should == true
+ end
- ruby_version_is "2.7" ... "3.0" do
- it "fixes delegation warnings when calling a method accepting keywords" do
- obj = Object.new
- def obj.foo(*a, **b) end
+ it "applies to the underlying method and applies across duplication" do
+ f1 = -> *a { a.last }
+ f1.ruby2_keywords
+ f2 = f1.dup
- f = -> *a { obj.foo(*a) }
+ Hash.ruby2_keywords_hash?(f1.call(1, 2, a: "a")).should == true
+ Hash.ruby2_keywords_hash?(f2.call(1, 2, a: "a")).should == true
- -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
- f.ruby2_keywords
- -> { f.call(1, 2, {a: "a"}) }.should_not complain
- end
+ f3 = -> *a { a.last }
+ f4 = f3.dup
+ f3.ruby2_keywords
- it "fixes delegation warnings when calling a proc accepting keywords" do
- g = -> *a, **b { }
- f = -> *a { g.call(*a) }
+ Hash.ruby2_keywords_hash?(f3.call(1, 2, a: "a")).should == true
+ Hash.ruby2_keywords_hash?(f4.call(1, 2, a: "a")).should == true
+ end
- -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
- f.ruby2_keywords
- -> { f.call(1, 2, {a: "a"}) }.should_not complain
- end
- end
+ ruby_version_is ""..."3.0" do
+ it "fixes delegation warnings when calling a method accepting keywords" do
+ obj = Object.new
+ def obj.foo(*a, **b) end
- it "returns self" do
- f = -> *a { }
- f.ruby2_keywords.should equal f
+ f = -> *a { obj.foo(*a) }
+
+ -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
+ f.ruby2_keywords
+ -> { f.call(1, 2, {a: "a"}) }.should_not complain
end
- it "prints warning when a proc does not accept argument splat" do
- f = -> a, b, c { }
+ it "fixes delegation warnings when calling a proc accepting keywords" do
+ g = -> *a, **b { }
+ f = -> *a { g.call(*a) }
- -> {
- f.ruby2_keywords
- }.should complain(/Skipping set of ruby2_keywords flag for/)
+ -> { f.call(1, 2, {a: "a"}) }.should complain(/Using the last argument as keyword parameters is deprecated/)
+ f.ruby2_keywords
+ -> { f.call(1, 2, {a: "a"}) }.should_not complain
end
+ end
+
+ it "returns self" do
+ f = -> *a { }
+ f.ruby2_keywords.should equal f
+ end
- it "prints warning when a proc accepts keywords" do
- f = -> a:, b: { }
+ it "prints warning when a proc does not accept argument splat" do
+ f = -> a, b, c { }
- -> {
- f.ruby2_keywords
- }.should complain(/Skipping set of ruby2_keywords flag for/)
- end
+ -> {
+ f.ruby2_keywords
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
- it "prints warning when a proc accepts keyword splat" do
- f = -> **a { }
+ it "prints warning when a proc accepts keywords" do
+ f = -> a:, b: { }
- -> {
- f.ruby2_keywords
- }.should complain(/Skipping set of ruby2_keywords flag for/)
- end
+ -> {
+ f.ruby2_keywords
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
+
+ it "prints warning when a proc accepts keyword splat" do
+ f = -> **a { }
+
+ -> {
+ f.ruby2_keywords
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
end
end
diff --git a/spec/ruby/core/proc/shared/compose.rb b/spec/ruby/core/proc/shared/compose.rb
index e3ae7f76b8..3d3f3b310d 100644
--- a/spec/ruby/core/proc/shared/compose.rb
+++ b/spec/ruby/core/proc/shared/compose.rb
@@ -1,47 +1,22 @@
describe :proc_compose, shared: true do
- ruby_version_is ""..."2.7" do
- it "raises NoMethodError when called if passed not callable object" do
- not_callable = Object.new
- composed = @object.call.send(@method, not_callable)
+ it "raises TypeError if passed not callable object" do
+ lhs = @object.call
+ not_callable = Object.new
- -> {
- composed.call('a')
- }.should raise_error(NoMethodError, /undefined method `call' for/)
+ -> {
+ lhs.send(@method, not_callable)
+ }.should raise_error(TypeError, "callable object is expected")
- end
-
- it "when called does not try to coerce argument with #to_proc" do
- succ = Object.new
- def succ.to_proc(s); s.succ; end
-
- composed = @object.call.send(@method, succ)
-
- -> {
- composed.call('a')
- }.should raise_error(NoMethodError, /undefined method `call' for/)
- end
end
- ruby_version_is "2.7" do # https://bugs.ruby-lang.org/issues/15428
- it "raises TypeError if passed not callable object" do
- lhs = @object.call
- not_callable = Object.new
-
- -> {
- lhs.send(@method, not_callable)
- }.should raise_error(TypeError, "callable object is expected")
-
- end
-
- it "does not try to coerce argument with #to_proc" do
- lhs = @object.call
+ it "does not try to coerce argument with #to_proc" do
+ lhs = @object.call
- succ = Object.new
- def succ.to_proc(s); s.succ; end
+ succ = Object.new
+ def succ.to_proc(s); s.succ; end
- -> {
- lhs.send(@method, succ)
- }.should raise_error(TypeError, "callable object is expected")
- end
+ -> {
+ lhs.send(@method, succ)
+ }.should raise_error(TypeError, "callable object is expected")
end
end
diff --git a/spec/ruby/core/proc/shared/to_s.rb b/spec/ruby/core/proc/shared/to_s.rb
index 7f167a3d9d..f1e2f416fc 100644
--- a/spec/ruby/core/proc/shared/to_s.rb
+++ b/spec/ruby/core/proc/shared/to_s.rb
@@ -1,9 +1,7 @@
describe :proc_to_s, shared: true do
- sep = ruby_version_is("2.7") ? " " : "@"
-
describe "for a proc created with Proc.new" do
it "returns a description including file and line number" do
- Proc.new { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{__LINE__ }>$/
+ Proc.new { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ }>$/
end
it "has a binary encoding" do
@@ -13,7 +11,7 @@ describe :proc_to_s, shared: true do
describe "for a proc created with lambda" do
it "returns a description including '(lambda)' and including file and line number" do
- -> { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{__LINE__ } \(lambda\)>$/
+ -> { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ } \(lambda\)>$/
end
it "has a binary encoding" do
@@ -23,7 +21,7 @@ describe :proc_to_s, shared: true do
describe "for a proc created with proc" do
it "returns a description including file and line number" do
- proc { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{__LINE__ }>$/
+ proc { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ }>$/
end
it "has a binary encoding" do
@@ -36,7 +34,7 @@ describe :proc_to_s, shared: true do
def hello; end
s = method("hello").to_proc.send(@method)
if s.include? __FILE__
- s.should =~ /^#<Proc:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{__LINE__ - 3} \(lambda\)>$/
+ s.should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ - 3} \(lambda\)>$/
else
s.should =~ /^#<Proc:([^ ]*?) \(lambda\)>$/
end
diff --git a/spec/ruby/core/process/_fork_spec.rb b/spec/ruby/core/process/_fork_spec.rb
new file mode 100644
index 0000000000..6f711ad2dd
--- /dev/null
+++ b/spec/ruby/core/process/_fork_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "Process._fork" do
+ it "for #respond_to? returns the same as Process.respond_to?(:fork)" do
+ Process.respond_to?(:_fork).should == Process.respond_to?(:fork)
+ end
+
+ guard_not -> { Process.respond_to?(:fork) } do
+ it "raises a NotImplementedError when called" do
+ -> { Process._fork }.should raise_error(NotImplementedError)
+ end
+ end
+
+ guard -> { Process.respond_to?(:fork) } do
+ it "is called by Process#fork" do
+ Process.should_receive(:_fork).once.and_return(42)
+
+ pid = Process.fork {}
+ pid.should equal(42)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/process/clock_gettime_spec.rb b/spec/ruby/core/process/clock_gettime_spec.rb
index 59e1406e02..6c1a52f21e 100644
--- a/spec/ruby/core/process/clock_gettime_spec.rb
+++ b/spec/ruby/core/process/clock_gettime_spec.rb
@@ -52,7 +52,7 @@ describe "Process.clock_gettime" do
end
# These specs need macOS 10.12+ / darwin 16+
- guard_not -> { platform_is_not(:darwin) or RUBY_PLATFORM[/darwin\d+/].to_i >= 16 } do
+ guard -> { platform_is_not(:darwin) or kernel_version_is '16' } do
platform_is :linux, :openbsd, :darwin do
it "CLOCK_PROCESS_CPUTIME_ID" do
Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID).should be_an_instance_of(Float)
@@ -65,20 +65,6 @@ describe "Process.clock_gettime" do
end
end
- platform_is :freebsd, :openbsd do
- it "CLOCK_VIRTUAL" do
- Process.clock_gettime(Process::CLOCK_VIRTUAL).should be_an_instance_of(Float)
- end
-
- it "CLOCK_PROF" do
- Process.clock_gettime(Process::CLOCK_PROF).should be_an_instance_of(Float)
- end
-
- it "CLOCK_UPTIME" do
- Process.clock_gettime(Process::CLOCK_UPTIME).should be_an_instance_of(Float)
- end
- end
-
platform_is :linux, :darwin do
it "CLOCK_MONOTONIC_RAW" do
Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW).should be_an_instance_of(Float)
@@ -95,42 +81,71 @@ describe "Process.clock_gettime" do
Process.clock_gettime(Process::CLOCK_UPTIME_RAW_APPROX).should be_an_instance_of(Float)
end
end
+ end
- platform_is :freebsd do
- it "CLOCK_REALTIME_FAST and CLOCK_REALTIME_PRECISE" do
- Process.clock_gettime(Process::CLOCK_REALTIME_FAST).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_REALTIME_PRECISE).should be_an_instance_of(Float)
- end
+ platform_is :freebsd do
+ it "CLOCK_VIRTUAL" do
+ Process.clock_gettime(Process::CLOCK_VIRTUAL).should be_an_instance_of(Float)
+ end
- it "CLOCK_MONOTONIC_FAST and CLOCK_MONOTONIC_PRECISE" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC_FAST).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_MONOTONIC_PRECISE).should be_an_instance_of(Float)
- end
+ it "CLOCK_PROF" do
+ Process.clock_gettime(Process::CLOCK_PROF).should be_an_instance_of(Float)
+ end
+ end
- it "CLOCK_UPTIME_FAST and CLOCK_UPTIME_PRECISE" do
- Process.clock_gettime(Process::CLOCK_UPTIME_FAST).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_UPTIME_PRECISE).should be_an_instance_of(Float)
- end
+ platform_is :freebsd, :openbsd do
+ it "CLOCK_UPTIME" do
+ Process.clock_gettime(Process::CLOCK_UPTIME).should be_an_instance_of(Float)
+ end
+ end
- it "CLOCK_SECOND" do
- Process.clock_gettime(Process::CLOCK_SECOND).should be_an_instance_of(Float)
- end
+ platform_is :freebsd do
+ it "CLOCK_REALTIME_FAST and CLOCK_REALTIME_PRECISE" do
+ Process.clock_gettime(Process::CLOCK_REALTIME_FAST).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_REALTIME_PRECISE).should be_an_instance_of(Float)
end
- platform_is :linux do
- it "CLOCK_REALTIME_COARSE and CLOCK_REALTIME_ALARM" do
- Process.clock_gettime(Process::CLOCK_REALTIME_COARSE).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_REALTIME_ALARM).should be_an_instance_of(Float)
- end
+ it "CLOCK_MONOTONIC_FAST and CLOCK_MONOTONIC_PRECISE" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_FAST).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_PRECISE).should be_an_instance_of(Float)
+ end
- it "CLOCK_MONOTONIC_COARSE" do
- Process.clock_gettime(Process::CLOCK_MONOTONIC_COARSE).should be_an_instance_of(Float)
- end
+ it "CLOCK_UPTIME_FAST and CLOCK_UPTIME_PRECISE" do
+ Process.clock_gettime(Process::CLOCK_UPTIME_FAST).should be_an_instance_of(Float)
+ Process.clock_gettime(Process::CLOCK_UPTIME_PRECISE).should be_an_instance_of(Float)
+ end
- it "CLOCK_BOOTTIME and CLOCK_BOOTTIME_ALARM" do
- Process.clock_gettime(Process::CLOCK_BOOTTIME).should be_an_instance_of(Float)
- Process.clock_gettime(Process::CLOCK_BOOTTIME_ALARM).should be_an_instance_of(Float)
- end
+ it "CLOCK_SECOND" do
+ Process.clock_gettime(Process::CLOCK_SECOND).should be_an_instance_of(Float)
+ end
+ end
+
+ guard -> { platform_is :linux and kernel_version_is '2.6.32' } do
+ it "CLOCK_REALTIME_COARSE" do
+ Process.clock_gettime(Process::CLOCK_REALTIME_COARSE).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_MONOTONIC_COARSE" do
+ Process.clock_gettime(Process::CLOCK_MONOTONIC_COARSE).should be_an_instance_of(Float)
+ end
+ end
+
+ guard -> { platform_is :linux and kernel_version_is '2.6.39' } do
+ it "CLOCK_BOOTTIME" do
+ skip "No Process::CLOCK_BOOTTIME" unless defined?(Process::CLOCK_BOOTTIME)
+ Process.clock_gettime(Process::CLOCK_BOOTTIME).should be_an_instance_of(Float)
+ end
+ end
+
+ guard -> { platform_is "x86_64-linux" and kernel_version_is '3.0' } do
+ it "CLOCK_REALTIME_ALARM" do
+ skip "No Process::CLOCK_REALTIME_ALARM" unless defined?(Process::CLOCK_REALTIME_ALARM)
+ Process.clock_gettime(Process::CLOCK_REALTIME_ALARM).should be_an_instance_of(Float)
+ end
+
+ it "CLOCK_BOOTTIME_ALARM" do
+ skip "No Process::CLOCK_BOOTTIME_ALARM" unless defined?(Process::CLOCK_BOOTTIME_ALARM)
+ Process.clock_gettime(Process::CLOCK_BOOTTIME_ALARM).should be_an_instance_of(Float)
end
end
end
diff --git a/spec/ruby/core/process/constants_spec.rb b/spec/ruby/core/process/constants_spec.rb
index b61f5ab64e..4130bb58a5 100644
--- a/spec/ruby/core/process/constants_spec.rb
+++ b/spec/ruby/core/process/constants_spec.rb
@@ -1,3 +1,4 @@
+require_relative '../../spec_helper'
describe "Process::Constants" do
platform_is :darwin, :netbsd, :freebsd do
diff --git a/spec/ruby/core/process/daemon_spec.rb b/spec/ruby/core/process/daemon_spec.rb
index 70ffd1b320..20b0d743b9 100644
--- a/spec/ruby/core/process/daemon_spec.rb
+++ b/spec/ruby/core/process/daemon_spec.rb
@@ -2,6 +2,9 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
platform_is_not :windows do
+ # macOS 15 is not working this examples
+ return if /darwin/ =~ RUBY_PLATFORM && /15/ =~ `sw_vers -productVersion`
+
describe :process_daemon_keep_stdio_open_false, shared: true do
it "redirects stdout to /dev/null" do
@daemon.invoke("keep_stdio_open_false_stdout", @object).should == ""
diff --git a/spec/ruby/core/process/detach_spec.rb b/spec/ruby/core/process/detach_spec.rb
index 1c27ed9c2c..91661afcea 100644
--- a/spec/ruby/core/process/detach_spec.rb
+++ b/spec/ruby/core/process/detach_spec.rb
@@ -42,5 +42,34 @@ describe "Process.detach" do
thr.pid.should == pid
end
+
+ it "tolerates not existing child process pid" do
+ # ensure there is no child process with this hardcoded pid
+ # `kill 0 pid` for existing process returns "1" and raises Errno::ESRCH if process doesn't exist
+ -> { Process.kill(0, 100500) }.should raise_error(Errno::ESRCH)
+
+ thr = Process.detach(100500)
+ thr.join
+
+ thr.should be_kind_of(Thread)
+ end
+
+ it "calls #to_int to implicitly convert non-Integer pid to Integer" do
+ pid = MockObject.new('mock-enumerable')
+ pid.should_receive(:to_int).and_return(100500)
+
+ Process.detach(pid).join
+ end
+
+ it "raises TypeError when pid argument does not have #to_int method" do
+ -> { Process.detach(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
+ end
+
+ it "raises TypeError when #to_int returns non-Integer value" do
+ pid = MockObject.new('mock-enumerable')
+ pid.should_receive(:to_int).and_return(:symbol)
+
+ -> { Process.detach(pid) }.should raise_error(TypeError, "can't convert MockObject to Integer (MockObject#to_int gives Symbol)")
+ end
end
end
diff --git a/spec/ruby/core/process/egid_spec.rb b/spec/ruby/core/process/egid_spec.rb
index 24dda43804..a67b623d5c 100644
--- a/spec/ruby/core/process/egid_spec.rb
+++ b/spec/ruby/core/process/egid_spec.rb
@@ -15,5 +15,44 @@ describe "Process.egid" do
end
describe "Process.egid=" do
- it "needs to be reviewed for spec completeness"
+
+ platform_is_not :windows do
+ it "raises TypeError if not passed an Integer or String" do
+ -> { Process.egid = Object.new }.should raise_error(TypeError)
+ end
+
+ it "sets the effective group id to its own gid if given the username corresponding to its own gid" do
+ raise unless Process.gid == Process.egid
+
+ require "etc"
+ group = Etc.getgrgid(Process.gid).name
+
+ Process.egid = group
+ Process.egid.should == Process.gid
+ end
+
+ as_user do
+ it "raises Errno::ERPERM if run by a non superuser trying to set the root group id" do
+ -> { Process.egid = 0 }.should raise_error(Errno::EPERM)
+ end
+
+ platform_is :linux do
+ it "raises Errno::ERPERM if run by a non superuser trying to set the group id from group name" do
+ -> { Process.egid = "root" }.should raise_error(Errno::EPERM)
+ end
+ end
+ end
+
+ as_superuser do
+ context "when ran by a superuser" do
+ it "sets the effective group id for the current process if run by a superuser" do
+ code = <<-RUBY
+ Process.egid = 1
+ puts Process.egid
+ RUBY
+ ruby_exe(code).should == "1\n"
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/euid_spec.rb b/spec/ruby/core/process/euid_spec.rb
index a2f1bbf42e..c1ec4171d0 100644
--- a/spec/ruby/core/process/euid_spec.rb
+++ b/spec/ruby/core/process/euid_spec.rb
@@ -21,9 +21,19 @@ describe "Process.euid=" do
-> { Process.euid = Object.new }.should raise_error(TypeError)
end
+ it "sets the effective user id to its own uid if given the username corresponding to its own uid" do
+ raise unless Process.uid == Process.euid
+
+ require "etc"
+ user = Etc.getpwuid(Process.uid).name
+
+ Process.euid = user
+ Process.euid.should == Process.uid
+ end
+
as_user do
it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id" do
- -> { (Process.euid = 0)}.should raise_error(Errno::EPERM)
+ -> { Process.euid = 0 }.should raise_error(Errno::EPERM)
end
it "raises Errno::ERPERM if run by a non superuser trying to set the superuser id from username" do
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index 56e02ff38a..c8a58c4d04 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -212,6 +212,26 @@ describe "Process.spawn" do
end.should output_to_fd("nil\n")
end
+ platform_is_not :windows do
+ it "uses the passed env['PATH'] to search the executable" do
+ dir = tmp("spawn_path_dir")
+ mkdir_p dir
+ begin
+ exe = 'process-spawn-executable-in-path'
+ path = "#{dir}/#{exe}"
+ File.write(path, "#!/bin/sh\necho $1")
+ File.chmod(0755, path)
+
+ env = { "PATH" => "#{dir}#{File::PATH_SEPARATOR}#{ENV['PATH']}" }
+ Process.wait Process.spawn(env, exe, 'OK', out: @name)
+ $?.should.success?
+ File.read(@name).should == "OK\n"
+ ensure
+ rm_r dir
+ end
+ end
+ end
+
it "calls #to_hash to convert the environment" do
o = mock("to_hash")
o.should_receive(:to_hash).and_return({"FOO" => "BAR"})
@@ -329,7 +349,7 @@ describe "Process.spawn" do
pgid = Process.getpgid(Process.pid)
# The process group is not available on all platforms.
# See "man proc" - /proc/[pid]/stat - (5) pgrp
- # In Travis arm64 environment, the value is 0.
+ # In Travis aarch64 environment, the value is 0.
#
# $ cat /proc/[pid]/stat
# 19179 (ruby) S 19160 0 0 ...
@@ -457,6 +477,16 @@ describe "Process.spawn" do
# redirection
+ it 'redirects to the wrapped IO using wrapped_io.to_io if out: wrapped_io' do
+ File.open(@name, 'w') do |file|
+ -> do
+ wrapped_io = mock('wrapped IO')
+ wrapped_io.should_receive(:to_io).and_return(file)
+ Process.wait Process.spawn('echo Hello World', out: wrapped_io)
+ end.should output_to_fd("Hello World\n", file)
+ end
+ end
+
it "redirects STDOUT to the given file descriptor if out: Integer" do
File.open(@name, 'w') do |file|
-> do
@@ -547,6 +577,24 @@ describe "Process.spawn" do
end
end
+ platform_is_not :windows do
+ it "redirects non-default file descriptor to itself" do
+ File.open(@name, 'w') do |file|
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{file.fileno}, 'w'); f.print(:bang); f.flush"), file.fileno => file.fileno)
+ end.should output_to_fd("bang", file)
+ end
+ end
+ end
+
+ it "redirects default file descriptor to itself" do
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{STDOUT.fileno}, 'w'); f.print(:bang); f.flush"), STDOUT.fileno => STDOUT.fileno)
+ end.should output_to_fd("bang", STDOUT)
+ end
+
# :close_others
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/equal_value_spec.rb b/spec/ruby/core/process/status/equal_value_spec.rb
index d85bb22214..d8a2be26b8 100644
--- a/spec/ruby/core/process/status/equal_value_spec.rb
+++ b/spec/ruby/core/process/status/equal_value_spec.rb
@@ -8,7 +8,7 @@ describe "Process::Status#==" do
end
it "returns true when compared to the integer status of a terminated child" do
- ruby_exe("Process.kill(:KILL, $$); exit(29)", exit_status: platform_is(:windows) ? 0 : nil)
+ ruby_exe("Process.kill(:KILL, $$); exit(29)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
$?.to_i.should == $?
$?.should == $?.to_i
end
diff --git a/spec/ruby/core/process/status/exited_spec.rb b/spec/ruby/core/process/status/exited_spec.rb
index 059cd5b1aa..a61292b146 100644
--- a/spec/ruby/core/process/status/exited_spec.rb
+++ b/spec/ruby/core/process/status/exited_spec.rb
@@ -14,7 +14,7 @@ describe "Process::Status#exited?" do
describe "for a terminated child" do
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil)
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/exitstatus_spec.rb b/spec/ruby/core/process/status/exitstatus_spec.rb
index 3087bd619e..5c86c2b3c8 100644
--- a/spec/ruby/core/process/status/exitstatus_spec.rb
+++ b/spec/ruby/core/process/status/exitstatus_spec.rb
@@ -11,7 +11,7 @@ describe "Process::Status#exitstatus" do
describe "for a child that raised SignalException" do
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil)
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/signaled_spec.rb b/spec/ruby/core/process/status/signaled_spec.rb
index 389092a533..c0de7b8006 100644
--- a/spec/ruby/core/process/status/signaled_spec.rb
+++ b/spec/ruby/core/process/status/signaled_spec.rb
@@ -13,7 +13,7 @@ describe "Process::Status#signaled?" do
describe "for a terminated child" do
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil)
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/success_spec.rb b/spec/ruby/core/process/status/success_spec.rb
index c531121f08..3589cc611f 100644
--- a/spec/ruby/core/process/status/success_spec.rb
+++ b/spec/ruby/core/process/status/success_spec.rb
@@ -23,7 +23,7 @@ describe "Process::Status#success?" do
describe "for a child that was terminated" do
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil)
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/termsig_spec.rb b/spec/ruby/core/process/status/termsig_spec.rb
index 1c87a6f455..5d286950f8 100644
--- a/spec/ruby/core/process/status/termsig_spec.rb
+++ b/spec/ruby/core/process/status/termsig_spec.rb
@@ -13,7 +13,7 @@ describe "Process::Status#termsig" do
describe "for a child that raised SignalException" do
before :each do
- ruby_exe("raise SignalException, 'SIGTERM'", exit_status: nil)
+ ruby_exe("raise SignalException, 'SIGTERM'", exit_status: :SIGTERM)
end
platform_is_not :windows do
@@ -25,7 +25,7 @@ describe "Process::Status#termsig" do
describe "for a child that was sent a signal" do
before :each do
- ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : nil)
+ ruby_exe("Process.kill(:KILL, $$); exit(42)", exit_status: platform_is(:windows) ? 0 : :SIGKILL)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/status/to_i_spec.rb b/spec/ruby/core/process/status/to_i_spec.rb
index 7cde9b915b..39f8e2d84c 100644
--- a/spec/ruby/core/process/status/to_i_spec.rb
+++ b/spec/ruby/core/process/status/to_i_spec.rb
@@ -7,7 +7,7 @@ describe "Process::Status#to_i" do
end
it "returns an integer when the child is signaled" do
- ruby_exe('raise SignalException, "TERM"', exit_status: platform_is(:windows) ? 3 : nil)
+ ruby_exe('raise SignalException, "TERM"', exit_status: platform_is(:windows) ? 3 : :SIGTERM)
$?.to_i.should be_an_instance_of(Integer)
end
end
diff --git a/spec/ruby/core/process/times_spec.rb b/spec/ruby/core/process/times_spec.rb
index b47189a7e7..6142cd257c 100644
--- a/spec/ruby/core/process/times_spec.rb
+++ b/spec/ruby/core/process/times_spec.rb
@@ -5,12 +5,16 @@ describe "Process.times" do
Process.times.should be_kind_of(Process::Tms)
end
- it "returns current cpu times" do
- t = Process.times
- user = t.utime
+ # TODO: Intel C Compiler does not work this example
+ # http://rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20221013T030005Z.fail.html.gz
+ unless RbConfig::CONFIG['CC']&.include?("icx")
+ it "returns current cpu times" do
+ t = Process.times
+ user = t.utime
- 1 until Process.times.utime > user
- Process.times.utime.should > user
+ 1 until Process.times.utime > user
+ Process.times.utime.should > user
+ end
end
platform_is_not :windows do
diff --git a/spec/ruby/core/process/wait2_spec.rb b/spec/ruby/core/process/wait2_spec.rb
index 6eb7fc6d06..673d3cdb9d 100644
--- a/spec/ruby/core/process/wait2_spec.rb
+++ b/spec/ruby/core/process/wait2_spec.rb
@@ -33,4 +33,13 @@ describe "Process.wait2" do
-> { Process.wait2 }.should raise_error(Errno::ECHILD)
-> { Process.wait2 }.should raise_error(StandardError)
end
+
+ it "returns nil if the child process is still running when given the WNOHANG flag" do
+ IO.popen(ruby_cmd('STDIN.getbyte'), "w") do |io|
+ pid, status = Process.wait2(io.pid, Process::WNOHANG)
+ pid.should be_nil
+ status.should be_nil
+ io.write('a')
+ end
+ end
end
diff --git a/spec/ruby/core/queue/initialize_spec.rb b/spec/ruby/core/queue/initialize_spec.rb
index 83c7e595fe..c45abcd29d 100644
--- a/spec/ruby/core/queue/initialize_spec.rb
+++ b/spec/ruby/core/queue/initialize_spec.rb
@@ -7,6 +7,10 @@ describe "Queue#initialize" do
q.should.empty?
end
+ it "is a private method" do
+ Queue.private_instance_methods.include?(:initialize).should == true
+ end
+
ruby_version_is '3.1' do
it "adds all elements of the passed Enumerable to self" do
q = Queue.new([1, 2, 3])
@@ -30,9 +34,16 @@ describe "Queue#initialize" do
q.should.empty?
end
- it "raises if the provided Enumerable does not respond to #to_a" do
+ it "raises TypeError if the provided Enumerable does not respond to #to_a" do
enumerable = MockObject.new('mock-enumerable')
-> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject into Array")
end
+
+ it "raises TypeError if #to_a does not return Array" do
+ enumerable = MockObject.new('mock-enumerable')
+ enumerable.should_receive(:to_a).and_return("string")
+
+ -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject to Array (MockObject#to_a gives String)")
+ end
end
end
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb
index 06e84d03bd..ed1b3a7b41 100644
--- a/spec/ruby/core/random/bytes_spec.rb
+++ b/spec/ruby/core/random/bytes_spec.rb
@@ -18,7 +18,7 @@ describe "Random#bytes" do
end
it "returns the same numeric output for a given huge seed across all implementations and platforms" do
- rnd = Random.new(bignum_value ** 4)
+ rnd = Random.new(2 ** (63 * 4))
rnd.bytes(2).should == "_\x91"
rnd.bytes(1000) # skip some
rnd.bytes(2).should == "\x17\x12"
diff --git a/spec/ruby/core/random/default_spec.rb b/spec/ruby/core/random/default_spec.rb
index a709eddd53..b4ffcb81f4 100644
--- a/spec/ruby/core/random/default_spec.rb
+++ b/spec/ruby/core/random/default_spec.rb
@@ -1,38 +1,45 @@
require_relative '../../spec_helper'
describe "Random::DEFAULT" do
+ ruby_version_is ''...'3.2' do
+ it "returns a random number generator" do
+ suppress_warning do
+ Random::DEFAULT.should respond_to(:rand)
+ end
+ end
- it "returns a random number generator" do
- suppress_warning do
- Random::DEFAULT.should respond_to(:rand)
+ 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
- ruby_version_is ''...'3.0' do
- it "returns a Random instance" do
- suppress_warning do
- Random::DEFAULT.should be_an_instance_of(Random)
+ 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
- end
- ruby_version_is '3.0' do
- it "refers to the Random class" do
- suppress_warning do
- Random::DEFAULT.should.equal?(Random)
+ ruby_version_is '3.0' do
+ it "refers to the Random class" do
+ suppress_warning do
+ Random::DEFAULT.should.equal?(Random)
+ end
end
- end
- it "is deprecated" do
- -> {
- Random::DEFAULT.should.equal?(Random)
- }.should complain(/constant Random::DEFAULT is deprecated/)
+ it "is deprecated" do
+ -> {
+ Random::DEFAULT.should.equal?(Random)
+ }.should complain(/constant Random::DEFAULT is deprecated/)
+ end
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
+ ruby_version_is '3.2' do
+ it "is no longer defined" do
+ Random.should_not.const_defined?(:DEFAULT)
+ end
end
end
diff --git a/spec/ruby/core/random/rand_spec.rb b/spec/ruby/core/random/rand_spec.rb
index 6ea7eece5f..9244177ab5 100644
--- a/spec/ruby/core/random/rand_spec.rb
+++ b/spec/ruby/core/random/rand_spec.rb
@@ -205,6 +205,11 @@ describe "Random#rand with Range" do
Random.new(42).rand(0..1.0).should be_kind_of(Float)
end
+ it "returns a float within a given float range" do
+ Random.new(42).rand(0.0...100.0).should == 37.454011884736246
+ Random.new(42).rand(-100.0...0.0).should == -62.545988115263754
+ end
+
it "raises an ArgumentError when the startpoint lacks #+ and #- methods" do
-> do
Random.new.rand(Object.new..67)
diff --git a/spec/ruby/core/random/raw_seed_spec.rb b/spec/ruby/core/random/raw_seed_spec.rb
deleted file mode 100644
index 0e40ed0796..0000000000
--- a/spec/ruby/core/random/raw_seed_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/urandom'
-
-describe "Random.urandom" do
- it_behaves_like :random_urandom, :urandom
-end
diff --git a/spec/ruby/core/random/shared/urandom.rb b/spec/ruby/core/random/shared/urandom.rb
deleted file mode 100644
index 159716075c..0000000000
--- a/spec/ruby/core/random/shared/urandom.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-describe :random_urandom, shared: true do
- it "returns a String" do
- Random.send(@method, 1).should be_an_instance_of(String)
- end
-
- it "returns a String of the length given as argument" do
- Random.send(@method, 15).length.should == 15
- end
-
- it "raises an ArgumentError on a negative size" do
- -> {
- Random.send(@method, -1)
- }.should raise_error(ArgumentError)
- end
-
- it "returns a binary String" do
- Random.send(@method, 15).encoding.should == Encoding::BINARY
- end
-
- it "returns a random binary String" do
- Random.send(@method, 12).should_not == Random.send(@method, 12)
- end
-end
diff --git a/spec/ruby/core/random/urandom_spec.rb b/spec/ruby/core/random/urandom_spec.rb
new file mode 100644
index 0000000000..6f180e54ac
--- /dev/null
+++ b/spec/ruby/core/random/urandom_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+describe "Random.urandom" do
+ it "returns a String" do
+ Random.urandom(1).should be_an_instance_of(String)
+ end
+
+ it "returns a String of the length given as argument" do
+ Random.urandom(15).length.should == 15
+ end
+
+ it "raises an ArgumentError on a negative size" do
+ -> {
+ Random.urandom(-1)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "returns a binary String" do
+ Random.urandom(15).encoding.should == Encoding::BINARY
+ end
+
+ it "returns a random binary String" do
+ Random.urandom(12).should_not == Random.urandom(12)
+ end
+end
diff --git a/spec/ruby/core/range/bsearch_spec.rb b/spec/ruby/core/range/bsearch_spec.rb
index 438c7ce314..9c93671d85 100644
--- a/spec/ruby/core/range/bsearch_spec.rb
+++ b/spec/ruby/core/range/bsearch_spec.rb
@@ -330,108 +330,106 @@ describe "Range#bsearch" do
end
- ruby_version_is "2.7" do
- context "with beginless ranges and Integer values" do
- context "with a block returning true or false" do
- it "returns the smallest element for which block returns true" do
- eval("(..10)").bsearch { |x| x >= 2 }.should == 2
- eval("(...-1)").bsearch { |x| x >= -10 }.should == -10
- end
- end
-
- context "with a block returning negative, zero, positive numbers" do
- it "returns nil if the block returns greater than zero for every element" do
- eval("(..0)").bsearch { |x| 1 }.should be_nil
- end
-
- it "returns nil if the block never returns zero" do
- eval("(..0)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
- end
-
- it "accepts Float::INFINITY from the block" do
- eval("(..0)").bsearch { |x| Float::INFINITY }.should be_nil
- end
-
- it "returns an element at an index for which block returns 0.0" do
- result = eval("(..10)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
- result.should == 2
- end
-
- it "returns an element at an index for which block returns 0" do
- result = eval("(...10)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- [1, 2, 3].should include(result)
- end
+ context "with beginless ranges and Integer values" do
+ context "with a block returning true or false" do
+ it "returns the smallest element for which block returns true" do
+ (..10).bsearch { |x| x >= 2 }.should == 2
+ (...-1).bsearch { |x| x >= -10 }.should == -10
+ end
+ end
+
+ context "with a block returning negative, zero, positive numbers" do
+ it "returns nil if the block returns greater than zero for every element" do
+ (..0).bsearch { |x| 1 }.should be_nil
+ end
+
+ it "returns nil if the block never returns zero" do
+ (..0).bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
+ end
+
+ it "accepts Float::INFINITY from the block" do
+ (..0).bsearch { |x| Float::INFINITY }.should be_nil
+ end
+
+ it "returns an element at an index for which block returns 0.0" do
+ result = (..10).bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
+ result.should == 2
+ end
+
+ it "returns an element at an index for which block returns 0" do
+ result = (...10).bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
+ [1, 2, 3].should include(result)
end
end
+ end
+
+ context "with beginless ranges and Float values" do
+ context "with a block returning true or false" do
+ it "returns nil if the block returns true for every element" do
+ (..-0.1).bsearch { |x| x > 0.0 }.should be_nil
+ (...-0.1).bsearch { |x| x > 0.0 }.should be_nil
+ end
+
+ it "returns nil if the block returns nil for every element" do
+ (..-0.1).bsearch { |x| nil }.should be_nil
+ (...-0.1).bsearch { |x| nil }.should be_nil
+ end
+
+ it "returns the smallest element for which block returns true" do
+ (..10).bsearch { |x| x >= 2 }.should == 2
+ (..10).bsearch { |x| x >= 1 }.should == 1
+ end
- context "with beginless ranges and Float values" do
- context "with a block returning true or false" do
- it "returns nil if the block returns true for every element" do
- eval("(..-0.1)").bsearch { |x| x > 0.0 }.should be_nil
- eval("(...-0.1)").bsearch { |x| x > 0.0 }.should be_nil
- end
-
- it "returns nil if the block returns nil for every element" do
- eval("(..-0.1)").bsearch { |x| nil }.should be_nil
- eval("(...-0.1)").bsearch { |x| nil }.should be_nil
- end
-
- it "returns the smallest element for which block returns true" do
- eval("(..10)").bsearch { |x| x >= 2 }.should == 2
- eval("(..10)").bsearch { |x| x >= 1 }.should == 1
- end
-
- it "works with infinity bounds" do
- inf = Float::INFINITY
- eval("(..inf)").bsearch { |x| true }.should == -inf
- eval("(...inf)").bsearch { |x| true }.should == -inf
- eval("(..-inf)").bsearch { |x| true }.should == -inf
- eval("(...-inf)").bsearch { |x| true }.should == nil
- end
- end
-
- context "with a block returning negative, zero, positive numbers" do
- it "returns nil if the block returns less than zero for every element" do
- eval("(..5.0)").bsearch { |x| -1 }.should be_nil
- eval("(...5.0)").bsearch { |x| -1 }.should be_nil
- end
-
- it "returns nil if the block returns greater than zero for every element" do
- eval("(..1.1)").bsearch { |x| 1 }.should be_nil
- eval("(...1.1)").bsearch { |x| 1 }.should be_nil
- end
-
- it "returns nil if the block never returns zero" do
- eval("(..6.3)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
- end
-
- it "accepts (+/-)Float::INFINITY from the block" do
- eval("(..5.0)").bsearch { |x| Float::INFINITY }.should be_nil
- eval("(..7.0)").bsearch { |x| -Float::INFINITY }.should be_nil
- end
-
- it "returns an element at an index for which block returns 0.0" do
- result = eval("(..8.0)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
- result.should == 2
- end
-
- it "returns an element at an index for which block returns 0" do
- result = eval("(..8.0)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
- result.should >= 1
- result.should <= 3
- end
-
- it "works with infinity bounds" do
- inf = Float::INFINITY
- eval("(..-inf)").bsearch { |x| 1 }.should == nil
- eval("(...-inf)").bsearch { |x| 1 }.should == nil
- eval("(..inf)").bsearch { |x| x == inf ? 0 : 1 }.should == inf
- eval("(...inf)").bsearch { |x| x == inf ? 0 : 1 }.should == nil
- eval("(..-inf)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf
- eval("(...-inf)").bsearch { |x| x == -inf ? 0 : -1 }.should == nil
- eval("(..inf)").bsearch { |x| 3 - x }.should == 3
- eval("(...inf)").bsearch { |x| 3 - x }.should == 3
- end
+ it "works with infinity bounds" do
+ inf = Float::INFINITY
+ (..inf).bsearch { |x| true }.should == -inf
+ (...inf).bsearch { |x| true }.should == -inf
+ (..-inf).bsearch { |x| true }.should == -inf
+ (...-inf).bsearch { |x| true }.should == nil
+ end
+ end
+
+ context "with a block returning negative, zero, positive numbers" do
+ it "returns nil if the block returns less than zero for every element" do
+ (..5.0).bsearch { |x| -1 }.should be_nil
+ (...5.0).bsearch { |x| -1 }.should be_nil
+ end
+
+ it "returns nil if the block returns greater than zero for every element" do
+ (..1.1).bsearch { |x| 1 }.should be_nil
+ (...1.1).bsearch { |x| 1 }.should be_nil
+ end
+
+ it "returns nil if the block never returns zero" do
+ (..6.3).bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
+ end
+
+ it "accepts (+/-)Float::INFINITY from the block" do
+ (..5.0).bsearch { |x| Float::INFINITY }.should be_nil
+ (..7.0).bsearch { |x| -Float::INFINITY }.should be_nil
+ end
+
+ it "returns an element at an index for which block returns 0.0" do
+ result = (..8.0).bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
+ result.should == 2
+ end
+
+ it "returns an element at an index for which block returns 0" do
+ result = (..8.0).bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
+ result.should >= 1
+ result.should <= 3
+ end
+
+ it "works with infinity bounds" do
+ inf = Float::INFINITY
+ (..-inf).bsearch { |x| 1 }.should == nil
+ (...-inf).bsearch { |x| 1 }.should == nil
+ (..inf).bsearch { |x| x == inf ? 0 : 1 }.should == inf
+ (...inf).bsearch { |x| x == inf ? 0 : 1 }.should == nil
+ (..-inf).bsearch { |x| x == -inf ? 0 : -1 }.should == -inf
+ (...-inf).bsearch { |x| x == -inf ? 0 : -1 }.should == nil
+ (..inf).bsearch { |x| 3 - x }.should == 3
+ (...inf).bsearch { |x| 3 - x }.should == 3
end
end
end
diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb
index e795026230..65878aaabe 100644
--- a/spec/ruby/core/range/case_compare_spec.rb
+++ b/spec/ruby/core/range/case_compare_spec.rb
@@ -8,8 +8,12 @@ describe "Range#===" do
(range === RangeSpecs::WithoutSucc.new(2)).should == true
end
- ruby_version_is "2.7" do
- it_behaves_like :range_cover_and_include, :===
- it_behaves_like :range_cover, :===
+ it_behaves_like :range_cover_and_include, :===
+ it_behaves_like :range_cover, :===
+
+ ruby_bug "#19533", "3.2"..."3.3" do
+ it "returns true on any value if begin and end are both nil" do
+ (nil..nil).should === 1
+ end
end
end
diff --git a/spec/ruby/core/range/clone_spec.rb b/spec/ruby/core/range/clone_spec.rb
new file mode 100644
index 0000000000..cf6ce74da0
--- /dev/null
+++ b/spec/ruby/core/range/clone_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+describe "Range#clone" do
+ it "duplicates the range" do
+ original = (1..3)
+ copy = original.clone
+ copy.begin.should == 1
+ copy.end.should == 3
+ copy.should_not.exclude_end?
+ copy.should_not.equal? original
+
+ original = ("a"..."z")
+ copy = original.clone
+ copy.begin.should == "a"
+ copy.end.should == "z"
+ copy.should.exclude_end?
+ copy.should_not.equal? original
+ end
+
+ it "maintains the frozen state" do
+ (1..2).clone.frozen?.should == (1..2).frozen?
+ (1..).clone.frozen?.should == (1..).frozen?
+ Range.new(1, 2).clone.frozen?.should == Range.new(1, 2).frozen?
+ Class.new(Range).new(1, 2).clone.frozen?.should == Class.new(Range).new(1, 2).frozen?
+ end
+end
diff --git a/spec/ruby/core/range/count_spec.rb b/spec/ruby/core/range/count_spec.rb
index f6f60fa054..24d4a9caf3 100644
--- a/spec/ruby/core/range/count_spec.rb
+++ b/spec/ruby/core/range/count_spec.rb
@@ -1,14 +1,12 @@
require_relative '../../spec_helper'
describe "Range#count" do
- ruby_version_is "2.7" do
- it "returns Infinity for beginless ranges without arguments or blocks" do
- inf = Float::INFINITY
- eval("('a'...)").count.should == inf
- eval("(7..)").count.should == inf
- eval("(...'a')").count.should == inf
- eval("(...nil)").count.should == inf
- eval("(..10.0)").count.should == inf
- end
+ it "returns Infinity for beginless ranges without arguments or blocks" do
+ inf = Float::INFINITY
+ eval("('a'...)").count.should == inf
+ eval("(7..)").count.should == inf
+ (...'a').count.should == inf
+ (...nil).count.should == inf
+ (..10.0).count.should == inf
end
end
diff --git a/spec/ruby/core/range/dup_spec.rb b/spec/ruby/core/range/dup_spec.rb
index 6c9d0c954a..fab3c3f1b2 100644
--- a/spec/ruby/core/range/dup_spec.rb
+++ b/spec/ruby/core/range/dup_spec.rb
@@ -2,14 +2,22 @@ require_relative '../../spec_helper'
describe "Range#dup" do
it "duplicates the range" do
- copy = (1..3).dup
+ original = (1..3)
+ copy = original.dup
copy.begin.should == 1
copy.end.should == 3
copy.should_not.exclude_end?
+ copy.should_not.equal?(original)
copy = ("a"..."z").dup
copy.begin.should == "a"
copy.end.should == "z"
copy.should.exclude_end?
end
+
+ it "creates an unfrozen range" do
+ (1..2).dup.should_not.frozen?
+ (1..).dup.should_not.frozen?
+ Range.new(1, 2).dup.should_not.frozen?
+ end
end
diff --git a/spec/ruby/core/range/each_spec.rb b/spec/ruby/core/range/each_spec.rb
index bd4bbb82e5..ecae17c881 100644
--- a/spec/ruby/core/range/each_spec.rb
+++ b/spec/ruby/core/range/each_spec.rb
@@ -58,10 +58,8 @@ describe "Range#each" do
a.should == ["A", "B", "C", "D"]
end
- ruby_version_is "2.7" do
- it "raises a TypeError beginless ranges" do
- -> { eval("(..2)").each { |x| x } }.should raise_error(TypeError)
- end
+ it "raises a TypeError beginless ranges" do
+ -> { (..2).each { |x| x } }.should raise_error(TypeError)
end
it "raises a TypeError if the first element does not respond to #succ" do
@@ -84,9 +82,27 @@ describe "Range#each" do
enum.to_a.should == [1, 2, 3]
end
- it "raises a TypeError if the first element is a Time object" do
- t = Time.now
- -> { (t..t+1).each { |i| i } }.should raise_error(TypeError)
+ ruby_version_is "3.1" do
+ it "supports Time objects that respond to #succ" do
+ t = Time.utc(1970)
+ def t.succ; self + 1 end
+ t_succ = t.succ
+ def t_succ.succ; self + 1; end
+
+ (t..t_succ).to_a.should == [Time.utc(1970), Time.utc(1970, nil, nil, nil, nil, 1)]
+ (t...t_succ).to_a.should == [Time.utc(1970)]
+ end
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "raises a TypeError if the first element is a Time object even if it responds to #succ" do
+ t = Time.utc(1970)
+ def t.succ; self + 1 end
+ t_succ = t.succ
+ def t_succ.succ; self + 1; end
+
+ -> { (t..t_succ).each { |i| i } }.should raise_error(TypeError)
+ end
end
it "passes each Symbol element by using #succ" do
diff --git a/spec/ruby/core/range/equal_value_spec.rb b/spec/ruby/core/range/equal_value_spec.rb
index 0aaebfb59a..83dcf5cec8 100644
--- a/spec/ruby/core/range/equal_value_spec.rb
+++ b/spec/ruby/core/range/equal_value_spec.rb
@@ -12,9 +12,7 @@ describe "Range#==" do
eval("(1.0..)").should == eval("(1.0..)")
end
- ruby_version_is "2.7" do
- it "returns true if the endpoints are == for beginless ranges" do
- eval("(...10)").should == eval("(...10)")
- end
+ it "returns true if the endpoints are == for beginless ranges" do
+ (...10).should == (...10)
end
end
diff --git a/spec/ruby/core/range/first_spec.rb b/spec/ruby/core/range/first_spec.rb
index c5c90800ac..2af935f439 100644
--- a/spec/ruby/core/range/first_spec.rb
+++ b/spec/ruby/core/range/first_spec.rb
@@ -47,9 +47,7 @@ describe "Range#first" do
-> { (2..3).first("1") }.should raise_error(TypeError)
end
- ruby_version_is "2.7" do
- it "raises a RangeError when called on an beginless range" do
- -> { eval("(..1)").first }.should raise_error(RangeError)
- end
+ it "raises a RangeError when called on an beginless range" do
+ -> { (..1).first }.should raise_error(RangeError)
end
end
diff --git a/spec/ruby/core/range/frozen_spec.rb b/spec/ruby/core/range/frozen_spec.rb
new file mode 100644
index 0000000000..298ffc87cb
--- /dev/null
+++ b/spec/ruby/core/range/frozen_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+# There is no Range#frozen? method but this feels like the best place for these specs
+describe "Range#frozen?" do
+ ruby_version_is "3.0" do
+ it "is true for literal ranges" do
+ (1..2).should.frozen?
+ (1..).should.frozen?
+ (..1).should.frozen?
+ end
+
+ it "is true for Range.new" do
+ Range.new(1, 2).should.frozen?
+ Range.new(1, nil).should.frozen?
+ Range.new(nil, 1).should.frozen?
+ end
+
+ it "is false for instances of a subclass of Range" do
+ sub_range = Class.new(Range).new(1, 2)
+ sub_range.should_not.frozen?
+ end
+
+ it "is false for Range.allocate" do
+ Range.allocate.should_not.frozen?
+ end
+ end
+end
diff --git a/spec/ruby/core/range/inspect_spec.rb b/spec/ruby/core/range/inspect_spec.rb
index f49882e6ce..072de123b7 100644
--- a/spec/ruby/core/range/inspect_spec.rb
+++ b/spec/ruby/core/range/inspect_spec.rb
@@ -17,29 +17,13 @@ describe "Range#inspect" do
eval("(0.1...)").inspect.should == "0.1..."
end
- ruby_version_is '2.7' do
- it "works for beginless ranges" do
- eval("(..1)").inspect.should == "..1"
- eval("(...0.1)").inspect.should == "...0.1"
- end
-
- it "works for nil ... nil ranges" do
- eval("(..nil)").inspect.should == "nil..nil"
- eval("(nil...)").inspect.should == "nil...nil"
- end
+ it "works for beginless ranges" do
+ (..1).inspect.should == "..1"
+ (...0.1).inspect.should == "...0.1"
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
- ("a"...("c".taint)).inspect.tainted?.should be_true
- ("a"..."c").taint.inspect.tainted?.should be_true
- end
-
- it "returns a untrusted string if either end is untrusted" do
- (("a".untrust)..."c").inspect.untrusted?.should be_true
- ("a"...("c".untrust)).inspect.untrusted?.should be_true
- ("a"..."c").untrust.inspect.untrusted?.should be_true
- end
+ it "works for nil ... nil ranges" do
+ (..nil).inspect.should == "nil..nil"
+ eval("(nil...)").inspect.should == "nil...nil"
end
end
diff --git a/spec/ruby/core/range/last_spec.rb b/spec/ruby/core/range/last_spec.rb
index d7ef776b42..6698686dd5 100644
--- a/spec/ruby/core/range/last_spec.rb
+++ b/spec/ruby/core/range/last_spec.rb
@@ -8,6 +8,12 @@ describe "Range#last" do
(1..5).last(3).should == [3, 4, 5]
end
+ ruby_bug '#18994', '2.7'...'3.2' do
+ it "returns the specified number if elements for single element inclusive range" do
+ (1..1).last(1).should == [1]
+ end
+ end
+
it "returns an empty array for an empty Range" do
(0...0).last(2).should == []
end
diff --git a/spec/ruby/core/range/max_spec.rb b/spec/ruby/core/range/max_spec.rb
index a970144d66..6c9ada2a3c 100644
--- a/spec/ruby/core/range/max_spec.rb
+++ b/spec/ruby/core/range/max_spec.rb
@@ -52,13 +52,13 @@ describe "Range#max" do
ruby_version_is "3.0" do
it "returns the end point for beginless ranges" do
- eval("(..1)").max.should == 1
- eval("(..1.0)").max.should == 1.0
+ (..1).max.should == 1
+ (..1.0).max.should == 1.0
end
it "raises for an exclusive beginless range" do
-> {
- eval("(...1)").max
+ (...1).max
}.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value')
end
end
@@ -97,9 +97,7 @@ describe "Range#max given a block" do
(5...5).max {|x,y| x <=> y}.should be_nil
end
- ruby_version_is "2.7" do
- it "raises RangeError when called with custom comparison method on an beginless range" do
- -> { eval("(..1)").max {|a, b| a} }.should raise_error(RangeError)
- end
+ it "raises RangeError when called with custom comparison method on an beginless range" do
+ -> { (..1).max {|a, b| a} }.should raise_error(RangeError)
end
end
diff --git a/spec/ruby/core/range/min_spec.rb b/spec/ruby/core/range/min_spec.rb
index 6e56cc733b..89310ee589 100644
--- a/spec/ruby/core/range/min_spec.rb
+++ b/spec/ruby/core/range/min_spec.rb
@@ -44,10 +44,8 @@ describe "Range#min" do
eval("(1.0...)").min.should == 1.0
end
- ruby_version_is "2.7" do
- it "raises RangeError when called on an beginless range" do
- -> { eval("(..1)").min }.should raise_error(RangeError)
- end
+ it "raises RangeError when called on an beginless range" do
+ -> { (..1).min }.should raise_error(RangeError)
end
end
diff --git a/spec/ruby/core/range/minmax_spec.rb b/spec/ruby/core/range/minmax_spec.rb
index 1db9bfce38..b2b4fd61a1 100644
--- a/spec/ruby/core/range/minmax_spec.rb
+++ b/spec/ruby/core/range/minmax_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
-# These specs use Range.new instead of the literal notation for beginless Ranges so they parse fine on Ruby < 2.7
describe 'Range#minmax' do
before(:each) do
@x = mock('x')
@@ -13,37 +12,26 @@ describe 'Range#minmax' do
end
describe 'on an inclusive range' do
- ruby_version_is ''...'2.7' do
- it 'should try to iterate endlessly on an endless range' do
- @x.should_receive(:succ).once.and_return(@y)
- range = (@x..)
-
- -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/)
- end
- end
-
- ruby_version_is '2.7' do
- it 'should raise RangeError on an endless range without iterating the range' do
- @x.should_not_receive(:succ)
+ it 'should raise RangeError on an endless range without iterating the range' do
+ @x.should_not_receive(:succ)
- range = (@x..)
+ range = (@x..)
- -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
- end
+ -> { 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
+ it 'raises RangeError or ArgumentError on a beginless range' do
+ range = (..@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
it 'should return beginning of range if beginning and end are equal without iterating the range' do
@@ -58,34 +46,22 @@ describe 'Range#minmax' do
(@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)
+ 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
+ (@x..@y).minmax.should == [@x, @y]
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
+ 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
+ (1..range_end).minmax.should == [1, range_end]
end
it 'should return the minimum and maximum values according to the provided block by iterating the range' do
@@ -96,33 +72,21 @@ describe 'Range#minmax' do
end
describe 'on an exclusive range' do
- ruby_version_is ''...'2.7' do
- # Endless ranges introduced in 2.6
- it 'should try to iterate endlessly on an endless range' do
- @x.should_receive(:succ).once.and_return(@y)
- range = (@x...)
+ it 'should raise RangeError on an endless range' do
+ @x.should_not_receive(:succ)
+ range = (@x...)
- -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/)
- end
+ -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
end
- ruby_version_is '2.7' do
- it 'should raise RangeError on an endless range' do
- @x.should_not_receive(:succ)
- range = (@x...)
+ it 'should raise RangeError on a beginless range' do
+ range = (...@x)
- -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
- end
-
- it 'should raise RangeError on a beginless range' do
- range = Range.new(nil, @x, true)
-
- -> { range.minmax }.should raise_error(RangeError,
- /cannot get the maximum of beginless range with custom comparison method|cannot get the minimum of beginless range/)
- end
+ -> { 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
- ruby_bug "#17014", "2.7.0"..."3.0" do
+ ruby_bug "#17014", ""..."3.0" do
it 'should return nil pair if beginning and end are equal without iterating the range' do
@x.should_not_receive(:succ)
@@ -146,19 +110,17 @@ describe 'Range#minmax' 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
+ 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
+ (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
+ 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
it 'should return the minimum and maximum values according to the provided block by iterating the range' do
diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb
index a4de4963e7..40df914b83 100644
--- a/spec/ruby/core/range/new_spec.rb
+++ b/spec/ruby/core/range/new_spec.rb
@@ -42,24 +42,16 @@ describe "Range.new" do
end
describe "beginless/endless range" do
- ruby_version_is ""..."2.7" do
- it "does not allow range without left boundary" do
- -> { Range.new(nil, 1) }.should raise_error(ArgumentError, /bad value for range/)
- end
+ it "allows beginless left boundary" do
+ range = Range.new(nil, 1)
+ range.begin.should == nil
end
- ruby_version_is "2.7" do
- it "allows beginless left boundary" do
- range = Range.new(nil, 1)
- range.begin.should == nil
- end
-
- it "distinguishes ranges with included and excluded right boundary" do
- range_exclude = Range.new(nil, 1, true)
- range_include = Range.new(nil, 1, false)
+ it "distinguishes ranges with included and excluded right boundary" do
+ range_exclude = Range.new(nil, 1, true)
+ range_include = Range.new(nil, 1, false)
- range_exclude.should_not == range_include
- end
+ range_exclude.should_not == range_include
end
it "allows endless right boundary" do
@@ -73,5 +65,15 @@ describe "Range.new" do
range_exclude.should_not == range_include
end
+
+ ruby_version_is "3.0" do
+ it "creates a frozen range if the class is Range.class" do
+ Range.new(1, 2).should.frozen?
+ end
+
+ it "does not create a frozen range if the class is not Range.class" do
+ Class.new(Range).new(1, 2).should_not.frozen?
+ end
+ end
end
end
diff --git a/spec/ruby/core/range/shared/cover.rb b/spec/ruby/core/range/shared/cover.rb
index f3c7d22668..0b41a26455 100644
--- a/spec/ruby/core/range/shared/cover.rb
+++ b/spec/ruby/core/range/shared/cover.rb
@@ -151,45 +151,43 @@ describe :range_cover_subrange, shared: true do
end
end
- ruby_version_is "2.7" do
- it "allows self to be a beginless range" do
- eval("(...10)").send(@method, (3..7)).should be_true
- eval("(...10)").send(@method, (3..15)).should be_false
+ it "allows self to be a beginless range" do
+ (...10).send(@method, (3..7)).should be_true
+ (...10).send(@method, (3..15)).should be_false
- eval("(..7.9)").send(@method, (2.5..6.5)).should be_true
- eval("(..7.9)").send(@method, (2.5..8.5)).should be_false
+ (..7.9).send(@method, (2.5..6.5)).should be_true
+ (..7.9).send(@method, (2.5..8.5)).should be_false
- eval("(..'i')").send(@method, ('d'..'f')).should be_true
- eval("(..'i')").send(@method, ('d'..'z')).should be_false
- end
+ (..'i').send(@method, ('d'..'f')).should be_true
+ (..'i').send(@method, ('d'..'z')).should be_false
+ end
- it "allows self to be a endless range" do
- eval("(0...)").send(@method, (3..7)).should be_true
- eval("(5...)").send(@method, (3..15)).should be_false
+ it "allows self to be a endless range" do
+ eval("(0...)").send(@method, (3..7)).should be_true
+ eval("(5...)").send(@method, (3..15)).should be_false
- eval("(1.1..)").send(@method, (2.5..6.5)).should be_true
- eval("(3.3..)").send(@method, (2.5..8.5)).should be_false
+ eval("(1.1..)").send(@method, (2.5..6.5)).should be_true
+ eval("(3.3..)").send(@method, (2.5..8.5)).should be_false
- eval("('a'..)").send(@method, ('d'..'f')).should be_true
- eval("('p'..)").send(@method, ('d'..'z')).should be_false
- end
+ eval("('a'..)").send(@method, ('d'..'f')).should be_true
+ eval("('p'..)").send(@method, ('d'..'z')).should be_false
+ end
- it "accepts beginless range argument" do
- eval("(..10)").send(@method, eval("(...10)")).should be_true
- (0..10).send(@method, eval("(...10)")).should be_false
+ it "accepts beginless range argument" do
+ (..10).send(@method, (...10)).should be_true
+ (0..10).send(@method, (...10)).should be_false
- (1.1..7.9).send(@method, eval("(...10.5)")).should be_false
+ (1.1..7.9).send(@method, (...10.5)).should be_false
- ('c'..'i').send(@method, eval("(..'i')")).should be_false
- end
+ ('c'..'i').send(@method, (..'i')).should be_false
+ end
- it "accepts endless range argument" do
- eval("(0..)").send(@method, eval("(0...)")).should be_true
- (0..10).send(@method, eval("(0...)")).should be_false
+ it "accepts endless range argument" do
+ eval("(0..)").send(@method, eval("(0...)")).should be_true
+ (0..10).send(@method, eval("(0...)")).should be_false
- (1.1..7.9).send(@method, eval("(0.8...)")).should be_false
+ (1.1..7.9).send(@method, eval("(0.8...)")).should be_false
- ('c'..'i').send(@method, eval("('a'..)")).should be_false
- end
+ ('c'..'i').send(@method, eval("('a'..)")).should be_false
end
end
diff --git a/spec/ruby/core/range/shared/cover_and_include.rb b/spec/ruby/core/range/shared/cover_and_include.rb
index e978e39af5..7028afaa89 100644
--- a/spec/ruby/core/range/shared/cover_and_include.rb
+++ b/spec/ruby/core/range/shared/cover_and_include.rb
@@ -24,11 +24,9 @@ describe :range_cover_and_include, shared: true do
eval("(0.5...)").send(@method, 2.4).should == true
end
- ruby_version_is "2.7" do
- it "returns true if other is an element of self for beginless ranges" do
- eval("(..10)").send(@method, 2.4).should == true
- eval("(...10.5)").send(@method, 2.4).should == true
- end
+ it "returns true if other is an element of self for beginless ranges" do
+ (..10).send(@method, 2.4).should == true
+ (...10.5).send(@method, 2.4).should == true
end
it "compares values using <=>" do
diff --git a/spec/ruby/core/range/size_spec.rb b/spec/ruby/core/range/size_spec.rb
index 0019c5ff00..9b625c9963 100644
--- a/spec/ruby/core/range/size_spec.rb
+++ b/spec/ruby/core/range/size_spec.rb
@@ -34,12 +34,27 @@ describe "Range#size" do
eval("([]...)").size.should == nil
end
- ruby_version_is "2.7" do
+ ruby_version_is ""..."3.2" do
it 'returns Float::INFINITY for all beginless ranges' do
- eval("(..1)").size.should == Float::INFINITY
- eval("(...0.5)").size.should == Float::INFINITY
- eval("(..nil)").size.should == Float::INFINITY
- eval("(...'o')").size.should == Float::INFINITY
+ (..1).size.should == Float::INFINITY
+ (...0.5).size.should == Float::INFINITY
+ (..nil).size.should == Float::INFINITY
+ (...'o').size.should == Float::INFINITY
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it 'returns Float::INFINITY for all beginless ranges if the start is numeric' do
+ (..1).size.should == Float::INFINITY
+ (...0.5).size.should == Float::INFINITY
+ end
+
+ it 'returns nil for all beginless ranges if the start is numeric' do
+ (...'o').size.should == nil
+ end
+
+ it 'returns nil if the start and the end is both nil' do
+ (nil..nil).size.should == nil
end
end
diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb
index 624fa71f5f..61ddc5205d 100644
--- a/spec/ruby/core/range/step_spec.rb
+++ b/spec/ruby/core/range/step_spec.rb
@@ -481,6 +481,28 @@ describe "Range#step" do
end
end
+ context "when begin is not defined and end is numeric" do
+ it "returns an instance of Enumerator::ArithmeticSequence" do
+ (..10).step.class.should == Enumerator::ArithmeticSequence
+ end
+ end
+
+ context "when range is endless" do
+ it "returns an instance of Enumerator::ArithmeticSequence when begin is numeric" do
+ (1..).step.class.should == Enumerator::ArithmeticSequence
+ end
+
+ it "returns an instance of Enumerator when begin is not numeric" do
+ ("a"..).step.class.should == Enumerator
+ end
+ end
+
+ context "when range is beginless and endless" do
+ it "returns an instance of Enumerator" do
+ Range.new(nil, nil).step.class.should == Enumerator
+ end
+ end
+
context "when begin and end are not numerics" do
it "returns an instance of Enumerator" do
("a".."z").step.class.should == Enumerator
diff --git a/spec/ruby/core/range/to_a_spec.rb b/spec/ruby/core/range/to_a_spec.rb
index 52ebc02941..b1d3de32db 100644
--- a/spec/ruby/core/range/to_a_spec.rb
+++ b/spec/ruby/core/range/to_a_spec.rb
@@ -33,9 +33,7 @@ describe "Range#to_a" do
-> { eval("(1..)").to_a }.should raise_error(RangeError)
end
- ruby_version_is "2.7" do
- it "throws an exception for beginless ranges" do
- -> { eval("(..1)").to_a }.should raise_error(TypeError)
- end
+ it "throws an exception for beginless ranges" do
+ -> { (..1).to_a }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/range/to_s_spec.rb b/spec/ruby/core/range/to_s_spec.rb
index 581c2e7d90..460c330912 100644
--- a/spec/ruby/core/range/to_s_spec.rb
+++ b/spec/ruby/core/range/to_s_spec.rb
@@ -16,24 +16,8 @@ describe "Range#to_s" do
eval("(1.0...)").to_s.should == "1.0..."
end
- ruby_version_is "2.7" do
- it "can show beginless ranges" do
- eval("(..1)").to_s.should == "..1"
- eval("(...1.0)").to_s.should == "...1.0"
- end
- end
-
- ruby_version_is ''...'2.7' do
- it "returns a tainted string if either end is tainted" do
- (("a".taint)..."c").to_s.tainted?.should be_true
- ("a"...("c".taint)).to_s.tainted?.should be_true
- ("a"..."c").taint.to_s.tainted?.should be_true
- end
-
- it "returns a untrusted string if either end is untrusted" do
- (("a".untrust)..."c").to_s.untrusted?.should be_true
- ("a"...("c".untrust)).to_s.untrusted?.should be_true
- ("a"..."c").untrust.to_s.untrusted?.should be_true
- end
+ it "can show beginless ranges" do
+ (..1).to_s.should == "..1"
+ (...1.0).to_s.should == "...1.0"
end
end
diff --git a/spec/ruby/core/rational/minus_spec.rb b/spec/ruby/core/rational/minus_spec.rb
index 9e0f81556b..a61b62ebe6 100644
--- a/spec/ruby/core/rational/minus_spec.rb
+++ b/spec/ruby/core/rational/minus_spec.rb
@@ -1,7 +1,51 @@
-require_relative '../../shared/rational/minus'
+require_relative '../../spec_helper'
require_relative '../../shared/rational/arithmetic_exception_in_coerce'
describe "Rational#-" do
- it_behaves_like :rational_minus, :-
it_behaves_like :rational_arithmetic_exception_in_coerce, :-
+
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational - obj
+ end
+
+ it "calls #- on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:-).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational - obj).should == :result
+ end
+end
+
+describe "Rational#- passed a Rational" do
+ it "returns the result of subtracting other from self as a Rational" do
+ (Rational(3, 4) - Rational(0, 1)).should eql(Rational(3, 4))
+ (Rational(3, 4) - Rational(1, 4)).should eql(Rational(1, 2))
+
+ (Rational(3, 4) - Rational(2, 1)).should eql(Rational(-5, 4))
+ end
+end
+
+describe "Rational#- passed a Float" do
+ it "returns the result of subtracting other from self as a Float" do
+ (Rational(3, 4) - 0.2).should eql(0.55)
+ (Rational(3, 4) - 2.5).should eql(-1.75)
+ end
+end
+
+describe "Rational#- passed an Integer" do
+ it "returns the result of subtracting other from self as a Rational" do
+ (Rational(3, 4) - 1).should eql(Rational(-1, 4))
+ (Rational(3, 4) - 2).should eql(Rational(-5, 4))
+ end
end
diff --git a/spec/ruby/core/rational/rational_spec.rb b/spec/ruby/core/rational/rational_spec.rb
index 704e49354e..482deab38d 100644
--- a/spec/ruby/core/rational/rational_spec.rb
+++ b/spec/ruby/core/rational/rational_spec.rb
@@ -4,4 +4,8 @@ describe "Rational" do
it "includes Comparable" do
Rational.include?(Comparable).should == true
end
+
+ it "does not respond to new" do
+ -> { Rational.new(1) }.should raise_error(NoMethodError)
+ end
end
diff --git a/spec/ruby/core/refinement/append_features_spec.rb b/spec/ruby/core/refinement/append_features_spec.rb
new file mode 100644
index 0000000000..fb84f245bd
--- /dev/null
+++ b/spec/ruby/core/refinement/append_features_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#append_features" do
+ ruby_version_is "3.2" do
+ it "is not defined" do
+ Refinement.should_not have_private_instance_method(:append_features)
+ end
+
+ it "is not called by Module#include" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:append_features){called = true}
+ proc{c.include(self)}.should raise_error(TypeError)
+ called.should == false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/extend_object_spec.rb b/spec/ruby/core/refinement/extend_object_spec.rb
new file mode 100644
index 0000000000..e44e9f46d8
--- /dev/null
+++ b/spec/ruby/core/refinement/extend_object_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#extend_object" do
+ ruby_version_is "3.2" do
+ it "is not defined" do
+ Refinement.should_not have_private_instance_method(:extend_object)
+ end
+
+ it "is not called by Object#extend" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:extend_object){called = true}
+ proc{c.extend(self)}.should raise_error(TypeError)
+ called.should == false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/import_methods_spec.rb b/spec/ruby/core/refinement/import_methods_spec.rb
new file mode 100644
index 0000000000..1c526f5822
--- /dev/null
+++ b/spec/ruby/core/refinement/import_methods_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#import_methods" do
+ ruby_version_is "3.1" do
+ context "when methods are defined in Ruby code" do
+ it "imports methods" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils
+ "foo".indent(3).should == " foo"
+ end
+ end
+ end
+ end
+
+ context "when methods are not defined in Ruby code" do
+ it "raises ArgumentError" do
+ Module.new do
+ refine String do
+ -> {
+ import_methods Kernel
+ }.should raise_error(ArgumentError)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/include_spec.rb b/spec/ruby/core/refinement/include_spec.rb
new file mode 100644
index 0000000000..25a53f0ec7
--- /dev/null
+++ b/spec/ruby/core/refinement/include_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#include" do
+ ruby_version_is "3.1"..."3.2" do
+ it "warns about deprecation" do
+ Module.new do
+ refine String do
+ -> {
+ include Module.new
+ }.should complain(/warning: Refinement#include is deprecated and will be removed in Ruby 3.2/)
+ end
+ end
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "raises a TypeError" do
+ Module.new do
+ refine String do
+ -> {
+ include Module.new
+ }.should raise_error(TypeError, "Refinement#include has been removed")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/prepend_features_spec.rb b/spec/ruby/core/refinement/prepend_features_spec.rb
new file mode 100644
index 0000000000..9fdea199a2
--- /dev/null
+++ b/spec/ruby/core/refinement/prepend_features_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#prepend_features" do
+ ruby_version_is "3.2" do
+ it "is not defined" do
+ Refinement.should_not have_private_instance_method(:prepend_features)
+ end
+
+ it "is not called by Module#prepend" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:prepend_features){called = true}
+ proc{c.prepend(self)}.should raise_error(TypeError)
+ called.should == false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/prepend_spec.rb b/spec/ruby/core/refinement/prepend_spec.rb
new file mode 100644
index 0000000000..27b70d392a
--- /dev/null
+++ b/spec/ruby/core/refinement/prepend_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+describe "Refinement#prepend" do
+ ruby_version_is "3.1"..."3.2" do
+ it "warns about deprecation" do
+ Module.new do
+ refine String do
+ -> {
+ prepend Module.new
+ }.should complain(/warning: Refinement#prepend is deprecated and will be removed in Ruby 3.2/)
+ end
+ end
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "raises a TypeError" do
+ Module.new do
+ refine String do
+ -> {
+ prepend Module.new
+ }.should raise_error(TypeError, "Refinement#prepend has been removed")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/regexp/compile_spec.rb b/spec/ruby/core/regexp/compile_spec.rb
index 329cb4f753..c41399cfbb 100644
--- a/spec/ruby/core/regexp/compile_spec.rb
+++ b/spec/ruby/core/regexp/compile_spec.rb
@@ -13,3 +13,7 @@ end
describe "Regexp.compile given a Regexp" do
it_behaves_like :regexp_new_regexp, :compile
end
+
+describe "Regexp.new given a non-String/Regexp" do
+ it_behaves_like :regexp_new_non_string_or_regexp, :compile
+end
diff --git a/spec/ruby/core/regexp/initialize_spec.rb b/spec/ruby/core/regexp/initialize_spec.rb
index 772a233e82..a1583384af 100644
--- a/spec/ruby/core/regexp/initialize_spec.rb
+++ b/spec/ruby/core/regexp/initialize_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Regexp#initialize" do
it "is a private method" do
- Regexp.should have_private_method(:initialize)
+ Regexp.should have_private_instance_method(:initialize)
end
ruby_version_is ""..."3.0" do
diff --git a/spec/ruby/core/regexp/new_spec.rb b/spec/ruby/core/regexp/new_spec.rb
index ce662b7a4f..65f612df55 100644
--- a/spec/ruby/core/regexp/new_spec.rb
+++ b/spec/ruby/core/regexp/new_spec.rb
@@ -11,17 +11,9 @@ end
describe "Regexp.new given a Regexp" do
it_behaves_like :regexp_new_regexp, :new
- it_behaves_like :regexp_new_string_binary, :compile
+ it_behaves_like :regexp_new_string_binary, :new
end
-describe "Regexp.new given an Integer" do
- it "raises a TypeError" do
- -> { Regexp.new(1) }.should raise_error(TypeError)
- end
-end
-
-describe "Regexp.new given a Float" do
- it "raises a TypeError" do
- -> { Regexp.new(1.0) }.should raise_error(TypeError)
- end
+describe "Regexp.new given a non-String/Regexp" do
+ it_behaves_like :regexp_new_non_string_or_regexp, :new
end
diff --git a/spec/ruby/core/regexp/shared/new.rb b/spec/ruby/core/regexp/shared/new.rb
index 9cbf89cd8b..058a51b1aa 100644
--- a/spec/ruby/core/regexp/shared/new.rb
+++ b/spec/ruby/core/regexp/shared/new.rb
@@ -24,6 +24,32 @@ describe :regexp_new, shared: true do
end
end
+describe :regexp_new_non_string_or_regexp, shared: true do
+ it "calls #to_str method for non-String/Regexp argument" do
+ obj = Object.new
+ def obj.to_str() "a" end
+
+ Regexp.send(@method, obj).should == /a/
+ end
+
+ it "raises TypeError if there is no #to_str method for non-String/Regexp argument" do
+ obj = Object.new
+ -> { Regexp.send(@method, obj) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+
+ -> { Regexp.send(@method, 1) }.should raise_error(TypeError, "no implicit conversion of Integer into String")
+ -> { Regexp.send(@method, 1.0) }.should raise_error(TypeError, "no implicit conversion of Float into String")
+ -> { Regexp.send(@method, :symbol) }.should raise_error(TypeError, "no implicit conversion of Symbol into String")
+ -> { Regexp.send(@method, []) }.should raise_error(TypeError, "no implicit conversion of Array into String")
+ end
+
+ it "raises TypeError if #to_str returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> { Regexp.send(@method, obj) }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+end
+
describe :regexp_new_string, shared: true do
it "uses the String argument as an unescaped literal to construct a Regexp object" do
Regexp.send(@method, "^hi{2,3}fo.o$").should == /^hi{2,3}fo.o$/
@@ -58,6 +84,15 @@ describe :regexp_new_string, shared: true do
end
end
+ it "sets options from second argument if it is true" do
+ r = Regexp.send(@method, 'Hi', true)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
it "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
@@ -88,57 +123,124 @@ describe :regexp_new_string, shared: true do
(r.options & Regexp::EXTENDED).should_not == 0
end
- 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
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
- end
+ it "does not try to convert the second argument to Integer with #to_int method call" do
+ ScratchPad.clear
+ obj = Object.new
+ def obj.to_int() ScratchPad.record(:called) end
- it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
- end
+ Regexp.send(@method, "Hi", obj)
- it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
+ ScratchPad.recorded.should == nil
end
- it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
+ ruby_version_is ""..."3.2" 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
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
end
- it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do
- Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII
+ ruby_version_is "3.2" do
+ it "warns any non-Integer, non-nil, non-false second argument" do
+ r = nil
+ -> {
+ r = Regexp.send(@method, 'Hi', Object.new)
+ }.should complain(/expected true or false as ignorecase/, {verbose: true})
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "accepts a String of supported flags as the second argument" do
+ r = Regexp.send(@method, 'Hi', 'i')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', 'imx')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should_not == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', 'mimi')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', '')
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "raises an Argument error if the second argument contains unsupported chars" do
+ -> { Regexp.send(@method, 'Hi', 'e') }.should raise_error(ArgumentError)
+ -> { Regexp.send(@method, 'Hi', 'n') }.should raise_error(ArgumentError)
+ -> { Regexp.send(@method, 'Hi', 's') }.should raise_error(ArgumentError)
+ -> { Regexp.send(@method, 'Hi', 'u') }.should raise_error(ArgumentError)
+ -> { Regexp.send(@method, 'Hi', 'j') }.should raise_error(ArgumentError)
+ -> { Regexp.send(@method, 'Hi', 'mjx') }.should raise_error(ArgumentError)
+ end
end
- it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do
- a = "(?:[\x8E\xA1-\xFE])"
- str = "\A(?:#{a}|x*)\z"
+ ruby_version_is ""..."3.2" do
+ it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do
+ -> {
+ Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do
+ -> {
+ Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do
+ -> {
+ Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do
+ Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII
+ end
+
+ it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do
+ a = "(?:[\x8E\xA1-\xFE])"
+ str = "\A(?:#{a}|x*)\z"
- Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::BINARY
+ Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::BINARY
+ Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::BINARY
+ Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::BINARY
+ Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::BINARY
+ end
end
describe "with escaped characters" do
@@ -498,8 +600,10 @@ describe :regexp_new_regexp, shared: true do
Regexp.send(@method, /Hi/n).encoding.should == Encoding::US_ASCII
end
- it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do
- Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::BINARY
+ ruby_version_is ''...'3.2' do
+ it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do
+ Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::BINARY
+ end
end
end
end
diff --git a/spec/ruby/core/regexp/shared/quote.rb b/spec/ruby/core/regexp/shared/quote.rb
index a55adb5bf2..9533102766 100644
--- a/spec/ruby/core/regexp/shared/quote.rb
+++ b/spec/ruby/core/regexp/shared/quote.rb
@@ -12,6 +12,16 @@ describe :regexp_quote, shared: true do
Regexp.send(@method, :symbol).should == 'symbol'
end
+ it "works with substrings" do
+ str = ".+[]()"[1...-1]
+ Regexp.send(@method, str).should == '\+\[\]\('
+ end
+
+ it "works for broken strings" do
+ Regexp.send(@method, "a.\x85b.".force_encoding("US-ASCII")).should =="a\\.\x85b\\.".force_encoding("US-ASCII")
+ Regexp.send(@method, "a.\x80".force_encoding("UTF-8")).should == "a\\.\x80".force_encoding("UTF-8")
+ end
+
it "sets the encoding of the result to US-ASCII if there are only US-ASCII characters present in the input String" do
str = "abc".force_encoding("euc-jp")
Regexp.send(@method, str).encoding.should == Encoding::US_ASCII
diff --git a/spec/ruby/core/regexp/source_spec.rb b/spec/ruby/core/regexp/source_spec.rb
index 709fee49b3..5f253da9ea 100644
--- a/spec/ruby/core/regexp/source_spec.rb
+++ b/spec/ruby/core/regexp/source_spec.rb
@@ -9,8 +9,26 @@ describe "Regexp#source" do
/x(.)xz/.source.should == "x(.)xz"
end
- it "will remove escape characters" do
- /foo\/bar/.source.should == "foo/bar"
+ it "keeps escape sequences as is" do
+ /\x20\+/.source.should == '\x20\+'
+ end
+
+ describe "escaping" do
+ it "keeps escaping of metacharacter" do
+ /\$/.source.should == "\\$"
+ end
+
+ it "keeps escaping of metacharacter used as a terminator" do
+ %r+\++.source.should == "\\+"
+ end
+
+ it "removes escaping of non-metacharacter used as a terminator" do
+ %r@\@@.source.should == "@"
+ end
+
+ it "keeps escaping of non-metacharacter not used as a terminator" do
+ /\@/.source.should == "\\@"
+ end
end
not_supported_on :opal do
diff --git a/spec/ruby/core/regexp/timeout_spec.rb b/spec/ruby/core/regexp/timeout_spec.rb
new file mode 100644
index 0000000000..6fce261814
--- /dev/null
+++ b/spec/ruby/core/regexp/timeout_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.2" do
+ describe "Regexp.timeout" do
+ after :each do
+ Regexp.timeout = nil
+ end
+
+ it "returns global timeout" do
+ Regexp.timeout = 3
+ Regexp.timeout.should == 3
+ end
+
+ it "raises Regexp::TimeoutError after global timeout elapsed" do
+ Regexp.timeout = 0.001
+ Regexp.timeout.should == 0.001
+
+ -> {
+ # A typical ReDoS case
+ /^(a*)*$/ =~ "a" * 1000000 + "x"
+ }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
+ end
+
+ it "raises Regexp::TimeoutError after timeout keyword value elapsed" do
+ Regexp.timeout = 3 # This should be ignored
+ Regexp.timeout.should == 3
+
+ re = Regexp.new("^a*b?a*$", timeout: 0.001)
+
+ -> {
+ re =~ "a" * 1000000 + "x"
+ }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
+ end
+ end
+end
diff --git a/spec/ruby/core/signal/trap_spec.rb b/spec/ruby/core/signal/trap_spec.rb
index 3c78922694..10e122e072 100644
--- a/spec/ruby/core/signal/trap_spec.rb
+++ b/spec/ruby/core/signal/trap_spec.rb
@@ -221,6 +221,18 @@ describe "Signal.trap" do
Signal.trap(:HUP, @saved_trap).should equal(@proc)
end
+ it "raises ArgumentError when passed unknown signal" do
+ -> { Signal.trap(300) { } }.should raise_error(ArgumentError, "invalid signal number (300)")
+ -> { Signal.trap("USR10") { } }.should raise_error(ArgumentError, "unsupported signal `SIGUSR10'")
+ -> { Signal.trap("SIGUSR10") { } }.should raise_error(ArgumentError, "unsupported signal `SIGUSR10'")
+ end
+
+ it "raises ArgumentError when passed signal is not Integer, String or Symbol" do
+ -> { Signal.trap(nil) { } }.should raise_error(ArgumentError, "bad signal type NilClass")
+ -> { Signal.trap(100.0) { } }.should raise_error(ArgumentError, "bad signal type Float")
+ -> { Signal.trap(Rational(100)) { } }.should raise_error(ArgumentError, "bad signal type Rational")
+ end
+
# See man 2 signal
%w[KILL STOP].each do |signal|
it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do
@@ -254,12 +266,10 @@ describe "Signal.trap" do
r.close
loop { w.write("a"*1024) }
RUBY
- out = ruby_exe(code, exit_status: nil)
+ out = ruby_exe(code, exit_status: :SIGPIPE)
status = $?
out.should == "nil\n"
status.should.signaled?
- status.termsig.should be_kind_of(Integer)
- Signal.signame(status.termsig).should == "PIPE"
end
end
diff --git a/spec/ruby/core/string/allocate_spec.rb b/spec/ruby/core/string/allocate_spec.rb
index 5b36b4fd05..30d5f60594 100644
--- a/spec/ruby/core/string/allocate_spec.rb
+++ b/spec/ruby/core/string/allocate_spec.rb
@@ -14,6 +14,6 @@ describe "String.allocate" do
end
it "returns a binary String" do
- String.new.encoding.should == Encoding::BINARY
+ String.allocate.encoding.should == Encoding::BINARY
end
end
diff --git a/spec/ruby/core/string/append_spec.rb b/spec/ruby/core/string/append_spec.rb
index 1e1667f617..e001257621 100644
--- a/spec/ruby/core/string/append_spec.rb
+++ b/spec/ruby/core/string/append_spec.rb
@@ -5,4 +5,9 @@ require_relative 'shared/concat'
describe "String#<<" do
it_behaves_like :string_concat, :<<
it_behaves_like :string_concat_encoding, :<<
+
+ it "raises an ArgumentError when given the incorrect number of arguments" do
+ -> { "hello".send(:<<) }.should raise_error(ArgumentError)
+ -> { "hello".send(:<<, "one", "two") }.should raise_error(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/string/b_spec.rb b/spec/ruby/core/string/b_spec.rb
index b2e3d326ba..37c7994700 100644
--- a/spec/ruby/core/string/b_spec.rb
+++ b/spec/ruby/core/string/b_spec.rb
@@ -12,13 +12,4 @@ describe "String#b" do
str.b.should_not equal(str)
str.should == "こんちには"
end
-
- ruby_version_is ''...'2.7' do
- it "copies own tainted/untrusted status to the returning value" do
- utf_8 = "こんちには".taint.untrust
- ret = utf_8.b
- ret.tainted?.should be_true
- ret.untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/string/byteindex_spec.rb b/spec/ruby/core/string/byteindex_spec.rb
new file mode 100644
index 0000000000..af70c729e8
--- /dev/null
+++ b/spec/ruby/core/string/byteindex_spec.rb
@@ -0,0 +1,16 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "String#byteindex with Regexp" do
+ ruby_version_is "3.2" do
+ it "always clear $~" do
+ "a".byteindex(/a/)
+ $~.should_not == nil
+
+ string = "blablabla"
+ string.byteindex(/bla/, string.bytesize + 1)
+ $~.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/string/bytesize_spec.rb b/spec/ruby/core/string/bytesize_spec.rb
index b8b07cfbec..a31f3ae671 100644
--- a/spec/ruby/core/string/bytesize_spec.rb
+++ b/spec/ruby/core/string/bytesize_spec.rb
@@ -2,7 +2,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "#String#bytesize" do
+describe "String#bytesize" do
it "returns the length of self in bytes" do
"hello".bytesize.should == 5
" ".bytesize.should == 1
diff --git a/spec/ruby/core/string/byteslice_spec.rb b/spec/ruby/core/string/byteslice_spec.rb
index a49da040eb..312229523d 100644
--- a/spec/ruby/core/string/byteslice_spec.rb
+++ b/spec/ruby/core/string/byteslice_spec.rb
@@ -24,4 +24,10 @@ describe "String#byteslice on on non ASCII strings" do
"\u3042".byteslice(1..2).should == "\x81\x82".force_encoding("UTF-8")
"\u3042".byteslice(-1).should == "\x82".force_encoding("UTF-8")
end
+
+ it "returns a String in the same encoding as self" do
+ "ruby".encode("UTF-8").slice(0).encoding.should == Encoding::UTF_8
+ "ruby".encode("US-ASCII").slice(0).encoding.should == Encoding::US_ASCII
+ "ruby".encode("Windows-1251").slice(0).encoding.should == Encoding::Windows_1251
+ end
end
diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb
index 21df18a5ae..3f85cf5ae4 100644
--- a/spec/ruby/core/string/capitalize_spec.rb
+++ b/spec/ruby/core/string/capitalize_spec.rb
@@ -10,13 +10,7 @@ describe "String#capitalize" do
"hello".capitalize.should == "Hello"
"HELLO".capitalize.should == "Hello"
"123ABC".capitalize.should == "123abc"
- end
-
- ruby_version_is ''...'2.7' do
- it "taints resulting string when self is tainted" do
- "".taint.capitalize.should.tainted?
- "hello".taint.capitalize.should.tainted?
- end
+ "abcdef"[1...-1].capitalize.should == "Bcde"
end
describe "full Unicode case mapping" do
@@ -42,6 +36,10 @@ describe "String#capitalize" do
it "does not capitalize non-ASCII characters" do
"ßet".capitalize(:ascii).should == "ßet"
end
+
+ it "handles non-ASCII substrings properly" do
+ "garçon"[1...-1].capitalize(:ascii).should == "Arço"
+ end
end
describe "full Unicode case mapping adapted for Turkic languages" do
@@ -93,6 +91,10 @@ describe "String#capitalize" do
StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String)
end
end
+
+ it "returns a String in the same encoding as self" do
+ "h".encode("US-ASCII").capitalize.encoding.should == Encoding::US_ASCII
+ end
end
describe "String#capitalize!" do
diff --git a/spec/ruby/core/string/center_spec.rb b/spec/ruby/core/string/center_spec.rb
index b66015172c..76da6e1e09 100644
--- a/spec/ruby/core/string/center_spec.rb
+++ b/spec/ruby/core/string/center_spec.rb
@@ -47,16 +47,6 @@ describe "String#center with length, padding" do
"radiology".center(8, '-').should == "radiology"
end
- ruby_version_is ''...'2.7' do
- it "taints result when self or padstr is tainted" do
- "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
-
it "calls #to_int to convert length to an integer" do
"_".center(3.8, "^").should == "^_^"
@@ -113,14 +103,6 @@ describe "String#center with length, padding" do
end
end
- ruby_version_is ''...'2.7' do
- it "when padding is tainted and self is untainted returns a tainted string if and only if length is longer than self" do
- "hello".center(4, 'X'.taint).tainted?.should be_false
- "hello".center(5, 'X'.taint).tainted?.should be_false
- "hello".center(6, 'X'.taint).tainted?.should be_true
- end
- end
-
describe "with width" do
it "returns a String in the same encoding as the original" do
str = "abc".force_encoding Encoding::IBM437
diff --git a/spec/ruby/core/string/chars_spec.rb b/spec/ruby/core/string/chars_spec.rb
index e4f26bc0cc..715e65dc90 100644
--- a/spec/ruby/core/string/chars_spec.rb
+++ b/spec/ruby/core/string/chars_spec.rb
@@ -1,5 +1,4 @@
require_relative 'shared/chars'
-require_relative 'shared/each_char_without_block'
describe "String#chars" do
it_behaves_like :string_chars, :chars
@@ -7,4 +6,10 @@ describe "String#chars" do
it "returns an array when no block given" do
"hello".chars.should == ['h', 'e', 'l', 'l', 'o']
end
+
+ it "returns Strings in the same encoding as self" do
+ "hello".encode("US-ASCII").chars.each do |c|
+ c.encoding.should == Encoding::US_ASCII
+ end
+ end
end
diff --git a/spec/ruby/core/string/chomp_spec.rb b/spec/ruby/core/string/chomp_spec.rb
index 3d6207f876..d0508d938f 100644
--- a/spec/ruby/core/string/chomp_spec.rb
+++ b/spec/ruby/core/string/chomp_spec.rb
@@ -40,10 +40,8 @@ describe "String#chomp" do
"".chomp.should == ""
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc".taint.chomp.tainted?.should be_true
- end
+ it "returns a String in the same encoding as self" do
+ "abc\n\n".encode("US-ASCII").chomp.encoding.should == Encoding::US_ASCII
end
ruby_version_is ''...'3.0' do
@@ -80,12 +78,6 @@ describe "String#chomp" do
str.chomp(nil).should_not equal(str)
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc".taint.chomp(nil).tainted?.should be_true
- end
- end
-
it "returns an empty String when self is empty" do
"".chomp(nil).should == ""
end
@@ -112,12 +104,6 @@ describe "String#chomp" do
"abc\r\n\r\n\r\n".chomp("").should == "abc"
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc".taint.chomp("").tainted?.should be_true
- end
- end
-
it "returns an empty String when self is empty" do
"".chomp("").should == ""
end
@@ -140,12 +126,6 @@ describe "String#chomp" do
"abc\r\n\r\n".chomp("\n").should == "abc\r\n"
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc".taint.chomp("\n").tainted?.should be_true
- end
- end
-
it "returns an empty String when self is empty" do
"".chomp("\n").should == ""
end
@@ -178,16 +158,6 @@ describe "String#chomp" do
"".chomp("abc").should == ""
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc".taint.chomp("abc").tainted?.should be_true
- end
-
- it "does not taint the result when the argument is tainted" do
- "abc".chomp("abc".taint).tainted?.should be_false
- end
- end
-
it "returns an empty String when the argument equals self" do
"abc".chomp("abc").should == ""
end
@@ -232,12 +202,6 @@ describe "String#chomp!" do
"".chomp!.should be_nil
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc\n".taint.chomp!.tainted?.should be_true
- 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)
@@ -280,12 +244,6 @@ describe "String#chomp!" do
"abc\r\n\r\n\r\n".chomp!("").should == "abc"
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc\n".taint.chomp!("").tainted?.should be_true
- end
- end
-
it "returns nil when self is empty" do
"".chomp!("").should be_nil
end
@@ -304,12 +262,6 @@ describe "String#chomp!" do
"abc\r\n\r\n".chomp!("\n").should == "abc\r\n"
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc\n".taint.chomp!("\n").tainted?.should be_true
- end
- end
-
it "returns nil when self is empty" do
"".chomp!("\n").should be_nil
end
@@ -341,16 +293,6 @@ describe "String#chomp!" do
it "returns nil when self is empty" do
"".chomp!("abc").should be_nil
end
-
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "abc".taint.chomp!("abc").tainted?.should be_true
- end
-
- it "does not taint the result when the argument is tainted" do
- "abc".chomp!("abc".taint).tainted?.should be_false
- end
- end
end
it "raises a FrozenError on a frozen instance when it is modified" do
diff --git a/spec/ruby/core/string/chop_spec.rb b/spec/ruby/core/string/chop_spec.rb
index 9b4e7363c6..f598d34bc8 100644
--- a/spec/ruby/core/string/chop_spec.rb
+++ b/spec/ruby/core/string/chop_spec.rb
@@ -49,18 +49,6 @@ describe "String#chop" do
s.chop.should_not equal(s)
end
- ruby_version_is ''...'2.7' do
- it "taints result when self is tainted" do
- "hello".taint.chop.should.tainted?
- "".taint.chop.should.tainted?
- end
-
- it "untrusts result when self is untrusted" do
- "hello".untrust.chop.should.untrusted?
- "".untrust.chop.should.untrusted?
- end
- end
-
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)
@@ -72,6 +60,10 @@ describe "String#chop" do
StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String)
end
end
+
+ it "returns a String in the same encoding as self" do
+ "abc\n\n".encode("US-ASCII").chop.encoding.should == Encoding::US_ASCII
+ end
end
describe "String#chop!" do
diff --git a/spec/ruby/core/string/clone_spec.rb b/spec/ruby/core/string/clone_spec.rb
index f8d40423f0..a2ba2f9877 100644
--- a/spec/ruby/core/string/clone_spec.rb
+++ b/spec/ruby/core/string/clone_spec.rb
@@ -54,4 +54,8 @@ describe "String#clone" do
orig.should == "xtring"
clone.should == "string"
end
+
+ it "returns a String in the same encoding as self" do
+ "a".encode("US-ASCII").clone.encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/core/string/comparison_spec.rb b/spec/ruby/core/string/comparison_spec.rb
index 01199274b6..91cfdca25a 100644
--- a/spec/ruby/core/string/comparison_spec.rb
+++ b/spec/ruby/core/string/comparison_spec.rb
@@ -75,6 +75,10 @@ describe "String#<=> with String" do
(xff_1 <=> xff_2).should == -1
(xff_2 <=> xff_1).should == 1
end
+
+ it "returns 0 when comparing 2 empty strings but one is not ASCII-compatible" do
+ ("" <=> "".force_encoding('iso-2022-jp')).should == 0
+ end
end
# Note: This is inconsistent with Array#<=> which calls #to_ary instead of
diff --git a/spec/ruby/core/string/crypt_spec.rb b/spec/ruby/core/string/crypt_spec.rb
index b947702492..06f84c70a4 100644
--- a/spec/ruby/core/string/crypt_spec.rb
+++ b/spec/ruby/core/string/crypt_spec.rb
@@ -25,21 +25,6 @@ describe "String#crypt" do
"mypassword".crypt(obj).should == "$2a$04$0WVaz0pV3jzfZ5G5tpmHWuBQGbkjzgtSc3gJbmdy0GAGMa45MFM2."
end
- ruby_version_is ''...'2.7' do
- it "taints the result if either salt or self is tainted" do
- tainted_salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmHWu"
- tainted_str = "mypassword"
-
- tainted_salt.taint
- tainted_str.taint
-
- "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
-
it "doesn't return subclass instances" do
StringSpecs::MyString.new("mypassword").crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should be_an_instance_of(String)
"mypassword".crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should be_an_instance_of(String)
@@ -85,21 +70,6 @@ describe "String#crypt" do
"".crypt(obj).should == "aaQSqAReePlq6"
end
- ruby_version_is ''...'2.7' do
- it "taints the result if either salt or self is tainted" do
- tainted_salt = "aa"
- tainted_str = "hello"
-
- tainted_salt.taint
- tainted_str.taint
-
- "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
-
it "doesn't return subclass instances" do
StringSpecs::MyString.new("hello").crypt("aa").should be_an_instance_of(String)
"hello".crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
diff --git a/spec/ruby/core/string/dedup_spec.rb b/spec/ruby/core/string/dedup_spec.rb
new file mode 100644
index 0000000000..919d440c51
--- /dev/null
+++ b/spec/ruby/core/string/dedup_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'shared/dedup'
+
+describe 'String#dedup' do
+ ruby_version_is '3.2'do
+ it_behaves_like :string_dedup, :dedup
+ end
+end
diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb
index 8469791f74..238de85f05 100644
--- a/spec/ruby/core/string/delete_prefix_spec.rb
+++ b/spec/ruby/core/string/delete_prefix_spec.rb
@@ -21,11 +21,8 @@ describe "String#delete_prefix" do
r.should == s
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
+ it "does not remove partial bytes, only full characters" do
+ "\xe3\x81\x82".delete_prefix("\xe3").should == "\xe3\x81\x82"
end
it "doesn't set $~" do
@@ -54,6 +51,10 @@ describe "String#delete_prefix" do
s.delete_prefix('hell').should be_an_instance_of(String)
end
end
+
+ it "returns a String in the same encoding as self" do
+ 'hello'.encode("US-ASCII").delete_prefix('hell').encoding.should == Encoding::US_ASCII
+ end
end
describe "String#delete_prefix!" do
diff --git a/spec/ruby/core/string/delete_spec.rb b/spec/ruby/core/string/delete_spec.rb
index ebca0b7dae..87831a9d19 100644
--- a/spec/ruby/core/string/delete_spec.rb
+++ b/spec/ruby/core/string/delete_spec.rb
@@ -68,15 +68,6 @@ describe "String#delete" do
-> { "hello".delete("^h-e") }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "taints result when self is tainted" do
- "hello".taint.delete("e").should.tainted?
- "hello".taint.delete("a-z").should.tainted?
-
- "hello".delete("e".taint).should_not.tainted?
- end
- end
-
it "tries to convert each set arg to a string using to_str" do
other_string = mock('lo')
other_string.should_receive(:to_str).and_return("lo")
@@ -104,6 +95,10 @@ describe "String#delete" do
StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String)
end
end
+
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").delete("lo").encoding.should == Encoding::US_ASCII
+ end
end
describe "String#delete!" do
diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb
index 12d0ee175e..6883d6938c 100644
--- a/spec/ruby/core/string/delete_suffix_spec.rb
+++ b/spec/ruby/core/string/delete_suffix_spec.rb
@@ -21,11 +21,8 @@ describe "String#delete_suffix" do
r.should == s
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
+ it "does not remove partial bytes, only full characters" do
+ "\xe3\x81\x82".delete_suffix("\x82").should == "\xe3\x81\x82"
end
it "doesn't set $~" do
@@ -54,6 +51,10 @@ describe "String#delete_suffix" do
s.delete_suffix('ello').should be_an_instance_of(String)
end
end
+
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").delete_suffix("ello").encoding.should == Encoding::US_ASCII
+ end
end
describe "String#delete_suffix!" do
diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb
index 4427c9df10..153b4ce191 100644
--- a/spec/ruby/core/string/downcase_spec.rb
+++ b/spec/ruby/core/string/downcase_spec.rb
@@ -8,6 +8,10 @@ describe "String#downcase" do
"hello".downcase.should == "hello"
end
+ it "returns a String in the same encoding as self" do
+ "hELLO".encode("US-ASCII").downcase.encoding.should == Encoding::US_ASCII
+ end
+
describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"ÄÖÜ".downcase.should == "äöü"
@@ -27,6 +31,10 @@ describe "String#downcase" do
it "does not downcase non-ASCII characters" do
"CÅR".downcase(:ascii).should == "cÅr"
end
+
+ it "works with substrings" do
+ "prefix TÉ"[-2..-1].downcase(:ascii).should == "tÉ"
+ end
end
describe "full Unicode case mapping adapted for Turkic languages" do
@@ -68,14 +76,6 @@ describe "String#downcase" do
-> { "ABC".downcase(:invalid_option) }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "taints result when self is tainted" do
- "".taint.downcase.should.tainted?
- "x".taint.downcase.should.tainted?
- "X".taint.downcase.should.tainted?
- end
- end
-
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)
diff --git a/spec/ruby/core/string/dump_spec.rb b/spec/ruby/core/string/dump_spec.rb
index 817dec6c4d..81de0cfae4 100644
--- a/spec/ruby/core/string/dump_spec.rb
+++ b/spec/ruby/core/string/dump_spec.rb
@@ -3,18 +3,6 @@ require_relative '../../spec_helper'
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.should.tainted?
- "foo\n".taint.dump.should.tainted?
- end
-
- it "untrusts the result if self is untrusted" do
- "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.should_not.frozen?
end
@@ -362,7 +350,7 @@ describe "String#dump" do
].should be_computed_by(:dump)
end
- it "returns a string with multi-byte UTF-8 characters replaced by \\u{} notation with upper-case hex digits" do
+ it "returns a string with multi-byte UTF-8 characters less than or equal 0xFFFF replaced by \\uXXXX notation with upper-case hex digits" do
[ [0200.chr('utf-8'), '"\u0080"'],
[0201.chr('utf-8'), '"\u0081"'],
[0202.chr('utf-8'), '"\u0082"'],
@@ -394,15 +382,21 @@ describe "String#dump" do
[0235.chr('utf-8'), '"\u009D"'],
[0236.chr('utf-8'), '"\u009E"'],
[0237.chr('utf-8'), '"\u009F"'],
+ [0177777.chr('utf-8'), '"\uFFFF"'],
].should be_computed_by(:dump)
end
+ it "returns a string with multi-byte UTF-8 characters greater than 0xFFFF replaced by \\u{XXXXXX} notation with upper-case hex digits" do
+ 0x10000.chr('utf-8').dump.should == '"\u{10000}"'
+ 0x10FFFF.chr('utf-8').dump.should == '"\u{10FFFF}"'
+ end
+
it "includes .force_encoding(name) if the encoding isn't ASCII compatible" do
"\u{876}".encode('utf-16be').dump.should.end_with?(".force_encoding(\"UTF-16BE\")")
"\u{876}".encode('utf-16le').dump.should.end_with?(".force_encoding(\"UTF-16LE\")")
end
- it "keeps origin encoding" do
+ it "returns a String in the same encoding as self" do
"foo".encode("ISO-8859-1").dump.encoding.should == Encoding::ISO_8859_1
"foo".encode('windows-1251').dump.encoding.should == Encoding::Windows_1251
1.chr.dump.encoding.should == Encoding::US_ASCII
diff --git a/spec/ruby/core/string/dup_spec.rb b/spec/ruby/core/string/dup_spec.rb
index d650788210..73f71b8ffc 100644
--- a/spec/ruby/core/string/dup_spec.rb
+++ b/spec/ruby/core/string/dup_spec.rb
@@ -49,4 +49,17 @@ describe "String#dup" do
orig.should == "xtring"
dup.should == "string"
end
+
+ it "does not modify the original setbyte-mutated string when changing dupped string" do
+ orig = "a"
+ orig.setbyte 0, "b".ord
+ copy = orig.dup
+ orig.setbyte 0, "c".ord
+ orig.should == "c"
+ copy.should == "b"
+ end
+
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").dup.encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
index 632f2337f1..b45d89ecb0 100644
--- a/spec/ruby/core/string/each_grapheme_cluster_spec.rb
+++ b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
@@ -6,4 +6,12 @@ describe "String#each_grapheme_cluster" do
it_behaves_like :string_chars, :each_grapheme_cluster
it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster
it_behaves_like :string_each_char_without_block, :each_grapheme_cluster
+
+ ruby_version_is '3.0' do
+ it "yields String instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("abc").each_grapheme_cluster { |s| a << s.class }
+ a.should == [String, String, String]
+ end
+ end
end
diff --git a/spec/ruby/core/string/element_set_spec.rb b/spec/ruby/core/string/element_set_spec.rb
index c9e02a7381..fa041fa31d 100644
--- a/spec/ruby/core/string/element_set_spec.rb
+++ b/spec/ruby/core/string/element_set_spec.rb
@@ -14,18 +14,6 @@ describe "String#[]= with Integer index" do
a.should == "bamelo"
end
- ruby_version_is ''...'2.7' do
- it "taints self if other_str is tainted" do
- a = "hello"
- a[0] = "".taint
- a.should.tainted?
-
- a = "hello"
- a[0] = "x".taint
- a.should.tainted?
- end
- end
-
it "raises an IndexError without changing self if idx is outside of self" do
str = "hello"
@@ -141,6 +129,12 @@ describe "String#[]= with Integer index" do
str.encoding.should equal(Encoding::BINARY)
end
+ it "updates the string to a compatible encoding" do
+ str = " "
+ str[1] = [0xB9].pack("C*")
+ str.encoding.should == Encoding::ASCII_8BIT
+ end
+
it "raises an Encoding::CompatibilityError if the replacement encoding is incompatible" do
str = "あれ"
rep = "が".encode Encoding::EUC_JP
@@ -363,11 +357,11 @@ describe "String#[]= with a Range index" do
end
it "raises a RangeError if negative Range begin is out of range" do
- -> { "abc"[-4..-2] = "x" }.should raise_error(RangeError)
+ -> { "abc"[-4..-2] = "x" }.should raise_error(RangeError, "-4..-2 out of range")
end
it "raises a RangeError if positive Range begin is greater than String size" do
- -> { "abc"[4..2] = "x" }.should raise_error(RangeError)
+ -> { "abc"[4..2] = "x" }.should raise_error(RangeError, "4..2 out of range")
end
it "uses the Range end as an index rather than a count" do
@@ -487,18 +481,6 @@ describe "String#[]= with Integer index, count" do
a.should == "hellobob"
end
- ruby_version_is ''...'2.7' do
- it "taints self if other_str is tainted" do
- a = "hello"
- a[0, 0] = "".taint
- a.should.tainted?
-
- a = "hello"
- a[1, 4] = "x".taint
- a.should.tainted?
- end
- end
-
it "calls #to_int to convert the index and count objects" do
index = mock("string element set index")
index.should_receive(:to_int).and_return(-4)
diff --git a/spec/ruby/core/string/encode_spec.rb b/spec/ruby/core/string/encode_spec.rb
index ae641b2110..5604ab7210 100644
--- a/spec/ruby/core/string/encode_spec.rb
+++ b/spec/ruby/core/string/encode_spec.rb
@@ -67,10 +67,52 @@ describe "String#encode" do
"\rfoo".encode(universal_newline: true).should == "\nfoo"
end
- it "replaces invalid encoding" do
- encoded = "ち\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "?")
- encoded.should == "\u3061??".encode("UTF-16LE")
- encoded.encode("UTF-8").should == "ち??"
+ it "replaces invalid encoding in source with default replacement" do
+ encoded = "ち\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace)
+ encoded.should == "\u3061\ufffd\ufffd".encode("UTF-16LE")
+ encoded.encode("UTF-8").should == "ち\ufffd\ufffd"
+ end
+
+ it "replaces invalid encoding in source with a specified replacement" do
+ encoded = "ち\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo")
+ encoded.should == "\u3061foofoo".encode("UTF-16LE")
+ encoded.encode("UTF-8").should == "ちfoofoo"
+ end
+
+ it "replaces invalid encoding in source using a specified replacement even when a fallback is given" do
+ encoded = "ち\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo", fallback: -> c { "bar" })
+ encoded.should == "\u3061foofoo".encode("UTF-16LE")
+ encoded.encode("UTF-8").should == "ちfoofoo"
+ end
+
+ it "replaces undefined encoding in destination with default replacement" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, undef: :replace)
+ encoded.should == "B?".encode(Encoding::US_ASCII)
+ encoded.encode("UTF-8").should == "B?"
+ end
+
+ it "replaces undefined encoding in destination with a specified replacement" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, undef: :replace, replace: "foo")
+ encoded.should == "Bfoo".encode(Encoding::US_ASCII)
+ encoded.encode("UTF-8").should == "Bfoo"
+ end
+
+ it "replaces undefined encoding in destination with a specified replacement even if a fallback is given" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, undef: :replace, replace: "foo", fallback: proc {|x| "bar"})
+ encoded.should == "Bfoo".encode(Encoding::US_ASCII)
+ encoded.encode("UTF-8").should == "Bfoo"
+ end
+
+ it "replaces undefined encoding in destination using a fallback proc" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc {|x| "bar"})
+ encoded.should == "Bbar".encode(Encoding::US_ASCII)
+ encoded.encode("UTF-8").should == "Bbar"
+ end
+
+ it "replaces invalid encoding in source using replace even when fallback is given as proc" do
+ encoded = "ち\xE3\x81\xFF".encode("UTF-16LE", invalid: :replace, replace: "foo", fallback: proc {|x| "bar"})
+ encoded.should == "\u3061foofoo".encode("UTF-16LE")
+ encoded.encode("UTF-8").should == "ちfoofoo"
end
end
diff --git a/spec/ruby/core/string/encoding_spec.rb b/spec/ruby/core/string/encoding_spec.rb
index 4d17a39f29..574a1e2f92 100644
--- a/spec/ruby/core/string/encoding_spec.rb
+++ b/spec/ruby/core/string/encoding_spec.rb
@@ -10,6 +10,7 @@ describe "String#encoding" do
it "is equal to the source encoding by default" do
s = StringSpecs::ISO88599Encoding.new
s.cedilla.encoding.should == s.source_encoding
+ s.cedilla.encode("utf-8").should == 350.chr(Encoding::UTF_8) # S-cedilla
end
it "returns the given encoding if #force_encoding has been called" do
diff --git a/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb b/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb
index 61a691ff78..cfa91dedc3 100644
--- a/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb
+++ b/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb
@@ -4,6 +4,6 @@ module StringSpecs
def source_encoding; __ENCODING__; end
def x_escape; [0xDF].pack('C').force_encoding("iso-8859-9"); end
def ascii_only; "glark"; end
- def cedilla; "Ş"; end
+ def cedilla; ""; end # S-cedilla
end
end
diff --git a/spec/ruby/core/string/fixtures/to_c.rb b/spec/ruby/core/string/fixtures/to_c.rb
new file mode 100644
index 0000000000..7776933263
--- /dev/null
+++ b/spec/ruby/core/string/fixtures/to_c.rb
@@ -0,0 +1,5 @@
+module StringSpecs
+ def self.to_c_method(string)
+ string.to_c
+ end
+end
diff --git a/spec/ruby/core/string/force_encoding_spec.rb b/spec/ruby/core/string/force_encoding_spec.rb
index 2fe5f79c0f..f37aaf9eb4 100644
--- a/spec/ruby/core/string/force_encoding_spec.rb
+++ b/spec/ruby/core/string/force_encoding_spec.rb
@@ -60,7 +60,7 @@ describe "String#force_encoding" do
end
it "does not transcode self" do
- str = "\u{8612}"
+ str = "é"
str.dup.force_encoding('utf-16le').should_not == str.encode('utf-16le')
end
diff --git a/spec/ruby/core/string/gsub_spec.rb b/spec/ruby/core/string/gsub_spec.rb
index ad41b7e0a2..c87a566591 100644
--- a/spec/ruby/core/string/gsub_spec.rb
+++ b/spec/ruby/core/string/gsub_spec.rb
@@ -160,56 +160,12 @@ describe "String#gsub with pattern and replacement" do
it_behaves_like :string_gsub_named_capture, :gsub
- ruby_version_is ''...'2.7' do
- it "taints the result if the original string or replacement is tainted" do
- hello = "hello"
- hello_t = "hello"
- a = "a"
- a_t = "a"
- empty = ""
- empty_t = ""
-
- hello_t.taint; a_t.taint; empty_t.taint
-
- hello_t.gsub(/./, a).should.tainted?
- hello_t.gsub(/./, empty).should.tainted?
-
- hello.gsub(/./, a_t).should.tainted?
- hello.gsub(/./, empty_t).should.tainted?
- hello.gsub(//, empty_t).should.tainted?
-
- hello.gsub(//.taint, "foo").should_not.tainted?
- end
- end
-
it "handles pattern collapse" do
str = "こにちわ"
reg = %r!!
str.gsub(reg, ".").should == ".こ.に.ち.わ."
end
- ruby_version_is ''...'2.7' do
- it "untrusts the result if the original string or replacement is untrusted" do
- hello = "hello"
- hello_t = "hello"
- a = "a"
- a_t = "a"
- empty = ""
- empty_t = ""
-
- hello_t.untrust; a_t.untrust; empty_t.untrust
-
- hello_t.gsub(/./, a).should.untrusted?
- hello_t.gsub(/./, empty).should.untrusted?
-
- hello.gsub(/./, a_t).should.untrusted?
- hello.gsub(/./, empty_t).should.untrusted?
- hello.gsub(//, empty_t).should.untrusted?
-
- hello.gsub(//.untrust, "foo").should_not.untrusted?
- end
- end
-
it "tries to convert pattern to a string using to_str" do
pattern = mock('.')
def pattern.to_str() "." end
@@ -254,8 +210,6 @@ describe "String#gsub with pattern and replacement" do
end
end
- # Note: $~ cannot be tested because mspec messes with it
-
it "sets $~ to MatchData of last match and nil when there's none" do
'hello.'.gsub('hello', 'x')
$~[0].should == 'hello'
@@ -269,6 +223,18 @@ describe "String#gsub with pattern and replacement" do
'hello.'.gsub(/not/, 'x')
$~.should == nil
end
+
+ it "handles a pattern in a superset encoding" do
+ result = 'abc'.force_encoding(Encoding::US_ASCII).gsub('é', 'è')
+ result.should == 'abc'
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ result = 'été'.gsub('t'.force_encoding(Encoding::US_ASCII), 'u')
+ result.should == 'éué'
+ result.encoding.should == Encoding::UTF_8
+ end
end
describe "String#gsub with pattern and Hash" do
@@ -336,28 +302,6 @@ describe "String#gsub with pattern and Hash" do
repl = '\& \0 \1 \` \\\' \+ \\\\ foo'
"hello".gsub(/(.+)/, 'hello' => repl ).should == repl
end
-
- ruby_version_is ''...'2.7' do
- it "untrusts the result if the original string is untrusted" do
- str = "Ghana".untrust
- str.gsub(/[Aa]na/, 'ana' => '').untrusted?.should be_true
- end
-
- it "untrusts the result if a hash value is untrusted" do
- str = "Ghana"
- str.gsub(/a$/, 'a' => 'di'.untrust).untrusted?.should be_true
- end
-
- it "taints the result if the original string is tainted" do
- str = "Ghana".taint
- str.gsub(/[Aa]na/, 'ana' => '').tainted?.should be_true
- end
-
- it "taints the result if a hash value is tainted" do
- str = "Ghana"
- str.gsub(/a$/, 'a' => 'di'.taint).tainted?.should be_true
- end
- end
end
describe "String#gsub! with pattern and Hash" do
@@ -426,28 +370,6 @@ describe "String#gsub! with pattern and Hash" do
repl = '\& \0 \1 \` \\\' \+ \\\\ foo'
"hello".gsub!(/(.+)/, 'hello' => repl ).should == repl
end
-
- ruby_version_is ''...'2.7' do
- it "keeps untrusted state" do
- str = "Ghana".untrust
- str.gsub!(/[Aa]na/, 'ana' => '').untrusted?.should be_true
- end
-
- it "untrusts self if a hash value is untrusted" do
- str = "Ghana"
- str.gsub!(/a$/, 'a' => 'di'.untrust).untrusted?.should be_true
- end
-
- it "keeps tainted state" do
- str = "Ghana".taint
- str.gsub!(/[Aa]na/, 'ana' => '').tainted?.should be_true
- end
-
- it "taints self if a hash value is tainted" do
- str = "Ghana"
- str.gsub!(/a$/, 'a' => 'di'.taint).tainted?.should be_true
- end
- end
end
describe "String#gsub with pattern and block" do
@@ -526,28 +448,6 @@ describe "String#gsub with pattern and block" do
"hello".gsub(/.+/) { obj }.should == "ok"
end
- ruby_version_is ''...'2.7' do
- it "untrusts the result if the original string or replacement is untrusted" do
- hello = "hello"
- hello_t = "hello"
- a = "a"
- a_t = "a"
- empty = ""
- empty_t = ""
-
- hello_t.untrust; a_t.untrust; empty_t.untrust
-
- hello_t.gsub(/./) { a }.should.untrusted?
- hello_t.gsub(/./) { empty }.should.untrusted?
-
- hello.gsub(/./) { a_t }.should.untrusted?
- hello.gsub(/./) { empty_t }.should.untrusted?
- hello.gsub(//) { empty_t }.should.untrusted?
-
- hello.gsub(//.untrust) { "foo" }.should_not.untrusted?
- end
- end
-
it "uses the compatible encoding if they are compatible" do
s = "hello"
s2 = "#{195.chr}#{192.chr}#{195.chr}"
@@ -615,20 +515,6 @@ describe "String#gsub! with pattern and replacement" do
a.should == "*¿** **é*?*"
end
- ruby_version_is ''...'2.7' do
- it "taints self if replacement is tainted" do
- a = "hello"
- 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").should_not.untrusted?
- a.gsub!(/./, "foo".untrust).should.untrusted?
- end
- end
-
it "returns nil if no modifications were made" do
a = "hello"
a.gsub!(/z/, '*').should == nil
@@ -645,6 +531,27 @@ describe "String#gsub! with pattern and replacement" do
-> { s.gsub!(/e/, "e") }.should raise_error(FrozenError)
-> { s.gsub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
end
+
+ it "handles a pattern in a superset encoding" do
+ string = 'abc'.force_encoding(Encoding::US_ASCII)
+
+ result = string.gsub!('é', 'è')
+
+ result.should == nil
+ string.should == 'abc'
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ string = 'été'
+ pattern = 't'.force_encoding(Encoding::US_ASCII)
+
+ result = string.gsub!(pattern, 'u')
+
+ result.should == string
+ string.should == 'éué'
+ string.encoding.should == Encoding::UTF_8
+ end
end
describe "String#gsub! with pattern and block" do
@@ -654,20 +561,6 @@ describe "String#gsub! with pattern and block" do
a.should == "h*ll*"
end
- ruby_version_is ''...'2.7' do
- it "taints self if block's result is tainted" do
- a = "hello"
- 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" }.should_not.untrusted?
- a.gsub!(/./) { "foo".untrust }.should.untrusted?
- end
- end
-
it "returns nil if no modifications were made" do
a = "hello"
a.gsub!(/z/) { '*' }.should == nil
diff --git a/spec/ruby/core/string/include_spec.rb b/spec/ruby/core/string/include_spec.rb
index e32eb17c29..23e1e134ec 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?("")
+ "".force_encoding("EUC-JP").should.include?("")
+ "".should.include?("".force_encoding("EUC-JP"))
+ "".force_encoding("EUC-JP").should.include?("".force_encoding("EUC-JP"))
+ end
+
+ it "returns true if the RHS is empty" do
+ "a".should.include?("")
+ "a".force_encoding("EUC-JP").should.include?("")
+ "a".should.include?("".force_encoding("EUC-JP"))
+ "a".force_encoding("EUC-JP").should.include?("".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")
diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb
index 5d77a88e4e..2eeee9be87 100644
--- a/spec/ruby/core/string/index_spec.rb
+++ b/spec/ruby/core/string/index_spec.rb
@@ -159,6 +159,14 @@ describe "String#index with String" do
"あれ".index char
end.should raise_error(Encoding::CompatibilityError)
end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.force_encoding(Encoding::US_ASCII).index('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.index('t'.force_encoding(Encoding::US_ASCII)).should == 1
+ end
end
describe "String#index with Regexp" do
diff --git a/spec/ruby/core/string/insert_spec.rb b/spec/ruby/core/string/insert_spec.rb
index 752cbb2f37..0c87df3a95 100644
--- a/spec/ruby/core/string/insert_spec.rb
+++ b/spec/ruby/core/string/insert_spec.rb
@@ -41,18 +41,6 @@ describe "String#insert with index, other" do
"abcd".insert(-3, other).should == "abXYZcd"
end
- ruby_version_is ''...'2.7' do
- it "taints self if string to insert is tainted" do
- str = "abcd"
- str.insert(0, "T".taint).should.tainted?
-
- str = "abcd"
- other = mock('T')
- def other.to_str() "T".taint end
- str.insert(0, other).should.tainted?
- end
- end
-
it "raises a TypeError if other can't be converted to string" do
-> { "abcd".insert(-6, Object.new)}.should raise_error(TypeError)
-> { "abcd".insert(-6, []) }.should raise_error(TypeError)
@@ -81,4 +69,13 @@ describe "String#insert with index, other" do
"あれ".insert 0, pat
end.should raise_error(Encoding::CompatibilityError)
end
+
+ it "should not call subclassed string methods" do
+ cls = Class.new(String) do
+ def replace(arg)
+ raise "should not call replace"
+ end
+ end
+ cls.new("abcd").insert(0, 'X').should == "Xabcd"
+ end
end
diff --git a/spec/ruby/core/string/inspect_spec.rb b/spec/ruby/core/string/inspect_spec.rb
index 98b5b32b61..8bf3d3161f 100644
--- a/spec/ruby/core/string/inspect_spec.rb
+++ b/spec/ruby/core/string/inspect_spec.rb
@@ -3,18 +3,6 @@ require_relative '../../spec_helper'
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.should.tainted?
- "foo\n".taint.inspect.should.tainted?
- end
-
- it "untrusts the result if self is untrusted" do
- "foo".untrust.inspect.should.untrusted?
- "foo\n".untrust.inspect.should.untrusted?
- end
- end
-
it "does not return a subclass instance" do
StringSpecs::MyString.new.inspect.should be_an_instance_of(String)
end
@@ -31,6 +19,21 @@ describe "String#inspect" do
].should be_computed_by(:inspect)
end
+ it "returns a string with special characters replaced with \\<char> notation for UTF-16" do
+ pairs = [
+ ["\a", '"\\a"'],
+ ["\b", '"\\b"'],
+ ["\t", '"\\t"'],
+ ["\n", '"\\n"'],
+ ["\v", '"\\v"'],
+ ["\f", '"\\f"'],
+ ["\r", '"\\r"'],
+ ["\e", '"\\e"']
+ ].map { |str, result| [str.encode('UTF-16LE'), result] }
+
+ pairs.should be_computed_by(:inspect)
+ end
+
it "returns a string with \" and \\ escaped with a backslash" do
[ ["\"", '"\\""'],
["\\", '"\\\\"']
@@ -323,6 +326,11 @@ describe "String#inspect" do
"\xF0\x9F".inspect.should == '"\\xF0\\x9F"'
end
+ it "works for broken US-ASCII strings" do
+ s = "©".force_encoding("US-ASCII")
+ s.inspect.should == '"\xC2\xA9"'
+ 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/lines_spec.rb b/spec/ruby/core/string/lines_spec.rb
index ad4b119074..40ab5f71d8 100644
--- a/spec/ruby/core/string/lines_spec.rb
+++ b/spec/ruby/core/string/lines_spec.rb
@@ -1,7 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/each_line'
-require_relative 'shared/each_line_without_block'
describe "String#lines" do
it_behaves_like :string_each_line, :lines
diff --git a/spec/ruby/core/string/ljust_spec.rb b/spec/ruby/core/string/ljust_spec.rb
index 0c3b2a2f44..9a25d3abd4 100644
--- a/spec/ruby/core/string/ljust_spec.rb
+++ b/spec/ruby/core/string/ljust_spec.rb
@@ -31,16 +31,6 @@ describe "String#ljust with length, padding" do
"radiology".ljust(8, '-').should == "radiology"
end
- ruby_version_is ''...'2.7' do
- it "taints result when self or padstr is tainted" do
- "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
-
it "tries to convert length to an integer using to_int" do
"^".ljust(3.8, "_^").should == "^_^"
@@ -96,14 +86,6 @@ describe "String#ljust with length, padding" do
end
end
- ruby_version_is ''...'2.7' do
- it "when padding is tainted and self is untainted returns a tainted string if and only if length is longer than self" do
- "hello".ljust(4, 'X'.taint).tainted?.should be_false
- "hello".ljust(5, 'X'.taint).tainted?.should be_false
- "hello".ljust(6, 'X'.taint).tainted?.should be_true
- end
- end
-
describe "with width" do
it "returns a String in the same encoding as the original" do
str = "abc".force_encoding Encoding::IBM437
diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb
index 6b40189500..75434613f1 100644
--- a/spec/ruby/core/string/lstrip_spec.rb
+++ b/spec/ruby/core/string/lstrip_spec.rb
@@ -1,28 +1,31 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/strip'
describe "String#lstrip" do
+ it_behaves_like :string_strip, :lstrip
+
it "returns a copy of self with leading whitespace removed" do
" hello ".lstrip.should == "hello "
" hello world ".lstrip.should == "hello world "
"\n\r\t\n\v\r hello world ".lstrip.should == "hello world "
"hello".lstrip.should == "hello"
+ " こにちわ".lstrip.should == "こにちわ"
+ end
+
+ it "works with lazy substrings" do
+ " hello "[1...-1].lstrip.should == "hello "
+ " hello world "[1...-1].lstrip.should == "hello world "
+ "\n\r\t\n\v\r hello world "[1...-1].lstrip.should == "hello world "
+ " こにちわ "[1...-1].lstrip.should == "こにちわ"
end
- ruby_version_is '3.1' do
+ ruby_version_is '3.0' 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.should.tainted?
- "ok".taint.lstrip.should.tainted?
- " ok".taint.lstrip.should.tainted?
- end
- end
end
describe "String#lstrip!" do
@@ -32,20 +35,26 @@ describe "String#lstrip!" do
a.should == "hello "
end
- 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
a = "hello"
a.lstrip!.should == nil
a.should == "hello"
end
+ it "makes a string empty if it is only whitespace" do
+ "".lstrip!.should == nil
+ " ".lstrip.should == ""
+ " ".lstrip.should == ""
+ end
+
+ ruby_version_is '3.0' do
+ it "removes leading NULL bytes and whitespace" do
+ a = "\000 \000hello\000 \000"
+ a.lstrip!
+ a.should == "hello\000 \000"
+ end
+ end
+
it "raises a FrozenError on a frozen instance that is modified" do
-> { " hello ".freeze.lstrip! }.should raise_error(FrozenError)
end
@@ -55,4 +64,14 @@ describe "String#lstrip!" do
-> { "hello".freeze.lstrip! }.should raise_error(FrozenError)
-> { "".freeze.lstrip! }.should raise_error(FrozenError)
end
+
+ it "raises an ArgumentError if the first non-space codepoint is invalid" do
+ s = "\xDFabc".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.lstrip! }.should raise_error(ArgumentError)
+
+ s = " \xDFabc".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.lstrip! }.should raise_error(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb
index dc11ced4e2..bf96a82874 100644
--- a/spec/ruby/core/string/modulo_spec.rb
+++ b/spec/ruby/core/string/modulo_spec.rb
@@ -302,29 +302,6 @@ describe "String#%" do
end
end
- ruby_version_is ''...'2.7' do
- it "always taints the result when the format string is tainted" do
- universal = mock('0')
- def universal.to_int() 0 end
- def universal.to_str() "0" end
- def universal.to_f() 0.0 end
-
- [
- "", "foo",
- "%b", "%B", "%c", "%d", "%e", "%E",
- "%f", "%g", "%G", "%i", "%o", "%p",
- "%s", "%u", "%x", "%X"
- ].each do |format|
- subcls_format = StringSpecs::MyString.new(format)
- subcls_format.taint
- format.taint
-
- (format % universal).should.tainted?
- (subcls_format % universal).should.tainted?
- end
- end
- end
-
it "supports binary formats using %b for positive numbers" do
("%b" % 10).should == "1010"
("% b" % 10).should == " 1010"
@@ -391,8 +368,16 @@ describe "String#%" do
("%c" % 'A').should == "A"
end
- it "raises an exception for multiple character strings as argument for %c" do
- -> { "%c" % 'AA' }.should raise_error(ArgumentError)
+ ruby_version_is ""..."3.2" do
+ it "raises an exception for multiple character strings as argument for %c" do
+ -> { "%c" % 'AA' }.should raise_error(ArgumentError)
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "supports only the first character as argument for %c" do
+ ("%c" % 'AA').should == "A"
+ end
end
it "calls to_str on argument for %c formats" do
@@ -578,20 +563,6 @@ describe "String#%" do
# ("%p" % obj).should == "obj"
end
- ruby_version_is ''...'2.7' do
- it "taints result for %p when argument.inspect is tainted" do
- obj = mock('x')
- def obj.inspect() "x".taint end
-
- ("%p" % obj).should.tainted?
-
- obj = mock('x'); obj.taint
- def obj.inspect() "x" end
-
- ("%p" % obj).should_not.tainted?
- end
- end
-
it "supports string formats using %s" do
("%s" % "hello").should == "hello"
("%s" % "").should == ""
@@ -620,13 +591,6 @@ describe "String#%" do
# ("%s" % obj).should == "obj"
end
- ruby_version_is ''...'2.7' do
- it "taints result for %s when argument is tainted" do
- ("%s" % "x".taint).should.tainted?
- ("%s" % mock('x').taint).should.tainted?
- end
- end
-
# MRI crashes on this one.
# See http://groups.google.com/group/ruby-core-google/t/c285c18cd94c216d
it "raises an ArgumentError for huge precisions for %s" do
@@ -786,12 +750,6 @@ describe "String#%" do
it "behaves as if calling Kernel#Float for #{format} arguments, when the passed argument is hexadecimal string" do
(format % "0xA").should == (format % 0xA)
end
-
- ruby_version_is ''...'2.7' do
- it "doesn't taint the result for #{format} when argument is tainted" do
- (format % "5".taint).should_not.tainted?
- end
- end
end
describe "when format string contains %{} sections" do
diff --git a/spec/ruby/core/string/ord_spec.rb b/spec/ruby/core/string/ord_spec.rb
index cfc630a124..4cf26990fe 100644
--- a/spec/ruby/core/string/ord_spec.rb
+++ b/spec/ruby/core/string/ord_spec.rb
@@ -25,4 +25,9 @@ describe "String#ord" do
it "raises an ArgumentError if called on an empty String" do
-> { ''.ord }.should raise_error(ArgumentError)
end
+
+ it "raises ArgumentError if the character is broken" do
+ s = "©".force_encoding("US-ASCII")
+ -> { s.ord }.should raise_error(ArgumentError, "invalid byte sequence in US-ASCII")
+ end
end
diff --git a/spec/ruby/core/string/partition_spec.rb b/spec/ruby/core/string/partition_spec.rb
index 996368d6a4..9cb3672881 100644
--- a/spec/ruby/core/string/partition_spec.rb
+++ b/spec/ruby/core/string/partition_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/partition'
describe "String#partition with String" do
+ it_behaves_like :string_partition, :partition
+
it "returns an array of substrings based on splitting on the given string" do
"hello world".partition("o").should == ["hell", "o", " world"]
end
@@ -35,4 +38,26 @@ describe "String#partition with String" do
it "takes precedence over a given block" do
"hello world".partition("o") { true }.should == ["hell", "o", " world"]
end
+
+ it "handles a pattern in a superset encoding" do
+ string = "hello".force_encoding(Encoding::US_ASCII)
+
+ result = string.partition("é")
+
+ result.should == ["hello", "", ""]
+ result[0].encoding.should == Encoding::US_ASCII
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ pattern = "o".force_encoding(Encoding::US_ASCII)
+
+ result = "héllo world".partition(pattern)
+
+ result.should == ["héll", "o", " world"]
+ result[0].encoding.should == Encoding::UTF_8
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::UTF_8
+ end
end
diff --git a/spec/ruby/core/string/plus_spec.rb b/spec/ruby/core/string/plus_spec.rb
index 9f0db6427c..5ff198f07e 100644
--- a/spec/ruby/core/string/plus_spec.rb
+++ b/spec/ruby/core/string/plus_spec.rb
@@ -32,18 +32,5 @@ describe "String#+" do
("hello" + StringSpecs::MyString.new("")).should be_an_instance_of(String)
end
- ruby_version_is ''...'2.7' do
- it "taints the result when self or other is tainted" do
- strs = ["", "OK", StringSpecs::MyString.new(""), StringSpecs::MyString.new("OK")]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- strs.each do |other|
- (str + other).tainted?.should == (str.tainted? | other.tainted?)
- end
- end
- end
- end
-
it_behaves_like :string_concat_encoding, :+
end
diff --git a/spec/ruby/core/string/prepend_spec.rb b/spec/ruby/core/string/prepend_spec.rb
index a6074be3c6..a0393d4760 100644
--- a/spec/ruby/core/string/prepend_spec.rb
+++ b/spec/ruby/core/string/prepend_spec.rb
@@ -34,16 +34,6 @@ describe "String#prepend" do
a.should == "hello world"
end
- ruby_version_is ''...'2.7' do
- it "taints self if other is tainted" do
- x = "x"
- x.prepend("".taint).tainted?.should be_true
-
- x = "x"
- x.prepend("y".taint).tainted?.should be_true
- end
- end
-
it "takes multiple arguments" do
str = " world"
str.prepend "he", "", "llo"
diff --git a/spec/ruby/core/string/reverse_spec.rb b/spec/ruby/core/string/reverse_spec.rb
index cf4956a528..73526256ef 100644
--- a/spec/ruby/core/string/reverse_spec.rb
+++ b/spec/ruby/core/string/reverse_spec.rb
@@ -10,10 +10,19 @@ describe "String#reverse" do
"".reverse.should == ""
end
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- "".taint.reverse.should.tainted?
- "m".taint.reverse.should.tainted?
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(String)
+ StringSpecs::MyString.new("m").reverse.should be_an_instance_of(String)
+ StringSpecs::MyString.new("").reverse.should be_an_instance_of(String)
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("m").reverse.should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("").reverse.should be_an_instance_of(StringSpecs::MyString)
end
end
@@ -21,6 +30,17 @@ describe "String#reverse" do
"微軟正黑體".reverse.should == "體黑正軟微"
end
+ it "works with a broken string" do
+ str = "微軟\xDF\xDE正黑體".force_encoding(Encoding::UTF_8)
+
+ str.valid_encoding?.should be_false
+
+ str.reverse.should == "體黑正\xDE\xDF軟微"
+ end
+
+ it "returns a String in the same encoding as self" do
+ "stressed".encode("US-ASCII").reverse.encoding.should == Encoding::US_ASCII
+ end
end
describe "String#reverse!" do
@@ -47,4 +67,13 @@ describe "String#reverse!" do
str.reverse!
str.should == "體黑正軟微"
end
+
+ it "works with a broken string" do
+ str = "微軟\xDF\xDE正黑體".force_encoding(Encoding::UTF_8)
+
+ str.valid_encoding?.should be_false
+ str.reverse!
+
+ str.should == "體黑正\xDE\xDF軟微"
+ end
end
diff --git a/spec/ruby/core/string/rindex_spec.rb b/spec/ruby/core/string/rindex_spec.rb
index 7a6af0c9d0..cd2aabba34 100644
--- a/spec/ruby/core/string/rindex_spec.rb
+++ b/spec/ruby/core/string/rindex_spec.rb
@@ -4,13 +4,17 @@ 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, Integer or Regexp" do
+ it "raises a TypeError if obj isn't a String or Regexp" do
not_supported_on :opal do
-> { "hello".rindex(:sym) }.should raise_error(TypeError)
end
-> { "hello".rindex(mock('x')) }.should raise_error(TypeError)
end
+ it "raises a TypeError if obj is an Integer" do
+ -> { "hello".rindex(42) }.should raise_error(TypeError)
+ end
+
it "doesn't try to convert obj to an integer via to_int" do
obj = mock('x')
obj.should_not_receive(:to_int)
@@ -192,6 +196,14 @@ describe "String#rindex with String" do
it "raises a TypeError when given offset is nil" do
-> { "str".rindex("st", nil) }.should raise_error(TypeError)
end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.force_encoding(Encoding::US_ASCII).rindex('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.rindex('t'.force_encoding(Encoding::US_ASCII)).should == 1
+ end
end
describe "String#rindex with Regexp" do
@@ -253,6 +265,15 @@ describe "String#rindex with Regexp" do
$~.should == nil
end
+ it "always clear $~" do
+ "a".rindex(/a/)
+ $~.should_not == nil
+
+ string = "blablabla"
+ string.rindex(/bla/, -(string.length + 1))
+ $~.should == nil
+ end
+
it "starts the search at the given offset" do
"blablabla".rindex(/.{0}/, 5).should == 5
"blablabla".rindex(/.{1}/, 5).should == 5
diff --git a/spec/ruby/core/string/rjust_spec.rb b/spec/ruby/core/string/rjust_spec.rb
index f51aacff44..d067b7bdb3 100644
--- a/spec/ruby/core/string/rjust_spec.rb
+++ b/spec/ruby/core/string/rjust_spec.rb
@@ -31,16 +31,6 @@ describe "String#rjust with length, padding" do
"radiology".rjust(8, '-').should == "radiology"
end
- ruby_version_is ''...'2.7' do
- it "taints result when self or padstr is tainted" do
- "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
-
it "tries to convert length to an integer using to_int" do
"^".rjust(3.8, "^_").should == "^_^"
@@ -96,14 +86,6 @@ describe "String#rjust with length, padding" do
end
end
- ruby_version_is ''...'2.7' do
- it "when padding is tainted and self is untainted returns a tainted string if and only if length is longer than self" do
- "hello".rjust(4, 'X'.taint).tainted?.should be_false
- "hello".rjust(5, 'X'.taint).tainted?.should be_false
- "hello".rjust(6, 'X'.taint).tainted?.should be_true
- end
- end
-
describe "with width" do
it "returns a String in the same encoding as the original" do
str = "abc".force_encoding Encoding::IBM437
diff --git a/spec/ruby/core/string/rpartition_spec.rb b/spec/ruby/core/string/rpartition_spec.rb
index fc37f8b427..21e87f530a 100644
--- a/spec/ruby/core/string/rpartition_spec.rb
+++ b/spec/ruby/core/string/rpartition_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/partition'
describe "String#rpartition with String" do
+ it_behaves_like :string_partition, :rpartition
+
it "returns an array of substrings based on splitting on the given string" do
"hello world".rpartition("o").should == ["hello w", "o", "rld"]
end
@@ -43,4 +46,26 @@ describe "String#rpartition with String" do
->{ "hello".rpartition(5) }.should raise_error(TypeError)
->{ "hello".rpartition(nil) }.should raise_error(TypeError)
end
+
+ it "handles a pattern in a superset encoding" do
+ string = "hello".force_encoding(Encoding::US_ASCII)
+
+ result = string.rpartition("é")
+
+ result.should == ["", "", "hello"]
+ result[0].encoding.should == Encoding::US_ASCII
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ pattern = "o".force_encoding(Encoding::US_ASCII)
+
+ result = "héllo world".rpartition(pattern)
+
+ result.should == ["héllo w", "o", "rld"]
+ result[0].encoding.should == Encoding::UTF_8
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::UTF_8
+ end
end
diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb
index 57e1867956..e96ce4120f 100644
--- a/spec/ruby/core/string/rstrip_spec.rb
+++ b/spec/ruby/core/string/rstrip_spec.rb
@@ -1,25 +1,28 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/strip'
describe "String#rstrip" do
+ it_behaves_like :string_strip, :rstrip
+
it "returns a copy of self with trailing whitespace removed" do
" hello ".rstrip.should == " hello"
" hello world ".rstrip.should == " hello world"
" hello world \n\r\t\n\v\r".rstrip.should == " hello world"
"hello".rstrip.should == "hello"
"hello\x00".rstrip.should == "hello"
+ "こにちわ ".rstrip.should == "こにちわ"
end
- it "returns a copy of self with all trailing whitespace and NULL bytes removed" do
- "\x00 \x00hello\x00 \x00".rstrip.should == "\x00 \x00hello"
+ it "works with lazy substrings" do
+ " hello "[1...-1].rstrip.should == " hello"
+ " hello world "[1...-1].rstrip.should == " hello world"
+ " hello world \n\r\t\n\v\r"[1...-1].rstrip.should == " hello world"
+ " こにちわ "[1...-1].rstrip.should == "こにちわ"
end
- ruby_version_is ''...'2.7' do
- it "taints the result when self is tainted" do
- "".taint.rstrip.should.tainted?
- "ok".taint.rstrip.should.tainted?
- "ok ".taint.rstrip.should.tainted?
- end
+ it "returns a copy of self with all trailing whitespace and NULL bytes removed" do
+ "\x00 \x00hello\x00 \x00".rstrip.should == "\x00 \x00hello"
end
end
@@ -42,6 +45,20 @@ describe "String#rstrip!" do
a.should == "hello"
end
+ it "makes a string empty if it is only whitespace" do
+ "".rstrip!.should == nil
+ " ".rstrip.should == ""
+ " ".rstrip.should == ""
+ end
+
+ ruby_version_is '3.0' do
+ it "removes trailing NULL bytes and whitespace" do
+ a = "\000 goodbye \000"
+ a.rstrip!
+ a.should == "\000 goodbye"
+ end
+ end
+
it "raises a FrozenError on a frozen instance that is modified" do
-> { " hello ".freeze.rstrip! }.should raise_error(FrozenError)
end
@@ -51,4 +68,28 @@ describe "String#rstrip!" do
-> { "hello".freeze.rstrip! }.should raise_error(FrozenError)
-> { "".freeze.rstrip! }.should raise_error(FrozenError)
end
+
+ ruby_version_is "3.2" do
+ it "raises an Encoding::CompatibilityError if the last non-space codepoint is invalid" do
+ s = "abc\xDF".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError)
+
+ s = "abc\xDF ".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError)
+ end
+ end
+
+ ruby_version_is ""..."3.2" do
+ it "raises an ArgumentError if the last non-space codepoint is invalid" do
+ s = "abc\xDF".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.rstrip! }.should raise_error(ArgumentError)
+
+ s = "abc\xDF ".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.rstrip! }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/string/scan_spec.rb b/spec/ruby/core/string/scan_spec.rb
index 024e97022a..a2d1815132 100644
--- a/spec/ruby/core/string/scan_spec.rb
+++ b/spec/ruby/core/string/scan_spec.rb
@@ -65,32 +65,16 @@ describe "String#scan" do
-> { "cruel world".scan(mock('x')) }.should raise_error(TypeError)
end
- ruby_version_is ''...'2.7' do
- it "taints the results if the String argument is tainted" do
- a = "hello hello hello".scan("hello".taint)
- a.each { |m| m.tainted?.should be_true }
- end
-
- it "taints the results when passed a String argument if self is tainted" do
- a = "hello hello hello".taint.scan("hello")
- a.each { |m| m.tainted?.should be_true }
- end
-
- it "taints the results if the Regexp argument is tainted" do
- a = "hello".scan(/./.taint)
- a.each { |m| m.tainted?.should be_true }
- end
-
- it "taints the results when passed a Regexp argument if self is tainted" do
- a = "hello".taint.scan(/./)
- a.each { |m| m.tainted?.should be_true }
- end
- end
-
# jruby/jruby#5513
it "does not raise any errors when passed a multi-byte string" do
"あああaaaあああ".scan("あああ").should == ["あああ", "あああ"]
end
+
+ it "returns Strings in the same encoding as self" do
+ "cruel world".encode("US-ASCII").scan(/\w+/).each do |s|
+ s.encoding.should == Encoding::US_ASCII
+ end
+ end
end
describe "String#scan with pattern and block" do
@@ -173,24 +157,6 @@ describe "String#scan with pattern and block" do
$~.should == nil
end
- ruby_version_is ''...'2.7' do
- it "taints the results if the String argument is tainted" do
- "hello hello hello".scan("hello".taint).each { |m| m.tainted?.should be_true }
- end
-
- it "taints the results when passed a String argument if self is tainted" do
- "hello hello hello".taint.scan("hello").each { |m| m.tainted?.should be_true }
- end
-
- it "taints the results if the Regexp argument is tainted" do
- "hello".scan(/./.taint).each { |m| m.tainted?.should be_true }
- end
-
- it "taints the results when passed a Regexp argument if self is tainted" do
- "hello".taint.scan(/./).each { |m| m.tainted?.should be_true }
- end
- end
-
it "passes block arguments as individual arguments when blocks are provided" do
"a b c\na b c\na b c".scan(/(\w*) (\w*) (\w*)/) do |first,second,third|
first.should == 'a';
@@ -198,4 +164,12 @@ describe "String#scan with pattern and block" do
third.should == 'c';
end
end
+
+ ruby_version_is '3.0' do
+ it "yields String instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("abc").scan(/./) { |s| a << s.class }
+ a.should == [String, String, String]
+ end
+ end
end
diff --git a/spec/ruby/core/string/scrub_spec.rb b/spec/ruby/core/string/scrub_spec.rb
index 5c67ad01bc..a51fbd020a 100644
--- a/spec/ruby/core/string/scrub_spec.rb
+++ b/spec/ruby/core/string/scrub_spec.rb
@@ -1,5 +1,6 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "String#scrub with a default replacement" do
it "returns self for valid strings" do
@@ -13,18 +14,41 @@ describe "String#scrub with a default replacement" do
"abc\u3042#{x81}".scrub.should == "abc\u3042\uFFFD"
end
+ it "replaces invalid byte sequences in lazy substrings" do
+ x81 = [0x81].pack('C').force_encoding('utf-8')
+ "abc\u3042#{x81}def"[1...-1].scrub.should == "bc\u3042\uFFFDde"
+ end
+
it "returns a copy of self when the input encoding is BINARY" do
input = "foo".encode('BINARY')
input.scrub.should == "foo"
end
-
it "replaces invalid byte sequences when using ASCII as the input encoding" do
xE3x80 = [0xE3, 0x80].pack('CC').force_encoding 'utf-8'
input = "abc\u3042#{xE3x80}".force_encoding('ASCII')
input.scrub.should == "abc?????"
end
+
+ it "returns a String in the same encoding as self" do
+ x81 = [0x81].pack('C').force_encoding('utf-8')
+ "abc\u3042#{x81}".scrub.encoding.should == Encoding::UTF_8
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(String)
+ input = [0x81].pack('C').force_encoding('utf-8')
+ StringSpecs::MyString.new(input).scrub.should be_an_instance_of(String)
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
end
describe "String#scrub with a custom replacement" do
@@ -42,7 +66,9 @@ describe "String#scrub with a custom replacement" do
it "replaces invalid byte sequences in frozen strings" do
x81 = [0x81].pack('C').force_encoding('utf-8')
(-"abc\u3042#{x81}").scrub("*").should == "abc\u3042*"
- utf16_str = ("abc".encode('UTF-16LE').bytes + [0x81]).pack('c*').force_encoding('UTF-16LE')
+
+ leading_surrogate = [0x00, 0xD8]
+ utf16_str = ("abc".encode('UTF-16LE').bytes + leading_surrogate).pack('c*').force_encoding('UTF-16LE')
(-(utf16_str)).scrub("*".encode('UTF-16LE')).should == "abc*".encode('UTF-16LE')
end
@@ -59,12 +85,25 @@ describe "String#scrub with a custom replacement" do
block.should raise_error(ArgumentError)
end
+ it "returns a String in the same encoding as self" do
+ x81 = [0x81].pack('C').force_encoding('utf-8')
+ "abc\u3042#{x81}".scrub("*").encoding.should == Encoding::UTF_8
+ end
+
it "raises TypeError when a non String replacement is given" do
x81 = [0x81].pack('C').force_encoding('utf-8')
block = -> { "foo#{x81}".scrub(1) }
block.should raise_error(TypeError)
end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub("*").should be_an_instance_of(String)
+ input = [0x81].pack('C').force_encoding('utf-8')
+ StringSpecs::MyString.new(input).scrub("*").should be_an_instance_of(String)
+ end
+ end
end
describe "String#scrub with a block" do
@@ -89,6 +128,14 @@ describe "String#scrub with a block" do
replaced.should == "€€"
end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("foo").scrub { |b| "*" }.should be_an_instance_of(String)
+ input = [0x81].pack('C').force_encoding('utf-8')
+ StringSpecs::MyString.new(input).scrub { |b| "<#{b.unpack("H*")[0]}>" }.should be_an_instance_of(String)
+ end
+ end
end
describe "String#scrub!" do
diff --git a/spec/ruby/core/string/setbyte_spec.rb b/spec/ruby/core/string/setbyte_spec.rb
index 03e5bad88b..77bff64038 100644
--- a/spec/ruby/core/string/setbyte_spec.rb
+++ b/spec/ruby/core/string/setbyte_spec.rb
@@ -36,6 +36,12 @@ describe "String#setbyte" do
str.valid_encoding?.should be_true
str.setbyte(2,253)
str.valid_encoding?.should be_false
+
+ str = "ABC"
+ str.setbyte(0, 0x20) # ' '
+ str.should.valid_encoding?
+ str.setbyte(0, 0xE3)
+ str.should_not.valid_encoding?
end
it "regards a negative index as counting from the end of the String" do
diff --git a/spec/ruby/core/string/shared/chars.rb b/spec/ruby/core/string/shared/chars.rb
index 1f045e4530..e9fdf89fd6 100644
--- a/spec/ruby/core/string/shared/chars.rb
+++ b/spec/ruby/core/string/shared/chars.rb
@@ -63,18 +63,4 @@ describe :string_chars, shared: true do
[0xA2].pack('C').force_encoding('SJIS')
]
end
-
- ruby_version_is ''...'2.7' do
- it "taints resulting strings when self is tainted" do
- str = "hello"
-
- str.send(@method) do |x|
- x.should_not.tainted?
- end
-
- str.dup.taint.send(@method) do |x|
- x.should.tainted?
- end
- end
- end
end
diff --git a/spec/ruby/core/string/shared/concat.rb b/spec/ruby/core/string/shared/concat.rb
index d6ffad7d4d..54ac1035d3 100644
--- a/spec/ruby/core/string/shared/concat.rb
+++ b/spec/ruby/core/string/shared/concat.rb
@@ -39,18 +39,6 @@ describe :string_concat, shared: true do
str.should be_an_instance_of(StringSpecs::MyString)
end
- ruby_version_is ''...'2.7' do
- it "taints self if other is tainted" do
- "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).should.untrusted?
- "x".send(@method, "y".untrust).should.untrusted?
- end
- end
-
describe "with Integer" do
it "concatenates the argument interpreted as a codepoint" do
b = "".send(@method, 33)
diff --git a/spec/ruby/core/string/shared/dedup.rb b/spec/ruby/core/string/shared/dedup.rb
new file mode 100644
index 0000000000..6ffcb9b045
--- /dev/null
+++ b/spec/ruby/core/string/shared/dedup.rb
@@ -0,0 +1,57 @@
+describe :string_dedup, shared: true do
+ it 'returns self if the String is frozen' do
+ input = 'foo'.freeze
+ output = input.send(@method)
+
+ output.should equal(input)
+ output.should.frozen?
+ end
+
+ it 'returns a frozen copy if the String is not frozen' do
+ input = 'foo'
+ output = input.send(@method)
+
+ output.should.frozen?
+ output.should_not equal(input)
+ output.should == 'foo'
+ end
+
+ 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.send(@method).should equal(dynamic.send(@method))
+ end
+
+ it "returns the same object when it's called on the same String literal" do
+ "unfrozen string".send(@method).should equal("unfrozen string".send(@method))
+ "unfrozen string".send(@method).should_not equal("another unfrozen string".send(@method))
+ end
+
+ it "deduplicates frozen strings" do
+ dynamic = %w(this string is frozen).join(' ').freeze
+
+ dynamic.should_not equal("this string is frozen".freeze)
+
+ dynamic.send(@method).should equal("this string is frozen".freeze)
+ dynamic.send(@method).should equal("this string is frozen".send(@method).freeze)
+ end
+
+ it "does not deduplicate a frozen string when it has instance variables" do
+ dynamic = %w(this string is frozen).join(' ')
+ dynamic.instance_variable_set(:@a, 1)
+ dynamic.freeze
+
+ dynamic.send(@method).should_not equal("this string is frozen".freeze)
+ dynamic.send(@method).should_not equal("this string is frozen".send(@method).freeze)
+ dynamic.send(@method).should equal(dynamic)
+ 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.send(@method).should equal(dynamic)
+ end
+ end
+end
diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb
index f9c910596a..df78bd2186 100644
--- a/spec/ruby/core/string/shared/each_line.rb
+++ b/spec/ruby/core/string/shared/each_line.rb
@@ -40,14 +40,6 @@ describe :string_each_line, shared: true do
b.should == ["foo\n", "🤡🤡🤡🤡🤡🤡🤡\n", "bar\n", "baz\n"]
end
- 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.should.tainted? }
-
- "x.y.".send(@method, ".".taint) { |s| s.should_not.tainted? }
- end
- end
-
it "passes self as a whole to the block if the separator is nil" do
a = []
"one\ntwo\r\nthree".send(@method, nil) { |s| a << s }
@@ -130,6 +122,12 @@ describe :string_each_line, shared: true do
out.should == ["hello\n", "world."]
end
+ it "returns Strings in the same encoding as self" do
+ "one\ntwo\r\nthree".encode("US-ASCII").send(@method) do |s|
+ s.encoding.should == Encoding::US_ASCII
+ end
+ end
+
it "raises a TypeError when the separator can't be converted to a string" do
-> { "hello world".send(@method, false) {} }.should raise_error(TypeError)
-> { "hello world".send(@method, mock('x')) {} }.should raise_error(TypeError)
diff --git a/spec/ruby/core/string/shared/eql.rb b/spec/ruby/core/string/shared/eql.rb
index 85b861f4f1..6f268c929c 100644
--- a/spec/ruby/core/string/shared/eql.rb
+++ b/spec/ruby/core/string/shared/eql.rb
@@ -21,7 +21,7 @@ describe :string_eql_value, shared: true do
end
it "considers encoding compatibility" do
- "hello".force_encoding("utf-8").send(@method, "hello".force_encoding("utf-32le")).should be_false
+ "abcd".force_encoding("utf-8").send(@method, "abcd".force_encoding("utf-32le")).should be_false
end
it "ignores subclass differences" do
@@ -31,4 +31,8 @@ describe :string_eql_value, shared: true do
a.send(@method, b).should be_true
b.send(@method, a).should be_true
end
+
+ it "returns true when comparing 2 empty strings but one is not ASCII-compatible" do
+ "".send(@method, "".force_encoding('iso-2022-jp')).should == true
+ end
end
diff --git a/spec/ruby/core/string/shared/length.rb b/spec/ruby/core/string/shared/length.rb
index b9eae5170f..94e5ec135b 100644
--- a/spec/ruby/core/string/shared/length.rb
+++ b/spec/ruby/core/string/shared/length.rb
@@ -12,9 +12,9 @@ describe :string_length, shared: true do
it "returns the length of a string in different encodings" do
utf8_str = 'こにちわ' * 100
- utf8_str.size.should == 400
- utf8_str.encode(Encoding::UTF_32BE).size.should == 400
- utf8_str.encode(Encoding::SHIFT_JIS).size.should == 400
+ utf8_str.send(@method).should == 400
+ utf8_str.encode(Encoding::UTF_32BE).send(@method).should == 400
+ utf8_str.encode(Encoding::SHIFT_JIS).send(@method).should == 400
end
it "returns the length of the new self after encoding is changed" do
@@ -32,8 +32,24 @@ describe :string_length, shared: true do
concat.encoding.should == Encoding::UTF_8
concat.bytesize.should == 4
- concat.size.should == 2
+ concat.send(@method).should == 2
concat.force_encoding(Encoding::ASCII_8BIT)
- concat.size.should == 4
+ concat.send(@method).should == 4
+ end
+
+ it "adds 1 for every invalid byte in UTF-8" do
+ "\xF4\x90\x80\x80".send(@method).should == 4
+ "a\xF4\x90\x80\x80b".send(@method).should == 6
+ "é\xF4\x90\x80\x80è".send(@method).should == 6
+ end
+
+ it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do
+ "\x00\xd8".force_encoding("UTF-16LE").send(@method).should == 1
+ "\xd8\x00".force_encoding("UTF-16BE").send(@method).should == 1
+ end
+
+ it "adds 1 for a broken sequence in UTF-32" do
+ "\x04\x03\x02\x01".force_encoding("UTF-32LE").send(@method).should == 1
+ "\x01\x02\x03\x04".force_encoding("UTF-32BE").send(@method).should == 1
end
end
diff --git a/spec/ruby/core/string/shared/partition.rb b/spec/ruby/core/string/shared/partition.rb
new file mode 100644
index 0000000000..41b3c7e0c9
--- /dev/null
+++ b/spec/ruby/core/string/shared/partition.rb
@@ -0,0 +1,51 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+
+describe :string_partition, shared: true do
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").send(@method, "l").each do |item|
+ item.should be_an_instance_of(String)
+ end
+
+ StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
+ item.should be_an_instance_of(String)
+ end
+
+ StringSpecs::MyString.new("hello").send(@method, /l./).each do |item|
+ item.should be_an_instance_of(String)
+ end
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").send(@method, StringSpecs::MyString.new("l")).each do |item|
+ item.should be_an_instance_of(StringSpecs::MyString)
+ end
+
+ StringSpecs::MyString.new("hello").send(@method, "x").each do |item|
+ item.should be_an_instance_of(StringSpecs::MyString)
+ end
+
+ StringSpecs::MyString.new("hello").send(@method, /l./).each do |item|
+ item.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+ end
+
+ it "returns before- and after- parts in the same encoding as self" do
+ strings = "hello".encode("US-ASCII").send(@method, "ello")
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[2].encoding.should == Encoding::US_ASCII
+
+ strings = "hello".encode("US-ASCII").send(@method, /ello/)
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns the matching part in the separator's encoding" do
+ strings = "hello".encode("US-ASCII").send(@method, "ello")
+ strings[1].encoding.should == Encoding::UTF_8
+ end
+end
diff --git a/spec/ruby/core/string/shared/replace.rb b/spec/ruby/core/string/shared/replace.rb
index 8dfac49f02..a5108d9e7c 100644
--- a/spec/ruby/core/string/shared/replace.rb
+++ b/spec/ruby/core/string/shared/replace.rb
@@ -10,36 +10,6 @@ describe :string_replace, shared: true do
a.should == "another string"
end
- ruby_version_is ''...'2.7' do
- it "taints self if other is tainted" do
- a = ""
- b = "".taint
- a.send(@method, b)
- a.should.tainted?
- end
-
- it "does not untaint self if other is untainted" do
- a = "".taint
- b = ""
- a.send(@method, b)
- a.should.tainted?
- end
-
- it "untrusts self if other is untrusted" do
- a = ""
- b = "".untrust
- a.send(@method, b)
- a.should.untrusted?
- end
-
- it "does not trust self if other is trusted" do
- a = "".untrust
- b = ""
- a.send(@method, b)
- a.should.untrusted?
- end
- end
-
it "replaces the encoding of self with that of other" do
a = "".encode("UTF-16LE")
b = "".encode("UTF-8")
diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb
index 1db8fd6730..a7c1d05b56 100644
--- a/spec/ruby/core/string/shared/slice.rb
+++ b/spec/ruby/core/string/shared/slice.rb
@@ -80,18 +80,7 @@ describe :string_slice_index_length, shared: true do
"hello there".send(@method, -3,2).should == "er"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self is tainted" do
- str = "hello world"
- str.taint
-
- str.send(@method, 0,0).should.tainted?
- str.send(@method, 0,1).should.tainted?
- str.send(@method, 2,1).should.tainted?
- end
- end
-
- it "returns a string with the same encoding" do
+ it "returns a string with the same encoding as self" do
s = "hello there"
s.send(@method, 1, 9).encoding.should == s.encoding
@@ -217,6 +206,10 @@ describe :string_slice_range, shared: true do
"x".send(@method, 1..-1).should == ""
end
+ it "returns a String in the same encoding as self" do
+ "hello there".encode("US-ASCII").send(@method, 1..1).encoding.should == Encoding::US_ASCII
+ end
+
it "returns nil if the beginning of the range falls outside of self" do
"hello there".send(@method, 12..-1).should == nil
"hello there".send(@method, 20..25).should == nil
@@ -249,20 +242,6 @@ describe :string_slice_range, shared: true do
"x".send(@method, 1...-1).should == ""
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self is tainted" do
- str = "hello world"
- str.taint
-
- str.send(@method, 0..0).should.tainted?
- str.send(@method, 0...0).should.tainted?
- str.send(@method, 0..1).should.tainted?
- str.send(@method, 0...1).should.tainted?
- str.send(@method, 2..3).should.tainted?
- str.send(@method, 2..0).should.tainted?
- end
- end
-
ruby_version_is ''...'3.0' do
it "returns subclass instances" do
s = StringSpecs::MyString.new("hello")
@@ -334,14 +313,12 @@ describe :string_slice_range, shared: true do
"hello there".send(@method, eval("(-4...)")).should == "here"
end
- ruby_version_is "2.7" do
- it "works with beginless ranges" do
- "hello there".send(@method, eval("(..5)")).should == "hello "
- "hello there".send(@method, eval("(...5)")).should == "hello"
- "hello there".send(@method, eval("(..-4)")).should == "hello th"
- "hello there".send(@method, eval("(...-4)")).should == "hello t"
- "hello there".send(@method, eval("(...nil)")).should == "hello there"
- end
+ it "works with beginless ranges" do
+ "hello there".send(@method, (..5)).should == "hello "
+ "hello there".send(@method, (...5)).should == "hello"
+ "hello there".send(@method, (..-4)).should == "hello th"
+ "hello there".send(@method, (...-4)).should == "hello t"
+ "hello there".send(@method, (...nil)).should == "hello there"
end
end
@@ -355,27 +332,8 @@ describe :string_slice_regexp, shared: true do
"hello there".send(@method, /xyz/).should == nil
end
- not_supported_on :opal do
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self or regexp is tainted" do
- strs = ["hello world"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- str.send(@method, //).tainted?.should == str.tainted?
- str.send(@method, /hello/).tainted?.should == str.tainted?
-
- tainted_re = /./
- tainted_re.taint
-
- str.send(@method, tainted_re).should.tainted?
- end
- end
-
- it "returns an untrusted string if the regexp is untrusted" do
- "hello".send(@method, /./.untrust).untrusted?.should be_true
- end
- end
+ it "returns a String in the same encoding as self" do
+ "hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/).encoding.should == Encoding::US_ASCII
end
ruby_version_is ''...'3.0' do
@@ -418,44 +376,28 @@ describe :string_slice_regexp_index, shared: true do
"har".send(@method, /(.)(.)(.)/, -3).should == "h"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self or regexp is tainted" do
- strs = ["hello world"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- str.send(@method, //, 0).tainted?.should == str.tainted?
- str.send(@method, /hello/, 0).tainted?.should == str.tainted?
-
- str.send(@method, /(.)(.)(.)/, 0).tainted?.should == str.tainted?
- str.send(@method, /(.)(.)(.)/, 1).tainted?.should == str.tainted?
- str.send(@method, /(.)(.)(.)/, -1).tainted?.should == str.tainted?
- str.send(@method, /(.)(.)(.)/, -2).tainted?.should == str.tainted?
-
- tainted_re = /(.)(.)(.)/
- tainted_re.taint
-
- 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
-
- not_supported_on :opal do
- it "returns an untrusted string if the regexp is untrusted" do
- "hello".send(@method, /(.)/.untrust, 1).untrusted?.should be_true
- end
- end
- end
-
it "returns nil if there is no match" do
"hello there".send(@method, /(what?)/, 1).should == nil
end
+ it "returns nil if the index is larger than the number of captures" do
+ "hello there".send(@method, /hello (.)/, 2).should == nil
+ # You can't refer to 0 using negative indices
+ "hello there".send(@method, /hello (.)/, -2).should == nil
+ end
+
it "returns nil if there is no capture for the given index" do
"hello there".send(@method, /[aeiou](.)\1/, 2).should == nil
- # You can't refer to 0 using negative indices
- "hello there".send(@method, /[aeiou](.)\1/, -2).should == nil
+ end
+
+ it "returns nil if the given capture group was not matched but still sets $~" do
+ "test".send(@method, /te(z)?/, 1).should == nil
+ $~[0].should == "te"
+ $~[1].should == nil
+ end
+
+ it "returns a String in the same encoding as self" do
+ "hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/, 0).encoding.should == Encoding::US_ASCII
end
it "calls to_int on the given index" do
@@ -510,21 +452,6 @@ describe :string_slice_string, shared: true do
"hello there".send(@method, s).should == s
end
- ruby_version_is ''...'2.7' do
- it "taints resulting strings when other is tainted" do
- strs = ["", "hello world", "hello"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- strs.each do |other|
- r = str.send(@method, other)
-
- r.tainted?.should == !r.nil? & other.tainted?
- end
- end
- end
- end
-
it "doesn't set $~" do
$~ = nil
@@ -584,30 +511,6 @@ describe :string_slice_regexp_group, shared: true do
"hello there".send(@method, /(?<g>h(?<g>.))/, 'g').should == "e"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self or regexp is tainted" do
- strs = ["hello world"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- str.send(@method, /(?<hi>hello)/, 'hi').tainted?.should == str.tainted?
-
- str.send(@method, /(?<g>(.)(.)(.))/, 'g').tainted?.should == str.tainted?
- str.send(@method, /(?<h>.)(.)(.)/, 'h').tainted?.should == str.tainted?
- str.send(@method, /(.)(?<a>.)(.)/, 'a').tainted?.should == str.tainted?
- str.send(@method, /(.)(.)(?<r>.)/, 'r').tainted?.should == str.tainted?
- str.send(@method, /(?<h>.)(?<a>.)(?<r>.)/, 'r').tainted?.should == str.tainted?
-
- tainted_re = /(?<a>.)(?<b>.)(?<c>.)/
- tainted_re.taint
-
- str.send(@method, tainted_re, 'a').tainted?.should be_true
- str.send(@method, tainted_re, 'b').tainted?.should be_true
- str.send(@method, tainted_re, 'c').tainted?.should be_true
- end
- end
- end
-
it "returns nil if there is no match" do
"hello there".send(@method, /(?<whut>what?)/, 'whut').should be_nil
end
diff --git a/spec/ruby/core/string/shared/strip.rb b/spec/ruby/core/string/shared/strip.rb
new file mode 100644
index 0000000000..0c0aae20f3
--- /dev/null
+++ b/spec/ruby/core/string/shared/strip.rb
@@ -0,0 +1,24 @@
+require_relative '../../../spec_helper'
+require_relative '../fixtures/classes'
+
+describe :string_strip, shared: true do
+ it "returns a String in the same encoding as self" do
+ " hello ".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(String)
+ StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(String)
+ StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String)
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+end
diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb
index 25602103b6..3605fa99a2 100644
--- a/spec/ruby/core/string/shared/succ.rb
+++ b/spec/ruby/core/string/shared/succ.rb
@@ -75,12 +75,8 @@ describe :string_succ, shared: true do
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).should.tainted?
- end
- end
+ it "returns a String in the same encoding as self" do
+ "z".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
end
end
diff --git a/spec/ruby/core/string/shared/to_s.rb b/spec/ruby/core/string/shared/to_s.rb
index b8c9b8ab44..4b87a6cbe1 100644
--- a/spec/ruby/core/string/shared/to_s.rb
+++ b/spec/ruby/core/string/shared/to_s.rb
@@ -10,11 +10,4 @@ describe :string_to_s, shared: true do
s.should == "a string"
s.should be_an_instance_of(String)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the result when self is tainted" do
- "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 416f302aef..ef7c22bb6a 100644
--- a/spec/ruby/core/string/shared/to_sym.rb
+++ b/spec/ruby/core/string/shared/to_sym.rb
@@ -53,6 +53,15 @@ describe :string_to_sym, shared: true do
sym.to_s.should == binary_string
end
+ it "ignores existing symbols with different encoding" do
+ source = "fée"
+
+ iso_symbol = source.force_encoding(Encoding::ISO_8859_1).send(@method)
+ iso_symbol.encoding.should == Encoding::ISO_8859_1
+ binary_symbol = source.force_encoding(Encoding::BINARY).send(@method)
+ binary_symbol.encoding.should == Encoding::BINARY
+ end
+
it "raises an EncodingError for UTF-8 String containing invalid bytes" do
invalid_utf8 = "\xC3"
invalid_utf8.should_not.valid_encoding?
diff --git a/spec/ruby/core/string/slice_spec.rb b/spec/ruby/core/string/slice_spec.rb
index 83b475c8b5..c9e13ed1bc 100644
--- a/spec/ruby/core/string/slice_spec.rb
+++ b/spec/ruby/core/string/slice_spec.rb
@@ -94,16 +94,6 @@ describe "String#slice! with index, length" do
a.should == "h"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self is tainted" do
- str = "hello world"
- str.taint
-
- str.slice!(0, 0).should.tainted?
- str.slice!(2, 1).should.tainted?
- end
- end
-
it "returns nil if the given position is out of self" do
a = "hello"
a.slice(10, 3).should == nil
@@ -195,16 +185,6 @@ describe "String#slice! Range" do
b.should == "hello"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self is tainted" do
- str = "hello world"
- str.taint
-
- 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")
@@ -294,30 +274,6 @@ describe "String#slice! with Regexp" do
s.should == "this is a string"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self or regexp is tainted" do
- strs = ["hello world"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- str = str.dup
- str.slice!(//).tainted?.should == str.tainted?
- str.slice!(/hello/).tainted?.should == str.tainted?
-
- tainted_re = /./
- tainted_re.taint
-
- str.slice!(tainted_re).should.tainted?
- end
- end
-
- it "doesn't taint self when regexp is tainted" do
- s = "hello"
- s.slice!(/./.taint)
- s.should_not.tainted?
- end
- end
-
ruby_version_is ''...'3.0' do
it "returns subclass instances" do
s = StringSpecs::MyString.new("hello")
@@ -365,30 +321,6 @@ describe "String#slice! with Regexp, index" do
str.should == "ho here"
end
- ruby_version_is ''...'2.7' do
- it "always taints resulting strings when self or regexp is tainted" do
- strs = ["hello world"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- str = str.dup
- str.slice!(//, 0).tainted?.should == str.tainted?
- str.slice!(/hello/, 0).tainted?.should == str.tainted?
-
- tainted_re = /(.)(.)(.)/
- tainted_re.taint
-
- 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.should_not.tainted?
- end
- end
-
it "returns nil if there was no match" do
s = "this is a string"
s.slice!(/x(zzz)/, 1).should == nil
@@ -463,23 +395,6 @@ describe "String#slice! with String" do
c.should == "he hello"
end
- ruby_version_is ''...'2.7' do
- it "taints resulting strings when other is tainted" do
- strs = ["", "hello world", "hello"]
- strs += strs.map { |s| s.dup.taint }
-
- strs.each do |str|
- str = str.dup
- strs.each do |other|
- other = other.dup
- r = str.slice!(other)
-
- r.tainted?.should == !r.nil? & other.tainted?
- end
- end
- end
- end
-
it "doesn't set $~" do
$~ = nil
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index a373be360d..519c5d845d 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -3,12 +3,17 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "String#split with String" do
+ it "throws an ArgumentError if the string is not a valid" do
+ s = "\xDF".force_encoding(Encoding::UTF_8)
+
+ -> { s.split }.should raise_error(ArgumentError)
+ -> { s.split(':') }.should raise_error(ArgumentError)
+ end
+
it "throws an ArgumentError if the pattern is not a valid string" do
str = 'проверка'
- broken_str = 'проверка'
- broken_str.force_encoding('binary')
- broken_str.chop!
- broken_str.force_encoding('utf-8')
+ broken_str = "\xDF".force_encoding(Encoding::UTF_8)
+
-> { str.split(broken_str) }.should raise_error(ArgumentError)
end
@@ -24,9 +29,35 @@ describe "String#split with String" do
"1,2,,3,4,,".split(',').should == ["1", "2", "", "3", "4"]
"1,2,,3,4,,".split(',', 0).should == ["1", "2", "", "3", "4"]
" a b c\nd ".split(" ").should == ["", "a", "b", "c\nd"]
+ " a あ c\nd ".split(" ").should == ["", "a", "あ", "c\nd"]
"hai".split("hai").should == []
",".split(",").should == []
",".split(",", 0).should == []
+ "あ".split("あ").should == []
+ "あ".split("あ", 0).should == []
+ end
+
+ it "does not suppress trailing empty fields when a positive limit is given" do
+ " 1 2 ".split(" ", 2).should == ["1", "2 "]
+ " 1 2 ".split(" ", 3).should == ["1", "2", ""]
+ " 1 2 ".split(" ", 4).should == ["1", "2", ""]
+ " 1 あ ".split(" ", 2).should == ["1", "あ "]
+ " 1 あ ".split(" ", 3).should == ["1", "あ", ""]
+ " 1 あ ".split(" ", 4).should == ["1", "あ", ""]
+
+ "1,2,".split(',', 2).should == ["1", "2,"]
+ "1,2,".split(',', 3).should == ["1", "2", ""]
+ "1,2,".split(',', 4).should == ["1", "2", ""]
+ "1,あ,".split(',', 2).should == ["1", "あ,"]
+ "1,あ,".split(',', 3).should == ["1", "あ", ""]
+ "1,あ,".split(',', 4).should == ["1", "あ", ""]
+
+ "1 2 ".split(/ /, 2).should == ["1", "2 "]
+ "1 2 ".split(/ /, 3).should == ["1", "2", ""]
+ "1 2 ".split(/ /, 4).should == ["1", "2", ""]
+ "1 あ ".split(/ /, 2).should == ["1", "あ "]
+ "1 あ ".split(/ /, 3).should == ["1", "あ", ""]
+ "1 あ ".split(/ /, 4).should == ["1", "あ", ""]
end
it "returns an array with one entry if limit is 1: the original string" do
@@ -62,6 +93,10 @@ describe "String#split with String" do
",".split(",", -1).should == ["", ""]
end
+ it "raises a RangeError when the limit is larger than int" do
+ -> { "a,b".split(" ", 2147483649) }.should raise_error(RangeError)
+ end
+
it "defaults to $; when string isn't given or nil" do
suppress_warning do
old_fs = $;
@@ -85,21 +120,19 @@ describe "String#split with String" do
end
end
- ruby_version_is "2.7" do
- context "when $; is not nil" do
- before do
- suppress_warning do
- @old_value, $; = $;, 'foobar'
- end
+ context "when $; is not nil" do
+ before do
+ suppress_warning do
+ @old_value, $; = $;, 'foobar'
end
+ end
- after do
- $; = @old_value
- end
+ after do
+ $; = @old_value
+ end
- it "warns" do
- -> { "".split }.should complain(/warning: \$; is set to non-nil value/)
- end
+ it "warns" do
+ -> { "".split }.should complain(/warning: \$; is set to non-nil value/)
end
end
end
@@ -203,26 +236,32 @@ describe "String#split with String" do
end
end
- ruby_version_is ''...'2.7' do
- it "taints the resulting strings if self is tainted" do
- ["", "x.y.z.", " x y "].each do |str|
- ["", ".", " "].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- str.dup.taint.split(pat).each do |x|
- x.should.tainted?
- end
+ it "returns an empty array when whitespace is split on whitespace" do
+ " ".split(" ").should == []
+ " \n ".split(" ").should == []
+ " ".split(" ").should == []
+ " \t ".split(" ").should == []
+ end
- str.split(pat.dup.taint).each do |x|
- x.should_not.tainted?
- end
- end
- end
- end
- end
+ it "doesn't split on non-ascii whitespace" do
+ "a\u{2008}b".split(" ").should == ["a\u{2008}b"]
+ end
+
+ it "returns Strings in the same encoding as self" do
+ strings = "hello world".encode("US-ASCII").split(" ")
+
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[1].encoding.should == Encoding::US_ASCII
end
end
describe "String#split with Regexp" do
+ it "throws an ArgumentError if the string is not a valid" do
+ s = "\xDF".force_encoding(Encoding::UTF_8)
+
+ -> { s.split(/./) }.should raise_error(ArgumentError)
+ end
+
it "divides self on regexp matches" do
" now's the time".split(/ /).should == ["", "now's", "", "the", "time"]
" x\ny ".split(/ /).should == ["", "x\ny"]
@@ -411,44 +450,12 @@ describe "String#split with Regexp" do
end
end
- ruby_version_is ''...'2.7' do
- it "taints the resulting strings if self is tainted" do
- ["", "x:y:z:", " x y "].each do |str|
- [//, /:/, /\s+/].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- str.dup.taint.split(pat, limit).each do |x|
- # See the spec below for why the conditional is here
- x.tainted?.should be_true unless x.empty?
- end
- end
- end
- end
- end
-
- it "taints an empty string if self is tainted" do
- ":".taint.split(//, -1).last.tainted?.should be_true
- end
-
- it "doesn't taints the resulting strings if the Regexp is tainted" do
- ["", "x:y:z:", " x y "].each do |str|
- [//, /:/, /\s+/].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- str.split(pat.dup.taint, limit).each do |x|
- x.tainted?.should be_false
- end
- end
- end
- end
- end
- end
-
- it "retains the encoding of the source string" do
+ it "returns Strings in the same encoding as self" do
ary = "а б в".split
encodings = ary.map { |s| s.encoding }
encodings.should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8]
end
-
it "splits a string on each character for a multibyte encoding and empty split" do
"That's why efficiency could not be helped".split("").size.should == 39
end
@@ -480,6 +487,14 @@ describe "String#split with Regexp" do
a.should == ["Chunky", "Bacon"]
end
+ it "yields each split substring with default pattern for a lazy substring" do
+ a = []
+ returned_object = "chunky bacon"[1...-1].split { |str| a << str.capitalize }
+
+ returned_object.should == "hunky baco"
+ a.should == ["Hunky", "Baco"]
+ end
+
it "yields each split substring with default pattern for a non-ASCII string" do
a = []
returned_object = "l'été arrive bientôt".split { |str| a << str }
@@ -488,6 +503,14 @@ describe "String#split with Regexp" do
a.should == ["l'été", "arrive", "bientôt"]
end
+ it "yields each split substring with default pattern for a non-ASCII lazy substring" do
+ a = []
+ returned_object = "l'été arrive bientôt"[1...-1].split { |str| a << str }
+
+ returned_object.should == "'été arrive bientô"
+ a.should == ["'été", "arrive", "bientô"]
+ end
+
it "yields the string when limit is 1" do
a = []
returned_object = "chunky bacon".split("", 1) { |str| a << str.capitalize }
@@ -574,4 +597,18 @@ describe "String#split with Regexp" do
end
end
end
+
+ it "raises a TypeError when not called with nil, String, or Regexp" do
+ -> { "hello".split(42) }.should raise_error(TypeError)
+ -> { "hello".split(:ll) }.should raise_error(TypeError)
+ -> { "hello".split(false) }.should raise_error(TypeError)
+ -> { "hello".split(Object.new) }.should raise_error(TypeError)
+ end
+
+ it "returns Strings in the same encoding as self" do
+ strings = "hello world".encode("US-ASCII").split(/ /)
+
+ strings[0].encoding.should == Encoding::US_ASCII
+ strings[1].encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/core/string/squeeze_spec.rb b/spec/ruby/core/string/squeeze_spec.rb
index 6f75402c9c..2f3fa65745 100644
--- a/spec/ruby/core/string/squeeze_spec.rb
+++ b/spec/ruby/core/string/squeeze_spec.rb
@@ -54,16 +54,6 @@ describe "String#squeeze" do
-> { s.squeeze("^e-b") }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "taints the result when self is tainted" do
- "hello".taint.squeeze("e").should.tainted?
- "hello".taint.squeeze("a-z").should.tainted?
-
- "hello".squeeze("e".taint).should_not.tainted?
- "hello".squeeze("l".taint).should_not.tainted?
- end
- end
-
it "tries to convert each set arg to a string using to_str" do
other_string = mock('lo')
other_string.should_receive(:to_str).and_return("lo")
@@ -74,6 +64,11 @@ describe "String#squeeze" do
"hello room".squeeze(other_string, other_string2).should == "hello rom"
end
+ it "returns a String in the same encoding as self" do
+ "yellow moon".encode("US-ASCII").squeeze.encoding.should == Encoding::US_ASCII
+ "yellow moon".encode("US-ASCII").squeeze("a").encoding.should == Encoding::US_ASCII
+ end
+
it "raises a TypeError when one set arg can't be converted to a string" do
-> { "hello world".squeeze([]) }.should raise_error(TypeError)
-> { "hello world".squeeze(Object.new)}.should raise_error(TypeError)
diff --git a/spec/ruby/core/string/start_with_spec.rb b/spec/ruby/core/string/start_with_spec.rb
index aaed197ff3..3833289f96 100644
--- a/spec/ruby/core/string/start_with_spec.rb
+++ b/spec/ruby/core/string/start_with_spec.rb
@@ -5,4 +5,14 @@ require_relative '../../shared/string/start_with'
describe "String#start_with?" do
it_behaves_like :start_with, :to_s
+
+ # Here and not in the shared examples because this is invalid as a Symbol
+ it "does not check that we are not starting to match at the head of a character" do
+ "\xA9".should.start_with?("\xA9") # A9 is not a character head for UTF-8
+ end
+
+ it "does not check we are matching only part of a character" do
+ "\xe3\x81\x82".size.should == 1
+ "\xe3\x81\x82".should.start_with?("\xe3")
+ end
end
diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb
index 463a9fedf3..662f13b032 100644
--- a/spec/ruby/core/string/strip_spec.rb
+++ b/spec/ruby/core/string/strip_spec.rb
@@ -1,26 +1,21 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/strip'
describe "String#strip" do
+ it_behaves_like :string_strip, :strip
+
it "returns a new string with leading and trailing whitespace removed" do
" hello ".strip.should == "hello"
" hello world ".strip.should == "hello world"
"\tgoodbye\r\v\n".strip.should == "goodbye"
end
- ruby_version_is '3.1' do
+ ruby_version_is '3.0' 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.should.tainted?
- "ok".taint.strip.should.tainted?
- " ok ".taint.strip.should.tainted?
- end
- end
end
describe "String#strip!" do
@@ -40,7 +35,13 @@ describe "String#strip!" do
a.should == "hello"
end
- ruby_version_is '3.1' do
+ it "makes a string empty if it is only whitespace" do
+ "".strip!.should == nil
+ " ".strip.should == ""
+ " ".strip.should == ""
+ end
+
+ ruby_version_is '3.0' do
it "removes leading and trailing NULL bytes and whitespace" do
a = "\000 goodbye \000"
a.strip!
diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb
index 5ae9a4bbf3..99dd7b45a8 100644
--- a/spec/ruby/core/string/sub_spec.rb
+++ b/spec/ruby/core/string/sub_spec.rb
@@ -137,28 +137,6 @@ describe "String#sub with pattern, replacement" do
"hello".sub(/./, 'hah\\').should == 'hah\\ello'
end
- ruby_version_is ''...'2.7' do
- it "taints the result if the original string or replacement is tainted" do
- hello = "hello"
- hello_t = "hello"
- a = "a"
- a_t = "a"
- empty = ""
- empty_t = ""
-
- hello_t.taint; a_t.taint; empty_t.taint
-
- hello_t.sub(/./, a).should.tainted?
- hello_t.sub(/./, empty).should.tainted?
-
- hello.sub(/./, a_t).should.tainted?
- hello.sub(/./, empty_t).should.tainted?
- hello.sub(//, empty_t).should.tainted?
-
- hello.sub(//.taint, "foo").should_not.tainted?
- end
- end
-
it "tries to convert pattern to a string using to_str" do
pattern = mock('.')
pattern.should_receive(:to_str).and_return(".")
@@ -236,6 +214,17 @@ describe "String#sub with pattern, replacement" do
"ababa".sub(/(b)/, '\\\\\1').should == "a\\baba"
end
+ it "handles a pattern in a superset encoding" do
+ result = 'abc'.force_encoding(Encoding::US_ASCII).sub('é', 'è')
+ result.should == 'abc'
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ result = 'été'.sub('t'.force_encoding(Encoding::US_ASCII), 'u')
+ result.should == 'éué'
+ result.encoding.should == Encoding::UTF_8
+ end
end
describe "String#sub with pattern and block" do
@@ -297,28 +286,6 @@ describe "String#sub with pattern and block" do
obj.should_receive(:to_s).and_return("ok")
"hello".sub(/.+/) { obj }.should == "ok"
end
-
- ruby_version_is ''...'2.7' do
- it "taints the result if the original string or replacement is tainted" do
- hello = "hello"
- hello_t = "hello"
- a = "a"
- a_t = "a"
- empty = ""
- empty_t = ""
-
- hello_t.taint; a_t.taint; empty_t.taint
-
- hello_t.sub(/./) { a }.should.tainted?
- hello_t.sub(/./) { empty }.should.tainted?
-
- hello.sub(/./) { a_t }.should.tainted?
- hello.sub(/./) { empty_t }.should.tainted?
- hello.sub(//) { empty_t }.should.tainted?
-
- hello.sub(//.taint) { "foo" }.should_not.tainted?
- end
- end
end
describe "String#sub! with pattern, replacement" do
@@ -328,14 +295,6 @@ describe "String#sub! with pattern, replacement" do
a.should == "h*llo"
end
- ruby_version_is ''...'2.7' do
- it "taints self if replacement is tainted" do
- a = "hello"
- a.sub!(/./.taint, "foo").should_not.tainted?
- a.sub!(/./, "foo".taint).should.tainted?
- end
- end
-
it "returns nil if no modifications were made" do
a = "hello"
a.sub!(/z/, '*').should == nil
@@ -351,6 +310,27 @@ describe "String#sub! with pattern, replacement" do
-> { s.sub!(/e/, "e") }.should raise_error(FrozenError)
-> { s.sub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
end
+
+ it "handles a pattern in a superset encoding" do
+ string = 'abc'.force_encoding(Encoding::US_ASCII)
+
+ result = string.sub!('é', 'è')
+
+ result.should == nil
+ string.should == 'abc'
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ string = 'été'
+ pattern = 't'.force_encoding(Encoding::US_ASCII)
+
+ result = string.sub!(pattern, 'u')
+
+ result.should == string
+ string.should == 'éué'
+ string.encoding.should == Encoding::UTF_8
+ end
end
describe "String#sub! with pattern and block" do
@@ -378,14 +358,6 @@ describe "String#sub! with pattern and block" do
offsets.should == [[1, 2]]
end
- ruby_version_is ''...'2.7' do
- it "taints self if block's result is tainted" do
- a = "hello"
- a.sub!(/./.taint) { "foo" }.should_not.tainted?
- a.sub!(/./) { "foo".taint }.should.tainted?
- end
- end
-
it "returns nil if no modifications were made" do
a = "hello"
a.sub!(/z/) { '*' }.should == nil
@@ -471,28 +443,6 @@ describe "String#sub with pattern and Hash" do
"hello".sub(/(.+)/, 'hello' => repl ).should == repl
end
- ruby_version_is ''...'2.7' do
- it "untrusts the result if the original string is untrusted" do
- str = "Ghana".untrust
- str.sub(/[Aa]na/, 'ana' => '').untrusted?.should be_true
- end
-
- it "untrusts the result if a hash value is untrusted" do
- str = "Ghana"
- str.sub(/a$/, 'a' => 'di'.untrust).untrusted?.should be_true
- end
-
- it "taints the result if the original string is tainted" do
- str = "Ghana".taint
- str.sub(/[Aa]na/, 'ana' => '').tainted?.should be_true
- end
-
- it "taints the result if a hash value is tainted" do
- str = "Ghana"
- str.sub(/a$/, 'a' => 'di'.taint).tainted?.should be_true
- end
- end
-
end
describe "String#sub! with pattern and Hash" do
@@ -557,28 +507,6 @@ describe "String#sub! with pattern and Hash" do
repl = '\& \0 \1 \` \\\' \+ \\\\ foo'
"hello".sub!(/(.+)/, 'hello' => repl ).should == repl
end
-
- ruby_version_is ''...'2.7' do
- it "keeps untrusted state" do
- str = "Ghana".untrust
- str.sub!(/[Aa]na/, 'ana' => '').untrusted?.should be_true
- end
-
- it "untrusts self if a hash value is untrusted" do
- str = "Ghana"
- str.sub!(/a$/, 'a' => 'di'.untrust).untrusted?.should be_true
- end
-
- it "keeps tainted state" do
- str = "Ghana".taint
- str.sub!(/[Aa]na/, 'ana' => '').tainted?.should be_true
- end
-
- it "taints self if a hash value is tainted" do
- str = "Ghana"
- str.sub!(/a$/, 'a' => 'di'.taint).tainted?.should be_true
- end
- end
end
describe "String#sub with pattern and without replacement and block" do
diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb
index 32b358607e..d369ab3e4e 100644
--- a/spec/ruby/core/string/swapcase_spec.rb
+++ b/spec/ruby/core/string/swapcase_spec.rb
@@ -9,11 +9,8 @@ describe "String#swapcase" do
"+++---111222???".swapcase.should == "+++---111222???"
end
- ruby_version_is ''...'2.7' do
- it "taints resulting string when self is tainted" do
- "".taint.swapcase.should.tainted?
- "hello".taint.swapcase.should.tainted?
- end
+ it "returns a String in the same encoding as self" do
+ "Hello".encode("US-ASCII").swapcase.encoding.should == Encoding::US_ASCII
end
describe "full Unicode case mapping" do
@@ -35,6 +32,10 @@ describe "String#swapcase" do
it "does not swapcase non-ASCII characters" do
"aßet".swapcase(:ascii).should == "AßET"
end
+
+ it "works with substrings" do
+ "prefix aTé"[-3..-1].swapcase(:ascii).should == "Até"
+ end
end
describe "full Unicode case mapping adapted for Turkic languages" do
diff --git a/spec/ruby/core/string/to_c_spec.rb b/spec/ruby/core/string/to_c_spec.rb
index 9c84b14f4d..edc8a4f14f 100644
--- a/spec/ruby/core/string/to_c_spec.rb
+++ b/spec/ruby/core/string/to_c_spec.rb
@@ -1,99 +1,41 @@
require_relative '../../spec_helper'
+require_relative '../../shared/kernel/complex'
+require_relative 'fixtures/to_c'
describe "String#to_c" do
- it "returns a Complex object" do
- '9'.to_c.should be_an_instance_of(Complex)
- end
-
- it "understands integers" do
- '20'.to_c.should == Complex(20)
- end
-
- it "understands negative integers" do
- '-3'.to_c.should == Complex(-3)
- end
-
- it "understands fractions (numerator/denominator) for the real part" do
- '2/3'.to_c.should == Complex(Rational(2, 3))
- end
-
- it "understands fractions (numerator/denominator) for the imaginary part" do
- '4+2/3i'.to_c.should == Complex(4, Rational(2, 3))
- end
-
- it "understands negative fractions (-numerator/denominator) for the real part" do
- '-2/3'.to_c.should == Complex(Rational(-2, 3))
- end
-
- it "understands negative fractions (-numerator/denominator) for the imaginary part" do
- '7-2/3i'.to_c.should == Complex(7, Rational(-2, 3))
- end
-
- it "understands floats (a.b) for the real part" do
- '2.3'.to_c.should == Complex(2.3)
- end
-
- it "understands floats (a.b) for the imaginary part" do
- '4+2.3i'.to_c.should == Complex(4, 2.3)
- end
-
- it "understands negative floats (-a.b) for the real part" do
- '-2.33'.to_c.should == Complex(-2.33)
- end
-
- it "understands negative floats (-a.b) for the imaginary part" do
- '7-28.771i'.to_c.should == Complex(7, -28.771)
- end
-
- it "understands an integer followed by 'i' to mean that integer is the imaginary part" do
- '35i'.to_c.should == Complex(0,35)
- end
-
- it "understands a negative integer followed by 'i' to mean that negative integer is the imaginary part" do
- '-29i'.to_c.should == Complex(0,-29)
- end
-
- it "understands an 'i' by itself as denoting a complex number with an imaginary part of 1" do
- 'i'.to_c.should == Complex(0,1)
- end
-
- it "understands a '-i' by itself as denoting a complex number with an imaginary part of -1" do
- '-i'.to_c.should == Complex(0,-1)
- end
-
- it "understands 'a+bi' to mean a complex number with 'a' as the real part, 'b' as the imaginary" do
- '79+4i'.to_c.should == Complex(79,4)
- end
-
- it "understands 'a-bi' to mean a complex number with 'a' as the real part, '-b' as the imaginary" do
- '79-4i'.to_c.should == Complex(79,-4)
- end
-
- it "understands scientific notation for the real part" do
- '2e3+4i'.to_c.should == Complex(2e3,4)
- end
+ it_behaves_like :kernel_complex, :to_c_method, StringSpecs
+end
- it "understands negative scientific notation for the real part" do
- '-2e3+4i'.to_c.should == Complex(-2e3,4)
+describe "String#to_c" do
+ it "returns a complex number with 0 as the real part, 0 as the imaginary part for unrecognised Strings" do
+ 'ruby'.to_c.should == Complex(0, 0)
end
- it "understands scientific notation for the imaginary part" do
- '4+2e3i'.to_c.should == Complex(4, 2e3)
+ it "ignores trailing garbage" do
+ '79+4iruby'.to_c.should == Complex(79, 4)
+ ruby_bug "[Bug #19087]", ""..."3.2" do
+ '7__9+4__0i'.to_c.should == Complex(7, 0)
+ end
end
- it "understands negative scientific notation for the imaginary part" do
- '4-2e3i'.to_c.should == Complex(4, -2e3)
+ it "understands Float::INFINITY" do
+ 'Infinity'.to_c.should == Complex(0, 1)
+ '-Infinity'.to_c.should == Complex(0, -1)
end
- it "understands scientific notation for the real and imaginary part in the same String" do
- '2e3+2e4i'.to_c.should == Complex(2e3,2e4)
+ it "understands Float::NAN" do
+ 'NaN'.to_c.should == Complex(0, 0)
end
- it "understands negative scientific notation for the real and imaginary part in the same String" do
- '-2e3-2e4i'.to_c.should == Complex(-2e3,-2e4)
+ it "allows null-byte" do
+ "1-2i\0".to_c.should == Complex(1, -2)
+ "1\0-2i".to_c.should == Complex(1, 0)
+ "\01-2i".to_c.should == Complex(0, 0)
end
- it "returns a complex number with 0 as the real part, 0 as the imaginary part for unrecognised Strings" do
- 'ruby'.to_c.should == Complex(0,0)
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ '79+4i'.encode("UTF-16").to_c
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
end
end
diff --git a/spec/ruby/core/string/tr_s_spec.rb b/spec/ruby/core/string/tr_s_spec.rb
index c6ad12139e..e1bb20ce35 100644
--- a/spec/ruby/core/string/tr_s_spec.rb
+++ b/spec/ruby/core/string/tr_s_spec.rb
@@ -57,19 +57,6 @@ describe "String#tr_s" do
end
end
- ruby_version_is ''...'2.7' do
- it "taints the result when self is tainted" do
- ["h", "hello"].each do |str|
- tainted_str = str.dup.taint
-
- tainted_str.tr_s("e", "a").should.tainted?
-
- str.tr_s("e".taint, "a").should_not.tainted?
- str.tr_s("e", "a".taint).should_not.tainted?
- end
- end
- end
-
# http://redmine.ruby-lang.org/issues/show/1839
it "can replace a 7-bit ASCII character with a multibyte one" do
a = "uber"
diff --git a/spec/ruby/core/string/tr_spec.rb b/spec/ruby/core/string/tr_spec.rb
index 06be1e6641..72adb9f2eb 100644
--- a/spec/ruby/core/string/tr_spec.rb
+++ b/spec/ruby/core/string/tr_spec.rb
@@ -69,19 +69,6 @@ describe "String#tr" do
end
end
- ruby_version_is ''...'2.7' do
- it "taints the result when self is tainted" do
- ["h", "hello"].each do |str|
- tainted_str = str.dup.taint
-
- tainted_str.tr("e", "a").should.tainted?
-
- str.tr("e".taint, "a").should_not.tainted?
- str.tr("e", "a".taint).should_not.tainted?
- end
- end
- end
-
# http://redmine.ruby-lang.org/issues/show/1839
it "can replace a 7-bit ASCII character with a multibyte one" do
a = "uber"
diff --git a/spec/ruby/core/string/uminus_spec.rb b/spec/ruby/core/string/uminus_spec.rb
index 800dca5044..46d88f6704 100644
--- a/spec/ruby/core/string/uminus_spec.rb
+++ b/spec/ruby/core/string/uminus_spec.rb
@@ -1,49 +1,6 @@
require_relative '../../spec_helper'
+require_relative 'shared/dedup'
describe 'String#-@' do
- it 'returns self if the String is frozen' do
- input = 'foo'.freeze
- output = -input
-
- output.should equal(input)
- output.should.frozen?
- end
-
- it 'returns a frozen copy if the String is not frozen' do
- input = 'foo'
- output = -input
-
- output.should.frozen?
- output.should_not equal(input)
- output.should == 'foo'
- end
-
- it "returns the same object for equal unfrozen strings" do
- origin = "this is a string"
- dynamic = %w(this is a string).join(' ')
-
- origin.should_not equal(dynamic)
- (-origin).should equal(-dynamic)
- end
-
- it "returns the same object when it's called on the same String literal" do
- (-"unfrozen string").should equal(-"unfrozen string")
- (-"unfrozen string").should_not equal(-"another unfrozen string")
- end
-
- it "deduplicates frozen strings" do
- dynamic = %w(this string is frozen).join(' ').freeze
-
- dynamic.should_not equal("this string is frozen".freeze)
-
- (-dynamic).should equal("this string is frozen".freeze)
- (-dynamic).should equal(-"this string is frozen".freeze)
- 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
+ it_behaves_like :string_dedup, :-@
end
diff --git a/spec/ruby/core/string/undump_spec.rb b/spec/ruby/core/string/undump_spec.rb
index b990aa25ee..6ff220161c 100644
--- a/spec/ruby/core/string/undump_spec.rb
+++ b/spec/ruby/core/string/undump_spec.rb
@@ -3,16 +3,6 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
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 "untrusts the result if self is untrusted" do
- '"foo"'.untrust.undump.should.untrusted?
- end
- end
-
it "does not take into account if a string is frozen" do
'"foo"'.freeze.undump.should_not.frozen?
end
@@ -399,7 +389,7 @@ describe "String#undump" do
'"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be')
end
- it "keeps origin encoding" do
+ it "returns a String in the same encoding as self" do
'"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1
'"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251
end
diff --git a/spec/ruby/core/string/unpack/b_spec.rb b/spec/ruby/core/string/unpack/b_spec.rb
index 1a838d6c7c..2cf5ebad34 100644
--- a/spec/ruby/core/string/unpack/b_spec.rb
+++ b/spec/ruby/core/string/unpack/b_spec.rb
@@ -86,13 +86,28 @@ describe "String#unpack with format 'B'" do
].should be_computed_by(:unpack, "BBB")
end
- it "ignores NULL bytes between directives" do
- "\x80\x00".unpack("B\x00B").should == ["1", "0"]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "\x80\x00".unpack("B\x00B").should == ["1", "0"]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x80\x00".unpack("B\x00B")
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
"\x80\x00".unpack("B B").should == ["1", "0"]
end
+
+ it "decodes into US-ASCII string values" do
+ str = "s".force_encoding('UTF-8').unpack("B*")[0]
+ str.encoding.name.should == 'US-ASCII'
+ end
end
describe "String#unpack with format 'b'" do
@@ -177,8 +192,18 @@ describe "String#unpack with format 'b'" do
].should be_computed_by(:unpack, "bbb")
end
- it "ignores NULL bytes between directives" do
- "\x01\x00".unpack("b\x00b").should == ["1", "0"]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "\x01\x00".unpack("b\x00b").should == ["1", "0"]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x00".unpack("b\x00b")
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -189,5 +214,4 @@ describe "String#unpack with format 'b'" do
str = "s".force_encoding('UTF-8').unpack("b*")[0]
str.encoding.name.should == 'US-ASCII'
end
-
end
diff --git a/spec/ruby/core/string/unpack/c_spec.rb b/spec/ruby/core/string/unpack/c_spec.rb
index ed8caa4895..dbcbacc74d 100644
--- a/spec/ruby/core/string/unpack/c_spec.rb
+++ b/spec/ruby/core/string/unpack/c_spec.rb
@@ -35,8 +35,18 @@ describe :string_unpack_8bit, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "abc".unpack(unpack_format("\000", 2)).should == [97, 98]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "abc".unpack(unpack_format("\000", 2)).should == [97, 98]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "abc".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/h_spec.rb b/spec/ruby/core/string/unpack/h_spec.rb
index f2f5dcf396..ee08d20926 100644
--- a/spec/ruby/core/string/unpack/h_spec.rb
+++ b/spec/ruby/core/string/unpack/h_spec.rb
@@ -56,8 +56,18 @@ describe "String#unpack with format 'H'" do
].should be_computed_by(:unpack, "HHH")
end
- it "ignores NULL bytes between directives" do
- "\x01\x10".unpack("H\x00H").should == ["0", "1"]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "\x01\x10".unpack("H\x00H").should == ["0", "1"]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x10".unpack("H\x00H")
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -121,8 +131,18 @@ describe "String#unpack with format 'h'" do
].should be_computed_by(:unpack, "hhh")
end
- it "ignores NULL bytes between directives" do
- "\x01\x10".unpack("h\x00h").should == ["1", "0"]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "\x01\x10".unpack("h\x00h").should == ["1", "0"]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x10".unpack("h\x00h")
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/m_spec.rb b/spec/ruby/core/string/unpack/m_spec.rb
index 21134514a1..c551c755d1 100644
--- a/spec/ruby/core/string/unpack/m_spec.rb
+++ b/spec/ruby/core/string/unpack/m_spec.rb
@@ -97,6 +97,11 @@ describe "String#unpack with format 'M'" do
["=FF=\n", ["\xff"]]
].should be_computed_by(:unpack, "M")
end
+
+ it "unpacks incomplete escape sequences as literal characters" do
+ "foo=".unpack("M").should == ["foo="]
+ "foo=4".unpack("M").should == ["foo=4"]
+ end
end
describe "String#unpack with format 'm'" do
diff --git a/spec/ruby/core/string/unpack/p_spec.rb b/spec/ruby/core/string/unpack/p_spec.rb
index 3e187d674f..cd48c0523d 100644
--- a/spec/ruby/core/string/unpack/p_spec.rb
+++ b/spec/ruby/core/string/unpack/p_spec.rb
@@ -18,12 +18,6 @@ describe "String#unpack with format 'P'" do
-> { packed.to_sym.to_s.unpack("P5") }.should raise_error(ArgumentError, /no associated pointer/)
end
- ruby_version_is ''...'2.7' do
- it "taints the unpacked string" do
- ["hello"].pack("P").unpack("P5").first.tainted?.should be_true
- end
- end
-
it "reads as many characters as specified" do
["hello"].pack("P").unpack("P1").should == ["h"]
end
@@ -47,10 +41,4 @@ describe "String#unpack with format 'p'" do
packed.dup.unpack("p").should == ["hello"]
-> { packed.to_sym.to_s.unpack("p") }.should raise_error(ArgumentError, /no associated pointer/)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the unpacked string" do
- ["hello"].pack("p").unpack("p").first.tainted?.should be_true
- end
- end
end
diff --git a/spec/ruby/core/string/unpack/shared/basic.rb b/spec/ruby/core/string/unpack/shared/basic.rb
index 332e39d8d1..bb5302edc5 100644
--- a/spec/ruby/core/string/unpack/shared/basic.rb
+++ b/spec/ruby/core/string/unpack/shared/basic.rb
@@ -8,14 +8,6 @@ describe :string_unpack_basic, shared: true do
d.should_receive(:to_str).and_return("a"+unpack_format)
"abc".unpack(d).should be_an_instance_of(Array)
end
-
- it "raises a TypeError when passed nil" do
- -> { "abc".unpack(nil) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when passed an Integer" do
- -> { "abc".unpack(1) }.should raise_error(TypeError)
- end
end
describe :string_unpack_no_platform, shared: true do
diff --git a/spec/ruby/core/string/unpack/shared/float.rb b/spec/ruby/core/string/unpack/shared/float.rb
index 99bd8a3401..ccddf94f99 100644
--- a/spec/ruby/core/string/unpack/shared/float.rb
+++ b/spec/ruby/core/string/unpack/shared/float.rb
@@ -56,9 +56,19 @@ describe :string_unpack_float_le, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end
- it "ignores NULL bytes between directives" do
- array = "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
- array.should == [2.9000000953674316, 1.399999976158142]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ array = "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
+ array.should == [2.9000000953674316, 1.399999976158142]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -123,9 +133,19 @@ describe :string_unpack_float_be, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end
- it "ignores NULL bytes between directives" do
- array = "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
- array.should == [2.9000000953674316, 1.399999976158142]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ array = "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
+ array.should == [2.9000000953674316, 1.399999976158142]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -193,8 +213,18 @@ describe :string_unpack_double_le, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end
- it "ignores NULL bytes between directives" do
- "333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -261,8 +291,18 @@ describe :string_unpack_double_be, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end
- it "ignores NULL bytes between directives" do
- "@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/shared/integer.rb b/spec/ruby/core/string/unpack/shared/integer.rb
index cbaa743683..ba4f149dad 100644
--- a/spec/ruby/core/string/unpack/shared/integer.rb
+++ b/spec/ruby/core/string/unpack/shared/integer.rb
@@ -32,8 +32,18 @@ describe :string_unpack_16bit_le, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "abcd".unpack(unpack_format("\000", 2)).should == [25185, 25699]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "abcd".unpack(unpack_format("\000", 2)).should == [25185, 25699]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "abcd".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -85,8 +95,18 @@ describe :string_unpack_16bit_be, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "badc".unpack(unpack_format("\000", 2)).should == [25185, 25699]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "badc".unpack(unpack_format("\000", 2)).should == [25185, 25699]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "badc".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -139,8 +159,18 @@ describe :string_unpack_32bit_le, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "abcdefgh".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "abcdefgh".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "abcdefgh".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -193,8 +223,18 @@ describe :string_unpack_32bit_be, shared: true do
].should be_computed_by(:unpack, unpack_format(3))
end
- it "ignores NULL bytes between directives" do
- "dcbahgfe".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "dcbahgfe".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "dcbahgfe".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -243,9 +283,19 @@ describe :string_unpack_64bit_le, shared: true do
"abc".unpack(unpack_format('*')).should == []
end
- it "ignores NULL bytes between directives" do
- array = "abcdefghabghefcd".unpack(unpack_format("\000", 2))
- array.should == [7523094288207667809, 7233738012216484449]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ array = "abcdefghabghefcd".unpack(unpack_format("\000", 2))
+ array.should == [7523094288207667809, 7233738012216484449]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "badc".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
@@ -305,9 +355,19 @@ describe :string_unpack_64bit_be, shared: true do
"abc".unpack(unpack_format('*')).should == []
end
- it "ignores NULL bytes between directives" do
- array = "hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
- array.should == [7523094288207667809, 7233738012216484449]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ array = "hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
+ array.should == [7523094288207667809, 7233738012216484449]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/shared/taint.rb b/spec/ruby/core/string/unpack/shared/taint.rb
index 061a3e26ad..79c7251f01 100644
--- a/spec/ruby/core/string/unpack/shared/taint.rb
+++ b/spec/ruby/core/string/unpack/shared/taint.rb
@@ -1,83 +1,2 @@
describe :string_unpack_taint, shared: true do
- ruby_version_is ''...'2.7' do
- it "does not taint returned arrays if given an untainted format string" do
- "".unpack(unpack_format(2)).tainted?.should be_false
- end
-
- it "does not taint returned arrays if given a tainted format string" do
- format_string = unpack_format(2).dup
- format_string.taint
- "".unpack(format_string).tainted?.should be_false
- end
-
- it "does not taint returned strings if given an untainted format string" do
- "".unpack(unpack_format(2)).any?(&:tainted?).should be_false
- end
-
- it "does not taint returned strings if given a tainted format string" do
- format_string = unpack_format(2).dup
- format_string.taint
- "".unpack(format_string).any?(&:tainted?).should be_false
- end
-
- it "does not taint returned arrays if given an untainted packed string" do
- "".unpack(unpack_format(2)).tainted?.should be_false
- end
-
- it "does not taint returned arrays if given a tainted packed string" do
- packed_string = ""
- packed_string.taint
- packed_string.unpack(unpack_format(2)).tainted?.should be_false
- end
-
- it "does not taint returned strings if given an untainted packed string" do
- "".unpack(unpack_format(2)).any?(&:tainted?).should be_false
- end
-
- it "taints returned strings if given a tainted packed string" do
- packed_string = ""
- packed_string.taint
- packed_string.unpack(unpack_format(2)).all?(&:tainted?).should be_true
- end
-
- it "does not untrust returned arrays if given an untrusted format string" do
- "".unpack(unpack_format(2)).untrusted?.should be_false
- end
-
- it "does not untrust returned arrays if given a untrusted format string" do
- format_string = unpack_format(2).dup
- format_string.untrust
- "".unpack(format_string).untrusted?.should be_false
- end
-
- it "does not untrust returned strings if given an untainted format string" do
- "".unpack(unpack_format(2)).any?(&:untrusted?).should be_false
- end
-
- it "does not untrust returned strings if given a untrusted format string" do
- format_string = unpack_format(2).dup
- format_string.untrust
- "".unpack(format_string).any?(&:untrusted?).should be_false
- end
-
- it "does not untrust returned arrays if given an trusted packed string" do
- "".unpack(unpack_format(2)).untrusted?.should be_false
- end
-
- it "does not untrust returned arrays if given a untrusted packed string" do
- packed_string = ""
- packed_string.untrust
- packed_string.unpack(unpack_format(2)).untrusted?.should be_false
- end
-
- it "does not untrust returned strings if given an trusted packed string" do
- "".unpack(unpack_format(2)).any?(&:untrusted?).should be_false
- end
-
- it "untrusts returned strings if given a untrusted packed string" do
- packed_string = ""
- packed_string.untrust
- packed_string.unpack(unpack_format(2)).all?(&:untrusted?).should be_true
- end
- end
end
diff --git a/spec/ruby/core/string/unpack/shared/unicode.rb b/spec/ruby/core/string/unpack/shared/unicode.rb
index a2b4e142b2..ce1f29fe87 100644
--- a/spec/ruby/core/string/unpack/shared/unicode.rb
+++ b/spec/ruby/core/string/unpack/shared/unicode.rb
@@ -50,8 +50,18 @@ describe :string_unpack_unicode, shared: true do
"\xc2\x80".unpack("UUUU").should == [0x80]
end
- it "ignores NULL bytes between directives" do
- "\x01\x02".unpack("U\x00U").should == [1, 2]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "\x01\x02".unpack("U\x00U").should == [1, 2]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x02".unpack("U\x00U")
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/w_spec.rb b/spec/ruby/core/string/unpack/w_spec.rb
index 011c75f5c4..b213b32921 100644
--- a/spec/ruby/core/string/unpack/w_spec.rb
+++ b/spec/ruby/core/string/unpack/w_spec.rb
@@ -15,8 +15,18 @@ describe "String#unpack with directive 'w'" do
].should be_computed_by(:unpack, "w")
end
- it "ignores NULL bytes between directives" do
- "\x01\x02\x03".unpack("w\x00w").should == [1, 2]
+ ruby_version_is ""..."3.3" do
+ it "ignores NULL bytes between directives" do
+ "\x01\x02\x03".unpack("w\x00w").should == [1, 2]
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise ArgumentError for NULL bytes between directives" do
+ -> {
+ "\x01\x02\x03".unpack("w\x00w")
+ }.should raise_error(ArgumentError, /unknown unpack directive/)
+ end
end
it "ignores spaces between directives" do
diff --git a/spec/ruby/core/string/unpack/z_spec.rb b/spec/ruby/core/string/unpack/z_spec.rb
index 552851ce04..ce8da4b29e 100644
--- a/spec/ruby/core/string/unpack/z_spec.rb
+++ b/spec/ruby/core/string/unpack/z_spec.rb
@@ -20,4 +20,9 @@ describe "String#unpack with format 'Z'" do
["\x00a\x00 bc \x00", ["", "c"]]
].should be_computed_by(:unpack, "Z5Z")
end
+
+ it "does not advance past the null byte when given a 'Z' format specifier" do
+ "a\x00\x0f".unpack('Zxc').should == ['a', 15]
+ "a\x00\x0f".unpack('Zcc').should == ['a', 0, 15]
+ end
end
diff --git a/spec/ruby/core/string/unpack1_spec.rb b/spec/ruby/core/string/unpack1_spec.rb
index 5fe81733fb..df830916a3 100644
--- a/spec/ruby/core/string/unpack1_spec.rb
+++ b/spec/ruby/core/string/unpack1_spec.rb
@@ -7,4 +7,30 @@ describe "String#unpack1" do
"aG9nZWZ1Z2E=".unpack1("m").should == "hogefuga"
"A".unpack1("B*").should == "01000001"
end
+
+ ruby_version_is "3.1" do
+ it "starts unpacking from the given offset" do
+ "ZZABCD".unpack1('x3C', offset: 2).should == "ABCD".unpack('x3C')[0]
+ "ZZZZaG9nZWZ1Z2E=".unpack1("m", offset: 4).should == "hogefuga"
+ "ZA".unpack1("B*", offset: 1).should == "01000001"
+ end
+
+ it "traits offset as a bytes offset" do
+ "؈".unpack("CC").should == [216, 136]
+ "؈".unpack1("C").should == 216
+ "؈".unpack1("C", offset: 1).should == 136
+ end
+
+ it "raises an ArgumentError when the offset is negative" do
+ -> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
+ end
+
+ it "returns nil if the offset is at the end of the string" do
+ "a".unpack1("C", offset: 1).should == nil
+ end
+
+ it "raises an ArgumentError when the offset is larger than the string bytesize" do
+ -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
+ end
+ end
end
diff --git a/spec/ruby/core/string/unpack_spec.rb b/spec/ruby/core/string/unpack_spec.rb
new file mode 100644
index 0000000000..4ff7d07460
--- /dev/null
+++ b/spec/ruby/core/string/unpack_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+
+describe "String#unpack" do
+ it "raises a TypeError when passed nil" do
+ -> { "abc".unpack(nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when passed an Integer" do
+ -> { "abc".unpack(1) }.should raise_error(TypeError)
+ end
+
+ ruby_version_is "3.1" do
+ it "starts unpacking from the given offset" do
+ "abc".unpack("CC", offset: 1).should == [98, 99]
+ end
+
+ it "traits offset as a bytes offset" do
+ "؈".unpack("CC").should == [216, 136]
+ "؈".unpack("CC", offset: 1).should == [136, nil]
+ end
+
+ it "raises an ArgumentError when the offset is negative" do
+ -> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
+ end
+
+ it "returns nil if the offset is at the end of the string" do
+ "a".unpack("C", offset: 1).should == [nil]
+ end
+
+ it "raises an ArgumentError when the offset is larget than the string" do
+ -> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/ruby/core/string/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb
index 6cf44b4703..5ce7b0b95f 100644
--- a/spec/ruby/core/string/upcase_spec.rb
+++ b/spec/ruby/core/string/upcase_spec.rb
@@ -8,6 +8,10 @@ describe "String#upcase" do
"hello".upcase.should == "HELLO"
end
+ it "returns a String in the same encoding as self" do
+ "hello".encode("US-ASCII").upcase.encoding.should == Encoding::US_ASCII
+ end
+
describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do
"äöü".upcase.should == "ÄÖÜ"
@@ -27,6 +31,10 @@ describe "String#upcase" do
it "does not upcase non-ASCII characters" do
"aßet".upcase(:ascii).should == "AßET"
end
+
+ it "works with substrings" do
+ "prefix té"[-2..-1].upcase(:ascii).should == "Té"
+ end
end
describe "full Unicode case mapping adapted for Turkic languages" do
@@ -65,14 +73,6 @@ describe "String#upcase" do
-> { "abc".upcase(:invalid_option) }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "taints result when self is tainted" do
- "".taint.upcase.should.tainted?
- "X".taint.upcase.should.tainted?
- "x".taint.upcase.should.tainted?
- end
- end
-
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)
diff --git a/spec/ruby/core/string/valid_encoding/utf_8_spec.rb b/spec/ruby/core/string/valid_encoding/utf_8_spec.rb
new file mode 100644
index 0000000000..a14c3af830
--- /dev/null
+++ b/spec/ruby/core/string/valid_encoding/utf_8_spec.rb
@@ -0,0 +1,214 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../../spec_helper'
+
+describe "String#valid_encoding? and UTF-8" do
+ def utf8(bytes)
+ bytes.pack("C*").force_encoding("UTF-8")
+ end
+
+ describe "1-byte character" do
+ it "is valid if is in format 0xxxxxxx" do
+ utf8([0b00000000]).valid_encoding?.should == true
+ utf8([0b01111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if is not in format 0xxxxxxx" do
+ utf8([0b10000000]).valid_encoding?.should == false
+ utf8([0b11111111]).valid_encoding?.should == false
+ end
+ end
+
+ describe "2-bytes character" do
+ it "is valid if in format [110xxxxx 10xxxxx]" do
+ utf8([0b11000010, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11000010, 0b10111111]).valid_encoding?.should == true
+
+ utf8([0b11011111, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11011111, 0b10111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if the first byte is not in format 110xxxxx" do
+ utf8([0b00000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00100010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01100010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10100010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11000010, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11100010, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is not in format 10xxxxxx" do
+ utf8([0b11000010, 0b00000000]).valid_encoding?.should == false
+ utf8([0b11000010, 0b01000000]).valid_encoding?.should == false
+ utf8([0b11000010, 0b11000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is smaller than [xxxxxx10 xx000000] (codepoints < U+007F, that are encoded with the 1-byte format)" do
+ utf8([0b11000000, 0b10111111]).valid_encoding?.should == false
+ utf8([0b11000001, 0b10111111]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the first byte is missing" do
+ bytes = [0b11000010, 0b10000000]
+ utf8(bytes[1..1]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is missing" do
+ bytes = [0b11000010, 0b10000000]
+ utf8(bytes[0..0]).valid_encoding?.should == false
+ end
+ end
+
+ describe "3-bytes character" do
+ it "is valid if in format [1110xxxx 10xxxxxx 10xxxxxx]" do
+ utf8([0b11100000, 0b10100000, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11100000, 0b10100000, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11100000, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11101111, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if the first byte is not in format 1110xxxx" do
+ utf8([0b00000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b00110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10100000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is not in format 10xxxxxx" do
+ utf8([0b11100000, 0b00100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b01100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b11100000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the third byte is not in format 10xxxxxx" do
+ utf8([0b11100000, 0b10100000, 0b00000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10100000, 0b01000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10100000, 0b01000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is smaller than [xxxx0000 xx100000 xx000000] (codepoints < U+07FF that are encoded with the 2-byte format)" do
+ utf8([0b11100000, 0b10010000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10001000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000100, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000010, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000001, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11100000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if in range [xxxx1101 xx100000 xx000000] - [xxxx1101 xx111111 xx111111] (codepoints U+D800 - U+DFFF)" do
+ utf8([0b11101101, 0b10100000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11101101, 0b10100000, 0b10000001]).valid_encoding?.should == false
+ utf8([0b11101101, 0b10111111, 0b10111111]).valid_encoding?.should == false
+
+ utf8([0b11101101, 0b10011111, 0b10111111]).valid_encoding?.should == true # lower boundary - 1
+ utf8([0b11101110, 0b10000000, 0b10000000]).valid_encoding?.should == true # upper boundary + 1
+ end
+
+ it "is not valid if the first byte is missing" do
+ bytes = [0b11100000, 0b10100000, 0b10000000]
+ utf8(bytes[2..3]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is missing" do
+ bytes = [0b11100000, 0b10100000, 0b10000000]
+ utf8([bytes[0], bytes[2]]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second and the third bytes are missing" do
+ bytes = [0b11100000, 0b10100000, 0b10000000]
+ utf8(bytes[0..0]).valid_encoding?.should == false
+ end
+ end
+
+ describe "4-bytes character" do
+ it "is valid if in format [11110xxx 10xxxxxx 10xxxxxx 10xxxxxx]" do
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11110000, 0b10010000, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11110000, 0b10111111, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ utf8([0b11110100, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == true
+ end
+
+ it "is not valid if the first byte is not in format 11110xxx" do
+ utf8([0b11100000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11010000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b10110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b01110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is not in format 10xxxxxx" do
+ utf8([0b11110000, 0b00010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b01010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b11010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the third byte is not in format 10xxxxxx" do
+ utf8([0b11110000, 0b10010000, 0b00000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b01000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b10010000, 0b11000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the forth byte is not in format 10xxxxxx" do
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b00000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b01000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
+ utf8([0b11110000, 0b10010000, 0b10000000, 0b11000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is smaller than [xxxxx000 xx001000 xx000000 xx000000] (codepoint < U+10000)" do
+ utf8([0b11110000, 0b10000111, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000110, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000101, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000100, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000011, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000010, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000001, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110000, 0b10000000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ end
+
+ it "is not valid if is greater than [xxxxx100 xx001111 xx111111 xx111111] (codepoint > U+10FFFF)" do
+ utf8([0b11110100, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110100, 0b10100000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+ utf8([0b11110100, 0b10110000, 0b10000000, 0b10000000]).valid_encoding?.should == false
+
+ utf8([0b11110101, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
+ utf8([0b11110110, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
+ utf8([0b11110111, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the first byte is missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8(bytes[1..3]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second byte is missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8([bytes[0], bytes[2], bytes[3]]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second and the third bytes are missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8([bytes[0], bytes[3]]).valid_encoding?.should == false
+ end
+
+ it "is not valid if the second, the third and the fourth bytes are missing" do
+ bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
+ utf8(bytes[0..0]).valid_encoding?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/string/valid_encoding_spec.rb b/spec/ruby/core/string/valid_encoding_spec.rb
index d5bf31710f..be7cef7a8e 100644
--- a/spec/ruby/core/string/valid_encoding_spec.rb
+++ b/spec/ruby/core/string/valid_encoding_spec.rb
@@ -43,10 +43,10 @@ describe "String#valid_encoding?" do
str.force_encoding('KOI8-R').valid_encoding?.should be_true
str.force_encoding('KOI8-U').valid_encoding?.should be_true
str.force_encoding('Shift_JIS').valid_encoding?.should be_false
- str.force_encoding('UTF-16BE').valid_encoding?.should be_false
- str.force_encoding('UTF-16LE').valid_encoding?.should be_false
- str.force_encoding('UTF-32BE').valid_encoding?.should be_false
- str.force_encoding('UTF-32LE').valid_encoding?.should be_false
+ "\xD8\x00".force_encoding('UTF-16BE').valid_encoding?.should be_false
+ "\x00\xD8".force_encoding('UTF-16LE').valid_encoding?.should be_false
+ "\x04\x03\x02\x01".force_encoding('UTF-32BE').valid_encoding?.should be_false
+ "\x01\x02\x03\x04".force_encoding('UTF-32LE').valid_encoding?.should be_false
str.force_encoding('Windows-1251').valid_encoding?.should be_true
str.force_encoding('IBM437').valid_encoding?.should be_true
str.force_encoding('IBM737').valid_encoding?.should be_true
diff --git a/spec/ruby/core/struct/deconstruct_keys_spec.rb b/spec/ruby/core/struct/deconstruct_keys_spec.rb
index f0a1f50ad3..088803d028 100644
--- a/spec/ruby/core/struct/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/struct/deconstruct_keys_spec.rb
@@ -1,78 +1,76 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "Struct#deconstruct_keys" do
- it "returns a hash of attributes" do
- struct = Struct.new(:x, :y)
- s = struct.new(1, 2)
-
- s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
- end
-
- it "requires one argument" do
- struct = Struct.new(:x)
- obj = struct.new(1)
-
- -> {
- obj.deconstruct_keys
- }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
- end
-
- it "returns only specified keys" do
- struct = Struct.new(:x, :y, :z)
- s = struct.new(1, 2, 3)
-
- s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
- s.deconstruct_keys([:x] ).should == {x: 1}
- s.deconstruct_keys([] ).should == {}
- end
-
- it "accepts string attribute names" do
- struct = Struct.new(:x, :y)
- s = struct.new(1, 2)
-
- s.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
- end
-
- it "accepts argument position number as well but returns them as keys" do
- struct = Struct.new(:x, :y, :z)
- s = struct.new(10, 20, 30)
-
- s.deconstruct_keys([0, 1, 2]).should == {0 => 10, 1 => 20, 2 => 30}
- s.deconstruct_keys([0, 1] ).should == {0 => 10, 1 => 20}
- s.deconstruct_keys([0] ).should == {0 => 10}
- end
-
- it "returns an empty hash when there are more keys than attributes" do
- struct = Struct.new(:x, :y)
- s = struct.new(1, 2)
-
- s.deconstruct_keys([:x, :y, :a]).should == {}
- end
-
- it "returns at first not existing attribute name" do
- struct = Struct.new(:x, :y)
- s = struct.new(1, 2)
-
- s.deconstruct_keys([:a, :x]).should == {}
- s.deconstruct_keys([:x, :a]).should == {x: 1}
- end
-
- it "accepts nil argument and return all the attributes" do
- struct = Struct.new(:x, :y)
- obj = struct.new(1, 2)
-
- obj.deconstruct_keys(nil).should == {x: 1, y: 2}
- end
-
- it "raise TypeError if passed anything accept nil or array" do
- struct = Struct.new(:x, :y)
- s = struct.new(1, 2)
-
- -> { s.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
- -> { s.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
- -> { s.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
- -> { s.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
- end
+describe "Struct#deconstruct_keys" do
+ it "returns a hash of attributes" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ end
+
+ it "requires one argument" do
+ struct = Struct.new(:x)
+ obj = struct.new(1)
+
+ -> {
+ obj.deconstruct_keys
+ }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ end
+
+ it "returns only specified keys" do
+ struct = Struct.new(:x, :y, :z)
+ s = struct.new(1, 2, 3)
+
+ s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ s.deconstruct_keys([:x] ).should == {x: 1}
+ s.deconstruct_keys([] ).should == {}
+ end
+
+ it "accepts string attribute names" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
+ end
+
+ it "accepts argument position number as well but returns them as keys" do
+ struct = Struct.new(:x, :y, :z)
+ s = struct.new(10, 20, 30)
+
+ s.deconstruct_keys([0, 1, 2]).should == {0 => 10, 1 => 20, 2 => 30}
+ s.deconstruct_keys([0, 1] ).should == {0 => 10, 1 => 20}
+ s.deconstruct_keys([0] ).should == {0 => 10}
+ end
+
+ it "returns an empty hash when there are more keys than attributes" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([:x, :y, :a]).should == {}
+ end
+
+ it "returns at first not existing attribute name" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([:a, :x]).should == {}
+ s.deconstruct_keys([:x, :a]).should == {x: 1}
+ end
+
+ it "accepts nil argument and return all the attributes" do
+ struct = Struct.new(:x, :y)
+ obj = struct.new(1, 2)
+
+ obj.deconstruct_keys(nil).should == {x: 1, y: 2}
+ end
+
+ it "raise TypeError if passed anything accept nil or array" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ -> { s.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
end
end
diff --git a/spec/ruby/core/struct/deconstruct_spec.rb b/spec/ruby/core/struct/deconstruct_spec.rb
index 7518a40987..32d4f6bac4 100644
--- a/spec/ruby/core/struct/deconstruct_spec.rb
+++ b/spec/ruby/core/struct/deconstruct_spec.rb
@@ -1,12 +1,10 @@
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)
+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
+ s.deconstruct.should == [1, 2]
end
end
diff --git a/spec/ruby/core/struct/initialize_spec.rb b/spec/ruby/core/struct/initialize_spec.rb
index e82289071a..cfb302209e 100644
--- a/spec/ruby/core/struct/initialize_spec.rb
+++ b/spec/ruby/core/struct/initialize_spec.rb
@@ -40,4 +40,12 @@ describe "Struct#initialize" do
it "can be overridden" do
StructClasses::SubclassX.new(:y).new.key.should == :value
end
+
+ ruby_version_is "3.1"..."3.2" do
+ it "warns about passing only keyword arguments" do
+ -> {
+ StructClasses::Ruby.new(version: "3.1", platform: "OS")
+ }.should complain(/warning: Passing only keyword arguments/)
+ end
+ end
end
diff --git a/spec/ruby/core/struct/keyword_init_spec.rb b/spec/ruby/core/struct/keyword_init_spec.rb
new file mode 100644
index 0000000000..061f4c56e0
--- /dev/null
+++ b/spec/ruby/core/struct/keyword_init_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ # See https://bugs.ruby-lang.org/issues/18008
+ describe "StructClass#keyword_init?" do
+ it "returns true for a struct that accepts keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: true)
+ struct.keyword_init?.should be_true
+ end
+
+ it "returns false for a struct that does not accept keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: false)
+ struct.keyword_init?.should be_false
+ end
+
+ it "returns nil for a struct that did not explicitly specify keyword_init" do
+ struct = Struct.new(:arg)
+ struct.keyword_init?.should be_nil
+ end
+ end
+end
diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb
index cbbec829d7..7b4a4f7980 100644
--- a/spec/ruby/core/struct/new_spec.rb
+++ b/spec/ruby/core/struct/new_spec.rb
@@ -62,8 +62,20 @@ describe "Struct.new" do
-> { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError)
end
- it "raises a ArgumentError if passed a Hash with an unknown key" do
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError)
+ ruby_version_is ""..."3.2" do
+ it "raises a TypeError or ArgumentError if passed a Hash with an unknown key" do
+ # CRuby < 3.2 raises ArgumentError: unknown keyword: :name, but that seems a bug:
+ # https://bugs.ruby-lang.org/issues/18632
+ -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(StandardError) { |e|
+ [ArgumentError, TypeError].should.include?(e.class)
+ }
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "raises a TypeError if passed a Hash with an unknown key" do
+ -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
+ end
end
it "raises ArgumentError when there is a duplicate member" do
diff --git a/spec/ruby/core/struct/values_at_spec.rb b/spec/ruby/core/struct/values_at_spec.rb
index 7e517cdb4b..5e5a496600 100644
--- a/spec/ruby/core/struct/values_at_spec.rb
+++ b/spec/ruby/core/struct/values_at_spec.rb
@@ -1,16 +1,59 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+# Should be synchronized with core/array/values_at_spec.rb
describe "Struct#values_at" do
- it "returns an array of values" do
+ before do
clazz = Struct.new(:name, :director, :year)
- movie = clazz.new('Sympathy for Mr. Vengence', 'Chan-wook Park', 2002)
- movie.values_at(0, 1).should == ['Sympathy for Mr. Vengence', 'Chan-wook Park']
- movie.values_at(0..2).should == ['Sympathy for Mr. Vengence', 'Chan-wook Park', 2002]
+ @movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002)
+ end
+
+ context "when passed a list of Integers" do
+ it "returns an array containing each value given by one of integers" do
+ @movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park']
+ end
+
+ it "raises IndexError if any of integers is out of range" do
+ -> { @movie.values_at(3) }.should raise_error(IndexError, "offset 3 too large for struct(size:3)")
+ -> { @movie.values_at(-4) }.should raise_error(IndexError, "offset -4 too small for struct(size:3)")
+ end
+ end
+
+ context "when passed an integer Range" do
+ it "returns an array containing each value given by the elements of the range" do
+ @movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002]
+ end
+
+ it "fills with nil values for range elements larger than the structure" do
+ @movie.values_at(0..3).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, nil]
+ end
+
+ it "raises RangeError if any element of the range is negative and out of range" do
+ -> { @movie.values_at(-4..3) }.should raise_error(RangeError, "-4..3 out of range")
+ end
+
+ it "supports endless Range" do
+ @movie.values_at(0..).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002]
+ end
+
+ it "supports beginningless Range" do
+ @movie.values_at(..2).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002]
+ end
+ end
+
+ it "supports multiple integer Ranges" do
+ @movie.values_at(0..2, 1..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 'Chan-wook Park', 2002]
+ end
+
+ it "supports mixing integer Ranges and Integers" do
+ @movie.values_at(0..2, 2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 2002]
+ end
+
+ it "returns a new empty Array if no arguments given" do
+ @movie.values_at().should == []
end
it "fails when passed unsupported types" do
- car = StructClasses::Car.new('Ford', 'Ranger')
- -> { car.values_at('make') }.should raise_error(TypeError)
+ -> { @movie.values_at('make') }.should raise_error(TypeError, "no implicit conversion of String into Integer")
end
end
diff --git a/spec/ruby/core/symbol/end_with_spec.rb b/spec/ruby/core/symbol/end_with_spec.rb
index 77dc4caf71..4b9f5a4996 100644
--- a/spec/ruby/core/symbol/end_with_spec.rb
+++ b/spec/ruby/core/symbol/end_with_spec.rb
@@ -3,8 +3,6 @@
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
+describe "Symbol#end_with?" do
+ it_behaves_like :end_with, :to_sym
end
diff --git a/spec/ruby/core/symbol/shared/id2name.rb b/spec/ruby/core/symbol/shared/id2name.rb
index 47f97bd332..d012b7634e 100644
--- a/spec/ruby/core/symbol/shared/id2name.rb
+++ b/spec/ruby/core/symbol/shared/id2name.rb
@@ -6,4 +6,11 @@ describe :symbol_id2name, shared: true do
:@ruby.send(@method).should == "@ruby"
:@@ruby.send(@method).should == "@@ruby"
end
+
+ it "returns a String in the same encoding as self" do
+ string = "ruby".encode("US-ASCII")
+ symbol = string.to_sym
+
+ symbol.send(@method).encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/core/symbol/shared/slice.rb b/spec/ruby/core/symbol/shared/slice.rb
index 3f07f6aedb..0df87e183d 100644
--- a/spec/ruby/core/symbol/shared/slice.rb
+++ b/spec/ruby/core/symbol/shared/slice.rb
@@ -190,16 +190,6 @@ describe :symbol_slice, shared: true do
:symbol.send(@method, /[0-9]+/)
$~.should be_nil
end
-
- ruby_version_is ''...'2.7' do
- it "returns a tainted string if the regexp is tainted" do
- :symbol.send(@method, /./.taint).tainted?.should be_true
- end
-
- it "returns an untrusted string if the regexp is untrusted" do
- :symbol.send(@method, /./.untrust).untrusted?.should be_true
- end
- end
end
describe "with a capture index" do
@@ -221,16 +211,6 @@ describe :symbol_slice, shared: true do
:symbol.send(@method, /(sy)(mb)(ol)/, 1.5).should == "sy"
end
- ruby_version_is ''...'2.7' do
- it "returns a tainted string if the regexp is tainted" do
- :symbol.send(@method, /(.)/.taint, 1).tainted?.should be_true
- end
-
- it "returns an untrusted string if the regexp is untrusted" do
- :symbol.send(@method, /(.)/.untrust, 1).untrusted?.should be_true
- end
- end
-
describe "and an index that cannot be converted to an Integer" do
it "raises a TypeError when given an Hash" do
-> { :symbol.send(@method, /(sy)(mb)(ol)/, Hash.new) }.should raise_error(TypeError)
diff --git a/spec/ruby/core/symbol/start_with_spec.rb b/spec/ruby/core/symbol/start_with_spec.rb
index f54b3e499e..cd43279003 100644
--- a/spec/ruby/core/symbol/start_with_spec.rb
+++ b/spec/ruby/core/symbol/start_with_spec.rb
@@ -3,8 +3,6 @@ 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
+describe "Symbol#start_with?" do
+ it_behaves_like :start_with, :to_sym
end
diff --git a/spec/ruby/core/symbol/to_proc_spec.rb b/spec/ruby/core/symbol/to_proc_spec.rb
index e9261e6cdf..6d9c4bc622 100644
--- a/spec/ruby/core/symbol/to_proc_spec.rb
+++ b/spec/ruby/core/symbol/to_proc_spec.rb
@@ -46,8 +46,37 @@ describe "Symbol#to_proc" do
end
end
+ ruby_version_is "3.2" do
+ it "only calls public methods" do
+ body = proc do
+ public def pub; @a << :pub end
+ protected def pro; @a << :pro end
+ private def pri; @a << :pri end
+ attr_reader :a
+ end
+
+ @a = []
+ singleton_class.class_eval(&body)
+ tap(&:pub)
+ proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method `pro' called/)
+ proc{tap(&:pri)}.should raise_error(NoMethodError, /private method `pri' called/)
+ @a.should == [:pub]
+
+ @a = []
+ c = Class.new(&body)
+ o = c.new
+ o.instance_variable_set(:@a, [])
+ o.tap(&:pub)
+ proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method `pro' called/)
+ proc{o.tap(&:pri)}.should raise_error(NoMethodError, /private method `pri' called/)
+ o.a.should == [:pub]
+ end
+ 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")
+ -> {
+ :object_id.to_proc.call
+ }.should raise_error(ArgumentError, /no receiver given|wrong number of arguments \(given 0, expected 1\+\)/)
end
it "passes along the block passed to Proc#call" do
diff --git a/spec/ruby/core/thread/backtrace/limit_spec.rb b/spec/ruby/core/thread/backtrace/limit_spec.rb
new file mode 100644
index 0000000000..26a87a806c
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/limit_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "Thread::Backtrace.limit" do
+ it "returns maximum backtrace length set by --backtrace-limit command-line option" do
+ out = ruby_exe("print Thread::Backtrace.limit", options: "--backtrace-limit=2")
+ out.should == "2"
+ end
+
+ it "returns -1 when --backtrace-limit command-line option is not set" do
+ out = ruby_exe("print Thread::Backtrace.limit")
+ out.should == "-1"
+ end
+ end
+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 4136f09348..e35e1fc0b4 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -17,6 +17,15 @@ describe 'Thread::Backtrace::Location#absolute_path' do
end
end
+ it 'returns the correct absolute path when using a relative main script path and changing CWD' do
+ script = fixture(__FILE__, 'subdir/absolute_path_main_chdir.rb')
+ sibling = fixture(__FILE__, 'subdir/sibling.rb')
+ subdir = File.dirname script
+ Dir.chdir(fixture(__FILE__)) do
+ ruby_exe('subdir/absolute_path_main_chdir.rb').should == "subdir/absolute_path_main_chdir.rb\n#{subdir}\n#{subdir}\n#{script}\n#{sibling}\n"
+ end
+ end
+
context "when used in eval with a given filename" do
code = "caller_locations(0)[0].absolute_path"
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb
new file mode 100644
index 0000000000..33c8fb36ef
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb
@@ -0,0 +1,11 @@
+puts __FILE__
+puts __dir__
+Dir.chdir __dir__
+
+# Check __dir__ is still correct after chdir
+puts __dir__
+
+puts caller_locations(0)[0].absolute_path
+
+# require_relative also needs to know the absolute path of the current file so we test it here too
+require_relative 'sibling'
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb
new file mode 100644
index 0000000000..2a854ddccd
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb
@@ -0,0 +1 @@
+puts __FILE__
diff --git a/spec/ruby/core/thread/backtrace_locations_spec.rb b/spec/ruby/core/thread/backtrace_locations_spec.rb
index 237941c214..c970ae023b 100644
--- a/spec/ruby/core/thread/backtrace_locations_spec.rb
+++ b/spec/ruby/core/thread/backtrace_locations_spec.rb
@@ -49,12 +49,10 @@ describe "Thread#backtrace_locations" do
locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
end
- ruby_version_is "2.7" do
- it "can be called with an beginless range" do
- locations1 = Thread.current.backtrace_locations(0)
- locations2 = Thread.current.backtrace_locations(eval("(..5)"))
- locations2.map(&:to_s)[eval("(2..)")].should == locations1[eval("(..5)")].map(&:to_s)[eval("(2..)")]
- end
+ it "can be called with an beginless range" do
+ locations1 = Thread.current.backtrace_locations(0)
+ locations2 = Thread.current.backtrace_locations((..5))
+ locations2.map(&:to_s)[eval("(2..)")].should == locations1[(..5)].map(&:to_s)[eval("(2..)")]
end
it "returns nil if omitting more locations than available" do
diff --git a/spec/ruby/core/thread/ignore_deadlock_spec.rb b/spec/ruby/core/thread/ignore_deadlock_spec.rb
new file mode 100644
index 0000000000..53cc2a7f5b
--- /dev/null
+++ b/spec/ruby/core/thread/ignore_deadlock_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.0" do
+ describe "Thread.ignore_deadlock" do
+ it "returns false by default" do
+ Thread.ignore_deadlock.should == false
+ end
+ end
+
+ describe "Thread.ignore_deadlock=" do
+ it "changes the value of Thread.ignore_deadlock" do
+ ignore_deadlock = Thread.ignore_deadlock
+ Thread.ignore_deadlock = true
+ begin
+ Thread.ignore_deadlock.should == true
+ ensure
+ Thread.ignore_deadlock = ignore_deadlock
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/thread/native_thread_id_spec.rb b/spec/ruby/core/thread/native_thread_id_spec.rb
new file mode 100644
index 0000000000..d6cc332bf6
--- /dev/null
+++ b/spec/ruby/core/thread/native_thread_id_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+
+if ruby_version_is "3.1" and Thread.method_defined?(:native_thread_id)
+ # This method is very platform specific
+
+ describe "Thread#native_thread_id" do
+ it "returns an integer when the thread is alive" do
+ Thread.current.native_thread_id.should be_kind_of(Integer)
+ end
+
+ it "returns nil when the thread is not running" do
+ t = Thread.new {}
+ t.join
+ t.native_thread_id.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/thread/raise_spec.rb b/spec/ruby/core/thread/raise_spec.rb
index 27de3cc627..49323cf270 100644
--- a/spec/ruby/core/thread/raise_spec.rb
+++ b/spec/ruby/core/thread/raise_spec.rb
@@ -102,6 +102,30 @@ describe "Thread#raise on a sleeping thread" do
raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
end
end
+
+ it "calls #exception in both the caller and in the target thread" do
+ cls = Class.new(Exception) do
+ attr_accessor :log
+ def initialize(*args)
+ @log = [] # This is shared because the super #exception uses a shallow clone
+ super
+ end
+
+ def exception(*args)
+ @log << [self, Thread.current, args]
+ super
+ end
+ end
+ exc = cls.new
+
+ @thr.raise exc, "Thread#raise #exception spec"
+ @thr.join
+ ScratchPad.recorded.should.is_a?(cls)
+ exc.log.should == [
+ [exc, Thread.current, ["Thread#raise #exception spec"]],
+ [ScratchPad.recorded, @thr, []]
+ ]
+ end
end
describe "Thread#raise on a running thread" do
diff --git a/spec/ruby/core/thread/report_on_exception_spec.rb b/spec/ruby/core/thread/report_on_exception_spec.rb
index bf50a167df..9279fa1da5 100644
--- a/spec/ruby/core/thread/report_on_exception_spec.rb
+++ b/spec/ruby/core/thread/report_on_exception_spec.rb
@@ -60,6 +60,57 @@ describe "Thread#report_on_exception=" do
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception specs")
end
+
+ ruby_version_is "3.0" do
+ it "prints a backtrace on $stderr in the regular backtrace order" do
+ line_raise = __LINE__ + 2
+ def foo
+ raise RuntimeError, "Thread#report_on_exception specs backtrace order"
+ end
+
+ line_call_foo = __LINE__ + 5
+ go = false
+ t = Thread.new {
+ Thread.current.report_on_exception = true
+ Thread.pass until go
+ foo
+ }
+
+ -> {
+ go = true
+ Thread.pass while t.alive?
+ }.should output("", <<ERR)
+#{t.inspect} terminated with exception (report_on_exception is true):
+#{__FILE__}:#{line_raise}:in `foo': Thread#report_on_exception specs backtrace order (RuntimeError)
+\tfrom #{__FILE__}:#{line_call_foo}:in `block (5 levels) in <top (required)>'
+ERR
+
+ -> {
+ t.join
+ }.should raise_error(RuntimeError, "Thread#report_on_exception specs backtrace order")
+ end
+ end
+
+ it "prints the backtrace even if the thread was killed just after Thread#raise" do
+ t = nil
+ ready = false
+ -> {
+ t = Thread.new {
+ Thread.current.report_on_exception = true
+ ready = true
+ sleep
+ }
+
+ Thread.pass until ready and t.stop?
+ t.raise RuntimeError, "Thread#report_on_exception before kill spec"
+ t.kill
+ Thread.pass while t.alive?
+ }.should output("", /Thread.+terminated with exception.+Thread#report_on_exception before kill spec/m)
+
+ -> {
+ t.join
+ }.should raise_error(RuntimeError, "Thread#report_on_exception before kill spec")
+ end
end
describe "when set to false" do
diff --git a/spec/ruby/core/thread/shared/exit.rb b/spec/ruby/core/thread/shared/exit.rb
index 40dc478947..3663827579 100644
--- a/spec/ruby/core/thread/shared/exit.rb
+++ b/spec/ruby/core/thread/shared/exit.rb
@@ -66,6 +66,26 @@ describe :thread_exit, shared: true do
ScratchPad.recorded.should == nil
end
+ it "does not reset $!" do
+ ScratchPad.record []
+
+ exc = RuntimeError.new("foo")
+ thread = Thread.new do
+ begin
+ raise exc
+ ensure
+ ScratchPad << $!
+ begin
+ Thread.current.send(@method)
+ ensure
+ ScratchPad << $!
+ end
+ end
+ end
+ thread.join
+ ScratchPad.recorded.should == [exc, exc]
+ end
+
it "cannot be rescued" do
thread = Thread.new do
begin
@@ -73,7 +93,7 @@ describe :thread_exit, shared: true do
rescue Exception
ScratchPad.record :in_rescue
end
- ScratchPad.record :end_of_thread_block
+ ScratchPad.record :end_of_thread_block
end
thread.join
diff --git a/spec/ruby/core/thread/shared/to_s.rb b/spec/ruby/core/thread/shared/to_s.rb
index 45c04af627..43640deb33 100644
--- a/spec/ruby/core/thread/shared/to_s.rb
+++ b/spec/ruby/core/thread/shared/to_s.rb
@@ -1,12 +1,10 @@
require_relative '../fixtures/classes'
describe :thread_to_s, shared: true do
- sep = ruby_version_is("2.7") ? " " : "@"
-
it "returns a description including file and line number" do
thread, line = Thread.new { "hello" }, __LINE__
thread.join
- thread.send(@method).should =~ /^#<Thread:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{line} \w+>$/
+ thread.send(@method).should =~ /^#<Thread:([^ ]*?) #{Regexp.escape __FILE__}:#{line} \w+>$/
end
it "has a binary encoding" do
diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb
index 2cc46ab8c9..0459589f01 100644
--- a/spec/ruby/core/time/at_spec.rb
+++ b/spec/ruby/core/time/at_spec.rb
@@ -251,6 +251,22 @@ describe "Time.at" do
time.to_i.should == @epoch_time
end
+ it "could be UTC offset as a 'UTC' String" do
+ time = Time.at(@epoch_time, in: "UTC")
+
+ time.utc_offset.should == 0
+ time.zone.should == "UTC"
+ time.to_i.should == @epoch_time
+ end
+
+ it "could be UTC offset as a military zone A-Z" do
+ time = Time.at(@epoch_time, in: "B")
+
+ time.utc_offset.should == 3600 * 2
+ time.zone.should == nil
+ time.to_i.should == @epoch_time
+ end
+
it "could be a timezone object" do
zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
time = Time.at(@epoch_time, in: zone)
@@ -266,5 +282,10 @@ describe "Time.at" do
time.zone.should == zone
time.to_i.should == @epoch_time
end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.at(@epoch_time, in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.at(@epoch_time, in: "ABC") }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/time/ceil_spec.rb b/spec/ruby/core/time/ceil_spec.rb
index 86029554db..9d624a1ed0 100644
--- a/spec/ruby/core/time/ceil_spec.rb
+++ b/spec/ruby/core/time/ceil_spec.rb
@@ -1,46 +1,44 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "Time#ceil" do
- before do
- @time = Time.utc(2010, 3, 30, 5, 43, "25.0123456789".to_r)
- end
-
- it "defaults to ceiling to 0 places" do
- @time.ceil.should == Time.utc(2010, 3, 30, 5, 43, 26.to_r)
- end
+describe "Time#ceil" do
+ before do
+ @time = Time.utc(2010, 3, 30, 5, 43, "25.0123456789".to_r)
+ end
- it "ceils to 0 decimal places with an explicit argument" do
- @time.ceil(0).should == Time.utc(2010, 3, 30, 5, 43, 26.to_r)
- end
+ it "defaults to ceiling to 0 places" do
+ @time.ceil.should == Time.utc(2010, 3, 30, 5, 43, 26.to_r)
+ end
- it "ceils to 2 decimal places with an explicit argument" do
- @time.ceil(2).should == Time.utc(2010, 3, 30, 5, 43, "25.02".to_r)
- end
+ it "ceils to 0 decimal places with an explicit argument" do
+ @time.ceil(0).should == Time.utc(2010, 3, 30, 5, 43, 26.to_r)
+ end
- it "ceils to 4 decimal places with an explicit argument" do
- @time.ceil(4).should == Time.utc(2010, 3, 30, 5, 43, "25.0124".to_r)
- end
+ it "ceils to 2 decimal places with an explicit argument" do
+ @time.ceil(2).should == Time.utc(2010, 3, 30, 5, 43, "25.02".to_r)
+ end
- it "ceils to 7 decimal places with an explicit argument" do
- @time.ceil(7).should == Time.utc(2010, 3, 30, 5, 43, "25.0123457".to_r)
- end
+ it "ceils to 4 decimal places with an explicit argument" do
+ @time.ceil(4).should == Time.utc(2010, 3, 30, 5, 43, "25.0124".to_r)
+ end
- it "returns an instance of Time, even if #ceil is called on a subclass" do
- subclass = Class.new(Time)
- instance = subclass.at(0)
- instance.class.should equal subclass
- instance.ceil.should be_an_instance_of(Time)
- end
+ it "ceils to 7 decimal places with an explicit argument" do
+ @time.ceil(7).should == Time.utc(2010, 3, 30, 5, 43, "25.0123457".to_r)
+ end
- it "copies own timezone to the returning value" do
- @time.zone.should == @time.ceil.zone
+ it "returns an instance of Time, even if #ceil is called on a subclass" do
+ subclass = Class.new(Time)
+ instance = subclass.at(0)
+ instance.class.should equal subclass
+ instance.ceil.should be_an_instance_of(Time)
+ end
- time = with_timezone "JST-9" do
- Time.at 0, 1
- end
+ it "copies own timezone to the returning value" do
+ @time.zone.should == @time.ceil.zone
- 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
diff --git a/spec/ruby/core/time/floor_spec.rb b/spec/ruby/core/time/floor_spec.rb
index a19585b787..b0003469c9 100644
--- a/spec/ruby/core/time/floor_spec.rb
+++ b/spec/ruby/core/time/floor_spec.rb
@@ -1,38 +1,36 @@
require_relative '../../spec_helper'
-ruby_version_is "2.7" do
- describe "Time#floor" do
- before do
- @time = Time.utc(2010, 3, 30, 5, 43, "25.123456789".to_r)
- end
-
- it "defaults to flooring to 0 places" do
- @time.floor.should == Time.utc(2010, 3, 30, 5, 43, 25.to_r)
- end
+describe "Time#floor" do
+ before do
+ @time = Time.utc(2010, 3, 30, 5, 43, "25.123456789".to_r)
+ end
- it "floors to 0 decimal places with an explicit argument" do
- @time.floor(0).should == Time.utc(2010, 3, 30, 5, 43, 25.to_r)
- end
+ it "defaults to flooring to 0 places" do
+ @time.floor.should == Time.utc(2010, 3, 30, 5, 43, 25.to_r)
+ end
- it "floors to 7 decimal places with an explicit argument" do
- @time.floor(7).should == Time.utc(2010, 3, 30, 5, 43, "25.1234567".to_r)
- end
+ it "floors to 0 decimal places with an explicit argument" do
+ @time.floor(0).should == Time.utc(2010, 3, 30, 5, 43, 25.to_r)
+ end
- it "returns an instance of Time, even if #floor is called on a subclass" do
- subclass = Class.new(Time)
- instance = subclass.at(0)
- instance.class.should equal subclass
- instance.floor.should be_an_instance_of(Time)
- end
+ it "floors to 7 decimal places with an explicit argument" do
+ @time.floor(7).should == Time.utc(2010, 3, 30, 5, 43, "25.1234567".to_r)
+ end
- it "copies own timezone to the returning value" do
- @time.zone.should == @time.floor.zone
+ it "returns an instance of Time, even if #floor is called on a subclass" do
+ subclass = Class.new(Time)
+ instance = subclass.at(0)
+ instance.class.should equal subclass
+ instance.floor.should be_an_instance_of(Time)
+ end
- time = with_timezone "JST-9" do
- Time.at 0, 1
- end
+ it "copies own timezone to the returning value" do
+ @time.zone.should == @time.floor.zone
- 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
diff --git a/spec/ruby/core/time/inspect_spec.rb b/spec/ruby/core/time/inspect_spec.rb
index 6f1b2e3ef1..c3a4519a24 100644
--- a/spec/ruby/core/time/inspect_spec.rb
+++ b/spec/ruby/core/time/inspect_spec.rb
@@ -4,32 +4,30 @@ require_relative 'shared/inspect'
describe "Time#inspect" do
it_behaves_like :inspect, :inspect
- ruby_version_is "2.7" do
- it "preserves microseconds" do
- t = Time.utc(2007, 11, 1, 15, 25, 0, 123456)
- t.inspect.should == "2007-11-01 15:25:00.123456 UTC"
- end
+ it "preserves microseconds" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 123456)
+ t.inspect.should == "2007-11-01 15:25:00.123456 UTC"
+ end
- it "omits trailing zeros from microseconds" do
- t = Time.utc(2007, 11, 1, 15, 25, 0, 100000)
- t.inspect.should == "2007-11-01 15:25:00.1 UTC"
- end
+ it "omits trailing zeros from microseconds" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 100000)
+ t.inspect.should == "2007-11-01 15:25:00.1 UTC"
+ end
- it "uses the correct time zone without microseconds" do
- t = Time.utc(2000, 1, 1)
- t = t.localtime(9*3600)
- t.inspect.should == "2000-01-01 09:00:00 +0900"
- end
+ it "uses the correct time zone without microseconds" do
+ t = Time.utc(2000, 1, 1)
+ t = t.localtime(9*3600)
+ t.inspect.should == "2000-01-01 09:00:00 +0900"
+ end
- it "uses the correct time zone with microseconds" do
- t = Time.utc(2000, 1, 1, 0, 0, 0, 123456)
- t = t.localtime(9*3600)
- t.inspect.should == "2000-01-01 09:00:00.123456 +0900"
- end
+ it "uses the correct time zone with microseconds" do
+ t = Time.utc(2000, 1, 1, 0, 0, 0, 123456)
+ t = t.localtime(9*3600)
+ t.inspect.should == "2000-01-01 09:00:00.123456 +0900"
+ end
- it "preserves nanoseconds" do
- t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
- t.inspect.should == "2007-11-01 15:25:00.123456789 UTC"
- end
+ it "preserves nanoseconds" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
+ t.inspect.should == "2007-11-01 15:25:00.123456789 UTC"
end
end
diff --git a/spec/ruby/core/time/localtime_spec.rb b/spec/ruby/core/time/localtime_spec.rb
index 2975e112d0..609b6532a1 100644
--- a/spec/ruby/core/time/localtime_spec.rb
+++ b/spec/ruby/core/time/localtime_spec.rb
@@ -29,10 +29,10 @@ describe "Time#localtime" do
time.localtime.should equal(time)
end
- it "raises a RuntimeError if the time has a different time zone" do
+ it "raises a FrozenError if the time has a different time zone" do
time = Time.gm(2007, 1, 9, 12, 0, 0)
time.freeze
- -> { time.localtime }.should raise_error(RuntimeError)
+ -> { time.localtime }.should raise_error(FrozenError)
end
end
@@ -79,6 +79,18 @@ describe "Time#localtime" do
t.utc_offset.should == -3600
end
+ it "returns a Time with a UTC offset specified as UTC" do
+ t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
+ t.localtime("UTC")
+ t.utc_offset.should == 0
+ end
+
+ it "returns a Time with a UTC offset specified as A-Z military zone" do
+ t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
+ t.localtime("B")
+ t.utc_offset.should == 3600 * 2
+ end
+
platform_is_not :windows do
it "changes the timezone according to the set one" do
t = Time.new(2005, 2, 27, 22, 50, 0, -3600)
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index 09b4d03a44..727fdf92c2 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -58,6 +58,32 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
end
+ ruby_bug '#13669', '3.0'...'3.1' do
+ it "returns a Time with a UTC offset specified as +HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+05").utc_offset.should == 3600 * 5
+ end
+
+ it "returns a Time with a UTC offset specified as -HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-05").utc_offset.should == -3600 * 5
+ end
+
+ it "returns a Time with a UTC offset specified as +HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+0530").utc_offset.should == 19800
+ end
+
+ it "returns a Time with a UTC offset specified as -HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-0530").utc_offset.should == -19800
+ end
+
+ it "returns a Time with a UTC offset specified as +HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+053037").utc_offset.should == 19837
+ end
+
+ it "returns a Time with a UTC offset specified as -HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-053037").utc_offset.should == -19837
+ end
+ end
+
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@@ -66,6 +92,57 @@ describe "Time.new with a utc_offset argument" do
end
end
+ it "returns a Time with UTC offset specified as UTC" do
+ Time.new(2000, 1, 1, 0, 0, 0, "UTC").utc_offset.should == 0
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ [
+ ["A", 3600],
+ ["B", 3600 * 2],
+ ["C", 3600 * 3],
+ ["D", 3600 * 4],
+ ["E", 3600 * 5],
+ ["F", 3600 * 6],
+ ["G", 3600 * 7],
+ ["H", 3600 * 8],
+ ["I", 3600 * 9],
+ # J is not supported
+ ["K", 3600 * 10],
+ ["L", 3600 * 11],
+ ["M", 3600 * 12],
+ ["N", 3600 * -1],
+ ["O", 3600 * -2],
+ ["P", 3600 * -3],
+ ["Q", 3600 * -4],
+ ["R", 3600 * -5],
+ ["S", 3600 * -6],
+ ["T", 3600 * -7],
+ ["U", 3600 * -8],
+ ["V", 3600 * -9],
+ ["W", 3600 * -10],
+ ["X", 3600 * -11],
+ ["Y", 3600 * -12],
+ ["Z", 0]
+ ].each do |letter, offset|
+ Time.new(2000, 1, 1, 0, 0, 0, letter).utc_offset.should == offset
+ end
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "raises ArgumentError if the string argument is J" do
+ message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "raises ArgumentError if the string argument is J" do
+ message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: J'
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
+ end
+ end
+
it "returns a local Time if the argument is nil" do
with_timezone("PST", -8) do
t = Time.new(2000, 1, 1, 0, 0, 0, nil)
@@ -93,7 +170,12 @@ describe "Time.new with a utc_offset argument" do
end
it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do
- -> { Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE")) }.should raise_error(ArgumentError)
+ # Don't check exception message - it was changed in previous CRuby versions:
+ # - "string contains null byte"
+ # - '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
+ -> {
+ Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE"))
+ }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do
@@ -106,19 +188,9 @@ describe "Time.new with a utc_offset argument" do
-> { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError)
end
- it "raises ArgumentError if the seconds argument is negative" do
- -> { Time.new(2000, 1, 1, 0, 0, -1) }.should raise_error(ArgumentError)
- end
-
it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
-> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
end
-
- it "raises ArgumentError if the month is greater than 12" do
- # For some reason MRI uses a different message for month in 13-15 and month>=16
- -> { Time.new(2000, 13, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, /(mon|argument) out of range/)
- -> { Time.new(2000, 16, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, "argument out of range")
- end
end
describe "Time.new with a timezone argument" do
@@ -332,4 +404,55 @@ describe "Time.new with a timezone argument" do
end
end
end
+
+ ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/17485
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "ABC") }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if two offset arguments are given" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, "+05:00", in: "+05:00") }.should raise_error(ArgumentError)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/time/now_spec.rb b/spec/ruby/core/time/now_spec.rb
index 7dc7951996..2b2e53a17c 100644
--- a/spec/ruby/core/time/now_spec.rb
+++ b/spec/ruby/core/time/now_spec.rb
@@ -3,4 +3,49 @@ require_relative 'shared/now'
describe "Time.now" do
it_behaves_like :time_now, :now
+
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.now(in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.now(in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.now(in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.now(in: "ABC") }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/time/shared/gmtime.rb b/spec/ruby/core/time/shared/gmtime.rb
index 5ed64c2ab6..bae19da462 100644
--- a/spec/ruby/core/time/shared/gmtime.rb
+++ b/spec/ruby/core/time/shared/gmtime.rb
@@ -22,11 +22,11 @@ describe :time_gmtime, shared: true do
time.send(@method).should equal(time)
end
- it "raises a RuntimeError if the time is not UTC" do
+ it "raises a FrozenError if the time is not UTC" do
with_timezone("CST", -6) do
time = Time.now
time.freeze
- -> { time.send(@method) }.should raise_error(RuntimeError)
+ -> { time.send(@method) }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/time/shared/local.rb b/spec/ruby/core/time/shared/local.rb
index 43f331c4c1..068e314999 100644
--- a/spec/ruby/core/time/shared/local.rb
+++ b/spec/ruby/core/time/shared/local.rb
@@ -7,12 +7,10 @@ describe :time_local, shared: true do
end
platform_is_not :windows do
- describe "timezone changes" do
- it "correctly adjusts the timezone change to 'CEST' on 'Europe/Amsterdam'" do
- with_timezone("Europe/Amsterdam") do
- Time.send(@method, 1940, 5, 16).to_a.should ==
- [0, 40, 1, 16, 5, 1940, 4, 137, true, "CEST"]
- end
+ it "uses the 'CET' timezone with TZ=Europe/Amsterdam in 1970" do
+ with_timezone("Europe/Amsterdam") do
+ Time.send(@method, 1970, 5, 16).to_a.should ==
+ [0, 0, 0, 16, 5, 1970, 6, 136, false, "CET"]
end
end
end
@@ -41,5 +39,4 @@ describe :time_local_10_arg, shared: true do
end
end
end
-
end
diff --git a/spec/ruby/core/time/shared/time_params.rb b/spec/ruby/core/time/shared/time_params.rb
index 63d0dbc120..b6a6c88c8e 100644
--- a/spec/ruby/core/time/shared/time_params.rb
+++ b/spec/ruby/core/time/shared/time_params.rb
@@ -145,9 +145,10 @@ describe :time_params, shared: true do
end
it "raises an ArgumentError for out of range month" do
+ # For some reason MRI uses a different message for month in 13-15 and month>=16
-> {
- Time.send(@method, 2008, 13, 31, 23, 59, 59)
- }.should raise_error(ArgumentError)
+ Time.send(@method, 2008, 16, 31, 23, 59, 59)
+ }.should raise_error(ArgumentError, /(mon|argument) out of range/)
end
it "raises an ArgumentError for out of range day" do
@@ -169,9 +170,13 @@ describe :time_params, shared: true do
end
it "raises an ArgumentError for out of range second" do
+ # For some reason MRI uses different messages for seconds 61-63 and seconds >= 64
-> {
Time.send(@method, 2008, 12, 31, 23, 59, 61)
- }.should raise_error(ArgumentError)
+ }.should raise_error(ArgumentError, /(sec|argument) out of range/)
+ -> {
+ Time.send(@method, 2008, 12, 31, 23, 59, -1)
+ }.should raise_error(ArgumentError, "argument out of range")
end
it "raises ArgumentError when given 9 arguments" do
diff --git a/spec/ruby/core/time/strftime_spec.rb b/spec/ruby/core/time/strftime_spec.rb
index 1bd24b0538..4cb300c916 100644
--- a/spec/ruby/core/time/strftime_spec.rb
+++ b/spec/ruby/core/time/strftime_spec.rb
@@ -49,4 +49,45 @@ describe "Time#strftime" do
time = @new_time_with_offset[2012, 1, 1, 0, 0, 0, Rational(36645, 10)]
time.strftime("%::z").should == "+01:01:05"
end
+
+ ruby_version_is "3.1" do
+ it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do
+ time = Time.gm(2022)
+
+ time.strftime("%z").should == "+0000"
+ time.strftime("%-z").should == "-0000"
+ time.strftime("%-:z").should == "-00:00"
+ time.strftime("%-::z").should == "-00:00:00"
+ end
+
+ it "applies '-' flag to UTC time" do
+ time = Time.utc(2022)
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.gm(2022)
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.new(2022, 1, 1, 0, 0, 0, "Z")
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.new(2022, 1, 1, 0, 0, 0, "-00:00")
+ time.strftime("%-z").should == "-0000"
+
+ time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00").utc
+ time.strftime("%-z").should == "-0000"
+ end
+
+ it "ignores '-' flag for non-UTC time" do
+ time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00")
+ time.strftime("%-z").should == "+0300"
+ end
+
+ it "works correctly with width, _ and 0 flags, and :" do
+ Time.now.utc.strftime("%-_10z").should == " -000"
+ Time.now.utc.strftime("%-10z").should == "-000000000"
+ Time.now.utc.strftime("%-010:z").should == "-000000:00"
+ Time.now.utc.strftime("%-_10:z").should == " -0:00"
+ Time.now.utc.strftime("%-_10::z").should == " -0:00:00"
+ end
+ end
end
diff --git a/spec/ruby/core/time/utc_spec.rb b/spec/ruby/core/time/utc_spec.rb
index 74c17a93d1..809accc809 100644
--- a/spec/ruby/core/time/utc_spec.rb
+++ b/spec/ruby/core/time/utc_spec.rb
@@ -4,8 +4,45 @@ require_relative 'shared/gmtime'
require_relative 'shared/time_params'
describe "Time#utc?" do
- it "returns true if time represents a time in UTC (GMT)" do
- Time.now.should_not.utc?
+ it "returns true only if time represents a time in UTC (GMT)" do
+ Time.now.utc?.should == false
+ Time.now.utc.utc?.should == true
+ end
+
+ it "treats time as UTC what was created in different ways" do
+ Time.now.utc.utc?.should == true
+ Time.now.gmtime.utc?.should == true
+ Time.now.getgm.utc?.should == true
+ Time.now.getutc.utc?.should == true
+ Time.utc(2022).utc?.should == true
+ end
+
+ it "does treat time with 'UTC' offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "UTC").utc?.should == true
+ Time.now.localtime("UTC").utc?.should == true
+ Time.at(Time.now, in: 'UTC').utc?.should == true
+ end
+
+ it "does treat time with Z offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "Z").utc?.should == true
+ Time.now.localtime("Z").utc?.should == true
+ Time.at(Time.now, in: 'Z').utc?.should == true
+ end
+
+ ruby_version_is "3.1" do
+ it "does treat time with -00:00 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "-00:00").utc?.should == true
+ Time.now.localtime("-00:00").utc?.should == true
+ Time.at(Time.now, in: '-00:00').utc?.should == true
+ end
+ end
+
+ it "does not treat time with +00:00 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "+00:00").utc?.should == false
+ end
+
+ it "does not treat time with 0 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, 0).utc?.should == false
end
end
diff --git a/spec/ruby/core/time/zone_spec.rb b/spec/ruby/core/time/zone_spec.rb
index 907ccf9f4b..cbb0977f24 100644
--- a/spec/ruby/core/time/zone_spec.rb
+++ b/spec/ruby/core/time/zone_spec.rb
@@ -52,14 +52,28 @@ describe "Time#zone" do
end
it "doesn't raise errors for a Time with a fixed offset" do
- -> {
- Time.new(2001, 1, 1, 0, 0, 0, "+05:00").zone
- }.should_not raise_error
+ Time.new(2001, 1, 1, 0, 0, 0, "+05:00").zone.should == nil
end
end
it "returns UTC when called on a UTC time" do
Time.now.utc.zone.should == "UTC"
+ Time.now.gmtime.zone.should == "UTC"
+ Time.now.getgm.zone.should == "UTC"
+ Time.now.getutc.zone.should == "UTC"
+ Time.utc(2022).zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, "UTC").zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, "Z").zone.should == "UTC"
+ Time.now.localtime("UTC").zone.should == "UTC"
+ Time.now.localtime("Z").zone.should == "UTC"
+ Time.at(Time.now, in: 'UTC').zone.should == "UTC"
+ Time.at(Time.now, in: 'Z').zone.should == "UTC"
+
+ ruby_version_is "3.1" do
+ Time.new(2022, 1, 1, 0, 0, 0, "-00:00").zone.should == "UTC"
+ Time.now.localtime("-00:00").zone.should == "UTC"
+ Time.at(Time.now, in: '-00:00').zone.should == "UTC"
+ end
end
platform_is_not :aix, :windows do
diff --git a/spec/ruby/core/tracepoint/allow_reentry_spec.rb b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
new file mode 100644
index 0000000000..6bff1bed76
--- /dev/null
+++ b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
@@ -0,0 +1,32 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1" do
+ describe 'TracePoint.allow_reentry' do
+ it 'allows the reentrance in a given block' do
+ event_lines = []
+ l1 = l2 = l3 = l4 = nil
+ TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
+
+ event_lines << tp.lineno
+ next if (__LINE__ + 2 .. __LINE__ + 4).cover?(tp.lineno)
+ TracePoint.allow_reentry do
+ a = 1; l3 = __LINE__
+ b = 2; l4 = __LINE__
+ end
+ end.enable do
+ c = 3; l1 = __LINE__
+ d = 4; l2 = __LINE__
+ end
+
+ event_lines.should == [l1, l3, l4, l2, l3, l4]
+ end
+
+ it 'raises RuntimeError when not called inside a TracePoint' do
+ -> {
+ TracePoint.allow_reentry{}
+ }.should raise_error(RuntimeError)
+ end
+ end
+end
diff --git a/spec/ruby/core/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb
index ab392c7583..24f6070b97 100644
--- a/spec/ruby/core/tracepoint/enable_spec.rb
+++ b/spec/ruby/core/tracepoint/enable_spec.rb
@@ -57,25 +57,50 @@ describe 'TracePoint#enable' do
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
+ ruby_version_is '3.2' do
+ it 'enables the trace object only for the current thread' do
+ threads = []
+ trace = TracePoint.new(:line) do |tp|
+ # Runs on purpose on any Thread
+ threads << Thread.current
+ end
- thread = nil
- trace.enable do
- line_event = true
- thread = Thread.new do
- event_in_other_thread = true
+ thread = nil
+ trace.enable do
+ line_event = true
+ thread = Thread.new do
+ event_in_other_thread = true
+ end
+ thread.join
end
- thread.join
+
+ threads = threads.uniq
+ threads.should.include?(Thread.current)
+ threads.should_not.include?(thread)
end
+ end
- threads = threads.uniq
- threads.should.include?(Thread.current)
- threads.should.include?(thread)
+ ruby_version_is ''...'3.2' do
+ it 'enables the trace object for any thread' do
+ threads = []
+ trace = TracePoint.new(:line) do |tp|
+ # Runs on purpose on any Thread
+ threads << Thread.current
+ end
+
+ thread = nil
+ trace.enable do
+ line_event = true
+ thread = Thread.new do
+ event_in_other_thread = true
+ end
+ thread.join
+ end
+
+ threads = threads.uniq
+ threads.should.include?(Thread.current)
+ threads.should.include?(thread)
+ end
end
it 'can accept arguments within a block but it should not yield arguments' do
diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb
index 06bed9c99a..151a08e7b4 100644
--- a/spec/ruby/core/tracepoint/inspect_spec.rb
+++ b/spec/ruby/core/tracepoint/inspect_spec.rb
@@ -16,6 +16,15 @@ describe 'TracePoint#inspect' do
TracePoint.new(:line) {}.inspect.should == '#<TracePoint:disabled>'
end
+ it "shows only whether it's enabled when outside the TracePoint handler" do
+ trace = TracePoint.new(:line) {}
+ trace.enable
+
+ trace.inspect.should == '#<TracePoint:enabled>'
+
+ trace.disable
+ end
+
it 'returns a String showing the event, path and line' do
inspect = nil
line = nil
@@ -64,12 +73,12 @@ describe 'TracePoint#inspect' do
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|
+ tracepoint = TracePoint.new(:c_call) { |tp|
next unless TracePointSpec.target_thread?
inspect ||= tp.inspect
- }.enable do
- line = __LINE__ + 1
+ }
+ line = __LINE__ + 2
+ tracepoint.enable do
[0, 1].max
end
@@ -98,7 +107,7 @@ describe 'TracePoint#inspect' do
TracePoint.new(:thread_begin) { |tp|
next unless Thread.current == thread
inspect ||= tp.inspect
- }.enable do
+ }.enable(target_thread: nil) do
thread = Thread.new {}
thread_inspection = thread.inspect
thread.join
@@ -114,7 +123,7 @@ describe 'TracePoint#inspect' do
TracePoint.new(:thread_end) { |tp|
next unless Thread.current == thread
inspect ||= tp.inspect
- }.enable do
+ }.enable(target_thread: nil) do
thread = Thread.new {}
thread_inspection = thread.inspect
thread.join
diff --git a/spec/ruby/core/true/to_s_spec.rb b/spec/ruby/core/true/to_s_spec.rb
index f26cd138e2..fa1b53a580 100644
--- a/spec/ruby/core/true/to_s_spec.rb
+++ b/spec/ruby/core/true/to_s_spec.rb
@@ -5,13 +5,11 @@ describe "TrueClass#to_s" do
true.to_s.should == "true"
end
- ruby_version_is "2.7" do
- it "returns a frozen string" do
- true.to_s.should.frozen?
- end
+ it "returns a frozen string" do
+ true.to_s.should.frozen?
+ end
- it "always returns the same string" do
- true.to_s.should equal(true.to_s)
- end
+ it "always returns the same string" do
+ true.to_s.should equal(true.to_s)
end
end
diff --git a/spec/ruby/core/unboundmethod/bind_call_spec.rb b/spec/ruby/core/unboundmethod/bind_call_spec.rb
index c5d392156c..8f25f8bd0d 100644
--- a/spec/ruby/core/unboundmethod/bind_call_spec.rb
+++ b/spec/ruby/core/unboundmethod/bind_call_spec.rb
@@ -1,52 +1,50 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '2.7' do
- describe "UnboundMethod#bind_call" do
- before :each do
- @normal_um = UnboundMethodSpecs::Methods.new.method(:foo).unbind
- @parent_um = UnboundMethodSpecs::Parent.new.method(:foo).unbind
- @child1_um = UnboundMethodSpecs::Child1.new.method(:foo).unbind
- @child2_um = UnboundMethodSpecs::Child2.new.method(:foo).unbind
- end
+describe "UnboundMethod#bind_call" do
+ before :each do
+ @normal_um = UnboundMethodSpecs::Methods.new.method(:foo).unbind
+ @parent_um = UnboundMethodSpecs::Parent.new.method(:foo).unbind
+ @child1_um = UnboundMethodSpecs::Child1.new.method(:foo).unbind
+ @child2_um = UnboundMethodSpecs::Child2.new.method(:foo).unbind
+ end
- it "raises TypeError if object is not kind_of? the Module the method defined in" do
- -> { @normal_um.bind_call(UnboundMethodSpecs::B.new) }.should raise_error(TypeError)
- end
+ it "raises TypeError if object is not kind_of? the Module the method defined in" do
+ -> { @normal_um.bind_call(UnboundMethodSpecs::B.new) }.should raise_error(TypeError)
+ end
- it "binds and calls the method if object is kind_of the Module the method defined in" do
- @normal_um.bind_call(UnboundMethodSpecs::Methods.new).should == true
- end
+ it "binds and calls the method if object is kind_of the Module the method defined in" do
+ @normal_um.bind_call(UnboundMethodSpecs::Methods.new).should == true
+ end
- it "binds and calls the method on any object when UnboundMethod is unbound from a module" do
- UnboundMethodSpecs::Mod.instance_method(:from_mod).bind_call(Object.new).should == nil
- end
+ it "binds and calls the method on any object when UnboundMethod is unbound from a module" do
+ UnboundMethodSpecs::Mod.instance_method(:from_mod).bind_call(Object.new).should == nil
+ end
- it "binds and calls the method for any object kind_of? the Module the method is defined in" do
- @parent_um.bind_call(UnboundMethodSpecs::Child1.new).should == nil
- @child1_um.bind_call(UnboundMethodSpecs::Parent.new).should == nil
- @child2_um.bind_call(UnboundMethodSpecs::Child1.new).should == nil
- end
+ it "binds and calls the method for any object kind_of? the Module the method is defined in" do
+ @parent_um.bind_call(UnboundMethodSpecs::Child1.new).should == nil
+ @child1_um.bind_call(UnboundMethodSpecs::Parent.new).should == nil
+ @child2_um.bind_call(UnboundMethodSpecs::Child1.new).should == nil
+ end
- it "binds and calls a Kernel method retrieved from Object on BasicObject" do
- Object.instance_method(:instance_of?).bind_call(BasicObject.new, BasicObject).should == true
- end
+ it "binds and calls a Kernel method retrieved from Object on BasicObject" do
+ Object.instance_method(:instance_of?).bind_call(BasicObject.new, BasicObject).should == true
+ end
- it "binds and calls a Parent's class method to any Child's class methods" do
- um = UnboundMethodSpecs::Parent.method(:class_method).unbind
- um.bind_call(UnboundMethodSpecs::Child1).should == "I am UnboundMethodSpecs::Child1"
- end
+ it "binds and calls a Parent's class method to any Child's class methods" do
+ um = UnboundMethodSpecs::Parent.method(:class_method).unbind
+ um.bind_call(UnboundMethodSpecs::Child1).should == "I am UnboundMethodSpecs::Child1"
+ end
- it "will raise when binding a an object singleton's method to another object" do
- other = UnboundMethodSpecs::Parent.new
- p = UnboundMethodSpecs::Parent.new
- class << p
- def singleton_method
- :single
- end
+ it "will raise when binding a an object singleton's method to another object" do
+ other = UnboundMethodSpecs::Parent.new
+ p = UnboundMethodSpecs::Parent.new
+ class << p
+ def singleton_method
+ :single
end
- um = p.method(:singleton_method).unbind
- ->{ um.bind_call(other) }.should raise_error(TypeError)
end
+ um = p.method(:singleton_method).unbind
+ ->{ um.bind_call(other) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/unboundmethod/equal_value_spec.rb b/spec/ruby/core/unboundmethod/equal_value_spec.rb
index 6242b04884..036c6b7f8c 100644
--- a/spec/ruby/core/unboundmethod/equal_value_spec.rb
+++ b/spec/ruby/core/unboundmethod/equal_value_spec.rb
@@ -76,19 +76,38 @@ describe "UnboundMethod#==" do
(@identical_body == @original_body).should == false
end
- it "returns false if same method but one extracted from a subclass" do
- (@parent == @child1).should == false
- (@child1 == @parent).should == false
- end
+ ruby_version_is ""..."3.2" do
+ it "returns false if same method but one extracted from a subclass" do
+ (@parent == @child1).should == false
+ (@child1 == @parent).should == false
+ end
+
+ it "returns false if same method but extracted from two different subclasses" do
+ (@child2 == @child1).should == false
+ (@child1 == @child2).should == false
+ end
- it "returns false if same method but extracted from two different subclasses" do
- (@child2 == @child1).should == false
- (@child1 == @child2).should == false
+ it "returns false if methods are the same but added from an included Module" do
+ (@includee == @includer).should == false
+ (@includer == @includee).should == false
+ end
end
- it "returns false if methods are the same but added from an included Module" do
- (@includee == @includer).should == false
- (@includer == @includee).should == false
+ ruby_version_is "3.2" do
+ it "returns true if same method but one extracted from a subclass" do
+ (@parent == @child1).should == true
+ (@child1 == @parent).should == true
+ end
+
+ it "returns false if same method but extracted from two different subclasses" do
+ (@child2 == @child1).should == true
+ (@child1 == @child2).should == true
+ end
+
+ it "returns true if methods are the same but added from an included Module" do
+ (@includee == @includer).should == true
+ (@includer == @includee).should == true
+ end
end
it "returns false if both have same Module, same name, identical body but not the same" do
@@ -98,4 +117,41 @@ describe "UnboundMethod#==" do
(@discard_1 == UnboundMethodSpecs::Methods.instance_method(:discard_1)).should == false
end
+
+ it "considers methods through aliasing equal" do
+ c = Class.new do
+ class << self
+ alias_method :n, :new
+ end
+ end
+
+ c.method(:new).should == c.method(:n)
+ c.method(:n).should == Class.instance_method(:new).bind(c)
+ end
+
+ # On CRuby < 3.2, the 2 specs below pass due to method/instance_method skipping zsuper methods.
+ # We are interested in the general pattern working, i.e. the combination of method/instance_method
+ # and #== exposes the wanted behavior.
+ it "considers methods through visibility change equal" do
+ c = Class.new do
+ class << self
+ private :new
+ end
+ end
+
+ c.method(:new).should == Class.instance_method(:new).bind(c)
+ end
+
+ it "considers methods through aliasing and visibility change equal" do
+ c = Class.new do
+ class << self
+ alias_method :n, :new
+ private :new
+ end
+ end
+
+ c.method(:new).should == c.method(:n)
+ c.method(:n).should == Class.instance_method(:new).bind(c)
+ c.method(:new).should == Class.instance_method(:new).bind(c)
+ end
end
diff --git a/spec/ruby/core/unboundmethod/fixtures/classes.rb b/spec/ruby/core/unboundmethod/fixtures/classes.rb
index 46b1c51669..6ab958d447 100644
--- a/spec/ruby/core/unboundmethod/fixtures/classes.rb
+++ b/spec/ruby/core/unboundmethod/fixtures/classes.rb
@@ -53,6 +53,12 @@ module UnboundMethodSpecs
def discard_1(); :discard; end
def discard_2(); :discard; end
+
+ def my_public_method; end
+ def my_protected_method; end
+ def my_private_method; end
+ protected :my_protected_method
+ private :my_private_method
end
class Parent
@@ -84,4 +90,14 @@ module UnboundMethodSpecs
class C < B
def overridden; end
end
+
+ module HashSpecs
+ class SuperClass
+ def foo
+ end
+ end
+
+ class SubClass < SuperClass
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/hash_spec.rb b/spec/ruby/core/unboundmethod/hash_spec.rb
index 12dce0020f..6888675bc1 100644
--- a/spec/ruby/core/unboundmethod/hash_spec.rb
+++ b/spec/ruby/core/unboundmethod/hash_spec.rb
@@ -12,4 +12,11 @@ describe "UnboundMethod#hash" do
to_s, inspect = Array.instance_method(:to_s), Array.instance_method(:inspect)
to_s.hash.should == inspect.hash
end
+
+ it "equals a hash of the same method in the superclass" do
+ foo_in_superclass = UnboundMethodSpecs::HashSpecs::SuperClass.instance_method(:foo)
+ foo = UnboundMethodSpecs::HashSpecs::SubClass.instance_method(:foo)
+
+ foo.hash.should == foo_in_superclass.hash
+ end
end
diff --git a/spec/ruby/core/unboundmethod/owner_spec.rb b/spec/ruby/core/unboundmethod/owner_spec.rb
index 5f1f4646b3..e8a734dac4 100644
--- a/spec/ruby/core/unboundmethod/owner_spec.rb
+++ b/spec/ruby/core/unboundmethod/owner_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../method/fixtures/classes'
describe "UnboundMethod#owner" do
it "returns the owner of the method" do
@@ -23,4 +24,10 @@ describe "UnboundMethod#owner" do
child_singleton_class.instance_method(:class_method).owner.should == parent_singleton_class
child_singleton_class.instance_method(:another_class_method).owner.should == child_singleton_class
end
+
+ ruby_version_is "3.2" do
+ it "returns the class on which public was called for a private method in ancestor" do
+ MethodSpecs::InheritedMethods::C.instance_method(:derp).owner.should == MethodSpecs::InheritedMethods::C
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/private_spec.rb b/spec/ruby/core/unboundmethod/private_spec.rb
new file mode 100644
index 0000000000..fa735846bb
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/private_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "UnboundMethod#private?" do
+ it "returns false when the method is public" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.private?.should == false
+ end
+
+ it "returns false when the method is protected" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.private?.should == false
+ end
+
+ it "returns true when the method is private" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.private?.should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/protected_spec.rb b/spec/ruby/core/unboundmethod/protected_spec.rb
new file mode 100644
index 0000000000..db00e7ef43
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/protected_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "UnboundMethod#protected?" do
+ it "returns false when the method is public" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.protected?.should == false
+ end
+
+ it "returns true when the method is protected" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.protected?.should == true
+ end
+
+ it "returns false when the method is private" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.protected?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/public_spec.rb b/spec/ruby/core/unboundmethod/public_spec.rb
new file mode 100644
index 0000000000..7b87a03b15
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/public_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "UnboundMethod#public?" do
+ it "returns true when the method is public" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.public?.should == true
+ end
+
+ it "returns false when the method is protected" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.public?.should == false
+ end
+
+ it "returns false when the method is private" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.public?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/shared/to_s.rb b/spec/ruby/core/unboundmethod/shared/to_s.rb
index 38503c3c60..b92bb0b207 100644
--- a/spec/ruby/core/unboundmethod/shared/to_s.rb
+++ b/spec/ruby/core/unboundmethod/shared/to_s.rb
@@ -20,12 +20,22 @@ describe :unboundmethod_to_s, shared: true do
it "the String shows the method name, Module defined in and Module extracted from" do
@from_module.send(@method).should =~ /\bfrom_mod\b/
@from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/
- @from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/
+
+ ruby_version_is ""..."3.2" do
+ @from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/
+ end
end
it "returns a String including all details" do
- @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"
+ ruby_version_is ""..."3.2" do
+ @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
+ @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
+ end
+
+ ruby_version_is "3.2" do
+ @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
+ @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
+ end
end
it "does not show the defining module if it is the same as the origin" do
diff --git a/spec/ruby/core/unboundmethod/super_method_spec.rb b/spec/ruby/core/unboundmethod/super_method_spec.rb
index c9fa1ec533..101c83b8b3 100644
--- a/spec/ruby/core/unboundmethod/super_method_spec.rb
+++ b/spec/ruby/core/unboundmethod/super_method_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../method/fixtures/classes'
describe "UnboundMethod#super_method" do
it "returns the method that would be called by super in the method" do
@@ -25,4 +26,26 @@ describe "UnboundMethod#super_method" do
method.super_method.should == nil
end
+
+ # https://github.com/jruby/jruby/issues/7240
+ context "after changing an inherited methods visibility" do
+ it "calls the proper super method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
+ method.bind(MethodSpecs::InheritedMethods::C.new).call.should == 'BA'
+ end
+
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+
+ ruby_version_is "2.7.3" do
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/warning/element_reference_spec.rb b/spec/ruby/core/warning/element_reference_spec.rb
index c3bf06a95b..67728ca0f6 100644
--- a/spec/ruby/core/warning/element_reference_spec.rb
+++ b/spec/ruby/core/warning/element_reference_spec.rb
@@ -1,14 +1,20 @@
require_relative '../../spec_helper'
-ruby_version_is '2.7.2' do
- describe "Warning.[]" do
+describe "Warning.[]" do
+ ruby_version_is '2.7.2' 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
+ end
- it "raises for unknown category" do
- -> { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/)
- end
+ it "raises for unknown category" do
+ -> { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/)
+ end
+
+ it "raises for non-Symbol category" do
+ -> { Warning[42] }.should raise_error(TypeError)
+ -> { Warning[false] }.should raise_error(TypeError)
+ -> { Warning["noop"] }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/warning/element_set_spec.rb b/spec/ruby/core/warning/element_set_spec.rb
index 3b0ea45c9b..d20ee215ad 100644
--- a/spec/ruby/core/warning/element_set_spec.rb
+++ b/spec/ruby/core/warning/element_set_spec.rb
@@ -1,31 +1,35 @@
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
+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
- ruby_version_is "3.0" do
- @src = 'warn "This is experimental warning.", category: :experimental'
- end
+ describe ":experimental" do
+ before do
+ ruby_version_is ""..."3.0" do
+ @src = 'case [0, 1]; in [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 == ""
+ ruby_version_is "3.0" do
+ @src = 'warn "This is experimental warning.", category: :experimental'
end
end
- it "raises for unknown category" do
- -> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/)
+ it "emits and suppresses warnings for :experimental" do
+ ruby_exe("Warning[:experimental] = true; eval('#{@src}')", args: "2>&1").should =~ /is experimental/
+ ruby_exe("Warning[:experimental] = false; eval('#{@src}')", args: "2>&1").should == ""
end
end
+
+ it "raises for unknown category" do
+ -> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/)
+ end
+
+ it "raises for non-Symbol category" do
+ -> { Warning[42] = false }.should raise_error(TypeError)
+ -> { Warning[false] = false }.should raise_error(TypeError)
+ -> { Warning["noop"] = false }.should raise_error(TypeError)
+ end
end
diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb
index 2ded6a109d..5ccff3aa2b 100644
--- a/spec/ruby/core/warning/warn_spec.rb
+++ b/spec/ruby/core/warning/warn_spec.rb
@@ -51,7 +51,6 @@ describe "Warning.warn" do
end
end
-
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)
@@ -69,7 +68,7 @@ describe "Warning.warn" do
verbose = $VERBOSE
$VERBOSE = false
begin
- Kernel.warn("Chunky bacon!", category: 'deprecated')
+ Kernel.warn("Chunky bacon!", category: "deprecated")
ensure
$VERBOSE = verbose
end
diff --git a/spec/ruby/fixtures/class.rb b/spec/ruby/fixtures/class.rb
index 68fbca7ba7..98cb6c82a2 100644
--- a/spec/ruby/fixtures/class.rb
+++ b/spec/ruby/fixtures/class.rb
@@ -122,6 +122,10 @@ module ClassSpecs
end
end
end
+
+ DEFINE_CLASS = -> do
+ class ::A; end
+ end
end
class Class
diff --git a/spec/ruby/fixtures/code/a/load_fixture.dylib b/spec/ruby/fixtures/code/a/load_fixture.dylib
new file mode 100644
index 0000000000..31f4b1a7bb
--- /dev/null
+++ b/spec/ruby/fixtures/code/a/load_fixture.dylib
@@ -0,0 +1 @@
+ScratchPad << :ext_dylib
diff --git a/spec/ruby/fixtures/code/c/load_fixture.rb b/spec/ruby/fixtures/code/c/load_fixture.rb
new file mode 100644
index 0000000000..4a6e9c9601
--- /dev/null
+++ b/spec/ruby/fixtures/code/c/load_fixture.rb
@@ -0,0 +1 @@
+ScratchPad << :loaded
diff --git a/spec/ruby/fixtures/code/concurrent_require_fixture.rb b/spec/ruby/fixtures/code/concurrent_require_fixture.rb
new file mode 100644
index 0000000000..d4ce734183
--- /dev/null
+++ b/spec/ruby/fixtures/code/concurrent_require_fixture.rb
@@ -0,0 +1,4 @@
+object = ScratchPad.recorded
+thread = Thread.new { object.require(__FILE__) }
+Thread.pass until thread.stop?
+ScratchPad.record(thread)
diff --git a/spec/ruby/fixtures/code/load_fixture.dylib b/spec/ruby/fixtures/code/load_fixture.dylib
new file mode 100644
index 0000000000..31f4b1a7bb
--- /dev/null
+++ b/spec/ruby/fixtures/code/load_fixture.dylib
@@ -0,0 +1 @@
+ScratchPad << :ext_dylib
diff --git a/spec/ruby/fixtures/code/load_fixture.ext.dylib b/spec/ruby/fixtures/code/load_fixture.ext.dylib
new file mode 100644
index 0000000000..31f4b1a7bb
--- /dev/null
+++ b/spec/ruby/fixtures/code/load_fixture.ext.dylib
@@ -0,0 +1 @@
+ScratchPad << :ext_dylib
diff --git a/spec/ruby/fixtures/code/wrap_fixture.rb b/spec/ruby/fixtures/code/load_wrap_fixture.rb
index 7ddf5a62e0..526bbf8c82 100644
--- a/spec/ruby/fixtures/code/wrap_fixture.rb
+++ b/spec/ruby/fixtures/code/load_wrap_fixture.rb
@@ -2,7 +2,10 @@ class LoadSpecWrap
ScratchPad << String
end
+LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT = 1
+
def load_wrap_specs_top_level_method
+ :load_wrap_specs_top_level_method
end
ScratchPad << method(:load_wrap_specs_top_level_method).owner
diff --git a/spec/ruby/fixtures/constants.rb b/spec/ruby/fixtures/constants.rb
index 37271ddcc8..47a8e87e56 100644
--- a/spec/ruby/fixtures/constants.rb
+++ b/spec/ruby/fixtures/constants.rb
@@ -75,6 +75,13 @@ module ConstantSpecs
CS_CONST10 = :const10_8
end
+ # Included in ContainerA
+ module ModuleIncludePrepended
+ prepend ModuleD
+
+ CS_CONST11 = :const11_8
+ end
+
# The following classes/modules have all the constants set "statically".
# Contrast with the classes below where the constants are set as the specs
# are run.
@@ -169,6 +176,10 @@ module ConstantSpecs
def const10; CS_CONST10; end
end
+ class ContainerPrepend
+ include ModuleIncludePrepended
+ end
+
class ContainerA::ChildA
def self.const23; CS_CONST23; end
end
@@ -299,4 +310,14 @@ module ConstantSpecs
private_constant :CS_PRIVATE
end
+module ConstantSpecsThree
+ module ConstantSpecsTwo
+ Foo = :cs_three_foo
+ end
+end
+
+module ConstantSpecsTwo
+ Foo = :cs_two_foo
+end
+
include ConstantSpecs::ModuleA
diff --git a/spec/ruby/language/alias_spec.rb b/spec/ruby/language/alias_spec.rb
index d1d06e3fac..c353390679 100644
--- a/spec/ruby/language/alias_spec.rb
+++ b/spec/ruby/language/alias_spec.rb
@@ -243,6 +243,19 @@ describe "The alias keyword" do
e.class.should == NameError
}
end
+
+ it "defines the method on the aliased class when the original method is from a parent class" do
+ parent = Class.new do
+ def parent_method
+ end
+ end
+ child = Class.new(parent) do
+ alias parent_method_alias parent_method
+ end
+
+ child.instance_method(:parent_method_alias).owner.should == child
+ child.instance_methods(false).should include(:parent_method_alias)
+ end
end
describe "The alias keyword" do
diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb
index b2a3cc84c4..8488b945d5 100644
--- a/spec/ruby/language/block_spec.rb
+++ b/spec/ruby/language/block_spec.rb
@@ -40,8 +40,17 @@ describe "A block yielded a single" do
m([1, 2]) { |a=5, b, c, d| [a, b, c, d] }.should == [5, 1, 2, nil]
end
- it "assigns elements to required arguments when a keyword rest argument is present" do
- m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
+ ruby_version_is "3.2" do
+ it "does not autosplat single argument to required arguments when a keyword rest argument is present" do
+ m([1, 2]) { |a, **k| [a, k] }.should == [[1, 2], {}]
+ end
+ end
+
+ ruby_version_is ''..."3.2" do
+ # https://bugs.ruby-lang.org/issues/18633
+ it "autosplats single argument to required arguments when a keyword rest argument is present" do
+ m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
+ end
end
ruby_version_is ''..."3.0" do
@@ -92,17 +101,7 @@ describe "A block yielded a single" do
end
end
- ruby_version_is ""..."2.7" do
- it "calls #to_hash on the argument and uses resulting hash as first argument 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})
-
- result = m([obj]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 1, "b" => 2}, {}]
- end
- end
-
- ruby_version_is "2.7"...'3.0' do
+ ruby_version_is ""...'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})
@@ -264,12 +263,55 @@ describe "A block yielded a single" do
m(obj) { |a, b, c| [a, b, c] }.should == [obj, nil, nil]
end
+ it "receives the object if it does not respond to #to_ary" do
+ obj = Object.new
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [obj, nil, nil]
+ end
+
+ it "calls #respond_to? to check if object has method #to_ary" do
+ obj = mock("destructure block arguments")
+ obj.should_receive(:respond_to?).with(:to_ary, true).and_return(true)
+ obj.should_receive(:to_ary).and_return([1, 2])
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [1, 2, nil]
+ end
+
+ it "receives the object if it does not respond to #respond_to?" do
+ obj = BasicObject.new
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [obj, nil, nil]
+ end
+
+ it "calls #to_ary on the object when it is defined dynamically" do
+ obj = Object.new
+ def obj.method_missing(name, *args, &block)
+ if name == :to_ary
+ [1, 2]
+ else
+ super
+ end
+ end
+ def obj.respond_to_missing?(name, include_private)
+ name == :to_ary
+ end
+
+ m(obj) { |a, b, c| [a, b, c] }.should == [1, 2, nil]
+ end
+
it "raises a TypeError if #to_ary does not return an Array" do
obj = mock("destructure block arguments")
obj.should_receive(:to_ary).and_return(1)
-> { m(obj) { |a, b| } }.should raise_error(TypeError)
end
+
+ it "raises error transparently if #to_ary raises error on its own" do
+ obj = Object.new
+ def obj.to_ary; raise "Exception raised in #to_ary" end
+
+ -> { m(obj) { |a, b| } }.should raise_error(RuntimeError, "Exception raised in #to_ary")
+ end
end
end
@@ -949,38 +991,18 @@ describe "Post-args" do
end
describe "with a circular argument reference" do
- ruby_version_is ''...'2.7' do
- it "warns and uses a nil value when there is an existing local variable with same name" do
- a = 1
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
-
- it "warns and uses a nil value when there is an existing method with same name" do
- def a; 1; end
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
+ it "raises a SyntaxError if using an existing local with the same name as the argument" do
+ a = 1
+ -> {
+ @proc = eval "proc { |a=a| a }"
+ }.should raise_error(SyntaxError)
end
- ruby_version_is '2.7' do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
- end
-
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
- end
+ it "raises a SyntaxError if there is an existing method with the same name as the argument" do
+ def a; 1; end
+ -> {
+ @proc = eval "proc { |a=a| a }"
+ }.should raise_error(SyntaxError)
end
it "calls an existing method with the same name as the argument if explicitly using ()" do
@@ -1004,3 +1026,77 @@ describe "Post-args" do
end
end
end
+
+describe "Anonymous block forwarding" do
+ ruby_version_is "3.1" do
+ it "forwards blocks to other functions that formally declare anonymous blocks" do
+ eval <<-EOF
+ def b(&); c(&) end
+ def c(&); yield :non_null end
+ EOF
+
+ b { |c| c }.should == :non_null
+ end
+
+ it "requires the anonymous block parameter to be declared if directly passing a block" do
+ -> { eval "def a; b(&); end; def b; end" }.should raise_error(SyntaxError)
+ end
+
+ it "works when it's the only declared parameter" do
+ eval <<-EOF
+ def inner; yield end
+ def block_only(&); inner(&) end
+ EOF
+
+ block_only { 1 }.should == 1
+ end
+
+ it "works alongside positional parameters" do
+ eval <<-EOF
+ def inner; yield end
+ def pos(arg1, &); inner(&) end
+ EOF
+
+ pos(:a) { 1 }.should == 1
+ end
+
+ it "works alongside positional arguments and splatted keyword arguments" do
+ eval <<-EOF
+ def inner; yield end
+ def pos_kwrest(arg1, **kw, &); inner(&) end
+ EOF
+
+ pos_kwrest(:a, arg: 3) { 1 }.should == 1
+ end
+
+ it "works alongside positional arguments and disallowed keyword arguments" do
+ eval <<-EOF
+ def inner; yield end
+ def no_kw(arg1, **nil, &); inner(&) end
+ EOF
+
+ no_kw(:a) { 1 }.should == 1
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "works alongside explicit keyword arguments" do
+ eval <<-EOF
+ def inner; yield end
+ def rest_kw(*a, kwarg: 1, &); inner(&) end
+ def kw(kwarg: 1, &); inner(&) end
+ def pos_kw_kwrest(arg1, kwarg: 1, **kw, &); inner(&) end
+ def pos_rkw(arg1, kwarg1:, &); inner(&) end
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &); inner(&) end
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &); inner(&) end
+ EOF
+
+ rest_kw { 1 }.should == 1
+ kw { 1 }.should == 1
+ pos_kw_kwrest(:a) { 1 }.should == 1
+ pos_rkw(:a, kwarg1: 3) { 1 }.should == 1
+ all(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ all_kwrest(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ end
+ end
+end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index 410cb9afb1..915c032a71 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -103,7 +103,7 @@ describe "The 'case'-construct" do
$1.should == "42"
end
- it "tests with a regexp interpolated within another regexp" do
+ it "tests with a string interpolated in a regexp" do
digits = '\d+'
case "foo44"
when /oo(#{digits})/
@@ -116,7 +116,7 @@ describe "The 'case'-construct" do
$1.should == "44"
end
- it "tests with a string interpolated in a regexp" do
+ it "tests with a regexp interpolated within another regexp" do
digits_regexp = /\d+/
case "foo43"
when /oo(#{digits_regexp})/
@@ -156,6 +156,15 @@ describe "The 'case'-construct" do
end.should == "foo"
end
+ it "tests an empty array" do
+ case []
+ when []
+ 'foo'
+ else
+ 'bar'
+ end.should == 'foo'
+ end
+
it "expands arrays to lists of values" do
case 'z'
when *['a', 'b', 'c', 'd']
diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb
index 83db164e1a..877895bf15 100644
--- a/spec/ruby/language/class_spec.rb
+++ b/spec/ruby/language/class_spec.rb
@@ -17,6 +17,19 @@ describe "The class keyword" do
eval "class ClassSpecsKeywordWithoutSemicolon end"
ClassSpecsKeywordWithoutSemicolon.should be_an_instance_of(Class)
end
+
+ it "can redefine a class when called from a block" do
+ ClassSpecs::DEFINE_CLASS.call
+ A.should be_an_instance_of(Class)
+
+ Object.send(:remove_const, :A)
+ defined?(A).should be_nil
+
+ ClassSpecs::DEFINE_CLASS.call
+ A.should be_an_instance_of(Class)
+ ensure
+ Object.send(:remove_const, :A) if defined?(::A)
+ end
end
describe "A class definition" do
diff --git a/spec/ruby/language/class_variable_spec.rb b/spec/ruby/language/class_variable_spec.rb
index dffab47a6b..f98deaa081 100644
--- a/spec/ruby/language/class_variable_spec.rb
+++ b/spec/ruby/language/class_variable_spec.rb
@@ -82,3 +82,35 @@ describe 'A class variable definition' do
c.class_variable_get(:@@cv).should == :next
end
end
+
+ruby_version_is "3.0" do
+ describe 'Accessing a class variable' do
+ it "raises a RuntimeError when accessed from the toplevel scope (not in some module or class)" do
+ -> {
+ eval "@@cvar_toplevel1"
+ }.should raise_error(RuntimeError, 'class variable access from toplevel')
+ -> {
+ eval "@@cvar_toplevel2 = 2"
+ }.should raise_error(RuntimeError, 'class variable access from toplevel')
+ end
+
+ it "does not raise an error when checking if defined from the toplevel scope" do
+ -> {
+ eval "defined?(@@cvar_toplevel1)"
+ }.should_not raise_error
+ end
+
+ it "raises a RuntimeError when a class variable is overtaken in an ancestor class" do
+ parent = Class.new()
+ subclass = Class.new(parent)
+ subclass.class_variable_set(:@@cvar_overtaken, :subclass)
+ parent.class_variable_set(:@@cvar_overtaken, :parent)
+
+ -> {
+ subclass.class_variable_get(:@@cvar_overtaken)
+ }.should raise_error(RuntimeError, /class variable @@cvar_overtaken of .+ is overtaken by .+/)
+
+ parent.class_variable_get(:@@cvar_overtaken).should == :parent
+ end
+ end
+end
diff --git a/spec/ruby/language/comment_spec.rb b/spec/ruby/language/comment_spec.rb
index 690e844dc0..dd788e681c 100644
--- a/spec/ruby/language/comment_spec.rb
+++ b/spec/ruby/language/comment_spec.rb
@@ -1,15 +1,13 @@
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
+ it "can be placed between fluent dot now" do
+ code = <<~CODE
+ 10
+ # some comment
+ .to_s
+ CODE
- eval(code).should == '10'
- end
+ eval(code).should == '10'
end
end
diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb
index 03f1272401..8586e46158 100644
--- a/spec/ruby/language/constants_spec.rb
+++ b/spec/ruby/language/constants_spec.rb
@@ -135,18 +135,34 @@ describe "Literal (A::X) constant resolution" do
ConstantSpecs::ClassB::CS_CONST109.should == :const109_2
end
- it "evaluates the right hand side before evaluating a constant path" do
- mod = Module.new
+ ruby_version_is "3.2" do
+ it "evaluates left-to-right" do
+ mod = Module.new
- mod.module_eval <<-EOC
- ConstantSpecsRHS::B = begin
- module ConstantSpecsRHS; end
+ mod.module_eval <<-EOC
+ order = []
+ ConstantSpecsRHS = Module.new
+ (order << :lhs; ConstantSpecsRHS)::B = (order << :rhs)
+ EOC
- "hello"
- end
- EOC
+ mod::ConstantSpecsRHS::B.should == [:lhs, :rhs]
+ end
+ end
+
+ ruby_version_is ""..."3.2" do
+ it "evaluates the right hand side before evaluating a constant path" do
+ mod = Module.new
+
+ mod.module_eval <<-EOC
+ ConstantSpecsRHS::B = begin
+ module ConstantSpecsRHS; end
+
+ "hello"
+ end
+ EOC
- mod::ConstantSpecsRHS::B.should == 'hello'
+ mod::ConstantSpecsRHS::B.should == 'hello'
+ end
end
end
@@ -718,3 +734,17 @@ describe 'Allowed characters' do
eval("mod::ἍBB").should == 1
end
end
+
+describe 'Assignment' do
+ context 'dynamic assignment' do
+ it 'raises SyntaxError' do
+ -> do
+ eval <<-CODE
+ def test
+ B = 1
+ end
+ CODE
+ end.should raise_error(SyntaxError, /dynamic constant assignment/)
+ end
+ end
+end
diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb
index 6b0be19d90..c8531343c0 100644
--- a/spec/ruby/language/def_spec.rb
+++ b/spec/ruby/language/def_spec.rb
@@ -197,32 +197,15 @@ describe "An instance method with a default argument" do
foo(2,3,3).should == [2,3,[3]]
end
- ruby_version_is ''...'2.7' do
- it "warns and uses a nil value when there is an existing local method with same name" do
- def bar
- 1
- end
- -> {
- eval "def foo(bar = bar)
- bar
- end"
- }.should complain(/circular argument reference/)
- foo.should == nil
- foo(2).should == 2
- end
- end
-
- ruby_version_is '2.7' do
- it "raises a syntaxError an existing method with the same name as the local variable" do
- def bar
- 1
- end
- -> {
- eval "def foo(bar = bar)
- bar
- end"
- }.should raise_error(SyntaxError)
+ it "raises a SyntaxError when there is an existing method with the same name as the local variable" do
+ def bar
+ 1
end
+ -> {
+ eval "def foo(bar = bar)
+ bar
+ end"
+ }.should raise_error(SyntaxError)
end
it "calls a method with the same name as the local when explicitly using ()" do
diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb
index f2da8a9293..ae2bf45bda 100644
--- a/spec/ruby/language/defined_spec.rb
+++ b/spec/ruby/language/defined_spec.rb
@@ -5,21 +5,25 @@ describe "The defined? keyword for literals" do
it "returns 'self' for self" do
ret = defined?(self)
ret.should == "self"
+ ret.frozen?.should == true
end
it "returns 'nil' for nil" do
ret = defined?(nil)
ret.should == "nil"
+ ret.frozen?.should == true
end
it "returns 'true' for true" do
ret = defined?(true)
ret.should == "true"
+ ret.frozen?.should == true
end
it "returns 'false' for false" do
ret = defined?(false)
ret.should == "false"
+ ret.frozen?.should == true
end
describe "for a literal Array" do
@@ -27,6 +31,7 @@ describe "The defined? keyword for literals" do
it "returns 'expression' if each element is defined" do
ret = defined?([Object, Array])
ret.should == "expression"
+ ret.frozen?.should == true
end
it "returns nil if one element is not defined" do
@@ -43,9 +48,25 @@ describe "The defined? keyword for literals" do
end
describe "The defined? keyword when called with a method name" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "does not call the method" do
+ defined?(DefinedSpecs.side_effects).should == "method"
+ ScratchPad.recorded.should != :defined_specs_side_effects
+ end
+
+ it "does not execute the arguments" do
+ defined?(DefinedSpecs.any_args(DefinedSpecs.side_effects)).should == "method"
+ ScratchPad.recorded.should != :defined_specs_side_effects
+ end
+
describe "without a receiver" do
it "returns 'method' if the method is defined" do
- defined?(puts).should == "method"
+ ret = defined?(puts)
+ ret.should == "method"
+ ret.frozen?.should == true
end
it "returns nil if the method is not defined" do
@@ -167,7 +188,9 @@ describe "The defined? keyword for an expression" do
end
it "returns 'assignment' for assigning a local variable" do
- defined?(x = 2).should == "assignment"
+ ret = defined?(x = 2)
+ ret.should == "assignment"
+ ret.frozen?.should == true
end
it "returns 'assignment' for assigning an instance variable" do
@@ -470,7 +493,9 @@ end
describe "The defined? keyword for variables" do
it "returns 'local-variable' when called with the name of a local variable" do
- DefinedSpecs::Basic.new.local_variable_defined.should == "local-variable"
+ ret = DefinedSpecs::Basic.new.local_variable_defined
+ ret.should == "local-variable"
+ ret.frozen?.should == true
end
it "returns 'local-variable' when called with the name of a local variable assigned to nil" do
@@ -486,7 +511,9 @@ describe "The defined? keyword for variables" do
end
it "returns 'instance-variable' for an instance variable that has been assigned" do
- DefinedSpecs::Basic.new.instance_variable_defined.should == "instance-variable"
+ ret = DefinedSpecs::Basic.new.instance_variable_defined
+ ret.should == "instance-variable"
+ ret.frozen?.should == true
end
it "returns 'instance-variable' for an instance variable that has been assigned to nil" do
@@ -502,7 +529,9 @@ describe "The defined? keyword for variables" do
end
it "returns 'global-variable' for a global variable that has been assigned nil" do
- DefinedSpecs::Basic.new.global_variable_defined_as_nil.should == "global-variable"
+ ret = DefinedSpecs::Basic.new.global_variable_defined_as_nil
+ ret.should == "global-variable"
+ ret.frozen?.should == true
end
# MRI appears to special case defined? for $! and $~ in that it returns
@@ -674,7 +703,9 @@ describe "The defined? keyword for variables" do
# get to the defined? call so it really has nothing to do with 'defined?'.
it "returns 'class variable' when called with the name of a class variable" do
- DefinedSpecs::Basic.new.class_variable_defined.should == "class variable"
+ ret = DefinedSpecs::Basic.new.class_variable_defined
+ ret.should == "class variable"
+ ret.frozen?.should == true
end
it "returns 'local-variable' when called with the name of a block local" do
@@ -685,7 +716,9 @@ end
describe "The defined? keyword for a simple constant" do
it "returns 'constant' when the constant is defined" do
- defined?(DefinedSpecs).should == "constant"
+ ret = defined?(DefinedSpecs)
+ ret.should == "constant"
+ ret.frozen?.should == true
end
it "returns nil when the constant is not defined" do
@@ -941,12 +974,26 @@ describe "The defined? keyword for yield" do
end
it "returns 'yield' if a block is passed to a method not taking a block parameter" do
- DefinedSpecs::Basic.new.yield_block.should == "yield"
+ ret = DefinedSpecs::Basic.new.yield_block
+ ret.should == "yield"
+ ret.frozen?.should == true
end
it "returns 'yield' if a block is passed to a method taking a block parameter" do
DefinedSpecs::Basic.new.yield_block_parameter.should == "yield"
end
+
+ it "returns 'yield' when called within a block" do
+ def yielder
+ yield
+ end
+
+ def call_defined
+ yielder { defined?(yield) }
+ end
+
+ call_defined() { }.should == "yield"
+ end
end
describe "The defined? keyword for super" do
@@ -972,7 +1019,9 @@ describe "The defined? keyword for super" do
end
it "returns 'super' when a superclass method exists" do
- DefinedSpecs::Super.new.method_no_args.should == "super"
+ ret = DefinedSpecs::Super.new.method_no_args
+ ret.should == "super"
+ ret.frozen?.should == true
end
it "returns 'super' from a block when a superclass method exists" do
diff --git a/spec/ruby/language/delegation_spec.rb b/spec/ruby/language/delegation_spec.rb
index 8e4183cbcc..3f24a79d5c 100644
--- a/spec/ruby/language/delegation_spec.rb
+++ b/spec/ruby/language/delegation_spec.rb
@@ -1,42 +1,40 @@
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
+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
+ 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
+ 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
+ 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
+ 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
+ a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
end
end
@@ -63,6 +61,5 @@ ruby_version_is "2.7.3" do
a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]]
end
-
end
end
diff --git a/spec/ruby/language/file_spec.rb b/spec/ruby/language/file_spec.rb
index 729dee1008..136b262d07 100644
--- a/spec/ruby/language/file_spec.rb
+++ b/spec/ruby/language/file_spec.rb
@@ -12,18 +12,10 @@ describe "The __FILE__ pseudo-variable" do
end
end
-describe "The __FILE__ pseudo-variable" do
- it_behaves_like :language___FILE__, :require, CodeLoadingSpecs::Method.new
-end
-
-describe "The __FILE__ pseudo-variable" do
+describe "The __FILE__ pseudo-variable with require" do
it_behaves_like :language___FILE__, :require, Kernel
end
-describe "The __FILE__ pseudo-variable" do
- it_behaves_like :language___FILE__, :load, CodeLoadingSpecs::Method.new
-end
-
-describe "The __FILE__ pseudo-variable" do
+describe "The __FILE__ pseudo-variable with load" do
it_behaves_like :language___FILE__, :load, Kernel
end
diff --git a/spec/ruby/language/fixtures/defined.rb b/spec/ruby/language/fixtures/defined.rb
index 8b6004c19f..a9552619bf 100644
--- a/spec/ruby/language/fixtures/defined.rb
+++ b/spec/ruby/language/fixtures/defined.rb
@@ -19,6 +19,9 @@ module DefinedSpecs
DefinedSpecs
end
+ def self.any_args(*)
+ end
+
class Basic
A = 42
diff --git a/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb b/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb
index a4d655ad02..cccc5969bd 100644
--- a/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb
+++ b/spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb
@@ -1,3 +1,3 @@
# frozen_string_literal: true
-p "abc".object_id == "abc".object_id
+p "abc".equal?("abc")
diff --git a/spec/ruby/language/hash_spec.rb b/spec/ruby/language/hash_spec.rb
index f99ff8ab3f..c84564d3ea 100644
--- a/spec/ruby/language/hash_spec.rb
+++ b/spec/ruby/language/hash_spec.rb
@@ -148,18 +148,9 @@ describe "Hash literal" do
{a: 1, **obj, c: 3}.should == {a:1, b: 2, c: 3, d: 4}
end
- ruby_version_is ""..."2.7" do
- it "raises a TypeError if any splatted elements keys are not symbols" do
- h = {1 => 2, b: 3}
- -> { {a: 1, **h} }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is "2.7" do
- it "allows splatted elements keys that are not symbols" do
- h = {1 => 2, b: 3}
- {a: 1, **h}.should == {a: 1, 1 => 2, b: 3}
- end
+ it "allows splatted elements keys that are not symbols" do
+ h = {1 => 2, b: 3}
+ {a: 1, **h}.should == {a: 1, 1 => 2, b: 3}
end
it "raises a TypeError if #to_hash does not return a Hash" do
@@ -225,4 +216,43 @@ describe "The ** operator" do
h.should == { two: 2 }
end
end
+
+ ruby_version_is "3.1" do
+ describe "hash with omitted value" do
+ it "accepts short notation 'key' for 'key: value' syntax" do
+ a, b, c = 1, 2, 3
+ h = eval('{a:}')
+ {a: 1}.should == h
+ h = eval('{a:, b:, c:}')
+ {a: 1, b: 2, c: 3}.should == h
+ end
+
+ it "ignores hanging comma on short notation" do
+ a, b, c = 1, 2, 3
+ h = eval('{a:, b:, c:,}')
+ {a: 1, b: 2, c: 3}.should == h
+ end
+
+ it "accepts mixed syntax" do
+ a, e = 1, 5
+ h = eval('{a:, b: 2, "c" => 3, :d => 4, e:}')
+ eval('{a: 1, :b => 2, "c" => 3, "d": 4, e: 5}').should == h
+ end
+
+ it "works with methods and local vars" do
+ a = Class.new
+ a.class_eval(<<-RUBY)
+ def bar
+ "baz"
+ end
+
+ def foo(val)
+ {bar:, val:}
+ end
+ RUBY
+
+ a.new.foo(1).should == {bar: "baz", val: 1}
+ end
+ end
+ end
end
diff --git a/spec/ruby/language/heredoc_spec.rb b/spec/ruby/language/heredoc_spec.rb
index 61a27ad8e0..b3b160fd11 100644
--- a/spec/ruby/language/heredoc_spec.rb
+++ b/spec/ruby/language/heredoc_spec.rb
@@ -59,20 +59,10 @@ 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
+ 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
it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do
diff --git a/spec/ruby/language/keyword_arguments_spec.rb b/spec/ruby/language/keyword_arguments_spec.rb
new file mode 100644
index 0000000000..c47b7b0ae9
--- /dev/null
+++ b/spec/ruby/language/keyword_arguments_spec.rb
@@ -0,0 +1,397 @@
+require_relative '../spec_helper'
+
+ruby_version_is "3.0" do
+ describe "Keyword arguments" do
+ def target(*args, **kwargs)
+ [args, kwargs]
+ end
+
+ it "are separated from positional arguments" do
+ def m(*args, **kwargs)
+ [args, kwargs]
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+ end
+
+ it "when the receiving method has not keyword parameters it treats kwargs as positional" do
+ def m(*a)
+ a
+ end
+
+ m(a: 1).should == [{a: 1}]
+ m({a: 1}).should == [{a: 1}]
+ end
+
+ context "empty kwargs are treated as if they were not passed" do
+ it "when calling a method" do
+ def m(*a)
+ a
+ end
+
+ empty = {}
+ m(**empty).should == []
+ m(empty).should == [{}]
+ end
+
+ it "when yielding to a block" do
+ def y(*args, **kwargs)
+ yield(*args, **kwargs)
+ end
+
+ empty = {}
+ y(**empty) { |*a| a }.should == []
+ y(empty) { |*a| a }.should == [{}]
+ end
+ end
+
+ it "extra keywords are not allowed without **kwrest" do
+ def m(*a, kw:)
+ a
+ end
+
+ m(kw: 1).should == []
+ -> { m(kw: 1, kw2: 2) }.should raise_error(ArgumentError, 'unknown keyword: :kw2')
+ -> { m(kw: 1, true => false) }.should raise_error(ArgumentError, 'unknown keyword: true')
+ -> { m(kw: 1, a: 1, b: 2, c: 3) }.should raise_error(ArgumentError, 'unknown keywords: :a, :b, :c')
+ end
+
+ it "raises ArgumentError exception when required keyword argument is not passed" do
+ def m(a:, b:, c:)
+ [a, b, c]
+ end
+
+ -> { m(a: 1, b: 2) }.should raise_error(ArgumentError, /missing keyword: :c/)
+ -> { m() }.should raise_error(ArgumentError, /missing keywords: :a, :b, :c/)
+ end
+
+ it "raises ArgumentError for missing keyword arguments even if there are extra ones" do
+ def m(a:)
+ a
+ end
+
+ -> { m(b: 1) }.should raise_error(ArgumentError, /missing keyword: :a/)
+ end
+
+ it "handle * and ** at the same call site" do
+ def m(*a)
+ a
+ end
+
+ m(*[], **{}).should == []
+ m(*[], 42, **{}).should == [42]
+ end
+
+ context "**" do
+ it "does not copy a non-empty Hash for a method taking (*args)" do
+ def m(*args)
+ args[0]
+ end
+
+ h = {a: 1}
+ m(**h).should.equal?(h)
+ end
+
+ it "copies the given Hash for a method taking (**kwargs)" do
+ def m(**kw)
+ kw
+ end
+
+ empty = {}
+ m(**empty).should == empty
+ m(**empty).should_not.equal?(empty)
+
+ h = {a: 1}
+ m(**h).should == h
+ m(**h).should_not.equal?(h)
+ end
+ end
+
+ context "delegation" do
+ it "works with (*args, **kwargs)" do
+ def m(*args, **kwargs)
+ target(*args, **kwargs)
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+ end
+
+ it "works with proc { |*args, **kwargs| }" do
+ m = proc do |*args, **kwargs|
+ target(*args, **kwargs)
+ end
+
+ empty = {}
+ m.(**empty).should == [[], {}]
+ m.(empty).should == [[{}], {}]
+
+ m.(a: 1).should == [[], {a: 1}]
+ m.({a: 1}).should == [[{a: 1}], {}]
+
+ # no autosplatting for |*args, **kwargs|
+ m.([1, 2]).should == [[[1, 2]], {}]
+ end
+
+ it "works with -> (*args, **kwargs) {}" do
+ m = -> *args, **kwargs do
+ target(*args, **kwargs)
+ end
+
+ empty = {}
+ m.(**empty).should == [[], {}]
+ m.(empty).should == [[{}], {}]
+
+ m.(a: 1).should == [[], {a: 1}]
+ m.({a: 1}).should == [[{a: 1}], {}]
+ end
+
+ it "works with (...)" do
+ instance_eval <<~DEF
+ def m(...)
+ target(...)
+ end
+ DEF
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+ end
+
+ it "works with call(*ruby2_keyword_args)" do
+ class << self
+ ruby2_keywords def m(*args)
+ target(*args)
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+ m(empty).should == [[{}], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+
+ kw = {a: 1}
+
+ m(**kw).should == [[], {a: 1}]
+ m(**kw)[1].should == kw
+ m(**kw)[1].should_not.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false
+
+ m(kw).should == [[{a: 1}], {}]
+ m(kw)[0][0].should.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ end
+
+ it "works with super(*ruby2_keyword_args)" do
+ parent = Class.new do
+ def m(*args, **kwargs)
+ [args, kwargs]
+ end
+ end
+
+ child = Class.new(parent) do
+ ruby2_keywords def m(*args)
+ super(*args)
+ end
+ end
+
+ obj = child.new
+
+ empty = {}
+ obj.m(**empty).should == [[], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+ obj.m(empty).should == [[{}], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+
+ obj.m(a: 1).should == [[], {a: 1}]
+ obj.m({a: 1}).should == [[{a: 1}], {}]
+
+ kw = {a: 1}
+
+ obj.m(**kw).should == [[], {a: 1}]
+ obj.m(**kw)[1].should == kw
+ obj.m(**kw)[1].should_not.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ Hash.ruby2_keywords_hash?(obj.m(**kw)[1]).should == false
+
+ obj.m(kw).should == [[{a: 1}], {}]
+ obj.m(kw)[0][0].should.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ end
+
+ it "works with zsuper" do
+ parent = Class.new do
+ def m(*args, **kwargs)
+ [args, kwargs]
+ end
+ end
+
+ child = Class.new(parent) do
+ ruby2_keywords def m(*args)
+ super
+ end
+ end
+
+ obj = child.new
+
+ empty = {}
+ obj.m(**empty).should == [[], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+ obj.m(empty).should == [[{}], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+
+ obj.m(a: 1).should == [[], {a: 1}]
+ obj.m({a: 1}).should == [[{a: 1}], {}]
+
+ kw = {a: 1}
+
+ obj.m(**kw).should == [[], {a: 1}]
+ obj.m(**kw)[1].should == kw
+ obj.m(**kw)[1].should_not.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ Hash.ruby2_keywords_hash?(obj.m(**kw)[1]).should == false
+
+ obj.m(kw).should == [[{a: 1}], {}]
+ obj.m(kw)[0][0].should.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ end
+
+ it "works with yield(*ruby2_keyword_args)" do
+ class << self
+ def y(args)
+ yield(*args)
+ end
+
+ ruby2_keywords def m(*outer_args)
+ y(outer_args, &-> *args, **kwargs { target(*args, **kwargs) })
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+ m(empty).should == [[{}], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+
+ kw = {a: 1}
+
+ m(**kw).should == [[], {a: 1}]
+ m(**kw)[1].should == kw
+ m(**kw)[1].should_not.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false
+
+ m(kw).should == [[{a: 1}], {}]
+ m(kw)[0][0].should.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ end
+
+ it "does not work with (*args)" do
+ class << self
+ def m(*args)
+ target(*args)
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
+
+ m(a: 1).should == [[{a: 1}], {}]
+ m({a: 1}).should == [[{a: 1}], {}]
+ end
+
+ ruby_version_is "3.1" do
+ describe "omitted values" do
+ it "accepts short notation 'key' for 'key: value' syntax" do
+ def m(a:, b:)
+ [a, b]
+ end
+
+ a = 1
+ b = 2
+
+ eval('m(a:, b:).should == [1, 2]')
+ end
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "does not work with call(*ruby2_keyword_args) with missing ruby2_keywords in between" do
+ class << self
+ def n(*args) # Note the missing ruby2_keywords here
+ target(*args)
+ end
+
+ ruby2_keywords def m(*args)
+ n(*args)
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
+
+ m(a: 1).should == [[{a: 1}], {}]
+ m({a: 1}).should == [[{a: 1}], {}]
+ end
+ end
+
+ ruby_version_is ""..."3.2" do
+ # https://bugs.ruby-lang.org/issues/18625
+ it "works with call(*ruby2_keyword_args) with missing ruby2_keywords in between due to CRuby bug #18625" do
+ class << self
+ def n(*args) # Note the missing ruby2_keywords here
+ target(*args)
+ end
+
+ ruby2_keywords def m(*args)
+ n(*args)
+ end
+ end
+
+ empty = {}
+ m(**empty).should == [[], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+ m(empty).should == [[{}], {}]
+ Hash.ruby2_keywords_hash?(empty).should == false
+
+ m(a: 1).should == [[], {a: 1}]
+ m({a: 1}).should == [[{a: 1}], {}]
+
+ kw = {a: 1}
+
+ m(**kw).should == [[], {a: 1}]
+ m(**kw)[1].should == kw
+ m(**kw)[1].should_not.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false
+
+ m(kw).should == [[{a: 1}], {}]
+ m(kw)[0][0].should.equal?(kw)
+ Hash.ruby2_keywords_hash?(kw).should == false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/language/lambda_spec.rb b/spec/ruby/language/lambda_spec.rb
index 6393fb5c47..a3f01ec04b 100644
--- a/spec/ruby/language/lambda_spec.rb
+++ b/spec/ruby/language/lambda_spec.rb
@@ -281,38 +281,18 @@ describe "A lambda literal -> () { }" do
end
describe "with circular optional argument reference" do
- ruby_version_is ''...'2.7' do
- it "warns and uses a nil value when there is an existing local variable with same name" do
- a = 1
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
-
- it "warns and uses a nil value when there is an existing method with same name" do
- def a; 1; end
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should complain(/circular argument reference/)
- @proc.call.should == nil
- end
+ it "raises a SyntaxError if using an existing local with the same name as the argument" do
+ a = 1
+ -> {
+ @proc = eval "-> (a=a) { a }"
+ }.should raise_error(SyntaxError)
end
- ruby_version_is '2.7' do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should raise_error(SyntaxError)
- end
-
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should raise_error(SyntaxError)
- end
+ it "raises a SyntaxError if there is an existing method with the same name as the argument" do
+ def a; 1; end
+ -> {
+ @proc = eval "-> (a=a) { a }"
+ }.should raise_error(SyntaxError)
end
it "calls an existing method with the same name as the argument if explicitly using ()" do
@@ -360,26 +340,12 @@ describe "A lambda expression 'lambda { ... }'" do
def meth; lambda; end
end
- ruby_version_is ""..."2.7" do
- it "can be created" do
- implicit_lambda = nil
+ it "raises ArgumentError" do
+ implicit_lambda = nil
+ suppress_warning do
-> {
- implicit_lambda = meth { 1 }
- }.should complain(/tried to create Proc object without a block/)
-
- implicit_lambda.lambda?.should be_true
- implicit_lambda.call.should == 1
- end
- end
-
- ruby_version_is "2.7" do
- it "raises ArgumentError" do
- implicit_lambda = nil
- suppress_warning do
- -> {
- meth { 1 }
- }.should raise_error(ArgumentError, /tried to create Proc object without a block/)
- end
+ meth { 1 }
+ }.should raise_error(ArgumentError, /tried to create Proc object without a block/)
end
end
end
diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb
index 449d5e6f1b..b80b314f6f 100644
--- a/spec/ruby/language/method_spec.rb
+++ b/spec/ruby/language/method_spec.rb
@@ -572,6 +572,13 @@ describe "A method" do
end
evaluate <<-ruby do
+ def m(a:, **kw) [a, kw] end
+ ruby
+
+ -> { m(b: 1) }.should raise_error(ArgumentError)
+ end
+
+ evaluate <<-ruby do
def m(a: 1) a end
ruby
@@ -602,13 +609,11 @@ describe "A method" do
-> { m(2) }.should raise_error(ArgumentError)
end
- ruby_version_is "2.7" do
- evaluate <<-ruby do
- def m(**k); k end;
- ruby
+ evaluate <<-ruby do
+ def m(**k); k end;
+ ruby
- m("a" => 1).should == { "a" => 1 }
- end
+ m("a" => 1).should == { "a" => 1 }
end
evaluate <<-ruby do
@@ -962,26 +967,13 @@ describe "A method" do
end
end
- ruby_version_is ""..."2.7" do
- evaluate <<-ruby do
- def m(a=1, **) a end
- ruby
-
- m().should == 1
- m(2, a: 1, b: 0).should == 2
- m("a" => 1, a: 2).should == {"a" => 1}
- end
- end
-
- ruby_version_is "2.7" do
- evaluate <<-ruby do
- def m(a=1, **) a end
- ruby
+ evaluate <<-ruby do
+ def m(a=1, **) a end
+ ruby
- m().should == 1
- m(2, a: 1, b: 0).should == 2
- m("a" => 1, a: 2).should == 1
- end
+ m().should == 1
+ m(2, a: 1, b: 0).should == 2
+ m("a" => 1, a: 2).should == 1
end
evaluate <<-ruby do
@@ -1021,164 +1013,7 @@ describe "A method" do
m(1, 2, 3).should == [[1, 2], 3]
end
- 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
- 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(*, **) 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
-
- 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")
- error = RuntimeError.new("error while converting to a hash")
- h.should_receive(:to_hash).and_raise(error)
- -> { m(h) }.should raise_error(error)
- 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 == [{"a" => 1}]
- 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}
-
- h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({a: 1})
- m(h).should == {a: 1}
- end
-
- evaluate <<-ruby do
- def m(a = nil, **k) [a, k] end
- ruby
-
- m().should == [nil, {}]
- m("a" => 1).should == [{"a" => 1}, {}]
- m(a: 1).should == [nil, {a: 1}]
- m("a" => 1, a: 1).should == [{"a" => 1}, {a: 1}]
- m({ "a" => 1 }, a: 1).should == [{"a" => 1}, {a: 1}]
- m({a: 1}, {}).should == [{a: 1}, {}]
-
- h = {"a" => 1, b: 2}
- m(h).should == [{"a" => 1}, {b: 2}]
- h.should == {"a" => 1, b: 2}
-
- h = {"a" => 1}
- m(h).first.should == h
-
- h = {}
- r = m(h)
- r.first.should be_nil
- r.last.should == {}
-
- hh = {}
- h = mock("keyword splat empty hash")
- h.should_receive(:to_hash).and_return(hh)
- r = m(h)
- r.first.should be_nil
- r.last.should == {}
-
- h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({"a" => 1, a: 2})
- m(h).should == [{"a" => 1}, {a: 2}]
- 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}]
- m({a: 1}, {}).should == [[{a: 1}], {}]
- 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
-
- ruby_version_is "2.7"...'3.0' do
+ ruby_version_is ""...'3.0' do
evaluate <<-ruby do
def m(*, a:) a end
ruby
@@ -1503,44 +1338,22 @@ describe "A method" do
end
end
- ruby_version_is ''...'2.7' do
- evaluate <<-ruby do
- def m(a:, **) a end
- ruby
-
- m(a: 1).should == 1
- m(a: 1, b: 2).should == 1
- -> { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError)
- end
-
- evaluate <<-ruby do
- def m(a:, **k) [a, k] end
- ruby
+ evaluate <<-ruby do
+ def m(a:, **) a end
+ ruby
- m(a: 1).should == [1, {}]
- m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
- -> { m("a" => 1, a: 1, b: 2) }.should raise_error(ArgumentError)
- end
+ m(a: 1).should == 1
+ m(a: 1, b: 2).should == 1
+ m("a" => 1, a: 1, b: 2).should == 1
end
- ruby_version_is '2.7' do
- evaluate <<-ruby do
- def m(a:, **) a end
- ruby
-
- m(a: 1).should == 1
- m(a: 1, b: 2).should == 1
- m("a" => 1, a: 1, b: 2).should == 1
- end
-
- evaluate <<-ruby do
- def m(a:, **k) [a, k] end
- ruby
+ evaluate <<-ruby do
+ def m(a:, **k) [a, k] end
+ ruby
- m(a: 1).should == [1, {}]
- m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
- m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}]
- end
+ m(a: 1).should == [1, {}]
+ m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
+ m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}]
end
evaluate <<-ruby do
@@ -1637,18 +1450,16 @@ describe "A method" do
result.should == [1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l]
end
- ruby_version_is "2.7" do
- evaluate <<-ruby do
- def m(a, **nil); a end;
- ruby
+ 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 == {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
+ -> { m(a: 1) }.should raise_error(ArgumentError)
+ -> { m(**{a: 1}) }.should raise_error(ArgumentError)
+ -> { m("a" => 1) }.should raise_error(ArgumentError)
end
ruby_version_is ''...'3.0' do
@@ -1690,19 +1501,17 @@ describe "A method" do
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
+ 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
+ h = {}
+ m(**h).should == []
end
end
- ruby_version_is '2.7'...'3.0' do
+ 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
@@ -1861,15 +1670,187 @@ describe "An array-dereference method ([])" do
end
end
-ruby_version_is '3.0' do
+ruby_version_is "3.0" do
describe "An endless method definition" do
- evaluate <<-ruby do
- def m(a) = a
- ruby
+ context "without arguments" do
+ evaluate <<-ruby do
+ def m() = 42
+ ruby
+
+ m.should == 42
+ end
+
+ context "without parenthesis" do
+ evaluate <<-ruby do
+ def m = 42
+ ruby
+
+ m.should == 42
+ end
+ end
+ end
+
+ context "with arguments" do
+ evaluate <<-ruby do
+ def m(a, b) = a + b
+ ruby
+
+ m(1, 4).should == 5
+ end
+ end
+
+ context "with multiline body" do
+ evaluate <<-ruby do
+ def m(n) =
+ if n > 2
+ m(n - 2) + m(n - 1)
+ else
+ 1
+ end
+ ruby
+
+ m(6).should == 8
+ end
+ end
+
+ context "with args forwarding" do
+ evaluate <<-ruby do
+ def mm(word, num:)
+ word * num
+ end
+
+ def m(...) = mm(...) + mm(...)
+ ruby
+
+ m("meow", num: 2).should == "meow" * 4
+ end
+ end
+
+ ruby_version_is ""..."3.0" do
+ context "inside 'endless' method definitions" do
+ it "does not allow method calls without parenthesis" do
+ -> {
+ eval("def greet(person) = 'Hi, '.concat person")
+ }.should raise_error(SyntaxError)
+ end
+ end
+ end
+ end
+
+ describe "Keyword arguments are now separated from positional arguments" do
+ context "when the method has only positional parameters" do
+ it "treats incoming keyword arguments as positional for compatibility" do
+ def foo(a, b, c, hsh)
+ hsh[:key]
+ end
+
+ foo(1, 2, 3, key: 42).should == 42
+ end
+ end
+
+ context "when the method takes a ** parameter" do
+ it "captures the passed literal keyword arguments" do
+ def foo(a, b, c, **hsh)
+ hsh[:key]
+ end
+
+ foo(1, 2, 3, key: 42).should == 42
+ end
+
+ it "captures the passed ** keyword arguments" do
+ def foo(a, b, c, **hsh)
+ hsh[:key]
+ end
+
+ h = { key: 42 }
+ foo(1, 2, 3, **h).should == 42
+ end
+
+ it "does not convert a positional Hash to keyword arguments" do
+ def foo(a, b, c, **hsh)
+ hsh[:key]
+ end
+
+ -> {
+ foo(1, 2, 3, { key: 42 })
+ }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)')
+ end
+ end
+
+ context "when the method takes a key: parameter" do
+ context "when it's called with a positional Hash and no **" do
+ it "raises ArgumentError" do
+ def foo(a, b, c, key: 1)
+ key
+ end
+
+ -> {
+ foo(1, 2, 3, { key: 42 })
+ }.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)')
+ end
+ end
+
+ context "when it's called with **" do
+ it "captures the passed keyword arguments" do
+ def foo(a, b, c, key: 1)
+ key
+ end
+
+ h = { key: 42 }
+ foo(1, 2, 3, **h).should == 42
+ end
+ end
+ end
+ end
+end
+
+ruby_version_is "3.1" do
+ describe "kwarg with omitted value in a method call" do
+ context "accepts short notation 'kwarg' in method call" do
+ evaluate <<-ruby do
+ def call(*args, **kwargs) = [args, kwargs]
+ ruby
+
+ a, b, c = 1, 2, 3
+ arr, h = eval('call a:')
+ h.should == {a: 1}
+ arr.should == []
+
+ arr, h = eval('call(a:, b:, c:)')
+ h.should == {a: 1, b: 2, c: 3}
+ arr.should == []
+
+ arr, h = eval('call(a:, b: 10, c:)')
+ h.should == {a: 1, b: 10, c: 3}
+ arr.should == []
+ end
+ end
+
+ context "with methods and local variables" do
+ evaluate <<-ruby do
+ def call(*args, **kwargs) = [args, kwargs]
+
+ def bar
+ "baz"
+ end
+
+ def foo(val)
+ call bar:, val:
+ end
+ ruby
+
+ foo(1).should == [[], {bar: "baz", val: 1}]
+ end
+ end
+ end
+
+ describe "Inside 'endless' method definitions" do
+ it "allows method calls without parenthesis" do
+ eval <<-ruby
+ def greet(person) = "Hi, ".concat person
+ ruby
- a = b = m 1
- a.should == 1
- b.should == 1
+ greet("Homer").should == "Hi, Homer"
end
end
end
diff --git a/spec/ruby/language/module_spec.rb b/spec/ruby/language/module_spec.rb
index 1a5fcaf46f..e361bf58f5 100644
--- a/spec/ruby/language/module_spec.rb
+++ b/spec/ruby/language/module_spec.rb
@@ -28,9 +28,18 @@ describe "The module keyword" do
ModuleSpecs::Reopened.should be_true
end
- it "reopens a module included in Object" do
- module IncludedModuleSpecs; Reopened = true; end
- ModuleSpecs::IncludedInObject::IncludedModuleSpecs::Reopened.should be_true
+ ruby_version_is '3.2' do
+ it "does not reopen a module included in Object" do
+ module IncludedModuleSpecs; Reopened = true; end
+ ModuleSpecs::IncludedInObject::IncludedModuleSpecs.should_not == Object::IncludedModuleSpecs
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it "reopens a module included in Object" do
+ module IncludedModuleSpecs; Reopened = true; end
+ ModuleSpecs::IncludedInObject::IncludedModuleSpecs::Reopened.should be_true
+ end
end
it "raises a TypeError if the constant is a Class" do
diff --git a/spec/ruby/language/numbered_parameters_spec.rb b/spec/ruby/language/numbered_parameters_spec.rb
index cd1ddf4555..424d7a06e3 100644
--- a/spec/ruby/language/numbered_parameters_spec.rb
+++ b/spec/ruby/language/numbered_parameters_spec.rb
@@ -1,106 +1,118 @@
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
+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 "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 "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]
+ it "can not be used in both outer and nested blocks at the same time" do
+ -> {
+ eval("-> { _1; -> { _2 } }")
+ }.should raise_error(SyntaxError, /numbered parameter is already used in/m)
+ end
+
+ ruby_version_is ''...'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 "does not support more than 9 parameters" do
+ it "warns when numbered parameter is overwritten with local variable" do
-> {
- proc { [_10] }.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
- }.should raise_error(NameError, /undefined local variable or method `_10'/)
+ eval("_1 = 0")
+ }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
end
+ end
- it "can not be used in both outer and nested blocks at the same time" do
+ ruby_version_is '3.0' do
+ it "cannot be overwritten with local variable" do
-> {
- eval("-> { _1; -> { _2 } }")
- }.should raise_error(SyntaxError, /numbered parameter is already used in/m)
+ eval <<~CODE
+ _1 = 0
+ proc { _1 }.call("a").should == 0
+ CODE
+ }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
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
+ 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
- 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/)
- 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("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("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
- -> { 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/)
+ describe "assigning to a numbered parameter" do
+ ruby_version_is ''...'3.0' do
+ it "warns" do
+ -> { eval("proc { _1 = 0 }") }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
+ end
end
- it "affects block arity" do
- -> { _1 }.arity.should == 1
- -> { _2 }.arity.should == 2
- -> { _3 }.arity.should == 3
- -> { _4 }.arity.should == 4
- -> { _5 }.arity.should == 5
- -> { _6 }.arity.should == 6
- -> { _7 }.arity.should == 7
- -> { _8 }.arity.should == 8
- -> { _9 }.arity.should == 9
-
- -> { _9 }.arity.should == 9
- proc { _9 }.arity.should == 9
- lambda { _9 }.arity.should == 9
+ ruby_version_is '3.0' do
+ it "raises SyntaxError" do
+ -> { eval("proc { _1 = 0 }") }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
+ end
end
+ end
- it "does not work in methods" do
- obj = Object.new
- def obj.foo; _1 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
- -> { obj.foo("a") }.should raise_error(ArgumentError, /wrong number of arguments/)
- 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
diff --git a/spec/ruby/language/numbers_spec.rb b/spec/ruby/language/numbers_spec.rb
index 2d8e19c40a..a8e023efb6 100644
--- a/spec/ruby/language/numbers_spec.rb
+++ b/spec/ruby/language/numbers_spec.rb
@@ -53,7 +53,7 @@ describe "A number literal" do
eval('0.0174532925199432957r').should == Rational(174532925199432957, 10000000000000000000)
end
- it "can be an bignum literal with trailing 'r' to represent a Rational" do
+ it "can be a bignum literal with trailing 'r' to represent a Rational" do
eval('1111111111111111111111111111111111111111111111r').should == Rational(1111111111111111111111111111111111111111111111, 1)
eval('-1111111111111111111111111111111111111111111111r').should == Rational(-1111111111111111111111111111111111111111111111, 1)
end
diff --git a/spec/ruby/language/optional_assignments_spec.rb b/spec/ruby/language/optional_assignments_spec.rb
index 217dcab74b..02461655d6 100644
--- a/spec/ruby/language/optional_assignments_spec.rb
+++ b/spec/ruby/language/optional_assignments_spec.rb
@@ -300,6 +300,44 @@ describe 'Optional variable assignments' do
(@b[:k] ||= 12).should == 12
end
+ it 'correctly handles a splatted argument for the index' do
+ (@b[*[:k]] ||= 12).should == 12
+ end
+
+ it "evaluates the index precisely once" do
+ ary = [:x, :y]
+ @a[:x] = 15
+ @a[ary.pop] ||= 25
+ ary.should == [:x]
+ @a.should == { x: 15, y: 25 }
+ end
+
+ it "evaluates the index arguments in the correct order" do
+ ary = Class.new(Array) do
+ def [](x, y)
+ super(x + 3 * y)
+ end
+
+ def []=(x, y, value)
+ super(x + 3 * y, value)
+ end
+ end.new
+ ary[0, 0] = 1
+ ary[1, 0] = 1
+ ary[2, 0] = nil
+ ary[3, 0] = 1
+ ary[4, 0] = 1
+ ary[5, 0] = 1
+ ary[6, 0] = nil
+
+ foo = [0, 2]
+
+ ary[foo.pop, foo.pop] ||= 2
+
+ ary[2, 0].should == 2
+ ary[6, 0].should == nil
+ end
+
it 'returns the assigned value, not the result of the []= method with +=' do
@b[:k] = 17
(@b[:k] += 12).should == 29
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
index 4e9d42b257..f3cc86fa0b 100644
--- a/spec/ruby/language/pattern_matching_spec.rb
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -1,115 +1,356 @@
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
+describe "Pattern matching" do
+ # TODO: Remove excessive eval calls when Ruby 3 is the minimum version.
+ # It is best to keep the eval's longer if other Ruby impls cannot parse pattern matching yet.
+ before :each do
+ ScratchPad.record []
+ end
+
+ ruby_version_is "3.0" do
+ it "can be standalone assoc operator that deconstructs value" do
+ suppress_warning do
+ eval(<<-RUBY).should == [0, 1]
+ [0, 1] => [a, b]
+ [a, b]
+ RUBY
+ end
+ end
+
+ describe "find pattern" do
+ it "captures preceding elements to the pattern" do
+ eval(<<~RUBY).should == [0, 1]
+ case [0, 1, 2, 3]
+ in [*pre, 2, 3]
+ pre
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "captures following elements to the pattern" do
+ eval(<<~RUBY).should == [2, 3]
+ case [0, 1, 2, 3]
+ in [0, 1, *post]
+ post
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "captures both preceding and following elements to the pattern" do
+ eval(<<~RUBY).should == [[0, 1], [3, 4]]
+ case [0, 1, 2, 3, 4]
+ in [*pre, 2, *post]
+ [pre, post]
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can capture the entirety of the pattern" do
+ eval(<<~RUBY).should == [0, 1, 2, 3, 4]
+ case [0, 1, 2, 3, 4]
+ in [*everything]
+ everything
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "will match an empty Array-like structure" do
+ eval(<<~RUBY).should == []
+ case []
+ in [*everything]
+ everything
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can be nested" do
+ eval(<<~RUBY).should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [*pre, [*, 9, a], *post]
+ [pre, post, a]
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can be nested with an array pattern" do
+ eval(<<~RUBY).should == [[4, 16, 64]]
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [_, _, [*, 9, *], *post]
+ post
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can be nested within a hash pattern" do
+ eval(<<~RUBY).should == [27]
+ case {a: [3, 9, 27]}
+ in {a: [*, 9, *post]}
+ post
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can nest hash and array patterns" do
+ eval(<<~RUBY).should == [42, 2]
+ case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
+ in [*, {a:, b: [1, c]}, *]
+ [a, c]
+ else
+ false
+ end
+ RUBY
+ end
+ end
+ end
+
+ it "extends case expression with case/in construction" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ end
+ RUBY
+ end
+
+ it "allows using then operator" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0] then :foo
+ in [0, 1] then :bar
+ end
+ RUBY
+ end
+
+ describe "warning" do
before :each do
- ScratchPad.record []
+ @experimental, Warning[:experimental] = Warning[:experimental], true
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
+ after :each do
+ Warning[:experimental] = @experimental
+ end
+
+ context 'when regular form' do
+ before :each do
+ @src = 'case [0, 1]; in [a, b]; end'
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "warns about pattern matching is experimental feature" do
+ -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "does not warn about pattern matching is experimental feature" do
+ -> { eval @src }.should_not complain
end
end
end
- it "extends case expression with case/in construction" do
- eval(<<~RUBY).should == :bar
+ context 'when one-line form' do
+ ruby_version_is '3.0' do
+ before :each do
+ @src = '[0, 1] => [a, b]'
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "warns about pattern matching is experimental feature" do
+ -> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "does not warn about pattern matching is experimental feature" do
+ -> { eval @src }.should_not complain
+ end
+ end
+ end
+ end
+ end
+
+ it "binds variables" do
+ eval(<<~RUBY).should == 1
+ case [0, 1]
+ in [0, a]
+ a
+ end
+ RUBY
+ end
+
+ it "cannot mix in and when operators" do
+ -> {
+ eval <<~RUBY
+ case []
+ when 1 == 1
+ in []
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /syntax error, unexpected `in'/)
+
+ -> {
+ eval <<~RUBY
+ case []
+ in []
+ when 1 == 1
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /syntax error, unexpected `when'/)
+ end
+
+ it "checks patterns until the first matching" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ in [0, 1]
+ :baz
+ end
+ RUBY
+ end
+
+ it "executes else clause if no pattern matches" do
+ eval(<<~RUBY).should == false
+ case [0, 1]
+ in [0]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises NoMatchingPatternError if no pattern matches and no else clause" do
+ -> {
+ eval <<~RUBY
case [0, 1]
in [0]
- :foo
- in [0, 1]
- :bar
end
RUBY
- end
+ }.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+ end
- it "allows using then operator" do
- eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0] then :foo
- in [0, 1] then :bar
+ it "does not allow calculation or method calls in a pattern" do
+ -> {
+ eval <<~RUBY
+ case 0
+ in 1 + 1
+ true
end
RUBY
- end
+ }.should raise_error(SyntaxError, /unexpected/)
+ end
- describe "warning" do
- ruby_version_is ""..."3.1" do
- before :each do
- ruby_version_is ""..."3.0" do
- @src = 'case [0, 1]; in [a, b]; end'
- end
+ it "evaluates the case expression once for multiple patterns, caching the result" do
+ eval(<<~RUBY).should == true
+ case (ScratchPad << :foo; 1)
+ in 0
+ false
+ in 1
+ true
+ end
+ RUBY
- ruby_version_is "3.0" do
- @src = '[0, 1] => [a, b]'
- end
+ ScratchPad.recorded.should == [:foo]
+ end
- @experimental, Warning[:experimental] = Warning[:experimental], true
+ describe "guards" do
+ it "supports if guard" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 if false
+ true
+ else
+ false
end
+ RUBY
- after :each do
- Warning[:experimental] = @experimental
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 if true
+ true
+ else
+ false
end
+ RUBY
+ 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)
+ it "supports unless guard" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 unless true
+ true
+ else
+ false
end
- end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 unless false
+ true
+ else
+ false
+ end
+ RUBY
end
- it "binds variables" do
- eval(<<~RUBY).should == 1
+ it "makes bound variables visible in guard" do
+ eval(<<~RUBY).should == true
case [0, 1]
- in [0, a]
- a
+ in [a, 1] if a >= 0
+ true
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'/)
+ it "does not evaluate guard if pattern does not match" do
+ eval <<~RUBY
+ case 0
+ in 1 if (ScratchPad << :foo) || true
+ else
+ end
+ RUBY
- -> {
- eval <<~RUBY
- case []
- in []
- when 1 == 1
- end
- RUBY
- }.should raise_error(SyntaxError, /syntax error, unexpected `when'/)
+ ScratchPad.recorded.should == []
end
- it "checks patterns until the first matching" do
+ it "takes guards into account when there are several matching patterns" do
eval(<<~RUBY).should == :bar
- case [0, 1]
- in [0]
+ case 0
+ in 0 if false
:foo
- in [0, 1]
+ in 0 if true
:bar
- in [0, 1]
- :baz
end
RUBY
end
- it "executes else clause if no pattern matches" do
+ it "executes else clause if no guarded pattern matches" do
eval(<<~RUBY).should == false
- case [0, 1]
- in [0]
+ case 0
+ in 0 if false
true
else
false
@@ -117,1023 +358,1046 @@ ruby_version_is "2.7" do
RUBY
end
- it "raises NoMatchingPatternError if no pattern matches and no else clause" do
+ it "raises NoMatchingPatternError if no guarded pattern matches and no else clause" do
-> {
eval <<~RUBY
case [0, 1]
- in [0]
+ in [0, 1] if false
end
RUBY
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
end
+ end
- it "does not allow calculation or method calls in a pattern" do
- -> {
- eval <<~RUBY
- case 0
- in 1 + 1
- true
- end
- RUBY
- }.should raise_error(SyntaxError, /unexpected/)
- end
-
- it "evaluates the case expression once for multiple patterns, caching the result" do
+ describe "value pattern" do
+ it "matches an object such that pattern === object" do
eval(<<~RUBY).should == true
- case (ScratchPad << :foo; 1)
+ case 0
in 0
- false
- in 1
true
end
RUBY
- ScratchPad.recorded.should == [:foo]
- end
-
- describe "guards" do
- it "supports if guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 if false
- true
- else
- false
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case 0
- in 0 if true
- true
- else
- false
- end
- RUBY
- end
-
- it "supports unless guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 unless true
- true
- else
- false
- end
- RUBY
-
- eval(<<~RUBY).should == true
- case 0
- in 0 unless false
- true
- else
- false
- end
- RUBY
- end
-
- it "makes bound variables visible in guard" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in [a, 1] if a >= 0
- true
- end
- RUBY
- end
-
- it "does not evaluate guard if pattern does not match" do
- eval <<~RUBY
- case 0
- in 1 if (ScratchPad << :foo) || true
- else
- end
- RUBY
-
- ScratchPad.recorded.should == []
- end
+ eval(<<~RUBY).should == true
+ case 0
+ in (-1..1)
+ true
+ end
+ RUBY
- 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
+ eval(<<~RUBY).should == true
+ case 0
+ in Integer
+ true
+ end
+ RUBY
- 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
+ eval(<<~RUBY).should == true
+ case "0"
+ in /0/
+ true
+ end
+ RUBY
- 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
+ eval(<<~RUBY).should == true
+ case "0"
+ in ->(s) { s == "0" }
+ true
+ end
+ RUBY
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
+ it "allows string literal with interpolation" do
+ x = "x"
- 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 "x"
+ in "#{x + ""}"
+ true
+ end
+ RUBY
+ end
+ end
- eval(<<~RUBY).should == true
- case "0"
- in ->(s) { s == "0" }
- true
- end
- RUBY
- 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 "allows string literal with interpolation" do
- x = "x"
+ it "makes bounded variable visible outside a case statement scope" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in a
+ end
- eval(<<~RUBY).should == true
- case "x"
- in "#{x + ""}"
- true
- end
- RUBY
- end
+ a
+ RUBY
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 "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
- it "makes bounded variable visible outside a case statement scope" do
- eval(<<~RUBY).should == 0
- case 0
- in a
- end
+ [a, b, c]
+ RUBY
+ end
+ it "allow using _ name to drop values" do
+ eval(<<~RUBY).should == 0
+ case [0, 1]
+ in [a, _]
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
+ end
+ 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 _ 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
- 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
- eval(<<~RUBY).should == true
- case {a: 0, b: 1, c: 2}
- in {a: 0, b: _x, c: _x}
- true
+ it "does not support using variable name (except _) several times" do
+ -> {
+ eval <<~RUBY
+ case [0]
+ in [a, a]
end
RUBY
- end
+ }.should raise_error(SyntaxError, /duplicated variable name/)
+ 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
- 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
- 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
- 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
- eval(<<~RUBY).should == false
+ 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]
+ 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
+ }.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
+ 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 "support underscore prefixed variables in alternation" do
- eval(<<~RUBY).should == true
+ it "does not support variable binding" do
+ -> {
+ eval <<~RUBY
case [0, 1]
- in [1, _]
- false
- in [0, 0] | [0, _a]
- true
+ in [0, 0] | [0, a]
end
RUBY
- end
+ }.should raise_error(SyntaxError, /illegal variable in alternative pattern/)
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
+ 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
- describe "Array pattern" do
- it "supports form Constant(pat, pat, ...)" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array(0, 1, 2)
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == true
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
true
- end
- RUBY
- end
+ end
+ RUBY
- it "supports form Constant[pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array[0, 1, 2]
+ eval(<<~RUBY).should == true
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
true
- end
- RUBY
- end
+ end
+ RUBY
+ end
+ end
- it "supports form [pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, 1, 2]
- true
- end
- RUBY
- 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 "supports form pat, pat, ..." do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in 0, 1, 2
- true
- end
- RUBY
+ 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
- eval(<<~RUBY).should == 1
- case [0, 1, 2]
- in 0, a, 2
- a
- end
- RUBY
+ 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
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in 0, *rest
- rest
- 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 "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
+ it "supports form [pat, pat, ...]" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, 1, 2]
+ true
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in [Integer, Integer]
- 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
- ruby_version_is "3.0" do
- it "calls #deconstruct once for multiple patterns, caching the result" do
- obj = Object.new
+ eval(<<~RUBY).should == 1
+ case [0, 1, 2]
+ in 0, a, 2
+ a
+ end
+ RUBY
- def obj.deconstruct
- ScratchPad << :deconstruct
- [0, 1]
- end
+ eval(<<~RUBY).should == [1, 2]
+ case [0, 1, 2]
+ in 0, *rest
+ rest
+ end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
+ 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
- ScratchPad.recorded.should == [:deconstruct]
+ eval(<<~RUBY).should == true
+ case obj
+ in [Integer, Integer]
+ true
end
- end
+ RUBY
+ end
+
+ ruby_version_is "3.0" do
+ it "calls #deconstruct once for multiple patterns, caching the result" do
+ obj = Object.new
- it "calls #deconstruct even on objects that are already an array" do
- obj = [1, 2]
def obj.deconstruct
ScratchPad << :deconstruct
- [3, 4]
+ [0, 1]
end
eval(<<~RUBY).should == true
case obj
- in [3, 4]
- true
- else
+ in [1, 2]
false
+ in [0, 1]
+ true
end
RUBY
ScratchPad.recorded.should == [:deconstruct]
end
+ 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
+ it "calls #deconstruct even on objects that are already an array" do
+ obj = [1, 2]
+ def obj.deconstruct
+ ScratchPad << :deconstruct
+ [3, 4]
end
- it "does not match object without #deconstruct method" do
- obj = Object.new
- obj.should_receive(:respond_to?).with(:deconstruct)
+ eval(<<~RUBY).should == true
+ case obj
+ in [3, 4]
+ true
+ else
+ false
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:deconstruct]
+ end
+
+ it "does not match object if Constant === object returns false" do
+ eval(<<~RUBY).should == false
+ case [0, 1, 2]
+ in String[0, 1, 2]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does not match object without #deconstruct method" do
+ obj = Object.new
+ obj.should_receive(:respond_to?).with(:deconstruct)
+
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises TypeError if #deconstruct method does not return array" do
+ obj = Object.new
+ def obj.deconstruct; "" end
- eval(<<~RUBY).should == false
+ -> {
+ eval <<~RUBY
case obj
in Object[]
- true
else
- false
end
RUBY
- end
+ }.should raise_error(TypeError, /deconstruct must return Array/)
+ 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/)
+ it "accepts a subclass of Array from #deconstruct" do
+ obj = Object.new
+ def obj.deconstruct
+ subarray = Class.new(Array).new(2)
+ def subarray.[](n)
+ n
+ end
+ subarray
end
- it "accepts a subclass of Array from #deconstruct" do
- obj = Object.new
- def obj.deconstruct
- subarray = Class.new(Array).new(2)
- def subarray.[](n)
- n
- end
- subarray
+ eval(<<~RUBY).should == true
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
end
+ RUBY
+ end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
- end
+ it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do
+ obj = Object.new
+ def obj.deconstruct; [1] end
- 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
- 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 "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 "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 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
- 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
- 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 [] with []" do
- eval(<<~RUBY).should == true
- case []
- in []
+ it "matches anything with *" do
+ eval(<<~RUBY).should == true
+ case [0, 1]
+ in *;
+ true
+ end
+ RUBY
+ end
+
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == true
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
true
- end
- RUBY
- end
+ end
+ RUBY
- it "matches anything with *" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in *;
+ eval(<<~RUBY).should == true
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
true
- end
- RUBY
- end
+ 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
+ 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 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
+ 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
+ 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 == [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
+ 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
+ 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 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 = 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 = 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]
+ 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
- end
+ }.should raise_error(SyntaxError, /unexpected/)
+ 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]
+ it "does not support string interpolation in keys" do
+ x = "a"
+
+ -> {
+ eval <<~'RUBY'
+ case {a: 1}
+ in {"#{x}": 1}
end
RUBY
- end
+ }.should raise_error(SyntaxError, /symbol literal with interpolation is not allowed/)
+ end
- it "supports 'string': key literal" do
- eval(<<~RUBY).should == true
- case {a: 0}
- in {"a": 0}
- true
+ it "raise SyntaxError when keys duplicate in pattern" do
+ -> {
+ eval <<~RUBY
+ case {a: 1}
+ in {a: 1, b: 2, a: 3}
end
RUBY
- end
+ }.should raise_error(SyntaxError, /duplicated key name/)
+ 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 "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
- it "does not support string interpolation in keys" do
- x = "a"
+ eval(<<~RUBY).should == true
+ case obj
+ in {a: 1}
+ true
+ end
+ RUBY
+ end
- -> {
- eval <<~'RUBY'
- case {a: 1}
- in {"#{x}": 1}
- end
- RUBY
- }.should raise_error(SyntaxError, /symbol literal with interpolation is not allowed/)
- end
+ it "calls #deconstruct_keys per pattern" do
+ obj = Object.new
- 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/)
+ def obj.deconstruct_keys(*)
+ ScratchPad << :deconstruct_keys
+ {a: 1}
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 {b: 1}
+ false
+ in {a: 1}
+ true
+ end
+ RUBY
- eval(<<~RUBY).should == true
- case obj
- in {a: 1}
- true
- end
- RUBY
- end
+ ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys]
+ end
- it "calls #deconstruct_keys per pattern" do
- obj = Object.new
+ it "does not match object if Constant === object returns false" do
+ eval(<<~RUBY).should == false
+ case {a: 1}
+ in String[a: 1]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does not match object without #deconstruct_keys method" do
+ obj = Object.new
+ obj.should_receive(:respond_to?).with(:deconstruct_keys)
- def obj.deconstruct_keys(*)
- ScratchPad << :deconstruct_keys
- {a: 1}
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
end
+ RUBY
+ end
- eval(<<~RUBY).should == true
+ 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 {b: 1}
- false
- in {a: 1}
- true
+ in Object[a: 1]
end
RUBY
+ }.should raise_error(TypeError, /deconstruct_keys must return Hash/)
+ end
- ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys]
- 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
- 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
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end
+ RUBY
+ end
- it "does not match object without #deconstruct_keys method" do
- obj = Object.new
- obj.should_receive(:respond_to?).with(:deconstruct_keys)
+ 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: 1]
- true
- else
- false
- end
- RUBY
- end
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 2]
+ 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/)
+ 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
- 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
+ case obj
+ in Object[a: 1, b: 2, c: 3]
+ end
+ RUBY
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 1]
- true
- else
- false
- 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
- 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
+ case obj
+ in Object[a: 1, b: 2, **]
+ end
+ RUBY
- eval(<<~RUBY).should == false
- case obj
- in Object[a: 2]
- true
- else
- false
- 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
- it "passes keys specified in pattern as arguments to #deconstruct_keys method" do
- obj = Object.new
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, **rest]
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [[nil]]
+ end
- def obj.deconstruct_keys(*args)
- ScratchPad << args
- {a: 1, b: 2, c: 3}
+ 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
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, c: 3]
- end
- RUBY
+ 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
- ScratchPad.recorded.sort.should == [[[:a, :b, :c]]]
- 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
- it "passes keys specified in pattern to #deconstruct_keys method if pattern contains double splat operator **" do
- obj = Object.new
+ eval(<<~RUBY).should == false
+ case {a: 1, b: 2}
+ in {a: 1, **nil}
+ true
+ else
+ false
+ end
+ RUBY
+ end
- def obj.deconstruct_keys(*args)
- ScratchPad << args
- {a: 1, b: 2, c: 3}
+ it "can match partially" do
+ eval(<<~RUBY).should == true
+ case {a: 1, b: 2}
+ in {a: 1}
+ true
end
+ RUBY
+ end
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, **]
- end
- RUBY
+ it "matches {} with {}" do
+ eval(<<~RUBY).should == true
+ case {}
+ in {}
+ true
+ end
+ RUBY
+ end
- ScratchPad.recorded.sort.should == [[[:a, :b]]]
- end
+ it "matches anything with **" do
+ eval(<<~RUBY).should == true
+ case {a: 1}
+ in **;
+ true
+ end
+ RUBY
+ end
- it "passes nil to #deconstruct_keys method if pattern contains double splat operator **rest" do
- obj = Object.new
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == true
+ case {a: {a: 1, b: 1}, b: {a: 1, b: 2}}
+ in {a: {a: 0}}
+ false
+ in {a: {a: 1}, b: {b: 1}}
+ false
+ in {a: {a: 1}, b: {b: 2}}
+ true
+ end
+ RUBY
- def obj.deconstruct_keys(*args)
- ScratchPad << args
- {a: 1, b: 2}
+ eval(<<~RUBY).should == true
+ case [{a: 1, b: [1]}, {a: 1, c: ["2"]}]
+ in [{a:, c:},]
+ false
+ in [{a: 1, b:}, {a: 1, c: [Integer]}]
+ false
+ in [_, {a: 1, c: [String]}]
+ true
end
+ RUBY
+ end
+ end
- eval <<~RUBY
- case obj
- in Object[a: 1, **rest]
+ describe "refinements" do
+ it "are used for #deconstruct" do
+ refinery = Module.new do
+ refine Array do
+ def deconstruct
+ [0]
end
- RUBY
-
- ScratchPad.recorded.should == [[nil]]
+ end
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]
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case []
+ in [0]
+ true
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
+ result.should == true
+ end
+
+ it "are used for #deconstruct_keys" do
+ refinery = Module.new do
+ refine Hash do
+ def deconstruct_keys(_)
+ {a: 0}
end
- RUBY
+ end
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
+ result = nil
+ Module.new do
+ using refinery
- eval(<<~RUBY).should == false
- case {a: 1, b: 2}
- in {a: 1, **nil}
+ result = eval(<<~RUBY)
+ case {}
+ in a: 0
true
- else
- false
end
RUBY
end
- it "can match partially" do
- eval(<<~RUBY).should == true
- case {a: 1, b: 2}
- in {a: 1}
- true
+ 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
- RUBY
+ end
end
- it "matches {} with {}" do
- eval(<<~RUBY).should == true
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
case {}
- in {}
+ in Array
true
end
RUBY
end
- it "matches anything with **" do
- eval(<<~RUBY).should == true
- case {a: 1}
- in **;
- true
- end
- RUBY
- end
+ result.should == true
end
+ end
- describe "refinements" do
- it "are used for #deconstruct" do
- refinery = Module.new do
- refine Array do
- def deconstruct
- [0]
- end
- end
- end
+ ruby_version_is "3.1" do
+ it "can omit parentheses in one line pattern matching" do
+ eval(<<~RUBY).should == [1, 2]
+ [1, 2] => a, b
+ [a, b]
+ RUBY
- result = nil
- Module.new do
- using refinery
+ eval(<<~RUBY).should == 1
+ {a: 1} => a:
+ a
+ RUBY
+ end
- result = eval(<<~RUBY)
- case []
- in [0]
- true
- end
- RUBY
+ it "supports pinning instance variables" do
+ eval(<<~RUBY).should == true
+ @a = /a/
+ case 'abc'
+ in ^@a
+ true
end
+ RUBY
+ end
- result.should == true
- end
+ it "supports pinning class variables" do
+ result = nil
+ Module.new do
+ result = module_eval(<<~RUBY)
+ @@a = 0..10
- it "are used for #deconstruct_keys" do
- refinery = Module.new do
- refine Hash do
- def deconstruct_keys(_)
- {a: 0}
- end
+ case 2
+ in ^@@a
+ true
end
- end
+ RUBY
+ end
- result = nil
- Module.new do
- using refinery
+ result.should == true
+ end
- result = eval(<<~RUBY)
- case {}
- in a: 0
- true
- end
- RUBY
+ it "supports pinning global variables" do
+ eval(<<~RUBY).should == true
+ $a = /a/
+ case 'abc'
+ in ^$a
+ 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
+ it "supports pinning expressions" do
+ eval(<<~RUBY).should == true
+ case 'abc'
+ in ^(/a/)
+ true
end
+ RUBY
- result = nil
- Module.new do
- using refinery
-
- result = eval(<<~RUBY)
- case {}
- in Array
- true
- end
- RUBY
+ eval(<<~RUBY).should == true
+ case {name: '2.6', released_at: Time.new(2018, 12, 25)}
+ in {released_at: ^(Time.new(2010)..Time.new(2020))}
+ true
end
+ RUBY
- result.should == true
- end
+ eval(<<~RUBY).should == true
+ case 0
+ in ^(0+0)
+ true
+ end
+ RUBY
end
end
end
diff --git a/spec/ruby/language/precedence_spec.rb b/spec/ruby/language/precedence_spec.rb
index 5a3c2861ce..c5adcca2c0 100644
--- a/spec/ruby/language/precedence_spec.rb
+++ b/spec/ruby/language/precedence_spec.rb
@@ -14,46 +14,44 @@ require_relative 'fixtures/precedence'
# the level below (as well as showing associativity within
# the precedence level).
-=begin
-Excerpted from 'Programming Ruby: The Pragmatic Programmer's Guide'
-Second Edition by Dave Thomas, Chad Fowler, and Andy Hunt, page 324
-
-Table 22.4. Ruby operators (high to low precedence)
-Method Operator Description
------------------------------------------------------------------------
- :: .
- x* [ ] [ ]= Element reference, element set
- x ** Exponentiation
- x ! ~ + - Not, complement, unary plus and minus
- (method names for the last two are +@ and -@)
- x * / % Multiply, divide, and modulo
- x + - Plus and minus
- x >> << Right and left shift
- x & “And” (bitwise for integers)
- x ^ | Exclusive “or” and regular “or” (bitwise for integers)
- x <= < > >= Comparison operators
- x <=> == === != =~ !~ Equality and pattern match operators (!=
- and !~ may not be defined as methods)
- && Logical “and”
- || Logical “or”
- .. ... Range (inclusive and exclusive)
- ? : Ternary if-then-else
- = %= /= -= += |= &= Assignment
- >>= <<= *= &&= ||= **=
- defined? Check if symbol defined
- not Logical negation
- or and Logical composition
- if unless while until Expression modifiers
- begin/end Block expression
------------------------------------------------------------------------
-
-* Operators marked with 'x' in the Method column are implemented as methods
-and can be overridden (except != and !~ as noted). (But see the specs
-below for implementations that define != and !~ as methods.)
-
-** These are not included in the excerpted table but are shown here for
-completeness.
-=end
+# Excerpted from 'Programming Ruby: The Pragmatic Programmer's Guide'
+# Second Edition by Dave Thomas, Chad Fowler, and Andy Hunt, page 324
+#
+# Table 22.4. Ruby operators (high to low precedence)
+# Method Operator Description
+# -----------------------------------------------------------------------
+# :: .
+# x* [ ] [ ]= Element reference, element set
+# x ** Exponentiation
+# x ! ~ + - Not, complement, unary plus and minus
+# (method names for the last two are +@ and -@)
+# x * / % Multiply, divide, and modulo
+# x + - Plus and minus
+# x >> << Right and left shift
+# x & “And” (bitwise for integers)
+# x ^ | Exclusive “or” and regular “or” (bitwise for integers)
+# x <= < > >= Comparison operators
+# x <=> == === != =~ !~ Equality and pattern match operators (!=
+# and !~ may not be defined as methods)
+# && Logical “and”
+# || Logical “or”
+# .. ... Range (inclusive and exclusive)
+# ? : Ternary if-then-else
+# = %= /= -= += |= &= Assignment
+# >>= <<= *= &&= ||= **=
+# defined? Check if symbol defined
+# not Logical negation
+# or and Logical composition
+# if unless while until Expression modifiers
+# begin/end Block expression
+# -----------------------------------------------------------------------
+#
+# * Operators marked with 'x' in the Method column are implemented as methods
+# and can be overridden (except != and !~ as noted). (But see the specs
+# below for implementations that define != and !~ as methods.)
+#
+# ** These are not included in the excerpted table but are shown here for
+# completeness.
# -----------------------------------------------------------------------
# It seems that this table is not correct anymore
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index 24a8cf2f67..d1cda25918 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -7,37 +7,33 @@ require 'stringio'
# Entries marked [r/o] are read-only and an error will be raised of the program attempts to
# modify them. Entries marked [thread] are thread local.
-=begin
-Exception Information
----------------------------------------------------------------------------------------------------
-
-$! Exception The exception object passed to raise. [thread]
-$@ Array The stack backtrace generated by the last exception. [thread]
-=end
-
-=begin
-Pattern Matching Variables
----------------------------------------------------------------------------------------------------
-
-These variables are set to nil after an unsuccessful pattern match.
-
-$& String The string matched (following a successful pattern match). This variable is
- local to the current scope. [r/o, thread]
-$+ String The contents of the highest-numbered group matched following a successful
- pattern match. Thus, in "cat" =~/(c|a)(t|z)/, $+ will be set to “t”. This
- variable is local to the current scope. [r/o, thread]
-$` String The string preceding the match in a successful pattern match. This variable
- is local to the current scope. [r/o, thread]
-$' String The string following the match in a successful pattern match. This variable
- is local to the current scope. [r/o, thread]
-$1 to $<N> String The contents of successive groups matched in a successful pattern match. In
- "cat" =~/(c|a)(t|z)/, $1 will be set to “a” and $2 to “t”. This variable
- is local to the current scope. [r/o, thread]
-$~ MatchData An object that encapsulates the results of a successful pattern match. The
- variables $&, $`, $', and $1 to $<N> are all derived from $~. Assigning to $~
- changes the values of these derived variables. This variable is local to the
- current scope. [thread]
-=end
+# Exception Information
+# ---------------------------------------------------------------------------------------------------
+#
+# $! Exception The exception object passed to raise. [thread]
+# $@ Array The stack backtrace generated by the last exception. [thread]
+
+# Pattern Matching Variables
+# ---------------------------------------------------------------------------------------------------
+#
+# These variables are set to nil after an unsuccessful pattern match.
+#
+# $& String The string matched (following a successful pattern match). This variable is
+# local to the current scope. [r/o, thread]
+# $+ String The contents of the highest-numbered group matched following a successful
+# pattern match. Thus, in "cat" =~/(c|a)(t|z)/, $+ will be set to “t”. This
+# variable is local to the current scope. [r/o, thread]
+# $` String The string preceding the match in a successful pattern match. This variable
+# is local to the current scope. [r/o, thread]
+# $' String The string following the match in a successful pattern match. This variable
+# is local to the current scope. [r/o, thread]
+# $1 to $<N> String The contents of successive groups matched in a successful pattern match. In
+# "cat" =~/(c|a)(t|z)/, $1 will be set to “a” and $2 to “t”. This variable
+# is local to the current scope. [r/o, thread]
+# $~ MatchData An object that encapsulates the results of a successful pattern match. The
+# variables $&, $`, $', and $1 to $<N> are all derived from $~. Assigning to $~
+# changes the values of these derived variables. This variable is local to the
+# current scope. [thread]
describe "Predefined global $~" do
@@ -506,41 +502,39 @@ describe "Predefined global $!" do
end
end
-=begin
-Input/Output Variables
----------------------------------------------------------------------------------------------------
-
-$/ String The input record separator (newline by default). This is the value that rou-
- tines such as Kernel#gets use to determine record boundaries. If set to
- nil, gets will read the entire file.
-$-0 String Synonym for $/.
-$\ String The string appended to the output of every call to methods such as
- 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.
-$. 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
- the files given as command-line arguments or $stdin (in the case where
- there are no arguments). $< supports methods similar to a File object:
- binmode, close, closed?, each, each_byte, each_line, eof, eof?,
- file, filename, fileno, getc, gets, lineno, lineno=, path, pos, pos=,
- read, readchar, readline, readlines, rewind, seek, skip, tell, to_a,
- to_i, to_io, to_s, along with the methods in Enumerable. The method
- file returns a File object for the file currently being read. This may change
- as $< reads through the files on the command line. [r/o]
-$> IO The destination of output for Kernel#print and Kernel#printf. The
- default value is $stdout.
-$_ String The last line read by Kernel#gets or Kernel#readline. Many string-
- related functions in the Kernel module operate on $_ by default. The vari-
- able is local to the current scope. [thread]
-$-F String Synonym for $;.
-$stderr IO The current standard error output.
-$stdin IO The current standard input.
-$stdout IO The current standard output. Assignment to $stdout is deprecated: use
- $stdout.reopen instead.
-=end
+# Input/Output Variables
+# ---------------------------------------------------------------------------------------------------
+#
+# $/ String The input record separator (newline by default). This is the value that rou-
+# tines such as Kernel#gets use to determine record boundaries. If set to
+# nil, gets will read the entire file.
+# $-0 String Synonym for $/.
+# $\ String The string appended to the output of every call to methods such as
+# 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.
+# $. 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
+# the files given as command-line arguments or $stdin (in the case where
+# there are no arguments). $< supports methods similar to a File object:
+# binmode, close, closed?, each, each_byte, each_line, eof, eof?,
+# file, filename, fileno, getc, gets, lineno, lineno=, path, pos, pos=,
+# read, readchar, readline, readlines, rewind, seek, skip, tell, to_a,
+# to_i, to_io, to_s, along with the methods in Enumerable. The method
+# file returns a File object for the file currently being read. This may change
+# as $< reads through the files on the command line. [r/o]
+# $> IO The destination of output for Kernel#print and Kernel#printf. The
+# default value is $stdout.
+# $_ String The last line read by Kernel#gets or Kernel#readline. Many string-
+# related functions in the Kernel module operate on $_ by default. The vari-
+# able is local to the current scope. [thread]
+# $-F String Synonym for $;.
+# $stderr IO The current standard error output.
+# $stdin IO The current standard input.
+# $stdout IO The current standard output. Assignment to $stdout is deprecated: use
+# $stdout.reopen instead.
describe "Predefined global $/" do
before :each do
@@ -570,7 +564,6 @@ describe "Predefined global $/" do
($/ = "xyz").should == "xyz"
end
-
it "changes $-0" do
$/ = "xyz"
$-0.should equal($/)
@@ -641,6 +634,45 @@ describe "Predefined global $-0" do
end
end
+describe "Predefined global $\\" do
+ before :each do
+ @verbose, $VERBOSE = $VERBOSE, nil
+ @dollar_backslash = $\
+ end
+
+ after :each do
+ $\ = @dollar_backslash
+ $VERBOSE = @verbose
+ end
+
+ it "can be assigned a String" do
+ str = "abc"
+ $\ = str
+ $\.should equal(str)
+ end
+
+ it "can be assigned nil" do
+ $\ = nil
+ $\.should be_nil
+ end
+
+ it "returns the value assigned" do
+ ($\ = "xyz").should == "xyz"
+ end
+
+ it "does not call #to_str to convert the object to a String" do
+ obj = mock("$\\ value")
+ obj.should_not_receive(:to_str)
+
+ -> { $\ = obj }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if assigned not String" do
+ -> { $\ = 1 }.should raise_error(TypeError)
+ -> { $\ = true }.should raise_error(TypeError)
+ end
+end
+
describe "Predefined global $," do
after :each do
$, = nil
@@ -654,10 +686,8 @@ describe "Predefined global $," 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
+ it "warns if assigned non-nil" do
+ -> { $, = "_" }.should complain(/warning: `\$,' is deprecated/)
end
end
@@ -693,10 +723,8 @@ describe "Predefined global $;" do
$; = nil
end
- ruby_version_is "2.7" do
- it "warns if assigned non-nil" do
- -> { $; = "_" }.should complain(/warning: `\$;' is deprecated/)
- end
+ it "warns if assigned non-nil" do
+ -> { $; = "_" }.should complain(/warning: `\$;' is deprecated/)
end
end
@@ -769,54 +797,52 @@ describe "Predefined global $_" do
end
end
-=begin
-Execution Environment Variables
----------------------------------------------------------------------------------------------------
-
-$0 String The name of the top-level Ruby program being executed. Typically this will
- be the program’s filename. On some operating systems, assigning to this
- variable will change the name of the process reported (for example) by the
- ps(1) command.
-$* Array An array of strings containing the command-line options from the invoca-
- 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]
-$$ 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.
- The initial value is the value of the arguments passed via the -I command-
- line option, followed by an installation-defined standard library location, fol-
- lowed by the current directory (“.”). This variable may be set from within a
- program to alter the default search path; typically, programs use $: << dir
- to append dir to the path. [r/o]
-$-a Object True if the -a option is specified on the command line. [r/o]
-$-d Object Synonym for $DEBUG.
-$DEBUG Object Set to true if the -d command-line option is specified.
-__FILE__ String The name of the current source file. [r/o]
-$F Array The array that receives the split input line if the -a command-line option is
- used.
-$FILENAME String The name of the current input file. Equivalent to $<.filename. [r/o]
-$-i String If in-place edit mode is enabled (perhaps using the -i command-line
- option), $-i holds the extension used when creating the backup file. If you
- set a value into $-i, enables in-place edit mode.
-$-I Array Synonym for $:. [r/o]
-$-K String Sets the multibyte coding system for strings and regular expressions. Equiv-
- alent to the -K command-line option.
-$-l Object Set to true if the -l option (which enables line-end processing) is present
- on the command line. [r/o]
-__LINE__ String The current line number in the source file. [r/o]
-$LOAD_PATH Array A synonym for $:. [r/o]
-$-p Object Set to true if the -p option (which puts an implicit while gets . . . end
- loop around your program) is present on the command line. [r/o]
-$VERBOSE Object Set to true if the -v, --version, -W, or -w option is specified on the com-
- mand line. Set to false if no option, or -W1 is given. Set to nil if -W0
- was specified. Setting this option to true causes the interpreter and some
- library routines to report additional information. Setting to nil suppresses
- all warnings (including the output of Kernel.warn).
-$-v Object Synonym for $VERBOSE.
-$-w Object Synonym for $VERBOSE.
-=end
+# Execution Environment Variables
+# ---------------------------------------------------------------------------------------------------
+#
+# $0 String The name of the top-level Ruby program being executed. Typically this will
+# be the program’s filename. On some operating systems, assigning to this
+# variable will change the name of the process reported (for example) by the
+# ps(1) command.
+# $* Array An array of strings containing the command-line options from the invoca-
+# 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]
+# $$ 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.
+# The initial value is the value of the arguments passed via the -I command-
+# line option, followed by an installation-defined standard library location, fol-
+# lowed by the current directory (“.”). This variable may be set from within a
+# program to alter the default search path; typically, programs use $: << dir
+# to append dir to the path. [r/o]
+# $-a Object True if the -a option is specified on the command line. [r/o]
+# $-d Object Synonym for $DEBUG.
+# $DEBUG Object Set to true if the -d command-line option is specified.
+# __FILE__ String The name of the current source file. [r/o]
+# $F Array The array that receives the split input line if the -a command-line option is
+# used.
+# $FILENAME String The name of the current input file. Equivalent to $<.filename. [r/o]
+# $-i String If in-place edit mode is enabled (perhaps using the -i command-line
+# option), $-i holds the extension used when creating the backup file. If you
+# set a value into $-i, enables in-place edit mode.
+# $-I Array Synonym for $:. [r/o]
+# $-K String Sets the multibyte coding system for strings and regular expressions. Equiv-
+# alent to the -K command-line option.
+# $-l Object Set to true if the -l option (which enables line-end processing) is present
+# on the command line. [r/o]
+# __LINE__ String The current line number in the source file. [r/o]
+# $LOAD_PATH Array A synonym for $:. [r/o]
+# $-p Object Set to true if the -p option (which puts an implicit while gets . . . end
+# loop around your program) is present on the command line. [r/o]
+# $VERBOSE Object Set to true if the -v, --version, -W, or -w option is specified on the com-
+# mand line. Set to false if no option, or -W1 is given. Set to nil if -W0
+# was specified. Setting this option to true causes the interpreter and some
+# library routines to report additional information. Setting to nil suppresses
+# all warnings (including the output of Kernel.warn).
+# $-v Object Synonym for $VERBOSE.
+# $-w Object Synonym for $VERBOSE.
describe "Execution variable $:" do
it "is initialized to an array of strings" do
$:.is_a?(Array).should == true
@@ -835,6 +861,8 @@ describe "Execution variable $:" do
it "can be changed via <<" do
$: << "foo"
$:.should include("foo")
+ ensure
+ $:.delete("foo")
end
it "is read-only" do
@@ -850,6 +878,16 @@ describe "Execution variable $:" do
$-I = []
}.should raise_error(NameError)
end
+
+ it "default $LOAD_PATH entries until sitelibdir included have @gem_prelude_index set" do
+ skip "no sense in ruby itself" if MSpecScript.instance_variable_defined?(:@testing_ruby)
+
+ $:.should.include?(RbConfig::CONFIG['sitelibdir'])
+ idx = $:.index(RbConfig::CONFIG['sitelibdir'])
+
+ $:[idx..-1].all? { |p| p.instance_variable_defined?(:@gem_prelude_index) }.should be_true
+ $:[0...idx].all? { |p| !p.instance_variable_defined?(:@gem_prelude_index) }.should be_true
+ end
end
describe "Global variable $\"" do
@@ -1022,22 +1060,20 @@ describe "Global variable $0" do
end
end
-=begin
-Standard Objects
----------------------------------------------------------------------------------------------------
-
-ARGF Object A synonym for $<.
-ARGV Array A synonym for $*.
-ENV Object A hash-like object containing the program’s environment variables. An
- instance of class Object, ENV implements the full set of Hash methods. Used
- to query and set the value of an environment variable, as in ENV["PATH"]
- and ENV["term"]="ansi".
-false FalseClass Singleton instance of class FalseClass. [r/o]
-nil NilClass The singleton instance of class NilClass. The value of uninitialized
- instance and global variables. [r/o]
-self Object The receiver (object) of the current method. [r/o]
-true TrueClass Singleton instance of class TrueClass. [r/o]
-=end
+# Standard Objects
+# ---------------------------------------------------------------------------------------------------
+#
+# ARGF Object A synonym for $<.
+# ARGV Array A synonym for $*.
+# ENV Object A hash-like object containing the program’s environment variables. An
+# instance of class Object, ENV implements the full set of Hash methods. Used
+# to query and set the value of an environment variable, as in ENV["PATH"]
+# and ENV["term"]="ansi".
+# false FalseClass Singleton instance of class FalseClass. [r/o]
+# nil NilClass The singleton instance of class NilClass. The value of uninitialized
+# instance and global variables. [r/o]
+# self Object The receiver (object) of the current method. [r/o]
+# true TrueClass Singleton instance of class TrueClass. [r/o]
describe "The predefined standard objects" do
it "includes ARGF" do
@@ -1090,35 +1126,81 @@ describe "The self pseudo-variable" do
end
end
-=begin
-Global Constants
----------------------------------------------------------------------------------------------------
-
-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.
-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).
-RUBY_RELEASE_DATE String The date of this release.
-RUBY_VERSION String The version number of the interpreter.
-STDERR IO The actual standard error stream for the program. The initial
- value of $stderr.
-STDIN IO The actual standard input stream for the program. The initial
- value of $stdin.
-STDOUT IO The actual standard output stream for the program. The initial
- value of $stdout.
-SCRIPT_LINES__ Hash If a constant SCRIPT_LINES__ is defined and references a Hash,
- Ruby will store an entry containing the contents of each file it
- parses, with the file’s name as the key and an array of strings as
- the value.
-TOPLEVEL_BINDING Binding A Binding object representing the binding at Ruby’s top level—
- the level where programs are initially executed.
-=end
+# Global Constants
+# ---------------------------------------------------------------------------------------------------
+#
+# 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 (deprecated, removed in Ruby 3).
+# NIL NilClass Synonym for nil (deprecated, removed in Ruby 3).
+# RUBY_PLATFORM String The identifier of the platform running this program. This string
+# is in the same form as the platform identifier used by the GNU
+# configure utility (which is not a coincidence).
+# RUBY_RELEASE_DATE String The date of this release.
+# RUBY_VERSION String The version number of the interpreter.
+# STDERR IO The actual standard error stream for the program. The initial
+# value of $stderr.
+# STDIN IO The actual standard input stream for the program. The initial
+# value of $stdin.
+# STDOUT IO The actual standard output stream for the program. The initial
+# value of $stdout.
+# SCRIPT_LINES__ Hash If a constant SCRIPT_LINES__ is defined and references a Hash,
+# Ruby will store an entry containing the contents of each file it
+# parses, with the file’s name as the key and an array of strings as
+# 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 (deprecated, removed in Ruby 3).
describe "The predefined global constants" do
+ describe "TRUE" do
+ ruby_version_is "3.0" do
+ it "is no longer defined" do
+ Object.const_defined?(:TRUE).should == false
+ end
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "includes TRUE" do
+ Object.const_defined?(:TRUE).should == true
+ -> { TRUE }.should complain(/constant ::TRUE is deprecated/)
+ end
+ end
+ end
+
+ describe "FALSE" do
+ ruby_version_is "3.0" do
+ it "is no longer defined" do
+ Object.const_defined?(:FALSE).should == false
+ end
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "includes FALSE" do
+ Object.const_defined?(:FALSE).should == true
+ -> { FALSE }.should complain(/constant ::FALSE is deprecated/)
+ end
+ end
+ end
+
+ describe "NIL" do
+ ruby_version_is "3.0" do
+ it "is no longer defined" do
+ Object.const_defined?(:NIL).should == false
+ end
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "includes NIL" do
+ Object.const_defined?(:NIL).should == true
+ -> { NIL }.should complain(/constant ::NIL is deprecated/)
+ end
+ end
+ end
+
it "includes STDIN" do
Object.const_defined?(:STDIN).should == true
end
@@ -1146,7 +1228,6 @@ describe "The predefined global constants" do
it "includes TOPLEVEL_BINDING" do
Object.const_defined?(:TOPLEVEL_BINDING).should == true
end
-
end
describe "The predefined global constant" do
@@ -1161,13 +1242,24 @@ describe "The predefined global constant" do
end
describe "STDIN" do
- it "has the same external encoding as Encoding.default_external" do
- STDIN.external_encoding.should equal(Encoding.default_external)
- end
+ platform_is_not :windows do
+ it "has the same external encoding as Encoding.default_external" do
+ STDIN.external_encoding.should equal(Encoding.default_external)
+ end
+
+ it "has the same external encoding as Encoding.default_external when that encoding is changed" do
+ Encoding.default_external = Encoding::ISO_8859_16
+ STDIN.external_encoding.should equal(Encoding::ISO_8859_16)
+ end
- it "has the same external encoding as Encoding.default_external when that encoding is changed" do
- Encoding.default_external = Encoding::ISO_8859_16
- STDIN.external_encoding.should equal(Encoding::ISO_8859_16)
+ it "has nil for the internal encoding" do
+ STDIN.internal_encoding.should be_nil
+ end
+
+ it "has nil for the internal encoding despite Encoding.default_internal being changed" do
+ Encoding.default_internal = Encoding::IBM437
+ STDIN.internal_encoding.should be_nil
+ end
end
it "has the encodings set by #set_encoding" do
@@ -1182,15 +1274,6 @@ describe "The predefined global constant" do
"p [STDIN.external_encoding.name, STDIN.internal_encoding.name]"
ruby_exe(code).chomp.should == %{["IBM775", "IBM866"]}
end
-
- it "has nil for the internal encoding" do
- STDIN.internal_encoding.should be_nil
- end
-
- it "has nil for the internal encoding despite Encoding.default_internal being changed" do
- Encoding.default_internal = Encoding::IBM437
- STDIN.internal_encoding.should be_nil
- end
end
describe "STDOUT" do
@@ -1255,32 +1338,57 @@ describe "The predefined global constant" do
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
+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'
+ it "returns what will be loaded without actual loading, .so file" do
+ require 'rbconfig'
+ skip "no dynamically loadable standard extension" if RbConfig::CONFIG["EXTSTATIC"] == "static"
- extension, path = $LOAD_PATH.resolve_feature_path('etc')
- extension.should == :so
- path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
- end
+ extension, path = $LOAD_PATH.resolve_feature_path('etc')
+ extension.should == :so
+ path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
+ end
- ruby_version_is "2.7"..."3.1" do
- it "raises LoadError if feature cannot be found" do
- -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError)
- end
+ ruby_version_is ""..."3.1" do
+ it "raises LoadError if feature cannot be found" do
+ -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError)
end
+ end
- ruby_version_is "3.1" do
- it "return nil if feature cannot be found" do
- $LOAD_PATH.resolve_feature_path('noop').should be_nil
- end
+ ruby_version_is "3.1" do
+ it "return nil if feature cannot be found" do
+ $LOAD_PATH.resolve_feature_path('noop').should be_nil
end
end
end
+
+# Some other pre-defined global variables
+
+describe "Predefined global $=" do
+ before :each do
+ @verbose, $VERBOSE = $VERBOSE, nil
+ @dollar_assign = $=
+ end
+
+ after :each do
+ $= = @dollar_assign
+ $VERBOSE = @verbose
+ end
+
+ it "warns when accessed" do
+ -> { a = $= }.should complain(/is no longer effective/)
+ end
+
+ it "warns when assigned" do
+ -> { $= = "_" }.should complain(/is no longer effective/)
+ end
+
+ it "returns the value assigned" do
+ ($= = "xyz").should == "xyz"
+ end
+end
diff --git a/spec/ruby/language/proc_spec.rb b/spec/ruby/language/proc_spec.rb
index c44e711d2b..f8a29962b0 100644
--- a/spec/ruby/language/proc_spec.rb
+++ b/spec/ruby/language/proc_spec.rb
@@ -217,4 +217,31 @@ describe "A Proc" do
lambda { @l.call(obj) }.should raise_error(TypeError)
end
end
+
+ describe "taking |*a, **kw| arguments" do
+ before :each do
+ @p = proc { |*a, **kw| [a, kw] }
+ end
+
+ ruby_version_is ""..."3.0" do
+ it 'autosplats keyword arguments and warns' do
+ -> {
+ @p.call([1, {a: 1}]).should == [[1], {a: 1}]
+ }.should complain(/warning: Using the last argument as keyword parameters is deprecated; maybe \*\* should be added to the call/)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it 'does not autosplat keyword arguments' do
+ @p.call([1, {a: 1}]).should == [[[1, {a: 1}]], {}]
+ end
+ end
+ end
+
+ describe "taking |required keyword arguments, **kw| arguments" do
+ it "raises ArgumentError for missing required argument" do
+ p = proc { |a:, **kw| [a, kw] }
+ -> { p.call() }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/language/range_spec.rb b/spec/ruby/language/range_spec.rb
index 79500c6b33..ccc9f55537 100644
--- a/spec/ruby/language/range_spec.rb
+++ b/spec/ruby/language/range_spec.rb
@@ -10,15 +10,21 @@ describe "Literal Ranges" do
(1...10).should == Range.new(1, 10, true)
end
+ it "creates a simple range as an object literal" do
+ ary = []
+ 2.times do
+ ary.push(1..3)
+ end
+ ary[0].should.equal?(ary[1])
+ end
+
it "creates endless ranges" do
(1..).should == Range.new(1, nil)
(1...).should == Range.new(1, nil, true)
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
+ it "creates beginless ranges" do
+ (..1).should == Range.new(nil, 1)
+ (...1).should == Range.new(nil, 1, true)
end
end
diff --git a/spec/ruby/language/regexp/character_classes_spec.rb b/spec/ruby/language/regexp/character_classes_spec.rb
index 0cf1e9b6f4..12a51178b2 100644
--- a/spec/ruby/language/regexp/character_classes_spec.rb
+++ b/spec/ruby/language/regexp/character_classes_spec.rb
@@ -609,6 +609,11 @@ describe "Regexp with character classes" do
"루비(Ruby)".match(/\p{Hangul}+/u).to_a.should == ["루비"]
end
+ it "supports negated property condition" do
+ "a".match(/\P{L}/).should be_nil
+ "1".match(/\P{N}/).should be_nil
+ end
+
ruby_bug "#17340", ''...'3.0' do
it "raises a RegexpError for an unterminated unicode property" do
-> { Regexp.new('\p{') }.should raise_error(RegexpError)
diff --git a/spec/ruby/language/regexp/encoding_spec.rb b/spec/ruby/language/regexp/encoding_spec.rb
index 8e2a294b95..febc3fdb37 100644
--- a/spec/ruby/language/regexp/encoding_spec.rb
+++ b/spec/ruby/language/regexp/encoding_spec.rb
@@ -38,6 +38,10 @@ describe "Regexps with encoding modifiers" do
/#{/./}/n.match("\303\251").to_a.should == ["\303"]
end
+ it "warns when using /n with a match string with non-ASCII characters and an encoding other than ASCII-8BIT" do
+ -> { /./n.match("\303\251".force_encoding('utf-8')) }.should complain(%r{historical binary regexp match /.../n against UTF-8 string})
+ end
+
it 'uses US-ASCII as /n encoding if all chars are 7-bit' do
/./n.encoding.should == Encoding::US_ASCII
end
@@ -117,6 +121,19 @@ describe "Regexps with encoding modifiers" do
-> { /\A[[:space:]]*\z/ =~ " ".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError)
end
+ it "raises Encoding::CompatibilityError when the regexp has a fixed, non-ASCII-compatible encoding" do
+ -> { Regexp.new("".force_encoding("UTF-16LE"), Regexp::FIXEDENCODING) =~ " ".encode("UTF-8") }.should raise_error(Encoding::CompatibilityError)
+ end
+
+ it "raises Encoding::CompatibilityError when the regexp has a fixed encoding and the match string has non-ASCII characters" do
+ -> { Regexp.new("".force_encoding("US-ASCII"), Regexp::FIXEDENCODING) =~ "\303\251".force_encoding('UTF-8') }.should raise_error(Encoding::CompatibilityError)
+ end
+
+ it "raises ArgumentError when trying to match a broken String" do
+ s = "\x80".force_encoding('UTF-8')
+ -> { s =~ /./ }.should raise_error(ArgumentError, "invalid byte sequence in UTF-8")
+ end
+
it "computes the Regexp Encoding for each interpolated Regexp instance" do
make_regexp = -> str { /#{str}/ }
diff --git a/spec/ruby/language/regexp/escapes_spec.rb b/spec/ruby/language/regexp/escapes_spec.rb
index 2e5fe5ad2e..16a4d8c23b 100644
--- a/spec/ruby/language/regexp/escapes_spec.rb
+++ b/spec/ruby/language/regexp/escapes_spec.rb
@@ -2,8 +2,10 @@
require_relative '../../spec_helper'
require_relative '../fixtures/classes'
+# TODO: synchronize with spec/core/regexp/new_spec.rb -
+# escaping is also tested there
describe "Regexps with escape characters" do
- it "they're supported" do
+ it "supports escape sequences" do
/\t/.match("\t").to_a.should == ["\t"] # horizontal tab
/\v/.match("\v").to_a.should == ["\v"] # vertical tab
/\n/.match("\n").to_a.should == ["\n"] # newline
@@ -15,9 +17,7 @@ describe "Regexps with escape characters" do
# \nnn octal char (encoded byte value)
end
- it "support quoting meta-characters via escape sequence" do
- /\\/.match("\\").to_a.should == ["\\"]
- /\//.match("/").to_a.should == ["/"]
+ it "supports quoting meta-characters via escape sequence" do
# parenthesis, etc
/\(/.match("(").to_a.should == ["("]
/\)/.match(")").to_a.should == [")"]
@@ -25,6 +25,8 @@ describe "Regexps with escape characters" do
/\]/.match("]").to_a.should == ["]"]
/\{/.match("{").to_a.should == ["{"]
/\}/.match("}").to_a.should == ["}"]
+ /\</.match("<").to_a.should == ["<"]
+ /\>/.match(">").to_a.should == [">"]
# alternation separator
/\|/.match("|").to_a.should == ["|"]
# quantifiers
@@ -37,11 +39,81 @@ describe "Regexps with escape characters" do
/\$/.match("$").to_a.should == ["$"]
end
+ it "supports quoting meta-characters via escape sequence when used as a terminator" do
+ # parenthesis, etc
+ # %r[[, %r((, etc literals - are forbidden
+ %r(\().match("(").to_a.should == ["("]
+ %r(\)).match(")").to_a.should == [")"]
+ %r)\().match("(").to_a.should == ["("]
+ %r)\)).match(")").to_a.should == [")"]
+
+ %r[\[].match("[").to_a.should == ["["]
+ %r[\]].match("]").to_a.should == ["]"]
+ %r]\[].match("[").to_a.should == ["["]
+ %r]\]].match("]").to_a.should == ["]"]
+
+ %r{\{}.match("{").to_a.should == ["{"]
+ %r{\}}.match("}").to_a.should == ["}"]
+ %r}\{}.match("{").to_a.should == ["{"]
+ %r}\}}.match("}").to_a.should == ["}"]
+
+ %r<\<>.match("<").to_a.should == ["<"]
+ %r<\>>.match(">").to_a.should == [">"]
+ %r>\<>.match("<").to_a.should == ["<"]
+ %r>\>>.match(">").to_a.should == [">"]
+
+ # alternation separator
+ %r|\||.match("|").to_a.should == ["|"]
+ # quantifiers
+ %r?\??.match("?").to_a.should == ["?"]
+ %r.\...match(".").to_a.should == ["."]
+ %r*\**.match("*").to_a.should == ["*"]
+ %r+\++.match("+").to_a.should == ["+"]
+ # line anchors
+ %r^\^^.match("^").to_a.should == ["^"]
+ %r$\$$.match("$").to_a.should == ["$"]
+ end
+
+ it "supports quoting non-meta-characters via escape sequence when used as a terminator" do
+ non_meta_character_terminators = [
+ '!', '"', '#', '%', '&', "'", ',', '-', ':', ';', '@', '_', '`', '/', '=', '~'
+ ]
+
+ non_meta_character_terminators.each do |c|
+ pattern = eval("%r" + c + "\\" + c + c)
+ pattern.match(c).to_a.should == [c]
+ end
+ end
+
+ it "does not change semantics of escaped non-meta-character when used as a terminator" do
+ all_terminators = [*("!".."/"), *(":".."@"), *("[".."`"), *("{".."~")]
+ meta_character_terminators = ["$", "^", "*", "+", ".", "?", "|", "}", ")", ">", "]"]
+ special_cases = ['(', '{', '[', '<', '\\']
+
+ # it should be equivalent to
+ # [ '!', '"', '#', '%', '&', "'", ',', '-', ':', ';', '@', '_', '`', '/', '=', '~' ]
+ non_meta_character_terminators = all_terminators - meta_character_terminators - special_cases
+
+ non_meta_character_terminators.each do |c|
+ pattern = eval("%r" + c + "\\" + c + c)
+ pattern.should == /#{c}/
+ end
+ end
+
+ it "does not change semantics of escaped meta-character when used as a terminator" do
+ meta_character_terminators = ["$", "^", "*", "+", ".", "?", "|", "}", ")", ">", "]"]
+
+ meta_character_terminators.each do |c|
+ pattern = eval("%r" + c + "\\" + c + c)
+ pattern.should == eval("/\\#{c}/")
+ end
+ end
+
it "allows any character to be escaped" do
/\y/.match("y").to_a.should == ["y"]
end
- it "support \\x (hex characters)" do
+ it "supports \\x (hex characters)" do
/\xA/.match("\nxyz").to_a.should == ["\n"]
/\x0A/.match("\n").to_a.should == ["\n"]
/\xAA/.match("\nA").should be_nil
@@ -53,7 +125,7 @@ describe "Regexps with escape characters" do
# \x{7HHHHHHH} wide hexadecimal char (character code point value)
end
- it "support \\c (control characters)" do
+ it "supports \\c (control characters)" do
#/\c \c@\c`/.match("\00\00\00").to_a.should == ["\00\00\00"]
/\c#\cc\cC/.match("\03\03\03").to_a.should == ["\03\03\03"]
/\c'\cG\cg/.match("\a\a\a").to_a.should == ["\a\a\a"]
diff --git a/spec/ruby/language/regexp/grouping_spec.rb b/spec/ruby/language/regexp/grouping_spec.rb
index e2abe71d0d..2f04a04018 100644
--- a/spec/ruby/language/regexp/grouping_spec.rb
+++ b/spec/ruby/language/regexp/grouping_spec.rb
@@ -32,4 +32,32 @@ describe "Regexps with grouping" do
b # there is no capture group on this line (not even here)
$/x.match("ab").to_a.should == [ "ab", "a" ]
end
+
+ it "does not consider # inside a character class as a comment" do
+ # From https://github.com/rubocop/rubocop/blob/39fcf1c568/lib/rubocop/cop/utils/format_string.rb#L18
+ regexp = /
+ % (?<type>%) # line comment
+ | % (?<flags>(?-mix:[ #0+-]|(?-mix:(\d+)\$))*) (?#group comment)
+ (?:
+ (?: (?-mix:(?<width>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\.(?<precision>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:<(?<name>\w+)>)?
+ | (?-mix:(?<width>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:<(?<name>\w+)>) (?-mix:\.(?<precision>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))?
+ | (?-mix:<(?<name>\w+)>) (?<more_flags>(?-mix:[ #0+-]|(?-mix:(\d+)\$))*) (?-mix:(?<width>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\.(?<precision>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))?
+ ) (?-mix:(?<type>[bBdiouxXeEfgGaAcps]))
+ | (?-mix:(?<width>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\.(?<precision>(?-mix:\d+|(?-mix:\*(?-mix:(\d+)\$)?))))? (?-mix:\{(?<name>\w+)\})
+ )
+ /x
+ regexp.named_captures.should == {
+ "type" => [1, 13],
+ "flags" => [2],
+ "width" => [3, 6, 11, 14],
+ "precision" => [4, 8, 12, 15],
+ "name" => [5, 7, 9, 16],
+ "more_flags" => [10]
+ }
+ match = regexp.match("%6.3f")
+ match[:width].should == '6'
+ match[:precision].should == '3'
+ match[:type].should == 'f'
+ match.to_a.should == [ "%6.3f", nil, "", "6", "3"] + [nil] * 8 + ["f"] + [nil] * 3
+ end
end
diff --git a/spec/ruby/language/regexp_spec.rb b/spec/ruby/language/regexp_spec.rb
index f607fa6010..d49689349d 100644
--- a/spec/ruby/language/regexp_spec.rb
+++ b/spec/ruby/language/regexp_spec.rb
@@ -96,7 +96,6 @@ describe "Literal Regexps" do
/./.match("\0").to_a.should == ["\0"]
end
-
it "supports | (alternations)" do
/a|b/.match("a").to_a.should == ["a"]
end
@@ -115,7 +114,7 @@ describe "Literal Regexps" do
/foo.(?<=\d)/.match("fooA foo1").to_a.should == ["foo1"]
end
- ruby_bug "#13671", ""..."3.2" do # https://bugs.ruby-lang.org/issues/13671
+ ruby_bug "#13671", ""..."3.3" do # https://bugs.ruby-lang.org/issues/13671
it "handles a lookbehind with ss characters" do
r = Regexp.new("(?<!dss)", Regexp::IGNORECASE)
r.should =~ "✨"
@@ -161,26 +160,6 @@ describe "Literal Regexps" do
pattern.should_not =~ 'T'
end
- escapable_terminators = ['!', '"', '#', '%', '&', "'", ',', '-', ':', ';', '@', '_', '`']
-
- it "supports escaping characters when used as a terminator" do
- escapable_terminators.each do |c|
- ref = "(?-mix:#{c})"
- pattern = eval("%r" + c + "\\" + c + c)
- pattern.to_s.should == ref
- end
- end
-
- it "treats an escaped non-escapable character normally when used as a terminator" do
- all_terminators = [*("!".."/"), *(":".."@"), *("[".."`"), *("{".."~")]
- special_cases = ['(', '{', '[', '<', '\\', '=', '~']
- (all_terminators - special_cases - escapable_terminators).each do |c|
- ref = "(?-mix:\\#{c})"
- pattern = eval("%r" + c + "\\" + c + c)
- pattern.to_s.should == ref
- end
- end
-
it "support handling unicode 9.0 characters with POSIX bracket expressions" do
char_lowercase = "\u{104D8}" # OSAGE SMALL LETTER A
/[[:lower:]]/.match(char_lowercase).to_s.should == char_lowercase
diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb
index 4d164b38c6..b91b52fa0f 100644
--- a/spec/ruby/language/rescue_spec.rb
+++ b/spec/ruby/language/rescue_spec.rb
@@ -115,6 +115,18 @@ describe "The rescue keyword" do
end
end
+ it "converts the splatted list of exceptions using #to_a" do
+ exceptions = mock("to_a")
+ exceptions.should_receive(:to_a).and_return(exception_list)
+ caught_it = false
+ begin
+ raise SpecificExampleException, "not important"
+ rescue *exceptions
+ caught_it = true
+ end
+ caught_it.should be_true
+ end
+
it "can combine a splatted list of exceptions with a literal list of exceptions" do
caught_it = false
begin
@@ -492,14 +504,12 @@ describe "The rescue keyword" do
}.should raise_error(Exception)
end
- ruby_version_is "2.7" do
- it "rescues with multiple assignment" do
+ it "rescues with multiple assignment" do
- a, b = raise rescue [1, 2]
+ a, b = raise rescue [1, 2]
- a.should == 1
- b.should == 2
- end
+ a.should == 1
+ b.should == 2
end
end
end
diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb
index d8506834c8..a62ed1242d 100644
--- a/spec/ruby/language/return_spec.rb
+++ b/spec/ruby/language/return_spec.rb
@@ -422,18 +422,31 @@ describe "The return keyword" do
end
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
+ 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
+
+ describe "within BEGIN" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ BEGIN {
+ ScratchPad << "before call"
+ return
+ ScratchPad << "after call"
+ }
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before call"]
end
end
@@ -464,25 +477,13 @@ describe "The return keyword" do
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
+ 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 062381d729..ee5c1b3ccc 100644
--- a/spec/ruby/language/safe_spec.rb
+++ b/spec/ruby/language/safe_spec.rb
@@ -1,99 +1,7 @@
require_relative '../spec_helper'
describe "The $SAFE variable" do
- ruby_version_is ""..."2.7" do
- after :each do
- $SAFE = 0
- end
-
- it "is 0 by default" do
- $SAFE.should == 0
- proc {
- $SAFE.should == 0
- }.call
- end
-
- it "can be set to 0" do
- proc {
- $SAFE = 0
- $SAFE.should == 0
- }.call
- end
-
- it "can be set to 1" do
- proc {
- $SAFE = 1
- $SAFE.should == 1
- }.call
- end
-
- [2, 3, 4].each do |n|
- it "cannot be set to #{n}" do
- -> {
- proc {
- $SAFE = n
- }.call
- }.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/)
- end
- end
-
- it "raises ArgumentError when set to values below 0" do
- -> {
- proc {
- $SAFE = -100
- }.call
- }.should raise_error(ArgumentError, "$SAFE should be >= 0")
- end
-
- it "cannot be set to values above 4" do
- -> {
- proc {
- $SAFE = 100
- }.call
- }.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/)
- end
-
- it "can be manually lowered" do
- $SAFE = 1
- $SAFE = 0
- $SAFE.should == 0
- end
-
- it "is not Proc local" do
- $SAFE.should == 0
- proc {
- $SAFE = 1
- }.call
- $SAFE.should == 1
- end
-
- it "is not lambda local" do
- $SAFE.should == 0
- -> {
- $SAFE = 1
- }.call
- $SAFE.should == 1
- end
-
- it "is global like regular global variables" do
- Thread.new { $SAFE }.value.should == 0
- $SAFE = 1
- Thread.new { $SAFE }.value.should == 1
- end
-
- it "can be read when default from Thread#safe_level" do
- Thread.current.safe_level.should == 0
- end
-
- it "can be read when modified from Thread#safe_level" do
- proc {
- $SAFE = 1
- Thread.current.safe_level.should == 1
- }.call
- end
- end
-
- ruby_version_is "2.7"..."3.0" do
+ ruby_version_is ""..."3.0" do
it "warn when access" do
-> {
$SAFE
@@ -106,4 +14,14 @@ describe "The $SAFE variable" do
}.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/)
end
end
+
+ ruby_version_is "3.0" do
+ it "$SAFE is a regular global variable" do
+ $SAFE.should == nil
+ $SAFE = 42
+ $SAFE.should == 42
+ ensure
+ $SAFE = nil
+ end
+ end
end
diff --git a/spec/ruby/language/send_spec.rb b/spec/ruby/language/send_spec.rb
index e57e2c65dc..5999079d58 100644
--- a/spec/ruby/language/send_spec.rb
+++ b/spec/ruby/language/send_spec.rb
@@ -258,20 +258,10 @@ describe "Invoking a private setter method" do
end
describe "Invoking a private getter method" do
- ruby_version_is ""..."2.7" do
- it "does not permit self as a receiver" do
- receiver = LangSendSpecs::PrivateGetter.new
- -> { receiver.call_self_foo }.should raise_error(NoMethodError)
- -> { receiver.call_self_foo_or_equals(6) }.should raise_error(NoMethodError)
- end
- end
-
- ruby_version_is "2.7" do
- it "permits self as a receiver" do
- receiver = LangSendSpecs::PrivateGetter.new
- receiver.call_self_foo_or_equals(6)
- receiver.call_self_foo.should == 6
- end
+ it "permits self as a receiver" do
+ receiver = LangSendSpecs::PrivateGetter.new
+ receiver.call_self_foo_or_equals(6)
+ receiver.call_self_foo.should == 6
end
end
diff --git a/spec/ruby/language/singleton_class_spec.rb b/spec/ruby/language/singleton_class_spec.rb
index 7e9370d6f9..c1fb682ea0 100644
--- a/spec/ruby/language/singleton_class_spec.rb
+++ b/spec/ruby/language/singleton_class_spec.rb
@@ -157,23 +157,6 @@ 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 ce4941569e..02e3488a1f 100644
--- a/spec/ruby/language/string_spec.rb
+++ b/spec/ruby/language/string_spec.rb
@@ -56,28 +56,6 @@ describe "Ruby character strings" do
"#\$".should == '#$'
end
- ruby_version_is ''...'2.7' do
- it "taints the result of interpolation when an interpolated value is tainted" do
- "#{"".taint}".tainted?.should be_true
-
- @ip.taint
- "#@ip".tainted?.should be_true
-
- $ip.taint
- "#$ip".tainted?.should be_true
- end
-
- it "untrusts the result of interpolation when an interpolated value is untrusted" do
- "#{"".untrust}".untrusted?.should be_true
-
- @ip.untrust
- "#@ip".untrusted?.should be_true
-
- $ip.untrust
- "#$ip".untrusted?.should be_true
- end
- end
-
it "allows using non-alnum characters as string delimiters" do
%(hey #{@ip}).should == "hey xxx"
%[hey #{@ip}].should == "hey xxx"
diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb
index 7d6969e659..c900c03d37 100644
--- a/spec/ruby/language/variables_spec.rb
+++ b/spec/ruby/language/variables_spec.rb
@@ -797,8 +797,21 @@ describe 'Local variable shadowing' do
end
describe 'Allowed characters' do
- # new feature in 2.6 -- https://bugs.ruby-lang.org/issues/13770
- it 'does not allow non-ASCII upcased characters at the beginning' do
+ 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
+
+ it 'parses a non-ASCII upcased character as a constant identifier' do
-> do
eval <<-CODE
def test
@@ -807,18 +820,51 @@ describe 'Allowed characters' do
CODE
end.should raise_error(SyntaxError, /dynamic constant assignment/)
end
+end
- it 'allows non-ASCII lowercased characters at the beginning' do
- result = nil
+describe "Instance variables" do
+ context "when instance variable is uninitialized" do
+ ruby_version_is ""..."3.0" do
+ it "warns about accessing uninitialized instance variable" do
+ obj = Object.new
+ def obj.foobar; a = @a; end
- eval <<-CODE
- def test
- μ = 1
+ -> { obj.foobar }.should complain(/warning: instance variable @a not initialized/, verbose: true)
end
+ end
- result = test
- CODE
+ ruby_version_is "3.0" do
+ it "doesn't warn about accessing uninitialized instance variable" do
+ obj = Object.new
+ def obj.foobar; a = @a; end
- result.should == 1
+ -> { obj.foobar }.should_not complain(verbose: true)
+ end
+ end
+
+ it "doesn't warn at lazy initialization" do
+ obj = Object.new
+ def obj.foobar; @a ||= 42; end
+
+ -> { obj.foobar }.should_not complain(verbose: true)
+ end
+ end
+
+ describe "global variable" do
+ context "when global variable is uninitialized" do
+ it "warns about accessing uninitialized global variable in verbose mode" do
+ obj = Object.new
+ def obj.foobar; a = $specs_uninitialized_global_variable; end
+
+ -> { obj.foobar }.should complain(/warning: global variable `\$specs_uninitialized_global_variable' not initialized/, verbose: true)
+ end
+
+ it "doesn't warn at lazy initialization" do
+ obj = Object.new
+ def obj.foobar; $specs_uninitialized_global_variable_lazy ||= 42; end
+
+ -> { obj.foobar }.should_not complain(verbose: true)
+ end
+ end
end
end
diff --git a/spec/ruby/language/yield_spec.rb b/spec/ruby/language/yield_spec.rb
index 5fad7cb176..05d713af70 100644
--- a/spec/ruby/language/yield_spec.rb
+++ b/spec/ruby/language/yield_spec.rb
@@ -183,5 +183,43 @@ describe "The yield call" do
it "uses captured block of a block used in define_method" do
@y.deep(2).should == 4
end
+end
+
+describe "Using yield in a singleton class literal" do
+ ruby_version_is ""..."3.0" do
+ it 'emits a deprecation warning' do
+ code = <<~RUBY
+ def m
+ class << Object.new
+ yield
+ end
+ end
+ m { :ok }
+ RUBY
+
+ -> { eval(code) }.should complain(/warning: `yield' in class syntax will not be supported from Ruby 3.0/)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it 'raises a SyntaxError' do
+ code = <<~RUBY
+ class << Object.new
+ yield
+ end
+ RUBY
+ -> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/)
+ end
+ end
+end
+
+describe "Using yield in non-lambda block" do
+ it 'raises a SyntaxError' do
+ code = <<~RUBY
+ 1.times { yield }
+ RUBY
+
+ -> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/)
+ end
end
diff --git a/spec/ruby/library/base64/decode64_spec.rb b/spec/ruby/library/base64/decode64_spec.rb
index f6cd26d788..6dd33dddfe 100644
--- a/spec/ruby/library/base64/decode64_spec.rb
+++ b/spec/ruby/library/base64/decode64_spec.rb
@@ -22,4 +22,8 @@ describe "Base64#decode64" do
it "returns a binary encoded string" do
Base64.decode64("SEk=").encoding.should == Encoding::BINARY
end
+
+ it "decodes without padding suffix ==" do
+ Base64.decode64("eyJrZXkiOnsibiI6InR0dCJ9fQ").should == "{\"key\":{\"n\":\"ttt\"}}"
+ end
end
diff --git a/spec/ruby/library/bigdecimal/exponent_spec.rb b/spec/ruby/library/bigdecimal/exponent_spec.rb
index f63c4e5798..8877147955 100644
--- a/spec/ruby/library/bigdecimal/exponent_spec.rb
+++ b/spec/ruby/library/bigdecimal/exponent_spec.rb
@@ -18,17 +18,6 @@ describe "BigDecimal#exponent" do
BigDecimal("1234567E10").exponent.should == 17
end
-# commenting this spec out after discussion with Defiler, since it seems to be an MRI bug, not a real feature
-=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 Integer" do
- BigDecimal("2E1000000000000000").exponent.should == 0
- BigDecimal("-5E-999999999999999").exponent.should == 0
- end
- end
-=end
-
it "returns 0 if self is 0" do
BigDecimal("0").exponent.should == 0
BigDecimal("+0").exponent.should == 0
diff --git a/spec/ruby/library/bigdecimal/round_spec.rb b/spec/ruby/library/bigdecimal/round_spec.rb
index 501a1a7342..bfc6dbc763 100644
--- a/spec/ruby/library/bigdecimal/round_spec.rb
+++ b/spec/ruby/library/bigdecimal/round_spec.rb
@@ -228,7 +228,15 @@ describe "BigDecimal#round" do
-> { BigDecimal('-Infinity').round(2) }.should_not raise_error(FloatDomainError)
end
- it "raise for a non-existent round mode" do
- -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode")
+ ruby_version_is ''...'3.2' do
+ it 'raise for a non-existent round mode' do
+ -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode")
+ end
+ end
+
+ ruby_version_is '3.2' do
+ it 'raise for a non-existent round mode' do
+ -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode (nonsense)")
+ end
end
end
diff --git a/spec/ruby/library/bigdecimal/to_r_spec.rb b/spec/ruby/library/bigdecimal/to_r_spec.rb
index 91d2b33993..c350beff08 100644
--- a/spec/ruby/library/bigdecimal/to_r_spec.rb
+++ b/spec/ruby/library/bigdecimal/to_r_spec.rb
@@ -13,4 +13,16 @@ describe "BigDecimal#to_r" do
r.denominator.should eql(1000000000000000000000000)
end
+ it "returns a Rational from a BigDecimal with an exponent" do
+ r = BigDecimal("1E2").to_r
+ r.numerator.should eql(100)
+ r.denominator.should eql(1)
+ end
+
+ it "returns a Rational from a negative BigDecimal with an exponent" do
+ r = BigDecimal("-1E2").to_r
+ r.numerator.should eql(-100)
+ r.denominator.should eql(1)
+ end
+
end
diff --git a/spec/ruby/library/cgi/cookie/name_spec.rb b/spec/ruby/library/cgi/cookie/name_spec.rb
index 14226824c8..326a43ade3 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 90d2c3d148..d484c7bad9 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/cmath/math/acos_spec.rb b/spec/ruby/library/cmath/math/acos_spec.rb
deleted file mode 100644
index 2e9104f835..0000000000
--- a/spec/ruby/library/cmath/math/acos_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/acos'
-
- describe "Math#acos" do
- it_behaves_like :complex_math_acos, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:acos)
- end
- end
-
- describe "Math.acos" do
- it_behaves_like :complex_math_acos, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/acosh_spec.rb b/spec/ruby/library/cmath/math/acosh_spec.rb
deleted file mode 100644
index 809112f6c0..0000000000
--- a/spec/ruby/library/cmath/math/acosh_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/acosh'
-
- describe "Math#acosh" do
- it_behaves_like :complex_math_acosh, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:acosh)
- end
- end
-
- describe "Math.acosh" do
- it_behaves_like :complex_math_acosh, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/asin_spec.rb b/spec/ruby/library/cmath/math/asin_spec.rb
deleted file mode 100644
index 4ac588ebd2..0000000000
--- a/spec/ruby/library/cmath/math/asin_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/asin'
-
- describe "Math#asin" do
- it_behaves_like :complex_math_asin, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:asin)
- end
- end
-
- describe "Math.asin" do
- it_behaves_like :complex_math_asin, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/asinh_spec.rb b/spec/ruby/library/cmath/math/asinh_spec.rb
deleted file mode 100644
index 7d8b397a04..0000000000
--- a/spec/ruby/library/cmath/math/asinh_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/asinh'
-
- describe "Math#asinh" do
- it_behaves_like :complex_math_asinh, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:asinh)
- end
- end
-
- describe "Math.asinh" do
- it_behaves_like :complex_math_asinh, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/atan2_spec.rb b/spec/ruby/library/cmath/math/atan2_spec.rb
deleted file mode 100644
index 1a9b7d7607..0000000000
--- a/spec/ruby/library/cmath/math/atan2_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/atan2'
-
- describe "Math#atan2" do
- it_behaves_like :complex_math_atan2, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:atan2)
- end
- end
-
- describe "Math.atan2" do
- it_behaves_like :complex_math_atan2, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/atan_spec.rb b/spec/ruby/library/cmath/math/atan_spec.rb
deleted file mode 100644
index b0171081a6..0000000000
--- a/spec/ruby/library/cmath/math/atan_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/atan'
-
- describe "Math#atan" do
- it_behaves_like :complex_math_atan, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:atan)
- end
- end
-
- describe "Math.atan" do
- it_behaves_like :complex_math_atan, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/atanh_spec.rb b/spec/ruby/library/cmath/math/atanh_spec.rb
deleted file mode 100644
index 6b22c6c9e4..0000000000
--- a/spec/ruby/library/cmath/math/atanh_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative '../../../fixtures/math/common'
- require_relative '../../../shared/math/atanh'
- require_relative 'shared/atanh'
-
- describe "Math#atanh" do
- it_behaves_like :math_atanh_base, :atanh, IncludesMath.new
- it_behaves_like :complex_math_atanh_complex, :atanh, IncludesMath.new
-
- it_behaves_like :math_atanh_private, :atanh, IncludesMath.new
- end
-
- describe "Math.atanh" do
- it_behaves_like :math_atanh_base, :atanh, CMath
- it_behaves_like :complex_math_atanh_complex, :atanh, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/cos_spec.rb b/spec/ruby/library/cmath/math/cos_spec.rb
deleted file mode 100644
index 3f097bcb3b..0000000000
--- a/spec/ruby/library/cmath/math/cos_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/cos'
-
- describe "Math#cos" do
- it_behaves_like :complex_math_cos, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:cos)
- end
- end
-
- describe "Math.cos" do
- it_behaves_like :complex_math_cos, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/cosh_spec.rb b/spec/ruby/library/cmath/math/cosh_spec.rb
deleted file mode 100644
index 197f899981..0000000000
--- a/spec/ruby/library/cmath/math/cosh_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/cosh'
-
- describe "Math#cosh" do
- it_behaves_like :complex_math_cosh, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:cosh)
- end
- end
-
- describe "Math.cosh" do
- it_behaves_like :complex_math_cosh, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/exp_spec.rb b/spec/ruby/library/cmath/math/exp_spec.rb
deleted file mode 100644
index eef2ec3129..0000000000
--- a/spec/ruby/library/cmath/math/exp_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/exp'
-
- describe "Math#exp" do
- it_behaves_like :complex_math_exp, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:exp)
- end
- end
-
- describe "Math.exp" do
- it_behaves_like :complex_math_exp, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/fixtures/classes.rb b/spec/ruby/library/cmath/math/fixtures/classes.rb
deleted file mode 100644
index 443c1a9ace..0000000000
--- a/spec/ruby/library/cmath/math/fixtures/classes.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'cmath'
-class IncludesMath
- include CMath
-end
diff --git a/spec/ruby/library/cmath/math/log10_spec.rb b/spec/ruby/library/cmath/math/log10_spec.rb
deleted file mode 100644
index 603bbb1457..0000000000
--- a/spec/ruby/library/cmath/math/log10_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/log10'
-
- describe "Math#log10" do
- it_behaves_like :complex_math_log10, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:log10)
- end
- end
-
- describe "Math.log10" do
- it_behaves_like :complex_math_log10, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/log_spec.rb b/spec/ruby/library/cmath/math/log_spec.rb
deleted file mode 100644
index b4da781323..0000000000
--- a/spec/ruby/library/cmath/math/log_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/log'
-
- describe "Math#log" do
- it_behaves_like :complex_math_log, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:log)
- end
- end
-
- describe "Math.log" do
- it_behaves_like :complex_math_log, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/acos.rb b/spec/ruby/library/cmath/math/shared/acos.rb
deleted file mode 100644
index 65637fa838..0000000000
--- a/spec/ruby/library/cmath/math/shared/acos.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_acos, shared: true do
- it "returns the arccosine of the passed argument" do
- @object.send(:acos, 1).should be_close(0.0, TOLERANCE)
- @object.send(:acos, 0).should be_close(1.5707963267949, TOLERANCE)
- @object.send(:acos, -1).should be_close(Math::PI,TOLERANCE)
- end
-
- it "returns the arccosine for Complex numbers" do
- @object.send(:acos, Complex(3, 4)).should be_close(Complex(0.93681246115572, -2.30550903124348), TOLERANCE)
- end
-
- it "returns the arccosine for numbers greater than 1.0 as a Complex number" do
- @object.send(:acos, 1.0001).should be_close(Complex(0.0, 0.0141420177752494), TOLERANCE)
- end
-
- it "returns the arccosine for numbers less than -1.0 as a Complex number" do
- @object.send(:acos, -1.0001).should be_close(Complex(3.14159265358979, -0.0141420177752495), TOLERANCE)
- end
-end
-
-describe :complex_math_acos_bang, shared: true do
- it "returns the arccosine of the argument" do
- @object.send(:acos!, 1).should be_close(0.0, TOLERANCE)
- @object.send(:acos!, 0).should be_close(1.5707963267949, TOLERANCE)
- @object.send(:acos!, -1).should be_close(Math::PI,TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:acos!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-
- it "raises an Errno::EDOM for numbers greater than 1.0" do
- -> { @object.send(:acos!, 1.0001) }.should raise_error(Errno::EDOM)
- end
-
- it "raises an Errno::EDOM for numbers less than -1.0" do
- -> { @object.send(:acos!, -1.0001) }.should raise_error(Errno::EDOM)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/acosh.rb b/spec/ruby/library/cmath/math/shared/acosh.rb
deleted file mode 100644
index 285b0b823f..0000000000
--- a/spec/ruby/library/cmath/math/shared/acosh.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_acosh, shared: true do
- it "returns the principle value of the inverse hyperbolic cosine of the argument" do
- @object.send(:acosh, 14.2).should be_close(3.345146999647, TOLERANCE)
- @object.send(:acosh, 1.0).should be_close(0.0, TOLERANCE)
- end
-
- it "returns the principle value of the inverse hyperbolic cosine for numbers less than 1.0 as a Complex number" do
- @object.send(:acosh, 1.0 - TOLERANCE).should be_close(Complex(0.0, 0.00774598605746135), TOLERANCE)
- @object.send(:acosh, 0).should be_close(Complex(0.0, 1.5707963267949), TOLERANCE)
- @object.send(:acosh, -1.0).should be_close(Complex(0.0, 3.14159265358979), TOLERANCE)
- end
-
- it "returns the principle value of the inverse hyperbolic cosine for Complex numbers" do
- @object.send(:acosh, Complex(3, 4))
- @object.send(:acosh, Complex(3, 4)).imaginary.should be_close(0.93681246115572, TOLERANCE)
- @object.send(:acosh, Complex(3, 4)).real.should be_close(2.305509031243477, TOLERANCE)
- end
-end
-
-describe :complex_math_acosh_bang, shared: true do
- it "returns the principle value of the inverse hyperbolic cosine of the argument" do
- @object.send(:acosh!, 14.2).should be_close(3.345146999647, TOLERANCE)
- @object.send(:acosh!, 1.0).should be_close(0.0, TOLERANCE)
- end
-
- it "raises Errno::EDOM for numbers less than 1.0" do
- -> { @object.send(:acosh!, 1.0 - TOLERANCE) }.should raise_error(Errno::EDOM)
- -> { @object.send(:acosh!, 0) }.should raise_error(Errno::EDOM)
- -> { @object.send(:acosh!, -1.0) }.should raise_error(Errno::EDOM)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:acosh!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/asin.rb b/spec/ruby/library/cmath/math/shared/asin.rb
deleted file mode 100644
index 91fed7aa06..0000000000
--- a/spec/ruby/library/cmath/math/shared/asin.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_asin, shared: true do
- it "returns the arcsine of the argument" do
- @object.send(:asin, 1).should be_close(Math::PI/2, TOLERANCE)
- @object.send(:asin, 0).should be_close(0.0, TOLERANCE)
- @object.send(:asin, -1).should be_close(-Math::PI/2, TOLERANCE)
- @object.send(:asin, 0.25).should be_close(0.252680255142079, TOLERANCE)
- @object.send(:asin, 0.50).should be_close(0.523598775598299, TOLERANCE)
- @object.send(:asin, 0.75).should be_close(0.8480620789814816,TOLERANCE)
- end
-
- it "returns the arcsine for Complex numbers" do
- @object.send(:asin, Complex(3, 4)).should be_close(Complex(0.633983865639174, 2.30550903124347), TOLERANCE)
- end
-
- it "returns a Complex number when the argument is greater than 1.0" do
- @object.send(:asin, 1.0001).should be_close(Complex(1.5707963267949, -0.0141420177752494), TOLERANCE)
- end
-
- it "returns a Complex number when the argument is less than -1.0" do
- @object.send(:asin, -1.0001).should be_close(Complex(-1.5707963267949, 0.0141420177752494), TOLERANCE)
- end
-end
-
-describe :complex_math_asin_bang, shared: true do
- it "returns the arcsine of the argument" do
- @object.send(:asin!, 1).should be_close(Math::PI/2, TOLERANCE)
- @object.send(:asin!, 0).should be_close(0.0, TOLERANCE)
- @object.send(:asin!, -1).should be_close(-Math::PI/2, TOLERANCE)
- @object.send(:asin!, 0.25).should be_close(0.252680255142079, TOLERANCE)
- @object.send(:asin!, 0.50).should be_close(0.523598775598299, TOLERANCE)
- @object.send(:asin!, 0.75).should be_close(0.8480620789814816,TOLERANCE)
- end
-
- it "raises an Errno::EDOM if the argument is greater than 1.0" do
- -> { @object.send(:asin!, 1.0001) }.should raise_error( Errno::EDOM)
- end
-
- it "raises an Errno::EDOM if the argument is less than -1.0" do
- -> { @object.send(:asin!, -1.0001) }.should raise_error( Errno::EDOM)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:asin!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/asinh.rb b/spec/ruby/library/cmath/math/shared/asinh.rb
deleted file mode 100644
index b4ddd3a22e..0000000000
--- a/spec/ruby/library/cmath/math/shared/asinh.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_asinh, shared: true do
- it "returns the inverse hyperbolic sin of the argument" do
- @object.send(:asinh, 1.5).should be_close(1.19476321728711, TOLERANCE)
- @object.send(:asinh, -2.97).should be_close(-1.8089166921397, TOLERANCE)
- @object.send(:asinh, 0.0).should == 0.0
- @object.send(:asinh, -0.0).should == -0.0
- @object.send(:asinh, 1.05367e-08).should be_close(1.05367e-08, TOLERANCE)
- @object.send(:asinh, -1.05367e-08).should be_close(-1.05367e-08, TOLERANCE)
- end
-
- it "returns the inverse hyperbolic sin for Complex numbers" do
- @object.send(:asinh, Complex(3, 4)).should be_close(Complex(2.29991404087927, 0.917616853351479), TOLERANCE)
- @object.send(:asinh, Complex(3.5, -4)).should be_close(Complex(2.36263337274419, -0.843166327537659), TOLERANCE)
- end
-end
-
-describe :complex_math_asinh_bang, shared: true do
- it "returns the inverse hyperbolic sin of the argument" do
- @object.send(:asinh!, 1.5).should be_close(1.19476321728711, TOLERANCE)
- @object.send(:asinh!, -2.97).should be_close(-1.8089166921397, TOLERANCE)
- @object.send(:asinh!, 0.0).should == 0.0
- @object.send(:asinh!, -0.0).should == -0.0
- @object.send(:asinh!, 1.05367e-08).should be_close(1.05367e-08, TOLERANCE)
- @object.send(:asinh!, -1.05367e-08).should be_close(-1.05367e-08, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:asinh!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/atan.rb b/spec/ruby/library/cmath/math/shared/atan.rb
deleted file mode 100644
index 63a496e841..0000000000
--- a/spec/ruby/library/cmath/math/shared/atan.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_atan, shared: true do
- it "returns the arctangent of the argument" do
- @object.send(:atan, 1).should be_close(Math::PI/4, TOLERANCE)
- @object.send(:atan, 0).should be_close(0.0, TOLERANCE)
- @object.send(:atan, -1).should be_close(-Math::PI/4, TOLERANCE)
- @object.send(:atan, 0.25).should be_close(0.244978663126864, TOLERANCE)
- @object.send(:atan, 0.50).should be_close(0.463647609000806, TOLERANCE)
- @object.send(:atan, 0.75).should be_close(0.643501108793284, TOLERANCE)
- end
-
- it "returns the arctangent for Complex numbers" do
- @object.send(:atan, Complex(3, 4)).should be_close(Complex(1.44830699523146, 0.158997191679999), TOLERANCE)
- @object.send(:atan, Complex(3.5, -4)).should be_close(Complex(1.44507428165589, -0.140323762363786), TOLERANCE)
- end
-end
-
-describe :complex_math_atan_bang, shared: true do
- it "returns the arctangent of the argument" do
- @object.send(:atan!, 1).should be_close(Math::PI/4, TOLERANCE)
- @object.send(:atan!, 0).should be_close(0.0, TOLERANCE)
- @object.send(:atan!, -1).should be_close(-Math::PI/4, TOLERANCE)
- @object.send(:atan!, 0.25).should be_close(0.244978663126864, TOLERANCE)
- @object.send(:atan!, 0.50).should be_close(0.463647609000806, TOLERANCE)
- @object.send(:atan!, 0.75).should be_close(0.643501108793284, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:atan!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/atan2.rb b/spec/ruby/library/cmath/math/shared/atan2.rb
deleted file mode 100644
index 6d89423924..0000000000
--- a/spec/ruby/library/cmath/math/shared/atan2.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_atan2, shared: true do
- it "returns the arc tangent of the passed arguments" do
- @object.send(:atan2, 4.2, 0.3).should be_close(1.49948886200961, TOLERANCE)
- @object.send(:atan2, 0.0, 1.0).should be_close(0.0, TOLERANCE)
- @object.send(:atan2, -9.1, 3.2).should be_close(-1.23265379809025, TOLERANCE)
- @object.send(:atan2, 7.22, -3.3).should be_close(1.99950888779256, TOLERANCE)
- end
-
- it "returns the arc tangent for two Complex numbers" do
- CMath.atan2(Complex(3, 4), Complex(3.5, -4)).should be_close(Complex(-0.641757436698881, 1.10829873031207), TOLERANCE)
- end
-
- it "returns the arc tangent for Complex and real numbers" do
- CMath.atan2(Complex(3, 4), -7).should be_close(Complex(2.61576754731561, -0.494290673139855), TOLERANCE)
- CMath.atan2(5, Complex(3.5, -4)).should be_close(Complex(0.739102348493673, 0.487821626522923), TOLERANCE)
- end
-end
-
-describe :complex_math_atan2_bang, shared: true do
- it "returns the arc tangent of the passed arguments" do
- @object.send(:atan2!, 4.2, 0.3).should be_close(1.49948886200961, TOLERANCE)
- @object.send(:atan2!, 0.0, 1.0).should be_close(0.0, TOLERANCE)
- @object.send(:atan2!, -9.1, 3.2).should be_close(-1.23265379809025, TOLERANCE)
- @object.send(:atan2!, 7.22, -3.3).should be_close(1.99950888779256, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:atan2!, Complex(4, 5), Complex(4, 5)) }.should raise_error(TypeError)
- -> { @object.send(:atan2!, 4, Complex(4, 5)) }.should raise_error(TypeError)
- -> { @object.send(:atan2!, Complex(4, 5), 5) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/atanh.rb b/spec/ruby/library/cmath/math/shared/atanh.rb
deleted file mode 100644
index ae80e61bec..0000000000
--- a/spec/ruby/library/cmath/math/shared/atanh.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_atanh_complex, shared: true do
- it "returns the inverse hyperbolic tangent as a Complex number for arguments greater than 1.0" do
- value = Complex(18.36840028483855, 1.5707963267948966)
- @object.send(@method, 1.0 + Float::EPSILON).should be_close(value, TOLERANCE)
-
- value = Complex(0.100335347731076, 1.5707963267949)
- @object.send(@method, 10).should be_close(value, TOLERANCE)
- end
-
- it "returns the inverse hyperbolic tangent as a Complex number for arguments greater than 1.0" do
- value = Complex(-18.36840028483855, 1.5707963267948966)
- @object.send(@method, -1.0 - Float::EPSILON).should be_close(value, TOLERANCE)
-
- value = Complex(0.100335347731076, 1.5707963267949)
- @object.send(@method, 10).should be_close(value, TOLERANCE)
- end
-
- it "returns the inverse hyperbolic tangent for Complex numbers" do
- value = Complex(0.117500907311434, 1.40992104959658)
- @object.send(@method, Complex(3, 4)).should be_close(value, TOLERANCE)
- end
-end
-
-describe :complex_math_atanh_no_complex, shared: true do
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:atanh!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/cos.rb b/spec/ruby/library/cmath/math/shared/cos.rb
deleted file mode 100644
index 31cb5ab1e5..0000000000
--- a/spec/ruby/library/cmath/math/shared/cos.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_cos, shared: true do
- it "returns the cosine of the argument expressed in radians" do
- @object.send(:cos, CMath::PI).should be_close(-1.0, TOLERANCE)
- @object.send(:cos, 0).should be_close(1.0, TOLERANCE)
- @object.send(:cos, CMath::PI/2).should be_close(0.0, TOLERANCE)
- @object.send(:cos, 3*Math::PI/2).should be_close(0.0, TOLERANCE)
- @object.send(:cos, 2*Math::PI).should be_close(1.0, TOLERANCE)
- end
-
- it "returns the cosine for Complex numbers" do
- @object.send(:cos, Complex(0, CMath::PI)).should be_close(Complex(11.5919532755215, 0.0), TOLERANCE)
- @object.send(:cos, Complex(3, 4)).should be_close(Complex(-27.0349456030742, -3.85115333481178), TOLERANCE)
- end
-end
-
-describe :complex_math_cos_bang, shared: true do
- it "returns the cosine of the argument expressed in radians" do
- @object.send(:cos!, CMath::PI).should be_close(-1.0, TOLERANCE)
- @object.send(:cos!, 0).should be_close(1.0, TOLERANCE)
- @object.send(:cos!, CMath::PI/2).should be_close(0.0, TOLERANCE)
- @object.send(:cos!, 3*Math::PI/2).should be_close(0.0, TOLERANCE)
- @object.send(:cos!, 2*Math::PI).should be_close(1.0, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:cos!, Complex(3, 4)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/cosh.rb b/spec/ruby/library/cmath/math/shared/cosh.rb
deleted file mode 100644
index 7cf561c985..0000000000
--- a/spec/ruby/library/cmath/math/shared/cosh.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_cosh, shared: true do
- it "returns the hyperbolic cosine of the passed argument" do
- @object.send(:cosh, 0.0).should == 1.0
- @object.send(:cosh, -0.0).should == 1.0
- @object.send(:cosh, 1.5).should be_close(2.35240961524325, TOLERANCE)
- @object.send(:cosh, -2.99).should be_close(9.96798496414416, TOLERANCE)
- end
-
- it "returns the hyperbolic cosine for Complex numbers" do
- @object.send(:cosh, Complex(0, CMath::PI)).should be_close(Complex(-1.0, 0.0), TOLERANCE)
- @object.send(:cosh, Complex(3, 4)).should be_close(Complex(-6.58066304055116, -7.58155274274654), TOLERANCE)
- end
-end
-
-describe :complex_math_cosh_bang, shared: true do
- it "returns the hyperbolic cosine of the passed argument" do
- @object.send(:cosh!, 0.0).should == 1.0
- @object.send(:cosh!, -0.0).should == 1.0
- @object.send(:cosh!, 1.5).should be_close(2.35240961524325, TOLERANCE)
- @object.send(:cosh!, -2.99).should be_close(9.96798496414416, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:cosh!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/exp.rb b/spec/ruby/library/cmath/math/shared/exp.rb
deleted file mode 100644
index 6715ac63d3..0000000000
--- a/spec/ruby/library/cmath/math/shared/exp.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_exp, shared: true do
- it "returns the base-e exponential of the passed argument" do
- @object.send(:exp, 0.0).should == 1.0
- @object.send(:exp, -0.0).should == 1.0
- @object.send(:exp, -1.8).should be_close(0.165298888221587, TOLERANCE)
- @object.send(:exp, 1.25).should be_close(3.49034295746184, TOLERANCE)
- end
-
- it "returns the base-e exponential for Complex numbers" do
- @object.send(:exp, Complex(0, 0)).should == Complex(1.0, 0.0)
- @object.send(:exp, Complex(1, 3)).should be_close(Complex(-2.69107861381979, 0.383603953541131), TOLERANCE)
- end
-end
-
-describe :complex_math_exp_bang, shared: true do
- it "returns the base-e exponential of the passed argument" do
- @object.send(:exp!, 0.0).should == 1.0
- @object.send(:exp!, -0.0).should == 1.0
- @object.send(:exp!, -1.8).should be_close(0.165298888221587, TOLERANCE)
- @object.send(:exp!, 1.25).should be_close(3.49034295746184, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:exp!, Complex(1, 3)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/log.rb b/spec/ruby/library/cmath/math/shared/log.rb
deleted file mode 100644
index 4b23e8c5f2..0000000000
--- a/spec/ruby/library/cmath/math/shared/log.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_log, shared: true do
- it "returns the natural logarithm of the passed argument" do
- @object.send(:log, 0.0001).should be_close(-9.21034037197618, TOLERANCE)
- @object.send(:log, 0.000000000001e-15).should be_close(-62.1697975108392, TOLERANCE)
- @object.send(:log, 1).should be_close(0.0, TOLERANCE)
- @object.send(:log, 10).should be_close( 2.30258509299405, TOLERANCE)
- @object.send(:log, 10e15).should be_close(36.8413614879047, TOLERANCE)
- end
-
- it "returns the natural logarithm for Complex numbers" do
- @object.send(:log, Complex(3, 4)).should be_close(Complex(1.6094379124341, 0.927295218001612), TOLERANCE)
- @object.send(:log, Complex(-3, 4)).should be_close(Complex(1.6094379124341, 2.21429743558818), TOLERANCE)
- end
-
- it "returns the natural logarithm for negative numbers as a Complex number" do
- @object.send(:log, -10).should be_close(Complex(2.30258509299405, 3.14159265358979), TOLERANCE)
- @object.send(:log, -20).should be_close(Complex(2.99573227355399, 3.14159265358979), TOLERANCE)
- end
-end
-
-describe :complex_math_log_bang, shared: true do
- it "returns the natural logarithm of the argument" do
- @object.send(:log!, 0.0001).should be_close(-9.21034037197618, TOLERANCE)
- @object.send(:log!, 0.000000000001e-15).should be_close(-62.1697975108392, TOLERANCE)
- @object.send(:log!, 1).should be_close(0.0, TOLERANCE)
- @object.send(:log!, 10).should be_close( 2.30258509299405, TOLERANCE)
- @object.send(:log!, 10e15).should be_close(36.8413614879047, TOLERANCE)
- end
-
- it "raises an Errno::EDOM if the argument is less than 0" do
- -> { @object.send(:log!, -10) }.should raise_error(Errno::EDOM)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:log!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/log10.rb b/spec/ruby/library/cmath/math/shared/log10.rb
deleted file mode 100644
index f49934d958..0000000000
--- a/spec/ruby/library/cmath/math/shared/log10.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_log10, shared: true do
- it "returns the base-10 logarithm of the passed argument" do
- @object.send(:log10, 0.0001).should be_close(-4.0, TOLERANCE)
- @object.send(:log10, 0.000000000001e-15).should be_close(-27.0, TOLERANCE)
- @object.send(:log10, 1).should be_close(0.0, TOLERANCE)
- @object.send(:log10, 10).should be_close(1.0, TOLERANCE)
- @object.send(:log10, 10e15).should be_close(16.0, TOLERANCE)
- end
-
- it "returns the base-10 logarithm for Complex numbers" do
- @object.send(:log10, Complex(3, 4)).should be_close(Complex(0.698970004336019, 0.402719196273373), TOLERANCE)
- @object.send(:log10, Complex(-3, 4)).should be_close(Complex(0.698970004336019, 0.961657157568468), TOLERANCE)
- end
-
- # BUG: does not work correctly, because Math#log10
- # does not check for negative values
- #it "returns the base-10 logarithm for negative numbers as a Complex number" do
- # @object.send(:log10, -10).should be_close(Complex(2.30258509299405, 3.14159265358979), TOLERANCE)
- # @object.send(:log10, -20).should be_close(Complex(2.99573227355399, 3.14159265358979), TOLERANCE)
- #end
-end
-
-describe :complex_math_log10_bang, shared: true do
- it "returns the base-10 logarithm of the argument" do
- @object.send(:log10!, 0.0001).should be_close(-4.0, TOLERANCE)
- @object.send(:log10!, 0.000000000001e-15).should be_close(-27.0, TOLERANCE)
- @object.send(:log10!, 1).should be_close(0.0, TOLERANCE)
- @object.send(:log10!, 10).should be_close(1.0, TOLERANCE)
- @object.send(:log10!, 10e15).should be_close(16.0, TOLERANCE)
- end
-
- it "raises an Errno::EDOM when the passed argument is negative" do
- -> { @object.send(:log10!, -10) }.should raise_error(Errno::EDOM)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:log10!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/sin.rb b/spec/ruby/library/cmath/math/shared/sin.rb
deleted file mode 100644
index 1cb1b29cda..0000000000
--- a/spec/ruby/library/cmath/math/shared/sin.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_sin, shared: true do
- it "returns the sine of the passed argument expressed in radians" do
- @object.send(:sin, CMath::PI).should be_close(0.0, TOLERANCE)
- @object.send(:sin, 0).should be_close(0.0, TOLERANCE)
- @object.send(:sin, CMath::PI/2).should be_close(1.0, TOLERANCE)
- @object.send(:sin, 3*Math::PI/2).should be_close(-1.0, TOLERANCE)
- @object.send(:sin, 2*Math::PI).should be_close(0.0, TOLERANCE)
- end
-
- it "returns the sine for Complex numbers" do
- @object.send(:sin, Complex(0, CMath::PI)).should be_close(Complex(0.0, 11.5487393572577), TOLERANCE)
- @object.send(:sin, Complex(3, 4)).should be_close(Complex(3.85373803791938, -27.0168132580039), TOLERANCE)
- end
-end
-
-describe :complex_math_sin_bang, shared: true do
- it "returns the sine of the passed argument expressed in radians" do
- @object.send(:sin!, CMath::PI).should be_close(0.0, TOLERANCE)
- @object.send(:sin!, 0).should be_close(0.0, TOLERANCE)
- @object.send(:sin!, CMath::PI/2).should be_close(1.0, TOLERANCE)
- @object.send(:sin!, 3*Math::PI/2).should be_close(-1.0, TOLERANCE)
- @object.send(:sin!, 2*Math::PI).should be_close(0.0, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:sin!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/sinh.rb b/spec/ruby/library/cmath/math/shared/sinh.rb
deleted file mode 100644
index de80a376da..0000000000
--- a/spec/ruby/library/cmath/math/shared/sinh.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_sinh, shared: true do
- it "returns the hyperbolic sin of the argument" do
- @object.send(:sinh, 0.0).should == 0.0
- @object.send(:sinh, -0.0).should == 0.0
- @object.send(:sinh, 1.5).should be_close(2.12927945509482, TOLERANCE)
- @object.send(:sinh, -2.8).should be_close(-8.19191835423591, TOLERANCE)
- end
-
- it "returns the hyperbolic sin for Complex numbers" do
- @object.send(:sinh, Complex(0, CMath::PI)).should be_close(Complex(-0.0, 1.22464679914735e-16), TOLERANCE)
- @object.send(:sinh, Complex(3, 4)).should be_close(Complex(-6.548120040911, -7.61923172032141), TOLERANCE)
- end
-end
-
-describe :complex_math_sinh_bang, shared: true do
- it "returns the hyperbolic sin of the argument" do
- @object.send(:sinh!, 0.0).should == 0.0
- @object.send(:sinh!, -0.0).should == 0.0
- @object.send(:sinh!, 1.5).should be_close(2.12927945509482, TOLERANCE)
- @object.send(:sinh!, -2.8).should be_close(-8.19191835423591, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:sinh!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/sqrt.rb b/spec/ruby/library/cmath/math/shared/sqrt.rb
deleted file mode 100644
index 23b1ba48ff..0000000000
--- a/spec/ruby/library/cmath/math/shared/sqrt.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_sqrt, shared: true do
- it "returns the square root for positive numbers" do
- @object.send(:sqrt, 4).should == 2
- @object.send(:sqrt, 19.36).should == 4.4
- end
-
- it "returns the square root for negative numbers" do
- @object.send(:sqrt, -4).should == Complex(0, 2.0)
- @object.send(:sqrt, -19.36).should == Complex(0, 4.4)
- end
-
- it "returns the square root for Complex numbers" do
- @object.send(:sqrt, Complex(4, 5)).should be_close(Complex(2.2806933416653, 1.09615788950152), TOLERANCE)
- @object.send(:sqrt, Complex(4, -5)).should be_close(Complex(2.2806933416653, -1.09615788950152), TOLERANCE)
- end
-end
-
-describe :complex_math_sqrt_bang, shared: true do
- it "returns the square root for positive numbers" do
- @object.send(:sqrt!, 4).should == 2
- @object.send(:sqrt!, 19.36).should == 4.4
- end
-
- it "raises Errno::EDOM when the passed argument is negative" do
- -> { @object.send(:sqrt!, -4) }.should raise_error(Errno::EDOM)
- -> { @object.send(:sqrt!, -19.36) }.should raise_error(Errno::EDOM)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:sqrt!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/tan.rb b/spec/ruby/library/cmath/math/shared/tan.rb
deleted file mode 100644
index 9022c84fc9..0000000000
--- a/spec/ruby/library/cmath/math/shared/tan.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_tan, shared: true do
- it "returns the tangent of the argument" do
- @object.send(:tan, 0.0).should == 0.0
- @object.send(:tan, -0.0).should == -0.0
- @object.send(:tan, 4.22).should be_close(1.86406937682395, TOLERANCE)
- @object.send(:tan, -9.65).should be_close(-0.229109052606441, TOLERANCE)
- end
-
- it "returns the tangent for Complex numbers" do
- @object.send(:tan, Complex(0, CMath::PI)).should be_close(Complex(0.0, 0.99627207622075), TOLERANCE)
- @object.send(:tan, Complex(3, 4)).should be_close(Complex(-0.000187346204629452, 0.999355987381473), TOLERANCE)
- end
-end
-
-describe :complex_math_tan_bang, shared: true do
- it "returns the tangent of the argument" do
- @object.send(:tan!, 0.0).should == 0.0
- @object.send(:tan!, -0.0).should == -0.0
- @object.send(:tan!, 4.22).should be_close(1.86406937682395, TOLERANCE)
- @object.send(:tan!, -9.65).should be_close(-0.229109052606441, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:tan!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/shared/tanh.rb b/spec/ruby/library/cmath/math/shared/tanh.rb
deleted file mode 100644
index f2c9a5abb1..0000000000
--- a/spec/ruby/library/cmath/math/shared/tanh.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require_relative '../fixtures/classes'
-
-describe :complex_math_tanh, shared: true do
- it "returns the hyperbolic tangent of the argument" do
- @object.send(:tanh, 0.0).should == 0.0
- @object.send(:tanh, -0.0).should == -0.0
- @object.send(:tanh, infinity_value).should == 1.0
- @object.send(:tanh, -infinity_value).should == -1.0
- @object.send(:tanh, 2.5).should be_close(0.98661429815143, TOLERANCE)
- @object.send(:tanh, -4.892).should be_close(-0.999887314427707, TOLERANCE)
- end
-
- it "returns the hyperbolic tangent for Complex numbers" do
- @object.send(:tanh, Complex(0, CMath::PI)).should be_close(Complex(0.0, -1.22464679914735e-16), TOLERANCE)
- @object.send(:tanh, Complex(3, 4)).should be_close(Complex(1.00070953606723, 0.00490825806749599), TOLERANCE)
- end
-end
-
-describe :complex_math_tanh_bang, shared: true do
- it "returns the hyperbolic tangent of the argument" do
- @object.send(:tanh!, 0.0).should == 0.0
- @object.send(:tanh!, -0.0).should == -0.0
- @object.send(:tanh!, infinity_value).should == 1.0
- @object.send(:tanh!, -infinity_value).should == -1.0
- @object.send(:tanh!, 2.5).should be_close(0.98661429815143, TOLERANCE)
- @object.send(:tanh!, -4.892).should be_close(-0.999887314427707, TOLERANCE)
- end
-
- it "raises a TypeError when passed a Complex number" do
- -> { @object.send(:tanh!, Complex(4, 5)) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/library/cmath/math/sin_spec.rb b/spec/ruby/library/cmath/math/sin_spec.rb
deleted file mode 100644
index b7a219fbbd..0000000000
--- a/spec/ruby/library/cmath/math/sin_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/sin'
-
- describe "Math#sin" do
- it_behaves_like :complex_math_sin, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:sin)
- end
- end
-
- describe "Math.sin" do
- it_behaves_like :complex_math_sin, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/sinh_spec.rb b/spec/ruby/library/cmath/math/sinh_spec.rb
deleted file mode 100644
index c6e6a3baf4..0000000000
--- a/spec/ruby/library/cmath/math/sinh_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/sinh'
-
- describe "Math#sinh" do
- it_behaves_like :complex_math_sinh, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:sinh)
- end
- end
-
- describe "Math.sinh" do
- it_behaves_like :complex_math_sinh, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/sqrt_spec.rb b/spec/ruby/library/cmath/math/sqrt_spec.rb
deleted file mode 100644
index 421824f99c..0000000000
--- a/spec/ruby/library/cmath/math/sqrt_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/sqrt'
-
- describe "Math#sqrt" do
- it_behaves_like :complex_math_sqrt, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:sqrt)
- end
- end
-
- describe "Math.sqrt" do
- it_behaves_like :complex_math_sqrt, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/tan_spec.rb b/spec/ruby/library/cmath/math/tan_spec.rb
deleted file mode 100644
index e2acdd8091..0000000000
--- a/spec/ruby/library/cmath/math/tan_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/tan'
-
- describe "Math#tan" do
- it_behaves_like :complex_math_tan, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:tan)
- end
- end
-
- describe "Math.tan" do
- it_behaves_like :complex_math_tan, :_, CMath
- end
-end
diff --git a/spec/ruby/library/cmath/math/tanh_spec.rb b/spec/ruby/library/cmath/math/tanh_spec.rb
deleted file mode 100644
index 94da20cd51..0000000000
--- a/spec/ruby/library/cmath/math/tanh_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require 'complex'
- require_relative 'shared/tanh'
-
- describe "Math#tanh" do
- it_behaves_like :complex_math_tanh, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:tanh)
- end
- end
-
- describe "Math.tanh" do
- it_behaves_like :complex_math_tanh, :_, CMath
- end
-end
diff --git a/spec/ruby/library/coverage/result_spec.rb b/spec/ruby/library/coverage/result_spec.rb
index 6cf5be1346..4bcce00cd7 100644
--- a/spec/ruby/library/coverage/result_spec.rb
+++ b/spec/ruby/library/coverage/result_spec.rb
@@ -65,12 +65,25 @@ describe 'Coverage.result' do
result.should == {}
end
- it 'second Coverage.start does nothing' do
- Coverage.start
- require @config_file.chomp('.rb')
- result = Coverage.result
+ ruby_version_is ''...'3.1' do
+ it 'second Coverage.start does nothing' do
+ Coverage.start
+ require @config_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == { @config_file => [1, 1, 1] }
+ end
+ end
- result.should == { @config_file => [1, 1, 1] }
+ ruby_version_is '3.1' do
+ it 'second Coverage.start give exception' do
+ Coverage.start
+ -> {
+ require @config_file.chomp('.rb')
+ }.should raise_error(RuntimeError, 'coverage measurement is already setup')
+ ensure
+ Coverage.result
+ end
end
it 'does not include the file starting coverage since it is not tracked' do
@@ -78,15 +91,51 @@ describe 'Coverage.result' do
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
+ ruby_version_is '3.1'...'3.2' do
+ it 'returns the correct results when eval is used' do
+ Coverage.start
+ require @eval_code_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == {
+ @eval_code_file => [
+ 1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1
+ ]
+ }
+ end
+ end
- result.should == {
- @eval_code_file => [
- 1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1
- ]
- }
+ ruby_version_is '3.2' do
+ it 'indicates support for different features' do
+ Coverage.supported?(:lines).should == true
+ end
+
+ it 'returns the correct results when eval coverage is enabled' do
+ Coverage.supported?(:eval).should == true
+
+ Coverage.start(lines: true, eval: true)
+ require @eval_code_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == {
+ @eval_code_file => {
+ lines: [1, nil, 1, nil, 1, 1, nil, nil, nil, nil, 1]
+ }
+ }
+ end
+
+ it 'returns the correct results when eval coverage is enabled' do
+ Coverage.supported?(:eval).should == true
+
+ Coverage.start(lines: true, eval: false)
+ require @eval_code_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == {
+ @eval_code_file => {
+ lines: [1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1]
+ }
+ }
+ end
end
end
diff --git a/spec/ruby/library/coverage/running_spec.rb b/spec/ruby/library/coverage/running_spec.rb
new file mode 100644
index 0000000000..745270164f
--- /dev/null
+++ b/spec/ruby/library/coverage/running_spec.rb
@@ -0,0 +1,20 @@
+require_relative '../../spec_helper'
+require 'coverage'
+
+describe 'Coverage.running?' do
+ it "returns false if coverage is not started" do
+ Coverage.running?.should == false
+ end
+
+ it "returns true if coverage is started" do
+ Coverage.start
+ Coverage.running?.should == true
+ Coverage.result
+ end
+
+ it "returns false if coverage was started and stopped" do
+ Coverage.start
+ Coverage.result
+ Coverage.running?.should == false
+ end
+end \ No newline at end of file
diff --git a/spec/ruby/library/coverage/start_spec.rb b/spec/ruby/library/coverage/start_spec.rb
index ddfad8b47c..a993abbf4e 100644
--- a/spec/ruby/library/coverage/start_spec.rb
+++ b/spec/ruby/library/coverage/start_spec.rb
@@ -2,5 +2,11 @@ require_relative '../../spec_helper'
require 'coverage'
describe 'Coverage.start' do
- it 'needs to be reviewed for spec completeness'
+ ruby_version_is '3.2' do
+ it "can measure coverage within eval" do
+ Coverage.start(lines: true, eval: true)
+ eval("Object.new\n"*3, binding, "test.rb", 1)
+ Coverage.result["test.rb"].should == {lines: [1, 1, 1]}
+ end
+ end
end
diff --git a/spec/ruby/library/date/civil_spec.rb b/spec/ruby/library/date/civil_spec.rb
index f3537c2f84..1c780fce56 100644
--- a/spec/ruby/library/date/civil_spec.rb
+++ b/spec/ruby/library/date/civil_spec.rb
@@ -2,11 +2,6 @@ require_relative '../../spec_helper'
require_relative 'shared/civil'
require 'date'
-describe "Date#civil" do
- it_behaves_like :date_civil, :civil
-end
-
-
describe "Date.civil" do
- it "needs to be reviewed for spec completeness"
+ it_behaves_like :date_civil, :civil
end
diff --git a/spec/ruby/library/date/iso8601_spec.rb b/spec/ruby/library/date/iso8601_spec.rb
index 2c698db514..a29652014e 100644
--- a/spec/ruby/library/date/iso8601_spec.rb
+++ b/spec/ruby/library/date/iso8601_spec.rb
@@ -17,20 +17,11 @@ describe "Date.iso8601" do
d.should == Date.civil(-4712, 1, 1)
end
- it "parses a Symbol into a Date object" do
- d = Date.iso8601(:'2015-10-15')
- d.should == Date.civil(2015, 10, 15)
- end
-
it "parses a StringSubclass into a Date object" do
d = Date.iso8601(Class.new(String).new("-4712-01-01"))
d.should == Date.civil(-4712, 1, 1)
end
- it "raises an ArgumentError when passed a Symbol without a valid Date" do
- -> { Date.iso8601(:test) }.should raise_error(ArgumentError)
- end
-
it "raises a TypeError when passed an Object" do
-> { Date.iso8601(Object.new) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/library/date/parse_spec.rb b/spec/ruby/library/date/parse_spec.rb
index ef72ba3f4e..bfbe86fbac 100644
--- a/spec/ruby/library/date/parse_spec.rb
+++ b/spec/ruby/library/date/parse_spec.rb
@@ -67,7 +67,7 @@ describe "Date#parse" do
it "raises a TypeError trying to parse non-String-like object" do
-> { Date.parse(1) }.should raise_error(TypeError)
- -> { Date.parse(:invalid) }.should raise_error(TypeError)
+ -> { Date.parse([]) }.should raise_error(TypeError)
end
it "coerces using to_str" do
diff --git a/spec/ruby/library/date/shared/valid_jd.rb b/spec/ruby/library/date/shared/valid_jd.rb
index f6ca3f579d..e474dfb450 100644
--- a/spec/ruby/library/date/shared/valid_jd.rb
+++ b/spec/ruby/library/date/shared/valid_jd.rb
@@ -10,23 +10,11 @@ describe :date_valid_jd?, shared: true do
Date.send(@method, nil).should be_false
end
- ruby_version_is ''...'2.7' do
- it "returns true if passed symbol" do
- Date.send(@method, :number).should be_true
- end
-
- it "returns true if passed false" do
- Date.send(@method, false).should be_true
- end
+ it "returns false if passed symbol" do
+ Date.send(@method, :number).should be_false
end
- ruby_version_is '2.7' do
- it "returns false if passed symbol" do
- Date.send(@method, :number).should be_false
- end
-
- it "returns false if passed false" do
- Date.send(@method, false).should be_false
- end
+ it "returns false if passed false" do
+ Date.send(@method, false).should be_false
end
end
diff --git a/spec/ruby/library/date/strftime_spec.rb b/spec/ruby/library/date/strftime_spec.rb
index 9d298e42e6..8b1ebe061c 100644
--- a/spec/ruby/library/date/strftime_spec.rb
+++ b/spec/ruby/library/date/strftime_spec.rb
@@ -22,9 +22,18 @@ describe "Date#strftime" do
end
# %v is %e-%b-%Y for Date/DateTime
- it "should be able to show the commercial week" do
- @date.strftime("%v").should == " 9-Apr-2000"
- @date.strftime("%v").should == @date.strftime('%e-%b-%Y')
+ ruby_version_is ""..."3.1" do
+ it "should be able to show the commercial week" do
+ @date.strftime("%v").should == " 9-Apr-2000"
+ @date.strftime("%v").should == @date.strftime('%e-%b-%Y')
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "should be able to show the commercial week" do
+ @date.strftime("%v").should == " 9-APR-2000"
+ @date.strftime("%v").should != @date.strftime('%e-%b-%Y')
+ end
end
# additional conversion specifiers only in Date/DateTime
diff --git a/spec/ruby/library/datetime/strftime_spec.rb b/spec/ruby/library/datetime/strftime_spec.rb
index cf07bbf9de..725bcafb0d 100644
--- a/spec/ruby/library/datetime/strftime_spec.rb
+++ b/spec/ruby/library/datetime/strftime_spec.rb
@@ -33,9 +33,18 @@ describe "DateTime#strftime" do
end
# %v is %e-%b-%Y for Date/DateTime
- it "should be able to show the commercial week" do
- @time.strftime("%v").should == " 3-Feb-2001"
- @time.strftime("%v").should == @time.strftime('%e-%b-%Y')
+ ruby_version_is ""..."3.1" do
+ it "should be able to show the commercial week" do
+ @time.strftime("%v").should == " 3-Feb-2001"
+ @time.strftime("%v").should == @time.strftime('%e-%b-%Y')
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "should be able to show the commercial week" do
+ @time.strftime("%v").should == " 3-FEB-2001"
+ @time.strftime("%v").should != @time.strftime('%e-%b-%Y')
+ end
end
# additional conversion specifiers only in Date/DateTime
diff --git a/spec/ruby/library/datetime/to_time_spec.rb b/spec/ruby/library/datetime/to_time_spec.rb
index a11b6e30e1..95eca864da 100644
--- a/spec/ruby/library/datetime/to_time_spec.rb
+++ b/spec/ruby/library/datetime/to_time_spec.rb
@@ -7,10 +7,10 @@ describe "DateTime#to_time" do
end
it "returns a Time representing the same instant" do
- datetime = DateTime.civil(3, 12, 31, 23, 58, 59)
+ datetime = DateTime.civil(2012, 12, 31, 23, 58, 59)
time = datetime.to_time.utc
- time.year.should == 3
+ time.year.should == 2012
time.month.should == 12
time.day.should == 31
time.hour.should == 23
@@ -18,6 +18,20 @@ describe "DateTime#to_time" do
time.sec.should == 59
end
+ date_version = defined?(Date::VERSION) ? Date::VERSION : '0.0.0'
+ version_is(date_version, '3.2.3') do
+ it "returns a Time representing the same instant before Gregorian" do
+ datetime = DateTime.civil(1582, 10, 4, 23, 58, 59)
+ time = datetime.to_time.utc
+ time.year.should == 1582
+ time.month.should == 10
+ time.day.should == 14
+ time.hour.should == 23
+ time.min.should == 58
+ time.sec.should == 59
+ end
+ end
+
it "preserves the same time regardless of local time or zone" do
date = DateTime.new(2012, 12, 24, 12, 23, 00, '+03:00')
diff --git a/spec/ruby/library/delegate/delegator/taint_spec.rb b/spec/ruby/library/delegate/delegator/taint_spec.rb
index b875b5a6b8..6bf13bb73d 100644
--- a/spec/ruby/library/delegate/delegator/taint_spec.rb
+++ b/spec/ruby/library/delegate/delegator/taint_spec.rb
@@ -5,21 +5,4 @@ describe "Delegator#taint" do
before :each do
@delegate = DelegateSpecs::Delegator.new("")
end
-
- ruby_version_is ''...'2.7' do
- it "returns self" do
- @delegate.taint.equal?(@delegate).should be_true
- end
-
- it "taints the delegator" do
- @delegate.__setobj__(nil)
- @delegate.taint
- @delegate.tainted?.should be_true
- end
-
- it "taints the delegated object" do
- @delegate.taint
- @delegate.__getobj__.tainted?.should be_true
- end
- end
end
diff --git a/spec/ruby/library/delegate/delegator/trust_spec.rb b/spec/ruby/library/delegate/delegator/trust_spec.rb
index 492f02e27f..f1b81814c5 100644
--- a/spec/ruby/library/delegate/delegator/trust_spec.rb
+++ b/spec/ruby/library/delegate/delegator/trust_spec.rb
@@ -5,20 +5,4 @@ describe "Delegator#trust" do
before :each do
@delegate = DelegateSpecs::Delegator.new([])
end
-
- ruby_version_is ''...'2.7' do
- it "returns self" do
- @delegate.trust.equal?(@delegate).should be_true
- end
-
- it "trusts the delegator" do
- @delegate.trust
- @delegate.untrusted?.should be_false
- end
-
- it "trusts the delegated object" do
- @delegate.trust
- @delegate.__getobj__.untrusted?.should be_false
- end
- end
end
diff --git a/spec/ruby/library/delegate/delegator/untaint_spec.rb b/spec/ruby/library/delegate/delegator/untaint_spec.rb
index 3f8f7721a9..4051fd2629 100644
--- a/spec/ruby/library/delegate/delegator/untaint_spec.rb
+++ b/spec/ruby/library/delegate/delegator/untaint_spec.rb
@@ -5,22 +5,4 @@ describe "Delegator#untaint" do
before :each do
@delegate = -> { DelegateSpecs::Delegator.new("") }.call
end
-
- ruby_version_is ''...'2.7' do
- it "returns self" do
- @delegate.untaint.equal?(@delegate).should be_true
- end
-
- it "untaints the delegator" do
- @delegate.untaint
- @delegate.tainted?.should be_false
- # No additional meaningful test; that it does or not taint
- # "for real" the delegator has no consequence
- end
-
- it "untaints the delegated object" do
- @delegate.untaint
- @delegate.__getobj__.tainted?.should be_false
- end
- end
end
diff --git a/spec/ruby/library/delegate/delegator/untrust_spec.rb b/spec/ruby/library/delegate/delegator/untrust_spec.rb
index acc91b099a..4f7fa1e582 100644
--- a/spec/ruby/library/delegate/delegator/untrust_spec.rb
+++ b/spec/ruby/library/delegate/delegator/untrust_spec.rb
@@ -5,21 +5,4 @@ describe "Delegator#untrust" do
before :each do
@delegate = DelegateSpecs::Delegator.new("")
end
-
- ruby_version_is ''...'2.7' do
- it "returns self" do
- @delegate.untrust.equal?(@delegate).should be_true
- end
-
- it "untrusts the delegator" do
- @delegate.__setobj__(nil)
- @delegate.untrust
- @delegate.untrusted?.should be_true
- end
-
- it "untrusts the delegated object" do
- @delegate.untrust
- @delegate.__getobj__.untrusted?.should be_true
- end
- end
end
diff --git a/spec/ruby/library/erb/new_spec.rb b/spec/ruby/library/erb/new_spec.rb
index f18e25939e..4d7f7bf36a 100644
--- a/spec/ruby/library/erb/new_spec.rb
+++ b/spec/ruby/library/erb/new_spec.rb
@@ -138,4 +138,20 @@ END
ERB.new(@eruby_str).result
->{ ERB.new("<%= list %>").result }.should raise_error(NameError)
end
+
+ describe "warning about arguments" do
+ ruby_version_is "3.1" do
+ it "warns when passed safe_level and later arguments" do
+ -> {
+ ERB.new(@eruby_str, nil, '%')
+ }.should complain(/warning: Passing safe_level with the 2nd argument of ERB.new is deprecated. Do not use it, and specify other arguments as keyword arguments./)
+ end
+
+ it "does not warn when passed arguments as keyword argument" do
+ -> {
+ ERB.new(@eruby_str, trim_mode: '%')
+ }.should_not complain(/warning: Passing safe_level with the 2nd argument of ERB.new is deprecated. Do not use it, and specify other arguments as keyword arguments./)
+ end
+ end
+ end
end
diff --git a/spec/ruby/library/fiber/resume_spec.rb b/spec/ruby/library/fiber/resume_spec.rb
index 39d14bdda0..8b7c104a6f 100644
--- a/spec/ruby/library/fiber/resume_spec.rb
+++ b/spec/ruby/library/fiber/resume_spec.rb
@@ -10,6 +10,12 @@ describe "Fiber#resume" do
fiber2.resume
-> { fiber2.resume }.should raise_error(FiberError)
end
+
+ it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do
+ root_fiber = Fiber.current
+ fiber1 = Fiber.new { root_fiber.resume }
+ -> { fiber1.resume }.should raise_error(FiberError, /double resume/)
+ end
end
ruby_version_is '3.0' do
@@ -19,5 +25,11 @@ describe "Fiber#resume" do
fiber2.resume.should == 10
fiber2.resume.should == 20
end
+
+ it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do
+ root_fiber = Fiber.current
+ fiber1 = Fiber.new { root_fiber.resume }
+ -> { fiber1.resume }.should raise_error(FiberError, /attempt to resume a resuming fiber/)
+ end
end
end
diff --git a/spec/ruby/library/fiddle/handle/initialize_spec.rb b/spec/ruby/library/fiddle/handle/initialize_spec.rb
new file mode 100644
index 0000000000..51c2470efd
--- /dev/null
+++ b/spec/ruby/library/fiddle/handle/initialize_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../../spec_helper'
+require 'fiddle'
+
+describe "Fiddle::Handle#initialize" do
+ it "raises Fiddle::DLError if the library cannot be found" do
+ -> {
+ Fiddle::Handle.new("doesnotexist.doesnotexist")
+ }.should raise_error(Fiddle::DLError)
+ end
+end
diff --git a/spec/ruby/library/io-wait/wait_readable_spec.rb b/spec/ruby/library/io-wait/wait_readable_spec.rb
new file mode 100644
index 0000000000..06ffbda5c8
--- /dev/null
+++ b/spec/ruby/library/io-wait/wait_readable_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+ruby_version_is ''...'3.2' do
+ require 'io/wait'
+end
+
+describe "IO#wait_readable" do
+ before :each do
+ @io = File.new(__FILE__ )
+ end
+
+ after :each do
+ @io.close
+ end
+
+ it "waits for the IO to become readable with no timeout" do
+ @io.wait_readable.should == @io
+ end
+
+ it "waits for the IO to become readable with the given timeout" do
+ @io.wait_readable(1).should == @io
+ end
+
+ it "waits for the IO to become readable with the given large timeout" do
+ @io.wait_readable(365 * 24 * 60 * 60).should == @io
+ end
+end
diff --git a/spec/ruby/library/io-wait/wait_writable_spec.rb b/spec/ruby/library/io-wait/wait_writable_spec.rb
new file mode 100644
index 0000000000..8c44780d39
--- /dev/null
+++ b/spec/ruby/library/io-wait/wait_writable_spec.rb
@@ -0,0 +1,20 @@
+require_relative '../../spec_helper'
+
+ruby_version_is ''...'3.2' do
+ require 'io/wait'
+end
+
+describe "IO#wait_writable" do
+ it "waits for the IO to become writable with no timeout" do
+ STDOUT.wait_writable.should == STDOUT
+ end
+
+ it "waits for the IO to become writable with the given timeout" do
+ STDOUT.wait_writable(1).should == STDOUT
+ end
+
+ it "waits for the IO to become writable with the given large timeout" do
+ # Represents one year and is larger than a 32-bit int
+ STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT
+ end
+end
diff --git a/spec/ruby/library/ipaddr/new_spec.rb b/spec/ruby/library/ipaddr/new_spec.rb
index 3148d6e39c..053928c3cf 100644
--- a/spec/ruby/library/ipaddr/new_spec.rb
+++ b/spec/ruby/library/ipaddr/new_spec.rb
@@ -77,17 +77,34 @@ describe "IPAddr#new" do
a.family.should == Socket::AF_INET6
end
- it "raises on incorrect IPAddr strings" do
- [
- ["fe80::1%fxp0"],
- ["::1/255.255.255.0"],
- [IPAddr.new("::1").to_i],
- ["::ffff:192.168.1.2/120", Socket::AF_INET],
- ["[192.168.1.2]/120"],
- ].each { |args|
- ->{
- IPAddr.new(*args)
- }.should raise_error(ArgumentError)
- }
+ ruby_version_is ""..."3.1" do
+ it "raises on incorrect IPAddr strings" do
+ [
+ ["fe80::1%fxp0"],
+ ["::1/255.255.255.0"],
+ [IPAddr.new("::1").to_i],
+ ["::ffff:192.168.1.2/120", Socket::AF_INET],
+ ["[192.168.1.2]/120"],
+ ].each { |args|
+ ->{
+ IPAddr.new(*args)
+ }.should raise_error(ArgumentError)
+ }
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "raises on incorrect IPAddr strings" do
+ [
+ ["::1/255.255.255.0"],
+ [IPAddr.new("::1").to_i],
+ ["::ffff:192.168.1.2/120", Socket::AF_INET],
+ ["[192.168.1.2]/120"],
+ ].each { |args|
+ ->{
+ IPAddr.new(*args)
+ }.should raise_error(ArgumentError)
+ }
+ end
end
end
diff --git a/spec/ruby/library/logger/device/close_spec.rb b/spec/ruby/library/logger/device/close_spec.rb
index d7d107fcce..7c5e118d56 100644
--- a/spec/ruby/library/logger/device/close_spec.rb
+++ b/spec/ruby/library/logger/device/close_spec.rb
@@ -15,14 +15,14 @@ describe "Logger::LogDevice#close" do
rm_r @file_path
end
- ruby_version_is ""..."2.7" do
+ version_is Logger::VERSION, ""..."1.4.0" do
it "closes the LogDevice's stream" do
@device.close
-> { @device.write("Test") }.should complain(/\Alog writing failed\./)
end
end
- ruby_version_is "2.7" do
+ version_is Logger::VERSION, "1.4.0" do
it "closes the LogDevice's stream" do
@device.close
-> { @device.write("Test") }.should complain(/\Alog shifting failed\./)
diff --git a/spec/ruby/library/logger/device/write_spec.rb b/spec/ruby/library/logger/device/write_spec.rb
index 5506bb2c38..cd2d7e27a9 100644
--- a/spec/ruby/library/logger/device/write_spec.rb
+++ b/spec/ruby/library/logger/device/write_spec.rb
@@ -35,14 +35,14 @@ describe "Logger::LogDevice#write" do
rm_r path
end
- ruby_version_is ""..."2.7" do
+ version_is Logger::VERSION, ""..."1.4.0" do
it "fails if the device is already closed" do
@device.close
-> { @device.write "foo" }.should complain(/\Alog writing failed\./)
end
end
- ruby_version_is "2.7" do
+ version_is Logger::VERSION, "1.4.0" do
it "fails if the device is already closed" do
@device.close
-> { @device.write "foo" }.should complain(/\Alog shifting failed\./)
diff --git a/spec/ruby/library/matrix/multiply_spec.rb b/spec/ruby/library/matrix/multiply_spec.rb
index 841d9d95b7..a63fcf4020 100644
--- a/spec/ruby/library/matrix/multiply_spec.rb
+++ b/spec/ruby/library/matrix/multiply_spec.rb
@@ -24,8 +24,8 @@ ruby_version_is ""..."3.1" do
it "returns the result of multiplying the elements of self and a Bignum" do
(@a * bignum_value).should == Matrix[
- [9223372036854775808, 18446744073709551616],
- [27670116110564327424, 36893488147419103232]
+ [18446744073709551616, 36893488147419103232],
+ [55340232221128654848, 73786976294838206464]
]
end
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 63543b46a9..c1cedbfa76 100644
--- a/spec/ruby/library/net/http/http/fixtures/http_server.rb
+++ b/spec/ruby/library/net/http/http/fixtures/http_server.rb
@@ -11,29 +11,23 @@ module NetHTTPSpecs
class SmallHTTPServer
def initialize(bind_address)
@server = TCPServer.new(bind_address, 0)
- @running = Mutex.new
@thread = Thread.new {
Thread.current.abort_on_exception = true
listen
}
end
+ def ip
+ @server.addr[3]
+ end
+
def port
@server.addr[1]
end
def listen
- loop do
- begin
- client = @server.accept
- rescue IOError => e
- if @running.locked? # close
- break
- else
- raise e
- end
- end
-
+ until @server.closed?
+ client = @server.accept
handle_client(client)
end
end
@@ -43,6 +37,10 @@ module NetHTTPSpecs
until client.closed?
request = client.gets("\r\n\r\n")
break unless request
+ if request == "CLOSE"
+ @server.close
+ break
+ end
handle_request(client, request)
end
ensure
@@ -95,8 +93,9 @@ module NetHTTPSpecs
end
def close
- @running.lock
- @server.close
+ TCPSocket.open(ip, port) do |socket|
+ socket.write "CLOSE"
+ end
@thread.join
end
end
diff --git a/spec/ruby/library/objectspace/fixtures/trace.rb b/spec/ruby/library/objectspace/fixtures/trace.rb
new file mode 100644
index 0000000000..fd4524b0ba
--- /dev/null
+++ b/spec/ruby/library/objectspace/fixtures/trace.rb
@@ -0,0 +1,5 @@
+require "objspace/trace"
+a = "foo"
+b = "b" + "a" + "r"
+c = 42
+p a, b, c
diff --git a/spec/ruby/library/objectspace/memsize_of_all_spec.rb b/spec/ruby/library/objectspace/memsize_of_all_spec.rb
index 6898862e8f..c5a48165ce 100644
--- a/spec/ruby/library/objectspace/memsize_of_all_spec.rb
+++ b/spec/ruby/library/objectspace/memsize_of_all_spec.rb
@@ -13,9 +13,10 @@ describe "ObjectSpace.memsize_of_all" do
end
it "increases when a new object is allocated" do
- before = ObjectSpace.memsize_of_all(Class)
- o = Class.new
- after = ObjectSpace.memsize_of_all(Class)
+ c = Class.new
+ before = ObjectSpace.memsize_of_all(c)
+ o = c.new
+ after = ObjectSpace.memsize_of_all(c)
after.should > before
end
end
diff --git a/spec/ruby/library/objectspace/trace_object_allocations_spec.rb b/spec/ruby/library/objectspace/trace_object_allocations_spec.rb
index 3100511dc9..612430e067 100644
--- a/spec/ruby/library/objectspace/trace_object_allocations_spec.rb
+++ b/spec/ruby/library/objectspace/trace_object_allocations_spec.rb
@@ -128,4 +128,22 @@ describe "ObjectSpace.trace_object_allocations" do
ObjectSpace.trace_object_allocations_stop
end
end
+
+ it "returns nil for class_path, generation, method_id, sourcefile, and sourceline for immutable objects" do
+ ObjectSpace.trace_object_allocations_start
+ begin
+ one = nil
+ two = 42
+ three = :foo
+ [one, two, three].each do |i|
+ ObjectSpace.allocation_class_path(i).should == nil
+ ObjectSpace.allocation_generation(i).should == nil
+ ObjectSpace.allocation_method_id(i).should == nil
+ ObjectSpace.allocation_sourcefile(i).should == nil
+ ObjectSpace.allocation_sourceline(i).should == nil
+ end
+ ensure
+ ObjectSpace.trace_object_allocations_stop
+ end
+ end
end
diff --git a/spec/ruby/library/objectspace/trace_spec.rb b/spec/ruby/library/objectspace/trace_spec.rb
new file mode 100644
index 0000000000..59952a006c
--- /dev/null
+++ b/spec/ruby/library/objectspace/trace_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe 'require "objspace/trace"' do
+ it "shows object allocation sites" do
+ file = fixture(__FILE__ , "trace.rb")
+ ruby_exe(file, args: "2>&1").lines(chomp: true).should == [
+ "objspace/trace is enabled",
+ "\"foo\" @ #{file}:2",
+ "\"bar\" @ #{file}:3",
+ "42"
+ ]
+ end
+ end
+end
diff --git a/spec/ruby/library/openssl/x509/name/verify_spec.rb b/spec/ruby/library/openssl/x509/name/verify_spec.rb
new file mode 100644
index 0000000000..6dcfc99466
--- /dev/null
+++ b/spec/ruby/library/openssl/x509/name/verify_spec.rb
@@ -0,0 +1,78 @@
+require_relative '../../../../spec_helper'
+require 'openssl'
+
+describe "OpenSSL::X509::Name.verify" do
+ it "returns true for valid certificate" do
+ key = OpenSSL::PKey::RSA.new 2048
+ cert = OpenSSL::X509::Certificate.new
+ cert.version = 2
+ cert.serial = 1
+ cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=truffleruby/CN=TruffleRuby CA"
+ cert.issuer = cert.subject
+ cert.public_key = key.public_key
+ cert.not_before = Time.now - 10
+ cert.not_after = cert.not_before + 365 * 24 * 60 * 60
+ cert.sign key, OpenSSL::Digest.new('SHA256')
+ store = OpenSSL::X509::Store.new
+ store.add_cert(cert)
+ [store.verify(cert), store.error, store.error_string].should == [true, 0, "ok"]
+ end
+
+ it "returns false for an expired certificate" do
+ key = OpenSSL::PKey::RSA.new 2048
+ cert = OpenSSL::X509::Certificate.new
+ cert.version = 2
+ cert.serial = 1
+ cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=truffleruby/CN=TruffleRuby CA"
+ cert.issuer = cert.subject
+ cert.public_key = key.public_key
+ cert.not_before = Time.now - 10
+ cert.not_after = Time.now - 5
+ cert.sign key, OpenSSL::Digest.new('SHA256')
+ store = OpenSSL::X509::Store.new
+ store.add_cert(cert)
+ store.verify(cert).should == false
+ end
+
+ it "returns false for an expired root certificate" do
+ root_key = OpenSSL::PKey::RSA.new 2048
+ root_cert = OpenSSL::X509::Certificate.new
+ root_cert.version = 2
+ root_cert.serial = 1
+ root_cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=truffleruby/CN=TruffleRuby CA"
+ root_cert.issuer = root_cert.subject
+ root_cert.public_key = root_key.public_key
+ root_cert.not_before = Time.now - 10
+ root_cert.not_after = Time.now - 5
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.subject_certificate = root_cert
+ ef.issuer_certificate = root_cert
+ root_cert.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
+ root_cert.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
+ root_cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
+ root_cert.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
+ root_cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
+
+
+ key = OpenSSL::PKey::RSA.new 2048
+ cert = OpenSSL::X509::Certificate.new
+ cert.version = 2
+ cert.serial = 2
+ cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=truffleruby/CN=TruffleRuby certificate"
+ cert.issuer = root_cert.subject
+ cert.public_key = key.public_key
+ cert.not_before = Time.now
+ cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.subject_certificate = cert
+ ef.issuer_certificate = root_cert
+ cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
+ cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
+ cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
+
+ store = OpenSSL::X509::Store.new
+ store.add_cert(root_cert)
+ store.add_cert(cert)
+ store.verify(cert).should == false
+ end
+end
diff --git a/spec/ruby/library/openstruct/method_missing_spec.rb b/spec/ruby/library/openstruct/method_missing_spec.rb
index 212db015a9..89f83d07b3 100644
--- a/spec/ruby/library/openstruct/method_missing_spec.rb
+++ b/spec/ruby/library/openstruct/method_missing_spec.rb
@@ -17,10 +17,8 @@ describe "OpenStruct#method_missing when passed additional arguments" do
-> { 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.test(1, 2, 3) }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError when the key exists" do
+ os = OpenStruct.new(test: 20)
+ -> { os.test(1, 2, 3) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/library/pathname/birthtime_spec.rb b/spec/ruby/library/pathname/birthtime_spec.rb
new file mode 100644
index 0000000000..109c112303
--- /dev/null
+++ b/spec/ruby/library/pathname/birthtime_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+require 'pathname'
+
+describe "Pathname#birthtime" do
+ platform_is :windows, :darwin, :freebsd, :netbsd do
+ it "returns the birth time for self" do
+ Pathname.new(__FILE__).birthtime.should be_kind_of(Time)
+ end
+ end
+
+ platform_is :openbsd do
+ it "raises an NotImplementedError" do
+ -> { Pathname.new(__FILE__).birthtime }.should raise_error(NotImplementedError)
+ end
+ end
+end
diff --git a/spec/ruby/library/pathname/glob_spec.rb b/spec/ruby/library/pathname/glob_spec.rb
index f6dfd6cd58..ced810fa90 100644
--- a/spec/ruby/library/pathname/glob_spec.rb
+++ b/spec/ruby/library/pathname/glob_spec.rb
@@ -40,18 +40,45 @@ describe 'Pathname.glob' do
}.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
+ 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
+
+
+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.new(@dir).glob('lib/*.js').should == []
+ end
+
+ it 'returns matching file paths' do
+ Pathname.new(@dir).glob('lib/*i*.rb').sort.should == [Pathname.new(@file_1), Pathname.new(@file_2)].sort
+ end
+
+ it 'yields matching file paths to block' do
+ ary = []
+ Pathname.new(@dir).glob('lib/*i*.rb') { |p| ary << p }.should be_nil
+ ary.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.new(@dir).glob('lib/*i*.rb', File::FNM_DOTMATCH).sort.should == expected
end
end
diff --git a/spec/ruby/library/pathname/new_spec.rb b/spec/ruby/library/pathname/new_spec.rb
index 760fd8638f..36226ed515 100644
--- a/spec/ruby/library/pathname/new_spec.rb
+++ b/spec/ruby/library/pathname/new_spec.rb
@@ -10,13 +10,6 @@ describe "Pathname.new" do
-> { Pathname.new("\0")}.should raise_error(ArgumentError)
end
- ruby_version_is ''...'2.7' do
- it "is tainted if path is tainted" do
- path = '/usr/local/bin'.taint
- Pathname.new(path).should.tainted?
- end
- end
-
it "raises a TypeError if not passed a String type" do
-> { Pathname.new(nil) }.should raise_error(TypeError)
-> { Pathname.new(0) }.should raise_error(TypeError)
diff --git a/spec/ruby/library/pathname/pathname_spec.rb b/spec/ruby/library/pathname/pathname_spec.rb
index 7d63fe86e3..0fb2881468 100644
--- a/spec/ruby/library/pathname/pathname_spec.rb
+++ b/spec/ruby/library/pathname/pathname_spec.rb
@@ -10,21 +10,10 @@ describe "Kernel#Pathname" 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)
+ it "returns same argument 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
+ path.should.equal?(new_path)
end
end
diff --git a/spec/ruby/library/pp/pp_spec.rb b/spec/ruby/library/pp/pp_spec.rb
index 06b22601d8..243478efd9 100644
--- a/spec/ruby/library/pp/pp_spec.rb
+++ b/spec/ruby/library/pp/pp_spec.rb
@@ -20,4 +20,11 @@ describe "PP.pp" do
other_out.to_s.should == "[1, 2, 3]\n"
end
+
+ it 'correctly prints a Hash' do
+ hash = { 'key' => 42 }
+ -> {
+ PP.pp hash
+ }.should output('{"key"=>42}' + "\n")
+ end
end
diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb
index 99b9da71e4..b90cc90970 100644
--- a/spec/ruby/library/rbconfig/rbconfig_spec.rb
+++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb
@@ -26,7 +26,7 @@ describe 'RbConfig::CONFIG' do
it "['sitelibdir'] is set and is part of $LOAD_PATH" do
sitelibdir = RbConfig::CONFIG['sitelibdir']
sitelibdir.should be_kind_of String
- $LOAD_PATH.should.include? sitelibdir
+ $LOAD_PATH.map{|path| File.realpath(path) rescue path }.should.include? sitelibdir
end
end
@@ -42,6 +42,17 @@ describe 'RbConfig::CONFIG' do
RUBY
end
+ platform_is_not :windows do
+ it "['LIBRUBY'] is the same as LIBRUBY_SO if and only if ENABLE_SHARED" do
+ case RbConfig::CONFIG['ENABLE_SHARED']
+ when 'yes'
+ RbConfig::CONFIG['LIBRUBY'].should == RbConfig::CONFIG['LIBRUBY_SO']
+ when 'no'
+ RbConfig::CONFIG['LIBRUBY'].should_not == RbConfig::CONFIG['LIBRUBY_SO']
+ end
+ end
+ end
+
guard -> { RbConfig::TOPDIR } do
it "libdir/LIBRUBY_SO is the path to libruby and it exists if and only if ENABLE_SHARED" do
libdirname = RbConfig::CONFIG['LIBPATHENV'] == 'PATH' ? 'bindir' :
diff --git a/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb b/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
index b7d9c7a8e4..3dc9900127 100644
--- a/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
+++ b/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
@@ -2,27 +2,22 @@ require_relative '../../spec_helper'
require 'rbconfig'
describe "RbConfig::CONFIG['UNICODE_EMOJI_VERSION']" do
- ruby_version_is "2.6"..."2.6.2" do
- it "is 11.0 for Ruby 2.6.0 and 2.6.1" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "11.0"
- end
- end
-
- ruby_version_is "2.6.2"..."2.7" do
- it "is 12.0 for Ruby 2.6.2+" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.0"
+ ruby_version_is ""..."3.1" do
+ it "is 12.1" do
+ RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.1"
end
end
- ruby_version_is "2.7"..."3.1" do
- it "is 12.1 for Ruby 2.7 and 3.0" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.1"
+ ruby_version_is "3.1"..."3.2" do
+ it "is 13.1" do
+ RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "13.1"
end
end
- ruby_version_is "3.1" do
- it "is 13.1 for Ruby 3.1" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "13.1"
+ # Caution: ruby_version_is means is_or_later
+ ruby_version_is "3.2" do
+ it "is 15.0" do
+ RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "15.0"
end
end
end
diff --git a/spec/ruby/library/rbconfig/unicode_version_spec.rb b/spec/ruby/library/rbconfig/unicode_version_spec.rb
index fe19b10293..458f13bf03 100644
--- a/spec/ruby/library/rbconfig/unicode_version_spec.rb
+++ b/spec/ruby/library/rbconfig/unicode_version_spec.rb
@@ -2,27 +2,22 @@ require_relative '../../spec_helper'
require 'rbconfig'
describe "RbConfig::CONFIG['UNICODE_VERSION']" do
- ruby_version_is "2.6"..."2.6.2" do
- it "is 11.0.0 for Ruby 2.6.0 and 2.6.1" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "11.0.0"
- end
- end
-
- ruby_version_is "2.6.2"..."2.6.3" do
- it "is 12.0.0 for Ruby 2.6.2" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "12.0.0"
+ ruby_version_is ""..."3.1" do
+ it "is 12.1.0" do
+ RbConfig::CONFIG['UNICODE_VERSION'].should == "12.1.0"
end
end
- ruby_version_is "2.6.3"..."3.1" do
- it "is 12.1.0 for Ruby 2.6.3+, Ruby 2.7, and Ruby 3.0" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "12.1.0"
+ ruby_version_is "3.1"..."3.2" do
+ it "is 13.0.0" do
+ RbConfig::CONFIG['UNICODE_VERSION'].should == "13.0.0"
end
end
- ruby_version_is "3.1" do
- it "is 13.0.0 for Ruby 3.1" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "13.0.0"
+ # Caution: ruby_version_is means is_or_later
+ ruby_version_is "3.2" do
+ it "is 15.0.0" do
+ RbConfig::CONFIG['UNICODE_VERSION'].should == "15.0.0"
end
end
end
diff --git a/spec/ruby/library/readline/history/delete_at_spec.rb b/spec/ruby/library/readline/history/delete_at_spec.rb
index c95a6a865e..3bd577e75c 100644
--- a/spec/ruby/library/readline/history/delete_at_spec.rb
+++ b/spec/ruby/library/readline/history/delete_at_spec.rb
@@ -34,14 +34,5 @@ with_feature :readline do
-> { Readline::HISTORY.delete_at(10) }.should raise_error(IndexError)
-> { Readline::HISTORY.delete_at(-10) }.should raise_error(IndexError)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned strings" do
- Readline::HISTORY.push("1", "2", "3")
- Readline::HISTORY.delete_at(0).tainted?.should be_true
- Readline::HISTORY.delete_at(0).tainted?.should be_true
- Readline::HISTORY.delete_at(0).tainted?.should be_true
- end
- end
end
end
diff --git a/spec/ruby/library/readline/history/each_spec.rb b/spec/ruby/library/readline/history/each_spec.rb
index 23387bfc98..aa48dd46df 100644
--- a/spec/ruby/library/readline/history/each_spec.rb
+++ b/spec/ruby/library/readline/history/each_spec.rb
@@ -19,13 +19,5 @@ with_feature :readline do
end
result.should == ["1", "2", "3"]
end
-
- ruby_version_is ''...'2.7' do
- it "yields tainted Objects" do
- Readline::HISTORY.each do |x|
- x.tainted?.should be_true
- end
- end
- end
end
end
diff --git a/spec/ruby/library/readline/history/element_reference_spec.rb b/spec/ruby/library/readline/history/element_reference_spec.rb
index dfa5367cad..0a74f3d62d 100644
--- a/spec/ruby/library/readline/history/element_reference_spec.rb
+++ b/spec/ruby/library/readline/history/element_reference_spec.rb
@@ -12,13 +12,6 @@ with_feature :readline do
Readline::HISTORY.pop
end
- ruby_version_is ''...'2.7' do
- it "returns tainted objects" do
- Readline::HISTORY[0].tainted?.should be_true
- Readline::HISTORY[1].tainted?.should be_true
- end
- end
-
it "returns the history item at the passed index" do
Readline::HISTORY[0].should == "1"
Readline::HISTORY[1].should == "2"
diff --git a/spec/ruby/library/readline/history/pop_spec.rb b/spec/ruby/library/readline/history/pop_spec.rb
index e17be666d8..156a8a06f8 100644
--- a/spec/ruby/library/readline/history/pop_spec.rb
+++ b/spec/ruby/library/readline/history/pop_spec.rb
@@ -19,14 +19,5 @@ with_feature :readline do
Readline::HISTORY.pop.should == "1"
Readline::HISTORY.size.should == 0
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned strings" do
- Readline::HISTORY.push("1", "2", "3")
- Readline::HISTORY.pop.tainted?.should be_true
- Readline::HISTORY.pop.tainted?.should be_true
- Readline::HISTORY.pop.tainted?.should be_true
- end
- end
end
end
diff --git a/spec/ruby/library/readline/history/shift_spec.rb b/spec/ruby/library/readline/history/shift_spec.rb
index ccd90193fd..9aad7d5399 100644
--- a/spec/ruby/library/readline/history/shift_spec.rb
+++ b/spec/ruby/library/readline/history/shift_spec.rb
@@ -19,14 +19,5 @@ with_feature :readline do
Readline::HISTORY.shift.should == "3"
Readline::HISTORY.size.should == 0
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned strings" do
- Readline::HISTORY.push("1", "2", "3")
- Readline::HISTORY.shift.tainted?.should be_true
- Readline::HISTORY.shift.tainted?.should be_true
- Readline::HISTORY.shift.tainted?.should be_true
- end
- end
end
end
diff --git a/spec/ruby/library/readline/readline_spec.rb b/spec/ruby/library/readline/readline_spec.rb
index 24d2cbbe86..6e349ad543 100644
--- a/spec/ruby/library/readline/readline_spec.rb
+++ b/spec/ruby/library/readline/readline_spec.rb
@@ -21,13 +21,6 @@ with_feature :readline do
ruby_exe('File.write ARGV[0], Readline.readline', @options)
File.read(@out).should == "test"
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned strings" do
- ruby_exe('File.write ARGV[0], Readline.readline.tainted?', @options)
- File.read(@out).should == "true"
- end
- end
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 f2d779e577..dcc6dbbf17 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
@@ -12,23 +12,23 @@ ruby_version_is ''...'3.0' do
@son.attributes["name"] = "Fred"
@document.root << @father
@document.root << @son
- @childs = []
+ @children = []
end
- it "returns childs with attribute" do
- @document.each_element_with_attribute("name") { |elem| @childs << elem }
- @childs[0].should == @father
- @childs[1].should == @son
+ it "returns children with attribute" do
+ @document.each_element_with_attribute("name") { |elem| @children << elem }
+ @children[0].should == @father
+ @children[1].should == @son
end
it "takes 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
+ it "takes max number of children as third argument" do
+ @document.each_element_with_attribute("name", nil, 1) { |elem| @children << elem }
+ @children.size.should == 1
+ @children[0].should == @father
end
it "takes XPath filter as fourth argument" do
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 8f9d062c99..a4a200d237 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
@@ -16,10 +16,10 @@ ruby_version_is ''...'3.0' do
@document.root << @joe
@document.root << @fred
@document.root << @another
- @childs = []
+ @children = []
end
- it "returns childs with text" do
+ it "returns children with text" do
@document.each_element_with_text("Joe"){|c| c.should == @joe}
end
diff --git a/spec/ruby/library/rexml/element/has_text_spec.rb b/spec/ruby/library/rexml/element/has_text_spec.rb
index de19fe0763..206c167ae6 100644
--- a/spec/ruby/library/rexml/element/has_text_spec.rb
+++ b/spec/ruby/library/rexml/element/has_text_spec.rb
@@ -11,7 +11,7 @@ ruby_version_is ''...'3.0' do
e.has_text?.should be_true
end
- it "returns false if it has no Text childs" do
+ it "returns false if it has no Text children" do
e = REXML::Element.new("Person")
e.has_text?.should be_false
end
diff --git a/spec/ruby/library/rexml/node/parent_spec.rb b/spec/ruby/library/rexml/node/parent_spec.rb
index 07425e8f36..43c3a747e0 100644
--- a/spec/ruby/library/rexml/node/parent_spec.rb
+++ b/spec/ruby/library/rexml/node/parent_spec.rb
@@ -14,7 +14,7 @@ ruby_version_is ''...'3.0' do
e.should.parent?
end
- # This includes attributes, CDatas and declarations.
+ # This includes attributes, CData and declarations.
it "returns false for Texts" do
e = REXML::Text.new("foo")
e.should_not.parent?
diff --git a/spec/ruby/library/rexml/shared/elements_to_a.rb b/spec/ruby/library/rexml/shared/elements_to_a.rb
index 388250d8b3..b7169f0b2e 100644
--- a/spec/ruby/library/rexml/shared/elements_to_a.rb
+++ b/spec/ruby/library/rexml/shared/elements_to_a.rb
@@ -19,7 +19,7 @@ describe :rexml_elements_to_a, shared: true do
# always needs the first param (even if it's nil).
# A patch was submitted:
# http://rubyforge.org/tracker/index.php?func=detail&aid=19354&group_id=426&atid=1698
- it "returns all childs if xpath is nil" do
+ it "returns all children if xpath is nil" do
@e.elements.send(@method).should == [@first, @second]
end
diff --git a/spec/ruby/library/scanf/io/block_scanf_spec.rb b/spec/ruby/library/scanf/io/block_scanf_spec.rb
deleted file mode 100644
index b9cc1b507e..0000000000
--- a/spec/ruby/library/scanf/io/block_scanf_spec.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require_relative 'shared/block_scanf'
- require 'scanf'
-
- describe "IO#block_scanf" do
- it_behaves_like :scanf_io_block_scanf, :block_scanf
- end
-end
diff --git a/spec/ruby/library/scanf/io/fixtures/date.txt b/spec/ruby/library/scanf/io/fixtures/date.txt
deleted file mode 100644
index a1bd635c0c..0000000000
--- a/spec/ruby/library/scanf/io/fixtures/date.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Beethoven 1770
-Bach 1685
-Handel 1685
-
diff --git a/spec/ruby/library/scanf/io/fixtures/helloworld.txt b/spec/ruby/library/scanf/io/fixtures/helloworld.txt
deleted file mode 100644
index 3b18e512db..0000000000
--- a/spec/ruby/library/scanf/io/fixtures/helloworld.txt
+++ /dev/null
@@ -1 +0,0 @@
-hello world
diff --git a/spec/ruby/library/scanf/io/scanf_spec.rb b/spec/ruby/library/scanf/io/scanf_spec.rb
deleted file mode 100644
index 6a3e6d0d1a..0000000000
--- a/spec/ruby/library/scanf/io/scanf_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require_relative 'shared/block_scanf'
- require 'scanf'
-
- describe "IO#scanf" do
- before :each do
- @hw = File.open(fixture(__FILE__, 'helloworld.txt'), 'rb')
- @data = File.open(fixture(__FILE__, 'date.txt'), 'rb')
- end
-
- after :each do
- @hw.close unless @hw.closed?
- @data.close unless @data.closed?
- end
-
- it "returns an array containing the input converted in the specified type" do
- @hw.scanf("%s%s").should == ["hello", "world"]
- @data.scanf("%s%d").should == ["Beethoven", 1770]
- end
-
- it "returns an array containing the input converted in the specified type with given maximum field width" do
- @hw.scanf("%2s").should == ["he"]
- @data.scanf("%2c").should == ["Be"]
- end
-
- it "returns an empty array when a wrong specifier is passed" do
- @hw.scanf("%a").should == []
- @hw.scanf("%1").should == []
- @data.scanf("abc").should == []
- end
- end
-
- describe "IO#scanf with block" do
- it_behaves_like :scanf_io_block_scanf, :scanf
- end
-end
diff --git a/spec/ruby/library/scanf/io/shared/block_scanf.rb b/spec/ruby/library/scanf/io/shared/block_scanf.rb
deleted file mode 100644
index d938f43734..0000000000
--- a/spec/ruby/library/scanf/io/shared/block_scanf.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'scanf'
-
-describe :scanf_io_block_scanf, shared: true do
- before :each do
- @data = File.open(fixture(__FILE__, 'date.txt'), 'rb')
- end
-
- after :each do
- @data.close unless @data.closed?
- end
-
- it "passes each match to the block as an array" do
- res = @data.send(@method, "%s%d") { |name, year| "#{name} was born in #{year}." }
- res.should == ["Beethoven was born in 1770.", "Bach was born in 1685.", "Handel was born in 1685."]
- end
-
- it "keeps scanning the input and cycling back to the beginning of the input string" do
- a = []
- @data.send(@method, "%s"){|w| a << w}
- a.should == [["Beethoven"], ["1770"], ["Bach"], ["1685"], ["Handel"], ["1685"]]
- end
-
- it "returns an empty array when a wrong specifier is passed" do
- a = []
- @data.send(@method, "%z"){|w| a << w}
- a.empty?.should be_true
- end
-end
diff --git a/spec/ruby/library/scanf/string/block_scanf_spec.rb b/spec/ruby/library/scanf/string/block_scanf_spec.rb
deleted file mode 100644
index 277e1fa1d7..0000000000
--- a/spec/ruby/library/scanf/string/block_scanf_spec.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require_relative 'shared/block_scanf'
- require 'scanf'
-
- describe "String#block_scanf" do
- it_behaves_like :scanf_string_block_scanf, :block_scanf
- end
-end
diff --git a/spec/ruby/library/scanf/string/scanf_spec.rb b/spec/ruby/library/scanf/string/scanf_spec.rb
deleted file mode 100644
index c8897db675..0000000000
--- a/spec/ruby/library/scanf/string/scanf_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.7' do
- require_relative 'shared/block_scanf'
- require 'scanf'
-
- describe "String#scanf" do
- it "returns an array containing the input converted in the specified type" do
- "hello world".scanf("%s").should == ["hello"]
- "hello world".scanf("%s%d").should == ["hello"]
- "hello world".scanf("%s%c").should == ["hello", " "]
- "hello world".scanf("%c%s").should == ["h", "ello"]
- "hello world".scanf("%s%s").should == ["hello", "world"]
- "hello world".scanf("%c").should == ["h"]
- "123".scanf("%s").should == ["123"]
- "123".scanf("%c").should == ["1"]
- "123".scanf("%d").should == [123]
- "123".scanf("%u").should == [123]
- "123".scanf("%o").should == [83]
- "123".scanf("%x").should == [291]
- "123".scanf("%i").should == [123]
- "0123".scanf("%i").should == [83]
- "123".scanf("%f").should == [123.0]
- "0X123".scanf("%i").should == [291]
- "0x123".scanf("%i").should == [291]
- end
-
- it "returns an array containing the input converted in the specified type with given maximum field width" do
- "hello world".scanf("%2s").should == ["he"]
- "hello world".scanf("%2c").should == ["he"]
- "123".scanf("%2s").should == ["12"]
- "123".scanf("%2c").should == ["12"]
- "123".scanf("%2d").should == [12]
- "123".scanf("%2u").should == [12]
- "123".scanf("%2o").should == [10]
- "123".scanf("%2x").should == [18]
- "123".scanf("%2i").should == [12]
- "0123".scanf("%2i").should == [1]
- "123".scanf("%2f").should == [12.0]
- "0X123".scanf("%2i").should == [0]
- "0X123".scanf("%3i").should == [1]
- "0X123".scanf("%4i").should == [18]
- end
-
- it "returns an empty array when a wrong specifier is passed" do
- "hello world".scanf("%a").should == []
- "123".scanf("%1").should == []
- "123".scanf("abc").should == []
- "123".scanf(:d).should == []
- end
- end
-
- describe "String#scanf with block" do
- it_behaves_like :scanf_string_block_scanf, :scanf
- end
-end
diff --git a/spec/ruby/library/scanf/string/shared/block_scanf.rb b/spec/ruby/library/scanf/string/shared/block_scanf.rb
deleted file mode 100644
index 25ab3f442a..0000000000
--- a/spec/ruby/library/scanf/string/shared/block_scanf.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'scanf'
-
-describe :scanf_string_block_scanf, shared: true do
- it "passes each match to the block as an array" do
- a = []
- "hello world".send(@method, "%s%s"){|w| a << w}
- a.should == [["hello", "world"]]
- end
-
- it "keeps scanning the input and cycling back to the beginning of the input string" do
- a = []
- "hello world".send(@method, "%s"){|w| a << w}
- a.should == [["hello"], ["world"]]
-
- string = "123 abc 456 def 789 ghi"
- s = string.send(@method, "%d%s"){|num,str| [num * 2, str.upcase]}
- s.should == [[246, "ABC"], [912, "DEF"], [1578, "GHI"]]
- end
-
- it "returns an empty array when a wrong specifier is passed" do
- a = []
- "hello world".send(@method, "%z"){|w| a << w}
- a.empty?.should be_true
- end
-end
diff --git a/spec/ruby/library/set/comparison_spec.rb b/spec/ruby/library/set/comparison_spec.rb
new file mode 100644
index 0000000000..b851ea3d57
--- /dev/null
+++ b/spec/ruby/library/set/comparison_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../spec_helper'
+require 'set'
+
+ruby_version_is "3.0" do
+ describe "Set#<=>" do
+ it "returns 0 if the sets are equal" do
+ (Set[] <=> Set[]).should == 0
+ (Set[:a, :b, :c] <=> Set[:a, :b, :c]).should == 0
+ end
+
+ it "returns -1 if the set is a proper subset of the other set" do
+ (Set[] <=> Set[1]).should == -1
+ (Set[1, 2] <=> Set[1, 2, 3]).should == -1
+ end
+
+ it "returns +1 if the set is a proper superset of other set" do
+ (Set[1] <=> Set[]).should == +1
+ (Set[1, 2, 3] <=> Set[1, 2]).should == +1
+ end
+
+ it "returns nil if the set has unique elements" do
+ (Set[1, 2, 3] <=> Set[:a, :b, :c]).should be_nil
+ end
+
+ it "returns nil when the argument is not set-like" do
+ (Set[] <=> false).should be_nil
+ end
+ end
+end
diff --git a/spec/ruby/library/set/initialize_clone_spec.rb b/spec/ruby/library/set/initialize_clone_spec.rb
new file mode 100644
index 0000000000..62985987fa
--- /dev/null
+++ b/spec/ruby/library/set/initialize_clone_spec.rb
@@ -0,0 +1,18 @@
+require_relative '../../spec_helper'
+require 'set'
+
+describe "Set#initialize_clone" do
+ ruby_version_is "3.0" do
+ # See https://bugs.ruby-lang.org/issues/14266
+ it "does not freeze the new Set when called from clone(freeze: false)" do
+ set1 = Set[1, 2]
+ set1.freeze
+ set2 = set1.clone(freeze: false)
+ set1.frozen?.should == true
+ set2.frozen?.should == false
+ set2.add 3
+ set1.should == Set[1, 2]
+ set2.should == Set[1, 2, 3]
+ end
+ end
+end
diff --git a/spec/ruby/library/set/join_spec.rb b/spec/ruby/library/set/join_spec.rb
new file mode 100644
index 0000000000..7498a91d98
--- /dev/null
+++ b/spec/ruby/library/set/join_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../spec_helper'
+require 'set'
+
+ruby_version_is "3.0" do
+ describe "Set#join" do
+ it "returns an empty string if the Set is empty" do
+ Set[].join.should == ''
+ end
+
+ it "returns a new string formed by joining elements after conversion" do
+ set = Set[:a, :b, :c]
+ set.join.should == "abc"
+ end
+
+ it "does not separate elements when the passed separator is nil" do
+ set = Set[:a, :b, :c]
+ set.join(nil).should == "abc"
+ end
+
+ it "returns a string formed by concatenating each element separated by the separator" do
+ set = Set[:a, :b, :c]
+ set.join(' | ').should == "a | b | c"
+ end
+
+ it "calls #to_a to convert the Set in to an Array" do
+ set = Set[:a, :b, :c]
+ set.should_receive(:to_a).and_return([:a, :b, :c])
+ set.join.should == "abc"
+ end
+ end
+end
diff --git a/spec/ruby/library/set/pretty_print_spec.rb b/spec/ruby/library/set/pretty_print_spec.rb
index f2392e6968..ea9ead0df8 100644
--- a/spec/ruby/library/set/pretty_print_spec.rb
+++ b/spec/ruby/library/set/pretty_print_spec.rb
@@ -1,17 +1,19 @@
require_relative '../../spec_helper'
require 'set'
-describe "Set#pretty_print" do
- it "passes the 'pretty print' representation of self to the pretty print writer" do
- pp = mock("PrettyPrint")
- set = Set[1, 2, 3]
+ruby_version_is ""..."3.1" do
+ describe "Set#pretty_print" do
+ it "passes the 'pretty print' representation of self to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ set = Set[1, 2, 3]
- pp.should_receive(:text).with("#<Set: {")
- pp.should_receive(:text).with("}>")
+ pp.should_receive(:text).with("#<Set: {")
+ pp.should_receive(:text).with("}>")
- pp.should_receive(:nest).with(1).and_yield
- pp.should_receive(:seplist).with(set)
+ pp.should_receive(:nest).with(1).and_yield
+ pp.should_receive(:seplist).with(set)
- set.pretty_print(pp)
+ set.pretty_print(pp)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/sortedset_spec.rb b/spec/ruby/library/set/sortedset/sortedset_spec.rb
new file mode 100644
index 0000000000..3ead5495fc
--- /dev/null
+++ b/spec/ruby/library/set/sortedset/sortedset_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../../spec_helper'
+require 'set'
+
+ruby_version_is "3.0" do
+ describe "SortedSet" do
+ it "raises error including message that it has been extracted from the set stdlib" do
+ -> {
+ SortedSet
+ }.should raise_error(RuntimeError) { |e|
+ e.message.should.include?("The `SortedSet` class has been extracted from the `set` library")
+ }
+ end
+ end
+end
+
+ruby_version_is ""..."3.0" do
+ describe "SortedSet" do
+ it "is part of the set stdlib" do
+ SortedSet.superclass.should == Set
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/addrinfo/initialize_spec.rb b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
index 00250439fd..83b204b575 100644
--- a/spec/ruby/library/socket/addrinfo/initialize_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
@@ -91,7 +91,7 @@ describe "Addrinfo#initialize" do
@addrinfo.afamily.should == Socket::AF_INET6
end
- it "returns the 0 socket type" do
+ it "returns the specified socket type" do
@addrinfo.socktype.should == Socket::SOCK_STREAM
end
diff --git a/spec/ruby/library/socket/basicsocket/local_address_spec.rb b/spec/ruby/library/socket/basicsocket/local_address_spec.rb
new file mode 100644
index 0000000000..0bd60a44cd
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/local_address_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../spec_helper'
+require_relative '../shared/address'
+
+describe 'BasicSocket#local_address' do
+ it_behaves_like :socket_local_remote_address, :local_address, -> socket {
+ a2 = BasicSocket.for_fd(socket.fileno)
+ a2.autoclose = false
+ a2.local_address
+ }
+end
diff --git a/spec/ruby/library/socket/basicsocket/remote_address_spec.rb b/spec/ruby/library/socket/basicsocket/remote_address_spec.rb
new file mode 100644
index 0000000000..439bf31592
--- /dev/null
+++ b/spec/ruby/library/socket/basicsocket/remote_address_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../spec_helper'
+require_relative '../shared/address'
+
+describe 'BasicSocket#remote_address' do
+ it_behaves_like :socket_local_remote_address, :remote_address, -> socket {
+ a2 = BasicSocket.for_fd(socket.fileno)
+ a2.autoclose = false
+ a2.remote_address
+ }
+end
diff --git a/spec/ruby/library/socket/shared/address.rb b/spec/ruby/library/socket/shared/address.rb
new file mode 100644
index 0000000000..f3be9cfb99
--- /dev/null
+++ b/spec/ruby/library/socket/shared/address.rb
@@ -0,0 +1,249 @@
+require_relative '../fixtures/classes'
+
+describe :socket_local_remote_address, shared: true do
+ describe 'using TCPSocket' do
+ before :each do
+ @s = TCPServer.new('127.0.0.1', 0)
+ @a = TCPSocket.new('127.0.0.1', @s.addr[1])
+ @b = @s.accept
+ @addr = @object.call(@a)
+ end
+
+ after :each do
+ [@b, @a, @s].each(&:close)
+ end
+
+ it 'uses AF_INET as the address family' do
+ @addr.afamily.should == Socket::AF_INET
+ end
+
+ it 'uses PF_INET as the protocol family' do
+ @addr.pfamily.should == Socket::PF_INET
+ end
+
+ it 'uses SOCK_STREAM as the socket type' do
+ @addr.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it 'uses the correct IP address' do
+ @addr.ip_address.should == '127.0.0.1'
+ end
+
+ it 'uses the correct port' do
+ if @method == :local_address
+ @addr.ip_port.should != @s.addr[1]
+ else
+ @addr.ip_port.should == @s.addr[1]
+ end
+ end
+
+ it 'equals address of peer socket' do
+ if @method == :local_address
+ @addr.to_s.should == @b.remote_address.to_s
+ else
+ @addr.to_s.should == @b.local_address.to_s
+ end
+ end
+
+ it 'returns an Addrinfo' do
+ @addr.should be_an_instance_of(Addrinfo)
+ end
+
+ it 'uses 0 as the protocol' do
+ @addr.protocol.should == 0
+ end
+
+ it 'can be used to connect to the server' do
+ skip if @method == :local_address
+ b = @addr.connect
+ begin
+ b.remote_address.to_s.should == @addr.to_s
+ ensure
+ b.close
+ end
+ end
+ end
+
+ guard -> { SocketSpecs.ipv6_available? } do
+ describe 'using IPv6' do
+ before :each do
+ @s = TCPServer.new('::1', 0)
+ @a = TCPSocket.new('::1', @s.addr[1])
+ @b = @s.accept
+ @addr = @object.call(@a)
+ end
+
+ after :each do
+ [@b, @a, @s].each(&:close)
+ end
+
+ it 'uses AF_INET6 as the address family' do
+ @addr.afamily.should == Socket::AF_INET6
+ end
+
+ it 'uses PF_INET6 as the protocol family' do
+ @addr.pfamily.should == Socket::PF_INET6
+ end
+
+ it 'uses SOCK_STREAM as the socket type' do
+ @addr.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it 'uses the correct IP address' do
+ @addr.ip_address.should == '::1'
+ end
+
+ it 'uses the correct port' do
+ if @method == :local_address
+ @addr.ip_port.should != @s.addr[1]
+ else
+ @addr.ip_port.should == @s.addr[1]
+ end
+ end
+
+ it 'equals address of peer socket' do
+ if @method == :local_address
+ @addr.to_s.should == @b.remote_address.to_s
+ else
+ @addr.to_s.should == @b.local_address.to_s
+ end
+ end
+
+ it 'returns an Addrinfo' do
+ @addr.should be_an_instance_of(Addrinfo)
+ end
+
+ it 'uses 0 as the protocol' do
+ @addr.protocol.should == 0
+ end
+
+ it 'can be used to connect to the server' do
+ skip if @method == :local_address
+ b = @addr.connect
+ begin
+ b.remote_address.to_s.should == @addr.to_s
+ ensure
+ b.close
+ end
+ end
+ end
+ end
+
+ with_feature :unix_socket do
+ describe 'using UNIXSocket' do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @s = UNIXServer.new(@path)
+ @a = UNIXSocket.new(@path)
+ @b = @s.accept
+ @addr = @object.call(@a)
+ end
+
+ after :each do
+ [@b, @a, @s].each(&:close)
+ rm_r(@path)
+ end
+
+ it 'uses AF_UNIX as the address family' do
+ @addr.afamily.should == Socket::AF_UNIX
+ end
+
+ it 'uses PF_UNIX as the protocol family' do
+ @addr.pfamily.should == Socket::PF_UNIX
+ end
+
+ it 'uses SOCK_STREAM as the socket type' do
+ @addr.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it 'uses the correct socket path' do
+ if @method == :local_address
+ @addr.unix_path.should == ""
+ else
+ @addr.unix_path.should == @path
+ end
+ end
+
+ it 'equals address of peer socket' do
+ if @method == :local_address
+ @addr.to_s.should == @b.remote_address.to_s
+ else
+ @addr.to_s.should == @b.local_address.to_s
+ end
+ end
+
+ it 'returns an Addrinfo' do
+ @addr.should be_an_instance_of(Addrinfo)
+ end
+
+ it 'uses 0 as the protocol' do
+ @addr.protocol.should == 0
+ end
+
+ it 'can be used to connect to the server' do
+ skip if @method == :local_address
+ b = @addr.connect
+ begin
+ b.remote_address.to_s.should == @addr.to_s
+ ensure
+ b.close
+ end
+ end
+ end
+ end
+
+ describe 'using UDPSocket' do
+ before :each do
+ @s = UDPSocket.new
+ @s.bind("127.0.0.1", 0)
+ @a = UDPSocket.new
+ @a.connect("127.0.0.1", @s.addr[1])
+ @addr = @object.call(@a)
+ end
+
+ after :each do
+ [@a, @s].each(&:close)
+ end
+
+ it 'uses the correct address family' do
+ @addr.afamily.should == Socket::AF_INET
+ end
+
+ it 'uses the correct protocol family' do
+ @addr.pfamily.should == Socket::PF_INET
+ end
+
+ it 'uses SOCK_DGRAM as the socket type' do
+ @addr.socktype.should == Socket::SOCK_DGRAM
+ end
+
+ it 'uses the correct IP address' do
+ @addr.ip_address.should == '127.0.0.1'
+ end
+
+ it 'uses the correct port' do
+ if @method == :local_address
+ @addr.ip_port.should != @s.addr[1]
+ else
+ @addr.ip_port.should == @s.addr[1]
+ end
+ end
+
+ it 'returns an Addrinfo' do
+ @addr.should be_an_instance_of(Addrinfo)
+ end
+
+ it 'uses 0 as the protocol' do
+ @addr.protocol.should == 0
+ end
+
+ it 'can be used to connect to the peer' do
+ b = @addr.connect
+ begin
+ b.remote_address.to_s.should == @addr.to_s
+ ensure
+ b.close
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/shared/pack_sockaddr.rb b/spec/ruby/library/socket/shared/pack_sockaddr.rb
index 2df09027c9..9f6238e7bc 100644
--- a/spec/ruby/library/socket/shared/pack_sockaddr.rb
+++ b/spec/ruby/library/socket/shared/pack_sockaddr.rb
@@ -19,6 +19,13 @@ describe :socket_pack_sockaddr_in, shared: true do
Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '127.0.0.1']
end
+ platform_is_not :solaris do
+ it 'resolves the service name to a port' do
+ sockaddr_in = Socket.public_send(@method, 'http', '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
+ end
+ end
+
describe 'using an IPv4 address' do
it 'returns a String of 16 bytes' do
str = Socket.public_send(@method, 80, '127.0.0.1')
diff --git a/spec/ruby/library/socket/socket/bind_spec.rb b/spec/ruby/library/socket/socket/bind_spec.rb
index 0349df84a6..4465a3dafa 100644
--- a/spec/ruby/library/socket/socket/bind_spec.rb
+++ b/spec/ruby/library/socket/socket/bind_spec.rb
@@ -33,6 +33,7 @@ describe "Socket#bind on SOCK_DGRAM socket" do
platform_is_not :windows, :cygwin do
as_user do
+ break if File.read('/proc/sys/net/ipv4/ip_unprivileged_port_start').to_i <= 1 rescue nil
it "raises Errno::EACCES when the current user does not have permission to bind" do
sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1")
-> { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES)
@@ -74,6 +75,7 @@ describe "Socket#bind on SOCK_STREAM socket" do
platform_is_not :windows, :cygwin do
as_user do
+ break if File.read('/proc/sys/net/ipv4/ip_unprivileged_port_start').to_i <= 1 rescue nil
it "raises Errno::EACCES when the current user does not have permission to bind" do
sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1")
-> { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES)
@@ -113,6 +115,8 @@ describe 'Socket#bind' do
platform_is_not :windows do
as_user do
+ break if File.read('/proc/sys/net/ipv4/ip_unprivileged_port_start').to_i <= 1 rescue nil
+
it 'raises Errno::EACCES when the user is not allowed to bind to the port' do
sockaddr1 = Socket.pack_sockaddr_in(1, ip_address)
diff --git a/spec/ruby/library/socket/tcpsocket/initialize_spec.rb b/spec/ruby/library/socket/tcpsocket/initialize_spec.rb
index a3cee05412..065c8f4190 100644
--- a/spec/ruby/library/socket/tcpsocket/initialize_spec.rb
+++ b/spec/ruby/library/socket/tcpsocket/initialize_spec.rb
@@ -1,5 +1,10 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
+require_relative 'shared/new'
+
+describe 'TCPSocket#initialize' do
+ it_behaves_like :tcpsocket_new, :new
+end
describe 'TCPSocket#initialize' do
SocketSpecs.each_ip_protocol do |family, ip_address|
diff --git a/spec/ruby/library/socket/tcpsocket/new_spec.rb b/spec/ruby/library/socket/tcpsocket/new_spec.rb
deleted file mode 100644
index 4924468be7..0000000000
--- a/spec/ruby/library/socket/tcpsocket/new_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative 'shared/new'
-
-describe "TCPSocket.new" do
- it_behaves_like :tcpsocket_new, :new
-end
diff --git a/spec/ruby/library/socket/tcpsocket/shared/new.rb b/spec/ruby/library/socket/tcpsocket/shared/new.rb
index 5ca3a0e6cc..e7eb2f3c13 100644
--- a/spec/ruby/library/socket/tcpsocket/shared/new.rb
+++ b/spec/ruby/library/socket/tcpsocket/shared/new.rb
@@ -14,6 +14,22 @@ describe :tcpsocket_new, shared: true do
}
end
+ ruby_version_is "3.0"..."3.1" do
+ it 'raises Errno::ETIMEDOUT with :connect_timeout when no server is listening on the given address' do
+ -> {
+ TCPSocket.send(@method, "192.0.2.1", 80, connect_timeout: 0)
+ }.should raise_error(Errno::ETIMEDOUT)
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it 'raises IO::TimeoutError with :connect_timeout when no server is listening on the given address' do
+ -> {
+ TCPSocket.send(@method, "192.0.2.1", 80, connect_timeout: 0)
+ }.should raise_error(IO::TimeoutError)
+ end
+ end
+
describe "with a running server" do
before :each do
@server = SocketSpecs::SpecTCPServer.new
@@ -75,5 +91,12 @@ describe :tcpsocket_new, shared: true do
@socket.addr[1].should be_kind_of(Integer)
@socket.addr[2].should =~ /^#{@hostname}/
end
+
+ ruby_version_is "3.0" do
+ it "connects to a server when passed connect_timeout argument" do
+ @socket = TCPSocket.send(@method, @hostname, @server.port, connect_timeout: 1)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+ end
end
end
diff --git a/spec/ruby/library/stringio/append_spec.rb b/spec/ruby/library/stringio/append_spec.rb
index d0cf5550cd..981229fc10 100644
--- a/spec/ruby/library/stringio/append_spec.rb
+++ b/spec/ruby/library/stringio/append_spec.rb
@@ -29,13 +29,6 @@ describe "StringIO#<< when passed [Object]" do
@io.string.should == "example\000\000\000\000\000\000\000\000just testing"
end
- ruby_version_is ""..."2.7" do
- it "taints self's String when the passed argument is tainted" do
- (@io << "test".taint)
- @io.string.tainted?.should be_true
- end
- end
-
ruby_version_is ""..."3.0" do
it "does not taint self when the passed argument is tainted" do
(@io << "test".taint)
diff --git a/spec/ruby/library/stringio/each_line_spec.rb b/spec/ruby/library/stringio/each_line_spec.rb
index 1389408399..c68f7dae82 100644
--- a/spec/ruby/library/stringio/each_line_spec.rb
+++ b/spec/ruby/library/stringio/each_line_spec.rb
@@ -17,3 +17,7 @@ end
describe "StringIO#each_line when passed chomp" do
it_behaves_like :stringio_each_chomp, :each_line
end
+
+describe "StringIO#each_line when passed limit" do
+ it_behaves_like :stringio_each_limit, :each_line
+end
diff --git a/spec/ruby/library/stringio/each_spec.rb b/spec/ruby/library/stringio/each_spec.rb
index a76460049b..2c30ed5cda 100644
--- a/spec/ruby/library/stringio/each_spec.rb
+++ b/spec/ruby/library/stringio/each_spec.rb
@@ -17,3 +17,11 @@ end
describe "StringIO#each when passed chomp" do
it_behaves_like :stringio_each_chomp, :each
end
+
+describe "StringIO#each when passed chomp" do
+ it_behaves_like :stringio_each_separator_and_chomp, :each
+end
+
+describe "StringIO#each when passed limit" do
+ it_behaves_like :stringio_each_limit, :each
+end
diff --git a/spec/ruby/library/stringio/gets_spec.rb b/spec/ruby/library/stringio/gets_spec.rb
index 97429e6a29..d597ec0e45 100644
--- a/spec/ruby/library/stringio/gets_spec.rb
+++ b/spec/ruby/library/stringio/gets_spec.rb
@@ -171,6 +171,10 @@ describe "StringIO#gets when passed [limit]" do
it "returns a blank string when passed a limit of 0" do
@io.gets(0).should == ""
end
+
+ it "ignores it when passed a negative limit" do
+ @io.gets(-4).should == "this>is>an>example"
+ end
end
describe "StringIO#gets when passed [separator] and [limit]" do
diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb
index 1e8096e3bb..c597e328d3 100644
--- a/spec/ruby/library/stringio/initialize_spec.rb
+++ b/spec/ruby/library/stringio/initialize_spec.rb
@@ -163,6 +163,91 @@ describe "StringIO#initialize when passed [Object]" do
end
end
+# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
+describe "StringIO#initialize when passed keyword arguments" do
+ it "sets the mode based on the passed :mode option" do
+ io = StringIO.new("example", "r")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+ end
+
+ it "accepts a mode argument set to nil with a valid :mode option" do
+ @io = StringIO.new('', nil, mode: "w")
+ @io.write("foo").should == 3
+ end
+
+ it "accepts a mode argument with a :mode option set to nil" do
+ @io = StringIO.new('', "w", mode: nil)
+ @io.write("foo").should == 3
+ end
+
+ it "sets binmode from :binmode option" do
+ @io = StringIO.new('', 'w', binmode: true)
+ @io.external_encoding.to_s.should == "ASCII-8BIT" # #binmode? isn't implemented in StringIO
+ end
+
+ it "does not set binmode from false :binmode" do
+ @io = StringIO.new('', 'w', binmode: false)
+ @io.external_encoding.to_s.should == "UTF-8" # #binmode? isn't implemented in StringIO
+ end
+end
+
+# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
+describe "StringIO#initialize when passed keyword arguments and error happens" do
+ it "raises an error if passed encodings two ways" do
+ -> {
+ @io = StringIO.new('', 'w:ISO-8859-1', encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', 'w:ISO-8859-1', external_encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', 'w:ISO-8859-1:UTF-8', internal_encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error if passed matching binary/text mode two ways" do
+ -> {
+ @io = StringIO.new('', "wb", binmode: true)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', "wt", textmode: true)
+ }.should raise_error(ArgumentError)
+
+ -> {
+ @io = StringIO.new('', "wb", textmode: false)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', "wt", binmode: false)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error if passed conflicting binary/text mode two ways" do
+ -> {
+ @io = StringIO.new('', "wb", binmode: false)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', "wt", textmode: false)
+ }.should raise_error(ArgumentError)
+
+ -> {
+ @io = StringIO.new('', "wb", textmode: true)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', "wt", binmode: true)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error when trying to set both binmode and textmode" do
+ -> {
+ @io = StringIO.new('', "w", textmode: true, binmode: true)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new('', File::Constants::WRONLY, textmode: true, binmode: true)
+ }.should raise_error(ArgumentError)
+ end
+end
+
describe "StringIO#initialize when passed no arguments" do
before :each do
@io = StringIO.allocate
diff --git a/spec/ruby/library/stringio/new_spec.rb b/spec/ruby/library/stringio/new_spec.rb
new file mode 100644
index 0000000000..e36d210caa
--- /dev/null
+++ b/spec/ruby/library/stringio/new_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require 'stringio'
+
+describe "StringIO.new" do
+ it "warns when called with a block" do
+ -> { eval("StringIO.new {}") }.should complain(/StringIO::new\(\) does not take block; use StringIO::open\(\) instead/)
+ end
+end \ No newline at end of file
diff --git a/spec/ruby/library/stringio/open_spec.rb b/spec/ruby/library/stringio/open_spec.rb
index acab6e9056..3068e19435 100644
--- a/spec/ruby/library/stringio/open_spec.rb
+++ b/spec/ruby/library/stringio/open_spec.rb
@@ -167,10 +167,14 @@ describe "StringIO.open when passed [Object]" do
io.should equal(ret)
end
- it "sets the mode to read-write" do
+ it "sets the mode to read-write (r+)" do
io = StringIO.open("example")
io.closed_read?.should be_false
io.closed_write?.should be_false
+
+ io = StringIO.new("example")
+ io.printf("%d", 123)
+ io.string.should == "123mple"
end
it "tries to convert the passed Object to a String using #to_str" do
@@ -195,10 +199,14 @@ describe "StringIO.open when passed no arguments" do
io.should equal(ret)
end
- it "sets the mode to read-write" do
+ it "sets the mode to read-write (r+)" do
io = StringIO.open
io.closed_read?.should be_false
io.closed_write?.should be_false
+
+ io = StringIO.new("example")
+ io.printf("%d", 123)
+ io.string.should == "123mple"
end
it "uses an empty String as the StringIO backend" do
diff --git a/spec/ruby/library/stringio/printf_spec.rb b/spec/ruby/library/stringio/printf_spec.rb
index 9dd1a3b410..f3f669a185 100644
--- a/spec/ruby/library/stringio/printf_spec.rb
+++ b/spec/ruby/library/stringio/printf_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../core/kernel/shared/sprintf'
describe "StringIO#printf" do
before :each do
- @io = StringIO.new('example')
+ @io = StringIO.new()
end
it "returns nil" do
@@ -12,9 +12,9 @@ describe "StringIO#printf" do
end
it "pads self with \\000 when the current position is after the end" do
- @io.pos = 10
+ @io.pos = 3
@io.printf("%d", 123)
- @io.string.should == "example\000\000\000123"
+ @io.string.should == "\000\000\000123"
end
it "performs format conversion" do
@@ -39,6 +39,27 @@ describe "StringIO#printf" do
end
end
+describe "StringIO#printf when in read-write mode" do
+ before :each do
+ @io = StringIO.new("example", "r+")
+ end
+
+ it "starts from the beginning" do
+ @io.printf("%s", "abcdefghijk")
+ @io.string.should == "abcdefghijk"
+ end
+
+ it "does not truncate existing string" do
+ @io.printf("%s", "abc")
+ @io.string.should == "abcmple"
+ end
+
+ it "correctly updates self's position" do
+ @io.printf("%s", "abc")
+ @io.pos.should eql(3)
+ end
+end
+
describe "StringIO#printf when in append mode" do
before :each do
@io = StringIO.new("example", "a")
diff --git a/spec/ruby/library/stringio/putc_spec.rb b/spec/ruby/library/stringio/putc_spec.rb
index 223b3523e5..1ce53b7ef2 100644
--- a/spec/ruby/library/stringio/putc_spec.rb
+++ b/spec/ruby/library/stringio/putc_spec.rb
@@ -35,6 +35,21 @@ describe "StringIO#putc when passed [String]" do
@io.putc("t")
@io.pos.should == 3
end
+
+ it "handles concurrent writes correctly" do
+ @io = StringIO.new
+ n = 8
+ go = false
+ threads = n.times.map { |i|
+ Thread.new {
+ Thread.pass until go
+ @io.putc i.to_s
+ }
+ }
+ go = true
+ threads.each(&:join)
+ @io.string.size.should == n
+ end
end
describe "StringIO#putc when passed [Object]" do
diff --git a/spec/ruby/library/stringio/puts_spec.rb b/spec/ruby/library/stringio/puts_spec.rb
index a9f289a5a5..9c890262dd 100644
--- a/spec/ruby/library/stringio/puts_spec.rb
+++ b/spec/ruby/library/stringio/puts_spec.rb
@@ -101,6 +101,20 @@ describe "StringIO#puts when passed 1 or more objects" do
@io.puts ''
@io.string.should == "\n"
end
+
+ it "handles concurrent writes correctly" do
+ n = 8
+ go = false
+ threads = n.times.map { |i|
+ Thread.new {
+ Thread.pass until go
+ @io.puts i
+ }
+ }
+ go = true
+ threads.each(&:join)
+ @io.string.size.should == n.times.map { |i| "#{i}\n" }.join.size
+ end
end
describe "StringIO#puts when passed no arguments" do
diff --git a/spec/ruby/library/stringio/read_nonblock_spec.rb b/spec/ruby/library/stringio/read_nonblock_spec.rb
index 2a8f926bd0..d4ec56d9aa 100644
--- a/spec/ruby/library/stringio/read_nonblock_spec.rb
+++ b/spec/ruby/library/stringio/read_nonblock_spec.rb
@@ -5,10 +5,21 @@ require_relative 'shared/sysread'
describe "StringIO#read_nonblock when passed length, buffer" do
it_behaves_like :stringio_read, :read_nonblock
+
+ it "accepts :exception option" do
+ io = StringIO.new("example")
+ io.read_nonblock(3, buffer = "", exception: true)
+ buffer.should == "exa"
+ end
end
describe "StringIO#read_nonblock when passed length" do
it_behaves_like :stringio_read_length, :read_nonblock
+
+ it "accepts :exception option" do
+ io = StringIO.new("example")
+ io.read_nonblock(3, exception: true).should == "exa"
+ end
end
describe "StringIO#read_nonblock when passed nil" do
diff --git a/spec/ruby/library/stringio/readline_spec.rb b/spec/ruby/library/stringio/readline_spec.rb
index 94b67bc92d..b794e5fade 100644
--- a/spec/ruby/library/stringio/readline_spec.rb
+++ b/spec/ruby/library/stringio/readline_spec.rb
@@ -128,3 +128,23 @@ describe "StringIO#readline when passed [chomp]" do
io.readline(chomp: true).should == "this>is>an>example"
end
end
+
+describe "StringIO#readline when passed [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is met" do
+ io = StringIO.new("this>is>an>example\n")
+ io.readline(3).should == "thi"
+ end
+
+ it "returns a blank string when passed a limit of 0" do
+ @io.readline(0).should == ""
+ end
+
+ it "ignores it when the limit is negative" do
+ seen = []
+ @io.readline(-4).should == "this>is>an>example"
+ end
+end
diff --git a/spec/ruby/library/stringio/readlines_spec.rb b/spec/ruby/library/stringio/readlines_spec.rb
index 4b007787e2..c471d0fd73 100644
--- a/spec/ruby/library/stringio/readlines_spec.rb
+++ b/spec/ruby/library/stringio/readlines_spec.rb
@@ -98,3 +98,21 @@ describe "StringIO#readlines when passed [chomp]" do
io.readlines(chomp: true).should == ["this>is", "an>example"]
end
end
+
+describe "StringIO#readlines when passed [limit]" do
+ before :each do
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
+ end
+
+ it "returns the data read until the limit is met" do
+ @io.readlines(4).should == ["a b ", "c d ", "e\n", "1 2 ", "3 4 ", "5"]
+ end
+
+ it "raises ArgumentError when limit is 0" do
+ -> { @io.readlines(0) }.should raise_error(ArgumentError)
+ end
+
+ it "ignores it when the limit is negative" do
+ @io.readlines(-4).should == ["a b c d e\n", "1 2 3 4 5"]
+ end
+end
diff --git a/spec/ruby/library/stringio/reopen_spec.rb b/spec/ruby/library/stringio/reopen_spec.rb
index 6752cf9970..4863a5332b 100644
--- a/spec/ruby/library/stringio/reopen_spec.rb
+++ b/spec/ruby/library/stringio/reopen_spec.rb
@@ -206,14 +206,6 @@ describe "StringIO#reopen when passed [Object]" do
@io.reopen(obj)
@io.string.should == "to_strio"
end
-
- # NOTE: WEIRD!
- ruby_version_is ""..."2.7" do
- it "taints self when the passed Object was tainted" do
- @io.reopen(StringIO.new("reopened").taint)
- @io.tainted?.should be_true
- end
- end
end
describe "StringIO#reopen when passed no arguments" do
@@ -278,15 +270,6 @@ describe "StringIO#reopen" do
str.should == ''
end
- ruby_version_is ""..."2.7" do
- it "taints self if the provided StringIO argument is tainted" do
- new_io = StringIO.new("tainted")
- new_io.taint
- @io.reopen(new_io)
- @io.should.tainted?
- end
- end
-
it "does not truncate the content even when the StringIO argument is in the truncate mode" do
orig_io = StringIO.new("Original StringIO", IO::RDWR|IO::TRUNC)
orig_io.write("BLAH") # make sure the content is not empty
diff --git a/spec/ruby/library/stringio/shared/each.rb b/spec/ruby/library/stringio/shared/each.rb
index 14b0a013b3..bf3265ee46 100644
--- a/spec/ruby/library/stringio/shared/each.rb
+++ b/spec/ruby/library/stringio/shared/each.rb
@@ -36,11 +36,22 @@ describe :stringio_each_separator, shared: true do
seen.should == ["2 1 2 1 2"]
end
- it "yields each paragraph when passed an empty String as separator" do
- seen = []
- io = StringIO.new("para1\n\npara2\n\n\npara3")
- io.send(@method, "") {|s| seen << s}
- seen.should == ["para1\n\n", "para2\n\n", "para3"]
+ ruby_version_is ''..."3.2" do
+ it "yields each paragraph with two separation characters when passed an empty String as separator" do
+ seen = []
+ io = StringIO.new("para1\n\npara2\n\n\npara3")
+ io.send(@method, "") {|s| seen << s}
+ seen.should == ["para1\n\n", "para2\n\n", "para3"]
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "yields each paragraph with all separation characters when passed an empty String as separator" do
+ seen = []
+ io = StringIO.new("para1\n\npara2\n\n\npara3")
+ io.send(@method, "") {|s| seen << s}
+ seen.should == ["para1\n\n", "para2\n\n\n", "para3"]
+ end
end
end
@@ -112,4 +123,41 @@ describe :stringio_each_chomp, shared: true do
io.send(@method, chomp: true) {|s| seen << s }
seen.should == ["a b \rc d e", "1 2 3 4 5", "the end"]
end
+
+ it "returns each line with removed newline characters when called without block" do
+ seen = []
+ io = StringIO.new("a b \rc d e\n1 2 3 4 5\r\nthe end")
+ enum = io.send(@method, chomp: true)
+ enum.each {|s| seen << s }
+ seen.should == ["a b \rc d e", "1 2 3 4 5", "the end"]
+ end
+end
+
+describe :stringio_each_separator_and_chomp, shared: true do
+ it "yields each line with removed separator to the passed block" do
+ seen = []
+ io = StringIO.new("a b \nc d e|1 2 3 4 5\n|the end")
+ io.send(@method, "|", chomp: true) {|s| seen << s }
+ seen.should == ["a b \nc d e", "1 2 3 4 5\n", "the end"]
+ end
+
+ it "returns each line with removed separator when called without block" do
+ seen = []
+ io = StringIO.new("a b \nc d e|1 2 3 4 5\n|the end")
+ enum = io.send(@method, "|", chomp: true)
+ enum.each {|s| seen << s }
+ seen.should == ["a b \nc d e", "1 2 3 4 5\n", "the end"]
+ end
+end
+
+describe :stringio_each_limit, shared: true do
+ before :each do
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
+ end
+
+ it "returns the data read until the limit is met" do
+ seen = []
+ @io.send(@method, 4) { |s| seen << s }
+ seen.should == ["a b ", "c d ", "e\n", "1 2 ", "3 4 ", "5"]
+ end
end
diff --git a/spec/ruby/library/stringio/shared/read.rb b/spec/ruby/library/stringio/shared/read.rb
index c60677bba7..252a85d89d 100644
--- a/spec/ruby/library/stringio/shared/read.rb
+++ b/spec/ruby/library/stringio/shared/read.rb
@@ -89,6 +89,12 @@ describe :stringio_read_no_arguments, shared: true do
@io.send(@method)
@io.pos.should eql(7)
end
+
+ it "correctly update the current position in bytes when multi-byte characters are used" do
+ @io.print("example\u03A3") # Overwrite the original string with 8 characters containing 9 bytes.
+ @io.send(@method)
+ @io.pos.should eql(9)
+ end
end
describe :stringio_read_nil, shared: true do
diff --git a/spec/ruby/library/stringio/shared/write.rb b/spec/ruby/library/stringio/shared/write.rb
index 080729217b..d9c21028e0 100644
--- a/spec/ruby/library/stringio/shared/write.rb
+++ b/spec/ruby/library/stringio/shared/write.rb
@@ -45,11 +45,19 @@ describe :stringio_write_string, shared: true do
@io.pos.should eql(4)
end
- ruby_version_is ""..."2.7" do
- it "taints self's String when the passed argument is tainted" do
- @io.send(@method, "test".taint)
- @io.string.tainted?.should be_true
- end
+ it "handles concurrent writes correctly" do
+ @io = StringIO.new
+ n = 8
+ go = false
+ threads = n.times.map { |i|
+ Thread.new {
+ Thread.pass until go
+ @io.write i.to_s
+ }
+ }
+ go = true
+ threads.each(&:join)
+ @io.string.size.should == n.times.map(&:to_s).join.size
end
ruby_version_is ""..."3.0" do
@@ -58,6 +66,28 @@ describe :stringio_write_string, shared: true do
@io.tainted?.should be_false
end
end
+
+ it "handles writing non-ASCII UTF-8 after seek" do
+ @io.binmode
+ @io << "\x80"
+ @io.pos = 0
+ @io << "\x81"
+ @io.string.should == "\x812345".b
+ end
+
+ it "handles writing with position < buffer size" do
+ @io.pos = 2
+ @io.write "abc"
+ @io.string.should == "12abc"
+
+ @io.pos = 2
+ @io.write "de"
+ @io.string.should == "12dec"
+
+ @io.pos = 2
+ @io.write "fghi"
+ @io.string.should == "12fghi"
+ end
end
describe :stringio_write_not_writable, shared: true do
diff --git a/spec/ruby/library/stringio/truncate_spec.rb b/spec/ruby/library/stringio/truncate_spec.rb
index ba910ee98c..e8d7f1a15d 100644
--- a/spec/ruby/library/stringio/truncate_spec.rb
+++ b/spec/ruby/library/stringio/truncate_spec.rb
@@ -6,10 +6,8 @@ describe "StringIO#truncate when passed [length]" do
@io = StringIO.new('123456789')
end
- # TODO: Report to Ruby-Core: The RDoc says it always returns 0
- it "returns the passed length" do
- @io.truncate(4).should eql(4)
- @io.truncate(10).should eql(10)
+ it "returns an Integer" do
+ @io.truncate(4).should be_kind_of(Integer)
end
it "truncated the underlying string down to the passed length" do
@@ -47,12 +45,6 @@ describe "StringIO#truncate when passed [length]" do
@io.string.should == "1234"
end
- it "returns the passed length Object, NOT the result of #to_int" do
- obj = mock("to_int")
- obj.should_receive(:to_int).and_return(4)
- @io.truncate(obj).should equal(obj)
- end
-
it "raises a TypeError when the passed length can't be converted to an Integer" do
-> { @io.truncate(Object.new) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/library/stringio/ungetbyte_spec.rb b/spec/ruby/library/stringio/ungetbyte_spec.rb
index 701463e621..87b27b837e 100644
--- a/spec/ruby/library/stringio/ungetbyte_spec.rb
+++ b/spec/ruby/library/stringio/ungetbyte_spec.rb
@@ -1,6 +1,42 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require 'stringio'
describe "StringIO#ungetbyte" do
- it "needs to be reviewed for spec completeness"
+ it "ungets a single byte from a string starting with a single byte character" do
+ str = 'This is a simple string.'
+ io = StringIO.new("#{str}")
+ c = io.getc
+ c.should == 'T'
+ io.ungetbyte(83)
+ io.string.should == 'Shis is a simple string.'
+ end
+
+ it "ungets a single byte from a string in the middle of a multibyte character" do
+ str = "\u01a9"
+ io = StringIO.new(str)
+ b = io.getbyte
+ b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9
+ io.ungetbyte(0xce) # First byte of UTF-8 encoding of \u03a9
+ io.string.should == "\u03a9"
+ end
+
+ it "constrains the value of a numeric argument to a single byte" do
+ str = 'This is a simple string.'
+ io = StringIO.new("#{str}")
+ c = io.getc
+ c.should == 'T'
+ io.ungetbyte(83 | 0xff00)
+ io.string.should == 'Shis is a simple string.'
+ end
+
+ it "ungets the bytes of a string if given a string as an argument" do
+ str = "\u01a9"
+ io = StringIO.new(str)
+ b = io.getbyte
+ b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9
+ io.ungetbyte("\u01a9")
+ io.string.bytes.should == [198, 169, 169]
+ end
+
end
diff --git a/spec/ruby/library/stringio/write_nonblock_spec.rb b/spec/ruby/library/stringio/write_nonblock_spec.rb
index 4f4c5039fe..a457b97667 100644
--- a/spec/ruby/library/stringio/write_nonblock_spec.rb
+++ b/spec/ruby/library/stringio/write_nonblock_spec.rb
@@ -8,6 +8,12 @@ end
describe "StringIO#write_nonblock when passed [String]" do
it_behaves_like :stringio_write_string, :write_nonblock
+
+ it "accepts :exception option" do
+ io = StringIO.new("12345", "a")
+ io.write_nonblock("67890", exception: true)
+ io.string.should == "1234567890"
+ end
end
describe "StringIO#write_nonblock when self is not writable" do
diff --git a/spec/ruby/library/stringscanner/check_spec.rb b/spec/ruby/library/stringscanner/check_spec.rb
index c7f788f0b3..a97c26af83 100644
--- a/spec/ruby/library/stringscanner/check_spec.rb
+++ b/spec/ruby/library/stringscanner/check_spec.rb
@@ -13,4 +13,13 @@ describe "StringScanner#check" do
@s.check(/is/).should == nil
@s.matched.should == nil
end
+
+ it "treats String as the pattern itself" do
+ @s.check("This").should == "This"
+ @s.matched.should == "This"
+ @s.pos.should == 0
+ @s.check(/is/).should == nil
+ @s.matched.should == nil
+ end
+
end
diff --git a/spec/ruby/library/stringscanner/check_until_spec.rb b/spec/ruby/library/stringscanner/check_until_spec.rb
index e92ae5a2e9..ad222fd76b 100644
--- a/spec/ruby/library/stringscanner/check_until_spec.rb
+++ b/spec/ruby/library/stringscanner/check_until_spec.rb
@@ -12,4 +12,10 @@ describe "StringScanner#check_until" do
@s.matched.should == "a"
@s.check_until(/test/).should == "This is a test"
end
+
+ it "raises TypeError if given a String" do
+ -> {
+ @s.check_until('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
end
diff --git a/spec/ruby/library/stringscanner/exist_spec.rb b/spec/ruby/library/stringscanner/exist_spec.rb
index beafadc07b..ff860a0d3e 100644
--- a/spec/ruby/library/stringscanner/exist_spec.rb
+++ b/spec/ruby/library/stringscanner/exist_spec.rb
@@ -21,4 +21,10 @@ describe "StringScanner#exist?" do
@s.scan(/This is/)
@s.exist?(/i/).should == nil
end
+
+ it "raises TypeError if given a String" do
+ -> {
+ @s.exist?('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
end
diff --git a/spec/ruby/library/stringscanner/matched_size_spec.rb b/spec/ruby/library/stringscanner/matched_size_spec.rb
index a36bd3aafe..d9c338a07e 100644
--- a/spec/ruby/library/stringscanner/matched_size_spec.rb
+++ b/spec/ruby/library/stringscanner/matched_size_spec.rb
@@ -1,7 +1,24 @@
require_relative '../../spec_helper'
-require_relative 'shared/matched_size'
require 'strscan'
describe "StringScanner#matched_size" do
- it_behaves_like :strscan_matched_size, :matched_size
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the size of the most recent match" do
+ @s.check(/This/)
+ @s.matched_size.should == 4
+ @s.matched_size.should == 4
+ @s.scan(//)
+ @s.matched_size.should == 0
+ end
+
+ it "returns nil if there was no recent match" do
+ @s.matched_size.should == nil
+ @s.check(/\d+/)
+ @s.matched_size.should == nil
+ @s.terminate
+ @s.matched_size.should == nil
+ end
end
diff --git a/spec/ruby/library/stringscanner/scan_spec.rb b/spec/ruby/library/stringscanner/scan_spec.rb
index 2269abd6b3..ea711767b9 100644
--- a/spec/ruby/library/stringscanner/scan_spec.rb
+++ b/spec/ruby/library/stringscanner/scan_spec.rb
@@ -50,17 +50,9 @@ describe "StringScanner#scan" do
@s.scan(/./).should be_nil
end
- ruby_version_is ""..."2.7" do
- it "raises a TypeError if pattern is a String" do
- -> { @s.scan("aoeu") }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is "2.7" do
- it "treats String as the pattern itself" do
- @s.scan("this").should be_nil
- @s.scan("This").should == "This"
- end
+ it "treats String as the pattern itself" do
+ @s.scan("this").should be_nil
+ @s.scan("This").should == "This"
end
it "raises a TypeError if pattern isn't a Regexp nor String" do
@@ -75,23 +67,21 @@ describe "StringScanner#scan with fixed_anchor: true" do
@s = StringScanner.new("This\nis\na\ntest", fixed_anchor: true)
end
- ruby_version_is "2.7" do
- it "returns the matched string" do
- @s.scan(/\w+/).should == "This"
- @s.scan(/.../m).should == "\nis"
- @s.scan(//).should == ""
- @s.scan(/\s+/).should == "\n"
- end
+ it "returns the matched string" do
+ @s.scan(/\w+/).should == "This"
+ @s.scan(/.../m).should == "\nis"
+ @s.scan(//).should == ""
+ @s.scan(/\s+/).should == "\n"
+ end
- it "treats ^ as matching from the beginning of line" do
- @s.scan(/\w+\n/).should == "This\n"
- @s.scan(/^\w/).should == "i"
- @s.scan(/^\w/).should be_nil
- end
+ it "treats ^ as matching from the beginning of line" do
+ @s.scan(/\w+\n/).should == "This\n"
+ @s.scan(/^\w/).should == "i"
+ @s.scan(/^\w/).should be_nil
+ end
- it "treats \\A as matching from the beginning of string" do
- @s.scan(/\A\w/).should == "T"
- @s.scan(/\A\w/).should be_nil
- end
+ it "treats \\A as matching from the beginning of string" do
+ @s.scan(/\A\w/).should == "T"
+ @s.scan(/\A\w/).should be_nil
end
end
diff --git a/spec/ruby/library/stringscanner/scan_until_spec.rb b/spec/ruby/library/stringscanner/scan_until_spec.rb
index 94239db50e..6b7782572d 100644
--- a/spec/ruby/library/stringscanner/scan_until_spec.rb
+++ b/spec/ruby/library/stringscanner/scan_until_spec.rb
@@ -20,4 +20,10 @@ describe "StringScanner#scan_until" do
@s.scan(/T/)
@s.scan_until(/^h/).should == "h"
end
+
+ it "raises TypeError if given a String" do
+ -> {
+ @s.scan_until('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
end
diff --git a/spec/ruby/library/stringscanner/search_full_spec.rb b/spec/ruby/library/stringscanner/search_full_spec.rb
index da9067e012..7d2a714fa5 100644
--- a/spec/ruby/library/stringscanner/search_full_spec.rb
+++ b/spec/ruby/library/stringscanner/search_full_spec.rb
@@ -27,4 +27,10 @@ describe "StringScanner#search_full" do
@s.search_full(/This/, true, true).should == "This"
@s.pos.should == 4
end
+
+ it "raises TypeError if given a String" do
+ -> {
+ @s.search_full('T', true, true)
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
end
diff --git a/spec/ruby/library/stringscanner/shared/extract_range.rb b/spec/ruby/library/stringscanner/shared/extract_range.rb
index 1c14f716c9..e7404fd0cb 100644
--- a/spec/ruby/library/stringscanner/shared/extract_range.rb
+++ b/spec/ruby/library/stringscanner/shared/extract_range.rb
@@ -8,17 +8,4 @@ describe :extract_range, shared: true do
ch.should_not be_kind_of(cls)
ch.should be_an_instance_of(String)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned String if the input was tainted" do
- str = 'abc'
- str.taint
-
- s = StringScanner.new(str)
-
- s.send(@method).tainted?.should be_true
- s.send(@method).tainted?.should be_true
- s.send(@method).tainted?.should be_true
- end
- end
end
diff --git a/spec/ruby/library/stringscanner/shared/extract_range_matched.rb b/spec/ruby/library/stringscanner/shared/extract_range_matched.rb
index 5c536f5c01..070a132812 100644
--- a/spec/ruby/library/stringscanner/shared/extract_range_matched.rb
+++ b/spec/ruby/library/stringscanner/shared/extract_range_matched.rb
@@ -10,15 +10,4 @@ describe :extract_range_matched, shared: true do
ch.should_not be_kind_of(cls)
ch.should be_an_instance_of(String)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned String if the input was tainted" do
- str = 'abc'
- str.taint
-
- s = StringScanner.new(str)
- s.scan(/\w{1}/)
- s.send(@method).tainted?.should be_true
- end
- end
end
diff --git a/spec/ruby/library/stringscanner/shared/matched_size.rb b/spec/ruby/library/stringscanner/shared/matched_size.rb
deleted file mode 100644
index 92174733f7..0000000000
--- a/spec/ruby/library/stringscanner/shared/matched_size.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-describe :strscan_matched_size, shared: true do
- before :each do
- @s = StringScanner.new("This is a test")
- end
-
- it "returns the size of the most recent match" do
- @s.check(/This/)
- @s.send(@method).should == 4
- @s.send(@method).should == 4
- @s.scan(//)
- @s.send(@method).should == 0
- end
-
- it "returns nil if there was no recent match" do
- @s.send(@method).should == nil
- @s.check(/\d+/)
- @s.send(@method).should == nil
- @s.terminate
- @s.send(@method).should == nil
- end
-end
diff --git a/spec/ruby/library/stringscanner/shared/peek.rb b/spec/ruby/library/stringscanner/shared/peek.rb
index 4e2e643353..4c757866c1 100644
--- a/spec/ruby/library/stringscanner/shared/peek.rb
+++ b/spec/ruby/library/stringscanner/shared/peek.rb
@@ -36,14 +36,4 @@ describe :strscan_peek, shared: true do
ch.should_not be_kind_of(cls)
ch.should be_an_instance_of(String)
end
-
- ruby_version_is ''...'2.7' do
- it "taints the returned String if the input was tainted" do
- str = 'abc'
- str.taint
-
- s = StringScanner.new(str)
- s.send(@method, 1).tainted?.should be_true
- end
- end
end
diff --git a/spec/ruby/library/stringscanner/size_spec.rb b/spec/ruby/library/stringscanner/size_spec.rb
new file mode 100644
index 0000000000..3e475489e3
--- /dev/null
+++ b/spec/ruby/library/stringscanner/size_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+describe "StringScanner#size" do
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns the number of captures groups of the last match" do
+ @s.scan(/(.)(.)(.)/)
+ @s.size.should == 4
+ end
+
+ it "returns nil if there is no last match" do
+ @s.size.should == nil
+ end
+end
diff --git a/spec/ruby/library/stringscanner/skip_until_spec.rb b/spec/ruby/library/stringscanner/skip_until_spec.rb
index 73eb91b8ad..7b56f13e4f 100644
--- a/spec/ruby/library/stringscanner/skip_until_spec.rb
+++ b/spec/ruby/library/stringscanner/skip_until_spec.rb
@@ -15,4 +15,10 @@ describe "StringScanner#skip_until" do
it "returns nil if no match was found" do
@s.skip_until(/d+/).should == nil
end
+
+ it "raises TypeError if given a String" do
+ -> {
+ @s.skip_until('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
end
diff --git a/spec/ruby/library/time/to_datetime_spec.rb b/spec/ruby/library/time/to_datetime_spec.rb
index 0e37a61108..6025950b59 100644
--- a/spec/ruby/library/time/to_datetime_spec.rb
+++ b/spec/ruby/library/time/to_datetime_spec.rb
@@ -3,9 +3,9 @@ require 'time'
describe "Time#to_datetime" do
it "returns a DateTime representing the same instant" do
- time = Time.utc(3, 12, 31, 23, 58, 59)
+ time = Time.utc(2012, 12, 31, 23, 58, 59)
datetime = time.to_datetime
- datetime.year.should == 3
+ datetime.year.should == 2012
datetime.month.should == 12
datetime.day.should == 31
datetime.hour.should == 23
@@ -13,6 +13,20 @@ describe "Time#to_datetime" do
datetime.sec.should == 59
end
+ date_version = defined?(Date::VERSION) ? Date::VERSION : '0.0.0'
+ version_is(date_version, '3.2.3') do
+ it "returns a DateTime representing the same instant before Gregorian" do
+ time = Time.utc(1582, 10, 14, 23, 58, 59)
+ datetime = time.to_datetime
+ datetime.year.should == 1582
+ datetime.month.should == 10
+ datetime.day.should == 4
+ datetime.hour.should == 23
+ datetime.min.should == 58
+ datetime.sec.should == 59
+ end
+ end
+
it "roundtrips" do
time = Time.utc(3, 12, 31, 23, 58, 59)
datetime = time.to_datetime
diff --git a/spec/ruby/library/yaml/to_yaml_spec.rb b/spec/ruby/library/yaml/to_yaml_spec.rb
index 03ec4f6916..8e80b02cb4 100644
--- a/spec/ruby/library/yaml/to_yaml_spec.rb
+++ b/spec/ruby/library/yaml/to_yaml_spec.rb
@@ -72,16 +72,8 @@ describe "Object#to_yaml" do
true_klass.to_yaml.should match_yaml("--- true\n")
end
- ruby_version_is ""..."2.7" do
- it "returns the YAML representation of a Error object" do
- StandardError.new("foobar").to_yaml.should match_yaml("--- !ruby/exception:StandardError\nmessage: foobar\n")
- end
- end
-
- ruby_version_is "2.7" do
- it "returns the YAML representation of a Error object" do
- StandardError.new("foobar").to_yaml.should match_yaml("--- !ruby/exception:StandardError\nmessage: foobar\nbacktrace: \n")
- end
+ it "returns the YAML representation of a Error object" do
+ StandardError.new("foobar").to_yaml.should match_yaml("--- !ruby/exception:StandardError\nmessage: foobar\nbacktrace: \n")
end
it "returns the YAML representation for Range objects" do
diff --git a/spec/ruby/library/zlib/crc_table_spec.rb b/spec/ruby/library/zlib/crc_table_spec.rb
index f7fc2749fa..de8876086b 100644
--- a/spec/ruby/library/zlib/crc_table_spec.rb
+++ b/spec/ruby/library/zlib/crc_table_spec.rb
@@ -2,74 +2,79 @@ require_relative '../../spec_helper'
require "zlib"
describe "Zlib.crc_table" do
-
- it "returns the same value as zlib's get_crc_table()" do
- Zlib.crc_table.should == [
- 0, 1996959894, 3993919788, 2567524794,
- 124634137, 1886057615, 3915621685, 2657392035,
- 249268274, 2044508324, 3772115230, 2547177864,
- 162941995, 2125561021, 3887607047, 2428444049,
- 498536548, 1789927666, 4089016648, 2227061214,
- 450548861, 1843258603, 4107580753, 2211677639,
- 325883990, 1684777152, 4251122042, 2321926636,
- 335633487, 1661365465, 4195302755, 2366115317,
- 997073096, 1281953886, 3579855332, 2724688242,
- 1006888145, 1258607687, 3524101629, 2768942443,
- 901097722, 1119000684, 3686517206, 2898065728,
- 853044451, 1172266101, 3705015759, 2882616665,
- 651767980, 1373503546, 3369554304, 3218104598,
- 565507253, 1454621731, 3485111705, 3099436303,
- 671266974, 1594198024, 3322730930, 2970347812,
- 795835527, 1483230225, 3244367275, 3060149565,
- 1994146192, 31158534, 2563907772, 4023717930,
- 1907459465, 112637215, 2680153253, 3904427059,
- 2013776290, 251722036, 2517215374, 3775830040,
- 2137656763, 141376813, 2439277719, 3865271297,
- 1802195444, 476864866, 2238001368, 4066508878,
- 1812370925, 453092731, 2181625025, 4111451223,
- 1706088902, 314042704, 2344532202, 4240017532,
- 1658658271, 366619977, 2362670323, 4224994405,
- 1303535960, 984961486, 2747007092, 3569037538,
- 1256170817, 1037604311, 2765210733, 3554079995,
- 1131014506, 879679996, 2909243462, 3663771856,
- 1141124467, 855842277, 2852801631, 3708648649,
- 1342533948, 654459306, 3188396048, 3373015174,
- 1466479909, 544179635, 3110523913, 3462522015,
- 1591671054, 702138776, 2966460450, 3352799412,
- 1504918807, 783551873, 3082640443, 3233442989,
- 3988292384, 2596254646, 62317068, 1957810842,
- 3939845945, 2647816111, 81470997, 1943803523,
- 3814918930, 2489596804, 225274430, 2053790376,
- 3826175755, 2466906013, 167816743, 2097651377,
- 4027552580, 2265490386, 503444072, 1762050814,
- 4150417245, 2154129355, 426522225, 1852507879,
- 4275313526, 2312317920, 282753626, 1742555852,
- 4189708143, 2394877945, 397917763, 1622183637,
- 3604390888, 2714866558, 953729732, 1340076626,
- 3518719985, 2797360999, 1068828381, 1219638859,
- 3624741850, 2936675148, 906185462, 1090812512,
- 3747672003, 2825379669, 829329135, 1181335161,
- 3412177804, 3160834842, 628085408, 1382605366,
- 3423369109, 3138078467, 570562233, 1426400815,
- 3317316542, 2998733608, 733239954, 1555261956,
- 3268935591, 3050360625, 752459403, 1541320221,
- 2607071920, 3965973030, 1969922972, 40735498,
- 2617837225, 3943577151, 1913087877, 83908371,
- 2512341634, 3803740692, 2075208622, 213261112,
- 2463272603, 3855990285, 2094854071, 198958881,
- 2262029012, 4057260610, 1759359992, 534414190,
- 2176718541, 4139329115, 1873836001, 414664567,
- 2282248934, 4279200368, 1711684554, 285281116,
- 2405801727, 4167216745, 1634467795, 376229701,
- 2685067896, 3608007406, 1308918612, 956543938,
- 2808555105, 3495958263, 1231636301, 1047427035,
- 2932959818, 3654703836, 1088359270, 936918000,
- 2847714899, 3736837829, 1202900863, 817233897,
- 3183342108, 3401237130, 1404277552, 615818150,
- 3134207493, 3453421203, 1423857449, 601450431,
- 3009837614, 3294710456, 1567103746, 711928724,
- 3020668471, 3272380065, 1510334235, 755167117,
- ]
+ # This spec fails when zlib.h and libz.so are not from the same version.
+ # In older zlib (< 1.2.7 it seems), get_crc_table() is stored as u64[],
+ # but in newer zlib, get_crc_table() is stored as u32[].
+ # Technically, there is ABI breakage between those zlib versions,
+ # but get_crc_table() is an "undocumented function" according to zlib.h.
+ guard -> { ENV["RUBY_SPEC_TEST_ZLIB_CRC_TABLE"] != "false" } do
+ it "returns the same value as zlib's get_crc_table()" do
+ Zlib.crc_table.should == [
+ 0, 1996959894, 3993919788, 2567524794,
+ 124634137, 1886057615, 3915621685, 2657392035,
+ 249268274, 2044508324, 3772115230, 2547177864,
+ 162941995, 2125561021, 3887607047, 2428444049,
+ 498536548, 1789927666, 4089016648, 2227061214,
+ 450548861, 1843258603, 4107580753, 2211677639,
+ 325883990, 1684777152, 4251122042, 2321926636,
+ 335633487, 1661365465, 4195302755, 2366115317,
+ 997073096, 1281953886, 3579855332, 2724688242,
+ 1006888145, 1258607687, 3524101629, 2768942443,
+ 901097722, 1119000684, 3686517206, 2898065728,
+ 853044451, 1172266101, 3705015759, 2882616665,
+ 651767980, 1373503546, 3369554304, 3218104598,
+ 565507253, 1454621731, 3485111705, 3099436303,
+ 671266974, 1594198024, 3322730930, 2970347812,
+ 795835527, 1483230225, 3244367275, 3060149565,
+ 1994146192, 31158534, 2563907772, 4023717930,
+ 1907459465, 112637215, 2680153253, 3904427059,
+ 2013776290, 251722036, 2517215374, 3775830040,
+ 2137656763, 141376813, 2439277719, 3865271297,
+ 1802195444, 476864866, 2238001368, 4066508878,
+ 1812370925, 453092731, 2181625025, 4111451223,
+ 1706088902, 314042704, 2344532202, 4240017532,
+ 1658658271, 366619977, 2362670323, 4224994405,
+ 1303535960, 984961486, 2747007092, 3569037538,
+ 1256170817, 1037604311, 2765210733, 3554079995,
+ 1131014506, 879679996, 2909243462, 3663771856,
+ 1141124467, 855842277, 2852801631, 3708648649,
+ 1342533948, 654459306, 3188396048, 3373015174,
+ 1466479909, 544179635, 3110523913, 3462522015,
+ 1591671054, 702138776, 2966460450, 3352799412,
+ 1504918807, 783551873, 3082640443, 3233442989,
+ 3988292384, 2596254646, 62317068, 1957810842,
+ 3939845945, 2647816111, 81470997, 1943803523,
+ 3814918930, 2489596804, 225274430, 2053790376,
+ 3826175755, 2466906013, 167816743, 2097651377,
+ 4027552580, 2265490386, 503444072, 1762050814,
+ 4150417245, 2154129355, 426522225, 1852507879,
+ 4275313526, 2312317920, 282753626, 1742555852,
+ 4189708143, 2394877945, 397917763, 1622183637,
+ 3604390888, 2714866558, 953729732, 1340076626,
+ 3518719985, 2797360999, 1068828381, 1219638859,
+ 3624741850, 2936675148, 906185462, 1090812512,
+ 3747672003, 2825379669, 829329135, 1181335161,
+ 3412177804, 3160834842, 628085408, 1382605366,
+ 3423369109, 3138078467, 570562233, 1426400815,
+ 3317316542, 2998733608, 733239954, 1555261956,
+ 3268935591, 3050360625, 752459403, 1541320221,
+ 2607071920, 3965973030, 1969922972, 40735498,
+ 2617837225, 3943577151, 1913087877, 83908371,
+ 2512341634, 3803740692, 2075208622, 213261112,
+ 2463272603, 3855990285, 2094854071, 198958881,
+ 2262029012, 4057260610, 1759359992, 534414190,
+ 2176718541, 4139329115, 1873836001, 414664567,
+ 2282248934, 4279200368, 1711684554, 285281116,
+ 2405801727, 4167216745, 1634467795, 376229701,
+ 2685067896, 3608007406, 1308918612, 956543938,
+ 2808555105, 3495958263, 1231636301, 1047427035,
+ 2932959818, 3654703836, 1088359270, 936918000,
+ 2847714899, 3736837829, 1202900863, 817233897,
+ 3183342108, 3401237130, 1404277552, 615818150,
+ 3134207493, 3453421203, 1423857449, 601450431,
+ 3009837614, 3294710456, 1567103746, 711928724,
+ 3020668471, 3272380065, 1510334235, 755167117,
+ ]
+ end
end
-
end
diff --git a/spec/ruby/library/zlib/deflate/deflate_spec.rb b/spec/ruby/library/zlib/deflate/deflate_spec.rb
index 828880f8d8..50a563ef6f 100644
--- a/spec/ruby/library/zlib/deflate/deflate_spec.rb
+++ b/spec/ruby/library/zlib/deflate/deflate_spec.rb
@@ -58,6 +58,11 @@ describe "Zlib::Deflate#deflate" do
Array.new(31, 0) +
[24, 128, 0, 0, 1]).pack('C*')
end
+
+ it "has a binary encoding" do
+ @deflator.deflate("").encoding.should == Encoding::BINARY
+ @deflator.finish.encoding.should == Encoding::BINARY
+ end
end
describe "Zlib::Deflate#deflate" do
diff --git a/spec/ruby/library/zlib/inflate/inflate_spec.rb b/spec/ruby/library/zlib/inflate/inflate_spec.rb
index cc33bd4c32..79b72bf91c 100644
--- a/spec/ruby/library/zlib/inflate/inflate_spec.rb
+++ b/spec/ruby/library/zlib/inflate/inflate_spec.rb
@@ -39,6 +39,13 @@ describe "Zlib::Inflate#inflate" do
@inflator.finish.should == 'uncompressed_data'
end
+ it "has a binary encoding" do
+ data = [120, 156, 99, 96, 128, 1, 0, 0, 10, 0, 1].pack('C*')
+ unzipped = @inflator.inflate data
+ @inflator.finish.encoding.should == Encoding::BINARY
+ unzipped.encoding.should == Encoding::BINARY
+ end
+
end
describe "Zlib::Inflate.inflate" do
diff --git a/spec/ruby/optional/capi/binding_spec.rb b/spec/ruby/optional/capi/binding_spec.rb
index 966d650c46..2165705457 100644
--- a/spec/ruby/optional/capi/binding_spec.rb
+++ b/spec/ruby/optional/capi/binding_spec.rb
@@ -8,12 +8,21 @@ describe "CApiBindingSpecs" do
end
describe "Kernel#binding" do
- it "gives the top-most Ruby binding when called from C" do
- foo = 14
- b = @b.get_binding
- b.local_variable_get(:foo).should == 14
- b.local_variable_set :foo, 12
- foo.should == 12
+ ruby_version_is '3.2' do
+ it "raises when called from C" do
+ foo = 14
+ -> { @b.get_binding }.should raise_error(RuntimeError)
+ end
+ end
+
+ ruby_version_is ''...'3.2' do
+ it "gives the top-most Ruby binding when called from C" do
+ foo = 14
+ b = @b.get_binding
+ b.local_variable_get(:foo).should == 14
+ b.local_variable_set :foo, 12
+ foo.should == 12
+ end
end
end
end
diff --git a/spec/ruby/optional/capi/class_spec.rb b/spec/ruby/optional/capi/class_spec.rb
index c2424668b9..66af381243 100644
--- a/spec/ruby/optional/capi/class_spec.rb
+++ b/spec/ruby/optional/capi/class_spec.rb
@@ -12,6 +12,7 @@ autoload :ClassIdUnderAutoload, "#{object_path}/class_id_under_autoload_spec"
describe :rb_path_to_class, shared: true do
it "returns a class or module from a scoped String" do
@s.send(@method, "CApiClassSpecs::A::B").should equal(CApiClassSpecs::A::B)
+ @s.send(@method, "CApiClassSpecs::A::M").should equal(CApiClassSpecs::A::M)
end
it "resolves autoload constants" do
@@ -27,7 +28,9 @@ describe :rb_path_to_class, shared: true do
end
it "raises a TypeError if the constant is not a class or module" do
- -> { @s.send(@method, "CApiClassSpecs::A::C") }.should raise_error(TypeError)
+ -> {
+ @s.send(@method, "CApiClassSpecs::A::C")
+ }.should raise_error(TypeError, 'CApiClassSpecs::A::C does not refer to class/module')
end
it "raises an ArgumentError even if a constant in the path exists on toplevel" do
@@ -105,17 +108,37 @@ describe "C-API Class function" do
describe "rb_class_new_instance" do
it "allocates and initializes a new object" do
- o = @s.rb_class_new_instance(0, nil, CApiClassSpecs::Alloc)
+ o = @s.rb_class_new_instance([], CApiClassSpecs::Alloc)
o.class.should == CApiClassSpecs::Alloc
o.initialized.should be_true
end
it "passes arguments to the #initialize method" do
- o = @s.rb_class_new_instance(2, [:one, :two], CApiClassSpecs::Alloc)
+ o = @s.rb_class_new_instance([:one, :two], CApiClassSpecs::Alloc)
o.arguments.should == [:one, :two]
end
end
+ ruby_version_is "3.0" do
+ describe "rb_class_new_instance_kw" do
+ it "passes arguments and keywords to the #initialize method" do
+ obj = @s.rb_class_new_instance_kw([{pos: 1}, {kw: 2}], CApiClassSpecs::KeywordAlloc)
+ obj.args.should == [{pos: 1}]
+ obj.kwargs.should == {kw: 2}
+
+ obj = @s.rb_class_new_instance_kw([{}], CApiClassSpecs::KeywordAlloc)
+ obj.args.should == []
+ obj.kwargs.should == {}
+ end
+
+ it "raises TypeError if the last argument is not a Hash" do
+ -> {
+ @s.rb_class_new_instance_kw([42], CApiClassSpecs::KeywordAlloc)
+ }.should raise_error(TypeError, 'no implicit conversion of Integer into Hash')
+ end
+ end
+ end
+
describe "rb_include_module" do
it "includes a module into a class" do
c = Class.new
@@ -173,16 +196,6 @@ describe "C-API Class function" do
end
end
- describe "rb_define_method" do
- it "defines a method taking variable arguments as a C array if the argument count is -1" do
- @s.rb_method_varargs_1(1, 3, 7, 4).should == [1, 3, 7, 4]
- end
-
- it "defines a method taking variable arguments as a Ruby array if the argument count is -2" do
- @s.rb_method_varargs_2(1, 3, 7, 4).should == [1, 3, 7, 4]
- end
- end
-
describe "rb_class2name" do
it "returns the class name" do
@s.rb_class2name(CApiClassSpecs).should == "CApiClassSpecs"
@@ -191,6 +204,10 @@ describe "C-API Class function" do
it "returns a string for an anonymous class" do
@s.rb_class2name(Class.new).should be_kind_of(String)
end
+
+ it "returns a string beginning with # for an anonymous class" do
+ @s.rb_class2name(Struct.new(:x, :y).new(1, 2).class).should.start_with?('#')
+ end
end
describe "rb_class_path" do
@@ -306,6 +323,15 @@ describe "C-API Class function" do
@s.rb_define_class("ClassSpecDefineClass4", nil)
}.should raise_error(ArgumentError)
end
+
+ it "allows arbitrary names, including constant names not valid in Ruby" do
+ cls = @s.rb_define_class("_INVALID_CLASS", CApiClassSpecs::Super)
+ cls.name.should == "_INVALID_CLASS"
+
+ -> {
+ Object.const_get(cls.name)
+ }.should raise_error(NameError, /wrong constant name/)
+ end
end
describe "rb_define_class_under" do
@@ -350,6 +376,15 @@ describe "C-API Class function" do
it "raises a TypeError if class is defined and its superclass mismatches the given one" do
-> { @s.rb_define_class_under(CApiClassSpecs, "Sub", Object) }.should raise_error(TypeError)
end
+
+ it "allows arbitrary names, including constant names not valid in Ruby" do
+ cls = @s.rb_define_class_under(CApiClassSpecs, "_INVALID_CLASS", CApiClassSpecs::Super)
+ cls.name.should == "CApiClassSpecs::_INVALID_CLASS"
+
+ -> {
+ CApiClassSpecs.const_get(cls.name)
+ }.should raise_error(NameError, /wrong constant name/)
+ end
end
describe "rb_define_class_id_under" do
@@ -377,6 +412,15 @@ describe "C-API Class function" do
it "raises a TypeError if class is defined and its superclass mismatches the given one" do
-> { @s.rb_define_class_id_under(CApiClassSpecs, :Sub, Object) }.should raise_error(TypeError)
end
+
+ it "allows arbitrary names, including constant names not valid in Ruby" do
+ cls = @s.rb_define_class_id_under(CApiClassSpecs, :_INVALID_CLASS2, CApiClassSpecs::Super)
+ cls.name.should == "CApiClassSpecs::_INVALID_CLASS2"
+
+ -> {
+ CApiClassSpecs.const_get(cls.name)
+ }.should raise_error(NameError, /wrong constant name/)
+ end
end
describe "rb_define_class_variable" do
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index 66c2dd40de..aa632b963b 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -63,6 +63,48 @@ describe "C-API Encoding function" do
end
end
+ describe "rb_enc_strlen" do
+ before :each do
+ @str = 'こにちわ' # Each codepoint in this string is 3 bytes in UTF-8
+ end
+
+ it "returns the correct string length for the encoding" do
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_8).should == 4
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::BINARY).should == 12
+ end
+
+ it "returns the string length based on a fixed-width encoding's character length, even if the encoding is incompatible" do
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_16BE).should == 6
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_16LE).should == 6
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_32BE).should == 3
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_32LE).should == 3
+ end
+
+ it "does not consider strings to be NUL-terminated" do
+ s = "abc\0def"
+ @s.rb_enc_strlen(s, s.bytesize, Encoding::US_ASCII).should == 7
+ @s.rb_enc_strlen(s, s.bytesize, Encoding::UTF_8).should == 7
+ end
+
+ describe "handles broken strings" do
+ it "combines valid character and invalid character counts in UTF-8" do
+ # The result is 3 because `rb_enc_strlen` counts the first valid character and then adds
+ # the byte count for the invalid character that follows for 1 + 2.
+ @s.rb_enc_strlen(@str, 5, Encoding::UTF_8).should == 3
+ end
+
+ it "combines valid character and invalid character counts in UTF-16" do
+ @s.rb_enc_strlen(@str, 5, Encoding::UTF_16BE).should == 3
+ end
+
+ it "rounds up for fixed-width encodings" do
+ @s.rb_enc_strlen(@str, 7, Encoding::UTF_32BE).should == 2
+ @s.rb_enc_strlen(@str, 7, Encoding::UTF_32LE).should == 2
+ @s.rb_enc_strlen(@str, 5, Encoding::BINARY).should == 5
+ end
+ end
+ end
+
describe "rb_enc_find" do
it "returns the encoding of an Encoding" do
@s.rb_enc_find("UTF-8").should == "UTF-8"
@@ -128,10 +170,16 @@ describe "C-API Encoding function" do
describe "rb_enc_mbc_to_codepoint" do
it "returns the correct codepoint for the given character and size" do
- @s.rb_enc_mbc_to_codepoint("é", 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
+ @s.rb_enc_mbc_to_codepoint("é").should == 0xE9
+ end
+
+ it "returns 0 if p == e" do
+ @s.rb_enc_mbc_to_codepoint("").should == 0
+ end
+
+ it "returns the raw byte if incomplete character in UTF-8" do
+ @s.rb_enc_mbc_to_codepoint("\xC3").should == 0xC3
+ @s.rb_enc_mbc_to_codepoint("\x80").should == 0x80
end
end
@@ -613,15 +661,15 @@ describe "C-API Encoding function" 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",
+ 1 => "\x01",
+ 0x80 => "\xC2\x80",
+ 0x800 => "\xE0\xA0\x80",
+ 0x10000 => "\xF0\x90\x80\x80",
+ 0x200000 => "\xF8\x88\x80\x80\x80",
+ 0x4000000 => "\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
+ len = @s.rb_uv_to_utf8(str, num)
+ str.byteslice(0, len).should == result
end
end
end
@@ -630,6 +678,7 @@ describe "C-API Encoding function" 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]
+ @s.ONIGENC_MBC_CASE_FOLD("ABC"[1..-1]).should == ["b", 1]
end
it "works with other encodings" do
diff --git a/spec/ruby/optional/capi/ext/class_spec.c b/spec/ruby/optional/capi/ext/class_spec.c
index 36b8c8f2f3..589025f677 100644
--- a/spec/ruby/optional/capi/ext/class_spec.c
+++ b/spec/ruby/optional/capi/ext/class_spec.c
@@ -61,18 +61,15 @@ static VALUE class_spec_rb_class_new(VALUE self, VALUE super) {
return rb_class_new(super);
}
-static VALUE class_spec_rb_class_new_instance(VALUE self,
- VALUE nargs, VALUE args,
- VALUE klass) {
- int c_nargs = FIX2INT(nargs);
- VALUE *c_args = (VALUE*)alloca(sizeof(VALUE) * c_nargs);
- int i;
-
- for (i = 0; i < c_nargs; i++)
- c_args[i] = rb_ary_entry(args, i);
+static VALUE class_spec_rb_class_new_instance(VALUE self, VALUE args, VALUE klass) {
+ return rb_class_new_instance(RARRAY_LENINT(args), RARRAY_PTR(args), klass);
+}
- return rb_class_new_instance(c_nargs, c_args, klass);
+#ifdef RUBY_VERSION_IS_3_0
+static VALUE class_spec_rb_class_new_instance_kw(VALUE self, VALUE args, VALUE klass) {
+ return rb_class_new_instance_kw(RARRAY_LENINT(args), RARRAY_PTR(args), klass, RB_PASS_KEYWORDS);
}
+#endif
static VALUE class_spec_rb_class_real(VALUE self, VALUE object) {
if(rb_type_p(object, T_FIXNUM)) {
@@ -145,19 +142,6 @@ static VALUE class_spec_include_module(VALUE self, VALUE klass, VALUE module) {
return klass;
}
-static VALUE class_spec_method_var_args_1(int argc, VALUE *argv, VALUE self) {
- VALUE ary = rb_ary_new();
- int i;
- for (i = 0; i < argc; i++) {
- rb_ary_push(ary, argv[i]);
- }
- return ary;
-}
-
-static VALUE class_spec_method_var_args_2(VALUE self, VALUE argv) {
- return argv;
-}
-
void Init_class_spec(void) {
VALUE cls = rb_define_class("CApiClassSpecs", rb_cObject);
rb_define_method(cls, "define_call_super_method", class_spec_define_call_super_method, 2);
@@ -171,7 +155,10 @@ void Init_class_spec(void) {
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_new_instance", class_spec_rb_class_new_instance, 2);
+#ifdef RUBY_VERSION_IS_3_0
+ rb_define_method(cls, "rb_class_new_instance_kw", class_spec_rb_class_new_instance_kw, 2);
+#endif
rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1);
rb_define_method(cls, "rb_class_superclass", class_spec_rb_class_superclass, 1);
rb_define_method(cls, "rb_cvar_defined", class_spec_cvar_defined, 2);
@@ -185,8 +172,6 @@ void Init_class_spec(void) {
rb_define_method(cls, "rb_define_class_id_under", class_spec_rb_define_class_id_under, 3);
rb_define_method(cls, "rb_define_class_variable", class_spec_define_class_variable, 3);
rb_define_method(cls, "rb_include_module", class_spec_include_module, 2);
- rb_define_method(cls, "rb_method_varargs_1", class_spec_method_var_args_1, -1);
- rb_define_method(cls, "rb_method_varargs_2", class_spec_method_var_args_2, -2);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c
index cde4d0c351..a0136530f2 100644
--- a/spec/ruby/optional/capi/ext/encoding_spec.c
+++ b/spec/ruby/optional/capi/ext/encoding_spec.c
@@ -71,11 +71,9 @@ static VALUE encoding_spec_rb_default_external_encoding(VALUE self) {
return rb_str_new2(enc->name);
}
-#ifdef RUBY_VERSION_IS_2_6
static VALUE encoding_spec_rb_enc_alias(VALUE self, VALUE alias, VALUE orig) {
return INT2NUM(rb_enc_alias(RSTRING_PTR(alias), RSTRING_PTR(orig)));
}
-#endif
static VALUE encoding_spec_rb_enc_associate(VALUE self, VALUE obj, VALUE enc) {
return rb_enc_associate(obj, NIL_P(enc) ? NULL : rb_enc_find(RSTRING_PTR(enc)));
@@ -120,10 +118,9 @@ 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);
+static VALUE encoding_spec_rb_enc_mbc_to_codepoint(VALUE self, VALUE str) {
char *p = RSTRING_PTR(str);
- char *e = p + o;
+ char *e = RSTRING_END(str);
return INT2FIX(rb_enc_mbc_to_codepoint(p, e, rb_enc_get(str)));
}
@@ -275,7 +272,9 @@ static VALUE encoding_spec_rb_enc_str_asciionly_p(VALUE self, VALUE str) {
}
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)));
+ int len = rb_uv_to_utf8(RSTRING_PTR(buf), NUM2INT(num));
+ RB_ENC_CODERANGE_CLEAR(buf);
+ return INT2NUM(len);
}
static VALUE encoding_spec_ONIGENC_MBC_CASE_FOLD(VALUE self, VALUE str) {
@@ -300,6 +299,14 @@ static VALUE encoding_spec_rb_enc_codelen(VALUE self, VALUE code, VALUE encoding
return INT2FIX(rb_enc_codelen(c, enc));
}
+static VALUE encoding_spec_rb_enc_strlen(VALUE self, VALUE str, VALUE length, VALUE encoding) {
+ int l = FIX2INT(length);
+ char *p = RSTRING_PTR(str);
+ char *e = p + l;
+
+ return LONG2FIX(rb_enc_strlen(p, e, rb_to_encoding(encoding)));
+}
+
void Init_encoding_spec(void) {
VALUE cls;
native_rb_encoding_pointer = (rb_encoding**) malloc(sizeof(rb_encoding*));
@@ -318,28 +325,22 @@ void Init_encoding_spec(void) {
rb_define_method(cls, "rb_locale_encindex", encoding_spec_rb_locale_encindex, 0);
rb_define_method(cls, "rb_filesystem_encoding", encoding_spec_rb_filesystem_encoding, 0);
rb_define_method(cls, "rb_filesystem_encindex", encoding_spec_rb_filesystem_encindex, 0);
- rb_define_method(cls, "rb_default_internal_encoding",
- encoding_spec_rb_default_internal_encoding, 0);
-
- rb_define_method(cls, "rb_default_external_encoding",
- encoding_spec_rb_default_external_encoding, 0);
-
-#ifdef RUBY_VERSION_IS_2_6
+ rb_define_method(cls, "rb_default_internal_encoding", encoding_spec_rb_default_internal_encoding, 0);
+ rb_define_method(cls, "rb_default_external_encoding", encoding_spec_rb_default_external_encoding, 0);
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_strlen", encoding_spec_rb_enc_strlen, 3);
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_mbc_to_codepoint", encoding_spec_rb_enc_mbc_to_codepoint, 1);
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);
diff --git a/spec/ruby/optional/capi/ext/fiber_spec.c b/spec/ruby/optional/capi/ext/fiber_spec.c
index 7912e878f3..f06a54494e 100644
--- a/spec/ruby/optional/capi/ext/fiber_spec.c
+++ b/spec/ruby/optional/capi/ext/fiber_spec.c
@@ -44,6 +44,13 @@ VALUE fiber_spec_rb_fiber_new(VALUE self) {
return rb_fiber_new(fiber_spec_rb_fiber_new_function, Qnil);
}
+#ifdef RUBY_VERSION_IS_3_1
+VALUE fiber_spec_rb_fiber_raise(int argc, VALUE *argv, VALUE self) {
+ VALUE fiber = argv[0];
+ return rb_fiber_raise(fiber, argc-1, argv+1);
+}
+#endif
+
void Init_fiber_spec(void) {
VALUE cls = rb_define_class("CApiFiberSpecs", rb_cObject);
rb_define_method(cls, "rb_fiber_current", fiber_spec_rb_fiber_current, 0);
@@ -51,6 +58,10 @@ void Init_fiber_spec(void) {
rb_define_method(cls, "rb_fiber_resume", fiber_spec_rb_fiber_resume, 2);
rb_define_method(cls, "rb_fiber_yield", fiber_spec_rb_fiber_yield, 1);
rb_define_method(cls, "rb_fiber_new", fiber_spec_rb_fiber_new, 0);
+
+#ifdef RUBY_VERSION_IS_3_1
+ rb_define_method(cls, "rb_fiber_raise", fiber_spec_rb_fiber_raise, -1);
+#endif
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/gc_spec.c b/spec/ruby/optional/capi/ext/gc_spec.c
index 7dc9c347c7..b323c2456d 100644
--- a/spec/ruby/optional/capi/ext/gc_spec.c
+++ b/spec/ruby/optional/capi/ext/gc_spec.c
@@ -7,6 +7,9 @@ extern "C" {
VALUE registered_tagged_value;
VALUE registered_reference_value;
+VALUE registered_before_rb_gc_register_address;
+VALUE registered_before_rb_global_variable;
+VALUE rb_gc_register_address_outside_init;
static VALUE registered_tagged_address(VALUE self) {
return registered_tagged_value;
@@ -16,6 +19,25 @@ static VALUE registered_reference_address(VALUE self) {
return registered_reference_value;
}
+static VALUE get_registered_before_rb_gc_register_address(VALUE self) {
+ return registered_before_rb_gc_register_address;
+}
+
+static VALUE get_registered_before_rb_global_variable(VALUE self) {
+ return registered_before_rb_global_variable;
+}
+
+static VALUE gc_spec_rb_gc_register_address(VALUE self) {
+ rb_gc_register_address(&rb_gc_register_address_outside_init);
+ rb_gc_register_address_outside_init = rb_str_new_cstr("rb_gc_register_address() outside Init_");
+ return rb_gc_register_address_outside_init;
+}
+
+static VALUE gc_spec_rb_gc_unregister_address(VALUE self) {
+ rb_gc_unregister_address(&rb_gc_register_address_outside_init);
+ return Qnil;
+}
+
static VALUE gc_spec_rb_gc_enable(VALUE self) {
return rb_gc_enable();
}
@@ -45,14 +67,23 @@ static VALUE gc_spec_rb_gc_register_mark_object(VALUE self, VALUE obj) {
void Init_gc_spec(void) {
VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject);
- registered_tagged_value = INT2NUM(10);
- registered_reference_value = rb_str_new2("Globally registered data");
rb_gc_register_address(&registered_tagged_value);
rb_gc_register_address(&registered_reference_value);
+ rb_gc_register_address(&registered_before_rb_gc_register_address);
+ rb_global_variable(&registered_before_rb_global_variable);
+
+ registered_tagged_value = INT2NUM(10);
+ registered_reference_value = rb_str_new2("Globally registered data");
+ registered_before_rb_gc_register_address = rb_str_new_cstr("registered before rb_gc_register_address()");
+ registered_before_rb_global_variable = rb_str_new_cstr("registered before rb_global_variable()");
rb_define_method(cls, "registered_tagged_address", registered_tagged_address, 0);
rb_define_method(cls, "registered_reference_address", registered_reference_address, 0);
+ rb_define_method(cls, "registered_before_rb_gc_register_address", get_registered_before_rb_gc_register_address, 0);
+ rb_define_method(cls, "registered_before_rb_global_variable", get_registered_before_rb_global_variable, 0);
+ rb_define_method(cls, "rb_gc_register_address", gc_spec_rb_gc_register_address, 0);
+ rb_define_method(cls, "rb_gc_unregister_address", gc_spec_rb_gc_unregister_address, 0);
rb_define_method(cls, "rb_gc_enable", gc_spec_rb_gc_enable, 0);
rb_define_method(cls, "rb_gc_disable", gc_spec_rb_gc_disable, 0);
rb_define_method(cls, "rb_gc", gc_spec_rb_gc, 0);
diff --git a/spec/ruby/optional/capi/ext/globals_spec.c b/spec/ruby/optional/capi/ext/globals_spec.c
index 28a9633f98..20dea1a05a 100644
--- a/spec/ruby/optional/capi/ext/globals_spec.c
+++ b/spec/ruby/optional/capi/ext/globals_spec.c
@@ -20,6 +20,16 @@ static VALUE sb_define_hooked_variable(VALUE self, VALUE var_name) {
return Qnil;
}
+static VALUE sb_define_hooked_variable_default_accessors(VALUE self, VALUE var_name) {
+ rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, (rb_gvar_getter_t*) NULL, (rb_gvar_setter_t*) NULL);
+ return Qnil;
+}
+
+static VALUE sb_define_hooked_variable_null_var(VALUE self, VALUE var_name) {
+ rb_define_hooked_variable(StringValuePtr(var_name), NULL, (rb_gvar_getter_t*) NULL, (rb_gvar_setter_t*) NULL);
+ return Qnil;
+}
+
VALUE g_ro_var;
static VALUE sb_define_readonly_variable(VALUE self, VALUE var_name, VALUE val) {
@@ -40,6 +50,26 @@ static VALUE sb_define_variable(VALUE self, VALUE var_name, VALUE val) {
return Qnil;
}
+long virtual_var_storage;
+
+VALUE incrementing_getter(ID id, VALUE *data) {
+ return LONG2FIX(virtual_var_storage++);
+}
+
+void incrementing_setter(VALUE val, ID id, VALUE *data) {
+ virtual_var_storage = FIX2LONG(val);
+}
+
+static VALUE sb_define_virtual_variable_default_accessors(VALUE self, VALUE name) {
+ rb_define_virtual_variable(StringValuePtr(name), (rb_gvar_getter_t*) NULL, (rb_gvar_setter_t*) NULL);
+ return Qnil;
+}
+
+static VALUE sb_define_virtual_variable_incrementing_accessors(VALUE self, VALUE name) {
+ rb_define_virtual_variable(StringValuePtr(name), incrementing_getter, incrementing_setter);
+ return Qnil;
+}
+
static VALUE sb_f_global_variables(VALUE self) {
return rb_f_global_variables();
}
@@ -101,10 +131,14 @@ void Init_globals_spec(void) {
VALUE cls = rb_define_class("CApiGlobalSpecs", rb_cObject);
g_hooked_var = Qnil;
rb_define_method(cls, "rb_define_hooked_variable_2x", sb_define_hooked_variable, 1);
+ rb_define_method(cls, "rb_define_hooked_variable_default_accessors", sb_define_hooked_variable_default_accessors, 1);
+ rb_define_method(cls, "rb_define_hooked_variable_null_var", sb_define_hooked_variable_null_var, 1);
g_ro_var = Qnil;
rb_define_method(cls, "rb_define_readonly_variable", sb_define_readonly_variable, 2);
g_var = Qnil;
rb_define_method(cls, "rb_define_variable", sb_define_variable, 2);
+ rb_define_method(cls, "rb_define_virtual_variable_default_accessors", sb_define_virtual_variable_default_accessors, 1);
+ rb_define_method(cls, "rb_define_virtual_variable_incrementing_accessors", sb_define_virtual_variable_incrementing_accessors, 1);
rb_define_method(cls, "sb_get_global_value", sb_get_global_value, 0);
rb_define_method(cls, "rb_f_global_variables", sb_f_global_variables, 0);
rb_define_method(cls, "sb_gv_get", sb_gv_get, 1);
diff --git a/spec/ruby/optional/capi/ext/integer_spec.c b/spec/ruby/optional/capi/ext/integer_spec.c
index 5ed1d3fd73..16cd95f111 100644
--- a/spec/ruby/optional/capi/ext/integer_spec.c
+++ b/spec/ruby/optional/capi/ext/integer_spec.c
@@ -13,7 +13,7 @@ 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 */
+RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y); /* internal.h, used in ripper */
static VALUE integer_spec_rb_int_positive_pow(VALUE self, VALUE a, VALUE b){
return rb_int_positive_pow(FIX2INT(a), FIX2INT(b));
diff --git a/spec/ruby/optional/capi/ext/io_spec.c b/spec/ruby/optional/capi/ext/io_spec.c
index b4ffe9207a..f257cef554 100644
--- a/spec/ruby/optional/capi/ext/io_spec.c
+++ b/spec/ruby/optional/capi/ext/io_spec.c
@@ -182,6 +182,46 @@ VALUE io_spec_rb_thread_fd_writable(VALUE self, VALUE io) {
return Qnil;
}
+VALUE io_spec_rb_thread_fd_select_read(VALUE self, VALUE io) {
+ int fd = io_spec_get_fd(io);
+
+ rb_fdset_t fds;
+ rb_fd_init(&fds);
+ rb_fd_set(fd, &fds);
+
+ int r = rb_thread_fd_select(fd + 1, &fds, NULL, NULL, NULL);
+ rb_fd_term(&fds);
+ return INT2FIX(r);
+}
+
+VALUE io_spec_rb_thread_fd_select_write(VALUE self, VALUE io) {
+ int fd = io_spec_get_fd(io);
+
+ rb_fdset_t fds;
+ rb_fd_init(&fds);
+ rb_fd_set(fd, &fds);
+
+ int r = rb_thread_fd_select(fd + 1, NULL, &fds, NULL, NULL);
+ rb_fd_term(&fds);
+ return INT2FIX(r);
+}
+
+VALUE io_spec_rb_thread_fd_select_timeout(VALUE self, VALUE io) {
+ int fd = io_spec_get_fd(io);
+
+ struct timeval timeout;
+ timeout.tv_sec = 10;
+ timeout.tv_usec = 20;
+
+ rb_fdset_t fds;
+ rb_fd_init(&fds);
+ rb_fd_set(fd, &fds);
+
+ int r = rb_thread_fd_select(fd + 1, NULL, &fds, NULL, &timeout);
+ rb_fd_term(&fds);
+ return INT2FIX(r);
+}
+
VALUE io_spec_rb_io_binmode(VALUE self, VALUE io) {
return rb_io_binmode(io);
}
@@ -256,6 +296,9 @@ void Init_io_spec(void) {
rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1);
rb_define_method(cls, "rb_thread_wait_fd", io_spec_rb_thread_wait_fd, 1);
rb_define_method(cls, "rb_thread_fd_writable", io_spec_rb_thread_fd_writable, 1);
+ rb_define_method(cls, "rb_thread_fd_select_read", io_spec_rb_thread_fd_select_read, 1);
+ rb_define_method(cls, "rb_thread_fd_select_write", io_spec_rb_thread_fd_select_write, 1);
+ rb_define_method(cls, "rb_thread_fd_select_timeout", io_spec_rb_thread_fd_select_timeout, 1);
rb_define_method(cls, "rb_wait_for_single_fd", io_spec_rb_wait_for_single_fd, 4);
rb_define_method(cls, "rb_io_binmode", io_spec_rb_io_binmode, 1);
rb_define_method(cls, "rb_fd_fix_cloexec", io_spec_rb_fd_fix_cloexec, 1);
diff --git a/spec/ruby/optional/capi/ext/kernel_spec.c b/spec/ruby/optional/capi/ext/kernel_spec.c
index bbfeb198b7..e194ba8fde 100644
--- a/spec/ruby/optional/capi/ext/kernel_spec.c
+++ b/spec/ruby/optional/capi/ext/kernel_spec.c
@@ -112,6 +112,10 @@ VALUE kernel_spec_rb_eval_string(VALUE self, VALUE str) {
return rb_eval_string(RSTRING_PTR(str));
}
+VALUE kernel_spec_rb_eval_cmd_kw(VALUE self, VALUE cmd, VALUE args, VALUE kw_splat) {
+ return rb_eval_cmd_kw(cmd, args, NUM2INT(kw_splat));
+}
+
VALUE kernel_spec_rb_raise(VALUE self, VALUE hash) {
rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("before")));
if (self != Qundef)
@@ -142,7 +146,7 @@ VALUE kernel_spec_call_proc_with_raised_exc(VALUE arg_array, VALUE raised_exc) {
argc = 2;
- return rb_funcall2(proc, rb_intern("call"), argc, argv);
+ return rb_funcallv(proc, rb_intern("call"), argc, argv);
}
VALUE kernel_spec_rb_rescue(VALUE self, VALUE main_proc, VALUE arg,
@@ -318,8 +322,22 @@ static VALUE kernel_spec_rb_make_backtrace(VALUE self) {
return rb_make_backtrace();
}
-static VALUE kernel_spec_rb_funcall3(VALUE self, VALUE obj, VALUE method) {
- return rb_funcall3(obj, SYM2ID(method), 0, NULL);
+static VALUE kernel_spec_rb_funcallv(VALUE self, VALUE obj, VALUE method, VALUE args) {
+ return rb_funcallv(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args));
+}
+
+#ifdef RUBY_VERSION_IS_3_0
+static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VALUE args) {
+ return rb_funcallv_kw(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args), RB_PASS_KEYWORDS);
+}
+
+static VALUE kernel_spec_rb_keyword_given_p(int argc, VALUE *args, VALUE self) {
+ return rb_keyword_given_p() ? Qtrue : Qfalse;
+}
+#endif
+
+static VALUE kernel_spec_rb_funcallv_public(VALUE self, VALUE obj, VALUE method) {
+ return rb_funcallv_public(obj, SYM2ID(method), 0, NULL);
}
static VALUE kernel_spec_rb_funcall_with_block(VALUE self, VALUE obj, VALUE method, VALUE block) {
@@ -347,6 +365,7 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_frame_this_func_test_again", kernel_spec_rb_frame_this_func, 0);
rb_define_method(cls, "rb_ensure", kernel_spec_rb_ensure, 4);
rb_define_method(cls, "rb_eval_string", kernel_spec_rb_eval_string, 1);
+ rb_define_method(cls, "rb_eval_cmd_kw", kernel_spec_rb_eval_cmd_kw, 3);
rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1);
rb_define_method(cls, "rb_throw", kernel_spec_rb_throw, 1);
rb_define_method(cls, "rb_throw_obj", kernel_spec_rb_throw_obj, 2);
@@ -371,7 +390,12 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_set_end_proc", kernel_spec_rb_set_end_proc, 1);
rb_define_method(cls, "rb_f_sprintf", kernel_spec_rb_f_sprintf, 1);
rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0);
- rb_define_method(cls, "rb_funcall3", kernel_spec_rb_funcall3, 2);
+ rb_define_method(cls, "rb_funcallv", kernel_spec_rb_funcallv, 3);
+#ifdef RUBY_VERSION_IS_3_0
+ rb_define_method(cls, "rb_funcallv_kw", kernel_spec_rb_funcallv_kw, 3);
+ rb_define_method(cls, "rb_keyword_given_p", kernel_spec_rb_keyword_given_p, -1);
+#endif
+ rb_define_method(cls, "rb_funcallv_public", kernel_spec_rb_funcallv_public, 2);
rb_define_method(cls, "rb_funcall_many_args", kernel_spec_rb_funcall_many_args, 2);
rb_define_method(cls, "rb_funcall_with_block", kernel_spec_rb_funcall_with_block, 3);
}
diff --git a/spec/ruby/optional/capi/ext/module_spec.c b/spec/ruby/optional/capi/ext/module_spec.c
index 7475994fa1..12bcf99983 100644
--- a/spec/ruby/optional/capi/ext/module_spec.c
+++ b/spec/ruby/optional/capi/ext/module_spec.c
@@ -9,18 +9,6 @@ static VALUE module_specs_test_method(VALUE self) {
return ID2SYM(rb_intern("test_method"));
}
-static VALUE module_specs_test_method_2required(VALUE self, VALUE arg1, VALUE arg2) {
- return ID2SYM(rb_intern("test_method_2required"));
-}
-
-static VALUE module_specs_test_method_c_array(int argc, VALUE *argv, VALUE self) {
- return ID2SYM(rb_intern("test_method_c_array"));
-}
-
-static VALUE module_specs_test_method_ruby_array(VALUE self, VALUE args) {
- return ID2SYM(rb_intern("test_method_ruby_array"));
-}
-
static VALUE module_specs_const_defined(VALUE self, VALUE klass, VALUE id) {
return rb_const_defined(klass, SYM2ID(id)) ? Qtrue : Qfalse;
}
@@ -88,19 +76,25 @@ static VALUE module_specs_rb_define_method(VALUE self, VALUE cls, VALUE str_name
return Qnil;
}
-static VALUE module_specs_rb_define_method_2required(VALUE self, VALUE cls, VALUE str_name) {
- rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method_2required, 2);
- return Qnil;
+static VALUE module_specs_method_var_args_1(int argc, VALUE *argv, VALUE self) {
+ VALUE ary = rb_ary_new();
+ int i;
+ for (i = 0; i < argc; i++) {
+ rb_ary_push(ary, argv[i]);
+ }
+ return ary;
}
-static VALUE module_specs_rb_define_method_c_array(VALUE self, VALUE cls, VALUE str_name) {
- rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method_c_array, -1);
- return Qnil;
+static VALUE module_specs_method_var_args_2(VALUE self, VALUE argv) {
+ return argv;
}
-static VALUE module_specs_rb_define_method_ruby_array(VALUE self, VALUE cls, VALUE str_name) {
- rb_define_method(cls, RSTRING_PTR(str_name), module_specs_test_method_ruby_array, -2);
- return Qnil;
+static VALUE module_specs_rb_define_method_1required(VALUE self, VALUE arg1) {
+ return arg1;
+}
+
+static VALUE module_specs_rb_define_method_2required(VALUE self, VALUE arg1, VALUE arg2) {
+ return arg2;
}
static VALUE module_specs_rb_define_module_function(VALUE self, VALUE cls, VALUE str_name) {
@@ -155,25 +149,21 @@ void Init_module_spec(void) {
rb_define_method(cls, "rb_define_module_under", module_specs_rb_define_module_under, 2);
rb_define_method(cls, "rb_define_const", module_specs_define_const, 3);
rb_define_method(cls, "rb_define_global_const", module_specs_define_global_const, 2);
- rb_define_method(cls, "rb_define_global_function",
- module_specs_rb_define_global_function, 1);
+ rb_define_method(cls, "rb_define_global_function", module_specs_rb_define_global_function, 1);
rb_define_method(cls, "rb_define_method", module_specs_rb_define_method, 2);
+ rb_define_method(cls, "rb_define_method_varargs_1", module_specs_method_var_args_1, -1);
+ rb_define_method(cls, "rb_define_method_varargs_2", module_specs_method_var_args_2, -2);
+ rb_define_method(cls, "rb_define_method_1required", module_specs_rb_define_method_1required, 1);
rb_define_method(cls, "rb_define_method_2required", module_specs_rb_define_method_2required, 2);
- rb_define_method(cls, "rb_define_method_c_array", module_specs_rb_define_method_c_array, 2);
- rb_define_method(cls, "rb_define_method_ruby_array", module_specs_rb_define_method_ruby_array, 2);
- rb_define_method(cls, "rb_define_module_function",
- module_specs_rb_define_module_function, 2);
+ rb_define_method(cls, "rb_define_module_function", module_specs_rb_define_module_function, 2);
- rb_define_method(cls, "rb_define_private_method",
- module_specs_rb_define_private_method, 2);
+ rb_define_method(cls, "rb_define_private_method", module_specs_rb_define_private_method, 2);
- rb_define_method(cls, "rb_define_protected_method",
- module_specs_rb_define_protected_method, 2);
+ rb_define_method(cls, "rb_define_protected_method", module_specs_rb_define_protected_method, 2);
- rb_define_method(cls, "rb_define_singleton_method",
- module_specs_rb_define_singleton_method, 2);
+ rb_define_method(cls, "rb_define_singleton_method", module_specs_rb_define_singleton_method, 2);
rb_define_method(cls, "rb_undef_method", module_specs_rb_undef_method, 2);
rb_define_method(cls, "rb_undef", module_specs_rb_undef, 2);
diff --git a/spec/ruby/optional/capi/ext/object_spec.c b/spec/ruby/optional/capi/ext/object_spec.c
index 950c081818..30ac44cf1f 100644
--- a/spec/ruby/optional/capi/ext/object_spec.c
+++ b/spec/ruby/optional/capi/ext/object_spec.c
@@ -118,11 +118,14 @@ static VALUE so_rb_obj_call_init(VALUE self, VALUE object,
return Qnil;
}
+static VALUE so_rb_obj_class(VALUE self, VALUE obj) {
+ return rb_obj_class(obj);
+}
+
static VALUE so_rbobjclassname(VALUE self, VALUE obj) {
return rb_str_new2(rb_obj_classname(obj));
}
-
static VALUE object_spec_rb_obj_freeze(VALUE self, VALUE obj) {
return rb_obj_freeze(obj);
}
@@ -151,9 +154,29 @@ static VALUE object_specs_rb_obj_method(VALUE self, VALUE obj, VALUE method) {
return rb_obj_method(obj, method);
}
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated-declarations")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# endif
+#endif
+
+#ifndef RUBY_VERSION_IS_3_2
static VALUE object_spec_rb_obj_taint(VALUE self, VALUE obj) {
return rb_obj_taint(obj);
}
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+# pragma GCC diagnostic pop
+#elif defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated-declarations")
+# pragma clang diagnostic pop
+# endif
+#endif
static VALUE so_require(VALUE self) {
rb_require("fixtures/foo");
@@ -278,6 +301,13 @@ static VALUE so_is_rb_type_p_data(VALUE self, VALUE obj) {
return Qfalse;
}
+static VALUE so_is_rb_type_p_file(VALUE self, VALUE obj) {
+ if(rb_type_p(obj, T_FILE)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
static VALUE so_is_builtin_type_object(VALUE self, VALUE obj) {
if(BUILTIN_TYPE(obj) == T_OBJECT) {
return Qtrue;
@@ -363,6 +393,18 @@ static VALUE object_spec_rb_class_inherited_p(VALUE self, VALUE mod, VALUE arg)
return rb_class_inherited_p(mod, arg);
}
+static int foreach_f(ID key, VALUE val, VALUE ary) {
+ rb_ary_push(ary, ID2SYM(key));
+ rb_ary_push(ary, val);
+ return ST_CONTINUE;
+}
+
+static VALUE object_spec_rb_ivar_foreach(VALUE self, VALUE obj) {
+ VALUE ary = rb_ary_new();
+ rb_ivar_foreach(obj, foreach_f, ary);
+ return ary;
+}
+
static VALUE speced_allocator(VALUE klass) {
VALUE flags = 0;
VALUE instance;
@@ -422,6 +464,7 @@ void Init_object_spec(void) {
rb_define_method(cls, "rb_obj_alloc", so_rb_obj_alloc, 1);
rb_define_method(cls, "rb_obj_dup", so_rb_obj_dup, 1);
rb_define_method(cls, "rb_obj_call_init", so_rb_obj_call_init, 3);
+ rb_define_method(cls, "rb_obj_class", so_rb_obj_class, 1);
rb_define_method(cls, "rb_obj_classname", so_rbobjclassname, 1);
rb_define_method(cls, "rb_obj_freeze", object_spec_rb_obj_freeze, 1);
rb_define_method(cls, "rb_obj_frozen_p", object_spec_rb_obj_frozen_p, 1);
@@ -430,7 +473,9 @@ void Init_object_spec(void) {
rb_define_method(cls, "rb_obj_is_kind_of", so_kind_of, 2);
rb_define_method(cls, "rb_obj_method_arity", object_specs_rb_obj_method_arity, 2);
rb_define_method(cls, "rb_obj_method", object_specs_rb_obj_method, 2);
+#ifndef RUBY_VERSION_IS_3_2
rb_define_method(cls, "rb_obj_taint", object_spec_rb_obj_taint, 1);
+#endif
rb_define_method(cls, "rb_require", so_require, 0);
rb_define_method(cls, "rb_respond_to", so_respond_to, 2);
rb_define_method(cls, "rb_method_boundp", object_spec_rb_method_boundp, 3);
@@ -452,6 +497,7 @@ void Init_object_spec(void) {
rb_define_method(cls, "rb_is_rb_type_p_module", so_is_rb_type_p_module, 1);
rb_define_method(cls, "rb_is_rb_type_p_class", so_is_rb_type_p_class, 1);
rb_define_method(cls, "rb_is_rb_type_p_data", so_is_rb_type_p_data, 1);
+ rb_define_method(cls, "rb_is_rb_type_p_file", so_is_rb_type_p_file, 1);
rb_define_method(cls, "rb_is_builtin_type_object", so_is_builtin_type_object, 1);
rb_define_method(cls, "rb_is_builtin_type_array", so_is_builtin_type_array, 1);
rb_define_method(cls, "rb_is_builtin_type_module", so_is_builtin_type_module, 1);
@@ -474,6 +520,7 @@ void Init_object_spec(void) {
rb_define_method(cls, "speced_allocator?", speced_allocator_p, 1);
rb_define_method(cls, "custom_alloc_func?", custom_alloc_func_p, 1);
rb_define_method(cls, "not_implemented_method", rb_f_notimplement, -1);
+ rb_define_method(cls, "rb_ivar_foreach", object_spec_rb_ivar_foreach, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/proc_spec.c b/spec/ruby/optional/capi/ext/proc_spec.c
index e0bd8b1bbc..1137f4156b 100644
--- a/spec/ruby/optional/capi/ext/proc_spec.c
+++ b/spec/ruby/optional/capi/ext/proc_spec.c
@@ -11,10 +11,63 @@ VALUE proc_spec_rb_proc_new_function(RB_BLOCK_CALL_FUNC_ARGLIST(args, dummy)) {
return rb_funcall(args, rb_intern("inspect"), 0);
}
+VALUE proc_spec_rb_proc_new_function_arg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return arg;
+}
+
+VALUE proc_spec_rb_proc_new_function_argc(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return INT2FIX(argc);
+}
+
+VALUE proc_spec_rb_proc_new_function_argv_n(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ int n = FIX2INT(arg);
+ if (n < argc) {
+ return argv[n];
+ } else {
+ rb_exc_raise(rb_exc_new2(rb_eArgError, "Arg index out of bounds."));
+ }
+}
+
+VALUE proc_spec_rb_proc_new_function_callback_arg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return callback_arg;
+}
+
+VALUE proc_spec_rb_proc_new_function_blockarg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return blockarg;
+}
+
+VALUE proc_spec_rb_proc_new_function_block_given_p(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return rb_block_given_p() ? Qtrue : Qfalse;
+}
+
VALUE proc_spec_rb_proc_new(VALUE self) {
return rb_proc_new(proc_spec_rb_proc_new_function, Qnil);
}
+VALUE proc_spec_rb_proc_new_arg(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_arg, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_argc(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_argc, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_argv_n(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_argv_n, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_callback_arg(VALUE self, VALUE arg) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_callback_arg, arg);
+}
+
+VALUE proc_spec_rb_proc_new_blockarg(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_blockarg, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_block_given_p(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_block_given_p, Qnil);
+}
+
VALUE proc_spec_rb_proc_arity(VALUE self, VALUE prc) {
return INT2FIX(rb_proc_arity(prc));
}
@@ -62,6 +115,12 @@ VALUE proc_spec_rb_Proc_new(VALUE self, VALUE scenario) {
void Init_proc_spec(void) {
VALUE cls = rb_define_class("CApiProcSpecs", rb_cObject);
rb_define_method(cls, "rb_proc_new", proc_spec_rb_proc_new, 0);
+ rb_define_method(cls, "rb_proc_new_arg", proc_spec_rb_proc_new_arg, 0);
+ rb_define_method(cls, "rb_proc_new_argc", proc_spec_rb_proc_new_argc, 0);
+ rb_define_method(cls, "rb_proc_new_argv_n", proc_spec_rb_proc_new_argv_n, 0);
+ rb_define_method(cls, "rb_proc_new_callback_arg", proc_spec_rb_proc_new_callback_arg, 1);
+ rb_define_method(cls, "rb_proc_new_blockarg", proc_spec_rb_proc_new_blockarg, 0);
+ rb_define_method(cls, "rb_proc_new_block_given_p", proc_spec_rb_proc_new_block_given_p, 0);
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);
diff --git a/spec/ruby/optional/capi/ext/rbasic_spec.c b/spec/ruby/optional/capi/ext/rbasic_spec.c
index 6cd6c236c4..9178e5f639 100644
--- a/spec/ruby/optional/capi/ext/rbasic_spec.c
+++ b/spec/ruby/optional/capi/ext/rbasic_spec.c
@@ -6,9 +6,11 @@ extern "C" {
#endif
#ifndef FL_SHAREABLE
-static const VALUE VISIBLE_BITS = FL_TAINT | FL_FREEZE | ~(FL_USER0 - 1);
+static const VALUE VISIBLE_BITS = FL_TAINT | FL_FREEZE;
+static const VALUE DATA_VISIBLE_BITS = FL_TAINT | FL_FREEZE | ~(FL_USER0 - 1);
#else
-static const VALUE VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1);
+static const VALUE VISIBLE_BITS = FL_FREEZE;
+static const VALUE DATA_VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1);
#endif
#if SIZEOF_VALUE == SIZEOF_LONG
@@ -32,27 +34,27 @@ 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;
+ static VALUE spec_get_flags(const struct RBasic *b, VALUE visible_bits) {
+ VALUE flags = b->flags & visible_bits;
return VALUE2NUM(flags);
}
-static VALUE spec_set_flags(struct RBasic *b, VALUE flags) {
- flags &= VISIBLE_BITS;
- b->flags = (b->flags & ~VISIBLE_BITS) | flags;
+static VALUE spec_set_flags(struct RBasic *b, VALUE flags, VALUE visible_bits) {
+ flags &= visible_bits;
+ b->flags = (b->flags & ~visible_bits) | flags;
return VALUE2NUM(flags);
}
VALUE rbasic_spec_get_flags(VALUE self, VALUE val) {
- return spec_get_flags(RBASIC(val));
+ return spec_get_flags(RBASIC(val), VISIBLE_BITS);
}
VALUE rbasic_spec_set_flags(VALUE self, VALUE val, VALUE flags) {
- return spec_set_flags(RBASIC(val), NUM2VALUE(flags));
+ return spec_set_flags(RBASIC(val), NUM2VALUE(flags), VISIBLE_BITS);
}
VALUE rbasic_spec_copy_flags(VALUE self, VALUE to, VALUE from) {
- return spec_set_flags(RBASIC(to), RBASIC(from)->flags);
+ return spec_set_flags(RBASIC(to), RBASIC(from)->flags, VISIBLE_BITS);
}
VALUE rbasic_spec_get_klass(VALUE self, VALUE val) {
@@ -60,15 +62,15 @@ VALUE rbasic_spec_get_klass(VALUE self, VALUE val) {
}
VALUE rbasic_rdata_spec_get_flags(VALUE self, VALUE structure) {
- return spec_get_flags(&RDATA(structure)->basic);
+ return spec_get_flags(&RDATA(structure)->basic, DATA_VISIBLE_BITS);
}
VALUE rbasic_rdata_spec_set_flags(VALUE self, VALUE structure, VALUE flags) {
- return spec_set_flags(&RDATA(structure)->basic, NUM2VALUE(flags));
+ return spec_set_flags(&RDATA(structure)->basic, NUM2VALUE(flags), DATA_VISIBLE_BITS);
}
VALUE rbasic_rdata_spec_copy_flags(VALUE self, VALUE to, VALUE from) {
- return spec_set_flags(&RDATA(to)->basic, RDATA(from)->basic.flags);
+ return spec_set_flags(&RDATA(to)->basic, RDATA(from)->basic.flags, DATA_VISIBLE_BITS);
}
VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) {
diff --git a/spec/ruby/optional/capi/ext/regexp_spec.c b/spec/ruby/optional/capi/ext/regexp_spec.c
index 0a62616f33..9de7982b50 100644
--- a/spec/ruby/optional/capi/ext/regexp_spec.c
+++ b/spec/ruby/optional/capi/ext/regexp_spec.c
@@ -49,6 +49,12 @@ VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) {
return rb_funcall(regexp, rb_intern("match"), 1, str);
}
+VALUE regexp_spec_memcicmp(VALUE self, VALUE str1, VALUE str2) {
+ long l1 = RSTRING_LEN(str1);
+ long l2 = RSTRING_LEN(str2);
+ return INT2FIX(rb_memcicmp(RSTRING_PTR(str1), RSTRING_PTR(str2), l1 < l2 ? l1 : l2));
+}
+
void Init_regexp_spec(void) {
VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject);
rb_define_method(cls, "match", regexp_spec_match, 2);
@@ -60,6 +66,7 @@ void Init_regexp_spec(void) {
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);
+ rb_define_method(cls, "rb_memcicmp", regexp_spec_memcicmp, 2);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h
index 7e4a252b38..245669d200 100644
--- a/spec/ruby/optional/capi/ext/rubyspec.h
+++ b/spec/ruby/optional/capi/ext/rubyspec.h
@@ -22,6 +22,10 @@
(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 >= 2)
+#define RUBY_VERSION_IS_3_2
+#endif
+
#if RUBY_VERSION_MAJOR > 3 || (RUBY_VERSION_MAJOR == 3 && RUBY_VERSION_MINOR >= 1)
#define RUBY_VERSION_IS_3_1
#endif
@@ -30,34 +34,4 @@
#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 defined(__cplusplus) && !defined(RUBY_VERSION_IS_2_7)
-/* Ruby < 2.7 needs this to let these function with callbacks and compile in C++ code */
-#define rb_define_method(mod, name, func, argc) rb_define_method(mod, name, RUBY_METHOD_FUNC(func), argc)
-#define rb_define_protected_method(mod, name, func, argc) rb_define_protected_method(mod, name, RUBY_METHOD_FUNC(func), argc)
-#define rb_define_private_method(mod, name, func, argc) rb_define_private_method(mod, name, RUBY_METHOD_FUNC(func), argc)
-#define rb_define_singleton_method(mod, name, func, argc) rb_define_singleton_method(mod, name, RUBY_METHOD_FUNC(func), argc)
-#define rb_define_module_function(mod, name, func, argc) rb_define_module_function(mod, name, RUBY_METHOD_FUNC(func), argc)
-#define rb_define_global_function(name, func, argc) rb_define_global_function(name, RUBY_METHOD_FUNC(func), argc)
-#define rb_hash_foreach(hash, func, farg) rb_hash_foreach(hash, (int (*)(...))func, farg)
-#define st_foreach(tab, func, arg) st_foreach(tab, (int (*)(...))func, arg)
-#define rb_block_call(object, name, args_count, args, block_call_func, data) rb_block_call(object, name, args_count, args, RUBY_METHOD_FUNC(block_call_func), data)
-#define rb_ensure(b_proc, data1, e_proc, data2) rb_ensure(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2)
-#define rb_rescue(b_proc, data1, e_proc, data2) rb_rescue(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2)
-#define rb_rescue2(b_proc, data1, e_proc, data2, ...) rb_rescue2(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2, __VA_ARGS__)
-#define rb_catch(tag, func, data) rb_catch(tag, RUBY_METHOD_FUNC(func), data)
-#define rb_catch_obj(tag, func, data) rb_catch_obj(tag, RUBY_METHOD_FUNC(func), data)
-#define rb_proc_new(fn, arg) rb_proc_new(RUBY_METHOD_FUNC(fn), arg)
-#define rb_fiber_new(fn, arg) rb_fiber_new(RUBY_METHOD_FUNC(fn), arg)
-#define rb_thread_create(fn, arg) rb_thread_create(RUBY_METHOD_FUNC(fn), arg)
-#define rb_define_hooked_variable(name, var, getter, setter) rb_define_hooked_variable(name, var, RUBY_METHOD_FUNC(getter), (void (*)(...))setter)
-#endif
-
#endif
diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c
index feacbbdbb7..a858936243 100644
--- a/spec/ruby/optional/capi/ext/string_spec.c
+++ b/spec/ruby/optional/capi/ext/string_spec.c
@@ -87,6 +87,10 @@ 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_append(VALUE self, VALUE str, VALUE two) {
+ return rb_str_buf_append(str, two);
+}
+
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));
@@ -251,6 +255,17 @@ VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) {
return rb_str_new5(str, RSTRING_PTR(ptr), FIX2INT(len));
}
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated-declarations")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# endif
+#endif
+
+#ifndef RUBY_VERSION_IS_3_2
VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) {
return rb_tainted_str_new(RSTRING_PTR(str), FIX2INT(len));
}
@@ -258,6 +273,15 @@ VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) {
VALUE string_spec_rb_tainted_str_new2(VALUE self, VALUE str) {
return rb_tainted_str_new2(RSTRING_PTR(str));
}
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+# pragma GCC diagnostic pop
+#elif defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated-declarations")
+# pragma clang diagnostic pop
+# endif
+#endif
VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) {
return rb_str_plus(str1, str2);
@@ -413,6 +437,12 @@ VALUE string_spec_RSTRING_PTR_read(VALUE self, VALUE str, VALUE path) {
return capacities;
}
+VALUE string_spec_RSTRING_PTR_null_terminate(VALUE self, VALUE str, VALUE min_length) {
+ char* ptr = RSTRING_PTR(str);
+ char* end = ptr + RSTRING_LEN(str);
+ return rb_str_new(end, FIX2LONG(min_length));
+}
+
VALUE string_spec_StringValue(VALUE self, VALUE str) {
return StringValue(str);
}
@@ -453,6 +483,33 @@ static VALUE string_spec_rb_sprintf4(VALUE self, VALUE str) {
return rb_sprintf("Result: %+" PRIsVALUE ".", str);
}
+static VALUE string_spec_rb_sprintf5(VALUE self, VALUE width, VALUE precision, VALUE str) {
+ return rb_sprintf("Result: %*.*s.", FIX2INT(width), FIX2INT(precision), RSTRING_PTR(str));
+}
+
+static VALUE string_spec_rb_sprintf6(VALUE self, VALUE width, VALUE precision, VALUE str) {
+ return rb_sprintf("Result: %*.*" PRIsVALUE ".", FIX2INT(width), FIX2INT(precision), str);
+}
+
+static VALUE string_spec_rb_sprintf7(VALUE self, VALUE str, VALUE obj) {
+ VALUE results = rb_ary_new();
+ rb_ary_push(results, rb_sprintf(RSTRING_PTR(str), obj));
+ char cstr[256];
+ int len = snprintf(cstr, 256, RSTRING_PTR(str), obj);
+ rb_ary_push(results, rb_str_new(cstr, len));
+ return results;
+}
+
+static VALUE string_spec_rb_sprintf8(VALUE self, VALUE str, VALUE num) {
+ VALUE results = rb_ary_new();
+ rb_ary_push(results, rb_sprintf(RSTRING_PTR(str), FIX2LONG(num)));
+ char cstr[256];
+ int len = snprintf(cstr, 256, RSTRING_PTR(str), FIX2LONG(num));
+ rb_ary_push(results, rb_str_new(cstr, len));
+ return results;
+}
+
+PRINTF_ARGS(static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...), 1, 2);
static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) {
va_list varargs;
VALUE str;
@@ -515,6 +572,7 @@ static VALUE string_spec_rb_utf8_str_new_cstr(VALUE self) {
return rb_utf8_str_new_cstr("nokogiri");
}
+PRINTF_ARGS(static VALUE call_rb_str_vcatf(VALUE mesg, const char *fmt, ...), 2, 3);
static VALUE call_rb_str_vcatf(VALUE mesg, const char *fmt, ...){
va_list ap;
va_start(ap, fmt);
@@ -527,6 +585,30 @@ static VALUE string_spec_rb_str_vcatf(VALUE self, VALUE mesg) {
return call_rb_str_vcatf(mesg, "fmt %d %d number", 42, 7);
}
+static VALUE string_spec_rb_str_catf(VALUE self, VALUE mesg) {
+ return rb_str_catf(mesg, "fmt %d %d number", 41, 6);
+}
+
+static VALUE string_spec_rb_str_locktmp(VALUE self, VALUE str) {
+ return rb_str_locktmp(str);
+}
+
+static VALUE string_spec_rb_str_unlocktmp(VALUE self, VALUE str) {
+ return rb_str_unlocktmp(str);
+}
+
+VALUE rb_str_to_interned_str(VALUE str);
+VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc);
+
+static VALUE string_spec_rb_enc_interned_str_cstr(VALUE self, VALUE str, VALUE enc) {
+ rb_encoding *e = NIL_P(enc) ? 0 : rb_to_encoding(enc);
+ return rb_enc_interned_str_cstr(RSTRING_PTR(str), e);
+}
+
+static VALUE string_spec_rb_str_to_interned_str(VALUE self, VALUE str) {
+ return rb_str_to_interned_str(str);
+}
+
void Init_string_spec(void) {
VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject);
rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2);
@@ -539,6 +621,7 @@ void Init_string_spec(void) {
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_append", string_spec_rb_str_buf_append, 2);
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);
@@ -571,8 +654,10 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_str_new3", string_spec_rb_str_new3, 1);
rb_define_method(cls, "rb_str_new4", string_spec_rb_str_new4, 1);
rb_define_method(cls, "rb_str_new5", string_spec_rb_str_new5, 3);
+#ifndef RUBY_VERSION_IS_3_2
rb_define_method(cls, "rb_tainted_str_new", string_spec_rb_tainted_str_new, 2);
rb_define_method(cls, "rb_tainted_str_new2", string_spec_rb_tainted_str_new2, 1);
+#endif
rb_define_method(cls, "rb_str_plus", string_spec_rb_str_plus, 2);
rb_define_method(cls, "rb_str_times", string_spec_rb_str_times, 2);
rb_define_method(cls, "rb_str_modify_expand", string_spec_rb_str_modify_expand, 2);
@@ -595,6 +680,7 @@ void Init_string_spec(void) {
rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2);
rb_define_method(cls, "RSTRING_PTR_after_yield", string_spec_RSTRING_PTR_after_yield, 1);
rb_define_method(cls, "RSTRING_PTR_read", string_spec_RSTRING_PTR_read, 2);
+ rb_define_method(cls, "RSTRING_PTR_null_terminate", string_spec_RSTRING_PTR_null_terminate, 2);
rb_define_method(cls, "StringValue", string_spec_StringValue, 1);
rb_define_method(cls, "SafeStringValue", string_spec_SafeStringValue, 1);
rb_define_method(cls, "rb_str_hash", string_spec_rb_str_hash, 1);
@@ -604,6 +690,10 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_sprintf2", string_spec_rb_sprintf2, 3);
rb_define_method(cls, "rb_sprintf3", string_spec_rb_sprintf3, 1);
rb_define_method(cls, "rb_sprintf4", string_spec_rb_sprintf4, 1);
+ rb_define_method(cls, "rb_sprintf5", string_spec_rb_sprintf5, 3);
+ rb_define_method(cls, "rb_sprintf6", string_spec_rb_sprintf6, 3);
+ rb_define_method(cls, "rb_sprintf7", string_spec_rb_sprintf7, 2);
+ rb_define_method(cls, "rb_sprintf8", string_spec_rb_sprintf8, 2);
rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4);
rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2);
rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2);
@@ -617,6 +707,11 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_utf8_str_new", string_spec_rb_utf8_str_new, 0);
rb_define_method(cls, "rb_utf8_str_new_cstr", string_spec_rb_utf8_str_new_cstr, 0);
rb_define_method(cls, "rb_str_vcatf", string_spec_rb_str_vcatf, 1);
+ rb_define_method(cls, "rb_str_catf", string_spec_rb_str_catf, 1);
+ rb_define_method(cls, "rb_str_locktmp", string_spec_rb_str_locktmp, 1);
+ rb_define_method(cls, "rb_str_unlocktmp", string_spec_rb_str_unlocktmp, 1);
+ rb_define_method(cls, "rb_enc_interned_str_cstr", string_spec_rb_enc_interned_str_cstr, 2);
+ rb_define_method(cls, "rb_str_to_interned_str", string_spec_rb_str_to_interned_str, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/symbol_spec.c b/spec/ruby/optional/capi/ext/symbol_spec.c
index 7d9a7b4379..ba88635faa 100644
--- a/spec/ruby/optional/capi/ext/symbol_spec.c
+++ b/spec/ruby/optional/capi/ext/symbol_spec.c
@@ -47,10 +47,19 @@ VALUE symbol_spec_rb_id2name(VALUE self, VALUE symbol) {
return rb_str_new(c_str, strlen(c_str));
}
+VALUE symbol_spec_rb_id2name_id_zero(VALUE self) {
+ const char* c_str = rb_id2name((ID) 0);
+ return c_str ? rb_str_new(c_str, strlen(c_str)) : Qnil;
+}
+
VALUE symbol_spec_rb_id2str(VALUE self, VALUE symbol) {
return rb_id2str(SYM2ID(symbol));
}
+VALUE symbol_spec_rb_id2str_id_zero(VALUE self) {
+ return rb_id2str((ID) 0);
+}
+
VALUE symbol_spec_rb_intern_str(VALUE self, VALUE str) {
return ID2SYM(rb_intern_str(str));
}
@@ -90,7 +99,9 @@ void Init_symbol_spec(void) {
rb_define_method(cls, "rb_intern3", symbol_spec_rb_intern3, 3);
rb_define_method(cls, "rb_intern3_c_compare", symbol_spec_rb_intern3_c_compare, 4);
rb_define_method(cls, "rb_id2name", symbol_spec_rb_id2name, 1);
+ rb_define_method(cls, "rb_id2name_id_zero", symbol_spec_rb_id2name_id_zero, 0);
rb_define_method(cls, "rb_id2str", symbol_spec_rb_id2str, 1);
+ rb_define_method(cls, "rb_id2str_id_zero", symbol_spec_rb_id2str_id_zero, 0);
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);
diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c
index 21f98dec52..be812d796f 100644
--- a/spec/ruby/optional/capi/ext/thread_spec.c
+++ b/spec/ruby/optional/capi/ext/thread_spec.c
@@ -11,6 +11,10 @@
#define pipe(p) rb_w32_pipe(p)
#endif
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -131,6 +135,38 @@ static VALUE thread_spec_rb_thread_create(VALUE self, VALUE proc, VALUE arg) {
return rb_thread_create(thread_spec_call_proc, (void*)args);
}
+static VALUE thread_spec_ruby_native_thread_p(VALUE self) {
+ if (ruby_native_thread_p()) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
+
+#ifndef _WIN32
+static VALUE false_result = Qfalse;
+static VALUE true_result = Qtrue;
+
+static void *new_thread_check(void *args) {
+ if (ruby_native_thread_p()) {
+ return &true_result;
+ } else {
+ return &false_result;
+ }
+}
+#endif
+
+static VALUE thread_spec_ruby_native_thread_p_new_thread(VALUE self) {
+#ifndef _WIN32
+ pthread_t t;
+ void *result = &true_result;
+ pthread_create(&t, NULL, new_thread_check, NULL);
+ pthread_join(t, &result);
+ return *(VALUE *)result;
+#else
+ return Qfalse;
+#endif
+}
void Init_thread_spec(void) {
VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject);
@@ -143,6 +179,8 @@ void Init_thread_spec(void) {
rb_define_method(cls, "rb_thread_wakeup", thread_spec_rb_thread_wakeup, 1);
rb_define_method(cls, "rb_thread_wait_for", thread_spec_rb_thread_wait_for, 2);
rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2);
+ rb_define_method(cls, "ruby_native_thread_p", thread_spec_ruby_native_thread_p, 0);
+ rb_define_method(cls, "ruby_native_thread_p_new_thread", thread_spec_ruby_native_thread_p_new_thread, 0);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/util_spec.c b/spec/ruby/optional/capi/ext/util_spec.c
index a7269353c2..95ba71ea9d 100644
--- a/spec/ruby/optional/capi/ext/util_spec.c
+++ b/spec/ruby/optional/capi/ext/util_spec.c
@@ -7,15 +7,18 @@ extern "C" {
#endif
VALUE util_spec_rb_scan_args(VALUE self, VALUE argv, VALUE fmt, VALUE expected, VALUE acc) {
- int i, result, argc = (int)RARRAY_LEN(argv);
- VALUE args[6], failed, a1, a2, a3, a4, a5, a6;
-
- failed = rb_intern("failed");
- a1 = a2 = a3 = a4 = a5 = a6 = failed;
-
- for(i = 0; i < argc; i++) {
- args[i] = rb_ary_entry(argv, i);
- }
+ int result, argc;
+ VALUE a1, a2, a3, a4, a5, a6;
+
+ argc = (int) RARRAY_LEN(argv);
+ VALUE* args = RARRAY_PTR(argv);
+ /* the line above can be replaced with this for Ruby implementations which do not support RARRAY_PTR() yet
+ VALUE args[6];
+ for(int i = 0; i < argc; i++) {
+ args[i] = rb_ary_entry(argv, i);
+ } */
+
+ a1 = a2 = a3 = a4 = a5 = a6 = INT2FIX(-1);
#ifdef RB_SCAN_ARGS_KEYWORDS
if (*RSTRING_PTR(fmt) == 'k') {
diff --git a/spec/ruby/optional/capi/fiber_spec.rb b/spec/ruby/optional/capi/fiber_spec.rb
index 196ddc45fb..357033f860 100644
--- a/spec/ruby/optional/capi/fiber_spec.rb
+++ b/spec/ruby/optional/capi/fiber_spec.rb
@@ -48,4 +48,42 @@ describe "C-API Fiber function" do
fiber.resume(42).should == "42"
end
end
+
+ ruby_version_is '3.1' do
+ describe "rb_fiber_raise" do
+ it "raises an exception on the resumed fiber" do
+ fiber = Fiber.new do
+ begin
+ Fiber.yield
+ rescue => error
+ error
+ end
+ end
+
+ fiber.resume
+
+ result = @s.rb_fiber_raise(fiber, "Boom!")
+ result.should be_an_instance_of(RuntimeError)
+ result.message.should == "Boom!"
+ end
+
+ it "raises an exception on the transferred fiber" do
+ main = Fiber.current
+
+ fiber = Fiber.new do
+ begin
+ main.transfer
+ rescue => error
+ error
+ end
+ end
+
+ fiber.transfer
+
+ result = @s.rb_fiber_raise(fiber, "Boom!")
+ result.should be_an_instance_of(RuntimeError)
+ result.message.should == "Boom!"
+ end
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/fixtures/class.rb b/spec/ruby/optional/capi/fixtures/class.rb
index dbb0b69967..b463e3b4c3 100644
--- a/spec/ruby/optional/capi/fixtures/class.rb
+++ b/spec/ruby/optional/capi/fixtures/class.rb
@@ -15,6 +15,16 @@ class CApiClassSpecs
end
end
+ class KeywordAlloc
+ attr_reader :initialized, :args, :kwargs
+
+ def initialize(*args, **kwargs)
+ @initialized = true
+ @args = args
+ @kwargs = kwargs
+ end
+ end
+
class Attr
def initialize
@foo, @bar, @baz = 1, 2, 3
@@ -87,5 +97,8 @@ class CApiClassSpecs
class B
end
+
+ module M
+ end
end
end
diff --git a/spec/ruby/optional/capi/fixtures/object.rb b/spec/ruby/optional/capi/fixtures/object.rb
new file mode 100644
index 0000000000..a59f2309d8
--- /dev/null
+++ b/spec/ruby/optional/capi/fixtures/object.rb
@@ -0,0 +1,29 @@
+class CApiObjectSpecs
+ class IVars
+ def initialize
+ @a = 3
+ @b = 7
+ @c = 4
+ end
+
+ def self.set_class_variables
+ @@foo = :a
+ @@bar = :b
+ @@baz = :c
+ end
+ end
+
+ module MVars
+ @@mvar = :foo
+ @@mvar2 = :bar
+
+ @ivar = :baz
+ end
+
+ module CVars
+ @@cvar = :foo
+ @@cvar2 = :bar
+
+ @ivar = :baz
+ end
+end
diff --git a/spec/ruby/optional/capi/gc_spec.rb b/spec/ruby/optional/capi/gc_spec.rb
index 23e2b7c9ab..d76ea7394f 100644
--- a/spec/ruby/optional/capi/gc_spec.rb
+++ b/spec/ruby/optional/capi/gc_spec.rb
@@ -7,15 +7,33 @@ describe "CApiGCSpecs" do
@f = CApiGCSpecs.new
end
- it "correctly gets the value from a registered address" do
- @f.registered_tagged_address.should == 10
- @f.registered_tagged_address.should equal(@f.registered_tagged_address)
- @f.registered_reference_address.should == "Globally registered data"
- @f.registered_reference_address.should equal(@f.registered_reference_address)
+ describe "rb_gc_register_address" do
+ it "correctly gets the value from a registered address" do
+ @f.registered_tagged_address.should == 10
+ @f.registered_tagged_address.should equal(@f.registered_tagged_address)
+ @f.registered_reference_address.should == "Globally registered data"
+ @f.registered_reference_address.should equal(@f.registered_reference_address)
+ end
+
+ it "keeps the value alive even if the value is assigned after rb_gc_register_address() is called" do
+ GC.start
+ @f.registered_before_rb_gc_register_address.should == "registered before rb_gc_register_address()"
+ end
+
+ it "can be called outside Init_" do
+ @f.rb_gc_register_address.should == "rb_gc_register_address() outside Init_"
+ @f.rb_gc_unregister_address
+ end
end
- describe "rb_gc_enable" do
+ describe "rb_global_variable" do
+ it "keeps the value alive even if the value is assigned after rb_global_variable() is called" do
+ GC.start
+ @f.registered_before_rb_global_variable.should == "registered before rb_global_variable()"
+ end
+ end
+ describe "rb_gc_enable" do
after do
GC.enable
end
diff --git a/spec/ruby/optional/capi/globals_spec.rb b/spec/ruby/optional/capi/globals_spec.rb
index cc6f6ef3a8..48677620bc 100644
--- a/spec/ruby/optional/capi/globals_spec.rb
+++ b/spec/ruby/optional/capi/globals_spec.rb
@@ -9,7 +9,7 @@ describe "CApiGlobalSpecs" do
end
it "correctly gets global values" do
- @f.sb_gv_get("$BLAH").should == nil
+ suppress_warning { @f.sb_gv_get("$BLAH") }.should == nil
@f.sb_gv_get("$\\").should == nil
@f.sb_gv_get("\\").should == nil # rb_gv_get should change \ to $\
end
@@ -21,7 +21,7 @@ describe "CApiGlobalSpecs" do
end
it "correctly sets global values" do
- @f.sb_gv_get("$BLAH").should == nil
+ suppress_warning { @f.sb_gv_get("$BLAH") }.should == nil
@f.sb_gv_set("$BLAH", 10)
begin
@f.sb_gv_get("$BLAH").should == 10
@@ -42,6 +42,10 @@ describe "CApiGlobalSpecs" do
end
it "rb_define_readonly_variable should define a new readonly global variable" do
+ # Check the gvar doesn't exist and ensure rb_gv_get doesn't implicitly declare the gvar,
+ # otherwise the rb_define_readonly_variable call will conflict.
+ suppress_warning { @f.sb_gv_get("ro_gvar") } .should == nil
+
@f.rb_define_readonly_variable("ro_gvar", 15)
$ro_gvar.should == 15
-> { $ro_gvar = 10 }.should raise_error(NameError)
@@ -53,6 +57,52 @@ describe "CApiGlobalSpecs" do
$hooked_gvar.should == 4
end
+ it "rb_define_hooked_variable should use default accessors if NULL ones are supplied" do
+ @f.rb_define_hooked_variable_default_accessors("$hooked_gvar_default_accessors")
+ $hooked_gvar_default_accessors = 10
+ $hooked_gvar_default_accessors.should == 10
+ end
+
+ it "rb_define_hooked_variable with default accessors should return nil for NULL variables" do
+ @f.rb_define_hooked_variable_null_var("$hooked_gvar_null_value")
+ $hooked_gvar_null_value.should == nil
+ end
+
+ describe "rb_define_virtual_variable" do
+ describe "with default accessors" do
+ before :all do
+ @f.rb_define_virtual_variable_default_accessors("$virtual_variable_default_accessors")
+ end
+
+ it "is read-only" do
+ -> { $virtual_variable_default_accessors = 10 }.should raise_error(NameError, /read-only/)
+ end
+
+ it "returns false with the default getter" do
+ $virtual_variable_default_accessors.should == false
+ $virtual_variable_default_accessors.should == false
+ end
+ end
+
+ describe "with supplied accessors" do
+ before :all do
+ @f.rb_define_virtual_variable_incrementing_accessors("$virtual_variable_incrementing_accessors")
+ end
+
+ it "returns a dynamically changing value" do
+ $virtual_variable_incrementing_accessors = 20
+ $virtual_variable_incrementing_accessors.should == 20
+ $virtual_variable_incrementing_accessors.should == 21
+ $virtual_variable_incrementing_accessors.should == 22
+
+ $virtual_variable_incrementing_accessors = 100
+ $virtual_variable_incrementing_accessors.should == 100
+ $virtual_variable_incrementing_accessors.should == 101
+ $virtual_variable_incrementing_accessors.should == 102
+ end
+ end
+ end
+
describe "rb_fs" do
before :each do
@field_separator = $;
diff --git a/spec/ruby/optional/capi/io_spec.rb b/spec/ruby/optional/capi/io_spec.rb
index 489a01c515..95717351a6 100644
--- a/spec/ruby/optional/capi/io_spec.rb
+++ b/spec/ruby/optional/capi/io_spec.rb
@@ -262,6 +262,21 @@ describe "C-API IO function" do
end
end
+ describe "rb_thread_fd_select" do
+ it "waits until an fd is ready for reading" do
+ @w_io.write "rb_thread_fd_select"
+ @o.rb_thread_fd_select_read(@r_io).should == 1
+ end
+
+ it "waits until an fd is ready for writing" do
+ @o.rb_thread_fd_select_write(@w_io).should == 1
+ end
+
+ it "waits until an fd is ready for writing with timeout" do
+ @o.rb_thread_fd_select_timeout(@w_io).should == 1
+ end
+ end
+
platform_is_not :windows do
describe "rb_io_wait_readable" do
it "returns false if there is no error condition" do
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 758d944da9..54d8d8a8d3 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -412,12 +412,10 @@ describe "C-API Kernel function" do
}.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
+ 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
@@ -506,6 +504,25 @@ describe "C-API Kernel function" do
end
end
+ describe "rb_eval_cmd_kw" do
+ it "evaluates a string of ruby code" do
+ @s.rb_eval_cmd_kw("1+1", [], 0).should == 2
+ end
+
+ it "calls a proc with the supplied arguments" do
+ @s.rb_eval_cmd_kw(-> *x { x.map { |i| i + 1 } }, [1, 3, 7], 0).should == [2, 4, 8]
+ end
+
+ it "calls a proc with keyword arguments if kw_splat is non zero" do
+ a_proc = -> *x, **y {
+ res = x.map { |i| i + 1 }
+ y.each { |k, v| res << k; res << v }
+ res
+ }
+ @s.rb_eval_cmd_kw(a_proc, [1, 3, 7, {a: 1, b: 2, c: 3}], 1).should == [2, 4, 8, :a, 1, :b, 2, :c, 3]
+ end
+ end
+
describe "rb_block_proc" do
it "converts the implicit block into a proc" do
proc = @s.rb_block_proc { 1+1 }
@@ -567,7 +584,64 @@ describe "C-API Kernel function" do
end
end
- describe "rb_funcall3" do
+ describe "rb_funcallv" do
+ def empty
+ 42
+ end
+
+ def sum(a, b)
+ a + b
+ end
+
+ it "calls a method" do
+ @s.rb_funcallv(self, :empty, []).should == 42
+ @s.rb_funcallv(self, :sum, [1, 2]).should == 3
+ end
+ end
+
+ ruby_version_is "3.0" do
+ describe "rb_funcallv_kw" do
+ it "passes keyword arguments to the callee" do
+ def m(*args, **kwargs)
+ [args, kwargs]
+ end
+
+ @s.rb_funcallv_kw(self, :m, [{}]).should == [[], {}]
+ @s.rb_funcallv_kw(self, :m, [{a: 1}]).should == [[], {a: 1}]
+ @s.rb_funcallv_kw(self, :m, [{b: 2}, {a: 1}]).should == [[{b: 2}], {a: 1}]
+ @s.rb_funcallv_kw(self, :m, [{b: 2}, {}]).should == [[{b: 2}], {}]
+ end
+
+ it "raises TypeError if the last argument is not a Hash" do
+ def m(*args, **kwargs)
+ [args, kwargs]
+ end
+
+ -> {
+ @s.rb_funcallv_kw(self, :m, [42])
+ }.should raise_error(TypeError, 'no implicit conversion of Integer into Hash')
+ end
+ end
+
+ describe "rb_keyword_given_p" do
+ it "returns whether keywords were given to the C extension method" do
+ h = {a: 1}
+ empty = {}
+ @s.rb_keyword_given_p(a: 1).should == true
+ @s.rb_keyword_given_p("foo" => "bar").should == true
+ @s.rb_keyword_given_p(**h).should == true
+
+ @s.rb_keyword_given_p(h).should == false
+ @s.rb_keyword_given_p().should == false
+ @s.rb_keyword_given_p(**empty).should == false
+
+ @s.rb_funcallv_kw(@s, :rb_keyword_given_p, [{a: 1}]).should == true
+ @s.rb_funcallv_kw(@s, :rb_keyword_given_p, [{}]).should == false
+ end
+ end
+ end
+
+ describe "rb_funcallv_public" do
before :each do
@obj = Object.new
class << @obj
@@ -578,10 +652,11 @@ describe "C-API Kernel function" do
end
it "calls a public method" do
- @s.rb_funcall3(@obj, :method_public).should == :method_public
+ @s.rb_funcallv_public(@obj, :method_public).should == :method_public
end
+
it "does not call a private method" do
- -> { @s.rb_funcall3(@obj, :method_private) }.should raise_error(NoMethodError, /private/)
+ -> { @s.rb_funcallv_public(@obj, :method_private) }.should raise_error(NoMethodError, /private/)
end
end
@@ -599,6 +674,7 @@ describe "C-API Kernel function" 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/module_spec.rb b/spec/ruby/optional/capi/module_spec.rb
index acf4d1fe48..d7c0ab9c52 100644
--- a/spec/ruby/optional/capi/module_spec.rb
+++ b/spec/ruby/optional/capi/module_spec.rb
@@ -252,22 +252,30 @@ describe "CApiModule" do
cls.new.method(:test_method).arity.should == 0
end
+ it "returns the correct arity when argc of the method in class is 1" do
+ @m.rb_define_method_1required(42).should == 42
+ @m.method(:rb_define_method_1required).arity.should == 1
+ end
+
+ it "returns the correct arity when argc of the method in class is 2" do
+ @m.rb_define_method_2required(1, 2).should == 2
+ @m.method(:rb_define_method_2required).arity.should == 2
+ end
+
+ it "defines a method taking variable arguments as a C array if the argument count is -1" do
+ @m.rb_define_method_varargs_1(1, 3, 7, 4).should == [1, 3, 7, 4]
+ end
+
it "returns the correct arity when argc of the method in class is -1" do
- cls = Class.new
- @m.rb_define_method_c_array(cls, "test_method_c_array")
- cls.new.method(:test_method_c_array).arity.should == -1
+ @m.method(:rb_define_method_varargs_1).arity.should == -1
end
- it "returns the correct arity when argc of the method in class is -2" do
- cls = Class.new
- @m.rb_define_method_ruby_array(cls, "test_method_ruby_array")
- cls.new.method(:test_method_ruby_array).arity.should == -1
+ it "defines a method taking variable arguments as a Ruby array if the argument count is -2" do
+ @m.rb_define_method_varargs_2(1, 3, 7, 4).should == [1, 3, 7, 4]
end
- it "returns the correct arity when argc of the method in class is 2" do
- cls = Class.new
- @m.rb_define_method_2required(cls, "test_method_2required")
- cls.new.method(:test_method_2required).arity.should == 2
+ it "returns the correct arity when argc of the method in class is -2" do
+ @m.method(:rb_define_method_varargs_2).arity.should == -1
end
it "defines a method on a module" do
diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb
index ab11367060..25a43d8908 100644
--- a/spec/ruby/optional/capi/object_spec.rb
+++ b/spec/ruby/optional/capi/object_spec.rb
@@ -1,4 +1,5 @@
require_relative 'spec_helper'
+require_relative 'fixtures/object'
load_extension("object")
@@ -30,6 +31,7 @@ describe "CApiObject" do
class ObjectTest
def initialize
@foo = 7
+ yield if block_given?
end
def foo
@@ -88,6 +90,15 @@ describe "CApiObject" do
o.initialized.should be_true
o.arguments.should == [:one, :two]
end
+
+ it "passes the block to #initialize" do
+ v = nil
+ o = @o.rb_obj_alloc(ObjectTest)
+ @o.rb_obj_call_init(o, 0, []) do
+ v = :foo
+ end
+ v.should == :foo
+ end
end
describe "rb_is_instance_of" do
@@ -438,15 +449,6 @@ describe "CApiObject" do
end
describe "FL_TEST" do
- ruby_version_is ''...'2.7' do
- it "returns correct status for FL_TAINT" do
- obj = Object.new
- @o.FL_TEST(obj, "FL_TAINT").should == 0
- obj.taint
- @o.FL_TEST(obj, "FL_TAINT").should_not == 0
- end
- end
-
it "returns correct status for FL_FREEZE" do
obj = Object.new
@o.FL_TEST(obj, "FL_FREEZE").should == 0
@@ -480,12 +482,31 @@ describe "CApiObject" do
end
end
+ describe "rb_obj_class" do
+ it "returns the class of an object" do
+ @o.rb_obj_class(nil).should == NilClass
+ @o.rb_obj_class(0).should == Integer
+ @o.rb_obj_class(0.1).should == Float
+ @o.rb_obj_class(ObjectTest.new).should == ObjectTest
+ end
+
+ it "does not return the singleton class if it exists" do
+ o = ObjectTest.new
+ o.singleton_class
+ @o.rb_obj_class(o).should equal ObjectTest
+ end
+ end
+
describe "rb_obj_classname" do
it "returns the class name of an object" do
@o.rb_obj_classname(nil).should == 'NilClass'
@o.rb_obj_classname(0).should == 'Integer'
@o.rb_obj_classname(0.1).should == 'Float'
@o.rb_obj_classname(ObjectTest.new).should == 'ObjectTest'
+
+ o = ObjectTest.new
+ o.singleton_class
+ @o.rb_obj_classname(o).should == 'ObjectTest'
end
end
@@ -503,6 +524,21 @@ describe "CApiObject" do
@o.rb_is_type_class(ObjectTest).should == true
@o.rb_is_type_data(Time.now).should == true
end
+
+ it "returns T_FILE for instances of IO and subclasses" do
+ STDERR.class.should == IO
+ @o.rb_is_rb_type_p_file(STDERR).should == true
+
+ File.open(__FILE__) do |f|
+ f.class.should == File
+ @o.rb_is_rb_type_p_file(f).should == true
+ end
+
+ require 'socket'
+ TCPServer.open(0) do |s|
+ @o.rb_is_rb_type_p_file(s).should == true
+ end
+ end
end
describe "rb_check_type" do
@@ -617,68 +653,12 @@ describe "CApiObject" do
end
describe "OBJ_TAINT" do
- ruby_version_is ''...'2.7' do
- it "taints the object" do
- obj = mock("tainted")
- @o.OBJ_TAINT(obj)
- obj.tainted?.should be_true
- end
- end
end
describe "OBJ_TAINTED" do
- ruby_version_is ''...'2.7' do
- it "returns C true if the object is tainted" do
- obj = mock("tainted")
- obj.taint
- @o.OBJ_TAINTED(obj).should be_true
- end
-
- it "returns C false if the object is not tainted" do
- obj = mock("untainted")
- @o.OBJ_TAINTED(obj).should be_false
- end
- end
end
describe "OBJ_INFECT" do
- ruby_version_is ''...'2.7' do
- it "does not taint the first argument if the second argument is not tainted" do
- host = mock("host")
- source = mock("source")
- @o.OBJ_INFECT(host, source)
- host.tainted?.should be_false
- end
-
- it "taints the first argument if the second argument is tainted" do
- host = mock("host")
- source = mock("source").taint
- @o.OBJ_INFECT(host, source)
- host.tainted?.should be_true
- end
-
- it "does not untrust the first argument if the second argument is trusted" do
- host = mock("host")
- source = mock("source")
- @o.OBJ_INFECT(host, source)
- host.untrusted?.should be_false
- end
-
- it "untrusts the first argument if the second argument is untrusted" do
- host = mock("host")
- source = mock("source").untrust
- @o.OBJ_INFECT(host, source)
- host.untrusted?.should be_true
- end
-
- it "propagates both taint and distrust" do
- host = mock("host")
- source = mock("source").taint.untrust
- @o.OBJ_INFECT(host, source)
- host.tainted?.should be_true
- host.untrusted?.should be_true
- end
- end
end
describe "rb_obj_freeze" do
@@ -712,18 +692,6 @@ describe "CApiObject" do
end
describe "rb_obj_taint" do
- ruby_version_is ''...'2.7' do
- it "marks the object passed as tainted" do
- obj = ""
- obj.should_not.tainted?
- @o.rb_obj_taint(obj)
- obj.should.tainted?
- end
-
- 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
@@ -1016,5 +984,24 @@ describe "CApiObject" do
@o.speced_allocator?(parent).should == true
end
end
+
+ describe "rb_ivar_foreach" do
+ it "calls the callback function for each instance variable on an object" do
+ o = CApiObjectSpecs::IVars.new
+ ary = @o.rb_ivar_foreach(o)
+ ary.should == [:@a, 3, :@b, 7, :@c, 4]
+ end
+
+ it "calls the callback function for each cvar and ivar on a class" do
+ ary = @o.rb_ivar_foreach(CApiObjectSpecs::CVars)
+ ary.should == [:__classpath__, 'CApiObjectSpecs::CVars', :@@cvar, :foo, :@@cvar2, :bar, :@ivar, :baz]
+ end
+
+ it "calls the callback function for each cvar and ivar on a module" do
+ ary = @o.rb_ivar_foreach(CApiObjectSpecs::MVars)
+ ary.should == [:__classpath__, 'CApiObjectSpecs::MVars', :@@mvar, :foo, :@@mvar2, :bar, :@ivar, :baz]
+ end
+
+ end
end
end
diff --git a/spec/ruby/optional/capi/proc_spec.rb b/spec/ruby/optional/capi/proc_spec.rb
index 6e797fdeb4..c839665ae9 100644
--- a/spec/ruby/optional/capi/proc_spec.rb
+++ b/spec/ruby/optional/capi/proc_spec.rb
@@ -7,6 +7,8 @@ describe "C-API Proc function" do
before :each do
@p = CApiProcSpecs.new
@prc = @p.rb_proc_new
+ @prc2 = @p.rb_proc_new_argv_n
+ @prc3 = @p.rb_proc_new_argc
end
describe "rb_proc_new" do
@@ -15,6 +17,7 @@ describe "C-API Proc function" do
end
it "calls the C function wrapped by the Proc instance when sent #call" do
+ @p.rb_proc_new_arg.call().should == nil
@prc.call(:foo_bar).should == ":foo_bar"
@prc.call([:foo, :bar]).should == "[:foo, :bar]"
end
@@ -24,6 +27,30 @@ describe "C-API Proc function" do
@prc[[:foo, :bar]].should == "[:foo, :bar]"
end
+ it "calls the C function with the arg count in argc" do
+ @prc3.call().should == 0
+ @prc3.call(:foo).should == 1
+ @prc3.call(:foo, :bar).should == 2
+ end
+
+ it "calls the C function with arguments in argv" do
+ @prc2.call(1, :foo).should == :foo
+ @prc2.call(2, :foo, :bar).should == :bar
+ -> { @prc2.call(3, :foo, :bar) }.should raise_error(ArgumentError)
+ end
+
+ it "calls the C function with the block passed in blockarg" do
+ a_block = :foo.to_proc
+ @p.rb_proc_new_blockarg.call(&a_block).should == a_block
+ @p.rb_proc_new_blockarg.call().should == nil
+ end
+
+ it "calls the C function and yields to the block passed in blockarg" do
+ @p.rb_proc_new_block_given_p.call() do
+ end.should == false
+ @p.rb_proc_new_block_given_p.call().should == false
+ end
+
it "returns a Proc instance correctly described in #inspect without source location" do
@prc.inspect.should =~ /^#<Proc:([^ :@]*?)>$/
end
@@ -88,20 +115,6 @@ describe "C-API when calling Proc.new from a C function" do
# For example: C -> Ruby <- C -> Ruby means a C function called into Ruby
# code which returned to C, then C called into Ruby code again.
- ruby_version_is ""..."2.7" do
- # Ruby -> C -> rb_funcall(Proc.new)
- it "returns the Proc passed by the Ruby code calling the C function" do
- prc = @p.rb_Proc_new(0) { :called }
- prc.call.should == :called
- end
-
- # Ruby -> C -> Ruby <- C -> rb_funcall(Proc.new)
- it "returns the Proc passed to the Ruby method when the C function calls other Ruby methods before calling Proc.new" do
- prc = @p.rb_Proc_new(1) { :called }
- prc.call.should == :called
- end
- end
-
# Ruby -> C -> Ruby -> Proc.new
it "raises an ArgumentError when the C function calls a Ruby method that calls Proc.new" do
-> {
@@ -115,20 +128,6 @@ describe "C-API when calling Proc.new from a C function" do
-> { @p.rb_Proc_new(3) { :called } }.should raise_error(ArgumentError)
end
- ruby_version_is ""..."2.7" do
- # Ruby -> C -> Ruby -> C (with new block) -> rb_funcall(Proc.new)
- it "returns the most recent Proc passed when the Ruby method called the C function" do
- prc = @p.rb_Proc_new(4) { :called }
- prc.call.should == :calling_with_block
- end
-
- # Ruby -> C -> Ruby -> C (with new block) <- Ruby <- C -> # rb_funcall(Proc.new)
- it "returns the Proc passed from the original Ruby call to the C function" do
- prc = @p.rb_Proc_new(5) { :called }
- prc.call.should == :called
- end
- end
-
# Ruby -> C -> Ruby -> block_given?
it "returns false from block_given? in a Ruby method called by the C function" do
@p.rb_Proc_new(6).should be_false
diff --git a/spec/ruby/optional/capi/rbasic_spec.rb b/spec/ruby/optional/capi/rbasic_spec.rb
index 691c4250d2..577f2060da 100644
--- a/spec/ruby/optional/capi/rbasic_spec.rb
+++ b/spec/ruby/optional/capi/rbasic_spec.rb
@@ -1,7 +1,6 @@
require_relative 'spec_helper'
require_relative 'shared/rbasic'
load_extension("rbasic")
-return if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
load_extension("data")
load_extension("array")
@@ -20,4 +19,24 @@ describe "RBasic support for RData" do
@data = -> { [@wrapping.wrap_struct(1024), @wrapping.wrap_struct(1025)] }
end
it_should_behave_like :rbasic
+
+ it "supports user flags" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ @specs.set_flags(obj, 1 << 14 | 1 << 16 | initial).should == 1 << 14 | 1 << 16 | initial
+ @specs.get_flags(obj).should == 1 << 14 | 1 << 16 | initial
+ @specs.set_flags(obj, initial).should == initial
+ end
+
+ it "supports copying the flags from one object over to the other" do
+ obj1, obj2 = @data.call
+ initial = @specs.get_flags(obj1)
+ @specs.get_flags(obj2).should == initial
+ @specs.set_flags(obj1, 1 << 14 | 1 << 16 | initial)
+ @specs.copy_flags(obj2, obj1)
+ @specs.get_flags(obj2).should == 1 << 14 | 1 << 16 | initial
+ @specs.set_flags(obj1, initial)
+ @specs.copy_flags(obj2, obj1)
+ @specs.get_flags(obj2).should == initial
+ end
end
diff --git a/spec/ruby/optional/capi/regexp_spec.rb b/spec/ruby/optional/capi/regexp_spec.rb
index 81844e2a6e..af366e17a2 100644
--- a/spec/ruby/optional/capi/regexp_spec.rb
+++ b/spec/ruby/optional/capi/regexp_spec.rb
@@ -109,4 +109,20 @@ describe "C-API Regexp function" do
thr.join
end
end
+
+ describe "rb_memicmp" do
+ it "returns 0 for identical strings" do
+ @p.rb_memcicmp('Hello', 'Hello').should == 0
+ end
+
+ it "returns 0 for strings which only differ in case" do
+ @p.rb_memcicmp('Hello', 'HELLO').should == 0
+ @p.rb_memcicmp('HELLO', 'Hello').should == 0
+ end
+
+ it "returns the difference between the first non matching characters" do
+ @p.rb_memcicmp('Hello', 'HELLP').should == -1
+ @p.rb_memcicmp('HELLp', 'Hello').should == 1
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/shared/rbasic.rb b/spec/ruby/optional/capi/shared/rbasic.rb
index 659cb074dd..95c3137143 100644
--- a/spec/ruby/optional/capi/shared/rbasic.rb
+++ b/spec/ruby/optional/capi/shared/rbasic.rb
@@ -10,7 +10,7 @@ describe :rbasic, shared: true do
obj, _ = @data.call
initial = @specs.get_flags(obj)
obj.freeze
- @specs.get_flags(obj).should == @freeze | initial
+ (@specs.get_flags(obj) & 0xFFFF).should == (@freeze | initial) & 0xFFFF
end
it "supports setting the FREEZE flag" do
@@ -20,60 +20,6 @@ describe :rbasic, shared: true do
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
diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb
index 2c36ead8d0..2691aa1332 100644
--- a/spec/ruby/optional/capi/spec_helper.rb
+++ b/spec/ruby/optional/capi/spec_helper.rb
@@ -29,12 +29,14 @@ def compile_extension(name)
ext = "#{name}_spec"
lib = "#{object_path}/#{ext}.#{RbConfig::CONFIG['DLEXT']}"
- ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"
+ rubyhdrdir = RbConfig::CONFIG['rubyhdrdir']
+ ruby_header = "#{rubyhdrdir}/ruby.h"
+ abi_header = "#{rubyhdrdir}/ruby/internal/abi.h"
if RbConfig::CONFIG["ENABLE_SHARED"] == "yes"
- libdirname = RbConfig::CONFIG['LIBPATHENV'] == 'PATH' ? 'bindir' :
- RbConfig::CONFIG['libdirname'] # defined since 2.1
- libruby_so = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
+ # below is defined since 2.1, except for mswin, and maybe other platforms
+ libdirname = RbConfig::CONFIG.fetch 'libdirname', 'libdir'
+ libruby = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY']}"
end
begin
@@ -46,7 +48,8 @@ def compile_extension(name)
when mtime <= File.mtime("#{core_ext_dir}/rubyspec.h")
when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c")
when mtime <= File.mtime(ruby_header)
- when libruby_so && mtime <= File.mtime(libruby_so)
+ when (mtime <= File.mtime(abi_header) rescue nil)
+ when libruby && mtime <= File.mtime(libruby)
else
return lib # up-to-date
end
diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb
index c6ab1ca0fe..c0fbf3d1ba 100644
--- a/spec/ruby/optional/capi/string_spec.rb
+++ b/spec/ruby/optional/capi/string_spec.rb
@@ -97,6 +97,32 @@ describe "C-API String function" do
end
end
+ describe "rb_str_set_len on a UTF-16 String" do
+ before :each do
+ @str = "abcdefghij".force_encoding(Encoding::UTF_16BE)
+ # Make sure to unshare the string
+ @s.rb_str_modify(@str)
+ end
+
+ it "inserts two NULL bytes at the length" do
+ @s.rb_str_set_len(@str, 4).b.should == "abcd".b
+ @s.rb_str_set_len(@str, 8).b.should == "abcd\x00\x00gh".b
+ end
+ end
+
+ describe "rb_str_set_len on a UTF-32 String" do
+ before :each do
+ @str = "abcdefghijkl".force_encoding(Encoding::UTF_32BE)
+ # Make sure to unshare the string
+ @s.rb_str_modify(@str)
+ end
+
+ it "inserts four NULL bytes at the length" do
+ @s.rb_str_set_len(@str, 4).b.should == "abcd".b
+ @s.rb_str_set_len(@str, 12).b.should == "abcd\x00\x00\x00\x00ijkl".b
+ end
+ end
+
describe "rb_str_buf_new" do
it "returns the equivalent of an empty string" do
buf = @s.rb_str_buf_new(10, nil)
@@ -108,7 +134,7 @@ describe "C-API String function" do
it "returns a string with the given capacity" do
buf = @s.rb_str_buf_new(256, nil)
- @s.rb_str_capacity(buf).should == 256
+ @s.rb_str_capacity(buf).should >= 256
end
it "returns a string that can be appended to" do
@@ -181,12 +207,6 @@ describe "C-API String function" do
@s.rb_str_new("hello", 3).should == "hel"
end
- ruby_version_is ''...'2.7' do
- it "returns a non-tainted string" do
- @s.rb_str_new("hello", 5).should_not.tainted?
- end
- end
-
it "returns an empty string if len is 0" do
@s.rb_str_new("hello", 0).should == ""
end
@@ -335,24 +355,6 @@ describe "C-API String function" do
end
end
- ruby_version_is ''...'2.7' do
- describe "rb_tainted_str_new" do
- it "creates a new tainted String" do
- newstring = @s.rb_tainted_str_new("test", 4)
- newstring.should == "test"
- newstring.tainted?.should be_true
- end
- end
-
- describe "rb_tainted_str_new2" do
- it "creates a new tainted String" do
- newstring = @s.rb_tainted_str_new2("test")
- newstring.should == "test"
- newstring.tainted?.should be_true
- end
- end
- end
-
describe "rb_str_append" do
it "appends a string to another string" do
@s.rb_str_append("Hello", " Goodbye").should == "Hello Goodbye"
@@ -378,6 +380,14 @@ describe "C-API String function" do
it_behaves_like :string_times, :rb_str_times, -> str, times { @s.rb_str_times(str, times) }
end
+ describe "rb_str_buf_append" do
+ it "concatenates a string to another string" do
+ str = "Your house "
+ @s.rb_str_buf_append(str, "is on fire?").should.equal?(str)
+ str.should == "Your house is on fire?"
+ end
+ end
+
describe "rb_str_buf_cat" do
it "concatenates a C string to a ruby string" do
@s.rb_str_buf_cat("Your house is on fire").should == "Your house is on fire?"
@@ -603,9 +613,17 @@ describe "C-API String function" do
filename = fixture(__FILE__, "read.txt")
str = ""
capacities = @s.RSTRING_PTR_read(str, filename)
- capacities.should == [30, 53]
+ capacities[0].should >= 30
+ capacities[1].should >= 53
+ capacities[0].should < capacities[1]
str.should == "fixture file contents to test read() with RSTRING_PTR"
end
+
+ it "terminates the string with at least (encoding min length) \\0 bytes" do
+ @s.RSTRING_PTR_null_terminate("abc", 1).should == "\x00"
+ @s.RSTRING_PTR_null_terminate("abc".encode("UTF-16BE"), 2).should == "\x00\x00"
+ @s.RSTRING_PTR_null_terminate("abc".encode("UTF-32BE"), 4).should == "\x00\x00\x00\x00"
+ end
end
describe "RSTRING_LEN" do
@@ -655,22 +673,6 @@ describe "C-API String function" do
end
describe "SafeStringValue" do
- ruby_version_is ''...'2.7' do
- it "raises for tained string when $SAFE is 1" do
- begin
- Thread.new {
- $SAFE = 1
- -> {
- @s.SafeStringValue("str".taint)
- }.should raise_error(SecurityError)
- }.join
- ensure
- $SAFE = 0
- end
- end
-
- it_behaves_like :string_value_macro, :SafeStringValue
- end
end
describe "rb_str_modify" do
@@ -682,27 +684,27 @@ describe "C-API String function" do
describe "rb_str_modify_expand" do
it "grows the capacity to bytesize + expand, not changing the bytesize" do
str = @s.rb_str_buf_new(256, "abcd")
- @s.rb_str_capacity(str).should == 256
+ @s.rb_str_capacity(str).should >= 256
@s.rb_str_set_len(str, 3)
str.bytesize.should == 3
@s.RSTRING_LEN(str).should == 3
- @s.rb_str_capacity(str).should == 256
+ @s.rb_str_capacity(str).should >= 256
@s.rb_str_modify_expand(str, 4)
str.bytesize.should == 3
@s.RSTRING_LEN(str).should == 3
- @s.rb_str_capacity(str).should == 7
+ @s.rb_str_capacity(str).should >= 7
@s.rb_str_modify_expand(str, 1024)
str.bytesize.should == 3
@s.RSTRING_LEN(str).should == 3
- @s.rb_str_capacity(str).should == 1027
+ @s.rb_str_capacity(str).should >= 1027
@s.rb_str_modify_expand(str, 1)
str.bytesize.should == 3
@s.RSTRING_LEN(str).should == 3
- @s.rb_str_capacity(str).should == 4
+ @s.rb_str_capacity(str).should >= 4
end
it "raises an error if the string is frozen" do
@@ -800,12 +802,6 @@ describe :rb_external_str_new, shared: true do
x80 = [0x80].pack('C')
@s.send(@method, "#{x80}abc").encoding.should == Encoding::BINARY
end
-
- ruby_version_is ''...'2.7' do
- it "returns a tainted String" do
- @s.send(@method, "abc").tainted?.should be_true
- end
- end
end
describe "C-API String function" do
@@ -885,13 +881,6 @@ describe "C-API String function" do
s.should == x
s.encoding.should equal(Encoding::EUC_JP)
end
-
- ruby_version_is ''...'2.7' do
- it "returns a tainted String" do
- s = @s.rb_external_str_new_with_enc("abc", 3, Encoding::US_ASCII)
- s.tainted?.should be_true
- end
- end
end
describe "rb_locale_str_new" do
@@ -1051,9 +1040,56 @@ end
@s.rb_sprintf3(true.class).should == s
end
- it "formats a TrueClass VALUE as 'true' if sign specified in format" do
- s = 'Result: true.'
- @s.rb_sprintf4(true.class).should == s
+ ruby_bug "#19167", ""..."3.2" do
+ it "formats a TrueClass VALUE as 'true' if sign specified in format" do
+ s = 'Result: TrueClass.'
+ @s.rb_sprintf4(true.class).should == s
+ end
+ end
+
+ it "truncates a string to a supplied precision if that is shorter than the string" do
+ s = 'Result: Hel.'
+ @s.rb_sprintf5(0, 3, "Hello").should == s
+ end
+
+ it "does not truncates a string to a supplied precision if that is longer than the string" do
+ s = 'Result: Hello.'
+ @s.rb_sprintf5(0, 8, "Hello").should == s
+ end
+
+ it "pads a string to a supplied width if that is longer than the string" do
+ s = 'Result: Hello.'
+ @s.rb_sprintf5(8, 5, "Hello").should == s
+ end
+
+ it "truncates a VALUE string to a supplied precision if that is shorter than the VALUE string" do
+ s = 'Result: Hel.'
+ @s.rb_sprintf6(0, 3, "Hello").should == s
+ end
+
+ it "does not truncates a VALUE string to a supplied precision if that is longer than the VALUE string" do
+ s = 'Result: Hello.'
+ @s.rb_sprintf6(0, 8, "Hello").should == s
+ end
+
+ it "pads a VALUE string to a supplied width if that is longer than the VALUE string" do
+ s = 'Result: Hello.'
+ @s.rb_sprintf6(8, 5, "Hello").should == s
+ end
+
+ it "can format a nil VALUE as a pointer and gives the same output as sprintf in C" do
+ res = @s.rb_sprintf7("%p", nil);
+ res[0].should == res[1]
+ end
+
+ it "can format a string VALUE as a pointer and gives the same output as sprintf in C" do
+ res = @s.rb_sprintf7("%p", "Hello")
+ res[0].should == res[1]
+ end
+
+ it "can format a raw number a pointer and gives the same output as sprintf in C" do
+ res = @s.rb_sprintf7("%p", 0x223643);
+ res[0].should == res[1]
end
end
@@ -1154,4 +1190,104 @@ end
str.should == "test fmt 42 7 number"
end
end
+
+ describe "rb_str_catf" do
+ it "appends the message to the string" do
+ @s.rb_str_catf("").should == "fmt 41 6 number"
+
+ str = "test "
+ @s.rb_str_catf(str)
+ str.should == "test fmt 41 6 number"
+ end
+ end
+
+ describe "rb_str_locktmp" do
+ it "raises an error when trying to lock an already locked string" do
+ str = "test"
+ @s.rb_str_locktmp(str).should == str
+ -> { @s.rb_str_locktmp(str) }.should raise_error(RuntimeError, 'temporal locking already locked string')
+ end
+
+ it "locks a string so that modifications would raise an error" do
+ str = "test"
+ @s.rb_str_locktmp(str).should == str
+ -> { str.upcase! }.should raise_error(RuntimeError, 'can\'t modify string; temporarily locked')
+ end
+ end
+
+ describe "rb_str_unlocktmp" do
+ it "unlocks a locked string" do
+ str = "test"
+ @s.rb_str_locktmp(str)
+ @s.rb_str_unlocktmp(str).should == str
+ str.upcase!.should == "TEST"
+ end
+
+ it "raises an error when trying to unlock an already unlocked string" do
+ -> { @s.rb_str_unlocktmp("test") }.should raise_error(RuntimeError, 'temporal unlocking already unlocked string')
+ end
+ end
+
+ describe "rb_enc_interned_str_cstr" do
+ it "returns a frozen string" do
+ str = "hello"
+ val = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
+
+ val.should.is_a?(String)
+ val.encoding.should == Encoding::US_ASCII
+ val.should.frozen?
+ end
+
+ it "returns the same frozen string" do
+ str = "hello"
+ result1 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
+ result2 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
+ result1.should.equal?(result2)
+ end
+
+ it "returns different frozen strings for different encodings" do
+ str = "hello"
+ result1 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
+ result2 = @s.rb_enc_interned_str_cstr(str, Encoding::UTF_8)
+ result1.should_not.equal?(result2)
+ end
+
+ it "returns the same string as String#-@" do
+ @s.rb_enc_interned_str_cstr("hello", Encoding::UTF_8).should.equal?(-"hello")
+ end
+
+ ruby_bug "#20322", ""..."3.4" do
+ it "uses the default encoding if encoding is null" do
+ str = "hello"
+ val = @s.rb_enc_interned_str_cstr(str, nil)
+ val.encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+ end
+
+ describe "rb_str_to_interned_str" do
+ it "returns a frozen string" do
+ str = "hello"
+ result = @s.rb_str_to_interned_str(str)
+ result.should.is_a?(String)
+ result.should.frozen?
+ end
+
+ it "returns the same frozen string" do
+ str = "hello"
+ result1 = @s.rb_str_to_interned_str(str)
+ result2 = @s.rb_str_to_interned_str(str)
+ result1.should.equal?(result2)
+ end
+
+ it "returns different frozen strings for different encodings" do
+ result1 = @s.rb_str_to_interned_str("hello".force_encoding(Encoding::US_ASCII))
+ result2 = @s.rb_str_to_interned_str("hello".force_encoding(Encoding::UTF_8))
+ result1.should_not.equal?(result2)
+ end
+
+ it "returns the same string as String#-@" do
+ @s.rb_str_to_interned_str("hello").should.equal?(-"hello")
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/symbol_spec.rb b/spec/ruby/optional/capi/symbol_spec.rb
index b8fda34c0e..12c93c9f27 100644
--- a/spec/ruby/optional/capi/symbol_spec.rb
+++ b/spec/ruby/optional/capi/symbol_spec.rb
@@ -61,6 +61,10 @@ describe "C-API Symbol function" do
it "converts a symbol to a C char array" do
@s.rb_id2name(:test_symbol).should == "test_symbol"
end
+
+ it "returns (char*) NULL for (ID) 0" do
+ @s.rb_id2name_id_zero.should == nil
+ end
end
describe "rb_id2str" do
@@ -72,6 +76,10 @@ describe "C-API Symbol function" do
str = "test_symbol".encode(Encoding::UTF_16LE)
@s.rb_id2str(str.to_sym).encoding.should == Encoding::UTF_16LE
end
+
+ it "returns (VALUE) 0 = Qfalse for (ID) 0" do
+ @s.rb_id2str_id_zero.should == false
+ end
end
describe "rb_intern_str" do
diff --git a/spec/ruby/optional/capi/thread_spec.rb b/spec/ruby/optional/capi/thread_spec.rb
index 30e29681eb..5cb46bbb7c 100644
--- a/spec/ruby/optional/capi/thread_spec.rb
+++ b/spec/ruby/optional/capi/thread_spec.rb
@@ -101,6 +101,16 @@ describe "C-API Thread function" do
end
end
+ describe "ruby_native_thread_p" do
+ it "returns non-zero for a ruby thread" do
+ @t.ruby_native_thread_p.should be_true
+ end
+
+ it "returns zero for a non ruby thread" do
+ @t.ruby_native_thread_p_new_thread.should be_false
+ end
+ end
+
describe "rb_thread_call_without_gvl" do
it "runs a C function with the global lock unlocked and can be woken by Thread#wakeup" do
thr = Thread.new do
diff --git a/spec/ruby/optional/capi/util_spec.rb b/spec/ruby/optional/capi/util_spec.rb
index a90c28a78e..38f6f47b1a 100644
--- a/spec/ruby/optional/capi/util_spec.rb
+++ b/spec/ruby/optional/capi/util_spec.rb
@@ -11,13 +11,13 @@ describe "C-API Util function" do
before :each do
@prc = -> { 1 }
@acc = []
- @keyword_prefix = 'k' if RUBY_VERSION >= '2.7'
ScratchPad.record @acc
end
it "assigns the required arguments scanned" do
- @o.rb_scan_args([1, 2], "2", 2, @acc).should == 2
- ScratchPad.recorded.should == [1, 2]
+ obj = Object.new
+ @o.rb_scan_args([obj, 2], "2", 2, @acc).should == 2
+ ScratchPad.recorded.should == [obj, 2]
end
it "raises an ArgumentError if there are insufficient arguments" do
@@ -100,13 +100,13 @@ describe "C-API Util function" do
it "assigns Hash arguments" do
h = {a: 1, b: 2}
- @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc).should == 0
+ @o.rb_scan_args([h], "k0:", 1, @acc).should == 0
ScratchPad.recorded.should == [h]
end
it "assigns required and Hash arguments" do
h = {a: 1, b: 2}
- @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc).should == 1
+ @o.rb_scan_args([1, h], "k1:", 2, @acc).should == 1
ScratchPad.recorded.should == [1, h]
end
@@ -140,7 +140,7 @@ describe "C-API Util function" do
it "assigns required, optional, splat, post-splat, Hash and block arguments" do
h = {a: 1, b: 2}
- @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 5
+ @o.rb_scan_args([1, 2, 3, 4, 5, h], "k11*1:&", 6, @acc, &@prc).should == 5
ScratchPad.recorded.should == [1, 2, [3, 4], 5, h, @prc]
end
@@ -150,7 +150,7 @@ describe "C-API Util function" do
h = {1 => 2, 3 => 4}
-> {
suppress_warning do
- @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc)
+ @o.rb_scan_args([h], "k0:", 1, @acc)
end
}.should raise_error(ArgumentError)
ScratchPad.recorded.should == []
@@ -160,7 +160,7 @@ describe "C-API Util function" 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, h], "k1:", 2, @acc)
end
}.should raise_error(ArgumentError)
ScratchPad.recorded.should == []
@@ -169,7 +169,7 @@ describe "C-API Util function" do
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
+ @o.rb_scan_args([1, 2, 3, 4, 5, h], "k11*1:&", 6, @acc, &@prc).should == 6
end
ScratchPad.recorded.should == [1, 2, [3, 4, 5], h, nil, @prc]
end
@@ -178,19 +178,19 @@ describe "C-API Util function" do
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
+ @o.rb_scan_args([h], "k0:", 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
+ @o.rb_scan_args([1, h], "k1:", 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
+ @o.rb_scan_args([1, 2, 3, 4, 5, h], "k11*1:&", 6, @acc, &@prc).should == 5
ScratchPad.recorded.should == [1, 2, [3, 4], 5, h, @prc]
end
end
diff --git a/spec/ruby/security/cve_2010_1330_spec.rb b/spec/ruby/security/cve_2010_1330_spec.rb
index fa4c756c6d..33e88d652e 100644
--- a/spec/ruby/security/cve_2010_1330_spec.rb
+++ b/spec/ruby/security/cve_2010_1330_spec.rb
@@ -1,7 +1,6 @@
require_relative '../spec_helper'
describe "String#gsub" do
-
it "resists CVE-2010-1330 by raising an exception on invalid UTF-8 bytes" do
# This original vulnerability talked about KCODE, which is no longer
# used. Instead we are forcing encodings here. But I think the idea is the
@@ -17,5 +16,4 @@ describe "String#gsub" do
str.gsub(/</, "&lt;")
}.should raise_error(ArgumentError, /invalid byte sequence in UTF-8/)
end
-
end
diff --git a/spec/ruby/security/cve_2013_4164_spec.rb b/spec/ruby/security/cve_2013_4164_spec.rb
index 94578cc7ce..d223b8fd5e 100644
--- a/spec/ruby/security/cve_2013_4164_spec.rb
+++ b/spec/ruby/security/cve_2013_4164_spec.rb
@@ -3,17 +3,13 @@ require_relative '../spec_helper'
require 'json'
describe "String#to_f" do
-
it "resists CVE-2013-4164 by converting very long Strings to a Float" do
"1.#{'1'*1000000}".to_f.should be_close(1.1111111111111112, TOLERANCE)
end
-
end
describe "JSON.parse" do
-
it "resists CVE-2013-4164 by converting very long Strings to a Float" do
JSON.parse("[1.#{'1'*1000000}]").first.should be_close(1.1111111111111112, TOLERANCE)
end
-
end
diff --git a/spec/ruby/security/cve_2014_8080_spec.rb b/spec/ruby/security/cve_2014_8080_spec.rb
index a3f4483994..23770f94b1 100644
--- a/spec/ruby/security/cve_2014_8080_spec.rb
+++ b/spec/ruby/security/cve_2014_8080_spec.rb
@@ -1,6 +1,5 @@
require_relative '../spec_helper'
-
ruby_version_is ''...'3.0' do
require 'rexml/document'
diff --git a/spec/ruby/security/cve_2018_16396_spec.rb b/spec/ruby/security/cve_2018_16396_spec.rb
index 303c47a8c7..6f8a5d2f5d 100644
--- a/spec/ruby/security/cve_2018_16396_spec.rb
+++ b/spec/ruby/security/cve_2018_16396_spec.rb
@@ -1,25 +1,7 @@
require_relative '../spec_helper'
describe "Array#pack" do
-
- ruby_version_is ''...'2.7' do
- it "resists CVE-2018-16396 by tainting output based on input" do
- "aAZBbHhuMmPp".each_char do |f|
- ["123456".taint].pack(f).tainted?.should be_true
- end
- end
- end
-
end
describe "String#unpack" do
-
- ruby_version_is ''...'2.7' do
- it "resists CVE-2018-16396 by tainting output based on input" do
- "aAZBbHhuMm".each_char do |f|
- "123456".taint.unpack(f).first.tainted?.should be_true
- end
- end
- end
-
end
diff --git a/spec/ruby/security/cve_2018_8778_spec.rb b/spec/ruby/security/cve_2018_8778_spec.rb
index 628159a4db..62057faa53 100644
--- a/spec/ruby/security/cve_2018_8778_spec.rb
+++ b/spec/ruby/security/cve_2018_8778_spec.rb
@@ -1,12 +1,10 @@
require_relative '../spec_helper'
describe "String#unpack" do
-
it "resists CVE-2018-8778 by raising an exception when a position indicator is larger than a native integer" do
pos = (1 << PlatformGuard::POINTER_SIZE) - 99
-> {
"0123456789".unpack("@#{pos}C10")
}.should raise_error(RangeError, /pack length too big/)
end
-
end
diff --git a/spec/ruby/security/cve_2019_8325_spec.rb b/spec/ruby/security/cve_2019_8325_spec.rb
index 935f127d7f..bbddb3a6ce 100644
--- a/spec/ruby/security/cve_2019_8325_spec.rb
+++ b/spec/ruby/security/cve_2019_8325_spec.rb
@@ -3,36 +3,44 @@ require_relative '../spec_helper'
require 'rubygems'
require 'rubygems/command_manager'
-platform_is_not :darwin do # frequent timeout/hang on macOS
- describe "CVE-2019-8325 is resisted by" do
- describe "sanitising error message components" do
- it "for the 'while executing' message" do
- manager = Gem::CommandManager.new
- def manager.process_args(args, build_args)
- raise StandardError, "\e]2;nyan\a"
- end
- def manager.terminate_interaction(n)
- end
- manager.should_receive(:alert_error).with("While executing gem ... (StandardError)\n .]2;nyan.")
- manager.run nil, nil
+describe "CVE-2019-8325 is resisted by" do
+ describe "sanitising error message components" do
+ before :each do
+ @ui = Gem::SilentUI.new
+ end
+
+ after :each do
+ @ui.close
+ end
+
+ it "for the 'while executing' message" do
+ manager = Gem::CommandManager.new
+ manager.ui = @ui
+ def manager.process_args(args, build_args)
+ raise StandardError, "\e]2;nyan\a"
end
+ def manager.terminate_interaction(n)
+ end
+ manager.should_receive(:alert_error).with("While executing gem ... (StandardError)\n .]2;nyan.")
+ manager.run nil, nil
+ end
- it "for the 'invalid option' message" do
- manager = Gem::CommandManager.new
- def manager.terminate_interaction(n)
- end
- manager.should_receive(:alert_error).with("Invalid option: --.]2;nyan.. See 'gem --help'.")
- manager.process_args ["--\e]2;nyan\a"], nil
+ it "for the 'invalid option' message" do
+ manager = Gem::CommandManager.new
+ def manager.terminate_interaction(n)
end
+ manager.should_receive(:alert_error).with("Invalid option: --.]2;nyan.. See 'gem --help'.")
+ manager.process_args ["--\e]2;nyan\a"], nil
+ end
- it "for the 'loading command' message" do
- manager = Gem::CommandManager.new
- def manager.require(x)
- raise 'foo'
- end
- manager.should_receive(:alert_error).with("Loading command: .]2;nyan. (RuntimeError)\n\tfoo")
- manager.send :load_and_instantiate, "\e]2;nyan\a"
+ it "for the 'loading command' message" do
+ manager = Gem::CommandManager.new
+ manager.ui = @ui
+ def manager.require(x)
+ raise 'foo'
end
+ manager.should_receive(:alert_error).with("Loading command: .]2;nyan. (RuntimeError)\n\tfoo")
+ manager.send :load_and_instantiate, "\e]2;nyan\a"
end
end
end
diff --git a/spec/ruby/security/cve_2020_10663_spec.rb b/spec/ruby/security/cve_2020_10663_spec.rb
index 766590d501..cce1beb012 100644
--- a/spec/ruby/security/cve_2020_10663_spec.rb
+++ b/spec/ruby/security/cve_2020_10663_spec.rb
@@ -18,25 +18,22 @@ module JSONSpecs
end
guard -> {
- ruby_version_is "2.6.6" or
JSON.const_defined?(:Pure) or
version_is(JSON::VERSION, '2.3.0')
} do
- platform_is_not :darwin do # frequent timeout/hang on macOS
- describe "CVE-2020-10663 is resisted by" do
- it "only creating custom objects if passed create_additions: true or using JSON.load" do
- obj = JSONSpecs::MyClass.new("bar")
- JSONSpecs::MyClass.should.json_creatable?
- json = JSON.dump(obj)
+ describe "CVE-2020-10663 is resisted by" do
+ it "only creating custom objects if passed create_additions: true or using JSON.load" do
+ obj = JSONSpecs::MyClass.new("bar")
+ JSONSpecs::MyClass.should.json_creatable?
+ json = JSON.dump(obj)
- JSON.parse(json, create_additions: true).class.should == JSONSpecs::MyClass
- JSON(json, create_additions: true).class.should == JSONSpecs::MyClass
- JSON.load(json).class.should == JSONSpecs::MyClass
+ JSON.parse(json, create_additions: true).class.should == JSONSpecs::MyClass
+ JSON(json, create_additions: true).class.should == JSONSpecs::MyClass
+ 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
+ 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/file/executable.rb b/spec/ruby/shared/file/executable.rb
index 7b5c4c580c..baa156de98 100644
--- a/spec/ruby/shared/file/executable.rb
+++ b/spec/ruby/shared/file/executable.rb
@@ -39,6 +39,41 @@ describe :file_executable, shared: true do
-> { @object.send(@method, nil) }.should raise_error(TypeError)
-> { @object.send(@method, false) }.should raise_error(TypeError)
end
+
+ platform_is_not :windows do
+ as_superuser do
+ context "when run by a superuser" do
+ before :each do
+ @file = tmp('temp3.txt')
+ touch @file
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns true if file owner has permission to execute" do
+ File.chmod(0766, @file)
+ @object.send(@method, @file).should == true
+ end
+
+ it "returns true if group has permission to execute" do
+ File.chmod(0676, @file)
+ @object.send(@method, @file).should == true
+ end
+
+ it "returns true if other have permission to execute" do
+ File.chmod(0667, @file)
+ @object.send(@method, @file).should == true
+ end
+
+ it "return false if nobody has permission to execute" do
+ File.chmod(0666, @file)
+ @object.send(@method, @file).should == false
+ end
+ end
+ end
+ end
end
describe :file_executable_missing, shared: true do
diff --git a/spec/ruby/shared/file/executable_real.rb b/spec/ruby/shared/file/executable_real.rb
index ce3d5ca176..bf2734ea07 100644
--- a/spec/ruby/shared/file/executable_real.rb
+++ b/spec/ruby/shared/file/executable_real.rb
@@ -37,6 +37,41 @@ describe :file_executable_real, shared: true do
-> { @object.send(@method, nil) }.should raise_error(TypeError)
-> { @object.send(@method, false) }.should raise_error(TypeError)
end
+
+ platform_is_not :windows do
+ as_real_superuser do
+ context "when run by a real superuser" do
+ before :each do
+ @file = tmp('temp3.txt')
+ touch @file
+ end
+
+ after :each do
+ rm_r @file
+ end
+
+ it "returns true if file owner has permission to execute" do
+ File.chmod(0766, @file)
+ @object.send(@method, @file).should == true
+ end
+
+ it "returns true if group has permission to execute" do
+ File.chmod(0676, @file)
+ @object.send(@method, @file).should == true
+ end
+
+ it "returns true if other have permission to execute" do
+ File.chmod(0667, @file)
+ @object.send(@method, @file).should == true
+ end
+
+ it "return false if nobody has permission to execute" do
+ File.chmod(0666, @file)
+ @object.send(@method, @file).should == false
+ end
+ end
+ end
+ end
end
describe :file_executable_real_missing, shared: true do
diff --git a/spec/ruby/shared/file/readable.rb b/spec/ruby/shared/file/readable.rb
index eb2ca06812..7b45e23e36 100644
--- a/spec/ruby/shared/file/readable.rb
+++ b/spec/ruby/shared/file/readable.rb
@@ -24,6 +24,22 @@ describe :file_readable, shared: true do
it "accepts an object that has a #to_path method" do
@object.send(@method, mock_to_path(@file2)).should == true
end
+
+ platform_is_not :windows do
+ as_superuser do
+ context "when run by a superuser" do
+ it "returns true unconditionally" do
+ file = tmp('temp.txt')
+ touch file
+
+ File.chmod(0333, file)
+ @object.send(@method, file).should == true
+
+ rm_r file
+ end
+ end
+ end
+ end
end
describe :file_readable_missing, shared: true do
diff --git a/spec/ruby/shared/file/readable_real.rb b/spec/ruby/shared/file/readable_real.rb
index b6e53ac76d..32d38bc7a2 100644
--- a/spec/ruby/shared/file/readable_real.rb
+++ b/spec/ruby/shared/file/readable_real.rb
@@ -14,6 +14,22 @@ describe :file_readable_real, shared: true do
it "accepts an object that has a #to_path method" do
File.open(@file,'w') { @object.send(@method, mock_to_path(@file)).should == true }
end
+
+ platform_is_not :windows do
+ as_real_superuser do
+ context "when run by a real superuser" do
+ it "returns true unconditionally" do
+ file = tmp('temp.txt')
+ touch file
+
+ File.chmod(0333, file)
+ @object.send(@method, file).should == true
+
+ rm_r file
+ end
+ end
+ end
+ end
end
describe :file_readable_real_missing, shared: true do
diff --git a/spec/ruby/shared/file/writable.rb b/spec/ruby/shared/file/writable.rb
index 4bb8aedce6..65ea2c1781 100644
--- a/spec/ruby/shared/file/writable.rb
+++ b/spec/ruby/shared/file/writable.rb
@@ -19,6 +19,22 @@ describe :file_writable, shared: true do
it "accepts an object that has a #to_path method" do
File.open(@file,'w') { @object.send(@method, mock_to_path(@file)).should == true }
end
+
+ platform_is_not :windows do
+ as_superuser do
+ context "when run by a superuser" do
+ it "returns true unconditionally" do
+ file = tmp('temp.txt')
+ touch file
+
+ File.chmod(0555, file)
+ @object.send(@method, file).should == true
+
+ rm_r file
+ end
+ end
+ end
+ end
end
describe :file_writable_missing, shared: true do
diff --git a/spec/ruby/shared/file/writable_real.rb b/spec/ruby/shared/file/writable_real.rb
index e9721fd379..b4a0a58c6e 100644
--- a/spec/ruby/shared/file/writable_real.rb
+++ b/spec/ruby/shared/file/writable_real.rb
@@ -24,6 +24,22 @@ describe :file_writable_real, shared: true do
-> { @object.send(@method, nil) }.should raise_error(TypeError)
-> { @object.send(@method, false) }.should raise_error(TypeError)
end
+
+ platform_is_not :windows do
+ as_real_superuser do
+ context "when run by a real superuser" do
+ it "returns true unconditionally" do
+ file = tmp('temp.txt')
+ touch file
+
+ File.chmod(0555, file)
+ @object.send(@method, file).should == true
+
+ rm_r file
+ end
+ end
+ end
+ end
end
describe :file_writable_real_missing, shared: true do
diff --git a/spec/ruby/shared/kernel/complex.rb b/spec/ruby/shared/kernel/complex.rb
new file mode 100644
index 0000000000..98ee0b2b3f
--- /dev/null
+++ b/spec/ruby/shared/kernel/complex.rb
@@ -0,0 +1,133 @@
+# Specs shared by Kernel#Complex() and String#to_c()
+describe :kernel_complex, shared: true do
+
+ it "returns a Complex object" do
+ @object.send(@method, '9').should be_an_instance_of(Complex)
+ end
+
+ it "understands integers" do
+ @object.send(@method, '20').should == Complex(20)
+ end
+
+ it "understands negative integers" do
+ @object.send(@method, '-3').should == Complex(-3)
+ end
+
+ it "understands fractions (numerator/denominator) for the real part" do
+ @object.send(@method, '2/3').should == Complex(Rational(2, 3))
+ end
+
+ it "understands fractions (numerator/denominator) for the imaginary part" do
+ @object.send(@method, '4+2/3i').should == Complex(4, Rational(2, 3))
+ end
+
+ it "understands negative fractions (-numerator/denominator) for the real part" do
+ @object.send(@method, '-2/3').should == Complex(Rational(-2, 3))
+ end
+
+ it "understands negative fractions (-numerator/denominator) for the imaginary part" do
+ @object.send(@method, '7-2/3i').should == Complex(7, Rational(-2, 3))
+ end
+
+ it "understands floats (a.b) for the real part" do
+ @object.send(@method, '2.3').should == Complex(2.3)
+ end
+
+ it "understands floats (a.b) for the imaginary part" do
+ @object.send(@method, '4+2.3i').should == Complex(4, 2.3)
+ end
+
+ it "understands negative floats (-a.b) for the real part" do
+ @object.send(@method, '-2.33').should == Complex(-2.33)
+ end
+
+ it "understands negative floats (-a.b) for the imaginary part" do
+ @object.send(@method, '7-28.771i').should == Complex(7, -28.771)
+ end
+
+ it "understands an integer followed by 'i' to mean that integer is the imaginary part" do
+ @object.send(@method, '35i').should == Complex(0,35)
+ end
+
+ it "understands a negative integer followed by 'i' to mean that negative integer is the imaginary part" do
+ @object.send(@method, '-29i').should == Complex(0,-29)
+ end
+
+ it "understands an 'i' by itself as denoting a complex number with an imaginary part of 1" do
+ @object.send(@method, 'i').should == Complex(0,1)
+ end
+
+ it "understands a '-i' by itself as denoting a complex number with an imaginary part of -1" do
+ @object.send(@method, '-i').should == Complex(0,-1)
+ end
+
+ it "understands 'a+bi' to mean a complex number with 'a' as the real part, 'b' as the imaginary" do
+ @object.send(@method, '79+4i').should == Complex(79,4)
+ end
+
+ it "understands 'a-bi' to mean a complex number with 'a' as the real part, '-b' as the imaginary" do
+ @object.send(@method, '79-4i').should == Complex(79,-4)
+ end
+
+ it "understands 'a+i' to mean a complex number with 'a' as the real part, 1i as the imaginary" do
+ @object.send(@method, '79+i').should == Complex(79, 1)
+ end
+
+ it "understands 'a-i' to mean a complex number with 'a' as the real part, -1i as the imaginary" do
+ @object.send(@method, '79-i').should == Complex(79, -1)
+ end
+
+ it "understands i, I, j, and J imaginary units" do
+ @object.send(@method, '79+4i').should == Complex(79, 4)
+ @object.send(@method, '79+4I').should == Complex(79, 4)
+ @object.send(@method, '79+4j').should == Complex(79, 4)
+ @object.send(@method, '79+4J').should == Complex(79, 4)
+ end
+
+ it "understands scientific notation for the real part" do
+ @object.send(@method, '2e3+4i').should == Complex(2e3,4)
+ end
+
+ it "understands negative scientific notation for the real part" do
+ @object.send(@method, '-2e3+4i').should == Complex(-2e3,4)
+ end
+
+ it "understands scientific notation for the imaginary part" do
+ @object.send(@method, '4+2e3i').should == Complex(4, 2e3)
+ end
+
+ it "understands negative scientific notation for the imaginary part" do
+ @object.send(@method, '4-2e3i').should == Complex(4, -2e3)
+ end
+
+ it "understands scientific notation for the real and imaginary part in the same String" do
+ @object.send(@method, '2e3+2e4i').should == Complex(2e3,2e4)
+ end
+
+ it "understands negative scientific notation for the real and imaginary part in the same String" do
+ @object.send(@method, '-2e3-2e4i').should == Complex(-2e3,-2e4)
+ end
+
+ it "understands scientific notation with e and E" do
+ @object.send(@method, '2e3+2e4i').should == Complex(2e3, 2e4)
+ @object.send(@method, '2E3+2E4i').should == Complex(2e3, 2e4)
+ end
+
+ it "understands 'm@a' to mean a complex number in polar form with 'm' as the modulus, 'a' as the argument" do
+ @object.send(@method, '79@4').should == Complex.polar(79, 4)
+ @object.send(@method, '-79@4').should == Complex.polar(-79, 4)
+ @object.send(@method, '79@-4').should == Complex.polar(79, -4)
+ end
+
+ it "ignores leading whitespaces" do
+ @object.send(@method, ' 79+4i').should == Complex(79, 4)
+ end
+
+ it "ignores trailing whitespaces" do
+ @object.send(@method, '79+4i ').should == Complex(79, 4)
+ end
+
+ it "understands _" do
+ @object.send(@method, '7_9+4_0i').should == Complex(79, 40)
+ end
+end
diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb
index 765ba0f929..82fb0333c8 100644
--- a/spec/ruby/shared/kernel/raise.rb
+++ b/spec/ruby/shared/kernel/raise.rb
@@ -29,11 +29,41 @@ describe :kernel_raise, shared: true do
@data = data
end
end
- -> { @object.raise(data_error, {:data => 42}) }.should raise_error(data_error) do |ex|
- ex.data.should == {:data => 42}
+
+ -> { @object.raise(data_error, {data: 42}) }.should raise_error(data_error) do |ex|
+ ex.data.should == {data: 42}
+ end
+ end
+
+ # https://bugs.ruby-lang.org/issues/8257#note-36
+ it "allows extra keyword arguments for compatibility" do
+ data_error = Class.new(StandardError) do
+ attr_reader :data
+ def initialize(data)
+ @data = data
+ end
+ end
+
+ -> { @object.raise(data_error, data: 42) }.should raise_error(data_error) do |ex|
+ ex.data.should == {data: 42}
end
end
+ it "does not allow message and extra keyword arguments" do
+ data_error = Class.new(StandardError) do
+ attr_reader :data
+ def initialize(data)
+ @data = data
+ end
+ end
+
+ -> { @object.raise(data_error, {a: 1}, b: 2) }.should raise_error(StandardError) do |e|
+ [TypeError, ArgumentError].should.include?(e.class)
+ end
+
+ -> { @object.raise(data_error, {a: 1}, [], b: 2) }.should raise_error(ArgumentError)
+ end
+
it "raises RuntimeError if no exception class is given" do
-> { @object.raise }.should raise_error(RuntimeError, "")
end
diff --git a/spec/ruby/shared/process/exit.rb b/spec/ruby/shared/process/exit.rb
index ae8abaea40..7d901f1f1e 100644
--- a/spec/ruby/shared/process/exit.rb
+++ b/spec/ruby/shared/process/exit.rb
@@ -21,6 +21,12 @@ describe :process_exit, shared: true do
end
end
+ it "raises a SystemExit with message 'exit'" do
+ -> { @object.exit }.should raise_error(SystemExit) { |e|
+ e.message.should == "exit"
+ }
+ end
+
it "tries to convert the passed argument to an Integer using #to_int" do
obj = mock('5')
obj.should_receive(:to_int).and_return(5)
diff --git a/spec/ruby/shared/queue/deque.rb b/spec/ruby/shared/queue/deque.rb
index 8b755dd9b7..616e56ec8a 100644
--- a/spec/ruby/shared/queue/deque.rb
+++ b/spec/ruby/shared/queue/deque.rb
@@ -55,6 +55,68 @@ describe :queue_deq, shared: true do
t.join
end
+ describe "with a timeout" do
+ ruby_version_is "3.2" do
+ it "returns an item if one is available in time" do
+ q = @object.call
+
+ t = Thread.new {
+ q.send(@method, timeout: 1).should == 1
+ }
+ Thread.pass until t.status == "sleep" && q.num_waiting == 1
+ q << 1
+ t.join
+ end
+
+ it "returns nil if no item is available in time" do
+ q = @object.call
+
+ t = Thread.new {
+ q.send(@method, timeout: 0.1).should == nil
+ }
+ t.join
+ end
+
+ it "does nothing if the timeout is nil" do
+ q = @object.call
+ t = Thread.new {
+ q.send(@method, timeout: nil).should == 1
+ }
+ t.join(0.2).should == nil
+ q << 1
+ t.join
+ end
+
+ it "immediately returns nil if no item is available and the timeout is 0" do
+ q = @object.call
+ q << 1
+ q.send(@method, timeout: 0).should == 1
+ q.send(@method, timeout: 0).should == nil
+ end
+
+ it "raise TypeError if timeout is not a valid numeric" do
+ q = @object.call
+ -> { q.send(@method, timeout: "1") }.should raise_error(
+ TypeError,
+ "no implicit conversion to float from string",
+ )
+
+ -> { q.send(@method, timeout: false) }.should raise_error(
+ TypeError,
+ "no implicit conversion to float from false",
+ )
+ end
+
+ it "raise ArgumentError if non_block = true is passed too" do
+ q = @object.call
+ -> { q.send(@method, true, timeout: 1) }.should raise_error(
+ ArgumentError,
+ "can't set a timeout if non_block is enabled",
+ )
+ end
+ end
+ end
+
describe "in non-blocking mode" do
it "removes an item from the queue" do
q = @object.call
diff --git a/spec/ruby/shared/rational/Rational.rb b/spec/ruby/shared/rational/Rational.rb
index 936a90c086..2dc49c869c 100644
--- a/spec/ruby/shared/rational/Rational.rb
+++ b/spec/ruby/shared/rational/Rational.rb
@@ -65,40 +65,40 @@ describe :kernel_Rational, shared: true do
r_s.should == r
r_s.should_not == f_r
end
+ end
- describe "when passed a Numeric" do
- it "calls #to_r to convert the first argument to a Rational" do
- num = RationalSpecs::SubNumeric.new(2)
+ describe "when passed a Numeric" do
+ it "calls #to_r to convert the first argument to a Rational" do
+ num = RationalSpecs::SubNumeric.new(2)
- Rational(num).should == Rational(2)
- end
+ Rational(num).should == Rational(2)
end
+ end
- describe "when passed a Complex" do
- it "returns a Rational from the real part if the imaginary part is 0" do
- Rational(Complex(1, 0)).should == Rational(1)
- end
-
- it "raises a RangeError if the imaginary part is not 0" do
- -> { Rational(Complex(1, 2)) }.should raise_error(RangeError)
- end
+ describe "when passed a Complex" do
+ it "returns a Rational from the real part if the imaginary part is 0" do
+ Rational(Complex(1, 0)).should == Rational(1)
end
- it "raises a TypeError if the first argument is nil" do
- -> { Rational(nil) }.should raise_error(TypeError)
+ it "raises a RangeError if the imaginary part is not 0" do
+ -> { Rational(Complex(1, 2)) }.should raise_error(RangeError)
end
+ end
- it "raises a TypeError if the second argument is nil" do
- -> { Rational(1, nil) }.should raise_error(TypeError)
- end
+ it "raises a TypeError if the first argument is nil" do
+ -> { Rational(nil) }.should raise_error(TypeError)
+ end
- it "raises a TypeError if the first argument is a Symbol" do
- -> { Rational(:sym) }.should raise_error(TypeError)
- end
+ it "raises a TypeError if the second argument is nil" do
+ -> { Rational(1, nil) }.should raise_error(TypeError)
+ end
- it "raises a TypeError if the second argument is a Symbol" do
- -> { Rational(1, :sym) }.should raise_error(TypeError)
- end
+ it "raises a TypeError if the first argument is a Symbol" do
+ -> { Rational(:sym) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if the second argument is a Symbol" do
+ -> { Rational(1, :sym) }.should raise_error(TypeError)
end
describe "when passed exception: false" do
diff --git a/spec/ruby/shared/rational/divmod.rb b/spec/ruby/shared/rational/divmod.rb
index 5b319a95ff..9e23a18186 100644
--- a/spec/ruby/shared/rational/divmod.rb
+++ b/spec/ruby/shared/rational/divmod.rb
@@ -6,10 +6,10 @@ describe :rational_divmod_rat, shared: true do
Rational(7, 4).divmod(Rational(-1, 2)).should eql([-4, Rational(-1, 4)])
Rational(0, 4).divmod(Rational(4, 3)).should eql([0, Rational(0, 1)])
- Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([1729382256910270464, Rational(0, 1)])
+ Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([3458764513820540928, Rational(0, 1)])
end
- it "raises a ZeroDivisonError when passed a Rational with a numerator of 0" do
+ it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do
-> { Rational(7, 4).divmod(Rational(0, 3)) }.should raise_error(ZeroDivisionError)
end
end
@@ -19,7 +19,7 @@ describe :rational_divmod_int, shared: true do
Rational(7, 4).divmod(2).should eql([0, Rational(7, 4)])
Rational(7, 4).divmod(-2).should eql([-1, Rational(-1, 4)])
- Rational(bignum_value, 4).divmod(3).should == [768614336404564650, Rational(2, 1)]
+ Rational(bignum_value, 4).divmod(3).should eql([1537228672809129301, Rational(1, 1)])
end
it "raises a ZeroDivisionError when passed 0" do
diff --git a/spec/ruby/shared/rational/exponent.rb b/spec/ruby/shared/rational/exponent.rb
index 3fd02de08f..b0e9b23574 100644
--- a/spec/ruby/shared/rational/exponent.rb
+++ b/spec/ruby/shared/rational/exponent.rb
@@ -40,10 +40,10 @@ describe :rational_exponent, shared: true do
(Rational(-3, 4) ** -4).should == Rational(256, 81)
(Rational(3, -4) ** -4).should == Rational(256, 81)
- (Rational(bignum_value, 4) ** 4).should == Rational(28269553036454149273332760011886696253239742350009903329945699220681916416, 1)
- (Rational(3, bignum_value) ** -4).should == Rational(7237005577332262213973186563042994240829374041602535252466099000494570602496, 81)
- (Rational(-bignum_value, 4) ** -4).should == Rational(1, 28269553036454149273332760011886696253239742350009903329945699220681916416)
- (Rational(3, -bignum_value) ** -4).should == Rational(7237005577332262213973186563042994240829374041602535252466099000494570602496, 81)
+ (Rational(bignum_value, 4) ** 4).should == Rational(452312848583266388373324160190187140051835877600158453279131187530910662656, 1)
+ (Rational(3, bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
+ (Rational(-bignum_value, 4) ** -4).should == Rational(1, 452312848583266388373324160190187140051835877600158453279131187530910662656)
+ (Rational(3, -bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
end
# Guard against the Mathn library
diff --git a/spec/ruby/shared/rational/minus.rb b/spec/ruby/shared/rational/minus.rb
deleted file mode 100644
index 0a0946fdb9..0000000000
--- a/spec/ruby/shared/rational/minus.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_minus_rat, shared: true do
- it "returns the result of subtracting other from self as a Rational" do
- (Rational(3, 4) - Rational(0, 1)).should eql(Rational(3, 4))
- (Rational(3, 4) - Rational(1, 4)).should eql(Rational(1, 2))
-
- (Rational(3, 4) - Rational(2, 1)).should eql(Rational(-5, 4))
- end
-end
-
-describe :rational_minus_int, shared: true do
- it "returns the result of subtracting other from self as a Rational" do
- (Rational(3, 4) - 1).should eql(Rational(-1, 4))
- (Rational(3, 4) - 2).should eql(Rational(-5, 4))
- end
-end
-
-describe :rational_minus_float, shared: true do
- it "returns the result of subtracting other from self as a Float" do
- (Rational(3, 4) - 0.2).should eql(0.55)
- (Rational(3, 4) - 2.5).should eql(-1.75)
- end
-end
-
-describe :rational_minus, shared: true do
- it "calls #coerce on the passed argument with self" do
- rational = Rational(3, 4)
- obj = mock("Object")
- obj.should_receive(:coerce).with(rational).and_return([1, 2])
-
- rational - obj
- end
-
- it "calls #- on the coerced Rational with the coerced Object" do
- rational = Rational(3, 4)
-
- coerced_rational = mock("Coerced Rational")
- coerced_rational.should_receive(:-).and_return(:result)
-
- coerced_obj = mock("Coerced Object")
-
- obj = mock("Object")
- obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
-
- (rational - obj).should == :result
- end
-end
diff --git a/spec/ruby/shared/rational/to_f.rb b/spec/ruby/shared/rational/to_f.rb
index 56e0b61d68..472a585daa 100644
--- a/spec/ruby/shared/rational/to_f.rb
+++ b/spec/ruby/shared/rational/to_f.rb
@@ -7,4 +7,10 @@ describe :rational_to_f, shared: true do
Rational(-1, 4).to_f.should eql(-0.25)
Rational(-1, -4).to_f.should eql(0.25)
end
+
+ it "converts to a Float for large numerator and denominator" do
+ num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009
+ den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ Rational(num, den).to_f.should == 500.0
+ end
end
diff --git a/spec/ruby/shared/sizedqueue/enque.rb b/spec/ruby/shared/sizedqueue/enque.rb
index 6ef12349f8..059f1025a7 100644
--- a/spec/ruby/shared/sizedqueue/enque.rb
+++ b/spec/ruby/shared/sizedqueue/enque.rb
@@ -47,4 +47,67 @@ describe :sizedqueue_enq, shared: true do
t.join
q.pop.should == 1
end
+
+ describe "with a timeout" do
+ ruby_version_is "3.2" do
+ it "returns self if the item was pushed in time" do
+ q = @object.call(1)
+ q << 1
+
+ t = Thread.new {
+ q.send(@method, 2, timeout: 1).should == q
+ }
+ Thread.pass until t.status == "sleep" && q.num_waiting == 1
+ q.pop
+ t.join
+ end
+
+ it "does nothing if the timeout is nil" do
+ q = @object.call(1)
+ q << 1
+ t = Thread.new {
+ q.send(@method, 2, timeout: nil).should == q
+ }
+ t.join(0.2).should == nil
+ q.pop
+ t.join
+ end
+
+ it "returns nil if no space is avialable and timeout is 0" do
+ q = @object.call(1)
+ q.send(@method, 1, timeout: 0).should == q
+ q.send(@method, 2, timeout: 0).should == nil
+ end
+
+ it "returns nil if no space is available in time" do
+ q = @object.call(1)
+ q << 1
+ t = Thread.new {
+ q.send(@method, 2, timeout: 0.1).should == nil
+ }
+ t.join
+ end
+
+ it "raise TypeError if timeout is not a valid numeric" do
+ q = @object.call(1)
+ -> { q.send(@method, 2, timeout: "1") }.should raise_error(
+ TypeError,
+ "no implicit conversion to float from string",
+ )
+
+ -> { q.send(@method, 2, timeout: false) }.should raise_error(
+ TypeError,
+ "no implicit conversion to float from false",
+ )
+ end
+
+ it "raise ArgumentError if non_block = true is passed too" do
+ q = @object.call(1)
+ -> { q.send(@method, 2, true, timeout: 1) }.should raise_error(
+ ArgumentError,
+ "can't set a timeout if non_block is enabled",
+ )
+ end
+ end
+ end
end
diff --git a/spec/ruby/shared/sizedqueue/new.rb b/spec/ruby/shared/sizedqueue/new.rb
index 713785fb50..2573194efb 100644
--- a/spec/ruby/shared/sizedqueue/new.rb
+++ b/spec/ruby/shared/sizedqueue/new.rb
@@ -1,7 +1,12 @@
describe :sizedqueue_new, shared: true do
- it "raises a TypeError when the given argument is not Numeric" do
- -> { @object.call("foo") }.should raise_error(TypeError)
+ it "raises a TypeError when the given argument doesn't respond to #to_int" do
+ -> { @object.call("12") }.should raise_error(TypeError)
-> { @object.call(Object.new) }.should raise_error(TypeError)
+
+ @object.call(12.9).max.should == 12
+ object = Object.new
+ object.define_singleton_method(:to_int) { 42 }
+ @object.call(object).max.should == 42
end
it "raises an argument error when no argument is given" do
diff --git a/spec/ruby/shared/string/end_with.rb b/spec/ruby/shared/string/end_with.rb
index 5f2a011235..0e4c1386e8 100644
--- a/spec/ruby/shared/string/end_with.rb
+++ b/spec/ruby/shared/string/end_with.rb
@@ -38,7 +38,7 @@ describe :end_with, shared: true do
it "uses only the needed arguments" do
find = mock('h')
find.should_not_receive(:to_str)
- "hello".send(@method).should.end_with?("o",find)
+ "hello".send(@method).should.end_with?("o", find)
end
it "works for multibyte strings" do
@@ -51,4 +51,11 @@ describe :end_with, shared: true do
"あれ".send(@method).end_with?(pat)
end.should raise_error(Encoding::CompatibilityError)
end
+
+ it "checks that we are starting to match at the head of a character" do
+ "\xC3\xA9".send(@method).should_not.end_with?("\xA9")
+ "\xe3\x81\x82".send(@method).should_not.end_with?("\x82")
+ "ab".force_encoding("UTF-16BE").send(@method).should_not.end_with?(
+ "b".force_encoding("UTF-16BE"))
+ end
end
diff --git a/spec/ruby/shared/string/start_with.rb b/spec/ruby/shared/string/start_with.rb
index d8d6e13f6a..6932a017b6 100644
--- a/spec/ruby/shared/string/start_with.rb
+++ b/spec/ruby/shared/string/start_with.rb
@@ -69,4 +69,8 @@ describe :start_with, shared: true do
Regexp.last_match.should be_nil
$1.should be_nil
end
+
+ it "does not check that we are not matching part of a character" do
+ "\xC3\xA9".send(@method).should.start_with?("\xC3")
+ end
end
diff --git a/spec/ruby/shared/string/times.rb b/spec/ruby/shared/string/times.rb
index cd4edf5340..8ca9507570 100644
--- a/spec/ruby/shared/string/times.rb
+++ b/spec/ruby/shared/string/times.rb
@@ -48,18 +48,6 @@ describe :string_times, shared: true do
end
end
- ruby_version_is ''...'2.7' do
- it "always taints the result when self is tainted" do
- ["", "OK", MyString.new(""), MyString.new("OK")].each do |str|
- str.taint
-
- [0, 1, 2].each do |arg|
- @object.call(str, arg).should.tainted?
- end
- end
- end
- end
-
it "returns a String in the same encoding as self" do
str = "\xE3\x81\x82".force_encoding Encoding::UTF_8
result = @object.call(str, 2)
diff --git a/spec/ruby/spec_helper.rb b/spec/ruby/spec_helper.rb
index c38965d3c5..3404521c03 100644
--- a/spec/ruby/spec_helper.rb
+++ b/spec/ruby/spec_helper.rb
@@ -14,8 +14,7 @@ else
end
end
-# Running directly with ruby some_spec.rb
-unless ENV['MSPEC_RUNNER']
+unless ENV['MSPEC_RUNNER'] # Running directly with ruby some_spec.rb
mspec_lib = File.expand_path("../../mspec/lib", __FILE__)
$LOAD_PATH << mspec_lib if File.directory?(mspec_lib)
@@ -26,7 +25,14 @@ unless ENV['MSPEC_RUNNER']
puts "Please add -Ipath/to/mspec/lib or clone mspec as a sibling to run the specs."
exit 1
end
+end
+
+# Compare with SpecVersion directly here so it works even with --unguarded
+if VersionGuard::FULL_RUBY_VERSION < SpecVersion.new('2.7')
+ abort "This version of ruby/spec requires Ruby 2.7+"
+end
+unless ENV['MSPEC_RUNNER'] # Running directly with ruby some_spec.rb
ARGV.unshift $0
MSpecRun.main
end
diff --git a/spec/syntax_suggest/fixtures/derailed_require_tree.rb.txt b/spec/syntax_suggest/fixtures/derailed_require_tree.rb.txt
new file mode 100644
index 0000000000..668ac4010b
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/derailed_require_tree.rb.txt
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+# Tree structure used to store and sort require memory costs
+# RequireTree.new('get_process_mem')
+module DerailedBenchmarks
+ class RequireTree
+ REQUIRED_BY = {}
+
+ attr_reader :name
+ attr_writer :cost
+ attr_accessor :parent
+
+ def initialize(name)
+ @name = name
+ @children = {}
+ @cost = 0
+
+ def self.reset!
+ REQUIRED_BY.clear
+ if defined?(Kernel::REQUIRE_STACK)
+ Kernel::REQUIRE_STACK.clear
+
+ Kernel::REQUIRE_STACK.push(TOP_REQUIRE)
+ end
+ end
+
+ def <<(tree)
+ @children[tree.name.to_s] = tree
+ tree.parent = self
+ (REQUIRED_BY[tree.name.to_s] ||= []) << self.name
+ end
+
+ def [](name)
+ @children[name.to_s]
+ end
+
+ # Returns array of child nodes
+ def children
+ @children.values
+ end
+
+ def cost
+ @cost || 0
+ end
+
+ # Returns sorted array of child nodes from Largest to Smallest
+ def sorted_children
+ children.sort { |c1, c2| c2.cost <=> c1.cost }
+ end
+
+ def to_string
+ str = String.new("#{name}: #{cost.round(4)} MiB")
+ if parent && REQUIRED_BY[self.name.to_s]
+ names = REQUIRED_BY[self.name.to_s].uniq - [parent.name.to_s]
+ if names.any?
+ str << " (Also required by: #{ names.first(2).join(", ") }"
+ str << ", and #{names.count - 2} others" if names.count > 3
+ str << ")"
+ end
+ end
+ str
+ end
+
+ # Recursively prints all child nodes
+ def print_sorted_children(level = 0, out = STDOUT)
+ return if cost < ENV['CUT_OFF'].to_f
+ out.puts " " * level + self.to_string
+ level += 1
+ sorted_children.each do |child|
+ child.print_sorted_children(level, out)
+ end
+ end
+ end
+end
diff --git a/spec/syntax_suggest/fixtures/rexe.rb.txt b/spec/syntax_suggest/fixtures/rexe.rb.txt
new file mode 100755
index 0000000000..92e44d4d1e
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/rexe.rb.txt
@@ -0,0 +1,569 @@
+#!/usr/bin/env ruby
+#
+# rexe - Ruby Command Line Executor Filter
+#
+# Inspired by https://github.com/thisredone/rb
+
+# frozen_string_literal: true
+
+
+require 'bundler'
+require 'date'
+require 'optparse'
+require 'ostruct'
+require 'shellwords'
+
+class Rexe
+
+ VERSION = '1.5.1'
+
+ PROJECT_URL = 'https://github.com/keithrbennett/rexe'
+
+
+ module Helpers
+
+ # Try executing code. If error raised, print message (but not stack trace) & exit -1.
+ def try
+ begin
+ yield
+ rescue Exception => e
+ unless e.class == SystemExit
+ $stderr.puts("rexe: #{e}")
+ $stderr.puts("Use the -h option to get help.")
+ exit(-1)
+ end
+ end
+ end
+ end
+
+
+ class Options < Struct.new(
+ :input_filespec,
+ :input_format,
+ :input_mode,
+ :loads,
+ :output_format,
+ :output_format_tty,
+ :output_format_block,
+ :requires,
+ :log_format,
+ :noop)
+
+
+ def initialize
+ super
+ clear
+ end
+
+
+ def clear
+ self.input_filespec = nil
+ self.input_format = :none
+ self.input_mode = :none
+ self.output_format = :none
+ self.output_format_tty = :none
+ self.output_format_block = :none
+ self.loads = []
+ self.requires = []
+ self.log_format = :none
+ self.noop = false
+ end
+ end
+
+
+
+
+
+ class Lookups
+ def input_modes
+ @input_modes ||= {
+ 'l' => :line,
+ 'e' => :enumerator,
+ 'b' => :one_big_string,
+ 'n' => :none
+ }
+ end
+
+
+ def input_formats
+ @input_formats ||= {
+ 'j' => :json,
+ 'm' => :marshal,
+ 'n' => :none,
+ 'y' => :yaml,
+ }
+ end
+
+
+ def input_parsers
+ @input_parsers ||= {
+ json: ->(string) { JSON.parse(string) },
+ marshal: ->(string) { Marshal.load(string) },
+ none: ->(string) { string },
+ yaml: ->(string) { YAML.load(string) },
+ }
+ end
+
+
+ def output_formats
+ @output_formats ||= {
+ 'a' => :amazing_print,
+ 'i' => :inspect,
+ 'j' => :json,
+ 'J' => :pretty_json,
+ 'm' => :marshal,
+ 'n' => :none,
+ 'p' => :puts, # default
+ 'P' => :pretty_print,
+ 's' => :to_s,
+ 'y' => :yaml,
+ }
+ end
+
+
+ def formatters
+ @formatters ||= {
+ amazing_print: ->(obj) { obj.ai + "\n" },
+ inspect: ->(obj) { obj.inspect + "\n" },
+ json: ->(obj) { obj.to_json },
+ marshal: ->(obj) { Marshal.dump(obj) },
+ none: ->(_obj) { nil },
+ pretty_json: ->(obj) { JSON.pretty_generate(obj) },
+ pretty_print: ->(obj) { obj.pretty_inspect },
+ puts: ->(obj) { require 'stringio'; sio = StringIO.new; sio.puts(obj); sio.string },
+ to_s: ->(obj) { obj.to_s + "\n" },
+ yaml: ->(obj) { obj.to_yaml },
+ }
+ end
+
+
+ def format_requires
+ @format_requires ||= {
+ json: 'json',
+ pretty_json: 'json',
+ amazing_print: 'amazing_print',
+ pretty_print: 'pp',
+ yaml: 'yaml'
+ }
+ end
+ end
+
+
+
+ class CommandLineParser
+
+ include Helpers
+
+ attr_reader :lookups, :options
+
+ def initialize
+ @lookups = Lookups.new
+ @options = Options.new
+ end
+
+
+ # Inserts contents of REXE_OPTIONS environment variable at the beginning of ARGV.
+ private def prepend_environment_options
+ env_opt_string = ENV['REXE_OPTIONS']
+ if env_opt_string
+ args_to_prepend = Shellwords.shellsplit(env_opt_string)
+ ARGV.unshift(args_to_prepend).flatten!
+ end
+ end
+
+
+ private def add_format_requires_to_requires_list
+ formats = [options.input_format, options.output_format, options.log_format]
+ requires = formats.map { |format| lookups.format_requires[format] }.uniq.compact
+ requires.each { |r| options.requires << r }
+ end
+
+
+ private def help_text
+ unless @help_text
+ @help_text ||= <<~HEREDOC
+
+ rexe -- Ruby Command Line Executor/Filter -- v#{VERSION} -- #{PROJECT_URL}
+
+ Executes Ruby code on the command line,
+ optionally automating management of standard input and standard output,
+ and optionally parsing input and formatting output with YAML, JSON, etc.
+
+ rexe [options] [Ruby source code]
+
+ Options:
+
+ -c --clear_options Clear all previous command line options specified up to now
+ -f --input_file Use this file instead of stdin for preprocessed input;
+ if filespec has a YAML and JSON file extension,
+ sets input format accordingly and sets input mode to -mb
+ -g --log_format FORMAT Log format, logs to stderr, defaults to -gn (none)
+ (see -o for format options)
+ -h, --help Print help and exit
+ -i, --input_format FORMAT Input format, defaults to -in (None)
+ -ij JSON
+ -im Marshal
+ -in None (default)
+ -iy YAML
+ -l, --load RUBY_FILE(S) Ruby file(s) to load, comma separated;
+ ! to clear all, or precede a name with '-' to remove
+ -m, --input_mode MODE Input preprocessing mode (determines what `self` will be)
+ defaults to -mn (none)
+ -ml line; each line is ingested as a separate string
+ -me enumerator (each_line on STDIN or File)
+ -mb big string; all lines combined into one string
+ -mn none (default); no input preprocessing;
+ self is an Object.new
+ -n, --[no-]noop Do not execute the code (useful with -g);
+ For true: yes, true, y, +; for false: no, false, n
+ -o, --output_format FORMAT Output format, defaults to -on (no output):
+ -oa Amazing Print
+ -oi Inspect
+ -oj JSON
+ -oJ Pretty JSON
+ -om Marshal
+ -on No Output (default)
+ -op Puts
+ -oP Pretty Print
+ -os to_s
+ -oy YAML
+ If 2 letters are provided, 1st is for tty devices, 2nd for block
+ --project-url Outputs project URL on Github, then exits
+ -r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated;
+ ! to clear all, or precede a name with '-' to remove
+ -v, --version Prints version and exits
+
+ ---------------------------------------------------------------------------------------
+
+ In many cases you will need to enclose your source code in single or double quotes.
+
+ If source code is not specified, it will default to 'self',
+ which is most likely useful only in a filter mode (-ml, -me, -mb).
+
+ If there is a .rexerc file in your home directory, it will be run as Ruby code
+ before processing the input.
+
+ If there is a REXE_OPTIONS environment variable, its content will be prepended
+ to the command line so that you can specify options implicitly
+ (e.g. `export REXE_OPTIONS="-r amazing_print,yaml"`)
+
+ HEREDOC
+
+ @help_text.freeze
+ end
+
+ @help_text
+ end
+
+
+ # File file input mode; detects the input mode (JSON, YAML, or None) from the extension.
+ private def autodetect_file_format(filespec)
+ extension = File.extname(filespec).downcase
+ if extension == '.json'
+ :json
+ elsif extension == '.yml' || extension == '.yaml'
+ :yaml
+ else
+ :none
+ end
+ end
+
+
+ private def open_resource(resource_identifier)
+ command = case (`uname`.chomp)
+ when 'Darwin'
+ 'open'
+ when 'Linux'
+ 'xdg-open'
+ else
+ 'start'
+ end
+
+ `#{command} #{resource_identifier}`
+ end
+
+
+ # Using 'optparse', parses the command line.
+ # Settings go into this instance's properties (see Struct declaration).
+ def parse
+
+ prepend_environment_options
+
+ OptionParser.new do |parser|
+
+ parser.on('-c', '--clear_options', "Clear all previous command line options") do |v|
+ options.clear
+ end
+
+ parser.on('-f', '--input_file FILESPEC',
+ 'Use this file instead of stdin; autodetects YAML and JSON file extensions') do |v|
+ unless File.exist?(v)
+ raise "File #{v} does not exist."
+ end
+ options.input_filespec = v
+ options.input_format = autodetect_file_format(v)
+ if [:json, :yaml].include?(options.input_format)
+ options.input_mode = :one_big_string
+ end
+ end
+
+ parser.on('-g', '--log_format FORMAT', 'Log format, logs to stderr, defaults to none (see -o for format options)') do |v|
+ options.log_format = lookups.output_formats[v]
+ if options.log_format.nil?
+ raise("Output mode was '#{v}' but must be one of #{lookups.output_formats.keys}.")
+ end
+ end
+
+ parser.on("-h", "--help", "Show help") do |_help_requested|
+ puts help_text
+ exit
+ end
+
+ parser.on('-i', '--input_format FORMAT',
+ 'Mode with which to parse input values (n = none (default), j = JSON, m = Marshal, y = YAML') do |v|
+
+ options.input_format = lookups.input_formats[v]
+ if options.input_format.nil?
+ raise("Input mode was '#{v}' but must be one of #{lookups.input_formats.keys}.")
+ end
+ end
+
+ parser.on('-l', '--load RUBY_FILE(S)', 'Ruby file(s) to load, comma separated, or ! to clear') do |v|
+ if v == '!'
+ options.loads.clear
+ else
+ loadfiles = v.split(',').map(&:strip).map { |s| File.expand_path(s) }
+ removes, adds = loadfiles.partition { |filespec| filespec[0] == '-' }
+
+ existent, nonexistent = adds.partition { |filespec| File.exists?(filespec) }
+ if nonexistent.any?
+ raise("\nDid not find the following files to load: #{nonexistent}\n\n")
+ else
+ existent.each { |filespec| options.loads << filespec }
+ end
+
+ removes.each { |filespec| options.loads -= [filespec[1..-1]] }
+ end
+ end
+
+ parser.on('-m', '--input_mode MODE',
+ 'Mode with which to handle input (-ml, -me, -mb, -mn (default)') do |v|
+
+ options.input_mode = lookups.input_modes[v]
+ if options.input_mode.nil?
+ raise("Input mode was '#{v}' but must be one of #{lookups.input_modes.keys}.")
+ end
+ end
+
+ # See https://stackoverflow.com/questions/54576873/ruby-optionparser-short-code-for-boolean-option
+ # for an excellent explanation of this optparse incantation.
+ # According to the answer, valid options are:
+ # -n no, -n yes, -n false, -n true, -n n, -n y, -n +, but not -n -.
+ parser.on('-n', '--[no-]noop [FLAG]', TrueClass, "Do not execute the code (useful with -g)") do |v|
+ options.noop = (v.nil? ? true : v)
+ end
+
+ parser.on('-o', '--output_format FORMAT',
+ 'Mode with which to format values for output (`-o` + [aijJmnpsy])') do |v|
+ options.output_format_tty = lookups.output_formats[v[0]]
+ options.output_format_block = lookups.output_formats[v[-1]]
+ options.output_format = ($stdout.tty? ? options.output_format_tty : options.output_format_block)
+ if [options.output_format_tty, options.output_format_block].include?(nil)
+ raise("Bad output mode '#{v}'; each must be one of #{lookups.output_formats.keys}.")
+ end
+ end
+
+ parser.on('-r', '--require REQUIRE(S)',
+ 'Gems and built-in libraries (e.g. shellwords, yaml) to require, comma separated, or ! to clear') do |v|
+ if v == '!'
+ options.requires.clear
+ else
+ v.split(',').map(&:strip).each do |r|
+ if r[0] == '-'
+ options.requires -= [r[1..-1]]
+ else
+ options.requires << r
+ end
+ end
+ end
+ end
+
+ parser.on('-v', '--version', 'Print version') do
+ puts VERSION
+ exit(0)
+ end
+
+ # Undocumented feature: open Github project with default web browser on a Mac
+ parser.on('', '--open-project') do
+ open_resource(PROJECT_URL)
+ exit(0)
+ end
+
+ parser.on('', '--project-url') do
+ puts PROJECT_URL
+ exit(0)
+ end
+
+ end.parse!
+
+ # We want to do this after all options have been processed because we don't want any clearing of the
+ # options (by '-c', etc.) to result in exclusion of these needed requires.
+ add_format_requires_to_requires_list
+
+ options.requires = options.requires.sort.uniq
+ options.loads.uniq!
+
+ options
+
+ end
+ end
+
+
+ class Main
+
+ include Helpers
+
+ attr_reader :callable, :input_parser, :lookups,
+ :options, :output_formatter,
+ :log_formatter, :start_time, :user_source_code
+
+
+ def initialize
+ @lookups = Lookups.new
+ @start_time = DateTime.now
+ end
+
+
+ private def load_global_config_if_exists
+ filespec = File.join(Dir.home, '.rexerc')
+ load(filespec) if File.exists?(filespec)
+ end
+
+
+ private def init_parser_and_formatters
+ @input_parser = lookups.input_parsers[options.input_format]
+ @output_formatter = lookups.formatters[options.output_format]
+ @log_formatter = lookups.formatters[options.log_format]
+ end
+
+
+ # Executes the user specified code in the manner appropriate to the input mode.
+ # Performs any optionally specified parsing on input and formatting on output.
+ private def execute(eval_context_object, code)
+ if options.input_format != :none && options.input_mode != :none
+ eval_context_object = input_parser.(eval_context_object)
+ end
+
+ value = eval_context_object.instance_eval(&code)
+
+ unless options.output_format == :none
+ print output_formatter.(value)
+ end
+ rescue Errno::EPIPE
+ exit(-13)
+ end
+
+
+ # The global $RC (Rexe Context) OpenStruct is available in your user code.
+ # In order to make it possible to access this object in your loaded files, we are not creating
+ # it here; instead we add properties to it. This way, you can initialize an OpenStruct yourself
+ # in your loaded code and it will still work. If you do that, beware, any properties you add will be
+ # included in the log output. If the to_s of your added objects is large, that might be a pain.
+ private def init_rexe_context
+ $RC ||= OpenStruct.new
+ $RC.count = 0
+ $RC.rexe_version = VERSION
+ $RC.start_time = start_time.iso8601
+ $RC.source_code = user_source_code
+ $RC.options = options.to_h
+
+ def $RC.i; count end # `i` aliases `count` so you can more concisely get the count in your user code
+ end
+
+
+ private def create_callable
+ eval("Proc.new { #{user_source_code} }")
+ end
+
+
+ private def lookup_action(mode)
+ input = options.input_filespec ? File.open(options.input_filespec) : STDIN
+ {
+ line: -> { input.each { |l| execute(l.chomp, callable); $RC.count += 1 } },
+ enumerator: -> { execute(input.each_line, callable); $RC.count += 1 },
+ one_big_string: -> { big_string = input.read; execute(big_string, callable); $RC.count += 1 },
+ none: -> { execute(Object.new, callable) }
+ }.fetch(mode)
+ end
+
+
+ private def output_log_entry
+ if options.log_format != :none
+ $RC.duration_secs = Time.now - start_time.to_time
+ STDERR.puts(log_formatter.($RC.to_h))
+ end
+ end
+
+
+ # Bypasses Bundler's restriction on loading gems
+ # (see https://stackoverflow.com/questions/55144094/bundler-doesnt-permit-using-gems-in-project-home-directory)
+ private def require!(the_require)
+ begin
+ require the_require
+ rescue LoadError => error
+ gem_path = `gem which #{the_require}`
+ if gem_path.chomp.strip.empty?
+ raise error # re-raise the error, can't fix it
+ else
+ load_dir = File.dirname(gem_path)
+ $LOAD_PATH += load_dir
+ require the_require
+ end
+ end
+ end
+
+
+ # This class' entry point.
+ def call
+
+ try do
+
+ @options = CommandLineParser.new.parse
+
+ options.requires.each { |r| require!(r) }
+ load_global_config_if_exists
+ options.loads.each { |file| load(file) }
+
+ @user_source_code = ARGV.join(' ')
+ @user_source_code = 'self' if @user_source_code == ''
+
+ @callable = create_callable
+
+ init_rexe_context
+ init_parser_and_formatters
+
+ # This is where the user's source code will be executed; the action will in turn call `execute`.
+ lookup_action(options.input_mode).call unless options.noop
+
+ output_log_entry
+ end
+ end
+ end
+end
+
+
+def bundler_run(&block)
+ # This used to be an unconditional call to with_clean_env but that method is now deprecated:
+ # [DEPRECATED] `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`
+
+ if Bundler.respond_to?(:with_unbundled_env)
+ Bundler.with_unbundled_env { block.call }
+ else
+ Bundler.with_clean_env { block.call }
+ end
+end
+
+
+bundler_run { Rexe::Main.new.call }
diff --git a/spec/syntax_suggest/fixtures/routes.rb.txt b/spec/syntax_suggest/fixtures/routes.rb.txt
new file mode 100644
index 0000000000..86733821c0
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/routes.rb.txt
@@ -0,0 +1,121 @@
+Rails.application.routes.draw do
+ constraints -> { Rails.application.config.non_production } do
+ namespace :foo do
+ resource :bar
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+ constraints -> { Rails.application.config.non_production } do
+ namespace :bar do
+ resource :baz
+ end
+ end
+
+ namespace :admin do
+ resource :session
+
+ match "/foobar(*path)", via: :all, to: redirect { |_params, req|
+ uri = URI(req.path.gsub("foobar", "foobaz"))
+ uri.query = req.query_string.presence
+ uri.to_s
+ }
+end
diff --git a/spec/syntax_suggest/fixtures/ruby_buildpack.rb.txt b/spec/syntax_suggest/fixtures/ruby_buildpack.rb.txt
new file mode 100644
index 0000000000..9acdbf3a61
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/ruby_buildpack.rb.txt
@@ -0,0 +1,1344 @@
+require "tmpdir"
+require "digest/md5"
+require "benchmark"
+require "rubygems"
+require "language_pack"
+require "language_pack/base"
+require "language_pack/ruby_version"
+require "language_pack/helpers/nodebin"
+require "language_pack/helpers/node_installer"
+require "language_pack/helpers/yarn_installer"
+require "language_pack/helpers/layer"
+require "language_pack/helpers/binstub_check"
+require "language_pack/version"
+
+# base Ruby Language Pack. This is for any base ruby app.
+class LanguagePack::Ruby < LanguagePack::Base
+ NAME = "ruby"
+ LIBYAML_VERSION = "0.1.7"
+ LIBYAML_PATH = "libyaml-#{LIBYAML_VERSION}"
+ RBX_BASE_URL = "http://binaries.rubini.us/heroku"
+ NODE_BP_PATH = "vendor/node/bin"
+
+ Layer = LanguagePack::Helpers::Layer
+
+ # detects if this is a valid Ruby app
+ # @return [Boolean] true if it's a Ruby app
+ def self.use?
+ instrument "ruby.use" do
+ File.exist?("Gemfile")
+ end
+ end
+
+ def self.bundler
+ @@bundler ||= LanguagePack::Helpers::BundlerWrapper.new.install
+ end
+
+ def bundler
+ self.class.bundler
+ end
+
+ def initialize(*args)
+ super(*args)
+ @fetchers[:mri] = LanguagePack::Fetcher.new(VENDOR_URL, @stack)
+ @fetchers[:rbx] = LanguagePack::Fetcher.new(RBX_BASE_URL, @stack)
+ @node_installer = LanguagePack::Helpers::NodeInstaller.new
+ @yarn_installer = LanguagePack::Helpers::YarnInstaller.new
+ end
+
+ def name
+ "Ruby"
+ end
+
+ def default_addons
+ instrument "ruby.default_addons" do
+ add_dev_database_addon
+ end
+ end
+
+ def default_config_vars
+ instrument "ruby.default_config_vars" do
+ vars = {
+ "LANG" => env("LANG") || "en_US.UTF-8",
+ }
+
+ ruby_version.jruby? ? vars.merge({
+ "JRUBY_OPTS" => default_jruby_opts
+ }) : vars
+ end
+ end
+
+ def default_process_types
+ instrument "ruby.default_process_types" do
+ {
+ "rake" => "bundle exec rake",
+ "console" => "bundle exec irb"
+ }
+ end
+ end
+
+ def best_practice_warnings
+ if bundler.has_gem?("asset_sync")
+ warn(<<-WARNING)
+You are using the `asset_sync` gem.
+This is not recommended.
+See https://devcenter.heroku.com/articles/please-do-not-use-asset-sync for more information.
+WARNING
+ end
+ end
+
+ def compile
+ instrument 'ruby.compile' do
+ # check for new app at the beginning of the compile
+ new_app?
+ Dir.chdir(build_path)
+ remove_vendor_bundle
+ warn_bundler_upgrade
+ warn_bad_binstubs
+ install_ruby(slug_vendor_ruby, build_ruby_path)
+ setup_language_pack_environment(
+ ruby_layer_path: File.expand_path("."),
+ gem_layer_path: File.expand_path("."),
+ bundle_path: "vendor/bundle",
+ bundle_default_without: "development:test"
+ )
+ allow_git do
+ install_bundler_in_app(slug_vendor_base)
+ load_bundler_cache
+ build_bundler
+ post_bundler
+ create_database_yml
+ install_binaries
+ run_assets_precompile_rake_task
+ end
+ config_detect
+ best_practice_warnings
+ warn_outdated_ruby
+ setup_profiled(ruby_layer_path: "$HOME", gem_layer_path: "$HOME") # $HOME is set to /app at run time
+ setup_export
+ cleanup
+ super
+ end
+ rescue => e
+ warn_outdated_ruby
+ raise e
+ end
+
+
+ def build
+ new_app?
+ remove_vendor_bundle
+ warn_bad_binstubs
+ ruby_layer = Layer.new(@layer_dir, "ruby", launch: true)
+ install_ruby("#{ruby_layer.path}/#{slug_vendor_ruby}")
+ ruby_layer.metadata[:version] = ruby_version.version
+ ruby_layer.metadata[:patchlevel] = ruby_version.patchlevel if ruby_version.patchlevel
+ ruby_layer.metadata[:engine] = ruby_version.engine.to_s
+ ruby_layer.metadata[:engine_version] = ruby_version.engine_version
+ ruby_layer.write
+
+ gem_layer = Layer.new(@layer_dir, "gems", launch: true, cache: true, build: true)
+ setup_language_pack_environment(
+ ruby_layer_path: ruby_layer.path,
+ gem_layer_path: gem_layer.path,
+ bundle_path: "#{gem_layer.path}/vendor/bundle",
+ bundle_default_without: "development:test"
+ )
+ allow_git do
+ # TODO install bundler in separate layer
+ topic "Loading Bundler Cache"
+ gem_layer.validate! do |metadata|
+ valid_bundler_cache?(gem_layer.path, gem_layer.metadata)
+ end
+ install_bundler_in_app("#{gem_layer.path}/#{slug_vendor_base}")
+ build_bundler
+ # TODO post_bundler might need to be done in a new layer
+ bundler.clean
+ gem_layer.metadata[:gems] = Digest::SHA2.hexdigest(File.read("Gemfile.lock"))
+ gem_layer.metadata[:stack] = @stack
+ gem_layer.metadata[:ruby_version] = run_stdout(%q(ruby -v)).strip
+ gem_layer.metadata[:rubygems_version] = run_stdout(%q(gem -v)).strip
+ gem_layer.metadata[:buildpack_version] = BUILDPACK_VERSION
+ gem_layer.write
+
+ create_database_yml
+ # TODO replace this with multibuildpack stuff? put binaries in their own layer?
+ install_binaries
+ run_assets_precompile_rake_task
+ end
+ setup_profiled(ruby_layer_path: ruby_layer.path, gem_layer_path: gem_layer.path)
+ setup_export(gem_layer)
+ config_detect
+ best_practice_warnings
+ cleanup
+
+ super
+ end
+
+ def cleanup
+ end
+
+ def config_detect
+ end
+
+private
+
+ # A bad shebang line looks like this:
+ #
+ # ```
+ # #!/usr/bin/env ruby2.5
+ # ```
+ #
+ # Since `ruby2.5` is not a valid binary name
+ #
+ def warn_bad_binstubs
+ check = LanguagePack::Helpers::BinstubCheck.new(app_root_dir: Dir.pwd, warn_object: self)
+ check.call
+ end
+
+ def default_malloc_arena_max?
+ return true if @metadata.exists?("default_malloc_arena_max")
+ return @metadata.touch("default_malloc_arena_max") if new_app?
+
+ return false
+ end
+
+ def warn_bundler_upgrade
+ old_bundler_version = @metadata.read("bundler_version").strip if @metadata.exists?("bundler_version")
+
+ if old_bundler_version && old_bundler_version != bundler.version
+ warn(<<-WARNING, inline: true)
+Your app was upgraded to bundler #{ bundler.version }.
+Previously you had a successful deploy with bundler #{ old_bundler_version }.
+
+If you see problems related to the bundler version please refer to:
+https://devcenter.heroku.com/articles/bundler-version#known-upgrade-issues
+
+WARNING
+ end
+ end
+
+ # For example "vendor/bundle/ruby/2.6.0"
+ def self.slug_vendor_base
+ @slug_vendor_base ||= begin
+ command = %q(ruby -e "require 'rbconfig';puts \"vendor/bundle/#{RUBY_ENGINE}/#{RbConfig::CONFIG['ruby_version']}\"")
+ out = run_no_pipe(command, user_env: true).strip
+ error "Problem detecting bundler vendor directory: #{out}" unless $?.success?
+ out
+ end
+ end
+
+ # the relative path to the bundler directory of gems
+ # @return [String] resulting path
+ def slug_vendor_base
+ instrument 'ruby.slug_vendor_base' do
+ @slug_vendor_base ||= self.class.slug_vendor_base
+ end
+ end
+
+ # the relative path to the vendored ruby directory
+ # @return [String] resulting path
+ def slug_vendor_ruby
+ "vendor/#{ruby_version.version_without_patchlevel}"
+ end
+
+ # the absolute path of the build ruby to use during the buildpack
+ # @return [String] resulting path
+ def build_ruby_path
+ "/tmp/#{ruby_version.version_without_patchlevel}"
+ end
+
+ # fetch the ruby version from bundler
+ # @return [String, nil] returns the ruby version if detected or nil if none is detected
+ def ruby_version
+ instrument 'ruby.ruby_version' do
+ return @ruby_version if @ruby_version
+ new_app = !File.exist?("vendor/heroku")
+ last_version_file = "buildpack_ruby_version"
+ last_version = nil
+ last_version = @metadata.read(last_version_file).strip if @metadata.exists?(last_version_file)
+
+ @ruby_version = LanguagePack::RubyVersion.new(bundler.ruby_version,
+ is_new: new_app,
+ last_version: last_version)
+ return @ruby_version
+ end
+ end
+
+ def set_default_web_concurrency
+ <<-EOF
+case $(ulimit -u) in
+256)
+ export HEROKU_RAM_LIMIT_MB=${HEROKU_RAM_LIMIT_MB:-512}
+ export WEB_CONCURRENCY=${WEB_CONCURRENCY:-2}
+ ;;
+512)
+ export HEROKU_RAM_LIMIT_MB=${HEROKU_RAM_LIMIT_MB:-1024}
+ export WEB_CONCURRENCY=${WEB_CONCURRENCY:-4}
+ ;;
+16384)
+ export HEROKU_RAM_LIMIT_MB=${HEROKU_RAM_LIMIT_MB:-2560}
+ export WEB_CONCURRENCY=${WEB_CONCURRENCY:-8}
+ ;;
+32768)
+ export HEROKU_RAM_LIMIT_MB=${HEROKU_RAM_LIMIT_MB:-6144}
+ export WEB_CONCURRENCY=${WEB_CONCURRENCY:-16}
+ ;;
+*)
+ ;;
+esac
+EOF
+ end
+
+ # default JRUBY_OPTS
+ # return [String] string of JRUBY_OPTS
+ def default_jruby_opts
+ "-Xcompile.invokedynamic=false"
+ end
+
+ # sets up the environment variables for the build process
+ def setup_language_pack_environment(ruby_layer_path:, gem_layer_path:, bundle_path:, bundle_default_without:)
+ instrument 'ruby.setup_language_pack_environment' do
+ if ruby_version.jruby?
+ ENV["PATH"] += ":bin"
+ ENV["JRUBY_OPTS"] = env('JRUBY_BUILD_OPTS') || env('JRUBY_OPTS')
+ end
+ setup_ruby_install_env(ruby_layer_path)
+
+ # By default Node can address 1.5GB of memory, a limitation it inherits from
+ # the underlying v8 engine. This can occasionally cause issues during frontend
+ # builds where memory use can exceed this threshold.
+ #
+ # This passes an argument to all Node processes during the build, so that they
+ # can take advantage of all available memory on the build dynos.
+ ENV["NODE_OPTIONS"] ||= "--max_old_space_size=2560"
+
+ # TODO when buildpack-env-args rolls out, we can get rid of
+ # ||= and the manual setting below
+ default_config_vars.each do |key, value|
+ ENV[key] ||= value
+ end
+
+ paths = []
+ gem_path = "#{gem_layer_path}/#{slug_vendor_base}"
+ ENV["GEM_PATH"] = gem_path
+ ENV["GEM_HOME"] = gem_path
+
+ ENV["DISABLE_SPRING"] = "1"
+
+ # Rails has a binstub for yarn that doesn't work for all applications
+ # we need to ensure that yarn comes before local bin dir for that case
+ paths << yarn_preinstall_bin_path if yarn_preinstalled?
+
+ # Need to remove `./bin` folder since it links to the wrong --prefix ruby binstubs breaking require in Ruby 1.9.2 and 1.8.7.
+ # Because for 1.9.2 and 1.8.7 there is a "build" ruby and a non-"build" Ruby
+ paths << "#{File.expand_path(".")}/bin" unless ruby_version.ruby_192_or_lower?
+
+ paths << "#{gem_layer_path}/#{bundler_binstubs_path}" # Binstubs from bundler, eg. vendor/bundle/bin
+ paths << "#{gem_layer_path}/#{slug_vendor_base}/bin" # Binstubs from rubygems, eg. vendor/bundle/ruby/2.6.0/bin
+ paths << ENV["PATH"]
+
+ ENV["PATH"] = paths.join(":")
+
+ ENV["BUNDLE_WITHOUT"] = env("BUNDLE_WITHOUT") || bundle_default_without
+ if ENV["BUNDLE_WITHOUT"].include?(' ')
+ ENV["BUNDLE_WITHOUT"] = ENV["BUNDLE_WITHOUT"].tr(' ', ':')
+
+ warn("Your BUNDLE_WITHOUT contains a space, we are converting it to a colon `:` BUNDLE_WITHOUT=#{ENV["BUNDLE_WITHOUT"]}", inline: true)
+ end
+ ENV["BUNDLE_PATH"] = bundle_path
+ ENV["BUNDLE_BIN"] = bundler_binstubs_path
+ ENV["BUNDLE_DEPLOYMENT"] = "1"
+ ENV["BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE"] = "1" if bundler.needs_ruby_global_append_path?
+ end
+ end
+
+ # Sets up the environment variables for subsequent processes run by
+ # muiltibuildpack. We can't use profile.d because $HOME isn't set up
+ def setup_export(layer = nil)
+ instrument 'ruby.setup_export' do
+ if layer
+ paths = ENV["PATH"]
+ else
+ paths = ENV["PATH"].split(":").map do |path|
+ /^\/.*/ !~ path ? "#{build_path}/#{path}" : path
+ end.join(":")
+ end
+
+ # TODO ensure path exported is correct
+ set_export_path "PATH", paths, layer
+
+ if layer
+ gem_path = "#{layer.path}/#{slug_vendor_base}"
+ else
+ gem_path = "#{build_path}/#{slug_vendor_base}"
+ end
+ set_export_path "GEM_PATH", gem_path, layer
+ set_export_default "LANG", "en_US.UTF-8", layer
+
+ # TODO handle jruby
+ if ruby_version.jruby?
+ set_export_default "JRUBY_OPTS", default_jruby_opts
+ end
+
+ set_export_default "BUNDLE_PATH", ENV["BUNDLE_PATH"], layer
+ set_export_default "BUNDLE_WITHOUT", ENV["BUNDLE_WITHOUT"], layer
+ set_export_default "BUNDLE_BIN", ENV["BUNDLE_BIN"], layer
+ set_export_default "BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE", ENV["BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE"], layer if bundler.needs_ruby_global_append_path?
+ set_export_default "BUNDLE_DEPLOYMENT", ENV["BUNDLE_DEPLOYMENT"], layer if ENV["BUNDLE_DEPLOYMENT"] # Unset on windows since we delete the Gemfile.lock
+ end
+ end
+
+ # sets up the profile.d script for this buildpack
+ def setup_profiled(ruby_layer_path: , gem_layer_path: )
+ instrument 'setup_profiled' do
+ profiled_path = []
+
+ # Rails has a binstub for yarn that doesn't work for all applications
+ # we need to ensure that yarn comes before local bin dir for that case
+ if yarn_preinstalled?
+ profiled_path << yarn_preinstall_bin_path.gsub(File.expand_path("."), "$HOME")
+ elsif has_yarn_binary?
+ profiled_path << "#{ruby_layer_path}/vendor/#{@yarn_installer.binary_path}"
+ end
+ profiled_path << "$HOME/bin" # /app in production
+ profiled_path << "#{gem_layer_path}/#{bundler_binstubs_path}" # Binstubs from bundler, eg. vendor/bundle/bin
+ profiled_path << "#{gem_layer_path}/#{slug_vendor_base}/bin" # Binstubs from rubygems, eg. vendor/bundle/ruby/2.6.0/bin
+ profiled_path << "$PATH"
+
+ set_env_default "LANG", "en_US.UTF-8"
+ set_env_override "GEM_PATH", "#{gem_layer_path}/#{slug_vendor_base}:$GEM_PATH"
+ set_env_override "PATH", profiled_path.join(":")
+ set_env_override "DISABLE_SPRING", "1"
+
+ set_env_default "MALLOC_ARENA_MAX", "2" if default_malloc_arena_max?
+
+ web_concurrency = env("SENSIBLE_DEFAULTS") ? set_default_web_concurrency : ""
+ add_to_profiled(web_concurrency, filename: "WEB_CONCURRENCY.sh", mode: "w") # always write that file, even if its empty (meaning no defaults apply), for interop with other buildpacks - and we overwrite the file rather than appending (which is the default)
+
+ # TODO handle JRUBY
+ if ruby_version.jruby?
+ set_env_default "JRUBY_OPTS", default_jruby_opts
+ end
+
+ set_env_default "BUNDLE_PATH", ENV["BUNDLE_PATH"]
+ set_env_default "BUNDLE_WITHOUT", ENV["BUNDLE_WITHOUT"]
+ set_env_default "BUNDLE_BIN", ENV["BUNDLE_BIN"]
+ set_env_default "BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE", ENV["BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE"] if bundler.needs_ruby_global_append_path?
+ set_env_default "BUNDLE_DEPLOYMENT", ENV["BUNDLE_DEPLOYMENT"] if ENV["BUNDLE_DEPLOYMENT"] # Unset on windows since we delete the Gemfile.lock
+ end
+ end
+
+ def warn_outdated_ruby
+ return unless defined?(@outdated_version_check)
+
+ @warn_outdated ||= begin
+ @outdated_version_check.join
+
+ warn_outdated_minor
+ warn_outdated_eol
+ warn_stack_upgrade
+ true
+ end
+ end
+
+ def warn_stack_upgrade
+ return unless defined?(@ruby_download_check)
+ return unless @ruby_download_check.next_stack(current_stack: stack)
+ return if @ruby_download_check.exists_on_next_stack?(current_stack: stack)
+
+ warn(<<~WARNING)
+ Your Ruby version is not present on the next stack
+
+ You are currently using #{ruby_version.version_for_download} on #{stack} stack.
+ This version does not exist on #{@ruby_download_check.next_stack(current_stack: stack)}. In order to upgrade your stack you will
+ need to upgrade to a supported Ruby version.
+
+ For a list of supported Ruby versions see:
+ https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
+
+ For a list of the oldest Ruby versions present on a given stack see:
+ https://devcenter.heroku.com/articles/ruby-support#oldest-available-runtimes
+ WARNING
+ end
+
+ def warn_outdated_eol
+ return unless @outdated_version_check.maybe_eol?
+
+ if @outdated_version_check.eol?
+ warn(<<~WARNING)
+ EOL Ruby Version
+
+ You are using a Ruby version that has reached its End of Life (EOL)
+
+ We strongly suggest you upgrade to Ruby #{@outdated_version_check.suggest_ruby_eol_version} or later
+
+ Your current Ruby version no longer receives security updates from
+ Ruby Core and may have serious vulnerabilities. While you will continue
+ to be able to deploy on Heroku with this Ruby version you must upgrade
+ to a non-EOL version to be eligible to receive support.
+
+ Upgrade your Ruby version as soon as possible.
+
+ For a list of supported Ruby versions see:
+ https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
+ WARNING
+ else
+ # Maybe EOL
+ warn(<<~WARNING)
+ Potential EOL Ruby Version
+
+ You are using a Ruby version that has either reached its End of Life (EOL)
+ or will reach its End of Life on December 25th of this year.
+
+ We suggest you upgrade to Ruby #{@outdated_version_check.suggest_ruby_eol_version} or later
+
+ Once a Ruby version becomes EOL, it will no longer receive
+ security updates from Ruby core and may have serious vulnerabilities.
+
+ Please upgrade your Ruby version.
+
+ For a list of supported Ruby versions see:
+ https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
+ WARNING
+ end
+ end
+
+ def warn_outdated_minor
+ return if @outdated_version_check.latest_minor_version?
+
+ warn(<<~WARNING)
+ There is a more recent Ruby version available for you to use:
+
+ #{@outdated_version_check.suggested_ruby_minor_version}
+
+ The latest version will include security and bug fixes. We always recommend
+ running the latest version of your minor release.
+
+ Please upgrade your Ruby version.
+
+ For all available Ruby versions see:
+ https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
+ WARNING
+ end
+
+ # install the vendored ruby
+ # @return [Boolean] true if it installs the vendored ruby and false otherwise
+ def install_ruby(install_path, build_ruby_path = nil)
+ instrument 'ruby.install_ruby' do
+ # Could do a compare operation to avoid re-downloading ruby
+ return false unless ruby_version
+ installer = LanguagePack::Installers::RubyInstaller.installer(ruby_version).new(@stack)
+
+ @ruby_download_check = LanguagePack::Helpers::DownloadPresence.new(ruby_version.file_name)
+ @ruby_download_check.call
+
+ if ruby_version.build?
+ installer.fetch_unpack(ruby_version, build_ruby_path, true)
+ end
+
+ installer.install(ruby_version, install_path)
+
+ @outdated_version_check = LanguagePack::Helpers::OutdatedRubyVersion.new(
+ current_ruby_version: ruby_version,
+ fetcher: installer.fetcher
+ )
+ @outdated_version_check.call
+
+ @metadata.write("buildpack_ruby_version", ruby_version.version_for_download)
+
+ topic "Using Ruby version: #{ruby_version.version_for_download}"
+ if !ruby_version.set
+ warn(<<~WARNING)
+ You have not declared a Ruby version in your Gemfile.
+
+ To declare a Ruby version add this line to your Gemfile:
+
+ ```
+ ruby "#{LanguagePack::RubyVersion::DEFAULT_VERSION_NUMBER}"
+ ```
+
+ For more information see:
+ https://devcenter.heroku.com/articles/ruby-versions
+ WARNING
+ end
+
+ if ruby_version.warn_ruby_26_bundler?
+ warn(<<~WARNING, inline: true)
+ There is a known bundler bug with your version of Ruby
+
+ Your version of Ruby contains a problem with the built-in integration of bundler. If
+ you encounter a bundler error you need to upgrade your Ruby version. We suggest you upgrade to:
+
+ #{@outdated_version_check.suggested_ruby_minor_version}
+
+ For more information see:
+ https://devcenter.heroku.com/articles/bundler-version#known-upgrade-issues
+ WARNING
+ end
+ end
+
+ true
+ rescue LanguagePack::Fetcher::FetchError
+ if @ruby_download_check.does_not_exist?
+ message = <<~ERROR
+ The Ruby version you are trying to install does not exist: #{ruby_version.version_for_download}
+ ERROR
+ else
+ message = <<~ERROR
+ The Ruby version you are trying to install does not exist on this stack.
+
+ You are trying to install #{ruby_version.version_for_download} on #{stack}.
+
+ Ruby #{ruby_version.version_for_download} is present on the following stacks:
+
+ - #{@ruby_download_check.valid_stack_list.join("\n - ")}
+ ERROR
+
+ if env("CI")
+ message << <<~ERROR
+
+ On Heroku CI you can set your stack in the `app.json`. For example:
+
+ ```
+ "stack": "heroku-20"
+ ```
+ ERROR
+ end
+ end
+
+ message << <<~ERROR
+
+ Heroku recommends you use the latest supported Ruby version listed here:
+ https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
+
+ For more information on syntax for declaring a Ruby version see:
+ https://devcenter.heroku.com/articles/ruby-versions
+ ERROR
+
+ error message
+ end
+
+ # TODO make this compatible with CNB
+ def new_app?
+ @new_app ||= !File.exist?("vendor/heroku")
+ end
+
+ # find the ruby install path for its binstubs during build
+ # @return [String] resulting path or empty string if ruby is not vendored
+ def ruby_install_binstub_path(ruby_layer_path = ".")
+ @ruby_install_binstub_path ||=
+ if ruby_version.build?
+ "#{build_ruby_path}/bin"
+ elsif ruby_version
+ "#{ruby_layer_path}/#{slug_vendor_ruby}/bin"
+ else
+ ""
+ end
+ end
+
+ # setup the environment so we can use the vendored ruby
+ def setup_ruby_install_env(ruby_layer_path = ".")
+ instrument 'ruby.setup_ruby_install_env' do
+ ENV["PATH"] = "#{File.expand_path(ruby_install_binstub_path(ruby_layer_path))}:#{ENV["PATH"]}"
+ end
+ end
+
+ # installs vendored gems into the slug
+ def install_bundler_in_app(bundler_dir)
+ instrument 'ruby.install_language_pack_gems' do
+ FileUtils.mkdir_p(bundler_dir)
+ Dir.chdir(bundler_dir) do |dir|
+ `cp -R #{bundler.bundler_path}/. .`
+ end
+
+ # write bundler shim, so we can control the version bundler used
+ # Ruby 2.6.0 started vendoring bundler
+ write_bundler_shim("vendor/bundle/bin") if ruby_version.vendored_bundler?
+ end
+ end
+
+ # default set of binaries to install
+ # @return [Array] resulting list
+ def binaries
+ add_node_js_binary + add_yarn_binary
+ end
+
+ # vendors binaries into the slug
+ def install_binaries
+ instrument 'ruby.install_binaries' do
+ binaries.each {|binary| install_binary(binary) }
+ Dir["bin/*"].each {|path| run("chmod +x #{path}") }
+ end
+ end
+
+ # vendors individual binary into the slug
+ # @param [String] name of the binary package from S3.
+ # Example: https://s3.amazonaws.com/language-pack-ruby/node-0.4.7.tgz, where name is "node-0.4.7"
+ def install_binary(name)
+ topic "Installing #{name}"
+ bin_dir = "bin"
+ FileUtils.mkdir_p bin_dir
+ Dir.chdir(bin_dir) do |dir|
+ if name.match(/^node\-/)
+ @node_installer.install
+ # need to set PATH here b/c `node-gyp` can change the CWD, but still depends on executing node.
+ # the current PATH is relative, but it needs to be absolute for this.
+ # doing this here also prevents it from being exported during runtime
+ node_bin_path = File.absolute_path(".")
+ # this needs to be set after so other binaries in bin/ don't take precedence"
+ ENV["PATH"] = "#{ENV["PATH"]}:#{node_bin_path}"
+ elsif name.match(/^yarn\-/)
+ FileUtils.mkdir_p("../vendor")
+ Dir.chdir("../vendor") do |vendor_dir|
+ @yarn_installer.install
+ yarn_path = File.absolute_path("#{vendor_dir}/#{@yarn_installer.binary_path}")
+ ENV["PATH"] = "#{yarn_path}:#{ENV["PATH"]}"
+ end
+ else
+ @fetchers[:buildpack].fetch_untar("#{name}.tgz")
+ end
+ end
+ end
+
+ # removes a binary from the slug
+ # @param [String] relative path of the binary on the slug
+ def uninstall_binary(path)
+ FileUtils.rm File.join('bin', File.basename(path)), :force => true
+ end
+
+ def load_default_cache?
+ new_app? && ruby_version.default?
+ end
+
+ # loads a default bundler cache for new apps to speed up initial bundle installs
+ def load_default_cache
+ instrument "ruby.load_default_cache" do
+ if false # load_default_cache?
+ puts "New app detected loading default bundler cache"
+ patchlevel = run("ruby -e 'puts RUBY_PATCHLEVEL'").strip
+ cache_name = "#{LanguagePack::RubyVersion::DEFAULT_VERSION}-p#{patchlevel}-default-cache"
+ @fetchers[:buildpack].fetch_untar("#{cache_name}.tgz")
+ end
+ end
+ end
+
+ # remove `vendor/bundle` that comes from the git repo
+ # in case there are native ext.
+ # users should be using `bundle pack` instead.
+ # https://github.com/heroku/heroku-buildpack-ruby/issues/21
+ def remove_vendor_bundle
+ if File.exists?("vendor/bundle")
+ warn(<<-WARNING)
+Removing `vendor/bundle`.
+Checking in `vendor/bundle` is not supported. Please remove this directory
+and add it to your .gitignore. To vendor your gems with Bundler, use
+`bundle pack` instead.
+WARNING
+ FileUtils.rm_rf("vendor/bundle")
+ end
+ end
+
+ def bundler_binstubs_path
+ "vendor/bundle/bin"
+ end
+
+ def bundler_path
+ @bundler_path ||= "#{slug_vendor_base}/gems/#{bundler.dir_name}"
+ end
+
+ def write_bundler_shim(path)
+ FileUtils.mkdir_p(path)
+ shim_path = "#{path}/bundle"
+ File.open(shim_path, "w") do |file|
+ file.print <<-BUNDLE
+#!/usr/bin/env ruby
+require 'rubygems'
+
+version = "#{bundler.version}"
+
+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('bundler', 'bundle', version)
+else
+gem "bundler", version
+load Gem.bin_path("bundler", "bundle", version)
+end
+BUNDLE
+ end
+ FileUtils.chmod(0755, shim_path)
+ end
+
+ # runs bundler to install the dependencies
+ def build_bundler
+ instrument 'ruby.build_bundler' do
+ log("bundle") do
+ if File.exist?("#{Dir.pwd}/.bundle/config")
+ warn(<<~WARNING, inline: true)
+ You have the `.bundle/config` file checked into your repository
+ It contains local state like the location of the installed bundle
+ as well as configured git local gems, and other settings that should
+ not be shared between multiple checkouts of a single repo. Please
+ remove the `.bundle/` folder from your repo and add it to your `.gitignore` file.
+
+ https://devcenter.heroku.com/articles/bundler-configuration
+ WARNING
+ end
+
+ if bundler.windows_gemfile_lock?
+ log("bundle", "has_windows_gemfile_lock")
+
+ File.unlink("Gemfile.lock")
+ ENV.delete("BUNDLE_DEPLOYMENT")
+
+ warn(<<~WARNING, inline: true)
+ Removing `Gemfile.lock` because it was generated on Windows.
+ Bundler will do a full resolve so native gems are handled properly.
+ This may result in unexpected gem versions being used in your app.
+ In rare occasions Bundler may not be able to resolve your dependencies at all.
+
+ https://devcenter.heroku.com/articles/bundler-windows-gemfile
+ WARNING
+ end
+
+ bundle_command = String.new("")
+ bundle_command << "BUNDLE_WITHOUT='#{ENV["BUNDLE_WITHOUT"]}' "
+ bundle_command << "BUNDLE_PATH=#{ENV["BUNDLE_PATH"]} "
+ bundle_command << "BUNDLE_BIN=#{ENV["BUNDLE_BIN"]} "
+ bundle_command << "BUNDLE_DEPLOYMENT=#{ENV["BUNDLE_DEPLOYMENT"]} " if ENV["BUNDLE_DEPLOYMENT"] # Unset on windows since we delete the Gemfile.lock
+ bundle_command << "BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE=#{ENV["BUNDLE_GLOBAL_PATH_APPENDS_RUBY_SCOPE"]} " if bundler.needs_ruby_global_append_path?
+ bundle_command << "bundle install -j4"
+
+ topic("Installing dependencies using bundler #{bundler.version}")
+
+ bundler_output = String.new("")
+ bundle_time = nil
+ env_vars = {}
+ Dir.mktmpdir("libyaml-") do |tmpdir|
+ libyaml_dir = "#{tmpdir}/#{LIBYAML_PATH}"
+
+ # need to setup compile environment for the psych gem
+ yaml_include = File.expand_path("#{libyaml_dir}/include").shellescape
+ yaml_lib = File.expand_path("#{libyaml_dir}/lib").shellescape
+ pwd = Dir.pwd
+ bundler_path = "#{pwd}/#{slug_vendor_base}/gems/#{bundler.dir_name}/lib"
+
+ # we need to set BUNDLE_CONFIG and BUNDLE_GEMFILE for
+ # codon since it uses bundler.
+ env_vars["BUNDLE_GEMFILE"] = "#{pwd}/Gemfile"
+ env_vars["BUNDLE_CONFIG"] = "#{pwd}/.bundle/config"
+ env_vars["CPATH"] = noshellescape("#{yaml_include}:$CPATH")
+ env_vars["CPPATH"] = noshellescape("#{yaml_include}:$CPPATH")
+ env_vars["LIBRARY_PATH"] = noshellescape("#{yaml_lib}:$LIBRARY_PATH")
+ env_vars["RUBYOPT"] = syck_hack
+ env_vars["NOKOGIRI_USE_SYSTEM_LIBRARIES"] = "true"
+ env_vars["BUNDLE_DISABLE_VERSION_CHECK"] = "true"
+ env_vars["BUNDLER_LIB_PATH"] = "#{bundler_path}" if ruby_version.ruby_version == "1.8.7"
+ env_vars["BUNDLE_DISABLE_VERSION_CHECK"] = "true"
+
+ puts "Running: #{bundle_command}"
+ instrument "ruby.bundle_install" do
+ bundle_time = Benchmark.realtime do
+ bundler_output << pipe("#{bundle_command} --no-clean", out: "2>&1", env: env_vars, user_env: true)
+ end
+ end
+ end
+
+ if $?.success?
+ puts "Bundle completed (#{"%.2f" % bundle_time}s)"
+ log "bundle", :status => "success"
+ puts "Cleaning up the bundler cache."
+ instrument "ruby.bundle_clean" do
+ # Only show bundle clean output when not using default cache
+ if load_default_cache?
+ run("bundle clean > /dev/null", user_env: true, env: env_vars)
+ else
+ pipe("bundle clean", out: "2> /dev/null", user_env: true, env: env_vars)
+ end
+ end
+ @bundler_cache.store
+
+ # Keep gem cache out of the slug
+ FileUtils.rm_rf("#{slug_vendor_base}/cache")
+ else
+ mcount "fail.bundle.install"
+ log "bundle", :status => "failure"
+ error_message = "Failed to install gems via Bundler."
+ puts "Bundler Output: #{bundler_output}"
+ if bundler_output.match(/An error occurred while installing sqlite3/)
+ mcount "fail.sqlite3"
+ error_message += <<~ERROR
+
+ Detected sqlite3 gem which is not supported on Heroku:
+ https://devcenter.heroku.com/articles/sqlite3
+ ERROR
+ end
+
+ if bundler_output.match(/but your Gemfile specified/)
+ mcount "fail.ruby_version_mismatch"
+ error_message += <<~ERROR
+
+ Detected a mismatch between your Ruby version installed and
+ Ruby version specified in Gemfile or Gemfile.lock. You can
+ correct this by running:
+
+ $ bundle update --ruby
+ $ git add Gemfile.lock
+ $ git commit -m "update ruby version"
+
+ If this does not solve the issue please see this documentation:
+
+ https://devcenter.heroku.com/articles/ruby-versions#your-ruby-version-is-x-but-your-gemfile-specified-y
+ ERROR
+ end
+
+ error error_message
+ end
+ end
+ end
+ end
+
+ def post_bundler
+ instrument "ruby.post_bundler" do
+ Dir[File.join(slug_vendor_base, "**", ".git")].each do |dir|
+ FileUtils.rm_rf(dir)
+ end
+ bundler.clean
+ end
+ end
+
+ # RUBYOPT line that requires syck_hack file
+ # @return [String] require string if needed or else an empty string
+ def syck_hack
+ instrument "ruby.syck_hack" do
+ syck_hack_file = File.expand_path(File.join(File.dirname(__FILE__), "../../vendor/syck_hack"))
+ rv = run_stdout('ruby -e "puts RUBY_VERSION"').strip
+ # < 1.9.3 includes syck, so we need to use the syck hack
+ if Gem::Version.new(rv) < Gem::Version.new("1.9.3")
+ "-r#{syck_hack_file}"
+ else
+ ""
+ end
+ end
+ end
+
+ # writes ERB based database.yml for Rails. The database.yml uses the DATABASE_URL from the environment during runtime.
+ def create_database_yml
+ instrument 'ruby.create_database_yml' do
+ return false unless File.directory?("config")
+ return false if bundler.has_gem?('activerecord') && bundler.gem_version('activerecord') >= Gem::Version.new('4.1.0.beta1')
+
+ log("create_database_yml") do
+ topic("Writing config/database.yml to read from DATABASE_URL")
+ File.open("config/database.yml", "w") do |file|
+ file.puts <<-DATABASE_YML
+<%
+
+require 'cgi'
+require 'uri'
+
+begin
+ uri = URI.parse(ENV["DATABASE_URL"])
+rescue URI::InvalidURIError
+ raise "Invalid DATABASE_URL"
+end
+
+raise "No RACK_ENV or RAILS_ENV found" unless ENV["RAILS_ENV"] || ENV["RACK_ENV"]
+
+def attribute(name, value, force_string = false)
+ if value
+ value_string =
+ if force_string
+ '"' + value + '"'
+ else
+ value
+ end
+ "\#{name}: \#{value_string}"
+ else
+ ""
+ end
+end
+
+adapter = uri.scheme
+adapter = "postgresql" if adapter == "postgres"
+
+database = (uri.path || "").split("/")[1]
+
+username = uri.user
+password = uri.password
+
+host = uri.host
+port = uri.port
+
+params = CGI.parse(uri.query || "")
+
+%>
+
+<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
+ <%= attribute "adapter", adapter %>
+ <%= attribute "database", database %>
+ <%= attribute "username", username %>
+ <%= attribute "password", password, true %>
+ <%= attribute "host", host %>
+ <%= attribute "port", port %>
+
+<% params.each do |key, value| %>
+ <%= key %>: <%= value.first %>
+<% end %>
+ DATABASE_YML
+ end
+ end
+ end
+ end
+
+ def rake
+ @rake ||= begin
+ rake_gem_available = bundler.has_gem?("rake") || ruby_version.rake_is_vendored?
+ raise_on_fail = bundler.gem_version('railties') && bundler.gem_version('railties') > Gem::Version.new('3.x')
+
+ topic "Detecting rake tasks"
+ rake = LanguagePack::Helpers::RakeRunner.new(rake_gem_available)
+ rake.load_rake_tasks!({ env: rake_env }, raise_on_fail)
+ rake
+ end
+ end
+
+ def rake_env
+ if database_url
+ { "DATABASE_URL" => database_url }
+ else
+ {}
+ end.merge(user_env_hash)
+ end
+
+ def database_url
+ env("DATABASE_URL") if env("DATABASE_URL")
+ end
+
+ # executes the block with GIT_DIR environment variable removed since it can mess with the current working directory git thinks it's in
+ # @param [block] block to be executed in the GIT_DIR free context
+ def allow_git(&blk)
+ git_dir = ENV.delete("GIT_DIR") # can mess with bundler
+ blk.call
+ ENV["GIT_DIR"] = git_dir
+ end
+
+ # decides if we need to enable the dev database addon
+ # @return [Array] the database addon if the pg gem is detected or an empty Array if it isn't.
+ def add_dev_database_addon
+ pg_adapters.any? {|a| bundler.has_gem?(a) } ? ['heroku-postgresql'] : []
+ end
+
+ def pg_adapters
+ [
+ "pg",
+ "activerecord-jdbcpostgresql-adapter",
+ "jdbc-postgres",
+ "jdbc-postgresql",
+ "jruby-pg",
+ "rjack-jdbc-postgres",
+ "tgbyte-activerecord-jdbcpostgresql-adapter"
+ ]
+ end
+
+ # decides if we need to install the node.js binary
+ # @note execjs will blow up if no JS RUNTIME is detected and is loaded.
+ # @return [Array] the node.js binary path if we need it or an empty Array
+ def add_node_js_binary
+ return [] if node_js_preinstalled?
+
+ if Pathname(build_path).join("package.json").exist? ||
+ bundler.has_gem?('execjs') ||
+ bundler.has_gem?('webpacker')
+ [@node_installer.binary_path]
+ else
+ []
+ end
+ end
+
+ def add_yarn_binary
+ return [] if yarn_preinstalled?
+|
+ if Pathname(build_path).join("yarn.lock").exist? || bundler.has_gem?('webpacker')
+ [@yarn_installer.name]
+ else
+ []
+ end
+ end
+
+ def has_yarn_binary?
+ add_yarn_binary.any?
+ end
+
+ # checks if node.js is installed via the official heroku-buildpack-nodejs using multibuildpack
+ # @return String if it's detected and false if it isn't
+ def node_preinstall_bin_path
+ return @node_preinstall_bin_path if defined?(@node_preinstall_bin_path)
+
+ legacy_path = "#{Dir.pwd}/#{NODE_BP_PATH}"
+ path = run("which node").strip
+ if path && $?.success?
+ @node_preinstall_bin_path = path
+ elsif run("#{legacy_path}/node -v") && $?.success?
+ @node_preinstall_bin_path = legacy_path
+ else
+ @node_preinstall_bin_path = false
+ end
+ end
+ alias :node_js_preinstalled? :node_preinstall_bin_path
+
+ def node_not_preinstalled?
+ !node_js_preinstalled?
+ end
+
+ # Example: tmp/build_8523f77fb96a956101d00988dfeed9d4/.heroku/yarn/bin/ (without the `yarn` at the end)
+ def yarn_preinstall_bin_path
+ (yarn_preinstall_binary_path || "").chomp("/yarn")
+ end
+
+ # Example `tmp/build_8523f77fb96a956101d00988dfeed9d4/.heroku/yarn/bin/yarn`
+ def yarn_preinstall_binary_path
+ return @yarn_preinstall_binary_path if defined?(@yarn_preinstall_binary_path)
+
+ path = run("which yarn").strip
+ if path && $?.success?
+ @yarn_preinstall_binary_path = path
+ else
+ @yarn_preinstall_binary_path = false
+ end
+ end
+
+ def yarn_preinstalled?
+ yarn_preinstall_binary_path
+ end
+
+ def yarn_not_preinstalled?
+ !yarn_preinstalled?
+ end
+
+ def run_assets_precompile_rake_task
+ instrument 'ruby.run_assets_precompile_rake_task' do
+
+ precompile = rake.task("assets:precompile")
+ return true unless precompile.is_defined?
+
+ topic "Precompiling assets"
+ precompile.invoke(env: rake_env)
+ if precompile.success?
+ puts "Asset precompilation completed (#{"%.2f" % precompile.time}s)"
+ else
+ precompile_fail(precompile.output)
+ end
+ end
+ end
+
+ def precompile_fail(output)
+ mcount "fail.assets_precompile"
+ log "assets_precompile", :status => "failure"
+ msg = "Precompiling assets failed.\n"
+ if output.match(/(127\.0\.0\.1)|(org\.postgresql\.util)/)
+ msg << "Attempted to access a nonexistent database:\n"
+ msg << "https://devcenter.heroku.com/articles/pre-provision-database\n"
+ end
+
+ sprockets_version = bundler.gem_version('sprockets')
+ if output.match(/Sprockets::FileNotFound/) && (sprockets_version < Gem::Version.new('4.0.0.beta7') && sprockets_version > Gem::Version.new('4.0.0.beta4'))
+ mcount "fail.assets_precompile.file_not_found_beta"
+ msg << "If you have this file in your project\n"
+ msg << "try upgrading to Sprockets 4.0.0.beta7 or later:\n"
+ msg << "https://github.com/rails/sprockets/pull/547\n"
+ end
+
+ error msg
+ end
+
+ def bundler_cache
+ "vendor/bundle"
+ end
+
+ def valid_bundler_cache?(path, metadata)
+ full_ruby_version = run_stdout(%q(ruby -v)).strip
+ rubygems_version = run_stdout(%q(gem -v)).strip
+ old_rubygems_version = nil
+
+ old_rubygems_version = metadata[:ruby_version]
+ old_stack = metadata[:stack]
+ old_stack ||= DEFAULT_LEGACY_STACK
+
+ stack_change = old_stack != @stack
+ if !new_app? && stack_change
+ return [false, "Purging Cache. Changing stack from #{old_stack} to #{@stack}"]
+ end
+
+ # fix bug from v37 deploy
+ if File.exists?("#{path}/vendor/ruby_version")
+ puts "Broken cache detected. Purging build cache."
+ cache.clear("vendor")
+ FileUtils.rm_rf("#{path}/vendor/ruby_version")
+ return [false, "Broken cache detected. Purging build cache."]
+ # fix bug introduced in v38
+ elsif !metadata.include?(:buildpack_version) && metadata.include?(:ruby_version)
+ puts "Broken cache detected. Purging build cache."
+ return [false, "Broken cache detected. Purging build cache."]
+ elsif (@bundler_cache.exists? || @bundler_cache.old?) && full_ruby_version != metadata[:ruby_version]
+ return [false, <<-MESSAGE]
+Ruby version change detected. Clearing bundler cache.
+Old: #{metadata[:ruby_version]}
+New: #{full_ruby_version}
+MESSAGE
+ end
+
+ # fix git gemspec bug from Bundler 1.3.0+ upgrade
+ if File.exists?(bundler_cache) && !metadata.include?(:bundler_version) && !run("find #{path}/vendor/bundle/*/*/bundler/gems/*/ -name *.gemspec").include?("No such file or directory")
+ return [false, "Old bundler cache detected. Clearing bundler cache."]
+ end
+
+ # fix for https://github.com/heroku/heroku-buildpack-ruby/issues/86
+ if (!metadata.include?(:rubygems_version) ||
+ (old_rubygems_version == "2.0.0" && old_rubygems_version != rubygems_version)) &&
+ metadata.include?(:ruby_version) && metadata[:ruby_version].strip.include?("ruby 2.0.0p0")
+ return [false, "Updating to rubygems #{rubygems_version}. Clearing bundler cache."]
+ end
+
+ # fix for https://github.com/sparklemotion/nokogiri/issues/923
+ if metadata.include?(:buildpack_version) && (bv = metadata[:buildpack_version].sub('v', '').to_i) && bv != 0 && bv <= 76
+ return [false, <<-MESSAGE]
+Fixing nokogiri install. Clearing bundler cache.
+See https://github.com/sparklemotion/nokogiri/issues/923.
+MESSAGE
+ end
+
+ # recompile nokogiri to use new libyaml
+ if metadata.include?(:buildpack_version) && (bv = metadata[:buildpack_version].sub('v', '').to_i) && bv != 0 && bv <= 99 && bundler.has_gem?("psych")
+ return [false, <<-MESSAGE]
+Need to recompile psych for CVE-2013-6393. Clearing bundler cache.
+See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=737076.
+MESSAGE
+ end
+
+ # recompile gems for libyaml 0.1.7 update
+ if metadata.include?(:buildpack_version) && (bv = metadata[:buildpack_version].sub('v', '').to_i) && bv != 0 && bv <= 147 &&
+ (metadata.include?(:ruby_version) && metadata[:ruby_version].match(/ruby 2\.1\.(9|10)/) ||
+ bundler.has_gem?("psych")
+ )
+ return [false, <<-MESSAGE]
+Need to recompile gems for CVE-2014-2014-9130. Clearing bundler cache.
+See https://devcenter.heroku.com/changelog-items/1016.
+MESSAGE
+ end
+
+ true
+ end
+
+ def load_bundler_cache
+ instrument "ruby.load_bundler_cache" do
+ cache.load "vendor"
+
+ full_ruby_version = run_stdout(%q(ruby -v)).strip
+ rubygems_version = run_stdout(%q(gem -v)).strip
+ heroku_metadata = "vendor/heroku"
+ old_rubygems_version = nil
+ ruby_version_cache = "ruby_version"
+ buildpack_version_cache = "buildpack_version"
+ bundler_version_cache = "bundler_version"
+ rubygems_version_cache = "rubygems_version"
+ stack_cache = "stack"
+
+ # bundle clean does not remove binstubs
+ FileUtils.rm_rf("vendor/bundler/bin")
+
+ old_rubygems_version = @metadata.read(ruby_version_cache).strip if @metadata.exists?(ruby_version_cache)
+ old_stack = @metadata.read(stack_cache).strip if @metadata.exists?(stack_cache)
+ old_stack ||= DEFAULT_LEGACY_STACK
+
+ stack_change = old_stack != @stack
+ convert_stack = @bundler_cache.old?
+ @bundler_cache.convert_stack(stack_change) if convert_stack
+ if !new_app? && stack_change
+ puts "Purging Cache. Changing stack from #{old_stack} to #{@stack}"
+ purge_bundler_cache(old_stack)
+ elsif !new_app? && !convert_stack
+ @bundler_cache.load
+ end
+
+ # fix bug from v37 deploy
+ if File.exists?("vendor/ruby_version")
+ puts "Broken cache detected. Purging build cache."
+ cache.clear("vendor")
+ FileUtils.rm_rf("vendor/ruby_version")
+ purge_bundler_cache
+ # fix bug introduced in v38
+ elsif !@metadata.include?(buildpack_version_cache) && @metadata.exists?(ruby_version_cache)
+ puts "Broken cache detected. Purging build cache."
+ purge_bundler_cache
+ elsif (@bundler_cache.exists? || @bundler_cache.old?) && @metadata.exists?(ruby_version_cache) && full_ruby_version != @metadata.read(ruby_version_cache).strip
+ puts "Ruby version change detected. Clearing bundler cache."
+ puts "Old: #{@metadata.read(ruby_version_cache).strip}"
+ puts "New: #{full_ruby_version}"
+ purge_bundler_cache
+ end
+
+ # fix git gemspec bug from Bundler 1.3.0+ upgrade
+ if File.exists?(bundler_cache) && !@metadata.exists?(bundler_version_cache) && !run("find vendor/bundle/*/*/bundler/gems/*/ -name *.gemspec").include?("No such file or directory")
+ puts "Old bundler cache detected. Clearing bundler cache."
+ purge_bundler_cache
+ end
+
+ # fix for https://github.com/heroku/heroku-buildpack-ruby/issues/86
+ if (!@metadata.exists?(rubygems_version_cache) ||
+ (old_rubygems_version == "2.0.0" && old_rubygems_version != rubygems_version)) &&
+ @metadata.exists?(ruby_version_cache) && @metadata.read(ruby_version_cache).strip.include?("ruby 2.0.0p0")
+ puts "Updating to rubygems #{rubygems_version}. Clearing bundler cache."
+ purge_bundler_cache
+ end
+
+ # fix for https://github.com/sparklemotion/nokogiri/issues/923
+ if @metadata.exists?(buildpack_version_cache) && (bv = @metadata.read(buildpack_version_cache).sub('v', '').to_i) && bv != 0 && bv <= 76
+ puts "Fixing nokogiri install. Clearing bundler cache."
+ puts "See https://github.com/sparklemotion/nokogiri/issues/923."
+ purge_bundler_cache
+ end
+
+ # recompile nokogiri to use new libyaml
+ if @metadata.exists?(buildpack_version_cache) && (bv = @metadata.read(buildpack_version_cache).sub('v', '').to_i) && bv != 0 && bv <= 99 && bundler.has_gem?("psych")
+ puts "Need to recompile psych for CVE-2013-6393. Clearing bundler cache."
+ puts "See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=737076."
+ purge_bundler_cache
+ end
+
+ # recompile gems for libyaml 0.1.7 update
+ if @metadata.exists?(buildpack_version_cache) && (bv = @metadata.read(buildpack_version_cache).sub('v', '').to_i) && bv != 0 && bv <= 147 &&
+ (@metadata.exists?(ruby_version_cache) && @metadata.read(ruby_version_cache).strip.match(/ruby 2\.1\.(9|10)/) ||
+ bundler.has_gem?("psych")
+ )
+ puts "Need to recompile gems for CVE-2014-2014-9130. Clearing bundler cache."
+ puts "See https://devcenter.heroku.com/changelog-items/1016."
+ purge_bundler_cache
+ end
+
+ FileUtils.mkdir_p(heroku_metadata)
+ @metadata.write(ruby_version_cache, full_ruby_version, false)
+ @metadata.write(buildpack_version_cache, BUILDPACK_VERSION, false)
+ @metadata.write(bundler_version_cache, bundler.version, false)
+ @metadata.write(rubygems_version_cache, rubygems_version, false)
+ @metadata.write(stack_cache, @stack, false)
+ @metadata.save
+ end
+ end
+
+ def purge_bundler_cache(stack = nil)
+ instrument "ruby.purge_bundler_cache" do
+ @bundler_cache.clear(stack)
+ # need to reinstall language pack gems
+ install_bundler_in_app(slug_vendor_base)
+ end
+ end
+end
diff --git a/spec/syntax_suggest/fixtures/syntax_tree.rb.txt b/spec/syntax_suggest/fixtures/syntax_tree.rb.txt
new file mode 100644
index 0000000000..1c110783f9
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/syntax_tree.rb.txt
@@ -0,0 +1,9234 @@
+# frozen_string_literal: true
+
+require 'ripper'
+require_relative 'syntax_tree/version'
+
+class SyntaxTree < Ripper
+ # Represents a line in the source. If this class is being used, it means that
+ # every character in the string is 1 byte in length, so we can just return the
+ # start of the line + the index.
+ class SingleByteString
+ def initialize(start)
+ @start = start
+ end
+
+ def [](byteindex)
+ @start + byteindex
+ end
+ end
+
+ # Represents a line in the source. If this class is being used, it means that
+ # there are characters in the string that are multi-byte, so we will build up
+ # an array of indices, such that array[byteindex] will be equal to the index
+ # of the character within the string.
+ class MultiByteString
+ def initialize(start, line)
+ @indices = []
+
+ line
+ .each_char
+ .with_index(start) do |char, index|
+ char.bytesize.times { @indices << index }
+ end
+ end
+
+ def [](byteindex)
+ @indices[byteindex]
+ end
+ end
+
+ # Represents the location of a node in the tree from the source code.
+ class Location
+ attr_reader :start_line, :start_char, :end_line, :end_char
+
+ def initialize(start_line:, start_char:, end_line:, end_char:)
+ @start_line = start_line
+ @start_char = start_char
+ @end_line = end_line
+ @end_char = end_char
+ end
+
+ def ==(other)
+ other.is_a?(Location) && start_line == other.start_line &&
+ start_char == other.start_char && end_line == other.end_line &&
+ end_char == other.end_char
+ end
+
+ def to(other)
+ Location.new(
+ start_line: start_line,
+ start_char: start_char,
+ end_line: other.end_line,
+ end_char: other.end_char
+ )
+ end
+
+ def to_json(*opts)
+ [start_line, start_char, end_line, end_char].to_json(*opts)
+ end
+
+ def self.token(line:, char:, size:)
+ new(
+ start_line: line,
+ start_char: char,
+ end_line: line,
+ end_char: char + size
+ )
+ end
+
+ def self.fixed(line:, char:)
+ new(start_line: line, start_char: char, end_line: line, end_char: char)
+ end
+ end
+
+ # A special parser error so that we can get nice syntax displays on the error
+ # message when prettier prints out the results.
+ class ParseError < StandardError
+ attr_reader :lineno, :column
+
+ def initialize(error, lineno, column)
+ super(error)
+ @lineno = lineno
+ @column = column
+ end
+ end
+
+ attr_reader :source, :lines, :tokens
+
+ # This is an attr_accessor so Stmts objects can grab comments out of this
+ # array and attach them to themselves.
+ attr_accessor :comments
+
+ def initialize(source, *)
+ super
+
+ # We keep the source around so that we can refer back to it when we're
+ # generating the AST. Sometimes it's easier to just reference the source
+ # string when you want to check if it contains a certain character, for
+ # example.
+ @source = source
+
+ # Similarly, we keep the lines of the source string around to be able to
+ # check if certain lines contain certain characters. For example, we'll use
+ # this to generate the content that goes after the __END__ keyword. Or we'll
+ # use this to check if a comment has other content on its line.
+ @lines = source.split("\n")
+
+ # This is the full set of comments that have been found by the parser. It's
+ # a running list. At the end of every block of statements, they will go in
+ # and attempt to grab any comments that are on their own line and turn them
+ # into regular statements. So at the end of parsing the only comments left
+ # in here will be comments on lines that also contain code.
+ @comments = []
+
+ # This is the current embdoc (comments that start with =begin and end with
+ # =end). Since they can't be nested, there's no need for a stack here, as
+ # there can only be one active. These end up getting dumped into the
+ # comments list before getting picked up by the statements that surround
+ # them.
+ @embdoc = nil
+
+ # This is an optional node that can be present if the __END__ keyword is
+ # used in the file. In that case, this will represent the content after that
+ # keyword.
+ @__end__ = nil
+
+ # Heredocs can actually be nested together if you're using interpolation, so
+ # this is a stack of heredoc nodes that are currently being created. When we
+ # get to the token that finishes off a heredoc node, we pop the top
+ # one off. If there are others surrounding it, then the body events will now
+ # be added to the correct nodes.
+ @heredocs = []
+
+ # This is a running list of tokens that have fired. It's useful
+ # mostly for maintaining location information. For example, if you're inside
+ # the handle of a def event, then in order to determine where the AST node
+ # started, you need to look backward in the tokens to find a def
+ # keyword. Most of the time, when a parser event consumes one of these
+ # events, it will be deleted from the list. So ideally, this list stays
+ # pretty short over the course of parsing a source string.
+ @tokens = []
+
+ # Here we're going to build up a list of SingleByteString or MultiByteString
+ # objects. They're each going to represent a string in the source. They are
+ # used by the `char_pos` method to determine where we are in the source
+ # string.
+ @line_counts = []
+ last_index = 0
+
+ @source.lines.each do |line|
+ if line.size == line.bytesize
+ @line_counts << SingleByteString.new(last_index)
+ else
+ @line_counts << MultiByteString.new(last_index, line)
+ end
+
+ last_index += line.size
+ end
+ end
+
+ def self.parse(source)
+ parser = new(source)
+ response = parser.parse
+ response unless parser.error?
+ end
+
+ private
+
+ # ----------------------------------------------------------------------------
+ # :section: Helper methods
+ # The following methods are used by the ripper event handlers to either
+ # determine their bounds or query other nodes.
+ # ----------------------------------------------------------------------------
+
+ # This represents the current place in the source string that we've gotten to
+ # so far. We have a memoized line_counts object that we can use to get the
+ # number of characters that we've had to go through to get to the beginning of
+ # this line, then we add the number of columns into this line that we've gone
+ # through.
+ def char_pos
+ @line_counts[lineno - 1][column]
+ end
+
+ # As we build up a list of tokens, we'll periodically need to go backwards and
+ # find the ones that we've already hit in order to determine the location
+ # information for nodes that use them. For example, if you have a module node
+ # then you'll look backward for a kw token to determine your start location.
+ #
+ # This works with nesting since we're deleting tokens from the list once
+ # they've been used up. For example if you had nested module declarations then
+ # the innermost declaration would grab the last kw node that matches "module"
+ # (which would happen to be the innermost keyword). Then the outer one would
+ # only be able to grab the first one. In this way all of the tokens act as
+ # their own stack.
+ def find_token(type, value = :any, consume: true)
+ index =
+ tokens.rindex do |token|
+ token.is_a?(type) && (value == :any || (token.value == value))
+ end
+
+ if consume
+ # If we're expecting to be able to find a token and consume it,
+ # but can't actually find it, then we need to raise an error. This is
+ # _usually_ caused by a syntax error in the source that we're printing. It
+ # could also be caused by accidentally attempting to consume a token twice
+ # by two different parser event handlers.
+ unless index
+ message = "Cannot find expected #{value == :any ? type : value}"
+ raise ParseError.new(message, lineno, column)
+ end
+
+ tokens.delete_at(index)
+ elsif index
+ tokens[index]
+ end
+ end
+
+ # A helper function to find a :: operator. We do special handling instead of
+ # using find_token here because we don't pop off all of the ::
+ # operators so you could end up getting the wrong information if you have for
+ # instance ::X::Y::Z.
+ def find_colon2_before(const)
+ index =
+ tokens.rindex do |token|
+ token.is_a?(Op) && token.value == '::' &&
+ token.location.start_char < const.location.start_char
+ end
+
+ tokens[index]
+ end
+
+ # Finds the next position in the source string that begins a statement. This
+ # is used to bind statements lists and make sure they don't include a
+ # preceding comment. For example, we want the following comment to be attached
+ # to the class node and not the statement node:
+ #
+ # class Foo # :nodoc:
+ # ...
+ # end
+ #
+ # By finding the next non-space character, we can make sure that the bounds of
+ # the statement list are correct.
+ def find_next_statement_start(position)
+ remaining = source[position..-1]
+
+ if remaining.sub(/\A +/, '')[0] == '#'
+ return position + remaining.index("\n")
+ end
+
+ position
+ end
+
+ # ----------------------------------------------------------------------------
+ # :section: Ripper event handlers
+ # The following methods all handle a dispatched ripper event.
+ # ----------------------------------------------------------------------------
+
+ # BEGINBlock represents the use of the +BEGIN+ keyword, which hooks into the
+ # lifecycle of the interpreter. Whatever is inside the block will get executed
+ # when the program starts.
+ #
+ # BEGIN {
+ # }
+ #
+ # Interestingly, the BEGIN keyword doesn't allow the do and end keywords for
+ # the block. Only braces are permitted.
+ class BEGINBlock
+ # [LBrace] the left brace that is seen after the keyword
+ attr_reader :lbrace
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(lbrace:, statements:, location:)
+ @lbrace = lbrace
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('BEGIN')
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :BEGIN,
+ lbrace: lbrace,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_BEGIN: (Statements statements) -> BEGINBlock
+ def on_BEGIN(statements)
+ lbrace = find_token(LBrace)
+ rbrace = find_token(RBrace)
+
+ statements.bind(
+ find_next_statement_start(lbrace.location.end_char),
+ rbrace.location.start_char
+ )
+
+ keyword = find_token(Kw, 'BEGIN')
+
+ BEGINBlock.new(
+ lbrace: lbrace,
+ statements: statements,
+ location: keyword.location.to(rbrace.location)
+ )
+ end
+
+ # CHAR irepresents a single codepoint in the script encoding.
+ #
+ # ?a
+ #
+ # In the example above, the CHAR node represents the string literal "a". You
+ # can use control characters with this as well, as in ?\C-a.
+ class CHAR
+ # [String] the value of the character literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('CHAR')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :CHAR, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_CHAR: (String value) -> CHAR
+ def on_CHAR(value)
+ node =
+ CHAR.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # ENDBlock represents the use of the +END+ keyword, which hooks into the
+ # lifecycle of the interpreter. Whatever is inside the block will get executed
+ # when the program ends.
+ #
+ # END {
+ # }
+ #
+ # Interestingly, the END keyword doesn't allow the do and end keywords for the
+ # block. Only braces are permitted.
+ class ENDBlock
+ # [LBrace] the left brace that is seen after the keyword
+ attr_reader :lbrace
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(lbrace:, statements:, location:)
+ @lbrace = lbrace
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('END')
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :END, lbrace: lbrace, stmts: statements, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_END: (Statements statements) -> ENDBlock
+ def on_END(statements)
+ lbrace = find_token(LBrace)
+ rbrace = find_token(RBrace)
+
+ statements.bind(
+ find_next_statement_start(lbrace.location.end_char),
+ rbrace.location.start_char
+ )
+
+ keyword = find_token(Kw, 'END')
+
+ ENDBlock.new(
+ lbrace: lbrace,
+ statements: statements,
+ location: keyword.location.to(rbrace.location)
+ )
+ end
+
+ # EndContent represents the use of __END__ syntax, which allows individual
+ # scripts to keep content after the main ruby code that can be read through
+ # the DATA constant.
+ #
+ # puts DATA.read
+ #
+ # __END__
+ # some other content that is not executed by the program
+ #
+ class EndContent
+ # [String] the content after the script
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('__end__')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :__end__, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on___end__: (String value) -> EndContent
+ def on___end__(value)
+ @__end__ =
+ EndContent.new(
+ value: lines[lineno..-1].join("\n"),
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+ end
+
+ # Alias represents the use of the +alias+ keyword with regular arguments (not
+ # global variables). The +alias+ keyword is used to make a method respond to
+ # another name as well as the current one.
+ #
+ # alias aliased_name name
+ #
+ # For the example above, in the current context you can now call aliased_name
+ # and it will execute the name method. When you're aliasing two methods, you
+ # can either provide bare words (like the example above) or you can provide
+ # symbols (note that this includes dynamic symbols like
+ # :"left-#{middle}-right").
+ class Alias
+ # [DynaSymbol | SymbolLiteral] the new name of the method
+ attr_reader :left
+
+ # [DynaSymbol | SymbolLiteral] the old name of the method
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(left:, right:, location:)
+ @left = left
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('alias')
+ q.breakable
+ q.pp(left)
+ q.breakable
+ q.pp(right)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :alias, left: left, right: right, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_alias: (
+ # (DynaSymbol | SymbolLiteral) left,
+ # (DynaSymbol | SymbolLiteral) right
+ # ) -> Alias
+ def on_alias(left, right)
+ keyword = find_token(Kw, 'alias')
+
+ Alias.new(
+ left: left,
+ right: right,
+ location: keyword.location.to(right.location)
+ )
+ end
+
+ # ARef represents when you're pulling a value out of a collection at a
+ # specific index. Put another way, it's any time you're calling the method
+ # #[].
+ #
+ # collection[index]
+ #
+ # The nodes usually contains two children, the collection and the index. In
+ # some cases, you don't necessarily have the second child node, because you
+ # can call procs with a pretty esoteric syntax. In the following example, you
+ # wouldn't have a second child node:
+ #
+ # collection[]
+ #
+ class ARef
+ # [untyped] the value being indexed
+ attr_reader :collection
+
+ # [nil | Args | ArgsAddBlock] the value being passed within the brackets
+ attr_reader :index
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(collection:, index:, location:)
+ @collection = collection
+ @index = index
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('aref')
+ q.breakable
+ q.pp(collection)
+ q.breakable
+ q.pp(index)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :aref,
+ collection: collection,
+ index: index,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_aref: (untyped collection, (nil | Args | ArgsAddBlock) index) -> ARef
+ def on_aref(collection, index)
+ find_token(LBracket)
+ rbracket = find_token(RBracket)
+
+ ARef.new(
+ collection: collection,
+ index: index,
+ location: collection.location.to(rbracket.location)
+ )
+ end
+
+ # ARefField represents assigning values into collections at specific indices.
+ # Put another way, it's any time you're calling the method #[]=. The
+ # ARefField node itself is just the left side of the assignment, and they're
+ # always wrapped in assign nodes.
+ #
+ # collection[index] = value
+ #
+ class ARefField
+ # [untyped] the value being indexed
+ attr_reader :collection
+
+ # [nil | ArgsAddBlock] the value being passed within the brackets
+ attr_reader :index
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(collection:, index:, location:)
+ @collection = collection
+ @index = index
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('aref_field')
+ q.breakable
+ q.pp(collection)
+ q.breakable
+ q.pp(index)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :aref_field,
+ collection: collection,
+ index: index,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_aref_field: (
+ # untyped collection,
+ # (nil | ArgsAddBlock) index
+ # ) -> ARefField
+ def on_aref_field(collection, index)
+ find_token(LBracket)
+ rbracket = find_token(RBracket)
+
+ ARefField.new(
+ collection: collection,
+ index: index,
+ location: collection.location.to(rbracket.location)
+ )
+ end
+
+ # def on_arg_ambiguous(value)
+ # value
+ # end
+
+ # ArgParen represents wrapping arguments to a method inside a set of
+ # parentheses.
+ #
+ # method(argument)
+ #
+ # In the example above, there would be an ArgParen node around the
+ # ArgsAddBlock node that represents the set of arguments being sent to the
+ # method method. The argument child node can be +nil+ if no arguments were
+ # passed, as in:
+ #
+ # method()
+ #
+ class ArgParen
+ # [nil | Args | ArgsAddBlock | ArgsForward] the arguments inside the
+ # parentheses
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('arg_paren')
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :arg_paren, args: arguments, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_arg_paren: (
+ # (nil | Args | ArgsAddBlock | ArgsForward) arguments
+ # ) -> ArgParen
+ def on_arg_paren(arguments)
+ lparen = find_token(LParen)
+ rparen = find_token(RParen)
+
+ # If the arguments exceed the ending of the parentheses, then we know we
+ # have a heredoc in the arguments, and we need to use the bounds of the
+ # arguments to determine how large the arg_paren is.
+ ending =
+ if arguments && arguments.location.end_line > rparen.location.end_line
+ arguments
+ else
+ rparen
+ end
+
+ ArgParen.new(
+ arguments: arguments,
+ location: lparen.location.to(ending.location)
+ )
+ end
+
+ # Args represents a list of arguments being passed to a method call or array
+ # literal.
+ #
+ # method(first, second, third)
+ #
+ class Args
+ # [Array[ untyped ]] the arguments that this node wraps
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, location:)
+ @parts = parts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('args')
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :args, parts: parts, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_args_add: (Args arguments, untyped argument) -> Args
+ def on_args_add(arguments, argument)
+ if arguments.parts.empty?
+ # If this is the first argument being passed into the list of arguments,
+ # then we're going to use the bounds of the argument to override the
+ # parent node's location since this will be more accurate.
+ Args.new(parts: [argument], location: argument.location)
+ else
+ # Otherwise we're going to update the existing list with the argument
+ # being added as well as the new end bounds.
+ Args.new(
+ parts: arguments.parts << argument,
+ location: arguments.location.to(argument.location)
+ )
+ end
+ end
+
+ # ArgsAddBlock represents a list of arguments and potentially a block
+ # argument. ArgsAddBlock is commonly seen being passed to any method where you
+ # use parentheses (wrapped in an ArgParen node). It’s also used to pass
+ # arguments to the various control-flow keywords like +return+.
+ #
+ # method(argument, &block)
+ #
+ class ArgsAddBlock
+ # [Args] the arguments before the optional block
+ attr_reader :arguments
+
+ # [nil | untyped] the optional block argument
+ attr_reader :block
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, block:, location:)
+ @arguments = arguments
+ @block = block
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('args_add_block')
+ q.breakable
+ q.pp(arguments)
+ q.breakable
+ q.pp(block)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :args_add_block,
+ args: arguments,
+ block: block,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_args_add_block: (
+ # Args arguments,
+ # (false | untyped) block
+ # ) -> ArgsAddBlock
+ def on_args_add_block(arguments, block)
+ ending = block || arguments
+
+ ArgsAddBlock.new(
+ arguments: arguments,
+ block: block || nil,
+ location: arguments.location.to(ending.location)
+ )
+ end
+
+ # Star represents using a splat operator on an expression.
+ #
+ # method(*arguments)
+ #
+ class ArgStar
+ # [untyped] the expression being splatted
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('arg_star')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :arg_star, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_args_add_star: (Args arguments, untyped star) -> Args
+ def on_args_add_star(arguments, argument)
+ beginning = find_token(Op, '*')
+ ending = argument || beginning
+
+ location =
+ if arguments.parts.empty?
+ ending.location
+ else
+ arguments.location.to(ending.location)
+ end
+
+ arg_star =
+ ArgStar.new(
+ value: argument,
+ location: beginning.location.to(ending.location)
+ )
+
+ Args.new(parts: arguments.parts << arg_star, location: location)
+ end
+
+ # ArgsForward represents forwarding all kinds of arguments onto another method
+ # call.
+ #
+ # def request(method, path, **headers, &block); end
+ #
+ # def get(...)
+ # request(:GET, ...)
+ # end
+ #
+ # def post(...)
+ # request(:POST, ...)
+ # end
+ #
+ # In the example above, both the get and post methods are forwarding all of
+ # their arguments (positional, keyword, and block) on to the request method.
+ # The ArgsForward node appears in both the caller (the request method calls)
+ # and the callee (the get and post definitions).
+ class ArgsForward
+ # [String] the value of the operator
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('args_forward')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :args_forward, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_args_forward: () -> ArgsForward
+ def on_args_forward
+ op = find_token(Op, '...')
+
+ ArgsForward.new(value: op.value, location: op.location)
+ end
+
+ # :call-seq:
+ # on_args_new: () -> Args
+ def on_args_new
+ Args.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
+ end
+
+ # ArrayLiteral represents any form of an array literal, and contains myriad
+ # child nodes because of the special array literal syntax like %w and %i.
+ #
+ # []
+ # [one, two, three]
+ # [*one_two_three]
+ # %i[one two three]
+ # %w[one two three]
+ # %I[one two three]
+ # %W[one two three]
+ #
+ # Every line in the example above produces an ArrayLiteral node. In order, the
+ # child contents node of this ArrayLiteral node would be nil, Args, QSymbols,
+ # QWords, Symbols, and Words.
+ class ArrayLiteral
+ # [nil | Args | QSymbols | QWords | Symbols | Words] the
+ # contents of the array
+ attr_reader :contents
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(contents:, location:)
+ @contents = contents
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('array')
+ q.breakable
+ q.pp(contents)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :array, cnts: contents, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_array: (
+ # (nil | Args | QSymbols | QWords | Symbols | Words) contents
+ # ) -> ArrayLiteral
+ def on_array(contents)
+ if !contents || contents.is_a?(Args)
+ lbracket = find_token(LBracket)
+ rbracket = find_token(RBracket)
+
+ ArrayLiteral.new(
+ contents: contents,
+ location: lbracket.location.to(rbracket.location)
+ )
+ else
+ tstring_end = find_token(TStringEnd)
+ contents =
+ contents.class.new(
+ elements: contents.elements,
+ location: contents.location.to(tstring_end.location)
+ )
+
+ ArrayLiteral.new(contents: contents, location: contents.location)
+ end
+ end
+
+ # AryPtn represents matching against an array pattern using the Ruby 2.7+
+ # pattern matching syntax. It’s one of the more complicated nodes, because
+ # the four parameters that it accepts can almost all be nil.
+ #
+ # case [1, 2, 3]
+ # in [Integer, Integer]
+ # "matched"
+ # in Container[Integer, Integer]
+ # "matched"
+ # in [Integer, *, Integer]
+ # "matched"
+ # end
+ #
+ # An AryPtn node is created with four parameters: an optional constant
+ # wrapper, an array of positional matches, an optional splat with identifier,
+ # and an optional array of positional matches that occur after the splat.
+ # All of the in clauses above would create an AryPtn node.
+ class AryPtn
+ # [nil | VarRef] the optional constant wrapper
+ attr_reader :constant
+
+ # [Array[ untyped ]] the regular positional arguments that this array
+ # pattern is matching against
+ attr_reader :requireds
+
+ # [nil | VarField] the optional starred identifier that grabs up a list of
+ # positional arguments
+ attr_reader :rest
+
+ # [Array[ untyped ]] the list of positional arguments occurring after the
+ # optional star if there is one
+ attr_reader :posts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, requireds:, rest:, posts:, location:)
+ @constant = constant
+ @requireds = requireds
+ @rest = rest
+ @posts = posts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('aryptn')
+
+ if constant
+ q.breakable
+ q.pp(constant)
+ end
+
+ if requireds.any?
+ q.breakable
+ q.group(2, '(', ')') do
+ q.seplist(requireds) { |required| q.pp(required) }
+ end
+ end
+
+ if rest
+ q.breakable
+ q.pp(rest)
+ end
+
+ if posts.any?
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(posts) { |post| q.pp(post) } }
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :aryptn,
+ constant: constant,
+ reqs: requireds,
+ rest: rest,
+ posts: posts,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_aryptn: (
+ # (nil | VarRef) constant,
+ # (nil | Array[untyped]) requireds,
+ # (nil | VarField) rest,
+ # (nil | Array[untyped]) posts
+ # ) -> AryPtn
+ def on_aryptn(constant, requireds, rest, posts)
+ parts = [constant, *requireds, rest, *posts].compact
+
+ AryPtn.new(
+ constant: constant,
+ requireds: requireds || [],
+ rest: rest,
+ posts: posts || [],
+ location: parts[0].location.to(parts[-1].location)
+ )
+ end
+
+ # Assign represents assigning something to a variable or constant. Generally,
+ # the left side of the assignment is going to be any node that ends with the
+ # name "Field".
+ #
+ # variable = value
+ #
+ class Assign
+ # [ARefField | ConstPathField | Field | TopConstField | VarField] the target
+ # to assign the result of the expression to
+ attr_reader :target
+
+ # [untyped] the expression to be assigned
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(target:, value:, location:)
+ @target = target
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('assign')
+ q.breakable
+ q.pp(target)
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :assign, target: target, value: value, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_assign: (
+ # (ARefField | ConstPathField | Field | TopConstField | VarField) target,
+ # untyped value
+ # ) -> Assign
+ def on_assign(target, value)
+ Assign.new(
+ target: target,
+ value: value,
+ location: target.location.to(value.location)
+ )
+ end
+
+ # Assoc represents a key-value pair within a hash. It is a child node of
+ # either an AssocListFromArgs or a BareAssocHash.
+ #
+ # { key1: value1, key2: value2 }
+ #
+ # In the above example, the would be two AssocNew nodes.
+ class Assoc
+ # [untyped] the key of this pair
+ attr_reader :key
+
+ # [untyped] the value of this pair
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(key:, value:, location:)
+ @key = key
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('assoc')
+ q.breakable
+ q.pp(key)
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :assoc, key: key, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_assoc_new: (untyped key, untyped value) -> Assoc
+ def on_assoc_new(key, value)
+ Assoc.new(
+ key: key,
+ value: value,
+ location: key.location.to(value.location)
+ )
+ end
+
+ # AssocSplat represents double-splatting a value into a hash (either a hash
+ # literal or a bare hash in a method call).
+ #
+ # { **pairs }
+ #
+ class AssocSplat
+ # [untyped] the expression that is being splatted
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('assoc_splat')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :assoc_splat, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_assoc_splat: (untyped value) -> AssocSplat
+ def on_assoc_splat(value)
+ operator = find_token(Op, '**')
+
+ AssocSplat.new(value: value, location: operator.location.to(value.location))
+ end
+
+ # AssocListFromArgs represents the key-value pairs of a hash literal. Its
+ # parent node is always a hash.
+ #
+ # { key1: value1, key2: value2 }
+ #
+ class AssocListFromArgs
+ # [Array[ AssocNew | AssocSplat ]]
+ attr_reader :assocs
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(assocs:, location:)
+ @assocs = assocs
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('assoclist_from_args')
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(assocs) { |assoc| q.pp(assoc) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :assoclist_from_args, assocs: assocs, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_assoclist_from_args: (
+ # Array[AssocNew | AssocSplat] assocs
+ # ) -> AssocListFromArgs
+ def on_assoclist_from_args(assocs)
+ AssocListFromArgs.new(
+ assocs: assocs,
+ location: assocs[0].location.to(assocs[-1].location)
+ )
+ end
+
+ # Backref represents a global variable referencing a matched value. It comes
+ # in the form of a $ followed by a positive integer.
+ #
+ # $1
+ #
+ class Backref
+ # [String] the name of the global backreference variable
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('backref')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :backref, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_backref: (String value) -> Backref
+ def on_backref(value)
+ node =
+ Backref.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Backtick represents the use of the ` operator. It's usually found being used
+ # for an XStringLiteral, but could also be found as the name of a method being
+ # defined.
+ class Backtick
+ # [String] the backtick in the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('backtick')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :backtick, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_backtick: (String value) -> Backtick
+ def on_backtick(value)
+ node =
+ Backtick.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # BareAssocHash represents a hash of contents being passed as a method
+ # argument (and therefore has omitted braces). It's very similar to an
+ # AssocListFromArgs node.
+ #
+ # method(key1: value1, key2: value2)
+ #
+ class BareAssocHash
+ # [Array[ AssocNew | AssocSplat ]]
+ attr_reader :assocs
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(assocs:, location:)
+ @assocs = assocs
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('bare_assoc_hash')
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(assocs) { |assoc| q.pp(assoc) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :bare_assoc_hash, assocs: assocs, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_bare_assoc_hash: (Array[AssocNew | AssocSplat] assocs) -> BareAssocHash
+ def on_bare_assoc_hash(assocs)
+ BareAssocHash.new(
+ assocs: assocs,
+ location: assocs[0].location.to(assocs[-1].location)
+ )
+ end
+
+ # Begin represents a begin..end chain.
+ #
+ # begin
+ # value
+ # end
+ #
+ class Begin
+ # [BodyStmt] the bodystmt that contains the contents of this begin block
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(bodystmt:, location:)
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('begin')
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :begin, bodystmt: bodystmt, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_begin: (BodyStmt bodystmt) -> Begin
+ def on_begin(bodystmt)
+ keyword = find_token(Kw, 'begin')
+ end_char =
+ if bodystmt.rescue_clause || bodystmt.ensure_clause ||
+ bodystmt.else_clause
+ bodystmt.location.end_char
+ else
+ find_token(Kw, 'end').location.end_char
+ end
+
+ bodystmt.bind(keyword.location.end_char, end_char)
+
+ Begin.new(
+ bodystmt: bodystmt,
+ location: keyword.location.to(bodystmt.location)
+ )
+ end
+
+ # Binary represents any expression that involves two sub-expressions with an
+ # operator in between. This can be something that looks like a mathematical
+ # operation:
+ #
+ # 1 + 1
+ #
+ # but can also be something like pushing a value onto an array:
+ #
+ # array << value
+ #
+ class Binary
+ # [untyped] the left-hand side of the expression
+ attr_reader :left
+
+ # [String] the operator used between the two expressions
+ attr_reader :operator
+
+ # [untyped] the right-hand side of the expression
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(left:, operator:, right:, location:)
+ @left = left
+ @operator = operator
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('binary')
+ q.breakable
+ q.pp(left)
+ q.breakable
+ q.text(operator)
+ q.breakable
+ q.pp(right)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :binary,
+ left: left,
+ op: operator,
+ right: right,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_binary: (untyped left, (Op | Symbol) operator, untyped right) -> Binary
+ def on_binary(left, operator, right)
+ # On most Ruby implementations, operator is a Symbol that represents that
+ # operation being performed. For instance in the example `1 < 2`, the
+ # `operator` object would be `:<`. However, on JRuby, it's an `@op` node,
+ # so here we're going to explicitly convert it into the same normalized
+ # form.
+ operator = tokens.delete(operator).value unless operator.is_a?(Symbol)
+
+ Binary.new(
+ left: left,
+ operator: operator,
+ right: right,
+ location: left.location.to(right.location)
+ )
+ end
+
+ # BlockVar represents the parameters being declared for a block. Effectively
+ # this node is everything contained within the pipes. This includes all of the
+ # various parameter types, as well as block-local variable declarations.
+ #
+ # method do |positional, optional = value, keyword:, &block; local|
+ # end
+ #
+ class BlockVar
+ # [Params] the parameters being declared with the block
+ attr_reader :params
+
+ # [Array[ Ident ]] the list of block-local variable declarations
+ attr_reader :locals
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(params:, locals:, location:)
+ @params = params
+ @locals = locals
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('block_var')
+ q.breakable
+ q.pp(params)
+
+ if locals.any?
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(locals) { |local| q.pp(local) } }
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :block_var,
+ params: params,
+ locals: locals,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_block_var: (Params params, (nil | Array[Ident]) locals) -> BlockVar
+ def on_block_var(params, locals)
+ index =
+ tokens.rindex do |node|
+ node.is_a?(Op) && %w[| ||].include?(node.value) &&
+ node.location.start_char < params.location.start_char
+ end
+
+ beginning = tokens[index]
+ ending = tokens[-1]
+
+ BlockVar.new(
+ params: params,
+ locals: locals || [],
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # BlockArg represents declaring a block parameter on a method definition.
+ #
+ # def method(&block); end
+ #
+ class BlockArg
+ # [Ident] the name of the block argument
+ attr_reader :name
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(name:, location:)
+ @name = name
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('blockarg')
+ q.breakable
+ q.pp(name)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :blockarg, name: name, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_blockarg: (Ident name) -> BlockArg
+ def on_blockarg(name)
+ operator = find_token(Op, '&')
+
+ BlockArg.new(name: name, location: operator.location.to(name.location))
+ end
+
+ # bodystmt can't actually determine its bounds appropriately because it
+ # doesn't necessarily know where it started. So the parent node needs to
+ # report back down into this one where it goes.
+ class BodyStmt
+ # [Statements] the list of statements inside the begin clause
+ attr_reader :statements
+
+ # [nil | Rescue] the optional rescue chain attached to the begin clause
+ attr_reader :rescue_clause
+
+ # [nil | Statements] the optional set of statements inside the else clause
+ attr_reader :else_clause
+
+ # [nil | Ensure] the optional ensure clause
+ attr_reader :ensure_clause
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(
+ statements:,
+ rescue_clause:,
+ else_clause:,
+ ensure_clause:,
+ location:
+ )
+ @statements = statements
+ @rescue_clause = rescue_clause
+ @else_clause = else_clause
+ @ensure_clause = ensure_clause
+ @location = location
+ end
+
+ def bind(start_char, end_char)
+ @location =
+ Location.new(
+ start_line: location.start_line,
+ start_char: start_char,
+ end_line: location.end_line,
+ end_char: end_char
+ )
+
+ parts = [rescue_clause, else_clause, ensure_clause]
+
+ # Here we're going to determine the bounds for the statements
+ consequent = parts.compact.first
+ statements.bind(
+ start_char,
+ consequent ? consequent.location.start_char : end_char
+ )
+
+ # Next we're going to determine the rescue clause if there is one
+ if rescue_clause
+ consequent = parts.drop(1).compact.first
+ rescue_clause.bind_end(
+ consequent ? consequent.location.start_char : end_char
+ )
+ end
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('bodystmt')
+ q.breakable
+ q.pp(statements)
+
+ if rescue_clause
+ q.breakable
+ q.pp(rescue_clause)
+ end
+
+ if else_clause
+ q.breakable
+ q.pp(else_clause)
+ end
+
+ if ensure_clause
+ q.breakable
+ q.pp(ensure_clause)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :bodystmt,
+ stmts: statements,
+ rsc: rescue_clause,
+ els: else_clause,
+ ens: ensure_clause,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_bodystmt: (
+ # Statements statements,
+ # (nil | Rescue) rescue_clause,
+ # (nil | Statements) else_clause,
+ # (nil | Ensure) ensure_clause
+ # ) -> BodyStmt
+ def on_bodystmt(statements, rescue_clause, else_clause, ensure_clause)
+ BodyStmt.new(
+ statements: statements,
+ rescue_clause: rescue_clause,
+ else_clause: else_clause,
+ ensure_clause: ensure_clause,
+ location: Location.fixed(line: lineno, char: char_pos)
+ )
+ end
+
+ # BraceBlock represents passing a block to a method call using the { }
+ # operators.
+ #
+ # method { |variable| variable + 1 }
+ #
+ class BraceBlock
+ # [LBrace] the left brace that opens this block
+ attr_reader :lbrace
+
+ # [nil | BlockVar] the optional set of parameters to the block
+ attr_reader :block_var
+
+ # [Statements] the list of expressions to evaluate within the block
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(lbrace:, block_var:, statements:, location:)
+ @lbrace = lbrace
+ @block_var = block_var
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('brace_block')
+
+ if block_var
+ q.breakable
+ q.pp(block_var)
+ end
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :brace_block,
+ lbrace: lbrace,
+ block_var: block_var,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_brace_block: (
+ # (nil | BlockVar) block_var,
+ # Statements statements
+ # ) -> BraceBlock
+ def on_brace_block(block_var, statements)
+ lbrace = find_token(LBrace)
+ rbrace = find_token(RBrace)
+
+ statements.bind(
+ find_next_statement_start((block_var || lbrace).location.end_char),
+ rbrace.location.start_char
+ )
+
+ location =
+ Location.new(
+ start_line: lbrace.location.start_line,
+ start_char: lbrace.location.start_char,
+ end_line: [rbrace.location.end_line, statements.location.end_line].max,
+ end_char: rbrace.location.end_char
+ )
+
+ BraceBlock.new(
+ lbrace: lbrace,
+ block_var: block_var,
+ statements: statements,
+ location: location
+ )
+ end
+
+ # Break represents using the +break+ keyword.
+ #
+ # break
+ #
+ # It can also optionally accept arguments, as in:
+ #
+ # break 1
+ #
+ class Break
+ # [Args | ArgsAddBlock] the arguments being sent to the keyword
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('break')
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :break, args: arguments, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_break: ((Args | ArgsAddBlock) arguments) -> Break
+ def on_break(arguments)
+ keyword = find_token(Kw, 'break')
+
+ location = keyword.location
+ location = location.to(arguments.location) unless arguments.is_a?(Args)
+
+ Break.new(arguments: arguments, location: location)
+ end
+
+ # Call represents a method call. This node doesn't contain the arguments being
+ # passed (if arguments are passed, this node will get nested under a
+ # MethodAddArg node).
+ #
+ # receiver.message
+ #
+ class Call
+ # [untyped] the receiver of the method call
+ attr_reader :receiver
+
+ # [:"::" | Op | Period] the operator being used to send the message
+ attr_reader :operator
+
+ # [:call | Backtick | Const | Ident | Op] the message being sent
+ attr_reader :message
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(receiver:, operator:, message:, location:)
+ @receiver = receiver
+ @operator = operator
+ @message = message
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('call')
+ q.breakable
+ q.pp(receiver)
+ q.breakable
+ q.pp(operator)
+ q.breakable
+ q.pp(message)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :call,
+ receiver: receiver,
+ op: operator,
+ message: message,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_call: (
+ # untyped receiver,
+ # (:"::" | Op | Period) operator,
+ # (:call | Backtick | Const | Ident | Op) message
+ # ) -> Call
+ def on_call(receiver, operator, message)
+ ending = message
+ ending = operator if message == :call
+
+ Call.new(
+ receiver: receiver,
+ operator: operator,
+ message: message,
+ location:
+ Location.new(
+ start_line: receiver.location.start_line,
+ start_char: receiver.location.start_char,
+ end_line: [ending.location.end_line, receiver.location.end_line].max,
+ end_char: ending.location.end_char
+ )
+ )
+ end
+
+ # Case represents the beginning of a case chain.
+ #
+ # case value
+ # when 1
+ # "one"
+ # when 2
+ # "two"
+ # else
+ # "number"
+ # end
+ #
+ class Case
+ # [nil | untyped] optional value being switched on
+ attr_reader :value
+
+ # [In | When] the next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, consequent:, location:)
+ @value = value
+ @consequent = consequent
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('case')
+
+ if value
+ q.breakable
+ q.pp(value)
+ end
+
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :case, value: value, cons: consequent, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # RAssign represents a single-line pattern match.
+ #
+ # value in pattern
+ # value => pattern
+ #
+ class RAssign
+ # [untyped] the left-hand expression
+ attr_reader :value
+
+ # [Kw | Op] the operator being used to match against the pattern, which is
+ # either => or in
+ attr_reader :operator
+
+ # [untyped] the pattern on the right-hand side of the expression
+ attr_reader :pattern
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, operator:, pattern:, location:)
+ @value = value
+ @operator = operator
+ @pattern = pattern
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('rassign')
+
+ q.breakable
+ q.pp(value)
+
+ q.breakable
+ q.pp(operator)
+
+ q.breakable
+ q.pp(pattern)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :rassign,
+ value: value,
+ op: operator,
+ pattern: pattern,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_case: (untyped value, untyped consequent) -> Case | RAssign
+ def on_case(value, consequent)
+ if keyword = find_token(Kw, 'case', consume: false)
+ tokens.delete(keyword)
+
+ Case.new(
+ value: value,
+ consequent: consequent,
+ location: keyword.location.to(consequent.location)
+ )
+ else
+ operator = find_token(Kw, 'in', consume: false) || find_token(Op, '=>')
+
+ RAssign.new(
+ value: value,
+ operator: operator,
+ pattern: consequent,
+ location: value.location.to(consequent.location)
+ )
+ end
+ end
+
+ # Class represents defining a class using the +class+ keyword.
+ #
+ # class Container
+ # end
+ #
+ # Classes can have path names as their class name in case it's being nested
+ # under a namespace, as in:
+ #
+ # class Namespace::Container
+ # end
+ #
+ # Classes can also be defined as a top-level path, in the case that it's
+ # already in a namespace but you want to define it at the top-level instead,
+ # as in:
+ #
+ # module OtherNamespace
+ # class ::Namespace::Container
+ # end
+ # end
+ #
+ # All of these declarations can also have an optional superclass reference, as
+ # in:
+ #
+ # class Child < Parent
+ # end
+ #
+ # That superclass can actually be any Ruby expression, it doesn't necessarily
+ # need to be a constant, as in:
+ #
+ # class Child < method
+ # end
+ #
+ class ClassDeclaration
+ # [ConstPathRef | ConstRef | TopConstRef] the name of the class being
+ # defined
+ attr_reader :constant
+
+ # [nil | untyped] the optional superclass declaration
+ attr_reader :superclass
+
+ # [BodyStmt] the expressions to execute within the context of the class
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, superclass:, bodystmt:, location:)
+ @constant = constant
+ @superclass = superclass
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('class')
+
+ q.breakable
+ q.pp(constant)
+
+ if superclass
+ q.breakable
+ q.pp(superclass)
+ end
+
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :class,
+ constant: constant,
+ superclass: superclass,
+ bodystmt: bodystmt,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_class: (
+ # (ConstPathRef | ConstRef | TopConstRef) constant,
+ # untyped superclass,
+ # BodyStmt bodystmt
+ # ) -> ClassDeclaration
+ def on_class(constant, superclass, bodystmt)
+ beginning = find_token(Kw, 'class')
+ ending = find_token(Kw, 'end')
+
+ bodystmt.bind(
+ find_next_statement_start((superclass || constant).location.end_char),
+ ending.location.start_char
+ )
+
+ ClassDeclaration.new(
+ constant: constant,
+ superclass: superclass,
+ bodystmt: bodystmt,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # Comma represents the use of the , operator.
+ class Comma
+ # [String] the comma in the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_comma: (String value) -> Comma
+ def on_comma(value)
+ node =
+ Comma.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Command represents a method call with arguments and no parentheses. Note
+ # that Command nodes only happen when there is no explicit receiver for this
+ # method.
+ #
+ # method argument
+ #
+ class Command
+ # [Const | Ident] the message being sent to the implicit receiver
+ attr_reader :message
+
+ # [Args | ArgsAddBlock] the arguments being sent with the message
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(message:, arguments:, location:)
+ @message = message
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('command')
+
+ q.breakable
+ q.pp(message)
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :command,
+ message: message,
+ args: arguments,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_command: (
+ # (Const | Ident) message,
+ # (Args | ArgsAddBlock) arguments
+ # ) -> Command
+ def on_command(message, arguments)
+ Command.new(
+ message: message,
+ arguments: arguments,
+ location: message.location.to(arguments.location)
+ )
+ end
+
+ # CommandCall represents a method call on an object with arguments and no
+ # parentheses.
+ #
+ # object.method argument
+ #
+ class CommandCall
+ # [untyped] the receiver of the message
+ attr_reader :receiver
+
+ # [:"::" | Op | Period] the operator used to send the message
+ attr_reader :operator
+
+ # [Const | Ident | Op] the message being send
+ attr_reader :message
+
+ # [Args | ArgsAddBlock] the arguments going along with the message
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(receiver:, operator:, message:, arguments:, location:)
+ @receiver = receiver
+ @operator = operator
+ @message = message
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('command_call')
+
+ q.breakable
+ q.pp(receiver)
+
+ q.breakable
+ q.pp(operator)
+
+ q.breakable
+ q.pp(message)
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :command_call,
+ receiver: receiver,
+ op: operator,
+ message: message,
+ args: arguments,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_command_call: (
+ # untyped receiver,
+ # (:"::" | Op | Period) operator,
+ # (Const | Ident | Op) message,
+ # (Args | ArgsAddBlock) arguments
+ # ) -> CommandCall
+ def on_command_call(receiver, operator, message, arguments)
+ ending = arguments || message
+
+ CommandCall.new(
+ receiver: receiver,
+ operator: operator,
+ message: message,
+ arguments: arguments,
+ location: receiver.location.to(ending.location)
+ )
+ end
+
+ # Comment represents a comment in the source.
+ #
+ # # comment
+ #
+ class Comment
+ # [String] the contents of the comment
+ attr_reader :value
+
+ # [boolean] whether or not there is code on the same line as this comment.
+ # If there is, then inline will be true.
+ attr_reader :inline
+ alias inline? inline
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, inline:, location:)
+ @value = value
+ @inline = inline
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('comment')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :comment,
+ value: value.force_encoding('UTF-8'),
+ inline: inline,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_comment: (String value) -> Comment
+ def on_comment(value)
+ line = lineno
+ comment =
+ Comment.new(
+ value: value[1..-1].chomp,
+ inline: value.strip != lines[line - 1],
+ location:
+ Location.token(line: line, char: char_pos, size: value.size - 1)
+ )
+
+ @comments << comment
+ comment
+ end
+
+ # Const represents a literal value that _looks_ like a constant. This could
+ # actually be a reference to a constant:
+ #
+ # Constant
+ #
+ # It could also be something that looks like a constant in another context, as
+ # in a method call to a capitalized method:
+ #
+ # object.Constant
+ #
+ # or a symbol that starts with a capital letter:
+ #
+ # :Constant
+ #
+ class Const
+ # [String] the name of the constant
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('const')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :const, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_const: (String value) -> Const
+ def on_const(value)
+ node =
+ Const.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # ConstPathField represents the child node of some kind of assignment. It
+ # represents when you're assigning to a constant that is being referenced as
+ # a child of another variable.
+ #
+ # object::Const = value
+ #
+ class ConstPathField
+ # [untyped] the source of the constant
+ attr_reader :parent
+
+ # [Const] the constant itself
+ attr_reader :constant
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parent:, constant:, location:)
+ @parent = parent
+ @constant = constant
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('const_path_field')
+
+ q.breakable
+ q.pp(parent)
+
+ q.breakable
+ q.pp(constant)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :const_path_field,
+ parent: parent,
+ constant: constant,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_const_path_field: (untyped parent, Const constant) -> ConstPathField
+ def on_const_path_field(parent, constant)
+ ConstPathField.new(
+ parent: parent,
+ constant: constant,
+ location: parent.location.to(constant.location)
+ )
+ end
+
+ # ConstPathRef represents referencing a constant by a path.
+ #
+ # object::Const
+ #
+ class ConstPathRef
+ # [untyped] the source of the constant
+ attr_reader :parent
+
+ # [Const] the constant itself
+ attr_reader :constant
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parent:, constant:, location:)
+ @parent = parent
+ @constant = constant
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('const_path_ref')
+
+ q.breakable
+ q.pp(parent)
+
+ q.breakable
+ q.pp(constant)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :const_path_ref,
+ parent: parent,
+ constant: constant,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_const_path_ref: (untyped parent, Const constant) -> ConstPathRef
+ def on_const_path_ref(parent, constant)
+ ConstPathRef.new(
+ parent: parent,
+ constant: constant,
+ location: parent.location.to(constant.location)
+ )
+ end
+
+ # ConstRef represents the name of the constant being used in a class or module
+ # declaration.
+ #
+ # class Container
+ # end
+ #
+ class ConstRef
+ # [Const] the constant itself
+ attr_reader :constant
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, location:)
+ @constant = constant
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('const_ref')
+
+ q.breakable
+ q.pp(constant)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :const_ref, constant: constant, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_const_ref: (Const constant) -> ConstRef
+ def on_const_ref(constant)
+ ConstRef.new(constant: constant, location: constant.location)
+ end
+
+ # CVar represents the use of a class variable.
+ #
+ # @@variable
+ #
+ class CVar
+ # [String] the name of the class variable
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('cvar')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :cvar, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_cvar: (String value) -> CVar
+ def on_cvar(value)
+ node =
+ CVar.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Def represents defining a regular method on the current self object.
+ #
+ # def method(param) result end
+ #
+ class Def
+ # [Backtick | Const | Ident | Kw | Op] the name of the method
+ attr_reader :name
+
+ # [Params | Paren] the parameter declaration for the method
+ attr_reader :params
+
+ # [BodyStmt] the expressions to be executed by the method
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(name:, params:, bodystmt:, location:)
+ @name = name
+ @params = params
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('def')
+
+ q.breakable
+ q.pp(name)
+
+ q.breakable
+ q.pp(params)
+
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :def,
+ name: name,
+ params: params,
+ bodystmt: bodystmt,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # DefEndless represents defining a single-line method since Ruby 3.0+.
+ #
+ # def method = result
+ #
+ class DefEndless
+ # [Backtick | Const | Ident | Kw | Op] the name of the method
+ attr_reader :name
+
+ # [Paren] the parameter declaration for the method
+ attr_reader :paren
+
+ # [untyped] the expression to be executed by the method
+ attr_reader :statement
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(name:, paren:, statement:, location:)
+ @name = name
+ @paren = paren
+ @statement = statement
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('def_endless')
+
+ q.breakable
+ q.pp(name)
+
+ q.breakable
+ q.pp(paren)
+
+ q.breakable
+ q.pp(statement)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :def_endless,
+ name: name,
+ paren: paren,
+ stmt: statement,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_def: (
+ # (Backtick | Const | Ident | Kw | Op) name,
+ # (Params | Paren) params,
+ # untyped bodystmt
+ # ) -> Def | DefEndless
+ def on_def(name, params, bodystmt)
+ # Make sure to delete this token in case you're defining something like def
+ # class which would lead to this being a kw and causing all kinds of trouble
+ tokens.delete(name)
+
+ # Find the beginning of the method definition, which works for single-line
+ # and normal method definitions.
+ beginning = find_token(Kw, 'def')
+
+ # If we don't have a bodystmt node, then we have a single-line method
+ unless bodystmt.is_a?(BodyStmt)
+ node =
+ DefEndless.new(
+ name: name,
+ paren: params,
+ statement: bodystmt,
+ location: beginning.location.to(bodystmt.location)
+ )
+
+ return node
+ end
+
+ # If there aren't any params then we need to correct the params node
+ # location information
+ if params.is_a?(Params) && params.empty?
+ end_char = name.location.end_char
+ location =
+ Location.new(
+ start_line: params.location.start_line,
+ start_char: end_char,
+ end_line: params.location.end_line,
+ end_char: end_char
+ )
+
+ params = Params.new(location: location)
+ end
+
+ ending = find_token(Kw, 'end')
+ bodystmt.bind(
+ find_next_statement_start(params.location.end_char),
+ ending.location.start_char
+ )
+
+ Def.new(
+ name: name,
+ params: params,
+ bodystmt: bodystmt,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # Defined represents the use of the +defined?+ operator. It can be used with
+ # and without parentheses.
+ #
+ # defined?(variable)
+ #
+ class Defined
+ # [untyped] the value being sent to the keyword
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('defined')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :defined, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_defined: (untyped value) -> Defined
+ def on_defined(value)
+ beginning = find_token(Kw, 'defined?')
+ ending = value
+
+ range = beginning.location.end_char...value.location.start_char
+ if source[range].include?('(')
+ find_token(LParen)
+ ending = find_token(RParen)
+ end
+
+ Defined.new(value: value, location: beginning.location.to(ending.location))
+ end
+
+ # Defs represents defining a singleton method on an object.
+ #
+ # def object.method(param) result end
+ #
+ class Defs
+ # [untyped] the target where the method is being defined
+ attr_reader :target
+
+ # [Op | Period] the operator being used to declare the method
+ attr_reader :operator
+
+ # [Backtick | Const | Ident | Kw | Op] the name of the method
+ attr_reader :name
+
+ # [Params | Paren] the parameter declaration for the method
+ attr_reader :params
+
+ # [BodyStmt] the expressions to be executed by the method
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(target:, operator:, name:, params:, bodystmt:, location:)
+ @target = target
+ @operator = operator
+ @name = name
+ @params = params
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('defs')
+
+ q.breakable
+ q.pp(target)
+
+ q.breakable
+ q.pp(operator)
+
+ q.breakable
+ q.pp(name)
+
+ q.breakable
+ q.pp(params)
+
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :defs,
+ target: target,
+ op: operator,
+ name: name,
+ params: params,
+ bodystmt: bodystmt,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_defs: (
+ # untyped target,
+ # (Op | Period) operator,
+ # (Backtick | Const | Ident | Kw | Op) name,
+ # (Params | Paren) params,
+ # BodyStmt bodystmt
+ # ) -> Defs
+ def on_defs(target, operator, name, params, bodystmt)
+ # Make sure to delete this token in case you're defining something
+ # like def class which would lead to this being a kw and causing all kinds
+ # of trouble
+ tokens.delete(name)
+
+ # If there aren't any params then we need to correct the params node
+ # location information
+ if params.is_a?(Params) && params.empty?
+ end_char = name.location.end_char
+ location =
+ Location.new(
+ start_line: params.location.start_line,
+ start_char: end_char,
+ end_line: params.location.end_line,
+ end_char: end_char
+ )
+
+ params = Params.new(location: location)
+ end
+
+ beginning = find_token(Kw, 'def')
+ ending = find_token(Kw, 'end')
+
+ bodystmt.bind(
+ find_next_statement_start(params.location.end_char),
+ ending.location.start_char
+ )
+
+ Defs.new(
+ target: target,
+ operator: operator,
+ name: name,
+ params: params,
+ bodystmt: bodystmt,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # DoBlock represents passing a block to a method call using the +do+ and +end+
+ # keywords.
+ #
+ # method do |value|
+ # end
+ #
+ class DoBlock
+ # [Kw] the do keyword that opens this block
+ attr_reader :keyword
+
+ # [nil | BlockVar] the optional variable declaration within this block
+ attr_reader :block_var
+
+ # [BodyStmt] the expressions to be executed within this block
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(keyword:, block_var:, bodystmt:, location:)
+ @keyword = keyword
+ @block_var = block_var
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('do_block')
+
+ if block_var
+ q.breakable
+ q.pp(block_var)
+ end
+
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :do_block,
+ keyword: keyword,
+ block_var: block_var,
+ bodystmt: bodystmt,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_do_block: (BlockVar block_var, BodyStmt bodystmt) -> DoBlock
+ def on_do_block(block_var, bodystmt)
+ beginning = find_token(Kw, 'do')
+ ending = find_token(Kw, 'end')
+
+ bodystmt.bind(
+ find_next_statement_start((block_var || beginning).location.end_char),
+ ending.location.start_char
+ )
+
+ DoBlock.new(
+ keyword: beginning,
+ block_var: block_var,
+ bodystmt: bodystmt,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # Dot2 represents using the .. operator between two expressions. Usually this
+ # is to create a range object.
+ #
+ # 1..2
+ #
+ # Sometimes this operator is used to create a flip-flop.
+ #
+ # if value == 5 .. value == 10
+ # end
+ #
+ # One of the sides of the expression may be nil, but not both.
+ class Dot2
+ # [nil | untyped] the left side of the expression
+ attr_reader :left
+
+ # [nil | untyped] the right side of the expression
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(left:, right:, location:)
+ @left = left
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('dot2')
+
+ if left
+ q.breakable
+ q.pp(left)
+ end
+
+ if right
+ q.breakable
+ q.pp(right)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ { type: :dot2, left: left, right: right, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_dot2: ((nil | untyped) left, (nil | untyped) right) -> Dot2
+ def on_dot2(left, right)
+ operator = find_token(Op, '..')
+
+ beginning = left || operator
+ ending = right || operator
+
+ Dot2.new(
+ left: left,
+ right: right,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # Dot3 represents using the ... operator between two expressions. Usually this
+ # is to create a range object. It's effectively the same event as the Dot2
+ # node but with this operator you're asking Ruby to omit the final value.
+ #
+ # 1...2
+ #
+ # Like Dot2 it can also be used to create a flip-flop.
+ #
+ # if value == 5 ... value == 10
+ # end
+ #
+ # One of the sides of the expression may be nil, but not both.
+ class Dot3
+ # [nil | untyped] the left side of the expression
+ attr_reader :left
+
+ # [nil | untyped] the right side of the expression
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(left:, right:, location:)
+ @left = left
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('dot3')
+
+ if left
+ q.breakable
+ q.pp(left)
+ end
+
+ if right
+ q.breakable
+ q.pp(right)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ { type: :dot3, left: left, right: right, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_dot3: ((nil | untyped) left, (nil | untyped) right) -> Dot3
+ def on_dot3(left, right)
+ operator = find_token(Op, '...')
+
+ beginning = left || operator
+ ending = right || operator
+
+ Dot3.new(
+ left: left,
+ right: right,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # DynaSymbol represents a symbol literal that uses quotes to dynamically
+ # define its value.
+ #
+ # :"#{variable}"
+ #
+ # They can also be used as a special kind of dynamic hash key, as in:
+ #
+ # { "#{key}": value }
+ #
+ class DynaSymbol
+ # [Array[ StringDVar | StringEmbExpr | TStringContent ]] the parts of the
+ # dynamic symbol
+ attr_reader :parts
+
+ # [String] the quote used to delimit the dynamic symbol
+ attr_reader :quote
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, quote:, location:)
+ @parts = parts
+ @quote = quote
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('dyna_symbol')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :dyna_symbol, parts: parts, quote: quote, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_dyna_symbol: (StringContent string_content) -> DynaSymbol
+ def on_dyna_symbol(string_content)
+ if find_token(SymBeg, consume: false)
+ # A normal dynamic symbol
+ symbeg = find_token(SymBeg)
+ tstring_end = find_token(TStringEnd)
+
+ DynaSymbol.new(
+ quote: symbeg.value,
+ parts: string_content.parts,
+ location: symbeg.location.to(tstring_end.location)
+ )
+ else
+ # A dynamic symbol as a hash key
+ tstring_beg = find_token(TStringBeg)
+ label_end = find_token(LabelEnd)
+
+ DynaSymbol.new(
+ parts: string_content.parts,
+ quote: label_end.value[0],
+ location: tstring_beg.location.to(label_end.location)
+ )
+ end
+ end
+
+ # Else represents the end of an +if+, +unless+, or +case+ chain.
+ #
+ # if variable
+ # else
+ # end
+ #
+ class Else
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statements:, location:)
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('else')
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :else, stmts: statements, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_else: (Statements statements) -> Else
+ def on_else(statements)
+ beginning = find_token(Kw, 'else')
+
+ # else can either end with an end keyword (in which case we'll want to
+ # consume that event) or it can end with an ensure keyword (in which case
+ # we'll leave that to the ensure to handle).
+ index =
+ tokens.rindex do |token|
+ token.is_a?(Kw) && %w[end ensure].include?(token.value)
+ end
+
+ node = tokens[index]
+ ending = node.value == 'end' ? tokens.delete_at(index) : node
+
+ statements.bind(beginning.location.end_char, ending.location.start_char)
+
+ Else.new(
+ statements: statements,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # Elsif represents another clause in an +if+ or +unless+ chain.
+ #
+ # if variable
+ # elsif other_variable
+ # end
+ #
+ class Elsif
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [nil | Elsif | Else] the next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(predicate:, statements:, consequent:, location:)
+ @predicate = predicate
+ @statements = statements
+ @consequent = consequent
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('elsif')
+
+ q.breakable
+ q.pp(predicate)
+
+ q.breakable
+ q.pp(statements)
+
+ if consequent
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :elsif,
+ pred: predicate,
+ stmts: statements,
+ cons: consequent,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_elsif: (
+ # untyped predicate,
+ # Statements statements,
+ # (nil | Elsif | Else) consequent
+ # ) -> Elsif
+ def on_elsif(predicate, statements, consequent)
+ beginning = find_token(Kw, 'elsif')
+ ending = consequent || find_token(Kw, 'end')
+
+ statements.bind(predicate.location.end_char, ending.location.start_char)
+
+ Elsif.new(
+ predicate: predicate,
+ statements: statements,
+ consequent: consequent,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # EmbDoc represents a multi-line comment.
+ #
+ # =begin
+ # first line
+ # second line
+ # =end
+ #
+ class EmbDoc
+ # [String] the contents of the comment
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def inline?
+ false
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('embdoc')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :embdoc, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_embdoc: (String value) -> EmbDoc
+ def on_embdoc(value)
+ @embdoc.value << value
+ @embdoc
+ end
+
+ # :call-seq:
+ # on_embdoc_beg: (String value) -> EmbDoc
+ def on_embdoc_beg(value)
+ @embdoc =
+ EmbDoc.new(
+ value: value,
+ location: Location.fixed(line: lineno, char: char_pos)
+ )
+ end
+
+ # :call-seq:
+ # on_embdoc_end: (String value) -> EmbDoc
+ def on_embdoc_end(value)
+ location = @embdoc.location
+ embdoc =
+ EmbDoc.new(
+ value: @embdoc.value << value.chomp,
+ location:
+ Location.new(
+ start_line: location.start_line,
+ start_char: location.start_char,
+ end_line: lineno,
+ end_char: char_pos + value.length - 1
+ )
+ )
+
+ @comments << embdoc
+ @embdoc = nil
+
+ embdoc
+ end
+
+ # EmbExprBeg represents the beginning token for using interpolation inside of
+ # a parent node that accepts string content (like a string or regular
+ # expression).
+ #
+ # "Hello, #{person}!"
+ #
+ class EmbExprBeg
+ # [String] the #{ used in the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_embexpr_beg: (String value) -> EmbExprBeg
+ def on_embexpr_beg(value)
+ node =
+ EmbExprBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # EmbExprEnd represents the ending token for using interpolation inside of a
+ # parent node that accepts string content (like a string or regular
+ # expression).
+ #
+ # "Hello, #{person}!"
+ #
+ class EmbExprEnd
+ # [String] the } used in the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_embexpr_end: (String value) -> EmbExprEnd
+ def on_embexpr_end(value)
+ node =
+ EmbExprEnd.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # EmbVar represents the use of shorthand interpolation for an instance, class,
+ # or global variable into a parent node that accepts string content (like a
+ # string or regular expression).
+ #
+ # "#@variable"
+ #
+ # In the example above, an EmbVar node represents the # because it forces
+ # @variable to be interpolated.
+ class EmbVar
+ # [String] the # used in the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_embvar: (String value) -> EmbVar
+ def on_embvar(value)
+ node =
+ EmbVar.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Ensure represents the use of the +ensure+ keyword and its subsequent
+ # statements.
+ #
+ # begin
+ # ensure
+ # end
+ #
+ class Ensure
+ # [Kw] the ensure keyword that began this node
+ attr_reader :keyword
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(keyword:, statements:, location:)
+ @keyword = keyword
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('ensure')
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :ensure,
+ keyword: keyword,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_ensure: (Statements statements) -> Ensure
+ def on_ensure(statements)
+ keyword = find_token(Kw, 'ensure')
+
+ # We don't want to consume the :@kw event, because that would break
+ # def..ensure..end chains.
+ ending = find_token(Kw, 'end', consume: false)
+ statements.bind(
+ find_next_statement_start(keyword.location.end_char),
+ ending.location.start_char
+ )
+
+ Ensure.new(
+ keyword: keyword,
+ statements: statements,
+ location: keyword.location.to(ending.location)
+ )
+ end
+
+ # ExcessedComma represents a trailing comma in a list of block parameters. It
+ # changes the block parameters such that they will destructure.
+ #
+ # [[1, 2, 3], [2, 3, 4]].each do |first, second,|
+ # end
+ #
+ # In the above example, an ExcessedComma node would appear in the third
+ # position of the Params node that is used to declare that block. The third
+ # position typically represents a rest-type parameter, but in this case is
+ # used to indicate that a trailing comma was used.
+ class ExcessedComma
+ # [String] the comma
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('excessed_comma')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :excessed_comma, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # The handler for this event accepts no parameters (though in previous
+ # versions of Ruby it accepted a string literal with a value of ",").
+ #
+ # :call-seq:
+ # on_excessed_comma: () -> ExcessedComma
+ def on_excessed_comma(*)
+ comma = find_token(Comma)
+
+ ExcessedComma.new(value: comma.value, location: comma.location)
+ end
+
+ # FCall represents the piece of a method call that comes before any arguments
+ # (i.e., just the name of the method). It is used in places where the parser
+ # is sure that it is a method call and not potentially a local variable.
+ #
+ # method(argument)
+ #
+ # In the above example, it's referring to the +method+ segment.
+ class FCall
+ # [Const | Ident] the name of the method
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('fcall')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :fcall, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_fcall: ((Const | Ident) value) -> FCall
+ def on_fcall(value)
+ FCall.new(value: value, location: value.location)
+ end
+
+ # Field is always the child of an assignment. It represents assigning to a
+ # “field” on an object.
+ #
+ # object.variable = value
+ #
+ class Field
+ # [untyped] the parent object that owns the field being assigned
+ attr_reader :parent
+
+ # [:"::" | Op | Period] the operator being used for the assignment
+ attr_reader :operator
+
+ # [Const | Ident] the name of the field being assigned
+ attr_reader :name
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parent:, operator:, name:, location:)
+ @parent = parent
+ @operator = operator
+ @name = name
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('field')
+
+ q.breakable
+ q.pp(parent)
+
+ q.breakable
+ q.pp(operator)
+
+ q.breakable
+ q.pp(name)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :field,
+ parent: parent,
+ op: operator,
+ name: name,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_field: (
+ # untyped parent,
+ # (:"::" | Op | Period) operator
+ # (Const | Ident) name
+ # ) -> Field
+ def on_field(parent, operator, name)
+ Field.new(
+ parent: parent,
+ operator: operator,
+ name: name,
+ location: parent.location.to(name.location)
+ )
+ end
+
+ # FloatLiteral represents a floating point number literal.
+ #
+ # 1.0
+ #
+ class FloatLiteral
+ # [String] the value of the floating point number literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('float')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :float, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_float: (String value) -> FloatLiteral
+ def on_float(value)
+ node =
+ FloatLiteral.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # FndPtn represents matching against a pattern where you find a pattern in an
+ # array using the Ruby 3.0+ pattern matching syntax.
+ #
+ # case value
+ # in [*, 7, *]
+ # end
+ #
+ class FndPtn
+ # [nil | untyped] the optional constant wrapper
+ attr_reader :constant
+
+ # [VarField] the splat on the left-hand side
+ attr_reader :left
+
+ # [Array[ untyped ]] the list of positional expressions in the pattern that
+ # are being matched
+ attr_reader :values
+
+ # [VarField] the splat on the right-hand side
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, left:, values:, right:, location:)
+ @constant = constant
+ @left = left
+ @values = values
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('fndptn')
+
+ if constant
+ q.breakable
+ q.pp(constant)
+ end
+
+ q.breakable
+ q.pp(left)
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(values) { |value| q.pp(value) } }
+
+ q.breakable
+ q.pp(right)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :fndptn,
+ constant: constant,
+ left: left,
+ values: values,
+ right: right,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_fndptn: (
+ # (nil | untyped) constant,
+ # VarField left,
+ # Array[untyped] values,
+ # VarField right
+ # ) -> FndPtn
+ def on_fndptn(constant, left, values, right)
+ beginning = constant || find_token(LBracket)
+ ending = find_token(RBracket)
+
+ FndPtn.new(
+ constant: constant,
+ left: left,
+ values: values,
+ right: right,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # For represents using a +for+ loop.
+ #
+ # for value in list do
+ # end
+ #
+ class For
+ # [MLHS | MLHSAddStar | VarField] the variable declaration being used to
+ # pull values out of the object being enumerated
+ attr_reader :index
+
+ # [untyped] the object being enumerated in the loop
+ attr_reader :collection
+
+ # [Statements] the statements to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(index:, collection:, statements:, location:)
+ @index = index
+ @collection = collection
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('for')
+
+ q.breakable
+ q.pp(index)
+
+ q.breakable
+ q.pp(collection)
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :for,
+ index: index,
+ collection: collection,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_for: (
+ # (MLHS | MLHSAddStar | VarField) value,
+ # untyped collection,
+ # Statements statements
+ # ) -> For
+ def on_for(index, collection, statements)
+ beginning = find_token(Kw, 'for')
+ ending = find_token(Kw, 'end')
+
+ # Consume the do keyword if it exists so that it doesn't get confused for
+ # some other block
+ keyword = find_token(Kw, 'do', consume: false)
+ if keyword && keyword.location.start_char > collection.location.end_char &&
+ keyword.location.end_char < ending.location.start_char
+ tokens.delete(keyword)
+ end
+
+ statements.bind(
+ (keyword || collection).location.end_char,
+ ending.location.start_char
+ )
+
+ For.new(
+ index: index,
+ collection: collection,
+ statements: statements,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # GVar represents a global variable literal.
+ #
+ # $variable
+ #
+ class GVar
+ # [String] the name of the global variable
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('gvar')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :gvar, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_gvar: (String value) -> GVar
+ def on_gvar(value)
+ node =
+ GVar.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # HashLiteral represents a hash literal.
+ #
+ # { key => value }
+ #
+ class HashLiteral
+ # [nil | AssocListFromArgs] the contents of the hash
+ attr_reader :contents
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(contents:, location:)
+ @contents = contents
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('hash')
+
+ q.breakable
+ q.pp(contents)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :hash, cnts: contents, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_hash: ((nil | AssocListFromArgs) contents) -> HashLiteral
+ def on_hash(contents)
+ lbrace = find_token(LBrace)
+ rbrace = find_token(RBrace)
+
+ if contents
+ # Here we're going to expand out the location information for the contents
+ # node so that it can grab up any remaining comments inside the hash.
+ location =
+ Location.new(
+ start_line: contents.location.start_line,
+ start_char: lbrace.location.end_char,
+ end_line: contents.location.end_line,
+ end_char: rbrace.location.start_char
+ )
+
+ contents = contents.class.new(assocs: contents.assocs, location: location)
+ end
+
+ HashLiteral.new(
+ contents: contents,
+ location: lbrace.location.to(rbrace.location)
+ )
+ end
+
+ # Heredoc represents a heredoc string literal.
+ #
+ # <<~DOC
+ # contents
+ # DOC
+ #
+ class Heredoc
+ # [HeredocBeg] the opening of the heredoc
+ attr_reader :beginning
+
+ # [String] the ending of the heredoc
+ attr_reader :ending
+
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # heredoc string literal
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(beginning:, ending: nil, parts: [], location:)
+ @beginning = beginning
+ @ending = ending
+ @parts = parts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('heredoc')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :heredoc,
+ beging: beginning,
+ ending: ending,
+ parts: parts,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # HeredocBeg represents the beginning declaration of a heredoc.
+ #
+ # <<~DOC
+ # contents
+ # DOC
+ #
+ # In the example above the HeredocBeg node represents <<~DOC.
+ class HeredocBeg
+ # [String] the opening declaration of the heredoc
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('heredoc_beg')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :heredoc_beg, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_heredoc_beg: (String value) -> HeredocBeg
+ def on_heredoc_beg(value)
+ location =
+ Location.token(line: lineno, char: char_pos, size: value.size + 1)
+
+ # Here we're going to artificially create an extra node type so that if
+ # there are comments after the declaration of a heredoc, they get printed.
+ beginning = HeredocBeg.new(value: value, location: location)
+ @heredocs << Heredoc.new(beginning: beginning, location: location)
+
+ beginning
+ end
+
+ # :call-seq:
+ # on_heredoc_dedent: (StringContent string, Integer width) -> Heredoc
+ def on_heredoc_dedent(string, width)
+ heredoc = @heredocs[-1]
+
+ @heredocs[-1] =
+ Heredoc.new(
+ beginning: heredoc.beginning,
+ ending: heredoc.ending,
+ parts: string.parts,
+ location: heredoc.location
+ )
+ end
+
+ # :call-seq:
+ # on_heredoc_end: (String value) -> Heredoc
+ def on_heredoc_end(value)
+ heredoc = @heredocs[-1]
+
+ @heredocs[-1] =
+ Heredoc.new(
+ beginning: heredoc.beginning,
+ ending: value.chomp,
+ parts: heredoc.parts,
+ location:
+ Location.new(
+ start_line: heredoc.location.start_line,
+ start_char: heredoc.location.start_char,
+ end_line: lineno,
+ end_char: char_pos
+ )
+ )
+ end
+
+ # HshPtn represents matching against a hash pattern using the Ruby 2.7+
+ # pattern matching syntax.
+ #
+ # case value
+ # in { key: }
+ # end
+ #
+ class HshPtn
+ # [nil | untyped] the optional constant wrapper
+ attr_reader :constant
+
+ # [Array[ [Label, untyped] ]] the set of tuples representing the keywords
+ # that should be matched against in the pattern
+ attr_reader :keywords
+
+ # [nil | VarField] an optional parameter to gather up all remaining keywords
+ attr_reader :keyword_rest
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, keywords:, keyword_rest:, location:)
+ @constant = constant
+ @keywords = keywords
+ @keyword_rest = keyword_rest
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('hshptn')
+
+ if constant
+ q.breakable
+ q.pp(constant)
+ end
+
+ if keywords.any?
+ q.breakable
+ q.group(2, '(', ')') do
+ q.seplist(keywords) { |keyword| q.pp(keyword) }
+ end
+ end
+
+ if keyword_rest
+ q.breakable
+ q.pp(keyword_rest)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :hshptn,
+ constant: constant,
+ keywords: keywords,
+ kwrest: keyword_rest,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_hshptn: (
+ # (nil | untyped) constant,
+ # Array[[Label, untyped]] keywords,
+ # (nil | VarField) keyword_rest
+ # ) -> HshPtn
+ def on_hshptn(constant, keywords, keyword_rest)
+ parts = [constant, keywords, keyword_rest].flatten(2).compact
+
+ HshPtn.new(
+ constant: constant,
+ keywords: keywords,
+ keyword_rest: keyword_rest,
+ location: parts[0].location.to(parts[-1].location)
+ )
+ end
+
+ # Ident represents an identifier anywhere in code. It can represent a very
+ # large number of things, depending on where it is in the syntax tree.
+ #
+ # value
+ #
+ class Ident
+ # [String] the value of the identifier
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('ident')
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :ident,
+ value: value.force_encoding('UTF-8'),
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_ident: (String value) -> Ident
+ def on_ident(value)
+ node =
+ Ident.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # If represents the first clause in an +if+ chain.
+ #
+ # if predicate
+ # end
+ #
+ class If
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [nil, Elsif, Else] the next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(predicate:, statements:, consequent:, location:)
+ @predicate = predicate
+ @statements = statements
+ @consequent = consequent
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('if')
+
+ q.breakable
+ q.pp(predicate)
+
+ q.breakable
+ q.pp(statements)
+
+ if consequent
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :if,
+ pred: predicate,
+ stmts: statements,
+ cons: consequent,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_if: (
+ # untyped predicate,
+ # Statements statements,
+ # (nil | Elsif | Else) consequent
+ # ) -> If
+ def on_if(predicate, statements, consequent)
+ beginning = find_token(Kw, 'if')
+ ending = consequent || find_token(Kw, 'end')
+
+ statements.bind(predicate.location.end_char, ending.location.start_char)
+
+ If.new(
+ predicate: predicate,
+ statements: statements,
+ consequent: consequent,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # IfOp represents a ternary clause.
+ #
+ # predicate ? truthy : falsy
+ #
+ class IfOp
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [untyped] the expression to be executed if the predicate is truthy
+ attr_reader :truthy
+
+ # [untyped] the expression to be executed if the predicate is falsy
+ attr_reader :falsy
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(predicate:, truthy:, falsy:, location:)
+ @predicate = predicate
+ @truthy = truthy
+ @falsy = falsy
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('ifop')
+
+ q.breakable
+ q.pp(predicate)
+
+ q.breakable
+ q.pp(truthy)
+
+ q.breakable
+ q.pp(falsy)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :ifop,
+ pred: predicate,
+ tthy: truthy,
+ flsy: falsy,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_ifop: (untyped predicate, untyped truthy, untyped falsy) -> IfOp
+ def on_ifop(predicate, truthy, falsy)
+ IfOp.new(
+ predicate: predicate,
+ truthy: truthy,
+ falsy: falsy,
+ location: predicate.location.to(falsy.location)
+ )
+ end
+
+ # IfMod represents the modifier form of an +if+ statement.
+ #
+ # expression if predicate
+ #
+ class IfMod
+ # [untyped] the expression to be executed
+ attr_reader :statement
+
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statement:, predicate:, location:)
+ @statement = statement
+ @predicate = predicate
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('if_mod')
+
+ q.breakable
+ q.pp(statement)
+
+ q.breakable
+ q.pp(predicate)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :if_mod,
+ stmt: statement,
+ pred: predicate,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_if_mod: (untyped predicate, untyped statement) -> IfMod
+ def on_if_mod(predicate, statement)
+ find_token(Kw, 'if')
+
+ IfMod.new(
+ statement: statement,
+ predicate: predicate,
+ location: statement.location.to(predicate.location)
+ )
+ end
+
+ # def on_ignored_nl(value)
+ # value
+ # end
+
+ # def on_ignored_sp(value)
+ # value
+ # end
+
+ # Imaginary represents an imaginary number literal.
+ #
+ # 1i
+ #
+ class Imaginary
+ # [String] the value of the imaginary number literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('imaginary')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :imaginary, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_imaginary: (String value) -> Imaginary
+ def on_imaginary(value)
+ node =
+ Imaginary.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # In represents using the +in+ keyword within the Ruby 2.7+ pattern matching
+ # syntax.
+ #
+ # case value
+ # in pattern
+ # end
+ #
+ class In
+ # [untyped] the pattern to check against
+ attr_reader :pattern
+
+ # [Statements] the expressions to execute if the pattern matched
+ attr_reader :statements
+
+ # [nil | In | Else] the next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(pattern:, statements:, consequent:, location:)
+ @pattern = pattern
+ @statements = statements
+ @consequent = consequent
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('in')
+
+ q.breakable
+ q.pp(pattern)
+
+ q.breakable
+ q.pp(statements)
+
+ if consequent
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :in,
+ pattern: pattern,
+ stmts: statements,
+ cons: consequent,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_in: (RAssign pattern, nil statements, nil consequent) -> RAssign
+ # | (
+ # untyped pattern,
+ # Statements statements,
+ # (nil | In | Else) consequent
+ # ) -> In
+ def on_in(pattern, statements, consequent)
+ # Here we have a rightward assignment
+ return pattern unless statements
+
+ beginning = find_token(Kw, 'in')
+ ending = consequent || find_token(Kw, 'end')
+
+ statements.bind(beginning.location.end_char, ending.location.start_char)
+
+ In.new(
+ pattern: pattern,
+ statements: statements,
+ consequent: consequent,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # Int represents an integer number literal.
+ #
+ # 1
+ #
+ class Int
+ # [String] the value of the integer
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('int')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :int, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_int: (String value) -> Int
+ def on_int(value)
+ node =
+ Int.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # IVar represents an instance variable literal.
+ #
+ # @variable
+ #
+ class IVar
+ # [String] the name of the instance variable
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('ivar')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :ivar, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_ivar: (String value) -> IVar
+ def on_ivar(value)
+ node =
+ IVar.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Kw represents the use of a keyword. It can be almost anywhere in the syntax
+ # tree, so you end up seeing it quite a lot.
+ #
+ # if value
+ # end
+ #
+ # In the above example, there would be two Kw nodes: one for the if and one
+ # for the end. Note that anything that matches the list of keywords in Ruby
+ # will use a Kw, so if you use a keyword in a symbol literal for instance:
+ #
+ # :if
+ #
+ # then the contents of the symbol node will contain a Kw node.
+ class Kw
+ # [String] the value of the keyword
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('kw')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :kw, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_kw: (String value) -> Kw
+ def on_kw(value)
+ node =
+ Kw.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # KwRestParam represents defining a parameter in a method definition that
+ # accepts all remaining keyword parameters.
+ #
+ # def method(**kwargs) end
+ #
+ class KwRestParam
+ # [nil | Ident] the name of the parameter
+ attr_reader :name
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(name:, location:)
+ @name = name
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('kwrest_param')
+
+ q.breakable
+ q.pp(name)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :kwrest_param, name: name, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_kwrest_param: ((nil | Ident) name) -> KwRestParam
+ def on_kwrest_param(name)
+ location = find_token(Op, '**').location
+ location = location.to(name.location) if name
+
+ KwRestParam.new(name: name, location: location)
+ end
+
+ # Label represents the use of an identifier to associate with an object. You
+ # can find it in a hash key, as in:
+ #
+ # { key: value }
+ #
+ # In this case "key:" would be the body of the label. You can also find it in
+ # pattern matching, as in:
+ #
+ # case value
+ # in key:
+ # end
+ #
+ # In this case "key:" would be the body of the label.
+ class Label
+ # [String] the value of the label
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('label')
+
+ q.breakable
+ q.text(':')
+ q.text(value[0...-1])
+ end
+ end
+
+ def to_json(*opts)
+ { type: :label, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_label: (String value) -> Label
+ def on_label(value)
+ node =
+ Label.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # LabelEnd represents the end of a dynamic symbol.
+ #
+ # { "key": value }
+ #
+ # In the example above, LabelEnd represents the "\":" token at the end of the
+ # hash key. This node is important for determining the type of quote being
+ # used by the label.
+ class LabelEnd
+ # [String] the end of the label
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_label_end: (String value) -> LabelEnd
+ def on_label_end(value)
+ node =
+ LabelEnd.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Lambda represents using a lambda literal (not the lambda method call).
+ #
+ # ->(value) { value * 2 }
+ #
+ class Lambda
+ # [Params | Paren] the parameter declaration for this lambda
+ attr_reader :params
+
+ # [BodyStmt | Statements] the expressions to be executed in this lambda
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(params:, statements:, location:)
+ @params = params
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('lambda')
+
+ q.breakable
+ q.pp(params)
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :lambda,
+ params: params,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_lambda: (
+ # (Params | Paren) params,
+ # (BodyStmt | Statements) statements
+ # ) -> Lambda
+ def on_lambda(params, statements)
+ beginning = find_token(TLambda)
+
+ if token = find_token(TLamBeg, consume: false)
+ opening = tokens.delete(token)
+ closing = find_token(RBrace)
+ else
+ opening = find_token(Kw, 'do')
+ closing = find_token(Kw, 'end')
+ end
+
+ statements.bind(opening.location.end_char, closing.location.start_char)
+
+ Lambda.new(
+ params: params,
+ statements: statements,
+ location: beginning.location.to(closing.location)
+ )
+ end
+
+ # LBrace represents the use of a left brace, i.e., {.
+ class LBrace
+ # [String] the left brace
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('lbrace')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :lbrace, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_lbrace: (String value) -> LBrace
+ def on_lbrace(value)
+ node =
+ LBrace.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # LBracket represents the use of a left bracket, i.e., [.
+ class LBracket
+ # [String] the left bracket
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_lbracket: (String value) -> LBracket
+ def on_lbracket(value)
+ node =
+ LBracket.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # LParen represents the use of a left parenthesis, i.e., (.
+ class LParen
+ # [String] the left parenthesis
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('lparen')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :lparen, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_lparen: (String value) -> LParen
+ def on_lparen(value)
+ node =
+ LParen.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # def on_magic_comment(key, value)
+ # [key, value]
+ # end
+
+ # MAssign is a parent node of any kind of multiple assignment. This includes
+ # splitting out variables on the left like:
+ #
+ # first, second, third = value
+ #
+ # as well as splitting out variables on the right, as in:
+ #
+ # value = first, second, third
+ #
+ # Both sides support splats, as well as variables following them. There's also
+ # destructuring behavior that you can achieve with the following:
+ #
+ # first, = value
+ #
+ class MAssign
+ # [Mlhs | MlhsAddPost | MlhsAddStar | MlhsParen] the target of the multiple
+ # assignment
+ attr_reader :target
+
+ # [untyped] the value being assigned
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(target:, value:, location:)
+ @target = target
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('massign')
+
+ q.breakable
+ q.pp(target)
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :massign, target: target, value: value, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_massign: (
+ # (Mlhs | MlhsAddPost | MlhsAddStar | MlhsParen) target,
+ # untyped value
+ # ) -> MAssign
+ def on_massign(target, value)
+ comma_range = target.location.end_char...value.location.start_char
+ target.comma = true if source[comma_range].strip.start_with?(',')
+
+ MAssign.new(
+ target: target,
+ value: value,
+ location: target.location.to(value.location)
+ )
+ end
+
+ # MethodAddArg represents a method call with arguments and parentheses.
+ #
+ # method(argument)
+ #
+ # MethodAddArg can also represent with a method on an object, as in:
+ #
+ # object.method(argument)
+ #
+ # Finally, MethodAddArg can represent calling a method with no receiver that
+ # ends in a ?. In this case, the parser knows it's a method call and not a
+ # local variable, so it uses a MethodAddArg node as opposed to a VCall node,
+ # as in:
+ #
+ # method?
+ #
+ class MethodAddArg
+ # [Call | FCall] the method call
+ attr_reader :call
+
+ # [ArgParen | Args | ArgsAddBlock] the arguments to the method call
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(call:, arguments:, location:)
+ @call = call
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('method_add_arg')
+
+ q.breakable
+ q.pp(call)
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :method_add_arg,
+ call: call,
+ args: arguments,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_method_add_arg: (
+ # (Call | FCall) call,
+ # (ArgParen | Args | ArgsAddBlock) arguments
+ # ) -> MethodAddArg
+ def on_method_add_arg(call, arguments)
+ location = call.location
+
+ location = location.to(arguments.location) unless arguments.is_a?(Args)
+
+ MethodAddArg.new(call: call, arguments: arguments, location: location)
+ end
+
+ # MethodAddBlock represents a method call with a block argument.
+ #
+ # method {}
+ #
+ class MethodAddBlock
+ # [Call | Command | CommandCall | FCall | MethodAddArg] the method call
+ attr_reader :call
+
+ # [BraceBlock | DoBlock] the block being sent with the method call
+ attr_reader :block
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(call:, block:, location:)
+ @call = call
+ @block = block
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('method_add_block')
+
+ q.breakable
+ q.pp(call)
+
+ q.breakable
+ q.pp(block)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :method_add_block,
+ call: call,
+ block: block,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_method_add_block: (
+ # (Call | Command | CommandCall | FCall | MethodAddArg) call,
+ # (BraceBlock | DoBlock) block
+ # ) -> MethodAddBlock
+ def on_method_add_block(call, block)
+ MethodAddBlock.new(
+ call: call,
+ block: block,
+ location: call.location.to(block.location)
+ )
+ end
+
+ # MLHS represents a list of values being destructured on the left-hand side
+ # of a multiple assignment.
+ #
+ # first, second, third = value
+ #
+ class MLHS
+ # Array[ARefField | Field | Ident | MlhsParen | VarField] the parts of
+ # the left-hand side of a multiple assignment
+ attr_reader :parts
+
+ # [boolean] whether or not there is a trailing comma at the end of this
+ # list, which impacts destructuring. It's an attr_accessor so that while
+ # the syntax tree is being built it can be set by its parent node
+ attr_accessor :comma
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, comma: false, location:)
+ @parts = parts
+ @comma = comma
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mlhs')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mlhs, parts: parts, comma: comma, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_mlhs_add: (
+ # MLHS mlhs,
+ # (ARefField | Field | Ident | MlhsParen | VarField) part
+ # ) -> MLHS
+ def on_mlhs_add(mlhs, part)
+ if mlhs.parts.empty?
+ MLHS.new(parts: [part], location: part.location)
+ else
+ MLHS.new(
+ parts: mlhs.parts << part,
+ location: mlhs.location.to(part.location)
+ )
+ end
+ end
+
+ # MLHSAddPost represents adding another set of variables onto a list of
+ # assignments after a splat variable within a multiple assignment.
+ #
+ # left, *middle, right = values
+ #
+ class MLHSAddPost
+ # [MlhsAddStar] the value being starred
+ attr_reader :star
+
+ # [Mlhs] the values after the star
+ attr_reader :mlhs
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(star:, mlhs:, location:)
+ @star = star
+ @mlhs = mlhs
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mlhs_add_post')
+
+ q.breakable
+ q.pp(star)
+
+ q.breakable
+ q.pp(mlhs)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mlhs_add_post, star: star, mlhs: mlhs, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_mlhs_add_post: (MLHSAddStar star, MLHS mlhs) -> MLHSAddPost
+ def on_mlhs_add_post(star, mlhs)
+ MLHSAddPost.new(
+ star: star,
+ mlhs: mlhs,
+ location: star.location.to(mlhs.location)
+ )
+ end
+
+ # MLHSAddStar represents a splatted variable inside of a multiple assignment
+ # on the left hand side.
+ #
+ # first, *rest = values
+ #
+ class MLHSAddStar
+ # [MLHS] the values before the starred expression
+ attr_reader :mlhs
+
+ # [nil | ARefField | Field | Ident | VarField] the expression being
+ # splatted
+ attr_reader :star
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(mlhs:, star:, location:)
+ @mlhs = mlhs
+ @star = star
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mlhs_add_star')
+
+ q.breakable
+ q.pp(mlhs)
+
+ q.breakable
+ q.pp(star)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mlhs_add_star, mlhs: mlhs, star: star, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_mlhs_add_star: (
+ # MLHS mlhs,
+ # (nil | ARefField | Field | Ident | VarField) part
+ # ) -> MLHSAddStar
+ def on_mlhs_add_star(mlhs, part)
+ beginning = find_token(Op, '*')
+ ending = part || beginning
+
+ MLHSAddStar.new(
+ mlhs: mlhs,
+ star: part,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # :call-seq:
+ # on_mlhs_new: () -> MLHS
+ def on_mlhs_new
+ MLHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
+ end
+
+ # MLHSParen represents parentheses being used to destruct values in a multiple
+ # assignment on the left hand side.
+ #
+ # (left, right) = value
+ #
+ class MLHSParen
+ # [Mlhs | MlhsAddPost | MlhsAddStar | MlhsParen] the contents inside of the
+ # parentheses
+ attr_reader :contents
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(contents:, location:)
+ @contents = contents
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mlhs_paren')
+
+ q.breakable
+ q.pp(contents)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mlhs_paren, cnts: contents, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_mlhs_paren: (
+ # (Mlhs | MlhsAddPost | MlhsAddStar | MlhsParen) contents
+ # ) -> MLHSParen
+ def on_mlhs_paren(contents)
+ lparen = find_token(LParen)
+ rparen = find_token(RParen)
+
+ comma_range = lparen.location.end_char...rparen.location.start_char
+ contents.comma = true if source[comma_range].strip.end_with?(',')
+
+ MLHSParen.new(
+ contents: contents,
+ location: lparen.location.to(rparen.location)
+ )
+ end
+
+ # ModuleDeclaration represents defining a module using the +module+ keyword.
+ #
+ # module Namespace
+ # end
+ #
+ class ModuleDeclaration
+ # [ConstPathRef | ConstRef | TopConstRef] the name of the module
+ attr_reader :constant
+
+ # [BodyStmt] the expressions to be executed in the context of the module
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, bodystmt:, location:)
+ @constant = constant
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('module')
+
+ q.breakable
+ q.pp(constant)
+
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :module,
+ constant: constant,
+ bodystmt: bodystmt,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_module: (
+ # (ConstPathRef | ConstRef | TopConstRef) constant,
+ # BodyStmt bodystmt
+ # ) -> ModuleDeclaration
+ def on_module(constant, bodystmt)
+ beginning = find_token(Kw, 'module')
+ ending = find_token(Kw, 'end')
+
+ bodystmt.bind(
+ find_next_statement_start(constant.location.end_char),
+ ending.location.start_char
+ )
+
+ ModuleDeclaration.new(
+ constant: constant,
+ bodystmt: bodystmt,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # MRHS represents the values that are being assigned on the right-hand side of
+ # a multiple assignment.
+ #
+ # values = first, second, third
+ #
+ class MRHS
+ # Array[untyped] the parts that are being assigned
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, location:)
+ @parts = parts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mrhs')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mrhs, parts: parts, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_mrhs_new: () -> MRHS
+ def on_mrhs_new
+ MRHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
+ end
+
+ # :call-seq:
+ # on_mrhs_add: (MRHS mrhs, untyped part) -> MRHS
+ def on_mrhs_add(mrhs, part)
+ if mrhs.is_a?(MRHSNewFromArgs)
+ MRHS.new(
+ parts: [*mrhs.arguments.parts, part],
+ location: mrhs.location.to(part.location)
+ )
+ elsif mrhs.parts.empty?
+ MRHS.new(parts: [part], location: mrhs.location)
+ else
+ MRHS.new(parts: mrhs.parts << part, loc: mrhs.location.to(part.location))
+ end
+ end
+
+ # MRHSAddStar represents using the splat operator to expand out a value on the
+ # right hand side of a multiple assignment.
+ #
+ # values = first, *rest
+ #
+ class MRHSAddStar
+ # [MRHS | MRHSNewFromArgs] the values before the splatted expression
+ attr_reader :mrhs
+
+ # [untyped] the splatted expression
+ attr_reader :star
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(mrhs:, star:, location:)
+ @mrhs = mrhs
+ @star = star
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mrhs_add_star')
+
+ q.breakable
+ q.pp(mrhs)
+
+ q.breakable
+ q.pp(star)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mrhs_add_star, mrhs: mrhs, star: star, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_mrhs_add_star: (
+ # (MRHS | MRHSNewFromArgs) mrhs,
+ # untyped star
+ # ) -> MRHSAddStar
+ def on_mrhs_add_star(mrhs, star)
+ beginning = find_token(Op, '*')
+ ending = star || beginning
+
+ MRHSAddStar.new(
+ mrhs: mrhs,
+ star: star,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # MRHSNewFromArgs represents the shorthand of a multiple assignment that
+ # allows you to assign values using just commas as opposed to assigning from
+ # an array.
+ #
+ # values = first, second, third
+ #
+ class MRHSNewFromArgs
+ # [Args] the arguments being used in the assignment
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('mrhs_new_from_args')
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :mrhs_new_from_args, args: arguments, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_mrhs_new_from_args: (Args arguments) -> MRHSNewFromArgs
+ def on_mrhs_new_from_args(arguments)
+ MRHSNewFromArgs.new(arguments: arguments, location: arguments.location)
+ end
+
+ # Next represents using the +next+ keyword.
+ #
+ # next
+ #
+ # The +next+ keyword can also optionally be called with an argument:
+ #
+ # next value
+ #
+ # +next+ can even be called with multiple arguments, but only if parentheses
+ # are omitted, as in:
+ #
+ # next first, second, third
+ #
+ # If a single value is being given, parentheses can be used, as in:
+ #
+ # next(value)
+ #
+ class Next
+ # [Args | ArgsAddBlock] the arguments passed to the next keyword
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('next')
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :next, args: arguments, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_next: ((Args | ArgsAddBlock) arguments) -> Next
+ def on_next(arguments)
+ keyword = find_token(Kw, 'next')
+
+ location = keyword.location
+ location = location.to(arguments.location) unless arguments.is_a?(Args)
+
+ Next.new(arguments: arguments, location: location)
+ end
+
+ # def on_nl(value)
+ # value
+ # end
+
+ # def on_nokw_param(value)
+ # value
+ # end
+
+ # Op represents an operator literal in the source.
+ #
+ # 1 + 2
+ #
+ # In the example above, the Op node represents the + operator.
+ class Op
+ # [String] the operator
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('op')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :op, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_op: (String value) -> Op
+ def on_op(value)
+ node =
+ Op.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # OpAssign represents assigning a value to a variable or constant using an
+ # operator like += or ||=.
+ #
+ # variable += value
+ #
+ class OpAssign
+ # [ARefField | ConstPathField | Field | TopConstField | VarField] the target
+ # to assign the result of the expression to
+ attr_reader :target
+
+ # [Op] the operator being used for the assignment
+ attr_reader :operator
+
+ # [untyped] the expression to be assigned
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(target:, operator:, value:, location:)
+ @target = target
+ @operator = operator
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('opassign')
+
+ q.breakable
+ q.pp(target)
+
+ q.breakable
+ q.pp(operator)
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :opassign,
+ target: target,
+ op: operator,
+ value: value,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_opassign: (
+ # (ARefField | ConstPathField | Field | TopConstField | VarField) target,
+ # Op operator,
+ # untyped value
+ # ) -> OpAssign
+ def on_opassign(target, operator, value)
+ OpAssign.new(
+ target: target,
+ operator: operator,
+ value: value,
+ location: target.location.to(value.location)
+ )
+ end
+
+ # def on_operator_ambiguous(value)
+ # value
+ # end
+
+ # Params represents defining parameters on a method or lambda.
+ #
+ # def method(param) end
+ #
+ class Params
+ # [Array[ Ident ]] any required parameters
+ attr_reader :requireds
+
+ # [Array[ [ Ident, untyped ] ]] any optional parameters and their default
+ # values
+ attr_reader :optionals
+
+ # [nil | ArgsForward | ExcessedComma | RestParam] the optional rest
+ # parameter
+ attr_reader :rest
+
+ # [Array[ Ident ]] any positional parameters that exist after a rest
+ # parameter
+ attr_reader :posts
+
+ # [Array[ [ Ident, nil | untyped ] ]] any keyword parameters and their
+ # optional default values
+ attr_reader :keywords
+
+ # [nil | :nil | KwRestParam] the optional keyword rest parameter
+ attr_reader :keyword_rest
+
+ # [nil | BlockArg] the optional block parameter
+ attr_reader :block
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(
+ requireds: [],
+ optionals: [],
+ rest: nil,
+ posts: [],
+ keywords: [],
+ keyword_rest: nil,
+ block: nil,
+ location:
+ )
+ @requireds = requireds
+ @optionals = optionals
+ @rest = rest
+ @posts = posts
+ @keywords = keywords
+ @keyword_rest = keyword_rest
+ @block = block
+ @location = location
+ end
+
+ # Params nodes are the most complicated in the tree. Occasionally you want
+ # to know if they are "empty", which means not having any parameters
+ # declared. This logic accesses every kind of parameter and determines if
+ # it's missing.
+ def empty?
+ requireds.empty? && optionals.empty? && !rest && posts.empty? &&
+ keywords.empty? && !keyword_rest && !block
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('params')
+
+ if requireds.any?
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(requireds) { |name| q.pp(name) } }
+ end
+
+ if optionals.any?
+ q.breakable
+ q.group(2, '(', ')') do
+ q.seplist(optionals) do |(name, default)|
+ q.pp(name)
+ q.text('=')
+ q.group(2) do
+ q.breakable('')
+ q.pp(default)
+ end
+ end
+ end
+ end
+
+ if rest
+ q.breakable
+ q.pp(rest)
+ end
+
+ if posts.any?
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(posts) { |value| q.pp(value) } }
+ end
+
+ if keywords.any?
+ q.breakable
+ q.group(2, '(', ')') do
+ q.seplist(keywords) do |(name, default)|
+ q.pp(name)
+
+ if default
+ q.text('=')
+ q.group(2) do
+ q.breakable('')
+ q.pp(default)
+ end
+ end
+ end
+ end
+ end
+
+ if keyword_rest
+ q.breakable
+ q.pp(keyword_rest)
+ end
+
+ if block
+ q.breakable
+ q.pp(block)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :params,
+ reqs: requireds,
+ opts: optionals,
+ rest: rest,
+ posts: posts,
+ keywords: keywords,
+ kwrest: keyword_rest,
+ block: block,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_params: (
+ # (nil | Array[Ident]) requireds,
+ # (nil | Array[[Ident, untyped]]) optionals,
+ # (nil | ArgsForward | ExcessedComma | RestParam) rest,
+ # (nil | Array[Ident]) posts,
+ # (nil | Array[[Ident, nil | untyped]]) keywords,
+ # (nil | :nil | KwRestParam) keyword_rest,
+ # (nil | BlockArg) block
+ # ) -> Params
+ def on_params(
+ requireds,
+ optionals,
+ rest,
+ posts,
+ keywords,
+ keyword_rest,
+ block
+ )
+ parts = [
+ *requireds,
+ *optionals&.flatten(1),
+ rest,
+ *posts,
+ *keywords&.flat_map { |(key, value)| [key, value || nil] },
+ (keyword_rest if keyword_rest != :nil),
+ block
+ ].compact
+
+ location =
+ if parts.any?
+ parts[0].location.to(parts[-1].location)
+ else
+ Location.fixed(line: lineno, char: char_pos)
+ end
+
+ Params.new(
+ requireds: requireds || [],
+ optionals: optionals || [],
+ rest: rest,
+ posts: posts || [],
+ keywords: keywords || [],
+ keyword_rest: keyword_rest,
+ block: block,
+ location: location
+ )
+ end
+
+ # Paren represents using balanced parentheses in a couple places in a Ruby
+ # program. In general parentheses can be used anywhere a Ruby expression can
+ # be used.
+ #
+ # (1 + 2)
+ #
+ class Paren
+ # [LParen] the left parenthesis that opened this statement
+ attr_reader :lparen
+
+ # [untyped] the expression inside the parentheses
+ attr_reader :contents
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(lparen:, contents:, location:)
+ @lparen = lparen
+ @contents = contents
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('paren')
+
+ q.breakable
+ q.pp(contents)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :paren, lparen: lparen, cnts: contents, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_paren: (untyped contents) -> Paren
+ def on_paren(contents)
+ lparen = find_token(LParen)
+ rparen = find_token(RParen)
+
+ if contents && contents.is_a?(Params)
+ location = contents.location
+ location =
+ Location.new(
+ start_line: location.start_line,
+ start_char: find_next_statement_start(lparen.location.end_char),
+ end_line: location.end_line,
+ end_char: rparen.location.start_char
+ )
+
+ contents =
+ Params.new(
+ requireds: contents.requireds,
+ optionals: contents.optionals,
+ rest: contents.rest,
+ posts: contents.posts,
+ keywords: contents.keywords,
+ keyword_rest: contents.keyword_rest,
+ block: contents.block,
+ location: location
+ )
+ end
+
+ Paren.new(
+ lparen: lparen,
+ contents: contents,
+ location: lparen.location.to(rparen.location)
+ )
+ end
+
+ # If we encounter a parse error, just immediately bail out so that our runner
+ # can catch it.
+ def on_parse_error(error, *)
+ raise ParseError.new(error, lineno, column)
+ end
+ alias on_alias_error on_parse_error
+ alias on_assign_error on_parse_error
+ alias on_class_name_error on_parse_error
+ alias on_param_error on_parse_error
+
+ # Period represents the use of the +.+ operator. It is usually found in method
+ # calls.
+ class Period
+ # [String] the period
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('period')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :period, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_period: (String value) -> Period
+ def on_period(value)
+ Period.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+ end
+
+ # Program represents the overall syntax tree.
+ class Program
+ # [Statements] the top-level expressions of the program
+ attr_reader :statements
+
+ # [Array[ Comment | EmbDoc ]] the comments inside the program
+ attr_reader :comments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statements:, comments:, location:)
+ @statements = statements
+ @comments = comments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('program')
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :program,
+ stmts: statements,
+ comments: comments,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_program: (Statements statements) -> Program
+ def on_program(statements)
+ location =
+ Location.new(
+ start_line: 1,
+ start_char: 0,
+ end_line: lines.length,
+ end_char: source.length
+ )
+
+ statements.body << @__end__ if @__end__
+ statements.bind(0, source.length)
+
+ Program.new(statements: statements, comments: @comments, location: location)
+ end
+
+ # QSymbols represents a symbol literal array without interpolation.
+ #
+ # %i[one two three]
+ #
+ class QSymbols
+ # [Array[ TStringContent ]] the elements of the array
+ attr_reader :elements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(elements:, location:)
+ @elements = elements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('qsymbols')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(elements) { |element| q.pp(element) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :qsymbols, elems: elements, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_qsymbols_add: (QSymbols qsymbols, TStringContent element) -> QSymbols
+ def on_qsymbols_add(qsymbols, element)
+ QSymbols.new(
+ elements: qsymbols.elements << element,
+ location: qsymbols.location.to(element.location)
+ )
+ end
+
+ # QSymbolsBeg represents the beginning of a symbol literal array.
+ #
+ # %i[one two three]
+ #
+ # In the snippet above, QSymbolsBeg represents the "%i[" token. Note that
+ # these kinds of arrays can start with a lot of different delimiter types
+ # (e.g., %i| or %i<).
+ class QSymbolsBeg
+ # [String] the beginning of the array literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_qsymbols_beg: (String value) -> QSymbolsBeg
+ def on_qsymbols_beg(value)
+ node =
+ QSymbolsBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # :call-seq:
+ # on_qsymbols_new: () -> QSymbols
+ def on_qsymbols_new
+ qsymbols_beg = find_token(QSymbolsBeg)
+
+ QSymbols.new(elements: [], location: qsymbols_beg.location)
+ end
+
+ # QWords represents a string literal array without interpolation.
+ #
+ # %w[one two three]
+ #
+ class QWords
+ # [Array[ TStringContent ]] the elements of the array
+ attr_reader :elements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(elements:, location:)
+ @elements = elements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('qwords')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(elements) { |element| q.pp(element) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :qwords, elems: elements, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_qwords_add: (QWords qwords, TStringContent element) -> QWords
+ def on_qwords_add(qwords, element)
+ QWords.new(
+ elements: qwords.elements << element,
+ location: qwords.location.to(element.location)
+ )
+ end
+
+ # QWordsBeg represents the beginning of a string literal array.
+ #
+ # %w[one two three]
+ #
+ # In the snippet above, QWordsBeg represents the "%w[" token. Note that these
+ # kinds of arrays can start with a lot of different delimiter types (e.g.,
+ # %w| or %w<).
+ class QWordsBeg
+ # [String] the beginning of the array literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_qwords_beg: (String value) -> QWordsBeg
+ def on_qwords_beg(value)
+ node =
+ QWordsBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # :call-seq:
+ # on_qwords_new: () -> QWords
+ def on_qwords_new
+ qwords_beg = find_token(QWordsBeg)
+
+ QWords.new(elements: [], location: qwords_beg.location)
+ end
+
+ # RationalLiteral represents the use of a rational number literal.
+ #
+ # 1r
+ #
+ class RationalLiteral
+ # [String] the rational number literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('rational')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :rational, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_rational: (String value) -> RationalLiteral
+ def on_rational(value)
+ node =
+ RationalLiteral.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # RBrace represents the use of a right brace, i.e., +++.
+ class RBrace
+ # [String] the right brace
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_rbrace: (String value) -> RBrace
+ def on_rbrace(value)
+ node =
+ RBrace.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # RBracket represents the use of a right bracket, i.e., +]+.
+ class RBracket
+ # [String] the right bracket
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_rbracket: (String value) -> RBracket
+ def on_rbracket(value)
+ node =
+ RBracket.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Redo represents the use of the +redo+ keyword.
+ #
+ # redo
+ #
+ class Redo
+ # [String] the value of the keyword
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('redo')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :redo, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_redo: () -> Redo
+ def on_redo
+ keyword = find_token(Kw, 'redo')
+
+ Redo.new(value: keyword.value, location: keyword.location)
+ end
+
+ # RegexpContent represents the body of a regular expression.
+ #
+ # /.+ #{pattern} .+/
+ #
+ # In the example above, a RegexpContent node represents everything contained
+ # within the forward slashes.
+ class RegexpContent
+ # [String] the opening of the regular expression
+ attr_reader :beginning
+
+ # [Array[ StringDVar | StringEmbExpr | TStringContent ]] the parts of the
+ # regular expression
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(beginning:, parts:, location:)
+ @beginning = beginning
+ @parts = parts
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_regexp_add: (
+ # RegexpContent regexp_content,
+ # (StringDVar | StringEmbExpr | TStringContent) part
+ # ) -> RegexpContent
+ def on_regexp_add(regexp_content, part)
+ RegexpContent.new(
+ beginning: regexp_content.beginning,
+ parts: regexp_content.parts << part,
+ location: regexp_content.location.to(part.location)
+ )
+ end
+
+ # RegexpBeg represents the start of a regular expression literal.
+ #
+ # /.+/
+ #
+ # In the example above, RegexpBeg represents the first / token. Regular
+ # expression literals can also be declared using the %r syntax, as in:
+ #
+ # %r{.+}
+ #
+ class RegexpBeg
+ # [String] the beginning of the regular expression
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_regexp_beg: (String value) -> RegexpBeg
+ def on_regexp_beg(value)
+ node =
+ RegexpBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # RegexpEnd represents the end of a regular expression literal.
+ #
+ # /.+/m
+ #
+ # In the example above, the RegexpEnd event represents the /m at the end of
+ # the regular expression literal. You can also declare regular expression
+ # literals using %r, as in:
+ #
+ # %r{.+}m
+ #
+ class RegexpEnd
+ # [String] the end of the regular expression
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_regexp_end: (String value) -> RegexpEnd
+ def on_regexp_end(value)
+ RegexpEnd.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+ end
+
+ # RegexpLiteral represents a regular expression literal.
+ #
+ # /.+/
+ #
+ class RegexpLiteral
+ # [String] the beginning of the regular expression literal
+ attr_reader :beginning
+
+ # [String] the ending of the regular expression literal
+ attr_reader :ending
+
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # regular expression literal
+ attr_reader :parts
+
+ # [Locatione] the location of this node
+ attr_reader :location
+
+ def initialize(beginning:, ending:, parts:, location:)
+ @beginning = beginning
+ @ending = ending
+ @parts = parts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('regexp_literal')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :regexp_literal,
+ beging: beginning,
+ ending: ending,
+ parts: parts,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_regexp_literal: (
+ # RegexpContent regexp_content,
+ # RegexpEnd ending
+ # ) -> RegexpLiteral
+ def on_regexp_literal(regexp_content, ending)
+ RegexpLiteral.new(
+ beginning: regexp_content.beginning,
+ ending: ending.value,
+ parts: regexp_content.parts,
+ location: regexp_content.location.to(ending.location)
+ )
+ end
+
+ # :call-seq:
+ # on_regexp_new: () -> RegexpContent
+ def on_regexp_new
+ regexp_beg = find_token(RegexpBeg)
+
+ RegexpContent.new(
+ beginning: regexp_beg.value,
+ parts: [],
+ location: regexp_beg.location
+ )
+ end
+
+ # RescueEx represents the list of exceptions being rescued in a rescue clause.
+ #
+ # begin
+ # rescue Exception => exception
+ # end
+ #
+ class RescueEx
+ # [untyped] the list of exceptions being rescued
+ attr_reader :exceptions
+
+ # [nil | Field | VarField] the expression being used to capture the raised
+ # exception
+ attr_reader :variable
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(exceptions:, variable:, location:)
+ @exceptions = exceptions
+ @variable = variable
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('rescue_ex')
+
+ q.breakable
+ q.pp(exceptions)
+
+ q.breakable
+ q.pp(variable)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :rescue_ex,
+ extns: exceptions,
+ var: variable,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # Rescue represents the use of the rescue keyword inside of a BodyStmt node.
+ #
+ # begin
+ # rescue
+ # end
+ #
+ class Rescue
+ # [RescueEx] the exceptions being rescued
+ attr_reader :exception
+
+ # [Statements] the expressions to evaluate when an error is rescued
+ attr_reader :statements
+
+ # [nil | Rescue] the optional next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(exception:, statements:, consequent:, location:)
+ @exception = exception
+ @statements = statements
+ @consequent = consequent
+ @location = location
+ end
+
+ def bind_end(end_char)
+ @location =
+ Location.new(
+ start_line: location.start_line,
+ start_char: location.start_char,
+ end_line: location.end_line,
+ end_char: end_char
+ )
+
+ if consequent
+ consequent.bind_end(end_char)
+ statements.bind_end(consequent.location.start_char)
+ else
+ statements.bind_end(end_char)
+ end
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('rescue')
+
+ if exception
+ q.breakable
+ q.pp(exception)
+ end
+
+ q.breakable
+ q.pp(statements)
+
+ if consequent
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :rescue,
+ extn: exception,
+ stmts: statements,
+ cons: consequent,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_rescue: (
+ # (nil | [untyped] | MRHS | MRHSAddStar) exceptions,
+ # (nil | Field | VarField) variable,
+ # Statements statements,
+ # (nil | Rescue) consequent
+ # ) -> Rescue
+ def on_rescue(exceptions, variable, statements, consequent)
+ keyword = find_token(Kw, 'rescue')
+ exceptions = exceptions[0] if exceptions.is_a?(Array)
+
+ last_node = variable || exceptions || keyword
+ statements.bind(
+ find_next_statement_start(last_node.location.end_char),
+ char_pos
+ )
+
+ # We add an additional inner node here that ripper doesn't provide so that
+ # we have a nice place to attach inline comments. But we only need it if we
+ # have an exception or a variable that we're rescuing.
+ rescue_ex =
+ if exceptions || variable
+ RescueEx.new(
+ exceptions: exceptions,
+ variable: variable,
+ location:
+ Location.new(
+ start_line: keyword.location.start_line,
+ start_char: keyword.location.end_char + 1,
+ end_line: last_node.location.end_line,
+ end_char: last_node.location.end_char
+ )
+ )
+ end
+
+ Rescue.new(
+ exception: rescue_ex,
+ statements: statements,
+ consequent: consequent,
+ location:
+ Location.new(
+ start_line: keyword.location.start_line,
+ start_char: keyword.location.start_char,
+ end_line: lineno,
+ end_char: char_pos
+ )
+ )
+ end
+
+ # RescueMod represents the use of the modifier form of a +rescue+ clause.
+ #
+ # expression rescue value
+ #
+ class RescueMod
+ # [untyped] the expression to execute
+ attr_reader :statement
+
+ # [untyped] the value to use if the executed expression raises an error
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statement:, value:, location:)
+ @statement = statement
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('rescue_mod')
+
+ q.breakable
+ q.pp(statement)
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :rescue_mod,
+ stmt: statement,
+ value: value,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_rescue_mod: (untyped statement, untyped value) -> RescueMod
+ def on_rescue_mod(statement, value)
+ find_token(Kw, 'rescue')
+
+ RescueMod.new(
+ statement: statement,
+ value: value,
+ location: statement.location.to(value.location)
+ )
+ end
+
+ # RestParam represents defining a parameter in a method definition that
+ # accepts all remaining positional parameters.
+ #
+ # def method(*rest) end
+ #
+ class RestParam
+ # [nil | Ident] the name of the parameter
+ attr_reader :name
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(name:, location:)
+ @name = name
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('rest_param')
+
+ q.breakable
+ q.pp(name)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :rest_param, name: name, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_rest_param: ((nil | Ident) name) -> RestParam
+ def on_rest_param(name)
+ location = find_token(Op, '*').location
+ location = location.to(name.location) if name
+
+ RestParam.new(name: name, location: location)
+ end
+
+ # Retry represents the use of the +retry+ keyword.
+ #
+ # retry
+ #
+ class Retry
+ # [String] the value of the keyword
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('retry')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :retry, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_retry: () -> Retry
+ def on_retry
+ keyword = find_token(Kw, 'retry')
+
+ Retry.new(value: keyword.value, location: keyword.location)
+ end
+
+ # Return represents using the +return+ keyword with arguments.
+ #
+ # return value
+ #
+ class Return
+ # [Args | ArgsAddBlock] the arguments being passed to the keyword
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('return')
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :return, args: arguments, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_return: ((Args | ArgsAddBlock) arguments) -> Return
+ def on_return(arguments)
+ keyword = find_token(Kw, 'return')
+
+ Return.new(
+ arguments: arguments,
+ location: keyword.location.to(arguments.location)
+ )
+ end
+
+ # Return0 represents the bare +return+ keyword with no arguments.
+ #
+ # return
+ #
+ class Return0
+ # [String] the value of the keyword
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('return0')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :return0, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_return0: () -> Return0
+ def on_return0
+ keyword = find_token(Kw, 'return')
+
+ Return0.new(value: keyword.value, location: keyword.location)
+ end
+
+ # RParen represents the use of a right parenthesis, i.e., +)+.
+ class RParen
+ # [String] the parenthesis
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_rparen: (String value) -> RParen
+ def on_rparen(value)
+ node =
+ RParen.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # SClass represents a block of statements that should be evaluated within the
+ # context of the singleton class of an object. It's frequently used to define
+ # singleton methods.
+ #
+ # class << self
+ # end
+ #
+ class SClass
+ # [untyped] the target of the singleton class to enter
+ attr_reader :target
+
+ # [BodyStmt] the expressions to be executed
+ attr_reader :bodystmt
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(target:, bodystmt:, location:)
+ @target = target
+ @bodystmt = bodystmt
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('sclass')
+
+ q.breakable
+ q.pp(target)
+
+ q.breakable
+ q.pp(bodystmt)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :sclass,
+ target: target,
+ bodystmt: bodystmt,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_sclass: (untyped target, BodyStmt bodystmt) -> SClass
+ def on_sclass(target, bodystmt)
+ beginning = find_token(Kw, 'class')
+ ending = find_token(Kw, 'end')
+
+ bodystmt.bind(
+ find_next_statement_start(target.location.end_char),
+ ending.location.start_char
+ )
+
+ SClass.new(
+ target: target,
+ bodystmt: bodystmt,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # def on_semicolon(value)
+ # value
+ # end
+
+ # def on_sp(value)
+ # value
+ # end
+
+ # stmts_add is a parser event that represents a single statement inside a
+ # list of statements within any lexical block. It accepts as arguments the
+ # parent stmts node as well as an stmt which can be any expression in
+ # Ruby.
+ def on_stmts_add(statements, statement)
+ statements << statement
+ end
+
+ # Everything that has a block of code inside of it has a list of statements.
+ # Normally we would just track those as a node that has an array body, but we
+ # have some special handling in order to handle empty statement lists. They
+ # need to have the right location information, so all of the parent node of
+ # stmts nodes will report back down the location information. We then
+ # propagate that onto void_stmt nodes inside the stmts in order to make sure
+ # all comments get printed appropriately.
+ class Statements
+ # [SyntaxTree] the parser that created this node
+ attr_reader :parser
+
+ # [Array[ untyped ]] the list of expressions contained within this node
+ attr_reader :body
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parser:, body:, location:)
+ @parser = parser
+ @body = body
+ @location = location
+ end
+
+ def bind(start_char, end_char)
+ @location =
+ Location.new(
+ start_line: location.start_line,
+ start_char: start_char,
+ end_line: location.end_line,
+ end_char: end_char
+ )
+
+ if body[0].is_a?(VoidStmt)
+ location = body[0].location
+ location =
+ Location.new(
+ start_line: location.start_line,
+ start_char: start_char,
+ end_line: location.end_line,
+ end_char: start_char
+ )
+
+ body[0] = VoidStmt.new(location: location)
+ end
+
+ attach_comments(start_char, end_char)
+ end
+
+ def bind_end(end_char)
+ @location =
+ Location.new(
+ start_line: location.start_line,
+ start_char: location.start_char,
+ end_line: location.end_line,
+ end_char: end_char
+ )
+ end
+
+ def <<(statement)
+ @location =
+ body.any? ? location.to(statement.location) : statement.location
+
+ body << statement
+ self
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('statements')
+
+ q.breakable
+ q.seplist(body) { |statement| q.pp(statement) }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :statements, body: body, loc: location }.to_json(*opts)
+ end
+
+ private
+
+ def attach_comments(start_char, end_char)
+ attachable =
+ parser.comments.select do |comment|
+ !comment.inline? && start_char <= comment.location.start_char &&
+ end_char >= comment.location.end_char &&
+ !comment.value.include?('prettier-ignore')
+ end
+
+ return if attachable.empty?
+
+ parser.comments -= attachable
+ @body = (body + attachable).sort_by! { |node| node.location.start_char }
+ end
+ end
+
+ # :call-seq:
+ # on_stmts_new: () -> Statements
+ def on_stmts_new
+ Statements.new(
+ parser: self,
+ body: [],
+ location: Location.fixed(line: lineno, char: char_pos)
+ )
+ end
+
+ # StringContent represents the contents of a string-like value.
+ #
+ # "string"
+ #
+ class StringContent
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # string
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, location:)
+ @parts = parts
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_string_add: (
+ # String string,
+ # (StringEmbExpr | StringDVar | TStringContent) part
+ # ) -> StringContent
+ def on_string_add(string, part)
+ location =
+ string.parts.any? ? string.location.to(part.location) : part.location
+
+ StringContent.new(parts: string.parts << part, location: location)
+ end
+
+ # StringConcat represents concatenating two strings together using a backward
+ # slash.
+ #
+ # "first" \
+ # "second"
+ #
+ class StringConcat
+ # [StringConcat | StringLiteral] the left side of the concatenation
+ attr_reader :left
+
+ # [StringLiteral] the right side of the concatenation
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(left:, right:, location:)
+ @left = left
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('string_concat')
+
+ q.breakable
+ q.pp(left)
+
+ q.breakable
+ q.pp(right)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :string_concat, left: left, right: right, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_string_concat: (
+ # (StringConcat | StringLiteral) left,
+ # StringLiteral right
+ # ) -> StringConcat
+ def on_string_concat(left, right)
+ StringConcat.new(
+ left: left,
+ right: right,
+ location: left.location.to(right.location)
+ )
+ end
+
+ # :call-seq:
+ # on_string_content: () -> StringContent
+ def on_string_content
+ StringContent.new(
+ parts: [],
+ location: Location.fixed(line: lineno, char: char_pos)
+ )
+ end
+
+ # StringDVar represents shorthand interpolation of a variable into a string.
+ # It allows you to take an instance variable, class variable, or global
+ # variable and omit the braces when interpolating.
+ #
+ # "#@variable"
+ #
+ class StringDVar
+ # [Backref | VarRef] the variable being interpolated
+ attr_reader :variable
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(variable:, location:)
+ @variable = variable
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('string_dvar')
+
+ q.breakable
+ q.pp(variable)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :string_dvar, var: variable, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_string_dvar: ((Backref | VarRef) variable) -> StringDVar
+ def on_string_dvar(variable)
+ embvar = find_token(EmbVar)
+
+ StringDVar.new(
+ variable: variable,
+ location: embvar.location.to(variable.location)
+ )
+ end
+
+ # StringEmbExpr represents interpolated content. It can be contained within a
+ # couple of different parent nodes, including regular expressions, strings,
+ # and dynamic symbols.
+ #
+ # "string #{expression}"
+ #
+ class StringEmbExpr
+ # [Statements] the expressions to be interpolated
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statements:, location:)
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('string_embexpr')
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :string_embexpr, stmts: statements, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_string_embexpr: (Statements statements) -> StringEmbExpr
+ def on_string_embexpr(statements)
+ embexpr_beg = find_token(EmbExprBeg)
+ embexpr_end = find_token(EmbExprEnd)
+
+ statements.bind(
+ embexpr_beg.location.end_char,
+ embexpr_end.location.start_char
+ )
+
+ StringEmbExpr.new(
+ statements: statements,
+ location: embexpr_beg.location.to(embexpr_end.location)
+ )
+ end
+
+ # StringLiteral represents a string literal.
+ #
+ # "string"
+ #
+ class StringLiteral
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # string literal
+ attr_reader :parts
+
+ # [String] which quote was used by the string literal
+ attr_reader :quote
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, quote:, location:)
+ @parts = parts
+ @quote = quote
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('string_literal')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :string_literal,
+ parts: parts,
+ quote: quote,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_string_literal: (String string) -> Heredoc | StringLiteral
+ def on_string_literal(string)
+ heredoc = @heredocs[-1]
+
+ if heredoc && heredoc.ending
+ heredoc = @heredocs.pop
+
+ Heredoc.new(
+ beginning: heredoc.beginning,
+ ending: heredoc.ending,
+ parts: string.parts,
+ location: heredoc.location
+ )
+ else
+ tstring_beg = find_token(TStringBeg)
+ tstring_end = find_token(TStringEnd)
+
+ StringLiteral.new(
+ parts: string.parts,
+ quote: tstring_beg.value,
+ location: tstring_beg.location.to(tstring_end.location)
+ )
+ end
+ end
+
+ # Super represents using the +super+ keyword with arguments. It can optionally
+ # use parentheses.
+ #
+ # super(value)
+ #
+ class Super
+ # [ArgParen | Args | ArgsAddBlock] the arguments to the keyword
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('super')
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :super, args: arguments, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_super: ((ArgParen | Args | ArgsAddBlock) arguments) -> Super
+ def on_super(arguments)
+ keyword = find_token(Kw, 'super')
+
+ Super.new(
+ arguments: arguments,
+ location: keyword.location.to(arguments.location)
+ )
+ end
+
+ # SymBeg represents the beginning of a symbol literal.
+ #
+ # :symbol
+ #
+ # SymBeg is also used for dynamic symbols, as in:
+ #
+ # :"symbol"
+ #
+ # Finally, SymBeg is also used for symbols using the %s syntax, as in:
+ #
+ # %s[symbol]
+ #
+ # The value of this node is a string. In most cases (as in the first example
+ # above) it will contain just ":". In the case of dynamic symbols it will
+ # contain ":'" or ":\"". In the case of %s symbols, it will contain the start
+ # of the symbol including the %s and the delimiter.
+ class SymBeg
+ # [String] the beginning of the symbol
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # symbeg is a token that represents the beginning of a symbol literal.
+ # In most cases it will contain just ":" as in the value, but if its a dynamic
+ # symbol being defined it will contain ":'" or ":\"".
+ def on_symbeg(value)
+ node =
+ SymBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # SymbolContent represents symbol contents and is always the child of a
+ # SymbolLiteral node.
+ #
+ # :symbol
+ #
+ class SymbolContent
+ # [Backtick | Const | CVar | GVar | Ident | IVar | Kw | Op] the value of the
+ # symbol
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_symbol: (
+ # (Backtick | Const | CVar | GVar | Ident | IVar | Kw | Op) value
+ # ) -> SymbolContent
+ def on_symbol(value)
+ tokens.pop
+
+ SymbolContent.new(value: value, location: value.location)
+ end
+
+ # SymbolLiteral represents a symbol in the system with no interpolation
+ # (as opposed to a DynaSymbol which has interpolation).
+ #
+ # :symbol
+ #
+ class SymbolLiteral
+ # [Backtick | Const | CVar | GVar | Ident | IVar | Kw | Op] the value of the
+ # symbol
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('symbol_literal')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :symbol_literal, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_symbol_literal: (
+ # (
+ # Backtick | Const | CVar | GVar | Ident |
+ # IVar | Kw | Op | SymbolContent
+ # ) value
+ # ) -> SymbolLiteral
+ def on_symbol_literal(value)
+ if tokens[-1] == value
+ SymbolLiteral.new(value: tokens.pop, location: value.location)
+ else
+ symbeg = find_token(SymBeg)
+
+ SymbolLiteral.new(
+ value: value.value,
+ location: symbeg.location.to(value.location)
+ )
+ end
+ end
+
+ # Symbols represents a symbol array literal with interpolation.
+ #
+ # %I[one two three]
+ #
+ class Symbols
+ # [Array[ Word ]] the words in the symbol array literal
+ attr_reader :elements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(elements:, location:)
+ @elements = elements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('symbols')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(elements) { |element| q.pp(element) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :symbols, elems: elements, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_symbols_add: (Symbols symbols, Word word) -> Symbols
+ def on_symbols_add(symbols, word)
+ Symbols.new(
+ elements: symbols.elements << word,
+ location: symbols.location.to(word.location)
+ )
+ end
+
+ # SymbolsBeg represents the start of a symbol array literal with
+ # interpolation.
+ #
+ # %I[one two three]
+ #
+ # In the snippet above, SymbolsBeg represents the "%I[" token. Note that these
+ # kinds of arrays can start with a lot of different delimiter types
+ # (e.g., %I| or %I<).
+ class SymbolsBeg
+ # [String] the beginning of the symbol literal array
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_symbols_beg: (String value) -> SymbolsBeg
+ def on_symbols_beg(value)
+ node =
+ SymbolsBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # :call-seq:
+ # on_symbols_new: () -> Symbols
+ def on_symbols_new
+ symbols_beg = find_token(SymbolsBeg)
+
+ Symbols.new(elements: [], location: symbols_beg.location)
+ end
+
+ # TLambda represents the beginning of a lambda literal.
+ #
+ # -> { value }
+ #
+ # In the example above the TLambda represents the +->+ operator.
+ class TLambda
+ # [String] the beginning of the lambda literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_tlambda: (String value) -> TLambda
+ def on_tlambda(value)
+ node =
+ TLambda.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # TLamBeg represents the beginning of the body of a lambda literal using
+ # braces.
+ #
+ # -> { value }
+ #
+ # In the example above the TLamBeg represents the +{+ operator.
+ class TLamBeg
+ # [String] the beginning of the body of the lambda literal
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_tlambeg: (String value) -> TLamBeg
+ def on_tlambeg(value)
+ node =
+ TLamBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # TopConstField is always the child node of some kind of assignment. It
+ # represents when you're assigning to a constant that is being referenced at
+ # the top level.
+ #
+ # ::Constant = value
+ #
+ class TopConstField
+ # [Const] the constant being assigned
+ attr_reader :constant
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, location:)
+ @constant = constant
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('top_const_field')
+
+ q.breakable
+ q.pp(constant)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :top_const_field, constant: constant, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_top_const_field: (Const constant) -> TopConstRef
+ def on_top_const_field(constant)
+ operator = find_colon2_before(constant)
+
+ TopConstField.new(
+ constant: constant,
+ location: operator.location.to(constant.location)
+ )
+ end
+
+ # TopConstRef is very similar to TopConstField except that it is not involved
+ # in an assignment.
+ #
+ # ::Constant
+ #
+ class TopConstRef
+ # [Const] the constant being referenced
+ attr_reader :constant
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(constant:, location:)
+ @constant = constant
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('top_const_ref')
+
+ q.breakable
+ q.pp(constant)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :top_const_ref, constant: constant, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_top_const_ref: (Const constant) -> TopConstRef
+ def on_top_const_ref(constant)
+ operator = find_colon2_before(constant)
+
+ TopConstRef.new(
+ constant: constant,
+ location: operator.location.to(constant.location)
+ )
+ end
+
+ # TStringBeg represents the beginning of a string literal.
+ #
+ # "string"
+ #
+ # In the example above, TStringBeg represents the first set of quotes. Strings
+ # can also use single quotes. They can also be declared using the +%q+ and
+ # +%Q+ syntax, as in:
+ #
+ # %q{string}
+ #
+ class TStringBeg
+ # [String] the beginning of the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_tstring_beg: (String value) -> TStringBeg
+ def on_tstring_beg(value)
+ node =
+ TStringBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # TStringContent represents plain characters inside of an entity that accepts
+ # string content like a string, heredoc, command string, or regular
+ # expression.
+ #
+ # "string"
+ #
+ # In the example above, TStringContent represents the +string+ token contained
+ # within the string.
+ class TStringContent
+ # [String] the content of the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('tstring_content')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :tstring_content,
+ value: value.force_encoding('UTF-8'),
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_tstring_content: (String value) -> TStringContent
+ def on_tstring_content(value)
+ TStringContent.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+ end
+
+ # TStringEnd represents the end of a string literal.
+ #
+ # "string"
+ #
+ # In the example above, TStringEnd represents the second set of quotes.
+ # Strings can also use single quotes. They can also be declared using the +%q+
+ # and +%Q+ syntax, as in:
+ #
+ # %q{string}
+ #
+ class TStringEnd
+ # [String] the end of the string
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_tstring_end: (String value) -> TStringEnd
+ def on_tstring_end(value)
+ node =
+ TStringEnd.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # Not represents the unary +not+ method being called on an expression.
+ #
+ # not value
+ #
+ class Not
+ # [untyped] the statement on which to operate
+ attr_reader :statement
+
+ # [boolean] whether or not parentheses were used
+ attr_reader :parentheses
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statement:, parentheses:, location:)
+ @statement = statement
+ @parentheses = parentheses
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('not')
+
+ q.breakable
+ q.pp(statement)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :not,
+ value: statement,
+ paren: parentheses,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # Unary represents a unary method being called on an expression, as in +!+ or
+ # +~+.
+ #
+ # !value
+ #
+ class Unary
+ # [String] the operator being used
+ attr_reader :operator
+
+ # [untyped] the statement on which to operate
+ attr_reader :statement
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(operator:, statement:, location:)
+ @operator = operator
+ @statement = statement
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('unary')
+
+ q.breakable
+ q.pp(operator)
+
+ q.breakable
+ q.pp(statement)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :unary, op: operator, value: statement, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_unary: (:not operator, untyped statement) -> Not
+ # | (Symbol operator, untyped statement) -> Unary
+ def on_unary(operator, statement)
+ if operator == :not
+ # We have somewhat special handling of the not operator since if it has
+ # parentheses they don't get reported as a paren node for some reason.
+
+ beginning = find_token(Kw, 'not')
+ ending = statement
+
+ range = beginning.location.end_char...statement.location.start_char
+ paren = source[range].include?('(')
+
+ if paren
+ find_token(LParen)
+ ending = find_token(RParen)
+ end
+
+ Not.new(
+ statement: statement,
+ parentheses: paren,
+ location: beginning.location.to(ending.location)
+ )
+ else
+ # Special case instead of using find_token here. It turns out that
+ # if you have a range that goes from a negative number to a negative
+ # number then you can end up with a .. or a ... that's higher in the
+ # stack. So we need to explicitly disallow those operators.
+ index =
+ tokens.rindex do |token|
+ token.is_a?(Op) &&
+ token.location.start_char < statement.location.start_char &&
+ !%w[.. ...].include?(token.value)
+ end
+
+ beginning = tokens.delete_at(index)
+
+ Unary.new(
+ operator: operator[0], # :+@ -> "+"
+ statement: statement,
+ location: beginning.location.to(statement.location)
+ )
+ end
+ end
+
+ # Undef represents the use of the +undef+ keyword.
+ #
+ # undef method
+ #
+ class Undef
+ # [Array[ DynaSymbol | SymbolLiteral ]] the symbols to undefine
+ attr_reader :symbols
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(symbols:, location:)
+ @symbols = symbols
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('undef')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(symbols) { |symbol| q.pp(symbol) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :undef, syms: symbols, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_undef: (Array[DynaSymbol | SymbolLiteral] symbols) -> Undef
+ def on_undef(symbols)
+ keyword = find_token(Kw, 'undef')
+
+ Undef.new(
+ symbols: symbols,
+ location: keyword.location.to(symbols.last.location)
+ )
+ end
+
+ # Unless represents the first clause in an +unless+ chain.
+ #
+ # unless predicate
+ # end
+ #
+ class Unless
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [nil, Elsif, Else] the next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(predicate:, statements:, consequent:, location:)
+ @predicate = predicate
+ @statements = statements
+ @consequent = consequent
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('unless')
+
+ q.breakable
+ q.pp(predicate)
+
+ q.breakable
+ q.pp(statements)
+
+ if consequent
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :unless,
+ pred: predicate,
+ stmts: statements,
+ cons: consequent,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_unless: (
+ # untyped predicate,
+ # Statements statements,
+ # ((nil | Elsif | Else) consequent)
+ # ) -> Unless
+ def on_unless(predicate, statements, consequent)
+ beginning = find_token(Kw, 'unless')
+ ending = consequent || find_token(Kw, 'end')
+
+ statements.bind(predicate.location.end_char, ending.location.start_char)
+
+ Unless.new(
+ predicate: predicate,
+ statements: statements,
+ consequent: consequent,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # UnlessMod represents the modifier form of an +unless+ statement.
+ #
+ # expression unless predicate
+ #
+ class UnlessMod
+ # [untyped] the expression to be executed
+ attr_reader :statement
+
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statement:, predicate:, location:)
+ @statement = statement
+ @predicate = predicate
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('unless_mod')
+
+ q.breakable
+ q.pp(statement)
+
+ q.breakable
+ q.pp(predicate)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :unless_mod,
+ stmt: statement,
+ pred: predicate,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_unless_mod: (untyped predicate, untyped statement) -> UnlessMod
+ def on_unless_mod(predicate, statement)
+ find_token(Kw, 'unless')
+
+ UnlessMod.new(
+ statement: statement,
+ predicate: predicate,
+ location: statement.location.to(predicate.location)
+ )
+ end
+
+ # Until represents an +until+ loop.
+ #
+ # until predicate
+ # end
+ #
+ class Until
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(predicate:, statements:, location:)
+ @predicate = predicate
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('until')
+
+ q.breakable
+ q.pp(predicate)
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :until,
+ pred: predicate,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_until: (untyped predicate, Statements statements) -> Until
+ def on_until(predicate, statements)
+ beginning = find_token(Kw, 'until')
+ ending = find_token(Kw, 'end')
+
+ # Consume the do keyword if it exists so that it doesn't get confused for
+ # some other block
+ keyword = find_token(Kw, 'do', consume: false)
+ if keyword && keyword.location.start_char > predicate.location.end_char &&
+ keyword.location.end_char < ending.location.start_char
+ tokens.delete(keyword)
+ end
+
+ # Update the Statements location information
+ statements.bind(predicate.location.end_char, ending.location.start_char)
+
+ Until.new(
+ predicate: predicate,
+ statements: statements,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # UntilMod represents the modifier form of a +until+ loop.
+ #
+ # expression until predicate
+ #
+ class UntilMod
+ # [untyped] the expression to be executed
+ attr_reader :statement
+
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statement:, predicate:, location:)
+ @statement = statement
+ @predicate = predicate
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('until_mod')
+
+ q.breakable
+ q.pp(statement)
+
+ q.breakable
+ q.pp(predicate)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :until_mod,
+ stmt: statement,
+ pred: predicate,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_until_mod: (untyped predicate, untyped statement) -> UntilMod
+ def on_until_mod(predicate, statement)
+ find_token(Kw, 'until')
+
+ UntilMod.new(
+ statement: statement,
+ predicate: predicate,
+ location: statement.location.to(predicate.location)
+ )
+ end
+
+ # VarAlias represents when you're using the +alias+ keyword with global
+ # variable arguments.
+ #
+ # alias $new $old
+ #
+ class VarAlias
+ # [GVar] the new alias of the variable
+ attr_reader :left
+
+ # [Backref | GVar] the current name of the variable to be aliased
+ attr_reader :right
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(left:, right:, location:)
+ @left = left
+ @right = right
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('var_alias')
+
+ q.breakable
+ q.pp(left)
+
+ q.breakable
+ q.pp(right)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :var_alias, left: left, right: right, loc: location }.to_json(
+ *opts
+ )
+ end
+ end
+
+ # :call-seq:
+ # on_var_alias: (GVar left, (Backref | GVar) right) -> VarAlias
+ def on_var_alias(left, right)
+ keyword = find_token(Kw, 'alias')
+
+ VarAlias.new(
+ left: left,
+ right: right,
+ location: keyword.location.to(right.location)
+ )
+ end
+
+ # VarField represents a variable that is being assigned a value. As such, it
+ # is always a child of an assignment type node.
+ #
+ # variable = value
+ #
+ # In the example above, the VarField node represents the +variable+ token.
+ class VarField
+ # [nil | Const | CVar | GVar | Ident | IVar] the target of this node
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('var_field')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :var_field, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_var_field: (
+ # (nil | Const | CVar | GVar | Ident | IVar) value
+ # ) -> VarField
+ def on_var_field(value)
+ location =
+ if value
+ value.location
+ else
+ # You can hit this pattern if you're assigning to a splat using pattern
+ # matching syntax in Ruby 2.7+
+ Location.fixed(line: lineno, char: char_pos)
+ end
+
+ VarField.new(value: value, location: location)
+ end
+
+ # VarRef represents a variable reference.
+ #
+ # true
+ #
+ # This can be a plain local variable like the example above. It can also be a
+ # constant, a class variable, a global variable, an instance variable, a
+ # keyword (like +self+, +nil+, +true+, or +false+), or a numbered block
+ # variable.
+ class VarRef
+ # [Const | CVar | GVar | Ident | IVar | Kw] the value of this node
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('var_ref')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :var_ref, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_var_ref: ((Const | CVar | GVar | Ident | IVar | Kw) value) -> VarRef
+ def on_var_ref(value)
+ VarRef.new(value: value, location: value.location)
+ end
+
+ # AccessCtrl represents a call to a method visibility control, i.e., +public+,
+ # +protected+, or +private+.
+ #
+ # private
+ #
+ class AccessCtrl
+ # [Ident] the value of this expression
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('access_ctrl')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :access_ctrl, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # VCall represent any plain named object with Ruby that could be either a
+ # local variable or a method call.
+ #
+ # variable
+ #
+ class VCall
+ # [Ident] the value of this expression
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('vcall')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :vcall, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_vcall: (Ident ident) -> AccessCtrl | VCall
+ def on_vcall(ident)
+ @controls ||= %w[private protected public].freeze
+
+ if @controls.include?(ident.value) && ident.value == lines[lineno - 1].strip
+ # Access controls like private, protected, and public are reported as
+ # vcall nodes since they're technically method calls. We want to be able
+ # add new lines around them as necessary, so here we're going to
+ # explicitly track those as a different node type.
+ AccessCtrl.new(value: ident, location: ident.location)
+ else
+ VCall.new(value: ident, location: ident.location)
+ end
+ end
+
+ # VoidStmt represents an empty lexical block of code.
+ #
+ # ;;
+ #
+ class VoidStmt
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(location:)
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') { q.text('void_stmt') }
+ end
+
+ def to_json(*opts)
+ { type: :void_stmt, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_void_stmt: () -> VoidStmt
+ def on_void_stmt
+ VoidStmt.new(location: Location.fixed(line: lineno, char: char_pos))
+ end
+
+ # When represents a +when+ clause in a +case+ chain.
+ #
+ # case value
+ # when predicate
+ # end
+ #
+ class When
+ # [untyped] the arguments to the when clause
+ attr_reader :arguments
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [nil | Else | When] the next clause in the chain
+ attr_reader :consequent
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, statements:, consequent:, location:)
+ @arguments = arguments
+ @statements = statements
+ @consequent = consequent
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('when')
+
+ q.breakable
+ q.pp(arguments)
+
+ q.breakable
+ q.pp(statements)
+
+ if consequent
+ q.breakable
+ q.pp(consequent)
+ end
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :when,
+ args: arguments,
+ stmts: statements,
+ cons: consequent,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_when: (
+ # untyped arguments,
+ # Statements statements,
+ # (nil | Else | When) consequent
+ # ) -> When
+ def on_when(arguments, statements, consequent)
+ beginning = find_token(Kw, 'when')
+ ending = consequent || find_token(Kw, 'end')
+
+ statements.bind(arguments.location.end_char, ending.location.start_char)
+
+ When.new(
+ arguments: arguments,
+ statements: statements,
+ consequent: consequent,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # While represents a +while+ loop.
+ #
+ # while predicate
+ # end
+ #
+ class While
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Statements] the expressions to be executed
+ attr_reader :statements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(predicate:, statements:, location:)
+ @predicate = predicate
+ @statements = statements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('while')
+
+ q.breakable
+ q.pp(predicate)
+
+ q.breakable
+ q.pp(statements)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :while,
+ pred: predicate,
+ stmts: statements,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_while: (untyped predicate, Statements statements) -> While
+ def on_while(predicate, statements)
+ beginning = find_token(Kw, 'while')
+ ending = find_token(Kw, 'end')
+
+ # Consume the do keyword if it exists so that it doesn't get confused for
+ # some other block
+ keyword = find_token(Kw, 'do', consume: false)
+ if keyword && keyword.location.start_char > predicate.location.end_char &&
+ keyword.location.end_char < ending.location.start_char
+ tokens.delete(keyword)
+ end
+
+ # Update the Statements location information
+ statements.bind(predicate.location.end_char, ending.location.start_char)
+
+ While.new(
+ predicate: predicate,
+ statements: statements,
+ location: beginning.location.to(ending.location)
+ )
+ end
+
+ # WhileMod represents the modifier form of a +while+ loop.
+ #
+ # expression while predicate
+ #
+ class WhileMod
+ # [untyped] the expression to be executed
+ attr_reader :statement
+
+ # [untyped] the expression to be checked
+ attr_reader :predicate
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(statement:, predicate:, location:)
+ @statement = statement
+ @predicate = predicate
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('while_mod')
+
+ q.breakable
+ q.pp(statement)
+
+ q.breakable
+ q.pp(predicate)
+ end
+ end
+
+ def to_json(*opts)
+ {
+ type: :while_mod,
+ stmt: statement,
+ pred: predicate,
+ loc: location
+ }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_while_mod: (untyped predicate, untyped statement) -> WhileMod
+ def on_while_mod(predicate, statement)
+ find_token(Kw, 'while')
+
+ WhileMod.new(
+ statement: statement,
+ predicate: predicate,
+ location: statement.location.to(predicate.location)
+ )
+ end
+
+ # Word represents an element within a special array literal that accepts
+ # interpolation.
+ #
+ # %W[a#{b}c xyz]
+ #
+ # In the example above, there would be two Word nodes within a parent Words
+ # node.
+ class Word
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # word
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, location:)
+ @parts = parts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('word')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :word, parts: parts, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_word_add: (
+ # Word word,
+ # (StringEmbExpr | StringDVar | TStringContent) part
+ # ) -> Word
+ def on_word_add(word, part)
+ location =
+ word.parts.empty? ? part.location : word.location.to(part.location)
+
+ Word.new(parts: word.parts << part, location: location)
+ end
+
+ # :call-seq:
+ # on_word_new: () -> Word
+ def on_word_new
+ Word.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
+ end
+
+ # Words represents a string literal array with interpolation.
+ #
+ # %W[one two three]
+ #
+ class Words
+ # [Array[ Word ]] the elements of this array
+ attr_reader :elements
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(elements:, location:)
+ @elements = elements
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('words')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(elements) { |element| q.pp(element) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :words, elems: elements, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_words_add: (Words words, Word word) -> Words
+ def on_words_add(words, word)
+ Words.new(
+ elements: words.elements << word,
+ location: words.location.to(word.location)
+ )
+ end
+
+ # WordsBeg represents the beginning of a string literal array with
+ # interpolation.
+ #
+ # %W[one two three]
+ #
+ # In the snippet above, a WordsBeg would be created with the value of "%W[".
+ # Note that these kinds of arrays can start with a lot of different delimiter
+ # types (e.g., %W| or %W<).
+ class WordsBeg
+ # [String] the start of the word literal array
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_words_beg: (String value) -> WordsBeg
+ def on_words_beg(value)
+ node =
+ WordsBeg.new(
+ value: value,
+ location: Location.token(line: lineno, char: char_pos, size: value.size)
+ )
+
+ tokens << node
+ node
+ end
+
+ # :call-seq:
+ # on_words_new: () -> Words
+ def on_words_new
+ words_beg = find_token(WordsBeg)
+
+ Words.new(elements: [], location: words_beg.location)
+ end
+
+ # def on_words_sep(value)
+ # value
+ # end
+
+ # XString represents the contents of an XStringLiteral.
+ #
+ # `ls`
+ #
+ class XString
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # xstring
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, location:)
+ @parts = parts
+ @location = location
+ end
+ end
+
+ # :call-seq:
+ # on_xstring_add: (
+ # XString xstring,
+ # (StringEmbExpr | StringDVar | TStringContent) part
+ # ) -> XString
+ def on_xstring_add(xstring, part)
+ XString.new(
+ parts: xstring.parts << part,
+ location: xstring.location.to(part.location)
+ )
+ end
+
+ # :call-seq:
+ # on_xstring_new: () -> XString
+ def on_xstring_new
+ heredoc = @heredocs[-1]
+
+ location =
+ if heredoc && heredoc.beginning.value.include?('`')
+ heredoc.location
+ else
+ find_token(Backtick).location
+ end
+
+ XString.new(parts: [], location: location)
+ end
+
+ # XStringLiteral represents a string that gets executed.
+ #
+ # `ls`
+ #
+ class XStringLiteral
+ # [Array[ StringEmbExpr | StringDVar | TStringContent ]] the parts of the
+ # xstring
+ attr_reader :parts
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(parts:, location:)
+ @parts = parts
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('xstring_literal')
+
+ q.breakable
+ q.group(2, '(', ')') { q.seplist(parts) { |part| q.pp(part) } }
+ end
+ end
+
+ def to_json(*opts)
+ { type: :xstring_literal, parts: parts, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_xstring_literal: (XString xstring) -> Heredoc | XStringLiteral
+ def on_xstring_literal(xstring)
+ heredoc = @heredocs[-1]
+
+ if heredoc && heredoc.beginning.value.include?('`')
+ Heredoc.new(
+ beginning: heredoc.beginning,
+ ending: heredoc.ending,
+ parts: xstring.parts,
+ location: heredoc.location
+ )
+ else
+ ending = find_token(TStringEnd)
+
+ XStringLiteral.new(
+ parts: xstring.parts,
+ location: xstring.location.to(ending.location)
+ )
+ end
+ end
+
+ # Yield represents using the +yield+ keyword with arguments.
+ #
+ # yield value
+ #
+ class Yield
+ # [ArgsAddBlock | Paren] the arguments passed to the yield
+ attr_reader :arguments
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(arguments:, location:)
+ @arguments = arguments
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('yield')
+
+ q.breakable
+ q.pp(arguments)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :yield, args: arguments, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_yield: ((ArgsAddBlock | Paren) arguments) -> Yield
+ def on_yield(arguments)
+ keyword = find_token(Kw, 'yield')
+
+ Yield.new(
+ arguments: arguments,
+ location: keyword.location.to(arguments.location)
+ )
+ end
+
+ # Yield0 represents the bare +yield+ keyword with no arguments.
+ #
+ # yield
+ #
+ class Yield0
+ # [String] the value of the keyword
+ attr_reader :value
+
+ # [Location] the location of this node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('yield0')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :yield0, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_yield0: () -> Yield0
+ def on_yield0
+ keyword = find_token(Kw, 'yield')
+
+ Yield0.new(value: keyword.value, location: keyword.location)
+ end
+
+ # ZSuper represents the bare +super+ keyword with no arguments.
+ #
+ # super
+ #
+ class ZSuper
+ # [String] the value of the keyword
+ attr_reader :value
+
+ # [Location] the location of the node
+ attr_reader :location
+
+ def initialize(value:, location:)
+ @value = value
+ @location = location
+ end
+
+ def pretty_print(q)
+ q.group(2, '(', ')') do
+ q.text('zsuper')
+
+ q.breakable
+ q.pp(value)
+ end
+ end
+
+ def to_json(*opts)
+ { type: :zsuper, value: value, loc: location }.to_json(*opts)
+ end
+ end
+
+ # :call-seq:
+ # on_zsuper: () -> ZSuper
+ def on_zsuper
+ keyword = find_token(Kw, 'super')
+
+ ZSuper.new(value: keyword.value, location: keyword.location)
+ end
+end
diff --git a/spec/syntax_suggest/fixtures/this_project_extra_def.rb.txt b/spec/syntax_suggest/fixtures/this_project_extra_def.rb.txt
new file mode 100644
index 0000000000..e62fd3fa66
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/this_project_extra_def.rb.txt
@@ -0,0 +1,64 @@
+module SyntaxErrorSearch
+ # Used for formatting invalid blocks
+ class DisplayInvalidBlocks
+ attr_reader :filename
+
+ def initialize(block_array, io: $stderr, filename: nil)
+ @filename = filename
+ @io = io
+ @blocks = block_array
+ @lines = @blocks.map(&:lines).flatten
+ @digit_count = @lines.last.line_number.to_s.length
+ @code_lines = @blocks.first.code_lines
+
+ @invalid_line_hash = @lines.each_with_object({}) {|line, h| h[line] = true}
+ end
+
+ def call
+ @io.puts <<~EOM
+
+ SyntaxSuggest: A syntax error was detected
+
+ This code has an unmatched `end` this is caused by either
+ missing a syntax keyword (`def`, `do`, etc.) or inclusion
+ of an extra `end` line:
+ EOM
+
+ @io.puts(<<~EOM) if filename
+ file: #{filename}
+ EOM
+
+ @io.puts <<~EOM
+ #{code_with_filename}
+ EOM
+ end
+
+ def filename
+
+ def code_with_filename
+ string = String.new("")
+ string << "```\n"
+ string << "#".rjust(@digit_count) + " filename: #{filename}\n\n" if filename
+ string << code_with_lines
+ string << "```\n"
+ string
+ end
+
+ def code_with_lines
+ @code_lines.map do |line|
+ next if line.hidden?
+ number = line.line_number.to_s.rjust(@digit_count)
+ if line.empty?
+ "#{number.to_s}#{line}"
+ else
+ string = String.new
+ string << "\e[1;3m" if @invalid_line_hash[line] # Bold, italics
+ string << "#{number.to_s} "
+ string << line.to_s
+ string << "\e[0m"
+ string
+ end
+ end.join
+ end
+ end
+end
diff --git a/spec/syntax_suggest/fixtures/webmock.rb.txt b/spec/syntax_suggest/fixtures/webmock.rb.txt
new file mode 100644
index 0000000000..16da0d2ac0
--- /dev/null
+++ b/spec/syntax_suggest/fixtures/webmock.rb.txt
@@ -0,0 +1,35 @@
+describe "webmock tests" do
+ before(:each) do
+ WebMock.enable!
+ end
+
+ after(:each) do
+ WebMock.disable!
+ end
+
+ it "port" do
+ port = rand(1000...9999)
+ stub_request(:any, "localhost:#{port}")
+
+ query = Cutlass::FunctionQuery.new(
+ port: port
+ ).call
+
+ expect(WebMock).to have_requested(:post, "localhost:#{port}").
+ with(body: "{}")
+ end
+
+ it "body" do
+ body = { lol: "hi" }
+ port = 8080
+ stub_request(:any, "localhost:#{port}")
+
+ query = Cutlass::FunctionQuery.new(
+ port: port
+ body: body
+ ).call
+
+ expect(WebMock).to have_requested(:post, "localhost:#{port}").
+ with(body: body.to_json)
+ end
+end
diff --git a/spec/syntax_suggest/integration/exe_cli_spec.rb b/spec/syntax_suggest/integration/exe_cli_spec.rb
new file mode 100644
index 0000000000..b9a3173715
--- /dev/null
+++ b/spec/syntax_suggest/integration/exe_cli_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "exe" do
+ def exe_path
+ if ruby_core?
+ root_dir.join("../libexec").join("syntax_suggest")
+ else
+ root_dir.join("exe").join("syntax_suggest")
+ end
+ end
+
+ def exe(cmd)
+ ruby = ENV.fetch("RUBY", "ruby")
+ out = run!("#{ruby} #{exe_path} #{cmd}", raise_on_nonzero_exit: false)
+ puts out if ENV["SYNTAX_SUGGEST_DEBUG"]
+ out
+ end
+
+ it "prints the version" do
+ out = exe("-v")
+ expect(out.strip).to include(SyntaxSuggest::VERSION)
+ end
+ end
+end
diff --git a/spec/syntax_suggest/integration/ruby_command_line_spec.rb b/spec/syntax_suggest/integration/ruby_command_line_spec.rb
new file mode 100644
index 0000000000..b41a4c86e3
--- /dev/null
+++ b/spec/syntax_suggest/integration/ruby_command_line_spec.rb
@@ -0,0 +1,193 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ ruby = ENV.fetch("RUBY", "ruby")
+ RSpec.describe "Requires with ruby cli" do
+ it "namespaces all monkeypatched methods" do
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ script.write <<~'EOM'
+ puts Kernel.private_methods
+ EOM
+
+ syntax_suggest_methods_file = tmpdir.join("syntax_suggest_methods.txt")
+ api_only_methods_file = tmpdir.join("api_only_methods.txt")
+ kernel_methods_file = tmpdir.join("kernel_methods.txt")
+
+ d_pid = Process.spawn("#{ruby} -I#{lib_dir} -rsyntax_suggest #{script} 2>&1 > #{syntax_suggest_methods_file}")
+ k_pid = Process.spawn("#{ruby} #{script} 2>&1 >> #{kernel_methods_file}")
+ r_pid = Process.spawn("#{ruby} -I#{lib_dir} -rsyntax_suggest/api #{script} 2>&1 > #{api_only_methods_file}")
+
+ Process.wait(k_pid)
+ Process.wait(d_pid)
+ Process.wait(r_pid)
+
+ kernel_methods_array = kernel_methods_file.read.strip.lines.map(&:strip)
+ syntax_suggest_methods_array = syntax_suggest_methods_file.read.strip.lines.map(&:strip)
+ api_only_methods_array = api_only_methods_file.read.strip.lines.map(&:strip)
+
+ # In ruby 3.1.0-preview1 the `timeout` file is already required
+ # we can remove it if it exists to normalize the output for
+ # all ruby versions
+ [syntax_suggest_methods_array, kernel_methods_array, api_only_methods_array].each do |array|
+ array.delete("timeout")
+ end
+
+ methods = (syntax_suggest_methods_array - kernel_methods_array).sort
+ if methods.any?
+ expect(methods).to eq(["syntax_suggest_original_load", "syntax_suggest_original_require", "syntax_suggest_original_require_relative"])
+ end
+
+ methods = (api_only_methods_array - kernel_methods_array).sort
+ expect(methods).to eq([])
+ end
+ end
+
+ # Since Ruby 3.2 includes syntax_suggest as a default gem, we might accidentally
+ # be requiring the default gem instead of this library under test. Assert that's
+ # not the case
+ it "tests current version of syntax_suggest" do
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ contents = <<~'EOM'
+ puts "suggest_version is #{SyntaxSuggest::VERSION}"
+ EOM
+ script.write(contents)
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest/version #{script} 2>&1`
+
+ expect(out).to include("suggest_version is #{SyntaxSuggest::VERSION}").once
+ end
+ end
+
+ it "detects require error and adds a message with auto mode" do
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ script.write <<~EOM
+ describe "things" do
+ it "blerg" do
+ end
+
+ it "flerg"
+ end
+
+ it "zlerg" do
+ end
+ end
+ EOM
+
+ require_rb = tmpdir.join("require.rb")
+ require_rb.write <<~EOM
+ load "#{script.expand_path}"
+ EOM
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest #{require_rb} 2>&1`
+
+ expect($?.success?).to be_falsey
+ expect(out).to include('> 5 it "flerg"').once
+ end
+ end
+
+ it "gem can be tested when executing on Ruby with default gem included" do
+ skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest -e "puts SyntaxError.instance_method(:detailed_message).source_location" 2>&1`
+
+ expect($?.success?).to be_truthy
+ expect(out).to include(lib_dir.join("syntax_suggest").join("core_ext.rb").to_s).once
+ end
+
+ it "annotates a syntax error in Ruby 3.2+ when require is not used" do
+ skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")
+
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ script.write <<~EOM
+ describe "things" do
+ it "blerg" do
+ end
+
+ it "flerg"
+ end
+
+ it "zlerg" do
+ end
+ end
+ EOM
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest #{script} 2>&1`
+
+ expect($?.success?).to be_falsey
+ expect(out).to include('> 5 it "flerg"').once
+ end
+ end
+
+ it "does not load internals into memory if no syntax error" do
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ script.write <<~EOM
+ class Dog
+ end
+
+ if defined?(SyntaxSuggest::DEFAULT_VALUE)
+ puts "SyntaxSuggest is loaded"
+ else
+ puts "SyntaxSuggest is NOT loaded"
+ end
+ EOM
+
+ require_rb = tmpdir.join("require.rb")
+ require_rb.write <<~EOM
+ load "#{script.expand_path}"
+ EOM
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest #{require_rb} 2>&1`
+
+ expect($?.success?).to be_truthy
+ expect(out).to include("SyntaxSuggest is NOT loaded").once
+ end
+ end
+
+ it "ignores eval" do
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ script.write <<~'EOM'
+ $stderr = STDOUT
+ eval("def lol")
+ EOM
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest #{script} 2>&1`
+
+ expect($?.success?).to be_falsey
+ expect(out).to include("(eval):1")
+
+ expect(out).to_not include("SyntaxSuggest")
+ expect(out).to_not include("Could not find filename")
+ end
+ end
+
+ it "does not say 'syntax ok' when a syntax error fires" do
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ script = tmpdir.join("script.rb")
+ script.write <<~'EOM'
+ break
+ EOM
+
+ out = `#{ruby} -I#{lib_dir} -rsyntax_suggest -e "require_relative '#{script}'" 2>&1`
+
+ expect($?.success?).to be_falsey
+ expect(out.downcase).to_not include("syntax ok")
+ expect(out).to include("Invalid break")
+ end
+ end
+ end
+end
diff --git a/spec/syntax_suggest/integration/syntax_suggest_spec.rb b/spec/syntax_suggest/integration/syntax_suggest_spec.rb
new file mode 100644
index 0000000000..64dafabcdd
--- /dev/null
+++ b/spec/syntax_suggest/integration/syntax_suggest_spec.rb
@@ -0,0 +1,239 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "Integration tests that don't spawn a process (like using the cli)" do
+ it "does not timeout on massive files" do
+ next unless ENV["SYNTAX_SUGGEST_TIMEOUT"]
+
+ file = fixtures_dir.join("syntax_tree.rb.txt")
+ lines = file.read.lines
+ lines.delete_at(768 - 1)
+
+ io = StringIO.new
+
+ benchmark = Benchmark.measure do
+ debug_perf do
+ SyntaxSuggest.call(
+ io: io,
+ source: lines.join,
+ filename: file
+ )
+ end
+ end
+
+ debug_display(io.string)
+ debug_display(benchmark)
+
+ expect(io.string).to include(<<~'EOM')
+ 6 class SyntaxTree < Ripper
+ 170 def self.parse(source)
+ 174 end
+ > 754 def on_args_add(arguments, argument)
+ > 776 class ArgsAddBlock
+ > 810 end
+ 9233 end
+ EOM
+ end
+
+ it "re-checks all block code, not just what's visible issues/95" do
+ file = fixtures_dir.join("ruby_buildpack.rb.txt")
+ io = StringIO.new
+
+ debug_perf do
+ benchmark = Benchmark.measure do
+ SyntaxSuggest.call(
+ io: io,
+ source: file.read,
+ filename: file
+ )
+ end
+ debug_display(io.string)
+ debug_display(benchmark)
+ end
+
+ expect(io.string).to_not include("def ruby_install_binstub_path")
+ expect(io.string).to include(<<~'EOM')
+ > 1067 def add_yarn_binary
+ > 1068 return [] if yarn_preinstalled?
+ > 1069 |
+ > 1075 end
+ EOM
+ end
+
+ it "returns good results on routes.rb" do
+ source = fixtures_dir.join("routes.rb.txt").read
+
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ debug_display(io.string)
+
+ expect(io.string).to include(<<~'EOM')
+ 1 Rails.application.routes.draw do
+ > 113 namespace :admin do
+ > 116 match "/foobar(*path)", via: :all, to: redirect { |_params, req|
+ > 120 }
+ 121 end
+ EOM
+ end
+
+ it "handles multi-line-methods issues/64" do
+ source = fixtures_dir.join("webmock.rb.txt").read
+
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ debug_display(io.string)
+
+ expect(io.string).to include(<<~'EOM')
+ 1 describe "webmock tests" do
+ 22 it "body" do
+ 27 query = Cutlass::FunctionQuery.new(
+ > 28 port: port
+ > 29 body: body
+ 30 ).call
+ 34 end
+ 35 end
+ EOM
+ end
+
+ it "handles derailed output issues/50" do
+ source = fixtures_dir.join("derailed_require_tree.rb.txt").read
+
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ debug_display(io.string)
+
+ expect(io.string).to include(<<~'EOM')
+ 5 module DerailedBenchmarks
+ 6 class RequireTree
+ > 13 def initialize(name)
+ > 18 def self.reset!
+ > 25 end
+ 73 end
+ 74 end
+ EOM
+ end
+
+ it "handles heredocs" do
+ lines = fixtures_dir.join("rexe.rb.txt").read.lines
+ lines.delete_at(85 - 1)
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: lines.join
+ )
+
+ out = io.string
+ debug_display(out)
+
+ expect(out).to include(<<~EOM)
+ 16 class Rexe
+ > 77 class Lookups
+ > 78 def input_modes
+ > 148 end
+ 551 end
+ EOM
+ end
+
+ it "rexe" do
+ lines = fixtures_dir.join("rexe.rb.txt").read.lines
+ lines.delete_at(148 - 1)
+ source = lines.join
+
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ out = io.string
+ expect(out).to include(<<~EOM)
+ 16 class Rexe
+ > 77 class Lookups
+ > 140 def format_requires
+ > 148 end
+ 551 end
+ EOM
+ end
+
+ it "ambiguous end" do
+ source = <<~'EOM'
+ def call # 0
+ print "lol" # 1
+ end # one # 2
+ end # two # 3
+ EOM
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ out = io.string
+ expect(out).to include(<<~EOM)
+ > 1 def call # 0
+ > 3 end # one # 2
+ > 4 end # two # 3
+ EOM
+ end
+
+ it "simple regression" do
+ source = <<~'EOM'
+ class Dog
+ def bark
+ puts "woof"
+ end
+ EOM
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ out = io.string
+ expect(out).to include(<<~EOM)
+ > 1 class Dog
+ > 2 def bark
+ > 4 end
+ EOM
+ end
+
+ it "empty else" do
+ source = <<~'EOM'
+ class Foo
+ def foo
+ if cond?
+ foo
+ else
+
+ end
+ end
+
+ # ...
+
+ def bar
+ if @recv
+ end_is_missing_here
+ end
+ end
+ EOM
+
+ io = StringIO.new
+ SyntaxSuggest.call(
+ io: io,
+ source: source
+ )
+ out = io.string
+ expect(out).to include(<<~EOM)
+ end_is_missing_here
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/spec_helper.rb b/spec/syntax_suggest/spec_helper.rb
new file mode 100644
index 0000000000..89bc9f4ab1
--- /dev/null
+++ b/spec/syntax_suggest/spec_helper.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require "bundler/setup"
+require "syntax_suggest/api"
+
+require "benchmark"
+require "tempfile"
+
+RSpec.configure do |config|
+ # Enable flags like --only-failures and --next-failure
+ config.example_status_persistence_file_path = ".rspec_status"
+
+ # Disable RSpec exposing methods globally on `Module` and `main`
+ config.disable_monkey_patching!
+
+ config.expect_with :rspec do |c|
+ c.syntax = :expect
+ end
+
+ if config.color_mode == :automatic
+ if config.color_enabled? && ((ENV["TERM"] == "dumb") || ENV["NO_COLOR"]&.slice(0))
+ config.color_mode = :off
+ end
+ end
+end
+
+# Used for debugging modifications to
+# display output
+def debug_display(output)
+ return unless ENV["DEBUG_DISPLAY"]
+ puts
+ puts output
+ puts
+end
+
+def spec_dir
+ Pathname(__dir__)
+end
+
+def lib_dir
+ if ruby_core?
+ root_dir.join("../lib")
+ else
+ root_dir.join("lib")
+ end
+end
+
+def root_dir
+ spec_dir.join("..")
+end
+
+def fixtures_dir
+ spec_dir.join("fixtures")
+end
+
+def ruby_core?
+ !root_dir.join("syntax_suggest.gemspec").exist?
+end
+
+def code_line_array(source)
+ SyntaxSuggest::CleanDocument.new(source: source).call.lines
+end
+
+autoload :RubyProf, "ruby-prof"
+
+def debug_perf
+ raise "No block given" unless block_given?
+
+ if ENV["DEBUG_PERF"]
+ out = nil
+ result = RubyProf.profile do
+ out = yield
+ end
+
+ dir = SyntaxSuggest.record_dir("tmp")
+ printer = RubyProf::MultiPrinter.new(result, [:flat, :graph, :graph_html, :tree, :call_tree, :stack, :dot])
+ printer.print(path: dir, profile: "profile")
+
+ out
+ else
+ yield
+ end
+end
+
+def run!(cmd, raise_on_nonzero_exit: true)
+ out = `#{cmd} 2>&1`
+ raise "Command: #{cmd} failed: #{out}" if !$?.success? && raise_on_nonzero_exit
+ out
+end
+
+# Allows us to write cleaner tests since <<~EOM block quotes
+# strip off all leading indentation and we need it to be preserved
+# sometimes.
+class String
+ def indent(number)
+ lines.map do |line|
+ if line.chomp.empty?
+ line
+ else
+ " " * number + line
+ end
+ end.join
+ end
+end
diff --git a/spec/syntax_suggest/unit/api_spec.rb b/spec/syntax_suggest/unit/api_spec.rb
new file mode 100644
index 0000000000..079a91e46d
--- /dev/null
+++ b/spec/syntax_suggest/unit/api_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+begin
+ require "ruby-prof"
+rescue LoadError
+end
+
+module SyntaxSuggest
+ RSpec.describe "Top level SyntaxSuggest api" do
+ it "has a `handle_error` interface" do
+ fake_error = Object.new
+ def fake_error.message
+ "#{__FILE__}:216: unterminated string meets end of file "
+ end
+
+ def fake_error.is_a?(v)
+ true
+ end
+
+ io = StringIO.new
+ SyntaxSuggest.handle_error(
+ fake_error,
+ re_raise: false,
+ io: io
+ )
+
+ expect(io.string.strip).to eq("")
+ end
+
+ it "raises original error with warning if a non-syntax error is passed" do
+ error = NameError.new("blerg")
+ io = StringIO.new
+ expect {
+ SyntaxSuggest.handle_error(
+ error,
+ re_raise: false,
+ io: io
+ )
+ }.to raise_error { |e|
+ expect(io.string).to include("Must pass a SyntaxError")
+ expect(e).to eq(error)
+ }
+ end
+
+ it "raises original error with warning if file is not found" do
+ fake_error = SyntaxError.new
+ def fake_error.message
+ "#does/not/exist/lol/doesnotexist:216: unterminated string meets end of file "
+ end
+
+ io = StringIO.new
+ expect {
+ SyntaxSuggest.handle_error(
+ fake_error,
+ re_raise: false,
+ io: io
+ )
+ }.to raise_error { |e|
+ expect(io.string).to include("Could not find filename")
+ expect(e).to eq(fake_error)
+ }
+ end
+
+ it "respects highlight API" do
+ skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")
+
+ core_ext_file = lib_dir.join("syntax_suggest").join("core_ext.rb")
+ require_relative core_ext_file
+
+ error_klass = Class.new do
+ def path
+ fixtures_dir.join("this_project_extra_def.rb.txt")
+ end
+
+ def detailed_message(**kwargs)
+ "error"
+ end
+ end
+ error_klass.prepend(SyntaxSuggest.module_for_detailed_message)
+ error = error_klass.new
+
+ expect(error.detailed_message(highlight: true)).to include(SyntaxSuggest::DisplayCodeWithLineNumbers::TERMINAL_HIGHLIGHT)
+ expect(error.detailed_message(highlight: false)).to_not include(SyntaxSuggest::DisplayCodeWithLineNumbers::TERMINAL_HIGHLIGHT)
+ end
+
+ it "can be disabled via falsey kwarg" do
+ skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")
+
+ core_ext_file = lib_dir.join("syntax_suggest").join("core_ext.rb")
+ require_relative core_ext_file
+
+ error_klass = Class.new do
+ def path
+ fixtures_dir.join("this_project_extra_def.rb.txt")
+ end
+
+ def detailed_message(**kwargs)
+ "error"
+ end
+ end
+ error_klass.prepend(SyntaxSuggest.module_for_detailed_message)
+ error = error_klass.new
+
+ expect(error.detailed_message(syntax_suggest: true)).to_not eq(error.detailed_message(syntax_suggest: false))
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/around_block_scan_spec.rb b/spec/syntax_suggest/unit/around_block_scan_spec.rb
new file mode 100644
index 0000000000..d6756448bd
--- /dev/null
+++ b/spec/syntax_suggest/unit/around_block_scan_spec.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe AroundBlockScan do
+ it "continues scan from last location even if scan is false" do
+ source = <<~'EOM'
+ print 'omg'
+ print 'lol'
+ print 'haha'
+ EOM
+ code_lines = CodeLine.from_source(source)
+ block = CodeBlock.new(lines: code_lines[1])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ .scan_neighbors_not_empty
+
+ expect(expand.code_block.to_s).to eq(source)
+ expand.scan_while { |line| false }
+
+ expect(expand.code_block.to_s).to eq(source)
+ end
+
+ it "scan_adjacent_indent works on first or last line" do
+ source_string = <<~EOM
+ def foo
+ if [options.output_format_tty, options.output_format_block].include?(nil)
+ raise("Bad output mode '\#{v}'; each must be one of \#{lookups.output_formats.keys}.")
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: code_lines[4])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ .scan_adjacent_indent
+
+ expect(expand.code_block.to_s).to eq(<<~EOM)
+ def foo
+ if [options.output_format_tty, options.output_format_block].include?(nil)
+ raise("Bad output mode '\#{v}'; each must be one of \#{lookups.output_formats.keys}.")
+ end
+ end
+ EOM
+ end
+
+ it "expands indentation" do
+ source_string = <<~EOM
+ def foo
+ if [options.output_format_tty, options.output_format_block].include?(nil)
+ raise("Bad output mode '\#{v}'; each must be one of \#{lookups.output_formats.keys}.")
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: code_lines[2])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ .stop_after_kw
+ .scan_adjacent_indent
+
+ expect(expand.code_block.to_s).to eq(<<~EOM.indent(2))
+ if [options.output_format_tty, options.output_format_block].include?(nil)
+ raise("Bad output mode '\#{v}'; each must be one of \#{lookups.output_formats.keys}.")
+ end
+ EOM
+ end
+
+ it "can stop before hitting another end" do
+ source_string = <<~EOM
+ def lol
+ end
+ def foo
+ puts "lol"
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: code_lines[3])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ expand.stop_after_kw
+ expand.scan_while { true }
+
+ expect(expand.code_block.to_s).to eq(<<~EOM)
+ def foo
+ puts "lol"
+ end
+ EOM
+ end
+
+ it "captures multiple empty and hidden lines" do
+ source_string = <<~EOM
+ def foo
+ Foo.call
+
+ puts "lol"
+
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: code_lines[3])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ expand.scan_while { true }
+
+ expect(expand.lines.first.index).to eq(0)
+ expect(expand.lines.last.index).to eq(6)
+ expect(expand.code_block.to_s).to eq(source_string)
+ end
+
+ it "only takes what you ask" do
+ source_string = <<~EOM
+ def foo
+ Foo.call
+
+ puts "lol"
+
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: code_lines[3])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ expand.scan_while { |line| line.not_empty? }
+
+ expect(expand.code_block.to_s).to eq(<<~EOM.indent(4))
+ puts "lol"
+ EOM
+ end
+
+ it "skips what you want" do
+ source_string = <<~EOM
+ def foo
+ Foo.call
+
+ puts "haha"
+ # hide me
+
+ puts "lol"
+
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ code_lines[4].mark_invisible
+
+ block = CodeBlock.new(lines: code_lines[3])
+ expand = AroundBlockScan.new(code_lines: code_lines, block: block)
+ expand.force_add_empty
+ expand.force_add_hidden
+ expand.scan_neighbors_not_empty
+
+ expect(expand.code_block.to_s).to eq(<<~EOM.indent(4))
+
+ puts "haha"
+
+ puts "lol"
+
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/block_expand_spec.rb b/spec/syntax_suggest/unit/block_expand_spec.rb
new file mode 100644
index 0000000000..5cff73621d
--- /dev/null
+++ b/spec/syntax_suggest/unit/block_expand_spec.rb
@@ -0,0 +1,230 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe BlockExpand do
+ it "empty line in methods" do
+ source_string = <<~EOM
+ class Dog # index 0
+ def bark # index 1
+
+ end # index 3
+
+ def sit # index 5
+ print "sit" # index 6
+ end # index 7
+ end # index 8
+ end # extra end
+ EOM
+
+ code_lines = code_line_array(source_string)
+
+ sit = code_lines[4..7]
+ sit.each(&:mark_invisible)
+
+ block = CodeBlock.new(lines: sit)
+ expansion = BlockExpand.new(code_lines: code_lines)
+ block = expansion.expand_neighbors(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(2))
+ def bark # index 1
+
+ end # index 3
+ EOM
+ end
+
+ it "captures multiple empty and hidden lines" do
+ source_string = <<~EOM
+ def foo
+ Foo.call
+
+
+ puts "lol"
+
+ # hidden
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+
+ code_lines[6].mark_invisible
+
+ block = CodeBlock.new(lines: [code_lines[3]])
+ expansion = BlockExpand.new(code_lines: code_lines)
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(4))
+
+
+ puts "lol"
+
+ EOM
+ end
+
+ it "captures multiple empty lines" do
+ source_string = <<~EOM
+ def foo
+ Foo.call
+
+
+ puts "lol"
+
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: [code_lines[3]])
+ expansion = BlockExpand.new(code_lines: code_lines)
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(4))
+
+
+ puts "lol"
+
+ EOM
+ end
+
+ it "expands neighbors then indentation" do
+ source_string = <<~EOM
+ def foo
+ Foo.call
+ puts "hey"
+ puts "lol"
+ puts "sup"
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: [code_lines[3]])
+ expansion = BlockExpand.new(code_lines: code_lines)
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(4))
+ puts "hey"
+ puts "lol"
+ puts "sup"
+ EOM
+
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(2))
+ Foo.call
+ puts "hey"
+ puts "lol"
+ puts "sup"
+ end
+ EOM
+ end
+
+ it "handles else code" do
+ source_string = <<~EOM
+ Foo.call
+ if blerg
+ puts "lol"
+ else
+ puts "haha"
+ end
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ block = CodeBlock.new(lines: [code_lines[2]])
+ expansion = BlockExpand.new(code_lines: code_lines)
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(2))
+ if blerg
+ puts "lol"
+ else
+ puts "haha"
+ end
+ EOM
+ end
+
+ it "expand until next boundry (indentation)" do
+ source_string = <<~EOM
+ describe "what" do
+ Foo.call
+ end
+
+ describe "hi"
+ Bar.call do
+ Foo.call
+ end
+ end
+
+ it "blerg" do
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+
+ block = CodeBlock.new(
+ lines: code_lines[6]
+ )
+
+ expansion = BlockExpand.new(code_lines: code_lines)
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM.indent(2))
+ Bar.call do
+ Foo.call
+ end
+ EOM
+
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM)
+ describe "hi"
+ Bar.call do
+ Foo.call
+ end
+ end
+ EOM
+ end
+
+ it "expand until next boundry (empty lines)" do
+ source_string = <<~EOM
+ describe "what" do
+ end
+
+ describe "hi"
+ end
+
+ it "blerg" do
+ end
+ EOM
+
+ code_lines = code_line_array(source_string)
+ expansion = BlockExpand.new(code_lines: code_lines)
+
+ block = CodeBlock.new(lines: code_lines[3])
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM)
+
+ describe "hi"
+ end
+
+ EOM
+
+ block = expansion.call(block)
+
+ expect(block.to_s).to eq(<<~EOM)
+ describe "what" do
+ end
+
+ describe "hi"
+ end
+
+ it "blerg" do
+ end
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb b/spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb
new file mode 100644
index 0000000000..02d9be4387
--- /dev/null
+++ b/spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require_relative "../../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe Capture::BeforeAfterKeywordEnds do
+ it "before after keyword ends" do
+ source = <<~'EOM'
+ def nope
+ print 'not me'
+ end
+
+ def lol
+ print 'lol'
+ end
+
+ def hello # 8
+
+ def yolo
+ print 'haha'
+ end
+
+ def nada
+ print 'nope'
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[8])
+
+ expect(block.to_s).to include("def hello")
+
+ lines = Capture::BeforeAfterKeywordEnds.new(
+ block: block,
+ code_lines: code_lines
+ ).call
+ lines.sort!
+
+ expect(lines.join).to include(<<~'EOM')
+ def lol
+ end
+ def yolo
+ end
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb b/spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb
new file mode 100644
index 0000000000..61d1642d97
--- /dev/null
+++ b/spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require_relative "../../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe Capture::FallingIndentLines do
+ it "on_falling_indent" do
+ source = <<~'EOM'
+ class OH
+ def lol
+ print 'lol
+ end
+
+ def hello
+ it "foo" do
+ end
+
+ def yolo
+ print 'haha'
+ end
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[6])
+
+ lines = []
+ Capture::FallingIndentLines.new(
+ block: block,
+ code_lines: code_lines
+ ).call do |line|
+ lines << line
+ end
+ lines.sort!
+
+ expect(lines.join).to eq(<<~'EOM')
+ class OH
+ def hello
+ end
+ end
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/capture_code_context_spec.rb b/spec/syntax_suggest/unit/capture_code_context_spec.rb
new file mode 100644
index 0000000000..46f13e8961
--- /dev/null
+++ b/spec/syntax_suggest/unit/capture_code_context_spec.rb
@@ -0,0 +1,229 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe CaptureCodeContext do
+ it "capture_before_after_kws two" do
+ source = <<~'EOM'
+ class OH
+
+ def hello
+
+ def hai
+ end
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[2])
+
+ display = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+ display.capture_before_after_kws(block)
+ expect(display.sorted_lines.join).to eq(<<~'EOM'.indent(2))
+ def hello
+ def hai
+ end
+ EOM
+ end
+
+ it "capture_before_after_kws" do
+ source = <<~'EOM'
+ def sit
+ end
+
+ def bark
+
+ def eat
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[3])
+
+ display = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+
+ lines = display.capture_before_after_kws(block).sort
+ expect(lines.join).to eq(<<~'EOM')
+ def sit
+ end
+ def bark
+ def eat
+ end
+ EOM
+ end
+
+ it "handles ambiguous end" do
+ source = <<~'EOM'
+ def call # 0
+ print "lol" # 1
+ end # one # 2
+ end # two # 3
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ code_lines[0..2].each(&:mark_invisible)
+ block = CodeBlock.new(lines: code_lines)
+
+ display = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+ lines = display.call
+
+ lines = lines.sort.map(&:original)
+
+ expect(lines.join).to eq(<<~'EOM')
+ def call # 0
+ end # one # 2
+ end # two # 3
+ EOM
+ end
+
+ it "shows ends of captured block" do
+ lines = fixtures_dir.join("rexe.rb.txt").read.lines
+ lines.delete_at(148 - 1)
+ source = lines.join
+
+ code_lines = CleanDocument.new(source: source).call.lines
+
+ code_lines[0..75].each(&:mark_invisible)
+ code_lines[77..-1].each(&:mark_invisible)
+ expect(code_lines.join.strip).to eq("class Lookups")
+
+ block = CodeBlock.new(lines: code_lines[76..149])
+
+ display = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+ lines = display.call
+
+ lines = lines.sort.map(&:original)
+ expect(lines.join).to include(<<~'EOM'.indent(2))
+ class Lookups
+ def format_requires
+ end
+ EOM
+ end
+
+ it "shows ends of captured block" do
+ source = <<~'EOM'
+ class Dog
+ def bark
+ puts "woof"
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines)
+ code_lines[1..-1].each(&:mark_invisible)
+
+ expect(block.to_s.strip).to eq("class Dog")
+
+ display = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+ lines = display.call.sort.map(&:original)
+ expect(lines.join).to eq(<<~'EOM')
+ class Dog
+ def bark
+ end
+ EOM
+ end
+
+ it "captures surrounding context on falling indent" do
+ source = <<~'EOM'
+ class Blerg
+ end
+
+ class OH
+
+ def hello
+ it "foo" do
+ end
+ end
+
+ class Zerg
+ end
+ EOM
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[6])
+
+ expect(block.to_s.strip).to eq('it "foo" do')
+
+ display = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+ lines = display.call.sort.map(&:original)
+ expect(lines.join).to eq(<<~'EOM')
+ class OH
+ def hello
+ it "foo" do
+ end
+ end
+ EOM
+ end
+
+ it "captures surrounding context on same indent" do
+ source = <<~'EOM'
+ class Blerg
+ end
+ class OH
+
+ def nope
+ end
+
+ def lol
+ end
+
+ end # here
+
+ def haha
+ end
+
+ def nope
+ end
+ end
+
+ class Zerg
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[7..10])
+ expect(block.to_s).to eq(<<~'EOM'.indent(2))
+ def lol
+ end
+
+ end # here
+ EOM
+
+ code_context = CaptureCodeContext.new(
+ blocks: [block],
+ code_lines: code_lines
+ )
+
+ lines = code_context.call
+ out = DisplayCodeWithLineNumbers.new(
+ lines: lines
+ ).call
+
+ expect(out).to eq(<<~'EOM'.indent(2))
+ 3 class OH
+ 8 def lol
+ 9 end
+ 11 end # here
+ 18 end
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/clean_document_spec.rb b/spec/syntax_suggest/unit/clean_document_spec.rb
new file mode 100644
index 0000000000..25a62e4454
--- /dev/null
+++ b/spec/syntax_suggest/unit/clean_document_spec.rb
@@ -0,0 +1,260 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe CleanDocument do
+ it "heredocs" do
+ source = fixtures_dir.join("this_project_extra_def.rb.txt").read
+ code_lines = CleanDocument.new(source: source).call.lines
+
+ expect(code_lines[18 - 1].to_s).to eq(<<-'EOL')
+ @io.puts <<~EOM
+
+ SyntaxSuggest: A syntax error was detected
+
+ This code has an unmatched `end` this is caused by either
+ missing a syntax keyword (`def`, `do`, etc.) or inclusion
+ of an extra `end` line:
+ EOM
+ EOL
+ expect(code_lines[18].to_s).to eq("")
+
+ expect(code_lines[27 - 1].to_s).to eq(<<-'EOL')
+ @io.puts(<<~EOM) if filename
+ file: #{filename}
+ EOM
+ EOL
+ expect(code_lines[27].to_s).to eq("")
+
+ expect(code_lines[31 - 1].to_s).to eq(<<-'EOL')
+ @io.puts <<~EOM
+ #{code_with_filename}
+ EOM
+ EOL
+ expect(code_lines[31].to_s).to eq("")
+ end
+
+ it "joins: multi line methods" do
+ source = <<~EOM
+ User
+ .where(name: 'schneems')
+ .first
+ EOM
+
+ doc = CleanDocument.new(source: source).join_consecutive!
+
+ expect(doc.lines[0].to_s).to eq(source)
+ expect(doc.lines[1].to_s).to eq("")
+ expect(doc.lines[2].to_s).to eq("")
+ expect(doc.lines[3]).to eq(nil)
+
+ lines = doc.lines
+ expect(
+ DisplayCodeWithLineNumbers.new(
+ lines: lines
+ ).call
+ ).to eq(<<~'EOM'.indent(2))
+ 1 User
+ 2 .where(name: 'schneems')
+ 3 .first
+ EOM
+
+ expect(
+ DisplayCodeWithLineNumbers.new(
+ lines: lines,
+ highlight_lines: lines[0]
+ ).call
+ ).to eq(<<~'EOM')
+ > 1 User
+ > 2 .where(name: 'schneems')
+ > 3 .first
+ EOM
+ end
+
+ it "joins multi-line chained methods when separated by comments" do
+ source = <<~EOM
+ User.
+ # comment
+ where(name: 'schneems').
+ # another comment
+ first
+ EOM
+
+ doc = CleanDocument.new(source: source).join_consecutive!
+ code_lines = doc.lines
+
+ expect(code_lines[0].to_s.count($/)).to eq(5)
+ code_lines[1..-1].each do |line|
+ expect(line.to_s.strip.length).to eq(0)
+ end
+ end
+
+ it "helper method: take_while_including" do
+ source = <<~EOM
+ User
+ .where(name: 'schneems')
+ .first
+ EOM
+
+ doc = CleanDocument.new(source: source)
+
+ lines = doc.take_while_including { |line| !line.to_s.include?("where") }
+ expect(lines.count).to eq(2)
+ end
+
+ it "comments: removes comments" do
+ source = <<~EOM
+ # lol
+ puts "what"
+ # yolo
+ EOM
+
+ lines = CleanDocument.new(source: source).lines
+ expect(lines[0].to_s).to eq($/)
+ expect(lines[1].to_s).to eq('puts "what"' + $/)
+ expect(lines[2].to_s).to eq($/)
+ end
+
+ it "trailing slash: does not join trailing do" do
+ # Some keywords and syntaxes trigger the "ignored line"
+ # lex output, we ignore them by filtering by BEG
+ #
+ # The `do` keyword is one of these:
+ # https://gist.github.com/schneems/6a7d7f988d3329fb3bd4b5be3e2efc0c
+ source = <<~EOM
+ foo do
+ puts "lol"
+ end
+ EOM
+
+ doc = CleanDocument.new(source: source).join_consecutive!
+
+ expect(doc.lines[0].to_s).to eq(source.lines[0])
+ expect(doc.lines[1].to_s).to eq(source.lines[1])
+ expect(doc.lines[2].to_s).to eq(source.lines[2])
+ end
+
+ it "trailing slash: formats output" do
+ source = <<~'EOM'
+ context "timezones workaround" do
+ it "should receive a time in UTC format and return the time with the"\
+ "office's UTC offset substracted from it" do
+ travel_to DateTime.new(2020, 10, 1, 10, 0, 0) do
+ office = build(:office)
+ end
+ end
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ expect(
+ DisplayCodeWithLineNumbers.new(
+ lines: code_lines.select(&:visible?)
+ ).call
+ ).to eq(<<~'EOM'.indent(2))
+ 1 context "timezones workaround" do
+ 2 it "should receive a time in UTC format and return the time with the"\
+ 3 "office's UTC offset substracted from it" do
+ 4 travel_to DateTime.new(2020, 10, 1, 10, 0, 0) do
+ 5 office = build(:office)
+ 6 end
+ 7 end
+ 8 end
+ EOM
+
+ expect(
+ DisplayCodeWithLineNumbers.new(
+ lines: code_lines.select(&:visible?),
+ highlight_lines: code_lines[1]
+ ).call
+ ).to eq(<<~'EOM')
+ 1 context "timezones workaround" do
+ > 2 it "should receive a time in UTC format and return the time with the"\
+ > 3 "office's UTC offset substracted from it" do
+ 4 travel_to DateTime.new(2020, 10, 1, 10, 0, 0) do
+ 5 office = build(:office)
+ 6 end
+ 7 end
+ 8 end
+ EOM
+ end
+
+ it "trailing slash: basic detection" do
+ source = <<~'EOM'
+ it "trailing s" \
+ "lash" do
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+
+ expect(code_lines[0]).to_not be_hidden
+ expect(code_lines[1]).to be_hidden
+
+ expect(
+ code_lines.join
+ ).to eq(code_lines.map(&:original).join)
+ end
+
+ it "trailing slash: joins multiple lines" do
+ source = <<~'EOM'
+ it "should " \
+ "keep " \
+ "going " do
+ end
+ EOM
+
+ doc = CleanDocument.new(source: source).join_trailing_slash!
+ expect(doc.lines[0].to_s).to eq(source.lines[0..2].join)
+ expect(doc.lines[1].to_s).to eq("")
+ expect(doc.lines[2].to_s).to eq("")
+ expect(doc.lines[3].to_s).to eq(source.lines[3])
+
+ lines = doc.lines
+ expect(
+ DisplayCodeWithLineNumbers.new(
+ lines: lines
+ ).call
+ ).to eq(<<~'EOM'.indent(2))
+ 1 it "should " \
+ 2 "keep " \
+ 3 "going " do
+ 4 end
+ EOM
+
+ expect(
+ DisplayCodeWithLineNumbers.new(
+ lines: lines,
+ highlight_lines: lines[0]
+ ).call
+ ).to eq(<<~'EOM')
+ > 1 it "should " \
+ > 2 "keep " \
+ > 3 "going " do
+ 4 end
+ EOM
+ end
+
+ it "trailing slash: no false positives" do
+ source = <<~'EOM'
+ def formatters
+ @formatters ||= {
+ amazing_print: ->(obj) { obj.ai + "\n" },
+ inspect: ->(obj) { obj.inspect + "\n" },
+ json: ->(obj) { obj.to_json },
+ marshal: ->(obj) { Marshal.dump(obj) },
+ none: ->(_obj) { nil },
+ pretty_json: ->(obj) { JSON.pretty_generate(obj) },
+ pretty_print: ->(obj) { obj.pretty_inspect },
+ puts: ->(obj) { require 'stringio'; sio = StringIO.new; sio.puts(obj); sio.string },
+ to_s: ->(obj) { obj.to_s + "\n" },
+ yaml: ->(obj) { obj.to_yaml },
+ }
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ expect(code_lines.join).to eq(code_lines.join)
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/cli_spec.rb b/spec/syntax_suggest/unit/cli_spec.rb
new file mode 100644
index 0000000000..23412f0193
--- /dev/null
+++ b/spec/syntax_suggest/unit/cli_spec.rb
@@ -0,0 +1,224 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ class FakeExit
+ def initialize
+ @called = false
+ @value = nil
+ end
+
+ def exit(value = nil)
+ @called = true
+ @value = value
+ end
+
+ def called?
+ @called
+ end
+
+ attr_reader :value
+ end
+
+ RSpec.describe Cli do
+ it "parses valid code" do
+ Dir.mktmpdir do |dir|
+ dir = Pathname(dir)
+ file = dir.join("script.rb")
+ file.write("puts 'lol'")
+
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ Cli.new(
+ io: io,
+ argv: [file.to_s],
+ exit_obj: exit_obj
+ ).call
+
+ expect(exit_obj.called?).to be_truthy
+ expect(exit_obj.value).to eq(0)
+ expect(io.string.strip).to eq("Syntax OK")
+ end
+ end
+
+ it "parses invalid code" do
+ file = fixtures_dir.join("this_project_extra_def.rb.txt")
+
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ Cli.new(
+ io: io,
+ argv: [file.to_s],
+ exit_obj: exit_obj
+ ).call
+
+ out = io.string
+ debug_display(out)
+
+ expect(exit_obj.called?).to be_truthy
+ expect(exit_obj.value).to eq(1)
+ expect(out.strip).to include("> 36 def filename")
+ end
+
+ it "parses valid code with flags" do
+ Dir.mktmpdir do |dir|
+ dir = Pathname(dir)
+ file = dir.join("script.rb")
+ file.write("puts 'lol'")
+
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: ["--terminal", file.to_s],
+ exit_obj: exit_obj
+ )
+ cli.call
+
+ expect(exit_obj.called?).to be_truthy
+ expect(exit_obj.value).to eq(0)
+ expect(cli.options[:terminal]).to be_truthy
+ expect(io.string.strip).to eq("Syntax OK")
+ end
+ end
+
+ it "errors when no file given" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: ["--terminal"],
+ exit_obj: exit_obj
+ )
+ cli.call
+
+ expect(exit_obj.called?).to be_truthy
+ expect(exit_obj.value).to eq(1)
+ expect(io.string.strip).to eq("No file given")
+ end
+
+ it "errors when file does not exist" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: ["lol-i-d-o-not-ex-ist-yololo.txtblerglol"],
+ exit_obj: exit_obj
+ )
+ cli.call
+
+ expect(exit_obj.called?).to be_truthy
+ expect(exit_obj.value).to eq(1)
+ expect(io.string.strip).to include("file not found:")
+ end
+
+ # We cannot execute the parser here
+ # because it calls `exit` and it will exit
+ # our tests, however we can assert that the
+ # parser has the right value for version
+ it "-v version" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ parser = Cli.new(
+ io: io,
+ argv: ["-v"],
+ exit_obj: exit_obj
+ ).parser
+
+ expect(parser.version).to include(SyntaxSuggest::VERSION.to_s)
+ end
+
+ it "SYNTAX_SUGGEST_RECORD_DIR" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: [],
+ env: {"SYNTAX_SUGGEST_RECORD_DIR" => "hahaha"},
+ exit_obj: exit_obj
+ ).parse
+
+ expect(exit_obj.called?).to be_falsey
+ expect(cli.options[:record_dir]).to eq("hahaha")
+ end
+
+ it "--record-dir=<dir>" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: ["--record=lol"],
+ exit_obj: exit_obj
+ ).parse
+
+ expect(exit_obj.called?).to be_falsey
+ expect(cli.options[:record_dir]).to eq("lol")
+ end
+
+ it "terminal default to respecting TTY" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: [],
+ exit_obj: exit_obj
+ ).parse
+
+ expect(exit_obj.called?).to be_falsey
+ expect(cli.options[:terminal]).to eq(SyntaxSuggest::DEFAULT_VALUE)
+ end
+
+ it "--terminal" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: ["--terminal"],
+ exit_obj: exit_obj
+ ).parse
+
+ expect(exit_obj.called?).to be_falsey
+ expect(cli.options[:terminal]).to be_truthy
+ end
+
+ it "--no-terminal" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ cli = Cli.new(
+ io: io,
+ argv: ["--no-terminal"],
+ exit_obj: exit_obj
+ ).parse
+
+ expect(exit_obj.called?).to be_falsey
+ expect(cli.options[:terminal]).to be_falsey
+ end
+
+ it "--help outputs help" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ Cli.new(
+ io: io,
+ argv: ["--help"],
+ exit_obj: exit_obj
+ ).call
+
+ expect(exit_obj.called?).to be_truthy
+ expect(io.string).to include("Usage: syntax_suggest <file> [options]")
+ end
+
+ it "<empty args> outputs help" do
+ io = StringIO.new
+ exit_obj = FakeExit.new
+ Cli.new(
+ io: io,
+ argv: [],
+ exit_obj: exit_obj
+ ).call
+
+ expect(exit_obj.called?).to be_truthy
+ expect(io.string).to include("Usage: syntax_suggest <file> [options]")
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/code_block_spec.rb b/spec/syntax_suggest/unit/code_block_spec.rb
new file mode 100644
index 0000000000..3ab2751b27
--- /dev/null
+++ b/spec/syntax_suggest/unit/code_block_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe CodeBlock do
+ it "can detect if it's valid or not" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts 'lol'
+ end
+ EOM
+
+ block = CodeBlock.new(lines: code_lines[1])
+ expect(block.valid?).to be_truthy
+ end
+
+ it "can be sorted in indentation order" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts 'lol'
+ end
+ EOM
+
+ block_0 = CodeBlock.new(lines: code_lines[0])
+ block_1 = CodeBlock.new(lines: code_lines[1])
+ block_2 = CodeBlock.new(lines: code_lines[2])
+
+ expect(block_0 <=> block_0.dup).to eq(0)
+ expect(block_1 <=> block_0).to eq(1)
+ expect(block_1 <=> block_2).to eq(-1)
+
+ array = [block_2, block_1, block_0].sort
+ expect(array.last).to eq(block_2)
+
+ block = CodeBlock.new(lines: CodeLine.new(line: " " * 8 + "foo", index: 4, lex: []))
+ array.prepend(block)
+ expect(array.max).to eq(block)
+ end
+
+ it "knows it's current indentation level" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts 'lol'
+ end
+ EOM
+
+ block = CodeBlock.new(lines: code_lines[1])
+ expect(block.current_indent).to eq(2)
+
+ block = CodeBlock.new(lines: code_lines[0])
+ expect(block.current_indent).to eq(0)
+ end
+
+ it "knows it's current indentation level when mismatched indents" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts 'lol'
+ end
+ EOM
+
+ block = CodeBlock.new(lines: [code_lines[1], code_lines[2]])
+ expect(block.current_indent).to eq(1)
+ end
+
+ it "before lines and after lines" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ bar; end
+ end
+ EOM
+
+ block = CodeBlock.new(lines: code_lines[1])
+ expect(block.valid?).to be_falsey
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/code_frontier_spec.rb b/spec/syntax_suggest/unit/code_frontier_spec.rb
new file mode 100644
index 0000000000..c9aba7c8d8
--- /dev/null
+++ b/spec/syntax_suggest/unit/code_frontier_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe CodeFrontier do
+ it "detect_bad_blocks" do
+ code_lines = code_line_array(<<~EOM)
+ describe "lol" do
+ end
+ end
+
+ it "lol" do
+ end
+ end
+ EOM
+
+ frontier = CodeFrontier.new(code_lines: code_lines)
+ blocks = []
+ blocks << CodeBlock.new(lines: code_lines[1])
+ blocks << CodeBlock.new(lines: code_lines[5])
+ blocks.each do |b|
+ frontier << b
+ end
+
+ expect(frontier.detect_invalid_blocks.sort).to eq(blocks.sort)
+ end
+
+ it "self.combination" do
+ expect(
+ CodeFrontier.combination([:a, :b, :c, :d])
+ ).to eq(
+ [
+ [:a], [:b], [:c], [:d],
+ [:a, :b],
+ [:a, :c],
+ [:a, :d],
+ [:b, :c],
+ [:b, :d],
+ [:c, :d],
+ [:a, :b, :c],
+ [:a, :b, :d],
+ [:a, :c, :d],
+ [:b, :c, :d],
+ [:a, :b, :c, :d]
+ ]
+ )
+ end
+
+ it "doesn't duplicate blocks" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts "lol"
+ puts "lol"
+ puts "lol"
+ end
+ EOM
+
+ frontier = CodeFrontier.new(code_lines: code_lines)
+ frontier << CodeBlock.new(lines: [code_lines[2]])
+ expect(frontier.count).to eq(1)
+
+ frontier << CodeBlock.new(lines: [code_lines[1], code_lines[2], code_lines[3]])
+ # expect(frontier.count).to eq(1)
+ expect(frontier.pop.to_s).to eq(<<~EOM.indent(2))
+ puts "lol"
+ puts "lol"
+ puts "lol"
+ EOM
+
+ expect(frontier.pop).to be_nil
+
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts "lol"
+ puts "lol"
+ puts "lol"
+ end
+ EOM
+
+ frontier = CodeFrontier.new(code_lines: code_lines)
+ frontier << CodeBlock.new(lines: [code_lines[2]])
+ expect(frontier.count).to eq(1)
+
+ frontier << CodeBlock.new(lines: [code_lines[3]])
+ expect(frontier.count).to eq(2)
+ expect(frontier.pop.to_s).to eq(<<~EOM.indent(2))
+ puts "lol"
+ EOM
+ end
+
+ it "detects if multiple syntax errors are found" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ end
+ end
+ EOM
+
+ frontier = CodeFrontier.new(code_lines: code_lines)
+
+ frontier << CodeBlock.new(lines: code_lines[1])
+ block = frontier.pop
+ expect(block.to_s).to eq(<<~EOM.indent(2))
+ end
+ EOM
+ frontier << block
+
+ expect(frontier.holds_all_syntax_errors?).to be_truthy
+ end
+
+ it "detects if it has not captured all syntax errors" do
+ code_lines = code_line_array(<<~EOM)
+ def foo
+ puts "lol"
+ end
+
+ describe "lol"
+ end
+
+ it "lol"
+ end
+ EOM
+
+ frontier = CodeFrontier.new(code_lines: code_lines)
+ frontier << CodeBlock.new(lines: [code_lines[1]])
+ block = frontier.pop
+ expect(block.to_s).to eq(<<~EOM.indent(2))
+ puts "lol"
+ EOM
+ frontier << block
+
+ expect(frontier.holds_all_syntax_errors?).to be_falsey
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/code_line_spec.rb b/spec/syntax_suggest/unit/code_line_spec.rb
new file mode 100644
index 0000000000..d5b568fd19
--- /dev/null
+++ b/spec/syntax_suggest/unit/code_line_spec.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe CodeLine do
+ it "bug in keyword detection" do
+ lines = CodeLine.from_source(<<~'EOM')
+ def to_json(*opts)
+ {
+ type: :module,
+ }.to_json(*opts)
+ end
+ EOM
+ expect(lines.count(&:is_kw?)).to eq(1)
+ expect(lines.count(&:is_end?)).to eq(1)
+ end
+
+ it "supports endless method definitions" do
+ skip("Unsupported ruby version") unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3")
+
+ line = CodeLine.from_source(<<~'EOM').first
+ def square(x) = x * x
+ EOM
+
+ expect(line.is_kw?).to be_falsey
+ expect(line.is_end?).to be_falsey
+ end
+
+ it "retains original line value, after being marked invisible" do
+ line = CodeLine.from_source(<<~'EOM').first
+ puts "lol"
+ EOM
+ expect(line.line).to match('puts "lol"')
+ line.mark_invisible
+ expect(line.line).to eq("")
+ expect(line.original).to match('puts "lol"')
+ end
+
+ it "knows which lines can be joined" do
+ code_lines = CodeLine.from_source(<<~'EOM')
+ user = User.
+ where(name: 'schneems').
+ first
+ puts user.name
+ EOM
+
+ # Indicates line 1 can join 2, 2 can join 3, but 3 won't join it's next line
+ expect(code_lines.map(&:ignore_newline_not_beg?)).to eq([true, true, false, false])
+ end
+
+ it "trailing if" do
+ code_lines = CodeLine.from_source(<<~'EOM')
+ puts "lol" if foo
+ if foo
+ end
+ EOM
+
+ expect(code_lines.map(&:is_kw?)).to eq([false, true, false])
+ end
+
+ it "trailing unless" do
+ code_lines = CodeLine.from_source(<<~'EOM')
+ puts "lol" unless foo
+ unless foo
+ end
+ EOM
+
+ expect(code_lines.map(&:is_kw?)).to eq([false, true, false])
+ end
+
+ it "trailing slash" do
+ code_lines = CodeLine.from_source(<<~'EOM')
+ it "trailing s" \
+ "lash" do
+ EOM
+
+ expect(code_lines.map(&:trailing_slash?)).to eq([true, false])
+
+ code_lines = CodeLine.from_source(<<~'EOM')
+ amazing_print: ->(obj) { obj.ai + "\n" },
+ EOM
+ expect(code_lines.map(&:trailing_slash?)).to eq([false])
+ end
+
+ it "knows it's got an end" do
+ line = CodeLine.from_source(" end").first
+
+ expect(line.is_end?).to be_truthy
+ expect(line.is_kw?).to be_falsey
+ end
+
+ it "knows it's got a keyword" do
+ line = CodeLine.from_source(" if").first
+
+ expect(line.is_end?).to be_falsey
+ expect(line.is_kw?).to be_truthy
+ end
+
+ it "ignores marked lines" do
+ code_lines = CodeLine.from_source(<<~EOM)
+ def foo
+ Array(value) |x|
+ end
+ end
+ EOM
+
+ expect(SyntaxSuggest.valid?(code_lines)).to be_falsey
+ expect(code_lines.join).to eq(<<~EOM)
+ def foo
+ Array(value) |x|
+ end
+ end
+ EOM
+
+ expect(code_lines[0].visible?).to be_truthy
+ expect(code_lines[3].visible?).to be_truthy
+
+ code_lines[0].mark_invisible
+ code_lines[3].mark_invisible
+
+ expect(code_lines[0].visible?).to be_falsey
+ expect(code_lines[3].visible?).to be_falsey
+
+ expect(code_lines.join).to eq(<<~EOM.indent(2))
+ Array(value) |x|
+ end
+ EOM
+ expect(SyntaxSuggest.valid?(code_lines)).to be_falsey
+ end
+
+ it "knows empty lines" do
+ code_lines = CodeLine.from_source(<<~EOM)
+ # Not empty
+
+ # Not empty
+ EOM
+
+ expect(code_lines.map(&:empty?)).to eq([false, true, false])
+ expect(code_lines.map(&:not_empty?)).to eq([true, false, true])
+ expect(code_lines.map { |l| SyntaxSuggest.valid?(l) }).to eq([true, true, true])
+ end
+
+ it "counts indentations" do
+ code_lines = CodeLine.from_source(<<~EOM)
+ def foo
+ Array(value) |x|
+ puts 'lol'
+ end
+ end
+ EOM
+
+ expect(code_lines.map(&:indent)).to eq([0, 2, 4, 2, 0])
+ end
+
+ it "doesn't count empty lines as having an indentation" do
+ code_lines = CodeLine.from_source(<<~EOM)
+
+
+ EOM
+
+ expect(code_lines.map(&:indent)).to eq([0, 0])
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/code_search_spec.rb b/spec/syntax_suggest/unit/code_search_spec.rb
new file mode 100644
index 0000000000..f836ba36f3
--- /dev/null
+++ b/spec/syntax_suggest/unit/code_search_spec.rb
@@ -0,0 +1,505 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe CodeSearch do
+ it "rexe regression" do
+ lines = fixtures_dir.join("rexe.rb.txt").read.lines
+ lines.delete_at(148 - 1)
+ source = lines.join
+
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join.strip).to eq(<<~'EOM'.strip)
+ class Lookups
+ EOM
+ end
+
+ it "squished do regression" do
+ source = <<~'EOM'
+ def call
+ trydo
+
+ @options = CommandLineParser.new.parse
+
+ options.requires.each { |r| require!(r) }
+ load_global_config_if_exists
+ options.loads.each { |file| load(file) }
+
+ @user_source_code = ARGV.join(' ')
+ @user_source_code = 'self' if @user_source_code == ''
+
+ @callable = create_callable
+
+ init_rexe_context
+ init_parser_and_formatters
+
+ # This is where the user's source code will be executed; the action will in turn call `execute`.
+ lookup_action(options.input_mode).call unless options.noop
+
+ output_log_entry
+ end # one
+ end # two
+ EOM
+
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ trydo
+ end # one
+ EOM
+ end
+
+ it "regression test ambiguous end" do
+ source = <<~'EOM'
+ def call # 0
+ print "lol" # 1
+ end # one # 2
+ end # two # 3
+ EOM
+
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ end # two # 3
+ EOM
+ end
+
+ it "regression dog test" do
+ source = <<~'EOM'
+ class Dog
+ def bark
+ puts "woof"
+ end
+ EOM
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ class Dog
+ EOM
+ expect(search.invalid_blocks.first.lines.length).to eq(4)
+ end
+
+ it "handles mismatched |" do
+ source = <<~EOM
+ class Blerg
+ Foo.call do |a
+ end # one
+
+ puts lol
+ class Foo
+ end # two
+ end # three
+ EOM
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ Foo.call do |a
+ end # one
+ EOM
+ end
+
+ it "handles mismatched }" do
+ source = <<~EOM
+ class Blerg
+ Foo.call do {
+
+ puts lol
+ class Foo
+ end # two
+ end # three
+ EOM
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ Foo.call do {
+ EOM
+ end
+
+ it "handles no spaces between blocks and trailing slash" do
+ source = <<~'EOM'
+ require "rails_helper"
+ RSpec.describe Foo, type: :model do
+ describe "#bar" do
+ context "context" do
+ it "foos the bar with a foo and then bazes the foo with a bar to"\
+ "fooify the barred bar" do
+ travel_to DateTime.new(2020, 10, 1, 10, 0, 0) do
+ foo = build(:foo)
+ end
+ end
+ end
+ end
+ describe "#baz?" do
+ context "baz has barred the foo" do
+ it "returns true" do # <== HERE
+ end
+ end
+ end
+ EOM
+
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join.strip).to eq('it "returns true" do # <== HERE')
+ end
+
+ it "handles no spaces between blocks" do
+ source = <<~'EOM'
+ context "foo bar" do
+ it "bars the foo" do
+ travel_to DateTime.new(2020, 10, 1, 10, 0, 0) do
+ end
+ end
+ end
+ context "test" do
+ it "should" do
+ end
+ EOM
+ search = CodeSearch.new(source)
+ search.call
+
+ expect(search.invalid_blocks.join.strip).to eq('it "should" do')
+ end
+
+ it "records debugging steps to a directory" do
+ Dir.mktmpdir do |dir|
+ dir = Pathname(dir)
+ search = CodeSearch.new(<<~'EOM', record_dir: dir)
+ class OH
+ def hello
+ def hai
+ end
+ end
+ EOM
+ search.call
+
+ expect(search.record_dir.entries.map(&:to_s)).to include("1-add-1-(3__4).txt")
+ expect(search.record_dir.join("1-add-1-(3__4).txt").read).to include(<<~EOM)
+ 1 class OH
+ 2 def hello
+ > 3 def hai
+ > 4 end
+ 5 end
+ EOM
+ end
+ end
+
+ it "def with missing end" do
+ search = CodeSearch.new(<<~'EOM')
+ class OH
+ def hello
+
+ def hai
+ puts "lol"
+ end
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join.strip).to eq("def hello")
+
+ search = CodeSearch.new(<<~'EOM')
+ class OH
+ def hello
+
+ def hai
+ end
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join.strip).to eq("def hello")
+
+ search = CodeSearch.new(<<~'EOM')
+ class OH
+ def hello
+ def hai
+ end
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ def hello
+ EOM
+ end
+
+ describe "real world cases" do
+ it "finds hanging def in this project" do
+ source_string = fixtures_dir.join("this_project_extra_def.rb.txt").read
+ search = CodeSearch.new(source_string)
+ search.call
+
+ document = DisplayCodeWithLineNumbers.new(
+ lines: search.code_lines.select(&:visible?),
+ terminal: false,
+ highlight_lines: search.invalid_blocks.flat_map(&:lines)
+ ).call
+
+ expect(document).to include(<<~'EOM')
+ > 36 def filename
+ EOM
+ end
+
+ it "Format Code blocks real world example" do
+ search = CodeSearch.new(<<~'EOM')
+ require 'rails_helper'
+
+ RSpec.describe AclassNameHere, type: :worker do
+ describe "thing" do
+ context "when" do
+ let(:thing) { stuff }
+ let(:another_thing) { moarstuff }
+ subject { foo.new.perform(foo.id, true) }
+
+ it "stuff" do
+ subject
+
+ expect(foo.foo.foo).to eq(true)
+ end
+ end
+ end # line 16 accidental end, but valid block
+
+ context "stuff" do
+ let(:thing) { create(:foo, foo: stuff) }
+ let(:another_thing) { create(:stuff) }
+
+ subject { described_class.new.perform(foo.id, false) }
+
+ it "more stuff" do
+ subject
+
+ expect(foo.foo.foo).to eq(false)
+ end
+ end
+ end # mismatched due to 16
+ end
+ EOM
+ search.call
+
+ document = DisplayCodeWithLineNumbers.new(
+ lines: search.code_lines.select(&:visible?),
+ terminal: false,
+ highlight_lines: search.invalid_blocks.flat_map(&:lines)
+ ).call
+
+ expect(document).to include(<<~'EOM')
+ 1 require 'rails_helper'
+ 2
+ 3 RSpec.describe AclassNameHere, type: :worker do
+ > 4 describe "thing" do
+ > 16 end # line 16 accidental end, but valid block
+ > 30 end # mismatched due to 16
+ 31 end
+ EOM
+ end
+ end
+
+ # For code that's not perfectly formatted, we ideally want to do our best
+ # These examples represent the results that exist today, but I would like to improve upon them
+ describe "needs improvement" do
+ describe "mis-matched-indentation" do
+ it "extra space before end" do
+ search = CodeSearch.new(<<~'EOM')
+ Foo.call
+ def foo
+ puts "lol"
+ puts "lol"
+ end # one
+ end # two
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ Foo.call
+ end # two
+ EOM
+ end
+
+ it "stacked ends 2" do
+ search = CodeSearch.new(<<~'EOM')
+ def cat
+ blerg
+ end
+
+ Foo.call do
+ end # one
+ end # two
+
+ def dog
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ Foo.call do
+ end # one
+ end # two
+
+ EOM
+ end
+
+ it "stacked ends " do
+ search = CodeSearch.new(<<~'EOM')
+ Foo.call
+ def foo
+ puts "lol"
+ puts "lol"
+ end
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ Foo.call
+ end
+ EOM
+ end
+
+ it "missing space before end" do
+ search = CodeSearch.new(<<~'EOM')
+ Foo.call
+
+ def foo
+ puts "lol"
+ puts "lol"
+ end
+ end
+ EOM
+ search.call
+
+ # expand-1 and expand-2 seem to be broken?
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ Foo.call
+ end
+ EOM
+ end
+ end
+ end
+
+ it "returns syntax error in outer block without inner block" do
+ search = CodeSearch.new(<<~'EOM')
+ Foo.call
+ def foo
+ puts "lol"
+ puts "lol"
+ end # one
+ end # two
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ Foo.call
+ end # two
+ EOM
+ end
+
+ it "doesn't just return an empty `end`" do
+ search = CodeSearch.new(<<~'EOM')
+ Foo.call
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ Foo.call
+ end
+ EOM
+ end
+
+ it "finds multiple syntax errors" do
+ search = CodeSearch.new(<<~'EOM')
+ describe "hi" do
+ Foo.call
+ end
+ end
+
+ it "blerg" do
+ Bar.call
+ end
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ Foo.call
+ end
+ Bar.call
+ end
+ EOM
+ end
+
+ it "finds a typo def" do
+ search = CodeSearch.new(<<~'EOM')
+ defzfoo
+ puts "lol"
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM')
+ defzfoo
+ end
+ EOM
+ end
+
+ it "finds a mis-matched def" do
+ search = CodeSearch.new(<<~'EOM')
+ def foo
+ def blerg
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ def blerg
+ EOM
+ end
+
+ it "finds a naked end" do
+ search = CodeSearch.new(<<~'EOM')
+ def foo
+ end # one
+ end # two
+ EOM
+ search.call
+
+ expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2))
+ end # one
+ EOM
+ end
+
+ it "returns when no invalid blocks are found" do
+ search = CodeSearch.new(<<~'EOM')
+ def foo
+ puts 'lol'
+ end
+ EOM
+ search.call
+
+ expect(search.invalid_blocks).to eq([])
+ end
+
+ it "expands frontier by eliminating valid lines" do
+ search = CodeSearch.new(<<~'EOM')
+ def foo
+ puts 'lol'
+ end
+ EOM
+ search.create_blocks_from_untracked_lines
+
+ expect(search.code_lines.join).to eq(<<~'EOM')
+ def foo
+ end
+ EOM
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/core_ext_spec.rb b/spec/syntax_suggest/unit/core_ext_spec.rb
new file mode 100644
index 0000000000..802d03ecc0
--- /dev/null
+++ b/spec/syntax_suggest/unit/core_ext_spec.rb
@@ -0,0 +1,34 @@
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "Core extension" do
+ it "SyntaxError monkepatch ensures there is a newline to the end of the file" do
+ skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")
+
+ Dir.mktmpdir do |dir|
+ tmpdir = Pathname(dir)
+ file = tmpdir.join("file.rb")
+ file.write(<<~'EOM'.strip)
+ print 'no newline
+ EOM
+
+ core_ext_file = lib_dir.join("syntax_suggest").join("core_ext")
+ require_relative core_ext_file
+
+ original_message = "blerg"
+ error = SyntaxError.new(original_message)
+ def error.set_tmp_path_for_testing=(path)
+ @tmp_path_for_testing = path
+ end
+ error.set_tmp_path_for_testing = file
+ def error.path
+ @tmp_path_for_testing
+ end
+
+ detailed = error.detailed_message(highlight: false, syntax_suggest: true)
+ expect(detailed).to include("'no newline\n#{original_message}")
+ expect(detailed).to_not include("print 'no newline#{original_message}")
+ end
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/display_invalid_blocks_spec.rb b/spec/syntax_suggest/unit/display_invalid_blocks_spec.rb
new file mode 100644
index 0000000000..b11d7d242e
--- /dev/null
+++ b/spec/syntax_suggest/unit/display_invalid_blocks_spec.rb
@@ -0,0 +1,174 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe DisplayInvalidBlocks do
+ it "works with valid code" do
+ syntax_string = <<~EOM
+ class OH
+ def hello
+ end
+ def hai
+ end
+ end
+ EOM
+
+ search = CodeSearch.new(syntax_string)
+ search.call
+
+ io = StringIO.new
+ display = DisplayInvalidBlocks.new(
+ io: io,
+ blocks: search.invalid_blocks,
+ terminal: false,
+ code_lines: search.code_lines
+ )
+ display.call
+ expect(io.string).to include("")
+ end
+
+ it "selectively prints to terminal if input is a tty by default" do
+ source = <<~EOM
+ class OH
+ def hello
+ def hai
+ end
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+
+ io = StringIO.new
+ def io.isatty
+ true
+ end
+
+ block = CodeBlock.new(lines: code_lines[1])
+ display = DisplayInvalidBlocks.new(
+ io: io,
+ blocks: block,
+ code_lines: code_lines
+ )
+ display.call
+ expect(io.string).to include([
+ "> 2 ",
+ DisplayCodeWithLineNumbers::TERMINAL_HIGHLIGHT,
+ " def hello"
+ ].join)
+
+ io = StringIO.new
+ def io.isatty
+ false
+ end
+
+ block = CodeBlock.new(lines: code_lines[1])
+ display = DisplayInvalidBlocks.new(
+ io: io,
+ blocks: block,
+ code_lines: code_lines
+ )
+ display.call
+ expect(io.string).to include("> 2 def hello")
+ end
+
+ it "outputs to io when using `call`" do
+ source = <<~EOM
+ class OH
+ def hello
+ def hai
+ end
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+
+ io = StringIO.new
+ block = CodeBlock.new(lines: code_lines[1])
+ display = DisplayInvalidBlocks.new(
+ io: io,
+ blocks: block,
+ terminal: false,
+ code_lines: code_lines
+ )
+ display.call
+ expect(io.string).to include("> 2 def hello")
+ end
+
+ it " wraps code with github style codeblocks" do
+ source = <<~EOM
+ class OH
+ def hello
+
+ def hai
+ end
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[1])
+ io = StringIO.new
+ DisplayInvalidBlocks.new(
+ io: io,
+ blocks: block,
+ terminal: false,
+ code_lines: code_lines
+ ).call
+ expect(io.string).to include(<<~EOM)
+ 1 class OH
+ > 2 def hello
+ 4 def hai
+ 5 end
+ 6 end
+ EOM
+ end
+
+ it "shows terminal characters" do
+ code_lines = code_line_array(<<~EOM)
+ class OH
+ def hello
+ def hai
+ end
+ end
+ EOM
+
+ io = StringIO.new
+ block = CodeBlock.new(lines: code_lines[1])
+ DisplayInvalidBlocks.new(
+ io: io,
+ blocks: block,
+ terminal: false,
+ code_lines: code_lines
+ ).call
+
+ expect(io.string).to include([
+ " 1 class OH",
+ "> 2 def hello",
+ " 3 def hai",
+ " 4 end",
+ " 5 end",
+ ""
+ ].join($/))
+
+ block = CodeBlock.new(lines: code_lines[1])
+ io = StringIO.new
+ DisplayInvalidBlocks.new(
+ io: io,
+ blocks: block,
+ terminal: true,
+ code_lines: code_lines
+ ).call
+
+ expect(io.string).to include(
+ [
+ " 1 class OH",
+ ["> 2 ", DisplayCodeWithLineNumbers::TERMINAL_HIGHLIGHT, " def hello"].join,
+ " 3 def hai",
+ " 4 end",
+ " 5 end",
+ ""
+ ].join($/ + DisplayCodeWithLineNumbers::TERMINAL_END)
+ )
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/explain_syntax_spec.rb b/spec/syntax_suggest/unit/explain_syntax_spec.rb
new file mode 100644
index 0000000000..394981dcf6
--- /dev/null
+++ b/spec/syntax_suggest/unit/explain_syntax_spec.rb
@@ -0,0 +1,255 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "ExplainSyntax" do
+ it "handles shorthand syntaxes with non-bracket characters" do
+ source = <<~EOM
+ %Q* lol
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq([])
+ expect(explain.errors.join).to include("unterminated string")
+ end
+
+ it "handles %w[]" do
+ source = <<~EOM
+ node.is_a?(Op) && %w[| ||].include?(node.value) &&
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq([])
+ end
+
+ it "doesn't falsely identify strings or symbols as critical chars" do
+ source = <<~EOM
+ a = ['(', '{', '[', '|']
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq([])
+
+ source = <<~EOM
+ a = [:'(', :'{', :'[', :'|']
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq([])
+ end
+
+ it "finds missing |" do
+ source = <<~EOM
+ Foo.call do |
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["|"])
+ expect(explain.errors).to eq([explain.why("|")])
+ end
+
+ it "finds missing {" do
+ source = <<~EOM
+ class Cat
+ lol = {
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["}"])
+ expect(explain.errors).to eq([explain.why("}")])
+ end
+
+ it "finds missing }" do
+ source = <<~EOM
+ def foo
+ lol = "foo" => :bar }
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["{"])
+ expect(explain.errors).to eq([explain.why("{")])
+ end
+
+ it "finds missing [" do
+ source = <<~EOM
+ class Cat
+ lol = [
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["]"])
+ expect(explain.errors).to eq([explain.why("]")])
+ end
+
+ it "finds missing ]" do
+ source = <<~EOM
+ def foo
+ lol = ]
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["["])
+ expect(explain.errors).to eq([explain.why("[")])
+ end
+
+ it "finds missing (" do
+ source = "def initialize; ); end"
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["("])
+ expect(explain.errors).to eq([explain.why("(")])
+ end
+
+ it "finds missing )" do
+ source = "def initialize; (; end"
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq([")"])
+ expect(explain.errors).to eq([explain.why(")")])
+ end
+
+ it "finds missing keyword" do
+ source = <<~EOM
+ class Cat
+ end
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["keyword"])
+ expect(explain.errors).to eq([explain.why("keyword")])
+ end
+
+ it "finds missing end" do
+ source = <<~EOM
+ class Cat
+ def meow
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["end"])
+ expect(explain.errors).to eq([explain.why("end")])
+ end
+
+ it "falls back to ripper on unknown errors" do
+ source = <<~EOM
+ class Cat
+ def meow
+ 1 *
+ end
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq([])
+ expect(explain.errors).to eq(RipperErrors.new(source).call.errors)
+ end
+
+ it "handles an unexpected rescue" do
+ source = <<~EOM
+ def foo
+ if bar
+ "baz"
+ else
+ "foo"
+ rescue FooBar
+ nil
+ end
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["end"])
+ end
+
+ # String embeds are `"#{foo} <-- here`
+ #
+ # We need to count a `#{` as a `{`
+ # otherwise it will report that we are
+ # missing a curly when we are using valid
+ # string embed syntax
+ it "is not confused by valid string embed" do
+ source = <<~'EOM'
+ foo = "#{hello}"
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+ expect(explain.missing).to eq([])
+ end
+
+ # Missing string embed beginnings are not a
+ # syntax error. i.e. `"foo}"` or `"{foo}` or "#foo}"
+ # would just be strings with extra characters.
+ #
+ # However missing the end curly will trigger
+ # an error: i.e. `"#{foo`
+ #
+ # String embed beginning is a `#{` rather than
+ # a `{`, make sure we handle that case and
+ # report the correct missing `}` diagnosis
+ it "finds missing string embed end" do
+ source = <<~'EOM'
+ "#{foo
+ EOM
+
+ explain = ExplainSyntax.new(
+ code_lines: CodeLine.from_source(source)
+ ).call
+
+ expect(explain.missing).to eq(["}"])
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/lex_all_spec.rb b/spec/syntax_suggest/unit/lex_all_spec.rb
new file mode 100644
index 0000000000..0c0df7cfaa
--- /dev/null
+++ b/spec/syntax_suggest/unit/lex_all_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "EndBlockParse" do
+ it "finds blocks based on `end` keyword" do
+ source = <<~EOM
+ describe "cat" # 1
+ Cat.call do # 2
+ end # 3
+ end # 4
+ # 5
+ it "dog" do # 6
+ Dog.call do # 7
+ end # 8
+ end # 9
+ EOM
+
+ # raw_lex = Ripper.lex(source)
+ # expect(raw_lex.to_s).to_not include("dog")
+
+ lex = LexAll.new(source: source)
+ expect(lex.map(&:token).to_s).to include("dog")
+ expect(lex.first.line).to eq(1)
+ expect(lex.last.line).to eq(9)
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/pathname_from_message_spec.rb b/spec/syntax_suggest/unit/pathname_from_message_spec.rb
new file mode 100644
index 0000000000..76756efda9
--- /dev/null
+++ b/spec/syntax_suggest/unit/pathname_from_message_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "PathnameFromMessage" do
+ it "handles filenames with colons in them" do
+ Dir.mktmpdir do |dir|
+ dir = Pathname(dir)
+
+ file = dir.join("scr:atch.rb").tap { |p| FileUtils.touch(p) }
+
+ message = "#{file}:2:in `require_relative': /private/tmp/bad.rb:1: syntax error, unexpected `end' (SyntaxError)"
+ file = PathnameFromMessage.new(message).call.name
+
+ expect(file).to be_truthy
+ end
+ end
+
+ it "checks if the file exists" do
+ Dir.mktmpdir do |dir|
+ dir = Pathname(dir)
+
+ file = dir.join("scratch.rb")
+ # No touch, file does not exist
+ expect(file.exist?).to be_falsey
+
+ message = "#{file}:2:in `require_relative': /private/tmp/bad.rb:1: syntax error, unexpected `end' (SyntaxError)"
+ io = StringIO.new
+ file = PathnameFromMessage.new(message, io: io).call.name
+
+ expect(io.string).to include(file.to_s)
+ expect(file).to be_falsey
+ end
+ end
+
+ it "does not output error message on syntax error inside of an (eval)" do
+ message = "(eval):1: invalid multibyte char (UTF-8) (SyntaxError)\n"
+ io = StringIO.new
+ file = PathnameFromMessage.new(message, io: io).call.name
+
+ expect(io.string).to eq("")
+ expect(file).to be_falsey
+ end
+
+ it "does not output error message on syntax error inside of streamed code" do
+ # An example of streamed code is: $ echo "def foo" | ruby
+ message = "-:1: syntax error, unexpected end-of-input\n"
+ io = StringIO.new
+ file = PathnameFromMessage.new(message, io: io).call.name
+
+ expect(io.string).to eq("")
+ expect(file).to be_falsey
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/priority_queue_spec.rb b/spec/syntax_suggest/unit/priority_queue_spec.rb
new file mode 100644
index 0000000000..17361833e5
--- /dev/null
+++ b/spec/syntax_suggest/unit/priority_queue_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ class CurrentIndex
+ attr_reader :current_indent
+
+ def initialize(value)
+ @current_indent = value
+ end
+
+ def <=>(other)
+ @current_indent <=> other.current_indent
+ end
+
+ def inspect
+ @current_indent
+ end
+ end
+
+ RSpec.describe CodeFrontier do
+ it "works" do
+ q = PriorityQueue.new
+ q << 1
+ q << 2
+ expect(q.elements).to eq([2, 1])
+
+ q << 3
+ expect(q.elements).to eq([3, 1, 2])
+
+ expect(q.pop).to eq(3)
+ expect(q.pop).to eq(2)
+ expect(q.pop).to eq(1)
+ expect(q.pop).to eq(nil)
+
+ array = []
+ q = PriorityQueue.new
+ array.reverse_each do |v|
+ q << v
+ end
+ expect(q.elements).to eq(array)
+
+ array = [100, 36, 17, 19, 25, 0, 3, 1, 7, 2]
+ array.reverse_each do |v|
+ q << v
+ end
+
+ expect(q.pop).to eq(100)
+ expect(q.elements).to eq([36, 25, 19, 17, 0, 1, 7, 2, 3])
+
+ # expected [36, 25, 19, 17, 0, 1, 7, 2, 3]
+ expect(q.pop).to eq(36)
+ expect(q.pop).to eq(25)
+ expect(q.pop).to eq(19)
+ expect(q.pop).to eq(17)
+ expect(q.pop).to eq(7)
+ expect(q.pop).to eq(3)
+ expect(q.pop).to eq(2)
+ expect(q.pop).to eq(1)
+ expect(q.pop).to eq(0)
+ expect(q.pop).to eq(nil)
+ end
+
+ it "priority queue" do
+ frontier = PriorityQueue.new
+ frontier << CurrentIndex.new(0)
+ frontier << CurrentIndex.new(1)
+
+ expect(frontier.sorted.map(&:current_indent)).to eq([0, 1])
+
+ frontier << CurrentIndex.new(1)
+ expect(frontier.sorted.map(&:current_indent)).to eq([0, 1, 1])
+
+ frontier << CurrentIndex.new(0)
+ expect(frontier.sorted.map(&:current_indent)).to eq([0, 0, 1, 1])
+
+ frontier << CurrentIndex.new(10)
+ expect(frontier.sorted.map(&:current_indent)).to eq([0, 0, 1, 1, 10])
+
+ frontier << CurrentIndex.new(2)
+ expect(frontier.sorted.map(&:current_indent)).to eq([0, 0, 1, 1, 2, 10])
+
+ frontier = PriorityQueue.new
+ values = [18, 18, 0, 18, 0, 18, 18, 18, 18, 16, 18, 8, 18, 8, 8, 8, 16, 6, 0, 0, 16, 16, 4, 14, 14, 12, 12, 12, 10, 12, 12, 12, 12, 8, 10, 10, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 10, 6, 6, 6, 6, 6, 6, 8, 10, 8, 8, 10, 8, 10, 8, 10, 8, 6, 8, 8, 6, 8, 6, 6, 8, 0, 8, 0, 0, 8, 8, 0, 8, 0, 8, 8, 0, 8, 8, 8, 0, 8, 0, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 6, 8, 6, 6, 6, 6, 8, 6, 8, 6, 6, 4, 4, 6, 6, 4, 6, 4, 6, 6, 4, 6, 4, 4, 6, 6, 6, 6, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 6, 6, 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, 6, 6, 6, 0, 0, 6, 6, 2]
+
+ values.each do |v|
+ value = CurrentIndex.new(v)
+ frontier << value # CurrentIndex.new(v)
+ end
+
+ expect(frontier.sorted.map(&:current_indent)).to eq(values.sort)
+ end
+ end
+end
diff --git a/spec/syntax_suggest/unit/scan_history_spec.rb b/spec/syntax_suggest/unit/scan_history_spec.rb
new file mode 100644
index 0000000000..0e75ac66ce
--- /dev/null
+++ b/spec/syntax_suggest/unit/scan_history_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe ScanHistory do
+ it "retains commits" do
+ source = <<~'EOM'
+ class OH # 0
+ def lol # 1
+ print 'lol # 2
+ end # 3
+
+ def hello # 5
+ it "foo" do # 6
+ end # 7
+
+ def yolo # 8
+ print 'haha' # 9
+ end # 10
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[6])
+
+ scanner = ScanHistory.new(code_lines: code_lines, block: block)
+ scanner.scan(up: ->(_, _, _) { true }, down: ->(_, _, _) { true })
+
+ expect(scanner.changed?).to be_truthy
+ scanner.commit_if_changed
+ expect(scanner.changed?).to be_falsey
+
+ expect(scanner.lines).to eq(code_lines)
+
+ scanner.stash_changes # Assert does nothing if changes are already committed
+ expect(scanner.lines).to eq(code_lines)
+
+ scanner.revert_last_commit
+
+ expect(scanner.lines.join).to eq(code_lines[6].to_s)
+ end
+
+ it "is stashable" do
+ source = <<~'EOM'
+ class OH # 0
+ def lol # 1
+ print 'lol # 2
+ end # 3
+
+ def hello # 5
+ it "foo" do # 6
+ end # 7
+
+ def yolo # 8
+ print 'haha' # 9
+ end # 10
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[6])
+
+ scanner = ScanHistory.new(code_lines: code_lines, block: block)
+ scanner.scan(up: ->(_, _, _) { true }, down: ->(_, _, _) { true })
+
+ expect(scanner.lines).to eq(code_lines)
+ expect(scanner.changed?).to be_truthy
+ expect(scanner.next_up).to be_falsey
+ expect(scanner.next_down).to be_falsey
+
+ scanner.stash_changes
+
+ expect(scanner.changed?).to be_falsey
+
+ expect(scanner.next_up).to eq(code_lines[5])
+ expect(scanner.lines.join).to eq(code_lines[6].to_s)
+ expect(scanner.next_down).to eq(code_lines[7])
+ end
+
+ it "doesnt change if you dont't change it" do
+ source = <<~'EOM'
+ class OH # 0
+ def lol # 1
+ print 'lol # 2
+ end # 3
+
+ def hello # 5
+ it "foo" do # 6
+ end # 7
+
+ def yolo # 8
+ print 'haha' # 9
+ end # 10
+ end
+ EOM
+
+ code_lines = CleanDocument.new(source: source).call.lines
+ block = CodeBlock.new(lines: code_lines[6])
+
+ scanner = ScanHistory.new(code_lines: code_lines, block: block)
+
+ lines = scanner.lines
+ expect(scanner.changed?).to be_falsey
+ expect(scanner.next_up).to eq(code_lines[5])
+ expect(scanner.next_down).to eq(code_lines[7])
+
+ expect(scanner.stash_changes.lines).to eq(lines)
+ expect(scanner.revert_last_commit.lines).to eq(lines)
+
+ expect(scanner.scan(up: ->(_, _, _) { false }, down: ->(_, _, _) { false }).lines).to eq(lines)
+ end
+ end
+end
diff --git a/sprintf.c b/sprintf.c
index 693b30bd8b..b13530614f 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -28,9 +28,9 @@
#include "internal/object.h"
#include "internal/sanitizers.h"
#include "internal/symbol.h"
-#include "internal/util.h"
#include "ruby/encoding.h"
#include "ruby/re.h"
+#include "ruby/util.h"
#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
@@ -44,13 +44,13 @@ sign_bits(int base, const char *p)
switch (base) {
case 16:
- if (*p == 'X') c = 'F';
- else c = 'f';
- break;
+ if (*p == 'X') c = 'F';
+ else c = 'f';
+ break;
case 8:
- c = '7'; break;
+ c = '7'; break;
case 2:
- c = '1'; break;
+ c = '1'; break;
}
return c;
}
@@ -68,8 +68,8 @@ sign_bits(int base, const char *p)
#define CHECK(l) do {\
int cr = ENC_CODERANGE(result);\
while ((l) >= bsiz - blen) {\
- bsiz*=2;\
- if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
+ bsiz*=2;\
+ if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
}\
rb_str_resize(result, bsiz);\
ENC_CODERANGE_SET(result, cr);\
@@ -97,8 +97,8 @@ sign_bits(int base, const char *p)
blen += (l);\
} while (0)
-#define GETARG() (nextvalue != Qundef ? nextvalue : \
- GETNEXTARG())
+#define GETARG() (!UNDEF_P(nextvalue) ? nextvalue : \
+ GETNEXTARG())
#define GETNEXTARG() ( \
check_next_arg(posarg, nextarg), \
@@ -124,11 +124,11 @@ sign_bits(int base, const char *p)
n = 0; \
GETNUM(n, val); \
if (*p == '$') { \
- tmp = GETPOSARG(n); \
+ tmp = GETPOSARG(n); \
} \
else { \
- tmp = GETNEXTARG(); \
- p = t; \
+ tmp = GETNEXTARG(); \
+ p = t; \
} \
(val) = NUM2INT(tmp); \
} while (0)
@@ -138,15 +138,15 @@ get_num(const char *p, const char *end, rb_encoding *enc, int *valp)
{
int next_n = *valp;
for (; p < end && rb_enc_isdigit(*p, enc); p++) {
- if (MUL_OVERFLOW_INT_P(10, next_n))
- return NULL;
- next_n *= 10;
- if (INT_MAX - (*p - '0') < next_n)
- return NULL;
- next_n += *p - '0';
+ if (MUL_OVERFLOW_INT_P(10, next_n))
+ return NULL;
+ next_n *= 10;
+ if (INT_MAX - (*p - '0') < next_n)
+ return NULL;
+ next_n += *p - '0';
}
if (p >= end) {
- rb_raise(rb_eArgError, "malformed format string - %%*[0-9]");
+ rb_raise(rb_eArgError, "malformed format string - %%*[0-9]");
}
*valp = next_n;
return p;
@@ -157,9 +157,9 @@ check_next_arg(int posarg, int nextarg)
{
switch (posarg) {
case -1:
- rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg);
+ rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg);
case -2:
- rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg);
+ rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg);
}
}
@@ -167,13 +167,13 @@ static void
check_pos_arg(int posarg, int n)
{
if (posarg > 0) {
- rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg);
+ rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg);
}
if (posarg == -2) {
- rb_raise(rb_eArgError, "numbered(%d) after named", n);
+ rb_raise(rb_eArgError, "numbered(%d) after named", n);
}
if (n < 1) {
- rb_raise(rb_eArgError, "invalid index - %d$", n);
+ rb_raise(rb_eArgError, "invalid index - %d$", n);
}
}
@@ -181,10 +181,10 @@ static void
check_name_arg(int posarg, const char *name, int len, rb_encoding *enc)
{
if (posarg > 0) {
- rb_enc_raise(enc, rb_eArgError, "named%.*s after unnumbered(%d)", len, name, posarg);
+ rb_enc_raise(enc, rb_eArgError, "named%.*s after unnumbered(%d)", len, name, posarg);
}
if (posarg == -1) {
- rb_enc_raise(enc, rb_eArgError, "named%.*s after numbered", len, name);
+ rb_enc_raise(enc, rb_eArgError, "named%.*s after numbered", len, name);
}
}
@@ -193,13 +193,13 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
{
VALUE tmp;
- if (*hash != Qundef) return *hash;
+ if (!UNDEF_P(*hash)) return *hash;
if (argc != 2) {
- rb_raise(rb_eArgError, "one hash required");
+ rb_raise(rb_eArgError, "one hash required");
}
tmp = rb_check_hash_type(argv[1]);
if (NIL_P(tmp)) {
- rb_raise(rb_eArgError, "one hash required");
+ rb_raise(rb_eArgError, "one hash required");
}
return (*hash = tmp);
}
@@ -221,7 +221,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
VALUE result;
long scanned = 0;
- int coderange = ENC_CODERANGE_7BIT;
+ enum ruby_coderange_type coderange = ENC_CODERANGE_7BIT;
int width, prec, flags = FNONE;
int nextarg = 1;
int posarg = 0;
@@ -233,23 +233,33 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
#define CHECK_FOR_WIDTH(f) \
if ((f) & FWIDTH) { \
- rb_raise(rb_eArgError, "width given twice"); \
+ rb_raise(rb_eArgError, "width given twice"); \
} \
if ((f) & FPREC0) { \
- rb_raise(rb_eArgError, "width after precision"); \
+ rb_raise(rb_eArgError, "width after precision"); \
}
#define CHECK_FOR_FLAGS(f) \
if ((f) & FWIDTH) { \
- rb_raise(rb_eArgError, "flag after width"); \
+ rb_raise(rb_eArgError, "flag after width"); \
} \
if ((f) & FPREC0) { \
- rb_raise(rb_eArgError, "flag after precision"); \
+ rb_raise(rb_eArgError, "flag after precision"); \
}
+#define update_coderange(partial) do { \
+ if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) { \
+ int cr = coderange; \
+ scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr); \
+ ENC_CODERANGE_SET(result, \
+ (partial && cr == ENC_CODERANGE_UNKNOWN ? \
+ ENC_CODERANGE_BROKEN : (coderange = cr))); \
+ } \
+ } while (0)
++argc;
--argv;
StringValue(fmt);
enc = rb_enc_get(fmt);
+ rb_must_asciicompat(fmt);
orig = fmt;
fmt = rb_str_tmp_frozen_acquire(fmt);
p = RSTRING_PTR(fmt);
@@ -263,362 +273,360 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
ENC_CODERANGE_SET(result, coderange);
for (; p < end; p++) {
- const char *t;
- int n;
- VALUE sym = Qnil;
-
- for (t = p; t < end && *t != '%'; t++) ;
- if (t + 1 == end) {
- rb_raise(rb_eArgError, "incomplete format specifier; use %%%% (double %%) instead");
- }
- PUSH(p, t - p);
- if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
- scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange);
- ENC_CODERANGE_SET(result, coderange);
- }
- if (t >= end) {
- /* end of fmt string */
- goto sprint_exit;
- }
- p = t + 1; /* skip `%' */
-
- width = prec = -1;
- nextvalue = Qundef;
+ const char *t;
+ int n;
+ VALUE sym = Qnil;
+
+ for (t = p; t < end && *t != '%'; t++) ;
+ if (t + 1 == end) {
+ rb_raise(rb_eArgError, "incomplete format specifier; use %%%% (double %%) instead");
+ }
+ PUSH(p, t - p);
+ update_coderange(FALSE);
+ if (t >= end) {
+ /* end of fmt string */
+ goto sprint_exit;
+ }
+ p = t + 1; /* skip `%' */
+
+ width = prec = -1;
+ nextvalue = Qundef;
retry:
- switch (*p) {
- default:
- if (rb_enc_isprint(*p, enc))
- rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
- else
- rb_raise(rb_eArgError, "malformed format string");
- break;
-
- case ' ':
- CHECK_FOR_FLAGS(flags);
- flags |= FSPACE;
- p++;
- goto retry;
-
- case '#':
- CHECK_FOR_FLAGS(flags);
- flags |= FSHARP;
- p++;
- goto retry;
-
- case '+':
- CHECK_FOR_FLAGS(flags);
- flags |= FPLUS;
- p++;
- goto retry;
-
- case '-':
- CHECK_FOR_FLAGS(flags);
- flags |= FMINUS;
- p++;
- goto retry;
-
- case '0':
- CHECK_FOR_FLAGS(flags);
- flags |= FZERO;
- p++;
- goto retry;
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- GETNUM(n, width);
- if (*p == '$') {
- if (nextvalue != Qundef) {
- rb_raise(rb_eArgError, "value given twice - %d$", n);
- }
- nextvalue = GETPOSARG(n);
- p++;
- goto retry;
- }
- CHECK_FOR_WIDTH(flags);
- width = n;
- flags |= FWIDTH;
- goto retry;
-
- case '<':
- case '{':
- {
- const char *start = p;
- char term = (*p == '<') ? '>' : '}';
- int len;
-
- for (; p < end && *p != term; ) {
- p += rb_enc_mbclen(p, end, enc);
- }
- if (p >= end) {
- rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
- }
+ switch (*p) {
+ default:
+ if (rb_enc_isprint(*p, enc))
+ rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
+ else
+ rb_raise(rb_eArgError, "malformed format string");
+ break;
+
+ case ' ':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FSPACE;
+ p++;
+ goto retry;
+
+ case '#':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FSHARP;
+ p++;
+ goto retry;
+
+ case '+':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FPLUS;
+ p++;
+ goto retry;
+
+ case '-':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FMINUS;
+ p++;
+ goto retry;
+
+ case '0':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FZERO;
+ p++;
+ goto retry;
+
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ GETNUM(n, width);
+ if (*p == '$') {
+ if (!UNDEF_P(nextvalue)) {
+ rb_raise(rb_eArgError, "value given twice - %d$", n);
+ }
+ nextvalue = GETPOSARG(n);
+ p++;
+ goto retry;
+ }
+ CHECK_FOR_WIDTH(flags);
+ width = n;
+ flags |= FWIDTH;
+ goto retry;
+
+ case '<':
+ case '{':
+ {
+ const char *start = p;
+ char term = (*p == '<') ? '>' : '}';
+ int len;
+
+ for (; p < end && *p != term; ) {
+ p += rb_enc_mbclen(p, end, enc);
+ }
+ if (p >= end) {
+ rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
+ }
#if SIZEOF_INT < SIZEOF_SIZE_T
- if ((size_t)(p - start) >= INT_MAX) {
- const int message_limit = 20;
- len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
- rb_enc_raise(enc, rb_eArgError,
- "too long name (%"PRIuSIZE" bytes) - %.*s...%c",
- (size_t)(p - start - 2), len, start, term);
- }
+ if ((size_t)(p - start) >= INT_MAX) {
+ const int message_limit = 20;
+ len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
+ rb_enc_raise(enc, rb_eArgError,
+ "too long name (%"PRIuSIZE" bytes) - %.*s...%c",
+ (size_t)(p - start - 2), len, start, term);
+ }
#endif
- len = (int)(p - start + 1); /* including parenthesis */
- if (sym != Qnil) {
- rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
- len, start, rb_sym2str(sym));
- }
- CHECKNAMEARG(start, len, enc);
- get_hash(&hash, argc, argv);
- sym = rb_check_symbol_cstr(start + 1,
- len - 2 /* without parenthesis */,
- enc);
- if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
- if (nextvalue == Qundef) {
- if (NIL_P(sym)) {
- sym = rb_sym_intern(start + 1,
- len - 2 /* without parenthesis */,
- enc);
- }
- nextvalue = rb_hash_default_value(hash, sym);
- if (NIL_P(nextvalue)) {
- rb_key_err_raise(rb_enc_sprintf(enc, "key%.*s not found", len, start), hash, sym);
- }
- }
- if (term == '}') goto format_s;
- p++;
- goto retry;
- }
-
- case '*':
- CHECK_FOR_WIDTH(flags);
- flags |= FWIDTH;
- GETASTER(width);
- if (width < 0) {
- flags |= FMINUS;
- width = -width;
- if (width < 0) rb_raise(rb_eArgError, "width too big");
- }
- p++;
- goto retry;
-
- case '.':
- if (flags & FPREC0) {
- rb_raise(rb_eArgError, "precision given twice");
- }
- flags |= FPREC|FPREC0;
-
- prec = 0;
- p++;
- if (*p == '*') {
- GETASTER(prec);
- if (prec < 0) { /* ignore negative precision */
- flags &= ~FPREC;
- }
- p++;
- goto retry;
- }
-
- GETNUM(prec, precision);
- goto retry;
-
- case '\n':
- case '\0':
- p--;
+ len = (int)(p - start + 1); /* including parenthesis */
+ if (sym != Qnil) {
+ rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
+ len, start, rb_sym2str(sym));
+ }
+ CHECKNAMEARG(start, len, enc);
+ get_hash(&hash, argc, argv);
+ sym = rb_check_symbol_cstr(start + 1,
+ len - 2 /* without parenthesis */,
+ enc);
+ if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
+ if (UNDEF_P(nextvalue)) {
+ if (NIL_P(sym)) {
+ sym = rb_sym_intern(start + 1,
+ len - 2 /* without parenthesis */,
+ enc);
+ }
+ nextvalue = rb_hash_default_value(hash, sym);
+ if (NIL_P(nextvalue)) {
+ rb_key_err_raise(rb_enc_sprintf(enc, "key%.*s not found", len, start), hash, sym);
+ }
+ }
+ if (term == '}') goto format_s;
+ p++;
+ goto retry;
+ }
+
+ case '*':
+ CHECK_FOR_WIDTH(flags);
+ flags |= FWIDTH;
+ GETASTER(width);
+ if (width < 0) {
+ flags |= FMINUS;
+ width = -width;
+ if (width < 0) rb_raise(rb_eArgError, "width too big");
+ }
+ p++;
+ goto retry;
+
+ case '.':
+ if (flags & FPREC0) {
+ rb_raise(rb_eArgError, "precision given twice");
+ }
+ flags |= FPREC|FPREC0;
+
+ prec = 0;
+ p++;
+ if (*p == '*') {
+ GETASTER(prec);
+ if (prec < 0) { /* ignore negative precision */
+ flags &= ~FPREC;
+ }
+ p++;
+ goto retry;
+ }
+
+ GETNUM(prec, precision);
+ goto retry;
+
+ case '\n':
+ case '\0':
+ p--;
/* fall through */
- case '%':
- if (flags != FNONE) {
- rb_raise(rb_eArgError, "invalid format character - %%");
- }
- PUSH("%", 1);
- break;
-
- case 'c':
- {
- VALUE val = GETARG();
- VALUE tmp;
- unsigned int c;
- int n;
-
- tmp = rb_check_string_type(val);
- if (!NIL_P(tmp)) {
- if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) {
- rb_raise(rb_eArgError, "%%c requires a character");
- }
- c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc);
- RB_GC_GUARD(tmp);
- }
- else {
- c = NUM2INT(val);
- n = rb_enc_codelen(c, enc);
- }
- if (n <= 0) {
- rb_raise(rb_eArgError, "invalid character");
- }
- if (!(flags & FWIDTH)) {
- CHECK(n);
- rb_enc_mbcput(c, &buf[blen], enc);
- blen += n;
- }
- else if ((flags & FMINUS)) {
- CHECK(n);
- rb_enc_mbcput(c, &buf[blen], enc);
- blen += n;
- if (width > 1) FILL(' ', width-1);
- }
- else {
- if (width > 1) FILL(' ', width-1);
- CHECK(n);
- rb_enc_mbcput(c, &buf[blen], enc);
- blen += n;
- }
- }
- break;
-
- case 's':
- case 'p':
- format_s:
- {
- VALUE arg = GETARG();
- long len, slen;
-
- if (*p == 'p') {
- str = rb_inspect(arg);
- }
- else {
- str = rb_obj_as_string(arg);
- }
- len = RSTRING_LEN(str);
- rb_str_set_len(result, blen);
- if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
- int cr = coderange;
- scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr);
- ENC_CODERANGE_SET(result,
- (cr == ENC_CODERANGE_UNKNOWN ?
- ENC_CODERANGE_BROKEN : (coderange = cr)));
- }
- enc = rb_enc_check(result, str);
- if (flags&(FPREC|FWIDTH)) {
- slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
- if (slen < 0) {
- rb_raise(rb_eArgError, "invalid mbstring sequence");
- }
- if ((flags&FPREC) && (prec < slen)) {
- char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
- prec, enc);
- slen = prec;
- len = p - RSTRING_PTR(str);
- }
- /* need to adjust multi-byte string pos */
- if ((flags&FWIDTH) && (width > slen)) {
- width -= (int)slen;
- if (!(flags&FMINUS)) {
- FILL(' ', width);
- width = 0;
- }
- CHECK(len);
- memcpy(&buf[blen], RSTRING_PTR(str), len);
- RB_GC_GUARD(str);
- blen += len;
- if (flags&FMINUS) {
- FILL(' ', width);
- }
- rb_enc_associate(result, enc);
- break;
- }
- }
- PUSH(RSTRING_PTR(str), len);
- RB_GC_GUARD(str);
- rb_enc_associate(result, enc);
- }
- break;
-
- case 'd':
- case 'i':
- case 'o':
- case 'x':
- case 'X':
- case 'b':
- case 'B':
- case 'u':
- {
- volatile VALUE val = GETARG();
+ case '%':
+ if (flags != FNONE) {
+ rb_raise(rb_eArgError, "invalid format character - %%");
+ }
+ PUSH("%", 1);
+ break;
+
+ case 'c':
+ {
+ VALUE val = GETARG();
+ VALUE tmp;
+ unsigned int c;
+ int n;
+
+ tmp = rb_check_string_type(val);
+ if (!NIL_P(tmp)) {
+ flags |= FPREC;
+ prec = 1;
+ str = tmp;
+ goto format_s1;
+ }
+ n = NUM2INT(val);
+ if (n >= 0) n = rb_enc_codelen((c = n), enc);
+ if (n <= 0) {
+ rb_raise(rb_eArgError, "invalid character");
+ }
+ int encidx = rb_ascii8bit_appendable_encoding_index(enc, c);
+ if (encidx >= 0 && encidx != rb_enc_to_index(enc)) {
+ /* special case */
+ rb_enc_associate_index(result, encidx);
+ enc = rb_enc_from_index(encidx);
+ coderange = ENC_CODERANGE_VALID;
+ }
+ if (!(flags & FWIDTH)) {
+ CHECK(n);
+ rb_enc_mbcput(c, &buf[blen], enc);
+ blen += n;
+ }
+ else if ((flags & FMINUS)) {
+ --width;
+ CHECK(n + (width > 0 ? width : 0));
+ rb_enc_mbcput(c, &buf[blen], enc);
+ blen += n;
+ if (width > 0) FILL_(' ', width);
+ }
+ else {
+ --width;
+ CHECK(n + (width > 0 ? width : 0));
+ if (width > 0) FILL_(' ', width);
+ rb_enc_mbcput(c, &buf[blen], enc);
+ blen += n;
+ }
+ }
+ break;
+
+ case 's':
+ case 'p':
+ format_s:
+ {
+ VALUE arg = GETARG();
+ long len, slen;
+
+ if (*p == 'p') {
+ str = rb_inspect(arg);
+ }
+ else {
+ str = rb_obj_as_string(arg);
+ }
+ format_s1:
+ len = RSTRING_LEN(str);
+ rb_str_set_len(result, blen);
+ update_coderange(TRUE);
+ enc = rb_enc_check(result, str);
+ if (flags&(FPREC|FWIDTH)) {
+ slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
+ if (slen < 0) {
+ rb_raise(rb_eArgError, "invalid mbstring sequence");
+ }
+ if ((flags&FPREC) && (prec < slen)) {
+ char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
+ prec, enc);
+ slen = prec;
+ len = p - RSTRING_PTR(str);
+ }
+ /* need to adjust multi-byte string pos */
+ if ((flags&FWIDTH) && (width > slen)) {
+ width -= (int)slen;
+ CHECK(len + width);
+ if (!(flags&FMINUS)) {
+ FILL_(' ', width);
+ width = 0;
+ }
+ memcpy(&buf[blen], RSTRING_PTR(str), len);
+ RB_GC_GUARD(str);
+ blen += len;
+ if (flags&FMINUS) {
+ FILL_(' ', width);
+ }
+ rb_enc_associate(result, enc);
+ break;
+ }
+ }
+ PUSH(RSTRING_PTR(str), len);
+ RB_GC_GUARD(str);
+ rb_enc_associate(result, enc);
+ }
+ break;
+
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'b':
+ case 'B':
+ case 'u':
+ {
+ volatile VALUE val = GETARG();
int valsign;
- char nbuf[BIT_DIGITS(SIZEOF_LONG*CHAR_BIT)+2], *s;
- const char *prefix = 0;
- int sign = 0, dots = 0;
- char sc = 0;
- long v = 0;
- int base, bignum = 0;
- int len;
-
- switch (*p) {
- case 'd':
- case 'i':
- case 'u':
- sign = 1; break;
- case 'o':
- case 'x':
- case 'X':
- case 'b':
- case 'B':
- if (flags&(FPLUS|FSPACE)) sign = 1;
- break;
- }
- if (flags & FSHARP) {
- switch (*p) {
- case 'o':
- prefix = "0"; break;
- case 'x':
- prefix = "0x"; break;
- case 'X':
- prefix = "0X"; break;
- case 'b':
- prefix = "0b"; break;
- case 'B':
- prefix = "0B"; break;
- }
- }
-
- bin_retry:
- switch (TYPE(val)) {
- case T_FLOAT:
- if (FIXABLE(RFLOAT_VALUE(val))) {
- val = LONG2FIX((long)RFLOAT_VALUE(val));
- goto bin_retry;
- }
- val = rb_dbl2big(RFLOAT_VALUE(val));
- if (FIXNUM_P(val)) goto bin_retry;
- bignum = 1;
- break;
- case T_STRING:
- val = rb_str_to_inum(val, 0, TRUE);
- goto bin_retry;
- case T_BIGNUM:
- bignum = 1;
- break;
- case T_FIXNUM:
- v = FIX2LONG(val);
- break;
- default:
- val = rb_Integer(val);
- goto bin_retry;
- }
-
- switch (*p) {
- case 'o':
- base = 8; break;
- case 'x':
- case 'X':
- base = 16; break;
- case 'b':
- case 'B':
- base = 2; break;
- case 'u':
- case 'd':
- case 'i':
- default:
- base = 10; break;
- }
+ char nbuf[BIT_DIGITS(SIZEOF_LONG*CHAR_BIT)+2], *s;
+ const char *prefix = 0;
+ int sign = 0, dots = 0;
+ char sc = 0;
+ long v = 0;
+ int base, bignum = 0;
+ int len;
+
+ switch (*p) {
+ case 'd':
+ case 'i':
+ case 'u':
+ sign = 1; break;
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'b':
+ case 'B':
+ if (flags&(FPLUS|FSPACE)) sign = 1;
+ break;
+ }
+ if (flags & FSHARP) {
+ switch (*p) {
+ case 'o':
+ prefix = "0"; break;
+ case 'x':
+ prefix = "0x"; break;
+ case 'X':
+ prefix = "0X"; break;
+ case 'b':
+ prefix = "0b"; break;
+ case 'B':
+ prefix = "0B"; break;
+ }
+ }
+
+ bin_retry:
+ switch (TYPE(val)) {
+ case T_FLOAT:
+ if (FIXABLE(RFLOAT_VALUE(val))) {
+ val = LONG2FIX((long)RFLOAT_VALUE(val));
+ goto bin_retry;
+ }
+ val = rb_dbl2big(RFLOAT_VALUE(val));
+ if (FIXNUM_P(val)) goto bin_retry;
+ bignum = 1;
+ break;
+ case T_STRING:
+ val = rb_str_to_inum(val, 0, TRUE);
+ goto bin_retry;
+ case T_BIGNUM:
+ bignum = 1;
+ break;
+ case T_FIXNUM:
+ v = FIX2LONG(val);
+ break;
+ default:
+ val = rb_Integer(val);
+ goto bin_retry;
+ }
+
+ switch (*p) {
+ case 'o':
+ base = 8; break;
+ case 'x':
+ case 'X':
+ base = 16; break;
+ case 'b':
+ case 'B':
+ base = 2; break;
+ case 'u':
+ case 'd':
+ case 'i':
+ default:
+ base = 10; break;
+ }
if (base != 10) {
int numbits = ffs(base)-1;
@@ -690,10 +698,10 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
sc = ' ';
width--;
}
- s = ruby_ultoa((unsigned long)v, nbuf + sizeof(nbuf), 10, 0);
- len = (int)(nbuf + sizeof(nbuf) - s);
- }
- else {
+ s = ruby_ultoa((unsigned long)v, nbuf + sizeof(nbuf), 10, 0);
+ len = (int)(nbuf + sizeof(nbuf) - s);
+ }
+ else {
tmp = rb_big2str(val, 10);
s = RSTRING_PTR(tmp);
valsign = 1;
@@ -711,230 +719,231 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
sc = ' ';
width--;
}
- len = rb_long2int(RSTRING_END(tmp) - s);
- }
-
- if (dots) {
- prec -= 2;
- width -= 2;
- }
-
- if (*p == 'X') {
- char *pp = s;
- int c;
- while ((c = (int)(unsigned char)*pp) != 0) {
- *pp = rb_enc_toupper(c, enc);
- pp++;
- }
- }
- if (prefix && !prefix[1]) { /* octal */
- if (dots) {
- prefix = 0;
- }
- else if (len == 1 && *s == '0') {
- len = 0;
- if (flags & FPREC) prec--;
- }
- else if ((flags & FPREC) && (prec > len)) {
- prefix = 0;
- }
- }
- else if (len == 1 && *s == '0') {
- prefix = 0;
- }
- if (prefix) {
- width -= (int)strlen(prefix);
- }
- if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
- prec = width;
- width = 0;
- }
- else {
- if (prec < len) {
- if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
- prec = len;
- }
- width -= prec;
- }
- if (!(flags&FMINUS)) {
- FILL(' ', width);
- width = 0;
- }
- if (sc) PUSH(&sc, 1);
- if (prefix) {
- int plen = (int)strlen(prefix);
- PUSH(prefix, plen);
- }
- if (dots) PUSH("..", 2);
- if (prec > len) {
- CHECK(prec - len);
- if (!sign && valsign < 0) {
- char c = sign_bits(base, p);
- FILL_(c, prec - len);
- }
- else if ((flags & (FMINUS|FPREC)) != FMINUS) {
- FILL_('0', prec - len);
- }
- }
- PUSH(s, len);
- RB_GC_GUARD(tmp);
- FILL(' ', width);
- }
- break;
-
- case 'f':
- {
- VALUE val = GETARG(), num, den;
- int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
- long len, fill;
- if (RB_INTEGER_TYPE_P(val)) {
- den = INT2FIX(1);
- num = val;
- }
- else if (RB_TYPE_P(val, T_RATIONAL)) {
- den = rb_rational_den(val);
- num = rb_rational_num(val);
- }
- else {
- nextvalue = val;
- goto float_value;
- }
- if (!(flags&FPREC)) prec = default_float_precision;
- if (FIXNUM_P(num)) {
- if ((SIGNED_VALUE)num < 0) {
- long n = -FIX2LONG(num);
- num = LONG2FIX(n);
- sign = -1;
- }
- }
- else if (BIGNUM_NEGATIVE_P(num)) {
- sign = -1;
- num = rb_big_uminus(num);
- }
- if (den != INT2FIX(1)) {
- num = rb_int_mul(num, rb_int_positive_pow(10, prec));
- num = rb_int_plus(num, rb_int_idiv(den, INT2FIX(2)));
- num = rb_int_idiv(num, den);
- }
- else if (prec >= 0) {
- zero = prec;
- }
- val = rb_int2str(num, 10);
- len = RSTRING_LEN(val) + zero;
- if (prec >= len) len = prec + 1; /* integer part 0 */
- if (sign || (flags&FSPACE)) ++len;
- if (prec > 0) ++len; /* period */
- fill = width > len ? width - len : 0;
- CHECK(fill + len);
- if (fill && !(flags&(FMINUS|FZERO))) {
- FILL_(' ', fill);
- }
- if (sign || (flags&FSPACE)) {
- buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
- }
- if (fill && (flags&(FMINUS|FZERO)) == FZERO) {
- FILL_('0', fill);
- }
- len = RSTRING_LEN(val) + zero;
- t = RSTRING_PTR(val);
- if (len > prec) {
- PUSH_(t, len - prec);
- }
- else {
- buf[blen++] = '0';
- }
- if (prec > 0) {
- buf[blen++] = '.';
- }
- if (zero) {
- FILL_('0', zero);
- }
- else if (prec > len) {
- FILL_('0', prec - len);
- PUSH_(t, len);
- }
- else if (prec > 0) {
- PUSH_(t + len - prec, prec);
- }
- if (fill && (flags&FMINUS)) {
- FILL_(' ', fill);
- }
- RB_GC_GUARD(val);
- break;
- }
- case 'g':
- case 'G':
- case 'e':
- case 'E':
- /* TODO: rational support */
- case 'a':
- case 'A':
- float_value:
- {
- VALUE val = GETARG();
- double fval;
-
- fval = RFLOAT_VALUE(rb_Float(val));
- if (isnan(fval) || isinf(fval)) {
- const char *expr;
- int need;
- int elen;
- char sign = '\0';
-
- if (isnan(fval)) {
- expr = "NaN";
- }
- else {
- expr = "Inf";
- }
- need = (int)strlen(expr);
- elen = need;
- if (!isnan(fval) && fval < 0.0)
- sign = '-';
- else if (flags & (FPLUS|FSPACE))
- sign = (flags & FPLUS) ? '+' : ' ';
- if (sign)
- ++need;
- if ((flags & FWIDTH) && need < width)
- need = width;
-
- FILL(' ', need);
- if (flags & FMINUS) {
- if (sign)
- buf[blen - need--] = sign;
- memcpy(&buf[blen - need], expr, elen);
- }
- else {
- if (sign)
- buf[blen - elen - 1] = sign;
- memcpy(&buf[blen - elen], expr, elen);
- }
- break;
- }
- else {
- int cr = ENC_CODERANGE(result);
- char fbuf[2*BIT_DIGITS(SIZEOF_INT*CHAR_BIT)+10];
- char *fmt = fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
- rb_str_set_len(result, blen);
- rb_str_catf(result, fmt, fval);
- ENC_CODERANGE_SET(result, cr);
- bsiz = rb_str_capacity(result);
- RSTRING_GETMEM(result, buf, blen);
- }
- }
- break;
- }
- flags = FNONE;
+ len = rb_long2int(RSTRING_END(tmp) - s);
+ }
+
+ if (dots) {
+ prec -= 2;
+ width -= 2;
+ }
+
+ if (*p == 'X') {
+ char *pp = s;
+ int c;
+ while ((c = (int)(unsigned char)*pp) != 0) {
+ *pp = rb_enc_toupper(c, enc);
+ pp++;
+ }
+ }
+ if (prefix && !prefix[1]) { /* octal */
+ if (dots) {
+ prefix = 0;
+ }
+ else if (len == 1 && *s == '0') {
+ len = 0;
+ if (flags & FPREC) prec--;
+ }
+ else if ((flags & FPREC) && (prec > len)) {
+ prefix = 0;
+ }
+ }
+ else if (len == 1 && *s == '0') {
+ prefix = 0;
+ }
+ if (prefix) {
+ width -= (int)strlen(prefix);
+ }
+ if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
+ prec = width;
+ width = 0;
+ }
+ else {
+ if (prec < len) {
+ if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
+ prec = len;
+ }
+ width -= prec;
+ }
+ if (!(flags&FMINUS)) {
+ FILL(' ', width);
+ width = 0;
+ }
+ if (sc) PUSH(&sc, 1);
+ if (prefix) {
+ int plen = (int)strlen(prefix);
+ PUSH(prefix, plen);
+ }
+ if (dots) PUSH("..", 2);
+ if (prec > len) {
+ CHECK(prec - len);
+ if (!sign && valsign < 0) {
+ char c = sign_bits(base, p);
+ FILL_(c, prec - len);
+ }
+ else if ((flags & (FMINUS|FPREC)) != FMINUS) {
+ FILL_('0', prec - len);
+ }
+ }
+ PUSH(s, len);
+ RB_GC_GUARD(tmp);
+ FILL(' ', width);
+ }
+ break;
+
+ case 'f':
+ {
+ VALUE val = GETARG(), num, den;
+ int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
+ long len, fill;
+ if (RB_INTEGER_TYPE_P(val)) {
+ den = INT2FIX(1);
+ num = val;
+ }
+ else if (RB_TYPE_P(val, T_RATIONAL)) {
+ den = rb_rational_den(val);
+ num = rb_rational_num(val);
+ }
+ else {
+ nextvalue = val;
+ goto float_value;
+ }
+ if (!(flags&FPREC)) prec = default_float_precision;
+ if (FIXNUM_P(num)) {
+ if ((SIGNED_VALUE)num < 0) {
+ long n = -FIX2LONG(num);
+ num = LONG2NUM(n);
+ sign = -1;
+ }
+ }
+ else if (BIGNUM_NEGATIVE_P(num)) {
+ sign = -1;
+ num = rb_big_uminus(num);
+ }
+ if (den != INT2FIX(1)) {
+ num = rb_int_mul(num, rb_int_positive_pow(10, prec));
+ num = rb_int_plus(num, rb_int_idiv(den, INT2FIX(2)));
+ num = rb_int_idiv(num, den);
+ }
+ else if (prec >= 0) {
+ zero = prec;
+ }
+ val = rb_int2str(num, 10);
+ len = RSTRING_LEN(val) + zero;
+ if (prec >= len) len = prec + 1; /* integer part 0 */
+ if (sign || (flags&FSPACE)) ++len;
+ if (prec > 0) ++len; /* period */
+ fill = width > len ? width - len : 0;
+ CHECK(fill + len);
+ if (fill && !(flags&(FMINUS|FZERO))) {
+ FILL_(' ', fill);
+ }
+ if (sign || (flags&FSPACE)) {
+ buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
+ }
+ if (fill && (flags&(FMINUS|FZERO)) == FZERO) {
+ FILL_('0', fill);
+ }
+ len = RSTRING_LEN(val) + zero;
+ t = RSTRING_PTR(val);
+ if (len > prec) {
+ PUSH_(t, len - prec);
+ }
+ else {
+ buf[blen++] = '0';
+ }
+ if (prec > 0) {
+ buf[blen++] = '.';
+ }
+ if (zero) {
+ FILL_('0', zero);
+ }
+ else if (prec > len) {
+ FILL_('0', prec - len);
+ PUSH_(t, len);
+ }
+ else if (prec > 0) {
+ PUSH_(t + len - prec, prec);
+ }
+ if (fill && (flags&FMINUS)) {
+ FILL_(' ', fill);
+ }
+ RB_GC_GUARD(val);
+ break;
+ }
+ case 'g':
+ case 'G':
+ case 'e':
+ case 'E':
+ /* TODO: rational support */
+ case 'a':
+ case 'A':
+ float_value:
+ {
+ VALUE val = GETARG();
+ double fval;
+
+ fval = RFLOAT_VALUE(rb_Float(val));
+ if (!isfinite(fval)) {
+ const char *expr;
+ int need;
+ int elen;
+ char sign = '\0';
+
+ if (isnan(fval)) {
+ expr = "NaN";
+ }
+ else {
+ expr = "Inf";
+ }
+ need = (int)strlen(expr);
+ elen = need;
+ if (!isnan(fval) && fval < 0.0)
+ sign = '-';
+ else if (flags & (FPLUS|FSPACE))
+ sign = (flags & FPLUS) ? '+' : ' ';
+ if (sign)
+ ++need;
+ if ((flags & FWIDTH) && need < width)
+ need = width;
+
+ FILL(' ', need);
+ if (flags & FMINUS) {
+ if (sign)
+ buf[blen - need--] = sign;
+ memcpy(&buf[blen - need], expr, elen);
+ }
+ else {
+ if (sign)
+ buf[blen - elen - 1] = sign;
+ memcpy(&buf[blen - elen], expr, elen);
+ }
+ break;
+ }
+ else {
+ int cr = ENC_CODERANGE(result);
+ char fbuf[2*BIT_DIGITS(SIZEOF_INT*CHAR_BIT)+10];
+ char *fmt = fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
+ rb_str_set_len(result, blen);
+ rb_str_catf(result, fmt, fval);
+ ENC_CODERANGE_SET(result, cr);
+ bsiz = rb_str_capacity(result);
+ RSTRING_GETMEM(result, buf, blen);
+ }
+ }
+ break;
+ }
+ flags = FNONE;
}
+ update_coderange(FALSE);
sprint_exit:
rb_str_tmp_frozen_release(orig, fmt);
/* XXX - We cannot validate the number of arguments if (digit)$ style used.
*/
if (posarg >= 0 && nextarg < argc) {
- const char *mesg = "too many arguments for format string";
- if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
- if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
+ const char *mesg = "too many arguments for format string";
+ if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
+ if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
}
rb_str_resize(result, blen);
@@ -949,12 +958,12 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
*--buf = c;
if (flags & FPREC) {
- buf = ruby_ultoa(prec, buf, 10, 0);
- *--buf = '.';
+ buf = ruby_ultoa(prec, buf, 10, 0);
+ *--buf = '.';
}
if (flags & FWIDTH) {
- buf = ruby_ultoa(width, buf, 10, 0);
+ buf = ruby_ultoa(width, buf, 10, 0);
}
if (flags & FSPACE) *--buf = ' ';
@@ -1008,7 +1017,7 @@ int
ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{
if (str && (ssize_t)n < 1)
- return (EOF);
+ return (EOF);
return ruby_do_vsnprintf(str, n, fmt, ap);
}
@@ -1038,7 +1047,7 @@ ruby_snprintf(char *str, size_t n, char const *fmt, ...)
va_list ap;
if (str && (ssize_t)n < 1)
- return (EOF);
+ return (EOF);
va_start(ap, fmt);
ret = ruby_do_vsnprintf(str, n, fmt, ap);
@@ -1061,22 +1070,22 @@ ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
long blen = buf - RSTRING_PTR(result), bsiz = fp->_w;
if (RBASIC(result)->klass) {
- rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
+ rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
}
if (uio->uio_resid == 0)
- return 0;
+ return 0;
#if SIZE_MAX > LONG_MAX
if (uio->uio_resid >= LONG_MAX)
- rb_raise(rb_eRuntimeError, "too big string");
+ rb_raise(rb_eRuntimeError, "too big string");
#endif
len = (long)uio->uio_resid;
CHECK(len);
buf += blen;
fp->_w = bsiz;
for (iov = uio->uio_iov; len > 0; ++iov) {
- MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
- buf += n;
- len -= n;
+ MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
+ buf += n;
+ len -= n;
}
fp->_p = (unsigned char *)buf;
rb_str_set_len(result, buf - RSTRING_PTR(result));
@@ -1093,51 +1102,41 @@ ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz, int s
if (valsize != sizeof(VALUE)) return 0;
value = *(VALUE *)valp;
if (RBASIC(result)->klass) {
- rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
+ rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
}
if (sign == '+') {
- if (RB_TYPE_P(value, T_CLASS)) {
# define LITERAL(str) (*sz = rb_strlen_lit(str), str)
-
- if (value == rb_cNilClass) {
- return LITERAL("nil");
- }
- else if (value == rb_cInteger) {
- return LITERAL("Integer");
- }
- else if (value == rb_cSymbol) {
- return LITERAL("Symbol");
- }
- else if (value == rb_cTrueClass) {
- return LITERAL("true");
- }
- else if (value == rb_cFalseClass) {
- return LITERAL("false");
- }
+ /* optimize special const cases */
+ switch (value) {
+# define LITERAL_CASE(x) case Q##x: return LITERAL(#x)
+ LITERAL_CASE(nil);
+ LITERAL_CASE(true);
+ LITERAL_CASE(false);
+# undef LITERAL_CASE
+ }
# undef LITERAL
- }
- value = rb_inspect(value);
+ value = rb_inspect(value);
}
else if (SYMBOL_P(value)) {
- value = rb_sym2str(value);
- if (sign == ' ' && !rb_str_symname_p(value)) {
- value = rb_str_escape(value);
- }
+ value = rb_sym2str(value);
+ if (sign == ' ' && !rb_str_symname_p(value)) {
+ value = rb_str_escape(value);
+ }
}
else {
- value = rb_obj_as_string(value);
- if (sign == ' ') value = QUOTE(value);
+ value = rb_obj_as_string(value);
+ if (sign == ' ') value = QUOTE(value);
}
enc = rb_enc_compatible(result, value);
if (enc) {
- rb_enc_associate(result, enc);
+ rb_enc_associate(result, enc);
}
else {
- enc = rb_enc_get(result);
- value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
- ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
- Qnil);
- *(volatile VALUE *)valp = value;
+ enc = rb_enc_get(result);
+ value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
+ ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
+ Qnil);
+ *(volatile VALUE *)valp = value;
}
StringValueCStr(value);
RSTRING_GETMEM(value, cp, *sz);
@@ -1145,36 +1144,54 @@ ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz, int s
return cp;
}
-VALUE
-rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
+static void
+ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
{
rb_printf_buffer_extra buffer;
#define f buffer.base
- VALUE result;
+ VALUE klass = RBASIC(result)->klass;
+ int coderange = ENC_CODERANGE(result);
+ long scanned = 0;
+
+ if (coderange != ENC_CODERANGE_UNKNOWN) scanned = p - RSTRING_PTR(result);
f._flags = __SWR | __SSTR;
f._bf._size = 0;
- f._w = 120;
- result = rb_str_buf_new(f._w);
- if (enc) {
- if (rb_enc_mbminlen(enc) > 1) {
- /* the implementation deeply depends on plain char */
- rb_raise(rb_eArgError, "cannot construct wchar_t based encoding string: %s",
- rb_enc_name(enc));
- }
- rb_enc_associate(result, enc);
- }
+ f._w = rb_str_capacity(result);
f._bf._base = (unsigned char *)result;
- f._p = (unsigned char *)RSTRING_PTR(result);
+ f._p = (unsigned char *)p;
RBASIC_CLEAR_CLASS(result);
f.vwrite = ruby__sfvwrite;
f.vextra = ruby__sfvextra;
buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
- RBASIC_SET_CLASS_RAW(result, rb_cString);
- rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
+ RBASIC_SET_CLASS_RAW(result, klass);
+ p = RSTRING_PTR(result);
+ long blen = (char *)f._p - p;
+ if (scanned < blen) {
+ rb_str_coderange_scan_restartable(p + scanned, p + blen, rb_enc_get(result), &coderange);
+ ENC_CODERANGE_SET(result, coderange);
+ }
+ rb_str_resize(result, blen);
#undef f
+}
+VALUE
+rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
+{
+ const int initial_len = 120;
+ VALUE result;
+
+ result = rb_str_buf_new(initial_len);
+ if (enc) {
+ if (rb_enc_mbminlen(enc) > 1) {
+ /* the implementation deeply depends on plain char */
+ rb_raise(rb_eArgError, "cannot construct wchar_t based encoding string: %s",
+ rb_enc_name(enc));
+ }
+ rb_enc_associate(result, enc);
+ }
+ ruby_vsprintf0(result, RSTRING_PTR(result), fmt, ap);
return result;
}
@@ -1213,26 +1230,9 @@ rb_sprintf(const char *format, ...)
VALUE
rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
{
- rb_printf_buffer_extra buffer;
-#define f buffer.base
- VALUE klass;
-
StringValue(str);
rb_str_modify(str);
- f._flags = __SWR | __SSTR;
- f._bf._size = 0;
- f._w = rb_str_capacity(str);
- f._bf._base = (unsigned char *)str;
- f._p = (unsigned char *)RSTRING_END(str);
- klass = RBASIC(str)->klass;
- RBASIC_CLEAR_CLASS(str);
- f.vwrite = ruby__sfvwrite;
- f.vextra = ruby__sfvextra;
- buffer.value = 0;
- BSD_vfprintf(&f, fmt, ap);
- RBASIC_SET_CLASS_RAW(str, klass);
- rb_str_resize(str, (char *)f._p - RSTRING_PTR(str));
-#undef f
+ ruby_vsprintf0(str, RSTRING_END(str), fmt, ap);
return str;
}
diff --git a/st.c b/st.c
index 53e9dc8320..d9a588db8a 100644
--- a/st.c
+++ b/st.c
@@ -103,11 +103,13 @@
#ifdef NOT_RUBY
#include "regint.h"
#include "st.h"
+#include <assert.h>
#else
#include "internal.h"
#include "internal/bits.h"
#include "internal/hash.h"
#include "internal/sanitizers.h"
+#include "ruby_assert.h"
#endif
#include <stdio.h>
@@ -115,7 +117,6 @@
#include <stdlib.h>
#endif
#include <string.h>
-#include <assert.h>
#ifdef __GNUC__
#define PREFETCH(addr, write_p) __builtin_prefetch(addr, write_p)
@@ -177,13 +178,13 @@ static const struct st_hash_type type_strcasehash = {
#define PTR_EQUAL(tab, ptr, hash_val, key_) \
((ptr)->hash == (hash_val) && EQUAL((tab), (key_), (ptr)->key))
-/* As PRT_EQUAL only its result is returned in RES. REBUILT_P is set
+/* As PTR_EQUAL only its result is returned in RES. REBUILT_P is set
up to TRUE if the table is rebuilt during the comparison. */
#define DO_PTR_EQUAL_CHECK(tab, ptr, hash_val, key, res, rebuilt_p) \
do { \
- unsigned int _old_rebuilds_num = (tab)->rebuilds_num; \
- res = PTR_EQUAL(tab, ptr, hash_val, key); \
- rebuilt_p = _old_rebuilds_num != (tab)->rebuilds_num; \
+ unsigned int _old_rebuilds_num = (tab)->rebuilds_num; \
+ res = PTR_EQUAL(tab, ptr, hash_val, key); \
+ rebuilt_p = _old_rebuilds_num != (tab)->rebuilds_num; \
} while (FALSE)
/* Features of a table. */
@@ -313,17 +314,22 @@ static const struct st_features features[] = {
#define RESERVED_HASH_VAL (~(st_hash_t) 0)
#define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0)
-/* Return hash value of KEY for table TAB. */
static inline st_hash_t
-do_hash(st_data_t key, st_table *tab)
+normalize_hash_value(st_hash_t hash)
{
- st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
-
/* RESERVED_HASH_VAL is used for a deleted entry. Map it into
another value. Such mapping should be extremely rare. */
return hash == RESERVED_HASH_VAL ? RESERVED_HASH_SUBSTITUTION_VAL : hash;
}
+/* Return hash value of KEY for table TAB. */
+static inline st_hash_t
+do_hash(st_data_t key, st_table *tab)
+{
+ st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
+ return normalize_hash_value(hash);
+}
+
/* Power of 2 defining the minimal number of allocated entries. */
#define MINIMAL_POWER2 2
@@ -356,9 +362,9 @@ static inline st_index_t
get_bin(st_index_t *bins, int s, st_index_t n)
{
return (s == 0 ? ((unsigned char *) bins)[n]
- : s == 1 ? ((unsigned short *) bins)[n]
- : s == 2 ? ((unsigned int *) bins)[n]
- : ((st_index_t *) bins)[n]);
+ : s == 1 ? ((unsigned short *) bins)[n]
+ : s == 2 ? ((unsigned int *) bins)[n]
+ : ((st_index_t *) bins)[n]);
}
/* Set up N-th bin in array BINS of table with bins size index S to
@@ -557,7 +563,7 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
#endif
}
tab->entries = (st_table_entry *) malloc(get_allocated_entries(tab)
- * sizeof(st_table_entry));
+ * sizeof(st_table_entry));
#ifndef RUBY
if (tab->entries == NULL) {
st_free_table(tab);
@@ -569,6 +575,12 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
return tab;
}
+size_t
+st_table_size(const struct st_table *tbl)
+{
+ return tbl->num_entries;
+}
+
/* Create and return table with TYPE which can hold a minimal number
of entries (see comments for get_power2). */
st_table *
@@ -661,7 +673,7 @@ find_table_bin_ind_direct(st_table *table, st_hash_t hash_value, st_data_t key);
static st_index_t
find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
- st_data_t key, st_index_t *bin_ind);
+ st_data_t key, st_index_t *bin_ind);
#ifdef HASH_LOG
static void
@@ -696,6 +708,8 @@ count_collision(const struct st_hash_type *type)
#error "REBUILD_THRESHOLD should be >= 2"
#endif
+static void rebuild_table_with(st_table *new_tab, st_table *tab);
+
/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
and can change size of the table entries and bins arrays.
Rebuilding is implemented by creation of a new table or by
@@ -703,59 +717,72 @@ count_collision(const struct st_hash_type *type)
static void
rebuild_table(st_table *tab)
{
- st_index_t i, ni, bound;
- unsigned int size_ind;
- st_table *new_tab;
- st_table_entry *entries, *new_entries;
- st_table_entry *curr_entry_ptr;
- st_index_t *bins;
- st_index_t bin_ind;
-
- bound = tab->entries_bound;
- entries = tab->entries;
if ((2 * tab->num_entries <= get_allocated_entries(tab)
- && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
- || tab->num_entries < (1 << MINIMAL_POWER2)) {
+ && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
+ || tab->num_entries < (1 << MINIMAL_POWER2)) {
/* Compaction: */
tab->num_entries = 0;
- if (tab->bins != NULL)
- initialize_bins(tab);
- new_tab = tab;
- new_entries = entries;
+ if (tab->bins != NULL)
+ initialize_bins(tab);
+ rebuild_table_with(tab, tab);
}
else {
+ st_table *new_tab;
+ /* This allocation could trigger GC and compaction. If tab is the
+ * gen_iv_tbl, then tab could have changed in size due to objects being
+ * freed and/or moved. Do not store attributes of tab before this line. */
new_tab = st_init_table_with_size(tab->type,
- 2 * tab->num_entries - 1);
- new_entries = new_tab->entries;
+ 2 * tab->num_entries - 1);
+ rebuild_table_with(new_tab, tab);
}
+}
+
+static void
+rebuild_table_with(st_table *new_tab, st_table *tab)
+{
+ st_index_t i, ni;
+ unsigned int size_ind;
+ st_table_entry *new_entries;
+ st_table_entry *curr_entry_ptr;
+ st_index_t *bins;
+ st_index_t bin_ind;
+
+ new_entries = new_tab->entries;
+
ni = 0;
bins = new_tab->bins;
size_ind = get_size_ind(new_tab);
+ st_index_t bound = tab->entries_bound;
+ st_table_entry *entries = tab->entries;
+
for (i = tab->entries_start; i < bound; i++) {
curr_entry_ptr = &entries[i];
- PREFETCH(entries + i + 1, 0);
- if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
- continue;
- if (&new_entries[ni] != curr_entry_ptr)
- new_entries[ni] = *curr_entry_ptr;
- if (EXPECT(bins != NULL, 1)) {
- bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
- curr_entry_ptr->key);
- set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
- }
- new_tab->num_entries++;
- ni++;
+ PREFETCH(entries + i + 1, 0);
+ if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
+ continue;
+ if (&new_entries[ni] != curr_entry_ptr)
+ new_entries[ni] = *curr_entry_ptr;
+ if (EXPECT(bins != NULL, 1)) {
+ bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
+ curr_entry_ptr->key);
+ set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
+ }
+ new_tab->num_entries++;
+ ni++;
}
+
+ assert(new_tab->num_entries == tab->num_entries);
+
if (new_tab != tab) {
tab->entry_power = new_tab->entry_power;
- tab->bin_power = new_tab->bin_power;
- tab->size_ind = new_tab->size_ind;
- if (tab->bins != NULL)
- free(tab->bins);
- tab->bins = new_tab->bins;
- free(tab->entries);
- tab->entries = new_tab->entries;
- free(new_tab);
+ tab->bin_power = new_tab->bin_power;
+ tab->size_ind = new_tab->size_ind;
+ if (tab->bins != NULL)
+ free(tab->bins);
+ tab->bins = new_tab->bins;
+ free(tab->entries);
+ tab->entries = new_tab->entries;
+ free(new_tab);
}
tab->entries_start = 0;
tab->entries_bound = tab->num_entries;
@@ -796,11 +823,11 @@ find_entry(st_table *tab, st_hash_t hash_value, st_data_t key)
bound = tab->entries_bound;
entries = tab->entries;
for (i = tab->entries_start; i < bound; i++) {
- DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
- if (EXPECT(rebuilt_p, 0))
- return REBUILT_TABLE_ENTRY_IND;
- if (eq_p)
- return i;
+ DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ return i;
}
return UNDEFINED_ENTRY_IND;
}
@@ -836,17 +863,17 @@ find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
for (;;) {
bin = get_bin(tab->bins, get_size_ind(tab), ind);
if (! EMPTY_OR_DELETED_BIN_P(bin)) {
- DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
- if (EXPECT(rebuilt_p, 0))
- return REBUILT_TABLE_ENTRY_IND;
- if (eq_p)
- break;
- }
- else if (EMPTY_BIN_P(bin))
+ DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ break;
+ }
+ else if (EMPTY_BIN_P(bin))
return UNDEFINED_ENTRY_IND;
#ifdef QUADRATIC_PROBE
- ind = hash_bin(ind + d, tab);
- d++;
+ ind = hash_bin(ind + d, tab);
+ d++;
#else
ind = secondary_hash(ind, tab, &peterb);
#endif
@@ -882,17 +909,17 @@ find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
for (;;) {
bin = get_bin(tab->bins, get_size_ind(tab), ind);
if (! EMPTY_OR_DELETED_BIN_P(bin)) {
- DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
- if (EXPECT(rebuilt_p, 0))
- return REBUILT_TABLE_BIN_IND;
- if (eq_p)
- break;
- }
- else if (EMPTY_BIN_P(bin))
+ DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_BIN_IND;
+ if (eq_p)
+ break;
+ }
+ else if (EMPTY_BIN_P(bin))
return UNDEFINED_BIN_IND;
#ifdef QUADRATIC_PROBE
- ind = hash_bin(ind + d, tab);
- d++;
+ ind = hash_bin(ind + d, tab);
+ d++;
#else
ind = secondary_hash(ind, tab, &peterb);
#endif
@@ -925,10 +952,10 @@ find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
for (;;) {
bin = get_bin(tab->bins, get_size_ind(tab), ind);
if (EMPTY_OR_DELETED_BIN_P(bin))
- return ind;
+ return ind;
#ifdef QUADRATIC_PROBE
- ind = hash_bin(ind + d, tab);
- d++;
+ ind = hash_bin(ind + d, tab);
+ d++;
#else
ind = secondary_hash(ind, tab, &peterb);
#endif
@@ -947,7 +974,7 @@ find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
during the search, return REBUILT_TABLE_ENTRY_IND. */
static st_index_t
find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
- st_data_t key, st_index_t *bin_ind)
+ st_data_t key, st_index_t *bin_ind)
{
int eq_p, rebuilt_p;
st_index_t ind;
@@ -974,26 +1001,26 @@ find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
entry_index = get_bin(tab->bins, get_size_ind(tab), ind);
if (EMPTY_BIN_P(entry_index)) {
tab->num_entries++;
- entry_index = UNDEFINED_ENTRY_IND;
+ entry_index = UNDEFINED_ENTRY_IND;
if (first_deleted_bin_ind != UNDEFINED_BIN_IND) {
/* We can reuse bin of a deleted entry. */
ind = first_deleted_bin_ind;
MARK_BIN_EMPTY(tab, ind);
}
break;
- }
- else if (! DELETED_BIN_P(entry_index)) {
- DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
- if (EXPECT(rebuilt_p, 0))
- return REBUILT_TABLE_ENTRY_IND;
+ }
+ else if (! DELETED_BIN_P(entry_index)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
if (eq_p)
break;
- }
- else if (first_deleted_bin_ind == UNDEFINED_BIN_IND)
+ }
+ else if (first_deleted_bin_ind == UNDEFINED_BIN_IND)
first_deleted_bin_ind = ind;
#ifdef QUADRATIC_PROBE
- ind = hash_bin(ind + d, tab);
- d++;
+ ind = hash_bin(ind + d, tab);
+ d++;
#else
ind = secondary_hash(ind, tab, &peterb);
#endif
@@ -1014,18 +1041,18 @@ st_lookup(st_table *tab, st_data_t key, st_data_t *value)
retry:
if (tab->bins == NULL) {
bin = find_entry(tab, hash, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- if (bin == UNDEFINED_ENTRY_IND)
- return 0;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
}
else {
bin = find_table_entry_ind(tab, hash, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- if (bin == UNDEFINED_ENTRY_IND)
- return 0;
- bin -= ENTRY_BASE;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ bin -= ENTRY_BASE;
}
if (value != 0)
*value = tab->entries[bin].record;
@@ -1043,18 +1070,18 @@ st_get_key(st_table *tab, st_data_t key, st_data_t *result)
retry:
if (tab->bins == NULL) {
bin = find_entry(tab, hash, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- if (bin == UNDEFINED_ENTRY_IND)
- return 0;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
}
else {
bin = find_table_entry_ind(tab, hash, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- if (bin == UNDEFINED_ENTRY_IND)
- return 0;
- bin -= ENTRY_BASE;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ bin -= ENTRY_BASE;
}
if (result != 0)
*result = tab->entries[bin].key;
@@ -1089,29 +1116,29 @@ st_insert(st_table *tab, st_data_t key, st_data_t value)
rebuild_table_if_necessary(tab);
if (tab->bins == NULL) {
bin = find_entry(tab, hash_value, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- new_p = bin == UNDEFINED_ENTRY_IND;
- if (new_p)
- tab->num_entries++;
- bin_ind = UNDEFINED_BIN_IND;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ if (new_p)
+ tab->num_entries++;
+ bin_ind = UNDEFINED_BIN_IND;
}
else {
bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
- key, &bin_ind);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- new_p = bin == UNDEFINED_ENTRY_IND;
- bin -= ENTRY_BASE;
+ key, &bin_ind);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ bin -= ENTRY_BASE;
}
if (new_p) {
- ind = tab->entries_bound++;
+ ind = tab->entries_bound++;
entry = &tab->entries[ind];
entry->hash = hash_value;
entry->key = key;
entry->record = value;
- if (bin_ind != UNDEFINED_BIN_IND)
- set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ if (bin_ind != UNDEFINED_BIN_IND)
+ set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
return 0;
}
tab->entries[bin].record = value;
@@ -1122,12 +1149,14 @@ st_insert(st_table *tab, st_data_t key, st_data_t value)
entry with KEY before the insertion. */
static inline void
st_add_direct_with_hash(st_table *tab,
- st_data_t key, st_data_t value, st_hash_t hash)
+ st_data_t key, st_data_t value, st_hash_t hash)
{
st_table_entry *entry;
st_index_t ind;
st_index_t bin_ind;
+ assert(hash != RESERVED_HASH_VAL);
+
rebuild_table_if_necessary(tab);
ind = tab->entries_bound++;
entry = &tab->entries[ind];
@@ -1137,10 +1166,17 @@ 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);
- set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
}
}
+void
+rb_st_add_direct_with_hash(st_table *tab,
+ st_data_t key, st_data_t value, st_hash_t hash)
+{
+ st_add_direct_with_hash(tab, key, value, normalize_hash_value(hash));
+}
+
/* Insert (KEY, VALUE) into table TAB. The table should not have
entry with KEY before the insertion. */
void
@@ -1171,20 +1207,20 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value,
rebuild_table_if_necessary (tab);
if (tab->bins == NULL) {
bin = find_entry(tab, hash_value, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- new_p = bin == UNDEFINED_ENTRY_IND;
- if (new_p)
- tab->num_entries++;
- bin_ind = UNDEFINED_BIN_IND;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ if (new_p)
+ tab->num_entries++;
+ bin_ind = UNDEFINED_BIN_IND;
}
else {
bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
- key, &bin_ind);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- new_p = bin == UNDEFINED_ENTRY_IND;
- bin -= ENTRY_BASE;
+ key, &bin_ind);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ bin -= ENTRY_BASE;
}
if (new_p) {
key = (*func)(key);
@@ -1193,8 +1229,8 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value,
entry->hash = hash_value;
entry->key = key;
entry->record = value;
- if (bin_ind != UNDEFINED_BIN_IND)
- set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ if (bin_ind != UNDEFINED_BIN_IND)
+ set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
return 0;
}
tab->entries[bin].record = value;
@@ -1225,7 +1261,7 @@ st_copy(st_table *old_tab)
#endif
}
new_tab->entries = (st_table_entry *) malloc(get_allocated_entries(old_tab)
- * sizeof(st_table_entry));
+ * sizeof(st_table_entry));
#ifndef RUBY
if (new_tab->entries == NULL) {
st_free_table(new_tab);
@@ -1233,7 +1269,7 @@ st_copy(st_table *old_tab)
}
#endif
MEMCPY(new_tab->entries, old_tab->entries, st_table_entry,
- get_allocated_entries(old_tab));
+ get_allocated_entries(old_tab));
if (old_tab->bins != NULL)
MEMCPY(new_tab->bins, old_tab->bins, char, bins_size(old_tab));
return new_tab;
@@ -1271,23 +1307,23 @@ st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
retry:
if (tab->bins == NULL) {
bin = find_entry(tab, hash, *key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- if (bin == UNDEFINED_ENTRY_IND) {
- if (value != 0) *value = 0;
- return 0;
- }
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND) {
+ if (value != 0) *value = 0;
+ return 0;
+ }
}
else {
bin_ind = find_table_bin_ind(tab, hash, *key);
- if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
- goto retry;
- if (bin_ind == UNDEFINED_BIN_IND) {
- if (value != 0) *value = 0;
- return 0;
- }
- bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
- MARK_BIN_DELETED(tab, bin_ind);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto retry;
+ if (bin_ind == UNDEFINED_BIN_IND) {
+ if (value != 0) *value = 0;
+ return 0;
+ }
+ bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ MARK_BIN_DELETED(tab, bin_ind);
}
entry = &tab->entries[bin];
*key = entry->key;
@@ -1332,38 +1368,37 @@ st_shift(st_table *tab, st_data_t *key, st_data_t *value)
bound = tab->entries_bound;
for (i = tab->entries_start; i < bound; i++) {
curr_entry_ptr = &entries[i];
- if (! DELETED_ENTRY_P(curr_entry_ptr)) {
- st_hash_t entry_hash = curr_entry_ptr->hash;
- st_data_t entry_key = curr_entry_ptr->key;
-
- if (value != 0) *value = curr_entry_ptr->record;
- *key = entry_key;
- retry:
- if (tab->bins == NULL) {
- bin = find_entry(tab, entry_hash, entry_key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) {
- entries = tab->entries;
- goto retry;
- }
- curr_entry_ptr = &entries[bin];
- }
- else {
- bin_ind = find_table_bin_ind(tab, entry_hash, entry_key);
- if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) {
- entries = tab->entries;
- goto retry;
- }
- curr_entry_ptr = &entries[get_bin(tab->bins, get_size_ind(tab), bin_ind)
- - ENTRY_BASE];
- MARK_BIN_DELETED(tab, bin_ind);
- }
- MARK_ENTRY_DELETED(curr_entry_ptr);
- tab->num_entries--;
- update_range_for_deleted(tab, i);
- return 1;
- }
+ if (! DELETED_ENTRY_P(curr_entry_ptr)) {
+ st_hash_t entry_hash = curr_entry_ptr->hash;
+ st_data_t entry_key = curr_entry_ptr->key;
+
+ if (value != 0) *value = curr_entry_ptr->record;
+ *key = entry_key;
+ retry:
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, entry_hash, entry_key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) {
+ entries = tab->entries;
+ goto retry;
+ }
+ curr_entry_ptr = &entries[bin];
+ }
+ else {
+ bin_ind = find_table_bin_ind(tab, entry_hash, entry_key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) {
+ entries = tab->entries;
+ goto retry;
+ }
+ curr_entry_ptr = &entries[get_bin(tab->bins, get_size_ind(tab), bin_ind)
+ - ENTRY_BASE];
+ MARK_BIN_DELETED(tab, bin_ind);
+ }
+ MARK_ENTRY_DELETED(curr_entry_ptr);
+ tab->num_entries--;
+ update_range_for_deleted(tab, i);
+ return 1;
+ }
}
- tab->entries_start = tab->entries_bound = 0;
if (value != 0) *value = 0;
return 0;
}
@@ -1386,7 +1421,7 @@ st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED,
the table before the call. */
int
st_update(st_table *tab, st_data_t key,
- st_update_callback_func *func, st_data_t arg)
+ st_update_callback_func *func, st_data_t arg)
{
st_table_entry *entry = NULL; /* to avoid uninitialized value warning */
st_index_t bin = 0; /* Ditto */
@@ -1400,21 +1435,21 @@ st_update(st_table *tab, st_data_t key,
entries = tab->entries;
if (tab->bins == NULL) {
bin = find_entry(tab, hash, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- existing = bin != UNDEFINED_ENTRY_IND;
- entry = &entries[bin];
- bin_ind = UNDEFINED_BIN_IND;
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ existing = bin != UNDEFINED_ENTRY_IND;
+ entry = &entries[bin];
+ bin_ind = UNDEFINED_BIN_IND;
}
else {
bin_ind = find_table_bin_ind(tab, hash, key);
- if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
- goto retry;
- existing = bin_ind != UNDEFINED_BIN_IND;
- if (existing) {
- bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
- entry = &entries[bin];
- }
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto retry;
+ existing = bin_ind != UNDEFINED_BIN_IND;
+ if (existing) {
+ bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ entry = &entries[bin];
+ }
}
if (existing) {
key = entry->key;
@@ -1425,7 +1460,7 @@ st_update(st_table *tab, st_data_t key,
switch (retval) {
case ST_CONTINUE:
if (! existing) {
- st_add_direct_with_hash(tab, key, value, hash);
+ st_add_direct_with_hash(tab, key, value, hash);
break;
}
if (old_key != key) {
@@ -1435,11 +1470,11 @@ st_update(st_table *tab, st_data_t key,
break;
case ST_DELETE:
if (existing) {
- if (bin_ind != UNDEFINED_BIN_IND)
- MARK_BIN_DELETED(tab, bin_ind);
+ if (bin_ind != UNDEFINED_BIN_IND)
+ MARK_BIN_DELETED(tab, bin_ind);
MARK_ENTRY_DELETED(entry);
- tab->num_entries--;
- update_range_for_deleted(tab, bin);
+ tab->num_entries--;
+ update_range_for_deleted(tab, bin);
}
break;
}
@@ -1456,7 +1491,7 @@ st_update(st_table *tab, st_data_t key,
during traversing. */
static inline int
st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg,
- int check_p)
+ int check_p)
{
st_index_t bin;
st_index_t bin_ind;
@@ -1472,12 +1507,12 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat
the table, e.g. by an entry insertion. */
for (i = tab->entries_start; i < tab->entries_bound; i++) {
curr_entry_ptr = &entries[i];
- if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
- continue;
- key = curr_entry_ptr->key;
- rebuilds_num = tab->rebuilds_num;
- hash = curr_entry_ptr->hash;
- retval = (*func)(key, curr_entry_ptr->record, arg, 0);
+ if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
+ continue;
+ key = curr_entry_ptr->key;
+ rebuilds_num = tab->rebuilds_num;
+ hash = curr_entry_ptr->hash;
+ retval = (*func)(key, curr_entry_ptr->record, arg, 0);
if (retval == ST_REPLACE && replace) {
st_data_t value;
@@ -1487,44 +1522,44 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat
curr_entry_ptr->record = value;
}
- if (rebuilds_num != tab->rebuilds_num) {
- retry:
- entries = tab->entries;
- packed_p = tab->bins == NULL;
- if (packed_p) {
- i = find_entry(tab, hash, key);
- if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- error_p = i == UNDEFINED_ENTRY_IND;
- }
- else {
- i = find_table_entry_ind(tab, hash, key);
- if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
- goto retry;
- error_p = i == UNDEFINED_ENTRY_IND;
- i -= ENTRY_BASE;
- }
- if (error_p && check_p) {
- /* call func with error notice */
- retval = (*func)(0, 0, arg, 1);
- return 1;
- }
- curr_entry_ptr = &entries[i];
- }
- switch (retval) {
+ if (rebuilds_num != tab->rebuilds_num) {
+ retry:
+ entries = tab->entries;
+ packed_p = tab->bins == NULL;
+ if (packed_p) {
+ i = find_entry(tab, hash, key);
+ if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ error_p = i == UNDEFINED_ENTRY_IND;
+ }
+ else {
+ i = find_table_entry_ind(tab, hash, key);
+ if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ error_p = i == UNDEFINED_ENTRY_IND;
+ i -= ENTRY_BASE;
+ }
+ if (error_p && check_p) {
+ /* call func with error notice */
+ retval = (*func)(0, 0, arg, 1);
+ return 1;
+ }
+ curr_entry_ptr = &entries[i];
+ }
+ switch (retval) {
case ST_REPLACE:
break;
- case ST_CONTINUE:
+ case ST_CONTINUE:
break;
- case ST_CHECK:
+ case ST_CHECK:
if (check_p)
break;
- case ST_STOP:
+ case ST_STOP:
return 0;
- case ST_DELETE: {
+ case ST_DELETE: {
st_data_t key = curr_entry_ptr->key;
- again:
+ again:
if (packed_p) {
bin = find_entry(tab, hash, key);
if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
@@ -1546,8 +1581,8 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat
tab->num_entries--;
update_range_for_deleted(tab, bin);
break;
- }
- }
+ }
+ }
}
return 0;
}
@@ -1598,12 +1633,12 @@ st_general_keys(st_table *tab, st_data_t *keys, st_index_t size)
keys_start = keys;
keys_end = keys + size;
for (i = tab->entries_start; i < bound; i++) {
- if (keys == keys_end)
- break;
- curr_entry_ptr = &entries[i];
- key = curr_entry_ptr->key;
+ if (keys == keys_end)
+ break;
+ curr_entry_ptr = &entries[i];
+ key = curr_entry_ptr->key;
if (! DELETED_ENTRY_P(curr_entry_ptr))
- *keys++ = key;
+ *keys++ = key;
}
return keys - keys_start;
@@ -1636,11 +1671,11 @@ st_general_values(st_table *tab, st_data_t *values, st_index_t size)
values_end = values + size;
bound = tab->entries_bound;
for (i = tab->entries_start; i < bound; i++) {
- if (values == values_end)
- break;
+ if (values == values_end)
+ break;
curr_entry_ptr = &entries[i];
if (! DELETED_ENTRY_P(curr_entry_ptr))
- *values++ = curr_entry_ptr->record;
+ *values++ = curr_entry_ptr->record;
}
return values - values_start;
@@ -1655,7 +1690,7 @@ st_values(st_table *tab, st_data_t *values, st_index_t size)
/* See comments for function st_delete_safe. */
st_index_t
st_values_check(st_table *tab, st_data_t *values, st_index_t size,
- st_data_t never ATTRIBUTE_UNUSED)
+ st_data_t never ATTRIBUTE_UNUSED)
{
return st_general_values(tab, values, size);
}
@@ -1667,10 +1702,11 @@ st_values_check(st_table *tab, st_data_t *values, st_index_t size,
*/
#define FNV_32_PRIME 0x01000193
+/* __POWERPC__ added to accommodate Darwin case. */
#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(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
defined(__mc68020__)
# define UNALIGNED_WORD_ACCESS 1
# endif
@@ -1771,87 +1807,87 @@ st_hash(const void *ptr, size_t len, st_index_t h)
#undef SKIP_TAIL
if (len >= sizeof(st_index_t)) {
#if !UNALIGNED_WORD_ACCESS
- int align = (int)((st_data_t)data % sizeof(st_index_t));
- if (align) {
- st_index_t d = 0;
- int sl, sr, pack;
+ int align = (int)((st_data_t)data % sizeof(st_index_t));
+ if (align) {
+ st_index_t d = 0;
+ int sl, sr, pack;
- switch (align) {
+ switch (align) {
#ifdef WORDS_BIGENDIAN
# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
- t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2)
+ t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2)
#else
# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
- t |= data_at(n) << CHAR_BIT*(n)
+ t |= data_at(n) << CHAR_BIT*(n)
#endif
- UNALIGNED_ADD_ALL;
+ UNALIGNED_ADD_ALL;
#undef UNALIGNED_ADD
- }
+ }
#ifdef WORDS_BIGENDIAN
- t >>= (CHAR_BIT * align) - CHAR_BIT;
+ t >>= (CHAR_BIT * align) - CHAR_BIT;
#else
- t <<= (CHAR_BIT * align);
+ t <<= (CHAR_BIT * align);
#endif
- data += sizeof(st_index_t)-align;
- len -= sizeof(st_index_t)-align;
+ data += sizeof(st_index_t)-align;
+ len -= sizeof(st_index_t)-align;
- sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align);
- sr = CHAR_BIT * align;
+ sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align);
+ sr = CHAR_BIT * align;
- while (len >= sizeof(st_index_t)) {
- d = *(st_index_t *)data;
+ while (len >= sizeof(st_index_t)) {
+ d = *(st_index_t *)data;
#ifdef WORDS_BIGENDIAN
- t = (t << sr) | (d >> sl);
+ t = (t << sr) | (d >> sl);
#else
- t = (t >> sr) | (d << sl);
+ t = (t >> sr) | (d << sl);
#endif
- h = murmur_step(h, t);
- t = d;
- data += sizeof(st_index_t);
- len -= sizeof(st_index_t);
- }
-
- pack = len < (size_t)align ? (int)len : align;
- d = 0;
- switch (pack) {
+ h = murmur_step(h, t);
+ t = d;
+ data += sizeof(st_index_t);
+ len -= sizeof(st_index_t);
+ }
+
+ pack = len < (size_t)align ? (int)len : align;
+ d = 0;
+ switch (pack) {
#ifdef WORDS_BIGENDIAN
# define UNALIGNED_ADD(n) case (n) + 1: \
- d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
+ d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
#else
# define UNALIGNED_ADD(n) case (n) + 1: \
- d |= data_at(n) << CHAR_BIT*(n)
+ d |= data_at(n) << CHAR_BIT*(n)
#endif
- UNALIGNED_ADD_ALL;
+ UNALIGNED_ADD_ALL;
#undef UNALIGNED_ADD
- }
+ }
#ifdef WORDS_BIGENDIAN
- t = (t << sr) | (d >> sl);
+ t = (t << sr) | (d >> sl);
#else
- t = (t >> sr) | (d << sl);
+ t = (t >> sr) | (d << sl);
#endif
- if (len < (size_t)align) goto skip_tail;
+ if (len < (size_t)align) goto skip_tail;
# define SKIP_TAIL 1
- h = murmur_step(h, t);
- data += pack;
- len -= pack;
- }
- else
+ h = murmur_step(h, t);
+ data += pack;
+ len -= pack;
+ }
+ else
#endif
#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
#define aligned_data __builtin_assume_aligned(data, sizeof(st_index_t))
#else
#define aligned_data data
#endif
- {
- do {
- h = murmur_step(h, *(st_index_t *)aligned_data);
- data += sizeof(st_index_t);
- len -= sizeof(st_index_t);
- } while (len >= sizeof(st_index_t));
- }
+ {
+ do {
+ h = murmur_step(h, *(st_index_t *)aligned_data);
+ data += sizeof(st_index_t);
+ len -= sizeof(st_index_t);
+ } while (len >= sizeof(st_index_t));
+ }
}
t = 0;
@@ -1863,8 +1899,8 @@ st_hash(const void *ptr, size_t len, st_index_t h)
case 6: t |= data_at(5) << 40;
case 5: t |= data_at(4) << 32;
case 4:
- t |= (st_index_t)*(uint32_t*)aligned_data;
- goto skip_tail;
+ t |= (st_index_t)*(uint32_t*)aligned_data;
+ goto skip_tail;
# define SKIP_TAIL 1
#endif
case 3: t |= data_at(2) << 16;
@@ -1873,19 +1909,19 @@ st_hash(const void *ptr, size_t len, st_index_t h)
#else
#ifdef WORDS_BIGENDIAN
# define UNALIGNED_ADD(n) case (n) + 1: \
- t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
+ t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
#else
# define UNALIGNED_ADD(n) case (n) + 1: \
- t |= data_at(n) << CHAR_BIT*(n)
+ t |= data_at(n) << CHAR_BIT*(n)
#endif
- UNALIGNED_ADD_ALL;
+ UNALIGNED_ADD_ALL;
#undef UNALIGNED_ADD
#endif
#ifdef SKIP_TAIL
skip_tail:
#endif
- h ^= t; h -= ROTL(t, 7);
- h *= C2;
+ h ^= t; h -= ROTL(t, 7);
+ h *= C2;
}
h ^= l;
#undef aligned_data
@@ -2011,12 +2047,12 @@ strcasehash(st_data_t arg)
* FNV-1a hash each octet in the buffer
*/
while (*string) {
- unsigned int c = (unsigned char)*string++;
- if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
- hval ^= c;
+ unsigned int c = (unsigned char)*string++;
+ if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
+ hval ^= c;
- /* multiply by the 32 bit FNV magic prime mod 2^32 */
- hval *= FNV_32_PRIME;
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+ hval *= FNV_32_PRIME;
}
return hval;
}
@@ -2083,10 +2119,10 @@ st_rehash_linear(st_table *tab)
q = &tab->entries[j];
if (DELETED_ENTRY_P(q))
continue;
- DO_PTR_EQUAL_CHECK(tab, p, q->hash, q->key, eq_p, rebuilt_p);
- if (EXPECT(rebuilt_p, 0))
- return TRUE;
- if (eq_p) {
+ DO_PTR_EQUAL_CHECK(tab, p, q->hash, q->key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return TRUE;
+ if (eq_p) {
*p = *q;
MARK_ENTRY_DELETED(q);
tab->num_entries--;
@@ -2131,27 +2167,27 @@ st_rehash_indexed(st_table *tab)
}
else {
st_table_entry *q = &tab->entries[bin - ENTRY_BASE];
- DO_PTR_EQUAL_CHECK(tab, q, p->hash, p->key, eq_p, rebuilt_p);
- if (EXPECT(rebuilt_p, 0))
- return TRUE;
- if (eq_p) {
- /* duplicated key; delete it */
- q->record = p->record;
- MARK_ENTRY_DELETED(p);
- tab->num_entries--;
- update_range_for_deleted(tab, bin);
- break;
- }
- else {
- /* hash collision; skip it */
+ DO_PTR_EQUAL_CHECK(tab, q, p->hash, p->key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return TRUE;
+ if (eq_p) {
+ /* duplicated key; delete it */
+ q->record = p->record;
+ MARK_ENTRY_DELETED(p);
+ tab->num_entries--;
+ update_range_for_deleted(tab, bin);
+ break;
+ }
+ else {
+ /* hash collision; skip it */
#ifdef QUADRATIC_PROBE
- ind = hash_bin(ind + d, tab);
- d++;
+ ind = hash_bin(ind + d, tab);
+ d++;
#else
- ind = secondary_hash(ind, tab, &peterb);
+ ind = secondary_hash(ind, tab, &peterb);
#endif
- }
- }
+ }
+ }
}
}
return FALSE;
@@ -2166,10 +2202,10 @@ st_rehash(st_table *tab)
int rebuilt_p;
do {
- if (tab->bin_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
- rebuilt_p = st_rehash_linear(tab);
- else
- rebuilt_p = st_rehash_indexed(tab);
+ if (tab->bin_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
+ rebuilt_p = st_rehash_linear(tab);
+ else
+ rebuilt_p = st_rehash_indexed(tab);
} while (rebuilt_p);
}
@@ -2261,4 +2297,15 @@ rb_st_nth_key(st_table *tab, st_index_t index)
}
}
+void
+rb_st_compact_table(st_table *tab)
+{
+ st_index_t num = tab->num_entries;
+ if (REBUILD_THRESHOLD * num <= get_allocated_entries(tab)) {
+ /* Compaction: */
+ st_table *new_tab = st_init_table_with_size(tab->type, 2 * num);
+ rebuild_table_with(new_tab, tab);
+ }
+}
+
#endif
diff --git a/strftime.c b/strftime.c
index 17cfed1dda..33e7d3fdb8 100644
--- a/strftime.c
+++ b/strftime.c
@@ -66,11 +66,12 @@
#include <math.h>
#include "internal.h"
+#include "internal/encoding.h"
#include "internal/string.h"
-#include "internal/util.h"
#include "internal/vm.h"
#include "ruby/encoding.h"
#include "ruby/ruby.h"
+#include "ruby/util.h"
#include "timev.h"
/* defaults: season to taste */
@@ -219,7 +220,7 @@ case_conv(char *s, ptrdiff_t i, int flags)
static VALUE
format_value(VALUE val, int base)
{
- if (!RB_TYPE_P(val, T_BIGNUM))
+ if (!RB_BIGNUM_TYPE_P(val))
val = rb_Integer(val);
return rb_big2str(val, base);
}
@@ -270,9 +271,9 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
}
if (enc &&
- (enc == rb_usascii_encoding() ||
- enc == rb_ascii8bit_encoding() ||
- enc == rb_locale_encoding())) {
+ (rb_is_usascii_enc(enc) ||
+ rb_is_ascii8bit_enc(enc) ||
+ rb_is_locale_enc(enc))) {
enc = NULL;
}
diff --git a/string.c b/string.c
index 8efe1174fb..441e09bc24 100644
--- a/string.c
+++ b/string.c
@@ -45,6 +45,7 @@
#include "ruby/util.h"
#include "ruby_assert.h"
#include "vm_sync.h"
+#include "ruby/internal/attr/nonstring.h"
#if defined HAVE_CRYPT_R
# if defined HAVE_CRYPT_H
@@ -63,7 +64,6 @@
#undef rb_utf8_str_new
#undef rb_enc_str_new
#undef rb_str_new_cstr
-#undef rb_tainted_str_new_cstr
#undef rb_usascii_str_new_cstr
#undef rb_utf8_str_new_cstr
#undef rb_enc_str_new_cstr
@@ -89,12 +89,16 @@ VALUE rb_cSymbol;
* other strings that rely on this string's buffer)
* 6: STR_BORROWED (when RSTRING_NOEMBED==1 && klass==0, unsafe to recycle
* early, specific to rb_str_tmp_frozen_{acquire,release})
- * 7: STR_TMPLOCK
+ * 7: STR_TMPLOCK (set when a pointer to the buffer is passed to syscall
+ * such as read(2). Any modification and realloc is prohibited)
+ *
* 8-9: ENC_CODERANGE (2 bits)
* 10-16: ENCODING (7 bits == 128)
* 17: RSTRING_FSTR
- * 18: STR_NOFREE
- * 19: STR_FAKESTR
+ * 18: STR_NOFREE (do not free this string's buffer when a String is freed.
+ * used for a string object based on C string literal)
+ * 19: STR_FAKESTR (when RVALUE is not managed by GC. Typically, the string
+ * object header is temporarily allocated on C stack)
*/
#define RUBY_MAX_CHAR_LEN 16
@@ -106,42 +110,68 @@ VALUE rb_cSymbol;
#define STR_SET_NOEMBED(str) do {\
FL_SET((str), STR_NOEMBED);\
- STR_SET_EMBED_LEN((str), 0);\
+ if (USE_RVARGC) {\
+ FL_UNSET((str), STR_SHARED | STR_SHARED_ROOT | STR_BORROWED);\
+ }\
+ else {\
+ STR_SET_EMBED_LEN((str), 0);\
+ }\
} while (0)
#define STR_SET_EMBED(str) FL_UNSET((str), (STR_NOEMBED|STR_NOFREE))
-#define STR_SET_EMBED_LEN(str, n) do { \
+#if USE_RVARGC
+# define STR_SET_EMBED_LEN(str, n) do { \
+ assert(str_embed_capa(str) > (n));\
+ RSTRING(str)->as.embed.len = (n);\
+} while (0)
+#else
+# define STR_SET_EMBED_LEN(str, n) do { \
long tmp_n = (n);\
RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\
RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\
} while (0)
+#endif
#define STR_SET_LEN(str, n) do { \
if (STR_EMBED_P(str)) {\
- STR_SET_EMBED_LEN((str), (n));\
+ STR_SET_EMBED_LEN((str), (n));\
}\
else {\
- RSTRING(str)->as.heap.len = (n);\
+ RSTRING(str)->as.heap.len = (n);\
}\
} while (0)
#define STR_DEC_LEN(str) do {\
if (STR_EMBED_P(str)) {\
- long n = RSTRING_LEN(str);\
- n--;\
- STR_SET_EMBED_LEN((str), n);\
+ long n = RSTRING_LEN(str);\
+ n--;\
+ STR_SET_EMBED_LEN((str), n);\
}\
else {\
- RSTRING(str)->as.heap.len--;\
+ RSTRING(str)->as.heap.len--;\
}\
} while (0)
-#define TERM_LEN(str) rb_enc_mbminlen(rb_enc_get(str))
+static inline bool
+str_enc_fastpath(VALUE str)
+{
+ // The overwhelming majority of strings are in one of these 3 encodings.
+ switch (ENCODING_GET_INLINED(str)) {
+ case ENCINDEX_ASCII_8BIT:
+ case ENCINDEX_UTF_8:
+ case ENCINDEX_US_ASCII:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#define TERM_LEN(str) (str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
#define TERM_FILL(ptr, termlen) do {\
char *const term_fill_ptr = (ptr);\
const int term_fill_len = (termlen);\
*term_fill_ptr = '\0';\
if (UNLIKELY(term_fill_len > 1))\
- memset(term_fill_ptr, 0, term_fill_len);\
+ memset(term_fill_ptr, 0, term_fill_len);\
} while (0)
#define RESIZE_CAPA(str,capacity) do {\
@@ -150,31 +180,33 @@ VALUE rb_cSymbol;
} while (0)
#define RESIZE_CAPA_TERM(str,capacity,termlen) do {\
if (STR_EMBED_P(str)) {\
- if (!STR_EMBEDDABLE_P(capacity, termlen)) {\
- char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\
- const long tlen = RSTRING_LEN(str);\
- memcpy(tmp, RSTRING_PTR(str), tlen);\
- RSTRING(str)->as.heap.ptr = tmp;\
- RSTRING(str)->as.heap.len = tlen;\
+ if (str_embed_capa(str) < capacity + termlen) {\
+ char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\
+ const long tlen = RSTRING_LEN(str);\
+ memcpy(tmp, RSTRING_PTR(str), tlen);\
+ RSTRING(str)->as.heap.ptr = tmp;\
+ RSTRING(str)->as.heap.len = tlen;\
STR_SET_NOEMBED(str);\
- RSTRING(str)->as.heap.aux.capa = (capacity);\
- }\
+ RSTRING(str)->as.heap.aux.capa = (capacity);\
+ }\
}\
else {\
- assert(!FL_TEST((str), STR_SHARED)); \
- SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char, \
- (size_t)(capacity) + (termlen), STR_HEAP_SIZE(str)); \
- RSTRING(str)->as.heap.aux.capa = (capacity);\
+ assert(!FL_TEST((str), STR_SHARED)); \
+ SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char, \
+ (size_t)(capacity) + (termlen), STR_HEAP_SIZE(str)); \
+ RSTRING(str)->as.heap.aux.capa = (capacity);\
}\
} while (0)
#define STR_SET_SHARED(str, shared_str) do { \
if (!FL_TEST(str, STR_FAKESTR)) { \
- RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
- FL_SET((str), STR_SHARED); \
+ assert(RSTRING_PTR(shared_str) <= RSTRING_PTR(str)); \
+ assert(RSTRING_PTR(str) <= RSTRING_PTR(shared_str) + RSTRING_LEN(shared_str)); \
+ RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
+ FL_SET((str), STR_SHARED); \
FL_SET((shared_str), STR_SHARED_ROOT); \
- if (RBASIC_CLASS((shared_str)) == 0) /* for CoW-friendliness */ \
- FL_SET_RAW((shared_str), STR_BORROWED); \
+ if (RBASIC_CLASS((shared_str)) == 0) /* for CoW-friendliness */ \
+ FL_SET_RAW((shared_str), STR_BORROWED); \
} \
} while (0)
@@ -193,8 +225,60 @@ VALUE rb_cSymbol;
#define SHARABLE_SUBSTRING_P(beg, len, end) 1
#endif
-#define STR_EMBEDDABLE_P(len, termlen) \
- ((len) <= RSTRING_EMBED_LEN_MAX + 1 - (termlen))
+
+static inline long
+str_embed_capa(VALUE str)
+{
+#if USE_RVARGC
+ return rb_gc_obj_slot_size(str) - offsetof(struct RString, as.embed.ary);
+#else
+ return RSTRING_EMBED_LEN_MAX + 1;
+#endif
+}
+
+bool
+rb_str_reembeddable_p(VALUE str)
+{
+ return !FL_TEST(str, STR_NOFREE|STR_SHARED_ROOT|STR_SHARED);
+}
+
+static inline size_t
+rb_str_embed_size(long capa)
+{
+ return offsetof(struct RString, as.embed.ary) + capa;
+}
+
+size_t
+rb_str_size_as_embedded(VALUE str)
+{
+ size_t real_size;
+#if USE_RVARGC
+ if (STR_EMBED_P(str)) {
+ real_size = rb_str_embed_size(RSTRING(str)->as.embed.len) + TERM_LEN(str);
+ }
+ /* if the string is not currently embedded, but it can be embedded, how
+ * much space would it require */
+ else if (rb_str_reembeddable_p(str)) {
+ real_size = rb_str_embed_size(RSTRING(str)->as.heap.aux.capa) + TERM_LEN(str);
+ }
+ else {
+#endif
+ real_size = sizeof(struct RString);
+#if USE_RVARGC
+ }
+#endif
+ return real_size;
+}
+
+static inline bool
+STR_EMBEDDABLE_P(long len, long termlen)
+{
+#if USE_RVARGC
+ return rb_gc_size_allocatable_p(rb_str_embed_size(len + termlen));
+#else
+ return len <= RSTRING_EMBED_LEN_MAX + 1 - termlen;
+#endif
+}
static VALUE str_replace_shared_without_enc(VALUE str2, VALUE str);
static VALUE str_new_frozen(VALUE klass, VALUE orig);
@@ -223,50 +307,70 @@ rb_str_make_independent(VALUE str)
}
}
-/* symbols for [up|down|swap]case/capitalize options */
-static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
+void
+rb_str_make_embedded(VALUE str)
+{
+ RUBY_ASSERT(rb_str_reembeddable_p(str));
+ RUBY_ASSERT(!STR_EMBED_P(str));
-static rb_encoding *
-get_actual_encoding(const int encidx, VALUE str)
+ char *buf = RSTRING(str)->as.heap.ptr;
+ long len = RSTRING(str)->as.heap.len;
+
+ STR_SET_EMBED(str);
+ STR_SET_EMBED_LEN(str, len);
+
+ if (len > 0) {
+ memcpy(RSTRING_PTR(str), buf, len);
+ ruby_xfree(buf);
+ }
+
+ TERM_FILL(RSTRING(str)->as.embed.ary + len, TERM_LEN(str));
+}
+
+void
+rb_str_update_shared_ary(VALUE str, VALUE old_root, VALUE new_root)
{
- const unsigned char *q;
+ // if the root location hasn't changed, we don't need to update
+ if (new_root == old_root) {
+ return;
+ }
- switch (encidx) {
- case ENCINDEX_UTF_16:
- if (RSTRING_LEN(str) < 2) break;
- q = (const unsigned char *)RSTRING_PTR(str);
- if (q[0] == 0xFE && q[1] == 0xFF) {
- return rb_enc_get_from_index(ENCINDEX_UTF_16BE);
- }
- if (q[0] == 0xFF && q[1] == 0xFE) {
- return rb_enc_get_from_index(ENCINDEX_UTF_16LE);
- }
- return rb_ascii8bit_encoding();
- case ENCINDEX_UTF_32:
- if (RSTRING_LEN(str) < 4) break;
- q = (const unsigned char *)RSTRING_PTR(str);
- if (q[0] == 0 && q[1] == 0 && q[2] == 0xFE && q[3] == 0xFF) {
- return rb_enc_get_from_index(ENCINDEX_UTF_32BE);
- }
- if (q[3] == 0 && q[2] == 0 && q[1] == 0xFE && q[0] == 0xFF) {
- return rb_enc_get_from_index(ENCINDEX_UTF_32LE);
- }
- return rb_ascii8bit_encoding();
- }
- return rb_enc_from_index(encidx);
+ // if the root string isn't embedded, we don't need to touch the ponter.
+ // it already points to the shame shared buffer
+ if (!STR_EMBED_P(new_root)) {
+ return;
+ }
+
+ size_t offset = (size_t)((uintptr_t)RSTRING(str)->as.heap.ptr - (uintptr_t)RSTRING(old_root)->as.embed.ary);
+
+ RUBY_ASSERT(RSTRING(str)->as.heap.ptr >= RSTRING(old_root)->as.embed.ary);
+ RSTRING(str)->as.heap.ptr = RSTRING(new_root)->as.embed.ary + offset;
+}
+
+void
+rb_debug_rstring_null_ptr(const char *func)
+{
+ fprintf(stderr, "%s is returning NULL!! "
+ "SIGSEGV is highly expected to follow immediately.\n"
+ "If you could reproduce, attach your debugger here, "
+ "and look at the passed string.\n",
+ func);
}
+/* symbols for [up|down|swap]case/capitalize options */
+static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
+
static rb_encoding *
get_encoding(VALUE str)
{
- return get_actual_encoding(ENCODING_GET(str), str);
+ return rb_enc_from_index(ENCODING_GET(str));
}
static void
mustnot_broken(VALUE str)
{
if (is_broken_string(str)) {
- rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
}
}
@@ -275,7 +379,7 @@ mustnot_wchar(VALUE str)
{
rb_encoding *enc = STR_ENC_GET(str);
if (rb_enc_mbminlen(enc) > 1) {
- rb_raise(rb_eArgError, "wide char encoding: %s", rb_enc_name(enc));
+ rb_raise(rb_eArgError, "wide char encoding: %s", rb_enc_name(enc));
}
}
@@ -303,47 +407,47 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist
VALUE str = (VALUE)*key;
if (existing) {
- /* because of lazy sweep, str may be unmarked already and swept
- * at next time */
+ /* because of lazy sweep, str may be unmarked already and swept
+ * at next time */
- if (rb_objspace_garbage_object_p(str)) {
- arg->fstr = Qundef;
- return ST_DELETE;
- }
+ if (rb_objspace_garbage_object_p(str)) {
+ arg->fstr = Qundef;
+ return ST_DELETE;
+ }
- arg->fstr = str;
- return ST_STOP;
+ arg->fstr = str;
+ return ST_STOP;
}
else {
- if (FL_TEST_RAW(str, STR_FAKESTR)) {
- 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 {
- if (!OBJ_FROZEN(str))
- str = str_new_frozen(rb_cString, str);
- if (STR_SHARED_P(str)) { /* str should not be shared */
- /* shared substring */
+ if (FL_TEST_RAW(str, STR_FAKESTR)) {
+ 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 {
+ 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);
- assert(OBJ_FROZEN(str));
- }
- if (!BARE_STRING_P(str)) {
- str = str_new_frozen(rb_cString, str);
- }
- }
- RBASIC(str)->flags |= RSTRING_FSTR;
+ assert(OBJ_FROZEN(str));
+ }
+ if (!BARE_STRING_P(str)) {
+ str = str_new_frozen(rb_cString, str);
+ }
+ }
+ RBASIC(str)->flags |= RSTRING_FSTR;
- *key = *value = arg->fstr = str;
- return ST_CONTINUE;
+ *key = *value = arg->fstr = str;
+ return ST_CONTINUE;
}
}
@@ -357,7 +461,7 @@ rb_fstring(VALUE str)
Check_Type(str, T_STRING);
if (FL_TEST(str, RSTRING_FSTR))
- return str;
+ return str;
bare = BARE_STRING_P(str);
if (!bare) {
@@ -377,9 +481,9 @@ rb_fstring(VALUE str)
fstr = register_fstring(str, FALSE);
if (!bare) {
- str_replace_shared_without_enc(str, fstr);
- OBJ_FREEZE_RAW(str);
- return str;
+ str_replace_shared_without_enc(str, fstr);
+ OBJ_FREEZE_RAW(str);
+ return str;
}
return fstr;
}
@@ -396,7 +500,7 @@ register_fstring(VALUE str, bool copy)
do {
args.fstr = str;
st_update(frozen_strings, (st_data_t)str, fstr_update_callback, (st_data_t)&args);
- } while (args.fstr == Qundef);
+ } while (UNDEF_P(args.fstr));
}
RB_VM_LOCK_LEAVE();
@@ -413,6 +517,11 @@ setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx)
fake_str->basic.flags = T_STRING|RSTRING_NOEMBED|STR_NOFREE|STR_FAKESTR;
/* SHARED to be allocated by the callback */
+ if (!name) {
+ RUBY_ASSERT_ALWAYS(len == 0);
+ name = "";
+ }
+
ENCODING_SET_INLINED((VALUE)fake_str, encidx);
RBASIC_SET_CLASS_RAW((VALUE)fake_str, rb_cString);
@@ -471,8 +580,8 @@ fstring_cmp(VALUE a, VALUE b)
RSTRING_GETMEM(a, aptr, alen);
RSTRING_GETMEM(b, bptr, blen);
return (alen != blen ||
- ENCODING_GET(a) != ENCODING_GET(b) ||
- memcmp(aptr, bptr, alen) != 0);
+ ENCODING_GET(a) != ENCODING_GET(b) ||
+ memcmp(aptr, bptr, alen) != 0);
}
static inline int
@@ -520,23 +629,23 @@ search_nonascii(const char *p, const char *e)
if (UNALIGNED_WORD_ACCESS || e - p >= SIZEOF_VOIDP) {
#if !UNALIGNED_WORD_ACCESS
- if ((uintptr_t)p % SIZEOF_VOIDP) {
- int l = SIZEOF_VOIDP - (uintptr_t)p % SIZEOF_VOIDP;
- p += l;
- switch (l) {
- default: UNREACHABLE;
+ if ((uintptr_t)p % SIZEOF_VOIDP) {
+ int l = SIZEOF_VOIDP - (uintptr_t)p % SIZEOF_VOIDP;
+ p += l;
+ switch (l) {
+ default: UNREACHABLE;
#if SIZEOF_VOIDP > 4
- case 7: if (p[-7]&0x80) return p-7;
- case 6: if (p[-6]&0x80) return p-6;
- case 5: if (p[-5]&0x80) return p-5;
- case 4: if (p[-4]&0x80) return p-4;
+ case 7: if (p[-7]&0x80) return p-7;
+ case 6: if (p[-6]&0x80) return p-6;
+ case 5: if (p[-5]&0x80) return p-5;
+ case 4: if (p[-4]&0x80) return p-4;
#endif
- case 3: if (p[-3]&0x80) return p-3;
- case 2: if (p[-2]&0x80) return p-2;
- case 1: if (p[-1]&0x80) return p-1;
- case 0: break;
- }
- }
+ case 3: if (p[-3]&0x80) return p-3;
+ case 2: if (p[-2]&0x80) return p-2;
+ case 1: if (p[-1]&0x80) return p-1;
+ case 0: break;
+ }
+ }
#endif
#if defined(HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED) &&! UNALIGNED_WORD_ACCESS
#define aligned_ptr(value) \
@@ -544,19 +653,19 @@ search_nonascii(const char *p, const char *e)
#else
#define aligned_ptr(value) (uintptr_t *)(value)
#endif
- s = aligned_ptr(p);
- t = (uintptr_t *)(e - (SIZEOF_VOIDP-1));
+ s = aligned_ptr(p);
+ t = (uintptr_t *)(e - (SIZEOF_VOIDP-1));
#undef aligned_ptr
- for (;s < t; s++) {
- if (*s & NONASCII_MASK) {
+ for (;s < t; s++) {
+ if (*s & NONASCII_MASK) {
#ifdef WORDS_BIGENDIAN
- return (const char *)s + (nlz_intptr(*s&NONASCII_MASK)>>3);
+ return (const char *)s + (nlz_intptr(*s&NONASCII_MASK)>>3);
#else
- return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3);
+ return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3);
#endif
- }
- }
- p = (const char *)s;
+ }
+ }
+ p = (const char *)s;
}
switch (e - p) {
@@ -613,42 +722,42 @@ rb_str_coderange_scan_restartable(const char *s, const char *e, rb_encoding *enc
const char *p = s;
if (*cr == ENC_CODERANGE_BROKEN)
- return e - s;
+ return e - s;
if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
- /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */
- if (*cr == ENC_CODERANGE_VALID) return e - s;
- p = search_nonascii(p, e);
+ /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */
+ if (*cr == ENC_CODERANGE_VALID) return e - s;
+ p = search_nonascii(p, e);
*cr = p ? ENC_CODERANGE_VALID : ENC_CODERANGE_7BIT;
- return e - s;
+ return e - s;
}
else if (rb_enc_asciicompat(enc)) {
- p = search_nonascii(p, e);
- if (!p) {
- if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT;
- return e - s;
- }
- for (;;) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(ret)) {
- *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
- return p - s;
- }
- p += MBCLEN_CHARFOUND_LEN(ret);
- if (p == e) break;
- p = search_nonascii(p, e);
- if (!p) break;
- }
+ p = search_nonascii(p, e);
+ if (!p) {
+ if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT;
+ return e - s;
+ }
+ for (;;) {
+ int ret = rb_enc_precise_mbclen(p, e, enc);
+ if (!MBCLEN_CHARFOUND_P(ret)) {
+ *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
+ return p - s;
+ }
+ p += MBCLEN_CHARFOUND_LEN(ret);
+ if (p == e) break;
+ p = search_nonascii(p, e);
+ if (!p) break;
+ }
}
else {
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(ret)) {
- *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
- return p - s;
- }
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
+ while (p < e) {
+ int ret = rb_enc_precise_mbclen(p, e, enc);
+ if (!MBCLEN_CHARFOUND_P(ret)) {
+ *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
+ return p - s;
+ }
+ p += MBCLEN_CHARFOUND_LEN(ret);
+ }
}
*cr = ENC_CODERANGE_VALID;
return e - s;
@@ -668,25 +777,25 @@ rb_enc_cr_str_copy_for_substr(VALUE dest, VALUE src)
*/
str_enc_copy(dest, src);
if (RSTRING_LEN(dest) == 0) {
- if (!rb_enc_asciicompat(STR_ENC_GET(src)))
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
- else
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
- return;
+ if (!rb_enc_asciicompat(STR_ENC_GET(src)))
+ ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
+ else
+ ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
+ return;
}
switch (ENC_CODERANGE(src)) {
case ENC_CODERANGE_7BIT:
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
- break;
+ ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
+ break;
case ENC_CODERANGE_VALID:
- if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
- search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest)))
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
- else
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
- break;
+ if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
+ search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest)))
+ ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
+ else
+ ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
+ break;
default:
- break;
+ break;
}
}
@@ -698,15 +807,15 @@ rb_enc_cr_str_exact_copy(VALUE dest, VALUE src)
}
static int
-enc_coderange_scan(VALUE str, rb_encoding *enc, int encidx)
+enc_coderange_scan(VALUE str, rb_encoding *enc)
{
- 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);
- }
+ 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);
}
int
@@ -715,9 +824,7 @@ rb_enc_str_coderange(VALUE str)
int cr = ENC_CODERANGE(str);
if (cr == ENC_CODERANGE_UNKNOWN) {
- int encidx = ENCODING_GET(str);
- rb_encoding *enc = rb_enc_from_index(encidx);
- cr = enc_coderange_scan(str, enc, encidx);
+ cr = enc_coderange_scan(str, get_encoding(str));
ENC_CODERANGE_SET(str, cr);
}
return cr;
@@ -730,7 +837,7 @@ rb_enc_str_asciionly_p(VALUE str)
if (!rb_enc_asciicompat(enc))
return FALSE;
- else if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
+ else if (is_ascii_string(str))
return TRUE;
return FALSE;
}
@@ -739,7 +846,7 @@ static inline void
str_mod_check(VALUE s, const char *p, long len)
{
if (RSTRING_PTR(s) != p || RSTRING_LEN(s) != len){
- rb_raise(rb_eRuntimeError, "string modified");
+ rb_raise(rb_eRuntimeError, "string modified");
}
}
@@ -747,13 +854,17 @@ static size_t
str_capacity(VALUE str, const int termlen)
{
if (STR_EMBED_P(str)) {
- return (RSTRING_EMBED_LEN_MAX + 1 - termlen);
+#if USE_RVARGC
+ return str_embed_capa(str) - termlen;
+#else
+ return (RSTRING_EMBED_LEN_MAX + 1 - termlen);
+#endif
}
else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
- return RSTRING(str)->as.heap.len;
+ return RSTRING(str)->as.heap.len;
}
else {
- return RSTRING(str)->as.heap.aux.capa;
+ return RSTRING(str)->as.heap.aux.capa;
}
}
@@ -767,14 +878,32 @@ static inline void
must_not_null(const char *ptr)
{
if (!ptr) {
- rb_raise(rb_eArgError, "NULL pointer given");
+ rb_raise(rb_eArgError, "NULL pointer given");
}
}
static inline VALUE
-str_alloc(VALUE klass)
+str_alloc_embed(VALUE klass, size_t capa)
{
- NEWOBJ_OF(str, struct RString, klass, T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0));
+ size_t size = rb_str_embed_size(capa);
+ assert(size > 0);
+ assert(rb_gc_size_allocatable_p(size));
+#if !USE_RVARGC
+ assert(size <= sizeof(struct RString));
+#endif
+
+ RVARGC_NEWOBJ_OF(str, struct RString, klass,
+ T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size);
+
+ return (VALUE)str;
+}
+
+static inline VALUE
+str_alloc_heap(VALUE klass)
+{
+ RVARGC_NEWOBJ_OF(str, struct RString, klass,
+ T_STRING | STR_NOEMBED | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), sizeof(struct RString));
+
return (VALUE)str;
}
@@ -782,7 +911,9 @@ static inline VALUE
empty_str_alloc(VALUE klass)
{
RUBY_DTRACE_CREATE_HOOK(STRING, 0);
- return str_alloc(klass);
+ VALUE str = str_alloc_embed(klass, 0);
+ memset(RSTRING(str)->as.embed.ary, 0, str_embed_capa(str));
+ return str;
}
static VALUE
@@ -791,22 +922,28 @@ str_new0(VALUE klass, const char *ptr, long len, int termlen)
VALUE str;
if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
}
RUBY_DTRACE_CREATE_HOOK(STRING, len);
- str = str_alloc(klass);
- if (!STR_EMBEDDABLE_P(len, termlen)) {
- RSTRING(str)->as.heap.aux.capa = len;
- RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)len + termlen);
- STR_SET_NOEMBED(str);
+ if (STR_EMBEDDABLE_P(len, termlen)) {
+ str = str_alloc_embed(klass, len + termlen);
+ if (len == 0) {
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ }
}
- else if (len == 0) {
- ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ else {
+ str = str_alloc_heap(klass);
+ RSTRING(str)->as.heap.aux.capa = len;
+ /* :FIXME: @shyouhei guesses `len + termlen` is guaranteed to never
+ * integer overflow. If we can STATIC_ASSERT that, the following
+ * mul_add_mul can be reverted to a simple ALLOC_N. */
+ RSTRING(str)->as.heap.ptr =
+ rb_xmalloc_mul_add_mul(sizeof(char), len, sizeof(char), termlen);
}
if (ptr) {
- memcpy(RSTRING_PTR(str), ptr, len);
+ memcpy(RSTRING_PTR(str), ptr, len);
}
STR_SET_LEN(str, len);
TERM_FILL(RSTRING_PTR(str) + len, termlen);
@@ -886,7 +1023,7 @@ rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
{
must_not_null(ptr);
if (rb_enc_mbminlen(enc) != 1) {
- rb_raise(rb_eArgError, "wchar encoding given");
+ rb_raise(rb_eArgError, "wchar encoding given");
}
return rb_enc_str_new(ptr, strlen(ptr), enc);
}
@@ -897,21 +1034,20 @@ str_new_static(VALUE klass, const char *ptr, long len, int encindex)
VALUE str;
if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
}
if (!ptr) {
- rb_encoding *enc = rb_enc_get_from_index(encindex);
- str = str_new0(klass, ptr, len, rb_enc_mbminlen(enc));
+ rb_encoding *enc = rb_enc_get_from_index(encindex);
+ str = str_new0(klass, ptr, len, rb_enc_mbminlen(enc));
}
else {
- RUBY_DTRACE_CREATE_HOOK(STRING, len);
- str = str_alloc(klass);
- RSTRING(str)->as.heap.len = len;
- RSTRING(str)->as.heap.ptr = (char *)ptr;
- RSTRING(str)->as.heap.aux.capa = len;
- STR_SET_NOEMBED(str);
- RBASIC(str)->flags |= STR_NOFREE;
+ RUBY_DTRACE_CREATE_HOOK(STRING, len);
+ str = str_alloc_heap(klass);
+ RSTRING(str)->as.heap.len = len;
+ RSTRING(str)->as.heap.ptr = (char *)ptr;
+ RSTRING(str)->as.heap.aux.capa = len;
+ RBASIC(str)->flags |= STR_NOFREE;
}
rb_enc_associate_index(str, encindex);
return str;
@@ -941,31 +1077,17 @@ rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc)
return str_new_static(rb_cString, ptr, len, rb_enc_to_index(enc));
}
-VALUE
-rb_tainted_str_new(const char *ptr, long len)
-{
- rb_warn_deprecated_to_remove_at(3.2, "rb_tainted_str_new", NULL);
- return rb_str_new(ptr, len);
-}
-
-VALUE
-rb_tainted_str_new_cstr(const char *ptr)
-{
- rb_warn_deprecated_to_remove_at(3.2, "rb_tainted_str_new_cstr", NULL);
- return rb_str_new_cstr(ptr);
-}
-
static VALUE str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
- rb_encoding *from, rb_encoding *to,
- int ecflags, VALUE ecopts);
+ 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;
+ return is_ascii_string(str);
+ return enc_coderange_scan(str, enc) == ENC_CODERANGE_7BIT;
}
VALUE
@@ -979,27 +1101,27 @@ rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags,
if (!from) from = rb_enc_get(str);
if (from == to) return 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);
- rb_enc_associate(str, to);
- }
- return str;
+ rb_is_ascii8bit_enc(to)) {
+ if (STR_ENC_GET(str) != to) {
+ str = rb_str_dup(str);
+ rb_enc_associate(str, to);
+ }
+ return str;
}
RSTRING_GETMEM(str, ptr, len);
newstr = str_cat_conv_enc_opts(rb_str_buf_new(len), 0, ptr, len,
- from, to, ecflags, ecopts);
+ from, to, ecflags, ecopts);
if (NIL_P(newstr)) {
- /* some error, return original */
- return str;
+ /* some error, return original */
+ return str;
}
return newstr;
}
VALUE
rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
- rb_encoding *from, int ecflags, VALUE ecopts)
+ rb_encoding *from, int ecflags, VALUE ecopts)
{
long olen;
@@ -1008,14 +1130,14 @@ rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
rb_raise(rb_eIndexError, "index %ld out of string", ofs);
if (ofs < 0) ofs += olen;
if (!from) {
- STR_SET_LEN(newstr, ofs);
- return rb_str_cat(newstr, ptr, len);
+ STR_SET_LEN(newstr, ofs);
+ return rb_str_cat(newstr, ptr, len);
}
rb_str_modify(newstr);
return str_cat_conv_enc_opts(newstr, ofs, ptr, len, from,
- rb_enc_get(newstr),
- ecflags, ecopts);
+ rb_enc_get(newstr),
+ ecflags, ecopts);
}
VALUE
@@ -1029,8 +1151,8 @@ rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc)
static VALUE
str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
- rb_encoding *from, rb_encoding *to,
- int ecflags, VALUE ecopts)
+ rb_encoding *from, rb_encoding *to,
+ int ecflags, VALUE ecopts)
{
rb_econv_t *ec;
rb_econv_result_t ret;
@@ -1051,36 +1173,35 @@ str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
sp = (unsigned char*)ptr;
start = sp;
while ((dest = (unsigned char*)RSTRING_PTR(newstr)),
- (dp = dest + converted_output),
- (ret = rb_econv_convert(ec, &sp, start + len, &dp, dest + olen, 0)),
- ret == econv_destination_buffer_full) {
- /* destination buffer short */
- size_t converted_input = sp - start;
- size_t rest = len - converted_input;
- converted_output = dp - dest;
- rb_str_set_len(newstr, converted_output);
- if (converted_input && converted_output &&
- rest < (LONG_MAX / converted_output)) {
- rest = (rest * converted_output) / converted_input;
- }
- else {
- rest = olen;
- }
- olen += rest < 2 ? 2 : rest;
- rb_str_resize(newstr, olen);
+ (dp = dest + converted_output),
+ (ret = rb_econv_convert(ec, &sp, start + len, &dp, dest + olen, 0)),
+ ret == econv_destination_buffer_full) {
+ /* destination buffer short */
+ size_t converted_input = sp - start;
+ size_t rest = len - converted_input;
+ converted_output = dp - dest;
+ rb_str_set_len(newstr, converted_output);
+ if (converted_input && converted_output &&
+ rest < (LONG_MAX / converted_output)) {
+ rest = (rest * converted_output) / converted_input;
+ }
+ else {
+ rest = olen;
+ }
+ olen += rest < 2 ? 2 : rest;
+ rb_str_resize(newstr, olen);
}
DATA_PTR(econv_wrapper) = 0;
rb_econv_close(ec);
- rb_gc_force_recycle(econv_wrapper);
switch (ret) {
case econv_finished:
- len = dp - (unsigned char*)RSTRING_PTR(newstr);
- rb_str_set_len(newstr, len);
- rb_enc_associate(newstr, to);
- return newstr;
+ len = dp - (unsigned char*)RSTRING_PTR(newstr);
+ rb_str_set_len(newstr, len);
+ rb_enc_associate(newstr, to);
+ return newstr;
default:
- return Qnil;
+ return Qnil;
}
}
@@ -1103,7 +1224,7 @@ rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *eenc)
/* ASCII-8BIT case, no conversion */
if ((eidx == rb_ascii8bit_encindex()) ||
- (eidx == rb_usascii_encindex() && search_nonascii(ptr, ptr + len))) {
+ (eidx == rb_usascii_encindex() && search_nonascii(ptr, ptr + len))) {
return rb_str_new(ptr, len);
}
/* no default_internal or same encoding, no conversion */
@@ -1114,8 +1235,8 @@ rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *eenc)
/* ASCII compatible, and ASCII only string, no conversion in
* default_internal */
if ((eidx == rb_ascii8bit_encindex()) ||
- (eidx == rb_usascii_encindex()) ||
- (rb_enc_asciicompat(eenc) && !search_nonascii(ptr, ptr + len))) {
+ (eidx == rb_usascii_encindex()) ||
+ (rb_enc_asciicompat(eenc) && !search_nonascii(ptr, ptr + len))) {
return rb_enc_str_new(ptr, len, ienc);
}
/* convert from the given encoding to default_internal */
@@ -1123,7 +1244,7 @@ rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *eenc)
/* when the conversion failed for some reason, just ignore the
* default_internal and result in the given encoding as-is. */
if (NIL_P(rb_str_cat_conv_enc_opts(str, 0, ptr, len, eenc, 0, Qnil))) {
- rb_str_initialize(str, ptr, len, eenc);
+ rb_str_initialize(str, ptr, len, eenc);
}
return str;
}
@@ -1133,9 +1254,9 @@ rb_external_str_with_enc(VALUE str, rb_encoding *eenc)
{
int eidx = rb_enc_to_index(eenc);
if (eidx == rb_usascii_encindex() &&
- rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
- rb_enc_associate_index(str, rb_ascii8bit_encindex());
- return str;
+ !is_ascii_string(str)) {
+ rb_enc_associate_index(str, rb_ascii8bit_encindex());
+ return str;
}
rb_enc_associate_index(str, eidx);
return rb_str_conv_enc(str, eenc, rb_default_internal_encoding());
@@ -1203,12 +1324,12 @@ str_replace_shared_without_enc(VALUE str2, VALUE str)
long len;
RSTRING_GETMEM(str, ptr, len);
- if (STR_EMBEDDABLE_P(len, termlen)) {
- char *ptr2 = RSTRING(str2)->as.ary;
- STR_SET_EMBED(str2);
- memcpy(ptr2, RSTRING_PTR(str), len);
- STR_SET_EMBED_LEN(str2, len);
- TERM_FILL(ptr2+len, termlen);
+ if (str_embed_capa(str2) >= len + termlen) {
+ char *ptr2 = RSTRING(str2)->as.embed.ary;
+ STR_SET_EMBED(str2);
+ memcpy(ptr2, RSTRING_PTR(str), len);
+ STR_SET_EMBED_LEN(str2, len);
+ TERM_FILL(ptr2+len, termlen);
}
else {
VALUE root;
@@ -1220,6 +1341,7 @@ str_replace_shared_without_enc(VALUE str2, VALUE str)
root = rb_str_new_frozen(str);
RSTRING_GETMEM(root, ptr, len);
}
+ assert(OBJ_FROZEN(root));
if (!STR_EMBED_P(str2) && !FL_TEST_RAW(str2, STR_SHARED|STR_NOFREE)) {
if (FL_TEST_RAW(str2, STR_SHARED_ROOT)) {
rb_fatal("about to free a possible shared root");
@@ -1229,9 +1351,9 @@ str_replace_shared_without_enc(VALUE str2, VALUE str)
ruby_sized_xfree(ptr2, STR_HEAP_SIZE(str2));
}
}
- FL_SET(str2, STR_NOEMBED);
- RSTRING(str2)->as.heap.len = len;
- RSTRING(str2)->as.heap.ptr = ptr;
+ FL_SET(str2, STR_NOEMBED);
+ RSTRING(str2)->as.heap.len = len;
+ RSTRING(str2)->as.heap.ptr = ptr;
STR_SET_SHARED(str2, root);
}
return str2;
@@ -1248,7 +1370,7 @@ str_replace_shared(VALUE str2, VALUE str)
static VALUE
str_new_shared(VALUE klass, VALUE str)
{
- return str_replace_shared(str_alloc(klass), str);
+ return str_replace_shared(str_alloc_heap(klass), str);
}
VALUE
@@ -1282,25 +1404,29 @@ void
rb_str_tmp_frozen_release(VALUE orig, VALUE tmp)
{
if (RBASIC_CLASS(tmp) != 0)
- return;
+ return;
if (STR_EMBED_P(tmp)) {
- assert(OBJ_FROZEN_RAW(tmp));
- rb_gc_force_recycle(tmp);
+ assert(OBJ_FROZEN_RAW(tmp));
}
else if (FL_TEST_RAW(orig, STR_SHARED) &&
- !FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)) {
- VALUE shared = RSTRING(orig)->as.heap.aux.shared;
-
- if (shared == tmp && !FL_TEST_RAW(tmp, STR_BORROWED)) {
- FL_UNSET_RAW(orig, STR_SHARED);
- assert(RSTRING(orig)->as.heap.ptr == RSTRING(tmp)->as.heap.ptr);
- assert(RSTRING(orig)->as.heap.len == RSTRING(tmp)->as.heap.len);
- RSTRING(orig)->as.heap.aux.capa = RSTRING(tmp)->as.heap.aux.capa;
- RBASIC(orig)->flags |= RBASIC(tmp)->flags & STR_NOFREE;
- assert(OBJ_FROZEN_RAW(tmp));
- rb_gc_force_recycle(tmp);
- }
+ !FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)) {
+ VALUE shared = RSTRING(orig)->as.heap.aux.shared;
+
+ if (shared == tmp && !FL_TEST_RAW(tmp, STR_BORROWED)) {
+ assert(RSTRING(orig)->as.heap.ptr == RSTRING(tmp)->as.heap.ptr);
+ assert(RSTRING(orig)->as.heap.len == RSTRING(tmp)->as.heap.len);
+
+ /* Unshare orig since the root (tmp) only has this one child. */
+ FL_UNSET_RAW(orig, STR_SHARED);
+ RSTRING(orig)->as.heap.aux.capa = RSTRING(tmp)->as.heap.aux.capa;
+ RBASIC(orig)->flags |= RBASIC(tmp)->flags & STR_NOFREE;
+ assert(OBJ_FROZEN_RAW(tmp));
+
+ /* Make tmp embedded and empty so it is safe for sweeping. */
+ STR_SET_EMBED(tmp);
+ STR_SET_EMBED_LEN(tmp, 0);
+ }
}
}
@@ -1311,53 +1437,72 @@ str_new_frozen(VALUE klass, VALUE orig)
}
static VALUE
+heap_str_make_shared(VALUE klass, VALUE orig)
+{
+ assert(!STR_EMBED_P(orig));
+ assert(!STR_SHARED_P(orig));
+
+ VALUE str = str_alloc_heap(klass);
+ RSTRING(str)->as.heap.len = RSTRING_LEN(orig);
+ RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
+ RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa;
+ RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE;
+ RBASIC(orig)->flags &= ~STR_NOFREE;
+ STR_SET_SHARED(orig, str);
+ if (klass == 0)
+ FL_UNSET_RAW(str, STR_BORROWED);
+ return str;
+}
+
+static VALUE
str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding)
{
VALUE str;
- if (STR_EMBED_P(orig)) {
- str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
+ long len = RSTRING_LEN(orig);
+ int termlen = copy_encoding ? TERM_LEN(orig) : 1;
+
+ if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(len, termlen)) {
+ str = str_new0(klass, RSTRING_PTR(orig), len, termlen);
+ assert(STR_EMBED_P(str));
}
else {
- if (FL_TEST_RAW(orig, STR_SHARED)) {
- VALUE shared = RSTRING(orig)->as.heap.aux.shared;
- long ofs = RSTRING(orig)->as.heap.ptr - RSTRING(shared)->as.heap.ptr;
- long rest = RSTRING(shared)->as.heap.len - ofs - RSTRING(orig)->as.heap.len;
- assert(!STR_EMBED_P(shared));
- assert(OBJ_FROZEN(shared));
-
- if ((ofs > 0) || (rest > 0) ||
- (klass != RBASIC(shared)->klass) ||
- ENCODING_GET(shared) != ENCODING_GET(orig)) {
- str = str_new_shared(klass, shared);
- RSTRING(str)->as.heap.ptr += ofs;
- RSTRING(str)->as.heap.len -= ofs + rest;
- }
- else {
- if (RBASIC_CLASS(shared) == 0)
- FL_SET_RAW(shared, STR_BORROWED);
- return shared;
- }
- }
- else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) {
- str = str_alloc(klass);
- STR_SET_EMBED(str);
- memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig));
- STR_SET_EMBED_LEN(str, RSTRING_LEN(orig));
- TERM_FILL(RSTRING_END(str), TERM_LEN(orig));
- }
- else {
- str = str_alloc(klass);
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.len = RSTRING_LEN(orig);
- RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
- RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa;
- RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE;
- RBASIC(orig)->flags &= ~STR_NOFREE;
- STR_SET_SHARED(orig, str);
- if (klass == 0)
- FL_UNSET_RAW(str, STR_BORROWED);
- }
+ if (FL_TEST_RAW(orig, STR_SHARED)) {
+ VALUE shared = RSTRING(orig)->as.heap.aux.shared;
+ long ofs = RSTRING(orig)->as.heap.ptr - RSTRING_PTR(shared);
+ long rest = RSTRING_LEN(shared) - ofs - RSTRING(orig)->as.heap.len;
+ assert(ofs >= 0);
+ assert(rest >= 0);
+ assert(ofs + rest <= RSTRING_LEN(shared));
+#if !USE_RVARGC
+ assert(!STR_EMBED_P(shared));
+#endif
+ assert(OBJ_FROZEN(shared));
+
+ if ((ofs > 0) || (rest > 0) ||
+ (klass != RBASIC(shared)->klass) ||
+ ENCODING_GET(shared) != ENCODING_GET(orig)) {
+ str = str_new_shared(klass, shared);
+ assert(!STR_EMBED_P(str));
+ RSTRING(str)->as.heap.ptr += ofs;
+ RSTRING(str)->as.heap.len -= ofs + rest;
+ }
+ else {
+ if (RBASIC_CLASS(shared) == 0)
+ FL_SET_RAW(shared, STR_BORROWED);
+ return shared;
+ }
+ }
+ else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) {
+ str = str_alloc_embed(klass, RSTRING_LEN(orig) + TERM_LEN(orig));
+ STR_SET_EMBED(str);
+ memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig));
+ STR_SET_EMBED_LEN(str, RSTRING_LEN(orig));
+ TERM_FILL(RSTRING_END(str), TERM_LEN(orig));
+ }
+ else {
+ str = heap_str_make_shared(klass, orig);
+ }
}
if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig);
@@ -1380,18 +1525,24 @@ str_new_empty_String(VALUE str)
}
#define STR_BUF_MIN_SIZE 63
+#if !USE_RVARGC
STATIC_ASSERT(STR_BUF_MIN_SIZE, STR_BUF_MIN_SIZE > RSTRING_EMBED_LEN_MAX);
+#endif
VALUE
rb_str_buf_new(long capa)
{
- VALUE str = str_alloc(rb_cString);
+ if (STR_EMBEDDABLE_P(capa, 1)) {
+ return str_alloc_embed(rb_cString, capa + 1);
+ }
+
+ VALUE str = str_alloc_heap(rb_cString);
- if (capa <= RSTRING_EMBED_LEN_MAX) return str;
+#if !USE_RVARGC
if (capa < STR_BUF_MIN_SIZE) {
- capa = STR_BUF_MIN_SIZE;
+ capa = STR_BUF_MIN_SIZE;
}
- FL_SET(str, STR_NOEMBED);
+#endif
RSTRING(str)->as.heap.aux.capa = capa;
RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)capa + 1);
RSTRING(str)->as.heap.ptr[0] = '\0';
@@ -1421,7 +1572,7 @@ void
rb_str_free(VALUE str)
{
if (FL_TEST(str, RSTRING_FSTR)) {
- st_data_t fstr = (st_data_t)str;
+ st_data_t fstr = (st_data_t)str;
RB_VM_LOCK_ENTER();
{
@@ -1432,15 +1583,15 @@ rb_str_free(VALUE str)
}
if (STR_EMBED_P(str)) {
- RB_DEBUG_COUNTER_INC(obj_str_embed);
+ RB_DEBUG_COUNTER_INC(obj_str_embed);
}
else if (FL_TEST(str, STR_SHARED | STR_NOFREE)) {
- (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared, FL_TEST(str, STR_SHARED));
- (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared, FL_TEST(str, STR_NOFREE));
+ (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared, FL_TEST(str, STR_SHARED));
+ (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared, FL_TEST(str, STR_NOFREE));
}
else {
- RB_DEBUG_COUNTER_INC(obj_str_ptr);
- ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
+ RB_DEBUG_COUNTER_INC(obj_str_ptr);
+ ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
}
}
@@ -1448,10 +1599,10 @@ RUBY_FUNC_EXPORTED size_t
rb_str_memsize(VALUE str)
{
if (FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) {
- return STR_HEAP_SIZE(str);
+ return STR_HEAP_SIZE(str);
}
else {
- return 0;
+ return 0;
}
}
@@ -1483,33 +1634,48 @@ str_shared_replace(VALUE str, VALUE str2)
str_discard(str);
termlen = rb_enc_mbminlen(enc);
- if (STR_EMBEDDABLE_P(RSTRING_LEN(str2), termlen)) {
- STR_SET_EMBED(str);
- memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (size_t)RSTRING_LEN(str2) + termlen);
- STR_SET_EMBED_LEN(str, RSTRING_LEN(str2));
+ if (str_embed_capa(str) >= RSTRING_LEN(str2) + termlen) {
+ STR_SET_EMBED(str);
+ memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (size_t)RSTRING_LEN(str2) + termlen);
+ STR_SET_EMBED_LEN(str, RSTRING_LEN(str2));
rb_enc_associate(str, enc);
ENC_CODERANGE_SET(str, cr);
}
else {
- STR_SET_NOEMBED(str);
- FL_UNSET(str, STR_SHARED);
- RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
- RSTRING(str)->as.heap.len = RSTRING_LEN(str2);
+#if USE_RVARGC
+ if (STR_EMBED_P(str2)) {
+ assert(!FL_TEST(str2, STR_SHARED));
+ long len = RSTRING(str2)->as.embed.len;
+ assert(len + termlen <= str_embed_capa(str2));
+
+ char *new_ptr = ALLOC_N(char, len + termlen);
+ memcpy(new_ptr, RSTRING(str2)->as.embed.ary, len + termlen);
+ RSTRING(str2)->as.heap.ptr = new_ptr;
+ RSTRING(str2)->as.heap.len = len;
+ RSTRING(str2)->as.heap.aux.capa = len;
+ STR_SET_NOEMBED(str2);
+ }
+#endif
+
+ STR_SET_NOEMBED(str);
+ FL_UNSET(str, STR_SHARED);
+ RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
+ RSTRING(str)->as.heap.len = RSTRING_LEN(str2);
- if (FL_TEST(str2, STR_SHARED)) {
- VALUE shared = RSTRING(str2)->as.heap.aux.shared;
- STR_SET_SHARED(str, shared);
- }
- else {
- RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa;
- }
+ if (FL_TEST(str2, STR_SHARED)) {
+ VALUE shared = RSTRING(str2)->as.heap.aux.shared;
+ STR_SET_SHARED(str, shared);
+ }
+ else {
+ RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa;
+ }
- /* abandon str2 */
- STR_SET_EMBED(str2);
- RSTRING_PTR(str2)[0] = 0;
- STR_SET_EMBED_LEN(str2, 0);
- rb_enc_associate(str, enc);
- ENC_CODERANGE_SET(str, cr);
+ /* abandon str2 */
+ STR_SET_EMBED(str2);
+ RSTRING_PTR(str2)[0] = 0;
+ STR_SET_EMBED_LEN(str2, 0);
+ rb_enc_associate(str, enc);
+ ENC_CODERANGE_SET(str, cr);
}
}
@@ -1519,7 +1685,7 @@ rb_obj_as_string(VALUE obj)
VALUE str;
if (RB_TYPE_P(obj, T_STRING)) {
- return obj;
+ return obj;
}
str = rb_funcall(obj, idTo_s, 0);
return rb_obj_as_string_result(str, obj);
@@ -1529,7 +1695,7 @@ MJIT_FUNC_EXPORTED VALUE
rb_obj_as_string_result(VALUE str, VALUE obj)
{
if (!RB_TYPE_P(str, T_STRING))
- return rb_any_to_s(obj);
+ return rb_any_to_s(obj);
return str;
}
@@ -1540,61 +1706,97 @@ str_replace(VALUE str, VALUE str2)
len = RSTRING_LEN(str2);
if (STR_SHARED_P(str2)) {
- VALUE shared = RSTRING(str2)->as.heap.aux.shared;
- assert(OBJ_FROZEN(shared));
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.len = len;
- RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
- STR_SET_SHARED(str, shared);
- rb_enc_cr_str_exact_copy(str, str2);
+ VALUE shared = RSTRING(str2)->as.heap.aux.shared;
+ assert(OBJ_FROZEN(shared));
+ STR_SET_NOEMBED(str);
+ RSTRING(str)->as.heap.len = len;
+ RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
+ STR_SET_SHARED(str, shared);
+ rb_enc_cr_str_exact_copy(str, str2);
}
else {
- str_replace_shared(str, str2);
+ str_replace_shared(str, str2);
}
return str;
}
static inline VALUE
-ec_str_alloc(struct rb_execution_context_struct *ec, VALUE klass)
+ec_str_alloc_embed(struct rb_execution_context_struct *ec, VALUE klass, size_t capa)
{
- RB_EC_NEWOBJ_OF(ec, str, struct RString, klass, T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0));
+ size_t size = rb_str_embed_size(capa);
+ assert(size > 0);
+ assert(rb_gc_size_allocatable_p(size));
+#if !USE_RVARGC
+ assert(size <= sizeof(struct RString));
+#endif
+
+ RB_RVARGC_EC_NEWOBJ_OF(ec, str, struct RString, klass,
+ T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size);
+
+ return (VALUE)str;
+}
+
+static inline VALUE
+ec_str_alloc_heap(struct rb_execution_context_struct *ec, VALUE klass)
+{
+ RB_RVARGC_EC_NEWOBJ_OF(ec, str, struct RString, klass,
+ T_STRING | STR_NOEMBED | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), sizeof(struct RString));
+
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 =
- RSTRING_NOEMBED | RSTRING_EMBED_LEN_MASK |
- ENC_CODERANGE_MASK | ENCODING_MASK |
+#if !USE_RVARGC
+ RSTRING_NOEMBED | RSTRING_EMBED_LEN_MASK |
+#endif
+ ENC_CODERANGE_MASK | ENCODING_MASK |
FL_FREEZE
- ;
+ ;
VALUE flags = FL_TEST_RAW(str, flag_mask);
int encidx = 0;
- MEMCPY(RSTRING(dup)->as.ary, RSTRING(str)->as.ary,
- char, embed_size);
- if (flags & STR_NOEMBED) {
+ if (STR_EMBED_P(str)) {
+ long len = RSTRING_EMBED_LEN(str);
+
+ assert(STR_EMBED_P(dup));
+ assert(str_embed_capa(dup) >= len + 1);
+ STR_SET_EMBED_LEN(dup, len);
+ MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + 1);
+ }
+ else {
+ VALUE root = str;
if (FL_TEST_RAW(str, STR_SHARED)) {
- str = RSTRING(str)->as.heap.aux.shared;
+ root = RSTRING(str)->as.heap.aux.shared;
}
else if (UNLIKELY(!(flags & FL_FREEZE))) {
- str = str_new_frozen(klass, str);
+ root = str = str_new_frozen(klass, str);
flags = FL_TEST_RAW(str, flag_mask);
- }
- if (flags & STR_NOEMBED) {
- RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, str);
- flags |= STR_SHARED;
- }
- else {
- MEMCPY(RSTRING(dup)->as.ary, RSTRING(str)->as.ary,
- char, embed_size);
- }
+ }
+ assert(!STR_SHARED_P(root));
+ assert(RB_OBJ_FROZEN_RAW(root));
+ if (0) {}
+#if !USE_RVARGC
+ else if (STR_EMBED_P(root)) {
+ MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(root)->as.embed.ary,
+ char, RSTRING_EMBED_LEN_MAX + 1);
+ FL_UNSET(dup, STR_NOEMBED);
+ }
+#endif
+ else {
+ RSTRING(dup)->as.heap.len = RSTRING_LEN(str);
+ RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
+ FL_SET(root, STR_SHARED_ROOT);
+ RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, root);
+ flags |= RSTRING_NOEMBED | STR_SHARED;
+ }
}
+
if ((flags & ENCODING_MASK) == (ENCODING_INLINE_MAX<<ENCODING_SHIFT)) {
- encidx = rb_enc_get_index(str);
- flags &= ~ENCODING_MASK;
+ encidx = rb_enc_get_index(str);
+ flags &= ~ENCODING_MASK;
}
FL_SET_RAW(dup, flags & ~FL_FREEZE);
if (encidx) rb_enc_associate_index(dup, encidx);
@@ -1604,14 +1806,28 @@ str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
static inline VALUE
ec_str_duplicate(struct rb_execution_context_struct *ec, VALUE klass, VALUE str)
{
- VALUE dup = ec_str_alloc(ec, klass);
+ VALUE dup;
+ if (FL_TEST(str, STR_NOEMBED)) {
+ dup = ec_str_alloc_heap(ec, klass);
+ }
+ else {
+ dup = ec_str_alloc_embed(ec, klass, RSTRING_EMBED_LEN(str) + TERM_LEN(str));
+ }
+
return str_duplicate_setup(klass, str, dup);
}
static inline VALUE
str_duplicate(VALUE klass, VALUE str)
{
- VALUE dup = str_alloc(klass);
+ VALUE dup;
+ if (FL_TEST(str, STR_NOEMBED)) {
+ dup = str_alloc_heap(klass);
+ }
+ else {
+ dup = str_alloc_embed(klass, RSTRING_EMBED_LEN(str) + TERM_LEN(str));
+ }
+
return str_duplicate_setup(klass, str, dup);
}
@@ -1636,47 +1852,12 @@ rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str)
}
/*
- * call-seq:
- * 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>
- *
- * Note that these are equivalent:
- * s0 = String.new('foo', encoding: 'ASCII')
- * s1 = 'foo'.force_encoding('ASCII')
- * s0.encoding == s1.encoding # => true
+ * call-seq:
+ * String.new(string = '', **opts) -> new_string
*
- * 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) # => ""
+ * :include: doc/string/new.rdoc
*
- * The +string+, +encoding+, and +capacity+ arguments may all be used together:
- * String.new('hello', encoding: 'UTF-8', capacity: 25)
*/
static VALUE
@@ -1689,38 +1870,43 @@ rb_str_init(int argc, VALUE *argv, VALUE str)
int n;
if (!keyword_ids[0]) {
- keyword_ids[0] = rb_id_encoding();
- CONST_ID(keyword_ids[1], "capacity");
+ keyword_ids[0] = rb_id_encoding();
+ CONST_ID(keyword_ids[1], "capacity");
}
n = rb_scan_args(argc, argv, "01:", &orig, &opt);
if (!NIL_P(opt)) {
- rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
- venc = kwargs[0];
- vcapa = kwargs[1];
- if (venc != Qundef && !NIL_P(venc)) {
- enc = rb_to_encoding(venc);
- }
- if (vcapa != Qundef && !NIL_P(vcapa)) {
- long capa = NUM2LONG(vcapa);
- long len = 0;
- int termlen = enc ? rb_enc_mbminlen(enc) : 1;
-
- if (capa < STR_BUF_MIN_SIZE) {
- capa = STR_BUF_MIN_SIZE;
- }
- if (n == 1) {
- StringValue(orig);
- len = RSTRING_LEN(orig);
- if (capa < len) {
- capa = len;
- }
- if (orig == str) n = 0;
- }
- str_modifiable(str);
- if (STR_EMBED_P(str)) { /* make noembed always */
+ rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
+ venc = kwargs[0];
+ vcapa = kwargs[1];
+ if (!UNDEF_P(venc) && !NIL_P(venc)) {
+ enc = rb_to_encoding(venc);
+ }
+ if (!UNDEF_P(vcapa) && !NIL_P(vcapa)) {
+ long capa = NUM2LONG(vcapa);
+ long len = 0;
+ int termlen = enc ? rb_enc_mbminlen(enc) : 1;
+
+ if (capa < STR_BUF_MIN_SIZE) {
+ capa = STR_BUF_MIN_SIZE;
+ }
+ if (n == 1) {
+ StringValue(orig);
+ len = RSTRING_LEN(orig);
+ if (capa < len) {
+ capa = len;
+ }
+ if (orig == str) n = 0;
+ }
+ str_modifiable(str);
+ if (STR_EMBED_P(str)) { /* make noembed always */
char *new_ptr = ALLOC_N(char, (size_t)capa + termlen);
- memcpy(new_ptr, RSTRING(str)->as.ary, RSTRING_EMBED_LEN_MAX + 1);
+#if USE_RVARGC
+ assert(RSTRING(str)->as.embed.len + 1 <= str_embed_capa(str));
+ memcpy(new_ptr, RSTRING(str)->as.embed.ary, RSTRING(str)->as.embed.len + 1);
+#else
+ memcpy(new_ptr, RSTRING(str)->as.embed.ary, RSTRING_EMBED_LEN_MAX + 1);
+#endif
RSTRING(str)->as.heap.ptr = new_ptr;
}
else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
@@ -1729,32 +1915,32 @@ rb_str_init(int argc, VALUE *argv, VALUE str)
const size_t osize = RSTRING(str)->as.heap.len + TERM_LEN(str);
char *new_ptr = ALLOC_N(char, (size_t)capa + termlen);
memcpy(new_ptr, old_ptr, osize < size ? osize : size);
- FL_UNSET_RAW(str, STR_SHARED);
+ FL_UNSET_RAW(str, STR_SHARED|STR_NOFREE);
RSTRING(str)->as.heap.ptr = new_ptr;
- }
- else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
- SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
- (size_t)capa + termlen, STR_HEAP_SIZE(str));
- }
- RSTRING(str)->as.heap.len = len;
- TERM_FILL(&RSTRING(str)->as.heap.ptr[len], termlen);
- if (n == 1) {
- memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), len);
- rb_enc_cr_str_exact_copy(str, orig);
- }
- FL_SET(str, STR_NOEMBED);
- RSTRING(str)->as.heap.aux.capa = capa;
- }
- else if (n == 1) {
- rb_str_replace(str, orig);
- }
- if (enc) {
- rb_enc_associate(str, enc);
- ENC_CODERANGE_CLEAR(str);
- }
+ }
+ else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
+ SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
+ (size_t)capa + termlen, STR_HEAP_SIZE(str));
+ }
+ RSTRING(str)->as.heap.len = len;
+ TERM_FILL(&RSTRING(str)->as.heap.ptr[len], termlen);
+ if (n == 1) {
+ memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), len);
+ rb_enc_cr_str_exact_copy(str, orig);
+ }
+ FL_SET(str, STR_NOEMBED);
+ RSTRING(str)->as.heap.aux.capa = capa;
+ }
+ else if (n == 1) {
+ rb_str_replace(str, orig);
+ }
+ if (enc) {
+ rb_enc_associate(str, enc);
+ ENC_CODERANGE_CLEAR(str);
+ }
}
else if (n == 1) {
- rb_str_replace(str, orig);
+ rb_str_replace(str, orig);
}
return str;
}
@@ -1806,62 +1992,62 @@ enc_strlen(const char *p, const char *e, rb_encoding *enc, int cr)
const char *q;
if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- long diff = (long)(e - p);
- return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
+ long diff = (long)(e - p);
+ return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
}
#ifdef NONASCII_MASK
else if (cr == ENC_CODERANGE_VALID && enc == rb_utf8_encoding()) {
- uintptr_t len = 0;
- if ((int)sizeof(uintptr_t) * 2 < e - p) {
- const uintptr_t *s, *t;
- const uintptr_t lowbits = sizeof(uintptr_t) - 1;
- s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
- t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
- while (p < (const char *)s) {
- if (is_utf8_lead_byte(*p)) len++;
- p++;
- }
- while (s < t) {
- len += count_utf8_lead_bytes_with_word(s);
- s++;
- }
- p = (const char *)s;
- }
- while (p < e) {
- if (is_utf8_lead_byte(*p)) len++;
- p++;
- }
- return (long)len;
+ uintptr_t len = 0;
+ if ((int)sizeof(uintptr_t) * 2 < e - p) {
+ const uintptr_t *s, *t;
+ const uintptr_t lowbits = sizeof(uintptr_t) - 1;
+ s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
+ t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
+ while (p < (const char *)s) {
+ if (is_utf8_lead_byte(*p)) len++;
+ p++;
+ }
+ while (s < t) {
+ len += count_utf8_lead_bytes_with_word(s);
+ s++;
+ }
+ p = (const char *)s;
+ }
+ while (p < e) {
+ if (is_utf8_lead_byte(*p)) len++;
+ p++;
+ }
+ return (long)len;
}
#endif
else if (rb_enc_asciicompat(enc)) {
c = 0;
- if (ENC_CODERANGE_CLEAN_P(cr)) {
- while (p < e) {
- if (ISASCII(*p)) {
- q = search_nonascii(p, e);
- if (!q)
- return c + (e - p);
- c += q - p;
- p = q;
- }
- p += rb_enc_fast_mbclen(p, e, enc);
- c++;
- }
- }
- else {
- while (p < e) {
- if (ISASCII(*p)) {
- q = search_nonascii(p, e);
- if (!q)
- return c + (e - p);
- c += q - p;
- p = q;
- }
- p += rb_enc_mbclen(p, e, enc);
- c++;
- }
- }
+ if (ENC_CODERANGE_CLEAN_P(cr)) {
+ while (p < e) {
+ if (ISASCII(*p)) {
+ q = search_nonascii(p, e);
+ if (!q)
+ return c + (e - p);
+ c += q - p;
+ p = q;
+ }
+ p += rb_enc_fast_mbclen(p, e, enc);
+ c++;
+ }
+ }
+ else {
+ while (p < e) {
+ if (ISASCII(*p)) {
+ q = search_nonascii(p, e);
+ if (!q)
+ return c + (e - p);
+ c += q - p;
+ p = q;
+ }
+ p += rb_enc_mbclen(p, e, enc);
+ c++;
+ }
+ }
return c;
}
@@ -1889,49 +2075,49 @@ rb_enc_strlen_cr(const char *p, const char *e, rb_encoding *enc, int *cr)
*cr = 0;
if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- long diff = (long)(e - p);
- return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
+ long diff = (long)(e - p);
+ return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
}
else if (rb_enc_asciicompat(enc)) {
- c = 0;
- while (p < e) {
- if (ISASCII(*p)) {
- q = search_nonascii(p, e);
- if (!q) {
- if (!*cr) *cr = ENC_CODERANGE_7BIT;
- return c + (e - p);
- }
- c += q - p;
- p = q;
- }
- ret = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_CHARFOUND_P(ret)) {
- *cr |= ENC_CODERANGE_VALID;
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- else {
- *cr = ENC_CODERANGE_BROKEN;
- p++;
- }
- c++;
- }
- if (!*cr) *cr = ENC_CODERANGE_7BIT;
- return c;
+ c = 0;
+ while (p < e) {
+ if (ISASCII(*p)) {
+ q = search_nonascii(p, e);
+ if (!q) {
+ if (!*cr) *cr = ENC_CODERANGE_7BIT;
+ return c + (e - p);
+ }
+ c += q - p;
+ p = q;
+ }
+ ret = rb_enc_precise_mbclen(p, e, enc);
+ if (MBCLEN_CHARFOUND_P(ret)) {
+ *cr |= ENC_CODERANGE_VALID;
+ p += MBCLEN_CHARFOUND_LEN(ret);
+ }
+ else {
+ *cr = ENC_CODERANGE_BROKEN;
+ p++;
+ }
+ c++;
+ }
+ if (!*cr) *cr = ENC_CODERANGE_7BIT;
+ return c;
}
for (c=0; p<e; c++) {
- ret = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_CHARFOUND_P(ret)) {
- *cr |= ENC_CODERANGE_VALID;
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- else {
- *cr = ENC_CODERANGE_BROKEN;
+ ret = rb_enc_precise_mbclen(p, e, enc);
+ if (MBCLEN_CHARFOUND_P(ret)) {
+ *cr |= ENC_CODERANGE_VALID;
+ p += MBCLEN_CHARFOUND_LEN(ret);
+ }
+ else {
+ *cr = ENC_CODERANGE_BROKEN;
if (p + rb_enc_mbminlen(enc) <= e)
p += rb_enc_mbminlen(enc);
else
p = e;
- }
+ }
}
if (!*cr) *cr = ENC_CODERANGE_7BIT;
return c;
@@ -1951,12 +2137,12 @@ str_strlen(VALUE str, rb_encoding *enc)
cr = ENC_CODERANGE(str);
if (cr == ENC_CODERANGE_UNKNOWN) {
- long n = rb_enc_strlen_cr(p, e, enc, &cr);
- if (cr) ENC_CODERANGE_SET(str, cr);
- return n;
+ long n = rb_enc_strlen_cr(p, e, enc, &cr);
+ if (cr) ENC_CODERANGE_SET(str, cr);
+ return n;
}
else {
- return enc_strlen(p, e, enc, cr);
+ return enc_strlen(p, e, enc, cr);
}
}
@@ -1968,15 +2154,10 @@ rb_str_strlen(VALUE str)
/*
* call-seq:
- * string.length -> integer
- *
- * Returns the count of characters (not bytes) in +self+:
- * "\x80\u3042".length # => 2
- * "hello".length # => 5
+ * length -> integer
*
- * String#size is an alias for String#length.
+ * :include: doc/string/length.rdoc
*
- * Related: String#bytesize.
*/
VALUE
@@ -1987,13 +2168,10 @@ rb_str_length(VALUE str)
/*
* call-seq:
- * string.bytesize -> integer
+ * bytesize -> integer
*
- * Returns the count of bytes in +self+:
- * "\x80\u3042".bytesize # => 4
- * "hello".bytesize # => 5
+ * :include: doc/string/bytesize.rdoc
*
- * Related: String#length.
*/
static VALUE
@@ -2004,12 +2182,14 @@ rb_str_bytesize(VALUE str)
/*
* call-seq:
- * string.empty? -> true or false
+ * empty? -> true or false
*
* Returns +true+ if the length of +self+ is zero, +false+ otherwise:
+ *
* "hello".empty? # => false
* " ".empty? # => false
* "".empty? # => true
+ *
*/
static VALUE
@@ -2023,7 +2203,9 @@ rb_str_empty(VALUE str)
* string + other_string -> new_string
*
* Returns a new \String containing +other_string+ concatenated to +self+:
+ *
* "Hello from " + self.to_s # => "Hello from main"
+ *
*/
VALUE
@@ -2041,7 +2223,7 @@ rb_str_plus(VALUE str1, VALUE str2)
RSTRING_GETMEM(str2, ptr2, len2);
termlen = rb_enc_mbminlen(enc);
if (len1 > LONG_MAX - len2) {
- rb_raise(rb_eArgError, "string size too big");
+ rb_raise(rb_eArgError, "string size too big");
}
str3 = str_new0(rb_cString, 0, len1+len2, termlen);
ptr3 = RSTRING_PTR(str3);
@@ -2050,7 +2232,7 @@ rb_str_plus(VALUE str1, VALUE str2)
TERM_FILL(&ptr3[len1+len2], termlen);
ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
- ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
+ ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
RB_GC_GUARD(str1);
RB_GC_GUARD(str2);
return str3;
@@ -2092,8 +2274,10 @@ rb_str_opt_plus(VALUE str1, VALUE str2)
* string * integer -> new_string
*
* Returns a new \String containing +integer+ copies of +self+:
+ *
* "Ho! " * 3 # => "Ho! Ho! Ho! "
* "Ho! " * 0 # => ""
+ *
*/
VALUE
@@ -2108,27 +2292,30 @@ rb_str_times(VALUE str, VALUE times)
return str_duplicate(rb_cString, str);
}
if (times == INT2FIX(0)) {
- str2 = str_alloc(rb_cString);
- rb_enc_copy(str2, str);
- return str2;
+ str2 = str_alloc_embed(rb_cString, 0);
+ rb_enc_copy(str2, str);
+ return str2;
}
len = NUM2LONG(times);
if (len < 0) {
- rb_raise(rb_eArgError, "negative argument");
+ rb_raise(rb_eArgError, "negative argument");
}
if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
- str2 = str_alloc(rb_cString);
- if (!STR_EMBEDDABLE_P(len, 1)) {
+ if (STR_EMBEDDABLE_P(len, 1)) {
+ str2 = str_alloc_embed(rb_cString, len + 1);
+ memset(RSTRING_PTR(str2), 0, len + 1);
+ }
+ else {
+ str2 = str_alloc_heap(rb_cString);
RSTRING(str2)->as.heap.aux.capa = len;
RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
- STR_SET_NOEMBED(str2);
}
STR_SET_LEN(str2, len);
rb_enc_copy(str2, str);
return str2;
}
if (len && LONG_MAX/len < RSTRING_LEN(str)) {
- rb_raise(rb_eArgError, "argument too big");
+ rb_raise(rb_eArgError, "argument too big");
}
len *= RSTRING_LEN(str);
@@ -2157,13 +2344,16 @@ rb_str_times(VALUE str, VALUE times)
*
* Returns the result of formatting +object+ into the format specification +self+
* (see Kernel#sprintf for formatting details):
+ *
* "%05d" % 123 # => "00123"
*
* 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
@@ -2181,7 +2371,7 @@ static inline void
rb_check_lockedtmp(VALUE str)
{
if (FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
+ rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
}
}
@@ -2196,10 +2386,10 @@ static inline int
str_dependent_p(VALUE str)
{
if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
- return 0;
+ return 0;
}
else {
- return 1;
+ return 1;
}
}
@@ -2219,19 +2409,19 @@ str_make_independent_expand(VALUE str, long len, long expand, const int termlen)
if (len > capa) len = capa;
- if (!STR_EMBED_P(str) && STR_EMBEDDABLE_P(capa, termlen)) {
- ptr = RSTRING(str)->as.heap.ptr;
- STR_SET_EMBED(str);
- memcpy(RSTRING(str)->as.ary, ptr, len);
- TERM_FILL(RSTRING(str)->as.ary + len, termlen);
- STR_SET_EMBED_LEN(str, len);
- return;
+ if (!STR_EMBED_P(str) && str_embed_capa(str) >= capa + termlen) {
+ ptr = RSTRING(str)->as.heap.ptr;
+ STR_SET_EMBED(str);
+ memcpy(RSTRING(str)->as.embed.ary, ptr, len);
+ TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
+ STR_SET_EMBED_LEN(str, len);
+ return;
}
ptr = ALLOC_N(char, (size_t)capa + termlen);
oldptr = RSTRING_PTR(str);
if (oldptr) {
- memcpy(ptr, oldptr, len);
+ memcpy(ptr, oldptr, len);
}
if (FL_TEST_RAW(str, STR_NOEMBED|STR_NOFREE|STR_SHARED) == STR_NOEMBED) {
xfree(oldptr);
@@ -2248,7 +2438,7 @@ void
rb_str_modify(VALUE str)
{
if (!str_independent(str))
- str_make_independent(str);
+ str_make_independent(str);
ENC_CODERANGE_CLEAR(str);
}
@@ -2259,17 +2449,17 @@ rb_str_modify_expand(VALUE str, long expand)
long len = RSTRING_LEN(str);
if (expand < 0) {
- rb_raise(rb_eArgError, "negative expanding string size");
+ rb_raise(rb_eArgError, "negative expanding string size");
}
if (expand >= LONG_MAX - len) {
- rb_raise(rb_eArgError, "string size too big");
+ rb_raise(rb_eArgError, "string size too big");
}
if (!str_independent(str)) {
- str_make_independent_expand(str, len, expand, termlen);
+ str_make_independent_expand(str, len, expand, termlen);
}
else if (expand > 0) {
- RESIZE_CAPA_TERM(str, len + expand, termlen);
+ RESIZE_CAPA_TERM(str, len + expand, termlen);
}
ENC_CODERANGE_CLEAR(str);
}
@@ -2279,10 +2469,10 @@ static void
str_modify_keep_cr(VALUE str)
{
if (!str_independent(str))
- str_make_independent(str);
+ str_make_independent(str);
if (ENC_CODERANGE(str) == ENC_CODERANGE_BROKEN)
- /* Force re-scan later */
- ENC_CODERANGE_CLEAR(str);
+ /* Force re-scan later */
+ ENC_CODERANGE_CLEAR(str);
}
static inline void
@@ -2290,9 +2480,9 @@ str_discard(VALUE str)
{
str_modifiable(str);
if (!STR_EMBED_P(str) && !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
- ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
- RSTRING(str)->as.heap.ptr = 0;
- RSTRING(str)->as.heap.len = 0;
+ ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
+ RSTRING(str)->as.heap.ptr = 0;
+ RSTRING(str)->as.heap.len = 0;
}
}
@@ -2300,8 +2490,11 @@ void
rb_must_asciicompat(VALUE str)
{
rb_encoding *enc = rb_enc_get(str);
+ if (!enc) {
+ rb_raise(rb_eTypeError, "not encoding capable object");
+ }
if (!rb_enc_asciicompat(enc)) {
- rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc));
+ rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc));
}
}
@@ -2310,8 +2503,8 @@ rb_string_value(volatile VALUE *ptr)
{
VALUE s = *ptr;
if (!RB_TYPE_P(s, T_STRING)) {
- s = rb_str_to_str(s);
- *ptr = s;
+ s = rb_str_to_str(s);
+ *ptr = s;
}
return s;
}
@@ -2327,7 +2520,7 @@ static int
zero_filled(const char *s, int n)
{
for (; n > 0; --n) {
- if (*s++) return 0;
+ if (*s++) return 0;
}
return 1;
}
@@ -2338,7 +2531,7 @@ str_null_char(const char *s, long len, const int minlen, rb_encoding *enc)
const char *e = s + len;
for (; s + minlen <= e; s += rb_enc_mbclen(s, e, enc)) {
- if (zero_filled(s, minlen)) return s;
+ if (zero_filled(s, minlen)) return s;
}
return 0;
}
@@ -2350,12 +2543,12 @@ str_fill_term(VALUE str, char *s, long len, int termlen)
* is allocated, like many other functions in this file.
*/
if (str_dependent_p(str)) {
- if (!zero_filled(s + len, termlen))
- str_make_independent_expand(str, len, 0L, termlen);
+ if (!zero_filled(s + len, termlen))
+ str_make_independent_expand(str, len, 0L, termlen);
}
else {
- TERM_FILL(s + len, termlen);
- return s;
+ TERM_FILL(s + len, termlen);
+ return s;
}
return RSTRING_PTR(str);
}
@@ -2368,22 +2561,22 @@ rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int terml
assert(capa >= len);
if (capa - len < termlen) {
- rb_check_lockedtmp(str);
- str_make_independent_expand(str, len, 0L, termlen);
+ rb_check_lockedtmp(str);
+ str_make_independent_expand(str, len, 0L, termlen);
}
else if (str_dependent_p(str)) {
- if (termlen > oldtermlen)
- str_make_independent_expand(str, len, 0L, termlen);
+ if (termlen > oldtermlen)
+ str_make_independent_expand(str, len, 0L, termlen);
}
else {
- if (!STR_EMBED_P(str)) {
- /* modify capa instead of realloc */
- assert(!FL_TEST((str), STR_SHARED));
- RSTRING(str)->as.heap.aux.capa = capa - termlen;
- }
- if (termlen > oldtermlen) {
- TERM_FILL(RSTRING_PTR(str) + len, termlen);
- }
+ if (!STR_EMBED_P(str)) {
+ /* modify capa instead of realloc */
+ assert(!FL_TEST((str), STR_SHARED));
+ RSTRING(str)->as.heap.aux.capa = capa - termlen;
+ }
+ if (termlen > oldtermlen) {
+ TERM_FILL(RSTRING_PTR(str) + len, termlen);
+ }
}
return;
@@ -2398,18 +2591,18 @@ str_null_check(VALUE str, int *w)
const int minlen = rb_enc_mbminlen(enc);
if (minlen > 1) {
- *w = 1;
- if (str_null_char(s, len, minlen, enc)) {
- return NULL;
- }
- return str_fill_term(str, s, len, minlen);
+ *w = 1;
+ if (str_null_char(s, len, minlen, enc)) {
+ return NULL;
+ }
+ return str_fill_term(str, s, len, minlen);
}
*w = 0;
if (!s || memchr(s, 0, len)) {
- return NULL;
+ return NULL;
}
if (s[len]) {
- s = str_fill_term(str, s, len, minlen);
+ s = str_fill_term(str, s, len, minlen);
}
return s;
}
@@ -2428,10 +2621,10 @@ rb_string_value_cstr(volatile VALUE *ptr)
int w;
char *s = str_null_check(str, &w);
if (!s) {
- if (w) {
- rb_raise(rb_eArgError, "string contains null char");
- }
- rb_raise(rb_eArgError, "string contains null byte");
+ if (w) {
+ rb_raise(rb_eArgError, "string contains null char");
+ }
+ rb_raise(rb_eArgError, "string contains null byte");
}
return s;
}
@@ -2460,7 +2653,7 @@ rb_check_string_type(VALUE str)
* 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>
+ * 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.
*/
@@ -2493,8 +2686,8 @@ str_nth_len(const char *p, const char *e, long *nthp, rb_encoding *enc)
if (ISASCII(*p)) {
p2 = search_nonascii(p, e2);
if (!p2) {
- nth -= e2 - p;
- *nthp = nth;
+ nth -= e2 - p;
+ *nthp = nth;
return (char *)e2;
}
nth -= p2 - p;
@@ -2530,9 +2723,9 @@ static char*
str_nth(const char *p, const char *e, long nth, rb_encoding *enc, int singlebyte)
{
if (singlebyte)
- p += nth;
+ p += nth;
else {
- p = str_nth_len(p, e, &nth, enc);
+ p = str_nth_len(p, e, &nth, enc);
}
if (!p) return 0;
if (p > e) p = e;
@@ -2552,7 +2745,7 @@ long
rb_str_offset(VALUE str, long pos)
{
return str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
- STR_ENC_GET(str), single_byte_optimizable(str));
+ STR_ENC_GET(str), single_byte_optimizable(str));
}
#ifdef NONASCII_MASK
@@ -2561,26 +2754,26 @@ str_utf8_nth(const char *p, const char *e, long *nthp)
{
long nth = *nthp;
if ((int)SIZEOF_VOIDP * 2 < e - p && (int)SIZEOF_VOIDP * 2 < nth) {
- const uintptr_t *s, *t;
- const uintptr_t lowbits = SIZEOF_VOIDP - 1;
- s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
- t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
- while (p < (const char *)s) {
- if (is_utf8_lead_byte(*p)) nth--;
- p++;
- }
- do {
- nth -= count_utf8_lead_bytes_with_word(s);
- s++;
- } while (s < t && (int)SIZEOF_VOIDP <= nth);
- p = (char *)s;
+ const uintptr_t *s, *t;
+ const uintptr_t lowbits = SIZEOF_VOIDP - 1;
+ s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
+ t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
+ while (p < (const char *)s) {
+ if (is_utf8_lead_byte(*p)) nth--;
+ p++;
+ }
+ do {
+ nth -= count_utf8_lead_bytes_with_word(s);
+ s++;
+ } while (s < t && (int)SIZEOF_VOIDP <= nth);
+ p = (char *)s;
}
while (p < e) {
- if (is_utf8_lead_byte(*p)) {
- if (nth == 0) break;
- nth--;
- }
- p++;
+ if (is_utf8_lead_byte(*p)) {
+ if (nth == 0) break;
+ nth--;
+ }
+ p++;
}
*nthp = nth;
return (char *)p;
@@ -2601,31 +2794,40 @@ rb_str_sublen(VALUE str, long pos)
if (single_byte_optimizable(str) || pos < 0)
return pos;
else {
- char *p = RSTRING_PTR(str);
+ char *p = RSTRING_PTR(str);
return enc_strlen(p, p + pos, STR_ENC_GET(str), ENC_CODERANGE(str));
}
}
-VALUE
-rb_str_subseq(VALUE str, long beg, long len)
+static VALUE
+str_subseq(VALUE str, long beg, long len)
{
VALUE str2;
- 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_String(str));
- RSTRING(str2)->as.heap.ptr += beg;
- olen = RSTRING(str2)->as.heap.len;
- if (olen > len) RSTRING(str2)->as.heap.len = len;
+ const long rstring_embed_capa_max = ((sizeof(struct RString) - offsetof(struct RString, as.embed.ary)) / sizeof(char)) - 1;
+
+ if (!SHARABLE_SUBSTRING_P(beg, len, RSTRING_LEN(str)) ||
+ len <= rstring_embed_capa_max) {
+ str2 = rb_str_new(RSTRING_PTR(str) + beg, len);
+ RB_GC_GUARD(str);
}
else {
- str2 = rb_str_new(RSTRING_PTR(str)+beg, len);
- RB_GC_GUARD(str);
+ str2 = str_new_shared(rb_cString, str);
+ ENC_CODERANGE_CLEAR(str2);
+ RSTRING(str2)->as.heap.ptr += beg;
+ if (RSTRING(str2)->as.heap.len > len) {
+ RSTRING(str2)->as.heap.len = len;
+ }
}
- rb_enc_cr_str_copy_for_substr(str2, str);
+ return str2;
+}
+VALUE
+rb_str_subseq(VALUE str, long beg, long len)
+{
+ VALUE str2 = str_subseq(str, beg, len);
+ rb_enc_cr_str_copy_for_substr(str2, str);
return str2;
}
@@ -2634,52 +2836,54 @@ rb_str_subpos(VALUE str, long beg, long *lenp)
{
long len = *lenp;
long slen = -1L;
- long blen = RSTRING_LEN(str);
+ const long blen = RSTRING_LEN(str);
rb_encoding *enc = STR_ENC_GET(str);
char *p, *s = RSTRING_PTR(str), *e = s + blen;
if (len < 0) return 0;
+ if (beg < 0 && -beg < 0) return 0;
if (!blen) {
- len = 0;
+ len = 0;
}
if (single_byte_optimizable(str)) {
- if (beg > blen) return 0;
- if (beg < 0) {
- beg += blen;
- if (beg < 0) return 0;
- }
- if (len > blen - beg)
- len = blen - beg;
- if (len < 0) return 0;
- p = s + beg;
- goto end;
+ if (beg > blen) return 0;
+ if (beg < 0) {
+ beg += blen;
+ if (beg < 0) return 0;
+ }
+ if (len > blen - beg)
+ len = blen - beg;
+ if (len < 0) return 0;
+ p = s + beg;
+ goto end;
}
if (beg < 0) {
- if (len > -beg) len = -beg;
- if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) {
- beg = -beg;
- while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
- p = e;
- if (!p) return 0;
- while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
- if (!p) return 0;
- len = e - p;
- goto end;
- }
- else {
- slen = str_strlen(str, enc);
- beg += slen;
- if (beg < 0) return 0;
- p = s + beg;
- if (len == 0) goto end;
- }
- }
- else if (beg > 0 && beg > RSTRING_LEN(str)) {
- return 0;
+ if (len > -beg) len = -beg;
+ if ((ENC_CODERANGE(str) == ENC_CODERANGE_VALID) &&
+ (-beg * rb_enc_mbmaxlen(enc) < blen / 8)) {
+ beg = -beg;
+ while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
+ p = e;
+ if (!p) return 0;
+ while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
+ if (!p) return 0;
+ len = e - p;
+ goto end;
+ }
+ else {
+ slen = str_strlen(str, enc);
+ beg += slen;
+ if (beg < 0) return 0;
+ p = s + beg;
+ if (len == 0) goto end;
+ }
+ }
+ else if (beg > 0 && beg > blen) {
+ return 0;
}
if (len == 0) {
- if (beg > str_strlen(str, enc)) return 0; /* str's enc */
- p = s + beg;
+ if (beg > str_strlen(str, enc)) return 0; /* str's enc */
+ p = s + beg;
}
#ifdef NONASCII_MASK
else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
@@ -2690,23 +2894,23 @@ rb_str_subpos(VALUE str, long beg, long *lenp)
}
#endif
else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- int char_sz = rb_enc_mbmaxlen(enc);
+ int char_sz = rb_enc_mbmaxlen(enc);
- p = s + beg * char_sz;
- if (p > e) {
- return 0;
- }
+ p = s + beg * char_sz;
+ if (p > e) {
+ return 0;
+ }
else if (len * char_sz > e - p)
len = e - p;
else
- len *= char_sz;
+ len *= char_sz;
}
else if ((p = str_nth_len(s, e, &beg, enc)) == e) {
- if (beg > 0) return 0;
- len = 0;
+ if (beg > 0) return 0;
+ len = 0;
}
else {
- len = str_offset(p, e, len, enc, 0);
+ len = str_offset(p, e, len, enc, 0);
}
end:
*lenp = len;
@@ -2725,26 +2929,15 @@ rb_str_substr(VALUE str, long beg, long len)
static VALUE
str_substr(VALUE str, long beg, long len, int empty)
{
- VALUE str2;
char *p = rb_str_subpos(str, beg, &len);
if (!p) return Qnil;
- if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) &&
- 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_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(p, len);
- RB_GC_GUARD(str);
- }
- rb_enc_cr_str_copy_for_substr(str2, str);
+ if (!len && !empty) return Qnil;
+
+ beg = p - RSTRING_PTR(str);
+ VALUE str2 = str_subseq(str, beg, len);
+ rb_enc_cr_str_copy_for_substr(str2, str);
return str2;
}
@@ -2763,16 +2956,16 @@ rb_str_freeze(VALUE str)
*
* Returns +self+ if +self+ is not frozen.
*
- * Otherwise. returns <tt>self.dup</tt>, which is not frozen.
+ * Otherwise returns <tt>self.dup</tt>, which is not frozen.
*/
static VALUE
str_uplus(VALUE str)
{
if (OBJ_FROZEN(str)) {
- return rb_str_dup(str);
+ return rb_str_dup(str);
}
else {
- return str;
+ return str;
}
}
@@ -2783,7 +2976,9 @@ str_uplus(VALUE str)
* Returns a frozen, possibly pre-existing copy of the string.
*
* The returned \String will be deduplicated as long as it does not have
- * any instance variables set on it.
+ * any instance variables set on it and is not a String subclass.
+ *
+ * String#dedup is an alias for String#-@.
*/
static VALUE
str_uminus(VALUE str)
@@ -2801,7 +2996,7 @@ VALUE
rb_str_locktmp(VALUE str)
{
if (FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "temporal locking already locked string");
+ rb_raise(rb_eRuntimeError, "temporal locking already locked string");
}
FL_SET(str, STR_TMPLOCK);
return str;
@@ -2811,7 +3006,7 @@ VALUE
rb_str_unlocktmp(VALUE str)
{
if (!FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
+ rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
}
FL_UNSET(str, STR_TMPLOCK);
return str;
@@ -2832,11 +3027,38 @@ rb_str_set_len(VALUE str, long len)
str_modifiable(str);
if (STR_SHARED_P(str)) {
- rb_raise(rb_eRuntimeError, "can't set length of shared string");
+ rb_raise(rb_eRuntimeError, "can't set length of shared string");
}
if (len > (capa = (long)str_capacity(str, termlen)) || len < 0) {
- rb_bug("probable buffer overflow: %ld for %ld", len, capa);
+ rb_bug("probable buffer overflow: %ld for %ld", len, capa);
+ }
+
+ int cr = ENC_CODERANGE(str);
+ if (cr == ENC_CODERANGE_UNKNOWN) {
+ /* Leave unknown. */
+ }
+ else if (len > RSTRING_LEN(str)) {
+ if (ENC_CODERANGE_CLEAN_P(cr)) {
+ /* Update the coderange regarding the extended part. */
+ const char *const prev_end = RSTRING_END(str);
+ const char *const new_end = RSTRING_PTR(str) + len;
+ rb_encoding *enc = rb_enc_get(str);
+ rb_str_coderange_scan_restartable(prev_end, new_end, enc, &cr);
+ ENC_CODERANGE_SET(str, cr);
+ }
+ else if (cr == ENC_CODERANGE_BROKEN) {
+ /* May be valid now, by appended part. */
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
+ }
}
+ else if (len < RSTRING_LEN(str)) {
+ if (cr != ENC_CODERANGE_7BIT) {
+ /* ASCII-only string is keeping after truncated. Valid
+ * and broken may be invalid or valid, leave unknown. */
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
+ }
+ }
+
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], termlen);
}
@@ -2844,93 +3066,102 @@ rb_str_set_len(VALUE str, long len)
VALUE
rb_str_resize(VALUE str, long len)
{
- long slen;
- int independent;
-
if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
}
- independent = str_independent(str);
- ENC_CODERANGE_CLEAR(str);
- slen = RSTRING_LEN(str);
+ int independent = str_independent(str);
+ long slen = RSTRING_LEN(str);
+
+ if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
+ ENC_CODERANGE_CLEAR(str);
+ }
{
- long capa;
- const int termlen = TERM_LEN(str);
- if (STR_EMBED_P(str)) {
- if (len == slen) return str;
- if (STR_EMBEDDABLE_P(len, termlen)) {
- STR_SET_EMBED_LEN(str, len);
- TERM_FILL(RSTRING(str)->as.ary + len, termlen);
- return str;
- }
- str_make_independent_expand(str, slen, len - slen, termlen);
- }
- else if (STR_EMBEDDABLE_P(len, termlen)) {
- char *ptr = STR_HEAP_PTR(str);
- STR_SET_EMBED(str);
- if (slen > len) slen = len;
- if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, slen);
- TERM_FILL(RSTRING(str)->as.ary + len, termlen);
- STR_SET_EMBED_LEN(str, len);
- if (independent) ruby_xfree(ptr);
- return str;
- }
- else if (!independent) {
- if (len == slen) return str;
- str_make_independent_expand(str, slen, len - slen, termlen);
- }
- else if ((capa = RSTRING(str)->as.heap.aux.capa) < len ||
- (capa - len) > (len < 1024 ? len : 1024)) {
- SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
- (size_t)len + termlen, STR_HEAP_SIZE(str));
- RSTRING(str)->as.heap.aux.capa = len;
- }
- else if (len == slen) return str;
- RSTRING(str)->as.heap.len = len;
- TERM_FILL(RSTRING(str)->as.heap.ptr + len, termlen); /* sentinel */
+ long capa;
+ const int termlen = TERM_LEN(str);
+ if (STR_EMBED_P(str)) {
+ if (len == slen) return str;
+ if (str_embed_capa(str) >= len + termlen) {
+ STR_SET_EMBED_LEN(str, len);
+ TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
+ return str;
+ }
+ str_make_independent_expand(str, slen, len - slen, termlen);
+ }
+ else if (str_embed_capa(str) >= len + termlen) {
+ char *ptr = STR_HEAP_PTR(str);
+ STR_SET_EMBED(str);
+ if (slen > len) slen = len;
+ if (slen > 0) MEMCPY(RSTRING(str)->as.embed.ary, ptr, char, slen);
+ TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
+ STR_SET_EMBED_LEN(str, len);
+ if (independent) ruby_xfree(ptr);
+ return str;
+ }
+ else if (!independent) {
+ if (len == slen) return str;
+ str_make_independent_expand(str, slen, len - slen, termlen);
+ }
+ else if ((capa = RSTRING(str)->as.heap.aux.capa) < len ||
+ (capa - len) > (len < 1024 ? len : 1024)) {
+ SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
+ (size_t)len + termlen, STR_HEAP_SIZE(str));
+ RSTRING(str)->as.heap.aux.capa = len;
+ }
+ else if (len == slen) return str;
+ RSTRING(str)->as.heap.len = len;
+ TERM_FILL(RSTRING(str)->as.heap.ptr + len, termlen); /* sentinel */
}
return str;
}
static VALUE
-str_buf_cat(VALUE str, const char *ptr, long len)
+str_buf_cat4(VALUE str, const char *ptr, long len, bool keep_cr)
{
+ if (keep_cr) {
+ str_modify_keep_cr(str);
+ }
+ else {
+ rb_str_modify(str);
+ }
+ if (len == 0) return 0;
+
long capa, total, olen, off = -1;
char *sptr;
const int termlen = TERM_LEN(str);
+#if !USE_RVARGC
assert(termlen < RSTRING_EMBED_LEN_MAX + 1); /* < (LONG_MAX/2) */
+#endif
RSTRING_GETMEM(str, sptr, olen);
if (ptr >= sptr && ptr <= sptr + olen) {
off = ptr - sptr;
}
- rb_str_modify(str);
- if (len == 0) return 0;
+
if (STR_EMBED_P(str)) {
- capa = RSTRING_EMBED_LEN_MAX + 1 - termlen;
- sptr = RSTRING(str)->as.ary;
- olen = RSTRING_EMBED_LEN(str);
+ capa = str_embed_capa(str) - termlen;
+ sptr = RSTRING(str)->as.embed.ary;
+ olen = RSTRING_EMBED_LEN(str);
}
else {
- capa = RSTRING(str)->as.heap.aux.capa;
- sptr = RSTRING(str)->as.heap.ptr;
- olen = RSTRING(str)->as.heap.len;
+ capa = RSTRING(str)->as.heap.aux.capa;
+ sptr = RSTRING(str)->as.heap.ptr;
+ olen = RSTRING(str)->as.heap.len;
}
if (olen > LONG_MAX - len) {
- rb_raise(rb_eArgError, "string sizes too big");
+ rb_raise(rb_eArgError, "string sizes too big");
}
total = olen + len;
if (capa < total) {
- if (total >= LONG_MAX / 2) {
- capa = total;
- }
- while (total > capa) {
- capa = 2 * capa + termlen; /* == 2*(capa+termlen)-termlen */
- }
- RESIZE_CAPA_TERM(str, capa, termlen);
- sptr = RSTRING_PTR(str);
+ if (total >= LONG_MAX / 2) {
+ capa = total;
+ }
+ while (total > capa) {
+ capa = 2 * capa + termlen; /* == 2*(capa+termlen)-termlen */
+ }
+ RESIZE_CAPA_TERM(str, capa, termlen);
+ sptr = RSTRING_PTR(str);
}
if (off != -1) {
ptr = sptr + off;
@@ -2942,14 +3173,15 @@ str_buf_cat(VALUE str, const char *ptr, long len)
return str;
}
-#define str_buf_cat2(str, ptr) str_buf_cat((str), (ptr), strlen(ptr))
+#define str_buf_cat(str, ptr, len) str_buf_cat4((str), (ptr), len, false)
+#define str_buf_cat2(str, ptr) str_buf_cat4((str), (ptr), rb_strlen_lit(ptr), false)
VALUE
rb_str_cat(VALUE str, const char *ptr, long len)
{
if (len == 0) return str;
if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
}
return str_buf_cat(str, ptr, len);
}
@@ -2977,26 +3209,27 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
str_cr = RSTRING_LEN(str) ? ENC_CODERANGE(str) : ENC_CODERANGE_7BIT;
if (str_encindex == ptr_encindex) {
- if (str_cr != ENC_CODERANGE_UNKNOWN && ptr_cr == ENC_CODERANGE_UNKNOWN) {
+ if (str_cr != ENC_CODERANGE_UNKNOWN && ptr_cr == ENC_CODERANGE_UNKNOWN) {
ptr_cr = coderange_scan(ptr, len, rb_enc_from_index(ptr_encindex));
}
}
else {
- str_enc = rb_enc_from_index(str_encindex);
- ptr_enc = rb_enc_from_index(ptr_encindex);
+ str_enc = rb_enc_from_index(str_encindex);
+ ptr_enc = rb_enc_from_index(ptr_encindex);
if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
if (len == 0)
return str;
if (RSTRING_LEN(str) == 0) {
rb_str_buf_cat(str, ptr, len);
ENCODING_CODERANGE_SET(str, ptr_encindex, ptr_cr);
+ rb_str_change_terminator_length(str, rb_enc_mbminlen(str_enc), rb_enc_mbminlen(ptr_enc));
return str;
}
goto incompatible;
}
- if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
- ptr_cr = coderange_scan(ptr, len, ptr_enc);
- }
+ if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
+ ptr_cr = coderange_scan(ptr, len, ptr_enc);
+ }
if (str_cr == ENC_CODERANGE_UNKNOWN) {
if (ENCODING_IS_ASCII8BIT(str) || ptr_cr != ENC_CODERANGE_7BIT) {
str_cr = rb_enc_str_coderange(str);
@@ -3009,8 +3242,8 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
if (str_encindex != ptr_encindex &&
str_cr != ENC_CODERANGE_7BIT &&
ptr_cr != ENC_CODERANGE_7BIT) {
- str_enc = rb_enc_from_index(str_encindex);
- ptr_enc = rb_enc_from_index(ptr_encindex);
+ str_enc = rb_enc_from_index(str_encindex);
+ ptr_enc = rb_enc_from_index(ptr_encindex);
goto incompatible;
}
@@ -3030,10 +3263,10 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
}
else if (str_cr == ENC_CODERANGE_VALID) {
res_encindex = str_encindex;
- if (ENC_CODERANGE_CLEAN_P(ptr_cr))
- res_cr = str_cr;
- else
- res_cr = ptr_cr;
+ if (ENC_CODERANGE_CLEAN_P(ptr_cr))
+ res_cr = str_cr;
+ else
+ res_cr = ptr_cr;
}
else { /* str_cr == ENC_CODERANGE_BROKEN */
res_encindex = str_encindex;
@@ -3042,7 +3275,7 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
}
if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
}
str_buf_cat(str, ptr, len);
ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
@@ -3088,9 +3321,28 @@ rb_str_buf_cat_ascii(VALUE str, const char *ptr)
VALUE
rb_str_buf_append(VALUE str, VALUE str2)
{
- int str2_cr;
+ int str2_cr = rb_enc_str_coderange(str2);
- str2_cr = ENC_CODERANGE(str2);
+ if (str_enc_fastpath(str)) {
+ switch (str2_cr) {
+ case ENC_CODERANGE_7BIT:
+ // If RHS is 7bit we can do simple concatenation
+ str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2), true);
+ RB_GC_GUARD(str2);
+ return str;
+ case ENC_CODERANGE_VALID:
+ // If RHS is valid, we can do simple concatenation if encodings are the same
+ if (ENCODING_GET_INLINED(str) == ENCODING_GET_INLINED(str2)) {
+ str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2), true);
+ int str_cr = ENC_CODERANGE(str);
+ if (UNLIKELY(str_cr != ENC_CODERANGE_VALID)) {
+ ENC_CODERANGE_SET(str, RB_ENC_CODERANGE_AND(str_cr, str2_cr));
+ }
+ RB_GC_GUARD(str2);
+ return str;
+ }
+ }
+ }
rb_enc_cr_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
ENCODING_GET(str2), str2_cr, &str2_cr);
@@ -3121,41 +3373,41 @@ rb_str_concat_literals(size_t num, const VALUE *strary)
for (i = 0; i < num; ++i) { len += RSTRING_LEN(strary[i]); }
if (LIKELY(len < MIN_PRE_ALLOC_SIZE)) {
- str = rb_str_resurrect(strary[0]);
- s = 1;
+ str = rb_str_resurrect(strary[0]);
+ s = 1;
}
else {
- str = rb_str_buf_new(len);
- rb_enc_copy(str, strary[0]);
- s = 0;
+ str = rb_str_buf_new(len);
+ rb_enc_copy(str, strary[0]);
+ s = 0;
}
for (i = s; i < num; ++i) {
- const VALUE v = strary[i];
- int encidx = ENCODING_GET(v);
+ const VALUE v = strary[i];
+ int encidx = ENCODING_GET(v);
- rb_enc_cr_str_buf_cat(str, RSTRING_PTR(v), RSTRING_LEN(v),
- encidx, ENC_CODERANGE(v), NULL);
- if (encidx != ENCINDEX_US_ASCII) {
- if (ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII)
- rb_enc_set_index(str, encidx);
- }
+ rb_str_buf_append(str, v);
+ if (encidx != ENCINDEX_US_ASCII) {
+ if (ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII)
+ rb_enc_set_index(str, encidx);
+ }
}
return str;
}
/*
* call-seq:
- * string.concat(*objects) -> new_string
+ * concat(*objects) -> string
*
- * Returns a new \String containing the concatenation
- * of +self+ and all objects in +objects+:
+ * Concatenates each object in +objects+ to +self+ and returns +self+:
*
* s = 'foo'
* s.concat('bar', 'baz') # => "foobarbaz"
+ * s # => "foobarbaz"
*
* For each given object +object+ that is an \Integer,
* the value is considered a codepoint and converted to a character before concatenation:
+ *
* s = 'foo'
* s.concat(32, 'bar', 32, 'baz') # => "foo bar baz"
*
@@ -3167,16 +3419,16 @@ rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
str_modifiable(str);
if (argc == 1) {
- return rb_str_concat(str, argv[0]);
+ return rb_str_concat(str, argv[0]);
}
else if (argc > 1) {
- int i;
- VALUE arg_str = rb_str_tmp_new(0);
- rb_enc_copy(arg_str, str);
- for (i = 0; i < argc; i++) {
- rb_str_concat(arg_str, argv[i]);
- }
- rb_str_buf_append(str, arg_str);
+ int i;
+ VALUE arg_str = rb_str_tmp_new(0);
+ rb_enc_copy(arg_str, str);
+ for (i = 0; i < argc; i++) {
+ rb_str_concat(arg_str, argv[i]);
+ }
+ rb_str_buf_append(str, arg_str);
}
return str;
@@ -3184,15 +3436,17 @@ rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * string << object -> str
+ * string << object -> string
+ *
+ * Concatenates +object+ to +self+ and returns +self+:
*
- * Returns a new \String containing the concatenation
- * of +self+ and +object+:
* s = 'foo'
* s << 'bar' # => "foobar"
+ * s # => "foobar"
*
* If +object+ is an \Integer,
* the value is considered a codepoint and converted to a character before concatenation:
+ *
* s = 'foo'
* s << 33 # => "foo!"
*
@@ -3206,70 +3460,91 @@ rb_str_concat(VALUE str1, VALUE str2)
int encidx;
if (RB_INTEGER_TYPE_P(str2)) {
- if (rb_num_to_uint(str2, &code) == 0) {
- }
- else if (FIXNUM_P(str2)) {
- rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2));
- }
- else {
- rb_raise(rb_eRangeError, "bignum out of char range");
- }
+ if (rb_num_to_uint(str2, &code) == 0) {
+ }
+ else if (FIXNUM_P(str2)) {
+ rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2));
+ }
+ else {
+ rb_raise(rb_eRangeError, "bignum out of char range");
+ }
}
else {
- return rb_str_append(str1, str2);
+ return rb_str_append(str1, str2);
}
- encidx = rb_enc_to_index(enc);
- if (encidx == ENCINDEX_ASCII || encidx == ENCINDEX_US_ASCII) {
- /* US-ASCII automatically extended to ASCII-8BIT */
- char buf[1];
- buf[0] = (char)code;
- if (code > 0xFF) {
- rb_raise(rb_eRangeError, "%u out of char range", code);
- }
- rb_str_cat(str1, buf, 1);
- if (encidx == ENCINDEX_US_ASCII && code > 127) {
- rb_enc_associate_index(str1, ENCINDEX_ASCII);
- ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID);
- }
+ encidx = rb_ascii8bit_appendable_encoding_index(enc, code);
+ if (encidx >= 0) {
+ char buf[1];
+ buf[0] = (char)code;
+ rb_str_cat(str1, buf, 1);
+ if (encidx != rb_enc_to_index(enc)) {
+ rb_enc_associate_index(str1, encidx);
+ ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID);
+ }
}
else {
- long pos = RSTRING_LEN(str1);
- int cr = ENC_CODERANGE(str1);
- int len;
- char *buf;
-
- switch (len = rb_enc_codelen(code, enc)) {
- case ONIGERR_INVALID_CODE_POINT_VALUE:
- rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
- break;
- case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
- case 0:
- rb_raise(rb_eRangeError, "%u out of char range", code);
- break;
- }
- buf = ALLOCA_N(char, len + 1);
- rb_enc_mbcput(code, buf, enc);
- if (rb_enc_precise_mbclen(buf, buf + len + 1, enc) != len) {
- rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
- }
- rb_str_resize(str1, pos+len);
- memcpy(RSTRING_PTR(str1) + pos, buf, len);
- if (cr == ENC_CODERANGE_7BIT && code > 127)
- cr = ENC_CODERANGE_VALID;
- ENC_CODERANGE_SET(str1, cr);
+ long pos = RSTRING_LEN(str1);
+ int cr = ENC_CODERANGE(str1);
+ int len;
+ char *buf;
+
+ switch (len = rb_enc_codelen(code, enc)) {
+ case ONIGERR_INVALID_CODE_POINT_VALUE:
+ rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
+ break;
+ case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
+ case 0:
+ rb_raise(rb_eRangeError, "%u out of char range", code);
+ break;
+ }
+ buf = ALLOCA_N(char, len + 1);
+ rb_enc_mbcput(code, buf, enc);
+ if (rb_enc_precise_mbclen(buf, buf + len + 1, enc) != len) {
+ rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
+ }
+ rb_str_resize(str1, pos+len);
+ memcpy(RSTRING_PTR(str1) + pos, buf, len);
+ if (cr == ENC_CODERANGE_7BIT && code > 127) {
+ cr = ENC_CODERANGE_VALID;
+ }
+ else if (cr == ENC_CODERANGE_BROKEN) {
+ cr = ENC_CODERANGE_UNKNOWN;
+ }
+ ENC_CODERANGE_SET(str1, cr);
}
return str1;
}
+int
+rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code)
+{
+ int encidx = rb_enc_to_index(enc);
+
+ if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII) {
+ /* US-ASCII automatically extended to ASCII-8BIT */
+ if (code > 0xFF) {
+ rb_raise(rb_eRangeError, "%u out of char range", code);
+ }
+ if (encidx == ENCINDEX_US_ASCII && code > 127) {
+ return ENCINDEX_ASCII_8BIT;
+ }
+ return encidx;
+ }
+ else {
+ return -1;
+ }
+}
+
/*
* call-seq:
- * string.prepend(*other_strings) -> str
+ * prepend(*other_strings) -> string
+ *
+ * Prepends each string in +other_strings+ to +self+ and returns +self+:
*
- * Returns a new \String containing the concatenation
- * of all given +other_strings+ and +self+:
* s = 'foo'
* s.prepend('bar', 'baz') # => "barbazfoo"
+ * s # => "barbazfoo"
*
* Related: String#concat.
*/
@@ -3280,16 +3555,16 @@ rb_str_prepend_multi(int argc, VALUE *argv, VALUE str)
str_modifiable(str);
if (argc == 1) {
- rb_str_update(str, 0L, 0L, argv[0]);
+ rb_str_update(str, 0L, 0L, argv[0]);
}
else if (argc > 1) {
- int i;
- VALUE arg_str = rb_str_tmp_new(0);
- rb_enc_copy(arg_str, str);
- for (i = 0; i < argc; i++) {
- rb_str_append(arg_str, argv[i]);
- }
- rb_str_update(str, 0L, 0L, arg_str);
+ int i;
+ VALUE arg_str = rb_str_tmp_new(0);
+ rb_enc_copy(arg_str, str);
+ for (i = 0; i < argc; i++) {
+ rb_str_append(arg_str, argv[i]);
+ }
+ rb_str_update(str, 0L, 0L, arg_str);
}
return str;
@@ -3299,8 +3574,8 @@ st_index_t
rb_str_hash(VALUE str)
{
int e = ENCODING_GET(str);
- if (e && rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
- e = 0;
+ if (e && is_ascii_string(str)) {
+ e = 0;
}
return rb_memhash((const void *)RSTRING_PTR(str), RSTRING_LEN(str)) ^ e;
}
@@ -3313,18 +3588,18 @@ rb_str_hash_cmp(VALUE str1, VALUE str2)
RSTRING_GETMEM(str1, ptr1, len1);
RSTRING_GETMEM(str2, ptr2, len2);
return (len1 != len2 ||
- !rb_str_comparable(str1, str2) ||
- memcmp(ptr1, ptr2, len1) != 0);
+ !rb_str_comparable(str1, str2) ||
+ memcmp(ptr1, ptr2, len1) != 0);
}
/*
* call-seq:
- * string.hash -> integer
+ * hash -> integer
*
* Returns the integer hash value for +self+.
* The value is based on the length, content and encoding of +self+.
*
- * Related: Object#hash
+ * Related: Object#hash.
*/
static VALUE
@@ -3350,13 +3625,13 @@ rb_str_comparable(VALUE str1, VALUE str2)
rc1 = rb_enc_str_coderange(str1);
rc2 = rb_enc_str_coderange(str2);
if (rc1 == ENC_CODERANGE_7BIT) {
- if (rc2 == ENC_CODERANGE_7BIT) return TRUE;
- if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
- return TRUE;
+ if (rc2 == ENC_CODERANGE_7BIT) return TRUE;
+ if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
+ return TRUE;
}
if (rc2 == ENC_CODERANGE_7BIT) {
- if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
- return TRUE;
+ if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
+ return TRUE;
}
return FALSE;
}
@@ -3372,16 +3647,16 @@ rb_str_cmp(VALUE str1, VALUE str2)
RSTRING_GETMEM(str1, ptr1, len1);
RSTRING_GETMEM(str2, ptr2, len2);
if (ptr1 == ptr2 || (retval = memcmp(ptr1, ptr2, lesser(len1, len2))) == 0) {
- if (len1 == len2) {
- if (!rb_str_comparable(str1, str2)) {
- if (ENCODING_GET(str1) > ENCODING_GET(str2))
- return 1;
- return -1;
- }
- return 0;
- }
- if (len1 > len2) return 1;
- return -1;
+ if (len1 == len2) {
+ if (!rb_str_comparable(str1, str2)) {
+ if (ENCODING_GET(str1) > ENCODING_GET(str2))
+ return 1;
+ return -1;
+ }
+ return 0;
+ }
+ if (len1 > len2) return 1;
+ return -1;
}
if (retval > 0) return 1;
return -1;
@@ -3394,6 +3669,7 @@ rb_str_cmp(VALUE str1, VALUE str2)
*
* Returns +true+ if +object+ has the same length and content;
* as +self+; +false+ otherwise:
+ *
* s = 'foo'
* s == 'foo' # => true
* s == 'food' # => false
@@ -3411,27 +3687,30 @@ rb_str_equal(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) {
- if (!rb_respond_to(str2, idTo_str)) {
- return Qfalse;
- }
- return rb_equal(str2, str1);
+ if (!rb_respond_to(str2, idTo_str)) {
+ return Qfalse;
+ }
+ return rb_equal(str2, str1);
}
return rb_str_eql_internal(str1, str2);
}
/*
* call-seq:
- * string.eql?(object) -> true or false
+ * eql?(object) -> true or false
*
* Returns +true+ if +object+ has the same length and content;
* as +self+; +false+ otherwise:
+ *
* s = 'foo'
* s.eql?('foo') # => true
* s.eql?('food') # => false
* s.eql?('FOO') # => false
*
* Returns +false+ if the two strings' encodings are not compatible:
+ *
* "\u{e4 f6 fc}".encode("ISO-8859-1").eql?("\u{c4 d6 dc}") # => false
+ *
*/
MJIT_FUNC_EXPORTED VALUE
@@ -3447,18 +3726,21 @@ rb_str_eql(VALUE str1, VALUE str2)
* string <=> other_string -> -1, 0, 1, or nil
*
* 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.
*
* Examples:
+ *
* 'foo' <=> 'foo' # => 0
* 'foo' <=> 'food' # => -1
* 'food' <=> 'foo' # => 1
* 'FOO' <=> 'foo' # => -1
* 'foo' <=> 'FOO' # => 1
* 'foo' <=> 1 # => nil
+ *
*/
static VALUE
@@ -3467,7 +3749,7 @@ rb_str_cmp_m(VALUE str1, VALUE str2)
int result;
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
- return rb_invcmp(str1, str2);
+ return rb_invcmp(str1, str2);
}
result = rb_str_cmp(str1, s);
return INT2FIX(result);
@@ -3478,21 +3760,28 @@ static VALUE str_casecmp_p(VALUE str1, VALUE str2);
/*
* call-seq:
- * str.casecmp(other_str) -> -1, 0, 1, or nil
+ * casecmp(other_string) -> -1, 0, 1, or nil
*
- * Compares +self+ and +other_string+, ignoring case, and returning:
- * - -1 if +other_string+ is larger.
+ * Compares <tt>self.downcase</tt> and <tt>other_string.downcase</tt>; returns:
+ *
+ * - -1 if <tt>other_string.downcase</tt> is larger.
* - 0 if the two are equal.
- * - 1 if +other_string+ is smaller.
+ * - 1 if <tt>other_string.downcase</tt> is smaller.
* - +nil+ if the two are incomparable.
*
* 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
+ *
+ * See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#casecmp?.
+ *
*/
static VALUE
@@ -3500,7 +3789,7 @@ rb_str_casecmp(VALUE str1, VALUE str2)
{
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
- return Qnil;
+ return Qnil;
}
return str_casecmp(str1, s);
}
@@ -3514,25 +3803,25 @@ str_casecmp(VALUE str1, VALUE str2)
enc = rb_enc_compatible(str1, str2);
if (!enc) {
- return Qnil;
+ return Qnil;
}
p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
- while (p1 < p1end && p2 < p2end) {
- if (*p1 != *p2) {
+ while (p1 < p1end && p2 < p2end) {
+ if (*p1 != *p2) {
unsigned int c1 = TOLOWER(*p1 & 0xff);
unsigned int c2 = TOLOWER(*p2 & 0xff);
if (c1 != c2)
return INT2FIX(c1 < c2 ? -1 : 1);
- }
- p1++;
- p2++;
- }
+ }
+ p1++;
+ p2++;
+ }
}
else {
- while (p1 < p1end && p2 < p2end) {
+ while (p1 < p1end && p2 < p2end) {
int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
@@ -3553,9 +3842,9 @@ str_casecmp(VALUE str1, VALUE str2)
if (l1 != l2)
return INT2FIX(l1 < l2 ? -1 : 1);
}
- p1 += l1;
- p2 += l2;
- }
+ p1 += l1;
+ p2 += l2;
+ }
}
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
@@ -3564,10 +3853,11 @@ str_casecmp(VALUE str1, VALUE str2)
/*
* call-seq:
- * string.casecmp?(other_string) -> true, false, or nil
+ * casecmp?(other_string) -> true, false, or nil
*
* Returns +true+ if +self+ and +other_string+ are equal after
* Unicode case folding, otherwise +false+:
+ *
* 'foo'.casecmp?('foo') # => true
* 'foo'.casecmp?('food') # => false
* 'food'.casecmp?('foo') # => false
@@ -3575,7 +3865,13 @@ str_casecmp(VALUE str1, VALUE str2)
* 'foo'.casecmp?('FOO') # => true
*
* Returns +nil+ if the two values are incomparable:
+ *
* 'foo'.casecmp?(1) # => nil
+ *
+ * See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#casecmp.
+ *
*/
static VALUE
@@ -3583,7 +3879,7 @@ rb_str_casecmp_p(VALUE str1, VALUE str2)
{
VALUE s = rb_check_string_type(str2);
if (NIL_P(s)) {
- return Qnil;
+ return Qnil;
}
return str_casecmp_p(str1, s);
}
@@ -3597,7 +3893,7 @@ str_casecmp_p(VALUE str1, VALUE str2)
enc = rb_enc_compatible(str1, str2);
if (!enc) {
- return Qnil;
+ return Qnil;
}
folded_str1 = rb_str_downcase(1, &fold_opt, str1);
@@ -3608,21 +3904,21 @@ str_casecmp_p(VALUE str1, VALUE str2)
static long
strseq_core(const char *str_ptr, const char *str_ptr_end, long str_len,
- const char *sub_ptr, long sub_len, long offset, rb_encoding *enc)
+ const char *sub_ptr, long sub_len, long offset, rb_encoding *enc)
{
const char *search_start = str_ptr;
long pos, search_len = str_len - offset;
for (;;) {
- const char *t;
- pos = rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc);
- if (pos < 0) return pos;
- t = rb_enc_right_char_head(search_start, search_start+pos, str_ptr_end, enc);
- if (t == search_start + pos) break;
- search_len -= t - search_start;
- if (search_len <= 0) return -1;
- offset += t - search_start;
- search_start = t;
+ const char *t;
+ pos = rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc);
+ if (pos < 0) return pos;
+ t = rb_enc_right_char_head(search_start, search_start+pos, str_ptr_end, enc);
+ if (t == search_start + pos) break;
+ search_len -= t - search_start;
+ if (search_len <= 0) return -1;
+ offset += t - search_start;
+ search_start = t;
}
return pos + offset;
}
@@ -3648,17 +3944,17 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
if (str_len < sub_len) return -1;
if (offset != 0) {
- long str_len_char, sub_len_char;
+ 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) {
- offset += str_len_char;
- if (offset < 0) return -1;
- }
- if (str_len_char - offset < sub_len_char) return -1;
- if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte);
- str_ptr += offset;
+ 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) {
+ offset += str_len_char;
+ if (offset < 0) return -1;
+ }
+ if (str_len_char - offset < sub_len_char) return -1;
+ if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte);
+ str_ptr += offset;
}
if (sub_len == 0) return offset;
@@ -3669,81 +3965,162 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
/*
* call-seq:
- * string.index(substring, offset = 0) -> integer or nil
- * string.index(regexp, offset = 0) -> integer or nil
+ * index(substring, offset = 0) -> integer or nil
+ * index(regexp, offset = 0) -> integer or nil
+ *
+ * :include: doc/string/index.rdoc
+ *
+ */
+
+static VALUE
+rb_str_index_m(int argc, VALUE *argv, VALUE str)
+{
+ VALUE sub;
+ VALUE initpos;
+ long pos;
+
+ if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
+ pos = NUM2LONG(initpos);
+ }
+ else {
+ pos = 0;
+ }
+ if (pos < 0) {
+ pos += str_strlen(str, NULL);
+ if (pos < 0) {
+ if (RB_TYPE_P(sub, T_REGEXP)) {
+ rb_backref_set(Qnil);
+ }
+ return Qnil;
+ }
+ }
+
+ if (RB_TYPE_P(sub, T_REGEXP)) {
+ if (pos > str_strlen(str, NULL)) {
+ rb_backref_set(Qnil);
+ return Qnil;
+ }
+ pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
+ rb_enc_check(str, sub), single_byte_optimizable(str));
+
+ 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);
+ }
+
+ if (pos == -1) return Qnil;
+ return LONG2NUM(pos);
+}
+
+/* whether given pos is valid character boundary or not
+ * Note that in this function, "character" means a code point
+ * (Unicode scalar value), not a grapheme cluster.
+ */
+static bool
+str_check_byte_pos(VALUE str, long pos)
+{
+ const char *s = RSTRING_PTR(str);
+ const char *e = RSTRING_END(str);
+ const char *p = s + pos;
+ const char *pp = rb_enc_left_char_head(s, p, e, rb_enc_get(str));
+ return p == pp;
+}
+
+/*
+ * call-seq:
+ * byteindex(substring, offset = 0) -> integer or nil
+ * byteindex(regexp, offset = 0) -> integer or nil
*
- * Returns the \Integer index of the first occurrence of the given +substring+,
+ * Returns the \Integer byte-based index of the first occurrence of the given +substring+,
* or +nil+ if none found:
- * 'foo'.index('f') # => 0
- * 'foo'.index('o') # => 1
- * 'foo'.index('oo') # => 1
- * 'foo'.index('ooo') # => nil
*
- * Returns the \Integer index of the first match for the given \Regexp +regexp+,
+ * 'foo'.byteindex('f') # => 0
+ * 'foo'.byteindex('o') # => 1
+ * 'foo'.byteindex('oo') # => 1
+ * 'foo'.byteindex('ooo') # => nil
+ *
+ * Returns the \Integer byte-based 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
*
- * \Integer argument +offset+, if given, specifies the position in the
+ * 'foo'.byteindex(/f/) # => 0
+ * 'foo'.byteindex(/o/) # => 1
+ * 'foo'.byteindex(/oo/) # => 1
+ * 'foo'.byteindex(/ooo/) # => nil
+ *
+ * \Integer argument +offset+, if given, specifies the byte-based position in the
* string to begin the search:
- * 'foo'.index('o', 1) # => 1
- * 'foo'.index('o', 2) # => 2
- * 'foo'.index('o', 3) # => nil
+ *
+ * 'foo'.byteindex('o', 1) # => 1
+ * 'foo'.byteindex('o', 2) # => 2
+ * 'foo'.byteindex('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
+ * 'foo'.byteindex('o', -1) # => 2
+ * 'foo'.byteindex('o', -2) # => 1
+ * 'foo'.byteindex('o', -3) # => 1
+ * 'foo'.byteindex('o', -4) # => nil
+ *
+ * If +offset+ does not land on character (codepoint) boundary, +IndexError+ is
+ * raised.
+ *
+ * Related: String#index, String#byterindex.
*/
static VALUE
-rb_str_index_m(int argc, VALUE *argv, VALUE str)
+rb_str_byteindex_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE initpos;
long pos;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
- pos = NUM2LONG(initpos);
+ long slen = RSTRING_LEN(str);
+ pos = NUM2LONG(initpos);
+ if (pos < 0) {
+ pos += slen;
+ }
+ if (pos < 0 || pos > slen) {
+ if (RB_TYPE_P(sub, T_REGEXP)) {
+ rb_backref_set(Qnil);
+ }
+ return Qnil;
+ }
}
else {
- pos = 0;
+ pos = 0;
}
- if (pos < 0) {
- pos += str_strlen(str, NULL);
- if (pos < 0) {
- if (RB_TYPE_P(sub, T_REGEXP)) {
- rb_backref_set(Qnil);
- }
- return Qnil;
- }
+
+ if (!str_check_byte_pos(str, pos)) {
+ rb_raise(rb_eIndexError,
+ "offset %ld does not land on character boundary", pos);
}
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));
-
- if (rb_reg_search(sub, str, pos, 0) < 0) {
+ 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));
+ pos = BEG(0);
return LONG2NUM(pos);
}
}
else {
StringValue(sub);
- pos = rb_str_index(str, sub, pos);
- pos = rb_str_sublen(str, pos);
+ pos = rb_strseq_index(str, sub, pos, 1);
}
if (pos == -1) return Qnil;
@@ -3752,39 +4129,39 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
#ifdef HAVE_MEMRCHR
static long
-str_rindex(VALUE str, VALUE sub, const char *s, long pos, rb_encoding *enc)
+str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
{
char *hit, *adjusted;
int c;
long slen, searchlen;
char *sbeg, *e, *t;
- slen = RSTRING_LEN(sub);
- if (slen == 0) return pos;
sbeg = RSTRING_PTR(str);
+ slen = RSTRING_LEN(sub);
+ if (slen == 0) return s - sbeg;
e = RSTRING_END(str);
t = RSTRING_PTR(sub);
c = *t & 0xff;
searchlen = s - sbeg + 1;
do {
- hit = memrchr(sbeg, c, searchlen);
- if (!hit) break;
- adjusted = rb_enc_left_char_head(sbeg, hit, e, enc);
- if (hit != adjusted) {
- searchlen = adjusted - sbeg;
- continue;
- }
- if (memcmp(hit, t, slen) == 0)
- return rb_str_sublen(str, hit - sbeg);
- searchlen = adjusted - sbeg;
+ hit = memrchr(sbeg, c, searchlen);
+ if (!hit) break;
+ adjusted = rb_enc_left_char_head(sbeg, hit, e, enc);
+ if (hit != adjusted) {
+ searchlen = adjusted - sbeg;
+ continue;
+ }
+ if (memcmp(hit, t, slen) == 0)
+ return hit - sbeg;
+ searchlen = adjusted - sbeg;
} while (searchlen > 0);
return -1;
}
#else
static long
-str_rindex(VALUE str, VALUE sub, const char *s, long pos, rb_encoding *enc)
+str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
{
long slen;
char *sbeg, *e, *t;
@@ -3795,12 +4172,11 @@ str_rindex(VALUE str, VALUE sub, const char *s, long pos, rb_encoding *enc)
slen = RSTRING_LEN(sub);
while (s) {
- if (memcmp(s, t, slen) == 0) {
- return pos;
- }
- if (pos == 0) break;
- pos--;
- s = rb_enc_prev_char(sbeg, s, e, enc);
+ if (memcmp(s, t, slen) == 0) {
+ return s - sbeg;
+ }
+ if (s <= sbeg) break;
+ s = rb_enc_prev_char(sbeg, s, e, enc);
}
return -1;
@@ -3829,24 +4205,24 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
sbeg = RSTRING_PTR(str);
if (pos == 0) {
- if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
- return 0;
- else
- return -1;
+ if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
+ return 0;
+ else
+ return -1;
}
s = str_nth(sbeg, RSTRING_END(str), pos, enc, singlebyte);
- return str_rindex(str, sub, s, pos, enc);
+ return rb_str_sublen(str, str_rindex(str, sub, s, enc));
}
-
/*
* call-seq:
- * string.rindex(substring, offset = self.length) -> integer or nil
- * string.rindex(regexp, offset = self.length) -> integer or nil
+ * rindex(substring, offset = self.length) -> integer or nil
+ * rindex(regexp, offset = self.length) -> integer or nil
*
* Returns the \Integer index of the _last_ occurrence of the given +substring+,
* or +nil+ if none found:
+ *
* 'foo'.rindex('f') # => 0
* 'foo'.rindex('o') # => 2
* 'foo'.rindex('oo') # => 1
@@ -3854,13 +4230,32 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
*
* 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.
+ *
+ * 'foo'.index(/o+(?!.*o)/) # => 1
+ * $~ #=> #<MatchData "oo">
+ *
* \Integer argument +offset+, if given and non-negative, specifies the maximum starting position in the
* string to _end_ the search:
+ *
* 'foo'.rindex('o', 0) # => nil
* 'foo'.rindex('o', 1) # => 1
* 'foo'.rindex('o', 2) # => 2
@@ -3868,12 +4263,13 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
*
* 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
+ * Related: String#index.
*/
static VALUE
@@ -3885,28 +4281,28 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
long pos, len = str_strlen(str, enc); /* str's enc */
if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
- pos = NUM2LONG(vpos);
- if (pos < 0) {
- pos += len;
- if (pos < 0) {
- if (RB_TYPE_P(sub, T_REGEXP)) {
- rb_backref_set(Qnil);
- }
- return Qnil;
- }
- }
- if (pos > len) pos = len;
+ pos = NUM2LONG(vpos);
+ if (pos < 0) {
+ pos += len;
+ if (pos < 0) {
+ if (RB_TYPE_P(sub, T_REGEXP)) {
+ rb_backref_set(Qnil);
+ }
+ return Qnil;
+ }
+ }
+ if (pos > len) pos = len;
}
else {
- pos = len;
+ pos = len;
}
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));
+ /* enc = rb_get_check(str, sub); */
+ pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
+ enc, single_byte_optimizable(str));
- if (rb_reg_search(sub, str, pos, 1) >= 0) {
+ 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));
@@ -3915,8 +4311,144 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
}
else {
StringValue(sub);
- pos = rb_str_rindex(str, sub, pos);
- if (pos >= 0) return LONG2NUM(pos);
+ pos = rb_str_rindex(str, sub, pos);
+ if (pos >= 0) return LONG2NUM(pos);
+ }
+ return Qnil;
+}
+
+static long
+rb_str_byterindex(VALUE str, VALUE sub, long pos)
+{
+ long len, slen;
+ char *sbeg, *s;
+ rb_encoding *enc;
+
+ enc = rb_enc_check(str, sub);
+ if (is_broken_string(sub)) return -1;
+ len = RSTRING_LEN(str);
+ slen = RSTRING_LEN(sub);
+
+ /* substring longer than string */
+ if (len < slen) return -1;
+ if (len - pos < slen) pos = len - slen;
+ if (len == 0) return pos;
+
+ sbeg = RSTRING_PTR(str);
+
+ if (pos == 0) {
+ if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+ s = sbeg + pos;
+ return str_rindex(str, sub, s, enc);
+}
+
+
+/*
+ * call-seq:
+ * byterindex(substring, offset = self.bytesize) -> integer or nil
+ * byterindex(regexp, offset = self.bytesize) -> integer or nil
+ *
+ * Returns the \Integer byte-based index of the _last_ occurrence of the given +substring+,
+ * or +nil+ if none found:
+ *
+ * 'foo'.byterindex('f') # => 0
+ * 'foo'.byterindex('o') # => 2
+ * 'foo'.byterindex('oo') # => 1
+ * 'foo'.byterindex('ooo') # => nil
+ *
+ * Returns the \Integer byte-based index of the _last_ match for the given \Regexp +regexp+,
+ * or +nil+ if none found:
+ *
+ * 'foo'.byterindex(/f/) # => 0
+ * 'foo'.byterindex(/o/) # => 2
+ * 'foo'.byterindex(/oo/) # => 1
+ * 'foo'.byterindex(/ooo/) # => nil
+ *
+ * The _last_ match means starting at the possible last position, not
+ * the last of longest matches.
+ *
+ * 'foo'.byterindex(/o+/) # => 2
+ * $~ #=> #<MatchData "o">
+ *
+ * To get the last longest match, needs to combine with negative
+ * lookbehind.
+ *
+ * 'foo'.byterindex(/(?<!o)o+/) # => 1
+ * $~ #=> #<MatchData "oo">
+ *
+ * Or String#byteindex with negative lookforward.
+ *
+ * 'foo'.byteindex(/o+(?!.*o)/) # => 1
+ * $~ #=> #<MatchData "oo">
+ *
+ * \Integer argument +offset+, if given and non-negative, specifies the maximum starting byte-based position in the
+ * string to _end_ the search:
+ *
+ * 'foo'.byterindex('o', 0) # => nil
+ * 'foo'.byterindex('o', 1) # => 1
+ * 'foo'.byterindex('o', 2) # => 2
+ * 'foo'.byterindex('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'.byterindex('o', -1) # => 2
+ * 'foo'.byterindex('o', -2) # => 1
+ * 'foo'.byterindex('o', -3) # => nil
+ * 'foo'.byterindex('o', -4) # => nil
+ *
+ * If +offset+ does not land on character (codepoint) boundary, +IndexError+ is
+ * raised.
+ *
+ * Related: String#byteindex.
+ */
+
+static VALUE
+rb_str_byterindex_m(int argc, VALUE *argv, VALUE str)
+{
+ VALUE sub;
+ VALUE vpos;
+ long pos, len = RSTRING_LEN(str);
+
+ if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
+ pos = NUM2LONG(vpos);
+ if (pos < 0) {
+ pos += len;
+ if (pos < 0) {
+ if (RB_TYPE_P(sub, T_REGEXP)) {
+ rb_backref_set(Qnil);
+ }
+ return Qnil;
+ }
+ }
+ if (pos > len) pos = len;
+ }
+ else {
+ pos = len;
+ }
+
+ if (!str_check_byte_pos(str, pos)) {
+ rb_raise(rb_eIndexError,
+ "offset %ld does not land on character boundary", pos);
+ }
+
+ if (RB_TYPE_P(sub, T_REGEXP)) {
+ if (rb_reg_search(sub, str, pos, 1) >= 0) {
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
+ pos = BEG(0);
+ return LONG2NUM(pos);
+ }
+ }
+ else {
+ StringValue(sub);
+ pos = rb_str_byterindex(str, sub, pos);
+ if (pos >= 0) return LONG2NUM(pos);
}
return Qnil;
}
@@ -3928,23 +4460,25 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
*
* Returns the \Integer index of the first substring that matches
* the given +regexp+, or +nil+ if no match found:
+ *
* 'foo' =~ /f/ # => 0
* 'foo' =~ /o/ # => 1
* 'foo' =~ /x/ # => nil
*
- * Note: also updates
- * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables].
+ * Note: also updates Regexp@Special+global+variables.
*
* If the given +object+ is not a \Regexp, returns the value
* returned by <tt>object =~ self</tt>.
*
* 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]):
+ * (see Regexp#=~):
+ *
* number= nil
* "no. 9" =~ /(?<number>\d+)/
* number # => nil (not assigned)
* /(?<number>\d+)/ =~ "no. 9"
* number #=> "9"
+ *
*/
static VALUE
@@ -3952,13 +4486,13 @@ rb_str_match(VALUE x, VALUE y)
{
switch (OBJ_BUILTIN_TYPE(y)) {
case T_STRING:
- rb_raise(rb_eTypeError, "type mismatch: String given");
+ rb_raise(rb_eTypeError, "type mismatch: String given");
case T_REGEXP:
- return rb_reg_match(y, x);
+ return rb_reg_match(y, x);
default:
- return rb_funcall(y, idEqTilde, 1, x);
+ return rb_funcall(y, idEqTilde, 1, x);
}
}
@@ -3968,13 +4502,12 @@ static VALUE get_pat(VALUE);
/*
* call-seq:
- * string.match(pattern, offset = 0) -> matchdata or nil
- * string.match(pattern, offset = 0) {|matchdata| ... } -> object
+ * match(pattern, offset = 0) -> matchdata or nil
+ * match(pattern, offset = 0) {|matchdata| ... } -> object
*
- * Returns a \Matchdata object (or +nil+) based on +self+ and the given +pattern+.
+ * Returns a \MatchData object (or +nil+) based on +self+ and the given +pattern+.
*
- * Note: also updates
- * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables].
+ * Note: also updates Regexp@Special+global+variables.
*
* - Computes +regexp+ by converting +pattern+ (if not already a \Regexp).
* regexp = Regexp.new(pattern)
@@ -3983,19 +4516,23 @@ static VALUE get_pat(VALUE);
* matchdata = <tt>regexp.match(self)
*
* With no block given, returns the computed +matchdata+:
+ *
* 'foo'.match('f') # => #<MatchData "f">
* 'foo'.match('o') # => #<MatchData "o">
* 'foo'.match('x') # => nil
*
* If \Integer argument +offset+ is given, the search begins at index +offset+:
+ *
* 'foo'.match('f', 1) # => nil
* 'foo'.match('o', 1) # => #<MatchData "o">
*
* With a block given, calls the block with the computed +matchdata+
* and returns the block's return value:
+ *
* 'foo'.match(/o/) {|matchdata| matchdata } # => #<MatchData "o">
* 'foo'.match(/x/) {|matchdata| matchdata } # => nil
* 'foo'.match(/f/, 1) {|matchdata| matchdata } # => nil
+ *
*/
static VALUE
@@ -4003,30 +4540,30 @@ rb_str_match_m(int argc, VALUE *argv, VALUE str)
{
VALUE re, result;
if (argc < 1)
- rb_check_arity(argc, 1, 2);
+ rb_check_arity(argc, 1, 2);
re = argv[0];
argv[0] = str;
result = rb_funcallv(get_pat(re), rb_intern("match"), argc, argv);
if (!NIL_P(result) && rb_block_given_p()) {
- return rb_yield(result);
+ return rb_yield(result);
}
return result;
}
/*
* call-seq:
- * string.match?(pattern, offset = 0) -> true or false
+ * match?(pattern, offset = 0) -> true or false
*
* Returns +true+ or +false+ based on whether a match is found for +self+ and +pattern+.
*
- * Note: does not update
- * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables].
+ * Note: does not update Regexp@Special+global+variables.
*
* Computes +regexp+ by converting +pattern+ (if not already a \Regexp).
* regexp = Regexp.new(pattern)
*
- * Returns +true+ if <tt>self+.match(regexp)</tt> returns a \Matchdata object,
+ * Returns +true+ if <tt>self+.match(regexp)</tt> returns a \MatchData object,
* +false+ otherwise:
+ *
* 'foo'.match?(/o/) # => true
* 'foo'.match?('o') # => true
* 'foo'.match?(/x/) # => false
@@ -4034,6 +4571,7 @@ rb_str_match_m(int argc, VALUE *argv, VALUE str)
* If \Integer argument +offset+ is given, the search begins at index +offset+:
* 'foo'.match?('f', 1) # => false
* 'foo'.match?('o', 1) # => true
+ *
*/
static VALUE
@@ -4058,21 +4596,21 @@ enc_succ_char(char *p, long len, rb_encoding *enc)
int l;
if (rb_enc_mbminlen(enc) > 1) {
- /* wchar, trivial case */
- int r = rb_enc_precise_mbclen(p, p + len, enc), c;
- if (!MBCLEN_CHARFOUND_P(r)) {
- return NEIGHBOR_NOT_CHAR;
- }
- c = rb_enc_mbc_to_codepoint(p, p + len, enc) + 1;
- l = rb_enc_code_to_mbclen(c, enc);
- if (!l) return NEIGHBOR_NOT_CHAR;
- if (l != len) return NEIGHBOR_WRAPPED;
- rb_enc_mbcput(c, p, enc);
- r = rb_enc_precise_mbclen(p, p + len, enc);
- if (!MBCLEN_CHARFOUND_P(r)) {
- return NEIGHBOR_NOT_CHAR;
- }
- return NEIGHBOR_FOUND;
+ /* wchar, trivial case */
+ int r = rb_enc_precise_mbclen(p, p + len, enc), c;
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ return NEIGHBOR_NOT_CHAR;
+ }
+ c = rb_enc_mbc_to_codepoint(p, p + len, enc) + 1;
+ l = rb_enc_code_to_mbclen(c, enc);
+ if (!l) return NEIGHBOR_NOT_CHAR;
+ if (l != len) return NEIGHBOR_WRAPPED;
+ rb_enc_mbcput(c, p, enc);
+ r = rb_enc_precise_mbclen(p, p + len, enc);
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ return NEIGHBOR_NOT_CHAR;
+ }
+ return NEIGHBOR_FOUND;
}
while (1) {
for (i = len-1; 0 <= i && (unsigned char)p[i] == 0xff; i--)
@@ -4109,23 +4647,23 @@ enc_pred_char(char *p, long len, rb_encoding *enc)
long i;
int l;
if (rb_enc_mbminlen(enc) > 1) {
- /* wchar, trivial case */
- int r = rb_enc_precise_mbclen(p, p + len, enc), c;
- if (!MBCLEN_CHARFOUND_P(r)) {
- return NEIGHBOR_NOT_CHAR;
- }
- c = rb_enc_mbc_to_codepoint(p, p + len, enc);
- if (!c) return NEIGHBOR_NOT_CHAR;
- --c;
- l = rb_enc_code_to_mbclen(c, enc);
- if (!l) return NEIGHBOR_NOT_CHAR;
- if (l != len) return NEIGHBOR_WRAPPED;
- rb_enc_mbcput(c, p, enc);
- r = rb_enc_precise_mbclen(p, p + len, enc);
- if (!MBCLEN_CHARFOUND_P(r)) {
- return NEIGHBOR_NOT_CHAR;
- }
- return NEIGHBOR_FOUND;
+ /* wchar, trivial case */
+ int r = rb_enc_precise_mbclen(p, p + len, enc), c;
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ return NEIGHBOR_NOT_CHAR;
+ }
+ c = rb_enc_mbc_to_codepoint(p, p + len, enc);
+ if (!c) return NEIGHBOR_NOT_CHAR;
+ --c;
+ l = rb_enc_code_to_mbclen(c, enc);
+ if (!l) return NEIGHBOR_NOT_CHAR;
+ if (l != len) return NEIGHBOR_WRAPPED;
+ rb_enc_mbcput(c, p, enc);
+ r = rb_enc_precise_mbclen(p, p + len, enc);
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ return NEIGHBOR_NOT_CHAR;
+ }
+ return NEIGHBOR_FOUND;
}
while (1) {
for (i = len-1; 0 <= i && (unsigned char)p[i] == 0; i--)
@@ -4188,12 +4726,12 @@ enc_succ_alnum_char(char *p, long len, rb_encoding *enc, char *carry)
MEMCPY(save, p, char, len);
for (try = 0; try <= max_gaps; ++try) {
- ret = enc_succ_char(p, len, enc);
- if (ret == NEIGHBOR_FOUND) {
- c = rb_enc_mbc_to_codepoint(p, p+len, enc);
- if (rb_enc_isctype(c, ctype, enc))
- return NEIGHBOR_FOUND;
- }
+ ret = enc_succ_char(p, len, enc);
+ if (ret == NEIGHBOR_FOUND) {
+ c = rb_enc_mbc_to_codepoint(p, p+len, enc);
+ if (rb_enc_isctype(c, ctype, enc))
+ return NEIGHBOR_FOUND;
+ }
}
MEMCPY(p, save, char, len);
range = 1;
@@ -4232,13 +4770,14 @@ static VALUE str_succ(VALUE str);
/*
* call-seq:
- * string.succ -> new_str
+ * succ -> new_str
*
* Returns the successor to +self+. The successor is calculated by
* incrementing characters.
*
* The first character to be incremented is the rightmost alphanumeric:
* or, if no alphanumerics, the rightmost character:
+ *
* 'THX1138'.succ # => "THX1139"
* '<<koala>>'.succ # => "<<koalb>>"
* '***'.succ # => '**+'
@@ -4246,6 +4785,7 @@ static VALUE str_succ(VALUE str);
* 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"
@@ -4253,6 +4793,7 @@ static VALUE str_succ(VALUE str);
* 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"
@@ -4264,6 +4805,7 @@ static VALUE str_succ(VALUE str);
* 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"
@@ -4272,12 +4814,14 @@ static VALUE str_succ(VALUE str);
* 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.
@@ -4311,50 +4855,50 @@ str_succ(VALUE str)
s = e = sbeg + slen;
while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
- if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
- if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
- ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
- break;
- }
- }
- l = rb_enc_precise_mbclen(s, e, enc);
- if (!ONIGENC_MBCLEN_CHARFOUND_P(l)) continue;
- l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
+ if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
+ if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
+ ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
+ break;
+ }
+ }
+ l = rb_enc_precise_mbclen(s, e, enc);
+ if (!ONIGENC_MBCLEN_CHARFOUND_P(l)) continue;
+ l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
neighbor = enc_succ_alnum_char(s, l, enc, carry);
switch (neighbor) {
- case NEIGHBOR_NOT_CHAR:
- continue;
- case NEIGHBOR_FOUND:
- return str;
- case NEIGHBOR_WRAPPED:
- last_alnum = s;
- break;
- }
+ case NEIGHBOR_NOT_CHAR:
+ continue;
+ case NEIGHBOR_FOUND:
+ return str;
+ case NEIGHBOR_WRAPPED:
+ last_alnum = s;
+ break;
+ }
found_alnum = 1;
carry_pos = s - sbeg;
carry_len = l;
}
if (!found_alnum) { /* str contains no alnum */
- s = e;
- while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
+ s = e;
+ while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
enum neighbor_char neighbor;
- char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
- l = rb_enc_precise_mbclen(s, e, enc);
- if (!ONIGENC_MBCLEN_CHARFOUND_P(l)) continue;
- l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
- MEMCPY(tmp, s, char, l);
- neighbor = enc_succ_char(tmp, l, enc);
- switch (neighbor) {
- case NEIGHBOR_FOUND:
- MEMCPY(s, tmp, char, l);
+ char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
+ l = rb_enc_precise_mbclen(s, e, enc);
+ if (!ONIGENC_MBCLEN_CHARFOUND_P(l)) continue;
+ l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
+ MEMCPY(tmp, s, char, l);
+ neighbor = enc_succ_char(tmp, l, enc);
+ switch (neighbor) {
+ case NEIGHBOR_FOUND:
+ MEMCPY(s, tmp, char, l);
return str;
- break;
- case NEIGHBOR_WRAPPED:
- MEMCPY(s, tmp, char, l);
- break;
- case NEIGHBOR_NOT_CHAR:
- break;
- }
+ break;
+ case NEIGHBOR_WRAPPED:
+ MEMCPY(s, tmp, char, l);
+ break;
+ case NEIGHBOR_NOT_CHAR:
+ break;
+ }
if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
/* wrapped to \0...\0. search next valid char. */
enc_succ_char(s, l, enc);
@@ -4364,8 +4908,8 @@ str_succ(VALUE str)
carry_len = l;
}
carry_pos = s - sbeg;
- }
- ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
+ }
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
}
RESIZE_CAPA(str, slen + carry_len);
sbeg = RSTRING_PTR(str);
@@ -4382,7 +4926,7 @@ str_succ(VALUE str)
/*
* call-seq:
- * string.succ! -> self
+ * succ! -> self
*
* Equivalent to String#succ, but modifies +self+ in place; returns +self+.
*
@@ -4401,8 +4945,8 @@ static int
all_digits_p(const char *s, long len)
{
while (len-- > 0) {
- if (!ISDIGIT(*s)) return 0;
- s++;
+ if (!ISDIGIT(*s)) return 0;
+ s++;
}
return 1;
}
@@ -4416,29 +4960,37 @@ str_upto_i(VALUE str, VALUE arg)
/*
* call-seq:
- * string.upto(other_string, exclusive = false) {|string| ... } -> self
- * string.upto(other_string, exclusive = false) -> new_enumerator
+ * upto(other_string, exclusive = false) {|string| ... } -> self
+ * upto(other_string, exclusive = false) -> new_enumerator
*
* With a block given, calls the block with each \String value
* returned by successive calls to String#succ;
* the first value is +self+, the next is <tt>self.succ</tt>, and so on;
* the sequence terminates when value +other_string+ is reached;
* returns +self+:
+ *
* 'a8'.upto('b6') {|s| print s, ' ' } # => "a8"
* Output:
+ *
* a8 a9 b0 b1 b2 b3 b4 b5 b6
*
* If argument +exclusive+ is given as a truthy object, the last value is omitted:
+ *
* 'a8'.upto('b6', true) {|s| print s, ' ' } # => "a8"
+ *
* Output:
+ *
* a8 a9 b0 b1 b2 b3 b4 b5
*
* If +other_string+ would not be reached, does not call the block:
+ *
* '25'.upto('5') {|s| fail s }
* 'aa'.upto('a') {|s| fail s }
*
* With no block given, returns a new \Enumerator:
+ *
* 'a8'.upto('b6') # => #<Enumerator: "a8":upto("b6")>
+ *
*/
static VALUE
@@ -4465,51 +5017,51 @@ rb_str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALU
ascii = (is_ascii_string(beg) && is_ascii_string(end));
/* single character */
if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
- char c = RSTRING_PTR(beg)[0];
- char e = RSTRING_PTR(end)[0];
-
- if (c > e || (excl && c == e)) return beg;
- for (;;) {
- if ((*each)(rb_enc_str_new(&c, 1, enc), arg)) break;
- if (!excl && c == e) break;
- c++;
- if (excl && c == e) break;
- }
- return beg;
+ char c = RSTRING_PTR(beg)[0];
+ char e = RSTRING_PTR(end)[0];
+
+ if (c > e || (excl && c == e)) return beg;
+ for (;;) {
+ if ((*each)(rb_enc_str_new(&c, 1, enc), arg)) break;
+ if (!excl && c == e) break;
+ c++;
+ if (excl && c == e) break;
+ }
+ return beg;
}
/* both edges are all digits */
if (ascii && ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0]) &&
- all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
- all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
- VALUE b, e;
- int width;
-
- width = RSTRING_LENINT(beg);
- b = rb_str_to_inum(beg, 10, FALSE);
- e = rb_str_to_inum(end, 10, FALSE);
- if (FIXNUM_P(b) && FIXNUM_P(e)) {
- long bi = FIX2LONG(b);
- long ei = FIX2LONG(e);
- rb_encoding *usascii = rb_usascii_encoding();
-
- while (bi <= ei) {
- if (excl && bi == ei) break;
- if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break;
- bi++;
- }
- }
- else {
- ID op = excl ? '<' : idLE;
- VALUE args[2], fmt = rb_fstring_lit("%.*d");
-
- args[0] = INT2FIX(width);
- while (rb_funcall(b, op, 1, e)) {
- args[1] = b;
- if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break;
- b = rb_funcallv(b, succ, 0, 0);
- }
- }
- return beg;
+ all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
+ all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
+ VALUE b, e;
+ int width;
+
+ width = RSTRING_LENINT(beg);
+ b = rb_str_to_inum(beg, 10, FALSE);
+ e = rb_str_to_inum(end, 10, FALSE);
+ if (FIXNUM_P(b) && FIXNUM_P(e)) {
+ long bi = FIX2LONG(b);
+ long ei = FIX2LONG(e);
+ rb_encoding *usascii = rb_usascii_encoding();
+
+ while (bi <= ei) {
+ if (excl && bi == ei) break;
+ if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break;
+ bi++;
+ }
+ }
+ else {
+ ID op = excl ? '<' : idLE;
+ VALUE args[2], fmt = rb_fstring_lit("%.*d");
+
+ args[0] = INT2FIX(width);
+ while (rb_funcall(b, op, 1, e)) {
+ args[1] = b;
+ if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break;
+ b = rb_funcallv(b, succ, 0, 0);
+ }
+ }
+ return beg;
}
/* normal case */
n = rb_str_cmp(beg, end);
@@ -4518,16 +5070,16 @@ rb_str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALU
after_end = rb_funcallv(end, succ, 0, 0);
current = str_duplicate(rb_cString, beg);
while (!rb_str_equal(current, after_end)) {
- VALUE next = Qnil;
- if (excl || !rb_str_equal(current, end))
- next = rb_funcallv(current, succ, 0, 0);
- if ((*each)(current, arg)) break;
- if (NIL_P(next)) break;
- current = next;
- StringValue(current);
- if (excl && rb_str_equal(current, end)) break;
- if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
- break;
+ VALUE next = Qnil;
+ if (excl || !rb_str_equal(current, end))
+ next = rb_funcallv(current, succ, 0, 0);
+ if ((*each)(current, arg)) break;
+ if (NIL_P(next)) break;
+ current = next;
+ StringValue(current);
+ if (excl && rb_str_equal(current, end)) break;
+ if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
+ break;
}
return beg;
@@ -4542,36 +5094,36 @@ rb_str_upto_endless_each(VALUE beg, int (*each)(VALUE, VALUE), VALUE arg)
CONST_ID(succ, "succ");
/* both edges are all digits */
if (is_ascii_string(beg) && ISDIGIT(RSTRING_PTR(beg)[0]) &&
- all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
- VALUE b, args[2], fmt = rb_fstring_lit("%.*d");
- int width = RSTRING_LENINT(beg);
- b = rb_str_to_inum(beg, 10, FALSE);
- if (FIXNUM_P(b)) {
- long bi = FIX2LONG(b);
- rb_encoding *usascii = rb_usascii_encoding();
-
- while (FIXABLE(bi)) {
- if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break;
- bi++;
- }
- b = LONG2NUM(bi);
- }
- args[0] = INT2FIX(width);
- while (1) {
- args[1] = b;
- if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break;
- b = rb_funcallv(b, succ, 0, 0);
- }
+ all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
+ VALUE b, args[2], fmt = rb_fstring_lit("%.*d");
+ int width = RSTRING_LENINT(beg);
+ b = rb_str_to_inum(beg, 10, FALSE);
+ if (FIXNUM_P(b)) {
+ long bi = FIX2LONG(b);
+ rb_encoding *usascii = rb_usascii_encoding();
+
+ while (FIXABLE(bi)) {
+ if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break;
+ bi++;
+ }
+ b = LONG2NUM(bi);
+ }
+ args[0] = INT2FIX(width);
+ while (1) {
+ args[1] = b;
+ if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break;
+ b = rb_funcallv(b, succ, 0, 0);
+ }
}
/* normal case */
current = str_duplicate(rb_cString, beg);
while (1) {
- VALUE next = rb_funcallv(current, succ, 0, 0);
- if ((*each)(current, arg)) break;
- current = next;
- StringValue(current);
- if (RSTRING_LEN(current) == 0)
- break;
+ VALUE next = rb_funcallv(current, succ, 0, 0);
+ if ((*each)(current, arg)) break;
+ current = next;
+ StringValue(current);
+ if (RSTRING_LEN(current) == 0)
+ break;
}
return beg;
@@ -4596,33 +5148,32 @@ rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive)
val = rb_check_string_type(val);
if (NIL_P(val)) return Qfalse;
if (rb_enc_asciicompat(STR_ENC_GET(beg)) &&
- rb_enc_asciicompat(STR_ENC_GET(end)) &&
- rb_enc_asciicompat(STR_ENC_GET(val))) {
- const char *bp = RSTRING_PTR(beg);
- const char *ep = RSTRING_PTR(end);
- const char *vp = RSTRING_PTR(val);
- if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
- if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
- return Qfalse;
- else {
- char b = *bp;
- char e = *ep;
- char v = *vp;
-
- if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
- if (b <= v && v < e) return Qtrue;
- if (!RTEST(exclusive) && v == e) return Qtrue;
- return Qfalse;
- }
- }
- }
+ rb_enc_asciicompat(STR_ENC_GET(end)) &&
+ rb_enc_asciicompat(STR_ENC_GET(val))) {
+ const char *bp = RSTRING_PTR(beg);
+ const char *ep = RSTRING_PTR(end);
+ const char *vp = RSTRING_PTR(val);
+ if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
+ if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
+ return Qfalse;
+ else {
+ char b = *bp;
+ char e = *ep;
+ char v = *vp;
+
+ if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
+ if (b <= v && v < e) return Qtrue;
+ return RBOOL(!RTEST(exclusive) && v == e);
+ }
+ }
+ }
#if 0
- /* both edges are all digits */
- if (ISDIGIT(*bp) && ISDIGIT(*ep) &&
- all_digits_p(bp, RSTRING_LEN(beg)) &&
- all_digits_p(ep, RSTRING_LEN(end))) {
- /* TODO */
- }
+ /* both edges are all digits */
+ if (ISDIGIT(*bp) && ISDIGIT(*ep) &&
+ all_digits_p(bp, RSTRING_LEN(beg)) &&
+ all_digits_p(ep, RSTRING_LEN(end))) {
+ /* TODO */
+ }
#endif
}
rb_str_upto_each(beg, end, RTEST(exclusive), include_range_i, (VALUE)&val);
@@ -4636,7 +5187,7 @@ rb_str_subpat(VALUE str, VALUE re, VALUE backref)
if (rb_reg_search(re, str, 0, 0) >= 0) {
VALUE match = rb_backref_get();
int nth = rb_reg_backref_number(match, backref);
- return rb_reg_nth_match(nth, match);
+ return rb_reg_nth_match(nth, match);
}
return Qnil;
}
@@ -4647,28 +5198,28 @@ rb_str_aref(VALUE str, VALUE indx)
long idx;
if (FIXNUM_P(indx)) {
- idx = FIX2LONG(indx);
+ idx = FIX2LONG(indx);
}
else if (RB_TYPE_P(indx, T_REGEXP)) {
- return rb_str_subpat(str, indx, INT2FIX(0));
+ return rb_str_subpat(str, indx, INT2FIX(0));
}
else if (RB_TYPE_P(indx, T_STRING)) {
- if (rb_str_index(str, indx, 0) != -1)
+ if (rb_str_index(str, indx, 0) != -1)
return str_duplicate(rb_cString, indx);
- return Qnil;
+ return Qnil;
}
else {
- /* check if indx is Range */
- long beg, len = str_strlen(str, NULL);
- switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
- case Qfalse:
- break;
- case Qnil:
- return Qnil;
- default:
- return rb_str_substr(str, beg, len);
- }
- idx = NUM2LONG(indx);
+ /* check if indx is Range */
+ long beg, len = str_strlen(str, NULL);
+ switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ return Qnil;
+ default:
+ return rb_str_substr(str, beg, len);
+ }
+ idx = NUM2LONG(indx);
}
return str_substr(str, idx, 1, FALSE);
@@ -4684,80 +5235,23 @@ rb_str_aref(VALUE str, VALUE indx)
* string[substring] -> new_string or nil
*
* Returns the substring of +self+ specified by the arguments.
+ * See examples at {String Slices}[rdoc-ref:String@String+Slices].
*
- * 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
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
- if (RB_TYPE_P(argv[0], T_REGEXP)) {
- return rb_str_subpat(str, argv[0], argv[1]);
- }
- else {
- long beg = NUM2LONG(argv[0]);
- long len = NUM2LONG(argv[1]);
- return rb_str_substr(str, beg, len);
- }
+ if (RB_TYPE_P(argv[0], T_REGEXP)) {
+ return rb_str_subpat(str, argv[0], argv[1]);
+ }
+ else {
+ long beg = NUM2LONG(argv[0]);
+ long len = NUM2LONG(argv[1]);
+ return rb_str_substr(str, beg, len);
+ }
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0]);
@@ -4772,19 +5266,23 @@ rb_str_drop_bytes(VALUE str, long len)
str_modifiable(str);
if (len > olen) len = olen;
nlen = olen - len;
- if (STR_EMBEDDABLE_P(nlen, TERM_LEN(str))) {
- char *oldptr = ptr;
- int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
- STR_SET_EMBED(str);
- STR_SET_EMBED_LEN(str, nlen);
- ptr = RSTRING(str)->as.ary;
- memmove(ptr, oldptr + len, nlen);
- if (fl == STR_NOEMBED) xfree(oldptr);
+ if (str_embed_capa(str) >= nlen + TERM_LEN(str)) {
+ char *oldptr = ptr;
+ int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
+ STR_SET_EMBED(str);
+ STR_SET_EMBED_LEN(str, nlen);
+ ptr = RSTRING(str)->as.embed.ary;
+ memmove(ptr, oldptr + len, nlen);
+ if (fl == STR_NOEMBED) xfree(oldptr);
}
else {
- if (!STR_SHARED_P(str)) rb_str_new_frozen(str);
- ptr = RSTRING(str)->as.heap.ptr += len;
- RSTRING(str)->as.heap.len = nlen;
+ if (!STR_SHARED_P(str)) {
+ VALUE shared = heap_str_make_shared(rb_obj_class(str), str);
+ rb_enc_cr_str_exact_copy(shared, str);
+ OBJ_FREEZE(shared);
+ }
+ ptr = RSTRING(str)->as.heap.ptr += len;
+ RSTRING(str)->as.heap.len = nlen;
}
ptr[nlen] = 0;
ENC_CODERANGE_CLEAR(str);
@@ -4799,33 +5297,33 @@ rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
int cr;
if (beg == 0 && vlen == 0) {
- rb_str_drop_bytes(str, len);
- return;
+ rb_str_drop_bytes(str, len);
+ return;
}
str_modify_keep_cr(str);
RSTRING_GETMEM(str, sptr, slen);
if (len < vlen) {
- /* expand string */
- RESIZE_CAPA(str, slen + vlen - len);
- sptr = RSTRING_PTR(str);
+ /* expand string */
+ RESIZE_CAPA(str, slen + vlen - len);
+ sptr = RSTRING_PTR(str);
}
if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT)
- cr = rb_enc_str_coderange(val);
+ cr = rb_enc_str_coderange(val);
else
- cr = ENC_CODERANGE_UNKNOWN;
+ cr = ENC_CODERANGE_UNKNOWN;
if (vlen != len) {
- memmove(sptr + beg + vlen,
- sptr + beg + len,
- slen - (beg + len));
+ memmove(sptr + beg + vlen,
+ sptr + beg + len,
+ slen - (beg + len));
}
if (vlen < beg && len < 0) {
- MEMZERO(sptr + slen, char, -len);
+ MEMZERO(sptr + slen, char, -len);
}
if (vlen > 0) {
- memmove(sptr + beg, RSTRING_PTR(val), vlen);
+ memmove(sptr + beg, RSTRING_PTR(val), vlen);
}
slen += vlen - len;
STR_SET_LEN(str, slen);
@@ -4849,17 +5347,16 @@ rb_str_update(VALUE str, long beg, long len, VALUE val)
slen = str_strlen(str, enc); /* rb_enc_check */
if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
- rb_raise(rb_eIndexError, "index %ld out of string", beg);
+ rb_raise(rb_eIndexError, "index %ld out of string", beg);
}
if (beg < 0) {
- beg += slen;
+ beg += slen;
}
assert(beg >= 0);
assert(beg <= slen);
if (len > slen - beg) {
- len = slen - beg;
+ len = slen - beg;
}
- str_modify_keep_cr(str);
p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc, singlebyte);
if (!p) p = RSTRING_END(str);
e = str_nth(p, RSTRING_END(str), len, enc, singlebyte);
@@ -4871,7 +5368,7 @@ rb_str_update(VALUE str, long beg, long len, VALUE val)
rb_enc_associate(str, enc);
cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
if (cr != ENC_CODERANGE_BROKEN)
- ENC_CODERANGE_SET(str, cr);
+ ENC_CODERANGE_SET(str, cr);
}
#define rb_str_splice(str, beg, len, val) rb_str_update(str, beg, len, val)
@@ -4886,21 +5383,21 @@ rb_str_subpat_set(VALUE str, VALUE re, VALUE backref, VALUE val)
struct re_registers *regs;
if (rb_reg_search(re, str, 0, 0) < 0) {
- rb_raise(rb_eIndexError, "regexp not matched");
+ rb_raise(rb_eIndexError, "regexp not matched");
}
match = rb_backref_get();
nth = rb_reg_backref_number(match, backref);
regs = RMATCH_REGS(match);
if ((nth >= regs->num_regs) || ((nth < 0) && (-nth >= regs->num_regs))) {
- rb_raise(rb_eIndexError, "index %d out of regexp", nth);
+ rb_raise(rb_eIndexError, "index %d out of regexp", nth);
}
if (nth < 0) {
- nth += regs->num_regs;
+ nth += regs->num_regs;
}
start = BEG(nth);
if (start == -1) {
- rb_raise(rb_eIndexError, "regexp group %d not matched", nth);
+ rb_raise(rb_eIndexError, "regexp group %d not matched", nth);
}
end = END(nth);
len = end - start;
@@ -4917,31 +5414,31 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
switch (TYPE(indx)) {
case T_REGEXP:
- rb_str_subpat_set(str, indx, INT2FIX(0), val);
- return val;
+ rb_str_subpat_set(str, indx, INT2FIX(0), val);
+ return val;
case T_STRING:
- beg = rb_str_index(str, indx, 0);
- if (beg < 0) {
- rb_raise(rb_eIndexError, "string not matched");
- }
- beg = rb_str_sublen(str, beg);
- rb_str_splice(str, beg, str_strlen(indx, NULL), val);
- return val;
+ beg = rb_str_index(str, indx, 0);
+ if (beg < 0) {
+ rb_raise(rb_eIndexError, "string not matched");
+ }
+ beg = rb_str_sublen(str, beg);
+ rb_str_splice(str, beg, str_strlen(indx, NULL), val);
+ return val;
default:
- /* check if indx is Range */
- {
- long beg, len;
- if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 2)) {
- rb_str_splice(str, beg, len, val);
- return val;
- }
- }
+ /* check if indx is Range */
+ {
+ long beg, len;
+ if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 2)) {
+ rb_str_splice(str, beg, len, val);
+ return val;
+ }
+ }
/* FALLTHROUGH */
case T_FIXNUM:
- idx = NUM2LONG(indx);
+ idx = NUM2LONG(indx);
rb_str_splice(str, idx, 1, val);
return val;
}
@@ -4949,39 +5446,44 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
/*
* call-seq:
- * str[integer] = new_str
- * str[integer, integer] = new_str
- * str[range] = aString
- * str[regexp] = new_str
- * str[regexp, integer] = new_str
- * str[regexp, name] = new_str
- * str[other_str] = new_str
+ * string[index] = new_string
+ * string[start, length] = new_string
+ * string[range] = new_string
+ * string[regexp, capture = 0] = new_string
+ * string[substring] = new_string
+ *
+ * Replaces all, some, or none of the contents of +self+; returns +new_string+.
+ * See {String Slices}[rdoc-ref:String@String+Slices].
+ *
+ * A few examples:
+ *
+ * s = 'foo'
+ * s[2] = 'rtune' # => "rtune"
+ * s # => "fortune"
+ * s[1, 5] = 'init' # => "init"
+ * s # => "finite"
+ * s[3..4] = 'al' # => "al"
+ * s # => "finale"
+ * s[/e$/] = 'ly' # => "ly"
+ * s # => "finally"
+ * s['lly'] = 'ncial' # => "ncial"
+ * s # => "financial"
+ *
+ * String#slice is an alias for String#[].
*
- * Element Assignment---Replaces some or all of the content of
- * <i>str</i>. The portion of the string affected is determined using
- * the same criteria as String#[]. If the replacement string is not
- * the same length as the text it is replacing, the string will be
- * adjusted accordingly. If the regular expression or string is used
- * as the index doesn't match a position in the string, IndexError is
- * raised. If the regular expression form is used, the optional
- * second Integer allows you to specify which portion of the match to
- * replace (effectively using the MatchData indexing rules. The forms
- * that take an Integer will raise an IndexError if the value is out
- * of range; the Range form will raise a RangeError, and the Regexp
- * and String will raise an IndexError on negative match.
*/
static VALUE
rb_str_aset_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 3) {
- if (RB_TYPE_P(argv[0], T_REGEXP)) {
- rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
- }
- else {
- rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
- }
- return argv[2];
+ if (RB_TYPE_P(argv[0], T_REGEXP)) {
+ rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
+ }
+ else {
+ rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
+ }
+ return argv[2];
}
rb_check_arity(argc, 2, 3);
return rb_str_aset(str, argv[0], argv[1]);
@@ -4989,17 +5491,20 @@ rb_str_aset_m(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * string.insert(index, other_string) -> self
+ * insert(index, other_string) -> self
*
* Inserts the given +other_string+ into +self+; returns +self+.
*
* If the \Integer +index+ is positive, inserts +other_string+ at offset +index+:
+ *
* 'foo'.insert(1, 'bar') # => "fbaroo"
*
* If the \Integer +index+ is negative, counts backward from the end of +self+
* and inserts +other_string+ at offset <tt>index+1</tt>
* (that is, _after_ <tt>self[index]</tt>):
+ *
* 'foo'.insert(-2, 'bar') # => "fobaro"
+ *
*/
static VALUE
@@ -5008,10 +5513,10 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2)
long pos = NUM2LONG(idx);
if (pos == -1) {
- return rb_str_append(str, str2);
+ return rb_str_append(str, str2);
}
else if (pos < 0) {
- pos++;
+ pos++;
}
rb_str_splice(str, pos, 0, str2);
return str;
@@ -5020,21 +5525,24 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2)
/*
* call-seq:
- * str.slice!(integer) -> new_str or nil
- * str.slice!(integer, integer) -> new_str or nil
- * str.slice!(range) -> new_str or nil
- * str.slice!(regexp) -> new_str or nil
- * str.slice!(other_str) -> new_str or nil
+ * slice!(index) -> new_string or nil
+ * slice!(start, length) -> new_string or nil
+ * slice!(range) -> new_string or nil
+ * slice!(regexp, capture = 0) -> new_string or nil
+ * slice!(substring) -> new_string or nil
+ *
+ * Removes and returns the substring of +self+ specified by the arguments.
+ * See {String Slices}[rdoc-ref:String@String+Slices].
*
- * Deletes the specified portion from <i>str</i>, and returns the portion
- * deleted.
+ * A few examples:
*
- * string = "this is a string"
+ * string = "This is a string"
* string.slice!(2) #=> "i"
* string.slice!(3..6) #=> " is "
* string.slice!(/s.*t/) #=> "sa st"
* string.slice!("r") #=> "r"
- * string #=> "thing"
+ * string #=> "Thing"
+ *
*/
static VALUE
@@ -5049,50 +5557,50 @@ rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
str_modify_keep_cr(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;
+ 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]);
+ 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;
+ 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);
+ 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;
- }
+ 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:
@@ -5105,21 +5613,21 @@ rb_str_slice_bang(int argc, VALUE *argv, VALUE 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));
- }
+ 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;
}
@@ -5131,17 +5639,17 @@ get_pat(VALUE pat)
switch (OBJ_BUILTIN_TYPE(pat)) {
case T_REGEXP:
- return pat;
+ return pat;
case T_STRING:
- break;
+ break;
default:
- val = rb_check_string_type(pat);
- if (NIL_P(val)) {
- Check_Type(pat, T_REGEXP);
- }
- pat = val;
+ val = rb_check_string_type(pat);
+ if (NIL_P(val)) {
+ Check_Type(pat, T_REGEXP);
+ }
+ pat = val;
}
return rb_reg_regcomp(pat);
@@ -5154,20 +5662,20 @@ get_pat_quoted(VALUE pat, int check)
switch (OBJ_BUILTIN_TYPE(pat)) {
case T_REGEXP:
- return pat;
+ return pat;
case T_STRING:
- break;
+ break;
default:
- val = rb_check_string_type(pat);
- if (NIL_P(val)) {
- Check_Type(pat, T_REGEXP);
- }
- pat = val;
+ val = rb_check_string_type(pat);
+ if (NIL_P(val)) {
+ Check_Type(pat, T_REGEXP);
+ }
+ pat = val;
}
if (check && is_broken_string(pat)) {
- rb_exc_raise(rb_reg_check_preprocess(pat));
+ rb_exc_raise(rb_reg_check_preprocess(pat));
}
return pat;
}
@@ -5176,33 +5684,36 @@ static long
rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str)
{
if (BUILTIN_TYPE(pat) == T_STRING) {
- pos = rb_strseq_index(str, pat, pos, 1);
- if (set_backref_str) {
- if (pos >= 0) {
+ pos = rb_strseq_index(str, pat, pos, 1);
+ if (set_backref_str) {
+ if (pos >= 0) {
str = rb_str_new_frozen_String(str);
- rb_backref_set_string(str, pos, RSTRING_LEN(pat));
- }
- else {
- rb_backref_set(Qnil);
- }
- }
- return pos;
+ rb_backref_set_string(str, pos, RSTRING_LEN(pat));
+ }
+ else {
+ rb_backref_set(Qnil);
+ }
+ }
+ return pos;
}
else {
- return rb_reg_search0(pat, str, pos, 0, set_backref_str);
+ return rb_reg_search0(pat, str, pos, 0, set_backref_str);
}
}
/*
* call-seq:
- * str.sub!(pattern, replacement) -> str or nil
- * str.sub!(pattern) {|match| block } -> str or nil
+ * sub!(pattern, replacement) -> self or nil
+ * sub!(pattern) {|match| ... } -> self or nil
+ *
+ * Returns +self+ with only the first occurrence
+ * (not all occurrences) of the given +pattern+ replaced.
*
- * Performs the same substitution as String#sub in-place.
+ * See {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
+ *
+ * Related: String#sub, String#gsub, String#gsub!.
*
- * Returns +str+ if a substitution was performed or +nil+ if no substitution
- * was performed.
*/
static VALUE
@@ -5216,14 +5727,14 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
rb_check_arity(argc, min_arity, 2);
if (argc == 1) {
- iter = 1;
+ iter = 1;
}
else {
- repl = argv[1];
- hash = rb_check_hash_type(argv[1]);
- if (NIL_P(hash)) {
- StringValue(repl);
- }
+ repl = argv[1];
+ hash = rb_check_hash_type(argv[1]);
+ if (NIL_P(hash)) {
+ StringValue(repl);
+ }
}
pat = get_pat_quoted(argv[0], 1);
@@ -5231,29 +5742,29 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
str_modifiable(str);
beg = rb_pat_search(pat, str, 0, 1);
if (beg >= 0) {
- rb_encoding *enc;
- int cr = ENC_CODERANGE(str);
- long beg0, end0;
- VALUE match, match0 = Qnil;
- struct re_registers *regs;
- char *p, *rp;
- long len, rlen;
-
- match = rb_backref_get();
- regs = RMATCH_REGS(match);
- if (RB_TYPE_P(pat, T_STRING)) {
- beg0 = beg;
- end0 = beg0 + RSTRING_LEN(pat);
- match0 = pat;
- }
- else {
- beg0 = BEG(0);
- end0 = END(0);
- if (iter) match0 = rb_reg_nth_match(0, match);
- }
-
- if (iter || !NIL_P(hash)) {
- p = RSTRING_PTR(str); len = RSTRING_LEN(str);
+ rb_encoding *enc;
+ int cr = ENC_CODERANGE(str);
+ long beg0, end0;
+ VALUE match, match0 = Qnil;
+ struct re_registers *regs;
+ char *p, *rp;
+ long len, rlen;
+
+ match = rb_backref_get();
+ regs = RMATCH_REGS(match);
+ if (RB_TYPE_P(pat, T_STRING)) {
+ beg0 = beg;
+ end0 = beg0 + RSTRING_LEN(pat);
+ match0 = pat;
+ }
+ else {
+ beg0 = BEG(0);
+ end0 = END(0);
+ if (iter) match0 = rb_reg_nth_match(0, match);
+ }
+
+ if (iter || !NIL_P(hash)) {
+ p = RSTRING_PTR(str); len = RSTRING_LEN(str);
if (iter) {
repl = rb_obj_as_string(rb_yield(match0));
@@ -5262,53 +5773,53 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
repl = rb_obj_as_string(repl);
}
- str_mod_check(str, p, len);
- rb_check_frozen(str);
- }
- else {
- repl = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
- }
+ str_mod_check(str, p, len);
+ rb_check_frozen(str);
+ }
+ else {
+ repl = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
+ }
enc = rb_enc_compatible(str, repl);
if (!enc) {
rb_encoding *str_enc = STR_ENC_GET(str);
- p = RSTRING_PTR(str); len = RSTRING_LEN(str);
- if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
- coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
+ p = RSTRING_PTR(str); len = RSTRING_LEN(str);
+ if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
+ coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(str_enc),
- rb_enc_name(STR_ENC_GET(repl)));
+ rb_enc_name(str_enc),
+ rb_enc_name(STR_ENC_GET(repl)));
}
enc = STR_ENC_GET(repl);
}
- rb_str_modify(str);
- rb_enc_associate(str, enc);
- if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
- int cr2 = ENC_CODERANGE(repl);
+ rb_str_modify(str);
+ rb_enc_associate(str, enc);
+ if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
+ int cr2 = ENC_CODERANGE(repl);
if (cr2 == ENC_CODERANGE_BROKEN ||
(cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
cr = ENC_CODERANGE_UNKNOWN;
else
cr = cr2;
- }
- plen = end0 - beg0;
+ }
+ plen = end0 - beg0;
rlen = RSTRING_LEN(repl);
- len = RSTRING_LEN(str);
- if (rlen > plen) {
- RESIZE_CAPA(str, len + rlen - plen);
- }
- p = RSTRING_PTR(str);
- if (rlen != plen) {
- memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
- }
+ len = RSTRING_LEN(str);
+ if (rlen > plen) {
+ RESIZE_CAPA(str, len + rlen - plen);
+ }
+ p = RSTRING_PTR(str);
+ if (rlen != plen) {
+ memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
+ }
rp = RSTRING_PTR(repl);
memmove(p + beg0, rp, rlen);
- len += rlen - plen;
- STR_SET_LEN(str, len);
- TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
- ENC_CODERANGE_SET(str, cr);
+ len += rlen - plen;
+ STR_SET_LEN(str, len);
+ TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
+ ENC_CODERANGE_SET(str, cr);
- return str;
+ return str;
}
return Qnil;
}
@@ -5316,58 +5827,16 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.sub(pattern, replacement) -> new_str
- * str.sub(pattern, hash) -> new_str
- * str.sub(pattern) {|match| block } -> new_str
- *
- * Returns a copy of +str+ with the _first_ occurrence of +pattern+
- * replaced by the second argument. The +pattern+ is typically a Regexp; if
- * given as a String, any regular expression metacharacters it contains will
- * be interpreted literally, e.g. <code>\d</code> will match a backslash
- * followed by 'd', instead of a digit.
- *
- * If +replacement+ is a String it will be substituted for the matched text.
- * It may contain back-references to the pattern's capture groups of the form
- * <code>\d</code>, where <i>d</i> is a group number, or
- * <code>\k<n></code>, where <i>n</i> is a group name.
- * Similarly, <code>\&</code>, <code>\'</code>, <code>\`</code>, and
- * <code>\+</code> correspond to special variables, <code>$&</code>,
- * <code>$'</code>, <code>$`</code>, and <code>$+</code>, respectively.
- * (See rdoc-ref:regexp.rdoc for details.)
- * <code>\0</code> is the same as <code>\&</code>.
- * <code>\\\\</code> is interpreted as an escape, i.e., a single backslash.
- * Note that, within +replacement+ the special match variables, such as
- * <code>$&</code>, will not refer to the current match.
- *
- * If the second argument is a Hash, and the matched text is one of its keys,
- * the corresponding value is the replacement string.
- *
- * In the block form, the current match string is passed in as a parameter,
- * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- * <code>$&</code>, and <code>$'</code> will be set appropriately.
- * (See rdoc-ref:regexp.rdoc for details.)
- * The value returned by the block will be substituted for the match on each
- * call.
- *
- * "hello".sub(/[aeiou]/, '*') #=> "h*llo"
- * "hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo"
- * "hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello"
- * "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo"
- * 'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
- * #=> "Is /bin/bash your preferred shell?"
- *
- * Note that a string literal consumes backslashes.
- * (See rdoc-ref:syntax/literals.rdoc for details about string literals.)
- * Back-references are typically preceded by an additional backslash.
- * For example, if you want to write a back-reference <code>\&</code> in
- * +replacement+ with a double-quoted string literal, you need to write:
- * <code>"..\\\\&.."</code>.
- * If you want to write a non-back-reference string <code>\&</code> in
- * +replacement+, you need first to escape the backslash to prevent
- * this method from interpreting it as a back-reference, and then you
- * need to escape the backslashes again to prevent a string literal from
- * consuming them: <code>"..\\\\\\\\&.."</code>.
- * You may want to use the block form to avoid a lot of backslashes.
+ * sub(pattern, replacement) -> new_string
+ * sub(pattern) {|match| ... } -> new_string
+ *
+ * Returns a copy of +self+ with only the first occurrence
+ * (not all occurrences) of the given +pattern+ replaced.
+ *
+ * See {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
+ *
+ * Related: String#sub!, String#gsub, String#gsub!.
+ *
*/
static VALUE
@@ -5392,19 +5861,19 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
switch (argc) {
case 1:
- RETURN_ENUMERATOR(str, argc, argv);
- mode = ITER;
- break;
+ RETURN_ENUMERATOR(str, argc, argv);
+ mode = ITER;
+ break;
case 2:
- repl = argv[1];
- hash = rb_check_hash_type(argv[1]);
- if (NIL_P(hash)) {
- StringValue(repl);
- }
- else {
- mode = MAP;
- }
- break;
+ repl = argv[1];
+ hash = rb_check_hash_type(argv[1]);
+ if (NIL_P(hash)) {
+ StringValue(repl);
+ }
+ else {
+ mode = MAP;
+ }
+ break;
default:
rb_error_arity(argc, 1, 2);
}
@@ -5412,7 +5881,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
pat = get_pat_quoted(argv[0], 1);
beg = rb_pat_search(pat, str, 0, need_backref);
if (beg < 0) {
- if (bang) return Qnil; /* no match, no substitution */
+ if (bang) return Qnil; /* no match, no substitution */
return str_duplicate(rb_cString, str);
}
@@ -5427,20 +5896,20 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
ENC_CODERANGE_SET(dest, rb_enc_asciicompat(str_enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);
do {
- match = rb_backref_get();
- regs = RMATCH_REGS(match);
- if (RB_TYPE_P(pat, T_STRING)) {
- beg0 = beg;
- end0 = beg0 + RSTRING_LEN(pat);
- match0 = pat;
- }
- else {
- beg0 = BEG(0);
- end0 = END(0);
- if (mode == ITER) match0 = rb_reg_nth_match(0, match);
- }
-
- if (mode) {
+ match = rb_backref_get();
+ regs = RMATCH_REGS(match);
+ if (RB_TYPE_P(pat, T_STRING)) {
+ beg0 = beg;
+ end0 = beg0 + RSTRING_LEN(pat);
+ match0 = pat;
+ }
+ else {
+ beg0 = BEG(0);
+ end0 = END(0);
+ if (mode == ITER) match0 = rb_reg_nth_match(0, match);
+ }
+
+ if (mode) {
if (mode == ITER) {
val = rb_obj_as_string(rb_yield(match0));
}
@@ -5448,43 +5917,43 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
val = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
val = rb_obj_as_string(val);
}
- str_mod_check(str, sp, slen);
- if (val == dest) { /* paranoid check [ruby-dev:24827] */
- rb_raise(rb_eRuntimeError, "block should not cheat");
- }
- }
- else if (need_backref) {
- val = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
- if (need_backref < 0) {
- need_backref = val != repl;
- }
- }
- else {
- val = repl;
- }
-
- len = beg0 - offset; /* copy pre-match substr */
+ str_mod_check(str, sp, slen);
+ if (val == dest) { /* paranoid check [ruby-dev:24827] */
+ rb_raise(rb_eRuntimeError, "block should not cheat");
+ }
+ }
+ else if (need_backref) {
+ val = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
+ if (need_backref < 0) {
+ need_backref = val != repl;
+ }
+ }
+ else {
+ val = repl;
+ }
+
+ len = beg0 - offset; /* copy pre-match substr */
if (len) {
rb_enc_str_buf_cat(dest, cp, len, str_enc);
}
rb_str_buf_append(dest, val);
- last = offset;
- offset = end0;
- if (beg0 == end0) {
- /*
- * Always consume at least one character of the input string
- * in order to prevent infinite loops.
- */
- if (RSTRING_LEN(str) <= end0) break;
- len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0, RSTRING_END(str), str_enc);
+ last = offset;
+ offset = end0;
+ if (beg0 == end0) {
+ /*
+ * Always consume at least one character of the input string
+ * in order to prevent infinite loops.
+ */
+ if (RSTRING_LEN(str) <= end0) break;
+ len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0, RSTRING_END(str), str_enc);
rb_enc_str_buf_cat(dest, RSTRING_PTR(str)+end0, len, str_enc);
- offset = end0 + len;
- }
- cp = RSTRING_PTR(str) + offset;
- if (offset > RSTRING_LEN(str)) break;
- beg = rb_pat_search(pat, str, offset, need_backref);
+ offset = end0 + len;
+ }
+ cp = RSTRING_PTR(str) + offset;
+ if (offset > RSTRING_LEN(str)) break;
+ beg = rb_pat_search(pat, str, offset, need_backref);
} while (beg >= 0);
if (RSTRING_LEN(str) > offset) {
rb_enc_str_buf_cat(dest, cp, RSTRING_LEN(str) - offset, str_enc);
@@ -5494,7 +5963,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
str_shared_replace(str, dest);
}
else {
- str = dest;
+ str = dest;
}
return str;
@@ -5503,15 +5972,19 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
/*
* call-seq:
- * str.gsub!(pattern, replacement) -> str or nil
- * str.gsub!(pattern, hash) -> str or nil
- * str.gsub!(pattern) {|match| block } -> str or nil
- * str.gsub!(pattern) -> an_enumerator
+ * gsub!(pattern, replacement) -> self or nil
+ * gsub!(pattern) {|match| ... } -> self or nil
+ * gsub!(pattern) -> an_enumerator
+ *
+ * Performs the specified substring replacement(s) on +self+;
+ * returns +self+ if any replacement occurred, +nil+ otherwise.
+ *
+ * See {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
+ *
+ * Returns an Enumerator if no +replacement+ and no block given.
+ *
+ * Related: String#sub, String#gsub, String#sub!.
*
- * Performs the substitutions of String#gsub in place, returning
- * <i>str</i>, or <code>nil</code> if no substitutions were
- * performed. If no block and no <i>replacement</i> is given, an
- * enumerator is returned instead.
*/
static VALUE
@@ -5524,62 +5997,18 @@ rb_str_gsub_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.gsub(pattern, replacement) -> new_str
- * str.gsub(pattern, hash) -> new_str
- * str.gsub(pattern) {|match| block } -> new_str
- * str.gsub(pattern) -> enumerator
- *
- * Returns a copy of <i>str</i> with <em>all</em> occurrences of
- * <i>pattern</i> substituted for the second argument. The <i>pattern</i> is
- * typically a Regexp; if given as a String, any
- * regular expression metacharacters it contains will be interpreted
- * literally, e.g. <code>\d</code> will match a backslash followed by 'd',
- * instead of a digit.
- *
- * If +replacement+ is a String it will be substituted for the matched text.
- * It may contain back-references to the pattern's capture groups of the form
- * <code>\d</code>, where <i>d</i> is a group number, or
- * <code>\k<n></code>, where <i>n</i> is a group name.
- * Similarly, <code>\&</code>, <code>\'</code>, <code>\`</code>, and
- * <code>\+</code> correspond to special variables, <code>$&</code>,
- * <code>$'</code>, <code>$`</code>, and <code>$+</code>, respectively.
- * (See rdoc-ref:regexp.rdoc for details.)
- * <code>\0</code> is the same as <code>\&</code>.
- * <code>\\\\</code> is interpreted as an escape, i.e., a single backslash.
- * Note that, within +replacement+ the special match variables, such as
- * <code>$&</code>, will not refer to the current match.
- *
- * If the second argument is a Hash, and the matched text is one
- * of its keys, the corresponding value is the replacement string.
- *
- * In the block form, the current match string is passed in as a parameter,
- * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- * <code>$&</code>, and <code>$'</code> will be set appropriately.
- * (See rdoc-ref:regexp.rdoc for details.)
- * The value returned by the block will be substituted for the match on each
- * call.
- *
- * When neither a block nor a second argument is supplied, an
- * Enumerator is returned.
- *
- * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
- * "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>"
- * "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 "
- * "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}"
- * 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"
- *
- * Note that a string literal consumes backslashes.
- * (See rdoc-ref:syntax/literals.rdoc for details on string literals.)
- * Back-references are typically preceded by an additional backslash.
- * For example, if you want to write a back-reference <code>\&</code> in
- * +replacement+ with a double-quoted string literal, you need to write:
- * <code>"..\\\\&.."</code>.
- * If you want to write a non-back-reference string <code>\&</code> in
- * +replacement+, you need first to escape the backslash to prevent
- * this method from interpreting it as a back-reference, and then you
- * need to escape the backslashes again to prevent a string literal from
- * consuming them: <code>"..\\\\\\\\&.."</code>.
- * You may want to use the block form to avoid a lot of backslashes.
+ * gsub(pattern, replacement) -> new_string
+ * gsub(pattern) {|match| ... } -> new_string
+ * gsub(pattern) -> enumerator
+ *
+ * Returns a copy of +self+ with all occurrences of the given +pattern+ replaced.
+ *
+ * See {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
+ *
+ * Returns an Enumerator if no +replacement+ and no block given.
+ *
+ * Related: String#sub, String#sub!, String#gsub!.
+ *
*/
static VALUE
@@ -5591,13 +6020,13 @@ rb_str_gsub(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.replace(other_str) -> str
+ * replace(other_string) -> self
*
- * Replaces the contents of <i>str</i> with the corresponding
- * values in <i>other_str</i>.
+ * Replaces the contents of +self+ with the contents of +other_string+:
+ *
+ * s = 'foo' # => "foo"
+ * s.replace('bar') # => "bar"
*
- * s = "hello" #=> "hello"
- * s.replace "world" #=> "world"
*/
VALUE
@@ -5613,12 +6042,13 @@ rb_str_replace(VALUE str, VALUE str2)
/*
* call-seq:
- * string.clear -> string
+ * clear -> self
+ *
+ * Removes the contents of +self+:
*
- * Makes string empty.
+ * s = 'foo' # => "foo"
+ * s.clear # => ""
*
- * a = "abcde"
- * a.clear #=> ""
*/
static VALUE
@@ -5629,20 +6059,21 @@ rb_str_clear(VALUE str)
STR_SET_EMBED_LEN(str, 0);
RSTRING_PTR(str)[0] = 0;
if (rb_enc_asciicompat(STR_ENC_GET(str)))
- ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
else
- ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
return str;
}
/*
* call-seq:
- * string.chr -> string
+ * chr -> string
+ *
+ * Returns a string containing the first character of +self+:
*
- * Returns a one-character string at the beginning of the string.
+ * s = 'foo' # => "foo"
+ * s.chr # => "f"
*
- * a = "abcde"
- * a.chr #=> "a"
*/
static VALUE
@@ -5653,9 +6084,16 @@ rb_str_chr(VALUE str)
/*
* call-seq:
- * str.getbyte(index) -> 0 .. 255
+ * getbyte(index) -> integer or nil
*
- * returns the <i>index</i>th byte as an integer.
+ * Returns the byte at zero-based +index+ as an integer, or +nil+ if +index+ is out of range:
+ *
+ * s = 'abcde' # => "abcde"
+ * s.getbyte(0) # => 97
+ * s.getbyte(-1) # => 101
+ * s.getbyte(5) # => nil
+ *
+ * Related: String#setbyte.
*/
static VALUE
rb_str_getbyte(VALUE str, VALUE index)
@@ -5672,17 +6110,22 @@ rb_str_getbyte(VALUE str, VALUE index)
/*
* call-seq:
- * str.setbyte(index, integer) -> integer
+ * setbyte(index, integer) -> integer
+ *
+ * Sets the byte at zero-based +index+ to +integer+; returns +integer+:
*
- * modifies the <i>index</i>th byte as <i>integer</i>.
+ * s = 'abcde' # => "abcde"
+ * s.setbyte(0, 98) # => 98
+ * s # => "bbcde"
+ *
+ * Related: String#getbyte.
*/
static VALUE
rb_str_setbyte(VALUE str, VALUE index, VALUE value)
{
long pos = NUM2LONG(index);
long len = RSTRING_LEN(str);
- char *head, *left = 0;
- unsigned char *ptr;
+ char *ptr, *head, *left = 0;
rb_encoding *enc;
int cr = ENC_CODERANGE_UNKNOWN, width, nlen;
@@ -5693,37 +6136,37 @@ rb_str_setbyte(VALUE str, VALUE index, VALUE value)
VALUE v = rb_to_int(value);
VALUE w = rb_int_and(v, INT2FIX(0xff));
- unsigned char byte = NUM2INT(w) & 0xFF;
+ char byte = (char)(NUM2INT(w) & 0xFF);
if (!str_independent(str))
- str_make_independent(str);
+ str_make_independent(str);
enc = STR_ENC_GET(str);
head = RSTRING_PTR(str);
- ptr = (unsigned char *)&head[pos];
+ ptr = &head[pos];
if (!STR_EMBED_P(str)) {
- cr = ENC_CODERANGE(str);
- switch (cr) {
- case ENC_CODERANGE_7BIT:
- left = (char *)ptr;
- *ptr = byte;
- if (ISASCII(byte)) goto end;
- nlen = rb_enc_precise_mbclen(left, head+len, enc);
- if (!MBCLEN_CHARFOUND_P(nlen))
- ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
- else
- ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
- goto end;
- case ENC_CODERANGE_VALID:
- left = rb_enc_left_char_head(head, ptr, head+len, enc);
- width = rb_enc_precise_mbclen(left, head+len, enc);
- *ptr = byte;
- nlen = rb_enc_precise_mbclen(left, head+len, enc);
- if (!MBCLEN_CHARFOUND_P(nlen))
- ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
- else if (MBCLEN_CHARFOUND_LEN(nlen) != width || ISASCII(byte))
- ENC_CODERANGE_CLEAR(str);
- goto end;
- }
+ cr = ENC_CODERANGE(str);
+ switch (cr) {
+ case ENC_CODERANGE_7BIT:
+ left = ptr;
+ *ptr = byte;
+ if (ISASCII(byte)) goto end;
+ nlen = rb_enc_precise_mbclen(left, head+len, enc);
+ if (!MBCLEN_CHARFOUND_P(nlen))
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
+ else
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
+ goto end;
+ case ENC_CODERANGE_VALID:
+ left = rb_enc_left_char_head(head, ptr, head+len, enc);
+ width = rb_enc_precise_mbclen(left, head+len, enc);
+ *ptr = byte;
+ nlen = rb_enc_precise_mbclen(left, head+len, enc);
+ if (!MBCLEN_CHARFOUND_P(nlen))
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
+ else if (MBCLEN_CHARFOUND_LEN(nlen) != width || ISASCII(byte))
+ ENC_CODERANGE_CLEAR(str);
+ goto end;
+ }
}
ENC_CODERANGE_CLEAR(str);
*ptr = byte;
@@ -5735,52 +6178,39 @@ rb_str_setbyte(VALUE str, VALUE index, VALUE value)
static VALUE
str_byte_substr(VALUE str, long beg, long len, int empty)
{
- char *p, *s = RSTRING_PTR(str);
long n = RSTRING_LEN(str);
- VALUE str2;
if (beg > n || len < 0) return Qnil;
if (beg < 0) {
- beg += n;
- if (beg < 0) return Qnil;
+ beg += n;
+ if (beg < 0) return Qnil;
}
if (len > n - beg)
- len = n - beg;
+ len = n - beg;
if (len <= 0) {
- if (!empty) return Qnil;
- len = 0;
- p = 0;
+ if (!empty) return Qnil;
+ len = 0;
}
- else
- p = s + beg;
- 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_cString, str2);
- RSTRING(str2)->as.heap.ptr += beg;
- RSTRING(str2)->as.heap.len = len;
- }
- else {
- str2 = rb_str_new(p, len);
- }
+ VALUE str2 = str_subseq(str, beg, len);
str_enc_copy(str2, str);
if (RSTRING_LEN(str2) == 0) {
- if (!rb_enc_asciicompat(STR_ENC_GET(str)))
- ENC_CODERANGE_SET(str2, ENC_CODERANGE_VALID);
- else
- ENC_CODERANGE_SET(str2, ENC_CODERANGE_7BIT);
+ if (!rb_enc_asciicompat(STR_ENC_GET(str)))
+ ENC_CODERANGE_SET(str2, ENC_CODERANGE_VALID);
+ else
+ ENC_CODERANGE_SET(str2, ENC_CODERANGE_7BIT);
}
else {
- switch (ENC_CODERANGE(str)) {
- case ENC_CODERANGE_7BIT:
- ENC_CODERANGE_SET(str2, ENC_CODERANGE_7BIT);
- break;
- default:
- ENC_CODERANGE_SET(str2, ENC_CODERANGE_UNKNOWN);
- break;
- }
+ switch (ENC_CODERANGE(str)) {
+ case ENC_CODERANGE_7BIT:
+ ENC_CODERANGE_SET(str2, ENC_CODERANGE_7BIT);
+ break;
+ default:
+ ENC_CODERANGE_SET(str2, ENC_CODERANGE_UNKNOWN);
+ break;
+ }
}
return str2;
@@ -5791,56 +6221,76 @@ str_byte_aref(VALUE str, VALUE indx)
{
long idx;
if (FIXNUM_P(indx)) {
- idx = FIX2LONG(indx);
+ idx = FIX2LONG(indx);
}
else {
- /* check if indx is Range */
- long beg, len = RSTRING_LEN(str);
+ /* check if indx is Range */
+ long beg, len = RSTRING_LEN(str);
- switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
- case Qfalse:
- break;
- case Qnil:
- return Qnil;
- default:
- return str_byte_substr(str, beg, len, TRUE);
- }
+ switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ return Qnil;
+ default:
+ return str_byte_substr(str, beg, len, TRUE);
+ }
- idx = NUM2LONG(indx);
+ idx = NUM2LONG(indx);
}
return str_byte_substr(str, idx, 1, FALSE);
}
/*
* call-seq:
- * str.byteslice(integer) -> new_str or nil
- * str.byteslice(integer, integer) -> new_str or nil
- * str.byteslice(range) -> new_str or nil
+ * byteslice(index, length = 1) -> string or nil
+ * byteslice(range) -> string or nil
+ *
+ * Returns a substring of +self+, or +nil+ if the substring cannot be constructed.
+ *
+ * With integer arguments +index+ and +length+ given,
+ * returns the substring beginning at the given +index+
+ * of the given +length+ (if possible),
+ * or +nil+ if +length+ is negative or +index+ falls outside of +self+:
+ *
+ * s = '0123456789' # => "0123456789"
+ * s.byteslice(2) # => "2"
+ * s.byteslice(200) # => nil
+ * s.byteslice(4, 3) # => "456"
+ * s.byteslice(4, 30) # => "456789"
+ * s.byteslice(4, -1) # => nil
+ * s.byteslice(40, 2) # => nil
+ *
+ * In either case above, counts backwards from the end of +self+
+ * if +index+ is negative:
+ *
+ * s = '0123456789' # => "0123456789"
+ * s.byteslice(-4) # => "6"
+ * s.byteslice(-4, 3) # => "678"
*
- * Byte Reference---If passed a single Integer, returns a
- * substring of one byte at that position. If passed two Integer
- * objects, returns a substring starting at the offset given by the first, and
- * a length given by the second. If given a Range, a substring containing
- * bytes at offsets given by the range is returned. In all three cases, if
- * an offset is negative, it is counted from the end of <i>str</i>. Returns
- * <code>nil</code> if the initial offset falls outside the string, the length
- * is negative, or the beginning of the range is greater than the end.
- * The encoding of the resulted string keeps original encoding.
+ * With Range argument +range+ given, returns
+ * <tt>byteslice(range.begin, range.size)</tt>:
+ *
+ * s = '0123456789' # => "0123456789"
+ * s.byteslice(4..6) # => "456"
+ * s.byteslice(-6..-4) # => "456"
+ * s.byteslice(5..2) # => "" # range.size is zero.
+ * s.byteslice(40..42) # => nil
+ *
+ * In all cases, a returned string has the same encoding as +self+:
+ *
+ * s.encoding # => #<Encoding:UTF-8>
+ * s.byteslice(4).encoding # => #<Encoding:UTF-8>
*
- * "hello".byteslice(1) #=> "e"
- * "hello".byteslice(-1) #=> "o"
- * "hello".byteslice(1, 2) #=> "el"
- * "\x80\u3042".byteslice(1, 3) #=> "\u3042"
- * "\x03\u3042\xff".byteslice(1..3) #=> "\u3042"
*/
static VALUE
rb_str_byteslice(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
- long beg = NUM2LONG(argv[0]);
- long end = NUM2LONG(argv[1]);
- return str_byte_substr(str, beg, end, TRUE);
+ long beg = NUM2LONG(argv[0]);
+ long len = NUM2LONG(argv[1]);
+ return str_byte_substr(str, beg, len, TRUE);
}
rb_check_arity(argc, 1, 2);
return str_byte_aref(str, argv[0]);
@@ -5848,11 +6298,82 @@ rb_str_byteslice(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.reverse -> new_str
+ * bytesplice(index, length, str) -> string
+ * bytesplice(range, str) -> string
+ *
+ * Replaces some or all of the content of +self+ with +str+, and returns +self+.
+ * The portion of the string affected is determined using
+ * the same criteria as String#byteslice, except that +length+ cannot be omitted.
+ * If the replacement string is not the same length as the text it is replacing,
+ * the string will be adjusted accordingly.
+ * The form that take an Integer will raise an IndexError if the value is out
+ * of range; the Range form will raise a RangeError.
+ * If the beginning or ending offset does not land on character (codepoint)
+ * boundary, an IndexError will be raised.
+ */
+
+static VALUE
+rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
+{
+ long beg, end, len, slen;
+ VALUE val;
+ rb_encoding *enc;
+ int cr;
+
+ rb_check_arity(argc, 2, 3);
+ if (argc == 2) {
+ if (!rb_range_beg_len(argv[0], &beg, &len, RSTRING_LEN(str), 2)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
+ rb_builtin_class_name(argv[0]));
+ }
+ val = argv[1];
+ }
+ else {
+ beg = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[1]);
+ val = argv[2];
+ }
+ if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
+ slen = RSTRING_LEN(str);
+ if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
+ rb_raise(rb_eIndexError, "index %ld out of string", beg);
+ }
+ if (beg < 0) {
+ beg += slen;
+ }
+ assert(beg >= 0);
+ assert(beg <= slen);
+ if (len > slen - beg) {
+ len = slen - beg;
+ }
+ end = beg + len;
+ if (!str_check_byte_pos(str, beg)) {
+ rb_raise(rb_eIndexError,
+ "offset %ld does not land on character boundary", beg);
+ }
+ if (!str_check_byte_pos(str, end)) {
+ rb_raise(rb_eIndexError,
+ "offset %ld does not land on character boundary", end);
+ }
+ StringValue(val);
+ enc = rb_enc_check(str, val);
+ str_modify_keep_cr(str);
+ rb_str_splice_0(str, beg, len, val);
+ rb_enc_associate(str, enc);
+ cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(str, cr);
+ return str;
+}
+
+/*
+ * call-seq:
+ * reverse -> string
+ *
+ * Returns a new string with the characters from +self+ in reverse order.
*
- * Returns a new string with the characters from <i>str</i> in reverse order.
+ * 'stressed'.reverse # => "desserts"
*
- * "stressed".reverse #=> "desserts"
*/
static VALUE
@@ -5871,32 +6392,32 @@ rb_str_reverse(VALUE str)
cr = ENC_CODERANGE(str);
if (RSTRING_LEN(str) > 1) {
- if (single_byte_optimizable(str)) {
- while (s < e) {
- *--p = *s++;
- }
- }
- else if (cr == ENC_CODERANGE_VALID) {
- while (s < e) {
- int clen = rb_enc_fast_mbclen(s, e, enc);
-
- p -= clen;
- memcpy(p, s, clen);
- s += clen;
- }
- }
- else {
- cr = rb_enc_asciicompat(enc) ?
- ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
- while (s < e) {
- int clen = rb_enc_mbclen(s, e, enc);
-
- if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN;
- p -= clen;
- memcpy(p, s, clen);
- s += clen;
- }
- }
+ if (single_byte_optimizable(str)) {
+ while (s < e) {
+ *--p = *s++;
+ }
+ }
+ else if (cr == ENC_CODERANGE_VALID) {
+ while (s < e) {
+ int clen = rb_enc_fast_mbclen(s, e, enc);
+
+ p -= clen;
+ memcpy(p, s, clen);
+ s += clen;
+ }
+ }
+ else {
+ cr = rb_enc_asciicompat(enc) ?
+ ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
+ while (s < e) {
+ int clen = rb_enc_mbclen(s, e, enc);
+
+ if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN;
+ p -= clen;
+ memcpy(p, s, clen);
+ s += clen;
+ }
+ }
}
STR_SET_LEN(rev, RSTRING_LEN(str));
str_enc_copy(rev, str);
@@ -5908,33 +6429,38 @@ rb_str_reverse(VALUE str)
/*
* call-seq:
- * str.reverse! -> str
+ * reverse! -> self
+ *
+ * Returns +self+ with its characters reversed:
+ *
+ * s = 'stressed'
+ * s.reverse! # => "desserts"
+ * s # => "desserts"
*
- * Reverses <i>str</i> in place.
*/
static VALUE
rb_str_reverse_bang(VALUE str)
{
if (RSTRING_LEN(str) > 1) {
- if (single_byte_optimizable(str)) {
- char *s, *e, c;
-
- str_modify_keep_cr(str);
- s = RSTRING_PTR(str);
- e = RSTRING_END(str) - 1;
- while (s < e) {
- c = *s;
- *s++ = *e;
- *e-- = c;
- }
- }
- else {
- str_shared_replace(str, rb_str_reverse(str));
- }
+ if (single_byte_optimizable(str)) {
+ char *s, *e, c;
+
+ str_modify_keep_cr(str);
+ s = RSTRING_PTR(str);
+ e = RSTRING_END(str) - 1;
+ while (s < e) {
+ c = *s;
+ *s++ = *e;
+ *e-- = c;
+ }
+ }
+ else {
+ str_shared_replace(str, rb_str_reverse(str));
+ }
}
else {
- str_modify_keep_cr(str);
+ str_modify_keep_cr(str);
}
return str;
}
@@ -5942,17 +6468,18 @@ rb_str_reverse_bang(VALUE str)
/*
* call-seq:
- * str.include? other_str -> true or false
+ * include? other_string -> true or false
*
- * Returns <code>true</code> if <i>str</i> contains the given string or
- * character.
+ * Returns +true+ if +self+ contains +other_string+, +false+ otherwise:
+ *
+ * s = 'foo'
+ * s.include?('f') # => true
+ * s.include?('fo') # => true
+ * s.include?('food') # => false
*
- * "hello".include? "lo" #=> true
- * "hello".include? "ol" #=> false
- * "hello".include? ?h #=> true
*/
-static VALUE
+VALUE
rb_str_include(VALUE str, VALUE arg)
{
long i;
@@ -5966,23 +6493,34 @@ rb_str_include(VALUE str, VALUE arg)
/*
* call-seq:
- * str.to_i(base=10) -> integer
+ * to_i(base = 10) -> integer
+ *
+ * Returns the result of interpreting leading characters in +self+
+ * as an integer in the given +base+ (which must be in (0, 2..36)):
+ *
+ * '123456'.to_i # => 123456
+ * '123def'.to_i(16) # => 1195503
+ *
+ * With +base+ zero, string +object+ may contain leading characters
+ * to specify the actual base:
*
- * Returns the result of interpreting leading characters in <i>str</i> as an
- * integer base <i>base</i> (between 2 and 36). Extraneous characters past the
- * end of a valid number are ignored. If there is not a valid number at the
- * start of <i>str</i>, <code>0</code> is returned. This method never raises an
- * exception when <i>base</i> is valid.
+ * '123def'.to_i(0) # => 123
+ * '0123def'.to_i(0) # => 83
+ * '0b123def'.to_i(0) # => 1
+ * '0o123def'.to_i(0) # => 83
+ * '0d123def'.to_i(0) # => 123
+ * '0x123def'.to_i(0) # => 1195503
+ *
+ * Characters past a leading valid number (in the given +base+) are ignored:
+ *
+ * '12.345'.to_i # => 12
+ * '12345'.to_i(2) # => 1
+ *
+ * Returns zero if there is no leading valid number:
+ *
+ * 'abcdef'.to_i # => 0
+ * '2'.to_i(2) # => 0
*
- * "12345".to_i #=> 12345
- * "99 red balloons".to_i #=> 99
- * "0a".to_i #=> 0
- * "0a".to_i(16) #=> 10
- * "hello".to_i #=> 0
- * "1100101".to_i(2) #=> 101
- * "1100101".to_i(8) #=> 294977
- * "1100101".to_i(10) #=> 1100101
- * "1100101".to_i(16) #=> 17826049
*/
static VALUE
@@ -5991,7 +6529,7 @@ rb_str_to_i(int argc, VALUE *argv, VALUE str)
int base = 10;
if (rb_check_arity(argc, 0, 1) && (base = NUM2INT(argv[0])) < 0) {
- rb_raise(rb_eArgError, "invalid radix %d", base);
+ rb_raise(rb_eArgError, "invalid radix %d", base);
}
return rb_str_to_inum(str, base, FALSE);
}
@@ -5999,16 +6537,21 @@ rb_str_to_i(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.to_f -> float
+ * to_f -> float
+ *
+ * Returns the result of interpreting leading characters in +self+ as a Float:
+ *
+ * '3.14159'.to_f # => 3.14159
+ '1.234e-2'.to_f # => 0.01234
*
- * Returns the result of interpreting leading characters in <i>str</i> as a
- * floating point number. Extraneous characters past the end of a valid number
- * are ignored. If there is not a valid number at the start of <i>str</i>,
- * <code>0.0</code> is returned. This method never raises an exception.
+ * Characters past a leading valid number (in the given +base+) are ignored:
+ *
+ * '3.14 (pi to two places)'.to_f # => 3.14
+ *
+ * Returns zero if there is no leading valid number:
+ *
+ * 'abcdef'.to_f # => 0.0
*
- * "123.45e1".to_f #=> 1234.5
- * "45.67 degrees".to_f #=> 45.67
- * "thx1138".to_f #=> 0.0
*/
static VALUE
@@ -6020,19 +6563,20 @@ rb_str_to_f(VALUE str)
/*
* call-seq:
- * str.to_s -> str
- * str.to_str -> str
+ * to_s -> self or string
*
- * Returns +self+.
+ * Returns +self+ if +self+ is a \String,
+ * or +self+ converted to a \String if +self+ is a subclass of \String.
+ *
+ * String#to_str is an alias for String#to_s.
*
- * If called on a subclass of String, converts the receiver to a String object.
*/
static VALUE
rb_str_to_s(VALUE str)
{
if (rb_obj_class(str) != rb_cString) {
- return str_duplicate(rb_cString, str);
+ return str_duplicate(rb_cString, str);
}
return str;
}
@@ -6061,23 +6605,23 @@ rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p)
c &= 0xffffffff;
#endif
if (unicode_p) {
- if (c < 0x7F && ISPRINT(c)) {
- snprintf(buf, CHAR_ESC_LEN, "%c", c);
- }
- else if (c < 0x10000) {
- snprintf(buf, CHAR_ESC_LEN, "\\u%04X", c);
- }
- else {
- snprintf(buf, CHAR_ESC_LEN, "\\u{%X}", c);
- }
+ if (c < 0x7F && ISPRINT(c)) {
+ snprintf(buf, CHAR_ESC_LEN, "%c", c);
+ }
+ else if (c < 0x10000) {
+ snprintf(buf, CHAR_ESC_LEN, "\\u%04X", c);
+ }
+ else {
+ snprintf(buf, CHAR_ESC_LEN, "\\u{%X}", c);
+ }
}
else {
- if (c < 0x100) {
- snprintf(buf, CHAR_ESC_LEN, "\\x%02X", c);
- }
- else {
- snprintf(buf, CHAR_ESC_LEN, "\\x{%X}", c);
- }
+ if (c < 0x100) {
+ snprintf(buf, CHAR_ESC_LEN, "\\x%02X", c);
+ }
+ else {
+ snprintf(buf, CHAR_ESC_LEN, "\\x{%X}", c);
+ }
}
l = (int)strlen(buf); /* CHAR_ESC_LEN cannot exceed INT_MAX */
rb_str_buf_cat(result, buf, l);
@@ -6118,9 +6662,9 @@ rb_str_escape(VALUE str)
while (p < pend) {
unsigned int c;
const char *cc;
- int n = rb_enc_precise_mbclen(p, pend, enc);
+ int n = rb_enc_precise_mbclen(p, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
- if (p > prev) str_buf_cat(result, prev, p - prev);
+ if (p > prev) str_buf_cat(result, prev, p - prev);
n = rb_enc_mbminlen(enc);
if (pend < p + n)
n = (int)(pend - p);
@@ -6129,24 +6673,24 @@ rb_str_escape(VALUE str)
str_buf_cat(result, buf, strlen(buf));
prev = ++p;
}
- continue;
- }
+ continue;
+ }
n = MBCLEN_CHARFOUND_LEN(n);
- c = rb_enc_mbc_to_codepoint(p, pend, enc);
- p += n;
+ c = rb_enc_mbc_to_codepoint(p, pend, enc);
+ p += n;
cc = ruby_escaped_char(c);
- if (cc) {
- if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
+ if (cc) {
+ if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
str_buf_cat(result, cc, strlen(cc));
- prev = p;
- }
- else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) {
- }
- else {
- if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
- rb_str_buf_cat_escaped_char(result, c, unicode_p);
- prev = p;
- }
+ prev = p;
+ }
+ else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) {
+ }
+ else {
+ if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
+ rb_str_buf_cat_escaped_char(result, c, unicode_p);
+ prev = p;
+ }
}
if (p > prev) str_buf_cat(result, prev, p - prev);
ENCODING_CODERANGE_SET(result, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
@@ -6155,22 +6699,23 @@ rb_str_escape(VALUE str)
}
/*
- * call-seq:
- * str.inspect -> string
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a printable version of +self+, enclosed in double-quotes,
+ * and with special characters escaped:
*
- * Returns a printable version of _str_, surrounded by quote marks,
- * with special characters escaped.
+ * s = "foo\tbar\tbaz\n"
+ * s.inspect
+ * # => "\"foo\\tbar\\tbaz\\n\""
*
- * str = "hello"
- * str[3] = "\b"
- * str.inspect #=> "\"hel\\bo\""
*/
VALUE
rb_str_inspect(VALUE str)
{
int encidx = ENCODING_GET(str);
- rb_encoding *enc = rb_enc_from_index(encidx), *actenc;
+ rb_encoding *enc = rb_enc_from_index(encidx);
const char *p, *pend, *prev;
char buf[CHAR_ESC_LEN + 1];
VALUE result = rb_str_buf_new(0);
@@ -6185,18 +6730,13 @@ rb_str_inspect(VALUE str)
p = RSTRING_PTR(str); pend = RSTRING_END(str);
prev = p;
- actenc = get_actual_encoding(encidx, str);
- if (actenc != enc) {
- enc = actenc;
- if (unicode_p) unicode_p = rb_enc_unicode_p(enc);
- }
while (p < pend) {
- unsigned int c, cc;
- int n;
+ unsigned int c, cc;
+ int n;
n = rb_enc_precise_mbclen(p, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
- if (p > prev) str_buf_cat(result, prev, p - prev);
+ if (p > prev) str_buf_cat(result, prev, p - prev);
n = rb_enc_mbminlen(enc);
if (pend < p + n)
n = (int)(pend - p);
@@ -6205,54 +6745,62 @@ rb_str_inspect(VALUE str)
str_buf_cat(result, buf, strlen(buf));
prev = ++p;
}
- continue;
- }
+ continue;
+ }
n = MBCLEN_CHARFOUND_LEN(n);
- c = rb_enc_mbc_to_codepoint(p, pend, enc);
- p += n;
- if ((asciicompat || unicode_p) &&
- (c == '"'|| c == '\\' ||
- (c == '#' &&
+ c = rb_enc_mbc_to_codepoint(p, pend, enc);
+ p += n;
+ if ((asciicompat || unicode_p) &&
+ (c == '"'|| c == '\\' ||
+ (c == '#' &&
p < pend &&
MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
(cc = rb_enc_codepoint(p,pend,enc),
(cc == '$' || cc == '@' || cc == '{'))))) {
- if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
- str_buf_cat2(result, "\\");
- if (asciicompat || enc == resenc) {
- prev = p - n;
- continue;
- }
- }
- switch (c) {
- case '\n': cc = 'n'; break;
- case '\r': cc = 'r'; break;
- case '\t': cc = 't'; break;
- case '\f': cc = 'f'; break;
- case '\013': cc = 'v'; break;
- case '\010': cc = 'b'; break;
- case '\007': cc = 'a'; break;
- case 033: cc = 'e'; break;
- default: cc = 0; break;
- }
- if (cc) {
- if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
- buf[0] = '\\';
- buf[1] = (char)cc;
- str_buf_cat(result, buf, 2);
- prev = p;
- continue;
- }
- if ((enc == resenc && rb_enc_isprint(c, enc)) ||
- (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
- continue;
- }
- else {
- if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
- rb_str_buf_cat_escaped_char(result, c, unicode_p);
- prev = p;
- continue;
- }
+ if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
+ str_buf_cat2(result, "\\");
+ if (asciicompat || enc == resenc) {
+ prev = p - n;
+ continue;
+ }
+ }
+ switch (c) {
+ case '\n': cc = 'n'; break;
+ case '\r': cc = 'r'; break;
+ case '\t': cc = 't'; break;
+ case '\f': cc = 'f'; break;
+ case '\013': cc = 'v'; break;
+ case '\010': cc = 'b'; break;
+ case '\007': cc = 'a'; break;
+ case 033: cc = 'e'; break;
+ default: cc = 0; break;
+ }
+ if (cc) {
+ if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
+ buf[0] = '\\';
+ buf[1] = (char)cc;
+ str_buf_cat(result, buf, 2);
+ prev = p;
+ continue;
+ }
+ /* The special casing of 0x85 (NEXT_LINE) here is because
+ * Oniguruma historically treats it as printable, but it
+ * doesn't match the print POSIX bracket class or character
+ * property in regexps.
+ *
+ * See Ruby Bug #16842 for details:
+ * https://bugs.ruby-lang.org/issues/16842
+ */
+ if ((enc == resenc && rb_enc_isprint(c, enc) && c != 0x85) ||
+ (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
+ continue;
+ }
+ else {
+ if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
+ rb_str_buf_cat_escaped_char(result, c, unicode_p);
+ prev = p;
+ continue;
+ }
}
if (p > prev) str_buf_cat(result, prev, p - prev);
str_buf_cat2(result, "\"");
@@ -6264,18 +6812,17 @@ rb_str_inspect(VALUE str)
/*
* call-seq:
- * str.dump -> new_str
+ * dump -> string
*
- * Returns a quoted version of the string with all non-printing characters
- * replaced by <code>\xHH</code> notation and all special characters escaped.
+ * Returns a printable version of +self+, enclosed in double-quotes,
+ * with special characters escaped, and with non-printing characters
+ * replaced by hexadecimal notation:
*
- * This method can be used for round-trip: if the resulting +new_str+ is
- * eval'ed, it will produce the original string.
+ * "hello \n ''".dump # => "\"hello \\n ''\""
+ * "\f\x00\xff\\\"".dump # => "\"\\f\\x00\\xFF\\\\\\\"\""
*
- * "hello \n ''".dump #=> "\"hello \\n ''\""
- * "\f\x00\xff\\\"".dump #=> "\"\\f\\x00\\xFF\\\\\\\"\""
+ * Related: String#undump (inverse of String#dump).
*
- * See also String#undump.
*/
VALUE
@@ -6292,55 +6839,55 @@ rb_str_dump(VALUE str)
len = 2; /* "" */
if (!rb_enc_asciicompat(enc)) {
- len += strlen(nonascii_suffix) - rb_strlen_lit("%s");
- len += strlen(enc->name);
+ len += strlen(nonascii_suffix) - rb_strlen_lit("%s");
+ len += strlen(enc->name);
}
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
while (p < pend) {
- int clen;
- unsigned char c = *p++;
-
- switch (c) {
- case '"': case '\\':
- case '\n': case '\r':
- case '\t': case '\f':
- case '\013': case '\010': case '\007': case '\033':
- clen = 2;
- break;
-
- case '#':
- clen = IS_EVSTR(p, pend) ? 2 : 1;
- break;
-
- default:
- if (ISPRINT(c)) {
- clen = 1;
- }
- else {
- if (u8 && c > 0x7F) { /* \u notation */
- int n = rb_enc_precise_mbclen(p-1, pend, enc);
- if (MBCLEN_CHARFOUND_P(n)) {
- unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
- if (cc <= 0xFFFF)
- clen = 6; /* \uXXXX */
- else if (cc <= 0xFFFFF)
- clen = 9; /* \u{XXXXX} */
- else
- clen = 10; /* \u{XXXXXX} */
- p += MBCLEN_CHARFOUND_LEN(n)-1;
- break;
- }
- }
- clen = 4; /* \xNN */
- }
- break;
- }
-
- if (clen > LONG_MAX - len) {
- rb_raise(rb_eRuntimeError, "string size too big");
- }
- len += clen;
+ int clen;
+ unsigned char c = *p++;
+
+ switch (c) {
+ case '"': case '\\':
+ case '\n': case '\r':
+ case '\t': case '\f':
+ case '\013': case '\010': case '\007': case '\033':
+ clen = 2;
+ break;
+
+ case '#':
+ clen = IS_EVSTR(p, pend) ? 2 : 1;
+ break;
+
+ default:
+ if (ISPRINT(c)) {
+ clen = 1;
+ }
+ else {
+ if (u8 && c > 0x7F) { /* \u notation */
+ int n = rb_enc_precise_mbclen(p-1, pend, enc);
+ if (MBCLEN_CHARFOUND_P(n)) {
+ unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
+ if (cc <= 0xFFFF)
+ clen = 6; /* \uXXXX */
+ else if (cc <= 0xFFFFF)
+ clen = 9; /* \u{XXXXX} */
+ else
+ clen = 10; /* \u{XXXXXX} */
+ p += MBCLEN_CHARFOUND_LEN(n)-1;
+ break;
+ }
+ }
+ clen = 4; /* \xNN */
+ }
+ break;
+ }
+
+ if (clen > LONG_MAX - len) {
+ rb_raise(rb_eRuntimeError, "string size too big");
+ }
+ len += clen;
}
result = rb_str_new(0, len);
@@ -6349,75 +6896,75 @@ rb_str_dump(VALUE str)
*q++ = '"';
while (p < pend) {
- unsigned char c = *p++;
-
- if (c == '"' || c == '\\') {
- *q++ = '\\';
- *q++ = c;
- }
- else if (c == '#') {
- if (IS_EVSTR(p, pend)) *q++ = '\\';
- *q++ = '#';
- }
- else if (c == '\n') {
- *q++ = '\\';
- *q++ = 'n';
- }
- else if (c == '\r') {
- *q++ = '\\';
- *q++ = 'r';
- }
- else if (c == '\t') {
- *q++ = '\\';
- *q++ = 't';
- }
- else if (c == '\f') {
- *q++ = '\\';
- *q++ = 'f';
- }
- else if (c == '\013') {
- *q++ = '\\';
- *q++ = 'v';
- }
- else if (c == '\010') {
- *q++ = '\\';
- *q++ = 'b';
- }
- else if (c == '\007') {
- *q++ = '\\';
- *q++ = 'a';
- }
- else if (c == '\033') {
- *q++ = '\\';
- *q++ = 'e';
- }
- else if (ISPRINT(c)) {
- *q++ = c;
- }
- else {
- *q++ = '\\';
- if (u8) {
- int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
- if (MBCLEN_CHARFOUND_P(n)) {
- int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
- p += n;
- if (cc <= 0xFFFF)
- snprintf(q, qend-q, "u%04X", cc); /* \uXXXX */
- else
- snprintf(q, qend-q, "u{%X}", cc); /* \u{XXXXX} or \u{XXXXXX} */
- q += strlen(q);
- continue;
- }
- }
- snprintf(q, qend-q, "x%02X", c);
- q += 3;
- }
+ unsigned char c = *p++;
+
+ if (c == '"' || c == '\\') {
+ *q++ = '\\';
+ *q++ = c;
+ }
+ else if (c == '#') {
+ if (IS_EVSTR(p, pend)) *q++ = '\\';
+ *q++ = '#';
+ }
+ else if (c == '\n') {
+ *q++ = '\\';
+ *q++ = 'n';
+ }
+ else if (c == '\r') {
+ *q++ = '\\';
+ *q++ = 'r';
+ }
+ else if (c == '\t') {
+ *q++ = '\\';
+ *q++ = 't';
+ }
+ else if (c == '\f') {
+ *q++ = '\\';
+ *q++ = 'f';
+ }
+ else if (c == '\013') {
+ *q++ = '\\';
+ *q++ = 'v';
+ }
+ else if (c == '\010') {
+ *q++ = '\\';
+ *q++ = 'b';
+ }
+ else if (c == '\007') {
+ *q++ = '\\';
+ *q++ = 'a';
+ }
+ else if (c == '\033') {
+ *q++ = '\\';
+ *q++ = 'e';
+ }
+ else if (ISPRINT(c)) {
+ *q++ = c;
+ }
+ else {
+ *q++ = '\\';
+ if (u8) {
+ int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
+ if (MBCLEN_CHARFOUND_P(n)) {
+ int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
+ p += n;
+ if (cc <= 0xFFFF)
+ snprintf(q, qend-q, "u%04X", cc); /* \uXXXX */
+ else
+ snprintf(q, qend-q, "u{%X}", cc); /* \u{XXXXX} or \u{XXXXXX} */
+ q += strlen(q);
+ continue;
+ }
+ }
+ snprintf(q, qend-q, "x%02X", c);
+ q += 3;
+ }
}
*q++ = '"';
*q = '\0';
if (!rb_enc_asciicompat(enc)) {
- snprintf(q, qend-q, nonascii_suffix, enc->name);
- encidx = rb_ascii8bit_encindex();
+ snprintf(q, qend-q, nonascii_suffix, enc->name);
+ encidx = rb_ascii8bit_encindex();
}
/* result from dump is ASCII */
rb_enc_associate_index(result, encidx);
@@ -6430,21 +6977,21 @@ unescape_ascii(unsigned int c)
{
switch (c) {
case 'n':
- return '\n';
+ return '\n';
case 'r':
- return '\r';
+ return '\r';
case 't':
- return '\t';
+ return '\t';
case 'f':
- return '\f';
+ return '\f';
case 'v':
- return '\13';
+ return '\13';
case 'b':
- return '\010';
+ return '\010';
case 'a':
- return '\007';
+ return '\007';
case 'e':
- return 033;
+ return 033;
}
UNREACHABLE_RETURN(-1);
}
@@ -6463,9 +7010,9 @@ undump_after_backslash(VALUE undumped, const char **ss, const char *s_end, rb_en
case '\\':
case '"':
case '#':
- rb_str_cat(undumped, s, 1); /* cat itself */
- s++;
- break;
+ rb_str_cat(undumped, s, 1); /* cat itself */
+ s++;
+ break;
case 'n':
case 'r':
case 't':
@@ -6476,81 +7023,81 @@ undump_after_backslash(VALUE undumped, const char **ss, const char *s_end, rb_en
case 'e':
*buf = unescape_ascii(*s);
rb_str_cat(undumped, (char *)buf, 1);
- s++;
- break;
+ s++;
+ break;
case 'u':
- if (*binary) {
- rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
- }
- *utf8 = true;
- if (++s >= s_end) {
- rb_raise(rb_eRuntimeError, "invalid Unicode escape");
- }
- if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
- if (*penc != enc_utf8) {
- *penc = enc_utf8;
- rb_enc_associate(undumped, enc_utf8);
- }
- if (*s == '{') { /* handle \u{...} form */
- s++;
- for (;;) {
- if (s >= s_end) {
- rb_raise(rb_eRuntimeError, "unterminated Unicode escape");
- }
- if (*s == '}') {
- s++;
- break;
- }
- if (ISSPACE(*s)) {
- s++;
- continue;
- }
- c = scan_hex(s, s_end-s, &hexlen);
- if (hexlen == 0 || hexlen > 6) {
- rb_raise(rb_eRuntimeError, "invalid Unicode escape");
- }
- if (c > 0x10ffff) {
- rb_raise(rb_eRuntimeError, "invalid Unicode codepoint (too large)");
- }
- if (0xd800 <= c && c <= 0xdfff) {
- rb_raise(rb_eRuntimeError, "invalid Unicode codepoint");
- }
+ if (*binary) {
+ rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
+ }
+ *utf8 = true;
+ if (++s >= s_end) {
+ rb_raise(rb_eRuntimeError, "invalid Unicode escape");
+ }
+ if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
+ if (*penc != enc_utf8) {
+ *penc = enc_utf8;
+ rb_enc_associate(undumped, enc_utf8);
+ }
+ if (*s == '{') { /* handle \u{...} form */
+ s++;
+ for (;;) {
+ if (s >= s_end) {
+ rb_raise(rb_eRuntimeError, "unterminated Unicode escape");
+ }
+ if (*s == '}') {
+ s++;
+ break;
+ }
+ if (ISSPACE(*s)) {
+ s++;
+ continue;
+ }
+ c = scan_hex(s, s_end-s, &hexlen);
+ if (hexlen == 0 || hexlen > 6) {
+ rb_raise(rb_eRuntimeError, "invalid Unicode escape");
+ }
+ if (c > 0x10ffff) {
+ rb_raise(rb_eRuntimeError, "invalid Unicode codepoint (too large)");
+ }
+ if (0xd800 <= c && c <= 0xdfff) {
+ rb_raise(rb_eRuntimeError, "invalid Unicode codepoint");
+ }
codelen = rb_enc_mbcput(c, (char *)buf, *penc);
rb_str_cat(undumped, (char *)buf, codelen);
- s += hexlen;
- }
- }
- else { /* handle \uXXXX form */
- c = scan_hex(s, 4, &hexlen);
- if (hexlen != 4) {
- rb_raise(rb_eRuntimeError, "invalid Unicode escape");
- }
- if (0xd800 <= c && c <= 0xdfff) {
- rb_raise(rb_eRuntimeError, "invalid Unicode codepoint");
- }
+ s += hexlen;
+ }
+ }
+ else { /* handle \uXXXX form */
+ c = scan_hex(s, 4, &hexlen);
+ if (hexlen != 4) {
+ rb_raise(rb_eRuntimeError, "invalid Unicode escape");
+ }
+ if (0xd800 <= c && c <= 0xdfff) {
+ rb_raise(rb_eRuntimeError, "invalid Unicode codepoint");
+ }
codelen = rb_enc_mbcput(c, (char *)buf, *penc);
rb_str_cat(undumped, (char *)buf, codelen);
- s += hexlen;
- }
- break;
+ s += hexlen;
+ }
+ break;
case 'x':
- if (*utf8) {
- rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
- }
- *binary = true;
- if (++s >= s_end) {
- rb_raise(rb_eRuntimeError, "invalid hex escape");
- }
- *buf = scan_hex(s, 2, &hexlen);
- if (hexlen != 2) {
- rb_raise(rb_eRuntimeError, "invalid hex escape");
- }
+ if (*utf8) {
+ rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
+ }
+ *binary = true;
+ if (++s >= s_end) {
+ rb_raise(rb_eRuntimeError, "invalid hex escape");
+ }
+ *buf = scan_hex(s, 2, &hexlen);
+ if (hexlen != 2) {
+ rb_raise(rb_eRuntimeError, "invalid hex escape");
+ }
rb_str_cat(undumped, (char *)buf, 1);
- s += hexlen;
- break;
+ s += hexlen;
+ break;
default:
- rb_str_cat(undumped, s-1, 2);
- s++;
+ rb_str_cat(undumped, s-1, 2);
+ s++;
}
*ss = s;
@@ -6560,12 +7107,17 @@ static VALUE rb_str_is_ascii_only_p(VALUE str);
/*
* call-seq:
- * str.undump -> new_str
+ * undump -> string
*
- * Returns an unescaped version of the string.
- * This does the inverse of String#dump.
+ * Returns an unescaped version of +self+:
+ *
+ * s_orig = "\f\x00\xff\\\"" # => "\f\u0000\xFF\\\""
+ * s_dumped = s_orig.dump # => "\"\\f\\x00\\xFF\\\\\\\"\""
+ * s_undumped = s_dumped.undump # => "\f\u0000\xFF\\\""
+ * s_undumped == s_orig # => true
+ *
+ * Related: String#dump (inverse of String#undump).
*
- * "\"hello \\n ''\"".undump #=> "hello \n ''"
*/
static VALUE
@@ -6581,10 +7133,10 @@ str_undump(VALUE str)
rb_must_asciicompat(str);
if (rb_str_is_ascii_only_p(str) == Qfalse) {
- rb_raise(rb_eRuntimeError, "non-ASCII character detected");
+ 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;
@@ -6593,63 +7145,63 @@ str_undump(VALUE str)
s++;
for (;;) {
- if (s >= s_end) {
- rb_raise(rb_eRuntimeError, "unterminated dumped string");
- }
-
- if (*s == '"') {
- /* epilogue */
- s++;
- if (s == s_end) {
- /* ascii compatible dumped string */
- break;
- }
- else {
- static const char force_encoding_suffix[] = ".force_encoding(\""; /* "\")" */
- static const char dup_suffix[] = ".dup";
- const char *encname;
- int encidx;
- ptrdiff_t size;
-
- /* check separately for strings dumped by older versions */
- size = sizeof(dup_suffix) - 1;
- if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
-
- size = sizeof(force_encoding_suffix) - 1;
- if (s_end - s <= size) goto invalid_format;
- if (memcmp(s, force_encoding_suffix, size) != 0) goto invalid_format;
- s += size;
-
- if (utf8) {
- rb_raise(rb_eRuntimeError, "dumped string contained Unicode escape but used force_encoding");
- }
-
- encname = s;
- s = memchr(s, '"', s_end-s);
- size = s - encname;
- if (!s) goto invalid_format;
- if (s_end - s != 2) goto invalid_format;
- if (s[0] != '"' || s[1] != ')') goto invalid_format;
-
- encidx = rb_enc_find_index2(encname, (long)size);
- if (encidx < 0) {
- rb_raise(rb_eRuntimeError, "dumped string has unknown encoding name");
- }
- rb_enc_associate_index(undumped, encidx);
- }
- break;
- }
-
- if (*s == '\\') {
- s++;
- if (s >= s_end) {
- rb_raise(rb_eRuntimeError, "invalid escape");
- }
- undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
- }
- else {
- rb_str_cat(undumped, s++, 1);
- }
+ if (s >= s_end) {
+ rb_raise(rb_eRuntimeError, "unterminated dumped string");
+ }
+
+ if (*s == '"') {
+ /* epilogue */
+ s++;
+ if (s == s_end) {
+ /* ascii compatible dumped string */
+ break;
+ }
+ else {
+ static const char force_encoding_suffix[] = ".force_encoding(\""; /* "\")" */
+ static const char dup_suffix[] = ".dup";
+ const char *encname;
+ int encidx;
+ ptrdiff_t size;
+
+ /* check separately for strings dumped by older versions */
+ size = sizeof(dup_suffix) - 1;
+ if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
+
+ size = sizeof(force_encoding_suffix) - 1;
+ if (s_end - s <= size) goto invalid_format;
+ if (memcmp(s, force_encoding_suffix, size) != 0) goto invalid_format;
+ s += size;
+
+ if (utf8) {
+ rb_raise(rb_eRuntimeError, "dumped string contained Unicode escape but used force_encoding");
+ }
+
+ encname = s;
+ s = memchr(s, '"', s_end-s);
+ size = s - encname;
+ if (!s) goto invalid_format;
+ if (s_end - s != 2) goto invalid_format;
+ if (s[0] != '"' || s[1] != ')') goto invalid_format;
+
+ encidx = rb_enc_find_index2(encname, (long)size);
+ if (encidx < 0) {
+ rb_raise(rb_eRuntimeError, "dumped string has unknown encoding name");
+ }
+ rb_enc_associate_index(undumped, encidx);
+ }
+ break;
+ }
+
+ if (*s == '\\') {
+ s++;
+ if (s >= s_end) {
+ rb_raise(rb_eRuntimeError, "invalid escape");
+ }
+ undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
+ }
+ else {
+ rb_str_cat(undumped, s++, 1);
+ }
}
return undumped;
@@ -6661,8 +7213,8 @@ static void
rb_str_check_dummy_enc(rb_encoding *enc)
{
if (rb_enc_dummy_p(enc)) {
- rb_raise(rb_eEncCompatError, "incompatible encoding with this operation: %s",
- rb_enc_name(enc));
+ rb_raise(rb_eEncCompatError, "incompatible encoding with this operation: %s",
+ rb_enc_name(enc));
}
}
@@ -6682,35 +7234,35 @@ check_case_options(int argc, VALUE *argv, OnigCaseFoldType flags)
if (argc>2)
rb_raise(rb_eArgError, "too many options");
if (argv[0]==sym_turkic) {
- flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
- if (argc==2) {
- if (argv[1]==sym_lithuanian)
- flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
- else
- rb_raise(rb_eArgError, "invalid second option");
- }
+ flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
+ if (argc==2) {
+ if (argv[1]==sym_lithuanian)
+ flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
+ else
+ rb_raise(rb_eArgError, "invalid second option");
+ }
}
else if (argv[0]==sym_lithuanian) {
- flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
- if (argc==2) {
- if (argv[1]==sym_turkic)
- flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
- else
- rb_raise(rb_eArgError, "invalid second option");
- }
+ flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
+ if (argc==2) {
+ if (argv[1]==sym_turkic)
+ flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
+ else
+ rb_raise(rb_eArgError, "invalid second option");
+ }
}
else if (argc>1)
- rb_raise(rb_eArgError, "too many options");
+ rb_raise(rb_eArgError, "too many options");
else if (argv[0]==sym_ascii)
- flags |= ONIGENC_CASE_ASCII_ONLY;
+ flags |= ONIGENC_CASE_ASCII_ONLY;
else if (argv[0]==sym_fold) {
- if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
- flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
- else
- rb_raise(rb_eArgError, "option :fold only allowed for downcasing");
+ if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
+ flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
+ else
+ rb_raise(rb_eArgError, "option :fold only allowed for downcasing");
}
else
- rb_raise(rb_eArgError, "invalid option");
+ rb_raise(rb_eArgError, "invalid option");
return flags;
}
@@ -6774,52 +7326,54 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
buffer_anchor = TypedData_Wrap_Struct(0, &mapping_buffer_type, 0);
pre_buffer = (mapping_buffer **)&DATA_PTR(buffer_anchor);
while (source_current < source_end) {
- /* increase multiplier using buffer count to converge quickly */
- size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
- if (CASEMAP_DEBUG) {
- fprintf(stderr, "Buffer allocation, capa is %"PRIuSIZE"\n", capa); /* for tuning */
- }
+ /* increase multiplier using buffer count to converge quickly */
+ size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
+ if (CASEMAP_DEBUG) {
+ fprintf(stderr, "Buffer allocation, capa is %"PRIuSIZE"\n", capa); /* for tuning */
+ }
current_buffer = xmalloc(offsetof(mapping_buffer, space) + capa);
*pre_buffer = current_buffer;
pre_buffer = &current_buffer->next;
- current_buffer->next = NULL;
- current_buffer->capa = capa;
- buffer_length_or_invalid = enc->case_map(flags,
- (const OnigUChar**)&source_current, source_end,
- current_buffer->space,
- current_buffer->space+current_buffer->capa,
- enc);
- if (buffer_length_or_invalid < 0) {
+ current_buffer->next = NULL;
+ current_buffer->capa = capa;
+ buffer_length_or_invalid = enc->case_map(flags,
+ &source_current, source_end,
+ current_buffer->space,
+ current_buffer->space+current_buffer->capa,
+ enc);
+ if (buffer_length_or_invalid < 0) {
current_buffer = DATA_PTR(buffer_anchor);
DATA_PTR(buffer_anchor) = 0;
mapping_buffer_free(current_buffer);
- rb_raise(rb_eArgError, "input string invalid");
- }
- target_length += current_buffer->used = buffer_length_or_invalid;
+ rb_raise(rb_eArgError, "input string invalid");
+ }
+ target_length += current_buffer->used = buffer_length_or_invalid;
}
if (CASEMAP_DEBUG) {
- fprintf(stderr, "Buffer count is %"PRIuSIZE"\n", buffer_count); /* for tuning */
+ fprintf(stderr, "Buffer count is %"PRIuSIZE"\n", buffer_count); /* for tuning */
}
if (buffer_count==1) {
target = rb_str_new((const char*)current_buffer->space, target_length);
}
else {
- char *target_current;
+ char *target_current;
target = rb_str_new(0, target_length);
- target_current = RSTRING_PTR(target);
+ target_current = RSTRING_PTR(target);
current_buffer = DATA_PTR(buffer_anchor);
- while (current_buffer) {
- memcpy(target_current, current_buffer->space, current_buffer->used);
- target_current += current_buffer->used;
- current_buffer = current_buffer->next;
- }
+ while (current_buffer) {
+ memcpy(target_current, current_buffer->space, current_buffer->used);
+ target_current += current_buffer->used;
+ current_buffer = current_buffer->next;
+ }
}
current_buffer = DATA_PTR(buffer_anchor);
DATA_PTR(buffer_anchor) = 0;
mapping_buffer_free(current_buffer);
+ RB_GC_GUARD(buffer_anchor);
+
/* TODO: check about string terminator character */
str_enc_copy(target, source);
/*ENC_CODERANGE_SET(mapped, cr);*/
@@ -6854,10 +7408,10 @@ rb_str_ascii_casemap(VALUE source, VALUE target, OnigCaseFoldType *flags, rb_enc
if (length_or_invalid < 0)
rb_raise(rb_eArgError, "input string invalid");
if (CASEMAP_DEBUG && length_or_invalid != old_length) {
- fprintf(stderr, "problem with rb_str_ascii_casemap"
- "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
- rb_raise(rb_eArgError, "internal problem with rb_str_ascii_casemap"
- "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
+ fprintf(stderr, "problem with rb_str_ascii_casemap"
+ "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
+ rb_raise(rb_eArgError, "internal problem with rb_str_ascii_casemap"
+ "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
}
str_enc_copy(target, source);
@@ -6874,7 +7428,7 @@ upcase_single(VALUE str)
while (s < send) {
unsigned int c = *(unsigned char*)s;
- if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
+ if ('a' <= c && c <= 'z') {
*s = 'A' + (c - 'a');
modified = true;
}
@@ -6885,13 +7439,21 @@ upcase_single(VALUE str)
/*
* call-seq:
- * str.upcase! -> str or nil
- * str.upcase!([options]) -> str or nil
+ * upcase!(*options) -> self or nil
*
- * Upcases the contents of <i>str</i>, returning <code>nil</code> if no changes
- * were made.
+ * Upcases the characters in +self+;
+ * returns +self+ if any changes were made, +nil+ otherwise:
+ *
+ * s = 'Hello World!' # => "Hello World!"
+ * s.upcase! # => "HELLO WORLD!"
+ * s # => "HELLO WORLD!"
+ * s.upcase! # => nil
+ *
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#upcase, String#downcase, String#downcase!.
*
- * See String#downcase for meaning of +options+ and use with different encodings.
*/
static VALUE
@@ -6910,7 +7472,7 @@ rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, str, &flags, enc);
else
- str_shared_replace(str, rb_str_casemap(str, &flags, enc));
+ str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
@@ -6919,15 +7481,18 @@ rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.upcase -> new_str
- * str.upcase([options]) -> new_str
+ * upcase(*options) -> string
*
- * Returns a copy of <i>str</i> with all lowercase letters replaced with their
- * uppercase counterparts.
+ * Returns a string containing the upcased characters in +self+:
*
- * See String#downcase for meaning of +options+ and use with different encodings.
+ * s = 'Hello World!' # => "Hello World!"
+ * s.upcase # => "HELLO WORLD!"
+ *
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#upcase!, String#downcase, String#downcase!.
*
- * "hEllO".upcase #=> "HELLO"
*/
static VALUE
@@ -6964,7 +7529,7 @@ downcase_single(VALUE str)
while (s < send) {
unsigned int c = *(unsigned char*)s;
- if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
+ if ('A' <= c && c <= 'Z') {
*s = 'a' + (c - 'A');
modified = true;
}
@@ -6976,13 +7541,21 @@ downcase_single(VALUE str)
/*
* call-seq:
- * str.downcase! -> str or nil
- * str.downcase!([options]) -> str or nil
+ * downcase!(*options) -> self or nil
+ *
+ * Downcases the characters in +self+;
+ * returns +self+ if any changes were made, +nil+ otherwise:
*
- * Downcases the contents of <i>str</i>, returning <code>nil</code> if no
- * changes were made.
+ * s = 'Hello World!' # => "Hello World!"
+ * s.downcase! # => "hello world!"
+ * s # => "hello world!"
+ * s.downcase! # => nil
+ *
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#downcase, String#upcase, String#upcase!.
*
- * See String#downcase for meaning of +options+ and use with different encodings.
*/
static VALUE
@@ -7001,7 +7574,7 @@ rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
else if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, str, &flags, enc);
else
- str_shared_replace(str, rb_str_casemap(str, &flags, enc));
+ str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
@@ -7010,52 +7583,18 @@ rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.downcase -> new_str
- * str.downcase([options]) -> new_str
- *
- * Returns a copy of <i>str</i> with all uppercase letters replaced with their
- * lowercase counterparts. Which letters exactly are replaced, and by which
- * other letters, depends on the presence or absence of options, and on the
- * +encoding+ of the string.
+ * downcase(*options) -> string
*
- * The meaning of the +options+ is as follows:
+ * Returns a string containing the downcased characters in +self+:
*
- * No option ::
- * Full Unicode case mapping, suitable for most languages
- * (see :turkic and :lithuanian options below for exceptions).
- * Context-dependent case mapping as described in Table 3-14 of the
- * Unicode standard is currently not supported.
- * :ascii ::
- * Only the ASCII region, i.e. the characters ``A'' to ``Z'' and
- * ``a'' to ``z'', are affected.
- * This option cannot be combined with any other option.
- * :turkic ::
- * Full Unicode case mapping, adapted for Turkic languages
- * (Turkish, Azerbaijani, ...). This means that upper case I is mapped to
- * lower case dotless i, and so on.
- * :lithuanian ::
- * Currently, just full Unicode case mapping. In the future, full Unicode
- * case mapping adapted for Lithuanian (keeping the dot on the lower case
- * i even if there is an accent on top).
- * :fold ::
- * Only available on +downcase+ and +downcase!+. Unicode case <b>folding</b>,
- * which is more far-reaching than Unicode case mapping.
- * This option currently cannot be combined with any other option
- * (i.e. there is currently no variant for turkic languages).
+ * s = 'Hello World!' # => "Hello World!"
+ * s.downcase # => "hello world!"
*
- * Please note that several assumptions that are valid for ASCII-only case
- * conversions do not hold for more general case conversions. For example,
- * the length of the result may not be the same as the length of the input
- * (neither in characters nor in bytes), some roundtrip assumptions
- * (e.g. str.downcase == str.upcase.downcase) may not apply, and Unicode
- * normalization (i.e. String#unicode_normalize) is not necessarily maintained
- * by case mapping operations.
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
*
- * Non-ASCII case mapping/folding is currently supported for UTF-8,
- * UTF-16BE/LE, UTF-32BE/LE, and ISO-8859-1~16 Strings/Symbols.
- * This support will be extended to other encodings.
+ * Related: String#downcase!, String#upcase, String#upcase!.
*
- * "hEllO".downcase #=> "hello"
*/
static VALUE
@@ -7086,20 +7625,22 @@ rb_str_downcase(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.capitalize! -> str or nil
- * str.capitalize!([options]) -> str or nil
+ * capitalize!(*options) -> self or nil
*
- * Modifies <i>str</i> by converting the first character to uppercase and the
- * remainder to lowercase. Returns <code>nil</code> if no changes are made.
- * There is an exception for modern Georgian (mkhedruli/MTAVRULI), where
- * the result is the same as for String#downcase, to avoid mixed case.
+ * Upcases the first character in +self+;
+ * downcases the remaining characters;
+ * returns +self+ if any changes were made, +nil+ otherwise:
*
- * See String#downcase for meaning of +options+ and use with different encodings.
+ * s = 'hello World!' # => "hello World!"
+ * s.capitalize! # => "Hello world!"
+ * s # => "Hello world!"
+ * s.capitalize! # => nil
+ *
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#capitalize.
*
- * a = "hello"
- * a.capitalize! #=> "Hello"
- * a #=> "Hello"
- * a.capitalize! #=> nil
*/
static VALUE
@@ -7115,7 +7656,7 @@ rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, str, &flags, enc);
else
- str_shared_replace(str, rb_str_casemap(str, &flags, enc));
+ str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
@@ -7124,17 +7665,20 @@ rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.capitalize -> new_str
- * str.capitalize([options]) -> new_str
+ * capitalize(*options) -> string
+ *
+ * Returns a string containing the characters in +self+;
+ * the first character is upcased;
+ * the remaining characters are downcased:
*
- * Returns a copy of <i>str</i> with the first character converted to uppercase
- * and the remainder to lowercase.
+ * s = 'hello World!' # => "hello World!"
+ * s.capitalize # => "Hello world!"
*
- * See String#downcase for meaning of +options+ and use with different encodings.
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#capitalize!.
*
- * "hello".capitalize #=> "Hello"
- * "HELLO".capitalize #=> "Hello"
- * "123ABC".capitalize #=> "123abc"
*/
static VALUE
@@ -7160,14 +7704,22 @@ rb_str_capitalize(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.swapcase! -> str or nil
- * str.swapcase!([options]) -> str or nil
+ * swapcase!(*options) -> self or nil
+ *
+ * Upcases each lowercase character in +self+;
+ * downcases uppercase character;
+ * returns +self+ if any changes were made, +nil+ otherwise:
+ *
+ * s = 'Hello World!' # => "Hello World!"
+ * s.swapcase! # => "hELLO wORLD!"
+ * s # => "hELLO wORLD!"
+ * ''.swapcase! # => nil
*
- * Equivalent to String#swapcase, but modifies the receiver in place,
- * returning <i>str</i>, or <code>nil</code> if no changes were made.
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
+ * Related: String#swapcase.
*
- * See String#downcase for meaning of +options+ and use with
- * different encodings.
*/
static VALUE
@@ -7182,7 +7734,7 @@ rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
if (flags&ONIGENC_CASE_ASCII_ONLY)
rb_str_ascii_casemap(str, str, &flags, enc);
else
- str_shared_replace(str, rb_str_casemap(str, &flags, enc));
+ str_shared_replace(str, rb_str_casemap(str, &flags, enc));
if (ONIGENC_CASE_MODIFIED&flags) return str;
return Qnil;
@@ -7191,16 +7743,20 @@ rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.swapcase -> new_str
- * str.swapcase([options]) -> new_str
+ * swapcase(*options) -> string
+ *
+ * Returns a string containing the characters in +self+, with cases reversed;
+ * each uppercase character is downcased;
+ * each lowercase character is upcased:
+ *
+ * s = 'Hello World!' # => "Hello World!"
+ * s.swapcase # => "hELLO wORLD!"
*
- * Returns a copy of <i>str</i> with uppercase alphabetic characters converted
- * to lowercase and lowercase characters converted to uppercase.
+ * The casing may be affected by the given +options+;
+ * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
*
- * See String#downcase for meaning of +options+ and use with different encodings.
+ * Related: String#swapcase!.
*
- * "Hello".swapcase #=> "hELLO"
- * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"
*/
static VALUE
@@ -7238,50 +7794,50 @@ trnext(struct tr *t, rb_encoding *enc)
for (;;) {
nextpart:
- if (!t->gen) {
- 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;
- }
- t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
- t->p += n;
- if (rb_enc_ascget(t->p, t->pend, &n, enc) == '-' && t->p + n < t->pend) {
- t->p += n;
- if (t->p < t->pend) {
- unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
- t->p += n;
- if (t->now > c) {
- if (t->now < 0x80 && c < 0x80) {
- rb_raise(rb_eArgError,
- "invalid range \"%c-%c\" in string transliteration",
- t->now, c);
- }
- else {
- rb_raise(rb_eArgError, "invalid range in string transliteration");
- }
- continue; /* not reached */
- }
- t->gen = 1;
- t->max = c;
- }
- }
- return t->now;
- }
- else {
- while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
- if (t->now == t->max) {
- t->gen = 0;
- goto nextpart;
- }
- }
- if (t->now < t->max) {
- return t->now;
- }
- else {
- t->gen = 0;
- return t->max;
- }
- }
+ if (!t->gen) {
+ 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;
+ }
+ t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
+ t->p += n;
+ if (rb_enc_ascget(t->p, t->pend, &n, enc) == '-' && t->p + n < t->pend) {
+ t->p += n;
+ if (t->p < t->pend) {
+ unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
+ t->p += n;
+ if (t->now > c) {
+ if (t->now < 0x80 && c < 0x80) {
+ rb_raise(rb_eArgError,
+ "invalid range \"%c-%c\" in string transliteration",
+ t->now, c);
+ }
+ else {
+ rb_raise(rb_eArgError, "invalid range in string transliteration");
+ }
+ continue; /* not reached */
+ }
+ t->gen = 1;
+ t->max = c;
+ }
+ }
+ return t->now;
+ }
+ else {
+ while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
+ if (t->now == t->max) {
+ t->gen = 0;
+ goto nextpart;
+ }
+ }
+ if (t->now < t->max) {
+ return t->now;
+ }
+ else {
+ t->gen = 0;
+ return t->max;
+ }
+ }
}
}
@@ -7305,30 +7861,30 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
#define CHECK_IF_ASCII(c) \
(void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \
- (cr = ENC_CODERANGE_VALID) : 0)
+ (cr = ENC_CODERANGE_VALID) : 0)
StringValue(src);
StringValue(repl);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
if (RSTRING_LEN(repl) == 0) {
- return rb_str_delete_bang(1, &src, str);
+ return rb_str_delete_bang(1, &src, str);
}
cr = ENC_CODERANGE(str);
e1 = rb_enc_check(str, src);
e2 = rb_enc_check(str, repl);
if (e1 == e2) {
- enc = e1;
+ enc = e1;
}
else {
- enc = rb_enc_check(src, repl);
+ enc = rb_enc_check(src, repl);
}
trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src);
if (RSTRING_LEN(src) > 1 &&
- rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) == '^' &&
- trsrc.p + l < trsrc.pend) {
- cflag = 1;
- trsrc.p += l;
+ rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) == '^' &&
+ trsrc.p + l < trsrc.pend) {
+ cflag = 1;
+ trsrc.p += l;
}
trrepl.p = RSTRING_PTR(repl);
trrepl.pend = trrepl.p + RSTRING_LEN(repl);
@@ -7337,198 +7893,198 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
trsrc.max = trrepl.max = 0;
if (cflag) {
- for (i=0; i<256; i++) {
- trans[i] = 1;
- }
- while ((c = trnext(&trsrc, enc)) != errc) {
- if (c < 256) {
- trans[c] = errc;
- }
- else {
- if (!hash) hash = rb_hash_new();
- rb_hash_aset(hash, UINT2NUM(c), Qtrue);
- }
- }
- while ((c = trnext(&trrepl, enc)) != errc)
- /* retrieve last replacer */;
- last = trrepl.now;
- for (i=0; i<256; i++) {
- if (trans[i] != errc) {
- trans[i] = last;
- }
- }
+ for (i=0; i<256; i++) {
+ trans[i] = 1;
+ }
+ while ((c = trnext(&trsrc, enc)) != errc) {
+ if (c < 256) {
+ trans[c] = errc;
+ }
+ else {
+ if (!hash) hash = rb_hash_new();
+ rb_hash_aset(hash, UINT2NUM(c), Qtrue);
+ }
+ }
+ while ((c = trnext(&trrepl, enc)) != errc)
+ /* retrieve last replacer */;
+ last = trrepl.now;
+ for (i=0; i<256; i++) {
+ if (trans[i] != errc) {
+ trans[i] = last;
+ }
+ }
}
else {
- unsigned int r;
-
- for (i=0; i<256; i++) {
- trans[i] = errc;
- }
- while ((c = trnext(&trsrc, enc)) != errc) {
- r = trnext(&trrepl, enc);
- if (r == errc) r = trrepl.now;
- if (c < 256) {
- trans[c] = r;
- if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
- }
- else {
- if (!hash) hash = rb_hash_new();
- rb_hash_aset(hash, UINT2NUM(c), UINT2NUM(r));
- }
- }
+ unsigned int r;
+
+ for (i=0; i<256; i++) {
+ trans[i] = errc;
+ }
+ while ((c = trnext(&trsrc, enc)) != errc) {
+ r = trnext(&trrepl, enc);
+ if (r == errc) r = trrepl.now;
+ if (c < 256) {
+ trans[c] = r;
+ if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
+ }
+ else {
+ if (!hash) hash = rb_hash_new();
+ rb_hash_aset(hash, UINT2NUM(c), UINT2NUM(r));
+ }
+ }
}
if (cr == ENC_CODERANGE_VALID && rb_enc_asciicompat(e1))
- cr = ENC_CODERANGE_7BIT;
+ cr = ENC_CODERANGE_7BIT;
str_modify_keep_cr(str);
s = (unsigned char *)RSTRING_PTR(str); send = (unsigned char *)RSTRING_END(str);
termlen = rb_enc_mbminlen(enc);
if (sflag) {
- int clen, tlen;
- long offset, max = RSTRING_LEN(str);
- unsigned int save = -1;
+ int clen, tlen;
+ long offset, max = RSTRING_LEN(str);
+ unsigned int save = -1;
unsigned char *buf = ALLOC_N(unsigned char, max + termlen), *t = buf;
- while (s < send) {
- int may_modify = 0;
+ while (s < send) {
+ int may_modify = 0;
c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1);
- tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
-
- s += clen;
- if (c < 256) {
- c = trans[c];
- }
- else if (hash) {
- VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
- if (NIL_P(tmp)) {
- if (cflag) c = last;
- else c = errc;
- }
- else if (cflag) c = errc;
- else c = NUM2INT(tmp);
- }
- else {
- c = errc;
- }
- if (c != (unsigned int)-1) {
- if (save == c) {
- CHECK_IF_ASCII(c);
- continue;
- }
- save = c;
- tlen = rb_enc_codelen(c, enc);
- modify = 1;
- }
- else {
- save = -1;
- c = c0;
- if (enc != e1) may_modify = 1;
- }
- if ((offset = t - buf) + tlen > max) {
- size_t MAYBE_UNUSED(old) = max + termlen;
- max = offset + tlen + (send - s);
+ tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
+
+ s += clen;
+ if (c < 256) {
+ c = trans[c];
+ }
+ else if (hash) {
+ VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
+ if (NIL_P(tmp)) {
+ if (cflag) c = last;
+ else c = errc;
+ }
+ else if (cflag) c = errc;
+ else c = NUM2INT(tmp);
+ }
+ else {
+ c = errc;
+ }
+ if (c != (unsigned int)-1) {
+ if (save == c) {
+ CHECK_IF_ASCII(c);
+ continue;
+ }
+ save = c;
+ tlen = rb_enc_codelen(c, enc);
+ modify = 1;
+ }
+ else {
+ save = -1;
+ c = c0;
+ if (enc != e1) may_modify = 1;
+ }
+ if ((offset = t - buf) + tlen > max) {
+ size_t MAYBE_UNUSED(old) = max + termlen;
+ max = offset + tlen + (send - s);
SIZED_REALLOC_N(buf, unsigned char, max + termlen, old);
- t = buf + offset;
- }
- rb_enc_mbcput(c, t, enc);
- if (may_modify && memcmp(s, t, tlen) != 0) {
- modify = 1;
- }
- CHECK_IF_ASCII(c);
- t += tlen;
- }
- if (!STR_EMBED_P(str)) {
- ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
- }
+ t = buf + offset;
+ }
+ rb_enc_mbcput(c, t, enc);
+ if (may_modify && memcmp(s, t, tlen) != 0) {
+ modify = 1;
+ }
+ CHECK_IF_ASCII(c);
+ t += tlen;
+ }
+ if (!STR_EMBED_P(str)) {
+ ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
+ }
TERM_FILL((char *)t, termlen);
RSTRING(str)->as.heap.ptr = (char *)buf;
- RSTRING(str)->as.heap.len = t - buf;
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.aux.capa = max;
+ RSTRING(str)->as.heap.len = t - buf;
+ STR_SET_NOEMBED(str);
+ RSTRING(str)->as.heap.aux.capa = max;
}
else if (rb_enc_mbmaxlen(enc) == 1 || (singlebyte && !hash)) {
- while (s < send) {
- c = (unsigned char)*s;
- if (trans[c] != errc) {
- if (!cflag) {
- c = trans[c];
- *s = c;
- modify = 1;
- }
- else {
- *s = last;
- modify = 1;
- }
- }
- CHECK_IF_ASCII(c);
- s++;
- }
+ while (s < send) {
+ c = (unsigned char)*s;
+ if (trans[c] != errc) {
+ if (!cflag) {
+ c = trans[c];
+ *s = c;
+ modify = 1;
+ }
+ else {
+ *s = last;
+ modify = 1;
+ }
+ }
+ CHECK_IF_ASCII(c);
+ s++;
+ }
}
else {
- int clen, tlen;
- long offset, max = (long)((send - s) * 1.2);
+ int clen, tlen;
+ long offset, max = (long)((send - s) * 1.2);
unsigned char *buf = ALLOC_N(unsigned char, max + termlen), *t = buf;
- while (s < send) {
- int may_modify = 0;
+ while (s < send) {
+ int may_modify = 0;
c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1);
- tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
-
- if (c < 256) {
- c = trans[c];
- }
- else if (hash) {
- VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
- if (NIL_P(tmp)) {
- if (cflag) c = last;
- else c = errc;
- }
- else if (cflag) c = errc;
- else c = NUM2INT(tmp);
- }
- else {
- c = cflag ? last : errc;
- }
- if (c != errc) {
- tlen = rb_enc_codelen(c, enc);
- modify = 1;
- }
- else {
- c = c0;
- if (enc != e1) may_modify = 1;
- }
- if ((offset = t - buf) + tlen > max) {
- size_t MAYBE_UNUSED(old) = max + termlen;
- max = offset + tlen + (long)((send - s) * 1.2);
+ tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
+
+ if (c < 256) {
+ c = trans[c];
+ }
+ else if (hash) {
+ VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
+ if (NIL_P(tmp)) {
+ if (cflag) c = last;
+ else c = errc;
+ }
+ else if (cflag) c = errc;
+ else c = NUM2INT(tmp);
+ }
+ else {
+ c = cflag ? last : errc;
+ }
+ if (c != errc) {
+ tlen = rb_enc_codelen(c, enc);
+ modify = 1;
+ }
+ else {
+ c = c0;
+ if (enc != e1) may_modify = 1;
+ }
+ if ((offset = t - buf) + tlen > max) {
+ size_t MAYBE_UNUSED(old) = max + termlen;
+ max = offset + tlen + (long)((send - s) * 1.2);
SIZED_REALLOC_N(buf, unsigned char, max + termlen, old);
- t = buf + offset;
- }
- if (s != t) {
- rb_enc_mbcput(c, t, enc);
- if (may_modify && memcmp(s, t, tlen) != 0) {
- modify = 1;
- }
- }
- CHECK_IF_ASCII(c);
- s += clen;
- t += tlen;
- }
- if (!STR_EMBED_P(str)) {
- ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
- }
+ t = buf + offset;
+ }
+ if (s != t) {
+ rb_enc_mbcput(c, t, enc);
+ if (may_modify && memcmp(s, t, tlen) != 0) {
+ modify = 1;
+ }
+ }
+ CHECK_IF_ASCII(c);
+ s += clen;
+ t += tlen;
+ }
+ if (!STR_EMBED_P(str)) {
+ ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
+ }
TERM_FILL((char *)t, termlen);
RSTRING(str)->as.heap.ptr = (char *)buf;
- RSTRING(str)->as.heap.len = t - buf;
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.aux.capa = max;
+ RSTRING(str)->as.heap.len = t - buf;
+ STR_SET_NOEMBED(str);
+ RSTRING(str)->as.heap.aux.capa = max;
}
if (modify) {
- if (cr != ENC_CODERANGE_BROKEN)
- ENC_CODERANGE_SET(str, cr);
- rb_enc_associate(str, enc);
- return str;
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(str, cr);
+ rb_enc_associate(str, enc);
+ return str;
}
return Qnil;
}
@@ -7536,11 +8092,11 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
/*
* call-seq:
- * str.tr!(from_str, to_str) -> str or nil
+ * tr!(selector, replacements) -> self or nil
+ *
+ * Like String#tr, but modifies +self+ in place.
+ * Returns +self+ if any changes were made, +nil+ otherwise.
*
- * Translates <i>str</i> in place, using the same rules as
- * String#tr. Returns <i>str</i>, or <code>nil</code> if no changes
- * were made.
*/
static VALUE
@@ -7552,37 +8108,41 @@ rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
/*
* call-seq:
- * str.tr(from_str, to_str) => new_str
+ * tr(selector, replacements) -> new_string
*
- * Returns a copy of +str+ with the characters in +from_str+ replaced by the
- * corresponding characters in +to_str+. If +to_str+ is shorter than
- * +from_str+, it is padded with its last character in order to maintain the
- * correspondence.
+ * Returns a copy of +self+ with each character specified by string +selector+
+ * translated to the corresponding character in string +replacements+.
+ * The correspondence is _positional_:
*
- * "hello".tr('el', 'ip') #=> "hippo"
- * "hello".tr('aeiou', '*') #=> "h*ll*"
- * "hello".tr('aeiou', 'AA*') #=> "hAll*"
+ * - Each occurrence of the first character specified by +selector+
+ * is translated to the first character in +replacements+.
+ * - Each occurrence of the second character specified by +selector+
+ * is translated to the second character in +replacements+.
+ * - And so on.
*
- * Both strings may use the <code>c1-c2</code> notation to denote ranges of
- * characters, and +from_str+ may start with a <code>^</code>, which denotes
- * all characters except those listed.
+ * Example:
*
- * "hello".tr('a-y', 'b-z') #=> "ifmmp"
- * "hello".tr('^aeiou', '*') #=> "*e**o"
+ * 'hello'.tr('el', 'ip') #=> "hippo"
*
- * The backslash character <code>\\</code> can be used to escape
- * <code>^</code> or <code>-</code> and is otherwise ignored unless it
- * appears at the end of a range or the end of the +from_str+ or +to_str+:
+ * If +replacements+ is shorter than +selector+,
+ * it is implicitly padded with its own last character:
*
- * "hello^world".tr("\\^aeiou", "*") #=> "h*ll**w*rld"
- * "hello-world".tr("a\\-eo", "*") #=> "h*ll**w*rld"
+ * 'hello'.tr('aeiou', '-') # => "h-ll-"
+ * 'hello'.tr('aeiou', 'AA-') # => "hAll-"
*
- * "hello\r\nworld".tr("\r", "") #=> "hello\nworld"
- * "hello\r\nworld".tr("\\r", "") #=> "hello\r\nwold"
- * "hello\r\nworld".tr("\\\r", "") #=> "hello\nworld"
+ * Arguments +selector+ and +replacements+ must be valid character selectors
+ * (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
+ * and may use any of its valid forms, including negation, ranges, and escaping:
+ *
+ * # Negation.
+ * 'hello'.tr('^aeiou', '-') # => "-e--o"
+ * # Ranges.
+ * 'ibm'.tr('b-z', 'a-z') # => "hal"
+ * # Escapes.
+ * 'hel^lo'.tr('\^aeiou', '-') # => "h-l-l-" # Escaped leading caret.
+ * 'i-b-m'.tr('b\-z', 'a-z') # => "ibabm" # Escaped embedded hyphen.
+ * 'foo\\bar'.tr('ab\\', 'XYZ') # => "fooZYXr" # Escaped backslash.
*
- * "X['\\b']".tr("X\\", "") #=> "['b']"
- * "X['\\b']".tr("X-\\]", "") #=> "'b'"
*/
static VALUE
@@ -7597,7 +8157,7 @@ rb_str_tr(VALUE str, VALUE src, VALUE repl)
#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)
+ VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
{
const unsigned int errc = -1;
char buf[TR_TABLE_MAX];
@@ -7610,51 +8170,51 @@ tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first,
tr.gen = tr.now = tr.max = 0;
if (RSTRING_LEN(str) > 1 && rb_enc_ascget(tr.p, tr.pend, &l, enc) == '^') {
- cflag = 1;
- tr.p += l;
+ cflag = 1;
+ tr.p += l;
}
if (first) {
- for (i=0; i<TR_TABLE_MAX; i++) {
- stable[i] = 1;
- }
- stable[TR_TABLE_MAX] = cflag;
+ for (i=0; i<TR_TABLE_MAX; i++) {
+ stable[i] = 1;
+ }
+ stable[TR_TABLE_MAX] = cflag;
}
else if (stable[TR_TABLE_MAX] && !cflag) {
- stable[TR_TABLE_MAX] = 0;
+ stable[TR_TABLE_MAX] = 0;
}
for (i=0; i<TR_TABLE_MAX; i++) {
- buf[i] = cflag;
+ buf[i] = cflag;
}
while ((c = trnext(&tr, enc)) != errc) {
- if (c < TR_TABLE_MAX) {
- buf[(unsigned char)c] = !cflag;
- }
- else {
- VALUE key = UINT2NUM(c);
-
- if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
- if (cflag) {
- ptable = *ctablep;
- table = ptable ? ptable : rb_hash_new();
- *ctablep = table;
- }
- else {
- table = rb_hash_new();
- ptable = *tablep;
- *tablep = table;
- }
- }
- if (table && (!ptable || (cflag ^ !NIL_P(rb_hash_aref(ptable, key))))) {
- rb_hash_aset(table, key, Qtrue);
- }
- }
+ if (c < TR_TABLE_MAX) {
+ buf[(unsigned char)c] = !cflag;
+ }
+ else {
+ VALUE key = UINT2NUM(c);
+
+ if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
+ if (cflag) {
+ ptable = *ctablep;
+ table = ptable ? ptable : rb_hash_new();
+ *ctablep = table;
+ }
+ else {
+ table = rb_hash_new();
+ ptable = *tablep;
+ *tablep = table;
+ }
+ }
+ if (table && (!ptable || (cflag ^ !NIL_P(rb_hash_aref(ptable, key))))) {
+ rb_hash_aset(table, key, Qtrue);
+ }
+ }
}
for (i=0; i<TR_TABLE_MAX; i++) {
- stable[i] = stable[i] && buf[i];
+ stable[i] = stable[i] && buf[i];
}
if (!table && !cflag) {
- *tablep = 0;
+ *tablep = 0;
}
}
@@ -7663,30 +8223,31 @@ static int
tr_find(unsigned int c, const char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
{
if (c < TR_TABLE_MAX) {
- return table[c] != 0;
+ return table[c] != 0;
}
else {
- VALUE v = UINT2NUM(c);
+ VALUE v = UINT2NUM(c);
- if (del) {
- if (!NIL_P(rb_hash_lookup(del, v)) &&
- (!nodel || NIL_P(rb_hash_lookup(nodel, v)))) {
- return TRUE;
- }
- }
- else if (nodel && !NIL_P(rb_hash_lookup(nodel, v))) {
- return FALSE;
- }
- return table[TR_TABLE_MAX] ? TRUE : FALSE;
+ if (del) {
+ if (!NIL_P(rb_hash_lookup(del, v)) &&
+ (!nodel || NIL_P(rb_hash_lookup(nodel, v)))) {
+ return TRUE;
+ }
+ }
+ else if (nodel && !NIL_P(rb_hash_lookup(nodel, v))) {
+ return FALSE;
+ }
+ return table[TR_TABLE_MAX] ? TRUE : FALSE;
}
}
/*
* call-seq:
- * str.delete!([other_str]+) -> str or nil
+ * delete!(*selectors) -> self or nil
+ *
+ * Like String#delete, but modifies +self+ in place.
+ * Returns +self+ if any changes were made, +nil+ otherwise.
*
- * Performs a <code>delete</code> operation in place, returning <i>str</i>, or
- * <code>nil</code> if <i>str</i> was not modified.
*/
static VALUE
@@ -7702,11 +8263,11 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i=0; i<argc; i++) {
- VALUE s = argv[i];
+ VALUE s = argv[i];
- StringValue(s);
- enc = rb_enc_check(str, s);
- tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
+ StringValue(s);
+ enc = rb_enc_check(str, s);
+ tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
str_modify_keep_cr(str);
@@ -7715,32 +8276,32 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
send = RSTRING_END(str);
cr = ascompat ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
while (s < send) {
- unsigned int c;
- int clen;
-
- if (ascompat && (c = *(unsigned char*)s) < 0x80) {
- if (squeez[c]) {
- modify = 1;
- }
- else {
- if (t != s) *t = c;
- t++;
- }
- s++;
- }
- else {
- c = rb_enc_codepoint_len(s, send, &clen, enc);
-
- if (tr_find(c, squeez, del, nodel)) {
- modify = 1;
- }
- else {
- if (t != s) rb_enc_mbcput(c, t, enc);
- t += clen;
- if (cr == ENC_CODERANGE_7BIT) cr = ENC_CODERANGE_VALID;
- }
- s += clen;
- }
+ unsigned int c;
+ int clen;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (squeez[c]) {
+ modify = 1;
+ }
+ else {
+ if (t != s) *t = c;
+ t++;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint_len(s, send, &clen, enc);
+
+ if (tr_find(c, squeez, del, nodel)) {
+ modify = 1;
+ }
+ else {
+ if (t != s) rb_enc_mbcput(c, t, enc);
+ t += clen;
+ if (cr == ENC_CODERANGE_7BIT) cr = ENC_CODERANGE_VALID;
+ }
+ s += clen;
+ }
}
TERM_FILL(t, TERM_LEN(str));
STR_SET_LEN(str, t - RSTRING_PTR(str));
@@ -7753,16 +8314,16 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.delete([other_str]+) -> new_str
+ * delete(*selectors) -> new_string
*
- * Returns a copy of <i>str</i> with all characters in the intersection of its
- * arguments deleted. Uses the same rules for building the set of characters as
- * String#count.
+ * Returns a copy of +self+ with characters specified by +selectors+ removed
+ * (see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors]):
*
* "hello".delete "l","lo" #=> "heo"
* "hello".delete "lo" #=> "he"
* "hello".delete "aeiou", "^e" #=> "hell"
* "hello".delete "ej-m" #=> "ho"
+ *
*/
static VALUE
@@ -7776,10 +8337,10 @@ rb_str_delete(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.squeeze!([other_str]*) -> str or nil
+ * squeeze!(*selectors) -> self or nil
*
- * Squeezes <i>str</i> in place, returning either <i>str</i>, or
- * <code>nil</code> if no changes were made.
+ * Like String#squeeze, but modifies +self+ in place.
+ * Returns +self+ if any changes were made, +nil+ otherwise.
*/
static VALUE
@@ -7794,18 +8355,18 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
unsigned int save;
if (argc == 0) {
- enc = STR_ENC_GET(str);
+ enc = STR_ENC_GET(str);
}
else {
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- enc = rb_enc_check(str, s);
- if (singlebyte && !single_byte_optimizable(s))
- singlebyte = 0;
- tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
- }
+ for (i=0; i<argc; i++) {
+ VALUE s = argv[i];
+
+ StringValue(s);
+ enc = rb_enc_check(str, s);
+ if (singlebyte && !single_byte_optimizable(s))
+ singlebyte = 0;
+ tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
+ }
}
str_modify_keep_cr(str);
@@ -7818,39 +8379,39 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
if (singlebyte) {
while (s < send) {
unsigned int c = *s++;
- if (c != save || (argc > 0 && !squeez[c])) {
- *t++ = save = c;
- }
- }
+ if (c != save || (argc > 0 && !squeez[c])) {
+ *t++ = save = c;
+ }
+ }
}
else {
- while (s < send) {
- unsigned int c;
- int clen;
+ while (s < send) {
+ unsigned int c;
+ int clen;
if (ascompat && (c = *s) < 0x80) {
- if (c != save || (argc > 0 && !squeez[c])) {
- *t++ = save = c;
- }
- s++;
- }
- else {
+ if (c != save || (argc > 0 && !squeez[c])) {
+ *t++ = save = c;
+ }
+ s++;
+ }
+ else {
c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, enc);
- if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
- if (t != s) rb_enc_mbcput(c, t, enc);
- save = c;
- t += clen;
- }
- s += clen;
- }
- }
+ if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
+ if (t != s) rb_enc_mbcput(c, t, enc);
+ save = c;
+ t += clen;
+ }
+ s += clen;
+ }
+ }
}
TERM_FILL((char *)t, TERM_LEN(str));
if ((char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
STR_SET_LEN(str, (char *)t - RSTRING_PTR(str));
- modify = 1;
+ modify = 1;
}
if (modify) return str;
@@ -7860,17 +8421,19 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.squeeze([other_str]*) -> new_str
+ * squeeze(*selectors) -> new_string
*
- * Builds a set of characters from the <i>other_str</i> parameter(s)
- * using the procedure described for String#count. Returns a new
- * string where runs of the same character that occur in this set are
- * replaced by a single character. If no arguments are given, all
- * runs of identical characters are replaced by a single character.
+ * Returns a copy of +self+ with characters specified by +selectors+ "squeezed"
+ * (see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors]):
+ *
+ * "Squeezed" means that each multiple-character run of a selected character
+ * is squeezed down to a single character;
+ * with no arguments given, squeezes all characters:
*
* "yellow moon".squeeze #=> "yelow mon"
* " now is the".squeeze(" ") #=> " now is the"
* "putters shoot balls".squeeze("m-z") #=> "puters shot balls"
+ *
*/
static VALUE
@@ -7884,10 +8447,12 @@ rb_str_squeeze(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.tr_s!(from_str, to_str) -> str or nil
+ * tr_s!(selector, replacements) -> self or nil
+ *
+ * Like String#tr_s, but modifies +self+ in place.
+ * Returns +self+ if any changes were made, +nil+ otherwise.
*
- * Performs String#tr_s processing on <i>str</i> in place,
- * returning <i>str</i>, or <code>nil</code> if no changes were made.
+ * Related: String#squeeze!.
*/
static VALUE
@@ -7899,15 +8464,17 @@ rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
/*
* call-seq:
- * str.tr_s(from_str, to_str) -> new_str
+ * tr_s(selector, replacements) -> string
*
- * Processes a copy of <i>str</i> as described under String#tr, then
- * removes duplicate characters in regions that were affected by the
- * translation.
+ * Like String#tr, but also squeezes the modified portions of the translated string;
+ * returns a new string (translated and squeezed).
+ *
+ * 'hello'.tr_s('l', 'r') #=> "hero"
+ * 'hello'.tr_s('el', '-') #=> "h-o"
+ * 'hello'.tr_s('el', 'hx') #=> "hhxo"
+ *
+ * Related: String#squeeze.
*
- * "hello".tr_s('l', 'r') #=> "hero"
- * "hello".tr_s('el', '*') #=> "h*o"
- * "hello".tr_s('el', 'hx') #=> "hhxo"
*/
static VALUE
@@ -7921,15 +8488,11 @@ rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
/*
* call-seq:
- * str.count([other_str]+) -> integer
+ * count(*selectors) -> integer
*
- * Each +other_str+ parameter defines a set of characters to count. The
- * intersection of these sets defines the characters to count in +str+. Any
- * +other_str+ that starts with a caret <code>^</code> is negated. The
- * sequence <code>c1-c2</code> means all characters between c1 and c2. The
- * backslash character <code>\\</code> can be used to escape <code>^</code> or
- * <code>-</code> and is otherwise ignored unless it appears at the end of a
- * sequence or the end of a +other_str+.
+ * Returns the total number of characters in +self+
+ * that are specified by the given +selectors+
+ * (see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors]):
*
* a = "hello world"
* a.count "lo" #=> 5
@@ -7963,30 +8526,30 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
StringValue(tstr);
enc = rb_enc_check(str, tstr);
if (argc == 1) {
- const char *ptstr;
- if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
- (ptstr = RSTRING_PTR(tstr),
- ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (const unsigned char *)ptstr, (const unsigned char *)ptstr+1)) &&
- !is_broken_string(str)) {
- int clen;
- unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
-
- s = RSTRING_PTR(str);
- if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
- send = RSTRING_END(str);
- while (s < send) {
- if (*(unsigned char*)s++ == c) n++;
- }
- return SIZET2NUM(n);
- }
+ const char *ptstr;
+ if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
+ (ptstr = RSTRING_PTR(tstr),
+ ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (const unsigned char *)ptstr, (const unsigned char *)ptstr+1)) &&
+ !is_broken_string(str)) {
+ int clen;
+ unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
+
+ s = RSTRING_PTR(str);
+ if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
+ send = RSTRING_END(str);
+ while (s < send) {
+ if (*(unsigned char*)s++ == c) n++;
+ }
+ return SIZET2NUM(n);
+ }
}
tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
for (i=1; i<argc; i++) {
- tstr = argv[i];
- StringValue(tstr);
- enc = rb_enc_check(str, tstr);
- tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
+ tstr = argv[i];
+ StringValue(tstr);
+ enc = rb_enc_check(str, tstr);
+ tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
}
s = RSTRING_PTR(str);
@@ -7994,22 +8557,22 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
send = RSTRING_END(str);
ascompat = rb_enc_asciicompat(enc);
while (s < send) {
- unsigned int c;
-
- if (ascompat && (c = *(unsigned char*)s) < 0x80) {
- if (table[c]) {
- n++;
- }
- s++;
- }
- else {
- int clen;
- c = rb_enc_codepoint_len(s, send, &clen, enc);
- if (tr_find(c, table, del, nodel)) {
- n++;
- }
- s += clen;
- }
+ unsigned int c;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (table[c]) {
+ n++;
+ }
+ s++;
+ }
+ else {
+ int clen;
+ c = rb_enc_codepoint_len(s, send, &clen, enc);
+ if (tr_find(c, table, del, nodel)) {
+ n++;
+ }
+ s += clen;
+ }
}
return SIZET2NUM(n);
@@ -8019,8 +8582,8 @@ static VALUE
rb_fs_check(VALUE val)
{
if (!NIL_P(val) && !RB_TYPE_P(val, T_STRING) && !RB_TYPE_P(val, T_REGEXP)) {
- val = rb_check_string_type(val);
- if (NIL_P(val)) return 0;
+ val = rb_check_string_type(val);
+ if (NIL_P(val)) return 0;
}
return val;
}
@@ -8050,27 +8613,27 @@ static long
split_string(VALUE result, VALUE str, long beg, long len, long empty_count)
{
if (empty_count >= 0 && len == 0) {
- return empty_count + 1;
+ return empty_count + 1;
}
if (empty_count > 0) {
- /* make different substrings */
- if (result) {
- do {
+ /* make different substrings */
+ if (result) {
+ do {
rb_ary_push(result, str_new_empty_String(str));
- } while (--empty_count > 0);
- }
- else {
- do {
+ } while (--empty_count > 0);
+ }
+ else {
+ do {
rb_yield(str_new_empty_String(str));
- } while (--empty_count > 0);
- }
+ } while (--empty_count > 0);
+ }
}
str = rb_str_subseq(str, beg, len);
if (result) {
- rb_ary_push(result, str);
+ rb_ary_push(result, str);
}
else {
- rb_yield(str);
+ rb_yield(str);
}
return empty_count;
}
@@ -8106,56 +8669,10 @@ literal_split_pattern(VALUE spat, split_type_t default_type)
/*
* call-seq:
- * str.split(pattern=nil, [limit]) -> an_array
- * str.split(pattern=nil, [limit]) {|sub| block } -> str
+ * split(field_sep = $;, limit = nil) -> array
+ * split(field_sep = $;, limit = nil) {|substring| ... } -> self
*
- * Divides <i>str</i> into substrings based on a delimiter, returning an array
- * of these substrings.
- *
- * If <i>pattern</i> is a String, then its contents are used as
- * the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single
- * space, <i>str</i> is split on whitespace, with leading and trailing
- * whitespace and runs of contiguous whitespace characters ignored.
- *
- * If <i>pattern</i> is a Regexp, <i>str</i> is divided where the
- * pattern matches. Whenever the pattern matches a zero-length string,
- * <i>str</i> is split into individual characters. If <i>pattern</i> contains
- * groups, the respective matches will be returned in the array as well.
- *
- * If <i>pattern</i> is <code>nil</code>, the value of <code>$;</code> is used.
- * If <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is
- * split on whitespace as if ' ' were specified.
- *
- * If the <i>limit</i> parameter is omitted, trailing null fields are
- * suppressed. If <i>limit</i> is a positive number, at most that number
- * of split substrings will be returned (captured groups will be returned
- * as well, but are not counted towards the limit).
- * If <i>limit</i> is <code>1</code>, the entire
- * string is returned as the only entry in an array. If negative, there is no
- * limit to the number of fields returned, and trailing null fields are not
- * suppressed.
- *
- * When the input +str+ is empty an empty Array is returned as the string is
- * considered to have no fields to split.
- *
- * " now's the time ".split #=> ["now's", "the", "time"]
- * " now's the time ".split(' ') #=> ["now's", "the", "time"]
- * " now's the time".split(/ /) #=> ["", "now's", "", "the", "time"]
- * "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
- * "hello".split(//) #=> ["h", "e", "l", "l", "o"]
- * "hello".split(//, 3) #=> ["h", "e", "llo"]
- * "hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"]
- *
- * "mellow yellow".split("ello") #=> ["m", "w y", "w"]
- * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"]
- * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"]
- * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""]
- *
- * "1:2:3".split(/(:)()()/, 2) #=> ["1", ":", "", "", "2:3"]
- *
- * "".split(',', -1) #=> []
- *
- * If a block is given, invoke the block with each split substring.
+ * :include: doc/string/split.rdoc
*
*/
@@ -8172,32 +8689,32 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
result = rb_block_given_p() ? Qfalse : Qnil;
if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
- lim = NUM2INT(limit);
- if (lim <= 0) limit = Qnil;
- else if (lim == 1) {
- if (RSTRING_LEN(str) == 0)
+ lim = NUM2INT(limit);
+ if (lim <= 0) limit = Qnil;
+ else if (lim == 1) {
+ if (RSTRING_LEN(str) == 0)
return result ? rb_ary_new2(0) : str;
tmp = str_duplicate(rb_cString, str);
- if (!result) {
- rb_yield(tmp);
+ if (!result) {
+ rb_yield(tmp);
return str;
- }
- return rb_ary_new3(1, tmp);
- }
- i = 1;
+ }
+ return rb_ary_new3(1, tmp);
+ }
+ i = 1;
}
if (NIL_P(limit) && !lim) empty_count = 0;
enc = STR_ENC_GET(str);
split_type = SPLIT_TYPE_REGEXP;
if (!NIL_P(spat)) {
- spat = get_pat_quoted(spat, 0);
+ spat = get_pat_quoted(spat, 0);
}
else if (NIL_P(spat = rb_fs)) {
- split_type = 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");
+ rb_raise(rb_eTypeError, "value of $; must be String or Regexp");
}
else {
rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$; is set to non-nil value");
@@ -8215,13 +8732,13 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
break;
case T_STRING:
- mustnot_broken(spat);
+ mustnot_broken(spat);
split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
break;
default:
UNREACHABLE_RETURN(Qnil);
- }
+ }
}
#define SPLIT_STR(beg, len) (empty_count = split_string(result, str, beg, len, empty_count))
@@ -8231,85 +8748,85 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
if (split_type == SPLIT_TYPE_AWK) {
- char *bptr = ptr;
- int skip = 1;
- unsigned int c;
-
- end = beg;
- if (is_ascii_string(str)) {
- while (ptr < eptr) {
- c = (unsigned char)*ptr++;
- if (skip) {
- if (ascii_isspace(c)) {
- beg = ptr - bptr;
- }
- else {
- end = ptr - bptr;
- skip = 0;
- if (!NIL_P(limit) && lim <= i) break;
- }
- }
- else if (ascii_isspace(c)) {
- SPLIT_STR(beg, end-beg);
- skip = 1;
- beg = ptr - bptr;
- if (!NIL_P(limit)) ++i;
- }
- else {
- end = ptr - bptr;
- }
- }
- }
- else {
- while (ptr < eptr) {
- int n;
-
- c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
- ptr += n;
- if (skip) {
- if (rb_isspace(c)) {
- beg = ptr - bptr;
- }
- else {
- end = ptr - bptr;
- skip = 0;
- if (!NIL_P(limit) && lim <= i) break;
- }
- }
- else if (rb_isspace(c)) {
- SPLIT_STR(beg, end-beg);
- skip = 1;
- beg = ptr - bptr;
- if (!NIL_P(limit)) ++i;
- }
- else {
- end = ptr - bptr;
- }
- }
- }
+ char *bptr = ptr;
+ int skip = 1;
+ unsigned int c;
+
+ end = beg;
+ if (is_ascii_string(str)) {
+ while (ptr < eptr) {
+ c = (unsigned char)*ptr++;
+ if (skip) {
+ if (ascii_isspace(c)) {
+ beg = ptr - bptr;
+ }
+ else {
+ end = ptr - bptr;
+ skip = 0;
+ if (!NIL_P(limit) && lim <= i) break;
+ }
+ }
+ else if (ascii_isspace(c)) {
+ SPLIT_STR(beg, end-beg);
+ skip = 1;
+ beg = ptr - bptr;
+ if (!NIL_P(limit)) ++i;
+ }
+ else {
+ end = ptr - bptr;
+ }
+ }
+ }
+ else {
+ while (ptr < eptr) {
+ int n;
+
+ c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
+ ptr += n;
+ if (skip) {
+ if (rb_isspace(c)) {
+ beg = ptr - bptr;
+ }
+ else {
+ end = ptr - bptr;
+ skip = 0;
+ if (!NIL_P(limit) && lim <= i) break;
+ }
+ }
+ else if (rb_isspace(c)) {
+ SPLIT_STR(beg, end-beg);
+ skip = 1;
+ beg = ptr - bptr;
+ if (!NIL_P(limit)) ++i;
+ }
+ else {
+ end = ptr - bptr;
+ }
+ }
+ }
}
else if (split_type == SPLIT_TYPE_STRING) {
- char *str_start = ptr;
- char *substr_start = ptr;
- char *sptr = RSTRING_PTR(spat);
- long slen = RSTRING_LEN(spat);
-
- mustnot_broken(str);
- enc = rb_enc_check(str, spat);
- while (ptr < eptr &&
- (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
- /* Check we are at the start of a char */
- char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
- if (t != ptr + end) {
- ptr = t;
- continue;
- }
- SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
- ptr += end + slen;
- substr_start = ptr;
- if (!NIL_P(limit) && lim <= ++i) break;
- }
- beg = ptr - str_start;
+ char *str_start = ptr;
+ char *substr_start = ptr;
+ char *sptr = RSTRING_PTR(spat);
+ long slen = RSTRING_LEN(spat);
+
+ mustnot_broken(str);
+ enc = rb_enc_check(str, spat);
+ while (ptr < eptr &&
+ (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
+ /* Check we are at the start of a char */
+ char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
+ if (t != ptr + end) {
+ ptr = t;
+ continue;
+ }
+ SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
+ ptr += end + slen;
+ substr_start = ptr;
+ if (!NIL_P(limit) && lim <= ++i) break;
+ }
+ beg = ptr - str_start;
}
else if (split_type == SPLIT_TYPE_CHARS) {
char *str_start = ptr;
@@ -8326,11 +8843,11 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
beg = ptr - str_start;
}
else {
- long len = RSTRING_LEN(str);
- long start = beg;
- long idx;
- int last_null = 0;
- struct re_registers *regs;
+ long len = RSTRING_LEN(str);
+ long start = beg;
+ long idx;
+ int last_null = 0;
+ struct re_registers *regs;
VALUE match = 0;
for (; rb_reg_search(spat, str, start, 0) >= 0;
@@ -8339,40 +8856,40 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
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);
- break;
- }
- else if (last_null == 1) {
+ if (start == end && BEG(0) == END(0)) {
+ if (!ptr) {
+ SPLIT_STR(0, 0);
+ break;
+ }
+ else if (last_null == 1) {
SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, eptr, enc));
- beg = start;
- }
- else {
+ beg = start;
+ }
+ else {
if (start == len)
start++;
else
start += rb_enc_fast_mbclen(ptr+start,eptr,enc);
- last_null = 1;
- continue;
- }
- }
- else {
- SPLIT_STR(beg, end-beg);
- beg = start = END(0);
- }
- last_null = 0;
-
- for (idx=1; idx < regs->num_regs; idx++) {
- if (BEG(idx) == -1) continue;
- SPLIT_STR(BEG(idx), END(idx)-BEG(idx));
- }
- if (!NIL_P(limit) && lim <= ++i) break;
- }
+ last_null = 1;
+ continue;
+ }
+ }
+ else {
+ SPLIT_STR(beg, end-beg);
+ beg = start = END(0);
+ }
+ last_null = 0;
+
+ for (idx=1; idx < regs->num_regs; idx++) {
+ if (BEG(idx) == -1) continue;
+ SPLIT_STR(BEG(idx), END(idx)-BEG(idx));
+ }
+ if (!NIL_P(limit) && lim <= ++i) break;
+ }
if (match) rb_match_unbusy(match);
}
if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
- SPLIT_STR(beg, RSTRING_LEN(str)-beg);
+ SPLIT_STR(beg, RSTRING_LEN(str)-beg);
}
return result ? result : str;
@@ -8394,12 +8911,12 @@ static inline int
enumerator_element(VALUE ary, VALUE e)
{
if (ary) {
- rb_ary_push(ary, e);
- return 0;
+ rb_ary_push(ary, e);
+ return 0;
}
else {
- rb_yield(e);
- return 1;
+ rb_yield(e);
+ return 1;
}
}
@@ -8410,10 +8927,10 @@ chomp_newline(const char *p, const char *e, rb_encoding *enc)
{
const char *prev = rb_enc_prev_char(p, e, e, enc);
if (rb_enc_is_newline(prev, e, enc)) {
- e = prev;
- prev = rb_enc_prev_char(p, e, e, enc);
- if (prev && rb_enc_ascget(prev, e, NULL, enc) == '\r')
- e = prev;
+ e = prev;
+ prev = rb_enc_prev_char(p, e, e, enc);
+ if (prev && rb_enc_ascget(prev, e, NULL, enc) == '\r')
+ e = prev;
}
return e;
}
@@ -8423,9 +8940,9 @@ 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_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;
@@ -8443,23 +8960,23 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary)
int rsnewline = 0;
if (rb_scan_args(argc, argv, "01:", &rs, &opts) == 0)
- rs = rb_rs;
+ rs = rb_rs;
if (!NIL_P(opts)) {
- static ID keywords[1];
- if (!keywords[0]) {
- keywords[0] = rb_intern_const("chomp");
- }
- rb_get_kwargs(opts, keywords, 0, 1, &chomp);
- chomp = (chomp != Qundef && RTEST(chomp));
+ static ID keywords[1];
+ if (!keywords[0]) {
+ keywords[0] = rb_intern_const("chomp");
+ }
+ rb_get_kwargs(opts, keywords, 0, 1, &chomp);
+ chomp = (!UNDEF_P(chomp) && RTEST(chomp));
}
if (NIL_P(rs)) {
- if (!ENUM_ELEM(ary, str)) {
- return ary;
- }
- else {
- return orig;
- }
+ if (!ENUM_ELEM(ary, str)) {
+ return ary;
+ }
+ else {
+ return orig;
+ }
}
if (!RSTRING_LEN(str)) goto end;
@@ -8471,147 +8988,114 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary)
rslen = RSTRING_LEN(rs);
if (rs == rb_default_rs)
- enc = rb_enc_get(str);
+ enc = rb_enc_get(str);
else
- enc = rb_enc_check(str, rs);
+ enc = rb_enc_check(str, rs);
if (rslen == 0) {
- /* paragraph mode */
- int n;
- const char *eol = NULL;
- subend = subptr;
- while (subend < pend) {
- do {
- if (rb_enc_ascget(subend, pend, &n, enc) != '\r')
- n = 0;
- rslen = n + rb_enc_mbclen(subend + n, pend, enc);
- if (rb_enc_is_newline(subend + n, pend, enc)) {
- if (eol == subend) break;
- subend += rslen;
- if (subptr) eol = subend;
- }
- else {
- if (!subptr) subptr = subend;
- subend += rslen;
- }
- rslen = 0;
- } while (subend < pend);
- if (!subptr) break;
- line = rb_str_subseq(str, subptr - ptr,
- subend - subptr + (chomp ? 0 : rslen));
- if (ENUM_ELEM(ary, line)) {
- str_mod_check(str, ptr, len);
- }
- subptr = eol = NULL;
- }
- goto end;
+ /* paragraph mode */
+ int n;
+ const char *eol = NULL;
+ subend = subptr;
+ while (subend < pend) {
+ long chomp_rslen = 0;
+ do {
+ if (rb_enc_ascget(subend, pend, &n, enc) != '\r')
+ n = 0;
+ rslen = n + rb_enc_mbclen(subend + n, pend, enc);
+ if (rb_enc_is_newline(subend + n, pend, enc)) {
+ if (eol == subend) break;
+ subend += rslen;
+ if (subptr) {
+ eol = subend;
+ chomp_rslen = -rslen;
+ }
+ }
+ else {
+ if (!subptr) subptr = subend;
+ subend += rslen;
+ }
+ rslen = 0;
+ } while (subend < pend);
+ if (!subptr) break;
+ if (rslen == 0) chomp_rslen = 0;
+ line = rb_str_subseq(str, subptr - ptr,
+ subend - subptr + (chomp ? chomp_rslen : rslen));
+ if (ENUM_ELEM(ary, line)) {
+ str_mod_check(str, ptr, len);
+ }
+ subptr = eol = NULL;
+ }
+ goto end;
}
else {
- rsptr = RSTRING_PTR(rs);
- if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
- rb_enc_is_newline(rsptr, rsptr + RSTRING_LEN(rs), enc)) {
- rsnewline = 1;
- }
+ rsptr = RSTRING_PTR(rs);
+ if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
+ rb_enc_is_newline(rsptr, rsptr + RSTRING_LEN(rs), enc)) {
+ rsnewline = 1;
+ }
}
if ((rs == rb_default_rs) && !rb_enc_asciicompat(enc)) {
- rs = rb_str_new(rsptr, rslen);
- rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
- rsptr = RSTRING_PTR(rs);
- rslen = RSTRING_LEN(rs);
+ rs = rb_str_new(rsptr, rslen);
+ rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
+ rsptr = RSTRING_PTR(rs);
+ rslen = RSTRING_LEN(rs);
}
while (subptr < pend) {
- pos = rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
- if (pos < 0) break;
- hit = subptr + pos;
- adjusted = rb_enc_right_char_head(subptr, hit, pend, enc);
- if (hit != adjusted) {
- subptr = adjusted;
- continue;
- }
- subend = hit += rslen;
- if (chomp) {
- if (rsnewline) {
- subend = chomp_newline(subptr, subend, enc);
- }
- else {
- subend -= rslen;
- }
- }
- line = rb_str_subseq(str, subptr - ptr, subend - subptr);
- if (ENUM_ELEM(ary, line)) {
- str_mod_check(str, ptr, len);
- }
- subptr = hit;
+ pos = rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
+ if (pos < 0) break;
+ hit = subptr + pos;
+ adjusted = rb_enc_right_char_head(subptr, hit, pend, enc);
+ if (hit != adjusted) {
+ subptr = adjusted;
+ continue;
+ }
+ subend = hit += rslen;
+ if (chomp) {
+ if (rsnewline) {
+ subend = chomp_newline(subptr, subend, enc);
+ }
+ else {
+ subend -= rslen;
+ }
+ }
+ line = rb_str_subseq(str, subptr - ptr, subend - subptr);
+ if (ENUM_ELEM(ary, line)) {
+ str_mod_check(str, ptr, len);
+ }
+ subptr = hit;
}
if (subptr != pend) {
- if (chomp) {
- if (rsnewline) {
- pend = chomp_newline(subptr, pend, enc);
- }
- else if (pend - subptr >= rslen &&
- memcmp(pend - rslen, rsptr, rslen) == 0) {
- pend -= rslen;
- }
- }
- line = rb_str_subseq(str, subptr - ptr, pend - subptr);
- ENUM_ELEM(ary, line);
- RB_GC_GUARD(str);
+ if (chomp) {
+ if (rsnewline) {
+ pend = chomp_newline(subptr, pend, enc);
+ }
+ else if (pend - subptr >= rslen &&
+ memcmp(pend - rslen, rsptr, rslen) == 0) {
+ pend -= rslen;
+ }
+ }
+ line = rb_str_subseq(str, subptr - ptr, pend - subptr);
+ ENUM_ELEM(ary, line);
+ RB_GC_GUARD(str);
}
end:
if (ary)
- return ary;
+ return ary;
else
- return orig;
+ return orig;
}
/*
* call-seq:
- * str.each_line(separator=$/, chomp: false) {|substr| block } -> str
- * str.each_line(separator=$/, chomp: false) -> an_enumerator
- *
- * Splits <i>str</i> using the supplied parameter as the record
- * separator (<code>$/</code> by default), passing each substring in
- * turn to the supplied block. If a zero-length record separator is
- * supplied, the string is split into paragraphs delimited by
- * multiple successive newlines.
- *
- * If +chomp+ is +true+, +separator+ will be removed from the end of each
- * line.
- *
- * If no block is given, an enumerator is returned instead.
+ * each_line(line_sep = $/, chomp: false) {|substring| ... } -> self
+ * each_line(line_sep = $/, chomp: false) -> enumerator
*
- * "hello\nworld".each_line {|s| p s}
- * # prints:
- * # "hello\n"
- * # "world"
- *
- * "hello\nworld".each_line('l') {|s| p s}
- * # prints:
- * # "hel"
- * # "l"
- * # "o\nworl"
- * # "d"
- *
- * "hello\n\n\nworld".each_line('') {|s| p s}
- * # prints
- * # "hello\n\n"
- * # "world"
- *
- * "hello\nworld".each_line(chomp: true) {|s| p s}
- * # prints:
- * # "hello"
- * # "world"
- *
- * "hello\nworld".each_line('l', chomp: true) {|s| p s}
- * # prints:
- * # "he"
- * # ""
- * # "o\nwor"
- * # "d"
+ * :include: doc/string/each_line.rdoc
*
*/
@@ -8624,21 +9108,11 @@ rb_str_each_line(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.lines(separator=$/, chomp: false) -> an_array
- *
- * Returns an array of lines in <i>str</i> split using the supplied
- * record separator (<code>$/</code> by default). This is a
- * shorthand for <code>str.each_line(separator, getline_args).to_a</code>.
- *
- * If +chomp+ is +true+, +separator+ will be removed from the end of each
- * line.
+ * lines(Line_sep = $/, chomp: false) -> array_of_strings
*
- * "hello\nworld\n".lines #=> ["hello\n", "world\n"]
- * "hello world".lines(' ') #=> ["hello ", " ", "world"]
- * "hello\nworld\n".lines(chomp: true) #=> ["hello", "world"]
+ * Forms substrings ("lines") of +self+ according to the given arguments
+ * (see String#each_line for details); returns the lines in an array.
*
- * If a block is given, which is a deprecated form, works the same as
- * <code>each_line</code>.
*/
static VALUE
@@ -8660,27 +9134,21 @@ rb_str_enumerate_bytes(VALUE str, VALUE ary)
long i;
for (i=0; i<RSTRING_LEN(str); i++) {
- ENUM_ELEM(ary, INT2FIX((unsigned char)RSTRING_PTR(str)[i]));
+ ENUM_ELEM(ary, INT2FIX((unsigned char)RSTRING_PTR(str)[i]));
}
if (ary)
- return ary;
+ return ary;
else
- return str;
+ return str;
}
/*
* call-seq:
- * str.each_byte {|integer| block } -> str
- * str.each_byte -> an_enumerator
- *
- * Passes each byte in <i>str</i> to the given block, or returns an
- * enumerator if no block is given.
- *
- * "hello".each_byte {|c| print c, ' ' }
+ * each_byte {|byte| ... } -> self
+ * each_byte -> enumerator
*
- * <em>produces:</em>
+ * :include: doc/string/each_byte.rdoc
*
- * 104 101 108 108 111
*/
static VALUE
@@ -8692,13 +9160,10 @@ rb_str_each_byte(VALUE str)
/*
* call-seq:
- * str.bytes -> an_array
+ * bytes -> array_of_bytes
*
- * Returns an array of bytes in <i>str</i>. This is a shorthand for
- * <code>str.each_byte.to_a</code>.
+ * :include: doc/string/bytes.rdoc
*
- * If a block is given, which is a deprecated form, works the same as
- * <code>each_byte</code>.
*/
static VALUE
@@ -8728,37 +9193,31 @@ rb_str_enumerate_chars(VALUE str, VALUE ary)
enc = rb_enc_get(str);
if (ENC_CODERANGE_CLEAN_P(ENC_CODERANGE(str))) {
- for (i = 0; i < len; i += n) {
- n = rb_enc_fast_mbclen(ptr + i, ptr + len, enc);
- ENUM_ELEM(ary, rb_str_subseq(str, i, n));
- }
+ for (i = 0; i < len; i += n) {
+ n = rb_enc_fast_mbclen(ptr + i, ptr + len, enc);
+ ENUM_ELEM(ary, rb_str_subseq(str, i, n));
+ }
}
else {
- for (i = 0; i < len; i += n) {
- n = rb_enc_mbclen(ptr + i, ptr + len, enc);
- ENUM_ELEM(ary, rb_str_subseq(str, i, n));
- }
+ for (i = 0; i < len; i += n) {
+ n = rb_enc_mbclen(ptr + i, ptr + len, enc);
+ ENUM_ELEM(ary, rb_str_subseq(str, i, n));
+ }
}
RB_GC_GUARD(str);
if (ary)
- return ary;
+ return ary;
else
- return orig;
+ return orig;
}
/*
* call-seq:
- * str.each_char {|cstr| block } -> str
- * str.each_char -> an_enumerator
- *
- * Passes each character in <i>str</i> to the given block, or returns
- * an enumerator if no block is given.
+ * each_char {|c| ... } -> self
+ * each_char -> enumerator
*
- * "hello".each_char {|c| print c, ' ' }
+ * :include: doc/string/each_char.rdoc
*
- * <em>produces:</em>
- *
- * h e l l o
*/
static VALUE
@@ -8770,13 +9229,10 @@ rb_str_each_char(VALUE str)
/*
* call-seq:
- * str.chars -> an_array
+ * chars -> array_of_characters
*
- * Returns an array of characters in <i>str</i>. This is a shorthand
- * for <code>str.each_char.to_a</code>.
+ * :include: doc/string/chars.rdoc
*
- * If a block is given, which is a deprecated form, works the same as
- * <code>each_char</code>.
*/
static VALUE
@@ -8796,7 +9252,7 @@ rb_str_enumerate_codepoints(VALUE str, VALUE ary)
rb_encoding *enc;
if (single_byte_optimizable(str))
- return rb_str_enumerate_bytes(str, ary);
+ return rb_str_enumerate_bytes(str, ary);
str = rb_str_new_frozen(str);
ptr = RSTRING_PTR(str);
@@ -8804,35 +9260,24 @@ rb_str_enumerate_codepoints(VALUE str, VALUE ary)
enc = STR_ENC_GET(str);
while (ptr < end) {
- c = rb_enc_codepoint_len(ptr, end, &n, enc);
- ENUM_ELEM(ary, UINT2NUM(c));
- ptr += n;
+ c = rb_enc_codepoint_len(ptr, end, &n, enc);
+ ENUM_ELEM(ary, UINT2NUM(c));
+ ptr += n;
}
RB_GC_GUARD(str);
if (ary)
- return ary;
+ return ary;
else
- return orig;
+ return orig;
}
/*
* call-seq:
- * str.each_codepoint {|integer| block } -> str
- * str.each_codepoint -> an_enumerator
- *
- * Passes the Integer ordinal of each character in <i>str</i>,
- * also known as a <i>codepoint</i> when applied to Unicode strings to the
- * given block. For encodings other than UTF-8/UTF-16(BE|LE)/UTF-32(BE|LE),
- * values are directly derived from the binary representation
- * of each character.
- *
- * If no block is given, an enumerator is returned instead.
+ * each_codepoint {|integer| ... } -> self
+ * each_codepoint -> enumerator
*
- * "hello\u0639".each_codepoint {|c| print c, ' ' }
+ * :include: doc/string/each_codepoint.rdoc
*
- * <em>produces:</em>
- *
- * 104 101 108 108 111 1593
*/
static VALUE
@@ -8844,14 +9289,10 @@ rb_str_each_codepoint(VALUE str)
/*
* call-seq:
- * str.codepoints -> an_array
+ * codepoints -> array_of_integers
*
- * Returns an array of the Integer ordinals of the
- * characters in <i>str</i>. This is a shorthand for
- * <code>str.each_codepoint.to_a</code>.
+ * :include: doc/string/codepoints.rdoc
*
- * If a block is given, which is a deprecated form, works the same as
- * <code>each_codepoint</code>.
*/
static VALUE
@@ -8865,74 +9306,93 @@ static regex_t *
get_reg_grapheme_cluster(rb_encoding *enc)
{
int encidx = rb_enc_to_index(enc);
- regex_t *reg_grapheme_cluster = NULL;
- static regex_t *reg_grapheme_cluster_utf8 = NULL;
- /* synchronize */
- if (encidx == rb_utf8_encindex() && reg_grapheme_cluster_utf8) {
- reg_grapheme_cluster = reg_grapheme_cluster_utf8;
- }
- if (!reg_grapheme_cluster) {
- const OnigUChar source_ascii[] = "\\X";
- OnigErrorInfo einfo;
- const OnigUChar *source = source_ascii;
- size_t source_len = sizeof(source_ascii) - 1;
- switch (encidx) {
+ const OnigUChar source_ascii[] = "\\X";
+ const OnigUChar *source = source_ascii;
+ size_t source_len = sizeof(source_ascii) - 1;
+
+ switch (encidx) {
#define CHARS_16BE(x) (OnigUChar)((x)>>8), (OnigUChar)(x)
#define CHARS_16LE(x) (OnigUChar)(x), (OnigUChar)((x)>>8)
#define CHARS_32BE(x) CHARS_16BE((x)>>16), CHARS_16BE(x)
#define CHARS_32LE(x) CHARS_16LE(x), CHARS_16LE((x)>>16)
#define CASE_UTF(e) \
- case ENCINDEX_UTF_##e: { \
- static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
- source = source_UTF_##e; \
- source_len = sizeof(source_UTF_##e); \
- break; \
- }
- CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
+ case ENCINDEX_UTF_##e: { \
+ static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
+ source = source_UTF_##e; \
+ source_len = sizeof(source_UTF_##e); \
+ break; \
+ }
+ CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
#undef CASE_UTF
#undef CHARS_16BE
#undef CHARS_16LE
#undef CHARS_32BE
#undef CHARS_32LE
- }
- int r = onig_new(&reg_grapheme_cluster, source, source + source_len,
- ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
- if (r) {
- UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
- onig_error_code_to_str(message, r, &einfo);
- rb_fatal("cannot compile grapheme cluster regexp: %s", (char *)message);
- }
- if (encidx == rb_utf8_encindex()) {
- reg_grapheme_cluster_utf8 = reg_grapheme_cluster;
- }
}
+
+ regex_t *reg_grapheme_cluster;
+ OnigErrorInfo einfo;
+ int r = onig_new(&reg_grapheme_cluster, source, source + source_len,
+ ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
+ if (r) {
+ UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
+ onig_error_code_to_str(message, r, &einfo);
+ rb_fatal("cannot compile grapheme cluster regexp: %s", (char *)message);
+ }
+
return reg_grapheme_cluster;
}
+static regex_t *
+get_cached_reg_grapheme_cluster(rb_encoding *enc)
+{
+ int encidx = rb_enc_to_index(enc);
+ static regex_t *reg_grapheme_cluster_utf8 = NULL;
+
+ if (encidx == rb_utf8_encindex()) {
+ if (!reg_grapheme_cluster_utf8) {
+ reg_grapheme_cluster_utf8 = get_reg_grapheme_cluster(enc);
+ }
+
+ return reg_grapheme_cluster_utf8;
+ }
+
+ return NULL;
+}
+
static VALUE
rb_str_each_grapheme_cluster_size(VALUE str, VALUE args, VALUE eobj)
{
size_t grapheme_cluster_count = 0;
- regex_t *reg_grapheme_cluster = NULL;
- rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
+ rb_encoding *enc = get_encoding(str);
const char *ptr, *end;
if (!rb_enc_unicode_p(enc)) {
- return rb_str_length(str);
+ return rb_str_length(str);
+ }
+
+ bool cached_reg_grapheme_cluster = true;
+ regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
+ if (!reg_grapheme_cluster) {
+ reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
+ cached_reg_grapheme_cluster = false;
}
- reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
ptr = RSTRING_PTR(str);
end = RSTRING_END(str);
while (ptr < end) {
- OnigPosition len = onig_match(reg_grapheme_cluster,
- (const OnigUChar *)ptr, (const OnigUChar *)end,
- (const OnigUChar *)ptr, NULL, 0);
- if (len <= 0) break;
- grapheme_cluster_count++;
- ptr += len;
+ OnigPosition len = onig_match(reg_grapheme_cluster,
+ (const OnigUChar *)ptr, (const OnigUChar *)end,
+ (const OnigUChar *)ptr, NULL, 0);
+ if (len <= 0) break;
+ grapheme_cluster_count++;
+ ptr += len;
+ }
+
+ if (!cached_reg_grapheme_cluster) {
+ onig_free(reg_grapheme_cluster);
}
return SIZET2NUM(grapheme_cluster_count);
@@ -8942,46 +9402,51 @@ static VALUE
rb_str_enumerate_grapheme_clusters(VALUE str, VALUE ary)
{
VALUE orig = str;
- regex_t *reg_grapheme_cluster = NULL;
- rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
+ rb_encoding *enc = get_encoding(str);
const char *ptr0, *ptr, *end;
if (!rb_enc_unicode_p(enc)) {
- return rb_str_enumerate_chars(str, ary);
+ return rb_str_enumerate_chars(str, ary);
}
if (!ary) str = rb_str_new_frozen(str);
- reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
+
+ bool cached_reg_grapheme_cluster = true;
+ regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
+ if (!reg_grapheme_cluster) {
+ reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
+ cached_reg_grapheme_cluster = false;
+ }
+
ptr0 = ptr = RSTRING_PTR(str);
end = RSTRING_END(str);
while (ptr < end) {
- OnigPosition len = onig_match(reg_grapheme_cluster,
- (const OnigUChar *)ptr, (const OnigUChar *)end,
- (const OnigUChar *)ptr, NULL, 0);
- if (len <= 0) break;
+ OnigPosition len = onig_match(reg_grapheme_cluster,
+ (const OnigUChar *)ptr, (const OnigUChar *)end,
+ (const OnigUChar *)ptr, NULL, 0);
+ if (len <= 0) break;
ENUM_ELEM(ary, rb_str_subseq(str, ptr-ptr0, len));
- ptr += len;
+ ptr += len;
}
+
+ if (!cached_reg_grapheme_cluster) {
+ onig_free(reg_grapheme_cluster);
+ }
+
RB_GC_GUARD(str);
if (ary)
- return ary;
+ return ary;
else
- return orig;
+ return orig;
}
/*
* call-seq:
- * str.each_grapheme_cluster {|cstr| block } -> str
- * str.each_grapheme_cluster -> an_enumerator
- *
- * Passes each grapheme cluster in <i>str</i> to the given block, or returns
- * an enumerator if no block is given.
- * Unlike String#each_char, this enumerates by grapheme clusters defined by
- * Unicode Standard Annex #29 http://unicode.org/reports/tr29/
+ * each_grapheme_cluster {|gc| ... } -> self
+ * each_grapheme_cluster -> enumerator
*
- * "a\u0300".each_char.to_a.size #=> 2
- * "a\u0300".each_grapheme_cluster.to_a.size #=> 1
+ * :include: doc/string/each_grapheme_cluster.rdoc
*
*/
@@ -8994,13 +9459,10 @@ rb_str_each_grapheme_cluster(VALUE str)
/*
* call-seq:
- * str.grapheme_clusters -> an_array
+ * grapheme_clusters -> array_of_grapheme_clusters
*
- * Returns an array of grapheme clusters in <i>str</i>. This is a shorthand
- * for <code>str.each_grapheme_cluster.to_a</code>.
+ * :include: doc/string/grapheme_clusters.rdoc
*
- * If a block is given, which is a deprecated form, works the same as
- * <code>each_grapheme_cluster</code>.
*/
static VALUE
@@ -9022,19 +9484,20 @@ chopped_length(VALUE str)
p = rb_enc_prev_char(beg, end, end, enc);
if (!p) return 0;
if (p > beg && rb_enc_ascget(p, end, 0, enc) == '\n') {
- p2 = rb_enc_prev_char(beg, p, end, enc);
- if (p2 && rb_enc_ascget(p2, end, 0, enc) == '\r') p = p2;
+ p2 = rb_enc_prev_char(beg, p, end, enc);
+ if (p2 && rb_enc_ascget(p2, end, 0, enc) == '\r') p = p2;
}
return p - beg;
}
/*
* call-seq:
- * str.chop! -> str or nil
+ * chop! -> self or nil
*
- * Processes <i>str</i> as for String#chop, returning <i>str</i>, or
- * <code>nil</code> if <i>str</i> is the empty string. See also
- * String#chomp!.
+ * Like String#chop, but modifies +self+ in place;
+ * returns +nil+ if +self+ is empty, +self+ otherwise.
+ *
+ * Related: String#chomp!.
*/
static VALUE
@@ -9042,14 +9505,14 @@ rb_str_chop_bang(VALUE str)
{
str_modify_keep_cr(str);
if (RSTRING_LEN(str) > 0) {
- long len;
- len = chopped_length(str);
- STR_SET_LEN(str, len);
- TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
- if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
- ENC_CODERANGE_CLEAR(str);
- }
- return str;
+ long len;
+ len = chopped_length(str);
+ STR_SET_LEN(str, len);
+ TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
+ if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
+ ENC_CODERANGE_CLEAR(str);
+ }
+ return str;
}
return Qnil;
}
@@ -9057,20 +9520,10 @@ rb_str_chop_bang(VALUE str)
/*
* call-seq:
- * str.chop -> new_str
+ * chop -> new_string
*
- * Returns a new String with the last character removed. If the
- * string ends with <code>\r\n</code>, both characters are
- * removed. Applying <code>chop</code> to an empty string returns an
- * empty string. String#chomp is often a safer alternative, as it
- * leaves the string unchanged if it doesn't end in a record
- * separator.
+ * :include: doc/string/chop.rdoc
*
- * "string\r\n".chop #=> "string"
- * "string\n\r".chop #=> "string\n"
- * "string\n".chop #=> "string"
- * "string".chop #=> "strin"
- * "x".chop.chop #=> ""
*/
static VALUE
@@ -9130,55 +9583,55 @@ chompped_length(VALUE str, VALUE rs)
enc = rb_enc_get(str);
RSTRING_GETMEM(rs, rsptr, rslen);
if (rslen == 0) {
- if (rb_enc_mbminlen(enc) > 1) {
- while (e > p) {
- pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
- if (!rb_enc_is_newline(pp, e, enc)) break;
- e = pp;
- pp -= 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 {
- while (e > p && *(e-1) == '\n') {
- --e;
- if (e > p && *(e-1) == '\r')
- --e;
- }
- }
- return e - p;
+ if (rb_enc_mbminlen(enc) > 1) {
+ while (e > p) {
+ pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
+ if (!rb_enc_is_newline(pp, e, enc)) break;
+ e = pp;
+ pp -= 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 {
+ while (e > p && *(e-1) == '\n') {
+ --e;
+ if (e > p && *(e-1) == '\r')
+ --e;
+ }
+ }
+ return e - p;
}
if (rslen > len) return len;
enc = rb_enc_get(rs);
newline = rsptr[rslen-1];
if (rslen == rb_enc_mbminlen(enc)) {
- if (rslen == 1) {
- if (newline == '\n')
+ if (rslen == 1) {
+ if (newline == '\n')
return smart_chomp(str, e, p);
- }
- else {
- if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
+ }
+ else {
+ if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
return smart_chomp(str, e, p);
- }
+ }
}
enc = rb_enc_check(str, rs);
if (is_broken_string(rs)) {
- return len;
+ return len;
}
pp = e - rslen;
if (p[len-1] == newline &&
- (rslen <= 1 ||
- memcmp(rsptr, pp, rslen) == 0)) {
- if (rb_enc_left_char_head(p, pp, e, enc) == pp)
- return len - rslen;
- RB_GC_GUARD(rs);
+ (rslen <= 1 ||
+ memcmp(rsptr, pp, rslen) == 0)) {
+ if (rb_enc_left_char_head(p, pp, e, enc) == pp)
+ return len - rslen;
+ RB_GC_GUARD(rs);
}
return len;
}
@@ -9186,19 +9639,19 @@ chompped_length(VALUE str, VALUE rs)
/*!
* Returns the separator for arguments of rb_str_chomp.
*
- * @return returns rb_ps ($/) as default, the default value of rb_ps ($/) is "\n".
+ * @return returns rb_rs ($/) as default, the default value of rb_rs ($/) is "\n".
*/
static VALUE
chomp_rs(int argc, const VALUE *argv)
{
rb_check_arity(argc, 0, 1);
if (argc > 0) {
- VALUE rs = argv[0];
- if (!NIL_P(rs)) StringValue(rs);
- return rs;
+ VALUE rs = argv[0];
+ if (!NIL_P(rs)) StringValue(rs);
+ return rs;
}
else {
- return rb_rs;
+ return rb_rs;
}
}
@@ -9212,18 +9665,18 @@ rb_str_chomp_string(VALUE str, VALUE rs)
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
- ENC_CODERANGE_CLEAR(str);
+ ENC_CODERANGE_CLEAR(str);
}
return str;
}
/*
* call-seq:
- * str.chomp!(separator=$/) -> str or nil
+ * chomp!(line_sep = $/) -> self or nil
+ *
+ * Like String#chomp, but modifies +self+ in place;
+ * returns +nil+ if no modification made, +self+ otherwise.
*
- * Modifies <i>str</i> in place as described for String#chomp,
- * returning <i>str</i>, or <code>nil</code> if no modifications were
- * made.
*/
static VALUE
@@ -9240,24 +9693,10 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.chomp(separator=$/) -> new_str
+ * chomp(line_sep = $/) -> new_string
*
- * Returns a new String with the given record separator removed
- * from the end of <i>str</i> (if present). If <code>$/</code> has not been
- * changed from the default Ruby record separator, then <code>chomp</code> also
- * removes carriage return characters (that is, it will remove <code>\n</code>,
- * <code>\r</code>, and <code>\r\n</code>). If <code>$/</code> is an empty string,
- * it will remove all trailing newlines from the string.
+ * :include: doc/string/chomp.rdoc
*
- * "hello".chomp #=> "hello"
- * "hello\n".chomp #=> "hello"
- * "hello\r\n".chomp #=> "hello"
- * "hello\n\r".chomp #=> "hello\n"
- * "hello\r".chomp #=> "hello"
- * "hello \n there".chomp #=> "hello \n there"
- * "hello".chomp("llo") #=> "he"
- * "hello\r\n\r\n".chomp('') #=> "hello"
- * "hello\r\n\r\r\n".chomp('') #=> "hello\r\n\r"
*/
static VALUE
@@ -9280,30 +9719,25 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
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);
+ while (s < e) {
+ int n;
+ unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
if (cc && !rb_isspace(cc)) break;
- s += n;
- }
+ s += n;
+ }
}
return s - start;
}
/*
* call-seq:
- * str.lstrip! -> self or nil
- *
- * Removes leading whitespace from the receiver.
- * Returns the altered receiver, or +nil+ if no change was made.
- * See also String#rstrip! and String#strip!.
+ * lstrip! -> self or nil
*
- * Refer to String#strip for the definition of whitespace.
+ * Like String#lstrip, except that any modifications are made in +self+;
+ * returns +self+ if any modification are made, +nil+ otherwise.
*
- * " hello ".lstrip! #=> "hello "
- * "hello ".lstrip! #=> nil
- * "hello".lstrip! #=> nil
+ * Related: String#rstrip!, String#strip!.
*/
static VALUE
@@ -9318,12 +9752,12 @@ rb_str_lstrip_bang(VALUE str)
RSTRING_GETMEM(str, start, olen);
loffset = lstrip_offset(str, start, start+olen, enc);
if (loffset > 0) {
- long len = olen-loffset;
- s = start + loffset;
- memmove(start, s, len);
- STR_SET_LEN(str, len);
- TERM_FILL(start+len, rb_enc_mbminlen(enc));
- return str;
+ long len = olen-loffset;
+ s = start + loffset;
+ memmove(start, s, len);
+ STR_SET_LEN(str, len);
+ TERM_FILL(start+len, rb_enc_mbminlen(enc));
+ return str;
}
return Qnil;
}
@@ -9331,15 +9765,17 @@ rb_str_lstrip_bang(VALUE str)
/*
* call-seq:
- * str.lstrip -> new_str
+ * lstrip -> new_string
*
- * Returns a copy of the receiver with leading whitespace removed.
- * See also String#rstrip and String#strip.
+ * Returns a copy of +self+ with leading whitespace removed;
+ * see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
*
- * Refer to String#strip for the definition of whitespace.
+ * whitespace = "\x00\t\n\v\f\r "
+ * s = whitespace + 'abc' + whitespace
+ * s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
+ * s.lstrip # => "abc\u0000\t\n\v\f\r "
*
- * " hello ".lstrip #=> "hello "
- * "hello".lstrip #=> "hello"
+ * Related: String#rstrip, String#strip.
*/
static VALUE
@@ -9359,39 +9795,37 @@ rstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
const char *t;
rb_str_check_dummy_enc(enc);
+ if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
+ rb_raise(rb_eEncCompatError, "invalid byte sequence in %s", rb_enc_name(enc));
+ }
if (!s || s >= e) return 0;
t = e;
/* remove trailing spaces or '\0's */
if (single_byte_optimizable(str)) {
- unsigned char c;
- while (s < t && ((c = *(t-1)) == '\0' || ascii_isspace(c))) t--;
+ unsigned char c;
+ while (s < t && ((c = *(t-1)) == '\0' || ascii_isspace(c))) t--;
}
else {
- char *tp;
+ char *tp;
while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
- unsigned int c = rb_enc_codepoint(tp, e, enc);
- if (c && !rb_isspace(c)) break;
- t = tp;
- }
+ unsigned int c = rb_enc_codepoint(tp, e, enc);
+ if (c && !rb_isspace(c)) break;
+ t = tp;
+ }
}
return e - t;
}
/*
* call-seq:
- * str.rstrip! -> self or nil
+ * rstrip! -> self or nil
*
- * Removes trailing whitespace from the receiver.
- * Returns the altered receiver, or +nil+ if no change was made.
- * See also String#lstrip! and String#strip!.
+ * Like String#rstrip, except that any modifications are made in +self+;
+ * returns +self+ if any modification are made, +nil+ otherwise.
*
- * Refer to String#strip for the definition of whitespace.
- *
- * " hello ".rstrip! #=> " hello"
- * " hello".rstrip! #=> nil
- * "hello".rstrip! #=> nil
+ * Related: String#lstrip!, String#strip!.
*/
static VALUE
@@ -9406,11 +9840,11 @@ rb_str_rstrip_bang(VALUE str)
RSTRING_GETMEM(str, start, olen);
roffset = rstrip_offset(str, start, start+olen, enc);
if (roffset > 0) {
- long len = olen - roffset;
+ long len = olen - roffset;
- STR_SET_LEN(str, len);
- TERM_FILL(start+len, rb_enc_mbminlen(enc));
- return str;
+ STR_SET_LEN(str, len);
+ TERM_FILL(start+len, rb_enc_mbminlen(enc));
+ return str;
}
return Qnil;
}
@@ -9418,15 +9852,17 @@ rb_str_rstrip_bang(VALUE str)
/*
* call-seq:
- * str.rstrip -> new_str
+ * rstrip -> new_string
*
- * Returns a copy of the receiver with trailing whitespace removed.
- * See also String#lstrip and String#strip.
+ * Returns a copy of the receiver with trailing whitespace removed;
+ * see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
*
- * Refer to String#strip for the definition of whitespace.
+ * whitespace = "\x00\t\n\v\f\r "
+ * s = whitespace + 'abc' + whitespace
+ * s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
+ * s.rstrip # => "\u0000\t\n\v\f\r abc"
*
- * " hello ".rstrip #=> " hello"
- * "hello".rstrip #=> "hello"
+ * Related: String#lstrip, String#strip.
*/
static VALUE
@@ -9447,15 +9883,12 @@ rb_str_rstrip(VALUE str)
/*
* call-seq:
- * str.strip! -> self or nil
- *
- * Removes leading and trailing whitespace from the receiver.
- * Returns the altered receiver, or +nil+ if there was no change.
+ * strip! -> self or nil
*
- * Refer to String#strip for the definition of whitespace.
+ * Like String#strip, except that any modifications are made in +self+;
+ * returns +self+ if any modification are made, +nil+ otherwise.
*
- * " hello ".strip! #=> "hello"
- * "hello".strip! #=> nil
+ * Related: String#lstrip!, String#strip!.
*/
static VALUE
@@ -9472,14 +9905,14 @@ rb_str_strip_bang(VALUE str)
roffset = rstrip_offset(str, start+loffset, start+olen, enc);
if (loffset > 0 || roffset > 0) {
- long len = olen-roffset;
- if (loffset > 0) {
- len -= loffset;
- memmove(start, start + loffset, len);
- }
- STR_SET_LEN(str, len);
- TERM_FILL(start+len, rb_enc_mbminlen(enc));
- return str;
+ long len = olen-roffset;
+ if (loffset > 0) {
+ len -= loffset;
+ memmove(start, start + loffset, len);
+ }
+ STR_SET_LEN(str, len);
+ TERM_FILL(start+len, rb_enc_mbminlen(enc));
+ return str;
}
return Qnil;
}
@@ -9487,17 +9920,17 @@ rb_str_strip_bang(VALUE str)
/*
* call-seq:
- * str.strip -> new_str
+ * strip -> new_string
*
- * Returns a copy of the receiver with leading and trailing whitespace removed.
+ * Returns a copy of the receiver with leading and trailing whitespace removed;
+ * see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
*
- * Whitespace is defined as any of the following characters:
- * null, horizontal tab, line feed, vertical tab, form feed, carriage return, space.
+ * whitespace = "\x00\t\n\v\f\r "
+ * s = whitespace + 'abc' + whitespace
+ * s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
+ * s.strip # => "abc"
*
- * " hello ".strip #=> "hello"
- * "\tgoodbye\r\n".strip #=> "goodbye"
- * "\x00\t\n\v\f\r ".strip #=> ""
- * "hello".strip #=> "hello"
+ * Related: String#lstrip, String#rstrip.
*/
static VALUE
@@ -9523,44 +9956,44 @@ scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
int i;
long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
if (pos >= 0) {
- if (BUILTIN_TYPE(pat) == T_STRING) {
- regs = NULL;
- end = pos + RSTRING_LEN(pat);
- }
- else {
- match = rb_backref_get();
- regs = RMATCH_REGS(match);
- pos = BEG(0);
- end = END(0);
- }
- if (pos == end) {
- rb_encoding *enc = STR_ENC_GET(str);
- /*
- * Always consume at least one character of the input string
- */
- if (RSTRING_LEN(str) > end)
- *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
- RSTRING_END(str), enc);
- else
- *start = end + 1;
- }
- else {
- *start = end;
- }
- if (!regs || regs->num_regs == 1) {
- result = rb_str_subseq(str, pos, end - pos);
- return result;
- }
- result = rb_ary_new2(regs->num_regs);
- for (i=1; i < regs->num_regs; i++) {
- VALUE s = Qnil;
- if (BEG(i) >= 0) {
- s = rb_str_subseq(str, BEG(i), END(i)-BEG(i));
- }
- rb_ary_push(result, s);
- }
-
- return result;
+ if (BUILTIN_TYPE(pat) == T_STRING) {
+ regs = NULL;
+ end = pos + RSTRING_LEN(pat);
+ }
+ else {
+ match = rb_backref_get();
+ regs = RMATCH_REGS(match);
+ pos = BEG(0);
+ end = END(0);
+ }
+ if (pos == end) {
+ rb_encoding *enc = STR_ENC_GET(str);
+ /*
+ * Always consume at least one character of the input string
+ */
+ if (RSTRING_LEN(str) > end)
+ *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
+ RSTRING_END(str), enc);
+ else
+ *start = end + 1;
+ }
+ else {
+ *start = end;
+ }
+ if (!regs || regs->num_regs == 1) {
+ result = rb_str_subseq(str, pos, end - pos);
+ return result;
+ }
+ result = rb_ary_new2(regs->num_regs);
+ for (i=1; i < regs->num_regs; i++) {
+ VALUE s = Qnil;
+ if (BEG(i) >= 0) {
+ s = rb_str_subseq(str, BEG(i), END(i)-BEG(i));
+ }
+ rb_ary_push(result, s);
+ }
+
+ return result;
}
return Qnil;
}
@@ -9568,33 +10001,41 @@ scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
/*
* call-seq:
- * str.scan(pattern) -> array
- * str.scan(pattern) {|match, ...| block } -> str
+ * scan(string_or_regexp) -> array
+ * scan(string_or_regexp) {|matches| ... } -> self
*
- * Both forms iterate through <i>str</i>, matching the pattern (which may be a
- * Regexp or a String). For each match, a result is
- * generated and either added to the result array or passed to the block. If
- * the pattern contains no groups, each individual result consists of the
- * matched string, <code>$&</code>. If the pattern contains groups, each
- * individual result is itself an array containing one entry per group.
+ * Matches a pattern against +self+; the pattern is:
*
- * a = "cruel world"
- * a.scan(/\w+/) #=> ["cruel", "world"]
- * a.scan(/.../) #=> ["cru", "el ", "wor"]
- * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
- * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
+ * - +string_or_regexp+ itself, if it is a Regexp.
+ * - <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
*
- * And the block form:
+ * Iterates through +self+, generating a collection of matching results:
*
- * a.scan(/\w+/) {|w| print "<<#{w}>> " }
- * print "\n"
- * a.scan(/(.)(.)/) {|x,y| print y, x }
- * print "\n"
+ * - If the pattern contains no groups, each result is the
+ * matched string, <code>$&</code>.
+ * - If the pattern contains groups, each result is an array
+ * containing one entry per group.
*
- * <em>produces:</em>
+ * With no block given, returns an array of the results:
+ *
+ * s = 'cruel world'
+ * s.scan(/\w+/) # => ["cruel", "world"]
+ * s.scan(/.../) # => ["cru", "el ", "wor"]
+ * s.scan(/(...)/) # => [["cru"], ["el "], ["wor"]]
+ * s.scan(/(..)(..)/) # => [["cr", "ue"], ["l ", "wo"]]
+ *
+ * With a block given, calls the block with each result; returns +self+:
+ *
+ * s.scan(/\w+/) {|w| print "<<#{w}>> " }
+ * print "\n"
+ * s.scan(/(.)(.)/) {|x,y| print y, x }
+ * print "\n"
+ *
+ * Output:
*
* <<cruel>> <<world>>
* rceu lowlr
+ *
*/
static VALUE
@@ -9608,23 +10049,23 @@ rb_str_scan(VALUE str, VALUE pat)
pat = get_pat_quoted(pat, 1);
mustnot_broken(str);
if (!rb_block_given_p()) {
- VALUE ary = rb_ary_new();
+ VALUE ary = rb_ary_new();
- while (!NIL_P(result = scan_once(str, pat, &start, 0))) {
- last = prev;
- prev = start;
- rb_ary_push(ary, result);
- }
- if (last >= 0) rb_pat_search(pat, str, last, 1);
- else rb_backref_set(Qnil);
- return ary;
+ while (!NIL_P(result = scan_once(str, pat, &start, 0))) {
+ last = prev;
+ prev = start;
+ rb_ary_push(ary, result);
+ }
+ if (last >= 0) rb_pat_search(pat, str, last, 1);
+ else rb_backref_set(Qnil);
+ return ary;
}
while (!NIL_P(result = scan_once(str, pat, &start, 1))) {
- last = prev;
- prev = start;
- rb_yield(result);
- str_mod_check(str, p, len);
+ last = prev;
+ prev = start;
+ rb_yield(result);
+ str_mod_check(str, p, len);
}
if (last >= 0) rb_pat_search(pat, str, last, 1);
return str;
@@ -9633,16 +10074,20 @@ rb_str_scan(VALUE str, VALUE pat)
/*
* call-seq:
- * str.hex -> integer
+ * hex -> integer
*
- * Treats leading characters from <i>str</i> as a string of hexadecimal digits
+ * Interprets the leading substring of +self+ as a string of hexadecimal digits
* (with an optional sign and an optional <code>0x</code>) and returns the
- * corresponding number. Zero is returned on error.
+ * corresponding number;
+ * returns zero if there is no such leading substring:
+ *
+ * '0x0a'.hex # => 10
+ * '-1234'.hex # => -4660
+ * '0'.hex # => 0
+ * 'non-numeric'.hex # => 0
+ *
+ * Related: String#oct.
*
- * "0x0a".hex #=> 10
- * "-1234".hex #=> -4660
- * "0".hex #=> 0
- * "wombat".hex #=> 0
*/
static VALUE
@@ -9654,19 +10099,22 @@ rb_str_hex(VALUE str)
/*
* call-seq:
- * str.oct -> integer
+ * oct -> integer
*
- * Treats leading characters of <i>str</i> as a string of octal digits (with an
- * optional sign) and returns the corresponding number. Returns 0 if the
- * conversion fails.
+ * Interprets the leading substring of +self+ as a string of octal digits
+ * (with an optional sign) and returns the corresponding number;
+ * returns zero if there is no such leading substring:
*
- * "123".oct #=> 83
- * "-377".oct #=> -255
- * "bad".oct #=> 0
- * "0377bad".oct #=> 255
+ * '123'.oct # => 83
+ * '-377'.oct # => -255
+ * '0377non-numeric'.oct # => 255
+ * 'non-numeric'.oct # => 0
+ *
+ * If +self+ starts with <tt>0</tt>, radix indicators are honored;
+ * see Kernel#Integer.
+ *
+ * Related: String#hex.
*
- * If +str+ starts with <code>0</code>, radix indicators are honored.
- * See Kernel#Integer.
*/
static VALUE
@@ -9680,41 +10128,18 @@ rb_str_oct(VALUE str)
# include "ruby/atomic.h"
static struct {
- rb_atomic_t initialized;
rb_nativethread_lock_t lock;
-} crypt_mutex;
-
-static void
-crypt_mutex_destroy(void)
-{
- RUBY_ASSERT_ALWAYS(crypt_mutex.initialized == 1);
- rb_nativethread_lock_destroy(&crypt_mutex.lock);
- crypt_mutex.initialized = 0;
-}
+} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
static void
crypt_mutex_initialize(void)
{
- rb_atomic_t i;
- while ((i = RUBY_ATOMIC_CAS(crypt_mutex.initialized, 0, 2)) == 2);
- switch (i) {
- case 0:
- rb_nativethread_lock_initialize(&crypt_mutex.lock);
- atexit(crypt_mutex_destroy);
- RUBY_ASSERT(crypt_mutex.initialized == 2);
- RUBY_ATOMIC_CAS(crypt_mutex.initialized, 2, 1);
- break;
- case 1:
- break;
- default:
- rb_bug("crypt_mutex.initialized: %d->%d", i, crypt_mutex.initialized);
- }
}
#endif
/*
* call-seq:
- * str.crypt(salt_str) -> new_str
+ * crypt(salt_str) -> new_string
*
* Returns the string generated by calling <code>crypt(3)</code>
* standard library function with <code>str</code> and
@@ -9796,15 +10221,15 @@ rb_str_crypt(VALUE str, VALUE salt)
s = StringValueCStr(str);
saltp = RSTRING_PTR(salt);
if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
- rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
+ rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
}
#ifdef BROKEN_CRYPT
if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
- salt_8bit_clean[0] = saltp[0] & 0x7f;
- salt_8bit_clean[1] = saltp[1] & 0x7f;
- salt_8bit_clean[2] = '\0';
- saltp = salt_8bit_clean;
+ salt_8bit_clean[0] = saltp[0] & 0x7f;
+ salt_8bit_clean[1] = saltp[1] & 0x7f;
+ salt_8bit_clean[2] = '\0';
+ saltp = salt_8bit_clean;
}
#endif
#ifdef HAVE_CRYPT_R
@@ -9819,9 +10244,9 @@ rb_str_crypt(VALUE str, VALUE salt)
res = crypt(s, saltp);
#endif
if (!res) {
- int err = errno;
- CRYPT_END();
- rb_syserr_fail(err, "crypt");
+ int err = errno;
+ CRYPT_END();
+ rb_syserr_fail(err, "crypt");
}
result = rb_str_new_cstr(res);
CRYPT_END();
@@ -9831,11 +10256,10 @@ rb_str_crypt(VALUE str, VALUE salt)
/*
* call-seq:
- * str.ord -> integer
+ * ord -> integer
*
- * Returns the Integer ordinal of a one-character string.
+ * :include: doc/string/ord.rdoc
*
- * "a".ord #=> 97
*/
static VALUE
@@ -9848,13 +10272,10 @@ rb_str_ord(VALUE s)
}
/*
* call-seq:
- * str.sum(n=16) -> integer
+ * sum(n = 16) -> integer
+ *
+ * :include: doc/string/sum.rdoc
*
- * Returns a basic <em>n</em>-bit checksum of the characters in <i>str</i>,
- * where <em>n</em> is the optional Integer parameter, defaulting
- * to 16. The result is simply the sum of the binary value of each byte in
- * <i>str</i> modulo <code>2**n - 1</code>. This is not a particularly good
- * checksum.
*/
static VALUE
@@ -9929,15 +10350,15 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
termlen = rb_enc_mbminlen(enc);
width = NUM2LONG(w);
if (argc == 2) {
- StringValue(pad);
- enc = rb_enc_check(str, pad);
- f = RSTRING_PTR(pad);
- flen = RSTRING_LEN(pad);
- fclen = str_strlen(pad, enc); /* rb_enc_check */
- singlebyte = single_byte_optimizable(pad);
- if (flen == 0 || fclen == 0) {
- rb_raise(rb_eArgError, "zero width padding");
- }
+ StringValue(pad);
+ enc = rb_enc_check(str, pad);
+ f = RSTRING_PTR(pad);
+ flen = RSTRING_LEN(pad);
+ fclen = str_strlen(pad, enc); /* rb_enc_check */
+ singlebyte = single_byte_optimizable(pad);
+ if (flen == 0 || fclen == 0) {
+ rb_raise(rb_eArgError, "zero width padding");
+ }
}
len = str_strlen(str, enc); /* rb_enc_check */
if (width < 0 || len >= width) return str_duplicate(rb_cString, str);
@@ -9964,14 +10385,14 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
}
else {
while (llen >= fclen) {
- memcpy(p,f,flen);
- p += flen;
- llen -= fclen;
- }
+ memcpy(p,f,flen);
+ p += flen;
+ llen -= fclen;
+ }
if (llen > 0) {
memcpy(p, f, llen2);
p += llen2;
- }
+ }
}
memcpy(p, RSTRING_PTR(str), size);
p += size;
@@ -9981,22 +10402,22 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
}
else {
while (rlen >= fclen) {
- memcpy(p,f,flen);
- p += flen;
- rlen -= fclen;
- }
+ memcpy(p,f,flen);
+ p += flen;
+ rlen -= fclen;
+ }
if (rlen > 0) {
memcpy(p, f, rlen2);
p += rlen2;
- }
+ }
}
TERM_FILL(p, termlen);
STR_SET_LEN(res, p-RSTRING_PTR(res));
rb_enc_associate(res, enc);
if (argc == 2)
- cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
+ cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
if (cr != ENC_CODERANGE_BROKEN)
- ENC_CODERANGE_SET(res, cr);
+ ENC_CODERANGE_SET(res, cr);
RB_GC_GUARD(pad);
return res;
@@ -10005,15 +10426,12 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
/*
* call-seq:
- * str.ljust(integer, padstr=' ') -> new_str
+ * ljust(size, pad_string = ' ') -> new_string
*
- * If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- * String of length <i>integer</i> with <i>str</i> left justified
- * and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
+ * :include: doc/string/ljust.rdoc
+ *
+ * Related: String#rjust, String#center.
*
- * "hello".ljust(4) #=> "hello"
- * "hello".ljust(20) #=> "hello "
- * "hello".ljust(20, '1234') #=> "hello123412341234123"
*/
static VALUE
@@ -10022,18 +10440,14 @@ rb_str_ljust(int argc, VALUE *argv, VALUE str)
return rb_str_justify(argc, argv, str, 'l');
}
-
/*
* call-seq:
- * str.rjust(integer, padstr=' ') -> new_str
+ * rjust(size, pad_string = ' ') -> new_string
+ *
+ * :include: doc/string/rjust.rdoc
*
- * If <i>integer</i> is greater than the length of <i>str</i>, returns a new
- * String of length <i>integer</i> with <i>str</i> right justified
- * and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
+ * Related: String#ljust, String#center.
*
- * "hello".rjust(4) #=> "hello"
- * "hello".rjust(20) #=> " hello"
- * "hello".rjust(20, '1234') #=> "123412341234123hello"
*/
static VALUE
@@ -10045,15 +10459,12 @@ rb_str_rjust(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.center(width, padstr=' ') -> new_str
+ * center(size, pad_string = ' ') -> new_string
*
- * Centers +str+ in +width+. If +width+ is greater than the length of +str+,
- * returns a new String of length +width+ with +str+ centered and padded with
- * +padstr+; otherwise, returns +str+.
+ * :include: doc/string/center.rdoc
+ *
+ * Related: String#ljust, String#rjust.
*
- * "hello".center(4) #=> "hello"
- * "hello".center(20) #=> " hello "
- * "hello".center(20, '123') #=> "1231231hello12312312"
*/
static VALUE
@@ -10064,17 +10475,10 @@ rb_str_center(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.partition(sep) -> [head, sep, tail]
- * str.partition(regexp) -> [head, match, tail]
+ * partition(string_or_regexp) -> [head, match, tail]
*
- * Searches <i>sep</i> or pattern (<i>regexp</i>) in the string
- * and returns the part before it, the match, and the part
- * after it.
- * If it is not found, returns two empty strings and <i>str</i>.
+ * :include: doc/string/partition.rdoc
*
- * "hello".partition("l") #=> ["he", "l", "lo"]
- * "hello".partition("x") #=> ["hello", "", ""]
- * "hello".partition(/.l/) #=> ["h", "el", "lo"]
*/
static VALUE
@@ -10084,23 +10488,23 @@ rb_str_partition(VALUE str, VALUE sep)
sep = get_pat_quoted(sep, 0);
if (RB_TYPE_P(sep, T_REGEXP)) {
- if (rb_reg_search(sep, str, 0, 0) < 0) {
+ if (rb_reg_search(sep, str, 0, 0) < 0) {
goto failed;
- }
- VALUE match = rb_backref_get();
- struct re_registers *regs = RMATCH_REGS(match);
+ }
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
pos = BEG(0);
- sep = rb_str_subseq(str, pos, END(0) - pos);
+ sep = rb_str_subseq(str, pos, END(0) - pos);
}
else {
- pos = rb_str_index(str, sep, 0);
- if (pos < 0) goto failed;
+ pos = rb_str_index(str, sep, 0);
+ if (pos < 0) goto failed;
}
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)));
+ 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));
@@ -10108,17 +10512,10 @@ rb_str_partition(VALUE str, VALUE sep)
/*
* call-seq:
- * str.rpartition(sep) -> [head, sep, tail]
- * str.rpartition(regexp) -> [head, match, tail]
+ * rpartition(sep) -> [head, match, tail]
*
- * Searches <i>sep</i> or pattern (<i>regexp</i>) in the string from the end
- * of the string, and returns the part before it, the match, and the part
- * after it.
- * If it is not found, returns two empty strings and <i>str</i>.
+ * :include: doc/string/rpartition.rdoc
*
- * "hello".rpartition("l") #=> ["hel", "l", "o"]
- * "hello".rpartition("x") #=> ["", "", "hello"]
- * "hello".rpartition(/.l/) #=> ["he", "ll", "o"]
*/
static VALUE
@@ -10132,14 +10529,14 @@ rb_str_rpartition(VALUE str, VALUE sep)
goto failed;
}
VALUE match = rb_backref_get();
- struct re_registers *regs = RMATCH_REGS(match);
+ struct re_registers *regs = RMATCH_REGS(match);
pos = BEG(0);
sep = rb_str_subseq(str, pos, END(0) - pos);
}
else {
- pos = rb_str_sublen(str, pos);
- pos = rb_str_rindex(str, sep, pos);
+ pos = rb_str_sublen(str, pos);
+ pos = rb_str_rindex(str, sep, pos);
if (pos < 0) {
goto failed;
}
@@ -10147,26 +10544,19 @@ rb_str_rpartition(VALUE str, VALUE sep)
}
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)));
+ 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));
}
/*
* call-seq:
- * str.start_with?([prefixes]+) -> true or false
- *
- * Returns true if +str+ starts with one of the +prefixes+ given.
- * Each of the +prefixes+ should be a String or a Regexp.
+ * start_with?(*string_or_regexp) -> true or false
*
- * "hello".start_with?("hell") #=> true
- * "hello".start_with?(/H/i) #=> true
+ * :include: doc/string/start_with_p.rdoc
*
- * # returns true if one of the prefixes matches.
- * "hello".start_with?("heaven", "hell") #=> true
- * "hello".start_with?("heaven", "paradise") #=> false
*/
static VALUE
@@ -10175,33 +10565,28 @@ rb_str_start_with(int argc, VALUE *argv, VALUE str)
int i;
for (i=0; i<argc; i++) {
- VALUE tmp = argv[i];
- if (RB_TYPE_P(tmp, T_REGEXP)) {
- if (rb_reg_start_with_p(tmp, str))
- return Qtrue;
- }
- else {
- StringValue(tmp);
- rb_enc_check(str, tmp);
- if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
- if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
- return Qtrue;
- }
+ VALUE tmp = argv[i];
+ if (RB_TYPE_P(tmp, T_REGEXP)) {
+ if (rb_reg_start_with_p(tmp, str))
+ return Qtrue;
+ }
+ else {
+ StringValue(tmp);
+ rb_enc_check(str, tmp);
+ if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
+ if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
+ return Qtrue;
+ }
}
return Qfalse;
}
/*
* call-seq:
- * str.end_with?([suffixes]+) -> true or false
+ * end_with?(*strings) -> true or false
*
- * Returns true if +str+ ends with one of the +suffixes+ given.
+ * :include: doc/string/end_with_p.rdoc
*
- * "hello".end_with?("ello") #=> true
- *
- * # returns true if one of the +suffixes+ matches.
- * "hello".end_with?("heaven", "ello") #=> true
- * "hello".end_with?("heaven", "paradise") #=> false
*/
static VALUE
@@ -10212,17 +10597,19 @@ rb_str_end_with(int argc, VALUE *argv, VALUE str)
rb_encoding *enc;
for (i=0; i<argc; i++) {
- VALUE tmp = argv[i];
- StringValue(tmp);
- enc = rb_enc_check(str, tmp);
- if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
- p = RSTRING_PTR(str);
- e = p + RSTRING_LEN(str);
- s = e - RSTRING_LEN(tmp);
- if (rb_enc_left_char_head(p, s, e, enc) != s)
- continue;
- if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
- return Qtrue;
+ VALUE tmp = argv[i];
+ long slen, tlen;
+ StringValue(tmp);
+ enc = rb_enc_check(str, tmp);
+ if ((tlen = RSTRING_LEN(tmp)) == 0) return Qtrue;
+ if ((slen = RSTRING_LEN(str)) < tlen) continue;
+ p = RSTRING_PTR(str);
+ e = p + slen;
+ s = e - tlen;
+ if (rb_enc_left_char_head(p, s, e, enc) != s)
+ continue;
+ if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
+ return Qtrue;
}
return Qfalse;
}
@@ -10260,13 +10647,11 @@ deleted_prefix_length(VALUE str, VALUE prefix)
/*
* call-seq:
- * str.delete_prefix!(prefix) -> self or nil
+ * delete_prefix!(prefix) -> self or nil
*
- * Deletes leading <code>prefix</code> from <i>str</i>, returning
- * <code>nil</code> if no change was made.
+ * Like String#delete_prefix, except that +self+ is modified in place.
+ * Returns +self+ if the prefix is removed, +nil+ otherwise.
*
- * "hello".delete_prefix!("hel") #=> "lo"
- * "hello".delete_prefix!("llo") #=> nil
*/
static VALUE
@@ -10283,12 +10668,10 @@ rb_str_delete_prefix_bang(VALUE str, VALUE prefix)
/*
* call-seq:
- * str.delete_prefix(prefix) -> new_str
+ * delete_prefix(prefix) -> new_string
*
- * Returns a copy of <i>str</i> with leading <code>prefix</code> deleted.
+ * :include: doc/string/delete_prefix.rdoc
*
- * "hello".delete_prefix("hel") #=> "lo"
- * "hello".delete_prefix("llo") #=> "hello"
*/
static VALUE
@@ -10338,13 +10721,11 @@ deleted_suffix_length(VALUE str, VALUE suffix)
/*
* call-seq:
- * str.delete_suffix!(suffix) -> self or nil
+ * delete_suffix!(suffix) -> self or nil
*
- * Deletes trailing <code>suffix</code> from <i>str</i>, returning
- * <code>nil</code> if no change was made.
+ * Like String#delete_suffix, except that +self+ is modified in place.
+ * Returns +self+ if the suffix is removed, +nil+ otherwise.
*
- * "hello".delete_suffix!("llo") #=> "he"
- * "hello".delete_suffix!("hel") #=> nil
*/
static VALUE
@@ -10362,19 +10743,17 @@ rb_str_delete_suffix_bang(VALUE str, VALUE suffix)
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
- ENC_CODERANGE_CLEAR(str);
+ ENC_CODERANGE_CLEAR(str);
}
return str;
}
/*
* call-seq:
- * str.delete_suffix(suffix) -> new_str
+ * delete_suffix(suffix) -> new_string
*
- * Returns a copy of <i>str</i> with trailing <code>suffix</code> deleted.
+ * :include: doc/string/delete_suffix.rdoc
*
- * "hello".delete_suffix("llo") #=> "he"
- * "hello".delete_suffix("hel") #=> "hello"
*/
static VALUE
@@ -10392,7 +10771,7 @@ void
rb_str_setter(VALUE val, ID id, VALUE *var)
{
if (!NIL_P(val) && !RB_TYPE_P(val, T_STRING)) {
- rb_raise(rb_eTypeError, "value of %"PRIsVALUE" must be String", rb_id2str(id));
+ rb_raise(rb_eTypeError, "value of %"PRIsVALUE" must be String", rb_id2str(id));
}
*var = val;
}
@@ -10402,9 +10781,9 @@ rb_fs_setter(VALUE val, ID id, VALUE *var)
{
val = rb_fs_check(val);
if (!val) {
- rb_raise(rb_eTypeError,
- "value of %"PRIsVALUE" must be String or Regexp",
- rb_id2str(id));
+ rb_raise(rb_eTypeError,
+ "value of %"PRIsVALUE" must be String or Regexp",
+ rb_id2str(id));
}
if (!NIL_P(val)) {
rb_warn_deprecated("`$;'", NULL);
@@ -10415,9 +10794,10 @@ rb_fs_setter(VALUE val, ID id, VALUE *var)
/*
* call-seq:
- * str.force_encoding(encoding) -> str
+ * force_encoding(encoding) -> self
+ *
+ * :include: doc/string/force_encoding.rdoc
*
- * Changes the encoding to +encoding+ and returns self.
*/
static VALUE
@@ -10431,29 +10811,54 @@ rb_str_force_encoding(VALUE str, VALUE enc)
/*
* call-seq:
- * str.b -> str
+ * b -> string
+ *
+ * :include: doc/string/b.rdoc
*
- * Returns a copied string whose encoding is ASCII-8BIT.
*/
static VALUE
rb_str_b(VALUE str)
{
- VALUE str2 = str_alloc(rb_cString);
+ VALUE str2;
+ if (FL_TEST(str, STR_NOEMBED)) {
+ str2 = str_alloc_heap(rb_cString);
+ }
+ else {
+ str2 = str_alloc_embed(rb_cString, RSTRING_EMBED_LEN(str) + TERM_LEN(str));
+ }
str_replace_shared_without_enc(str2, str);
- ENC_CODERANGE_CLEAR(str2);
+
+ if (rb_enc_asciicompat(STR_ENC_GET(str))) {
+ // BINARY strings can never be broken; they're either 7-bit ASCII or VALID.
+ // If we know the receiver's code range then we know the result's code range.
+ int cr = ENC_CODERANGE(str);
+ switch (cr) {
+ case ENC_CODERANGE_7BIT:
+ ENC_CODERANGE_SET(str2, ENC_CODERANGE_7BIT);
+ break;
+ case ENC_CODERANGE_BROKEN:
+ case ENC_CODERANGE_VALID:
+ ENC_CODERANGE_SET(str2, ENC_CODERANGE_VALID);
+ break;
+ default:
+ ENC_CODERANGE_CLEAR(str2);
+ break;
+ }
+ }
+
return str2;
}
/*
* call-seq:
- * str.valid_encoding? -> true or false
+ * valid_encoding? -> true or false
*
- * Returns true for a string which is encoded correctly.
+ * Returns +true+ if +self+ is encoded correctly, +false+ otherwise:
*
- * "\xc2\xa1".force_encoding("UTF-8").valid_encoding? #=> true
- * "\xc2".force_encoding("UTF-8").valid_encoding? #=> false
- * "\x80".force_encoding("UTF-8").valid_encoding? #=> false
+ * "\xc2\xa1".force_encoding("UTF-8").valid_encoding? # => true
+ * "\xc2".force_encoding("UTF-8").valid_encoding? # => false
+ * "\x80".force_encoding("UTF-8").valid_encoding? # => false
*/
static VALUE
@@ -10466,12 +10871,14 @@ rb_str_valid_encoding_p(VALUE str)
/*
* call-seq:
- * str.ascii_only? -> true or false
+ * ascii_only? -> true or false
*
- * Returns true for a string which has only ASCII characters.
+ * Returns +true+ if +self+ contains only ASCII characters,
+ * +false+ otherwise:
+ *
+ * 'abc'.ascii_only? # => true
+ * "abc\u{6666}".ascii_only? # => false
*
- * "abc".force_encoding("UTF-8").ascii_only? #=> true
- * "abc\u{6666}".force_encoding("UTF-8").ascii_only? #=> false
*/
static VALUE
@@ -10482,20 +10889,6 @@ rb_str_is_ascii_only_p(VALUE str)
return RBOOL(cr == ENC_CODERANGE_7BIT);
}
-/**
- * Shortens _str_ and adds three dots, an ellipsis, if it is longer
- * than _len_ characters.
- *
- * \param str the string to ellipsize.
- * \param len the maximum string length.
- * \return the ellipsized string.
- * \pre _len_ must not be negative.
- * \post the length of the returned string in characters is less than or equal to _len_.
- * \post If the length of _str_ is less than or equal _len_, returns _str_ itself.
- * \post the encoding of returned string is equal to the encoding of _str_.
- * \post the class of returned string is equal to the class of _str_.
- * \note the length is counted in characters.
- */
VALUE
rb_str_ellipsize(VALUE str, long len)
{
@@ -10508,27 +10901,27 @@ rb_str_ellipsize(VALUE str, long len)
if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
if (len * rb_enc_mbminlen(enc) >= blen ||
- (e = rb_enc_nth(p, e, len, enc)) - p == blen) {
- ret = str;
+ (e = rb_enc_nth(p, e, len, enc)) - p == blen) {
+ ret = str;
}
else if (len <= ellipsislen ||
- !(e = rb_enc_step_back(p, e, e, len = ellipsislen, enc))) {
- if (rb_enc_asciicompat(enc)) {
+ !(e = rb_enc_step_back(p, e, e, len = ellipsislen, enc))) {
+ if (rb_enc_asciicompat(enc)) {
ret = rb_str_new(ellipsis, len);
- rb_enc_associate(ret, enc);
- }
- else {
- estr = rb_usascii_str_new(ellipsis, len);
- ret = rb_str_encode(estr, rb_enc_from_encoding(enc), 0, Qnil);
- }
+ rb_enc_associate(ret, enc);
+ }
+ else {
+ estr = rb_usascii_str_new(ellipsis, len);
+ ret = rb_str_encode(estr, rb_enc_from_encoding(enc), 0, Qnil);
+ }
}
else if (ret = rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
- rb_str_cat(ret, ellipsis, ellipsislen);
+ rb_str_cat(ret, ellipsis, ellipsislen);
}
else {
- estr = rb_str_encode(rb_usascii_str_new(ellipsis, ellipsislen),
- rb_enc_from_encoding(enc), 0, Qnil);
- rb_str_append(ret, estr);
+ estr = rb_str_encode(rb_usascii_str_new(ellipsis, ellipsislen),
+ rb_enc_from_encoding(enc), 0, Qnil);
+ rb_str_append(ret, estr);
}
return ret;
}
@@ -10540,25 +10933,20 @@ str_compat_and_valid(VALUE str, rb_encoding *enc)
str = StringValue(str);
cr = rb_enc_str_coderange(str);
if (cr == ENC_CODERANGE_BROKEN) {
- rb_raise(rb_eArgError, "replacement must be valid byte sequence '%+"PRIsVALUE"'", str);
+ rb_raise(rb_eArgError, "replacement must be valid byte sequence '%+"PRIsVALUE"'", str);
}
else {
- rb_encoding *e = STR_ENC_GET(str);
- if (cr == ENC_CODERANGE_7BIT ? rb_enc_mbminlen(enc) != 1 : enc != e) {
- rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(enc), rb_enc_name(e));
- }
+ rb_encoding *e = STR_ENC_GET(str);
+ if (cr == ENC_CODERANGE_7BIT ? rb_enc_mbminlen(enc) != 1 : enc != e) {
+ rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
+ rb_enc_name(enc), rb_enc_name(e));
+ }
}
return str;
}
static VALUE enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr);
-/**
- * @param str the string to be scrubbed
- * @param repl the replacement character
- * @return If given string is invalid, returns a new string. Otherwise, returns Qnil.
- */
VALUE
rb_str_scrub(VALUE str, VALUE repl)
{
@@ -10571,9 +10959,9 @@ rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl)
{
int cr = ENC_CODERANGE_UNKNOWN;
if (enc == STR_ENC_GET(str)) {
- /* cached coderange makes sense only when enc equals the
- * actual encoding of str */
- cr = ENC_CODERANGE(str);
+ /* cached coderange makes sense only when enc equals the
+ * actual encoding of str */
+ cr = ENC_CODERANGE(str);
}
return enc_str_scrub(enc, str, repl, cr);
}
@@ -10588,26 +10976,26 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
long slen;
if (rb_block_given_p()) {
- if (!NIL_P(repl))
- rb_raise(rb_eArgError, "both of block and replacement given");
- replen = 0;
+ if (!NIL_P(repl))
+ rb_raise(rb_eArgError, "both of block and replacement given");
+ replen = 0;
}
if (ENC_CODERANGE_CLEAN_P(cr))
- return Qnil;
+ return Qnil;
if (!NIL_P(repl)) {
- repl = str_compat_and_valid(repl, enc);
+ repl = str_compat_and_valid(repl, enc);
}
if (rb_enc_dummy_p(enc)) {
- return Qnil;
+ return Qnil;
}
encidx = rb_enc_to_index(enc);
#define DEFAULT_REPLACE_CHAR(str) do { \
- static const char replace[sizeof(str)-1] = str; \
- rep = replace; replen = (int)sizeof(replace); \
+ RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
+ rep = replace; replen = (int)sizeof(replace); \
} while (0)
slen = RSTRING_LEN(str);
@@ -10617,204 +11005,204 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
sp = p;
if (rb_enc_asciicompat(enc)) {
- int rep7bit_p;
- if (!replen) {
- rep = NULL;
- rep7bit_p = FALSE;
- }
- else if (!NIL_P(repl)) {
- rep = RSTRING_PTR(repl);
- replen = RSTRING_LEN(repl);
- rep7bit_p = (ENC_CODERANGE(repl) == ENC_CODERANGE_7BIT);
- }
- else if (encidx == rb_utf8_encindex()) {
- DEFAULT_REPLACE_CHAR("\xEF\xBF\xBD");
- rep7bit_p = FALSE;
- }
- else {
- DEFAULT_REPLACE_CHAR("?");
- rep7bit_p = TRUE;
- }
- cr = ENC_CODERANGE_7BIT;
-
- p = search_nonascii(p, e);
- if (!p) {
- p = e;
- }
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_NEEDMORE_P(ret)) {
- break;
- }
- else if (MBCLEN_CHARFOUND_P(ret)) {
- cr = ENC_CODERANGE_VALID;
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- else if (MBCLEN_INVALID_P(ret)) {
- /*
- * p1~p: valid ascii/multibyte chars
- * p ~e: invalid bytes + unknown bytes
- */
- long clen = rb_enc_mbmaxlen(enc);
- if (NIL_P(buf)) buf = rb_str_buf_new(RSTRING_LEN(str));
- if (p > p1) {
- rb_str_buf_cat(buf, p1, p - p1);
- }
-
- if (e - p < clen) clen = e - p;
- if (clen <= 2) {
- clen = 1;
- }
- else {
- const char *q = p;
- clen--;
- for (; clen > 1; clen--) {
- ret = rb_enc_precise_mbclen(q, q + clen, enc);
- if (MBCLEN_NEEDMORE_P(ret)) break;
- if (MBCLEN_INVALID_P(ret)) continue;
- UNREACHABLE;
- }
- }
- if (rep) {
- rb_str_buf_cat(buf, rep, replen);
- if (!rep7bit_p) cr = ENC_CODERANGE_VALID;
- }
- else {
- repl = rb_yield(rb_enc_str_new(p, clen, enc));
+ int rep7bit_p;
+ if (!replen) {
+ rep = NULL;
+ rep7bit_p = FALSE;
+ }
+ else if (!NIL_P(repl)) {
+ rep = RSTRING_PTR(repl);
+ replen = RSTRING_LEN(repl);
+ rep7bit_p = (ENC_CODERANGE(repl) == ENC_CODERANGE_7BIT);
+ }
+ else if (encidx == rb_utf8_encindex()) {
+ DEFAULT_REPLACE_CHAR("\xEF\xBF\xBD");
+ rep7bit_p = FALSE;
+ }
+ else {
+ DEFAULT_REPLACE_CHAR("?");
+ rep7bit_p = TRUE;
+ }
+ cr = ENC_CODERANGE_7BIT;
+
+ p = search_nonascii(p, e);
+ if (!p) {
+ p = e;
+ }
+ while (p < e) {
+ int ret = rb_enc_precise_mbclen(p, e, enc);
+ if (MBCLEN_NEEDMORE_P(ret)) {
+ break;
+ }
+ else if (MBCLEN_CHARFOUND_P(ret)) {
+ cr = ENC_CODERANGE_VALID;
+ p += MBCLEN_CHARFOUND_LEN(ret);
+ }
+ else if (MBCLEN_INVALID_P(ret)) {
+ /*
+ * p1~p: valid ascii/multibyte chars
+ * p ~e: invalid bytes + unknown bytes
+ */
+ long clen = rb_enc_mbmaxlen(enc);
+ if (NIL_P(buf)) buf = rb_str_buf_new(RSTRING_LEN(str));
+ if (p > p1) {
+ rb_str_buf_cat(buf, p1, p - p1);
+ }
+
+ if (e - p < clen) clen = e - p;
+ if (clen <= 2) {
+ clen = 1;
+ }
+ else {
+ const char *q = p;
+ clen--;
+ for (; clen > 1; clen--) {
+ ret = rb_enc_precise_mbclen(q, q + clen, enc);
+ if (MBCLEN_NEEDMORE_P(ret)) break;
+ if (MBCLEN_INVALID_P(ret)) continue;
+ UNREACHABLE;
+ }
+ }
+ if (rep) {
+ rb_str_buf_cat(buf, rep, replen);
+ if (!rep7bit_p) cr = ENC_CODERANGE_VALID;
+ }
+ else {
+ repl = rb_yield(rb_enc_str_new(p, clen, enc));
str_mod_check(str, sp, slen);
- repl = str_compat_and_valid(repl, enc);
- rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
- if (ENC_CODERANGE(repl) == ENC_CODERANGE_VALID)
- cr = ENC_CODERANGE_VALID;
- }
- p += clen;
- p1 = p;
- p = search_nonascii(p, e);
- if (!p) {
- p = e;
- break;
- }
- }
- else {
- UNREACHABLE;
- }
- }
- if (NIL_P(buf)) {
- if (p == e) {
- ENC_CODERANGE_SET(str, cr);
- return Qnil;
- }
- buf = rb_str_buf_new(RSTRING_LEN(str));
- }
- if (p1 < p) {
- rb_str_buf_cat(buf, p1, p - p1);
- }
- if (p < e) {
- if (rep) {
- rb_str_buf_cat(buf, rep, replen);
- if (!rep7bit_p) cr = ENC_CODERANGE_VALID;
- }
- else {
- repl = rb_yield(rb_enc_str_new(p, e-p, enc));
+ repl = str_compat_and_valid(repl, enc);
+ rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
+ if (ENC_CODERANGE(repl) == ENC_CODERANGE_VALID)
+ cr = ENC_CODERANGE_VALID;
+ }
+ p += clen;
+ p1 = p;
+ p = search_nonascii(p, e);
+ if (!p) {
+ p = e;
+ break;
+ }
+ }
+ else {
+ UNREACHABLE;
+ }
+ }
+ if (NIL_P(buf)) {
+ if (p == e) {
+ ENC_CODERANGE_SET(str, cr);
+ return Qnil;
+ }
+ buf = rb_str_buf_new(RSTRING_LEN(str));
+ }
+ if (p1 < p) {
+ rb_str_buf_cat(buf, p1, p - p1);
+ }
+ if (p < e) {
+ if (rep) {
+ rb_str_buf_cat(buf, rep, replen);
+ if (!rep7bit_p) cr = ENC_CODERANGE_VALID;
+ }
+ else {
+ repl = rb_yield(rb_enc_str_new(p, e-p, enc));
str_mod_check(str, sp, slen);
- repl = str_compat_and_valid(repl, enc);
- rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
- if (ENC_CODERANGE(repl) == ENC_CODERANGE_VALID)
- cr = ENC_CODERANGE_VALID;
- }
- }
+ repl = str_compat_and_valid(repl, enc);
+ rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
+ if (ENC_CODERANGE(repl) == ENC_CODERANGE_VALID)
+ cr = ENC_CODERANGE_VALID;
+ }
+ }
}
else {
- /* ASCII incompatible */
- long mbminlen = rb_enc_mbminlen(enc);
- if (!replen) {
- rep = NULL;
- }
- else if (!NIL_P(repl)) {
- rep = RSTRING_PTR(repl);
- replen = RSTRING_LEN(repl);
- }
- else if (encidx == ENCINDEX_UTF_16BE) {
- DEFAULT_REPLACE_CHAR("\xFF\xFD");
- }
- else if (encidx == ENCINDEX_UTF_16LE) {
- DEFAULT_REPLACE_CHAR("\xFD\xFF");
- }
- else if (encidx == ENCINDEX_UTF_32BE) {
- DEFAULT_REPLACE_CHAR("\x00\x00\xFF\xFD");
- }
- else if (encidx == ENCINDEX_UTF_32LE) {
- DEFAULT_REPLACE_CHAR("\xFD\xFF\x00\x00");
- }
- else {
- DEFAULT_REPLACE_CHAR("?");
- }
-
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_NEEDMORE_P(ret)) {
- break;
- }
- else if (MBCLEN_CHARFOUND_P(ret)) {
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- else if (MBCLEN_INVALID_P(ret)) {
- const char *q = p;
- long clen = rb_enc_mbmaxlen(enc);
- if (NIL_P(buf)) buf = rb_str_buf_new(RSTRING_LEN(str));
- if (p > p1) rb_str_buf_cat(buf, p1, p - p1);
-
- if (e - p < clen) clen = e - p;
- if (clen <= mbminlen * 2) {
- clen = mbminlen;
- }
- else {
- clen -= mbminlen;
- for (; clen > mbminlen; clen-=mbminlen) {
- ret = rb_enc_precise_mbclen(q, q + clen, enc);
- if (MBCLEN_NEEDMORE_P(ret)) break;
- if (MBCLEN_INVALID_P(ret)) continue;
- UNREACHABLE;
- }
- }
- if (rep) {
- rb_str_buf_cat(buf, rep, replen);
- }
- else {
- repl = rb_yield(rb_enc_str_new(p, clen, enc));
+ /* ASCII incompatible */
+ long mbminlen = rb_enc_mbminlen(enc);
+ if (!replen) {
+ rep = NULL;
+ }
+ else if (!NIL_P(repl)) {
+ rep = RSTRING_PTR(repl);
+ replen = RSTRING_LEN(repl);
+ }
+ else if (encidx == ENCINDEX_UTF_16BE) {
+ DEFAULT_REPLACE_CHAR("\xFF\xFD");
+ }
+ else if (encidx == ENCINDEX_UTF_16LE) {
+ DEFAULT_REPLACE_CHAR("\xFD\xFF");
+ }
+ else if (encidx == ENCINDEX_UTF_32BE) {
+ DEFAULT_REPLACE_CHAR("\x00\x00\xFF\xFD");
+ }
+ else if (encidx == ENCINDEX_UTF_32LE) {
+ DEFAULT_REPLACE_CHAR("\xFD\xFF\x00\x00");
+ }
+ else {
+ DEFAULT_REPLACE_CHAR("?");
+ }
+
+ while (p < e) {
+ int ret = rb_enc_precise_mbclen(p, e, enc);
+ if (MBCLEN_NEEDMORE_P(ret)) {
+ break;
+ }
+ else if (MBCLEN_CHARFOUND_P(ret)) {
+ p += MBCLEN_CHARFOUND_LEN(ret);
+ }
+ else if (MBCLEN_INVALID_P(ret)) {
+ const char *q = p;
+ long clen = rb_enc_mbmaxlen(enc);
+ if (NIL_P(buf)) buf = rb_str_buf_new(RSTRING_LEN(str));
+ if (p > p1) rb_str_buf_cat(buf, p1, p - p1);
+
+ if (e - p < clen) clen = e - p;
+ if (clen <= mbminlen * 2) {
+ clen = mbminlen;
+ }
+ else {
+ clen -= mbminlen;
+ for (; clen > mbminlen; clen-=mbminlen) {
+ ret = rb_enc_precise_mbclen(q, q + clen, enc);
+ if (MBCLEN_NEEDMORE_P(ret)) break;
+ if (MBCLEN_INVALID_P(ret)) continue;
+ UNREACHABLE;
+ }
+ }
+ if (rep) {
+ rb_str_buf_cat(buf, rep, replen);
+ }
+ else {
+ repl = rb_yield(rb_enc_str_new(p, clen, enc));
str_mod_check(str, sp, slen);
- repl = str_compat_and_valid(repl, enc);
- rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
- }
- p += clen;
- p1 = p;
- }
- else {
- UNREACHABLE;
- }
- }
- if (NIL_P(buf)) {
- if (p == e) {
- ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
- return Qnil;
- }
- buf = rb_str_buf_new(RSTRING_LEN(str));
- }
- if (p1 < p) {
- rb_str_buf_cat(buf, p1, p - p1);
- }
- if (p < e) {
- if (rep) {
- rb_str_buf_cat(buf, rep, replen);
- }
- else {
- repl = rb_yield(rb_enc_str_new(p, e-p, enc));
+ repl = str_compat_and_valid(repl, enc);
+ rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
+ }
+ p += clen;
+ p1 = p;
+ }
+ else {
+ UNREACHABLE;
+ }
+ }
+ if (NIL_P(buf)) {
+ if (p == e) {
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
+ return Qnil;
+ }
+ buf = rb_str_buf_new(RSTRING_LEN(str));
+ }
+ if (p1 < p) {
+ rb_str_buf_cat(buf, p1, p - p1);
+ }
+ if (p < e) {
+ if (rep) {
+ rb_str_buf_cat(buf, rep, replen);
+ }
+ else {
+ repl = rb_yield(rb_enc_str_new(p, e-p, enc));
str_mod_check(str, sp, slen);
- repl = str_compat_and_valid(repl, enc);
- rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
- }
- }
- cr = ENC_CODERANGE_VALID;
+ repl = str_compat_and_valid(repl, enc);
+ rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
+ }
+ }
+ cr = ENC_CODERANGE_VALID;
}
ENCODING_CODERANGE_SET(buf, rb_enc_to_index(enc), cr);
return buf;
@@ -10822,17 +11210,11 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
/*
* call-seq:
- * str.scrub -> new_str
- * str.scrub(repl) -> new_str
- * str.scrub{|bytes|} -> new_str
+ * scrub(replacement_string = default_replacement) -> new_string
+ * scrub{|bytes| ... } -> new_string
*
- * If the string is invalid byte sequence then replace invalid bytes with given replacement
- * character, else returns self.
- * If block is given, replace invalid bytes with returned value of the block.
+ * :include: doc/string/scrub.rdoc
*
- * "abc\u3042\x81".scrub #=> "abc\u3042\uFFFD"
- * "abc\u3042\x81".scrub("*") #=> "abc\u3042*"
- * "abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
*/
static VALUE
str_scrub(int argc, VALUE *argv, VALUE str)
@@ -10844,17 +11226,12 @@ str_scrub(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.scrub! -> str
- * str.scrub!(repl) -> str
- * str.scrub!{|bytes|} -> str
+ * scrub! -> self
+ * scrub!(replacement_string = default_replacement) -> self
+ * scrub!{|bytes| ... } -> self
*
- * If the string is invalid byte sequence then replace invalid bytes with given replacement
- * character, else returns self.
- * If block is given, replace invalid bytes with returned value of the block.
+ * Like String#scrub, except that any replacements are made in +self+.
*
- * "abc\u3042\x81".scrub! #=> "abc\u3042\uFFFD"
- * "abc\u3042\x81".scrub!("*") #=> "abc\u3042*"
- * "abc\u3042\xE3\x80".scrub!{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"
*/
static VALUE
str_scrub_bang(int argc, VALUE *argv, VALUE str)
@@ -10876,8 +11253,8 @@ unicode_normalize_common(int argc, VALUE *argv, VALUE str, ID id)
VALUE argv2[2];
if (!UnicodeNormalizeRequired) {
- rb_require("unicode_normalize/normalize.rb");
- UnicodeNormalizeRequired = 1;
+ rb_require("unicode_normalize/normalize.rb");
+ UnicodeNormalizeRequired = 1;
}
argv2[0] = str;
if (rb_check_arity(argc, 0, 1)) argv2[1] = argv[0];
@@ -10886,25 +11263,36 @@ unicode_normalize_common(int argc, VALUE *argv, VALUE str, ID id)
/*
* call-seq:
- * str.unicode_normalize(form=:nfc)
+ * unicode_normalize(form = :nfc) -> string
+ *
+ * Returns a copy of +self+ with
+ * {Unicode normalization}[https://unicode.org/reports/tr15] applied.
*
- * Unicode Normalization---Returns a normalized form of +str+,
- * using Unicode normalizations NFC, NFD, NFKC, or NFKD.
- * The normalization form used is determined by +form+, which can
- * be any of the four values +:nfc+, +:nfd+, +:nfkc+, or +:nfkd+.
- * The default is +:nfc+.
+ * Argument +form+ must be one of the following symbols
+ * (see {Unicode normalization forms}[https://unicode.org/reports/tr15/#Norm_Forms]):
*
- * If the string is not in a Unicode Encoding, then an Exception is raised.
- * In this context, 'Unicode Encoding' means any of UTF-8, UTF-16BE/LE,
- * and UTF-32BE/LE, as well as GB18030, UCS_2BE, and UCS_4BE.
- * Anything other than UTF-8 is implemented by converting to UTF-8,
- * which makes it slower than UTF-8.
+ * - +:nfc+: Canonical decomposition, followed by canonical composition.
+ * - +:nfd+: Canonical decomposition.
+ * - +:nfkc+: Compatibility decomposition, followed by canonical composition.
+ * - +:nfkd+: Compatibility decomposition.
*
- * "a\u0300".unicode_normalize #=> "\u00E0"
- * "a\u0300".unicode_normalize(:nfc) #=> "\u00E0"
- * "\u00E0".unicode_normalize(:nfd) #=> "a\u0300"
- * "\xE0".force_encoding('ISO-8859-1').unicode_normalize(:nfd)
- * #=> Encoding::CompatibilityError raised
+ * The encoding of +self+ must be one of:
+ *
+ * - Encoding::UTF_8
+ * - Encoding::UTF_16BE
+ * - Encoding::UTF_16LE
+ * - Encoding::UTF_32BE
+ * - Encoding::UTF_32LE
+ * - Encoding::GB18030
+ * - Encoding::UCS_2BE
+ * - Encoding::UCS_4BE
+ *
+ * Examples:
+ *
+ * "a\u0300".unicode_normalize # => "a"
+ * "\u00E0".unicode_normalize(:nfd) # => "a "
+ *
+ * Related: String#unicode_normalize!, String#unicode_normalized?.
*/
static VALUE
rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
@@ -10914,10 +11302,13 @@ rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.unicode_normalize!(form=:nfc)
+ * unicode_normalize!(form = :nfc) -> self
+ *
+ * Like String#unicode_normalize, except that the normalization
+ * is performed on +self+.
+ *
+ * Related String#unicode_normalized?.
*
- * Destructive version of String#unicode_normalize, doing Unicode
- * normalization in place.
*/
static VALUE
rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
@@ -10926,21 +11317,27 @@ rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
}
/* call-seq:
- * str.unicode_normalized?(form=:nfc)
+ * unicode_normalized?(form = :nfc) -> true or false
+ *
+ * Returns +true+ if +self+ is in the given +form+ of Unicode normalization,
+ * +false+ otherwise.
+ * The +form+ must be one of +:nfc+, +:nfd+, +:nfkc+, or +:nfkd+.
+ *
+ * Examples:
+ *
+ * "a\u0300".unicode_normalized? # => false
+ * "a\u0300".unicode_normalized?(:nfd) # => true
+ * "\u00E0".unicode_normalized? # => true
+ * "\u00E0".unicode_normalized?(:nfd) # => false
+ *
*
- * Checks whether +str+ is in Unicode normalization form +form+,
- * which can be any of the four values +:nfc+, +:nfd+, +:nfkc+, or +:nfkd+.
- * The default is +:nfc+.
+ * Raises an exception if +self+ is not in a Unicode encoding:
*
- * If the string is not in a Unicode Encoding, then an Exception is raised.
- * For details, see String#unicode_normalize.
+ * s = "\xE0".force_encoding('ISO-8859-1')
+ * s.unicode_normalized? # Raises Encoding::CompatibilityError.
+ *
+ * Related: String#unicode_normalize, String#unicode_normalize!.
*
- * "a\u0300".unicode_normalized? #=> false
- * "a\u0300".unicode_normalized?(:nfd) #=> true
- * "\u00E0".unicode_normalized? #=> true
- * "\u00E0".unicode_normalized?(:nfd) #=> false
- * "\xE0".force_encoding('ISO-8859-1').unicode_normalized?
- * #=> Encoding::CompatibilityError raised
*/
static VALUE
rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
@@ -10951,15 +11348,18 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
/**********************************************************************
* Document-class: Symbol
*
- * Symbol objects represent names inside the Ruby interpreter. They
- * are generated using the <code>:name</code> and
- * <code>:"string"</code> literals syntax, and by the various
- * <code>to_sym</code> methods. The same Symbol object will be
- * created for a given name or string for the duration of a program's
- * execution, regardless of the context or meaning of that name. Thus
- * if <code>Fred</code> is a constant in one context, a method in
- * another, and a class in a third, the Symbol <code>:Fred</code>
- * will be the same object in all three contexts.
+ * Symbol objects represent named identifiers inside the Ruby interpreter.
+ *
+ * You can create a \Symbol object explicitly with:
+ *
+ * - A {symbol literal}[rdoc-ref:syntax/literals.rdoc@Symbol+Literals].
+ *
+ * The same Symbol object will be
+ * created for a given name or string for the duration of a program's
+ * execution, regardless of the context or meaning of that name. Thus
+ * if <code>Fred</code> is a constant in one context, a method in
+ * another, and a class in a third, the Symbol <code>:Fred</code>
+ * will be the same object in all three contexts.
*
* module One
* class Fred
@@ -10977,15 +11377,104 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
* $f2.object_id #=> 2514190
* $f3.object_id #=> 2514190
*
+ * Constant, method, and variable names are returned as symbols:
+ *
+ * module One
+ * Two = 2
+ * def three; 3 end
+ * @four = 4
+ * @@five = 5
+ * $six = 6
+ * end
+ * seven = 7
+ *
+ * One.constants
+ * # => [:Two]
+ * One.instance_methods(true)
+ * # => [:three]
+ * One.instance_variables
+ * # => [:@four]
+ * One.class_variables
+ * # => [:@@five]
+ * global_variables.grep(/six/)
+ * # => [:$six]
+ * local_variables
+ * # => [:seven]
+ *
+ * Symbol objects are different from String objects in that
+ * Symbol objects represent identifiers, while String objects
+ * represent text or data.
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere. \Class \Symbol:
+ *
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
+ *
+ * Here, class \Symbol provides methods that are useful for:
+ *
+ * - {Querying}[rdoc-ref:Symbol@Methods+for+Querying]
+ * - {Comparing}[rdoc-ref:Symbol@Methods+for+Comparing]
+ * - {Converting}[rdoc-ref:Symbol@Methods+for+Converting]
+ *
+ * === Methods for Querying
+ *
+ * - ::all_symbols: Returns an array of the symbols currently in Ruby's symbol table.
+ * - #=~: Returns the index of the first substring in symbol that matches a
+ * given Regexp or other object; returns +nil+ if no match is found.
+ * - #[], #slice : Returns a substring of symbol
+ * determined by a given index, start/length, or range, or string.
+ * - #empty?: Returns +true+ if +self.length+ is zero; +false+ otherwise.
+ * - #encoding: Returns the Encoding object that represents the encoding
+ * of symbol.
+ * - #end_with?: Returns +true+ if symbol ends with
+ * any of the given strings.
+ * - #match: Returns a MatchData object if symbol
+ * matches a given Regexp; +nil+ otherwise.
+ * - #match?: Returns +true+ if symbol
+ * matches a given Regexp; +false+ otherwise.
+ * - #length, #size: Returns the number of characters in symbol.
+ * - #start_with?: Returns +true+ if symbol starts with
+ * any of the given strings.
+ *
+ * === Methods for Comparing
+ *
+ * - #<=>: Returns -1, 0, or 1 as a given symbol is smaller than, equal to,
+ * or larger than symbol.
+ * - #==, #===: Returns +true+ if a given symbol has the same content and
+ * encoding.
+ * - #casecmp: Ignoring case, returns -1, 0, or 1 as a given
+ * symbol is smaller than, equal to, or larger than symbol.
+ * - #casecmp?: Returns +true+ if symbol is equal to a given symbol
+ * after Unicode case folding; +false+ otherwise.
+ *
+ * === Methods for Converting
+ *
+ * - #capitalize: Returns symbol with the first character upcased
+ * and all other characters downcased.
+ * - #downcase: Returns symbol with all characters downcased.
+ * - #inspect: Returns the string representation of +self+ as a symbol literal.
+ * - #name: Returns the frozen string corresponding to symbol.
+ * - #succ, #next: Returns the symbol that is the successor to symbol.
+ * - #swapcase: Returns symbol with all upcase characters downcased
+ * and all downcase characters upcased.
+ * - #to_proc: Returns a Proc object which responds to the method named by symbol.
+ * - #to_s, #id2name: Returns the string corresponding to +self+.
+ * - #to_sym, #intern: Returns +self+.
+ * - #upcase: Returns symbol with all characters upcased.
+ *
*/
/*
* call-seq:
- * sym == obj -> true or false
+ * symbol == object -> true or false
+ *
+ * Returns +true+ if +object+ is the same object as +self+, +false+ otherwise.
+ *
+ * Symbol#=== is an alias for Symbol#==.
*
- * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
- * symbol, returns <code>true</code>.
*/
#define sym_equal rb_obj_equal
@@ -10994,14 +11483,14 @@ static int
sym_printable(const char *s, const char *send, rb_encoding *enc)
{
while (s < send) {
- int n;
- int c = rb_enc_precise_mbclen(s, send, enc);
+ int n;
+ int c = rb_enc_precise_mbclen(s, send, enc);
- if (!MBCLEN_CHARFOUND_P(c)) return FALSE;
- n = MBCLEN_CHARFOUND_LEN(c);
- c = rb_enc_mbc_to_codepoint(s, send, enc);
- if (!rb_enc_isprint(c, enc)) return FALSE;
- s += n;
+ if (!MBCLEN_CHARFOUND_P(c)) return FALSE;
+ n = MBCLEN_CHARFOUND_LEN(c);
+ c = rb_enc_mbc_to_codepoint(s, send, enc);
+ if (!rb_enc_isprint(c, enc)) return FALSE;
+ s += n;
}
return TRUE;
}
@@ -11019,8 +11508,8 @@ rb_str_symname_p(VALUE sym)
ptr = RSTRING_PTR(sym);
len = RSTRING_LEN(sym);
if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) || len != (long)strlen(ptr) ||
- !rb_enc_symname2_p(ptr, len, enc) || !sym_printable(ptr, ptr + len, enc)) {
- return FALSE;
+ !rb_enc_symname2_p(ptr, len, enc) || !sym_printable(ptr, ptr + len, enc)) {
+ return FALSE;
}
return TRUE;
}
@@ -11040,8 +11529,8 @@ rb_str_quote_unprintable(VALUE str)
ptr = RSTRING_PTR(str);
len = RSTRING_LEN(str);
if ((resenc != enc && !rb_str_is_ascii_only_p(str)) ||
- !sym_printable(ptr, ptr + len, enc)) {
- return rb_str_escape(str);
+ !sym_printable(ptr, ptr + len, enc)) {
+ return rb_str_escape(str);
}
return str;
}
@@ -11051,18 +11540,21 @@ rb_id_quote_unprintable(ID id)
{
VALUE str = rb_id2str(id);
if (!rb_str_symname_p(str)) {
- return rb_str_escape(str);
+ return rb_str_escape(str);
}
return str;
}
/*
* call-seq:
- * sym.inspect -> string
+ * inspect -> string
*
- * Returns the representation of <i>sym</i> as a symbol literal.
+ * Returns a string representation of +self+ (including the leading colon):
+ *
+ * :foo.inspect # => ":foo"
+ *
+ * Related: Symbol#to_s, Symbol#name.
*
- * :fred.inspect #=> ":fred"
*/
static VALUE
@@ -11074,116 +11566,65 @@ sym_inspect(VALUE sym)
char *dest;
if (!rb_str_symname_p(str)) {
- str = rb_str_inspect(str);
- len = RSTRING_LEN(str);
- rb_str_resize(str, len + 1);
- dest = RSTRING_PTR(str);
- memmove(dest + 1, dest, len);
+ str = rb_str_inspect(str);
+ len = RSTRING_LEN(str);
+ rb_str_resize(str, len + 1);
+ dest = RSTRING_PTR(str);
+ memmove(dest + 1, dest, len);
}
else {
- rb_encoding *enc = STR_ENC_GET(str);
- RSTRING_GETMEM(str, ptr, len);
- str = rb_enc_str_new(0, len + 1, enc);
- dest = RSTRING_PTR(str);
- memcpy(dest + 1, ptr, len);
+ rb_encoding *enc = STR_ENC_GET(str);
+ RSTRING_GETMEM(str, ptr, len);
+ str = rb_enc_str_new(0, len + 1, enc);
+ dest = RSTRING_PTR(str);
+ memcpy(dest + 1, ptr, len);
}
dest[0] = ':';
return str;
}
-#if 0 /* for RDoc */
/*
* call-seq:
- * sym.name -> string
+ * to_s -> string
*
- * Returns the name or string corresponding to <i>sym</i>. Unlike #to_s, the
- * returned string is frozen.
+ * Returns a string representation of +self+ (not including the leading colon):
*
- * :fred.name #=> "fred"
- * :fred.name.frozen? #=> true
- * :fred.to_s #=> "fred"
- * :fred.to_s.frozen? #=> false
- */
-VALUE
-rb_sym2str(VALUE sym)
-{
-
-}
-#endif
-
-
-/*
- * call-seq:
- * sym.id2name -> string
- * sym.to_s -> string
+ * :foo.to_s # => "foo"
*
- * Returns the name or string corresponding to <i>sym</i>.
+ * Symbol#id2name is an alias for Symbol#to_s.
*
- * :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.
+ * Related: Symbol#inspect, Symbol#name.
*/
-
VALUE
rb_sym_to_s(VALUE sym)
{
return str_new_shared(rb_cString, rb_sym2str(sym));
}
-
-/*
- * call-seq:
- * sym.to_sym -> sym
- * sym.intern -> sym
- *
- * In general, <code>to_sym</code> returns the Symbol corresponding
- * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
- * in this case.
- */
-
-static VALUE
-sym_to_sym(VALUE sym)
-{
- return sym;
-}
-
MJIT_FUNC_EXPORTED VALUE
rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc)
{
VALUE obj;
if (argc < 1) {
- rb_raise(rb_eArgError, "no receiver given");
+ rb_raise(rb_eArgError, "no receiver given");
}
obj = argv[0];
return rb_funcall_with_block_kw(obj, mid, argc - 1, argv + 1, passed_proc, kw_splat);
}
-#if 0
/*
- * call-seq:
- * sym.to_proc
+ * call-seq:
+ * succ
*
- * Returns a _Proc_ object which responds to the given method by _sym_.
+ * Equivalent to <tt>self.to_s.succ.to_sym</tt>:
*
- * (1..3).collect(&:to_s) #=> ["1", "2", "3"]
- */
-
-VALUE
-rb_sym_to_proc(VALUE sym)
-{
-}
-#endif
-
-/*
- * call-seq:
+ * :foo.succ # => :fop
*
- * sym.succ
+ * Symbol#next is an alias for Symbol#succ.
*
- * Same as <code>sym.to_s.succ.intern</code>.
+ * Related: String#succ.
*/
static VALUE
@@ -11193,91 +11634,74 @@ sym_succ(VALUE sym)
}
/*
- * call-seq:
+ * call-seq:
+ * symbol <=> object -> -1, 0, +1, or nil
*
- * symbol <=> other_symbol -> -1, 0, +1, or nil
+ * If +object+ is a symbol,
+ * returns the equivalent of <tt>symbol.to_s <=> object.to_s</tt>:
*
- * Compares +symbol+ with +other_symbol+ after calling #to_s on each of the
- * symbols. Returns -1, 0, +1, or +nil+ depending on whether +symbol+ is
- * less than, equal to, or greater than +other_symbol+.
+ * :bar <=> :foo # => -1
+ * :foo <=> :foo # => 0
+ * :foo <=> :bar # => 1
*
- * +nil+ is returned if the two values are incomparable.
+ * Otherwise, returns +nil+:
*
- * See String#<=> for more information.
+ * :foo <=> 'bar' # => nil
+ *
+ * Related: String#<=>.
*/
static VALUE
sym_cmp(VALUE sym, VALUE other)
{
if (!SYMBOL_P(other)) {
- return Qnil;
+ return Qnil;
}
return rb_str_cmp_m(rb_sym2str(sym), rb_sym2str(other));
}
/*
- * call-seq:
- * sym.casecmp(other_symbol) -> -1, 0, +1, or nil
- *
- * Case-insensitive version of Symbol#<=>.
- * Currently, case-insensitivity only works on characters A-Z/a-z,
- * not all of Unicode. This is different from Symbol#casecmp?.
- *
- * :aBcDeF.casecmp(:abcde) #=> 1
- * :aBcDeF.casecmp(:abcdef) #=> 0
- * :aBcDeF.casecmp(:abcdefg) #=> -1
- * :abcdef.casecmp(:ABCDEF) #=> 0
+ * call-seq:
+ * casecmp(object) -> -1, 0, 1, or nil
*
- * +nil+ is returned if the two symbols have incompatible encodings,
- * or if +other_symbol+ is not a symbol.
+ * :include: doc/symbol/casecmp.rdoc
*
- * :foo.casecmp(2) #=> nil
- * "\u{e4 f6 fc}".encode("ISO-8859-1").to_sym.casecmp(:"\u{c4 d6 dc}") #=> nil
*/
static VALUE
sym_casecmp(VALUE sym, VALUE other)
{
if (!SYMBOL_P(other)) {
- return Qnil;
+ return Qnil;
}
return str_casecmp(rb_sym2str(sym), rb_sym2str(other));
}
/*
- * call-seq:
- * sym.casecmp?(other_symbol) -> true, false, or nil
- *
- * Returns +true+ if +sym+ and +other_symbol+ are equal after
- * Unicode case folding, +false+ if they are not equal.
- *
- * :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
+ * call-seq:
+ * casecmp?(object) -> true, false, or nil
*
- * +nil+ is returned if the two symbols have incompatible encodings,
- * or if +other_symbol+ is not a symbol.
+ * :include: doc/symbol/casecmp_p.rdoc
*
- * :foo.casecmp?(2) #=> nil
- * "\u{e4 f6 fc}".encode("ISO-8859-1").to_sym.casecmp?(:"\u{c4 d6 dc}") #=> nil
*/
static VALUE
sym_casecmp_p(VALUE sym, VALUE other)
{
if (!SYMBOL_P(other)) {
- return Qnil;
+ return Qnil;
}
return str_casecmp_p(rb_sym2str(sym), rb_sym2str(other));
}
/*
- * call-seq:
- * sym =~ obj -> integer or nil
+ * call-seq:
+ * symbol =~ object -> integer or nil
+ *
+ * Equivalent to <tt>symbol.to_s =~ object</tt>,
+ * including possible updates to global variables;
+ * see String#=~.
*
- * Returns <code>sym.to_s =~ obj</code>.
*/
static VALUE
@@ -11287,11 +11711,14 @@ sym_match(VALUE sym, VALUE other)
}
/*
- * call-seq:
- * sym.match(pattern) -> matchdata or nil
- * sym.match(pattern, pos) -> matchdata or nil
+ * call-seq:
+ * match(pattern, offset = 0) -> matchdata or nil
+ * match(pattern, offset = 0) {|matchdata| } -> object
+ *
+ * Equivalent to <tt>self.to_s.match</tt>,
+ * including possible updates to global variables;
+ * see String#match.
*
- * Returns <code>sym.to_s.match</code>.
*/
static VALUE
@@ -11301,11 +11728,12 @@ sym_match_m(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym.match?(pattern) -> true or false
- * sym.match?(pattern, pos) -> true or false
+ * call-seq:
+ * match?(pattern, offset) -> true or false
+ *
+ * Equivalent to <tt>sym.to_s.match?</tt>;
+ * see String#match.
*
- * Returns <code>sym.to_s.match?</code>.
*/
static VALUE
@@ -11315,13 +11743,15 @@ sym_match_m_p(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym[idx] -> char
- * sym[b, n] -> string
- * sym.slice(idx) -> char
- * sym.slice(b, n) -> string
+ * call-seq:
+ * symbol[index] -> string or nil
+ * symbol[start, length] -> string or nil
+ * symbol[range] -> string or nil
+ * symbol[regexp, capture = 0] -> string or nil
+ * symbol[substring] -> string or nil
+ *
+ * Equivalent to <tt>symbol.to_s[]</tt>; see String#[].
*
- * Returns <code>sym.to_s[]</code>.
*/
static VALUE
@@ -11331,11 +11761,13 @@ sym_aref(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym.length -> integer
- * sym.size -> integer
+ * call-seq:
+ * length -> integer
+ *
+ * Equivalent to <tt>self.to_s.length</tt>; see String#length.
+ *
+ * Symbol#size is an alias for Symbol#length.
*
- * Same as <code>sym.to_s.length</code>.
*/
static VALUE
@@ -11345,10 +11777,11 @@ sym_length(VALUE sym)
}
/*
- * call-seq:
- * sym.empty? -> true or false
+ * call-seq:
+ * empty? -> true or false
+ *
+ * Returns +true+ if +self+ is <tt>:''</tt>, +false+ otherwise.
*
- * Returns whether _sym_ is :"" or not.
*/
static VALUE
@@ -11358,11 +11791,13 @@ sym_empty(VALUE sym)
}
/*
- * call-seq:
- * sym.upcase -> symbol
- * sym.upcase([options]) -> symbol
+ * call-seq:
+ * upcase(*options) -> symbol
+ *
+ * Equivalent to <tt>sym.to_s.upcase.to_sym</tt>.
+ *
+ * See String#upcase.
*
- * Same as <code>sym.to_s.upcase.intern</code>.
*/
static VALUE
@@ -11372,11 +11807,15 @@ sym_upcase(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym.downcase -> symbol
- * sym.downcase([options]) -> symbol
+ * call-seq:
+ * downcase(*options) -> symbol
+ *
+ * Equivalent to <tt>sym.to_s.downcase.to_sym</tt>.
+ *
+ * See String#downcase.
+ *
+ * Related: Symbol#upcase.
*
- * Same as <code>sym.to_s.downcase.intern</code>.
*/
static VALUE
@@ -11386,11 +11825,13 @@ sym_downcase(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym.capitalize -> symbol
- * sym.capitalize([options]) -> symbol
+ * call-seq:
+ * capitalize(*options) -> symbol
+ *
+ * Equivalent to <tt>sym.to_s.capitalize.to_sym</tt>.
+ *
+ * See String#capitalize.
*
- * Same as <code>sym.to_s.capitalize.intern</code>.
*/
static VALUE
@@ -11400,11 +11841,13 @@ sym_capitalize(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym.swapcase -> symbol
- * sym.swapcase([options]) -> symbol
+ * call-seq:
+ * swapcase(*options) -> symbol
+ *
+ * Equivalent to <tt>sym.to_s.swapcase.to_sym</tt>.
+ *
+ * See String#swapcase.
*
- * Same as <code>sym.to_s.swapcase.intern</code>.
*/
static VALUE
@@ -11415,17 +11858,10 @@ sym_swapcase(int argc, VALUE *argv, VALUE sym)
/*
* call-seq:
- * sym.start_with?([prefixes]+) -> true or false
- *
- * Returns true if +sym+ starts with one of the +prefixes+ given.
- * Each of the +prefixes+ should be a String or a Regexp.
+ * start_with?(*string_or_regexp) -> true or false
*
- * :hello.start_with?("hell") #=> true
- * :hello.start_with?(/H/i) #=> true
+ * Equivalent to <tt>self.to_s.start_with?</tt>; see String#start_with?.
*
- * # returns true if one of the prefixes matches.
- * :hello.start_with?("heaven", "hell") #=> true
- * :hello.start_with?("heaven", "paradise") #=> false
*/
static VALUE
@@ -11436,15 +11872,11 @@ sym_start_with(int argc, VALUE *argv, VALUE sym)
/*
* call-seq:
- * sym.end_with?([suffixes]+) -> true or false
+ * end_with?(*string_or_regexp) -> true or false
*
- * Returns true if +sym+ ends with one of the +suffixes+ given.
*
- * :hello.end_with?("ello") #=> true
+ * Equivalent to <tt>self.to_s.end_with?</tt>; see String#end_with?.
*
- * # returns true if one of the +suffixes+ matches.
- * :hello.end_with?("heaven", "ello") #=> true
- * :hello.end_with?("heaven", "paradise") #=> false
*/
static VALUE
@@ -11454,10 +11886,11 @@ sym_end_with(int argc, VALUE *argv, VALUE sym)
}
/*
- * call-seq:
- * sym.encoding -> encoding
+ * call-seq:
+ * encoding -> encoding
+ *
+ * Equivalent to <tt>self.to_s.encoding</tt>; see String#encoding.
*
- * Returns the Encoding object that represents the encoding of _sym_.
*/
static VALUE
@@ -11470,12 +11903,12 @@ static VALUE
string_for_symbol(VALUE name)
{
if (!RB_TYPE_P(name, T_STRING)) {
- VALUE tmp = rb_check_string_type(name);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol",
- name);
- }
- name = tmp;
+ VALUE tmp = rb_check_string_type(name);
+ if (NIL_P(tmp)) {
+ rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol",
+ name);
+ }
+ name = tmp;
}
return name;
}
@@ -11484,7 +11917,7 @@ ID
rb_to_id(VALUE name)
{
if (SYMBOL_P(name)) {
- return SYM2ID(name);
+ return SYM2ID(name);
}
name = string_for_symbol(name);
return rb_intern_str(name);
@@ -11494,7 +11927,7 @@ VALUE
rb_to_symbol(VALUE name)
{
if (SYMBOL_P(name)) {
- return name;
+ return name;
}
name = string_for_symbol(name);
return rb_str_intern(name);
@@ -11502,18 +11935,13 @@ rb_to_symbol(VALUE name)
/*
* call-seq:
- * Symbol.all_symbols => array
+ * Symbol.all_symbols -> array_of_symbols
*
- * Returns an array of all the symbols currently in Ruby's symbol
- * table.
+ * Returns an array of all symbols currently in Ruby's symbol table:
+ *
+ * Symbol.all_symbols.size # => 9334
+ * Symbol.all_symbols.take(3) # => [:!, :"\"", :"#"]
*
- * Symbol.all_symbols.size #=> 903
- * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
- * :chown, :EOFError, :$;, :String,
- * :LOCK_SH, :"setuid?", :$<,
- * :default_proc, :compact, :extend,
- * :Tms, :getwd, :$=, :ThreadGroup,
- * :wait2, :$>]
*/
static VALUE
@@ -11544,7 +11972,7 @@ rb_interned_str_cstr(const char *ptr)
VALUE
rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
{
- if (UNLIKELY(rb_enc_autoload_p(enc))) {
+ if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
rb_enc_autoload(enc);
}
@@ -11558,269 +11986,6 @@ rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc)
return rb_enc_interned_str(ptr, strlen(ptr), enc);
}
-/*
- * A String object holds and manipulates an arbitrary sequence of
- * bytes, typically representing characters. String objects may be created
- * using String::new or as literals.
- *
- * Because of aliasing issues, users of strings should be aware of the methods
- * that modify the contents of a String object. Typically,
- * methods with names ending in ``!'' modify their receiver, while those
- * without a ``!'' return a new String. However, there are
- * exceptions, such as String#[]=.
- *
- * == What's Here
- *
- * First, what's elsewhere. \Class \String:
- *
- * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
- * - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here].
- *
- * Here, class \String provides methods that are useful for:
- *
- * - {Creating a String}[#class-String-label-Methods+for+Creating+a+String]
- * - {Frozen/Unfrozen Strings}[#class-String-label-Methods+for+a+Frozen-2FUnfrozen+String]
- * - {Querying}[#class-String-label-Methods+for+Querying]
- * - {Comparing}[#class-String-label-Methods+for+Comparing]
- * - {Modifying a String}[#class-String-label-Methods+for+Modifying+a+String]
- * - {Converting to New String}[#class-String-label-Methods+for+Converting+to+New+String]
- * - {Converting to Non-String}[#class-String-label-Methods+for+Converting+to+Non--5CString]
- * - {Iterating}[#class-String-label-Methods+for+Iterating]
- *
- * === Methods for Creating a \String
- *
- * - ::new:: Returns a new string.
- * - ::try_convert:: Returns a new string created from a given object.
- *
- * === Methods for a Frozen/Unfrozen String
- *
- * - {#+string}[#method-i-2B-40]:: Returns a string that is not frozen:
- * +self+, if not frozen; +self.dup+ otherwise.
- * - {#-string}[#method-i-2D-40]:: Returns a string that is frozen:
- * +self+, if already frozen; +self.freeze+ otherwise.
- * - #freeze:: Freezes +self+, if not already frozen; returns +self+.
- *
- * === Methods for Querying
- *
- * _Counts_
- *
- * - #length, #size:: Returns the count of characters (not bytes).
- * - #empty?:: Returns +true+ if +self.length+ is zero; +false+ otherwise.
- * - #bytesize:: Returns the count of bytes.
- * - #count:: Returns the count of substrings matching given strings.
- *
- * _Substrings_
- *
- * - {#=~}[#method-i-3D~]:: Returns the index of the first substring that matches a given Regexp or other object;
- * returns +nil+ if no match is found.
- * - #index:: Returns the index of the _first_ occurrence of a given substring;
- * returns +nil+ if none found.
- * - #rindex:: Returns the index of the _last_ occurrence of a given substring;
- * returns +nil+ if none found.
- * - #include?:: Returns +true+ if the string contains a given substring; +false+ otherwise.
- * - #match:: Returns a MatchData object if the string matches a given Regexp; +nil+ otherwise.
- * - #match?:: Returns +true+ if the string matches a given Regexp; +false+ otherwise.
- * - #start_with?:: Returns +true+ if the string begins with any of the given substrings.
- * - #end_with?:: Returns +true+ if the string ends with any of the given substrings.
- *
- * _Encodings_
- *
- * - #encoding:: Returns the Encoding object that represents the encoding of the string.
- * - #unicode_normalized?:: Returns +true+ if the string is in Unicode normalized form; +false+ otherwise.
- * - #valid_encoding?:: Returns +true+ if the string contains only characters that are valid
- * for its encoding.
- * - #ascii_only?:: Returns +true+ if the string has only ASCII characters; +false+ otherwise.
- *
- * _Other_
- *
- * - #sum:: Returns a basic checksum for the string: the sum of each byte.
- * - #hash:: Returns the integer hash code.
- *
- * === Methods for Comparing
- *
- * - {#==, #===}[#method-i-3D-3D]:: Returns +true+ if a given other string has the same content as +self+.
- * - #eql?:: Returns +true+ if the content is the same as the given other string.
- * - {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1 as a given other string is smaller than, equal to, or larger than +self+.
- * - #casecmp:: Ignoring case, returns -1, 0, or 1 as a given
- * other string is smaller than, equal to, or larger than +self+.
- * - #casecmp?:: Returns +true+ if the string is equal to a given string after Unicode case folding;
- * +false+ otherwise.
- *
- * === Methods for Modifying a \String
- *
- * Each of these methods modifies +self+.
- *
- * _Insertion_
- *
- * - #insert:: Returns +self+ with a given string inserted at a given offset.
- * - #<<:: Returns +self+ concatenated with a given string or integer.
- *
- * _Substitution_
- *
- * - #sub!:: Replaces the first substring that matches a given pattern with a given replacement string;
- * returns +self+ if any changes, +nil+ otherwise.
- * - #gsub!:: Replaces each substring that matches a given pattern with a given replacement string;
- * returns +self+ if any changes, +nil+ otherwise.
- * - #succ!, #next!:: Returns +self+ modified to become its own successor.
- * - #replace:: Returns +self+ with its entire content replaced by a given string.
- * - #reverse!:: Returns +self+ with its characters in reverse order.
- * - #setbyte:: Sets the byte at a given integer offset to a given value; returns the argument.
- * - #tr!:: Replaces specified characters in +self+ with specified replacement characters;
- * returns +self+ if any changes, +nil+ otherwise.
- * - #tr_s!:: Replaces specified characters in +self+ with specified replacement characters,
- * removing duplicates from the substrings that were modified;
- * returns +self+ if any changes, +nil+ otherwise.
- *
- * _Casing_
- *
- * - #capitalize!:: Upcases the initial character and downcases all others;
- * returns +self+ if any changes, +nil+ otherwise.
- * - #downcase!:: Downcases all characters; returns +self+ if any changes, +nil+ otherwise.
- * - #upcase!:: Upcases all characters; returns +self+ if any changes, +nil+ otherwise.
- * - #swapcase!:: Upcases each downcase character and downcases each upcase character;
- * returns +self+ if any changes, +nil+ otherwise.
- *
- * _Encoding_
- *
- * - #encode!:: Returns +self+ with all characters transcoded from one given encoding into another.
- * - #unicode_normalize!:: Unicode-normalizes +self+; returns +self+.
- * - #scrub!:: Replaces each invalid byte with a given character; returns +self+.
- * - #force_encoding:: Changes the encoding to a given encoding; returns +self+.
- *
- * _Deletion_
- *
- * - #clear:: Removes all content, so that +self+ is empty; returns +self+.
- * - #slice!, #[]=:: Removes a substring determined by a given index, start/length, range, regexp, or substring.
- * - #squeeze!:: Removes contiguous duplicate characters; returns +self+.
- * - #delete!:: Removes characters as determined by the intersection of substring arguments.
- * - #lstrip!:: Removes leading whitespace; returns +self+ if any changes, +nil+ otherwise.
- * - #rstrip!:: Removes trailing whitespace; returns +self+ if any changes, +nil+ otherwise.
- * - #strip!:: Removes leading and trailing whitespace; returns +self+ if any changes, +nil+ otherwise.
- * - #chomp!:: Removes trailing record separator, if found; returns +self+ if any changes, +nil+ otherwise.
- * - #chop!:: Removes trailing whitespace if found, otherwise removes the last character;
- * returns +self+ if any changes, +nil+ otherwise.
- *
- * === Methods for Converting to New \String
- *
- * Each of these methods returns a new \String based on +self+,
- * often just a modified copy of +self+.
- *
- * _Extension_
- *
- * - #*:: Returns the concatenation of multiple copies of +self+,
- * - #+:: Returns the concatenation of +self+ and a given other string.
- * - #center:: Returns a copy of +self+ centered between pad substring.
- * - #concat:: Returns the concatenation of +self+ with given other strings.
- * - #prepend:: Returns the concatenation of a given other string with +self+.
- * - #ljust:: Returns a copy of +self+ of a given length, right-padded with a given other string.
- * - #rjust:: Returns a copy of +self+ of a given length, left-padded with a given other string.
- *
- * _Encoding_
- *
- * - #b:: Returns a copy of +self+ with ASCII-8BIT encoding.
- * - #scrub:: Returns a copy of +self+ with each invalid byte replaced with a given character.
- * - #unicode_normalize:: Returns a copy of +self+ with each character Unicode-normalized.
- * - #encode:: Returns a copy of +self+ with all characters transcoded from one given encoding into another.
- *
- * _Substitution_
- *
- * - #dump:: Returns a copy of +self with all non-printing characters replaced by \xHH notation
- * and all special characters escaped.
- * - #undump:: Returns a copy of +self with all <tt>\xNN</tt> notation replace by <tt>\uNNNN</tt> notation
- * and all escaped characters unescaped.
- * - #sub:: Returns a copy of +self+ with the first substring matching a given pattern
- * replaced with a given replacement string;.
- * - #gsub:: Returns a copy of +self+ with each substring that matches a given pattern
- * replaced with a given replacement string.
- * - #succ, #next:: Returns the string that is the successor to +self+.
- * - #reverse:: Returns a copy of +self+ with its characters in reverse order.
- * - #tr:: Returns a copy of +self+ with specified characters replaced with specified replacement characters.
- * - #tr_s:: Returns a copy of +self+ with specified characters replaced with specified replacement characters,
- * removing duplicates from the substrings that were modified.
- * - #%:: Returns the string resulting from formatting a given object into +self+
- *
- * _Casing_
- *
- * - #capitalize:: Returns a copy of +self+ with the first character upcased
- * and all other characters downcased.
- * - #downcase:: Returns a copy of +self+ with all characters downcased.
- * - #upcase:: Returns a copy of +self+ with all characters upcased.
- * - #swapcase:: Returns a copy of +self+ with all upcase characters downcased
- * and all downcase characters upcased.
- *
- * _Deletion_
- *
- * - #delete:: Returns a copy of +self+ with characters removed
- * - #delete_prefix:: Returns a copy of +self+ with a given prefix removed.
- * - #delete_suffix:: Returns a copy of +self+ with a given suffix removed.
- * - #lstrip:: Returns a copy of +self+ with leading whitespace removed.
- * - #rstrip:: Returns a copy of +self+ with trailing whitespace removed.
- * - #strip:: Returns a copy of +self+ with leading and trailing whitespace removed.
- * - #chomp:: Returns a copy of +self+ with a trailing record separator removed, if found.
- * - #chop:: Returns a copy of +self+ with trailing whitespace or the last character removed.
- * - #squeeze:: Returns a copy of +self+ with contiguous duplicate characters removed.
- * - #[], #slice:: Returns a substring determined by a given index, start/length, or range, or string.
- * - #byteslice:: Returns a substring determined by a given index, start/length, or range.
- * - #chr:: Returns the first character.
- *
- * _Duplication_
- *
- * - #to_s, $to_str:: If +self+ is a subclass of \String, returns +self+ copied into a \String;
- * otherwise, returns +self+.
- *
- * === Methods for Converting to Non-\String
- *
- * Each of these methods converts the contents of +self+ to a non-\String.
- *
- * <em>Characters, Bytes, and Clusters</em>
- *
- * - #bytes:: Returns an array of the bytes in +self+.
- * - #chars:: Returns an array of the characters in +self+.
- * - #codepoints:: Returns an array of the integer ordinals in +self+.
- * - #getbyte:: Returns an integer byte as determined by a given index.
- * - #grapheme_clusters:: Returns an array of the grapheme clusters in +self+.
- *
- * _Splitting_
- *
- * - #lines:: Returns an array of the lines in +self+, as determined by a given record separator.
- * - #partition:: Returns a 3-element array determined by the first substring that matches
- * a given substring or regexp,
- * - #rpartition:: Returns a 3-element array determined by the last substring that matches
- * a given substring or regexp,
- * - #split:: Returns an array of substrings determined by a given delimiter -- regexp or string --
- * or, if a block given, passes those substrings to the block.
- *
- * _Matching_
- *
- * - #scan:: Returns an array of substrings matching a given regexp or string, or,
- * if a block given, passes each matching substring to the block.
- * - #unpack:: Returns an array of substrings extracted from +self+ according to a given format.
- * - #unpack1:: Returns the first substring extracted from +self+ according to a given format.
- *
- * _Numerics_
- *
- * - #hex:: Returns the integer value of the leading characters, interpreted as hexadecimal digits.
- * - #oct:: Returns the integer value of the leading characters, interpreted as octal digits.
- * - #ord:: Returns the integer ordinal of the first character in +self+.
- * - #to_i:: Returns the integer value of leading characters, interpreted as an integer.
- * - #to_f:: Returns the floating-point value of leading characters, interpreted as a floating-point number.
- *
- * <em>Strings and Symbols</em>
- *
- * - #inspect:: Returns copy of +self+, enclosed in double-quotes, with special characters escaped.
- * - #to_sym, #intern:: Returns the symbol corresponding to +self+.
- *
- * === Methods for Iterating
- *
- * - #each_byte:: Calls the given block with each successive byte in +self+.
- * - #each_char:: Calls the given block with each successive character in +self+.
- * - #each_codepoint:: Calls the given block with each successive integer codepoint in +self+.
- * - #each_grapheme_cluster:: Calls the given block with each successive grapheme cluster in +self+.
- * - #each_line:: Calls the given block with each successive line in +self+,
- * as determined by a given record separator.
- * - #upto:: Calls the given block with each string value returned by successive calls to #succ.
- */
-
void
Init_String(void)
{
@@ -11858,18 +12023,22 @@ Init_String(void)
rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
rb_define_method(rb_cString, "upto", rb_str_upto, -1);
rb_define_method(rb_cString, "index", rb_str_index_m, -1);
+ rb_define_method(rb_cString, "byteindex", rb_str_byteindex_m, -1);
rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1);
+ rb_define_method(rb_cString, "byterindex", rb_str_byterindex_m, -1);
rb_define_method(rb_cString, "replace", rb_str_replace, 1);
rb_define_method(rb_cString, "clear", rb_str_clear, 0);
rb_define_method(rb_cString, "chr", rb_str_chr, 0);
rb_define_method(rb_cString, "getbyte", rb_str_getbyte, 1);
rb_define_method(rb_cString, "setbyte", rb_str_setbyte, 2);
rb_define_method(rb_cString, "byteslice", rb_str_byteslice, -1);
+ rb_define_method(rb_cString, "bytesplice", rb_str_bytesplice, -1);
rb_define_method(rb_cString, "scrub", str_scrub, -1);
rb_define_method(rb_cString, "scrub!", str_scrub_bang, -1);
rb_define_method(rb_cString, "freeze", rb_str_freeze, 0);
rb_define_method(rb_cString, "+@", str_uplus, 0);
rb_define_method(rb_cString, "-@", str_uminus, 0);
+ rb_define_alias(rb_cString, "dedup", "-@");
rb_define_method(rb_cString, "to_i", rb_str_to_i, -1);
rb_define_method(rb_cString, "to_f", rb_str_to_f, 0);
@@ -11998,10 +12167,8 @@ 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);
+ rb_define_method(rb_cSymbol, "name", rb_sym2str, 0); /* in symbol.c */
+ rb_define_method(rb_cSymbol, "to_proc", rb_sym_to_proc, 0); /* in proc.c */
rb_define_method(rb_cSymbol, "succ", sym_succ, 0);
rb_define_method(rb_cSymbol, "next", sym_succ, 0);
diff --git a/string.rb b/string.rb
new file mode 100644
index 0000000000..b410e09395
--- /dev/null
+++ b/string.rb
@@ -0,0 +1,552 @@
+# A \String object has an arbitrary sequence of bytes,
+# typically representing text or binary data.
+# A \String object may be created using String::new or as literals.
+#
+# String objects differ from Symbol objects in that Symbol objects are
+# designed to be used as identifiers, instead of text or data.
+#
+# You can create a \String object explicitly with:
+#
+# - A {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals].
+# - A {heredoc literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals].
+#
+# You can convert certain objects to Strings with:
+#
+# - \Method #String.
+#
+# Some \String methods modify +self+.
+# Typically, a method whose name ends with <tt>!</tt> modifies +self+
+# and returns +self+;
+# often a similarly named method (without the <tt>!</tt>)
+# returns a new string.
+#
+# In general, if there exist both bang and non-bang version of method,
+# the bang! mutates and the non-bang! does not.
+# However, a method without a bang can also mutate, such as String#replace.
+#
+# == Substitution Methods
+#
+# These methods perform substitutions:
+#
+# - String#sub: One substitution (or none); returns a new string.
+# - String#sub!: One substitution (or none); returns +self+.
+# - String#gsub: Zero or more substitutions; returns a new string.
+# - String#gsub!: Zero or more substitutions; returns +self+.
+#
+# Each of these methods takes:
+#
+# - A first argument, +pattern+ (string or regexp),
+# that specifies the substring(s) to be replaced.
+#
+# - Either of these:
+#
+# - A second argument, +replacement+ (string or hash),
+# that determines the replacing string.
+# - A block that will determine the replacing string.
+#
+# The examples in this section mostly use methods String#sub and String#gsub;
+# the principles illustrated apply to all four substitution methods.
+#
+# <b>Argument +pattern+</b>
+#
+# Argument +pattern+ is commonly a regular expression:
+#
+# s = 'hello'
+# s.sub(/[aeiou]/, '*')# => "h*llo"
+# s.gsub(/[aeiou]/, '*') # => "h*ll*"
+# s.gsub(/[aeiou]/, '')# => "hll"
+# s.sub(/ell/, 'al') # => "halo"
+# s.gsub(/xyzzy/, '*') # => "hello"
+# 'THX1138'.gsub(/\d+/, '00') # => "THX00"
+#
+# When +pattern+ is a string, all its characters are treated
+# as ordinary characters (not as regexp special characters):
+#
+# 'THX1138'.gsub('\d+', '00') # => "THX1138"
+#
+# <b>\String +replacement+</b>
+#
+# If +replacement+ is a string, that string will determine
+# the replacing string that is to be substituted for the matched text.
+#
+# Each of the examples above uses a simple string as the replacing string.
+#
+# \String +replacement+ may contain back-references to the pattern's captures:
+#
+# - <tt>\n</tt> (_n_ a non-negative integer) refers to <tt>$n</tt>.
+# - <tt>\k<name></tt> refers to the named capture +name+.
+#
+# See rdoc-ref:regexp.rdoc for details.
+#
+# Note that within the string +replacement+, a character combination
+# such as <tt>$&</tt> is treated as ordinary text, and not as
+# a special match variable.
+# However, you may refer to some special match variables using these
+# combinations:
+#
+# - <tt>\&</tt> and <tt>\0</tt> correspond to <tt>$&</tt>,
+# which contains the complete matched text.
+# - <tt>\'</tt> corresponds to <tt>$'</tt>,
+# which contains string after match.
+# - <tt>\`</tt> corresponds to <tt>$`</tt>,
+# which contains string before match.
+# - <tt>\+</tt> corresponds to <tt>$+</tt>,
+# which contains last capture group.
+#
+# See rdoc-ref:regexp.rdoc for details.
+#
+# Note that <tt>\\\\</tt> is interpreted as an escape, i.e., a single backslash.
+#
+# Note also that a string literal consumes backslashes.
+# See {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals] for details about string literals.
+#
+# A back-reference is typically preceded by an additional backslash.
+# For example, if you want to write a back-reference <tt>\&</tt> in
+# +replacement+ with a double-quoted string literal, you need to write
+# <tt>"..\\\\&.."</tt>.
+#
+# If you want to write a non-back-reference string <tt>\&</tt> in
+# +replacement+, you need first to escape the backslash to prevent
+# this method from interpreting it as a back-reference, and then you
+# need to escape the backslashes again to prevent a string literal from
+# consuming them: <tt>"..\\\\\\\\&.."</tt>.
+#
+# You may want to use the block form to avoid a lot of backslashes.
+#
+# <b>\Hash +replacement+</b>
+#
+# If argument +replacement+ is a hash, and +pattern+ matches one of its keys,
+# the replacing string is the value for that key:
+#
+# h = {'foo' => 'bar', 'baz' => 'bat'}
+# 'food'.sub('foo', h) # => "bard"
+#
+# Note that a symbol key does not match:
+#
+# h = {foo: 'bar', baz: 'bat'}
+# 'food'.sub('foo', h) # => "d"
+#
+# <b>Block</b>
+#
+# In the block form, the current match string is passed to the block;
+# the block's return value becomes the replacing string:
+#
+# s = '@'
+# '1234'.gsub(/\d/) {|match| s.succ! } # => "ABCD"
+#
+# Special match variables such as <tt>$1</tt>, <tt>$2</tt>, <tt>$`</tt>,
+# <tt>$&</tt>, and <tt>$'</tt> are set appropriately.
+#
+# == Whitespace in Strings
+#
+# In class \String, _whitespace_ is defined as a contiguous sequence of characters
+# consisting of any mixture of the following:
+#
+# - NL (null): <tt>"\x00"</tt>, <tt>"\u0000"</tt>.
+# - HT (horizontal tab): <tt>"\x09"</tt>, <tt>"\t"</tt>.
+# - LF (line feed): <tt>"\x0a"</tt>, <tt>"\n"</tt>.
+# - VT (vertical tab): <tt>"\x0b"</tt>, <tt>"\v"</tt>.
+# - FF (form feed): <tt>"\x0c"</tt>, <tt>"\f"</tt>.
+# - CR (carriage return): <tt>"\x0d"</tt>, <tt>"\r"</tt>.
+# - SP (space): <tt>"\x20"</tt>, <tt>" "</tt>.
+#
+#
+# Whitespace is relevant for these methods:
+#
+# - #lstrip, #lstrip!: strip leading whitespace.
+# - #rstrip, #rstrip!: strip trailing whitespace.
+# - #strip, #strip!: strip leading and trailing whitespace.
+#
+# == \String Slices
+#
+# A _slice_ of a string is a substring that is selected by certain criteria.
+#
+# These instance methods make use of slicing:
+#
+# - String#[] (also aliased as String#slice) returns a slice copied from +self+.
+# - String#[]= returns a copy of +self+ with a slice replaced.
+# - String#slice! returns +self+ with a slice removed.
+#
+# Each of the above methods takes arguments that determine the slice
+# to be copied or replaced.
+#
+# The arguments have several forms.
+# For string +string+, the forms are:
+#
+# - <tt>string[index]</tt>.
+# - <tt>string[start, length]</tt>.
+# - <tt>string[range]</tt>.
+# - <tt>string[regexp, capture = 0]</tt>.
+# - <tt>string[substring]</tt>.
+#
+# <b><tt>string[index]</tt></b>
+#
+# When non-negative integer argument +index+ is given,
+# the slice is the 1-character substring found in +self+ at character offset +index+:
+#
+# 'bar'[0] # => "b"
+# 'bar'[2] # => "r"
+# 'bar'[20] # => nil
+# 'тест'[2] # => "с"
+# 'こんにちは'[4] # => "は"
+#
+# When negative integer +index+ is given,
+# the slice begins at the offset given by counting backward from the end of +self+:
+#
+# 'bar'[-3] # => "b"
+# 'bar'[-1] # => "r"
+# 'bar'[-20] # => nil
+#
+# <b><tt>string[start, length]</tt></b>
+#
+# When non-negative integer arguments +start+ and +length+ are given,
+# the slice begins at character offset +start+, if it exists,
+# and continues for +length+ characters, if available:
+#
+# 'foo'[0, 2] # => "fo"
+# 'тест'[1, 2] # => "ес"
+# 'こんにちは'[2, 2] # => "にち"
+# # Zero length.
+# 'foo'[2, 0] # => ""
+# # Length not entirely available.
+# 'foo'[1, 200] # => "oo"
+# # Start out of range.
+# 'foo'[4, 2] # => nil
+#
+# Special case: if +start+ is equal to the length of +self+,
+# the slice is a new empty string:
+#
+# 'foo'[3, 2] # => ""
+# 'foo'[3, 200] # => ""
+#
+# When negative +start+ and non-negative +length+ are given,
+# the slice beginning is determined by counting backward from the end of +self+,
+# and the slice continues for +length+ characters, if available:
+#
+# 'foo'[-2, 2] # => "oo"
+# 'foo'[-2, 200] # => "oo"
+# # Start out of range.
+# 'foo'[-4, 2] # => nil
+#
+# When negative +length+ is given, there is no slice:
+#
+# 'foo'[1, -1] # => nil
+# 'foo'[-2, -1] # => nil
+#
+# <b><tt>string[range]</tt></b>
+#
+# When Range argument +range+ is given,
+# creates a substring of +string+ using the indices in +range+.
+# The slice is then determined as above:
+#
+# 'foo'[0..1] # => "fo"
+# 'foo'[0, 2] # => "fo"
+#
+# 'foo'[2...2] # => ""
+# 'foo'[2, 0] # => ""
+#
+# 'foo'[1..200] # => "oo"
+# 'foo'[1, 200] # => "oo"
+#
+# 'foo'[4..5] # => nil
+# 'foo'[4, 2] # => nil
+#
+# 'foo'[-4..-3] # => nil
+# 'foo'[-4, 2] # => nil
+#
+# 'foo'[3..4] # => ""
+# 'foo'[3, 2] # => ""
+#
+# 'foo'[-2..-1] # => "oo"
+# 'foo'[-2, 2] # => "oo"
+#
+# 'foo'[-2..197] # => "oo"
+# 'foo'[-2, 200] # => "oo"
+#
+# <b><tt>string[regexp, capture = 0]</tt></b>
+#
+# When the \Regexp argument +regexp+ is given,
+# and the +capture+ argument is <tt>0</tt>,
+# the slice is the first matching substring found in +self+:
+#
+# 'foo'[/o/] # => "o"
+# 'foo'[/x/] # => nil
+# s = 'hello there'
+# s[/[aeiou](.)\1/] # => "ell"
+# s[/[aeiou](.)\1/, 0] # => "ell"
+#
+# If argument +capture+ is given and not <tt>0</tt>,
+# it should be either an capture group index (integer)
+# or a capture group name (string or symbol);
+# the slice is the specified capture (see Regexp@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, there is no slice.
+# If an invalid capture group name is given, +IndexError+ is raised.
+#
+# <b><tt>string[substring]</tt></b>
+#
+# When the single \String argument +substring+ is given,
+# returns the substring from +self+ if found, otherwise +nil+:
+#
+# 'foo'['oo'] # => "oo"
+# 'foo'['xx'] # => nil
+#
+# == What's Here
+#
+# First, what's elsewhere. \Class \String:
+#
+# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+# - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
+#
+# Here, class \String provides methods that are useful for:
+#
+# - {Creating a String}[rdoc-ref:String@Methods+for+Creating+a+String]
+# - {Frozen/Unfrozen Strings}[rdoc-ref:String@Methods+for+a+Frozen-2FUnfrozen+String]
+# - {Querying}[rdoc-ref:String@Methods+for+Querying]
+# - {Comparing}[rdoc-ref:String@Methods+for+Comparing]
+# - {Modifying a String}[rdoc-ref:String@Methods+for+Modifying+a+String]
+# - {Converting to New String}[rdoc-ref:String@Methods+for+Converting+to+New+String]
+# - {Converting to Non-String}[rdoc-ref:String@Methods+for+Converting+to+Non--5CString]
+# - {Iterating}[rdoc-ref:String@Methods+for+Iterating]
+#
+# === Methods for Creating a \String
+#
+# - ::new: Returns a new string.
+# - ::try_convert: Returns a new string created from a given object.
+#
+# === Methods for a Frozen/Unfrozen String
+#
+# - #+@: Returns a string that is not frozen: +self+, if not frozen;
+# +self.dup+ otherwise.
+# - #-@: Returns a string that is frozen: +self+, if already frozen;
+# +self.freeze+ otherwise.
+# - #freeze: Freezes +self+, if not already frozen; returns +self+.
+#
+# === Methods for Querying
+#
+# _Counts_
+#
+# - #length, #size: Returns the count of characters (not bytes).
+# - #empty?: Returns +true+ if +self.length+ is zero; +false+ otherwise.
+# - #bytesize: Returns the count of bytes.
+# - #count: Returns the count of substrings matching given strings.
+#
+# _Substrings_
+#
+# - #=~: Returns the index of the first substring that matches a given
+# Regexp or other object; returns +nil+ if no match is found.
+# - #index: Returns the index of the _first_ occurrence of a given substring;
+# returns +nil+ if none found.
+# - #rindex: Returns the index of the _last_ occurrence of a given substring;
+# returns +nil+ if none found.
+# - #include?: Returns +true+ if the string contains a given substring; +false+ otherwise.
+# - #match: Returns a MatchData object if the string matches a given Regexp; +nil+ otherwise.
+# - #match?: Returns +true+ if the string matches a given Regexp; +false+ otherwise.
+# - #start_with?: Returns +true+ if the string begins with any of the given substrings.
+# - #end_with?: Returns +true+ if the string ends with any of the given substrings.
+#
+# _Encodings_
+#
+# - #encoding\: Returns the Encoding object that represents the encoding of the string.
+# - #unicode_normalized?: Returns +true+ if the string is in Unicode normalized form; +false+ otherwise.
+# - #valid_encoding?: Returns +true+ if the string contains only characters that are valid
+# for its encoding.
+# - #ascii_only?: Returns +true+ if the string has only ASCII characters; +false+ otherwise.
+#
+# _Other_
+#
+# - #sum: Returns a basic checksum for the string: the sum of each byte.
+# - #hash: Returns the integer hash code.
+#
+# === Methods for Comparing
+#
+# - #==, #===: Returns +true+ if a given other string has the same content as +self+.
+# - #eql?: Returns +true+ if the content is the same as the given other string.
+# - #<=>: Returns -1, 0, or 1 as a given other string is smaller than,
+# equal to, or larger than +self+.
+# - #casecmp: Ignoring case, returns -1, 0, or 1 as a given
+# other string is smaller than, equal to, or larger than +self+.
+# - #casecmp?: Returns +true+ if the string is equal to a given string after Unicode case folding;
+# +false+ otherwise.
+#
+# === Methods for Modifying a \String
+#
+# Each of these methods modifies +self+.
+#
+# _Insertion_
+#
+# - #insert: Returns +self+ with a given string inserted at a given offset.
+# - #<<: Returns +self+ concatenated with a given string or integer.
+#
+# _Substitution_
+#
+# - #sub!: Replaces the first substring that matches a given pattern with a given replacement string;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #gsub!: Replaces each substring that matches a given pattern with a given replacement string;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #succ!, #next!: Returns +self+ modified to become its own successor.
+# - #replace: Returns +self+ with its entire content replaced by a given string.
+# - #reverse!: Returns +self+ with its characters in reverse order.
+# - #setbyte: Sets the byte at a given integer offset to a given value; returns the argument.
+# - #tr!: Replaces specified characters in +self+ with specified replacement characters;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #tr_s!: Replaces specified characters in +self+ with specified replacement characters,
+# removing duplicates from the substrings that were modified;
+# returns +self+ if any changes, +nil+ otherwise.
+#
+# _Casing_
+#
+# - #capitalize!: Upcases the initial character and downcases all others;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #downcase!: Downcases all characters; returns +self+ if any changes, +nil+ otherwise.
+# - #upcase!: Upcases all characters; returns +self+ if any changes, +nil+ otherwise.
+# - #swapcase!: Upcases each downcase character and downcases each upcase character;
+# returns +self+ if any changes, +nil+ otherwise.
+#
+# _Encoding_
+#
+# - #encode!: Returns +self+ with all characters transcoded from one given encoding into another.
+# - #unicode_normalize!: Unicode-normalizes +self+; returns +self+.
+# - #scrub!: Replaces each invalid byte with a given character; returns +self+.
+# - #force_encoding: Changes the encoding to a given encoding; returns +self+.
+#
+# _Deletion_
+#
+# - #clear: Removes all content, so that +self+ is empty; returns +self+.
+# - #slice!, #[]=: Removes a substring determined by a given index, start/length, range, regexp, or substring.
+# - #squeeze!: Removes contiguous duplicate characters; returns +self+.
+# - #delete!: Removes characters as determined by the intersection of substring arguments.
+# - #lstrip!: Removes leading whitespace; returns +self+ if any changes, +nil+ otherwise.
+# - #rstrip!: Removes trailing whitespace; returns +self+ if any changes, +nil+ otherwise.
+# - #strip!: Removes leading and trailing whitespace; returns +self+ if any changes, +nil+ otherwise.
+# - #chomp!: Removes trailing record separator, if found; returns +self+ if any changes, +nil+ otherwise.
+# - #chop!: Removes trailing newline characters if found; otherwise removes the last character;
+# returns +self+ if any changes, +nil+ otherwise.
+#
+# === Methods for Converting to New \String
+#
+# Each of these methods returns a new \String based on +self+,
+# often just a modified copy of +self+.
+#
+# _Extension_
+#
+# - #*: Returns the concatenation of multiple copies of +self+,
+# - #+: Returns the concatenation of +self+ and a given other string.
+# - #center: Returns a copy of +self+ centered between pad substring.
+# - #concat: Returns the concatenation of +self+ with given other strings.
+# - #prepend: Returns the concatenation of a given other string with +self+.
+# - #ljust: Returns a copy of +self+ of a given length, right-padded with a given other string.
+# - #rjust: Returns a copy of +self+ of a given length, left-padded with a given other string.
+#
+# _Encoding_
+#
+# - #b: Returns a copy of +self+ with ASCII-8BIT encoding.
+# - #scrub: Returns a copy of +self+ with each invalid byte replaced with a given character.
+# - #unicode_normalize: Returns a copy of +self+ with each character Unicode-normalized.
+# - #encode: Returns a copy of +self+ with all characters transcoded from one given encoding into another.
+#
+# _Substitution_
+#
+# - #dump: Returns a copy of +self+ with all non-printing characters replaced by \xHH notation
+# and all special characters escaped.
+# - #undump: Returns a copy of +self+ with all <tt>\xNN</tt> notation replace by <tt>\uNNNN</tt> notation
+# and all escaped characters unescaped.
+# - #sub: Returns a copy of +self+ with the first substring matching a given pattern
+# replaced with a given replacement string;.
+# - #gsub: Returns a copy of +self+ with each substring that matches a given pattern
+# replaced with a given replacement string.
+# - #succ, #next: Returns the string that is the successor to +self+.
+# - #reverse: Returns a copy of +self+ with its characters in reverse order.
+# - #tr: Returns a copy of +self+ with specified characters replaced with specified replacement characters.
+# - #tr_s: Returns a copy of +self+ with specified characters replaced with
+# specified replacement characters,
+# removing duplicates from the substrings that were modified.
+# - #%: Returns the string resulting from formatting a given object into +self+
+#
+# _Casing_
+#
+# - #capitalize: Returns a copy of +self+ with the first character upcased
+# and all other characters downcased.
+# - #downcase: Returns a copy of +self+ with all characters downcased.
+# - #upcase: Returns a copy of +self+ with all characters upcased.
+# - #swapcase: Returns a copy of +self+ with all upcase characters downcased
+# and all downcase characters upcased.
+#
+# _Deletion_
+#
+# - #delete: Returns a copy of +self+ with characters removed
+# - #delete_prefix: Returns a copy of +self+ with a given prefix removed.
+# - #delete_suffix: Returns a copy of +self+ with a given suffix removed.
+# - #lstrip: Returns a copy of +self+ with leading whitespace removed.
+# - #rstrip: Returns a copy of +self+ with trailing whitespace removed.
+# - #strip: Returns a copy of +self+ with leading and trailing whitespace removed.
+# - #chomp: Returns a copy of +self+ with a trailing record separator removed, if found.
+# - #chop: Returns a copy of +self+ with trailing newline characters or the last character removed.
+# - #squeeze: Returns a copy of +self+ with contiguous duplicate characters removed.
+# - #[], #slice: Returns a substring determined by a given index, start/length, or range, or string.
+# - #byteslice: Returns a substring determined by a given index, start/length, or range.
+# - #chr: Returns the first character.
+#
+# _Duplication_
+#
+# - #to_s, $to_str: If +self+ is a subclass of \String, returns +self+ copied into a \String;
+# otherwise, returns +self+.
+#
+# === Methods for Converting to Non-\String
+#
+# Each of these methods converts the contents of +self+ to a non-\String.
+#
+# <em>Characters, Bytes, and Clusters</em>
+#
+# - #bytes: Returns an array of the bytes in +self+.
+# - #chars: Returns an array of the characters in +self+.
+# - #codepoints: Returns an array of the integer ordinals in +self+.
+# - #getbyte: Returns an integer byte as determined by a given index.
+# - #grapheme_clusters: Returns an array of the grapheme clusters in +self+.
+#
+# _Splitting_
+#
+# - #lines: Returns an array of the lines in +self+, as determined by a given record separator.
+# - #partition: Returns a 3-element array determined by the first substring that matches
+# a given substring or regexp,
+# - #rpartition: Returns a 3-element array determined by the last substring that matches
+# a given substring or regexp,
+# - #split: Returns an array of substrings determined by a given delimiter -- regexp or string --
+# or, if a block given, passes those substrings to the block.
+#
+# _Matching_
+#
+# - #scan: Returns an array of substrings matching a given regexp or string, or,
+# if a block given, passes each matching substring to the block.
+# - #unpack: Returns an array of substrings extracted from +self+ according to a given format.
+# - #unpack1: Returns the first substring extracted from +self+ according to a given format.
+#
+# _Numerics_
+#
+# - #hex: Returns the integer value of the leading characters, interpreted as hexadecimal digits.
+# - #oct: Returns the integer value of the leading characters, interpreted as octal digits.
+# - #ord: Returns the integer ordinal of the first character in +self+.
+# - #to_i: Returns the integer value of leading characters, interpreted as an integer.
+# - #to_f: Returns the floating-point value of leading characters, interpreted as a floating-point number.
+#
+# <em>Strings and Symbols</em>
+#
+# - #inspect: Returns copy of +self+, enclosed in double-quotes, with special characters escaped.
+# - #to_sym, #intern: Returns the symbol corresponding to +self+.
+#
+# === Methods for Iterating
+#
+# - #each_byte: Calls the given block with each successive byte in +self+.
+# - #each_char: Calls the given block with each successive character in +self+.
+# - #each_codepoint: Calls the given block with each successive integer codepoint in +self+.
+# - #each_grapheme_cluster: Calls the given block with each successive grapheme cluster in +self+.
+# - #each_line: Calls the given block with each successive line in +self+,
+# as determined by a given record separator.
+# - #upto: Calls the given block with each string value returned by successive calls to #succ.
+
+class String; end
diff --git a/struct.c b/struct.c
index 9207c6291d..8b7fea7f95 100644
--- a/struct.c
+++ b/struct.c
@@ -28,10 +28,11 @@ enum {
AREF_HASH_THRESHOLD = 10
};
-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);
-
+/* Note: Data is a stricter version of the Struct: no attr writers & no
+ hash-alike/array-alike behavior. It shares most of the implementation
+ on the C level, but is unrelated on the Ruby level. */
VALUE rb_cStruct;
+static VALUE rb_cData;
static ID id_members, id_back_members, id_keyword_init;
static VALUE struct_alloc(VALUE);
@@ -43,16 +44,17 @@ struct_ivar_get(VALUE c, ID id)
VALUE ivar = rb_attr_get(c, id);
if (!NIL_P(ivar))
- return ivar;
+ return ivar;
for (;;) {
- c = RCLASS_SUPER(c);
- if (c == 0 || c == rb_cStruct)
- return Qnil;
- ivar = rb_attr_get(c, id);
- if (!NIL_P(ivar)) {
- return rb_ivar_set(orig, id, ivar);
- }
+ c = rb_class_superclass(c);
+ if (c == rb_cStruct || c == rb_cData || !RTEST(c))
+ return Qnil;
+ RUBY_ASSERT(RB_TYPE_P(c, T_CLASS));
+ ivar = rb_attr_get(c, id);
+ if (!NIL_P(ivar)) {
+ return rb_ivar_set(orig, id, ivar);
+ }
}
}
@@ -68,10 +70,10 @@ rb_struct_s_members(VALUE klass)
VALUE members = struct_ivar_get(klass, id_members);
if (NIL_P(members)) {
- rb_raise(rb_eTypeError, "uninitialized struct");
+ rb_raise(rb_eTypeError, "uninitialized struct");
}
if (!RB_TYPE_P(members, T_ARRAY)) {
- rb_raise(rb_eTypeError, "corrupted struct");
+ rb_raise(rb_eTypeError, "corrupted struct");
}
return members;
}
@@ -82,8 +84,8 @@ rb_struct_members(VALUE s)
VALUE members = rb_struct_s_members(rb_obj_class(s));
if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
- rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
- RARRAY_LEN(members), RSTRUCT_LEN(s));
+ rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
+ RARRAY_LEN(members), RSTRUCT_LEN(s));
}
return members;
}
@@ -109,33 +111,33 @@ struct_set_members(VALUE klass, VALUE /* frozen hidden array */ members)
const long members_length = RARRAY_LEN(members);
if (members_length <= AREF_HASH_THRESHOLD) {
- back = members;
+ back = members;
}
else {
- long i, j, mask = 64;
- VALUE name;
+ long i, j, mask = 64;
+ VALUE name;
- while (mask < members_length * AREF_HASH_UNIT) mask *= 2;
+ while (mask < members_length * AREF_HASH_UNIT) mask *= 2;
- back = rb_ary_tmp_new(mask + 1);
- rb_ary_store(back, mask, INT2FIX(members_length));
- mask -= 2; /* mask = (2**k-1)*2 */
+ back = rb_ary_hidden_new(mask + 1);
+ rb_ary_store(back, mask, INT2FIX(members_length));
+ mask -= 2; /* mask = (2**k-1)*2 */
- for (i=0; i < members_length; i++) {
- name = RARRAY_AREF(members, i);
+ for (i=0; i < members_length; i++) {
+ name = RARRAY_AREF(members, i);
- j = struct_member_pos_ideal(name, mask);
+ j = struct_member_pos_ideal(name, mask);
- for (;;) {
- if (!RTEST(RARRAY_AREF(back, j))) {
- rb_ary_store(back, j, name);
- rb_ary_store(back, j + 1, INT2FIX(i));
- break;
- }
- j = struct_member_pos_probe(j, mask);
- }
- }
- OBJ_FREEZE_RAW(back);
+ for (;;) {
+ if (!RTEST(RARRAY_AREF(back, j))) {
+ rb_ary_store(back, j, name);
+ rb_ary_store(back, j + 1, INT2FIX(i));
+ break;
+ }
+ j = struct_member_pos_probe(j, mask);
+ }
+ }
+ OBJ_FREEZE_RAW(back);
}
rb_ivar_set(klass, id_members, members);
rb_ivar_set(klass, id_back_members, back);
@@ -150,30 +152,30 @@ struct_member_pos(VALUE s, VALUE name)
long j, mask;
if (UNLIKELY(NIL_P(back))) {
- rb_raise(rb_eTypeError, "uninitialized struct");
+ rb_raise(rb_eTypeError, "uninitialized struct");
}
if (UNLIKELY(!RB_TYPE_P(back, T_ARRAY))) {
- rb_raise(rb_eTypeError, "corrupted struct");
+ rb_raise(rb_eTypeError, "corrupted struct");
}
mask = RARRAY_LEN(back);
if (mask <= AREF_HASH_THRESHOLD) {
- if (UNLIKELY(RSTRUCT_LEN(s) != mask)) {
- rb_raise(rb_eTypeError,
- "struct size differs (%ld required %ld given)",
- mask, RSTRUCT_LEN(s));
- }
- for (j = 0; j < mask; j++) {
+ if (UNLIKELY(RSTRUCT_LEN(s) != mask)) {
+ rb_raise(rb_eTypeError,
+ "struct size differs (%ld required %ld given)",
+ mask, RSTRUCT_LEN(s));
+ }
+ for (j = 0; j < mask; j++) {
if (RARRAY_AREF(back, j) == name)
- return (int)j;
- }
- return -1;
+ return (int)j;
+ }
+ return -1;
}
if (UNLIKELY(RSTRUCT_LEN(s) != FIX2INT(RARRAY_AREF(back, mask-1)))) {
- rb_raise(rb_eTypeError, "struct size differs (%d required %ld given)",
- FIX2INT(RARRAY_AREF(back, mask-1)), RSTRUCT_LEN(s));
+ rb_raise(rb_eTypeError, "struct size differs (%d required %ld given)",
+ FIX2INT(RARRAY_AREF(back, mask-1)), RSTRUCT_LEN(s));
}
mask -= 3;
@@ -184,12 +186,23 @@ struct_member_pos(VALUE s, VALUE name)
if (e == name)
return FIX2INT(RARRAY_AREF(back, j + 1));
if (!RTEST(e)) {
- return -1;
- }
- j = struct_member_pos_probe(j, mask);
+ return -1;
+ }
+ j = struct_member_pos_probe(j, mask);
}
}
+/*
+ * call-seq:
+ * StructClass::members -> array_of_symbols
+ *
+ * Returns the member names of the Struct descendant as an array:
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * Customer.members # => [:name, :address, :zip]
+ *
+ */
+
static VALUE
rb_struct_s_members_m(VALUE klass)
{
@@ -200,13 +213,14 @@ rb_struct_s_members_m(VALUE klass)
/*
* call-seq:
- * struct.members -> array
+ * members -> array_of_symbols
*
- * Returns the struct members as an array of symbols:
+ * Returns the member names from +self+ as an array:
*
* Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.members #=> [:name, :address, :zip]
+ * Customer.new.members # => [:name, :address, :zip]
+ *
+ * Related: #to_a.
*/
static VALUE
@@ -221,39 +235,13 @@ rb_struct_getmember(VALUE obj, ID id)
VALUE slot = ID2SYM(id);
int i = struct_member_pos(obj, slot);
if (i != -1) {
- return RSTRUCT_GET(obj, i);
+ return RSTRUCT_GET(obj, i);
}
rb_name_err_raise("`%1$s' is not a struct member", obj, ID2SYM(id));
UNREACHABLE_RETURN(Qnil);
}
-static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
-static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
-static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
-static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
-static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
-static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
-static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
-static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
-static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
-static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
-
-#define N_REF_FUNC numberof(ref_func)
-
-static VALUE (*const ref_func[])(VALUE) = {
- rb_struct_ref0,
- rb_struct_ref1,
- rb_struct_ref2,
- rb_struct_ref3,
- rb_struct_ref4,
- rb_struct_ref5,
- rb_struct_ref6,
- rb_struct_ref7,
- rb_struct_ref8,
- rb_struct_ref9,
-};
-
static void
rb_struct_modify(VALUE s)
{
@@ -278,63 +266,29 @@ new_struct(VALUE name, VALUE super)
ID id;
name = rb_str_to_str(name);
if (!rb_is_const_name(name)) {
- rb_name_err_raise("identifier %1$s needs to be constant",
- super, name);
+ rb_name_err_raise("identifier %1$s needs to be constant",
+ super, name);
}
id = rb_to_id(name);
if (rb_const_defined_at(super, id)) {
- rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name);
- rb_mod_remove_const(super, ID2SYM(id));
+ rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name);
+ rb_mod_remove_const(super, ID2SYM(id));
}
- return rb_define_class_id_under(super, id, super);
+ return rb_define_class_id_under_no_pin(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)
{
- 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);
+ rb_add_method_optimized(nstr, SYM2ID(name), OPTIMIZED_METHOD_TYPE_STRUCT_AREF, FIX2UINT(off), METHOD_VISI_PUBLIC);
}
static void
define_aset_method(VALUE nstr, VALUE name, VALUE off)
{
- 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);
+ rb_add_method_optimized(nstr, SYM2ID(name), OPTIMIZED_METHOD_TYPE_STRUCT_ASET, FIX2UINT(off), METHOD_VISI_PUBLIC);
}
static VALUE
@@ -342,17 +296,42 @@ rb_struct_s_inspect(VALUE klass)
{
VALUE inspect = rb_class_name(klass);
if (RTEST(rb_struct_s_keyword_init(klass))) {
- rb_str_cat_cstr(inspect, "(keyword_init: true)");
+ rb_str_cat_cstr(inspect, "(keyword_init: true)");
}
return inspect;
}
+static VALUE
+rb_data_s_new(int argc, const VALUE *argv, VALUE klass)
+{
+ if (rb_keyword_given_p()) {
+ if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
+ rb_error_arity(argc, 0, 0);
+ }
+ return rb_class_new_instance_pass_kw(argc, argv, klass);
+ }
+ else {
+ VALUE members = struct_ivar_get(klass, id_members);
+ int num_members = RARRAY_LENINT(members);
+
+ rb_check_arity(argc, 0, num_members);
+ VALUE arg_hash = rb_hash_new_with_size(argc);
+ for (long i=0; i<argc; i++) {
+ VALUE k = rb_ary_entry(members, i), v = argv[i];
+ rb_hash_aset(arg_hash, k, v);
+ }
+ return rb_class_new_instance_kw(1, &arg_hash, klass, RB_PASS_KEYWORDS);
+ }
+}
+
+#if 0 /* for RDoc */
+
/*
* call-seq:
- * StructClass.keyword_init? -> true or false
+ * StructClass::keyword_init? -> true or falsy value
*
- * Returns true if the class was initialized with +keyword_init: true+.
- * Otherwise returns false.
+ * Returns +true+ if the class was initialized with <tt>keyword_init: true</tt>.
+ * Otherwise returns +nil+ or +false+.
*
* Examples:
* Foo = Struct.new(:a)
@@ -362,6 +341,11 @@ rb_struct_s_inspect(VALUE klass)
* Baz = Struct.new(:a, keyword_init: false)
* Baz.keyword_init? # => false
*/
+static VALUE
+rb_struct_s_keyword_init_p(VALUE obj)
+{
+}
+#endif
#define rb_struct_s_keyword_init_p rb_struct_s_keyword_init
@@ -383,20 +367,41 @@ setup_struct(VALUE nstr, VALUE members)
for (i=0; i< len; i++) {
VALUE sym = RARRAY_AREF(members, i);
ID id = SYM2ID(sym);
- VALUE off = LONG2NUM(i);
+ VALUE off = LONG2NUM(i);
- if (i < N_REF_FUNC) {
- rb_define_method_id(nstr, id, ref_func[i], 0);
- }
- else {
- define_aref_method(nstr, sym, off);
- }
- define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
+ define_aref_method(nstr, sym, off);
+ define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
}
return nstr;
}
+static VALUE
+setup_data(VALUE subclass, VALUE members)
+{
+ long i, len;
+
+ members = struct_set_members(subclass, members);
+
+ rb_define_alloc_func(subclass, struct_alloc);
+ VALUE sclass = rb_singleton_class(subclass);
+ rb_undef_method(sclass, "define");
+ rb_define_method(sclass, "new", rb_data_s_new, -1);
+ rb_define_method(sclass, "[]", rb_data_s_new, -1);
+ rb_define_method(sclass, "members", rb_struct_s_members_m, 0);
+ rb_define_method(sclass, "inspect", rb_struct_s_inspect, 0); // FIXME: just a separate method?..
+
+ len = RARRAY_LEN(members);
+ for (i=0; i< len; i++) {
+ VALUE sym = RARRAY_AREF(members, i);
+ VALUE off = LONG2NUM(i);
+
+ define_aref_method(subclass, sym, off);
+ }
+
+ return subclass;
+}
+
VALUE
rb_struct_alloc_noinit(VALUE klass)
{
@@ -413,10 +418,10 @@ struct_make_members_list(va_list ar)
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)) {
- rb_raise(rb_eArgError, "duplicate member: %s", mem);
- }
+ VALUE sym = rb_sym_intern_ascii_cstr(mem);
+ if (st_insert(tbl, sym, Qtrue)) {
+ rb_raise(rb_eArgError, "duplicate member: %s", mem);
+ }
}
ary = rb_hash_keys(list);
st_clear(tbl);
@@ -431,24 +436,24 @@ struct_define_without_accessor(VALUE outer, const char *class_name, VALUE super,
VALUE klass;
if (class_name) {
- if (outer) {
- klass = rb_define_class_under(outer, class_name, super);
- }
- else {
- klass = rb_define_class(class_name, super);
- }
+ if (outer) {
+ klass = rb_define_class_under(outer, class_name, super);
+ }
+ else {
+ klass = rb_define_class(class_name, super);
+ }
}
else {
- klass = anonymous_struct(super);
+ klass = anonymous_struct(super);
}
struct_set_members(klass, members);
if (alloc) {
- rb_define_alloc_func(klass, alloc);
+ rb_define_alloc_func(klass, alloc);
}
else {
- rb_define_alloc_func(klass, struct_alloc);
+ rb_define_alloc_func(klass, struct_alloc);
}
return klass;
@@ -490,8 +495,13 @@ rb_struct_define(const char *name, ...)
ary = struct_make_members_list(ar);
va_end(ar);
- if (!name) st = anonymous_struct(rb_cStruct);
- else st = new_struct(rb_str_new2(name), rb_cStruct);
+ if (!name) {
+ st = anonymous_struct(rb_cStruct);
+ }
+ else {
+ st = new_struct(rb_str_new2(name), rb_cStruct);
+ rb_vm_add_root_module(st);
+ }
return setup_struct(st, ary);
}
@@ -505,70 +515,133 @@ rb_struct_define_under(VALUE outer, const char *name, ...)
ary = struct_make_members_list(ar);
va_end(ar);
- return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary);
+ return setup_struct(rb_define_class_id_under(outer, rb_intern(name), rb_cStruct), ary);
}
/*
* call-seq:
- * Struct.new([class_name] [, member_name]+) -> StructClass
- * Struct.new([class_name] [, member_name]+, keyword_init: true) -> StructClass
- * Struct.new([class_name] [, member_name]+) {|StructClass| block } -> StructClass
- * StructClass.new(value, ...) -> object
- * StructClass[value, ...] -> object
- *
- * The first two forms are used to create a new Struct subclass +class_name+
- * that can contain a value for each +member_name+. This subclass can be
- * used to create instances of the structure like any other Class.
- *
- * If the +class_name+ is omitted an anonymous structure class will be
- * created. Otherwise, the name of this struct will appear as a constant in
- * class Struct, so it must be unique for all Structs in the system and
- * must start with a capital letter. Assigning a structure class to a
- * constant also gives the class the name of the constant.
- *
- * # Create a structure with a name under Struct
- * Struct.new("Customer", :name, :address)
- * #=> Struct::Customer
- * Struct::Customer.new("Dave", "123 Main")
- * #=> #<struct Struct::Customer name="Dave", address="123 Main">
- *
- * # Create a structure named by its constant
- * Customer = Struct.new(:name, :address)
- * #=> Customer
- * Customer.new("Dave", "123 Main")
- * #=> #<struct Customer name="Dave", address="123 Main">
- *
- * If the optional +keyword_init+ keyword argument is set to +true+,
- * .new takes keyword arguments instead of normal arguments.
- *
- * Customer = Struct.new(:name, :address, keyword_init: true)
- * Customer.new(name: "Dave", address: "123 Main")
- * #=> #<struct Customer name="Dave", address="123 Main">
- *
- * If a block is given it will be evaluated in the context of
- * +StructClass+, passing the created class as a parameter:
- *
- * Customer = Struct.new(:name, :address) do
- * def greeting
- * "Hello #{name}!"
- * end
- * end
- * Customer.new("Dave", "123 Main").greeting #=> "Hello Dave!"
- *
- * This is the recommended way to customize a struct. Subclassing an
- * anonymous struct creates an extra anonymous class that will never be used.
- *
- * The last two forms create a new instance of a struct subclass. The number
- * of +value+ parameters must be less than or equal to the number of
- * attributes defined for the structure. Unset parameters default to +nil+.
- * Passing more parameters than number of attributes will raise
- * an ArgumentError.
- *
- * Customer = Struct.new(:name, :address)
- * Customer.new("Dave", "123 Main")
- * #=> #<struct Customer name="Dave", address="123 Main">
- * Customer["Dave"]
- * #=> #<struct Customer name="Dave", address=nil>
+ * Struct.new(*member_names, keyword_init: false){|Struct_subclass| ... } -> Struct_subclass
+ * Struct.new(class_name, *member_names, keyword_init: false){|Struct_subclass| ... } -> Struct_subclass
+ * Struct_subclass.new(*member_names) -> Struct_subclass_instance
+ * Struct_subclass.new(**member_names) -> Struct_subclass_instance
+ *
+ * <tt>Struct.new</tt> returns a new subclass of +Struct+. The new subclass:
+ *
+ * - May be anonymous, or may have the name given by +class_name+.
+ * - May have members as given by +member_names+.
+ * - May have initialization via ordinary arguments, or via keyword arguments
+ *
+ * The new subclass has its own method <tt>::new</tt>; thus:
+ *
+ * Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo
+ * f = Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1>
+ *
+ * <b>\Class Name</b>
+ *
+ * With string argument +class_name+,
+ * returns a new subclass of +Struct+ named <tt>Struct::<em>class_name</em></tt>:
+ *
+ * Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo
+ * Foo.name # => "Struct::Foo"
+ * Foo.superclass # => Struct
+ *
+ * Without string argument +class_name+,
+ * returns a new anonymous subclass of +Struct+:
+ *
+ * Struct.new(:foo, :bar).name # => nil
+ *
+ * <b>Block</b>
+ *
+ * With a block given, the created subclass is yielded to the block:
+ *
+ * Customer = Struct.new('Customer', :name, :address) do |new_class|
+ * p "The new subclass is #{new_class}"
+ * def greeting
+ * "Hello #{name} at #{address}"
+ * end
+ * end # => Struct::Customer
+ * dave = Customer.new('Dave', '123 Main')
+ * dave # => #<struct Struct::Customer name="Dave", address="123 Main">
+ * dave.greeting # => "Hello Dave at 123 Main"
+ *
+ * Output, from <tt>Struct.new</tt>:
+ *
+ * "The new subclass is Struct::Customer"
+ *
+ * <b>Member Names</b>
+ *
+ * \Symbol arguments +member_names+
+ * determines the members of the new subclass:
+ *
+ * Struct.new(:foo, :bar).members # => [:foo, :bar]
+ * Struct.new('Foo', :foo, :bar).members # => [:foo, :bar]
+ *
+ * The new subclass has instance methods corresponding to +member_names+:
+ *
+ * Foo = Struct.new('Foo', :foo, :bar)
+ * Foo.instance_methods(false) # => [:foo, :bar, :foo=, :bar=]
+ * f = Foo.new # => #<struct Struct::Foo foo=nil, bar=nil>
+ * f.foo # => nil
+ * f.foo = 0 # => 0
+ * f.bar # => nil
+ * f.bar = 1 # => 1
+ * f # => #<struct Struct::Foo foo=0, bar=1>
+ *
+ * <b>Singleton Methods</b>
+ *
+ * A subclass returned by Struct.new has these singleton methods:
+ *
+ * - \Method <tt>::new </tt> creates an instance of the subclass:
+ *
+ * Foo.new # => #<struct Struct::Foo foo=nil, bar=nil>
+ * Foo.new(0) # => #<struct Struct::Foo foo=0, bar=nil>
+ * Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1>
+ * Foo.new(0, 1, 2) # Raises ArgumentError: struct size differs
+ *
+ * # Initialization with keyword arguments:
+ * Foo.new(foo: 0) # => #<struct Struct::Foo foo=0, bar=nil>
+ * Foo.new(foo: 0, bar: 1) # => #<struct Struct::Foo foo=0, bar=1>
+ * Foo.new(foo: 0, bar: 1, baz: 2)
+ * # Raises ArgumentError: unknown keywords: baz
+ *
+ * \Method <tt>::[]</tt> is an alias for method <tt>::new</tt>.
+ *
+ * - \Method <tt>:inspect</tt> returns a string representation of the subclass:
+ *
+ * Foo.inspect
+ * # => "Struct::Foo"
+ *
+ * - \Method <tt>::members</tt> returns an array of the member names:
+ *
+ * Foo.members # => [:foo, :bar]
+ *
+ * <b>Keyword Argument</b>
+ *
+ * By default, the arguments for initializing an instance of the new subclass
+ * can be both positional and keyword arguments.
+ *
+ * Optional keyword argument <tt>keyword_init:</tt> allows to force only one
+ * type of arguments to be accepted:
+ *
+ * KeywordsOnly = Struct.new(:foo, :bar, keyword_init: true)
+ * KeywordsOnly.new(bar: 1, foo: 0)
+ * # => #<struct KeywordsOnly foo=0, bar=1>
+ * KeywordsOnly.new(0, 1)
+ * # Raises ArgumentError: wrong number of arguments
+ *
+ * PositionalOnly = Struct.new(:foo, :bar, keyword_init: false)
+ * PositionalOnly.new(0, 1)
+ * # => #<struct PositionalOnly foo=0, bar=1>
+ * PositionalOnly.new(bar: 1, foo: 0)
+ * # => #<struct PositionalOnly foo={:foo=>1, :bar=>2}, bar=nil>
+ * # Note that no error is raised, but arguments treated as one hash value
+ *
+ * # Same as not providing keyword_init:
+ * Any = Struct.new(:foo, :bar, keyword_init: nil)
+ * Any.new(foo: 1, bar: 2)
+ * # => #<struct Any foo=1, bar=2>
+ * Any.new(1, 2)
+ * # => #<struct Any foo=1, bar=2>
*/
static VALUE
@@ -578,31 +651,31 @@ rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
long i;
VALUE st;
st_table *tbl;
+ VALUE opt;
- rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
+ argc = rb_scan_args(argc, argv, "1*:", NULL, NULL, &opt);
name = argv[0];
if (SYMBOL_P(name)) {
- name = Qnil;
+ name = Qnil;
}
else {
- --argc;
- ++argv;
+ --argc;
+ ++argv;
}
- if (RB_TYPE_P(argv[argc-1], T_HASH)) {
- static ID keyword_ids[1];
+ if (!NIL_P(opt)) {
+ static ID keyword_ids[1];
- if (!keyword_ids[0]) {
- keyword_ids[0] = rb_intern("keyword_init");
- }
- rb_get_kwargs(argv[argc-1], keyword_ids, 0, 1, &keyword_init);
- if (keyword_init == Qundef) {
+ if (!keyword_ids[0]) {
+ keyword_ids[0] = rb_intern("keyword_init");
+ }
+ rb_get_kwargs(opt, keyword_ids, 0, 1, &keyword_init);
+ if (UNDEF_P(keyword_init)) {
keyword_init = Qnil;
}
else if (RTEST(keyword_init)) {
keyword_init = Qtrue;
}
- --argc;
}
rest = rb_ident_hash_new();
@@ -610,23 +683,23 @@ rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
OBJ_WB_UNPROTECT(rest);
tbl = RHASH_TBL_RAW(rest);
for (i=0; i<argc; i++) {
- VALUE mem = rb_to_symbol(argv[i]);
+ VALUE mem = rb_to_symbol(argv[i]);
if (rb_is_attrset_sym(mem)) {
rb_raise(rb_eArgError, "invalid struct member: %"PRIsVALUE, mem);
}
- if (st_insert(tbl, mem, Qtrue)) {
- rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
- }
+ if (st_insert(tbl, mem, Qtrue)) {
+ rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
+ }
}
rest = rb_hash_keys(rest);
st_clear(tbl);
RBASIC_CLEAR_CLASS(rest);
OBJ_FREEZE_RAW(rest);
if (NIL_P(name)) {
- st = anonymous_struct(klass);
+ st = anonymous_struct(klass);
}
else {
- st = new_struct(name, klass);
+ st = new_struct(name, klass);
}
setup_struct(st, rest);
rb_ivar_set(st, id_keyword_init, keyword_init);
@@ -643,7 +716,7 @@ num_members(VALUE klass)
VALUE members;
members = struct_ivar_get(klass, id_members);
if (!RB_TYPE_P(members, T_ARRAY)) {
- rb_raise(rb_eTypeError, "broken members");
+ rb_raise(rb_eTypeError, "broken members");
}
return RARRAY_LEN(members);
}
@@ -664,14 +737,14 @@ struct_hash_set_i(VALUE key, VALUE val, VALUE arg)
struct struct_hash_set_arg *args = (struct struct_hash_set_arg *)arg;
int i = rb_struct_pos(args->self, &key);
if (i < 0) {
- if (args->unknown_keywords == Qnil) {
- args->unknown_keywords = rb_ary_new();
- }
- rb_ary_push(args->unknown_keywords, key);
+ if (NIL_P(args->unknown_keywords)) {
+ args->unknown_keywords = rb_ary_new();
+ }
+ rb_ary_push(args->unknown_keywords, key);
}
else {
- rb_struct_modify(args->self);
- RSTRUCT_SET(args->self, i, val);
+ rb_struct_modify(args->self);
+ RSTRUCT_SET(args->self, i, val);
}
return ST_CONTINUE;
}
@@ -687,35 +760,44 @@ rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
return Qnil;
}
- VALUE keyword_init = rb_struct_s_keyword_init(klass);
- if (RTEST(keyword_init)) {
- struct struct_hash_set_arg arg;
- if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
- rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0)", argc);
- }
- rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), n);
- arg.self = self;
- arg.unknown_keywords = Qnil;
- rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
- if (arg.unknown_keywords != Qnil) {
- rb_raise(rb_eArgError, "unknown keywords: %s",
- RSTRING_PTR(rb_ary_join(arg.unknown_keywords, rb_str_new2(", "))));
- }
+ bool keyword_init = false;
+ switch (rb_struct_s_keyword_init(klass)) {
+ default:
+ if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
+ rb_error_arity(argc, 0, 0);
+ }
+ keyword_init = true;
+ break;
+ case Qfalse:
+ break;
+ case Qnil:
+ if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
+ break;
+ }
+ keyword_init = rb_keyword_given_p();
+ break;
+ }
+ if (keyword_init) {
+ struct struct_hash_set_arg arg;
+ rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), n);
+ arg.self = self;
+ arg.unknown_keywords = Qnil;
+ rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
+ if (arg.unknown_keywords != Qnil) {
+ rb_raise(rb_eArgError, "unknown keywords: %s",
+ RSTRING_PTR(rb_ary_join(arg.unknown_keywords, rb_str_new2(", "))));
+ }
}
else {
- if (n < argc) {
- rb_raise(rb_eArgError, "struct size differs");
- }
- if (keyword_init == Qnil && argc == 1 && RB_TYPE_P(argv[0], T_HASH) && rb_keyword_given_p()) {
- rb_warn("Passing only keyword arguments to Struct#initialize will behave differently from Ruby 3.2. "\
- "Please use a Hash literal like .new({k: v}) instead of .new(k: v).");
+ if (n < argc) {
+ rb_raise(rb_eArgError, "struct size differs");
}
for (long i=0; i<argc; i++) {
- RSTRUCT_SET(self, i, argv[i]);
- }
- if (n > argc) {
- rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc);
- }
+ RSTRUCT_SET(self, i, argv[i]);
+ }
+ if (n > argc) {
+ rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc);
+ }
}
return Qnil;
}
@@ -724,6 +806,7 @@ VALUE
rb_struct_initialize(VALUE self, VALUE values)
{
rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
+ if (rb_obj_is_kind_of(self, rb_cData)) OBJ_FREEZE_RAW(self);
RB_GC_GUARD(values);
return Qnil;
}
@@ -776,7 +859,7 @@ struct_alloc(VALUE klass)
if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
- rb_mem_clear((VALUE *)st->as.ary, n);
+ rb_mem_clear((VALUE *)st->as.ary, n);
}
else {
st->as.heap.ptr = struct_heap_alloc((VALUE)st, n);
@@ -796,18 +879,18 @@ rb_struct_alloc(VALUE klass, VALUE values)
VALUE
rb_struct_new(VALUE klass, ...)
{
- VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
+ VALUE tmpargs[16], *mem = tmpargs;
int size, i;
va_list args;
size = rb_long2int(num_members(klass));
if (size > numberof(tmpargs)) {
- tmpargs[0] = rb_ary_tmp_new(size);
- mem = RARRAY_PTR(tmpargs[0]);
+ tmpargs[0] = rb_ary_hidden_new(size);
+ mem = RARRAY_PTR(tmpargs[0]);
}
va_start(args, klass);
for (i=0; i<size; i++) {
- mem[i] = va_arg(args, VALUE);
+ mem[i] = va_arg(args, VALUE);
}
va_end(args);
@@ -822,21 +905,24 @@ struct_enum_size(VALUE s, VALUE args, VALUE eobj)
/*
* call-seq:
- * struct.each {|obj| block } -> struct
- * struct.each -> enumerator
+ * each {|value| ... } -> self
+ * each -> enumerator
*
- * Yields the value of each struct member in order. If no block is given an
- * enumerator is returned.
+ * Calls the given block with the value of each member; returns +self+:
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.each {|x| puts(x) }
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.each {|value| p value }
+ *
+ * Output:
*
- * Produces:
+ * "Joe Smith"
+ * "123 Maple, Anytown NC"
+ * 12345
*
- * Joe Smith
- * 123 Maple, Anytown NC
- * 12345
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: #each_pair.
*/
static VALUE
@@ -846,28 +932,32 @@ rb_struct_each(VALUE s)
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
for (i=0; i<RSTRUCT_LEN(s); i++) {
- rb_yield(RSTRUCT_GET(s, i));
+ rb_yield(RSTRUCT_GET(s, i));
}
return s;
}
/*
* call-seq:
- * struct.each_pair {|sym, obj| block } -> struct
- * struct.each_pair -> enumerator
+ * each_pair {|(name, value)| ... } -> self
+ * each_pair -> enumerator
*
- * Yields the name and value of each struct member in order. If no block is
- * given an enumerator is returned.
+ * Calls the given block with each member name/value pair; returns +self+:
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.each_pair {|name, value| puts("#{name} => #{value}") }
+ * Customer = Struct.new(:name, :address, :zip) # => Customer
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.each_pair {|(name, value)| p "#{name} => #{value}" }
+ *
+ * Output:
+ *
+ * "name => Joe Smith"
+ * "address => 123 Maple, Anytown NC"
+ * "zip => 12345"
*
- * Produces:
+ * Returns an Enumerator if no block is given.
+ *
+ * Related: #each.
*
- * name => Joe Smith
- * address => 123 Maple, Anytown NC
- * zip => 12345
*/
static VALUE
@@ -879,60 +969,61 @@ rb_struct_each_pair(VALUE s)
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
members = rb_struct_members(s);
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);
- rb_yield_values(2, key, value);
- }
+ for (i=0; i<RSTRUCT_LEN(s); i++) {
+ VALUE key = rb_ary_entry(members, i);
+ VALUE value = RSTRUCT_GET(s, i);
+ rb_yield_values(2, key, value);
+ }
}
else {
- for (i=0; i<RSTRUCT_LEN(s); i++) {
- VALUE key = rb_ary_entry(members, i);
- VALUE value = RSTRUCT_GET(s, i);
- rb_yield(rb_assoc_new(key, value));
- }
+ for (i=0; i<RSTRUCT_LEN(s); i++) {
+ VALUE key = rb_ary_entry(members, i);
+ VALUE value = RSTRUCT_GET(s, i);
+ rb_yield(rb_assoc_new(key, value));
+ }
}
return s;
}
static VALUE
-inspect_struct(VALUE s, VALUE dummy, int recur)
+inspect_struct(VALUE s, VALUE prefix, int recur)
{
VALUE cname = rb_class_path(rb_obj_class(s));
- VALUE members, str = rb_str_new2("#<struct ");
+ VALUE members;
+ VALUE str = prefix;
long i, len;
char first = RSTRING_PTR(cname)[0];
if (recur || first != '#') {
- rb_str_append(str, cname);
+ rb_str_append(str, cname);
}
if (recur) {
- return rb_str_cat2(str, ":...>");
+ return rb_str_cat2(str, ":...>");
}
members = rb_struct_members(s);
len = RSTRUCT_LEN(s);
for (i=0; i<len; i++) {
- VALUE slot;
- ID id;
-
- if (i > 0) {
- rb_str_cat2(str, ", ");
- }
- else if (first != '#') {
- rb_str_cat2(str, " ");
- }
- slot = RARRAY_AREF(members, i);
- id = SYM2ID(slot);
- if (rb_is_local_id(id) || rb_is_const_id(id)) {
- rb_str_append(str, rb_id2str(id));
- }
- else {
- rb_str_append(str, rb_inspect(slot));
- }
- rb_str_cat2(str, "=");
- rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i)));
+ VALUE slot;
+ ID id;
+
+ if (i > 0) {
+ rb_str_cat2(str, ", ");
+ }
+ else if (first != '#') {
+ rb_str_cat2(str, " ");
+ }
+ slot = RARRAY_AREF(members, i);
+ id = SYM2ID(slot);
+ if (rb_is_local_id(id) || rb_is_const_id(id)) {
+ rb_str_append(str, rb_id2str(id));
+ }
+ else {
+ rb_str_append(str, rb_inspect(slot));
+ }
+ rb_str_cat2(str, "=");
+ rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i)));
}
rb_str_cat2(str, ">");
@@ -940,29 +1031,38 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
}
/*
- * call-seq:
- * struct.to_s -> string
- * struct.inspect -> string
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a string representation of +self+:
+ *
+ * Customer = Struct.new(:name, :address, :zip) # => Customer
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.inspect # => "#<struct Customer name=\"Joe Smith\", address=\"123 Maple, Anytown NC\", zip=12345>"
+ *
+ * Struct#to_s is an alias for Struct#inspect.
*
- * Returns a description of this struct as a string.
*/
static VALUE
rb_struct_inspect(VALUE s)
{
- return rb_exec_recursive(inspect_struct, s, 0);
+ return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<struct "));
}
/*
* call-seq:
- * struct.to_a -> array
- * struct.values -> array
+ * to_a -> array
*
- * Returns the values for this struct as an Array.
+ * Returns the values in +self+ as an array:
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.to_a[1] #=> "123 Maple, Anytown NC"
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.to_a # => ["Joe Smith", "123 Maple, Anytown NC", 12345]
+ *
+ * Struct#values and Struct#deconstruct are aliases for Struct#to_a.
+ *
+ * Related: #members.
*/
static VALUE
@@ -973,19 +1073,25 @@ rb_struct_to_a(VALUE s)
/*
* call-seq:
- * struct.to_h -> hash
- * struct.to_h {|name, value| block } -> hash
+ * to_h -> hash
+ * to_h {|name, value| ... } -> hash
*
- * Returns a Hash containing the names and values for the struct's members.
+ * Returns a hash containing the name and value for each member:
*
- * If a block is given, the results of the block on each pair of the receiver
- * will be used as pairs.
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * h = joe.to_h
+ * h # => {:name=>"Joe Smith", :address=>"123 Maple, Anytown NC", :zip=>12345}
+ *
+ * If a block is given, it is called with each name/value pair;
+ * the block should return a 2-element array whose elements will become
+ * a key/value pair in the returned hash:
+ *
+ * h = joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}
+ * h # => {:NAME=>"JOE SMITH", :ADDRESS=>"123 MAPLE, ANYTOWN NC", :ZIP=>"12345"}
+ *
+ * Raises ArgumentError if the block returns an inappropriate value.
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.to_h[:address] #=> "123 Maple, Anytown NC"
- * joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}[:ADDRESS]
- * #=> "123 MAPLE, ANYTOWN NC"
*/
static VALUE
@@ -1006,6 +1112,23 @@ rb_struct_to_h(VALUE s)
return h;
}
+/*
+ * call-seq:
+ * deconstruct_keys(array_of_names) -> hash
+ *
+ * Returns a hash of the name/value pairs for the given member names.
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * h = joe.deconstruct_keys([:zip, :address])
+ * h # => {:zip=>12345, :address=>"123 Maple, Anytown NC"}
+ *
+ * Returns all names and values if +array_of_names+ is +nil+:
+ *
+ * h = joe.deconstruct_keys(nil)
+ * h # => {:name=>"Joseph Smith, Jr.", :address=>"123 Maple, Anytown NC", :zip=>12345}
+ *
+ */
static VALUE
rb_struct_deconstruct_keys(VALUE s, VALUE keys)
{
@@ -1016,7 +1139,7 @@ rb_struct_deconstruct_keys(VALUE s, VALUE keys)
return rb_struct_to_h(s);
}
if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
- rb_raise(rb_eTypeError,
+ rb_raise(rb_eTypeError,
"wrong argument type %"PRIsVALUE" (expected Array or nil)",
rb_obj_class(keys));
@@ -1044,11 +1167,11 @@ rb_struct_init_copy(VALUE copy, VALUE s)
if (!OBJ_INIT_COPY(copy, s)) return copy;
if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
- rb_raise(rb_eTypeError, "struct size mismatch");
+ rb_raise(rb_eTypeError, "struct size mismatch");
}
for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
- RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
+ RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
}
return copy;
@@ -1060,30 +1183,30 @@ rb_struct_pos(VALUE s, VALUE *name)
long i;
VALUE idx = *name;
- if (RB_TYPE_P(idx, T_SYMBOL)) {
- return struct_member_pos(s, idx);
+ if (SYMBOL_P(idx)) {
+ return struct_member_pos(s, idx);
}
else if (RB_TYPE_P(idx, T_STRING)) {
- idx = rb_check_symbol(name);
- if (NIL_P(idx)) return -1;
- return struct_member_pos(s, idx);
+ idx = rb_check_symbol(name);
+ if (NIL_P(idx)) return -1;
+ return struct_member_pos(s, idx);
}
else {
- long len;
- i = NUM2LONG(idx);
- len = RSTRUCT_LEN(s);
- if (i < 0) {
- if (i + len < 0) {
- *name = LONG2FIX(i);
- return -1;
- }
- i += len;
- }
- else if (len <= i) {
- *name = LONG2FIX(i);
- return -1;
- }
- return (int)i;
+ long len;
+ i = NUM2LONG(idx);
+ len = RSTRUCT_LEN(s);
+ if (i < 0) {
+ if (i + len < 0) {
+ *name = LONG2FIX(i);
+ return -1;
+ }
+ i += len;
+ }
+ else if (len <= i) {
+ *name = LONG2FIX(i);
+ return -1;
+ }
+ return (int)i;
}
}
@@ -1091,36 +1214,45 @@ static void
invalid_struct_pos(VALUE s, VALUE idx)
{
if (FIXNUM_P(idx)) {
- long i = FIX2INT(idx), len = RSTRUCT_LEN(s);
- if (i < 0) {
- rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
- i, len);
- }
- else {
- rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
- i, len);
- }
+ long i = FIX2INT(idx), len = RSTRUCT_LEN(s);
+ if (i < 0) {
+ rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
+ i, len);
+ }
+ else {
+ rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
+ i, len);
+ }
}
else {
- rb_name_err_raise("no member '%1$s' in struct", s, idx);
+ rb_name_err_raise("no member '%1$s' in struct", s, idx);
}
}
/*
* call-seq:
- * struct[member] -> object
- * struct[index] -> object
+ * struct[name] -> object
+ * struct[n] -> object
*
- * Attribute Reference---Returns the value of the given struct +member+ or
- * the member at the given +index+. Raises NameError if the +member+ does
- * not exist and IndexError if the +index+ is out of range.
+ * Returns a value from +self+.
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * With symbol or string argument +name+ given, returns the value for the named member:
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe[:zip] # => 12345
+ *
+ * Raises NameError if +name+ is not the name of a member.
+ *
+ * With integer argument +n+ given, returns <tt>self.values[n]</tt>
+ * if +n+ is in range;
+ * see Array@Array+Indexes:
+ *
+ * joe[2] # => 12345
+ * joe[-2] # => "123 Maple, Anytown NC"
+ *
+ * Raises IndexError if +n+ is out of range.
*
- * joe["name"] #=> "Joe Smith"
- * joe[:name] #=> "Joe Smith"
- * joe[0] #=> "Joe Smith"
*/
VALUE
@@ -1133,21 +1265,32 @@ rb_struct_aref(VALUE s, VALUE idx)
/*
* call-seq:
- * struct[member] = obj -> obj
- * struct[index] = obj -> obj
+ * struct[name] = value -> value
+ * struct[n] = value -> value
*
- * Attribute Assignment---Sets the value of the given struct +member+ or
- * the member at the given +index+. Raises NameError if the +member+ does not
- * exist and IndexError if the +index+ is out of range.
+ * Assigns a value to a member.
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * With symbol or string argument +name+ given, assigns the given +value+
+ * to the named member; returns +value+:
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe[:zip] = 54321 # => 54321
+ * joe # => #<struct Customer name="Joe Smith", address="123 Maple, Anytown NC", zip=54321>
+ *
+ * Raises NameError if +name+ is not the name of a member.
+ *
+ * With integer argument +n+ given, assigns the given +value+
+ * to the +n+-th member if +n+ is in range;
+ * see Array@Array+Indexes:
*
- * joe["name"] = "Luke"
- * joe[:zip] = "90210"
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe[2] = 54321 # => 54321
+ * joe[-3] = 'Joseph Smith' # => "Joseph Smith"
+ * joe # => #<struct Customer name="Joseph Smith", address="123 Maple, Anytown NC", zip=54321>
+ *
+ * Raises IndexError if +n+ is out of range.
*
- * joe.name #=> "Luke"
- * joe.zip #=> "90210"
*/
VALUE
@@ -1185,15 +1328,36 @@ struct_entry(VALUE s, long n)
/*
* call-seq:
- * struct.values_at(selector, ...) -> array
+ * values_at(*integers) -> array
+ * values_at(integer_range) -> array
*
- * Returns the struct member values for each +selector+ as an Array. A
- * +selector+ may be either an Integer offset or a Range of offsets (as in
- * Array#values_at).
+ * Returns an array of values from +self+.
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.values_at(0, 2) #=> ["Joe Smith", 12345]
+ * With integer arguments +integers+ given,
+ * returns an array containing each value given by one of +integers+:
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.values_at(0, 2) # => ["Joe Smith", 12345]
+ * joe.values_at(2, 0) # => [12345, "Joe Smith"]
+ * joe.values_at(2, 1, 0) # => [12345, "123 Maple, Anytown NC", "Joe Smith"]
+ * joe.values_at(0, -3) # => ["Joe Smith", "Joe Smith"]
+ *
+ * Raises IndexError if any of +integers+ is out of range;
+ * see Array@Array+Indexes.
+ *
+ * With integer range argument +integer_range+ given,
+ * returns an array containing each value given by the elements of the range;
+ * fills with +nil+ values for range elements larger than the structure:
+ *
+ * joe.values_at(0..2)
+ * # => ["Joe Smith", "123 Maple, Anytown NC", 12345]
+ * joe.values_at(-3..-1)
+ * # => ["Joe Smith", "123 Maple, Anytown NC", 12345]
+ * joe.values_at(1..4) # => ["123 Maple, Anytown NC", 12345, nil, nil]
+ *
+ * Raises RangeError if any element of the range is negative and out of range;
+ * see Array@Array+Indexes.
*
*/
@@ -1205,18 +1369,20 @@ rb_struct_values_at(int argc, VALUE *argv, VALUE s)
/*
* call-seq:
- * struct.select {|obj| block } -> array
- * struct.select -> enumerator
- * struct.filter {|obj| block } -> array
- * struct.filter -> enumerator
+ * select {|value| ... } -> array
+ * select -> enumerator
*
- * Yields each member value from the struct to the block and returns an Array
- * containing the member values from the +struct+ for which the given block
- * returns a true value (equivalent to Enumerable#select).
+ * With a block given, returns an array of values from +self+
+ * for which the block returns a truthy value:
*
- * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
- * l = Lots.new(11, 22, 33, 44, 55, 66)
- * l.select {|v| v.even? } #=> [22, 44, 66]
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * a = joe.select {|value| value.is_a?(String) }
+ * a # => ["Joe Smith", "123 Maple, Anytown NC"]
+ * a = joe.select {|value| value.is_a?(Integer) }
+ * a # => [12345]
+ *
+ * With no block given, returns an Enumerator.
*
* Struct#filter is an alias for Struct#select.
*/
@@ -1231,9 +1397,9 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
result = rb_ary_new();
for (i = 0; i < RSTRUCT_LEN(s); i++) {
- if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
- rb_ary_push(result, RSTRUCT_GET(s, i));
- }
+ if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
+ rb_ary_push(result, RSTRUCT_GET(s, i));
+ }
}
return result;
@@ -1252,19 +1418,25 @@ recursive_equal(VALUE s, VALUE s2, int recur)
return Qtrue;
}
+
/*
* call-seq:
- * struct == other -> true or false
+ * self == other -> true or false
*
- * Equality---Returns +true+ if +other+ has the same struct subclass and has
- * equal member values (according to Object#==).
+ * Returns +true+ if and only if the following are true; otherwise returns +false+:
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
- * joe == joejr #=> true
- * joe == jane #=> false
+ * - <tt>other.class == self.class</tt>.
+ * - For each member name +name+, <tt>other.name == self.name</tt>.
+ *
+ * Examples:
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe_jr == joe # => true
+ * joe_jr[:name] = 'Joe Smith, Jr.'
+ * # => "Joe Smith, Jr."
+ * joe_jr == joe # => false
*/
static VALUE
@@ -1274,19 +1446,29 @@ rb_struct_equal(VALUE s, VALUE s2)
if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
- rb_bug("inconsistent struct"); /* should never happen */
+ rb_bug("inconsistent struct"); /* should never happen */
}
return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
}
/*
- * call-seq:
- * struct.hash -> integer
+ * call-seq:
+ * hash -> integer
*
- * Returns a hash value based on this struct's contents.
+ * Returns the integer hash value for +self+.
*
- * See also Object#hash.
+ * Two structs of the same class and with the same content
+ * will have the same hash code (and will compare using Struct#eql?):
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.hash == joe_jr.hash # => true
+ * joe_jr[:name] = 'Joe Smith, Jr.'
+ * joe.hash == joe_jr.hash # => false
+ *
+ * Related: Object#hash.
*/
static VALUE
@@ -1300,7 +1482,7 @@ rb_struct_hash(VALUE s)
len = RSTRUCT_LEN(s);
for (i = 0; i < len; i++) {
n = rb_hash(RSTRUCT_GET(s, i));
- h = rb_hash_uint(h, NUM2LONG(n));
+ h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return ST2FIX(h);
@@ -1321,11 +1503,21 @@ recursive_eql(VALUE s, VALUE s2, int recur)
/*
* call-seq:
- * struct.eql?(other) -> true or false
+ * eql?(other) -> true or false
+ *
+ * Returns +true+ if and only if the following are true; otherwise returns +false+:
*
- * Hash equality---+other+ and +struct+ refer to the same hash key if they
- * have the same struct subclass and have equal member values (according to
- * Object#eql?).
+ * - <tt>other.class == self.class</tt>.
+ * - For each member name +name+, <tt>other.name.eql?(self.name)</tt>.
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe_jr.eql?(joe) # => true
+ * joe_jr[:name] = 'Joe Smith, Jr.'
+ * joe_jr.eql?(joe) # => false
+ *
+ * Related: Object#==.
*/
static VALUE
@@ -1335,7 +1527,7 @@ rb_struct_eql(VALUE s, VALUE s2)
if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
- rb_bug("inconsistent struct"); /* should never happen */
+ rb_bug("inconsistent struct"); /* should never happen */
}
return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
@@ -1343,14 +1535,15 @@ rb_struct_eql(VALUE s, VALUE s2)
/*
* call-seq:
- * struct.length -> integer
- * struct.size -> integer
+ * size -> integer
*
- * Returns the number of struct members.
+ * Returns the number of members.
*
- * Customer = Struct.new(:name, :address, :zip)
- * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
- * joe.length #=> 3
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.size #=> 3
+ *
+ * Struct#length is an alias for Struct#size.
*/
VALUE
@@ -1361,14 +1554,17 @@ rb_struct_size(VALUE s)
/*
* call-seq:
- * struct.dig(key, *identifiers) -> object
+ * dig(name, *identifiers) -> object
+ * dig(n, *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].
+ * Finds and returns an object among nested objects.
+ * The nested objects may be instances of various classes.
+ * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
+ *
+ *
+ * Given symbol or string argument +name+,
+ * returns the object that is specified by +name+ and +identifiers+:
*
- * Examples:
* Foo = Struct.new(:a)
* f = Foo.new(Foo.new({b: [1, 2, 3]}))
* f.dig(:a) # => #<struct Foo a={:b=>[1, 2, 3]}>
@@ -1376,6 +1572,16 @@ rb_struct_size(VALUE s)
* f.dig(:a, :a, :b) # => [1, 2, 3]
* f.dig(:a, :a, :b, 0) # => 1
* f.dig(:b, 0) # => nil
+ *
+ * Given integer argument +n+,
+ * returns the object that is specified by +n+ and +identifiers+:
+ *
+ * f.dig(0) # => #<struct Foo a={:b=>[1, 2, 3]}>
+ * f.dig(0, 0) # => {:b=>[1, 2, 3]}
+ * f.dig(0, 0, :b) # => [1, 2, 3]
+ * f.dig(0, 0, :b, 0) # => 1
+ * f.dig(:b, 0) # => nil
+ *
*/
static VALUE
@@ -1389,31 +1595,623 @@ rb_struct_dig(int argc, VALUE *argv, VALUE self)
}
/*
- * Document-class: Struct
+ * Document-class: Data
+ *
+ * \Class \Data provides a convenient way to define simple classes
+ * for value-alike objects.
+ *
+ * The simplest example of usage:
+ *
+ * Measure = Data.define(:amount, :unit)
+ *
+ * # Positional arguments constructor is provided
+ * distance = Measure.new(100, 'km')
+ * #=> #<data Measure amount=100, unit="km">
+ *
+ * # Keyword arguments constructor is provided
+ * weight = Measure.new(amount: 50, unit: 'kg')
+ * #=> #<data Measure amount=50, unit="kg">
+ *
+ * # Alternative form to construct an object:
+ * speed = Measure[10, 'mPh']
+ * #=> #<data Measure amount=10, unit="mPh">
+ *
+ * # Works with keyword arguments, too:
+ * area = Measure[amount: 1.5, unit: 'm^2']
+ * #=> #<data Measure amount=1.5, unit="m^2">
+ *
+ * # Argument accessors are provided:
+ * distance.amount #=> 100
+ * distance.unit #=> "km"
+ *
+ * Constructed object also has a reasonable definitions of #==
+ * operator, #to_h hash conversion, and #deconstruct/#deconstruct_keys
+ * to be used in pattern matching.
+ *
+ * ::define method accepts an optional block and evaluates it in
+ * the context of the newly defined class. That allows to define
+ * additional methods:
+ *
+ * Measure = Data.define(:amount, :unit) do
+ * def <=>(other)
+ * return unless other.is_a?(self.class) && other.unit == unit
+ * amount <=> other.amount
+ * end
+ *
+ * include Comparable
+ * end
+ *
+ * Measure[3, 'm'] < Measure[5, 'm'] #=> true
+ * Measure[3, 'm'] < Measure[5, 'kg']
+ * # comparison of Measure with Measure failed (ArgumentError)
+ *
+ * Data provides no member writers, or enumerators: it is meant
+ * to be a storage for immutable atomic values. But note that
+ * if some of data members is of a mutable class, Data does no additional
+ * immutability enforcement:
+ *
+ * Event = Data.define(:time, :weekdays)
+ * event = Event.new('18:00', %w[Tue Wed Fri])
+ * #=> #<data Event time="18:00", weekdays=["Tue", "Wed", "Fri"]>
+ *
+ * # There is no #time= or #weekdays= accessors, but changes are
+ * # still possible:
+ * event.weekdays << 'Sat'
+ * event
+ * #=> #<data Event time="18:00", weekdays=["Tue", "Wed", "Fri", "Sat"]>
+ *
+ * See also Struct, which is a similar concept, but has more
+ * container-alike API, allowing to change contents of the object
+ * and enumerate it.
+ */
+
+/*
+ * call-seq:
+ * define(*symbols) -> class
+ *
+ * Defines a new \Data class.
+ *
+ * measure = Data.define(:amount, :unit)
+ * #=> #<Class:0x00007f70c6868498>
+ * measure.new(1, 'km')
+ * #=> #<data amount=1, unit="km">
+ *
+ * # It you store the new class in the constant, it will
+ * # affect #inspect and will be more natural to use:
+ * Measure = Data.define(:amount, :unit)
+ * #=> Measure
+ * Measure.new(1, 'km')
+ * #=> #<data Measure amount=1, unit="km">
+ *
+ *
+ * Note that member-less \Data is acceptable and might be a useful technique
+ * for defining several homogenous data classes, like
+ *
+ * class HTTPFetcher
+ * Response = Data.define(:body)
+ * NotFound = Data.define
+ * # ... implementation
+ * end
+ *
+ * Now, different kinds of responses from +HTTPFetcher+ would have consistent
+ * representation:
+ *
+ * #<data HTTPFetcher::Response body="<html...">
+ * #<data HTTPFetcher::NotFound>
+ *
+ * And are convenient to use in pattern matching:
+ *
+ * case fetcher.get(url)
+ * in HTTPFetcher::Response(body)
+ * # process body variable
+ * in HTTPFetcher::NotFound
+ * # handle not found case
+ * end
+ */
+
+static VALUE
+rb_data_s_def(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE rest;
+ long i;
+ VALUE data_class;
+ st_table *tbl;
+
+ rest = rb_ident_hash_new();
+ RBASIC_CLEAR_CLASS(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)) {
+ rb_raise(rb_eArgError, "invalid data member: %"PRIsVALUE, mem);
+ }
+ if (st_insert(tbl, mem, Qtrue)) {
+ rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
+ }
+ }
+ rest = rb_hash_keys(rest);
+ st_clear(tbl);
+ RBASIC_CLEAR_CLASS(rest);
+ OBJ_FREEZE_RAW(rest);
+ data_class = anonymous_struct(klass);
+ setup_data(data_class, rest);
+ if (rb_block_given_p()) {
+ rb_mod_module_eval(0, 0, data_class);
+ }
+
+ return data_class;
+}
+
+/*
+ * call-seq:
+ * DataClass::members -> array_of_symbols
+ *
+ * Returns an array of member names of the data class:
+ *
+ * Measure = Data.define(:amount, :unit)
+ * Measure.members # => [:amount, :unit]
+ *
+ */
+
+#define rb_data_s_members_m rb_struct_s_members_m
+
+
+/*
+ * call-seq:
+ * new(*args) -> instance
+ * new(**kwargs) -> instance
+ * ::[](*args) -> instance
+ * ::[](**kwargs) -> instance
+ *
+ * Constructors for classes defined with ::define accept both positional and
+ * keyword arguments.
+ *
+ * Measure = Data.define(:amount, :unit)
*
- * A Struct is a convenient way to bundle a number of attributes together,
- * using accessor methods, without having to write an explicit class.
+ * Measure.new(1, 'km')
+ * #=> #<data Measure amount=1, unit="km">
+ * Measure.new(amount: 1, unit: 'km')
+ * #=> #<data Measure amount=1, unit="km">
*
- * The Struct class generates new subclasses that hold a set of members and
- * their values. For each member a reader and writer method is created
- * similar to Module#attr_accessor.
+ * # Alternative shorter intialization with []
+ * Measure[1, 'km']
+ * #=> #<data Measure amount=1, unit="km">
+ * Measure[amount: 1, unit: 'km']
+ * #=> #<data Measure amount=1, unit="km">
*
- * Customer = Struct.new(:name, :address) do
- * def greeting
- * "Hello #{name}!"
+ * All arguments are mandatory (unlike Struct), and converted to keyword arguments:
+ *
+ * Measure.new(amount: 1)
+ * # in `initialize': missing keyword: :unit (ArgumentError)
+ *
+ * Measure.new(1)
+ * # in `initialize': missing keyword: :unit (ArgumentError)
+ *
+ * Note that <tt>Measure#initialize</tt> always receives keyword arguments, and that
+ * mandatory arguments are checked in +initialize+, not in +new+. This can be
+ * important for redefining initialize in order to convert arguments or provide
+ * defaults:
+ *
+ * Measure = Data.define(:amount, :unit) do
+ * NONE = Data.define
+ *
+ * def initialize(amount:, unit: NONE.new)
+ * super(amount: Float(amount), unit:)
* end
* end
*
- * dave = Customer.new("Dave", "123 Main")
- * dave.name #=> "Dave"
- * dave.greeting #=> "Hello Dave!"
+ * Measure.new('10', 'km') # => #<data Measure amount=10.0, unit="km">
+ * Measure.new(10_000) # => #<data Measure amount=10000.0, unit=#<data NONE>>
+ *
+ */
+
+static VALUE
+rb_data_initialize_m(int argc, const VALUE *argv, VALUE self)
+{
+ VALUE klass = rb_obj_class(self);
+ rb_struct_modify(self);
+ VALUE members = struct_ivar_get(klass, id_members);
+ size_t num_members = RARRAY_LEN(members);
+
+ if (argc == 0) {
+ if (num_members > 0) {
+ rb_exc_raise(rb_keyword_error_new("missing", members));
+ }
+ return Qnil;
+ }
+ if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
+ rb_error_arity(argc, 0, 0);
+ }
+
+ if (RHASH_SIZE(argv[0]) < num_members) {
+ VALUE missing = rb_ary_diff(members, rb_hash_keys(argv[0]));
+ rb_exc_raise(rb_keyword_error_new("missing", missing));
+ }
+
+ struct struct_hash_set_arg arg;
+ rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), num_members);
+ arg.self = self;
+ arg.unknown_keywords = Qnil;
+ rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
+ if (arg.unknown_keywords != Qnil) {
+ rb_exc_raise(rb_keyword_error_new("unknown", arg.unknown_keywords));
+ }
+ OBJ_FREEZE_RAW(self);
+ return Qnil;
+}
+
+/* :nodoc: */
+static VALUE
+rb_data_init_copy(VALUE copy, VALUE s)
+{
+ copy = rb_struct_init_copy(copy, s);
+ RB_OBJ_FREEZE_RAW(copy);
+ return copy;
+}
+
+/*
+ * call-seq:
+ * with(**kwargs) -> instance
+ *
+ * Returns a shallow copy of +self+ --- the instance variables of
+ * +self+ are copied, but not the objects they reference.
+ *
+ * If the method is supplied any keyword arguments, the copy will
+ * be created with the respective field values updated to use the
+ * supplied keyword argument values. Note that it is an error to
+ * supply a keyword that the Data class does not have as a member.
+ *
+ * Point = Data.define(:x, :y)
+ *
+ * origin = Point.new(x: 0, y: 0)
+ *
+ * up = origin.with(x: 1)
+ * right = origin.with(y: 1)
+ * up_and_right = up.with(y: 1)
+ *
+ * p origin # #<data Point x=0, y=0>
+ * p up # #<data Point x=1, y=0>
+ * p right # #<data Point x=0, y=1>
+ * p up_and_right # #<data Point x=1, y=1>
+ *
+ * out = origin.with(z: 1) # ArgumentError: unknown keyword: :z
+ * some_point = origin.with(1, 2) # ArgumentError: expected keyword arguments, got positional arguments
+ *
+ */
+
+static VALUE
+rb_data_with(int argc, const VALUE *argv, VALUE self)
+{
+ VALUE kwargs;
+ rb_scan_args(argc, argv, "0:", &kwargs);
+ if (NIL_P(kwargs)) {
+ return self;
+ }
+
+ VALUE copy = rb_obj_alloc(rb_obj_class(self));
+ rb_struct_init_copy(copy, self);
+
+ struct struct_hash_set_arg arg;
+ arg.self = copy;
+ arg.unknown_keywords = Qnil;
+ rb_hash_foreach(kwargs, struct_hash_set_i, (VALUE)&arg);
+ // Freeze early before potentially raising, so that we don't leave an
+ // unfrozen copy on the heap, which could get exposed via ObjectSpace.
+ RB_OBJ_FREEZE_RAW(copy);
+
+ if (arg.unknown_keywords != Qnil) {
+ rb_exc_raise(rb_keyword_error_new("unknown", arg.unknown_keywords));
+ }
+
+ return copy;
+}
+
+/*
+ * call-seq:
+ * inspect -> string
+ * to_s -> string
+ *
+ * Returns a string representation of +self+:
*
- * See Struct::new for further examples of creating struct subclasses and
- * instances.
+ * Measure = Data.define(:amount, :unit)
+ *
+ * distance = Measure[10, 'km']
+ *
+ * p distance # uses #inspect underneath
+ * #<data Measure amount=10, unit="km">
+ *
+ * puts distance # uses #to_s underneath, same representation
+ * #<data Measure amount=10, unit="km">
+ *
+ */
+
+static VALUE
+rb_data_inspect(VALUE s)
+{
+ return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<data "));
+}
+
+/*
+ * call-seq:
+ * self == other -> true or false
+ *
+ * Returns +true+ if +other+ is the same class as +self+, and all members are
+ * equal.
+ *
+ * Examples:
+ *
+ * Measure = Data.define(:amount, :unit)
+ *
+ * Measure[1, 'km'] == Measure[1, 'km'] #=> true
+ * Measure[1, 'km'] == Measure[2, 'km'] #=> false
+ * Measure[1, 'km'] == Measure[1, 'm'] #=> false
+ *
+ * Measurement = Data.define(:amount, :unit)
+ * # Even though Measurement and Measure have the same "shape"
+ * # their instances are never equal
+ * Measure[1, 'km'] == Measurement[1, 'km'] #=> false
+ */
+
+#define rb_data_equal rb_struct_equal
+
+/*
+ * call-seq:
+ * self.eql?(other) -> true or false
+ *
+ * Equality check that is used when two items of data are keys of a Hash.
+ *
+ * The subtle difference with #== is that members are also compared with their
+ * #eql? method, which might be important in some cases:
+ *
+ * Measure = Data.define(:amount, :unit)
+ *
+ * Measure[1, 'km'] == Measure[1.0, 'km'] #=> true, they are equal as values
+ * # ...but...
+ * Measure[1, 'km'].eql? Measure[1.0, 'km'] #=> false, they represent different hash keys
+ *
+ * See also Object#eql? for further explanations of the method usage.
+ */
+
+#define rb_data_eql rb_struct_eql
+
+/*
+ * call-seq:
+ * hash -> integer
+ *
+ * Redefines Object#hash (used to distinguish objects as Hash keys) so that
+ * data objects of the same class with same content would have the same +hash+
+ * value, and represented the same Hash key.
+ *
+ * Measure = Data.define(:amount, :unit)
+ *
+ * Measure[1, 'km'].hash == Measure[1, 'km'].hash #=> true
+ * Measure[1, 'km'].hash == Measure[10, 'km'].hash #=> false
+ * Measure[1, 'km'].hash == Measure[1, 'm'].hash #=> false
+ * Measure[1, 'km'].hash == Measure[1.0, 'km'].hash #=> false
+ *
+ * # Structurally similar data class, but shouldn't be considered
+ * # the same hash key
+ * Measurement = Data.define(:amount, :unit)
+ *
+ * Measure[1, 'km'].hash == Measurement[1, 'km'].hash #=> false
+ */
+
+#define rb_data_hash rb_struct_hash
+
+/*
+ * call-seq:
+ * to_h -> hash
+ * to_h {|name, value| ... } -> hash
+ *
+ * Returns Hash representation of the data object.
+ *
+ * Measure = Data.define(:amount, :unit)
+ * distance = Measure[10, 'km']
+ *
+ * distance.to_h
+ * #=> {:amount=>10, :unit=>"km"}
+ *
+ * Like Enumerable#to_h, if the block is provided, it is expected to
+ * produce key-value pairs to construct a hash:
+ *
+ *
+ * distance.to_h { |name, val| [name.to_s, val.to_s] }
+ * #=> {"amount"=>"10", "unit"=>"km"}
+ *
+ * Note that there is a useful symmetry between #to_h and #initialize:
+ *
+ * distance2 = Measure.new(**distance.to_h)
+ * #=> #<data Measure amount=10, unit="km">
+ * distance2 == distance
+ * #=> true
+ */
+
+#define rb_data_to_h rb_struct_to_h
+
+/*
+ * call-seq:
+ * members -> array_of_symbols
+ *
+ * Returns the member names from +self+ as an array:
+ *
+ * Measure = Data.define(:amount, :unit)
+ * distance = Measure[10, 'km']
+ *
+ * distance.members #=> [:amount, :unit]
+ *
+ */
+
+#define rb_data_members_m rb_struct_members_m
+
+/*
+ * call-seq:
+ * deconstruct -> array
+ *
+ * Returns the values in +self+ as an array, to use in pattern matching:
+ *
+ * Measure = Data.define(:amount, :unit)
+ *
+ * distance = Measure[10, 'km']
+ * distance.deconstruct #=> [10, "km"]
+ *
+ * # usage
+ * case distance
+ * in n, 'km' # calls #deconstruct underneath
+ * puts "It is #{n} kilometers away"
+ * else
+ * puts "Don't know how to handle it"
+ * end
+ * # prints "It is 10 kilometers away"
+ *
+ * Or, with checking the class, too:
+ *
+ * case distance
+ * in Measure(n, 'km')
+ * puts "It is #{n} kilometers away"
+ * # ...
+ * end
+ */
+
+#define rb_data_deconstruct rb_struct_to_a
+
+/*
+ * call-seq:
+ * deconstruct_keys(array_of_names_or_nil) -> hash
+ *
+ * Returns a hash of the name/value pairs, to use in pattern matching.
+ *
+ * Measure = Data.define(:amount, :unit)
+ *
+ * distance = Measure[10, 'km']
+ * distance.deconstruct_keys(nil) #=> {:amount=>10, :unit=>"km"}
+ * distance.deconstruct_keys([:amount]) #=> {:amount=>10}
+ *
+ * # usage
+ * case distance
+ * in amount:, unit: 'km' # calls #deconstruct_keys underneath
+ * puts "It is #{amount} kilometers away"
+ * else
+ * puts "Don't know how to handle it"
+ * end
+ * # prints "It is 10 kilometers away"
+ *
+ * Or, with checking the class, too:
+ *
+ * case distance
+ * in Measure(amount:, unit: 'km')
+ * puts "It is #{amount} kilometers away"
+ * # ...
+ * end
+ */
+
+#define rb_data_deconstruct_keys rb_struct_deconstruct_keys
+
+/*
+ * Document-class: Struct
+ *
+ * \Class \Struct provides a convenient way to create a simple class
+ * that can store and fetch values.
+ *
+ * This example creates a subclass of +Struct+, <tt>Struct::Customer</tt>;
+ * the first argument, a string, is the name of the subclass;
+ * the other arguments, symbols, determine the _members_ of the new subclass.
+ *
+ * Customer = Struct.new('Customer', :name, :address, :zip)
+ * Customer.name # => "Struct::Customer"
+ * Customer.class # => Class
+ * Customer.superclass # => Struct
+ *
+ * Corresponding to each member are two methods, a writer and a reader,
+ * that store and fetch values:
+ *
+ * methods = Customer.instance_methods false
+ * methods # => [:zip, :address=, :zip=, :address, :name, :name=]
+ *
+ * An instance of the subclass may be created,
+ * and its members assigned values, via method <tt>::new</tt>:
+ *
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe # => #<struct Struct::Customer name="Joe Smith", address="123 Maple, Anytown NC", zip=12345>
+ *
+ * The member values may be managed thus:
+ *
+ * joe.name # => "Joe Smith"
+ * joe.name = 'Joseph Smith'
+ * joe.name # => "Joseph Smith"
+ *
+ * And thus; note that member name may be expressed as either a string or a symbol:
+ *
+ * joe[:name] # => "Joseph Smith"
+ * joe[:name] = 'Joseph Smith, Jr.'
+ * joe['name'] # => "Joseph Smith, Jr."
+ *
+ * See Struct::new.
+ *
+ * == What's Here
+ *
+ * First, what's elsewhere. \Class \Struct:
+ *
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
+ * which provides dozens of additional methods.
+ *
+ * See also Data, which is a somewhat similar, but stricter concept for defining immutable
+ * value objects.
+ *
+ * Here, class \Struct provides methods that are useful for:
+ *
+ * - {Creating a Struct Subclass}[rdoc-ref:Struct@Methods+for+Creating+a+Struct+Subclass]
+ * - {Querying}[rdoc-ref:Struct@Methods+for+Querying]
+ * - {Comparing}[rdoc-ref:Struct@Methods+for+Comparing]
+ * - {Fetching}[rdoc-ref:Struct@Methods+for+Fetching]
+ * - {Assigning}[rdoc-ref:Struct@Methods+for+Assigning]
+ * - {Iterating}[rdoc-ref:Struct@Methods+for+Iterating]
+ * - {Converting}[rdoc-ref:Struct@Methods+for+Converting]
+ *
+ * === Methods for Creating a Struct Subclass
+ *
+ * - ::new: Returns a new subclass of \Struct.
+ *
+ * === Methods for Querying
+ *
+ * - #hash: Returns the integer hash code.
+ * - #length, #size: Returns the number of members.
+ *
+ * === Methods for Comparing
+ *
+ * - #==: Returns whether a given object is equal to +self+, using <tt>==</tt>
+ * to compare member values.
+ * - #eql?: Returns whether a given object is equal to +self+,
+ * using <tt>eql?</tt> to compare member values.
+ *
+ * === Methods for Fetching
+ *
+ * - #[]: Returns the value associated with a given member name.
+ * - #to_a, #values, #deconstruct: Returns the member values in +self+ as an array.
+ * - #deconstruct_keys: Returns a hash of the name/value pairs
+ * for given member names.
+ * - #dig: Returns the object in nested objects that is specified
+ * by a given member name and additional arguments.
+ * - #members: Returns an array of the member names.
+ * - #select, #filter: Returns an array of member values from +self+,
+ * as selected by the given block.
+ * - #values_at: Returns an array containing values for given member names.
+ *
+ * === Methods for Assigning
+ *
+ * - #[]=: Assigns a given value to a given member name.
+ *
+ * === Methods for Iterating
+ *
+ * - #each: Calls a given block with each member name.
+ * - #each_pair: Calls a given block with each member name/value pair.
+ *
+ * === Methods for Converting
+ *
+ * - #inspect, #to_s: Returns a string representation of +self+.
+ * - #to_h: Returns a hash of the member name/value pairs in +self+.
*
- * In the method descriptions that follow, a "member" parameter refers to a
- * struct member which is either a quoted string (<code>"name"</code>) or a
- * Symbol (<code>:name</code>).
*/
void
InitVM_Struct(void)
@@ -1423,6 +2221,10 @@ InitVM_Struct(void)
rb_undef_alloc_func(rb_cStruct);
rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
+#if 0 /* for RDoc */
+ rb_define_singleton_method(rb_cStruct, "keyword_init?", rb_struct_s_keyword_init_p, 0);
+ rb_define_singleton_method(rb_cStruct, "members", rb_struct_s_members_m, 0);
+#endif
rb_define_method(rb_cStruct, "initialize", rb_struct_initialize_m, -1);
rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
@@ -1452,6 +2254,34 @@ InitVM_Struct(void)
rb_define_method(rb_cStruct, "deconstruct", rb_struct_to_a, 0);
rb_define_method(rb_cStruct, "deconstruct_keys", rb_struct_deconstruct_keys, 1);
+
+ rb_cData = rb_define_class("Data", rb_cObject);
+
+ rb_undef_method(CLASS_OF(rb_cData), "new");
+ rb_undef_alloc_func(rb_cData);
+ rb_define_singleton_method(rb_cData, "define", rb_data_s_def, -1);
+
+#if 0 /* for RDoc */
+ rb_define_singleton_method(rb_cData, "members", rb_data_s_members_m, 0);
+#endif
+
+ rb_define_method(rb_cData, "initialize", rb_data_initialize_m, -1);
+ rb_define_method(rb_cData, "initialize_copy", rb_data_init_copy, 1);
+
+ rb_define_method(rb_cData, "==", rb_data_equal, 1);
+ rb_define_method(rb_cData, "eql?", rb_data_eql, 1);
+ rb_define_method(rb_cData, "hash", rb_data_hash, 0);
+
+ rb_define_method(rb_cData, "inspect", rb_data_inspect, 0);
+ rb_define_alias(rb_cData, "to_s", "inspect");
+ rb_define_method(rb_cData, "to_h", rb_data_to_h, 0);
+
+ rb_define_method(rb_cData, "members", rb_data_members_m, 0);
+
+ rb_define_method(rb_cData, "deconstruct", rb_data_deconstruct, 0);
+ rb_define_method(rb_cData, "deconstruct_keys", rb_data_deconstruct_keys, 1);
+
+ rb_define_method(rb_cData, "with", rb_data_with, -1);
}
#undef rb_intern
diff --git a/symbol.c b/symbol.c
index c515437d16..429064e43d 100644
--- a/symbol.c
+++ b/symbol.c
@@ -22,8 +22,14 @@
#include "ruby/st.h"
#include "symbol.h"
#include "vm_sync.h"
+#include "builtin.h"
+#include "ruby/internal/attr/nonstring.h"
-#ifndef USE_SYMBOL_GC
+#if defined(USE_SYMBOL_GC) && !(USE_SYMBOL_GC+0)
+# undef USE_SYMBOL_GC
+# define USE_SYMBOL_GC 0
+#else
+# undef USE_SYMBOL_GC
# define USE_SYMBOL_GC 1
#endif
#ifndef SYMBOL_DEBUG
@@ -35,7 +41,7 @@
#define SYMBOL_PINNED_P(sym) (RSYMBOL(sym)->id&~ID_SCOPE_MASK)
-#define STATIC_SYM2ID(sym) RSHIFT((unsigned long)(sym), RUBY_SPECIAL_SHIFT)
+#define STATIC_SYM2ID(sym) RSHIFT((VALUE)(sym), RUBY_SPECIAL_SHIFT)
static ID register_static_symid(ID, const char *, long, rb_encoding *);
static ID register_static_symid_str(ID, VALUE);
@@ -55,13 +61,13 @@ Init_op_tbl(void)
rb_encoding *const enc = rb_usascii_encoding();
for (i = '!'; i <= '~'; ++i) {
- if (!ISALNUM(i) && i != '_') {
- char c = (char)i;
- register_static_symid(i, &c, 1, enc);
- }
+ if (!ISALNUM(i) && i != '_') {
+ char c = (char)i;
+ register_static_symid(i, &c, 1, enc);
+ }
}
for (i = 0; i < op_tbl_count; ++i) {
- register_static_symid(op_tbl[i].token, op_tbl[i].name, op_tbl_len(i), enc);
+ register_static_symid(op_tbl[i].token, op_tbl[i].name, op_tbl_len(i), enc);
}
}
@@ -91,7 +97,7 @@ Init_sym(void)
rb_obj_hide(dsym_fstrs);
symbols->str_sym = st_init_table_with_size(&symhash, 1000);
- symbols->ids = rb_ary_tmp_new(0);
+ symbols->ids = rb_ary_hidden_new(0);
rb_gc_register_mark_object(symbols->ids);
Init_op_tbl();
@@ -116,49 +122,49 @@ rb_id_attrset(ID id)
int scope;
if (!is_notop_id(id)) {
- switch (id) {
- case tAREF: case tASET:
- return tASET; /* only exception */
- }
- rb_name_error(id, "cannot make operator ID :%"PRIsVALUE" attrset",
- rb_id2str(id));
+ switch (id) {
+ case tAREF: case tASET:
+ return tASET; /* only exception */
+ }
+ rb_name_error(id, "cannot make operator ID :%"PRIsVALUE" attrset",
+ rb_id2str(id));
}
else {
- scope = id_type(id);
- switch (scope) {
- case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
- case ID_CONST: case ID_CLASS: case ID_JUNK:
- break;
- case ID_ATTRSET:
- return id;
- default:
- {
- if ((str = lookup_id_str(id)) != 0) {
- rb_name_error(id, "cannot make unknown type ID %d:%"PRIsVALUE" attrset",
- scope, str);
- }
- else {
- rb_name_error_str(Qnil, "cannot make unknown type anonymous ID %d:%"PRIxVALUE" attrset",
- scope, (VALUE)id);
- }
- }
- }
+ scope = id_type(id);
+ switch (scope) {
+ case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
+ case ID_CONST: case ID_CLASS: case ID_JUNK:
+ break;
+ case ID_ATTRSET:
+ return id;
+ default:
+ {
+ if ((str = lookup_id_str(id)) != 0) {
+ rb_name_error(id, "cannot make unknown type ID %d:%"PRIsVALUE" attrset",
+ scope, str);
+ }
+ else {
+ rb_name_error_str(Qnil, "cannot make unknown type anonymous ID %d:%"PRIxVALUE" attrset",
+ scope, (VALUE)id);
+ }
+ }
+ }
}
/* make new symbol and ID */
if (!(str = lookup_id_str(id))) {
- static const char id_types[][8] = {
- "local",
- "instance",
- "invalid",
- "global",
- "attrset",
- "const",
- "class",
- "junk",
- };
- rb_name_error(id, "cannot make anonymous %.*s ID %"PRIxVALUE" attrset",
- (int)sizeof(id_types[0]), id_types[scope], (VALUE)id);
+ RBIMPL_ATTR_NONSTRING() static const char id_types[][8] = {
+ "local",
+ "instance",
+ "invalid",
+ "global",
+ "attrset",
+ "const",
+ "class",
+ "junk",
+ };
+ rb_name_error(id, "cannot make anonymous %.*s ID %"PRIxVALUE" attrset",
+ (int)sizeof(id_types[0]), id_types[scope], (VALUE)id);
}
str = rb_str_dup(str);
rb_str_cat(str, "=", 1);
@@ -174,21 +180,21 @@ is_special_global_name(const char *m, const char *e, rb_encoding *enc)
if (m >= e) return 0;
if (is_global_name_punct(*m)) {
- ++m;
+ ++m;
}
else if (*m == '-') {
- if (++m >= e) return 0;
- if (is_identchar(m, e, enc)) {
- if (!ISASCII(*m)) mb = 1;
- m += rb_enc_mbclen(m, e, enc);
- }
+ if (++m >= e) return 0;
+ if (is_identchar(m, e, enc)) {
+ if (!ISASCII(*m)) mb = 1;
+ m += rb_enc_mbclen(m, e, enc);
+ }
}
else {
- if (!ISDIGIT(*m)) return 0;
- do {
- if (!ISASCII(*m)) mb = 1;
- ++m;
- } while (m < e && ISDIGIT(*m));
+ if (!ISDIGIT(*m)) return 0;
+ do {
+ if (!ISASCII(*m)) mb = 1;
+ ++m;
+ } while (m < e && ISDIGIT(*m));
}
return m == e ? mb + 1 : 0;
}
@@ -217,26 +223,26 @@ rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc)
if (!MBCLEN_CHARFOUND_P(c)) return FALSE;
len = MBCLEN_CHARFOUND_LEN(c);
c = rb_enc_mbc_to_codepoint(name, end, enc);
+ if (rb_enc_isupper(c, enc)) return TRUE;
+ if (rb_enc_islower(c, enc)) return FALSE;
if (ONIGENC_IS_UNICODE(enc)) {
- static int ctype_titlecase = 0;
- if (rb_enc_isupper(c, enc)) return TRUE;
- if (rb_enc_islower(c, enc)) return FALSE;
- if (!ctype_titlecase) {
- static const UChar cname[] = "titlecaseletter";
- static const UChar *const end = cname + sizeof(cname) - 1;
- ctype_titlecase = ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, cname, end);
- }
- if (rb_enc_isctype(c, ctype_titlecase, enc)) return TRUE;
+ static int ctype_titlecase = 0;
+ if (!ctype_titlecase) {
+ static const UChar cname[] = "titlecaseletter";
+ static const UChar *const end = cname + sizeof(cname) - 1;
+ ctype_titlecase = ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, cname, end);
+ }
+ if (rb_enc_isctype(c, ctype_titlecase, enc)) return TRUE;
}
else {
- /* fallback to case-folding */
- OnigUChar fold[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
- const OnigUChar *beg = (const OnigUChar *)name;
- int r = enc->mbc_case_fold(ONIGENC_CASE_FOLD,
- &beg, (const OnigUChar *)end,
- fold, enc);
- if (r > 0 && (r != len || memcmp(fold, name, r)))
- return TRUE;
+ /* fallback to case-folding */
+ OnigUChar fold[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
+ const OnigUChar *beg = (const OnigUChar *)name;
+ int r = enc->mbc_case_fold(ONIGENC_CASE_FOLD,
+ &beg, (const OnigUChar *)end,
+ fold, enc);
+ if (r > 0 && (r != len || memcmp(fold, name, r)))
+ return TRUE;
}
return FALSE;
}
@@ -286,7 +292,7 @@ enc_synmane_type_leading_chars(const char *name, long len, rb_encoding *enc, int
}
case '<':
- switch (*++m) {
+ switch (*++m) {
default: return (t) { stophere, ID_JUNK, 1, };
case '<': return (t) { stophere, ID_JUNK, 2, };
case '=':
@@ -294,16 +300,16 @@ enc_synmane_type_leading_chars(const char *name, long len, rb_encoding *enc, int
default: return (t) { stophere, ID_JUNK, 2, };
case '>': return (t) { stophere, ID_JUNK, 3, };
}
- }
+ }
case '>':
- switch (*++m) {
+ switch (*++m) {
default: return (t) { stophere, ID_JUNK, 1, };
case '>': case '=': return (t) { stophere, ID_JUNK, 2, };
- }
+ }
case '=':
- switch (*++m) {
+ switch (*++m) {
default: return (t) { invalid, 0, 1, };
case '~': return (t) { stophere, ID_JUNK, 2, };
case '=':
@@ -311,7 +317,7 @@ enc_synmane_type_leading_chars(const char *name, long len, rb_encoding *enc, int
default: return (t) { stophere, ID_JUNK, 2, };
case '=': return (t) { stophere, ID_JUNK, 3, };
}
- }
+ }
case '*':
switch (*++m) {
@@ -339,16 +345,16 @@ enc_synmane_type_leading_chars(const char *name, long len, rb_encoding *enc, int
}
case '!':
- switch (*++m) {
+ switch (*++m) {
case '=': case '~': return (t) { stophere, ID_JUNK, 2, };
- default:
+ default:
if (allowed_attrset & (1U << ID_JUNK)) {
return (t) { needmore, ID_JUNK, 1, };
}
else {
return (t) { stophere, ID_JUNK, 1, };
}
- }
+ }
default:
if (rb_sym_constant_char_p(name, len, enc)) {
@@ -378,7 +384,7 @@ rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int a
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;
+ if (allowed_attrset & (1U << type)) return ID_ATTRSET;
}
return -1;
}
@@ -426,8 +432,8 @@ set_id_entry(rb_symbols_t *symbols, rb_id_serial_t num, VALUE str, VALUE sym)
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);
+ ary = rb_ary_hidden_new(ID_ENTRY_UNIT * ID_ENTRY_SIZE);
+ rb_ary_store(ids, (long)idx, ary);
}
idx = (num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
rb_ary_store(ary, (long)idx + ID_ENTRY_STR, str);
@@ -481,18 +487,22 @@ get_id_entry(ID id, const enum id_entry_type t)
return get_id_serial_entry(rb_id_to_serial(id), id, t);
}
+int
+rb_static_id_valid_p(ID id)
+{
+ return STATIC_ID2SYM(id) == get_id_entry(id, ID_ENTRY_SYM);
+}
+
static inline ID
-#ifdef __GNUC__
-__attribute__((unused))
-#endif
rb_id_serial_to_id(rb_id_serial_t num)
{
if (is_notop_id((ID)num)) {
VALUE sym = get_id_serial_entry(num, 0, ID_ENTRY_SYM);
- return SYM2ID(sym);
+ if (sym) return SYM2ID(sym);
+ return ((ID)num << ID_SCOPE_SHIFT) | ID_INTERNAL | ID_STATIC_SYM;
}
else {
- return (ID)num;
+ return (ID)num;
}
}
@@ -501,8 +511,8 @@ static int
register_sym_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
{
if (existing) {
- rb_fatal("symbol :% "PRIsVALUE" is already registered with %"PRIxVALUE,
- (VALUE)*key, (VALUE)*value);
+ rb_fatal("symbol :% "PRIsVALUE" is already registered with %"PRIxVALUE,
+ (VALUE)*key, (VALUE)*value);
}
*value = arg;
return ST_CONTINUE;
@@ -562,15 +572,18 @@ register_static_symid_str(ID id, VALUE str)
}
static int
-sym_check_asciionly(VALUE str)
+sym_check_asciionly(VALUE str, bool fake_str)
{
if (!rb_enc_asciicompat(rb_enc_get(str))) return FALSE;
switch (rb_enc_str_coderange(str)) {
case ENC_CODERANGE_BROKEN:
- rb_raise(rb_eEncodingError, "invalid symbol in encoding %s :%+"PRIsVALUE,
- rb_enc_name(rb_enc_get(str)), str);
+ if (fake_str) {
+ str = rb_enc_str_new(RSTRING_PTR(str), RSTRING_LEN(str), rb_enc_get(str));
+ }
+ rb_raise(rb_eEncodingError, "invalid symbol in encoding %s :%+"PRIsVALUE,
+ rb_enc_name(rb_enc_get(str)), str);
case ENC_CODERANGE_7BIT:
- return TRUE;
+ return TRUE;
}
return FALSE;
}
@@ -586,19 +599,19 @@ static inline void
must_be_dynamic_symbol(VALUE x)
{
if (UNLIKELY(!DYNAMIC_SYM_P(x))) {
- if (STATIC_SYM_P(x)) {
- VALUE str = lookup_id_str(RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT));
-
- if (str) {
- rb_bug("wrong argument: %s (inappropriate Symbol)", RSTRING_PTR(str));
- }
- else {
- rb_bug("wrong argument: inappropriate Symbol (%p)", (void *)x);
- }
- }
- else {
- rb_bug("wrong argument type %s (expected Symbol)", rb_builtin_class_name(x));
- }
+ if (STATIC_SYM_P(x)) {
+ VALUE str = lookup_id_str(RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT));
+
+ if (str) {
+ rb_bug("wrong argument: %s (inappropriate Symbol)", RSTRING_PTR(str));
+ }
+ else {
+ rb_bug("wrong argument: inappropriate Symbol (%p)", (void *)x);
+ }
+ }
+ else {
+ rb_bug("wrong argument type %s (expected Symbol)", rb_builtin_class_name(x));
+ }
}
}
#endif
@@ -632,14 +645,14 @@ 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;
+ const VALUE fstr = RSYMBOL(sym)->fstr;
+ const ID type = RSYMBOL(sym)->id & ID_SCOPE_MASK;
+ RSYMBOL(sym)->fstr = 0;
unregister_sym(symbols, fstr, sym);
return dsymbol_alloc(symbols, rb_cSymbol, fstr, rb_enc_get(fstr), type);
}
else {
- return sym;
+ return sym;
}
}
@@ -656,19 +669,19 @@ lookup_str_id(VALUE str)
GLOBAL_SYMBOLS_LEAVE();
if (found) {
- const VALUE sym = (VALUE)sym_data;
-
- if (STATIC_SYM_P(sym)) {
- return STATIC_SYM2ID(sym);
- }
- else if (DYNAMIC_SYM_P(sym)) {
- ID id = RSYMBOL(sym)->id;
- if (id & ~ID_SCOPE_MASK) return id;
- }
- else {
- rb_bug("non-symbol object %s:%"PRIxVALUE" for %"PRIsVALUE" in symbol table",
- rb_builtin_class_name(sym), sym, str);
- }
+ const VALUE sym = (VALUE)sym_data;
+
+ if (STATIC_SYM_P(sym)) {
+ return STATIC_SYM2ID(sym);
+ }
+ else if (DYNAMIC_SYM_P(sym)) {
+ ID id = RSYMBOL(sym)->id;
+ if (id & ~ID_SCOPE_MASK) return id;
+ }
+ else {
+ rb_bug("non-symbol object %s:%"PRIxVALUE" for %"PRIsVALUE" in symbol table",
+ rb_builtin_class_name(sym), sym, str);
+ }
}
return (ID)0;
}
@@ -759,14 +772,14 @@ intern_str(VALUE str, int mutable)
id = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
if (id == (ID)-1) id = ID_JUNK;
- if (sym_check_asciionly(str)) {
- if (!mutable) str = rb_str_dup(str);
- rb_enc_associate(str, rb_usascii_encoding());
+ if (sym_check_asciionly(str, false)) {
+ if (!mutable) str = rb_str_dup(str);
+ rb_enc_associate(str, rb_usascii_encoding());
}
if ((nid = next_id_base()) == (ID)-1) {
- str = rb_str_ellipsize(str, 20);
- rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %"PRIsVALUE")",
- str);
+ str = rb_str_ellipsize(str, 20);
+ rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %"PRIsVALUE")",
+ str);
}
id |= nid;
id |= ID_STATIC_SYM;
@@ -792,7 +805,7 @@ rb_intern_str(VALUE str)
VALUE sym = lookup_str_sym(str);
if (sym) {
- return SYM2ID(sym);
+ return SYM2ID(sym);
}
return intern_str(str, 0);
@@ -804,7 +817,7 @@ rb_gc_free_dsymbol(VALUE sym)
VALUE str = RSYMBOL(sym)->fstr;
if (str) {
- RSYMBOL(sym)->fstr = 0;
+ RSYMBOL(sym)->fstr = 0;
GLOBAL_SYMBOLS_ENTER(symbols);
{
@@ -839,12 +852,7 @@ VALUE
rb_str_intern(VALUE str)
{
VALUE sym;
-#if USE_SYMBOL_GC
- rb_encoding *enc, *ascii;
- int type;
-#else
- ID id;
-#endif
+
GLOBAL_SYMBOLS_ENTER(symbols);
{
sym = lookup_str_sym_with_lock(symbols, str);
@@ -852,11 +860,10 @@ rb_str_intern(VALUE 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)) {
+ else if (USE_SYMBOL_GC) {
+ rb_encoding *enc = rb_enc_get(str);
+ rb_encoding *ascii = rb_usascii_encoding();
+ if (enc != ascii && sym_check_asciionly(str, false)) {
str = rb_str_dup(str);
rb_enc_associate(str, ascii);
OBJ_FREEZE(str);
@@ -867,13 +874,13 @@ rb_str_intern(VALUE str)
OBJ_FREEZE(str);
}
str = rb_fstring(str);
- type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
+ int 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);
+ }
+ else {
+ ID id = intern_str(str, 0);
sym = ID2SYM(id);
-#endif
}
}
GLOBAL_SYMBOLS_LEAVE();
@@ -885,7 +892,7 @@ rb_sym2id(VALUE sym)
{
ID id;
if (STATIC_SYM_P(sym)) {
- id = STATIC_SYM2ID(sym);
+ id = STATIC_SYM2ID(sym);
}
else if (DYNAMIC_SYM_P(sym)) {
GLOBAL_SYMBOLS_ENTER(symbols);
@@ -903,12 +910,12 @@ rb_sym2id(VALUE sym)
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)",
- rb_builtin_class_name(sym));
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)",
+ rb_builtin_class_name(sym));
}
return id;
}
@@ -921,15 +928,26 @@ rb_id2sym(ID x)
return get_id_entry(x, ID_ENTRY_SYM);
}
+/*
+ * call-seq:
+ * name -> string
+ *
+ * Returns a frozen string representation of +self+ (not including the leading colon):
+ *
+ * :foo.name # => "foo"
+ * :foo.name.frozen? # => true
+ *
+ * Related: Symbol#to_s, Symbol#inspect.
+ */
VALUE
rb_sym2str(VALUE sym)
{
if (DYNAMIC_SYM_P(sym)) {
- return RSYMBOL(sym)->fstr;
+ return RSYMBOL(sym)->fstr;
}
else {
- return rb_id2str(STATIC_SYM2ID(sym));
+ return rb_id2str(STATIC_SYM2ID(sym));
}
}
@@ -954,6 +972,17 @@ rb_make_internal_id(void)
return next_id_base() | ID_INTERNAL | ID_STATIC_SYM;
}
+ID
+rb_make_temporary_id(size_t n)
+{
+ const ID max_id = RB_ID_SERIAL_MAX & ~0xffff;
+ const ID id = max_id - (ID)n;
+ if (id <= ruby_global_symbols.last_id) {
+ rb_raise(rb_eRuntimeError, "too big to make temporary ID: %" PRIdSIZE, n);
+ }
+ return (id << ID_SCOPE_SHIFT) | ID_STATIC_SYM | ID_INTERNAL;
+}
+
static int
symbols_i(st_data_t key, st_data_t value, st_data_t arg)
{
@@ -961,19 +990,19 @@ symbols_i(st_data_t key, st_data_t value, st_data_t arg)
VALUE sym = (VALUE)value;
if (STATIC_SYM_P(sym)) {
- rb_ary_push(ary, sym);
- return ST_CONTINUE;
+ rb_ary_push(ary, sym);
+ return ST_CONTINUE;
}
else if (!DYNAMIC_SYM_P(sym)) {
- rb_bug("invalid symbol: %s", RSTRING_PTR((VALUE)key));
+ rb_bug("invalid symbol: %s", RSTRING_PTR((VALUE)key));
}
else if (!SYMBOL_PINNED_P(sym) && rb_objspace_garbage_object_p(sym)) {
- RSYMBOL(sym)->fstr = 0;
- return ST_DELETE;
+ RSYMBOL(sym)->fstr = 0;
+ return ST_DELETE;
}
else {
- rb_ary_push(ary, sym);
- return ST_CONTINUE;
+ rb_ary_push(ary, sym);
+ return ST_CONTINUE;
}
}
@@ -1053,17 +1082,6 @@ rb_is_attrset_sym(VALUE sym)
return is_attrset_sym(sym);
}
-/**
- * Returns ID for the given name if it is interned already, or 0.
- *
- * \param namep the pointer to the name object
- * \return the ID for *namep
- * \pre the object referred by \p namep must be a Symbol or
- * a String, or possible to convert with to_str method.
- * \post the object referred by \p namep is a Symbol or a
- * String if non-zero value is returned, or is a String
- * if 0 is returned.
- */
ID
rb_check_id(volatile VALUE *namep)
{
@@ -1071,44 +1089,54 @@ rb_check_id(volatile VALUE *namep)
VALUE name = *namep;
if (STATIC_SYM_P(name)) {
- return STATIC_SYM2ID(name);
+ return STATIC_SYM2ID(name);
}
else if (DYNAMIC_SYM_P(name)) {
- if (SYMBOL_PINNED_P(name)) {
- return RSYMBOL(name)->id;
- }
- else {
- *namep = RSYMBOL(name)->fstr;
- return 0;
- }
+ if (SYMBOL_PINNED_P(name)) {
+ return RSYMBOL(name)->id;
+ }
+ else {
+ *namep = RSYMBOL(name)->fstr;
+ return 0;
+ }
}
else if (!RB_TYPE_P(name, T_STRING)) {
- tmp = rb_check_string_type(name);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
- name);
- }
- name = tmp;
- *namep = name;
+ tmp = rb_check_string_type(name);
+ if (NIL_P(tmp)) {
+ rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
+ name);
+ }
+ name = tmp;
+ *namep = name;
}
- sym_check_asciionly(name);
+ sym_check_asciionly(name, false);
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.
- */
+// Used by yjit for handling .send without throwing exceptions
+ID
+rb_get_symbol_id(VALUE name)
+{
+ if (STATIC_SYM_P(name)) {
+ return STATIC_SYM2ID(name);
+ }
+ else if (DYNAMIC_SYM_P(name)) {
+ if (SYMBOL_PINNED_P(name)) {
+ return RSYMBOL(name)->id;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ RUBY_ASSERT_ALWAYS(RB_TYPE_P(name, T_STRING));
+ return lookup_str_id(name);
+ }
+}
+
+
VALUE
rb_check_symbol(volatile VALUE *namep)
{
@@ -1117,10 +1145,10 @@ rb_check_symbol(volatile VALUE *namep)
VALUE name = *namep;
if (STATIC_SYM_P(name)) {
- return name;
+ return name;
}
else if (DYNAMIC_SYM_P(name)) {
- if (!SYMBOL_PINNED_P(name)) {
+ if (!SYMBOL_PINNED_P(name)) {
GLOBAL_SYMBOLS_ENTER(symbols);
{
name = dsymbol_check(symbols, name);
@@ -1128,23 +1156,23 @@ rb_check_symbol(volatile VALUE *namep)
GLOBAL_SYMBOLS_LEAVE();
*namep = name;
- }
- return name;
+ }
+ return name;
}
else if (!RB_TYPE_P(name, T_STRING)) {
- tmp = rb_check_string_type(name);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
- name);
- }
- name = tmp;
- *namep = name;
+ tmp = rb_check_string_type(name);
+ if (NIL_P(tmp)) {
+ rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
+ name);
+ }
+ name = tmp;
+ *namep = name;
}
- sym_check_asciionly(name);
+ sym_check_asciionly(name, false);
if ((sym = lookup_str_sym(name)) != 0) {
- return sym;
+ return sym;
}
return Qnil;
@@ -1156,7 +1184,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
struct RString fake_str;
const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
- sym_check_asciionly(name);
+ sym_check_asciionly(name, true);
return lookup_str_id(name);
}
@@ -1168,10 +1196,10 @@ rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
struct RString fake_str;
const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
- sym_check_asciionly(name);
+ sym_check_asciionly(name, true);
if ((sym = lookup_str_sym(name)) != 0) {
- return sym;
+ return sym;
}
return Qnil;
@@ -1237,3 +1265,4 @@ rb_is_local_name(VALUE name)
}
#include "id_table.c"
+#include "symbol.rbinc"
diff --git a/symbol.h b/symbol.h
index e2710ba61b..ffbf7ce198 100644
--- a/symbol.h
+++ b/symbol.h
@@ -20,7 +20,7 @@
#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
#define rb_id2sym(id) \
RB_GNUC_EXTENSION_BLOCK(__builtin_constant_p(id) && !DYNAMIC_ID_P(id) ? \
- STATIC_ID2SYM(id) : rb_id2sym(id))
+ STATIC_ID2SYM(id) : rb_id2sym(id))
#endif
struct RSymbol {
@@ -45,10 +45,10 @@ static inline int
id_type(ID id)
{
if (is_notop_id(id)) {
- return (int)(id&ID_SCOPE_MASK);
+ return (int)(id&ID_SCOPE_MASK);
}
else {
- return -1;
+ return -1;
}
}
@@ -69,10 +69,10 @@ static inline rb_id_serial_t
rb_id_to_serial(ID id)
{
if (is_notop_id(id)) {
- return (rb_id_serial_t)(id >> ID_SCOPE_SHIFT);
+ return (rb_id_serial_t)(id >> ID_SCOPE_SHIFT);
}
else {
- return (rb_id_serial_t)id;
+ return (rb_id_serial_t)id;
}
}
@@ -81,13 +81,13 @@ sym_type(VALUE sym)
{
ID id;
if (STATIC_SYM_P(sym)) {
- id = RSHIFT(sym, RUBY_SPECIAL_SHIFT);
- if (id<=tLAST_OP_ID) {
- return -1;
- }
+ id = RSHIFT(sym, RUBY_SPECIAL_SHIFT);
+ if (id<=tLAST_OP_ID) {
+ return -1;
+ }
}
else {
- id = RSYMBOL(sym)->id;
+ id = RSYMBOL(sym)->id;
}
return (int)(id&ID_SCOPE_MASK);
}
diff --git a/symbol.rb b/symbol.rb
new file mode 100644
index 0000000000..0b23ebb267
--- /dev/null
+++ b/symbol.rb
@@ -0,0 +1,15 @@
+class Symbol
+ # call-seq:
+ # to_sym -> self
+ #
+ # Returns +self+.
+ #
+ # Symbol#intern is an alias for Symbol#to_sym.
+ #
+ # Related: String#to_sym.
+ def to_sym
+ self
+ end
+
+ alias intern to_sym
+end
diff --git a/template/Doxyfile.tmpl b/template/Doxyfile.tmpl
index 4f6c432871..502e171384 100644
--- a/template/Doxyfile.tmpl
+++ b/template/Doxyfile.tmpl
@@ -1,4 +1,18 @@
-# Doxyfile 1.5.7
+# Doxyfile 1.9.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
<%
srcdir = miniruby = nil
opt = OptionParser.new do |o|
@@ -15,290 +29,2659 @@ end
dot = RbConfig::CONFIG['DOT'] || ""
have_dot = dot.empty? ? "NO" : "YES"
%>
+
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-PROJECT_NAME = Ruby
-PROJECT_NUMBER = <%=RUBY_VERSION%><%= RUBY_PATCHLEVEL < 0 ? 'dev' : "p#{RUBY_PATCHLEVEL}" %> (<%=RUBY_RELEASE_DATE%> revision <%=RUBY_REVISION%>)
-STRIP_FROM_PATH = <%=srcdir%>
-FILE_VERSION_FILTER = "<%=miniruby%> <%=srcdir%>/tool/file2lastrev.rb -q --srcdir=<%=srcdir%>"
-INPUT = <%=srcdir%> .
-INPUT_FILTER = "<%=miniruby%> <%=srcdir%>/tool/strip-rdoc.rb"
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = Ruby
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = "<%=RUBY_VERSION%><%= RUBY_PATCHLEVEL < 0 ? 'dev' : "p#{RUBY_PATCHLEVEL}" %> (<%=RUBY_RELEASE_DATE%> revision <%=RUBY_REVISION%>)"
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
OUTPUT_DIRECTORY = doc/capi
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
CREATE_SUBDIRS = YES
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH = <%=srcdir%>
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
JAVADOC_AUTOBRIEF = YES
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
QT_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
ALIASES =
+ALIASES += "alias{1}=Just another name of @ref \1"
+ALIASES += "old{1}=Old name of @ref \1.^^@deprecated Use @ref \1 instead.^^@ingroup deprecated_macros"
+ALIASES += "shyouhei=\@shyouhei"
+ALIASES += "ko1=\@ko1"
+ALIASES += "matz=\@matz"
+ALIASES += "shugo=\@shugo"
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
TYPEDEF_HIDES_STRUCT = NO
-SYMBOL_CACHE_SIZE = 0
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-EXTRACT_ALL = YES
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
EXTRACT_PRIVATE = NO
-EXTRACT_STATIC = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
EXTRACT_ANON_NSPACES = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
HIDE_IN_BODY_DOCS = YES
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
INTERNAL_DOCS = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# The default value is: system dependent.
+
CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER = "<%=miniruby%> <%=srcdir%>/tool/file2lastrev.rb -q --srcdir=<%=srcdir%>"
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
WARN_IF_DOC_ERROR = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
WARN_LOGFILE =
+
#---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT =
+INPUT += <%=srcdir%>
+INPUT += .
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# The default value is: UTF-8.
+
INPUT_ENCODING = UTF-8
-FILE_PATTERNS = *.c *.h *.hpp *.y *.def
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS =
+FILE_PATTERNS += *.c
+FILE_PATTERNS += *.h
+FILE_PATTERNS += *.hpp
+FILE_PATTERNS += *.y
+FILE_PATTERNS +=*.def
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
RECURSIVE = YES
-EXCLUDE = <%=srcdir%>/ext/dl/callback <%=srcdir%>/ccan <%=srcdir%>/ext/psych/yaml
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+EXCLUDE += <%=srcdir%>/ccan
+EXCLUDE += <%=srcdir%>/ext
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
EXCLUDE_SYMLINKS = YES
-EXCLUDE_PATTERNS = *.src doc enc build */ext/-test-/* tmp test yarvtest lib bootstraptest spec .ext .git .svn extconf.h *prelude.c encdb.h transdb.h insns.def rb_mjit_header.h
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS += *.src
+EXCLUDE_PATTERNS += *prelude.c
+EXCLUDE_PATTERNS += .ext
+EXCLUDE_PATTERNS += .git
+EXCLUDE_PATTERNS += .svn
+EXCLUDE_PATTERNS += bootstraptest
+EXCLUDE_PATTERNS += build
+EXCLUDE_PATTERNS += doc
+EXCLUDE_PATTERNS += enc
+EXCLUDE_PATTERNS += encdb.h
+EXCLUDE_PATTERNS += extconf.h
+EXCLUDE_PATTERNS += insns.def
+EXCLUDE_PATTERNS += lib
+EXCLUDE_PATTERNS += rb_mjit_header.h
+EXCLUDE_PATTERNS += spec
+EXCLUDE_PATTERNS += test
+EXCLUDE_PATTERNS += tmp
+EXCLUDE_PATTERNS += transdb.h
+EXCLUDE_PATTERNS += yarvtest
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
IMAGE_PATH = <%=srcdir%>/doc/images
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER = "<%=miniruby%> <%=srcdir%>/tool/strip-rdoc.rb"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
FILTER_SOURCE_FILES = YES
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
#---------------------------------------------------------------------------
-# configuration options related to source browsing
+# Configuration options related to source browsing
#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
REFERENCED_BY_RELATION = YES
-REFERENCES_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
VERBATIM_HEADERS = YES
+
#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-COLS_IN_ALPHA_INDEX = 5
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
IGNORE_PREFIX =
+
#---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
DISABLE_INDEX = NO
-ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
GENERATE_TREEVIEW = NO
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATOR_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH =
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
+# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
COMPACT_LATEX = NO
-PAPER_TYPE = a4wide
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
LATEX_HIDE_INDICES = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
-# configuration options related to the RTF output
+# Configuration options related to the RTF output
#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
RTF_EXTENSIONS_FILE =
+
#---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
MAN_LINKS = NO
+
#---------------------------------------------------------------------------
-# configuration options related to the XML output
+# Configuration options related to the XML output
#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
XML_OUTPUT = xml
-XML_SCHEMA =
-XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
XML_PROGRAMLISTING = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
+# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
GENERATE_AUTOGEN_DEF = NO
+
#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
+# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
PERLMOD_MAKEVAR_PREFIX =
+
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
SEARCH_INCLUDES = YES
-INCLUDE_PATH = <%=srcdir%> <%=srcdir%>/include
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+INCLUDE_PATH += <%=srcdir%>
+INCLUDE_PATH += <%=srcdir%>/include
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
INCLUDE_FILE_PATTERNS =
-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
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+PREDEFINED += ALWAYS_INLINE(_)=_
+PREDEFINED += COLDFUNC=
+PREDEFINED += CONSTFUNC(_)=_
+PREDEFINED += DEPRECATED(_)=_
+PREDEFINED += DEPRECATED_BY(__,_)=_
+PREDEFINED += ENUM_OVER_INT=1
+PREDEFINED += ERRORFUNC(__,_)=_
+PREDEFINED += MJIT_FUNC_EXPORTED=
+PREDEFINED += MJIT_STATIC=extern
+PREDEFINED += MJIT_SYMBOL_EXPORT_BEGIN=
+PREDEFINED += MJIT_SYMBOL_EXPORT_END=
+PREDEFINED += NOINLINE(_)=_
+PREDEFINED += NORETURN(_)=_
+PREDEFINED += PACKED_STRUCT_UNALIGNED(_)=_
+PREDEFINED += PRINTF_ARGS(_,__,___)=_
+PREDEFINED += PUREFUNC(_)=_
+PREDEFINED += RB_UNUSED_VAR(_)=_
+PREDEFINED += RUBY_EXTERN=extern
+PREDEFINED += RUBY_FUNC_EXPORTED=
+PREDEFINED += RUBY_FUNC_NONNULL(__,_)=_
+PREDEFINED += RUBY_SYMBOL_EXPORT_BEGIN=
+PREDEFINED += RUBY_SYMBOL_EXPORT_END=
+PREDEFINED += WARNINGFUNC(__,_)=_
+PREDEFINED += _MSC_VER=1924
+PREDEFINED += __DOXYGEN__
+PREDEFINED += __GNUC_MINOR__=0
+PREDEFINED += __GNUC_PATCHLEVEL__=0
+PREDEFINED += __GNUC__=10
+PREDEFINED += __STDC_VERSION__=201710L
+PREDEFINED += __clang__=10
+PREDEFINED += __clang_major__=10
+PREDEFINED += __clang_minor__=0
+PREDEFINED += __clang_patchlevel__=0
+PREDEFINED += __cplusplus=201704L
+PREDEFINED += __has_attribute(_)=1
+PREDEFINED += __has_builtin(_)=1
+PREDEFINED += __has_c_attribute(_)=1
+PREDEFINED += __has_cpp_attribute(_)=1
+PREDEFINED += __has_declspec_attribute(_)=1
+PREDEFINED += __has_extension(_)=1
+PREDEFINED += __has_feature(_)=1
+PREDEFINED += __has_warning(_)=1
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED += RBIMPL_FL_USER_N
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
SKIP_FUNCTION_MACROS = YES
+
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration options related to external references
#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
EXTERNAL_GROUPS = YES
-PERL_PATH = /usr/bin/perl
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-CLASS_DIAGRAMS = NO
-MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
HAVE_DOT = <%= have_dot %>
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
+# The default value is: YES.
+
CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DIRECTORY_GRAPH = NO
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOTFILE_DIRS =
-DOT_GRAPH_MAX_NODES = 50
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 128
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
DOT_CLEANUP = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-SEARCHENGINE = NO
diff --git a/template/GNUmakefile.in b/template/GNUmakefile.in
index e2f2d1aebd..4db4467905 100644
--- a/template/GNUmakefile.in
+++ b/template/GNUmakefile.in
@@ -12,6 +12,23 @@ ifeq ($(HAVE_BASERUBY),yes)
override REVISION_FORCE := PHONY
endif
+override order_only := |
+
+ifneq ($(filter notintermediate,$(.FEATURES)),)
+DOT_WAIT = .WAIT
+endif
+
+# Needs the dependency when any Unicode tables data files exist.
+override UNICODE_TABLES_DEPENDENTS = \
+ $(if $(or \
+ $(filter yes,$(ALWAYS_UPDATE_UNICODE)), \
+ $(wildcard \
+ $(if $(filter .,$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)),,\
+ $(UNICODE_TABLES_DATA_FILES)))),\
+ force,none)
+
include $(srcdir)/defs/universal.mk
-include uncommon.mk
include $(srcdir)/defs/gmake.mk
+
+GNUmakefile: $(srcdir)/template/GNUmakefile.in
diff --git a/template/Makefile.in b/template/Makefile.in
index c382159da5..e189d88c3f 100644
--- a/template/Makefile.in
+++ b/template/Makefile.in
@@ -27,6 +27,8 @@ CC_WRAPPER = @XCC_WRAPPER@
CC = @CC@
CPP = @CPP@
LD = @LD@
+RUSTC = @RUSTC@
+CARGO = @CARGO@
YACC = bison
PURIFY =
AUTOCONF = autoconf
@@ -47,6 +49,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
datarootdir = @datarootdir@
datadir = @datadir@
+target_os = @target_os@
arch = @arch@
sitearch = @sitearch@
sitedir = @sitedir@
@@ -86,7 +89,10 @@ optflags = @optflags@
debugflags = @debugflags@
warnflags = @warnflags@ @strict_warnflags@
cppflags = @cppflags@
-XCFLAGS = @XCFLAGS@ $(INCFLAGS)
+incflags = @incflags@
+RUBY_DEVEL = @RUBY_DEVEL@ # "yes" or empty
+_RUBY_DEVEL_enabled = $(RUBY_DEVEL:no=)
+XCFLAGS = @XCFLAGS@ $(INCFLAGS) $(_RUBY_DEVEL_enabled:yes=-DRUBY_DEVEL=1)
USE_RUBYGEMS = @USE_RUBYGEMS@
USE_RUBYGEMS_ = $(USE_RUBYGEMS:yes=)
CPPFLAGS = @CPPFLAGS@ $(USE_RUBYGEMS_:no=-DDISABLE_RUBYGEMS=1)
@@ -106,6 +112,11 @@ 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@
+YJIT_SUPPORT=@YJIT_SUPPORT@
+YJIT_LIBS=@YJIT_LIBS@
+YJIT_OBJ=@YJIT_OBJ@
+CARGO_TARGET_DIR=@abs_top_builddir@/yjit/target
+CARGO_BUILD_ARGS=@CARGO_BUILD_ARGS@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
EXE_LDFLAGS = $(LDFLAGS)
EXTLDFLAGS = @EXTLDFLAGS@
@@ -120,7 +131,7 @@ XDLDFLAGS = @DLDFLAGS@
DLDFLAGS = @LIBRUBY_DLDFLAGS@ $(XLDFLAGS) $(ARCH_FLAG)
SOLIBS = @SOLIBS@
ENABLE_DEBUG_ENV = @ENABLE_DEBUG_ENV@
-MAINLIBS = @MAINLIBS@
+MAINLIBS = $(YJIT_LIBS) @MAINLIBS@
ARCHMINIOBJS = @MINIOBJS@
DLNOBJ = @DLNOBJ@
ENCOBJS = @ENCOBJS@
@@ -130,6 +141,9 @@ BUILTIN_TRANSSRCS = @BUILTIN_TRANSSRCS@
BUILTIN_TRANSOBJS = @BUILTIN_TRANSOBJS@
POSTLINK = @POSTLINK@
+LIBPATHENV = @LIBPATHENV@
+PRELOADENV = @PRELOADENV@
+
RUBY_BASE_NAME=@RUBY_BASE_NAME@
RUBY_API_VERSION=@RUBY_API_VERSION@
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
@@ -147,8 +161,7 @@ RUNRUBY = @RUNRUBY@ $(RUN_OPTS)
# RUNRUBY_DEBUGGER:: debugging option for runruby.rb
RUNRUBY_DEBUGGER = --debugger='gdb -x run.gdb --quiet --args'
XRUBY = @XRUBY@
-BTESTRUBY = @BTESTRUBY@\
- $(MINIRUBYOPT)
+BTESTRUBY = @BTESTRUBY@ -r./$(arch)-fake
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
@@ -156,10 +169,15 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
XRUBY_LIBDIR = @XRUBY_LIBDIR@
XRUBY_RUBYLIBDIR = @XRUBY_RUBYLIBDIR@
XRUBY_RUBYHDRDIR = @XRUBY_RUBYHDRDIR@
-BOOTSTRAPRUBY = @BOOTSTRAPRUBY@
+
+yes_baseruby = $(HAVE_BASERUBY:no=)
+no_baseruby = $(HAVE_BASERUBY:yes=)
+BOOTSTRAPRUBY = $(yes_baseruby:yes=$(BASERUBY)) $(no_baseruby:no=$(MINIRUBY))
+BOOTSTRAPRUBY_OPT = $(yes_baseruby:yes=-r./$(arch)-fake)
+BOOTSTRAPRUBY_FAKE = $(yes_baseruby:yes=$(arch)-fake.rb)
COROUTINE_H = @X_COROUTINE_H@
-COROUTINE_OBJ = $(COROUTINE_H:.h=.@OBJEXT@)
+COROUTINE_OBJ = $(COROUTINE_H:.h=.$(OBJEXT))
COROUTINE_SRC = @X_COROUTINE_SRC@
#### End of system configuration section. ####
@@ -193,7 +211,8 @@ DTRACE_DEPENDENT_OBJS = array.$(OBJEXT) \
parse.$(OBJEXT) \
string.$(OBJEXT) \
symbol.$(OBJEXT) \
- vm.$(OBJEXT)
+ vm.$(OBJEXT) \
+ $(YJIT_OBJ)
THREAD_MODEL = @THREAD_MODEL@
@@ -208,10 +227,12 @@ MAKEDIRS = @MKDIR_P@
CP = cp
MV = mv
RM = rm -f
+RM1 = $(RM)
RMDIR = @RMDIR@
RMDIRS = @RMDIRS@
RMALL = @RMALL@
LN_S = @LN_S@
+TOUCH = touch
NM = @NM@
AR = @AR@
ARFLAGS = @ARFLAGS@$(empty)
@@ -245,7 +266,7 @@ MINIPRELUDE_C = miniprelude.c
GOLF_PRELUDE_C= golf_prelude.c
RBCONFIG = .rbconfig.time
-MAINSRC = $(MAINOBJ:.@OBJEXT@=.c)
+MAINSRC = $(MAINOBJ:.$(OBJEXT)=.c)
SRC_FILE = $<
OS_SRC_FILE = $<
@@ -265,6 +286,10 @@ DESTDIR = @DESTDIR@
configure_args = @configure_args@
#### End of variables
+ABI_VERSION_HDR = $(hdrdir)/ruby/internal/abi.h
+
+CAT_DEPEND = sed -e 's/{\$$([^(){}]*)[^{}]*}//g' -e /AUTOGENERATED/q
+
.SUFFIXES: .inc .h .c .y .i .$(ASMEXT) .$(DTRACE_EXT)
all:
@@ -284,16 +309,30 @@ $(PROGRAM):
$(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@
$(Q) $(POSTLINK)
+$(PROGRAM): @XRUBY_LIBPATHENV_WRAPPER@
+
PRE_LIBRUBY_UPDATE = [ -n "$(LIBRUBY_SO_UPDATE)" ] || $(gnumake:yes=exec) $(RM) $(LIBRUBY_EXTS)
# We must `rm' the library each time this rule is invoked because "updating" a
# MAB library on Apple/NeXT (see --enable-fat-binary in configure) is not
# supported.
+#
+# In YJIT builds, merge libyjit.a with libruby_static.a
$(LIBRUBY_A):
@$(RM) $@
@-[ -z "$(EXTSTATIC)" ] || $(PRE_LIBRUBY_UPDATE)
$(ECHO) linking static-library $@
$(Q) $(AR) $(ARFLAGS) $@ $(LIBRUBY_A_OBJS) $(INITOBJS)
+ $(Q) if [ 'no' != '$(YJIT_SUPPORT)' ]; then \
+ set -eu$(V0:1=x) && \
+ $(ECHO0) 'merging $(YJIT_LIBS) into $@' && \
+ $(RMALL) libyjit/ && \
+ $(MAKEDIRS) libyjit/ && \
+ trap "$(RMALL) libyjit/" 0 && \
+ (cd libyjit/ && $(AR) -x ../$(YJIT_LIBS)) && \
+ : "$(AR) $(ARFLAGS) $@ libyjit/*.$(OBJEXT)" && \
+ find libyjit/ -name '*.$(OBJEXT)' -exec $(AR) $(ARFLAGS) $@ '{}' '+' ; \
+ fi
@-$(RANLIB) $@ 2> /dev/null || true
verify-static-library: $(LIBRUBY_A)
@@ -315,20 +354,23 @@ $(LIBRUBY_SO):
LIBRUBY_WITH_EXT = @LIBRUBY_WITH_EXT@
$(LIBRUBY_$(LIBRUBY_WITH_EXT)): $(LIBRUBY_SO_UPDATE)
+PKG_CONFIG = @PKG_CONFIG@
ruby_pc = @ruby_pc@
-ruby.pc: $(ruby_pc)
-$(ruby_pc): config.status
- @./config.status --file=$@:$(srcdir)/template/ruby.pc.in
+$(ruby_pc): config.status Makefile
+ $(Q)./config.status --file=-:$(srcdir)/template/ruby.pc.in | \
+ sed -e 's/\$$(\([A-Za-z_][A-Za-z0-9_]*\))/$${\1}/g' \
+ -e 's|^prefix=.*|prefix=$(prefix)|' \
+ > ruby.tmp.pc
+ $(Q)pkg_config=${PKG_CONFIG} && PKG_CONFIG_PATH=. $${pkg_config:-:} --print-errors ruby.tmp
+ $(Q)$(MV) -f ruby.tmp.pc $(ruby_pc)
+
+pre-install-local:: pkgconfig-data
ruby-runner.h: template/ruby-runner.h.in config.status
@./config.status --file=$@:$(srcdir)/template/$(@F).in
-$(RBCONFIG): $(PREP)
-
-rbconfig.rb: $(RBCONFIG)
-
install-cross: $(arch)-fake.rb $(RBCONFIG) rbconfig.rb $(arch_hdrdir)/ruby/config.h \
- $(LIBRUBY_A) $(LIBRUBY_SO) $(ARCHFILE)
+ $(LIBRUBY_A) $(LIBRUBY_SO) $(ARCHFILE) pkgconfig-data
$(ECHO) installing cross-compiling stuff
$(Q) $(MAKEDIRS) $(XRUBY_RUBYLIBDIR)/$(arch) $(XRUBY_RUBYHDRDIR)/$(arch)/ruby
$(Q) sed '/^\$$:\.unshift/q' $(arch)-fake.rb > fake.rb
@@ -346,7 +388,7 @@ install-cross: $(arch)-fake.rb $(RBCONFIG) rbconfig.rb $(arch_hdrdir)/ruby/confi
Makefile: $(srcdir)/template/Makefile.in $(srcdir)/enc/Makefile.in
-$(MKFILES): config.status $(srcdir)/version.h
+$(MKFILES): config.status $(srcdir)/version.h $(REVISION_H) $(ABI_VERSION_HDR)
@[ -f $@ ] && mv $@ $@.old
MAKE=$(MAKE) $(SHELL) ./config.status $@
@cmp $@ $@.old > /dev/null 2>&1 && echo $@ unchanged && exit 0; \
@@ -364,13 +406,14 @@ uncommon.mk: $(srcdir)/common.mk
.PHONY: reconfig
reconfig-args = $(srcdir)/$(CONFIGURE) $(yes_silence:yes=--silent) $(configure_args)
config.status-args = ./config.status $(yes_silence:yes=--silent) --recheck
-reconfig-exec-0 = test -t 1 && { : $${CONFIGURE_TTY=yes}; export CONFIGURE_TTY; }; exec 3>&1; exit `exec 4>&1; { "$$@" 3>&- 4>&-; echo $$? 1>&4; } | fgrep -v '(cached)' 1>&3 3>&- 4>&-`
-reconfig-exec-1 = set -x; "$$@"
+reconfig-exec-0 = test -t 1 && { : $${CONFIGURE_TTY=yes}; export CONFIGURE_TTY; }; exec 3>&1; exit `exec 4>&1; { "$$@" 3>&- 4>&-; echo $$? 1>&4; } | grep -F -v '(cached)' 1>&3 3>&- 4>&-`
+reconfig-exec-1 = set -x; exec "$$@"
+reconfig-exec-yes = $(reconfig-exec-1)
reconfig config.status: $(srcdir)/$(CONFIGURE) $(srcdir)/enc/Makefile.in \
- $(srcdir)/include/ruby/version.h
+ $(hdrdir)/ruby/version.h $(ABI_VERSION_HDR)
@PWD= MINIRUBY="$(MINIRUBY)"; export MINIRUBY; \
- set $(SHELL) $($@-args); $(reconfig-exec-$(V))
+ set $(SHELL) $($@-args); $(reconfig-exec-$(silence:no=$(V)))
$(srcdir)/$(CONFIGURE): $(srcdir)/configure.ac
$(CHDIR) $(srcdir) && exec $(AUTOCONF) -o $(@F)
@@ -384,7 +427,6 @@ all-incs: probes.h
# * with gperf v.s. without gperf
# * committers may have various versions of gperf
# * ./configure v.s. ../ruby/configure
-# * GNU make v.s. HP-UX make # HP-UX make invokes the action if lex.c and keywords has same mtime.
# * svn checkout generate a file with mtime as current time
# * ext4 and XFS has a mtime with fractional part
lex.c: defs/keywords
@@ -418,11 +460,11 @@ $(srcdir)/enc/jis/props.h: enc/jis/props.kwd
$(CP) $@ $(?:.kwd=.h.blt); \
fi
-.c.@OBJEXT@:
+.c.$(OBJEXT):
@$(ECHO) compiling $<
$(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $<
-.$(ASMEXT).@OBJEXT@:
+.$(ASMEXT).$(OBJEXT):
@$(ECHO) assembling $<
$(Q) $(CC) $(ASFLAGS) -DSYMBOL_PREFIX=$(SYMBOL_PREFIX) -o $@ -c $<
@@ -470,7 +512,7 @@ clean-local::
-$(Q) $(RMDIRS) $(MJIT_HEADER_INSTALL_DIR) $(MJIT_HEADER_BUILD_DIR) $(TIMESTAMPDIR) 2> $(NULL) || $(NULLCMD)
# DTrace static library hacks described here:
-# http://mail.opensolaris.org/pipermail/dtrace-discuss/2005-August/000207.html
+# https://marc.info/?l=opensolaris-dtrace-discuss&m=114761203110734&w=4
ruby-glommed.$(OBJEXT):
@$(ECHO) generating a glommed object with DTrace probes for static library
$(Q) $(LD) -r -o $@ $(OBJS)
@@ -481,6 +523,7 @@ clean-local::
enc/encinit.c enc/encinit.$(OBJEXT) $(pkgconfig_DATA) \
ruby-runner.$(OBJEXT) ruby-runner.h \
|| $(NULLCMD)
+ $(Q)find . \( -name '*.bc' -o -name '*.[is]' \) -delete
-$(Q)$(RMALL) exe/ *.dSYM
distclean-local::
@@ -500,12 +543,16 @@ ext/clean.mk ext/distclean.mk ext/realclean.mk::
ext/clean:: ext/clean.sub
ext/distclean:: ext/distclean.sub
ext/realclean:: ext/realclean.sub
-gems/clean:: gems/clean.sub
-gems/distclean:: gems/distclean.sub
-gems/realclean:: gems/realclean.sub
+.bundle/clean:: .bundle/clean.sub
+.bundle/distclean:: .bundle/distclean.sub
+.bundle/realclean:: .bundle/realclean.sub
+
+ext/clean.sub .bundle/clean.sub:: ext/clean.mk
+ext/distclean.sub .bundle/distclean.sub:: ext/distclean.mk
+ext/realclean.sub .bundle/realclean.sub:: ext/realclean.mk
ext/clean.sub ext/distclean.sub ext/realclean.sub \
-gems/clean.sub gems/distclean.sub gems/realclean.sub::
+.bundle/clean.sub .bundle/distclean.sub .bundle/realclean.sub::
$(Q) set dummy `echo "${EXTS}" | tr , ' '`; shift; \
test "$$#" = 0 && set .; \
set dummy `\
@@ -521,7 +568,7 @@ gems/clean.sub gems/distclean.sub gems/realclean.sub::
fi; \
done || true
-ext/distclean ext/realclean gems/distclean gems/realclean::
+ext/distclean ext/realclean .bundle/distclean .bundle/realclean::
$(Q) set dummy `echo "${EXTS}" | tr , ' '`; shift; \
test "$$#" = 0 && set .; \
cd $(@D) 2>/dev/null && \
@@ -581,7 +628,7 @@ update-known-errors:
$(IFCHANGE) $(srcdir)/defs/known_errors.def -
INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \
- vmtc.inc vm.inc mjit_compile.inc
+ vmtc.inc vm.inc mjit_sp_inc.inc
$(INSNS): $(srcdir)/insns.def vm_opts.h \
$(srcdir)/defs/opt_operand.def $(srcdir)/defs/opt_insn_unif.def \
@@ -615,17 +662,12 @@ $(INSNS): $(srcdir)/insns.def vm_opts.h \
$(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/mjit_sp_inc.inc.erb \
$(tooldir)/ruby_vm/views/opt_sc.inc.erb \
$(tooldir)/ruby_vm/views/optinsn.inc.erb \
$(tooldir)/ruby_vm/views/optunifs.inc.erb \
@@ -634,8 +676,6 @@ $(INSNS): $(srcdir)/insns.def vm_opts.h \
$(ECHO) generating $@
$(Q) $(BASERUBY) -Ku $(tooldir)/insns2vm.rb $(INSNS2VMOPT) $@
-verconf.h: $(RBCONFIG)
-
loadpath: verconf.h
@$(CPP) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/loadpath.c | \
sed -e '1,/^const char ruby_initial_load_paths/d;/;/,$$d' \
diff --git a/template/extinit.c.tmpl b/template/extinit.c.tmpl
index 7a9c910633..e0b076b03c 100644
--- a/template/extinit.c.tmpl
+++ b/template/extinit.c.tmpl
@@ -1,5 +1,5 @@
%# -*- C -*-
-% extinits = ARGV.map {|n| [n[%r[[^/.]+(?=\.[^/]*)?\z]], n]}
+% extinits = ARGV.map {|n| [n.tr('/', '_'), n]}
#include "ruby/ruby.h"
#define init(func, name) { \
diff --git a/template/exts.mk.tmpl b/template/exts.mk.tmpl
index 924abeb2fb..5595a08da1 100644
--- a/template/exts.mk.tmpl
+++ b/template/exts.mk.tmpl
@@ -19,18 +19,17 @@ opt = OptionParser.new do |o|
o.on('--configure-exts=FILE') {|v| confexts = v}
o.order!(ARGV)
end
-confexts &&= File.read(confexts).scan(/^exts: (.*\.mk)/).flatten rescue nil
+confexts &&= File.read(confexts).scan(/^(?:ext|gem)s: (.*\.mk)/).flatten rescue nil
confexts ||= []
macros["old_extensions"] = []
contpat = /(?>(?>[^\\\n]|\\.)*\\\n)*(?>[^\\\n]|\\.)*/
Dir.glob("{ext,.bundle/gems}/*/exts.mk") do |e|
- gem = /\Agems(?=\/)/ =~ e
+ gem = e.start_with?(".bundle/gems/")
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] ||= []
@@ -133,7 +132,7 @@ distclean:
% end
libencs:
- $(Q)$(MAKE)<%=mflags%> -f enc.mk V=$(V) $@
+ $(Q)$(MAKE)<%=mflags%> -f enc.mk V=$(V) MINIRUBY="$(MINIRUBY)" $@
ext/extinit.<%=objext%>:
$(Q)$(MAKE)<%=mflags%> V=$(V) EXTINITS="$(EXTINITS)" $@
@@ -155,7 +154,7 @@ ext/extinit.<%=objext%>:
% end
$(Q)<%= submake %><%=mflags%> V=$(V) $(@F)
% if /^(dist|real)clean$/ =~ tgt
- $(Q)$(RM) $(@D)/exts.mk
+ $(Q)$(RM) <%=t[%r[\A(?:\.[^/]+/)?(?:[^/]+/){2}]]%>exts.mk
$(Q)$(RMDIRS) $(@D)
% end
% end
diff --git a/template/fake.rb.in b/template/fake.rb.in
index 25053d3dbf..7b74421d62 100644
--- a/template/fake.rb.in
+++ b/template/fake.rb.in
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+# shareable_constant_value: literal
<%
arg = {}
while /\A(\w+)=(.*)/ =~ ARGV[0]
@@ -7,16 +9,23 @@ while /\A(\w+)=(.*)/ =~ ARGV[0]
end
if inc = arg['i']
src = inc == '-' ? STDIN.read : File.read(inc)
- def src.value(name)
- eval(self[/\bruby_#{name}(?:\[\])?\s*=\s*((?:"(?:\\.|[^\"\\])*"\s*)*(?=;)|[^{};]+)/m, 1].gsub(/#/, '\\#'))
- end
- arg['versions'] = version = {}
- File.read(File.join(arg['srcdir'], 'version.c')).
- scan(/rb_define_global_const\("(RUBY_\w+)",[^;]*?\bMK(?:INT|STR)\(([^()]*)\)/m) do |n, v|
- version[n] = src.value(v)
+ src.gsub!(/^#.*\n/, '')
+else
+ src = ""
+end
+def src.value(name)
+ unless val = self[/\bruby_#{name}(?:\[\])?\s*=\s*((?:"(?:\\.|[^\"\\])*"\s*)*(?=;)|[^{};]+)/m, 1]
+ return
end
- arg['RUBY_DESCRIPTION_WITH_JIT'] = src.value('description_with_jit')
+ eval(val.gsub(/#/, '\\#').gsub(/((?:\G|[^\\])(?:\\\\)*)\n/, '\1'))
+end
+arg['versions'] = version = {}
+File.read(File.join(arg['srcdir'], 'version.c')).
+ scan(/rb_define_global_const\("(RUBY_\w+)",[^;]*?\bMK(?:INT|(STR))\(([^()]*)\)/m) do |n, s, v|
+ version[n] = arg[v] || src.value(v) || (s ? v : 0)
end
+arg['RUBY_DESCRIPTION_WITH_MJIT'] = src.value('description_with_mjit') || 'description_with_mjit'
+arg['RUBY_DESCRIPTION_WITH_YJIT'] = src.value('description_with_yjit') || 'description_with_yjit'
%>baseruby="<%=arg['BASERUBY']%>"
_\
=begin
@@ -32,12 +41,20 @@ class Object
CROSS_COMPILING = RUBY_PLATFORM
constants.grep(/^RUBY_/) {|n| remove_const n}
% arg['versions'].each {|n, v|
- <%=n%> = <%if n=='RUBY_DESCRIPTION' %>RubyVM.const_defined?(:JIT) && RubyVM::JIT.enabled? ?
- <%=arg['RUBY_DESCRIPTION_WITH_JIT'].inspect%> :
- <%end%><%=v.inspect%>
+ <%=n%> = <%if n=='RUBY_DESCRIPTION' %>case
+ when RubyVM.const_defined?(:MJIT) && RubyVM::MJIT.enabled?
+ <%=arg['RUBY_DESCRIPTION_WITH_MJIT'].inspect%>
+ when RubyVM.const_defined?(:YJIT) && RubyVM::YJIT.enabled?
+ <%=arg['RUBY_DESCRIPTION_WITH_YJIT'].inspect%>
+ else
+ <%=v.inspect%>
+ end<%else%><%=v.inspect%><%end%>
% }
end
builddir = File.dirname(File.expand_path(__FILE__))
+libpathenv = libpathenv = "<%=arg['LIBPATHENV']%>"
+preloadenv = preloadenv = "<%=arg['PRELOADENV']%>"
+libruby_so = libruby_so = "<%=arg['LIBRUBY_SO']%>"
srcdir = "<%=arg['srcdir']%>"
top_srcdir = File.realpath(srcdir, builddir)
fake = File.join(top_srcdir, "tool/fake.rb")
diff --git a/template/id.c.tmpl b/template/id.c.tmpl
index 4f30875c04..5aa8e47ce7 100644
--- a/template/id.c.tmpl
+++ b/template/id.c.tmpl
@@ -12,7 +12,7 @@
**********************************************************************/
<%
defs = File.join(File.dirname(File.dirname(erb.filename)), "defs/id.def")
-ids = eval(File.read(defs), binding, defs)
+ids = eval(File.read(defs), nil, defs)
ops = ids[:token_op].uniq {|id, op, token| token && op}
%>
% ops.each do |_id, _op, token|
@@ -22,7 +22,8 @@ ops = ids[:token_op].uniq {|id, op, token| token && op}
static const struct {
unsigned short token;
- const char name[3], term;
+ RBIMPL_ATTR_NONSTRING() const char name[3];
+ const char term;
} op_tbl[] = {
% ops.each do |_id, op, token|
% next unless token
diff --git a/template/id.h.tmpl b/template/id.h.tmpl
index 687cbbbe40..9c588305eb 100644
--- a/template/id.h.tmpl
+++ b/template/id.h.tmpl
@@ -11,10 +11,8 @@
**********************************************************************/
<%
-op_id_offset = 128
-
defs = File.join(File.dirname(File.dirname(erb.filename)), "defs/id.def")
-ids = eval(File.read(defs), binding, defs)
+ids = eval(File.read(defs), nil, defs)
types = ids.keys.grep(/^[A-Z]/)
%>
#ifndef RUBY_ID_H
@@ -49,11 +47,9 @@ enum ruby_id_types {
#define symIFUNC ID2SYM(idIFUNC)
#define symCFUNC ID2SYM(idCFUNC)
-% index = op_id_offset
-% ids[:token_op].each do |_id, _op, token|
+% ids[:token_op].each do |_id, _op, token, index|
% next unless token
#define RUBY_TOKEN_<%=token%> <%=index%>
-% index += 1
% end
#define RUBY_TOKEN(t) RUBY_TOKEN_##t
@@ -66,7 +62,7 @@ enum ruby_method_ids {
% ids[:token_op].uniq {|_, op| op}.each do |id, op, token|
id<%=id%> = <%=token ? "RUBY_TOKEN(#{token})" : "'#{op}'"%>,
% end
- tPRESERVED_ID_BEGIN = <%=index-1%>,
+ tPRESERVED_ID_BEGIN = <%=ids[:last_token]%>,
% ids[:preserved].each do |token|
id<%=token%>,
% end
diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl
index a36e572a41..b724ec6506 100644
--- a/template/prelude.c.tmpl
+++ b/template/prelude.c.tmpl
@@ -20,7 +20,6 @@ class Prelude
def initialize(output, preludes, vpath)
@output = output
- @have_sublib = false
@vpath = vpath
@prelude_count = 0
@builtin_count = 0
@@ -48,7 +47,7 @@ class Prelude
line.rstrip!
lineno += 1
@preludes[filename] ||= result
- comment = ($1 || '' if line.sub!(/(?:^|\s+)\#(?:$|[#\s](.*))/, ''))
+ comment = ($1 || '' if line.sub!(/(?:^|\s+)\#(?!\{)(?:$|(?:[#\s]|(?=\W))(.*))/, ''))
if !line.empty? or start_line
line << "\n"
start_line ||= lineno
@@ -64,8 +63,10 @@ class Prelude
end
path = translate("#{path}.rb", true) rescue nil
if path
- @have_sublib = true
- "TMP_RUBY_PREFIX.require(#{path[0]})"
+ # This library will be loaded before this,
+ # the order cannot be preserved
+ comment = "#{orig} #{comment}".rstrip
+ ""
else
orig
end
@@ -87,6 +88,7 @@ Prelude.new(output, ARGV, vpath).instance_eval do
#include "internal.h"
#include "internal/warnings.h"
#include "iseq.h"
+#include "ruby/internal/attr/nonstring.h"
#include "ruby/ruby.h"
#include "vm_core.h"
@@ -106,12 +108,12 @@ static const struct {
% size += line.size
% next
% end
- char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=n%> */
+ RBIMPL_ATTR_NONSTRING() char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=n%> */
% size = line.size
% beg = n
% }
% if size > 0
- char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=lines.size+1%> */
+ RBIMPL_ATTR_NONSTRING() char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=lines.size+1%> */
% end
} prelude_code<%=i%><%=%> = {
% size = 0
@@ -131,24 +133,6 @@ static const struct {
COMPILER_WARNING_POP
-% if @have_sublib
-#define PRELUDE_COUNT <%=preludes.size%>
-
-struct prelude_env {
- volatile VALUE prefix_path;
-#if PRELUDE_COUNT > 0
- char loaded[PRELUDE_COUNT];
-#endif
-};
-
-static VALUE
-prelude_prefix_path(VALUE self)
-{
- struct prelude_env *ptr = DATA_PTR(self);
- return ptr->prefix_path;
-}
-
-% end
% unless preludes.empty?
#define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1)
#define PRELUDE_CODE(n) rb_utf8_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n))
@@ -158,8 +142,8 @@ prelude_ast(VALUE name, VALUE code, int line)
{
rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
if (!ast->body.root) {
- rb_ast_dispose(ast);
- rb_exc_raise(rb_errinfo());
+ rb_ast_dispose(ast);
+ rb_exc_raise(rb_errinfo());
}
return ast;
}
@@ -179,7 +163,7 @@ rb_builtin_ast(const char *feature_name, VALUE *name_str)
rb_ast_t *ast = 0;
% @preludes.each_value do |i, prelude, lines, sub, start_line|
-% if sub and sub != true
+% if sub
if ((ast = PRELUDE_AST(<%=i%><%=%>, *name_str, <%=start_line%>)) != 0) return ast;
% end
% end
@@ -196,83 +180,37 @@ static void
prelude_eval(VALUE code, VALUE name, int line)
{
static const rb_compile_option_t optimization = {
- TRUE, /* int inline_const_cache; */
- TRUE, /* int peephole_optimization; */
- FALSE,/* int tailcall_optimization; */
- TRUE, /* int specialized_instruction; */
- TRUE, /* int operands_unification; */
- TRUE, /* int instructions_unification; */
- TRUE, /* int stack_caching; */
- TRUE, /* int frozen_string_literal; */
- FALSE, /* int debug_frozen_string_literal; */
- FALSE, /* unsigned int coverage_enabled; */
- 0, /* int debug_level; */
+ TRUE, /* int inline_const_cache; */
+ TRUE, /* int peephole_optimization; */
+ FALSE,/* int tailcall_optimization; */
+ TRUE, /* int specialized_instruction; */
+ TRUE, /* int operands_unification; */
+ TRUE, /* int instructions_unification; */
+ TRUE, /* int stack_caching; */
+ TRUE, /* int frozen_string_literal; */
+ FALSE, /* int debug_frozen_string_literal; */
+ FALSE, /* unsigned int coverage_enabled; */
+ 0, /* int debug_level; */
};
rb_ast_t *ast = prelude_ast(name, code, line);
- rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line),
- NULL, 0, ISEQ_TYPE_TOP, &optimization));
+ rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, line,
+ NULL, 0, ISEQ_TYPE_TOP, &optimization));
rb_ast_dispose(ast);
}
COMPILER_WARNING_POP
% end
-% if @have_sublib
-static VALUE
-prelude_require(VALUE self, VALUE nth)
-{
- struct prelude_env *ptr = DATA_PTR(self);
- VALUE code, name;
- int n = FIX2INT(nth);
- int start_line;
-
- if (n > PRELUDE_COUNT) return Qfalse;
- if (ptr->loaded[n]) return Qfalse;
- ptr->loaded[n] = 1;
- switch (n) {
-% @preludes.each_value do |i, prelude, lines, sub, start_line|
-% if sub == true
- case <%=i%><%=%>:
- code = PRELUDE_CODE(<%=i%><%=%>);
- name = PRELUDE_NAME(<%=i%><%=%>);
- start_line = <%=start_line%>;
- break;
-% end
-% end
- default:
- return Qfalse;
- }
- prelude_eval(code, name, start_line);
- return Qtrue;
-}
-
-% end
%end
% init_name = @output && @output[/\w+(?=_prelude.c\b)/] || 'prelude'
void
Init_<%=init_name%><%=%>(void)
{
%unless @prelude_count.zero?
-% if @have_sublib
- struct prelude_env memo;
- ID name = rb_intern("TMP_RUBY_PREFIX");
- VALUE prelude = Data_Wrap_Struct(rb_cData, 0, 0, &memo);
-
- memo.prefix_path = rb_const_remove(rb_cObject, name);
- rb_const_set(rb_cObject, name, prelude);
- rb_define_singleton_method(prelude, "to_s", prelude_prefix_path, 0);
-% end
-% if @have_sublib
- memset(memo.loaded, 0, sizeof(memo.loaded));
- rb_define_singleton_method(prelude, "require", prelude_require, 1);
-% end
% preludes.each do |i, prelude, lines, sub, start_line|
% next if sub
prelude_eval(PRELUDE_CODE(<%=i%><%=%>), PRELUDE_NAME(<%=i%><%=%>), <%=start_line%>);
% end
-% if @have_sublib
- rb_gc_force_recycle(prelude);
-% end
#if 0
% preludes.length.times {|i|
diff --git a/template/ruby.pc.in b/template/ruby.pc.in
index 7ce4461c05..c4848805a3 100644
--- a/template/ruby.pc.in
+++ b/template/ruby.pc.in
@@ -1,21 +1,21 @@
-arch=@arch@
-sitearch=@sitearch@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libdir=@libdir@
-includedir=@includedir@
MAJOR=@MAJOR@
MINOR=@MINOR@
TEENY=@TEENY@
ruby_version=@ruby_version@
RUBY_API_VERSION=@RUBY_API_VERSION@
RUBY_PROGRAM_VERSION=@RUBY_PROGRAM_VERSION@
+arch=@arch@
+sitearch=@sitearch@
+
RUBY_BASE_NAME=@RUBY_BASE_NAME@
RUBY_VERSION_NAME=@RUBY_VERSION_NAME@
RUBY_SO_NAME=@RUBY_SO_NAME@
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
-DEFFILE=@DEFFILE@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+includedir=@includedir@
archlibdir=@archlibdir@
sitearchlibdir=@sitearchlibdir@
archincludedir=@archincludedir@
diff --git a/test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb b/test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb
new file mode 100644
index 0000000000..4320c1f20d
--- /dev/null
+++ b/test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class Test_ArithSeq < Test::Unit::TestCase
+ def test_beg_len_step
+ assert_separately([], <<-"end;") #do
+ require '-test-/arith_seq/beg_len_step'
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__([1, 2, 3], 0, 0)
+ assert_equal(false, r)
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__([1, 2, 3], 1, 0)
+ assert_equal(false, r)
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__([1, 2, 3], 3, 0)
+ assert_equal(false, r)
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 0, 0)
+ assert_equal(nil, r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 1, 0)
+ assert_equal([true, 1, 0, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 2, 0)
+ assert_equal([true, 1, 1, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 3, 0)
+ assert_equal([true, 1, 2, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 4, 0)
+ assert_equal([true, 1, 3, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 5, 0)
+ assert_equal([true, 1, 3, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(2), 24, 0)
+ assert_equal([true, 14, 0, 2], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(3), 24, 0)
+ assert_equal([true, 14, 0, 3], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(3), 22, 0)
+ assert_equal([true, 12, 0, 3], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(-3), 22, 0)
+ assert_equal([true, 10, 3, -3], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 0, 1)
+ assert_equal([true, 1, 3, 1], r)
+ end;
+ 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-/bignum/test_big2str.rb b/test/-ext-/bignum/test_big2str.rb
index f8d6320338..88e35a7294 100644
--- a/test/-ext-/bignum/test_big2str.rb
+++ b/test/-ext-/bignum/test_big2str.rb
@@ -2,29 +2,27 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestBig2str < Test::Unit::TestCase
+class TestBignum_Big2str < Test::Unit::TestCase
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
- def test_big2str_generic
- x = 10**1000
- assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_generic(x, 10))
- end
-
- def test_big2str_poweroftwo
- e = BITSPERDIG*2
- x = 0b10**e
- assert_equal("1" + "0" * e, Bug::Bignum.big2str_poweroftwo(x, 2))
- end
+ def test_big2str_generic
+ x = 10**1000
+ assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_generic(x, 10))
+ end
- def test_big2str_gmp
- x = 10**1000
- assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_gmp(x, 10))
- rescue NotImplementedError
- end
+ def test_big2str_poweroftwo
+ e = BITSPERDIG*2
+ x = 0b10**e
+ assert_equal("1" + "0" * e, Bug::Bignum.big2str_poweroftwo(x, 2))
+ end
+ def test_big2str_gmp
+ x = 10**1000
+ assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_gmp(x, 10))
+ rescue NotImplementedError
end
+
end
diff --git a/test/-ext-/bignum/test_bigzero.rb b/test/-ext-/bignum/test_bigzero.rb
index cf34964acd..6dfa3486c1 100644
--- a/test/-ext-/bignum/test_bigzero.rb
+++ b/test/-ext-/bignum/test_bigzero.rb
@@ -2,19 +2,17 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestBigZero < Test::Unit::TestCase
- def test_equal_0
- bug8204 = '[ruby-core:53893] [Bug #8204]'
- (0..10).each do |i|
- assert_equal(0, Bug::Bignum.zero(i), "#{bug8204} Bignum.zero(#{i})")
- end
+class TestBignum_BigZero < Test::Unit::TestCase
+ def test_equal_0
+ bug8204 = '[ruby-core:53893] [Bug #8204]'
+ (0..10).each do |i|
+ assert_equal(0, Bug::Bignum.zero(i), "#{bug8204} Bignum.zero(#{i})")
end
+ end
- def test_zero?
- (0..10).each do |i|
- assert_equal(true, Bug::Bignum.zero(i).zero?)
- end
+ def test_zero?
+ (0..10).each do |i|
+ assert_equal(true, Bug::Bignum.zero(i).zero?)
end
end
end
diff --git a/test/-ext-/bignum/test_div.rb b/test/-ext-/bignum/test_div.rb
index e61fc2ced5..0c6f635ae8 100644
--- a/test/-ext-/bignum/test_div.rb
+++ b/test/-ext-/bignum/test_div.rb
@@ -2,28 +2,26 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestDiv < Test::Unit::TestCase
+class TestBignum_Div < Test::Unit::TestCase
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
- def test_divrem_normal
- x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
- y = (1 << BITSPERDIG) | 1
- q = (1 << BITSPERDIG) | 1
- r = 2
- assert_equal([q, r], Bug::Bignum.big_divrem_normal(x, y))
- end
+ def test_divrem_normal
+ x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
+ y = (1 << BITSPERDIG) | 1
+ q = (1 << BITSPERDIG) | 1
+ r = 2
+ assert_equal([q, r], Bug::Bignum.big_divrem_normal(x, y))
+ end
- def test_divrem_gmp
- x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
- y = (1 << BITSPERDIG) | 1
- q = (1 << BITSPERDIG) | 1
- r = 2
- assert_equal([q, r], Bug::Bignum.big_divrem_gmp(x, y))
- rescue NotImplementedError
- end
+ def test_divrem_gmp
+ x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
+ y = (1 << BITSPERDIG) | 1
+ q = (1 << BITSPERDIG) | 1
+ r = 2
+ assert_equal([q, r], Bug::Bignum.big_divrem_gmp(x, y))
+ rescue NotImplementedError
end
end
diff --git a/test/-ext-/bignum/test_mul.rb b/test/-ext-/bignum/test_mul.rb
index 7653a8e37a..95186bbf76 100644
--- a/test/-ext-/bignum/test_mul.rb
+++ b/test/-ext-/bignum/test_mul.rb
@@ -2,137 +2,135 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestMul < Test::Unit::TestCase
-
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
-
- def test_mul_normal
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_mul_normal_zero_in_x
- x = (1 << (2*BITSPERDIG)) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_mul_normal_zero_in_y
- x = (1 << BITSPERDIG) | 1
- y = (1 << (2*BITSPERDIG)) | 1
- z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_mul_normal_max_max
- x = (1 << (2*BITSPERDIG)) - 1
- y = (1 << (2*BITSPERDIG)) - 1
- z = (1 << (4*BITSPERDIG)) - (1 << (2*BITSPERDIG+1)) + 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_sq_fast
- x = (1 << BITSPERDIG) | 1
- z = (1 << 2*BITSPERDIG) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_sq_fast(x))
- end
-
- def test_sq_fast_max2
- x = (BDIGMAX << BITSPERDIG) | BDIGMAX
- assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
- end
-
- def test_sq_fast_zero_in_middle
- x = (BDIGMAX << 2*BITSPERDIG) | BDIGMAX
- assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
- end
-
- def test_mul_balance
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_balance(x, y))
- end
-
- def test_mul_balance_2x16
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG*16) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
- end
-
- def test_mul_balance_2x17
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG*17) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
- end
-
- def test_mul_karatsuba
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_odd_y
- x = (1 << BITSPERDIG) | 1
- y = (1 << (2*BITSPERDIG)) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_odd_xy
- x = (1 << (2*BITSPERDIG)) | 1
- y = (1 << (2*BITSPERDIG)) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_x1_gt_x0
- x = (2 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 2
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_y1_gt_y0
- x = (1 << BITSPERDIG) | 2
- y = (2 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_x1_gt_x0_and_y1_gt_y0
- x = (2 << BITSPERDIG) | 1
- y = (2 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_carry2
- x = (1 << BITSPERDIG) | BDIGMAX
- y = (1 << BITSPERDIG) | BDIGMAX
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_borrow
- x = (BDIGMAX << BITSPERDIG) | 1
- y = (BDIGMAX << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_toom3
- x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_toom3(x, y))
- end
-
- def test_mul_gmp
- x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_gmp(x, y))
- rescue NotImplementedError
- end
+class TestBignum_Mul < Test::Unit::TestCase
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
+
+ def test_mul_normal
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_mul_normal_zero_in_x
+ x = (1 << (2*BITSPERDIG)) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_mul_normal_zero_in_y
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << (2*BITSPERDIG)) | 1
+ z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_mul_normal_max_max
+ x = (1 << (2*BITSPERDIG)) - 1
+ y = (1 << (2*BITSPERDIG)) - 1
+ z = (1 << (4*BITSPERDIG)) - (1 << (2*BITSPERDIG+1)) + 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_sq_fast
+ x = (1 << BITSPERDIG) | 1
+ z = (1 << 2*BITSPERDIG) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_sq_fast(x))
+ end
+
+ def test_sq_fast_max2
+ x = (BDIGMAX << BITSPERDIG) | BDIGMAX
+ assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
+ end
+
+ def test_sq_fast_zero_in_middle
+ x = (BDIGMAX << 2*BITSPERDIG) | BDIGMAX
+ assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
+ end
+
+ def test_mul_balance
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_balance(x, y))
+ end
+
+ def test_mul_balance_2x16
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG*16) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
+ end
+
+ def test_mul_balance_2x17
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG*17) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
+ end
+
+ def test_mul_karatsuba
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_odd_y
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << (2*BITSPERDIG)) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_odd_xy
+ x = (1 << (2*BITSPERDIG)) | 1
+ y = (1 << (2*BITSPERDIG)) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_x1_gt_x0
+ x = (2 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 2
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_y1_gt_y0
+ x = (1 << BITSPERDIG) | 2
+ y = (2 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_x1_gt_x0_and_y1_gt_y0
+ x = (2 << BITSPERDIG) | 1
+ y = (2 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_carry2
+ x = (1 << BITSPERDIG) | BDIGMAX
+ y = (1 << BITSPERDIG) | BDIGMAX
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_borrow
+ x = (BDIGMAX << BITSPERDIG) | 1
+ y = (BDIGMAX << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
end
+
+ def test_mul_toom3
+ x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_toom3(x, y))
+ end
+
+ def test_mul_gmp
+ x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_gmp(x, y))
+ rescue NotImplementedError
+ end
+
end
diff --git a/test/-ext-/bignum/test_pack.rb b/test/-ext-/bignum/test_pack.rb
index d5605236f7..b7aea9ab68 100644
--- a/test/-ext-/bignum/test_pack.rb
+++ b/test/-ext-/bignum/test_pack.rb
@@ -4,348 +4,346 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestPack < Test::Unit::TestCase
-
- MSWORD_FIRST = Bug::Bignum::INTEGER_PACK_MSWORD_FIRST
- LSWORD_FIRST = Bug::Bignum::INTEGER_PACK_LSWORD_FIRST
- MSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_MSBYTE_FIRST
- LSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_LSBYTE_FIRST
- NATIVE_BYTE_ORDER = Bug::Bignum::INTEGER_PACK_NATIVE_BYTE_ORDER
- TWOCOMP = Bug::Bignum::INTEGER_PACK_2COMP
- LITTLE_ENDIAN = Bug::Bignum::INTEGER_PACK_LITTLE_ENDIAN
- BIG_ENDIAN = Bug::Bignum::INTEGER_PACK_BIG_ENDIAN
- NEGATIVE = Bug::Bignum::INTEGER_PACK_NEGATIVE
- GENERIC = Bug::Bignum::INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
-
- def test_pack_zero
- assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, BIG_ENDIAN))
- end
-
- def test_pack_argument_check
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 2, 1, 0, MSBYTE_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 0, MSWORD_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 0, 0, BIG_ENDIAN) }
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 8, BIG_ENDIAN) }
-
- # assume sizeof(ssize_t) == sizeof(intptr_t)
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
- end
-
- def test_pack_wordsize
- assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, BIG_ENDIAN))
- assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(1, 1, 2, 0, BIG_ENDIAN))
- assert_equal([1, "\x00\x00\x01"], Bug::Bignum.test_pack(1, 1, 3, 0, BIG_ENDIAN))
- assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(1, 1, 2, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x00\x00"], Bug::Bignum.test_pack(1, 1, 3, 0, LITTLE_ENDIAN))
- end
-
- def test_pack_fixed_buffer
- assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, BIG_ENDIAN))
- assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(0x01, 2, 1, 0, BIG_ENDIAN))
- assert_equal([1, "\x02\x01"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, BIG_ENDIAN))
- assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, BIG_ENDIAN))
- assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, BIG_ENDIAN))
- assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(0x01, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x02"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, LITTLE_ENDIAN))
- end
-
- def test_pack_wordorder_and_endian
- assert_equal([1, "\x12\x34\x56\x78"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
- assert_equal([1, "\x34\x12\x78\x56"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
- assert_equal([1, "\x56\x78\x12\x34"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
- assert_equal([1, "\x78\x56\x34\x12"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
- end
-
- def test_pack_native_endian
- assert_equal([1, [0x1234].pack("S!")], Bug::Bignum.test_pack(0x1234, 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
- end
-
- def test_pack_nail
- assert_equal([1, "\x01\x00\x00\x00\x01\x01"], Bug::Bignum.test_pack(0b100011, 6, 1, 7, BIG_ENDIAN))
- assert_equal([1, "\x01\x02\x03\x04\x05\x06\x07\x08"], Bug::Bignum.test_pack(0x12345678, 8, 1, 4, BIG_ENDIAN))
- assert_equal([1, "\x00\x12\x00\x34\x00\x56\x00\x78"], Bug::Bignum.test_pack(0x12345678, 4, 2, 8, BIG_ENDIAN))
- end
-
- def test_pack_overflow
- assert_equal([-2, "\x1"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, BIG_ENDIAN))
- assert_equal([-2, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, BIG_ENDIAN))
- assert_equal([-1, "\xF"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, BIG_ENDIAN))
- assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, BIG_ENDIAN))
- assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, BIG_ENDIAN))
- assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, BIG_ENDIAN))
-
- assert_equal([-2, "\x01"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, BIG_ENDIAN))
- assert_equal([-2, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, BIG_ENDIAN))
- assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, BIG_ENDIAN))
- assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, BIG_ENDIAN))
- assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, BIG_ENDIAN))
-
- assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
- assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
- assert_equal([-1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
- assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
-
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, BIG_ENDIAN))
- }
- }
+class TestBignum_Pack < Test::Unit::TestCase
+
+ MSWORD_FIRST = Bug::Bignum::INTEGER_PACK_MSWORD_FIRST
+ LSWORD_FIRST = Bug::Bignum::INTEGER_PACK_LSWORD_FIRST
+ MSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_MSBYTE_FIRST
+ LSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_LSBYTE_FIRST
+ NATIVE_BYTE_ORDER = Bug::Bignum::INTEGER_PACK_NATIVE_BYTE_ORDER
+ TWOCOMP = Bug::Bignum::INTEGER_PACK_2COMP
+ LITTLE_ENDIAN = Bug::Bignum::INTEGER_PACK_LITTLE_ENDIAN
+ BIG_ENDIAN = Bug::Bignum::INTEGER_PACK_BIG_ENDIAN
+ NEGATIVE = Bug::Bignum::INTEGER_PACK_NEGATIVE
+ GENERIC = Bug::Bignum::INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
+
+ def test_pack_zero
+ assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, BIG_ENDIAN))
+ end
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
- }
+ def test_pack_argument_check
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 2, 1, 0, MSBYTE_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 0, MSWORD_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 0, 0, BIG_ENDIAN) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 8, BIG_ENDIAN) }
+
+ # assume sizeof(ssize_t) == sizeof(intptr_t)
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
+ end
+
+ def test_pack_wordsize
+ assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, BIG_ENDIAN))
+ assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(1, 1, 2, 0, BIG_ENDIAN))
+ assert_equal([1, "\x00\x00\x01"], Bug::Bignum.test_pack(1, 1, 3, 0, BIG_ENDIAN))
+ assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(1, 1, 2, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x00\x00"], Bug::Bignum.test_pack(1, 1, 3, 0, LITTLE_ENDIAN))
+ end
+
+ def test_pack_fixed_buffer
+ assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(0x01, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([1, "\x02\x01"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(0x01, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x02"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, LITTLE_ENDIAN))
+ end
+
+ def test_pack_wordorder_and_endian
+ assert_equal([1, "\x12\x34\x56\x78"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal([1, "\x34\x12\x78\x56"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
+ assert_equal([1, "\x56\x78\x12\x34"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal([1, "\x78\x56\x34\x12"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
+ end
+
+ def test_pack_native_endian
+ assert_equal([1, [0x1234].pack("S!")], Bug::Bignum.test_pack(0x1234, 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
+ end
+
+ def test_pack_nail
+ assert_equal([1, "\x01\x00\x00\x00\x01\x01"], Bug::Bignum.test_pack(0b100011, 6, 1, 7, BIG_ENDIAN))
+ assert_equal([1, "\x01\x02\x03\x04\x05\x06\x07\x08"], Bug::Bignum.test_pack(0x12345678, 8, 1, 4, BIG_ENDIAN))
+ assert_equal([1, "\x00\x12\x00\x34\x00\x56\x00\x78"], Bug::Bignum.test_pack(0x12345678, 4, 2, 8, BIG_ENDIAN))
+ end
+
+ def test_pack_overflow
+ assert_equal([-2, "\x1"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([-2, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([-1, "\xF"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, BIG_ENDIAN))
+
+ assert_equal([-2, "\x01"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([-2, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, BIG_ENDIAN))
+
+ assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([-1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, BIG_ENDIAN))
}
- end
-
- def test_pack_sign
- assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-1), 1, 1, 0, BIG_ENDIAN))
- assert_equal([-1, "\x80\x70\x60\x50\x40\x30\x20\x10"], Bug::Bignum.test_pack((-0x8070605040302010), 8, 1, 0, BIG_ENDIAN))
- end
-
- def test_pack_orders
- [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
- [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 0;
- 0.upto(w) {|i|
- n |= ((i+1) % 256) << (i*8)
- }
- assert_equal(Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order|GENERIC),
- Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order),
- "#{'%#x' % n}.test_pack(#{numwords}, #{wordsize}, 0, #{'%#x' % (word_order|byte_order)})")
+ }
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ }
+ }
+ end
+
+ def test_pack_sign
+ assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-1), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([-1, "\x80\x70\x60\x50\x40\x30\x20\x10"], Bug::Bignum.test_pack((-0x8070605040302010), 8, 1, 0, BIG_ENDIAN))
+ end
+
+ def test_pack_orders
+ [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
+ [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 0;
+ 0.upto(w) {|i|
+ n |= ((i+1) % 256) << (i*8)
}
+ assert_equal(Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order|GENERIC),
+ Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order),
+ "#{'%#x' % n}.test_pack(#{numwords}, #{wordsize}, 0, #{'%#x' % (word_order|byte_order)})")
}
}
}
- end
-
- def test_pack2comp_zero
- assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_pack2comp_emptybuf
- assert_equal([-2, ""], Bug::Bignum.test_pack((-3), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-2, ""], Bug::Bignum.test_pack((-2), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, ""], Bug::Bignum.test_pack((-1), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([ 0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, ""], Bug::Bignum.test_pack(1, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, ""], Bug::Bignum.test_pack(2, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_pack2comp_nearly_zero
- assert_equal([-1, "\xFE"], Bug::Bignum.test_pack((-2), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-1), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([ 0, "\x00"], Bug::Bignum.test_pack(0, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\x02"], Bug::Bignum.test_pack(2, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_pack2comp_overflow
- assert_equal([-2, "\xF"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x1"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
-
- assert_equal([-2, "\xFF"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
-
- assert_equal([-2, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
-
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- }
- }
+ }
+ end
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([-1, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- }
- }
+ def test_pack2comp_zero
+ assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
- 2.upto(16) {|wordsize|
- w = wordsize
- b = 8*wordsize-1
- n = 2**b
- assert_equal([-2, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([+1, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- }
+ def test_pack2comp_emptybuf
+ assert_equal([-2, ""], Bug::Bignum.test_pack((-3), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-2, ""], Bug::Bignum.test_pack((-2), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, ""], Bug::Bignum.test_pack((-1), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([ 0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, ""], Bug::Bignum.test_pack(1, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, ""], Bug::Bignum.test_pack(2, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
- 2.upto(16) {|wordsize|
- w = wordsize
- b = 8*wordsize-1
- n = 2**b
- assert_equal([-2, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([-1, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([+1, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([+2, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ def test_pack2comp_nearly_zero
+ assert_equal([-1, "\xFE"], Bug::Bignum.test_pack((-2), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-1), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([ 0, "\x00"], Bug::Bignum.test_pack(0, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\x02"], Bug::Bignum.test_pack(2, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
+
+ def test_pack2comp_overflow
+ assert_equal([-2, "\xF"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x1"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+
+ assert_equal([-2, "\xFF"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+
+ assert_equal([-2, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
}
+ }
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([-1, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ }
+ }
+
+ 2.upto(16) {|wordsize|
+ w = wordsize
+ b = 8*wordsize-1
+ n = 2**b
+ assert_equal([-2, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([+1, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ }
+
+ 2.upto(16) {|wordsize|
+ w = wordsize
+ b = 8*wordsize-1
+ n = 2**b
+ assert_equal([-2, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([-1, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([+1, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([+2, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ }
+
+ end
+
+ def test_unpack_zero
+ assert_equal(0, Bug::Bignum.test_unpack("", 0, 1, 0, BIG_ENDIAN))
+ end
+
+ def test_unpack_argument_check
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 2, 1, 0, MSBYTE_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 0, MSWORD_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 0, 0, BIG_ENDIAN) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 8, BIG_ENDIAN) }
+
+ # assume sizeof(ssize_t) == sizeof(intptr_t)
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
+ end
+
+ def test_unpack_wordsize
+ assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x00\x01", 1, 2, 0, BIG_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x00\x00\x01", 1, 3, 0, BIG_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, LITTLE_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x01\x00", 1, 2, 0, LITTLE_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x01\x00\x00", 1, 3, 0, LITTLE_ENDIAN))
+ end
+
+ def test_unpack_wordorder_and_endian
+ assert_equal(0x01020304, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal(0x02010403, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
+ assert_equal(0x03040102, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal(0x04030201, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
+ end
+
+ def test_unpack_native_endian
+ assert_equal("\x12\x34".unpack("S!")[0], Bug::Bignum.test_unpack("\x12\x34", 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
+ end
+
+ def test_unpack_nail
+ assert_equal(0b100011, Bug::Bignum.test_unpack("\x01\x00\x00\x00\x01\x01", 6, 1, 7, BIG_ENDIAN))
+ assert_equal(0x12345678, Bug::Bignum.test_unpack("\x01\x02\x03\x04\x05\x06\x07\x08", 8, 1, 4, BIG_ENDIAN))
+ assert_equal(0x12345678, Bug::Bignum.test_unpack("\x00\x12\x00\x34\x00\x56\x00\x78", 4, 2, 8, BIG_ENDIAN))
+ end
+
+ def test_unpack_sign
+ assert_equal(-1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN|NEGATIVE))
+ assert_equal(-0x8070605040302010, Bug::Bignum.test_unpack("\x80\x70\x60\x50\x40\x30\x20\x10", 8, 1, 0, BIG_ENDIAN|NEGATIVE))
+ end
- end
-
- def test_unpack_zero
- assert_equal(0, Bug::Bignum.test_unpack("", 0, 1, 0, BIG_ENDIAN))
- end
-
- def test_unpack_argument_check
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 2, 1, 0, MSBYTE_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 0, MSWORD_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 0, 0, BIG_ENDIAN) }
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 8, BIG_ENDIAN) }
-
- # assume sizeof(ssize_t) == sizeof(intptr_t)
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
- end
-
- def test_unpack_wordsize
- assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x00\x01", 1, 2, 0, BIG_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x00\x00\x01", 1, 3, 0, BIG_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, LITTLE_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x01\x00", 1, 2, 0, LITTLE_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x01\x00\x00", 1, 3, 0, LITTLE_ENDIAN))
- end
-
- def test_unpack_wordorder_and_endian
- assert_equal(0x01020304, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
- assert_equal(0x02010403, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
- assert_equal(0x03040102, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
- assert_equal(0x04030201, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
- end
-
- def test_unpack_native_endian
- assert_equal("\x12\x34".unpack("S!")[0], Bug::Bignum.test_unpack("\x12\x34", 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
- end
-
- def test_unpack_nail
- assert_equal(0b100011, Bug::Bignum.test_unpack("\x01\x00\x00\x00\x01\x01", 6, 1, 7, BIG_ENDIAN))
- assert_equal(0x12345678, Bug::Bignum.test_unpack("\x01\x02\x03\x04\x05\x06\x07\x08", 8, 1, 4, BIG_ENDIAN))
- assert_equal(0x12345678, Bug::Bignum.test_unpack("\x00\x12\x00\x34\x00\x56\x00\x78", 4, 2, 8, BIG_ENDIAN))
- end
-
- def test_unpack_sign
- assert_equal(-1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN|NEGATIVE))
- assert_equal(-0x8070605040302010, Bug::Bignum.test_unpack("\x80\x70\x60\x50\x40\x30\x20\x10", 8, 1, 0, BIG_ENDIAN|NEGATIVE))
- end
-
- def test_unpack_orders
- [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
- [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- ary = []
- 0.upto(w) {|i|
- ary << ((i+1) % 256);
- }
- str = ary.pack("C*")
- flags = word_order|byte_order
- assert_equal(Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags|GENERIC),
- Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags),
- "Bug::Bignum.test_unpack(#{str.dump}, #{numwords}, #{wordsize}, 0, #{'%#x' % flags})")
+ def test_unpack_orders
+ [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
+ [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ ary = []
+ 0.upto(w) {|i|
+ ary << ((i+1) % 256);
}
+ str = ary.pack("C*")
+ flags = word_order|byte_order
+ assert_equal(Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags|GENERIC),
+ Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags),
+ "Bug::Bignum.test_unpack(#{str.dump}, #{numwords}, #{wordsize}, 0, #{'%#x' % flags})")
}
}
}
- end
-
- def test_unpack2comp_single_byte
- assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 0, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 2, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 127, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_unpack2comp_sequence_of_ff
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*2, 2, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*3, 3, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*4, 4, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*5, 5, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*6, 6, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*7, 7, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*8, 8, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*9, 9, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_unpack2comp_negative_single_byte
- assert_equal(-256, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-255, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-254, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-129, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- end
-
- def test_unpack2comp_negative_zero
- 0.upto(100) {|n|
- str = "\x00"*n
- flags = TWOCOMP|BIG_ENDIAN|NEGATIVE
- assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags))
- flags = TWOCOMP|LITTLE_ENDIAN|NEGATIVE
- assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags),
- "Bug::Bignum.test_unpack(#{str.dump}, #{n}, 1, 0, #{'%#x' % flags})")
- }
- end
+ }
+ end
+
+ def test_unpack2comp_single_byte
+ assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 0, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 2, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 127, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
+
+ def test_unpack2comp_sequence_of_ff
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*2, 2, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*3, 3, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*4, 4, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*5, 5, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*6, 6, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*7, 7, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*8, 8, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*9, 9, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
+
+ def test_unpack2comp_negative_single_byte
+ assert_equal(-256, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-255, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-254, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-129, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ end
+
+ def test_unpack2comp_negative_zero
+ 0.upto(100) {|n|
+ str = "\x00"*n
+ flags = TWOCOMP|BIG_ENDIAN|NEGATIVE
+ assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags))
+ flags = TWOCOMP|LITTLE_ENDIAN|NEGATIVE
+ assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags),
+ "Bug::Bignum.test_unpack(#{str.dump}, #{n}, 1, 0, #{'%#x' % flags})")
+ }
end
def test_numbits_2comp
@@ -395,5 +393,4 @@ class Test_Bignum < Test::Unit::TestCase
assert_equal(5, Bug::Bignum.test_numbytes_2comp_with_sign(0x7fffffffff))
assert_equal(6, Bug::Bignum.test_numbytes_2comp_with_sign(0x8000000000))
end
-
end
diff --git a/test/-ext-/bignum/test_str2big.rb b/test/-ext-/bignum/test_str2big.rb
index d5bd72a85b..d27e4d23f7 100644
--- a/test/-ext-/bignum/test_str2big.rb
+++ b/test/-ext-/bignum/test_str2big.rb
@@ -2,37 +2,35 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestStr2big < Test::Unit::TestCase
+class TestBignum_Str2big < Test::Unit::TestCase
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
- def test_str2big_poweroftwo
- s = "1" + "0" * 1000
- n = 16 ** 1000
- assert_equal(n, Bug::Bignum.str2big_poweroftwo(s, 16, true))
- end
-
- def test_str2big_normal
- s = "1" + "0" * 1000
- n = 10 ** 1000
- assert_equal(n, Bug::Bignum.str2big_normal(s, 10, true))
- end
+ def test_str2big_poweroftwo
+ s = "1" + "0" * 1000
+ n = 16 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_poweroftwo(s, 16, true))
+ end
- def test_str2big_karatsuba
- s = "1" + "0" * 1000
- n = 10 ** 1000
- assert_equal(n, Bug::Bignum.str2big_karatsuba(s, 10, true))
- end
+ def test_str2big_normal
+ s = "1" + "0" * 1000
+ n = 10 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_normal(s, 10, true))
+ end
- def test_str2big_gmp
- s = "1" + "0" * 1000
- n = 10 ** 1000
- assert_equal(n, Bug::Bignum.str2big_gmp(s, 10, true))
- rescue NotImplementedError
- end
+ def test_str2big_karatsuba
+ s = "1" + "0" * 1000
+ n = 10 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_karatsuba(s, 10, true))
+ end
+ def test_str2big_gmp
+ s = "1" + "0" * 1000
+ n = 10 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_gmp(s, 10, true))
+ rescue NotImplementedError
end
+
end
diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb
index ac6d92bb67..50f2d8201f 100644
--- a/test/-ext-/bug_reporter/test_bug_reporter.rb
+++ b/test/-ext-/bug_reporter/test_bug_reporter.rb
@@ -1,13 +1,20 @@
# frozen_string_literal: false
require 'test/unit'
require 'tmpdir'
+require_relative '../../lib/jit_support'
class TestBugReporter < Test::Unit::TestCase
+ def yjit_enabled?
+ defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled?
+ end
+
def test_bug_reporter_add
- skip if ENV['RUBY_ON_BUG']
+ pend "macOS 15 is not working with this test" if /darwin/ =~ RUBY_PLATFORM && /15/ =~ `sw_vers -productVersion`
+
+ omit if ENV['RUBY_ON_BUG']
description = RUBY_DESCRIPTION
- description = description.sub(/\+JIT /, '') if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ description = description.sub(/\+MJIT /, '') unless JITSupport.mjit_force_enabled?
expected_stderr = [
:*,
/\[BUG\]\sSegmentation\sfault.*\n/,
@@ -18,9 +25,11 @@ class TestBugReporter < Test::Unit::TestCase
]
tmpdir = Dir.mktmpdir
+ no_core = "Process.setrlimit(Process::RLIMIT_CORE, 0); " if defined?(Process.setrlimit) && defined?(Process::RLIMIT_CORE)
args = ["--disable-gems", "-r-test-/bug_reporter",
"-C", tmpdir]
- stdin = "register_sample_bug_reporter(12345); Process.kill :SEGV, $$"
+ args.push("--yjit") if yjit_enabled? # We want the printed description to match this process's RUBY_DESCRIPTION
+ stdin = "#{no_core}register_sample_bug_reporter(12345); Process.kill :SEGV, $$"
assert_in_out_err(args, stdin, [], expected_stderr, encoding: "ASCII-8BIT")
ensure
FileUtils.rm_rf(tmpdir) if tmpdir
diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index e0152247e7..d6ae953dd2 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -137,6 +137,30 @@ class TestProfileFrames < Test::Unit::TestCase
}
end
+ def test_matches_backtrace_locations_main_thread
+ assert_equal(Thread.current, Thread.main)
+
+ # Keep these in the same line, so the backtraces match exactly
+ backtrace_locations, profile_frames = [Thread.current.backtrace_locations, Bug::Debug.profile_frames(0, 100)]
+
+ assert_equal(backtrace_locations.size, profile_frames.size)
+
+ # The first entries are not going to match, since one is #backtrace_locations and the other #profile_frames
+ backtrace_locations.shift
+ profile_frames.shift
+
+ # The rest of the stack is expected to look the same...
+ backtrace_locations.zip(profile_frames).each.with_index do |(location, (path, absolute_path, _, base_label, _, _, _, _, _, _, lineno)), i|
+ next if absolute_path == "<cfunc>" # ...except for cfunc frames
+
+ err_msg = "#{i}th frame"
+ assert_equal(location.absolute_path, absolute_path, err_msg)
+ assert_equal(location.base_label, base_label, err_msg)
+ assert_equal(location.lineno, lineno, err_msg)
+ assert_equal(location.path, path, err_msg)
+ end
+ end
+
def test_ifunc_frame
bug11851 = '[ruby-core:72409] [Bug #11851]'
assert_ruby_status([], <<~'end;', bug11851) # do
diff --git a/test/-ext-/econv/test_append.rb b/test/-ext-/econv/test_append.rb
new file mode 100644
index 0000000000..f8c1d2add6
--- /dev/null
+++ b/test/-ext-/econv/test_append.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: false
+require 'test/unit'
+require "-test-/econv"
+
+class Test_EConvAppend < Test::Unit::TestCase
+ def test_econv_str_append_valid
+ ec = Bug::EConv.new("utf-8", "cp932")
+ dst = "\u3044".encode("cp932")
+ ret = ec.append("\u3042"*30, dst)
+ assert_same(dst, ret)
+ assert_not_predicate(dst, :ascii_only?)
+ assert_predicate(dst, :valid_encoding?)
+ end
+
+ def test_econv_str_append_broken
+ ec = Bug::EConv.new("utf-8", "cp932")
+ dst = ""
+ ret = ec.append("\u3042"*30, dst)
+ assert_same(dst, ret)
+ assert_not_predicate(dst, :ascii_only?)
+ assert_not_predicate(dst, :valid_encoding?)
+ end
+end
diff --git a/test/-ext-/eval/test_eval.rb b/test/-ext-/eval/test_eval.rb
new file mode 100644
index 0000000000..e37d301b2e
--- /dev/null
+++ b/test/-ext-/eval/test_eval.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: false
+require 'test/unit'
+require "-test-/eval"
+
+class EvalTest < Test::Unit::TestCase
+ def test_rb_eval_string
+ _a = 1
+ assert_equal [self, 1, __method__], rb_eval_string(%q{
+ [self, _a, __method__]
+ })
+ end
+end
diff --git a/test/-ext-/float/test_nextafter.rb b/test/-ext-/float/test_nextafter.rb
index 636f803fac..ea8d7c7fc7 100644
--- a/test/-ext-/float/test_nextafter.rb
+++ b/test/-ext-/float/test_nextafter.rb
@@ -50,9 +50,9 @@ class TestFloatExt < Test::Unit::TestCase
assert_equal(s1, s2,
"Bug::Float.missing_nextafter(#{'%a' % n1}, #{'%a' % n2}) = #{'%a' % v1} != " +
"#{'%a' % v2} = Bug::Float.system_nextafter(#{'%a' % n1}, #{'%a' % n2})")
- rescue Minitest::Assertion
+ rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in nextafter(3) on AIX"
+ omit "Known bug in nextafter(3) on AIX"
end
raise $!
end
diff --git a/test/-ext-/funcall/test_funcall.rb b/test/-ext-/funcall/test_funcall.rb
deleted file mode 100644
index 01a03bf5ef..0000000000
--- a/test/-ext-/funcall/test_funcall.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-
-class TestFuncall < Test::Unit::TestCase
- require '-test-/funcall'
-
- def test_funcall_extra_args
- assert_equal 'TestFuncall', TestFuncall.extra_args_name,
- '[ruby-core:85266] [Bug #14425]'
- end
-end
diff --git a/test/-ext-/funcall/test_passing_block.rb b/test/-ext-/funcall/test_passing_block.rb
index 71c9d905be..8964403494 100644
--- a/test/-ext-/funcall/test_passing_block.rb
+++ b/test/-ext-/funcall/test_passing_block.rb
@@ -9,6 +9,11 @@ class TestFuncall < Test::Unit::TestCase
end
require '-test-/funcall'
+ def test_funcall_extra_args
+ assert_equal 'TestFuncall', TestFuncall.extra_args_name,
+ '[ruby-core:85266] [Bug #14425]'
+ end
+
def test_with_funcall2
ok = nil
Relay.with_funcall2("feature#4504") {|arg| ok = arg || true}
diff --git a/test/-ext-/gvl/test_ubf_async_safe.rb b/test/-ext-/gvl/test_ubf_async_safe.rb
index fdaa4d418b..3261b42475 100644
--- a/test/-ext-/gvl/test_ubf_async_safe.rb
+++ b/test/-ext-/gvl/test_ubf_async_safe.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class TestUbfAsyncSafe < Test::Unit::TestCase
def test_ubf_async_safe
- skip 'need fork for single-threaded test' unless Process.respond_to?(:fork)
+ omit 'need fork for single-threaded test' unless Process.respond_to?(:fork)
IO.pipe do |r, w|
pid = fork do
require '-test-/gvl/call_without_gvl'
diff --git a/test/-ext-/iseq_load/test_iseq_load.rb b/test/-ext-/iseq_load/test_iseq_load.rb
index ffa6541c72..6e5bc8e811 100644
--- a/test/-ext-/iseq_load/test_iseq_load.rb
+++ b/test/-ext-/iseq_load/test_iseq_load.rb
@@ -98,7 +98,7 @@ class TestIseqLoad < Test::Unit::TestCase
iseq = ISeq.iseq_load(a)
iseq.eval
assert_equal false, @next_broke
- skip "failing due to stack_max mismatch"
+ omit "failing due to stack_max mismatch"
assert_iseq_roundtrip(src)
end
@@ -121,7 +121,7 @@ class TestIseqLoad < Test::Unit::TestCase
iseq = ISeq.iseq_load(a)
iseq.eval
assert_equal false, test_break_ensure_def_method
- skip "failing due to exception entry sp mismatch"
+ omit "failing due to exception entry sp mismatch"
assert_iseq_roundtrip(src)
end
@@ -137,7 +137,7 @@ class TestIseqLoad < Test::Unit::TestCase
# FIXME: still failing
def test_require_integration
- skip "iseq loader require integration tests still failing"
+ omit "iseq loader require integration tests still failing"
f = File.expand_path(__FILE__)
# $(top_srcdir)/test/ruby/test_....rb
3.times { f = File.dirname(f) }
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-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb
index df59e76778..0cb7c00761 100644
--- a/test/-ext-/string/test_capacity.rb
+++ b/test/-ext-/string/test_capacity.rb
@@ -4,21 +4,20 @@ require '-test-/string'
require 'rbconfig/sizeof'
class Test_StringCapacity < Test::Unit::TestCase
- def capa(str)
- Bug::String.capacity(str)
- end
-
def test_capacity_embedded
- size = RbConfig::SIZEOF['void*'] * 3 - 1
- assert_equal size, capa('foo')
+ assert_equal GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] - embed_header_size - 1, capa('foo')
+ assert_equal max_embed_len, capa('1' * max_embed_len)
+ assert_equal max_embed_len, capa('1' * (max_embed_len - 1))
end
def test_capacity_shared
- assert_equal 0, capa(:abcdefghijklmnopqrstuvwxyz.to_s)
+ sym = ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).to_sym
+ assert_equal 0, capa(sym.to_s)
end
def test_capacity_normal
- assert_equal 128, capa('1'*128)
+ assert_equal max_embed_len + 1, capa('1' * (max_embed_len + 1))
+ assert_equal max_embed_len + 100, capa('1' * (max_embed_len + 100))
end
def test_s_new_capacity
@@ -39,21 +38,42 @@ class Test_StringCapacity < Test::Unit::TestCase
end
def test_literal_capacity
- s = "I am testing string literal capacity"
+ s = eval(%{
+ # frozen_string_literal: true
+ "#{"a" * (max_embed_len + 1)}"
+ })
assert_equal(s.length, capa(s))
end
def test_capacity_frozen
s = String.new("I am testing", capacity: 1000)
- s << "fstring capacity"
+ s << "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
s.freeze
assert_equal(s.length, capa(s))
end
def test_capacity_fstring
- s = String.new("I am testing", capacity: 1000)
+ s = String.new("a" * max_embed_len, capacity: max_embed_len * 3)
s << "fstring capacity"
s = -s
assert_equal(s.length, capa(s))
end
+
+ private
+
+ def capa(str)
+ Bug::String.capacity(str)
+ end
+
+ def embed_header_size
+ if GC.using_rvargc?
+ 2 * RbConfig::SIZEOF['void*'] + RbConfig::SIZEOF['long']
+ else
+ 2 * RbConfig::SIZEOF['void*']
+ end
+ end
+
+ def max_embed_len
+ GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] - embed_header_size - 1
+ end
end
diff --git a/test/-ext-/string/test_cstr.rb b/test/-ext-/string/test_cstr.rb
index d909781700..efc64119dc 100644
--- a/test/-ext-/string/test_cstr.rb
+++ b/test/-ext-/string/test_cstr.rb
@@ -43,7 +43,11 @@ class Test_StringCStr < Test::Unit::TestCase
end
def test_rb_str_new_frozen_embed
- str = Bug::String.cstr_noembed("rbconfig.rb")
+ # "rbconfi" is the smallest "maximum embeddable string". VWA adds
+ # a capacity field, which removes one pointer capacity for embedded objects,
+ # so if VWA is enabled, but there is only one size pool, then the
+ # maximum embeddable capacity on 32 bit machines is 8 bytes.
+ str = Bug::String.cstr_noembed("rbconfi")
str = Bug::String.rb_str_new_frozen(str)
assert_equal true, Bug::String.cstr_embedded?(str)
end
diff --git a/test/-ext-/string/test_fstring.rb b/test/-ext-/string/test_fstring.rb
index 9b4956ecef..92982a315e 100644
--- a/test/-ext-/string/test_fstring.rb
+++ b/test/-ext-/string/test_fstring.rb
@@ -20,6 +20,10 @@ class Test_String_Fstring < Test::Unit::TestCase
RUBY
end
+ def test_rb_enc_interned_str_null_encoding
+ assert_equal Encoding::ASCII_8BIT, Bug::String.rb_enc_interned_str(nil).encoding
+ end
+
def test_rb_enc_str_new_autoloaded_encoding
assert_separately([], <<~RUBY)
require '-test-/string'
@@ -28,6 +32,10 @@ class Test_String_Fstring < Test::Unit::TestCase
RUBY
end
+ def test_rb_enc_str_new_null_encoding
+ assert_equal Encoding::ASCII_8BIT, Bug::String.rb_enc_str_new(nil).encoding
+ end
+
def test_instance_variable
str = __method__.to_s * 3
str.instance_variable_set(:@test, 42)
@@ -57,18 +65,4 @@ class Test_String_Fstring < Test::Unit::TestCase
str.freeze
assert_fstring(str) {|s| assert_instance_of(S, s)}
end
-
- def test_shared_string_safety
- _unused = -('a' * 30).force_encoding(Encoding::ASCII)
- begin
- verbose_back, $VERBOSE = $VERBOSE, nil
- str = ('a' * 30).force_encoding(Encoding::ASCII).taint
- ensure
- $VERBOSE = verbose_back
- end
- frozen_str = Bug::String.rb_str_new_frozen(str)
- assert_fstring(frozen_str) {|s| assert_equal(str, s)}
- GC.start
- assert_equal('a' * 30, str, "[Bug #16151]")
- end
end
diff --git a/test/-ext-/string/test_rb_str_dup.rb b/test/-ext-/string/test_rb_str_dup.rb
index 49b6af9598..c76a90252f 100644
--- a/test/-ext-/string/test_rb_str_dup.rb
+++ b/test/-ext-/string/test_rb_str_dup.rb
@@ -3,13 +3,15 @@ require '-test-/string'
class Test_RbStrDup < Test::Unit::TestCase
def test_nested_shared_non_frozen
- str = Bug::String.rb_str_dup(Bug::String.rb_str_dup("a" * 50))
+ orig_str = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE]
+ str = Bug::String.rb_str_dup(Bug::String.rb_str_dup(orig_str))
assert_send([Bug::String, :shared_string?, str])
assert_not_send([Bug::String, :sharing_with_shared?, str], '[Bug #15792]')
end
def test_nested_shared_frozen
- str = Bug::String.rb_str_dup(Bug::String.rb_str_dup("a" * 50).freeze)
+ orig_str = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE]
+ str = Bug::String.rb_str_dup(Bug::String.rb_str_dup(orig_str).freeze)
assert_send([Bug::String, :shared_string?, str])
assert_not_send([Bug::String, :sharing_with_shared?, str], '[Bug #15792]')
end
diff --git a/test/-ext-/string/test_set_len.rb b/test/-ext-/string/test_set_len.rb
index 58f51012fb..e3eff75d9b 100644
--- a/test/-ext-/string/test_set_len.rb
+++ b/test/-ext-/string/test_set_len.rb
@@ -4,23 +4,25 @@ require "-test-/string"
class Test_StrSetLen < Test::Unit::TestCase
def setup
- @s0 = [*"a".."z"].join("").freeze
+ # Make string long enough so that it is not embedded
+ @range_end = ("0".ord + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).chr
+ @s0 = [*"0"..@range_end].join("").freeze
@s1 = Bug::String.new(@s0)
end
def teardown
- orig = [*"a".."z"].join("")
+ orig = [*"0"..@range_end].join("")
assert_equal(orig, @s0)
end
def test_non_shared
@s1.modify!
- assert_equal("abc", @s1.set_len(3))
+ assert_equal("012", @s1.set_len(3))
end
def test_shared
assert_raise(RuntimeError) {
- assert_equal("abc", @s1.set_len(3))
+ @s1.set_len(3)
}
end
@@ -32,4 +34,33 @@ class Test_StrSetLen < Test::Unit::TestCase
assert_equal 128, Bug::String.capacity(str)
assert_equal 127, str.set_len(127).bytesize, bug12757
end
+
+ def test_coderange_after_append
+ u = -"\u3042"
+ str = Bug::String.new(encoding: Encoding::UTF_8)
+ bsize = u.bytesize
+ str.append(u)
+ assert_equal 0, str.bytesize
+ str.set_len(bsize)
+ assert_equal bsize, str.bytesize
+ assert_predicate str, :valid_encoding?
+ assert_not_predicate str, :ascii_only?
+ assert_equal u, str
+ end
+
+ def test_coderange_after_trunc
+ u = -"\u3042"
+ bsize = u.bytesize
+ str = Bug::String.new(u)
+ str.set_len(bsize - 1)
+ assert_equal bsize - 1, str.bytesize
+ assert_not_predicate str, :valid_encoding?
+ assert_not_predicate str, :ascii_only?
+ str.append(u.byteslice(-1))
+ str.set_len(bsize)
+ assert_equal bsize, str.bytesize
+ assert_predicate str, :valid_encoding?
+ assert_not_predicate str, :ascii_only?
+ assert_equal u, str
+ end
end
diff --git a/test/-ext-/symbol/test_type.rb b/test/-ext-/symbol/test_type.rb
index 7cb3c7b6ef..2b0fbe5b79 100644
--- a/test/-ext-/symbol/test_type.rb
+++ b/test/-ext-/symbol/test_type.rb
@@ -93,16 +93,16 @@ module Test_Symbol
assert_symtype("@foo=", :attrset?)
assert_symtype("@@foo=", :attrset?)
assert_symtype("$foo=", :attrset?)
- assert_symtype("0=", :attrset?)
- assert_symtype("@=", :attrset?)
- assert_symtype("@@=", :attrset?)
+ assert_not_symtype("0=", :attrset?)
+ assert_not_symtype("@=", :attrset?)
+ assert_not_symtype("@@=", :attrset?)
assert_not_symtype("foo", :attrset?)
assert_not_symtype("Foo", :attrset?)
assert_not_symtype("@foo", :attrset?)
assert_not_symtype("@@foo", :attrset?)
assert_not_symtype("$foo", :attrset?)
assert_not_symtype("[foo]", :attrset?)
- assert_symtype("[foo]=", :attrset?)
+ assert_not_symtype("[foo]=", :attrset?)
assert_equal(:"foo=", Bug::Symbol.attrset("foo"))
assert_symtype(Bug::Symbol.attrset("foo"), :attrset?)
assert_equal(:"Foo=", Bug::Symbol.attrset("Foo"))
@@ -114,7 +114,6 @@ module Test_Symbol
assert_equal(:"$foo=", Bug::Symbol.attrset("$foo"))
assert_symtype(Bug::Symbol.attrset("$foo"), :attrset?)
assert_equal(:"[foo]=", Bug::Symbol.attrset("[foo]"))
- assert_symtype(Bug::Symbol.attrset("[foo]"), :attrset?)
assert_equal(:[]=, Bug::Symbol.attrset(:[]))
assert_symtype(Bug::Symbol.attrset("foo?="), :attrset?)
assert_equal(:"foo?=", Bug::Symbol.attrset(:foo?))
@@ -135,5 +134,10 @@ module Test_Symbol
Bug::Symbol.find(cx)
}
end
+
+ def test_const_name_type
+ sym = "\xb5".force_encoding(Encoding::Windows_1253)
+ assert_not_operator Bug::Symbol, :const?, sym, sym.encode(Encoding::UTF_8)
+ end
end
end
diff --git a/test/-ext-/test_abi.rb b/test/-ext-/test_abi.rb
new file mode 100644
index 0000000000..d3ea6bb9b1
--- /dev/null
+++ b/test/-ext-/test_abi.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+return unless RUBY_PATCHLEVEL < 0
+
+class TestABI < Test::Unit::TestCase
+ def test_require_lib_with_incorrect_abi_on_dev_ruby
+ omit "ABI is not checked" unless abi_checking_supported?
+
+ assert_separately [], <<~RUBY
+ err = assert_raise(LoadError) { require "-test-/abi" }
+ assert_match(/incompatible ABI version/, err.message)
+ assert_include err.message, "/-test-/abi."
+ RUBY
+ end
+
+ def test_disable_abi_check_using_environment_variable
+ omit "ABI is not checked" unless abi_checking_supported?
+
+ assert_separately [{ "RUBY_ABI_CHECK" => "0" }], <<~RUBY
+ assert_nothing_raised { require "-test-/abi" }
+ RUBY
+ end
+
+ def test_enable_abi_check_using_environment_variable
+ omit "ABI is not checked" unless abi_checking_supported?
+
+ assert_separately [{ "RUBY_ABI_CHECK" => "1" }], <<~RUBY
+ err = assert_raise(LoadError) { require "-test-/abi" }
+ assert_match(/incompatible ABI version/, err.message)
+ assert_include err.message, "/-test-/abi."
+ RUBY
+ end
+
+ def test_require_lib_with_incorrect_abi_on_release_ruby
+ omit "ABI is enforced" if abi_checking_supported?
+
+ assert_separately [], <<~RUBY
+ assert_nothing_raised { require "-test-/abi" }
+ RUBY
+ end
+
+ private
+
+ def abi_checking_supported?
+ !(RUBY_PLATFORM =~ /mswin|mingw/)
+ end
+end
diff --git a/test/-ext-/test_random.rb b/test/-ext-/test_random.rb
index 838e5d2f14..e5cebcc871 100644
--- a/test/-ext-/test_random.rb
+++ b/test/-ext-/test_random.rb
@@ -1,11 +1,13 @@
require 'test/unit'
module TestRandomExt
+ def setup
+ super
+ assert_nothing_raised(LoadError) {require '-test-/random'}
+ end
+
class TestLoop < Test::Unit::TestCase
- def setup
- super
- assert_nothing_raised(LoadError) {require '-test-/random'}
- end
+ include TestRandomExt
def test_bytes
rnd = Bug::Random::Loop.new(1)
@@ -24,4 +26,20 @@ module TestRandomExt
assert_equal(1.00, Bug::Random::Loop.new(4<<14).rand)
end
end
+
+ class TestVersionZero < Test::Unit::TestCase
+ include TestRandomExt
+
+ def test_bad_version
+ assert_raise(TypeError) {Bug::Random::VersionZero.new}
+ end
+ end
+
+ class TestVersionMax < Test::Unit::TestCase
+ include TestRandomExt
+
+ def test_bad_version
+ assert_raise(TypeError) {Bug::Random::VersionMax.new}
+ end
+ end
end
diff --git a/test/-ext-/thread/test_instrumentation_api.rb b/test/-ext-/thread/test_instrumentation_api.rb
new file mode 100644
index 0000000000..dd620e7380
--- /dev/null
+++ b/test/-ext-/thread/test_instrumentation_api.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: false
+require 'envutil'
+
+class TestThreadInstrumentation < Test::Unit::TestCase
+ def setup
+ pend("No windows support") if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+
+ require '-test-/thread/instrumentation'
+
+ Thread.list.each do |thread|
+ if thread != Thread.current
+ thread.kill
+ thread.join rescue nil
+ end
+ end
+ assert_equal [Thread.current], Thread.list
+
+ Bug::ThreadInstrumentation.reset_counters
+ Bug::ThreadInstrumentation::register_callback
+ end
+
+ def teardown
+ return if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ Bug::ThreadInstrumentation::unregister_callback
+ end
+
+ THREADS_COUNT = 3
+
+ def test_thread_instrumentation
+ threads = threaded_cpu_work
+ assert_equal [false] * THREADS_COUNT, threads.map(&:status)
+ counters = Bug::ThreadInstrumentation.counters
+ assert_join_counters(counters)
+ assert_global_join_counters(counters)
+ end
+
+ def test_join_counters # Bug #18900
+ thr = Thread.new { fib(30) }
+ Bug::ThreadInstrumentation.reset_counters
+ thr.join
+ assert_join_counters(Bug::ThreadInstrumentation.local_counters)
+ end
+
+ def test_thread_instrumentation_fork_safe
+ skip "No fork()" unless Process.respond_to?(:fork)
+
+ thread_statuses = counters = nil
+ IO.popen("-") do |read_pipe|
+ if read_pipe
+ thread_statuses = Marshal.load(read_pipe)
+ counters = Marshal.load(read_pipe)
+ else
+ Bug::ThreadInstrumentation.reset_counters
+ threads = threaded_cpu_work
+ Marshal.dump(threads.map(&:status), STDOUT)
+ Marshal.dump(Bug::ThreadInstrumentation.counters, STDOUT)
+ end
+ end
+ assert_predicate $?, :success?
+
+ assert_equal [false] * THREADS_COUNT, thread_statuses
+ assert_join_counters(counters)
+ assert_global_join_counters(counters)
+ end
+
+ def test_thread_instrumentation_unregister
+ Bug::ThreadInstrumentation::unregister_callback
+ assert Bug::ThreadInstrumentation::register_and_unregister_callbacks
+ end
+
+ private
+
+ def fib(n = 20)
+ return n if n <= 1
+ fib(n-1) + fib(n-2)
+ end
+
+ def threaded_cpu_work(size = 20)
+ THREADS_COUNT.times.map { Thread.new { fib(size) } }.each(&:join)
+ end
+
+ def assert_join_counters(counters)
+ counters.each_with_index do |c, i|
+ assert_operator c, :>, 0, "Call counters[#{i}]: #{counters.inspect}"
+ end
+ end
+
+ def assert_global_join_counters(counters)
+ assert_equal THREADS_COUNT, counters.first
+ end
+end
diff --git a/test/-ext-/thread_fd/test_thread_fd_close.rb b/test/-ext-/thread_fd/test_thread_fd_close.rb
index a53949b93b..1d2ef63635 100644
--- a/test/-ext-/thread_fd/test_thread_fd_close.rb
+++ b/test/-ext-/thread_fd/test_thread_fd_close.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'test/unit'
require '-test-/thread_fd'
-require 'io/wait'
class TestThreadFdClose < Test::Unit::TestCase
diff --git a/test/-ext-/wait/test_wait.rb b/test/-ext-/wait/test_wait.rb
index 79127c041b..8e53f067cf 100644
--- a/test/-ext-/wait/test_wait.rb
+++ b/test/-ext-/wait/test_wait.rb
@@ -12,14 +12,18 @@ class TestWait < Test::Unit::TestCase
end
def test_wait_for_invalid_fd
- r, w = IO.pipe
- r.close
+ assert_separately [], <<~'RUBY'
+ require '-test-/wait'
- IO.for_fd(w.fileno).close
+ r, w = IO.pipe
+ r.close
- assert_raise(Errno::EBADF) do
- IO.io_wait(w, IO::WRITABLE, nil)
- end
+ IO.for_fd(w.fileno).close
+
+ assert_raise(Errno::EBADF) do
+ IO.io_wait(w, IO::WRITABLE, nil)
+ end
+ RUBY
end
def test_wait_for_closed_pipe
diff --git a/test/bigdecimal/helper.rb b/test/bigdecimal/helper.rb
index 22b05f09ae..46721fb9a8 100644
--- a/test/bigdecimal/helper.rb
+++ b/test/bigdecimal/helper.rb
@@ -1,8 +1,19 @@
# frozen_string_literal: false
require "test/unit"
require "bigdecimal"
+require 'rbconfig/sizeof'
module TestBigDecimalBase
+ if RbConfig::SIZEOF.key?("int64_t")
+ SIZEOF_DECDIG = RbConfig::SIZEOF["int32_t"]
+ BASE = 1_000_000_000
+ BASE_FIG = 9
+ else
+ SIZEOF_DECDIG = RbConfig::SIZEOF["int16_t"]
+ BASE = 1000
+ BASE_FIG = 4
+ end
+
def setup
@mode = BigDecimal.mode(BigDecimal::EXCEPTION_ALL)
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true)
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 99f92c461c..0228240506 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: false
require_relative "helper"
require 'bigdecimal/math'
-require 'rbconfig/sizeof'
class TestBigDecimal < Test::Unit::TestCase
include TestBigDecimalBase
@@ -12,7 +11,12 @@ class TestBigDecimal < Test::Unit::TestCase
require 'fiddle'
LONG_MAX = (1 << (Fiddle::SIZEOF_LONG*8 - 1)) - 1
LONG_MIN = [LONG_MAX + 1].pack("L!").unpack("l!")[0]
+ LLONG_MAX = (1 << (Fiddle::SIZEOF_LONG_LONG*8 - 1)) - 1
+ LLONG_MIN = [LLONG_MAX + 1].pack("Q!").unpack("q!")[0]
+ ULLONG_MAX = (1 << Fiddle::SIZEOF_LONG_LONG*8) - 1
LIMITS = {
+ "LLONG_MIN" => LLONG_MIN,
+ "ULLONG_MAX" => ULLONG_MAX,
"FIXNUM_MIN" => LONG_MIN / 2,
"FIXNUM_MAX" => LONG_MAX / 2,
"INT64_MIN" => -9223372036854775808,
@@ -96,6 +100,19 @@ class TestBigDecimal < Test::Unit::TestCase
assert_not_same(bd, BigDecimal(bd, 1, exception: false))
end
+ def test_BigDecimal_issue_192
+ # https://github.com/ruby/bigdecimal/issues/192
+ # https://github.com/rails/rails/pull/42125
+ if BASE_FIG == 9
+ int = 1_000_000_000_12345_0000
+ big = BigDecimal("0.100000000012345e19")
+ else # BASE_FIG == 4
+ int = 1_0000_12_00
+ big = BigDecimal("0.1000012e9")
+ end
+ assert_equal(BigDecimal(int), big, "[ruby/bigdecimal#192]")
+ end
+
def test_BigDecimal_with_invalid_string
[
'', '.', 'e1', 'd1', '.e', '.d', '1.e', '1.d', '.1e', '.1d',
@@ -146,6 +163,7 @@ class TestBigDecimal < Test::Unit::TestCase
def test_BigDecimal_with_float
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
+ assert_equal(BigDecimal("0.01"), BigDecimal(0.01, Float::DIG + 1))
assert_raise_with_message(ArgumentError, "can't omit precision for a Float.") { BigDecimal(4.2) }
assert_raise(ArgumentError) { BigDecimal(0.1, Float::DIG + 2) }
assert_nothing_raised { BigDecimal(0.1, Float::DIG + 1) }
@@ -656,13 +674,10 @@ class TestBigDecimal < Test::Unit::TestCase
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
+ Warning[:deprecated] = true if defined?(Warning.[])
BigDecimal("1").precs
end
- ensure
- Warning[:deprecated] = saved
end
def test_precs
@@ -938,9 +953,13 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(2, BigDecimal("2") / 1)
assert_equal(-2, BigDecimal("2") / -1)
- assert_equal(BigDecimal('1486.868686869'), BigDecimal('1472.0') / BigDecimal('0.99'), '[ruby-core:59365] [#9316]')
+ assert_equal(BigDecimal('1486.868686869'),
+ (BigDecimal('1472.0') / BigDecimal('0.99')).round(9),
+ '[ruby-core:59365] [#9316]')
- assert_equal(4.124045235, BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0')), '[#9305]')
+ assert_in_delta(4.124045235,
+ (BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0'))).round(9, half: :up),
+ 10**Float::MIN_10_EXP, '[#9305]')
BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
assert_positive_zero(BigDecimal("1.0") / BigDecimal("Infinity"))
@@ -950,8 +969,24 @@ class TestBigDecimal < Test::Unit::TestCase
BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false)
- assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { BigDecimal("1") / 0 }
- assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { BigDecimal("-1") / 0 }
+ assert_raise_with_message(FloatDomainError, "Computation results in 'Infinity'") { BigDecimal("1") / 0 }
+ assert_raise_with_message(FloatDomainError, "Computation results in '-Infinity'") { BigDecimal("-1") / 0 }
+ end
+
+ def test_div_gh220
+ x = BigDecimal("1.0")
+ y = BigDecimal("3672577333.6608990499165058135986328125")
+ c = BigDecimal("0.272288343892592687909520102748926752911779209181321744700032723729015151607289998e-9")
+ assert_equal(c, x / y, "[GH-220]")
+ end
+
+ def test_div_precision
+ bug13754 = '[ruby-core:82107] [Bug #13754]'
+ a = BigDecimal('101')
+ b = BigDecimal('0.9163472602589686')
+ c = a/b
+ assert(c.precision > b.precision,
+ "(101/0.9163472602589686).precision >= (0.9163472602589686).precision #{bug13754}")
end
def test_div_with_float
@@ -1015,6 +1050,19 @@ class TestBigDecimal < Test::Unit::TestCase
assert_raise(ZeroDivisionError){BigDecimal("0").divmod(0)}
end
+ def test_divmod_precision
+ a = BigDecimal('2e55')
+ b = BigDecimal('1.23456789e10')
+ q, r = a.divmod(b)
+ assert_equal((a/b).round(0, :down), q)
+ assert_equal((a - q*b), r)
+
+ b = BigDecimal('-1.23456789e10')
+ q, r = a.divmod(b)
+ assert_equal((a/b).round(0, :down) - 1, q)
+ assert_equal((a - q*b), r)
+ end
+
def test_divmod_error
assert_raise(TypeError) { BigDecimal(20).divmod('2') }
end
@@ -1052,6 +1100,40 @@ class TestBigDecimal < Test::Unit::TestCase
end
end
+ def test_div_bigdecimal_with_float_and_precision
+ x = BigDecimal(5)
+ y = 5.1
+ assert_equal(x.div(BigDecimal(y, 0), 8),
+ x.div(y, 8))
+
+ assert_equal(x.div(BigDecimal(y, 0), 100),
+ x.div(y, 100))
+ end
+
+ def test_quo_without_prec
+ x = BigDecimal(5)
+ y = BigDecimal(229)
+ assert_equal(BigDecimal("0.021834061135371179039301310043668122"), x.quo(y))
+ end
+
+ def test_quo_with_prec
+ begin
+ saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE)
+ BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
+
+ x = BigDecimal(5)
+ y = BigDecimal(229)
+ assert_equal(BigDecimal("0.021834061135371179039301310043668122"), x.quo(y, 0))
+ assert_equal(BigDecimal("0.022"), x.quo(y, 2))
+ assert_equal(BigDecimal("0.0218"), x.quo(y, 3))
+ assert_equal(BigDecimal("0.0218341"), x.quo(y, 6))
+ assert_equal(BigDecimal("0.02183406114"), x.quo(y, 10))
+ assert_equal(BigDecimal("0.021834061135371179039301310043668122270742358078603"), x.quo(y, 50))
+ ensure
+ BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode)
+ end
+ end
+
def test_abs_bigdecimal
x = BigDecimal((2**100).to_s)
assert_equal(1267650600228229401496703205376, x.abs)
@@ -1288,8 +1370,18 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_round_half_invalid_option
- assert_raise_with_message(ArgumentError, "invalid rounding mode: invalid") { BigDecimal('12.5').round(half: :invalid) }
- assert_raise_with_message(ArgumentError, "invalid rounding mode: invalid") { BigDecimal('2.15').round(1, half: :invalid) }
+ assert_raise_with_message(ArgumentError, "invalid rounding mode (upp)") do
+ BigDecimal('12.5').round(half: :upp)
+ end
+ assert_raise_with_message(ArgumentError, "invalid rounding mode (evenn)") do
+ BigDecimal('2.15').round(1, half: :evenn)
+ end
+ assert_raise_with_message(ArgumentError, "invalid rounding mode (downn)") do
+ BigDecimal('2.15').round(1, half: :downn)
+ end
+ assert_raise_with_message(ArgumentError, "invalid rounding mode (42)") do
+ BigDecimal('2.15').round(1, half: 42)
+ end
end
def test_truncate
@@ -1997,10 +2089,14 @@ class TestBigDecimal < Test::Unit::TestCase
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.01").precision)
+ assert_equal(2, BigDecimal("-0.01").precision)
assert_equal(2, BigDecimal("0.11").precision)
assert_equal(2, BigDecimal("-0.11").precision)
+ assert_equal(9, BigDecimal("0.000_000_001").precision)
+ assert_equal(9, BigDecimal("-0.000_000_001").precision)
+ assert_equal(10, BigDecimal("0.000_000_000_1").precision)
+ assert_equal(10, BigDecimal("-0.000_000_000_1").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)
@@ -2008,12 +2104,8 @@ class TestBigDecimal < Test::Unit::TestCase
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(5, BigDecimal("11111e-2").precision)
assert_equal(5, BigDecimal("-11111e-2").precision)
assert_equal(21, BigDecimal("100.000_000_000_000_000_001").precision)
@@ -2031,6 +2123,70 @@ class TestBigDecimal < Test::Unit::TestCase
end
end
+ def test_scale_only_integer
+ assert_equal(0, BigDecimal(0).scale)
+ assert_equal(0, BigDecimal(1).scale)
+ assert_equal(0, BigDecimal(-1).scale)
+ assert_equal(0, BigDecimal(10).scale)
+ assert_equal(0, BigDecimal(-10).scale)
+ assert_equal(0, BigDecimal(100_000_000).scale)
+ assert_equal(0, BigDecimal(-100_000_000).scale)
+ assert_equal(0, BigDecimal(100_000_000_000).scale)
+ assert_equal(0, BigDecimal(-100_000_000_000).scale)
+ assert_equal(0, BigDecimal(100_000_000_000_000_000_000).scale)
+ assert_equal(0, BigDecimal(-100_000_000_000_000_000_000).scale)
+ assert_equal(0, BigDecimal("111e100").scale)
+ assert_equal(0, BigDecimal("-111e100").scale)
+ end
+
+ def test_scale_only_fraction
+ assert_equal(1, BigDecimal("0.1").scale)
+ assert_equal(1, BigDecimal("-0.1").scale)
+ assert_equal(2, BigDecimal("0.01").scale)
+ assert_equal(2, BigDecimal("-0.01").scale)
+ assert_equal(2, BigDecimal("0.11").scale)
+ assert_equal(2, BigDecimal("-0.11").scale)
+ assert_equal(21, BigDecimal("0.000_000_000_000_000_000_001").scale)
+ assert_equal(21, BigDecimal("-0.000_000_000_000_000_000_001").scale)
+ assert_equal(100, BigDecimal("111e-100").scale)
+ assert_equal(100, BigDecimal("-111e-100").scale)
+ end
+
+ def test_scale_full
+ assert_equal(1, BigDecimal("0.1").scale)
+ assert_equal(1, BigDecimal("-0.1").scale)
+ assert_equal(2, BigDecimal("0.01").scale)
+ assert_equal(2, BigDecimal("-0.01").scale)
+ assert_equal(2, BigDecimal("0.11").scale)
+ assert_equal(2, BigDecimal("-0.11").scale)
+ assert_equal(2, BigDecimal("11111e-2").scale)
+ assert_equal(2, BigDecimal("-11111e-2").scale)
+ assert_equal(18, BigDecimal("100.000_000_000_000_000_001").scale)
+ assert_equal(18, BigDecimal("-100.000_000_000_000_000_001").scale)
+ end
+
+ def test_scale_special
+ BigDecimal.save_exception_mode do
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ assert_equal(0, BigDecimal("Infinity").scale)
+ assert_equal(0, BigDecimal("-Infinity").scale)
+ assert_equal(0, BigDecimal("NaN").scale)
+ end
+ end
+
+ def test_precision_scale
+ assert_equal([2, 0], BigDecimal("11.0").precision_scale)
+ assert_equal([2, 1], BigDecimal("1.1").precision_scale)
+ assert_equal([2, 2], BigDecimal("0.11").precision_scale)
+
+ BigDecimal.save_exception_mode do
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ assert_equal([0, 0], BigDecimal("Infinity").precision_scale)
+ 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)
@@ -2091,6 +2247,15 @@ class TestBigDecimal < Test::Unit::TestCase
assert_raise(err) { bd.send(:initialize_dup, bd2) }
end
+ def test_llong_min_gh_200
+ # https://github.com/ruby/bigdecimal/issues/199
+ # Between LLONG_MIN and -ULLONG_MAX
+ assert_equal(BigDecimal(LIMITS["LLONG_MIN"].to_s), BigDecimal(LIMITS["LLONG_MIN"]), "[GH-200]")
+
+ minus_ullong_max = -LIMITS["ULLONG_MAX"]
+ assert_equal(BigDecimal(minus_ullong_max.to_s), BigDecimal(minus_ullong_max), "[GH-200]")
+ 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 ffd4c5f679..2f27163ebf 100644
--- a/test/bigdecimal/test_bigdecimal_util.rb
+++ b/test/bigdecimal/test_bigdecimal_util.rb
@@ -25,6 +25,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
assert_equal(9.05, 9.05.to_d.to_f)
assert_equal("9.05", 9.05.to_d.to_s('F'))
+ assert_equal("65.6", 65.6.to_d.to_s("F"))
+
assert_equal(Math::PI, Math::PI.to_d.to_f)
bug9214 = '[ruby-core:58858]'
@@ -60,6 +62,19 @@ class TestBigDecimalUtil < Test::Unit::TestCase
"[ruby-core:80234] [Bug #13331]")
end
+ def test_Float_to_d_issue_192
+ # https://github.com/ruby/bigdecimal/issues/192
+ # https://github.com/rails/rails/pull/42125
+ if BASE_FIG == 9
+ flo = 1_000_000_000.12345
+ big = BigDecimal("0.100000000012345e10")
+ else # BASE_FIG == 4
+ flo = 1_0000.12
+ big = BigDecimal("0.1000012e5")
+ end
+ assert_equal(flo.to_d, big, "[ruby/bigdecimal#192]")
+ end
+
def test_Rational_to_d
digits = 100
delta = 1.0/10**(digits)
diff --git a/test/bigdecimal/test_ractor.rb b/test/bigdecimal/test_ractor.rb
index f78663f15e..798cc494e1 100644
--- a/test/bigdecimal/test_ractor.rb
+++ b/test/bigdecimal/test_ractor.rb
@@ -6,7 +6,7 @@ class TestBigDecimalRactor < Test::Unit::TestCase
def setup
super
- skip unless defined? Ractor
+ omit unless defined? Ractor
end
def test_ractor_shareable
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb
index 115a57e4a1..eadae45313 100644
--- a/test/cgi/test_cgi_cookie.rb
+++ b/test/cgi/test_cgi_cookie.rb
@@ -60,6 +60,27 @@ class CGICookieTest < Test::Unit::TestCase
end
+ def test_cgi_cookie_new_with_domain
+ h = {'name'=>'name1', 'value'=>'value1'}
+ cookie = CGI::Cookie.new(h.merge('domain'=>'a.example.com'))
+ assert_equal('a.example.com', cookie.domain)
+
+ cookie = CGI::Cookie.new(h.merge('domain'=>'.example.com'))
+ assert_equal('.example.com', cookie.domain)
+
+ cookie = CGI::Cookie.new(h.merge('domain'=>'1.example.com'))
+ assert_equal('1.example.com', cookie.domain, 'enhanced by RFC 1123')
+
+ assert_raise(ArgumentError) {
+ CGI::Cookie.new(h.merge('domain'=>'-a.example.com'))
+ }
+
+ assert_raise(ArgumentError) {
+ CGI::Cookie.new(h.merge('domain'=>'a-.example.com'))
+ }
+ end
+
+
def test_cgi_cookie_scriptname
cookie = CGI::Cookie.new('name1', 'value1')
assert_equal('', cookie.path)
@@ -101,6 +122,11 @@ class CGICookieTest < Test::Unit::TestCase
end
end
+ def test_cgi_cookie_parse_not_decode_name
+ cookie_str = "%66oo=baz;foo=bar"
+ cookies = CGI::Cookie.parse(cookie_str)
+ assert_equal({"%66oo" => ["baz"], "foo" => ["bar"]}, cookies)
+ end
def test_cgi_cookie_arrayinterface
cookie = CGI::Cookie.new('name1', 'a', 'b', 'c')
@@ -113,6 +139,70 @@ 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_header.rb b/test/cgi/test_cgi_header.rb
index bab2d0348a..ec2f4deb72 100644
--- a/test/cgi/test_cgi_header.rb
+++ b/test/cgi/test_cgi_header.rb
@@ -176,6 +176,14 @@ 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/cgi/test_cgi_util.rb b/test/cgi/test_cgi_util.rb
index 6ce8b42c20..d058cccd86 100644
--- a/test/cgi/test_cgi_util.rb
+++ b/test/cgi/test_cgi_util.rb
@@ -23,7 +23,6 @@ class CGIUtilTest < Test::Unit::TestCase
ENV.update(@environ)
end
-
def test_cgi_escape
assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escape(@str1))
assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escape(@str1).ascii_only?) if defined?(::Encoding)
@@ -70,6 +69,54 @@ class CGIUtilTest < Test::Unit::TestCase
end;
end
+ def test_cgi_escapeURIComponent
+ assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escapeURIComponent(@str1))
+ assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escapeURIComponent(@str1).ascii_only?) if defined?(::Encoding)
+ end
+
+ def test_cgi_escapeURIComponent_with_unreserved_characters
+ assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",
+ CGI.escapeURIComponent("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"),
+ "should not encode any unreserved characters, as per RFC3986 Section 2.3")
+ end
+
+ def test_cgi_escapeURIComponent_with_invalid_byte_sequence
+ assert_equal('%C0%3C%3C', CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")))
+ end
+
+ def test_cgi_escapeURIComponent_preserve_encoding
+ assert_equal(Encoding::US_ASCII, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("US-ASCII")).encoding)
+ assert_equal(Encoding::ASCII_8BIT, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("ASCII-8BIT")).encoding)
+ assert_equal(Encoding::UTF_8, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")).encoding)
+ end
+
+ def test_cgi_unescapeURIComponent
+ str = CGI.unescapeURIComponent('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93')
+ assert_equal(@str1, str)
+ return unless defined?(::Encoding)
+
+ assert_equal("foo+bar", CGI.unescapeURIComponent("foo+bar"))
+
+ assert_equal(@str1.encoding, str.encoding)
+ assert_equal("\u{30E1 30E2 30EA 691C 7D22}", CGI.unescapeURIComponent("\u{30E1 30E2 30EA}%E6%A4%9C%E7%B4%A2"))
+ end
+
+ def test_cgi_unescapeURIComponent_preserve_encoding
+ assert_equal(Encoding::US_ASCII, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("US-ASCII")).encoding)
+ assert_equal(Encoding::ASCII_8BIT, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("ASCII-8BIT")).encoding)
+ assert_equal(Encoding::UTF_8, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("UTF-8")).encoding)
+ end
+
+ def test_cgi_unescapeURIComponent_accept_charset
+ return unless defined?(::Encoding)
+
+ assert_raise(TypeError) {CGI.unescapeURIComponent('', nil)}
+ assert_separately(%w[-rcgi/util], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ assert_equal("", CGI.unescapeURIComponent(''))
+ end;
+ end
+
def test_cgi_pretty
assert_equal("<HTML>\n <BODY>\n </BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>"))
assert_equal("<HTML>\n\t<BODY>\n\t</BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>","\t"))
@@ -104,6 +151,24 @@ class CGIUtilTest < Test::Unit::TestCase
assert_not_predicate CGI.escapeHTML("Ruby".freeze), :frozen?
end
+ def test_cgi_escape_html_large
+ return if RUBY_ENGINE == 'jruby'
+ ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX")
+ return unless ulong_max < size_max # Platforms not concerned
+
+ size = (ulong_max / 6 + 1)
+ begin
+ str = '"' * size
+ escaped = CGI.escapeHTML(str)
+ rescue NoMemoryError
+ omit "Not enough memory"
+ rescue => e
+ end
+ assert_raise_with_message(ArgumentError, /overflow/, ->{"length = #{escaped.length}"}) do
+ raise e if e
+ end
+ end
+
def test_cgi_unescapeHTML
assert_equal("'&\"><", CGI.unescapeHTML("&#39;&amp;&quot;&gt;&lt;"))
end
@@ -179,6 +244,14 @@ class CGIUtilTest < Test::Unit::TestCase
assert_equal("<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"]))
assert_equal("<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escape_element('<BR><A HREF="url"></A>', "A", "IMG"))
assert_equal("<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escape_element('<BR><A HREF="url"></A>', ["A", "IMG"]))
+
+ assert_equal("&lt;A &lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escapeElement('<A <A HREF="url"></A>', "A", "IMG"))
+ assert_equal("&lt;A &lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escapeElement('<A <A HREF="url"></A>', ["A", "IMG"]))
+ assert_equal("&lt;A &lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escape_element('<A <A HREF="url"></A>', "A", "IMG"))
+ assert_equal("&lt;A &lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt;", escape_element('<A <A HREF="url"></A>', ["A", "IMG"]))
+
+ assert_equal("&lt;A &lt;A ", escapeElement('<A <A ', "A", "IMG"))
+ assert_equal("&lt;A &lt;A ", escapeElement('<A <A ', ["A", "IMG"]))
end
@@ -187,6 +260,16 @@ class CGIUtilTest < Test::Unit::TestCase
assert_equal('&lt;BR&gt;<A HREF="url"></A>', unescapeElement(escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]))
assert_equal('&lt;BR&gt;<A HREF="url"></A>', unescape_element(escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG"))
assert_equal('&lt;BR&gt;<A HREF="url"></A>', unescape_element(escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]))
+
+ assert_equal('<A <A HREF="url"></A>', unescapeElement(escapeHTML('<A <A HREF="url"></A>'), "A", "IMG"))
+ assert_equal('<A <A HREF="url"></A>', unescapeElement(escapeHTML('<A <A HREF="url"></A>'), ["A", "IMG"]))
+ assert_equal('<A <A HREF="url"></A>', unescape_element(escapeHTML('<A <A HREF="url"></A>'), "A", "IMG"))
+ assert_equal('<A <A HREF="url"></A>', unescape_element(escapeHTML('<A <A HREF="url"></A>'), ["A", "IMG"]))
+
+ assert_equal('<A <A ', unescapeElement(escapeHTML('<A <A '), "A", "IMG"))
+ assert_equal('<A <A ', unescapeElement(escapeHTML('<A <A '), ["A", "IMG"]))
+ assert_equal('<A <A ', unescape_element(escapeHTML('<A <A '), "A", "IMG"))
+ assert_equal('<A <A ', unescape_element(escapeHTML('<A <A '), ["A", "IMG"]))
end
end
diff --git a/test/coverage/autostart.rb b/test/coverage/autostart.rb
new file mode 100644
index 0000000000..067fe0a40d
--- /dev/null
+++ b/test/coverage/autostart.rb
@@ -0,0 +1,2 @@
+require 'coverage'
+Coverage.start(:all)
diff --git a/test/coverage/main.rb b/test/coverage/main.rb
new file mode 100644
index 0000000000..74f1e95fa3
--- /dev/null
+++ b/test/coverage/main.rb
@@ -0,0 +1 @@
+puts Coverage.peek_result[__FILE__][:lines]
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb
index 22557bd9d8..a2efa0d1c0 100644
--- a/test/coverage/test_coverage.rb
+++ b/test/coverage/test_coverage.rb
@@ -26,6 +26,13 @@ class TestCoverage < Test::Unit::TestCase
end;
end
+ def test_coverage_in_main_script
+ autostart_path = File.expand_path("autostart.rb", __dir__)
+ main_path = File.expand_path("main.rb", __dir__)
+
+ assert_in_out_err(['-r', autostart_path, main_path], "", ["1"], [])
+ end
+
def test_coverage_running?
assert_in_out_err(%w[-rcoverage], <<-"end;", ["false", "true", "true", "false"], [])
p Coverage.running?
@@ -136,7 +143,7 @@ class TestCoverage < Test::Unit::TestCase
f.puts 'REPEATS = 400'
f.puts 'def add_method(target)'
f.puts ' REPEATS.times do'
- f.puts ' target.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)'
+ f.puts ' target.class_eval(<<~RUBY)'
f.puts ' def foo'
f.puts ' #{"\n" * rand(REPEATS)}'
f.puts ' end'
@@ -147,16 +154,39 @@ class TestCoverage < Test::Unit::TestCase
end
assert_in_out_err(%w[-W0 -rcoverage], <<-"end;", ["[1, 1, 1, 400, nil, nil, nil, nil, nil, nil, nil]"], [], bug13305)
- Coverage.start
+ Coverage.start(:all)
tmp = Dir.pwd
require tmp + '/test.rb'
add_method(Class.new)
- p Coverage.result[tmp + "/test.rb"]
+ p Coverage.result[tmp + "/test.rb"][:lines]
end;
}
}
end
+ def test_eval_coverage
+ assert_in_out_err(%w[-rcoverage], <<-"end;", ["[1, nil, 1, nil]"], [])
+ Coverage.start(eval: true, lines: true)
+
+ eval(<<-RUBY, TOPLEVEL_BINDING, "test.rb")
+ s = String.new
+ begin
+ s << "foo
+ bar".freeze; end
+ RUBY
+
+ p Coverage.result["test.rb"][:lines]
+ end;
+ end
+
+ def test_coverage_supported
+ assert Coverage.supported?(:lines)
+ assert Coverage.supported?(:branches)
+ assert Coverage.supported?(:methods)
+ assert Coverage.supported?(:eval)
+ refute Coverage.supported?(:all)
+ end
+
def test_nocoverage_optimized_line
assert_ruby_status(%w[], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
@@ -181,6 +211,27 @@ class TestCoverage < Test::Unit::TestCase
end;
end
+ def test_coverage_ensure_if_return
+ result = {
+ :branches => {
+ [:if, 0, 3, 2, 6, 5] => {
+ [:then, 1, 3, 7, 3, 7] => 0,
+ [:else, 2, 5, 4, 5, 10] => 1,
+ },
+ },
+ }
+ assert_coverage(<<~"end;", { branches: true }, result)
+ def flush
+ ensure
+ if $!
+ else
+ return
+ end
+ end
+ flush
+ end;
+ end
+
def assert_coverage(code, opt, stdout)
stdout = [stdout] unless stdout.is_a?(Array)
stdout = stdout.map {|s| s.to_s }
@@ -774,4 +825,164 @@ class TestCoverage < Test::Unit::TestCase
end
end;
end
+
+ def test_coverage_suspendable
+ Dir.mktmpdir {|tmp|
+ Dir.chdir(tmp) {
+ File.open("test.rb", "w") do |f|
+ f.puts <<-EOS
+ def foo
+ :ok
+ end
+
+ def bar
+ :ok
+ end
+
+ def baz
+ :ok
+ end
+ EOS
+ end
+
+ cov1 = "[0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil]"
+ cov2 = "[0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil]"
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], [])
+ Coverage.setup
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ p Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ p Coverage.result[tmp + "/test.rb"]
+ end;
+
+ cov1 = "{:lines=>[0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil], :branches=>{}, :methods=>{[Object, :baz, 9, 12, 11, 15]=>0, [Object, :bar, 5, 12, 7, 15]=>1, [Object, :foo, 1, 12, 3, 15]=>0}}"
+ cov2 = "{:lines=>[0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil], :branches=>{}, :methods=>{[Object, :baz, 9, 12, 11, 15]=>1, [Object, :bar, 5, 12, 7, 15]=>1, [Object, :foo, 1, 12, 3, 15]=>0}}"
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], [])
+ Coverage.setup(:all)
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ p Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ p Coverage.result[tmp + "/test.rb"]
+ end;
+
+ cov1 = "{:oneshot_lines=>[6]}"
+ cov2 = "{:oneshot_lines=>[6, 10]}"
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [cov1, cov2], [])
+ Coverage.setup(oneshot_lines: true)
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ p Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ p Coverage.result[tmp + "/test.rb"]
+ end;
+ }
+ }
+ end
+
+ def test_coverage_state
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [":idle", ":running", ":running", ":idle"], [])
+ p Coverage.state
+ Coverage.start
+ p Coverage.state
+ Coverage.peek_result
+ p Coverage.state
+ Coverage.result
+ p Coverage.state
+ end;
+
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [":idle", ":suspended", ":running", ":suspended", ":running", ":suspended", ":idle"], [])
+ p Coverage.state
+ Coverage.setup
+ p Coverage.state
+ Coverage.resume
+ p Coverage.state
+ Coverage.suspend
+ p Coverage.state
+ Coverage.resume
+ p Coverage.state
+ Coverage.suspend
+ p Coverage.state
+ Coverage.result
+ p Coverage.state
+ end;
+ end
+
+ def test_result_without_resume
+ assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], [])
+ Coverage.setup
+ p Coverage.result
+ end;
+ end
+
+ def test_result_after_suspend
+ assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], [])
+ Coverage.start
+ Coverage.suspend
+ p Coverage.result
+ end;
+ end
+
+ def test_resume_without_setup
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not set up yet/)
+ Coverage.resume
+ p :NG
+ end;
+ end
+
+ def test_suspend_without_setup
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not running/)
+ Coverage.suspend
+ p :NG
+ end;
+ end
+
+ def test_double_resume
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is already running/)
+ Coverage.start
+ Coverage.resume
+ p :NG
+ end;
+ end
+
+ def test_double_suspend
+ assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not running/)
+ Coverage.setup
+ Coverage.suspend
+ p :NG
+ end;
+ end
+
+ def test_tag_break_with_branch_coverage
+ result = {
+ :branches => {
+ [:"&.", 0, 1, 0, 1, 6] => {
+ [:then, 1, 1, 0, 1, 6] => 1,
+ [:else, 2, 1, 0, 1, 6] => 0,
+ },
+ },
+ }
+ assert_coverage(<<~"end;", { branches: true }, result)
+ 1&.tap do break end
+ end;
+ end
end
diff --git a/test/csv/interface/test_read.rb b/test/csv/interface/test_read.rb
index b86c54fc9f..001177036a 100644
--- a/test/csv/interface/test_read.rb
+++ b/test/csv/interface/test_read.rb
@@ -26,21 +26,39 @@ class TestCSVInterfaceRead < Test::Unit::TestCase
def test_foreach
rows = []
- CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n").each do |row|
+ CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n") do |row|
rows << row
end
assert_equal(@rows, rows)
end
+ if respond_to?(:ractor)
+ ractor
+ def test_foreach_in_ractor
+ ractor = Ractor.new(@input.path) do |path|
+ rows = []
+ CSV.foreach(path, col_sep: "\t", row_sep: "\r\n") do |row|
+ rows << row
+ end
+ rows
+ end
+ rows = [
+ ["1", "2", "3"],
+ ["4", "5"],
+ ]
+ assert_equal(rows, ractor.take)
+ end
+ end
+
def test_foreach_mode
rows = []
- CSV.foreach(@input.path, "r", col_sep: "\t", row_sep: "\r\n").each do |row|
+ CSV.foreach(@input.path, "r", col_sep: "\t", row_sep: "\r\n") do |row|
rows << row
end
assert_equal(@rows, rows)
end
- def test_foreach_enumurator
+ def test_foreach_enumerator
rows = CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n").to_a
assert_equal(@rows, rows)
end
@@ -187,6 +205,16 @@ class TestCSVInterfaceRead < Test::Unit::TestCase
end
end
+ def test_open_with_newline
+ CSV.open(@input.path, col_sep: "\t", universal_newline: true) do |csv|
+ assert_equal(@rows, csv.to_a)
+ end
+ File.binwrite(@input.path, "1,2,3\r\n" "4,5\n")
+ CSV.open(@input.path, newline: :universal) do |csv|
+ assert_equal(@rows, csv.to_a)
+ end
+ end
+
def test_parse
assert_equal(@rows,
CSV.parse(@data, col_sep: "\t", row_sep: "\r\n"))
@@ -240,6 +268,20 @@ class TestCSVInterfaceRead < Test::Unit::TestCase
CSV.read(@input.path, col_sep: "\t", row_sep: "\r\n"))
end
+ if respond_to?(:ractor)
+ ractor
+ def test_read_in_ractor
+ ractor = Ractor.new(@input.path) do |path|
+ CSV.read(path, col_sep: "\t", row_sep: "\r\n")
+ end
+ rows = [
+ ["1", "2", "3"],
+ ["4", "5"],
+ ]
+ assert_equal(rows, ractor.take)
+ end
+ end
+
def test_readlines
assert_equal(@rows,
CSV.readlines(@input.path, col_sep: "\t", row_sep: "\r\n"))
diff --git a/test/csv/interface/test_read_write.rb b/test/csv/interface/test_read_write.rb
index 20c9fe317e..c371e9c5fc 100644
--- a/test/csv/interface/test_read_write.rb
+++ b/test/csv/interface/test_read_write.rb
@@ -112,4 +112,13 @@ a;b;c
assert_equal(CSV.instance,
CSV {|csv| csv})
end
+
+ def test_instance_shortcut_with_io
+ io = StringIO.new
+ from_instance = CSV.instance(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }
+ from_shortcut = CSV(io, col_sep: ";") { |csv| csv << ["e", "f", "g"] }
+
+ assert_equal(from_instance, from_shortcut)
+ assert_equal(from_instance.string, "a;b;c\ne;f;g\n")
+ end
end
diff --git a/test/csv/interface/test_write.rb b/test/csv/interface/test_write.rb
index 8650ecd624..0cd39a7663 100644
--- a/test/csv/interface/test_write.rb
+++ b/test/csv/interface/test_write.rb
@@ -25,6 +25,21 @@ class TestCSVInterfaceWrite < Test::Unit::TestCase
CSV
end
+ if respond_to?(:ractor)
+ ractor
+ def test_generate_default_in_ractor
+ ractor = Ractor.new do
+ CSV.generate do |csv|
+ csv << [1, 2, 3] << [4, nil, 5]
+ end
+ end
+ assert_equal(<<-CSV, ractor.take)
+1,2,3
+4,,5
+ CSV
+ end
+ end
+
def test_generate_append
csv_text = <<-CSV
1,2,3
@@ -70,6 +85,15 @@ testrow
LINE
end
+ def test_generate_lines
+ lines = CSV.generate_lines([["foo", "bar"], [1, 2], [3, 4]])
+ assert_equal(<<-LINES, lines)
+foo,bar
+1,2
+3,4
+ LINES
+ end
+
def test_headers_detection
headers = ["a", "b", "c"]
CSV.open(@output.path, "w", headers: true) do |csv|
@@ -101,6 +125,25 @@ a,b,c
CSV
end
+
+ if respond_to?(:ractor)
+ ractor
+ def test_append_row_in_ractor
+ ractor = Ractor.new(@output.path) do |path|
+ CSV.open(path, "wb") do |csv|
+ csv <<
+ CSV::Row.new([], ["1", "2", "3"]) <<
+ CSV::Row.new([], ["a", "b", "c"])
+ end
+ end
+ ractor.take
+ assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
+1,2,3
+a,b,c
+ CSV
+ end
+ end
+
def test_append_hash
CSV.open(@output.path, "wb", headers: true) do |csv|
csv << [:a, :b, :c]
diff --git a/test/csv/parse/test_convert.rb b/test/csv/parse/test_convert.rb
index bfe6ddd527..c9195c71d9 100644
--- a/test/csv/parse/test_convert.rb
+++ b/test/csv/parse/test_convert.rb
@@ -15,6 +15,22 @@ class TestCSVParseConvert < Test::Unit::TestCase
@time = Time.utc(2018, 12, 30, 6, 41, 29)
@windows_safe_time_data = @time.strftime("%a %b %d %H:%M:%S %Y")
+
+ @preserving_converter = lambda do |field, info|
+ f = field.encode(CSV::ConverterEncoding)
+ return f if info.quoted?
+ begin
+ Integer(f, 10)
+ rescue
+ f
+ end
+ end
+
+ @quoted_header_converter = lambda do |field, info|
+ f = field.encode(CSV::ConverterEncoding)
+ return f if info.quoted?
+ f.to_sym
+ end
end
def test_integer
@@ -43,7 +59,7 @@ class TestCSVParseConvert < Test::Unit::TestCase
@parser.shift)
end
- def test_numberic
+ def test_numeric
@parser.convert(:numeric)
assert_equal(["Numbers", ":integer", 1, ":float", 3.015],
@parser.shift)
@@ -107,4 +123,43 @@ class TestCSVParseConvert < Test::Unit::TestCase
assert_equal([nil, "empty", "a"],
CSV.parse_line(',"",a', empty_value: "empty"))
end
+
+ def test_quoted_parse_line
+ row = CSV.parse_line('1,"2",3', converters: @preserving_converter)
+ assert_equal([1, "2", 3], row)
+ end
+
+ def test_quoted_parse
+ expected = [["quoted", "unquoted"], ["109", 1], ["10A", 2]]
+ rows = CSV.parse(<<~CSV, converters: @preserving_converter)
+ "quoted",unquoted
+ "109",1
+ "10A",2
+ CSV
+ assert_equal(expected, rows)
+ end
+
+ def test_quoted_alternating_quote
+ row = CSV.parse_line('"1",2,"3"', converters: @preserving_converter)
+ assert_equal(['1', 2, '3'], row)
+ end
+
+ def test_quoted_parse_headers
+ expected = [["quoted", :unquoted], ["109", "1"], ["10A", "2"]]
+ table = CSV.parse(<<~CSV, headers: true, header_converters: @quoted_header_converter)
+ "quoted",unquoted
+ "109",1
+ "10A",2
+ CSV
+ assert_equal(expected, table.to_a)
+ end
+
+ def test_quoted_parse_with_string_headers
+ expected = [["quoted", :unquoted], %w[109 1], %w[10A 2]]
+ table = CSV.parse(<<~CSV, headers: '"quoted",unquoted', header_converters: @quoted_header_converter)
+ "109",1
+ "10A",2
+ CSV
+ assert_equal(expected, table.to_a)
+ end
end
diff --git a/test/csv/parse/test_general.rb b/test/csv/parse/test_general.rb
index 14903d462c..ff32eef6d3 100644
--- a/test/csv/parse/test_general.rb
+++ b/test/csv/parse/test_general.rb
@@ -14,7 +14,7 @@ require_relative "../helper"
class TestCSVParseGeneral < Test::Unit::TestCase
extend DifferentOFS
- BIG_DATA = "123456789\n" * 1024
+ BIG_DATA = "123456789\n" * 512
def test_mastering_regex_example
ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
@@ -199,6 +199,32 @@ line,5,jkl
field_size_limit: 2048 )
end
+ def test_field_size_limit_max_allowed
+ column = "abcde"
+ assert_equal([[column]],
+ CSV.parse("\"#{column}\"",
+ field_size_limit: column.size + 1))
+ end
+
+ def test_field_size_limit_quote_simple
+ column = "abcde"
+ assert_parse_errors_out("\"#{column}\"",
+ field_size_limit: column.size)
+ end
+
+ def test_field_size_limit_no_quote_implicitly
+ column = "abcde"
+ assert_parse_errors_out("#{column}",
+ field_size_limit: column.size)
+ end
+
+ def test_field_size_limit_no_quote_explicitly
+ column = "abcde"
+ assert_parse_errors_out("#{column}",
+ field_size_limit: column.size,
+ quote_char: nil)
+ end
+
def test_field_size_limit_in_extended_column_not_exceeding
data = <<~DATA
"a","b"
@@ -221,6 +247,59 @@ line,5,jkl
assert_parse_errors_out(data, field_size_limit: 5)
end
+ def test_max_field_size_controls_lookahead
+ assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
+ max_field_size: 2048 )
+ end
+
+ def test_max_field_size_max_allowed
+ column = "abcde"
+ assert_equal([[column]],
+ CSV.parse("\"#{column}\"",
+ max_field_size: column.size))
+ end
+
+ def test_max_field_size_quote_simple
+ column = "abcde"
+ assert_parse_errors_out("\"#{column}\"",
+ max_field_size: column.size - 1)
+ end
+
+ def test_max_field_size_no_quote_implicitly
+ column = "abcde"
+ assert_parse_errors_out("#{column}",
+ max_field_size: column.size - 1)
+ end
+
+ def test_max_field_size_no_quote_explicitly
+ column = "abcde"
+ assert_parse_errors_out("#{column}",
+ max_field_size: column.size - 1,
+ quote_char: nil)
+ end
+
+ def test_max_field_size_in_extended_column_not_exceeding
+ data = <<~DATA
+ "a","b"
+ "
+ 2
+ ",""
+ DATA
+ assert_nothing_raised(CSV::MalformedCSVError) do
+ CSV.parse(data, max_field_size: 3)
+ end
+ end
+
+ def test_max_field_size_in_extended_column_exceeding
+ data = <<~DATA
+ "a","b"
+ "
+ 2345
+ ",""
+ DATA
+ assert_parse_errors_out(data, max_field_size: 4)
+ end
+
def test_row_sep_auto_cr
assert_equal([["a"]], CSV.parse("a\r"))
end
@@ -247,7 +326,10 @@ line,5,jkl
def assert_parse_errors_out(data, **options)
assert_raise(CSV::MalformedCSVError) do
timeout = 0.2
- if defined?(RubyVM::JIT.enabled?) and RubyVM::JIT.enabled?
+ if defined?(RubyVM::YJIT.enabled?) and RubyVM::YJIT.enabled?
+ timeout = 1 # for --yjit-call-threshold=1
+ end
+ if defined?(RubyVM::MJIT.enabled?) and RubyVM::MJIT.enabled?
timeout = 5 # for --jit-wait
end
Timeout.timeout(timeout) do
diff --git a/test/csv/parse/test_header.rb b/test/csv/parse/test_header.rb
index 481c5107c6..e8c3786d68 100644
--- a/test/csv/parse/test_header.rb
+++ b/test/csv/parse/test_header.rb
@@ -218,6 +218,13 @@ A,B,C
assert_equal([:one, :two_three], csv.headers)
end
+ def test_builtin_symbol_raw_converter
+ csv = CSV.parse( "a b,c d", headers: true,
+ return_headers: true,
+ header_converters: :symbol_raw )
+ assert_equal([:"a b", :"c d"], csv.headers)
+ end
+
def test_builtin_symbol_converter_with_punctuation
csv = CSV.parse( "One, Two & Three ($)", headers: true,
return_headers: true,
@@ -228,7 +235,7 @@ A,B,C
def test_builtin_converters_with_blank_header
csv = CSV.parse( "one,,three", headers: true,
return_headers: true,
- header_converters: [:downcase, :symbol] )
+ header_converters: [:downcase, :symbol, :symbol_raw] )
assert_equal([:one, nil, :three], csv.headers)
end
diff --git a/test/csv/parse/test_inputs_scanner.rb b/test/csv/parse/test_inputs_scanner.rb
new file mode 100644
index 0000000000..06e1c845d5
--- /dev/null
+++ b/test/csv/parse/test_inputs_scanner.rb
@@ -0,0 +1,63 @@
+require_relative "../helper"
+
+class TestCSVParseInputsScanner < Test::Unit::TestCase
+ include Helper
+
+ def test_scan_keep_over_chunks_nested_back
+ input = CSV::Parser::UnoptimizedStringIO.new("abcdefghijklmnl")
+ scanner = CSV::Parser::InputsScanner.new([input],
+ Encoding::UTF_8,
+ nil,
+ chunk_size: 2)
+ scanner.keep_start
+ assert_equal("abc", scanner.scan_all(/[a-c]+/))
+ scanner.keep_start
+ assert_equal("def", scanner.scan_all(/[d-f]+/))
+ scanner.keep_back
+ scanner.keep_back
+ assert_equal("abcdefg", scanner.scan_all(/[a-g]+/))
+ end
+
+ def test_scan_keep_over_chunks_nested_drop_back
+ input = CSV::Parser::UnoptimizedStringIO.new("abcdefghijklmnl")
+ scanner = CSV::Parser::InputsScanner.new([input],
+ Encoding::UTF_8,
+ nil,
+ chunk_size: 3)
+ scanner.keep_start
+ assert_equal("ab", scanner.scan(/../))
+ scanner.keep_start
+ assert_equal("c", scanner.scan(/./))
+ assert_equal("d", scanner.scan(/./))
+ scanner.keep_drop
+ scanner.keep_back
+ assert_equal("abcdefg", scanner.scan_all(/[a-g]+/))
+ end
+
+ def test_each_line_keep_over_chunks_multibyte
+ input = CSV::Parser::UnoptimizedStringIO.new("ab\n\u{3000}a\n")
+ scanner = CSV::Parser::InputsScanner.new([input],
+ Encoding::UTF_8,
+ nil,
+ chunk_size: 1)
+ each_line = scanner.each_line("\n")
+ assert_equal("ab\n", each_line.next)
+ scanner.keep_start
+ assert_equal("\u{3000}a\n", each_line.next)
+ scanner.keep_back
+ assert_equal("\u{3000}a\n", scanner.scan_all(/[^,]+/))
+ end
+
+ def test_each_line_keep_over_chunks_fit_chunk_size
+ input = CSV::Parser::UnoptimizedStringIO.new("\na")
+ scanner = CSV::Parser::InputsScanner.new([input],
+ Encoding::UTF_8,
+ nil,
+ chunk_size: 1)
+ each_line = scanner.each_line("\n")
+ assert_equal("\n", each_line.next)
+ scanner.keep_start
+ assert_equal("a", each_line.next)
+ scanner.keep_back
+ end
+end
diff --git a/test/csv/parse/test_invalid.rb b/test/csv/parse/test_invalid.rb
index 9dfd081380..ddb59e2b9a 100644
--- a/test/csv/parse/test_invalid.rb
+++ b/test/csv/parse/test_invalid.rb
@@ -36,4 +36,17 @@ ggg,hhh,iii
csv.shift)
assert_equal(true, csv.eof?)
end
+
+ def test_ignore_invalid_line_cr_lf
+ data = <<-CSV
+"1","OK"\r
+"2",""NOT" OK"\r
+"3","OK"\r
+CSV
+ csv = CSV.new(data)
+
+ assert_equal(['1', 'OK'], csv.shift)
+ assert_raise(CSV::MalformedCSVError) { csv.shift }
+ assert_equal(['3', 'OK'], csv.shift)
+ end
end
diff --git a/test/csv/parse/test_liberal_parsing.rb b/test/csv/parse/test_liberal_parsing.rb
index 2f7b34689f..5796d10828 100644
--- a/test/csv/parse/test_liberal_parsing.rb
+++ b/test/csv/parse/test_liberal_parsing.rb
@@ -28,6 +28,17 @@ class TestCSVParseLiberalParsing < Test::Unit::TestCase
CSV.parse_line(input, liberal_parsing: true))
end
+ def test_endline_after_quoted_field_end
+ csv = CSV.new("A\r\n\"B\"\nC\r\n", liberal_parsing: true)
+ assert_equal(["A"], csv.gets)
+ error = assert_raise(CSV::MalformedCSVError) do
+ csv.gets
+ end
+ assert_equal('Illegal end-of-line sequence outside of a quoted field <"\n"> in line 2.',
+ error.message)
+ assert_equal(["C"], csv.gets)
+ end
+
def test_quote_after_column_separator
error = assert_raise(CSV::MalformedCSVError) do
CSV.parse_line('is,this "three," or four,fields', liberal_parsing: true)
diff --git a/test/csv/parse/test_read.rb b/test/csv/parse/test_read.rb
new file mode 100644
index 0000000000..ba6fe985a9
--- /dev/null
+++ b/test/csv/parse/test_read.rb
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# frozen_string_literal: false
+
+require_relative "../helper"
+
+class TestCSVParseRead < Test::Unit::TestCase
+ extend DifferentOFS
+
+ def test_shift
+ data = <<-CSV
+1
+2
+3
+ CSV
+ csv = CSV.new(data)
+ assert_equal([
+ ["1"],
+ [["2"], ["3"]],
+ nil,
+ ],
+ [
+ csv.shift,
+ csv.read,
+ csv.shift,
+ ])
+ end
+end
diff --git a/test/csv/parse/test_strip.rb b/test/csv/parse/test_strip.rb
index 3564fcb3ba..c5e35209cc 100644
--- a/test/csv/parse/test_strip.rb
+++ b/test/csv/parse/test_strip.rb
@@ -80,4 +80,33 @@ class TestCSVParseStrip < Test::Unit::TestCase
%Q{"a" ,"b " \r\n},
strip: true))
end
+
+ def test_col_sep_incompatible_true
+ message = "The provided strip (true) and " \
+ "col_sep (\\t) options are incompatible."
+ assert_raise_with_message(ArgumentError, message) do
+ CSV.parse_line(%Q{"a"\t"b"\n},
+ col_sep: "\t",
+ strip: true)
+ end
+ end
+
+ def test_col_sep_incompatible_string
+ message = "The provided strip (\\t) and " \
+ "col_sep (\\t) options are incompatible."
+ assert_raise_with_message(ArgumentError, message) do
+ CSV.parse_line(%Q{"a"\t"b"\n},
+ col_sep: "\t",
+ strip: "\t")
+ end
+ end
+
+ def test_col_sep_compatible_string
+ assert_equal(
+ ["a", "b"],
+ CSV.parse_line(%Q{\va\tb\v\n},
+ col_sep: "\t",
+ strip: "\v")
+ )
+ end
end
diff --git a/test/csv/test_data_converters.rb b/test/csv/test_data_converters.rb
index 1620e077be..c20a5d1f4b 100644
--- a/test/csv/test_data_converters.rb
+++ b/test/csv/test_data_converters.rb
@@ -103,4 +103,88 @@ class TestCSVDataConverters < Test::Unit::TestCase
assert_equal(datetime,
CSV::Converters[:date_time][iso8601_string])
end
+
+ def test_builtin_date_time_converter_rfc3339_minute
+ rfc3339_string = "2018-01-14 22:25"
+ datetime = DateTime.new(2018, 1, 14, 22, 25)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_second
+ rfc3339_string = "2018-01-14 22:25:19"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_under_second
+ rfc3339_string = "2018-01-14 22:25:19.1"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_under_second_offset
+ rfc3339_string = "2018-01-14 22:25:19.1+09:00"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1, "+9")
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_offset
+ rfc3339_string = "2018-01-14 22:25:19+09:00"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19, "+9")
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_utc
+ rfc3339_string = "2018-01-14 22:25:19Z"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_tab_minute
+ rfc3339_string = "2018-01-14\t22:25"
+ datetime = DateTime.new(2018, 1, 14, 22, 25)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_tab_second
+ rfc3339_string = "2018-01-14\t22:25:19"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_tab_under_second
+ rfc3339_string = "2018-01-14\t22:25:19.1"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_tab_under_second_offset
+ rfc3339_string = "2018-01-14\t22:25:19.1+09:00"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1, "+9")
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_tab_offset
+ rfc3339_string = "2018-01-14\t22:25:19+09:00"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19, "+9")
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
+
+ def test_builtin_date_time_converter_rfc3339_tab_utc
+ rfc3339_string = "2018-01-14\t22:25:19Z"
+ datetime = DateTime.new(2018, 1, 14, 22, 25, 19)
+ assert_equal(datetime,
+ CSV::Converters[:date_time][rfc3339_string])
+ end
end
diff --git a/test/csv/test_encodings.rb b/test/csv/test_encodings.rb
index 8d228c05f3..f08d551f69 100644
--- a/test/csv/test_encodings.rb
+++ b/test/csv/test_encodings.rb
@@ -288,6 +288,37 @@ class TestCSVEncodings < Test::Unit::TestCase
error.message)
end
+ def test_string_input_transcode
+ # U+3042 HIRAGANA LETTER A
+ # U+3044 HIRAGANA LETTER I
+ # U+3046 HIRAGANA LETTER U
+ value = "\u3042\u3044\u3046"
+ csv = CSV.new(value, encoding: "UTF-8:EUC-JP")
+ assert_equal([[value.encode("EUC-JP")]],
+ csv.read)
+ end
+
+ def test_string_input_set_encoding_string
+ # U+3042 HIRAGANA LETTER A
+ # U+3044 HIRAGANA LETTER I
+ # U+3046 HIRAGANA LETTER U
+ value = "\u3042\u3044\u3046".encode("EUC-JP")
+ csv = CSV.new(value.dup.force_encoding("UTF-8"), encoding: "EUC-JP")
+ assert_equal([[value.encode("EUC-JP")]],
+ csv.read)
+ end
+
+ def test_string_input_set_encoding_encoding
+ # U+3042 HIRAGANA LETTER A
+ # U+3044 HIRAGANA LETTER I
+ # U+3046 HIRAGANA LETTER U
+ value = "\u3042\u3044\u3046".encode("EUC-JP")
+ csv = CSV.new(value.dup.force_encoding("UTF-8"),
+ encoding: Encoding.find("EUC-JP"))
+ assert_equal([[value.encode("EUC-JP")]],
+ csv.read)
+ end
+
private
def assert_parses(fields, encoding, **options)
diff --git a/test/csv/test_patterns.rb b/test/csv/test_patterns.rb
new file mode 100644
index 0000000000..881f03a3a4
--- /dev/null
+++ b/test/csv/test_patterns.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+class TestCSVPatternMatching < Test::Unit::TestCase
+
+ def test_hash
+ case CSV::Row.new(%i{A B C}, [1, 2, 3])
+ in B: b, C: c
+ assert_equal([2, 3], [b, c])
+ end
+ end
+
+ def test_hash_rest
+ case CSV::Row.new(%i{A B C}, [1, 2, 3])
+ in B: b, **rest
+ assert_equal([2, { A: 1, C: 3 }], [b, rest])
+ end
+ end
+
+ def test_array
+ case CSV::Row.new(%i{A B C}, [1, 2, 3])
+ in *, matched
+ assert_equal(3, matched)
+ end
+ end
+end
diff --git a/test/csv/test_table.rb b/test/csv/test_table.rb
index 3202963a67..e8ab74044e 100644
--- a/test/csv/test_table.rb
+++ b/test/csv/test_table.rb
@@ -20,7 +20,7 @@ class TestCSVTable < Test::Unit::TestCase
@header_only_table = CSV::Table.new([], headers: %w{A B C})
end
- def test_initialze
+ def test_initialize
assert_not_nil(@table)
assert_instance_of(CSV::Table, @table)
end
@@ -274,6 +274,22 @@ A,B,C,Type,Index
@table.each { |row| assert_instance_of(CSV::Row, row) }
end
+ def test_each_by_col_duplicated_headers
+ table = CSV.parse(<<-CSV, headers: true)
+a,a,,,b
+1,2,3,4,5
+11,12,13,14,15
+ CSV
+ assert_equal([
+ ["a", ["1", "11"]],
+ ["a", ["2", "12"]],
+ [nil, ["3", "13"]],
+ [nil, ["4", "14"]],
+ ["b", ["5", "15"]],
+ ],
+ table.by_col.each.to_a)
+ end
+
def test_each_split
yielded_values = []
@table.each do |column1, column2, column3|
@@ -320,6 +336,43 @@ A,B,C
assert_equal(csv, @header_table.to_csv)
end
+ def test_to_csv_limit_positive
+ assert_equal(<<-CSV, @table.to_csv(limit: 2))
+A,B,C
+1,2,3
+4,5,6
+ CSV
+ end
+
+ def test_to_csv_limit_positive_over
+ assert_equal(<<-CSV, @table.to_csv(limit: 5))
+A,B,C
+1,2,3
+4,5,6
+7,8,9
+ CSV
+ end
+
+ def test_to_csv_limit_zero
+ assert_equal(<<-CSV, @table.to_csv(limit: 0))
+A,B,C
+ CSV
+ end
+
+ def test_to_csv_limit_negative
+ assert_equal(<<-CSV, @table.to_csv(limit: -2))
+A,B,C
+1,2,3
+4,5,6
+ CSV
+ end
+
+ def test_to_csv_limit_negative_over
+ assert_equal(<<-CSV, @table.to_csv(limit: -5))
+A,B,C
+ CSV
+ end
+
def test_append
# verify that we can chain the call
assert_equal(@table, @table << [10, 11, 12])
@@ -549,7 +602,25 @@ A
assert_send([Encoding, :compatible?,
Encoding.find("US-ASCII"),
@table.inspect.encoding],
- "inspect() was not ASCII compatible." )
+ "inspect() was not ASCII compatible." )
+ end
+
+ def test_inspect_with_rows
+ additional_rows = [ CSV::Row.new(%w{A B C}, [101, 102, 103]),
+ CSV::Row.new(%w{A B C}, [104, 105, 106]),
+ CSV::Row.new(%w{A B C}, [107, 108, 109]) ]
+ table = CSV::Table.new(@rows + additional_rows)
+ str_table = table.inspect
+
+ assert_equal(<<-CSV, str_table)
+#<CSV::Table mode:col_or_row row_count:7>
+A,B,C
+1,2,3
+4,5,6
+7,8,9
+101,102,103
+104,105,106
+ CSV
end
def test_dig_mixed
diff --git a/test/date/test_date.rb b/test/date/test_date.rb
index 6e99bc562c..3f9c893efa 100644
--- a/test/date/test_date.rb
+++ b/test/date/test_date.rb
@@ -175,4 +175,33 @@ class TestDate < Test::Unit::TestCase
assert_equal(-1, -Float::INFINITY <=> Date::Infinity.new)
assert_equal(-1, -Date::Infinity.new <=> Float::INFINITY)
end
+
+ def test_deconstruct_keys
+ d = Date.new(1999,5,23)
+ assert_equal({year: 1999, month: 5, day: 23, wday: 0, yday: 143}, d.deconstruct_keys(nil))
+ assert_equal({year: 1999}, d.deconstruct_keys([:year, :century]))
+ assert_equal(
+ {year: 1999, month: 5, day: 23, wday: 0, yday: 143},
+ d.deconstruct_keys([:year, :month, :day, :wday, :yday])
+ )
+
+ dt = DateTime.new(1999, 5, 23, 4, 20, Rational(1, 10000))
+
+ assert_equal(
+ {year: 1999, month: 5, day: 23, wday: 0, yday: 143,
+ hour: 4, min: 20, sec: 0, sec_fraction: Rational(1, 10000), zone: "+00:00"},
+ dt.deconstruct_keys(nil)
+ )
+
+ assert_equal({year: 1999}, dt.deconstruct_keys([:year, :century]))
+
+ assert_equal(
+ {year: 1999, month: 5, day: 23, wday: 0, yday: 143,
+ hour: 4, min: 20, sec: 0, sec_fraction: Rational(1, 10000), zone: "+00:00"},
+ dt.deconstruct_keys([:year, :month, :day, :wday, :yday, :hour, :min, :sec, :sec_fraction, :zone])
+ )
+
+ dtz = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
+ assert_equal({zone: '+03:30'}, dtz.deconstruct_keys([:zone]))
+ end
end
diff --git a/test/date/test_date_conv.rb b/test/date/test_date_conv.rb
index d41ff45d85..ed478b41bb 100644
--- a/test/date/test_date_conv.rb
+++ b/test/date/test_date_conv.rb
@@ -77,6 +77,11 @@ class TestDateConv < Test::Unit::TestCase
assert_equal([2004, 9, 19, 1, 2, 3, 456789],
[t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+ d = DateTime.new(1582, 10, 3, 1, 2, 3, 0) + 456789.to_r/86400000000
+ t = d.to_time.utc
+ assert_equal([1582, 10, 13, 1, 2, 3, 456789],
+ [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+
if Time.allocate.respond_to?(:nsec)
d = DateTime.new(2004, 9, 19, 1, 2, 3, 0) + 456789123.to_r/86400000000000
t = d.to_time.utc
@@ -100,6 +105,10 @@ class TestDateConv < Test::Unit::TestCase
t = Time.utc(2004, 9, 19, 1, 2, 3, 456789)
d = t.to_date
assert_equal([2004, 9, 19, 0], [d.year, d.mon, d.mday, d.day_fraction])
+
+ t = Time.utc(1582, 10, 13, 1, 2, 3, 456789)
+ d = t.to_date # using ITALY
+ assert_equal([1582, 10, 3, 0], [d.year, d.mon, d.mday, d.day_fraction])
end
def test_to_date__from_date
@@ -136,6 +145,14 @@ class TestDateConv < Test::Unit::TestCase
[d.year, d.mon, d.mday, d.hour, d.min, d.sec,
d.sec_fraction, d.offset])
+ t = Time.utc(1582, 10, 13, 1, 2, 3, 456789)
+ d = t.to_datetime # using ITALY
+ assert_equal([1582, 10, 3, 1, 2, 3,
+ 456789.to_r/1000000,
+ 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec,
+ d.sec_fraction, d.offset])
+
t = Time.now
d = t.to_datetime
require 'time'
diff --git a/test/date/test_date_parse.rb b/test/date/test_date_parse.rb
index 9f92635387..0b4a383630 100644
--- a/test/date/test_date_parse.rb
+++ b/test/date/test_date_parse.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'test/unit'
require 'date'
+require 'envutil'
class TestDateParse < Test::Unit::TestCase
@@ -40,6 +41,7 @@ class TestDateParse < Test::Unit::TestCase
[['Sat Aug 28 02:29:34 Mountain Daylight Time 2000',false],[2000,8,28,2,29,34,'Mountain Daylight Time',-6*3600,6], __LINE__],
[['Sat Aug 28 02:29:34 Mexico Standard Time 2000',false],[2000,8,28,2,29,34,'Mexico Standard Time',-6*3600,6], __LINE__],
[['Sat Aug 28 02:29:34 E. Australia Standard Time 2000',false],[2000,8,28,2,29,34,'E. Australia Standard Time',10*3600,6], __LINE__],
+ [['Sat Aug 28 02:29:34 W. Central Africa Standard Time 2000',false],[2000,8,28,2,29,34,'W. Central Africa Standard Time',1*3600,6], __LINE__],
# part of iso 8601
[['1999-05-23 23:55:21',false],[1999,5,23,23,55,21,nil,nil,nil], __LINE__],
@@ -131,6 +133,7 @@ class TestDateParse < Test::Unit::TestCase
[['19990523235521.123[-9]',false],[1999,5,23,23,55,21,'-9',-(9*3600),nil], __LINE__],
[['19990523235521.123[+9]',false],[1999,5,23,23,55,21,'+9',+(9*3600),nil], __LINE__],
[['19990523235521.123[9]',false],[1999,5,23,23,55,21,'9',+(9*3600),nil], __LINE__],
+ [['19990523235521.123[9 ]',false],[1999,5,23,23,55,21,'9 ',+(9*3600),nil], __LINE__],
[['19990523235521.123[-9.50]',false],[1999,5,23,23,55,21,'-9.50',-(9*3600+30*60),nil], __LINE__],
[['19990523235521.123[+9.50]',false],[1999,5,23,23,55,21,'+9.50',+(9*3600+30*60),nil], __LINE__],
[['19990523235521.123[-5:EST]',false],[1999,5,23,23,55,21,'EST',-5*3600,nil], __LINE__],
@@ -139,6 +142,7 @@ class TestDateParse < Test::Unit::TestCase
[['235521.123',false],[nil,nil,nil,23,55,21,nil,nil,nil], __LINE__],
[['235521.123[-9]',false],[nil,nil,nil,23,55,21,'-9',-9*3600,nil], __LINE__],
[['235521.123[+9]',false],[nil,nil,nil,23,55,21,'+9',+9*3600,nil], __LINE__],
+ [['235521.123[-9 ]',false],[nil,nil,nil,23,55,21,'-9 ',-9*3600,nil], __LINE__],
[['235521.123[-5:EST]',false],[nil,nil,nil,23,55,21,'EST',-5*3600,nil], __LINE__],
[['235521.123[+9:JST]',false],[nil,nil,nil,23,55,21,'JST',+9*3600,nil], __LINE__],
@@ -584,6 +588,18 @@ class TestDateParse < Test::Unit::TestCase
assert_equal(5025, h[:offset])
end
+ def test__parse_too_long_year
+ str = "Jan 1" + "0" * 100_000
+ h = EnvUtil.timeout(3) {Date._parse(str, limit: 100_010)}
+ assert_equal(100_000, Math.log10(h[:year]))
+ assert_equal(1, h[:mon])
+
+ str = "Jan - 1" + "0" * 100_000
+ h = EnvUtil.timeout(3) {Date._parse(str, limit: 100_010)}
+ assert_equal(1, h[:mon])
+ assert_not_include(h, :year)
+ end
+
require 'time'
def test_parse__time
@@ -847,6 +863,13 @@ class TestDateParse < Test::Unit::TestCase
h = Date._iso8601('')
assert_equal({}, h)
+
+ h = Date._iso8601(nil)
+ assert_equal({}, h)
+
+ h = assert_deprecated_warn {Date._iso8601('01-02-03T04:05:06Z'.to_sym)}
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
end
def test__rfc3339
@@ -862,6 +885,13 @@ class TestDateParse < Test::Unit::TestCase
h = Date._rfc3339('')
assert_equal({}, h)
+
+ h = Date._rfc3339(nil)
+ assert_equal({}, h)
+
+ h = assert_deprecated_warn {Date._rfc3339('2001-02-03T04:05:06Z'.to_sym)}
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
end
def test__xmlschema
@@ -944,6 +974,13 @@ class TestDateParse < Test::Unit::TestCase
h = Date._xmlschema('')
assert_equal({}, h)
+
+ h = Date._xmlschema(nil)
+ assert_equal({}, h)
+
+ h = assert_deprecated_warn {Date._xmlschema('2001-02-03'.to_sym)}
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
end
def test__rfc2822
@@ -976,6 +1013,13 @@ class TestDateParse < Test::Unit::TestCase
h = Date._rfc2822('')
assert_equal({}, h)
+
+ h = Date._rfc2822(nil)
+ assert_equal({}, h)
+
+ h = assert_deprecated_warn {Date._rfc2822('Sat, 3 Feb 2001 04:05:06 UT'.to_sym)}
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
end
def test__httpdate
@@ -996,6 +1040,13 @@ class TestDateParse < Test::Unit::TestCase
h = Date._httpdate('')
assert_equal({}, h)
+
+ h = Date._httpdate(nil)
+ assert_equal({}, h)
+
+ h = assert_deprecated_warn {Date._httpdate('Sat, 03 Feb 2001 04:05:06 GMT'.to_sym)}
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
end
def test__jisx0301
@@ -1072,6 +1123,13 @@ class TestDateParse < Test::Unit::TestCase
h = Date._jisx0301('')
assert_equal({}, h)
+
+ h = Date._jisx0301(nil)
+ assert_equal({}, h)
+
+ h = assert_deprecated_warn {Date._jisx0301('H13.02.03T04:05:06.07+0100'.to_sym)}
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
end
def test_iso8601
@@ -1228,4 +1286,31 @@ class TestDateParse < Test::Unit::TestCase
assert_equal(s0, s)
end
+ def test_length_limit
+ assert_raise(ArgumentError) { Date._parse("1" * 1000) }
+ assert_raise(ArgumentError) { Date._iso8601("1" * 1000) }
+ assert_raise(ArgumentError) { Date._rfc3339("1" * 1000) }
+ assert_raise(ArgumentError) { Date._xmlschema("1" * 1000) }
+ assert_raise(ArgumentError) { Date._rfc2822("1" * 1000) }
+ assert_raise(ArgumentError) { Date._rfc822("1" * 1000) }
+ assert_raise(ArgumentError) { Date._jisx0301("1" * 1000) }
+
+ assert_raise(ArgumentError) { Date.parse("1" * 1000) }
+ assert_raise(ArgumentError) { Date.iso8601("1" * 1000) }
+ assert_raise(ArgumentError) { Date.rfc3339("1" * 1000) }
+ assert_raise(ArgumentError) { Date.xmlschema("1" * 1000) }
+ assert_raise(ArgumentError) { Date.rfc2822("1" * 1000) }
+ assert_raise(ArgumentError) { Date.rfc822("1" * 1000) }
+ assert_raise(ArgumentError) { Date.jisx0301("1" * 1000) }
+
+ assert_raise(ArgumentError) { DateTime.parse("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.iso8601("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.rfc3339("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.xmlschema("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.rfc2822("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.rfc822("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.jisx0301("1" * 1000) }
+
+ assert_raise(ArgumentError) { Date._parse("Jan " + "9" * 1000000) }
+ end
end
diff --git a/test/date/test_date_ractor.rb b/test/date/test_date_ractor.rb
index 7b0c3f4911..7ec953d87a 100644
--- a/test/date/test_date_ractor.rb
+++ b/test/date/test_date_ractor.rb
@@ -2,7 +2,7 @@
require 'test/unit'
require 'date'
-class TestDateParse < Test::Unit::TestCase
+class TestDateParseRactor < Test::Unit::TestCase
def code(klass = Date, share: false)
<<~RUBY.gsub('Date', klass.name)
share = #{share}
diff --git a/test/date/test_date_strftime.rb b/test/date/test_date_strftime.rb
index f82874d26d..dd04c0d9a4 100644
--- a/test/date/test_date_strftime.rb
+++ b/test/date/test_date_strftime.rb
@@ -48,7 +48,7 @@ class TestDateStrftime < Test::Unit::TestCase
'%t'=>["\t",{}],
'%u'=>['6',{:cwday=>6}],
'%V'=>['05',{:cweek=>5}],
- '%v'=>[' 3-Feb-2001',{:mday=>3,:mon=>2,:year=>2001}],
+ '%v'=>[' 3-FEB-2001',{:mday=>3,:mon=>2,:year=>2001}],
'%z'=>['+0000',{:zone=>'+0000',:offset=>0}],
'%+'=>['Sat Feb 3 00:00:00 +00:00 2001',
{:wday=>6,:mon=>2,:mday=>3,
@@ -125,7 +125,7 @@ class TestDateStrftime < Test::Unit::TestCase
def test_strftime__3_2
s = Time.now.strftime('%G')
- skip if s.empty? || s == '%G'
+ omit if s.empty? || s == '%G'
(Date.new(1970,1,1)..Date.new(2037,12,31)).each do |d|
t = Time.utc(d.year,d.mon,d.mday)
assert_equal(t.strftime('%G'), d.strftime('%G'))
diff --git a/test/date/test_date_strptime.rb b/test/date/test_date_strptime.rb
index fc42ebf7cd..4efe1a47d0 100644
--- a/test/date/test_date_strptime.rb
+++ b/test/date/test_date_strptime.rb
@@ -180,6 +180,10 @@ class TestDateStrptime < Test::Unit::TestCase
[['fri1feb034pm+5', '%a%d%b%y%H%p%Z'], [2003,2,1,16,nil,nil,'+5',5*3600,5]],
[['E. Australia Standard Time', '%Z'], [nil,nil,nil,nil,nil,nil,'E. Australia Standard Time',10*3600,nil], __LINE__],
+
+ # out of range
+ [['+0.9999999999999999999999', '%Z'], [nil,nil,nil,nil,nil,nil,'+0.9999999999999999999999',+1*3600,nil], __LINE__],
+ [['+9999999999999999999999.0', '%Z'], [nil,nil,nil,nil,nil,nil,'+9999999999999999999999.0',nil,nil], __LINE__],
].each do |x, y|
h = Date._strptime(*x)
a = h.values_at(:year,:mon,:mday,:hour,:min,:sec,:zone,:offset,:wday)
@@ -292,6 +296,11 @@ class TestDateStrptime < Test::Unit::TestCase
assert_not_nil(Date._strptime('Januari', '%B'))
assert_nil(Date._strptime('Sundai,', '%A,'))
assert_nil(Date._strptime('Januari,', '%B,'))
+
+ assert_nil(Date._strptime('+24:00', '%Z')[:offset])
+ assert_nil(Date._strptime('+23:60', '%Z')[:offset])
+ assert_nil(Date._strptime('+23:00:60', '%Z')[:offset])
+ assert_nil(Date._strptime('+23:00:60', '%Z')[:offset])
end
def test_strptime
diff --git a/test/did_you_mean/core_ext/test_name_error_extension.rb b/test/did_you_mean/core_ext/test_name_error_extension.rb
index 9dc08dbde3..1fdbd4510f 100644
--- a/test/did_you_mean/core_ext/test_name_error_extension.rb
+++ b/test/did_you_mean/core_ext/test_name_error_extension.rb
@@ -1,7 +1,9 @@
require_relative '../helper'
class NameErrorExtensionTest < Test::Unit::TestCase
- SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS
+ include DidYouMean::TestHelper
+
+ SPELL_CHECKERS = DidYouMean.spell_checkers
class TestSpellChecker
def initialize(*); end
@@ -9,18 +11,23 @@ class NameErrorExtensionTest < Test::Unit::TestCase
end
def setup
- @org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker
+ @original_spell_checker = DidYouMean.spell_checkers['NameError']
+ DidYouMean.correct_error(NameError, TestSpellChecker)
@error = assert_raise(NameError){ doesnt_exist }
end
def teardown
- SPELL_CHECKERS['NameError'] = @org
+ DidYouMean.correct_error(NameError, @original_spell_checker)
end
def test_message
- assert_match(/Did you mean\? does_exist/, @error.to_s)
- assert_match(/Did you mean\? does_exist/, @error.message)
+ if Exception.method_defined?(:detailed_message)
+ assert_match(/Did you mean\? does_exist/, @error.detailed_message)
+ else
+ assert_match(/Did you mean\? does_exist/, @error.to_s)
+ assert_match(/Did you mean\? does_exist/, @error.message)
+ end
end
def test_to_s_does_not_make_disruptive_changes_to_error_message
@@ -28,8 +35,8 @@ class NameErrorExtensionTest < Test::Unit::TestCase
raise NameError, "uninitialized constant Object"
end
- error.to_s
- assert_equal 1, error.to_s.scan("Did you mean?").count
+ get_message(error)
+ assert_equal 1, get_message(error).scan("Did you mean?").count
end
def test_correctable_error_objects_are_dumpable
@@ -40,7 +47,7 @@ class NameErrorExtensionTest < Test::Unit::TestCase
e
end
- error.to_s
+ get_message(error)
assert_equal "undefined method `sizee' for #<File:test_name_error_extension.rb (closed)>",
Marshal.load(Marshal.dump(error)).original_message
diff --git a/test/did_you_mean/helper.rb b/test/did_you_mean/helper.rb
index d8aa41c3d1..d40d58d95d 100644
--- a/test/did_you_mean/helper.rb
+++ b/test/did_you_mean/helper.rb
@@ -4,6 +4,10 @@ module DidYouMean
module TestHelper
class << self
attr_reader :root
+
+ def ractor_compatible?
+ defined?(Ractor) && RUBY_VERSION >= "3.1.0"
+ end
end
if File.file?(File.expand_path('../lib/did_you_mean.rb', __dir__))
@@ -25,5 +29,15 @@ module DidYouMean
def assert_correction(expected, array)
assert_equal Array(expected), array, "Expected #{array.inspect} to only include #{expected.inspect}"
end
+
+ def get_message(err)
+ if err.respond_to?(:detailed_message)
+ err.detailed_message(highlight: false)
+ else
+ err.to_s
+ end
+ end
+
+ module_function :get_message
end
end
diff --git a/test/did_you_mean/spell_checking/test_key_name_check.rb b/test/did_you_mean/spell_checking/test_key_name_check.rb
index ea05ff69e4..2f246f04d7 100644
--- a/test/did_you_mean/spell_checking/test_key_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_key_name_check.rb
@@ -8,11 +8,11 @@ class KeyNameCheckTest < Test::Unit::TestCase
error = assert_raise(KeyError) { hash.fetch(:bax) }
assert_correction ":bar", error.corrections
- assert_match "Did you mean? :bar", error.to_s
+ assert_match "Did you mean? :bar", get_message(error)
error = assert_raise(KeyError) { hash.fetch("fooo") }
assert_correction %("foo"), error.corrections
- assert_match %(Did you mean? "foo"), error.to_s
+ assert_match %(Did you mean? "foo"), get_message(error)
end
def test_corrects_hash_key_name_with_fetch_values
@@ -20,11 +20,11 @@ class KeyNameCheckTest < Test::Unit::TestCase
error = assert_raise(KeyError) { hash.fetch_values("foo", :bar, :bax) }
assert_correction ":bar", error.corrections
- assert_match "Did you mean? :bar", error.to_s
+ assert_match "Did you mean? :bar", get_message(error)
error = assert_raise(KeyError) { hash.fetch_values("foo", :bar, "fooo") }
assert_correction %("foo"), error.corrections
- assert_match %(Did you mean? "foo"), error.to_s
+ assert_match %(Did you mean? "foo"), get_message(error)
end
def test_correct_symbolized_hash_keys_with_string_value
@@ -32,13 +32,13 @@ class KeyNameCheckTest < Test::Unit::TestCase
error = assert_raise(KeyError) { hash.fetch('foo_1') }
assert_correction %(:foo_1), error.corrections
- assert_match %(Did you mean? :foo_1), error.to_s
+ assert_match %(Did you mean? :foo_1), get_message(error)
end
def test_corrects_sprintf_key_name
error = assert_raise(KeyError) { sprintf("%<foo>d", {fooo: 1}) }
assert_correction ":fooo", error.corrections
- assert_match "Did you mean? :fooo", error.to_s
+ assert_match "Did you mean? :fooo", get_message(error)
end
def test_corrects_env_key_name
@@ -46,7 +46,7 @@ class KeyNameCheckTest < Test::Unit::TestCase
ENV["BAR"] = "2"
error = assert_raise(KeyError) { ENV.fetch("BAX") }
assert_correction %("BAR"), error.corrections
- assert_match %(Did you mean? "BAR"), error.to_s
+ assert_match %(Did you mean? "BAR"), get_message(error)
ensure
ENV.delete("FOO")
ENV.delete("BAR")
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 6e14e6acc4..4daaf7cec7 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
@@ -4,6 +4,8 @@ class MethodNameCheckTest < Test::Unit::TestCase
include DidYouMean::TestHelper
class User
+ attr_writer :writer
+ attr_reader :reader
def friends; end
def first_name; end
def descendants; end
@@ -41,28 +43,28 @@ class MethodNameCheckTest < Test::Unit::TestCase
error = assert_raise(NoMethodError){ @user.flrst_name }
assert_correction :first_name, error.corrections
- assert_match "Did you mean? first_name", error.to_s
+ assert_match "Did you mean? first_name", get_message(error)
end
def test_corrections_include_private_method
error = assert_raise(NoMethodError){ @user.friend }
assert_correction :friends, error.corrections
- assert_match "Did you mean? friends", error.to_s
+ assert_match "Did you mean? friends", get_message(error)
end
def test_corrections_include_method_from_module
error = assert_raise(NoMethodError){ @user.fr0m_module }
assert_correction :from_module, error.corrections
- assert_match "Did you mean? from_module", error.to_s
+ assert_match "Did you mean? from_module", get_message(error)
end
def test_corrections_include_class_method
error = assert_raise(NoMethodError){ User.l0ad }
assert_correction :load, error.corrections
- assert_match "Did you mean? load", error.to_s
+ assert_match "Did you mean? load", get_message(error)
end
def test_private_methods_should_not_be_suggested
@@ -77,7 +79,7 @@ class MethodNameCheckTest < Test::Unit::TestCase
error = assert_raise(NoMethodError){ @user.call_incorrect_private_method }
assert_correction :raise, error.corrections
- assert_match "Did you mean? raise", error.to_s
+ assert_match "Did you mean? raise", get_message(error)
end
def test_exclude_methods_on_nil
@@ -104,7 +106,7 @@ class MethodNameCheckTest < Test::Unit::TestCase
end
end
- assert_equal 1, error.to_s.scan(/Did you mean/).count
+ assert_equal 1, get_message(error).scan(/Did you mean/).count
end
def test_does_not_append_suggestions_three_times
@@ -116,7 +118,7 @@ class MethodNameCheckTest < Test::Unit::TestCase
end
end
- assert_equal 1, error.to_s.scan(/Did you mean/).count
+ assert_equal 1, get_message(error).scan(/Did you mean/).count
end
def test_suggests_corrections_on_nested_error
@@ -128,20 +130,36 @@ class MethodNameCheckTest < Test::Unit::TestCase
end
end
- assert_equal 1, error.to_s.scan(/Did you mean/).count
+ assert_equal 1, get_message(error).scan(/Did you mean/).count
end
def test_suggests_yield
error = assert_raise(NoMethodError) { yeild(1) }
assert_correction :yield, error.corrections
- assert_match "Did you mean? yield", error.to_s
+ assert_match "Did you mean? yield", get_message(error)
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)
+ assert_not_match(/Did you mean\? +yield/, get_message(error))
end if RUBY_ENGINE != "jruby"
+
+ # Do not suggest `name=` for `name`
+ def test_does_not_suggest_writer
+ error = assert_raise(NoMethodError) { @user.writer }
+
+ assert_correction [], error.corrections
+ assert_not_match(/Did you mean\? writer=/, get_message(error))
+ end
+
+ # Do not suggest `name` for `name=`
+ def test_does_not_suggest_reader
+ error = assert_raise(NoMethodError) { @user.reader = 1 }
+
+ assert_correction [], error.corrections
+ assert_not_match(/Did you mean\? reader/, get_message(error))
+ end
end
diff --git a/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb b/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb
new file mode 100644
index 0000000000..10f973802b
--- /dev/null
+++ b/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb
@@ -0,0 +1,20 @@
+require_relative '../helper'
+
+return if !defined?(::NoMatchingPatternKeyError)
+
+class PatternKeyNameCheckTest < Test::Unit::TestCase
+ include DidYouMean::TestHelper
+
+ def test_corrects_hash_key_name_with_single_pattern_match
+ error = assert_raise(NoMatchingPatternKeyError) do
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
+ hash = {foo: 1, bar: 2, baz: 3}
+ hash => {fooo:}
+ fooo = 1 # suppress "unused variable: fooo" warning
+ RUBY
+ end
+
+ assert_correction ":foo", error.corrections
+ assert_match "Did you mean? :foo", get_message(error)
+ end
+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
index f67fab0568..d6c06e9999 100644
--- a/test/did_you_mean/spell_checking/test_require_path_check.rb
+++ b/test/did_you_mean/spell_checking/test_require_path_check.rb
@@ -11,7 +11,7 @@ class RequirePathCheckTest < Test::Unit::TestCase
end
assert_correction 'ostruct', error.corrections
- assert_match "Did you mean? ostruct", error.to_s
+ assert_match "Did you mean? ostruct", get_message(error)
end
def test_load_error_from_require_for_nested_files_has_suggestions
@@ -20,13 +20,13 @@ class RequirePathCheckTest < Test::Unit::TestCase
end
assert_correction 'net/http', error.corrections
- assert_match "Did you mean? net/http", error.to_s
+ assert_match "Did you mean? net/http", get_message(error)
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
+ assert_match "Did you mean? net/http", get_message(error)
end
end
diff --git a/test/did_you_mean/spell_checking/test_variable_name_check.rb b/test/did_you_mean/spell_checking/test_variable_name_check.rb
index 193e2b7520..0350b62660 100644
--- a/test/did_you_mean/spell_checking/test_variable_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_variable_name_check.rb
@@ -39,7 +39,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :first_name, error.corrections
- assert_match "Did you mean? first_name", error.to_s
+ assert_match "Did you mean? first_name", get_message(error)
end
def test_corrections_include_method_from_module
@@ -48,7 +48,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :from_module, error.corrections
- assert_match "Did you mean? from_module", error.to_s
+ assert_match "Did you mean? from_module", get_message(error)
end
def test_corrections_include_local_variable_name
@@ -57,7 +57,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
error = (eprson rescue $!) # Do not use @assert_raise here as it changes a scope.
assert_correction :person, error.corrections
- assert_match "Did you mean? person", error.to_s
+ assert_match "Did you mean? person", get_message(error)
end
end
@@ -81,30 +81,30 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :false, false_error.corrections
- assert_match "Did you mean? false", false_error.to_s
+ assert_match "Did you mean? false", get_message(false_error)
assert_correction :true, true_error.corrections
- assert_match "Did you mean? true", true_error.to_s
+ assert_match "Did you mean? true", get_message(true_error)
assert_correction :nil, nil_error.corrections
- assert_match "Did you mean? nil", nil_error.to_s
+ assert_match "Did you mean? nil", get_message(nil_error)
assert_correction :__FILE__, file_error.corrections
- assert_match "Did you mean? __FILE__", file_error.to_s
+ assert_match "Did you mean? __FILE__", get_message(file_error)
end
def test_suggests_yield
error = assert_raise(NameError) { yeild }
assert_correction :yield, error.corrections
- assert_match "Did you mean? yield", error.to_s
+ assert_match "Did you mean? yield", get_message(error)
end
def test_corrections_include_instance_variable_name
error = assert_raise(NameError){ @user.to_s }
assert_correction :@email_address, error.corrections
- assert_match "Did you mean? @email_address", error.to_s
+ assert_match "Did you mean? @email_address", get_message(error)
end
def test_corrections_include_private_method
@@ -113,7 +113,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :cia_codename, error.corrections
- assert_match "Did you mean? cia_codename", error.to_s
+ assert_match "Did you mean? cia_codename", get_message(error)
end
@@does_exist = true
@@ -122,7 +122,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
error = assert_raise(NameError){ @@doesnt_exist }
assert_correction :@@does_exist, error.corrections
- assert_match "Did you mean? @@does_exist", error.to_s
+ assert_match "Did you mean? @@does_exist", get_message(error)
end
def test_struct_name_error
@@ -130,11 +130,23 @@ class VariableNameCheckTest < Test::Unit::TestCase
error = assert_raise(NameError){ value[:doesnt_exist] }
assert_correction [:does_exist, :does_exist=], error.corrections
- assert_match "Did you mean? does_exist", error.to_s
+ assert_match "Did you mean? does_exist", get_message(error)
end
def test_exclude_typical_incorrect_suggestions
error = assert_raise(NameError){ foo }
assert_empty error.corrections
end
+
+ def test_exclude_duplicates_with_same_name
+ error = assert_raise(NameError) do
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
+ bar = 1
+ def bar;end
+ zar
+ RUBY
+ end
+
+ assert_correction [:bar], error.corrections
+ end
end
diff --git a/test/did_you_mean/test_ractor_compatibility.rb b/test/did_you_mean/test_ractor_compatibility.rb
new file mode 100644
index 0000000000..7385f10612
--- /dev/null
+++ b/test/did_you_mean/test_ractor_compatibility.rb
@@ -0,0 +1,117 @@
+require_relative './helper'
+
+return if not DidYouMean::TestHelper.ractor_compatible?
+
+class RactorCompatibilityTest < Test::Unit::TestCase
+ def test_class_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ class ::Book; end
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ Boook
+ rescue NameError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction "Book", error.corrections
+ CODE
+ end
+
+ def test_key_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ hash = { "foo" => 1, bar: 2 }
+
+ hash.fetch(:bax)
+ rescue KeyError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction ":bar", error.corrections
+ assert_match "Did you mean? :bar", get_message(error)
+ CODE
+ end
+
+ def test_method_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ self.to__s
+ rescue NoMethodError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction :to_s, error.corrections
+ assert_match "Did you mean? to_s", get_message(error)
+ CODE
+ end
+
+ if defined?(::NoMatchingPatternKeyError)
+ def test_pattern_key_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
+ hash = {foo: 1, bar: 2, baz: 3}
+ hash => {fooo:}
+ fooo = 1 # suppress "unused variable: fooo" warning
+ RUBY
+ rescue NoMatchingPatternKeyError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction ":foo", error.corrections
+ assert_match "Did you mean? :foo", get_message(error)
+ CODE
+ end
+ end
+
+ def test_can_raise_other_name_error_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ class FirstNameError < NameError; end
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ raise FirstNameError, "Other name error"
+ rescue FirstNameError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_not_match(/Did you mean\?/, error.message)
+ CODE
+ end
+
+ def test_variable_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ in_ractor = in_ractor = 1
+
+ begin
+ in_reactor
+ rescue NameError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction :in_ractor, error.corrections
+ assert_match "Did you mean? in_ractor", get_message(error)
+ CODE
+ end
+end
diff --git a/test/did_you_mean/test_spell_checker.rb b/test/did_you_mean/test_spell_checker.rb
index 98460b4d94..8445380de3 100644
--- a/test/did_you_mean/test_spell_checker.rb
+++ b/test/did_you_mean/test_spell_checker.rb
@@ -10,6 +10,7 @@ class SpellCheckerTest < Test::Unit::TestCase
assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval']
assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!']
assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!']
+ assert_spell 'Foo', input: 'FOo', dictionary: ['Foo', 'FOo']
assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!)
assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!)
diff --git a/test/did_you_mean/test_verbose_formatter.rb b/test/did_you_mean/test_verbose_formatter.rb
deleted file mode 100644
index d8f2f46273..0000000000
--- a/test/did_you_mean/test_verbose_formatter.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-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
- DidYouMean.formatter = DidYouMean::PlainFormatter.new
- end
-
- def test_message
- @error = assert_raise(NoMethodError){ 1.zeor? }
-
- assert_match <<~MESSAGE.strip, @error.message
- undefined method `zeor?' for 1:Integer
-
- Did you mean? zero?
- MESSAGE
- end
-end
diff --git a/test/did_you_mean/tree_spell/test_change_word.rb b/test/did_you_mean/tree_spell/test_change_word.rb
index 613e11b869..7855b3de50 100644
--- a/test/did_you_mean/tree_spell/test_change_word.rb
+++ b/test/did_you_mean/tree_spell/test_change_word.rb
@@ -8,7 +8,7 @@ class ChangeWordTest < Test::Unit::TestCase
@len = @input.length
end
- def test_deleletion
+ def test_deletion
assert_match @cw.deletion(5), 'spec/ervices/anything_spec'
assert_match @cw.deletion(@len - 1), 'spec/services/anything_spe'
assert_match @cw.deletion(0), 'pec/services/anything_spec'
diff --git a/test/digest/test_digest_extend.rb b/test/digest/test_digest_extend.rb
index bd599f2d20..a66b896e1e 100644
--- a/test/digest/test_digest_extend.rb
+++ b/test/digest/test_digest_extend.rb
@@ -6,6 +6,11 @@ require_relative '../lib/with_different_ofs'
class TestDigestExtend < Test::Unit::TestCase
extend DifferentOFS
+ TEST_DIGEST = %w[SHA1024 SHA512 SHA384 SHA256 SHA1].find do |n|
+ break Digest.const_get(n)
+ rescue LoadError
+ end
+
class MyDigest < Digest::Class
def initialize(*arg)
super
@@ -54,7 +59,7 @@ class TestDigestExtend < Test::Unit::TestCase
end
def test_class_reset
- a = Digest::SHA1.new
+ a = TEST_DIGEST.new
base = a.to_s
assert_equal(base, a.reset.to_s)
b = a.new
@@ -62,7 +67,7 @@ class TestDigestExtend < Test::Unit::TestCase
b.update('1')
assert_not_equal(base, b.to_s)
assert_equal(base, b.reset.to_s)
- end
+ end if TEST_DIGEST
def test_digest
assert_equal("\3", MyDigest.digest("foo"))
@@ -83,7 +88,7 @@ class TestDigestExtend < Test::Unit::TestCase
end
def test_new
- a = Digest::SHA1.new
+ a = TEST_DIGEST.new
b = a.new
obj = a.to_s
assert_equal(obj, a.to_s)
@@ -91,7 +96,7 @@ class TestDigestExtend < Test::Unit::TestCase
a.update('1')
assert_not_equal(obj, a.to_s)
assert_equal(obj, b.to_s)
- end
+ end if TEST_DIGEST
def test_digest_hexdigest
[:digest, :hexdigest].each do |m|
diff --git a/test/digest/test_ractor.rb b/test/digest/test_ractor.rb
index 0dbdcb9c8c..b34a3653b4 100644
--- a/test/digest/test_ractor.rb
+++ b/test/digest/test_ractor.rb
@@ -13,10 +13,6 @@ module TestDigestRactor
Data1 = "abc"
Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- def setup
- pend unless defined?(Ractor)
- end
-
def test_s_hexdigest
assert_in_out_err([], <<-"end;", ["true", "true"], [])
$VERBOSE = nil
@@ -98,4 +94,4 @@ module TestDigestRactor
Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
}
end if defined?(Digest::RMD160)
-end
+end if defined?(Ractor)
diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb
index acef380ad6..71bc92ab70 100644
--- a/test/drb/drbtest.rb
+++ b/test/drb/drbtest.rb
@@ -90,6 +90,7 @@ module DRbBase
end
def teardown
+ return if @omitted
@ext.stop_service if defined?(@ext) && @ext
if defined?(@service_name) && @service_name
@drb_service.manager.unregist(@service_name)
@@ -214,9 +215,10 @@ module DRbCore
end
def test_06_timeout
- skip if RUBY_PLATFORM.include?("armv7l-linux")
- skip if RUBY_PLATFORM.include?("sparc-solaris2.10")
- skip if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # expecting a certain delay is difficult for --jit-wait CI
+ omit if RUBY_PLATFORM.include?("armv7l-linux")
+ omit if RUBY_PLATFORM.include?("sparc-solaris2.10")
+ omit if RUBY_PLATFORM.include?("freebsd")
+ omit if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # expecting a certain delay is difficult for --jit-wait CI
Timeout.timeout(60) do
ten = Onecky.new(10)
assert_raise(Timeout::Error) do
diff --git a/test/drb/test_drb.rb b/test/drb/test_drb.rb
index 1ee1b265d0..11e2219bad 100644
--- a/test/drb/test_drb.rb
+++ b/test/drb/test_drb.rb
@@ -335,6 +335,7 @@ end
class TestDRbTCP < Test::Unit::TestCase
def test_immediate_close
+ omit 'MinGW leaks a thread in this test' if /mingw/ =~ RUBY_PLATFORM
server = DRb::DRbServer.new('druby://localhost:0')
host, port, = DRb::DRbTCPSocket.send(:parse_uri, server.uri)
socket = TCPSocket.open host, port
@@ -345,8 +346,8 @@ class TestDRbTCP < Test::Unit::TestCase
ensure
client&.close
socket&.close
- server.stop_service
- server.thread.join
+ server&.stop_service
+ server&.thread&.join
DRb::DRbConn.stop_pool
end
end
diff --git a/test/drb/test_drbssl.rb b/test/drb/test_drbssl.rb
index 0254c7ab50..0c7e39ca70 100644
--- a/test/drb/test_drbssl.rb
+++ b/test/drb/test_drbssl.rb
@@ -41,6 +41,10 @@ end
class TestDRbSSLCore < Test::Unit::TestCase
include DRbCore
def setup
+ if RUBY_PLATFORM.match?(/mswin|mingw/)
+ @omitted = true
+ omit 'This test seems to randomly hang on Windows'
+ end
@drb_service = DRbSSLService.new
super
setup_service 'ut_drb_drbssl.rb'
@@ -59,6 +63,10 @@ end
class TestDRbSSLAry < Test::Unit::TestCase
include DRbAry
def setup
+ if RUBY_PLATFORM.match?(/mswin|mingw/)
+ @omitted = true
+ omit 'This test seems to randomly hang on Windows'
+ end
LeakChecker.skip if defined?(LeakChecker)
@drb_service = DRbSSLService.new
super
diff --git a/test/dtrace/helper.rb b/test/dtrace/helper.rb
index ce730800b4..7fa16965f1 100644
--- a/test/dtrace/helper.rb
+++ b/test/dtrace/helper.rb
@@ -122,7 +122,7 @@ module DTrace
def trap_probe d_program, ruby_program
if Hash === d_program
d_program = d_program[IMPL] or
- skip "#{d_program} not implemented for #{IMPL}"
+ omit "#{d_program} not implemented for #{IMPL}"
elsif String === d_program && IMPL == :stap
d_program = dtrace2systemtap(d_program)
end
diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb
index fb5e9b611e..555345a140 100644
--- a/test/erb/test_erb.rb
+++ b/test/erb/test_erb.rb
@@ -73,12 +73,28 @@ class TestERB < Test::Unit::TestCase
assert_equal("", ERB::Util.html_escape(""))
assert_equal("abc", ERB::Util.html_escape("abc"))
assert_equal("&lt;&lt;", ERB::Util.html_escape("<\<"))
+ assert_equal("&#39;&amp;&quot;&gt;&lt;", ERB::Util.html_escape("'&\"><"))
assert_equal("", ERB::Util.html_escape(nil))
assert_equal("123", ERB::Util.html_escape(123))
end
+ def test_html_escape_to_s
+ object = Object.new
+ def object.to_s
+ "object"
+ end
+ assert_equal("object", ERB::Util.html_escape(object))
+ end
+
+ def test_html_escape_extension
+ assert_nil(ERB::Util.method(:html_escape).source_location)
+ end if RUBY_ENGINE == 'ruby'
+
def test_concurrent_default_binding
+ # This test randomly fails with JRuby -- NameError: undefined local variable or method `template2'
+ pend if RUBY_ENGINE == 'jruby'
+
template1 = 'one <%= ERB.new(template2).result %>'
eval 'template2 = "two"', TOPLEVEL_BINDING
@@ -236,6 +252,8 @@ EOS
end
def test_invalid_trim_mode
+ pend if RUBY_ENGINE == 'truffleruby'
+
assert_warning(/#{__FILE__}:#{__LINE__ + 1}/) do
@erb.new("", trim_mode: 'abc-def')
end
@@ -695,6 +713,18 @@ EOS
erb = Marshal.load(Marshal.dump(erb))
assert_raise(ArgumentError) {erb.result}
end
+
+ def test_multi_line_comment_lineno
+ erb = ERB.new(<<~EOS)
+ <%= __LINE__ %>
+ <%#
+ %><%= __LINE__ %>
+ EOS
+ assert_equal <<~EOS, erb.result
+ 1
+ 3
+ EOS
+ end
end
class TestERBCoreWOStrScan < TestERBCore
diff --git a/test/erb/test_erb_command.rb b/test/erb/test_erb_command.rb
index 0baa59ddd5..6bf252c5cd 100644
--- a/test/erb/test_erb_command.rb
+++ b/test/erb/test_erb_command.rb
@@ -4,27 +4,17 @@ require 'test/unit'
class TestErbCommand < Test::Unit::TestCase
def test_var
- assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w",
+ pend if RUBY_ENGINE == 'truffleruby'
+ assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}",
File.expand_path("../../libexec/erb", __dir__),
"var=hoge"],
"<%=var%>", ["hoge"])
end
def test_template_file_encoding
- assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w",
+ pend if RUBY_ENGINE == 'truffleruby'
+ assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}",
File.expand_path("../../libexec/erb", __dir__)],
"<%=''.encoding.to_s%>", ["UTF-8"])
end
-
- # These interfaces will be removed at Ruby 2.7.
- def test_deprecated_option
- warnings = [
- "warning: -S option of erb command is deprecated. Please do not use this.",
- /\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(["-I#{File.expand_path('../../lib', __dir__)}", "-w",
- File.expand_path("../../libexec/erb", __dir__),
- "-S", "0"],
- "hoge", ["hoge"], warnings)
- end
end
diff --git a/test/error_highlight/test_error_highlight.rb b/test/error_highlight/test_error_highlight.rb
index 5d90f75bbb..37026d0578 100644
--- a/test/error_highlight/test_error_highlight.rb
+++ b/test/error_highlight/test_error_highlight.rb
@@ -5,7 +5,7 @@ require "tempfile"
class ErrorHighlightTest < Test::Unit::TestCase
class DummyFormatter
- def message_for(corrections)
+ def self.message_for(corrections)
""
end
end
@@ -23,9 +23,18 @@ class ErrorHighlightTest < Test::Unit::TestCase
end
end
- def assert_error_message(klass, expected_msg, &blk)
- err = assert_raise(klass, &blk)
- assert_equal(expected_msg.chomp, err.message)
+ if Exception.method_defined?(:detailed_message)
+ def assert_error_message(klass, expected_msg, &blk)
+ omit unless klass < ErrorHighlight::CoreExt
+ err = assert_raise(klass, &blk)
+ assert_equal(expected_msg.chomp, err.detailed_message(highlight: false).sub(/ \((?:NoMethod|Name)Error\)/, ""))
+ end
+ else
+ def assert_error_message(klass, expected_msg, &blk)
+ omit unless klass < ErrorHighlight::CoreExt
+ err = assert_raise(klass, &blk)
+ assert_equal(expected_msg.chomp, err.message)
+ end
end
def test_CALL_noarg_1
@@ -980,11 +989,9 @@ undefined method `あいうえお' for nil:NilClass
end
end
- if false
-
def test_args_CALL_1
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
1.+(nil)
^^^
@@ -997,7 +1004,7 @@ nil can't be coerced into Integer
def test_args_CALL_2
v = []
assert_error_message(TypeError, <<~END) do
-no implicit conversion from nil to integer
+no implicit conversion from nil to integer (TypeError)
v[nil]
^^^
@@ -1010,7 +1017,7 @@ no implicit conversion from nil to integer
def test_args_ATTRASGN_1
v = []
assert_error_message(ArgumentError, <<~END) do
-wrong number of arguments (given 1, expected 2..3)
+wrong number of arguments (given 1, expected 2..3) (ArgumentError)
v [ ] = 1
^^^^^^
@@ -1023,7 +1030,7 @@ wrong number of arguments (given 1, expected 2..3)
def test_args_ATTRASGN_2
v = []
assert_error_message(TypeError, <<~END) do
-no implicit conversion from nil to integer
+no implicit conversion from nil to integer (TypeError)
v [nil] = 1
^^^^^^^^
@@ -1035,7 +1042,7 @@ no implicit conversion from nil to integer
def test_args_ATTRASGN_3
assert_error_message(TypeError, <<~END) do
-no implicit conversion of String into Integer
+no implicit conversion of String into Integer (TypeError)
$stdin.lineno = "str"
^^^^^
@@ -1047,7 +1054,7 @@ no implicit conversion of String into Integer
def test_args_OPCALL
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
1 + nil
^^^
@@ -1059,7 +1066,7 @@ nil can't be coerced into Integer
def test_args_FCALL_1
assert_error_message(TypeError, <<~END) do
-no implicit conversion of Symbol into String
+no implicit conversion of Symbol into String (TypeError)
"str".instance_eval { gsub("foo", :sym) }
^^^^^^^^^^^
@@ -1071,7 +1078,7 @@ no implicit conversion of Symbol into String
def test_args_FCALL_2
assert_error_message(TypeError, <<~END) do
-no implicit conversion of Symbol into String
+no implicit conversion of Symbol into String (TypeError)
"str".instance_eval { gsub "foo", :sym }
^^^^^^^^^^^
@@ -1085,7 +1092,7 @@ no implicit conversion of Symbol into String
v = []
assert_error_message(TypeError, <<~END) do
-no implicit conversion from nil to integer
+no implicit conversion from nil to integer (TypeError)
v [nil] += 42
^^^^^^^^^^
@@ -1099,7 +1106,7 @@ no implicit conversion from nil to integer
v = []
assert_error_message(ArgumentError, <<~END) do
-wrong number of arguments (given 0, expected 1..2)
+wrong number of arguments (given 0, expected 1..2) (ArgumentError)
v [ ] += 42
^^^^^^^^
@@ -1113,7 +1120,7 @@ wrong number of arguments (given 0, expected 1..2)
v = [1]
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
v [0] += nil
^^^^^^^^^
@@ -1128,7 +1135,7 @@ nil can't be coerced into Integer
def v.foo; 1; end
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
v.foo += nil
^^^
@@ -1138,12 +1145,10 @@ nil can't be coerced into Integer
end
end
- end
-
def test_custom_formatter
custom_formatter = Object.new
def custom_formatter.message_for(spot)
- "\n\n" + spot.inspect
+ "\n\n" + spot.except(:script_lines).inspect
end
original_formatter, ErrorHighlight.formatter = ErrorHighlight.formatter, custom_formatter
@@ -1194,4 +1199,92 @@ undefined method `time' for 1:Integer
end
end
end
+
+ def test_simulate_funcallv_from_embedded_ruby
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `foo' for nil:NilClass
+ END
+
+ nil.foo + 1
+ rescue NoMethodError => exc
+ def exc.backtrace_locations = []
+ raise
+ end
+ end
+
+ def test_spoofed_filename
+ Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp|
+ tmp << "module Dummy\nend\n"
+ tmp.close
+
+ assert_error_message(NameError, <<~END) do
+ undefined local variable or method `foo' for "dummy":String
+ END
+
+ "dummy".instance_eval do
+ eval <<-END, nil, tmp.path
+ foo
+ END
+ end
+ end
+ end
+ end
+
+ def raise_name_error
+ 1.time
+ end
+
+ def test_spot_with_backtrace_location
+ lineno = __LINE__
+ begin
+ raise_name_error
+ rescue NameError => exc
+ end
+
+ spot = ErrorHighlight.spot(exc).except(:script_lines)
+ assert_equal(lineno - 4, spot[:first_lineno])
+ assert_equal(lineno - 4, spot[:last_lineno])
+ assert_equal(5, spot[:first_column])
+ assert_equal(10, spot[:last_column])
+ assert_equal(" 1.time\n", spot[:snippet])
+
+ spot = ErrorHighlight.spot(exc, backtrace_location: exc.backtrace_locations[1]).except(:script_lines)
+ assert_equal(lineno + 2, spot[:first_lineno])
+ assert_equal(lineno + 2, spot[:last_lineno])
+ assert_equal(6, spot[:first_column])
+ assert_equal(22, spot[:last_column])
+ assert_equal(" raise_name_error\n", spot[:snippet])
+ end
+
+ def test_spot_with_node
+ omit unless RubyVM::AbstractSyntaxTree.respond_to?(:node_id_for_backtrace_location)
+
+ begin
+ raise_name_error
+ rescue NameError => exc
+ end
+
+ bl = exc.backtrace_locations.first
+ expected_spot = ErrorHighlight.spot(exc, backtrace_location: bl)
+ ast = RubyVM::AbstractSyntaxTree.parse_file(__FILE__, keep_script_lines: true)
+ node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(bl)
+ node = find_node_by_id(ast, node_id)
+ actual_spot = ErrorHighlight.spot(node)
+
+ assert_equal expected_spot, actual_spot
+ end
+
+ private
+
+ def find_node_by_id(node, node_id)
+ return node if node.node_id == node_id
+
+ node.children.each do |child|
+ next unless child.is_a?(RubyVM::AbstractSyntaxTree::Node)
+ found = find_node_by_id(child, node_id)
+ return found if found
+ end
+
+ return false
+ end
end
diff --git a/test/excludes/TestArray.rb b/test/excludes/TestArray.rb
new file mode 100644
index 0000000000..73da272007
--- /dev/null
+++ b/test/excludes/TestArray.rb
@@ -0,0 +1 @@
+exclude(:test_shared_marking, "The target code has already been changed")
diff --git a/test/excludes/TestGem.rb b/test/excludes/TestGem.rb
new file mode 100644
index 0000000000..042af26eff
--- /dev/null
+++ b/test/excludes/TestGem.rb
@@ -0,0 +1,4 @@
+if RbConfig::CONFIG["LIBRUBY_RELATIVE"] == "yes"
+ exclude(/test_looks_for_gemdeps_files_automatically_from_binstubs/,
+ "can't test before installation")
+end
diff --git a/test/excludes/TestThread.rb b/test/excludes/TestThread.rb
index ea73a4c010..cf7e88427e 100644
--- a/test/excludes/TestThread.rb
+++ b/test/excludes/TestThread.rb
@@ -1,2 +1,14 @@
# frozen_string_literal: false
exclude(/_stack_size$/, 'often too expensive')
+if /freebsd13/ =~ RUBY_PLATFORM
+ # http://rubyci.s3.amazonaws.com/freebsd13/ruby-master/log/20220216T143001Z.fail.html.gz
+ #
+ # 1) Error:
+ # TestThread#test_signal_at_join:
+ # Timeout::Error: execution of assert_separately expired timeout (120 sec)
+ # pid 30743 killed by SIGABRT (signal 6) (core dumped)
+ # |
+ #
+ # /usr/home/chkbuild/chkbuild/tmp/build/20220216T143001Z/ruby/test/ruby/test_thread.rb:1390:in `test_signal_at_join'
+ exclude(:test_signal_at_join, 'gets stuck somewhere')
+end
diff --git a/test/excludes/TestThreadQueue.rb b/test/excludes/TestThreadQueue.rb
new file mode 100644
index 0000000000..c8231e372a
--- /dev/null
+++ b/test/excludes/TestThreadQueue.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: false
+if /freebsd13/ =~ RUBY_PLATFORM
+ # http://rubyci.s3.amazonaws.com/freebsd13/ruby-master/log/20220308T023001Z.fail.html.gz
+ #
+ # 1) Failure:
+ # TestThreadQueue#test_thr_kill [/usr/home/chkbuild/chkbuild/tmp/build/20220308T023001Z/ruby/test/ruby/test_thread_queue.rb:175]:
+ # only 169/250 done in 60 seconds.
+ exclude(:test_thr_kill, 'gets stuck somewhere')
+end
diff --git a/test/fiber/autoload.rb b/test/fiber/autoload.rb
new file mode 100644
index 0000000000..dcb27164a7
--- /dev/null
+++ b/test/fiber/autoload.rb
@@ -0,0 +1,3 @@
+sleep 0.01
+module TestFiberSchedulerAutoload
+end
diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb
index 2785561000..204a297133 100644
--- a/test/fiber/scheduler.rb
+++ b/test/fiber/scheduler.rb
@@ -14,6 +14,14 @@ rescue LoadError
end
class Scheduler
+ experimental = Warning[:experimental]
+ begin
+ Warning[:experimental] = false
+ IO::Buffer.new(0)
+ ensure
+ Warning[:experimental] = experimental
+ end
+
def initialize
@readable = {}
@writable = {}
@@ -22,7 +30,7 @@ class Scheduler
@closed = false
@lock = Thread::Mutex.new
- @blocking = 0
+ @blocking = Hash.new.compare_by_identity
@ready = []
@urgent = IO.pipe
@@ -49,7 +57,7 @@ class Scheduler
def run
# $stderr.puts [__method__, Fiber.current].inspect
- while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive?
+ while @readable.any? or @writable.any? or @waiting.any? or @blocking.any?
# Can only handle file descriptors up to 1024...
readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], next_timeout)
@@ -60,6 +68,7 @@ class Scheduler
readable&.each do |io|
if fiber = @readable.delete(io)
+ @writable.delete(io) if @writable[io] == fiber
selected[fiber] = IO::READABLE
elsif io == @urgent.first
@urgent.first.read_nonblock(1024)
@@ -68,7 +77,8 @@ class Scheduler
writable&.each do |io|
if fiber = @writable.delete(io)
- selected[fiber] |= IO::WRITABLE
+ @readable.delete(io) if @readable[io] == fiber
+ selected[fiber] = selected.fetch(fiber, 0) | IO::WRITABLE
end
end
@@ -105,10 +115,22 @@ class Scheduler
end
end
- def close
+ def scheduler_close
+ close(true)
+ end
+
+ def close(internal = false)
# $stderr.puts [__method__, Fiber.current].inspect
- raise "Scheduler already closed!" if @closed
+ unless internal
+ if Fiber.scheduler == self
+ return Fiber.set_scheduler(nil)
+ end
+ end
+
+ if @closed
+ raise "Scheduler already closed!"
+ end
self.run
ensure
@@ -117,7 +139,7 @@ class Scheduler
@urgent = nil
end
- @closed = true
+ @closed ||= true
# We freeze to detect any unintended modifications after the scheduler is closed:
self.freeze
@@ -170,6 +192,16 @@ class Scheduler
end
Fiber.yield
+ ensure
+ @readable.delete(io)
+ @writable.delete(io)
+ end
+
+ def io_select(...)
+ # Emulate the operation using a non-blocking thread:
+ Thread.new do
+ IO.select(...)
+ end.value
end
# Used for Kernel#sleep and Thread::Mutex#sleep
@@ -186,20 +218,22 @@ class Scheduler
def block(blocker, timeout = nil)
# $stderr.puts [__method__, blocker, timeout].inspect
+ fiber = Fiber.current
+
if timeout
- @waiting[Fiber.current] = current_time + timeout
+ @waiting[fiber] = current_time + timeout
begin
Fiber.yield
ensure
# Remove from @waiting in the case #unblock was called before the timeout expired:
- @waiting.delete(Fiber.current)
+ @waiting.delete(fiber)
end
else
- @blocking += 1
+ @blocking[fiber] = true
begin
Fiber.yield
ensure
- @blocking -= 1
+ @blocking.delete(fiber)
end
end
end
@@ -235,6 +269,70 @@ class Scheduler
end
end
+class IOBufferScheduler < Scheduler
+ EAGAIN = -Errno::EAGAIN::Errno
+
+ def io_read(io, buffer, length, offset)
+ total = 0
+ io.nonblock = true
+
+ while true
+ maximum_size = buffer.size - offset
+ result = blocking{buffer.read(io, maximum_size, offset)}
+
+ if result > 0
+ total += result
+ offset += result
+ break if total >= length
+ elsif result == 0
+ break
+ elsif result == EAGAIN
+ if length > 0
+ self.io_wait(io, IO::READABLE, nil)
+ else
+ return result
+ end
+ elsif result < 0
+ return result
+ end
+ end
+
+ return total
+ end
+
+ def io_write(io, buffer, length, offset)
+ total = 0
+ io.nonblock = true
+
+ while true
+ maximum_size = buffer.size - offset
+ result = blocking{buffer.write(io, maximum_size, offset)}
+
+ if result > 0
+ total += result
+ offset += result
+ break if total >= length
+ elsif result == 0
+ break
+ elsif result == EAGAIN
+ if length > 0
+ self.io_wait(io, IO::WRITABLE, nil)
+ else
+ return result
+ end
+ elsif result < 0
+ return result
+ end
+ end
+
+ return total
+ end
+
+ def blocking(&block)
+ Fiber.blocking(&block)
+ end
+end
+
class BrokenUnblockScheduler < Scheduler
def unblock(blocker, fiber)
super
@@ -252,3 +350,14 @@ class SleepingUnblockScheduler < Scheduler
sleep(0.1)
end
end
+
+class SleepingBlockingScheduler < Scheduler
+ def kernel_sleep(duration = nil)
+ # Deliberaly sleep in a blocking state which can trigger a deadlock if the implementation is not correct.
+ Fiber.blocking{sleep 0.0001}
+
+ self.block(:sleep, duration)
+
+ return true
+ end
+end
diff --git a/test/fiber/test_address_resolve.rb b/test/fiber/test_address_resolve.rb
index 457221b9b1..12223bcc06 100644
--- a/test/fiber/test_address_resolve.rb
+++ b/test/fiber/test_address_resolve.rb
@@ -269,7 +269,7 @@ class TestAddressResolve < Test::Unit::TestCase
Fiber.set_scheduler scheduler
Fiber.schedule do
- result = Socket.getnameinfo(["AF_INET", 80, "example.com"], Socket::NI_NUMERICSERV)
+ result = Socket.getnameinfo(["AF_INET", 80, "example.com"], Socket::NI_NUMERICSERV | Socket::NI_NUMERICHOST)
assert_equal(["1.2.3.4", "80"], result)
end
diff --git a/test/fiber/test_enumerator.rb b/test/fiber/test_enumerator.rb
index cd4ccd1de5..e9410f925c 100644
--- a/test/fiber/test_enumerator.rb
+++ b/test/fiber/test_enumerator.rb
@@ -6,16 +6,10 @@ class TestFiberEnumerator < Test::Unit::TestCase
MESSAGE = "Hello World"
def test_read_characters
- skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+ omit "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
@@ -48,4 +42,12 @@ class TestFiberEnumerator < Test::Unit::TestCase
assert_predicate(i, :closed?)
assert_predicate(o, :closed?)
end
+
+ def enumerator_fiber_is_nonblocking
+ enumerator = Enumerator.new do |yielder|
+ yielder << Fiber.current.blocking?
+ end
+
+ assert_equal(false, enumerator.next)
+ end
end
diff --git a/test/fiber/test_io.rb b/test/fiber/test_io.rb
index fafda7c310..c1ad56a8cf 100644
--- a/test/fiber/test_io.rb
+++ b/test/fiber/test_io.rb
@@ -6,14 +6,12 @@ class TestFiberIO < Test::Unit::TestCase
MESSAGE = "Hello World"
def test_read
- skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+ omit unless defined?(UNIXSocket)
i, o = UNIXSocket.pair
-
- unless i.nonblock? && o.nonblock?
- i.close
- o.close
- skip "I/O is not non-blocking!"
+ if RUBY_PLATFORM=~/mswin|mingw/
+ i.nonblock = true
+ o.nonblock = true
end
message = nil
@@ -41,11 +39,15 @@ class TestFiberIO < Test::Unit::TestCase
end
def test_heavy_read
- skip unless defined?(UNIXSocket)
+ omit unless defined?(UNIXSocket)
16.times.map do
Thread.new do
i, o = UNIXSocket.pair
+ if RUBY_PLATFORM=~/mswin|mingw/
+ i.nonblock = true
+ o.nonblock = true
+ end
scheduler = Scheduler.new
Fiber.set_scheduler scheduler
@@ -64,16 +66,11 @@ class TestFiberIO < Test::Unit::TestCase
end
def test_epipe_on_read
- skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+ omit unless defined?(UNIXSocket)
+ omit "nonblock=true isn't properly supported on Windows" if RUBY_PLATFORM=~/mswin|mingw/
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
@@ -97,4 +94,129 @@ class TestFiberIO < Test::Unit::TestCase
assert_kind_of Errno::EPIPE, error
end
+
+ def test_tcp_accept
+ server = TCPServer.new('localhost', 0)
+
+ th = Thread.new do
+ Fiber.set_scheduler(Scheduler.new)
+
+ Fiber.schedule do
+ sender = server.accept
+ sender.wait_writable
+ sender.write "hello"
+ sender.close
+ end
+ end
+
+ recver = TCPSocket.new('localhost', server.local_address.ip_port)
+ assert "hello", recver.read
+
+ recver.close
+ server.close
+ th.join
+ end
+
+ def test_tcp_connect
+ server = TCPServer.new('localhost', 0)
+
+ th = Thread.new do
+ Fiber.set_scheduler(Scheduler.new)
+
+ Fiber.schedule do
+ sender = TCPSocket.new('localhost', server.local_address.ip_port)
+ sender.write "hello"
+ sender.close
+ end
+ end
+
+ recver = server.accept
+ assert "hello", recver.read
+
+ recver.close
+ server.close
+ th.join
+ end
+
+ def test_read_write_blocking
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ message = nil
+
+ thread = Thread.new do
+ # This scheduler provides non-blocking `io_read`/`io_write`:
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read(20)
+ i.close
+ end
+
+ Fiber.schedule do
+ o.write("Hello World")
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, message
+ assert_predicate(i, :closed?)
+ assert_predicate(o, :closed?)
+ end
+
+ def test_puts_empty
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ thread = Thread.new do
+ # This scheduler provides non-blocking `io_read`/`io_write`:
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ # This was causing a segfault on older Ruby.
+ o.puts ""
+ o.puts nil
+ o.close
+ end
+ end
+
+ thread.join
+
+ message = i.read
+ i.close
+
+ assert_equal $/*2, message
+ end
+
+ def test_io_select
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ UNIXSocket.pair do |r, w|
+ result = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ w.write("Hello World")
+ result = IO.select([r], [w])
+ end
+ end
+
+ thread.join
+
+ assert_equal [[r], [w], []], result
+ end
+ end
end
diff --git a/test/fiber/test_io_buffer.rb b/test/fiber/test_io_buffer.rb
new file mode 100644
index 0000000000..3de70200d5
--- /dev/null
+++ b/test/fiber/test_io_buffer.rb
@@ -0,0 +1,158 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+require 'timeout'
+
+class TestFiberIOBuffer < Test::Unit::TestCase
+ MESSAGE = "Hello World"
+
+ def test_read_write_blocking
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ message = nil
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read(20)
+ i.close
+ end
+
+ Fiber.schedule do
+ o.write(MESSAGE)
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, message
+ assert_predicate(i, :closed?)
+ assert_predicate(o, :closed?)
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_timeout_after
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ message = nil
+ error = nil
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ Timeout.timeout(0.1) do
+ message = i.read(20)
+ end
+ rescue Timeout::Error => error
+ # Assertions below.
+ ensure
+ i.close
+ end
+ end
+
+ thread.join
+
+ assert_nil message
+ assert_kind_of Timeout::Error, error
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_read_nonblock
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ message = nil
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read_nonblock(20, exception: false)
+ i.close
+ end
+ end
+
+ thread.join
+
+ assert_equal :wait_readable, message
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_write_nonblock
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ o.write_nonblock(MESSAGE, exception: false)
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, i.read
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_io_buffer_read_write
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ source_buffer = IO::Buffer.for("Hello World!")
+ destination_buffer = IO::Buffer.new(source_buffer.size)
+
+ # Test non-scheduler code path:
+ source_buffer.write(o, source_buffer.size)
+ destination_buffer.read(i, source_buffer.size)
+ assert_equal source_buffer, destination_buffer
+
+ # Test scheduler code path:
+ destination_buffer.clear
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ source_buffer.write(o, source_buffer.size)
+ destination_buffer.read(i, source_buffer.size)
+ end
+ end
+
+ thread.join
+
+ assert_equal source_buffer, destination_buffer
+ ensure
+ i&.close
+ o&.close
+ end
+end
diff --git a/test/fiber/test_mutex.rb b/test/fiber/test_mutex.rb
index b0655f06a5..449c49f38b 100644
--- a/test/fiber/test_mutex.rb
+++ b/test/fiber/test_mutex.rb
@@ -194,7 +194,7 @@ class TestFiberMutex < Test::Unit::TestCase
end
def test_mutex_deadlock
- error_pattern = /No live threads left. Deadlock\?/
+ error_pattern = /lock already owned by another fiber/
assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], error_pattern, success: false
require 'scheduler'
@@ -217,4 +217,24 @@ class TestFiberMutex < Test::Unit::TestCase
thread.join
RUBY
end
+
+ def test_mutex_fiber_deadlock_no_scheduler
+ thr = Thread.new do
+ loop do
+ sleep 1
+ end
+ end
+
+ mutex = Mutex.new
+ mutex.synchronize do
+ error = assert_raise ThreadError do
+ Fiber.new do
+ mutex.lock
+ end.resume
+ end
+ assert_includes error.message, "deadlock; lock already owned by another fiber belonging to the same thread"
+ end
+ ensure
+ thr&.kill&.join
+ end
end
diff --git a/test/fiber/test_process.rb b/test/fiber/test_process.rb
index c6583cac9b..cc1694576e 100644
--- a/test/fiber/test_process.rb
+++ b/test/fiber/test_process.rb
@@ -33,4 +33,40 @@ class TestFiberProcess < Test::Unit::TestCase
end
end.join
end
+
+ def test_system_faulty_process_wait
+ Thread.new do
+ scheduler = Scheduler.new
+
+ def scheduler.process_wait(pid, flags)
+ Fiber.blocking{Process.wait(pid, flags)}
+
+ # Don't return `Process::Status` instance.
+ return false
+ end
+
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ assert_raise TypeError do
+ system("true")
+ end
+ 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_queue.rb b/test/fiber/test_queue.rb
new file mode 100644
index 0000000000..d78b026f11
--- /dev/null
+++ b/test/fiber/test_queue.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberQueue < Test::Unit::TestCase
+ def test_pop_with_timeout
+ queue = Thread::Queue.new
+ kill = false
+ result = :unspecified
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler(scheduler)
+
+ Fiber.schedule do
+ result = queue.pop(timeout: 0.0001)
+ end
+
+ scheduler.run
+ end
+ until thread.join(2)
+ kill = true
+ thread.kill
+ end
+
+ assert_false(kill, 'Getting stuck due to a possible compiler bug.')
+ assert_nil result
+ end
+
+ def test_pop_with_timeout_and_value
+ queue = Thread::Queue.new
+ queue.push(:something)
+ kill = false
+ result = :unspecified
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler(scheduler)
+
+ Fiber.schedule do
+ result = queue.pop(timeout: 0.0001)
+ end
+
+ scheduler.run
+ end
+ until thread.join(2)
+ kill = true
+ thread.kill
+ end
+
+ assert_false(kill, 'Getting stuck due to a possible compiler bug.')
+ assert_equal :something, result
+ end
+end
diff --git a/test/fiber/test_ractor.rb b/test/fiber/test_ractor.rb
index d03455a9f7..3c4ccbd8e5 100644
--- a/test/fiber/test_ractor.rb
+++ b/test/fiber/test_ractor.rb
@@ -4,7 +4,7 @@ require "fiber"
class TestFiberCurrentRactor < Test::Unit::TestCase
def setup
- skip unless defined? Ractor
+ omit unless defined? Ractor
end
def test_ractor_shareable
diff --git a/test/fiber/test_scheduler.rb b/test/fiber/test_scheduler.rb
index f0f5b79f36..654154c622 100644
--- a/test/fiber/test_scheduler.rb
+++ b/test/fiber/test_scheduler.rb
@@ -27,6 +27,18 @@ class TestFiberScheduler < Test::Unit::TestCase
refute f.blocking?
end
+ def test_fiber_blocking
+ f = Fiber.new(blocking: false) do
+ fiber = Fiber.current
+ refute fiber.blocking?
+ Fiber.blocking do |_fiber|
+ assert_equal fiber, _fiber
+ assert fiber.blocking?
+ end
+ end
+ f.resume
+ end
+
def test_closed_at_thread_exit
scheduler = Scheduler.new
@@ -55,6 +67,7 @@ class TestFiberScheduler < Test::Unit::TestCase
def test_close_at_exit
assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['Running Fiber'], [], success: true
require 'scheduler'
+ Warning[:experimental] = false
scheduler = Scheduler.new
Fiber.set_scheduler scheduler
@@ -103,4 +116,111 @@ class TestFiberScheduler < Test::Unit::TestCase
thread.join
end
+
+ def test_autoload
+ 100.times do
+ Object.autoload(:TestFiberSchedulerAutoload, File.expand_path("autoload.rb", __dir__))
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ 10.times do
+ Fiber.schedule do
+ Object.const_get(:TestFiberSchedulerAutoload)
+ end
+ end
+ end
+
+ thread.join
+ ensure
+ $LOADED_FEATURES.delete(File.expand_path("autoload.rb", __dir__))
+ Object.send(:remove_const, :TestFiberSchedulerAutoload)
+ end
+ end
+
+ def test_iseq_compile_under_gc_stress_bug_21180
+ Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ EnvUtil.under_gc_stress do
+ RubyVM::InstructionSequence.compile_file(File::NULL)
+ end
+ end
+ end.join
+ end
+
+ def test_deadlock
+ mutex = Thread::Mutex.new
+ condition = Thread::ConditionVariable.new
+ q = 0.0001
+
+ signaller = Thread.new do
+ loop do
+ mutex.synchronize do
+ condition.signal
+ end
+ sleep q
+ end
+ end
+
+ i = 0
+
+ thread = Thread.new do
+ scheduler = SleepingBlockingScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ 10.times do
+ mutex.synchronize do
+ condition.wait(mutex)
+ sleep q
+ i += 1
+ end
+ end
+ end
+ end
+
+ # Wait for 10 seconds at most... if it doesn't finish, it's deadlocked.
+ thread.join(10)
+
+ # If it's deadlocked, it will never finish, so this will be 0.
+ assert_equal 10, i
+ ensure
+ # Make sure the threads are dead...
+ thread.kill
+ signaller.kill
+ thread.join
+ signaller.join
+ end
+
+ def test_condition_variable
+ condition_variable = ::Thread::ConditionVariable.new
+ mutex = ::Thread::Mutex.new
+
+ error = nil
+
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ fiber = Fiber.schedule do
+ begin
+ mutex.synchronize do
+ condition_variable.wait(mutex)
+ end
+ rescue => error
+ end
+ end
+
+ fiber.raise(RuntimeError)
+ end
+
+ thread.join
+ assert_kind_of RuntimeError, error
+ end
end
diff --git a/test/fiber/test_storage.rb b/test/fiber/test_storage.rb
new file mode 100644
index 0000000000..3726decbdb
--- /dev/null
+++ b/test/fiber/test_storage.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class TestFiberStorage < Test::Unit::TestCase
+ def test_storage
+ Fiber.new do
+ Fiber[:x] = 10
+ assert_kind_of Hash, Fiber.current.storage
+ assert_predicate Fiber.current.storage, :any?
+ end.resume
+ end
+
+ def test_storage_inherited
+ Fiber.new do
+ Fiber[:foo] = :bar
+
+ Fiber.new do
+ assert_equal :bar, Fiber[:foo]
+ Fiber[:bar] = :baz
+ end.resume
+
+ assert_nil Fiber[:bar]
+ end.resume
+ end
+
+ def test_variable_assignment
+ Fiber.new do
+ Fiber[:foo] = :bar
+ assert_equal :bar, Fiber[:foo]
+ end.resume
+ end
+
+ def test_storage_assignment
+ old, Warning[:experimental] = Warning[:experimental], false
+
+ Fiber.new do
+ Fiber.current.storage = {foo: :bar}
+ assert_equal :bar, Fiber[:foo]
+ end.resume
+ ensure
+ Warning[:experimental] = old
+ end
+
+ def test_storage_only_allow_access_from_same_fiber
+ old, Warning[:experimental] = Warning[:experimental], false
+
+ f = Fiber.new do
+ Fiber[:a] = 1
+ end
+ assert_raise(ArgumentError) { f.storage }
+ assert_raise(ArgumentError) { f.storage = {} }
+ ensure
+ Warning[:experimental] = old
+ end
+
+ def test_inherited_storage
+ Fiber.new(storage: {foo: :bar}) do
+ f = Fiber.new do
+ assert_equal :bar, Fiber[:foo]
+ end
+ f.resume
+ end.resume
+ end
+
+ def test_enumerator_inherited_storage
+ Fiber.new do
+ Fiber[:item] = "Hello World"
+
+ enumerator = Enumerator.new do |out|
+ out << Fiber.current
+ out << Fiber[:item]
+ end
+
+ # The fiber within the enumerator is not equal to the current...
+ assert_not_equal Fiber.current, enumerator.next
+
+ # But it inherited the storage from the current fiber:
+ assert_equal "Hello World", enumerator.next
+ end.resume
+ end
+
+ def test_thread_inherited_storage
+ Fiber.new do
+ Fiber[:x] = 10
+
+ x = Thread.new do
+ Fiber[:y] = 20
+ Fiber[:x]
+ end.value
+
+ assert_equal 10, x
+ assert_equal nil, Fiber[:y]
+ end.resume
+ end
+
+ def test_enumerator_count
+ Fiber.new do
+ Fiber[:count] = 0
+
+ enumerator = Enumerator.new do |y|
+ Fiber[:count] += 1
+ y << Fiber[:count]
+ end
+
+ assert_equal 1, enumerator.next
+ assert_equal 0, Fiber[:count]
+ end.resume
+ end
+
+ def test_storage_assignment_type_error
+ assert_raise(TypeError) do
+ Fiber.new(storage: {Object.new => "bar"}) {}
+ end
+ end
+end
diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb
index 5c25c43de2..6fae266955 100644
--- a/test/fiber/test_thread.rb
+++ b/test/fiber/test_thread.rb
@@ -20,6 +20,28 @@ class TestFiberThread < Test::Unit::TestCase
assert_equal :done, thread.value
end
+ def test_thread_join_timeout
+ sleeper = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleeper = Thread.new{sleep}
+ sleeper.join(0.1)
+ end
+
+ scheduler.run
+ end
+
+ thread.join
+
+ assert_predicate sleeper, :alive?
+ ensure
+ sleeper&.kill
+ end
+
def test_thread_join_implicit
sleeping = false
finished = false
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index a6e2019924..e470f5a276 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
+
+require 'rbconfig/sizeof'
require 'test/unit'
require 'fiddle'
@@ -47,8 +49,14 @@ when /linux/
libm_so = libc_so
else
# glibc
- libc_so = "libc.so.6"
- libm_so = "libm.so.6"
+ case RUBY_PLATFORM
+ when /alpha-linux/, /ia64-linux/
+ libc_so = "libc.so.6.1"
+ libm_so = "libm.so.6.1"
+ else
+ libc_so = "libc.so.6"
+ libm_so = "libm.so.6"
+ end
end
when /mingw/, /mswin/
require "rbconfig"
@@ -56,6 +64,8 @@ when /mingw/, /mswin/
libc_so = libm_so = "#{crtname}.dll"
when /darwin/
libc_so = libm_so = "/usr/lib/libSystem.B.dylib"
+ # macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen.
+ rigid_path = true
when /kfreebsd/
libc_so = "/lib/libc.so.0.1"
libm_so = "/lib/libm.so.1"
@@ -131,12 +141,9 @@ else
end
end
-libc_so = nil if !libc_so || (libc_so[0] == ?/ && !File.file?(libc_so))
-libm_so = nil if !libm_so || (libm_so[0] == ?/ && !File.file?(libm_so))
-
-# macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen.
-if RUBY_PLATFORM =~ /darwin/
- libc_so = libm_so = "/usr/lib/libSystem.B.dylib"
+unless rigid_path
+ libc_so = nil if libc_so && libc_so[0] == ?/ && !File.file?(libc_so)
+ libm_so = nil if libm_so && libm_so[0] == ?/ && !File.file?(libm_so)
end
if !libc_so || !libm_so
@@ -166,5 +173,12 @@ module Fiddle
GC.start
end
end
+
+ def under_gc_stress
+ stress, GC.stress = GC.stress, true
+ yield
+ ensure
+ GC.stress = stress
+ end
end
end
diff --git a/test/fiddle/test_c_struct_builder.rb b/test/fiddle/test_c_struct_builder.rb
index 187424c92d..ca44c6cf7a 100644
--- a/test/fiddle/test_c_struct_builder.rb
+++ b/test/fiddle/test_c_struct_builder.rb
@@ -3,12 +3,45 @@ begin
require_relative 'helper'
require 'fiddle/struct'
require 'fiddle/cparser'
+ require 'fiddle/import'
rescue LoadError
end
module Fiddle
class TestCStructBuilder < TestCase
include Fiddle::CParser
+ extend Fiddle::Importer
+
+ RBasic = struct ['void * flags',
+ 'void * klass' ]
+
+
+ RObject = struct [
+ { 'basic' => RBasic },
+ { 'as' => union([
+ { 'heap'=> struct([ 'uint32_t numiv',
+ 'void * ivptr',
+ 'void * iv_index_tbl' ]) },
+ 'void *ary[3]' ])}
+ ]
+
+
+ def test_basic_embedded_members
+ assert_equal 0, RObject.offsetof("basic.flags")
+ assert_equal Fiddle::SIZEOF_VOIDP, RObject.offsetof("basic.klass")
+ end
+
+ def test_embedded_union_members
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as")
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap")
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.numiv")
+ assert_equal 3 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.ivptr")
+ assert_equal 4 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.iv_index_tbl")
+ end
+
+ def test_as_ary
+ assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.ary")
+ end
def test_offsetof
types, members = parse_struct_signature(['int64_t i','char c'])
diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb
index 9e748bf5ee..825ea9651d 100644
--- a/test/fiddle/test_closure.rb
+++ b/test/fiddle/test_closure.rb
@@ -6,6 +6,17 @@ end
module Fiddle
class TestClosure < Fiddle::TestCase
+ def teardown
+ super
+ # Ensure freeing all closures.
+ # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 .
+ not_freed_closures = []
+ ObjectSpace.each_object(Fiddle::Closure) do |closure|
+ not_freed_closures << closure unless closure.freed?
+ end
+ assert_equal([], not_freed_closures)
+ end
+
def test_argument_errors
assert_raise(TypeError) do
Closure.new(TYPE_INT, TYPE_INT)
@@ -21,37 +32,40 @@ module Fiddle
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),
- ])
+ Closure.create(:int, [:void]) do |closure|
+ assert_equal([
+ TYPE_INT,
+ [TYPE_VOID],
+ ],
+ [
+ closure.instance_variable_get(:@ctype),
+ closure.instance_variable_get(:@args),
+ ])
+ end
end
def test_call
- closure = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call
10
end
- }.new(TYPE_INT, [])
-
- func = Function.new(closure, [], TYPE_INT)
- assert_equal 10, func.call
+ end
+ closure_class.create(TYPE_INT, []) do |closure|
+ func = Function.new(closure, [], TYPE_INT)
+ assert_equal 10, func.call
+ end
end
def test_returner
- closure = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call thing
thing
end
- }.new(TYPE_INT, [TYPE_INT])
-
- func = Function.new(closure, [TYPE_INT], TYPE_INT)
- assert_equal 10, func.call(10)
+ end
+ closure_class.create(TYPE_INT, [TYPE_INT]) do |closure|
+ func = Function.new(closure, [TYPE_INT], TYPE_INT)
+ assert_equal 10, func.call(10)
+ end
end
def test_const_string
@@ -61,25 +75,41 @@ module Fiddle
@return_string
end
end
- closure = closure_class.new(:const_string, [:const_string])
+ closure_class.create(:const_string, [:const_string]) do |closure|
+ func = Function.new(closure, [:const_string], :const_string)
+ assert_equal("Hello! World!", func.call("World!"))
+ end
+ end
- func = Function.new(closure, [:const_string], :const_string)
- assert_equal("Hello! World!", func.call("World!"))
+ def test_free
+ Closure.create(:int, [:void]) do |closure|
+ assert(!closure.freed?)
+ closure.free
+ assert(closure.freed?)
+ closure.free
+ end
end
def test_block_caller
cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
one
end
- func = Function.new(cb, [TYPE_INT], TYPE_INT)
- assert_equal 11, func.call(11)
+ begin
+ func = Function.new(cb, [TYPE_INT], TYPE_INT)
+ assert_equal 11, func.call(11)
+ ensure
+ cb.free
+ end
end
- def test_memsize
+ def test_memsize_ruby_dev_42480
require 'objspace'
- bug = '[ruby-dev:42480]'
n = 10000
- assert_equal(n, n.times {ObjectSpace.memsize_of(Closure.allocate)}, bug)
+ n.times do
+ Closure.create(:int, [:void]) do |closure|
+ ObjectSpace.memsize_of(closure)
+ end
+ end
end
%w[INT SHORT CHAR LONG LONG_LONG].each do |name|
@@ -89,20 +119,21 @@ module Fiddle
define_method("test_conversion_#{n.downcase}") do
arg = nil
- clos = Class.new(Closure) do
+ closure_class = Class.new(Closure) do
define_method(:call) {|x| arg = x}
- end.new(t, [t])
-
- v = ~(~0 << (8*s))
-
- arg = nil
- assert_equal(v, clos.call(v))
- assert_equal(arg, v, n)
-
- arg = nil
- func = Function.new(clos, [t], t)
- assert_equal(v, func.call(v))
- assert_equal(arg, v, n)
+ end
+ closure_class.create(t, [t]) do |closure|
+ v = ~(~0 << (8*s))
+
+ arg = nil
+ assert_equal(v, closure.call(v))
+ assert_equal(arg, v, n)
+
+ arg = nil
+ func = Function.new(closure, [t], t)
+ assert_equal(v, func.call(v))
+ assert_equal(arg, v, n)
+ end
end
end
end
diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb
index 24e1800e59..ae319197a4 100644
--- a/test/fiddle/test_cparser.rb
+++ b/test/fiddle/test_cparser.rb
@@ -326,7 +326,7 @@ module Fiddle
def test_signature_variadic_arguments
unless Fiddle.const_defined?("TYPE_VARIADIC")
- skip "libffi doesn't support variadic arguments"
+ omit "libffi doesn't support variadic arguments"
end
assert_equal([
"printf",
diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb
index 8751d96920..9bddb056c9 100644
--- a/test/fiddle/test_fiddle.rb
+++ b/test/fiddle/test_fiddle.rb
@@ -5,6 +5,13 @@ rescue LoadError
end
class TestFiddle < Fiddle::TestCase
+ def test_nil_true_etc
+ assert_equal Fiddle::Qtrue, Fiddle.dlwrap(true)
+ assert_equal Fiddle::Qfalse, Fiddle.dlwrap(false)
+ assert_equal Fiddle::Qnil, Fiddle.dlwrap(nil)
+ assert Fiddle::Qundef
+ end
+
def test_windows_constant
require 'rbconfig'
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
@@ -14,4 +21,38 @@ class TestFiddle < Fiddle::TestCase
end
end
+ def test_dlopen_linker_script_input_linux
+ omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
+ if Dir.glob("/usr/lib/*/libncurses.so").empty?
+ omit("libncurses.so is needed")
+ end
+ # libncurses.so uses INPUT() on Debian GNU/Linux
+ # $ cat /usr/lib/x86_64-linux-gnu/libncurses.so
+ # INPUT(libncurses.so.6 -ltinfo)
+ handle = Fiddle.dlopen("libncurses.so")
+ begin
+ assert_equal("libncurses.so",
+ File.basename(handle.file_name, ".*"))
+ ensure
+ handle.close
+ end
+ end
+
+ def test_dlopen_linker_script_group_linux
+ omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
+ # libc.so uses GROUP() on Debian GNU/Linux
+ # $ cat /usr/lib/x86_64-linux-gnu/libc.so
+ # /* GNU ld script
+ # Use the shared library, but some functions are only in
+ # the static library, so try that secondarily. */
+ # OUTPUT_FORMAT(elf64-x86-64)
+ # GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
+ handle = Fiddle.dlopen("libc.so")
+ begin
+ assert_equal("libc.so",
+ File.basename(handle.file_name, ".*"))
+ ensure
+ handle.close
+ end
+ end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb
index d3604c79c3..ff52f727d0 100644
--- a/test/fiddle/test_func.rb
+++ b/test/fiddle/test_func.rb
@@ -15,7 +15,7 @@ module Fiddle
begin
f = Function.new(@libm['sinf'], [TYPE_FLOAT], TYPE_FLOAT)
rescue Fiddle::DLError
- skip "libm may not have sinf()"
+ omit "libm may not have sinf()"
end
assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001
end
@@ -26,14 +26,13 @@ module Fiddle
end
def test_string
- stress, GC.stress = GC.stress, true
- f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
- buff = +"000"
- str = f.call(buff, "123")
- assert_equal("123", buff)
- assert_equal("123", str.to_s)
- ensure
- GC.stress = stress
+ under_gc_stress do
+ f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
+ buff = +"000"
+ str = f.call(buff, "123")
+ assert_equal("123", buff)
+ assert_equal("123", str.to_s)
+ end
end
def test_isdigit
@@ -61,28 +60,40 @@ module Fiddle
end
def test_qsort1
- cb = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call(x, y)
Pointer.new(x)[0] <=> Pointer.new(y)[0]
end
- }.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP])
+ end
- qsort = Function.new(@libc['qsort'],
- [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP],
- TYPE_VOID)
- buff = "9341"
- qsort.call(buff, buff.size, 1, cb)
- assert_equal("1349", buff)
+ closure_class.create(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]) do |callback|
+ qsort = Function.new(@libc['qsort'],
+ [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP],
+ TYPE_VOID)
+ buff = "9341"
+ qsort.call(buff, buff.size, 1, callback)
+ assert_equal("1349", buff)
- bug4929 = '[ruby-core:37395]'
- buff = "9341"
- EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)}
- assert_equal("1349", buff, bug4929)
+ bug4929 = '[ruby-core:37395]'
+ buff = "9341"
+ under_gc_stress do
+ qsort.call(buff, buff.size, 1, callback)
+ end
+ assert_equal("1349", buff, bug4929)
+ end
+ ensure
+ # Ensure freeing all closures.
+ # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 .
+ not_freed_closures = []
+ ObjectSpace.each_object(Fiddle::Closure) do |closure|
+ not_freed_closures << closure unless closure.freed?
+ end
+ assert_equal([], not_freed_closures)
end
def test_snprintf
unless Fiddle.const_defined?("TYPE_VARIADIC")
- skip "libffi doesn't support variadic arguments"
+ omit "libffi doesn't support variadic arguments"
end
if Fiddle::WINDOWS
snprintf_name = "_snprintf"
@@ -92,7 +103,7 @@ module Fiddle
begin
snprintf_pointer = @libc[snprintf_name]
rescue Fiddle::DLError
- skip "Can't find #{snprintf_name}: #{$!.message}"
+ omit "Can't find #{snprintf_name}: #{$!.message}"
end
snprintf = Function.new(snprintf_pointer,
[
diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb
index df632925ad..847df3793a 100644
--- a/test/fiddle/test_function.rb
+++ b/test/fiddle/test_function.rb
@@ -15,6 +15,16 @@ module Fiddle
end
end
+ def teardown
+ # Ensure freeing all closures.
+ # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 .
+ not_freed_closures = []
+ ObjectSpace.each_object(Fiddle::Closure) do |closure|
+ not_freed_closures << closure unless closure.freed?
+ end
+ assert_equal([], not_freed_closures)
+ end
+
def test_default_abi
func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE)
assert_equal Function::DEFAULT, func.abi
@@ -75,18 +85,20 @@ module Fiddle
end
def test_argument_count
- closure = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call one
10 + one
end
- }.new(TYPE_INT, [TYPE_INT])
- func = Function.new(closure, [TYPE_INT], TYPE_INT)
-
- assert_raise(ArgumentError) do
- func.call(1,2,3)
end
- assert_raise(ArgumentError) do
- func.call
+ closure_class.create(TYPE_INT, [TYPE_INT]) do |closure|
+ func = Function.new(closure, [TYPE_INT], TYPE_INT)
+
+ assert_raise(ArgumentError) do
+ func.call(1,2,3)
+ end
+ assert_raise(ArgumentError) do
+ func.call
+ end
end
end
@@ -164,7 +176,7 @@ module Fiddle
begin
poll = @libc['poll']
rescue Fiddle::DLError
- skip 'poll(2) not available'
+ omit 'poll(2) not available'
end
f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT)
@@ -180,9 +192,37 @@ module Fiddle
end
def test_no_memory_leak
- 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)
+ if respond_to?(:assert_nothing_leaked_memory)
+ rb_obj_frozen_p_symbol = Fiddle.dlopen(nil)["rb_obj_frozen_p"]
+ rb_obj_frozen_p = Fiddle::Function.new(rb_obj_frozen_p_symbol,
+ [Fiddle::TYPE_UINTPTR_T],
+ Fiddle::TYPE_UINTPTR_T)
+ a = "a"
+ n_tries = 100_000
+ n_tries.times do
+ begin
+ a + 1
+ rescue TypeError
+ end
+ end
+ n_arguments = 1
+ sizeof_fiddle_generic = Fiddle::SIZEOF_VOIDP # Rough
+ size_per_try =
+ (sizeof_fiddle_generic * n_arguments) +
+ (Fiddle::SIZEOF_VOIDP * (n_arguments + 1))
+ assert_nothing_leaked_memory(size_per_try * n_tries) do
+ n_tries.times do
+ begin
+ rb_obj_frozen_p.call(a)
+ rescue TypeError
+ end
+ end
+ end
+ else
+ prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"'
+ code = 'begin r.call(a); rescue TypeError; end'
+ assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2)
+ end
end
private
diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb
index c0e85f7076..c19bcc6623 100644
--- a/test/fiddle/test_handle.rb
+++ b/test/fiddle/test_handle.rb
@@ -22,12 +22,14 @@ module Fiddle
def test_static_sym_unknown
assert_raise(DLError) { Fiddle::Handle.sym('fooo') }
assert_raise(DLError) { Fiddle::Handle['fooo'] }
+ refute Fiddle::Handle.sym_defined?('fooo')
end
def test_static_sym
begin
# Linux / Darwin / FreeBSD
refute_nil Fiddle::Handle.sym('dlopen')
+ assert Fiddle::Handle.sym_defined?('dlopen')
assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen']
return
rescue
@@ -54,6 +56,7 @@ module Fiddle
handle = Fiddle::Handle.new(LIBC_SO)
assert_raise(DLError) { handle.sym('fooo') }
assert_raise(DLError) { handle['fooo'] }
+ refute handle.sym_defined?('fooo')
end
def test_sym_with_bad_args
@@ -66,6 +69,7 @@ module Fiddle
handle = Handle.new(LIBC_SO)
refute_nil handle.sym('calloc')
refute_nil handle['calloc']
+ assert handle.sym_defined?('calloc')
end
def test_handle_close
@@ -185,7 +189,19 @@ module Fiddle
end if /freebsd/=~ RUBY_PLATFORM
def test_no_memory_leak
- assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true)
+ # https://github.com/ruby/fiddle/actions/runs/3202406059/jobs/5231356410
+ omit if RUBY_VERSION >= '3.2'
+
+ if respond_to?(:assert_nothing_leaked_memory)
+ n_tries = 100_000
+ assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do
+ n_tries.times do
+ Fiddle::Handle.allocate
+ end
+ end
+ else
+ assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true)
+ end
end
if /cygwin|mingw|mswin/ =~ RUBY_PLATFORM
diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb
index afa8df9e00..090ace620d 100644
--- a/test/fiddle/test_import.rb
+++ b/test/fiddle/test_import.rb
@@ -22,7 +22,6 @@ module Fiddle
extern "int fprintf(FILE*, char*)" rescue nil
extern "int gettimeofday(timeval*, timezone*)" rescue nil
- BoundQsortCallback = bind("void *bound_qsort_callback(void*, void*)"){|ptr1,ptr2| ptr1[0] <=> ptr2[0]}
Timeval = struct [
"long tv_sec",
"long tv_usec",
@@ -59,11 +58,6 @@ module Fiddle
]
}
]
-
- CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2|
- f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID)
- f.call(ptr2)
- }
end
class TestImport < TestCase
@@ -130,11 +124,28 @@ module Fiddle
name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase
type_name = name
end
+ type_name = "unsigned #{$1}" if type_name =~ /\Au(long|short|char|int|long long)\z/
+
define_method("test_sizeof_#{name}") do
assert_equal(size, Fiddle::Importer.sizeof(type_name), type)
end
end
+ # Assert that the unsigned constants are equal to the "negative" signed ones
+ # for backwards compatibility
+ def test_unsigned_equals_negative_signed
+ Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(U.*)/) do |unsigned|
+ assert_equal(-Fiddle.const_get(unsigned.to_s.sub(/U/, '')),
+ Fiddle.const_get(unsigned))
+ end
+ end
+
+ def test_type_constants
+ Fiddle::Types.constants.each do |const|
+ assert_equal Fiddle::Types.const_get(const), Fiddle.const_get("TYPE_#{const}")
+ end
+ end
+
def test_unsigned_result()
d = (2 ** 31) + 1
diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb
index 8130823fd6..240cda37df 100644
--- a/test/fiddle/test_memory_view.rb
+++ b/test/fiddle/test_memory_view.rb
@@ -14,7 +14,7 @@ end
module Fiddle
class TestMemoryView < TestCase
def setup
- skip "MemoryView is unavailable" unless defined? Fiddle::MemoryView
+ omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView
end
def test_null_ptr
@@ -49,7 +49,7 @@ module Fiddle
end
def test_memory_view_multi_dimensional
- skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+ omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
buf = [ 1, 2, 3, 4,
5, 6, 7, 8,
@@ -71,7 +71,7 @@ module Fiddle
end
def test_memory_view_multi_dimensional_with_strides
- skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+ omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*")
@@ -93,7 +93,7 @@ module Fiddle
end
def test_memory_view_multi_dimensional_with_multiple_members
- skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+ omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
-1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
diff --git a/test/fiddle/test_pack.rb b/test/fiddle/test_pack.rb
new file mode 100644
index 0000000000..ade1dd5040
--- /dev/null
+++ b/test/fiddle/test_pack.rb
@@ -0,0 +1,37 @@
+begin
+ require_relative 'helper'
+ require 'fiddle/pack'
+rescue LoadError
+ return
+end
+
+module Fiddle
+ class TestPack < TestCase
+ def test_pack_map
+ if defined?(TYPE_LONG_LONG)
+ assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG_LONG])
+ end
+
+ case Fiddle::SIZEOF_VOIDP
+ when 8
+ assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP])
+ when 4
+ assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP])
+ end
+
+ case Fiddle::SIZEOF_LONG
+ when 8
+ assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG])
+ when 4
+ assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG])
+ end
+
+ if Fiddle::SIZEOF_INT == 4
+ assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_INT]).unpack(PackInfo::PACK_MAP[-TYPE_INT])
+ end
+
+ assert_equal [0xffff], [0xffff].pack(PackInfo::PACK_MAP[-TYPE_SHORT]).unpack(PackInfo::PACK_MAP[-TYPE_SHORT])
+ assert_equal [0xff], [0xff].pack(PackInfo::PACK_MAP[-TYPE_CHAR]).unpack(PackInfo::PACK_MAP[-TYPE_CHAR])
+ end
+ end
+end
diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb
index 88dad75138..d6cba04bbe 100644
--- a/test/fiddle/test_pointer.rb
+++ b/test/fiddle/test_pointer.rb
@@ -179,16 +179,6 @@ module Fiddle
end
def test_free=
- assert_normal_exit(<<-"End", '[ruby-dev:39269]')
- require 'fiddle'
- include Fiddle
- free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
- ptr = Fiddle::Pointer.malloc(4)
- ptr.free = free
- free.ptr
- ptr.free.ptr
- End
-
free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
ptr = Pointer.malloc(4)
ptr.free = free
@@ -282,7 +272,19 @@ module Fiddle
end
def test_no_memory_leak
- assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true)
+ # https://github.com/ruby/fiddle/actions/runs/3202406059/jobs/5231356410
+ omit if RUBY_VERSION >= '3.2'
+
+ if respond_to?(:assert_nothing_leaked_memory)
+ n_tries = 100_000
+ assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do
+ n_tries.times do
+ Fiddle::Pointer.allocate
+ end
+ end
+ else
+ assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true)
+ end
end
end
end if defined?(Fiddle)
diff --git a/test/fileutils/clobber.rb b/test/fileutils/clobber.rb
index fdcecd5e08..ac5c8c79c0 100644
--- a/test/fileutils/clobber.rb
+++ b/test/fileutils/clobber.rb
@@ -4,10 +4,7 @@ require 'test/unit'
require 'tmpdir'
require_relative 'fileasserts'
-class TestFileUtils < Test::Unit::TestCase
-end
-
-module TestFileUtils::Clobber
+module TestFileUtilsClobber
include Test::Unit::FileAssertions
def my_rm_rf(path)
diff --git a/test/fileutils/test_dryrun.rb b/test/fileutils/test_dryrun.rb
index fd8a7805ec..a3efbb4bdf 100644
--- a/test/fileutils/test_dryrun.rb
+++ b/test/fileutils/test_dryrun.rb
@@ -8,7 +8,7 @@ require_relative 'visibility_tests'
class TestFileUtilsDryRun < Test::Unit::TestCase
include FileUtils::DryRun
- include TestFileUtilsInc::Visibility
+ include TestFileUtilsIncVisibility
def setup
super
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index 63936d1a05..3994da7433 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -242,7 +242,7 @@ class TestFileUtils < Test::Unit::TestCase
#
def test_assert_output_lines
- assert_raise(MiniTest::Assertion) {
+ assert_raise(Test::Unit::AssertionFailedError) {
Timeout.timeout(0.5) {
assert_output_lines([]) {
Thread.current.report_on_exception = false
@@ -317,7 +317,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_cp_preserve_permissions
bug4507 = '[ruby-core:35518]'
touch 'tmp/cptmp'
- chmod 0755, 'tmp/cptmp'
+ chmod 0o755, 'tmp/cptmp'
cp 'tmp/cptmp', 'tmp/cptmp2'
assert_equal_filemode('tmp/cptmp', 'tmp/cptmp2', bug4507, mask: ~File.umask)
@@ -327,9 +327,9 @@ class TestFileUtils < Test::Unit::TestCase
bug7246 = '[ruby-core:48603]'
mkdir 'tmp/cptmp'
mkdir 'tmp/cptmp/d1'
- chmod 0745, 'tmp/cptmp/d1'
+ chmod 0o745, 'tmp/cptmp/d1'
mkdir 'tmp/cptmp/d2'
- chmod 0700, 'tmp/cptmp/d2'
+ chmod 0o700, 'tmp/cptmp/d2'
cp_r 'tmp/cptmp', 'tmp/cptmp2', :preserve => true
assert_equal_filemode('tmp/cptmp/d1', 'tmp/cptmp2/d1', bug7246)
assert_equal_filemode('tmp/cptmp/d2', 'tmp/cptmp2/d2', bug7246)
@@ -472,10 +472,14 @@ class TestFileUtils < Test::Unit::TestCase
else
def test_cp_r_socket
pend "Skipping socket test on JRuby" if RUBY_ENGINE == 'jruby'
+
Dir.mkdir('tmp/cpr_src')
UNIXServer.new('tmp/cpr_src/socket').close
cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
assert_equal(true, File.socket?('tmp/cpr_dest/socket'))
+ rescue Errno::EINVAL => error
+ # On some platforms (windows) sockets cannot be copied by FileUtils.
+ omit error.message
end if defined?(UNIXServer)
end
@@ -750,6 +754,24 @@ class TestFileUtils < Test::Unit::TestCase
assert_file_not_exist 'tmp/tmpdir3'
end
+ def test_rm_r_no_permissions
+ check_singleton :rm_rf
+
+ return if /mswin|mingw/ =~ RUBY_PLATFORM
+
+ mkdir 'tmpdatadir'
+ touch 'tmpdatadir/tmpdata'
+ chmod "-x", 'tmpdatadir'
+
+ begin
+ assert_raise Errno::EACCES do
+ rm_r 'tmpdatadir'
+ end
+ ensure
+ chmod "+x", 'tmpdatadir'
+ end
+ end
+
def test_remove_entry_cjk_path
dir = "tmpdir\u3042"
my_rm_rf dir
@@ -823,7 +845,7 @@ class TestFileUtils < Test::Unit::TestCase
if File.sticky?('tmp/tmpdir')
Dir.mkdir 'tmp/tmpdir/d', 0
assert_raise(Errno::EACCES) {remove_entry_secure 'tmp/tmpdir/d'}
- File.chmod 0777, 'tmp/tmpdir/d'
+ File.chmod 0o777, 'tmp/tmpdir/d'
Dir.rmdir 'tmp/tmpdir/d'
end
end
@@ -980,6 +1002,43 @@ class TestFileUtils < Test::Unit::TestCase
}
end if have_symlink?
+ def test_ln_sr
+ check_singleton :ln_sr
+
+ TARGETS.each do |fname|
+ begin
+ lnfname = 'tmp/lnsdest'
+ ln_sr fname, lnfname
+ assert FileTest.symlink?(lnfname), 'not symlink'
+ assert_equal "../#{fname}", File.readlink(lnfname), fname
+ ensure
+ rm_f lnfname
+ end
+ end
+ mkdir 'data/src'
+ File.write('data/src/xxx', 'ok')
+ File.symlink '../data/src', 'tmp/src'
+ ln_sr 'tmp/src/xxx', 'data'
+ assert File.symlink?('data/xxx')
+ assert_equal 'ok', File.read('data/xxx')
+ end if have_symlink?
+
+ def test_ln_sr_broken_symlink
+ assert_nothing_raised {
+ ln_sr 'tmp/symlink', 'tmp/symlink'
+ }
+ end if have_symlink? and !no_broken_symlink?
+
+ def test_ln_sr_pathname
+ # pathname
+ touch 'tmp/lns_dest'
+ assert_nothing_raised {
+ ln_sr Pathname.new('tmp/lns_dest'), 'tmp/symlink_tmp1'
+ ln_sr 'tmp/lns_dest', Pathname.new('tmp/symlink_tmp2')
+ ln_sr Pathname.new('tmp/lns_dest'), Pathname.new('tmp/symlink_tmp3')
+ }
+ end if have_symlink?
+
def test_mkdir
check_singleton :mkdir
@@ -1098,6 +1157,14 @@ class TestFileUtils < Test::Unit::TestCase
ensure
Dir.rmdir(drive) if drive and File.directory?(drive)
end
+
+ def test_mkdir_p_offline_drive
+ offline_drive = ("A".."Z").to_a.reverse.find {|d| !File.exist?("#{d}:/") }
+
+ assert_raise(Errno::ENOENT) {
+ mkdir_p "#{offline_drive}:/new_dir"
+ }
+ end
end
def test_mkdir_p_file_perm
@@ -1227,9 +1294,9 @@ class TestFileUtils < Test::Unit::TestCase
check_singleton :chmod
touch 'tmp/a'
- chmod 0700, 'tmp/a'
+ chmod 0o700, 'tmp/a'
assert_filemode 0700, 'tmp/a'
- chmod 0500, 'tmp/a'
+ chmod 0o500, 'tmp/a'
assert_filemode 0500, 'tmp/a'
end if have_file_perm?
@@ -1333,9 +1400,9 @@ class TestFileUtils < Test::Unit::TestCase
assert_output_lines(["chmod 700 tmp/a", "chmod 500 tmp/a"]) {
touch 'tmp/a'
- chmod 0700, 'tmp/a', verbose: true
+ chmod 0o700, 'tmp/a', verbose: true
assert_filemode 0700, 'tmp/a', mask: 0777
- chmod 0500, 'tmp/a', verbose: true
+ chmod 0o500, 'tmp/a', verbose: true
assert_filemode 0500, 'tmp/a', mask: 0777
}
end if have_file_perm?
@@ -1343,7 +1410,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_s_chmod_verbose
assert_output_lines(["chmod 700 tmp/a"], FileUtils) {
touch 'tmp/a'
- FileUtils.chmod 0700, 'tmp/a', verbose: true
+ FileUtils.chmod 0o700, 'tmp/a', verbose: true
assert_filemode 0700, 'tmp/a', mask: 0777
}
end if have_file_perm?
@@ -1656,7 +1723,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_remove_file_file_perm
File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
- File.chmod 0, 'data/tmp'
+ File.chmod 0o000, 'data/tmp'
remove_file 'data/tmp'
assert_file_not_exist 'data/tmp'
end if have_file_perm?
@@ -1671,7 +1738,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_remove_dir_file_perm
Dir.mkdir 'data/tmpdir'
- File.chmod 0555, 'data/tmpdir'
+ File.chmod 0o555, 'data/tmpdir'
remove_dir 'data/tmpdir'
assert_file_not_exist 'data/tmpdir'
end if have_file_perm?
@@ -1790,7 +1857,7 @@ cd -
return if /mswin|mingw/ =~ RUBY_PLATFORM
mkdir 'tmpdatadir'
- chmod 700, 'tmpdatadir'
+ chmod 0o000, 'tmpdatadir'
rm_rf 'tmpdatadir'
assert_file_not_exist 'tmpdatadir'
diff --git a/test/fileutils/test_nowrite.rb b/test/fileutils/test_nowrite.rb
index 543fa39f5a..659fa20886 100644
--- a/test/fileutils/test_nowrite.rb
+++ b/test/fileutils/test_nowrite.rb
@@ -8,7 +8,7 @@ require_relative 'visibility_tests'
class TestFileUtilsNoWrite < Test::Unit::TestCase
include FileUtils::NoWrite
- include TestFileUtilsInc::Visibility
+ include TestFileUtilsIncVisibility
def setup
super
diff --git a/test/fileutils/test_verbose.rb b/test/fileutils/test_verbose.rb
index cf65be8e03..7987af2395 100644
--- a/test/fileutils/test_verbose.rb
+++ b/test/fileutils/test_verbose.rb
@@ -8,7 +8,7 @@ require_relative 'visibility_tests'
class TestFileUtilsVerbose < Test::Unit::TestCase
include FileUtils::Verbose
- include TestFileUtilsInc::Visibility
+ include TestFileUtilsIncVisibility
def setup
super
diff --git a/test/fileutils/visibility_tests.rb b/test/fileutils/visibility_tests.rb
index 4c02c9d207..9f8f8dc9e1 100644
--- a/test/fileutils/visibility_tests.rb
+++ b/test/fileutils/visibility_tests.rb
@@ -2,14 +2,11 @@
require 'test/unit'
require 'fileutils'
-class TestFileUtilsInc < Test::Unit::TestCase
-end
-
##
# These tests are reused in the FileUtils::Verbose, FileUtils::NoWrite and
# FileUtils::DryRun tests
-module TestFileUtilsInc::Visibility
+module TestFileUtilsIncVisibility
FileUtils::METHODS.each do |m|
define_method "test_singleton_visibility_#{m}" do
diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb
index 3d12b1f463..3f4b64bbcd 100644
--- a/test/io/console/test_io_console.rb
+++ b/test/io/console/test_io_console.rb
@@ -7,7 +7,13 @@ rescue LoadError
end
class TestIO_Console < Test::Unit::TestCase
- PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`}
+ begin
+ PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`}
+ rescue Encoding::CompatibilityError
+ $stderr.puts "test_io_console.rb debug"
+ $LOADED_FEATURES.each{|path| $stderr.puts [path, path.encoding].inspect}
+ raise
+ end
PATHS.uniq!
# FreeBSD seems to hang on TTOU when running parallel tests
@@ -43,6 +49,15 @@ class TestIO_Console < Test::Unit::TestCase
assert_include(e.message, IO::NULL)
end
end
+
+ def test_bad_keyword
+ omit if RUBY_ENGINE == 'jruby'
+ assert_raise_with_message(ArgumentError, /unknown keyword:.*bad/) do
+ File.open(IO::NULL) do |f|
+ f.raw(bad: 0)
+ end
+ end
+ end
end
defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
@@ -351,6 +366,15 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
end
def test_intr
+ # This test fails randomly on FreeBSD 13
+ # http://rubyci.s3.amazonaws.com/freebsd13/ruby-master/log/20220304T163001Z.fail.html.gz
+ #
+ # 1) Failure:
+ # TestIO_Console#test_intr [/usr/home/chkbuild/chkbuild/tmp/build/20220304T163001Z/ruby/test/io/console/test_io_console.rb:387]:
+ # <"25"> expected but was
+ # <"-e:12:in `p': \e[1mexecution expired (\e[1;4mTimeout::Error\e[m\e[1m)\e[m">.
+ omit if /freebsd/ =~ RUBY_PLATFORM
+
run_pty("#{<<~"begin;"}\n#{<<~'end;'}") do |r, w, _|
begin;
require 'timeout'
@@ -375,7 +399,7 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
if cc = ctrl["intr"]
assert_ctrl("#{cc.ord}", cc, r, w)
assert_ctrl("#{cc.ord}", cc, r, w)
- assert_ctrl("Interrupt", cc, r, w) unless /linux/ =~ RUBY_PLATFORM
+ assert_ctrl("Interrupt", cc, r, w) unless /linux|solaris/ =~ RUBY_PLATFORM
end
if cc = ctrl["dsusp"]
assert_ctrl("#{cc.ord}", cc, r, w)
@@ -401,6 +425,10 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
assert_equal(["true"], run_pty("IO.console(:close); p IO.console(:tty?)"))
end
+ def test_console_kw
+ assert_equal(["File"], run_pty("IO.console.close; p IO.console(:clone, freeze: true).class"))
+ end
+
def test_sync
assert_equal(["true"], run_pty("p IO.console.sync"))
end
@@ -421,7 +449,9 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
def run_pty(src, n = 1)
pend("PTY.spawn cannot control terminal on JRuby") if RUBY_ENGINE == 'jruby'
- r, w, pid = PTY.spawn(EnvUtil.rubybin, "-I#{TestIO_Console::PATHS.join(File::PATH_SEPARATOR)}", "-rio/console", "-e", src)
+ args = ["-I#{TestIO_Console::PATHS.join(File::PATH_SEPARATOR)}", "-rio/console", "-e", src]
+ args.shift if args.first == "-I" # statically linked
+ r, w, pid = PTY.spawn(EnvUtil.rubybin, *args)
rescue RuntimeError
omit $!
else
@@ -477,6 +507,12 @@ defined?(IO.console) and TestIO_Console.class_eval do
IO.console(:close)
end
+ def test_console_kw
+ io = IO.console(:clone, freeze: true)
+ io.close
+ assert_kind_of(IO, io)
+ end
+
def test_sync
assert(IO.console.sync, "console should be unbuffered")
ensure
diff --git a/test/io/nonblock/test_flush.rb b/test/io/nonblock/test_flush.rb
index 08d129de3f..447d761f18 100644
--- a/test/io/nonblock/test_flush.rb
+++ b/test/io/nonblock/test_flush.rb
@@ -15,7 +15,7 @@ class TestIONonblock < Test::Unit::TestCase
Socket.pair(:INET, :STREAM) {|s1, s2|
return if flush_test(s1, s2)
}
- skip "nonblocking IO did not work"
+ omit "nonblocking IO did not work"
end
def flush_test(r, w)
diff --git a/test/io/wait/test_io_wait.rb b/test/io/wait/test_io_wait.rb
index 6b4722e1be..7997a4814f 100644
--- a/test/io/wait/test_io_wait.rb
+++ b/test/io/wait/test_io_wait.rb
@@ -3,10 +3,9 @@
require 'test/unit'
require 'timeout'
require 'socket'
-begin
- require 'io/wait'
-rescue LoadError
-end
+
+# For `IO#ready?` and `IO#nread`:
+require 'io/wait'
class TestIOWait < Test::Unit::TestCase
@@ -50,6 +49,7 @@ class TestIOWait < Test::Unit::TestCase
end
def test_wait
+ omit 'unstable on MinGW' if /mingw/ =~ RUBY_PLATFORM
assert_nil @r.wait(0)
@w.syswrite "."
sleep 0.1
@@ -161,6 +161,34 @@ class TestIOWait < Test::Unit::TestCase
assert_equal @w, @w.wait(0.01, :read_write)
end
+ def test_wait_mask_writable
+ omit("Missing IO::WRITABLE!") unless IO.const_defined?(:WRITABLE)
+ assert_equal IO::WRITABLE, @w.wait(IO::WRITABLE, 0)
+ end
+
+ def test_wait_mask_readable
+ omit("Missing IO::READABLE!") unless IO.const_defined?(:READABLE)
+ @w.write("Hello World\n" * 3)
+ assert_equal IO::READABLE, @r.wait(IO::READABLE, 0)
+
+ @r.gets
+ assert_equal IO::READABLE, @r.wait(IO::READABLE, 0)
+ end
+
+ def test_wait_mask_zero
+ omit("Missing IO::WRITABLE!") unless IO.const_defined?(:WRITABLE)
+ assert_raise(ArgumentError) do
+ @w.wait(0, 0)
+ end
+ end
+
+ def test_wait_mask_negative
+ omit("Missing IO::WRITABLE!") unless IO.const_defined?(:WRITABLE)
+ assert_raise(ArgumentError) do
+ @w.wait(-6, 0)
+ end
+ end
+
private
def fill_pipe
diff --git a/test/io/wait/test_io_wait_uncommon.rb b/test/io/wait/test_io_wait_uncommon.rb
index b6f1c29bcd..0f922f4e24 100644
--- a/test/io/wait/test_io_wait_uncommon.rb
+++ b/test/io/wait/test_io_wait_uncommon.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'test/unit'
-require 'io/wait'
# test uncommon device types to check portability problems
# We may optimize IO#wait_*able for non-Linux kernels in the future
@@ -13,7 +12,7 @@ class TestIOWaitUncommon < Test::Unit::TestCase
end
def test_fifo_wait
- skip 'no mkfifo' unless File.respond_to?(:mkfifo) && IO.const_defined?(:NONBLOCK)
+ omit 'no mkfifo' unless File.respond_to?(:mkfifo) && IO.const_defined?(:NONBLOCK)
require 'tmpdir'
Dir.mktmpdir('rubytest-fifo') do |dir|
fifo = "#{dir}/fifo"
@@ -45,7 +44,7 @@ class TestIOWaitUncommon < Test::Unit::TestCase
rescue Errno::ENOENT
return # Ignore silently
rescue SystemCallError => e
- skip "#{dev} could not be opened #{e.message} (#{e.class})"
+ omit "#{dev} could not be opened #{e.message} (#{e.class})"
end
if block
yield fp
diff --git a/test/io/wait/test_ractor.rb b/test/io/wait/test_ractor.rb
index 3d286af77f..800216e610 100644
--- a/test/io/wait/test_ractor.rb
+++ b/test/io/wait/test_ractor.rb
@@ -1,13 +1,8 @@
# 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)}
@@ -19,4 +14,4 @@ class TestIOWaitInRactor < Test::Unit::TestCase
puts r.take
end;
end
-end
+end if defined? Ractor
diff --git a/test/irb/helper.rb b/test/irb/helper.rb
new file mode 100644
index 0000000000..e4ce7bff08
--- /dev/null
+++ b/test/irb/helper.rb
@@ -0,0 +1,76 @@
+require "test/unit"
+require "pathname"
+
+begin
+ require_relative "../lib/helper"
+rescue LoadError # ruby/ruby defines helpers differently
+end
+
+module IRB
+ class InputMethod; end
+end
+
+module TestIRB
+ class TestCase < 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 ruby_core?
+ !Pathname(__dir__).join("../../", "irb.gemspec").exist?
+ end
+
+ def save_encodings
+ @default_encoding = [Encoding.default_external, Encoding.default_internal]
+ @stdio_encodings = [STDIN, STDOUT, STDERR].map {|io| [io.external_encoding, io.internal_encoding] }
+ end
+
+ def restore_encodings
+ EnvUtil.suppress_warning do
+ Encoding.default_external, Encoding.default_internal = *@default_encoding
+ [STDIN, STDOUT, STDERR].zip(@stdio_encodings) do |io, encs|
+ io.set_encoding(*encs)
+ end
+ end
+ end
+
+ def without_rdoc(&block)
+ ::Kernel.send(:alias_method, :old_require, :require)
+
+ ::Kernel.define_method(:require) do |name|
+ raise LoadError, "cannot load such file -- rdoc (test)" if name.match?("rdoc") || name.match?(/^rdoc\/.*/)
+ ::Kernel.send(:old_require, name)
+ end
+
+ yield
+ ensure
+ begin
+ require_relative "../lib/envutil"
+ rescue LoadError # ruby/ruby defines EnvUtil differently
+ end
+ EnvUtil.suppress_warning { ::Kernel.send(:alias_method, :require, :old_require) }
+ end
+ end
+end
diff --git a/test/irb/test_cmd.rb b/test/irb/test_cmd.rb
index e6bb587b5c..719a2bbf8f 100644
--- a/test/irb/test_cmd.rb
+++ b/test/irb/test_cmd.rb
@@ -1,36 +1,29 @@
# frozen_string_literal: false
-require "test/unit"
+require "rubygems"
require "irb"
require "irb/extend-command"
-module TestIRB
- class ExtendCommand < Test::Unit::TestCase
- class TestInputMethod < ::IRB::InputMethod
- attr_reader :list, :line_no
-
- def initialize(list = [])
- super("test")
- @line_no = 0
- @list = list
- end
-
- def gets
- @list[@line_no]&.tap {@line_no += 1}
- end
-
- def eof?
- @line_no >= @list.size
- end
-
- def encoding
- Encoding.default_external
- end
+require_relative "helper"
- def reset
- @line_no = 0
+module TestIRB
+ class CommandTestCase < TestCase
+ def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
+ IRB.init_config(nil)
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
+ IRB.conf.merge!(conf)
+ input = TestInputMethod.new(lines)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
+ irb.context.return_format = "=> %s\n"
+ irb.context.irb_path = irb_path if irb_path
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ capture_output do
+ irb.eval_input
end
end
+ end
+ class ExtendCommandTest < CommandTestCase
def setup
@pwd = Dir.pwd
@tmpdir = File.join(Dir.tmpdir, "test_reline_config_#{$$}")
@@ -44,8 +37,7 @@ module TestIRB
@home_backup = ENV["HOME"]
ENV["HOME"] = @tmpdir
@xdg_config_home_backup = ENV.delete("XDG_CONFIG_HOME")
- @default_encoding = [Encoding.default_external, Encoding.default_internal]
- @stdio_encodings = [STDIN, STDOUT, STDERR].map {|io| [io.external_encoding, io.internal_encoding] }
+ save_encodings
IRB.instance_variable_get(:@CONF).clear
@is_win = (RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/)
end
@@ -55,299 +47,285 @@ module TestIRB
ENV["HOME"] = @home_backup
Dir.chdir(@pwd)
FileUtils.rm_rf(@tmpdir)
- EnvUtil.suppress_warning {
- Encoding.default_external, Encoding.default_internal = *@default_encoding
- [STDIN, STDOUT, STDERR].zip(@stdio_encodings) do |io, encs|
- io.set_encoding(*encs)
- end
- }
+ restore_encodings
end
- def test_irb_info_multiline
- FileUtils.touch("#{@tmpdir}/.inputrc")
- FileUtils.touch("#{@tmpdir}/.irbrc")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = true
- IRB.conf[:USE_SINGLELINE] = false
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- \.irbrc\spath:\s.+\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
+ class InfoCommandTest < ExtendCommandTest
+ def setup
+ super
+ @locals_backup = ENV.delete("LANG"), ENV.delete("LC_ALL")
+ end
- def test_irb_info_singleline
- FileUtils.touch("#{@tmpdir}/.inputrc")
- FileUtils.touch("#{@tmpdir}/.irbrc")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = false
- IRB.conf[:USE_SINGLELINE] = true
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- \.irbrc\spath:\s.+\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
+ def teardown
+ super
+ ENV["LANG"], ENV["LC_ALL"] = @locals_backup
+ end
- def test_irb_info_multiline_without_rc_files
- inputrc_backup = ENV["INPUTRC"]
- ENV["INPUTRC"] = "unknown_inpurc"
- ext_backup = IRB::IRBRC_EXT
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, "unknown_ext")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = true
- IRB.conf[:USE_SINGLELINE] = false
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- \z
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["INPUTRC"] = inputrc_backup
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, ext_backup)
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
+ def test_irb_info_multiline
+ FileUtils.touch("#{@tmpdir}/.inputrc")
+ FileUtils.touch("#{@tmpdir}/.irbrc")
- def test_irb_info_singleline_without_rc_files
- inputrc_backup = ENV["INPUTRC"]
- ENV["INPUTRC"] = "unknown_inpurc"
- ext_backup = IRB::IRBRC_EXT
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, "unknown_ext")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = false
- IRB.conf[:USE_SINGLELINE] = true
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- \z
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["INPUTRC"] = inputrc_backup
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, ext_backup)
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: true, USE_SINGLELINE: false }
+ )
- def test_irb_info_lang
- FileUtils.touch("#{@tmpdir}/.inputrc")
- FileUtils.touch("#{@tmpdir}/.irbrc")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = true
- IRB.conf[:USE_SINGLELINE] = false
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- ENV["LANG"] = "ja_JP.UTF-8"
- ENV["LC_ALL"] = "en_US.UTF-8"
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion: .+\n
- IRB\sversion:\sirb .+\n
- InputMethod:\sAbstract\sInputMethod\n
- \.irbrc\spath: .+\n
- RUBY_PLATFORM: .+\n
- LANG\senv:\sja_JP\.UTF-8\n
- LC_ALL\s env:\sen_US\.UTF-8\n
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ \.irbrc\spath:\s.+\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ end
+
+ def test_irb_info_singleline
+ FileUtils.touch("#{@tmpdir}/.inputrc")
+ FileUtils.touch("#{@tmpdir}/.irbrc")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: false, USE_SINGLELINE: true }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ \.irbrc\spath:\s.+\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ end
+
+ def test_irb_info_multiline_without_rc_files
+ inputrc_backup = ENV["INPUTRC"]
+ ENV["INPUTRC"] = "unknown_inpurc"
+ ext_backup = IRB::IRBRC_EXT
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, "unknown_ext")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: true, USE_SINGLELINE: false }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ ensure
+ ENV["INPUTRC"] = inputrc_backup
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, ext_backup)
+ end
+
+ def test_irb_info_singleline_without_rc_files
+ inputrc_backup = ENV["INPUTRC"]
+ ENV["INPUTRC"] = "unknown_inpurc"
+ ext_backup = IRB::IRBRC_EXT
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, "unknown_ext")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: false, USE_SINGLELINE: true }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ ensure
+ ENV["INPUTRC"] = inputrc_backup
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, ext_backup)
+ end
+
+ def test_irb_info_lang
+ FileUtils.touch("#{@tmpdir}/.inputrc")
+ FileUtils.touch("#{@tmpdir}/.irbrc")
+ ENV["LANG"] = "ja_JP.UTF-8"
+ ENV["LC_ALL"] = "en_US.UTF-8"
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: true, USE_SINGLELINE: false }
+ )
+
+ expected = %r{
+ Ruby\sversion: .+\n
+ IRB\sversion:\sirb .+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ \.irbrc\spath: .+\n
+ RUBY_PLATFORM: .+\n
+ LANG\senv:\sja_JP\.UTF-8\n
+ LC_ALL\senv:\sen_US\.UTF-8\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ end
end
def test_measure
- IRB.init_config(nil)
- IRB.conf[:PROMPT] = {
- DEFAULT: {
- PROMPT_I: '> ',
- PROMPT_S: '> ',
- PROMPT_C: '> ',
- PROMPT_N: '> '
- }
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false
}
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = false
- input = TestInputMethod.new([
+
+ c = Class.new(Object)
+ out, err = execute_lines(
"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
+ conf: conf,
+ main: c
+ )
+
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: '> '
- }
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: true
}
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = true
- input = TestInputMethod.new([
+
+ out, err = execute_lines(
"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
+ conf: conf,
+ )
+
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|
+ measuring_proc = 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([
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: true,
+ MEASURE_PROC: { CUSTOM: measuring_proc }
+ }
+
+ out, err = execute_lines(
"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
+ conf: conf,
+ )
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|
+ measuring_proc = 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([
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false,
+ MEASURE_PROC: { CUSTOM: measuring_proc }
+ }
+ out, err = execute_lines(
"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
+ conf: conf
+ )
+
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: '> '
- }
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false,
}
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = false
- input = TestInputMethod.new([
+ c = Class.new(Object)
+ out, err = execute_lines(
"3\n",
"measure { |context, code, line_no, &block|\n",
" result = block.()\n",
@@ -363,60 +341,49 @@ module TestIRB
"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
+ conf: conf,
+ main: c
+ )
+
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
+ out, err = execute_lines(
+ "a = 'bug17564'\n",
+ "a\n",
+ "irb_source '#{@tmpdir}/a.rb'\n",
+ "a\n",
+ )
assert_empty err
assert_pattern_list([
- /=> "bug17564"\n/,
- /=> "bug17564"\n/,
- / => "hi"\n/,
- / => nil\n/,
- /=> "hi"\n/,
- ], out)
+ /=> "bug17564"\n/,
+ /=> "bug17564"\n/,
+ / => "hi"\n/,
+ / => nil\n/,
+ /=> "hi"\n/,
+ ], out)
+ end
+
+ def test_irb_source_without_argument
+ out, err = execute_lines(
+ "irb_source\n",
+ )
+ assert_empty err
+ assert_match(/Please specify the file name./, 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
+ out, err = execute_lines(
+ "a = 'bug17564'\n",
+ "a\n",
+ "irb_load '#{@tmpdir}/a.rb'\n",
+ "a\n",
+ )
assert_empty err
assert_pattern_list([
/=> "bug17564"\n/,
@@ -427,8 +394,17 @@ module TestIRB
], out)
end
+ def test_irb_load_without_argument
+ out, err = execute_lines(
+ "irb_load\n",
+ )
+
+ assert_empty err
+ assert_match(/Please specify the file name./, out)
+ end
+
def test_ls
- input = TestInputMethod.new([
+ out, err = execute_lines(
"class P\n",
" def m() end\n",
" def m2() end\n",
@@ -454,16 +430,8 @@ module TestIRB
"obj.extend M2\n",
"def obj.m5() end\n",
"ls obj\n",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
+ )
+
assert_empty err
assert_match(/^instance variables:\s+@a\n/m, out)
assert_match(/P#methods:\s+m\n/m, out)
@@ -473,19 +441,48 @@ module TestIRB
assert_match(/C.methods:\s+m5\n/m, out)
end
+ def test_ls_grep
+ pend if RUBY_ENGINE == 'truffleruby'
+ out, err = execute_lines("ls 42\n")
+ assert_empty err
+ assert_match(/times/, out)
+ assert_match(/polar/, out)
+
+ [
+ "ls 42, grep: /times/\n",
+ "ls 42 -g times\n",
+ "ls 42 -G times\n",
+ ].each do |line|
+ out, err = execute_lines(line)
+ assert_empty err
+ assert_match(/times/, out)
+ assert_not_match(/polar/, out)
+ end
+ end
+
+ def test_ls_grep_empty
+ pend if RUBY_ENGINE == 'truffleruby'
+ out, err = execute_lines("ls\n")
+ assert_empty err
+ assert_match(/whereami/, out)
+ assert_match(/show_source/, out)
+
+ [
+ "ls grep: /whereami/\n",
+ "ls -g whereami\n",
+ "ls -G whereami\n",
+ ].each do |line|
+ out, err = execute_lines(line)
+ assert_empty err
+ assert_match(/whereami/, out)
+ assert_not_match(/show_source/, out)
+ end
+ end
+
def test_ls_with_no_singleton_class
- input = TestInputMethod.new([
+ out, err = execute_lines(
"ls 42",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
+ )
assert_empty err
assert_match(/Comparable#methods:\s+/, out)
assert_match(/Numeric#methods:\s+/, out)
@@ -493,37 +490,203 @@ module TestIRB
end
def test_show_source
- input = TestInputMethod.new([
+ out, err = execute_lines(
+ "show_source IRB.conf\n",
+ )
+ assert_empty err
+ assert_match(%r[/irb\.rb], out)
+ end
+
+ def test_show_source_method
+ out, err = execute_lines(
+ "p show_source('IRB.conf')\n",
+ )
+ assert_empty err
+ assert_match(%r[/irb\.rb], out)
+ end
+
+ def test_show_source_string
+ out, err = execute_lines(
"show_source 'IRB.conf'\n",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
+ )
assert_empty err
assert_match(%r[/irb\.rb], out)
end
+ def test_show_source_alias
+ out, err = execute_lines(
+ "$ 'IRB.conf'\n",
+ conf: { COMMAND_ALIASES: { :'$' => :show_source } }
+ )
+ assert_empty err
+ assert_match(%r[/irb\.rb], out)
+ end
+
+ def test_show_source_end_finder
+ pend if RUBY_ENGINE == 'truffleruby'
+ eval(code = <<-EOS, binding, __FILE__, __LINE__ + 1)
+ def show_source_test_method
+ unless true
+ end
+ end unless defined?(show_source_test_method)
+ EOS
+
+ out, err = execute_lines(
+ "show_source 'TestIRB::ExtendCommandTest#show_source_test_method'\n",
+ )
+
+ assert_empty err
+ assert_include(out, code)
+ end
+
def test_whereami
- input = TestInputMethod.new([
+ out, err = execute_lines(
"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
+
+ def test_whereami_alias
+ out, err = execute_lines(
+ "@\n",
+ )
assert_empty err
assert_match(/^From: .+ @ line \d+ :\n/, out)
end
+
+ def test_vars_with_aliases
+ @foo = "foo"
+ $bar = "bar"
+ out, err = execute_lines(
+ "@foo\n",
+ "$bar\n",
+ )
+ assert_empty err
+ assert_match(/"foo"/, out)
+ assert_match(/"bar"/, out)
+ ensure
+ remove_instance_variable(:@foo)
+ $bar = nil
+ end
+
+ def test_show_cmds
+ out, err = execute_lines(
+ "show_cmds\n"
+ )
+
+ assert_empty err
+ assert_match(/List all available commands and their description/, out)
+ assert_match(/Start the debugger of debug\.gem/, out)
+ end
+
+ class ShowDocTest < CommandTestCase
+ def test_help_and_show_doc
+ ["help", "show_doc"].each do |cmd|
+ out, _ = execute_lines(
+ "#{cmd} String#gsub\n",
+ "\n",
+ )
+
+ # the former is what we'd get without document content installed, like on CI
+ # the latter is what we may get locally
+ possible_rdoc_output = [/Nothing known about String#gsub/, /gsub\(pattern\)/]
+ assert(possible_rdoc_output.any? { |output| output.match?(out) }, "Expect the `#{cmd}` command to match one of the possible outputs. Got:\n#{out}")
+ end
+ ensure
+ # this is the only way to reset the redefined method without coupling the test with its implementation
+ EnvUtil.suppress_warning { load "irb/cmd/help.rb" }
+ end
+
+ def test_show_doc_without_rdoc
+ out, _ = without_rdoc do
+ execute_lines(
+ "show_doc String#gsub\n",
+ "\n",
+ )
+ end
+
+ # if it fails to require rdoc, it only returns the command object
+ assert_match(/=> IRB::ExtendCommand::Help\n/, out)
+ ensure
+ # this is the only way to reset the redefined method without coupling the test with its implementation
+ EnvUtil.suppress_warning { load "irb/cmd/help.rb" }
+ end
+ end
+
+ class EditTest < CommandTestCase
+ def setup
+ @original_editor = ENV["EDITOR"]
+ # noop the command so nothing gets executed
+ ENV["EDITOR"] = ": code"
+ end
+
+ def teardown
+ ENV["EDITOR"] = @original_editor
+ end
+
+ def test_edit_without_arg
+ out, err = execute_lines(
+ "edit",
+ irb_path: __FILE__
+ )
+
+ assert_empty err
+ assert_match("path: #{__FILE__}", out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_path
+ out, err = execute_lines(
+ "edit #{__FILE__}"
+ )
+
+ assert_empty err
+ assert_match("path: #{__FILE__}", out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_non_existing_path
+ out, err = execute_lines(
+ "edit test_cmd_non_existing_path.rb"
+ )
+
+ assert_empty err
+ assert_match(/Can not find file: test_cmd_non_existing_path\.rb/, out)
+ end
+
+ def test_edit_with_constant
+ # const_source_location is supported after Ruby 2.7
+ omit if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') || RUBY_ENGINE == 'truffleruby'
+
+ out, err = execute_lines(
+ "edit IRB::Irb"
+ )
+
+ assert_empty err
+ assert_match(/path: .*\/lib\/irb\.rb/, out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_class_method
+ out, err = execute_lines(
+ "edit IRB.start"
+ )
+
+ assert_empty err
+ assert_match(/path: .*\/lib\/irb\.rb/, out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_instance_method
+ out, err = execute_lines(
+ "edit IRB::Irb#run"
+ )
+
+ assert_empty err
+ assert_match(/path: .*\/lib\/irb\.rb/, out)
+ assert_match("command: ': code'", out)
+ end
+ end
end
end
diff --git a/test/irb/test_color.rb b/test/irb/test_color.rb
index ba99b1253f..1b27afb898 100644
--- a/test/irb/test_color.rb
+++ b/test/irb/test_color.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: false
-require 'test/unit'
require 'irb/color'
require 'rubygems'
require 'stringio'
+require_relative "helper"
+
module TestIRB
- class TestColor < Test::Unit::TestCase
+ class TestColor < TestCase
CLEAR = "\e[0m"
BOLD = "\e[1m"
UNDERLINE = "\e[4m"
@@ -88,6 +89,9 @@ module TestIRB
"foo(*%W(bar))" => "foo(*#{RED}#{BOLD}%W(#{CLEAR}#{RED}bar#{CLEAR}#{RED}#{BOLD})#{CLEAR})",
"$stdout" => "#{GREEN}#{BOLD}$stdout#{CLEAR}",
"__END__" => "#{GREEN}__END__#{CLEAR}",
+ "foo\n__END__\nbar" => "foo\n#{GREEN}__END__#{CLEAR}\nbar",
+ "foo\n<<A\0\0bar\nA\nbaz" => "foo\n#{RED}<<A#{CLEAR}^@^@bar\n#{RED}A#{CLEAR}\nbaz",
+ "<<A+1\nA" => "#{RED}<<A#{CLEAR}+#{BLUE}#{BOLD}1#{CLEAR}\n#{RED}A#{CLEAR}",
}
# specific to Ruby 2.7+
@@ -111,12 +115,24 @@ module TestIRB
"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}",
})
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.0')
+ tests.merge!({
+ "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}true#{CLEAR}#{RED}#{REVERSE})#{CLEAR} #{RED}#{REVERSE}end#{CLEAR}",
+ })
+ end
else
- tests.merge!({
- "[1]]]\u0013" => "[1]]]^S",
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
+ tests.merge!({
+ "[1]]]\u0013" => "[#{BLUE}#{BOLD}1#{CLEAR}]#{RED}#{REVERSE}]#{CLEAR}]^S",
+ "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}true#{CLEAR}) end",
})
+ else
+ tests.merge!({
+ "[1]]]\u0013" => "[#{BLUE}#{BOLD}1#{CLEAR}]]]^S",
+ "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{CYAN}#{BOLD}true#{CLEAR}) end",
+ })
+ end
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}",
@@ -125,29 +141,36 @@ module TestIRB
end
tests.each do |code, result|
- if colorize_code_supported?
- assert_equal_with_term(result, code, complete: true)
- assert_equal_with_term(result, code, complete: false)
+ assert_equal_with_term(result, code, complete: true)
+ assert_equal_with_term(result, code, complete: false)
- assert_equal_with_term(code, code, complete: true, tty: false)
- assert_equal_with_term(code, code, complete: false, tty: false)
+ assert_equal_with_term(code, code, complete: true, tty: false)
+ assert_equal_with_term(code, code, complete: false, tty: false)
- assert_equal_with_term(code, code, complete: true, colorable: false)
+ assert_equal_with_term(code, code, complete: true, colorable: false)
- assert_equal_with_term(code, code, complete: false, colorable: false)
+ assert_equal_with_term(code, code, complete: false, colorable: false)
- assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
+ assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
- assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
- else
- assert_equal_with_term(code, code)
- end
+ assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
end
end
+ def test_colorize_code_with_local_variables
+ code = "a /(b +1)/i"
+ result_without_lvars = "a #{RED}#{BOLD}/#{CLEAR}#{RED}(b +1)#{CLEAR}#{RED}#{BOLD}/i#{CLEAR}"
+ result_with_lvar = "a /(b #{BLUE}#{BOLD}+1#{CLEAR})/i"
+ result_with_lvars = "a /(b +#{BLUE}#{BOLD}1#{CLEAR})/i"
+
+ assert_equal_with_term(result_without_lvars, code)
+ assert_equal_with_term(result_with_lvar, code, local_variables: ['a'])
+ assert_equal_with_term(result_with_lvars, code, local_variables: ['a', 'b'])
+ end
+
def test_colorize_code_complete_true
unless complete_option_supported?
- skip '`complete: true` is the same as `complete: false` in Ruby 2.6-'
+ pend '`complete: true` is the same as `complete: false` in Ruby 2.6-'
end
# `complete: true` behaviors. Warn end-of-file.
@@ -171,26 +194,22 @@ module TestIRB
"'foo' + 'bar" => "#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}'#{CLEAR}#{RED}bar#{CLEAR}",
"('foo" => "(#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}",
}.each do |code, result|
- if colorize_code_supported?
- assert_equal_with_term(result, code, complete: false)
+ assert_equal_with_term(result, code, complete: false)
- assert_equal_with_term(code, code, complete: false, tty: false)
+ assert_equal_with_term(code, code, complete: false, tty: false)
- assert_equal_with_term(code, code, complete: false, colorable: false)
+ assert_equal_with_term(code, code, complete: false, colorable: false)
- assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
+ assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
- unless complete_option_supported?
- assert_equal_with_term(result, code, complete: true)
+ unless complete_option_supported?
+ assert_equal_with_term(result, code, complete: true)
- assert_equal_with_term(code, code, complete: true, tty: false)
+ assert_equal_with_term(code, code, complete: true, tty: false)
- assert_equal_with_term(code, code, complete: true, colorable: false)
+ assert_equal_with_term(code, code, complete: true, colorable: false)
- assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
- end
- else
- assert_equal_with_term(code, code)
+ assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
end
end
end
@@ -217,11 +236,6 @@ module TestIRB
private
- # `#colorize_code` is supported only for Ruby 2.5+. It just returns the original code in 2.4-.
- def colorize_code_supported?
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
- end
-
# `complete: true` is the same as `complete: false` in Ruby 2.6-
def complete_option_supported?
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
diff --git a/test/irb/test_color_printer.rb b/test/irb/test_color_printer.rb
index 1afc7ccf55..79ab050550 100644
--- a/test/irb/test_color_printer.rb
+++ b/test/irb/test_color_printer.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: false
-require 'test/unit'
require 'irb/color_printer'
require 'rubygems'
require 'stringio'
+require_relative "helper"
+
module TestIRB
- class TestColorPrinter < Test::Unit::TestCase
+ class TestColorPrinter < TestCase
CLEAR = "\e[0m"
BOLD = "\e[1m"
RED = "\e[31m"
@@ -30,7 +31,7 @@ module TestIRB
def test_color_printer
unless ripper_lexer_scan_supported?
- skip 'Ripper::Lexer#scan is supported in Ruby 2.7+'
+ pend 'Ripper::Lexer#scan is supported in Ruby 2.7+'
end
{
1 => "#{BLUE}#{BOLD}1#{CLEAR}\n",
diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb
index 535690ae22..1ab7dbbb19 100644
--- a/test/irb/test_completion.rb
+++ b/test/irb/test_completion.rb
@@ -1,9 +1,16 @@
# frozen_string_literal: false
-require "test/unit"
+require "pathname"
require "irb"
+require_relative "helper"
+
module TestIRB
- class TestCompletion < Test::Unit::TestCase
+ class TestCompletion < TestCase
+ def setup
+ # make sure require completion candidates are not cached
+ IRB::InputCompletor.class_variable_set(:@@files_from_load_path, nil)
+ end
+
def test_nonstring_module_name
begin
require "irb/completion"
@@ -17,23 +24,304 @@ module TestIRB
status = assert_in_out_err(cmds, "", //, [], bug5938)
assert(status.success?, bug5938)
rescue LoadError
- skip "cannot load irb/completion"
+ pend "cannot load irb/completion"
+ end
+ end
+
+ class TestMethodCompletion < TestCompletion
+ def test_complete_string
+ assert_include(IRB::InputCompletor.retrieve_completion_data("'foo'.up", bind: binding), "'foo'.upcase")
+ assert_equal("String.upcase", IRB::InputCompletor.retrieve_completion_data("'foo'.upcase", bind: binding, doc_namespace: true))
+ end
+
+ def test_complete_regexp
+ assert_include(IRB::InputCompletor.retrieve_completion_data("/foo/.ma", bind: binding), "/foo/.match")
+ assert_equal("Regexp.match", IRB::InputCompletor.retrieve_completion_data("/foo/.match", bind: binding, doc_namespace: true))
+ end
+
+ def test_complete_array
+ assert_include(IRB::InputCompletor.retrieve_completion_data("[].an", bind: binding), "[].any?")
+ assert_equal("Array.any?", IRB::InputCompletor.retrieve_completion_data("[].any?", bind: binding, doc_namespace: true))
+ end
+
+ def test_complete_hash_and_proc
+ # hash
+ assert_include(IRB::InputCompletor.retrieve_completion_data("{}.an", bind: binding), "{}.any?")
+ assert_equal(["Proc.any?", "Hash.any?"], IRB::InputCompletor.retrieve_completion_data("{}.any?", bind: binding, doc_namespace: true))
+
+ # proc
+ assert_include(IRB::InputCompletor.retrieve_completion_data("{}.bin", bind: binding), "{}.binding")
+ assert_equal(["Proc.binding", "Hash.binding"], IRB::InputCompletor.retrieve_completion_data("{}.binding", bind: binding, doc_namespace: true))
+ end
+
+ def test_complete_numeric
+ assert_include(IRB::InputCompletor.retrieve_completion_data("1.positi", bind: binding), "1.positive?")
+ assert_equal("Integer.positive?", IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true))
+
+ assert_include(IRB::InputCompletor.retrieve_completion_data("1r.positi", bind: binding), "1r.positive?")
+ assert_equal("Rational.positive?", IRB::InputCompletor.retrieve_completion_data("1r.positive?", bind: binding, doc_namespace: true))
+
+ assert_include(IRB::InputCompletor.retrieve_completion_data("0xFFFF.positi", bind: binding), "0xFFFF.positive?")
+ assert_equal("Integer.positive?", IRB::InputCompletor.retrieve_completion_data("0xFFFF.positive?", bind: binding, doc_namespace: true))
+
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("1i.positi", bind: binding))
+ end
+
+ def test_complete_symbol
+ assert_include(IRB::InputCompletor.retrieve_completion_data(":foo.to_p", bind: binding), ":foo.to_proc")
+ assert_equal("Symbol.to_proc", IRB::InputCompletor.retrieve_completion_data(":foo.to_proc", bind: binding, doc_namespace: true))
+ end
+
+ def test_complete_class
+ assert_include(IRB::InputCompletor.retrieve_completion_data("String.ne", bind: binding), "String.new")
+ assert_equal("String.new", IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true))
+ end
+ end
+
+ class TestRequireComepletion < TestCompletion
+ 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_with_pathname_in_load_path
+ temp_dir = Dir.mktmpdir
+ File.write(File.join(temp_dir, "foo.rb"), "test")
+ test_path = Pathname.new(temp_dir)
+ $LOAD_PATH << test_path
+
+ candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
+ assert_include candidates, "'foo"
+ ensure
+ $LOAD_PATH.pop if test_path
+ FileUtils.remove_entry(temp_dir) if temp_dir
+ end
+
+ def test_complete_require_with_string_convertable_in_load_path
+ temp_dir = Dir.mktmpdir
+ File.write(File.join(temp_dir, "foo.rb"), "test")
+ object = Object.new
+ object.define_singleton_method(:to_s) { temp_dir }
+ $LOAD_PATH << object
+
+ candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
+ assert_include candidates, "'foo"
+ ensure
+ $LOAD_PATH.pop if object
+ FileUtils.remove_entry(temp_dir) if temp_dir
+ end
+
+ def test_complete_require_with_malformed_object_in_load_path
+ object = Object.new
+ def object.to_s; raise; end
+ $LOAD_PATH << object
+
+ assert_nothing_raised do
+ IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
+ end
+ ensure
+ $LOAD_PATH.pop if object
+ end
+
+ def test_complete_require_library_name_first
+ pend 'Need to use virtual library paths'
+ candidates = IRB::InputCompletor::CompletionProc.("'csv", "require ", "")
+ assert_equal "'csv", candidates.first
+ end
+
+ def test_complete_require_relative
+ candidates = Dir.chdir(__dir__ + "/../..") do
+ IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
+ end
+ %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ # Test cache
+ candidates = Dir.chdir(__dir__ + "/../..") do
+ IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
+ end
+ %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
end
end
- def test_complete_numeric
- assert_include(IRB::InputCompletor.retrieve_completion_data("1r.positi", bind: binding), "1r.positive?")
- assert_empty(IRB::InputCompletor.retrieve_completion_data("1i.positi", bind: binding))
+ class TestVariableCompletion < TestCompletion
+ def test_complete_variable
+ # Bug fix issues https://github.com/ruby/irb/issues/368
+ # Variables other than `str_example` and `@str_example` are defined to ensure that irb completion does not cause unintended behavior
+ str_example = ''
+ @str_example = ''
+ private_methods = ''
+ methods = ''
+ global_variables = ''
+ local_variables = ''
+ instance_variables = ''
+
+ # suppress "assigned but unused variable" warning
+ str_example.clear
+ @str_example.clear
+ private_methods.clear
+ methods.clear
+ global_variables.clear
+ local_variables.clear
+ instance_variables.clear
+
+ assert_include(IRB::InputCompletor.retrieve_completion_data("str_examp", bind: binding), "str_example")
+ assert_equal("String", IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true))
+ assert_equal("String.to_s", IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true))
+
+ assert_include(IRB::InputCompletor.retrieve_completion_data("@str_examp", bind: binding), "@str_example")
+ assert_equal("String", IRB::InputCompletor.retrieve_completion_data("@str_example", bind: binding, doc_namespace: true))
+ assert_equal("String.to_s", IRB::InputCompletor.retrieve_completion_data("@str_example.to_s", bind: binding, doc_namespace: true))
+ end
+
+ def test_complete_sort_variables
+ xzy, xzy_1, xzy2 = '', '', ''
+
+ xzy.clear
+ xzy_1.clear
+ xzy2.clear
+
+ candidates = IRB::InputCompletor.retrieve_completion_data("xz", bind: binding, doc_namespace: false)
+ assert_equal(%w[xzy xzy2 xzy_1], candidates)
+ end
+ end
+
+ class TestConstantCompletion < TestCompletion
+ class Foo
+ B3 = 1
+ B1 = 1
+ B2 = 1
+ end
+
+ def test_complete_constants
+ assert_equal(["Foo"], IRB::InputCompletor.retrieve_completion_data("Fo", bind: binding))
+ assert_equal(["Foo::B1", "Foo::B2", "Foo::B3"], IRB::InputCompletor.retrieve_completion_data("Foo::B", bind: binding))
+ assert_equal(["Foo::B1.positive?"], IRB::InputCompletor.retrieve_completion_data("Foo::B1.pos", bind: binding))
+
+ assert_equal(["::Forwardable"], IRB::InputCompletor.retrieve_completion_data("::Fo", bind: binding))
+ assert_equal("Forwardable", IRB::InputCompletor.retrieve_completion_data("::Forwardable", bind: binding, doc_namespace: true))
+ end
+ end
+
+ class TestPerfectMatching < TestCompletion
+ def setup
+ # trigger PerfectMatchedProc to set up RDocRIDriver constant
+ IRB::InputCompletor::PerfectMatchedProc.("foo", bind: binding)
+
+ @original_use_stdout = IRB::InputCompletor::RDocRIDriver.use_stdout
+ # force the driver to use stdout so it doesn't start a pager and interrupt tests
+ IRB::InputCompletor::RDocRIDriver.use_stdout = true
+ end
+
+ def teardown
+ IRB::InputCompletor::RDocRIDriver.use_stdout = @original_use_stdout
+ end
+
+ def test_perfectly_matched_namespace_triggers_document_display
+ omit unless has_rdoc_content?
+
+ out, err = capture_output do
+ IRB::InputCompletor::PerfectMatchedProc.("String", bind: binding)
+ end
+
+ assert_empty(err)
+
+ assert_include(out, " S\bSt\btr\bri\bin\bng\bg")
+ end
+
+ def test_perfectly_matched_multiple_namespaces_triggers_document_display
+ result = nil
+ out, err = capture_output do
+ result = IRB::InputCompletor::PerfectMatchedProc.("{}.nil?", bind: binding)
+ end
+
+ assert_empty(err)
+
+ # check if there're rdoc contents (e.g. CI doesn't generate them)
+ if has_rdoc_content?
+ # if there's rdoc content, we can verify by checking stdout
+ # rdoc generates control characters for formatting method names
+ assert_include(out, "P\bPr\bro\boc\bc.\b.n\bni\bil\bl?\b?") # Proc.nil?
+ assert_include(out, "H\bHa\bas\bsh\bh.\b.n\bni\bil\bl?\b?") # Hash.nil?
+ else
+ # this is a hacky way to verify the rdoc rendering code path because CI doesn't have rdoc content
+ # if there are multiple namespaces to be rendered, PerfectMatchedProc renders the result with a document
+ # which always returns the bytes rendered, even if it's 0
+ assert_equal(0, result)
+ end
+ end
+
+ def test_not_matched_namespace_triggers_nothing
+ result = nil
+ out, err = capture_output do
+ result = IRB::InputCompletor::PerfectMatchedProc.("Stri", bind: binding)
+ end
+
+ assert_empty(err)
+ assert_empty(out)
+ assert_nil(result)
+ end
+
+ def test_perfect_matching_stops_without_rdoc
+ result = nil
+
+ out, err = capture_output do
+ without_rdoc do
+ result = IRB::InputCompletor::PerfectMatchedProc.("String", bind: binding)
+ end
+ end
+
+ assert_empty(err)
+ assert_not_match(/from ruby core/, out)
+ assert_nil(result)
+ end
+
+ def test_perfect_matching_handles_nil_namespace
+ out, err = capture_output do
+ # symbol literal has `nil` doc namespace so it's a good test subject
+ assert_nil(IRB::InputCompletor::PerfectMatchedProc.(":aiueo", bind: binding))
+ end
+
+ assert_empty(err)
+ assert_empty(out)
+ end
+
+ private
+
+ def has_rdoc_content?
+ File.exist?(RDoc::RI::Paths::BASE)
+ end
end
def test_complete_symbol
+ %w"UTF-16LE UTF-7".each do |enc|
+ "K".force_encoding(enc).to_sym
+ rescue
+ end
_ = :aiueo
assert_include(IRB::InputCompletor.retrieve_completion_data(":a", bind: binding), ":aiueo")
assert_empty(IRB::InputCompletor.retrieve_completion_data(":irb_unknown_symbol_abcdefg", bind: binding))
end
- def test_complete_symbol_failure
- assert_nil(IRB::InputCompletor::PerfectMatchedProc.(":aiueo", bind: binding))
+ def test_complete_invalid_three_colons
+ assert_empty(IRB::InputCompletor.retrieve_completion_data(":::A", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data(":::", bind: binding))
+ end
+
+ def test_complete_absolute_constants_with_special_characters
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A:", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A.", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A(", bind: binding))
+ assert_empty(IRB::InputCompletor.retrieve_completion_data("::A)", bind: binding))
end
def test_complete_reserved_words
@@ -48,40 +336,28 @@ module TestIRB
end
end
- def test_complete_predicate?
- candidates = IRB::InputCompletor.retrieve_completion_data("1.posi", bind: binding)
- assert_include candidates, '1.positive?'
+ def test_complete_methods
+ obj = Object.new
+ obj.singleton_class.class_eval {
+ def public_hoge; end
+ private def private_hoge; end
- namespace = IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true)
- assert_equal "Integer.positive?", namespace
- end
+ # Support for overriding #methods etc.
+ def methods; end
+ def private_methods; end
+ def global_variables; end
+ def local_variables; end
+ def instance_variables; end
+ }
+ bind = obj.instance_exec { binding }
- 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
+ assert_include(IRB::InputCompletor.retrieve_completion_data("public_hog", bind: bind), "public_hoge")
+ assert_include(IRB::InputCompletor.retrieve_completion_data("public_hoge.to_s", bind: bind), "public_hoge.to_s")
+ assert_include(IRB::InputCompletor.retrieve_completion_data("public_hoge", bind: bind, doc_namespace: true), "public_hoge")
- 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
+ assert_include(IRB::InputCompletor.retrieve_completion_data("private_hog", bind: bind), "private_hoge")
+ assert_include(IRB::InputCompletor.retrieve_completion_data("private_hoge.to_s", bind: bind), "private_hoge.to_s")
+ assert_include(IRB::InputCompletor.retrieve_completion_data("private_hoge", bind: bind, doc_namespace: true), "private_hoge")
end
end
end
diff --git a/test/irb/test_context.rb b/test/irb/test_context.rb
index 71e8ad1c0d..4d256a73a2 100644
--- a/test/irb/test_context.rb
+++ b/test/irb/test_context.rb
@@ -1,41 +1,12 @@
# frozen_string_literal: false
-require 'test/unit'
require 'tempfile'
require 'irb'
require 'rubygems' if defined?(Gem)
-module TestIRB
- class TestContext < 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
-
- def winsize
- [10, 20]
- end
- end
+require_relative "helper"
+module TestIRB
+ class TestContext < TestCase
def setup
IRB.init_config(nil)
IRB.conf[:USE_SINGLELINE] = false
@@ -79,7 +50,7 @@ module TestIRB
end
def test_evaluate_with_encoding_error_without_lineno
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
assert_raise_with_message(EncodingError, /invalid symbol/) {
@context.evaluate(%q[{"\xAE": 1}], 1)
# The backtrace of this invalid encoding hash doesn't contain lineno.
@@ -87,14 +58,14 @@ module TestIRB
end
def test_evaluate_with_onigmo_warning
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
assert_warning("(irb):1: warning: character class has duplicated range: /[aa]/\n") do
@context.evaluate('/[aa]/', 1)
end
end
def test_eval_input
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
"raise 'Foo'\n",
@@ -117,7 +88,7 @@ module TestIRB
end
def test_eval_input_raise2x
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
input = TestInputMethod.new([
"raise 'Foo'\n",
"raise 'Bar'\n",
@@ -135,30 +106,55 @@ module TestIRB
], 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)
+ def test_output_to_pipe
+ require 'stringio'
+ input = TestInputMethod.new(["n=1"])
+ input.instance_variable_set(:@stdout, StringIO.new)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.echo_on_assignment = :truncate
+ irb.context.prompt_mode = :DEFAULT
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal "=> 1\n", out
+ end
+
+ {
+ successful: [
+ [false, "class Foo < Struct.new(:bar); end; Foo.new(123)\n", /#<struct bar=123>/],
+ [:p, "class Foo < Struct.new(:bar); end; Foo.new(123)\n", /#<struct bar=123>/],
+ [true, "class Foo < Struct.new(:bar); end; Foo.new(123)\n", /#<struct #<Class:.*>::Foo bar=123>/],
+ [:yaml, "123", /--- 123\n/],
+ [:marshal, "123", Marshal.dump(123)],
+ ],
+ failed: [
+ [false, "BasicObject.new", /\(Object doesn't support #inspect\)\n(=> )?\n/],
+ [:p, "class Foo; undef inspect ;end; Foo.new", /\(Object doesn't support #inspect\)\n(=> )?\n/],
+ [true, "BasicObject.new", /\(Object doesn't support #inspect\)\n(=> )?\n/],
+ [:yaml, "BasicObject.new", /\(Object doesn't support #inspect\)\n(=> )?\n/],
+ [:marshal, "[Object.new, Class.new]", /\(Object doesn't support #inspect\)\n(=> )?\n/]
+ ]
+ }.each do |scenario, cases|
+ cases.each do |inspect_mode, input, expected|
+ define_method "test_#{inspect_mode}_inspect_mode_#{scenario}" do
+ pend if RUBY_ENGINE == 'truffleruby'
+ verbose, $VERBOSE = $VERBOSE, nil
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), TestInputMethod.new([input]))
+ irb.context.inspect_mode = inspect_mode
+ out, err = capture_output do
+ irb.eval_input
end
+ assert_empty err
+ assert_match(expected, out)
+ ensure
+ $VERBOSE = verbose
end
end
- ensure
- $VERBOSE = verbose
end
def test_default_config
- assert_equal(true, @context.use_colorize?)
+ assert_equal(true, @context.use_autocomplete?)
end
def test_assignment_expression
@@ -204,6 +200,16 @@ module TestIRB
end
end
+ def test_assignment_expression_with_local_variable
+ input = TestInputMethod.new
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ code = "a /1;x=1#/"
+ refute(irb.assignment_expression?(code), "#{code}: should not be an assignment expression")
+ irb.context.workspace.binding.eval('a = 1')
+ assert(irb.assignment_expression?(code), "#{code}: should be an assignment expression")
+ refute(irb.assignment_expression?(""), "empty code should not be an assignment expression")
+ end
+
def test_echo_on_assignment
input = TestInputMethod.new([
"a = 1\n",
@@ -220,7 +226,7 @@ module TestIRB
# The default
irb.context.echo = true
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -230,7 +236,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -240,7 +246,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -250,7 +256,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -268,7 +274,7 @@ module TestIRB
irb.context.echo = true
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -277,7 +283,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -286,7 +292,7 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -295,7 +301,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -304,7 +310,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -313,7 +319,7 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- out, err = capture_io do
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
@@ -321,99 +327,103 @@ module TestIRB
end
def test_omit_multiline_on_assignment
- input = TestInputMethod.new([
- "class A; def inspect; ([?* * 1000] * 3).join(%{\\n}); end; end; a = A.new\n",
- "a\n"
- ])
- value = ([?* * 1000] * 3).join(%{\n})
- value_first_line = (?* * 1000).to_s
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- irb.context.return_format = "=> %s\n"
-
- irb.context.echo = true
- irb.context.echo_on_assignment = false
- out, err = capture_io do
- irb.eval_input
- end
- assert_empty err
- assert_equal("=> \n#{value}\n", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = true
- irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
- irb.eval_input
- end
- assert_empty err
- assert_equal("=> #{value_first_line[0..(input.winsize.last - 9)]}...\e[0m\n=> \n#{value}\n", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = true
- irb.context.echo_on_assignment = true
- out, err = capture_io do
- irb.eval_input
- end
- assert_empty err
- assert_equal("=> \n#{value}\n=> \n#{value}\n", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = false
- irb.context.echo_on_assignment = false
- out, err = capture_io do
- irb.eval_input
- end
- assert_empty err
- assert_equal("", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = false
- irb.context.echo_on_assignment = :truncate
- out, err = capture_io do
- irb.eval_input
- end
- assert_empty err
- assert_equal("", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = false
- irb.context.echo_on_assignment = true
- out, err = capture_io do
- irb.eval_input
+ without_colorize do
+ input = TestInputMethod.new([
+ "class A; def inspect; ([?* * 1000] * 3).join(%{\\n}); end; end; a = A.new\n",
+ "a\n"
+ ])
+ value = ([?* * 1000] * 3).join(%{\n})
+ value_first_line = (?* * 1000).to_s
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.return_format = "=> %s\n"
+
+ irb.context.echo = true
+ irb.context.echo_on_assignment = false
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> \n#{value}\n", out)
+ irb.context.evaluate('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = true
+ irb.context.echo_on_assignment = :truncate
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> #{value_first_line[0..(input.winsize.last - 9)]}...\n=> \n#{value}\n", out)
+ irb.context.evaluate('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = true
+ irb.context.echo_on_assignment = true
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> \n#{value}\n=> \n#{value}\n", out)
+ irb.context.evaluate('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = false
+ irb.context.echo_on_assignment = false
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("", out)
+ irb.context.evaluate('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = false
+ irb.context.echo_on_assignment = :truncate
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("", out)
+ irb.context.evaluate('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = false
+ irb.context.echo_on_assignment = true
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("", out)
+ irb.context.evaluate('A.remove_method(:inspect)', 0)
end
- assert_empty err
- assert_equal("", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
end
def test_echo_on_assignment_conf
# Default
IRB.conf[:ECHO] = nil
IRB.conf[:ECHO_ON_ASSIGNMENT] = nil
- input = TestInputMethod.new()
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ without_colorize do
+ input = TestInputMethod.new()
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- assert(irb.context.echo?, "echo? should be true by default")
- assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
+ assert(irb.context.echo?, "echo? 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)
+ # 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_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
+ refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
+ 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 = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ # Explicitly set :ECHO_ON_ASSIGNMENT to true
+ IRB.conf[:ECHO] = nil
+ IRB.conf[:ECHO_ON_ASSIGNMENT] = false
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- assert(irb.context.echo?, "echo? should be true by default")
- refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false")
+ 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")
+ end
end
def test_multiline_output_on_default_inspector
@@ -421,34 +431,58 @@ module TestIRB
def main.inspect
"abc\ndef"
end
- input = TestInputMethod.new([
- "self"
- ])
- irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
- irb.context.return_format = "=> %s\n"
- # The default
- irb.context.newline_before_multiline_output = true
- out, err = capture_io do
- irb.eval_input
+ without_colorize do
+ input = TestInputMethod.new([
+ "self"
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
+ irb.context.return_format = "=> %s\n"
+
+ # The default
+ irb.context.newline_before_multiline_output = true
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> \nabc\ndef\n",
+ out)
+
+ # No newline before multiline output
+ input.reset
+ irb.context.newline_before_multiline_output = false
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> abc\ndef\n", out)
end
- assert_empty err
- assert_equal("=> \nabc\ndef\n",
- out)
+ end
- # No newline before multiline output
- input.reset
- irb.context.newline_before_multiline_output = false
- out, err = capture_io do
+ def test_default_return_format
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_N => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ # without :RETURN
+ # :RETURN => "%s\n"
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ input = TestInputMethod.new([
+ "3"
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ out, err = capture_output do
irb.eval_input
end
assert_empty err
- assert_equal("=> abc\ndef\n",
+ assert_equal("3\n",
out)
end
def test_eval_input_with_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
"def hoge() fuga; end; def fuga() raise; end; hoge\n",
@@ -458,7 +492,7 @@ module TestIRB
irb.eval_input
end
assert_empty err
- if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ if RUBY_VERSION < '3.0.0' && STDOUT.tty?
expected = [
:*, /Traceback \(most recent call last\):\n/,
:*, /\t 2: from \(irb\):1:in `<main>'\n/,
@@ -470,6 +504,7 @@ module TestIRB
:*, /\(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)
@@ -478,7 +513,7 @@ module TestIRB
end
def test_eval_input_with_invalid_byte_sequence_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
%Q{def hoge() fuga; end; def fuga() raise "A\\xF3B"; end; hoge\n},
@@ -488,7 +523,7 @@ module TestIRB
irb.eval_input
end
assert_empty err
- if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ if RUBY_VERSION < '3.0.0' && STDOUT.tty?
expected = [
:*, /Traceback \(most recent call last\):\n/,
:*, /\t 2: from \(irb\):1:in `<main>'\n/,
@@ -500,6 +535,7 @@ module TestIRB
:*, /\(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)
@@ -508,7 +544,7 @@ module TestIRB
end
def test_eval_input_with_long_exception
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
nesting = 20
generated_code = ''
@@ -524,10 +560,10 @@ module TestIRB
irb.eval_input
end
assert_empty err
- if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ if RUBY_VERSION < '3.0.0' && STDOUT.tty?
expected = [
:*, /Traceback \(most recent call last\):\n/,
- :*, /\t... 5 levels...\n/,
+ :*, /\t... \d+ levels...\n/,
:*, /\t16: from \(irb\):1:in `a4'\n/,
:*, /\t15: from \(irb\):1:in `a5'\n/,
:*, /\t14: from \(irb\):1:in `a6'\n/,
@@ -565,7 +601,7 @@ module TestIRB
:*, /\tfrom \(irb\):1:in `a6'\n/,
:*, /\tfrom \(irb\):1:in `a5'\n/,
:*, /\tfrom \(irb\):1:in `a4'\n/,
- :*, /\t... 5 levels...\n/,
+ :*, /\t... \d+ levels...\n/,
]
end
assert_pattern_list(expected, out)
@@ -593,5 +629,15 @@ module TestIRB
:*, /\b6\n/,
], out)
end
+
+ private
+
+ def without_colorize
+ original_value = IRB.conf[:USE_COLORIZE]
+ IRB.conf[:USE_COLORIZE] = false
+ yield
+ ensure
+ IRB.conf[:USE_COLORIZE] = original_value
+ end
end
end
diff --git a/test/irb/test_debug_cmd.rb b/test/irb/test_debug_cmd.rb
new file mode 100644
index 0000000000..4d1bb6d6b9
--- /dev/null
+++ b/test/irb/test_debug_cmd.rb
@@ -0,0 +1,303 @@
+# frozen_string_literal: true
+
+begin
+ require "pty"
+rescue LoadError
+ return
+end
+
+require "tempfile"
+require "tmpdir"
+require "envutil"
+
+require_relative "helper"
+
+module TestIRB
+ LIB = File.expand_path("../../lib", __dir__)
+
+ class DebugCommandTestCase < TestCase
+ IRB_AND_DEBUGGER_OPTIONS = {
+ "RUBY_DEBUG_NO_RELINE" => "true", "NO_COLOR" => "true", "RUBY_DEBUG_HISTORY_FILE" => ''
+ }
+
+ def setup
+ if ruby_core?
+ omit "This test works only under ruby/irb"
+ end
+
+ if RUBY_ENGINE == 'truffleruby'
+ omit "This test runs with ruby/debug, which doesn't work with truffleruby"
+ end
+ end
+
+ def test_backtrace
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ end
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "backtrace"
+ type "q!"
+ end
+
+ assert_match(/\(rdbg:irb\) backtrace/, output)
+ assert_match(/Object#foo at #{@ruby_file.to_path}/, output)
+ end
+
+ def test_debug
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "hello"
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type "next"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg\) next/, output)
+ assert_match(/=> 2\| puts "hello"/, output)
+ end
+
+ def test_next
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "hello"
+ ruby
+
+ output = run_ruby_file do
+ type "next"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) next/, output)
+ assert_match(/=> 2\| puts "hello"/, output)
+ end
+
+ def test_break
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "Hello"
+ RUBY
+
+ output = run_ruby_file do
+ type "break 2"
+ type "continue"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) break/, output)
+ assert_match(/=> 2\| puts "Hello"/, output)
+ end
+
+ def test_delete
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "Hello"
+ binding.irb
+ puts "World"
+ RUBY
+
+ output = run_ruby_file do
+ type "break 4"
+ type "continue"
+ type "delete 0"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) delete/, output)
+ assert_match(/deleted: #0 BP - Line/, output)
+ end
+
+ def test_step
+ write_ruby <<~'RUBY'
+ def foo
+ puts "Hello"
+ end
+ binding.irb
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "step"
+ type "step"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) step/, output)
+ assert_match(/=> 5\| foo/, output)
+ assert_match(/=> 2\| puts "Hello"/, output)
+ end
+
+ def test_continue
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "Hello"
+ binding.irb
+ puts "World"
+ RUBY
+
+ output = run_ruby_file do
+ type "continue"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) continue/, output)
+ assert_match(/=> 3: binding.irb/, output)
+ end
+
+ def test_finish
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ puts "Hello"
+ end
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "finish"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) finish/, output)
+ assert_match(/=> 4\| end/, output)
+ end
+
+ def test_info
+ write_ruby <<~'RUBY'
+ def foo
+ a = "He" + "llo"
+ binding.irb
+ end
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "info"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) info/, output)
+ assert_match(/%self = main/, output)
+ assert_match(/a = "Hello"/, output)
+ end
+
+ def test_catch
+ write_ruby <<~'RUBY'
+ binding.irb
+ 1 / 0
+ RUBY
+
+ output = run_ruby_file do
+ type "catch ZeroDivisionError"
+ type "continue"
+ type "continue"
+ end
+
+ assert_match(/\(rdbg:irb\) catch/, output)
+ assert_match(/Stop by #0 BP - Catch "ZeroDivisionError"/, output)
+ end
+
+ private
+
+ TIMEOUT_SEC = 3
+
+ def run_ruby_file(&block)
+ cmd = [EnvUtil.rubybin, "-I", LIB, @ruby_file.to_path]
+ tmp_dir = Dir.mktmpdir
+ rc_file = File.open(File.join(tmp_dir, ".irbrc"), "w+")
+ rc_file.write("IRB.conf[:USE_SINGLELINE] = true")
+ rc_file.close
+
+ @commands = []
+ lines = []
+
+ yield
+
+ PTY.spawn(IRB_AND_DEBUGGER_OPTIONS.merge("IRBRC" => rc_file.to_path), *cmd) do |read, write, pid|
+ Timeout.timeout(TIMEOUT_SEC) do
+ while line = safe_gets(read)
+ lines << line
+
+ # means the breakpoint is triggered
+ if line.match?(/binding\.irb/)
+ while command = @commands.shift
+ write.puts(command)
+ end
+ end
+ end
+ end
+ ensure
+ read.close
+ write.close
+ kill_safely(pid)
+ end
+
+ lines.join
+ rescue Timeout::Error
+ message = <<~MSG
+ Test timedout.
+
+ #{'=' * 30} OUTPUT #{'=' * 30}
+ #{lines.map { |l| " #{l}" }.join}
+ #{'=' * 27} END OF OUTPUT #{'=' * 27}
+ MSG
+ assert_block(message) { false }
+ ensure
+ File.unlink(@ruby_file) if @ruby_file
+ FileUtils.remove_entry tmp_dir
+ end
+
+ # read.gets could raise exceptions on some platforms
+ # https://github.com/ruby/ruby/blob/master/ext/pty/pty.c#L729-L736
+ def safe_gets(read)
+ read.gets
+ rescue Errno::EIO
+ nil
+ end
+
+ def kill_safely pid
+ return if wait_pid pid, TIMEOUT_SEC
+
+ Process.kill :TERM, pid
+ return if wait_pid pid, 0.2
+
+ Process.kill :KILL, pid
+ Process.waitpid(pid)
+ rescue Errno::EPERM, Errno::ESRCH
+ end
+
+ def wait_pid pid, sec
+ total_sec = 0.0
+ wait_sec = 0.001 # 1ms
+
+ while total_sec < sec
+ if Process.waitpid(pid, Process::WNOHANG) == pid
+ return true
+ end
+ sleep wait_sec
+ total_sec += wait_sec
+ wait_sec *= 2
+ end
+
+ false
+ rescue Errno::ECHILD
+ true
+ end
+
+ def type(command)
+ @commands << command
+ end
+
+ def write_ruby(program)
+ @ruby_file = Tempfile.create(%w{irb- .rb})
+ @ruby_file.write(program)
+ @ruby_file.close
+ end
+ end
+end
diff --git a/test/irb/test_history.rb b/test/irb/test_history.rb
index 81b7fe8679..c74a3a2cb9 100644
--- a/test/irb/test_history.rb
+++ b/test/irb/test_history.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: false
-require 'test/unit'
require 'irb'
require 'irb/ext/save-history'
require 'readline'
+require_relative "helper"
+
module TestIRB
- class TestHistory < Test::Unit::TestCase
+ class TestHistory < TestCase
def setup
IRB.conf[:RC_NAME_GENERATOR] = nil
end
@@ -14,38 +15,10 @@ module TestIRB
IRB.conf[:RC_NAME_GENERATOR] = nil
end
- class TestInputMethod < ::IRB::InputMethod
+ class TestInputMethodWithHistory < TestInputMethod
HISTORY = Array.new
include IRB::HistorySavingAbility
-
- attr_reader :list, :line_no
-
- def initialize(list = [])
- super("test")
- @line_no = 0
- @list = list
- end
-
- def gets
- @list[@line_no]&.tap {@line_no += 1}
- end
-
- def eof?
- @line_no >= @list.size
- end
-
- def encoding
- Encoding.default_external
- end
-
- def reset
- @line_no = 0
- end
-
- def winsize
- [10, 20]
- end
end
def test_history_save_1
@@ -158,6 +131,31 @@ module TestIRB
end
end
+ def test_history_concurrent_use_not_present
+ backup_home = ENV["HOME"]
+ backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
+ backup_irbrc = ENV.delete("IRBRC")
+ IRB.conf[:LC_MESSAGES] = IRB::Locale.new
+ IRB.conf[:SAVE_HISTORY] = 1
+ Dir.mktmpdir("test_irb_history_") do |tmpdir|
+ ENV["HOME"] = tmpdir
+ io = TestInputMethodWithHistory.new
+ io.class::HISTORY.clear
+ io.load_history
+ io.class::HISTORY.concat(%w"line1 line2")
+
+ history_file = IRB.rc_file("_history")
+ assert_not_send [File, :file?, history_file]
+ File.write(history_file, "line0\n")
+ io.save_history
+ assert_equal(%w"line0 line1 line2", File.read(history_file).split)
+ end
+ ensure
+ ENV["HOME"] = backup_home
+ ENV["XDG_CONFIG_HOME"] = backup_xdg_config_home
+ ENV["IRBRC"] = backup_irbrc
+ end
+
private
def assert_history(expected_history, initial_irb_history, input)
@@ -166,13 +164,13 @@ module TestIRB
backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
IRB.conf[:LC_MESSAGES] = IRB::Locale.new
actual_history = nil
- Dir.mktmpdir("test_irb_history_#{$$}") do |tmpdir|
+ Dir.mktmpdir("test_irb_history_") do |tmpdir|
ENV["HOME"] = tmpdir
- open(IRB.rc_file("_history"), "w") do |f|
+ File.open(IRB.rc_file("_history"), "w") do |f|
f.write(initial_irb_history)
end
- io = TestInputMethod.new
+ io = TestInputMethodWithHistory.new
io.class::HISTORY.clear
io.load_history
if block_given?
@@ -184,7 +182,7 @@ module TestIRB
io.save_history
io.load_history
- open(IRB.rc_file("_history"), "r") do |f|
+ File.open(IRB.rc_file("_history"), "r") do |f|
actual_history = f.read
end
end
diff --git a/test/irb/test_init.rb b/test/irb/test_init.rb
index e5417b18c3..d9e338da8d 100644
--- a/test/irb/test_init.rb
+++ b/test/irb/test_init.rb
@@ -1,10 +1,11 @@
# frozen_string_literal: false
-require "test/unit"
require "irb"
require "fileutils"
+require_relative "helper"
+
module TestIRB
- class TestInit < Test::Unit::TestCase
+ class TestInit < TestCase
def setup
# IRBRC is for RVM...
@backup_env = %w[HOME XDG_CONFIG_HOME IRBRC].each_with_object({}) do |env, hash|
@@ -16,6 +17,7 @@ module TestIRB
def teardown
ENV.update(@backup_env)
FileUtils.rm_rf(@tmpdir)
+ IRB.conf.delete(:SCRIPT)
end
def test_setup_with_argv_preserves_global_argv
@@ -35,13 +37,16 @@ module TestIRB
def test_rc_file
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
+ ENV["XDG_CONFIG_HOME"] = "#{tmpdir}/xdg"
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
+ assert_file.not_exist?(tmpdir+"/xdg")
IRB.conf[:RC_NAME_GENERATOR] = nil
FileUtils.touch(tmpdir+"/.irb#{IRB::IRBRC_EXT}")
assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
+ assert_file.not_exist?(tmpdir+"/xdg")
end
end
@@ -62,6 +67,7 @@ module TestIRB
end
def test_recovery_sigint
+ pend "This test gets stuck on Solaris for unknown reason; contribution is welcome" if RUBY_PLATFORM =~ /solaris/
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
status = assert_in_out_err(bundle_exec + %w[-W0 -rirb -e binding.irb;loop{Process.kill("SIGINT",$$)} -- -f --], "exit\n", //, //)
Process.kill("SIGKILL", status.pid) if !status.exited? && !status.stopped? && !status.signaled?
@@ -78,6 +84,10 @@ module TestIRB
IRB.setup(__FILE__)
refute IRB.conf[:USE_COLORIZE]
+ ENV['NO_COLOR'] = ''
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_COLORIZE]
+
ENV['NO_COLOR'] = nil
IRB.setup(__FILE__)
assert IRB.conf[:USE_COLORIZE]
@@ -86,6 +96,74 @@ module TestIRB
IRB.conf[:USE_COLORIZE] = orig_use_colorize
end
+ def test_use_autocomplete_environment_variable
+ orig_use_autocomplete_env = ENV['IRB_USE_AUTOCOMPLETE']
+ orig_use_autocomplete_conf = IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = nil
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = ''
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = 'false'
+ IRB.setup(__FILE__)
+ refute IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = 'true'
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_AUTOCOMPLETE]
+ ensure
+ ENV["IRB_USE_AUTOCOMPLETE"] = orig_use_autocomplete_env
+ IRB.conf[:USE_AUTOCOMPLETE] = orig_use_autocomplete_conf
+ end
+
+ def test_noscript
+ argv = %w[--noscript -- -f]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['-f'], argv)
+
+ argv = %w[--noscript -- a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['a'], argv)
+
+ argv = %w[--noscript a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['a'], argv)
+
+ argv = %w[--script --noscript a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['a'], argv)
+
+ argv = %w[--noscript --script a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('a', IRB.conf[:SCRIPT])
+ assert_equal([], argv)
+ end
+
+ def test_dash
+ argv = %w[-]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('-', IRB.conf[:SCRIPT])
+ assert_equal([], argv)
+
+ argv = %w[-- -]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('-', IRB.conf[:SCRIPT])
+ assert_equal([], argv)
+
+ argv = %w[-- - -f]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('-', IRB.conf[:SCRIPT])
+ assert_equal(['-f'], argv)
+ end
+
private
def with_argv(argv)
diff --git a/test/irb/test_input_method.rb b/test/irb/test_input_method.rb
new file mode 100644
index 0000000000..fdfb566390
--- /dev/null
+++ b/test/irb/test_input_method.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: false
+
+require "irb"
+
+require_relative "helper"
+
+module TestIRB
+ class TestRelineInputMethod < TestCase
+ def setup
+ @conf_backup = IRB.conf.dup
+ IRB.conf[:LC_MESSAGES] = IRB::Locale.new
+ save_encodings
+ end
+
+ def teardown
+ IRB.conf.replace(@conf_backup)
+ restore_encodings
+ end
+
+ def test_initialization
+ IRB::RelineInputMethod.new
+
+ assert_nil Reline.completion_append_character
+ assert_equal '', Reline.completer_quote_characters
+ assert_equal IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS, Reline.basic_word_break_characters
+ assert_equal IRB::InputCompletor::CompletionProc, Reline.completion_proc
+ assert_equal IRB::InputCompletor::PerfectMatchedProc, Reline.dig_perfect_match_proc
+ end
+
+ def test_initialization_without_use_autocomplete
+ original_show_doc_proc = Reline.dialog_proc(:show_doc)&.dialog_proc
+ empty_proc = Proc.new {}
+ Reline.add_dialog_proc(:show_doc, empty_proc)
+
+ IRB.conf[:USE_AUTOCOMPLETE] = false
+
+ IRB::RelineInputMethod.new
+
+ refute Reline.autocompletion
+ assert_equal empty_proc, Reline.dialog_proc(:show_doc).dialog_proc
+ ensure
+ Reline.add_dialog_proc(:show_doc, original_show_doc_proc, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
+
+ def test_initialization_with_use_autocomplete
+ original_show_doc_proc = Reline.dialog_proc(:show_doc)&.dialog_proc
+ empty_proc = Proc.new {}
+ Reline.add_dialog_proc(:show_doc, empty_proc)
+
+ IRB.conf[:USE_AUTOCOMPLETE] = true
+
+ IRB::RelineInputMethod.new
+
+ assert Reline.autocompletion
+ assert_equal IRB::RelineInputMethod::SHOW_DOC_DIALOG, Reline.dialog_proc(:show_doc).dialog_proc
+ ensure
+ Reline.add_dialog_proc(:show_doc, original_show_doc_proc, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
+
+ def test_initialization_with_use_autocomplete_but_without_rdoc
+ original_show_doc_proc = Reline.dialog_proc(:show_doc)&.dialog_proc
+ empty_proc = Proc.new {}
+ Reline.add_dialog_proc(:show_doc, empty_proc)
+
+ IRB.conf[:USE_AUTOCOMPLETE] = true
+
+ without_rdoc do
+ IRB::RelineInputMethod.new
+ end
+
+ assert Reline.autocompletion
+ # doesn't register show_doc dialog
+ assert_equal empty_proc, Reline.dialog_proc(:show_doc).dialog_proc
+ ensure
+ Reline.add_dialog_proc(:show_doc, original_show_doc_proc, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
+ end
+end
+
diff --git a/test/irb/test_option.rb b/test/irb/test_option.rb
index aa634c02a2..e334cee6dd 100644
--- a/test/irb/test_option.rb
+++ b/test/irb/test_option.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: false
-require 'test/unit'
+require_relative "helper"
module TestIRB
- class TestOption < Test::Unit::TestCase
+ class TestOption < TestCase
def test_end_of_option
bug4117 = '[ruby-core:33574]'
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
diff --git a/test/irb/test_raise_no_backtrace_exception.rb b/test/irb/test_raise_no_backtrace_exception.rb
index 3031f000ed..9565419cdd 100644
--- a/test/irb/test_raise_no_backtrace_exception.rb
+++ b/test/irb/test_raise_no_backtrace_exception.rb
@@ -1,10 +1,11 @@
# frozen_string_literal: false
-require 'test/unit'
+require "tmpdir"
+
+require_relative "helper"
module TestIRB
- class TestRaiseNoBacktraceException < Test::Unit::TestCase
+ class TestRaiseNoBacktraceException < 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")
@@ -15,7 +16,7 @@ IRB
end
def test_raise_exception_with_invalid_byte_sequence
- skip if RUBY_ENGINE == 'truffleruby' || /mswin|mingw/ =~ RUBY_PLATFORM
+ pend if RUBY_ENGINE == 'truffleruby' || /mswin|mingw/ =~ RUBY_PLATFORM
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<~IRB, /A\\xF3B \(StandardError\)/, [])
raise StandardError, "A\\xf3B"
@@ -23,7 +24,6 @@ IRB
end
def test_raise_exception_with_different_encoding_containing_invalid_byte_sequence
- skip if RUBY_ENGINE == 'truffleruby'
backup_home = ENV["HOME"]
Dir.mktmpdir("test_irb_raise_no_backtrace_exception_#{$$}") do |tmpdir|
ENV["HOME"] = tmpdir
@@ -40,6 +40,8 @@ IRB
end
env = {}
%w(LC_MESSAGES LC_ALL LC_CTYPE LANG).each {|n| env[n] = "ja_JP.UTF-8" }
+ # TruffleRuby warns when the locale does not exist
+ env['TRUFFLERUBYOPT'] = "#{ENV['TRUFFLERUBYOPT']} --log.level=SEVERE" if RUBY_ENGINE == 'truffleruby'
args = [env] + bundle_exec + %W[-rirb -C #{tmpdir} -W0 -e IRB.start(__FILE__) -- -f --]
error = /`raise_euc_with_invalid_byte_sequence': あ\\xFF \(RuntimeError\)/
assert_in_out_err(args, <<~IRB, error, [], encoding: "UTF-8")
diff --git a/test/irb/test_ruby_lex.rb b/test/irb/test_ruby_lex.rb
index 556afbd776..fa68a4632c 100644
--- a/test/irb/test_ruby_lex.rb
+++ b/test/irb/test_ruby_lex.rb
@@ -1,10 +1,12 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
-require 'irb/ruby-lex'
-require 'test/unit'
+require 'irb'
+require 'rubygems'
require 'ostruct'
+require_relative "helper"
+
module TestIRB
- class TestRubyLex < Test::Unit::TestCase
+ class TestRubyLex < TestCase
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level)
class MockIO_AutoIndent
@@ -19,30 +21,52 @@ module TestIRB
end
end
+ def setup
+ save_encodings
+ end
+
+ def teardown
+ restore_encodings
+ end
+
def assert_indenting(lines, correct_space_count, add_new_line)
lines = lines + [""] if add_new_line
last_line_index = lines.length - 1
byte_pointer = lines.last.length
+ context = build_context
+ context.auto_indent_mode = true
ruby_lex = RubyLex.new()
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
- ruby_lex.set_input(io)
- context = OpenStruct.new(auto_indent_mode: true)
+ ruby_lex.set_input(io, context: context)
ruby_lex.set_auto_indent(context)
end
- def assert_nesting_level(lines, expected)
- ruby_lex = RubyLex.new()
- io = proc{ lines.join("\n") }
- ruby_lex.set_input(io, io)
- ruby_lex.lex
+ def assert_nesting_level(lines, expected, local_variables: [])
+ ruby_lex = ruby_lex_for_lines(lines, local_variables: local_variables)
error_message = "Calculated the wrong number of nesting level for:\n #{lines.join("\n")}"
assert_equal(expected, ruby_lex.instance_variable_get(:@indent), error_message)
end
+ def assert_code_block_open(lines, expected, local_variables: [])
+ ruby_lex = ruby_lex_for_lines(lines, local_variables: local_variables)
+ error_message = "Wrong result of code_block_open for:\n #{lines.join("\n")}"
+ assert_equal(expected, ruby_lex.instance_variable_get(:@code_block_open), error_message)
+ end
+
+ def ruby_lex_for_lines(lines, local_variables: [])
+ ruby_lex = RubyLex.new()
+
+ context = build_context(local_variables)
+ io = proc{ lines.join("\n") }
+ ruby_lex.set_input(io, io, context: context)
+ ruby_lex.lex(context)
+ ruby_lex
+ end
+
def test_auto_indent
input_with_correct_indents = [
Row.new(%q(def each_top_level_statement), nil, 2),
@@ -109,8 +133,8 @@ module TestIRB
Row.new(%q( ]), 4, 4),
Row.new(%q( ]), 2, 2),
Row.new(%q(]), 0, 0),
- Row.new(%q([<<FOO]), nil, 0),
- Row.new(%q(hello), nil, 0),
+ Row.new(%q([<<FOO]), 0, 0),
+ Row.new(%q(hello), 0, 0),
Row.new(%q(FOO), nil, 0),
]
@@ -136,10 +160,27 @@ 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'
+ def test_symbols
+ input_with_correct_indents = [
+ Row.new(%q(:a), nil, 0),
+ Row.new(%q(:A), nil, 0),
+ Row.new(%q(:+), nil, 0),
+ Row.new(%q(:@@a), nil, 0),
+ Row.new(%q(:@a), nil, 0),
+ Row.new(%q(:$a), nil, 0),
+ Row.new(%q(:def), nil, 0),
+ Row.new(%q(:`), nil, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
end
+ end
+
+ def test_endless_range_at_end_of_line
input_with_prompt = [
PromptRow.new('001:0: :> ', %q(a = 3..)),
PromptRow.new('002:0: :* ', %q()),
@@ -150,6 +191,40 @@ module TestIRB
assert_dynamic_prompt(lines, expected_prompt_list)
end
+ def test_heredoc_with_embexpr
+ input_with_prompt = [
+ PromptRow.new('001:0:":* ', %q(<<A+%W[#{<<B)),
+ PromptRow.new('002:0:":* ', %q(#{<<C+%W[)),
+ PromptRow.new('003:0:":* ', %q()),
+ PromptRow.new('004:0:":* ', %q(C)),
+ PromptRow.new('005:0:]:* ', %q()),
+ PromptRow.new('006:0:":* ', %q(]})),
+ PromptRow.new('007:0:":* ', %q(})),
+ PromptRow.new('008:0:":* ', %q(A)),
+ PromptRow.new('009:0:]:* ', %q(B)),
+ PromptRow.new('010:0:]:* ', %q(})),
+ PromptRow.new('011:0: :> ', %q(])),
+ PromptRow.new('012: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_backtick_method
+ input_with_prompt = [
+ PromptRow.new('001:0: :> ', %q(self.`(arg))),
+ PromptRow.new('002:0: :* ', %q()),
+ PromptRow.new('003:0: :> ', %q(def `(); end)),
+ PromptRow.new('004: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),
@@ -379,6 +454,23 @@ module TestIRB
end
end
+ def test_corresponding_syntax_to_keyword_in
+ input_with_correct_indents = [
+ Row.new(%q(module E), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(class A), nil, 2, 1),
+ Row.new(%q( in), nil, 4, 1)
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
def test_bracket_corresponding_to_times
input_with_correct_indents = [
Row.new(%q(3.times { |i|), nil, 2, 1),
@@ -443,12 +535,21 @@ module TestIRB
end
end
+ def test_local_variables_dependent_code
+ pend if RUBY_ENGINE == 'truffleruby'
+ lines = ["a /1#/ do", "2"]
+ assert_nesting_level(lines, 1)
+ assert_code_block_open(lines, true)
+ assert_nesting_level(lines, 0, local_variables: ['a'])
+ assert_code_block_open(lines, false, local_variables: ['a'])
+ 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),
+ Row.new(%q(<<~Q), 0, 0, 0),
+ Row.new(%q({), 0, 0, 0),
+ Row.new(%q( #), 2, 0, 0),
+ Row.new(%q(}), 0, 0, 0)
]
lines = []
@@ -479,12 +580,12 @@ module TestIRB
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'
+ pend 'This test needs Ripper::Lexer#scan to take broken tokens'
end
input_with_correct_indents = [
Row.new(%q(def foo), nil, 2, 1),
- Row.new(%q( <<~Q), nil, 2, 1),
- Row.new(%q( Qend), nil, 2, 1),
+ Row.new(%q( <<~Q), 2, 2, 1),
+ Row.new(%q( Qend), 2, 2, 1),
]
lines = []
@@ -511,7 +612,7 @@ module TestIRB
end
def assert_dynamic_prompt(lines, expected_prompt_list)
- skip if RUBY_ENGINE == 'truffleruby'
+ pend if RUBY_ENGINE == 'truffleruby'
ruby_lex = RubyLex.new()
io = MockIO_DynamicPrompt.new(lines) do |prompt_list|
error_message = <<~EOM
@@ -526,7 +627,8 @@ module TestIRB
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)
+ context = build_context
+ ruby_lex.set_input(io, context: context)
end
def test_dyanmic_prompt
@@ -555,20 +657,20 @@ module TestIRB
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'
+ pend 'This test needs Ripper::Lexer#scan to take broken tokens'
end
tokens = RubyLex.ripper_lex_without_warning('%wwww')
pos_to_index = {}
tokens.each_with_index { |t, i|
- assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
- pos_to_index[t[0]] = i
+ assert_nil(pos_to_index[t.pos], "There is already another token in the position of #{t.inspect}.")
+ pos_to_index[t.pos] = i
}
end
def test_broken_percent_literal_in_method
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ pend 'This test needs Ripper::Lexer#scan to take broken tokens'
end
tokens = RubyLex.ripper_lex_without_warning(<<~EOC.chomp)
@@ -578,9 +680,46 @@ module TestIRB
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
+ assert_nil(pos_to_index[t.pos], "There is already another token in the position of #{t.inspect}.")
+ pos_to_index[t.pos] = i
}
end
+
+ def test_unterminated_code
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
+ pend 'This test needs Ripper::Lexer#scan to take broken tokens'
+ end
+
+ ['do', '<<A'].each do |code|
+ tokens = RubyLex.ripper_lex_without_warning(code)
+ assert_equal(code, tokens.map(&:tok).join, "Cannot reconstruct code from tokens")
+ error_tokens = tokens.map(&:event).grep(/error/)
+ assert_empty(error_tokens, 'Error tokens must be ignored if there is corresponding non-error token')
+ end
+ end
+
+ def test_unterminated_heredoc_string_literal
+ ['<<A;<<B', "<<A;<<B\n", "%W[\#{<<A;<<B", "%W[\#{<<A;<<B\n"].each do |code|
+ tokens = RubyLex.ripper_lex_without_warning(code)
+ string_literal = RubyLex.new.check_string_literal(tokens)
+ assert_equal('<<A', string_literal&.tok)
+ end
+ end
+
+ private
+
+ def build_context(local_variables = nil)
+ IRB.init_config(nil)
+ workspace = IRB::WorkSpace.new(TOPLEVEL_BINDING.dup)
+
+ if local_variables
+ local_variables.each do |n|
+ workspace.binding.local_variable_set(n, nil)
+ end
+ end
+
+ IRB.conf[:VERBOSE] = false
+ IRB::Context.new(nil, workspace)
+ end
end
end
diff --git a/test/irb/test_workspace.rb b/test/irb/test_workspace.rb
index f028fc3aa2..9b10c27b89 100644
--- a/test/irb/test_workspace.rb
+++ b/test/irb/test_workspace.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: false
-require 'test/unit'
require 'tempfile'
require 'rubygems'
require 'irb'
require 'irb/workspace'
require 'irb/color'
+require_relative "helper"
+
module TestIRB
- class TestWorkSpace < Test::Unit::TestCase
+ class TestWorkSpace < TestCase
def test_code_around_binding
IRB.conf[:USE_COLORIZE] = false
Tempfile.create('irb') do |f|
@@ -39,8 +40,8 @@ module TestIRB
end
def test_code_around_binding_with_existing_unreadable_file
- skip 'chmod cannot make file unreadable on windows' if windows?
- skip 'skipped in root privilege' if Process.uid == 0
+ pend 'chmod cannot make file unreadable on windows' if windows?
+ pend 'skipped in root privilege' if Process.uid == 0
Tempfile.create('irb') do |f|
code = "IRB::WorkSpace.new(binding)\n"
@@ -80,6 +81,23 @@ module TestIRB
assert_equal(nil, workspace.code_around_binding)
end
+
+ def test_toplevel_binding_local_variables
+ pend if RUBY_ENGINE == 'truffleruby'
+ bug17623 = '[ruby-core:102468]'
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ top_srcdir = "#{__dir__}/../.."
+ irb_path = nil
+ %w[exe libexec].find do |dir|
+ irb_path = "#{top_srcdir}/#{dir}/irb"
+ File.exist?(irb_path)
+ end or omit 'irb command not found'
+ assert_in_out_err(bundle_exec + ['-W0', "-C#{top_srcdir}", '-e', <<~RUBY , '--', '-f', '--'], 'binding.local_variables', /\[:_\]/, [], bug17623)
+ version = 'xyz' # typical rubygems loading file
+ load('#{irb_path}')
+ RUBY
+ end
+
private
def with_script_lines
diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb
index 8f55b38a93..9e09948869 100644
--- a/test/irb/yamatanooroti/test_rendering.rb
+++ b/test/irb/yamatanooroti/test_rendering.rb
@@ -29,7 +29,7 @@ begin
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')
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
write(<<~EOC)
'Hello, World!'
EOC
@@ -46,7 +46,7 @@ begin
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')
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
write(<<~EOC)
class A
def inspect; '#<A>'; end
@@ -85,7 +85,7 @@ begin
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')
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
write(<<~EOC)
class A
def inspect; '#<A>'; end
@@ -153,7 +153,91 @@ begin
EOC
end
- private def write_irbrc(content)
+ def test_symbol_with_backtick
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ :`
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001:0> :`
+ => :`
+ irb(main):002:0>
+ EOC
+ end
+
+ def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_right
+ pend "Needs a dummy document to show doc"
+ write_irbrc <<~'LINES'
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_N => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ puts 'start IRB'
+ LINES
+ start_terminal(4, 19, %W{ruby -I/home/aycabta/ruby/reline/lib -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("Str\C-i")
+ close
+ assert_screen(<<~EOC)
+ 001> String
+ StringPress A
+ StructString
+ of byte
+ EOC
+ end
+
+ def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_left
+ pend "Needs a dummy document to show doc"
+ write_irbrc <<~'LINES'
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_N => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ puts 'start IRB'
+ LINES
+ start_terminal(4, 12, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("Str\C-i")
+ close
+ assert_screen(<<~EOC)
+ 001> String
+ PressString
+ StrinStruct
+ of by
+ EOC
+ end
+
+ def test_assignment_expression_truncate
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ # Assignment expression code that turns into non-assignment expression after evaluation
+ code = "a /'/i if false; a=1; x=1000.times.to_a#'.size"
+ write(code + "\n")
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001:0> #{code}
+ =>
+ [0,
+ ...
+ irb(main):002:0>
+ EOC
+ end
+
+ private
+
+ def write_irbrc(content)
File.open(@irbrc_file, 'w') do |f|
f.write content
end
diff --git a/test/json/json_addition_test.rb b/test/json/json_addition_test.rb
index e95ace8375..614c735567 100644
--- a/test/json/json_addition_test.rb
+++ b/test/json/json_addition_test.rb
@@ -165,7 +165,7 @@ class JSONAdditionTest < Test::Unit::TestCase
def test_utc_datetime
now = Time.now
- d = DateTime.parse(now.to_s, :create_additions => true) # usual case
+ d = DateTime.parse(now.to_s) # usual case
assert_equal d, parse(d.to_json, :create_additions => true)
d = DateTime.parse(now.utc.to_s) # of = 0
assert_equal d, parse(d.to_json, :create_additions => true)
diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb
index dce693e548..146ff7c047 100644
--- a/test/json/json_parser_test.rb
+++ b/test/json/json_parser_test.rb
@@ -84,6 +84,7 @@ class JSONParserTest < Test::Unit::TestCase
assert_equal({ "a" => 23 }, parse(' { "a" : 23 } '))
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
+ assert_equal({ "" => 123 }, parse('{"":123}'))
end
def test_parse_numbers
@@ -114,6 +115,10 @@ class JSONParserTest < Test::Unit::TestCase
assert_equal(BigDecimal("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
end
+ def test_parse_string_mixed_unicode
+ assert_equal(["éé"], JSON.parse("[\"\\u00e9é\"]"))
+ end
+
if Array.method_defined?(:permutation)
def test_parse_more_complex_arrays
a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
diff --git a/test/lib/jit_support.rb b/test/lib/jit_support.rb
index 3bca63a549..812c13b925 100644
--- a/test/lib/jit_support.rb
+++ b/test/lib/jit_support.rb
@@ -2,13 +2,17 @@ require 'rbconfig'
module JITSupport
JIT_TIMEOUT = 600 # 10min for each...
- JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
+ JIT_SUCCESS_PREFIX = 'JIT success'
JIT_RECOMPILE_PREFIX = 'JIT recompile'
JIT_COMPACTION_PREFIX = 'JIT compaction \(\d+\.\dms\)'
UNSUPPORTED_COMPILERS = [
%r[\A.*/bin/intel64/icc\b],
%r[\A/opt/developerstudio\d+\.\d+/bin/cc\z],
]
+ UNSUPPORTED_ARCHITECTURES = [
+ 's390x',
+ 'sparc',
+ ]
# 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
@@ -21,7 +25,7 @@ module JITSupport
]
module_function
- # Run Ruby script with --jit-wait (Synchronous JIT compilation).
+ # Run Ruby script with --mjit-wait (Synchronous JIT compilation).
# Returns [stdout, stderr]
def eval_with_jit(env = nil, script, **opts)
stdout, stderr = nil, nil
@@ -34,14 +38,15 @@ module JITSupport
[stdout, stderr]
end
- def eval_with_jit_without_retry(env = nil, script, verbose: 0, min_calls: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT)
+ def eval_with_jit_without_retry(env = nil, script, verbose: 0, call_threshold: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT)
args = [
- '--disable-gems', "--jit-verbose=#{verbose}",
- "--jit-min-calls=#{min_calls}", "--jit-max-cache=#{max_cache}",
+ '--disable-gems', "--mjit-verbose=#{verbose}",
+ "--mjit-call-threshold=#{call_threshold}", "--mjit-max-cache=#{max_cache}",
]
- args << '--jit-wait' if wait
- args << '--jit-save-temps' if save_temps
- args << '--jit-debug' if defined?(@jit_debug) && @jit_debug
+ args << '--disable-yjit'
+ args << '--mjit-wait' if wait
+ args << '--mjit-save-temps' if save_temps
+ args << '--mjit-debug' if defined?(@mjit_debug) && @mjit_debug
args << '-e' << script
base_env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } # workaround to skip requiring `make install` for `make test-all`
if preloadenv = RbConfig::CONFIG['PRELOADENV'] and !preloadenv.empty?
@@ -54,27 +59,23 @@ module JITSupport
)
end
+ # For MJIT
def supported?
return @supported if defined?(@supported)
- @supported = RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' && UNSUPPORTED_COMPILERS.all? do |regexp|
- !regexp.match?(RbConfig::CONFIG['MJIT_CC'])
- end && !appveyor_pdb_corrupted? && !PENDING_RUBYCI_NICKNAMES.include?(ENV['RUBYCI_NICKNAME'])
+ @supported = RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' &&
+ UNSUPPORTED_COMPILERS.all? { |regexp| !regexp.match?(RbConfig::CONFIG['MJIT_CC']) } &&
+ !PENDING_RUBYCI_NICKNAMES.include?(ENV['RUBYCI_NICKNAME']) &&
+ !UNSUPPORTED_ARCHITECTURES.include?(RUBY_PLATFORM.split('-', 2).first)
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.')
+ def yjit_supported?
+ return @yjit_supported if defined?(@yjit_supported)
+ # nil in mswin
+ @yjit_supported = ![nil, 'no'].include?(RbConfig::CONFIG['YJIT_SUPPORT'])
end
def remove_mjit_logs(stderr)
- if defined?(RubyVM::JIT) && RubyVM::JIT.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
@@ -90,4 +91,8 @@ module JITSupport
RbConfig::CONFIG['CC'].start_with?('gcc') &&
stderr.include?("error trying to exec 'cc1': execvp: No such file or directory")
end
+
+ def mjit_force_enabled?
+ "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?MJIT_FORCE_ENABLE\b/)
+ end
end
diff --git a/test/logger/helper.rb b/test/logger/helper.rb
deleted file mode 100644
index 9eaeb205b0..0000000000
--- a/test/logger/helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-ROOT_DIR = File.dirname(__dir__)
-$LOAD_PATH.unshift File.join(ROOT_DIR, 'lib') # to use logger in this repo instead of ruby built-in logger
-$LOAD_PATH.unshift File.join(ROOT_DIR, 'test', 'lib') # to use custom test-unit in this repo
-require 'logger'
-require 'test/unit'
-
-begin
- # for standalone test suite on ruby/logger
- require 'core_assertions'
-
- Test::Unit::TestCase.include Test::Unit::CoreAssertions
-rescue LoadError
-end
diff --git a/test/logger/test_formatter.rb b/test/logger/test_formatter.rb
new file mode 100644
index 0000000000..9465722991
--- /dev/null
+++ b/test/logger/test_formatter.rb
@@ -0,0 +1,35 @@
+# coding: US-ASCII
+# frozen_string_literal: false
+require 'logger'
+
+class TestFormatter < Test::Unit::TestCase
+ def test_call
+ severity = 'INFO'
+ time = Time.now
+ progname = 'ruby'
+ msg = 'This is a test'
+ formatter = Logger::Formatter.new
+
+ result = formatter.call(severity, time, progname, msg)
+ time_matcher = /\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}/
+ matcher = /#{severity[0..0]}, \[#{time_matcher} #\d+\] #{severity} -- #{progname}: #{msg}\n/
+
+ assert_match(matcher, result)
+ end
+
+ class CustomFormatter < Logger::Formatter
+ def call(time)
+ format_datetime(time)
+ end
+ end
+
+ def test_format_datetime
+ time = Time.now
+ formatter = CustomFormatter.new
+
+ result = formatter.call(time)
+ matcher = /^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}$/
+
+ assert_match(matcher, result)
+ end
+end
diff --git a/test/logger/test_logdevice.rb b/test/logger/test_logdevice.rb
index 6fefd356cd..8f1c15542a 100644
--- a/test/logger/test_logdevice.rb
+++ b/test/logger/test_logdevice.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
require 'tempfile'
require 'tmpdir'
@@ -435,6 +435,7 @@ class TestLogDevice < Test::Unit::TestCase
logdev1.write(message)
assert_file.identical?(log, logdev1.dev)
+ # NOTE: below assertion fails in JRuby 9.3 and TruffleRuby
assert_file.identical?(log + ".0", logdev2.dev)
logdev2.write(message)
@@ -451,7 +452,7 @@ class TestLogDevice < Test::Unit::TestCase
end
ensure
logdev0.close
- end unless /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
+ end unless /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os']
def test_shifting_midnight
Dir.mktmpdir do |tmpdir|
diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb
index 4bbfd523c0..37d0f5862a 100644
--- a/test/logger/test_logger.rb
+++ b/test/logger/test_logger.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
require 'tempfile'
class TestLogger < Test::Unit::TestCase
@@ -13,7 +13,7 @@ class TestLogger < Test::Unit::TestCase
class Log
attr_reader :label, :datetime, :pid, :severity, :progname, :msg
def initialize(line)
- /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line
+ /\A(\w+), \[([^#]*) #(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line
@label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
end
end
@@ -124,7 +124,7 @@ class TestLogger < Test::Unit::TestCase
dummy = STDERR
logger = Logger.new(dummy)
log = log_add(logger, INFO, "foo")
- assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime)
+ assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime)
logger.datetime_format = "%d%b%Y@%H:%M:%S"
log = log_add(logger, INFO, "foo")
assert_match(/^\d\d\w\w\w\d\d\d\d@\d\d:\d\d:\d\d$/, log.datetime)
@@ -203,7 +203,7 @@ class TestLogger < Test::Unit::TestCase
# default
logger = Logger.new(STDERR)
log = log_add(logger, INFO, "foo")
- assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+ $/, log.datetime)
+ assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime)
# config
logger = Logger.new(STDERR, datetime_format: "%d%b%Y@%H:%M:%S")
log = log_add(logger, INFO, "foo")
diff --git a/test/logger/test_logperiod.rb b/test/logger/test_logperiod.rb
index 3c5cbbcd9b..6e6e5e9533 100644
--- a/test/logger/test_logperiod.rb
+++ b/test/logger/test_logperiod.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
require 'time'
class TestLogPeriod < Test::Unit::TestCase
diff --git a/test/logger/test_severity.rb b/test/logger/test_severity.rb
index 1197e8abb9..dad63472a6 100644
--- a/test/logger/test_severity.rb
+++ b/test/logger/test_severity.rb
@@ -1,6 +1,6 @@
# coding: US-ASCII
# frozen_string_literal: false
-require_relative 'helper'
+require 'logger'
class TestLoggerSeverity < Test::Unit::TestCase
def test_enum
diff --git a/test/mkmf/base.rb b/test/mkmf/base.rb
index 4f67478a56..ec42bca100 100644
--- a/test/mkmf/base.rb
+++ b/test/mkmf/base.rb
@@ -20,134 +20,132 @@ $INCFLAGS << " -I."
$extout_prefix = "$(extout)$(target_prefix)/"
class TestMkmf < Test::Unit::TestCase
-end
-
-module TestMkmf::Base
- MKMFLOG = proc {File.read("mkmf.log") rescue ""}
+ module Base
+ MKMFLOG = proc {File.read("mkmf.log") rescue ""}
- class Capture
- attr_accessor :origin
- def initialize
- @buffer = ""
- @filter = nil
- @out = true
- @origin = nil
- end
- def clear
- @buffer.clear
- end
- def flush
- STDOUT.print @filter ? @filter.call(@buffer) : @buffer
- clear
- end
- def reopen(io)
- case io
- when Capture
- initialize_copy(io)
- when File
- @out = false
- @origin.reopen(io) if @origin
- when IO
+ class Capture
+ attr_accessor :origin
+ def initialize
+ @buffer = ""
+ @filter = nil
@out = true
- @origin.reopen(io) if @origin
- else
- @out = false
+ @origin = nil
end
- end
- def filter(&block)
- @filter = block
- end
- def write(*s)
- if @out
- @buffer.concat(*s)
- elsif @origin
- @origin.write(*s)
+ def clear
+ @buffer.clear
+ end
+ def flush
+ STDOUT.print @filter ? @filter.call(@buffer) : @buffer
+ clear
+ end
+ def reopen(io)
+ case io
+ when Capture
+ initialize_copy(io)
+ when File
+ @out = false
+ @origin.reopen(io) if @origin
+ when IO
+ @out = true
+ @origin.reopen(io) if @origin
+ else
+ @out = false
+ end
+ end
+ def filter(&block)
+ @filter = block
+ end
+ def write(*s)
+ if @out
+ @buffer.concat(*s)
+ elsif @origin
+ @origin.write(*s)
+ end
end
end
- end
- attr_reader :stdout
+ attr_reader :stdout
- def mkmflog(msg)
- proc {MKMFLOG[] << msg}
- end
+ def mkmflog(msg)
+ proc {MKMFLOG[] << msg}
+ end
- def setup
- @rbconfig = rbconfig0 = RbConfig::CONFIG
- @mkconfig = mkconfig0 = RbConfig::MAKEFILE_CONFIG
- rbconfig = {
- "hdrdir" => $hdrdir,
- "srcdir" => $srcdir,
- "topdir" => $topdir,
- }
- mkconfig = {
- "hdrdir" => "$(top_srcdir)/include",
- "srcdir" => "$(top_srcdir)",
- "topdir" => $topdir,
- }
- rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
- mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
- RbConfig.module_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, rbconfig)
- remove_const(:MAKEFILE_CONFIG)
- const_set(:MAKEFILE_CONFIG, mkconfig)
- }
- MakeMakefile.class_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, mkconfig)
- }
- @tmpdir = Dir.mktmpdir
- @curdir = Dir.pwd
- @mkmfobj = Object.new
- @stdout = Capture.new
- Dir.chdir(@tmpdir)
- @quiet, Logging.quiet = Logging.quiet, true
- init_mkmf
- $INCFLAGS[0, 0] = "-I. "
- end
+ def setup
+ @rbconfig = rbconfig0 = RbConfig::CONFIG
+ @mkconfig = mkconfig0 = RbConfig::MAKEFILE_CONFIG
+ rbconfig = {
+ "hdrdir" => $hdrdir,
+ "srcdir" => $srcdir,
+ "topdir" => $topdir,
+ }
+ mkconfig = {
+ "hdrdir" => "$(top_srcdir)/include",
+ "srcdir" => "$(top_srcdir)",
+ "topdir" => $topdir,
+ }
+ rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
+ mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
+ RbConfig.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig)
+ }
+ MakeMakefile.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig)
+ }
+ @tmpdir = Dir.mktmpdir
+ @curdir = Dir.pwd
+ @mkmfobj = Object.new
+ @stdout = Capture.new
+ Dir.chdir(@tmpdir)
+ @quiet, Logging.quiet = Logging.quiet, true
+ init_mkmf
+ $INCFLAGS[0, 0] = "-I. "
+ end
- def teardown
- rbconfig0 = @rbconfig
- mkconfig0 = @mkconfig
- RbConfig.module_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, rbconfig0)
- remove_const(:MAKEFILE_CONFIG)
- const_set(:MAKEFILE_CONFIG, mkconfig0)
- }
- MakeMakefile.class_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, mkconfig0)
- }
- Logging.quiet = @quiet
- Logging.log_close
- FileUtils.rm_f("mkmf.log")
- Dir.chdir(@curdir)
- FileUtils.rm_rf(@tmpdir)
- end
+ def teardown
+ return if @omitted
+ rbconfig0 = @rbconfig
+ mkconfig0 = @mkconfig
+ RbConfig.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig0)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig0)
+ }
+ MakeMakefile.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig0)
+ }
+ Logging.quiet = @quiet
+ Logging.log_close
+ FileUtils.rm_f("mkmf.log")
+ Dir.chdir(@curdir)
+ FileUtils.rm_rf(@tmpdir)
+ end
- def mkmf(*args, &block)
- @stdout.clear
- stdout, @stdout.origin, $stdout = @stdout.origin, $stdout, @stdout
- verbose, $VERBOSE = $VERBOSE, false
- @mkmfobj.instance_eval(*args, &block)
- ensure
- $VERBOSE = verbose
- $stdout, @stdout.origin = @stdout.origin, stdout
- end
+ def mkmf(*args, &block)
+ @stdout.clear
+ stdout, @stdout.origin, $stdout = @stdout.origin, $stdout, @stdout
+ verbose, $VERBOSE = $VERBOSE, false
+ @mkmfobj.instance_eval(*args, &block)
+ ensure
+ $VERBOSE = verbose
+ $stdout, @stdout.origin = @stdout.origin, stdout
+ end
- def config_value(name)
- create_tmpsrc("---config-value=#{name}")
- xpopen(cpp_command('')) do |f|
- f.grep(/^---config-value=(.*)/) {return $1}
+ def config_value(name)
+ create_tmpsrc("---config-value=#{name}")
+ xpopen(cpp_command('')) do |f|
+ f.grep(/^---config-value=(.*)/) {return $1}
+ end
+ nil
end
- nil
end
-end
-class TestMkmf
- include TestMkmf::Base
+ include Base
def assert_separately(args, src, *rest, **options)
super(args + ["-r#{__FILE__}"], "extend TestMkmf::Base; setup\nEND{teardown}\n#{src}", *rest, **options)
diff --git a/test/mkmf/test_config.rb b/test/mkmf/test_config.rb
index 07ed641415..93ebe3a4ea 100644
--- a/test/mkmf/test_config.rb
+++ b/test/mkmf/test_config.rb
@@ -4,14 +4,12 @@ $extmk = true
require 'test/unit'
require 'mkmf'
-class TestMkmf < Test::Unit::TestCase
- class TestConfig < Test::Unit::TestCase
- def test_dir_config
- bug8074 = '[Bug #8074]'
- lib = RbConfig.expand(RbConfig::MAKEFILE_CONFIG["libdir"], "exec_prefix"=>"")
- assert_separately %w[-rmkmf - -- --with-foo-dir=/test/foo], %{
- assert_equal(%w[/test/foo/include /test/foo#{lib}], dir_config("foo"), #{bug8074.dump})
- }
- end
+class TestMkmfConfig < Test::Unit::TestCase
+ def test_dir_config
+ bug8074 = '[Bug #8074]'
+ lib = RbConfig.expand(RbConfig::MAKEFILE_CONFIG["libdir"], "exec_prefix"=>"/test/foo")
+ assert_separately %w[-rmkmf - -- --with-foo-dir=/test/foo], %{
+ assert_equal(%w[/test/foo/include #{lib}], dir_config("foo"), #{bug8074.dump})
+ }
end
end
diff --git a/test/mkmf/test_constant.rb b/test/mkmf/test_constant.rb
index f5a87a1caa..f22b82ff95 100644
--- a/test/mkmf/test_constant.rb
+++ b/test/mkmf/test_constant.rb
@@ -1,38 +1,44 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestTryConstant < TestMkmf
- def test_simple
- assert_equal( 0, mkmf {try_constant("0")}, MKMFLOG)
- assert_equal( 1, mkmf {try_constant("1")}, MKMFLOG)
- assert_equal(-1, mkmf {try_constant("-1")}, MKMFLOG)
+class TestMkmfTryConstant < TestMkmf
+ def setup
+ if ENV.key?('APPVEYOR')
+ @omitted = true
+ omit 'This test fails too often on AppVeyor'
end
+ super
+ end
- def test_sizeof
- assert_equal(config_value("SIZEOF_INT").to_i, mkmf {try_constant("sizeof(int)")}, MKMFLOG)
- assert_equal(config_value("SIZEOF_LONG").to_i, mkmf {try_constant("sizeof(long)")}, MKMFLOG)
- assert_equal(config_value("SIZEOF_VOIDP").to_i, mkmf {try_constant("sizeof(void*)")}, MKMFLOG)
- assert_equal(config_value("SIZEOF_VALUE").to_i, mkmf {try_constant("sizeof(Qnil)")}, MKMFLOG)
- end
+ def test_simple
+ assert_equal( 0, mkmf {try_constant("0")}, MKMFLOG)
+ assert_equal( 1, mkmf {try_constant("1")}, MKMFLOG)
+ assert_equal(-1, mkmf {try_constant("-1")}, MKMFLOG)
+ end
- def test_long
- sizeof_int = config_value("SIZEOF_INT").to_i
- sizeof_long = config_value("SIZEOF_LONG").to_i
- if sizeof_long > sizeof_int
- type = 'long'
- else
- sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
- return if !sizeof_long_long or sizeof_long_long <= sizeof_int
- type = 'LONG_LONG'
- end
+ def test_sizeof
+ assert_equal(config_value("SIZEOF_INT").to_i, mkmf {try_constant("sizeof(int)")}, MKMFLOG)
+ assert_equal(config_value("SIZEOF_LONG").to_i, mkmf {try_constant("sizeof(long)")}, MKMFLOG)
+ assert_equal(config_value("SIZEOF_VOIDP").to_i, mkmf {try_constant("sizeof(void*)")}, MKMFLOG)
+ assert_equal(config_value("SIZEOF_VALUE").to_i, mkmf {try_constant("sizeof(Qnil)")}, MKMFLOG)
+ end
- decl = "#define CONFTEST_VALUE (unsigned #{type})(((unsigned #{type})1)<<(CHAR_BIT*sizeof(int)))"
- assert_operator(mkmf {try_constant("CONFTEST_VALUE", [[decl]])}, :>, 0, MKMFLOG)
+ def test_long
+ sizeof_int = config_value("SIZEOF_INT").to_i
+ sizeof_long = config_value("SIZEOF_LONG").to_i
+ if sizeof_long > sizeof_int
+ type = 'long'
+ else
+ sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
+ return if !sizeof_long_long or sizeof_long_long <= sizeof_int
+ type = 'LONG_LONG'
end
- def test_large_unsigned
- assert_operator(mkmf {try_constant("1U<<(CHAR_BIT*sizeof(int)-1)")}, :>, 0, MKMFLOG)
- end
+ decl = "#define CONFTEST_VALUE (unsigned #{type})(((unsigned #{type})1)<<(CHAR_BIT*sizeof(int)))"
+ assert_operator(mkmf {try_constant("CONFTEST_VALUE", [[decl]])}, :>, 0, MKMFLOG)
+ end
+
+ def test_large_unsigned
+ assert_operator(mkmf {try_constant("1U<<(CHAR_BIT*sizeof(int)-1)")}, :>, 0, MKMFLOG)
end
end
diff --git a/test/mkmf/test_convertible.rb b/test/mkmf/test_convertible.rb
index 1baf892842..d65db4265b 100644
--- a/test/mkmf/test_convertible.rb
+++ b/test/mkmf/test_convertible.rb
@@ -1,35 +1,33 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestConvertible < TestMkmf
- def test_typeof_builtin
- ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
- %w[short int long].each do |type|
- assert_equal((prefix || signed)+type,
- mkmf {convertible_int(signed+type)}, MKMFLOG)
- end
+class TestMkmfConvertible < TestMkmf
+ def test_typeof_builtin
+ ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
+ %w[short int long].each do |type|
+ assert_equal((prefix || signed)+type,
+ mkmf {convertible_int(signed+type)}, MKMFLOG)
end
end
+ end
- def test_typeof_typedef
- ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
- %w[short int long].each do |type|
- open("confdefs.h", "w") {|f|
- f.puts "typedef #{signed}#{type} test1_t;"
- }
- $defs.clear
- assert_equal((prefix || signed)+type,
- mkmf {convertible_int("test1_t", "confdefs.h")}, MKMFLOG)
- (u = signed[/^u/]) and u.upcase!
- assert_include($defs, "-DTYPEOF_TEST1_T="+"#{prefix||signed}#{type}".quote)
- assert_include($defs, "-DPRI_TEST1T_PREFIX=PRI_#{type.upcase}_PREFIX")
- assert_include($defs, "-DTEST1T2NUM=#{u}#{type.upcase}2NUM")
- assert_include($defs, "-DNUM2TEST1T=NUM2#{u}#{type.upcase}")
- end
+ def test_typeof_typedef
+ ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
+ %w[short int long].each do |type|
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef #{signed}#{type} test1_t;"
+ }
+ $defs.clear
+ assert_equal((prefix || signed)+type,
+ mkmf {convertible_int("test1_t", "confdefs.h")}, MKMFLOG)
+ (u = signed[/^u/]) and u.upcase!
+ assert_include($defs, "-DTYPEOF_TEST1_T="+"#{prefix||signed}#{type}".quote)
+ assert_include($defs, "-DPRI_TEST1T_PREFIX=PRI_#{type.upcase}_PREFIX")
+ assert_include($defs, "-DTEST1T2NUM=#{u}#{type.upcase}2NUM")
+ assert_include($defs, "-DNUM2TEST1T=NUM2#{u}#{type.upcase}")
end
- ensure
- File.unlink("confdefs.h")
end
+ ensure
+ File.unlink("confdefs.h")
end
end
diff --git a/test/mkmf/test_egrep_cpp.rb b/test/mkmf/test_egrep_cpp.rb
index ce276bef20..7ac0e60010 100644
--- a/test/mkmf/test_egrep_cpp.rb
+++ b/test/mkmf/test_egrep_cpp.rb
@@ -2,14 +2,12 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestEgrepCpp < TestMkmf
- def test_egrep_cpp
- assert_equal(true, egrep_cpp(/ruby_init/, ""), MKMFLOG)
- end
+class TestMkmfEgrepCpp < TestMkmf
+ def test_egrep_cpp
+ assert_equal(true, egrep_cpp(/ruby_init/, ""), MKMFLOG)
+ end
- def test_not_have_func
- assert_equal(false, egrep_cpp(/never match/, ""), MKMFLOG)
- end
+ def test_not_have_func
+ assert_equal(false, egrep_cpp(/never match/, ""), MKMFLOG)
end
end
diff --git a/test/mkmf/test_find_executable.rb b/test/mkmf/test_find_executable.rb
index 7ffc28ecc8..88b70c21c0 100644
--- a/test/mkmf/test_find_executable.rb
+++ b/test/mkmf/test_find_executable.rb
@@ -1,58 +1,56 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestFindExecutable < TestMkmf
- def setup
- super
- @path, ENV["PATH"] = ENV["PATH"], @tmpdir
- end
+class TestMkmfFindExecutable < TestMkmf
+ def setup
+ super
+ @path, ENV["PATH"] = ENV["PATH"], @tmpdir
+ end
- def each_exts(&block)
- name = "foobar#{$$}#{rand(1000)}"
- stdout.filter {|s| s.sub(name, "<executable>")}
- exts = mkmf {self.class::CONFIG['EXECUTABLE_EXTS']}.split
- exts[0] ||= ""
- exts.each do |ext|
- yield name+ext, name
- end
+ def each_exts(&block)
+ name = "foobar#{$$}#{rand(1000)}"
+ stdout.filter {|s| s.sub(name, "<executable>")}
+ exts = mkmf {self.class::CONFIG['EXECUTABLE_EXTS']}.split
+ exts[0] ||= ""
+ exts.each do |ext|
+ yield name+ext, name
end
+ end
- def teardown
- ENV["PATH"] = @path
- super
- end
+ def teardown
+ ENV["PATH"] = @path
+ super
+ end
- def test_find_executable
- bug2669 = '[ruby-core:27912]'
- each_exts do |full, name|
- begin
- open(full, "w") {|ff| ff.chmod(0755)}
- result = mkmf {find_executable(name)}
- ensure
- File.unlink(full)
- end
- assert_equal("#{@tmpdir}/#{full}", result, bug2669)
+ def test_find_executable
+ bug2669 = '[ruby-core:27912]'
+ each_exts do |full, name|
+ begin
+ open(full, "w") {|ff| ff.chmod(0755)}
+ result = mkmf {find_executable(name)}
+ ensure
+ File.unlink(full)
end
+ assert_equal("#{@tmpdir}/#{full}", result, bug2669)
end
+ end
- def test_find_executable_dir
- each_exts do |full, name|
- begin
- Dir.mkdir(full)
- result = mkmf {find_executable(name)}
- ensure
- Dir.rmdir(full)
- end
- assert_nil(result)
+ def test_find_executable_dir
+ each_exts do |full, name|
+ begin
+ Dir.mkdir(full)
+ result = mkmf {find_executable(name)}
+ ensure
+ Dir.rmdir(full)
end
+ assert_nil(result)
end
+ end
- if /mingw|mswin/ =~ RUBY_PLATFORM
- def test_quoted_path_on_windows
- ENV["PATH"] = %["#{@tmpdir}"]
- test_find_executable
- end
+ if /mingw|mswin/ =~ RUBY_PLATFORM
+ def test_quoted_path_on_windows
+ ENV["PATH"] = %["#{@tmpdir}"]
+ test_find_executable
end
end
end
diff --git a/test/mkmf/test_flags.rb b/test/mkmf/test_flags.rb
index a3596d8e55..aedf06b610 100644
--- a/test/mkmf/test_flags.rb
+++ b/test/mkmf/test_flags.rb
@@ -1,57 +1,55 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestFlags < TestMkmf
- def test_valid_warnflags
- val = $extmk
- warnflags = $warnflags
- makefile = mkmf do
- $extmk = false
- self.class::CONFIG['warnflags'] = %w"-Wextra
- -Wno-unused-parameter -Wno-parentheses -Wno-long-long
- -Wno-missing-field-initializers -Werror=pointer-arith
- -Werror=write-strings -Werror=declaration-after-statement
- -Werror=shorten-64-to-32
- -Werror-implicit-function-declaration
- ".join(' ')
- self.class::CONFIG['GCC'] = 'yes'
- init_mkmf(self.class::CONFIG)
- configuration '.'
- end
- generated_flags = makefile.grep(/warnflags/).first[/^warnflags = (.*)$/, 1].split
+class TestMkmfFlags < TestMkmf
+ def test_valid_warnflags
+ val = $extmk
+ warnflags = $warnflags
+ makefile = mkmf do
+ $extmk = false
+ self.class::CONFIG['warnflags'] = %w"-Wextra
+ -Wno-unused-parameter -Wno-parentheses -Wno-long-long
+ -Wno-missing-field-initializers -Werror=pointer-arith
+ -Werror=write-strings -Werror=declaration-after-statement
+ -Werror=shorten-64-to-32
+ -Werror-implicit-function-declaration
+ ".join(' ')
+ self.class::CONFIG['GCC'] = 'yes'
+ init_mkmf(self.class::CONFIG)
+ configuration '.'
+ end
+ generated_flags = makefile.grep(/warnflags/).first[/^warnflags = (.*)$/, 1].split
- assert_equal %w"
- -Wextra -Wno-unused-parameter -Wno-parentheses
- -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith
- -Wwrite-strings -Wdeclaration-after-statement
- -Wshorten-64-to-32 -Wimplicit-function-declaration
- ", generated_flags
+ assert_equal %w"
+ -Wextra -Wno-unused-parameter -Wno-parentheses
+ -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith
+ -Wwrite-strings -Wdeclaration-after-statement
+ -Wshorten-64-to-32 -Werror-implicit-function-declaration
+ ", generated_flags
- ensure
- $warnflags = warnflags
- $extmk = val
- end
+ ensure
+ $warnflags = warnflags
+ $extmk = val
+ end
- def test_try_ldflag_invalid_opt
- assert_separately([], <<-'end;') #do
- assert(!try_ldflags("nosuch.c"), TestMkmf::MKMFLOG)
- assert(have_devel?, TestMkmf::MKMFLOG)
- end;
- end
+ def test_try_ldflag_invalid_opt
+ assert_separately([], <<-'end;') #do
+ assert(!try_ldflags("nosuch.c"), TestMkmf::MKMFLOG)
+ assert(have_devel?, TestMkmf::MKMFLOG)
+ end;
+ end
- def test_try_cflag_invalid_opt
- assert_separately([], <<-'end;', timeout: 30) #do
- assert(!try_cflags("nosuch.c"), TestMkmf::MKMFLOG)
- assert(have_devel?, TestMkmf::MKMFLOG)
- end;
- end
+ def test_try_cflag_invalid_opt
+ assert_separately([], <<-'end;', timeout: 30) #do
+ assert(!try_cflags("nosuch.c"), TestMkmf::MKMFLOG)
+ assert(have_devel?, TestMkmf::MKMFLOG)
+ end;
+ end
- def test_try_cppflag_invalid_opt
- assert_separately([], <<-'end;') #do
- assert(!try_cppflags("nosuch.c"), TestMkmf::MKMFLOG)
- assert(have_devel?, TestMkmf::MKMFLOG)
- end;
- end
+ def test_try_cppflag_invalid_opt
+ assert_separately([], <<-'end;') #do
+ assert(!try_cppflags("nosuch.c"), TestMkmf::MKMFLOG)
+ assert(have_devel?, TestMkmf::MKMFLOG)
+ end;
end
end
diff --git a/test/mkmf/test_framework.rb b/test/mkmf/test_framework.rb
index ba15299ae0..3245e43c75 100644
--- a/test/mkmf/test_framework.rb
+++ b/test/mkmf/test_framework.rb
@@ -1,49 +1,47 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestHaveFramework < TestMkmf
- def create_framework(fw, hdrname = "#{fw}.h")
- Dir.mktmpdir("frameworks") do |dir|
- fwdir = "#{dir}/#{fw}.framework"
- hdrdir = "#{fwdir}/Headers"
- FileUtils.mkdir_p(hdrdir)
- File.write("#{hdrdir}/#{hdrname}", "")
- src = "#{fwdir}/main.c"
- File.write(src, "void #{fw}(void) {}\n")
- cmd = LINK_SO.dup
- RbConfig.expand(cmd, RbConfig::CONFIG.merge("OBJS"=>src))
- cmd.gsub!("$@", "#{fwdir}/#{fw}")
- cmd.gsub!(/ -bundle /, ' -dynamiclib ')
- assert(xsystem(cmd), MKMFLOG)
- $INCFLAGS << " " << "-F#{dir}".quote
- yield fw, hdrname
- end
+class TestMkmfHaveFramework < TestMkmf
+ def create_framework(fw, hdrname = "#{fw}.h")
+ Dir.mktmpdir("frameworks") do |dir|
+ fwdir = "#{dir}/#{fw}.framework"
+ hdrdir = "#{fwdir}/Headers"
+ FileUtils.mkdir_p(hdrdir)
+ File.write("#{hdrdir}/#{hdrname}", "")
+ src = "#{fwdir}/main.c"
+ File.write(src, "void #{fw}(void) {}\n")
+ cmd = LINK_SO.dup
+ RbConfig.expand(cmd, RbConfig::CONFIG.merge("OBJS"=>src))
+ cmd.gsub!("$@", "#{fwdir}/#{fw}")
+ cmd.gsub!(/ -bundle /, ' -dynamiclib ')
+ assert(xsystem(cmd), MKMFLOG)
+ $INCFLAGS << " " << "-F#{dir}".quote
+ yield fw, hdrname
end
+ end
- def test_single_framework
- assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
- end
+ def test_single_framework
+ assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
+ end
- def test_multi_frameworks
- assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
- create_framework("MkmfTest") do |fw|
- assert(have_framework(fw), MKMFLOG)
- end
+ def test_multi_frameworks
+ assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
+ create_framework("MkmfTest") do |fw|
+ assert(have_framework(fw), MKMFLOG)
end
+ end
- def test_empty_framework
- create_framework("MkmfTest") do |fw|
- assert(have_framework(fw), MKMFLOG)
- end
+ def test_empty_framework
+ create_framework("MkmfTest") do |fw|
+ assert(have_framework(fw), MKMFLOG)
end
+ end
- def test_different_name_header
- _bug8593 = '[ruby-core:55745] [Bug #8593]'
- create_framework("MkmfTest", "test_mkmf.h") do |fw, hdrname|
- assert(!have_framework(fw), MKMFLOG)
- assert(have_framework([fw, hdrname]), MKMFLOG)
- end
+ def test_different_name_header
+ _bug8593 = '[ruby-core:55745] [Bug #8593]'
+ create_framework("MkmfTest", "test_mkmf.h") do |fw, hdrname|
+ assert(!have_framework(fw), MKMFLOG)
+ assert(have_framework([fw, hdrname]), MKMFLOG)
end
end
end if /darwin/ =~ RUBY_PLATFORM
diff --git a/test/mkmf/test_have_func.rb b/test/mkmf/test_have_func.rb
index 6204ab24f0..521a0bb435 100644
--- a/test/mkmf/test_have_func.rb
+++ b/test/mkmf/test_have_func.rb
@@ -2,16 +2,14 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestHaveFunc < TestMkmf
- def test_have_func
- assert_equal(true, have_func("ruby_init"), MKMFLOG)
- assert_include($defs, '-DHAVE_RUBY_INIT')
- end
+class TestMkmfHaveFunc < TestMkmf
+ def test_have_func
+ assert_equal(true, have_func("ruby_init"), MKMFLOG)
+ assert_include($defs, '-DHAVE_RUBY_INIT')
+ end
- def test_not_have_func
- assert_equal(false, have_func("no_ruby_init"), MKMFLOG)
- assert_not_include($defs, '-DHAVE_RUBY_INIT')
- end
+ def test_not_have_func
+ assert_equal(false, have_func("no_ruby_init"), MKMFLOG)
+ assert_not_include($defs, '-DHAVE_RUBY_INIT')
end
end
diff --git a/test/mkmf/test_have_library.rb b/test/mkmf/test_have_library.rb
index bb9ce6972d..e34a9b06da 100644
--- a/test/mkmf/test_have_library.rb
+++ b/test/mkmf/test_have_library.rb
@@ -2,55 +2,53 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestHaveLibrary < TestMkmf
- LIBRARY_NAME = 'mkmftest'
- HEADER_NAME = "#{LIBRARY_NAME}.h"
- FUNC_NAME = 'ruby_mkmftest_foo'
- ARPREFIX = config_string('LIBRUBY_A') {|lib| lib[/\A\w+/]}
-
- def create_library(libname = LIBRARY_NAME)
- lib = "#{ARPREFIX}#{libname}.#{$LIBEXT}"
- open(HEADER_NAME, "w") do |hdr|
- hdr.puts "void #{FUNC_NAME}(void);"
- hdr.puts "void #{FUNC_NAME}_fake(void);"
- end
- create_tmpsrc("#include \"#{HEADER_NAME}\"\n""void #{FUNC_NAME}(void) {}")
- assert(xsystem(cc_command), "compile failed: #{cc_command}")
- command = "#{CONFIG['AR']} #{config_string('ARFLAGS') || 'cru '}#{lib} #{CONFTEST}.#{$OBJEXT}"
- assert(xsystem(command), "making library failed: #{command}")
- File.unlink("#{CONFTEST}.#{$OBJEXT}")
- config_string('RANLIB') do |ranlib|
- command = "#{ranlib} #{lib}"
- assert(xsystem(command), "ranlib failed: #{command}")
- end
+class TestMkmfHaveLibrary < TestMkmf
+ LIBRARY_NAME = 'mkmftest'
+ HEADER_NAME = "#{LIBRARY_NAME}.h"
+ FUNC_NAME = 'ruby_mkmftest_foo'
+ ARPREFIX = config_string('LIBRUBY_A') {|lib| lib[/\A\w+/]}
+
+ def create_library(libname = LIBRARY_NAME)
+ lib = "#{ARPREFIX}#{libname}.#{$LIBEXT}"
+ open(HEADER_NAME, "w") do |hdr|
+ hdr.puts "void #{FUNC_NAME}(void);"
+ hdr.puts "void #{FUNC_NAME}_fake(void);"
end
-
- def assert_have_library(*args)
- assert_equal(true, have_library(LIBRARY_NAME, *args), MKMFLOG)
+ create_tmpsrc("#include \"#{HEADER_NAME}\"\n""void #{FUNC_NAME}(void) {}")
+ assert(xsystem(cc_command), "compile failed: #{cc_command}")
+ command = "#{CONFIG['AR']} #{config_string('ARFLAGS') || 'cru '}#{lib} #{CONFTEST}.#{$OBJEXT}"
+ assert(xsystem(command), "making library failed: #{command}")
+ File.unlink("#{CONFTEST}.#{$OBJEXT}")
+ config_string('RANLIB') do |ranlib|
+ command = "#{ranlib} #{lib}"
+ assert(xsystem(command), "ranlib failed: #{command}")
end
+ end
- def assert_not_have_library(*args)
- assert_equal(false, have_library(LIBRARY_NAME, *args), MKMFLOG)
- end
+ def assert_have_library(*args)
+ assert_equal(true, have_library(LIBRARY_NAME, *args), MKMFLOG)
+ end
- def test_have_library
- create_library
- assert_have_library
- end
+ def assert_not_have_library(*args)
+ assert_equal(false, have_library(LIBRARY_NAME, *args), MKMFLOG)
+ end
- def test_have_library_with_name
- create_library
- assert_have_library(FUNC_NAME, HEADER_NAME)
- end
+ def test_have_library
+ create_library
+ assert_have_library
+ end
- def test_not_have_library
- assert_not_have_library
- end
+ def test_have_library_with_name
+ create_library
+ assert_have_library(FUNC_NAME, HEADER_NAME)
+ end
- def test_not_have_library_with_name
- create_library
- assert_not_have_library("#{FUNC_NAME}_fake", HEADER_NAME)
- end
+ def test_not_have_library
+ assert_not_have_library
+ end
+
+ def test_not_have_library_with_name
+ create_library
+ assert_not_have_library("#{FUNC_NAME}_fake", HEADER_NAME)
end
end
diff --git a/test/mkmf/test_have_macro.rb b/test/mkmf/test_have_macro.rb
index ebc5648097..3178bfea0b 100644
--- a/test/mkmf/test_have_macro.rb
+++ b/test/mkmf/test_have_macro.rb
@@ -2,35 +2,33 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestHaveMacro < TestMkmf
- MACRO_NAME = "RUBY_MKMFTEST_FOOBAR"
+class TestMkmfHaveMacro < TestMkmf
+ MACRO_NAME = "RUBY_MKMFTEST_FOOBAR"
- def test_have_macro_opt
- assert_equal(true, have_macro(MACRO_NAME, nil, "-D#{MACRO_NAME}"), MKMFLOG)
- end
+ def test_have_macro_opt
+ assert_equal(true, have_macro(MACRO_NAME, nil, "-D#{MACRO_NAME}"), MKMFLOG)
+ end
- def test_have_macro_header
- Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
- tmp.puts("#undef #{MACRO_NAME}")
- tmp.puts("#define #{MACRO_NAME} 1")
- tmp.close
- base = File.basename(tmp.path)
- assert_equal(true, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
- end
+ def test_have_macro_header
+ Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
+ tmp.puts("#undef #{MACRO_NAME}")
+ tmp.puts("#define #{MACRO_NAME} 1")
+ tmp.close
+ base = File.basename(tmp.path)
+ assert_equal(true, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
end
+ end
- def test_not_have_macro_opt
- assert_equal(false, have_macro(MACRO_NAME, nil, "-U#{MACRO_NAME}"), MKMFLOG)
- end
+ def test_not_have_macro_opt
+ assert_equal(false, have_macro(MACRO_NAME, nil, "-U#{MACRO_NAME}"), MKMFLOG)
+ end
- def test_not_have_macro_header
- Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
- tmp.puts("#undef #{MACRO_NAME}")
- tmp.close
- base = File.basename(tmp.path)
- assert_equal(false, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
- end
+ def test_not_have_macro_header
+ Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
+ tmp.puts("#undef #{MACRO_NAME}")
+ tmp.close
+ base = File.basename(tmp.path)
+ assert_equal(false, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
end
end
end
diff --git a/test/mkmf/test_have_var.rb b/test/mkmf/test_have_var.rb
deleted file mode 100644
index 5367ec2248..0000000000
--- a/test/mkmf/test_have_var.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: false
-require_relative 'base'
-require 'tempfile'
-
-class TestMkmf
- class TestHaveVar < TestMkmf
- def test_have_var
- assert_equal(true, have_var("ruby_version"), MKMFLOG)
- assert_include($defs, '-DHAVE_RUBY_VERSION')
- end
-
- def test_not_have_var
- assert_equal(false, have_var("rb_vm_something_flag"), MKMFLOG)
- assert_not_include($defs, '-DHAVE_RB_VM_SOMETHING_FLAG')
- end
- end
-end
diff --git a/test/mkmf/test_install.rb b/test/mkmf/test_install.rb
index 7f8c603d42..009d55f72d 100644
--- a/test/mkmf/test_install.rb
+++ b/test/mkmf/test_install.rb
@@ -1,27 +1,25 @@
# 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|
+class TestMkmfInstall < 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(
- ["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
+ ["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
diff --git a/test/mkmf/test_libs.rb b/test/mkmf/test_libs.rb
index 9c5e1d29fb..2f84d024e2 100644
--- a/test/mkmf/test_libs.rb
+++ b/test/mkmf/test_libs.rb
@@ -1,94 +1,92 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestLibs < TestMkmf
- def test_split_libs
- assert_equal(%w[-lfoo -lbar], split_libs("-lfoo -lbar"))
- end
+class TestMkmfLibs < TestMkmf
+ def test_split_libs
+ assert_equal(%w[-lfoo -lbar], split_libs("-lfoo -lbar"))
+ end
- def test_split_libs_macos
- assert_equal(%w[-ObjC -framework\ Ruby], split_libs("-ObjC -framework Ruby"), 'Bug #6987')
- end if /darwin/ =~ RUBY_PLATFORM
+ def test_split_libs_macos
+ assert_equal(%w[-ObjC -framework\ Ruby], split_libs("-ObjC -framework Ruby"), 'Bug #6987')
+ end if /darwin/ =~ RUBY_PLATFORM
- def test_split_libs_windows
- assert_equal(%w[zdll.lib libffi.lib], split_libs("zdll.lib libffi.lib"))
- end if /mswin/ =~ RUBY_PLATFORM
+ def test_split_libs_windows
+ assert_equal(%w[zdll.lib libffi.lib], split_libs("zdll.lib libffi.lib"))
+ end if /mswin/ =~ RUBY_PLATFORM
- def assert_in_order(array, x, y, mesg = nil)
- mesg = "#{x} must proceed to #{y}#{': ' if mesg}#{mesg}"
- assert_operator(array.index(x), :<, array.rindex(y), mesg)
- end
+ def assert_in_order(array, x, y, mesg = nil)
+ mesg = "#{x} must proceed to #{y}#{': ' if mesg}#{mesg}"
+ assert_operator(array.index(x), :<, array.rindex(y), mesg)
+ end
- def test_merge_simple
- bug = '[ruby-dev:21765]'
- assert_equal([], merge_libs(%w[]))
- assert_equal(%w[a b], merge_libs(%w[a], %w[b]))
- array = merge_libs(%w[a c], %w[b])
- assert_in_order(array, "a", "c", bug)
- end
+ def test_merge_simple
+ bug = '[ruby-dev:21765]'
+ assert_equal([], merge_libs(%w[]))
+ assert_equal(%w[a b], merge_libs(%w[a], %w[b]))
+ array = merge_libs(%w[a c], %w[b])
+ assert_in_order(array, "a", "c", bug)
+ end
- def test_merge_seq
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c d], %w[c b e])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "c", "b", bug)
- assert_in_order(array, "b", "e", bug)
- end
+ def test_merge_seq
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c d], %w[c b e])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "c", "b", bug)
+ assert_in_order(array, "b", "e", bug)
+ end
- def test_merge_seq_pre
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c d], %w[b c d e])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "b", "c", bug)
- assert_in_order(array, "d", "e", bug)
- end
+ def test_merge_seq_pre
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c d], %w[b c d e])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "b", "c", bug)
+ assert_in_order(array, "d", "e", bug)
+ end
- def test_merge_cyclic
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c d], %w[b c b])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "b", "c", bug)
- assert_in_order(array, "c", "b", bug)
- end
+ def test_merge_cyclic
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c d], %w[b c b])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "b", "c", bug)
+ assert_in_order(array, "c", "b", bug)
+ end
- def test_merge_cyclic_2
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c a d], %w[b c b])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "a", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "a", "d", bug)
- assert_in_order(array, "b", "c", bug)
- assert_in_order(array, "c", "b", bug)
- end
+ def test_merge_cyclic_2
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c a d], %w[b c b])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "a", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "a", "d", bug)
+ assert_in_order(array, "b", "c", bug)
+ assert_in_order(array, "c", "b", bug)
+ end
- def test_merge_reversal
- bug = '[ruby-dev:22440]'
- array = merge_libs(%w[a b c], %w[c d a])
- assert_in_order(array, "a", "b" , bug)
- assert_in_order(array, "c", "d" , bug)
- ## assume that a and c have no dependency
- end
+ def test_merge_reversal
+ bug = '[ruby-dev:22440]'
+ array = merge_libs(%w[a b c], %w[c d a])
+ assert_in_order(array, "a", "b" , bug)
+ assert_in_order(array, "c", "d" , bug)
+ ## assume that a and c have no dependency
+ end
- def test_merge_reversal_followed
- bug7467 = '[ruby-core:50314] [Bug #7467]'
- array = nil
- assert_nothing_raised(bug7467) {
- array = merge_libs(%w[a b c d e f g h], %w[d c d e], [])
- }
- assert_in_order(array, "a", "b", bug7467)
- assert_in_order(array, "b", "c", bug7467)
- assert_in_order(array, "c", "d", bug7467)
- assert_in_order(array, "d", "e", bug7467)
- assert_in_order(array, "e", "f", bug7467)
- assert_in_order(array, "f", "g", bug7467)
- assert_in_order(array, "g", "h", bug7467)
- assert_in_order(array, "d", "c", bug7467)
- assert_in_order(array, "c", "e", bug7467)
- end
+ def test_merge_reversal_followed
+ bug7467 = '[ruby-core:50314] [Bug #7467]'
+ array = nil
+ assert_nothing_raised(bug7467) {
+ array = merge_libs(%w[a b c d e f g h], %w[d c d e], [])
+ }
+ assert_in_order(array, "a", "b", bug7467)
+ assert_in_order(array, "b", "c", bug7467)
+ assert_in_order(array, "c", "d", bug7467)
+ assert_in_order(array, "d", "e", bug7467)
+ assert_in_order(array, "e", "f", bug7467)
+ assert_in_order(array, "f", "g", bug7467)
+ assert_in_order(array, "g", "h", bug7467)
+ assert_in_order(array, "d", "c", bug7467)
+ assert_in_order(array, "c", "e", bug7467)
end
end if RUBY_ENGINE == "ruby"
diff --git a/test/mkmf/test_mkmf.rb b/test/mkmf/test_mkmf.rb
index adb86eca8d..55f9aa3b88 100644
--- a/test/mkmf/test_mkmf.rb
+++ b/test/mkmf/test_mkmf.rb
@@ -2,14 +2,12 @@
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
+class TestMkmfGlobal < Test::Unit::TestCase
+ 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
diff --git a/test/mkmf/test_pkg_config.rb b/test/mkmf/test_pkg_config.rb
new file mode 100644
index 0000000000..f6a960c7d9
--- /dev/null
+++ b/test/mkmf/test_pkg_config.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: false
+require_relative 'base'
+require 'shellwords'
+
+class TestMkmfPkgConfig < TestMkmf
+ PKG_CONFIG = config_string("PKG_CONFIG") {|path| find_executable0(path)}
+
+ def setup
+ super
+
+ if PKG_CONFIG
+ @fixtures_dir = File.join(Dir.pwd, "fixtures")
+ @fixtures_lib_dir = File.join(@fixtures_dir, "lib")
+ @fixtures_inc_dir = File.join(@fixtures_dir, "include")
+
+ FileUtils.mkdir(@fixtures_dir)
+ File.write("fixtures/test1.pc", <<~EOF)
+ libdir=#{@fixtures_lib_dir}
+ includedir=#{@fixtures_inc_dir}
+
+ Name: test1
+ Description: Test for mkmf pkg-config method
+ Version: 1.2.3
+ Libs: -L${libdir} -ltest1-public
+ Libs.private: -ltest1-private
+ Cflags: -I${includedir}/cflags-I --cflags-other
+ EOF
+
+ @pkg_config_path, ENV["PKG_CONFIG_PATH"] = ENV["PKG_CONFIG_PATH"], @fixtures_dir
+ end
+ end
+
+ def teardown
+ if PKG_CONFIG
+ ENV["PKG_CONFIG_PATH"] = @pkg_config_path
+ end
+
+ super
+ end
+
+ def test_pkgconfig_with_option_returns_nil_on_error
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ assert_nil(pkg_config("package-does-not-exist", "exists"), MKMFLOG)
+ end
+
+ def test_pkgconfig_with_libs_option_returns_output
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ expected = ["-L#{@fixtures_lib_dir}", "-ltest1-public"].sort
+ actual = pkg_config("test1", "libs").shellsplit.sort
+ assert_equal(expected, actual, MKMFLOG)
+ end
+
+ def test_pkgconfig_with_cflags_option_returns_output
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ expected = ["--cflags-other", "-I#{@fixtures_inc_dir}/cflags-I"].sort
+ actual = pkg_config("test1", "cflags").shellsplit.sort
+ assert_equal(expected, actual, MKMFLOG)
+ end
+
+ def test_pkgconfig_with_multiple_options
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ expected = ["-L#{@fixtures_lib_dir}", "-ltest1-public", "-ltest1-private"].sort
+ actual = pkg_config("test1", "libs", "static").shellsplit.sort
+ assert_equal(expected, actual, MKMFLOG)
+ end
+end
diff --git a/test/mkmf/test_signedness.rb b/test/mkmf/test_signedness.rb
index 589dcb56e8..a59e3548a2 100644
--- a/test/mkmf/test_signedness.rb
+++ b/test/mkmf/test_signedness.rb
@@ -1,30 +1,28 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestSignedness < TestMkmf
- def test_typeof_builtin
- bug4144 = '[ruby-dev:42731]'
- [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
- %w[short int long].each do |type|
- assert_equal(expect.to_i, mkmf {check_signedness(signed+type)}, mkmflog(bug4144))
- end
+class TestMkmfSignedness < TestMkmf
+ def test_typeof_builtin
+ bug4144 = '[ruby-dev:42731]'
+ [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
+ %w[short int long].each do |type|
+ assert_equal(expect.to_i, mkmf {check_signedness(signed+type)}, mkmflog(bug4144))
end
end
+ end
- def test_typeof_typedef
- [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
- %w[short int long].each do |type|
- open("confdefs.h", "w") {|f|
- f.puts "typedef #{signed}#{type} test1_t;"
- }
- $defs.clear
- assert_equal(expect.to_i, mkmf {check_signedness("test1_t", "confdefs.h")}, MKMFLOG)
- assert_include($defs, "-DSIGNEDNESS_OF_TEST1_T=#{expect}")
- end
+ def test_typeof_typedef
+ [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
+ %w[short int long].each do |type|
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef #{signed}#{type} test1_t;"
+ }
+ $defs.clear
+ assert_equal(expect.to_i, mkmf {check_signedness("test1_t", "confdefs.h")}, MKMFLOG)
+ assert_include($defs, "-DSIGNEDNESS_OF_TEST1_T=#{expect}")
end
- ensure
- File.unlink("confdefs.h")
end
+ ensure
+ File.unlink("confdefs.h")
end
end
diff --git a/test/mkmf/test_sizeof.rb b/test/mkmf/test_sizeof.rb
index 742c3d6454..6fb0a6a8f6 100644
--- a/test/mkmf/test_sizeof.rb
+++ b/test/mkmf/test_sizeof.rb
@@ -1,48 +1,46 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestSizeof < TestMkmf
- def setup
- super
- @sizeof_short = config_value("SIZEOF_SHORT").to_i
- @sizeof_int = config_value("SIZEOF_INT").to_i
- @sizeof_long = config_value("SIZEOF_LONG").to_i
- @sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
- @sizeof___int64 = config_value("SIZEOF___INT64").to_i
- end
+class TestMkmfSizeof < TestMkmf
+ def setup
+ super
+ @sizeof_short = config_value("SIZEOF_SHORT").to_i
+ @sizeof_int = config_value("SIZEOF_INT").to_i
+ @sizeof_long = config_value("SIZEOF_LONG").to_i
+ @sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
+ @sizeof___int64 = config_value("SIZEOF___INT64").to_i
+ end
- def test_sizeof_builtin
- %w[char short int long float double void*].each do |type|
- assert_kind_of(Integer, mkmf {check_sizeof(type)}, MKMFLOG)
- end
- assert_operator(@sizeof_short, :<=, @sizeof_int)
- assert_operator(@sizeof_int, :<=, @sizeof_long)
- assert_operator(@sizeof_long, :<=, @sizeof_long_long) unless @sizeof_long_long.zero?
- assert_equal(8, @sizeof___int64) unless @sizeof___int64.zero?
+ def test_sizeof_builtin
+ %w[char short int long float double void*].each do |type|
+ assert_kind_of(Integer, mkmf {check_sizeof(type)}, MKMFLOG)
end
+ assert_operator(@sizeof_short, :<=, @sizeof_int)
+ assert_operator(@sizeof_int, :<=, @sizeof_long)
+ assert_operator(@sizeof_long, :<=, @sizeof_long_long) unless @sizeof_long_long.zero?
+ assert_equal(8, @sizeof___int64) unless @sizeof___int64.zero?
+ end
- def test_sizeof_struct
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {char x;} test1_t;"
- }
- assert_equal(1, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ def test_sizeof_struct
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {char x;} test1_t;"
+ }
+ assert_equal(1, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {char x, y;} test1_t;"
- }
- assert_equal(2, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {char x, y;} test1_t;"
+ }
+ assert_equal(2, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {int x;} test1_t;"
- }
- assert_equal(@sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {int x, y;} test1_t;"
- }
- assert_equal(2 * @sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- ensure
- File.unlink("confdefs.h")
- end
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {int x;} test1_t;"
+ }
+ assert_equal(@sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {int x, y;} test1_t;"
+ }
+ assert_equal(2 * @sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ ensure
+ File.unlink("confdefs.h")
end
end
diff --git a/test/net/fixtures/Makefile b/test/net/fixtures/Makefile
index b2bc9c7368..88c232e3b6 100644
--- a/test/net/fixtures/Makefile
+++ b/test/net/fixtures/Makefile
@@ -5,11 +5,11 @@ regen_certs:
make server.crt
cacert.pem: server.key
- openssl req -new -x509 -days 1825 -key server.key -out cacert.pem -text -subj "/C=JP/ST=Shimane/L=Matz-e city/O=Ruby Core Team/CN=Ruby Test CA/emailAddress=security@ruby-lang.org"
+ openssl req -new -x509 -days 3650 -key server.key -out cacert.pem -subj "/C=JP/ST=Shimane/L=Matz-e city/O=Ruby Core Team/CN=Ruby Test CA/emailAddress=security@ruby-lang.org"
server.csr:
- openssl req -new -key server.key -out server.csr -text -subj "/C=JP/ST=Shimane/O=Ruby Core Team/OU=Ruby Test/CN=localhost"
+ openssl req -new -key server.key -out server.csr -subj "/C=JP/ST=Shimane/O=Ruby Core Team/OU=Ruby Test/CN=localhost"
server.crt: server.csr cacert.pem
- openssl x509 -days 1825 -CA cacert.pem -CAkey server.key -set_serial 00 -in server.csr -req -text -out server.crt
+ openssl x509 -days 3650 -CA cacert.pem -CAkey server.key -set_serial 00 -in server.csr -req -out server.crt
rm server.csr
diff --git a/test/net/fixtures/cacert.pem b/test/net/fixtures/cacert.pem
index f623bd62ed..24c83f1c65 100644
--- a/test/net/fixtures/cacert.pem
+++ b/test/net/fixtures/cacert.pem
@@ -1,24 +1,24 @@
-----BEGIN CERTIFICATE-----
-MIID7TCCAtWgAwIBAgIJAIltvxrFAuSnMA0GCSqGSIb3DQEBCwUAMIGMMQswCQYD
-VQQGEwJKUDEQMA4GA1UECAwHU2hpbWFuZTEUMBIGA1UEBwwLTWF0ei1lIGNpdHkx
-FzAVBgNVBAoMDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDDAxSdWJ5IFRlc3QgQ0Ex
-JTAjBgkqhkiG9w0BCQEWFnNlY3VyaXR5QHJ1YnktbGFuZy5vcmcwHhcNMTkwMTAy
-MDI1ODI4WhcNMjQwMTAxMDI1ODI4WjCBjDELMAkGA1UEBhMCSlAxEDAOBgNVBAgM
-B1NoaW1hbmUxFDASBgNVBAcMC01hdHotZSBjaXR5MRcwFQYDVQQKDA5SdWJ5IENv
-cmUgVGVhbTEVMBMGA1UEAwwMUnVieSBUZXN0IENBMSUwIwYJKoZIhvcNAQkBFhZz
-ZWN1cml0eUBydWJ5LWxhbmcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAznlbjRVhz1NlutHVrhcGnK8W0qug2ujKXv1njSC4U6nJF6py7I9EeehV
-SaKePyv+I9z3K1LnfUHOtUbdwdKC77yN66A6q2aqzu5q09/NSykcZGOIF0GuItYI
-3nvW3IqBddff2ffsyR+9pBjfb5AIPP08WowF9q4s1eGULwZc4w2B8PFhtxYANd7d
-BvGLXFlcufv9tDtzyRi4t7eqxCRJkZQIZNZ6DHHIJrNxejOILfHLarI12yk8VK6L
-2LG4WgGqyeePiRyd1o1MbuiAFYqAwpXNUbRKg5NaZGwBHZk8UZ+uFKt1QMBURO5R
-WFy1c349jbWszTqFyL4Lnbg9HhAowQIDAQABo1AwTjAdBgNVHQ4EFgQU9tEiKdU9
-I9derQyc5nWPnc34nVMwHwYDVR0jBBgwFoAU9tEiKdU9I9derQyc5nWPnc34nVMw
-DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAxj7F/u3C3fgq24N7hGRA
-of7ClFQxGmo/IGT0AISzW3HiVYiFaikKhbO1NwD9aBpD8Zwe62sCqMh8jGV/b0+q
-aOORnWYNy2R6r9FkASAglmdF6xn3bhgGD5ls4pCvcG9FynGnGc24g6MrjFNrBYUS
-2iIZsg36i0IJswo/Dy6HLphCms2BMCD3DeWtfjePUiTmQHJo6HsQIKP/u4N4Fvee
-uMBInei2M4VU74fLXbmKl1F9AEX7JDP3BKSZG19Ch5pnUo4uXM1uNTGsi07P4Y0s
-K44+SKBC0bYEFbDK0eQWMrX3kIhkPxyIWhxdq9/NqPYjShuSEAhA6CSpmRg0pqc+
-mA==
+MIID+zCCAuOgAwIBAgIUGMvHl3EhtKPKcgc3NQSAYfFuC+8wDQYJKoZIhvcNAQEL
+BQAwgYwxCzAJBgNVBAYTAkpQMRAwDgYDVQQIDAdTaGltYW5lMRQwEgYDVQQHDAtN
+YXR6LWUgY2l0eTEXMBUGA1UECgwOUnVieSBDb3JlIFRlYW0xFTATBgNVBAMMDFJ1
+YnkgVGVzdCBDQTElMCMGCSqGSIb3DQEJARYWc2VjdXJpdHlAcnVieS1sYW5nLm9y
+ZzAeFw0yNDAxMDExMTQ3MjNaFw0zMzEyMjkxMTQ3MjNaMIGMMQswCQYDVQQGEwJK
+UDEQMA4GA1UECAwHU2hpbWFuZTEUMBIGA1UEBwwLTWF0ei1lIGNpdHkxFzAVBgNV
+BAoMDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDDAxSdWJ5IFRlc3QgQ0ExJTAjBgkq
+hkiG9w0BCQEWFnNlY3VyaXR5QHJ1YnktbGFuZy5vcmcwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/tL4FI5sjqont9ABVI
++1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv8JmM/Y5vQt2lis0f
+qXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY7JRVcbB4khUN3Gp0
+yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjdi8mH6uG/icq4XuIe
+NWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSEonWW4HtLbtmS8He1
+JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMBAAGjUzBRMB0GA1Ud
+DgQWBBSJGVleDvFp9cu9R+E0/OKYzGkwkTAfBgNVHSMEGDAWgBSJGVleDvFp9cu9
+R+E0/OKYzGkwkTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBl
+8GLB8skAWlkSw/FwbUmEV3zyqu+p7PNP5YIYoZs0D74e7yVulGQ6PKMZH5hrZmHo
+orFSQU+VUUirG8nDGj7Rzce8WeWBxsaDGC8CE2dq6nC6LuUwtbdMnBrH0LRWAz48
+jGFF3jHtVz8VsGfoZTZCjukWqNXvU6hETT9GsfU+PZqbqcTVRPH52+XgYayKdIbD
+r97RM4X3+aXBHcUW0b76eyyi65RR/Xtvn8ioZt2AdX7T2tZzJyXJN3Hupp77s6Ui
+AZR35SToHCZeTZD12YBvLBdaTPLZN7O/Q/aAO9ZiJaZ7SbFOjz813B2hxXab4Fob
+2uJX6eMWTVxYK5D4M9lm
-----END CERTIFICATE-----
diff --git a/test/net/fixtures/server.crt b/test/net/fixtures/server.crt
index 5ca78a6d14..5d2923795d 100644
--- a/test/net/fixtures/server.crt
+++ b/test/net/fixtures/server.crt
@@ -1,82 +1,21 @@
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 2 (0x2)
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=JP, ST=Shimane, L=Matz-e city, O=Ruby Core Team, CN=Ruby Test CA/emailAddress=security@ruby-lang.org
- Validity
- Not Before: Jan 2 03:27:13 2019 GMT
- Not After : Jan 1 03:27:13 2024 GMT
- Subject: C=JP, ST=Shimane, O=Ruby Core Team, OU=Ruby Test, CN=localhost
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:e8:da:9c:01:2e:2b:10:ec:49:cd:5e:07:13:07:
- 9c:70:9e:c6:74:bc:13:c2:e1:6f:c6:82:fd:e3:48:
- e0:2c:a5:68:c7:9e:42:de:60:54:65:e6:6a:14:57:
- 7a:30:d0:cc:b5:b6:d9:c3:d2:df:c9:25:97:54:67:
- cf:f6:be:5e:cb:8b:ee:03:c5:e1:e2:f9:e7:f7:d1:
- 0c:47:f0:b8:da:33:5a:ad:41:ad:e7:b5:a2:7b:b7:
- bf:30:da:60:f8:e3:54:a2:bc:3a:fd:1b:74:d9:dc:
- 74:42:e9:29:be:df:ac:b4:4f:eb:32:f4:06:f1:e1:
- 8c:4b:a8:8b:fb:29:e7:b1:bf:1d:01:ee:73:0f:f9:
- 40:dc:d5:15:79:d9:c6:73:d0:c0:dd:cb:e4:da:19:
- 47:80:c6:14:04:72:fd:9a:7c:8f:11:82:76:49:04:
- 79:cc:f2:5c:31:22:95:13:3e:5d:40:a6:4d:e0:a3:
- 02:26:7d:52:3b:bb:ed:65:a1:0f:ed:6b:b0:3c:d4:
- de:61:15:5e:d3:dd:68:09:9f:4a:57:a5:c2:a9:6d:
- 86:92:c5:f4:a4:d4:b7:13:3b:52:63:24:05:e2:cc:
- e3:8a:3c:d4:35:34:2b:10:bb:58:72:e7:e1:8d:1d:
- 74:8c:61:16:20:3d:d0:1c:4e:8f:6e:fd:fe:64:10:
- 4f:41
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
- X509v3 Subject Key Identifier:
- ED:28:C2:7E:AB:4B:C8:E8:FE:55:6D:66:95:31:1C:2D:60:F9:02:36
- X509v3 Authority Key Identifier:
- keyid:F6:D1:22:29:D5:3D:23:D7:5E:AD:0C:9C:E6:75:8F:9D:CD:F8:9D:53
-
- Signature Algorithm: sha256WithRSAEncryption
- 1d:b8:c5:8b:72:41:20:65:ad:27:6f:15:63:06:26:12:8d:9c:
- ad:ca:f4:db:97:b4:90:cb:ff:35:94:bb:2a:a7:a1:ab:1e:35:
- 2d:a5:3f:c9:24:b0:1a:58:89:75:3e:81:0a:2c:4f:98:f9:51:
- fb:c0:a3:09:d0:0a:9b:e7:a2:b7:c3:60:40:c8:f4:6d:b2:6a:
- 56:12:17:4c:00:24:31:df:9c:60:ae:b1:68:54:a9:e6:b5:4a:
- 04:e6:92:05:86:d9:5a:dc:96:30:a5:58:de:14:99:0f:e5:15:
- 89:3e:9b:eb:80:e3:bd:83:c3:ea:33:35:4b:3e:2f:d3:0d:64:
- 93:67:7f:8d:f5:3f:0c:27:bc:37:5a:cc:d6:47:16:af:5a:62:
- d2:da:51:f8:74:06:6b:24:ad:28:68:08:98:37:7d:ed:0e:ab:
- 1e:82:61:05:d0:ba:75:a0:ab:21:b0:9a:fd:2b:54:86:1d:0d:
- 1f:c2:d4:77:1f:72:26:5e:ad:8a:9f:09:36:6d:44:be:74:c2:
- 5a:3e:ff:5c:9d:75:d6:38:7b:c5:39:f9:44:6e:a1:d1:8e:ff:
- 63:db:c4:bb:c6:91:92:ca:5c:60:9b:1d:eb:0a:de:08:ee:bf:
- da:76:03:65:62:29:8b:f8:7f:c7:86:73:1e:f6:1f:2d:89:69:
- fd:be:bd:6e
-----BEGIN CERTIFICATE-----
-MIID4zCCAsugAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCSlAx
-EDAOBgNVBAgMB1NoaW1hbmUxFDASBgNVBAcMC01hdHotZSBjaXR5MRcwFQYDVQQK
-DA5SdWJ5IENvcmUgVGVhbTEVMBMGA1UEAwwMUnVieSBUZXN0IENBMSUwIwYJKoZI
-hvcNAQkBFhZzZWN1cml0eUBydWJ5LWxhbmcub3JnMB4XDTE5MDEwMjAzMjcxM1oX
-DTI0MDEwMTAzMjcxM1owYDELMAkGA1UEBhMCSlAxEDAOBgNVBAgMB1NoaW1hbmUx
-FzAVBgNVBAoMDlJ1YnkgQ29yZSBUZWFtMRIwEAYDVQQLDAlSdWJ5IFRlc3QxEjAQ
-BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AOjanAEuKxDsSc1eBxMHnHCexnS8E8Lhb8aC/eNI4CylaMeeQt5gVGXmahRXejDQ
-zLW22cPS38kll1Rnz/a+XsuL7gPF4eL55/fRDEfwuNozWq1Bree1onu3vzDaYPjj
-VKK8Ov0bdNncdELpKb7frLRP6zL0BvHhjEuoi/sp57G/HQHucw/5QNzVFXnZxnPQ
-wN3L5NoZR4DGFARy/Zp8jxGCdkkEeczyXDEilRM+XUCmTeCjAiZ9Uju77WWhD+1r
-sDzU3mEVXtPdaAmfSlelwqlthpLF9KTUtxM7UmMkBeLM44o81DU0KxC7WHLn4Y0d
-dIxhFiA90BxOj279/mQQT0ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhC
-AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFO0o
-wn6rS8jo/lVtZpUxHC1g+QI2MB8GA1UdIwQYMBaAFPbRIinVPSPXXq0MnOZ1j53N
-+J1TMA0GCSqGSIb3DQEBCwUAA4IBAQAduMWLckEgZa0nbxVjBiYSjZytyvTbl7SQ
-y/81lLsqp6GrHjUtpT/JJLAaWIl1PoEKLE+Y+VH7wKMJ0Aqb56K3w2BAyPRtsmpW
-EhdMACQx35xgrrFoVKnmtUoE5pIFhtla3JYwpVjeFJkP5RWJPpvrgOO9g8PqMzVL
-Pi/TDWSTZ3+N9T8MJ7w3WszWRxavWmLS2lH4dAZrJK0oaAiYN33tDqsegmEF0Lp1
-oKshsJr9K1SGHQ0fwtR3H3ImXq2Knwk2bUS+dMJaPv9cnXXWOHvFOflEbqHRjv9j
-28S7xpGSylxgmx3rCt4I7r/adgNlYimL+H/HhnMe9h8tiWn9vr1u
+MIIDYTCCAkkCAQAwDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAkpQMRAwDgYD
+VQQIDAdTaGltYW5lMRQwEgYDVQQHDAtNYXR6LWUgY2l0eTEXMBUGA1UECgwOUnVi
+eSBDb3JlIFRlYW0xFTATBgNVBAMMDFJ1YnkgVGVzdCBDQTElMCMGCSqGSIb3DQEJ
+ARYWc2VjdXJpdHlAcnVieS1sYW5nLm9yZzAeFw0yNDAxMDExMTQ3MjNaFw0zMzEy
+MjkxMTQ3MjNaMGAxCzAJBgNVBAYTAkpQMRAwDgYDVQQIDAdTaGltYW5lMRcwFQYD
+VQQKDA5SdWJ5IENvcmUgVGVhbTESMBAGA1UECwwJUnVieSBUZXN0MRIwEAYDVQQD
+DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw+egZ
+Q6eumJKq3hfKfED4dE/tL4FI5sjqont9ABVI+1GSqyi1bFBgsRjM0THllIdMbKmJ
+tWwnKW8J+5OgNN8y6Xxv8JmM/Y5vQt2lis0fqXmG8UTz0VTWdlAXXmhUs6lSADvA
+aIe4RVrCsZ97L3ZQTryY7JRVcbB4khUN3Gp0yg+801SXzoFTTa+UGIRLE66jH51a
+a5VXu99hnv1OiH8tQrjdi8mH6uG/icq4XuIeNWMF32wHqIOOPvQcWV3M5D2vxJEj
+702Ku6k9OQXkAo17qRSEonWW4HtLbtmS8He1JNPc/n3dVUm+fM6NoDXPoLP7j55G
+9zKyqGtGAWXAj1MTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACtGNdj5TEtnJBYp
+M+LhBeU3oNteldfycEm993gJp6ghWZFg23oX8fVmyEeJr/3Ca9bAgDqg0t9a0npN
+oWKEY6wVKqcHgu3gSvThF5c9KhGbeDDmlTSVVNQmXWX0K2d4lS2cwZHH8mCm2mrY
+PDqlEkSc7k4qSiqigdS8i80Yk+lDXWsm8CjsiC93qaRM7DnS0WPQR0c16S95oM6G
+VklFKUSDAuFjw9aVWA/nahOucjn0w5fVW6lyIlkBslC1ChlaDgJmvhz+Ol3iMsE0
+kAmFNu2KKPVrpMWaBID49QwQTDyhetNLaVVFM88iUdA9JDoVMEuP1mm39JqyzHTu
+uBrdP4Q=
-----END CERTIFICATE-----
diff --git a/test/net/fixtures/server.key b/test/net/fixtures/server.key
index 7f2380e71e..6a83d5bcf4 100644
--- a/test/net/fixtures/server.key
+++ b/test/net/fixtures/server.key
@@ -1,28 +1,27 @@
------BEGIN PRIVATE KEY-----
-MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDo2pwBLisQ7EnN
-XgcTB5xwnsZ0vBPC4W/Ggv3jSOAspWjHnkLeYFRl5moUV3ow0My1ttnD0t/JJZdU
-Z8/2vl7Li+4DxeHi+ef30QxH8LjaM1qtQa3ntaJ7t78w2mD441SivDr9G3TZ3HRC
-6Sm+36y0T+sy9Abx4YxLqIv7Keexvx0B7nMP+UDc1RV52cZz0MDdy+TaGUeAxhQE
-cv2afI8RgnZJBHnM8lwxIpUTPl1Apk3gowImfVI7u+1loQ/ta7A81N5hFV7T3WgJ
-n0pXpcKpbYaSxfSk1LcTO1JjJAXizOOKPNQ1NCsQu1hy5+GNHXSMYRYgPdAcTo9u
-/f5kEE9BAgMBAAECggEBAOHkwhc7DLh8IhTDNSW26oMu5OP2WU1jmiYAigDmf+OQ
-DBgrZj+JQBci8qINQxL8XLukSZn5hvQCLc7Kbyu1/wyEEUFDxSGGwwzclodr9kho
-LX2LDASPZrOSzD2+fPi2wTKmXKuS6Uc44OjQfZkYMNkz9r4Vkm8xGgOD3VipjIYX
-QXlhhdqkXZcNABsihCV52GKkDFSVm8jv95YJc5xhoYCy/3a4/qPdF0aT2R7oYUej
-hKrxVDskyooe8Zg/JTydZNV5GQEDmW01/K3r6XGT26oPi1AqMU1gtv/jkW56CRQQ
-1got8smnqM+AV7Slf9R6DauIPdQJ2S8wsr/o8ISBsOECgYEA9YrqEP2gAYSGFXRt
-liw0WI2Ant8BqXS6yvq1jLo/qWhLw/ph4Di73OQ2mpycVTpgfGr2wFPQR1XJ+0Fd
-U+Ir/C3Q7FK4VIGHK7B0zNvZr5tEjlFfeRezo2JMVw5YWeSagIFcSwK+KqCTH9qc
-pw/Eb8nB/4XNcpTZu7Fg0Wc+ooUCgYEA8sVaicn1Wxkpb45a4qfrA6wOr5xdJ4cC
-A5qs7vjX2OdPIQOmoQhdI7bCWFXZzF33wA4YCws6j5wRaySLIJqdms8Gl9QnODy1
-ZlA5gwKToBC/jqPmWAXSKb8EH7cHilaxU9OKnQ7CfwlGLHqjMtjrhR7KHlt3CVRs
-oRmvsjZVXI0CgYAmPedslAO6mMhFSSfULrhMXmV82OCqYrrA6EEkVNGbcdnzAOkD
-gfKIWabDd8bFY10po4Mguy0CHzNhBXIioWQWV5BlbhC1YKMLw+S9DzSdLAKGY9gJ
-xQ4+UQ3wtRQ/k+IYR413RUsW2oFvgZ3KSyNeAb9MK6uuv84VdG/OzVSs/QKBgQDn
-kap//l2EbObiWyaERunckdVcW0lcN+KK75J/TGwPoOwQsLvTpPe65kxRGGrtDsEQ
-uCDk/+v3KkZPLgdrrTAih9FhJ+PVN8tMcb+6IM4SA4fFFr/UPJEwct0LJ3oQ0grJ
-y+HPWFHb/Uurh7t99/4H98uR02sjQh1wOeEmm78mzQKBgQDm+LzGH0se6CXQ6cdZ
-g1JRZeXkDEsrW3hfAsW62xJQmXcWxBoblP9OamMY+A06rM5og3JbDk5Zm6JsOaA8
-wS2gw4ilp46jors4eQey8ux7kB9LzdBoDBBElnsbjLO8oBNZlVcYXg+6BOl/CUi7
-2whRF0FEjKA8ehrNhAq+VFfFNw==
------END PRIVATE KEY-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso
+tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE
+89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU
+l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s
+B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59
+3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+
+dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI
+FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J
+aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2
+BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx
+IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/
+fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u
+pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT
+Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl
+u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD
+fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X
+Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE
+k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo
+qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS
+CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ
+XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw
+AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r
+UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0
+2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5
+7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3
+-----END RSA PRIVATE KEY-----
diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb
index c859021956..eb7d3e672c 100644
--- a/test/net/http/test_http.rb
+++ b/test/net/http/test_http.rb
@@ -126,10 +126,10 @@ class TestNetHTTP < Test::Unit::TestCase
def test_proxy_address_no_proxy
TestNetHTTPUtils.clean_http_proxy_env do
- http = Net::HTTP.new 'hostname.example', nil, 'proxy.example', nil, nil, nil, 'example'
+ http = Net::HTTP.new 'hostname.example', nil, 'proxy.com', nil, nil, nil, 'example'
assert_nil http.proxy_address
- http = Net::HTTP.new '10.224.1.1', nil, 'proxy.example', nil, nil, nil, 'example,10.224.0.0/22'
+ http = Net::HTTP.new '10.224.1.1', nil, 'proxy.com', nil, nil, nil, 'example,10.224.0.0/22'
assert_nil http.proxy_address
end
end
@@ -178,13 +178,8 @@ class TestNetHTTP < Test::Unit::TestCase
http = Net::HTTP.new 'hostname.example'
assert_equal true, http.proxy?
- if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE
- assert_equal 'foo', http.proxy_user
- assert_equal 'bar', http.proxy_pass
- else
- assert_nil http.proxy_user
- assert_nil http.proxy_pass
- end
+ assert_equal 'foo', http.proxy_user
+ assert_equal 'bar', http.proxy_pass
end
end
@@ -195,13 +190,8 @@ class TestNetHTTP < Test::Unit::TestCase
http = Net::HTTP.new 'hostname.example'
assert_equal true, http.proxy?
- if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE
- assert_equal "Y\\X", http.proxy_user
- assert_equal "R%S] ?X", http.proxy_pass
- else
- assert_nil http.proxy_user
- assert_nil http.proxy_pass
- end
+ assert_equal "Y\\X", http.proxy_user
+ assert_equal "R%S] ?X", http.proxy_pass
end
end
@@ -559,7 +549,7 @@ module TestNetHTTP_version_1_1_methods
conn = Net::HTTP.new('localhost', port)
conn.write_timeout = EnvUtil.apply_timeout_scale(0.01)
conn.read_timeout = EnvUtil.apply_timeout_scale(0.01) if windows?
- conn.open_timeout = EnvUtil.apply_timeout_scale(0.1)
+ conn.open_timeout = EnvUtil.apply_timeout_scale(1)
th = Thread.new do
err = !windows? ? Net::WriteTimeout : Net::ReadTimeout
@@ -583,9 +573,9 @@ module TestNetHTTP_version_1_1_methods
port = server.addr[1]
conn = Net::HTTP.new('localhost', port)
- conn.write_timeout = 0.01
- conn.read_timeout = 0.01 if windows?
- conn.open_timeout = 0.1
+ conn.write_timeout = EnvUtil.apply_timeout_scale(0.01)
+ conn.read_timeout = EnvUtil.apply_timeout_scale(0.01) if windows?
+ conn.open_timeout = EnvUtil.apply_timeout_scale(1)
req = Net::HTTP::Post.new('/')
data = "a"*50_000_000
@@ -1168,6 +1158,30 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase
}
end
+ def test_keep_alive_reset_on_new_connection
+ # Using WEBrick's debug log output on accepting connection:
+ #
+ # "[2021-04-29 20:36:46] DEBUG accept: 127.0.0.1:50674\n"
+ @log_tester = nil
+ @server.logger.level = WEBrick::BasicLog::DEBUG
+
+ start {|http|
+ res = http.get('/')
+ http.keep_alive_timeout = 1
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ http.finish
+ assert_equal 1, @log.grep(/accept/i).size
+
+ sleep 1.5
+ http.start
+ res = http.get('/')
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ assert_equal 2, @log.grep(/accept/i).size
+ }
+ end
+
class MockSocket
attr_reader :count
def initialize(success_after: nil)
@@ -1235,7 +1249,7 @@ end
class TestNetHTTPLocalBind < Test::Unit::TestCase
CONFIG = {
- 'host' => 'localhost',
+ 'host' => '127.0.0.1',
'proxy_host' => nil,
'proxy_port' => nil,
}
@@ -1270,3 +1284,87 @@ class TestNetHTTPLocalBind < Test::Unit::TestCase
end
end
+class TestNetHTTPForceEncoding < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+
+ def fe_request(force_enc, content_type=nil)
+ @server.mount_proc('/fe') do |req, res|
+ res['Content-Type'] = content_type if content_type
+ res.body = "hello\u1234"
+ end
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ http.local_host = Addrinfo.tcp(config('host'), config('port')).ip_address
+ assert_not_nil(http.local_host)
+ assert_nil(http.local_port)
+
+ http.response_body_encoding = force_enc
+ http.get('/fe')
+ end
+
+ def test_response_body_encoding_false
+ res = fe_request(false)
+ assert_equal("hello\u1234".b, res.body)
+ assert_equal(Encoding::ASCII_8BIT, res.body.encoding)
+ end
+
+ def test_response_body_encoding_true_without_content_type
+ res = fe_request(true)
+ assert_equal("hello\u1234".b, res.body)
+ assert_equal(Encoding::ASCII_8BIT, res.body.encoding)
+ end
+
+ def test_response_body_encoding_true_with_content_type
+ res = fe_request(true, 'text/html; charset=utf-8')
+ assert_equal("hello\u1234", res.body)
+ assert_equal(Encoding::UTF_8, res.body.encoding)
+ end
+
+ def test_response_body_encoding_string_without_content_type
+ res = fe_request('utf-8')
+ assert_equal("hello\u1234", res.body)
+ assert_equal(Encoding::UTF_8, res.body.encoding)
+ end
+
+ def test_response_body_encoding_encoding_without_content_type
+ res = fe_request(Encoding::UTF_8)
+ assert_equal("hello\u1234", res.body)
+ assert_equal(Encoding::UTF_8, res.body.encoding)
+ end
+end
+
+class TestNetHTTPPartialResponse < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+
+ def test_partial_response
+ str = "0123456789"
+ @server.mount_proc('/') do |req, res|
+ res.status = 200
+ res['Content-Type'] = 'text/plain'
+
+ res.body = str
+ res['Content-Length'] = str.length + 1
+ end
+ @server.mount_proc('/show_ip') { |req, res| res.body = req.remote_ip }
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ res = http.get('/')
+ assert_equal(str, res.body)
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ http.ignore_eof = false
+ assert_raise(EOFError) {http.get('/')}
+ end
+end
diff --git a/test/net/http/test_http_request.rb b/test/net/http/test_http_request.rb
index 239b2d1009..7fd82b0353 100644
--- a/test/net/http/test_http_request.rb
+++ b/test/net/http/test_http_request.rb
@@ -46,8 +46,9 @@ class HTTPRequestTest < Test::Unit::TestCase
assert_not_predicate req, :response_body_permitted?
expected = {
- 'accept' => %w[*/*],
- 'user-agent' => %w[Ruby],
+ 'accept' => %w[*/*],
+ "accept-encoding" => %w[gzip;q=1.0,deflate;q=0.6,identity;q=0.3],
+ 'user-agent' => %w[Ruby],
}
assert_equal expected, req.to_hash
diff --git a/test/net/http/test_httpheader.rb b/test/net/http/test_httpheader.rb
index cfbe36bcfd..69563168db 100644
--- a/test/net/http/test_httpheader.rb
+++ b/test/net/http/test_httpheader.rb
@@ -28,7 +28,11 @@ class HTTPHeaderTest < Test::Unit::TestCase
assert_raise(NoMethodError){ @c.initialize_http_header("foo"=>[]) }
assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\nb") }
assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\rb") }
- assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\xff") }
+ end
+
+ def test_initialize_with_broken_coderange
+ error = RUBY_VERSION >= "3.2" ? Encoding::CompatibilityError : ArgumentError
+ assert_raise(error){ @c.initialize_http_header("foo"=>"a\xff") }
end
def test_initialize_with_symbol
@@ -308,6 +312,18 @@ class HTTPHeaderTest < Test::Unit::TestCase
end
def test_content_range
+ @c['Content-Range'] = "bytes 0-499/1000"
+ assert_equal 0..499, @c.content_range
+ @c['Content-Range'] = "bytes 1-500/1000"
+ assert_equal 1..500, @c.content_range
+ @c['Content-Range'] = "bytes 1-1/1000"
+ assert_equal 1..1, @c.content_range
+ @c['Content-Range'] = "tokens 1-1/1000"
+ assert_equal nil, @c.content_range
+
+ try_invalid_content_range "invalid"
+ try_invalid_content_range "bytes 123-abc"
+ try_invalid_content_range "bytes abc-123"
end
def test_range_length
@@ -317,6 +333,15 @@ class HTTPHeaderTest < Test::Unit::TestCase
assert_equal 500, @c.range_length
@c['Content-Range'] = "bytes 1-1/1000"
assert_equal 1, @c.range_length
+ @c['Content-Range'] = "tokens 1-1/1000"
+ assert_equal nil, @c.range_length
+
+ try_invalid_content_range "bytes 1-1/abc"
+ end
+
+ def try_invalid_content_range(s)
+ @c['Content-Range'] = "#{s}"
+ assert_raise(Net::HTTPHeaderSyntaxError, s){ @c.content_range }
end
def test_chunked?
diff --git a/test/net/http/test_httpresponse.rb b/test/net/http/test_httpresponse.rb
index cb86b54648..01281063cd 100644
--- a/test/net/http/test_httpresponse.rb
+++ b/test/net/http/test_httpresponse.rb
@@ -54,6 +54,241 @@ EOS
assert_equal 'hello', body
end
+ def test_read_body_body_encoding_false
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234".b, body
+ assert_equal Encoding::ASCII_8BIT, body.encoding
+ end
+
+ def test_read_body_body_encoding_encoding
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = Encoding.find('utf-8')
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234", body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_string
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = 'utf-8'
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234", body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_without_content_type_header
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234".b, body
+ assert_equal Encoding::ASCII_8BIT, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_utf8_content_type_header
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+Content-Type: text/plain; charset=utf-8
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234", body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_iso_8859_1_content_type_header
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+Content-Type: text/plain; charset=iso-8859-1
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234".force_encoding("ISO-8859-1"), body
+ assert_equal Encoding::ISO_8859_1, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_utf8_meta_charset
+ res_body = "<html><meta charset=\"utf-8\">hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body, body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_iso8859_1_meta_charset
+ res_body = "<html><meta charset=\"iso-8859-1\">hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body.force_encoding("ISO-8859-1"), body
+ assert_equal Encoding::ISO_8859_1, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_utf8_meta_content_charset
+ res_body = "<meta http-equiv='content-type' content='text/html; charset=UTF-8'>hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body, body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_iso8859_1_meta_content_charset
+ res_body = "<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body.force_encoding("ISO-8859-1"), body
+ assert_equal Encoding::ISO_8859_1, body.encoding
+ end
+
def test_read_body_block
io = dummy_io(<<EOS)
HTTP/1.1 200 OK
@@ -77,9 +312,9 @@ EOS
end
def test_read_body_block_mod
- # http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/3019353
- if defined?(RubyVM::JIT) ? RubyVM::JIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
- skip 'too unstable with --jit-wait, and extending read_timeout did not help it'
+ # http://ci.rvm.jp/results/trunk-rjit-wait@silicon-docker/3019353
+ if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ omit 'too unstable with --jit-wait, and extending read_timeout did not help it'
end
IO.pipe do |r, w|
buf = 'x' * 1024
@@ -127,9 +362,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal '5', res['content-length']
assert_equal 'hello', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal '13', res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body
end
end
@@ -155,9 +392,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal '5', res['content-length']
assert_equal 'hello', body
else
assert_equal 'DEFLATE', res['content-encoding']
+ assert_equal '13', res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body
end
end
@@ -188,9 +427,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal 'hello', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body
end
end
@@ -215,6 +456,7 @@ EOS
end
assert_equal 'deflate', res['content-encoding'], 'Bug #7831'
+ assert_equal '13', res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body, 'Bug #7381'
end
@@ -238,9 +480,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal 'hello', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15\r\n", body
end
end
@@ -288,9 +532,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal '0', res['content-length']
assert_equal '', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal '0', res['content-length']
assert_equal '', body
end
end
@@ -314,9 +560,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal '', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal '', body
end
end
@@ -341,6 +589,41 @@ EOS
assert_equal 'hello', body
end
+ def test_read_body_receiving_no_body
+ io = dummy_io(<<EOS)
+HTTP/1.1 204 OK
+Connection: close
+
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = 'utf-8'
+
+ body = 'something to override'
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal nil, body
+ assert_equal nil, res.body
+ end
+
+ def test_read_body_outside_of_reading_body
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: 0
+
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+
+ assert_raise IOError do
+ res.read_body
+ end
+ end
+
def test_uri_equals
uri = URI 'http://example'
diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb
index 4dc9f1b026..6ce43b03d5 100644
--- a/test/net/http/test_https.rb
+++ b/test/net/http/test_https.rb
@@ -23,7 +23,7 @@ class TestNetHTTPS < Test::Unit::TestCase
TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) }
CONFIG = {
- 'host' => HOST,
+ 'host' => HOST_IP,
'proxy_host' => nil,
'proxy_port' => nil,
'ssl_enable' => true,
@@ -137,7 +137,7 @@ class TestNetHTTPS < Test::Unit::TestCase
def test_session_reuse
# 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.
- skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/
+ omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h')
http = Net::HTTP.new(HOST, config("port"))
http.use_ssl = true
@@ -148,33 +148,35 @@ class TestNetHTTPS < Test::Unit::TestCase
# 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
+ http.ssl_version = :TLSv1_2
end
http.start
- assert_equal false, http.instance_variable_get(:@socket).io.session_reused?
+ session_reused = http.instance_variable_get(:@socket).io.session_reused?
+ assert_false session_reused unless session_reused.nil? # can not detect re-use under JRuby
http.get("/")
http.finish
http.start
- assert_equal true, http.instance_variable_get(:@socket).io.session_reused?
+ session_reused = http.instance_variable_get(:@socket).io.session_reused?
+ assert_true session_reused unless session_reused.nil? # can not detect re-use under JRuby
assert_equal $test_net_http_data, http.get("/").body
http.finish
end
def test_session_reuse_but_expire
# FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h.
- skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/
+ omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h')
http = Net::HTTP.new(HOST, config("port"))
http.use_ssl = true
http.cert_store = TEST_STORE
- http.ssl_timeout = -1
+ http.ssl_timeout = 1
http.start
http.get("/")
http.finish
-
+ sleep 1.25
http.start
http.get("/")
@@ -301,7 +303,7 @@ class TestNetHTTPS < Test::Unit::TestCase
ex = assert_raise(OpenSSL::SSL::SSLError){
http.request_get("/") {|res| }
}
- re_msg = /\ASSL_connect returned=1 errno=0 |SSL_CTX_set_max_proto_version/
+ re_msg = /\ASSL_connect returned=1 errno=0 |SSL_CTX_set_max_proto_version|No appropriate protocol/
assert_match(re_msg, ex.message)
end
diff --git a/test/net/http/test_https_proxy.rb b/test/net/http/test_https_proxy.rb
index f833f1a1e3..4c2a92ccd6 100644
--- a/test/net/http/test_https_proxy.rb
+++ b/test/net/http/test_https_proxy.rb
@@ -10,7 +10,7 @@ class HTTPSProxyTest < Test::Unit::TestCase
begin
OpenSSL
rescue LoadError
- skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ omit 'autoload problem. see [ruby-dev:45021][Bug #5786]'
end
TCPServer.open("127.0.0.1", 0) {|serv|
diff --git a/test/net/protocol/test_protocol.rb b/test/net/protocol/test_protocol.rb
index d3dc2ccf4c..2f42fa3236 100644
--- a/test/net/protocol/test_protocol.rb
+++ b/test/net/protocol/test_protocol.rb
@@ -57,6 +57,14 @@ class TestProtocol < Test::Unit::TestCase
mockio
end
+ def test_readuntil
+ assert_output("", "") do
+ sio = StringIO.new("12345".dup)
+ io = Net::BufferedIO.new(sio)
+ assert_equal "12345", io.readuntil("5")
+ end
+ end
+
def test_write0_multibyte
mockio = create_mockio(max: 1)
io = Net::BufferedIO.new(mockio)
@@ -119,4 +127,33 @@ class TestProtocol < Test::Unit::TestCase
io.write_timeout = 0.1
assert_raise(Net::WriteTimeout){ io.write("a"*50,"a"*50,"a") }
end
+
+ class FakeReadPartialIO
+ def initialize(chunks)
+ @chunks = chunks.map(&:dup)
+ end
+
+ def read_nonblock(size, buf = nil, exception: false)
+ if buf
+ buf.replace(@chunks.shift)
+ buf
+ else
+ @chunks.shift
+ end
+ end
+ end
+
+ def test_shareable_buffer_leak # https://github.com/ruby/net-protocol/pull/19
+ expected_chunks = [
+ "aaaaa",
+ "bbbbb",
+ ]
+ fake_io = FakeReadPartialIO.new(expected_chunks)
+ io = Net::BufferedIO.new(fake_io)
+ actual_chunks = []
+ reader = Net::ReadAdapter.new(-> (chunk) { actual_chunks << chunk })
+ io.read(5, reader)
+ io.read(5, reader)
+ assert_equal expected_chunks, actual_chunks
+ end
end
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 8ed04f59c9..7556fca530 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -29,12 +29,12 @@ class TestObjSpace < Test::Unit::TestCase
end
def test_memsize_of_root_shared_string
- a = "hello" * 5
+ a = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE]
b = a.dup
c = nil
ObjectSpace.each_object(String) {|x| break c = x if x == a and x.frozen?}
- rv_size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
- assert_equal([rv_size, rv_size, 26 + rv_size], [a, b, c].map {|x| ObjectSpace.memsize_of(x)})
+ rv_size = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
+ assert_equal([rv_size, rv_size, a.length + 1 + rv_size], [a, b, c].map {|x| ObjectSpace.memsize_of(x)})
end
def test_argf_memsize
@@ -140,6 +140,18 @@ class TestObjSpace < Test::Unit::TestCase
end;
end
+ def test_reachable_objects_during_iteration
+ opts = %w[--disable-gem --disable=frozen-string-literal -robjspace]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+ begin;
+ ObjectSpace.each_object{|o|
+ o.inspect
+ ObjectSpace.reachable_objects_from(Class)
+ }
+ end;
+ end
+
+
def test_reachable_objects_from_root
root_objects = ObjectSpace.reachable_objects_from_root
@@ -204,6 +216,13 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal(c3, ObjectSpace.allocation_generation(o3))
assert_equal(self.class.name, ObjectSpace.allocation_class_path(o3))
assert_equal(__method__, ObjectSpace.allocation_method_id(o3))
+
+ # [Bug #19482]
+ EnvUtil.under_gc_stress do
+ 100.times do
+ Class.new
+ end
+ end
}
end
@@ -260,12 +279,41 @@ class TestObjSpace < Test::Unit::TestCase
JSON.parse(info) if defined?(JSON)
end
+ def test_dump_too_complex_shape
+ if defined?(RubyVM::Shape)
+ RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
+ Object.new.instance_variable_set(:"@a#{_1}", 1)
+ end
+
+ tc = Object.new
+ tc.instance_variable_set(:@new_ivar, 1)
+ info = ObjectSpace.dump(tc)
+ assert_match(/"too_complex_shape":true/, info)
+ if defined?(JSON)
+ assert_true(JSON.parse(info)["too_complex_shape"])
+ end
+ end
+ end
+
+ class NotTooComplex ; end
+
+ def test_dump_not_too_complex_shape
+ tc = NotTooComplex.new
+ tc.instance_variable_set(:@new_ivar, 1)
+ info = ObjectSpace.dump(tc)
+
+ assert_not_match(/"too_complex_shape"/, info)
+ if defined?(JSON)
+ assert_nil(JSON.parse(info)["too_complex_shape"])
+ end
+ end
+
def test_dump_to_default
line = nil
info = nil
ObjectSpace.trace_object_allocations do
line = __LINE__ + 1
- str = "hello world"
+ str = "hello w"
info = ObjectSpace.dump(str)
end
assert_dump_object(info, line)
@@ -277,7 +325,7 @@ class TestObjSpace < Test::Unit::TestCase
th = Thread.start {r.read}
ObjectSpace.trace_object_allocations do
line = __LINE__ + 1
- str = "hello world"
+ str = "hello w"
ObjectSpace.dump(str, output: w)
end
w.close
@@ -289,12 +337,34 @@ class TestObjSpace < Test::Unit::TestCase
def assert_dump_object(info, line)
loc = caller_locations(1, 1)[0]
assert_match(/"type":"STRING"/, info)
- assert_match(/"embedded":true, "bytesize":11, "value":"hello world", "encoding":"UTF-8"/, info)
+ assert_match(/"embedded":true, "bytesize":7, "value":"hello w", "encoding":"UTF-8"/, info)
assert_match(/"file":"#{Regexp.escape __FILE__}", "line":#{line}/, info)
assert_match(/"method":"#{loc.base_label}"/, info)
JSON.parse(info) if defined?(JSON)
end
+ def test_dump_array
+ # Empty array
+ info = ObjectSpace.dump([])
+ assert_include(info, '"length":0, "embedded":true')
+ assert_not_include(info, '"shared":true')
+
+ # Non-embed array
+ arr = (1..10).to_a
+ info = ObjectSpace.dump(arr)
+ assert_include(info, '"length":10')
+ assert_not_include(info, '"embedded":true')
+ assert_not_include(info, '"shared":true')
+
+ # Shared array
+ arr1 = (1..10).to_a
+ arr = []
+ arr.replace(arr1)
+ info = ObjectSpace.dump(arr)
+ assert_include(info, '"length":10, "shared":true')
+ assert_not_include(info, '"embedded":true')
+ end
+
def test_dump_control_char
assert_include(ObjectSpace.dump("\x0f"), '"value":"\u000f"')
assert_include(ObjectSpace.dump("\C-?"), '"value":"\u007f"')
@@ -380,7 +450,7 @@ class TestObjSpace < Test::Unit::TestCase
@obj1 = Object.new
GC.start
@obj2 = Object.new
- ObjectSpace.dump_all(output: :stdout, since: gc_gen)
+ ObjectSpace.dump_all(output: :stdout, since: gc_gen, shapes: false)
end
p dump_my_heap_please
@@ -388,7 +458,7 @@ class TestObjSpace < Test::Unit::TestCase
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
+ generations = output.map { |l| JSON.parse(l) }.map { |o| o["generation"] }.uniq.sort
assert_equal [since, since + 1], generations
end
end
@@ -431,6 +501,38 @@ class TestObjSpace < Test::Unit::TestCase
end
end
+ def test_dump_objects_dumps_page_slot_sizes
+ assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
+ begin;
+ def dump_my_heap_please
+ ObjectSpace.dump_all(output: $stdout)
+ end
+
+ p $stdout == dump_my_heap_please
+ end;
+ assert_equal 'true', output.pop
+ assert(output.count > 1)
+ output.each { |l|
+ obj = JSON.parse(l)
+ next if obj["type"] == "ROOT"
+ next if obj["type"] == "SHAPE"
+
+ assert_not_nil obj["slot_size"]
+ assert_equal 0, obj["slot_size"] % GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
+ }
+ end
+ end
+
+ def test_dump_string_coderange
+ assert_includes ObjectSpace.dump("TEST STRING"), '"coderange":"7bit"'
+ unknown = "TEST STRING".dup.force_encoding(Encoding::BINARY)
+ 2.times do # ensure that dumping the string doesn't mutate it
+ assert_includes ObjectSpace.dump(unknown), '"coderange":"unknown"'
+ end
+ assert_includes ObjectSpace.dump("Fée"), '"coderange":"valid"'
+ assert_includes ObjectSpace.dump("\xFF"), '"coderange":"broken"'
+ end
+
def test_dump_escapes_method_name
method_name = "foo\"bar"
klass = Class.new do
@@ -449,6 +551,13 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.trace_object_allocations_stop
end
+ def test_dump_includes_slot_size
+ str = "TEST"
+ dump = ObjectSpace.dump(str)
+
+ assert_includes dump, "\"slot_size\":#{GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]}"
+ end
+
def test_dump_reference_addresses_match_dump_all_addresses
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
begin;
@@ -470,8 +579,28 @@ class TestObjSpace < Test::Unit::TestCase
end
end
+ def assert_test_string_entry_correct_in_dump_all(output)
+ # `TEST STRING` appears twice in the output of `ObjectSpace.dump_all`
+ # 1. To create the T_STRING object for the literal string "TEST STRING"
+ # 2. When it is assigned to the `str` variable with a new encoding
+ #
+ # This test makes assertions on the assignment to `str`, so we look for
+ # the second appearance of /TEST STRING/ in the output
+ test_string_in_dump_all = output.grep(/TEST2/)
+ assert_equal(2, test_string_in_dump_all.size, "number of strings")
+
+ entry_hash = JSON.parse(test_string_in_dump_all[1])
+
+ assert_equal(5, entry_hash["bytesize"], "bytesize is wrong")
+ assert_equal("TEST2", entry_hash["value"], "value is wrong")
+ assert_equal("UTF-8", entry_hash["encoding"], "encoding is wrong")
+ assert_equal("-", entry_hash["file"], "file is wrong")
+ assert_equal(4, entry_hash["line"], "line is wrong")
+ assert_equal("dump_my_heap_please", entry_hash["method"], "method is wrong")
+ assert_not_nil(entry_hash["generation"])
+ end
+
def test_dump_all
- entry = /"bytesize":11, "value":"TEST STRING", "encoding":"UTF-8", "file":"-", "line":4, "method":"dump_my_heap_please", "generation":/
opts = %w[--disable-gem --disable=frozen-string-literal -robjspace]
assert_in_out_err(opts, "#{<<-"begin;"}#{<<-'end;'}") do |output, error|
@@ -479,14 +608,14 @@ class TestObjSpace < Test::Unit::TestCase
def dump_my_heap_please
ObjectSpace.trace_object_allocations_start
GC.start
- str = "TEST STRING".force_encoding("UTF-8")
+ str = "TEST2".force_encoding("UTF-8")
ObjectSpace.dump_all(output: :stdout)
end
p dump_my_heap_please
end;
- assert_equal 'nil', output.pop
- assert_match(entry, output.grep(/TEST STRING/).join("\n"))
+
+ assert_test_string_entry_correct_in_dump_all(output)
end
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}#{<<-'end;'}") do |(output), (error)|
@@ -494,7 +623,7 @@ class TestObjSpace < Test::Unit::TestCase
def dump_my_heap_please
ObjectSpace.trace_object_allocations_start
GC.start
- (str = "TEST STRING").force_encoding("UTF-8")
+ (str = "TEST2").force_encoding("UTF-8")
ObjectSpace.dump_all().path
end
@@ -503,7 +632,8 @@ class TestObjSpace < Test::Unit::TestCase
assert_nil(error)
dump = File.readlines(output)
File.unlink(output)
- assert_match(entry, dump.grep(/TEST STRING/).join("\n"))
+
+ assert_test_string_entry_correct_in_dump_all(dump)
end
if defined?(JSON)
@@ -632,4 +762,88 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal '42', out[2]
end
end
+
+ def load_allocation_path_helper method, to_binary: false
+
+ Tempfile.create(["test_ruby_load_allocation_path", ".rb"]) do |t|
+ path = t.path
+ str = "#{Time.now.to_f.to_s}_#{rand.to_s}"
+ t.puts script = <<~RUBY
+ # frozen-string-literal: true
+ return if Time.now.to_i > 0
+ $gv = 'rnd-#{str}' # unreachable, but the string literal was written
+ RUBY
+
+ t.close
+
+ if to_binary
+ bin = RubyVM::InstructionSequence.compile_file(t.path).to_binary
+ bt = Tempfile.new(['test_ruby_load_allocation_path', '.yarb'], mode: File::Constants::WRONLY)
+ bt.write bin
+ bt.close
+
+ path = bt.path
+ end
+
+ assert_separately(%w[-robjspace -rtempfile], <<~RUBY)
+ GC.disable
+ path = "#{path}"
+ ObjectSpace.trace_object_allocations do
+ #{method}
+ end
+
+ n = 0
+ dump = ObjectSpace.dump_all(output: :string)
+ dump.each_line do |line|
+ if /"value":"rnd-#{str}"/ =~ line && /"frozen":true/ =~ line
+ assert Regexp.new('"file":"' + "#{path}") =~ line
+ assert Regexp.new('"line":') !~ line
+ n += 1
+ end
+ rescue ArgumentError
+ end
+
+ assert_equal(1, n)
+ RUBY
+ ensure
+ bt.unlink if bt
+ end
+ end
+
+ def test_load_allocation_path_load
+ load_allocation_path_helper 'load(path)'
+ end
+
+ def test_load_allocation_path_compile_file
+ load_allocation_path_helper 'RubyVM::InstructionSequence.compile_file(path)'
+ end
+
+ def test_load_allocation_path_load_from_binary
+ # load_allocation_path_helper 'iseq = RubyVM::InstructionSequence.load_from_binary(File.binread(path))', to_binary: true
+ end
+
+ def test_utf8_method_names
+ name = "utf8_❨╯°□°❩╯︵┻━┻"
+ obj = ObjectSpace.trace_object_allocations do
+ __send__(name)
+ end
+ dump = ObjectSpace.dump(obj)
+ assert_equal name, JSON.parse(dump)["method"], dump
+ end
+
+ def test_dump_shapes
+ json = ObjectSpace.dump_shapes(output: :string)
+ json.each_line do |line|
+ assert_include(line, '"type":"SHAPE"')
+ end
+
+ assert_empty ObjectSpace.dump_shapes(output: :string, since: RubyVM.stat(:next_shape_id))
+ assert_equal 2, ObjectSpace.dump_shapes(output: :string, since: RubyVM.stat(:next_shape_id) - 2).lines.size
+ end
+
+ private
+
+ def utf8_❨╯°□°❩╯︵┻━┻
+ "1#{2}"
+ end
end
diff --git a/test/objspace/test_ractor.rb b/test/objspace/test_ractor.rb
new file mode 100644
index 0000000000..b7008ea731
--- /dev/null
+++ b/test/objspace/test_ractor.rb
@@ -0,0 +1,17 @@
+require "test/unit"
+
+class TestObjSpaceRactor < Test::Unit::TestCase
+ def test_tracing_does_not_crash
+ assert_ractor(<<~RUBY, require: 'objspace')
+ ObjectSpace.trace_object_allocations do
+ r = Ractor.new do
+ obj = 'a' * 1024
+ Ractor.yield obj
+ end
+
+ r.take
+ r.take
+ end
+ RUBY
+ end
+end
diff --git a/test/open-uri/test_open-uri.rb b/test/open-uri/test_open-uri.rb
index 72ebcdb0da..fdd1969666 100644
--- a/test/open-uri/test_open-uri.rb
+++ b/test/open-uri/test_open-uri.rb
@@ -902,5 +902,14 @@ class TestOpenURI < Test::Unit::TestCase
}
end
-end
+ def test_meta_init_doesnt_bump_global_constant_state
+ omit "RubyVM.stat not defined" unless defined? RubyVM.stat
+ omit unless RubyVM.stat.has_key?(:global_constant_state)
+
+ OpenURI::Meta.init(Object.new) # prewarm
+ before = RubyVM.stat(:global_constant_state)
+ OpenURI::Meta.init(Object.new)
+ assert_equal 0, RubyVM.stat(:global_constant_state) - before
+ end
+end
diff --git a/test/open-uri/test_ssl.rb b/test/open-uri/test_ssl.rb
index 4f645d83b9..3f94cab40f 100644
--- a/test/open-uri/test_ssl.rb
+++ b/test/open-uri/test_ssl.rb
@@ -107,6 +107,25 @@ class TestOpenURISSL
}
end
+ def test_ssl_min_version
+ with_https {|srv, dr, url|
+ setup_validation(srv, dr)
+ URI.open("#{url}/data", :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :ssl_min_version => :TLS1_2) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("ddd", f.read)
+ }
+ }
+ end
+
+ def test_bad_ssl_version
+ with_https(nil) {|srv, dr, url|
+ setup_validation(srv, dr)
+ assert_raise(ArgumentError) {
+ URI.open("#{url}/data", :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :ssl_min_version => :TLS_no_such_version) {}
+ }
+ }
+ end
+
def with_https_proxy(proxy_log_tester=lambda {|proxy_log, proxy_access_log| assert_equal([], proxy_log) })
proxy_log = []
proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
diff --git a/test/openssl/fixtures/pkey/p256_too_large.pem b/test/openssl/fixtures/pkey/p256_too_large.pem
new file mode 100644
index 0000000000..a73ac37f87
--- /dev/null
+++ b/test/openssl/fixtures/pkey/p256_too_large.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIP+TT0V8Fndsnacji9tyf6hmhHywcOWTee9XkiBeJoVloAoGCCqGSM49
+AwEHoUQDQgAEBkhhJIU/2/YdPSlY2I1k25xjK4trr5OXSgXvBC21PtY0HQ7lor7A
+jzT0giJITqmcd81fwGw5+96zLcdxTF1hVQ==
+-----END EC PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/p384_invalid.pem b/test/openssl/fixtures/pkey/p384_invalid.pem
new file mode 100644
index 0000000000..d5cdc9a3af
--- /dev/null
+++ b/test/openssl/fixtures/pkey/p384_invalid.pem
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDA1Tm0m7YhkfeVpFuarAJYVlHp2tQj+1fOBiLa10t9E8TiQO/hVfxB
+vGaVEQwOheWgBwYFK4EEACKhZANiAASyGqmryZGqdpsq5gEDIfNvgC3AwSJxiBCL
+XKHBTFRp+tCezLDOK/6V8KK/vVGBJlGFW6/I7ahyXprxS7xs7hPA9iz5YiuqXlu+
+lbrIpZOz7b73hyQQCkvbBO/Avg+hPAk=
+-----END EC PRIVATE KEY-----
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 6bd847806b..7b1722e5df 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -14,7 +14,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
["keyUsage","keyCertSign, cRLSign",true],
["subjectKeyIdentifier","hash",false],
]
- dgst = OpenSSL::Digest.new('SHA1')
+ dgst = OpenSSL::Digest.new('SHA256')
cert = OpenSSL::TestUtils.issue_cert(
subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600)
@@ -42,7 +42,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_equal(OpenSSL::ASN1::Sequence, sig.class)
assert_equal(2, sig.value.size)
assert_equal(OpenSSL::ASN1::ObjectId, sig.value[0].class)
- assert_equal("1.2.840.113549.1.1.5", sig.value[0].oid)
+ assert_equal("1.2.840.113549.1.1.11", sig.value[0].oid)
assert_equal(OpenSSL::ASN1::Null, sig.value[1].class)
dn = tbs_cert.value[3] # issuer
@@ -170,7 +170,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
str = +"\000"; str[0] = 0b00000110.chr
assert_equal(str, extv.value)
- ext = extensions.value[0].value[2] # subjetKeyIdentifier
+ ext = extensions.value[0].value[2] # subjectKeyIdentifier
assert_equal(OpenSSL::ASN1::Sequence, ext.class)
assert_equal(2, ext.value.size)
assert_equal(OpenSSL::ASN1::ObjectId, ext.value[0].class)
@@ -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.new('SHA1'), tbs_cert.to_der)
+ cululated_sig = key.sign(OpenSSL::Digest.new('SHA256'), tbs_cert.to_der)
assert_equal(cululated_sig, sig_val.value)
end
@@ -323,14 +323,9 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1::ObjectId.new("3.0".b).to_der }
assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1::ObjectId.new("0.40".b).to_der }
- begin
- oid = (0...100).to_a.join(".").b
- obj = OpenSSL::ASN1::ObjectId.new(oid)
- assert_equal oid, obj.oid
- rescue OpenSSL::ASN1::ASN1Error
- pend "OBJ_obj2txt() not working (LibreSSL?)" if $!.message =~ /OBJ_obj2txt/
- raise
- end
+ oid = (0...100).to_a.join(".").b
+ obj = OpenSSL::ASN1::ObjectId.new(oid)
+ assert_equal oid, obj.oid
aki = [
OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier"),
@@ -404,9 +399,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
def test_utctime
encode_decode_test B(%w{ 17 0D }) + "160908234339Z".b,
OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 39))
- # Seconds is omitted
- decode_test B(%w{ 17 0B }) + "1609082343Z".b,
- OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0))
begin
# possible range of UTCTime is 1969-2068 currently
encode_decode_test B(%w{ 17 0D }) + "690908234339Z".b,
@@ -432,8 +424,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29))
encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b,
OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39))
- decode_test B(%w{ 18 0D }) + "201612081934Z".b,
- OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0))
# not implemented
# decode_test B(%w{ 18 13 }) + "20161208193439+0930".b,
# OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30"))
diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb
index c36d6b89d8..77af14091e 100644
--- a/test/openssl/test_bn.rb
+++ b/test/openssl/test_bn.rb
@@ -174,6 +174,12 @@ class OpenSSL::TestBN < OpenSSL::TestCase
assert_equal(0, 59.to_bn.mod_sqr(59))
end
+ def test_mod_sqrt
+ assert_equal(3, 4.to_bn.mod_sqrt(5))
+ assert_equal(0, 5.to_bn.mod_sqrt(5))
+ assert_raise(OpenSSL::BNError) { 3.to_bn.mod_sqrt(5) }
+ end
+
def test_mod_inverse
assert_equal(2, 3.to_bn.mod_inverse(5))
assert_raise(OpenSSL::BNError) { 3.to_bn.mod_inverse(6) }
@@ -248,6 +254,10 @@ class OpenSSL::TestBN < OpenSSL::TestCase
r5 = OpenSSL::BN.rand_range(256)
assert_include(0..255, r5)
}
+
+ # Aliases
+ assert_include(128..255, OpenSSL::BN.pseudo_rand(8))
+ assert_include(0..255, OpenSSL::BN.pseudo_rand_range(256))
end
begin
@@ -330,6 +340,31 @@ class OpenSSL::TestBN < OpenSSL::TestCase
e.set_flags(0)
assert_equal(4, e.get_flags(OpenSSL::BN::CONSTTIME))
end
+
+ if respond_to?(:ractor)
+ ractor
+ def test_ractor
+ assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.take)
+ assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.take)
+ assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.take)
+ assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.take)
+ assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take)
+ assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take)
+ assert_equal(false, Ractor.new { 1.to_bn.zero? }.take)
+ assert_equal(true, Ractor.new { 1.to_bn.one? }.take)
+ assert_equal(true, Ractor.new(@e2) { _1.negative? }.take)
+ assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.take)
+ assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take)
+ assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take)
+ assert_equal(true, Ractor.new { 0.to_bn.zero? }.take)
+ assert_equal(true, Ractor.new { 1.to_bn.one? }.take )
+ assert_equal(false,Ractor.new { 2.to_bn.odd? }.take)
+ assert_equal(true, Ractor.new(@e2) { _1.negative? }.take)
+ assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.take)
+ assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.take)
+ assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.take)
+ end
+ end
end
end
diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb
index 6d18c0c85c..1c8610b2a9 100644
--- a/test/openssl/test_cipher.rb
+++ b/test/openssl/test_cipher.rb
@@ -108,12 +108,6 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
assert_not_equal s1, s2
end
- def test_empty_data
- cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt
- cipher.random_key
- assert_raise(ArgumentError) { cipher.update("") }
- end
-
def test_initialize
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC")
assert_raise(RuntimeError) { cipher.__send__(:initialize, "DES-EDE3-CBC") }
@@ -135,14 +129,11 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
end
def test_ciphers
- OpenSSL::Cipher.ciphers.each{|name|
- next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
- begin
- assert_kind_of(OpenSSL::Cipher, OpenSSL::Cipher.new(name))
- rescue OpenSSL::Cipher::CipherError => e
- raise unless /wrap/ =~ name and /wrap mode not allowed/ =~ e.message
- end
- }
+ ciphers = OpenSSL::Cipher.ciphers
+ assert_kind_of Array, ciphers
+ assert_include ciphers, "aes-128-cbc"
+ assert_include ciphers, "aes128" # alias of aes-128-cbc
+ assert_include ciphers, "aes-128-gcm"
end
def test_AES
diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb
index 769e65ceb5..24a215a486 100644
--- a/test/openssl/test_config.rb
+++ b/test/openssl/test_config.rb
@@ -61,14 +61,14 @@ foo\\bar::foo\\bar = baz
[default1 default2]\t\t # space is allowed in section name
fo =b ar # space allowed in value
[emptysection]
- [doller ]
+ [dollar ]
foo=bar
bar = $(foo)
baz = 123$(default::bar)456${foo}798
qux = ${baz}
quxx = $qux.$qux
__EOC__
- assert_equal(['default', 'default1 default2', 'doller', 'emptysection', 'foo', 'foo\\bar'], c.sections.sort)
+ assert_equal(['default', 'default1 default2', 'dollar', 'emptysection', 'foo', 'foo\\bar'], c.sections.sort)
assert_equal(['', 'a', 'bar', 'baz', 'd', 'dq', 'dq2', 'esc', 'foo\\bar', 'sq'], c['default'].keys.sort)
assert_equal('c', c['default'][''])
assert_equal('', c['default']['a'])
@@ -84,12 +84,12 @@ __EOC__
assert_equal('baz', c['foo\\bar']['foo\\bar'])
assert_equal('b ar', c['default1 default2']['fo'])
- # dolloer
- assert_equal('bar', c['doller']['foo'])
- assert_equal('bar', c['doller']['bar'])
- assert_equal('123baz456bar798', c['doller']['baz'])
- assert_equal('123baz456bar798', c['doller']['qux'])
- assert_equal('123baz456bar798.123baz456bar798', c['doller']['quxx'])
+ # dollar
+ assert_equal('bar', c['dollar']['foo'])
+ assert_equal('bar', c['dollar']['bar'])
+ assert_equal('123baz456bar798', c['dollar']['baz'])
+ assert_equal('123baz456bar798', c['dollar']['qux'])
+ assert_equal('123baz456bar798.123baz456bar798', c['dollar']['quxx'])
excn = assert_raise(OpenSSL::ConfigError) do
OpenSSL::Config.parse("foo = $bar")
diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb
index 8d7046e831..84c128c12f 100644
--- a/test/openssl/test_digest.rb
+++ b/test/openssl/test_digest.rb
@@ -54,7 +54,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def test_digest_constants
- %w{MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name|
+ %w{MD5 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name|
assert_not_nil(OpenSSL::Digest.new(name))
klass = OpenSSL::Digest.const_get(name.tr('-', '_'))
assert_not_nil(klass.new)
diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb
index 2f53a813e1..3cb707448a 100644
--- a/test/openssl/test_hmac.rb
+++ b/test/openssl/test_hmac.rb
@@ -62,6 +62,14 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase
b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There")
assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest
end
+
+ def test_zero_length_key
+ # Empty string as the key
+ hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test")
+ assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest
+ hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "", "test")
+ assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest
+ end
end
end
diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb
index ed3be86e2c..383931b98b 100644
--- a/test/openssl/test_ns_spki.rb
+++ b/test/openssl/test_ns_spki.rb
@@ -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.new('SHA1'))
+ spki.sign(key1, OpenSSL::Digest.new('SHA256'))
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 ef7321abd6..85f133752c 100644
--- a/test/openssl/test_ocsp.rb
+++ b/test/openssl/test_ocsp.rb
@@ -99,7 +99,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
request.sign(@cert, @cert_key, [@ca_cert], 0)
asn1 = OpenSSL::ASN1.decode(request.to_der)
assert_equal cid.to_der, asn1.value[0].value.find { |a| a.tag_class == :UNIVERSAL }.value[0].value[0].to_der
- assert_equal OpenSSL::ASN1.ObjectId("sha1WithRSAEncryption").to_der, asn1.value[1].value[0].value[0].value[0].to_der
+ assert_equal OpenSSL::ASN1.ObjectId("sha256WithRSAEncryption").to_der, asn1.value[1].value[0].value[0].value[0].to_der
assert_equal @cert.to_der, asn1.value[1].value[0].value[2].value[0].value[0].to_der
assert_equal @ca_cert.to_der, asn1.value[1].value[0].value[2].value[0].value[1].to_der
assert_equal asn1.to_der, OpenSSL::OCSP::Request.new(asn1.to_der).to_der
diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb
index 8316ec2a9c..14786100df 100644
--- a/test/openssl/test_pair.rb
+++ b/test/openssl/test_pair.rb
@@ -2,7 +2,7 @@
require_relative 'utils'
require_relative 'ut_eof'
-if defined?(OpenSSL)
+if defined?(OpenSSL::SSL)
module OpenSSL::SSLPairM
def setup
@@ -23,7 +23,6 @@ module OpenSSL::SSLPairM
sctx = OpenSSL::SSL::SSLContext.new
sctx.cert = @svr_cert
sctx.key = @svr_key
- sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") }
sctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION
ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx)
ns = ssls.accept
@@ -383,7 +382,6 @@ module OpenSSL::TestPairM
ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.cert = @svr_cert
ctx2.key = @svr_key
- ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") }
sock1, sock2 = tcp_pair
@@ -431,7 +429,6 @@ module OpenSSL::TestPairM
ctx = OpenSSL::SSL::SSLContext.new
ctx.cert = @svr_cert
ctx.key = @svr_key
- ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") }
sock1, sock2 = tcp_pair
diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb
index fdbe753b17..ec676743bc 100644
--- a/test/openssl/test_pkcs12.rb
+++ b/test/openssl/test_pkcs12.rb
@@ -5,6 +5,9 @@ if defined?(OpenSSL)
module OpenSSL
class TestPKCS12 < OpenSSL::TestCase
+ DEFAULT_PBE_PKEYS = "PBE-SHA1-3DES"
+ DEFAULT_PBE_CERTS = "PBE-SHA1-3DES"
+
def setup
super
ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
@@ -14,47 +17,41 @@ module OpenSSL
["subjectKeyIdentifier","hash",false],
["authorityKeyIdentifier","keyid:always",false],
]
- @cacert = issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil)
+ ca_key = Fixtures.pkey("rsa-1")
+ @cacert = issue_cert(ca, ca_key, 1, ca_exts, nil, nil)
inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA")
- inter_ca_key = OpenSSL::PKey.read <<-_EOS_
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQDp7hIG0SFMG/VWv1dBUWziAPrNmkMXJgTCAoB7jffzRtyyN04K
-oq/89HAszTMStZoMigQURfokzKsjpUp8OYCAEsBtt9d5zPndWMz/gHN73GrXk3LT
-ZsxEn7Xv5Da+Y9F/Hx2QZUHarV5cdZixq2NbzWGwrToogOQMh2pxN3Z/0wIDAQAB
-AoGBAJysUyx3olpsGzv3OMRJeahASbmsSKTXVLZvoIefxOINosBFpCIhZccAG6UV
-5c/xCvS89xBw8aD15uUfziw3AuT8QPEtHCgfSjeT7aWzBfYswEgOW4XPuWr7EeI9
-iNHGD6z+hCN/IQr7FiEBgTp6A+i/hffcSdR83fHWKyb4M7TRAkEA+y4BNd668HmC
-G5MPRx25n6LixuBxrNp1umfjEI6UZgEFVpYOg4agNuimN6NqM253kcTR94QNTUs5
-Kj3EhG1YWwJBAO5rUjiOyCNVX2WUQrOMYK/c1lU7fvrkdygXkvIGkhsPoNRzLPeA
-HGJszKtrKD8bNihWpWNIyqKRHfKVD7yXT+kCQGCAhVCIGTRoypcDghwljHqLnysf
-ci0h5ZdPcIqc7ODfxYhFsJ/Rql5ONgYsT5Ig/+lOQAkjf+TRYM4c2xKx2/8CQBvG
-jv6dy70qDgIUgqzONtlmHeYyFzn9cdBO5sShdVYHvRHjFSMEXsosqK9zvW2UqvuK
-FJx7d3f29gkzynCLJDkCQGQZlEZJC4vWmWJGRKJ24P6MyQn3VsPfErSKOg4lvyM3
-Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
------END RSA PRIVATE KEY-----
- _EOS_
- @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, Fixtures.pkey("rsa2048"))
+ inter_ca_key = Fixtures.pkey("rsa-2")
+ @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, ca_key)
exts = [
["keyUsage","digitalSignature",true],
["subjectKeyIdentifier","hash",false],
]
ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate")
- @mykey = Fixtures.pkey("rsa1024")
+ @mykey = Fixtures.pkey("rsa-3")
@mycert = issue_cert(ee, @mykey, 3, exts, @inter_cacert, inter_ca_key)
end
- def test_create
+ def test_create_single_key_single_cert
pkcs12 = OpenSSL::PKCS12.create(
"omg",
"hello",
@mykey,
- @mycert
+ @mycert,
+ nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
- assert_equal @mycert.to_der, pkcs12.certificate.to_der
+ assert_equal @mycert, pkcs12.certificate
assert_equal @mykey.to_der, pkcs12.key.to_der
assert_nil pkcs12.ca_certs
+
+ der = pkcs12.to_der
+ decoded = OpenSSL::PKCS12.new(der, "omg")
+ assert_equal @mykey.to_der, decoded.key.to_der
+ assert_equal @mycert, decoded.certificate
+ assert_equal [], Array(decoded.ca_certs)
end
def test_create_no_pass
@@ -62,14 +59,17 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
nil,
"hello",
@mykey,
- @mycert
+ @mycert,
+ nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
- assert_equal @mycert.to_der, pkcs12.certificate.to_der
+ assert_equal @mycert, pkcs12.certificate
assert_equal @mykey.to_der, pkcs12.key.to_der
assert_nil pkcs12.ca_certs
decoded = OpenSSL::PKCS12.new(pkcs12.to_der)
- assert_cert @mycert, decoded.certificate
+ assert_equal @mycert, decoded.certificate
end
def test_create_with_chain
@@ -80,7 +80,9 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
"hello",
@mykey,
@mycert,
- chain
+ chain,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
assert_equal chain, pkcs12.ca_certs
end
@@ -95,14 +97,16 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
"hello",
@mykey,
@mycert,
- chain
+ chain,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
decoded = OpenSSL::PKCS12.new(pkcs12.to_der, passwd)
assert_equal chain.size, decoded.ca_certs.size
- assert_include_cert @cacert, decoded.ca_certs
- assert_include_cert @inter_cacert, decoded.ca_certs
- assert_cert @mycert, decoded.certificate
+ assert_include decoded.ca_certs, @cacert
+ assert_include decoded.ca_certs, @inter_cacert
+ assert_equal @mycert, decoded.certificate
assert_equal @mykey.to_der, decoded.key.to_der
end
@@ -126,8 +130,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
2048
)
@@ -138,8 +142,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
"omg"
)
end
@@ -152,7 +156,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
nil,
nil,
2048
@@ -165,148 +170,144 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
nil,
"omg"
)
end
end
- def test_new_with_one_key_and_one_cert
- # generated with:
- # openssl version #=> OpenSSL 1.0.2h 3 May 2016
- # openssl pkcs12 -in <@mycert> -inkey <RSA1024> -export -out <out>
- str = <<~EOF.unpack("m").first
-MIIGQQIBAzCCBgcGCSqGSIb3DQEHAaCCBfgEggX0MIIF8DCCAu8GCSqGSIb3DQEH
-BqCCAuAwggLcAgEAMIIC1QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIeZPM
-Rh6KiXgCAggAgIICqL6O+LCZmBzdIg6mozPF3FpY0hVbWHvTNMiDHieW3CrAanhN
-YCH2/wHqH8WpFpEWwF0qEEXAWjHsIlYB4Cfqo6b7XpuZe5eVESsjNTOTMF1JCUJj
-A6iNefXmCFLync1JK5LUodRDhTlKLU1WPK20X9X4vuEwHn8wt5RUb8P0E+Xh6rpS
-XC4LkZKT45zF3cJa/n5+dW65ohVGNVnF9D1bCNEKHMOllK1V9omutQ9slW88hpga
-LGiFsJoFOb/ESGb78KO+bd6zbX1MdKdBV+WD6t1uF/cgU65y+2A4nXs1urda+MJ7
-7iVqiB7Vnc9cANTbAkTSGNyoUDVM/NZde782/8IvddLAzUZ2EftoRDke6PvuBOVL
-ljBhNWmdamrtBqzuzVZCRdWq44KZkF2Xoc9asepwIkdVmntzQF7f1Z+Ta5yg6HFp
-xnr7CuM+MlHEShXkMgYtHnwAq10fDMSXIvjhi/AA5XUAusDO3D+hbtcRDcJ4uUes
-dm5dhQE2qJ02Ysn4aH3o1F3RYNOzrxejHJwl0D2TCE8Ww2X342xib57+z9u03ufj
-jswhiMKxy67f1LhUMq3XrT3uV6kCVXk/KUOUPcXPlPVNA5JmZeFhMp6GrtB5xJJ9
-wwBZD8UL5A2U2Mxi2OZsdUBv8eo3jnjZ284aFpt+mCjIHrLW5O0jwY8OCwSlYUoY
-IY00wlabX0s82kBcIQNZbC1RSV2267ro/7A0MClc8YQ/zWN0FKY6apgtUkHJI1cL
-1dc77mhnjETjwW94iLMDFy4zQfVu7IfCBqOBzygRNnqqUG66UhTs1xFnWM0mWXl/
-Zh9+AMpbRLIPaKCktIjl5juzzm+KEgkhD+707XRCFIGUYGP5bSHzGaz8PK9hj0u1
-E2SpZHUvYOcawmxtA7pmpSxl5uQjMIIC+QYJKoZIhvcNAQcBoIIC6gSCAuYwggLi
-MIIC3gYLKoZIhvcNAQwKAQKgggKmMIICojAcBgoqhkiG9w0BDAEDMA4ECKB338m8
-qSzHAgIIAASCAoACFhJeqA3xx+s1qIH6udNQYY5hAL6oz7SXoGwFhDiceSyJjmAD
-Dby9XWM0bPl1Gj5nqdsuI/lAM++fJeoETk+rxw8q6Ofk2zUaRRE39qgpwBwSk44o
-0SAFJ6bzHpc5CFh6sZmDaUX5Lm9GtjnGFmmsPTSJT5an5JuJ9WczGBEd0nSBQhJq
-xHbTGZiN8i3SXcIH531Sub+CBIFWy5lyCKgDYh/kgJFGQAaWUOjLI+7dCEESonXn
-F3Jh2uPbnDF9MGJyAFoNgWFhgSpi1cf6AUi87GY4Oyur88ddJ1o0D0Kz2uw8/bpG
-s3O4PYnIW5naZ8mozzbnYByEFk7PoTwM7VhoFBfYNtBoAI8+hBnPY/Y71YUojEXf
-SeX6QbtkIANfzS1XuFNKElShC3DPQIHpKzaatEsfxHfP+8VOav6zcn4mioao7NHA
-x7Dp6R1enFGoQOq4UNjBT8YjnkG5vW8zQHW2dAHLTJBq6x2Fzm/4Pjo/8vM1FiGl
-BQdW5vfDeJ/l6NgQm3xR9ka2E2HaDqIcj1zWbN8jy/bHPFJYuF/HH8MBV/ngMIXE
-vFEW/ToYv8eif0+EpUtzBsCKD4a7qYYYh87RmEVoQU96q6m+UbhpD2WztYfAPkfo
-OSL9j2QHhVczhL7OAgqNeM95pOsjA9YMe7exTeqK31LYnTX8oH8WJD1xGbRSJYgu
-SY6PQbumcJkc/TFPn0GeVUpiDdf83SeG50lo/i7UKQi2l1hi5Y51fQhnBnyMr68D
-llSZEvSWqfDxBJkBpeg6PIYvkTpEwKRJpVQoM3uYvdqVSSnW6rydqIb+snfOrlhd
-f+xCtq9xr+kHeTSqLIDRRAnMfgFRhY3IBlj6MSUwIwYJKoZIhvcNAQkVMRYEFBdb
-8XGWehZ6oPj56Pf/uId46M9AMDEwITAJBgUrDgMCGgUABBRvSCB04/f8f13pp2PF
-vyl2WuMdEwQIMWFFphPkIUICAggA
- EOF
- p12 = OpenSSL::PKCS12.new(str, "abc123")
-
- assert_equal @mykey.to_der, p12.key.to_der
- assert_equal @mycert.subject.to_der, p12.certificate.subject.to_der
- assert_equal [], Array(p12.ca_certs)
- end
-
def test_new_with_no_keys
# generated with:
- # openssl pkcs12 -in <@mycert> -nokeys -export -out <out>
+ # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export
str = <<~EOF.unpack("m").first
-MIIDHAIBAzCCAuIGCSqGSIb3DQEHAaCCAtMEggLPMIICyzCCAscGCSqGSIb3DQEH
-BqCCArgwggK0AgEAMIICrQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIX4+W
-irqwH40CAggAgIICgOaCyo+5+6IOVoGCCL80c50bkkzAwqdXxvkKExJSdcJz2uMU
-0gRrKnZEjL5wrUsN8RwZu8DvgQTEhNEkKsUgM7AWainmN/EnwohIdHZAHpm6WD67
-I9kLGp0/DHrqZrV9P2dLfhXLUSQE8PI0tqZPZ8UEABhizkViw4eISTkrOUN7pGbN
-Qtx/oqgitXDuX2polbxYYDwt9vfHZhykHoKgew26SeJyZfeMs/WZ6olEI4cQUAFr
-mvYGuC1AxEGTo9ERmU8Pm16j9Hr9PFk50WYe+rnk9oX3wJogQ7XUWS5kYf7XRycd
-NDkNiwV/ts94bbuaGZp1YA6I48FXpIc8b5fX7t9tY0umGaWy0bARe1L7o0Y89EPe
-lMg25rOM7j3uPtFG8whbSfdETSy57UxzzTcJ6UwexeaK6wb2jqEmj5AOoPLWeaX0
-LyOAszR3v7OPAcjIDYZGdrbb3MZ2f2vo2pdQfu9698BrWhXuM7Odh73RLhJVreNI
-aezNOAtPyBlvGiBQBGTzRIYHSLL5Y5aVj2vWLAa7hjm5qTL5C5mFdDIo6TkEMr6I
-OsexNQofEGs19kr8nARXDlcbEimk2VsPj4efQC2CEXZNzURsKca82pa62MJ8WosB
-DTFd8X06zZZ4nED50vLopZvyW4fyW60lELwOyThAdG8UchoAaz2baqP0K4de44yM
-Y5/yPFDu4+GoimipJfbiYviRwbzkBxYW8+958ILh0RtagLbvIGxbpaym9PqGjOzx
-ShNXjLK2aAFZsEizQ8kd09quJHU/ogq2cUXdqqhmOqPnUWrJVi/VCoRB3Pv1/lE4
-mrUgr2YZ11rYvBw6g5XvNvFcSc53OKyV7SLn0dwwMTAhMAkGBSsOAwIaBQAEFEWP
-1WRQykaoD4uJCpTx/wv0SLLBBAiDKI26LJK7xgICCAA=
+MIIGJAIBAzCCBeoGCSqGSIb3DQEHAaCCBdsEggXXMIIF0zCCBc8GCSqGSIb3
+DQEHBqCCBcAwggW8AgEAMIIFtQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMw
+DgQIjv5c3OHvnBgCAggAgIIFiMJa8Z/w7errRvCQPXh9dGQz3eJaFq3S2gXD
+rh6oiwsgIRJZvYAWgU6ll9NV7N5SgvS2DDNVuc3tsP8TPWjp+bIxzS9qmGUV
+kYWuURWLMKhpF12ZRDab8jcIwBgKoSGiDJk8xHjx6L613/XcRM6ln3VeQK+C
+hlW5kXniNAUAgTft25Fn61Xa8xnhmsz/fk1ycGnyGjKCnr7Mgy7KV0C1vs23
+18n8+b1ktDWLZPYgpmXuMFVh0o+HJTV3O86mkIhJonMcnOMgKZ+i8KeXaocN
+JQlAPBG4+HOip7FbQT/h6reXv8/J+hgjLfqAb5aV3m03rUX9mXx66nR1tQU0
+Jq+XPfDh5+V4akIczLlMyyo/xZjI1/qupcMjr+giOGnGd8BA3cuXW+ueLQiA
+PpTp+DQLVHRfz9XTZbyqOReNEtEXvO9gOlKSEY5lp65ItXVEs2Oqyf9PfU9y
+DUltN6fCMilwPyyrsIBKXCu2ZLM5h65KVCXAYEX9lNqj9zrQ7vTqvCNN8RhS
+ScYouTX2Eqa4Z+gTZWLHa8RCQFoyP6hd+97/Tg2Gv2UTH0myQxIVcnpdi1wy
+cqb+er7tyKbcO96uSlUjpj/JvjlodtjJcX+oinEqGb/caj4UepbBwiG3vv70
+63bS3jTsOLNjDRsR9if3LxIhLa6DW8zOJiGC+EvMD1o4dzHcGVpQ/pZWCHZC
++YiNJpQOBApiZluE+UZ0m3XrtHFQYk7xblTrh+FJF91wBsok0rZXLAKd8m4p
+OJsc7quCq3cuHRRTzJQ4nSe01uqbwGDAYwLvi6VWy3svU5qa05eDRmgzEFTG
+e84Gp/1LQCtpQFr4txkjFchO2whWS80KoQKqmLPyGm1D9Lv53Q4ZsKMgNihs
+rEepuaOZMKHl4yMAYFoOXZCAYzfbhN6b2phcFAHjMUHUw9e3F0QuDk9D0tsr
+riYTrkocqlOKfK4QTomx27O0ON2J6f1rtEojGgfl9RNykN7iKGzjS3914QjW
+W6gGiZejxHsDPEAa4gUp0WiSUSXtD5WJgoyAzLydR2dKWsQ4WlaUXi01CuGy
++xvncSn2nO3bbot8VD5H6XU1CjREVtnIfbeRYO/uofyLUP3olK5RqN6ne6Xo
+eXnJ/bjYphA8NGuuuvuW1SCITmINkZDLC9cGlER9+K65RR/DR3TigkexXMeN
+aJ70ivZYAl0OuhZt3TGIlAzS64TIoyORe3z7Ta1Pp9PZQarYJpF9BBIZIFor
+757PHHuQKRuugiRkp8B7v4eq1BQ+VeAxCKpyZ7XrgEtbY/AWDiaKcGPKPjc3
+AqQraVeQm7kMBT163wFmZArCphzkDOI3bz2oEO8YArMgLq2Vto9jAZlqKyWr
+pi2bSJxuoP1aoD58CHcWMrf8/j1LVdQhKgHQXSik2ID0H2Wc/XnglhzlVFuJ
+JsNIW/EGJlZh/5WDez9U0bXqnBlu3uasPEOezdoKlcCmQlmTO5+uLHYLEtNA
+EH9MtnGZebi9XS5meTuS6z5LILt8O9IHZxmT3JRPHYj287FEzotlLdcJ4Ee5
+enW41UHjLrfv4OaITO1hVuoLRGdzjESx/fHMWmxroZ1nVClxECOdT42zvIYJ
+J3xBZ0gppzQ5fjoYiKjJpxTflRxUuxshk3ih6VUoKtqj/W18tBQ3g5SOlkgT
+yCW8r74yZlfYmNrPyDMUQYpLUPWj2n71GF0KyPfTU5yOatRgvheh262w5BG3
+omFY7mb3tCv8/U2jdMIoukRKacpZiagofz3SxojOJq52cHnCri+gTHBMX0cO
+j58ygfntHWRzst0pV7Ze2X3fdCAJ4DokH6bNJNthcgmolFJ/y3V1tJjgsdtQ
+7Pjn/vE6xUV0HXE2x4yoVYNirbAMIvkN/X+atxrN0dA4AchN+zGp8TAxMCEw
+CQYFKw4DAhoFAAQUQ+6XXkyhf6uYgtbibILN2IjKnOAECLiqoY45MPCrAgII
+AA==
EOF
p12 = OpenSSL::PKCS12.new(str, "abc123")
assert_equal nil, p12.key
assert_equal nil, p12.certificate
assert_equal 1, p12.ca_certs.size
- assert_equal @mycert.subject.to_der, p12.ca_certs[0].subject.to_der
+ assert_equal @mycert.subject, p12.ca_certs[0].subject
end
def test_new_with_no_certs
# generated with:
- # openssl pkcs12 -inkey <RSA1024> -nocerts -export -out <out>
+ # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export
str = <<~EOF.unpack("m").first
-MIIDJwIBAzCCAu0GCSqGSIb3DQEHAaCCAt4EggLaMIIC1jCCAtIGCSqGSIb3DQEH
-AaCCAsMEggK/MIICuzCCArcGCyqGSIb3DQEMCgECoIICpjCCAqIwHAYKKoZIhvcN
-AQwBAzAOBAg6AaYnJs84SwICCAAEggKAQzZH+fWSpcQYD1J7PsGSune85A++fLCQ
-V7tacp2iv95GJkxwYmfTP176pJdgs00mceB9UJ/u9EX5nD0djdjjQjwo6sgKjY0q
-cpVhZw8CMxw7kBD2dhtui0zT8z5hy03LePxsjEKsGiSbeVeeGbSfw/I6AAYbv+Uh
-O/YPBGumeHj/D2WKnfsHJLQ9GAV3H6dv5VKYNxjciK7f/JEyZCuUQGIN64QFHDhJ
-7fzLqd/ul3FZzJZO6a+dwvcgux09SKVXDRSeFmRCEX4b486iWhJJVspCo9P2KNne
-ORrpybr3ZSwxyoICmjyo8gj0OSnEfdx9790Ej1takPqSA1wIdSdBLekbZqB0RBQg
-DEuPOsXNo3QFi8ji1vu0WBRJZZSNC2hr5NL6lNR+DKxG8yzDll2j4W4BBIp22mAE
-7QRX7kVxu17QJXQhOUac4Dd1qXmzebP8t6xkAxD9L7BWEN5OdiXWwSWGjVjMBneX
-nYObi/3UT/aVc5WHMHK2BhCI1bwH51E6yZh06d5m0TQpYGUTWDJdWGBSrp3A+8jN
-N2PMQkWBFrXP3smHoTEN4oZC4FWiPsIEyAkQsfKRhcV9lGKl2Xgq54ROTFLnwKoj
-Z3zJScnq9qmNzvVZSMmDLkjLyDq0pxRxGKBvgouKkWY7VFFIwwBIJM39iDJ5NbBY
-i1AQFTRsRSsZrNVPasCXrIq7bhMoJZb/YZOGBLNyJVqKUoYXhtwsajzSq54VlWft
-JxsPayEd4Vi6O9EU1ahnj6qFEZiKFzsicgK2J1Rb8cYagrp0XWjHW0SBn5GVUWCg
-GUokSFG/0JTdeYTo/sQuG4qNgJkOolRjpeI48Fciq5VUWLvVdKioXzAxMCEwCQYF
-Kw4DAhoFAAQUYAuwVtGD1TdgbFK4Yal2XBgwUR4ECEawsN3rNaa6AgIIAA==
+MIIJ7wIBAzCCCbUGCSqGSIb3DQEHAaCCCaYEggmiMIIJnjCCCZoGCSqGSIb3
+DQEHAaCCCYsEggmHMIIJgzCCCX8GCyqGSIb3DQEMCgECoIIJbjCCCWowHAYK
+KoZIhvcNAQwBAzAOBAjX5nN8jyRKwQICCAAEgglIBIRLHfiY1mNHpl3FdX6+
+72L+ZOVXnlZ1MY9HSeg0RMkCJcm0mJ2UD7INUOGXvwpK9fr6WJUZM1IqTihQ
+1dM0crRC2m23aP7KtAlXh2DYD3otseDtwoN/NE19RsiJzeIiy5TSW1d47weU
++D4Ig/9FYVFPTDgMzdCxXujhvO/MTbZIjqtcS+IOyF+91KkXrHkfkGjZC7KS
+WRmYw9BBuIPQEewdTI35sAJcxT8rK7JIiL/9mewbSE+Z28Wq1WXwmjL3oZm9
+lw6+f515b197GYEGomr6LQqJJamSYpwQbTGHonku6Tf3ylB4NLFqOnRCKE4K
+zRSSYIqJBlKHmQ4pDm5awoupHYxMZLZKZvXNYyYN3kV8r1iiNVlY7KBR4CsX
+rqUkXehRmcPnuqEMW8aOpuYe/HWf8PYI93oiDZjcEZMwW2IZFFrgBbqUeNCM
+CQTkjAYxi5FyoaoTnHrj/aRtdLOg1xIJe4KKcmOXAVMmVM9QEPNfUwiXJrE7
+n42gl4NyzcZpxqwWBT++9TnQGZ/lEpwR6dzkZwICNQLdQ+elsdT7mumywP+1
+WaFqg9kpurimaiBu515vJNp9Iqv1Nmke6R8Lk6WVRKPg4Akw0fkuy6HS+LyN
+ofdCfVUkPGN6zkjAxGZP9ZBwvXUbLRC5W3N5qZuAy5WcsS75z+oVeX9ePV63
+cue23sClu8JSJcw3HFgPaAE4sfkQ4MoihPY5kezgT7F7Lw/j86S0ebrDNp4N
+Y685ec81NRHJ80CAM55f3kGCOEhoifD4VZrvr1TdHZY9Gm3b1RYaJCit2huF
+nlOfzeimdcv/tkjb6UsbpXx3JKkF2NFFip0yEBERRCdWRYMUpBRcl3ad6XHy
+w0pVTgIjTxGlbbtOCi3siqMOK0GNt6UgjoEFc1xqjsgLwU0Ta2quRu7RFPGM
+GoEwoC6VH23p9Hr4uTFOL0uHfkKWKunNN+7YPi6LT6IKmTQwrp+fTO61N6Xh
+KlqTpwESKsIJB2iMnc8wBkjXJtmG/e2n5oTqfhICIrxYmEb7zKDyK3eqeTj3
+FhQh2t7cUIiqcT52AckUqniPmlE6hf82yBjhaQUPfi/ExTBtTDSmFfRPUzq+
+Rlla4OHllPRzUXJExyansgCxZbPqlw46AtygSWRGcWoYAKUKwwoYjerqIV5g
+JoZICV9BOU9TXco1dHXZQTs/nnTwoRmYiL/Ly5XpvUAnQOhYeCPjBeFnPSBR
+R/hRNqrDH2MOV57v5KQIH2+mvy26tRG+tVGHmLMaOJeQkjLdxx+az8RfXIrH
+7hpAsoBb+g9jUDY1mUVavPk1T45GMpQH8u3kkzRvChfOst6533GyIZhE7FhN
+KanC6ACabVFDUs6P9pK9RPQMp1qJfpA0XJFx5TCbVbPkvnkZd8K5Tl/tzNM1
+n32eRao4MKr9KDwoDL93S1yJgYTlYjy1XW/ewdedtX+B4koAoz/wSXDYO+GQ
+Zu6ZSpKSEHTRPhchsJ4oICvpriVaJkn0/Z7H3YjNMB9U5RR9+GiIg1wY1Oa1
+S3WfuwrrI6eqfbQwj6PDNu3IKy6srEgvJwaofQALNBPSYWbauM2brc8qsD+t
+n8jC/aD1aMcy00+9t3H/RVCjEOb3yKfUpAldIkEA2NTTnZpoDQDXeNYU2F/W
+yhmFjJy8A0O4QOk2xnZK9kcxSRs0v8vI8HivvgWENoVPscsDC4742SSIe6SL
+f/T08reIX11f0K70rMtLhtFMQdHdYOTNl6JzhkHPLr/f9MEZsBEQx52depnF
+ARb3gXGbCt7BAi0OeCEBSbLr2yWuW4r55N0wRZSOBtgqgjsiHP7CDQSkbL6p
+FPlQS1do9gBSHiNYvsmN1LN5bG+mhcVb0UjZub4mL0EqGadjDfDdRJmWqlX0
+r5dyMcOWQVy4O2cPqYFlcP9lk8buc5otcyVI2isrAFdlvBK29oK6jc52Aq5Q
+0b2ESDlgX8WRgiOPPxK8dySKEeuIwngCtJyNTecP9Ug06TDsu0znZGCXJ+3P
+8JOpykgA8EQdOZOYHbo76ZfB2SkklI5KeRA5IBjGs9G3TZ4PHLy2DIwsbWzS
+H1g01o1x264nx1cJ+eEgUN/KIiGFIib42RS8Af4D5e+Vj54Rt3axq+ag3kI+
+53p8uotyu+SpvvXUP7Kv4xpQ/L6k41VM0rfrd9+DrlDVvSfxP2uh6I1TKF7A
+CT5n8zguMbng4PGjxvyPBM5k62t6hN5fuw6Af0aZFexh+IjB/5wFQ6onSz23
+fBzMW4St7RgSs8fDg3lrM+5rwXiey1jxY1ddaxOoUsWRMvvdd7rZxRZQoN5v
+AcI5iMkK/vvpQgC/sfzhtXtrJ2XOPZ+GVgi7VcuDLKSkdFMcPbGzO8SdxUnS
+SLV5XTKqKND+Lrfx7DAoKi5wbDFHu5496/MHK5qP4tBe6sJ5bZc+KDJIH46e
+wTV1oWtB5tV4q46hOb5WRcn/Wjz3HSKaGZgx5QbK1MfKTzD5CTUn+ArMockX
+2wJhPnFK85U4rgv8iBuh9bRjyw+YaKf7Z3loXRiE1eRG6RzuPF0ZecFiDumk
+AC/VUXynJhzePBLqzrQj0exanACdullN+pSfHiRWBxR2VFUkjoFP5X45GK3z
+OstSH6FOkMVU4afqEmjsIwozDFIyin5EyWTtdhJe3szdJSGY23Tut+9hUatx
+9FDFLESOd8z3tyQSNiLk/Hib+e/lbjxqbXBG/p/oyvP3N999PLUPtpKqtYkV
+H0+18sNh9CVfojiJl44fzxe8yCnuefBjut2PxEN0EFRBPv9P2wWlmOxkPKUq
+NrCJP0rDj5aONLrNZPrR8bZNdIShkZ/rKkoTuA0WMZ+xUlDRxAupdMkWAlrz
+8IcwNcdDjPnkGObpN5Ctm3vK7UGSBmPeNqkXOYf3QTJ9gStJEd0F6+DzTN5C
+KGt1IyuGwZqL2Yk51FDIIkr9ykEnBMaA39LS7GFHEDNGlW+fKC7AzA0zfoOr
+fXZlHMBuqHtXqk3zrsHRqGGoocigg4ctrhD1UREYKj+eIj1TBiRdf7c6+COf
+NIOmej8pX3FmZ4ui+dDA8r2ctgsWHrb4A6iiH+v1DRA61GtoaA/tNRggewXW
+VXCZCGWyyTuyHGOqq5ozrv5MlzZLWD/KV/uDsAWmy20RAed1C4AzcXlpX25O
+M4SNl47g5VRNJRtMqokc8j6TjZrzMDEwITAJBgUrDgMCGgUABBRrkIRuS5qg
+BC8fv38mue8LZVcbHQQIUNrWKEnskCoCAggA
EOF
p12 = OpenSSL::PKCS12.new(str, "abc123")
- assert_equal @mykey.to_der, p12.key.to_der
+ assert_equal Fixtures.pkey("rsa-1").to_der, p12.key.to_der
assert_equal nil, p12.certificate
assert_equal [], Array(p12.ca_certs)
end
def test_dup
- p12 = OpenSSL::PKCS12.create("pass", "name", @mykey, @mycert)
+ p12 = OpenSSL::PKCS12.create(
+ "pass",
+ "name",
+ @mykey,
+ @mycert,
+ nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
+ )
assert_equal p12.to_der, p12.dup.to_der
end
-
- private
- def assert_cert expected, actual
- [
- :subject,
- :issuer,
- :serial,
- :not_before,
- :not_after,
- ].each do |attribute|
- assert_equal expected.send(attribute), actual.send(attribute)
- end
- assert_equal expected.to_der, actual.to_der
- end
-
- def assert_include_cert cert, ary
- der = cert.to_der
- ary.each do |candidate|
- if candidate.to_der == der
- return true
- end
- end
- false
- end
end
end
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb
index 4a539d8c46..1219f3f1d7 100644
--- a/test/openssl/test_pkey.rb
+++ b/test/openssl/test_pkey.rb
@@ -27,20 +27,16 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
end
def test_s_generate_parameters
- # 512 is non-default; 1024 is used if 'dsa_paramgen_bits' is not specified
- # with OpenSSL 1.1.0.
- pkey = OpenSSL::PKey.generate_parameters("DSA", {
- "dsa_paramgen_bits" => 512,
- "dsa_paramgen_q_bits" => 256,
+ pkey = OpenSSL::PKey.generate_parameters("EC", {
+ "ec_paramgen_curve" => "secp384r1",
})
- assert_instance_of OpenSSL::PKey::DSA, pkey
- assert_equal 512, pkey.p.num_bits
- assert_equal 256, pkey.q.num_bits
- assert_equal nil, pkey.priv_key
+ assert_instance_of OpenSSL::PKey::EC, pkey
+ assert_equal "secp384r1", pkey.group.curve_name
+ assert_equal nil, pkey.private_key
# Invalid options are checked
assert_raise(OpenSSL::PKey::PKeyError) {
- OpenSSL::PKey.generate_parameters("DSA", "invalid" => "option")
+ OpenSSL::PKey.generate_parameters("EC", "invalid" => "option")
}
# Parameter generation callback is called
@@ -51,6 +47,11 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
raise "exit!" if cb_called.size == 3
}
}
+ if !cb_called && openssl?(3, 0, 0) && !openssl?(3, 0, 6)
+ # Errors in BN_GENCB were not properly handled. This special pend is to
+ # suppress failures on Ubuntu 22.04, which uses OpenSSL 3.0.2.
+ pend "unstable test on OpenSSL 3.0.[0-5]"
+ end
assert_not_empty cb_called
end
@@ -59,14 +60,13 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
# DSA key pair cannot be generated without parameters
OpenSSL::PKey.generate_key("DSA")
}
- pkey_params = OpenSSL::PKey.generate_parameters("DSA", {
- "dsa_paramgen_bits" => 512,
- "dsa_paramgen_q_bits" => 256,
+ pkey_params = OpenSSL::PKey.generate_parameters("EC", {
+ "ec_paramgen_curve" => "secp384r1",
})
pkey = OpenSSL::PKey.generate_key(pkey_params)
- assert_instance_of OpenSSL::PKey::DSA, pkey
- assert_equal 512, pkey.p.num_bits
- assert_not_equal nil, pkey.priv_key
+ assert_instance_of OpenSSL::PKey::EC, pkey
+ assert_equal "secp384r1", pkey.group.curve_name
+ assert_not_equal nil, pkey.private_key
end
def test_hmac_sign_verify
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index f80af8f841..161af1897b 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -26,26 +26,33 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
end
def test_derive_key
- dh1 = Fixtures.pkey("dh1024").generate_key!
- dh2 = Fixtures.pkey("dh1024").generate_key!
+ params = Fixtures.pkey("dh1024")
+ dh1 = OpenSSL::PKey.generate_key(params)
+ dh2 = OpenSSL::PKey.generate_key(params)
dh1_pub = OpenSSL::PKey.read(dh1.public_to_der)
dh2_pub = OpenSSL::PKey.read(dh2.public_to_der)
+
z = dh1.g.mod_exp(dh1.priv_key, dh1.p).mod_exp(dh2.priv_key, dh1.p).to_s(2)
assert_equal z, dh1.derive(dh2_pub)
assert_equal z, dh2.derive(dh1_pub)
+ assert_raise(OpenSSL::PKey::PKeyError) { params.derive(dh1_pub) }
+ assert_raise(OpenSSL::PKey::PKeyError) { dh1_pub.derive(params) }
+
assert_equal z, dh1.compute_key(dh2.pub_key)
assert_equal z, dh2.compute_key(dh1.pub_key)
end
def test_DHparams
dh1024 = Fixtures.pkey("dh1024")
+ dh1024params = dh1024.public_key
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(dh1024.p),
OpenSSL::ASN1::Integer(dh1024.g)
])
key = OpenSSL::PKey::DH.new(asn1.to_der)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh1024params, key
pem = <<~EOF
-----BEGIN DH PARAMETERS-----
@@ -55,9 +62,9 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
-----END DH PARAMETERS-----
EOF
key = OpenSSL::PKey::DH.new(pem)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh1024params, key
key = OpenSSL::PKey.read(pem)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh1024params, key
assert_equal asn1.to_der, dh1024.to_der
assert_equal pem, dh1024.export
@@ -72,19 +79,16 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
end
def test_generate_key
- dh = Fixtures.pkey("dh1024").public_key # creates a copy
+ # Deprecated in v3.0.0; incompatible with OpenSSL 3.0
+ dh = Fixtures.pkey("dh1024").public_key # creates a copy with params only
assert_no_key(dh)
dh.generate_key!
assert_key(dh)
- end
- def test_key_exchange
- dh = Fixtures.pkey("dh1024")
dh2 = dh.public_key
- dh.generate_key!
dh2.generate_key!
assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key))
- end
+ end if !openssl?(3, 0, 0)
def test_params_ok?
dh0 = Fixtures.pkey("dh1024")
@@ -103,13 +107,32 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
end
def test_dup
- dh = Fixtures.pkey("dh1024")
- dh2 = dh.dup
- assert_equal dh.to_der, dh2.to_der # params
- assert_equal_params dh, dh2 # keys
- dh2.set_pqg(dh2.p + 1, nil, dh2.g)
- assert_not_equal dh2.p, dh.p
- assert_equal dh2.g, dh.g
+ # Parameters only
+ dh1 = Fixtures.pkey("dh1024")
+ dh2 = dh1.dup
+ assert_equal dh1.to_der, dh2.to_der
+ assert_not_equal nil, dh1.p
+ assert_not_equal nil, dh1.g
+ assert_equal [dh1.p, dh1.g], [dh2.p, dh2.g]
+ assert_equal nil, dh1.pub_key
+ assert_equal nil, dh1.priv_key
+ assert_equal [dh1.pub_key, dh1.priv_key], [dh2.pub_key, dh2.priv_key]
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ dh2.set_pqg(dh2.p + 1, nil, dh2.g)
+ assert_not_equal dh2.p, dh1.p
+ end
+
+ # With a key pair
+ dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh1024"))
+ dh4 = dh3.dup
+ assert_equal dh3.to_der, dh4.to_der
+ assert_equal dh1.to_der, dh4.to_der # encodes parameters only
+ assert_equal [dh1.p, dh1.g], [dh4.p, dh4.g]
+ assert_not_equal nil, dh3.pub_key
+ assert_not_equal nil, dh3.priv_key
+ assert_equal [dh3.pub_key, dh3.priv_key], [dh4.pub_key, dh4.priv_key]
end
def test_marshal
@@ -121,11 +144,6 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
private
- def assert_equal_params(dh1, dh2)
- assert_equal(dh1.g, dh2.g)
- assert_equal(dh1.p, dh2.p)
- end
-
def assert_no_key(dh)
assert_equal(false, dh.public?)
assert_equal(false, dh.private?)
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index 147e50176b..d1059093c5 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -28,6 +28,25 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
end
end
+ def test_generate
+ # DSA.generate used to call DSA_generate_parameters_ex(), which adjusts the
+ # size of q according to the size of p
+ key1024 = OpenSSL::PKey::DSA.generate(1024)
+ assert_predicate key1024, :private?
+ assert_equal 1024, key1024.p.num_bits
+ assert_equal 160, key1024.q.num_bits
+
+ key2048 = OpenSSL::PKey::DSA.generate(2048)
+ assert_equal 2048, key2048.p.num_bits
+ assert_equal 256, key2048.q.num_bits
+
+ if ENV["OSSL_TEST_ALL"] == "1" # slow
+ key3072 = OpenSSL::PKey::DSA.generate(3072)
+ assert_equal 3072, key3072.p.num_bits
+ assert_equal 256, key3072.q.num_bits
+ end
+ end
+
def test_sign_verify
dsa512 = Fixtures.pkey("dsa512")
data = "Sign me!"
@@ -36,8 +55,8 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
assert_equal true, dsa512.verify(OpenSSL::Digest.new('DSS1'), signature, data)
end
- signature = dsa512.sign("SHA1", data)
- assert_equal true, dsa512.verify("SHA1", signature, data)
+ signature = dsa512.sign("SHA256", data)
+ assert_equal true, dsa512.verify("SHA256", signature, data)
signature0 = (<<~'end;').unpack("m")[0]
MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/
@@ -138,6 +157,8 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
def test_PUBKEY
dsa512 = Fixtures.pkey("dsa512")
+ dsa512pub = OpenSSL::PKey::DSA.new(dsa512.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("DSA"),
@@ -153,7 +174,7 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::DSA.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_dsa dup_public(dsa512), key
+ assert_same_dsa dsa512pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -166,10 +187,15 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::DSA.new(pem)
- assert_same_dsa dup_public(dsa512), key
+ assert_same_dsa dsa512pub, key
- assert_equal asn1.to_der, dup_public(dsa512).to_der
- assert_equal pem, dup_public(dsa512).export
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
+
+ assert_equal asn1.to_der, dsa512.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, dsa512.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_read_DSAPublicKey_pem
@@ -201,8 +227,12 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ==
key = Fixtures.pkey("dsa1024")
key2 = key.dup
assert_equal key.params, key2.params
- key2.set_pqg(key2.p + 1, key2.q, key2.g)
- assert_not_equal key.params, key2.params
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key2.set_pqg(key2.p + 1, key2.q, key2.g)
+ assert_not_equal key.params, key2.params
+ end
end
def test_marshal
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 0a460bd536..e5fef940a6 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require_relative 'utils'
-if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC)
+if defined?(OpenSSL)
class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_ec_key
@@ -13,21 +13,23 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
# FIPS-selftest failure on some environment, so skip for now.
next if ["Oakley", "X25519"].any? { |n| curve_name.start_with?(n) }
- key = OpenSSL::PKey::EC.new(curve_name)
- key.generate_key!
-
+ key = OpenSSL::PKey::EC.generate(curve_name)
assert_predicate key, :private?
assert_predicate key, :public?
assert_nothing_raised { key.check_key }
end
- key1 = OpenSSL::PKey::EC.new("prime256v1").generate_key!
+ key1 = OpenSSL::PKey::EC.generate("prime256v1")
- key2 = OpenSSL::PKey::EC.new
- key2.group = key1.group
- key2.private_key = key1.private_key
- key2.public_key = key1.public_key
- assert_equal key1.to_der, key2.to_der
+ # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is
+ # deprecated
+ if !openssl?(3, 0, 0)
+ key2 = OpenSSL::PKey::EC.new
+ key2.group = key1.group
+ key2.private_key = key1.private_key
+ key2.public_key = key1.public_key
+ assert_equal key1.to_der, key2.to_der
+ end
key3 = OpenSSL::PKey::EC.new(key1)
assert_equal key1.to_der, key3.to_der
@@ -37,10 +39,14 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
key5 = key1.dup
assert_equal key1.to_der, key5.to_der
- key_tmp = OpenSSL::PKey::EC.new("prime256v1").generate_key!
- key5.private_key = key_tmp.private_key
- key5.public_key = key_tmp.public_key
- assert_not_equal key1.to_der, key5.to_der
+
+ # PKey is immutable in OpenSSL >= 3.0; EC object should not be modified
+ if !openssl?(3, 0, 0)
+ key_tmp = OpenSSL::PKey::EC.generate("prime256v1")
+ key5.private_key = key_tmp.private_key
+ key5.public_key = key_tmp.public_key
+ assert_not_equal key1.to_der, key5.to_der
+ end
end
def test_generate
@@ -52,6 +58,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal(true, ec.private?)
end
+ def test_generate_key
+ ec = OpenSSL::PKey::EC.new("prime256v1")
+ assert_equal false, ec.private?
+ assert_raise(OpenSSL::PKey::ECError) { ec.to_der }
+ ec.generate_key!
+ assert_equal true, ec.private?
+ assert_nothing_raised { ec.to_der }
+ end if !openssl?(3, 0, 0)
+
def test_marshal
key = Fixtures.pkey("p256")
deserialized = Marshal.load(Marshal.dump(key))
@@ -60,29 +75,40 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
end
def test_check_key
- key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
- assert_equal(true, key.check_key)
- assert_equal(true, key.private?)
- assert_equal(true, key.public?)
- key2 = OpenSSL::PKey::EC.new(key.group)
- assert_equal(false, key2.private?)
- assert_equal(false, key2.public?)
- key2.public_key = key.public_key
- assert_equal(false, key2.private?)
- assert_equal(true, key2.public?)
- key2.private_key = key.private_key
+ key0 = Fixtures.pkey("p256")
+ assert_equal(true, key0.check_key)
+ assert_equal(true, key0.private?)
+ assert_equal(true, key0.public?)
+
+ key1 = OpenSSL::PKey.read(key0.public_to_der)
+ assert_equal(true, key1.check_key)
+ assert_equal(false, key1.private?)
+ assert_equal(true, key1.public?)
+
+ key2 = OpenSSL::PKey.read(key0.private_to_der)
assert_equal(true, key2.private?)
assert_equal(true, key2.public?)
assert_equal(true, key2.check_key)
- key2.private_key += 1
- assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
+
+ # Behavior of EVP_PKEY_public_check changes between OpenSSL 1.1.1 and 3.0
+ key4 = Fixtures.pkey("p256_too_large")
+ assert_raise(OpenSSL::PKey::ECError) { key4.check_key }
+
+ key5 = Fixtures.pkey("p384_invalid")
+ assert_raise(OpenSSL::PKey::ECError) { key5.check_key }
+
+ # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0
+ if !openssl?(3, 0, 0)
+ key2.private_key += 1
+ assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
+ end
end
def test_sign_verify
p256 = Fixtures.pkey("p256")
data = "Sign me!"
- signature = p256.sign("SHA1", data)
- assert_equal true, p256.verify("SHA1", signature, data)
+ signature = p256.sign("SHA256", data)
+ assert_equal true, p256.verify("SHA256", signature, data)
signature0 = (<<~'end;').unpack("m")[0]
MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq
@@ -107,7 +133,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal [zIUT].pack("H*"), a.derive(b)
assert_equal a.derive(b), a.dh_compute_key(b.public_key)
- end
+ end if !openssl?(3, 0, 0) # TODO: Test it without using #private_key=
def test_sign_verify_raw
key = Fixtures.pkey("p256")
@@ -136,7 +162,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
end
def test_dsa_sign_asn1_FIPS186_3
- key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
+ key = OpenSSL::PKey::EC.generate("prime256v1")
size = key.group.order.num_bits / 8 + 1
dgst = (1..size).to_a.pack('C*')
sig = key.dsa_sign_asn1(dgst)
@@ -145,8 +171,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
end
def test_dh_compute_key
- key_a = OpenSSL::PKey::EC.new("prime256v1").generate_key!
- key_b = OpenSSL::PKey::EC.new(key_a.group).generate_key!
+ key_a = OpenSSL::PKey::EC.generate("prime256v1")
+ key_b = OpenSSL::PKey::EC.generate(key_a.group)
pub_a = key_a.public_key
pub_b = key_b.public_key
@@ -182,6 +208,29 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal pem, p256.export
end
+ def test_ECPrivateKey_with_parameters
+ p256 = Fixtures.pkey("p256")
+
+ # The format used by "openssl ecparam -name prime256v1 -genkey -outform PEM"
+ #
+ # "EC PARAMETERS" block should be ignored if it is followed by an
+ # "EC PRIVATE KEY" block
+ in_pem = <<~EOF
+ -----BEGIN EC PARAMETERS-----
+ BggqhkjOPQMBBw==
+ -----END EC PARAMETERS-----
+ -----BEGIN EC PRIVATE KEY-----
+ MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49
+ AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt
+ CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
+ -----END EC PRIVATE KEY-----
+ EOF
+
+ key = OpenSSL::PKey::EC.new(in_pem)
+ assert_same_ec p256, key
+ assert_equal p256.to_der, key.to_der
+ end
+
def test_ECPrivateKey_encrypted
p256 = Fixtures.pkey("p256")
# key = abcdef
@@ -210,6 +259,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_PUBKEY
p256 = Fixtures.pkey("p256")
+ p256pub = OpenSSL::PKey::EC.new(p256.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
@@ -221,7 +272,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::EC.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_ec dup_public(p256), key
+ assert_same_ec p256pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -230,10 +281,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::EC.new(pem)
- assert_same_ec dup_public(p256), key
+ assert_same_ec p256pub, key
+
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
- assert_equal asn1.to_der, dup_public(p256).to_der
- assert_equal pem, dup_public(p256).export
+ assert_equal asn1.to_der, p256.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, p256.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_ec_group
@@ -269,7 +325,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_ec_point
group = OpenSSL::PKey::EC::Group.new("prime256v1")
- key = OpenSSL::PKey::EC.new(group).generate_key!
+ key = OpenSSL::PKey::EC.generate(group)
point = key.public_key
point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn)
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index 5e127f5407..b0ae5784b3 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -11,7 +11,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
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
+ end if !openssl?(3, 0, 0) # Impossible state in OpenSSL 3.0
def test_private
# Generated by key size and public exponent
@@ -31,15 +31,18 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
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?)
+ if !openssl?(3, 0, 0)
+ key = OpenSSL::PKey::RSA.new
+ # Generated by RSA#set_key
+ key5 = OpenSSL::PKey::RSA.new
+ key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert(key5.private?)
+
+ # Generated by RSA#set_key, without d
+ key6 = OpenSSL::PKey::RSA.new
+ key6.set_key(rsa1024.n, rsa1024.e, nil)
+ assert(!key6.private?)
+ end
end
def test_new
@@ -77,8 +80,8 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_sign_verify
rsa1024 = Fixtures.pkey("rsa1024")
data = "Sign me!"
- signature = rsa1024.sign("SHA1", data)
- assert_equal true, rsa1024.verify("SHA1", signature, data)
+ signature = rsa1024.sign("SHA256", data)
+ assert_equal true, rsa1024.verify("SHA256", signature, data)
signature0 = (<<~'end;').unpack("m")[0]
oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+
@@ -105,15 +108,20 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
salt_length: 20, mgf1_hash: "SHA1")
# Defaults to PKCS #1 v1.5 padding => verification failure
assert_equal false, key.verify("SHA256", sig_pss, data)
+
+ # option type check
+ assert_raise_with_message(TypeError, /expected Hash/) {
+ key.sign("SHA256", data, ["x"])
+ }
end
def test_sign_verify_raw
key = Fixtures.pkey("rsa-1")
data = "Sign me!"
- hash = OpenSSL::Digest.digest("SHA1", data)
- signature = key.sign_raw("SHA1", hash)
- assert_equal true, key.verify_raw("SHA1", signature, hash)
- assert_equal true, key.verify("SHA1", signature, data)
+ hash = OpenSSL::Digest.digest("SHA256", data)
+ signature = key.sign_raw("SHA256", hash)
+ assert_equal true, key.verify_raw("SHA256", signature, hash)
+ assert_equal true, key.verify("SHA256", signature, data)
# Too long data
assert_raise(OpenSSL::PKey::PKeyError) {
@@ -126,9 +134,9 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
"rsa_pss_saltlen" => 20,
"rsa_mgf1_md" => "SHA256"
}
- sig_pss = key.sign_raw("SHA1", hash, pssopts)
- assert_equal true, key.verify("SHA1", sig_pss, data, pssopts)
- assert_equal true, key.verify_raw("SHA1", sig_pss, hash, pssopts)
+ sig_pss = key.sign_raw("SHA256", hash, pssopts)
+ assert_equal true, key.verify("SHA256", sig_pss, data, pssopts)
+ assert_equal true, key.verify_raw("SHA256", sig_pss, hash, pssopts)
end
def test_sign_verify_raw_legacy
@@ -201,7 +209,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_encrypt_decrypt
rsapriv = Fixtures.pkey("rsa-1")
- rsapub = dup_public(rsapriv)
+ rsapub = OpenSSL::PKey.read(rsapriv.public_to_der)
# Defaults to PKCS #1 v1.5
raw = "data"
@@ -216,7 +224,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_encrypt_decrypt_legacy
rsapriv = Fixtures.pkey("rsa-1")
- rsapub = dup_public(rsapriv)
+ rsapub = OpenSSL::PKey.read(rsapriv.public_to_der)
# Defaults to PKCS #1 v1.5
raw = "data"
@@ -235,36 +243,52 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
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
+ pub = OpenSSL::PKey.read(rsa1024.public_to_der)
+ assert_not_equal rsa1024.export, pub.export
+ assert_equal rsa1024.public_to_pem, pub.export
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key = OpenSSL::PKey::RSA.new
+
+ # key has only n, e and d
+ key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert_equal rsa1024.public_key.export, key.export
- # key has only n, e, d, p and q
- key.set_factors(rsa1024.p, rsa1024.q)
- assert_equal rsa1024.public_key.export, key.export
+ # key has 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
+ # key has n, e, d, p, q, dmp1, dmq1 and iqmp
+ key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
+ assert_equal rsa1024.export, key.export
+ end
end
def test_to_der
rsa1024 = Fixtures.pkey("rsa1024")
- 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
+ pub = OpenSSL::PKey.read(rsa1024.public_to_der)
+ assert_not_equal rsa1024.to_der, pub.to_der
+ assert_equal rsa1024.public_to_der, pub.to_der
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key = OpenSSL::PKey::RSA.new
- # key has only n, e, d, p and q
- key.set_factors(rsa1024.p, rsa1024.q)
- assert_equal rsa1024.public_key.to_der, key.to_der
+ # 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 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
+ # key has only n, e, d, p and q
+ key.set_factors(rsa1024.p, rsa1024.q)
+ assert_equal rsa1024.public_key.to_der, key.to_der
+
+ # key has n, e, d, p, q, dmp1, dmq1 and iqmp
+ key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
+ assert_equal rsa1024.to_der, key.to_der
+ end
end
def test_RSAPrivateKey
@@ -306,6 +330,12 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
assert_equal asn1.to_der, rsa1024.to_der
assert_equal pem, rsa1024.export
+
+ # Unknown PEM prepended
+ cert = issue_cert(OpenSSL::X509::Name.new([["CN", "nobody"]]), rsa1024, 1, [], nil, nil)
+ str = cert.to_text + cert.to_pem + rsa1024.to_pem
+ key = OpenSSL::PKey::RSA.new(str)
+ assert_same_rsa rsa1024, key
end
def test_RSAPrivateKey_encrypted
@@ -346,13 +376,15 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_RSAPublicKey
rsa1024 = Fixtures.pkey("rsa1024")
+ rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(rsa1024.n),
OpenSSL::ASN1::Integer(rsa1024.e)
])
key = OpenSSL::PKey::RSA.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
pem = <<~EOF
-----BEGIN RSA PUBLIC KEY-----
@@ -362,11 +394,13 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
-----END RSA PUBLIC KEY-----
EOF
key = OpenSSL::PKey::RSA.new(pem)
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
end
def test_PUBKEY
rsa1024 = Fixtures.pkey("rsa1024")
+ rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("rsaEncryption"),
@@ -381,7 +415,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::RSA.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -392,10 +426,15 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::RSA.new(pem)
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
- assert_equal asn1.to_der, dup_public(rsa1024).to_der
- assert_equal pem, dup_public(rsa1024).export
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
+
+ assert_equal asn1.to_der, rsa1024.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, rsa1024.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_pem_passwd
@@ -482,18 +521,16 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
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
assert_equal key.params, key2.params
- key2.set_key(key2.n, 3, key2.d)
- assert_not_equal key.params, key2.params
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key2.set_key(key2.n, 3, key2.d)
+ assert_not_equal key.params, key2.params
+ end
end
def test_marshal
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 5dccac5fac..db76f1dc4c 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -1,9 +1,20 @@
# frozen_string_literal: true
require_relative "utils"
-if defined?(OpenSSL)
+if defined?(OpenSSL::SSL)
class OpenSSL::TestSSL < OpenSSL::SSLTestCase
+ def test_bad_socket
+ bad_socket = Struct.new(:sync).new
+ assert_raise TypeError do
+ socket = OpenSSL::SSL::SSLSocket.new bad_socket
+ # if the socket is not a T_FILE, `connect` will segv because it tries
+ # to get the underlying file descriptor but the API it calls assumes
+ # the object type is T_FILE
+ socket.connect
+ end
+ end
+
def test_ctx_options
ctx = OpenSSL::SSL::SSLContext.new
@@ -124,9 +135,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_add_certificate_multiple_certs
- pend "EC is not supported" unless defined?(OpenSSL::PKey::EC)
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ca2_key = Fixtures.pkey("rsa-3")
ca2_exts = [
["basicConstraints", "CA:TRUE", true],
@@ -365,59 +373,20 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
- def test_read_nonblock_without_session
- EnvUtil.suppress_warning do
- start_server(start_immediately: false) { |port|
- sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
- ssl.sync_close = true
-
- assert_equal :wait_readable, ssl.read_nonblock(100, exception: false)
- ssl.write("abc\n")
- IO.select [ssl]
- assert_equal('a', ssl.read_nonblock(1))
- assert_equal("bc\n", ssl.read_nonblock(100))
- assert_equal :wait_readable, ssl.read_nonblock(100, exception: false)
- ssl.close
- }
- end
- end
-
- def test_starttls
- server_proc = -> (ctx, ssl) {
- while line = ssl.gets
- if line =~ /^STARTTLS$/
- ssl.write("x")
- ssl.flush
- ssl.accept
- break
- end
- ssl.write(line)
- end
- readwrite_loop(ctx, ssl)
- }
-
- EnvUtil.suppress_warning do # read/write on not started session
- start_server(start_immediately: false,
- server_proc: server_proc) { |port|
- begin
- sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
-
- ssl.puts "plaintext"
- assert_equal "plaintext\n", ssl.gets
+ def test_unstarted_session
+ start_server do |port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
- ssl.puts("STARTTLS")
- ssl.read(1)
- ssl.connect
+ assert_raise(OpenSSL::SSL::SSLError) { ssl.syswrite("data") }
+ assert_raise(OpenSSL::SSL::SSLError) { ssl.sysread(1) }
- ssl.puts "over-tls"
- assert_equal "over-tls\n", ssl.gets
- ensure
- ssl&.close
- sock&.close
- end
- }
+ ssl.connect
+ ssl.puts "abc"
+ assert_equal "abc\n", ssl.gets
+ ensure
+ ssl&.close
+ sock&.close
end
end
@@ -526,6 +495,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}) { |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
@@ -553,11 +523,10 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_post_connect_check_with_anon_ciphers
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = -> ctx {
ctx.ssl_version = :TLSv1_2
ctx.ciphers = "aNULL"
+ ctx.tmp_dh = Fixtures.pkey("dh-1")
ctx.security_level = 0
}
@@ -596,8 +565,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
exts = [
["keyUsage","keyEncipherment,digitalSignature",true],
- ["subjectAltName","DNS:localhost.localdomain",false],
- ["subjectAltName","IP:127.0.0.1",false],
+ ["subjectAltName","DNS:localhost.localdomain,IP:127.0.0.1",false],
]
@svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
start_server { |port|
@@ -708,10 +676,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
# buzz.example.net, respectively). ...
assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com'))
+
+ # LibreSSL 3.5.0+ doesn't support other wildcard certificates
+ # (it isn't required to, as RFC states MAY, not MUST)
+ return if libressl?(3, 5, 0)
+
assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com'))
assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com'))
+
# Section 6.4.3 of RFC6125 states that client should NOT match identifier
# where wildcard is other than left-most label.
#
@@ -830,9 +804,56 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
+ def test_keylog_cb
+ pend "Keylog callback is not supported" if !openssl?(1, 1, 1) || libressl?
+
+ prefix = 'CLIENT_RANDOM'
+ context = OpenSSL::SSL::SSLContext.new
+ context.min_version = context.max_version = OpenSSL::SSL::TLS1_2_VERSION
+
+ cb_called = false
+ context.keylog_cb = proc do |_sock, line|
+ cb_called = true
+ assert_equal(prefix, line.split.first)
+ end
+
+ start_server do |port|
+ server_connect(port, context) do |ssl|
+ ssl.puts "abc"
+ assert_equal("abc\n", ssl.gets)
+ assert_equal(true, cb_called)
+ end
+ end
+
+ if tls13_supported?
+ prefixes = [
+ 'SERVER_HANDSHAKE_TRAFFIC_SECRET',
+ 'EXPORTER_SECRET',
+ 'SERVER_TRAFFIC_SECRET_0',
+ 'CLIENT_HANDSHAKE_TRAFFIC_SECRET',
+ 'CLIENT_TRAFFIC_SECRET_0',
+ ]
+ context = OpenSSL::SSL::SSLContext.new
+ context.min_version = context.max_version = OpenSSL::SSL::TLS1_3_VERSION
+ cb_called = false
+ context.keylog_cb = proc do |_sock, line|
+ cb_called = true
+ assert_not_nil(prefixes.delete(line.split.first))
+ end
+
+ start_server do |port|
+ server_connect(port, context) do |ssl|
+ ssl.puts "abc"
+ assert_equal("abc\n", ssl.gets)
+ assert_equal(true, cb_called)
+ end
+ assert_equal(0, prefixes.size)
+ end
+ end
+ end
+
def test_tlsext_hostname
fooctx = OpenSSL::SSL::SSLContext.new
- fooctx.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
fooctx.cert = @cli_cert
fooctx.key = @cli_key
@@ -884,7 +905,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.cert = @svr_cert
ctx2.key = @svr_key
- ctx2.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
ctx2.servername_cb = lambda { |args| Object.new }
sock1, sock2 = socketpair
@@ -927,14 +947,12 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- begin
- sock = TCPSocket.new("127.0.0.1", port)
- sock.puts "abc"
- ensure
- sock&.close
- end
+ sock = TCPSocket.new("127.0.0.1", port)
+ sock << "\x00" * 1024
assert t.join
+ ensure
+ sock&.close
server.close
end
@@ -1028,14 +1046,15 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
start_server(ignore_listener_error: true) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params
- assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) {
+ assert_raise_with_message(OpenSSL::SSL::SSLError, /certificate/) {
server_connect(port, ctx)
}
}
ctx_proc = proc { |ctx|
+ now = Time.now
ctx.cert = issue_cert(@svr, @svr_key, 30, [], @ca_cert, @ca_key,
- not_before: Time.now-100, not_after: Time.now-10)
+ not_before: now - 7200, not_after: now - 3600)
}
start_server(ignore_listener_error: true, ctx_proc: ctx_proc) { |port|
store = OpenSSL::X509::Store.new
@@ -1242,46 +1261,51 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_options_disable_versions
- # Note: Use of these OP_* flags has been deprecated since OpenSSL 1.1.0.
+ # It's recommended to use SSLContext#{min,max}_version= instead in real
+ # applications. The purpose of this test case is to check that SSL options
+ # are properly propagated to OpenSSL library.
supported = check_supported_protocol_versions
+ if !defined?(OpenSSL::SSL::TLS1_3_VERSION) ||
+ !supported.include?(OpenSSL::SSL::TLS1_2_VERSION) ||
+ !supported.include?(OpenSSL::SSL::TLS1_3_VERSION) ||
+ !defined?(OpenSSL::SSL::OP_NO_TLSv1_3) # LibreSSL < 3.4
+ pend "this test case requires both TLS 1.2 and TLS 1.3 to be supported " \
+ "and enabled by default"
+ end
- if supported.include?(OpenSSL::SSL::TLS1_1_VERSION) &&
- supported.include?(OpenSSL::SSL::TLS1_2_VERSION)
- # Server disables ~ TLS 1.1
- ctx_proc = proc { |ctx|
- ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
- OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1
- }
- start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
- # Client only supports TLS 1.1
- ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_1_VERSION
- assert_handshake_error { server_connect(port, ctx1) { } }
+ # Server disables TLS 1.2 and earlier
+ ctx_proc = proc { |ctx|
+ ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
+ OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 |
+ OpenSSL::SSL::OP_NO_TLSv1_2
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ # Client only supports TLS 1.2
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ assert_handshake_error { server_connect(port, ctx1) { } }
- # Client only supports TLS 1.2
- ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_2_VERSION
- assert_nothing_raised { server_connect(port, ctx2) { } }
- }
+ # Client only supports TLS 1.3
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_3_VERSION
+ assert_nothing_raised { server_connect(port, ctx2) { } }
+ }
- # Server only supports TLS 1.1
- ctx_proc = proc { |ctx|
- ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
- }
- start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
- # Client disables TLS 1.1
- ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_1
- assert_handshake_error { server_connect(port, ctx1) { } }
+ # Server only supports TLS 1.2
+ ctx_proc = proc { |ctx|
+ ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ # Client doesn't support TLS 1.2
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_2
+ assert_handshake_error { server_connect(port, ctx1) { } }
- # Client disables TLS 1.2
- ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_2
- assert_nothing_raised { server_connect(port, ctx2) { } }
- }
- else
- pend "TLS 1.1 and TLS 1.2 must be supported; skipping"
- end
+ # Client supports TLS 1.2 by default
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_3
+ assert_nothing_raised { server_connect(port, ctx2) { } }
+ }
end
def test_ssl_methods_constant
@@ -1331,7 +1355,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ctx1 = OpenSSL::SSL::SSLContext.new
ctx1.cert = @svr_cert
ctx1.key = @svr_key
- ctx1.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
ctx1.alpn_select_cb = -> (protocols) { nil }
ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
@@ -1354,10 +1377,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_protocol_selection_ary
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
advertised = ["http/1.1", "spdy/2"]
ctx_proc = proc { |ctx| ctx.npn_protocols = advertised }
@@ -1375,10 +1395,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_protocol_selection_enum
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
advertised = Object.new
def advertised.each
@@ -1400,10 +1417,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_protocol_selection_cancel
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
start_server_version(:TLSv1_2, ctx_proc) { |port|
@@ -1414,10 +1428,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_advertised_protocol_too_long
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] }
start_server_version(:TLSv1_2, ctx_proc) { |port|
@@ -1428,10 +1439,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_selected_protocol_too_long
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
start_server_version(:TLSv1_2, ctx_proc) { |port|
@@ -1469,56 +1477,51 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_get_ephemeral_key
- if tls12_supported?
- # kRSA
- ctx_proc1 = proc { |ctx|
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "kRSA"
- }
- start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "kRSA"
- begin
- server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
- rescue OpenSSL::SSL::SSLError
- # kRSA seems disabled
- raise unless $!.message =~ /no cipher/
- end
+ # kRSA
+ ctx_proc1 = proc { |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "kRSA"
+ }
+ start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "kRSA"
+ begin
+ server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
+ rescue OpenSSL::SSL::SSLError
+ # kRSA seems disabled
+ raise unless $!.message =~ /no cipher/
end
end
- if defined?(OpenSSL::PKey::DH) && tls12_supported?
- # DHE
- # TODO: How to test this with TLS 1.3?
- ctx_proc2 = proc { |ctx|
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "EDH"
+ # DHE
+ # TODO: How to test this with TLS 1.3?
+ ctx_proc2 = proc { |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "EDH"
+ ctx.tmp_dh = Fixtures.pkey("dh-1")
+ }
+ start_server(ctx_proc: ctx_proc2) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "EDH"
+ server_connect(port, ctx) { |ssl|
+ assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key
}
- start_server(ctx_proc: ctx_proc2) do |port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "EDH"
- server_connect(port, ctx) { |ssl|
- assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key
- }
- end
end
- if defined?(OpenSSL::PKey::EC)
- # ECDHE
- ctx_proc3 = proc { |ctx|
- ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
- ctx.ecdh_curves = "P-256"
+ # ECDHE
+ ctx_proc3 = proc { |ctx|
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ ctx.ecdh_curves = "P-256"
+ }
+ start_server(ctx_proc: ctx_proc3) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ server_connect(port, ctx) { |ssl|
+ assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key
+ ssl.puts "abc"; assert_equal "abc\n", ssl.gets
}
- start_server(ctx_proc: ctx_proc3) do |port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
- server_connect(port, ctx) { |ssl|
- assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key
- ssl.puts "abc"; assert_equal "abc\n", ssl.gets
- }
- end
end
end
@@ -1583,13 +1586,11 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_dh_callback
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
+ def test_tmp_dh_callback
dh = Fixtures.pkey("dh-1")
called = false
ctx_proc = -> ctx {
- ctx.ssl_version = :TLSv1_2
+ ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL"
ctx.tmp_dh_callback = ->(*args) {
called = true
@@ -1604,11 +1605,106 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_connect_works_when_setting_dh_callback_to_nil
- pend "TLS 1.2 is not supported" unless tls12_supported?
+ def test_ciphersuites_method_tls_connection
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ if !tls13_supported? || !ssl_ctx.respond_to?(:ciphersuites=)
+ pend 'TLS 1.3 not supported'
+ end
+
+ csuite = ['TLS_AES_128_GCM_SHA256', 'TLSv1.3', 128, 128]
+ inputs = [csuite[0], [csuite[0]], [csuite]]
+
+ start_server do |port|
+ inputs.each do |input|
+ cli_ctx = OpenSSL::SSL::SSLContext.new
+ cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
+ cli_ctx.ciphersuites = input
+
+ server_connect(port, cli_ctx) do |ssl|
+ assert_equal('TLSv1.3', ssl.ssl_version)
+ if libressl?(3, 4, 0) && !libressl?(3, 5, 0)
+ assert_equal("AEAD-AES128-GCM-SHA256", ssl.cipher[0])
+ else
+ assert_equal(csuite[0], ssl.cipher[0])
+ end
+ ssl.puts('abc'); assert_equal("abc\n", ssl.gets)
+ end
+ end
+ end
+ end
+
+ def test_ciphersuites_method_nil_argument
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=)
+
+ assert_nothing_raised { ssl_ctx.ciphersuites = nil }
+ end
+ def test_ciphersuites_method_frozen_object
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=)
+
+ ssl_ctx.freeze
+ assert_raise(FrozenError) { ssl_ctx.ciphersuites = 'TLS_AES_256_GCM_SHA384' }
+ end
+
+ def test_ciphersuites_method_bogus_csuite
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=)
+
+ assert_raise_with_message(
+ OpenSSL::SSL::SSLError,
+ /SSL_CTX_set_ciphersuites: no cipher match/i
+ ) { ssl_ctx.ciphersuites = 'BOGUS' }
+ end
+
+ def test_ciphers_method_tls_connection
+ csuite = ['ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256, 256]
+ inputs = [csuite[0], [csuite[0]], [csuite]]
+
+ start_server do |port|
+ inputs.each do |input|
+ cli_ctx = OpenSSL::SSL::SSLContext.new
+ cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ cli_ctx.ciphers = input
+
+ server_connect(port, cli_ctx) do |ssl|
+ assert_equal('TLSv1.2', ssl.ssl_version)
+ assert_equal(csuite[0], ssl.cipher[0])
+ ssl.puts('abc'); assert_equal("abc\n", ssl.gets)
+ end
+ end
+ end
+ end
+
+ def test_ciphers_method_nil_argument
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ assert_nothing_raised { ssl_ctx.ciphers = nil }
+ end
+
+ def test_ciphers_method_frozen_object
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+
+ ssl_ctx.freeze
+ assert_raise(FrozenError) { ssl_ctx.ciphers = 'ECDHE-RSA-AES128-SHA' }
+ end
+
+ def test_ciphers_method_bogus_csuite
+ omit "Old #{OpenSSL::OPENSSL_LIBRARY_VERSION}" if
+ year = OpenSSL::OPENSSL_LIBRARY_VERSION[/\A OpenSSL\s+[01]\..*\s\K\d+\z/x] and
+ year.to_i <= 2018
+
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+
+ assert_raise_with_message(
+ OpenSSL::SSL::SSLError,
+ /SSL_CTX_set_cipher_list: no cipher match/i
+ ) { ssl_ctx.ciphers = 'BOGUS' }
+ end
+
+ def test_connect_works_when_setting_dh_callback_to_nil
ctx_proc = -> ctx {
- ctx.ssl_version = :TLSv1_2
+ ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL" # use DH
ctx.tmp_dh_callback = nil
}
@@ -1621,9 +1717,21 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_ecdh_curves_tls12
- pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
+ def test_tmp_dh
+ dh = Fixtures.pkey("dh-1")
+ ctx_proc = -> ctx {
+ ctx.max_version = :TLS1_2
+ ctx.ciphers = "DH:!NULL" # use DH
+ ctx.tmp_dh = dh
+ }
+ start_server(ctx_proc: ctx_proc) do |port|
+ server_connect(port) { |ssl|
+ assert_equal dh.to_der, ssl.tmp_key.to_der
+ }
+ end
+ end
+ def test_ecdh_curves_tls12
ctx_proc = -> ctx {
# Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
@@ -1659,7 +1767,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_ecdh_curves_tls13
- pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
pend "TLS 1.3 not supported" unless tls13_supported?
ctx_proc = -> ctx {
@@ -1746,6 +1853,19 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
sock2.close
end
+ def test_export_keying_material
+ start_server do |port|
+ cli_ctx = OpenSSL::SSL::SSLContext.new
+ server_connect(port, cli_ctx) do |ssl|
+ assert_instance_of(String, ssl.export_keying_material('ttls keying material', 64))
+ assert_operator(64, :==, ssl.export_keying_material('ttls keying material', 64).b.length)
+ assert_operator(8, :==, ssl.export_keying_material('ttls keying material', 8).b.length)
+ assert_operator(5, :==, ssl.export_keying_material('test', 5, 'context').b.length)
+ ssl.puts "abc"; ssl.gets # workaround to make tests work on windows
+ end
+ end
+ end
+
private
def start_server_version(version, ctx_proc = nil,
diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb
index a98efdae2a..b243201e18 100644
--- a/test/openssl/test_ssl_session.rb
+++ b/test/openssl/test_ssl_session.rb
@@ -1,12 +1,10 @@
# frozen_string_literal: true
require_relative "utils"
-if defined?(OpenSSL)
+if defined?(OpenSSL::SSL)
class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
def test_session
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
start_server(ctx_proc: ctx_proc) do |port|
server_connect_with_session(port, nil, nil) { |ssl|
@@ -144,8 +142,6 @@ __EOS__
end
def test_server_session_cache
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = Proc.new do |ctx|
ctx.ssl_version = :TLSv1_2
ctx.options |= OpenSSL::SSL::OP_NO_TICKET
@@ -224,8 +220,6 @@ __EOS__
TEST_SESSION_REMOVE_CB = ENV["OSSL_TEST_ALL"] == "1"
def test_ctx_client_session_cb
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
start_server(ctx_proc: ctx_proc) do |port|
called = {}
@@ -257,8 +251,6 @@ __EOS__
end
def test_ctx_server_session_cb
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
connections = nil
called = {}
cctx = OpenSSL::SSL::SSLContext.new
diff --git a/test/openssl/test_ts.rb b/test/openssl/test_ts.rb
index 8e31a7d28d..7cb1a1fe8e 100644
--- a/test/openssl/test_ts.rb
+++ b/test/openssl/test_ts.rb
@@ -181,6 +181,12 @@ _end_of_pem_
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)
@@ -338,6 +344,12 @@ _end_of_pem_
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"
@@ -590,6 +602,12 @@ _end_of_pem_
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
diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb
index d696b98c0a..64805504de 100644
--- a/test/openssl/test_x509cert.rb
+++ b/test/openssl/test_x509cert.rb
@@ -173,13 +173,14 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
end
def test_sign_and_verify_rsa_sha1
- cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "sha1")
+ cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "SHA1")
assert_equal(false, cert.verify(@rsa1024))
assert_equal(true, cert.verify(@rsa2048))
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) })
cert.serial = 2
assert_equal(false, cert.verify(@rsa2048))
+ rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1
end
def test_sign_and_verify_rsa_md5
@@ -229,6 +230,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
# SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requires DSS1)
cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha1")
assert_equal("dsaWithSHA1", cert.signature_algorithm)
+ rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1
end
def test_check_private_key
diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb
index bcdb0a697c..146ee07309 100644
--- a/test/openssl/test_x509crl.rb
+++ b/test/openssl/test_x509crl.rb
@@ -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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
revoked = crl.revoked
assert_equal(1000, revoked.size)
assert_equal(1, revoked[0].serial)
@@ -124,7 +124,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
exts = crl.extensions
assert_equal(3, exts.size)
assert_equal("1", exts[0].value)
@@ -160,24 +160,24 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
assert_equal(false, exts[2].critical?)
no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text)
assert_match((2**100).to_s, crl.extensions[0].value)
end
@@ -185,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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
assert_equal(false, crl.verify(@rsa1024))
assert_equal(true, crl.verify(@rsa2048))
assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) })
@@ -195,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.new('SHA1'))
+ cert, @dsa512, OpenSSL::Digest.new('SHA256'))
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))
diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb
index ee9c678fbb..b98754b8c8 100644
--- a/test/openssl/test_x509req.rb
+++ b/test/openssl/test_x509req.rb
@@ -23,31 +23,26 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_public_key
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
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.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.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
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 +73,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
OpenSSL::X509::Attribute.new("msExtReq", attrval),
]
- req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
attrs.each{|attr| req0.add_attribute(attr) }
- req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
req1.attributes = attrs
assert_equal(req0.to_der, req1.to_der)
@@ -106,8 +101,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
assert_equal(false, req.verify(@rsa2048))
assert_equal(false, request_error_returns_false { req.verify(@dsa256) })
assert_equal(false, request_error_returns_false { req.verify(@dsa512) })
- req.version = 1
+ req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBarFooBar")
assert_equal(false, req.verify(@rsa1024))
+ rescue OpenSSL::X509::RequestError # RHEL 9 disables SHA1
end
def test_sign_and_verify_rsa_md5
@@ -122,7 +118,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_sign_and_verify_dsa
- req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1'))
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
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))
@@ -137,14 +133,14 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_dup
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
assert_equal(req.to_der, req.dup.to_der)
end
def test_eq
- req1 = issue_csr(0, @dn, @rsa1024, "sha1")
- req2 = issue_csr(0, @dn, @rsa1024, "sha1")
- req3 = issue_csr(0, @dn, @rsa1024, "sha256")
+ req1 = issue_csr(0, @dn, @rsa1024, "sha256")
+ req2 = issue_csr(0, @dn, @rsa1024, "sha256")
+ req3 = issue_csr(0, @dn, @rsa1024, "sha512")
assert_equal false, req1 == 12345
assert_equal true, req1 == req2
diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb
index 8ee0116412..4ebcb9837b 100644
--- a/test/openssl/utils.rb
+++ b/test/openssl/utils.rb
@@ -189,13 +189,6 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
@server = nil
end
- def tls12_supported?
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
- true
- rescue
- end
-
def tls13_supported?
return false unless defined?(OpenSSL::SSL::TLS1_3_VERSION)
ctx = OpenSSL::SSL::SSLContext.new
@@ -222,7 +215,6 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
ctx.cert_store = store
ctx.cert = @svr_cert
ctx.key = @svr_key
- ctx.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
ctx.verify_mode = verify_mode
ctx_proc.call(ctx) if ctx_proc
@@ -236,9 +228,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
threads = []
begin
server_thread = Thread.new do
- if Thread.method_defined?(:report_on_exception=) # Ruby >= 2.4
- Thread.current.report_on_exception = false
- end
+ Thread.current.report_on_exception = false
begin
loop do
@@ -254,9 +244,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
end
th = Thread.new do
- if Thread.method_defined?(:report_on_exception=)
- Thread.current.report_on_exception = false
- end
+ Thread.current.report_on_exception = false
begin
server_proc.call(ctx, ssl)
@@ -273,9 +261,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
end
client_thread = Thread.new do
- if Thread.method_defined?(:report_on_exception=)
- Thread.current.report_on_exception = false
- end
+ Thread.current.report_on_exception = false
begin
block.call(port)
@@ -294,8 +280,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
timeout = EnvUtil.apply_timeout_scale(30)
th.join(timeout) or
th.raise(RuntimeError, "[start_server] thread did not exit in #{timeout} secs")
- rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError)
- # MiniTest::Skip is for the Ruby tree
+ rescue Test::Unit::PendedError
pend = $!
rescue Exception
end
@@ -313,32 +298,6 @@ class OpenSSL::PKeyTestCase < OpenSSL::TestCase
assert_equal base.send(comp), test.send(comp)
}
end
-
- def dup_public(key)
- case key
- when OpenSSL::PKey::RSA
- rsa = OpenSSL::PKey::RSA.new
- rsa.set_key(key.n, key.e, nil)
- rsa
- when OpenSSL::PKey::DSA
- dsa = OpenSSL::PKey::DSA.new
- dsa.set_pqg(key.p, key.q, key.g)
- dsa.set_key(key.pub_key, nil)
- dsa
- when OpenSSL::PKey::DH
- dh = OpenSSL::PKey::DH.new
- dh.set_pqg(key.p, nil, key.g)
- dh
- else
- if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key
- ec = OpenSSL::PKey::EC.new(key.group)
- ec.public_key = key.public_key
- ec
- else
- raise "unknown key type"
- end
- end
- end
end
module OpenSSL::Certs
diff --git a/test/optparse/test_acceptable.rb b/test/optparse/test_acceptable.rb
index 12f7886538..12f5322726 100644
--- a/test/optparse/test_acceptable.rb
+++ b/test/optparse/test_acceptable.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::Acceptable < TestOptionParser
+class TestOptionParserAcceptable < TestOptionParser
def setup
super
diff --git a/test/optparse/test_autoconf.rb b/test/optparse/test_autoconf.rb
index 45f2ba09b2..ec87744633 100644
--- a/test/optparse/test_autoconf.rb
+++ b/test/optparse/test_autoconf.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse/ac'
-class TestOptionParser < Test::Unit::TestCase; end
-
-class TestOptionParser::AutoConf < Test::Unit::TestCase
+class TestOptionParserAutoConf < Test::Unit::TestCase
def setup
@opt = OptionParser::AC.new
@foo = @bar = self.class
diff --git a/test/optparse/test_bash_completion.rb b/test/optparse/test_bash_completion.rb
index 513e986f66..60c82f7136 100644
--- a/test/optparse/test_bash_completion.rb
+++ b/test/optparse/test_bash_completion.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::BashCompletion < Test::Unit::TestCase
+class TestOptionParserBashCompletion < Test::Unit::TestCase
def setup
@opt = OptionParser.new
@opt.define("-z", "zzz") {}
diff --git a/test/optparse/test_cclass.rb b/test/optparse/test_cclass.rb
index ac46f46bb2..0ded61f60e 100644
--- a/test/optparse/test_cclass.rb
+++ b/test/optparse/test_cclass.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::CClass < TestOptionParser
+class TestOptionParserCClass < TestOptionParser
def test_no_argument
flags = []
@opt.def_option("-[a-z]") {|x| flags << x}
diff --git a/test/optparse/test_did_you_mean.rb b/test/optparse/test_did_you_mean.rb
index 763062586c..3c923922ec 100644
--- a/test/optparse/test_did_you_mean.rb
+++ b/test/optparse/test_did_you_mean.rb
@@ -6,17 +6,21 @@ rescue LoadError
return
end
-class TestOptionParser::DidYouMean < TestOptionParser
+class TestOptionParserDidYouMean < TestOptionParser
def setup
super
@opt.def_option("--foo", Integer) { |v| @foo = v }
@opt.def_option("--bar", Integer) { |v| @bar = v }
@opt.def_option("--baz", Integer) { |v| @baz = v }
@formatter = ::DidYouMean.formatter
- case @formatter
- when ::DidYouMean::PlainFormatter
+ if ::DidYouMean.const_defined?(:Formatter)
+ ::DidYouMean.formatter = ::DidYouMean::Formatter
else
- ::DidYouMean.formatter = ::DidYouMean::PlainFormatter.new
+ case @formatter
+ when ::DidYouMean::PlainFormatter
+ else
+ ::DidYouMean.formatter = ::DidYouMean::PlainFormatter.new
+ end
end
end
@@ -36,15 +40,7 @@ class TestOptionParser::DidYouMean < TestOptionParser
end
end
- def test_verbose
- require 'did_you_mean/formatters/verbose_formatter'
- ::DidYouMean.formatter = ::DidYouMean::VerboseFormatter.new
- assert_raise_with_message(OptionParser::InvalidOption, /invalid option: --baa\n\s+Did you mean\?\s+bar\s+baz\s*\Z/) do
- @opt.permute!(%w"--baa")
- end
- end
-
- def test_ambiguos
+ def test_ambiguous
assert_raise_with_message(OptionParser::AmbiguousOption, /ambiguous option: --ba\nDid you mean\?\s+bar\s+baz\Z/) do
@opt.permute!(%w"--ba")
end
diff --git a/test/optparse/test_getopts.rb b/test/optparse/test_getopts.rb
index 3711e6f269..7d9160f7af 100644
--- a/test/optparse/test_getopts.rb
+++ b/test/optparse/test_getopts.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::Getopts < Test::Unit::TestCase
+class TestOptionParserGetopts < Test::Unit::TestCase
def setup
@opt = OptionParser.new
end
diff --git a/test/optparse/test_kwargs.rb b/test/optparse/test_kwargs.rb
index 78d7e2ee9c..2e826bfd12 100644
--- a/test/optparse/test_kwargs.rb
+++ b/test/optparse/test_kwargs.rb
@@ -3,9 +3,7 @@ require 'test/unit'
require 'optparse'
require 'optparse/kwargs'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::KwArg < Test::Unit::TestCase
+class TestOptionParserKwArg < Test::Unit::TestCase
class K
def initialize(host:, port: 8080)
@host = host
diff --git a/test/optparse/test_load.rb b/test/optparse/test_load.rb
new file mode 100644
index 0000000000..0ebe855682
--- /dev/null
+++ b/test/optparse/test_load.rb
@@ -0,0 +1,141 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'optparse'
+require 'tmpdir'
+
+class TestOptionParserLoad < Test::Unit::TestCase
+ def setup
+ @tmpdir = Dir.mktmpdir("optparse_test-")
+ @basename = File.basename($0, '.*')
+ @envs = %w[HOME XDG_CONFIG_HOME XDG_CONFIG_DIRS].each_with_object({}) do |v, h|
+ h[v] = ENV.delete(v)
+ end
+ end
+
+ def teardown
+ ENV.update(@envs)
+ FileUtils.rm_rf(@tmpdir)
+ end
+
+ def new_parser
+ @result = nil
+ OptionParser.new do |opt|
+ opt.on("--test=arg") {|v| @result = v}
+ end
+ end
+
+ def assert_load(result)
+ assert new_parser.load
+ assert_equal(result, @result)
+ assert new_parser.load(into: into = {})
+ assert_equal({test: result}, into)
+ end
+
+ def setup_options(env, dir, suffix = nil)
+ optdir = File.join(@tmpdir, dir)
+ FileUtils.mkdir_p(optdir)
+ file = File.join(optdir, [@basename, suffix].join(""))
+ File.write(file, "--test=#{dir}")
+ ENV.update(env)
+ if block_given?
+ begin
+ yield dir, optdir
+ ensure
+ File.unlink(file)
+ Dir.rmdir(optdir) rescue nil
+ end
+ else
+ return dir, optdir
+ end
+ end
+
+ def setup_options_home(&block)
+ setup_options({'HOME'=>@tmpdir}, ".options", &block)
+ end
+
+ def setup_options_xdg_config_home(&block)
+ setup_options({'XDG_CONFIG_HOME'=>@tmpdir+"/xdg"}, "xdg", ".options", &block)
+ end
+
+ def setup_options_home_config(&block)
+ setup_options({'HOME'=>@tmpdir}, ".config", ".options", &block)
+ end
+
+ def setup_options_xdg_config_dirs(&block)
+ setup_options({'XDG_CONFIG_DIRS'=>@tmpdir+"/xdgconf"}, "xdgconf", ".options", &block)
+ end
+
+ def setup_options_home_config_settings(&block)
+ setup_options({'HOME'=>@tmpdir}, "config/settings", ".options", &block)
+ end
+
+ def test_load_home_options
+ result, = setup_options_home
+ assert_load(result)
+
+ setup_options_xdg_config_home do
+ assert_load(result)
+ end
+
+ setup_options_home_config do
+ assert_load(result)
+ end
+
+ setup_options_xdg_config_dirs do
+ assert_load(result)
+ end
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_xdg_config_home
+ result, = setup_options_xdg_config_home
+ assert_load(result)
+
+ setup_options_home_config do
+ assert_load(result)
+ end
+
+ setup_options_xdg_config_dirs do
+ assert_load(result)
+ end
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_home_config
+ result, = setup_options_home_config
+ assert_load(result)
+
+ setup_options_xdg_config_dirs do
+ assert_load(result)
+ end
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_xdg_config_dirs
+ result, = setup_options_xdg_config_dirs
+ assert_load(result)
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_home_config_settings
+ result, = setup_options_home_config_settings
+ assert_load(result)
+ end
+
+ def test_load_nothing
+ assert !new_parser.load
+ assert_nil @result
+ end
+end
diff --git a/test/optparse/test_noarg.rb b/test/optparse/test_noarg.rb
index 8f20519408..a53399afc2 100644
--- a/test/optparse/test_noarg.rb
+++ b/test/optparse/test_noarg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-module TestOptionParser::NoArg
+module TestOptionParserNoArg
def setup
super
@opt.def_option "--with_underscore" do |x| @flag = x end
@@ -9,7 +9,7 @@ module TestOptionParser::NoArg
end
class Def1 < TestOptionParser
- include NoArg
+ include TestOptionParserNoArg
def setup
super
@opt.def_option("-x") {|x| @flag = x}
@@ -17,7 +17,7 @@ module TestOptionParser::NoArg
end
end
class Def2 < TestOptionParser
- include NoArg
+ include TestOptionParserNoArg
def setup
super
@opt.def_option("-x", "--option") {|x| @flag = x}
diff --git a/test/optparse/test_optarg.rb b/test/optparse/test_optarg.rb
index 14584f7e89..81127a8a37 100644
--- a/test/optparse/test_optarg.rb
+++ b/test/optparse/test_optarg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::OptArg < TestOptionParser
+class TestOptionParserOptArg < TestOptionParser
def setup
super
@opt.def_option("-x[VAL]") {|x| @flag = x}
diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb
index 5f5ea183b0..bfa705ad03 100644
--- a/test/optparse/test_optparse.rb
+++ b/test/optparse/test_optparse.rb
@@ -63,6 +63,9 @@ class TestOptionParser < Test::Unit::TestCase
assert_equal(/foo/i, @reopt)
assert_equal(%w"", no_error {@opt.parse!(%w"--regexp=/foo/n")})
assert_equal(/foo/n, @reopt)
+ assert_equal(%w"", no_error {@opt.parse!(%W"--regexp=/\u{3042}/s")})
+ assert_equal(Encoding::Windows_31J, @reopt.encoding)
+ assert_equal("\x82\xa0".force_encoding(Encoding::Windows_31J), @reopt.source)
end
def test_into
@@ -98,6 +101,18 @@ class TestOptionParser < Test::Unit::TestCase
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo))}
end
+ def test_raise_unknown
+ @opt.def_option('--my-foo [ARG]') {|arg| @foo = arg}
+ assert @opt.raise_unknown
+
+ @opt.raise_unknown = false
+ assert_equal(%w[--my-bar], @opt.parse(%w[--my-foo --my-bar]))
+ assert_nil(@foo)
+
+ assert_equal(%w[--my-bar], @opt.parse(%w[--my-foo x --my-bar]))
+ assert_equal("x", @foo)
+ end
+
def test_nonopt_pattern
@opt.def_option(/^[^-]/) do |arg|
assert(false, "Never gets called")
diff --git a/test/optparse/test_placearg.rb b/test/optparse/test_placearg.rb
index 8acfdb2161..ed0e4d3e6c 100644
--- a/test/optparse/test_placearg.rb
+++ b/test/optparse/test_placearg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::PlaceArg < TestOptionParser
+class TestOptionParserPlaceArg < TestOptionParser
def setup
super
@opt.def_option("-x [VAL]") {|x| @flag = x}
@@ -18,6 +18,8 @@ class TestOptionParser::PlaceArg < TestOptionParser
def test_short
assert_equal(%w"", no_error {@opt.parse!(%w"-x -n")})
assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x -")})
+ assert_equal("-", @flag)
@flag = false
assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")})
assert_equal("foo", @flag)
@@ -30,6 +32,8 @@ class TestOptionParser::PlaceArg < TestOptionParser
def test_abbrev
assert_equal(%w"", no_error {@opt.parse!(%w"-o -n")})
assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o -")})
+ assert_equal("-", @flag)
@flag = false
assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")})
assert_equal("foo", @flag)
@@ -42,6 +46,8 @@ class TestOptionParser::PlaceArg < TestOptionParser
def test_long
assert_equal(%w"", no_error {@opt.parse!(%w"--opt -n")})
assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt -")})
+ assert_equal("-", @flag)
assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")})
assert_equal("", @flag)
assert_equal(%w"", no_error {@opt.parse!(%w"--opt=foo")})
diff --git a/test/optparse/test_reqarg.rb b/test/optparse/test_reqarg.rb
index b2e4755f80..d5686d13aa 100644
--- a/test/optparse/test_reqarg.rb
+++ b/test/optparse/test_reqarg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-module TestOptionParser::ReqArg
+module TestOptionParserReqArg
def setup
super
@opt.def_option "--with_underscore=VAL" do |x| @flag = x end
@@ -9,7 +9,7 @@ module TestOptionParser::ReqArg
end
class Def1 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("-xVAL") {|x| @flag = x}
@@ -19,21 +19,21 @@ module TestOptionParser::ReqArg
end
end
class Def2 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("-x", "--option=VAL") {|x| @flag = x}
end
end
class Def3 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("--option=VAL", "-x") {|x| @flag = x}
end
end
class Def4 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("-xVAL", "--option=VAL") {|x| @flag = x}
diff --git a/test/optparse/test_summary.rb b/test/optparse/test_summary.rb
index 67b05672d4..b5dcb3524e 100644
--- a/test/optparse/test_summary.rb
+++ b/test/optparse/test_summary.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::SummaryTest < TestOptionParser
+class TestOptionParserSummaryTest < TestOptionParser
def test_short_clash
r = nil
o = OptionParser.new do |opts|
@@ -55,4 +55,27 @@ class TestOptionParser::SummaryTest < TestOptionParser
o.release = "rel"
assert_equal "foo 0.1 (rel)", o.ver
end
+
+ # https://github.com/ruby/optparse/issues/37
+ def test_very_long_without_short
+ o = OptionParser.new do |opts|
+ # This causes TypeError
+ opts.on('', '--long-long-option-param-without-short', "Error desc") { options[:long_long_option_param_without_short] = true }
+ opts.on('', '--long-option-param', "Long desc") { options[:long_option_param_without_short] = true }
+ opts.on('-a', '--long-long-option-param-with-short', "Normal description") { options[:long_long_option_param_with_short] = true }
+
+ opts.on('', '--long-long-option-param-without-short-but-with-desc', 'Description of the long long param') { options[:long_long_option_param_without_short_but_with_desc] = true }
+ end
+
+ s = o.summarize
+
+ assert_match(/^\s*--long-long-option-param-without-short$/, s[0])
+ assert_match(/^\s*Error desc$/, s[1])
+ assert_match(/^\s*--long-option-param\s+Long desc$/, s[2])
+ assert_match(/^\s*-a\s+Normal description$/, s[3])
+ assert_match(/^\s*--long-long-option-param-with-short$/, s[4])
+
+ assert_match(/^\s*--long-long-option-param-without-short-but-with-desc$/, s[5])
+ assert_match(/^\s*Description of the long long param$/, s[6])
+ end
end
diff --git a/test/optparse/test_zsh_completion.rb b/test/optparse/test_zsh_completion.rb
index c548d4af8a..76f0a73f32 100644
--- a/test/optparse/test_zsh_completion.rb
+++ b/test/optparse/test_zsh_completion.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::ZshCompletion < Test::Unit::TestCase
+class TestOptionParserZshCompletion < Test::Unit::TestCase
def setup
@opt = OptionParser.new
@opt.define("-z", "zzz") {}
diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb
index 1fd7d87811..256db7a0c7 100644
--- a/test/ostruct/test_ostruct.rb
+++ b/test/ostruct/test_ostruct.rb
@@ -280,6 +280,7 @@ class TC_OpenStruct < Test::Unit::TestCase
os = OpenStruct.new(method: :foo, hash: 42)
assert_equal(os.object_id, os.method!(:object_id).call)
assert_not_equal(42, os.hash!)
+ refute os.methods.include?(:"!~!")
end
def test_override_subclass
@@ -368,6 +369,18 @@ class TC_OpenStruct < Test::Unit::TestCase
RUBY
end if defined?(Ractor)
+ def test_access_methods_from_different_ractor
+ assert_ractor(<<~RUBY, require: 'ostruct')
+ os = OpenStruct.new
+ os.value = 100
+ r = Ractor.new(os) do |x|
+ v = x.value
+ Ractor.yield v
+ end
+ assert 100 == r.take
+ RUBY
+ end if defined?(Ractor)
+
def test_legacy_yaml
s = "--- !ruby/object:OpenStruct\ntable:\n :foo: 42\n"
o = YAML.safe_load(s, permitted_classes: [Symbol, OpenStruct])
@@ -393,4 +406,10 @@ class TC_OpenStruct < Test::Unit::TestCase
o2 = Marshal.load(Marshal.dump(o))
assert_equal o, o2
end
+
+ def test_class
+ os = OpenStruct.new(class: 'my-class', method: 'post')
+ assert_equal('my-class', os.class)
+ assert_equal(OpenStruct, os.class!)
+ end
end
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 8a0f3cbb66..a23dc21ae3 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -815,7 +815,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_birthtime
- skip if RUBY_PLATFORM =~ /android/
+ omit if RUBY_PLATFORM =~ /android/
# Check under a (probably) local filesystem.
# Remote filesystems often may not support birthtime.
with_tmpchdir('rubytest-pathname') do |dir|
@@ -823,9 +823,9 @@ class TestPathname < Test::Unit::TestCase
assert_kind_of(Time, Pathname("a").birthtime)
rescue Errno::EPERM
# Docker prohibits statx syscall by the default.
- skip("statx(2) is prohibited by seccomp")
+ omit("statx(2) is prohibited by seccomp")
rescue Errno::ENOSYS
- skip("statx(2) is not supported on this filesystem")
+ omit("statx(2) is not supported on this filesystem")
rescue NotImplementedError
# assert_raise(NotImplementedError) do
# File.birthtime("a")
@@ -1043,6 +1043,25 @@ class TestPathname < Test::Unit::TestCase
}
end
+ def test_lutime
+ return if !has_symlink?
+ with_tmpchdir('rubytest-pathname') {|dir|
+ open("a", "w") {|f| f.write "abc" }
+ atime = File.atime("a")
+ mtime = File.mtime("a")
+ latime = Time.utc(2000)
+ lmtime = Time.utc(1999)
+ File.symlink("a", "l")
+ Pathname("l").utime(latime, lmtime)
+ s = File.lstat("a")
+ ls = File.lstat("l")
+ assert_equal(atime, s.atime)
+ assert_equal(mtime, s.mtime)
+ assert_equal(latime, ls.atime)
+ assert_equal(lmtime, ls.mtime)
+ }
+ end
+
def test_basename
assert_equal(Pathname("basename"), Pathname("dirname/basename").basename)
assert_equal(Pathname("bar"), Pathname("foo/bar.x").basename(".x"))
@@ -1120,7 +1139,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_grpowned?
- skip "Unix file owner test" if DOSISH
+ omit "Unix file owner test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
File.chown(-1, Process.gid, "f")
@@ -1175,7 +1194,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_world_readable?
- skip "Unix file mode bit test" if DOSISH
+ omit "Unix file mode bit test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
File.chmod(0400, "f")
@@ -1227,7 +1246,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_sticky?
- skip "Unix file mode bit test" if DOSISH
+ omit "Unix file mode bit test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
assert_equal(false, Pathname("f").sticky?)
@@ -1249,7 +1268,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_world_writable?
- skip "Unix file mode bit test" if DOSISH
+ omit "Unix file mode bit test" if DOSISH
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
File.chmod(0600, "f")
@@ -1355,6 +1374,18 @@ class TestPathname < Test::Unit::TestCase
}
end
+ def test_each_entry_enumerator
+ with_tmpchdir('rubytest-pathname') {|dir|
+ open("a", "w") {}
+ open("b", "w") {}
+ a = []
+ e = Pathname(".").each_entry
+ assert_kind_of(Enumerator, e)
+ e.each {|v| a << v }
+ assert_equal([Pathname("."), Pathname(".."), Pathname("a"), Pathname("b")], a.sort)
+ }
+ end
+
def test_mkdir
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("d").mkdir
@@ -1409,8 +1440,8 @@ class TestPathname < Test::Unit::TestCase
a = []; Pathname("d").find(ignore_error: true) {|v| a << v }; a.sort!
assert_equal([Pathname("d"), Pathname("d/x")], a)
- skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
- skip 'skipped in root privilege' if Process.uid == 0
+ omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit 'skipped in root privilege' if Process.uid == 0
a = [];
assert_raise_with_message(Errno::EACCES, %r{d/x}) do
Pathname(".").find(ignore_error: false) {|v| a << v }
@@ -1429,10 +1460,22 @@ class TestPathname < Test::Unit::TestCase
}
end
+ def assert_mode(val, mask, path, mesg = nil)
+ st = File.stat(path)
+ assert_equal(val.to_s(8), (st.mode & mask).to_s(8), st.inspect)
+ end
+
def test_mkpath
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
assert_file.directory?("a/b/c/d")
+ unless File.stat(dir).world_readable?
+ # mktmpdir should make unreadable
+ Pathname("x/y/z").mkpath(mode: 0775)
+ assert_mode(0775, 0777, "x")
+ assert_mode(0775, 0777, "x/y")
+ assert_mode(0775, 0777, "x/y/z")
+ end
}
end
diff --git a/test/pathname/test_ractor.rb b/test/pathname/test_ractor.rb
index 9ce43ef640..3d7b63deed 100644
--- a/test/pathname/test_ractor.rb
+++ b/test/pathname/test_ractor.rb
@@ -4,7 +4,7 @@ require "pathname"
class TestPathnameRactor < Test::Unit::TestCase
def setup
- skip unless defined? Ractor
+ omit unless defined? Ractor
end
def test_ractor_shareable
diff --git a/test/psych/helper.rb b/test/psych/helper.rb
index 0643139d8c..4e82887c6d 100644
--- a/test/psych/helper.rb
+++ b/test/psych/helper.rb
@@ -51,7 +51,7 @@ module Psych
:UseVersion => true, :UseHeader => true, :SortKeys => true
)
))
- rescue Psych::DisallowedClass, Psych::BadAlias
+ rescue Psych::DisallowedClass, Psych::BadAlias, Psych::AliasesNotEnabled
assert_to_yaml obj, yaml, :unsafe_load
end
@@ -61,7 +61,7 @@ module Psych
def assert_parse_only( obj, yaml )
begin
assert_equal obj, Psych::load( yaml )
- rescue Psych::DisallowedClass, Psych::BadAlias
+ rescue Psych::DisallowedClass, Psych::BadAlias, Psych::AliasesNotEnabled
assert_equal obj, Psych::unsafe_load( yaml )
end
assert_equal obj, Psych::parse( yaml ).transform
@@ -79,7 +79,7 @@ module Psych
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
+ rescue Psych::DisallowedClass, Psych::BadAlias, Psych::AliasesNotEnabled
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))
diff --git a/test/psych/test_array.rb b/test/psych/test_array.rb
index 28b76da785..0dc82439d4 100644
--- a/test/psych/test_array.rb
+++ b/test/psych/test_array.rb
@@ -57,6 +57,22 @@ module Psych
assert_cycle(@list)
end
+ def test_recursive_array
+ @list << @list
+
+ loaded = Psych.load(Psych.dump(@list), aliases: true)
+
+ assert_same loaded, loaded.last
+ end
+
+ def test_recursive_array_uses_alias
+ @list << @list
+
+ assert_raise(AliasesNotEnabled) do
+ Psych.load(Psych.dump(@list), aliases: false)
+ end
+ end
+
def test_cycle
assert_cycle(@list)
end
diff --git a/test/psych/test_coder.rb b/test/psych/test_coder.rb
index b2be0a4109..a6f5ad7f36 100644
--- a/test/psych/test_coder.rb
+++ b/test/psych/test_coder.rb
@@ -220,6 +220,8 @@ module Psych
end
def test_coder_style_map_any
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
foo = Psych.dump CustomEncode.new \
map: {a: 1, b: 2},
style: Psych::Nodes::Mapping::ANY,
@@ -228,6 +230,8 @@ module Psych
end
def test_coder_style_map_block
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
foo = Psych.dump CustomEncode.new \
map: {a: 1, b: 2},
style: Psych::Nodes::Mapping::BLOCK,
@@ -236,6 +240,8 @@ module Psych
end
def test_coder_style_map_flow
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
foo = Psych.dump CustomEncode.new \
map: { a: 1, b: 2 },
style: Psych::Nodes::Mapping::FLOW,
diff --git a/test/psych/test_date_time.rb b/test/psych/test_date_time.rb
index 6f1e8b509e..3379bd24bf 100644
--- a/test/psych/test_date_time.rb
+++ b/test/psych/test_date_time.rb
@@ -44,6 +44,26 @@ module Psych
assert_match(/12:00:00-05:00/, cycled.last.to_s)
end
+ def test_julian_date
+ d = Date.new(1582, 10, 4, Date::GREGORIAN)
+ assert_cycle d
+ end
+
+ def test_proleptic_gregorian_date
+ d = Date.new(1582, 10, 14, Date::GREGORIAN)
+ assert_cycle d
+ end
+
+ def test_julian_datetime
+ dt = DateTime.new(1582, 10, 4, 23, 58, 59, 0, Date::GREGORIAN)
+ assert_cycle dt
+ end
+
+ def test_proleptic_gregorian_datetime
+ dt = DateTime.new(1582, 10, 14, 23, 58, 59, 0, Date::GREGORIAN)
+ assert_cycle dt
+ end
+
def test_invalid_date
assert_cycle "2013-10-31T10:40:07-000000000000033"
end
diff --git a/test/psych/test_encoding.rb b/test/psych/test_encoding.rb
index e5831c9045..7d33814805 100644
--- a/test/psych/test_encoding.rb
+++ b/test/psych/test_encoding.rb
@@ -119,6 +119,8 @@ module Psych
end
def test_emit_alias
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@emitter.start_stream Psych::Parser::UTF8
@emitter.start_document [], [], true
e = assert_raise(RuntimeError) do
@@ -151,6 +153,7 @@ module Psych
@emitter.end_mapping
@emitter.end_document false
@emitter.end_stream
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
@parser.parse @buffer.string
assert_encodings @utf8, @handler.strings
@@ -170,6 +173,7 @@ module Psych
@emitter.end_sequence
@emitter.end_document false
@emitter.end_stream
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
@parser.parse @buffer.string
assert_encodings @utf8, @handler.strings
@@ -187,6 +191,7 @@ module Psych
@emitter.scalar 'foo', nil, nil, true, false, Nodes::Scalar::ANY
@emitter.end_document false
@emitter.end_stream
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
@parser.parse @buffer.string
assert_encodings @utf8, @handler.strings
@@ -263,6 +268,8 @@ module Psych
end
def test_dump_non_ascii_string_to_file
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
Tempfile.create(['utf8', 'yml'], :encoding => 'UTF-8') do |t|
h = {'one' => 'いち'}
Psych.dump(h, t)
diff --git a/test/psych/test_hash.rb b/test/psych/test_hash.rb
index 5374781339..31eba8580b 100644
--- a/test/psych/test_hash.rb
+++ b/test/psych/test_hash.rb
@@ -102,26 +102,66 @@ module Psych
end
def test_ref_append
- hash = Psych.unsafe_load(<<-eoyml)
----
-foo: &foo
- hello: world
-bar:
- <<: *foo
-eoyml
+ hash = Psych.unsafe_load(<<~eoyml)
+ ---
+ foo: &foo
+ hello: world
+ bar:
+ <<: *foo
+ eoyml
assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
end
+ def test_anchor_reuse
+ hash = Psych.unsafe_load(<<~eoyml)
+ ---
+ foo: &foo
+ hello: world
+ bar: *foo
+ eoyml
+ assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
+ assert_same(hash.fetch("foo"), hash.fetch("bar"))
+ end
+
+ def test_raises_if_anchor_not_defined
+ assert_raise(Psych::AnchorNotDefined) do
+ Psych.unsafe_load(<<~eoyml)
+ ---
+ foo: &foo
+ hello: world
+ bar: *not_foo
+ eoyml
+ end
+ end
+
+ def test_recursive_hash
+ h = { }
+ h["recursive_reference"] = h
+
+ loaded = Psych.load(Psych.dump(h), aliases: true)
+
+ assert_same loaded, loaded.fetch("recursive_reference")
+ end
+
+ def test_recursive_hash_uses_alias
+ h = { }
+ h["recursive_reference"] = h
+
+ assert_raise(AliasesNotEnabled) do
+ Psych.load(Psych.dump(h), aliases: false)
+ end
+ end
+
def test_key_deduplication
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
pend "This Ruby implementation doesn't support string deduplication"
end
- hashes = Psych.load(<<-eoyml)
----
-- unique_identifier: 1
-- unique_identifier: 2
-eoyml
+ hashes = Psych.load(<<~eoyml)
+ ---
+ - unique_identifier: 1
+ - unique_identifier: 2
+ eoyml
assert_same hashes[0].keys.first, hashes[1].keys.first
end
diff --git a/test/psych/test_merge_keys.rb b/test/psych/test_merge_keys.rb
index dcf4f1fce3..2f55a1ed8e 100644
--- a/test/psych/test_merge_keys.rb
+++ b/test/psych/test_merge_keys.rb
@@ -117,7 +117,7 @@ development:
bar:
<< : *foo
eoyml
- exp = assert_raise(Psych::BadAlias) { Psych.load yaml }
+ exp = assert_raise(Psych::AnchorNotDefined) { Psych.load(yaml, aliases: true) }
assert_match 'foo', exp.message
end
diff --git a/test/psych/test_numeric.rb b/test/psych/test_numeric.rb
index 8c3dcd173c..9c75c016cd 100644
--- a/test/psych/test_numeric.rb
+++ b/test/psych/test_numeric.rb
@@ -43,5 +43,16 @@ module Psych
str = Psych.load('--- 1.1.1')
assert_equal '1.1.1', str
end
+
+ # This behavior is not to YML spec, but is kept for backwards compatibility
+ def test_string_with_commas
+ number = Psych.load('--- 12,34,56')
+ assert_equal 123456, number
+ end
+
+ def test_string_with_commas_with_strict_integer
+ str = Psych.load('--- 12,34,56', strict_integer: true)
+ assert_equal '12,34,56', str
+ end
end
end
diff --git a/test/psych/test_object.rb b/test/psych/test_object.rb
index 0faf6b244d..21c27794ea 100644
--- a/test/psych/test_object.rb
+++ b/test/psych/test_object.rb
@@ -36,10 +36,19 @@ module Psych
def test_cyclic_references
foo = Foo.new(nil)
foo.parent = foo
- loaded = Psych.unsafe_load Psych.dump foo
+ loaded = Psych.load(Psych.dump(foo), permitted_classes: [Foo], aliases: true)
assert_instance_of(Foo, loaded)
- assert_equal loaded, loaded.parent
+ assert_same loaded, loaded.parent
+ end
+
+ def test_cyclic_reference_uses_alias
+ foo = Foo.new(nil)
+ foo.parent = foo
+
+ assert_raise(AliasesNotEnabled) do
+ Psych.load(Psych.dump(foo), permitted_classes: [Foo], aliases: false)
+ end
end
end
end
diff --git a/test/psych/test_parser.rb b/test/psych/test_parser.rb
index 3604e7c985..e087e319a5 100644
--- a/test/psych/test_parser.rb
+++ b/test/psych/test_parser.rb
@@ -85,6 +85,8 @@ module Psych
def test_line_numbers
assert_equal 0, @parser.mark.line
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "---\n- hello\n- world"
line_calls = @handler.marks.map(&:line).zip(@handler.calls.map(&:first))
assert_equal [
@@ -110,6 +112,8 @@ module Psych
def test_column_numbers
assert_equal 0, @parser.mark.column
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "---\n- hello\n- world"
col_calls = @handler.marks.map(&:column).zip(@handler.calls.map(&:first))
assert_equal [
@@ -135,6 +139,8 @@ module Psych
def test_index_numbers
assert_equal 0, @parser.mark.index
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "---\n- hello\n- world"
idx_calls = @handler.marks.map(&:index).zip(@handler.calls.map(&:first))
assert_equal [
@@ -352,6 +358,8 @@ module Psych
end
def test_event_location
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "foo:\n" \
" barbaz: [1, 2]"
diff --git a/test/psych/test_safe_load.rb b/test/psych/test_safe_load.rb
index b52d6048b3..a9ed737528 100644
--- a/test/psych/test_safe_load.rb
+++ b/test/psych/test_safe_load.rb
@@ -19,18 +19,31 @@ module Psych
end
end
- def test_no_recursion
- x = []
- x << x
- assert_raise(Psych::BadAlias) do
- Psych.safe_load Psych.dump(x)
+ def test_raises_when_alias_found_if_alias_parsing_not_enabled
+ yaml_with_aliases = <<~YAML
+ ---
+ a: &ABC
+ k1: v1
+ k2: v2
+ b: *ABC
+ YAML
+
+ assert_raise(Psych::AliasesNotEnabled) do
+ Psych.safe_load(yaml_with_aliases)
end
end
- def test_explicit_recursion
- x = []
- x << x
- assert_equal(x, Psych.safe_load(Psych.dump(x), permitted_classes: [], permitted_symbols: [], aliases: true))
+ def test_aliases_are_parsed_when_alias_parsing_is_enabled
+ yaml_with_aliases = <<~YAML
+ ---
+ a: &ABC
+ k1: v1
+ k2: v2
+ b: *ABC
+ YAML
+
+ result = Psych.safe_load(yaml_with_aliases, aliases: true)
+ assert_same result.fetch("a"), result.fetch("b")
end
def test_permitted_symbol
diff --git a/test/psych/test_scalar_scanner.rb b/test/psych/test_scalar_scanner.rb
index 1bd6488e75..145db58fd9 100644
--- a/test/psych/test_scalar_scanner.rb
+++ b/test/psych/test_scalar_scanner.rb
@@ -66,6 +66,10 @@ module Psych
assert_equal(1 / 0.0, ss.tokenize('.inf'))
end
+ def test_scan_plus_inf
+ assert_equal(1 / 0.0, ss.tokenize('+.inf'))
+ end
+
def test_scan_minus_inf
assert_equal(-1 / 0.0, ss.tokenize('-.inf'))
end
@@ -111,7 +115,15 @@ module Psych
end
def test_scan_strings_starting_with_underscores
- assert_equal "_100", ss.tokenize('_100')
+ assert_equal '_100', ss.tokenize('_100')
+ end
+
+ def test_scan_strings_starting_with_number
+ assert_equal '450D', ss.tokenize('450D')
+ end
+
+ def test_scan_strings_ending_with_underscores
+ assert_equal '100_', ss.tokenize('100_')
end
def test_scan_int_commas_and_underscores
@@ -120,7 +132,10 @@ 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 1, ss.tokenize('1')
+ assert_equal 1, ss.tokenize('+1')
+ assert_equal(-1, ss.tokenize('-1'))
assert_equal 0b010101010, ss.tokenize('0b010101010')
assert_equal 0b010101010, ss.tokenize('0b0,1_0,1_,0,1_01,0')
@@ -133,5 +148,60 @@ module Psych
assert_equal 0x123456789abcdef, ss.tokenize('0x_12_,34,_56,_789abcdef')
assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef__')
end
+
+ def test_scan_strict_int_commas_and_underscores
+ # this test is to ensure adherance to YML spec using the 'strict_integer' option
+ scanner = Psych::ScalarScanner.new ClassLoader.new, strict_integer: true
+ assert_equal 123_456_789, scanner.tokenize('123_456_789')
+ assert_equal '123,456,789', scanner.tokenize('123,456,789')
+ assert_equal '1_2,3,4_5,6_789', scanner.tokenize('1_2,3,4_5,6_789')
+
+ assert_equal 1, scanner.tokenize('1')
+ assert_equal 1, scanner.tokenize('+1')
+ assert_equal(-1, scanner.tokenize('-1'))
+
+ assert_equal 0b010101010, scanner.tokenize('0b010101010')
+ assert_equal 0b010101010, scanner.tokenize('0b01_01_01_010')
+ assert_equal '0b0,1_0,1_,0,1_01,0', scanner.tokenize('0b0,1_0,1_,0,1_01,0')
+
+ assert_equal 01234567, scanner.tokenize('01234567')
+ assert_equal '0_,,,1_2,_34567', scanner.tokenize('0_,,,1_2,_34567')
+
+ assert_equal 0x123456789abcdef, scanner.tokenize('0x123456789abcdef')
+ assert_equal 0x123456789abcdef, scanner.tokenize('0x12_34_56_789abcdef')
+ assert_equal '0x12_,34,_56,_789abcdef', scanner.tokenize('0x12_,34,_56,_789abcdef')
+ assert_equal '0x_12_,34,_56,_789abcdef', scanner.tokenize('0x_12_,34,_56,_789abcdef')
+ assert_equal '0x12_,34,_56,_789abcdef__', scanner.tokenize('0x12_,34,_56,_789abcdef__')
+ end
+
+ def test_scan_dot
+ assert_equal '.', ss.tokenize('.')
+ end
+
+ def test_scan_plus_dot
+ assert_equal '+.', ss.tokenize('+.')
+ end
+
+ class MatchCallCounter < String
+ attr_reader :match_call_count
+
+ def match?(pat)
+ @match_call_count ||= 0
+ @match_call_count += 1
+ super
+ end
+ end
+
+ def test_scan_ascii_matches_quickly
+ ascii = MatchCallCounter.new('abcdefghijklmnopqrstuvwxyz')
+ ss.tokenize(ascii)
+ assert_equal 1, ascii.match_call_count
+ end
+
+ def test_scan_unicode_matches_quickly
+ unicode = MatchCallCounter.new('鳥かご関連用品')
+ ss.tokenize(unicode)
+ assert_equal 1, unicode.match_call_count
+ end
end
end
diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb
index 20ab79c05a..0dc34b3083 100644
--- a/test/psych/test_string.rb
+++ b/test/psych/test_string.rb
@@ -17,6 +17,19 @@ module Psych
end
end
+ # 'y' and 'n' are kind of ambiguous. Syck treated y and n literals in
+ # YAML documents as strings. But this is not what the YAML 1.1 spec says.
+ # YAML 1.1 says they should be treated as booleans. When we're dumping
+ # documents, we know it's a string, so adding quotes will eliminate the
+ # "ambiguity" in the emitted document
+ def test_y_is_quoted
+ assert_match(/"y"/, Psych.dump("y"))
+ end
+
+ def test_n_is_quoted
+ assert_match(/"n"/, Psych.dump("n"))
+ end
+
def test_string_with_newline
assert_equal "1\n2", Psych.load("--- ! '1\n\n 2'\n")
end
diff --git a/test/psych/test_yaml.rb b/test/psych/test_yaml.rb
index e12b9769fe..32dd43b98e 100644
--- a/test/psych/test_yaml.rb
+++ b/test/psych/test_yaml.rb
@@ -34,7 +34,7 @@ class Psych_Unit_Tests < Psych::TestCase
# [ruby-core:34969]
def test_regexp_with_n
- assert_cycle(Regexp.new('',0,'n'))
+ assert_cycle(Regexp.new('',Regexp::NOENCODING))
end
#
# Tests modified from 00basic.t in Psych.pm
diff --git a/test/racc/assets/mof.y b/test/racc/assets/mof.y
index da3172988f..2e83c79b6f 100644
--- a/test/racc/assets/mof.y
+++ b/test/racc/assets/mof.y
@@ -563,9 +563,9 @@ end # class Parser
require 'strscan'
require 'rubygems'
require 'cim'
-require File.join(File.dirname(__FILE__), 'result')
-require File.join(File.dirname(__FILE__), 'scanner')
-require File.join(File.dirname(__FILE__), 'helper')
+require File.join(__dir__, 'result')
+require File.join(__dir__, 'scanner')
+require File.join(__dir__, 'case')
---- inner ----
diff --git a/test/racc/helper.rb b/test/racc/case.rb
index 146beb5a73..ebc30b8288 100644
--- a/test/racc/helper.rb
+++ b/test/racc/case.rb
@@ -3,11 +3,6 @@ $VERBOSE = true
begin
require 'test/unit'
-begin
- require_relative './lib/core_assertions'
- Test::Unit::TestCase.include Test::Unit::CoreAssertions
-rescue LoadError
-end
require 'racc/static'
require 'fileutils'
require 'tempfile'
@@ -15,13 +10,15 @@ require 'timeout'
module Racc
class TestCase < Test::Unit::TestCase
- PROJECT_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ PROJECT_DIR = File.expand_path(File.join(__dir__, '..'))
test_dir = File.join(PROJECT_DIR, 'test')
test_dir = File.join(PROJECT_DIR, 'racc') unless File.exist?(test_dir)
TEST_DIR = test_dir
racc = File.join(PROJECT_DIR, 'bin', 'racc')
racc = File.join(PROJECT_DIR, '..', 'libexec', 'racc') unless File.exist?(racc)
+ racc = 'racc' unless File.exist?(racc)
+
RACC = racc
ASSET_DIR = File.join(TEST_DIR, 'assets') # test grammars
REGRESS_DIR = File.join(TEST_DIR, 'regress') # known-good generated outputs
@@ -95,8 +92,7 @@ module Racc
actual = File.read("#{@TAB_DIR}/#{file}")
result = (strip_version(expected) == strip_version(actual))
- assert(result, "Output of test/assets/#{file}.y differed from " \
- "expectation. Try compiling it and diff with test/regress/#{file}.")
+ assert(result, proc {`diff -u #{REGRESS_DIR}/#{file} #{@TAB_DIR}/#{file}`})
end
def racc(*arg, **opt)
diff --git a/test/racc/regress/mof b/test/racc/regress/mof
index 836604744b..d702292e51 100644
--- a/test/racc/regress/mof
+++ b/test/racc/regress/mof
@@ -12,9 +12,9 @@ require 'racc/parser.rb'
require 'strscan'
require 'rubygems'
require 'cim'
-require File.join(File.dirname(__FILE__), 'result')
-require File.join(File.dirname(__FILE__), 'scanner')
-require File.join(File.dirname(__FILE__), 'helper')
+require File.join(__dir__, 'result')
+require File.join(__dir__, 'scanner')
+require File.join(__dir__, 'case')
module MOF
class Parser < Racc::Parser
diff --git a/test/racc/test_chk_y.rb b/test/racc/test_chk_y.rb
index bb8b6b4fe3..883737c45f 100644
--- a/test/racc/test_chk_y.rb
+++ b/test/racc/test_chk_y.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestChkY < TestCase
diff --git a/test/racc/test_grammar_file_parser.rb b/test/racc/test_grammar_file_parser.rb
index b187bdcaec..8f6e090cb2 100644
--- a/test/racc/test_grammar_file_parser.rb
+++ b/test/racc/test_grammar_file_parser.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestGrammarFileParser < TestCase
diff --git a/test/racc/test_racc_command.rb b/test/racc/test_racc_command.rb
index 0d2c5829e4..5bfebf150b 100644
--- a/test/racc/test_racc_command.rb
+++ b/test/racc/test_racc_command.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestRaccCommand < TestCase
diff --git a/test/racc/test_scan_y.rb b/test/racc/test_scan_y.rb
index 4c60119119..fcd7e53c99 100644
--- a/test/racc/test_scan_y.rb
+++ b/test/racc/test_scan_y.rb
@@ -1,4 +1,4 @@
-require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
+require File.expand_path(File.join(__dir__, 'case'))
module Racc
class TestScanY < TestCase
diff --git a/test/rdoc/helper.rb b/test/rdoc/helper.rb
index 2ba26c296b..7985433060 100644
--- a/test/rdoc/helper.rb
+++ b/test/rdoc/helper.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require_relative './support/test_case'
-require_relative './support/formatter_test_case'
-require_relative './support/text_formatter_test_case'
+require_relative 'support/test_case'
+require_relative 'support/formatter_test_case'
+require_relative 'support/text_formatter_test_case'
diff --git a/test/rdoc/support/test_case.rb b/test/rdoc/support/test_case.rb
index 6d397625e8..d98dbe0d7b 100644
--- a/test/rdoc/support/test_case.rb
+++ b/test/rdoc/support/test_case.rb
@@ -1,16 +1,3 @@
-##
-# RDoc::TestCase is an abstract TestCase to provide common setup and teardown
-# across all RDoc tests. The test case uses minitest, so all the assertions
-# of minitest may be used.
-#
-# The testcase provides the following:
-#
-# * A reset code-object tree
-# * A reset markup preprocessor (RDoc::Markup::PreProcess)
-# * The <code>@RM</code> alias of RDoc::Markup (for less typing)
-# * <code>@pwd</code> containing the current working directory
-# * FileUtils, pp, Tempfile, Dir.tmpdir and StringIO
-
require 'bundler/errors'
begin
gem 'test-unit'
@@ -26,12 +13,12 @@ require 'tempfile'
require 'tmpdir'
require 'stringio'
-require 'rdoc'
+require_relative '../../../lib/rdoc'
##
# RDoc::TestCase is an abstract TestCase to provide common setup and teardown
-# across all RDoc tests. The test case uses minitest, so all the assertions
-# of minitest may be used.
+# across all RDoc tests. The test case uses test-unit, so all the assertions
+# of test-unit may be used.
#
# The testcase provides the following:
#
@@ -50,7 +37,8 @@ class RDoc::TestCase < Test::Unit::TestCase
super
@orig_home = ENV["HOME"]
- ENV["HOME"] = Dir.tmpdir
+ FileUtils.mkdir_p(@test_home = Dir.mktmpdir("test_rdoc_"))
+ ENV["HOME"] = @test_home
@top_level = nil
@@ -77,6 +65,7 @@ class RDoc::TestCase < Test::Unit::TestCase
def teardown
ENV["HOME"] = @orig_home if defined?(@orig_home)
+ defined?(@test_home) and FileUtils.rm_rf @test_home
super
end
diff --git a/test/rdoc/test_rdoc_alias.rb b/test/rdoc/test_rdoc_alias.rb
index 89ae2d5a56..3c096a49b4 100644
--- a/test/rdoc/test_rdoc_alias.rb
+++ b/test/rdoc/test_rdoc_alias.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocAlias < XrefTestCase
@@ -11,4 +11,3 @@ class TestRDocAlias < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_any_method.rb b/test/rdoc/test_rdoc_any_method.rb
index 615789dfb3..6915b466f0 100644
--- a/test/rdoc/test_rdoc_any_method.rb
+++ b/test/rdoc/test_rdoc_any_method.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocAnyMethod < XrefTestCase
@@ -51,6 +51,20 @@ method(a, b) { |c, d| ... }
assert_equal 'foo', m.call_seq
end
+ def test_call_seq_alias_for
+ a = RDoc::AnyMethod.new nil, "each"
+ m = RDoc::AnyMethod.new nil, "each_line"
+
+ a.call_seq = <<-CALLSEQ
+each(foo)
+each_line(foo)
+ CALLSEQ
+
+ m.is_alias_for = a
+
+ assert_equal "each_line(foo)", m.call_seq
+ end
+
def test_full_name
assert_equal 'C1::m', @c1.method_list.first.full_name
end
@@ -72,6 +86,54 @@ method(a, b) { |c, d| ... }
assert_nil m1.is_alias_for, 'missing alias'
end
+ def test_call_seq_handles_aliases
+ # see 0ead786
+ @store.path = Dir.tmpdir
+ top_level = @store.add_file 'file.rb'
+ cm = top_level.add_class RDoc::ClassModule, 'Klass'
+
+ method_with_call_seq = RDoc::AnyMethod.new(nil, "method_with_call_seq")
+ method_with_call_seq.call_seq = <<~SEQ
+ method_with_call_seq(a)
+ method_with_call_seq(a, b)
+ alias_to_method(a)
+ alias_to_method(a, b)
+ SEQ
+ cm.add_method(method_with_call_seq)
+
+ alias_to_method = method_with_call_seq.add_alias(
+ RDoc::Alias.new(nil, "method_with_call_seq", "alias_to_method", "comment"),
+ cm
+ )
+
+ assert_equal("method_with_call_seq(a)\nmethod_with_call_seq(a, b)",
+ method_with_call_seq.call_seq)
+ assert_equal("alias_to_method(a)\nalias_to_method(a, b)",
+ alias_to_method.call_seq)
+ end
+
+ def test_call_seq_returns_nil_if_alias_is_missing_from_call_seq
+ @store.path = Dir.tmpdir
+ top_level = @store.add_file 'file.rb'
+ cm = top_level.add_class RDoc::ClassModule, 'Klass'
+
+ method_with_call_seq = RDoc::AnyMethod.new(nil, "method_with_call_seq")
+ method_with_call_seq.call_seq = <<~SEQ
+ method_with_call_seq(a)
+ method_with_call_seq(a, b)
+ SEQ
+ cm.add_method(method_with_call_seq)
+
+ alias_to_method = method_with_call_seq.add_alias(
+ RDoc::Alias.new(nil, "method_with_call_seq", "alias_to_method", "comment"),
+ cm
+ )
+
+ assert_equal("method_with_call_seq(a)\nmethod_with_call_seq(a, b)",
+ method_with_call_seq.call_seq)
+ assert_nil(alias_to_method.call_seq)
+ end
+
def test_markup_code
tokens = [
{ :line_no => 0, :char_no => 0, :kind => :on_const, :text => 'CONSTANT' },
diff --git a/test/rdoc/test_rdoc_class_module.rb b/test/rdoc/test_rdoc_class_module.rb
index 4dcc5d15ab..27d37cb7dd 100644
--- a/test/rdoc/test_rdoc_class_module.rb
+++ b/test/rdoc/test_rdoc_class_module.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocClassModule < XrefTestCase
@@ -63,7 +63,7 @@ class TestRDocClassModule < XrefTestCase
end
def test_ancestors
- assert_equal [@parent, "Object"], @child.ancestors
+ assert_equal [@parent, @object, "BasicObject"], @child.ancestors
end
def test_comment_equals
@@ -89,7 +89,7 @@ class TestRDocClassModule < XrefTestCase
assert_equal 'comment', cm.comment.text
end
- def test_docuent_self_or_methods
+ def test_document_self_or_methods
assert @c1.document_self_or_methods
@c1.document_self = false
@@ -129,7 +129,7 @@ class TestRDocClassModule < XrefTestCase
end
def test_each_ancestor
- assert_equal [@parent], @child.each_ancestor.to_a
+ assert_equal [@parent, @object], @child.each_ancestor.to_a
end
def test_each_ancestor_cycle
@@ -238,7 +238,7 @@ class TestRDocClassModule < XrefTestCase
assert_equal tl, loaded.method_list.first.file
end
- def test_marshal_dump_visibilty
+ def test_marshal_dump_visibility
@store.path = Dir.tmpdir
tl = @store.add_file 'file.rb'
@@ -1501,4 +1501,3 @@ class TestRDocClassModule < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_code_object.rb b/test/rdoc/test_rdoc_code_object.rb
index fad182722a..24e228cce1 100644
--- a/test/rdoc/test_rdoc_code_object.rb
+++ b/test/rdoc/test_rdoc_code_object.rb
@@ -1,7 +1,7 @@
# coding: US-ASCII
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocCodeObject < XrefTestCase
diff --git a/test/rdoc/test_rdoc_constant.rb b/test/rdoc/test_rdoc_constant.rb
index 79dcdad57e..32ffe3f84d 100644
--- a/test/rdoc/test_rdoc_constant.rb
+++ b/test/rdoc/test_rdoc_constant.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocConstant < XrefTestCase
diff --git a/test/rdoc/test_rdoc_context.rb b/test/rdoc/test_rdoc_context.rb
index ecdb3cbd67..85665599fb 100644
--- a/test/rdoc/test_rdoc_context.rb
+++ b/test/rdoc/test_rdoc_context.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocContext < XrefTestCase
@@ -125,7 +125,7 @@ class TestRDocContext < XrefTestCase
basic = @c1.find_module_named 'BasicObject'
- assert_equal 'Object', basic.superclass
+ assert_equal @object, basic.superclass
end
def test_add_class_object
diff --git a/test/rdoc/test_rdoc_cross_reference.rb b/test/rdoc/test_rdoc_cross_reference.rb
index 183de0930d..cbda77a798 100644
--- a/test/rdoc/test_rdoc_cross_reference.rb
+++ b/test/rdoc/test_rdoc_cross_reference.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocCrossReference < XrefTestCase
+ EXAMPLE_METHODS = %w'== === != =~ !~ < > <= >= <=> [] []= << >>
+ -@ +@ ! - + * / % ** !@ ` | & ^ ~ __id__
+ '
def setup
super
@@ -18,9 +21,9 @@ class TestRDocCrossReference < XrefTestCase
end
def test_METHOD_REGEXP_STR
- re = /#{RDoc::CrossReference::METHOD_REGEXP_STR}/
+ re = /\A(?:#{RDoc::CrossReference::METHOD_REGEXP_STR})\z/
- %w'=== [] []= << >>'.each do |x|
+ EXAMPLE_METHODS.each do |x|
re =~ x
assert_equal x, $&
end
@@ -88,6 +91,15 @@ class TestRDocCrossReference < XrefTestCase
assert_ref @c4_c4, 'C4'
end
+ def test_resolve_class_and_method_of_the_same_name
+ assert_ref @c10_class, 'C10'
+ assert_ref @c10_method, '#C10'
+ assert_ref @c11_class, 'C11'
+ assert_ref @c11_method, '#C11'
+ assert_ref @c10_c11_class, 'C10::C11'
+ assert_ref @c10_c11_method, 'C10#C11'
+ end
+
def test_resolve_class
assert_ref @c1, 'C1'
refute_ref 'H1'
@@ -154,34 +166,35 @@ class TestRDocCrossReference < XrefTestCase
assert_ref @c9_a_c_bar, 'C9::B.bar'
end
- def test_resolve_method_equals3
- m = RDoc::AnyMethod.new '', '==='
- @c1.add_method m
-
- assert_ref m, '==='
- end
-
def test_resolve_page
page = @store.add_file 'README.txt', parser: RDoc::Parser::Simple
assert_ref page, 'README'
end
- def test_resolve_percent
- i_percent = RDoc::AnyMethod.new nil, '%'
- i_percent.singleton = false
- @c1.add_method i_percent
+ def assert_resolve_method(x)
+ @c1.methods_hash.clear
- c_percent = RDoc::AnyMethod.new nil, '%'
- c_percent.singleton = true
- @c1.add_method c_percent
+ i_op = RDoc::AnyMethod.new nil, x
+ i_op.singleton = false
+ @c1.add_method i_op
- assert_ref i_percent, '%'
- assert_ref i_percent, '#%'
- assert_ref c_percent, '::%'
+ c_op = RDoc::AnyMethod.new nil, x
+ c_op.singleton = true
+ @c1.add_method c_op
- assert_ref i_percent, 'C1#%'
- assert_ref c_percent, 'C1::%'
+ assert_ref i_op, x
+ assert_ref i_op, "##{x}"
+ assert_ref c_op, "::#{x}"
+
+ assert_ref i_op, "C1##{x}"
+ assert_ref c_op, "C1::#{x}"
+ end
+
+ EXAMPLE_METHODS.each do |x|
+ define_method("test_resolve_method:#{x}") do
+ assert_resolve_method(x)
+ end
end
def test_resolve_no_ref
@@ -204,4 +217,3 @@ class TestRDocCrossReference < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_extend.rb b/test/rdoc/test_rdoc_extend.rb
index f4c8425864..cc5038cc51 100644
--- a/test/rdoc/test_rdoc_extend.rb
+++ b/test/rdoc/test_rdoc_extend.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocExtend < XrefTestCase
@@ -43,7 +43,7 @@ class TestRDocExtend < XrefTestCase
m1_m2_k0.add_extend e0_m3
assert_equal [e0_m4, e0_m5, e0_m6, e0_m1, e0_m2, e0_m3], m1_m2_k0.extends
- assert_equal ['Object'], m1_m2_k0.ancestors
+ assert_equal [@object, 'BasicObject'], m1_m2_k0.ancestors
m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1'
@@ -60,7 +60,7 @@ class TestRDocExtend < XrefTestCase
m1_k1.add_extend e1_k0_m4
assert_equal [e1_m1, e1_m2, e1_m3, e1_m4, e1_k0_m4], m1_k1.extends
- assert_equal ['Object'], m1_k1.ancestors
+ assert_equal [@object, 'BasicObject'], m1_k1.ancestors
m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2'
@@ -75,7 +75,7 @@ class TestRDocExtend < XrefTestCase
m1_k2.add_extend e2_k0_m4
assert_equal [e2_m1, e2_m3, e2_m2, e2_k0_m4], m1_k2.extends
- assert_equal ['Object'], m1_k2.ancestors
+ assert_equal [@object, 'BasicObject'], m1_k2.ancestors
m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3'
@@ -88,8 +88,7 @@ class TestRDocExtend < XrefTestCase
m1_k3.add_extend e3_m4
assert_equal [e3_m1, e3_m2, e3_m4], m1_k3.extends
- assert_equal ['Object'], m1_k3.ancestors
+ assert_equal [@object, 'BasicObject'], m1_k3.ancestors
end
end
-
diff --git a/test/rdoc/test_rdoc_generator_darkfish.rb b/test/rdoc/test_rdoc_generator_darkfish.rb
index f5858bce6e..7e9edae469 100644
--- a/test/rdoc/test_rdoc_generator_darkfish.rb
+++ b/test/rdoc/test_rdoc_generator_darkfish.rb
@@ -72,11 +72,30 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
def test_generate
top_level = @store.add_file 'file.rb'
top_level.add_class @klass.class, @klass.name
+ @klass.add_class RDoc::NormalClass, 'Inner'
+ @klass.add_comment <<~RDOC, top_level
+ = Heading 1
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+ == Heading 1.1
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ === Heading 1.1.1
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ ==== Heading 1.1.1.1
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
+ == Heading 1.2
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
+ == Heading 1.3
+ non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+ === Heading 1.3.1
+ etc etc...
+ RDOC
@g.generate
assert_file 'index.html'
assert_file 'Object.html'
+ assert_file 'Klass.html'
+ assert_file 'Klass/Inner.html'
assert_file 'table_of_contents.html'
assert_file 'js/search_index.js'
@@ -92,6 +111,35 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
assert_match %r%<meta charset="#{encoding}">%, File.read('Object.html')
refute_match(/Ignored/, File.read('index.html'))
+ summary = File.read('index.html')[%r[<summary.*Klass\.html.*</summary>.*</details>]m]
+ assert_match(%r[Klass/Inner\.html".*>Inner<], summary)
+ omit 'The following line crashes with "invalid byte sequence in US-ASCII" on ci.rvm.jp and some RubyCIs'
+ klassnav = File.read('Klass.html')[%r[<div class="nav-section">.*<div id="class-metadata">]m]
+ assert_match(
+ %r[<li>\s*<details open>\s*<summary>\s*<a href=\S+>Heading 1</a>\s*</summary>\s*<ul]m,
+ klassnav
+ )
+ assert_match(
+ %r[<li>\s*<a href=\S+>Heading 1.1.1.1</a>\s*</ul>\s*</details>\s*</li>]m,
+ klassnav
+ )
+ end
+
+ def test_generate_page
+ @store.add_file 'outer.rdoc', parser: RDoc::Parser::Simple
+ @store.add_file 'outer/inner.rdoc', parser: RDoc::Parser::Simple
+ @g.generate
+ assert_file 'outer_rdoc.html'
+ assert_file 'outer/inner_rdoc.html'
+ index = File.read('index.html')
+ re = %r[<summary><a href="\./outer_rdoc\.html">outer</a></summary>.*?</details>]m
+ assert_match(re, index)
+ summary = index[re]
+ assert_match %r[<a href="\./outer/inner_rdoc.html">inner</a>], summary
+ re = %r[<details open><summary><a href="\./outer_rdoc\.html">outer</a></summary>.*?</details>]m
+ assert_match(re, File.read('outer_rdoc.html'))
+ re = %r[<details open><summary><a href="\.\./outer_rdoc\.html">outer</a></summary>.*?</details>]m
+ assert_match(re, File.read('outer/inner_rdoc.html'))
end
def test_generate_dry_run
@@ -142,15 +190,6 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
@g.install_rdoc_static_file src, dst, options
assert_file dst
-
- begin
- assert_hard_link dst
- rescue MiniTest::Assertion
- return # hard links are not supported, no further tests needed
- end
-
- @g.install_rdoc_static_file src, dst, options
-
assert_hard_link dst
end
@@ -220,6 +259,60 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
assert_includes method_name, '{ |%&lt;&lt;script&gt;alert(&quot;atui&quot;)&lt;/script&gt;&gt;, yield_arg| ... }'
end
+ def test_generated_filename_with_html_tag
+ filename = '"><em>should be escaped'
+ begin # in @tmpdir
+ File.write(filename, '')
+ rescue SystemCallError
+ # ", <, > chars are prohibited as filename
+ return
+ else
+ File.unlink(filename)
+ end
+ @store.add_file filename
+ doc = @store.all_files.last
+ doc.parser = RDoc::Parser::Simple
+
+ @g.generate
+
+ Dir.glob("*.html", base: @tmpdir) do |html|
+ File.read(File.join(@tmpdir, html)).scan(/.*should be escaped.*/) do |line|
+ assert_not_include line, "<em>", html
+ end
+ end
+ end
+
+ def test_template_stylesheets
+ css = Tempfile.create(%W'hoge .css', Dir.mktmpdir('tmp', '.'))
+ File.write(css, '')
+ css.close
+ base = File.basename(css)
+ refute_file(base)
+
+ @options.template_stylesheets << css
+
+ @g.generate
+
+ assert_file base
+ assert_include File.read('index.html'), %Q[href="./#{base}"]
+ end
+
+ def test_title
+ title = "RDoc Test".freeze
+ @options.title = title
+ @g.generate
+
+ assert_main_title(File.read('index.html'), title)
+ end
+
+ def test_title_escape
+ title = %[<script>alert("RDoc")</script>].freeze
+ @options.title = title
+ @g.generate
+
+ assert_main_title(File.read('index.html'), title)
+ end
+
##
# Asserts that +filename+ has a link count greater than 1 if hard links to
# @tmpdir are supported.
@@ -243,4 +336,9 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
"#{filename} is not hard-linked"
end
+ def assert_main_title(content, title)
+ title = CGI.escapeHTML(title)
+ assert_equal(title, content[%r[<title>(.*?)<\/title>]im, 1])
+ assert_include(content[%r[<main\s[^<>]*+>\s*(.*?)</main>]im, 1], title)
+ end
end
diff --git a/test/rdoc/test_rdoc_generator_json_index.rb b/test/rdoc/test_rdoc_generator_json_index.rb
index 66d15d1848..62d1ccec95 100644
--- a/test/rdoc/test_rdoc_generator_json_index.rb
+++ b/test/rdoc/test_rdoc_generator_json_index.rb
@@ -104,8 +104,20 @@ class TestRDocGeneratorJsonIndex < RDoc::TestCase
orig_file = Pathname(File.join srcdir, 'generator/template/json_index/js/navigation.js')
generated_file = Pathname(File.join @tmpdir, 'js/navigation.js')
- # This is dirty hack on JRuby for MiniTest 4
- assert orig_file.mtime.inspect == generated_file.mtime.inspect,
+ # The following assertion for the generated file's modified time randomly
+ # fails in a ppc64le environment.
+ # https://github.com/ruby/rdoc/issues/1048
+ if orig_file.mtime.inspect != generated_file.mtime.inspect &&
+ RUBY_PLATFORM =~ /powerpc64le/
+ pend <<~EOC
+ Unstable test in ppc64le.
+ <#{orig_file.mtime.inspect}> expected but was
+ <#{generated_file.mtime.inspect}>.
+ EOC
+ end
+
+ # This is dirty hack on JRuby
+ assert_equal orig_file.mtime.inspect, generated_file.mtime.inspect,
'.js files should be the same timestamp of original'
json = File.read 'js/search_index.js'
diff --git a/test/rdoc/test_rdoc_include.rb b/test/rdoc/test_rdoc_include.rb
index 67d3dfd88e..380464f6cc 100644
--- a/test/rdoc/test_rdoc_include.rb
+++ b/test/rdoc/test_rdoc_include.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocInclude < XrefTestCase
@@ -46,7 +46,7 @@ class TestRDocInclude < XrefTestCase
assert_equal [i0_m4, i0_m5, i0_m6, i0_m1, i0_m2, i0_m3], m1_m2_k0.includes
assert_equal [m1_m2_m3, m1_m2, m1, m1_m2_k0_m4_m6, m1_m2_k0_m5,
- m1_m2_k0_m4, 'Object'], m1_m2_k0.ancestors
+ m1_m2_k0_m4, @object, 'BasicObject'], m1_m2_k0.ancestors
m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1'
@@ -63,8 +63,8 @@ class TestRDocInclude < XrefTestCase
m1_k1.add_include i1_k0_m4
assert_equal [i1_m1, i1_m2, i1_m3, i1_m4, i1_k0_m4], m1_k1.includes
- assert_equal [m1_m2_k0_m4, m1_m2_m3_m4, m1_m2_m3, m1_m2, m1, 'Object'],
- m1_k1.ancestors
+ assert_equal [m1_m2_k0_m4, m1_m2_m3_m4, m1_m2_m3, m1_m2, m1, @object,
+ 'BasicObject'], m1_k1.ancestors
m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2'
@@ -79,7 +79,8 @@ class TestRDocInclude < XrefTestCase
m1_k2.add_include i2_k0_m4
assert_equal [i2_m1, i2_m3, i2_m2, i2_k0_m4], m1_k2.includes
- assert_equal [m1_m2_k0_m4, m1_m2, m1_m3, m1, 'Object'], m1_k2.ancestors
+ assert_equal [m1_m2_k0_m4, m1_m2, m1_m3, m1, @object, 'BasicObject'],
+ m1_k2.ancestors
m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3'
@@ -92,7 +93,7 @@ class TestRDocInclude < XrefTestCase
m1_k3.add_include i3_m4
assert_equal [i3_m1, i3_m2, i3_m4], m1_k3.includes
- assert_equal [m1_m2_m4, m1_m2, m1, 'Object'], m1_k3.ancestors
+ assert_equal [m1_m2_m4, m1_m2, m1, @object, 'BasicObject'], m1_k3.ancestors
end
def test_store_equals
@@ -106,4 +107,3 @@ class TestRDocInclude < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markdown.rb b/test/rdoc/test_rdoc_markdown.rb
index ad53e9473c..dd6f312fa9 100644
--- a/test/rdoc/test_rdoc_markdown.rb
+++ b/test/rdoc/test_rdoc_markdown.rb
@@ -2,8 +2,8 @@
# frozen_string_literal: true
require_relative 'helper'
-require 'rdoc/markup/block_quote'
-require 'rdoc/markdown'
+require_relative '../../lib/rdoc/markup/block_quote'
+require_relative '../../lib/rdoc/markdown'
class TestRDocMarkdown < RDoc::TestCase
@@ -761,7 +761,6 @@ with inline notes^[like this]
and an extra note.[^2]
[^1]: With a footnote
-
[^2]: Which should be numbered correctly
MD
@@ -1063,9 +1062,29 @@ and an extra note.[^2]
assert_equal expected, doc
end
+ def test_gfm_table_2
+ doc = parse <<~'MD'
+ | Cmd | Returns | Meaning
+ ----- | :-----: | -------
+ |"b" | boolean | True if file1 is a block device
+ "c" | boolean | True if file1 is a character device
+ |"\|" | boolean | escaped bar \| test
+ MD
+
+ head = %w[Cmd Returns Meaning]
+ align = [nil, :center, nil]
+ body = [
+ ['"b"', 'boolean', 'True if file1 is a block device'],
+ ['"c"', 'boolean', 'True if file1 is a character device'],
+ ['"|"', 'boolean', 'escaped bar | test'],
+ ]
+ expected = doc(@RM::Table.new(head, align, body))
+
+ assert_equal expected, doc
+ end
+
def parse text
@parser.parse text
end
end
-
diff --git a/test/rdoc/test_rdoc_markdown_test.rb b/test/rdoc/test_rdoc_markdown_test.rb
index 0ecd000136..d4f894c924 100644
--- a/test/rdoc/test_rdoc_markdown_test.rb
+++ b/test/rdoc/test_rdoc_markdown_test.rb
@@ -2,8 +2,8 @@
require_relative 'helper'
require 'pp'
-require 'rdoc'
-require 'rdoc/markdown'
+require_relative '../../lib/rdoc'
+require_relative '../../lib/rdoc/markdown'
class TestRDocMarkdownTest < RDoc::TestCase
diff --git a/test/rdoc/test_rdoc_markup_attribute_manager.rb b/test/rdoc/test_rdoc_markup_attribute_manager.rb
index 944364ba89..e8ff602f96 100644
--- a/test/rdoc/test_rdoc_markup_attribute_manager.rb
+++ b/test/rdoc/test_rdoc_markup_attribute_manager.rb
@@ -145,6 +145,8 @@ class TestRDocMarkupAttributeManager < RDoc::TestCase
assert_equal(["cat and ", @em_on, "5", @em_off, " dogs"],
@am.flow("cat and _5_ dogs"))
+
+ assert_equal([@tt_on, "__id__", @tt_off], @am.flow("+__id__+"))
end
def test_bold
diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb
index 342cf71082..d11c2a4ed7 100644
--- a/test/rdoc/test_rdoc_markup_to_html.rb
+++ b/test/rdoc/test_rdoc_markup_to_html.rb
@@ -665,6 +665,26 @@ EXPECTED
assert_equal "\n<p>C</p>\n", result
end
+ def test_convert_RDOCLINK_escape_image
+ assert_escaped '<script>', 'rdoc-image:"><script>alert(`rdoc-image`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_label_id
+ assert_escaped '<script>', 'rdoc-label::path::"><script>alert(`rdoc-label_id`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_label_path
+ assert_escaped '<script>', 'rdoc-label::"><script>alert(`rdoc-label_path`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_ref
+ assert_escaped '<script>', 'rdoc-ref:"><script>alert(`rdoc-ref`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_xxx
+ assert_escaped '<script>', 'rdoc-xxx:"><script>alert(`rdoc-xxx`)</script>"'
+ end
+
def test_convert_TIDYLINK_footnote
result = @to.convert 'text{*1}[rdoc-label:foottext-1:footmark-1]'
@@ -690,6 +710,11 @@ EXPECTED
"\n<p><a href=\"http://example.com\"><img src=\"path/to/image.jpg\"></a></p>\n"
assert_equal expected, result
+
+ result =
+ @to.convert '{rdoc-image:<script>alert`link text`</script>}[http://example.com]'
+
+ assert_not_include result, "<script>"
end
def test_convert_TIDYLINK_rdoc_label
@@ -704,15 +729,33 @@ EXPECTED
assert_equal "\n<p><a href=\"irc://irc.freenode.net/#ruby-lang\">ruby-lang</a></p>\n", result
end
+ def test_convert_TIDYLINK_escape_text
+ assert_escaped '<script>', '{<script>alert`link text`</script>}[a]'
+ assert_escaped '<script>', 'x:/<script>alert(1);</script>[[]'
+ end
+
+ def test_convert_TIDYLINK_escape_javascript
+ assert_not_include '{click}[javascript:alert`javascript_scheme`]', '<a href="javascript:'
+ end
+
+ def test_convert_TIDYLINK_escape_onmouseover
+ assert_escaped '"/onmouseover="', '{onmouseover}[http://"/onmouseover="alert`on_mouse_link`"]'
+ end
+
+ def test_convert_TIDYLINK_escape_onerror
+ assert_escaped '"onerror="', '{link_image}[http://"onerror="alert`link_image`".png]'
+ 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><code>https:</code>-foobar</p>\n", @to.convert('<tt>https:</tt>-foobar')
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_'})
+ assert_equal "\n<p>\u{2018}<code>i386-mswin32_</code><em>MSRTVERSION</em>\u{2019}</p>\n", @to.convert(%q{`+i386-mswin32_+_MSRTVERSION_'})
end
def test_gen_url
@@ -793,6 +836,11 @@ EXPECTED
assert_equal '<a href="irc://irc.freenode.net/#ruby-lang">irc.freenode.net/#ruby-lang</a>', link
end
+ def test_handle_regexp_HYPERLINK_escape
+ code = 'irc://irc.freenode.net/"><script>alert(`irc`)</script><a"'
+ assert_escaped '<script>', code
+ end
+
def test_list_verbatim_2
str = "* one\n verb1\n verb2\n* two\n"
@@ -811,6 +859,26 @@ EXPECTED
assert_equal expected, @m.convert(str, @to)
end
+ def test_block_quote_in_verbatim
+ str = "BlockQuote\n >>>\n"
+
+ expected = <<-EXPECTED
+<p>BlockQuote</p>
+<pre>&gt;&gt;&gt;</pre>
+ EXPECTED
+
+ assert_equal expected, @m.convert(str, @to).gsub(/^\n/, "")
+
+ str = "BlockQuote\n >>> word\n"
+
+ expected = <<-EXPECTED
+<p>BlockQuote</p>
+<pre>&gt;&gt;&gt; word</pre>
+ EXPECTED
+
+ assert_equal expected, @m.convert(str, @to).gsub(/^\n/, "")
+ end
+
def test_parseable_eh
valid_syntax = [
'def x() end',
@@ -855,5 +923,38 @@ EXPECTED
@to.end_accepting
end
+ def test_accept_table
+ header = %w[Col1 Col2 Col3]
+ body = [
+ %w[cell1_1 cell1_2 cell1_3],
+ %w[cell2_1 cell2_2 cell2_3],
+ ['<script>alert("foo");</script>',],
+ %w[+code+ _em_ **strong**],
+ ]
+ aligns = [:left, :right, nil]
+ @to.start_accepting
+ @to.accept_table(header, body, aligns)
+ res = @to.end_accepting
+ assert_include(res[%r<<th[^<>]*>Col1</th>>], 'align="left"')
+ assert_include(res[%r<<th[^<>]*>Col2</th>>], 'align="right"')
+ assert_not_include(res[%r<<th[^<>]*>Col3</th>>], 'align=')
+ assert_include(res[%r<<td[^<>]*>cell1_1</td>>], 'align="left"')
+ assert_include(res[%r<<td[^<>]*>cell1_2</td>>], 'align="right"')
+ assert_not_include(res[%r<<td[^<>]*>cell1_3</td>>], 'align=')
+ assert_include(res[%r<<td[^<>]*>cell2_1</td>>], 'align="left"')
+ assert_include(res[%r<<td[^<>]*>cell2_2</td>>], 'align="right"')
+ assert_not_include(res[%r<<td[^<>]*>cell2_3</td>>], 'align=')
+ assert_not_include(res, '<script>')
+ assert_include(res[%r<<td[^<>]*>.*script.*</td>>], '&lt;script&gt;')
+ assert_include(res[%r<<td[^<>]*>.*code.*</td>>], '<code>code</code>')
+ assert_include(res[%r<<td[^<>]*>.*em.*</td>>], '<em>em</em>')
+ assert_include(res[%r<<td[^<>]*>.*strong.*</td>>], '<strong>strong</strong>')
+ end
+
+ def assert_escaped(unexpected, code)
+ result = @to.convert(code)
+ assert_not_include result, unexpected
+ assert_include result, CGI.escapeHTML(unexpected)
+ end
end
diff --git a/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/test/rdoc/test_rdoc_markup_to_html_crossref.rb